From e54d9691616b9a0326e2fdb3156bb4eeb8abfcd7 Mon Sep 17 00:00:00 2001 From: Alan Mishchenko Date: Sun, 30 Sep 2007 08:01:00 -0700 Subject: Version abc70930 --- Makefile | 79 - __MACOSX/abc70930/._.DS_Store | Bin 0 -> 82 bytes .../._Instructions_for_Mac_OS_X_X_code_users.rtf | Bin 0 -> 82 bytes __MACOSX/abc70930/src/._.DS_Store | Bin 0 -> 82 bytes __MACOSX/abc70930/src/aig/hop/._cudd2.c | Bin 0 -> 174 bytes __MACOSX/abc70930/src/base/._.DS_Store | Bin 0 -> 82 bytes __MACOSX/abc70930/src/base/main/._main.h | Bin 0 -> 174 bytes __MACOSX/abc70930/src/base/main/._mainUtils.c | Bin 0 -> 174 bytes __MACOSX/abc70930/src/misc/espresso/._unate.c | Bin 0 -> 174 bytes abc.dsp | 2983 - abc.dsw | 29 - abc.rc | 176 - abc70930/.DS_Store | Bin 0 -> 6148 bytes .../Instructions_for_Mac_OS_X_X_code_users.rtf | 7 + abc70930/Makefile | 76 + abc70930/abc.dsp | 2847 + abc70930/abc.dsw | 29 + abc70930/abc.plg | 1105 + abc70930/abc.rc | 124 + abc70930/abclib.dsp | 2844 + abc70930/abclib.dsw | 29 + abc70930/abclib.plg | 2208 + abc70930/abctestlib.dsp | 102 + abc70930/abctestlib.dsw | 29 + abc70930/abctestlib.plg | 32 + abc70930/copyright.txt | 18 + abc70930/demo.c | 181 + abc70930/depends.sh | 13 + abc70930/examples/C2670.blif | 2395 + abc70930/examples/ac.v | 18772 +++ abc70930/examples/apex4.pla | 443 + abc70930/examples/frg2.blif | 1867 + abc70930/examples/i10.blif | 5679 + abc70930/examples/pj1.blif | 120216 ++++++++++++++++++ abc70930/examples/s38417.blif | 48956 +++++++ abc70930/examples/s38584.bench | 21008 +++ abc70930/examples/s444.blif | 353 + abc70930/examples/s5378.blif | 6138 + abc70930/examples/s6669.blif | 6413 + abc70930/readme | 26 + abc70930/regtest.script | 18 + abc70930/regtest_output.txt | 96 + abc70930/src/.DS_Store | Bin 0 -> 6148 bytes abc70930/src/abc.1 | 79 + abc70930/src/abc.xcodeproj/project.pbxproj | 3251 + abc70930/src/abc.xcodeproj/raiyan.pbxuser | 1622 + abc70930/src/abc.xcodeproj/raiyan.perspectivev3 | 1561 + abc70930/src/aig/aig/aig.h | 553 + abc70930/src/aig/aig/aigCheck.c | 163 + abc70930/src/aig/aig/aigDfs.c | 700 + abc70930/src/aig/aig/aigFanout.c | 189 + abc70930/src/aig/aig/aigMan.c | 325 + abc70930/src/aig/aig/aigMem.c | 598 + abc70930/src/aig/aig/aigMffc.c | 297 + abc70930/src/aig/aig/aigObj.c | 416 + abc70930/src/aig/aig/aigOper.c | 532 + abc70930/src/aig/aig/aigOrder.c | 171 + abc70930/src/aig/aig/aigPart.c | 990 + abc70930/src/aig/aig/aigRepr.c | 457 + abc70930/src/aig/aig/aigRet.c | 969 + abc70930/src/aig/aig/aigScl.c | 399 + abc70930/src/aig/aig/aigSeq.c | 502 + abc70930/src/aig/aig/aigShow.c | 356 + abc70930/src/aig/aig/aigTable.c | 268 + abc70930/src/aig/aig/aigTime.c | 299 + abc70930/src/aig/aig/aigTiming.c | 351 + abc70930/src/aig/aig/aigTruth.c | 98 + abc70930/src/aig/aig/aigTsim.c | 436 + abc70930/src/aig/aig/aigUtil.c | 851 + abc70930/src/aig/aig/aigWin.c | 184 + abc70930/src/aig/aig/aig_.c | 48 + abc70930/src/aig/aig/module.make | 21 + abc70930/src/aig/bar/bar.c | 177 + abc70930/src/aig/bar/bar.h | 74 + abc70930/src/aig/bar/module.make | 1 + abc70930/src/aig/bdc/bdc.h | 73 + abc70930/src/aig/bdc/bdcCore.c | 189 + abc70930/src/aig/bdc/bdcDec.c | 461 + abc70930/src/aig/bdc/bdcInt.h | 150 + abc70930/src/aig/bdc/bdcTable.c | 140 + abc70930/src/aig/bdc/bdc_.c | 49 + abc70930/src/aig/bdc/module.make | 4 + abc70930/src/aig/cnf/cnf.h | 162 + abc70930/src/aig/cnf/cnfCore.c | 185 + abc70930/src/aig/cnf/cnfCut.c | 371 + abc70930/src/aig/cnf/cnfData.c | 4784 + abc70930/src/aig/cnf/cnfMan.c | 202 + abc70930/src/aig/cnf/cnfMap.c | 356 + abc70930/src/aig/cnf/cnfPost.c | 233 + abc70930/src/aig/cnf/cnfUtil.c | 188 + abc70930/src/aig/cnf/cnfWrite.c | 443 + abc70930/src/aig/cnf/cnf_.c | 48 + abc70930/src/aig/cnf/module.make | 8 + abc70930/src/aig/csw/csw.h | 65 + abc70930/src/aig/csw/cswCore.c | 94 + abc70930/src/aig/csw/cswCut.c | 602 + abc70930/src/aig/csw/cswInt.h | 157 + abc70930/src/aig/csw/cswMan.c | 125 + abc70930/src/aig/csw/cswTable.c | 161 + abc70930/src/aig/csw/csw_.c | 48 + abc70930/src/aig/csw/module.make | 4 + abc70930/src/aig/dar/dar.h | 106 + abc70930/src/aig/dar/darBalance.c | 398 + abc70930/src/aig/dar/darCore.c | 244 + abc70930/src/aig/dar/darCut.c | 698 + abc70930/src/aig/dar/darData.c | 11287 ++ abc70930/src/aig/dar/darInt.h | 165 + abc70930/src/aig/dar/darLib.c | 980 + abc70930/src/aig/dar/darMan.c | 133 + abc70930/src/aig/dar/darPrec.c | 387 + abc70930/src/aig/dar/darRefact.c | 591 + abc70930/src/aig/dar/darResub.c | 48 + abc70930/src/aig/dar/darScript.c | 392 + abc70930/src/aig/dar/dar_.c | 48 + abc70930/src/aig/dar/module.make | 10 + abc70930/src/aig/deco/deco.h | 703 + abc70930/src/aig/deco/module.make | 1 + abc70930/src/aig/fra/fra.h | 300 + abc70930/src/aig/fra/fraBmc.c | 362 + abc70930/src/aig/fra/fraCec.c | 48 + abc70930/src/aig/fra/fraClass.c | 854 + abc70930/src/aig/fra/fraCnf.c | 286 + abc70930/src/aig/fra/fraCore.c | 428 + abc70930/src/aig/fra/fraImp.c | 721 + abc70930/src/aig/fra/fraInd.c | 479 + abc70930/src/aig/fra/fraLcr.c | 655 + abc70930/src/aig/fra/fraMan.c | 304 + abc70930/src/aig/fra/fraPart.c | 263 + abc70930/src/aig/fra/fraSat.c | 452 + abc70930/src/aig/fra/fraSec.c | 283 + abc70930/src/aig/fra/fraSim.c | 823 + abc70930/src/aig/fra/fra_.c | 48 + abc70930/src/aig/fra/module.make | 12 + abc70930/src/aig/hop/cudd2.c | 356 + abc70930/src/aig/hop/cudd2.h | 82 + abc70930/src/aig/hop/hop.h | 347 + abc70930/src/aig/hop/hopBalance.c | 391 + abc70930/src/aig/hop/hopCheck.c | 110 + abc70930/src/aig/hop/hopDfs.c | 399 + abc70930/src/aig/hop/hopMan.c | 164 + abc70930/src/aig/hop/hopMem.c | 115 + abc70930/src/aig/hop/hopObj.c | 271 + abc70930/src/aig/hop/hopOper.c | 373 + abc70930/src/aig/hop/hopTable.c | 262 + abc70930/src/aig/hop/hopUtil.c | 572 + abc70930/src/aig/hop/hop_.c | 48 + abc70930/src/aig/hop/module.make | 9 + abc70930/src/aig/ioa/ioa.h | 80 + abc70930/src/aig/ioa/ioaReadAig.c | 312 + abc70930/src/aig/ioa/ioaUtil.c | 117 + abc70930/src/aig/ioa/ioaWriteAig.c | 292 + abc70930/src/aig/ioa/module.make | 3 + abc70930/src/aig/ivy/attr.h | 414 + abc70930/src/aig/ivy/ivy.h | 557 + abc70930/src/aig/ivy/ivyBalance.c | 404 + abc70930/src/aig/ivy/ivyCanon.c | 144 + abc70930/src/aig/ivy/ivyCheck.c | 273 + abc70930/src/aig/ivy/ivyCut.c | 989 + abc70930/src/aig/ivy/ivyCutTrav.c | 473 + abc70930/src/aig/ivy/ivyDfs.c | 493 + abc70930/src/aig/ivy/ivyDsd.c | 819 + abc70930/src/aig/ivy/ivyFanout.c | 309 + abc70930/src/aig/ivy/ivyFastMap.c | 1593 + abc70930/src/aig/ivy/ivyFraig.c | 2762 + abc70930/src/aig/ivy/ivyHaig.c | 530 + abc70930/src/aig/ivy/ivyMan.c | 546 + abc70930/src/aig/ivy/ivyMem.c | 116 + abc70930/src/aig/ivy/ivyMulti.c | 301 + abc70930/src/aig/ivy/ivyMulti8.c | 427 + abc70930/src/aig/ivy/ivyObj.c | 476 + abc70930/src/aig/ivy/ivyOper.c | 293 + abc70930/src/aig/ivy/ivyResyn.c | 196 + abc70930/src/aig/ivy/ivyRwr.c | 609 + abc70930/src/aig/ivy/ivyRwrAlg.c | 408 + abc70930/src/aig/ivy/ivySeq.c | 1134 + abc70930/src/aig/ivy/ivyShow.c | 338 + abc70930/src/aig/ivy/ivyTable.c | 301 + abc70930/src/aig/ivy/ivyUtil.c | 818 + abc70930/src/aig/ivy/ivy_.c | 48 + abc70930/src/aig/ivy/module.make | 22 + abc70930/src/aig/kit/cloud.c | 987 + abc70930/src/aig/kit/cloud.h | 269 + abc70930/src/aig/kit/kit.h | 594 + abc70930/src/aig/kit/kitAig.c | 121 + abc70930/src/aig/kit/kitBdd.c | 231 + abc70930/src/aig/kit/kitCloud.c | 368 + abc70930/src/aig/kit/kitDsd.c | 2621 + abc70930/src/aig/kit/kitFactor.c | 339 + abc70930/src/aig/kit/kitGraph.c | 397 + abc70930/src/aig/kit/kitHop.c | 144 + abc70930/src/aig/kit/kitIsop.c | 325 + abc70930/src/aig/kit/kitSop.c | 572 + abc70930/src/aig/kit/kitTruth.c | 1721 + abc70930/src/aig/kit/kit_.c | 48 + abc70930/src/aig/kit/module.make | 10 + abc70930/src/aig/mem/mem.c | 604 + abc70930/src/aig/mem/mem.h | 72 + abc70930/src/aig/mem/module.make | 1 + abc70930/src/aig/rwt/module.make | 3 + abc70930/src/aig/rwt/rwt.h | 156 + abc70930/src/aig/rwt/rwtDec.c | 150 + abc70930/src/aig/rwt/rwtMan.c | 358 + abc70930/src/aig/rwt/rwtUtil.c | 665 + abc70930/src/base/.DS_Store | Bin 0 -> 6148 bytes abc70930/src/base/abc/abc.h | 929 + abc70930/src/base/abc/abcAig.c | 1476 + abc70930/src/base/abc/abcBlifMv.c | 970 + abc70930/src/base/abc/abcCheck.c | 939 + abc70930/src/base/abc/abcDfs.c | 1264 + abc70930/src/base/abc/abcFanio.c | 336 + abc70930/src/base/abc/abcFunc.c | 1154 + abc70930/src/base/abc/abcHie.c | 492 + abc70930/src/base/abc/abcInt.h | 52 + abc70930/src/base/abc/abcLatch.c | 326 + abc70930/src/base/abc/abcLib.c | 455 + abc70930/src/base/abc/abcMinBase.c | 256 + abc70930/src/base/abc/abcNames.c | 467 + abc70930/src/base/abc/abcNetlist.c | 411 + abc70930/src/base/abc/abcNtk.c | 1235 + abc70930/src/base/abc/abcObj.c | 976 + abc70930/src/base/abc/abcRefs.c | 452 + abc70930/src/base/abc/abcShow.c | 318 + abc70930/src/base/abc/abcSop.c | 1075 + abc70930/src/base/abc/abcUtil.c | 1764 + abc70930/src/base/abc/abc_.c | 47 + abc70930/src/base/abc/module.make | 18 + abc70930/src/base/abci/abc.c | 12765 ++ abc70930/src/base/abci/abcAttach.c | 404 + abc70930/src/base/abci/abcAuto.c | 239 + abc70930/src/base/abci/abcBalance.c | 613 + abc70930/src/base/abci/abcBmc.c | 115 + abc70930/src/base/abci/abcCas.c | 111 + abc70930/src/base/abci/abcClpBdd.c | 162 + abc70930/src/base/abci/abcClpSop.c | 53 + abc70930/src/base/abci/abcCut.c | 620 + abc70930/src/base/abci/abcDar.c | 1212 + abc70930/src/base/abci/abcDebug.c | 208 + abc70930/src/base/abci/abcDress.c | 209 + abc70930/src/base/abci/abcDsd.c | 551 + abc70930/src/base/abci/abcEspresso.c | 250 + abc70930/src/base/abci/abcExtract.c | 51 + abc70930/src/base/abci/abcFpga.c | 278 + abc70930/src/base/abci/abcFpgaFast.c | 190 + abc70930/src/base/abci/abcFraig.c | 803 + abc70930/src/base/abci/abcFxu.c | 260 + abc70930/src/base/abci/abcGen.c | 511 + abc70930/src/base/abci/abcHaig.c | 726 + abc70930/src/base/abci/abcIf.c | 497 + abc70930/src/base/abci/abcIvy.c | 1101 + abc70930/src/base/abci/abcLut.c | 786 + abc70930/src/base/abci/abcMap.c | 657 + abc70930/src/base/abci/abcMeasure.c | 478 + abc70930/src/base/abci/abcMini.c | 153 + abc70930/src/base/abci/abcMiter.c | 1138 + abc70930/src/base/abci/abcMulti.c | 643 + abc70930/src/base/abci/abcMv.c | 369 + abc70930/src/base/abci/abcNtbdd.c | 582 + abc70930/src/base/abci/abcOdc.c | 1134 + abc70930/src/base/abci/abcOrder.c | 131 + abc70930/src/base/abci/abcPart.c | 1205 + abc70930/src/base/abci/abcPlace.c | 255 + abc70930/src/base/abci/abcPrint.c | 953 + abc70930/src/base/abci/abcProve.c | 343 + abc70930/src/base/abci/abcQbf.c | 260 + abc70930/src/base/abci/abcQuant.c | 419 + abc70930/src/base/abci/abcRec.c | 1173 + abc70930/src/base/abci/abcReconv.c | 762 + abc70930/src/base/abci/abcRefactor.c | 379 + abc70930/src/base/abci/abcRenode.c | 311 + abc70930/src/base/abci/abcReorder.c | 100 + abc70930/src/base/abci/abcRestruct.c | 1496 + abc70930/src/base/abci/abcResub.c | 1951 + abc70930/src/base/abci/abcRewrite.c | 414 + abc70930/src/base/abci/abcRr.c | 999 + abc70930/src/base/abci/abcSat.c | 884 + abc70930/src/base/abci/abcStrash.c | 478 + abc70930/src/base/abci/abcSweep.c | 948 + abc70930/src/base/abci/abcSymm.c | 229 + abc70930/src/base/abci/abcTiming.c | 905 + abc70930/src/base/abci/abcUnate.c | 155 + abc70930/src/base/abci/abcUnreach.c | 349 + abc70930/src/base/abci/abcVerify.c | 1018 + abc70930/src/base/abci/abcXsim.c | 227 + abc70930/src/base/abci/abc_.c | 48 + abc70930/src/base/abci/module.make | 54 + abc70930/src/base/cmd/cmd.c | 1674 + abc70930/src/base/cmd/cmd.h | 73 + abc70930/src/base/cmd/cmdAlias.c | 120 + abc70930/src/base/cmd/cmdApi.c | 104 + abc70930/src/base/cmd/cmdFlag.c | 104 + abc70930/src/base/cmd/cmdHist.c | 55 + abc70930/src/base/cmd/cmdInt.h | 83 + abc70930/src/base/cmd/cmdUtils.c | 649 + abc70930/src/base/cmd/module.make | 6 + abc70930/src/base/io/io.c | 1954 + abc70930/src/base/io/io.h | 146 + abc70930/src/base/io/ioInt.h | 49 + abc70930/src/base/io/ioReadAiger.c | 310 + abc70930/src/base/io/ioReadBaf.c | 171 + abc70930/src/base/io/ioReadBench.c | 360 + abc70930/src/base/io/ioReadBlif.c | 1105 + abc70930/src/base/io/ioReadBlifAig.c | 1013 + abc70930/src/base/io/ioReadBlifMv.c | 1696 + abc70930/src/base/io/ioReadDsd.c | 308 + abc70930/src/base/io/ioReadEdif.c | 235 + abc70930/src/base/io/ioReadEqn.c | 239 + abc70930/src/base/io/ioReadPla.c | 250 + abc70930/src/base/io/ioReadVerilog.c | 90 + abc70930/src/base/io/ioUtil.c | 752 + abc70930/src/base/io/ioWriteAiger.c | 291 + abc70930/src/base/io/ioWriteBaf.c | 168 + abc70930/src/base/io/ioWriteBench.c | 335 + abc70930/src/base/io/ioWriteBlif.c | 591 + abc70930/src/base/io/ioWriteBlifMv.c | 519 + abc70930/src/base/io/ioWriteCnf.c | 115 + abc70930/src/base/io/ioWriteDot.c | 809 + abc70930/src/base/io/ioWriteEqn.c | 252 + abc70930/src/base/io/ioWriteGml.c | 116 + abc70930/src/base/io/ioWriteList.c | 288 + abc70930/src/base/io/ioWritePla.c | 197 + abc70930/src/base/io/ioWriteVerilog.c | 639 + abc70930/src/base/io/io_.c | 48 + abc70930/src/base/io/module.make | 25 + abc70930/src/base/main/libSupport.c | 193 + abc70930/src/base/main/main.c | 317 + abc70930/src/base/main/main.h | 122 + abc70930/src/base/main/mainFrame.c | 503 + abc70930/src/base/main/mainInit.c | 100 + abc70930/src/base/main/mainInt.h | 109 + abc70930/src/base/main/mainUtils.c | 277 + abc70930/src/base/main/module.make | 5 + abc70930/src/base/temp.c | 83 + abc70930/src/base/ver/module.make | 4 + abc70930/src/base/ver/ver.h | 118 + abc70930/src/base/ver/verCore.c | 2840 + abc70930/src/base/ver/verFormula.c | 474 + abc70930/src/base/ver/verParse.c | 117 + abc70930/src/base/ver/verStream.c | 443 + abc70930/src/base/ver/verWords.c | 48 + abc70930/src/base/ver/ver_.c | 48 + abc70930/src/bdd/cas/cas.h | 62 + abc70930/src/bdd/cas/casCore.c | 1263 + abc70930/src/bdd/cas/casDec.c | 508 + abc70930/src/bdd/cas/module.make | 3 + abc70930/src/bdd/cudd/cuBdd.make | 41 + abc70930/src/bdd/cudd/cudd.h | 959 + abc70930/src/bdd/cudd/cudd.make | 42 + abc70930/src/bdd/cudd/cuddAPI.c | 4409 + abc70930/src/bdd/cudd/cuddAddAbs.c | 566 + abc70930/src/bdd/cudd/cuddAddApply.c | 917 + abc70930/src/bdd/cudd/cuddAddFind.c | 283 + abc70930/src/bdd/cudd/cuddAddInv.c | 172 + abc70930/src/bdd/cudd/cuddAddIte.c | 613 + abc70930/src/bdd/cudd/cuddAddNeg.c | 262 + abc70930/src/bdd/cudd/cuddAddWalsh.c | 364 + abc70930/src/bdd/cudd/cuddAndAbs.c | 306 + abc70930/src/bdd/cudd/cuddAnneal.c | 788 + abc70930/src/bdd/cudd/cuddApa.c | 930 + abc70930/src/bdd/cudd/cuddApprox.c | 2192 + abc70930/src/bdd/cudd/cuddBddAbs.c | 689 + abc70930/src/bdd/cudd/cuddBddCorr.c | 481 + abc70930/src/bdd/cudd/cuddBddIte.c | 1254 + abc70930/src/bdd/cudd/cuddBridge.c | 981 + abc70930/src/bdd/cudd/cuddCache.c | 1023 + abc70930/src/bdd/cudd/cuddCheck.c | 851 + abc70930/src/bdd/cudd/cuddClip.c | 531 + abc70930/src/bdd/cudd/cuddCof.c | 300 + abc70930/src/bdd/cudd/cuddCompose.c | 1722 + abc70930/src/bdd/cudd/cuddDecomp.c | 2150 + abc70930/src/bdd/cudd/cuddEssent.c | 279 + abc70930/src/bdd/cudd/cuddExact.c | 1004 + abc70930/src/bdd/cudd/cuddExport.c | 1289 + abc70930/src/bdd/cudd/cuddGenCof.c | 1968 + abc70930/src/bdd/cudd/cuddGenetic.c | 921 + abc70930/src/bdd/cudd/cuddGroup.c | 2142 + abc70930/src/bdd/cudd/cuddHarwell.c | 541 + abc70930/src/bdd/cudd/cuddInit.c | 283 + abc70930/src/bdd/cudd/cuddInt.h | 1133 + abc70930/src/bdd/cudd/cuddInteract.c | 402 + abc70930/src/bdd/cudd/cuddLCache.c | 1428 + abc70930/src/bdd/cudd/cuddLevelQ.c | 533 + abc70930/src/bdd/cudd/cuddLinear.c | 1333 + abc70930/src/bdd/cudd/cuddLiteral.c | 237 + abc70930/src/bdd/cudd/cuddMatMult.c | 680 + abc70930/src/bdd/cudd/cuddPriority.c | 1475 + abc70930/src/bdd/cudd/cuddRead.c | 490 + abc70930/src/bdd/cudd/cuddRef.c | 781 + abc70930/src/bdd/cudd/cuddReorder.c | 2090 + abc70930/src/bdd/cudd/cuddSat.c | 1305 + abc70930/src/bdd/cudd/cuddSign.c | 292 + abc70930/src/bdd/cudd/cuddSolve.c | 339 + abc70930/src/bdd/cudd/cuddSplit.c | 657 + abc70930/src/bdd/cudd/cuddSubsetHB.c | 1311 + abc70930/src/bdd/cudd/cuddSubsetSP.c | 1624 + abc70930/src/bdd/cudd/cuddSymmetry.c | 1668 + abc70930/src/bdd/cudd/cuddTable.c | 3141 + abc70930/src/bdd/cudd/cuddUtil.c | 3633 + abc70930/src/bdd/cudd/cuddWindow.c | 997 + abc70930/src/bdd/cudd/cuddZddCount.c | 324 + abc70930/src/bdd/cudd/cuddZddFuncs.c | 1603 + abc70930/src/bdd/cudd/cuddZddGroup.c | 1317 + abc70930/src/bdd/cudd/cuddZddIsop.c | 885 + abc70930/src/bdd/cudd/cuddZddLin.c | 939 + abc70930/src/bdd/cudd/cuddZddMisc.c | 252 + abc70930/src/bdd/cudd/cuddZddPort.c | 354 + abc70930/src/bdd/cudd/cuddZddReord.c | 1633 + abc70930/src/bdd/cudd/cuddZddSetop.c | 1137 + abc70930/src/bdd/cudd/cuddZddSymm.c | 1677 + abc70930/src/bdd/cudd/cuddZddUtil.c | 1021 + abc70930/src/bdd/cudd/module.make | 61 + abc70930/src/bdd/cudd/r7x8.1.mat | 53 + abc70930/src/bdd/cudd/testcudd.c | 988 + abc70930/src/bdd/dsd/dsd.h | 129 + abc70930/src/bdd/dsd/dsdApi.c | 97 + abc70930/src/bdd/dsd/dsdCheck.c | 314 + abc70930/src/bdd/dsd/dsdInt.h | 91 + abc70930/src/bdd/dsd/dsdLocal.c | 337 + abc70930/src/bdd/dsd/dsdMan.c | 114 + abc70930/src/bdd/dsd/dsdProc.c | 1617 + abc70930/src/bdd/dsd/dsdTree.c | 1068 + abc70930/src/bdd/dsd/module.make | 6 + abc70930/src/bdd/epd/epd.c | 1314 + abc70930/src/bdd/epd/epd.h | 160 + abc70930/src/bdd/epd/module.make | 1 + abc70930/src/bdd/mtr/module.make | 2 + abc70930/src/bdd/mtr/mtr.h | 173 + abc70930/src/bdd/mtr/mtrBasic.c | 426 + abc70930/src/bdd/mtr/mtrGroup.c | 690 + abc70930/src/bdd/mtr/mtrInt.h | 65 + abc70930/src/bdd/parse/module.make | 3 + abc70930/src/bdd/parse/parse.h | 54 + abc70930/src/bdd/parse/parseCore.c | 504 + abc70930/src/bdd/parse/parseEqn.c | 349 + abc70930/src/bdd/parse/parseInt.h | 74 + abc70930/src/bdd/parse/parseStack.c | 243 + abc70930/src/bdd/reo/module.make | 7 + abc70930/src/bdd/reo/reo.h | 232 + abc70930/src/bdd/reo/reoApi.c | 289 + abc70930/src/bdd/reo/reoCore.c | 438 + abc70930/src/bdd/reo/reoProfile.c | 365 + abc70930/src/bdd/reo/reoSift.c | 341 + abc70930/src/bdd/reo/reoSwap.c | 898 + abc70930/src/bdd/reo/reoTest.c | 251 + abc70930/src/bdd/reo/reoTransfer.c | 199 + abc70930/src/bdd/reo/reoUnits.c | 184 + abc70930/src/generic.c | 47 + abc70930/src/generic.h | 59 + abc70930/src/map/fpga/fpga.c | 283 + abc70930/src/map/fpga/fpga.h | 172 + abc70930/src/map/fpga/fpgaCore.c | 188 + abc70930/src/map/fpga/fpgaCreate.c | 580 + abc70930/src/map/fpga/fpgaCut.c | 1159 + abc70930/src/map/fpga/fpgaCutUtils.c | 470 + abc70930/src/map/fpga/fpgaFanout.c | 141 + abc70930/src/map/fpga/fpgaGENERIC.c | 46 + abc70930/src/map/fpga/fpgaInt.h | 388 + abc70930/src/map/fpga/fpgaLib.c | 249 + abc70930/src/map/fpga/fpgaMatch.c | 794 + abc70930/src/map/fpga/fpgaSwitch.c | 151 + abc70930/src/map/fpga/fpgaTime.c | 262 + abc70930/src/map/fpga/fpgaTruth.c | 166 + abc70930/src/map/fpga/fpgaUtils.c | 986 + abc70930/src/map/fpga/fpgaVec.c | 408 + abc70930/src/map/fpga/module.make | 13 + abc70930/src/map/if/if.h | 386 + abc70930/src/map/if/ifCore.c | 146 + abc70930/src/map/if/ifCut.c | 777 + abc70930/src/map/if/ifMan.c | 570 + abc70930/src/map/if/ifMap.c | 300 + abc70930/src/map/if/ifReduce.c | 574 + abc70930/src/map/if/ifSeq.c | 405 + abc70930/src/map/if/ifTime.c | 221 + abc70930/src/map/if/ifTruth.c | 230 + abc70930/src/map/if/ifUtil.c | 454 + abc70930/src/map/if/if_.c | 47 + abc70930/src/map/if/module.make | 9 + abc70930/src/map/mapper/mapper.c | 176 + abc70930/src/map/mapper/mapper.h | 195 + abc70930/src/map/mapper/mapperCanon.c | 271 + abc70930/src/map/mapper/mapperCore.c | 228 + abc70930/src/map/mapper/mapperCreate.c | 600 + abc70930/src/map/mapper/mapperCut.c | 1168 + abc70930/src/map/mapper/mapperCutUtils.c | 273 + abc70930/src/map/mapper/mapperFanout.c | 141 + abc70930/src/map/mapper/mapperGENERIC.c | 46 + abc70930/src/map/mapper/mapperInt.h | 477 + abc70930/src/map/mapper/mapperLib.c | 231 + abc70930/src/map/mapper/mapperMatch.c | 596 + abc70930/src/map/mapper/mapperRefs.c | 557 + abc70930/src/map/mapper/mapperSuper.c | 449 + abc70930/src/map/mapper/mapperSwitch.c | 223 + abc70930/src/map/mapper/mapperTable.c | 402 + abc70930/src/map/mapper/mapperTime.c | 510 + abc70930/src/map/mapper/mapperTree.c | 818 + abc70930/src/map/mapper/mapperTruth.c | 310 + abc70930/src/map/mapper/mapperUtils.c | 1154 + abc70930/src/map/mapper/mapperVec.c | 318 + abc70930/src/map/mapper/module.make | 18 + abc70930/src/map/mio/mio.c | 269 + abc70930/src/map/mio/mio.h | 150 + abc70930/src/map/mio/mioApi.c | 172 + abc70930/src/map/mio/mioFunc.c | 268 + abc70930/src/map/mio/mioGENERIC.c | 46 + abc70930/src/map/mio/mioInt.h | 125 + abc70930/src/map/mio/mioRead.c | 582 + abc70930/src/map/mio/mioUtils.c | 531 + abc70930/src/map/mio/module.make | 5 + abc70930/src/map/super/module.make | 4 + abc70930/src/map/super/super.c | 319 + abc70930/src/map/super/super.h | 60 + abc70930/src/map/super/superAnd.c | 696 + abc70930/src/map/super/superGENERIC.c | 46 + abc70930/src/map/super/superGate.c | 1324 + abc70930/src/map/super/superInt.h | 62 + abc70930/src/map/super/superWrite.c | 76 + abc70930/src/misc/espresso/cofactor.c | 382 + abc70930/src/misc/espresso/cols.c | 314 + abc70930/src/misc/espresso/compl.c | 680 + abc70930/src/misc/espresso/contain.c | 441 + abc70930/src/misc/espresso/cubehack.c | 138 + abc70930/src/misc/espresso/cubestr.c | 152 + abc70930/src/misc/espresso/cvrin.c | 810 + abc70930/src/misc/espresso/cvrm.c | 539 + abc70930/src/misc/espresso/cvrmisc.c | 142 + abc70930/src/misc/espresso/cvrout.c | 609 + abc70930/src/misc/espresso/dominate.c | 98 + abc70930/src/misc/espresso/equiv.c | 94 + abc70930/src/misc/espresso/espresso.c | 139 + abc70930/src/misc/espresso/espresso.h | 782 + abc70930/src/misc/espresso/essen.c | 179 + abc70930/src/misc/espresso/exact.c | 181 + abc70930/src/misc/espresso/expand.c | 693 + abc70930/src/misc/espresso/gasp.c | 228 + abc70930/src/misc/espresso/gimpel.c | 106 + abc70930/src/misc/espresso/globals.c | 76 + abc70930/src/misc/espresso/hack.c | 641 + abc70930/src/misc/espresso/indep.c | 134 + abc70930/src/misc/espresso/irred.c | 440 + abc70930/src/misc/espresso/main.c | 746 + abc70930/src/misc/espresso/main.h | 122 + abc70930/src/misc/espresso/map.c | 115 + abc70930/src/misc/espresso/matrix.c | 574 + abc70930/src/misc/espresso/mincov.c | 378 + abc70930/src/misc/espresso/mincov.h | 11 + abc70930/src/misc/espresso/mincov_int.h | 55 + abc70930/src/misc/espresso/module.make | 39 + abc70930/src/misc/espresso/opo.c | 624 + abc70930/src/misc/espresso/pair.c | 675 + abc70930/src/misc/espresso/part.c | 122 + abc70930/src/misc/espresso/primes.c | 170 + abc70930/src/misc/espresso/reduce.c | 258 + abc70930/src/misc/espresso/rows.c | 314 + abc70930/src/misc/espresso/set.c | 820 + abc70930/src/misc/espresso/setc.c | 483 + abc70930/src/misc/espresso/sharp.c | 247 + abc70930/src/misc/espresso/sminterf.c | 44 + abc70930/src/misc/espresso/solution.c | 114 + abc70930/src/misc/espresso/sparse.c | 146 + abc70930/src/misc/espresso/sparse.h | 135 + abc70930/src/misc/espresso/sparse_int.h | 121 + abc70930/src/misc/espresso/unate.c | 441 + abc70930/src/misc/espresso/util_old.h | 301 + abc70930/src/misc/espresso/verify.c | 193 + abc70930/src/misc/extra/extra.h | 626 + abc70930/src/misc/extra/extraBddAuto.c | 1558 + abc70930/src/misc/extra/extraBddCas.c | 1230 + abc70930/src/misc/extra/extraBddKmap.c | 783 + abc70930/src/misc/extra/extraBddMisc.c | 1614 + abc70930/src/misc/extra/extraBddSymm.c | 1469 + abc70930/src/misc/extra/extraBddUnate.c | 641 + abc70930/src/misc/extra/extraUtilBitMatrix.c | 415 + abc70930/src/misc/extra/extraUtilCanon.c | 701 + abc70930/src/misc/extra/extraUtilFile.c | 495 + abc70930/src/misc/extra/extraUtilMemory.c | 625 + abc70930/src/misc/extra/extraUtilMisc.c | 2235 + abc70930/src/misc/extra/extraUtilProgress.c | 176 + abc70930/src/misc/extra/extraUtilReader.c | 383 + abc70930/src/misc/extra/extraUtilTruth.c | 1148 + abc70930/src/misc/extra/extraUtilUtil.c | 330 + abc70930/src/misc/extra/module.make | 15 + abc70930/src/misc/hash/hash.h | 65 + abc70930/src/misc/hash/hashFlt.h | 330 + abc70930/src/misc/hash/hashInt.h | 293 + abc70930/src/misc/hash/hashPtr.h | 331 + abc70930/src/misc/hash/module.make | 1 + abc70930/src/misc/mvc/module.make | 16 + abc70930/src/misc/mvc/mvc.c | 46 + abc70930/src/misc/mvc/mvc.h | 732 + abc70930/src/misc/mvc/mvcApi.c | 233 + abc70930/src/misc/mvc/mvcCompare.c | 369 + abc70930/src/misc/mvc/mvcContain.c | 173 + abc70930/src/misc/mvc/mvcCover.c | 251 + abc70930/src/misc/mvc/mvcCube.c | 175 + abc70930/src/misc/mvc/mvcDivide.c | 436 + abc70930/src/misc/mvc/mvcDivisor.c | 90 + abc70930/src/misc/mvc/mvcList.c | 362 + abc70930/src/misc/mvc/mvcLits.c | 345 + abc70930/src/misc/mvc/mvcMan.c | 77 + abc70930/src/misc/mvc/mvcOpAlg.c | 163 + abc70930/src/misc/mvc/mvcOpBool.c | 151 + abc70930/src/misc/mvc/mvcPrint.c | 220 + abc70930/src/misc/mvc/mvcSort.c | 141 + abc70930/src/misc/mvc/mvcUtils.c | 868 + abc70930/src/misc/nm/module.make | 2 + abc70930/src/misc/nm/nm.h | 92 + abc70930/src/misc/nm/nmApi.c | 272 + abc70930/src/misc/nm/nmInt.h | 91 + abc70930/src/misc/nm/nmTable.c | 340 + abc70930/src/misc/st/module.make | 2 + abc70930/src/misc/st/st.c | 625 + abc70930/src/misc/st/st.h | 96 + abc70930/src/misc/st/stmm.c | 688 + abc70930/src/misc/st/stmm.h | 127 + abc70930/src/misc/util/leaks.h | 30 + abc70930/src/misc/util/module.make | 1 + abc70930/src/misc/util/stdlib_hack.h | 471 + abc70930/src/misc/util/util_hack.h | 95 + abc70930/src/misc/vec/module.make | 1 + abc70930/src/misc/vec/vec.h | 110 + abc70930/src/misc/vec/vecAtt.h | 391 + abc70930/src/misc/vec/vecFlt.h | 630 + abc70930/src/misc/vec/vecInt.h | 834 + abc70930/src/misc/vec/vecPtr.h | 762 + abc70930/src/misc/vec/vecStr.h | 583 + abc70930/src/misc/vec/vecVec.h | 356 + abc70930/src/opt/cut/abcCut.c | 492 + abc70930/src/opt/cut/cut.h | 165 + abc70930/src/opt/cut/cutApi.c | 197 + abc70930/src/opt/cut/cutCut.c | 359 + abc70930/src/opt/cut/cutExpand.c | 184 + abc70930/src/opt/cut/cutInt.h | 157 + abc70930/src/opt/cut/cutList.h | 207 + abc70930/src/opt/cut/cutMan.c | 326 + abc70930/src/opt/cut/cutMerge.c | 657 + abc70930/src/opt/cut/cutNode.c | 992 + abc70930/src/opt/cut/cutOracle.c | 428 + abc70930/src/opt/cut/cutPre22.c | 988 + abc70930/src/opt/cut/cutSeq.c | 227 + abc70930/src/opt/cut/cutTruth.c | 226 + abc70930/src/opt/cut/module.make | 9 + abc70930/src/opt/dec/dec.h | 719 + abc70930/src/opt/dec/decAbc.c | 305 + abc70930/src/opt/dec/decFactor.c | 392 + abc70930/src/opt/dec/decMan.c | 83 + abc70930/src/opt/dec/decPrint.c | 284 + abc70930/src/opt/dec/decUtil.c | 134 + abc70930/src/opt/dec/module.make | 5 + abc70930/src/opt/fxu/fxu.c | 254 + abc70930/src/opt/fxu/fxu.h | 93 + abc70930/src/opt/fxu/fxuCreate.c | 431 + abc70930/src/opt/fxu/fxuHeapD.c | 445 + abc70930/src/opt/fxu/fxuHeapS.c | 444 + abc70930/src/opt/fxu/fxuInt.h | 539 + abc70930/src/opt/fxu/fxuList.c | 522 + abc70930/src/opt/fxu/fxuMatrix.c | 374 + abc70930/src/opt/fxu/fxuPair.c | 555 + abc70930/src/opt/fxu/fxuPrint.c | 195 + abc70930/src/opt/fxu/fxuReduce.c | 204 + abc70930/src/opt/fxu/fxuSelect.c | 603 + abc70930/src/opt/fxu/fxuSingle.c | 284 + abc70930/src/opt/fxu/fxuUpdate.c | 806 + abc70930/src/opt/fxu/module.make | 12 + abc70930/src/opt/lpk/lpk.h | 84 + abc70930/src/opt/lpk/lpkAbcDec.c | 290 + abc70930/src/opt/lpk/lpkAbcDsd.c | 603 + abc70930/src/opt/lpk/lpkAbcMux.c | 235 + abc70930/src/opt/lpk/lpkAbcUtil.c | 244 + abc70930/src/opt/lpk/lpkCore.c | 659 + abc70930/src/opt/lpk/lpkCut.c | 683 + abc70930/src/opt/lpk/lpkInt.h | 246 + abc70930/src/opt/lpk/lpkMan.c | 122 + abc70930/src/opt/lpk/lpkMap.c | 205 + abc70930/src/opt/lpk/lpkMulti.c | 495 + abc70930/src/opt/lpk/lpkMux.c | 247 + abc70930/src/opt/lpk/lpkSets.c | 440 + abc70930/src/opt/lpk/lpk_.c | 48 + abc70930/src/opt/lpk/module.make | 11 + abc70930/src/opt/res/module.make | 7 + abc70930/src/opt/res/res.h | 75 + abc70930/src/opt/res/resCore.c | 415 + abc70930/src/opt/res/resDivs.c | 285 + abc70930/src/opt/res/resFilter.c | 434 + abc70930/src/opt/res/resInt.h | 137 + abc70930/src/opt/res/resSat.c | 407 + abc70930/src/opt/res/resSim.c | 790 + abc70930/src/opt/res/resSim_old.c | 521 + abc70930/src/opt/res/resStrash.c | 117 + abc70930/src/opt/res/resWin.c | 485 + abc70930/src/opt/res/res_.c | 50 + abc70930/src/opt/ret/module.make | 8 + abc70930/src/opt/ret/retArea.c | 540 + abc70930/src/opt/ret/retCore.c | 132 + abc70930/src/opt/ret/retDelay.c | 305 + abc70930/src/opt/ret/retFlow.c | 783 + abc70930/src/opt/ret/retIncrem.c | 464 + abc70930/src/opt/ret/retInit.c | 349 + abc70930/src/opt/ret/retInt.h | 80 + abc70930/src/opt/ret/retLvalue.c | 395 + abc70930/src/opt/ret/ret_.c | 48 + abc70930/src/opt/rwr/module.make | 7 + abc70930/src/opt/rwr/rwr.h | 169 + abc70930/src/opt/rwr/rwrDec.c | 150 + abc70930/src/opt/rwr/rwrEva.c | 588 + abc70930/src/opt/rwr/rwrExp.c | 333 + abc70930/src/opt/rwr/rwrLib.c | 362 + abc70930/src/opt/rwr/rwrMan.c | 318 + abc70930/src/opt/rwr/rwrPrint.c | 266 + abc70930/src/opt/rwr/rwrTemp.c | 121 + abc70930/src/opt/rwr/rwrUtil.c | 659 + abc70930/src/opt/sim/module.make | 10 + abc70930/src/opt/sim/sim.h | 233 + abc70930/src/opt/sim/simMan.c | 288 + abc70930/src/opt/sim/simSat.c | 48 + abc70930/src/opt/sim/simSeq.c | 171 + abc70930/src/opt/sim/simSupp.c | 597 + abc70930/src/opt/sim/simSwitch.c | 107 + abc70930/src/opt/sim/simSym.c | 142 + abc70930/src/opt/sim/simSymSat.c | 199 + abc70930/src/opt/sim/simSymSim.c | 173 + abc70930/src/opt/sim/simSymStr.c | 488 + abc70930/src/opt/sim/simUtils.c | 711 + abc70930/src/sat/bsat/module.make | 6 + abc70930/src/sat/bsat/satInter.c | 991 + abc70930/src/sat/bsat/satMem.c | 527 + abc70930/src/sat/bsat/satMem.h | 78 + abc70930/src/sat/bsat/satSolver.c | 1358 + abc70930/src/sat/bsat/satSolver.h | 191 + abc70930/src/sat/bsat/satStore.c | 437 + abc70930/src/sat/bsat/satStore.h | 137 + abc70930/src/sat/bsat/satTrace.c | 109 + abc70930/src/sat/bsat/satUtil.c | 234 + abc70930/src/sat/bsat/satVec.h | 83 + abc70930/src/sat/csat/csat_apis.c | 769 + abc70930/src/sat/csat/csat_apis.h | 222 + abc70930/src/sat/csat/module.make | 1 + abc70930/src/sat/fraig/fraig.h | 267 + abc70930/src/sat/fraig/fraigApi.c | 297 + abc70930/src/sat/fraig/fraigCanon.c | 218 + abc70930/src/sat/fraig/fraigChoice.c | 241 + abc70930/src/sat/fraig/fraigFanout.c | 175 + abc70930/src/sat/fraig/fraigFeed.c | 909 + abc70930/src/sat/fraig/fraigInt.h | 451 + abc70930/src/sat/fraig/fraigMan.c | 540 + abc70930/src/sat/fraig/fraigMem.c | 246 + abc70930/src/sat/fraig/fraigNode.c | 313 + abc70930/src/sat/fraig/fraigPrime.c | 144 + abc70930/src/sat/fraig/fraigSat.c | 1455 + abc70930/src/sat/fraig/fraigTable.c | 657 + abc70930/src/sat/fraig/fraigUtil.c | 1034 + abc70930/src/sat/fraig/fraigVec.c | 545 + abc70930/src/sat/fraig/module.make | 12 + abc70930/src/sat/msat/module.make | 13 + abc70930/src/sat/msat/msat.h | 172 + abc70930/src/sat/msat/msatActivity.c | 160 + abc70930/src/sat/msat/msatClause.c | 529 + abc70930/src/sat/msat/msatClauseVec.c | 232 + abc70930/src/sat/msat/msatInt.h | 306 + abc70930/src/sat/msat/msatMem.c | 529 + abc70930/src/sat/msat/msatOrderH.c | 405 + abc70930/src/sat/msat/msatOrderJ.c | 472 + abc70930/src/sat/msat/msatQueue.c | 157 + abc70930/src/sat/msat/msatRead.c | 268 + abc70930/src/sat/msat/msatSolverApi.c | 500 + abc70930/src/sat/msat/msatSolverCore.c | 212 + abc70930/src/sat/msat/msatSolverIo.c | 177 + abc70930/src/sat/msat/msatSolverSearch.c | 629 + abc70930/src/sat/msat/msatSort.c | 173 + abc70930/src/sat/msat/msatVec.c | 495 + abc70930/src/sat/proof/pr.c | 1263 + abc70930/src/sat/proof/pr.h | 65 + abc70930/src/sat/proof/stats.txt | 66 + abclib.dsp | 2336 - abclib.dsw | 29 - abctestlib.dsp | 102 - abctestlib.dsw | 29 - copyright.txt | 18 - demo.c | 181 - depends.sh | 13 - readme | 26 - regtest.script | 18 - regtest_output.txt | 96 - src/aig/aig/aig.h | 556 - src/aig/aig/aigCheck.c | 163 - src/aig/aig/aigDfs.c | 700 - src/aig/aig/aigFanout.c | 189 - src/aig/aig/aigMan.c | 324 - src/aig/aig/aigMem.c | 598 - src/aig/aig/aigMffc.c | 297 - src/aig/aig/aigObj.c | 416 - src/aig/aig/aigOper.c | 532 - src/aig/aig/aigOrder.c | 171 - src/aig/aig/aigPart.c | 990 - src/aig/aig/aigRepr.c | 457 - src/aig/aig/aigRet.c | 969 - src/aig/aig/aigScl.c | 399 - src/aig/aig/aigSeq.c | 502 - src/aig/aig/aigShow.c | 356 - src/aig/aig/aigTable.c | 268 - src/aig/aig/aigTime.c | 299 - src/aig/aig/aigTiming.c | 351 - src/aig/aig/aigTruth.c | 98 - src/aig/aig/aigTsim.c | 436 - src/aig/aig/aigUtil.c | 846 - src/aig/aig/aigWin.c | 184 - src/aig/aig/aig_.c | 48 - src/aig/aig/module.make | 21 - src/aig/bar/bar.c | 177 - src/aig/bar/bar.h | 74 - src/aig/bar/module.make | 1 - src/aig/bdc/bdc.h | 73 - src/aig/bdc/bdcCore.c | 189 - src/aig/bdc/bdcDec.c | 461 - src/aig/bdc/bdcInt.h | 150 - src/aig/bdc/bdcTable.c | 140 - src/aig/bdc/bdc_.c | 49 - src/aig/bdc/module.make | 4 - src/aig/cnf/cnf.h | 162 - src/aig/cnf/cnfCore.c | 185 - src/aig/cnf/cnfCut.c | 371 - src/aig/cnf/cnfData.c | 4784 - src/aig/cnf/cnfMan.c | 202 - src/aig/cnf/cnfMap.c | 356 - src/aig/cnf/cnfPost.c | 233 - src/aig/cnf/cnfUtil.c | 188 - src/aig/cnf/cnfWrite.c | 443 - src/aig/cnf/cnf_.c | 48 - src/aig/cnf/module.make | 8 - src/aig/csw/csw.h | 65 - src/aig/csw/cswCore.c | 94 - src/aig/csw/cswCut.c | 602 - src/aig/csw/cswInt.h | 157 - src/aig/csw/cswMan.c | 125 - src/aig/csw/cswTable.c | 161 - src/aig/csw/csw_.c | 48 - src/aig/csw/module.make | 4 - src/aig/dar/dar.h | 103 - src/aig/dar/darBalance.c | 398 - src/aig/dar/darCore.c | 244 - src/aig/dar/darCut.c | 698 - src/aig/dar/darData.c | 11287 -- src/aig/dar/darInt.h | 165 - src/aig/dar/darLib.c | 980 - src/aig/dar/darMan.c | 132 - src/aig/dar/darPrec.c | 388 - src/aig/dar/darRefact.c | 591 - src/aig/dar/darResub.c | 48 - src/aig/dar/darScript.c | 369 - src/aig/dar/darTruth.c | 353 - src/aig/dar/dar_.c | 48 - src/aig/dar/module.make | 11 - src/aig/deco/deco.h | 703 - src/aig/deco/module.make | 1 - src/aig/fra/fra.h | 300 - src/aig/fra/fraBmc.c | 362 - src/aig/fra/fraCec.c | 48 - src/aig/fra/fraClass.c | 854 - src/aig/fra/fraCnf.c | 286 - src/aig/fra/fraCore.c | 428 - src/aig/fra/fraImp.c | 721 - src/aig/fra/fraInd.c | 479 - src/aig/fra/fraLcr.c | 655 - src/aig/fra/fraMan.c | 304 - src/aig/fra/fraPart.c | 263 - src/aig/fra/fraSat.c | 452 - src/aig/fra/fraSec.c | 279 - src/aig/fra/fraSim.c | 823 - src/aig/fra/fra_.c | 48 - src/aig/fra/module.make | 12 - src/aig/hop/cudd2.c | 355 - src/aig/hop/cudd2.h | 82 - src/aig/hop/hop.h | 347 - src/aig/hop/hopBalance.c | 391 - src/aig/hop/hopCheck.c | 110 - src/aig/hop/hopDfs.c | 399 - src/aig/hop/hopMan.c | 164 - src/aig/hop/hopMem.c | 115 - src/aig/hop/hopObj.c | 271 - src/aig/hop/hopOper.c | 373 - src/aig/hop/hopTable.c | 262 - src/aig/hop/hopUtil.c | 572 - src/aig/hop/hop_.c | 48 - src/aig/hop/module.make | 9 - src/aig/ioa/ioa.h | 80 - src/aig/ioa/ioaReadAig.c | 312 - src/aig/ioa/ioaUtil.c | 117 - src/aig/ioa/ioaWriteAig.c | 292 - src/aig/ioa/module.make | 3 - src/aig/ivy/attr.h | 414 - src/aig/ivy/ivy.h | 557 - src/aig/ivy/ivyBalance.c | 404 - src/aig/ivy/ivyCanon.c | 144 - src/aig/ivy/ivyCheck.c | 273 - src/aig/ivy/ivyCut.c | 989 - src/aig/ivy/ivyCutTrav.c | 473 - src/aig/ivy/ivyDfs.c | 493 - src/aig/ivy/ivyDsd.c | 819 - src/aig/ivy/ivyFanout.c | 309 - src/aig/ivy/ivyFastMap.c | 1593 - src/aig/ivy/ivyFraig.c | 2762 - src/aig/ivy/ivyHaig.c | 530 - src/aig/ivy/ivyMan.c | 546 - src/aig/ivy/ivyMem.c | 116 - src/aig/ivy/ivyMulti.c | 301 - src/aig/ivy/ivyMulti8.c | 427 - src/aig/ivy/ivyObj.c | 476 - src/aig/ivy/ivyOper.c | 293 - src/aig/ivy/ivyResyn.c | 196 - src/aig/ivy/ivyRwr.c | 609 - src/aig/ivy/ivyRwrAlg.c | 408 - src/aig/ivy/ivySeq.c | 1134 - src/aig/ivy/ivyShow.c | 338 - src/aig/ivy/ivyTable.c | 301 - src/aig/ivy/ivyUtil.c | 818 - src/aig/ivy/ivy_.c | 48 - src/aig/ivy/module.make | 22 - src/aig/kit/cloud.c | 987 - src/aig/kit/cloud.h | 269 - src/aig/kit/kit.h | 594 - src/aig/kit/kitAig.c | 121 - src/aig/kit/kitBdd.c | 231 - src/aig/kit/kitCloud.c | 368 - src/aig/kit/kitDsd.c | 2621 - src/aig/kit/kitFactor.c | 338 - src/aig/kit/kitGraph.c | 397 - src/aig/kit/kitHop.c | 144 - src/aig/kit/kitIsop.c | 325 - src/aig/kit/kitSop.c | 570 - src/aig/kit/kitTruth.c | 1729 - src/aig/kit/kit_.c | 48 - src/aig/kit/module.make | 10 - src/aig/mem/mem.c | 604 - src/aig/mem/mem.h | 72 - src/aig/mem/module.make | 1 - src/aig/rwt/module.make | 3 - src/aig/rwt/rwt.h | 156 - src/aig/rwt/rwtDec.c | 150 - src/aig/rwt/rwtMan.c | 358 - src/aig/rwt/rwtUtil.c | 665 - src/base/abc/abc.h | 929 - src/base/abc/abcAig.c | 1476 - src/base/abc/abcBlifMv.c | 970 - src/base/abc/abcCheck.c | 939 - src/base/abc/abcDfs.c | 1264 - src/base/abc/abcFanio.c | 336 - src/base/abc/abcFunc.c | 1154 - src/base/abc/abcHie.c | 492 - src/base/abc/abcInt.h | 52 - src/base/abc/abcLatch.c | 326 - src/base/abc/abcLib.c | 455 - src/base/abc/abcMinBase.c | 256 - src/base/abc/abcNames.c | 467 - src/base/abc/abcNetlist.c | 411 - src/base/abc/abcNtk.c | 1230 - src/base/abc/abcObj.c | 976 - src/base/abc/abcRefs.c | 452 - src/base/abc/abcShow.c | 318 - src/base/abc/abcSop.c | 1075 - src/base/abc/abcUtil.c | 1764 - src/base/abc/abc_.c | 47 - src/base/abc/module.make | 18 - src/base/abci/abc.c | 12764 -- src/base/abci/abcAttach.c | 404 - src/base/abci/abcAuto.c | 239 - src/base/abci/abcBalance.c | 613 - src/base/abci/abcBmc.c | 115 - src/base/abci/abcCas.c | 111 - src/base/abci/abcClpBdd.c | 162 - src/base/abci/abcClpSop.c | 53 - src/base/abci/abcCut.c | 620 - src/base/abci/abcDar.c | 1212 - src/base/abci/abcDebug.c | 208 - src/base/abci/abcDress.c | 209 - src/base/abci/abcDsd.c | 551 - src/base/abci/abcEspresso.c | 250 - src/base/abci/abcExtract.c | 51 - src/base/abci/abcFpga.c | 278 - src/base/abci/abcFpgaFast.c | 190 - src/base/abci/abcFraig.c | 803 - src/base/abci/abcFxu.c | 260 - src/base/abci/abcGen.c | 511 - src/base/abci/abcHaig.c | 726 - src/base/abci/abcIf.c | 497 - src/base/abci/abcIvy.c | 1101 - src/base/abci/abcLut.c | 786 - src/base/abci/abcMap.c | 657 - src/base/abci/abcMeasure.c | 478 - src/base/abci/abcMini.c | 153 - src/base/abci/abcMiter.c | 1138 - src/base/abci/abcMulti.c | 643 - src/base/abci/abcMv.c | 369 - src/base/abci/abcNtbdd.c | 582 - src/base/abci/abcOdc.c | 1134 - src/base/abci/abcOrder.c | 131 - src/base/abci/abcPart.c | 1205 - src/base/abci/abcPlace.c | 255 - src/base/abci/abcPrint.c | 949 - src/base/abci/abcProve.c | 343 - src/base/abci/abcQbf.c | 260 - src/base/abci/abcQuant.c | 419 - src/base/abci/abcRec.c | 1173 - src/base/abci/abcReconv.c | 762 - src/base/abci/abcRefactor.c | 379 - src/base/abci/abcRenode.c | 311 - src/base/abci/abcReorder.c | 100 - src/base/abci/abcRestruct.c | 1496 - src/base/abci/abcResub.c | 1951 - src/base/abci/abcRewrite.c | 414 - src/base/abci/abcRr.c | 999 - src/base/abci/abcSat.c | 884 - src/base/abci/abcStrash.c | 478 - src/base/abci/abcSweep.c | 948 - src/base/abci/abcSymm.c | 229 - src/base/abci/abcTiming.c | 905 - src/base/abci/abcUnate.c | 155 - src/base/abci/abcUnreach.c | 349 - src/base/abci/abcVerify.c | 1018 - src/base/abci/abcXsim.c | 227 - src/base/abci/abc_.c | 48 - src/base/abci/abc_new.h | 23 - src/base/abci/module.make | 55 - src/base/cmd/cmd.c | 1674 - src/base/cmd/cmd.h | 73 - src/base/cmd/cmdAlias.c | 120 - src/base/cmd/cmdApi.c | 104 - src/base/cmd/cmdFlag.c | 104 - src/base/cmd/cmdHist.c | 55 - src/base/cmd/cmdInt.h | 83 - src/base/cmd/cmdUtils.c | 649 - src/base/cmd/module.make | 6 - src/base/func/funcBlifMv.c | 62 - src/base/io/io.c | 1954 - src/base/io/io.h | 146 - src/base/io/ioInt.h | 49 - src/base/io/ioReadAiger.c | 310 - src/base/io/ioReadBaf.c | 171 - src/base/io/ioReadBench.c | 360 - src/base/io/ioReadBlif.c | 1105 - src/base/io/ioReadBlifAig.c | 1013 - src/base/io/ioReadBlifMv.c | 1696 - src/base/io/ioReadDsd.c | 308 - src/base/io/ioReadEdif.c | 235 - src/base/io/ioReadEqn.c | 239 - src/base/io/ioReadPla.c | 250 - src/base/io/ioReadVerilog.c | 90 - src/base/io/ioUtil.c | 752 - src/base/io/ioWriteAiger.c | 291 - src/base/io/ioWriteBaf.c | 168 - src/base/io/ioWriteBench.c | 335 - src/base/io/ioWriteBlif.c | 591 - src/base/io/ioWriteBlifMv.c | 519 - src/base/io/ioWriteCnf.c | 115 - src/base/io/ioWriteDot.c | 809 - src/base/io/ioWriteEqn.c | 252 - src/base/io/ioWriteGml.c | 116 - src/base/io/ioWriteList.c | 288 - src/base/io/ioWritePla.c | 197 - src/base/io/ioWriteVerilog.c | 636 - src/base/io/ioWriteVerilog.zip | Bin 3662 -> 0 bytes src/base/io/io_.c | 48 - src/base/io/module.make | 25 - src/base/main/libSupport.c | 193 - src/base/main/main.c | 317 - src/base/main/main.h | 122 - src/base/main/mainFrame.c | 503 - src/base/main/mainInit.c | 100 - src/base/main/mainInt.h | 109 - src/base/main/mainUtils.c | 237 - src/base/main/module.make | 5 - src/base/seq/module.make | 14 - src/base/seq/seq.h | 101 - src/base/seq/seqAigCore.c | 977 - src/base/seq/seqAigIter.c | 268 - src/base/seq/seqCreate.c | 482 - src/base/seq/seqFpgaCore.c | 643 - src/base/seq/seqFpgaIter.c | 270 - src/base/seq/seqInt.h | 256 - src/base/seq/seqLatch.c | 223 - src/base/seq/seqMan.c | 133 - src/base/seq/seqMapCore.c | 652 - src/base/seq/seqMapIter.c | 623 - src/base/seq/seqMaxMeanCycle.c | 567 - src/base/seq/seqRetCore.c | 492 - src/base/seq/seqRetIter.c | 403 - src/base/seq/seqShare.c | 388 - src/base/seq/seqUtil.c | 597 - src/base/temp.c | 83 - src/base/ver/module.make | 4 - src/base/ver/ver.h | 118 - src/base/ver/verCore.c | 2839 - src/base/ver/verCore.zip | Bin 14624 -> 0 bytes src/base/ver/verFormula.c | 474 - src/base/ver/verParse.c | 117 - src/base/ver/verStream.c | 440 - src/base/ver/verWords.c | 48 - src/base/ver/ver_.c | 48 - src/bdd/cas/cas.h | 62 - src/bdd/cas/casCore.c | 1263 - src/bdd/cas/casDec.c | 508 - src/bdd/cas/module.make | 3 - src/bdd/cudd/cuBdd.make | 41 - src/bdd/cudd/cudd.h | 959 - src/bdd/cudd/cudd.make | 42 - src/bdd/cudd/cuddAPI.c | 4409 - src/bdd/cudd/cuddAddAbs.c | 566 - src/bdd/cudd/cuddAddApply.c | 917 - src/bdd/cudd/cuddAddFind.c | 283 - src/bdd/cudd/cuddAddInv.c | 172 - src/bdd/cudd/cuddAddIte.c | 613 - src/bdd/cudd/cuddAddNeg.c | 262 - src/bdd/cudd/cuddAddWalsh.c | 364 - src/bdd/cudd/cuddAndAbs.c | 306 - src/bdd/cudd/cuddAnneal.c | 788 - src/bdd/cudd/cuddApa.c | 930 - src/bdd/cudd/cuddApprox.c | 2192 - src/bdd/cudd/cuddBddAbs.c | 689 - src/bdd/cudd/cuddBddCorr.c | 481 - src/bdd/cudd/cuddBddIte.c | 1254 - src/bdd/cudd/cuddBridge.c | 981 - src/bdd/cudd/cuddCache.c | 1023 - src/bdd/cudd/cuddCheck.c | 851 - src/bdd/cudd/cuddClip.c | 531 - src/bdd/cudd/cuddCof.c | 300 - src/bdd/cudd/cuddCompose.c | 1722 - src/bdd/cudd/cuddDecomp.c | 2150 - src/bdd/cudd/cuddEssent.c | 279 - src/bdd/cudd/cuddExact.c | 1004 - src/bdd/cudd/cuddExport.c | 1289 - src/bdd/cudd/cuddGenCof.c | 1968 - src/bdd/cudd/cuddGenetic.c | 921 - src/bdd/cudd/cuddGroup.c | 2142 - src/bdd/cudd/cuddHarwell.c | 541 - src/bdd/cudd/cuddInit.c | 283 - src/bdd/cudd/cuddInt.h | 1133 - src/bdd/cudd/cuddInteract.c | 402 - src/bdd/cudd/cuddLCache.c | 1428 - src/bdd/cudd/cuddLevelQ.c | 533 - src/bdd/cudd/cuddLinear.c | 1333 - src/bdd/cudd/cuddLiteral.c | 237 - src/bdd/cudd/cuddMatMult.c | 680 - src/bdd/cudd/cuddPriority.c | 1475 - src/bdd/cudd/cuddRead.c | 490 - src/bdd/cudd/cuddRef.c | 781 - src/bdd/cudd/cuddReorder.c | 2090 - src/bdd/cudd/cuddSat.c | 1305 - src/bdd/cudd/cuddSign.c | 292 - src/bdd/cudd/cuddSolve.c | 339 - src/bdd/cudd/cuddSplit.c | 657 - src/bdd/cudd/cuddSubsetHB.c | 1311 - src/bdd/cudd/cuddSubsetSP.c | 1624 - src/bdd/cudd/cuddSymmetry.c | 1668 - src/bdd/cudd/cuddTable.c | 3141 - src/bdd/cudd/cuddUtil.c | 3633 - src/bdd/cudd/cuddWindow.c | 997 - src/bdd/cudd/cuddZddCount.c | 324 - src/bdd/cudd/cuddZddFuncs.c | 1603 - src/bdd/cudd/cuddZddGroup.c | 1317 - src/bdd/cudd/cuddZddIsop.c | 885 - src/bdd/cudd/cuddZddLin.c | 939 - src/bdd/cudd/cuddZddMisc.c | 252 - src/bdd/cudd/cuddZddPort.c | 354 - src/bdd/cudd/cuddZddReord.c | 1633 - src/bdd/cudd/cuddZddSetop.c | 1137 - src/bdd/cudd/cuddZddSymm.c | 1677 - src/bdd/cudd/cuddZddUtil.c | 1021 - src/bdd/cudd/module.make | 61 - src/bdd/cudd/r7x8.1.mat | 53 - src/bdd/cudd/testcudd.c | 988 - src/bdd/dsd/dsd.h | 129 - src/bdd/dsd/dsdApi.c | 97 - src/bdd/dsd/dsdCheck.c | 314 - src/bdd/dsd/dsdInt.h | 91 - src/bdd/dsd/dsdLocal.c | 337 - src/bdd/dsd/dsdMan.c | 114 - src/bdd/dsd/dsdProc.c | 1617 - src/bdd/dsd/dsdTree.c | 1068 - src/bdd/dsd/module.make | 6 - src/bdd/epd/epd.c | 1314 - src/bdd/epd/epd.h | 160 - src/bdd/epd/module.make | 1 - src/bdd/mtr/module.make | 2 - src/bdd/mtr/mtr.h | 173 - src/bdd/mtr/mtrBasic.c | 426 - src/bdd/mtr/mtrGroup.c | 690 - src/bdd/mtr/mtrInt.h | 65 - src/bdd/parse/module.make | 3 - src/bdd/parse/parse.h | 54 - src/bdd/parse/parseCore.c | 504 - src/bdd/parse/parseEqn.c | 349 - src/bdd/parse/parseInt.h | 74 - src/bdd/parse/parseStack.c | 243 - src/bdd/reo/module.make | 7 - src/bdd/reo/reo.h | 232 - src/bdd/reo/reoApi.c | 289 - src/bdd/reo/reoCore.c | 438 - src/bdd/reo/reoProfile.c | 365 - src/bdd/reo/reoSift.c | 341 - src/bdd/reo/reoSwap.c | 898 - src/bdd/reo/reoTest.c | 251 - src/bdd/reo/reoTransfer.c | 199 - src/bdd/reo/reoUnits.c | 184 - src/generic.c | 47 - src/generic.h | 59 - src/map/fpga/fpga.c | 283 - src/map/fpga/fpga.h | 172 - src/map/fpga/fpgaCore.c | 188 - src/map/fpga/fpgaCreate.c | 580 - src/map/fpga/fpgaCut.c | 1159 - src/map/fpga/fpgaCutUtils.c | 470 - src/map/fpga/fpgaFanout.c | 141 - src/map/fpga/fpgaGENERIC.c | 46 - src/map/fpga/fpgaInt.h | 388 - src/map/fpga/fpgaLib.c | 249 - src/map/fpga/fpgaMatch.c | 794 - src/map/fpga/fpgaSwitch.c | 151 - src/map/fpga/fpgaTime.c | 262 - src/map/fpga/fpgaTruth.c | 166 - src/map/fpga/fpgaUtils.c | 986 - src/map/fpga/fpgaVec.c | 408 - src/map/fpga/module.make | 13 - src/map/if/if.h | 386 - src/map/if/ifCore.c | 146 - src/map/if/ifCut.c | 777 - src/map/if/ifMan.c | 570 - src/map/if/ifMap.c | 300 - src/map/if/ifReduce.c | 574 - src/map/if/ifSeq.c | 405 - src/map/if/ifTime.c | 221 - src/map/if/ifTruth.c | 230 - src/map/if/ifUtil.c | 454 - src/map/if/if_.c | 47 - src/map/if/module.make | 9 - src/map/mapper/mapper.c | 176 - src/map/mapper/mapper.h | 195 - src/map/mapper/mapperCanon.c | 271 - src/map/mapper/mapperCore.c | 228 - src/map/mapper/mapperCreate.c | 600 - src/map/mapper/mapperCut.c | 1168 - src/map/mapper/mapperCutUtils.c | 273 - src/map/mapper/mapperFanout.c | 141 - src/map/mapper/mapperGENERIC.c | 46 - src/map/mapper/mapperInt.h | 477 - src/map/mapper/mapperLib.c | 231 - src/map/mapper/mapperMatch.c | 596 - src/map/mapper/mapperRefs.c | 557 - src/map/mapper/mapperSuper.c | 449 - src/map/mapper/mapperSwitch.c | 223 - src/map/mapper/mapperTable.c | 402 - src/map/mapper/mapperTime.c | 510 - src/map/mapper/mapperTree.c | 818 - src/map/mapper/mapperTruth.c | 310 - src/map/mapper/mapperUtils.c | 1154 - src/map/mapper/mapperVec.c | 318 - src/map/mapper/module.make | 18 - src/map/mio/mio.c | 269 - src/map/mio/mio.h | 150 - src/map/mio/mioApi.c | 172 - src/map/mio/mioFunc.c | 268 - src/map/mio/mioGENERIC.c | 46 - src/map/mio/mioInt.h | 125 - src/map/mio/mioRead.c | 582 - src/map/mio/mioUtils.c | 531 - src/map/mio/module.make | 5 - src/map/pcm/module.make | 0 src/map/super/module.make | 4 - src/map/super/super.c | 319 - src/map/super/super.h | 60 - src/map/super/superAnd.c | 696 - src/map/super/superGENERIC.c | 46 - src/map/super/superGate.c | 1324 - src/map/super/superInt.h | 62 - src/map/super/superWrite.c | 76 - src/misc/espresso/cofactor.c | 382 - src/misc/espresso/cols.c | 314 - src/misc/espresso/compl.c | 680 - src/misc/espresso/contain.c | 441 - src/misc/espresso/cubehack.c | 138 - src/misc/espresso/cubestr.c | 152 - src/misc/espresso/cvrin.c | 810 - src/misc/espresso/cvrm.c | 539 - src/misc/espresso/cvrmisc.c | 142 - src/misc/espresso/cvrout.c | 609 - src/misc/espresso/dominate.c | 98 - src/misc/espresso/equiv.c | 94 - src/misc/espresso/espresso.c | 139 - src/misc/espresso/espresso.h | 782 - src/misc/espresso/essen.c | 179 - src/misc/espresso/exact.c | 181 - src/misc/espresso/expand.c | 693 - src/misc/espresso/gasp.c | 228 - src/misc/espresso/gimpel.c | 106 - src/misc/espresso/globals.c | 76 - src/misc/espresso/hack.c | 641 - src/misc/espresso/indep.c | 134 - src/misc/espresso/irred.c | 440 - src/misc/espresso/main.c | 746 - src/misc/espresso/main.h | 122 - src/misc/espresso/map.c | 115 - src/misc/espresso/matrix.c | 574 - src/misc/espresso/mincov.c | 378 - src/misc/espresso/mincov.h | 11 - src/misc/espresso/mincov_int.h | 55 - src/misc/espresso/module.make | 39 - src/misc/espresso/opo.c | 624 - src/misc/espresso/pair.c | 675 - src/misc/espresso/part.c | 122 - src/misc/espresso/primes.c | 170 - src/misc/espresso/reduce.c | 258 - src/misc/espresso/rows.c | 314 - src/misc/espresso/set.c | 820 - src/misc/espresso/setc.c | 483 - src/misc/espresso/sharp.c | 247 - src/misc/espresso/sminterf.c | 44 - src/misc/espresso/solution.c | 114 - src/misc/espresso/sparse.c | 146 - src/misc/espresso/sparse.h | 135 - src/misc/espresso/sparse_int.h | 121 - src/misc/espresso/unate.c | 441 - src/misc/espresso/util_old.h | 301 - src/misc/espresso/verify.c | 193 - src/misc/extra/extra.h | 626 - src/misc/extra/extraBddAuto.c | 1558 - src/misc/extra/extraBddCas.c | 1230 - src/misc/extra/extraBddKmap.c | 783 - src/misc/extra/extraBddMisc.c | 1614 - src/misc/extra/extraBddSymm.c | 1469 - src/misc/extra/extraBddUnate.c | 641 - src/misc/extra/extraUtilBitMatrix.c | 415 - src/misc/extra/extraUtilCanon.c | 701 - src/misc/extra/extraUtilFile.c | 495 - src/misc/extra/extraUtilMemory.c | 625 - src/misc/extra/extraUtilMisc.c | 2235 - src/misc/extra/extraUtilProgress.c | 176 - src/misc/extra/extraUtilReader.c | 383 - src/misc/extra/extraUtilTruth.c | 1148 - src/misc/extra/extraUtilUtil.c | 330 - src/misc/extra/module.make | 15 - src/misc/hash/hash.h | 65 - src/misc/hash/hashFlt.h | 330 - src/misc/hash/hashInt.h | 293 - src/misc/hash/hashPtr.h | 331 - src/misc/hash/module.make | 1 - src/misc/mvc/module.make | 16 - src/misc/mvc/mvc.c | 46 - src/misc/mvc/mvc.h | 732 - src/misc/mvc/mvcApi.c | 233 - src/misc/mvc/mvcCompare.c | 369 - src/misc/mvc/mvcContain.c | 173 - src/misc/mvc/mvcCover.c | 251 - src/misc/mvc/mvcCube.c | 175 - src/misc/mvc/mvcDivide.c | 436 - src/misc/mvc/mvcDivisor.c | 90 - src/misc/mvc/mvcList.c | 362 - src/misc/mvc/mvcLits.c | 345 - src/misc/mvc/mvcMan.c | 77 - src/misc/mvc/mvcOpAlg.c | 163 - src/misc/mvc/mvcOpBool.c | 151 - src/misc/mvc/mvcPrint.c | 220 - src/misc/mvc/mvcSort.c | 141 - src/misc/mvc/mvcUtils.c | 868 - src/misc/nm/module.make | 2 - src/misc/nm/nm.h | 92 - src/misc/nm/nmApi.c | 272 - src/misc/nm/nmInt.h | 91 - src/misc/nm/nmTable.c | 340 - src/misc/st/module.make | 2 - src/misc/st/st.c | 625 - src/misc/st/st.h | 96 - src/misc/st/stmm.c | 688 - src/misc/st/stmm.h | 127 - src/misc/util/leaks.h | 30 - src/misc/util/module.make | 1 - src/misc/util/stdlib_hack.h | 4 - src/misc/util/util_hack.h | 95 - src/misc/vec/module.make | 1 - src/misc/vec/vec.h | 110 - src/misc/vec/vecAtt.h | 391 - src/misc/vec/vecFlt.h | 630 - src/misc/vec/vecInt.h | 834 - src/misc/vec/vecPtr.h | 762 - src/misc/vec/vecStr.h | 583 - src/misc/vec/vecVec.h | 356 - src/opt/cut/abcCut.c | 492 - src/opt/cut/cut.h | 165 - src/opt/cut/cutApi.c | 197 - src/opt/cut/cutCut.c | 359 - src/opt/cut/cutExpand.c | 184 - src/opt/cut/cutInt.h | 157 - src/opt/cut/cutList.h | 207 - src/opt/cut/cutMan.c | 326 - src/opt/cut/cutMerge.c | 657 - src/opt/cut/cutNode.c | 992 - src/opt/cut/cutOracle.c | 428 - src/opt/cut/cutPre22.c | 988 - src/opt/cut/cutSeq.c | 227 - src/opt/cut/cutTruth.c | 226 - src/opt/cut/module.make | 9 - src/opt/dec/dec.h | 719 - src/opt/dec/decAbc.c | 305 - src/opt/dec/decFactor.c | 392 - src/opt/dec/decMan.c | 83 - src/opt/dec/decPrint.c | 284 - src/opt/dec/decUtil.c | 134 - src/opt/dec/module.make | 5 - src/opt/fxu/fxu.c | 254 - src/opt/fxu/fxu.h | 93 - src/opt/fxu/fxuCreate.c | 431 - src/opt/fxu/fxuHeapD.c | 445 - src/opt/fxu/fxuHeapS.c | 444 - src/opt/fxu/fxuInt.h | 539 - src/opt/fxu/fxuList.c | 522 - src/opt/fxu/fxuMatrix.c | 374 - src/opt/fxu/fxuPair.c | 555 - src/opt/fxu/fxuPrint.c | 195 - src/opt/fxu/fxuReduce.c | 204 - src/opt/fxu/fxuSelect.c | 603 - src/opt/fxu/fxuSingle.c | 284 - src/opt/fxu/fxuUpdate.c | 806 - src/opt/fxu/module.make | 12 - src/opt/lpk/lpk.h | 84 - src/opt/lpk/lpkAbcDec.c | 290 - src/opt/lpk/lpkAbcDsd.c | 603 - src/opt/lpk/lpkAbcMux.c | 235 - src/opt/lpk/lpkAbcUtil.c | 244 - src/opt/lpk/lpkCore.c | 659 - src/opt/lpk/lpkCut.c | 683 - src/opt/lpk/lpkInt.h | 246 - src/opt/lpk/lpkMan.c | 122 - src/opt/lpk/lpkMap.c | 205 - src/opt/lpk/lpkMulti.c | 495 - src/opt/lpk/lpkMux.c | 247 - src/opt/lpk/lpkSets.c | 440 - src/opt/lpk/lpk_.c | 48 - src/opt/lpk/module.make | 11 - src/opt/res/module.make | 7 - src/opt/res/res.h | 75 - src/opt/res/resCore.c | 415 - src/opt/res/resDivs.c | 285 - src/opt/res/resFilter.c | 434 - src/opt/res/resInt.h | 137 - src/opt/res/resSat.c | 407 - src/opt/res/resSim.c | 790 - src/opt/res/resSim_old.c | 521 - src/opt/res/resStrash.c | 117 - src/opt/res/resWin.c | 485 - src/opt/res/res_.c | 50 - src/opt/ret/module.make | 8 - src/opt/ret/retArea.c | 540 - src/opt/ret/retCore.c | 132 - src/opt/ret/retDelay.c | 305 - src/opt/ret/retFlow.c | 783 - src/opt/ret/retIncrem.c | 464 - src/opt/ret/retInit.c | 349 - src/opt/ret/retInt.h | 80 - src/opt/ret/retLvalue.c | 395 - src/opt/ret/ret_.c | 48 - src/opt/rwr/module.make | 7 - src/opt/rwr/rwr.h | 169 - src/opt/rwr/rwrDec.c | 150 - src/opt/rwr/rwrEva.c | 587 - src/opt/rwr/rwrExp.c | 333 - src/opt/rwr/rwrLib.c | 362 - src/opt/rwr/rwrMan.c | 318 - src/opt/rwr/rwrPrint.c | 266 - src/opt/rwr/rwrTemp.c | 121 - src/opt/rwr/rwrUtil.c | 659 - src/opt/sim/module.make | 10 - src/opt/sim/sim.h | 233 - src/opt/sim/simMan.c | 288 - src/opt/sim/simSat.c | 48 - src/opt/sim/simSeq.c | 171 - src/opt/sim/simSupp.c | 597 - src/opt/sim/simSwitch.c | 107 - src/opt/sim/simSym.c | 142 - src/opt/sim/simSymSat.c | 199 - src/opt/sim/simSymSim.c | 173 - src/opt/sim/simSymStr.c | 488 - src/opt/sim/simUtils.c | 711 - src/phys/place/Makefile | 30 - src/phys/place/README | 50 - src/phys/place/hpwl | 57 - src/phys/place/libhmetis.h | 31 - src/phys/place/module.make | 10 - src/phys/place/place_base.c | 345 - src/phys/place/place_base.h | 137 - src/phys/place/place_bin.c | 277 - src/phys/place/place_genqp.c | 309 - src/phys/place/place_gordian.c | 160 - src/phys/place/place_gordian.h | 78 - src/phys/place/place_inc.c | 106 - src/phys/place/place_io.c | 94 - src/phys/place/place_legalize.c | 23 - src/phys/place/place_pads.c | 141 - src/phys/place/place_partition.c | 1135 - src/phys/place/place_qpsolver.c | 1270 - src/phys/place/place_qpsolver.h | 140 - src/phys/place/place_test.c | 360 - src/sat/bsat/module.make | 6 - src/sat/bsat/satInter.c | 991 - src/sat/bsat/satMem.c | 527 - src/sat/bsat/satMem.h | 78 - src/sat/bsat/satSolver.c | 1358 - src/sat/bsat/satSolver.h | 191 - src/sat/bsat/satStore.c | 437 - src/sat/bsat/satStore.h | 137 - src/sat/bsat/satTrace.c | 109 - src/sat/bsat/satUtil.c | 234 - src/sat/bsat/satVec.h | 83 - src/sat/csat/csat_apis.c | 769 - src/sat/csat/csat_apis.h | 222 - src/sat/csat/module.make | 1 - src/sat/fraig/fraig.h | 267 - src/sat/fraig/fraigApi.c | 297 - src/sat/fraig/fraigCanon.c | 218 - src/sat/fraig/fraigChoice.c | 241 - src/sat/fraig/fraigFanout.c | 175 - src/sat/fraig/fraigFeed.c | 909 - src/sat/fraig/fraigInt.h | 451 - src/sat/fraig/fraigMan.c | 540 - src/sat/fraig/fraigMem.c | 246 - src/sat/fraig/fraigNode.c | 313 - src/sat/fraig/fraigPrime.c | 144 - src/sat/fraig/fraigSat.c | 1455 - src/sat/fraig/fraigTable.c | 657 - src/sat/fraig/fraigUtil.c | 1034 - src/sat/fraig/fraigVec.c | 545 - src/sat/fraig/module.make | 12 - src/sat/msat/module.make | 13 - src/sat/msat/msat.h | 172 - src/sat/msat/msatActivity.c | 160 - src/sat/msat/msatClause.c | 529 - src/sat/msat/msatClauseVec.c | 232 - src/sat/msat/msatInt.h | 306 - src/sat/msat/msatMem.c | 529 - src/sat/msat/msatOrderH.c | 405 - src/sat/msat/msatOrderJ.c | 472 - src/sat/msat/msatQueue.c | 157 - src/sat/msat/msatRead.c | 268 - src/sat/msat/msatSolverApi.c | 500 - src/sat/msat/msatSolverCore.c | 212 - src/sat/msat/msatSolverIo.c | 177 - src/sat/msat/msatSolverSearch.c | 629 - src/sat/msat/msatSort.c | 173 - src/sat/msat/msatVec.c | 495 - src/sat/proof/pr.c | 1263 - src/sat/proof/pr.h | 65 - src/sat/proof/stats.txt | 66 - todo.txt | 26 - 1547 files changed, 602089 insertions(+), 371421 deletions(-) delete mode 100644 Makefile create mode 100644 __MACOSX/abc70930/._.DS_Store create mode 100644 __MACOSX/abc70930/._Instructions_for_Mac_OS_X_X_code_users.rtf create mode 100644 __MACOSX/abc70930/src/._.DS_Store create mode 100644 __MACOSX/abc70930/src/aig/hop/._cudd2.c create mode 100644 __MACOSX/abc70930/src/base/._.DS_Store create mode 100644 __MACOSX/abc70930/src/base/main/._main.h create mode 100644 __MACOSX/abc70930/src/base/main/._mainUtils.c create mode 100644 __MACOSX/abc70930/src/misc/espresso/._unate.c delete mode 100644 abc.dsp delete mode 100644 abc.dsw delete mode 100644 abc.rc create mode 100644 abc70930/.DS_Store create mode 100644 abc70930/Instructions_for_Mac_OS_X_X_code_users.rtf create mode 100644 abc70930/Makefile create mode 100644 abc70930/abc.dsp create mode 100644 abc70930/abc.dsw create mode 100644 abc70930/abc.plg create mode 100644 abc70930/abc.rc create mode 100644 abc70930/abclib.dsp create mode 100644 abc70930/abclib.dsw create mode 100644 abc70930/abclib.plg create mode 100644 abc70930/abctestlib.dsp create mode 100644 abc70930/abctestlib.dsw create mode 100644 abc70930/abctestlib.plg create mode 100644 abc70930/copyright.txt create mode 100644 abc70930/demo.c create mode 100755 abc70930/depends.sh create mode 100644 abc70930/examples/C2670.blif create mode 100644 abc70930/examples/ac.v create mode 100644 abc70930/examples/apex4.pla create mode 100644 abc70930/examples/frg2.blif create mode 100644 abc70930/examples/i10.blif create mode 100644 abc70930/examples/pj1.blif create mode 100644 abc70930/examples/s38417.blif create mode 100644 abc70930/examples/s38584.bench create mode 100644 abc70930/examples/s444.blif create mode 100644 abc70930/examples/s5378.blif create mode 100644 abc70930/examples/s6669.blif create mode 100644 abc70930/readme create mode 100644 abc70930/regtest.script create mode 100644 abc70930/regtest_output.txt create mode 100644 abc70930/src/.DS_Store create mode 100644 abc70930/src/abc.1 create mode 100644 abc70930/src/abc.xcodeproj/project.pbxproj create mode 100644 abc70930/src/abc.xcodeproj/raiyan.pbxuser create mode 100644 abc70930/src/abc.xcodeproj/raiyan.perspectivev3 create mode 100644 abc70930/src/aig/aig/aig.h create mode 100644 abc70930/src/aig/aig/aigCheck.c create mode 100644 abc70930/src/aig/aig/aigDfs.c create mode 100644 abc70930/src/aig/aig/aigFanout.c create mode 100644 abc70930/src/aig/aig/aigMan.c create mode 100644 abc70930/src/aig/aig/aigMem.c create mode 100644 abc70930/src/aig/aig/aigMffc.c create mode 100644 abc70930/src/aig/aig/aigObj.c create mode 100644 abc70930/src/aig/aig/aigOper.c create mode 100644 abc70930/src/aig/aig/aigOrder.c create mode 100644 abc70930/src/aig/aig/aigPart.c create mode 100644 abc70930/src/aig/aig/aigRepr.c create mode 100644 abc70930/src/aig/aig/aigRet.c create mode 100644 abc70930/src/aig/aig/aigScl.c create mode 100644 abc70930/src/aig/aig/aigSeq.c create mode 100644 abc70930/src/aig/aig/aigShow.c create mode 100644 abc70930/src/aig/aig/aigTable.c create mode 100644 abc70930/src/aig/aig/aigTime.c create mode 100644 abc70930/src/aig/aig/aigTiming.c create mode 100644 abc70930/src/aig/aig/aigTruth.c create mode 100644 abc70930/src/aig/aig/aigTsim.c create mode 100644 abc70930/src/aig/aig/aigUtil.c create mode 100644 abc70930/src/aig/aig/aigWin.c create mode 100644 abc70930/src/aig/aig/aig_.c create mode 100644 abc70930/src/aig/aig/module.make create mode 100644 abc70930/src/aig/bar/bar.c create mode 100644 abc70930/src/aig/bar/bar.h create mode 100644 abc70930/src/aig/bar/module.make create mode 100644 abc70930/src/aig/bdc/bdc.h create mode 100644 abc70930/src/aig/bdc/bdcCore.c create mode 100644 abc70930/src/aig/bdc/bdcDec.c create mode 100644 abc70930/src/aig/bdc/bdcInt.h create mode 100644 abc70930/src/aig/bdc/bdcTable.c create mode 100644 abc70930/src/aig/bdc/bdc_.c create mode 100644 abc70930/src/aig/bdc/module.make create mode 100644 abc70930/src/aig/cnf/cnf.h create mode 100644 abc70930/src/aig/cnf/cnfCore.c create mode 100644 abc70930/src/aig/cnf/cnfCut.c create mode 100644 abc70930/src/aig/cnf/cnfData.c create mode 100644 abc70930/src/aig/cnf/cnfMan.c create mode 100644 abc70930/src/aig/cnf/cnfMap.c create mode 100644 abc70930/src/aig/cnf/cnfPost.c create mode 100644 abc70930/src/aig/cnf/cnfUtil.c create mode 100644 abc70930/src/aig/cnf/cnfWrite.c create mode 100644 abc70930/src/aig/cnf/cnf_.c create mode 100644 abc70930/src/aig/cnf/module.make create mode 100644 abc70930/src/aig/csw/csw.h create mode 100644 abc70930/src/aig/csw/cswCore.c create mode 100644 abc70930/src/aig/csw/cswCut.c create mode 100644 abc70930/src/aig/csw/cswInt.h create mode 100644 abc70930/src/aig/csw/cswMan.c create mode 100644 abc70930/src/aig/csw/cswTable.c create mode 100644 abc70930/src/aig/csw/csw_.c create mode 100644 abc70930/src/aig/csw/module.make create mode 100644 abc70930/src/aig/dar/dar.h create mode 100644 abc70930/src/aig/dar/darBalance.c create mode 100644 abc70930/src/aig/dar/darCore.c create mode 100644 abc70930/src/aig/dar/darCut.c create mode 100644 abc70930/src/aig/dar/darData.c create mode 100644 abc70930/src/aig/dar/darInt.h create mode 100644 abc70930/src/aig/dar/darLib.c create mode 100644 abc70930/src/aig/dar/darMan.c create mode 100644 abc70930/src/aig/dar/darPrec.c create mode 100644 abc70930/src/aig/dar/darRefact.c create mode 100644 abc70930/src/aig/dar/darResub.c create mode 100644 abc70930/src/aig/dar/darScript.c create mode 100644 abc70930/src/aig/dar/dar_.c create mode 100644 abc70930/src/aig/dar/module.make create mode 100644 abc70930/src/aig/deco/deco.h create mode 100644 abc70930/src/aig/deco/module.make create mode 100644 abc70930/src/aig/fra/fra.h create mode 100644 abc70930/src/aig/fra/fraBmc.c create mode 100644 abc70930/src/aig/fra/fraCec.c create mode 100644 abc70930/src/aig/fra/fraClass.c create mode 100644 abc70930/src/aig/fra/fraCnf.c create mode 100644 abc70930/src/aig/fra/fraCore.c create mode 100644 abc70930/src/aig/fra/fraImp.c create mode 100644 abc70930/src/aig/fra/fraInd.c create mode 100644 abc70930/src/aig/fra/fraLcr.c create mode 100644 abc70930/src/aig/fra/fraMan.c create mode 100644 abc70930/src/aig/fra/fraPart.c create mode 100644 abc70930/src/aig/fra/fraSat.c create mode 100644 abc70930/src/aig/fra/fraSec.c create mode 100644 abc70930/src/aig/fra/fraSim.c create mode 100644 abc70930/src/aig/fra/fra_.c create mode 100644 abc70930/src/aig/fra/module.make create mode 100644 abc70930/src/aig/hop/cudd2.c create mode 100644 abc70930/src/aig/hop/cudd2.h create mode 100644 abc70930/src/aig/hop/hop.h create mode 100644 abc70930/src/aig/hop/hopBalance.c create mode 100644 abc70930/src/aig/hop/hopCheck.c create mode 100644 abc70930/src/aig/hop/hopDfs.c create mode 100644 abc70930/src/aig/hop/hopMan.c create mode 100644 abc70930/src/aig/hop/hopMem.c create mode 100644 abc70930/src/aig/hop/hopObj.c create mode 100644 abc70930/src/aig/hop/hopOper.c create mode 100644 abc70930/src/aig/hop/hopTable.c create mode 100644 abc70930/src/aig/hop/hopUtil.c create mode 100644 abc70930/src/aig/hop/hop_.c create mode 100644 abc70930/src/aig/hop/module.make create mode 100644 abc70930/src/aig/ioa/ioa.h create mode 100644 abc70930/src/aig/ioa/ioaReadAig.c create mode 100644 abc70930/src/aig/ioa/ioaUtil.c create mode 100644 abc70930/src/aig/ioa/ioaWriteAig.c create mode 100644 abc70930/src/aig/ioa/module.make create mode 100644 abc70930/src/aig/ivy/attr.h create mode 100644 abc70930/src/aig/ivy/ivy.h create mode 100644 abc70930/src/aig/ivy/ivyBalance.c create mode 100644 abc70930/src/aig/ivy/ivyCanon.c create mode 100644 abc70930/src/aig/ivy/ivyCheck.c create mode 100644 abc70930/src/aig/ivy/ivyCut.c create mode 100644 abc70930/src/aig/ivy/ivyCutTrav.c create mode 100644 abc70930/src/aig/ivy/ivyDfs.c create mode 100644 abc70930/src/aig/ivy/ivyDsd.c create mode 100644 abc70930/src/aig/ivy/ivyFanout.c create mode 100644 abc70930/src/aig/ivy/ivyFastMap.c create mode 100644 abc70930/src/aig/ivy/ivyFraig.c create mode 100644 abc70930/src/aig/ivy/ivyHaig.c create mode 100644 abc70930/src/aig/ivy/ivyMan.c create mode 100644 abc70930/src/aig/ivy/ivyMem.c create mode 100644 abc70930/src/aig/ivy/ivyMulti.c create mode 100644 abc70930/src/aig/ivy/ivyMulti8.c create mode 100644 abc70930/src/aig/ivy/ivyObj.c create mode 100644 abc70930/src/aig/ivy/ivyOper.c create mode 100644 abc70930/src/aig/ivy/ivyResyn.c create mode 100644 abc70930/src/aig/ivy/ivyRwr.c create mode 100644 abc70930/src/aig/ivy/ivyRwrAlg.c create mode 100644 abc70930/src/aig/ivy/ivySeq.c create mode 100644 abc70930/src/aig/ivy/ivyShow.c create mode 100644 abc70930/src/aig/ivy/ivyTable.c create mode 100644 abc70930/src/aig/ivy/ivyUtil.c create mode 100644 abc70930/src/aig/ivy/ivy_.c create mode 100644 abc70930/src/aig/ivy/module.make create mode 100644 abc70930/src/aig/kit/cloud.c create mode 100644 abc70930/src/aig/kit/cloud.h create mode 100644 abc70930/src/aig/kit/kit.h create mode 100644 abc70930/src/aig/kit/kitAig.c create mode 100644 abc70930/src/aig/kit/kitBdd.c create mode 100644 abc70930/src/aig/kit/kitCloud.c create mode 100644 abc70930/src/aig/kit/kitDsd.c create mode 100644 abc70930/src/aig/kit/kitFactor.c create mode 100644 abc70930/src/aig/kit/kitGraph.c create mode 100644 abc70930/src/aig/kit/kitHop.c create mode 100644 abc70930/src/aig/kit/kitIsop.c create mode 100644 abc70930/src/aig/kit/kitSop.c create mode 100644 abc70930/src/aig/kit/kitTruth.c create mode 100644 abc70930/src/aig/kit/kit_.c create mode 100644 abc70930/src/aig/kit/module.make create mode 100644 abc70930/src/aig/mem/mem.c create mode 100644 abc70930/src/aig/mem/mem.h create mode 100644 abc70930/src/aig/mem/module.make create mode 100644 abc70930/src/aig/rwt/module.make create mode 100644 abc70930/src/aig/rwt/rwt.h create mode 100644 abc70930/src/aig/rwt/rwtDec.c create mode 100644 abc70930/src/aig/rwt/rwtMan.c create mode 100644 abc70930/src/aig/rwt/rwtUtil.c create mode 100644 abc70930/src/base/.DS_Store create mode 100644 abc70930/src/base/abc/abc.h create mode 100644 abc70930/src/base/abc/abcAig.c create mode 100644 abc70930/src/base/abc/abcBlifMv.c create mode 100644 abc70930/src/base/abc/abcCheck.c create mode 100644 abc70930/src/base/abc/abcDfs.c create mode 100644 abc70930/src/base/abc/abcFanio.c create mode 100644 abc70930/src/base/abc/abcFunc.c create mode 100644 abc70930/src/base/abc/abcHie.c create mode 100644 abc70930/src/base/abc/abcInt.h create mode 100644 abc70930/src/base/abc/abcLatch.c create mode 100644 abc70930/src/base/abc/abcLib.c create mode 100644 abc70930/src/base/abc/abcMinBase.c create mode 100644 abc70930/src/base/abc/abcNames.c create mode 100644 abc70930/src/base/abc/abcNetlist.c create mode 100644 abc70930/src/base/abc/abcNtk.c create mode 100644 abc70930/src/base/abc/abcObj.c create mode 100644 abc70930/src/base/abc/abcRefs.c create mode 100644 abc70930/src/base/abc/abcShow.c create mode 100644 abc70930/src/base/abc/abcSop.c create mode 100644 abc70930/src/base/abc/abcUtil.c create mode 100644 abc70930/src/base/abc/abc_.c create mode 100644 abc70930/src/base/abc/module.make create mode 100644 abc70930/src/base/abci/abc.c create mode 100644 abc70930/src/base/abci/abcAttach.c create mode 100644 abc70930/src/base/abci/abcAuto.c create mode 100644 abc70930/src/base/abci/abcBalance.c create mode 100644 abc70930/src/base/abci/abcBmc.c create mode 100644 abc70930/src/base/abci/abcCas.c create mode 100644 abc70930/src/base/abci/abcClpBdd.c create mode 100644 abc70930/src/base/abci/abcClpSop.c create mode 100644 abc70930/src/base/abci/abcCut.c create mode 100644 abc70930/src/base/abci/abcDar.c create mode 100644 abc70930/src/base/abci/abcDebug.c create mode 100644 abc70930/src/base/abci/abcDress.c create mode 100644 abc70930/src/base/abci/abcDsd.c create mode 100644 abc70930/src/base/abci/abcEspresso.c create mode 100644 abc70930/src/base/abci/abcExtract.c create mode 100644 abc70930/src/base/abci/abcFpga.c create mode 100644 abc70930/src/base/abci/abcFpgaFast.c create mode 100644 abc70930/src/base/abci/abcFraig.c create mode 100644 abc70930/src/base/abci/abcFxu.c create mode 100644 abc70930/src/base/abci/abcGen.c create mode 100644 abc70930/src/base/abci/abcHaig.c create mode 100644 abc70930/src/base/abci/abcIf.c create mode 100644 abc70930/src/base/abci/abcIvy.c create mode 100644 abc70930/src/base/abci/abcLut.c create mode 100644 abc70930/src/base/abci/abcMap.c create mode 100644 abc70930/src/base/abci/abcMeasure.c create mode 100644 abc70930/src/base/abci/abcMini.c create mode 100644 abc70930/src/base/abci/abcMiter.c create mode 100644 abc70930/src/base/abci/abcMulti.c create mode 100644 abc70930/src/base/abci/abcMv.c create mode 100644 abc70930/src/base/abci/abcNtbdd.c create mode 100644 abc70930/src/base/abci/abcOdc.c create mode 100644 abc70930/src/base/abci/abcOrder.c create mode 100644 abc70930/src/base/abci/abcPart.c create mode 100644 abc70930/src/base/abci/abcPlace.c create mode 100644 abc70930/src/base/abci/abcPrint.c create mode 100644 abc70930/src/base/abci/abcProve.c create mode 100644 abc70930/src/base/abci/abcQbf.c create mode 100644 abc70930/src/base/abci/abcQuant.c create mode 100644 abc70930/src/base/abci/abcRec.c create mode 100644 abc70930/src/base/abci/abcReconv.c create mode 100644 abc70930/src/base/abci/abcRefactor.c create mode 100644 abc70930/src/base/abci/abcRenode.c create mode 100644 abc70930/src/base/abci/abcReorder.c create mode 100644 abc70930/src/base/abci/abcRestruct.c create mode 100644 abc70930/src/base/abci/abcResub.c create mode 100644 abc70930/src/base/abci/abcRewrite.c create mode 100644 abc70930/src/base/abci/abcRr.c create mode 100644 abc70930/src/base/abci/abcSat.c create mode 100644 abc70930/src/base/abci/abcStrash.c create mode 100644 abc70930/src/base/abci/abcSweep.c create mode 100644 abc70930/src/base/abci/abcSymm.c create mode 100644 abc70930/src/base/abci/abcTiming.c create mode 100644 abc70930/src/base/abci/abcUnate.c create mode 100644 abc70930/src/base/abci/abcUnreach.c create mode 100644 abc70930/src/base/abci/abcVerify.c create mode 100644 abc70930/src/base/abci/abcXsim.c create mode 100644 abc70930/src/base/abci/abc_.c create mode 100644 abc70930/src/base/abci/module.make create mode 100644 abc70930/src/base/cmd/cmd.c create mode 100644 abc70930/src/base/cmd/cmd.h create mode 100644 abc70930/src/base/cmd/cmdAlias.c create mode 100644 abc70930/src/base/cmd/cmdApi.c create mode 100644 abc70930/src/base/cmd/cmdFlag.c create mode 100644 abc70930/src/base/cmd/cmdHist.c create mode 100644 abc70930/src/base/cmd/cmdInt.h create mode 100644 abc70930/src/base/cmd/cmdUtils.c create mode 100644 abc70930/src/base/cmd/module.make create mode 100644 abc70930/src/base/io/io.c create mode 100644 abc70930/src/base/io/io.h create mode 100644 abc70930/src/base/io/ioInt.h create mode 100644 abc70930/src/base/io/ioReadAiger.c create mode 100644 abc70930/src/base/io/ioReadBaf.c create mode 100644 abc70930/src/base/io/ioReadBench.c create mode 100644 abc70930/src/base/io/ioReadBlif.c create mode 100644 abc70930/src/base/io/ioReadBlifAig.c create mode 100644 abc70930/src/base/io/ioReadBlifMv.c create mode 100644 abc70930/src/base/io/ioReadDsd.c create mode 100644 abc70930/src/base/io/ioReadEdif.c create mode 100644 abc70930/src/base/io/ioReadEqn.c create mode 100644 abc70930/src/base/io/ioReadPla.c create mode 100644 abc70930/src/base/io/ioReadVerilog.c create mode 100644 abc70930/src/base/io/ioUtil.c create mode 100644 abc70930/src/base/io/ioWriteAiger.c create mode 100644 abc70930/src/base/io/ioWriteBaf.c create mode 100644 abc70930/src/base/io/ioWriteBench.c create mode 100644 abc70930/src/base/io/ioWriteBlif.c create mode 100644 abc70930/src/base/io/ioWriteBlifMv.c create mode 100644 abc70930/src/base/io/ioWriteCnf.c create mode 100644 abc70930/src/base/io/ioWriteDot.c create mode 100644 abc70930/src/base/io/ioWriteEqn.c create mode 100644 abc70930/src/base/io/ioWriteGml.c create mode 100644 abc70930/src/base/io/ioWriteList.c create mode 100644 abc70930/src/base/io/ioWritePla.c create mode 100644 abc70930/src/base/io/ioWriteVerilog.c create mode 100644 abc70930/src/base/io/io_.c create mode 100644 abc70930/src/base/io/module.make create mode 100644 abc70930/src/base/main/libSupport.c create mode 100644 abc70930/src/base/main/main.c create mode 100644 abc70930/src/base/main/main.h create mode 100644 abc70930/src/base/main/mainFrame.c create mode 100644 abc70930/src/base/main/mainInit.c create mode 100644 abc70930/src/base/main/mainInt.h create mode 100644 abc70930/src/base/main/mainUtils.c create mode 100644 abc70930/src/base/main/module.make create mode 100644 abc70930/src/base/temp.c create mode 100644 abc70930/src/base/ver/module.make create mode 100644 abc70930/src/base/ver/ver.h create mode 100644 abc70930/src/base/ver/verCore.c create mode 100644 abc70930/src/base/ver/verFormula.c create mode 100644 abc70930/src/base/ver/verParse.c create mode 100644 abc70930/src/base/ver/verStream.c create mode 100644 abc70930/src/base/ver/verWords.c create mode 100644 abc70930/src/base/ver/ver_.c create mode 100644 abc70930/src/bdd/cas/cas.h create mode 100644 abc70930/src/bdd/cas/casCore.c create mode 100644 abc70930/src/bdd/cas/casDec.c create mode 100644 abc70930/src/bdd/cas/module.make create mode 100644 abc70930/src/bdd/cudd/cuBdd.make create mode 100644 abc70930/src/bdd/cudd/cudd.h create mode 100644 abc70930/src/bdd/cudd/cudd.make create mode 100644 abc70930/src/bdd/cudd/cuddAPI.c create mode 100644 abc70930/src/bdd/cudd/cuddAddAbs.c create mode 100644 abc70930/src/bdd/cudd/cuddAddApply.c create mode 100644 abc70930/src/bdd/cudd/cuddAddFind.c create mode 100644 abc70930/src/bdd/cudd/cuddAddInv.c create mode 100644 abc70930/src/bdd/cudd/cuddAddIte.c create mode 100644 abc70930/src/bdd/cudd/cuddAddNeg.c create mode 100644 abc70930/src/bdd/cudd/cuddAddWalsh.c create mode 100644 abc70930/src/bdd/cudd/cuddAndAbs.c create mode 100644 abc70930/src/bdd/cudd/cuddAnneal.c create mode 100644 abc70930/src/bdd/cudd/cuddApa.c create mode 100644 abc70930/src/bdd/cudd/cuddApprox.c create mode 100644 abc70930/src/bdd/cudd/cuddBddAbs.c create mode 100644 abc70930/src/bdd/cudd/cuddBddCorr.c create mode 100644 abc70930/src/bdd/cudd/cuddBddIte.c create mode 100644 abc70930/src/bdd/cudd/cuddBridge.c create mode 100644 abc70930/src/bdd/cudd/cuddCache.c create mode 100644 abc70930/src/bdd/cudd/cuddCheck.c create mode 100644 abc70930/src/bdd/cudd/cuddClip.c create mode 100644 abc70930/src/bdd/cudd/cuddCof.c create mode 100644 abc70930/src/bdd/cudd/cuddCompose.c create mode 100644 abc70930/src/bdd/cudd/cuddDecomp.c create mode 100644 abc70930/src/bdd/cudd/cuddEssent.c create mode 100644 abc70930/src/bdd/cudd/cuddExact.c create mode 100644 abc70930/src/bdd/cudd/cuddExport.c create mode 100644 abc70930/src/bdd/cudd/cuddGenCof.c create mode 100644 abc70930/src/bdd/cudd/cuddGenetic.c create mode 100644 abc70930/src/bdd/cudd/cuddGroup.c create mode 100644 abc70930/src/bdd/cudd/cuddHarwell.c create mode 100644 abc70930/src/bdd/cudd/cuddInit.c create mode 100644 abc70930/src/bdd/cudd/cuddInt.h create mode 100644 abc70930/src/bdd/cudd/cuddInteract.c create mode 100644 abc70930/src/bdd/cudd/cuddLCache.c create mode 100644 abc70930/src/bdd/cudd/cuddLevelQ.c create mode 100644 abc70930/src/bdd/cudd/cuddLinear.c create mode 100644 abc70930/src/bdd/cudd/cuddLiteral.c create mode 100644 abc70930/src/bdd/cudd/cuddMatMult.c create mode 100644 abc70930/src/bdd/cudd/cuddPriority.c create mode 100644 abc70930/src/bdd/cudd/cuddRead.c create mode 100644 abc70930/src/bdd/cudd/cuddRef.c create mode 100644 abc70930/src/bdd/cudd/cuddReorder.c create mode 100644 abc70930/src/bdd/cudd/cuddSat.c create mode 100644 abc70930/src/bdd/cudd/cuddSign.c create mode 100644 abc70930/src/bdd/cudd/cuddSolve.c create mode 100644 abc70930/src/bdd/cudd/cuddSplit.c create mode 100644 abc70930/src/bdd/cudd/cuddSubsetHB.c create mode 100644 abc70930/src/bdd/cudd/cuddSubsetSP.c create mode 100644 abc70930/src/bdd/cudd/cuddSymmetry.c create mode 100644 abc70930/src/bdd/cudd/cuddTable.c create mode 100644 abc70930/src/bdd/cudd/cuddUtil.c create mode 100644 abc70930/src/bdd/cudd/cuddWindow.c create mode 100644 abc70930/src/bdd/cudd/cuddZddCount.c create mode 100644 abc70930/src/bdd/cudd/cuddZddFuncs.c create mode 100644 abc70930/src/bdd/cudd/cuddZddGroup.c create mode 100644 abc70930/src/bdd/cudd/cuddZddIsop.c create mode 100644 abc70930/src/bdd/cudd/cuddZddLin.c create mode 100644 abc70930/src/bdd/cudd/cuddZddMisc.c create mode 100644 abc70930/src/bdd/cudd/cuddZddPort.c create mode 100644 abc70930/src/bdd/cudd/cuddZddReord.c create mode 100644 abc70930/src/bdd/cudd/cuddZddSetop.c create mode 100644 abc70930/src/bdd/cudd/cuddZddSymm.c create mode 100644 abc70930/src/bdd/cudd/cuddZddUtil.c create mode 100644 abc70930/src/bdd/cudd/module.make create mode 100644 abc70930/src/bdd/cudd/r7x8.1.mat create mode 100644 abc70930/src/bdd/cudd/testcudd.c create mode 100644 abc70930/src/bdd/dsd/dsd.h create mode 100644 abc70930/src/bdd/dsd/dsdApi.c create mode 100644 abc70930/src/bdd/dsd/dsdCheck.c create mode 100644 abc70930/src/bdd/dsd/dsdInt.h create mode 100644 abc70930/src/bdd/dsd/dsdLocal.c create mode 100644 abc70930/src/bdd/dsd/dsdMan.c create mode 100644 abc70930/src/bdd/dsd/dsdProc.c create mode 100644 abc70930/src/bdd/dsd/dsdTree.c create mode 100644 abc70930/src/bdd/dsd/module.make create mode 100644 abc70930/src/bdd/epd/epd.c create mode 100644 abc70930/src/bdd/epd/epd.h create mode 100644 abc70930/src/bdd/epd/module.make create mode 100644 abc70930/src/bdd/mtr/module.make create mode 100644 abc70930/src/bdd/mtr/mtr.h create mode 100644 abc70930/src/bdd/mtr/mtrBasic.c create mode 100644 abc70930/src/bdd/mtr/mtrGroup.c create mode 100644 abc70930/src/bdd/mtr/mtrInt.h create mode 100644 abc70930/src/bdd/parse/module.make create mode 100644 abc70930/src/bdd/parse/parse.h create mode 100644 abc70930/src/bdd/parse/parseCore.c create mode 100644 abc70930/src/bdd/parse/parseEqn.c create mode 100644 abc70930/src/bdd/parse/parseInt.h create mode 100644 abc70930/src/bdd/parse/parseStack.c create mode 100644 abc70930/src/bdd/reo/module.make create mode 100644 abc70930/src/bdd/reo/reo.h create mode 100644 abc70930/src/bdd/reo/reoApi.c create mode 100644 abc70930/src/bdd/reo/reoCore.c create mode 100644 abc70930/src/bdd/reo/reoProfile.c create mode 100644 abc70930/src/bdd/reo/reoSift.c create mode 100644 abc70930/src/bdd/reo/reoSwap.c create mode 100644 abc70930/src/bdd/reo/reoTest.c create mode 100644 abc70930/src/bdd/reo/reoTransfer.c create mode 100644 abc70930/src/bdd/reo/reoUnits.c create mode 100644 abc70930/src/generic.c create mode 100644 abc70930/src/generic.h create mode 100644 abc70930/src/map/fpga/fpga.c create mode 100644 abc70930/src/map/fpga/fpga.h create mode 100644 abc70930/src/map/fpga/fpgaCore.c create mode 100644 abc70930/src/map/fpga/fpgaCreate.c create mode 100644 abc70930/src/map/fpga/fpgaCut.c create mode 100644 abc70930/src/map/fpga/fpgaCutUtils.c create mode 100644 abc70930/src/map/fpga/fpgaFanout.c create mode 100644 abc70930/src/map/fpga/fpgaGENERIC.c create mode 100644 abc70930/src/map/fpga/fpgaInt.h create mode 100644 abc70930/src/map/fpga/fpgaLib.c create mode 100644 abc70930/src/map/fpga/fpgaMatch.c create mode 100644 abc70930/src/map/fpga/fpgaSwitch.c create mode 100644 abc70930/src/map/fpga/fpgaTime.c create mode 100644 abc70930/src/map/fpga/fpgaTruth.c create mode 100644 abc70930/src/map/fpga/fpgaUtils.c create mode 100644 abc70930/src/map/fpga/fpgaVec.c create mode 100644 abc70930/src/map/fpga/module.make create mode 100644 abc70930/src/map/if/if.h create mode 100644 abc70930/src/map/if/ifCore.c create mode 100644 abc70930/src/map/if/ifCut.c create mode 100644 abc70930/src/map/if/ifMan.c create mode 100644 abc70930/src/map/if/ifMap.c create mode 100644 abc70930/src/map/if/ifReduce.c create mode 100644 abc70930/src/map/if/ifSeq.c create mode 100644 abc70930/src/map/if/ifTime.c create mode 100644 abc70930/src/map/if/ifTruth.c create mode 100644 abc70930/src/map/if/ifUtil.c create mode 100644 abc70930/src/map/if/if_.c create mode 100644 abc70930/src/map/if/module.make create mode 100644 abc70930/src/map/mapper/mapper.c create mode 100644 abc70930/src/map/mapper/mapper.h create mode 100644 abc70930/src/map/mapper/mapperCanon.c create mode 100644 abc70930/src/map/mapper/mapperCore.c create mode 100644 abc70930/src/map/mapper/mapperCreate.c create mode 100644 abc70930/src/map/mapper/mapperCut.c create mode 100644 abc70930/src/map/mapper/mapperCutUtils.c create mode 100644 abc70930/src/map/mapper/mapperFanout.c create mode 100644 abc70930/src/map/mapper/mapperGENERIC.c create mode 100644 abc70930/src/map/mapper/mapperInt.h create mode 100644 abc70930/src/map/mapper/mapperLib.c create mode 100644 abc70930/src/map/mapper/mapperMatch.c create mode 100644 abc70930/src/map/mapper/mapperRefs.c create mode 100644 abc70930/src/map/mapper/mapperSuper.c create mode 100644 abc70930/src/map/mapper/mapperSwitch.c create mode 100644 abc70930/src/map/mapper/mapperTable.c create mode 100644 abc70930/src/map/mapper/mapperTime.c create mode 100644 abc70930/src/map/mapper/mapperTree.c create mode 100644 abc70930/src/map/mapper/mapperTruth.c create mode 100644 abc70930/src/map/mapper/mapperUtils.c create mode 100644 abc70930/src/map/mapper/mapperVec.c create mode 100644 abc70930/src/map/mapper/module.make create mode 100644 abc70930/src/map/mio/mio.c create mode 100644 abc70930/src/map/mio/mio.h create mode 100644 abc70930/src/map/mio/mioApi.c create mode 100644 abc70930/src/map/mio/mioFunc.c create mode 100644 abc70930/src/map/mio/mioGENERIC.c create mode 100644 abc70930/src/map/mio/mioInt.h create mode 100644 abc70930/src/map/mio/mioRead.c create mode 100644 abc70930/src/map/mio/mioUtils.c create mode 100644 abc70930/src/map/mio/module.make create mode 100644 abc70930/src/map/super/module.make create mode 100644 abc70930/src/map/super/super.c create mode 100644 abc70930/src/map/super/super.h create mode 100644 abc70930/src/map/super/superAnd.c create mode 100644 abc70930/src/map/super/superGENERIC.c create mode 100644 abc70930/src/map/super/superGate.c create mode 100644 abc70930/src/map/super/superInt.h create mode 100644 abc70930/src/map/super/superWrite.c create mode 100644 abc70930/src/misc/espresso/cofactor.c create mode 100644 abc70930/src/misc/espresso/cols.c create mode 100644 abc70930/src/misc/espresso/compl.c create mode 100644 abc70930/src/misc/espresso/contain.c create mode 100644 abc70930/src/misc/espresso/cubehack.c create mode 100644 abc70930/src/misc/espresso/cubestr.c create mode 100644 abc70930/src/misc/espresso/cvrin.c create mode 100644 abc70930/src/misc/espresso/cvrm.c create mode 100644 abc70930/src/misc/espresso/cvrmisc.c create mode 100644 abc70930/src/misc/espresso/cvrout.c create mode 100644 abc70930/src/misc/espresso/dominate.c create mode 100644 abc70930/src/misc/espresso/equiv.c create mode 100644 abc70930/src/misc/espresso/espresso.c create mode 100644 abc70930/src/misc/espresso/espresso.h create mode 100644 abc70930/src/misc/espresso/essen.c create mode 100644 abc70930/src/misc/espresso/exact.c create mode 100644 abc70930/src/misc/espresso/expand.c create mode 100644 abc70930/src/misc/espresso/gasp.c create mode 100644 abc70930/src/misc/espresso/gimpel.c create mode 100644 abc70930/src/misc/espresso/globals.c create mode 100644 abc70930/src/misc/espresso/hack.c create mode 100644 abc70930/src/misc/espresso/indep.c create mode 100644 abc70930/src/misc/espresso/irred.c create mode 100644 abc70930/src/misc/espresso/main.c create mode 100644 abc70930/src/misc/espresso/main.h create mode 100644 abc70930/src/misc/espresso/map.c create mode 100644 abc70930/src/misc/espresso/matrix.c create mode 100644 abc70930/src/misc/espresso/mincov.c create mode 100644 abc70930/src/misc/espresso/mincov.h create mode 100644 abc70930/src/misc/espresso/mincov_int.h create mode 100644 abc70930/src/misc/espresso/module.make create mode 100644 abc70930/src/misc/espresso/opo.c create mode 100644 abc70930/src/misc/espresso/pair.c create mode 100644 abc70930/src/misc/espresso/part.c create mode 100644 abc70930/src/misc/espresso/primes.c create mode 100644 abc70930/src/misc/espresso/reduce.c create mode 100644 abc70930/src/misc/espresso/rows.c create mode 100644 abc70930/src/misc/espresso/set.c create mode 100644 abc70930/src/misc/espresso/setc.c create mode 100644 abc70930/src/misc/espresso/sharp.c create mode 100644 abc70930/src/misc/espresso/sminterf.c create mode 100644 abc70930/src/misc/espresso/solution.c create mode 100644 abc70930/src/misc/espresso/sparse.c create mode 100644 abc70930/src/misc/espresso/sparse.h create mode 100644 abc70930/src/misc/espresso/sparse_int.h create mode 100644 abc70930/src/misc/espresso/unate.c create mode 100644 abc70930/src/misc/espresso/util_old.h create mode 100644 abc70930/src/misc/espresso/verify.c create mode 100644 abc70930/src/misc/extra/extra.h create mode 100644 abc70930/src/misc/extra/extraBddAuto.c create mode 100644 abc70930/src/misc/extra/extraBddCas.c create mode 100644 abc70930/src/misc/extra/extraBddKmap.c create mode 100644 abc70930/src/misc/extra/extraBddMisc.c create mode 100644 abc70930/src/misc/extra/extraBddSymm.c create mode 100644 abc70930/src/misc/extra/extraBddUnate.c create mode 100644 abc70930/src/misc/extra/extraUtilBitMatrix.c create mode 100644 abc70930/src/misc/extra/extraUtilCanon.c create mode 100644 abc70930/src/misc/extra/extraUtilFile.c create mode 100644 abc70930/src/misc/extra/extraUtilMemory.c create mode 100644 abc70930/src/misc/extra/extraUtilMisc.c create mode 100644 abc70930/src/misc/extra/extraUtilProgress.c create mode 100644 abc70930/src/misc/extra/extraUtilReader.c create mode 100644 abc70930/src/misc/extra/extraUtilTruth.c create mode 100644 abc70930/src/misc/extra/extraUtilUtil.c create mode 100644 abc70930/src/misc/extra/module.make create mode 100644 abc70930/src/misc/hash/hash.h create mode 100644 abc70930/src/misc/hash/hashFlt.h create mode 100644 abc70930/src/misc/hash/hashInt.h create mode 100644 abc70930/src/misc/hash/hashPtr.h create mode 100644 abc70930/src/misc/hash/module.make create mode 100644 abc70930/src/misc/mvc/module.make create mode 100644 abc70930/src/misc/mvc/mvc.c create mode 100644 abc70930/src/misc/mvc/mvc.h create mode 100644 abc70930/src/misc/mvc/mvcApi.c create mode 100644 abc70930/src/misc/mvc/mvcCompare.c create mode 100644 abc70930/src/misc/mvc/mvcContain.c create mode 100644 abc70930/src/misc/mvc/mvcCover.c create mode 100644 abc70930/src/misc/mvc/mvcCube.c create mode 100644 abc70930/src/misc/mvc/mvcDivide.c create mode 100644 abc70930/src/misc/mvc/mvcDivisor.c create mode 100644 abc70930/src/misc/mvc/mvcList.c create mode 100644 abc70930/src/misc/mvc/mvcLits.c create mode 100644 abc70930/src/misc/mvc/mvcMan.c create mode 100644 abc70930/src/misc/mvc/mvcOpAlg.c create mode 100644 abc70930/src/misc/mvc/mvcOpBool.c create mode 100644 abc70930/src/misc/mvc/mvcPrint.c create mode 100644 abc70930/src/misc/mvc/mvcSort.c create mode 100644 abc70930/src/misc/mvc/mvcUtils.c create mode 100644 abc70930/src/misc/nm/module.make create mode 100644 abc70930/src/misc/nm/nm.h create mode 100644 abc70930/src/misc/nm/nmApi.c create mode 100644 abc70930/src/misc/nm/nmInt.h create mode 100644 abc70930/src/misc/nm/nmTable.c create mode 100644 abc70930/src/misc/st/module.make create mode 100644 abc70930/src/misc/st/st.c create mode 100644 abc70930/src/misc/st/st.h create mode 100644 abc70930/src/misc/st/stmm.c create mode 100644 abc70930/src/misc/st/stmm.h create mode 100644 abc70930/src/misc/util/leaks.h create mode 100644 abc70930/src/misc/util/module.make create mode 100644 abc70930/src/misc/util/stdlib_hack.h create mode 100644 abc70930/src/misc/util/util_hack.h create mode 100644 abc70930/src/misc/vec/module.make create mode 100644 abc70930/src/misc/vec/vec.h create mode 100644 abc70930/src/misc/vec/vecAtt.h create mode 100644 abc70930/src/misc/vec/vecFlt.h create mode 100644 abc70930/src/misc/vec/vecInt.h create mode 100644 abc70930/src/misc/vec/vecPtr.h create mode 100644 abc70930/src/misc/vec/vecStr.h create mode 100644 abc70930/src/misc/vec/vecVec.h create mode 100644 abc70930/src/opt/cut/abcCut.c create mode 100644 abc70930/src/opt/cut/cut.h create mode 100644 abc70930/src/opt/cut/cutApi.c create mode 100644 abc70930/src/opt/cut/cutCut.c create mode 100644 abc70930/src/opt/cut/cutExpand.c create mode 100644 abc70930/src/opt/cut/cutInt.h create mode 100644 abc70930/src/opt/cut/cutList.h create mode 100644 abc70930/src/opt/cut/cutMan.c create mode 100644 abc70930/src/opt/cut/cutMerge.c create mode 100644 abc70930/src/opt/cut/cutNode.c create mode 100644 abc70930/src/opt/cut/cutOracle.c create mode 100644 abc70930/src/opt/cut/cutPre22.c create mode 100644 abc70930/src/opt/cut/cutSeq.c create mode 100644 abc70930/src/opt/cut/cutTruth.c create mode 100644 abc70930/src/opt/cut/module.make create mode 100644 abc70930/src/opt/dec/dec.h create mode 100644 abc70930/src/opt/dec/decAbc.c create mode 100644 abc70930/src/opt/dec/decFactor.c create mode 100644 abc70930/src/opt/dec/decMan.c create mode 100644 abc70930/src/opt/dec/decPrint.c create mode 100644 abc70930/src/opt/dec/decUtil.c create mode 100644 abc70930/src/opt/dec/module.make create mode 100644 abc70930/src/opt/fxu/fxu.c create mode 100644 abc70930/src/opt/fxu/fxu.h create mode 100644 abc70930/src/opt/fxu/fxuCreate.c create mode 100644 abc70930/src/opt/fxu/fxuHeapD.c create mode 100644 abc70930/src/opt/fxu/fxuHeapS.c create mode 100644 abc70930/src/opt/fxu/fxuInt.h create mode 100644 abc70930/src/opt/fxu/fxuList.c create mode 100644 abc70930/src/opt/fxu/fxuMatrix.c create mode 100644 abc70930/src/opt/fxu/fxuPair.c create mode 100644 abc70930/src/opt/fxu/fxuPrint.c create mode 100644 abc70930/src/opt/fxu/fxuReduce.c create mode 100644 abc70930/src/opt/fxu/fxuSelect.c create mode 100644 abc70930/src/opt/fxu/fxuSingle.c create mode 100644 abc70930/src/opt/fxu/fxuUpdate.c create mode 100644 abc70930/src/opt/fxu/module.make create mode 100644 abc70930/src/opt/lpk/lpk.h create mode 100644 abc70930/src/opt/lpk/lpkAbcDec.c create mode 100644 abc70930/src/opt/lpk/lpkAbcDsd.c create mode 100644 abc70930/src/opt/lpk/lpkAbcMux.c create mode 100644 abc70930/src/opt/lpk/lpkAbcUtil.c create mode 100644 abc70930/src/opt/lpk/lpkCore.c create mode 100644 abc70930/src/opt/lpk/lpkCut.c create mode 100644 abc70930/src/opt/lpk/lpkInt.h create mode 100644 abc70930/src/opt/lpk/lpkMan.c create mode 100644 abc70930/src/opt/lpk/lpkMap.c create mode 100644 abc70930/src/opt/lpk/lpkMulti.c create mode 100644 abc70930/src/opt/lpk/lpkMux.c create mode 100644 abc70930/src/opt/lpk/lpkSets.c create mode 100644 abc70930/src/opt/lpk/lpk_.c create mode 100644 abc70930/src/opt/lpk/module.make create mode 100644 abc70930/src/opt/res/module.make create mode 100644 abc70930/src/opt/res/res.h create mode 100644 abc70930/src/opt/res/resCore.c create mode 100644 abc70930/src/opt/res/resDivs.c create mode 100644 abc70930/src/opt/res/resFilter.c create mode 100644 abc70930/src/opt/res/resInt.h create mode 100644 abc70930/src/opt/res/resSat.c create mode 100644 abc70930/src/opt/res/resSim.c create mode 100644 abc70930/src/opt/res/resSim_old.c create mode 100644 abc70930/src/opt/res/resStrash.c create mode 100644 abc70930/src/opt/res/resWin.c create mode 100644 abc70930/src/opt/res/res_.c create mode 100644 abc70930/src/opt/ret/module.make create mode 100644 abc70930/src/opt/ret/retArea.c create mode 100644 abc70930/src/opt/ret/retCore.c create mode 100644 abc70930/src/opt/ret/retDelay.c create mode 100644 abc70930/src/opt/ret/retFlow.c create mode 100644 abc70930/src/opt/ret/retIncrem.c create mode 100644 abc70930/src/opt/ret/retInit.c create mode 100644 abc70930/src/opt/ret/retInt.h create mode 100644 abc70930/src/opt/ret/retLvalue.c create mode 100644 abc70930/src/opt/ret/ret_.c create mode 100644 abc70930/src/opt/rwr/module.make create mode 100644 abc70930/src/opt/rwr/rwr.h create mode 100644 abc70930/src/opt/rwr/rwrDec.c create mode 100644 abc70930/src/opt/rwr/rwrEva.c create mode 100644 abc70930/src/opt/rwr/rwrExp.c create mode 100644 abc70930/src/opt/rwr/rwrLib.c create mode 100644 abc70930/src/opt/rwr/rwrMan.c create mode 100644 abc70930/src/opt/rwr/rwrPrint.c create mode 100644 abc70930/src/opt/rwr/rwrTemp.c create mode 100644 abc70930/src/opt/rwr/rwrUtil.c create mode 100644 abc70930/src/opt/sim/module.make create mode 100644 abc70930/src/opt/sim/sim.h create mode 100644 abc70930/src/opt/sim/simMan.c create mode 100644 abc70930/src/opt/sim/simSat.c create mode 100644 abc70930/src/opt/sim/simSeq.c create mode 100644 abc70930/src/opt/sim/simSupp.c create mode 100644 abc70930/src/opt/sim/simSwitch.c create mode 100644 abc70930/src/opt/sim/simSym.c create mode 100644 abc70930/src/opt/sim/simSymSat.c create mode 100644 abc70930/src/opt/sim/simSymSim.c create mode 100644 abc70930/src/opt/sim/simSymStr.c create mode 100644 abc70930/src/opt/sim/simUtils.c create mode 100644 abc70930/src/sat/bsat/module.make create mode 100644 abc70930/src/sat/bsat/satInter.c create mode 100644 abc70930/src/sat/bsat/satMem.c create mode 100644 abc70930/src/sat/bsat/satMem.h create mode 100644 abc70930/src/sat/bsat/satSolver.c create mode 100644 abc70930/src/sat/bsat/satSolver.h create mode 100644 abc70930/src/sat/bsat/satStore.c create mode 100644 abc70930/src/sat/bsat/satStore.h create mode 100644 abc70930/src/sat/bsat/satTrace.c create mode 100644 abc70930/src/sat/bsat/satUtil.c create mode 100644 abc70930/src/sat/bsat/satVec.h create mode 100644 abc70930/src/sat/csat/csat_apis.c create mode 100644 abc70930/src/sat/csat/csat_apis.h create mode 100644 abc70930/src/sat/csat/module.make create mode 100644 abc70930/src/sat/fraig/fraig.h create mode 100644 abc70930/src/sat/fraig/fraigApi.c create mode 100644 abc70930/src/sat/fraig/fraigCanon.c create mode 100644 abc70930/src/sat/fraig/fraigChoice.c create mode 100644 abc70930/src/sat/fraig/fraigFanout.c create mode 100644 abc70930/src/sat/fraig/fraigFeed.c create mode 100644 abc70930/src/sat/fraig/fraigInt.h create mode 100644 abc70930/src/sat/fraig/fraigMan.c create mode 100644 abc70930/src/sat/fraig/fraigMem.c create mode 100644 abc70930/src/sat/fraig/fraigNode.c create mode 100644 abc70930/src/sat/fraig/fraigPrime.c create mode 100644 abc70930/src/sat/fraig/fraigSat.c create mode 100644 abc70930/src/sat/fraig/fraigTable.c create mode 100644 abc70930/src/sat/fraig/fraigUtil.c create mode 100644 abc70930/src/sat/fraig/fraigVec.c create mode 100644 abc70930/src/sat/fraig/module.make create mode 100644 abc70930/src/sat/msat/module.make create mode 100644 abc70930/src/sat/msat/msat.h create mode 100644 abc70930/src/sat/msat/msatActivity.c create mode 100644 abc70930/src/sat/msat/msatClause.c create mode 100644 abc70930/src/sat/msat/msatClauseVec.c create mode 100644 abc70930/src/sat/msat/msatInt.h create mode 100644 abc70930/src/sat/msat/msatMem.c create mode 100644 abc70930/src/sat/msat/msatOrderH.c create mode 100644 abc70930/src/sat/msat/msatOrderJ.c create mode 100644 abc70930/src/sat/msat/msatQueue.c create mode 100644 abc70930/src/sat/msat/msatRead.c create mode 100644 abc70930/src/sat/msat/msatSolverApi.c create mode 100644 abc70930/src/sat/msat/msatSolverCore.c create mode 100644 abc70930/src/sat/msat/msatSolverIo.c create mode 100644 abc70930/src/sat/msat/msatSolverSearch.c create mode 100644 abc70930/src/sat/msat/msatSort.c create mode 100644 abc70930/src/sat/msat/msatVec.c create mode 100644 abc70930/src/sat/proof/pr.c create mode 100644 abc70930/src/sat/proof/pr.h create mode 100644 abc70930/src/sat/proof/stats.txt delete mode 100644 abclib.dsp delete mode 100644 abclib.dsw delete mode 100644 abctestlib.dsp delete mode 100644 abctestlib.dsw delete mode 100644 copyright.txt delete mode 100644 demo.c delete mode 100755 depends.sh delete mode 100644 readme delete mode 100644 regtest.script delete mode 100644 regtest_output.txt delete mode 100644 src/aig/aig/aig.h delete mode 100644 src/aig/aig/aigCheck.c delete mode 100644 src/aig/aig/aigDfs.c delete mode 100644 src/aig/aig/aigFanout.c delete mode 100644 src/aig/aig/aigMan.c delete mode 100644 src/aig/aig/aigMem.c delete mode 100644 src/aig/aig/aigMffc.c delete mode 100644 src/aig/aig/aigObj.c delete mode 100644 src/aig/aig/aigOper.c delete mode 100644 src/aig/aig/aigOrder.c delete mode 100644 src/aig/aig/aigPart.c delete mode 100644 src/aig/aig/aigRepr.c delete mode 100644 src/aig/aig/aigRet.c delete mode 100644 src/aig/aig/aigScl.c delete mode 100644 src/aig/aig/aigSeq.c delete mode 100644 src/aig/aig/aigShow.c delete mode 100644 src/aig/aig/aigTable.c delete mode 100644 src/aig/aig/aigTime.c delete mode 100644 src/aig/aig/aigTiming.c delete mode 100644 src/aig/aig/aigTruth.c delete mode 100644 src/aig/aig/aigTsim.c delete mode 100644 src/aig/aig/aigUtil.c delete mode 100644 src/aig/aig/aigWin.c delete mode 100644 src/aig/aig/aig_.c delete mode 100644 src/aig/aig/module.make delete mode 100644 src/aig/bar/bar.c delete mode 100644 src/aig/bar/bar.h delete mode 100644 src/aig/bar/module.make delete mode 100644 src/aig/bdc/bdc.h delete mode 100644 src/aig/bdc/bdcCore.c delete mode 100644 src/aig/bdc/bdcDec.c delete mode 100644 src/aig/bdc/bdcInt.h delete mode 100644 src/aig/bdc/bdcTable.c delete mode 100644 src/aig/bdc/bdc_.c delete mode 100644 src/aig/bdc/module.make delete mode 100644 src/aig/cnf/cnf.h delete mode 100644 src/aig/cnf/cnfCore.c delete mode 100644 src/aig/cnf/cnfCut.c delete mode 100644 src/aig/cnf/cnfData.c delete mode 100644 src/aig/cnf/cnfMan.c delete mode 100644 src/aig/cnf/cnfMap.c delete mode 100644 src/aig/cnf/cnfPost.c delete mode 100644 src/aig/cnf/cnfUtil.c delete mode 100644 src/aig/cnf/cnfWrite.c delete mode 100644 src/aig/cnf/cnf_.c delete mode 100644 src/aig/cnf/module.make delete mode 100644 src/aig/csw/csw.h delete mode 100644 src/aig/csw/cswCore.c delete mode 100644 src/aig/csw/cswCut.c delete mode 100644 src/aig/csw/cswInt.h delete mode 100644 src/aig/csw/cswMan.c delete mode 100644 src/aig/csw/cswTable.c delete mode 100644 src/aig/csw/csw_.c delete mode 100644 src/aig/csw/module.make delete mode 100644 src/aig/dar/dar.h delete mode 100644 src/aig/dar/darBalance.c delete mode 100644 src/aig/dar/darCore.c delete mode 100644 src/aig/dar/darCut.c delete mode 100644 src/aig/dar/darData.c delete mode 100644 src/aig/dar/darInt.h delete mode 100644 src/aig/dar/darLib.c delete mode 100644 src/aig/dar/darMan.c delete mode 100644 src/aig/dar/darPrec.c delete mode 100644 src/aig/dar/darRefact.c delete mode 100644 src/aig/dar/darResub.c delete mode 100644 src/aig/dar/darScript.c delete mode 100644 src/aig/dar/darTruth.c delete mode 100644 src/aig/dar/dar_.c delete mode 100644 src/aig/dar/module.make delete mode 100644 src/aig/deco/deco.h delete mode 100644 src/aig/deco/module.make delete mode 100644 src/aig/fra/fra.h delete mode 100644 src/aig/fra/fraBmc.c delete mode 100644 src/aig/fra/fraCec.c delete mode 100644 src/aig/fra/fraClass.c delete mode 100644 src/aig/fra/fraCnf.c delete mode 100644 src/aig/fra/fraCore.c delete mode 100644 src/aig/fra/fraImp.c delete mode 100644 src/aig/fra/fraInd.c delete mode 100644 src/aig/fra/fraLcr.c delete mode 100644 src/aig/fra/fraMan.c delete mode 100644 src/aig/fra/fraPart.c delete mode 100644 src/aig/fra/fraSat.c delete mode 100644 src/aig/fra/fraSec.c delete mode 100644 src/aig/fra/fraSim.c delete mode 100644 src/aig/fra/fra_.c delete mode 100644 src/aig/fra/module.make delete mode 100644 src/aig/hop/cudd2.c delete mode 100644 src/aig/hop/cudd2.h delete mode 100644 src/aig/hop/hop.h delete mode 100644 src/aig/hop/hopBalance.c delete mode 100644 src/aig/hop/hopCheck.c delete mode 100644 src/aig/hop/hopDfs.c delete mode 100644 src/aig/hop/hopMan.c delete mode 100644 src/aig/hop/hopMem.c delete mode 100644 src/aig/hop/hopObj.c delete mode 100644 src/aig/hop/hopOper.c delete mode 100644 src/aig/hop/hopTable.c delete mode 100644 src/aig/hop/hopUtil.c delete mode 100644 src/aig/hop/hop_.c delete mode 100644 src/aig/hop/module.make delete mode 100644 src/aig/ioa/ioa.h delete mode 100644 src/aig/ioa/ioaReadAig.c delete mode 100644 src/aig/ioa/ioaUtil.c delete mode 100644 src/aig/ioa/ioaWriteAig.c delete mode 100644 src/aig/ioa/module.make delete mode 100644 src/aig/ivy/attr.h delete mode 100644 src/aig/ivy/ivy.h delete mode 100644 src/aig/ivy/ivyBalance.c delete mode 100644 src/aig/ivy/ivyCanon.c delete mode 100644 src/aig/ivy/ivyCheck.c delete mode 100644 src/aig/ivy/ivyCut.c delete mode 100644 src/aig/ivy/ivyCutTrav.c delete mode 100644 src/aig/ivy/ivyDfs.c delete mode 100644 src/aig/ivy/ivyDsd.c delete mode 100644 src/aig/ivy/ivyFanout.c delete mode 100644 src/aig/ivy/ivyFastMap.c delete mode 100644 src/aig/ivy/ivyFraig.c delete mode 100644 src/aig/ivy/ivyHaig.c delete mode 100644 src/aig/ivy/ivyMan.c delete mode 100644 src/aig/ivy/ivyMem.c delete mode 100644 src/aig/ivy/ivyMulti.c delete mode 100644 src/aig/ivy/ivyMulti8.c delete mode 100644 src/aig/ivy/ivyObj.c delete mode 100644 src/aig/ivy/ivyOper.c delete mode 100644 src/aig/ivy/ivyResyn.c delete mode 100644 src/aig/ivy/ivyRwr.c delete mode 100644 src/aig/ivy/ivyRwrAlg.c delete mode 100644 src/aig/ivy/ivySeq.c delete mode 100644 src/aig/ivy/ivyShow.c delete mode 100644 src/aig/ivy/ivyTable.c delete mode 100644 src/aig/ivy/ivyUtil.c delete mode 100644 src/aig/ivy/ivy_.c delete mode 100644 src/aig/ivy/module.make delete mode 100644 src/aig/kit/cloud.c delete mode 100644 src/aig/kit/cloud.h delete mode 100644 src/aig/kit/kit.h delete mode 100644 src/aig/kit/kitAig.c delete mode 100644 src/aig/kit/kitBdd.c delete mode 100644 src/aig/kit/kitCloud.c delete mode 100644 src/aig/kit/kitDsd.c delete mode 100644 src/aig/kit/kitFactor.c delete mode 100644 src/aig/kit/kitGraph.c delete mode 100644 src/aig/kit/kitHop.c delete mode 100644 src/aig/kit/kitIsop.c delete mode 100644 src/aig/kit/kitSop.c delete mode 100644 src/aig/kit/kitTruth.c delete mode 100644 src/aig/kit/kit_.c delete mode 100644 src/aig/kit/module.make delete mode 100644 src/aig/mem/mem.c delete mode 100644 src/aig/mem/mem.h delete mode 100644 src/aig/mem/module.make delete mode 100644 src/aig/rwt/module.make delete mode 100644 src/aig/rwt/rwt.h delete mode 100644 src/aig/rwt/rwtDec.c delete mode 100644 src/aig/rwt/rwtMan.c delete mode 100644 src/aig/rwt/rwtUtil.c delete mode 100644 src/base/abc/abc.h delete mode 100644 src/base/abc/abcAig.c delete mode 100644 src/base/abc/abcBlifMv.c delete mode 100644 src/base/abc/abcCheck.c delete mode 100644 src/base/abc/abcDfs.c delete mode 100644 src/base/abc/abcFanio.c delete mode 100644 src/base/abc/abcFunc.c delete mode 100644 src/base/abc/abcHie.c delete mode 100644 src/base/abc/abcInt.h delete mode 100644 src/base/abc/abcLatch.c delete mode 100644 src/base/abc/abcLib.c delete mode 100644 src/base/abc/abcMinBase.c delete mode 100644 src/base/abc/abcNames.c delete mode 100644 src/base/abc/abcNetlist.c delete mode 100644 src/base/abc/abcNtk.c delete mode 100644 src/base/abc/abcObj.c delete mode 100644 src/base/abc/abcRefs.c delete mode 100644 src/base/abc/abcShow.c delete mode 100644 src/base/abc/abcSop.c delete mode 100644 src/base/abc/abcUtil.c delete mode 100644 src/base/abc/abc_.c delete mode 100644 src/base/abc/module.make delete mode 100644 src/base/abci/abc.c delete mode 100644 src/base/abci/abcAttach.c delete mode 100644 src/base/abci/abcAuto.c delete mode 100644 src/base/abci/abcBalance.c delete mode 100644 src/base/abci/abcBmc.c delete mode 100644 src/base/abci/abcCas.c delete mode 100644 src/base/abci/abcClpBdd.c delete mode 100644 src/base/abci/abcClpSop.c delete mode 100644 src/base/abci/abcCut.c delete mode 100644 src/base/abci/abcDar.c delete mode 100644 src/base/abci/abcDebug.c delete mode 100644 src/base/abci/abcDress.c delete mode 100644 src/base/abci/abcDsd.c delete mode 100644 src/base/abci/abcEspresso.c delete mode 100644 src/base/abci/abcExtract.c delete mode 100644 src/base/abci/abcFpga.c delete mode 100644 src/base/abci/abcFpgaFast.c delete mode 100644 src/base/abci/abcFraig.c delete mode 100644 src/base/abci/abcFxu.c delete mode 100644 src/base/abci/abcGen.c delete mode 100644 src/base/abci/abcHaig.c delete mode 100644 src/base/abci/abcIf.c delete mode 100644 src/base/abci/abcIvy.c delete mode 100644 src/base/abci/abcLut.c delete mode 100644 src/base/abci/abcMap.c delete mode 100644 src/base/abci/abcMeasure.c delete mode 100644 src/base/abci/abcMini.c delete mode 100644 src/base/abci/abcMiter.c delete mode 100644 src/base/abci/abcMulti.c delete mode 100644 src/base/abci/abcMv.c delete mode 100644 src/base/abci/abcNtbdd.c delete mode 100644 src/base/abci/abcOdc.c delete mode 100644 src/base/abci/abcOrder.c delete mode 100644 src/base/abci/abcPart.c delete mode 100644 src/base/abci/abcPlace.c delete mode 100644 src/base/abci/abcPrint.c delete mode 100644 src/base/abci/abcProve.c delete mode 100644 src/base/abci/abcQbf.c delete mode 100644 src/base/abci/abcQuant.c delete mode 100644 src/base/abci/abcRec.c delete mode 100644 src/base/abci/abcReconv.c delete mode 100644 src/base/abci/abcRefactor.c delete mode 100644 src/base/abci/abcRenode.c delete mode 100644 src/base/abci/abcReorder.c delete mode 100644 src/base/abci/abcRestruct.c delete mode 100644 src/base/abci/abcResub.c delete mode 100644 src/base/abci/abcRewrite.c delete mode 100644 src/base/abci/abcRr.c delete mode 100644 src/base/abci/abcSat.c delete mode 100644 src/base/abci/abcStrash.c delete mode 100644 src/base/abci/abcSweep.c delete mode 100644 src/base/abci/abcSymm.c delete mode 100644 src/base/abci/abcTiming.c delete mode 100644 src/base/abci/abcUnate.c delete mode 100644 src/base/abci/abcUnreach.c delete mode 100644 src/base/abci/abcVerify.c delete mode 100644 src/base/abci/abcXsim.c delete mode 100644 src/base/abci/abc_.c delete mode 100644 src/base/abci/abc_new.h delete mode 100644 src/base/abci/module.make delete mode 100644 src/base/cmd/cmd.c delete mode 100644 src/base/cmd/cmd.h delete mode 100644 src/base/cmd/cmdAlias.c delete mode 100644 src/base/cmd/cmdApi.c delete mode 100644 src/base/cmd/cmdFlag.c delete mode 100644 src/base/cmd/cmdHist.c delete mode 100644 src/base/cmd/cmdInt.h delete mode 100644 src/base/cmd/cmdUtils.c delete mode 100644 src/base/cmd/module.make delete mode 100644 src/base/func/funcBlifMv.c delete mode 100644 src/base/io/io.c delete mode 100644 src/base/io/io.h delete mode 100644 src/base/io/ioInt.h delete mode 100644 src/base/io/ioReadAiger.c delete mode 100644 src/base/io/ioReadBaf.c delete mode 100644 src/base/io/ioReadBench.c delete mode 100644 src/base/io/ioReadBlif.c delete mode 100644 src/base/io/ioReadBlifAig.c delete mode 100644 src/base/io/ioReadBlifMv.c delete mode 100644 src/base/io/ioReadDsd.c delete mode 100644 src/base/io/ioReadEdif.c delete mode 100644 src/base/io/ioReadEqn.c delete mode 100644 src/base/io/ioReadPla.c delete mode 100644 src/base/io/ioReadVerilog.c delete mode 100644 src/base/io/ioUtil.c delete mode 100644 src/base/io/ioWriteAiger.c delete mode 100644 src/base/io/ioWriteBaf.c delete mode 100644 src/base/io/ioWriteBench.c delete mode 100644 src/base/io/ioWriteBlif.c delete mode 100644 src/base/io/ioWriteBlifMv.c delete mode 100644 src/base/io/ioWriteCnf.c delete mode 100644 src/base/io/ioWriteDot.c delete mode 100644 src/base/io/ioWriteEqn.c delete mode 100644 src/base/io/ioWriteGml.c delete mode 100644 src/base/io/ioWriteList.c delete mode 100644 src/base/io/ioWritePla.c delete mode 100644 src/base/io/ioWriteVerilog.c delete mode 100644 src/base/io/ioWriteVerilog.zip delete mode 100644 src/base/io/io_.c delete mode 100644 src/base/io/module.make delete mode 100644 src/base/main/libSupport.c delete mode 100644 src/base/main/main.c delete mode 100644 src/base/main/main.h delete mode 100644 src/base/main/mainFrame.c delete mode 100644 src/base/main/mainInit.c delete mode 100644 src/base/main/mainInt.h delete mode 100644 src/base/main/mainUtils.c delete mode 100644 src/base/main/module.make delete mode 100644 src/base/seq/module.make delete mode 100644 src/base/seq/seq.h delete mode 100644 src/base/seq/seqAigCore.c delete mode 100644 src/base/seq/seqAigIter.c delete mode 100644 src/base/seq/seqCreate.c delete mode 100644 src/base/seq/seqFpgaCore.c delete mode 100644 src/base/seq/seqFpgaIter.c delete mode 100644 src/base/seq/seqInt.h delete mode 100644 src/base/seq/seqLatch.c delete mode 100644 src/base/seq/seqMan.c delete mode 100644 src/base/seq/seqMapCore.c delete mode 100644 src/base/seq/seqMapIter.c delete mode 100644 src/base/seq/seqMaxMeanCycle.c delete mode 100644 src/base/seq/seqRetCore.c delete mode 100644 src/base/seq/seqRetIter.c delete mode 100644 src/base/seq/seqShare.c delete mode 100644 src/base/seq/seqUtil.c delete mode 100644 src/base/temp.c delete mode 100644 src/base/ver/module.make delete mode 100644 src/base/ver/ver.h delete mode 100644 src/base/ver/verCore.c delete mode 100644 src/base/ver/verCore.zip delete mode 100644 src/base/ver/verFormula.c delete mode 100644 src/base/ver/verParse.c delete mode 100644 src/base/ver/verStream.c delete mode 100644 src/base/ver/verWords.c delete mode 100644 src/base/ver/ver_.c delete mode 100644 src/bdd/cas/cas.h delete mode 100644 src/bdd/cas/casCore.c delete mode 100644 src/bdd/cas/casDec.c delete mode 100644 src/bdd/cas/module.make delete mode 100644 src/bdd/cudd/cuBdd.make delete mode 100644 src/bdd/cudd/cudd.h delete mode 100644 src/bdd/cudd/cudd.make delete mode 100644 src/bdd/cudd/cuddAPI.c delete mode 100644 src/bdd/cudd/cuddAddAbs.c delete mode 100644 src/bdd/cudd/cuddAddApply.c delete mode 100644 src/bdd/cudd/cuddAddFind.c delete mode 100644 src/bdd/cudd/cuddAddInv.c delete mode 100644 src/bdd/cudd/cuddAddIte.c delete mode 100644 src/bdd/cudd/cuddAddNeg.c delete mode 100644 src/bdd/cudd/cuddAddWalsh.c delete mode 100644 src/bdd/cudd/cuddAndAbs.c delete mode 100644 src/bdd/cudd/cuddAnneal.c delete mode 100644 src/bdd/cudd/cuddApa.c delete mode 100644 src/bdd/cudd/cuddApprox.c delete mode 100644 src/bdd/cudd/cuddBddAbs.c delete mode 100644 src/bdd/cudd/cuddBddCorr.c delete mode 100644 src/bdd/cudd/cuddBddIte.c delete mode 100644 src/bdd/cudd/cuddBridge.c delete mode 100644 src/bdd/cudd/cuddCache.c delete mode 100644 src/bdd/cudd/cuddCheck.c delete mode 100644 src/bdd/cudd/cuddClip.c delete mode 100644 src/bdd/cudd/cuddCof.c delete mode 100644 src/bdd/cudd/cuddCompose.c delete mode 100644 src/bdd/cudd/cuddDecomp.c delete mode 100644 src/bdd/cudd/cuddEssent.c delete mode 100644 src/bdd/cudd/cuddExact.c delete mode 100644 src/bdd/cudd/cuddExport.c delete mode 100644 src/bdd/cudd/cuddGenCof.c delete mode 100644 src/bdd/cudd/cuddGenetic.c delete mode 100644 src/bdd/cudd/cuddGroup.c delete mode 100644 src/bdd/cudd/cuddHarwell.c delete mode 100644 src/bdd/cudd/cuddInit.c delete mode 100644 src/bdd/cudd/cuddInt.h delete mode 100644 src/bdd/cudd/cuddInteract.c delete mode 100644 src/bdd/cudd/cuddLCache.c delete mode 100644 src/bdd/cudd/cuddLevelQ.c delete mode 100644 src/bdd/cudd/cuddLinear.c delete mode 100644 src/bdd/cudd/cuddLiteral.c delete mode 100644 src/bdd/cudd/cuddMatMult.c delete mode 100644 src/bdd/cudd/cuddPriority.c delete mode 100644 src/bdd/cudd/cuddRead.c delete mode 100644 src/bdd/cudd/cuddRef.c delete mode 100644 src/bdd/cudd/cuddReorder.c delete mode 100644 src/bdd/cudd/cuddSat.c delete mode 100644 src/bdd/cudd/cuddSign.c delete mode 100644 src/bdd/cudd/cuddSolve.c delete mode 100644 src/bdd/cudd/cuddSplit.c delete mode 100644 src/bdd/cudd/cuddSubsetHB.c delete mode 100644 src/bdd/cudd/cuddSubsetSP.c delete mode 100644 src/bdd/cudd/cuddSymmetry.c delete mode 100644 src/bdd/cudd/cuddTable.c delete mode 100644 src/bdd/cudd/cuddUtil.c delete mode 100644 src/bdd/cudd/cuddWindow.c delete mode 100644 src/bdd/cudd/cuddZddCount.c delete mode 100644 src/bdd/cudd/cuddZddFuncs.c delete mode 100644 src/bdd/cudd/cuddZddGroup.c delete mode 100644 src/bdd/cudd/cuddZddIsop.c delete mode 100644 src/bdd/cudd/cuddZddLin.c delete mode 100644 src/bdd/cudd/cuddZddMisc.c delete mode 100644 src/bdd/cudd/cuddZddPort.c delete mode 100644 src/bdd/cudd/cuddZddReord.c delete mode 100644 src/bdd/cudd/cuddZddSetop.c delete mode 100644 src/bdd/cudd/cuddZddSymm.c delete mode 100644 src/bdd/cudd/cuddZddUtil.c delete mode 100644 src/bdd/cudd/module.make delete mode 100644 src/bdd/cudd/r7x8.1.mat delete mode 100644 src/bdd/cudd/testcudd.c delete mode 100644 src/bdd/dsd/dsd.h delete mode 100644 src/bdd/dsd/dsdApi.c delete mode 100644 src/bdd/dsd/dsdCheck.c delete mode 100644 src/bdd/dsd/dsdInt.h delete mode 100644 src/bdd/dsd/dsdLocal.c delete mode 100644 src/bdd/dsd/dsdMan.c delete mode 100644 src/bdd/dsd/dsdProc.c delete mode 100644 src/bdd/dsd/dsdTree.c delete mode 100644 src/bdd/dsd/module.make delete mode 100644 src/bdd/epd/epd.c delete mode 100644 src/bdd/epd/epd.h delete mode 100644 src/bdd/epd/module.make delete mode 100644 src/bdd/mtr/module.make delete mode 100644 src/bdd/mtr/mtr.h delete mode 100644 src/bdd/mtr/mtrBasic.c delete mode 100644 src/bdd/mtr/mtrGroup.c delete mode 100644 src/bdd/mtr/mtrInt.h delete mode 100644 src/bdd/parse/module.make delete mode 100644 src/bdd/parse/parse.h delete mode 100644 src/bdd/parse/parseCore.c delete mode 100644 src/bdd/parse/parseEqn.c delete mode 100644 src/bdd/parse/parseInt.h delete mode 100644 src/bdd/parse/parseStack.c delete mode 100644 src/bdd/reo/module.make delete mode 100644 src/bdd/reo/reo.h delete mode 100644 src/bdd/reo/reoApi.c delete mode 100644 src/bdd/reo/reoCore.c delete mode 100644 src/bdd/reo/reoProfile.c delete mode 100644 src/bdd/reo/reoSift.c delete mode 100644 src/bdd/reo/reoSwap.c delete mode 100644 src/bdd/reo/reoTest.c delete mode 100644 src/bdd/reo/reoTransfer.c delete mode 100644 src/bdd/reo/reoUnits.c delete mode 100644 src/generic.c delete mode 100644 src/generic.h delete mode 100644 src/map/fpga/fpga.c delete mode 100644 src/map/fpga/fpga.h delete mode 100644 src/map/fpga/fpgaCore.c delete mode 100644 src/map/fpga/fpgaCreate.c delete mode 100644 src/map/fpga/fpgaCut.c delete mode 100644 src/map/fpga/fpgaCutUtils.c delete mode 100644 src/map/fpga/fpgaFanout.c delete mode 100644 src/map/fpga/fpgaGENERIC.c delete mode 100644 src/map/fpga/fpgaInt.h delete mode 100644 src/map/fpga/fpgaLib.c delete mode 100644 src/map/fpga/fpgaMatch.c delete mode 100644 src/map/fpga/fpgaSwitch.c delete mode 100644 src/map/fpga/fpgaTime.c delete mode 100644 src/map/fpga/fpgaTruth.c delete mode 100644 src/map/fpga/fpgaUtils.c delete mode 100644 src/map/fpga/fpgaVec.c delete mode 100644 src/map/fpga/module.make delete mode 100644 src/map/if/if.h delete mode 100644 src/map/if/ifCore.c delete mode 100644 src/map/if/ifCut.c delete mode 100644 src/map/if/ifMan.c delete mode 100644 src/map/if/ifMap.c delete mode 100644 src/map/if/ifReduce.c delete mode 100644 src/map/if/ifSeq.c delete mode 100644 src/map/if/ifTime.c delete mode 100644 src/map/if/ifTruth.c delete mode 100644 src/map/if/ifUtil.c delete mode 100644 src/map/if/if_.c delete mode 100644 src/map/if/module.make delete mode 100644 src/map/mapper/mapper.c delete mode 100644 src/map/mapper/mapper.h delete mode 100644 src/map/mapper/mapperCanon.c delete mode 100644 src/map/mapper/mapperCore.c delete mode 100644 src/map/mapper/mapperCreate.c delete mode 100644 src/map/mapper/mapperCut.c delete mode 100644 src/map/mapper/mapperCutUtils.c delete mode 100644 src/map/mapper/mapperFanout.c delete mode 100644 src/map/mapper/mapperGENERIC.c delete mode 100644 src/map/mapper/mapperInt.h delete mode 100644 src/map/mapper/mapperLib.c delete mode 100644 src/map/mapper/mapperMatch.c delete mode 100644 src/map/mapper/mapperRefs.c delete mode 100644 src/map/mapper/mapperSuper.c delete mode 100644 src/map/mapper/mapperSwitch.c delete mode 100644 src/map/mapper/mapperTable.c delete mode 100644 src/map/mapper/mapperTime.c delete mode 100644 src/map/mapper/mapperTree.c delete mode 100644 src/map/mapper/mapperTruth.c delete mode 100644 src/map/mapper/mapperUtils.c delete mode 100644 src/map/mapper/mapperVec.c delete mode 100644 src/map/mapper/module.make delete mode 100644 src/map/mio/mio.c delete mode 100644 src/map/mio/mio.h delete mode 100644 src/map/mio/mioApi.c delete mode 100644 src/map/mio/mioFunc.c delete mode 100644 src/map/mio/mioGENERIC.c delete mode 100644 src/map/mio/mioInt.h delete mode 100644 src/map/mio/mioRead.c delete mode 100644 src/map/mio/mioUtils.c delete mode 100644 src/map/mio/module.make delete mode 100644 src/map/pcm/module.make delete mode 100644 src/map/super/module.make delete mode 100644 src/map/super/super.c delete mode 100644 src/map/super/super.h delete mode 100644 src/map/super/superAnd.c delete mode 100644 src/map/super/superGENERIC.c delete mode 100644 src/map/super/superGate.c delete mode 100644 src/map/super/superInt.h delete mode 100644 src/map/super/superWrite.c delete mode 100644 src/misc/espresso/cofactor.c delete mode 100644 src/misc/espresso/cols.c delete mode 100644 src/misc/espresso/compl.c delete mode 100644 src/misc/espresso/contain.c delete mode 100644 src/misc/espresso/cubehack.c delete mode 100644 src/misc/espresso/cubestr.c delete mode 100644 src/misc/espresso/cvrin.c delete mode 100644 src/misc/espresso/cvrm.c delete mode 100644 src/misc/espresso/cvrmisc.c delete mode 100644 src/misc/espresso/cvrout.c delete mode 100644 src/misc/espresso/dominate.c delete mode 100644 src/misc/espresso/equiv.c delete mode 100644 src/misc/espresso/espresso.c delete mode 100644 src/misc/espresso/espresso.h delete mode 100644 src/misc/espresso/essen.c delete mode 100644 src/misc/espresso/exact.c delete mode 100644 src/misc/espresso/expand.c delete mode 100644 src/misc/espresso/gasp.c delete mode 100644 src/misc/espresso/gimpel.c delete mode 100644 src/misc/espresso/globals.c delete mode 100644 src/misc/espresso/hack.c delete mode 100644 src/misc/espresso/indep.c delete mode 100644 src/misc/espresso/irred.c delete mode 100644 src/misc/espresso/main.c delete mode 100644 src/misc/espresso/main.h delete mode 100644 src/misc/espresso/map.c delete mode 100644 src/misc/espresso/matrix.c delete mode 100644 src/misc/espresso/mincov.c delete mode 100644 src/misc/espresso/mincov.h delete mode 100644 src/misc/espresso/mincov_int.h delete mode 100644 src/misc/espresso/module.make delete mode 100644 src/misc/espresso/opo.c delete mode 100644 src/misc/espresso/pair.c delete mode 100644 src/misc/espresso/part.c delete mode 100644 src/misc/espresso/primes.c delete mode 100644 src/misc/espresso/reduce.c delete mode 100644 src/misc/espresso/rows.c delete mode 100644 src/misc/espresso/set.c delete mode 100644 src/misc/espresso/setc.c delete mode 100644 src/misc/espresso/sharp.c delete mode 100644 src/misc/espresso/sminterf.c delete mode 100644 src/misc/espresso/solution.c delete mode 100644 src/misc/espresso/sparse.c delete mode 100644 src/misc/espresso/sparse.h delete mode 100644 src/misc/espresso/sparse_int.h delete mode 100644 src/misc/espresso/unate.c delete mode 100644 src/misc/espresso/util_old.h delete mode 100644 src/misc/espresso/verify.c delete mode 100644 src/misc/extra/extra.h delete mode 100644 src/misc/extra/extraBddAuto.c delete mode 100644 src/misc/extra/extraBddCas.c delete mode 100644 src/misc/extra/extraBddKmap.c delete mode 100644 src/misc/extra/extraBddMisc.c delete mode 100644 src/misc/extra/extraBddSymm.c delete mode 100644 src/misc/extra/extraBddUnate.c delete mode 100644 src/misc/extra/extraUtilBitMatrix.c delete mode 100644 src/misc/extra/extraUtilCanon.c delete mode 100644 src/misc/extra/extraUtilFile.c delete mode 100644 src/misc/extra/extraUtilMemory.c delete mode 100644 src/misc/extra/extraUtilMisc.c delete mode 100644 src/misc/extra/extraUtilProgress.c delete mode 100644 src/misc/extra/extraUtilReader.c delete mode 100644 src/misc/extra/extraUtilTruth.c delete mode 100644 src/misc/extra/extraUtilUtil.c delete mode 100644 src/misc/extra/module.make delete mode 100644 src/misc/hash/hash.h delete mode 100644 src/misc/hash/hashFlt.h delete mode 100644 src/misc/hash/hashInt.h delete mode 100644 src/misc/hash/hashPtr.h delete mode 100644 src/misc/hash/module.make delete mode 100644 src/misc/mvc/module.make delete mode 100644 src/misc/mvc/mvc.c delete mode 100644 src/misc/mvc/mvc.h delete mode 100644 src/misc/mvc/mvcApi.c delete mode 100644 src/misc/mvc/mvcCompare.c delete mode 100644 src/misc/mvc/mvcContain.c delete mode 100644 src/misc/mvc/mvcCover.c delete mode 100644 src/misc/mvc/mvcCube.c delete mode 100644 src/misc/mvc/mvcDivide.c delete mode 100644 src/misc/mvc/mvcDivisor.c delete mode 100644 src/misc/mvc/mvcList.c delete mode 100644 src/misc/mvc/mvcLits.c delete mode 100644 src/misc/mvc/mvcMan.c delete mode 100644 src/misc/mvc/mvcOpAlg.c delete mode 100644 src/misc/mvc/mvcOpBool.c delete mode 100644 src/misc/mvc/mvcPrint.c delete mode 100644 src/misc/mvc/mvcSort.c delete mode 100644 src/misc/mvc/mvcUtils.c delete mode 100644 src/misc/nm/module.make delete mode 100644 src/misc/nm/nm.h delete mode 100644 src/misc/nm/nmApi.c delete mode 100644 src/misc/nm/nmInt.h delete mode 100644 src/misc/nm/nmTable.c delete mode 100644 src/misc/st/module.make delete mode 100644 src/misc/st/st.c delete mode 100644 src/misc/st/st.h delete mode 100644 src/misc/st/stmm.c delete mode 100644 src/misc/st/stmm.h delete mode 100644 src/misc/util/leaks.h delete mode 100644 src/misc/util/module.make delete mode 100644 src/misc/util/stdlib_hack.h delete mode 100644 src/misc/util/util_hack.h delete mode 100644 src/misc/vec/module.make delete mode 100644 src/misc/vec/vec.h delete mode 100644 src/misc/vec/vecAtt.h delete mode 100644 src/misc/vec/vecFlt.h delete mode 100644 src/misc/vec/vecInt.h delete mode 100644 src/misc/vec/vecPtr.h delete mode 100644 src/misc/vec/vecStr.h delete mode 100644 src/misc/vec/vecVec.h delete mode 100644 src/opt/cut/abcCut.c delete mode 100644 src/opt/cut/cut.h delete mode 100644 src/opt/cut/cutApi.c delete mode 100644 src/opt/cut/cutCut.c delete mode 100644 src/opt/cut/cutExpand.c delete mode 100644 src/opt/cut/cutInt.h delete mode 100644 src/opt/cut/cutList.h delete mode 100644 src/opt/cut/cutMan.c delete mode 100644 src/opt/cut/cutMerge.c delete mode 100644 src/opt/cut/cutNode.c delete mode 100644 src/opt/cut/cutOracle.c delete mode 100644 src/opt/cut/cutPre22.c delete mode 100644 src/opt/cut/cutSeq.c delete mode 100644 src/opt/cut/cutTruth.c delete mode 100644 src/opt/cut/module.make delete mode 100644 src/opt/dec/dec.h delete mode 100644 src/opt/dec/decAbc.c delete mode 100644 src/opt/dec/decFactor.c delete mode 100644 src/opt/dec/decMan.c delete mode 100644 src/opt/dec/decPrint.c delete mode 100644 src/opt/dec/decUtil.c delete mode 100644 src/opt/dec/module.make delete mode 100644 src/opt/fxu/fxu.c delete mode 100644 src/opt/fxu/fxu.h delete mode 100644 src/opt/fxu/fxuCreate.c delete mode 100644 src/opt/fxu/fxuHeapD.c delete mode 100644 src/opt/fxu/fxuHeapS.c delete mode 100644 src/opt/fxu/fxuInt.h delete mode 100644 src/opt/fxu/fxuList.c delete mode 100644 src/opt/fxu/fxuMatrix.c delete mode 100644 src/opt/fxu/fxuPair.c delete mode 100644 src/opt/fxu/fxuPrint.c delete mode 100644 src/opt/fxu/fxuReduce.c delete mode 100644 src/opt/fxu/fxuSelect.c delete mode 100644 src/opt/fxu/fxuSingle.c delete mode 100644 src/opt/fxu/fxuUpdate.c delete mode 100644 src/opt/fxu/module.make delete mode 100644 src/opt/lpk/lpk.h delete mode 100644 src/opt/lpk/lpkAbcDec.c delete mode 100644 src/opt/lpk/lpkAbcDsd.c delete mode 100644 src/opt/lpk/lpkAbcMux.c delete mode 100644 src/opt/lpk/lpkAbcUtil.c delete mode 100644 src/opt/lpk/lpkCore.c delete mode 100644 src/opt/lpk/lpkCut.c delete mode 100644 src/opt/lpk/lpkInt.h delete mode 100644 src/opt/lpk/lpkMan.c delete mode 100644 src/opt/lpk/lpkMap.c delete mode 100644 src/opt/lpk/lpkMulti.c delete mode 100644 src/opt/lpk/lpkMux.c delete mode 100644 src/opt/lpk/lpkSets.c delete mode 100644 src/opt/lpk/lpk_.c delete mode 100644 src/opt/lpk/module.make delete mode 100644 src/opt/res/module.make delete mode 100644 src/opt/res/res.h delete mode 100644 src/opt/res/resCore.c delete mode 100644 src/opt/res/resDivs.c delete mode 100644 src/opt/res/resFilter.c delete mode 100644 src/opt/res/resInt.h delete mode 100644 src/opt/res/resSat.c delete mode 100644 src/opt/res/resSim.c delete mode 100644 src/opt/res/resSim_old.c delete mode 100644 src/opt/res/resStrash.c delete mode 100644 src/opt/res/resWin.c delete mode 100644 src/opt/res/res_.c delete mode 100644 src/opt/ret/module.make delete mode 100644 src/opt/ret/retArea.c delete mode 100644 src/opt/ret/retCore.c delete mode 100644 src/opt/ret/retDelay.c delete mode 100644 src/opt/ret/retFlow.c delete mode 100644 src/opt/ret/retIncrem.c delete mode 100644 src/opt/ret/retInit.c delete mode 100644 src/opt/ret/retInt.h delete mode 100644 src/opt/ret/retLvalue.c delete mode 100644 src/opt/ret/ret_.c delete mode 100644 src/opt/rwr/module.make delete mode 100644 src/opt/rwr/rwr.h delete mode 100644 src/opt/rwr/rwrDec.c delete mode 100644 src/opt/rwr/rwrEva.c delete mode 100644 src/opt/rwr/rwrExp.c delete mode 100644 src/opt/rwr/rwrLib.c delete mode 100644 src/opt/rwr/rwrMan.c delete mode 100644 src/opt/rwr/rwrPrint.c delete mode 100644 src/opt/rwr/rwrTemp.c delete mode 100644 src/opt/rwr/rwrUtil.c delete mode 100644 src/opt/sim/module.make delete mode 100644 src/opt/sim/sim.h delete mode 100644 src/opt/sim/simMan.c delete mode 100644 src/opt/sim/simSat.c delete mode 100644 src/opt/sim/simSeq.c delete mode 100644 src/opt/sim/simSupp.c delete mode 100644 src/opt/sim/simSwitch.c delete mode 100644 src/opt/sim/simSym.c delete mode 100644 src/opt/sim/simSymSat.c delete mode 100644 src/opt/sim/simSymSim.c delete mode 100644 src/opt/sim/simSymStr.c delete mode 100644 src/opt/sim/simUtils.c delete mode 100644 src/phys/place/Makefile delete mode 100644 src/phys/place/README delete mode 100644 src/phys/place/hpwl delete mode 100644 src/phys/place/libhmetis.h delete mode 100644 src/phys/place/module.make delete mode 100644 src/phys/place/place_base.c delete mode 100644 src/phys/place/place_base.h delete mode 100644 src/phys/place/place_bin.c delete mode 100644 src/phys/place/place_genqp.c delete mode 100644 src/phys/place/place_gordian.c delete mode 100644 src/phys/place/place_gordian.h delete mode 100644 src/phys/place/place_inc.c delete mode 100644 src/phys/place/place_io.c delete mode 100644 src/phys/place/place_legalize.c delete mode 100644 src/phys/place/place_pads.c delete mode 100644 src/phys/place/place_partition.c delete mode 100644 src/phys/place/place_qpsolver.c delete mode 100644 src/phys/place/place_qpsolver.h delete mode 100644 src/phys/place/place_test.c delete mode 100644 src/sat/bsat/module.make delete mode 100644 src/sat/bsat/satInter.c delete mode 100644 src/sat/bsat/satMem.c delete mode 100644 src/sat/bsat/satMem.h delete mode 100644 src/sat/bsat/satSolver.c delete mode 100644 src/sat/bsat/satSolver.h delete mode 100644 src/sat/bsat/satStore.c delete mode 100644 src/sat/bsat/satStore.h delete mode 100644 src/sat/bsat/satTrace.c delete mode 100644 src/sat/bsat/satUtil.c delete mode 100644 src/sat/bsat/satVec.h delete mode 100644 src/sat/csat/csat_apis.c delete mode 100644 src/sat/csat/csat_apis.h delete mode 100644 src/sat/csat/module.make delete mode 100644 src/sat/fraig/fraig.h delete mode 100644 src/sat/fraig/fraigApi.c delete mode 100644 src/sat/fraig/fraigCanon.c delete mode 100644 src/sat/fraig/fraigChoice.c delete mode 100644 src/sat/fraig/fraigFanout.c delete mode 100644 src/sat/fraig/fraigFeed.c delete mode 100644 src/sat/fraig/fraigInt.h delete mode 100644 src/sat/fraig/fraigMan.c delete mode 100644 src/sat/fraig/fraigMem.c delete mode 100644 src/sat/fraig/fraigNode.c delete mode 100644 src/sat/fraig/fraigPrime.c delete mode 100644 src/sat/fraig/fraigSat.c delete mode 100644 src/sat/fraig/fraigTable.c delete mode 100644 src/sat/fraig/fraigUtil.c delete mode 100644 src/sat/fraig/fraigVec.c delete mode 100644 src/sat/fraig/module.make delete mode 100644 src/sat/msat/module.make delete mode 100644 src/sat/msat/msat.h delete mode 100644 src/sat/msat/msatActivity.c delete mode 100644 src/sat/msat/msatClause.c delete mode 100644 src/sat/msat/msatClauseVec.c delete mode 100644 src/sat/msat/msatInt.h delete mode 100644 src/sat/msat/msatMem.c delete mode 100644 src/sat/msat/msatOrderH.c delete mode 100644 src/sat/msat/msatOrderJ.c delete mode 100644 src/sat/msat/msatQueue.c delete mode 100644 src/sat/msat/msatRead.c delete mode 100644 src/sat/msat/msatSolverApi.c delete mode 100644 src/sat/msat/msatSolverCore.c delete mode 100644 src/sat/msat/msatSolverIo.c delete mode 100644 src/sat/msat/msatSolverSearch.c delete mode 100644 src/sat/msat/msatSort.c delete mode 100644 src/sat/msat/msatVec.c delete mode 100644 src/sat/proof/pr.c delete mode 100644 src/sat/proof/pr.h delete mode 100644 src/sat/proof/stats.txt delete mode 100644 todo.txt diff --git a/Makefile b/Makefile deleted file mode 100644 index 68d221a2..00000000 --- a/Makefile +++ /dev/null @@ -1,79 +0,0 @@ - -CC := gcc -CXX := g++ -LD := g++ -CP := cp - -PROG := abc - -MODULES := src/base/abc src/base/abci src/base/cmd \ - src/base/io src/base/main src/base/ver \ - src/aig/ivy src/aig/hop src/aig/rwt src/aig/deco \ - src/aig/mem src/aig/dar src/aig/fra src/aig/cnf \ - src/aig/csw src/aig/ioa src/aig/aig src/aig/kit \ - src/aig/bdc src/aig/bar \ - src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr \ - src/bdd/parse src/bdd/reo src/bdd/cas \ - src/map/fpga src/map/mapper src/map/mio \ - src/map/super src/map/if src/map/pcm \ - src/misc/extra src/misc/mvc src/misc/st src/misc/util \ - src/misc/espresso src/misc/nm src/misc/vec \ - src/misc/hash \ - src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr \ - src/opt/sim src/opt/ret src/opt/res src/opt/lpk \ - src/sat/bsat src/sat/csat src/sat/msat src/sat/fraig \ - src/phys/place - -default: $(PROG) - -#OPTFLAGS := -DNDEBUG -O3 -OPTFLAGS := -g -O - -CFLAGS += -Wall -Wno-unused-function $(OPTFLAGS) $(patsubst %, -I%, $(MODULES)) -CXXFLAGS += $(CFLAGS) - -LIBS := -ldl -rdynamic -lreadline -ltermcap -SRC := -GARBAGE := core core.* *.stackdump ./tags $(PROG) - -.PHONY: tags clean docs - -include $(patsubst %, %/module.make, $(MODULES)) - -OBJ := \ - $(patsubst %.cc, %.o, $(filter %.cc, $(SRC))) \ - $(patsubst %.c, %.o, $(filter %.c, $(SRC))) \ - $(patsubst %.y, %.o, $(filter %.y, $(SRC))) - -DEP := $(OBJ:.o=.d) - -# implicit rules - -%.d: %.c - ./depends.sh $(CC) `dirname $*.c` $(CFLAGS) $*.c > $@ - -%.d: %.cc - ./depends.sh $(CXX) `dirname $*.cc` $(CXXFLAGS) $(CFLAGS) $*.cc > $@ - --include $(DEP) - -# Actual targets - -depend: $(DEP) - -clean: - rm -rf $(PROG) $(OBJ) $(GARBAGE) $(OBJ:.o=.d) - -tags: - ctags -R . - -$(PROG): $(OBJ) - $(LD) -o $@ $^ $(LIBS) - -lib$(PROG).a: $(OBJ) - ar rv $@ $? - ranlib $@ - -docs: - doxygen doxygen.conf - diff --git a/__MACOSX/abc70930/._.DS_Store b/__MACOSX/abc70930/._.DS_Store new file mode 100644 index 00000000..460d887a Binary files /dev/null and b/__MACOSX/abc70930/._.DS_Store differ diff --git a/__MACOSX/abc70930/._Instructions_for_Mac_OS_X_X_code_users.rtf b/__MACOSX/abc70930/._Instructions_for_Mac_OS_X_X_code_users.rtf new file mode 100644 index 00000000..0ddac7cf Binary files /dev/null and b/__MACOSX/abc70930/._Instructions_for_Mac_OS_X_X_code_users.rtf differ diff --git a/__MACOSX/abc70930/src/._.DS_Store b/__MACOSX/abc70930/src/._.DS_Store new file mode 100644 index 00000000..460d887a Binary files /dev/null and b/__MACOSX/abc70930/src/._.DS_Store differ diff --git a/__MACOSX/abc70930/src/aig/hop/._cudd2.c b/__MACOSX/abc70930/src/aig/hop/._cudd2.c new file mode 100644 index 00000000..1e408f45 Binary files /dev/null and b/__MACOSX/abc70930/src/aig/hop/._cudd2.c differ diff --git a/__MACOSX/abc70930/src/base/._.DS_Store b/__MACOSX/abc70930/src/base/._.DS_Store new file mode 100644 index 00000000..460d887a Binary files /dev/null and b/__MACOSX/abc70930/src/base/._.DS_Store differ diff --git a/__MACOSX/abc70930/src/base/main/._main.h b/__MACOSX/abc70930/src/base/main/._main.h new file mode 100644 index 00000000..2e9d99cf Binary files /dev/null and b/__MACOSX/abc70930/src/base/main/._main.h differ diff --git a/__MACOSX/abc70930/src/base/main/._mainUtils.c b/__MACOSX/abc70930/src/base/main/._mainUtils.c new file mode 100644 index 00000000..ca2aaa4c Binary files /dev/null and b/__MACOSX/abc70930/src/base/main/._mainUtils.c differ diff --git a/__MACOSX/abc70930/src/misc/espresso/._unate.c b/__MACOSX/abc70930/src/misc/espresso/._unate.c new file mode 100644 index 00000000..7d3cf3c0 Binary files /dev/null and b/__MACOSX/abc70930/src/misc/espresso/._unate.c differ diff --git a/abc.dsp b/abc.dsp deleted file mode 100644 index 6541d46c..00000000 --- a/abc.dsp +++ /dev/null @@ -1,2983 +0,0 @@ -# Microsoft Developer Studio Project File - Name="abc" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=abc - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "abc.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "abc.mak" CFG="abc - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "abc - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "abc - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "abc - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\bsat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\opt\res" /I "src\opt\lpk" /I "src\map\fpga" /I "src\map\if" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\misc\hash" /I "src\aig\ivy" /I "src\aig\hop" /I "src\aig\rwt" /I "src\aig\deco" /I "src\aig\mem" /I "src\aig\aig" /I "src\aig\dar" /I "src\aig\cnf" /I "src\aig\fra" /I "src\aig\kit" /I "src\aig\bdc" /I "src\aig\ioa" /I "src\aig\bar" /I "src\aig\pcm" /I "src\temp\esop" /I "src\phys\place" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /machine:I386 /out:"_TEST/abc.exe" - -!ELSEIF "$(CFG)" == "abc - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\bsat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\opt\res" /I "src\opt\lpk" /I "src\map\fpga" /I "src\map\if" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\misc\hash" /I "src\aig\ivy" /I "src\aig\hop" /I "src\aig\rwt" /I "src\aig\deco" /I "src\aig\mem" /I "src\aig\aig" /I "src\aig\dar" /I "src\aig\cnf" /I "src\aig\fra" /I "src\aig\kit" /I "src\aig\bdc" /I "src\aig\ioa" /I "src\aig\bar" /I "src\aig\pcm" /I "src\temp\esop" /I "src\phys\place" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /GZ /c -# SUBTRACT CPP /X -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abc.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "abc - Win32 Release" -# Name "abc - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Group "base" - -# PROP Default_Filter "" -# Begin Group "abc" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\abc\abc.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcAig.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcBlifMv.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcDfs.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcFanio.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcFunc.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcHie.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcLatch.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcLib.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcMinBase.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcNames.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcNetlist.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcNtk.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcObj.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcRefs.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcShow.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcSop.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcUtil.c -# End Source File -# End Group -# Begin Group "abci" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\abci\abc.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcAttach.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcAuto.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcBalance.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcBmc.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcCas.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcClpBdd.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcClpSop.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcDar.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcDebug.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcDress.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcDsd.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcEspresso.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcExtract.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcFpga.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcFpgaFast.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcFraig.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcFxu.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcGen.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcHaig.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcIf.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcIvy.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcLut.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcMap.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcMeasure.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcMini.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcMiter.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcMulti.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcMv.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcNtbdd.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcOdc.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcOrder.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcPart.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcPlace.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcPrint.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcProve.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcQbf.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcQuant.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcRec.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcReconv.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcRefactor.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcRenode.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcReorder.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcRestruct.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcResub.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcRewrite.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcRr.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcStrash.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcSweep.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcSymm.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcTiming.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcUnate.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcUnreach.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcVerify.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcXsim.c -# End Source File -# End Group -# Begin Group "cmd" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\cmd\cmd.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmd.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdAlias.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdFlag.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdHist.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdUtils.c -# End Source File -# End Group -# Begin Group "io" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\io\io.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\io.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadAiger.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadBaf.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadBench.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadBlif.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadBlifAig.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadBlifMv.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadDsd.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadEdif.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadEqn.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadPla.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadVerilog.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteAiger.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteBaf.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteBench.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteBlif.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteBlifMv.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteCnf.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteDot.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteEqn.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteGml.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteList.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWritePla.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteVerilog.c -# End Source File -# End Group -# Begin Group "main" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\main\libSupport.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\main.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\main.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\mainFrame.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\mainInit.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\mainInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\mainUtils.c -# End Source File -# End Group -# Begin Group "ver" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\ver\ver.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\ver\verCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\ver\verFormula.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\ver\verParse.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\ver\verStream.c -# End Source File -# End Group -# Begin Group "func" - -# PROP Default_Filter "" -# End Group -# End Group -# Begin Group "bdd" - -# PROP Default_Filter "" -# Begin Group "cudd" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\cudd\cudd.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddAbs.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddApply.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddFind.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddInv.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddIte.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddNeg.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddWalsh.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAndAbs.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAnneal.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddApa.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAPI.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddApprox.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddBddAbs.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddBddCorr.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddBddIte.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddBridge.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddCache.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddClip.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddCof.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddCompose.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddDecomp.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddEssent.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddExact.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddExport.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddGenCof.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddGenetic.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddGroup.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddHarwell.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddInit.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddInteract.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddLCache.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddLevelQ.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddLinear.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddLiteral.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddMatMult.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddPriority.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddRead.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddRef.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddReorder.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSign.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSolve.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSplit.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSubsetHB.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSubsetSP.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSymmetry.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddWindow.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddCount.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddFuncs.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddGroup.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddIsop.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddLin.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddMisc.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddPort.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddReord.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddSetop.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddSymm.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddUtil.c -# End Source File -# End Group -# Begin Group "epd" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\epd\epd.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\epd\epd.h -# End Source File -# End Group -# Begin Group "mtr" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\mtr\mtr.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\mtr\mtrBasic.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\mtr\mtrGroup.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\mtr\mtrInt.h -# End Source File -# End Group -# Begin Group "parse" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\parse\parse.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\parse\parseCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\parse\parseEqn.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\parse\parseInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\parse\parseStack.c -# End Source File -# End Group -# Begin Group "dsd" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsd.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdLocal.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdProc.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdTree.c -# End Source File -# End Group -# Begin Group "reo" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\reo\reo.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoProfile.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoSift.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoSwap.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoTest.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoTransfer.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoUnits.c -# End Source File -# End Group -# Begin Group "cas" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\cas\cas.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cas\casCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cas\casDec.c -# End Source File -# End Group -# End Group -# Begin Group "sat" - -# PROP Default_Filter "" -# Begin Group "msat" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\sat\msat\msat.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatActivity.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatClause.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatClauseVec.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatOrderH.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatQueue.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatRead.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatSolverApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatSolverCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatSolverIo.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatSolverSearch.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatSort.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatVec.c -# End Source File -# End Group -# Begin Group "fraig" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\sat\fraig\fraig.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigCanon.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigChoice.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigFanout.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigFeed.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigNode.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigPrime.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigVec.c -# End Source File -# End Group -# Begin Group "csat" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\sat\csat\csat_apis.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\csat\csat_apis.h -# End Source File -# End Group -# Begin Group "bsat" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\sat\bsat\satInter.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satMem.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satSolver.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satSolver.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satStore.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satStore.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satTrace.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satVec.h -# End Source File -# End Group -# Begin Group "proof" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\sat\proof\pr.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\proof\pr.h -# End Source File -# End Group -# End Group -# Begin Group "opt" - -# PROP Default_Filter "" -# Begin Group "fxu" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\fxu\fxu.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxu.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuCreate.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuHeapD.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuHeapS.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuList.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuMatrix.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuPair.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuPrint.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuReduce.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuSelect.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuSingle.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuUpdate.c -# End Source File -# End Group -# Begin Group "rwr" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\rwr\rwr.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrDec.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrEva.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrExp.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrLib.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrPrint.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrTemp.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrUtil.c -# End Source File -# End Group -# Begin Group "cut" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\cut\cut.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutExpand.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutList.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutMerge.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutNode.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutOracle.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutPre22.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutSeq.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutTruth.c -# End Source File -# End Group -# Begin Group "dec" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\dec\dec.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\dec\decAbc.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\dec\decFactor.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\dec\decMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\dec\decPrint.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\dec\decUtil.c -# End Source File -# End Group -# Begin Group "sim" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\sim\sim.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSeq.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSupp.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSwitch.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSym.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSymSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSymSim.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSymStr.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simUtils.c -# End Source File -# End Group -# Begin Group "ret" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\ret\retArea.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retDelay.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retFlow.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retIncrem.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retInit.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retLvalue.c -# End Source File -# End Group -# Begin Group "res" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\res\res.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\res\resCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\res\resDivs.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\res\resFilter.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\res\resInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\res\resSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\res\resSim.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\res\resStrash.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\res\resWin.c -# End Source File -# End Group -# Begin Group "lpk" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\lpk\lpk.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkAbcDec.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkAbcDsd.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkAbcMux.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkAbcUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkMap.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkMulti.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkMux.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\lpk\lpkSets.c -# End Source File -# End Group -# End Group -# Begin Group "map" - -# PROP Default_Filter "" -# Begin Group "fpga" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\fpga\fpga.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpga.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaCreate.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaCutUtils.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaFanout.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaLib.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaMatch.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaSwitch.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaTime.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaTruth.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaUtils.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaVec.c -# End Source File -# End Group -# Begin Group "mapper" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\mapper\mapper.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapper.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperCanon.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperCreate.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperCutUtils.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperFanout.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperLib.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperMatch.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperRefs.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperSuper.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperSwitch.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperTime.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperTree.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperTruth.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperUtils.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperVec.c -# End Source File -# End Group -# Begin Group "mio" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\mio\mio.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mio.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mioApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mioFunc.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mioInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mioRead.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mioUtils.c -# End Source File -# End Group -# Begin Group "super" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\super\super.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\super\super.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\super\superAnd.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\super\superGate.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\super\superInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\super\superWrite.c -# End Source File -# End Group -# Begin Group "if" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\if\if.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifMap.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifReduce.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifSeq.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifTime.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifTruth.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifUtil.c -# End Source File -# End Group -# Begin Group "pcm" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\pcm\pcm.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmAbc.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmAig.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmIter.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmLib.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmMap.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmPar.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmReduce.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmTime.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmTruth.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\pcm\pcmUtil.c -# End Source File -# End Group -# End Group -# Begin Group "misc" - -# PROP Default_Filter "" -# Begin Group "extra" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\extra\extra.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraBddAuto.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraBddCas.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraBddKmap.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraBddMisc.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraBddSymm.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraBddUnate.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilBitMatrix.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilCanon.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilFile.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilMemory.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilMisc.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilProgress.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilReader.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilTruth.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilUtil.c -# End Source File -# End Group -# Begin Group "st" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\st\st.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\st\st.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\st\stmm.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\st\stmm.h -# End Source File -# End Group -# Begin Group "mvc" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\mvc\mvc.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvc.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcCompare.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcContain.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcCover.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcCube.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcDivide.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcDivisor.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcList.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcLits.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcOpAlg.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcOpBool.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcPrint.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcSort.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcUtils.c -# End Source File -# End Group -# Begin Group "vec" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\vec\vec.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecAtt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecFlt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecPtr.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecStr.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecVec.h -# End Source File -# End Group -# Begin Group "espresso" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\espresso\cofactor.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cols.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\compl.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\contain.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cubehack.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cubestr.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cvrin.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cvrm.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cvrmisc.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cvrout.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\dominate.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\equiv.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\espresso.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\espresso.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\essen.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\exact.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\expand.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\gasp.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\gimpel.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\globals.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\hack.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\indep.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\irred.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\map.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\matrix.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\mincov.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\mincov.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\mincov_int.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\opo.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\pair.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\part.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\primes.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\reduce.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\rows.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\set.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\setc.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\sharp.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\sminterf.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\solution.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\sparse.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\sparse.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\sparse_int.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\unate.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\verify.c -# End Source File -# End Group -# Begin Group "util" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\util\util_hack.h -# End Source File -# End Group -# Begin Group "nm" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\nm\nm.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\nm\nmApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\nm\nmInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\nm\nmTable.c -# End Source File -# End Group -# Begin Group "hash" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\hash\hash.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\hash\hashFlt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\hash\hashInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\hash\hashPtr.h -# End Source File -# End Group -# End Group -# Begin Group "phys" - -# PROP Default_Filter "" -# Begin Group "place" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\phys\place\libhmetis.h -# End Source File -# Begin Source File - -SOURCE=.\src\phys\place\place_base.c -# End Source File -# Begin Source File - -SOURCE=.\src\phys\place\place_base.h -# End Source File -# Begin Source File - -SOURCE=.\src\phys\place\place_bin.c -# End Source File -# Begin Source File - -SOURCE=.\src\phys\place\place_genqp.c -# End Source File -# Begin Source File - -SOURCE=.\src\phys\place\place_gordian.c -# End Source File -# Begin Source File - -SOURCE=.\src\phys\place\place_gordian.h -# End Source File -# Begin Source File - -SOURCE=.\src\phys\place\place_legalize.c -# End Source File -# Begin Source File - -SOURCE=.\src\phys\place\place_pads.c -# End Source File -# Begin Source File - -SOURCE=.\src\phys\place\place_partition.c -# End Source File -# Begin Source File - -SOURCE=.\src\phys\place\place_qpsolver.c -# End Source File -# Begin Source File - -SOURCE=.\src\phys\place\place_qpsolver.h -# End Source File -# End Group -# End Group -# Begin Group "ai" - -# PROP Default_Filter "" -# Begin Group "hop" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\hop\hop.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopBalance.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopDfs.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopObj.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopOper.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopUtil.c -# End Source File -# End Group -# Begin Group "ivy" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\ivy\ivy.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyBalance.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyCanon.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyCutTrav.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyDfs.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyDsd.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyFanout.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyFastMap.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyFraig.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyHaig.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyMulti.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyObj.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyOper.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyResyn.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyRwr.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivySeq.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyShow.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyUtil.c -# End Source File -# End Group -# Begin Group "rwt" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\rwt\rwt.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\rwt\rwtDec.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\rwt\rwtMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\rwt\rwtUtil.c -# End Source File -# End Group -# Begin Group "deco" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\deco\deco.h -# End Source File -# End Group -# Begin Group "mem" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\mem\mem.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\mem\mem.h -# End Source File -# End Group -# Begin Group "ioa" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\ioa\ioa.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ioa\ioaReadAig.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ioa\ioaUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ioa\ioaWriteAig.c -# End Source File -# End Group -# Begin Group "dar" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\dar\dar.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darBalance.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darData.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darLib.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darPrec.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darRefact.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darResub.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darScript.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\dar\darTruth.c -# End Source File -# End Group -# Begin Group "fra" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\fra\fra.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraBmc.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraCec.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraClass.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraCnf.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraImp.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraInd.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraLcr.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraPart.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraSec.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\fra\fraSim.c -# End Source File -# End Group -# Begin Group "cnf" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\cnf\cnf.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\cnf\cnfCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\cnf\cnfCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\cnf\cnfData.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\cnf\cnfMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\cnf\cnfMap.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\cnf\cnfPost.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\cnf\cnfUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\cnf\cnfWrite.c -# End Source File -# End Group -# Begin Group "csw" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\csw\csw.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\csw\cswCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\csw\cswCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\csw\cswInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\csw\cswMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\csw\cswTable.c -# End Source File -# End Group -# Begin Group "kit" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\kit\cloud.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\cloud.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\kit.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\kitAig.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\kitBdd.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\kitCloud.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\kitDsd.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\kitFactor.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\kitGraph.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\kitHop.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\kitIsop.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\kitSop.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\kit\kitTruth.c -# End Source File -# End Group -# Begin Group "bdc" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\bdc\bdc.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\bdc\bdcCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\bdc\bdcDec.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\bdc\bdcInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\bdc\bdcTable.c -# End Source File -# End Group -# Begin Group "aig" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\aig\aig.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigDfs.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigFanout.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigMffc.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigObj.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigOper.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigOrder.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigPart.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigRepr.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigRet.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigScl.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigSeq.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigShow.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigTime.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigTiming.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigTruth.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigTsim.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\aig\aigWin.c -# End Source File -# End Group -# Begin Group "bar" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\bar\bar.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\bar\bar.h -# End Source File -# End Group -# End Group -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/abc.dsw b/abc.dsw deleted file mode 100644 index 83f94950..00000000 --- a/abc.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "abc"=.\abc.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/abc.rc b/abc.rc deleted file mode 100644 index d04fc6aa..00000000 --- a/abc.rc +++ /dev/null @@ -1,176 +0,0 @@ -# global parameters -set check # checks intermediate networks -#set checkfio # prints warnings when fanins/fanouts are duplicated -set checkread # checks new networks after reading from file -set backup # saves backup networks retrived by "undo" and "recall" -set savesteps 1 # sets the maximum number of backup networks to save -set progressbar # display the progress bar - -# program names for internal calls -set dotwin dot.exe -set dotunix dot -set gsviewwin gsview32.exe -set gsviewunix gv -set siswin sis.exe -set sisunix sis -set mvsiswin mvsis.exe -set mvsisunix mvsis -set capowin MetaPl-Capo10.1-Win32.exe -set capounix MetaPl-Capo10.1 -set gnuplotwin wgnuplot.exe -set gnuplotunix gnuplot - -# standard aliases -alias b balance -alias cl cleanup -alias clp collapse -alias esd ext_seq_dcs -alias f fraig -alias fs fraig_sweep -alias fsto fraig_store -alias fres fraig_restore -alias ft fraig_trust -alias lp lutpack -alias pd print_dsd -alias pex print_exdc -d -alias pf print_factor -alias pfan print_fanio -alias pl print_level -alias pio print_io -alias pk print_kmap -alias ps print_stats -alias psu print_supp -alias psy print_symm -alias pun print_unate -alias q quit -alias r read -alias r3 retime -M 3 -alias r3f retime -M 3 -f -alias r3b retime -M 3 -b -alias ren renode -alias rh read_hie -alias rl read_blif -alias rb read_bench -alias ret retime -alias rp read_pla -alias rt read_truth -alias rv read_verilog -alias rvl read_verlib -alias rsup read_super mcnc5_old.super -alias rlib read_library -alias rlibc read_library cadence.genlib -alias rw rewrite -alias rwz rewrite -z -alias rf refactor -alias rfz refactor -z -alias re restructure -alias rez restructure -z -alias rs resub -alias rsz resub -z -alias sa set autoexec ps -alias scl scleanup -alias sif if -s -alias so source -x -alias st strash -alias sw sweep -alias ssw ssweep -alias tr0 trace_start -alias tr1 trace_check -alias trt "r c.blif; st; tr0; b; tr1" -alias u undo -alias w write -alias wa write_aiger -alias wb write_bench -alias wc write_cnf -alias wh write_hie -alias wl write_blif -alias wp write_pla -alias wv write_verilog - -# standard scripts -alias share "b; multi; fx; b" -alias resyn "b; rw; rwz; b; rwz; b" -alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" -alias resyn2a "b; rw; b; rw; rwz; b; rwz; b" -alias resyn3 "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b" -alias compress "b -l; rw -l; rwz -l; b -l; rwz -l; b -l" -alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l" -alias choice "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore" -alias choice2 "fraig_store; balance; fraig_store; resyn; fraig_store; resyn2; fraig_store; resyn2; fraig_store; fraig_restore" -alias rwsat "st; rw -l; b -l; rw -l; rf -l" -alias rwsat2 "st; rw -l; b -l; rw -l; rf -l; fraig; rw -l; b -l; rw -l; rf -l" -alias shake "st; ps; sat -C 5000; rw -l; ps; sat -C 5000; b -l; rf -l; ps; sat -C 5000; rfz -l; ps; sat -C 5000; rwz -l; ps; sat -C 5000; rfz -l; ps; sat -C 5000" - -# resubstitution scripts for the IWLS paper -alias src_rw "st; rw -l; rwz -l; rwz -l" -alias src_rs "st; rs -K 6 -N 2 -l; rs -K 9 -N 2 -l; rs -K 12 -N 2 -l" -alias src_rws "st; rw -l; rs -K 6 -N 2 -l; rwz -l; rs -K 9 -N 2 -l; rwz -l; rs -K 12 -N 2 -l" -alias resyn2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b" -alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l" - -# experimental implementation of don't-cares -alias resyn2rsdc "b; rs -K 6 -F 2; rw; rs -K 6 -N 2 -F 2; rf; rs -K 8 -F 2; b; rs -K 8 -N 2 -F 2; rw; rs -K 10 -F 2; rwz; rs -K 10 -N 2 -F 2; b; rs -K 12 -F 2; rfz; rs -K 12 -N 2 -F 2; rwz; b" -alias compress2rsdc "b -l; rs -K 6 -F 2 -l; rw -l; rs -K 6 -N 2 -F 2 -l; rf -l; rs -K 8 -F 2 -l; b -l; rs -K 8 -N 2 -F 2 -l; rw -l; rs -K 10 -F 2 -l; rwz -l; rs -K 10 -N 2 -F 2 -l; b -l; rs -K 12 -F 2 -l; rfz -l; rs -K 12 -N 2 -F 2 -l; rwz -l; b -l" - -# minimizing for FF literals -alias fflitmin "compress2rs; ren; sop; ps -f" - -# temporaries -#alias t "rvl th/lib.v; rvv th/t2.v" -#alias t "so c/pure_sat/test.c" -#alias t "r c/14/csat_998.bench; st; ps" -#alias t0 "r res.blif; aig; mfs" -#alias t "r res2.blif; aig; mfs" - -#alias tt "r a/quip_opt/nut_001_opt.blif" -#alias ttb "wh a/quip_opt/nut_001_opt.blif 1.blif" -#alias ttv "wh a/quip_opt/nut_001_opt.blif 1.v" - -alias reach "st; ps; compress2; ps; qrel; ps; compress2; ps; qreach -v; ps" - -alias qs1 "qvar -I 96 -u; ps; qbf -P 96" -alias qs2 "qvar -I 96 -u; qvar -I 97 -u; ps; qbf -P 96" -alias qs3 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; ps; qbf -P 96" -alias qs4 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; ps; qbf -P 96" -alias qs5 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; ps; qbf -P 96" -alias qs6 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; ps; qbf -P 96" -alias qs7 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; ps; qbf -P 96" -alias qs8 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; qvar -I 103 -u; ps; qbf -P 96" -alias qs9 "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; qvar -I 103 -u; qvar -I 104 -u; ps; qbf -P 96" -alias qsA "qvar -I 96 -u; qvar -I 97 -u; qvar -I 98 -u; qvar -I 99 -u; qvar -I 100 -u; qvar -I 101 -u; qvar -I 102 -u; qvar -I 103 -u; qvar -I 104 -u; qvar -I 105 -u; ps; qbf -P 96" - -alias chnew "st; haig_start; resyn2; haig_use" -alias chnewrs "st; haig_start; resyn2rs; haig_use" - -alias stdsd "r test/6in.blif; st; ps; u; bdd; dsd -g; st; ps" -alias trec "rec_start; r c.blif; st; rec_add; rec_use" -alias trec4 "rec_start -K 4; r i10.blif; st; rec_add; rec_use" -alias trec5 "rec_start -K 5; r i10.blif; st; rec_add; rec_use" -alias trec6 "rec_start -K 6; r i10.blif; st; rec_add; rec_use" -alias trec7 "rec_start -K 7; r i10.blif; st; rec_add; rec_use" -alias trec8 "rec_start -K 8; r i10.blif; st; rec_add; rec_use" -alias trec10 "rec_start -K 10; r i10.blif; st; rec_add; rec_use" -alias trec12 "rec_start -K 12; r i10.blif; st; rec_add; rec_use" - -#alias tsh "r i10_if.blif; st; ps; u; sw; st; ps; cec" -alias tst4 "r i10_if4.blif; st; ps; r x/rec4_.blif; st; rec_start; r i10_if4.blif; st -r; ps; cec" -alias tst4n "r i10_if4.blif; st; ps; r 5npn/all_functions.aig; st; rec_start; r i10_if4.blif; st -r; ps; cec" -alias tst6 "r i10_if6.blif; st; ps; r x/rec6_16_.blif; st; rec_start; r i10_if6.blif; st -r; ps; cec" - -#alias t "r c.blif; st; wc c.cnf" -#alias t "r test/dsdmap6.blif; lutpack -vw; cec" -#alias t "r i10_if4.blif; lp" -#alias t1 "r pj1_if4.blif; lp" -#alias t2 "r pj1_if6.blif; lp" -#alias t "r pj/pj1.blif; st; dfraig -v" -#alias t "r c/16/csat_2.bench; st; dfraig -C 100 -v -r" -#alias t "r c/16/csat_147.bench; st; dfraig -C 10 -v -r" -#alias t "r i10.blif; st; ps; csweep; ps; cec" -#alias t "r c/5/csat_777.bench; st; csweep -v" -#alias t "r i10.blif; st; drw -v" -#alias t "r c.blif; st; drf" -alias t "r i10.blif; st; dchoice; ps" - -alias bmc "frames -i -F 10; orpos; iprove" - - diff --git a/abc70930/.DS_Store b/abc70930/.DS_Store new file mode 100644 index 00000000..49d2fba3 Binary files /dev/null and b/abc70930/.DS_Store differ diff --git a/abc70930/Instructions_for_Mac_OS_X_X_code_users.rtf b/abc70930/Instructions_for_Mac_OS_X_X_code_users.rtf new file mode 100644 index 00000000..e941b5bd --- /dev/null +++ b/abc70930/Instructions_for_Mac_OS_X_X_code_users.rtf @@ -0,0 +1,7 @@ +{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf330 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\paperw11900\paperh16840\margl1440\margr1440\vieww9000\viewh8400\viewkind0 +\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural + +\f0\fs24 \cf0 Go to src folder and open the Xcode Project. Compile and enjoy.} \ No newline at end of file diff --git a/abc70930/Makefile b/abc70930/Makefile new file mode 100644 index 00000000..9d42e6bc --- /dev/null +++ b/abc70930/Makefile @@ -0,0 +1,76 @@ + +CC := gcc +CXX := g++ +LD := g++ +CP := cp + +PROG := abc + +MODULES := src/base/abc src/base/abci src/base/cmd \ + src/base/io src/base/main src/base/ver \ + src/bdd/cudd src/bdd/dsd src/bdd/epd src/bdd/mtr \ + src/bdd/parse src/bdd/reo src/bdd/cas \ + src/map/fpga src/map/mapper src/map/mio src/map/super src/map/if \ + src/misc/extra src/misc/mvc src/misc/st src/misc/util \ + src/misc/espresso src/misc/nm src/misc/vec src/misc/hash \ + src/opt/cut src/opt/dec src/opt/fxu src/opt/rwr \ + src/opt/sim src/opt/ret src/opt/res src/opt/lpk \ + src/sat/bsat src/sat/csat src/sat/msat src/sat/fraig \ + src/aig/ivy src/aig/hop src/aig/rwt src/aig/deco \ + src/aig/mem src/aig/dar src/aig/fra src/aig/cnf \ + src/aig/csw src/aig/ioa src/aig/aig src/aig/kit \ + src/aig/bdc src/aig/bar + +default: $(PROG) + +#OPTFLAGS := -DNDEBUG -O3 +OPTFLAGS := -g -O + +CFLAGS += -Wall -Wno-unused-function $(OPTFLAGS) $(patsubst %, -I%, $(MODULES)) +CXXFLAGS += $(CFLAGS) + +LIBS := -ldl -rdynamic -lreadline -ltermcap +SRC := +GARBAGE := core core.* *.stackdump ./tags $(PROG) + +.PHONY: tags clean docs + +include $(patsubst %, %/module.make, $(MODULES)) + +OBJ := \ + $(patsubst %.cc, %.o, $(filter %.cc, $(SRC))) \ + $(patsubst %.c, %.o, $(filter %.c, $(SRC))) \ + $(patsubst %.y, %.o, $(filter %.y, $(SRC))) + +DEP := $(OBJ:.o=.d) + +# implicit rules + +%.d: %.c + ./depends.sh $(CC) `dirname $*.c` $(CFLAGS) $*.c > $@ + +%.d: %.cc + ./depends.sh $(CXX) `dirname $*.cc` $(CXXFLAGS) $(CFLAGS) $*.cc > $@ + +-include $(DEP) + +# Actual targets + +depend: $(DEP) + +clean: + rm -rf $(PROG) $(OBJ) $(GARBAGE) $(OBJ:.o=.d) + +tags: + ctags -R . + +$(PROG): $(OBJ) + $(LD) -o $@ $^ $(LIBS) + +lib$(PROG).a: $(OBJ) + ar rv $@ $? + ranlib $@ + +docs: + doxygen doxygen.conf + diff --git a/abc70930/abc.dsp b/abc70930/abc.dsp new file mode 100644 index 00000000..dca99338 --- /dev/null +++ b/abc70930/abc.dsp @@ -0,0 +1,2847 @@ +# Microsoft Developer Studio Project File - Name="abc" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=abc - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "abc.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "abc.mak" CFG="abc - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "abc - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "abc - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "abc - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /machine:I386 /out:"_TEST/abc.exe" + +!ELSEIF "$(CFG)" == "abc - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR /YX /FD /GZ /c +# SUBTRACT CPP /X +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abc.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "abc - Win32 Release" +# Name "abc - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "base" + +# PROP Default_Filter "" +# Begin Group "abc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\abc\abc.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcBlifMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcFanio.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcFunc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcHie.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcLatch.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcMinBase.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcNames.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcNetlist.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcNtk.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcRefs.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcSop.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcUtil.c +# End Source File +# End Group +# Begin Group "abci" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\abci\abc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcAttach.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcAuto.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcBmc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcCas.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcClpBdd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcClpSop.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDar.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDebug.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDress.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcEspresso.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcExtract.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcFpga.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcFpgaFast.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcFraig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcFxu.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcGen.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcHaig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcIf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcIvy.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcLut.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMeasure.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMini.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMiter.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMulti.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcNtbdd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcOdc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcOrder.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcPart.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcProve.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcQbf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcQuant.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRec.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcReconv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRefactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRenode.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcReorder.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRestruct.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcResub.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRewrite.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRr.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcStrash.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSweep.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSymm.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcTiming.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcUnate.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcUnreach.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcVerify.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcXsim.c +# End Source File +# End Group +# Begin Group "cmd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\cmd\cmd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmd.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdAlias.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdFlag.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdHist.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdUtils.c +# End Source File +# End Group +# Begin Group "io" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\io\io.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\io.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadAiger.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBaf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBench.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBlif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBlifAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBlifMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadEdif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadEqn.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadPla.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadVerilog.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteAiger.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBaf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBench.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBlif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBlifMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteDot.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteEqn.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteGml.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteList.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWritePla.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteVerilog.c +# End Source File +# End Group +# Begin Group "main" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\main\libSupport.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\main.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\main.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainFrame.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainInit.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainUtils.c +# End Source File +# End Group +# Begin Group "ver" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\ver\ver.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verFormula.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verParse.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verStream.c +# End Source File +# End Group +# End Group +# Begin Group "bdd" + +# PROP Default_Filter "" +# Begin Group "cudd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\cudd\cudd.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddAbs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddApply.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddFind.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddInv.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddIte.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddNeg.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddWalsh.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAndAbs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAnneal.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddApa.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAPI.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddApprox.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBddAbs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBddCorr.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBddIte.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBridge.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCache.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddClip.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCof.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCompose.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddDecomp.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddEssent.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddExact.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddExport.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddGenCof.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddGenetic.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddGroup.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddHarwell.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddInit.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddInteract.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLCache.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLevelQ.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLinear.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLiteral.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddMatMult.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddPriority.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddRef.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddReorder.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSign.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSolve.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSplit.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSubsetHB.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSubsetSP.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSymmetry.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddWindow.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddCount.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddFuncs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddGroup.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddIsop.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddLin.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddMisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddPort.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddReord.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddSetop.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddSymm.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddUtil.c +# End Source File +# End Group +# Begin Group "epd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\epd\epd.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\epd\epd.h +# End Source File +# End Group +# Begin Group "mtr" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtr.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtrBasic.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtrGroup.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtrInt.h +# End Source File +# End Group +# Begin Group "parse" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\parse\parse.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\parse\parseCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\parse\parseEqn.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\parse\parseInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\parse\parseStack.c +# End Source File +# End Group +# Begin Group "dsd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsd.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdLocal.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdProc.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdTree.c +# End Source File +# End Group +# Begin Group "reo" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\reo\reo.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoProfile.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoSift.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoSwap.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoTest.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoTransfer.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoUnits.c +# End Source File +# End Group +# Begin Group "cas" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\cas\cas.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cas\casCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cas\casDec.c +# End Source File +# End Group +# End Group +# Begin Group "sat" + +# PROP Default_Filter "" +# Begin Group "msat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\msat\msat.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatActivity.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatClause.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatClauseVec.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatOrderH.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatQueue.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverIo.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverSearch.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSort.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatVec.c +# End Source File +# End Group +# Begin Group "fraig" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\fraig\fraig.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigChoice.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigFeed.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigNode.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigPrime.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigVec.c +# End Source File +# End Group +# Begin Group "csat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\csat\csat_apis.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\csat\csat_apis.h +# End Source File +# End Group +# Begin Group "bsat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\bsat\satInter.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satMem.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satSolver.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satSolver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satStore.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satStore.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satTrace.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satVec.h +# End Source File +# End Group +# Begin Group "proof" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\proof\pr.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\proof\pr.h +# End Source File +# End Group +# End Group +# Begin Group "opt" + +# PROP Default_Filter "" +# Begin Group "fxu" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\fxu\fxu.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxu.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuCreate.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuHeapD.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuHeapS.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuList.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuMatrix.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuPair.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuReduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuSelect.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuSingle.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuUpdate.c +# End Source File +# End Group +# Begin Group "rwr" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\rwr\rwr.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrEva.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrExp.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrTemp.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrUtil.c +# End Source File +# End Group +# Begin Group "cut" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\cut\cut.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutExpand.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutList.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutMerge.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutNode.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutOracle.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutPre22.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutTruth.c +# End Source File +# End Group +# Begin Group "dec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\dec\dec.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dec\decAbc.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dec\decFactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dec\decMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dec\decPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dec\decUtil.c +# End Source File +# End Group +# Begin Group "sim" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\sim\sim.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSupp.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSwitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSym.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSymSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSymSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSymStr.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simUtils.c +# End Source File +# End Group +# Begin Group "ret" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\ret\retArea.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retDelay.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retFlow.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retIncrem.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retInit.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retLvalue.c +# End Source File +# End Group +# Begin Group "res" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\res\res.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resDivs.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resFilter.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resStrash.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resWin.c +# End Source File +# End Group +# Begin Group "lpk" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\lpk\lpk.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcMux.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMulti.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMux.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkSets.c +# End Source File +# End Group +# End Group +# Begin Group "map" + +# PROP Default_Filter "" +# Begin Group "fpga" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\fpga\fpga.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpga.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaCreate.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaCutUtils.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaMatch.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaSwitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaUtils.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaVec.c +# End Source File +# End Group +# Begin Group "mapper" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\mapper\mapper.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapper.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCreate.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCutUtils.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperMatch.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperRefs.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperSuper.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperSwitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTree.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperUtils.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperVec.c +# End Source File +# End Group +# Begin Group "mio" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\mio\mio.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mio.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioFunc.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioUtils.c +# End Source File +# End Group +# Begin Group "super" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\super\super.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\super.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\superAnd.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\superGate.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\superInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\superWrite.c +# End Source File +# End Group +# Begin Group "if" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\if\if.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifReduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifUtil.c +# End Source File +# End Group +# End Group +# Begin Group "misc" + +# PROP Default_Filter "" +# Begin Group "extra" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\extra\extra.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddAuto.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddCas.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddKmap.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddMisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddSymm.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddUnate.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilBitMatrix.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilFile.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilMemory.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilMisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilProgress.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilReader.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilUtil.c +# End Source File +# End Group +# Begin Group "st" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\st\st.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\st\st.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\st\stmm.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\st\stmm.h +# End Source File +# End Group +# Begin Group "mvc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\mvc\mvc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvc.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcCompare.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcContain.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcCover.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcCube.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcDivide.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcDivisor.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcList.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcLits.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcOpAlg.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcOpBool.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcSort.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcUtils.c +# End Source File +# End Group +# Begin Group "vec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\vec\vec.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecAtt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecFlt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecPtr.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecStr.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecVec.h +# End Source File +# End Group +# Begin Group "espresso" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\espresso\cofactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cols.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\compl.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\contain.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cubehack.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cubestr.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrin.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrm.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrmisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrout.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\dominate.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\equiv.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\espresso.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\espresso.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\essen.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\exact.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\expand.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\gasp.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\gimpel.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\globals.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\hack.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\indep.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\irred.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\map.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\matrix.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov_int.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\opo.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\pair.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\part.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\primes.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\reduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\rows.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\set.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\setc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sharp.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sminterf.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\solution.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse_int.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\unate.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\verify.c +# End Source File +# End Group +# Begin Group "util" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\util\util_hack.h +# End Source File +# End Group +# Begin Group "nm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\nm\nm.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\nm\nmApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\nm\nmInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\nm\nmTable.c +# End Source File +# End Group +# Begin Group "hash" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\hash\hash.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\hash\hashFlt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\hash\hashInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\hash\hashPtr.h +# End Source File +# End Group +# End Group +# Begin Group "ai" + +# PROP Default_Filter "" +# Begin Group "hop" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\hop\hop.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopUtil.c +# End Source File +# End Group +# Begin Group "ivy" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\ivy\ivy.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCutTrav.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFastMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFraig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyHaig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMulti.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyResyn.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyRwr.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivySeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyUtil.c +# End Source File +# End Group +# Begin Group "rwt" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\rwt\rwt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\rwt\rwtDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\rwt\rwtMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\rwt\rwtUtil.c +# End Source File +# End Group +# Begin Group "deco" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\deco\deco.h +# End Source File +# End Group +# Begin Group "mem" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\mem\mem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\mem\mem.h +# End Source File +# End Group +# Begin Group "ioa" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\ioa\ioa.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ioa\ioaReadAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ioa\ioaUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ioa\ioaWriteAig.c +# End Source File +# End Group +# Begin Group "dar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\dar\dar.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darData.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darPrec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darRefact.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darResub.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darScript.c +# End Source File +# End Group +# Begin Group "fra" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\fra\fra.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraBmc.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraCec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraClass.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraImp.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraInd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraLcr.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraPart.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraSec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraSim.c +# End Source File +# End Group +# Begin Group "cnf" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\cnf\cnf.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfData.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfPost.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfWrite.c +# End Source File +# End Group +# Begin Group "csw" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\csw\csw.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\csw\cswCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\csw\cswCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\csw\cswInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\csw\cswMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\csw\cswTable.c +# End Source File +# End Group +# Begin Group "kit" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\kit\cloud.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\cloud.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kit.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitBdd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitCloud.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitFactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitGraph.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitHop.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitIsop.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitSop.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitTruth.c +# End Source File +# End Group +# Begin Group "bdc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\bdc\bdc.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\bdc\bdcCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\bdc\bdcDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\bdc\bdcInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\bdc\bdcTable.c +# End Source File +# End Group +# Begin Group "aig" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\aig\aig.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigMffc.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigOrder.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigPart.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigRepr.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigRet.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigScl.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTiming.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTsim.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigWin.c +# End Source File +# End Group +# Begin Group "bar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\bar\bar.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\bar\bar.h +# End Source File +# End Group +# End Group +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/abc70930/abc.dsw b/abc70930/abc.dsw new file mode 100644 index 00000000..146413a5 --- /dev/null +++ b/abc70930/abc.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "abc"=.\abc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/abc70930/abc.plg b/abc70930/abc.plg new file mode 100644 index 00000000..7aadf0c8 --- /dev/null +++ b/abc70930/abc.plg @@ -0,0 +1,1105 @@ + + +
+

Build Log

+

+--------------------Configuration: abc - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP2086.tmp" with contents +[ +/nologo /ML /W3 /GX /O2 /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /FR"Release/" /Fp"Release/abc.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c +"C:\_projects\abc\src\base\abci\abc.c" +] +Creating command line "cl.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP2086.tmp" +Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP2087.tmp" with contents +[ +kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /profile /machine:I386 /out:"_TEST/abc.exe" +.\Release\abcAig.obj +.\Release\abcBlifMv.obj +.\Release\abcCheck.obj +.\Release\abcDfs.obj +.\Release\abcFanio.obj +.\Release\abcFunc.obj +.\Release\abcHie.obj +.\Release\abcLatch.obj +.\Release\abcLib.obj +.\Release\abcMinBase.obj +.\Release\abcNames.obj +.\Release\abcNetlist.obj +.\Release\abcNtk.obj +.\Release\abcObj.obj +.\Release\abcRefs.obj +.\Release\abcShow.obj +.\Release\abcSop.obj +.\Release\abcUtil.obj +.\Release\abc.obj +.\Release\abcAttach.obj +.\Release\abcAuto.obj +.\Release\abcBalance.obj +.\Release\abcBmc.obj +.\Release\abcCas.obj +.\Release\abcClpBdd.obj +.\Release\abcClpSop.obj +.\Release\abcCut.obj +.\Release\abcDar.obj +.\Release\abcDebug.obj +.\Release\abcDress.obj +.\Release\abcDsd.obj +.\Release\abcEspresso.obj +.\Release\abcExtract.obj +.\Release\abcFpga.obj +.\Release\abcFpgaFast.obj +.\Release\abcFraig.obj +.\Release\abcFxu.obj +.\Release\abcGen.obj +.\Release\abcHaig.obj +.\Release\abcIf.obj +.\Release\abcIvy.obj +.\Release\abcLut.obj +.\Release\abcMap.obj +.\Release\abcMeasure.obj +.\Release\abcMini.obj +.\Release\abcMiter.obj +.\Release\abcMulti.obj +.\Release\abcMv.obj +.\Release\abcNtbdd.obj +.\Release\abcOdc.obj +.\Release\abcOrder.obj +.\Release\abcPart.obj +.\Release\abcPrint.obj +.\Release\abcProve.obj +.\Release\abcQbf.obj +.\Release\abcQuant.obj +.\Release\abcRec.obj +.\Release\abcReconv.obj +.\Release\abcRefactor.obj +.\Release\abcRenode.obj +.\Release\abcReorder.obj +.\Release\abcRestruct.obj +.\Release\abcResub.obj +.\Release\abcRewrite.obj +.\Release\abcRr.obj +.\Release\abcSat.obj +.\Release\abcStrash.obj +.\Release\abcSweep.obj +.\Release\abcSymm.obj +.\Release\abcTiming.obj +.\Release\abcUnate.obj +.\Release\abcUnreach.obj +.\Release\abcVerify.obj +.\Release\abcXsim.obj +.\Release\cmd.obj +.\Release\cmdAlias.obj +.\Release\cmdApi.obj +.\Release\cmdFlag.obj +.\Release\cmdHist.obj +.\Release\cmdUtils.obj +.\Release\io.obj +.\Release\ioReadAiger.obj +.\Release\ioReadBaf.obj +.\Release\ioReadBench.obj +.\Release\ioReadBlif.obj +.\Release\ioReadBlifAig.obj +.\Release\ioReadBlifMv.obj +.\Release\ioReadDsd.obj +.\Release\ioReadEdif.obj +.\Release\ioReadEqn.obj +.\Release\ioReadPla.obj +.\Release\ioReadVerilog.obj +.\Release\ioUtil.obj +.\Release\ioWriteAiger.obj +.\Release\ioWriteBaf.obj +.\Release\ioWriteBench.obj +.\Release\ioWriteBlif.obj +.\Release\ioWriteBlifMv.obj +.\Release\ioWriteCnf.obj +.\Release\ioWriteDot.obj +.\Release\ioWriteEqn.obj +.\Release\ioWriteGml.obj +.\Release\ioWriteList.obj +.\Release\ioWritePla.obj +.\Release\ioWriteVerilog.obj +.\Release\libSupport.obj +.\Release\main.obj +.\Release\mainFrame.obj +.\Release\mainInit.obj +.\Release\mainUtils.obj +.\Release\verCore.obj +.\Release\verFormula.obj +.\Release\verParse.obj +.\Release\verStream.obj +.\Release\cuddAddAbs.obj +.\Release\cuddAddApply.obj +.\Release\cuddAddFind.obj +.\Release\cuddAddInv.obj +.\Release\cuddAddIte.obj +.\Release\cuddAddNeg.obj +.\Release\cuddAddWalsh.obj +.\Release\cuddAndAbs.obj +.\Release\cuddAnneal.obj +.\Release\cuddApa.obj +.\Release\cuddAPI.obj +.\Release\cuddApprox.obj +.\Release\cuddBddAbs.obj +.\Release\cuddBddCorr.obj +.\Release\cuddBddIte.obj +.\Release\cuddBridge.obj +.\Release\cuddCache.obj +.\Release\cuddCheck.obj +.\Release\cuddClip.obj +.\Release\cuddCof.obj +.\Release\cuddCompose.obj +.\Release\cuddDecomp.obj +.\Release\cuddEssent.obj +.\Release\cuddExact.obj +.\Release\cuddExport.obj +.\Release\cuddGenCof.obj +.\Release\cuddGenetic.obj +.\Release\cuddGroup.obj +.\Release\cuddHarwell.obj +.\Release\cuddInit.obj +.\Release\cuddInteract.obj +.\Release\cuddLCache.obj +.\Release\cuddLevelQ.obj +.\Release\cuddLinear.obj +.\Release\cuddLiteral.obj +.\Release\cuddMatMult.obj +.\Release\cuddPriority.obj +.\Release\cuddRead.obj +.\Release\cuddRef.obj +.\Release\cuddReorder.obj +.\Release\cuddSat.obj +.\Release\cuddSign.obj +.\Release\cuddSolve.obj +.\Release\cuddSplit.obj +.\Release\cuddSubsetHB.obj +.\Release\cuddSubsetSP.obj +.\Release\cuddSymmetry.obj +.\Release\cuddTable.obj +.\Release\cuddUtil.obj +.\Release\cuddWindow.obj +.\Release\cuddZddCount.obj +.\Release\cuddZddFuncs.obj +.\Release\cuddZddGroup.obj +.\Release\cuddZddIsop.obj +.\Release\cuddZddLin.obj +.\Release\cuddZddMisc.obj +.\Release\cuddZddPort.obj +.\Release\cuddZddReord.obj +.\Release\cuddZddSetop.obj +.\Release\cuddZddSymm.obj +.\Release\cuddZddUtil.obj +.\Release\epd.obj +.\Release\mtrBasic.obj +.\Release\mtrGroup.obj +.\Release\parseCore.obj +.\Release\parseEqn.obj +.\Release\parseStack.obj +.\Release\dsdApi.obj +.\Release\dsdCheck.obj +.\Release\dsdLocal.obj +.\Release\dsdMan.obj +.\Release\dsdProc.obj +.\Release\dsdTree.obj +.\Release\reoApi.obj +.\Release\reoCore.obj +.\Release\reoProfile.obj +.\Release\reoSift.obj +.\Release\reoSwap.obj +.\Release\reoTest.obj +.\Release\reoTransfer.obj +.\Release\reoUnits.obj +.\Release\casCore.obj +.\Release\casDec.obj +.\Release\msatActivity.obj +.\Release\msatClause.obj +.\Release\msatClauseVec.obj +.\Release\msatMem.obj +.\Release\msatOrderH.obj +.\Release\msatQueue.obj +.\Release\msatRead.obj +.\Release\msatSolverApi.obj +.\Release\msatSolverCore.obj +.\Release\msatSolverIo.obj +.\Release\msatSolverSearch.obj +.\Release\msatSort.obj +.\Release\msatVec.obj +.\Release\fraigApi.obj +.\Release\fraigCanon.obj +.\Release\fraigChoice.obj +.\Release\fraigFanout.obj +.\Release\fraigFeed.obj +.\Release\fraigMan.obj +.\Release\fraigMem.obj +.\Release\fraigNode.obj +.\Release\fraigPrime.obj +.\Release\fraigSat.obj +.\Release\fraigTable.obj +.\Release\fraigUtil.obj +.\Release\fraigVec.obj +.\Release\csat_apis.obj +.\Release\satInter.obj +.\Release\satMem.obj +.\Release\satSolver.obj +.\Release\satStore.obj +.\Release\satTrace.obj +.\Release\satUtil.obj +.\Release\pr.obj +.\Release\fxu.obj +.\Release\fxuCreate.obj +.\Release\fxuHeapD.obj +.\Release\fxuHeapS.obj +.\Release\fxuList.obj +.\Release\fxuMatrix.obj +.\Release\fxuPair.obj +.\Release\fxuPrint.obj +.\Release\fxuReduce.obj +.\Release\fxuSelect.obj +.\Release\fxuSingle.obj +.\Release\fxuUpdate.obj +.\Release\rwrDec.obj +.\Release\rwrEva.obj +.\Release\rwrExp.obj +.\Release\rwrLib.obj +.\Release\rwrMan.obj +.\Release\rwrPrint.obj +.\Release\rwrTemp.obj +.\Release\rwrUtil.obj +.\Release\cutApi.obj +.\Release\cutCut.obj +.\Release\cutExpand.obj +.\Release\cutMan.obj +.\Release\cutMerge.obj +.\Release\cutNode.obj +.\Release\cutOracle.obj +.\Release\cutPre22.obj +.\Release\cutSeq.obj +.\Release\cutTruth.obj +.\Release\decAbc.obj +.\Release\decFactor.obj +.\Release\decMan.obj +.\Release\decPrint.obj +.\Release\decUtil.obj +.\Release\simMan.obj +.\Release\simSat.obj +.\Release\simSeq.obj +.\Release\simSupp.obj +.\Release\simSwitch.obj +.\Release\simSym.obj +.\Release\simSymSat.obj +.\Release\simSymSim.obj +.\Release\simSymStr.obj +.\Release\simUtils.obj +.\Release\retArea.obj +.\Release\retCore.obj +.\Release\retDelay.obj +.\Release\retFlow.obj +.\Release\retIncrem.obj +.\Release\retInit.obj +.\Release\retLvalue.obj +.\Release\resCore.obj +.\Release\resDivs.obj +.\Release\resFilter.obj +.\Release\resSat.obj +.\Release\resSim.obj +.\Release\resStrash.obj +.\Release\resWin.obj +.\Release\lpkAbcDec.obj +.\Release\lpkAbcDsd.obj +.\Release\lpkAbcMux.obj +.\Release\lpkAbcUtil.obj +.\Release\lpkCore.obj +.\Release\lpkCut.obj +.\Release\lpkMan.obj +.\Release\lpkMap.obj +.\Release\lpkMulti.obj +.\Release\lpkMux.obj +.\Release\lpkSets.obj +.\Release\fpga.obj +.\Release\fpgaCore.obj +.\Release\fpgaCreate.obj +.\Release\fpgaCut.obj +.\Release\fpgaCutUtils.obj +.\Release\fpgaFanout.obj +.\Release\fpgaLib.obj +.\Release\fpgaMatch.obj +.\Release\fpgaSwitch.obj +.\Release\fpgaTime.obj +.\Release\fpgaTruth.obj +.\Release\fpgaUtils.obj +.\Release\fpgaVec.obj +.\Release\mapper.obj +.\Release\mapperCanon.obj +.\Release\mapperCore.obj +.\Release\mapperCreate.obj +.\Release\mapperCut.obj +.\Release\mapperCutUtils.obj +.\Release\mapperFanout.obj +.\Release\mapperLib.obj +.\Release\mapperMatch.obj +.\Release\mapperRefs.obj +.\Release\mapperSuper.obj +.\Release\mapperSwitch.obj +.\Release\mapperTable.obj +.\Release\mapperTime.obj +.\Release\mapperTree.obj +.\Release\mapperTruth.obj +.\Release\mapperUtils.obj +.\Release\mapperVec.obj +.\Release\mio.obj +.\Release\mioApi.obj +.\Release\mioFunc.obj +.\Release\mioRead.obj +.\Release\mioUtils.obj +.\Release\super.obj +.\Release\superAnd.obj +.\Release\superGate.obj +.\Release\superWrite.obj +.\Release\ifCore.obj +.\Release\ifCut.obj +.\Release\ifMan.obj +.\Release\ifMap.obj +.\Release\ifReduce.obj +.\Release\ifSeq.obj +.\Release\ifTime.obj +.\Release\ifTruth.obj +.\Release\ifUtil.obj +.\Release\extraBddAuto.obj +.\Release\extraBddCas.obj +.\Release\extraBddKmap.obj +.\Release\extraBddMisc.obj +.\Release\extraBddSymm.obj +.\Release\extraBddUnate.obj +.\Release\extraUtilBitMatrix.obj +.\Release\extraUtilCanon.obj +.\Release\extraUtilFile.obj +.\Release\extraUtilMemory.obj +.\Release\extraUtilMisc.obj +.\Release\extraUtilProgress.obj +.\Release\extraUtilReader.obj +.\Release\extraUtilTruth.obj +.\Release\extraUtilUtil.obj +.\Release\st.obj +.\Release\stmm.obj +.\Release\mvc.obj +.\Release\mvcApi.obj +.\Release\mvcCompare.obj +.\Release\mvcContain.obj +.\Release\mvcCover.obj +.\Release\mvcCube.obj +.\Release\mvcDivide.obj +.\Release\mvcDivisor.obj +.\Release\mvcList.obj +.\Release\mvcLits.obj +.\Release\mvcMan.obj +.\Release\mvcOpAlg.obj +.\Release\mvcOpBool.obj +.\Release\mvcPrint.obj +.\Release\mvcSort.obj +.\Release\mvcUtils.obj +.\Release\cofactor.obj +.\Release\cols.obj +.\Release\compl.obj +.\Release\contain.obj +.\Release\cubehack.obj +.\Release\cubestr.obj +.\Release\cvrin.obj +.\Release\cvrm.obj +.\Release\cvrmisc.obj +.\Release\cvrout.obj +.\Release\dominate.obj +.\Release\equiv.obj +.\Release\espresso.obj +.\Release\essen.obj +.\Release\exact.obj +.\Release\expand.obj +.\Release\gasp.obj +.\Release\gimpel.obj +.\Release\globals.obj +.\Release\hack.obj +.\Release\indep.obj +.\Release\irred.obj +.\Release\map.obj +.\Release\matrix.obj +.\Release\mincov.obj +.\Release\opo.obj +.\Release\pair.obj +.\Release\part.obj +.\Release\primes.obj +.\Release\reduce.obj +.\Release\rows.obj +.\Release\set.obj +.\Release\setc.obj +.\Release\sharp.obj +.\Release\sminterf.obj +.\Release\solution.obj +.\Release\sparse.obj +.\Release\unate.obj +.\Release\verify.obj +.\Release\nmApi.obj +.\Release\nmTable.obj +.\Release\hopBalance.obj +.\Release\hopCheck.obj +.\Release\hopDfs.obj +.\Release\hopMan.obj +.\Release\hopMem.obj +.\Release\hopObj.obj +.\Release\hopOper.obj +.\Release\hopTable.obj +.\Release\hopUtil.obj +.\Release\ivyBalance.obj +.\Release\ivyCanon.obj +.\Release\ivyCheck.obj +.\Release\ivyCut.obj +.\Release\ivyCutTrav.obj +.\Release\ivyDfs.obj +.\Release\ivyDsd.obj +.\Release\ivyFanout.obj +.\Release\ivyFastMap.obj +.\Release\ivyFraig.obj +.\Release\ivyHaig.obj +.\Release\ivyMan.obj +.\Release\ivyMem.obj +.\Release\ivyMulti.obj +.\Release\ivyObj.obj +.\Release\ivyOper.obj +.\Release\ivyResyn.obj +.\Release\ivyRwr.obj +.\Release\ivySeq.obj +.\Release\ivyShow.obj +.\Release\ivyTable.obj +.\Release\ivyUtil.obj +.\Release\rwtDec.obj +.\Release\rwtMan.obj +.\Release\rwtUtil.obj +.\Release\mem.obj +.\Release\ioaReadAig.obj +.\Release\ioaUtil.obj +.\Release\ioaWriteAig.obj +.\Release\darBalance.obj +.\Release\darCore.obj +.\Release\darCut.obj +.\Release\darData.obj +.\Release\darLib.obj +.\Release\darMan.obj +.\Release\darPrec.obj +.\Release\darRefact.obj +.\Release\darResub.obj +.\Release\darScript.obj +.\Release\fraBmc.obj +.\Release\fraCec.obj +.\Release\fraClass.obj +.\Release\fraCnf.obj +.\Release\fraCore.obj +.\Release\fraImp.obj +.\Release\fraInd.obj +.\Release\fraLcr.obj +.\Release\fraMan.obj +.\Release\fraPart.obj +.\Release\fraSat.obj +.\Release\fraSec.obj +.\Release\fraSim.obj +.\Release\cnfCore.obj +.\Release\cnfCut.obj +.\Release\cnfData.obj +.\Release\cnfMan.obj +.\Release\cnfMap.obj +.\Release\cnfPost.obj +.\Release\cnfUtil.obj +.\Release\cnfWrite.obj +.\Release\cswCore.obj +.\Release\cswCut.obj +.\Release\cswMan.obj +.\Release\cswTable.obj +.\Release\cloud.obj +.\Release\kitAig.obj +.\Release\kitBdd.obj +.\Release\kitCloud.obj +.\Release\kitDsd.obj +.\Release\kitFactor.obj +.\Release\kitGraph.obj +.\Release\kitHop.obj +.\Release\kitIsop.obj +.\Release\kitSop.obj +.\Release\kitTruth.obj +.\Release\bdcCore.obj +.\Release\bdcDec.obj +.\Release\bdcTable.obj +.\Release\aigCheck.obj +.\Release\aigDfs.obj +.\Release\aigFanout.obj +.\Release\aigMan.obj +.\Release\aigMem.obj +.\Release\aigMffc.obj +.\Release\aigObj.obj +.\Release\aigOper.obj +.\Release\aigOrder.obj +.\Release\aigPart.obj +.\Release\aigRepr.obj +.\Release\aigRet.obj +.\Release\aigScl.obj +.\Release\aigSeq.obj +.\Release\aigShow.obj +.\Release\aigTable.obj +.\Release\aigTime.obj +.\Release\aigTiming.obj +.\Release\aigTruth.obj +.\Release\aigTsim.obj +.\Release\aigUtil.obj +.\Release\aigWin.obj +.\Release\bar.obj +] +Creating command line "link.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP2087.tmp" +

Output Window

+Compiling... +abc.c +Linking... +Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP2089.tmp" with contents +[ +/nologo /o"Release/abc.bsc" +.\Release\abcAig.sbr +.\Release\abcBlifMv.sbr +.\Release\abcCheck.sbr +.\Release\abcDfs.sbr +.\Release\abcFanio.sbr +.\Release\abcFunc.sbr +.\Release\abcHie.sbr +.\Release\abcLatch.sbr +.\Release\abcLib.sbr +.\Release\abcMinBase.sbr +.\Release\abcNames.sbr +.\Release\abcNetlist.sbr +.\Release\abcNtk.sbr +.\Release\abcObj.sbr +.\Release\abcRefs.sbr +.\Release\abcShow.sbr +.\Release\abcSop.sbr +.\Release\abcUtil.sbr +.\Release\abc.sbr +.\Release\abcAttach.sbr +.\Release\abcAuto.sbr +.\Release\abcBalance.sbr +.\Release\abcBmc.sbr +.\Release\abcCas.sbr +.\Release\abcClpBdd.sbr +.\Release\abcClpSop.sbr +.\Release\abcCut.sbr +.\Release\abcDar.sbr +.\Release\abcDebug.sbr +.\Release\abcDress.sbr +.\Release\abcDsd.sbr +.\Release\abcEspresso.sbr +.\Release\abcExtract.sbr +.\Release\abcFpga.sbr +.\Release\abcFpgaFast.sbr +.\Release\abcFraig.sbr +.\Release\abcFxu.sbr +.\Release\abcGen.sbr +.\Release\abcHaig.sbr +.\Release\abcIf.sbr +.\Release\abcIvy.sbr +.\Release\abcLut.sbr +.\Release\abcMap.sbr +.\Release\abcMeasure.sbr +.\Release\abcMini.sbr +.\Release\abcMiter.sbr +.\Release\abcMulti.sbr +.\Release\abcMv.sbr +.\Release\abcNtbdd.sbr +.\Release\abcOdc.sbr +.\Release\abcOrder.sbr +.\Release\abcPart.sbr +.\Release\abcPrint.sbr +.\Release\abcProve.sbr +.\Release\abcQbf.sbr +.\Release\abcQuant.sbr +.\Release\abcRec.sbr +.\Release\abcReconv.sbr +.\Release\abcRefactor.sbr +.\Release\abcRenode.sbr +.\Release\abcReorder.sbr +.\Release\abcRestruct.sbr +.\Release\abcResub.sbr +.\Release\abcRewrite.sbr +.\Release\abcRr.sbr +.\Release\abcSat.sbr +.\Release\abcStrash.sbr +.\Release\abcSweep.sbr +.\Release\abcSymm.sbr +.\Release\abcTiming.sbr +.\Release\abcUnate.sbr +.\Release\abcUnreach.sbr +.\Release\abcVerify.sbr +.\Release\abcXsim.sbr +.\Release\cmd.sbr +.\Release\cmdAlias.sbr +.\Release\cmdApi.sbr +.\Release\cmdFlag.sbr +.\Release\cmdHist.sbr +.\Release\cmdUtils.sbr +.\Release\io.sbr +.\Release\ioReadAiger.sbr +.\Release\ioReadBaf.sbr +.\Release\ioReadBench.sbr +.\Release\ioReadBlif.sbr +.\Release\ioReadBlifAig.sbr +.\Release\ioReadBlifMv.sbr +.\Release\ioReadDsd.sbr +.\Release\ioReadEdif.sbr +.\Release\ioReadEqn.sbr +.\Release\ioReadPla.sbr +.\Release\ioReadVerilog.sbr +.\Release\ioUtil.sbr +.\Release\ioWriteAiger.sbr +.\Release\ioWriteBaf.sbr +.\Release\ioWriteBench.sbr +.\Release\ioWriteBlif.sbr +.\Release\ioWriteBlifMv.sbr +.\Release\ioWriteCnf.sbr +.\Release\ioWriteDot.sbr +.\Release\ioWriteEqn.sbr +.\Release\ioWriteGml.sbr +.\Release\ioWriteList.sbr +.\Release\ioWritePla.sbr +.\Release\ioWriteVerilog.sbr +.\Release\libSupport.sbr +.\Release\main.sbr +.\Release\mainFrame.sbr +.\Release\mainInit.sbr +.\Release\mainUtils.sbr +.\Release\verCore.sbr +.\Release\verFormula.sbr +.\Release\verParse.sbr +.\Release\verStream.sbr +.\Release\cuddAddAbs.sbr +.\Release\cuddAddApply.sbr +.\Release\cuddAddFind.sbr +.\Release\cuddAddInv.sbr +.\Release\cuddAddIte.sbr +.\Release\cuddAddNeg.sbr +.\Release\cuddAddWalsh.sbr +.\Release\cuddAndAbs.sbr +.\Release\cuddAnneal.sbr +.\Release\cuddApa.sbr +.\Release\cuddAPI.sbr +.\Release\cuddApprox.sbr +.\Release\cuddBddAbs.sbr +.\Release\cuddBddCorr.sbr +.\Release\cuddBddIte.sbr +.\Release\cuddBridge.sbr +.\Release\cuddCache.sbr +.\Release\cuddCheck.sbr +.\Release\cuddClip.sbr +.\Release\cuddCof.sbr +.\Release\cuddCompose.sbr +.\Release\cuddDecomp.sbr +.\Release\cuddEssent.sbr +.\Release\cuddExact.sbr +.\Release\cuddExport.sbr +.\Release\cuddGenCof.sbr +.\Release\cuddGenetic.sbr +.\Release\cuddGroup.sbr +.\Release\cuddHarwell.sbr +.\Release\cuddInit.sbr +.\Release\cuddInteract.sbr +.\Release\cuddLCache.sbr +.\Release\cuddLevelQ.sbr +.\Release\cuddLinear.sbr +.\Release\cuddLiteral.sbr +.\Release\cuddMatMult.sbr +.\Release\cuddPriority.sbr +.\Release\cuddRead.sbr +.\Release\cuddRef.sbr +.\Release\cuddReorder.sbr +.\Release\cuddSat.sbr +.\Release\cuddSign.sbr +.\Release\cuddSolve.sbr +.\Release\cuddSplit.sbr +.\Release\cuddSubsetHB.sbr +.\Release\cuddSubsetSP.sbr +.\Release\cuddSymmetry.sbr +.\Release\cuddTable.sbr +.\Release\cuddUtil.sbr +.\Release\cuddWindow.sbr +.\Release\cuddZddCount.sbr +.\Release\cuddZddFuncs.sbr +.\Release\cuddZddGroup.sbr +.\Release\cuddZddIsop.sbr +.\Release\cuddZddLin.sbr +.\Release\cuddZddMisc.sbr +.\Release\cuddZddPort.sbr +.\Release\cuddZddReord.sbr +.\Release\cuddZddSetop.sbr +.\Release\cuddZddSymm.sbr +.\Release\cuddZddUtil.sbr +.\Release\epd.sbr +.\Release\mtrBasic.sbr +.\Release\mtrGroup.sbr +.\Release\parseCore.sbr +.\Release\parseEqn.sbr +.\Release\parseStack.sbr +.\Release\dsdApi.sbr +.\Release\dsdCheck.sbr +.\Release\dsdLocal.sbr +.\Release\dsdMan.sbr +.\Release\dsdProc.sbr +.\Release\dsdTree.sbr +.\Release\reoApi.sbr +.\Release\reoCore.sbr +.\Release\reoProfile.sbr +.\Release\reoSift.sbr +.\Release\reoSwap.sbr +.\Release\reoTest.sbr +.\Release\reoTransfer.sbr +.\Release\reoUnits.sbr +.\Release\casCore.sbr +.\Release\casDec.sbr +.\Release\msatActivity.sbr +.\Release\msatClause.sbr +.\Release\msatClauseVec.sbr +.\Release\msatMem.sbr +.\Release\msatOrderH.sbr +.\Release\msatQueue.sbr +.\Release\msatRead.sbr +.\Release\msatSolverApi.sbr +.\Release\msatSolverCore.sbr +.\Release\msatSolverIo.sbr +.\Release\msatSolverSearch.sbr +.\Release\msatSort.sbr +.\Release\msatVec.sbr +.\Release\fraigApi.sbr +.\Release\fraigCanon.sbr +.\Release\fraigChoice.sbr +.\Release\fraigFanout.sbr +.\Release\fraigFeed.sbr +.\Release\fraigMan.sbr +.\Release\fraigMem.sbr +.\Release\fraigNode.sbr +.\Release\fraigPrime.sbr +.\Release\fraigSat.sbr +.\Release\fraigTable.sbr +.\Release\fraigUtil.sbr +.\Release\fraigVec.sbr +.\Release\csat_apis.sbr +.\Release\satInter.sbr +.\Release\satMem.sbr +.\Release\satSolver.sbr +.\Release\satStore.sbr +.\Release\satTrace.sbr +.\Release\satUtil.sbr +.\Release\pr.sbr +.\Release\fxu.sbr +.\Release\fxuCreate.sbr +.\Release\fxuHeapD.sbr +.\Release\fxuHeapS.sbr +.\Release\fxuList.sbr +.\Release\fxuMatrix.sbr +.\Release\fxuPair.sbr +.\Release\fxuPrint.sbr +.\Release\fxuReduce.sbr +.\Release\fxuSelect.sbr +.\Release\fxuSingle.sbr +.\Release\fxuUpdate.sbr +.\Release\rwrDec.sbr +.\Release\rwrEva.sbr +.\Release\rwrExp.sbr +.\Release\rwrLib.sbr +.\Release\rwrMan.sbr +.\Release\rwrPrint.sbr +.\Release\rwrTemp.sbr +.\Release\rwrUtil.sbr +.\Release\cutApi.sbr +.\Release\cutCut.sbr +.\Release\cutExpand.sbr +.\Release\cutMan.sbr +.\Release\cutMerge.sbr +.\Release\cutNode.sbr +.\Release\cutOracle.sbr +.\Release\cutPre22.sbr +.\Release\cutSeq.sbr +.\Release\cutTruth.sbr +.\Release\decAbc.sbr +.\Release\decFactor.sbr +.\Release\decMan.sbr +.\Release\decPrint.sbr +.\Release\decUtil.sbr +.\Release\simMan.sbr +.\Release\simSat.sbr +.\Release\simSeq.sbr +.\Release\simSupp.sbr +.\Release\simSwitch.sbr +.\Release\simSym.sbr +.\Release\simSymSat.sbr +.\Release\simSymSim.sbr +.\Release\simSymStr.sbr +.\Release\simUtils.sbr +.\Release\retArea.sbr +.\Release\retCore.sbr +.\Release\retDelay.sbr +.\Release\retFlow.sbr +.\Release\retIncrem.sbr +.\Release\retInit.sbr +.\Release\retLvalue.sbr +.\Release\resCore.sbr +.\Release\resDivs.sbr +.\Release\resFilter.sbr +.\Release\resSat.sbr +.\Release\resSim.sbr +.\Release\resStrash.sbr +.\Release\resWin.sbr +.\Release\lpkAbcDec.sbr +.\Release\lpkAbcDsd.sbr +.\Release\lpkAbcMux.sbr +.\Release\lpkAbcUtil.sbr +.\Release\lpkCore.sbr +.\Release\lpkCut.sbr +.\Release\lpkMan.sbr +.\Release\lpkMap.sbr +.\Release\lpkMulti.sbr +.\Release\lpkMux.sbr +.\Release\lpkSets.sbr +.\Release\fpga.sbr +.\Release\fpgaCore.sbr +.\Release\fpgaCreate.sbr +.\Release\fpgaCut.sbr +.\Release\fpgaCutUtils.sbr +.\Release\fpgaFanout.sbr +.\Release\fpgaLib.sbr +.\Release\fpgaMatch.sbr +.\Release\fpgaSwitch.sbr +.\Release\fpgaTime.sbr +.\Release\fpgaTruth.sbr +.\Release\fpgaUtils.sbr +.\Release\fpgaVec.sbr +.\Release\mapper.sbr +.\Release\mapperCanon.sbr +.\Release\mapperCore.sbr +.\Release\mapperCreate.sbr +.\Release\mapperCut.sbr +.\Release\mapperCutUtils.sbr +.\Release\mapperFanout.sbr +.\Release\mapperLib.sbr +.\Release\mapperMatch.sbr +.\Release\mapperRefs.sbr +.\Release\mapperSuper.sbr +.\Release\mapperSwitch.sbr +.\Release\mapperTable.sbr +.\Release\mapperTime.sbr +.\Release\mapperTree.sbr +.\Release\mapperTruth.sbr +.\Release\mapperUtils.sbr +.\Release\mapperVec.sbr +.\Release\mio.sbr +.\Release\mioApi.sbr +.\Release\mioFunc.sbr +.\Release\mioRead.sbr +.\Release\mioUtils.sbr +.\Release\super.sbr +.\Release\superAnd.sbr +.\Release\superGate.sbr +.\Release\superWrite.sbr +.\Release\ifCore.sbr +.\Release\ifCut.sbr +.\Release\ifMan.sbr +.\Release\ifMap.sbr +.\Release\ifReduce.sbr +.\Release\ifSeq.sbr +.\Release\ifTime.sbr +.\Release\ifTruth.sbr +.\Release\ifUtil.sbr +.\Release\extraBddAuto.sbr +.\Release\extraBddCas.sbr +.\Release\extraBddKmap.sbr +.\Release\extraBddMisc.sbr +.\Release\extraBddSymm.sbr +.\Release\extraBddUnate.sbr +.\Release\extraUtilBitMatrix.sbr +.\Release\extraUtilCanon.sbr +.\Release\extraUtilFile.sbr +.\Release\extraUtilMemory.sbr +.\Release\extraUtilMisc.sbr +.\Release\extraUtilProgress.sbr +.\Release\extraUtilReader.sbr +.\Release\extraUtilTruth.sbr +.\Release\extraUtilUtil.sbr +.\Release\st.sbr +.\Release\stmm.sbr +.\Release\mvc.sbr +.\Release\mvcApi.sbr +.\Release\mvcCompare.sbr +.\Release\mvcContain.sbr +.\Release\mvcCover.sbr +.\Release\mvcCube.sbr +.\Release\mvcDivide.sbr +.\Release\mvcDivisor.sbr +.\Release\mvcList.sbr +.\Release\mvcLits.sbr +.\Release\mvcMan.sbr +.\Release\mvcOpAlg.sbr +.\Release\mvcOpBool.sbr +.\Release\mvcPrint.sbr +.\Release\mvcSort.sbr +.\Release\mvcUtils.sbr +.\Release\cofactor.sbr +.\Release\cols.sbr +.\Release\compl.sbr +.\Release\contain.sbr +.\Release\cubehack.sbr +.\Release\cubestr.sbr +.\Release\cvrin.sbr +.\Release\cvrm.sbr +.\Release\cvrmisc.sbr +.\Release\cvrout.sbr +.\Release\dominate.sbr +.\Release\equiv.sbr +.\Release\espresso.sbr +.\Release\essen.sbr +.\Release\exact.sbr +.\Release\expand.sbr +.\Release\gasp.sbr +.\Release\gimpel.sbr +.\Release\globals.sbr +.\Release\hack.sbr +.\Release\indep.sbr +.\Release\irred.sbr +.\Release\map.sbr +.\Release\matrix.sbr +.\Release\mincov.sbr +.\Release\opo.sbr +.\Release\pair.sbr +.\Release\part.sbr +.\Release\primes.sbr +.\Release\reduce.sbr +.\Release\rows.sbr +.\Release\set.sbr +.\Release\setc.sbr +.\Release\sharp.sbr +.\Release\sminterf.sbr +.\Release\solution.sbr +.\Release\sparse.sbr +.\Release\unate.sbr +.\Release\verify.sbr +.\Release\nmApi.sbr +.\Release\nmTable.sbr +.\Release\hopBalance.sbr +.\Release\hopCheck.sbr +.\Release\hopDfs.sbr +.\Release\hopMan.sbr +.\Release\hopMem.sbr +.\Release\hopObj.sbr +.\Release\hopOper.sbr +.\Release\hopTable.sbr +.\Release\hopUtil.sbr +.\Release\ivyBalance.sbr +.\Release\ivyCanon.sbr +.\Release\ivyCheck.sbr +.\Release\ivyCut.sbr +.\Release\ivyCutTrav.sbr +.\Release\ivyDfs.sbr +.\Release\ivyDsd.sbr +.\Release\ivyFanout.sbr +.\Release\ivyFastMap.sbr +.\Release\ivyFraig.sbr +.\Release\ivyHaig.sbr +.\Release\ivyMan.sbr +.\Release\ivyMem.sbr +.\Release\ivyMulti.sbr +.\Release\ivyObj.sbr +.\Release\ivyOper.sbr +.\Release\ivyResyn.sbr +.\Release\ivyRwr.sbr +.\Release\ivySeq.sbr +.\Release\ivyShow.sbr +.\Release\ivyTable.sbr +.\Release\ivyUtil.sbr +.\Release\rwtDec.sbr +.\Release\rwtMan.sbr +.\Release\rwtUtil.sbr +.\Release\mem.sbr +.\Release\ioaReadAig.sbr +.\Release\ioaUtil.sbr +.\Release\ioaWriteAig.sbr +.\Release\darBalance.sbr +.\Release\darCore.sbr +.\Release\darCut.sbr +.\Release\darData.sbr +.\Release\darLib.sbr +.\Release\darMan.sbr +.\Release\darPrec.sbr +.\Release\darRefact.sbr +.\Release\darResub.sbr +.\Release\darScript.sbr +.\Release\fraBmc.sbr +.\Release\fraCec.sbr +.\Release\fraClass.sbr +.\Release\fraCnf.sbr +.\Release\fraCore.sbr +.\Release\fraImp.sbr +.\Release\fraInd.sbr +.\Release\fraLcr.sbr +.\Release\fraMan.sbr +.\Release\fraPart.sbr +.\Release\fraSat.sbr +.\Release\fraSec.sbr +.\Release\fraSim.sbr +.\Release\cnfCore.sbr +.\Release\cnfCut.sbr +.\Release\cnfData.sbr +.\Release\cnfMan.sbr +.\Release\cnfMap.sbr +.\Release\cnfPost.sbr +.\Release\cnfUtil.sbr +.\Release\cnfWrite.sbr +.\Release\cswCore.sbr +.\Release\cswCut.sbr +.\Release\cswMan.sbr +.\Release\cswTable.sbr +.\Release\cloud.sbr +.\Release\kitAig.sbr +.\Release\kitBdd.sbr +.\Release\kitCloud.sbr +.\Release\kitDsd.sbr +.\Release\kitFactor.sbr +.\Release\kitGraph.sbr +.\Release\kitHop.sbr +.\Release\kitIsop.sbr +.\Release\kitSop.sbr +.\Release\kitTruth.sbr +.\Release\bdcCore.sbr +.\Release\bdcDec.sbr +.\Release\bdcTable.sbr +.\Release\aigCheck.sbr +.\Release\aigDfs.sbr +.\Release\aigFanout.sbr +.\Release\aigMan.sbr +.\Release\aigMem.sbr +.\Release\aigMffc.sbr +.\Release\aigObj.sbr +.\Release\aigOper.sbr +.\Release\aigOrder.sbr +.\Release\aigPart.sbr +.\Release\aigRepr.sbr +.\Release\aigRet.sbr +.\Release\aigScl.sbr +.\Release\aigSeq.sbr +.\Release\aigShow.sbr +.\Release\aigTable.sbr +.\Release\aigTime.sbr +.\Release\aigTiming.sbr +.\Release\aigTruth.sbr +.\Release\aigTsim.sbr +.\Release\aigUtil.sbr +.\Release\aigWin.sbr +.\Release\bar.sbr] +Creating command line "bscmake.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP2089.tmp" +Creating browse info file... +

Output Window

+ + + +

Results

+abc.exe - 0 error(s), 0 warning(s) +
+ + diff --git a/abc70930/abc.rc b/abc70930/abc.rc new file mode 100644 index 00000000..a76cc04f --- /dev/null +++ b/abc70930/abc.rc @@ -0,0 +1,124 @@ +# global parameters +set check # checks intermediate networks +#set checkfio # prints warnings when fanins/fanouts are duplicated +set checkread # checks new networks after reading from file +set backup # saves backup networks retrived by "undo" and "recall" +set savesteps 1 # sets the maximum number of backup networks to save +set progressbar # display the progress bar + +# program names for internal calls +set dotwin dot.exe +set dotunix dot +set gsviewwin gsview32.exe +set gsviewunix gv +set siswin sis.exe +set sisunix sis +set mvsiswin mvsis.exe +set mvsisunix mvsis +set capowin MetaPl-Capo10.1-Win32.exe +set capounix MetaPl-Capo10.1 +set gnuplotwin wgnuplot.exe +set gnuplotunix gnuplot + +# standard aliases +alias b balance +alias cl cleanup +alias clp collapse +alias esd ext_seq_dcs +alias f fraig +alias fs fraig_sweep +alias fsto fraig_store +alias fres fraig_restore +alias ft fraig_trust +alias lp lutpack +alias pd print_dsd +alias pex print_exdc -d +alias pf print_factor +alias pfan print_fanio +alias pl print_level +alias pio print_io +alias pk print_kmap +alias ps print_stats +alias psu print_supp +alias psy print_symm +alias pun print_unate +alias q quit +alias r read +alias r3 retime -M 3 +alias r3f retime -M 3 -f +alias r3b retime -M 3 -b +alias ren renode +alias rh read_hie +alias rl read_blif +alias rb read_bench +alias ret retime +alias rp read_pla +alias rt read_truth +alias rv read_verilog +alias rvl read_verlib +alias rsup read_super mcnc5_old.super +alias rlib read_library +alias rlibc read_library cadence.genlib +alias rw rewrite +alias rwz rewrite -z +alias rf refactor +alias rfz refactor -z +alias re restructure +alias rez restructure -z +alias rs resub +alias rsz resub -z +alias sa set autoexec ps +alias scl scleanup +alias sif if -s +alias so source -x +alias st strash +alias sw sweep +alias ssw ssweep +alias tr0 trace_start +alias tr1 trace_check +alias trt "r c.blif; st; tr0; b; tr1" +alias u undo +alias w write +alias wa write_aiger +alias wb write_bench +alias wc write_cnf +alias wh write_hie +alias wl write_blif +alias wp write_pla +alias wv write_verilog + +# standard scripts +alias resyn "b; rw; rwz; b; rwz; b" +alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" +alias resyn2a "b; rw; b; rw; rwz; b; rwz; b" +alias resyn3 "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b" +alias compress "b -l; rw -l; rwz -l; b -l; rwz -l; b -l" +alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l" +alias choice "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore" +alias choice2 "fraig_store; balance; fraig_store; resyn; fraig_store; resyn2; fraig_store; resyn2; fraig_store; fraig_restore" +alias rwsat "st; rw -l; b -l; rw -l; rf -l" +alias rwsat2 "st; rw -l; b -l; rw -l; rf -l; fraig; rw -l; b -l; rw -l; rf -l" +alias shake "st; ps; sat -C 5000; rw -l; ps; sat -C 5000; b -l; rf -l; ps; sat -C 5000; rfz -l; ps; sat -C 5000; rwz -l; ps; sat -C 5000; rfz -l; ps; sat -C 5000" +alias share "st; multi -m; fx; resyn2" + +# resubstitution scripts for the IWLS paper +alias src_rw "st; rw -l; rwz -l; rwz -l" +alias src_rs "st; rs -K 6 -N 2 -l; rs -K 9 -N 2 -l; rs -K 12 -N 2 -l" +alias src_rws "st; rw -l; rs -K 6 -N 2 -l; rwz -l; rs -K 9 -N 2 -l; rwz -l; rs -K 12 -N 2 -l" +alias resyn2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b" +alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l" + +# experimental implementation of don't-cares +alias resyn2rsdc "b; rs -K 6 -F 2; rw; rs -K 6 -N 2 -F 2; rf; rs -K 8 -F 2; b; rs -K 8 -N 2 -F 2; rw; rs -K 10 -F 2; rwz; rs -K 10 -N 2 -F 2; b; rs -K 12 -F 2; rfz; rs -K 12 -N 2 -F 2; rwz; b" +alias compress2rsdc "b -l; rs -K 6 -F 2 -l; rw -l; rs -K 6 -N 2 -F 2 -l; rf -l; rs -K 8 -F 2 -l; b -l; rs -K 8 -N 2 -F 2 -l; rw -l; rs -K 10 -F 2 -l; rwz -l; rs -K 10 -N 2 -F 2 -l; b -l; rs -K 12 -F 2 -l; rfz -l; rs -K 12 -N 2 -F 2 -l; rwz -l; b -l" + +# temporaries +alias reach "st; ps; compress2; ps; qrel; ps; compress2; ps; qreach -v; ps" +alias chnew "st; haig_start; resyn2; haig_use" +alias chnewrs "st; haig_start; resyn2rs; haig_use" +alias stdsd "r test/6in.blif; st; ps; u; bdd; dsd -g; st; ps" +alias trec "rec_start; r c.blif; st; rec_add; rec_use" +alias trec4 "rec_start -K 4; r i10.blif; st; rec_add; rec_use" +alias bmc "frames -i -F 10; orpos; iprove" + + diff --git a/abc70930/abclib.dsp b/abc70930/abclib.dsp new file mode 100644 index 00000000..b9b88a15 --- /dev/null +++ b/abc70930/abclib.dsp @@ -0,0 +1,2844 @@ +# Microsoft Developer Studio Project File - Name="abclib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=abclib - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "abclib.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "abclib.mak" CFG="abclib - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "abclib - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "abclib - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "abclib - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "abclib___Win32_Release" +# PROP BASE Intermediate_Dir "abclib___Win32_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "abclib\ReleaseLib" +# PROP Intermediate_Dir "abclib\ReleaseLib" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"abclib\abclib_release.lib" + +!ELSEIF "$(CFG)" == "abclib - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "abclib___Win32_Debug" +# PROP BASE Intermediate_Dir "abclib___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "abclib\DebugLib" +# PROP Intermediate_Dir "abclib\DebugLib" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"abclib\abclib_debug.lib" + +!ENDIF + +# Begin Target + +# Name "abclib - Win32 Release" +# Name "abclib - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "base" + +# PROP Default_Filter "" +# Begin Group "abc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\abc\abc.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcBlifMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcFanio.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcFunc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcHie.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcLatch.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcMinBase.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcNames.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcNetlist.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcNtk.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcRefs.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcSop.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcUtil.c +# End Source File +# End Group +# Begin Group "abci" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\abci\abc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcAttach.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcAuto.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcBmc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcCas.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcClpBdd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcClpSop.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDar.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDebug.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDress.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcEspresso.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcExtract.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcFpga.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcFpgaFast.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcFraig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcFxu.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcGen.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcHaig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcIf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcIvy.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcLut.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMeasure.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMini.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMiter.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMulti.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcNtbdd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcOdc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcOrder.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcPart.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcProve.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcQbf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcQuant.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRec.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcReconv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRefactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRenode.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcReorder.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRestruct.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcResub.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRewrite.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRr.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcStrash.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSweep.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSymm.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcTiming.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcUnate.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcUnreach.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcVerify.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcXsim.c +# End Source File +# End Group +# Begin Group "cmd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\cmd\cmd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmd.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdAlias.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdFlag.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdHist.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdUtils.c +# End Source File +# End Group +# Begin Group "io" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\io\io.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\io.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadAiger.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBaf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBench.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBlif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBlifAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBlifMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadEdif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadEqn.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadPla.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadVerilog.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteAiger.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBaf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBench.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBlif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBlifMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteDot.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteEqn.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteGml.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteList.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWritePla.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteVerilog.c +# End Source File +# End Group +# Begin Group "main" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\main\libSupport.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\main.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\main.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainFrame.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainInit.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainUtils.c +# End Source File +# End Group +# Begin Group "ver" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\ver\ver.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verFormula.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verParse.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verStream.c +# End Source File +# End Group +# End Group +# Begin Group "bdd" + +# PROP Default_Filter "" +# Begin Group "cudd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\cudd\cudd.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddAbs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddApply.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddFind.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddInv.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddIte.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddNeg.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddWalsh.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAndAbs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAnneal.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddApa.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAPI.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddApprox.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBddAbs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBddCorr.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBddIte.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBridge.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCache.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddClip.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCof.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCompose.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddDecomp.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddEssent.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddExact.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddExport.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddGenCof.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddGenetic.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddGroup.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddHarwell.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddInit.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddInteract.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLCache.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLevelQ.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLinear.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLiteral.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddMatMult.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddPriority.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddRef.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddReorder.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSign.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSolve.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSplit.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSubsetHB.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSubsetSP.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSymmetry.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddWindow.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddCount.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddFuncs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddGroup.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddIsop.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddLin.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddMisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddPort.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddReord.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddSetop.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddSymm.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddUtil.c +# End Source File +# End Group +# Begin Group "epd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\epd\epd.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\epd\epd.h +# End Source File +# End Group +# Begin Group "mtr" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtr.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtrBasic.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtrGroup.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtrInt.h +# End Source File +# End Group +# Begin Group "parse" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\parse\parse.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\parse\parseCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\parse\parseEqn.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\parse\parseInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\parse\parseStack.c +# End Source File +# End Group +# Begin Group "dsd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsd.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdLocal.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdProc.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdTree.c +# End Source File +# End Group +# Begin Group "reo" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\reo\reo.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoProfile.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoSift.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoSwap.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoTest.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoTransfer.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoUnits.c +# End Source File +# End Group +# Begin Group "cas" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\cas\cas.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cas\casCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cas\casDec.c +# End Source File +# End Group +# End Group +# Begin Group "sat" + +# PROP Default_Filter "" +# Begin Group "msat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\msat\msat.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatActivity.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatClause.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatClauseVec.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatOrderH.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatQueue.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverIo.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverSearch.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSort.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatVec.c +# End Source File +# End Group +# Begin Group "fraig" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\fraig\fraig.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigChoice.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigFeed.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigNode.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigPrime.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\fraig\fraigVec.c +# End Source File +# End Group +# Begin Group "csat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\csat\csat_apis.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\csat\csat_apis.h +# End Source File +# End Group +# Begin Group "bsat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\bsat\satInter.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satMem.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satSolver.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satSolver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satStore.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satStore.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satTrace.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satVec.h +# End Source File +# End Group +# Begin Group "proof" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\proof\pr.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\proof\pr.h +# End Source File +# End Group +# End Group +# Begin Group "opt" + +# PROP Default_Filter "" +# Begin Group "fxu" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\fxu\fxu.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxu.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuCreate.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuHeapD.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuHeapS.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuList.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuMatrix.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuPair.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuReduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuSelect.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuSingle.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuUpdate.c +# End Source File +# End Group +# Begin Group "rwr" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\rwr\rwr.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrEva.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrExp.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrTemp.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrUtil.c +# End Source File +# End Group +# Begin Group "cut" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\cut\cut.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutExpand.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutList.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutMerge.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutNode.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutOracle.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutPre22.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutTruth.c +# End Source File +# End Group +# Begin Group "dec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\dec\dec.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dec\decAbc.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dec\decFactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dec\decMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dec\decPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dec\decUtil.c +# End Source File +# End Group +# Begin Group "sim" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\sim\sim.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSupp.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSwitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSym.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSymSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSymSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSymStr.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simUtils.c +# End Source File +# End Group +# Begin Group "ret" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\ret\retArea.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retDelay.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retFlow.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retIncrem.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retInit.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retLvalue.c +# End Source File +# End Group +# Begin Group "res" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\res\res.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resDivs.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resFilter.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resStrash.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resWin.c +# End Source File +# End Group +# Begin Group "lpk" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\lpk\lpk.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcMux.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMulti.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMux.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkSets.c +# End Source File +# End Group +# End Group +# Begin Group "map" + +# PROP Default_Filter "" +# Begin Group "fpga" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\fpga\fpga.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpga.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaCreate.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaCutUtils.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaMatch.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaSwitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaUtils.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\fpga\fpgaVec.c +# End Source File +# End Group +# Begin Group "mapper" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\mapper\mapper.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapper.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCreate.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCutUtils.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperMatch.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperRefs.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperSuper.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperSwitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTree.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperUtils.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperVec.c +# End Source File +# End Group +# Begin Group "mio" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\mio\mio.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mio.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioFunc.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioUtils.c +# End Source File +# End Group +# Begin Group "super" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\super\super.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\super.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\superAnd.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\superGate.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\superInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\superWrite.c +# End Source File +# End Group +# Begin Group "if" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\if\if.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifReduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifUtil.c +# End Source File +# End Group +# End Group +# Begin Group "misc" + +# PROP Default_Filter "" +# Begin Group "extra" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\extra\extra.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddAuto.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddCas.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddKmap.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddMisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddSymm.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraBddUnate.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilBitMatrix.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilFile.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilMemory.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilMisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilProgress.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilReader.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilUtil.c +# End Source File +# End Group +# Begin Group "st" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\st\st.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\st\st.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\st\stmm.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\st\stmm.h +# End Source File +# End Group +# Begin Group "util" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\util\util_hack.h +# End Source File +# End Group +# Begin Group "mvc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\mvc\mvc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvc.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcCompare.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcContain.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcCover.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcCube.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcDivide.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcDivisor.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcList.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcLits.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcOpAlg.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcOpBool.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcSort.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcUtils.c +# End Source File +# End Group +# Begin Group "vec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\vec\vec.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecAtt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecFlt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecPtr.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecStr.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecVec.h +# End Source File +# End Group +# Begin Group "espresso" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\espresso\cofactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cols.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\compl.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\contain.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cubehack.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cubestr.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrin.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrm.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrmisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\cvrout.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\dominate.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\equiv.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\espresso.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\espresso.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\essen.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\exact.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\expand.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\gasp.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\gimpel.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\globals.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\hack.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\indep.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\irred.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\map.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\matrix.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\mincov_int.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\opo.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\pair.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\part.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\primes.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\reduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\rows.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\set.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\setc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sharp.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sminterf.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\solution.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\sparse_int.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\unate.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\util_old.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\espresso\verify.c +# End Source File +# End Group +# Begin Group "nm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\nm\nm.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\nm\nmApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\nm\nmInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\nm\nmTable.c +# End Source File +# End Group +# Begin Group "hash" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\hash\hash.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\hash\hashFlt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\hash\hashInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\hash\hashPtr.h +# End Source File +# End Group +# End Group +# Begin Group "ai" + +# PROP Default_Filter "" +# Begin Group "hop" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\hop\hop.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopUtil.c +# End Source File +# End Group +# Begin Group "ivy" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\ivy\ivy.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCutTrav.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFastMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFraig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyHaig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMulti.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyResyn.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyRwr.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivySeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyUtil.c +# End Source File +# End Group +# Begin Group "rwt" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\rwt\rwt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\rwt\rwtDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\rwt\rwtMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\rwt\rwtUtil.c +# End Source File +# End Group +# Begin Group "deco" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\deco\deco.h +# End Source File +# End Group +# Begin Group "mem" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\mem\mem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\mem\mem.h +# End Source File +# End Group +# Begin Group "ioa" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\ioa\ioa.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ioa\ioaReadAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ioa\ioaUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ioa\ioaWriteAig.c +# End Source File +# End Group +# Begin Group "dar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\dar\dar.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darData.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darPrec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darRefact.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darResub.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\dar\darScript.c +# End Source File +# End Group +# Begin Group "fra" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\fra\fra.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraBmc.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraCec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraClass.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraImp.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraInd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraLcr.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraPart.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraSec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\fra\fraSim.c +# End Source File +# End Group +# Begin Group "cnf" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\cnf\cnf.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfData.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfPost.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\cnf\cnfWrite.c +# End Source File +# End Group +# Begin Group "csw" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\csw\csw.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\csw\cswCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\csw\cswCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\csw\cswInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\csw\cswMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\csw\cswTable.c +# End Source File +# End Group +# Begin Group "kit" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\kit\cloud.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\cloud.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kit.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitBdd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitCloud.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitFactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitGraph.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitHop.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitIsop.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitSop.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\kit\kitTruth.c +# End Source File +# End Group +# Begin Group "bdc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\bdc\bdc.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\bdc\bdcCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\bdc\bdcDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\bdc\bdcInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\bdc\bdcTable.c +# End Source File +# End Group +# Begin Group "aig" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\aig\aig.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigMffc.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigOrder.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigPart.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigRepr.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigRet.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigScl.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTiming.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTsim.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigWin.c +# End Source File +# End Group +# Begin Group "bar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\bar\bar.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\bar\bar.h +# End Source File +# End Group +# End Group +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# End Target +# End Project diff --git a/abc70930/abclib.dsw b/abc70930/abclib.dsw new file mode 100644 index 00000000..2e323b59 --- /dev/null +++ b/abc70930/abclib.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "abclib"=.\abclib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/abc70930/abclib.plg b/abc70930/abclib.plg new file mode 100644 index 00000000..b346e07b --- /dev/null +++ b/abc70930/abclib.plg @@ -0,0 +1,2208 @@ + + +
+

Build Log

+

+--------------------Configuration: abclib - Win32 Debug-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP20AB.tmp" with contents +[ +/nologo /MLd /W3 /Gm /GX /ZI /Od /I "src/base/abc" /I "src/base/abci" /I "src/base/cmd" /I "src/base/io" /I "src/base/main" /I "src/base/ver" /I "src/bdd/cudd" /I "src/bdd/dsd" /I "src/bdd/epd" /I "src/bdd/mtr" /I "src/bdd/parse" /I "src/bdd/reo" /I "src/bdd/cas" /I "src/map/fpga" /I "src/map/mapper" /I "src/map/mio" /I "src/map/super" /I "src/map/if" /I "src/map/pcm" /I "src/map/ply" /I "src/misc/extra" /I "src/misc/mvc" /I "src/misc/st" /I "src/misc/util" /I "src/misc/espresso" /I "src/misc/nm" /I "src/misc/vec" /I "src/misc/hash" /I "src/opt/cut" /I "src/opt/dec" /I "src/opt/fxu" /I "src/opt/rwr" /I "src/opt/sim" /I "src/opt/ret" /I "src/opt/res" /I "src/opt/lpk" /I "src/sat/bsat" /I "src/sat/csat" /I "src/sat/msat" /I "src/sat/fraig" /I "src/aig/ivy" /I "src/aig/hop" /I "src/aig/rwt" /I "src/aig/deco" /I "src/aig/mem" /I "src/aig/dar" /I "src/aig/fra" /I "src/aig/cnf" /I "src/aig/csw" /I "src/aig/ioa" /I "src/aig/aig" /I "src/aig/kit" /I "src/aig/bdc" /I "src/aig/bar" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "__STDC__" /D "HAVE_ASSERT_H" /FR"abclib\DebugLib/" /Fp"abclib\DebugLib/abclib.pch" /YX /Fo"abclib\DebugLib/" /Fd"abclib\DebugLib/" /FD /GZ /c +"C:\_projects\abc\src\base\abc\abcAig.c" +"C:\_projects\abc\src\base\abc\abcCheck.c" +"C:\_projects\abc\src\base\abc\abcDfs.c" +"C:\_projects\abc\src\base\abc\abcFanio.c" +"C:\_projects\abc\src\base\abc\abcFunc.c" +"C:\_projects\abc\src\base\abc\abcLatch.c" +"C:\_projects\abc\src\base\abc\abcLib.c" +"C:\_projects\abc\src\base\abc\abcMinBase.c" +"C:\_projects\abc\src\base\abc\abcNames.c" +"C:\_projects\abc\src\base\abc\abcNetlist.c" +"C:\_projects\abc\src\base\abc\abcNtk.c" +"C:\_projects\abc\src\base\abc\abcObj.c" +"C:\_projects\abc\src\base\abc\abcRefs.c" +"C:\_projects\abc\src\base\abc\abcShow.c" +"C:\_projects\abc\src\base\abc\abcSop.c" +"C:\_projects\abc\src\base\abc\abcUtil.c" +"C:\_projects\abc\src\base\abci\abc.c" +"C:\_projects\abc\src\base\abci\abcAttach.c" +"C:\_projects\abc\src\base\abci\abcAuto.c" +"C:\_projects\abc\src\base\abci\abcBalance.c" +"C:\_projects\abc\src\base\abci\abcBmc.c" +"C:\_projects\abc\src\base\abci\abcClpBdd.c" +"C:\_projects\abc\src\base\abci\abcClpSop.c" +"C:\_projects\abc\src\base\abci\abcCut.c" +"C:\_projects\abc\src\base\abci\abcDebug.c" +"C:\_projects\abc\src\base\abci\abcDress.c" +"C:\_projects\abc\src\base\abci\abcDsd.c" +"C:\_projects\abc\src\base\abci\abcEspresso.c" +"C:\_projects\abc\src\base\abci\abcExtract.c" +"C:\_projects\abc\src\base\abci\abcFpga.c" +"C:\_projects\abc\src\base\abci\abcFpgaFast.c" +"C:\_projects\abc\src\base\abci\abcFraig.c" +"C:\_projects\abc\src\base\abci\abcFxu.c" +"C:\_projects\abc\src\base\abci\abcGen.c" +"C:\_projects\abc\src\base\abci\abcIf.c" +"C:\_projects\abc\src\base\abci\abcIvy.c" +"C:\_projects\abc\src\base\abci\abcLut.c" +"C:\_projects\abc\src\base\abci\abcMap.c" +"C:\_projects\abc\src\base\abci\abcMini.c" +"C:\_projects\abc\src\base\abci\abcMiter.c" +"C:\_projects\abc\src\base\abci\abcMulti.c" +"C:\_projects\abc\src\base\abci\abcMv.c" +"C:\_projects\abc\src\base\abci\abcNtbdd.c" +"C:\_projects\abc\src\base\abci\abcOrder.c" +"C:\_projects\abc\src\base\abci\abcPrint.c" +"C:\_projects\abc\src\base\abci\abcProve.c" +"C:\_projects\abc\src\base\abci\abcReconv.c" +"C:\_projects\abc\src\base\abci\abcRefactor.c" +"C:\_projects\abc\src\base\abci\abcRenode.c" +"C:\_projects\abc\src\base\abci\abcReorder.c" +"C:\_projects\abc\src\base\abci\abcRestruct.c" +"C:\_projects\abc\src\base\abci\abcResub.c" +"C:\_projects\abc\src\base\abci\abcRewrite.c" +"C:\_projects\abc\src\base\abci\abcRr.c" +"C:\_projects\abc\src\base\abci\abcSat.c" +"C:\_projects\abc\src\base\abci\abcStrash.c" +"C:\_projects\abc\src\base\abci\abcSweep.c" +"C:\_projects\abc\src\base\abci\abcSymm.c" +"C:\_projects\abc\src\base\abci\abcTiming.c" +"C:\_projects\abc\src\base\abci\abcUnate.c" +"C:\_projects\abc\src\base\abci\abcUnreach.c" +"C:\_projects\abc\src\base\abci\abcVerify.c" +"C:\_projects\abc\src\base\abci\abcXsim.c" +"C:\_projects\abc\src\base\cmd\cmd.c" +"C:\_projects\abc\src\base\cmd\cmdAlias.c" +"C:\_projects\abc\src\base\cmd\cmdApi.c" +"C:\_projects\abc\src\base\cmd\cmdFlag.c" +"C:\_projects\abc\src\base\cmd\cmdHist.c" +"C:\_projects\abc\src\base\cmd\cmdUtils.c" +"C:\_projects\abc\src\base\io\io.c" +"C:\_projects\abc\src\base\io\ioReadAiger.c" +"C:\_projects\abc\src\base\io\ioReadBaf.c" +"C:\_projects\abc\src\base\io\ioReadBench.c" +"C:\_projects\abc\src\base\io\ioReadBlif.c" +"C:\_projects\abc\src\base\io\ioReadBlifAig.c" +"C:\_projects\abc\src\base\io\ioReadEdif.c" +"C:\_projects\abc\src\base\io\ioReadEqn.c" +"C:\_projects\abc\src\base\io\ioReadPla.c" +"C:\_projects\abc\src\base\io\ioUtil.c" +"C:\_projects\abc\src\base\io\ioWriteAiger.c" +"C:\_projects\abc\src\base\io\ioWriteBaf.c" +"C:\_projects\abc\src\base\io\ioWriteBench.c" +"C:\_projects\abc\src\base\io\ioWriteBlif.c" +"C:\_projects\abc\src\base\io\ioWriteCnf.c" +"C:\_projects\abc\src\base\io\ioWriteDot.c" +"C:\_projects\abc\src\base\io\ioWriteEqn.c" +"C:\_projects\abc\src\base\io\ioWriteGml.c" +"C:\_projects\abc\src\base\io\ioWriteList.c" +"C:\_projects\abc\src\base\io\ioWritePla.c" +"C:\_projects\abc\src\base\main\libSupport.c" +"C:\_projects\abc\src\base\main\main.c" +"C:\_projects\abc\src\base\main\mainFrame.c" +"C:\_projects\abc\src\base\main\mainInit.c" +"C:\_projects\abc\src\base\main\mainUtils.c" +"C:\_projects\abc\src\base\ver\verCore.c" +"C:\_projects\abc\src\base\ver\verFormula.c" +"C:\_projects\abc\src\base\ver\verParse.c" +"C:\_projects\abc\src\base\ver\verStream.c" +"C:\_projects\abc\src\bdd\cudd\cuddAddAbs.c" +"C:\_projects\abc\src\bdd\cudd\cuddAddApply.c" +"C:\_projects\abc\src\bdd\cudd\cuddAddFind.c" +"C:\_projects\abc\src\bdd\cudd\cuddAddInv.c" +"C:\_projects\abc\src\bdd\cudd\cuddAddIte.c" +"C:\_projects\abc\src\bdd\cudd\cuddAddNeg.c" +"C:\_projects\abc\src\bdd\cudd\cuddAddWalsh.c" +"C:\_projects\abc\src\bdd\cudd\cuddAndAbs.c" +"C:\_projects\abc\src\bdd\cudd\cuddAnneal.c" +"C:\_projects\abc\src\bdd\cudd\cuddApa.c" +"C:\_projects\abc\src\bdd\cudd\cuddAPI.c" +"C:\_projects\abc\src\bdd\cudd\cuddApprox.c" +"C:\_projects\abc\src\bdd\cudd\cuddBddAbs.c" +"C:\_projects\abc\src\bdd\cudd\cuddBddCorr.c" +"C:\_projects\abc\src\bdd\cudd\cuddBddIte.c" +"C:\_projects\abc\src\bdd\cudd\cuddBridge.c" +"C:\_projects\abc\src\bdd\cudd\cuddCache.c" +"C:\_projects\abc\src\bdd\cudd\cuddCheck.c" +"C:\_projects\abc\src\bdd\cudd\cuddClip.c" +"C:\_projects\abc\src\bdd\cudd\cuddCof.c" +"C:\_projects\abc\src\bdd\cudd\cuddCompose.c" +"C:\_projects\abc\src\bdd\cudd\cuddDecomp.c" +"C:\_projects\abc\src\bdd\cudd\cuddEssent.c" +"C:\_projects\abc\src\bdd\cudd\cuddExact.c" +"C:\_projects\abc\src\bdd\cudd\cuddExport.c" +"C:\_projects\abc\src\bdd\cudd\cuddGenCof.c" +"C:\_projects\abc\src\bdd\cudd\cuddGenetic.c" +"C:\_projects\abc\src\bdd\cudd\cuddGroup.c" +"C:\_projects\abc\src\bdd\cudd\cuddHarwell.c" +"C:\_projects\abc\src\bdd\cudd\cuddInit.c" +"C:\_projects\abc\src\bdd\cudd\cuddInteract.c" +"C:\_projects\abc\src\bdd\cudd\cuddLCache.c" +"C:\_projects\abc\src\bdd\cudd\cuddLevelQ.c" +"C:\_projects\abc\src\bdd\cudd\cuddLinear.c" +"C:\_projects\abc\src\bdd\cudd\cuddLiteral.c" +"C:\_projects\abc\src\bdd\cudd\cuddMatMult.c" +"C:\_projects\abc\src\bdd\cudd\cuddPriority.c" +"C:\_projects\abc\src\bdd\cudd\cuddRead.c" +"C:\_projects\abc\src\bdd\cudd\cuddRef.c" +"C:\_projects\abc\src\bdd\cudd\cuddReorder.c" +"C:\_projects\abc\src\bdd\cudd\cuddSat.c" +"C:\_projects\abc\src\bdd\cudd\cuddSign.c" +"C:\_projects\abc\src\bdd\cudd\cuddSolve.c" +"C:\_projects\abc\src\bdd\cudd\cuddSplit.c" +"C:\_projects\abc\src\bdd\cudd\cuddSubsetHB.c" +"C:\_projects\abc\src\bdd\cudd\cuddSubsetSP.c" +"C:\_projects\abc\src\bdd\cudd\cuddSymmetry.c" +"C:\_projects\abc\src\bdd\cudd\cuddTable.c" +"C:\_projects\abc\src\bdd\cudd\cuddUtil.c" +"C:\_projects\abc\src\bdd\cudd\cuddWindow.c" +"C:\_projects\abc\src\bdd\cudd\cuddZddCount.c" +"C:\_projects\abc\src\bdd\cudd\cuddZddFuncs.c" +"C:\_projects\abc\src\bdd\cudd\cuddZddGroup.c" +"C:\_projects\abc\src\bdd\cudd\cuddZddIsop.c" +"C:\_projects\abc\src\bdd\cudd\cuddZddLin.c" +"C:\_projects\abc\src\bdd\cudd\cuddZddMisc.c" +"C:\_projects\abc\src\bdd\cudd\cuddZddPort.c" +"C:\_projects\abc\src\bdd\cudd\cuddZddReord.c" +"C:\_projects\abc\src\bdd\cudd\cuddZddSetop.c" +"C:\_projects\abc\src\bdd\cudd\cuddZddSymm.c" +"C:\_projects\abc\src\bdd\cudd\cuddZddUtil.c" +"C:\_projects\abc\src\bdd\epd\epd.c" +"C:\_projects\abc\src\bdd\mtr\mtrBasic.c" +"C:\_projects\abc\src\bdd\mtr\mtrGroup.c" +"C:\_projects\abc\src\bdd\parse\parseCore.c" +"C:\_projects\abc\src\bdd\parse\parseEqn.c" +"C:\_projects\abc\src\bdd\parse\parseStack.c" +"C:\_projects\abc\src\bdd\dsd\dsdApi.c" +"C:\_projects\abc\src\bdd\dsd\dsdCheck.c" +"C:\_projects\abc\src\bdd\dsd\dsdLocal.c" +"C:\_projects\abc\src\bdd\dsd\dsdMan.c" +"C:\_projects\abc\src\bdd\dsd\dsdProc.c" +"C:\_projects\abc\src\bdd\dsd\dsdTree.c" +"C:\_projects\abc\src\bdd\reo\reoApi.c" +"C:\_projects\abc\src\bdd\reo\reoCore.c" +"C:\_projects\abc\src\bdd\reo\reoProfile.c" +"C:\_projects\abc\src\bdd\reo\reoSift.c" +"C:\_projects\abc\src\bdd\reo\reoSwap.c" +"C:\_projects\abc\src\bdd\reo\reoTest.c" +"C:\_projects\abc\src\bdd\reo\reoTransfer.c" +"C:\_projects\abc\src\bdd\reo\reoUnits.c" +"C:\_projects\abc\src\sat\msat\msatActivity.c" +"C:\_projects\abc\src\sat\msat\msatClause.c" +"C:\_projects\abc\src\sat\msat\msatClauseVec.c" +"C:\_projects\abc\src\sat\msat\msatMem.c" +"C:\_projects\abc\src\sat\msat\msatOrderH.c" +"C:\_projects\abc\src\sat\msat\msatQueue.c" +"C:\_projects\abc\src\sat\msat\msatRead.c" +"C:\_projects\abc\src\sat\msat\msatSolverApi.c" +"C:\_projects\abc\src\sat\msat\msatSolverCore.c" +"C:\_projects\abc\src\sat\msat\msatSolverIo.c" +"C:\_projects\abc\src\sat\msat\msatSolverSearch.c" +"C:\_projects\abc\src\sat\msat\msatSort.c" +"C:\_projects\abc\src\sat\msat\msatVec.c" +"C:\_projects\abc\src\sat\fraig\fraigApi.c" +"C:\_projects\abc\src\sat\fraig\fraigCanon.c" +"C:\_projects\abc\src\sat\fraig\fraigChoice.c" +"C:\_projects\abc\src\sat\fraig\fraigFanout.c" +"C:\_projects\abc\src\sat\fraig\fraigFeed.c" +"C:\_projects\abc\src\sat\fraig\fraigMan.c" +"C:\_projects\abc\src\sat\fraig\fraigMem.c" +"C:\_projects\abc\src\sat\fraig\fraigNode.c" +"C:\_projects\abc\src\sat\fraig\fraigPrime.c" +"C:\_projects\abc\src\sat\fraig\fraigSat.c" +"C:\_projects\abc\src\sat\fraig\fraigTable.c" +"C:\_projects\abc\src\sat\fraig\fraigUtil.c" +"C:\_projects\abc\src\sat\fraig\fraigVec.c" +"C:\_projects\abc\src\sat\csat\csat_apis.c" +"C:\_projects\abc\src\sat\bsat\satMem.c" +"C:\_projects\abc\src\sat\bsat\satSolver.c" +"C:\_projects\abc\src\sat\bsat\satUtil.c" +"C:\_projects\abc\src\opt\fxu\fxu.c" +"C:\_projects\abc\src\opt\fxu\fxuCreate.c" +"C:\_projects\abc\src\opt\fxu\fxuHeapD.c" +"C:\_projects\abc\src\opt\fxu\fxuHeapS.c" +"C:\_projects\abc\src\opt\fxu\fxuList.c" +"C:\_projects\abc\src\opt\fxu\fxuMatrix.c" +"C:\_projects\abc\src\opt\fxu\fxuPair.c" +"C:\_projects\abc\src\opt\fxu\fxuPrint.c" +"C:\_projects\abc\src\opt\fxu\fxuReduce.c" +"C:\_projects\abc\src\opt\fxu\fxuSelect.c" +"C:\_projects\abc\src\opt\fxu\fxuSingle.c" +"C:\_projects\abc\src\opt\fxu\fxuUpdate.c" +"C:\_projects\abc\src\opt\rwr\rwrDec.c" +"C:\_projects\abc\src\opt\rwr\rwrEva.c" +"C:\_projects\abc\src\opt\rwr\rwrExp.c" +"C:\_projects\abc\src\opt\rwr\rwrLib.c" +"C:\_projects\abc\src\opt\rwr\rwrMan.c" +"C:\_projects\abc\src\opt\rwr\rwrPrint.c" +"C:\_projects\abc\src\opt\rwr\rwrTemp.c" +"C:\_projects\abc\src\opt\rwr\rwrUtil.c" +"C:\_projects\abc\src\opt\cut\cutApi.c" +"C:\_projects\abc\src\opt\cut\cutCut.c" +"C:\_projects\abc\src\opt\cut\cutExpand.c" +"C:\_projects\abc\src\opt\cut\cutMan.c" +"C:\_projects\abc\src\opt\cut\cutMerge.c" +"C:\_projects\abc\src\opt\cut\cutNode.c" +"C:\_projects\abc\src\opt\cut\cutOracle.c" +"C:\_projects\abc\src\opt\cut\cutPre22.c" +"C:\_projects\abc\src\opt\cut\cutSeq.c" +"C:\_projects\abc\src\opt\cut\cutTruth.c" +"C:\_projects\abc\src\opt\dec\decAbc.c" +"C:\_projects\abc\src\opt\dec\decFactor.c" +"C:\_projects\abc\src\opt\dec\decMan.c" +"C:\_projects\abc\src\opt\dec\decPrint.c" +"C:\_projects\abc\src\opt\dec\decUtil.c" +"C:\_projects\abc\src\opt\sim\simMan.c" +"C:\_projects\abc\src\opt\sim\simSat.c" +"C:\_projects\abc\src\opt\sim\simSeq.c" +"C:\_projects\abc\src\opt\sim\simSupp.c" +"C:\_projects\abc\src\opt\sim\simSwitch.c" +"C:\_projects\abc\src\opt\sim\simSym.c" +"C:\_projects\abc\src\opt\sim\simSymSat.c" +"C:\_projects\abc\src\opt\sim\simSymSim.c" +"C:\_projects\abc\src\opt\sim\simSymStr.c" +"C:\_projects\abc\src\opt\sim\simUtils.c" +"C:\_projects\abc\src\opt\ret\retArea.c" +"C:\_projects\abc\src\opt\ret\retCore.c" +"C:\_projects\abc\src\opt\ret\retDelay.c" +"C:\_projects\abc\src\opt\ret\retFlow.c" +"C:\_projects\abc\src\opt\ret\retIncrem.c" +"C:\_projects\abc\src\opt\ret\retInit.c" +"C:\_projects\abc\src\opt\ret\retLvalue.c" +"C:\_projects\abc\src\map\fpga\fpga.c" +"C:\_projects\abc\src\map\fpga\fpgaCore.c" +"C:\_projects\abc\src\map\fpga\fpgaCreate.c" +"C:\_projects\abc\src\map\fpga\fpgaCut.c" +"C:\_projects\abc\src\map\fpga\fpgaCutUtils.c" +"C:\_projects\abc\src\map\fpga\fpgaFanout.c" +"C:\_projects\abc\src\map\fpga\fpgaLib.c" +"C:\_projects\abc\src\map\fpga\fpgaMatch.c" +"C:\_projects\abc\src\map\fpga\fpgaSwitch.c" +"C:\_projects\abc\src\map\fpga\fpgaTime.c" +"C:\_projects\abc\src\map\fpga\fpgaTruth.c" +"C:\_projects\abc\src\map\fpga\fpgaUtils.c" +"C:\_projects\abc\src\map\fpga\fpgaVec.c" +"C:\_projects\abc\src\map\mapper\mapper.c" +"C:\_projects\abc\src\map\mapper\mapperCanon.c" +"C:\_projects\abc\src\map\mapper\mapperCore.c" +"C:\_projects\abc\src\map\mapper\mapperCreate.c" +"C:\_projects\abc\src\map\mapper\mapperCut.c" +"C:\_projects\abc\src\map\mapper\mapperCutUtils.c" +"C:\_projects\abc\src\map\mapper\mapperFanout.c" +"C:\_projects\abc\src\map\mapper\mapperLib.c" +"C:\_projects\abc\src\map\mapper\mapperMatch.c" +"C:\_projects\abc\src\map\mapper\mapperRefs.c" +"C:\_projects\abc\src\map\mapper\mapperSuper.c" +"C:\_projects\abc\src\map\mapper\mapperSwitch.c" +"C:\_projects\abc\src\map\mapper\mapperTable.c" +"C:\_projects\abc\src\map\mapper\mapperTime.c" +"C:\_projects\abc\src\map\mapper\mapperTree.c" +"C:\_projects\abc\src\map\mapper\mapperTruth.c" +"C:\_projects\abc\src\map\mapper\mapperUtils.c" +"C:\_projects\abc\src\map\mapper\mapperVec.c" +"C:\_projects\abc\src\map\mio\mio.c" +"C:\_projects\abc\src\map\mio\mioApi.c" +"C:\_projects\abc\src\map\mio\mioFunc.c" +"C:\_projects\abc\src\map\mio\mioRead.c" +"C:\_projects\abc\src\map\mio\mioUtils.c" +"C:\_projects\abc\src\map\super\super.c" +"C:\_projects\abc\src\map\super\superAnd.c" +"C:\_projects\abc\src\map\super\superGate.c" +"C:\_projects\abc\src\map\super\superWrite.c" +"C:\_projects\abc\src\map\if\ifCore.c" +"C:\_projects\abc\src\map\if\ifCut.c" +"C:\_projects\abc\src\map\if\ifMan.c" +"C:\_projects\abc\src\map\if\ifMap.c" +"C:\_projects\abc\src\map\if\ifReduce.c" +"C:\_projects\abc\src\map\if\ifSeq.c" +"C:\_projects\abc\src\map\if\ifTime.c" +"C:\_projects\abc\src\map\if\ifTruth.c" +"C:\_projects\abc\src\map\if\ifUtil.c" +"C:\_projects\abc\src\misc\extra\extraBddAuto.c" +"C:\_projects\abc\src\misc\extra\extraBddKmap.c" +"C:\_projects\abc\src\misc\extra\extraBddMisc.c" +"C:\_projects\abc\src\misc\extra\extraBddSymm.c" +"C:\_projects\abc\src\misc\extra\extraBddUnate.c" +"C:\_projects\abc\src\misc\extra\extraUtilBitMatrix.c" +"C:\_projects\abc\src\misc\extra\extraUtilCanon.c" +"C:\_projects\abc\src\misc\extra\extraUtilFile.c" +"C:\_projects\abc\src\misc\extra\extraUtilMemory.c" +"C:\_projects\abc\src\misc\extra\extraUtilMisc.c" +"C:\_projects\abc\src\misc\extra\extraUtilProgress.c" +"C:\_projects\abc\src\misc\extra\extraUtilReader.c" +"C:\_projects\abc\src\misc\extra\extraUtilTruth.c" +"C:\_projects\abc\src\misc\extra\extraUtilUtil.c" +"C:\_projects\abc\src\misc\st\st.c" +"C:\_projects\abc\src\misc\st\stmm.c" +"C:\_projects\abc\src\misc\mvc\mvc.c" +"C:\_projects\abc\src\misc\mvc\mvcApi.c" +"C:\_projects\abc\src\misc\mvc\mvcCompare.c" +"C:\_projects\abc\src\misc\mvc\mvcContain.c" +"C:\_projects\abc\src\misc\mvc\mvcCover.c" +"C:\_projects\abc\src\misc\mvc\mvcCube.c" +"C:\_projects\abc\src\misc\mvc\mvcDivide.c" +"C:\_projects\abc\src\misc\mvc\mvcDivisor.c" +"C:\_projects\abc\src\misc\mvc\mvcList.c" +"C:\_projects\abc\src\misc\mvc\mvcLits.c" +"C:\_projects\abc\src\misc\mvc\mvcMan.c" +"C:\_projects\abc\src\misc\mvc\mvcOpAlg.c" +"C:\_projects\abc\src\misc\mvc\mvcOpBool.c" +"C:\_projects\abc\src\misc\mvc\mvcPrint.c" +"C:\_projects\abc\src\misc\mvc\mvcSort.c" +"C:\_projects\abc\src\misc\mvc\mvcUtils.c" +"C:\_projects\abc\src\misc\espresso\cofactor.c" +"C:\_projects\abc\src\misc\espresso\cols.c" +"C:\_projects\abc\src\misc\espresso\compl.c" +"C:\_projects\abc\src\misc\espresso\contain.c" +"C:\_projects\abc\src\misc\espresso\cubehack.c" +"C:\_projects\abc\src\misc\espresso\cubestr.c" +"C:\_projects\abc\src\misc\espresso\cvrin.c" +"C:\_projects\abc\src\misc\espresso\cvrm.c" +"C:\_projects\abc\src\misc\espresso\cvrmisc.c" +"C:\_projects\abc\src\misc\espresso\cvrout.c" +"C:\_projects\abc\src\misc\espresso\dominate.c" +"C:\_projects\abc\src\misc\espresso\equiv.c" +"C:\_projects\abc\src\misc\espresso\espresso.c" +"C:\_projects\abc\src\misc\espresso\essen.c" +"C:\_projects\abc\src\misc\espresso\exact.c" +"C:\_projects\abc\src\misc\espresso\expand.c" +"C:\_projects\abc\src\misc\espresso\gasp.c" +"C:\_projects\abc\src\misc\espresso\gimpel.c" +"C:\_projects\abc\src\misc\espresso\globals.c" +"C:\_projects\abc\src\misc\espresso\hack.c" +"C:\_projects\abc\src\misc\espresso\indep.c" +"C:\_projects\abc\src\misc\espresso\irred.c" +"C:\_projects\abc\src\misc\espresso\map.c" +"C:\_projects\abc\src\misc\espresso\matrix.c" +"C:\_projects\abc\src\misc\espresso\mincov.c" +"C:\_projects\abc\src\misc\espresso\opo.c" +"C:\_projects\abc\src\misc\espresso\pair.c" +"C:\_projects\abc\src\misc\espresso\part.c" +"C:\_projects\abc\src\misc\espresso\primes.c" +"C:\_projects\abc\src\misc\espresso\reduce.c" +"C:\_projects\abc\src\misc\espresso\rows.c" +"C:\_projects\abc\src\misc\espresso\set.c" +"C:\_projects\abc\src\misc\espresso\setc.c" +"C:\_projects\abc\src\misc\espresso\sharp.c" +"C:\_projects\abc\src\misc\espresso\sminterf.c" +"C:\_projects\abc\src\misc\espresso\solution.c" +"C:\_projects\abc\src\misc\espresso\sparse.c" +"C:\_projects\abc\src\misc\espresso\unate.c" +"C:\_projects\abc\src\misc\espresso\verify.c" +"C:\_projects\abc\src\misc\nm\nmApi.c" +"C:\_projects\abc\src\misc\nm\nmTable.c" +"C:\_projects\abc\src\aig\hop\hopBalance.c" +"C:\_projects\abc\src\aig\hop\hopCheck.c" +"C:\_projects\abc\src\aig\hop\hopDfs.c" +"C:\_projects\abc\src\aig\hop\hopMan.c" +"C:\_projects\abc\src\aig\hop\hopMem.c" +"C:\_projects\abc\src\aig\hop\hopObj.c" +"C:\_projects\abc\src\aig\hop\hopOper.c" +"C:\_projects\abc\src\aig\hop\hopTable.c" +"C:\_projects\abc\src\aig\hop\hopUtil.c" +"C:\_projects\abc\src\aig\ivy\ivyBalance.c" +"C:\_projects\abc\src\aig\ivy\ivyCanon.c" +"C:\_projects\abc\src\aig\ivy\ivyCheck.c" +"C:\_projects\abc\src\aig\ivy\ivyCut.c" +"C:\_projects\abc\src\aig\ivy\ivyCutTrav.c" +"C:\_projects\abc\src\aig\ivy\ivyDfs.c" +"C:\_projects\abc\src\aig\ivy\ivyDsd.c" +"C:\_projects\abc\src\aig\ivy\ivyFanout.c" +"C:\_projects\abc\src\aig\ivy\ivyFastMap.c" +"C:\_projects\abc\src\aig\ivy\ivyFraig.c" +"C:\_projects\abc\src\aig\ivy\ivyHaig.c" +"C:\_projects\abc\src\aig\ivy\ivyMan.c" +"C:\_projects\abc\src\aig\ivy\ivyMem.c" +"C:\_projects\abc\src\aig\ivy\ivyMulti.c" +"C:\_projects\abc\src\aig\ivy\ivyObj.c" +"C:\_projects\abc\src\aig\ivy\ivyOper.c" +"C:\_projects\abc\src\aig\ivy\ivyResyn.c" +"C:\_projects\abc\src\aig\ivy\ivyRwr.c" +"C:\_projects\abc\src\aig\ivy\ivySeq.c" +"C:\_projects\abc\src\aig\ivy\ivyShow.c" +"C:\_projects\abc\src\aig\ivy\ivyTable.c" +"C:\_projects\abc\src\aig\ivy\ivyUtil.c" +"C:\_projects\abc\src\aig\rwt\rwtDec.c" +"C:\_projects\abc\src\aig\rwt\rwtMan.c" +"C:\_projects\abc\src\aig\rwt\rwtUtil.c" +"C:\_projects\abc\src\aig\mem\mem.c" +"C:\_projects\abc\src\base\abc\abcHie.c" +"C:\_projects\abc\src\base\abc\abcBlifMv.c" +"C:\_projects\abc\src\base\abci\abcCas.c" +"C:\_projects\abc\src\base\abci\abcDar.c" +"C:\_projects\abc\src\base\abci\abcHaig.c" +"C:\_projects\abc\src\base\abci\abcMeasure.c" +"C:\_projects\abc\src\base\abci\abcOdc.c" +"C:\_projects\abc\src\base\abci\abcPart.c" +"C:\_projects\abc\src\base\abci\abcRec.c" +"C:\_projects\abc\src\base\abci\abcQbf.c" +"C:\_projects\abc\src\base\abci\abcQuant.c" +"C:\_projects\abc\src\base\io\ioReadDsd.c" +"C:\_projects\abc\src\base\io\ioReadBlifMv.c" +"C:\_projects\abc\src\base\io\ioReadVerilog.c" +"C:\_projects\abc\src\base\io\ioWriteVerilog.c" +"C:\_projects\abc\src\base\io\ioWriteBlifMv.c" +"C:\_projects\abc\src\bdd\cas\casDec.c" +"C:\_projects\abc\src\bdd\cas\casCore.c" +"C:\_projects\abc\src\sat\proof\pr.c" +"C:\_projects\abc\src\sat\bsat\satTrace.c" +"C:\_projects\abc\src\sat\bsat\satInter.c" +"C:\_projects\abc\src\sat\bsat\satStore.c" +"C:\_projects\abc\src\misc\extra\extraBddCas.c" +"C:\_projects\abc\src\aig\ioa\ioaWriteAig.c" +"C:\_projects\abc\src\aig\ioa\ioaReadAig.c" +"C:\_projects\abc\src\aig\ioa\ioaUtil.c" +"C:\_projects\abc\src\aig\dar\darBalance.c" +"C:\_projects\abc\src\aig\dar\darCore.c" +"C:\_projects\abc\src\aig\dar\darCut.c" +"C:\_projects\abc\src\aig\dar\darData.c" +"C:\_projects\abc\src\aig\dar\darLib.c" +"C:\_projects\abc\src\aig\dar\darMan.c" +"C:\_projects\abc\src\aig\dar\darPrec.c" +"C:\_projects\abc\src\aig\dar\darRefact.c" +"C:\_projects\abc\src\aig\dar\darResub.c" +"C:\_projects\abc\src\aig\dar\darScript.c" +"C:\_projects\abc\src\aig\fra\fraBmc.c" +"C:\_projects\abc\src\aig\fra\fraCec.c" +"C:\_projects\abc\src\aig\fra\fraClass.c" +"C:\_projects\abc\src\aig\fra\fraCnf.c" +"C:\_projects\abc\src\aig\fra\fraCore.c" +"C:\_projects\abc\src\aig\fra\fraImp.c" +"C:\_projects\abc\src\aig\fra\fraInd.c" +"C:\_projects\abc\src\aig\fra\fraLcr.c" +"C:\_projects\abc\src\aig\fra\fraMan.c" +"C:\_projects\abc\src\aig\fra\fraPart.c" +"C:\_projects\abc\src\aig\fra\fraSat.c" +"C:\_projects\abc\src\aig\fra\fraSec.c" +"C:\_projects\abc\src\aig\fra\fraSim.c" +"C:\_projects\abc\src\aig\cnf\cnfCore.c" +"C:\_projects\abc\src\aig\cnf\cnfCut.c" +"C:\_projects\abc\src\aig\cnf\cnfData.c" +"C:\_projects\abc\src\aig\cnf\cnfMan.c" +"C:\_projects\abc\src\aig\cnf\cnfMap.c" +"C:\_projects\abc\src\aig\cnf\cnfPost.c" +"C:\_projects\abc\src\aig\cnf\cnfUtil.c" +"C:\_projects\abc\src\aig\cnf\cnfWrite.c" +"C:\_projects\abc\src\aig\csw\cswCore.c" +"C:\_projects\abc\src\aig\csw\cswCut.c" +"C:\_projects\abc\src\aig\csw\cswMan.c" +"C:\_projects\abc\src\aig\csw\cswTable.c" +"C:\_projects\abc\src\aig\kit\cloud.c" +"C:\_projects\abc\src\aig\kit\kitAig.c" +"C:\_projects\abc\src\aig\kit\kitBdd.c" +"C:\_projects\abc\src\aig\kit\kitCloud.c" +"C:\_projects\abc\src\aig\kit\kitDsd.c" +"C:\_projects\abc\src\aig\kit\kitFactor.c" +"C:\_projects\abc\src\aig\kit\kitGraph.c" +"C:\_projects\abc\src\aig\kit\kitHop.c" +"C:\_projects\abc\src\aig\kit\kitIsop.c" +"C:\_projects\abc\src\aig\kit\kitSop.c" +"C:\_projects\abc\src\aig\kit\kitTruth.c" +"C:\_projects\abc\src\aig\bdc\bdcCore.c" +"C:\_projects\abc\src\aig\bdc\bdcDec.c" +"C:\_projects\abc\src\aig\bdc\bdcTable.c" +"C:\_projects\abc\src\aig\aig\aigCheck.c" +"C:\_projects\abc\src\aig\aig\aigDfs.c" +"C:\_projects\abc\src\aig\aig\aigFanout.c" +"C:\_projects\abc\src\aig\aig\aigMan.c" +"C:\_projects\abc\src\aig\aig\aigMem.c" +"C:\_projects\abc\src\aig\aig\aigMffc.c" +"C:\_projects\abc\src\aig\aig\aigObj.c" +"C:\_projects\abc\src\aig\aig\aigOper.c" +"C:\_projects\abc\src\aig\aig\aigOrder.c" +"C:\_projects\abc\src\aig\aig\aigPart.c" +"C:\_projects\abc\src\aig\aig\aigRepr.c" +"C:\_projects\abc\src\aig\aig\aigRet.c" +"C:\_projects\abc\src\aig\aig\aigScl.c" +"C:\_projects\abc\src\aig\aig\aigSeq.c" +"C:\_projects\abc\src\aig\aig\aigShow.c" +"C:\_projects\abc\src\aig\aig\aigTable.c" +"C:\_projects\abc\src\aig\aig\aigTime.c" +"C:\_projects\abc\src\aig\aig\aigTiming.c" +"C:\_projects\abc\src\aig\aig\aigTruth.c" +"C:\_projects\abc\src\aig\aig\aigTsim.c" +"C:\_projects\abc\src\aig\aig\aigUtil.c" +"C:\_projects\abc\src\aig\aig\aigWin.c" +"C:\_projects\abc\src\aig\bar\bar.c" +"C:\_projects\abc\src\opt\res\resCore.c" +"C:\_projects\abc\src\opt\res\resDivs.c" +"C:\_projects\abc\src\opt\res\resFilter.c" +"C:\_projects\abc\src\opt\res\resSat.c" +"C:\_projects\abc\src\opt\res\resSim.c" +"C:\_projects\abc\src\opt\res\resStrash.c" +"C:\_projects\abc\src\opt\res\resWin.c" +"C:\_projects\abc\src\opt\lpk\lpkAbcDec.c" +"C:\_projects\abc\src\opt\lpk\lpkAbcDsd.c" +"C:\_projects\abc\src\opt\lpk\lpkAbcMux.c" +"C:\_projects\abc\src\opt\lpk\lpkAbcUtil.c" +"C:\_projects\abc\src\opt\lpk\lpkCore.c" +"C:\_projects\abc\src\opt\lpk\lpkCut.c" +"C:\_projects\abc\src\opt\lpk\lpkMan.c" +"C:\_projects\abc\src\opt\lpk\lpkMap.c" +"C:\_projects\abc\src\opt\lpk\lpkMulti.c" +"C:\_projects\abc\src\opt\lpk\lpkMux.c" +"C:\_projects\abc\src\opt\lpk\lpkSets.c" +] +Creating command line "cl.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP20AB.tmp" +Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP20AC.tmp" with contents +[ +/nologo /out:"abclib\abclib_debug.lib" +.\abclib\DebugLib\abcAig.obj +.\abclib\DebugLib\abcCheck.obj +.\abclib\DebugLib\abcDfs.obj +.\abclib\DebugLib\abcFanio.obj +.\abclib\DebugLib\abcFunc.obj +.\abclib\DebugLib\abcLatch.obj +.\abclib\DebugLib\abcLib.obj +.\abclib\DebugLib\abcMinBase.obj +.\abclib\DebugLib\abcNames.obj +.\abclib\DebugLib\abcNetlist.obj +.\abclib\DebugLib\abcNtk.obj +.\abclib\DebugLib\abcObj.obj +.\abclib\DebugLib\abcRefs.obj +.\abclib\DebugLib\abcShow.obj +.\abclib\DebugLib\abcSop.obj +.\abclib\DebugLib\abcUtil.obj +.\abclib\DebugLib\abc.obj +.\abclib\DebugLib\abcAttach.obj +.\abclib\DebugLib\abcAuto.obj +.\abclib\DebugLib\abcBalance.obj +.\abclib\DebugLib\abcBmc.obj +.\abclib\DebugLib\abcClpBdd.obj +.\abclib\DebugLib\abcClpSop.obj +.\abclib\DebugLib\abcCut.obj +.\abclib\DebugLib\abcDebug.obj +.\abclib\DebugLib\abcDress.obj +.\abclib\DebugLib\abcDsd.obj +.\abclib\DebugLib\abcEspresso.obj +.\abclib\DebugLib\abcExtract.obj +.\abclib\DebugLib\abcFpga.obj +.\abclib\DebugLib\abcFpgaFast.obj +.\abclib\DebugLib\abcFraig.obj +.\abclib\DebugLib\abcFxu.obj +.\abclib\DebugLib\abcGen.obj +.\abclib\DebugLib\abcIf.obj +.\abclib\DebugLib\abcIvy.obj +.\abclib\DebugLib\abcLut.obj +.\abclib\DebugLib\abcMap.obj +.\abclib\DebugLib\abcMini.obj +.\abclib\DebugLib\abcMiter.obj +.\abclib\DebugLib\abcMulti.obj +.\abclib\DebugLib\abcMv.obj +.\abclib\DebugLib\abcNtbdd.obj +.\abclib\DebugLib\abcOrder.obj +.\abclib\DebugLib\abcPrint.obj +.\abclib\DebugLib\abcProve.obj +.\abclib\DebugLib\abcReconv.obj +.\abclib\DebugLib\abcRefactor.obj +.\abclib\DebugLib\abcRenode.obj +.\abclib\DebugLib\abcReorder.obj +.\abclib\DebugLib\abcRestruct.obj +.\abclib\DebugLib\abcResub.obj +.\abclib\DebugLib\abcRewrite.obj +.\abclib\DebugLib\abcRr.obj +.\abclib\DebugLib\abcSat.obj +.\abclib\DebugLib\abcStrash.obj +.\abclib\DebugLib\abcSweep.obj +.\abclib\DebugLib\abcSymm.obj +.\abclib\DebugLib\abcTiming.obj +.\abclib\DebugLib\abcUnate.obj +.\abclib\DebugLib\abcUnreach.obj +.\abclib\DebugLib\abcVerify.obj +.\abclib\DebugLib\abcXsim.obj +.\abclib\DebugLib\cmd.obj +.\abclib\DebugLib\cmdAlias.obj +.\abclib\DebugLib\cmdApi.obj +.\abclib\DebugLib\cmdFlag.obj +.\abclib\DebugLib\cmdHist.obj +.\abclib\DebugLib\cmdUtils.obj +.\abclib\DebugLib\io.obj +.\abclib\DebugLib\ioReadAiger.obj +.\abclib\DebugLib\ioReadBaf.obj +.\abclib\DebugLib\ioReadBench.obj +.\abclib\DebugLib\ioReadBlif.obj +.\abclib\DebugLib\ioReadBlifAig.obj +.\abclib\DebugLib\ioReadEdif.obj +.\abclib\DebugLib\ioReadEqn.obj +.\abclib\DebugLib\ioReadPla.obj +.\abclib\DebugLib\ioUtil.obj +.\abclib\DebugLib\ioWriteAiger.obj +.\abclib\DebugLib\ioWriteBaf.obj +.\abclib\DebugLib\ioWriteBench.obj +.\abclib\DebugLib\ioWriteBlif.obj +.\abclib\DebugLib\ioWriteCnf.obj +.\abclib\DebugLib\ioWriteDot.obj +.\abclib\DebugLib\ioWriteEqn.obj +.\abclib\DebugLib\ioWriteGml.obj +.\abclib\DebugLib\ioWriteList.obj +.\abclib\DebugLib\ioWritePla.obj +.\abclib\DebugLib\libSupport.obj +.\abclib\DebugLib\main.obj +.\abclib\DebugLib\mainFrame.obj +.\abclib\DebugLib\mainInit.obj +.\abclib\DebugLib\mainUtils.obj +.\abclib\DebugLib\verCore.obj +.\abclib\DebugLib\verFormula.obj +.\abclib\DebugLib\verParse.obj +.\abclib\DebugLib\verStream.obj +.\abclib\DebugLib\cuddAddAbs.obj +.\abclib\DebugLib\cuddAddApply.obj +.\abclib\DebugLib\cuddAddFind.obj +.\abclib\DebugLib\cuddAddInv.obj +.\abclib\DebugLib\cuddAddIte.obj +.\abclib\DebugLib\cuddAddNeg.obj +.\abclib\DebugLib\cuddAddWalsh.obj +.\abclib\DebugLib\cuddAndAbs.obj +.\abclib\DebugLib\cuddAnneal.obj +.\abclib\DebugLib\cuddApa.obj +.\abclib\DebugLib\cuddAPI.obj +.\abclib\DebugLib\cuddApprox.obj +.\abclib\DebugLib\cuddBddAbs.obj +.\abclib\DebugLib\cuddBddCorr.obj +.\abclib\DebugLib\cuddBddIte.obj +.\abclib\DebugLib\cuddBridge.obj +.\abclib\DebugLib\cuddCache.obj +.\abclib\DebugLib\cuddCheck.obj +.\abclib\DebugLib\cuddClip.obj +.\abclib\DebugLib\cuddCof.obj +.\abclib\DebugLib\cuddCompose.obj +.\abclib\DebugLib\cuddDecomp.obj +.\abclib\DebugLib\cuddEssent.obj +.\abclib\DebugLib\cuddExact.obj +.\abclib\DebugLib\cuddExport.obj +.\abclib\DebugLib\cuddGenCof.obj +.\abclib\DebugLib\cuddGenetic.obj +.\abclib\DebugLib\cuddGroup.obj +.\abclib\DebugLib\cuddHarwell.obj +.\abclib\DebugLib\cuddInit.obj +.\abclib\DebugLib\cuddInteract.obj +.\abclib\DebugLib\cuddLCache.obj +.\abclib\DebugLib\cuddLevelQ.obj +.\abclib\DebugLib\cuddLinear.obj +.\abclib\DebugLib\cuddLiteral.obj +.\abclib\DebugLib\cuddMatMult.obj +.\abclib\DebugLib\cuddPriority.obj +.\abclib\DebugLib\cuddRead.obj +.\abclib\DebugLib\cuddRef.obj +.\abclib\DebugLib\cuddReorder.obj +.\abclib\DebugLib\cuddSat.obj +.\abclib\DebugLib\cuddSign.obj +.\abclib\DebugLib\cuddSolve.obj +.\abclib\DebugLib\cuddSplit.obj +.\abclib\DebugLib\cuddSubsetHB.obj +.\abclib\DebugLib\cuddSubsetSP.obj +.\abclib\DebugLib\cuddSymmetry.obj +.\abclib\DebugLib\cuddTable.obj +.\abclib\DebugLib\cuddUtil.obj +.\abclib\DebugLib\cuddWindow.obj +.\abclib\DebugLib\cuddZddCount.obj +.\abclib\DebugLib\cuddZddFuncs.obj +.\abclib\DebugLib\cuddZddGroup.obj +.\abclib\DebugLib\cuddZddIsop.obj +.\abclib\DebugLib\cuddZddLin.obj +.\abclib\DebugLib\cuddZddMisc.obj +.\abclib\DebugLib\cuddZddPort.obj +.\abclib\DebugLib\cuddZddReord.obj +.\abclib\DebugLib\cuddZddSetop.obj +.\abclib\DebugLib\cuddZddSymm.obj +.\abclib\DebugLib\cuddZddUtil.obj +.\abclib\DebugLib\epd.obj +.\abclib\DebugLib\mtrBasic.obj +.\abclib\DebugLib\mtrGroup.obj +.\abclib\DebugLib\parseCore.obj +.\abclib\DebugLib\parseEqn.obj +.\abclib\DebugLib\parseStack.obj +.\abclib\DebugLib\dsdApi.obj +.\abclib\DebugLib\dsdCheck.obj +.\abclib\DebugLib\dsdLocal.obj +.\abclib\DebugLib\dsdMan.obj +.\abclib\DebugLib\dsdProc.obj +.\abclib\DebugLib\dsdTree.obj +.\abclib\DebugLib\reoApi.obj +.\abclib\DebugLib\reoCore.obj +.\abclib\DebugLib\reoProfile.obj +.\abclib\DebugLib\reoSift.obj +.\abclib\DebugLib\reoSwap.obj +.\abclib\DebugLib\reoTest.obj +.\abclib\DebugLib\reoTransfer.obj +.\abclib\DebugLib\reoUnits.obj +.\abclib\DebugLib\msatActivity.obj +.\abclib\DebugLib\msatClause.obj +.\abclib\DebugLib\msatClauseVec.obj +.\abclib\DebugLib\msatMem.obj +.\abclib\DebugLib\msatOrderH.obj +.\abclib\DebugLib\msatQueue.obj +.\abclib\DebugLib\msatRead.obj +.\abclib\DebugLib\msatSolverApi.obj +.\abclib\DebugLib\msatSolverCore.obj +.\abclib\DebugLib\msatSolverIo.obj +.\abclib\DebugLib\msatSolverSearch.obj +.\abclib\DebugLib\msatSort.obj +.\abclib\DebugLib\msatVec.obj +.\abclib\DebugLib\fraigApi.obj +.\abclib\DebugLib\fraigCanon.obj +.\abclib\DebugLib\fraigChoice.obj +.\abclib\DebugLib\fraigFanout.obj +.\abclib\DebugLib\fraigFeed.obj +.\abclib\DebugLib\fraigMan.obj +.\abclib\DebugLib\fraigMem.obj +.\abclib\DebugLib\fraigNode.obj +.\abclib\DebugLib\fraigPrime.obj +.\abclib\DebugLib\fraigSat.obj +.\abclib\DebugLib\fraigTable.obj +.\abclib\DebugLib\fraigUtil.obj +.\abclib\DebugLib\fraigVec.obj +.\abclib\DebugLib\csat_apis.obj +.\abclib\DebugLib\satMem.obj +.\abclib\DebugLib\satSolver.obj +.\abclib\DebugLib\satUtil.obj +.\abclib\DebugLib\fxu.obj +.\abclib\DebugLib\fxuCreate.obj +.\abclib\DebugLib\fxuHeapD.obj +.\abclib\DebugLib\fxuHeapS.obj +.\abclib\DebugLib\fxuList.obj +.\abclib\DebugLib\fxuMatrix.obj +.\abclib\DebugLib\fxuPair.obj +.\abclib\DebugLib\fxuPrint.obj +.\abclib\DebugLib\fxuReduce.obj +.\abclib\DebugLib\fxuSelect.obj +.\abclib\DebugLib\fxuSingle.obj +.\abclib\DebugLib\fxuUpdate.obj +.\abclib\DebugLib\rwrDec.obj +.\abclib\DebugLib\rwrEva.obj +.\abclib\DebugLib\rwrExp.obj +.\abclib\DebugLib\rwrLib.obj +.\abclib\DebugLib\rwrMan.obj +.\abclib\DebugLib\rwrPrint.obj +.\abclib\DebugLib\rwrTemp.obj +.\abclib\DebugLib\rwrUtil.obj +.\abclib\DebugLib\cutApi.obj +.\abclib\DebugLib\cutCut.obj +.\abclib\DebugLib\cutExpand.obj +.\abclib\DebugLib\cutMan.obj +.\abclib\DebugLib\cutMerge.obj +.\abclib\DebugLib\cutNode.obj +.\abclib\DebugLib\cutOracle.obj +.\abclib\DebugLib\cutPre22.obj +.\abclib\DebugLib\cutSeq.obj +.\abclib\DebugLib\cutTruth.obj +.\abclib\DebugLib\decAbc.obj +.\abclib\DebugLib\decFactor.obj +.\abclib\DebugLib\decMan.obj +.\abclib\DebugLib\decPrint.obj +.\abclib\DebugLib\decUtil.obj +.\abclib\DebugLib\simMan.obj +.\abclib\DebugLib\simSat.obj +.\abclib\DebugLib\simSeq.obj +.\abclib\DebugLib\simSupp.obj +.\abclib\DebugLib\simSwitch.obj +.\abclib\DebugLib\simSym.obj +.\abclib\DebugLib\simSymSat.obj +.\abclib\DebugLib\simSymSim.obj +.\abclib\DebugLib\simSymStr.obj +.\abclib\DebugLib\simUtils.obj +.\abclib\DebugLib\retArea.obj +.\abclib\DebugLib\retCore.obj +.\abclib\DebugLib\retDelay.obj +.\abclib\DebugLib\retFlow.obj +.\abclib\DebugLib\retIncrem.obj +.\abclib\DebugLib\retInit.obj +.\abclib\DebugLib\retLvalue.obj +.\abclib\DebugLib\fpga.obj +.\abclib\DebugLib\fpgaCore.obj +.\abclib\DebugLib\fpgaCreate.obj +.\abclib\DebugLib\fpgaCut.obj +.\abclib\DebugLib\fpgaCutUtils.obj +.\abclib\DebugLib\fpgaFanout.obj +.\abclib\DebugLib\fpgaLib.obj +.\abclib\DebugLib\fpgaMatch.obj +.\abclib\DebugLib\fpgaSwitch.obj +.\abclib\DebugLib\fpgaTime.obj +.\abclib\DebugLib\fpgaTruth.obj +.\abclib\DebugLib\fpgaUtils.obj +.\abclib\DebugLib\fpgaVec.obj +.\abclib\DebugLib\mapper.obj +.\abclib\DebugLib\mapperCanon.obj +.\abclib\DebugLib\mapperCore.obj +.\abclib\DebugLib\mapperCreate.obj +.\abclib\DebugLib\mapperCut.obj +.\abclib\DebugLib\mapperCutUtils.obj +.\abclib\DebugLib\mapperFanout.obj +.\abclib\DebugLib\mapperLib.obj +.\abclib\DebugLib\mapperMatch.obj +.\abclib\DebugLib\mapperRefs.obj +.\abclib\DebugLib\mapperSuper.obj +.\abclib\DebugLib\mapperSwitch.obj +.\abclib\DebugLib\mapperTable.obj +.\abclib\DebugLib\mapperTime.obj +.\abclib\DebugLib\mapperTree.obj +.\abclib\DebugLib\mapperTruth.obj +.\abclib\DebugLib\mapperUtils.obj +.\abclib\DebugLib\mapperVec.obj +.\abclib\DebugLib\mio.obj +.\abclib\DebugLib\mioApi.obj +.\abclib\DebugLib\mioFunc.obj +.\abclib\DebugLib\mioRead.obj +.\abclib\DebugLib\mioUtils.obj +.\abclib\DebugLib\super.obj +.\abclib\DebugLib\superAnd.obj +.\abclib\DebugLib\superGate.obj +.\abclib\DebugLib\superWrite.obj +.\abclib\DebugLib\ifCore.obj +.\abclib\DebugLib\ifCut.obj +.\abclib\DebugLib\ifMan.obj +.\abclib\DebugLib\ifMap.obj +.\abclib\DebugLib\ifReduce.obj +.\abclib\DebugLib\ifSeq.obj +.\abclib\DebugLib\ifTime.obj +.\abclib\DebugLib\ifTruth.obj +.\abclib\DebugLib\ifUtil.obj +.\abclib\DebugLib\extraBddAuto.obj +.\abclib\DebugLib\extraBddKmap.obj +.\abclib\DebugLib\extraBddMisc.obj +.\abclib\DebugLib\extraBddSymm.obj +.\abclib\DebugLib\extraBddUnate.obj +.\abclib\DebugLib\extraUtilBitMatrix.obj +.\abclib\DebugLib\extraUtilCanon.obj +.\abclib\DebugLib\extraUtilFile.obj +.\abclib\DebugLib\extraUtilMemory.obj +.\abclib\DebugLib\extraUtilMisc.obj +.\abclib\DebugLib\extraUtilProgress.obj +.\abclib\DebugLib\extraUtilReader.obj +.\abclib\DebugLib\extraUtilTruth.obj +.\abclib\DebugLib\extraUtilUtil.obj +.\abclib\DebugLib\st.obj +.\abclib\DebugLib\stmm.obj +.\abclib\DebugLib\mvc.obj +.\abclib\DebugLib\mvcApi.obj +.\abclib\DebugLib\mvcCompare.obj +.\abclib\DebugLib\mvcContain.obj +.\abclib\DebugLib\mvcCover.obj +.\abclib\DebugLib\mvcCube.obj +.\abclib\DebugLib\mvcDivide.obj +.\abclib\DebugLib\mvcDivisor.obj +.\abclib\DebugLib\mvcList.obj +.\abclib\DebugLib\mvcLits.obj +.\abclib\DebugLib\mvcMan.obj +.\abclib\DebugLib\mvcOpAlg.obj +.\abclib\DebugLib\mvcOpBool.obj +.\abclib\DebugLib\mvcPrint.obj +.\abclib\DebugLib\mvcSort.obj +.\abclib\DebugLib\mvcUtils.obj +.\abclib\DebugLib\cofactor.obj +.\abclib\DebugLib\cols.obj +.\abclib\DebugLib\compl.obj +.\abclib\DebugLib\contain.obj +.\abclib\DebugLib\cubehack.obj +.\abclib\DebugLib\cubestr.obj +.\abclib\DebugLib\cvrin.obj +.\abclib\DebugLib\cvrm.obj +.\abclib\DebugLib\cvrmisc.obj +.\abclib\DebugLib\cvrout.obj +.\abclib\DebugLib\dominate.obj +.\abclib\DebugLib\equiv.obj +.\abclib\DebugLib\espresso.obj +.\abclib\DebugLib\essen.obj +.\abclib\DebugLib\exact.obj +.\abclib\DebugLib\expand.obj +.\abclib\DebugLib\gasp.obj +.\abclib\DebugLib\gimpel.obj +.\abclib\DebugLib\globals.obj +.\abclib\DebugLib\hack.obj +.\abclib\DebugLib\indep.obj +.\abclib\DebugLib\irred.obj +.\abclib\DebugLib\map.obj +.\abclib\DebugLib\matrix.obj +.\abclib\DebugLib\mincov.obj +.\abclib\DebugLib\opo.obj +.\abclib\DebugLib\pair.obj +.\abclib\DebugLib\part.obj +.\abclib\DebugLib\primes.obj +.\abclib\DebugLib\reduce.obj +.\abclib\DebugLib\rows.obj +.\abclib\DebugLib\set.obj +.\abclib\DebugLib\setc.obj +.\abclib\DebugLib\sharp.obj +.\abclib\DebugLib\sminterf.obj +.\abclib\DebugLib\solution.obj +.\abclib\DebugLib\sparse.obj +.\abclib\DebugLib\unate.obj +.\abclib\DebugLib\verify.obj +.\abclib\DebugLib\nmApi.obj +.\abclib\DebugLib\nmTable.obj +.\abclib\DebugLib\hopBalance.obj +.\abclib\DebugLib\hopCheck.obj +.\abclib\DebugLib\hopDfs.obj +.\abclib\DebugLib\hopMan.obj +.\abclib\DebugLib\hopMem.obj +.\abclib\DebugLib\hopObj.obj +.\abclib\DebugLib\hopOper.obj +.\abclib\DebugLib\hopTable.obj +.\abclib\DebugLib\hopUtil.obj +.\abclib\DebugLib\ivyBalance.obj +.\abclib\DebugLib\ivyCanon.obj +.\abclib\DebugLib\ivyCheck.obj +.\abclib\DebugLib\ivyCut.obj +.\abclib\DebugLib\ivyCutTrav.obj +.\abclib\DebugLib\ivyDfs.obj +.\abclib\DebugLib\ivyDsd.obj +.\abclib\DebugLib\ivyFanout.obj +.\abclib\DebugLib\ivyFastMap.obj +.\abclib\DebugLib\ivyFraig.obj +.\abclib\DebugLib\ivyHaig.obj +.\abclib\DebugLib\ivyMan.obj +.\abclib\DebugLib\ivyMem.obj +.\abclib\DebugLib\ivyMulti.obj +.\abclib\DebugLib\ivyObj.obj +.\abclib\DebugLib\ivyOper.obj +.\abclib\DebugLib\ivyResyn.obj +.\abclib\DebugLib\ivyRwr.obj +.\abclib\DebugLib\ivySeq.obj +.\abclib\DebugLib\ivyShow.obj +.\abclib\DebugLib\ivyTable.obj +.\abclib\DebugLib\ivyUtil.obj +.\abclib\DebugLib\rwtDec.obj +.\abclib\DebugLib\rwtMan.obj +.\abclib\DebugLib\rwtUtil.obj +.\abclib\DebugLib\mem.obj +.\abclib\DebugLib\abcHie.obj +.\abclib\DebugLib\abcBlifMv.obj +.\abclib\DebugLib\abcCas.obj +.\abclib\DebugLib\abcDar.obj +.\abclib\DebugLib\abcHaig.obj +.\abclib\DebugLib\abcMeasure.obj +.\abclib\DebugLib\abcOdc.obj +.\abclib\DebugLib\abcPart.obj +.\abclib\DebugLib\abcRec.obj +.\abclib\DebugLib\abcQbf.obj +.\abclib\DebugLib\abcQuant.obj +.\abclib\DebugLib\ioReadDsd.obj +.\abclib\DebugLib\ioReadBlifMv.obj +.\abclib\DebugLib\ioReadVerilog.obj +.\abclib\DebugLib\ioWriteVerilog.obj +.\abclib\DebugLib\ioWriteBlifMv.obj +.\abclib\DebugLib\casDec.obj +.\abclib\DebugLib\casCore.obj +.\abclib\DebugLib\pr.obj +.\abclib\DebugLib\satTrace.obj +.\abclib\DebugLib\satInter.obj +.\abclib\DebugLib\satStore.obj +.\abclib\DebugLib\extraBddCas.obj +.\abclib\DebugLib\ioaWriteAig.obj +.\abclib\DebugLib\ioaReadAig.obj +.\abclib\DebugLib\ioaUtil.obj +.\abclib\DebugLib\darBalance.obj +.\abclib\DebugLib\darCore.obj +.\abclib\DebugLib\darCut.obj +.\abclib\DebugLib\darData.obj +.\abclib\DebugLib\darLib.obj +.\abclib\DebugLib\darMan.obj +.\abclib\DebugLib\darPrec.obj +.\abclib\DebugLib\darRefact.obj +.\abclib\DebugLib\darResub.obj +.\abclib\DebugLib\darScript.obj +.\abclib\DebugLib\fraBmc.obj +.\abclib\DebugLib\fraCec.obj +.\abclib\DebugLib\fraClass.obj +.\abclib\DebugLib\fraCnf.obj +.\abclib\DebugLib\fraCore.obj +.\abclib\DebugLib\fraImp.obj +.\abclib\DebugLib\fraInd.obj +.\abclib\DebugLib\fraLcr.obj +.\abclib\DebugLib\fraMan.obj +.\abclib\DebugLib\fraPart.obj +.\abclib\DebugLib\fraSat.obj +.\abclib\DebugLib\fraSec.obj +.\abclib\DebugLib\fraSim.obj +.\abclib\DebugLib\cnfCore.obj +.\abclib\DebugLib\cnfCut.obj +.\abclib\DebugLib\cnfData.obj +.\abclib\DebugLib\cnfMan.obj +.\abclib\DebugLib\cnfMap.obj +.\abclib\DebugLib\cnfPost.obj +.\abclib\DebugLib\cnfUtil.obj +.\abclib\DebugLib\cnfWrite.obj +.\abclib\DebugLib\cswCore.obj +.\abclib\DebugLib\cswCut.obj +.\abclib\DebugLib\cswMan.obj +.\abclib\DebugLib\cswTable.obj +.\abclib\DebugLib\cloud.obj +.\abclib\DebugLib\kitAig.obj +.\abclib\DebugLib\kitBdd.obj +.\abclib\DebugLib\kitCloud.obj +.\abclib\DebugLib\kitDsd.obj +.\abclib\DebugLib\kitFactor.obj +.\abclib\DebugLib\kitGraph.obj +.\abclib\DebugLib\kitHop.obj +.\abclib\DebugLib\kitIsop.obj +.\abclib\DebugLib\kitSop.obj +.\abclib\DebugLib\kitTruth.obj +.\abclib\DebugLib\bdcCore.obj +.\abclib\DebugLib\bdcDec.obj +.\abclib\DebugLib\bdcTable.obj +.\abclib\DebugLib\aigCheck.obj +.\abclib\DebugLib\aigDfs.obj +.\abclib\DebugLib\aigFanout.obj +.\abclib\DebugLib\aigMan.obj +.\abclib\DebugLib\aigMem.obj +.\abclib\DebugLib\aigMffc.obj +.\abclib\DebugLib\aigObj.obj +.\abclib\DebugLib\aigOper.obj +.\abclib\DebugLib\aigOrder.obj +.\abclib\DebugLib\aigPart.obj +.\abclib\DebugLib\aigRepr.obj +.\abclib\DebugLib\aigRet.obj +.\abclib\DebugLib\aigScl.obj +.\abclib\DebugLib\aigSeq.obj +.\abclib\DebugLib\aigShow.obj +.\abclib\DebugLib\aigTable.obj +.\abclib\DebugLib\aigTime.obj +.\abclib\DebugLib\aigTiming.obj +.\abclib\DebugLib\aigTruth.obj +.\abclib\DebugLib\aigTsim.obj +.\abclib\DebugLib\aigUtil.obj +.\abclib\DebugLib\aigWin.obj +.\abclib\DebugLib\bar.obj +.\abclib\DebugLib\resCore.obj +.\abclib\DebugLib\resDivs.obj +.\abclib\DebugLib\resFilter.obj +.\abclib\DebugLib\resSat.obj +.\abclib\DebugLib\resSim.obj +.\abclib\DebugLib\resStrash.obj +.\abclib\DebugLib\resWin.obj +.\abclib\DebugLib\lpkAbcDec.obj +.\abclib\DebugLib\lpkAbcDsd.obj +.\abclib\DebugLib\lpkAbcMux.obj +.\abclib\DebugLib\lpkAbcUtil.obj +.\abclib\DebugLib\lpkCore.obj +.\abclib\DebugLib\lpkCut.obj +.\abclib\DebugLib\lpkMan.obj +.\abclib\DebugLib\lpkMap.obj +.\abclib\DebugLib\lpkMulti.obj +.\abclib\DebugLib\lpkMux.obj +.\abclib\DebugLib\lpkSets.obj +] +Creating command line "link.exe -lib @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP20AC.tmp" +

Output Window

+Compiling... +abcAig.c +abcCheck.c +abcDfs.c +abcFanio.c +abcFunc.c +abcLatch.c +abcLib.c +abcMinBase.c +abcNames.c +abcNetlist.c +abcNtk.c +abcObj.c +abcRefs.c +abcShow.c +abcSop.c +abcUtil.c +abc.c +abcAttach.c +abcAuto.c +abcBalance.c +abcBmc.c +abcClpBdd.c +abcClpSop.c +abcCut.c +abcDebug.c +abcDress.c +abcDsd.c +abcEspresso.c +abcExtract.c +abcFpga.c +abcFpgaFast.c +abcFraig.c +abcFxu.c +abcGen.c +abcIf.c +abcIvy.c +abcLut.c +abcMap.c +abcMini.c +abcMiter.c +abcMulti.c +abcMv.c +abcNtbdd.c +abcOrder.c +abcPrint.c +abcProve.c +abcReconv.c +abcRefactor.c +abcRenode.c +abcReorder.c +abcRestruct.c +abcResub.c +abcRewrite.c +abcRr.c +abcSat.c +abcStrash.c +abcSweep.c +abcSymm.c +abcTiming.c +abcUnate.c +abcUnreach.c +abcVerify.c +abcXsim.c +cmd.c +cmdAlias.c +cmdApi.c +cmdFlag.c +cmdHist.c +cmdUtils.c +io.c +ioReadAiger.c +ioReadBaf.c +ioReadBench.c +ioReadBlif.c +ioReadBlifAig.c +ioReadEdif.c +ioReadEqn.c +ioReadPla.c +ioUtil.c +ioWriteAiger.c +ioWriteBaf.c +ioWriteBench.c +ioWriteBlif.c +ioWriteCnf.c +ioWriteDot.c +ioWriteEqn.c +ioWriteGml.c +ioWriteList.c +ioWritePla.c +libSupport.c +main.c +mainFrame.c +mainInit.c +mainUtils.c +verCore.c +verFormula.c +verParse.c +verStream.c +cuddAddAbs.c +cuddAddApply.c +cuddAddFind.c +cuddAddInv.c +cuddAddIte.c +cuddAddNeg.c +cuddAddWalsh.c +cuddAndAbs.c +cuddAnneal.c +cuddApa.c +C:\_projects\abc\src\bdd\cudd\cuddApa.c(181) : warning C4244: 'return' : conversion from 'unsigned long ' to 'unsigned short ', possible loss of data +C:\_projects\abc\src\bdd\cudd\cuddApa.c(213) : warning C4244: 'return' : conversion from 'unsigned long ' to 'unsigned short ', possible loss of data +C:\_projects\abc\src\bdd\cudd\cuddApa.c(530) : warning C4244: '=' : conversion from 'unsigned short ' to 'unsigned char ', possible loss of data +C:\_projects\abc\src\bdd\cudd\cuddApa.c(588) : warning C4244: '=' : conversion from 'unsigned short ' to 'unsigned char ', possible loss of data +cuddAPI.c +cuddApprox.c +cuddBddAbs.c +cuddBddCorr.c +cuddBddIte.c +cuddBridge.c +cuddCache.c +C:\_projects\abc\src\bdd\cudd\cuddCache.c(902) : warning C4146: unary minus operator applied to unsigned type, result still unsigned +cuddCheck.c +cuddClip.c +cuddCof.c +cuddCompose.c +cuddDecomp.c +cuddEssent.c +cuddExact.c +cuddExport.c +cuddGenCof.c +cuddGenetic.c +cuddGroup.c +C:\_projects\abc\src\bdd\cudd\cuddGroup.c(2062) : warning C4018: '<=' : signed/unsigned mismatch +cuddHarwell.c +cuddInit.c +cuddInteract.c +cuddLCache.c +c:\_projects\abc\src\bdd\cudd\cuddlcache.c(1387) : warning C4146: unary minus operator applied to unsigned type, result still unsigned +cuddLevelQ.c +cuddLinear.c +cuddLiteral.c +cuddMatMult.c +cuddPriority.c +cuddRead.c +cuddRef.c +cuddReorder.c +C:\_projects\abc\src\bdd\cudd\cuddReorder.c(395) : warning C4146: unary minus operator applied to unsigned type, result still unsigned +cuddSat.c +cuddSign.c +cuddSolve.c +cuddSplit.c +cuddSubsetHB.c +cuddSubsetSP.c +cuddSymmetry.c +cuddTable.c +C:\_projects\abc\src\bdd\cudd\cuddTable.c(1822) : warning C4018: '<' : signed/unsigned mismatch +C:\_projects\abc\src\bdd\cudd\cuddTable.c(1927) : warning C4018: '<' : signed/unsigned mismatch +C:\_projects\abc\src\bdd\cudd\cuddTable.c(2235) : warning C4018: '<' : signed/unsigned mismatch +C:\_projects\abc\src\bdd\cudd\cuddTable.c(2303) : warning C4018: '<' : signed/unsigned mismatch +C:\_projects\abc\src\bdd\cudd\cuddTable.c(2358) : warning C4146: unary minus operator applied to unsigned type, result still unsigned +cuddUtil.c +cuddWindow.c +cuddZddCount.c +cuddZddFuncs.c +cuddZddGroup.c +cuddZddIsop.c +cuddZddLin.c +cuddZddMisc.c +cuddZddPort.c +cuddZddReord.c +cuddZddSetop.c +cuddZddSymm.c +cuddZddUtil.c +epd.c +mtrBasic.c +mtrGroup.c +parseCore.c +parseEqn.c +parseStack.c +dsdApi.c +dsdCheck.c +dsdLocal.c +dsdMan.c +dsdProc.c +dsdTree.c +reoApi.c +reoCore.c +reoProfile.c +reoSift.c +reoSwap.c +reoTest.c +reoTransfer.c +reoUnits.c +msatActivity.c +msatClause.c +msatClauseVec.c +msatMem.c +msatOrderH.c +msatQueue.c +msatRead.c +msatSolverApi.c +msatSolverCore.c +msatSolverIo.c +msatSolverSearch.c +msatSort.c +msatVec.c +fraigApi.c +fraigCanon.c +fraigChoice.c +fraigFanout.c +fraigFeed.c +fraigMan.c +fraigMem.c +fraigNode.c +fraigPrime.c +fraigSat.c +fraigTable.c +fraigUtil.c +fraigVec.c +csat_apis.c +satMem.c +satSolver.c +satUtil.c +fxu.c +fxuCreate.c +fxuHeapD.c +fxuHeapS.c +fxuList.c +fxuMatrix.c +fxuPair.c +fxuPrint.c +fxuReduce.c +fxuSelect.c +fxuSingle.c +fxuUpdate.c +rwrDec.c +rwrEva.c +rwrExp.c +rwrLib.c +rwrMan.c +rwrPrint.c +rwrTemp.c +rwrUtil.c +cutApi.c +cutCut.c +cutExpand.c +cutMan.c +cutMerge.c +cutNode.c +cutOracle.c +cutPre22.c +cutSeq.c +cutTruth.c +decAbc.c +decFactor.c +decMan.c +decPrint.c +decUtil.c +simMan.c +simSat.c +simSeq.c +simSupp.c +simSwitch.c +simSym.c +simSymSat.c +simSymSim.c +simSymStr.c +simUtils.c +retArea.c +retCore.c +retDelay.c +retFlow.c +retIncrem.c +retInit.c +retLvalue.c +fpga.c +fpgaCore.c +fpgaCreate.c +fpgaCut.c +fpgaCutUtils.c +fpgaFanout.c +fpgaLib.c +fpgaMatch.c +fpgaSwitch.c +fpgaTime.c +fpgaTruth.c +fpgaUtils.c +fpgaVec.c +mapper.c +mapperCanon.c +mapperCore.c +mapperCreate.c +mapperCut.c +mapperCutUtils.c +mapperFanout.c +mapperLib.c +mapperMatch.c +mapperRefs.c +mapperSuper.c +mapperSwitch.c +mapperTable.c +mapperTime.c +mapperTree.c +mapperTruth.c +mapperUtils.c +mapperVec.c +mio.c +mioApi.c +mioFunc.c +mioRead.c +mioUtils.c +super.c +superAnd.c +superGate.c +superWrite.c +ifCore.c +ifCut.c +ifMan.c +ifMap.c +ifReduce.c +ifSeq.c +ifTime.c +ifTruth.c +ifUtil.c +extraBddAuto.c +extraBddKmap.c +extraBddMisc.c +extraBddSymm.c +extraBddUnate.c +extraUtilBitMatrix.c +extraUtilCanon.c +extraUtilFile.c +extraUtilMemory.c +extraUtilMisc.c +extraUtilProgress.c +extraUtilReader.c +extraUtilTruth.c +extraUtilUtil.c +st.c +stmm.c +mvc.c +mvcApi.c +mvcCompare.c +mvcContain.c +mvcCover.c +mvcCube.c +mvcDivide.c +mvcDivisor.c +mvcList.c +mvcLits.c +mvcMan.c +mvcOpAlg.c +mvcOpBool.c +mvcPrint.c +mvcSort.c +mvcUtils.c +cofactor.c +c:\_projects\abc\src\misc\espresso\cofactor.c(370) : warning C4113: 'int (__cdecl *)()' differs in parameter lists from 'int (__cdecl *)(const void *,const void *)' +cols.c +compl.c +c:\_projects\abc\src\misc\espresso\compl.c(200) : warning C4113: 'int (__cdecl *)()' differs in parameter lists from 'int (__cdecl *)(const void *,const void *)' +c:\_projects\abc\src\misc\espresso\compl.c(201) : warning C4113: 'int (__cdecl *)()' differs in parameter lists from 'int (__cdecl *)(const void *,const void *)' +contain.c +c:\_projects\abc\src\misc\espresso\contain.c(221) : warning C4018: '!=' : signed/unsigned mismatch +c:\_projects\abc\src\misc\espresso\contain.c(249) : warning C4018: '!=' : signed/unsigned mismatch +c:\_projects\abc\src\misc\espresso\contain.c(338) : warning C4113: 'int (__cdecl *)()' differs in parameter lists from 'int (__cdecl *)(const void *,const void *)' +cubehack.c +cubestr.c +cvrin.c +C:\_projects\abc\src\misc\espresso\cvrin.c(38) : warning C4013: 'isspace' undefined; assuming extern returning int +cvrm.c +C:\_projects\abc\src\misc\espresso\cvrm.c(161) : warning C4113: 'int (__cdecl *)()' differs in parameter lists from 'int (__cdecl *)(const void *,const void *)' +C:\_projects\abc\src\misc\espresso\cvrm.c(189) : warning C4113: 'int (__cdecl *)()' differs in parameter lists from 'int (__cdecl *)(const void *,const void *)' +C:\_projects\abc\src\misc\espresso\cvrm.c(380) : warning C4033: 'foreach_output_function' must return a value +C:\_projects\abc\src\misc\espresso\cvrm.c(391) : warning C4033: 'foreach_output_function' must return a value +cvrmisc.c +cvrout.c +C:\_projects\abc\src\misc\espresso\cvrout.c(528) : warning C4033: 'output_symbolic_constraints' must return a value +dominate.c +C:\_projects\abc\src\misc\espresso\cvrout.c(453) : warning C4716: 'makeup_labels' : must return a value +equiv.c +espresso.c +essen.c +exact.c +expand.c +gasp.c +gimpel.c +globals.c +hack.c +C:\_projects\abc\src\misc\espresso\hack.c(21) : warning C4033: 'map_dcset' must return a value +C:\_projects\abc\src\misc\espresso\hack.c(35) : warning C4033: 'map_dcset' must return a value +C:\_projects\abc\src\misc\espresso\hack.c(420) : warning C4033: 'symbolic_hack_labels' must return a value +indep.c +irred.c +map.c +matrix.c +mincov.c +opo.c +pair.c +C:\_projects\abc\src\misc\espresso\pair.c(597) : warning C4033: 'generate_all_pairs' must return a value +part.c +C:\_projects\abc\src\misc\espresso\pair.c(456) : warning C4716: 'find_best_cost' : must return a value +C:\_projects\abc\src\misc\espresso\pair.c(583) : warning C4716: 'minimize_pair' : must return a value +C:\_projects\abc\src\misc\espresso\pair.c(675) : warning C4716: 'pair_free' : must return a value +primes.c +reduce.c +rows.c +set.c +c:\_projects\abc\src\misc\espresso\set.c(453) : warning C4018: '<=' : signed/unsigned mismatch +setc.c +c:\_projects\abc\src\misc\espresso\set.c(27) : warning C4716: 'intcpy' : must return a value +sharp.c +sminterf.c +solution.c +sparse.c +unate.c +C:\_projects\abc\src\misc\espresso\unate.c(172) : warning C4018: '<' : signed/unsigned mismatch +C:\_projects\abc\src\misc\espresso\unate.c(175) : warning C4018: '==' : signed/unsigned mismatch +verify.c +nmApi.c +nmTable.c +hopBalance.c +hopCheck.c +hopDfs.c +hopMan.c +hopMem.c +hopObj.c +hopOper.c +hopTable.c +hopUtil.c +ivyBalance.c +ivyCanon.c +ivyCheck.c +ivyCut.c +ivyCutTrav.c +ivyDfs.c +ivyDsd.c +ivyFanout.c +ivyFastMap.c +ivyFraig.c +ivyHaig.c +ivyMan.c +ivyMem.c +ivyMulti.c +ivyObj.c +ivyOper.c +ivyResyn.c +ivyRwr.c +ivySeq.c +ivyShow.c +ivyTable.c +ivyUtil.c +rwtDec.c +rwtMan.c +rwtUtil.c +mem.c +abcHie.c +abcBlifMv.c +abcCas.c +abcDar.c +abcHaig.c +abcMeasure.c +abcOdc.c +abcPart.c +abcRec.c +abcQbf.c +abcQuant.c +ioReadDsd.c +ioReadBlifMv.c +ioReadVerilog.c +ioWriteVerilog.c +ioWriteBlifMv.c +casDec.c +casCore.c +pr.c +satTrace.c +satInter.c +satStore.c +extraBddCas.c +ioaWriteAig.c +ioaReadAig.c +ioaUtil.c +darBalance.c +darCore.c +darCut.c +darData.c +darLib.c +darMan.c +darPrec.c +darRefact.c +darResub.c +darScript.c +fraBmc.c +fraCec.c +fraClass.c +fraCnf.c +fraCore.c +fraImp.c +fraInd.c +fraLcr.c +fraMan.c +fraPart.c +fraSat.c +fraSec.c +fraSim.c +cnfCore.c +cnfCut.c +cnfData.c +cnfMan.c +cnfMap.c +cnfPost.c +cnfUtil.c +cnfWrite.c +cswCore.c +cswCut.c +cswMan.c +cswTable.c +cloud.c +kitAig.c +kitBdd.c +kitCloud.c +kitDsd.c +kitFactor.c +kitGraph.c +kitHop.c +kitIsop.c +kitSop.c +kitTruth.c +bdcCore.c +bdcDec.c +bdcTable.c +aigCheck.c +aigDfs.c +aigFanout.c +aigMan.c +aigMem.c +aigMffc.c +aigObj.c +aigOper.c +aigOrder.c +aigPart.c +aigRepr.c +aigRet.c +aigScl.c +aigSeq.c +aigShow.c +aigTable.c +aigTime.c +aigTiming.c +aigTruth.c +aigTsim.c +aigUtil.c +aigWin.c +bar.c +resCore.c +resDivs.c +resFilter.c +resSat.c +resSim.c +resStrash.c +resWin.c +lpkAbcDec.c +lpkAbcDsd.c +lpkAbcMux.c +lpkAbcUtil.c +lpkCore.c +lpkCut.c +lpkMan.c +lpkMap.c +lpkMulti.c +lpkMux.c +lpkSets.c +Creating library... +Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP20AD.tmp" with contents +[ +/nologo /o"abclib\DebugLib/abclib.bsc" +.\abclib\DebugLib\abcAig.sbr +.\abclib\DebugLib\abcCheck.sbr +.\abclib\DebugLib\abcDfs.sbr +.\abclib\DebugLib\abcFanio.sbr +.\abclib\DebugLib\abcFunc.sbr +.\abclib\DebugLib\abcLatch.sbr +.\abclib\DebugLib\abcLib.sbr +.\abclib\DebugLib\abcMinBase.sbr +.\abclib\DebugLib\abcNames.sbr +.\abclib\DebugLib\abcNetlist.sbr +.\abclib\DebugLib\abcNtk.sbr +.\abclib\DebugLib\abcObj.sbr +.\abclib\DebugLib\abcRefs.sbr +.\abclib\DebugLib\abcShow.sbr +.\abclib\DebugLib\abcSop.sbr +.\abclib\DebugLib\abcUtil.sbr +.\abclib\DebugLib\abc.sbr +.\abclib\DebugLib\abcAttach.sbr +.\abclib\DebugLib\abcAuto.sbr +.\abclib\DebugLib\abcBalance.sbr +.\abclib\DebugLib\abcBmc.sbr +.\abclib\DebugLib\abcClpBdd.sbr +.\abclib\DebugLib\abcClpSop.sbr +.\abclib\DebugLib\abcCut.sbr +.\abclib\DebugLib\abcDebug.sbr +.\abclib\DebugLib\abcDress.sbr +.\abclib\DebugLib\abcDsd.sbr +.\abclib\DebugLib\abcEspresso.sbr +.\abclib\DebugLib\abcExtract.sbr +.\abclib\DebugLib\abcFpga.sbr +.\abclib\DebugLib\abcFpgaFast.sbr +.\abclib\DebugLib\abcFraig.sbr +.\abclib\DebugLib\abcFxu.sbr +.\abclib\DebugLib\abcGen.sbr +.\abclib\DebugLib\abcIf.sbr +.\abclib\DebugLib\abcIvy.sbr +.\abclib\DebugLib\abcLut.sbr +.\abclib\DebugLib\abcMap.sbr +.\abclib\DebugLib\abcMini.sbr +.\abclib\DebugLib\abcMiter.sbr +.\abclib\DebugLib\abcMulti.sbr +.\abclib\DebugLib\abcMv.sbr +.\abclib\DebugLib\abcNtbdd.sbr +.\abclib\DebugLib\abcOrder.sbr +.\abclib\DebugLib\abcPrint.sbr +.\abclib\DebugLib\abcProve.sbr +.\abclib\DebugLib\abcReconv.sbr +.\abclib\DebugLib\abcRefactor.sbr +.\abclib\DebugLib\abcRenode.sbr +.\abclib\DebugLib\abcReorder.sbr +.\abclib\DebugLib\abcRestruct.sbr +.\abclib\DebugLib\abcResub.sbr +.\abclib\DebugLib\abcRewrite.sbr +.\abclib\DebugLib\abcRr.sbr +.\abclib\DebugLib\abcSat.sbr +.\abclib\DebugLib\abcStrash.sbr +.\abclib\DebugLib\abcSweep.sbr +.\abclib\DebugLib\abcSymm.sbr +.\abclib\DebugLib\abcTiming.sbr +.\abclib\DebugLib\abcUnate.sbr +.\abclib\DebugLib\abcUnreach.sbr +.\abclib\DebugLib\abcVerify.sbr +.\abclib\DebugLib\abcXsim.sbr +.\abclib\DebugLib\cmd.sbr +.\abclib\DebugLib\cmdAlias.sbr +.\abclib\DebugLib\cmdApi.sbr +.\abclib\DebugLib\cmdFlag.sbr +.\abclib\DebugLib\cmdHist.sbr +.\abclib\DebugLib\cmdUtils.sbr +.\abclib\DebugLib\io.sbr +.\abclib\DebugLib\ioReadAiger.sbr +.\abclib\DebugLib\ioReadBaf.sbr +.\abclib\DebugLib\ioReadBench.sbr +.\abclib\DebugLib\ioReadBlif.sbr +.\abclib\DebugLib\ioReadBlifAig.sbr +.\abclib\DebugLib\ioReadEdif.sbr +.\abclib\DebugLib\ioReadEqn.sbr +.\abclib\DebugLib\ioReadPla.sbr +.\abclib\DebugLib\ioUtil.sbr +.\abclib\DebugLib\ioWriteAiger.sbr +.\abclib\DebugLib\ioWriteBaf.sbr +.\abclib\DebugLib\ioWriteBench.sbr +.\abclib\DebugLib\ioWriteBlif.sbr +.\abclib\DebugLib\ioWriteCnf.sbr +.\abclib\DebugLib\ioWriteDot.sbr +.\abclib\DebugLib\ioWriteEqn.sbr +.\abclib\DebugLib\ioWriteGml.sbr +.\abclib\DebugLib\ioWriteList.sbr +.\abclib\DebugLib\ioWritePla.sbr +.\abclib\DebugLib\libSupport.sbr +.\abclib\DebugLib\main.sbr +.\abclib\DebugLib\mainFrame.sbr +.\abclib\DebugLib\mainInit.sbr +.\abclib\DebugLib\mainUtils.sbr +.\abclib\DebugLib\verCore.sbr +.\abclib\DebugLib\verFormula.sbr +.\abclib\DebugLib\verParse.sbr +.\abclib\DebugLib\verStream.sbr +.\abclib\DebugLib\cuddAddAbs.sbr +.\abclib\DebugLib\cuddAddApply.sbr +.\abclib\DebugLib\cuddAddFind.sbr +.\abclib\DebugLib\cuddAddInv.sbr +.\abclib\DebugLib\cuddAddIte.sbr +.\abclib\DebugLib\cuddAddNeg.sbr +.\abclib\DebugLib\cuddAddWalsh.sbr +.\abclib\DebugLib\cuddAndAbs.sbr +.\abclib\DebugLib\cuddAnneal.sbr +.\abclib\DebugLib\cuddApa.sbr +.\abclib\DebugLib\cuddAPI.sbr +.\abclib\DebugLib\cuddApprox.sbr +.\abclib\DebugLib\cuddBddAbs.sbr +.\abclib\DebugLib\cuddBddCorr.sbr +.\abclib\DebugLib\cuddBddIte.sbr +.\abclib\DebugLib\cuddBridge.sbr +.\abclib\DebugLib\cuddCache.sbr +.\abclib\DebugLib\cuddCheck.sbr +.\abclib\DebugLib\cuddClip.sbr +.\abclib\DebugLib\cuddCof.sbr +.\abclib\DebugLib\cuddCompose.sbr +.\abclib\DebugLib\cuddDecomp.sbr +.\abclib\DebugLib\cuddEssent.sbr +.\abclib\DebugLib\cuddExact.sbr +.\abclib\DebugLib\cuddExport.sbr +.\abclib\DebugLib\cuddGenCof.sbr +.\abclib\DebugLib\cuddGenetic.sbr +.\abclib\DebugLib\cuddGroup.sbr +.\abclib\DebugLib\cuddHarwell.sbr +.\abclib\DebugLib\cuddInit.sbr +.\abclib\DebugLib\cuddInteract.sbr +.\abclib\DebugLib\cuddLCache.sbr +.\abclib\DebugLib\cuddLevelQ.sbr +.\abclib\DebugLib\cuddLinear.sbr +.\abclib\DebugLib\cuddLiteral.sbr +.\abclib\DebugLib\cuddMatMult.sbr +.\abclib\DebugLib\cuddPriority.sbr +.\abclib\DebugLib\cuddRead.sbr +.\abclib\DebugLib\cuddRef.sbr +.\abclib\DebugLib\cuddReorder.sbr +.\abclib\DebugLib\cuddSat.sbr +.\abclib\DebugLib\cuddSign.sbr +.\abclib\DebugLib\cuddSolve.sbr +.\abclib\DebugLib\cuddSplit.sbr +.\abclib\DebugLib\cuddSubsetHB.sbr +.\abclib\DebugLib\cuddSubsetSP.sbr +.\abclib\DebugLib\cuddSymmetry.sbr +.\abclib\DebugLib\cuddTable.sbr +.\abclib\DebugLib\cuddUtil.sbr +.\abclib\DebugLib\cuddWindow.sbr +.\abclib\DebugLib\cuddZddCount.sbr +.\abclib\DebugLib\cuddZddFuncs.sbr +.\abclib\DebugLib\cuddZddGroup.sbr +.\abclib\DebugLib\cuddZddIsop.sbr +.\abclib\DebugLib\cuddZddLin.sbr +.\abclib\DebugLib\cuddZddMisc.sbr +.\abclib\DebugLib\cuddZddPort.sbr +.\abclib\DebugLib\cuddZddReord.sbr +.\abclib\DebugLib\cuddZddSetop.sbr +.\abclib\DebugLib\cuddZddSymm.sbr +.\abclib\DebugLib\cuddZddUtil.sbr +.\abclib\DebugLib\epd.sbr +.\abclib\DebugLib\mtrBasic.sbr +.\abclib\DebugLib\mtrGroup.sbr +.\abclib\DebugLib\parseCore.sbr +.\abclib\DebugLib\parseEqn.sbr +.\abclib\DebugLib\parseStack.sbr +.\abclib\DebugLib\dsdApi.sbr +.\abclib\DebugLib\dsdCheck.sbr +.\abclib\DebugLib\dsdLocal.sbr +.\abclib\DebugLib\dsdMan.sbr +.\abclib\DebugLib\dsdProc.sbr +.\abclib\DebugLib\dsdTree.sbr +.\abclib\DebugLib\reoApi.sbr +.\abclib\DebugLib\reoCore.sbr +.\abclib\DebugLib\reoProfile.sbr +.\abclib\DebugLib\reoSift.sbr +.\abclib\DebugLib\reoSwap.sbr +.\abclib\DebugLib\reoTest.sbr +.\abclib\DebugLib\reoTransfer.sbr +.\abclib\DebugLib\reoUnits.sbr +.\abclib\DebugLib\msatActivity.sbr +.\abclib\DebugLib\msatClause.sbr +.\abclib\DebugLib\msatClauseVec.sbr +.\abclib\DebugLib\msatMem.sbr +.\abclib\DebugLib\msatOrderH.sbr +.\abclib\DebugLib\msatQueue.sbr +.\abclib\DebugLib\msatRead.sbr +.\abclib\DebugLib\msatSolverApi.sbr +.\abclib\DebugLib\msatSolverCore.sbr +.\abclib\DebugLib\msatSolverIo.sbr +.\abclib\DebugLib\msatSolverSearch.sbr +.\abclib\DebugLib\msatSort.sbr +.\abclib\DebugLib\msatVec.sbr +.\abclib\DebugLib\fraigApi.sbr +.\abclib\DebugLib\fraigCanon.sbr +.\abclib\DebugLib\fraigChoice.sbr +.\abclib\DebugLib\fraigFanout.sbr +.\abclib\DebugLib\fraigFeed.sbr +.\abclib\DebugLib\fraigMan.sbr +.\abclib\DebugLib\fraigMem.sbr +.\abclib\DebugLib\fraigNode.sbr +.\abclib\DebugLib\fraigPrime.sbr +.\abclib\DebugLib\fraigSat.sbr +.\abclib\DebugLib\fraigTable.sbr +.\abclib\DebugLib\fraigUtil.sbr +.\abclib\DebugLib\fraigVec.sbr +.\abclib\DebugLib\csat_apis.sbr +.\abclib\DebugLib\satMem.sbr +.\abclib\DebugLib\satSolver.sbr +.\abclib\DebugLib\satUtil.sbr +.\abclib\DebugLib\fxu.sbr +.\abclib\DebugLib\fxuCreate.sbr +.\abclib\DebugLib\fxuHeapD.sbr +.\abclib\DebugLib\fxuHeapS.sbr +.\abclib\DebugLib\fxuList.sbr +.\abclib\DebugLib\fxuMatrix.sbr +.\abclib\DebugLib\fxuPair.sbr +.\abclib\DebugLib\fxuPrint.sbr +.\abclib\DebugLib\fxuReduce.sbr +.\abclib\DebugLib\fxuSelect.sbr +.\abclib\DebugLib\fxuSingle.sbr +.\abclib\DebugLib\fxuUpdate.sbr +.\abclib\DebugLib\rwrDec.sbr +.\abclib\DebugLib\rwrEva.sbr +.\abclib\DebugLib\rwrExp.sbr +.\abclib\DebugLib\rwrLib.sbr +.\abclib\DebugLib\rwrMan.sbr +.\abclib\DebugLib\rwrPrint.sbr +.\abclib\DebugLib\rwrTemp.sbr +.\abclib\DebugLib\rwrUtil.sbr +.\abclib\DebugLib\cutApi.sbr +.\abclib\DebugLib\cutCut.sbr +.\abclib\DebugLib\cutExpand.sbr +.\abclib\DebugLib\cutMan.sbr +.\abclib\DebugLib\cutMerge.sbr +.\abclib\DebugLib\cutNode.sbr +.\abclib\DebugLib\cutOracle.sbr +.\abclib\DebugLib\cutPre22.sbr +.\abclib\DebugLib\cutSeq.sbr +.\abclib\DebugLib\cutTruth.sbr +.\abclib\DebugLib\decAbc.sbr +.\abclib\DebugLib\decFactor.sbr +.\abclib\DebugLib\decMan.sbr +.\abclib\DebugLib\decPrint.sbr +.\abclib\DebugLib\decUtil.sbr +.\abclib\DebugLib\simMan.sbr +.\abclib\DebugLib\simSat.sbr +.\abclib\DebugLib\simSeq.sbr +.\abclib\DebugLib\simSupp.sbr +.\abclib\DebugLib\simSwitch.sbr +.\abclib\DebugLib\simSym.sbr +.\abclib\DebugLib\simSymSat.sbr +.\abclib\DebugLib\simSymSim.sbr +.\abclib\DebugLib\simSymStr.sbr +.\abclib\DebugLib\simUtils.sbr +.\abclib\DebugLib\retArea.sbr +.\abclib\DebugLib\retCore.sbr +.\abclib\DebugLib\retDelay.sbr +.\abclib\DebugLib\retFlow.sbr +.\abclib\DebugLib\retIncrem.sbr +.\abclib\DebugLib\retInit.sbr +.\abclib\DebugLib\retLvalue.sbr +.\abclib\DebugLib\fpga.sbr +.\abclib\DebugLib\fpgaCore.sbr +.\abclib\DebugLib\fpgaCreate.sbr +.\abclib\DebugLib\fpgaCut.sbr +.\abclib\DebugLib\fpgaCutUtils.sbr +.\abclib\DebugLib\fpgaFanout.sbr +.\abclib\DebugLib\fpgaLib.sbr +.\abclib\DebugLib\fpgaMatch.sbr +.\abclib\DebugLib\fpgaSwitch.sbr +.\abclib\DebugLib\fpgaTime.sbr +.\abclib\DebugLib\fpgaTruth.sbr +.\abclib\DebugLib\fpgaUtils.sbr +.\abclib\DebugLib\fpgaVec.sbr +.\abclib\DebugLib\mapper.sbr +.\abclib\DebugLib\mapperCanon.sbr +.\abclib\DebugLib\mapperCore.sbr +.\abclib\DebugLib\mapperCreate.sbr +.\abclib\DebugLib\mapperCut.sbr +.\abclib\DebugLib\mapperCutUtils.sbr +.\abclib\DebugLib\mapperFanout.sbr +.\abclib\DebugLib\mapperLib.sbr +.\abclib\DebugLib\mapperMatch.sbr +.\abclib\DebugLib\mapperRefs.sbr +.\abclib\DebugLib\mapperSuper.sbr +.\abclib\DebugLib\mapperSwitch.sbr +.\abclib\DebugLib\mapperTable.sbr +.\abclib\DebugLib\mapperTime.sbr +.\abclib\DebugLib\mapperTree.sbr +.\abclib\DebugLib\mapperTruth.sbr +.\abclib\DebugLib\mapperUtils.sbr +.\abclib\DebugLib\mapperVec.sbr +.\abclib\DebugLib\mio.sbr +.\abclib\DebugLib\mioApi.sbr +.\abclib\DebugLib\mioFunc.sbr +.\abclib\DebugLib\mioRead.sbr +.\abclib\DebugLib\mioUtils.sbr +.\abclib\DebugLib\super.sbr +.\abclib\DebugLib\superAnd.sbr +.\abclib\DebugLib\superGate.sbr +.\abclib\DebugLib\superWrite.sbr +.\abclib\DebugLib\ifCore.sbr +.\abclib\DebugLib\ifCut.sbr +.\abclib\DebugLib\ifMan.sbr +.\abclib\DebugLib\ifMap.sbr +.\abclib\DebugLib\ifReduce.sbr +.\abclib\DebugLib\ifSeq.sbr +.\abclib\DebugLib\ifTime.sbr +.\abclib\DebugLib\ifTruth.sbr +.\abclib\DebugLib\ifUtil.sbr +.\abclib\DebugLib\extraBddAuto.sbr +.\abclib\DebugLib\extraBddKmap.sbr +.\abclib\DebugLib\extraBddMisc.sbr +.\abclib\DebugLib\extraBddSymm.sbr +.\abclib\DebugLib\extraBddUnate.sbr +.\abclib\DebugLib\extraUtilBitMatrix.sbr +.\abclib\DebugLib\extraUtilCanon.sbr +.\abclib\DebugLib\extraUtilFile.sbr +.\abclib\DebugLib\extraUtilMemory.sbr +.\abclib\DebugLib\extraUtilMisc.sbr +.\abclib\DebugLib\extraUtilProgress.sbr +.\abclib\DebugLib\extraUtilReader.sbr +.\abclib\DebugLib\extraUtilTruth.sbr +.\abclib\DebugLib\extraUtilUtil.sbr +.\abclib\DebugLib\st.sbr +.\abclib\DebugLib\stmm.sbr +.\abclib\DebugLib\mvc.sbr +.\abclib\DebugLib\mvcApi.sbr +.\abclib\DebugLib\mvcCompare.sbr +.\abclib\DebugLib\mvcContain.sbr +.\abclib\DebugLib\mvcCover.sbr +.\abclib\DebugLib\mvcCube.sbr +.\abclib\DebugLib\mvcDivide.sbr +.\abclib\DebugLib\mvcDivisor.sbr +.\abclib\DebugLib\mvcList.sbr +.\abclib\DebugLib\mvcLits.sbr +.\abclib\DebugLib\mvcMan.sbr +.\abclib\DebugLib\mvcOpAlg.sbr +.\abclib\DebugLib\mvcOpBool.sbr +.\abclib\DebugLib\mvcPrint.sbr +.\abclib\DebugLib\mvcSort.sbr +.\abclib\DebugLib\mvcUtils.sbr +.\abclib\DebugLib\cofactor.sbr +.\abclib\DebugLib\cols.sbr +.\abclib\DebugLib\compl.sbr +.\abclib\DebugLib\contain.sbr +.\abclib\DebugLib\cubehack.sbr +.\abclib\DebugLib\cubestr.sbr +.\abclib\DebugLib\cvrin.sbr +.\abclib\DebugLib\cvrm.sbr +.\abclib\DebugLib\cvrmisc.sbr +.\abclib\DebugLib\cvrout.sbr +.\abclib\DebugLib\dominate.sbr +.\abclib\DebugLib\equiv.sbr +.\abclib\DebugLib\espresso.sbr +.\abclib\DebugLib\essen.sbr +.\abclib\DebugLib\exact.sbr +.\abclib\DebugLib\expand.sbr +.\abclib\DebugLib\gasp.sbr +.\abclib\DebugLib\gimpel.sbr +.\abclib\DebugLib\globals.sbr +.\abclib\DebugLib\hack.sbr +.\abclib\DebugLib\indep.sbr +.\abclib\DebugLib\irred.sbr +.\abclib\DebugLib\map.sbr +.\abclib\DebugLib\matrix.sbr +.\abclib\DebugLib\mincov.sbr +.\abclib\DebugLib\opo.sbr +.\abclib\DebugLib\pair.sbr +.\abclib\DebugLib\part.sbr +.\abclib\DebugLib\primes.sbr +.\abclib\DebugLib\reduce.sbr +.\abclib\DebugLib\rows.sbr +.\abclib\DebugLib\set.sbr +.\abclib\DebugLib\setc.sbr +.\abclib\DebugLib\sharp.sbr +.\abclib\DebugLib\sminterf.sbr +.\abclib\DebugLib\solution.sbr +.\abclib\DebugLib\sparse.sbr +.\abclib\DebugLib\unate.sbr +.\abclib\DebugLib\verify.sbr +.\abclib\DebugLib\nmApi.sbr +.\abclib\DebugLib\nmTable.sbr +.\abclib\DebugLib\hopBalance.sbr +.\abclib\DebugLib\hopCheck.sbr +.\abclib\DebugLib\hopDfs.sbr +.\abclib\DebugLib\hopMan.sbr +.\abclib\DebugLib\hopMem.sbr +.\abclib\DebugLib\hopObj.sbr +.\abclib\DebugLib\hopOper.sbr +.\abclib\DebugLib\hopTable.sbr +.\abclib\DebugLib\hopUtil.sbr +.\abclib\DebugLib\ivyBalance.sbr +.\abclib\DebugLib\ivyCanon.sbr +.\abclib\DebugLib\ivyCheck.sbr +.\abclib\DebugLib\ivyCut.sbr +.\abclib\DebugLib\ivyCutTrav.sbr +.\abclib\DebugLib\ivyDfs.sbr +.\abclib\DebugLib\ivyDsd.sbr +.\abclib\DebugLib\ivyFanout.sbr +.\abclib\DebugLib\ivyFastMap.sbr +.\abclib\DebugLib\ivyFraig.sbr +.\abclib\DebugLib\ivyHaig.sbr +.\abclib\DebugLib\ivyMan.sbr +.\abclib\DebugLib\ivyMem.sbr +.\abclib\DebugLib\ivyMulti.sbr +.\abclib\DebugLib\ivyObj.sbr +.\abclib\DebugLib\ivyOper.sbr +.\abclib\DebugLib\ivyResyn.sbr +.\abclib\DebugLib\ivyRwr.sbr +.\abclib\DebugLib\ivySeq.sbr +.\abclib\DebugLib\ivyShow.sbr +.\abclib\DebugLib\ivyTable.sbr +.\abclib\DebugLib\ivyUtil.sbr +.\abclib\DebugLib\rwtDec.sbr +.\abclib\DebugLib\rwtMan.sbr +.\abclib\DebugLib\rwtUtil.sbr +.\abclib\DebugLib\mem.sbr +.\abclib\DebugLib\abcHie.sbr +.\abclib\DebugLib\abcBlifMv.sbr +.\abclib\DebugLib\abcCas.sbr +.\abclib\DebugLib\abcDar.sbr +.\abclib\DebugLib\abcHaig.sbr +.\abclib\DebugLib\abcMeasure.sbr +.\abclib\DebugLib\abcOdc.sbr +.\abclib\DebugLib\abcPart.sbr +.\abclib\DebugLib\abcRec.sbr +.\abclib\DebugLib\abcQbf.sbr +.\abclib\DebugLib\abcQuant.sbr +.\abclib\DebugLib\ioReadDsd.sbr +.\abclib\DebugLib\ioReadBlifMv.sbr +.\abclib\DebugLib\ioReadVerilog.sbr +.\abclib\DebugLib\ioWriteVerilog.sbr +.\abclib\DebugLib\ioWriteBlifMv.sbr +.\abclib\DebugLib\casDec.sbr +.\abclib\DebugLib\casCore.sbr +.\abclib\DebugLib\pr.sbr +.\abclib\DebugLib\satTrace.sbr +.\abclib\DebugLib\satInter.sbr +.\abclib\DebugLib\satStore.sbr +.\abclib\DebugLib\extraBddCas.sbr +.\abclib\DebugLib\ioaWriteAig.sbr +.\abclib\DebugLib\ioaReadAig.sbr +.\abclib\DebugLib\ioaUtil.sbr +.\abclib\DebugLib\darBalance.sbr +.\abclib\DebugLib\darCore.sbr +.\abclib\DebugLib\darCut.sbr +.\abclib\DebugLib\darData.sbr +.\abclib\DebugLib\darLib.sbr +.\abclib\DebugLib\darMan.sbr +.\abclib\DebugLib\darPrec.sbr +.\abclib\DebugLib\darRefact.sbr +.\abclib\DebugLib\darResub.sbr +.\abclib\DebugLib\darScript.sbr +.\abclib\DebugLib\fraBmc.sbr +.\abclib\DebugLib\fraCec.sbr +.\abclib\DebugLib\fraClass.sbr +.\abclib\DebugLib\fraCnf.sbr +.\abclib\DebugLib\fraCore.sbr +.\abclib\DebugLib\fraImp.sbr +.\abclib\DebugLib\fraInd.sbr +.\abclib\DebugLib\fraLcr.sbr +.\abclib\DebugLib\fraMan.sbr +.\abclib\DebugLib\fraPart.sbr +.\abclib\DebugLib\fraSat.sbr +.\abclib\DebugLib\fraSec.sbr +.\abclib\DebugLib\fraSim.sbr +.\abclib\DebugLib\cnfCore.sbr +.\abclib\DebugLib\cnfCut.sbr +.\abclib\DebugLib\cnfData.sbr +.\abclib\DebugLib\cnfMan.sbr +.\abclib\DebugLib\cnfMap.sbr +.\abclib\DebugLib\cnfPost.sbr +.\abclib\DebugLib\cnfUtil.sbr +.\abclib\DebugLib\cnfWrite.sbr +.\abclib\DebugLib\cswCore.sbr +.\abclib\DebugLib\cswCut.sbr +.\abclib\DebugLib\cswMan.sbr +.\abclib\DebugLib\cswTable.sbr +.\abclib\DebugLib\cloud.sbr +.\abclib\DebugLib\kitAig.sbr +.\abclib\DebugLib\kitBdd.sbr +.\abclib\DebugLib\kitCloud.sbr +.\abclib\DebugLib\kitDsd.sbr +.\abclib\DebugLib\kitFactor.sbr +.\abclib\DebugLib\kitGraph.sbr +.\abclib\DebugLib\kitHop.sbr +.\abclib\DebugLib\kitIsop.sbr +.\abclib\DebugLib\kitSop.sbr +.\abclib\DebugLib\kitTruth.sbr +.\abclib\DebugLib\bdcCore.sbr +.\abclib\DebugLib\bdcDec.sbr +.\abclib\DebugLib\bdcTable.sbr +.\abclib\DebugLib\aigCheck.sbr +.\abclib\DebugLib\aigDfs.sbr +.\abclib\DebugLib\aigFanout.sbr +.\abclib\DebugLib\aigMan.sbr +.\abclib\DebugLib\aigMem.sbr +.\abclib\DebugLib\aigMffc.sbr +.\abclib\DebugLib\aigObj.sbr +.\abclib\DebugLib\aigOper.sbr +.\abclib\DebugLib\aigOrder.sbr +.\abclib\DebugLib\aigPart.sbr +.\abclib\DebugLib\aigRepr.sbr +.\abclib\DebugLib\aigRet.sbr +.\abclib\DebugLib\aigScl.sbr +.\abclib\DebugLib\aigSeq.sbr +.\abclib\DebugLib\aigShow.sbr +.\abclib\DebugLib\aigTable.sbr +.\abclib\DebugLib\aigTime.sbr +.\abclib\DebugLib\aigTiming.sbr +.\abclib\DebugLib\aigTruth.sbr +.\abclib\DebugLib\aigTsim.sbr +.\abclib\DebugLib\aigUtil.sbr +.\abclib\DebugLib\aigWin.sbr +.\abclib\DebugLib\bar.sbr +.\abclib\DebugLib\resCore.sbr +.\abclib\DebugLib\resDivs.sbr +.\abclib\DebugLib\resFilter.sbr +.\abclib\DebugLib\resSat.sbr +.\abclib\DebugLib\resSim.sbr +.\abclib\DebugLib\resStrash.sbr +.\abclib\DebugLib\resWin.sbr +.\abclib\DebugLib\lpkAbcDec.sbr +.\abclib\DebugLib\lpkAbcDsd.sbr +.\abclib\DebugLib\lpkAbcMux.sbr +.\abclib\DebugLib\lpkAbcUtil.sbr +.\abclib\DebugLib\lpkCore.sbr +.\abclib\DebugLib\lpkCut.sbr +.\abclib\DebugLib\lpkMan.sbr +.\abclib\DebugLib\lpkMap.sbr +.\abclib\DebugLib\lpkMulti.sbr +.\abclib\DebugLib\lpkMux.sbr +.\abclib\DebugLib\lpkSets.sbr] +Creating command line "bscmake.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP20AD.tmp" +Creating browse info file... +

Output Window

+ + + +

Results

+abclib_debug.lib - 0 error(s), 37 warning(s) +
+ + diff --git a/abc70930/abctestlib.dsp b/abc70930/abctestlib.dsp new file mode 100644 index 00000000..3c8fdc4f --- /dev/null +++ b/abc70930/abctestlib.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="abctestlib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=abctestlib - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "abctestlib.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "abctestlib.mak" CFG="abctestlib - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "abctestlib - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "abctestlib - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "abctestlib - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib C:\_projects\abc\abclib\abclib_release.lib /nologo /subsystem:console /machine:I386 /out:"_TEST/abctestlib.exe" + +!ELSEIF "$(CFG)" == "abctestlib - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib C:\_projects\abc\abclib\abclib_debug.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abctestlib.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "abctestlib - Win32 Release" +# Name "abctestlib - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\demo.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/abc70930/abctestlib.dsw b/abc70930/abctestlib.dsw new file mode 100644 index 00000000..45048e1c --- /dev/null +++ b/abc70930/abctestlib.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "abctestlib"=.\abctestlib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/abc70930/abctestlib.plg b/abc70930/abctestlib.plg new file mode 100644 index 00000000..4bf69035 --- /dev/null +++ b/abc70930/abctestlib.plg @@ -0,0 +1,32 @@ + + +
+

Build Log

+

+--------------------Configuration: abctestlib - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP20B8.tmp" with contents +[ +/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"Release/abctestlib.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c +"C:\_projects\abc\demo.c" +] +Creating command line "cl.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP20B8.tmp" +Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP20B9.tmp" with contents +[ +kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib C:\_projects\abc\abclib\abclib_release.lib /nologo /subsystem:console /incremental:no /pdb:"Release/abctestlib.pdb" /machine:I386 /out:"_TEST/abctestlib.exe" +.\Release\demo.obj +] +Creating command line "link.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP20B9.tmp" +

Output Window

+Compiling... +demo.c +Linking... + + + +

Results

+abctestlib.exe - 0 error(s), 0 warning(s) +
+ + diff --git a/abc70930/copyright.txt b/abc70930/copyright.txt new file mode 100644 index 00000000..121d63e8 --- /dev/null +++ b/abc70930/copyright.txt @@ -0,0 +1,18 @@ +Copyright (c) The Regents of the University of California. All rights reserved. + +Permission is hereby granted, without written agreement and without license or +royalty fees, to use, copy, modify, and distribute this software and its +documentation for any purpose, provided that the above copyright notice and +the following two paragraphs appear in all copies of this software. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF +THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF +CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, +AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, +SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + diff --git a/abc70930/demo.c b/abc70930/demo.c new file mode 100644 index 00000000..de162409 --- /dev/null +++ b/abc70930/demo.c @@ -0,0 +1,181 @@ +/**CFile**************************************************************** + + FileName [demo.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [ABC as a static library.] + + Synopsis [A demo program illustrating the use of ABC as a static library.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: demo.c,v 1.00 2005/11/14 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// procedures to start and stop the ABC framework +// (should be called before and after the ABC procedures are called) +extern void Abc_Start(); +extern void Abc_Stop(); + +// procedures to get the ABC framework and execute commands in it +extern void * Abc_FrameGetGlobalFrame(); +extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [The main() procedure.] + + Description [This procedure compiles into a stand-alone program for + DAG-aware rewriting of the AIGs. A BLIF or PLA file to be considered + for rewriting should be given as a command-line argument. Implementation + of the rewriting is inspired by the paper: Per Bjesse, Arne Boralv, + "DAG-aware circuit compression for formal verification", Proc. ICCAD 2004.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int main( int argc, char * argv[] ) +{ + // parameters + int fUseResyn2 = 0; + int fPrintStats = 1; + int fVerify = 1; + // variables + void * pAbc; + char * pFileName; + char Command[1000]; + int clkRead, clkResyn, clkVer, clk; + + ////////////////////////////////////////////////////////////////////////// + // get the input file name + if ( argc != 2 ) + { + printf( "Wrong number of command-line arguments.\n" ); + return 1; + } + pFileName = argv[1]; + + ////////////////////////////////////////////////////////////////////////// + // start the ABC framework + Abc_Start(); + pAbc = Abc_FrameGetGlobalFrame(); + +clk = clock(); + ////////////////////////////////////////////////////////////////////////// + // read the file + sprintf( Command, "read %s", pFileName ); + if ( Cmd_CommandExecute( pAbc, Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return 1; + } + + ////////////////////////////////////////////////////////////////////////// + // balance + sprintf( Command, "balance" ); + if ( Cmd_CommandExecute( pAbc, Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return 1; + } +clkRead = clock() - clk; + + ////////////////////////////////////////////////////////////////////////// + // print stats + if ( fPrintStats ) + { + sprintf( Command, "print_stats" ); + if ( Cmd_CommandExecute( pAbc, Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return 1; + } + } + +clk = clock(); + ////////////////////////////////////////////////////////////////////////// + // synthesize + if ( fUseResyn2 ) + { + sprintf( Command, "balance; rewrite -l; refactor -l; balance; rewrite -l; rewrite -lz; balance; refactor -lz; rewrite -lz; balance" ); + if ( Cmd_CommandExecute( pAbc, Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return 1; + } + } + else + { + sprintf( Command, "balance; rewrite -l; rewrite -lz; balance; rewrite -lz; balance" ); + if ( Cmd_CommandExecute( pAbc, Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return 1; + } + } +clkResyn = clock() - clk; + + ////////////////////////////////////////////////////////////////////////// + // print stats + if ( fPrintStats ) + { + sprintf( Command, "print_stats" ); + if ( Cmd_CommandExecute( pAbc, Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return 1; + } + } + + ////////////////////////////////////////////////////////////////////////// + // write the result in blif + sprintf( Command, "write_blif result.blif" ); + if ( Cmd_CommandExecute( pAbc, Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return 1; + } + + ////////////////////////////////////////////////////////////////////////// + // perform verification +clk = clock(); + if ( fVerify ) + { + sprintf( Command, "cec %s result.blif", pFileName ); + if ( Cmd_CommandExecute( pAbc, Command ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); + return 1; + } + } +clkVer = clock() - clk; + + printf( "Reading = %6.2f sec ", (float)(clkRead)/(float)(CLOCKS_PER_SEC) ); + printf( "Rewriting = %6.2f sec ", (float)(clkResyn)/(float)(CLOCKS_PER_SEC) ); + printf( "Verification = %6.2f sec\n", (float)(clkVer)/(float)(CLOCKS_PER_SEC) ); + + ////////////////////////////////////////////////////////////////////////// + // stop the ABC framework + Abc_Stop(); + return 0; +} + diff --git a/abc70930/depends.sh b/abc70930/depends.sh new file mode 100755 index 00000000..d302cd04 --- /dev/null +++ b/abc70930/depends.sh @@ -0,0 +1,13 @@ +#!/bin/sh +#echo "## Got: $*" +CC="$1" +DIR="$2" +shift 2 +case "$DIR" in + "" | ".") + $CC -MM -MG "$@" | sed -e 's@^\(.*\)\.o:@\1.d \1.o:@' + ;; + *) + $CC -MM -MG "$@" | sed -e "s@^\(.*\)\.o:@$DIR/\1.d $DIR/\1.o:@" + ;; +esac diff --git a/abc70930/examples/C2670.blif b/abc70930/examples/C2670.blif new file mode 100644 index 00000000..d8116b93 --- /dev/null +++ b/abc70930/examples/C2670.blif @@ -0,0 +1,2395 @@ + + +# ATPG -- Automatic Test Pattern Generation for +# Combinational Circuits +# ATPG, Version 1.0, 4/29/86, Author: Ruey-sing Wei and Tony Ma +.model C2670.iscas +.inputs 1(0) 2(1) 3(2) 4(3) 5(4) 6(5) 7(6) 8(7) 11(8) 14(9) 15(10) 16(11) 19(12) 20(13) 21(14) 22(15) 23(16) 24(17) 25(18) 26(19) 27(20) 28(21) 29(22) 32(23) 33(24) 34(25) 35(26) 36(27) 37(28) 40(29) 43(30) 44(31) 47(32) 48(33) 49(34) 50(35) 51(36) 52(37) 53(38) 54(39) 55(40) 56(41) 57(42) 60(43) 61(44) 62(45) 63(46) 64(47) 65(48) 66(49) 67(50) 68(51) 69(52) 72(53) 73(54) 74(55) 75(56) 76(57) 77(58) 78(59) 79(60) 80(61) 81(62) 82(63) 85(64) 86(65) 87(66) 88(67) 89(68) 90(69) 91(70) 92(71) 93(72) 94(73) 95(74) 96(75) 99(76) 100(77) 101(78) 102(79) 103(80) 104(81) 105(82) 106(83) 107(84) 108(85) 111(86) 112(87) 113(88) 114(89) 115(90) 116(91) 117(92) 118(93) 119(94) 120(95) 123(96) 124(97) 125(98) 126(99) 127(100) 128(101) 129(102) 130(103) 131(104) 132(105) 135(106) 136(107) 137(108) 138(109) 139(110) 140(111) 141(112) 142(113) 169(114) 174(115) 177(116) 178(117) 179(118) 180(119) 181(120) 182(121) 183(122) 184(123) 185(124) 186(125) 189(126) 190(127) 191(128) 192(129) 193(130) 194(131) 195(132) 196(133) 197(134) 198(135) 199(136) 200(137) 201(138) 202(139) 203(140) 204(141) 205(142) 206(143) 207(144) 208(145) 209(146) 210(147) 211(148) 212(149) 213(150) 214(151) 215(152) 239(153) 240(154) 241(155) 242(156) 243(157) 244(158) 245(159) 246(160) 247(161) 248(162) 249(163) 250(164) 251(165) 252(166) 253(167) 254(168) 255(169) 256(170) 257(171) 262(172) 263(173) 264(174) 265(175) 266(176) 267(177) 268(178) 269(179) 270(180) 271(181) 272(182) 273(183) 274(184) 275(185) 276(186) 277(187) 278(188) 279(189) 452(190) 483(191) 543(192) 559(193) 567(194) 651(195) 661(196) 860(197) 868(198) 1083(199) 1341(200) 1348(201) 1384(202) 1956(203) 1961(204) 1966(205) 1971(206) 1976(207) 1981(208) 1986(209) 1991(210) 1996(211) 2066(212) 2067(213) 2072(214) 2078(215) 2084(216) 2090(217) 2096(218) 2100(219) 2104(220) 2105(221) 2106(222) 2427(223) 2430(224) 2435(225) 2438(226) 2443(227) 2446(228) 2451(229) 2454(230) 2474(231) 2678(232) +.outputs 169(114) 174(115) 177(116) 178(117) 179(118) 180(119) 181(120) 182(121) 183(122) 184(123) 185(124) 186(125) 189(126) 190(127) 191(128) 192(129) 193(130) 194(131) 195(132) 196(133) 197(134) 198(135) 199(136) 200(137) 201(138) 202(139) 203(140) 204(141) 205(142) 206(143) 207(144) 208(145) 209(146) 210(147) 211(148) 212(149) 213(150) 214(151) 215(152) 239(153) 240(154) 241(155) 242(156) 243(157) 244(158) 245(159) 246(160) 247(161) 248(162) 249(163) 250(164) 251(165) 252(166) 253(167) 254(168) 255(169) 256(170) 257(171) 262(172) 263(173) 264(174) 265(175) 266(176) 267(177) 268(178) 269(179) 270(180) 271(181) 272(182) 273(183) 274(184) 275(185) 276(186) 277(187) 278(188) 279(189) 350(301) 335(299) 409(298) 369(289) 367(288) 411(264) 337(263) 384(262) 218(311) 219(302) 220(306) 221(305) 235(307) 236(303) 237(309) 238(304) 158(349) 259(414) 391(379) 173(389) 223(413) 234(376) 217(423) 325(507) 261(506) 319(656) 160(609) 162(612) 164(607) 166(625) 168(623) 171(621) 153(671) 176(803) 188(761) 299(692) 301(694) 286(696) 303(698) 288(700) 305(702) 290(704) 284(847) 321(848) 297(849) 280(850) 148(851) 282(922) 323(923) 156(1046) 401(1276) 227(1179) 229(1180) 311(1278) 150(1277) 145(1358) 395(1392) 295(1400) 331(1401) 397(1406) 329(1414) 231(1422) 308(1425) 225(1424) +.names 2678(232) 2682(233) +1 0 +.names 2474(231) 2478(234) +1 0 +.names 2454(230) 2458(235) +1 0 +.names 2451(229) 2457(236) +1 0 +.names 2446(228) 2450(237) +1 0 +.names 2443(227) 2449(238) +1 0 +.names 2438(226) 2442(239) +1 0 +.names 2435(225) 2441(240) +1 0 +.names 2430(224) 2434(241) +1 0 +.names 2427(223) 2433(242) +1 0 +.names 2105(221) 1655(243) +1 1 +.names 2105(221) 1418(244) +1 1 +.names 2104(220) 1631(245) +1 1 +.names 2104(220) 1394(246) +1 1 +.names 2100(219) 2103(247) +1 0 +.names 2100(219) 2699(248) +1 1 +.names 2096(218) 2099(249) +1 0 +.names 2096(218) 2702(250) +1 1 +.names 2090(217) 2094(251) +1 0 +.names 2090(217) 2691(252) +1 1 +.names 2084(216) 2088(253) +1 0 +.names 2084(216) 2694(254) +1 1 +.names 2078(215) 2082(255) +1 0 +.names 2078(215) 2683(256) +1 1 +.names 2072(214) 2076(257) +1 0 +.names 2072(214) 2686(258) +1 1 +.names 2090(217) 2084(216) 2078(215) 2072(214) 157(259) +1111 1 +.names 2067(213) 2070(260) +1 0 +.names 2067(213) 2675(261) +1 1 +.names 2066(212) 384(262) +1 1 +.names 2066(212) 337(263) +1 1 +.names 2066(212) 411(264) +1 1 +.names 1996(211) 1999(265) +1 0 +.names 1996(211) 2505(266) +1 1 +.names 1991(210) 1994(267) +1 0 +.names 1991(210) 2508(268) +1 1 +.names 1986(209) 1989(269) +1 0 +.names 1986(209) 2495(270) +1 1 +.names 1981(208) 1984(271) +1 0 +.names 1981(208) 2498(272) +1 1 +.names 1976(207) 1979(273) +1 0 +.names 1976(207) 2487(274) +1 1 +.names 1971(206) 1974(275) +1 0 +.names 1971(206) 2490(276) +1 1 +.names 1966(205) 1969(277) +1 0 +.names 1966(205) 2479(278) +1 1 +.names 1961(204) 1964(279) +1 0 +.names 1961(204) 2482(280) +1 1 +.names 1956(203) 1959(281) +1 0 +.names 1956(203) 2471(282) +1 1 +.names 1384(202) 1385(283) +1 0 +.names 1348(201) 1351(284) +1 0 +.names 1348(201) 2461(285) +1 1 +.names 1341(200) 1344(286) +1 0 +.names 1341(200) 2464(287) +1 1 +.names 1083(199) 367(288) +1 1 +.names 1083(199) 369(289) +1 1 +.names 868(198) 875(290) +1 0 +.names 860(197) 865(291) +1 0 +.names 661(196) 480(292) +1 1 +.names 651(195) 1284(293) +1 1 +.names 651(195) 795(294) +1 1 +.names 559(193) 560(295) +1 0 +.names 543(192) 1261(296) +1 1 +.names 543(192) 772(297) +1 1 +.names 452(190) 409(298) +1 1 +.names 452(190) 335(299) +1 1 +.names 452(190) 654(300) +1 1 +.names 452(190) 350(301) +1 1 +.names 132(105) 219(302) +1 0 +.names 120(95) 236(303) +1 0 +.names 108(85) 238(304) +1 0 +.names 96(75) 221(305) +1 0 +.names 82(63) 220(306) +1 0 +.names 69(52) 235(307) +1 0 +.names 120(95) 57(42) 108(85) 69(52) 1254(308) +1111 1 +.names 57(42) 237(309) +1 0 +.names 132(105) 82(63) 96(75) 44(31) 1251(310) +1111 1 +.names 44(31) 218(311) +1 0 +.names 37(28) 37(28) 486(312) +11 1 +.names 29(22) 2012(313) +1 1 +.names 29(22) 2001(314) +1 1 +.names 16(11) 1721(315) +1 1 +.names 16(11) 1710(316) +1 1 +.names 11(8) 868(198) 882(317) +11 1 +.names 8(7) 658(318) +1 1 +.names 8(7) 655(319) +1 1 +.names 7(6) 661(196) 1955(320) +11 1 +.names 2(1) 15(10) 661(196) 258(321) +111 1 +.names 1(0) 3(2) 546(322) +11 1 +.names 2675(261) 2682(233) 1776(323) +11 0 +.names 2471(282) 2478(234) 1499(324) +11 0 +.names 2454(230) 2457(236) 2459(325) +11 0 +.names 2451(229) 2458(235) 2460(326) +11 0 +.names 2446(228) 2449(238) 1493(327) +11 0 +.names 2443(227) 2450(237) 1494(328) +11 0 +.names 2438(226) 2441(240) 1484(329) +11 0 +.names 2435(225) 2442(239) 1485(330) +11 0 +.names 2430(224) 2433(242) 1475(331) +11 0 +.names 2427(223) 2434(241) 1476(332) +11 0 +.names 2106(222) 1955(320) 216(333) +11 1 +.names 1655(243) 1667(334) +1 0 +.names 1394(246) 1418(244) 1460(335) +11 1 +.names 1418(244) 1430(336) +1 0 +.names 1631(245) 1643(337) +1 0 +.names 1394(246) 1406(338) +1 0 +.names 2699(248) 2705(339) +1 0 +.names 2702(250) 2706(340) +1 0 +.names 2094(251) 2775(341) +1 1 +.names 2691(252) 2697(342) +1 0 +.names 2088(253) 2767(343) +1 1 +.names 2694(254) 2698(344) +1 0 +.names 2082(255) 2759(345) +1 1 +.names 2683(256) 2689(346) +1 0 +.names 2076(257) 2751(347) +1 1 +.names 2686(258) 2690(348) +1 0 +.names 157(259) 158(349) +1 0 +.names 2070(260) 2743(350) +1 1 +.names 2675(261) 2681(351) +1 0 +.names 1999(265) 2735(352) +1 1 +.names 2505(266) 2511(353) +1 0 +.names 1994(267) 2623(354) +1 1 +.names 2508(268) 2512(355) +1 0 +.names 1989(269) 2615(356) +1 1 +.names 2495(270) 2501(357) +1 0 +.names 1984(271) 2607(358) +1 1 +.names 2498(272) 2502(359) +1 0 +.names 1979(273) 2599(360) +1 1 +.names 2487(274) 2493(361) +1 0 +.names 1974(275) 2591(362) +1 1 +.names 2490(276) 2494(363) +1 0 +.names 1969(277) 2583(364) +1 1 +.names 2479(278) 2485(365) +1 0 +.names 1964(279) 2575(366) +1 1 +.names 2482(280) 2486(367) +1 0 +.names 1959(281) 2567(368) +1 1 +.names 2471(282) 2477(369) +1 0 +.names 1351(284) 2559(370) +1 1 +.names 2461(285) 2467(371) +1 0 +.names 1344(286) 2551(372) +1 1 +.names 2464(287) 2468(373) +1 0 +.names 1284(293) 1296(374) +1 0 +.names 795(294) 807(375) +1 0 +.names 567(194) 1955(320) 234(376) +11 0 +.names 1261(296) 1273(377) +1 0 +.names 772(297) 784(378) +1 0 +.names 654(300) 391(379) +1 1 +.names 118(93) 1631(245) 1655(243) 1681(380) +111 1 +.names 117(92) 1631(245) 1655(243) 1689(381) +111 1 +.names 116(91) 1631(245) 1655(243) 1693(382) +111 1 +.names 115(90) 1631(245) 1655(243) 1697(383) +111 1 +.names 114(89) 1394(246) 1418(244) 1444(384) +111 1 +.names 113(88) 1394(246) 1418(244) 1448(385) +111 1 +.names 112(87) 1394(246) 1418(244) 1452(386) +111 1 +.names 111(86) 1394(246) 1418(244) 1456(387) +111 1 +.names 107(84) 1631(245) 1655(243) 1685(388) +111 1 +.names 94(73) 654(300) 173(389) +11 1 +.names 80(61) 772(297) 795(294) 821(390) +111 1 +.names 79(60) 772(297) 795(294) 829(391) +111 1 +.names 78(59) 772(297) 795(294) 833(392) +111 1 +.names 77(58) 772(297) 795(294) 837(393) +111 1 +.names 76(57) 1261(296) 1284(293) 1310(394) +111 1 +.names 75(56) 1261(296) 1284(293) 1314(395) +111 1 +.names 74(55) 1261(296) 1284(293) 1318(396) +111 1 +.names 73(54) 1261(296) 1284(293) 1322(397) +111 1 +.names 72(53) 1261(296) 1284(293) 1326(398) +111 1 +.names 68(51) 772(297) 795(294) 825(399) +111 1 +.names 1254(308) 1251(310) 558(400) +11 1 +.names 1254(308) 1256(401) +1 0 +.names 1251(310) 1253(402) +1 0 +.names 486(312) 487(403) +1 0 +.names 2012(313) 2018(404) +1 0 +.names 2001(314) 2007(405) +1 0 +.names 1721(315) 1728(406) +1 0 +.names 1710(316) 1716(407) +1 0 +.names 11(8) 875(290) 881(408) +11 1 +.names 658(318) 1831(409) +1 1 +.names 658(318) 1893(410) +1 1 +.names 655(319) 748(411) +1 1 +.names 655(319) 994(412) +1 1 +.names 1955(320) 223(413) +1 0 +.names 258(321) 259(414) +1 0 +.names 546(322) 547(415) +1 0 +.names 2678(232) 2681(351) 1775(416) +11 0 +.names 2474(231) 2477(369) 1498(417) +11 0 +.names 2459(325) 2460(326) 2518(418) +11 0 +.names 1493(327) 1494(328) 1495(419) +11 0 +.names 1484(329) 1485(330) 1486(420) +11 0 +.names 1475(331) 1476(332) 1477(421) +11 0 +.names 2106(222) 1253(402) 550(422) +11 1 +.names 216(333) 217(423) +1 0 +.names 1406(338) 1418(244) 1459(424) +11 1 +.names 1406(338) 1430(336) 1457(425) +11 1 +.names 1394(246) 1430(336) 1458(426) +11 1 +.names 2699(248) 2706(340) 2708(427) +11 0 +.names 2702(250) 2705(339) 2707(428) +11 0 +.names 2775(341) 2781(429) +1 0 +.names 2691(252) 2698(344) 1794(430) +11 0 +.names 2767(343) 2773(431) +1 0 +.names 2694(254) 2697(342) 1793(432) +11 0 +.names 2759(345) 2765(433) +1 0 +.names 2683(256) 2690(348) 1785(434) +11 0 +.names 2751(347) 2757(435) +1 0 +.names 2686(258) 2689(346) 1784(436) +11 0 +.names 2743(350) 2749(437) +1 0 +.names 2735(352) 2741(438) +1 0 +.names 2505(266) 2512(355) 2514(439) +11 0 +.names 2623(354) 2629(440) +1 0 +.names 2508(268) 2511(353) 2513(441) +11 0 +.names 2615(356) 2621(442) +1 0 +.names 2495(270) 2502(359) 2504(443) +11 0 +.names 2607(358) 2613(444) +1 0 +.names 2498(272) 2501(357) 2503(445) +11 0 +.names 2599(360) 2605(446) +1 0 +.names 2487(274) 2494(363) 1517(447) +11 0 +.names 2591(362) 2597(448) +1 0 +.names 2490(276) 2493(361) 1516(449) +11 0 +.names 2583(364) 2589(450) +1 0 +.names 2479(278) 2486(367) 1508(451) +11 0 +.names 2575(366) 2581(452) +1 0 +.names 2482(280) 2485(365) 1507(453) +11 0 +.names 2567(368) 2573(454) +1 0 +.names 2559(370) 2565(455) +1 0 +.names 2461(285) 2468(373) 2470(456) +11 0 +.names 2551(372) 2557(457) +1 0 +.names 2464(287) 2467(371) 2469(458) +11 0 +.names 1273(377) 1284(293) 1317(459) +11 1 +.names 567(194) 1256(401) 552(460) +11 1 +.names 142(113) 1643(337) 1667(334) 1678(461) +111 1 +.names 141(112) 1643(337) 1667(334) 1686(462) +111 1 +.names 140(111) 1643(337) 1667(334) 1690(463) +111 1 +.names 139(110) 1643(337) 1667(334) 1694(464) +111 1 +.names 138(109) 1406(338) 1430(336) 1441(465) +111 1 +.names 137(108) 1406(338) 1430(336) 1445(466) +111 1 +.names 136(107) 1406(338) 1430(336) 1449(467) +111 1 +.names 135(106) 1406(338) 1430(336) 1453(468) +111 1 +.names 131(104) 1643(337) 1667(334) 1682(469) +111 1 +.names 130(103) 1643(337) 1655(243) 1680(470) +111 1 +.names 129(102) 1643(337) 1655(243) 1688(471) +111 1 +.names 128(101) 1643(337) 1655(243) 1692(472) +111 1 +.names 127(100) 1643(337) 1655(243) 1696(473) +111 1 +.names 126(99) 1406(338) 1418(244) 1443(474) +111 1 +.names 125(98) 1406(338) 1418(244) 1447(475) +111 1 +.names 124(97) 1406(338) 1418(244) 1451(476) +111 1 +.names 123(96) 1406(338) 1418(244) 1455(477) +111 1 +.names 119(94) 1643(337) 1655(243) 1684(478) +111 1 +.names 106(83) 1631(245) 1667(334) 1679(479) +111 1 +.names 105(82) 1631(245) 1667(334) 1687(480) +111 1 +.names 104(81) 1631(245) 1667(334) 1691(481) +111 1 +.names 103(80) 1631(245) 1667(334) 1695(482) +111 1 +.names 102(79) 1394(246) 1430(336) 1442(483) +111 1 +.names 101(78) 1394(246) 1430(336) 1446(484) +111 1 +.names 100(77) 1394(246) 1430(336) 1450(485) +111 1 +.names 99(76) 1394(246) 1430(336) 1454(486) +111 1 +.names 95(74) 1631(245) 1667(334) 1683(487) +111 1 +.names 93(72) 784(378) 807(375) 818(488) +111 1 +.names 92(71) 784(378) 807(375) 826(489) +111 1 +.names 91(70) 784(378) 807(375) 830(490) +111 1 +.names 90(69) 784(378) 807(375) 834(491) +111 1 +.names 89(68) 1273(377) 1296(374) 1307(492) +111 1 +.names 88(67) 1273(377) 1296(374) 1311(493) +111 1 +.names 87(66) 1273(377) 1296(374) 1315(494) +111 1 +.names 86(65) 1273(377) 1296(374) 1319(495) +111 1 +.names 85(64) 1273(377) 1296(374) 1323(496) +111 1 +.names 81(62) 784(378) 807(375) 822(497) +111 1 +.names 67(50) 784(378) 795(294) 820(498) +111 1 +.names 66(49) 784(378) 795(294) 828(499) +111 1 +.names 65(48) 784(378) 795(294) 832(500) +111 1 +.names 64(47) 784(378) 795(294) 836(501) +111 1 +.names 63(46) 1273(377) 1284(293) 1309(502) +111 1 +.names 62(45) 1273(377) 1284(293) 1313(503) +111 1 +.names 61(44) 1273(377) 1284(293) 1321(504) +111 1 +.names 60(43) 1273(377) 1284(293) 1325(505) +111 1 +.names 558(400) 261(506) +1 0 +.names 558(400) 325(507) +1 1 +.names 56(41) 784(378) 795(294) 824(508) +111 1 +.names 55(40) 772(297) 807(375) 819(509) +111 1 +.names 54(39) 772(297) 807(375) 827(510) +111 1 +.names 53(38) 772(297) 807(375) 831(511) +111 1 +.names 52(37) 772(297) 807(375) 835(512) +111 1 +.names 51(36) 1261(296) 1296(374) 1308(513) +111 1 +.names 50(35) 1261(296) 1296(374) 1312(514) +111 1 +.names 49(34) 1261(296) 1296(374) 1316(515) +111 1 +.names 48(33) 1261(296) 1296(374) 1320(516) +111 1 +.names 47(32) 1261(296) 1296(374) 1324(517) +111 1 +.names 43(30) 772(297) 807(375) 823(518) +111 1 +.names 35(26) 2018(404) 2035(519) +11 1 +.names 34(25) 2018(404) 2033(520) +11 1 +.names 33(24) 2007(405) 2029(521) +11 1 +.names 32(23) 2007(405) 2025(522) +11 1 +.names 28(21) 2018(404) 2037(523) +11 1 +.names 27(20) 2018(404) 2031(524) +11 1 +.names 26(19) 2007(405) 2027(525) +11 1 +.names 25(18) 2007(405) 2023(526) +11 1 +.names 24(17) 1728(406) 1750(527) +11 1 +.names 23(16) 1728(406) 1746(528) +11 1 +.names 22(15) 1728(406) 1744(529) +11 1 +.names 21(14) 1728(406) 1742(530) +11 1 +.names 20(13) 1716(407) 1738(531) +11 1 +.names 19(12) 1716(407) 1734(532) +11 1 +.names 881(408) 882(317) 894(533) +00 0 +.names 6(5) 1728(406) 1748(534) +11 1 +.names 5(4) 1716(407) 1740(535) +11 1 +.names 4(3) 1716(407) 1736(536) +11 1 +.names 1775(416) 1776(323) 1777(537) +11 0 +.names 1498(417) 1499(324) 1500(538) +11 0 +.names 2518(418) 2522(539) +1 0 +.names 1495(419) 1525(540) +1 1 +.names 1495(419) 1521(541) +1 1 +.names 1486(420) 1490(542) +1 0 +.names 1477(421) 1481(543) +1 0 +.names 550(422) 551(544) +1 0 +.names 1457(425) 1458(426) 1459(424) 1460(335) 1473(545) +0000 0 +.names 2707(428) 2708(427) 2730(546) +11 0 +.names 1793(432) 1794(430) 1795(547) +11 0 +.names 1784(436) 1785(434) 1786(548) +11 0 +.names 2513(441) 2514(439) 2525(549) +11 0 +.names 2503(445) 2504(443) 2528(550) +11 0 +.names 1516(449) 1517(447) 1518(551) +11 0 +.names 1507(453) 1508(451) 1509(552) +11 0 +.names 2469(458) 2470(456) 2515(553) +11 0 +.names 552(460) 553(554) +1 0 +.names 1678(461) 1679(479) 1680(470) 1681(380) 2634(555) +0000 0 +.names 1686(462) 1687(480) 1688(471) 1689(381) 1701(556) +0000 0 +.names 1690(463) 1691(481) 1692(472) 1693(382) 1704(557) +0000 0 +.names 1694(464) 1695(482) 1696(473) 1697(383) 1707(558) +0000 0 +.names 1441(465) 1442(483) 1443(474) 1444(384) 1461(559) +0000 0 +.names 1445(466) 1446(484) 1447(475) 1448(385) 1464(560) +0000 0 +.names 1449(467) 1450(485) 1451(476) 1452(386) 1467(561) +0000 0 +.names 1453(468) 1454(486) 1455(477) 1456(387) 1470(562) +0000 0 +.names 1682(469) 1683(487) 1684(478) 1685(388) 1698(563) +0000 0 +.names 818(488) 819(509) 820(498) 821(390) 838(564) +0000 0 +.names 826(489) 827(510) 828(499) 829(391) 846(565) +0000 0 +.names 830(490) 831(511) 832(500) 833(392) 854(566) +0000 0 +.names 834(491) 835(512) 836(501) 837(393) 857(567) +0000 0 +.names 1307(492) 1308(513) 1309(502) 1310(394) 1327(568) +0000 0 +.names 1311(493) 1312(514) 1313(503) 1314(395) 1329(569) +0000 0 +.names 1315(494) 1316(515) 1317(459) 1318(396) 1331(570) +0000 0 +.names 1319(495) 1320(516) 1321(504) 1322(397) 1333(571) +0000 0 +.names 1323(496) 1324(517) 1325(505) 1326(398) 1335(572) +0000 0 +.names 822(497) 823(518) 824(508) 825(399) 841(573) +0000 0 +.names 1777(537) 1781(574) +1 0 +.names 1500(538) 1504(575) +1 0 +.names 2515(553) 2522(539) 2524(576) +11 0 +.names 1490(542) 1481(543) 1525(540) 1541(577) +111 1 +.names 1525(540) 1528(578) +1 0 +.names 1521(541) 1524(579) +1 0 +.names 1486(420) 1477(421) 1521(541) 1538(580) +111 1 +.names 551(544) 553(554) 554(581) +11 1 +.names 1473(545) 2665(582) +1 1 +.names 2103(247) 1473(545) 1218(583) +11 0 +.names 2730(546) 2734(584) +1 0 +.names 2099(249) 1470(562) 1213(585) +11 0 +.names 1795(547) 1810(586) +1 1 +.names 1795(547) 1806(587) +1 1 +.names 1786(548) 1790(588) +1 0 +.names 2525(549) 2531(589) +1 0 +.names 2528(550) 2532(590) +1 0 +.names 1518(551) 1533(591) +1 1 +.names 1518(551) 1529(592) +1 1 +.names 1509(552) 1513(593) +1 0 +.names 1461(559) 1385(283) 1387(594) +11 1 +.names 2515(553) 2521(595) +1 0 +.names 841(573) 875(290) 885(596) +11 1 +.names 846(565) 875(290) 887(597) +11 1 +.names 1327(568) 868(198) 893(598) +11 1 +.names 841(573) 860(197) 152(599) +11 1 +.names 846(565) 860(197) 147(600) +11 1 +.names 838(564) 860(197) 144(601) +11 1 +.names 2634(555) 2638(602) +1 0 +.names 1701(556) 2642(603) +1 1 +.names 1704(557) 1250(604) +1 1 +.names 1704(557) 2639(605) +1 1 +.names 1707(558) 2650(606) +1 1 +.names 1461(559) 164(607) +1 0 +.names 1461(559) 2647(608) +1 1 +.names 1464(560) 160(609) +1 0 +.names 1464(560) 1389(610) +1 0 +.names 1464(560) 2658(611) +1 1 +.names 1467(561) 162(612) +1 0 +.names 1467(561) 2655(613) +1 1 +.names 1470(562) 2668(614) +1 1 +.names 1698(563) 2631(615) +1 1 +.names 838(564) 516(616) +1 1 +.names 838(564) 1028(617) +1 0 +.names 846(565) 1035(618) +1 0 +.names 846(565) 852(619) +1 0 +.names 854(566) 1041(620) +1 1 +.names 857(567) 171(621) +1 0 +.names 857(567) 1049(622) +1 1 +.names 1327(568) 168(623) +1 0 +.names 1327(568) 1057(624) +1 1 +.names 1329(569) 166(625) +1 0 +.names 1329(569) 1060(626) +1 1 +.names 1331(570) 1066(627) +1 1 +.names 1333(571) 1072(628) +1 1 +.names 1335(572) 1078(629) +1 1 +.names 841(573) 1031(630) +1 0 +.names 841(573) 2154(631) +1 1 +.names 1467(561) 2012(313) 2036(632) +11 1 +.names 1464(560) 2012(313) 2034(633) +11 1 +.names 1461(559) 2012(313) 2032(634) +11 1 +.names 1470(562) 2012(313) 2038(635) +11 1 +.names 1698(563) 2001(314) 2024(636) +11 1 +.names 1707(558) 2001(314) 2030(637) +11 1 +.names 1704(557) 2001(314) 2028(638) +11 1 +.names 1701(556) 2001(314) 2026(639) +11 1 +.names 1331(570) 1721(315) 1747(640) +11 1 +.names 1329(569) 1721(315) 1745(641) +11 1 +.names 1327(568) 1721(315) 1743(642) +11 1 +.names 1335(572) 1721(315) 1751(643) +11 1 +.names 1333(571) 1721(315) 1749(644) +11 1 +.names 841(573) 1710(316) 1735(645) +11 1 +.names 857(567) 1710(316) 1741(646) +11 1 +.names 854(566) 1710(316) 1739(647) +11 1 +.names 846(565) 1710(316) 1737(648) +11 1 +.names 1786(548) 1777(537) 1806(587) 1821(649) +111 1 +.names 1790(588) 1781(574) 1810(586) 1824(650) +111 1 +.names 1509(552) 1500(538) 1529(592) 1544(651) +111 1 +.names 1513(593) 1504(575) 1533(591) 1547(652) +111 1 +.names 2518(418) 2521(595) 2523(653) +11 0 +.names 1481(543) 1486(420) 1524(579) 1537(654) +111 1 +.names 1477(421) 1490(542) 1528(578) 1540(655) +111 1 +.names 554(581) 319(656) +1 1 +.names 1218(583) 1473(545) 1234(657) +11 1 +.names 2665(582) 2671(658) +1 0 +.names 2103(247) 1218(583) 1232(659) +11 1 +.names 2099(249) 1213(585) 1225(660) +11 1 +.names 1810(586) 1813(661) +1 0 +.names 1806(587) 1809(662) +1 0 +.names 2525(549) 2532(590) 2534(663) +11 0 +.names 2528(550) 2531(589) 2533(664) +11 0 +.names 1533(591) 1536(665) +1 0 +.names 1529(592) 1532(666) +1 0 +.names 1387(594) 466(667) +1 0 +.names 516(616) 875(290) 883(668) +11 1 +.names 1041(620) 875(290) 891(669) +11 1 +.names 1049(622) 868(198) 889(670) +11 1 +.names 865(291) 152(599) 153(671) +00 0 +.names 560(295) 852(619) 562(672) +11 0 +.names 480(292) 483(191) 554(581) 547(415) 187(673) +1111 1 +.names 2631(615) 2638(602) 1753(674) +11 0 +.names 2642(603) 2646(675) +1 0 +.names 2639(605) 2645(676) +1 0 +.names 2650(606) 2654(677) +1 0 +.names 2647(608) 2653(678) +1 0 +.names 2658(611) 2662(679) +1 0 +.names 2655(613) 2661(680) +1 0 +.names 1213(585) 1470(562) 1227(681) +11 1 +.names 2668(614) 2672(682) +1 0 +.names 2631(615) 2637(683) +1 0 +.names 516(616) 2235(684) +1 1 +.names 1028(617) 2110(685) +1 1 +.names 1028(617) 2164(686) +1 1 +.names 1035(618) 2350(687) +1 1 +.names 1035(618) 2118(688) +1 1 +.names 1035(618) 2262(689) +1 1 +.names 1035(618) 2172(690) +1 1 +.names 852(619) 2151(691) +1 0 +.names 1041(620) 299(692) +1 1 +.names 1041(620) 1043(693) +1 0 +.names 1049(622) 301(694) +1 1 +.names 1049(622) 1051(695) +1 0 +.names 1057(624) 286(696) +1 1 +.names 1057(624) 2123(697) +1 0 +.names 1060(626) 303(698) +1 1 +.names 1060(626) 1062(699) +1 0 +.names 1066(627) 288(700) +1 1 +.names 1066(627) 1068(701) +1 0 +.names 1072(628) 305(702) +1 1 +.names 1072(628) 1074(703) +1 0 +.names 1078(629) 290(704) +1 1 +.names 1078(629) 1080(705) +1 0 +.names 1031(630) 2107(706) +1 1 +.names 1031(630) 2161(707) +1 1 +.names 2154(631) 2158(708) +1 0 +.names 1389(610) 1387(594) 40(29) 456(709) +111 1 +.names 480(292) 483(191) 36(27) 554(581) 175(710) +1111 1 +.names 2035(519) 2036(632) 2778(711) +00 0 +.names 2033(520) 2034(633) 2770(712) +00 0 +.names 2029(521) 2030(637) 2754(713) +00 0 +.names 2025(522) 2026(639) 2738(714) +00 0 +.names 2037(523) 2038(635) 2065(715) +00 0 +.names 2031(524) 2032(634) 2762(716) +00 0 +.names 2027(525) 2028(638) 2746(717) +00 0 +.names 2023(526) 2024(636) 2626(718) +00 0 +.names 1750(527) 1751(643) 2618(719) +00 0 +.names 1746(528) 1747(640) 2602(720) +00 0 +.names 1744(529) 1745(641) 2594(721) +00 0 +.names 1742(530) 1743(642) 2586(722) +00 0 +.names 1738(531) 1739(647) 2570(723) +00 0 +.names 1734(532) 1735(645) 2554(724) +00 0 +.names 1748(534) 1749(644) 2610(725) +00 0 +.names 1740(535) 1741(646) 2578(726) +00 0 +.names 1736(536) 1737(648) 2562(727) +00 0 +.names 1777(537) 1790(588) 1813(661) 1823(728) +111 1 +.names 1500(538) 1513(593) 1536(665) 1546(729) +111 1 +.names 2523(653) 2524(576) 2538(730) +11 0 +.names 1540(655) 1541(577) 1542(731) +00 1 +.names 1537(654) 1538(580) 1539(732) +00 1 +.names 1232(659) 1234(657) 1235(733) +00 0 +.names 2665(582) 2672(682) 2674(734) +11 0 +.names 1225(660) 1227(681) 1228(735) +00 0 +.names 2778(711) 2781(429) 2059(736) +11 0 +.names 2770(712) 2773(431) 2055(737) +11 0 +.names 2762(716) 2765(433) 2051(738) +11 0 +.names 1781(574) 1786(548) 1809(662) 1820(739) +111 1 +.names 2754(713) 2757(435) 2047(740) +11 0 +.names 2746(717) 2749(437) 2043(741) +11 0 +.names 2738(714) 2741(438) 2039(742) +11 0 +.names 2533(664) 2534(663) 2546(743) +11 0 +.names 2626(718) 2629(440) 1597(744) +11 0 +.names 2618(719) 2621(442) 1593(745) +11 0 +.names 2610(725) 2613(444) 1589(746) +11 0 +.names 2602(720) 2605(446) 1585(747) +11 0 +.names 2594(721) 2597(448) 1581(748) +11 0 +.names 2586(722) 2589(450) 1577(749) +11 0 +.names 1504(575) 1509(552) 1532(666) 1543(750) +111 1 +.names 2578(726) 2581(452) 1573(751) +11 0 +.names 2570(723) 2573(454) 1569(752) +11 0 +.names 2562(727) 2565(455) 1565(753) +11 0 +.names 2554(724) 2557(457) 1561(754) +11 0 +.names 887(597) 889(670) 897(755) +00 0 +.names 891(669) 893(598) 898(756) +00 0 +.names 562(672) 868(198) 886(757) +11 1 +.names 562(672) 865(291) 146(758) +11 1 +.names 562(672) 2207(759) +1 0 +.names 562(672) 592(760) +1 1 +.names 187(673) 188(761) +1 0 +.names 2634(555) 2637(683) 1752(762) +11 0 +.names 2642(603) 2645(676) 1761(763) +11 0 +.names 2639(605) 2646(675) 1762(764) +11 0 +.names 2650(606) 2653(678) 1770(765) +11 0 +.names 2647(608) 2654(677) 1771(766) +11 0 +.names 2658(611) 2661(680) 2663(767) +11 0 +.names 2655(613) 2662(679) 2664(768) +11 0 +.names 2668(614) 2671(658) 2673(769) +11 0 +.names 2235(684) 2241(770) +1 0 +.names 2110(685) 2114(771) +1 0 +.names 2164(686) 2168(772) +1 0 +.names 2350(687) 2354(773) +1 0 +.names 2118(688) 2122(774) +1 0 +.names 2262(689) 2266(775) +1 0 +.names 2172(690) 2176(776) +1 0 +.names 2151(691) 2157(777) +1 0 +.names 2151(691) 2158(708) 2160(778) +11 0 +.names 1043(693) 2342(779) +1 1 +.names 1043(693) 2115(780) +1 1 +.names 1043(693) 2254(781) +1 1 +.names 1043(693) 2169(782) +1 1 +.names 1051(695) 2422(783) +1 1 +.names 1051(695) 2334(784) +1 1 +.names 1051(695) 2126(785) +1 1 +.names 2123(697) 2129(786) +1 0 +.names 1062(699) 2134(787) +1 1 +.names 1062(699) 2180(788) +1 1 +.names 1068(701) 2131(789) +1 1 +.names 1068(701) 2177(790) +1 1 +.names 1074(703) 2144(791) +1 1 +.names 1074(703) 2190(792) +1 1 +.names 1080(705) 2141(793) +1 1 +.names 1080(705) 2187(794) +1 1 +.names 2107(706) 2113(795) +1 0 +.names 2161(707) 2167(796) +1 0 +.names 40(29) 1389(610) 466(667) 468(797) +111 1 +.names 456(709) 995(798) +1 1 +.names 456(709) 1006(799) +1 0 +.names 456(709) 743(800) +1 0 +.names 456(709) 749(801) +1 1 +.names 456(709) 462(802) +1 0 +.names 175(710) 176(803) +1 0 +.names 2778(711) 2782(804) +1 0 +.names 2770(712) 2774(805) +1 0 +.names 2754(713) 2758(806) +1 0 +.names 2738(714) 2742(807) +1 0 +.names 2762(716) 2766(808) +1 0 +.names 2746(717) 2750(809) +1 0 +.names 2626(718) 2630(810) +1 0 +.names 2618(719) 2622(811) +1 0 +.names 2602(720) 2606(812) +1 0 +.names 2594(721) 2598(813) +1 0 +.names 2586(722) 2590(814) +1 0 +.names 2570(723) 2574(815) +1 0 +.names 2554(724) 2558(816) +1 0 +.names 2610(725) 2614(817) +1 0 +.names 2578(726) 2582(818) +1 0 +.names 2562(727) 2566(819) +1 0 +.names 1820(739) 1821(649) 1822(820) +00 1 +.names 1823(728) 1824(650) 1825(821) +00 1 +.names 1543(750) 1544(651) 1545(822) +00 1 +.names 1546(729) 1547(652) 1548(823) +00 1 +.names 2538(730) 2542(824) +1 0 +.names 1542(731) 1539(732) 2535(825) +11 0 +.names 1235(733) 1245(826) +1 0 +.names 2673(769) 2674(734) 2709(827) +11 0 +.names 1228(735) 1243(828) +1 0 +.names 2775(341) 2782(804) 2060(829) +11 0 +.names 2767(343) 2774(805) 2056(830) +11 0 +.names 2759(345) 2766(808) 2052(831) +11 0 +.names 2751(347) 2758(806) 2048(832) +11 0 +.names 2743(350) 2750(809) 2044(833) +11 0 +.names 2735(352) 2742(807) 2040(834) +11 0 +.names 2546(743) 2550(835) +1 0 +.names 2623(354) 2630(810) 1598(836) +11 0 +.names 2615(356) 2622(811) 1594(837) +11 0 +.names 2607(358) 2614(817) 1590(838) +11 0 +.names 2599(360) 2606(812) 1586(839) +11 0 +.names 2591(362) 2598(813) 1582(840) +11 0 +.names 2583(364) 2590(814) 1578(841) +11 0 +.names 2575(366) 2582(818) 1574(842) +11 0 +.names 2567(368) 2574(815) 1570(843) +11 0 +.names 2559(370) 2566(819) 1566(844) +11 0 +.names 2551(372) 2558(816) 1562(845) +11 0 +.names 885(596) 886(757) 896(846) +00 0 +.names 897(755) 284(847) +1 1 +.names 897(755) 321(848) +1 1 +.names 898(756) 297(849) +1 1 +.names 898(756) 280(850) +1 1 +.names 146(758) 147(600) 148(851) +00 0 +.names 2207(759) 2213(852) +1 0 +.names 592(760) 596(853) +1 0 +.names 1752(762) 1753(674) 1754(854) +11 0 +.names 1701(556) 743(800) 502(855) +11 1 +.names 1701(556) 1006(799) 729(856) +11 1 +.names 1761(763) 1762(764) 1763(857) +11 0 +.names 1250(604) 743(800) 508(858) +11 1 +.names 1250(604) 1006(799) 735(859) +11 1 +.names 1770(765) 1771(766) 1772(860) +11 0 +.names 2663(767) 2664(768) 2712(861) +11 0 +.names 1698(563) 743(800) 496(862) +11 1 +.names 1698(563) 1006(799) 723(863) +11 1 +.names 2110(685) 2113(795) 569(864) +11 0 +.names 2164(686) 2167(796) 599(865) +11 0 +.names 2115(780) 2122(774) 579(866) +11 0 +.names 2169(782) 2176(776) 609(867) +11 0 +.names 2342(779) 2346(868) +1 0 +.names 2115(780) 2121(869) +1 0 +.names 2254(781) 2258(870) +1 0 +.names 2169(782) 2175(871) +1 0 +.names 2422(783) 2426(872) +1 0 +.names 2334(784) 2338(873) +1 0 +.names 2126(785) 2129(786) 587(874) +11 0 +.names 2126(785) 2130(875) +1 0 +.names 1057(624) 749(801) 765(876) +11 1 +.names 1057(624) 995(798) 1014(877) +11 1 +.names 1060(626) 749(801) 769(878) +11 1 +.names 1060(626) 995(798) 1018(879) +11 1 +.names 2134(787) 2138(880) +1 0 +.names 2180(788) 2184(881) +1 0 +.names 2131(789) 2137(882) +1 0 +.names 2177(790) 2183(883) +1 0 +.names 2144(791) 2148(884) +1 0 +.names 2190(792) 2194(885) +1 0 +.names 1078(629) 743(800) 490(886) +11 1 +.names 1078(629) 1006(799) 717(887) +11 1 +.names 2141(793) 2147(888) +1 0 +.names 2187(794) 2193(889) +1 0 +.names 2107(706) 2114(771) 570(890) +11 0 +.names 2161(707) 2168(772) 600(891) +11 0 +.names 2154(631) 2157(777) 2159(892) +11 0 +.names 468(797) 1257(893) +1 1 +.names 468(797) 1258(894) +1 1 +.names 995(798) 999(895) +1 0 +.names 749(801) 753(896) +1 0 +.names 462(802) 475(897) +1 1 +.names 462(802) 1337(898) +1 1 +.names 1825(821) 1822(820) 2727(899) +11 0 +.names 1548(823) 1545(822) 2543(900) +11 0 +.names 2535(825) 2542(824) 1550(901) +11 0 +.names 2535(825) 2541(902) +1 0 +.names 1235(733) 1245(826) 1094(903) +11 1 +.names 2709(827) 2715(904) +1 0 +.names 1228(735) 1243(828) 1096(905) +11 1 +.names 2059(736) 2060(829) 2061(906) +11 0 +.names 2055(737) 2056(830) 2057(907) +11 0 +.names 2051(738) 2052(831) 2053(908) +11 0 +.names 2047(740) 2048(832) 2049(909) +11 0 +.names 2043(741) 2044(833) 2045(910) +11 0 +.names 2039(742) 2040(834) 2041(911) +11 0 +.names 1597(744) 1598(836) 1599(912) +11 0 +.names 1593(745) 1594(837) 1595(913) +11 0 +.names 1589(746) 1590(838) 1591(914) +11 0 +.names 1585(747) 1586(839) 1587(915) +11 0 +.names 1581(748) 1582(840) 1583(916) +11 0 +.names 1577(749) 1578(841) 1579(917) +11 0 +.names 1573(751) 1574(842) 1575(918) +11 0 +.names 1569(752) 1570(843) 1571(919) +11 0 +.names 1565(753) 1566(844) 1567(920) +11 0 +.names 1561(754) 1562(845) 1563(921) +11 0 +.names 896(846) 282(922) +1 1 +.names 896(846) 323(923) +1 1 +.names 1754(854) 1758(924) +1 0 +.names 1763(857) 1767(925) +1 0 +.names 1772(860) 1802(926) +1 1 +.names 1772(860) 1798(927) +1 1 +.names 2712(861) 2716(928) +1 0 +.names 569(864) 570(890) 571(929) +11 0 +.names 599(865) 600(891) 601(930) +11 0 +.names 2118(688) 2121(869) 578(931) +11 0 +.names 2172(690) 2175(871) 608(932) +11 0 +.names 2159(892) 2160(778) 2210(933) +11 0 +.names 1057(624) 753(896) 763(934) +11 1 +.names 1057(624) 999(895) 1012(935) +11 1 +.names 2123(697) 2130(875) 588(936) +11 0 +.names 1060(626) 753(896) 767(937) +11 1 +.names 1060(626) 999(895) 1016(938) +11 1 +.names 2134(787) 2137(882) 2139(939) +11 0 +.names 2180(788) 2183(883) 2185(940) +11 0 +.names 1066(627) 753(896) 531(941) +11 1 +.names 1066(627) 999(895) 705(942) +11 1 +.names 2131(789) 2138(880) 2140(943) +11 0 +.names 2177(790) 2184(881) 2186(944) +11 0 +.names 1072(628) 753(896) 537(945) +11 1 +.names 1072(628) 999(895) 711(946) +11 1 +.names 2144(791) 2147(888) 2149(947) +11 0 +.names 2190(792) 2193(889) 2195(948) +11 0 +.names 2141(793) 2148(884) 2150(949) +11 0 +.names 2187(794) 2194(885) 2196(950) +11 0 +.names 1257(893) 742(951) +1 1 +.names 1257(893) 1005(952) +1 1 +.names 1258(894) 1845(953) +1 1 +.names 1258(894) 1907(954) +1 1 +.names 475(897) 1836(955) +1 1 +.names 475(897) 1850(956) +1 1 +.names 475(897) 1355(957) +1 1 +.names 1337(898) 1898(958) +1 1 +.names 1337(898) 1912(959) +1 1 +.names 1337(898) 1601(960) +1 1 +.names 2727(899) 2733(961) +1 0 +.names 2543(900) 2549(962) +1 0 +.names 2538(730) 2541(902) 1549(963) +11 0 +.names 1094(903) 1245(826) 154(964) +00 0 +.names 2709(827) 2716(928) 2718(965) +11 0 +.names 2727(899) 2734(584) 1829(966) +11 0 +.names 1096(905) 1243(828) 155(967) +00 0 +.names 2061(906) 2062(968) +1 0 +.names 2057(907) 2058(969) +1 0 +.names 2053(908) 2054(970) +1 0 +.names 2049(909) 2050(971) +1 0 +.names 2070(260) 1850(956) 1876(972) +11 1 +.names 2070(260) 1912(959) 1938(973) +11 1 +.names 2045(910) 2046(974) +1 0 +.names 1999(265) 1850(956) 1874(975) +11 1 +.names 1999(265) 1912(959) 1936(976) +11 1 +.names 2041(911) 2042(977) +1 0 +.names 2543(900) 2550(835) 1552(978) +11 0 +.names 1994(267) 1850(956) 1872(979) +11 1 +.names 1994(267) 1912(959) 1934(980) +11 1 +.names 1599(912) 1600(981) +1 0 +.names 1989(269) 1850(956) 1870(982) +11 1 +.names 1989(269) 1912(959) 1932(983) +11 1 +.names 1595(913) 1596(984) +1 0 +.names 1984(271) 1836(955) 1868(985) +11 1 +.names 1984(271) 1898(958) 1930(986) +11 1 +.names 1591(914) 1592(987) +1 0 +.names 1979(273) 1836(955) 1866(988) +11 1 +.names 1979(273) 1898(958) 1928(989) +11 1 +.names 1587(915) 1588(990) +1 0 +.names 1974(275) 1836(955) 1863(991) +11 1 +.names 1974(275) 1898(958) 1925(992) +11 1 +.names 1583(916) 1584(993) +1 0 +.names 1969(277) 1836(955) 1858(994) +11 1 +.names 1969(277) 1898(958) 1920(995) +11 1 +.names 1579(917) 1580(996) +1 0 +.names 1964(279) 1355(957) 1377(997) +11 1 +.names 1964(279) 1601(960) 1623(998) +11 1 +.names 1575(918) 1576(999) +1 0 +.names 1959(281) 1355(957) 1373(1000) +11 1 +.names 1959(281) 1601(960) 1619(1001) +11 1 +.names 1571(919) 1572(1002) +1 0 +.names 1351(284) 1601(960) 1615(1003) +11 1 +.names 1351(284) 1355(957) 1369(1004) +11 1 +.names 1567(920) 1568(1005) +1 0 +.names 1344(286) 1355(957) 676(1006) +11 1 +.names 1344(286) 1601(960) 1108(1007) +11 1 +.names 1563(921) 1564(1008) +1 0 +.names 2210(933) 2213(852) 2215(1009) +11 0 +.names 1763(857) 1754(854) 1798(927) 1815(1010) +111 1 +.names 1767(925) 1758(924) 1802(926) 1818(1011) +111 1 +.names 502(855) 742(951) 504(1012) +11 1 +.names 729(856) 1005(952) 731(1013) +11 1 +.names 508(858) 742(951) 510(1014) +11 1 +.names 735(859) 1005(952) 737(1015) +11 1 +.names 1802(926) 1805(1016) +1 0 +.names 1798(927) 1801(1017) +1 0 +.names 2712(861) 2715(904) 2717(1018) +11 0 +.names 496(862) 742(951) 498(1019) +11 1 +.names 723(863) 1005(952) 725(1020) +11 1 +.names 571(929) 575(1021) +1 0 +.names 601(930) 605(1022) +1 0 +.names 578(931) 579(866) 580(1023) +11 0 +.names 608(932) 609(867) 610(1024) +11 0 +.names 2210(933) 2214(1025) +1 0 +.names 587(874) 588(936) 589(1026) +11 0 +.names 763(934) 765(876) 519(1027) +00 0 +.names 1012(935) 1014(877) 693(1028) +00 0 +.names 767(937) 769(878) 525(1029) +00 0 +.names 1016(938) 1018(879) 699(1030) +00 0 +.names 2139(939) 2140(943) 2200(1031) +11 0 +.names 2185(940) 2186(944) 2220(1032) +11 0 +.names 2149(947) 2150(949) 2197(1033) +11 0 +.names 2195(948) 2196(950) 2217(1034) +11 0 +.names 490(886) 742(951) 492(1035) +11 1 +.names 717(887) 1005(952) 719(1036) +11 1 +.names 1836(955) 1842(1037) +1 0 +.names 1355(957) 1361(1038) +1 0 +.names 1898(958) 1904(1039) +1 0 +.names 1601(960) 1607(1040) +1 0 +.names 531(941) 748(411) 533(1041) +11 1 +.names 537(945) 748(411) 539(1042) +11 1 +.names 705(942) 994(412) 707(1043) +11 1 +.names 711(946) 994(412) 713(1044) +11 1 +.names 1549(963) 1550(901) 1091(1045) +11 0 +.names 154(964) 155(967) 156(1046) +11 0 +.names 2717(1018) 2718(965) 2722(1047) +11 0 +.names 2730(546) 2733(961) 1828(1048) +11 0 +.names 2094(251) 1842(1037) 1861(1049) +11 1 +.names 2094(251) 1904(1039) 1923(1050) +11 1 +.names 2088(253) 1842(1037) 1856(1051) +11 1 +.names 2088(253) 1904(1039) 1918(1052) +11 1 +.names 2058(969) 2054(970) 2050(971) 2046(974) 2042(977) 1558(1053) +11111 1 +.names 2082(255) 1361(1038) 1375(1054) +11 1 +.names 2082(255) 1607(1040) 1621(1055) +11 1 +.names 2076(257) 1361(1038) 1371(1056) +11 1 +.names 2076(257) 1607(1040) 1617(1057) +11 1 +.names 2070(260) 1361(1038) 1368(1058) +11 1 +.names 2070(260) 1607(1040) 1614(1059) +11 1 +.names 1999(265) 1361(1038) 675(1060) +11 1 +.names 1999(265) 1607(1040) 1107(1061) +11 1 +.names 2546(743) 2549(962) 1551(1062) +11 0 +.names 1600(981) 1596(984) 1592(987) 1588(990) 1584(993) 1554(1063) +11111 1 +.names 1580(996) 1576(999) 1572(1002) 1568(1005) 1564(1008) 1555(1064) +11111 1 +.names 2207(759) 2214(1025) 2216(1065) +11 0 +.names 1754(854) 1767(925) 1805(1016) 1817(1066) +111 1 +.names 504(1012) 505(1067) +1 0 +.names 731(1013) 732(1068) +1 0 +.names 1758(924) 1763(857) 1801(1017) 1814(1069) +111 1 +.names 510(1014) 511(1070) +1 0 +.names 737(1015) 738(1071) +1 0 +.names 498(1019) 499(1072) +1 0 +.names 725(1020) 726(1073) +1 0 +.names 580(1023) 584(1074) +1 0 +.names 610(1024) 621(1075) +1 1 +.names 610(1024) 625(1076) +1 1 +.names 589(1026) 617(1077) +1 1 +.names 589(1026) 613(1078) +1 1 +.names 2200(1031) 2204(1079) +1 0 +.names 2220(1032) 2224(1080) +1 0 +.names 2197(1033) 2203(1081) +1 0 +.names 2217(1034) 2223(1082) +1 0 +.names 492(1035) 493(1083) +1 0 +.names 719(1036) 720(1084) +1 0 +.names 1874(975) 1845(953) 1889(1085) +11 1 +.names 1872(979) 1845(953) 1887(1086) +11 1 +.names 1870(982) 1845(953) 1885(1087) +11 1 +.names 1876(972) 1845(953) 1891(1088) +11 1 +.names 1936(976) 1907(954) 1951(1089) +11 1 +.names 1934(980) 1907(954) 1949(1090) +11 1 +.names 1932(983) 1907(954) 1947(1091) +11 1 +.names 1938(973) 1907(954) 1953(1092) +11 1 +.names 2065(715) 2062(968) 1557(1093) +11 1 +.names 1868(985) 1831(409) 1883(1094) +11 1 +.names 1866(988) 1831(409) 1881(1095) +11 1 +.names 1930(986) 1893(410) 1945(1096) +11 1 +.names 1928(989) 1893(410) 1943(1097) +11 1 +.names 519(1027) 748(411) 521(1098) +11 1 +.names 525(1029) 748(411) 527(1099) +11 1 +.names 533(1041) 534(1100) +1 0 +.names 539(1042) 540(1101) +1 0 +.names 693(1028) 994(412) 695(1102) +11 1 +.names 699(1030) 994(412) 701(1103) +11 1 +.names 707(1043) 708(1104) +1 0 +.names 713(1044) 714(1105) +1 0 +.names 1091(1045) 1092(1106) +1 0 +.names 2722(1047) 2726(1107) +1 0 +.names 1828(1048) 1829(966) 1830(1108) +11 0 +.names 1557(1093) 1558(1053) 1559(1109) +11 1 +.names 1551(1062) 1552(978) 1553(1110) +11 0 +.names 1554(1063) 1555(1064) 1556(1111) +11 1 +.names 1861(1049) 1863(991) 1864(1112) +00 0 +.names 1923(1050) 1925(992) 1926(1113) +00 0 +.names 1856(1051) 1858(994) 1859(1114) +00 0 +.names 1918(1052) 1920(995) 1921(1115) +00 0 +.names 1375(1054) 1377(997) 1382(1116) +00 0 +.names 1621(1055) 1623(998) 1628(1117) +00 0 +.names 1371(1056) 1373(1000) 1380(1118) +00 0 +.names 1617(1057) 1619(1001) 1626(1119) +00 0 +.names 1614(1059) 1615(1003) 1624(1120) +00 0 +.names 1368(1058) 1369(1004) 1378(1121) +00 0 +.names 675(1060) 676(1006) 677(1122) +00 0 +.names 1107(1061) 1108(1007) 1109(1123) +00 0 +.names 2215(1009) 2216(1065) 2238(1124) +11 0 +.names 601(930) 592(760) 621(1075) 636(1125) +111 1 +.names 605(1022) 596(853) 625(1076) 639(1126) +111 1 +.names 1814(1069) 1815(1010) 1816(1127) +00 1 +.names 1817(1066) 1818(1011) 1819(1128) +00 1 +.names 1889(1085) 505(1067) 915(1129) +11 1 +.names 505(1067) 2278(1130) +1 1 +.names 1951(1089) 732(1068) 1133(1131) +11 1 +.names 732(1068) 2366(1132) +1 1 +.names 1891(1088) 511(1070) 907(1133) +11 1 +.names 511(1070) 2270(1134) +1 1 +.names 1953(1092) 738(1071) 1125(1135) +11 1 +.names 738(1071) 2358(1136) +1 1 +.names 1887(1086) 499(1072) 922(1137) +11 1 +.names 499(1072) 2286(1138) +1 1 +.names 1949(1090) 726(1073) 1140(1139) +11 1 +.names 726(1073) 2374(1140) +1 1 +.names 580(1023) 571(929) 613(1078) 630(1141) +111 1 +.names 584(1074) 575(1021) 617(1077) 633(1142) +111 1 +.names 621(1075) 624(1143) +1 0 +.names 625(1076) 628(1144) +1 0 +.names 617(1077) 620(1145) +1 0 +.names 613(1078) 616(1146) +1 0 +.names 2200(1031) 2203(1081) 2205(1147) +11 0 +.names 2220(1032) 2223(1082) 2225(1148) +11 0 +.names 2197(1033) 2204(1079) 2206(1149) +11 0 +.names 2217(1034) 2224(1080) 2226(1150) +11 0 +.names 493(1083) 1885(1087) 924(1151) +11 1 +.names 493(1083) 2294(1152) +1 1 +.names 720(1084) 1947(1091) 1142(1153) +11 1 +.names 720(1084) 2382(1154) +1 1 +.names 1889(1085) 2275(1155) +1 1 +.names 1887(1086) 2283(1156) +1 1 +.names 1885(1087) 2291(1157) +1 1 +.names 1891(1088) 2267(1158) +1 1 +.names 1951(1089) 2363(1159) +1 1 +.names 1949(1090) 2371(1160) +1 1 +.names 1947(1091) 2379(1161) +1 1 +.names 1953(1092) 2355(1162) +1 1 +.names 1883(1094) 540(1101) 937(1163) +11 1 +.names 1883(1094) 2299(1164) +1 1 +.names 1881(1095) 534(1100) 946(1165) +11 1 +.names 1881(1095) 2307(1166) +1 1 +.names 1945(1096) 714(1105) 1155(1167) +11 1 +.names 1945(1096) 2387(1168) +1 1 +.names 1943(1097) 708(1104) 1164(1169) +11 1 +.names 1943(1097) 2395(1170) +1 1 +.names 521(1098) 522(1171) +1 0 +.names 527(1099) 528(1172) +1 0 +.names 534(1100) 2310(1173) +1 1 +.names 540(1101) 2302(1174) +1 1 +.names 695(1102) 696(1175) +1 0 +.names 701(1103) 702(1176) +1 0 +.names 708(1104) 2398(1177) +1 1 +.names 714(1105) 2390(1178) +1 1 +.names 1830(1108) 227(1179) +1 0 +.names 1553(1110) 229(1180) +1 0 +.names 1382(1116) 2331(1181) +1 1 +.names 1628(1117) 2419(1182) +1 1 +.names 1380(1118) 2251(1183) +1 1 +.names 1626(1119) 2339(1184) +1 1 +.names 1624(1120) 2347(1185) +1 1 +.names 1378(1121) 2259(1186) +1 1 +.names 2238(1124) 2242(1187) +1 0 +.names 592(760) 605(1022) 628(1144) 638(1188) +111 1 +.names 596(853) 601(930) 624(1143) 635(1189) +111 1 +.names 1819(1128) 1816(1127) 2719(1190) +11 0 +.names 2278(1130) 2282(1191) +1 0 +.names 2366(1132) 2370(1192) +1 0 +.names 2270(1134) 2274(1193) +1 0 +.names 2358(1136) 2362(1194) +1 0 +.names 2286(1138) 2290(1195) +1 0 +.names 2374(1140) 2378(1196) +1 0 +.names 2238(1124) 2241(770) 645(1197) +11 0 +.names 571(929) 584(1074) 620(1145) 632(1198) +111 1 +.names 575(1021) 580(1023) 616(1146) 629(1199) +111 1 +.names 1378(1121) 1035(618) 674(1200) +11 1 +.names 1624(1120) 1035(618) 1106(1201) +11 1 +.names 1380(1118) 1043(693) 671(1202) +11 1 +.names 1626(1119) 1043(693) 1104(1203) +11 1 +.names 1382(1116) 1051(695) 967(1204) +11 1 +.names 1628(1117) 1051(695) 1184(1205) +11 1 +.names 2205(1147) 2206(1149) 2230(1206) +11 0 +.names 2225(1148) 2226(1150) 2246(1207) +11 0 +.names 2294(1152) 2298(1208) +1 0 +.names 2382(1154) 2386(1209) +1 0 +.names 677(1122) 1031(630) 679(1210) +11 1 +.names 1109(1123) 1031(630) 1110(1211) +11 1 +.names 2275(1155) 2281(1212) +1 0 +.names 2283(1156) 2289(1213) +1 0 +.names 2291(1157) 2297(1214) +1 0 +.names 2267(1158) 2273(1215) +1 0 +.names 2363(1159) 2369(1216) +1 0 +.names 2371(1160) 2377(1217) +1 0 +.names 2379(1161) 2385(1218) +1 0 +.names 2355(1162) 2361(1219) +1 0 +.names 1092(1106) 14(9) 1093(1220) +11 1 +.names 1556(1111) 1559(1109) 894(533) 1560(1221) +111 1 +.names 2299(1164) 2305(1222) +1 0 +.names 2307(1166) 2313(1223) +1 0 +.names 1864(1112) 1831(409) 1879(1224) +11 1 +.names 1859(1114) 1831(409) 1877(1225) +11 1 +.names 2387(1168) 2393(1226) +1 0 +.names 2395(1170) 2401(1227) +1 0 +.names 1926(1113) 1893(410) 1941(1228) +11 1 +.names 1921(1115) 1893(410) 1939(1229) +11 1 +.names 522(1171) 2326(1230) +1 1 +.names 528(1172) 2318(1231) +1 1 +.names 2310(1173) 2314(1232) +1 0 +.names 2302(1174) 2306(1233) +1 0 +.names 696(1175) 2414(1234) +1 1 +.names 702(1176) 2406(1235) +1 1 +.names 2398(1177) 2402(1236) +1 0 +.names 2390(1178) 2394(1237) +1 0 +.names 2719(1190) 2726(1107) 1827(1238) +11 0 +.names 2331(1181) 2337(1239) +1 0 +.names 2419(1182) 2425(1240) +1 0 +.names 2251(1183) 2257(1241) +1 0 +.names 2339(1184) 2345(1242) +1 0 +.names 2347(1185) 2353(1243) +1 0 +.names 2259(1186) 2265(1244) +1 0 +.names 635(1189) 636(1125) 637(1245) +00 1 +.names 638(1188) 639(1126) 640(1246) +00 1 +.names 2719(1190) 2725(1247) +1 0 +.names 2278(1130) 2281(1212) 908(1248) +11 0 +.names 2366(1132) 2369(1216) 1126(1249) +11 0 +.names 2270(1134) 2273(1215) 899(1250) +11 0 +.names 2358(1136) 2361(1219) 1117(1251) +11 0 +.names 2286(1138) 2289(1213) 916(1252) +11 0 +.names 2374(1140) 2377(1217) 1134(1253) +11 0 +.names 2235(684) 2242(1187) 646(1254) +11 0 +.names 629(1199) 630(1141) 631(1255) +00 1 +.names 632(1198) 633(1142) 634(1256) +00 1 +.names 2347(1185) 2354(773) 1115(1257) +11 0 +.names 2259(1186) 2266(775) 684(1258) +11 0 +.names 2339(1184) 2346(868) 1099(1259) +11 0 +.names 2251(1183) 2258(870) 665(1260) +11 0 +.names 2419(1182) 2426(872) 1181(1261) +11 0 +.names 2331(1181) 2338(873) 963(1262) +11 0 +.names 2230(1206) 2234(1263) +1 0 +.names 2246(1207) 2250(1264) +1 0 +.names 2294(1152) 2297(1214) 925(1265) +11 0 +.names 2382(1154) 2385(1218) 1143(1266) +11 0 +.names 2275(1155) 2282(1191) 909(1267) +11 0 +.names 2283(1156) 2290(1195) 917(1268) +11 0 +.names 2291(1157) 2298(1208) 926(1269) +11 0 +.names 2267(1158) 2274(1193) 900(1270) +11 0 +.names 2363(1159) 2370(1192) 1127(1271) +11 0 +.names 2371(1160) 2378(1196) 1135(1272) +11 0 +.names 2379(1161) 2386(1209) 1144(1273) +11 0 +.names 2355(1162) 2362(1194) 1118(1274) +11 0 +.names 1093(1220) 1087(1275) +1 0 +.names 1093(1220) 401(1276) +1 1 +.names 1560(1221) 150(1277) +1 0 +.names 1560(1221) 311(1278) +1 1 +.names 2299(1164) 2306(1233) 929(1279) +11 0 +.names 2307(1166) 2314(1232) 939(1280) +11 0 +.names 1879(1224) 2315(1281) +1 1 +.names 1877(1225) 2323(1282) +1 1 +.names 2387(1168) 2394(1237) 1147(1283) +11 0 +.names 2395(1170) 2402(1236) 1157(1284) +11 0 +.names 1941(1228) 2403(1285) +1 1 +.names 1939(1229) 2411(1286) +1 1 +.names 2326(1230) 2330(1287) +1 0 +.names 1877(1225) 522(1171) 961(1288) +11 1 +.names 1879(1224) 528(1172) 954(1289) +11 1 +.names 2318(1231) 2322(1290) +1 0 +.names 2310(1173) 2313(1223) 938(1291) +11 0 +.names 2302(1174) 2305(1222) 928(1292) +11 0 +.names 2414(1234) 2418(1293) +1 0 +.names 1939(1229) 696(1175) 1179(1294) +11 1 +.names 1941(1228) 702(1176) 1172(1295) +11 1 +.names 2406(1235) 2410(1296) +1 0 +.names 2398(1177) 2401(1227) 1156(1297) +11 0 +.names 2390(1178) 2393(1226) 1146(1298) +11 0 +.names 2722(1047) 2725(1247) 1826(1299) +11 0 +.names 640(1246) 637(1245) 2243(1300) +11 0 +.names 908(1248) 909(1267) 910(1301) +11 0 +.names 1126(1249) 1127(1271) 1128(1302) +11 0 +.names 899(1250) 900(1270) 901(1303) +11 0 +.names 1117(1251) 1118(1274) 1119(1304) +11 0 +.names 916(1252) 917(1268) 918(1305) +11 0 +.names 1134(1253) 1135(1272) 1136(1306) +11 0 +.names 645(1197) 646(1254) 647(1307) +11 0 +.names 634(1256) 631(1255) 2227(1308) +11 0 +.names 2350(687) 2353(1243) 1114(1309) +11 0 +.names 2262(689) 2265(1244) 683(1310) +11 0 +.names 2342(779) 2345(1242) 1098(1311) +11 0 +.names 2254(781) 2257(1241) 664(1312) +11 0 +.names 2422(783) 2425(1240) 1180(1313) +11 0 +.names 2334(784) 2337(1239) 962(1314) +11 0 +.names 925(1265) 926(1269) 927(1315) +11 0 +.names 1143(1266) 1144(1273) 1145(1316) +11 0 +.names 928(1292) 929(1279) 930(1317) +11 0 +.names 938(1291) 939(1280) 940(1318) +11 0 +.names 2315(1281) 2322(1290) 948(1319) +11 0 +.names 2315(1281) 2321(1320) +1 0 +.names 2323(1282) 2330(1287) 956(1321) +11 0 +.names 2323(1282) 2329(1322) +1 0 +.names 1146(1298) 1147(1283) 1148(1323) +11 0 +.names 1156(1297) 1157(1284) 1158(1324) +11 0 +.names 2403(1285) 2410(1296) 1166(1325) +11 0 +.names 2403(1285) 2409(1326) +1 0 +.names 2411(1286) 2418(1293) 1174(1327) +11 0 +.names 2411(1286) 2417(1328) +1 0 +.names 1826(1299) 1827(1238) 686(1329) +11 0 +.names 647(1307) 865(291) 143(1330) +11 1 +.names 2243(1300) 2249(1331) +1 0 +.names 901(1303) 915(1129) 970(1332) +11 1 +.names 910(1301) 927(1315) 918(1305) 901(1303) 968(1333) +1111 1 +.names 1119(1304) 1133(1131) 1187(1334) +11 1 +.names 1128(1302) 1145(1316) 1136(1306) 1119(1304) 1185(1335) +1111 1 +.names 910(1301) 901(1303) 922(1137) 971(1336) +111 1 +.names 1128(1302) 1119(1304) 1140(1139) 1188(1337) +111 1 +.names 2227(1308) 2233(1338) +1 0 +.names 1114(1309) 1115(1257) 1112(1339) +11 0 +.names 683(1310) 684(1258) 681(1340) +11 0 +.names 1098(1311) 1099(1259) 1100(1341) +11 0 +.names 664(1312) 665(1260) 666(1342) +11 0 +.names 1180(1313) 1181(1261) 1182(1343) +11 0 +.names 962(1314) 963(1262) 964(1344) +11 0 +.names 2227(1308) 2234(1263) 642(1345) +11 0 +.names 2243(1300) 2250(1264) 649(1346) +11 0 +.names 918(1305) 901(1303) 924(1151) 910(1301) 972(1347) +1111 1 +.names 1136(1306) 1119(1304) 1142(1153) 1128(1302) 1189(1348) +1111 1 +.names 930(1317) 946(1165) 978(1349) +11 1 +.names 1148(1323) 1164(1169) 1195(1350) +11 1 +.names 2326(1230) 2329(1322) 955(1351) +11 0 +.names 940(1318) 930(1317) 954(1289) 979(1352) +111 1 +.names 2318(1231) 2321(1320) 947(1353) +11 0 +.names 2414(1234) 2417(1328) 1173(1354) +11 0 +.names 1158(1324) 1148(1323) 1172(1295) 1196(1355) +111 1 +.names 2406(1235) 2409(1326) 1165(1356) +11 0 +.names 686(1329) 687(1357) +1 0 +.names 143(1330) 144(601) 145(1358) +00 0 +.names 968(1333) 969(1359) +1 0 +.names 1185(1335) 1186(1360) +1 0 +.names 907(1133) 970(1332) 971(1336) 972(1347) 973(1361) +0000 0 +.names 1125(1135) 1187(1334) 1188(1337) 1189(1348) 1190(1362) +0000 0 +.names 666(1342) 674(1200) 680(1363) +11 1 +.names 1100(1341) 1106(1201) 1111(1364) +11 1 +.names 2230(1206) 2233(1338) 641(1365) +11 0 +.names 2246(1207) 2249(1331) 648(1366) +11 0 +.names 681(1340) 666(1342) 679(1210) 682(1367) +111 1 +.names 1112(1339) 1100(1341) 1110(1211) 1113(1368) +111 1 +.names 947(1353) 948(1319) 949(1369) +11 0 +.names 955(1351) 956(1321) 957(1370) +11 0 +.names 1165(1356) 1166(1325) 1167(1371) +11 0 +.names 1173(1354) 1174(1327) 1175(1372) +11 0 +.names 973(1361) 976(1373) +1 0 +.names 1190(1362) 1193(1374) +1 0 +.names 671(1202) 680(1363) 682(1367) 685(1375) +000 0 +.names 1104(1203) 1111(1364) 1113(1368) 1116(1376) +000 0 +.names 957(1370) 949(1369) 930(1317) 967(1204) 940(1318) 981(1377) +11111 1 +.names 1175(1372) 1167(1371) 1148(1323) 1184(1205) 1158(1324) 1198(1378) +11111 1 +.names 641(1365) 642(1345) 643(1379) +11 0 +.names 648(1366) 649(1346) 650(1380) +11 0 +.names 687(1357) 487(403) 688(1381) +11 1 +.names 940(1318) 964(1344) 949(1369) 930(1317) 957(1370) 977(1382) +11111 1 +.names 1158(1324) 1182(1343) 1167(1371) 1148(1323) 1175(1372) 1194(1383) +11111 1 +.names 949(1369) 930(1317) 961(1288) 940(1318) 980(1384) +1111 1 +.names 1167(1371) 1148(1323) 1179(1294) 1158(1324) 1197(1385) +1111 1 +.names 650(1380) 868(198) 884(1386) +11 1 +.names 976(1373) 969(1359) 988(1387) +11 0 +.names 1193(1374) 1186(1360) 1205(1388) +11 0 +.names 977(1382) 685(1375) 983(1389) +11 1 +.names 1194(1383) 1116(1376) 1200(1390) +11 1 +.names 643(1379) 644(1391) +1 0 +.names 688(1381) 395(1392) +1 1 +.names 688(1381) 690(1393) +1 0 +.names 937(1163) 978(1349) 979(1352) 980(1384) 981(1377) 982(1394) +00000 0 +.names 1155(1167) 1195(1350) 1196(1355) 1197(1385) 1198(1378) 1199(1395) +00000 0 +.names 883(668) 884(1386) 895(1396) +00 0 +.names 982(1394) 983(1389) 984(1397) +00 0 +.names 1199(1395) 1200(1390) 1201(1398) +00 0 +.names 644(1391) 487(403) 1025(1399) +11 1 +.names 895(1396) 295(1400) +1 1 +.names 895(1396) 331(1401) +1 1 +.names 988(1387) 984(1397) 990(1402) +11 1 +.names 1205(1388) 1201(1398) 1207(1403) +11 1 +.names 984(1397) 987(1404) +1 0 +.names 1201(1398) 1204(1405) +1 0 +.names 1025(1399) 397(1406) +1 1 +.names 1025(1399) 1027(1407) +1 0 +.names 690(1393) 1027(1407) 1830(1108) 1085(1408) +111 1 +.names 973(1361) 987(1404) 989(1409) +11 1 +.names 1190(1362) 1204(1405) 1206(1410) +11 1 +.names 989(1409) 990(1402) 991(1411) +00 0 +.names 1206(1410) 1207(1403) 1208(1412) +00 0 +.names 1208(1412) 991(1411) 1221(1413) +11 0 +.names 1208(1412) 329(1414) +1 1 +.names 1221(1413) 991(1411) 1239(1415) +11 1 +.names 1208(1412) 1221(1413) 1238(1416) +11 1 +.names 1238(1416) 1239(1415) 1240(1417) +00 0 +.names 1240(1417) 1247(1418) +1 0 +.names 1240(1417) 1247(1418) 471(1419) +11 1 +.names 471(1419) 1247(1418) 473(1420) +00 0 +.names 1553(1110) 1087(1275) 473(1420) 1088(1421) +111 1 +.names 473(1420) 231(1422) +1 0 +.names 1085(1408) 1088(1421) 554(581) 1089(1423) +111 1 +.names 1089(1423) 225(1424) +1 0 +.names 1089(1423) 308(1425) +1 1 +.end diff --git a/abc70930/examples/ac.v b/abc70930/examples/ac.v new file mode 100644 index 00000000..cbeb0800 --- /dev/null +++ b/abc70930/examples/ac.v @@ -0,0 +1,18772 @@ +//// +//// This design was downloaded from http://www.opencores.org +//// +//// The design was synthesized with Cadence RTL Compiler in a +//// quick synthesis run. +//// +///////////////////////////////////////////////////////////////////// +//// //// +//// WISHBONE AC 97 Controller //// +//// //// +//// Author: Rudolf Usselmann //// +//// rudi@asics.ws //// +//// //// +//// Downloaded from: http://www.opencores.org/cores/ac97_ctrl/ //// +//// //// +///////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000-2002 Rudolf Usselmann //// +//// www.asics.ws //// +//// rudi@asics.ws //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer.//// +//// //// +//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// +//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// +//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// +//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// +//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// +//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// +//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// +//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// +//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// +//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// +//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// +//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// +//// POSSIBILITY OF SUCH DAMAGE. //// +//// //// +///////////////////////////////////////////////////////////////////// + +// Generated by Cadence RTL Compiler (RC) v05.10-b006_1 + +module ac97_ctrl(clk_i, rst_i, wb_data_i, wb_data_o, wb_addr_i, + wb_sel_i, wb_we_i, wb_cyc_i, wb_stb_i, wb_ack_o, wb_err_o, int_o, + dma_req_o, dma_ack_i, suspended_o, bit_clk_pad_i, sync_pad_o, + sdata_pad_o, sdata_pad_i, ac97_reset_pad_o_); + input clk_i, rst_i, wb_we_i, wb_cyc_i, wb_stb_i, bit_clk_pad_i, + sdata_pad_i; + input [31:0] wb_data_i, wb_addr_i; + input [3:0] wb_sel_i; + input [8:0] dma_ack_i; + output [31:0] wb_data_o; + output wb_ack_o, wb_err_o, int_o, suspended_o, sync_pad_o, + sdata_pad_o, ac97_reset_pad_o_; + output [8:0] dma_req_o; + wire clk_i, rst_i, wb_we_i, wb_cyc_i, wb_stb_i, bit_clk_pad_i, + sdata_pad_i; + wire [31:0] wb_data_i, wb_addr_i; + wire [3:0] wb_sel_i; + wire [8:0] dma_ack_i; + wire [31:0] wb_data_o; + wire wb_ack_o, wb_err_o, int_o, suspended_o, sync_pad_o, sdata_pad_o, + ac97_reset_pad_o_; + wire [8:0] dma_req_o; + wire ac97_rst_force, crac_din, crac_din_692, crac_din_693, + crac_din_694, crac_din_695, crac_din_696, crac_din_697; + wire crac_din_698, crac_din_699, crac_din_700, crac_din_701, + crac_din_702, crac_din_703, crac_din_704, crac_din_705; + wire crac_din_706, crac_out, crac_out_846, crac_out_847, + crac_out_848, crac_out_849, crac_out_850, crac_out_851; + wire crac_out_852, crac_out_853, crac_out_854, crac_out_855, + crac_out_856, crac_out_857, crac_out_858, crac_out_859; + wire crac_out_860, crac_out_861, crac_out_862, crac_out_863, + crac_out_864, crac_out_865, crac_out_866, crac_out_867; + wire crac_out_876, crac_wr, i3_dout, i3_dout_564, i3_dout_565, + i3_dout_566, i3_dout_567, i3_dout_568; + wire i3_dout_569, i3_dout_570, i3_dout_571, i3_dout_572, i3_dout_573, + i3_dout_574, i3_dout_575, i3_dout_576; + wire i3_dout_577, i3_dout_578, i3_dout_579, i3_dout_580, i3_dout_581, + i3_dout_582, i3_dout_583, i3_dout_584; + wire i3_dout_585, i3_dout_586, i3_dout_587, i3_dout_588, i3_dout_589, + i3_dout_590, i3_dout_591, i3_dout_592; + wire i3_dout_593, i3_dout_594, i3_empty, i3_full, i3_re, i3_status, + i3_status_1022, i4_dout; + wire i4_dout_595, i4_dout_596, i4_dout_597, i4_dout_598, i4_dout_599, + i4_dout_600, i4_dout_601, i4_dout_602; + wire i4_dout_603, i4_dout_604, i4_dout_605, i4_dout_606, i4_dout_607, + i4_dout_608, i4_dout_609, i4_dout_610; + wire i4_dout_611, i4_dout_612, i4_dout_613, i4_dout_614, i4_dout_615, + i4_dout_616, i4_dout_617, i4_dout_618; + wire i4_dout_619, i4_dout_620, i4_dout_621, i4_dout_622, i4_dout_623, + i4_dout_624, i4_dout_625, i4_empty; + wire i4_full, i4_re, i4_status, i4_status_1032, i6_dout, i6_dout_626, + i6_dout_627, i6_dout_628; + wire i6_dout_629, i6_dout_630, i6_dout_631, i6_dout_632, i6_dout_633, + i6_dout_634, i6_dout_635, i6_dout_636; + wire i6_dout_637, i6_dout_638, i6_dout_639, i6_dout_640, i6_dout_641, + i6_dout_642, i6_dout_643, i6_dout_644; + wire i6_dout_645, i6_dout_646, i6_dout_647, i6_dout_648, i6_dout_649, + i6_dout_650, i6_dout_651, i6_dout_652; + wire i6_dout_653, i6_dout_654, i6_dout_655, i6_dout_656, i6_empty, + i6_full, i6_re, i6_status; + wire i6_status_1042, ic0_cfg, ic0_cfg_1024, ic0_cfg_1025, + ic0_cfg_1026, ic0_cfg_1029, ic0_cfg_1030, ic0_int_set; + wire ic0_int_set_719, ic0_int_set_720, ic1_cfg, ic1_cfg_1034, + ic1_cfg_1035, ic1_cfg_1036, ic1_cfg_1039, ic1_cfg_1040; + wire ic1_int_set, ic1_int_set_721, ic1_int_set_722, ic2_cfg, + ic2_cfg_1044, ic2_cfg_1045, ic2_cfg_1046, ic2_cfg_1049; + wire ic2_cfg_1050, ic2_int_set, ic2_int_set_723, ic2_int_set_724, + in_slt3, in_slt4, in_slt6, in_slt_397; + wire in_slt_398, in_slt_399, in_slt_400, in_slt_401, in_slt_402, + in_slt_403, in_slt_404, in_slt_405; + wire in_slt_406, in_slt_407, in_slt_408, in_slt_409, in_slt_410, + in_slt_411, in_slt_412, in_slt_413; + wire in_slt_414, in_slt_415, in_slt_419, in_slt_420, in_slt_421, + in_slt_422, in_slt_423, in_slt_424; + wire in_slt_425, in_slt_426, in_slt_427, in_slt_428, in_slt_429, + in_slt_430, in_slt_431, in_slt_432; + wire in_slt_433, in_slt_434, in_slt_435, in_slt_436, in_slt_437, + in_slt_441, in_slt_442, in_slt_443; + wire in_slt_444, in_slt_445, in_slt_446, in_slt_447, in_slt_448, + in_slt_449, in_slt_450, in_slt_451; + wire in_slt_452, in_slt_453, in_slt_454, in_slt_455, in_slt_456, + in_slt_457, in_slt_458, in_slt_459; + wire in_slt_736, in_slt_738, in_slt_739, in_slt_742, in_slt_747, + in_slt_748, in_slt_749, in_slt_750; + wire in_slt_752, in_slt_753, in_slt_830, in_slt_831, in_slt_832, + in_slt_833, in_slt_834, in_slt_835; + wire in_slt_836, in_slt_837, in_slt_838, in_slt_839, in_slt_840, + in_slt_841, in_slt_842, in_slt_843; + wire in_slt_844, in_slt_845, in_valid, in_valid_8, in_valid_9, + in_valid_s1, \in_valid_s[0] , \in_valid_s[1] ; + wire \in_valid_s[2] , in_valid_s_1, in_valid_s_2, n_5, n_9, n_16, + n_19, n_21; + wire n_22, n_35, n_36, n_37, n_39, n_42, n_45, n_53; + wire n_56, n_57, n_58, n_63, n_71, n_76, n_77, n_79; + wire n_81, n_82, n_84, n_86, n_87, n_90, n_95, n_96; + wire n_98, n_101, n_102, n_103, n_105, n_109, n_112, n_113; + wire n_114, n_116, n_117, n_118, n_120, n_121, n_122, n_125; + wire n_127, n_129, n_130, n_134, n_138, n_141, n_143, n_145; + wire n_147, n_149, n_150, n_152, n_157, n_160, n_162, n_163; + wire n_166, n_167, n_170, n_174, n_175, n_177, n_178, n_179; + wire n_181, n_182, n_183, n_184, n_186, n_188, n_190, n_191; + wire n_192, n_195, n_196, n_197, n_198, n_200, n_201, n_203; + wire n_204, n_206, n_208, n_209, n_211, n_212, n_214, n_215; + wire n_217, n_220, n_221, n_223, n_227, n_228, n_229, n_230; + wire n_231, n_232, n_234, n_236, n_237, n_240, n_242, n_243; + wire n_244, n_248, n_249, n_251, n_254, n_256, n_257, n_259; + wire n_261, n_262, n_263, n_264, n_265, n_266, n_267, n_268; + wire n_270, n_271, n_273, n_275, n_277, n_278, n_279, n_280; + wire n_281, n_282, n_283, n_284, n_287, n_288, n_290, n_294; + wire n_295, n_297, n_298, n_299, n_300, n_302, n_303, n_304; + wire n_306, n_308, n_311, n_312, n_313, n_314, n_319, n_320; + wire n_321, n_322, n_324, n_328, n_329, n_330, n_332, n_333; + wire n_334, n_335, n_337, n_338, n_339, n_340, n_341, n_343; + wire n_345, n_346, n_347, n_348, n_349, n_351, n_352, n_356; + wire n_357, n_359, n_361, n_362, n_363, n_365, n_366, n_370; + wire n_372, n_373, n_375, n_376, n_379, n_380, n_383, n_384; + wire n_385, n_387, n_389, n_391, n_392, n_393, n_394, n_396; + wire n_397, n_398, n_399, n_401, n_403, n_406, n_410, n_411; + wire n_412, n_414, n_415, n_416, n_418, n_419, n_421, n_422; + wire n_431, n_433, n_434, n_438, n_440, n_441, n_442, n_444; + wire n_445, n_447, n_449, n_450, n_453, n_454, n_456, n_457; + wire n_458, n_459, n_461, n_462, n_463, n_465, n_469, n_471; + wire n_473, n_476, n_477, n_478, n_480, n_481, n_485, n_487; + wire n_488, n_490, n_492, n_494, n_495, n_496, n_498, n_501; + wire n_502, n_503, n_507, n_508, n_509, n_510, n_512, n_513; + wire n_514, n_515, n_518, n_520, n_521, n_522, n_523, n_524; + wire n_525, n_528, n_529, n_531, n_532, n_539, n_540, n_541; + wire n_543, n_544, n_549, n_550, n_551, n_552, n_553, n_554; + wire n_557, n_564, n_565, n_568, n_569, n_571, n_574, n_576; + wire n_577, n_580, n_581, n_587, n_590, n_593, n_594, n_597; + wire n_598, n_599, n_600, n_601, n_602, n_603, n_604, n_605; + wire n_606, n_608, n_609, n_610, n_611, n_612, n_614, n_615; + wire n_616, n_617, n_620, n_621, n_625, n_626, n_627, n_630; + wire n_631, n_632, n_634, n_635, n_637, n_638, n_639, n_641; + wire n_650, n_656, n_657, n_664, n_665, n_666, n_667, n_668; + wire n_669, n_670, n_671, n_672, n_673, n_674, n_675, n_676; + wire n_677, n_679, n_680, n_681, n_683, n_684, n_685, n_686; + wire n_687, n_688, n_689, n_690, n_691, n_692, n_693, n_694; + wire n_695, n_696, n_697, n_698, n_699, n_700, n_701, n_702; + wire n_703, n_704, n_705, n_706, n_707, n_708, n_709, n_710; + wire n_711, n_712, n_713, n_714, n_715, n_716, n_719, n_725; + wire n_726, n_728, n_729, n_730, n_731, n_732, n_733, n_734; + wire n_736, n_737, n_739, n_740, n_741, n_742, n_743, n_744; + wire n_745, n_746, n_748, n_749, n_750, n_751, n_752, n_753; + wire n_754, n_757, n_760, n_761, n_762, n_763, n_765, n_771; + wire n_781, n_782, n_784, n_785, n_786, n_792, n_793, n_794; + wire n_795, n_796, n_798, n_799, n_802, n_804, n_806, n_807; + wire n_808, n_811, n_813, n_814, n_818, n_819, n_821, n_822; + wire n_823, n_825, n_829, n_830, n_831, n_832, n_834, n_835; + wire n_836, n_837, n_838, n_839, n_840, n_841, n_843, n_844; + wire n_846, n_847, n_851, n_853, n_854, n_858, n_862, n_863; + wire n_864, n_865, n_866, n_867, n_868, n_869, n_870, n_872; + wire n_877, n_886, n_888, n_907, n_908, n_909, n_910, n_913; + wire n_914, n_916, n_920, n_921, n_923, n_924, n_925, n_928; + wire n_929, n_930, n_931, n_932, n_933, n_935, n_936, n_937; + wire n_938, n_940, n_941, n_942, n_945, n_968, n_969, n_970; + wire n_974, n_976, n_977, n_980, n_982, n_984, n_991, n_995; + wire n_996, n_997, n_1000, n_1001, n_1005, n_1006, n_1007, n_1008; + wire n_1009, n_1010, n_1012, n_1014, n_1016, n_1019, n_1021, n_1022; + wire n_1023, n_1025, n_1027, n_1028, n_1029, n_1030, n_1031, n_1033; + wire n_1034, n_1035, n_1036, n_1037, n_1038, n_1039, n_1040, n_1042; + wire n_1045, n_1047, n_1049, n_1051, n_1052, n_1054, n_1055, n_1059; + wire n_1060, n_1063, n_1064, n_1067, n_1068, n_1071, n_1072, n_1074; + wire n_1076, n_1080, n_1082, n_1083, n_1084, n_1085, n_1087, n_1090; + wire n_1096, n_1100, n_1101, n_1103, n_1104, n_1105, n_1106, n_1107; + wire n_1108, n_1111, n_1114, n_1116, n_1119, n_1120, n_1121, n_1122; + wire n_1124, n_1126, n_1127, n_1129, n_1130, n_1132, n_1133, n_1134; + wire n_1136, n_1138, n_1142, n_1143, n_1146, n_1147, n_1148, n_1149; + wire n_1153, n_1156, n_1157, n_1158, n_1159, n_1160, n_1162, n_1163; + wire n_1164, n_1167, n_1172, n_1174, n_1176, n_1178, n_1180, n_1184; + wire n_1185, n_1188, n_1189, n_1192, n_1193, n_1194, n_1196, n_1197; + wire n_1198, n_1199, n_1200, n_1202, n_1203, n_1204, n_1205, n_1206; + wire n_1207, n_1208, n_1209, n_1211, n_1212, n_1213, n_1214, n_1215; + wire n_1216, n_1220, n_1221, n_1222, n_1224, n_1225, n_1226, n_1227; + wire n_1229, n_1230, n_1231, n_1232, n_1233, n_1234, n_1235, n_1236; + wire n_1237, n_1238, n_1239, n_1240, n_1241, n_1242, n_1243, n_1244; + wire n_1245, n_1246, n_1247, n_1248, n_1249, n_1251, n_1252, n_1253; + wire n_1255, n_1256, n_1258, n_1259, n_1260, n_1262, n_1263, n_1265; + wire n_1267, n_1269, n_1271, n_1272, n_1273, n_1274, n_1275, n_1276; + wire n_1277, n_1278, n_1281, n_1282, n_1283, n_1284, n_1285, n_1289; + wire n_1290, n_1291, n_1292, n_1294, n_1295, n_1297, n_1299, n_1300; + wire n_1301, n_1302, n_1308, n_1309, n_1316, n_1317, n_1319, n_1320; + wire n_1322, n_1323, n_1324, n_1325, n_1326, n_1327, n_1328, n_1333; + wire n_1335, n_1336, n_1337, n_1338, n_1339, n_1340, n_1347, n_1348; + wire n_1354, n_1355, n_1356, n_1360, n_1362, n_1363, n_1364, n_1367; + wire n_1372, n_1373, n_1374, n_1375, n_1376, n_1377, n_1378, n_1379; + wire n_1381, n_1383, n_1384, n_1386, n_1388, n_1391, n_1395, n_1396; + wire n_1397, n_1404, n_1406, n_1409, n_1411, n_1412, n_1414, n_1415; + wire n_1416, n_1417, n_1418, n_1419, n_1420, n_1421, n_1422, n_1423; + wire n_1424, n_1425, n_1427, n_1429, n_1430, n_1432, n_1434, n_1435; + wire n_1438, n_1441, n_1443, n_1444, n_1446, n_1447, n_1448, n_1449; + wire n_1450, n_1453, n_1454, n_1457, n_1458, n_1460, n_1462, n_1464; + wire n_1466, n_1469, n_1470, n_1472, n_1473, n_1475, n_1476, n_1477; + wire n_1478, n_1479, n_1480, n_1481, n_1483, n_1484, n_1485, n_1486; + wire n_1487, n_1488, n_1489, n_1490, n_1491, n_1492, n_1493, n_1495; + wire n_1496, n_1498, n_1499, n_1500, n_1501, n_1502, n_1503, n_1504; + wire n_1506, n_1507, n_1508, n_1509, n_1511, n_1512, n_1513, n_1514; + wire n_1515, n_1516, n_1517, n_1518, n_1519, n_1520, n_1521, n_1522; + wire n_1523, n_1524, n_1525, n_1526, n_1527, n_1528, n_1529, n_1530; + wire n_1531, n_1532, n_1533, n_1534, n_1535, n_1536, n_1537, n_1538; + wire n_1541, n_1542, n_1543, n_1544, n_1545, n_1546, n_1547, n_1548; + wire n_1549, n_1552, n_1553, n_1555, n_1556, n_1557, n_1558, n_1559; + wire n_1560, n_1561, n_1562, n_1563, n_1564, n_1565, n_1566, n_1567; + wire n_1568, n_1569, n_1570, n_1571, n_1572, n_1573, n_1574, n_1575; + wire n_1576, n_1577, n_1578, n_1579, n_1580, n_1581, n_1582, n_1583; + wire n_1584, n_1585, n_1586, n_1587, n_1588, n_1590, n_1591, n_1592; + wire n_1593, n_1594, n_1595, n_1596, n_1597, n_1599, n_1600, n_1601; + wire n_1602, n_1603, n_1604, n_1605, n_1606, n_1607, n_1609, n_1610; + wire n_1611, n_1612, n_1613, n_1614, n_1615, n_1616, n_1617, n_1619; + wire n_1620, n_1621, n_1623, n_1624, n_1625, n_1627, n_1628, n_1629; + wire n_1631, n_1632, n_1633, n_1634, n_1635, n_1637, n_1638, n_1639; + wire n_1640, n_1642, n_1643, n_1644, n_1645, n_1646, n_1648, n_1650; + wire n_1651, n_1652, n_1653, n_1654, n_1655, n_1656, n_1657, n_1658; + wire n_1660, n_1661, n_1662, n_1663, n_1664, n_1665, n_1666, n_1667; + wire n_1668, n_1669, n_1671, n_1672, n_1673, n_1674, n_1675, n_1676; + wire n_1677, n_1678, n_1679, n_1680, n_1681, n_1683, n_1684, n_1685; + wire n_1686, n_1687, n_1689, n_1690, n_1691, n_1692, n_1693, n_1694; + wire n_1695, n_1696, n_1697, n_1698, n_1699, n_1700, n_1701, n_1702; + wire n_1703, n_1704, n_1705, n_1706, n_1707, n_1709, n_1710, n_1711; + wire n_1712, n_1714, n_1715, n_1716, n_1717, n_1718, n_1719, n_1720; + wire n_1722, n_1723, n_1724, n_1725, n_1726, n_1727, n_1728, n_1729; + wire n_1730, n_1731, n_1732, n_1733, n_1734, n_1735, n_1736, n_1737; + wire n_1738, n_1739, n_1741, n_1742, n_1743, n_1744, n_1745, n_1746; + wire n_1747, n_1748, n_1749, n_1750, n_1751, n_1752, n_1753, n_1754; + wire n_1755, n_1756, n_1757, n_1758, n_1759, n_1760, n_1761, n_1763; + wire n_1764, n_1765, n_1766, n_1767, n_1768, n_1770, n_1772, n_1773; + wire n_1774, n_1775, n_1776, n_1777, n_1778, n_1779, n_1782, n_1784; + wire n_1785, n_1786, n_1788, n_1790, n_1791, n_1792, n_1793, n_1794; + wire n_1795, n_1796, n_1798, n_1800, n_1804, n_1805, n_1806, n_1807; + wire n_1808, n_1809, n_1810, n_1811, n_1812, n_1813, n_1814, n_1815; + wire n_1816, n_1818, n_1819, n_1820, n_1821, n_1822, n_1823, n_1824; + wire n_1825, n_1826, n_1827, n_1829, n_1831, n_1832, n_1833, n_1834; + wire n_1835, n_1836, n_1837, n_1838, n_1839, n_1840, n_1845, n_1846; + wire n_1848, n_1851, n_1854, n_1855, n_1858, n_1859, n_1860, n_1861; + wire n_1862, n_1863, n_1864, n_1865, n_1867, n_1869, n_1870, n_1871; + wire n_1873, n_1875, n_1881, n_1883, n_1884, n_1885, n_1886, n_1887; + wire n_1889, n_1891, n_1892, n_1894, n_1899, n_1901, n_1907, n_1908; + wire n_1910, n_1915, n_1918, n_1920, n_1921, n_1923, n_1924, n_1925; + wire n_1926, n_1927, n_1928, n_1929, n_1930, n_1931, n_1932, n_1933; + wire n_1934, n_1935, n_1936, n_1937, n_1938, n_1939, n_1940, n_1941; + wire n_1942, n_1943, n_1944, n_1945, n_1946, n_1947, n_1948, n_1949; + wire n_1950, n_1951, n_1952, n_1953, n_1954, n_1955, n_1956, n_1957; + wire n_1958, n_1959, n_1960, n_1961, n_1962, n_1963, n_1964, n_1965; + wire n_1966, n_1967, n_1968, n_1969, n_1970, n_1971, n_1972, n_1973; + wire n_1974, n_1975, n_1976, n_1977, n_1979, n_1980, n_1981, n_1982; + wire n_1983, n_1984, n_1985, n_1986, n_1987, n_1988, n_1989, n_1990; + wire n_1991, n_1992, n_1993, n_1994, n_1995, n_1996, n_1997, n_1998; + wire n_1999, n_2000, n_2001, n_2002, n_2003, n_2004, n_2005, n_2006; + wire n_2007, n_2008, n_2009, n_2010, n_2011, n_2012, n_2013, n_2014; + wire n_2015, n_2016, n_2018, n_2019, n_2020, n_2021, n_2022, n_2023; + wire n_2024, n_2025, n_2026, n_2027, n_2028, n_2029, n_2030, n_2032; + wire n_2034, n_2035, n_2036, n_2037, n_2038, n_2039, n_2040, n_2041; + wire n_2042, n_2043, n_2044, n_2045, n_2046, n_2047, n_2048, n_2049; + wire n_2051, n_2052, n_2053, n_2054, n_2055, n_2056, n_2057, n_2058; + wire n_2059, n_2060, n_2061, n_2062, n_2063, n_2064, n_2065, n_2066; + wire n_2067, n_2068, n_2069, n_2070, n_2071, n_2072, n_2073, n_2074; + wire n_2075, n_2077, n_2079, n_2080, n_2081, n_2082, n_2083, n_2084; + wire n_2085, n_2086, n_2087, n_2089, n_2091, n_2092, n_2093, n_2094; + wire n_2095, n_2096, n_2097, n_2098, n_2099, n_2100, n_2102, n_2103; + wire n_2104, n_2105, n_2106, n_2107, n_2108, n_2109, n_2110, n_2111; + wire n_2113, n_2114, n_2115, n_2116, n_2117, n_2118, n_2119, n_2120; + wire n_2121, n_2122, n_2123, n_2124, n_2126, n_2127, n_2128, n_2129; + wire n_2130, n_2131, n_2132, n_2133, n_2134, n_2135, n_2136, n_2137; + wire n_2138, n_2140, n_2141, n_2142, n_2143, n_2144, n_2145, n_2146; + wire n_2147, n_2149, n_2151, n_2152, n_2153, n_2154, n_2155, n_2156; + wire n_2157, n_2159, n_2160, n_2161, n_2162, n_2164, n_2165, n_2167; + wire n_2168, n_2169, n_2170, n_2171, n_2172, n_2173, n_2174, n_2175; + wire n_2176, n_2177, n_2178, n_2180, n_2181, n_2182, n_2183, n_2184; + wire n_2185, n_2186, n_2188, n_2189, n_2190, n_2191, n_2192, n_2193; + wire n_2195, n_2196, n_2197, n_2198, n_2199, n_2200, n_2201, n_2202; + wire n_2203, n_2204, n_2205, n_2206, n_2207, n_2208, n_2209, n_2210; + wire n_2211, n_2212, n_2214, n_2215, n_2216, n_2217, n_2218, n_2219; + wire n_2221, n_2222, n_2223, n_2224, n_2225, n_2226, n_2227, n_2229; + wire n_2231, n_2232, n_2233, n_2234, n_2235, n_2236, n_2237, n_2238; + wire n_2239, n_2240, n_2241, n_2243, n_2244, n_2245, n_2246, n_2247; + wire n_2248, n_2249, n_2250, n_2251, n_2252, n_2253, n_2255, n_2257; + wire n_2258, n_2259, n_2260, n_2261, n_2263, n_2264, n_2268, n_2269; + wire n_2270, n_2271, n_2272, n_2273, n_2274, n_2276, n_2277, n_2278; + wire n_2279, n_2280, n_2281, n_2282, n_2284, n_2285, n_2286, n_2287; + wire n_2288, n_2289, n_2290, n_2291, n_2292, n_2294, n_2295, n_2296; + wire n_2297, n_2298, n_2299, n_2300, n_2301, n_2302, n_2303, n_2304; + wire n_2305, n_2307, n_2312, n_2314, n_2316, n_2317, n_2319, n_2320; + wire n_2321, n_2322, n_2325, n_2326, n_2327, n_2329, n_2330, n_2331; + wire n_2332, n_2333, n_2334, n_2335, n_2336, n_2337, n_2338, n_2341; + wire n_2343, n_2344, n_2345, n_2346, n_2348, n_2350, n_2351, n_2352; + wire n_2353, n_2354, n_2355, n_2357, n_2359, n_2360, n_2362, n_2363; + wire n_2364, n_2365, n_2366, n_2367, n_2368, n_2369, n_2370, n_2371; + wire n_2372, n_2373, n_2374, n_2375, n_2376, n_2377, n_2378, n_2379; + wire n_2380, n_2381, n_2382, n_2383, n_2384, n_2385, n_2386, n_2387; + wire n_2388, n_2389, n_2390, n_2391, n_2392, n_2393, n_2395, n_2396; + wire n_2397, n_2398, n_2399, n_2400, n_2401, n_2402, n_2403, n_2404; + wire n_2405, n_2406, n_2407, n_2408, n_2409, n_2410, n_2411, n_2412; + wire n_2413, n_2414, n_2416, n_2417, n_2418, n_2419, n_2420, n_2421; + wire n_2423, n_2424, n_2425, n_2426, n_2428, n_2429, n_2431, n_2432; + wire n_2433, n_2435, n_2437, n_2438, n_2439, n_2440, n_2441, n_2443; + wire n_2444, n_2445, n_2446, n_2447, n_2448, n_2450, n_2452, n_2453; + wire n_2455, n_2456, n_2457, n_2458, n_2459, n_2460, n_2461, n_2462; + wire n_2463, n_2464, n_2465, n_2466, n_2467, n_2468, n_2469, n_2470; + wire n_2471, n_2472, n_2473, n_2475, n_2476, n_2477, n_2478, n_2479; + wire n_2481, n_2482, n_2483, n_2484, n_2485, n_2486, n_2487, n_2488; + wire n_2489, n_2491, n_2493, n_2496, n_2498, n_2499, n_2500, n_2501; + wire n_2502, n_2503, n_2504, n_2505, n_2506, n_2507, n_2508, n_2509; + wire n_2510, n_2511, n_2513, n_2516, n_2517, n_2519, n_2520, n_2521; + wire n_2523, n_2525, n_2526, n_2527, n_2528, n_2529, n_2530, n_2531; + wire n_2532, n_2533, n_2534, n_2535, n_2536, n_2537, n_2538, n_2539; + wire n_2540, n_2542, n_2543, n_2544, n_2545, n_2547, n_2548, n_2549; + wire n_2550, n_2551, n_2552, n_2553, n_2554, n_2555, n_2556, n_2557; + wire n_2558, n_2559, n_2560, n_2561, n_2563, n_2565, n_2566, n_2567; + wire n_2568, n_2569, n_2570, n_2571, n_2572, n_2574, n_2575, n_2576; + wire n_2577, n_2578, n_2579, n_2580, n_2582, n_2583, n_2584, n_2585; + wire n_2586, n_2587, n_2588, n_2589, n_2592, n_2593, n_2594, n_2595; + wire n_2596, n_2597, n_2599, n_2600, n_2602, n_2603, n_2604, n_2606; + wire n_2607, n_2608, n_2609, n_2610, n_2611, n_2612, n_2613, n_2614; + wire n_2615, n_2616, n_2617, n_2618, n_2619, n_2621, n_2622, n_2624; + wire n_2625, n_2627, n_2628, n_2629, n_2630, n_2631, n_2632, n_2633; + wire n_2634, n_2635, n_2636, n_2638, n_2640, n_2644, n_2645, n_2646; + wire n_2647, n_2648, n_2649, n_2650, n_2651, n_2652, n_2653, n_2655; + wire n_2656, n_2657, n_2658, n_2659, n_2660, n_2661, n_2662, n_2663; + wire n_2664, n_2665, n_2666, n_2667, n_2668, n_2669, n_2670, n_2671; + wire n_2672, n_2673, n_2674, n_2675, n_2676, n_2677, n_2678, n_2679; + wire n_2680, n_2681, n_2682, n_2683, n_2684, n_2685, n_2686, n_2688; + wire n_2689, n_2690, n_2691, n_2692, n_2693, n_2694, n_2695, n_2696; + wire n_2697, n_2698, n_2699, n_2700, n_2701, n_2702, n_2704, n_2705; + wire n_2706, n_2707, n_2709, n_2711, n_2712, n_2713, n_2714, n_2715; + wire n_2716, n_2717, n_2718, n_2719, n_2720, n_2721, n_2722, n_2723; + wire n_2725, n_2726, n_2727, n_2728, n_2729, n_2730, n_2731, n_2732; + wire n_2734, n_2735, n_2736, n_2737, n_2738, n_2739, n_2740, n_2741; + wire n_2742, n_2743, n_2744, n_2746, n_2747, n_2748, n_2749, n_2750; + wire n_2751, n_2752, n_2753, n_2754, n_2755, n_2757, n_2758, n_2759; + wire n_2760, n_2761, n_2762, n_2763, n_2764, n_2765, n_2766, n_2767; + wire n_2769, n_2770, n_2771, n_2772, n_2773, n_2774, n_2775, n_2776; + wire n_2777, n_2778, n_2779, n_2780, n_2781, n_2782, n_2783, n_2784; + wire n_2785, n_2786, n_2787, n_2788, n_2789, n_2790, n_2791, n_2792; + wire n_2793, n_2794, n_2796, n_2797, n_2799, n_2800, n_2801, n_2802; + wire n_2803, n_2804, n_2805, n_2806, n_2807, n_2808, n_2809, n_2810; + wire n_2811, n_2812, n_2813, n_2814, n_2815, n_2816, n_2817, n_2818; + wire n_2819, n_2820, n_2821, n_2822, n_2823, n_2824, n_2826, n_2827; + wire n_2828, n_2829, n_2830, n_2831, n_2832, n_2833, n_2835, n_2836; + wire n_2837, n_2838, n_2839, n_2840, n_2841, n_2844, n_2846, n_2849; + wire n_2850, n_2851, n_2852, n_2854, n_2855, n_2856, n_2857, n_2858; + wire n_2859, n_2861, n_2863, n_2864, n_2865, n_2867, n_2868, n_2870; + wire n_2871, n_2872, n_2873, n_2874, n_2876, n_2877, n_2878, n_2879; + wire n_2880, n_2882, n_2883, n_2886, n_2888, n_2889, n_2890, n_2891; + wire n_2893, n_2894, n_2895, n_2896, n_2897, n_2898, n_2902, n_2903; + wire n_2905, n_2906, n_2907, n_2908, n_2909, n_2911, n_2912, n_2913; + wire n_2914, n_2915, n_2916, n_2917, n_2918, n_2922, n_2923, n_2924; + wire n_2925, n_2926, n_2927, n_2928, n_2929, n_2930, n_2932, n_2934; + wire n_2935, n_2937, n_2938, n_2939, n_2940, n_2941, n_2943, n_2945; + wire n_2946, n_2947, n_2950, n_2951, n_2952, n_2953, n_2954, n_2955; + wire n_2956, n_2957, n_2958, n_2959, n_2961, n_2962, n_2964, n_2965; + wire n_2966, n_2967, n_2968, n_2969, n_2970, n_2971, n_2972, n_2974; + wire n_2975, n_2976, n_2977, n_2981, n_2982, n_2983, n_2984, n_2985; + wire n_2986, n_2987, n_2989, n_2992, n_2993, n_2994, n_2995, n_2996; + wire n_2997, n_2998, n_2999, n_3000, n_3001, n_3003, n_3004, n_3006; + wire n_3007, n_3008, n_3010, n_3013, n_3014, n_3015, n_3016, n_3018; + wire n_3019, n_3020, n_3022, n_3023, n_3027, n_3029, n_3030, n_3031; + wire n_3032, n_3035, n_3036, n_3037, n_3038, n_3040, n_3041, n_3043; + wire n_3044, n_3045, n_3051, n_3052, n_3053, n_3054, n_3056, n_3057; + wire n_3058, n_3060, n_3061, n_3063, n_3065, n_3066, n_3067, n_3069; + wire n_3070, n_3071, n_3073, n_3074, n_3076, n_3078, n_3079, n_3080; + wire n_3081, n_3082, n_3084, n_3086, n_3087, n_3089, n_3090, n_3091; + wire n_3092, n_3093, n_3094, n_3098, n_3103, n_3104, n_3105, n_3106; + wire n_3107, n_3108, n_3109, n_3111, n_3112, n_3114, n_3116, n_3117; + wire n_3118, n_3119, n_3120, n_3121, n_3122, n_3123, n_3124, n_3125; + wire n_3126, n_3128, n_3129, n_3130, n_3131, n_3132, n_3133, n_3134; + wire n_3135, n_3136, n_3137, n_3138, n_3142, n_3143, n_3144, n_3150; + wire n_3151, n_3154, n_3158, n_3159, n_3160, n_3161, n_3162, n_3163; + wire n_3164, n_3166, n_3167, n_3169, n_3171, n_3172, n_3173, n_3175; + wire n_3176, n_3177, n_3180, n_3181, n_3183, n_3184, n_3185, n_3186; + wire n_3188, n_3191, n_3192, n_3193, n_3194, n_3195, n_3198, n_3199; + wire n_3202, n_3204, n_3205, n_3206, n_3207, n_3208, n_3209, n_3210; + wire n_3212, n_3213, n_3214, n_3215, n_3218, n_3220, n_3223, n_3224; + wire n_3225, n_3227, n_3228, n_3229, n_3231, n_3234, n_3235, n_3236; + wire n_3238, n_3239, n_3240, n_3242, n_3246, n_3248, n_3251, n_3252; + wire n_3253, n_3254, n_3255, n_3256, n_3257, n_3258, n_3259, n_3260; + wire n_3261, n_3264, n_3268, n_3270, n_3274, n_3275, n_3277, n_3278; + wire n_3279, n_3280, n_3282, n_3283, n_3285, n_3287, n_3288, n_3289; + wire n_3290, n_3291, n_3292, n_3293, n_3295, n_3296, n_3297, n_3299; + wire n_3302, n_3305, n_3307, n_3309, n_3311, n_3313, n_3315, n_3316; + wire n_3317, n_3318, n_3321, n_3324, n_3328, n_3329, n_3330, n_3331; + wire n_3332, n_3333, n_3334, n_3336, n_3338, n_3339, n_3341, n_3342; + wire n_3343, n_3344, n_3346, n_3347, n_3348, n_3350, n_3351, n_3353; + wire n_3354, n_3355, n_3357, n_3358, n_3360, n_3362, n_3363, n_3364; + wire n_3366, n_3367, n_3370, n_3373, n_3374, n_3375, n_3376, n_3378; + wire n_3381, n_3383, n_3388, n_3389, n_3391, n_3392, n_3393, n_3394; + wire n_3396, n_3398, n_3399, n_3400, n_3401, n_3404, n_3405, n_3406; + wire n_3407, n_3409, n_3410, n_3411, n_3412, n_3415, n_3416, n_3417; + wire n_3419, n_3420, n_3422, n_3423, n_3424, n_3425, n_3426, n_3428; + wire n_3429, n_3431, n_3432, n_3434, n_3436, n_3437, n_3441, n_3442; + wire n_3444, n_3446, n_3449, n_3452, n_3453, n_3454, n_3455, n_3460; + wire n_3463, n_3465, n_3466, n_3467, n_3468, n_3469, n_3470, n_3472; + wire n_3473, n_3474, n_3478, n_3480, n_3482, n_3483, n_3486, n_3487; + wire n_3489, n_3490, n_3492, n_3493, n_3494, n_3495, n_3497, n_3499; + wire n_3501, n_3502, n_3505, n_3506, n_3507, n_3509, n_3511, n_3512; + wire n_3514, n_3515, n_3516, n_3517, n_3519, n_3520, n_3521, n_3522; + wire n_3523, n_3524, n_3525, n_3526, n_3527, n_3528, n_3529, n_3530; + wire n_3531, n_3532, n_3533, n_3534, n_3535, n_3536, n_3537, n_3538; + wire n_3539, n_3540, n_3542, n_3543, n_3544, n_3545, n_3546, n_3547; + wire n_3548, n_3549, n_3550, n_3551, n_3552, n_3553, n_3554, n_3555; + wire n_3556, n_3557, n_3559, n_3560, n_3561, n_3563, n_3564, n_3565; + wire n_3566, n_3567, n_3568, n_3569, n_3570, n_3571, n_3572, n_3573; + wire n_3574, n_3575, n_3576, n_3577, n_3579, n_3580, n_3582, n_3583; + wire n_3584, n_3585, n_3586, n_3587, n_3588, n_3589, n_3590, n_3592; + wire n_3593, n_3595, n_3596, n_3598, n_3599, n_3600, n_3601, n_3602; + wire n_3603, n_3604, n_3606, n_3607, n_3608, n_3609, n_3610, n_3611; + wire n_3612, n_3613, n_3614, n_3615, n_3616, n_3617, n_3619, n_3620; + wire n_3621, n_3622, n_3623, n_3624, n_3625, n_3626, n_3627, n_3628; + wire n_3630, n_3631, n_3632, n_3633, n_3635, n_3636, n_3638, n_3639; + wire n_3641, n_3642, n_3644, n_3645, n_3647, n_3648, n_3649, n_3651; + wire n_3652, n_3654, n_3656, n_3658, n_3660, n_3663, n_3664, n_3666; + wire n_3667, n_3668, n_3670, n_3671, n_3674, n_3675, n_3676, n_3677; + wire n_3679, n_3681, n_3682, n_3683, n_3684, n_3686, n_3688, n_3690; + wire n_3692, n_3693, n_3694, n_3696, n_3697, n_3698, n_3699, n_3700; + wire n_3701, n_3704, n_3707, n_3709, n_3710, n_3712, n_3714, n_3715; + wire n_3717, n_3719, n_3720, n_3722, n_3724, n_3725, n_3727, n_3728; + wire n_3731, n_3732, n_3734, n_3735, n_3737, n_3739, n_3741, n_3744; + wire n_3746, n_3748, n_3750, n_3751, n_3752, n_3753, n_3754, n_3755; + wire n_3756, n_3757, n_3759, n_3760, n_3761, n_3762, n_3763, n_3764; + wire n_3765, n_3766, n_3768, n_3770, n_3771, n_3773, n_3776, n_3777; + wire n_3779, n_3780, n_3783, n_3784, n_3786, n_3788, n_3790, n_3791; + wire n_3792, n_3795, n_3796, n_3797, n_3799, n_3801, n_3802, n_3803; + wire n_3804, n_3806, n_3807, n_3808, n_3809, n_3811, n_3812, n_3813; + wire n_3814, n_3815, n_3817, n_3818, n_3820, n_3822, n_3823, n_3824; + wire n_3825, n_3826, n_3827, n_3828, n_3830, n_3831, n_3832, n_3833; + wire n_3834, n_3836, n_3837, n_3838, n_3840, n_3841, n_3842, n_3843; + wire n_3844, n_3845, n_3846, n_3847, n_3848, n_3849, n_3850, n_3851; + wire n_3852, n_3854, n_3855, n_3856, n_3857, n_3858, n_3860, n_3861; + wire n_3862, n_3864, n_3865, n_3866, n_3867, n_3869, n_3871, n_3872; + wire n_3874, n_3875, n_3877, n_3878, n_3879, n_3880, n_3881, n_3883; + wire n_3884, n_3885, n_3886, n_3887, n_3888, n_3889, n_3890, n_3892; + wire n_3893, n_3894, n_3895, n_3896, n_3898, n_3899, n_3900, n_3902; + wire n_3903, n_3904, n_3905, n_3907, n_3908, n_3909, n_3910, n_3911; + wire n_3913, n_3914, n_3915, n_3916, n_3917, n_3918, n_3919, n_3920; + wire n_3921, n_3922, n_3923, n_3925, n_3927, n_3928, n_3929, n_3930; + wire n_3932, n_3933, n_3934, n_3935, n_3937, n_3938, n_3939, n_3940; + wire n_3941, n_3942, n_3943, n_3944, n_3945, n_3946, n_3947, n_3948; + wire n_3949, n_3950, n_3952, n_3953, n_3955, n_3956, n_3957, n_3958; + wire n_3959, n_3960, n_3961, n_3963, n_3964, n_3965, n_3966, n_3967; + wire n_3968, n_3969, n_3970, n_3971, n_3973, n_3974, n_3975, n_3976; + wire n_3978, n_3979, n_3980, n_3981, n_3982, n_3983, n_3984, n_3985; + wire n_3986, n_3987, n_3989, n_3991, n_3992, n_3993, n_3994, n_3995; + wire n_3996, n_3997, n_3998, n_3999, n_4000, n_4001, n_4002, n_4003; + wire n_4004, n_4005, n_4006, n_4007, n_4008, n_4009, n_4010, n_4011; + wire n_4012, n_4013, n_4014, n_4015, n_4016, n_4017, n_4018, n_4019; + wire n_4020, n_4021, n_4022, n_4023, n_4024, n_4025, n_4026, n_4027; + wire n_4028, n_4029, n_4030, n_4031, n_4032, n_4033, n_4034, n_4035; + wire n_4036, n_4037, n_4038, n_4039, n_4040, n_4041, n_4042, n_4043; + wire n_4044, n_4045, n_4046, n_4047, n_4048, n_4049, n_4050, n_4051; + wire n_4052, n_4053, n_4054, n_4055, n_4056, n_4057, n_4058, n_4059; + wire n_4060, n_4061, n_4062, n_4063, n_4064, n_4065, n_4066, n_4067; + wire n_4068, n_4070, n_4072, n_4073, n_4074, n_4075, n_4076, n_4077; + wire n_4078, n_4079, n_4080, n_4081, n_4082, n_4084, n_4085, n_4086; + wire n_4087, n_4088, n_4089, n_4090, n_4091, n_4092, n_4093, n_4094; + wire n_4095, n_4096, n_4097, n_4098, n_4100, n_4101, n_4102, n_4103; + wire n_4104, n_4105, n_4106, n_4107, n_4108, n_4109, n_4111, n_4112; + wire n_4113, n_4114, n_4116, n_4117, n_4118, n_4120, n_4121, n_4123; + wire n_4124, n_4125, n_4126, n_4127, n_4128, n_4129, n_4130, n_4131; + wire n_4133, n_4134, n_4135, n_4136, n_4138, n_4140, n_4142, n_4143; + wire n_4144, n_4147, n_4148, n_4150, n_4153, n_4154, n_4155, n_4157; + wire n_4158, n_4159, n_4161, n_4163, n_4164, n_4165, n_4167, n_4171; + wire n_4173, n_4175, n_4177, n_4178, n_4182, n_4183, n_4190, n_4191; + wire n_4192, n_4193, n_4195, n_4196, n_4198, n_4199, n_4200, n_4202; + wire n_4203, n_4204, n_4205, n_4206, n_4207, n_4208, n_4209, n_4210; + wire n_4212, n_4214, n_4217, n_4218, n_4219, n_4220, n_4222, n_4223; + wire n_4224, n_4225, n_4226, n_4229, n_4230, n_4231, n_4232, n_4234; + wire n_4236, n_4237, n_4238, n_4239, n_4240, n_4243, n_4244, n_4246; + wire n_4247, n_4249, n_4250, n_4251, n_4252, n_4253, n_4256, n_4257; + wire n_4258, n_4259, n_4260, n_4261, n_4266, n_4267, n_4268, n_4269; + wire n_4270, n_4271, n_4272, n_4273, n_4274, n_4275, n_4276, n_4277; + wire n_4278, n_4279, n_4280, n_4281, n_4282, n_4283, n_4284, n_4285; + wire n_4286, n_4287, n_4288, n_4289, n_4290, n_4291, n_4292, n_4293; + wire n_4294, n_4295, n_4296, n_4297, n_4298, n_4299, n_4300, n_4301; + wire n_4302, n_4303, n_4304, n_4305, n_4306, n_4307, n_4308, n_4309; + wire n_4310, n_4311, n_4312, n_4313, n_4314, n_4315, n_4316, n_4317; + wire n_4318, n_4319, n_4320, n_4321, n_4322, n_4323, n_4324, n_4325; + wire n_4326, n_4327, n_4328, n_4329, n_4330, n_4331, n_4332, n_4333; + wire n_4334, n_4335, n_4336, n_4337, n_4338, n_4339, n_4340, n_4341; + wire n_4342, n_4343, n_4344, n_4345, n_4346, n_4347, n_4348, n_4349; + wire n_4350, n_4351, n_4352, n_4353, n_4354, n_4355, n_4356, n_4357; + wire n_4358, n_4359, n_4360, n_4361, n_4362, n_4363, n_4364, n_4365; + wire n_4366, n_4367, n_4368, n_4369, n_4370, n_4371, n_4372, n_4373; + wire n_4374, n_4375, n_4376, n_4377, n_4378, n_4379, n_4380, n_4381; + wire n_4382, n_4383, n_4384, n_4385, n_4386, n_4387, n_4388, n_4389; + wire n_4390, n_4391, n_4392, n_4393, n_4394, n_4395, n_4396, n_4397; + wire n_4398, n_4399, n_4400, n_4401, n_4402, n_4403, n_4404, n_4405; + wire n_4406, n_4407, n_4408, n_4409, n_4410, n_4411, n_4412, n_4413; + wire n_4414, n_4415, n_4416, n_4417, n_4418, n_4419, n_4420, n_4421; + wire n_4422, n_4423, n_4424, n_4425, n_4426, n_4427, n_4428, n_4429; + wire n_4430, n_4431, n_4432, n_4433, n_4434, n_4435, n_4436, n_4438; + wire n_4439, n_4440, n_4441, n_4442, n_4443, n_4444, n_4445, n_4446; + wire n_4447, n_4448, n_4449, n_4450, n_4451, n_4452, n_4453, n_4454; + wire n_4455, n_4456, n_4457, n_4458, n_4459, n_4460, n_4461, n_4462; + wire n_4463, n_4464, n_4465, n_4466, n_4467, n_4468, n_4469, n_4470; + wire n_4471, n_4472, n_4473, n_4474, n_4475, n_4476, n_4477, n_4478; + wire n_4479, n_4480, n_4481, n_4482, n_4483, n_4484, n_4485, n_4486; + wire n_4487, n_4488, n_4489, n_4490, n_4491, n_4492, n_4493, n_4494; + wire n_4495, n_4496, n_4497, n_4498, n_4499, n_4500, n_4501, n_4502; + wire n_4503, n_4504, n_4505, n_4506, n_4507, n_4508, n_4509, n_4510; + wire n_4511, n_4512, n_4513, n_4514, n_4515, n_4516, n_4517, n_4518; + wire n_4519, n_4520, n_4521, n_4522, n_4523, n_4524, n_4525, n_4526; + wire n_4527, n_4528, n_4529, n_4530, n_4531, n_4532, n_4533, n_4534; + wire n_4535, n_4536, n_4537, n_4538, n_4539, n_4540, n_4541, n_4542; + wire n_4543, n_4544, n_4545, n_4546, n_4547, n_4550, n_4551, n_4552; + wire n_4553, n_4555, n_4557, n_4558, n_4559, n_4560, n_4561, n_4563; + wire n_4565, n_4566, n_4567, n_4568, n_4569, n_4570, n_4571, n_4572; + wire n_4573, n_4574, n_4576, n_4580, n_4581, n_4584, n_4586, n_4587; + wire n_4589, n_4590, n_4591, n_4592, n_4593, n_4594, n_4595, n_4596; + wire n_4597, n_4598, n_4599, n_4600, n_4601, n_4603, n_4605, n_4606; + wire n_4607, n_4608, n_4609, n_4610, n_4611, n_4613, n_4614, n_4615; + wire n_4616, n_4617, n_4618, n_4619, n_4621, n_4623, n_4624, n_4625; + wire n_4626, n_4627, n_4628, n_4629, n_4630, n_4631, n_4632, n_4633; + wire n_4634, n_4635, n_4636, n_4637, n_4638, n_4639, n_4640, n_4641; + wire n_4642, n_4643, n_4644, n_4645, n_4646, n_4647, n_4648, n_4649; + wire n_4650, n_4651, n_4652, n_4653, n_4654, n_4655, n_4656, n_4658; + wire n_4659, n_4660, n_4661, n_4662, n_4663, n_4664, n_4665, n_4666; + wire n_4667, n_4668, n_4669, n_4670, n_4671, n_4672, n_4673, n_4675; + wire n_4676, n_4677, n_4679, n_4680, n_4681, n_4683, n_4685, n_4686; + wire n_4687, n_4688, n_4689, n_4690, n_4692, n_4693, n_4694, n_4695; + wire n_4697, n_4698, n_4699, n_4701, n_4702, n_4703, n_4704, n_4706; + wire n_4707, n_4708, n_4709, n_4710, n_4711, n_4712, n_4713, n_4714; + wire n_4715, n_4716, n_4718, n_4719, n_4720, n_4721, n_4722, n_4723; + wire n_4724, n_4725, n_4726, n_4727, n_4728, n_4729, n_4730, n_4731; + wire n_4733, n_4734, n_4735, n_4736, n_4737, n_4738, n_4741, n_4742; + wire n_4743, n_4744, n_4745, n_4746, n_4747, n_4748, n_4749, n_4750; + wire n_4751, n_4752, n_4753, n_4754, n_4755, n_4756, n_4757, n_4758; + wire n_4759, n_4760, n_4761, n_4762, n_4764, n_4765, n_4766, n_4767; + wire n_4768, n_4769, n_4770, n_4772, n_4773, n_4774, n_4775, n_4776; + wire n_4777, n_4778, n_4779, n_4780, n_4781, n_4782, n_4783, n_4784; + wire n_4785, n_4786, n_4788, n_4789, n_4790, n_4791, n_4792, n_4793; + wire n_4794, n_4795, n_4796, n_4797, n_4799, n_4800, n_4801, n_4802; + wire n_4803, n_4804, n_4805, n_4806, n_4807, n_4808, n_4809, n_4810; + wire n_4811, n_4812, n_4813, n_4814, n_4815, n_4816, n_4817, n_4818; + wire n_4819, n_4820, n_4821, n_4822, n_4823, n_4824, n_4825, n_4826; + wire n_4827, n_4828, n_4829, n_4830, n_4831, n_4832, n_4833, n_4834; + wire n_4835, n_4836, n_4837, n_4838, n_4839, n_4840, n_4841, n_4842; + wire n_4843, n_4844, n_4845, n_4846, n_4848, n_4850, n_4851, n_4852; + wire n_4853, n_4854, n_4855, n_4856, n_4857, n_4858, n_4859, n_4860; + wire n_4861, n_4862, n_4863, n_4864, n_4865, n_4866, n_4867, n_4868; + wire n_4869, n_4870, n_4871, n_4872, n_4873, n_4874, n_4875, n_4876; + wire n_4877, n_4878, n_4879, n_4880, n_4881, n_4882, n_4883, n_4884; + wire n_4885, n_4886, n_4887, n_4888, n_4889, n_4890, n_4891, n_4892; + wire n_4893, n_4894, n_4895, n_4896, n_4897, n_4898, n_4899, n_4900; + wire n_4901, n_4902, n_4903, n_4904, n_4905, n_4906, n_4907, n_4908; + wire n_4909, n_4910, n_4911, n_4912, n_4913, n_4914, n_4915, n_4916; + wire n_4917, n_4918, n_4919, n_4920, n_4921, n_4922, n_4923, n_4924; + wire n_4925, n_4926, n_4927, n_4928, n_4929, n_4930, n_4931, n_4932; + wire n_4933, n_4934, n_4935, n_4936, n_4937, n_4938, n_4939, n_4940; + wire n_4941, n_4942, n_4943, n_4944, n_4945, n_4946, n_4947, n_4948; + wire n_4949, n_4950, n_4951, n_4952, n_4953, n_4954, n_4955, n_4956; + wire n_4957, n_4958, n_4959, n_4960, n_4961, n_4962, n_4963, n_4964; + wire n_4965, n_4966, n_4967, n_4968, n_4969, n_4970, n_4971, n_4972; + wire n_4973, n_4974, n_4975, n_4976, n_4977, n_4978, n_4979, n_4980; + wire n_4981, n_4982, n_4983, n_4984, n_4985, n_4986, n_4987, n_4988; + wire n_4989, n_4990, n_4991, n_4992, n_4993, n_4994, n_4995, n_4996; + wire n_4997, n_4998, n_4999, n_5000, n_5001, n_5002, n_5003, n_5004; + wire n_5005, n_5006, n_5007, n_5008, n_5009, n_5010, n_5011, n_5012; + wire n_5013, n_5014, n_5015, n_5016, n_5017, n_5018, n_5019, n_5020; + wire n_5021, n_5022, n_5023, n_5024, n_5025, n_5026, n_5027, n_5028; + wire n_5029, n_5030, n_5031, n_5032, n_5033, n_5034, n_5035, n_5036; + wire n_5037, n_5038, n_5039, n_5040, n_5041, n_5042, n_5043, n_5044; + wire n_5045, n_5046, n_5047, n_5048, n_5049, n_5050, n_5051, n_5052; + wire n_5053, n_5054, n_5055, n_5056, n_5057, n_5058, n_5059, n_5060; + wire n_5061, n_5062, n_5063, n_5064, n_5065, n_5066, n_5067, n_5068; + wire n_5069, n_5070, n_5071, n_5072, n_5073, n_5074, n_5075, n_5076; + wire n_5077, n_5078, n_5079, n_5080, n_5081, n_5082, n_5083, n_5084; + wire n_5085, n_5086, n_5087, n_5088, n_5089, n_5090, n_5091, n_5092; + wire n_5093, n_5094, n_5095, n_5096, n_5097, n_5098, n_5099, n_5100; + wire n_5101, n_5102, n_5103, n_5104, n_5105, n_5106, n_5107, n_5108; + wire n_5109, n_5110, n_5111, n_5112, n_5113, n_5114, n_5115, n_5116; + wire n_5117, n_5118, n_5119, n_5120, n_5121, n_5122, n_5123, n_5124; + wire n_5125, n_5126, n_5127, n_5128, n_5129, n_5130, n_5131, n_5132; + wire n_5133, n_5134, n_5135, n_5136, n_5137, n_5138, n_5139, n_5140; + wire n_5141, n_5142, n_5143, n_5144, n_5145, n_5146, n_5147, n_5148; + wire n_5149, n_5150, n_5151, n_5152, n_5153, n_5154, n_5155, n_5156; + wire n_5157, n_5158, n_5159, n_5160, n_5161, n_5162, n_5163, n_5164; + wire n_5165, n_5166, n_5167, n_5168, n_5169, n_5170, n_5171, n_5172; + wire n_5173, n_5174, n_5175, n_5176, n_5177, n_5178, n_5179, n_5180; + wire n_5181, n_5182, n_5183, n_5184, n_5185, n_5186, n_5187, n_5188; + wire n_5189, n_5190, n_5191, n_5193, n_5194, n_5195, n_5196, n_5197; + wire n_5198, n_5199, n_5200, n_5202, n_5203, n_5205, n_5210, n_5211; + wire n_5212, n_5213, n_5214, n_5215, n_5218, n_5219, n_5220, n_5222; + wire n_5224, n_5225, n_5226, n_5227, n_5228, n_5229, n_5230, n_5231; + wire n_5232, n_5233, n_5234, n_5235, n_5236, n_5237, n_5238, n_5239; + wire n_5240, n_5241, n_5242, n_5243, n_5244, n_5245, n_5246, n_5248; + wire n_5249, n_5250, n_5251, n_5252, n_5253, n_5254, n_5255, n_5256; + wire n_5258, n_5260, n_5261, n_5263, n_5265, n_5266, n_5268, n_5270; + wire n_5272, n_5273, n_5274, n_5275, n_5276, n_5277, n_5278, n_5279; + wire n_5280, n_5281, n_5282, n_5283, n_5284, n_5285, n_5287, n_5288; + wire n_5289, n_5290, n_5291, n_5292, n_5293, n_5294, n_5295, n_5296; + wire n_5297, n_5298, n_5299, n_5300, n_5301, n_5302, n_5303, n_5304; + wire n_5305, n_5307, n_5308, n_5309, n_5310, n_5311, n_5312, n_5313; + wire n_5314, n_5315, n_5316, n_5317, n_5318, n_5319, n_5320, n_5321; + wire n_5322, n_5323, n_5325, n_5326, n_5327, n_5329, n_5330, n_5331; + wire n_5332, n_5333, n_5334, n_5335, n_5336, n_5337, n_5338, n_5339; + wire n_5340, n_5341, n_5342, n_5343, n_5344, n_5345, n_5346, n_5347; + wire n_5348, n_5349, n_5350, n_5351, n_5352, n_5353, n_5355, n_5356; + wire n_5357, n_5358, n_5359, n_5360, n_5361, n_5362, n_5363, n_5364; + wire n_5365, n_5366, n_5367, n_5368, n_5369, n_5370, n_5371, n_5372; + wire n_5373, n_5374, n_5375, n_5377, n_5378, n_5379, n_5380, n_5381; + wire n_5382, n_5383, n_5384, n_5385, n_5386, n_5387, n_5388, n_5389; + wire n_5390, n_5391, n_5392, n_5393, n_5394, n_5396, n_5398, n_5400; + wire n_5403, n_5404, n_5405, n_5406, n_5407, n_5408, n_5409, n_5410; + wire n_5411, n_5412, n_5413, n_5414, n_5415, n_5416, n_5418, n_5419; + wire n_5420, n_5421, n_5422, n_5423, n_5424, n_5425, n_5426, n_5428; + wire n_5430, n_5431, n_5432, n_5434, n_5436, n_5438, n_5439, n_5440; + wire n_5441, n_5442, n_5443, n_5444, n_5445, n_5447, n_5448, n_5449; + wire n_5450, n_5451, n_5452, n_5453, n_5454, n_5455, n_5456, n_5457; + wire n_5458, n_5459, n_5460, n_5461, n_5463, n_5466, n_5467, n_5468; + wire n_5469, n_5470, n_5471, n_5472, n_5473, n_5474, n_5475, n_5477; + wire n_5479, n_5480, n_5481, n_5482, n_5483, n_5484, n_5486, n_5487; + wire n_5488, n_5489, n_5490, n_5491, n_5492, n_5493, n_5494, n_5495; + wire n_5496, n_5497, n_5498, n_5499, n_5500, n_5501, n_5502, n_5503; + wire n_5504, n_5505, n_5506, n_5507, n_5508, n_5509, n_5510, n_5511; + wire n_5512, n_5513, n_5514, n_5515, n_5516, n_5517, n_5518, n_5519; + wire n_5520, n_5521, n_5522, n_5523, n_5524, n_5525, n_5526, n_5527; + wire n_5528, n_5529, n_5530, n_5531, n_5532, n_5533, n_5534, n_5535; + wire n_5536, n_5537, n_5538, n_5539, n_5541, n_5542, n_5544, n_5545; + wire n_5546, n_5547, n_5548, n_5549, n_5550, n_5551, n_5552, n_5553; + wire n_5554, n_5555, n_5556, n_5557, n_5558, n_5559, n_5561, n_5562; + wire n_5563, n_5564, n_5565, n_5566, n_5567, n_5569, n_5570, n_5571; + wire n_5572, n_5575, n_5576, n_5577, n_5578, n_5580, n_5581, n_5582; + wire n_5583, n_5584, n_5585, n_5586, n_5587, n_5588, n_5589, n_5590; + wire n_5591, n_5592, n_5593, n_5594, n_5595, n_5596, n_5597, n_5611; + wire n_5612, n_5613, n_5614, n_5615, n_5616, n_5617, n_5618, n_5619; + wire n_5620, n_5621, n_5622, n_5623, n_5624, n_5625, n_5626, n_5627; + wire n_5628, n_5629, n_5630, n_5631, n_5632, n_5633, n_5634, n_5635; + wire n_5636, n_5637, n_5638, n_5639, n_5641, n_5643, n_5644, n_5645; + wire n_5646, n_5647, n_5648, n_5649, n_5650, n_5651, n_5653, n_5655; + wire n_5656, n_5657, n_5658, n_5659, n_5660, n_5662, n_5664, n_5665; + wire n_5666, n_5667, n_5668, n_5669, n_5670, n_5671, n_5672, n_5673; + wire n_5675, n_5676, n_5677, n_5678, n_5679, n_5680, n_5682, n_5683; + wire n_5684, n_5685, n_5686, n_5687, n_5688, n_5690, n_5691, n_5692; + wire n_5693, n_5694, n_5696, n_5697, n_5698, n_5699, n_5700, n_5701; + wire n_5702, n_5703, n_5704, n_5705, n_5707, n_5708, n_5709, n_5710; + wire n_5711, n_5713, n_5714, n_5715, n_5716, n_5717, n_5719, n_5720; + wire n_5721, n_5722, n_5723, n_5724, n_5725, n_5726, n_5727, n_5728; + wire n_5729, n_5730, n_5731, n_5732, n_5733, n_5734, n_5735, n_5736; + wire n_5737, n_5738, n_5740, n_5741, n_5742, n_5743, n_5744, n_5745; + wire n_5747, n_5748, n_5749, n_5751, n_5753, n_5756, n_5757, n_5758; + wire n_5759, n_5760, n_5761, n_5762, n_5763, n_5764, n_5765, n_5767; + wire n_5768, n_5769, n_5770, n_5771, n_5772, n_5773, n_5774, n_5775; + wire n_5776, n_5777, n_5779, n_5780, n_5781, n_5782, n_5783, n_5784; + wire n_5785, n_5786, n_5787, n_5788, n_5789, n_5790, n_5791, n_5793; + wire n_5794, n_5795, n_5796, n_5797, n_5798, n_5799, n_5800, n_5801; + wire n_5803, n_5804, n_5805, n_5806, n_5807, n_5808, n_5809, n_5810; + wire n_5811, n_5812, n_5813, n_5814, n_5815, n_5816, n_5817, n_5818; + wire n_5819, n_5820, n_5821, n_5822, n_5823, n_5824, n_5825, n_5826; + wire n_5827, n_5828, n_5829, n_5830, n_5831, n_5832, n_5833, n_5834; + wire n_5835, n_5836, n_5837, n_5838, n_5839, n_5840, n_5841, n_5842; + wire n_5844, n_5845, n_5846, n_5847, n_5848, n_5850, n_5851, n_5852; + wire n_5853, n_5854, n_5855, n_5856, n_5857, n_5858, n_5859, n_5860; + wire n_5861, n_5862, n_5863, n_5864, n_5865, n_5866, n_5867, n_5868; + wire n_5869, n_5870, n_5871, n_5873, n_5874, n_5875, n_5876, n_5877; + wire n_5878, n_5879, n_5880, n_5881, n_5882, n_5883, n_5884, n_5885; + wire n_5886, n_5887, n_5888, n_5889, n_5890, n_5892, n_5893, n_5894; + wire n_5895, n_5896, n_5897, n_5898, n_5899, n_5901, n_5902, n_5903; + wire n_5904, n_5905, n_5906, n_5907, n_5908, n_5909, n_5910, n_5911; + wire n_5913, n_5914, n_5916, n_5917, n_5918, n_5919, n_5920, n_5921; + wire n_5922, n_5923, n_5924, n_5925, n_5926, n_5929, n_5931, n_5932; + wire n_5933, n_5934, n_5935, n_5936, n_5937, n_5938, n_5939, n_5941; + wire n_5942, n_5944, n_5945, n_5946, n_5947, n_5948, n_5949, n_5950; + wire n_5951, n_5952, n_5953, n_5954, n_5955, n_5956, n_5957, n_5958; + wire n_5959, n_5960, n_5962, n_5963, n_5964, n_5965, n_5966, n_5967; + wire n_5969, n_5970, n_5971, n_5973, n_5974, n_5975, n_5976, n_5978; + wire n_5979, n_5981, n_5982, n_5983, n_5984, n_5985, n_5987, n_5988; + wire n_5989, n_5990, n_5991, n_5993, n_5994, n_5995, n_5997, n_5998; + wire n_5999, n_6000, n_6001, n_6002, n_6003, n_6004, n_6005, n_6006; + wire n_6007, n_6008, n_6009, n_6010, n_6011, n_6012, n_6013, n_6014; + wire n_6015, n_6017, n_6018, n_6019, n_6021, n_6022, n_6023, n_6024; + wire n_6025, n_6026, n_6027, n_6028, n_6029, n_6030, n_6031, n_6033; + wire n_6034, n_6035, n_6036, n_6037, n_6038, n_6040, n_6041, n_6042; + wire n_6043, n_6044, n_6045, n_6046, n_6047, n_6048, n_6049, n_6050; + wire n_6051, n_6052, n_6053, n_6054, n_6055, n_6056, n_6057, n_6058; + wire n_6059, n_6060, n_6061, n_6062, n_6063, n_6064, n_6065, n_6066; + wire n_6067, n_6068, n_6069, n_6070, n_6072, n_6073, n_6074, n_6075; + wire n_6076, n_6077, n_6078, n_6079, n_6080, n_6081, n_6082, n_6084; + wire n_6085, n_6087, n_6088, n_6089, n_6090, n_6091, n_6092, n_6093; + wire n_6094, n_6095, n_6096, n_6097, n_6099, n_6103, n_6104, n_6105; + wire n_6106, n_6108, n_6109, n_6111, n_6112, n_6113, n_6114, n_6116; + wire n_6117, n_6118, n_6119, n_6121, n_6122, n_6123, n_6124, n_6125; + wire n_6126, n_6127, n_6129, n_6130, n_6131, n_6132, n_6133, n_6134; + wire n_6135, n_6136, n_6137, n_6138, n_6139, n_6140, n_6141, n_6142; + wire n_6143, n_6144, n_6145, n_6146, n_6147, n_6150, n_6151, n_6152; + wire n_6153, n_6154, n_6155, n_6156, n_6157, n_6158, n_6159, n_6160; + wire n_6161, n_6162, n_6163, n_6164, n_6165, n_6166, n_6167, n_6168; + wire n_6169, n_6172, n_6173, n_6174, n_6176, n_6177, n_6179, n_6180; + wire n_6181, n_6182, n_6183, n_6184, n_6185, n_6186, n_6187, n_6188; + wire n_6191, n_6193, n_6194, n_6195, n_6197, n_6199, n_6200, n_6201; + wire n_6202, n_6203, n_6204, n_6205, n_6206, n_6207, n_6208, n_6209; + wire n_6210, n_6211, n_6212, n_6215, n_6216, n_6217, n_6218, n_6220; + wire n_6221, n_6223, n_6224, n_6225, n_6226, n_6227, n_6228, n_6229; + wire n_6232, n_6233, n_6234, n_6235, n_6236, n_6237, n_6238, n_6239; + wire n_6240, n_6241, n_6243, n_6244, n_6245, n_6246, n_6248, n_6249; + wire n_6250, n_6251, n_6252, n_6253, n_6254, n_6255, n_6259, n_6260; + wire n_6261, n_6263, n_6264, n_6265, n_6266, n_6267, n_6268, n_6271; + wire n_6275, n_6277, n_6278, n_6279, n_6280, n_6282, n_6283, n_6286; + wire n_6287, n_6288, n_6289, n_6290, n_6292, n_6293, n_6295, n_6296; + wire n_6297, n_6298, n_6300, n_6304, n_6305, n_6307, n_6308, n_6309; + wire n_6312, n_6313, n_6314, n_6315, n_6316, n_6317, n_6318, n_6319; + wire n_6320, n_6321, n_6322, n_6323, n_6324, n_6325, n_6326, n_6328; + wire n_6330, n_6331, n_6332, n_6333, n_6334, n_6335, n_6336, n_6337; + wire n_6338, n_6339, n_6340, n_6341, n_6342, n_6343, n_6344, n_6345; + wire n_6347, n_6348, n_6349, n_6350, n_6351, n_6352, n_6353, n_6354; + wire n_6355, n_6356, n_6357, n_6358, n_6359, n_6360, n_6361, n_6363; + wire n_6364, n_6366, n_6367, n_6368, n_6369, n_6370, n_6371, n_6372; + wire n_6373, n_6375, n_6376, n_6377, n_6378, n_6380, n_6381, n_6382; + wire n_6383, n_6384, n_6385, n_6386, n_6387, n_6388, n_6389, n_6390; + wire n_6391, n_6392, n_6393, n_6394, n_6395, n_6396, n_6397, n_6398; + wire n_6399, n_6400, n_6401, n_6402, n_6403, n_6404, n_6405, n_6406; + wire n_6407, n_6408, n_6409, n_6411, n_6412, n_6413, n_6414, n_6415; + wire n_6416, n_6417, n_6418, n_6419, n_6420, n_6421, n_6422, n_6424; + wire n_6425, n_6426, n_6427, n_6428, n_6429, n_6431, n_6432, n_6434; + wire n_6435, n_6437, n_6438, n_6439, n_6440, n_6441, n_6442, n_6443; + wire n_6444, n_6445, n_6446, n_6448, n_6449, n_6450, n_6451, n_6452; + wire n_6453, n_6454, n_6455, n_6457, n_6458, n_6459, n_6460, n_6461; + wire n_6463, n_6464, n_6465, n_6466, n_6467, n_6468, n_6469, n_6471; + wire n_6472, n_6473, n_6474, n_6475, n_6476, n_6477, n_6478, n_6479; + wire n_6480, n_6481, n_6483, n_6484, n_6485, n_6486, n_6487, n_6488; + wire n_6490, n_6491, n_6492, n_6493, n_6495, n_6496, n_6497, n_6498; + wire n_6499, n_6500, n_6501, n_6502, n_6503, n_6504, n_6505, n_6506; + wire n_6507, n_6508, n_6510, n_6511, n_6512, n_6514, n_6515, n_6516; + wire n_6517, n_6518, n_6519, n_6520, n_6521, n_6522, n_6523, n_6524; + wire n_6525, n_6526, n_6527, n_6528, n_6529, n_6530, n_6531, n_6533; + wire n_6534, n_6535, n_6536, n_6537, n_6538, n_6539, n_6540, n_6541; + wire n_6542, n_6543, n_6544, n_6545, n_6546, n_6547, n_6548, n_6549; + wire n_6551, n_6552, n_6554, n_6555, n_6556, n_6557, n_6559, n_6560; + wire n_6561, n_6562, n_6563, n_6564, n_6565, n_6566, n_6567, n_6569; + wire n_6570, n_6571, n_6572, n_6573, n_6574, n_6575, n_6576, n_6577; + wire n_6578, n_6579, n_6580, n_6581, n_6582, n_6583, n_6585, n_6586; + wire n_6587, n_6588, n_6589, n_6590, n_6591, n_6592, n_6593, n_6594; + wire n_6595, n_6596, n_6597, n_6598, n_6599, n_6600, n_6601, n_6602; + wire n_6603, n_6604, n_6605, n_6607, n_6608, n_6610, n_6611, n_6612; + wire n_6613, n_6614, n_6615, n_6617, n_6618, n_6619, n_6620, n_6621; + wire n_6623, n_6624, n_6625, n_6626, n_6628, n_6629, n_6630, n_6631; + wire n_6633, n_6634, n_6635, n_6636, n_6637, n_6638, n_6639, n_6641; + wire n_6642, n_6644, n_6645, n_6646, n_6647, n_6648, n_6649, n_6650; + wire n_6651, n_6652, n_6653, n_6654, n_6655, n_6656, n_6657, n_6658; + wire n_6659, n_6660, n_6661, n_6662, n_6663, n_6664, n_6665, n_6666; + wire n_6667, n_6668, n_6669, n_6670, n_6671, n_6672, n_6673, n_6674; + wire n_6675, n_6676, n_6677, n_6678, n_6680, n_6681, n_6683, n_6684; + wire n_6685, n_6686, n_6687, n_6688, n_6690, n_6691, n_6692, n_6693; + wire n_6694, n_6696, n_6697, n_6699, n_6700, n_6702, n_6703, n_6705; + wire n_6706, n_6707, n_6708, n_6709, n_6710, n_6711, n_6712, n_6713; + wire n_6714, n_6715, n_6716, n_6718, n_6720, n_6721, n_6722, n_6723; + wire n_6724, n_6725, n_6726, n_6727, n_6728, n_6729, n_6730, n_6731; + wire n_6732, n_6733, n_6734, n_6737, n_6738, n_6739, n_6740, n_6741; + wire n_6742, n_6743, n_6744, n_6745, n_6746, n_6747, n_6749, n_6750; + wire n_6751, n_6752, n_6753, n_6754, n_6755, n_6756, n_6757, n_6758; + wire n_6759, n_6761, n_6763, n_6765, n_6766, n_6769, n_6771, n_6772; + wire n_6773, n_6774, n_6777, n_6778, n_6779, n_6780, n_6781, n_6782; + wire n_6783, n_6784, n_6785, n_6786, n_6787, n_6789, n_6790, n_6791; + wire n_6793, n_6794, n_6797, n_6800, n_6801, n_6803, n_6804, n_6805; + wire n_6806, n_6807, n_6808, n_6809, n_6810, n_6812, n_6814, n_6815; + wire n_6816, n_6817, n_6818, n_6819, n_6820, n_6821, n_6822, n_6823; + wire n_6824, n_6825, n_6826, n_6833, n_6834, n_6836, n_6837, n_6838; + wire n_6839, n_6840, n_6841, n_6842, n_6843, n_6845, n_6846, n_6847; + wire n_6848, n_6849, n_6850, n_6852, n_6853, n_6854, n_6855, n_6856; + wire n_6857, n_6858, n_6859, n_6860, n_6862, n_6863, n_6864, n_6865; + wire n_6866, n_6867, n_6868, n_6869, n_6871, n_6873, n_6874, n_6876; + wire n_6877, n_6879, n_6880, n_6881, n_6882, n_6883, n_6884, n_6885; + wire n_6886, n_6887, n_6888, n_6889, n_6890, n_6891, n_6892, n_6893; + wire n_6894, n_6895, n_6896, n_6897, n_6898, n_6899, n_6900, n_6901; + wire n_6902, n_6903, n_6905, n_6906, n_6907, n_6908, n_6909, n_6910; + wire n_6912, n_6913, n_6914, n_6915, n_6916, n_6917, n_6918, n_6919; + wire n_6920, n_6921, n_6922, n_6923, n_6924, n_6925, n_6926, n_6927; + wire n_6928, n_6929, n_6931, n_6932, n_6933, n_6934, n_6935, n_6936; + wire n_6937, n_6938, n_6940, n_6941, n_6942, n_6943, n_6945, n_6946; + wire n_6947, n_6948, n_6949, n_6950, n_6951, n_6952, n_6953, n_6954; + wire n_6955, n_6956, n_6957, n_6958, n_6959, n_6960, n_6961, n_6962; + wire n_6963, n_6964, n_6965, n_6966, n_6967, n_6968, n_6969, n_6971; + wire n_6972, n_6973, n_6974, n_6975, n_6976, n_6977, n_6978, n_6979; + wire n_6981, n_6982, n_6983, n_6984, n_6987, n_6989, n_6990, n_6991; + wire n_6993, n_6994, n_6995, n_6996, n_6997, n_6998, n_6999, n_7003; + wire n_7010, n_7011, n_7012, n_7013, n_7016, n_7017, n_7018, n_7019; + wire n_7020, n_7021, n_7022, n_7023, n_7024, n_7025, n_7026, n_7027; + wire n_7028, n_7030, n_7031, n_7032, n_7033, n_7034, n_7035, n_7036; + wire n_7037, n_7038, n_7042, n_7043, n_7045, n_7046, n_7047, n_7048; + wire n_7049, n_7050, n_7052, n_7053, n_7054, n_7055, n_7056, n_7057; + wire n_7058, n_7059, n_7060, n_7062, n_7063, n_7064, n_7065, n_7066; + wire n_7067, n_7069, n_7073, n_7076, n_7077, n_7079, n_7080, n_7081; + wire n_7084, n_7085, n_7087, n_7088, n_7089, n_7090, n_7091, n_7092; + wire n_7093, n_7094, n_7095, n_7096, n_7099, n_7100, n_7101, n_7102; + wire n_7103, n_7104, n_7105, n_7106, n_7107, n_7108, n_7109, n_7110; + wire n_7111, n_7112, n_7113, n_7114, n_7115, n_7116, n_7117, n_7118; + wire n_7119, n_7120, n_7121, n_7122, n_7123, n_7124, n_7126, n_7127; + wire n_7128, n_7129, n_7130, n_7132, n_7133, n_7134, n_7135, n_7136; + wire n_7137, n_7138, n_7139, n_7140, n_7141, n_7142, n_7143, n_7144; + wire n_7145, n_7146, n_7147, n_7148, n_7149, n_7150, n_7151, n_7152; + wire n_7153, n_7154, n_7155, n_7156, n_7157, n_7160, n_7161, n_7162; + wire n_7163, n_7164, n_7165, n_7166, n_7172, n_7173, n_7175, n_7177; + wire n_7178, n_7179, n_7181, n_7182, n_7183, n_7184, n_7186, n_7187; + wire n_7188, n_7189, n_7190, n_7192, n_7193, n_7194, n_7196, n_7199; + wire n_7201, n_7202, n_7203, n_7204, n_7205, n_7207, n_7208, n_7209; + wire n_7210, n_7211, n_7212, n_7213, n_7214, n_7215, n_7216, n_7217; + wire n_7218, n_7219, n_7225, n_7227, n_7230, n_7231, n_7232, n_7233; + wire n_7235, n_7236, n_7239, n_7241, n_7244, n_7245, n_7246, n_7247; + wire n_7248, n_7249, n_7250, n_7251, n_7253, n_7254, n_7255, n_7256; + wire n_7257, n_7258, n_7260, n_7262, n_7264, n_7265, n_7266, n_7267; + wire n_7268, n_7269, n_7270, n_7271, n_7273, n_7275, n_7276, n_7277; + wire n_7278, n_7279, n_7280, n_7281, n_7282, n_7285, n_7286, n_7287; + wire n_7288, n_7289, n_7292, n_7294, n_7295, n_7296, n_7297, n_7298; + wire n_7299, n_7300, n_7301, n_7302, n_7303, n_7306, n_7309, n_7311; + wire n_7312, n_7314, n_7315, n_7316, n_7318, n_7319, n_7320, n_7324; + wire n_7325, n_7326, n_7327, n_7328, n_7329, n_7330, n_7331, n_7332; + wire n_7333, n_7335, n_7336, n_7337, n_7338, n_7339, n_7340, n_7341; + wire n_7342, n_7343, n_7344, n_7345, n_7346, n_7347, n_7348, n_7349; + wire n_7350, n_7351, n_7352, n_7353, n_7354, n_7356, n_7357, n_7358; + wire n_7359, n_7360, n_7361, n_7362, n_7363, n_7364, n_7365, n_7366; + wire n_7367, n_7369, n_7371, n_7372, n_7373, n_7374, n_7375, n_7376; + wire n_7377, n_7378, n_7379, n_7380, n_7381, n_7382, n_7383, n_7384; + wire n_7385, n_7386, n_7387, n_7388, n_7389, n_7395, n_7396, n_7402; + wire n_7408, n_7414, n_7423, n_7424, n_7428, n_7434, n_7435, n_7436; + wire n_7437, n_7438, n_7439, n_7440, n_7441, n_7442, n_7443, n_7444; + wire n_7445, n_7446, n_7447, n_7448, n_7449, n_7450, n_7451, n_7452; + wire n_7453, n_7454, n_7455, n_7456, n_7457, n_7458, n_7459, n_7460; + wire n_7461, n_7462, n_7463, n_7464, n_7465, n_7466, n_7467, n_7468; + wire n_7469, n_7470, n_7471, n_7472, n_7473, n_7475, n_7476, n_7477; + wire n_7478, n_7479, n_7480, n_7481, n_7482, n_7483, n_7484, n_7485; + wire n_7486, n_7487, n_7488, n_7490, n_7493, n_7496, n_7499, n_7505; + wire n_7507, n_7508, n_7509, n_7510, n_7511, n_7512, n_7513, n_7514; + wire n_7515, n_7518, n_7519, n_7520, n_7521, n_7522, n_7523, n_7524; + wire n_7525, n_7526, n_7527, n_7528, n_7529, n_7530, n_7531, n_7532; + wire n_7533, n_7536, n_7537, n_7538, n_7539, n_7541, n_7542, n_7557; + wire n_7558, n_7559, n_7560, n_7561, n_7562, n_7563, n_7564, n_7565; + wire n_7566, n_7567, n_7568, n_7569, n_7570, n_7571, n_7572, n_7573; + wire n_7574, n_7575, n_7576, n_7577, n_7578, n_7579, n_7580, n_7581; + wire n_7582, n_7583, n_7584, n_7585, n_7586, n_7587, n_7588, n_7589; + wire n_7590, n_7591, n_7592, n_7593, n_7594, n_7595, n_7596, n_7597; + wire n_7598, n_7599, n_7600, n_7601, n_7602, n_7603, n_7604, n_7605; + wire n_7606, n_7607, n_7608, n_7609, n_7610, n_7611, n_7612, n_7613; + wire n_7614, n_7615, n_7616, n_7617, n_7618, n_7619, n_7620, n_7621; + wire n_7622, n_7623, n_7624, n_7625, n_7626, n_7627, n_7628, n_7629; + wire n_7630, n_7631, n_7632, n_7633, n_7634, n_7635, n_7636, n_7637; + wire n_7638, n_7639, n_7640, n_7641, n_7642, n_7643, n_7644, n_7645; + wire n_7646, n_7647, n_7648, n_7649, n_7650, n_7651, n_7652, n_7653; + wire n_7654, n_7655, n_7656, n_7657, n_7658, n_7659, n_7660, n_7661; + wire n_7662, n_7663, n_7664, n_7665, n_7666, n_7667, n_7668, n_7669; + wire n_7670, n_7671, n_7672, n_7673, n_7674, n_7675, n_7676, n_7677; + wire n_7678, n_7679, n_7680, n_7681, n_7682, n_7683, n_7684, n_7685; + wire n_7686, n_7687, n_7688, n_7689, n_7690, n_7691, n_7692, n_7693; + wire n_7694, n_7695, n_7696, n_7697, n_7698, n_7699, n_7700, n_7701; + wire n_7702, n_7703, n_7704, n_7705, n_7706, n_7707, n_7708, n_7710; + wire n_7712, n_7713, n_7715, n_7716, n_7717, n_7718, n_7719, n_7721; + wire n_7722, n_7723, n_7724, n_7725, n_7726, n_7727, n_7728, n_7729; + wire n_7730, n_7731, n_7732, n_7733, n_7734, n_7735, n_7736, n_7737; + wire n_7738, n_7739, n_7740, n_7741, n_7742, n_7743, n_7744, n_7745; + wire n_7746, n_7747, n_7748, n_7749, n_7750, n_7751, n_7752, n_7753; + wire n_7754, n_7755, n_7756, n_7757, n_7758, n_7759, n_7760, n_7761; + wire n_7762, n_7763, n_7764, n_7765, n_7766, n_7767, n_7768, n_7769; + wire n_7770, n_7771, n_7772, n_7773, n_7774, n_7775, n_7776, n_7777; + wire n_7778, n_7779, n_7780, n_7781, n_7782, n_7783, n_7784, n_7785; + wire n_7786, n_7787, n_7788, n_7789, n_7790, n_7791, n_7792, n_7793; + wire n_7794, n_7795, n_7796, n_7797, n_7798, n_7799, n_7800, n_7801; + wire n_7802, n_7803, n_7804, n_7805, n_7806, n_7807, n_7808, n_7809; + wire n_7810, n_7811, n_7812, n_7813, n_7815, n_7817, n_7818, n_7819; + wire n_7821, n_7822, n_7823, n_7824, n_7825, n_7827, n_7828, n_7830; + wire n_7831, n_7832, n_7833, n_7834, n_7835, n_7836, n_7837, n_7838; + wire n_7839, n_7840, n_7841, n_7842, n_7843, n_7844, n_7845, n_7846; + wire n_7847, n_7848, n_7849, n_7850, n_7851, n_7852, n_7853, n_7854; + wire n_7855, n_7856, n_7857, n_7858, n_7859, n_7860, n_7861, n_7862; + wire n_7863, n_7864, n_7865, n_7866, n_7867, n_7868, n_7869, n_7870; + wire n_7871, n_7872, n_7873, n_7874, n_7875, n_7876, n_7877, n_7878; + wire n_7879, n_7880, n_7881, n_7882, n_7883, n_7884, n_7885, n_7886; + wire n_7887, n_7888, n_7889, n_7890, n_7891, n_7892, n_7893, n_7894; + wire n_7895, n_7896, n_7897, n_7898, n_7899, n_7900, n_7901, n_7902; + wire n_7903, n_7904, n_7906, n_7907, n_7908, n_7909, n_7910, n_7911; + wire n_7912, n_7913, n_7914, n_7915, n_7916, n_7917, n_7918, n_7919; + wire n_7920, n_7921, n_7922, n_7923, n_7924, n_7925, n_7927, n_7929; + wire n_7930, n_7932, n_7933, n_7934, n_7935, n_7936, n_7938, n_7939; + wire n_7941, n_7942, n_7943, n_7945, n_7946, n_7947, n_7948, n_7949; + wire n_7950, n_7951, n_7952, n_7953, n_7954, n_7955, n_7956, n_7957; + wire n_7958, n_7959, n_7960, n_7961, n_7962, n_7963, n_7964, n_7965; + wire n_7966, n_7967, n_7968, n_7969, n_7970, n_7971, n_7972, n_7973; + wire n_7974, n_7975, n_7976, n_7977, n_7978, n_7979, n_7980, n_7981; + wire n_7982, n_7983, n_7984, n_7985, n_7986, n_7987, n_7988, n_7989; + wire n_7990, n_7991, n_7992, n_7993, n_7994, n_7995, n_7996, n_7997; + wire n_7998, n_7999, n_8000, n_8001, n_8002, n_8003, n_8004, n_8005; + wire n_8006, n_8007, n_8008, n_8009, n_8010, n_8011, n_8012, n_8013; + wire n_8014, n_8015, n_8016, n_8017, n_8018, n_8019, n_8020, n_8021; + wire n_8022, n_8023, n_8024, n_8025, n_8026, n_8027, n_8028, n_8029; + wire n_8030, n_8031, n_8032, n_8033, n_8034, n_8035, n_8036, n_8037; + wire n_8039, n_8041, n_8042, n_8044, n_8045, n_8046, n_8047, n_8048; + wire n_8049, n_8051, n_8052, n_8054, n_8055, n_8056, n_8057, n_8058; + wire n_8060, n_8061, n_8062, n_8063, n_8064, n_8065, n_8066, n_8067; + wire n_8068, n_8069, n_8070, n_8071, n_8072, n_8073, n_8074, n_8075; + wire n_8076, n_8077, n_8078, n_8079, n_8080, n_8081, n_8082, n_8083; + wire n_8084, n_8085, n_8086, n_8087, n_8088, n_8089, n_8090, n_8091; + wire n_8092, n_8093, n_8094, n_8095, n_8096, n_8097, n_8098, n_8099; + wire n_8100, n_8101, n_8102, n_8104, n_8105, n_8106, n_8107, n_8109; + wire n_8110, n_8112, n_8113, n_8114, n_8115, n_8116, n_8117, n_8118; + wire n_8119, n_8120, n_8121, n_8122, n_8123, n_8124, n_8125, n_8126; + wire n_8127, n_8129, n_8130, n_8131, n_8132, n_8133, n_8134, n_8136; + wire n_8137, n_8138, n_8139, n_8140, n_8141, n_8142, n_8143, n_8144; + wire n_8145, n_8146, n_8147, n_8148, n_8149, n_8150, n_8151, n_8152; + wire n_8153, n_8154, n_8156, n_8157, n_8158, n_8160, n_8162, n_8163; + wire n_8164, n_8165, n_8167, n_8168, n_8169, n_8171, n_8172, n_8173; + wire n_8175, n_8177, n_8178, n_8179, n_8181, n_8182, n_8183, n_8184; + wire n_8185, n_8186, n_8187, n_8188, n_8189, n_8190, n_8191, n_8192; + wire n_8193, n_8194, n_8195, n_8196, n_8197, n_8198, n_8199, n_8200; + wire n_8201, n_8202, n_8203, n_8204, n_8205, n_8206, n_8207, n_8208; + wire n_8209, n_8210, n_8211, n_8213, n_8215, n_8218, n_8221, n_8224; + wire n_8227, n_8228, n_8229, n_8230, n_8231, n_8232, n_8233, n_8234; + wire n_8235, n_8236, n_8237, n_8238, n_8241, n_8242, n_8243, n_8244; + wire n_8245, n_8248, n_8249, n_8250, n_8252, n_8253, n_8254, n_8255; + wire n_8256, n_8257, n_8258, n_8259, n_8260, n_8261, n_8262, n_8264; + wire n_8265, n_8266, n_8267, n_8268, n_8269, n_8270, n_8271, n_8272; + wire n_8273, n_8274, n_8275, n_8277, n_8278, n_8280, n_8281, n_8282; + wire n_8283, n_8284, n_8285, n_8286, n_8287, n_8289, n_8290, n_8291; + wire n_8293, n_8294, n_8295, n_8296, n_8297, n_8298, n_8300, n_8301; + wire n_8302, n_8303, n_8304, n_8305, n_8306, n_8308, n_8309, n_8310; + wire n_8311, n_8313, n_8315, n_8317, n_8318, n_8319, n_8320, n_8321; + wire n_8322, n_8324, n_8325, n_8326, n_8327, n_8328, n_8329, n_8330; + wire n_8332, n_8333, n_8334, n_8336, n_8338, n_8340, n_8341, n_8342; + wire n_8343, n_8344, n_8345, n_8346, n_8347, n_8348, n_8349, n_8350; + wire n_8351, n_8352, n_8353, n_8354, n_8355, n_8356, n_8357, n_8358; + wire n_8359, n_8360, n_8361, n_8362, n_8363, n_8364, n_8365, n_8366; + wire n_8367, n_8368, n_8369, n_8370, n_8371, n_8372, n_8373, n_8374; + wire n_8375, n_8376, n_8377, n_8378, n_8379, n_8380, n_8381, n_8382; + wire n_8383, n_8384, n_8385, n_8386, n_8387, n_8388, n_8389, n_8390; + wire n_8391, n_8392, n_8393, n_8394, n_8395, n_8396, n_8397, n_8398; + wire n_8399, n_8400, n_8401, n_8402, n_8403, n_8404, n_8405, n_8406; + wire n_8407, n_8408, n_8410, n_8411, n_8412, n_8413, n_8415, n_8416; + wire n_8418, n_8419, n_8420, n_8421, n_8422, n_8424, n_8425, n_8426; + wire n_8427, n_8428, n_8430, n_8431, n_8432, n_8433, n_8434, n_8435; + wire n_8436, n_8437, n_8438, n_8439, n_8440, n_8441, n_8442, n_8443; + wire n_8445, n_8446, n_8447, n_8448, n_8449, n_8450, n_8452, n_8453; + wire n_8454, n_8455, n_8456, n_8457, n_8458, n_8459, n_8460, n_8462; + wire n_8463, n_8464, n_8465, n_8467, n_8468, n_8469, n_8470, n_8471; + wire n_8472, n_8473, n_8474, n_8475, n_8476, n_8477, n_8478, n_8479; + wire n_8480, n_8481, n_8482, n_8483, n_8484, n_8485, n_8486, n_8487; + wire n_8488, n_8489, n_8490, n_8491, n_8492, n_8493, n_8494, n_8496; + wire n_8498, n_8500, n_8502, n_8504, n_8505, n_8506, n_8507, n_8508; + wire n_8509, n_8510, n_8511, n_8512, n_8513, n_8514, n_8515, n_8516; + wire n_8517, n_8518, n_8519, n_8520, n_8521, n_8522, n_8523, n_8524; + wire n_8525, n_8526, n_8527, n_8528, n_8529, n_8530, n_8532, n_8534; + wire n_8535, n_8536, n_8537, n_8538, n_8540, n_8542, n_8543, n_8545; + wire n_8546, n_8548, n_8549, n_8550, n_8551, n_8554, n_8555, n_8556; + wire n_8558, n_8560, n_8562, n_8563, n_8564, n_8565, n_8566, n_8567; + wire n_8568, n_8569, n_8570, n_8571, n_8573, n_8575, n_8577, n_8579; + wire n_8581, n_8584, n_8586, n_8588, n_8589, n_8592, n_8594, n_8597; + wire n_8599, n_8601, n_8604, n_8606, n_8608, n_8610, n_8611, n_8613; + wire n_8616, n_8618, n_8620, n_8622, n_8624, n_8626, n_8627, n_8628; + wire n_8630, n_8631, n_8633, n_8634, n_8635, n_8636, n_8637, n_8638; + wire n_8639, n_8640, n_8641, n_8642, n_8643, n_8644, n_8646, n_8648; + wire n_8649, n_8651, n_8652, n_8653, n_8654, n_8655, n_8660, n_8661; + wire n_8662, n_8663, n_8664, n_8665, n_8666, n_8667, n_8669, n_8670; + wire n_8671, n_8673, n_8674, n_8675, n_8676, n_8677, n_8678, n_8679; + wire n_8680, n_8681, n_8682, n_8684, n_8685, n_8686, n_8687, n_8688; + wire n_8689, n_8691, n_8692, n_8693, n_8694, n_8695, n_8696, n_8698; + wire n_8699, n_8700, n_8701, n_8703, n_8704, n_8705, n_8707, n_8708; + wire n_8709, n_8711, n_8713, n_8714, n_8715, n_8717, n_8718, n_8719; + wire n_8720, n_8721, n_8722, n_8724, n_8725, n_8726, n_8727, n_8728; + wire n_8730, n_8731, n_8732, n_8733, n_8735, n_8736, n_8737, n_8738; + wire n_8739, n_8740, n_8742, n_8744, n_8745, n_8747, n_8748, n_8750; + wire n_8751, n_8752, n_8753, n_8754, n_8755, n_8756, n_8758, n_8759; + wire n_8760, n_8761, n_8763, n_8764, n_8765, n_8766, n_8767, n_8768; + wire n_8770, n_8772, n_8773, n_8775, n_8776, n_8778, n_8779, n_8780; + wire n_8781, n_8782, n_8783, n_8784, n_8786, n_8787, n_8788, n_8789; + wire n_8791, n_8792, n_8793, n_8794, n_8795, n_8796, n_8798, n_8800; + wire n_8801, n_8803, n_8804, n_8806, n_8807, n_8808, n_8809, n_8810; + wire n_8811, n_8812, n_8813, n_8815, n_8816, n_8817, n_8818, n_8820; + wire n_8821, n_8822, n_8823, n_8824, n_8825, n_8827, n_8829, n_8830; + wire n_8832, n_8833, n_8835, n_8836, n_8837, n_8838, n_8839, n_8841; + wire n_8842, n_8843, n_8844, n_8845, n_8846, n_8847, n_8848, n_8849; + wire n_8850, n_8851, n_8852, n_8854, n_8855, n_8856, n_8857, n_8858; + wire n_8859, n_8860, n_8861, n_8862, n_8864, n_8865, n_8866, n_8867; + wire n_8868, n_8869, n_8870, n_8871, n_8872, n_8874, n_8875, n_8876; + wire n_8878, n_8879, n_8880, n_8881, n_8882, n_8883, n_8885, n_8886; + wire n_8888, n_8890, n_8891, n_8892, n_8893, n_8894, n_8895, n_8896; + wire n_8897, n_8898, n_8899, n_8900, n_8901, n_8902, n_8903, n_8905; + wire n_8906, n_8907, n_8908, n_8909, n_8910, n_8911, n_8912, n_8914; + wire n_8915, n_8916, n_8917, n_8918, n_8920, n_8921, n_8922, n_8924; + wire n_8925, n_8926, n_8928, n_8929, n_8930, n_8931, n_8932, n_8933; + wire n_8934, n_8935, n_8936, n_8938, n_8939, n_8940, n_8941, n_8943; + wire n_8944, n_8945, n_8946, n_8947, n_8948, n_8949, n_8950, n_8951; + wire n_8952, n_8953, n_8954, n_8955, n_8956, n_8957, n_8958, n_8959; + wire n_8960, n_8961, n_8962, n_8963, n_8964, n_8965, n_8967, n_8968; + wire n_8969, n_8970, n_8971, n_8972, n_8973, n_8974, n_8975, n_8976; + wire n_8977, n_8978, n_8979, n_8980, n_8981, n_8982, n_8983, n_8984; + wire n_8985, n_8986, n_8987, n_8988, n_8989, n_8990, n_8991, n_8992; + wire n_8993, n_8995, n_8996, n_8998, n_8999, n_9000, n_9001, n_9002; + wire n_9003, n_9004, n_9005, n_9007, n_9008, n_9009, n_9010, n_9011; + wire n_9012, n_9013, n_9014, n_9015, n_9016, n_9018, n_9019, n_9020; + wire n_9021, n_9022, n_9023, n_9024, n_9025, n_9026, n_9028, n_9029; + wire n_9030, n_9031, n_9033, n_9034, n_9035, n_9036, n_9037, n_9038; + wire n_9039, n_9040, n_9041, n_9042, n_9043, n_9044, n_9045, n_9046; + wire n_9047, n_9048, n_9049, n_9050, n_9052, n_9054, n_9055, n_9056; + wire n_9058, n_9060, n_9061, n_9062, n_9063, n_9064, n_9065, n_9066; + wire n_9067, n_9068, n_9069, n_9070, n_9071, n_9072, n_9073, n_9074; + wire n_9075, n_9076, n_9077, n_9078, n_9079, n_9080, n_9081, n_9082; + wire n_9083, n_9084, n_9085, n_9086, n_9087, n_9088, n_9089, n_9091; + wire n_9092, n_9093, n_9094, n_9096, n_9097, n_9098, n_9099, n_9100; + wire n_9101, n_9102, n_9103, n_9104, n_9105, n_9106, n_9107, n_9108; + wire n_9109, n_9110, n_9111, n_9112, n_9113, n_9114, n_9115, n_9116; + wire n_9117, n_9118, n_9119, n_9120, n_9121, n_9122, n_9124, n_9125; + wire n_9127, n_9128, n_9129, n_9130, n_9131, n_9132, n_9133, n_9134; + wire n_9136, n_9137, n_9138, n_9139, n_9140, n_9141, n_9142, n_9143; + wire n_9144, n_9145, n_9147, n_9148, n_9149, n_9150, n_9151, n_9152; + wire n_9153, n_9155, n_9156, n_9157, n_9158, n_9160, n_9161, n_9162; + wire n_9164, n_9165, n_9166, n_9167, n_9168, n_9169, n_9170, n_9171; + wire n_9172, n_9173, n_9174, n_9175, n_9176, n_9177, n_9179, n_9181; + wire n_9182, n_9183, n_9185, n_9187, n_9188, n_9189, n_9190, n_9191; + wire n_9192, n_9193, n_9195, n_9196, n_9197, n_9198, n_9199, n_9200; + wire n_9201, n_9202, n_9203, n_9204, n_9205, n_9206, n_9207, n_9208; + wire n_9209, n_9210, n_9211, n_9212, n_9213, n_9214, n_9216, n_9217; + wire n_9218, n_9219, n_9221, n_9222, n_9223, n_9224, n_9226, n_9227; + wire n_9228, n_9229, n_9230, n_9231, n_9232, n_9233, n_9234, n_9235; + wire n_9236, n_9237, n_9238, n_9239, n_9240, n_9241, n_9242, n_9243; + wire n_9244, n_9245, n_9246, n_9247, n_9249, n_9250, n_9252, n_9253; + wire n_9254, n_9255, n_9256, n_9257, n_9258, n_9259, n_9261, n_9262; + wire n_9263, n_9264, n_9265, n_9266, n_9267, n_9268, n_9269, n_9270; + wire n_9272, n_9273, n_9274, n_9275, n_9276, n_9277, n_9278, n_9280; + wire n_9281, n_9282, n_9283, n_9285, n_9286, n_9287, n_9288, n_9289; + wire n_9290, n_9291, n_9292, n_9293, n_9294, n_9296, n_9297, n_9298; + wire n_9299, n_9300, n_9301, n_9302, n_9304, n_9306, n_9307, n_9308; + wire n_9310, n_9312, n_9313, n_9314, n_9315, n_9316, n_9317, n_9318; + wire n_9319, n_9320, n_9321, n_9322, n_9324, n_9325, n_9326, n_9327; + wire n_9328, n_9329, n_9330, n_9331, n_9332, n_9333, n_9334, n_9335; + wire n_9336, n_9337, n_9338, n_9339, n_9340, n_9342, n_9343, n_9344; + wire n_9345, n_9346, n_9347, n_9348, n_9349, n_9350, n_9351, n_9352; + wire n_9353, n_9354, n_9355, n_9356, n_9357, n_9359, n_9360, n_9361; + wire n_9362, n_9363, n_9364, n_9365, n_9366, n_9368, n_9369, n_9370; + wire n_9371, n_9373, n_9375, n_9376, n_9378, n_9379, n_9380, n_9381; + wire n_9382, n_9383, n_9385, n_9386, n_9387, n_9388, n_9389, n_9391; + wire n_9392, n_9393, n_9394, n_9396, n_9398, n_9399, n_9400, n_9401; + wire n_9402, n_9404, n_9405, n_9406, n_9407, n_9409, n_9411, n_9412; + wire n_9413, n_9414, n_9416, n_9417, n_9419, n_9420, n_9421, n_9422; + wire n_9424, n_9426, n_9427, n_9428, n_9429, n_9430, n_9432, n_9433; + wire n_9434, n_9435, n_9437, n_9439, n_9440, n_9441, n_9442, n_9443; + wire n_9444, n_9445, n_9446, n_9447, n_9448, n_9449, n_9450, n_9451; + wire n_9452, n_9453, n_9454, n_9455, n_9456, n_9457, n_9458, n_9459; + wire n_9460, n_9461, n_9462, n_9463, n_9464, n_9465, n_9466, n_9467; + wire n_9468, n_9469, n_9470, n_9471, n_9472, n_9473, n_9474, n_9475; + wire n_9476, n_9477, n_9478, n_9479, n_9480, n_9481, n_9482, n_9483; + wire n_9484, n_9485, n_9486, n_9487, n_9488, n_9489, n_9490, n_9491; + wire n_9492, n_9493, n_9494, n_9495, n_9496, n_9497, n_9498, n_9499; + wire n_9500, n_9501, n_9502, n_9503, n_9504, n_9506, n_9507, n_9508; + wire n_9509, n_9510, n_9511, n_9512, n_9513, n_9514, n_9515, n_9516; + wire n_9517, n_9518, n_9519, n_9520, n_9521, n_9522, n_9523, n_9524; + wire n_9525, n_9526, n_9527, n_9528, n_9529, n_9530, n_9531, n_9532; + wire n_9533, n_9534, n_9535, n_9536, n_9537, n_9538, n_9539, n_9541; + wire n_9542, n_9543, n_9544, n_9545, n_9546, n_9547, n_9548, n_9549; + wire n_9550, n_9551, n_9552, n_9553, n_9554, n_9555, n_9556, n_9557; + wire n_9558, n_9559, n_9560, n_9561, n_9563, n_9564, n_9567, n_9569; + wire n_9571, n_9572, n_9573, n_9574, n_9575, n_9576, n_9577, n_9578; + wire n_9579, n_9580, n_9581, n_9582, n_9583, n_9584, n_9585, n_9586; + wire n_9587, n_9588, n_9589, n_9590, n_9591, n_9592, n_9593, n_9594; + wire n_9595, n_9596, n_9597, n_9598, n_9599, n_9600, n_9601, n_9602; + wire n_9603, n_9604, n_9605, n_9606, n_9607, n_9608, n_9611, n_9612; + wire n_9613, n_9614, n_9615, n_9616, n_9617, n_9618, n_9619, n_9620; + wire n_9625, n_9626, n_9628, n_9629, n_9630, n_9631, n_9632, n_9633; + wire n_9635, n_9636, n_9637, n_9638, n_9639, n_9640, n_9641, n_9642; + wire n_9643, n_9644, n_9645, n_9646, n_9647, n_9648, n_9650, n_9651; + wire n_9652, n_9653, n_9654, n_9655, n_9656, n_9657, n_9658, n_9659; + wire n_9660, n_9661, n_9666, n_9668, n_9672, n_9674, n_9675, n_9676; + wire n_9681, n_9685, n_9686, n_9687, n_9688, n_9689, n_9690, n_9691; + wire n_9692, n_9693, n_9694, n_9695, n_9696, n_9697, n_9698, n_9699; + wire n_9700, n_9701, n_9702, n_9703, n_9705, n_9710, n_9711, n_9712; + wire n_9717, n_9719, n_9720, n_9721, n_9724, n_9726, n_9734, n_9737; + wire n_9741, n_9749, n_9750, n_9751, n_9752, n_9753, n_9754, n_9755; + wire n_9756, n_9757, n_9758, n_9759, n_9760, n_9761, n_9762, n_9763; + wire n_9764, n_9765, n_9766, n_9767, n_9768, n_9769, n_9770, n_9771; + wire n_9772, n_9773, n_9774, n_9775, n_9776, n_9777, n_9778, n_9779; + wire n_9780, n_9782, n_9784, n_9785, n_9786, n_9788, n_9789, n_9794; + wire n_9795, n_9796, n_9797, n_9798, n_9803, n_9804, n_9806, n_9807; + wire n_9808, n_9810, n_9811, n_9812, n_9813, n_9815, n_9818, n_9820; + wire n_9827, n_9829, n_9831, n_9833, n_9834, n_9835, n_9836, n_9837; + wire n_9838, n_9840, n_9841, n_9842, n_9843, n_9844, n_9845, n_9846; + wire n_9847, n_9848, n_9849, n_9850, n_9853, n_9854, n_9855, n_9856; + wire n_9857, n_9858, n_9859, n_9860, n_9861, n_9862, n_9863, n_9865; + wire n_9867, n_9868, n_9869, n_9871, n_9872, n_9873, n_9876, n_9882; + wire n_9883, n_9884, n_9885, n_9901, n_9902, n_9903, n_9905, n_9907; + wire n_9908, n_9910, n_9914, n_9915, n_9920, n_9921, n_9922, n_9925; + wire n_9926, n_9927, n_9928, n_9929, n_9930, n_9931, n_9932, n_9933; + wire n_9940, n_9941, n_9943, n_9947, n_9951, n_9952, n_9953, n_9954; + wire n_9955, n_9956, n_9957, n_9958, n_9960, n_9961, n_9962, n_9963; + wire n_9964, n_9965, n_9966, n_9967, n_9968, n_9969, n_9970, n_9972; + wire n_9973, n_9974, n_9975, n_9976, n_9977, n_9978, n_9979, n_9980; + wire n_9981, n_9982, n_9983, n_9984, n_9985, n_9986, n_9987, n_9988; + wire n_9989, n_9990, n_9991, n_9992, n_9993, n_9994, n_9995, n_9996; + wire n_9997, n_9998, n_9999, n_10000, n_10001, n_10002, n_10003, + n_10004; + wire n_10005, n_10006, n_10007, n_10008, n_10009, n_10010, n_10011, + n_10012; + wire n_10013, n_10014, n_10015, n_10016, n_10017, n_10018, n_10019, + n_10020; + wire n_10022, n_10023, n_10024, n_10025, n_10026, n_10027, n_10028, + n_10029; + wire n_10030, n_10031, n_10032, n_10034, n_10035, n_10037, n_10038, + n_10040; + wire n_10041, n_10042, n_10043, n_10044, n_10045, n_10046, n_10047, + n_10048; + wire n_10049, n_10050, n_10052, n_10053, n_10054, n_10055, n_10056, + n_10057; + wire n_10058, n_10059, n_10060, n_10062, n_10063, n_10064, n_10065, + n_10066; + wire n_10067, n_10068, n_10069, n_10071, n_10072, n_10073, n_10074, + n_10075; + wire n_10076, n_10078, n_10079, n_10080, n_10081, n_10082, n_10083, + n_10084; + wire n_10085, n_10086, n_10087, n_10088, n_10089, n_10090, n_10091, + n_10092; + wire n_10094, n_10095, n_10096, n_10097, n_10098, n_10099, n_10100, + n_10101; + wire n_10102, n_10103, n_10104, n_10105, n_10106, n_10108, n_10110, + n_10111; + wire n_10112, n_10114, n_10115, n_10118, n_10119, n_10120, n_10122, + n_10123; + wire n_10124, n_10126, n_10127, n_10128, n_10129, n_10130, n_10131, + n_10132; + wire n_10133, n_10134, n_10135, n_10136, n_10137, n_10138, n_10139, + n_10140; + wire n_10141, n_10142, n_10143, n_10145, n_10146, n_10147, n_10148, + n_10150; + wire n_10151, n_10152, n_10154, n_10155, n_10156, n_10157, n_10158, + n_10159; + wire n_10160, n_10162, n_10163, n_10164, n_10165, n_10166, n_10167, + n_10168; + wire n_10169, n_10170, n_10172, n_10173, n_10174, n_10176, n_10178, + n_10179; + wire n_10180, n_10181, n_10182, n_10183, n_10184, n_10185, n_10187, + n_10188; + wire n_10190, n_10194, n_10196, n_10197, n_10198, n_10199, n_10200, + n_10201; + wire n_10202, n_10204, n_10205, n_10206, n_10207, n_10209, n_10211, + n_10212; + wire n_10214, n_10215, n_10216, n_10217, n_10219, n_10220, n_10221, + n_10223; + wire n_10224, n_10225, n_10226, n_10228, n_10229, n_10230, n_10232, + n_10233; + wire n_10234, n_10235, n_10236, n_10238, n_10239, n_10241, n_10242, + n_10243; + wire n_10244, n_10245, n_10247, n_10249, n_10250, n_10251, n_10252, + n_10253; + wire n_10254, n_10256, n_10258, n_10259, n_10261, n_10262, n_10263, + n_10264; + wire n_10265, n_10266, n_10267, n_10268, n_10269, n_10270, n_10272, + n_10274; + wire n_10275, n_10276, n_10277, n_10278, n_10279, n_10280, n_10281, + n_10283; + wire n_10284, n_10285, n_10287, n_10288, n_10289, n_10290, n_10291, + n_10293; + wire n_10295, n_10296, n_10298, n_10299, n_10300, n_10301, n_10302, + n_10303; + wire n_10304, n_10305, n_10306, n_10307, n_10308, n_10309, n_10310, + n_10311; + wire n_10313, n_10314, n_10315, n_10316, n_10317, n_10318, n_10319, + n_10321; + wire n_10322, n_10323, n_10325, n_10326, n_10327, n_10328, n_10329, + n_10330; + wire n_10331, n_10332, n_10333, n_10335, n_10337, n_10338, n_10339, + n_10340; + wire n_10341, n_10342, n_10343, n_10344, n_10345, n_10346, n_10347, + n_10348; + wire n_10349, n_10350, n_10351, n_10352, n_10353, n_10354, n_10355, + n_10356; + wire n_10357, n_10358, n_10359, n_10360, n_10361, n_10362, n_10363, + n_10364; + wire n_10365, n_10366, n_10367, n_10369, n_10370, n_10371, n_10372, + n_10373; + wire n_10374, n_10375, n_10376, n_10377, n_10378, n_10379, n_10380, + n_10382; + wire n_10383, n_10384, n_10385, n_10386, n_10387, n_10388, n_10389, + n_10390; + wire n_10391, n_10392, n_10393, n_10394, n_10397, n_10399, n_10400, + n_10401; + wire n_10402, n_10403, n_10404, n_10405, n_10406, n_10407, n_10408, + n_10409; + wire n_10411, n_10412, n_10413, n_10415, n_10416, n_10417, n_10418, + n_10420; + wire n_10421, n_10422, n_10423, n_10424, n_10425, n_10426, n_10428, + n_10429; + wire n_10430, n_10432, n_10433, n_10435, n_10436, n_10437, n_10438, + n_10439; + wire n_10440, n_10441, n_10443, n_10444, n_10445, n_10446, n_10447, + n_10448; + wire n_10449, n_10450, n_10451, n_10452, n_10453, n_10454, n_10455, + n_10456; + wire n_10457, n_10458, n_10459, n_10462, n_10466, n_10472, n_10476, + n_10481; + wire n_10483, n_10489, n_10493, n_10494, n_10496, n_10498, n_10501, + n_10504; + wire n_10508, n_10513, n_10514, n_10518, n_10521, n_10523, n_10529, + n_10535; + wire n_10537, n_10538, n_10539, n_10540, n_10542, n_10543, n_10544, + n_10545; + wire n_10546, n_10547, n_10549, n_10551, n_10552, n_10554, n_10555, + n_10556; + wire n_10558, n_10559, n_10561, n_10562, n_10563, n_10564, n_10565, + n_10566; + wire n_10567, n_10573, n_10574, n_10583, n_10587, n_10589, n_10592, + n_10595; + wire n_10599, n_10600, n_10601, n_10605, n_10607, n_10609, n_10613, + n_10614; + wire n_10615, n_10616, n_10617, n_10618, n_10619, n_10620, n_10621, + n_10622; + wire n_10623, n_10625, n_10626, n_10633, n_10634, n_10636, n_10645, + n_10649; + wire n_10651, n_10652, n_10654, n_10655, n_10657, n_10659, n_10661, + n_10663; + wire n_10664, n_10665, n_10666, n_10667, n_10668, n_10669, n_10670, + n_10671; + wire n_10672, n_10673, n_10674, n_10675, n_10676, n_10677, n_10678, + n_10679; + wire n_10680, n_10681, n_10682, n_10684, n_10685, n_10686, n_10688, + n_10690; + wire n_10691, n_10693, n_10694, n_10695, n_10697, n_10699, n_10700, + n_10701; + wire n_10702, n_10703, n_10704, n_10705, n_10706, n_10707, n_10708, + n_10709; + wire n_10710, n_10711, n_10712, n_10713, n_10714, n_10715, n_10717, + n_10718; + wire n_10719, n_10721, n_10722, n_10723, n_10725, n_10727, n_10728, + n_10730; + wire n_10731, n_10732, n_10733, n_10735, n_10737, n_10738, n_10739, + n_10740; + wire n_10742, n_10743, n_10744, n_10746, n_10747, n_10748, n_10750, + n_10751; + wire n_10752, n_10753, n_10754, n_10755, n_10756, n_10757, n_10758, + n_10760; + wire n_10762, n_10763, n_10764, n_10765, n_10766, n_10768, n_10769, + n_10770; + wire n_10771, n_10772, n_10773, n_10774, n_10775, n_10776, n_10777, + n_10778; + wire n_10780, n_10781, n_10783, n_10784, n_10785, n_10786, n_10787, + n_10788; + wire n_10789, n_10790, n_10791, n_10794, n_10795, n_10796, n_10798, + n_10799; + wire n_10800, n_10801, n_10802, n_10803, n_10804, n_10805, n_10806, + n_10807; + wire n_10808, n_10809, n_10810, n_10811, n_10812, n_10813, n_10814, + n_10815; + wire n_10817, n_10818, n_10819, n_10820, n_10821, n_10822, n_10825, + n_10827; + wire n_10828, n_10829, n_10830, n_10831, n_10832, n_10833, n_10834, + n_10836; + wire n_10837, n_10838, n_10839, n_10840, n_10841, n_10842, n_10843, + n_10844; + wire n_10845, n_10846, n_10847, n_10848, n_10849, n_10850, n_10851, + n_10852; + wire n_10853, n_10854, n_10855, n_10856, n_10857, n_10858, n_10859, + n_10860; + wire n_10862, n_10863, n_10864, n_10866, n_10867, n_10868, n_10870, + n_10872; + wire n_10873, n_10875, n_10876, n_10877, n_10879, n_10880, n_10881, + n_10882; + wire n_10884, n_10885, n_10886, n_10888, n_10890, n_10892, n_10893, + n_10894; + wire n_10895, n_10896, n_10897, n_10898, n_10899, n_10900, n_10902, + n_10903; + wire n_10904, n_10905, n_10906, n_10907, n_10908, n_10909, n_10910, + n_10911; + wire n_10912, n_10913, n_10914, n_10915, n_10916, n_10917, n_10919, + n_10920; + wire n_10921, n_10922, n_10923, n_10924, n_10926, n_10927, n_10928, + n_10929; + wire n_10930, n_10931, n_10932, n_10933, n_10934, n_10935, n_10937, + n_10939; + wire n_10940, n_10941, n_10942, n_10943, n_10944, n_10945, n_10946, + n_10947; + wire n_10948, n_10949, n_10950, n_10951, n_10952, n_10953, n_10954, + n_10955; + wire n_10956, n_10957, n_10958, n_10959, n_10960, n_10961, n_10963, + n_10964; + wire n_10966, n_10967, n_10968, n_10969, n_10970, n_10971, n_10973, + n_10974; + wire n_10976, n_10977, n_10978, n_10979, n_10981, n_10982, n_10983, + n_10984; + wire n_10985, n_10986, n_10988, n_10989, n_10990, n_10991, n_10992, + n_10993; + wire n_10994, n_10995, n_10996, n_10998, n_10999, n_11002, n_11004, + n_11005; + wire n_11006, n_11007, n_11008, n_11009, n_11010, n_11011, n_11012, + n_11014; + wire n_11015, n_11016, n_11017, n_11018, n_11019, n_11020, n_11021, + n_11022; + wire n_11023, n_11024, n_11025, n_11026, n_11027, n_11028, n_11029, + n_11030; + wire n_11031, n_11032, n_11033, n_11034, n_11035, n_11036, n_11037, + n_11038; + wire n_11039, n_11040, n_11041, n_11042, n_11043, n_11044, n_11045, + n_11047; + wire n_11049, n_11051, n_11052, n_11053, n_11054, n_11055, n_11056, + n_11057; + wire n_11058, n_11059, n_11060, n_11061, n_11062, n_11063, n_11064, + n_11065; + wire n_11066, n_11068, n_11069, n_11070, n_11072, n_11073, n_11074, + n_11075; + wire n_11076, n_11077, n_11078, n_11079, n_11080, n_11081, n_11082, + n_11083; + wire n_11084, n_11085, n_11086, n_11087, n_11089, n_11091, n_11092, + n_11093; + wire n_11094, n_11095, n_11096, n_11097, n_11098, n_11099, n_11100, + n_11101; + wire n_11102, n_11103, n_11104, n_11105, n_11106, n_11107, n_11108, + n_11109; + wire n_11110, n_11111, n_11112, n_11113, n_11114, n_11115, n_11116, + n_11117; + wire n_11118, n_11119, n_11120, n_11121, n_11122, n_11123, n_11124, + n_11125; + wire n_11126, n_11128, n_11129, n_11130, n_11131, n_11134, n_11135, + n_11136; + wire n_11142, n_11144, n_11145, n_11146, n_11148, n_11149, n_11150, + n_11151; + wire n_11152, n_11153, n_11155, n_11157, n_11158, n_11159, n_11160, + n_11161; + wire n_11162, n_11163, n_11164, n_11165, n_11166, n_11167, n_11168, + n_11169; + wire n_11170, n_11171, n_11172, n_11173, n_11174, n_11175, n_11176, + n_11178; + wire n_11179, n_11180, n_11181, n_11182, n_11183, n_11184, n_11185, + n_11186; + wire n_11187, n_11188, n_11189, n_11190, n_11191, n_11192, n_11193, + n_11194; + wire n_11195, n_11196, n_11197, n_11198, n_11199, n_11200, n_11201, + n_11202; + wire n_11203, n_11204, n_11205, n_11206, n_11207, n_11209, n_11210, + n_11211; + wire n_11212, n_11213, n_11214, n_11215, n_11216, n_11217, n_11218, + n_11219; + wire n_11220, n_11221, n_11223, n_11224, n_11225, n_11227, n_11228, + n_11230; + wire n_11231, n_11232, n_11233, n_11234, n_11235, n_11236, n_11237, + n_11238; + wire n_11239, n_11240, n_11241, n_11242, n_11243, n_11244, n_11245, + n_11246; + wire n_11247, n_11248, n_11249, n_11250, n_11251, n_11252, n_11253, + n_11254; + wire n_11255, n_11256, n_11257, n_11258, n_11260, n_11262, n_11263, + n_11264; + wire n_11266, n_11267, n_11268, n_11269, n_11270, n_11272, n_11273, + n_11274; + wire n_11276, n_11278, n_11279, n_11280, n_11281, n_11283, n_11284, + n_11286; + wire n_11287, n_11288, n_11289, n_11290, n_11291, n_11292, n_11293, + n_11294; + wire n_11295, n_11296, n_11297, n_11298, n_11299, n_11300, n_11301, + n_11302; + wire n_11303, n_11304, n_11305, n_11306, n_11307, n_11308, n_11310, + n_11311; + wire n_11312, n_11313, n_11314, n_11315, n_11317, n_11318, n_11319, + n_11320; + wire n_11321, n_11323, n_11324, n_11326, n_11327, n_11328, n_11329, + n_11330; + wire n_11332, n_11333, n_11334, n_11336, n_11338, n_11339, n_11341, + n_11342; + wire n_11344, n_11346, n_11347, n_11348, n_11349, n_11351, n_11352, + n_11353; + wire n_11354, n_11355, n_11356, n_11358, n_11360, n_11361, n_11363, + n_11364; + wire n_11365, n_11366, n_11368, n_11370, n_11371, n_11372, n_11373, + n_11375; + wire n_11376, n_11377, n_11378, n_11379, n_11381, n_11383, n_11384, + n_11385; + wire n_11387, n_11388, n_11389, n_11390, n_11391, n_11392, n_11393, + n_11394; + wire n_11395, n_11396, n_11397, n_11399, n_11400, n_11401, n_11403, + n_11404; + wire n_11406, n_11408, n_11409, n_11410, n_11411, n_11413, n_11414, + n_11416; + wire n_11417, n_11418, n_11419, n_11420, n_11421, n_11423, n_11424, + n_11425; + wire n_11426, n_11427, n_11428, n_11429, n_11430, n_11431, n_11433, + n_11434; + wire n_11435, n_11436, n_11437, n_11438, n_11439, n_11440, n_11441, + n_11442; + wire n_11443, n_11444, n_11445, n_11446, n_11447, n_11448, n_11449, + n_11450; + wire n_11451, n_11452, n_11453, n_11454, n_11455, n_11456, n_11457, + n_11458; + wire n_11459, n_11460, n_11461, n_11462, n_11463, n_11464, n_11465, + n_11466; + wire n_11467, n_11468, n_11472, n_11476, n_11482, n_11491, n_11494, + n_11495; + wire n_11499, n_11501, n_11503, n_11504, n_11505, n_11507, n_11508, + n_11509; + wire n_11510, n_11511, n_11512, n_11513, n_11514, n_11515, n_11516, + n_11518; + wire n_11520, n_11522, n_11526, n_11528, n_11529, n_11530, n_11533, + n_11534; + wire n_11536, n_11538, n_11539, n_11540, n_11541, n_11542, n_11563, + n_11564; + wire n_11578, n_11579, n_11585, n_11586, n_11587, n_11597, n_11600, + n_11612; + wire n_11613, n_11614, n_11615, n_11616, n_11617, n_11618, n_11619, + n_11620; + wire n_11621, n_11622, n_11623, n_11624, n_11625, n_11626, n_11627, + n_11628; + wire n_11629, n_11630, n_11631, n_11632, n_11633, n_11634, n_11635, + n_11636; + wire n_11637, n_11638, n_11639, n_11640, n_11641, n_11642, n_11646, + n_11647; + wire n_11650, n_11651, n_11654, n_11655, n_11656, n_11657, n_11658, + n_11659; + wire n_11660, n_11661, n_11662, n_11663, n_11666, n_11667, n_11668, + n_11669; + wire n_11670, n_11671, n_11672, n_11673, n_11674, n_11675, n_11676, + n_11677; + wire n_11697, n_11698, n_11699, n_11700, n_11703, n_11704, n_11707, + n_11708; + wire n_11709, n_11710, n_11711, n_11712, n_11713, n_11714, n_11715, + n_11716; + wire n_11717, n_11718, n_11719, n_11720, n_11721, n_11722, n_11724, + n_11729; + wire n_11730, n_11731, n_11732, n_11733, n_11734, n_11735, n_11736, + n_11737; + wire n_11738, n_11741, n_11742, n_11743, n_11744, n_11746, n_11748, + n_11749; + wire n_11750, n_11751, n_11752, n_11762, n_11772, n_11777, n_11789, + n_11797; + wire n_11798, n_11802, n_11804, n_11823, n_11827, n_11841, n_11842, + n_11843; + wire n_11844, n_11846, n_11851, n_11852, n_11853, n_11855, n_11856, + n_11887; + wire n_11888, n_11889, n_11890, n_11891, n_11892, n_11893, n_11894, + n_11895; + wire n_11897, n_11898, n_11900, n_11901, n_11903, n_11904, n_11905, + n_11906; + wire n_11907, n_11908, n_11911, n_11912, n_11913, n_11914, n_11919, + n_11922; + wire n_11923, n_11924, n_11925, n_11927, n_11928, n_11934, n_11948, + n_11949; + wire n_11950, n_11951, n_11952, n_11953, n_11954, n_11955, n_11956, + n_11957; + wire n_11958, n_11959, n_11960, n_11961, n_11962, n_11963, n_11964, + n_11965; + wire n_11966, n_11967, n_11968, n_11969, n_11970, n_11971, n_11972, + n_11973; + wire n_11974, n_11975, n_11976, n_11977, n_11978, n_11979, n_11980, + n_11981; + wire n_11984, n_11985, n_11986, n_11987, n_11988, n_11989, n_11990, + n_11991; + wire n_11992, n_11993, n_11994, n_11995, n_11996, n_11997, n_11999, + n_12000; + wire n_12001, n_12004, n_12005, n_12006, n_12007, n_12008, n_12009, + n_12010; + wire n_12011, n_12012, n_12013, n_12016, n_12017, n_12018, n_12019, + n_12026; + wire n_12027, n_12030, n_12031, n_12032, n_12033, n_12034, n_12035, + n_12036; + wire n_12037, n_12038, n_12039, n_12041, n_12042, n_12043, n_12046, + n_12047; + wire n_12048, n_12049, n_12050, n_12051, n_12052, n_12053, n_12054, + n_12055; + wire n_12056, n_12057, n_12058, n_12059, n_12060, n_12061, n_12062, + n_12063; + wire n_12064, n_12065, n_12066, n_12067, n_12076, n_12077, n_12079, + n_12087; + wire n_12091, n_12111, n_12114, n_12115, n_12116, n_12120, n_12121, + n_12124; + wire n_12125, n_12131, n_12132, n_12135, n_12136, n_12140, n_12142, + n_12143; + wire n_12144, n_12145, n_12146, n_12147, n_12148, n_12149, n_12150, + n_12152; + wire n_12153, n_12156, n_12157, n_12161, n_12164, n_12165, n_12166, + n_12167; + wire n_12168, n_12169, n_12170, n_12171, n_12172, n_12193, n_12194, + n_12195; + wire n_12196, n_12204, n_12214, n_12244, n_12250, n_12252, n_12256, + n_12258; + wire n_12259, n_12261, n_12262, n_12265, n_12267, n_12269, n_12270, + n_12272; + wire n_12273, n_12274, n_12278, n_12280, n_12281, n_12291, n_12295, + n_12301; + wire n_12303, n_12304, n_12330, n_12331, n_12332, n_12333, n_12334, + n_12335; + wire n_12336, n_12339, n_12340, n_12354, n_12355, n_12357, n_12358, + n_12359; + wire n_12361, n_12362, n_12363, n_12364, n_12365, n_12366, n_12367, + n_12368; + wire n_12369, n_12370, n_12371, n_12372, n_12373, n_12374, n_12375, + n_12376; + wire n_12377, n_12378, n_12379, n_12383, n_12384, n_12385, n_12389, + n_12399; + wire n_12400, n_12401, n_12403, n_12404, n_12405, n_12410, n_12411, + n_12453; + wire n_12454, n_12457, n_12458, n_12459, n_12460, n_12464, n_12478, + n_12479; + wire n_12480, n_12481, n_12482, n_12483, n_12495, n_12496, n_12499, + n_12500; + wire n_12501, n_12502, n_12503, n_12504, n_12505, n_12506, n_12507, + n_12508; + wire n_12509, n_12513, n_12514, n_12516, n_12517, n_12520, n_12521, + n_12526; + wire n_12527, n_12528, n_12529, n_12530, n_12531, n_12532, n_12533, + n_12534; + wire n_12535, n_12536, n_12537, n_12538, n_12539, n_12543, n_12581, + n_12583; + wire n_12584, n_12585, n_12588, n_12589, n_12590, n_12591, n_12592, + n_12601; + wire n_12602, n_12603, n_12604, n_12605, n_12606, n_12607, n_12608, + n_12609; + wire n_12610, n_12611, n_12612, n_12613, n_12614, n_12617, n_12618, + n_12619; + wire n_12620, n_12621, n_12622, n_12623, n_12624, n_12625, n_12626, + n_12627; + wire n_12630, n_12631, n_12632, n_12634, n_12635, n_12636, n_12637, + n_12638; + wire n_12639, n_12640, n_12641, n_12645, n_12650, n_12654, n_12656, + n_12659; + wire n_12662, n_12663, n_12664, n_12666, n_12667, n_12668, n_12672, + n_12674; + wire n_12675, n_12676, n_12677, n_12678, n_12679, n_12680, n_12681, + n_12682; + wire n_12683, n_12684, n_12685, n_12686, n_12687, n_12688, n_12689, + n_12690; + wire n_12721, n_12735, n_12738, n_12739, n_12740, n_12741, n_12742, + n_12743; + wire n_12744, n_12745, n_12746, n_12747, n_12748, n_12749, n_12750, + n_12751; + wire n_12752, n_12753, n_12754, n_12755, n_12793, n_12794, n_12796, + n_12798; + wire n_12799, n_12800, n_12801, n_12802, n_12803, n_12804, n_12805, + n_12806; + wire n_12807, n_12808, n_12809, n_12810, n_12811, n_12812, n_12813, + n_12814; + wire n_12815, n_12816, n_12817, n_12818, n_12819, n_12820, n_12821, + n_12822; + wire n_12823, n_12825, n_12826, n_12827, n_12828, n_12829, n_12830, + n_12831; + wire n_12832, n_12833, n_12834, n_12835, n_12836, n_12837, n_12838, + n_12839; + wire n_12840, n_12841, n_12842, n_12843, n_12844, n_12845, n_12846, + n_12847; + wire n_12848, n_12849, n_12850, n_12851, n_12852, n_12853, n_12854, + n_12855; + wire n_12856, n_12857, n_12858, o3_empty, o3_status, o3_status_962, + o3_we, o4_empty; + wire o4_status, o4_status_972, o4_we, o6_empty, o6_status, + o6_status_982, o6_we, o7_empty; + wire o7_status, o7_status_992, o7_we, o8_empty, o8_status, + o8_status_1002, o8_we, o9_empty; + wire o9_status, o9_status_1012, o9_we, oc0_cfg, oc0_cfg_964, + oc0_cfg_965, oc0_cfg_966, oc0_cfg_969; + wire oc0_cfg_970, oc0_int_set, oc0_int_set_707, oc0_int_set_708, + oc1_cfg, oc1_cfg_974, oc1_cfg_975, oc1_cfg_976; + wire oc1_cfg_979, oc1_cfg_980, oc1_int_set, oc1_int_set_709, + oc1_int_set_710, oc2_cfg, oc2_cfg_984, oc2_cfg_985; + wire oc2_cfg_986, oc2_cfg_987, oc2_cfg_989, oc2_cfg_990, oc2_int_set, + oc2_int_set_711, oc2_int_set_712, oc3_cfg; + wire oc3_cfg_994, oc3_cfg_995, oc3_cfg_996, oc3_cfg_997, oc3_cfg_999, + oc3_cfg_1000, oc3_int_set, oc3_int_set_713; + wire oc3_int_set_714, oc4_cfg, oc4_cfg_1004, oc4_cfg_1005, + oc4_cfg_1006, oc4_cfg_1009, oc4_cfg_1010, oc4_int_set; + wire oc4_int_set_715, oc4_int_set_716, oc5_cfg, oc5_cfg_1014, + oc5_cfg_1015, oc5_cfg_1016, oc5_cfg_1019, oc5_cfg_1020; + wire oc5_int_set, oc5_int_set_717, oc5_int_set_718, out_le, + out_le_180, out_le_181, out_le_182, out_le_183; + wire out_le_184, out_slt3, out_slt4, out_slt6, out_slt7, out_slt8, + out_slt9, out_slt_17; + wire out_slt_18, out_slt_19, out_slt_20, out_slt_22, out_slt_23, + out_slt_24, out_slt_25, out_slt_65; + wire out_slt_66, out_slt_67, out_slt_68, out_slt_69, out_slt_70, + out_slt_71, out_slt_72, out_slt_73; + wire out_slt_74, out_slt_75, out_slt_76, out_slt_77, out_slt_78, + out_slt_79, out_slt_80, out_slt_81; + wire out_slt_82, out_slt_83, out_slt_84, out_slt_85, out_slt_86, + out_slt_87, out_slt_88, out_slt_89; + wire out_slt_90, out_slt_91, out_slt_92, out_slt_93, out_slt_94, + out_slt_95, out_slt_96, out_slt_97; + wire out_slt_98, out_slt_99, out_slt_100, out_slt_101, out_slt_102, + out_slt_103, out_slt_104, out_slt_105; + wire out_slt_106, out_slt_107, out_slt_108, out_slt_109, out_slt_110, + out_slt_111, out_slt_112, out_slt_113; + wire out_slt_114, out_slt_115, out_slt_116, out_slt_117, out_slt_118, + out_slt_119, out_slt_120, out_slt_121; + wire out_slt_122, out_slt_123, out_slt_124, out_slt_125, out_slt_126, + out_slt_127, out_slt_128, out_slt_129; + wire out_slt_130, out_slt_131, out_slt_132, out_slt_133, out_slt_134, + out_slt_135, out_slt_136, out_slt_137; + wire out_slt_138, out_slt_139, out_slt_140, out_slt_141, out_slt_142, + out_slt_143, out_slt_144, out_slt_145; + wire out_slt_146, out_slt_147, out_slt_148, out_slt_149, out_slt_150, + out_slt_151, out_slt_152, out_slt_153; + wire out_slt_154, out_slt_155, out_slt_156, out_slt_157, out_slt_158, + out_slt_159, out_slt_160, out_slt_161; + wire out_slt_162, out_slt_163, out_slt_164, out_slt_165, out_slt_166, + out_slt_167, out_slt_168, out_slt_169; + wire out_slt_170, out_slt_171, out_slt_172, out_slt_173, out_slt_174, + out_slt_175, out_slt_176, out_slt_177; + wire out_slt_178, resume_req, rf_we, u0_slt0_r, u0_slt0_r_1, + u0_slt0_r_2, u0_slt0_r_3, u0_slt0_r_4; + wire u0_slt0_r_5, u0_slt0_r_6, u0_slt0_r_7, u0_slt0_r_8, u0_slt0_r_9, + u0_slt0_r_10, u0_slt0_r_11, u0_slt0_r_12; + wire u0_slt0_r_13, u0_slt0_r_14, u0_slt1_r, u0_slt1_r_16, + u0_slt1_r_17, u0_slt1_r_18, u0_slt1_r_19, u0_slt1_r_20; + wire u0_slt1_r_21, u0_slt1_r_22, u0_slt1_r_23, u0_slt1_r_24, + u0_slt1_r_25, u0_slt1_r_26, u0_slt1_r_27, u0_slt1_r_28; + wire u0_slt1_r_29, u0_slt1_r_30, u0_slt1_r_31, u0_slt1_r_32, + u0_slt1_r_33, u0_slt1_r_34, u0_slt2_r, u0_slt2_r_35; + wire u0_slt2_r_36, u0_slt2_r_37, u0_slt2_r_38, u0_slt2_r_39, + u0_slt2_r_40, u0_slt2_r_41, u0_slt2_r_42, u0_slt2_r_43; + wire u0_slt2_r_44, u0_slt2_r_45, u0_slt2_r_46, u0_slt2_r_47, + u0_slt2_r_48, u0_slt2_r_49, u0_slt2_r_50, u0_slt2_r_51; + wire u0_slt2_r_52, u0_slt2_r_53, u0_slt3_r, u0_slt3_r_54, + u0_slt3_r_55, u0_slt3_r_56, u0_slt3_r_57, u0_slt3_r_58; + wire u0_slt3_r_59, u0_slt3_r_60, u0_slt3_r_61, u0_slt3_r_62, + u0_slt3_r_63, u0_slt3_r_64, u0_slt3_r_65, u0_slt3_r_66; + wire u0_slt3_r_67, u0_slt3_r_68, u0_slt3_r_69, u0_slt3_r_70, + u0_slt3_r_71, u0_slt3_r_72, u0_slt4_r, u0_slt4_r_73; + wire u0_slt4_r_74, u0_slt4_r_75, u0_slt4_r_76, u0_slt4_r_77, + u0_slt4_r_78, u0_slt4_r_79, u0_slt4_r_80, u0_slt4_r_81; + wire u0_slt4_r_82, u0_slt4_r_83, u0_slt4_r_84, u0_slt4_r_85, + u0_slt4_r_86, u0_slt4_r_87, u0_slt4_r_88, u0_slt4_r_89; + wire u0_slt4_r_90, u0_slt4_r_91, u0_slt5_r, u0_slt5_r_92, + u0_slt5_r_93, u0_slt5_r_94, u0_slt5_r_95, u0_slt5_r_96; + wire u0_slt5_r_97, u0_slt5_r_98, u0_slt5_r_99, u0_slt5_r_100, + u0_slt5_r_101, u0_slt5_r_102, u0_slt5_r_103, u0_slt5_r_104; + wire u0_slt5_r_105, u0_slt5_r_106, u0_slt5_r_107, u0_slt5_r_108, + u0_slt5_r_109, u0_slt5_r_110, u0_slt6_r, u0_slt6_r_111; + wire u0_slt6_r_112, u0_slt6_r_113, u0_slt6_r_114, u0_slt6_r_115, + u0_slt6_r_116, u0_slt6_r_117, u0_slt6_r_118, u0_slt6_r_119; + wire u0_slt6_r_120, u0_slt6_r_121, u0_slt6_r_122, u0_slt6_r_123, + u0_slt6_r_124, u0_slt6_r_125, u0_slt6_r_126, u0_slt6_r_127; + wire u0_slt6_r_128, u0_slt6_r_129, u0_slt7_r, u0_slt7_r_130, + u0_slt7_r_131, u0_slt7_r_132, u0_slt7_r_133, u0_slt7_r_134; + wire u0_slt7_r_135, u0_slt7_r_136, u0_slt7_r_137, u0_slt7_r_138, + u0_slt7_r_139, u0_slt7_r_140, u0_slt7_r_141, u0_slt7_r_142; + wire u0_slt7_r_143, u0_slt7_r_144, u0_slt7_r_145, u0_slt7_r_146, + u0_slt7_r_147, u0_slt7_r_148, u0_slt8_r, u0_slt8_r_149; + wire u0_slt8_r_150, u0_slt8_r_151, u0_slt8_r_152, u0_slt8_r_153, + u0_slt8_r_154, u0_slt8_r_155, u0_slt8_r_156, u0_slt8_r_157; + wire u0_slt8_r_158, u0_slt8_r_159, u0_slt8_r_160, u0_slt8_r_161, + u0_slt8_r_162, u0_slt8_r_163, u0_slt8_r_164, u0_slt8_r_165; + wire u0_slt8_r_166, u0_slt8_r_167, u0_slt9_r, u0_slt9_r_168, + u0_slt9_r_169, u0_slt9_r_170, u0_slt9_r_171, u0_slt9_r_172; + wire u0_slt9_r_173, u0_slt9_r_174, u0_slt9_r_175, u0_slt9_r_176, + u0_slt9_r_177, u0_slt9_r_178, u0_slt9_r_179, u0_slt9_r_180; + wire u0_slt9_r_181, u0_slt9_r_182, u0_slt9_r_183, u0_slt9_r_184, + u0_slt9_r_185, u0_slt9_r_186, u1_sdata_in_r, u1_sr; + wire u1_sr_117, u1_sr_118, u1_sr_119, u1_sr_120, u1_sr_121, + u1_sr_122, u1_sr_123, u1_sr_124; + wire u1_sr_125, u1_sr_126, u1_sr_127, u1_sr_128, u1_sr_129, + u1_sr_130, u1_sr_131, u1_sr_132; + wire u1_sr_133, u1_sr_134, u1_sr_135, u2_bit_clk_e, u2_bit_clk_r, + u2_bit_clk_r1, \u2_cnt[2] , \u2_cnt[3] ; + wire \u2_cnt[4] , \u2_cnt[5] , \u2_cnt[6] , \u2_res_cnt[0] , + \u2_res_cnt[1] , \u2_res_cnt[2] , \u2_res_cnt[3] , u2_sync_beat; + wire u2_sync_resume, \u2_to_cnt[0] , \u2_to_cnt[1] , \u2_to_cnt[3] , + \u2_to_cnt[5] , \u3_mem[0] , \u3_mem[0]_91 , \u3_mem[0]_92 ; + wire \u3_mem[0]_93 , \u3_mem[0]_94 , \u3_mem[0]_95 , \u3_mem[0]_96 , + \u3_mem[0]_97 , \u3_mem[0]_98 , \u3_mem[0]_99 , \u3_mem[0]_100 ; + wire \u3_mem[0]_101 , \u3_mem[0]_102 , \u3_mem[0]_103 , + \u3_mem[0]_104 , \u3_mem[0]_105 , \u3_mem[0]_106 , + \u3_mem[0]_107 , \u3_mem[0]_108 ; + wire \u3_mem[0]_109 , \u3_mem[0]_110 , \u3_mem[0]_111 , + \u3_mem[0]_112 , \u3_mem[0]_113 , \u3_mem[0]_114 , + \u3_mem[0]_115 , \u3_mem[0]_116 ; + wire \u3_mem[0]_117 , \u3_mem[0]_118 , \u3_mem[0]_119 , + \u3_mem[0]_120 , \u3_mem[0]_121 , \u3_mem[1] , \u3_mem[1]_60 , + \u3_mem[1]_61 ; + wire \u3_mem[1]_62 , \u3_mem[1]_63 , \u3_mem[1]_64 , \u3_mem[1]_65 , + \u3_mem[1]_66 , \u3_mem[1]_67 , \u3_mem[1]_68 , \u3_mem[1]_69 ; + wire \u3_mem[1]_70 , \u3_mem[1]_71 , \u3_mem[1]_72 , \u3_mem[1]_73 , + \u3_mem[1]_74 , \u3_mem[1]_75 , \u3_mem[1]_76 , \u3_mem[1]_77 ; + wire \u3_mem[1]_78 , \u3_mem[1]_79 , \u3_mem[1]_80 , \u3_mem[1]_81 , + \u3_mem[1]_82 , \u3_mem[1]_83 , \u3_mem[1]_84 , \u3_mem[1]_85 ; + wire \u3_mem[1]_86 , \u3_mem[1]_87 , \u3_mem[1]_88 , \u3_mem[1]_89 , + \u3_mem[1]_90 , \u3_mem[2] , \u3_mem[2]_29 , \u3_mem[2]_30 ; + wire \u3_mem[2]_31 , \u3_mem[2]_32 , \u3_mem[2]_33 , \u3_mem[2]_34 , + \u3_mem[2]_35 , \u3_mem[2]_36 , \u3_mem[2]_37 , \u3_mem[2]_38 ; + wire \u3_mem[2]_39 , \u3_mem[2]_40 , \u3_mem[2]_41 , \u3_mem[2]_42 , + \u3_mem[2]_43 , \u3_mem[2]_44 , \u3_mem[2]_45 , \u3_mem[2]_46 ; + wire \u3_mem[2]_47 , \u3_mem[2]_48 , \u3_mem[2]_49 , \u3_mem[2]_50 , + \u3_mem[2]_51 , \u3_mem[2]_52 , \u3_mem[2]_53 , \u3_mem[2]_54 ; + wire \u3_mem[2]_55 , \u3_mem[2]_56 , \u3_mem[2]_57 , \u3_mem[2]_58 , + \u3_mem[2]_59 , \u3_mem[3] , \u3_mem[3]_122 , \u3_mem[3]_123 ; + wire \u3_mem[3]_124 , \u3_mem[3]_125 , \u3_mem[3]_126 , + \u3_mem[3]_127 , \u3_mem[3]_128 , \u3_mem[3]_129 , + \u3_mem[3]_130 , \u3_mem[3]_131 ; + wire \u3_mem[3]_132 , \u3_mem[3]_133 , \u3_mem[3]_134 , + \u3_mem[3]_135 , \u3_mem[3]_136 , \u3_mem[3]_137 , + \u3_mem[3]_138 , \u3_mem[3]_139 ; + wire \u3_mem[3]_140 , \u3_mem[3]_141 , \u3_mem[3]_142 , + \u3_mem[3]_143 , \u3_mem[3]_144 , \u3_mem[3]_145 , + \u3_mem[3]_146 , \u3_mem[3]_147 ; + wire \u3_mem[3]_148 , \u3_mem[3]_149 , \u3_mem[3]_150 , + \u3_mem[3]_151 , \u3_mem[3]_152 , \u3_rp[0] , \u3_rp[1] , + \u3_rp[2] ; + wire \u3_rp[3] , \u3_wp[0] , \u3_wp[1] , \u3_wp[2] , \u4_mem[0] , + \u4_mem[0]_91 , \u4_mem[0]_92 , \u4_mem[0]_93 ; + wire \u4_mem[0]_94 , \u4_mem[0]_95 , \u4_mem[0]_96 , \u4_mem[0]_97 , + \u4_mem[0]_98 , \u4_mem[0]_99 , \u4_mem[0]_100 , \u4_mem[0]_101 ; + wire \u4_mem[0]_102 , \u4_mem[0]_103 , \u4_mem[0]_104 , + \u4_mem[0]_105 , \u4_mem[0]_106 , \u4_mem[0]_107 , + \u4_mem[0]_108 , \u4_mem[0]_109 ; + wire \u4_mem[0]_110 , \u4_mem[0]_111 , \u4_mem[0]_112 , + \u4_mem[0]_113 , \u4_mem[0]_114 , \u4_mem[0]_115 , + \u4_mem[0]_116 , \u4_mem[0]_117 ; + wire \u4_mem[0]_118 , \u4_mem[0]_119 , \u4_mem[0]_120 , + \u4_mem[0]_121 , \u4_mem[1] , \u4_mem[1]_60 , \u4_mem[1]_61 , + \u4_mem[1]_62 ; + wire \u4_mem[1]_63 , \u4_mem[1]_64 , \u4_mem[1]_65 , \u4_mem[1]_66 , + \u4_mem[1]_67 , \u4_mem[1]_68 , \u4_mem[1]_69 , \u4_mem[1]_70 ; + wire \u4_mem[1]_71 , \u4_mem[1]_72 , \u4_mem[1]_73 , \u4_mem[1]_74 , + \u4_mem[1]_75 , \u4_mem[1]_76 , \u4_mem[1]_77 , \u4_mem[1]_78 ; + wire \u4_mem[1]_79 , \u4_mem[1]_80 , \u4_mem[1]_81 , \u4_mem[1]_82 , + \u4_mem[1]_83 , \u4_mem[1]_84 , \u4_mem[1]_85 , \u4_mem[1]_86 ; + wire \u4_mem[1]_87 , \u4_mem[1]_88 , \u4_mem[1]_89 , \u4_mem[1]_90 , + \u4_mem[2] , \u4_mem[2]_29 , \u4_mem[2]_30 , \u4_mem[2]_31 ; + wire \u4_mem[2]_32 , \u4_mem[2]_33 , \u4_mem[2]_34 , \u4_mem[2]_35 , + \u4_mem[2]_36 , \u4_mem[2]_37 , \u4_mem[2]_38 , \u4_mem[2]_39 ; + wire \u4_mem[2]_40 , \u4_mem[2]_41 , \u4_mem[2]_42 , \u4_mem[2]_43 , + \u4_mem[2]_44 , \u4_mem[2]_45 , \u4_mem[2]_46 , \u4_mem[2]_47 ; + wire \u4_mem[2]_48 , \u4_mem[2]_49 , \u4_mem[2]_50 , \u4_mem[2]_51 , + \u4_mem[2]_52 , \u4_mem[2]_53 , \u4_mem[2]_54 , \u4_mem[2]_55 ; + wire \u4_mem[2]_56 , \u4_mem[2]_57 , \u4_mem[2]_58 , \u4_mem[2]_59 , + \u4_mem[3] , \u4_mem[3]_122 , \u4_mem[3]_123 , \u4_mem[3]_124 ; + wire \u4_mem[3]_125 , \u4_mem[3]_126 , \u4_mem[3]_127 , + \u4_mem[3]_128 , \u4_mem[3]_129 , \u4_mem[3]_130 , + \u4_mem[3]_131 , \u4_mem[3]_132 ; + wire \u4_mem[3]_133 , \u4_mem[3]_134 , \u4_mem[3]_135 , + \u4_mem[3]_136 , \u4_mem[3]_137 , \u4_mem[3]_138 , + \u4_mem[3]_139 , \u4_mem[3]_140 ; + wire \u4_mem[3]_141 , \u4_mem[3]_142 , \u4_mem[3]_143 , + \u4_mem[3]_144 , \u4_mem[3]_145 , \u4_mem[3]_146 , + \u4_mem[3]_147 , \u4_mem[3]_148 ; + wire \u4_mem[3]_149 , \u4_mem[3]_150 , \u4_mem[3]_151 , + \u4_mem[3]_152 , \u4_rp[0] , \u4_rp[1] , \u4_rp[2] , \u4_rp[3] ; + wire \u4_wp[0] , \u4_wp[1] , \u4_wp[2] , \u5_mem[0] , \u5_mem[0]_91 , + \u5_mem[0]_92 , \u5_mem[0]_93 , \u5_mem[0]_94 ; + wire \u5_mem[0]_95 , \u5_mem[0]_96 , \u5_mem[0]_97 , \u5_mem[0]_98 , + \u5_mem[0]_99 , \u5_mem[0]_100 , \u5_mem[0]_101 , \u5_mem[0]_102 + ; + wire \u5_mem[0]_103 , \u5_mem[0]_104 , \u5_mem[0]_105 , + \u5_mem[0]_106 , \u5_mem[0]_107 , \u5_mem[0]_108 , + \u5_mem[0]_109 , \u5_mem[0]_110 ; + wire \u5_mem[0]_111 , \u5_mem[0]_112 , \u5_mem[0]_113 , + \u5_mem[0]_114 , \u5_mem[0]_115 , \u5_mem[0]_116 , + \u5_mem[0]_117 , \u5_mem[0]_118 ; + wire \u5_mem[0]_119 , \u5_mem[0]_120 , \u5_mem[0]_121 , \u5_mem[1] , + \u5_mem[1]_60 , \u5_mem[1]_61 , \u5_mem[1]_62 , \u5_mem[1]_63 ; + wire \u5_mem[1]_64 , \u5_mem[1]_65 , \u5_mem[1]_66 , \u5_mem[1]_67 , + \u5_mem[1]_68 , \u5_mem[1]_69 , \u5_mem[1]_70 , \u5_mem[1]_71 ; + wire \u5_mem[1]_72 , \u5_mem[1]_73 , \u5_mem[1]_74 , \u5_mem[1]_75 , + \u5_mem[1]_76 , \u5_mem[1]_77 , \u5_mem[1]_78 , \u5_mem[1]_79 ; + wire \u5_mem[1]_80 , \u5_mem[1]_81 , \u5_mem[1]_82 , \u5_mem[1]_83 , + \u5_mem[1]_84 , \u5_mem[1]_85 , \u5_mem[1]_86 , \u5_mem[1]_87 ; + wire \u5_mem[1]_88 , \u5_mem[1]_89 , \u5_mem[1]_90 , \u5_mem[2] , + \u5_mem[2]_29 , \u5_mem[2]_30 , \u5_mem[2]_31 , \u5_mem[2]_32 ; + wire \u5_mem[2]_33 , \u5_mem[2]_34 , \u5_mem[2]_35 , \u5_mem[2]_36 , + \u5_mem[2]_37 , \u5_mem[2]_38 , \u5_mem[2]_39 , \u5_mem[2]_40 ; + wire \u5_mem[2]_41 , \u5_mem[2]_42 , \u5_mem[2]_43 , \u5_mem[2]_44 , + \u5_mem[2]_45 , \u5_mem[2]_46 , \u5_mem[2]_47 , \u5_mem[2]_48 ; + wire \u5_mem[2]_49 , \u5_mem[2]_50 , \u5_mem[2]_51 , \u5_mem[2]_52 , + \u5_mem[2]_53 , \u5_mem[2]_54 , \u5_mem[2]_55 , \u5_mem[2]_56 ; + wire \u5_mem[2]_57 , \u5_mem[2]_58 , \u5_mem[2]_59 , \u5_mem[3] , + \u5_mem[3]_122 , \u5_mem[3]_123 , \u5_mem[3]_124 , + \u5_mem[3]_125 ; + wire \u5_mem[3]_126 , \u5_mem[3]_127 , \u5_mem[3]_128 , + \u5_mem[3]_129 , \u5_mem[3]_130 , \u5_mem[3]_131 , + \u5_mem[3]_132 , \u5_mem[3]_133 ; + wire \u5_mem[3]_134 , \u5_mem[3]_135 , \u5_mem[3]_136 , + \u5_mem[3]_137 , \u5_mem[3]_138 , \u5_mem[3]_139 , + \u5_mem[3]_140 , \u5_mem[3]_141 ; + wire \u5_mem[3]_142 , \u5_mem[3]_143 , \u5_mem[3]_144 , + \u5_mem[3]_145 , \u5_mem[3]_146 , \u5_mem[3]_147 , + \u5_mem[3]_148 , \u5_mem[3]_149 ; + wire \u5_mem[3]_150 , \u5_mem[3]_151 , \u5_mem[3]_152 , \u5_rp[1] , + \u5_rp[2] , \u5_rp[3] , \u5_wp[0] , \u5_wp[1] ; + wire \u5_wp[2] , \u6_mem[0] , \u6_mem[0]_91 , \u6_mem[0]_92 , + \u6_mem[0]_93 , \u6_mem[0]_94 , \u6_mem[0]_95 , \u6_mem[0]_96 ; + wire \u6_mem[0]_97 , \u6_mem[0]_98 , \u6_mem[0]_99 , \u6_mem[0]_100 , + \u6_mem[0]_101 , \u6_mem[0]_102 , \u6_mem[0]_103 , + \u6_mem[0]_104 ; + wire \u6_mem[0]_105 , \u6_mem[0]_106 , \u6_mem[0]_107 , + \u6_mem[0]_108 , \u6_mem[0]_109 , \u6_mem[0]_110 , + \u6_mem[0]_111 , \u6_mem[0]_112 ; + wire \u6_mem[0]_113 , \u6_mem[0]_114 , \u6_mem[0]_115 , + \u6_mem[0]_116 , \u6_mem[0]_117 , \u6_mem[0]_118 , + \u6_mem[0]_119 , \u6_mem[0]_120 ; + wire \u6_mem[0]_121 , \u6_mem[1] , \u6_mem[1]_60 , \u6_mem[1]_61 , + \u6_mem[1]_62 , \u6_mem[1]_63 , \u6_mem[1]_64 , \u6_mem[1]_65 ; + wire \u6_mem[1]_66 , \u6_mem[1]_67 , \u6_mem[1]_68 , \u6_mem[1]_69 , + \u6_mem[1]_70 , \u6_mem[1]_71 , \u6_mem[1]_72 , \u6_mem[1]_73 ; + wire \u6_mem[1]_74 , \u6_mem[1]_75 , \u6_mem[1]_76 , \u6_mem[1]_77 , + \u6_mem[1]_78 , \u6_mem[1]_79 , \u6_mem[1]_80 , \u6_mem[1]_81 ; + wire \u6_mem[1]_82 , \u6_mem[1]_83 , \u6_mem[1]_84 , \u6_mem[1]_85 , + \u6_mem[1]_86 , \u6_mem[1]_87 , \u6_mem[1]_88 , \u6_mem[1]_89 ; + wire \u6_mem[1]_90 , \u6_mem[2] , \u6_mem[2]_29 , \u6_mem[2]_30 , + \u6_mem[2]_31 , \u6_mem[2]_32 , \u6_mem[2]_33 , \u6_mem[2]_34 ; + wire \u6_mem[2]_35 , \u6_mem[2]_36 , \u6_mem[2]_37 , \u6_mem[2]_38 , + \u6_mem[2]_39 , \u6_mem[2]_40 , \u6_mem[2]_41 , \u6_mem[2]_42 ; + wire \u6_mem[2]_43 , \u6_mem[2]_44 , \u6_mem[2]_45 , \u6_mem[2]_46 , + \u6_mem[2]_47 , \u6_mem[2]_48 , \u6_mem[2]_49 , \u6_mem[2]_50 ; + wire \u6_mem[2]_51 , \u6_mem[2]_52 , \u6_mem[2]_53 , \u6_mem[2]_54 , + \u6_mem[2]_55 , \u6_mem[2]_56 , \u6_mem[2]_57 , \u6_mem[2]_58 ; + wire \u6_mem[2]_59 , \u6_mem[3] , \u6_mem[3]_122 , \u6_mem[3]_123 , + \u6_mem[3]_124 , \u6_mem[3]_125 , \u6_mem[3]_126 , + \u6_mem[3]_127 ; + wire \u6_mem[3]_128 , \u6_mem[3]_129 , \u6_mem[3]_130 , + \u6_mem[3]_131 , \u6_mem[3]_132 , \u6_mem[3]_133 , + \u6_mem[3]_134 , \u6_mem[3]_135 ; + wire \u6_mem[3]_136 , \u6_mem[3]_137 , \u6_mem[3]_138 , + \u6_mem[3]_139 , \u6_mem[3]_140 , \u6_mem[3]_141 , + \u6_mem[3]_142 , \u6_mem[3]_143 ; + wire \u6_mem[3]_144 , \u6_mem[3]_145 , \u6_mem[3]_146 , + \u6_mem[3]_147 , \u6_mem[3]_148 , \u6_mem[3]_149 , + \u6_mem[3]_150 , \u6_mem[3]_151 ; + wire \u6_mem[3]_152 , \u6_rp[0] , \u6_rp[1] , \u6_rp[2] , \u6_rp[3] , + \u6_wp[0] , \u6_wp[1] , \u6_wp[2] ; + wire \u7_mem[0] , \u7_mem[0]_91 , \u7_mem[0]_92 , \u7_mem[0]_93 , + \u7_mem[0]_94 , \u7_mem[0]_95 , \u7_mem[0]_96 , \u7_mem[0]_97 ; + wire \u7_mem[0]_98 , \u7_mem[0]_99 , \u7_mem[0]_100 , \u7_mem[0]_101 + , \u7_mem[0]_102 , \u7_mem[0]_103 , \u7_mem[0]_104 , + \u7_mem[0]_105 ; + wire \u7_mem[0]_106 , \u7_mem[0]_107 , \u7_mem[0]_108 , + \u7_mem[0]_109 , \u7_mem[0]_110 , \u7_mem[0]_111 , + \u7_mem[0]_112 , \u7_mem[0]_113 ; + wire \u7_mem[0]_114 , \u7_mem[0]_115 , \u7_mem[0]_116 , + \u7_mem[0]_117 , \u7_mem[0]_118 , \u7_mem[0]_119 , + \u7_mem[0]_120 , \u7_mem[0]_121 ; + wire \u7_mem[1] , \u7_mem[1]_60 , \u7_mem[1]_61 , \u7_mem[1]_62 , + \u7_mem[1]_63 , \u7_mem[1]_64 , \u7_mem[1]_65 , \u7_mem[1]_66 ; + wire \u7_mem[1]_67 , \u7_mem[1]_68 , \u7_mem[1]_69 , \u7_mem[1]_70 , + \u7_mem[1]_71 , \u7_mem[1]_72 , \u7_mem[1]_73 , \u7_mem[1]_74 ; + wire \u7_mem[1]_75 , \u7_mem[1]_76 , \u7_mem[1]_77 , \u7_mem[1]_78 , + \u7_mem[1]_79 , \u7_mem[1]_80 , \u7_mem[1]_81 , \u7_mem[1]_82 ; + wire \u7_mem[1]_83 , \u7_mem[1]_84 , \u7_mem[1]_85 , \u7_mem[1]_86 , + \u7_mem[1]_87 , \u7_mem[1]_88 , \u7_mem[1]_89 , \u7_mem[1]_90 ; + wire \u7_mem[2] , \u7_mem[2]_29 , \u7_mem[2]_30 , \u7_mem[2]_31 , + \u7_mem[2]_32 , \u7_mem[2]_33 , \u7_mem[2]_34 , \u7_mem[2]_35 ; + wire \u7_mem[2]_36 , \u7_mem[2]_37 , \u7_mem[2]_38 , \u7_mem[2]_39 , + \u7_mem[2]_40 , \u7_mem[2]_41 , \u7_mem[2]_42 , \u7_mem[2]_43 ; + wire \u7_mem[2]_44 , \u7_mem[2]_45 , \u7_mem[2]_46 , \u7_mem[2]_47 , + \u7_mem[2]_48 , \u7_mem[2]_49 , \u7_mem[2]_50 , \u7_mem[2]_51 ; + wire \u7_mem[2]_52 , \u7_mem[2]_53 , \u7_mem[2]_54 , \u7_mem[2]_55 , + \u7_mem[2]_56 , \u7_mem[2]_57 , \u7_mem[2]_58 , \u7_mem[2]_59 ; + wire \u7_mem[3] , \u7_mem[3]_122 , \u7_mem[3]_123 , \u7_mem[3]_124 , + \u7_mem[3]_125 , \u7_mem[3]_126 , \u7_mem[3]_127 , + \u7_mem[3]_128 ; + wire \u7_mem[3]_129 , \u7_mem[3]_130 , \u7_mem[3]_131 , + \u7_mem[3]_132 , \u7_mem[3]_133 , \u7_mem[3]_134 , + \u7_mem[3]_135 , \u7_mem[3]_136 ; + wire \u7_mem[3]_137 , \u7_mem[3]_138 , \u7_mem[3]_139 , + \u7_mem[3]_140 , \u7_mem[3]_141 , \u7_mem[3]_142 , + \u7_mem[3]_143 , \u7_mem[3]_144 ; + wire \u7_mem[3]_145 , \u7_mem[3]_146 , \u7_mem[3]_147 , + \u7_mem[3]_148 , \u7_mem[3]_149 , \u7_mem[3]_150 , + \u7_mem[3]_151 , \u7_mem[3]_152 ; + wire \u7_rp[0] , \u7_rp[1] , \u7_rp[2] , \u7_rp[3] , \u7_wp[0] , + \u7_wp[1] , \u7_wp[2] , \u8_mem[0] ; + wire \u8_mem[0]_91 , \u8_mem[0]_92 , \u8_mem[0]_93 , \u8_mem[0]_94 , + \u8_mem[0]_95 , \u8_mem[0]_96 , \u8_mem[0]_97 , \u8_mem[0]_98 ; + wire \u8_mem[0]_99 , \u8_mem[0]_100 , \u8_mem[0]_101 , \u8_mem[0]_102 + , \u8_mem[0]_103 , \u8_mem[0]_104 , \u8_mem[0]_105 , + \u8_mem[0]_106 ; + wire \u8_mem[0]_107 , \u8_mem[0]_108 , \u8_mem[0]_109 , + \u8_mem[0]_110 , \u8_mem[0]_111 , \u8_mem[0]_112 , + \u8_mem[0]_113 , \u8_mem[0]_114 ; + wire \u8_mem[0]_115 , \u8_mem[0]_116 , \u8_mem[0]_117 , + \u8_mem[0]_118 , \u8_mem[0]_119 , \u8_mem[0]_120 , + \u8_mem[0]_121 , \u8_mem[1] ; + wire \u8_mem[1]_60 , \u8_mem[1]_61 , \u8_mem[1]_62 , \u8_mem[1]_63 , + \u8_mem[1]_64 , \u8_mem[1]_65 , \u8_mem[1]_66 , \u8_mem[1]_67 ; + wire \u8_mem[1]_68 , \u8_mem[1]_69 , \u8_mem[1]_70 , \u8_mem[1]_71 , + \u8_mem[1]_72 , \u8_mem[1]_73 , \u8_mem[1]_74 , \u8_mem[1]_75 ; + wire \u8_mem[1]_76 , \u8_mem[1]_77 , \u8_mem[1]_78 , \u8_mem[1]_79 , + \u8_mem[1]_80 , \u8_mem[1]_81 , \u8_mem[1]_82 , \u8_mem[1]_83 ; + wire \u8_mem[1]_84 , \u8_mem[1]_85 , \u8_mem[1]_86 , \u8_mem[1]_87 , + \u8_mem[1]_88 , \u8_mem[1]_89 , \u8_mem[1]_90 , \u8_mem[2] ; + wire \u8_mem[2]_29 , \u8_mem[2]_30 , \u8_mem[2]_31 , \u8_mem[2]_32 , + \u8_mem[2]_33 , \u8_mem[2]_34 , \u8_mem[2]_35 , \u8_mem[2]_36 ; + wire \u8_mem[2]_37 , \u8_mem[2]_38 , \u8_mem[2]_39 , \u8_mem[2]_40 , + \u8_mem[2]_41 , \u8_mem[2]_42 , \u8_mem[2]_43 , \u8_mem[2]_44 ; + wire \u8_mem[2]_45 , \u8_mem[2]_46 , \u8_mem[2]_47 , \u8_mem[2]_48 , + \u8_mem[2]_49 , \u8_mem[2]_50 , \u8_mem[2]_51 , \u8_mem[2]_52 ; + wire \u8_mem[2]_53 , \u8_mem[2]_54 , \u8_mem[2]_55 , \u8_mem[2]_56 , + \u8_mem[2]_57 , \u8_mem[2]_58 , \u8_mem[2]_59 , \u8_mem[3] ; + wire \u8_mem[3]_122 , \u8_mem[3]_123 , \u8_mem[3]_124 , + \u8_mem[3]_125 , \u8_mem[3]_126 , \u8_mem[3]_127 , + \u8_mem[3]_128 , \u8_mem[3]_129 ; + wire \u8_mem[3]_130 , \u8_mem[3]_131 , \u8_mem[3]_132 , + \u8_mem[3]_133 , \u8_mem[3]_134 , \u8_mem[3]_135 , + \u8_mem[3]_136 , \u8_mem[3]_137 ; + wire \u8_mem[3]_138 , \u8_mem[3]_139 , \u8_mem[3]_140 , + \u8_mem[3]_141 , \u8_mem[3]_142 , \u8_mem[3]_143 , + \u8_mem[3]_144 , \u8_mem[3]_145 ; + wire \u8_mem[3]_146 , \u8_mem[3]_147 , \u8_mem[3]_148 , + \u8_mem[3]_149 , \u8_mem[3]_150 , \u8_mem[3]_151 , + \u8_mem[3]_152 , \u8_rp[1] ; + wire \u8_rp[2] , \u8_rp[3] , \u8_wp[0] , \u8_wp[1] , \u8_wp[2] , + u9_din_tmp1, u9_din_tmp_42, u9_din_tmp_43; + wire u9_din_tmp_44, u9_din_tmp_45, u9_din_tmp_46, u9_din_tmp_47, + u9_din_tmp_48, u9_din_tmp_49, u9_din_tmp_50, u9_din_tmp_51; + wire u9_din_tmp_52, u9_din_tmp_53, u9_din_tmp_54, u9_din_tmp_55, + u9_din_tmp_56, \u9_mem[0] , \u9_mem[0]_150 , \u9_mem[0]_151 ; + wire \u9_mem[0]_152 , \u9_mem[0]_153 , \u9_mem[0]_154 , + \u9_mem[0]_155 , \u9_mem[0]_156 , \u9_mem[0]_157 , + \u9_mem[0]_158 , \u9_mem[0]_159 ; + wire \u9_mem[0]_160 , \u9_mem[0]_161 , \u9_mem[0]_162 , + \u9_mem[0]_163 , \u9_mem[0]_164 , \u9_mem[0]_165 , + \u9_mem[0]_166 , \u9_mem[0]_167 ; + wire \u9_mem[0]_168 , \u9_mem[0]_169 , \u9_mem[0]_170 , + \u9_mem[0]_171 , \u9_mem[0]_172 , \u9_mem[0]_173 , + \u9_mem[0]_174 , \u9_mem[0]_175 ; + wire \u9_mem[0]_176 , \u9_mem[0]_177 , \u9_mem[0]_178 , + \u9_mem[0]_179 , \u9_mem[0]_180 , \u9_mem[1] , \u9_mem[1]_119 , + \u9_mem[1]_120 ; + wire \u9_mem[1]_121 , \u9_mem[1]_122 , \u9_mem[1]_123 , + \u9_mem[1]_124 , \u9_mem[1]_125 , \u9_mem[1]_126 , + \u9_mem[1]_127 , \u9_mem[1]_128 ; + wire \u9_mem[1]_129 , \u9_mem[1]_130 , \u9_mem[1]_131 , + \u9_mem[1]_132 , \u9_mem[1]_133 , \u9_mem[1]_134 , + \u9_mem[1]_135 , \u9_mem[1]_136 ; + wire \u9_mem[1]_137 , \u9_mem[1]_138 , \u9_mem[1]_139 , + \u9_mem[1]_140 , \u9_mem[1]_141 , \u9_mem[1]_142 , + \u9_mem[1]_143 , \u9_mem[1]_144 ; + wire \u9_mem[1]_145 , \u9_mem[1]_146 , \u9_mem[1]_147 , + \u9_mem[1]_148 , \u9_mem[1]_149 , \u9_mem[2] , \u9_mem[2]_88 , + \u9_mem[2]_89 ; + wire \u9_mem[2]_90 , \u9_mem[2]_91 , \u9_mem[2]_92 , \u9_mem[2]_93 , + \u9_mem[2]_94 , \u9_mem[2]_95 , \u9_mem[2]_96 , \u9_mem[2]_97 ; + wire \u9_mem[2]_98 , \u9_mem[2]_99 , \u9_mem[2]_100 , \u9_mem[2]_101 + , \u9_mem[2]_102 , \u9_mem[2]_103 , \u9_mem[2]_104 , + \u9_mem[2]_105 ; + wire \u9_mem[2]_106 , \u9_mem[2]_107 , \u9_mem[2]_108 , + \u9_mem[2]_109 , \u9_mem[2]_110 , \u9_mem[2]_111 , + \u9_mem[2]_112 , \u9_mem[2]_113 ; + wire \u9_mem[2]_114 , \u9_mem[2]_115 , \u9_mem[2]_116 , + \u9_mem[2]_117 , \u9_mem[2]_118 , \u9_mem[3] , \u9_mem[3]_57 , + \u9_mem[3]_58 ; + wire \u9_mem[3]_59 , \u9_mem[3]_60 , \u9_mem[3]_61 , \u9_mem[3]_62 , + \u9_mem[3]_63 , \u9_mem[3]_64 , \u9_mem[3]_65 , \u9_mem[3]_66 ; + wire \u9_mem[3]_67 , \u9_mem[3]_68 , \u9_mem[3]_69 , \u9_mem[3]_70 , + \u9_mem[3]_71 , \u9_mem[3]_72 , \u9_mem[3]_73 , \u9_mem[3]_74 ; + wire \u9_mem[3]_75 , \u9_mem[3]_76 , \u9_mem[3]_77 , \u9_mem[3]_78 , + \u9_mem[3]_79 , \u9_mem[3]_80 , \u9_mem[3]_81 , \u9_mem[3]_82 ; + wire \u9_mem[3]_83 , \u9_mem[3]_84 , \u9_mem[3]_85 , \u9_mem[3]_86 , + \u9_mem[3]_87 , \u9_rp[0] , \u9_rp[1] , \u9_rp[2] ; + wire \u9_wp[1] , \u9_wp[2] , \u9_wp[3] , u10_din_tmp1, + u10_din_tmp_42, u10_din_tmp_43, u10_din_tmp_44, u10_din_tmp_45; + wire u10_din_tmp_46, u10_din_tmp_47, u10_din_tmp_48, u10_din_tmp_49, + u10_din_tmp_50, u10_din_tmp_51, u10_din_tmp_52, u10_din_tmp_53; + wire u10_din_tmp_54, u10_din_tmp_55, u10_din_tmp_56, \u10_mem[0] , + \u10_mem[0]_150 , \u10_mem[0]_151 , \u10_mem[0]_152 , + \u10_mem[0]_153 ; + wire \u10_mem[0]_154 , \u10_mem[0]_155 , \u10_mem[0]_156 , + \u10_mem[0]_157 , \u10_mem[0]_158 , \u10_mem[0]_159 , + \u10_mem[0]_160 , \u10_mem[0]_161 ; + wire \u10_mem[0]_162 , \u10_mem[0]_163 , \u10_mem[0]_164 , + \u10_mem[0]_165 , \u10_mem[0]_166 , \u10_mem[0]_167 , + \u10_mem[0]_168 , \u10_mem[0]_169 ; + wire \u10_mem[0]_170 , \u10_mem[0]_171 , \u10_mem[0]_172 , + \u10_mem[0]_173 , \u10_mem[0]_174 , \u10_mem[0]_175 , + \u10_mem[0]_176 , \u10_mem[0]_177 ; + wire \u10_mem[0]_178 , \u10_mem[0]_179 , \u10_mem[0]_180 , + \u10_mem[1] , \u10_mem[1]_119 , \u10_mem[1]_120 , + \u10_mem[1]_121 , \u10_mem[1]_122 ; + wire \u10_mem[1]_123 , \u10_mem[1]_124 , \u10_mem[1]_125 , + \u10_mem[1]_126 , \u10_mem[1]_127 , \u10_mem[1]_128 , + \u10_mem[1]_129 , \u10_mem[1]_130 ; + wire \u10_mem[1]_131 , \u10_mem[1]_132 , \u10_mem[1]_133 , + \u10_mem[1]_134 , \u10_mem[1]_135 , \u10_mem[1]_136 , + \u10_mem[1]_137 , \u10_mem[1]_138 ; + wire \u10_mem[1]_139 , \u10_mem[1]_140 , \u10_mem[1]_141 , + \u10_mem[1]_142 , \u10_mem[1]_143 , \u10_mem[1]_144 , + \u10_mem[1]_145 , \u10_mem[1]_146 ; + wire \u10_mem[1]_147 , \u10_mem[1]_148 , \u10_mem[1]_149 , + \u10_mem[2] , \u10_mem[2]_88 , \u10_mem[2]_89 , \u10_mem[2]_90 , + \u10_mem[2]_91 ; + wire \u10_mem[2]_92 , \u10_mem[2]_93 , \u10_mem[2]_94 , + \u10_mem[2]_95 , \u10_mem[2]_96 , \u10_mem[2]_97 , + \u10_mem[2]_98 , \u10_mem[2]_99 ; + wire \u10_mem[2]_100 , \u10_mem[2]_101 , \u10_mem[2]_102 , + \u10_mem[2]_103 , \u10_mem[2]_104 , \u10_mem[2]_105 , + \u10_mem[2]_106 , \u10_mem[2]_107 ; + wire \u10_mem[2]_108 , \u10_mem[2]_109 , \u10_mem[2]_110 , + \u10_mem[2]_111 , \u10_mem[2]_112 , \u10_mem[2]_113 , + \u10_mem[2]_114 , \u10_mem[2]_115 ; + wire \u10_mem[2]_116 , \u10_mem[2]_117 , \u10_mem[2]_118 , + \u10_mem[3] , \u10_mem[3]_57 , \u10_mem[3]_58 , \u10_mem[3]_59 , + \u10_mem[3]_60 ; + wire \u10_mem[3]_61 , \u10_mem[3]_62 , \u10_mem[3]_63 , + \u10_mem[3]_64 , \u10_mem[3]_65 , \u10_mem[3]_66 , + \u10_mem[3]_67 , \u10_mem[3]_68 ; + wire \u10_mem[3]_69 , \u10_mem[3]_70 , \u10_mem[3]_71 , + \u10_mem[3]_72 , \u10_mem[3]_73 , \u10_mem[3]_74 , + \u10_mem[3]_75 , \u10_mem[3]_76 ; + wire \u10_mem[3]_77 , \u10_mem[3]_78 , \u10_mem[3]_79 , + \u10_mem[3]_80 , \u10_mem[3]_81 , \u10_mem[3]_82 , + \u10_mem[3]_83 , \u10_mem[3]_84 ; + wire \u10_mem[3]_85 , \u10_mem[3]_86 , \u10_mem[3]_87 , \u10_rp[0] , + \u10_rp[1] , \u10_rp[2] , \u10_wp[1] , \u10_wp[2] ; + wire \u10_wp[3] , u11_din_tmp1, u11_din_tmp_42, u11_din_tmp_43, + u11_din_tmp_44, u11_din_tmp_45, u11_din_tmp_46, u11_din_tmp_47; + wire u11_din_tmp_48, u11_din_tmp_49, u11_din_tmp_50, u11_din_tmp_51, + u11_din_tmp_52, u11_din_tmp_53, u11_din_tmp_54, u11_din_tmp_55; + wire u11_din_tmp_56, \u11_mem[0] , \u11_mem[0]_150 , \u11_mem[0]_151 + , \u11_mem[0]_152 , \u11_mem[0]_153 , \u11_mem[0]_154 , + \u11_mem[0]_155 ; + wire \u11_mem[0]_156 , \u11_mem[0]_157 , \u11_mem[0]_158 , + \u11_mem[0]_159 , \u11_mem[0]_160 , \u11_mem[0]_161 , + \u11_mem[0]_162 , \u11_mem[0]_163 ; + wire \u11_mem[0]_164 , \u11_mem[0]_165 , \u11_mem[0]_166 , + \u11_mem[0]_167 , \u11_mem[0]_168 , \u11_mem[0]_169 , + \u11_mem[0]_170 , \u11_mem[0]_171 ; + wire \u11_mem[0]_172 , \u11_mem[0]_173 , \u11_mem[0]_174 , + \u11_mem[0]_175 , \u11_mem[0]_176 , \u11_mem[0]_177 , + \u11_mem[0]_178 , \u11_mem[0]_179 ; + wire \u11_mem[0]_180 , \u11_mem[1] , \u11_mem[1]_119 , + \u11_mem[1]_120 , \u11_mem[1]_121 , \u11_mem[1]_122 , + \u11_mem[1]_123 , \u11_mem[1]_124 ; + wire \u11_mem[1]_125 , \u11_mem[1]_126 , \u11_mem[1]_127 , + \u11_mem[1]_128 , \u11_mem[1]_129 , \u11_mem[1]_130 , + \u11_mem[1]_131 , \u11_mem[1]_132 ; + wire \u11_mem[1]_133 , \u11_mem[1]_134 , \u11_mem[1]_135 , + \u11_mem[1]_136 , \u11_mem[1]_137 , \u11_mem[1]_138 , + \u11_mem[1]_139 , \u11_mem[1]_140 ; + wire \u11_mem[1]_141 , \u11_mem[1]_142 , \u11_mem[1]_143 , + \u11_mem[1]_144 , \u11_mem[1]_145 , \u11_mem[1]_146 , + \u11_mem[1]_147 , \u11_mem[1]_148 ; + wire \u11_mem[1]_149 , \u11_mem[2] , \u11_mem[2]_88 , \u11_mem[2]_89 + , \u11_mem[2]_90 , \u11_mem[2]_91 , \u11_mem[2]_92 , + \u11_mem[2]_93 ; + wire \u11_mem[2]_94 , \u11_mem[2]_95 , \u11_mem[2]_96 , + \u11_mem[2]_97 , \u11_mem[2]_98 , \u11_mem[2]_99 , + \u11_mem[2]_100 , \u11_mem[2]_101 ; + wire \u11_mem[2]_102 , \u11_mem[2]_103 , \u11_mem[2]_104 , + \u11_mem[2]_105 , \u11_mem[2]_106 , \u11_mem[2]_107 , + \u11_mem[2]_108 , \u11_mem[2]_109 ; + wire \u11_mem[2]_110 , \u11_mem[2]_111 , \u11_mem[2]_112 , + \u11_mem[2]_113 , \u11_mem[2]_114 , \u11_mem[2]_115 , + \u11_mem[2]_116 , \u11_mem[2]_117 ; + wire \u11_mem[2]_118 , \u11_mem[3] , \u11_mem[3]_57 , \u11_mem[3]_58 + , \u11_mem[3]_59 , \u11_mem[3]_60 , \u11_mem[3]_61 , + \u11_mem[3]_62 ; + wire \u11_mem[3]_63 , \u11_mem[3]_64 , \u11_mem[3]_65 , + \u11_mem[3]_66 , \u11_mem[3]_67 , \u11_mem[3]_68 , + \u11_mem[3]_69 , \u11_mem[3]_70 ; + wire \u11_mem[3]_71 , \u11_mem[3]_72 , \u11_mem[3]_73 , + \u11_mem[3]_74 , \u11_mem[3]_75 , \u11_mem[3]_76 , + \u11_mem[3]_77 , \u11_mem[3]_78 ; + wire \u11_mem[3]_79 , \u11_mem[3]_80 , \u11_mem[3]_81 , + \u11_mem[3]_82 , \u11_mem[3]_83 , \u11_mem[3]_84 , + \u11_mem[3]_85 , \u11_mem[3]_86 ; + wire \u11_mem[3]_87 , \u11_rp[0] , \u11_rp[1] , \u11_rp[2] , + \u11_wp[0] , \u11_wp[1] , \u11_wp[2] , \u11_wp[3] ; + wire u12_re1, u12_re2, u12_we1, u12_we2, \u13_intm_r[0] , + \u13_intm_r[1] , \u13_intm_r[2] , \u13_intm_r[3] ; + wire \u13_intm_r[4] , \u13_intm_r[5] , \u13_intm_r[6] , + \u13_intm_r[7] , \u13_intm_r[8] , \u13_intm_r[9] , + \u13_intm_r[10] , \u13_intm_r[11] ; + wire \u13_intm_r[12] , \u13_intm_r[13] , \u13_intm_r[14] , + \u13_intm_r[15] , \u13_intm_r[16] , \u13_intm_r[17] , + \u13_intm_r[18] , \u13_intm_r[19] ; + wire \u13_intm_r[20] , \u13_intm_r[21] , \u13_intm_r[22] , + \u13_intm_r[23] , \u13_intm_r[24] , \u13_intm_r[25] , + \u13_intm_r[26] , \u13_intm_r[27] ; + wire \u13_intm_r[28] , \u13_ints_r[0] , \u13_ints_r[1] , + \u13_ints_r[2] , \u13_ints_r[3] , \u13_ints_r[4] , + \u13_ints_r[5] , \u13_ints_r[6] ; + wire \u13_ints_r[7] , \u13_ints_r[8] , \u13_ints_r[9] , + \u13_ints_r[10] , \u13_ints_r[11] , \u13_ints_r[12] , + \u13_ints_r[13] , \u13_ints_r[14] ; + wire \u13_ints_r[15] , \u13_ints_r[16] , \u13_ints_r[17] , + \u13_ints_r[18] , \u13_ints_r[19] , \u13_ints_r[20] , + \u13_ints_r[21] , \u13_ints_r[22] ; + wire \u13_ints_r[23] , \u13_ints_r[24] , \u13_ints_r[25] , + \u13_ints_r[26] , \u13_ints_r[27] , \u13_ints_r[28] , u14_n_133, + u14_n_134; + wire u14_n_135, u14_u0_full_empty_r, u14_u1_en_out_l2, + u14_u1_full_empty_r, u14_u2_full_empty_r, u14_u3_full_empty_r, + u14_u4_full_empty_r, u14_u5_full_empty_r; + wire u14_u6_en_out_l2, u14_u6_full_empty_r, u14_u7_en_out_l2, + u14_u7_full_empty_r, u14_u8_en_out_l2, u14_u8_full_empty_r, + u15_crac_rd, u15_crac_we_r; + wire u15_rdd1, u15_rdd2, u15_rdd3, u15_valid_r, u16_u0_dma_req_r1, + u16_u1_dma_req_r1, u16_u2_dma_req_r1, u16_u3_dma_req_r1; + wire u16_u4_dma_req_r1, u16_u5_dma_req_r1, u16_u8_dma_req_r1, + \u26_cnt[0] , \u26_cnt[1] , \u26_cnt[2] , \u26_ps_cnt[0] , + \u26_ps_cnt[1] ; + wire \u26_ps_cnt[3] , \u26_ps_cnt[4] , \u26_ps_cnt[5] , valid, + valid_s, valid_s1, wb_din, wb_din_661; + wire wb_din_662, wb_din_663, wb_din_664, wb_din_665, wb_din_666, + wb_din_667, wb_din_668, wb_din_669; + wire wb_din_670, wb_din_671, wb_din_672, wb_din_673, wb_din_674, + wb_din_675, wb_din_676, wb_din_677; + wire wb_din_678, wb_din_679, wb_din_680, wb_din_681, wb_din_682, + wb_din_683, wb_din_684, wb_din_685; + wire wb_din_686, wb_din_687, wb_din_688, wb_din_689, wb_din_690, + wb_din_691; + assign wb_err_o = 1'b0; + DFFX1 \u0_slt0_r_reg[15] (.CK (bit_clk_pad_i), .D (n_11438), .Q + (sdata_pad_o), .QN ()); + NAND3X1 g29500(.A (n_11437), .B (n_7043), .C (n_11426), .Y (n_11438)); + AOI21X1 g29501(.A0 (u0_slt0_r_14), .A1 (n_7042), .B0 (n_7013), .Y + (n_11437)); + DFFX1 \u0_slt0_r_reg[14] (.CK (bit_clk_pad_i), .D (n_11436), .Q + (u0_slt0_r_14), .QN ()); + MX2X1 g29503(.A (out_slt_25), .B (u0_slt0_r_13), .S0 (n_11389), .Y + (n_11436)); + DFFX1 \u0_slt0_r_reg[13] (.CK (bit_clk_pad_i), .D (n_11435), .Q + (u0_slt0_r_13), .QN ()); + MX2X1 g29505(.A (out_slt_24), .B (u0_slt0_r_12), .S0 (n_11389), .Y + (n_11435)); + DFFX1 \u0_slt0_r_reg[12] (.CK (bit_clk_pad_i), .D (n_11434), .Q + (u0_slt0_r_12), .QN ()); + MX2X1 g29507(.A (out_slt_23), .B (u0_slt0_r_11), .S0 (n_11389), .Y + (n_11434)); + DFFX1 \u0_slt0_r_reg[11] (.CK (bit_clk_pad_i), .D (n_11433), .Q + (u0_slt0_r_11), .QN ()); + MX2X1 g29509(.A (out_slt_22), .B (u0_slt0_r_10), .S0 (n_11389), .Y + (n_11433)); + DFFX1 \u0_slt0_r_reg[10] (.CK (bit_clk_pad_i), .D (n_11431), .Q + (u0_slt0_r_10), .QN ()); + AND2X1 g29511(.A (u0_slt0_r_9), .B (n_7042), .Y (n_11431)); + DFFX1 \u0_slt0_r_reg[9] (.CK (bit_clk_pad_i), .D (n_11430), .Q + (u0_slt0_r_9), .QN ()); + MX2X1 g29513(.A (out_slt_20), .B (u0_slt0_r_8), .S0 (n_11319), .Y + (n_11430)); + DFFX1 \u0_slt0_r_reg[8] (.CK (bit_clk_pad_i), .D (n_11429), .Q + (u0_slt0_r_8), .QN ()); + MX2X1 g29515(.A (out_slt_19), .B (u0_slt0_r_7), .S0 (n_11389), .Y + (n_11429)); + DFFX1 \u0_slt0_r_reg[7] (.CK (bit_clk_pad_i), .D (n_11428), .Q + (u0_slt0_r_7), .QN ()); + MX2X1 g29517(.A (out_slt_18), .B (u0_slt0_r_6), .S0 (n_11389), .Y + (n_11428)); + DFFX1 \u0_slt0_r_reg[6] (.CK (bit_clk_pad_i), .D (n_11427), .Q + (u0_slt0_r_6), .QN ()); + NAND2X1 g29519(.A (n_11425), .B (n_11426), .Y (n_11427)); + NAND2X1 g29520(.A (u0_slt0_r_5), .B (n_7042), .Y (n_11425)); + DFFX1 \u0_slt0_r_reg[5] (.CK (bit_clk_pad_i), .D (n_11424), .Q + (u0_slt0_r_5), .QN ()); + AND2X1 g29522(.A (u0_slt0_r_4), .B (n_11395), .Y (n_11424)); + DFFX1 \u0_slt0_r_reg[4] (.CK (bit_clk_pad_i), .D (n_11423), .Q + (u0_slt0_r_4), .QN ()); + AND2X1 g29524(.A (u0_slt0_r_3), .B (n_7042), .Y (n_11423)); + DFFX1 \u0_slt0_r_reg[3] (.CK (bit_clk_pad_i), .D (n_11421), .Q + (u0_slt0_r_3), .QN ()); + AND2X1 g29526(.A (u0_slt0_r_2), .B (n_11395), .Y (n_11421)); + DFFX1 \u0_slt0_r_reg[2] (.CK (bit_clk_pad_i), .D (n_11420), .Q + (u0_slt0_r_2), .QN ()); + AND2X1 g29528(.A (u0_slt0_r_1), .B (n_7042), .Y (n_11420)); + DFFX1 \u0_slt0_r_reg[1] (.CK (bit_clk_pad_i), .D (n_11419), .Q + (u0_slt0_r_1), .QN ()); + AND2X1 g29530(.A (u0_slt0_r), .B (n_11395), .Y (n_11419)); + DFFX1 \u0_slt0_r_reg[0] (.CK (bit_clk_pad_i), .D (n_11418), .Q + (u0_slt0_r), .QN ()); + AND2X1 g29532(.A (u0_slt1_r_34), .B (n_11395), .Y (n_11418)); + DFFX1 \u0_slt1_r_reg[19] (.CK (bit_clk_pad_i), .D (n_11417), .Q + (u0_slt1_r_34), .QN ()); + MX2X1 g29534(.A (crac_out_876), .B (u0_slt1_r_33), .S0 (n_11389), .Y + (n_11417)); + DFFX1 \u0_slt1_r_reg[18] (.CK (bit_clk_pad_i), .D (n_11416), .Q + (u0_slt1_r_33), .QN ()); + MX2X1 g29536(.A (crac_out_867), .B (u0_slt1_r_32), .S0 (n_11389), .Y + (n_11416)); + DFFX1 \u0_slt1_r_reg[17] (.CK (bit_clk_pad_i), .D (n_11414), .Q + (u0_slt1_r_32), .QN ()); + MX2X1 g29538(.A (crac_out_866), .B (u0_slt1_r_31), .S0 (n_11319), .Y + (n_11414)); + DFFX1 \u0_slt1_r_reg[16] (.CK (bit_clk_pad_i), .D (n_11413), .Q + (u0_slt1_r_31), .QN ()); + MX2X1 g29540(.A (crac_out_865), .B (u0_slt1_r_30), .S0 (n_7042), .Y + (n_11413)); + DFFX1 \u0_slt1_r_reg[15] (.CK (bit_clk_pad_i), .D (n_11411), .Q + (u0_slt1_r_30), .QN ()); + MX2X1 g29542(.A (crac_out_864), .B (u0_slt1_r_29), .S0 (n_7042), .Y + (n_11411)); + DFFX1 \u0_slt1_r_reg[14] (.CK (bit_clk_pad_i), .D (n_11410), .Q + (u0_slt1_r_29), .QN ()); + MX2X1 g29544(.A (crac_out_863), .B (u0_slt1_r_28), .S0 (n_7042), .Y + (n_11410)); + DFFX1 \u0_slt1_r_reg[13] (.CK (bit_clk_pad_i), .D (n_11409), .Q + (u0_slt1_r_28), .QN ()); + MX2X1 g29546(.A (crac_out_862), .B (u0_slt1_r_27), .S0 (n_11389), .Y + (n_11409)); + DFFX1 \u0_slt1_r_reg[12] (.CK (bit_clk_pad_i), .D (n_11408), .Q + (u0_slt1_r_27), .QN ()); + MX2X1 g29548(.A (crac_out_861), .B (u0_slt1_r_26), .S0 (n_11389), .Y + (n_11408)); + DFFX1 \u0_slt1_r_reg[11] (.CK (bit_clk_pad_i), .D (n_11406), .Q + (u0_slt1_r_26), .QN ()); + AND2X1 g29550(.A (u0_slt1_r_25), .B (n_11395), .Y (n_11406)); + DFFX1 \u0_slt1_r_reg[10] (.CK (bit_clk_pad_i), .D (n_11404), .Q + (u0_slt1_r_25), .QN ()); + AND2X1 g29552(.A (u0_slt1_r_24), .B (n_11395), .Y (n_11404)); + DFFX1 \u0_slt1_r_reg[9] (.CK (bit_clk_pad_i), .D (n_11403), .Q + (u0_slt1_r_24), .QN ()); + AND2X1 g29554(.A (u0_slt1_r_23), .B (n_11395), .Y (n_11403)); + DFFX1 \u0_slt1_r_reg[8] (.CK (bit_clk_pad_i), .D (n_11401), .Q + (u0_slt1_r_23), .QN ()); + AND2X1 g29556(.A (u0_slt1_r_22), .B (n_7042), .Y (n_11401)); + DFFX1 \u0_slt1_r_reg[7] (.CK (bit_clk_pad_i), .D (n_11400), .Q + (u0_slt1_r_22), .QN ()); + AND2X1 g29558(.A (u0_slt1_r_21), .B (n_11395), .Y (n_11400)); + DFFX1 \u0_slt1_r_reg[6] (.CK (bit_clk_pad_i), .D (n_11399), .Q + (u0_slt1_r_21), .QN ()); + AND2X1 g29560(.A (u0_slt1_r_20), .B (n_11395), .Y (n_11399)); + DFFX1 \u0_slt1_r_reg[5] (.CK (bit_clk_pad_i), .D (n_11397), .Q + (u0_slt1_r_20), .QN ()); + AND2X1 g29562(.A (u0_slt1_r_19), .B (n_11395), .Y (n_11397)); + DFFX1 \u0_slt1_r_reg[4] (.CK (bit_clk_pad_i), .D (n_11396), .Q + (u0_slt1_r_19), .QN ()); + AND2X1 g29564(.A (u0_slt1_r_18), .B (n_11395), .Y (n_11396)); + DFFX1 \u0_slt1_r_reg[3] (.CK (bit_clk_pad_i), .D (n_11394), .Q + (u0_slt1_r_18), .QN ()); + AND2X1 g29566(.A (u0_slt1_r_17), .B (n_11395), .Y (n_11394)); + DFFX1 \u0_slt1_r_reg[2] (.CK (bit_clk_pad_i), .D (n_11393), .Q + (u0_slt1_r_17), .QN ()); + AND2X1 g29568(.A (u0_slt1_r_16), .B (n_11395), .Y (n_11393)); + DFFX1 \u0_slt1_r_reg[1] (.CK (bit_clk_pad_i), .D (n_11392), .Q + (u0_slt1_r_16), .QN ()); + AND2X1 g29570(.A (u0_slt1_r), .B (n_11395), .Y (n_11392)); + DFFX1 \u0_slt1_r_reg[0] (.CK (bit_clk_pad_i), .D (n_11391), .Q + (u0_slt1_r), .QN ()); + AND2X1 g29572(.A (u0_slt2_r_53), .B (n_11395), .Y (n_11391)); + DFFX1 \u0_slt2_r_reg[19] (.CK (bit_clk_pad_i), .D (n_11390), .Q + (u0_slt2_r_53), .QN ()); + MX2X1 g29574(.A (n_170), .B (u0_slt2_r_52), .S0 (n_11389), .Y + (n_11390)); + DFFX1 \u0_slt2_r_reg[18] (.CK (bit_clk_pad_i), .D (n_11388), .Q + (u0_slt2_r_52), .QN ()); + MX2X1 g29576(.A (n_177), .B (u0_slt2_r_51), .S0 (n_11319), .Y + (n_11388)); + DFFX1 \u0_slt2_r_reg[17] (.CK (bit_clk_pad_i), .D (n_11387), .Q + (u0_slt2_r_51), .QN ()); + MX2X1 g29578(.A (n_179), .B (u0_slt2_r_50), .S0 (n_11389), .Y + (n_11387)); + DFFX1 \u0_slt2_r_reg[16] (.CK (bit_clk_pad_i), .D (n_11385), .Q + (u0_slt2_r_50), .QN ()); + MX2X1 g29580(.A (n_338), .B (u0_slt2_r_49), .S0 (n_6710), .Y + (n_11385)); + DFFX1 \u0_slt2_r_reg[15] (.CK (bit_clk_pad_i), .D (n_11384), .Q + (u0_slt2_r_49), .QN ()); + MX2X1 g29582(.A (n_138), .B (u0_slt2_r_48), .S0 (n_11319), .Y + (n_11384)); + DFFX1 \u0_slt2_r_reg[14] (.CK (bit_clk_pad_i), .D (n_11383), .Q + (u0_slt2_r_48), .QN ()); + MX2X1 g29584(.A (n_56), .B (u0_slt2_r_47), .S0 (n_11319), .Y + (n_11383)); + DFFX1 \u0_slt2_r_reg[13] (.CK (bit_clk_pad_i), .D (n_11381), .Q + (u0_slt2_r_47), .QN ()); + MX2X1 g29586(.A (n_112), .B (u0_slt2_r_46), .S0 (n_11319), .Y + (n_11381)); + DFFX1 \u0_slt2_r_reg[12] (.CK (bit_clk_pad_i), .D (n_11379), .Q + (u0_slt2_r_46), .QN ()); + MX2X1 g29588(.A (n_231), .B (u0_slt2_r_45), .S0 (n_11319), .Y + (n_11379)); + DFFX1 \u0_slt2_r_reg[11] (.CK (bit_clk_pad_i), .D (n_11378), .Q + (u0_slt2_r_45), .QN ()); + MX2X1 g29590(.A (n_357), .B (u0_slt2_r_44), .S0 (n_11395), .Y + (n_11378)); + DFFX1 \u0_slt2_r_reg[10] (.CK (bit_clk_pad_i), .D (n_11377), .Q + (u0_slt2_r_44), .QN ()); + MX2X1 g29592(.A (n_149), .B (u0_slt2_r_43), .S0 (n_11389), .Y + (n_11377)); + DFFX1 \u0_slt2_r_reg[9] (.CK (bit_clk_pad_i), .D (n_11376), .Q + (u0_slt2_r_43), .QN ()); + MX2X1 g29594(.A (n_311), .B (u0_slt2_r_42), .S0 (n_11319), .Y + (n_11376)); + DFFX1 \u0_slt2_r_reg[8] (.CK (bit_clk_pad_i), .D (n_11375), .Q + (u0_slt2_r_42), .QN ()); + MX2X1 g29596(.A (n_130), .B (u0_slt2_r_41), .S0 (n_11319), .Y + (n_11375)); + DFFX1 \u0_slt2_r_reg[7] (.CK (bit_clk_pad_i), .D (n_11373), .Q + (u0_slt2_r_41), .QN ()); + MX2X1 g29598(.A (n_71), .B (u0_slt2_r_40), .S0 (n_11319), .Y + (n_11373)); + DFFX1 \u0_slt2_r_reg[6] (.CK (bit_clk_pad_i), .D (n_11372), .Q + (u0_slt2_r_40), .QN ()); + MX2X1 g29600(.A (n_306), .B (u0_slt2_r_39), .S0 (n_11319), .Y + (n_11372)); + DFFX1 \u0_slt2_r_reg[5] (.CK (bit_clk_pad_i), .D (n_11371), .Q + (u0_slt2_r_39), .QN ()); + MX2X1 g29602(.A (n_227), .B (u0_slt2_r_38), .S0 (n_11319), .Y + (n_11371)); + DFFX1 \u0_slt2_r_reg[4] (.CK (bit_clk_pad_i), .D (n_11370), .Q + (u0_slt2_r_38), .QN ()); + MX2X1 g29604(.A (n_392), .B (u0_slt2_r_37), .S0 (n_11319), .Y + (n_11370)); + DFFX1 \u0_slt2_r_reg[3] (.CK (bit_clk_pad_i), .D (n_11368), .Q + (u0_slt2_r_37), .QN ()); + AND2X1 g29606(.A (u0_slt2_r_36), .B (n_11395), .Y (n_11368)); + DFFX1 \u0_slt2_r_reg[2] (.CK (bit_clk_pad_i), .D (n_11366), .Q + (u0_slt2_r_36), .QN ()); + AND2X1 g29608(.A (u0_slt2_r_35), .B (n_7042), .Y (n_11366)); + DFFX1 \u0_slt2_r_reg[1] (.CK (bit_clk_pad_i), .D (n_11365), .Q + (u0_slt2_r_35), .QN ()); + AND2X1 g29610(.A (u0_slt2_r), .B (n_7042), .Y (n_11365)); + DFFX1 \u0_slt2_r_reg[0] (.CK (bit_clk_pad_i), .D (n_11364), .Q + (u0_slt2_r), .QN ()); + AND2X1 g29612(.A (u0_slt3_r_72), .B (n_11395), .Y (n_11364)); + DFFX1 \u0_slt3_r_reg[19] (.CK (bit_clk_pad_i), .D (n_11363), .Q + (u0_slt3_r_72), .QN ()); + MX2X1 g29614(.A (n_329), .B (u0_slt3_r_71), .S0 (n_11389), .Y + (n_11363)); + DFFX1 \u0_slt3_r_reg[18] (.CK (bit_clk_pad_i), .D (n_11361), .Q + (u0_slt3_r_71), .QN ()); + MX2X1 g29616(.A (n_16), .B (u0_slt3_r_70), .S0 (n_11389), .Y + (n_11361)); + DFFX1 \u0_slt3_r_reg[17] (.CK (bit_clk_pad_i), .D (n_11360), .Q + (u0_slt3_r_70), .QN ()); + MX2X1 g29618(.A (n_109), .B (u0_slt3_r_69), .S0 (n_11319), .Y + (n_11360)); + DFFX1 \u0_slt3_r_reg[16] (.CK (bit_clk_pad_i), .D (n_11358), .Q + (u0_slt3_r_69), .QN ()); + MX2X1 g29620(.A (n_281), .B (u0_slt3_r_68), .S0 (n_11395), .Y + (n_11358)); + DFFX1 \u0_slt3_r_reg[15] (.CK (bit_clk_pad_i), .D (n_11356), .Q + (u0_slt3_r_68), .QN ()); + MX2X1 g29622(.A (n_282), .B (u0_slt3_r_67), .S0 (n_11395), .Y + (n_11356)); + DFFX1 \u0_slt3_r_reg[14] (.CK (bit_clk_pad_i), .D (n_11355), .Q + (u0_slt3_r_67), .QN ()); + MX2X1 g29624(.A (n_267), .B (u0_slt3_r_66), .S0 (n_7042), .Y + (n_11355)); + DFFX1 \u0_slt3_r_reg[13] (.CK (bit_clk_pad_i), .D (n_11354), .Q + (u0_slt3_r_66), .QN ()); + MX2X1 g29626(.A (n_195), .B (u0_slt3_r_65), .S0 (n_7042), .Y + (n_11354)); + DFFX1 \u0_slt3_r_reg[12] (.CK (bit_clk_pad_i), .D (n_11353), .Q + (u0_slt3_r_65), .QN ()); + MX2X1 g29628(.A (n_157), .B (u0_slt3_r_64), .S0 (n_11319), .Y + (n_11353)); + DFFX1 \u0_slt3_r_reg[11] (.CK (bit_clk_pad_i), .D (n_11352), .Q + (u0_slt3_r_64), .QN ()); + MX2X1 g29630(.A (n_398), .B (u0_slt3_r_63), .S0 (n_11395), .Y + (n_11352)); + DFFX1 \u0_slt3_r_reg[10] (.CK (bit_clk_pad_i), .D (n_11351), .Q + (u0_slt3_r_63), .QN ()); + MX2X1 g29632(.A (n_389), .B (u0_slt3_r_62), .S0 (n_11395), .Y + (n_11351)); + DFFX1 \u0_slt3_r_reg[9] (.CK (bit_clk_pad_i), .D (n_11349), .Q + (u0_slt3_r_62), .QN ()); + MX2X1 g29634(.A (n_341), .B (u0_slt3_r_61), .S0 (n_6710), .Y + (n_11349)); + DFFX1 \u0_slt3_r_reg[8] (.CK (bit_clk_pad_i), .D (n_11348), .Q + (u0_slt3_r_61), .QN ()); + MX2X1 g29636(.A (n_82), .B (u0_slt3_r_60), .S0 (n_11319), .Y + (n_11348)); + DFFX1 \u0_slt3_r_reg[7] (.CK (bit_clk_pad_i), .D (n_11347), .Q + (u0_slt3_r_60), .QN ()); + MX2X1 g29638(.A (n_230), .B (u0_slt3_r_59), .S0 (n_11319), .Y + (n_11347)); + DFFX1 \u0_slt3_r_reg[6] (.CK (bit_clk_pad_i), .D (n_11346), .Q + (u0_slt3_r_59), .QN ()); + MX2X1 g29640(.A (n_211), .B (u0_slt3_r_58), .S0 (n_11319), .Y + (n_11346)); + DFFX1 \u0_slt3_r_reg[5] (.CK (bit_clk_pad_i), .D (n_11344), .Q + (u0_slt3_r_58), .QN ()); + MX2X1 g29642(.A (n_200), .B (u0_slt3_r_57), .S0 (n_11319), .Y + (n_11344)); + DFFX1 \u0_slt3_r_reg[4] (.CK (bit_clk_pad_i), .D (n_11342), .Q + (u0_slt3_r_57), .QN ()); + MX2X1 g29644(.A (n_348), .B (u0_slt3_r_56), .S0 (n_11389), .Y + (n_11342)); + DFFX1 \u0_slt3_r_reg[3] (.CK (bit_clk_pad_i), .D (n_11341), .Q + (u0_slt3_r_56), .QN ()); + MX2X1 g29646(.A (n_10976), .B (u0_slt3_r_55), .S0 (n_11389), .Y + (n_11341)); + DFFX1 \u0_slt3_r_reg[2] (.CK (bit_clk_pad_i), .D (n_11339), .Q + (u0_slt3_r_55), .QN ()); + MX2X1 g29648(.A (n_10978), .B (u0_slt3_r_54), .S0 (n_11389), .Y + (n_11339)); + DFFX1 \u0_slt3_r_reg[1] (.CK (bit_clk_pad_i), .D (n_11338), .Q + (u0_slt3_r_54), .QN ()); + MX2X1 g29650(.A (n_220), .B (u0_slt3_r), .S0 (n_11319), .Y (n_11338)); + DFFX1 \u0_slt3_r_reg[0] (.CK (bit_clk_pad_i), .D (n_11336), .Q + (u0_slt3_r), .QN ()); + MX2X1 g29652(.A (n_251), .B (u0_slt4_r_91), .S0 (n_11319), .Y + (n_11336)); + DFFX1 \u0_slt4_r_reg[19] (.CK (bit_clk_pad_i), .D (n_11334), .Q + (u0_slt4_r_91), .QN ()); + MX2X1 g29654(.A (n_361), .B (u0_slt4_r_90), .S0 (n_11389), .Y + (n_11334)); + DFFX1 \u0_slt4_r_reg[18] (.CK (bit_clk_pad_i), .D (n_11333), .Q + (u0_slt4_r_90), .QN ()); + MX2X1 g29656(.A (n_295), .B (u0_slt4_r_89), .S0 (n_6710), .Y + (n_11333)); + DFFX1 \u0_slt4_r_reg[17] (.CK (bit_clk_pad_i), .D (n_11332), .Q + (u0_slt4_r_89), .QN ()); + MX2X1 g29658(.A (n_396), .B (u0_slt4_r_88), .S0 (n_6710), .Y + (n_11332)); + DFFX1 \u0_slt4_r_reg[16] (.CK (bit_clk_pad_i), .D (n_11330), .Q + (u0_slt4_r_88), .QN ()); + MX2X1 g29660(.A (n_248), .B (u0_slt4_r_87), .S0 (n_11319), .Y + (n_11330)); + DFFX1 \u0_slt4_r_reg[15] (.CK (bit_clk_pad_i), .D (n_11329), .Q + (u0_slt4_r_87), .QN ()); + MX2X1 g29662(.A (n_243), .B (u0_slt4_r_86), .S0 (n_11319), .Y + (n_11329)); + DFFX1 \u0_slt4_r_reg[14] (.CK (bit_clk_pad_i), .D (n_11328), .Q + (u0_slt4_r_86), .QN ()); + MX2X1 g29664(.A (n_103), .B (u0_slt4_r_85), .S0 (n_6710), .Y + (n_11328)); + DFFX1 \u0_slt4_r_reg[13] (.CK (bit_clk_pad_i), .D (n_11327), .Q + (u0_slt4_r_85), .QN ()); + MX2X1 g29666(.A (n_330), .B (u0_slt4_r_84), .S0 (n_11319), .Y + (n_11327)); + DFFX1 \u0_slt4_r_reg[12] (.CK (bit_clk_pad_i), .D (n_11326), .Q + (u0_slt4_r_84), .QN ()); + MX2X1 g29668(.A (n_332), .B (u0_slt4_r_83), .S0 (n_7042), .Y + (n_11326)); + DFFX1 \u0_slt4_r_reg[11] (.CK (bit_clk_pad_i), .D (n_11324), .Q + (u0_slt4_r_83), .QN ()); + MX2X1 g29670(.A (n_321), .B (u0_slt4_r_82), .S0 (n_11389), .Y + (n_11324)); + DFFX1 \u0_slt4_r_reg[10] (.CK (bit_clk_pad_i), .D (n_11323), .Q + (u0_slt4_r_82), .QN ()); + MX2X1 g29672(.A (n_320), .B (u0_slt4_r_81), .S0 (n_6710), .Y + (n_11323)); + DFFX1 \u0_slt4_r_reg[9] (.CK (bit_clk_pad_i), .D (n_11321), .Q + (u0_slt4_r_81), .QN ()); + MX2X1 g29674(.A (n_394), .B (u0_slt4_r_80), .S0 (n_11319), .Y + (n_11321)); + DFFX1 \u0_slt4_r_reg[8] (.CK (bit_clk_pad_i), .D (n_11320), .Q + (u0_slt4_r_80), .QN ()); + MX2X1 g29676(.A (n_391), .B (u0_slt4_r_79), .S0 (n_11319), .Y + (n_11320)); + DFFX1 \u0_slt4_r_reg[7] (.CK (bit_clk_pad_i), .D (n_11318), .Q + (u0_slt4_r_79), .QN ()); + MX2X1 g29678(.A (n_351), .B (u0_slt4_r_78), .S0 (n_7042), .Y + (n_11318)); + DFFX1 \u0_slt4_r_reg[6] (.CK (bit_clk_pad_i), .D (n_11317), .Q + (u0_slt4_r_78), .QN ()); + MX2X1 g29680(.A (n_370), .B (u0_slt4_r_77), .S0 (n_11389), .Y + (n_11317)); + DFFX1 \u0_slt4_r_reg[5] (.CK (bit_clk_pad_i), .D (n_11315), .Q + (u0_slt4_r_77), .QN ()); + MX2X1 g29682(.A (n_380), .B (u0_slt4_r_76), .S0 (n_7042), .Y + (n_11315)); + DFFX1 \u0_slt4_r_reg[4] (.CK (bit_clk_pad_i), .D (n_11314), .Q + (u0_slt4_r_76), .QN ()); + MX2X1 g29684(.A (n_373), .B (u0_slt4_r_75), .S0 (n_11319), .Y + (n_11314)); + DFFX1 \u0_slt4_r_reg[3] (.CK (bit_clk_pad_i), .D (n_11313), .Q + (u0_slt4_r_75), .QN ()); + MX2X1 g29686(.A (n_10788), .B (u0_slt4_r_74), .S0 (n_11389), .Y + (n_11313)); + DFFX1 \u0_slt4_r_reg[2] (.CK (bit_clk_pad_i), .D (n_11312), .Q + (u0_slt4_r_74), .QN ()); + MX2X1 g29688(.A (n_10790), .B (u0_slt4_r_73), .S0 (n_6710), .Y + (n_11312)); + DFFX1 \u0_slt4_r_reg[1] (.CK (bit_clk_pad_i), .D (n_11311), .Q + (u0_slt4_r_73), .QN ()); + MX2X1 g29690(.A (n_333), .B (u0_slt4_r), .S0 (n_7042), .Y (n_11311)); + DFFX1 \u0_slt4_r_reg[0] (.CK (bit_clk_pad_i), .D (n_11310), .Q + (u0_slt4_r), .QN ()); + MX2X1 g29692(.A (n_397), .B (u0_slt5_r_110), .S0 (n_7042), .Y + (n_11310)); + DFFX1 \u0_slt5_r_reg[19] (.CK (bit_clk_pad_i), .D (n_11308), .Q + (u0_slt5_r_110), .QN ()); + AND2X1 g29694(.A (u0_slt5_r_109), .B (n_11395), .Y (n_11308)); + DFFX1 \u0_slt5_r_reg[18] (.CK (bit_clk_pad_i), .D (n_11307), .Q + (u0_slt5_r_109), .QN ()); + AND2X1 g29696(.A (u0_slt5_r_108), .B (n_11395), .Y (n_11307)); + DFFX1 \u0_slt5_r_reg[17] (.CK (bit_clk_pad_i), .D (n_11306), .Q + (u0_slt5_r_108), .QN ()); + AND2X1 g29698(.A (u0_slt5_r_107), .B (n_11395), .Y (n_11306)); + DFFX1 \u0_slt5_r_reg[16] (.CK (bit_clk_pad_i), .D (n_11305), .Q + (u0_slt5_r_107), .QN ()); + AND2X1 g29700(.A (u0_slt5_r_106), .B (n_11395), .Y (n_11305)); + DFFX1 \u0_slt5_r_reg[15] (.CK (bit_clk_pad_i), .D (n_11304), .Q + (u0_slt5_r_106), .QN ()); + AND2X1 g29702(.A (u0_slt5_r_105), .B (n_11395), .Y (n_11304)); + DFFX1 \u0_slt5_r_reg[14] (.CK (bit_clk_pad_i), .D (n_11303), .Q + (u0_slt5_r_105), .QN ()); + AND2X1 g29704(.A (u0_slt5_r_104), .B (n_11395), .Y (n_11303)); + DFFX1 \u0_slt5_r_reg[13] (.CK (bit_clk_pad_i), .D (n_11302), .Q + (u0_slt5_r_104), .QN ()); + AND2X1 g29706(.A (u0_slt5_r_103), .B (n_11395), .Y (n_11302)); + DFFX1 \u0_slt5_r_reg[12] (.CK (bit_clk_pad_i), .D (n_11301), .Q + (u0_slt5_r_103), .QN ()); + AND2X1 g29708(.A (u0_slt5_r_102), .B (n_11395), .Y (n_11301)); + DFFX1 \u0_slt5_r_reg[11] (.CK (bit_clk_pad_i), .D (n_11300), .Q + (u0_slt5_r_102), .QN ()); + AND2X1 g29710(.A (u0_slt5_r_101), .B (n_11395), .Y (n_11300)); + DFFX1 \u0_slt5_r_reg[10] (.CK (bit_clk_pad_i), .D (n_11299), .Q + (u0_slt5_r_101), .QN ()); + AND2X1 g29712(.A (u0_slt5_r_100), .B (n_11395), .Y (n_11299)); + DFFX1 \u0_slt5_r_reg[9] (.CK (bit_clk_pad_i), .D (n_11298), .Q + (u0_slt5_r_100), .QN ()); + AND2X1 g29714(.A (u0_slt5_r_99), .B (n_11395), .Y (n_11298)); + DFFX1 \u0_slt5_r_reg[8] (.CK (bit_clk_pad_i), .D (n_11297), .Q + (u0_slt5_r_99), .QN ()); + AND2X1 g29716(.A (u0_slt5_r_98), .B (n_7042), .Y (n_11297)); + DFFX1 \u0_slt5_r_reg[7] (.CK (bit_clk_pad_i), .D (n_11296), .Q + (u0_slt5_r_98), .QN ()); + AND2X1 g29718(.A (u0_slt5_r_97), .B (n_7042), .Y (n_11296)); + DFFX1 \u0_slt5_r_reg[6] (.CK (bit_clk_pad_i), .D (n_11295), .Q + (u0_slt5_r_97), .QN ()); + AND2X1 g29720(.A (u0_slt5_r_96), .B (n_11395), .Y (n_11295)); + DFFX1 \u0_slt5_r_reg[5] (.CK (bit_clk_pad_i), .D (n_11294), .Q + (u0_slt5_r_96), .QN ()); + AND2X1 g29722(.A (u0_slt5_r_95), .B (n_11395), .Y (n_11294)); + DFFX1 \u0_slt5_r_reg[4] (.CK (bit_clk_pad_i), .D (n_11293), .Q + (u0_slt5_r_95), .QN ()); + AND2X1 g29724(.A (u0_slt5_r_94), .B (n_11395), .Y (n_11293)); + DFFX1 \u0_slt5_r_reg[3] (.CK (bit_clk_pad_i), .D (n_11292), .Q + (u0_slt5_r_94), .QN ()); + AND2X1 g29726(.A (u0_slt5_r_93), .B (n_11395), .Y (n_11292)); + DFFX1 \u0_slt5_r_reg[2] (.CK (bit_clk_pad_i), .D (n_11291), .Q + (u0_slt5_r_93), .QN ()); + AND2X1 g29728(.A (u0_slt5_r_92), .B (n_11395), .Y (n_11291)); + DFFX1 \u0_slt5_r_reg[1] (.CK (bit_clk_pad_i), .D (n_11290), .Q + (u0_slt5_r_92), .QN ()); + AND2X1 g29730(.A (u0_slt5_r), .B (n_11395), .Y (n_11290)); + DFFX1 \u0_slt5_r_reg[0] (.CK (bit_clk_pad_i), .D (n_11289), .Q + (u0_slt5_r), .QN ()); + AND2X1 g29732(.A (u0_slt6_r_129), .B (n_11395), .Y (n_11289)); + DFFX1 \u0_slt6_r_reg[19] (.CK (bit_clk_pad_i), .D (n_11288), .Q + (u0_slt6_r_129), .QN ()); + MX2X1 g29734(.A (n_102), .B (u0_slt6_r_128), .S0 (n_11319), .Y + (n_11288)); + DFFX1 \u0_slt6_r_reg[18] (.CK (bit_clk_pad_i), .D (n_11287), .Q + (u0_slt6_r_128), .QN ()); + MX2X1 g29736(.A (n_117), .B (u0_slt6_r_127), .S0 (n_11389), .Y + (n_11287)); + DFFX1 \u0_slt6_r_reg[17] (.CK (bit_clk_pad_i), .D (n_11286), .Q + (u0_slt6_r_127), .QN ()); + MX2X1 g29738(.A (n_114), .B (u0_slt6_r_126), .S0 (n_11319), .Y + (n_11286)); + DFFX1 \u0_slt6_r_reg[16] (.CK (bit_clk_pad_i), .D (n_11284), .Q + (u0_slt6_r_126), .QN ()); + MX2X1 g29740(.A (n_113), .B (u0_slt6_r_125), .S0 (n_11319), .Y + (n_11284)); + DFFX1 \u0_slt6_r_reg[15] (.CK (bit_clk_pad_i), .D (n_11283), .Q + (u0_slt6_r_125), .QN ()); + MX2X1 g29742(.A (n_101), .B (u0_slt6_r_124), .S0 (n_11389), .Y + (n_11283)); + DFFX1 \u0_slt6_r_reg[14] (.CK (bit_clk_pad_i), .D (n_11281), .Q + (u0_slt6_r_124), .QN ()); + MX2X1 g29744(.A (n_261), .B (u0_slt6_r_123), .S0 (n_7042), .Y + (n_11281)); + DFFX1 \u0_slt6_r_reg[13] (.CK (bit_clk_pad_i), .D (n_11280), .Q + (u0_slt6_r_123), .QN ()); + MX2X1 g29746(.A (n_300), .B (u0_slt6_r_122), .S0 (n_11319), .Y + (n_11280)); + DFFX1 \u0_slt6_r_reg[12] (.CK (bit_clk_pad_i), .D (n_11279), .Q + (u0_slt6_r_122), .QN ()); + MX2X1 g29748(.A (n_84), .B (u0_slt6_r_121), .S0 (n_11319), .Y + (n_11279)); + DFFX1 \u0_slt6_r_reg[11] (.CK (bit_clk_pad_i), .D (n_11278), .Q + (u0_slt6_r_121), .QN ()); + MX2X1 g29750(.A (n_287), .B (u0_slt6_r_120), .S0 (n_11389), .Y + (n_11278)); + DFFX1 \u0_slt6_r_reg[10] (.CK (bit_clk_pad_i), .D (n_11276), .Q + (u0_slt6_r_120), .QN ()); + MX2X1 g29752(.A (n_290), .B (u0_slt6_r_119), .S0 (n_11319), .Y + (n_11276)); + DFFX1 \u0_slt6_r_reg[9] (.CK (bit_clk_pad_i), .D (n_11274), .Q + (u0_slt6_r_119), .QN ()); + MX2X1 g29754(.A (n_264), .B (u0_slt6_r_118), .S0 (n_6710), .Y + (n_11274)); + DFFX1 \u0_slt6_r_reg[8] (.CK (bit_clk_pad_i), .D (n_11273), .Q + (u0_slt6_r_118), .QN ()); + MX2X1 g29756(.A (n_266), .B (u0_slt6_r_117), .S0 (n_11319), .Y + (n_11273)); + DFFX1 \u0_slt6_r_reg[7] (.CK (bit_clk_pad_i), .D (n_11272), .Q + (u0_slt6_r_117), .QN ()); + MX2X1 g29758(.A (n_166), .B (u0_slt6_r_116), .S0 (n_6710), .Y + (n_11272)); + DFFX1 \u0_slt6_r_reg[6] (.CK (bit_clk_pad_i), .D (n_11270), .Q + (u0_slt6_r_116), .QN ()); + MX2X1 g29760(.A (n_234), .B (u0_slt6_r_115), .S0 (n_11319), .Y + (n_11270)); + DFFX1 \u0_slt6_r_reg[5] (.CK (bit_clk_pad_i), .D (n_11269), .Q + (u0_slt6_r_115), .QN ()); + MX2X1 g29762(.A (n_262), .B (u0_slt6_r_114), .S0 (n_11319), .Y + (n_11269)); + DFFX1 \u0_slt6_r_reg[4] (.CK (bit_clk_pad_i), .D (n_11268), .Q + (u0_slt6_r_114), .QN ()); + MX2X1 g29764(.A (n_304), .B (u0_slt6_r_113), .S0 (n_11389), .Y + (n_11268)); + DFFX1 \u0_slt6_r_reg[3] (.CK (bit_clk_pad_i), .D (n_11267), .Q + (u0_slt6_r_113), .QN ()); + MX2X1 g29766(.A (n_10783), .B (u0_slt6_r_112), .S0 (n_11389), .Y + (n_11267)); + DFFX1 \u0_slt6_r_reg[2] (.CK (bit_clk_pad_i), .D (n_11266), .Q + (u0_slt6_r_112), .QN ()); + MX2X1 g29768(.A (n_10785), .B (u0_slt6_r_111), .S0 (n_11319), .Y + (n_11266)); + DFFX1 \u0_slt6_r_reg[1] (.CK (bit_clk_pad_i), .D (n_11264), .Q + (u0_slt6_r_111), .QN ()); + MX2X1 g29770(.A (n_21), .B (u0_slt6_r), .S0 (n_11319), .Y (n_11264)); + DFFX1 \u0_slt6_r_reg[0] (.CK (bit_clk_pad_i), .D (n_11263), .Q + (u0_slt6_r), .QN ()); + MX2X1 g29772(.A (n_223), .B (u0_slt7_r_148), .S0 (n_11389), .Y + (n_11263)); + DFFX1 \u0_slt7_r_reg[19] (.CK (bit_clk_pad_i), .D (n_11262), .Q + (u0_slt7_r_148), .QN ()); + MX2X1 g29774(.A (n_299), .B (u0_slt7_r_147), .S0 (n_11389), .Y + (n_11262)); + DFFX1 \u0_slt7_r_reg[18] (.CK (bit_clk_pad_i), .D (n_11260), .Q + (u0_slt7_r_147), .QN ()); + MX2X1 g29776(.A (n_399), .B (u0_slt7_r_146), .S0 (n_11319), .Y + (n_11260)); + DFFX1 \u0_slt7_r_reg[17] (.CK (bit_clk_pad_i), .D (n_11258), .Q + (u0_slt7_r_146), .QN ()); + MX2X1 g29778(.A (n_163), .B (u0_slt7_r_145), .S0 (n_11319), .Y + (n_11258)); + DFFX1 \u0_slt7_r_reg[16] (.CK (bit_clk_pad_i), .D (n_11257), .Q + (u0_slt7_r_145), .QN ()); + MX2X1 g29780(.A (n_254), .B (u0_slt7_r_144), .S0 (n_11389), .Y + (n_11257)); + DFFX1 \u0_slt7_r_reg[15] (.CK (bit_clk_pad_i), .D (n_11256), .Q + (u0_slt7_r_144), .QN ()); + MX2X1 g29782(.A (n_134), .B (u0_slt7_r_143), .S0 (n_11389), .Y + (n_11256)); + DFFX1 \u0_slt7_r_reg[14] (.CK (bit_clk_pad_i), .D (n_11255), .Q + (u0_slt7_r_143), .QN ()); + MX2X1 g29784(.A (n_186), .B (u0_slt7_r_142), .S0 (n_11319), .Y + (n_11255)); + DFFX1 \u0_slt7_r_reg[13] (.CK (bit_clk_pad_i), .D (n_11254), .Q + (u0_slt7_r_142), .QN ()); + MX2X1 g29786(.A (n_259), .B (u0_slt7_r_141), .S0 (n_11319), .Y + (n_11254)); + DFFX1 \u0_slt7_r_reg[12] (.CK (bit_clk_pad_i), .D (n_11253), .Q + (u0_slt7_r_141), .QN ()); + MX2X1 g29788(.A (n_401), .B (u0_slt7_r_140), .S0 (n_11389), .Y + (n_11253)); + DFFX1 \u0_slt7_r_reg[11] (.CK (bit_clk_pad_i), .D (n_11252), .Q + (u0_slt7_r_140), .QN ()); + MX2X1 g29790(.A (n_229), .B (u0_slt7_r_139), .S0 (n_11389), .Y + (n_11252)); + DFFX1 \u0_slt7_r_reg[10] (.CK (bit_clk_pad_i), .D (n_11251), .Q + (u0_slt7_r_139), .QN ()); + MX2X1 g29792(.A (n_387), .B (u0_slt7_r_138), .S0 (n_11319), .Y + (n_11251)); + DFFX1 \u0_slt7_r_reg[9] (.CK (bit_clk_pad_i), .D (n_11250), .Q + (u0_slt7_r_138), .QN ()); + MX2X1 g29794(.A (n_375), .B (u0_slt7_r_137), .S0 (n_11389), .Y + (n_11250)); + DFFX1 \u0_slt7_r_reg[8] (.CK (bit_clk_pad_i), .D (n_11249), .Q + (u0_slt7_r_137), .QN ()); + MX2X1 g29796(.A (n_265), .B (u0_slt7_r_136), .S0 (n_11319), .Y + (n_11249)); + DFFX1 \u0_slt7_r_reg[7] (.CK (bit_clk_pad_i), .D (n_11248), .Q + (u0_slt7_r_136), .QN ()); + MX2X1 g29798(.A (n_363), .B (u0_slt7_r_135), .S0 (n_11319), .Y + (n_11248)); + DFFX1 \u0_slt7_r_reg[6] (.CK (bit_clk_pad_i), .D (n_11247), .Q + (u0_slt7_r_135), .QN ()); + MX2X1 g29800(.A (n_217), .B (u0_slt7_r_134), .S0 (n_11319), .Y + (n_11247)); + DFFX1 \u0_slt7_r_reg[5] (.CK (bit_clk_pad_i), .D (n_11246), .Q + (u0_slt7_r_134), .QN ()); + MX2X1 g29802(.A (n_201), .B (u0_slt7_r_133), .S0 (n_6710), .Y + (n_11246)); + DFFX1 \u0_slt7_r_reg[4] (.CK (bit_clk_pad_i), .D (n_11245), .Q + (u0_slt7_r_133), .QN ()); + MX2X1 g29804(.A (n_335), .B (u0_slt7_r_132), .S0 (n_11389), .Y + (n_11245)); + DFFX1 \u0_slt7_r_reg[3] (.CK (bit_clk_pad_i), .D (n_11244), .Q + (u0_slt7_r_132), .QN ()); + MX2X1 g29806(.A (n_10988), .B (u0_slt7_r_131), .S0 (n_11389), .Y + (n_11244)); + DFFX1 \u0_slt7_r_reg[2] (.CK (bit_clk_pad_i), .D (n_11243), .Q + (u0_slt7_r_131), .QN ()); + MX2X1 g29808(.A (n_10990), .B (u0_slt7_r_130), .S0 (n_11395), .Y + (n_11243)); + DFFX1 \u0_slt7_r_reg[1] (.CK (bit_clk_pad_i), .D (n_11242), .Q + (u0_slt7_r_130), .QN ()); + MX2X1 g29810(.A (n_22), .B (u0_slt7_r), .S0 (n_11389), .Y (n_11242)); + DFFX1 \u0_slt7_r_reg[0] (.CK (bit_clk_pad_i), .D (n_11241), .Q + (u0_slt7_r), .QN ()); + MX2X1 g29812(.A (n_184), .B (u0_slt8_r_167), .S0 (n_11319), .Y + (n_11241)); + DFFX1 \u0_slt8_r_reg[19] (.CK (bit_clk_pad_i), .D (n_11240), .Q + (u0_slt8_r_167), .QN ()); + MX2X1 g29814(.A (n_328), .B (u0_slt8_r_166), .S0 (n_11319), .Y + (n_11240)); + DFFX1 \u0_slt8_r_reg[18] (.CK (bit_clk_pad_i), .D (n_11239), .Q + (u0_slt8_r_166), .QN ()); + MX2X1 g29816(.A (n_86), .B (u0_slt8_r_165), .S0 (n_11395), .Y + (n_11239)); + DFFX1 \u0_slt8_r_reg[17] (.CK (bit_clk_pad_i), .D (n_11238), .Q + (u0_slt8_r_165), .QN ()); + MX2X1 g29818(.A (n_240), .B (u0_slt8_r_164), .S0 (n_6710), .Y + (n_11238)); + DFFX1 \u0_slt8_r_reg[16] (.CK (bit_clk_pad_i), .D (n_11237), .Q + (u0_slt8_r_164), .QN ()); + MX2X1 g29820(.A (n_79), .B (u0_slt8_r_163), .S0 (n_11319), .Y + (n_11237)); + DFFX1 \u0_slt8_r_reg[15] (.CK (bit_clk_pad_i), .D (n_11236), .Q + (u0_slt8_r_163), .QN ()); + MX2X1 g29822(.A (n_237), .B (u0_slt8_r_162), .S0 (n_11395), .Y + (n_11236)); + DFFX1 \u0_slt8_r_reg[14] (.CK (bit_clk_pad_i), .D (n_11235), .Q + (u0_slt8_r_162), .QN ()); + MX2X1 g29824(.A (n_228), .B (u0_slt8_r_161), .S0 (n_11319), .Y + (n_11235)); + DFFX1 \u0_slt8_r_reg[13] (.CK (bit_clk_pad_i), .D (n_11234), .Q + (u0_slt8_r_161), .QN ()); + MX2X1 g29826(.A (n_76), .B (u0_slt8_r_160), .S0 (n_6710), .Y + (n_11234)); + DFFX1 \u0_slt8_r_reg[12] (.CK (bit_clk_pad_i), .D (n_11233), .Q + (u0_slt8_r_160), .QN ()); + MX2X1 g29828(.A (n_212), .B (u0_slt8_r_159), .S0 (n_11319), .Y + (n_11233)); + DFFX1 \u0_slt8_r_reg[11] (.CK (bit_clk_pad_i), .D (n_11232), .Q + (u0_slt8_r_159), .QN ()); + MX2X1 g29830(.A (n_181), .B (u0_slt8_r_158), .S0 (n_11319), .Y + (n_11232)); + DFFX1 \u0_slt8_r_reg[10] (.CK (bit_clk_pad_i), .D (n_11231), .Q + (u0_slt8_r_158), .QN ()); + MX2X1 g29832(.A (n_167), .B (u0_slt8_r_157), .S0 (n_11389), .Y + (n_11231)); + DFFX1 \u0_slt8_r_reg[9] (.CK (bit_clk_pad_i), .D (n_11230), .Q + (u0_slt8_r_157), .QN ()); + MX2X1 g29834(.A (n_384), .B (u0_slt8_r_156), .S0 (n_11319), .Y + (n_11230)); + DFFX1 \u0_slt8_r_reg[8] (.CK (bit_clk_pad_i), .D (n_11228), .Q + (u0_slt8_r_156), .QN ()); + MX2X1 g29836(.A (n_376), .B (u0_slt8_r_155), .S0 (n_11389), .Y + (n_11228)); + DFFX1 \u0_slt8_r_reg[7] (.CK (bit_clk_pad_i), .D (n_11227), .Q + (u0_slt8_r_155), .QN ()); + MX2X1 g29838(.A (n_362), .B (u0_slt8_r_154), .S0 (n_11319), .Y + (n_11227)); + DFFX1 \u0_slt8_r_reg[6] (.CK (bit_clk_pad_i), .D (n_11225), .Q + (u0_slt8_r_154), .QN ()); + MX2X1 g29840(.A (n_352), .B (u0_slt8_r_153), .S0 (n_11389), .Y + (n_11225)); + DFFX1 \u0_slt8_r_reg[5] (.CK (bit_clk_pad_i), .D (n_11224), .Q + (u0_slt8_r_153), .QN ()); + MX2X1 g29842(.A (n_280), .B (u0_slt8_r_152), .S0 (n_11389), .Y + (n_11224)); + DFFX1 \u0_slt8_r_reg[4] (.CK (bit_clk_pad_i), .D (n_11223), .Q + (u0_slt8_r_152), .QN ()); + MX2X1 g29844(.A (n_182), .B (u0_slt8_r_151), .S0 (n_11389), .Y + (n_11223)); + DFFX1 \u0_slt8_r_reg[3] (.CK (bit_clk_pad_i), .D (n_11221), .Q + (u0_slt8_r_151), .QN ()); + MX2X1 g29846(.A (n_10981), .B (u0_slt8_r_150), .S0 (n_11319), .Y + (n_11221)); + DFFX1 \u0_slt8_r_reg[2] (.CK (bit_clk_pad_i), .D (n_11220), .Q + (u0_slt8_r_150), .QN ()); + MX2X1 g29848(.A (n_10983), .B (u0_slt8_r_149), .S0 (n_11319), .Y + (n_11220)); + DFFX1 \u0_slt8_r_reg[1] (.CK (bit_clk_pad_i), .D (n_11219), .Q + (u0_slt8_r_149), .QN ()); + MX2X1 g29850(.A (n_57), .B (u0_slt8_r), .S0 (n_11389), .Y (n_11219)); + DFFX1 \u0_slt8_r_reg[0] (.CK (bit_clk_pad_i), .D (n_11218), .Q + (u0_slt8_r), .QN ()); + MX2X1 g29852(.A (n_273), .B (u0_slt9_r_186), .S0 (n_11389), .Y + (n_11218)); + DFFX1 \u0_slt9_r_reg[19] (.CK (bit_clk_pad_i), .D (n_11217), .Q + (u0_slt9_r_186), .QN ()); + MX2X1 g29854(.A (n_383), .B (u0_slt9_r_185), .S0 (n_11319), .Y + (n_11217)); + DFFX1 \u0_slt9_r_reg[18] (.CK (bit_clk_pad_i), .D (n_11216), .Q + (u0_slt9_r_185), .QN ()); + MX2X1 g29856(.A (n_19), .B (u0_slt9_r_184), .S0 (n_11319), .Y + (n_11216)); + DFFX1 \u0_slt9_r_reg[17] (.CK (bit_clk_pad_i), .D (n_11215), .Q + (u0_slt9_r_184), .QN ()); + MX2X1 g29858(.A (n_150), .B (u0_slt9_r_183), .S0 (n_7042), .Y + (n_11215)); + DFFX1 \u0_slt9_r_reg[16] (.CK (bit_clk_pad_i), .D (n_11214), .Q + (u0_slt9_r_183), .QN ()); + MX2X1 g29860(.A (n_208), .B (u0_slt9_r_182), .S0 (n_11395), .Y + (n_11214)); + DFFX1 \u0_slt9_r_reg[15] (.CK (bit_clk_pad_i), .D (n_11213), .Q + (u0_slt9_r_182), .QN ()); + MX2X1 g29862(.A (n_297), .B (u0_slt9_r_181), .S0 (n_11319), .Y + (n_11213)); + DFFX1 \u0_slt9_r_reg[14] (.CK (bit_clk_pad_i), .D (n_11212), .Q + (u0_slt9_r_181), .QN ()); + MX2X1 g29864(.A (n_263), .B (u0_slt9_r_180), .S0 (n_11389), .Y + (n_11212)); + DFFX1 \u0_slt9_r_reg[13] (.CK (bit_clk_pad_i), .D (n_11211), .Q + (u0_slt9_r_180), .QN ()); + MX2X1 g29866(.A (n_203), .B (u0_slt9_r_179), .S0 (n_11389), .Y + (n_11211)); + DFFX1 \u0_slt9_r_reg[12] (.CK (bit_clk_pad_i), .D (n_11210), .Q + (u0_slt9_r_179), .QN ()); + MX2X1 g29868(.A (n_152), .B (u0_slt9_r_178), .S0 (n_7042), .Y + (n_11210)); + DFFX1 \u0_slt9_r_reg[11] (.CK (bit_clk_pad_i), .D (n_11209), .Q + (u0_slt9_r_178), .QN ()); + MX2X1 g29870(.A (n_302), .B (u0_slt9_r_177), .S0 (n_6710), .Y + (n_11209)); + DFFX1 \u0_slt9_r_reg[10] (.CK (bit_clk_pad_i), .D (n_11207), .Q + (u0_slt9_r_177), .QN ()); + MX2X1 g29872(.A (n_308), .B (u0_slt9_r_176), .S0 (n_6710), .Y + (n_11207)); + DFFX1 \u0_slt9_r_reg[9] (.CK (bit_clk_pad_i), .D (n_11206), .Q + (u0_slt9_r_176), .QN ()); + MX2X1 g29874(.A (n_183), .B (u0_slt9_r_175), .S0 (n_11389), .Y + (n_11206)); + DFFX1 \u0_slt9_r_reg[8] (.CK (bit_clk_pad_i), .D (n_11205), .Q + (u0_slt9_r_175), .QN ()); + MX2X1 g29876(.A (n_160), .B (u0_slt9_r_174), .S0 (n_11389), .Y + (n_11205)); + DFFX1 \u0_slt9_r_reg[7] (.CK (bit_clk_pad_i), .D (n_11204), .Q + (u0_slt9_r_174), .QN ()); + MX2X1 g29878(.A (n_191), .B (u0_slt9_r_173), .S0 (n_6710), .Y + (n_11204)); + DFFX1 \u0_slt9_r_reg[6] (.CK (bit_clk_pad_i), .D (n_11203), .Q + (u0_slt9_r_173), .QN ()); + DFFX1 \u1_slt2_reg[19] (.CK (bit_clk_pad_i), .D (n_11202), .Q + (in_slt_845), .QN ()); + DFFX1 \u1_slt3_reg[19] (.CK (bit_clk_pad_i), .D (n_11201), .Q + (in_slt_415), .QN ()); + DFFX1 \u1_slt4_reg[19] (.CK (bit_clk_pad_i), .D (n_11200), .Q + (in_slt_437), .QN ()); + DFFX1 \u1_slt6_reg[19] (.CK (bit_clk_pad_i), .D (n_11199), .Q + (in_slt_459), .QN ()); + MX2X1 g29880(.A (n_372), .B (u0_slt9_r_172), .S0 (n_6710), .Y + (n_11203)); + MX2X1 g29896(.A (u1_sr_135), .B (in_slt_845), .S0 (out_le_181), .Y + (n_11202)); + MX2X1 g29897(.A (u1_sr_135), .B (in_slt_415), .S0 (out_le_182), .Y + (n_11201)); + MX2X1 g29898(.A (u1_sr_135), .B (in_slt_437), .S0 (out_le_183), .Y + (n_11200)); + MX2X1 g29899(.A (u1_sr_135), .B (in_slt_459), .S0 (out_le_184), .Y + (n_11199)); + DFFX1 \u1_slt2_reg[18] (.CK (bit_clk_pad_i), .D (n_11198), .Q + (in_slt_844), .QN ()); + DFFX1 \u1_slt3_reg[18] (.CK (bit_clk_pad_i), .D (n_11197), .Q + (in_slt_414), .QN ()); + DFFX1 \u1_slt4_reg[18] (.CK (bit_clk_pad_i), .D (n_11196), .Q + (in_slt_436), .QN ()); + DFFX1 \u1_slt6_reg[18] (.CK (bit_clk_pad_i), .D (n_11195), .Q + (in_slt_458), .QN ()); + DFFSRX1 u16_u1_dma_req_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11194), .Q (dma_req_o[1]), .QN ()); + DFFSRX1 u16_u3_dma_req_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11193), .Q (dma_req_o[3]), .QN ()); + DFFX1 \u0_slt9_r_reg[5] (.CK (bit_clk_pad_i), .D (n_11188), .Q + (u0_slt9_r_172), .QN ()); + DFFSRX1 u16_u0_dma_req_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11192), .Q (dma_req_o[0]), .QN ()); + DFFSRX1 u16_u2_dma_req_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11191), .Q (dma_req_o[2]), .QN ()); + DFFSRX1 u16_u4_dma_req_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11190), .Q (dma_req_o[4]), .QN ()); + DFFSRX1 u16_u5_dma_req_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11189), .Q (dma_req_o[5]), .QN ()); + DFFX1 \u1_slt2_reg[17] (.CK (bit_clk_pad_i), .D (n_11187), .Q + (in_slt_843), .QN ()); + DFFX1 \u1_slt3_reg[17] (.CK (bit_clk_pad_i), .D (n_11186), .Q + (in_slt_413), .QN ()); + DFFX1 \u1_slt4_reg[17] (.CK (bit_clk_pad_i), .D (n_11185), .Q + (in_slt_435), .QN ()); + DFFX1 \u1_slt6_reg[17] (.CK (bit_clk_pad_i), .D (n_11184), .Q + (in_slt_457), .QN ()); + MX2X1 g29910(.A (u1_sr_134), .B (in_slt_844), .S0 (out_le_181), .Y + (n_11198)); + MX2X1 g29911(.A (u1_sr_134), .B (in_slt_414), .S0 (out_le_182), .Y + (n_11197)); + MX2X1 g29912(.A (u1_sr_134), .B (in_slt_436), .S0 (out_le_183), .Y + (n_11196)); + MX2X1 g29913(.A (u1_sr_134), .B (in_slt_458), .S0 (out_le_184), .Y + (n_11195)); + OAI21X1 g29905(.A0 (dma_ack_i[1]), .A1 (n_278), .B0 (n_11183), .Y + (n_11194)); + OAI21X1 g29907(.A0 (dma_ack_i[3]), .A1 (n_118), .B0 (n_11182), .Y + (n_11193)); + DFFX1 \u1_sr_reg[19] (.CK (bit_clk_pad_i), .D (u1_sr_134), .Q + (u1_sr_135), .QN ()); + DFFX1 \u1_slt2_reg[16] (.CK (bit_clk_pad_i), .D (n_11169), .Q + (in_slt_842), .QN ()); + DFFX1 \u1_slt3_reg[16] (.CK (bit_clk_pad_i), .D (n_11168), .Q + (in_slt_412), .QN ()); + DFFX1 \u1_slt4_reg[16] (.CK (bit_clk_pad_i), .D (n_11167), .Q + (in_slt_434), .QN ()); + DFFX1 \u1_slt6_reg[16] (.CK (bit_clk_pad_i), .D (n_11166), .Q + (in_slt_456), .QN ()); + DFFSRX1 \u4_rp_reg[2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11165), .Q (\u4_rp[2] ), .QN ()); + DFFSRX1 \u5_rp_reg[2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11164), .Q (\u5_rp[2] ), .QN ()); + DFFSRX1 \u8_rp_reg[2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11181), .Q (\u8_rp[2] ), .QN ()); + DFFSRX1 \u3_rp_reg[2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11180), .Q (\u3_rp[2] ), .QN ()); + DFFSRX1 \u6_rp_reg[2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11179), .Q (\u6_rp[2] ), .QN ()); + DFFSRX1 \u7_rp_reg[2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11178), .Q (\u7_rp[2] ), .QN ()); + DFFSRX1 \u8_rp_reg[3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_12592), .Q (\u8_rp[3] ), .QN ()); + DFFSRX1 \u3_rp_reg[3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11176), .Q (\u3_rp[3] ), .QN ()); + DFFSRX1 \u6_rp_reg[3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11175), .Q (\u6_rp[3] ), .QN ()); + DFFSRX1 \u7_rp_reg[3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11174), .Q (\u7_rp[3] ), .QN ()); + OAI21X1 g29904(.A0 (dma_ack_i[0]), .A1 (n_271), .B0 (n_11173), .Y + (n_11192)); + OAI21X1 g29906(.A0 (dma_ack_i[2]), .A1 (n_105), .B0 (n_11172), .Y + (n_11191)); + OAI21X1 g29908(.A0 (dma_ack_i[4]), .A1 (n_268), .B0 (n_11171), .Y + (n_11190)); + OAI21X1 g29909(.A0 (dma_ack_i[5]), .A1 (n_284), .B0 (n_11170), .Y + (n_11189)); + MX2X1 g29914(.A (n_359), .B (u0_slt9_r_171), .S0 (n_11319), .Y + (n_11188)); + MX2X1 g29932(.A (u1_sr_133), .B (in_slt_843), .S0 (out_le_181), .Y + (n_11187)); + MX2X1 g29933(.A (u1_sr_133), .B (in_slt_413), .S0 (out_le_182), .Y + (n_11186)); + MX2X1 g29934(.A (u1_sr_133), .B (in_slt_435), .S0 (out_le_183), .Y + (n_11185)); + MX2X1 g29935(.A (u1_sr_133), .B (in_slt_457), .S0 (out_le_184), .Y + (n_11184)); + DFFSRX1 \u8_rp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11163), .Q (\u8_rp[1] ), .QN ()); + DFFSRX1 \u3_rp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11162), .Q (\u3_rp[1] ), .QN ()); + DFFSRX1 \u7_rp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11160), .Q (\u7_rp[1] ), .QN ()); + DFFSRX1 \u6_rp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11161), .Q (\u6_rp[1] ), .QN ()); + NAND2X1 g29927(.A (n_11159), .B (u16_u1_dma_req_r1), .Y (n_11183)); + NAND2X1 g29929(.A (n_11158), .B (u16_u3_dma_req_r1), .Y (n_11182)); + DFFX1 \u1_sr_reg[18] (.CK (bit_clk_pad_i), .D (u1_sr_133), .Q + (u1_sr_134), .QN ()); + NOR2X1 g30045(.A (n_12585), .B (n_11526), .Y (n_11181)); + NOR2X1 g30046(.A (n_11142), .B (n_5839), .Y (n_11180)); + NOR2X1 g30047(.A (n_1870), .B (n_11520), .Y (n_11179)); + NOR2X1 g30048(.A (n_5825), .B (n_11522), .Y (n_11178)); + NOR2X1 g30062(.A (n_11043), .B (n_11505), .Y (n_11176)); + NOR2X1 g30068(.A (n_1870), .B (n_11518), .Y (n_11175)); + NOR2X1 g30069(.A (n_11144), .B (n_11516), .Y (n_11174)); + DFFSRX1 \u13_ints_r_reg[11] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11121), .Q (\u13_ints_r[11] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[5] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11120), .Q (\u13_ints_r[5] ), .QN ()); + DFFX1 \u1_slt3_reg[15] (.CK (bit_clk_pad_i), .D (n_11116), .Q + (in_slt_411), .QN ()); + DFFX1 \u1_slt0_reg[15] (.CK (bit_clk_pad_i), .D (n_11118), .Q + (in_slt_742), .QN ()); + DFFX1 \u1_slt6_reg[15] (.CK (bit_clk_pad_i), .D (n_11114), .Q + (in_slt_455), .QN ()); + DFFX1 \u1_slt2_reg[15] (.CK (bit_clk_pad_i), .D (n_11117), .Q + (in_slt_841), .QN ()); + DFFX1 \u1_slt4_reg[15] (.CK (bit_clk_pad_i), .D (n_11115), .Q + (in_slt_433), .QN ()); + DFFSRX1 \u4_rp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11153), .Q (\u4_rp[1] ), .QN ()); + DFFSRX1 \u4_rp_reg[3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11157), .Q (\u4_rp[3] ), .QN ()); + DFFSRX1 \u5_rp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11152), .Q (\u5_rp[1] ), .QN ()); + DFFSRX1 \u5_rp_reg[3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_11155), .Q (\u5_rp[3] ), .QN ()); + DFFX1 \u6_dout_reg[2] (.CK (clk_i), .D (n_11149), .Q (), .QN + (out_slt_123)); + DFFX1 \u6_dout_reg[3] (.CK (clk_i), .D (n_11148), .Q (), .QN + (out_slt_124)); + DFFX1 \u7_dout_reg[2] (.CK (clk_i), .D (n_11146), .Q (), .QN + (out_slt_142)); + DFFX1 \u7_dout_reg[3] (.CK (clk_i), .D (n_11145), .Q (), .QN + (out_slt_143)); + DFFX1 \u3_dout_reg[2] (.CK (clk_i), .D (n_11135), .Q (), .QN + (out_slt_66)); + DFFX1 \u3_dout_reg[3] (.CK (clk_i), .D (n_11134), .Q (), .QN + (out_slt_67)); + DFFX1 \u8_dout_reg[2] (.CK (clk_i), .D (n_11130), .Q (), .QN + (out_slt_161)); + DFFX1 \u8_dout_reg[3] (.CK (clk_i), .D (n_11129), .Q (), .QN + (out_slt_162)); + NAND2X1 g29926(.A (n_11125), .B (u16_u0_dma_req_r1), .Y (n_11173)); + NAND2X1 g29928(.A (n_11124), .B (u16_u2_dma_req_r1), .Y (n_11172)); + NAND2X1 g29930(.A (n_11123), .B (u16_u4_dma_req_r1), .Y (n_11171)); + NAND2X1 g29931(.A (n_11122), .B (u16_u5_dma_req_r1), .Y (n_11170)); + MX2X1 g29958(.A (u1_sr_132), .B (in_slt_842), .S0 (out_le_181), .Y + (n_11169)); + MX2X1 g29959(.A (u1_sr_132), .B (in_slt_412), .S0 (out_le_182), .Y + (n_11168)); + MX2X1 g29960(.A (u1_sr_132), .B (in_slt_434), .S0 (out_le_183), .Y + (n_11167)); + MX2X1 g29961(.A (u1_sr_132), .B (in_slt_456), .S0 (out_le_184), .Y + (n_11166)); + AND2X1 g30020(.A (n_11151), .B (n_991), .Y (n_11165)); + AND2X1 g30021(.A (n_11150), .B (n_9833), .Y (n_11164)); + AOI21X1 g30070(.A0 (n_11512), .A1 (n_11513), .B0 (n_12585), .Y + (n_11163)); + AOI21X1 g30071(.A0 (n_10397), .A1 (n_11002), .B0 (n_5839), .Y + (n_11162)); + AOI21X1 g30074(.A0 (n_11510), .A1 (n_11511), .B0 (n_1870), .Y + (n_11161)); + AOI21X1 g30075(.A0 (n_11508), .A1 (n_11509), .B0 (n_11144), .Y + (n_11160)); + DFFSRX1 \u13_ints_r_reg[14] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11015), .Q (\u13_ints_r[14] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[17] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11014), .Q (\u13_ints_r[17] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11012), .Q (\u13_ints_r[2] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[8] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11011), .Q (\u13_ints_r[8] ), .QN ()); + DFFX1 \u6_dout_reg[0] (.CK (clk_i), .D (n_11111), .Q (), .QN + (out_slt7)); + DFFX1 \u6_dout_reg[1] (.CK (clk_i), .D (n_11110), .Q (), .QN + (out_slt_122)); + DFFX1 \u7_dout_reg[0] (.CK (clk_i), .D (n_11107), .Q (), .QN + (out_slt8)); + DFFX1 \u7_dout_reg[1] (.CK (clk_i), .D (n_11106), .Q (), .QN + (out_slt_141)); + DFFX1 \u3_dout_reg[0] (.CK (clk_i), .D (n_11103), .Q (), .QN + (out_slt3)); + DFFX1 \u8_dout_reg[0] (.CK (clk_i), .D (n_11102), .Q (), .QN + (out_slt9)); + DFFX1 \u3_dout_reg[1] (.CK (clk_i), .D (n_11101), .Q (), .QN + (out_slt_65)); + DFFX1 \u8_dout_reg[1] (.CK (clk_i), .D (n_11098), .Q (), .QN + (out_slt_160)); + DFFX1 \u8_rp_reg[0] (.CK (clk_i), .D (n_11009), .Q (n_610), .QN ()); + DFFX1 \u3_rp_reg[0] (.CK (clk_i), .D (n_11008), .Q (\u3_rp[0] ), .QN + ()); + DFFX1 \u6_rp_reg[0] (.CK (clk_i), .D (n_11113), .Q (\u6_rp[0] ), .QN + ()); + DFFX1 \u7_rp_reg[0] (.CK (clk_i), .D (n_11112), .Q (\u7_rp[0] ), .QN + ()); + DFFX1 \u6_dout_reg[12] (.CK (clk_i), .D (n_11093), .Q (), .QN + (out_slt_133)); + DFFX1 \u6_dout_reg[13] (.CK (clk_i), .D (n_11092), .Q (), .QN + (out_slt_134)); + DFFX1 \u6_dout_reg[14] (.CK (clk_i), .D (n_11091), .Q (), .QN + (out_slt_135)); + DFFX1 \u6_dout_reg[15] (.CK (clk_i), .D (n_11089), .Q (), .QN + (out_slt_136)); + DFFX1 \u6_dout_reg[10] (.CK (clk_i), .D (n_11095), .Q (), .QN + (out_slt_131)); + DFFX1 \u6_dout_reg[11] (.CK (clk_i), .D (n_11094), .Q (), .QN + (out_slt_132)); + DFFX1 \u6_dout_reg[18] (.CK (clk_i), .D (n_11084), .Q (), .QN + (out_slt_139)); + DFFX1 \u6_dout_reg[19] (.CK (clk_i), .D (n_11082), .Q (), .QN + (out_slt_140)); + DFFX1 \u6_dout_reg[16] (.CK (clk_i), .D (n_11087), .Q (), .QN + (out_slt_137)); + DFFX1 \u6_dout_reg[17] (.CK (clk_i), .D (n_11085), .Q (), .QN + (out_slt_138)); + DFFX1 \u6_dout_reg[4] (.CK (clk_i), .D (n_11081), .Q (), .QN + (out_slt_125)); + DFFX1 \u6_dout_reg[5] (.CK (clk_i), .D (n_11080), .Q (), .QN + (out_slt_126)); + DFFX1 \u6_dout_reg[6] (.CK (clk_i), .D (n_11079), .Q (), .QN + (out_slt_127)); + DFFX1 \u6_dout_reg[7] (.CK (clk_i), .D (n_11078), .Q (), .QN + (out_slt_128)); + DFFX1 \u6_dout_reg[8] (.CK (clk_i), .D (n_11077), .Q (), .QN + (out_slt_129)); + DFFX1 \u6_dout_reg[9] (.CK (clk_i), .D (n_11076), .Q (), .QN + (out_slt_130)); + DFFX1 \u7_dout_reg[10] (.CK (clk_i), .D (n_11075), .Q (), .QN + (out_slt_150)); + DFFX1 \u7_dout_reg[11] (.CK (clk_i), .D (n_11074), .Q (), .QN + (out_slt_151)); + DFFX1 \u7_dout_reg[12] (.CK (clk_i), .D (n_11073), .Q (), .QN + (out_slt_152)); + DFFX1 \u7_dout_reg[13] (.CK (clk_i), .D (n_11072), .Q (), .QN + (out_slt_153)); + DFFX1 \u7_dout_reg[14] (.CK (clk_i), .D (n_11070), .Q (), .QN + (out_slt_154)); + DFFX1 \u7_dout_reg[17] (.CK (clk_i), .D (n_11065), .Q (), .QN + (out_slt_157)); + DFFX1 \u7_dout_reg[15] (.CK (clk_i), .D (n_11068), .Q (), .QN + (out_slt_155)); + DFFX1 \u7_dout_reg[19] (.CK (clk_i), .D (n_11063), .Q (), .QN + (out_slt_159)); + DFFX1 \u7_dout_reg[16] (.CK (clk_i), .D (n_11066), .Q (), .QN + (out_slt_156)); + DFFX1 \u7_dout_reg[18] (.CK (clk_i), .D (n_11064), .Q (), .QN + (out_slt_158)); + DFFX1 \u7_dout_reg[4] (.CK (clk_i), .D (n_11062), .Q (), .QN + (out_slt_144)); + DFFX1 \u7_dout_reg[5] (.CK (clk_i), .D (n_11061), .Q (), .QN + (out_slt_145)); + DFFX1 \u7_dout_reg[6] (.CK (clk_i), .D (n_11060), .Q (), .QN + (out_slt_146)); + DFFX1 \u7_dout_reg[7] (.CK (clk_i), .D (n_11058), .Q (), .QN + (out_slt_147)); + DFFX1 \u7_dout_reg[8] (.CK (clk_i), .D (n_11057), .Q (), .QN + (out_slt_148)); + DFFX1 \u7_dout_reg[9] (.CK (clk_i), .D (n_11056), .Q (), .QN + (out_slt_149)); + DFFX1 \u3_dout_reg[10] (.CK (clk_i), .D (n_11055), .Q (), .QN + (out_slt_74)); + DFFX1 \u3_dout_reg[11] (.CK (clk_i), .D (n_11054), .Q (), .QN + (out_slt_75)); + DFFX1 \u3_dout_reg[13] (.CK (clk_i), .D (n_11052), .Q (), .QN + (out_slt_77)); + DFFX1 \u3_dout_reg[14] (.CK (clk_i), .D (n_11051), .Q (), .QN + (out_slt_78)); + DFFX1 \u3_dout_reg[15] (.CK (clk_i), .D (n_11049), .Q (), .QN + (out_slt_79)); + DFFX1 \u3_dout_reg[16] (.CK (clk_i), .D (n_11047), .Q (), .QN + (out_slt_80)); + DFFX1 \u3_dout_reg[17] (.CK (clk_i), .D (n_11045), .Q (), .QN + (out_slt_81)); + DFFX1 \u3_dout_reg[18] (.CK (clk_i), .D (n_11044), .Q (), .QN + (out_slt_82)); + DFFX1 \u8_dout_reg[10] (.CK (clk_i), .D (n_11042), .Q (), .QN + (out_slt_169)); + DFFX1 \u3_dout_reg[19] (.CK (clk_i), .D (n_11041), .Q (), .QN + (out_slt_83)); + DFFX1 \u8_dout_reg[11] (.CK (clk_i), .D (n_11040), .Q (), .QN + (out_slt_170)); + DFFX1 \u8_dout_reg[12] (.CK (clk_i), .D (n_11039), .Q (), .QN + (out_slt_171)); + DFFX1 \u3_dout_reg[12] (.CK (clk_i), .D (n_11053), .Q (), .QN + (out_slt_76)); + DFFX1 \u8_dout_reg[13] (.CK (clk_i), .D (n_11038), .Q (), .QN + (out_slt_172)); + DFFX1 \u8_dout_reg[14] (.CK (clk_i), .D (n_11037), .Q (), .QN + (out_slt_173)); + DFFX1 \u3_dout_reg[4] (.CK (clk_i), .D (n_11035), .Q (), .QN + (out_slt_68)); + DFFX1 \u8_dout_reg[16] (.CK (clk_i), .D (n_11031), .Q (), .QN + (out_slt_175)); + DFFX1 \u3_dout_reg[6] (.CK (clk_i), .D (n_11028), .Q (), .QN + (out_slt_70)); + DFFX1 \u8_dout_reg[17] (.CK (clk_i), .D (n_11029), .Q (), .QN + (out_slt_176)); + DFFX1 \u3_dout_reg[7] (.CK (clk_i), .D (n_11027), .Q (), .QN + (out_slt_71)); + DFFX1 \u8_dout_reg[18] (.CK (clk_i), .D (n_11026), .Q (), .QN + (out_slt_177)); + DFFX1 \u3_dout_reg[8] (.CK (clk_i), .D (n_11024), .Q (), .QN + (out_slt_72)); + DFFX1 \u8_dout_reg[15] (.CK (clk_i), .D (n_11034), .Q (), .QN + (out_slt_174)); + DFFX1 \u3_dout_reg[5] (.CK (clk_i), .D (n_11032), .Q (), .QN + (out_slt_69)); + DFFX1 \u8_dout_reg[19] (.CK (clk_i), .D (n_11023), .Q (), .QN + (out_slt_178)); + DFFX1 \u3_dout_reg[9] (.CK (clk_i), .D (n_11022), .Q (), .QN + (out_slt_73)); + DFFX1 \u8_dout_reg[4] (.CK (clk_i), .D (n_11021), .Q (), .QN + (out_slt_163)); + DFFX1 \u8_dout_reg[5] (.CK (clk_i), .D (n_11020), .Q (), .QN + (out_slt_164)); + DFFX1 \u8_dout_reg[6] (.CK (clk_i), .D (n_11019), .Q (), .QN + (out_slt_165)); + DFFX1 \u8_dout_reg[7] (.CK (clk_i), .D (n_11018), .Q (), .QN + (out_slt_166)); + DFFX1 \u8_dout_reg[8] (.CK (clk_i), .D (n_11017), .Q (), .QN + (out_slt_167)); + DFFX1 \u8_dout_reg[9] (.CK (clk_i), .D (n_11016), .Q (), .QN + (out_slt_168)); + DFFX1 \u0_slt9_r_reg[4] (.CK (bit_clk_pad_i), .D (n_11010), .Q + (u0_slt9_r_171), .QN ()); + DFFX1 u16_u1_dma_req_r1_reg(.CK (clk_i), .D (n_11159), .Q + (u16_u1_dma_req_r1), .QN ()); + DFFX1 u16_u3_dma_req_r1_reg(.CK (clk_i), .D (n_11158), .Q + (u16_u3_dma_req_r1), .QN ()); + DFFX1 \u1_sr_reg[17] (.CK (bit_clk_pad_i), .D (u1_sr_132), .Q + (u1_sr_133), .QN ()); + AND2X1 g30063(.A (n_10971), .B (n_991), .Y (n_11157)); + AND2X1 g30067(.A (n_10970), .B (n_9833), .Y (n_11155)); + AND2X1 g30072(.A (n_10969), .B (n_991), .Y (n_11153)); + AND2X1 g30073(.A (n_10968), .B (n_9833), .Y (n_11152)); + OAI21X1 g30076(.A0 (n_6328), .A1 (n_10992), .B0 (n_10993), .Y + (n_11151)); + OAI21X1 g30077(.A0 (n_5942), .A1 (n_10985), .B0 (n_10986), .Y + (n_11150)); + NOR2X1 g30838(.A (n_10991), .B (n_11086), .Y (n_11149)); + NOR2X1 g30839(.A (n_10989), .B (n_11086), .Y (n_11148)); + NOR2X1 g30859(.A (n_10984), .B (n_11144), .Y (n_11146)); + NOR2X1 g30860(.A (n_10982), .B (n_11144), .Y (n_11145)); + AOI21X1 g30122(.A0 (n_6836), .A1 (n_12589), .B0 (n_10963), .Y + (n_11526)); + AOI21X1 g30123(.A0 (n_6839), .A1 (n_11136), .B0 (n_10960), .Y + (n_11142)); + AOI21X1 g30124(.A0 (n_7049), .A1 (n_11131), .B0 (n_11007), .Y + (n_11520)); + AOI21X1 g30125(.A0 (n_6842), .A1 (n_11126), .B0 (n_11005), .Y + (n_11522)); + AOI21X1 g30127(.A0 (n_6059), .A1 (n_11136), .B0 (n_10959), .Y + (n_11505)); + NOR2X1 g30880(.A (n_10979), .B (n_5839), .Y (n_11135)); + NOR2X1 g30882(.A (n_10977), .B (n_5839), .Y (n_11134)); + AOI21X1 g30135(.A0 (n_5964), .A1 (n_11131), .B0 (n_11006), .Y + (n_11518)); + NOR2X1 g30895(.A (n_10974), .B (n_11128), .Y (n_11130)); + NOR2X1 g30896(.A (n_10973), .B (n_11128), .Y (n_11129)); + AOI21X1 g30137(.A0 (n_5636), .A1 (n_11126), .B0 (n_11004), .Y + (n_11516)); + DFFSRX1 u16_u8_dma_req_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_11906), .Q (dma_req_o[8]), .QN ()); + DFFX1 \u1_slt3_reg[14] (.CK (bit_clk_pad_i), .D (n_10961), .Q + (in_slt_410), .QN ()); + DFFX1 \u1_slt4_reg[14] (.CK (bit_clk_pad_i), .D (n_10958), .Q + (in_slt_432), .QN ()); + DFFX1 \u1_slt6_reg[14] (.CK (bit_clk_pad_i), .D (n_10957), .Q + (in_slt_454), .QN ()); + DFFX1 \u1_slt2_reg[14] (.CK (bit_clk_pad_i), .D (n_10964), .Q + (in_slt_840), .QN ()); + DFFX1 \u4_dout_reg[3] (.CK (clk_i), .D (n_10998), .Q (), .QN + (out_slt_86)); + DFFX1 \u5_dout_reg[3] (.CK (clk_i), .D (n_10995), .Q (), .QN + (out_slt_105)); + DFFX1 \u5_dout_reg[2] (.CK (clk_i), .D (n_10996), .Q (), .QN + (out_slt_104)); + DFFX1 \u4_dout_reg[2] (.CK (clk_i), .D (n_10999), .Q (), .QN + (out_slt_85)); + DFFX1 u16_u0_dma_req_r1_reg(.CK (clk_i), .D (n_11125), .Q + (u16_u0_dma_req_r1), .QN ()); + DFFX1 u16_u2_dma_req_r1_reg(.CK (clk_i), .D (n_11124), .Q + (u16_u2_dma_req_r1), .QN ()); + DFFX1 u16_u4_dma_req_r1_reg(.CK (clk_i), .D (n_11123), .Q + (u16_u4_dma_req_r1), .QN ()); + DFFX1 u16_u5_dma_req_r1_reg(.CK (clk_i), .D (n_11122), .Q + (u16_u5_dma_req_r1), .QN ()); + AND2X1 g29952(.A (n_10967), .B (n_11119), .Y (n_11121)); + AND2X1 g29956(.A (n_10966), .B (n_11119), .Y (n_11120)); + MX2X1 g29984(.A (in_slt_742), .B (u1_sr_131), .S0 (out_le), .Y + (n_11118)); + MX2X1 g29985(.A (u1_sr_131), .B (in_slt_841), .S0 (out_le_181), .Y + (n_11117)); + MX2X1 g29986(.A (u1_sr_131), .B (in_slt_411), .S0 (out_le_182), .Y + (n_11116)); + MX2X1 g29987(.A (u1_sr_131), .B (in_slt_433), .S0 (out_le_183), .Y + (n_11115)); + MX2X1 g29988(.A (u1_sr_131), .B (in_slt_455), .S0 (out_le_184), .Y + (n_11114)); + NOR2X1 g30720(.A (n_10811), .B (n_11086), .Y (n_11113)); + NOR2X1 g30725(.A (n_10810), .B (n_11144), .Y (n_11112)); + OAI22X1 g30745(.A0 (n_11109), .A1 (n_5556), .B0 (out_slt7), .B1 + (n_11108), .Y (n_11111)); + OAI22X1 g30746(.A0 (n_11109), .A1 (n_5703), .B0 (n_11108), .B1 + (out_slt_122), .Y (n_11110)); + OAI22X1 g30747(.A0 (n_11105), .A1 (n_5697), .B0 (out_slt8), .B1 + (n_11104), .Y (n_11107)); + OAI22X1 g30748(.A0 (n_11105), .A1 (n_5715), .B0 (n_11104), .B1 + (out_slt_141), .Y (n_11106)); + OAI22X1 g30749(.A0 (n_11100), .A1 (n_5686), .B0 (out_slt3), .B1 + (n_11099), .Y (n_11103)); + OAI22X1 g30750(.A0 (n_11097), .A1 (n_5536), .B0 (out_slt9), .B1 + (n_11096), .Y (n_11102)); + DFFX1 \u4_dout_reg[4] (.CK (clk_i), .D (n_10933), .Q (), .QN + (out_slt_87)); + OAI22X1 g30751(.A0 (n_11100), .A1 (n_5676), .B0 (n_11099), .B1 + (out_slt_65), .Y (n_11101)); + OAI22X1 g30752(.A0 (n_11097), .A1 (n_5670), .B0 (n_11096), .B1 + (out_slt_160), .Y (n_11098)); + DFFX1 \u11_wp_reg[3] (.CK (clk_i), .D (n_10900), .Q (\u11_wp[3] ), + .QN ()); + AOI21X1 g30828(.A0 (n_11964), .A1 (n_11965), .B0 (n_11086), .Y + (n_11095)); + AOI21X1 g30829(.A0 (n_11970), .A1 (n_11971), .B0 (n_5827), .Y + (n_11094)); + AOI21X1 g30830(.A0 (n_11968), .A1 (n_11969), .B0 (n_1870), .Y + (n_11093)); + AOI21X1 g30831(.A0 (n_11952), .A1 (n_11953), .B0 (n_11083), .Y + (n_11092)); + AOI21X1 g30832(.A0 (n_11978), .A1 (n_11979), .B0 (n_11083), .Y + (n_11091)); + AOI21X1 g30833(.A0 (n_11954), .A1 (n_11955), .B0 (n_5827), .Y + (n_11089)); + AOI21X1 g30834(.A0 (n_11990), .A1 (n_11991), .B0 (n_11086), .Y + (n_11087)); + AOI21X1 g30835(.A0 (n_11974), .A1 (n_11975), .B0 (n_11083), .Y + (n_11085)); + AOI21X1 g30836(.A0 (n_10636), .A1 (n_10523), .B0 (n_11083), .Y + (n_11084)); + AOI21X1 g30837(.A0 (n_11972), .A1 (n_11973), .B0 (n_5827), .Y + (n_11082)); + AOI21X1 g30840(.A0 (n_11956), .A1 (n_11957), .B0 (n_11083), .Y + (n_11081)); + AOI21X1 g30841(.A0 (n_11958), .A1 (n_11959), .B0 (n_11083), .Y + (n_11080)); + AOI21X1 g30842(.A0 (n_11996), .A1 (n_11997), .B0 (n_11083), .Y + (n_11079)); + AOI21X1 g30843(.A0 (n_11960), .A1 (n_11961), .B0 (n_11083), .Y + (n_11078)); + AOI21X1 g30844(.A0 (n_11962), .A1 (n_11963), .B0 (n_5827), .Y + (n_11077)); + AOI21X1 g30845(.A0 (n_11976), .A1 (n_11977), .B0 (n_11086), .Y + (n_11076)); + AOI21X1 g30846(.A0 (n_10626), .A1 (n_10209), .B0 (n_11069), .Y + (n_11075)); + AOI21X1 g30847(.A0 (n_10625), .A1 (n_10207), .B0 (n_5825), .Y + (n_11074)); + AOI21X1 g30849(.A0 (n_10623), .A1 (n_10206), .B0 (n_11144), .Y + (n_11073)); + AOI21X1 g30851(.A0 (n_10622), .A1 (n_10204), .B0 (n_5825), .Y + (n_11072)); + AOI21X1 g30852(.A0 (n_10621), .A1 (n_10202), .B0 (n_11069), .Y + (n_11070)); + AOI21X1 g30854(.A0 (n_10620), .A1 (n_10201), .B0 (n_11144), .Y + (n_11068)); + AOI21X1 g30855(.A0 (n_10619), .A1 (n_10200), .B0 (n_11059), .Y + (n_11066)); + AOI21X1 g30856(.A0 (n_10618), .A1 (n_10199), .B0 (n_5825), .Y + (n_11065)); + AOI21X1 g30857(.A0 (n_10616), .A1 (n_10198), .B0 (n_11144), .Y + (n_11064)); + AOI21X1 g30858(.A0 (n_10615), .A1 (n_10196), .B0 (n_11144), .Y + (n_11063)); + AOI21X1 g30861(.A0 (n_12193), .A1 (n_12194), .B0 (n_11069), .Y + (n_11062)); + AOI21X1 g30862(.A0 (n_12195), .A1 (n_12196), .B0 (n_11069), .Y + (n_11061)); + AOI21X1 g30863(.A0 (n_12064), .A1 (n_12065), .B0 (n_11059), .Y + (n_11060)); + AOI21X1 g30864(.A0 (n_10609), .A1 (n_12505), .B0 (n_11059), .Y + (n_11058)); + AOI21X1 g30865(.A0 (n_12793), .A1 (n_12794), .B0 (n_11059), .Y + (n_11057)); + AOI21X1 g30866(.A0 (n_10607), .A1 (n_10188), .B0 (n_5825), .Y + (n_11056)); + AOI21X1 g30867(.A0 (n_11743), .A1 (n_11744), .B0 (n_5839), .Y + (n_11055)); + AOI21X1 g30868(.A0 (n_12543), .A1 (n_11746), .B0 (n_5839), .Y + (n_11054)); + AOI21X1 g30869(.A0 (n_11749), .A1 (n_11750), .B0 (n_5839), .Y + (n_11053)); + AOI21X1 g30870(.A0 (n_11919), .A1 (n_11724), .B0 (n_5839), .Y + (n_11052)); + AOI21X1 g30871(.A0 (n_10601), .A1 (n_10504), .B0 (n_5839), .Y + (n_11051)); + AOI21X1 g30872(.A0 (n_10599), .A1 (n_12690), .B0 (n_5839), .Y + (n_11049)); + AOI21X1 g30873(.A0 (n_12453), .A1 (n_12672), .B0 (n_5839), .Y + (n_11047)); + AOI21X1 g30874(.A0 (n_12464), .A1 (n_11748), .B0 (n_11043), .Y + (n_11045)); + AOI21X1 g30875(.A0 (n_10595), .A1 (n_10496), .B0 (n_11043), .Y + (n_11044)); + AOI21X1 g30876(.A0 (n_11633), .A1 (n_11634), .B0 (n_11030), .Y + (n_11042)); + AOI21X1 g30877(.A0 (n_10592), .A1 (n_10493), .B0 (n_5839), .Y + (n_11041)); + AOI21X1 g30878(.A0 (n_11613), .A1 (n_11614), .B0 (n_11033), .Y + (n_11040)); + AOI21X1 g30879(.A0 (n_11615), .A1 (n_11616), .B0 (n_12585), .Y + (n_11039)); + AOI21X1 g30881(.A0 (n_11617), .A1 (n_11618), .B0 (n_11036), .Y + (n_11038)); + AOI21X1 g30883(.A0 (n_11619), .A1 (n_11620), .B0 (n_11036), .Y + (n_11037)); + AOI21X1 g30884(.A0 (n_12062), .A1 (n_12063), .B0 (n_5839), .Y + (n_11035)); + AOI21X1 g30885(.A0 (n_11627), .A1 (n_11628), .B0 (n_11033), .Y + (n_11034)); + AOI21X1 g30886(.A0 (n_11994), .A1 (n_11995), .B0 (n_5839), .Y + (n_11032)); + AOI21X1 g30887(.A0 (n_11621), .A1 (n_11622), .B0 (n_11030), .Y + (n_11031)); + AOI21X1 g30888(.A0 (n_11623), .A1 (n_11624), .B0 (n_11025), .Y + (n_11029)); + AOI21X1 g30889(.A0 (n_11731), .A1 (n_11732), .B0 (n_11043), .Y + (n_11028)); + AOI21X1 g30890(.A0 (n_11733), .A1 (n_11734), .B0 (n_11043), .Y + (n_11027)); + AOI21X1 g30891(.A0 (n_11625), .A1 (n_11626), .B0 (n_11025), .Y + (n_11026)); + AOI21X1 g30892(.A0 (n_11735), .A1 (n_11736), .B0 (n_5839), .Y + (n_11024)); + AOI21X1 g30893(.A0 (n_11629), .A1 (n_11630), .B0 (n_11033), .Y + (n_11023)); + AOI21X1 g30894(.A0 (n_12016), .A1 (n_12017), .B0 (n_5839), .Y + (n_11022)); + AOI21X1 g30897(.A0 (n_11635), .A1 (n_11636), .B0 (n_11036), .Y + (n_11021)); + AOI21X1 g30898(.A0 (n_11992), .A1 (n_11993), .B0 (n_11036), .Y + (n_11020)); + AOI21X1 g30899(.A0 (n_11637), .A1 (n_11638), .B0 (n_11025), .Y + (n_11019)); + AOI21X1 g30900(.A0 (n_11639), .A1 (n_11640), .B0 (n_11025), .Y + (n_11018)); + AOI21X1 g30901(.A0 (n_11631), .A1 (n_11632), .B0 (n_11033), .Y + (n_11017)); + AOI21X1 g30902(.A0 (n_11641), .A1 (n_11642), .B0 (n_11030), .Y + (n_11016)); + DFFSRX1 u16_u6_dma_req_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_12373), .Q (dma_req_o[6]), .QN ()); + DFFSRX1 u16_u7_dma_req_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_12378), .Q (dma_req_o[7]), .QN ()); + DFFX1 \u5_dout_reg[0] (.CK (clk_i), .D (n_10952), .Q (), .QN + (out_slt6)); + DFFX1 \u5_dout_reg[1] (.CK (clk_i), .D (n_10951), .Q (), .QN + (out_slt_103)); + DFFX1 \u4_dout_reg[1] (.CK (clk_i), .D (n_10955), .Q (), .QN + (out_slt_84)); + DFFX1 \u4_dout_reg[0] (.CK (clk_i), .D (n_10956), .Q (), .QN + (out_slt4)); + DFFX1 \u4_rp_reg[0] (.CK (clk_i), .D (n_10807), .Q (\u4_rp[0] ), .QN + ()); + DFFX1 \u5_rp_reg[0] (.CK (clk_i), .D (n_10806), .Q (n_6091), .QN ()); + DFFX1 \u11_mem_reg[0][18] (.CK (clk_i), .D (n_10899), .Q (), .QN + (\u11_mem[0]_167 )); + DFFX1 \u11_mem_reg[0][19] (.CK (clk_i), .D (n_10898), .Q (), .QN + (\u11_mem[0]_168 )); + DFFX1 \u11_mem_reg[1][18] (.CK (clk_i), .D (n_10897), .Q (), .QN + (\u11_mem[1]_136 )); + DFFX1 \u11_mem_reg[1][19] (.CK (clk_i), .D (n_10896), .Q (), .QN + (\u11_mem[1]_137 )); + DFFX1 \u11_mem_reg[1][20] (.CK (clk_i), .D (n_10895), .Q (), .QN + (\u11_mem[1]_138 )); + DFFX1 \u11_mem_reg[1][21] (.CK (clk_i), .D (n_10894), .Q (), .QN + (\u11_mem[1]_139 )); + DFFX1 \u11_mem_reg[1][22] (.CK (clk_i), .D (n_10893), .Q (), .QN + (\u11_mem[1]_140 )); + DFFX1 \u11_mem_reg[1][23] (.CK (clk_i), .D (n_10892), .Q (), .QN + (\u11_mem[1]_141 )); + DFFX1 \u11_mem_reg[1][24] (.CK (clk_i), .D (n_10890), .Q (), .QN + (\u11_mem[1]_142 )); + DFFX1 \u11_mem_reg[1][25] (.CK (clk_i), .D (n_10888), .Q (), .QN + (\u11_mem[1]_143 )); + DFFX1 \u11_mem_reg[1][26] (.CK (clk_i), .D (n_10886), .Q (), .QN + (\u11_mem[1]_144 )); + DFFX1 \u11_mem_reg[1][27] (.CK (clk_i), .D (n_10885), .Q (), .QN + (\u11_mem[1]_145 )); + DFFX1 \u11_mem_reg[1][28] (.CK (clk_i), .D (n_10884), .Q (), .QN + (\u11_mem[1]_146 )); + DFFX1 \u11_mem_reg[1][29] (.CK (clk_i), .D (n_10882), .Q (), .QN + (\u11_mem[1]_147 )); + DFFX1 \u11_mem_reg[1][30] (.CK (clk_i), .D (n_10881), .Q (), .QN + (\u11_mem[1]_148 )); + DFFX1 \u11_mem_reg[1][31] (.CK (clk_i), .D (n_10879), .Q (), .QN + (\u11_mem[1]_149 )); + DFFX1 \u11_mem_reg[2][18] (.CK (clk_i), .D (n_10877), .Q (), .QN + (\u11_mem[2]_105 )); + DFFX1 \u11_mem_reg[2][19] (.CK (clk_i), .D (n_10876), .Q (), .QN + (\u11_mem[2]_106 )); + DFFX1 \u11_mem_reg[2][20] (.CK (clk_i), .D (n_10875), .Q (), .QN + (\u11_mem[2]_107 )); + DFFX1 \u11_mem_reg[2][21] (.CK (clk_i), .D (n_10873), .Q (), .QN + (\u11_mem[2]_108 )); + DFFX1 \u11_mem_reg[2][22] (.CK (clk_i), .D (n_10872), .Q (), .QN + (\u11_mem[2]_109 )); + DFFX1 \u11_mem_reg[2][23] (.CK (clk_i), .D (n_10870), .Q (), .QN + (\u11_mem[2]_110 )); + DFFX1 \u11_mem_reg[2][24] (.CK (clk_i), .D (n_10868), .Q (), .QN + (\u11_mem[2]_111 )); + DFFX1 \u11_mem_reg[2][25] (.CK (clk_i), .D (n_10867), .Q (), .QN + (\u11_mem[2]_112 )); + DFFX1 \u11_mem_reg[2][26] (.CK (clk_i), .D (n_10866), .Q (), .QN + (\u11_mem[2]_113 )); + DFFX1 \u11_mem_reg[2][27] (.CK (clk_i), .D (n_10864), .Q (), .QN + (\u11_mem[2]_114 )); + DFFX1 \u11_mem_reg[2][28] (.CK (clk_i), .D (n_10863), .Q (), .QN + (\u11_mem[2]_115 )); + DFFX1 \u11_mem_reg[2][29] (.CK (clk_i), .D (n_10862), .Q (), .QN + (\u11_mem[2]_116 )); + DFFX1 \u11_mem_reg[2][30] (.CK (clk_i), .D (n_10860), .Q (), .QN + (\u11_mem[2]_117 )); + DFFX1 \u11_mem_reg[2][31] (.CK (clk_i), .D (n_10859), .Q (), .QN + (\u11_mem[2]_118 )); + DFFX1 \u11_mem_reg[3][18] (.CK (clk_i), .D (n_10858), .Q (), .QN + (\u11_mem[3]_74 )); + DFFX1 \u11_mem_reg[3][19] (.CK (clk_i), .D (n_10857), .Q (), .QN + (\u11_mem[3]_75 )); + DFFX1 \u11_mem_reg[3][20] (.CK (clk_i), .D (n_10856), .Q (), .QN + (\u11_mem[3]_76 )); + DFFX1 \u11_mem_reg[3][21] (.CK (clk_i), .D (n_10855), .Q (), .QN + (\u11_mem[3]_77 )); + DFFX1 \u11_mem_reg[3][22] (.CK (clk_i), .D (n_10854), .Q (), .QN + (\u11_mem[3]_78 )); + DFFX1 \u11_mem_reg[3][23] (.CK (clk_i), .D (n_10853), .Q (), .QN + (\u11_mem[3]_79 )); + DFFX1 \u11_mem_reg[3][24] (.CK (clk_i), .D (n_10852), .Q (), .QN + (\u11_mem[3]_80 )); + DFFX1 \u11_mem_reg[3][25] (.CK (clk_i), .D (n_10851), .Q (), .QN + (\u11_mem[3]_81 )); + DFFX1 \u11_mem_reg[3][26] (.CK (clk_i), .D (n_10850), .Q (), .QN + (\u11_mem[3]_82 )); + DFFX1 \u11_mem_reg[3][27] (.CK (clk_i), .D (n_10849), .Q (), .QN + (\u11_mem[3]_83 )); + DFFX1 \u11_mem_reg[3][28] (.CK (clk_i), .D (n_10848), .Q (), .QN + (\u11_mem[3]_84 )); + DFFX1 \u11_mem_reg[3][29] (.CK (clk_i), .D (n_10847), .Q (), .QN + (\u11_mem[3]_85 )); + DFFX1 \u11_mem_reg[3][30] (.CK (clk_i), .D (n_10846), .Q (), .QN + (\u11_mem[3]_86 )); + DFFX1 \u11_mem_reg[3][31] (.CK (clk_i), .D (n_10845), .Q (), .QN + (\u11_mem[3]_87 )); + DFFX1 \u11_mem_reg[3][7] (.CK (clk_i), .D (n_10827), .Q (), .QN + (\u11_mem[3]_63 )); + DFFX1 \u11_mem_reg[1][12] (.CK (clk_i), .D (n_10844), .Q (), .QN + (\u11_mem[1]_130 )); + DFFX1 \u11_mem_reg[1][13] (.CK (clk_i), .D (n_10843), .Q (), .QN + (\u11_mem[1]_131 )); + DFFX1 \u11_mem_reg[1][16] (.CK (clk_i), .D (n_10842), .Q (), .QN + (\u11_mem[1]_134 )); + DFFX1 \u11_mem_reg[2][17] (.CK (clk_i), .D (n_10841), .Q (), .QN + (\u11_mem[2]_104 )); + DFFX1 \u11_mem_reg[2][1] (.CK (clk_i), .D (n_10840), .Q (), .QN + (\u11_mem[2]_88 )); + DFFX1 \u11_mem_reg[2][7] (.CK (clk_i), .D (n_10838), .Q (), .QN + (\u11_mem[2]_94 )); + DFFX1 \u11_mem_reg[2][8] (.CK (clk_i), .D (n_10837), .Q (), .QN + (\u11_mem[2]_95 )); + DFFX1 \u11_mem_reg[3][16] (.CK (clk_i), .D (n_10836), .Q (), .QN + (\u11_mem[3]_72 )); + DFFX1 \u11_mem_reg[3][17] (.CK (clk_i), .D (n_10834), .Q (), .QN + (\u11_mem[3]_73 )); + DFFX1 \u11_mem_reg[3][5] (.CK (clk_i), .D (n_10829), .Q (), .QN + (\u11_mem[3]_61 )); + DFFX1 \u11_mem_reg[3][6] (.CK (clk_i), .D (n_10828), .Q (), .QN + (\u11_mem[3]_62 )); + DFFX1 \u11_wp_reg[1] (.CK (clk_i), .D (n_10902), .Q (\u11_wp[1] ), + .QN ()); + DFFX1 \u11_wp_reg[2] (.CK (clk_i), .D (n_10948), .Q (\u11_wp[2] ), + .QN ()); + DFFX1 \u4_dout_reg[10] (.CK (clk_i), .D (n_10947), .Q (), .QN + (out_slt_93)); + DFFX1 \u4_dout_reg[13] (.CK (clk_i), .D (n_10943), .Q (), .QN + (out_slt_96)); + DFFX1 \u4_dout_reg[14] (.CK (clk_i), .D (n_10942), .Q (), .QN + (out_slt_97)); + DFFX1 \u4_dout_reg[15] (.CK (clk_i), .D (n_10941), .Q (), .QN + (out_slt_98)); + DFFX1 \u4_dout_reg[16] (.CK (clk_i), .D (n_10939), .Q (), .QN + (out_slt_99)); + DFFX1 \u4_dout_reg[11] (.CK (clk_i), .D (n_10946), .Q (), .QN + (out_slt_94)); + DFFX1 \u4_dout_reg[18] (.CK (clk_i), .D (n_10935), .Q (), .QN + (out_slt_101)); + DFFX1 \u4_dout_reg[12] (.CK (clk_i), .D (n_10944), .Q (), .QN + (out_slt_95)); + DFFX1 \u4_dout_reg[19] (.CK (clk_i), .D (n_10934), .Q (), .QN + (out_slt_102)); + DFFX1 \u4_dout_reg[17] (.CK (clk_i), .D (n_10937), .Q (), .QN + (out_slt_100)); + DFFX1 \u4_dout_reg[5] (.CK (clk_i), .D (n_10932), .Q (), .QN + (out_slt_88)); + DFFX1 \u4_dout_reg[6] (.CK (clk_i), .D (n_10931), .Q (), .QN + (out_slt_89)); + DFFX1 \u4_dout_reg[7] (.CK (clk_i), .D (n_10930), .Q (), .QN + (out_slt_90)); + DFFX1 \u4_dout_reg[8] (.CK (clk_i), .D (n_10929), .Q (), .QN + (out_slt_91)); + DFFX1 \u4_dout_reg[9] (.CK (clk_i), .D (n_10928), .Q (), .QN + (out_slt_92)); + DFFX1 \u5_dout_reg[10] (.CK (clk_i), .D (n_10927), .Q (), .QN + (out_slt_112)); + DFFX1 \u5_dout_reg[11] (.CK (clk_i), .D (n_10926), .Q (), .QN + (out_slt_113)); + DFFX1 \u5_dout_reg[12] (.CK (clk_i), .D (n_10924), .Q (), .QN + (out_slt_114)); + DFFX1 \u5_dout_reg[14] (.CK (clk_i), .D (n_10922), .Q (), .QN + (out_slt_116)); + DFFX1 \u5_dout_reg[15] (.CK (clk_i), .D (n_10920), .Q (), .QN + (out_slt_117)); + DFFX1 \u5_dout_reg[16] (.CK (clk_i), .D (n_10919), .Q (), .QN + (out_slt_118)); + DFFX1 \u5_dout_reg[18] (.CK (clk_i), .D (n_10915), .Q (), .QN + (out_slt_120)); + DFFX1 \u5_dout_reg[19] (.CK (clk_i), .D (n_10914), .Q (), .QN + (out_slt_121)); + DFFX1 \u5_dout_reg[4] (.CK (clk_i), .D (n_10913), .Q (), .QN + (out_slt_106)); + DFFX1 \u5_dout_reg[5] (.CK (clk_i), .D (n_10912), .Q (), .QN + (out_slt_107)); + DFFX1 \u5_dout_reg[6] (.CK (clk_i), .D (n_10911), .Q (), .QN + (out_slt_108)); + DFFX1 \u5_dout_reg[8] (.CK (clk_i), .D (n_10909), .Q (), .QN + (out_slt_110)); + DFFX1 \u5_dout_reg[9] (.CK (clk_i), .D (n_10908), .Q (), .QN + (out_slt_111)); + DFFX1 \u11_mem_reg[0][0] (.CK (clk_i), .D (n_10821), .Q (), .QN + (\u11_mem[0] )); + DFFX1 \u11_mem_reg[0][10] (.CK (clk_i), .D (n_10819), .Q (), .QN + (\u11_mem[0]_159 )); + DFFX1 \u11_mem_reg[0][11] (.CK (clk_i), .D (n_10818), .Q (), .QN + (\u11_mem[0]_160 )); + DFFX1 \u11_mem_reg[0][12] (.CK (clk_i), .D (n_10815), .Q (), .QN + (\u11_mem[0]_161 )); + DFFX1 \u11_mem_reg[0][13] (.CK (clk_i), .D (n_10817), .Q (), .QN + (\u11_mem[0]_162 )); + DFFX1 \u11_mem_reg[0][14] (.CK (clk_i), .D (n_10814), .Q (), .QN + (\u11_mem[0]_163 )); + DFFX1 \u11_mem_reg[0][15] (.CK (clk_i), .D (n_10813), .Q (), .QN + (\u11_mem[0]_164 )); + DFFX1 \u11_mem_reg[0][1] (.CK (clk_i), .D (n_10812), .Q (), .QN + (\u11_mem[0]_150 )); + DFFSRX1 u15_crac_rd_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10903), .Q (u15_crac_rd), .QN ()); + DFFSRX1 \u17_int_set_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10907), .Q (), .QN (oc0_int_set_707)); + DFFSRX1 \u20_int_set_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10906), .Q (), .QN (oc3_int_set_713)); + DFFSRX1 \u21_int_set_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10905), .Q (), .QN (oc4_int_set_715)); + DFFSRX1 \u22_int_set_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10904), .Q (), .QN (oc5_int_set_717)); + AND2X1 g29953(.A (n_10833), .B (n_11119), .Y (n_11015)); + AND2X1 g29954(.A (n_10832), .B (n_11119), .Y (n_11014)); + AND2X1 g29955(.A (n_10831), .B (n_11119), .Y (n_11012)); + AND2X1 g29957(.A (n_10830), .B (n_11119), .Y (n_11011)); + DFFX1 \u5_dout_reg[7] (.CK (clk_i), .D (n_10910), .Q (), .QN + (out_slt_109)); + NOR2X1 g29976(.A (n_10809), .B (dma_ack_i[1]), .Y (n_11159)); + DFFX1 \u5_dout_reg[17] (.CK (clk_i), .D (n_10917), .Q (), .QN + (out_slt_119)); + NOR2X1 g29978(.A (n_10808), .B (dma_ack_i[3]), .Y (n_11158)); + MX2X1 g29989(.A (n_322), .B (u0_slt9_r_170), .S0 (n_11319), .Y + (n_11010)); + DFFX1 \u1_sr_reg[16] (.CK (bit_clk_pad_i), .D (u1_sr_131), .Q + (u1_sr_132), .QN ()); + DFFX1 \u5_dout_reg[13] (.CK (clk_i), .D (n_10923), .Q (), .QN + (out_slt_115)); + NOR2X1 g30708(.A (n_10825), .B (n_11128), .Y (n_11009)); + NOR2X1 g30711(.A (n_10822), .B (n_5839), .Y (n_11008)); + NOR2X1 g30721(.A (n_10774), .B (n_11131), .Y (n_11007)); + DFFX1 \u10_mem_reg[0][18] (.CK (clk_i), .D (n_10678), .Q (), .QN + (\u10_mem[0]_167 )); + NOR2X1 g30722(.A (n_10659), .B (n_11131), .Y (n_11006)); + NOR2X1 g30726(.A (n_10773), .B (n_11126), .Y (n_11005)); + DFFX1 \u10_mem_reg[3][28] (.CK (clk_i), .D (n_10684), .Q (), .QN + (\u10_mem[3]_84 )); + NOR2X1 g30727(.A (n_10657), .B (n_11126), .Y (n_11004)); + OR2X1 g30728(.A (n_10405), .B (n_12589), .Y (n_11512)); + OR2X1 g30729(.A (n_10404), .B (n_11136), .Y (n_11002)); + DFFX1 \u10_mem_reg[3][24] (.CK (clk_i), .D (n_10690), .Q (), .QN + (\u10_mem[3]_80 )); + OR2X1 g30730(.A (n_10403), .B (n_11131), .Y (n_11510)); + OR2X1 g30731(.A (n_10402), .B (n_11126), .Y (n_11508)); + DFFX1 \u9_mem_reg[3][30] (.CK (clk_i), .D (n_10701), .Q (), .QN + (\u9_mem[3]_86 )); + DFFX1 \u9_mem_reg[3][26] (.CK (clk_i), .D (n_10705), .Q (), .QN + (\u9_mem[3]_82 )); + DFFX1 \u10_wp_reg[3] (.CK (clk_i), .D (n_10778), .Q (\u10_wp[3] ), + .QN ()); + DFFX1 \u9_mem_reg[3][22] (.CK (clk_i), .D (n_10709), .Q (), .QN + (\u9_mem[3]_78 )); + DFFX1 \u9_mem_reg[2][28] (.CK (clk_i), .D (n_10718), .Q (), .QN + (\u9_mem[2]_115 )); + DFFX1 \u9_mem_reg[2][24] (.CK (clk_i), .D (n_10723), .Q (), .QN + (\u9_mem[2]_111 )); + DFFX1 \u9_mem_reg[2][20] (.CK (clk_i), .D (n_10730), .Q (), .QN + (\u9_mem[2]_107 )); + NOR2X1 g30801(.A (n_10791), .B (n_10940), .Y (n_10999)); + NOR2X1 g30802(.A (n_10789), .B (n_10940), .Y (n_10998)); + DFFX1 \u9_mem_reg[1][28] (.CK (clk_i), .D (n_10742), .Q (), .QN + (\u9_mem[1]_146 )); + DFFX1 \u9_mem_reg[1][25] (.CK (clk_i), .D (n_10746), .Q (), .QN + (\u9_mem[1]_143 )); + DFFX1 \u9_mem_reg[1][22] (.CK (clk_i), .D (n_10751), .Q (), .QN + (\u9_mem[1]_140 )); + NOR2X1 g30820(.A (n_10786), .B (n_10994), .Y (n_10996)); + DFFX1 \u10_mem_reg[2][24] (.CK (clk_i), .D (n_10763), .Q (), .QN + (\u10_mem[2]_111 )); + NOR2X1 g30821(.A (n_10784), .B (n_10994), .Y (n_10995)); + DFFX1 \u11_mem_reg[3][14] (.CK (clk_i), .D (n_10457), .Q (), .QN + (\u11_mem[3]_70 )); + NAND3X1 g30108(.A (n_10992), .B (n_9998), .C (n_10332), .Y (n_10993)); + AOI21X1 g31790(.A0 (n_10990), .A1 (n_9876), .B0 (n_10634), .Y + (n_10991)); + AOI21X1 g31791(.A0 (n_10988), .A1 (n_9876), .B0 (n_10633), .Y + (n_10989)); + NAND3X1 g30112(.A (n_10985), .B (n_9996), .C (n_10331), .Y (n_10986)); + AOI21X1 g31799(.A0 (n_10983), .A1 (n_10617), .B0 (n_10614), .Y + (n_10984)); + AOI21X1 g31800(.A0 (n_10981), .A1 (n_10617), .B0 (n_10613), .Y + (n_10982)); + AOI21X1 g31802(.A0 (n_10978), .A1 (n_10605), .B0 (n_10589), .Y + (n_10979)); + AOI21X1 g31803(.A0 (n_10976), .A1 (n_10605), .B0 (n_10587), .Y + (n_10977)); + AOI21X1 g31804(.A0 (n_9602), .A1 (n_9873), .B0 (n_10574), .Y + (n_10974)); + AOI21X1 g31805(.A0 (n_9952), .A1 (n_9873), .B0 (n_10573), .Y + (n_10973)); + DFFX1 \u11_mem_reg[3][0] (.CK (clk_i), .D (n_10472), .Q (), .QN + (\u11_mem[3] )); + DFFX1 \u11_mem_reg[3][13] (.CK (clk_i), .D (n_10458), .Q (), .QN + (\u11_mem[3]_69 )); + DFFX1 \u10_mem_reg[1][0] (.CK (clk_i), .D (n_10544), .Q (), .QN + (\u10_mem[1] )); + MX2X1 g30128(.A (n_7010), .B (n_10330), .S0 (n_10992), .Y (n_10971)); + MX2X1 g30129(.A (n_6756), .B (n_10328), .S0 (n_10985), .Y (n_10970)); + DFFX1 \u11_mem_reg[1][15] (.CK (clk_i), .D (n_10558), .Q (), .QN + (\u11_mem[1]_133 )); + DFFX1 \u11_mem_reg[1][6] (.CK (clk_i), .D (n_10547), .Q (), .QN + (\u11_mem[1]_124 )); + MX2X1 g30138(.A (n_4801), .B (n_10095), .S0 (n_10992), .Y (n_10969)); + MX2X1 g30139(.A (n_2594), .B (n_10094), .S0 (n_10985), .Y (n_10968)); + DFFX1 \u1_slt2_reg[13] (.CK (bit_clk_pad_i), .D (n_10804), .Q + (in_slt_839), .QN ()); + DFFX1 \u1_slt4_reg[13] (.CK (bit_clk_pad_i), .D (n_10802), .Q + (in_slt_431), .QN ()); + DFFX1 \u1_slt6_reg[13] (.CK (bit_clk_pad_i), .D (n_10800), .Q + (in_slt_453), .QN ()); + DFFX1 \u1_slt3_reg[13] (.CK (bit_clk_pad_i), .D (n_10803), .Q + (in_slt_409), .QN ()); + DFFX1 \u10_mem_reg[2][18] (.CK (clk_i), .D (n_10772), .Q (), .QN + (\u10_mem[2]_105 )); + DFFX1 \u10_mem_reg[2][19] (.CK (clk_i), .D (n_10771), .Q (), .QN + (\u10_mem[2]_106 )); + DFFX1 \u10_mem_reg[2][20] (.CK (clk_i), .D (n_10770), .Q (), .QN + (\u10_mem[2]_107 )); + DFFX1 \u10_mem_reg[2][21] (.CK (clk_i), .D (n_10769), .Q (), .QN + (\u10_mem[2]_108 )); + DFFX1 \u10_mem_reg[2][22] (.CK (clk_i), .D (n_10768), .Q (), .QN + (\u10_mem[2]_109 )); + DFFX1 \u9_mem_reg[0][18] (.CK (clk_i), .D (n_10765), .Q (), .QN + (\u9_mem[0]_167 )); + DFFX1 \u9_mem_reg[0][19] (.CK (clk_i), .D (n_10764), .Q (), .QN + (\u9_mem[0]_168 )); + DFFX1 \u10_mem_reg[2][23] (.CK (clk_i), .D (n_10766), .Q (), .QN + (\u10_mem[2]_110 )); + DFFX1 \u10_mem_reg[2][25] (.CK (clk_i), .D (n_10762), .Q (), .QN + (\u10_mem[2]_112 )); + DFFX1 \u10_mem_reg[2][26] (.CK (clk_i), .D (n_10760), .Q (), .QN + (\u10_mem[2]_113 )); + DFFX1 \u10_mem_reg[2][27] (.CK (clk_i), .D (n_10758), .Q (), .QN + (\u10_mem[2]_114 )); + DFFX1 \u9_mem_reg[1][18] (.CK (clk_i), .D (n_10756), .Q (), .QN + (\u9_mem[1]_136 )); + DFFX1 \u9_mem_reg[1][19] (.CK (clk_i), .D (n_10755), .Q (), .QN + (\u9_mem[1]_137 )); + DFFX1 \u9_mem_reg[1][20] (.CK (clk_i), .D (n_10754), .Q (), .QN + (\u9_mem[1]_138 )); + DFFX1 \u9_mem_reg[1][21] (.CK (clk_i), .D (n_10753), .Q (), .QN + (\u9_mem[1]_139 )); + DFFX1 \u10_mem_reg[2][28] (.CK (clk_i), .D (n_10757), .Q (), .QN + (\u10_mem[2]_115 )); + DFFX1 \u9_mem_reg[1][23] (.CK (clk_i), .D (n_10750), .Q (), .QN + (\u9_mem[1]_141 )); + DFFX1 \u9_mem_reg[1][24] (.CK (clk_i), .D (n_10748), .Q (), .QN + (\u9_mem[1]_142 )); + DFFX1 \u9_mem_reg[1][26] (.CK (clk_i), .D (n_10744), .Q (), .QN + (\u9_mem[1]_144 )); + DFFX1 \u10_mem_reg[2][29] (.CK (clk_i), .D (n_10752), .Q (), .QN + (\u10_mem[2]_116 )); + DFFX1 \u9_mem_reg[1][27] (.CK (clk_i), .D (n_10743), .Q (), .QN + (\u9_mem[1]_145 )); + DFFX1 \u9_mem_reg[1][29] (.CK (clk_i), .D (n_10740), .Q (), .QN + (\u9_mem[1]_147 )); + DFFX1 \u9_mem_reg[1][30] (.CK (clk_i), .D (n_10739), .Q (), .QN + (\u9_mem[1]_148 )); + DFFX1 \u9_mem_reg[1][31] (.CK (clk_i), .D (n_10737), .Q (), .QN + (\u9_mem[1]_149 )); + DFFX1 \u10_mem_reg[2][30] (.CK (clk_i), .D (n_10735), .Q (), .QN + (\u10_mem[2]_117 )); + DFFX1 \u9_mem_reg[2][18] (.CK (clk_i), .D (n_10732), .Q (), .QN + (\u9_mem[2]_105 )); + DFFX1 \u9_mem_reg[2][19] (.CK (clk_i), .D (n_10731), .Q (), .QN + (\u9_mem[2]_106 )); + DFFX1 \u10_mem_reg[2][31] (.CK (clk_i), .D (n_10733), .Q (), .QN + (\u10_mem[2]_118 )); + DFFX1 \u9_mem_reg[2][21] (.CK (clk_i), .D (n_10728), .Q (), .QN + (\u9_mem[2]_108 )); + DFFX1 \u9_mem_reg[2][22] (.CK (clk_i), .D (n_10727), .Q (), .QN + (\u9_mem[2]_109 )); + DFFX1 \u9_mem_reg[2][23] (.CK (clk_i), .D (n_10725), .Q (), .QN + (\u9_mem[2]_110 )); + DFFX1 \u9_mem_reg[2][25] (.CK (clk_i), .D (n_10722), .Q (), .QN + (\u9_mem[2]_112 )); + DFFX1 \u9_mem_reg[2][26] (.CK (clk_i), .D (n_10721), .Q (), .QN + (\u9_mem[2]_113 )); + DFFX1 \u9_mem_reg[2][27] (.CK (clk_i), .D (n_10719), .Q (), .QN + (\u9_mem[2]_114 )); + DFFX1 \u9_mem_reg[2][29] (.CK (clk_i), .D (n_10717), .Q (), .QN + (\u9_mem[2]_116 )); + DFFX1 \u9_mem_reg[2][30] (.CK (clk_i), .D (n_10715), .Q (), .QN + (\u9_mem[2]_117 )); + DFFX1 \u9_mem_reg[2][31] (.CK (clk_i), .D (n_10714), .Q (), .QN + (\u9_mem[2]_118 )); + DFFX1 \u9_mem_reg[3][18] (.CK (clk_i), .D (n_10713), .Q (), .QN + (\u9_mem[3]_74 )); + DFFX1 \u9_mem_reg[3][19] (.CK (clk_i), .D (n_10712), .Q (), .QN + (\u9_mem[3]_75 )); + DFFX1 \u9_mem_reg[3][20] (.CK (clk_i), .D (n_10711), .Q (), .QN + (\u9_mem[3]_76 )); + DFFX1 \u9_mem_reg[3][21] (.CK (clk_i), .D (n_10710), .Q (), .QN + (\u9_mem[3]_77 )); + DFFX1 \u9_mem_reg[3][23] (.CK (clk_i), .D (n_10708), .Q (), .QN + (\u9_mem[3]_79 )); + DFFX1 \u9_mem_reg[3][24] (.CK (clk_i), .D (n_10707), .Q (), .QN + (\u9_mem[3]_80 )); + DFFX1 \u9_mem_reg[3][25] (.CK (clk_i), .D (n_10706), .Q (), .QN + (\u9_mem[3]_81 )); + DFFX1 \u9_mem_reg[3][27] (.CK (clk_i), .D (n_10704), .Q (), .QN + (\u9_mem[3]_83 )); + DFFX1 \u9_mem_reg[3][28] (.CK (clk_i), .D (n_10703), .Q (), .QN + (\u9_mem[3]_84 )); + DFFX1 \u9_mem_reg[3][29] (.CK (clk_i), .D (n_10702), .Q (), .QN + (\u9_mem[3]_85 )); + DFFX1 \u9_mem_reg[3][31] (.CK (clk_i), .D (n_10700), .Q (), .QN + (\u9_mem[3]_87 )); + DFFX1 \u10_mem_reg[3][18] (.CK (clk_i), .D (n_10699), .Q (), .QN + (\u10_mem[3]_74 )); + DFFX1 \u10_mem_reg[3][19] (.CK (clk_i), .D (n_10697), .Q (), .QN + (\u10_mem[3]_75 )); + DFFX1 \u10_mem_reg[3][20] (.CK (clk_i), .D (n_10695), .Q (), .QN + (\u10_mem[3]_76 )); + DFFX1 \u10_mem_reg[3][21] (.CK (clk_i), .D (n_10694), .Q (), .QN + (\u10_mem[3]_77 )); + DFFX1 \u10_mem_reg[3][22] (.CK (clk_i), .D (n_10693), .Q (), .QN + (\u10_mem[3]_78 )); + DFFX1 \u10_mem_reg[3][23] (.CK (clk_i), .D (n_10691), .Q (), .QN + (\u10_mem[3]_79 )); + DFFX1 \u10_mem_reg[3][25] (.CK (clk_i), .D (n_10688), .Q (), .QN + (\u10_mem[3]_81 )); + DFFX1 \u10_mem_reg[3][26] (.CK (clk_i), .D (n_10686), .Q (), .QN + (\u10_mem[3]_82 )); + DFFX1 \u10_mem_reg[3][27] (.CK (clk_i), .D (n_10685), .Q (), .QN + (\u10_mem[3]_83 )); + DFFX1 \u10_mem_reg[3][29] (.CK (clk_i), .D (n_10682), .Q (), .QN + (\u10_mem[3]_85 )); + DFFX1 \u10_mem_reg[3][30] (.CK (clk_i), .D (n_10681), .Q (), .QN + (\u10_mem[3]_86 )); + DFFX1 \u10_mem_reg[3][31] (.CK (clk_i), .D (n_10680), .Q (), .QN + (\u10_mem[3]_87 )); + DFFX1 \u10_mem_reg[0][19] (.CK (clk_i), .D (n_10677), .Q (), .QN + (\u10_mem[0]_168 )); + DFFX1 \u10_mem_reg[1][18] (.CK (clk_i), .D (n_10676), .Q (), .QN + (\u10_mem[1]_136 )); + DFFX1 \u10_mem_reg[1][19] (.CK (clk_i), .D (n_10675), .Q (), .QN + (\u10_mem[1]_137 )); + DFFX1 \u10_mem_reg[1][21] (.CK (clk_i), .D (n_10673), .Q (), .QN + (\u10_mem[1]_139 )); + DFFX1 \u10_mem_reg[1][22] (.CK (clk_i), .D (n_10672), .Q (), .QN + (\u10_mem[1]_140 )); + DFFX1 \u10_mem_reg[1][23] (.CK (clk_i), .D (n_10671), .Q (), .QN + (\u10_mem[1]_141 )); + DFFX1 \u10_mem_reg[1][24] (.CK (clk_i), .D (n_10670), .Q (), .QN + (\u10_mem[1]_142 )); + DFFX1 \u10_mem_reg[1][25] (.CK (clk_i), .D (n_10669), .Q (), .QN + (\u10_mem[1]_143 )); + DFFX1 \u10_mem_reg[1][26] (.CK (clk_i), .D (n_10805), .Q (), .QN + (\u10_mem[1]_144 )); + DFFX1 \u10_mem_reg[1][27] (.CK (clk_i), .D (n_10667), .Q (), .QN + (\u10_mem[1]_145 )); + DFFX1 \u10_mem_reg[1][28] (.CK (clk_i), .D (n_10666), .Q (), .QN + (\u10_mem[1]_146 )); + DFFX1 \u10_mem_reg[1][29] (.CK (clk_i), .D (n_10668), .Q (), .QN + (\u10_mem[1]_147 )); + DFFX1 \u10_mem_reg[1][20] (.CK (clk_i), .D (n_10674), .Q (), .QN + (\u10_mem[1]_138 )); + DFFX1 \u10_mem_reg[1][30] (.CK (clk_i), .D (n_10664), .Q (), .QN + (\u10_mem[1]_148 )); + DFFX1 \u10_mem_reg[1][31] (.CK (clk_i), .D (n_10665), .Q (), .QN + (\u10_mem[1]_149 )); + DFFX1 \u11_mem_reg[3][8] (.CK (clk_i), .D (n_10655), .Q (), .QN + (\u11_mem[3]_64 )); + DFFX1 \u11_mem_reg[3][9] (.CK (clk_i), .D (n_10654), .Q (), .QN + (\u11_mem[3]_65 )); + DFFX1 \u10_mem_reg[2][1] (.CK (clk_i), .D (n_10652), .Q (), .QN + (\u10_mem[2]_88 )); + DFFX1 \u10_mem_reg[2][5] (.CK (clk_i), .D (n_10651), .Q (), .QN + (\u10_mem[2]_92 )); + DFFX1 \u10_mem_reg[2][6] (.CK (clk_i), .D (n_10649), .Q (), .QN + (\u10_mem[2]_93 )); + DFFX1 \u10_mem_reg[3][3] (.CK (clk_i), .D (n_10566), .Q (), .QN + (\u10_mem[3]_59 )); + DFFX1 \u10_mem_reg[2][9] (.CK (clk_i), .D (n_10600), .Q (), .QN + (\u10_mem[2]_96 )); + DFFX1 \u11_mem_reg[1][0] (.CK (clk_i), .D (n_10563), .Q (), .QN + (\u11_mem[1] )); + DFFX1 \u11_mem_reg[1][10] (.CK (clk_i), .D (n_10562), .Q (), .QN + (\u11_mem[1]_128 )); + DFFX1 \u11_mem_reg[1][11] (.CK (clk_i), .D (n_10561), .Q (), .QN + (\u11_mem[1]_129 )); + DFFX1 \u10_mem_reg[3][2] (.CK (clk_i), .D (n_10567), .Q (), .QN + (\u10_mem[3]_58 )); + DFFX1 \u10_mem_reg[3][9] (.CK (clk_i), .D (n_10564), .Q (), .QN + (\u10_mem[3]_65 )); + DFFX1 \u11_mem_reg[1][14] (.CK (clk_i), .D (n_10559), .Q (), .QN + (\u11_mem[1]_132 )); + DFFX1 \u11_mem_reg[1][1] (.CK (clk_i), .D (n_10555), .Q (), .QN + (\u11_mem[1]_119 )); + DFFX1 \u11_mem_reg[1][2] (.CK (clk_i), .D (n_10554), .Q (), .QN + (\u11_mem[1]_120 )); + DFFX1 \u11_mem_reg[1][3] (.CK (clk_i), .D (n_10552), .Q (), .QN + (\u11_mem[1]_121 )); + DFFX1 \u11_mem_reg[1][4] (.CK (clk_i), .D (n_10551), .Q (), .QN + (\u11_mem[1]_122 )); + DFFX1 \u11_mem_reg[1][5] (.CK (clk_i), .D (n_10549), .Q (), .QN + (\u11_mem[1]_123 )); + DFFX1 \u11_mem_reg[1][7] (.CK (clk_i), .D (n_10546), .Q (), .QN + (\u11_mem[1]_125 )); + DFFX1 \u11_mem_reg[1][8] (.CK (clk_i), .D (n_10545), .Q (), .QN + (\u11_mem[1]_126 )); + DFFX1 \u11_mem_reg[1][9] (.CK (clk_i), .D (n_10543), .Q (), .QN + (\u11_mem[1]_127 )); + DFFX1 \u11_mem_reg[2][0] (.CK (clk_i), .D (n_10542), .Q (), .QN + (\u11_mem[2] )); + DFFX1 \u11_mem_reg[2][10] (.CK (clk_i), .D (n_10540), .Q (), .QN + (\u11_mem[2]_97 )); + DFFX1 \u11_mem_reg[2][11] (.CK (clk_i), .D (n_10539), .Q (), .QN + (\u11_mem[2]_98 )); + DFFX1 \u11_mem_reg[2][13] (.CK (clk_i), .D (n_10535), .Q (), .QN + (\u11_mem[2]_100 )); + DFFX1 \u11_mem_reg[2][14] (.CK (clk_i), .D (n_10529), .Q (), .QN + (\u11_mem[2]_101 )); + DFFX1 \u11_mem_reg[2][15] (.CK (clk_i), .D (n_10521), .Q (), .QN + (\u11_mem[2]_102 )); + DFFX1 \u11_mem_reg[2][16] (.CK (clk_i), .D (n_10514), .Q (), .QN + (\u11_mem[2]_103 )); + DFFX1 \u11_mem_reg[1][17] (.CK (clk_i), .D (n_10556), .Q (), .QN + (\u11_mem[1]_135 )); + DFFX1 \u11_mem_reg[2][12] (.CK (clk_i), .D (n_10538), .Q (), .QN + (\u11_mem[2]_99 )); + DFFX1 \u11_mem_reg[2][2] (.CK (clk_i), .D (n_10508), .Q (), .QN + (\u11_mem[2]_89 )); + DFFX1 \u11_mem_reg[2][3] (.CK (clk_i), .D (n_10501), .Q (), .QN + (\u11_mem[2]_90 )); + DFFX1 \u11_mem_reg[2][6] (.CK (clk_i), .D (n_10489), .Q (), .QN + (\u11_mem[2]_93 )); + DFFX1 \u11_mem_reg[2][4] (.CK (clk_i), .D (n_10498), .Q (), .QN + (\u11_mem[2]_91 )); + DFFX1 \u11_mem_reg[2][5] (.CK (clk_i), .D (n_10494), .Q (), .QN + (\u11_mem[2]_92 )); + DFFX1 \u11_mem_reg[2][9] (.CK (clk_i), .D (n_10476), .Q (), .QN + (\u11_mem[2]_96 )); + DFFX1 \u11_mem_reg[3][11] (.CK (clk_i), .D (n_10462), .Q (), .QN + (\u11_mem[3]_67 )); + DFFX1 \u11_mem_reg[3][12] (.CK (clk_i), .D (n_10459), .Q (), .QN + (\u11_mem[3]_68 )); + DFFX1 \u11_mem_reg[3][15] (.CK (clk_i), .D (n_10456), .Q (), .QN + (\u11_mem[3]_71 )); + DFFX1 \u11_mem_reg[3][10] (.CK (clk_i), .D (n_10466), .Q (), .QN + (\u11_mem[3]_66 )); + DFFX1 \u11_mem_reg[3][2] (.CK (clk_i), .D (n_10454), .Q (), .QN + (\u11_mem[3]_58 )); + DFFX1 \u11_mem_reg[3][3] (.CK (clk_i), .D (n_10453), .Q (), .QN + (\u11_mem[3]_59 )); + DFFX1 \u11_mem_reg[3][4] (.CK (clk_i), .D (n_10452), .Q (), .QN + (\u11_mem[3]_60 )); + DFFX1 \u11_mem_reg[3][1] (.CK (clk_i), .D (n_10455), .Q (), .QN + (\u11_mem[3]_57 )); + DFFX1 \u10_wp_reg[1] (.CK (clk_i), .D (n_10780), .Q (\u10_wp[1] ), + .QN ()); + DFFX1 \u10_wp_reg[2] (.CK (clk_i), .D (n_10801), .Q (\u10_wp[2] ), + .QN ()); + DFFX1 \u10_mem_reg[0][2] (.CK (clk_i), .D (n_10412), .Q (), .QN + (\u10_mem[0]_151 )); + DFFX1 \u11_mem_reg[0][5] (.CK (clk_i), .D (n_10422), .Q (), .QN + (\u11_mem[0]_154 )); + DFFX1 \u10_mem_reg[0][13] (.CK (clk_i), .D (n_10449), .Q (), .QN + (\u10_mem[0]_162 )); + DFFX1 \u10_mem_reg[0][12] (.CK (clk_i), .D (n_10451), .Q (), .QN + (\u10_mem[0]_161 )); + DFFX1 \u11_mem_reg[0][16] (.CK (clk_i), .D (n_10448), .Q (), .QN + (\u11_mem[0]_165 )); + DFFX1 \u11_mem_reg[0][20] (.CK (clk_i), .D (n_10445), .Q (), .QN + (\u11_mem[0]_169 )); + DFFX1 \u11_mem_reg[0][21] (.CK (clk_i), .D (n_10444), .Q (), .QN + (\u11_mem[0]_170 )); + DFFX1 \u11_mem_reg[0][22] (.CK (clk_i), .D (n_10443), .Q (), .QN + (\u11_mem[0]_171 )); + DFFX1 \u11_mem_reg[0][23] (.CK (clk_i), .D (n_10441), .Q (), .QN + (\u11_mem[0]_172 )); + DFFX1 \u11_mem_reg[0][24] (.CK (clk_i), .D (n_10440), .Q (), .QN + (\u11_mem[0]_173 )); + DFFX1 \u11_mem_reg[0][25] (.CK (clk_i), .D (n_10439), .Q (), .QN + (\u11_mem[0]_174 )); + DFFX1 \u10_mem_reg[0][21] (.CK (clk_i), .D (n_10438), .Q (), .QN + (\u10_mem[0]_170 )); + DFFX1 \u11_mem_reg[0][26] (.CK (clk_i), .D (n_10437), .Q (), .QN + (\u11_mem[0]_175 )); + DFFX1 \u11_mem_reg[0][27] (.CK (clk_i), .D (n_10436), .Q (), .QN + (\u11_mem[0]_176 )); + DFFX1 \u10_mem_reg[0][22] (.CK (clk_i), .D (n_10435), .Q (), .QN + (\u10_mem[0]_171 )); + DFFX1 \u11_mem_reg[0][28] (.CK (clk_i), .D (n_10433), .Q (), .QN + (\u11_mem[0]_177 )); + DFFX1 \u11_mem_reg[0][29] (.CK (clk_i), .D (n_10432), .Q (), .QN + (\u11_mem[0]_178 )); + DFFX1 \u11_mem_reg[0][2] (.CK (clk_i), .D (n_10430), .Q (), .QN + (\u11_mem[0]_151 )); + DFFX1 \u11_mem_reg[0][30] (.CK (clk_i), .D (n_10429), .Q (), .QN + (\u11_mem[0]_179 )); + DFFX1 \u11_mem_reg[0][31] (.CK (clk_i), .D (n_10428), .Q (), .QN + (\u11_mem[0]_180 )); + DFFX1 \u11_mem_reg[0][3] (.CK (clk_i), .D (n_10425), .Q (), .QN + (\u11_mem[0]_152 )); + DFFX1 \u10_mem_reg[0][25] (.CK (clk_i), .D (n_10426), .Q (), .QN + (\u10_mem[0]_174 )); + DFFX1 \u11_mem_reg[0][4] (.CK (clk_i), .D (n_10424), .Q (), .QN + (\u11_mem[0]_153 )); + DFFX1 \u10_mem_reg[0][26] (.CK (clk_i), .D (n_10423), .Q (), .QN + (\u10_mem[0]_175 )); + DFFX1 \u10_mem_reg[0][27] (.CK (clk_i), .D (n_10421), .Q (), .QN + (\u10_mem[0]_176 )); + DFFX1 \u11_mem_reg[0][6] (.CK (clk_i), .D (n_10420), .Q (), .QN + (\u11_mem[0]_155 )); + DFFX1 \u10_mem_reg[0][28] (.CK (clk_i), .D (n_10418), .Q (), .QN + (\u10_mem[0]_177 )); + DFFX1 \u11_mem_reg[0][7] (.CK (clk_i), .D (n_10417), .Q (), .QN + (\u11_mem[0]_156 )); + DFFX1 \u11_mem_reg[0][8] (.CK (clk_i), .D (n_10416), .Q (), .QN + (\u11_mem[0]_157 )); + DFFX1 \u10_mem_reg[0][29] (.CK (clk_i), .D (n_10415), .Q (), .QN + (\u10_mem[0]_178 )); + DFFX1 \u11_mem_reg[0][9] (.CK (clk_i), .D (n_10413), .Q (), .QN + (\u11_mem[0]_158 )); + DFFX1 \u10_mem_reg[0][5] (.CK (clk_i), .D (n_10411), .Q (), .QN + (\u10_mem[0]_154 )); + DFFSRX1 \u11_wp_reg[0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_10777), .Q (\u11_wp[0] ), .QN ()); + DFFSRX1 \u25_int_set_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10794), .Q (), .QN (ic2_int_set_724)); + OR2X1 g29969(.A (\u13_ints_r[11] ), .B (oc3_int_set), .Y (n_10967)); + OR2X1 g29973(.A (\u13_ints_r[5] ), .B (oc1_int_set), .Y (n_10966)); + DFFX1 \u10_mem_reg[0][1] (.CK (clk_i), .D (n_10446), .Q (), .QN + (\u10_mem[0]_150 )); + NOR2X1 g29975(.A (n_10409), .B (dma_ack_i[0]), .Y (n_11125)); + NOR2X1 g29977(.A (n_10408), .B (dma_ack_i[2]), .Y (n_11124)); + NOR2X1 g29979(.A (n_10407), .B (dma_ack_i[4]), .Y (n_11123)); + NOR2X1 g29980(.A (n_10406), .B (dma_ack_i[5]), .Y (n_11122)); + DFFX1 \u11_mem_reg[0][17] (.CK (clk_i), .D (n_10447), .Q (), .QN + (\u11_mem[0]_166 )); + MX2X1 g30031(.A (u1_sr_130), .B (in_slt_840), .S0 (out_le_181), .Y + (n_10964)); + NOR2X1 g30709(.A (n_10776), .B (n_12589), .Y (n_10963)); + MX2X1 g30032(.A (u1_sr_130), .B (in_slt_410), .S0 (out_le_182), .Y + (n_10961)); + NOR2X1 g30712(.A (n_10775), .B (n_11136), .Y (n_10960)); + NOR2X1 g30713(.A (n_10661), .B (n_11136), .Y (n_10959)); + MX2X1 g30033(.A (u1_sr_130), .B (in_slt_432), .S0 (out_le_183), .Y + (n_10958)); + MX2X1 g30034(.A (u1_sr_130), .B (in_slt_454), .S0 (out_le_184), .Y + (n_10957)); + DFFX1 \u10_mem_reg[3][17] (.CK (clk_i), .D (n_10224), .Q (), .QN + (\u10_mem[3]_73 )); + DFFX1 \u1_sr_reg[15] (.CK (bit_clk_pad_i), .D (u1_sr_130), .Q + (u1_sr_131), .QN ()); + OAI22X1 g30741(.A0 (n_10954), .A1 (n_6077), .B0 (out_slt4), .B1 + (n_10953), .Y (n_10956)); + OAI22X1 g30742(.A0 (n_10954), .A1 (n_6080), .B0 (n_10953), .B1 + (out_slt_84), .Y (n_10955)); + OAI22X1 g30743(.A0 (n_10950), .A1 (n_5566), .B0 (out_slt6), .B1 + (n_10949), .Y (n_10952)); + OAI22X1 g30744(.A0 (n_10950), .A1 (n_5558), .B0 (n_10949), .B1 + (out_slt_103), .Y (n_10951)); + DFFX1 \u10_mem_reg[0][11] (.CK (clk_i), .D (n_10135), .Q (), .QN + (\u10_mem[0]_160 )); + DFFX1 \u9_mem_reg[0][4] (.CK (clk_i), .D (n_10147), .Q (), .QN + (\u9_mem[0]_153 )); + AND2X1 g30789(.A (n_10340), .B (n_11772), .Y (n_10948)); + AOI21X1 g30790(.A0 (n_12008), .A1 (n_12009), .B0 (n_10945), .Y + (n_10947)); + AOI21X1 g30791(.A0 (n_11988), .A1 (n_11989), .B0 (n_10945), .Y + (n_10946)); + AOI21X1 g30792(.A0 (n_12010), .A1 (n_12011), .B0 (n_10940), .Y + (n_10944)); + AOI21X1 g30793(.A0 (n_11674), .A1 (n_11675), .B0 (n_1473), .Y + (n_10943)); + AOI21X1 g30794(.A0 (n_11676), .A1 (n_11677), .B0 (n_1473), .Y + (n_10942)); + AOI21X1 g30795(.A0 (n_12000), .A1 (n_12001), .B0 (n_10940), .Y + (n_10941)); + AOI21X1 g30796(.A0 (n_11984), .A1 (n_11985), .B0 (n_1473), .Y + (n_10939)); + AOI21X1 g30797(.A0 (n_12018), .A1 (n_12019), .B0 (n_1473), .Y + (n_10937)); + DFFX1 \u9_wp_reg[3] (.CK (clk_i), .D (n_10335), .Q (\u9_wp[3] ), .QN + ()); + AOI21X1 g30799(.A0 (n_11948), .A1 (n_11949), .B0 (n_10945), .Y + (n_10935)); + AOI21X1 g30800(.A0 (n_12012), .A1 (n_12013), .B0 (n_1473), .Y + (n_10934)); + DFFX1 \u9_mem_reg[0][8] (.CK (clk_i), .D (n_10142), .Q (), .QN + (\u9_mem[0]_157 )); + AOI21X1 g30803(.A0 (n_12140), .A1 (n_11536), .B0 (n_1473), .Y + (n_10933)); + AOI21X1 g30804(.A0 (n_12150), .A1 (n_11538), .B0 (n_10940), .Y + (n_10932)); + AOI21X1 g30805(.A0 (n_12042), .A1 (n_12043), .B0 (n_10940), .Y + (n_10931)); + AOI21X1 g30806(.A0 (n_11950), .A1 (n_11951), .B0 (n_10945), .Y + (n_10930)); + AOI21X1 g30807(.A0 (n_11980), .A1 (n_11981), .B0 (n_1473), .Y + (n_10929)); + AOI21X1 g30808(.A0 (n_12006), .A1 (n_12007), .B0 (n_1473), .Y + (n_10928)); + AOI21X1 g30810(.A0 (n_9933), .A1 (n_9815), .B0 (n_2485), .Y + (n_10927)); + AOI21X1 g30811(.A0 (n_9932), .A1 (n_9813), .B0 (n_2485), .Y + (n_10926)); + AOI21X1 g30812(.A0 (n_9930), .A1 (n_9812), .B0 (n_10921), .Y + (n_10924)); + AOI21X1 g30813(.A0 (n_9929), .A1 (n_9811), .B0 (n_10916), .Y + (n_10923)); + AOI21X1 g30814(.A0 (n_9928), .A1 (n_9810), .B0 (n_10921), .Y + (n_10922)); + AOI21X1 g30815(.A0 (n_9927), .A1 (n_9808), .B0 (n_2485), .Y + (n_10920)); + AOI21X1 g30816(.A0 (n_9926), .A1 (n_9807), .B0 (n_2485), .Y + (n_10919)); + AOI21X1 g30817(.A0 (n_9925), .A1 (n_9806), .B0 (n_10916), .Y + (n_10917)); + AOI21X1 g30818(.A0 (n_12835), .A1 (n_12836), .B0 (n_2485), .Y + (n_10915)); + AOI21X1 g30819(.A0 (n_9922), .A1 (n_9804), .B0 (n_10921), .Y + (n_10914)); + AOI21X1 g30822(.A0 (n_12610), .A1 (n_11999), .B0 (n_10921), .Y + (n_10913)); + AOI21X1 g30823(.A0 (n_12811), .A1 (n_12812), .B0 (n_2485), .Y + (n_10912)); + AOI21X1 g30824(.A0 (n_12813), .A1 (n_12814), .B0 (n_2485), .Y + (n_10911)); + AOI21X1 g30825(.A0 (n_12815), .A1 (n_12816), .B0 (n_10916), .Y + (n_10910)); + AOI21X1 g30826(.A0 (n_9915), .A1 (n_9798), .B0 (n_10916), .Y + (n_10909)); + AOI21X1 g30827(.A0 (n_9914), .A1 (n_9797), .B0 (n_2485), .Y + (n_10908)); + INVX1 g31741(.A (n_10799), .Y (n_10907)); + INVX1 g31747(.A (n_10798), .Y (n_10906)); + INVX1 g31750(.A (n_10796), .Y (n_10905)); + INVX1 g31753(.A (n_10795), .Y (n_10904)); + DFFX1 \u10_mem_reg[1][8] (.CK (clk_i), .D (n_10179), .Q (), .QN + (\u10_mem[1]_126 )); + DFFX1 \u9_mem_reg[0][2] (.CK (clk_i), .D (n_10152), .Q (), .QN + (\u9_mem[0]_151 )); + DFFX1 \u9_mem_reg[0][26] (.CK (clk_i), .D (n_10157), .Q (), .QN + (\u9_mem[0]_175 )); + DFFX1 \u10_mem_reg[1][6] (.CK (clk_i), .D (n_10181), .Q (), .QN + (\u10_mem[1]_124 )); + DFFX1 \u9_mem_reg[0][17] (.CK (clk_i), .D (n_10166), .Q (), .QN + (\u9_mem[0]_166 )); + DFFX1 \u9_mem_reg[0][13] (.CK (clk_i), .D (n_10170), .Q (), .QN + (\u9_mem[0]_162 )); + INVX1 g31806(.A (n_10781), .Y (n_10903)); + DFFX1 \u10_mem_reg[1][1] (.CK (clk_i), .D (n_10187), .Q (), .QN + (\u10_mem[1]_119 )); + DFFX1 \u10_mem_reg[1][15] (.CK (clk_i), .D (n_10197), .Q (), .QN + (\u10_mem[1]_133 )); + DFFX1 \u10_mem_reg[1][13] (.CK (clk_i), .D (n_10211), .Q (), .QN + (\u10_mem[1]_131 )); + DFFX1 \u10_mem_reg[1][10] (.CK (clk_i), .D (n_10215), .Q (), .QN + (\u10_mem[1]_128 )); + DFFX1 \u10_mem_reg[3][8] (.CK (clk_i), .D (n_10216), .Q (), .QN + (\u10_mem[3]_64 )); + AND2X1 g30906(.A (n_10338), .B (n_11772), .Y (n_10902)); + AND2X1 g30909(.A (n_10337), .B (n_11772), .Y (n_10900)); + OAI21X1 g31019(.A0 (n_5428), .A1 (n_10820), .B0 (n_10393), .Y + (n_10899)); + OAI21X1 g31020(.A0 (n_5416), .A1 (n_10880), .B0 (n_10392), .Y + (n_10898)); + OAI21X1 g31022(.A0 (n_5414), .A1 (n_10880), .B0 (n_10390), .Y + (n_10897)); + OAI21X1 g31023(.A0 (n_5406), .A1 (n_10880), .B0 (n_10389), .Y + (n_10896)); + OAI21X1 g31024(.A0 (n_5336), .A1 (n_10820), .B0 (n_10388), .Y + (n_10895)); + OAI21X1 g31025(.A0 (n_5323), .A1 (n_10820), .B0 (n_10387), .Y + (n_10894)); + OAI21X1 g31026(.A0 (n_5332), .A1 (n_10820), .B0 (n_10386), .Y + (n_10893)); + OAI21X1 g31027(.A0 (n_5329), .A1 (n_10880), .B0 (n_10384), .Y + (n_10892)); + OAI21X1 g31028(.A0 (n_5327), .A1 (n_10880), .B0 (n_10383), .Y + (n_10890)); + OAI21X1 g31029(.A0 (n_5281), .A1 (n_10820), .B0 (n_10382), .Y + (n_10888)); + OAI21X1 g31030(.A0 (n_5326), .A1 (n_10880), .B0 (n_10380), .Y + (n_10886)); + OAI21X1 g31031(.A0 (n_5319), .A1 (n_10820), .B0 (n_10379), .Y + (n_10885)); + OAI21X1 g31032(.A0 (n_5320), .A1 (n_10820), .B0 (n_10378), .Y + (n_10884)); + OAI21X1 g31033(.A0 (n_5325), .A1 (n_10820), .B0 (n_10377), .Y + (n_10882)); + OAI21X1 g31034(.A0 (n_5338), .A1 (n_10880), .B0 (n_10375), .Y + (n_10881)); + OAI21X1 g31035(.A0 (n_5381), .A1 (n_10880), .B0 (n_10374), .Y + (n_10879)); + OAI21X1 g31036(.A0 (n_5412), .A1 (n_10820), .B0 (n_10373), .Y + (n_10877)); + OAI21X1 g31037(.A0 (n_5411), .A1 (n_10880), .B0 (n_10372), .Y + (n_10876)); + OAI21X1 g31038(.A0 (n_5337), .A1 (n_10820), .B0 (n_10371), .Y + (n_10875)); + OAI21X1 g31039(.A0 (n_5318), .A1 (n_10820), .B0 (n_10370), .Y + (n_10873)); + OAI21X1 g31040(.A0 (n_5316), .A1 (n_10820), .B0 (n_10369), .Y + (n_10872)); + OAI21X1 g31041(.A0 (n_5314), .A1 (n_10820), .B0 (n_10367), .Y + (n_10870)); + OAI21X1 g31042(.A0 (n_5322), .A1 (n_10820), .B0 (n_10366), .Y + (n_10868)); + OAI21X1 g31043(.A0 (n_5311), .A1 (n_10820), .B0 (n_10365), .Y + (n_10867)); + OAI21X1 g31045(.A0 (n_5310), .A1 (n_10820), .B0 (n_10364), .Y + (n_10866)); + OAI21X1 g31046(.A0 (n_5308), .A1 (n_10820), .B0 (n_10363), .Y + (n_10864)); + OAI21X1 g31048(.A0 (n_5305), .A1 (n_10880), .B0 (n_10362), .Y + (n_10863)); + OAI21X1 g31049(.A0 (n_5299), .A1 (n_10820), .B0 (n_10361), .Y + (n_10862)); + OAI21X1 g31050(.A0 (n_5297), .A1 (n_10820), .B0 (n_10360), .Y + (n_10860)); + OAI21X1 g31052(.A0 (n_5301), .A1 (n_10820), .B0 (n_10359), .Y + (n_10859)); + DFFX1 \u10_mem_reg[0][23] (.CK (clk_i), .D (n_10129), .Q (), .QN + (\u10_mem[0]_172 )); + DFFX1 \u11_din_tmp1_reg[8] (.CK (clk_i), .D (n_10097), .Q + (u11_din_tmp_49), .QN ()); + DFFX1 \u9_mem_reg[2][12] (.CK (clk_i), .D (n_10285), .Q (), .QN + (\u9_mem[2]_99 )); + DFFX1 \u10_mem_reg[3][13] (.CK (clk_i), .D (n_10229), .Q (), .QN + (\u10_mem[3]_69 )); + DFFX1 \u10_mem_reg[3][0] (.CK (clk_i), .D (n_10234), .Q (), .QN + (\u10_mem[3] )); + DFFX1 \u9_mem_reg[3][4] (.CK (clk_i), .D (n_10243), .Q (), .QN + (\u9_mem[3]_60 )); + DFFX1 \u9_mem_reg[3][1] (.CK (clk_i), .D (n_10251), .Q (), .QN + (\u9_mem[3]_57 )); + DFFX1 \u9_mem_reg[3][15] (.CK (clk_i), .D (n_10254), .Q (), .QN + (\u9_mem[3]_71 )); + DFFX1 \u9_mem_reg[2][5] (.CK (clk_i), .D (n_10269), .Q (), .QN + (\u9_mem[2]_92 )); + DFFX1 \u9_mem_reg[2][2] (.CK (clk_i), .D (n_10275), .Q (), .QN + (\u9_mem[2]_89 )); + DFFX1 \u10_mem_reg[1][9] (.CK (clk_i), .D (n_10178), .Q (), .QN + (\u10_mem[1]_127 )); + DFFX1 \u10_mem_reg[2][0] (.CK (clk_i), .D (n_10326), .Q (), .QN + (\u10_mem[2] )); + DFFX1 \u10_mem_reg[2][11] (.CK (clk_i), .D (n_10323), .Q (), .QN + (\u10_mem[2]_98 )); + DFFX1 \u10_mem_reg[2][12] (.CK (clk_i), .D (n_10322), .Q (), .QN + (\u10_mem[2]_99 )); + DFFX1 \u10_mem_reg[2][13] (.CK (clk_i), .D (n_10321), .Q (), .QN + (\u10_mem[2]_100 )); + DFFX1 \u10_mem_reg[2][14] (.CK (clk_i), .D (n_10319), .Q (), .QN + (\u10_mem[2]_101 )); + DFFX1 \u10_mem_reg[2][15] (.CK (clk_i), .D (n_10318), .Q (), .QN + (\u10_mem[2]_102 )); + DFFX1 \u10_mem_reg[2][16] (.CK (clk_i), .D (n_10317), .Q (), .QN + (\u10_mem[2]_103 )); + DFFX1 \u10_mem_reg[2][10] (.CK (clk_i), .D (n_10325), .Q (), .QN + (\u10_mem[2]_97 )); + DFFX1 \u9_mem_reg[1][0] (.CK (clk_i), .D (n_10314), .Q (), .QN + (\u9_mem[1] )); + DFFX1 \u9_mem_reg[1][10] (.CK (clk_i), .D (n_10313), .Q (), .QN + (\u9_mem[1]_128 )); + DFFX1 \u9_mem_reg[1][12] (.CK (clk_i), .D (n_10310), .Q (), .QN + (\u9_mem[1]_130 )); + DFFX1 \u9_mem_reg[1][13] (.CK (clk_i), .D (n_10309), .Q (), .QN + (\u9_mem[1]_131 )); + DFFX1 \u9_mem_reg[1][14] (.CK (clk_i), .D (n_10307), .Q (), .QN + (\u9_mem[1]_132 )); + DFFX1 \u9_mem_reg[1][16] (.CK (clk_i), .D (n_10305), .Q (), .QN + (\u9_mem[1]_134 )); + DFFX1 \u9_mem_reg[1][17] (.CK (clk_i), .D (n_10304), .Q (), .QN + (\u9_mem[1]_135 )); + DFFX1 \u9_mem_reg[1][1] (.CK (clk_i), .D (n_10302), .Q (), .QN + (\u9_mem[1]_119 )); + DFFX1 \u9_mem_reg[1][2] (.CK (clk_i), .D (n_10300), .Q (), .QN + (\u9_mem[1]_120 )); + DFFX1 \u9_mem_reg[1][3] (.CK (clk_i), .D (n_10299), .Q (), .QN + (\u9_mem[1]_121 )); + DFFX1 \u9_mem_reg[1][4] (.CK (clk_i), .D (n_10298), .Q (), .QN + (\u9_mem[1]_122 )); + DFFX1 \u9_mem_reg[1][5] (.CK (clk_i), .D (n_10296), .Q (), .QN + (\u9_mem[1]_123 )); + DFFX1 \u9_mem_reg[1][6] (.CK (clk_i), .D (n_10295), .Q (), .QN + (\u9_mem[1]_124 )); + DFFX1 \u9_mem_reg[1][7] (.CK (clk_i), .D (n_10293), .Q (), .QN + (\u9_mem[1]_125 )); + DFFX1 \u9_mem_reg[1][8] (.CK (clk_i), .D (n_10291), .Q (), .QN + (\u9_mem[1]_126 )); + DFFX1 \u9_mem_reg[2][0] (.CK (clk_i), .D (n_10289), .Q (), .QN + (\u9_mem[2] )); + DFFX1 \u9_mem_reg[2][10] (.CK (clk_i), .D (n_10288), .Q (), .QN + (\u9_mem[2]_97 )); + DFFX1 \u9_mem_reg[2][11] (.CK (clk_i), .D (n_10287), .Q (), .QN + (\u9_mem[2]_98 )); + DFFX1 \u9_mem_reg[2][14] (.CK (clk_i), .D (n_10283), .Q (), .QN + (\u9_mem[2]_101 )); + DFFX1 \u9_mem_reg[2][15] (.CK (clk_i), .D (n_10281), .Q (), .QN + (\u9_mem[2]_102 )); + DFFX1 \u9_mem_reg[2][16] (.CK (clk_i), .D (n_10280), .Q (), .QN + (\u9_mem[2]_103 )); + DFFX1 \u9_mem_reg[2][17] (.CK (clk_i), .D (n_10279), .Q (), .QN + (\u9_mem[2]_104 )); + DFFX1 \u9_mem_reg[2][1] (.CK (clk_i), .D (n_10278), .Q (), .QN + (\u9_mem[2]_88 )); + DFFX1 \u10_mem_reg[2][3] (.CK (clk_i), .D (n_10276), .Q (), .QN + (\u10_mem[2]_90 )); + DFFX1 \u9_mem_reg[2][3] (.CK (clk_i), .D (n_10272), .Q (), .QN + (\u9_mem[2]_90 )); + DFFX1 \u10_mem_reg[2][4] (.CK (clk_i), .D (n_10274), .Q (), .QN + (\u10_mem[2]_91 )); + DFFX1 \u9_mem_reg[2][4] (.CK (clk_i), .D (n_10270), .Q (), .QN + (\u9_mem[2]_91 )); + DFFX1 \u9_mem_reg[2][6] (.CK (clk_i), .D (n_10268), .Q (), .QN + (\u9_mem[2]_93 )); + DFFX1 \u9_mem_reg[2][7] (.CK (clk_i), .D (n_10266), .Q (), .QN + (\u9_mem[2]_94 )); + DFFX1 \u9_mem_reg[2][8] (.CK (clk_i), .D (n_10265), .Q (), .QN + (\u9_mem[2]_95 )); + DFFX1 \u9_mem_reg[3][0] (.CK (clk_i), .D (n_10263), .Q (), .QN + (\u9_mem[3] )); + DFFX1 \u9_mem_reg[3][10] (.CK (clk_i), .D (n_10262), .Q (), .QN + (\u9_mem[3]_66 )); + DFFX1 \u9_mem_reg[3][11] (.CK (clk_i), .D (n_10261), .Q (), .QN + (\u9_mem[3]_67 )); + DFFX1 \u9_mem_reg[3][12] (.CK (clk_i), .D (n_10259), .Q (), .QN + (\u9_mem[3]_68 )); + DFFX1 \u9_mem_reg[3][13] (.CK (clk_i), .D (n_10258), .Q (), .QN + (\u9_mem[3]_69 )); + DFFX1 \u9_mem_reg[3][14] (.CK (clk_i), .D (n_10256), .Q (), .QN + (\u9_mem[3]_70 )); + DFFX1 \u9_mem_reg[2][13] (.CK (clk_i), .D (n_10284), .Q (), .QN + (\u9_mem[2]_100 )); + DFFX1 \u9_mem_reg[3][16] (.CK (clk_i), .D (n_10253), .Q (), .QN + (\u9_mem[3]_72 )); + DFFX1 \u9_mem_reg[3][17] (.CK (clk_i), .D (n_10252), .Q (), .QN + (\u9_mem[3]_73 )); + DFFX1 \u10_mem_reg[2][7] (.CK (clk_i), .D (n_10249), .Q (), .QN + (\u10_mem[2]_94 )); + DFFX1 \u9_mem_reg[3][2] (.CK (clk_i), .D (n_10247), .Q (), .QN + (\u9_mem[3]_58 )); + DFFX1 \u9_mem_reg[3][3] (.CK (clk_i), .D (n_10245), .Q (), .QN + (\u9_mem[3]_59 )); + DFFX1 \u9_mem_reg[3][5] (.CK (clk_i), .D (n_10242), .Q (), .QN + (\u9_mem[3]_61 )); + DFFX1 \u9_mem_reg[3][6] (.CK (clk_i), .D (n_10241), .Q (), .QN + (\u9_mem[3]_62 )); + DFFX1 \u9_mem_reg[3][7] (.CK (clk_i), .D (n_10239), .Q (), .QN + (\u9_mem[3]_63 )); + DFFX1 \u10_mem_reg[2][8] (.CK (clk_i), .D (n_10244), .Q (), .QN + (\u10_mem[2]_95 )); + DFFX1 \u9_mem_reg[3][9] (.CK (clk_i), .D (n_10236), .Q (), .QN + (\u9_mem[3]_65 )); + DFFX1 \u9_mem_reg[3][8] (.CK (clk_i), .D (n_10238), .Q (), .QN + (\u9_mem[3]_64 )); + DFFX1 \u10_mem_reg[3][10] (.CK (clk_i), .D (n_10233), .Q (), .QN + (\u10_mem[3]_66 )); + DFFX1 \u10_mem_reg[3][11] (.CK (clk_i), .D (n_10232), .Q (), .QN + (\u10_mem[3]_67 )); + DFFX1 \u10_mem_reg[3][12] (.CK (clk_i), .D (n_10230), .Q (), .QN + (\u10_mem[3]_68 )); + DFFX1 \u10_mem_reg[3][14] (.CK (clk_i), .D (n_10228), .Q (), .QN + (\u10_mem[3]_70 )); + DFFX1 \u10_mem_reg[3][15] (.CK (clk_i), .D (n_10226), .Q (), .QN + (\u10_mem[3]_71 )); + DFFX1 \u10_mem_reg[3][16] (.CK (clk_i), .D (n_10225), .Q (), .QN + (\u10_mem[3]_72 )); + DFFX1 \u10_mem_reg[3][1] (.CK (clk_i), .D (n_10223), .Q (), .QN + (\u10_mem[3]_57 )); + DFFX1 \u10_mem_reg[3][4] (.CK (clk_i), .D (n_10221), .Q (), .QN + (\u10_mem[3]_60 )); + DFFX1 \u10_mem_reg[3][5] (.CK (clk_i), .D (n_10220), .Q (), .QN + (\u10_mem[3]_61 )); + DFFX1 \u10_mem_reg[3][6] (.CK (clk_i), .D (n_10219), .Q (), .QN + (\u10_mem[3]_62 )); + DFFX1 \u10_mem_reg[3][7] (.CK (clk_i), .D (n_10217), .Q (), .QN + (\u10_mem[3]_63 )); + OAI21X1 g31062(.A0 (n_5581), .A1 (n_10880), .B0 (n_10358), .Y + (n_10858)); + DFFX1 \u10_mem_reg[1][11] (.CK (clk_i), .D (n_10214), .Q (), .QN + (\u10_mem[1]_129 )); + DFFX1 \u10_mem_reg[1][12] (.CK (clk_i), .D (n_10212), .Q (), .QN + (\u10_mem[1]_130 )); + DFFX1 \u10_mem_reg[1][14] (.CK (clk_i), .D (n_10205), .Q (), .QN + (\u10_mem[1]_132 )); + DFFX1 \u10_mem_reg[1][17] (.CK (clk_i), .D (n_10190), .Q (), .QN + (\u10_mem[1]_135 )); + DFFX1 \u10_mem_reg[1][16] (.CK (clk_i), .D (n_10194), .Q (), .QN + (\u10_mem[1]_134 )); + DFFX1 \u9_mem_reg[1][9] (.CK (clk_i), .D (n_10290), .Q (), .QN + (\u9_mem[1]_127 )); + DFFX1 \u10_mem_reg[1][3] (.CK (clk_i), .D (n_10184), .Q (), .QN + (\u10_mem[1]_121 )); + DFFX1 \u10_mem_reg[1][4] (.CK (clk_i), .D (n_10183), .Q (), .QN + (\u10_mem[1]_122 )); + DFFX1 \u10_mem_reg[1][5] (.CK (clk_i), .D (n_10182), .Q (), .QN + (\u10_mem[1]_123 )); + DFFX1 \u10_mem_reg[1][2] (.CK (clk_i), .D (n_10185), .Q (), .QN + (\u10_mem[1]_120 )); + DFFX1 \u10_mem_reg[2][2] (.CK (clk_i), .D (n_10301), .Q (), .QN + (\u10_mem[2]_89 )); + DFFX1 \u10_mem_reg[1][7] (.CK (clk_i), .D (n_10180), .Q (), .QN + (\u10_mem[1]_125 )); + OAI21X1 g31063(.A0 (n_5583), .A1 (n_10880), .B0 (n_10357), .Y + (n_10857)); + DFFX1 \u9_wp_reg[2] (.CK (clk_i), .D (n_10394), .Q (\u9_wp[2] ), .QN + ()); + DFFX1 \u9_mem_reg[1][15] (.CK (clk_i), .D (n_10306), .Q (), .QN + (\u9_mem[1]_133 )); + DFFX1 \u9_mem_reg[1][11] (.CK (clk_i), .D (n_10311), .Q (), .QN + (\u9_mem[1]_129 )); + DFFX1 \u10_mem_reg[2][17] (.CK (clk_i), .D (n_10316), .Q (), .QN + (\u10_mem[2]_104 )); + DFFX1 \u10_mem_reg[0][24] (.CK (clk_i), .D (n_10128), .Q (), .QN + (\u10_mem[0]_173 )); + OAI21X1 g31064(.A0 (n_5495), .A1 (n_10880), .B0 (n_10356), .Y + (n_10856)); + DFFX1 \u11_din_tmp1_reg[4] (.CK (clk_i), .D (n_10101), .Q + (u11_din_tmp_45), .QN ()); + DFFX1 \u10_mem_reg[0][8] (.CK (clk_i), .D (n_10119), .Q (), .QN + (\u10_mem[0]_157 )); + DFFX1 \u10_mem_reg[0][4] (.CK (clk_i), .D (n_10123), .Q (), .QN + (\u10_mem[0]_153 )); + DFFX1 \u9_mem_reg[0][0] (.CK (clk_i), .D (n_10176), .Q (), .QN + (\u9_mem[0] )); + DFFX1 \u9_mem_reg[0][10] (.CK (clk_i), .D (n_10174), .Q (), .QN + (\u9_mem[0]_159 )); + DFFX1 \u9_mem_reg[0][11] (.CK (clk_i), .D (n_10173), .Q (), .QN + (\u9_mem[0]_160 )); + DFFX1 \u9_mem_reg[0][12] (.CK (clk_i), .D (n_10172), .Q (), .QN + (\u9_mem[0]_161 )); + DFFX1 \u9_mem_reg[0][14] (.CK (clk_i), .D (n_10169), .Q (), .QN + (\u9_mem[0]_163 )); + DFFX1 \u9_mem_reg[0][15] (.CK (clk_i), .D (n_10168), .Q (), .QN + (\u9_mem[0]_164 )); + DFFX1 \u9_mem_reg[0][16] (.CK (clk_i), .D (n_10167), .Q (), .QN + (\u9_mem[0]_165 )); + DFFX1 \u9_mem_reg[0][1] (.CK (clk_i), .D (n_10165), .Q (), .QN + (\u9_mem[0]_150 )); + DFFX1 \u9_mem_reg[0][20] (.CK (clk_i), .D (n_10164), .Q (), .QN + (\u9_mem[0]_169 )); + DFFX1 \u9_mem_reg[0][21] (.CK (clk_i), .D (n_10163), .Q (), .QN + (\u9_mem[0]_170 )); + DFFX1 \u9_mem_reg[0][22] (.CK (clk_i), .D (n_10162), .Q (), .QN + (\u9_mem[0]_171 )); + DFFX1 \u9_mem_reg[0][23] (.CK (clk_i), .D (n_10160), .Q (), .QN + (\u9_mem[0]_172 )); + DFFX1 \u9_mem_reg[0][24] (.CK (clk_i), .D (n_10159), .Q (), .QN + (\u9_mem[0]_173 )); + DFFX1 \u9_mem_reg[0][25] (.CK (clk_i), .D (n_10158), .Q (), .QN + (\u9_mem[0]_174 )); + DFFX1 \u9_mem_reg[0][27] (.CK (clk_i), .D (n_10156), .Q (), .QN + (\u9_mem[0]_176 )); + DFFX1 \u9_mem_reg[0][28] (.CK (clk_i), .D (n_10155), .Q (), .QN + (\u9_mem[0]_177 )); + DFFX1 \u9_mem_reg[0][29] (.CK (clk_i), .D (n_10154), .Q (), .QN + (\u9_mem[0]_178 )); + DFFX1 \u9_mem_reg[0][30] (.CK (clk_i), .D (n_10151), .Q (), .QN + (\u9_mem[0]_179 )); + DFFX1 \u9_mem_reg[0][31] (.CK (clk_i), .D (n_10150), .Q (), .QN + (\u9_mem[0]_180 )); + DFFX1 \u9_mem_reg[0][3] (.CK (clk_i), .D (n_10148), .Q (), .QN + (\u9_mem[0]_152 )); + DFFX1 \u9_mem_reg[0][5] (.CK (clk_i), .D (n_10146), .Q (), .QN + (\u9_mem[0]_154 )); + DFFX1 \u9_mem_reg[0][6] (.CK (clk_i), .D (n_10145), .Q (), .QN + (\u9_mem[0]_155 )); + DFFX1 \u9_mem_reg[0][7] (.CK (clk_i), .D (n_10143), .Q (), .QN + (\u9_mem[0]_156 )); + DFFX1 \u9_mem_reg[0][9] (.CK (clk_i), .D (n_10141), .Q (), .QN + (\u9_mem[0]_158 )); + DFFX1 \u10_mem_reg[0][0] (.CK (clk_i), .D (n_10138), .Q (), .QN + (\u10_mem[0] )); + DFFX1 \u10_mem_reg[0][10] (.CK (clk_i), .D (n_10136), .Q (), .QN + (\u10_mem[0]_159 )); + OAI21X1 g31066(.A0 (n_5527), .A1 (n_10820), .B0 (n_10355), .Y + (n_10855)); + DFFX1 \u10_mem_reg[0][14] (.CK (clk_i), .D (n_10134), .Q (), .QN + (\u10_mem[0]_163 )); + DFFX1 \u10_mem_reg[0][15] (.CK (clk_i), .D (n_10133), .Q (), .QN + (\u10_mem[0]_164 )); + DFFX1 \u10_mem_reg[0][16] (.CK (clk_i), .D (n_10132), .Q (), .QN + (\u10_mem[0]_165 )); + DFFX1 \u10_mem_reg[0][17] (.CK (clk_i), .D (n_10131), .Q (), .QN + (\u10_mem[0]_166 )); + OAI21X1 g31067(.A0 (n_5489), .A1 (n_10820), .B0 (n_10354), .Y + (n_10854)); + DFFX1 \u10_mem_reg[0][31] (.CK (clk_i), .D (n_10126), .Q (), .QN + (\u10_mem[0]_180 )); + DFFX1 \u10_mem_reg[0][3] (.CK (clk_i), .D (n_10124), .Q (), .QN + (\u10_mem[0]_152 )); + DFFX1 \u10_mem_reg[0][30] (.CK (clk_i), .D (n_10127), .Q (), .QN + (\u10_mem[0]_179 )); + DFFX1 \u10_mem_reg[0][6] (.CK (clk_i), .D (n_10122), .Q (), .QN + (\u10_mem[0]_155 )); + DFFX1 \u10_mem_reg[0][7] (.CK (clk_i), .D (n_10120), .Q (), .QN + (\u10_mem[0]_156 )); + DFFX1 \u10_mem_reg[0][9] (.CK (clk_i), .D (n_10118), .Q (), .QN + (\u10_mem[0]_158 )); + DFFSRX1 \u10_wp_reg[0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_10333), .Q (n_9641), .QN ()); + DFFX1 \u11_din_tmp1_reg[0] (.CK (clk_i), .D (n_10115), .Q + (u11_din_tmp1), .QN ()); + DFFX1 \u11_din_tmp1_reg[10] (.CK (clk_i), .D (n_10114), .Q + (u11_din_tmp_51), .QN ()); + DFFX1 \u11_din_tmp1_reg[11] (.CK (clk_i), .D (n_10112), .Q + (u11_din_tmp_52), .QN ()); + DFFX1 \u11_din_tmp1_reg[12] (.CK (clk_i), .D (n_10111), .Q + (u11_din_tmp_53), .QN ()); + DFFX1 \u11_din_tmp1_reg[13] (.CK (clk_i), .D (n_10110), .Q + (u11_din_tmp_54), .QN ()); + DFFX1 \u11_din_tmp1_reg[14] (.CK (clk_i), .D (n_10108), .Q + (u11_din_tmp_55), .QN ()); + DFFX1 \u11_din_tmp1_reg[15] (.CK (clk_i), .D (n_10106), .Q + (u11_din_tmp_56), .QN ()); + DFFX1 \u11_din_tmp1_reg[1] (.CK (clk_i), .D (n_10105), .Q + (u11_din_tmp_42), .QN ()); + DFFX1 \u11_din_tmp1_reg[2] (.CK (clk_i), .D (n_10104), .Q + (u11_din_tmp_43), .QN ()); + DFFX1 \u11_din_tmp1_reg[3] (.CK (clk_i), .D (n_10102), .Q + (u11_din_tmp_44), .QN ()); + DFFX1 \u11_din_tmp1_reg[5] (.CK (clk_i), .D (n_10100), .Q + (u11_din_tmp_46), .QN ()); + DFFX1 \u11_din_tmp1_reg[6] (.CK (clk_i), .D (n_10099), .Q + (u11_din_tmp_47), .QN ()); + DFFX1 \u11_din_tmp1_reg[7] (.CK (clk_i), .D (n_10098), .Q + (u11_din_tmp_48), .QN ()); + DFFX1 \u11_din_tmp1_reg[9] (.CK (clk_i), .D (n_10096), .Q + (u11_din_tmp_50), .QN ()); + DFFX1 \u9_mem_reg[2][9] (.CK (clk_i), .D (n_10264), .Q (), .QN + (\u9_mem[2]_96 )); + DFFSRX1 \u18_int_set_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10344), .Q (), .QN (oc1_int_set_709)); + DFFSRX1 \u19_int_set_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10343), .Q (), .QN (oc2_int_set_711)); + DFFSRX1 \u24_int_set_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10342), .Q (), .QN (ic1_int_set_722)); + DFFSRX1 u15_crac_wr_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10339), .Q (crac_wr), .QN ()); + DFFSRX1 \u13_ints_r_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10399), .Q (\u13_ints_r[1] ), .QN ()); + OAI21X1 g31069(.A0 (n_5491), .A1 (n_10880), .B0 (n_10353), .Y + (n_10853)); + OAI21X1 g31070(.A0 (n_5497), .A1 (n_10820), .B0 (n_10352), .Y + (n_10852)); + OAI21X1 g31071(.A0 (n_5493), .A1 (n_10820), .B0 (n_10351), .Y + (n_10851)); + OAI21X1 g31072(.A0 (n_5501), .A1 (n_10820), .B0 (n_10350), .Y + (n_10850)); + OAI21X1 g31073(.A0 (n_5503), .A1 (n_10820), .B0 (n_10349), .Y + (n_10849)); + OAI21X1 g31074(.A0 (n_5499), .A1 (n_10820), .B0 (n_10348), .Y + (n_10848)); + OAI21X1 g31075(.A0 (n_5525), .A1 (n_10820), .B0 (n_10347), .Y + (n_10847)); + OAI21X1 g31076(.A0 (n_5509), .A1 (n_10880), .B0 (n_10346), .Y + (n_10846)); + OAI21X1 g31077(.A0 (n_5523), .A1 (n_10880), .B0 (n_10345), .Y + (n_10845)); + MX2X1 g31179(.A (n_6516), .B (n_6515), .S0 (n_10839), .Y (n_10844)); + MX2X1 g31180(.A (n_6512), .B (n_6511), .S0 (n_10820), .Y (n_10843)); + MX2X1 g31183(.A (n_5991), .B (n_5990), .S0 (n_9818), .Y (n_10842)); + DFFX1 \u10_mem_reg[0][20] (.CK (clk_i), .D (n_10130), .Q (), .QN + (\u10_mem[0]_169 )); + MX2X1 g31207(.A (n_5979), .B (n_5978), .S0 (n_10839), .Y (n_10841)); + MX2X1 g31209(.A (n_6455), .B (n_6454), .S0 (n_10839), .Y (n_10840)); + MX2X1 g31219(.A (n_6531), .B (n_6530), .S0 (n_10839), .Y (n_10838)); + MX2X1 g31220(.A (n_6432), .B (n_6431), .S0 (n_10839), .Y (n_10837)); + MX2X1 g31229(.A (n_6024), .B (n_6023), .S0 (n_10839), .Y (n_10836)); + MX2X1 g31230(.A (n_6027), .B (n_6026), .S0 (n_10839), .Y (n_10834)); + OR2X1 g29970(.A (\u13_ints_r[14] ), .B (oc4_int_set), .Y (n_10833)); + OR2X1 g29971(.A (\u13_ints_r[17] ), .B (oc5_int_set), .Y (n_10832)); + OR2X1 g29972(.A (\u13_ints_r[2] ), .B (oc0_int_set), .Y (n_10831)); + OR2X1 g29974(.A (\u13_ints_r[8] ), .B (oc2_int_set), .Y (n_10830)); + MX2X1 g31242(.A (n_6557), .B (n_6556), .S0 (n_10839), .Y (n_10829)); + MX2X1 g31243(.A (n_6659), .B (n_6658), .S0 (n_9818), .Y (n_10828)); + MX2X1 g31245(.A (n_6626), .B (n_6625), .S0 (n_9818), .Y (n_10827)); + XOR2X1 g31246(.A (n_610), .B (n_9908), .Y (n_10825)); + XOR2X1 g31272(.A (n_634), .B (n_9907), .Y (n_10822)); + MX2X1 g31285(.A (n_6378), .B (n_6377), .S0 (n_10820), .Y (n_10821)); + MX2X1 g31287(.A (n_6373), .B (n_6372), .S0 (n_10820), .Y (n_10819)); + MX2X1 g31288(.A (n_6371), .B (n_6370), .S0 (n_10820), .Y (n_10818)); + MX2X1 g31291(.A (n_6367), .B (n_6366), .S0 (n_9818), .Y (n_10817)); + MX2X1 g31290(.A (n_6369), .B (n_6368), .S0 (n_9818), .Y (n_10815)); + MX2X1 g31293(.A (n_6364), .B (n_6363), .S0 (n_9818), .Y (n_10814)); + MX2X1 g31295(.A (n_6361), .B (n_6360), .S0 (n_9818), .Y (n_10813)); + MX2X1 g31301(.A (n_6389), .B (n_6388), .S0 (n_9818), .Y (n_10812)); + XOR2X1 g31327(.A (n_784), .B (n_9902), .Y (n_10811)); + XOR2X1 g31346(.A (\u7_rp[0] ), .B (n_9901), .Y (n_10810)); + AOI21X1 g30026(.A0 (n_9607), .A1 (n_9768), .B0 (n_10401), .Y + (n_10809)); + AOI21X1 g30028(.A0 (n_9605), .A1 (n_9766), .B0 (n_10400), .Y + (n_10808)); + AND2X1 g30714(.A (n_10140), .B (n_2343), .Y (n_10807)); + AND2X1 g30715(.A (n_10139), .B (n_9833), .Y (n_10806)); + DFFX1 \u0_slt9_r_reg[3] (.CK (bit_clk_pad_i), .D (n_9953), .Q + (u0_slt9_r_170), .QN ()); + OAI21X1 g31058(.A0 (n_4766), .A1 (n_10679), .B0 (n_9980), .Y + (n_10805)); + MX2X1 g30078(.A (u1_sr_129), .B (in_slt_839), .S0 (out_le_181), .Y + (n_10804)); + MX2X1 g30079(.A (u1_sr_129), .B (in_slt_409), .S0 (out_le_182), .Y + (n_10803)); + MX2X1 g30080(.A (u1_sr_129), .B (in_slt_431), .S0 (out_le_183), .Y + (n_10802)); + AND2X1 g30809(.A (n_9964), .B (n_11600), .Y (n_10801)); + MX2X1 g30081(.A (u1_sr_129), .B (in_slt_453), .S0 (out_le_184), .Y + (n_10800)); + DFFX1 \u10_din_tmp1_reg[13] (.CK (clk_i), .D (n_9856), .Q + (u10_din_tmp_54), .QN ()); + NAND3X1 g31737(.A (n_6816), .B (n_10518), .C (n_1873), .Y (n_11109)); + AOI21X1 g31742(.A0 (n_9543), .A1 (n_12689), .B0 (n_616), .Y + (n_10799)); + AOI21X1 g31748(.A0 (n_9536), .A1 (n_10518), .B0 (n_676), .Y + (n_10798)); + AOI21X1 g31751(.A0 (n_9534), .A1 (n_12161), .B0 (n_668), .Y + (n_10796)); + NAND3X1 g31752(.A (n_6773), .B (n_12503), .C (n_1481), .Y (n_11105)); + AOI21X1 g31754(.A0 (n_9532), .A1 (n_10483), .B0 (n_611), .Y + (n_10795)); + INVX1 g31759(.A (n_10341), .Y (n_10794)); + NAND3X1 g31762(.A (n_12115), .B (n_12689), .C (n_862), .Y (n_11100)); + NAND3X1 g31764(.A (n_6259), .B (n_10483), .C (n_8182), .Y (n_11097)); + AOI21X1 g31784(.A0 (n_10790), .A1 (n_10787), .B0 (n_9941), .Y + (n_10791)); + AOI21X1 g31785(.A0 (n_10788), .A1 (n_10787), .B0 (n_9940), .Y + (n_10789)); + AOI21X1 g31787(.A0 (n_10785), .A1 (n_9931), .B0 (n_9921), .Y + (n_10786)); + AOI21X1 g31788(.A0 (n_10783), .A1 (n_9931), .B0 (n_9920), .Y + (n_10784)); + AOI22X1 g31807(.A0 (n_9795), .A1 (u15_crac_rd), .B0 (crac_out_876), + .B1 (u15_crac_we_r), .Y (n_10781)); + DFFX1 \u1_slt6_reg[12] (.CK (bit_clk_pad_i), .D (n_9954), .Q + (in_slt_452), .QN ()); + AND2X1 g30908(.A (n_9961), .B (n_11600), .Y (n_10780)); + AND2X1 g30911(.A (n_9960), .B (n_11600), .Y (n_10778)); + NAND2X1 g30924(.A (n_10086), .B (n_9910), .Y (n_10777)); + AOI21X1 g30933(.A0 (n_11893), .A1 (n_12278), .B0 (n_9966), .Y + (n_10776)); + AOI21X1 g30934(.A0 (n_12339), .A1 (n_763), .B0 (n_9965), .Y + (n_10775)); + AOI21X1 g30937(.A0 (n_11891), .A1 (n_762), .B0 (n_9963), .Y + (n_10774)); + AOI21X1 g30939(.A0 (n_11889), .A1 (n_754), .B0 (n_9962), .Y + (n_10773)); + OAI21X1 g30946(.A0 (n_5426), .A1 (n_10679), .B0 (n_10084), .Y + (n_10772)); + OAI21X1 g30947(.A0 (n_5425), .A1 (n_10450), .B0 (n_10082), .Y + (n_10771)); + OAI21X1 g30948(.A0 (n_5380), .A1 (n_10450), .B0 (n_10080), .Y + (n_10770)); + OAI21X1 g30949(.A0 (n_4793), .A1 (n_10450), .B0 (n_10079), .Y + (n_10769)); + OAI21X1 g30950(.A0 (n_5379), .A1 (n_10679), .B0 (n_10078), .Y + (n_10768)); + OAI21X1 g30951(.A0 (n_5283), .A1 (n_10450), .B0 (n_10076), .Y + (n_10766)); + OAI21X1 g30952(.A0 (n_5740), .A1 (n_10747), .B0 (n_10075), .Y + (n_10765)); + OAI21X1 g30953(.A0 (n_5738), .A1 (n_10747), .B0 (n_10074), .Y + (n_10764)); + OAI21X1 g30954(.A0 (n_5378), .A1 (n_10450), .B0 (n_10072), .Y + (n_10763)); + OAI21X1 g30955(.A0 (n_5377), .A1 (n_10450), .B0 (n_10071), .Y + (n_10762)); + OAI21X1 g30956(.A0 (n_4762), .A1 (n_10450), .B0 (n_10069), .Y + (n_10760)); + OAI21X1 g30957(.A0 (n_4760), .A1 (n_10679), .B0 (n_10067), .Y + (n_10758)); + OAI21X1 g30958(.A0 (n_4752), .A1 (n_10450), .B0 (n_10066), .Y + (n_10757)); + OAI21X1 g30959(.A0 (n_5737), .A1 (n_10747), .B0 (n_10064), .Y + (n_10756)); + OAI21X1 g30960(.A0 (n_5731), .A1 (n_10747), .B0 (n_9991), .Y + (n_10755)); + OAI21X1 g30961(.A0 (n_4791), .A1 (n_10747), .B0 (n_10063), .Y + (n_10754)); + OAI21X1 g30962(.A0 (n_4790), .A1 (n_10738), .B0 (n_10062), .Y + (n_10753)); + OAI21X1 g30963(.A0 (n_5342), .A1 (n_10450), .B0 (n_10058), .Y + (n_10752)); + OAI21X1 g30964(.A0 (n_4794), .A1 (n_10738), .B0 (n_10060), .Y + (n_10751)); + OAI21X1 g30965(.A0 (n_4789), .A1 (n_10747), .B0 (n_10059), .Y + (n_10750)); + OAI21X1 g30966(.A0 (n_4754), .A1 (n_10747), .B0 (n_9995), .Y + (n_10748)); + OAI21X1 g30967(.A0 (n_4788), .A1 (n_10747), .B0 (n_10057), .Y + (n_10746)); + OAI21X1 g30968(.A0 (n_4750), .A1 (n_10738), .B0 (n_10056), .Y + (n_10744)); + OAI21X1 g30969(.A0 (n_4786), .A1 (n_10747), .B0 (n_10055), .Y + (n_10743)); + OAI21X1 g30970(.A0 (n_4785), .A1 (n_10738), .B0 (n_10053), .Y + (n_10742)); + OAI21X1 g30971(.A0 (n_4784), .A1 (n_10747), .B0 (n_10052), .Y + (n_10740)); + OAI21X1 g30972(.A0 (n_4782), .A1 (n_10738), .B0 (n_10050), .Y + (n_10739)); + OAI21X1 g30973(.A0 (n_4781), .A1 (n_10747), .B0 (n_10049), .Y + (n_10737)); + OAI21X1 g30974(.A0 (n_5331), .A1 (n_10450), .B0 (n_10048), .Y + (n_10735)); + OAI21X1 g30975(.A0 (n_5340), .A1 (n_10679), .B0 (n_10047), .Y + (n_10733)); + OAI21X1 g30976(.A0 (n_5735), .A1 (n_10019), .B0 (n_10046), .Y + (n_10732)); + OAI21X1 g30977(.A0 (n_5734), .A1 (n_10747), .B0 (n_10044), .Y + (n_10731)); + OAI21X1 g30978(.A0 (n_4779), .A1 (n_10738), .B0 (n_10043), .Y + (n_10730)); + OAI21X1 g30979(.A0 (n_4748), .A1 (n_10738), .B0 (n_10042), .Y + (n_10728)); + OAI21X1 g30980(.A0 (n_4777), .A1 (n_10747), .B0 (n_10041), .Y + (n_10727)); + OAI21X1 g30981(.A0 (n_4758), .A1 (n_10738), .B0 (n_10040), .Y + (n_10725)); + OAI21X1 g30982(.A0 (n_4775), .A1 (n_10747), .B0 (n_10038), .Y + (n_10723)); + OAI21X1 g30983(.A0 (n_4756), .A1 (n_10738), .B0 (n_9994), .Y + (n_10722)); + OAI21X1 g30984(.A0 (n_4774), .A1 (n_10747), .B0 (n_10037), .Y + (n_10721)); + OAI21X1 g30985(.A0 (n_4744), .A1 (n_10738), .B0 (n_10035), .Y + (n_10719)); + OAI21X1 g30986(.A0 (n_4773), .A1 (n_10747), .B0 (n_10034), .Y + (n_10718)); + OAI21X1 g30987(.A0 (n_4770), .A1 (n_10019), .B0 (n_10032), .Y + (n_10717)); + OAI21X1 g30988(.A0 (n_4765), .A1 (n_10019), .B0 (n_10031), .Y + (n_10715)); + OAI21X1 g30989(.A0 (n_4768), .A1 (n_10738), .B0 (n_10030), .Y + (n_10714)); + OAI21X1 g30990(.A0 (n_6090), .A1 (n_10738), .B0 (n_10029), .Y + (n_10713)); + OAI21X1 g30991(.A0 (n_6088), .A1 (n_10747), .B0 (n_10028), .Y + (n_10712)); + OAI21X1 g30992(.A0 (n_5295), .A1 (n_10747), .B0 (n_10027), .Y + (n_10711)); + OAI21X1 g30993(.A0 (n_5375), .A1 (n_10747), .B0 (n_10026), .Y + (n_10710)); + OAI21X1 g30994(.A0 (n_5344), .A1 (n_10019), .B0 (n_10025), .Y + (n_10709)); + OAI21X1 g30995(.A0 (n_5373), .A1 (n_10747), .B0 (n_10023), .Y + (n_10708)); + OAI21X1 g30996(.A0 (n_5334), .A1 (n_10747), .B0 (n_10022), .Y + (n_10707)); + OAI21X1 g30997(.A0 (n_5303), .A1 (n_10747), .B0 (n_10020), .Y + (n_10706)); + OAI21X1 g30998(.A0 (n_5370), .A1 (n_10747), .B0 (n_9997), .Y + (n_10705)); + OAI21X1 g30999(.A0 (n_5368), .A1 (n_10738), .B0 (n_10018), .Y + (n_10704)); + OAI21X1 g31000(.A0 (n_5348), .A1 (n_10738), .B0 (n_10017), .Y + (n_10703)); + OAI21X1 g31001(.A0 (n_5346), .A1 (n_10738), .B0 (n_10016), .Y + (n_10702)); + OAI21X1 g31002(.A0 (n_5366), .A1 (n_10747), .B0 (n_10015), .Y + (n_10701)); + OAI21X1 g31003(.A0 (n_5351), .A1 (n_10738), .B0 (n_10014), .Y + (n_10700)); + OAI21X1 g31004(.A0 (n_5578), .A1 (n_10450), .B0 (n_10013), .Y + (n_10699)); + OAI21X1 g31005(.A0 (n_5576), .A1 (n_10450), .B0 (n_10012), .Y + (n_10697)); + OAI21X1 g31006(.A0 (n_5521), .A1 (n_10679), .B0 (n_10011), .Y + (n_10695)); + OAI21X1 g31007(.A0 (n_5364), .A1 (n_10450), .B0 (n_10009), .Y + (n_10694)); + OAI21X1 g31008(.A0 (n_5519), .A1 (n_10450), .B0 (n_10008), .Y + (n_10693)); + OAI21X1 g31009(.A0 (n_5517), .A1 (n_10679), .B0 (n_10007), .Y + (n_10691)); + OAI21X1 g31010(.A0 (n_5515), .A1 (n_10679), .B0 (n_10006), .Y + (n_10690)); + OAI21X1 g31011(.A0 (n_5513), .A1 (n_10679), .B0 (n_10005), .Y + (n_10688)); + OAI21X1 g31012(.A0 (n_5360), .A1 (n_10679), .B0 (n_10004), .Y + (n_10686)); + OAI21X1 g31013(.A0 (n_5358), .A1 (n_10450), .B0 (n_10003), .Y + (n_10685)); + OAI21X1 g31014(.A0 (n_5353), .A1 (n_10450), .B0 (n_10002), .Y + (n_10684)); + OAI21X1 g31015(.A0 (n_5511), .A1 (n_10450), .B0 (n_10001), .Y + (n_10682)); + OAI21X1 g31016(.A0 (n_5507), .A1 (n_10450), .B0 (n_10000), .Y + (n_10681)); + OAI21X1 g31017(.A0 (n_5505), .A1 (n_10679), .B0 (n_9999), .Y + (n_10680)); + OAI21X1 g31018(.A0 (n_5419), .A1 (n_10679), .B0 (n_9993), .Y + (n_10678)); + OAI21X1 g31021(.A0 (n_5415), .A1 (n_10450), .B0 (n_9992), .Y + (n_10677)); + OAI21X1 g31044(.A0 (n_5408), .A1 (n_10450), .B0 (n_9988), .Y + (n_10676)); + OAI21X1 g31047(.A0 (n_5423), .A1 (n_10450), .B0 (n_9987), .Y + (n_10675)); + OAI21X1 g31051(.A0 (n_5293), .A1 (n_10450), .B0 (n_9986), .Y + (n_10674)); + OAI21X1 g31053(.A0 (n_4746), .A1 (n_10679), .B0 (n_9985), .Y + (n_10673)); + OAI21X1 g31054(.A0 (n_5291), .A1 (n_10679), .B0 (n_9984), .Y + (n_10672)); + OAI21X1 g31055(.A0 (n_5289), .A1 (n_10450), .B0 (n_9983), .Y + (n_10671)); + DFFSRX1 \u13_ints_r_reg[26] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10083), .Q (\u13_ints_r[26] ), .QN ()); + DFFX1 \u1_slt0_reg[12] (.CK (bit_clk_pad_i), .D (n_9958), .Q + (in_slt_739), .QN ()); + DFFX1 \u1_slt2_reg[12] (.CK (bit_clk_pad_i), .D (n_9957), .Q + (in_slt_838), .QN ()); + DFFX1 \u1_slt3_reg[12] (.CK (bit_clk_pad_i), .D (n_9956), .Q + (in_slt_408), .QN ()); + DFFX1 \u1_slt4_reg[12] (.CK (bit_clk_pad_i), .D (n_9955), .Q + (in_slt_430), .QN ()); + OAI21X1 g31056(.A0 (n_5288), .A1 (n_10450), .B0 (n_9982), .Y + (n_10670)); + DFFX1 \u10_din_tmp1_reg[11] (.CK (clk_i), .D (n_9858), .Q + (u10_din_tmp_52), .QN ()); + OAI21X1 g31057(.A0 (n_5356), .A1 (n_10450), .B0 (n_9981), .Y + (n_10669)); + OAI21X1 g31061(.A0 (n_5285), .A1 (n_10450), .B0 (n_9977), .Y + (n_10668)); + OAI21X1 g31059(.A0 (n_4780), .A1 (n_10679), .B0 (n_9979), .Y + (n_10667)); + OAI21X1 g31060(.A0 (n_4792), .A1 (n_10679), .B0 (n_9978), .Y + (n_10666)); + DFFSRX1 \u9_wp_reg[0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9951), .Q (n_1203), .QN ()); + OAI21X1 g31068(.A0 (n_5349), .A1 (n_10450), .B0 (n_9975), .Y + (n_10665)); + DFFX1 \u10_din_tmp1_reg[5] (.CK (clk_i), .D (n_9868), .Q + (u10_din_tmp_46), .QN ()); + DFFX1 \u10_din_tmp1_reg[3] (.CK (clk_i), .D (n_9871), .Q + (u10_din_tmp_44), .QN ()); + OAI21X1 g31065(.A0 (n_5362), .A1 (n_10450), .B0 (n_9976), .Y + (n_10664)); + DFFX1 \u10_din_tmp1_reg[1] (.CK (clk_i), .D (n_9853), .Q + (u10_din_tmp_42), .QN ()); + DFFX1 \u10_din_tmp1_reg[2] (.CK (clk_i), .D (n_9872), .Q + (u10_din_tmp_43), .QN ()); + DFFX1 \u10_din_tmp1_reg[4] (.CK (clk_i), .D (n_9869), .Q + (u10_din_tmp_45), .QN ()); + DFFX1 \u10_din_tmp1_reg[6] (.CK (clk_i), .D (n_9867), .Q + (u10_din_tmp_47), .QN ()); + DFFX1 \u10_din_tmp1_reg[8] (.CK (clk_i), .D (n_9863), .Q + (u10_din_tmp_49), .QN ()); + DFFX1 \u10_din_tmp1_reg[9] (.CK (clk_i), .D (n_9862), .Q + (u10_din_tmp_50), .QN ()); + DFFX1 \u10_din_tmp1_reg[7] (.CK (clk_i), .D (n_9865), .Q + (u10_din_tmp_48), .QN ()); + DFFX1 \u10_din_tmp1_reg[0] (.CK (clk_i), .D (n_9861), .Q + (u10_din_tmp1), .QN ()); + DFFX1 \u10_din_tmp1_reg[10] (.CK (clk_i), .D (n_9859), .Q + (u10_din_tmp_51), .QN ()); + DFFX1 \u10_din_tmp1_reg[15] (.CK (clk_i), .D (n_9854), .Q + (u10_din_tmp_56), .QN ()); + DFFX1 \u10_din_tmp1_reg[14] (.CK (clk_i), .D (n_9855), .Q + (u10_din_tmp_55), .QN ()); + DFFX1 \u10_din_tmp1_reg[12] (.CK (clk_i), .D (n_9857), .Q + (u10_din_tmp_53), .QN ()); + DFFSRX1 u15_rdd1_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9884), .Q (u15_rdd1), .QN ()); + DFFSRX1 u15_rdd2_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9883), .Q (), .QN (u15_rdd2)); + AOI21X1 g31078(.A0 (n_11893), .A1 (\u8_rp[3] ), .B0 (n_9974), .Y + (n_10663)); + AOI21X1 g31079(.A0 (n_12339), .A1 (\u3_rp[3] ), .B0 (n_9973), .Y + (n_10661)); + AOI21X1 g31082(.A0 (n_11891), .A1 (\u6_rp[3] ), .B0 (n_9969), .Y + (n_10659)); + AOI21X1 g31083(.A0 (n_11889), .A1 (\u7_rp[3] ), .B0 (n_9967), .Y + (n_10657)); + MX2X1 g31084(.A (n_6651), .B (n_6650), .S0 (n_10537), .Y (n_10655)); + MX2X1 g31086(.A (n_6036), .B (n_6035), .S0 (n_10537), .Y (n_10654)); + MX2X1 g31095(.A (n_6029), .B (n_6028), .S0 (n_10450), .Y (n_10652)); + MX2X1 g31132(.A (n_6624), .B (n_6623), .S0 (n_9724), .Y (n_10651)); + NAND2X1 g32624(.A (n_160), .B (n_10583), .Y (n_11632)); + MX2X1 g31142(.A (n_6613), .B (n_6612), .S0 (n_9724), .Y (n_10649)); + NAND2X1 g32666(.A (n_387), .B (n_10645), .Y (n_11965)); + NAND2X1 g32667(.A (n_229), .B (n_10645), .Y (n_11971)); + NAND2X1 g32668(.A (n_401), .B (n_10645), .Y (n_11969)); + NAND2X1 g32669(.A (n_259), .B (n_10645), .Y (n_11953)); + NAND2X1 g32670(.A (n_186), .B (n_10645), .Y (n_11979)); + NAND2X1 g32671(.A (n_134), .B (n_10645), .Y (n_11955)); + NAND2X1 g32672(.A (n_254), .B (n_10645), .Y (n_11991)); + NAND2X1 g32673(.A (n_163), .B (n_10645), .Y (n_11975)); + NAND2X1 g32674(.A (n_230), .B (n_10605), .Y (n_11734)); + NAND2X1 g32675(.A (n_399), .B (n_10645), .Y (n_10636)); + NAND2X1 g32676(.A (n_299), .B (n_10645), .Y (n_11973)); + AOI21X1 g32677(.A0 (n_6784), .A1 (n_5845), .B0 (n_9876), .Y + (n_10634)); + AOI21X1 g32678(.A0 (n_6227), .A1 (n_6225), .B0 (n_9876), .Y + (n_10633)); + NAND2X1 g32679(.A (n_335), .B (n_10645), .Y (n_11957)); + NAND2X1 g32680(.A (n_201), .B (n_10645), .Y (n_11959)); + NAND2X1 g32681(.A (n_217), .B (n_10645), .Y (n_11997)); + NAND2X1 g32682(.A (n_363), .B (n_10645), .Y (n_11961)); + NAND2X1 g32688(.A (n_265), .B (n_10645), .Y (n_11963)); + NAND2X1 g32689(.A (n_375), .B (n_10645), .Y (n_11977)); + NAND2X1 g32694(.A (n_167), .B (n_10617), .Y (n_10626)); + NAND2X1 g32695(.A (n_181), .B (n_10617), .Y (n_10625)); + NAND2X1 g32696(.A (n_212), .B (n_10617), .Y (n_10623)); + NAND2X1 g32698(.A (n_76), .B (n_10617), .Y (n_10622)); + NAND2X1 g32700(.A (n_228), .B (n_10617), .Y (n_10621)); + NAND2X1 g32702(.A (n_237), .B (n_10617), .Y (n_10620)); + NAND2X1 g32703(.A (n_79), .B (n_10617), .Y (n_10619)); + NAND2X1 g32704(.A (n_240), .B (n_10617), .Y (n_10618)); + NAND2X1 g32705(.A (n_86), .B (n_10617), .Y (n_10616)); + NAND2X1 g32706(.A (n_328), .B (n_10617), .Y (n_10615)); + AOI21X1 g32707(.A0 (n_6205), .A1 (n_6203), .B0 (n_10617), .Y + (n_10614)); + AOI21X1 g32708(.A0 (n_6265), .A1 (n_6229), .B0 (n_10617), .Y + (n_10613)); + NAND2X1 g32709(.A (n_182), .B (n_10617), .Y (n_12194)); + NAND2X1 g32710(.A (n_280), .B (n_10617), .Y (n_12196)); + NAND2X1 g32711(.A (n_352), .B (n_10617), .Y (n_12065)); + NAND2X1 g32712(.A (n_362), .B (n_10617), .Y (n_10609)); + NAND2X1 g32713(.A (n_376), .B (n_10617), .Y (n_12794)); + NAND2X1 g32714(.A (n_384), .B (n_10617), .Y (n_10607)); + NAND2X1 g32716(.A (n_389), .B (n_10605), .Y (n_11744)); + NAND2X1 g32717(.A (n_398), .B (n_10605), .Y (n_11746)); + NAND2X1 g32718(.A (n_157), .B (n_10605), .Y (n_11750)); + NAND2X1 g32719(.A (n_195), .B (n_10605), .Y (n_11724)); + NAND2X1 g32720(.A (n_267), .B (n_10605), .Y (n_10601)); + MX2X1 g31155(.A (n_6019), .B (n_6018), .S0 (n_10565), .Y (n_10600)); + NAND2X1 g32721(.A (n_282), .B (n_10605), .Y (n_10599)); + NAND2X1 g32722(.A (n_281), .B (n_10605), .Y (n_12453)); + NAND2X1 g32723(.A (n_109), .B (n_10605), .Y (n_11748)); + NAND2X1 g32724(.A (n_16), .B (n_10605), .Y (n_10595)); + NAND2X1 g32726(.A (n_308), .B (n_10583), .Y (n_11634)); + NAND2X1 g32727(.A (n_329), .B (n_10605), .Y (n_10592)); + NAND2X1 g32728(.A (n_302), .B (n_10583), .Y (n_11614)); + NAND2X1 g32729(.A (n_152), .B (n_10583), .Y (n_11616)); + AOI21X1 g32730(.A0 (n_6185), .A1 (n_6151), .B0 (n_10605), .Y + (n_10589)); + NAND2X1 g32731(.A (n_203), .B (n_10583), .Y (n_11618)); + AOI21X1 g32732(.A0 (n_6179), .A1 (n_6177), .B0 (n_10605), .Y + (n_10587)); + NAND2X1 g32733(.A (n_263), .B (n_10583), .Y (n_11620)); + NAND2X1 g32734(.A (n_348), .B (n_10605), .Y (n_12063)); + NAND2X1 g32735(.A (n_297), .B (n_10583), .Y (n_11628)); + NAND2X1 g32736(.A (n_200), .B (n_10605), .Y (n_11995)); + NAND2X1 g32737(.A (n_208), .B (n_10583), .Y (n_11622)); + NAND2X1 g32738(.A (n_150), .B (n_10583), .Y (n_11624)); + NAND2X1 g32739(.A (n_211), .B (n_10605), .Y (n_11732)); + NAND2X1 g32740(.A (n_19), .B (n_10583), .Y (n_11626)); + NAND2X1 g32741(.A (n_82), .B (n_10605), .Y (n_11736)); + NAND2X1 g32742(.A (n_383), .B (n_10583), .Y (n_11630)); + NAND2X1 g32743(.A (n_341), .B (n_10605), .Y (n_12017)); + AOI21X1 g32744(.A0 (n_6160), .A1 (n_5804), .B0 (n_9873), .Y + (n_10574)); + AOI21X1 g32750(.A0 (n_6245), .A1 (n_6251), .B0 (n_9873), .Y + (n_10573)); + NAND2X1 g32751(.A (n_322), .B (n_10583), .Y (n_11636)); + NAND2X1 g32752(.A (n_359), .B (n_10583), .Y (n_11993)); + NAND2X1 g32753(.A (n_372), .B (n_10583), .Y (n_11638)); + NAND2X1 g32754(.A (n_191), .B (n_10583), .Y (n_11640)); + NAND2X1 g32755(.A (n_183), .B (n_10583), .Y (n_11642)); + MX2X1 g31168(.A (n_6580), .B (n_6578), .S0 (n_10565), .Y (n_10567)); + MX2X1 g31169(.A (n_6577), .B (n_6575), .S0 (n_10565), .Y (n_10566)); + MX2X1 g31175(.A (n_6001), .B (n_6000), .S0 (n_10565), .Y (n_10564)); + MX2X1 g31176(.A (n_6523), .B (n_6522), .S0 (n_10513), .Y (n_10563)); + MX2X1 g31177(.A (n_6520), .B (n_6519), .S0 (n_10513), .Y (n_10562)); + MX2X1 g31178(.A (n_6518), .B (n_6517), .S0 (n_10513), .Y (n_10561)); + MX2X1 g31181(.A (n_6508), .B (n_6507), .S0 (n_10513), .Y (n_10559)); + MX2X1 g31182(.A (n_6504), .B (n_6503), .S0 (n_10513), .Y (n_10558)); + MX2X1 g31184(.A (n_5989), .B (n_5988), .S0 (n_10513), .Y (n_10556)); + MX2X1 g31185(.A (n_6501), .B (n_6500), .S0 (n_9721), .Y (n_10555)); + MX2X1 g31186(.A (n_6499), .B (n_6498), .S0 (n_9721), .Y (n_10554)); + MX2X1 g31187(.A (n_6493), .B (n_6492), .S0 (n_10513), .Y (n_10552)); + MX2X1 g31188(.A (n_6491), .B (n_6490), .S0 (n_10513), .Y (n_10551)); + MX2X1 g31189(.A (n_6546), .B (n_6545), .S0 (n_10513), .Y (n_10549)); + MX2X1 g31190(.A (n_6488), .B (n_6487), .S0 (n_10513), .Y (n_10547)); + MX2X1 g31191(.A (n_6549), .B (n_6548), .S0 (n_10537), .Y (n_10546)); + MX2X1 g31192(.A (n_6485), .B (n_6484), .S0 (n_10537), .Y (n_10545)); + MX2X1 g31193(.A (n_5982), .B (n_5981), .S0 (n_10565), .Y (n_10544)); + MX2X1 g31194(.A (n_5985), .B (n_5984), .S0 (n_10513), .Y (n_10543)); + MX2X1 g31195(.A (n_6481), .B (n_419), .S0 (n_10513), .Y (n_10542)); + MX2X1 g31196(.A (n_6480), .B (n_6479), .S0 (n_10537), .Y (n_10540)); + MX2X1 g31198(.A (n_6474), .B (n_433), .S0 (n_10537), .Y (n_10539)); + MX2X1 g31200(.A (n_6472), .B (n_6471), .S0 (n_10537), .Y (n_10538)); + OAI21X1 g33020(.A0 (n_7257), .A1 (n_7193), .B0 (n_10518), .Y + (n_11964)); + MX2X1 g31201(.A (n_6670), .B (n_461), .S0 (n_10537), .Y (n_10535)); + OAI21X1 g33021(.A0 (n_7255), .A1 (n_7192), .B0 (n_10518), .Y + (n_11970)); + OAI21X1 g33022(.A0 (n_7254), .A1 (n_7190), .B0 (n_10518), .Y + (n_11968)); + OAI21X1 g33023(.A0 (n_7316), .A1 (n_6918), .B0 (n_10518), .Y + (n_11952)); + MX2X1 g31202(.A (n_6467), .B (n_6466), .S0 (n_10537), .Y (n_10529)); + OAI21X1 g33024(.A0 (n_7315), .A1 (n_7189), .B0 (n_10518), .Y + (n_11978)); + OAI21X1 g33025(.A0 (n_7253), .A1 (n_7016), .B0 (n_10518), .Y + (n_11954)); + OAI21X1 g33026(.A0 (n_7314), .A1 (n_7094), .B0 (n_10518), .Y + (n_11990)); + OAI21X1 g33027(.A0 (n_7251), .A1 (n_7188), .B0 (n_10518), .Y + (n_11974)); + OAI21X1 g33028(.A0 (n_7250), .A1 (n_7093), .B0 (n_10518), .Y + (n_10523)); + OAI21X1 g33029(.A0 (n_7249), .A1 (n_7186), .B0 (n_10518), .Y + (n_11972)); + MX2X1 g31204(.A (n_6461), .B (n_6460), .S0 (n_10513), .Y (n_10521)); + OAI21X1 g33030(.A0 (n_7248), .A1 (n_7184), .B0 (n_10518), .Y + (n_11956)); + OAI21X1 g33031(.A0 (n_7312), .A1 (n_7092), .B0 (n_10518), .Y + (n_11958)); + OAI21X1 g33032(.A0 (n_7311), .A1 (n_6991), .B0 (n_10518), .Y + (n_11996)); + OAI21X1 g33033(.A0 (n_7309), .A1 (n_6990), .B0 (n_10518), .Y + (n_11960)); + OAI21X1 g33034(.A0 (n_7246), .A1 (n_6989), .B0 (n_10518), .Y + (n_11962)); + MX2X1 g31206(.A (n_5995), .B (n_5994), .S0 (n_10513), .Y (n_10514)); + OAI21X1 g33035(.A0 (n_7245), .A1 (n_7183), .B0 (n_10518), .Y + (n_11976)); + OAI21X1 g33055(.A0 (n_7271), .A1 (n_7095), .B0 (n_10481), .Y + (n_11743)); + MX2X1 g31214(.A (n_6449), .B (n_6448), .S0 (n_10513), .Y (n_10508)); + OAI21X1 g33057(.A0 (n_7227), .A1 (n_7076), .B0 (n_10481), .Y + (n_11749)); + OAI21X1 g33059(.A0 (n_7225), .A1 (n_7073), .B0 (n_12689), .Y + (n_10504)); + MX2X1 g31215(.A (n_6446), .B (n_6445), .S0 (n_10513), .Y (n_10501)); + MX2X1 g31216(.A (n_6440), .B (n_6439), .S0 (n_10513), .Y (n_10498)); + OAI21X1 g33063(.A0 (n_7219), .A1 (n_7067), .B0 (n_10481), .Y + (n_10496)); + OAI21X1 g33064(.A0 (n_7218), .A1 (n_6984), .B0 (n_10483), .Y + (n_11633)); + MX2X1 g31217(.A (n_6438), .B (n_6437), .S0 (n_10513), .Y (n_10494)); + OAI21X1 g33065(.A0 (n_7217), .A1 (n_7066), .B0 (n_10481), .Y + (n_10493)); + OAI21X1 g33066(.A0 (n_7122), .A1 (n_7065), .B0 (n_10483), .Y + (n_11613)); + OAI21X1 g33067(.A0 (n_7121), .A1 (n_7064), .B0 (n_10483), .Y + (n_11615)); + MX2X1 g31218(.A (n_6435), .B (n_6434), .S0 (n_10513), .Y (n_10489)); + OAI21X1 g33068(.A0 (n_7216), .A1 (n_6983), .B0 (n_10483), .Y + (n_11617)); + OAI21X1 g33069(.A0 (n_7123), .A1 (n_7069), .B0 (n_10483), .Y + (n_11619)); + OAI21X1 g33070(.A0 (n_7215), .A1 (n_7062), .B0 (n_10481), .Y + (n_12062)); + OAI21X1 g33071(.A0 (n_7119), .A1 (n_6982), .B0 (n_10483), .Y + (n_11627)); + OAI21X1 g33072(.A0 (n_7244), .A1 (n_11901), .B0 (n_10481), .Y + (n_11994)); + OAI21X1 g33073(.A0 (n_7213), .A1 (n_7060), .B0 (n_10483), .Y + (n_11621)); + OAI21X1 g33074(.A0 (n_7118), .A1 (n_6979), .B0 (n_10483), .Y + (n_11623)); + OAI21X1 g33075(.A0 (n_7211), .A1 (n_7059), .B0 (n_12689), .Y + (n_11731)); + OAI21X1 g33076(.A0 (n_7210), .A1 (n_7058), .B0 (n_12689), .Y + (n_11733)); + MX2X1 g31221(.A (n_5970), .B (n_5969), .S0 (n_10537), .Y (n_10476)); + OAI21X1 g33077(.A0 (n_7124), .A1 (n_7057), .B0 (n_10483), .Y + (n_11625)); + OAI21X1 g33078(.A0 (n_7209), .A1 (n_7056), .B0 (n_10481), .Y + (n_11735)); + OAI21X1 g33079(.A0 (n_7117), .A1 (n_6978), .B0 (n_10483), .Y + (n_11629)); + MX2X1 g31222(.A (n_6555), .B (n_6554), .S0 (n_10537), .Y (n_10472)); + OAI21X1 g33080(.A0 (n_7208), .A1 (n_7055), .B0 (n_10481), .Y + (n_12016)); + OAI21X1 g33081(.A0 (n_7207), .A1 (n_7054), .B0 (n_10483), .Y + (n_11635)); + OAI21X1 g33082(.A0 (n_7205), .A1 (n_7053), .B0 (n_10483), .Y + (n_11992)); + MX2X1 g31223(.A (n_6429), .B (n_6428), .S0 (n_10537), .Y (n_10466)); + OAI21X1 g33083(.A0 (n_7204), .A1 (n_6977), .B0 (n_10483), .Y + (n_11637)); + OAI21X1 g33084(.A0 (n_7276), .A1 (n_6976), .B0 (n_10483), .Y + (n_11639)); + OAI21X1 g33085(.A0 (n_7172), .A1 (n_6975), .B0 (n_10483), .Y + (n_11631)); + MX2X1 g31224(.A (n_6427), .B (n_6426), .S0 (n_10537), .Y (n_10462)); + OAI21X1 g33086(.A0 (n_7114), .A1 (n_7052), .B0 (n_10483), .Y + (n_11641)); + MX2X1 g31225(.A (n_6605), .B (n_6604), .S0 (n_10537), .Y (n_10459)); + MX2X1 g31226(.A (n_6425), .B (n_6424), .S0 (n_10537), .Y (n_10458)); + MX2X1 g31227(.A (n_6422), .B (n_6421), .S0 (n_10537), .Y (n_10457)); + MX2X1 g31228(.A (n_6420), .B (n_6419), .S0 (n_10537), .Y (n_10456)); + MX2X1 g31232(.A (n_6414), .B (n_6413), .S0 (n_10513), .Y (n_10455)); + MX2X1 g31236(.A (n_6525), .B (n_6524), .S0 (n_10513), .Y (n_10454)); + MX2X1 g31238(.A (n_6418), .B (n_6417), .S0 (n_10513), .Y (n_10453)); + MX2X1 g31240(.A (n_6443), .B (n_6441), .S0 (n_10513), .Y (n_10452)); + MX2X1 g31283(.A (n_6383), .B (n_6382), .S0 (n_10450), .Y (n_10451)); + MX2X1 g31284(.A (n_6381), .B (n_6380), .S0 (n_10450), .Y (n_10449)); + DFFSRX1 \u20_int_set_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10091), .Q (oc3_int_set), .QN ()); + DFFSRX1 \u18_int_set_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_10092), .Q (oc1_int_set), .QN ()); + MX2X1 g31297(.A (n_5954), .B (n_5953), .S0 (n_10513), .Y (n_10448)); + MX2X1 g31299(.A (n_5952), .B (n_5951), .S0 (n_10513), .Y (n_10447)); + MX2X1 g31302(.A (n_5950), .B (n_5949), .S0 (n_10450), .Y (n_10446)); + MX2X1 g31303(.A (n_5657), .B (n_1634), .S0 (n_10513), .Y (n_10445)); + MX2X1 g31304(.A (n_5664), .B (n_1628), .S0 (n_10537), .Y (n_10444)); + MX2X1 g31305(.A (n_5655), .B (n_1755), .S0 (n_10537), .Y (n_10443)); + MX2X1 g31306(.A (n_5653), .B (n_1620), .S0 (n_9721), .Y (n_10441)); + MX2X1 g31308(.A (n_5666), .B (n_1615), .S0 (n_9721), .Y (n_10440)); + MX2X1 g31310(.A (n_5651), .B (n_1610), .S0 (n_10537), .Y (n_10439)); + MX2X1 g31311(.A (n_5472), .B (n_1244), .S0 (n_9724), .Y (n_10438)); + MX2X1 g31312(.A (n_5650), .B (n_1605), .S0 (n_10537), .Y (n_10437)); + MX2X1 g31313(.A (n_5660), .B (n_1600), .S0 (n_10513), .Y (n_10436)); + MX2X1 g31314(.A (n_5662), .B (n_2557), .S0 (n_9724), .Y (n_10435)); + MX2X1 g31315(.A (n_5644), .B (n_1596), .S0 (n_10513), .Y (n_10433)); + MX2X1 g31316(.A (n_5658), .B (n_1592), .S0 (n_10537), .Y (n_10432)); + MX2X1 g31319(.A (n_6358), .B (n_6357), .S0 (n_10537), .Y (n_10430)); + MX2X1 g31321(.A (n_5648), .B (n_1585), .S0 (n_10513), .Y (n_10429)); + MX2X1 g31322(.A (n_5659), .B (n_1581), .S0 (n_10513), .Y (n_10428)); + MX2X1 g31323(.A (n_5646), .B (n_2550), .S0 (n_9724), .Y (n_10426)); + MX2X1 g31324(.A (n_6356), .B (n_6355), .S0 (n_10513), .Y (n_10425)); + MX2X1 g31325(.A (n_6354), .B (n_6353), .S0 (n_10513), .Y (n_10424)); + MX2X1 g31326(.A (n_5471), .B (n_1677), .S0 (n_9724), .Y (n_10423)); + MX2X1 g31328(.A (n_6352), .B (n_6351), .S0 (n_10537), .Y (n_10422)); + MX2X1 g31329(.A (n_5470), .B (n_1240), .S0 (n_9724), .Y (n_10421)); + MX2X1 g31330(.A (n_6350), .B (n_6349), .S0 (n_10537), .Y (n_10420)); + MX2X1 g31331(.A (n_5469), .B (n_1238), .S0 (n_9724), .Y (n_10418)); + MX2X1 g31332(.A (n_6348), .B (n_6347), .S0 (n_10537), .Y (n_10417)); + MX2X1 g31333(.A (n_6345), .B (n_6344), .S0 (n_10537), .Y (n_10416)); + MX2X1 g31334(.A (n_5639), .B (n_2539), .S0 (n_10565), .Y (n_10415)); + MX2X1 g31335(.A (n_5948), .B (n_5947), .S0 (n_10537), .Y (n_10413)); + MX2X1 g31336(.A (n_6343), .B (n_6342), .S0 (n_10565), .Y (n_10412)); + MX2X1 g31341(.A (n_6336), .B (n_6335), .S0 (n_10565), .Y (n_10411)); + AOI21X1 g30025(.A0 (n_9557), .A1 (n_9701), .B0 (n_10090), .Y + (n_10409)); + AOI21X1 g30027(.A0 (n_9555), .A1 (n_9699), .B0 (n_10089), .Y + (n_10408)); + AOI21X1 g30029(.A0 (n_9553), .A1 (n_9697), .B0 (n_10088), .Y + (n_10407)); + AOI21X1 g30030(.A0 (n_9551), .A1 (n_9695), .B0 (n_10087), .Y + (n_10406)); + AOI21X1 g31395(.A0 (n_11893), .A1 (n_757), .B0 (n_10085), .Y + (n_10405)); + AOI21X1 g31396(.A0 (n_12339), .A1 (n_1096), .B0 (n_10068), .Y + (n_10404)); + AOI21X1 g31399(.A0 (n_11891), .A1 (n_11586), .B0 (n_9990), .Y + (n_10403)); + AOI21X1 g31400(.A0 (n_11889), .A1 (n_1184), .B0 (n_9989), .Y + (n_10402)); + OAI21X1 g30056(.A0 (n_9563), .A1 (n_9647), .B0 (n_9838), .Y + (n_10401)); + OAI21X1 g30058(.A0 (n_9561), .A1 (n_9645), .B0 (n_9837), .Y + (n_10400)); + NOR2X1 g31568(.A (n_9803), .B (n_6752), .Y (n_10399)); + NAND2X1 g31569(.A (n_3992), .B (n_12589), .Y (n_11513)); + NAND2X1 g31570(.A (n_4795), .B (n_11136), .Y (n_10397)); + NAND2X1 g31571(.A (n_4799), .B (n_11131), .Y (n_11511)); + NAND2X1 g31572(.A (n_4797), .B (n_11126), .Y (n_11509)); + AND2X1 g30798(.A (n_9841), .B (n_11564), .Y (n_10394)); + NAND2X1 g31664(.A (n_334), .B (n_10391), .Y (n_10393)); + NAND2X1 g31665(.A (n_312), .B (n_10391), .Y (n_10392)); + NAND2X1 g31674(.A (n_1650), .B (n_10391), .Y (n_10390)); + NAND2X1 g31675(.A (n_1644), .B (n_10391), .Y (n_10389)); + NAND2X1 g31676(.A (n_1633), .B (n_10385), .Y (n_10388)); + NAND2X1 g31677(.A (n_339), .B (n_10385), .Y (n_10387)); + NAND2X1 g31678(.A (n_1754), .B (n_10385), .Y (n_10386)); + NAND2X1 g31679(.A (n_1619), .B (n_10391), .Y (n_10384)); + NAND2X1 g31680(.A (n_1614), .B (n_10391), .Y (n_10383)); + NAND2X1 g31681(.A (n_1609), .B (n_10385), .Y (n_10382)); + NAND2X1 g31682(.A (n_1604), .B (n_10376), .Y (n_10380)); + NAND2X1 g31683(.A (n_1599), .B (n_10385), .Y (n_10379)); + NAND2X1 g31684(.A (n_1595), .B (n_10376), .Y (n_10378)); + NAND2X1 g31685(.A (n_1591), .B (n_10376), .Y (n_10377)); + NAND2X1 g31686(.A (n_1584), .B (n_10385), .Y (n_10375)); + NAND2X1 g31687(.A (n_1580), .B (n_10385), .Y (n_10374)); + NAND2X1 g31688(.A (n_129), .B (n_10391), .Y (n_10373)); + NAND2X1 g31689(.A (n_288), .B (n_10391), .Y (n_10372)); + NAND2X1 g31690(.A (n_81), .B (n_10385), .Y (n_10371)); + NAND2X1 g31691(.A (n_1627), .B (n_10376), .Y (n_10370)); + NAND2X1 g31692(.A (n_279), .B (n_10376), .Y (n_10369)); + NAND2X1 g31694(.A (n_277), .B (n_10376), .Y (n_10367)); + NAND2X1 g31695(.A (n_275), .B (n_10376), .Y (n_10366)); + NAND2X1 g31696(.A (n_270), .B (n_10385), .Y (n_10365)); + NAND2X1 g31698(.A (n_298), .B (n_10376), .Y (n_10364)); + NAND2X1 g31699(.A (n_236), .B (n_10376), .Y (n_10363)); + NAND2X1 g31701(.A (n_188), .B (n_10385), .Y (n_10362)); + NAND2X1 g31702(.A (n_125), .B (n_10376), .Y (n_10361)); + NAND2X1 g31703(.A (n_190), .B (n_10376), .Y (n_10360)); + NAND2X1 g31705(.A (n_122), .B (n_10376), .Y (n_10359)); + NAND2X1 g31714(.A (n_5580), .B (n_10391), .Y (n_10358)); + NAND2X1 g31716(.A (n_5582), .B (n_10391), .Y (n_10357)); + NAND2X1 g31717(.A (n_5494), .B (n_10385), .Y (n_10356)); + NAND2X1 g31718(.A (n_5526), .B (n_10385), .Y (n_10355)); + NAND2X1 g31720(.A (n_5488), .B (n_10385), .Y (n_10354)); + NAND2X1 g31721(.A (n_5490), .B (n_10391), .Y (n_10353)); + NAND2X1 g31723(.A (n_5496), .B (n_10376), .Y (n_10352)); + NAND2X1 g31724(.A (n_5492), .B (n_10376), .Y (n_10351)); + NAND2X1 g31725(.A (n_5500), .B (n_10376), .Y (n_10350)); + NAND2X1 g31726(.A (n_5502), .B (n_10376), .Y (n_10349)); + NAND2X1 g31727(.A (n_5498), .B (n_10385), .Y (n_10348)); + NAND2X1 g31728(.A (n_5524), .B (n_10391), .Y (n_10347)); + NAND2X1 g31729(.A (n_5508), .B (n_10385), .Y (n_10346)); + NAND2X1 g31730(.A (n_5522), .B (n_10385), .Y (n_10345)); + INVX1 g31743(.A (n_9972), .Y (n_10344)); + INVX1 g31745(.A (n_9970), .Y (n_10343)); + INVX1 g31757(.A (n_9968), .Y (n_10342)); + AOI21X1 g31760(.A0 (n_9672), .A1 (i6_full), .B0 (n_749), .Y + (n_10341)); + OAI21X1 g31780(.A0 (n_4848), .A1 (n_9631), .B0 (n_9835), .Y + (n_10340)); + DFFX1 \u1_sr_reg[14] (.CK (bit_clk_pad_i), .D (u1_sr_129), .Q + (u1_sr_130), .QN ()); + OAI21X1 g31789(.A0 (crac_out_876), .A1 (n_8486), .B0 (n_9794), .Y + (n_10339)); + MX2X1 g31808(.A (\u11_wp[1] ), .B (n_4073), .S0 (n_9672), .Y + (n_10338)); + OAI21X1 g31811(.A0 (n_5634), .A1 (n_9631), .B0 (n_9834), .Y + (n_10337)); + AND2X1 g30910(.A (n_9840), .B (n_11564), .Y (n_10335)); + NAND2X1 g30926(.A (n_9844), .B (n_9831), .Y (n_10333)); + NAND3X1 g30935(.A (n_12077), .B (n_12256), .C (n_10329), .Y + (n_10332)); + NAND3X1 g30936(.A (n_12214), .B (n_1908), .C (n_10327), .Y (n_10331)); + DFFSRX1 \u13_ints_r_reg[23] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9845), .Q (\u13_ints_r[23] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[20] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9846), .Q (\u13_ints_r[20] ), .QN ()); + DFFX1 \u9_wp_reg[1] (.CK (clk_i), .D (n_9836), .Q (\u9_wp[1] ), .QN + ()); + DFFX1 \u9_din_tmp1_reg[9] (.CK (clk_i), .D (n_9770), .Q + (u9_din_tmp_50), .QN ()); + DFFX1 \u9_din_tmp1_reg[3] (.CK (clk_i), .D (n_9776), .Q + (u9_din_tmp_44), .QN ()); + DFFX1 \u9_din_tmp1_reg[10] (.CK (clk_i), .D (n_9788), .Q + (u9_din_tmp_51), .QN ()); + DFFX1 \u9_din_tmp1_reg[14] (.CK (clk_i), .D (n_9782), .Q + (u9_din_tmp_55), .QN ()); + DFFX1 \u9_din_tmp1_reg[0] (.CK (clk_i), .D (n_9789), .Q + (u9_din_tmp1), .QN ()); + DFFX1 \u9_din_tmp1_reg[11] (.CK (clk_i), .D (n_9786), .Q + (u9_din_tmp_52), .QN ()); + DFFX1 \u9_din_tmp1_reg[12] (.CK (clk_i), .D (n_9785), .Q + (u9_din_tmp_53), .QN ()); + DFFX1 \u9_din_tmp1_reg[13] (.CK (clk_i), .D (n_9784), .Q + (u9_din_tmp_54), .QN ()); + DFFX1 \u9_din_tmp1_reg[15] (.CK (clk_i), .D (n_9780), .Q + (u9_din_tmp_56), .QN ()); + DFFX1 \u9_din_tmp1_reg[1] (.CK (clk_i), .D (n_9779), .Q + (u9_din_tmp_42), .QN ()); + DFFX1 \u9_din_tmp1_reg[2] (.CK (clk_i), .D (n_9778), .Q + (u9_din_tmp_43), .QN ()); + DFFX1 \u9_din_tmp1_reg[5] (.CK (clk_i), .D (n_9774), .Q + (u9_din_tmp_46), .QN ()); + DFFX1 \u9_din_tmp1_reg[6] (.CK (clk_i), .D (n_9773), .Q + (u9_din_tmp_47), .QN ()); + DFFX1 \u9_din_tmp1_reg[4] (.CK (clk_i), .D (n_9775), .Q + (u9_din_tmp_45), .QN ()); + DFFX1 \u9_din_tmp1_reg[8] (.CK (clk_i), .D (n_9771), .Q + (u9_din_tmp_49), .QN ()); + DFFX1 \u9_din_tmp1_reg[7] (.CK (clk_i), .D (n_9772), .Q + (u9_din_tmp_48), .QN ()); + DFFSRX1 u15_rdd3_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9796), .Q (u15_rdd3), .QN ()); + MX2X1 g31080(.A (\u4_rp[3] ), .B (n_5467), .S0 (n_10329), .Y + (n_10330)); + MX2X1 g31081(.A (\u5_rp[3] ), .B (n_4645), .S0 (n_10327), .Y + (n_10328)); + MX2X1 g31085(.A (n_5999), .B (n_5998), .S0 (n_10137), .Y (n_10326)); + MX2X1 g31087(.A (n_6611), .B (n_6610), .S0 (n_10137), .Y (n_10325)); + MX2X1 g31088(.A (n_6669), .B (n_6668), .S0 (n_10137), .Y (n_10323)); + MX2X1 g31089(.A (n_6667), .B (n_6666), .S0 (n_10137), .Y (n_10322)); + MX2X1 g31090(.A (n_6665), .B (n_6664), .S0 (n_10137), .Y (n_10321)); + MX2X1 g31091(.A (n_6663), .B (n_6662), .S0 (n_10315), .Y (n_10319)); + MX2X1 g31092(.A (n_6661), .B (n_6660), .S0 (n_10137), .Y (n_10318)); + MX2X1 g31093(.A (n_6034), .B (n_6033), .S0 (n_10315), .Y (n_10317)); + MX2X1 g31094(.A (n_6031), .B (n_6030), .S0 (n_10315), .Y (n_10316)); + MX2X1 g31096(.A (n_6957), .B (n_6956), .S0 (n_10235), .Y (n_10314)); + MX2X1 g31097(.A (n_6657), .B (n_6656), .S0 (n_10235), .Y (n_10313)); + MX2X1 g31098(.A (n_6552), .B (n_6551), .S0 (n_10267), .Y (n_10311)); + MX2X1 g31099(.A (n_6541), .B (n_6540), .S0 (n_10308), .Y (n_10310)); + MX2X1 g31100(.A (n_6535), .B (n_6534), .S0 (n_10308), .Y (n_10309)); + MX2X1 g31101(.A (n_6655), .B (n_6654), .S0 (n_10250), .Y (n_10307)); + MX2X1 g31102(.A (n_6529), .B (n_6528), .S0 (n_10308), .Y (n_10306)); + MX2X1 g31103(.A (n_6885), .B (n_6884), .S0 (n_10303), .Y (n_10305)); + MX2X1 g31104(.A (n_6955), .B (n_6954), .S0 (n_10303), .Y (n_10304)); + MX2X1 g31105(.A (n_6950), .B (n_6949), .S0 (n_10250), .Y (n_10302)); + MX2X1 g31106(.A (n_6653), .B (n_6652), .S0 (n_10315), .Y (n_10301)); + MX2X1 g31107(.A (n_6880), .B (n_6879), .S0 (n_10250), .Y (n_10300)); + MX2X1 g31108(.A (n_6948), .B (n_6947), .S0 (n_10308), .Y (n_10299)); + MX2X1 g31109(.A (n_6877), .B (n_6876), .S0 (n_10308), .Y (n_10298)); + MX2X1 g31110(.A (n_6946), .B (n_6945), .S0 (n_10308), .Y (n_10296)); + MX2X1 g31111(.A (n_6943), .B (n_6942), .S0 (n_10308), .Y (n_10295)); + MX2X1 g31112(.A (n_6941), .B (n_6940), .S0 (n_10250), .Y (n_10293)); + MX2X1 g31113(.A (n_6538), .B (n_6537), .S0 (n_10250), .Y (n_10291)); + MX2X1 g31114(.A (n_6938), .B (n_6937), .S0 (n_10267), .Y (n_10290)); + MX2X1 g31115(.A (n_6871), .B (n_509), .S0 (n_10250), .Y (n_10289)); + MX2X1 g31116(.A (n_6648), .B (n_6647), .S0 (n_10235), .Y (n_10288)); + MX2X1 g31117(.A (n_6645), .B (n_6644), .S0 (n_10235), .Y (n_10287)); + MX2X1 g31118(.A (n_6496), .B (n_6495), .S0 (n_10235), .Y (n_10285)); + MX2X1 g31119(.A (n_6642), .B (n_6641), .S0 (n_10267), .Y (n_10284)); + MX2X1 g31120(.A (n_6639), .B (n_6638), .S0 (n_10267), .Y (n_10283)); + MX2X1 g31121(.A (n_6636), .B (n_6635), .S0 (n_10267), .Y (n_10281)); + MX2X1 g31122(.A (n_6874), .B (n_6873), .S0 (n_10267), .Y (n_10280)); + MX2X1 g31123(.A (n_6936), .B (n_6935), .S0 (n_10277), .Y (n_10279)); + MX2X1 g31124(.A (n_6882), .B (n_6881), .S0 (n_10277), .Y (n_10278)); + MX2X1 g31125(.A (n_6634), .B (n_6633), .S0 (n_10137), .Y (n_10276)); + MX2X1 g31126(.A (n_6934), .B (n_6933), .S0 (n_10277), .Y (n_10275)); + MX2X1 g31127(.A (n_6631), .B (n_6630), .S0 (n_10137), .Y (n_10274)); + MX2X1 g31128(.A (n_6889), .B (n_6888), .S0 (n_10277), .Y (n_10272)); + MX2X1 g31129(.A (n_6932), .B (n_6931), .S0 (n_10235), .Y (n_10270)); + MX2X1 g31130(.A (n_6903), .B (n_6902), .S0 (n_10235), .Y (n_10269)); + MX2X1 g31131(.A (n_6901), .B (n_6900), .S0 (n_10267), .Y (n_10268)); + MX2X1 g31133(.A (n_6929), .B (n_6928), .S0 (n_10267), .Y (n_10266)); + MX2X1 g31134(.A (n_6629), .B (n_6628), .S0 (n_10267), .Y (n_10265)); + MX2X1 g31135(.A (n_6894), .B (n_6893), .S0 (n_10277), .Y (n_10264)); + MX2X1 g31136(.A (n_6926), .B (n_6924), .S0 (n_10277), .Y (n_10263)); + MX2X1 g31137(.A (n_6621), .B (n_6620), .S0 (n_10747), .Y (n_10262)); + MX2X1 g31138(.A (n_6619), .B (n_6617), .S0 (n_10747), .Y (n_10261)); + MX2X1 g31139(.A (n_6615), .B (n_6614), .S0 (n_10235), .Y (n_10259)); + MX2X1 g31140(.A (n_6451), .B (n_6450), .S0 (n_10235), .Y (n_10258)); + MX2X1 g31141(.A (n_6506), .B (n_6505), .S0 (n_10747), .Y (n_10256)); + NAND2X1 g32665(.A (n_9876), .B (n_1873), .Y (n_11108)); + MX2X1 g31143(.A (n_6583), .B (n_6581), .S0 (n_10747), .Y (n_10254)); + MX2X1 g31144(.A (n_6923), .B (n_6922), .S0 (n_10235), .Y (n_10253)); + MX2X1 g31145(.A (n_6953), .B (n_6951), .S0 (n_10235), .Y (n_10252)); + MX2X1 g31146(.A (n_6921), .B (n_6919), .S0 (n_10250), .Y (n_10251)); + MX2X1 g31147(.A (n_6608), .B (n_6607), .S0 (n_10315), .Y (n_10249)); + MX2X1 g31148(.A (n_6917), .B (n_6915), .S0 (n_10250), .Y (n_10247)); + NAND2X1 g32693(.A (n_10617), .B (n_1481), .Y (n_11104)); + MX2X1 g31149(.A (n_6892), .B (n_6890), .S0 (n_10277), .Y (n_10245)); + MX2X1 g31150(.A (n_6022), .B (n_6021), .S0 (n_10315), .Y (n_10244)); + MX2X1 g31151(.A (n_6897), .B (n_6895), .S0 (n_10277), .Y (n_10243)); + MX2X1 g31152(.A (n_6914), .B (n_6912), .S0 (n_10308), .Y (n_10242)); + MX2X1 g31153(.A (n_6887), .B (n_6886), .S0 (n_10308), .Y (n_10241)); + NAND2X1 g32715(.A (n_12688), .B (n_862), .Y (n_11099)); + MX2X1 g31154(.A (n_6910), .B (n_6909), .S0 (n_10250), .Y (n_10239)); + MX2X1 g31156(.A (n_6561), .B (n_6559), .S0 (n_10235), .Y (n_10238)); + NAND2X1 g32725(.A (n_9873), .B (n_8182), .Y (n_11096)); + MX2X1 g31157(.A (n_6907), .B (n_6905), .S0 (n_10235), .Y (n_10236)); + MX2X1 g31158(.A (n_6006), .B (n_6005), .S0 (n_10137), .Y (n_10234)); + MX2X1 g31159(.A (n_6603), .B (n_6601), .S0 (n_10137), .Y (n_10233)); + MX2X1 g31160(.A (n_6600), .B (n_6598), .S0 (n_10137), .Y (n_10232)); + MX2X1 g31161(.A (n_6597), .B (n_6595), .S0 (n_10137), .Y (n_10230)); + MX2X1 g31162(.A (n_6593), .B (n_6591), .S0 (n_9676), .Y (n_10229)); + MX2X1 g31163(.A (n_6590), .B (n_6588), .S0 (n_9676), .Y (n_10228)); + MX2X1 g31164(.A (n_6587), .B (n_6585), .S0 (n_9676), .Y (n_10226)); + MX2X1 g31165(.A (n_6015), .B (n_6013), .S0 (n_9676), .Y (n_10225)); + MX2X1 g31166(.A (n_6012), .B (n_6010), .S0 (n_10137), .Y (n_10224)); + MX2X1 g31167(.A (n_6009), .B (n_6007), .S0 (n_10137), .Y (n_10223)); + MX2X1 g31170(.A (n_6574), .B (n_6572), .S0 (n_10137), .Y (n_10221)); + MX2X1 g31171(.A (n_6571), .B (n_6569), .S0 (n_10137), .Y (n_10220)); + MX2X1 g31172(.A (n_6567), .B (n_6565), .S0 (n_10137), .Y (n_10219)); + MX2X1 g31173(.A (n_6564), .B (n_6562), .S0 (n_10137), .Y (n_10217)); + MX2X1 g31174(.A (n_6004), .B (n_6002), .S0 (n_10137), .Y (n_10216)); + MX2X1 g31197(.A (n_6477), .B (n_6476), .S0 (n_10315), .Y (n_10215)); + MX2X1 g31199(.A (n_6469), .B (n_6468), .S0 (n_10315), .Y (n_10214)); + MX2X1 g31203(.A (n_6464), .B (n_6463), .S0 (n_10315), .Y (n_10212)); + MX2X1 g31205(.A (n_6458), .B (n_6457), .S0 (n_10315), .Y (n_10211)); + OAI21X1 g33038(.A0 (n_12632), .A1 (n_7091), .B0 (n_12161), .Y + (n_10209)); + OAI21X1 g33039(.A0 (n_12639), .A1 (n_7090), .B0 (n_12161), .Y + (n_10207)); + OAI21X1 g33040(.A0 (n_7241), .A1 (n_7089), .B0 (n_12504), .Y + (n_10206)); + MX2X1 g31208(.A (n_6536), .B (n_508), .S0 (n_10315), .Y (n_10205)); + OAI21X1 g33041(.A0 (n_7247), .A1 (n_7087), .B0 (n_12504), .Y + (n_10204)); + OAI21X1 g33042(.A0 (n_7239), .A1 (n_7085), .B0 (n_12161), .Y + (n_10202)); + OAI21X1 g33043(.A0 (n_12483), .A1 (n_7084), .B0 (n_12504), .Y + (n_10201)); + OAI21X1 g33044(.A0 (n_7236), .A1 (n_7182), .B0 (n_12504), .Y + (n_10200)); + OAI21X1 g33045(.A0 (n_7235), .A1 (n_7181), .B0 (n_12504), .Y + (n_10199)); + OAI21X1 g33046(.A0 (n_7233), .A1 (n_7179), .B0 (n_12504), .Y + (n_10198)); + MX2X1 g31210(.A (n_6452), .B (n_502), .S0 (n_10315), .Y (n_10197)); + OAI21X1 g33047(.A0 (n_7232), .A1 (n_7178), .B0 (n_12504), .Y + (n_10196)); + MX2X1 g31211(.A (n_5975), .B (n_5974), .S0 (n_10315), .Y (n_10194)); + OAI21X1 g33050(.A0 (n_7203), .A1 (n_7081), .B0 (n_12161), .Y + (n_12064)); + MX2X1 g31212(.A (n_5973), .B (n_501), .S0 (n_10315), .Y (n_10190)); + OAI21X1 g33053(.A0 (n_7230), .A1 (n_7079), .B0 (n_12161), .Y + (n_12793)); + OAI21X1 g33054(.A0 (n_7306), .A1 (n_6987), .B0 (n_12161), .Y + (n_10188)); + MX2X1 g31213(.A (n_5971), .B (n_406), .S0 (n_10315), .Y (n_10187)); + MX2X1 g31231(.A (n_6527), .B (n_6526), .S0 (n_10315), .Y (n_10185)); + MX2X1 g31233(.A (n_6416), .B (n_6415), .S0 (n_10137), .Y (n_10184)); + MX2X1 g31234(.A (n_6543), .B (n_6542), .S0 (n_10137), .Y (n_10183)); + MX2X1 g31235(.A (n_6412), .B (n_6411), .S0 (n_10137), .Y (n_10182)); + MX2X1 g31237(.A (n_6409), .B (n_6408), .S0 (n_10137), .Y (n_10181)); + MX2X1 g31239(.A (n_6407), .B (n_6406), .S0 (n_10315), .Y (n_10180)); + MX2X1 g31241(.A (n_5967), .B (n_5966), .S0 (n_10315), .Y (n_10179)); + MX2X1 g31244(.A (n_6038), .B (n_6037), .S0 (n_10315), .Y (n_10178)); + MX2X1 g31247(.A (n_6869), .B (n_6868), .S0 (n_10308), .Y (n_10176)); + MX2X1 g31248(.A (n_6405), .B (n_6404), .S0 (n_10308), .Y (n_10174)); + MX2X1 g31249(.A (n_6403), .B (n_6402), .S0 (n_10308), .Y (n_10173)); + MX2X1 g31250(.A (n_6401), .B (n_6400), .S0 (n_10250), .Y (n_10172)); + MX2X1 g31251(.A (n_6393), .B (n_6392), .S0 (n_10250), .Y (n_10170)); + MX2X1 g31252(.A (n_6399), .B (n_6398), .S0 (n_10235), .Y (n_10169)); + MX2X1 g31253(.A (n_6397), .B (n_6396), .S0 (n_10235), .Y (n_10168)); + MX2X1 g31254(.A (n_6867), .B (n_6866), .S0 (n_10303), .Y (n_10167)); + MX2X1 g31255(.A (n_6865), .B (n_6864), .S0 (n_10303), .Y (n_10166)); + MX2X1 g31256(.A (n_6863), .B (n_6862), .S0 (n_10250), .Y (n_10165)); + MX2X1 g31257(.A (n_5486), .B (n_1742), .S0 (n_10250), .Y (n_10164)); + MX2X1 g31258(.A (n_5484), .B (n_1680), .S0 (n_10303), .Y (n_10163)); + MX2X1 g31259(.A (n_5468), .B (n_1738), .S0 (n_10303), .Y (n_10162)); + MX2X1 g31260(.A (n_5483), .B (n_1562), .S0 (n_10308), .Y (n_10160)); + MX2X1 g31261(.A (n_5482), .B (n_1733), .S0 (n_10308), .Y (n_10159)); + MX2X1 g31262(.A (n_5481), .B (n_1701), .S0 (n_10303), .Y (n_10158)); + MX2X1 g31263(.A (n_5479), .B (n_1704), .S0 (n_10303), .Y (n_10157)); + MX2X1 g31264(.A (n_5477), .B (n_1728), .S0 (n_10308), .Y (n_10156)); + MX2X1 g31265(.A (n_5475), .B (n_1724), .S0 (n_10308), .Y (n_10155)); + MX2X1 g31266(.A (n_5474), .B (n_2500), .S0 (n_10267), .Y (n_10154)); + MX2X1 g31267(.A (n_6860), .B (n_6859), .S0 (n_10267), .Y (n_10152)); + MX2X1 g31268(.A (n_5473), .B (n_2507), .S0 (n_10267), .Y (n_10151)); + MX2X1 g31269(.A (n_5487), .B (n_1716), .S0 (n_10267), .Y (n_10150)); + MX2X1 g31270(.A (n_6858), .B (n_6857), .S0 (n_10267), .Y (n_10148)); + MX2X1 g31271(.A (n_6855), .B (n_6854), .S0 (n_10267), .Y (n_10147)); + MX2X1 g31273(.A (n_6853), .B (n_6852), .S0 (n_10267), .Y (n_10146)); + MX2X1 g31274(.A (n_6850), .B (n_6849), .S0 (n_10250), .Y (n_10145)); + MX2X1 g31275(.A (n_6848), .B (n_6847), .S0 (n_10250), .Y (n_10143)); + MX2X1 g31276(.A (n_6395), .B (n_6394), .S0 (n_10250), .Y (n_10142)); + MX2X1 g31277(.A (n_6846), .B (n_6845), .S0 (n_10235), .Y (n_10141)); + OAI21X1 g31278(.A0 (n_10992), .A1 (\u4_rp[0] ), .B0 (n_9843), .Y + (n_10140)); + OAI21X1 g31279(.A0 (n_10985), .A1 (n_5772), .B0 (n_9842), .Y + (n_10139)); + MX2X1 g31280(.A (n_5960), .B (n_5959), .S0 (n_10137), .Y (n_10138)); + MX2X1 g31281(.A (n_6387), .B (n_6386), .S0 (n_10137), .Y (n_10136)); + MX2X1 g31282(.A (n_6385), .B (n_6384), .S0 (n_10137), .Y (n_10135)); + MX2X1 g31286(.A (n_6376), .B (n_6375), .S0 (n_10315), .Y (n_10134)); + MX2X1 g31289(.A (n_6391), .B (n_6390), .S0 (n_10315), .Y (n_10133)); + MX2X1 g31292(.A (n_5958), .B (n_5957), .S0 (n_10315), .Y (n_10132)); + DFFSRX1 \u21_int_set_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9848), .Q (oc4_int_set), .QN ()); + DFFSRX1 \u22_int_set_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9847), .Q (oc5_int_set), .QN ()); + DFFSRX1 \u17_int_set_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9850), .Q (oc0_int_set), .QN ()); + MX2X1 g31296(.A (n_5956), .B (n_5955), .S0 (n_10315), .Y (n_10131)); + DFFSRX1 \u19_int_set_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9849), .Q (oc2_int_set), .QN ()); + MX2X1 g31307(.A (n_5665), .B (n_1246), .S0 (n_10315), .Y (n_10130)); + MX2X1 g31317(.A (n_5649), .B (n_1242), .S0 (n_10137), .Y (n_10129)); + MX2X1 g31320(.A (n_5647), .B (n_1685), .S0 (n_10137), .Y (n_10128)); + MX2X1 g31337(.A (n_5643), .B (n_1251), .S0 (n_10315), .Y (n_10127)); + MX2X1 g31338(.A (n_5641), .B (n_1864), .S0 (n_10315), .Y (n_10126)); + MX2X1 g31339(.A (n_6340), .B (n_6339), .S0 (n_10315), .Y (n_10124)); + MX2X1 g31340(.A (n_6338), .B (n_6337), .S0 (n_10315), .Y (n_10123)); + MX2X1 g31342(.A (n_6332), .B (n_6331), .S0 (n_10137), .Y (n_10122)); + MX2X1 g31343(.A (n_6334), .B (n_6333), .S0 (n_10137), .Y (n_10120)); + MX2X1 g31344(.A (n_5946), .B (n_5945), .S0 (n_10137), .Y (n_10119)); + MX2X1 g31345(.A (n_5963), .B (n_5962), .S0 (n_10137), .Y (n_10118)); + MX2X1 g31371(.A (u11_din_tmp1), .B (in_slt_444), .S0 (n_10103), .Y + (n_10115)); + MX2X1 g31372(.A (u11_din_tmp_51), .B (in_slt_454), .S0 (n_10103), .Y + (n_10114)); + MX2X1 g31373(.A (u11_din_tmp_52), .B (in_slt_455), .S0 (n_10103), .Y + (n_10112)); + MX2X1 g31374(.A (u11_din_tmp_53), .B (in_slt_456), .S0 (n_10103), .Y + (n_10111)); + MX2X1 g31375(.A (u11_din_tmp_54), .B (in_slt_457), .S0 (n_10103), .Y + (n_10110)); + MX2X1 g31376(.A (u11_din_tmp_55), .B (in_slt_458), .S0 (n_10103), .Y + (n_10108)); + MX2X1 g31377(.A (u11_din_tmp_56), .B (in_slt_459), .S0 (n_10103), .Y + (n_10106)); + MX2X1 g31378(.A (u11_din_tmp_42), .B (in_slt_445), .S0 (n_10103), .Y + (n_10105)); + MX2X1 g31379(.A (u11_din_tmp_43), .B (in_slt_446), .S0 (n_10103), .Y + (n_10104)); + MX2X1 g31380(.A (u11_din_tmp_44), .B (in_slt_447), .S0 (n_10103), .Y + (n_10102)); + MX2X1 g31381(.A (u11_din_tmp_45), .B (in_slt_448), .S0 (n_10103), .Y + (n_10101)); + MX2X1 g31382(.A (u11_din_tmp_46), .B (in_slt_449), .S0 (n_10103), .Y + (n_10100)); + MX2X1 g31383(.A (u11_din_tmp_47), .B (in_slt_450), .S0 (n_10103), .Y + (n_10099)); + MX2X1 g31384(.A (u11_din_tmp_48), .B (in_slt_451), .S0 (n_10103), .Y + (n_10098)); + MX2X1 g31385(.A (u11_din_tmp_49), .B (in_slt_452), .S0 (n_10103), .Y + (n_10097)); + MX2X1 g31386(.A (u11_din_tmp_50), .B (in_slt_453), .S0 (n_10103), .Y + (n_10096)); + XOR2X1 g31397(.A (n_1012), .B (n_10329), .Y (n_10095)); + XOR2X1 g31398(.A (n_641), .B (n_10327), .Y (n_10094)); + DFFX1 u16_u8_dma_req_r1_reg(.CK (clk_i), .D (n_11907), .Q + (u16_u8_dma_req_r1), .QN ()); + NAND3X1 g30050(.A (n_9769), .B (n_9601), .C (n_9661), .Y (n_10092)); + NAND3X1 g30052(.A (n_9767), .B (n_9600), .C (n_9658), .Y (n_10091)); + OAI21X1 g30055(.A0 (n_9506), .A1 (n_9591), .B0 (n_9756), .Y + (n_10090)); + OAI21X1 g30057(.A0 (n_9504), .A1 (n_9589), .B0 (n_9755), .Y + (n_10089)); + OAI21X1 g30059(.A0 (n_9502), .A1 (n_9587), .B0 (n_9754), .Y + (n_10088)); + OAI21X1 g30060(.A0 (n_9500), .A1 (n_9585), .B0 (n_9753), .Y + (n_10087)); + NAND3X1 g31573(.A (\u11_wp[0] ), .B (n_11772), .C (n_9631), .Y + (n_10086)); + NOR2X1 g31574(.A (n_11894), .B (n_757), .Y (n_10085)); + NAND2X1 g31575(.A (n_1690), .B (n_10081), .Y (n_10084)); + AND2X1 g30066(.A (n_9757), .B (n_11119), .Y (n_10083)); + NAND2X1 g31576(.A (n_256), .B (n_10081), .Y (n_10082)); + NAND2X1 g31577(.A (n_98), .B (n_10081), .Y (n_10080)); + NAND2X1 g31578(.A (n_39), .B (n_10010), .Y (n_10079)); + NAND2X1 g31579(.A (n_2556), .B (n_10010), .Y (n_10078)); + NAND2X1 g31580(.A (n_366), .B (n_10010), .Y (n_10076)); + NAND2X1 g31581(.A (n_349), .B (n_10073), .Y (n_10075)); + NAND2X1 g31582(.A (n_174), .B (n_10073), .Y (n_10074)); + NAND2X1 g31583(.A (n_9), .B (n_10065), .Y (n_10072)); + NAND2X1 g31584(.A (n_2549), .B (n_10010), .Y (n_10071)); + NAND2X1 g31585(.A (n_379), .B (n_10010), .Y (n_10069)); + NOR2X1 g31586(.A (n_12339), .B (n_1096), .Y (n_10068)); + NAND2X1 g31587(.A (n_2627), .B (n_10010), .Y (n_10067)); + NAND2X1 g31588(.A (n_2545), .B (n_10065), .Y (n_10066)); + NAND2X1 g31589(.A (n_204), .B (n_10045), .Y (n_10064)); + NAND2X1 g31590(.A (n_356), .B (n_10054), .Y (n_10063)); + NAND2X1 g31591(.A (n_1679), .B (n_10054), .Y (n_10062)); + NAND2X1 g31592(.A (n_1737), .B (n_10054), .Y (n_10060)); + NAND2X1 g31593(.A (n_340), .B (n_10054), .Y (n_10059)); + NAND2X1 g31594(.A (n_42), .B (n_10010), .Y (n_10058)); + NAND2X1 g31595(.A (n_45), .B (n_10054), .Y (n_10057)); + NAND2X1 g31596(.A (n_1703), .B (n_10054), .Y (n_10056)); + NAND2X1 g31597(.A (n_1727), .B (n_10054), .Y (n_10055)); + NAND2X1 g31598(.A (n_1723), .B (n_10054), .Y (n_10053)); + NAND2X1 g31599(.A (n_206), .B (n_10054), .Y (n_10052)); + NAND2X1 g31600(.A (n_2506), .B (n_10045), .Y (n_10050)); + NAND2X1 g31601(.A (n_1715), .B (n_10054), .Y (n_10049)); + NAND2X1 g31602(.A (n_2542), .B (n_10010), .Y (n_10048)); + NAND2X1 g31603(.A (n_1863), .B (n_10010), .Y (n_10047)); + NAND2X1 g31604(.A (n_1766), .B (n_10045), .Y (n_10046)); + NAND2X1 g31605(.A (n_141), .B (n_10045), .Y (n_10044)); + NAND2X1 g31606(.A (n_1744), .B (n_10054), .Y (n_10043)); + NAND2X1 g31607(.A (n_35), .B (n_10054), .Y (n_10042)); + NAND2X1 g31608(.A (n_198), .B (n_10045), .Y (n_10041)); + NAND2X1 g31609(.A (n_1561), .B (n_10045), .Y (n_10040)); + NAND2X1 g31610(.A (n_347), .B (n_10045), .Y (n_10038)); + NAND2X1 g31611(.A (n_365), .B (n_10045), .Y (n_10037)); + NAND2X1 g31612(.A (n_346), .B (n_10045), .Y (n_10035)); + NAND2X1 g31613(.A (n_345), .B (n_10054), .Y (n_10034)); + NAND2X1 g31614(.A (n_2499), .B (n_10054), .Y (n_10032)); + NAND2X1 g31615(.A (n_385), .B (n_10054), .Y (n_10031)); + NAND2X1 g31616(.A (n_343), .B (n_10045), .Y (n_10030)); + NAND2X1 g31617(.A (n_6089), .B (n_10045), .Y (n_10029)); + NAND2X1 g31618(.A (n_6087), .B (n_10073), .Y (n_10028)); + NAND2X1 g31619(.A (n_5294), .B (n_10024), .Y (n_10027)); + NAND2X1 g31620(.A (n_5374), .B (n_10019), .Y (n_10026)); + NAND2X1 g31621(.A (n_5343), .B (n_10024), .Y (n_10025)); + NAND2X1 g31622(.A (n_5372), .B (n_10019), .Y (n_10023)); + NAND2X1 g31623(.A (n_5333), .B (n_10019), .Y (n_10022)); + NAND2X1 g31624(.A (n_5302), .B (n_10019), .Y (n_10020)); + NAND2X1 g31625(.A (n_5367), .B (n_10019), .Y (n_10018)); + NAND2X1 g31626(.A (n_5347), .B (n_10024), .Y (n_10017)); + NAND2X1 g31627(.A (n_5345), .B (n_10024), .Y (n_10016)); + NAND2X1 g31628(.A (n_5365), .B (n_10019), .Y (n_10015)); + NAND2X1 g31629(.A (n_5350), .B (n_10019), .Y (n_10014)); + NAND2X1 g31632(.A (n_5577), .B (n_10081), .Y (n_10013)); + NAND2X1 g31633(.A (n_5575), .B (n_10081), .Y (n_10012)); + NAND2X1 g31634(.A (n_5520), .B (n_10010), .Y (n_10011)); + NAND2X1 g31635(.A (n_5363), .B (n_10081), .Y (n_10009)); + NAND2X1 g31636(.A (n_5518), .B (n_10010), .Y (n_10008)); + NAND2X1 g31637(.A (n_5516), .B (n_10065), .Y (n_10007)); + NAND2X1 g31638(.A (n_5514), .B (n_10010), .Y (n_10006)); + NAND2X1 g31639(.A (n_5512), .B (n_10010), .Y (n_10005)); + NAND2X1 g31640(.A (n_5359), .B (n_10065), .Y (n_10004)); + NAND2X1 g31641(.A (n_5357), .B (n_10010), .Y (n_10003)); + NAND2X1 g31642(.A (n_5352), .B (n_10010), .Y (n_10002)); + NAND2X1 g31643(.A (n_5510), .B (n_10010), .Y (n_10001)); + NAND2X1 g31644(.A (n_5506), .B (n_10010), .Y (n_10000)); + NAND2X1 g31645(.A (n_5504), .B (n_10010), .Y (n_9999)); + OR2X1 g31648(.A (n_10329), .B (n_765), .Y (n_9998)); + NAND2X1 g31649(.A (n_5369), .B (n_10019), .Y (n_9997)); + OR2X1 g31651(.A (n_10327), .B (n_771), .Y (n_9996)); + NAND2X1 g31652(.A (n_1732), .B (n_10045), .Y (n_9995)); + NAND2X1 g31653(.A (n_1700), .B (n_10054), .Y (n_9994)); + NAND2X1 g31663(.A (n_314), .B (n_10081), .Y (n_9993)); + NAND2X1 g31666(.A (n_337), .B (n_10081), .Y (n_9992)); + NAND2X1 g31667(.A (n_1748), .B (n_10073), .Y (n_9991)); + NOR2X1 g31669(.A (n_11892), .B (n_11586), .Y (n_9990)); + NOR2X1 g31693(.A (n_11890), .B (n_1184), .Y (n_9989)); + NAND2X1 g31697(.A (n_313), .B (n_10081), .Y (n_9988)); + NAND2X1 g31700(.A (n_96), .B (n_10081), .Y (n_9987)); + NAND2X1 g31704(.A (n_90), .B (n_10010), .Y (n_9986)); + NAND2X1 g31706(.A (n_249), .B (n_10010), .Y (n_9985)); + NAND2X1 g31707(.A (n_87), .B (n_10010), .Y (n_9984)); + NAND2X1 g31708(.A (n_232), .B (n_10081), .Y (n_9983)); + NAND2X1 g31709(.A (n_1684), .B (n_10065), .Y (n_9982)); + NAND2X1 g31710(.A (n_147), .B (n_10010), .Y (n_9981)); + NAND2X1 g31711(.A (n_1676), .B (n_10065), .Y (n_9980)); + NAND2X1 g31712(.A (n_143), .B (n_10065), .Y (n_9979)); + NAND2X1 g31713(.A (n_215), .B (n_10081), .Y (n_9978)); + NAND2X1 g31715(.A (n_2538), .B (n_10065), .Y (n_9977)); + NAND2X1 g31719(.A (n_196), .B (n_10010), .Y (n_9976)); + NAND2X1 g31722(.A (n_162), .B (n_10010), .Y (n_9975)); + AOI21X1 g31733(.A0 (n_2369), .A1 (n_4829), .B0 (n_11894), .Y + (n_9974)); + AOI21X1 g31734(.A0 (n_2986), .A1 (n_4836), .B0 (n_12339), .Y + (n_9973)); + NAND3X1 g31735(.A (n_12531), .B (n_12149), .C (n_991), .Y (n_10954)); + NAND3X1 g31736(.A (n_1229), .B (n_12608), .C (n_9833), .Y (n_10950)); + DFFX1 \u1_slt4_reg[11] (.CK (bit_clk_pad_i), .D (n_9761), .Q + (in_slt_429), .QN ()); + AOI21X1 g31744(.A0 (n_9541), .A1 (n_12149), .B0 (n_540), .Y (n_9972)); + AOI21X1 g31746(.A0 (n_9538), .A1 (n_12609), .B0 (n_665), .Y (n_9970)); + AOI21X1 g31749(.A0 (n_2360), .A1 (n_4834), .B0 (n_11892), .Y + (n_9969)); + AOI21X1 g31758(.A0 (n_9620), .A1 (i4_full), .B0 (n_608), .Y (n_9968)); + AOI21X1 g31763(.A0 (n_1500), .A1 (n_4080), .B0 (n_11890), .Y + (n_9967)); + AOI21X1 g31781(.A0 (n_1549), .A1 (n_12303), .B0 (n_11894), .Y + (n_9966)); + AOI21X1 g31782(.A0 (n_2488), .A1 (n_1918), .B0 (n_12339), .Y + (n_9965)); + OAI21X1 g31786(.A0 (n_5447), .A1 (n_9564), .B0 (n_9752), .Y (n_9964)); + AOI21X1 g31796(.A0 (n_1411), .A1 (n_1845), .B0 (n_11892), .Y + (n_9963)); + AOI21X1 g31801(.A0 (n_12656), .A1 (n_1907), .B0 (n_11890), .Y + (n_9962)); + MX2X1 g31810(.A (n_5420), .B (n_5421), .S0 (n_9620), .Y (n_9961)); + OAI21X1 g31813(.A0 (n_6055), .A1 (n_9564), .B0 (n_9751), .Y (n_9960)); + MX2X1 g30130(.A (in_slt_739), .B (u1_sr_128), .S0 (out_le), .Y + (n_9958)); + MX2X1 g30131(.A (u1_sr_128), .B (in_slt_838), .S0 (out_le_181), .Y + (n_9957)); + MX2X1 g30132(.A (u1_sr_128), .B (in_slt_408), .S0 (out_le_182), .Y + (n_9956)); + MX2X1 g30133(.A (u1_sr_128), .B (in_slt_430), .S0 (out_le_183), .Y + (n_9955)); + MX2X1 g30134(.A (u1_sr_128), .B (in_slt_452), .S0 (out_le_184), .Y + (n_9954)); + MX2X1 g30136(.A (n_9952), .B (u0_slt9_r_169), .S0 (n_11319), .Y + (n_9953)); + NAND2X1 g30925(.A (n_9759), .B (n_9734), .Y (n_9951)); + DFFX1 \u1_slt0_reg[11] (.CK (bit_clk_pad_i), .D (n_9765), .Q + (in_slt_738), .QN ()); + DFFX1 \u1_slt1_reg[11] (.CK (bit_clk_pad_i), .D (n_9764), .Q + (in_slt_753), .QN ()); + DFFX1 \u1_slt2_reg[11] (.CK (bit_clk_pad_i), .D (n_9763), .Q + (in_slt_837), .QN ()); + DFFX1 \u1_slt3_reg[11] (.CK (bit_clk_pad_i), .D (n_9762), .Q + (in_slt_407), .QN ()); + DFFX1 \u1_slt6_reg[11] (.CK (bit_clk_pad_i), .D (n_9760), .Q + (in_slt_451), .QN ()); + DFFSRX1 \u23_int_set_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9758), .Q (), .QN (ic0_int_set_720)); + DFFX1 u15_crac_rd_done_reg(.CK (clk_i), .D (n_9712), .Q (n_1036), .QN + ()); + NAND2X1 g32621(.A (n_320), .B (n_9943), .Y (n_12009)); + NAND2X1 g32622(.A (n_321), .B (n_9947), .Y (n_11989)); + NAND2X1 g32623(.A (n_330), .B (n_9947), .Y (n_11675)); + NAND2X1 g32625(.A (n_248), .B (n_9947), .Y (n_11985)); + NAND2X1 g32626(.A (n_396), .B (n_9947), .Y (n_12019)); + NAND2X1 g32629(.A (n_295), .B (n_9943), .Y (n_11949)); + NAND2X1 g32630(.A (n_361), .B (n_9943), .Y (n_12013)); + AOI21X1 g32631(.A0 (n_6808), .A1 (n_6806), .B0 (n_10787), .Y + (n_9941)); + AOI21X1 g32632(.A0 (n_6804), .A1 (n_6801), .B0 (n_10787), .Y + (n_9940)); + NAND2X1 g32633(.A (n_373), .B (n_9943), .Y (n_11536)); + NAND2X1 g32634(.A (n_380), .B (n_9947), .Y (n_11538)); + NAND2X1 g32635(.A (n_370), .B (n_9947), .Y (n_12043)); + NAND2X1 g32636(.A (n_351), .B (n_9947), .Y (n_11951)); + NAND2X1 g32637(.A (n_391), .B (n_9943), .Y (n_11981)); + NAND2X1 g32638(.A (n_394), .B (n_9947), .Y (n_12007)); + NAND2X1 g32647(.A (n_290), .B (n_9931), .Y (n_9933)); + NAND2X1 g32648(.A (n_287), .B (n_9931), .Y (n_9932)); + NAND2X1 g32649(.A (n_84), .B (n_9931), .Y (n_9930)); + NAND2X1 g32650(.A (n_300), .B (n_9931), .Y (n_9929)); + NAND2X1 g32651(.A (n_261), .B (n_9931), .Y (n_9928)); + NAND2X1 g32652(.A (n_101), .B (n_9931), .Y (n_9927)); + NAND2X1 g32653(.A (n_113), .B (n_9931), .Y (n_9926)); + NAND2X1 g32654(.A (n_114), .B (n_9931), .Y (n_9925)); + NAND2X1 g32655(.A (n_117), .B (n_9931), .Y (n_12836)); + NAND2X1 g32656(.A (n_102), .B (n_9931), .Y (n_9922)); + AOI21X1 g32657(.A0 (n_5870), .A1 (n_5868), .B0 (n_9931), .Y (n_9921)); + AOI21X1 g32658(.A0 (n_5866), .A1 (n_5864), .B0 (n_9931), .Y (n_9920)); + NAND2X1 g32659(.A (n_304), .B (n_9931), .Y (n_11999)); + NAND2X1 g32660(.A (n_262), .B (n_9931), .Y (n_12812)); + NAND2X1 g32661(.A (n_234), .B (n_9931), .Y (n_12814)); + NAND2X1 g32662(.A (n_166), .B (n_9931), .Y (n_12816)); + NAND2X1 g32663(.A (n_266), .B (n_9931), .Y (n_9915)); + NAND2X1 g32664(.A (n_264), .B (n_9931), .Y (n_9914)); + NAND2X1 g32691(.A (n_332), .B (n_9943), .Y (n_12011)); + NAND2X1 g32692(.A (n_243), .B (n_9943), .Y (n_12001)); + NAND2X1 g32756(.A (n_103), .B (n_9943), .Y (n_11677)); + NAND3X1 g32766(.A (n_9672), .B (n_4679), .C (n_11772), .Y (n_9910)); + INVX1 g32767(.A (n_12589), .Y (n_9908)); + INVX1 g32836(.A (n_11136), .Y (n_9907)); + INVX2 g32937(.A (n_9905), .Y (n_10839)); + INVX4 g32942(.A (n_9905), .Y (n_10880)); + INVX8 g32958(.A (n_9903), .Y (n_10820)); + INVX1 g32968(.A (n_11131), .Y (n_9902)); + INVX1 g32974(.A (n_11126), .Y (n_9901)); + OAI21X1 g32988(.A0 (n_7277), .A1 (n_7199), .B0 (n_9885), .Y + (n_11676)); + OAI21X1 g32989(.A0 (n_7327), .A1 (n_7175), .B0 (n_9885), .Y + (n_12018)); + OAI21X1 g32991(.A0 (n_7326), .A1 (n_7292), .B0 (n_12149), .Y + (n_11948)); + OAI21X1 g32992(.A0 (n_7325), .A1 (n_7196), .B0 (n_12149), .Y + (n_12012)); + OAI21X1 g32995(.A0 (n_7320), .A1 (n_7104), .B0 (n_9885), .Y + (n_12042)); + OAI21X1 g32996(.A0 (n_7319), .A1 (n_7194), .B0 (n_9885), .Y + (n_11950)); + OAI21X1 g32997(.A0 (n_7273), .A1 (n_7103), .B0 (n_12149), .Y + (n_11980)); + OAI21X1 g32999(.A0 (n_7270), .A1 (n_7201), .B0 (n_9885), .Y + (n_11674)); + OAI21X1 g33011(.A0 (n_7279), .A1 (n_7105), .B0 (n_9885), .Y + (n_12008)); + NAND2X1 g33018(.A (n_414), .B (n_9882), .Y (n_9884)); + OAI21X1 g33019(.A0 (n_753), .A1 (u15_rdd2), .B0 (n_9882), .Y + (n_9883)); + OAI21X1 g33036(.A0 (n_7318), .A1 (n_12359), .B0 (n_12149), .Y + (n_12000)); + OAI21X1 g33037(.A0 (n_7278), .A1 (n_7046), .B0 (n_12149), .Y + (n_12010)); + OAI21X1 g33052(.A0 (n_7328), .A1 (n_7202), .B0 (n_9885), .Y + (n_11988)); + OAI21X1 g33087(.A0 (n_7275), .A1 (n_7177), .B0 (n_9885), .Y + (n_11984)); + INVX2 g33285(.A (n_12689), .Y (n_10605)); + INVX2 g33291(.A (n_12688), .Y (n_10481)); + INVX4 g33324(.A (n_10518), .Y (n_10645)); + INVX8 g33327(.A (n_9876), .Y (n_10518)); + INVX4 g33342(.A (n_12503), .Y (n_10617)); + INVX4 g33351(.A (n_10483), .Y (n_10583)); + INVX8 g33355(.A (n_9873), .Y (n_10483)); + MX2X1 g31347(.A (u10_din_tmp_43), .B (in_slt_424), .S0 (n_9860), .Y + (n_9872)); + MX2X1 g31348(.A (u10_din_tmp_44), .B (in_slt_425), .S0 (n_9860), .Y + (n_9871)); + MX2X1 g31349(.A (u10_din_tmp_45), .B (in_slt_426), .S0 (n_9860), .Y + (n_9869)); + MX2X1 g31350(.A (u10_din_tmp_46), .B (in_slt_427), .S0 (n_9860), .Y + (n_9868)); + MX2X1 g31367(.A (u10_din_tmp_47), .B (in_slt_428), .S0 (n_9860), .Y + (n_9867)); + MX2X1 g31368(.A (u10_din_tmp_48), .B (in_slt_429), .S0 (n_9860), .Y + (n_9865)); + MX2X1 g31369(.A (u10_din_tmp_49), .B (in_slt_430), .S0 (n_9860), .Y + (n_9863)); + MX2X1 g31370(.A (u10_din_tmp_50), .B (in_slt_431), .S0 (n_9860), .Y + (n_9862)); + MX2X1 g31387(.A (u10_din_tmp1), .B (in_slt_422), .S0 (n_9860), .Y + (n_9861)); + MX2X1 g31388(.A (u10_din_tmp_51), .B (in_slt_432), .S0 (n_9860), .Y + (n_9859)); + MX2X1 g31389(.A (u10_din_tmp_52), .B (in_slt_433), .S0 (n_9860), .Y + (n_9858)); + MX2X1 g31390(.A (u10_din_tmp_53), .B (in_slt_434), .S0 (n_9860), .Y + (n_9857)); + MX2X1 g31391(.A (u10_din_tmp_54), .B (in_slt_435), .S0 (n_9860), .Y + (n_9856)); + MX2X1 g31392(.A (u10_din_tmp_55), .B (in_slt_436), .S0 (n_9860), .Y + (n_9855)); + MX2X1 g31393(.A (u10_din_tmp_56), .B (in_slt_437), .S0 (n_9860), .Y + (n_9854)); + MX2X1 g31394(.A (u10_din_tmp_42), .B (in_slt_423), .S0 (n_9860), .Y + (n_9853)); + DFFX1 u16_u6_dma_req_r1_reg(.CK (clk_i), .D (n_12374), .Q (n_12066), + .QN ()); + DFFX1 u16_u7_dma_req_r1_reg(.CK (clk_i), .D (n_12379), .Q (n_12067), + .QN ()); + NAND3X1 g30049(.A (n_9702), .B (n_9525), .C (n_9616), .Y (n_9850)); + NAND3X1 g30051(.A (n_9700), .B (n_9524), .C (n_9613), .Y (n_9849)); + NAND3X1 g30053(.A (n_9698), .B (n_9523), .C (n_9655), .Y (n_9848)); + NAND3X1 g30054(.A (n_9696), .B (n_9522), .C (n_9652), .Y (n_9847)); + AND2X1 g30064(.A (n_9693), .B (n_11119), .Y (n_9846)); + AND2X1 g30065(.A (n_9692), .B (n_11119), .Y (n_9845)); + NAND3X1 g31646(.A (n_9641), .B (n_11600), .C (n_9564), .Y (n_9844)); + NAND2X1 g31647(.A (n_10992), .B (\u4_rp[0] ), .Y (n_9843)); + NAND2X1 g31650(.A (n_10985), .B (n_5772), .Y (n_9842)); + OAI21X1 g31783(.A0 (n_4850), .A1 (n_9514), .B0 (n_9687), .Y (n_9841)); + OAI21X1 g31812(.A0 (n_6056), .A1 (n_9514), .B0 (n_9686), .Y (n_9840)); + AOI22X1 g30117(.A0 (n_9644), .A1 (n_9659), .B0 (n_741), .B1 + (n_12845), .Y (n_9838)); + AOI22X1 g30119(.A0 (n_9643), .A1 (n_9656), .B0 (n_683), .B1 (n_9560), + .Y (n_9837)); + AND2X1 g30907(.A (n_9691), .B (n_11564), .Y (n_9836)); + NAND2X1 g32619(.A (n_853), .B (n_9631), .Y (n_9835)); + NAND2X1 g32620(.A (\u11_wp[3] ), .B (n_9631), .Y (n_9834)); + NAND2X1 g32646(.A (n_9931), .B (n_9833), .Y (n_10949)); + NAND2X1 g32690(.A (n_10787), .B (n_991), .Y (n_10953)); + AND2X1 g32837(.A (n_12689), .B (n_12534), .Y (n_11136)); + NAND3X1 g32841(.A (n_9620), .B (n_5250), .C (n_11600), .Y (n_9831)); + INVX2 g32875(.A (n_9829), .Y (n_10565)); + INVX4 g32880(.A (n_9829), .Y (n_10679)); + INVX8 g32891(.A (n_9827), .Y (n_10450)); + INVX8 g32919(.A (n_9820), .Y (n_10513)); + INVX8 g32928(.A (n_9820), .Y (n_10537)); + CLKBUFX3 g32934(.A (n_9818), .Y (n_10391)); + INVX2 g32944(.A (n_9818), .Y (n_9905)); + INVX4 g32947(.A (n_9720), .Y (n_10376)); + INVX2 g32948(.A (n_9720), .Y (n_10385)); + INVX4 g32960(.A (n_10376), .Y (n_9903)); + AND2X1 g32969(.A (n_9705), .B (n_9719), .Y (n_11131)); + AND2X1 g32975(.A (n_12502), .B (n_12636), .Y (n_11126)); + OAI21X1 g33000(.A0 (n_7269), .A1 (n_6998), .B0 (n_12609), .Y + (n_9815)); + OAI21X1 g33001(.A0 (n_7268), .A1 (n_7102), .B0 (n_12609), .Y + (n_9813)); + OAI21X1 g33002(.A0 (n_7132), .A1 (n_6993), .B0 (n_12609), .Y + (n_9812)); + OAI21X1 g33003(.A0 (n_7266), .A1 (n_6997), .B0 (n_12609), .Y + (n_9811)); + OAI21X1 g33004(.A0 (n_7130), .A1 (n_7162), .B0 (n_12609), .Y + (n_9810)); + OAI21X1 g33005(.A0 (n_7129), .A1 (n_6996), .B0 (n_12609), .Y + (n_9808)); + OAI21X1 g33006(.A0 (n_7128), .A1 (n_7173), .B0 (n_12609), .Y + (n_9807)); + OAI21X1 g33007(.A0 (n_7127), .A1 (n_6994), .B0 (n_12609), .Y + (n_9806)); + OAI21X1 g33008(.A0 (n_7265), .A1 (n_7101), .B0 (n_12609), .Y + (n_12835)); + OAI21X1 g33009(.A0 (n_7264), .A1 (n_7100), .B0 (n_12609), .Y + (n_9804)); + AOI21X1 g33010(.A0 (crac_wr), .A1 (n_9710), .B0 (\u13_ints_r[1] ), .Y + (n_9803)); + OAI21X1 g33013(.A0 (n_7126), .A1 (n_7099), .B0 (n_12609), .Y + (n_12811)); + OAI21X1 g33015(.A0 (n_7262), .A1 (n_7047), .B0 (n_12609), .Y + (n_12815)); + OAI21X1 g33016(.A0 (n_7260), .A1 (n_7096), .B0 (n_12609), .Y + (n_9798)); + OAI21X1 g33017(.A0 (n_7258), .A1 (n_7116), .B0 (n_12609), .Y + (n_9797)); + OAI21X1 g33088(.A0 (n_9711), .A1 (u15_rdd2), .B0 (n_716), .Y + (n_9796)); + NAND2X1 g33278(.A (u15_rdd1), .B (n_9688), .Y (n_9795)); + NAND2X1 g33279(.A (crac_wr), .B (n_9689), .Y (n_9794)); + MX2X1 g31351(.A (u9_din_tmp1), .B (in_slt_400), .S0 (n_9777), .Y + (n_9789)); + MX2X1 g31352(.A (u9_din_tmp_51), .B (in_slt_410), .S0 (n_9777), .Y + (n_9788)); + MX2X1 g31353(.A (u9_din_tmp_52), .B (in_slt_411), .S0 (n_9777), .Y + (n_9786)); + MX2X1 g31354(.A (u9_din_tmp_53), .B (in_slt_412), .S0 (n_9777), .Y + (n_9785)); + MX2X1 g31355(.A (u9_din_tmp_54), .B (in_slt_413), .S0 (n_9777), .Y + (n_9784)); + MX2X1 g31356(.A (u9_din_tmp_55), .B (in_slt_414), .S0 (n_9777), .Y + (n_9782)); + MX2X1 g31357(.A (u9_din_tmp_56), .B (in_slt_415), .S0 (n_9777), .Y + (n_9780)); + MX2X1 g31358(.A (u9_din_tmp_42), .B (in_slt_401), .S0 (n_9777), .Y + (n_9779)); + MX2X1 g31359(.A (u9_din_tmp_43), .B (in_slt_402), .S0 (n_9777), .Y + (n_9778)); + MX2X1 g31360(.A (u9_din_tmp_44), .B (in_slt_403), .S0 (n_9777), .Y + (n_9776)); + MX2X1 g31361(.A (u9_din_tmp_45), .B (in_slt_404), .S0 (n_9777), .Y + (n_9775)); + MX2X1 g31362(.A (u9_din_tmp_46), .B (in_slt_405), .S0 (n_9777), .Y + (n_9774)); + MX2X1 g31363(.A (u9_din_tmp_47), .B (in_slt_406), .S0 (n_9777), .Y + (n_9773)); + MX2X1 g31364(.A (u9_din_tmp_48), .B (in_slt_407), .S0 (n_9777), .Y + (n_9772)); + MX2X1 g31365(.A (u9_din_tmp_49), .B (in_slt_408), .S0 (n_9777), .Y + (n_9771)); + MX2X1 g31366(.A (u9_din_tmp_50), .B (in_slt_409), .S0 (n_9777), .Y + (n_9770)); + DFFX1 \u1_sr_reg[13] (.CK (bit_clk_pad_i), .D (u1_sr_128), .Q + (u1_sr_129), .QN ()); + AOI21X1 g30736(.A0 (n_9768), .A1 (n_9660), .B0 (n_9648), .Y (n_9769)); + AOI21X1 g30738(.A0 (n_9766), .A1 (n_9657), .B0 (n_9646), .Y (n_9767)); + MX2X1 g30753(.A (in_slt_738), .B (u1_sr_127), .S0 (out_le), .Y + (n_9765)); + MX2X1 g30754(.A (u1_sr_127), .B (in_slt_753), .S0 (out_le_180), .Y + (n_9764)); + MX2X1 g30755(.A (u1_sr_127), .B (in_slt_837), .S0 (out_le_181), .Y + (n_9763)); + MX2X1 g30756(.A (u1_sr_127), .B (in_slt_407), .S0 (out_le_182), .Y + (n_9762)); + MX2X1 g30757(.A (u1_sr_127), .B (in_slt_429), .S0 (out_le_183), .Y + (n_9761)); + MX2X1 g30758(.A (u1_sr_127), .B (in_slt_451), .S0 (out_le_184), .Y + (n_9760)); + NAND3X1 g31630(.A (n_11564), .B (n_1203), .C (n_9514), .Y (n_9759)); + INVX1 g31755(.A (n_9694), .Y (n_9758)); + OR2X1 g30111(.A (\u13_ints_r[26] ), .B (ic2_int_set), .Y (n_9757)); + AOI22X1 g30116(.A0 (n_9584), .A1 (n_9614), .B0 (n_672), .B1 + (n_12847), .Y (n_9756)); + DFFX1 \u1_slt6_reg[10] (.CK (bit_clk_pad_i), .D (n_9618), .Q + (in_slt_450), .QN ()); + AOI22X1 g30118(.A0 (n_9583), .A1 (n_9611), .B0 (n_752), .B1 (n_9503), + .Y (n_9755)); + DFFX1 \u1_slt2_reg[10] (.CK (bit_clk_pad_i), .D (n_9628), .Q + (in_slt_836), .QN ()); + AOI22X1 g30120(.A0 (n_9582), .A1 (n_9653), .B0 (n_690), .B1 (n_9501), + .Y (n_9754)); + AOI22X1 g30121(.A0 (n_9581), .A1 (n_9650), .B0 (n_599), .B1 (n_9499), + .Y (n_9753)); + DFFSRX1 u14_u4_en_out_l_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9636), .Q (out_slt_18), .QN ()); + DFFSRX1 u2_sync_resume_reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9617), .Q (u2_sync_resume), .QN ()); + DFFX1 \u1_slt1_reg[10] (.CK (bit_clk_pad_i), .D (n_9630), .Q + (in_slt_752), .QN ()); + DFFX1 \u1_slt4_reg[10] (.CK (bit_clk_pad_i), .D (n_9619), .Q + (in_slt_428), .QN ()); + DFFX1 \u1_slt3_reg[10] (.CK (bit_clk_pad_i), .D (n_9625), .Q + (in_slt_406), .QN ()); + DFFSRX1 u14_u0_en_out_l_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9640), .Q (out_slt_23), .QN ()); + DFFSRX1 u14_u1_en_out_l_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9639), .Q (out_slt_22), .QN ()); + DFFSRX1 u14_u2_en_out_l_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9638), .Q (out_slt_20), .QN ()); + DFFSRX1 u14_u3_en_out_l_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9637), .Q (out_slt_19), .QN ()); + DFFSRX1 u14_u5_en_out_l_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9635), .Q (out_slt_17), .QN ()); + DFFX1 u14_crac_valid_r_reg(.CK (clk_i), .D (n_9629), .Q (out_slt_25), + .QN ()); + NAND2X1 g32639(.A (\u10_wp[2] ), .B (n_9564), .Y (n_9752)); + NAND2X1 g32640(.A (\u10_wp[3] ), .B (n_9564), .Y (n_9751)); + INVX4 g32643(.A (n_9750), .Y (n_10103)); + INVX8 g32772(.A (n_9749), .Y (n_10747)); + INVX4 g32783(.A (n_9737), .Y (n_10308)); + INVX4 g32787(.A (n_9737), .Y (n_10045)); + INVX4 g32794(.A (n_9741), .Y (n_10019)); + INVX4 g32799(.A (n_9741), .Y (n_10054)); + INVX4 g32811(.A (n_9741), .Y (n_10235)); + INVX4 g32817(.A (n_9741), .Y (n_10250)); + INVX2 g32822(.A (n_9737), .Y (n_10277)); + INVX4 g32825(.A (n_9737), .Y (n_10267)); + INVX2 g32828(.A (n_9737), .Y (n_10303)); + NAND3X1 g32840(.A (n_9690), .B (n_4680), .C (n_11564), .Y (n_9734)); + NOR2X1 g32843(.A (n_9626), .B (n_12144), .Y (n_10329)); + NOR2X1 g32846(.A (n_12603), .B (n_11491), .Y (n_10327)); + INVX8 g32857(.A (n_9726), .Y (n_10137)); + INVX8 g32866(.A (n_9726), .Y (n_10315)); + CLKBUFX3 g32872(.A (n_9724), .Y (n_10081)); + INVX2 g32882(.A (n_9724), .Y (n_9829)); + INVX4 g32885(.A (n_9675), .Y (n_10065)); + INVX2 g32887(.A (n_9675), .Y (n_10010)); + INVX2 g32898(.A (n_10065), .Y (n_9827)); + INVX4 g32929(.A (n_9721), .Y (n_9820)); + INVX4 g32945(.A (n_9720), .Y (n_9818)); + NOR2X1 g33277(.A (n_9711), .B (n_294), .Y (n_9712)); + NAND2X1 g33280(.A (n_9710), .B (u15_crac_rd), .Y (n_9882)); + INVX1 g33299(.A (n_12149), .Y (n_9943)); + INVX1 g33300(.A (n_12149), .Y (n_9947)); + INVX4 g33303(.A (n_10787), .Y (n_9885)); + INVX2 g33316(.A (n_12608), .Y (n_9931)); + INVX4 g33332(.A (n_9705), .Y (n_9876)); + INVX4 g33359(.A (n_9703), .Y (n_9873)); + AOI21X1 g30735(.A0 (n_9701), .A1 (n_9615), .B0 (n_9592), .Y (n_9702)); + AOI21X1 g30737(.A0 (n_9699), .A1 (n_9612), .B0 (n_9590), .Y (n_9700)); + AOI21X1 g30739(.A0 (n_9697), .A1 (n_9654), .B0 (n_9588), .Y (n_9698)); + AOI21X1 g30740(.A0 (n_9695), .A1 (n_9651), .B0 (n_9586), .Y (n_9696)); + DFFX1 \u0_slt9_r_reg[2] (.CK (bit_clk_pad_i), .D (n_9603), .Q + (u0_slt9_r_169), .QN ()); + DFFX1 \u1_sr_reg[12] (.CK (bit_clk_pad_i), .D (u1_sr_127), .Q + (u1_sr_128), .QN ()); + DFFSRX1 \u26_ps_cnt_reg[5] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9593), .Q (\u26_ps_cnt[5] ), .QN ()); + AOI21X1 g31756(.A0 (i3_full), .A1 (n_9690), .B0 (n_739), .Y (n_9694)); + DFFSRX1 \u26_ps_cnt_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9596), .Q (n_760), .QN ()); + OR2X1 g30109(.A (\u13_ints_r[20] ), .B (ic0_int_set), .Y (n_9693)); + OR2X1 g30110(.A (\u13_ints_r[23] ), .B (ic1_int_set), .Y (n_9692)); + MX2X1 g31809(.A (n_4074), .B (n_4075), .S0 (n_9690), .Y (n_9691)); + INVX1 g34880(.A (n_9710), .Y (n_9689)); + INVX1 g34884(.A (n_9711), .Y (n_9688)); + DFFSRX1 \u26_ps_cnt_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9599), .Q (\u26_ps_cnt[0] ), .QN ()); + DFFSRX1 \u26_ps_cnt_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9598), .Q (\u26_ps_cnt[1] ), .QN ()); + DFFSRX1 \u26_ps_cnt_reg[4] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9594), .Q (\u26_ps_cnt[4] ), .QN ()); + DFFSRX1 \u26_ps_cnt_reg[3] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9595), .Q (\u26_ps_cnt[3] ), .QN ()); + DFFX1 \u12_wb_data_o_reg[1] (.CK (clk_i), .D (n_9608), .Q + (wb_data_o[1]), .QN ()); + DFFSRX1 \u17_int_set_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9578), .Q (), .QN (oc0_int_set_708)); + DFFSRX1 \u18_int_set_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9577), .Q (), .QN (oc1_int_set_710)); + DFFSRX1 \u21_int_set_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9574), .Q (), .QN (oc4_int_set_716)); + DFFSRX1 \u20_int_set_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9575), .Q (), .QN (oc3_int_set_714)); + DFFX1 u14_crac_wr_r_reg(.CK (clk_i), .D (n_9580), .Q (out_slt_24), + .QN ()); + NAND2X1 g32627(.A (\u9_wp[2] ), .B (n_9514), .Y (n_9687)); + NAND2X1 g32628(.A (n_9514), .B (\u9_wp[3] ), .Y (n_9686)); + OR2X1 g32645(.A (\u11_wp[0] ), .B (n_9631), .Y (n_9750)); + DFFSRX1 \u22_int_set_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9573), .Q (), .QN (oc5_int_set_718)); + INVX4 g32747(.A (n_9685), .Y (n_9860)); + INVX2 g32774(.A (n_10024), .Y (n_9749)); + INVX4 g32805(.A (n_9681), .Y (n_10738)); + INVX4 g32816(.A (n_10073), .Y (n_9741)); + INVX4 g32829(.A (n_10073), .Y (n_9737)); + NAND2X1 g32842(.A (n_12148), .B (n_12144), .Y (n_10992)); + NAND2X1 g32845(.A (n_12607), .B (n_12603), .Y (n_10985)); + INVX4 g32867(.A (n_9676), .Y (n_9726)); + INVX4 g32883(.A (n_9675), .Y (n_9724)); + BUFX3 g32933(.A (n_9674), .Y (n_9721)); + INVX2 g32962(.A (n_9674), .Y (n_9720)); + DFFSRX1 \u19_int_set_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9576), .Q (), .QN (oc2_int_set_712)); + INVX1 g33333(.A (n_9668), .Y (n_9705)); + INVX1 g33360(.A (n_9666), .Y (n_9703)); + OAI21X1 g30717(.A0 (n_5832), .A1 (n_9660), .B0 (n_9659), .Y (n_9661)); + OAI21X1 g30719(.A0 (n_5828), .A1 (n_9657), .B0 (n_9656), .Y (n_9658)); + OAI21X1 g30723(.A0 (n_5826), .A1 (n_9654), .B0 (n_9653), .Y (n_9655)); + OAI21X1 g30724(.A0 (n_5436), .A1 (n_9651), .B0 (n_9650), .Y (n_9652)); + AOI21X1 g30734(.A0 (n_7519), .A1 (n_9444), .B0 (n_9526), .Y + (n_11504)); + DFFX1 \u1_slt2_reg[9] (.CK (bit_clk_pad_i), .D (n_9530), .Q + (in_slt_835), .QN ()); + DFFX1 u14_u3_full_empty_r_reg(.CK (clk_i), .D (n_9537), .Q + (u14_u3_full_empty_r), .QN ()); + DFFSRX1 \u25_int_set_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9545), .Q (ic2_int_set), .QN ()); + NOR2X1 g30928(.A (n_9549), .B (n_9647), .Y (n_9648)); + NOR2X1 g30930(.A (n_9547), .B (n_9645), .Y (n_9646)); + OAI21X1 g30941(.A0 (n_1381), .A1 (o4_status), .B0 (n_9606), .Y + (n_9644)); + OAI21X1 g30943(.A0 (n_1384), .A1 (o7_status), .B0 (n_9604), .Y + (n_9643)); + AND2X1 g34881(.A (u15_valid_r), .B (n_11827), .Y (n_9710)); + OR2X1 g34885(.A (u15_valid_r), .B (n_11827), .Y (n_9711)); + DFFX1 u14_u0_full_empty_r_reg(.CK (clk_i), .D (n_9544), .Q + (u14_u0_full_empty_r), .QN ()); + DFFX1 u14_u1_full_empty_r_reg(.CK (clk_i), .D (n_9542), .Q + (u14_u1_full_empty_r), .QN ()); + DFFX1 u14_u2_full_empty_r_reg(.CK (clk_i), .D (n_9539), .Q + (u14_u2_full_empty_r), .QN ()); + DFFX1 u14_u5_full_empty_r_reg(.CK (clk_i), .D (n_9533), .Q + (u14_u5_full_empty_r), .QN ()); + DFFX1 \u1_slt0_reg[9] (.CK (bit_clk_pad_i), .D (n_9531), .Q + (in_slt_736), .QN ()); + DFFX1 u14_u4_full_empty_r_reg(.CK (clk_i), .D (n_9535), .Q + (u14_u4_full_empty_r), .QN ()); + DFFX1 \u1_slt4_reg[9] (.CK (bit_clk_pad_i), .D (n_9528), .Q + (in_slt_427), .QN ()); + DFFX1 \u1_slt3_reg[9] (.CK (bit_clk_pad_i), .D (n_9529), .Q + (in_slt_405), .QN ()); + DFFX1 \u8_wp_reg[0] (.CK (clk_i), .D (n_9520), .Q (\u8_wp[0] ), .QN + ()); + DFFX1 \u3_wp_reg[0] (.CK (clk_i), .D (n_9519), .Q (\u3_wp[0] ), .QN + ()); + DFFX1 \u4_wp_reg[0] (.CK (clk_i), .D (n_9518), .Q (\u4_wp[0] ), .QN + ()); + DFFX1 \u5_wp_reg[0] (.CK (clk_i), .D (n_9517), .Q (\u5_wp[0] ), .QN + ()); + DFFX1 \u6_wp_reg[0] (.CK (clk_i), .D (n_9516), .Q (\u6_wp[0] ), .QN + ()); + DFFX1 \u7_wp_reg[0] (.CK (clk_i), .D (n_9515), .Q (\u7_wp[0] ), .QN + ()); + INVX2 g32685(.A (n_9642), .Y (n_9777)); + OR2X1 g32749(.A (n_9641), .B (n_9564), .Y (n_9685)); + OR2X1 g32757(.A (n_9512), .B (n_9480), .Y (n_9640)); + OR2X1 g32758(.A (n_9511), .B (n_9479), .Y (n_9639)); + OR2X1 g32759(.A (n_9510), .B (n_9478), .Y (n_9638)); + OR2X1 g32760(.A (n_9509), .B (n_9477), .Y (n_9637)); + OR2X1 g32761(.A (n_9508), .B (n_9476), .Y (n_9636)); + OR2X1 g32762(.A (n_9507), .B (n_9475), .Y (n_9635)); + INVX2 g32780(.A (n_9633), .Y (n_10024)); + INVX4 g32791(.A (n_9633), .Y (n_10073)); + CLKBUFX1 g32807(.A (n_9633), .Y (n_9681)); + BUFX3 g32871(.A (n_9632), .Y (n_9676)); + INVX2 g32900(.A (n_9632), .Y (n_9675)); + NAND2X1 g32963(.A (n_3944), .B (n_9571), .Y (n_9674)); + INVX1 g33271(.A (n_9631), .Y (n_9672)); + MX2X1 g31294(.A (u1_sr_126), .B (in_slt_752), .S0 (out_le_180), .Y + (n_9630)); + NAND3X1 g33276(.A (n_9579), .B (n_9472), .C (n_9471), .Y (n_9629)); + MX2X1 g31298(.A (u1_sr_126), .B (in_slt_836), .S0 (out_le_181), .Y + (n_9628)); + INVX1 g33309(.A (n_12148), .Y (n_9626)); + MX2X1 g31300(.A (u1_sr_126), .B (in_slt_406), .S0 (out_le_182), .Y + (n_9625)); + INVX1 g33320(.A (n_12607), .Y (n_11491)); + INVX1 g33334(.A (n_9569), .Y (n_9668)); + INVX1 g33361(.A (n_9567), .Y (n_9666)); + MX2X1 g31309(.A (u1_sr_126), .B (in_slt_428), .S0 (out_le_183), .Y + (n_9619)); + MX2X1 g31318(.A (u1_sr_126), .B (in_slt_450), .S0 (out_le_184), .Y + (n_9618)); + DFFX1 \u1_slt6_reg[9] (.CK (bit_clk_pad_i), .D (n_9527), .Q + (in_slt_449), .QN ()); + AOI21X1 g30707(.A0 (n_415), .A1 (n_416), .B0 (n_9521), .Y (n_9617)); + OAI21X1 g30716(.A0 (n_5840), .A1 (n_9615), .B0 (n_9614), .Y (n_9616)); + OAI21X1 g30718(.A0 (n_5438), .A1 (n_9612), .B0 (n_9611), .Y (n_9613)); + AOI21X1 g30732(.A0 (n_7448), .A1 (n_8847), .B0 (n_9474), .Y + (n_11672)); + AOI21X1 g30733(.A0 (n_7446), .A1 (n_8843), .B0 (n_9473), .Y + (n_11673)); + DFFSRX1 u26_ac97_rst__reg(.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9491), .Q (ac97_reset_pad_o_), .QN ()); + DFFX1 \u1_sr_reg[11] (.CK (bit_clk_pad_i), .D (u1_sr_126), .Q + (u1_sr_127), .QN ()); + DFFSRX1 \u26_cnt_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9492), .Q (\u26_cnt[2] ), .QN ()); + NAND2X1 g31631(.A (n_6680), .B (n_9454), .Y (n_9608)); + INVX1 g31767(.A (n_9606), .Y (n_9607)); + INVX1 g31771(.A (n_9604), .Y (n_9605)); + MX2X1 g31825(.A (n_9602), .B (u0_slt9_r_168), .S0 (n_11319), .Y + (n_9603)); + DFFSRX1 \u23_int_set_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9490), .Q (ic0_int_set), .QN ()); + DFFSRX1 \u24_int_set_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9485), .Q (ic1_int_set), .QN ()); + NAND3X1 g30913(.A (n_8565), .B (n_8567), .C (n_9559), .Y (n_9601)); + NAND3X1 g30915(.A (n_8536), .B (oc3_cfg_997), .C (n_9558), .Y + (n_9600)); + NOR2X1 g30918(.A (n_9597), .B (\u26_ps_cnt[0] ), .Y (n_9599)); + NOR2X1 g30919(.A (n_1441), .B (n_9597), .Y (n_9598)); + NOR2X1 g30920(.A (n_3849), .B (n_9597), .Y (n_9596)); + NOR2X1 g30921(.A (n_2630), .B (n_9597), .Y (n_9595)); + NOR2X1 g30922(.A (n_3994), .B (n_9597), .Y (n_9594)); + NOR2X1 g30923(.A (n_4827), .B (n_9597), .Y (n_9593)); + NOR2X1 g30927(.A (n_9489), .B (n_9591), .Y (n_9592)); + NOR2X1 g30929(.A (n_9487), .B (n_9589), .Y (n_9590)); + NOR2X1 g30931(.A (n_9484), .B (n_9587), .Y (n_9588)); + NOR2X1 g30932(.A (n_9482), .B (n_9585), .Y (n_9586)); + OAI21X1 g30940(.A0 (n_1379), .A1 (o3_status), .B0 (n_9556), .Y + (n_9584)); + OAI21X1 g30942(.A0 (n_1391), .A1 (o6_status), .B0 (n_9554), .Y + (n_9583)); + OAI21X1 g30944(.A0 (n_847), .A1 (o8_status), .B0 (n_9552), .Y + (n_9582)); + OAI21X1 g30945(.A0 (n_977), .A1 (o9_status), .B0 (n_9550), .Y + (n_9581)); + NAND2X1 g34883(.A (n_9470), .B (n_9579), .Y (n_9580)); + DFFSRX1 u14_u8_en_out_l_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9461), .Q (u14_n_135), .QN ()); + DFFSRX1 \u5_wp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9458), .Q (\u5_wp[1] ), .QN ()); + DFFX1 \u6_wp_reg[2] (.CK (clk_i), .D (n_9465), .Q (\u6_wp[2] ), .QN + ()); + DFFSRX1 \u26_cnt_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9494), .Q (\u26_cnt[0] ), .QN ()); + DFFSRX1 \u26_cnt_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_9493), .Q (\u26_cnt[1] ), .QN ()); + DFFX1 \u8_wp_reg[2] (.CK (clk_i), .D (n_9469), .Q (\u8_wp[2] ), .QN + ()); + DFFX1 \u3_wp_reg[2] (.CK (clk_i), .D (n_9466), .Q (\u3_wp[2] ), .QN + ()); + DFFX1 \u5_wp_reg[2] (.CK (clk_i), .D (n_9467), .Q (\u5_wp[2] ), .QN + ()); + DFFX1 \u7_wp_reg[2] (.CK (clk_i), .D (n_9464), .Q (\u7_wp[2] ), .QN + ()); + DFFSRX1 u14_u6_en_out_l_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9463), .Q (u14_n_133), .QN ()); + DFFSRX1 u14_u7_en_out_l_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9462), .Q (u14_n_134), .QN ()); + DFFSRX1 \u8_wp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9460), .Q (\u8_wp[1] ), .QN ()); + DFFSRX1 \u3_wp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9457), .Q (\u3_wp[1] ), .QN ()); + DFFSRX1 \u4_wp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9459), .Q (\u4_wp[1] ), .QN ()); + DFFSRX1 \u6_wp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9456), .Q (\u6_wp[1] ), .QN ()); + DFFSRX1 \u7_wp_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9455), .Q (\u7_wp[1] ), .QN ()); + DFFX1 \u4_wp_reg[2] (.CK (clk_i), .D (n_9468), .Q (\u4_wp[2] ), .QN + ()); + NAND2X1 g32607(.A (n_9453), .B (oc0_int_set_708), .Y (n_9578)); + NAND2X1 g32608(.A (n_9452), .B (oc1_int_set_710), .Y (n_9577)); + NAND2X1 g32609(.A (n_9451), .B (oc2_int_set_712), .Y (n_9576)); + NAND2X1 g32610(.A (n_9450), .B (oc3_int_set_714), .Y (n_9575)); + NAND2X1 g32611(.A (n_9449), .B (oc4_int_set_716), .Y (n_9574)); + NAND2X1 g32612(.A (n_9448), .B (oc5_int_set_718), .Y (n_9573)); + OR2X1 g32687(.A (n_1203), .B (n_9514), .Y (n_9642)); + INVX2 g32834(.A (n_9572), .Y (n_9633)); + NAND2X1 g32901(.A (n_4633), .B (n_9513), .Y (n_9632)); + INVX1 g33272(.A (n_9571), .Y (n_9631)); + NOR2X1 g33335(.A (n_11529), .B (n_8665), .Y (n_9569)); + NOR2X1 g33362(.A (n_11530), .B (n_8661), .Y (n_9567)); + INVX1 g33379(.A (n_9564), .Y (n_9620)); + AOI21X1 g31655(.A0 (n_7289), .A1 (n_1127), .B0 (n_12845), .Y + (n_9563)); + AOI21X1 g31657(.A0 (n_7165), .A1 (n_1071), .B0 (n_9560), .Y (n_9561)); + OR2X1 g31661(.A (n_9559), .B (n_9548), .Y (n_9660)); + OR2X1 g31668(.A (n_9558), .B (n_9546), .Y (n_9657)); + INVX1 g31765(.A (n_9556), .Y (n_9557)); + AOI21X1 g31768(.A0 (n_1127), .A1 (n_7161), .B0 (n_12846), .Y + (n_9606)); + INVX1 g31769(.A (n_9554), .Y (n_9555)); + AOI21X1 g31772(.A0 (n_1071), .A1 (n_7036), .B0 (n_9560), .Y (n_9604)); + INVX1 g31773(.A (n_9552), .Y (n_9553)); + INVX1 g31775(.A (n_9550), .Y (n_9551)); + AOI21X1 g31793(.A0 (n_5396), .A1 (n_9548), .B0 (n_9559), .Y (n_9549)); + AOI21X1 g31795(.A0 (n_5400), .A1 (n_9546), .B0 (n_9558), .Y (n_9547)); + NAND3X1 g30853(.A (n_9445), .B (n_1885), .C (n_8209), .Y (n_9545)); + MX2X1 g31814(.A (u14_u0_full_empty_r), .B (n_9543), .S0 (n_11827), .Y + (n_9544)); + MX2X1 g31815(.A (u14_u1_full_empty_r), .B (n_9541), .S0 (n_11827), .Y + (n_9542)); + MX2X1 g31816(.A (u14_u2_full_empty_r), .B (n_9538), .S0 (n_11827), .Y + (n_9539)); + MX2X1 g31817(.A (u14_u3_full_empty_r), .B (n_9536), .S0 (n_11827), .Y + (n_9537)); + MX2X1 g31818(.A (u14_u4_full_empty_r), .B (n_9534), .S0 (n_11827), .Y + (n_9535)); + MX2X1 g31819(.A (u14_u5_full_empty_r), .B (n_9532), .S0 (n_11827), .Y + (n_9533)); + MX2X1 g31820(.A (in_slt_736), .B (u1_sr_125), .S0 (out_le), .Y + (n_9531)); + MX2X1 g31821(.A (u1_sr_125), .B (in_slt_835), .S0 (out_le_181), .Y + (n_9530)); + MX2X1 g31822(.A (u1_sr_125), .B (in_slt_405), .S0 (out_le_182), .Y + (n_9529)); + MX2X1 g31823(.A (u1_sr_125), .B (in_slt_427), .S0 (out_le_183), .Y + (n_9528)); + MX2X1 g31824(.A (u1_sr_125), .B (in_slt_449), .S0 (out_le_184), .Y + (n_9527)); + OAI21X1 g30905(.A0 (n_7387), .A1 (n_8205), .B0 (n_9446), .Y (n_9526)); + NAND3X1 g30912(.A (n_8526), .B (n_8528), .C (n_9498), .Y (n_9525)); + NAND3X1 g30914(.A (n_8550), .B (oc2_cfg_987), .C (n_9497), .Y + (n_9524)); + NAND3X1 g30916(.A (n_8188), .B (n_8190), .C (n_9496), .Y (n_9523)); + NAND3X1 g30917(.A (n_8197), .B (n_8199), .C (n_9495), .Y (n_9522)); + AOI21X1 g30938(.A0 (resume_req), .A1 (suspended_o), .B0 + (u2_sync_resume), .Y (n_9521)); + DFFX1 u15_valid_r_reg(.CK (clk_i), .D (n_11823), .Q (u15_valid_r), + .QN ()); + DFFX1 \u1_slt6_reg[8] (.CK (bit_clk_pad_i), .D (n_9353), .Q + (in_slt_448), .QN ()); + DFFX1 \u1_slt2_reg[8] (.CK (bit_clk_pad_i), .D (n_9356), .Q + (in_slt_834), .QN ()); + DFFX1 \u1_slt1_reg[8] (.CK (bit_clk_pad_i), .D (n_9357), .Q + (in_slt_750), .QN ()); + DFFX1 \u1_slt4_reg[8] (.CK (bit_clk_pad_i), .D (n_9354), .Q + (in_slt_426), .QN ()); + DFFX1 \u1_slt3_reg[8] (.CK (bit_clk_pad_i), .D (n_9355), .Q + (in_slt_404), .QN ()); + DFFSRX1 \u4_mem_reg[0][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9442), .Q (\u4_mem[0]_103 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9441), .Q (\u4_mem[0]_104 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9440), .Q (\u4_mem[0]_106 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9439), .Q (\u4_mem[0]_109 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9437), .Q (\u4_mem[0]_112 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9435), .Q (\u4_mem[0]_114 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9434), .Q (\u4_mem[0]_121 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9433), .Q (\u4_mem[0]_94 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9432), .Q (\u4_mem[0]_97 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9430), .Q (\u4_mem[0]_99 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9429), .Q (\u5_mem[0]_103 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9428), .Q (\u5_mem[0]_104 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9427), .Q (\u5_mem[0]_106 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9426), .Q (\u5_mem[0]_109 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9424), .Q (\u5_mem[0]_112 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9422), .Q (\u5_mem[0]_114 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9421), .Q (\u5_mem[0]_121 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9420), .Q (\u5_mem[0]_94 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9419), .Q (\u5_mem[0]_97 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9417), .Q (\u5_mem[0]_99 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9414), .Q (\u6_mem[0]_103 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9413), .Q (\u6_mem[0]_104 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9412), .Q (\u6_mem[0]_106 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9411), .Q (\u6_mem[0]_109 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9409), .Q (\u6_mem[0]_112 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9407), .Q (\u6_mem[0]_114 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9406), .Q (\u6_mem[0]_121 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9405), .Q (\u6_mem[0]_94 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9404), .Q (\u6_mem[0]_97 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9402), .Q (\u6_mem[0]_99 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9401), .Q (\u7_mem[0]_103 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9400), .Q (\u7_mem[0]_104 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9399), .Q (\u7_mem[0]_106 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9398), .Q (\u7_mem[0]_109 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9396), .Q (\u7_mem[0]_112 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9394), .Q (\u7_mem[0]_114 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9393), .Q (\u7_mem[0]_121 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9392), .Q (\u7_mem[0]_94 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9391), .Q (\u7_mem[0]_97 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9389), .Q (\u7_mem[0]_99 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9443), .Q (\u3_mem[0]_101 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9388), .Q (\u3_mem[0]_102 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9387), .Q (\u3_mem[0]_105 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9386), .Q (\u8_mem[0] ), .QN ()); + DFFSRX1 \u8_mem_reg[0][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9385), .Q (\u8_mem[0]_101 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9383), .Q (\u8_mem[0]_102 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9381), .Q (\u8_mem[0]_107 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9382), .Q (\u3_mem[0]_91 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9380), .Q (\u3_mem[0]_111 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9379), .Q (\u8_mem[0]_116 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9378), .Q (\u8_mem[0]_118 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9376), .Q (\u8_mem[0]_119 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9375), .Q (\u8_mem[0]_120 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9373), .Q (\u3_mem[0]_117 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9371), .Q (\u8_mem[0]_94 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9370), .Q (\u8_mem[0]_95 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9416), .Q (\u3_mem[0]_92 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9369), .Q (\u3_mem[0]_119 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9366), .Q (\u3_mem[0]_96 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9368), .Q (\u3_mem[0]_95 ), .QN ()); + NOR2X1 g32769(.A (n_9365), .B (n_11128), .Y (n_9520)); + NAND2X1 g32835(.A (n_3942), .B (n_9447), .Y (n_9572)); + NOR2X1 g32839(.A (n_9362), .B (n_5839), .Y (n_9519)); + NOR2X1 g32844(.A (n_9364), .B (n_10940), .Y (n_9518)); + NOR2X1 g32902(.A (n_9363), .B (n_10994), .Y (n_9517)); + NOR2X1 g32972(.A (n_9361), .B (n_11086), .Y (n_9516)); + NOR2X1 g32977(.A (n_9360), .B (n_11144), .Y (n_9515)); + NOR2X1 g33273(.A (n_8210), .B (u14_u8_en_out_l2), .Y (n_9571)); + INVX1 g33368(.A (n_9514), .Y (n_9690)); + INVX1 g33380(.A (n_9513), .Y (n_9564)); + AOI21X1 g33383(.A0 (n_8671), .A1 (n_1375), .B0 (n_1021), .Y (n_9512)); + AOI21X1 g33384(.A0 (n_8669), .A1 (n_1302), .B0 (n_1010), .Y (n_9511)); + AOI21X1 g33385(.A0 (n_8666), .A1 (n_1373), .B0 (n_1009), .Y (n_9510)); + AOI21X1 g33386(.A0 (n_8664), .A1 (n_1356), .B0 (n_1023), .Y (n_9509)); + AOI21X1 g33387(.A0 (n_8662), .A1 (n_1101), .B0 (n_1008), .Y (n_9508)); + AOI21X1 g33388(.A0 (n_8660), .A1 (n_1146), .B0 (n_1007), .Y (n_9507)); + DFFSRX1 \u13_crac_r_reg[6] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8627), .Q (crac_out_867), .QN ()); + DFFSRX1 \u3_mem_reg[0][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8720), .Q (\u3_mem[0]_107 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8875), .Q (\u8_mem[2]_46 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8742), .Q (\u7_mem[0]_110 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8861), .Q (\u8_mem[2]_53 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8855), .Q (\u8_mem[2]_56 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8294), .Q (\u4_mem[2]_44 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9293), .Q (\u5_mem[1]_85 ), .QN ()); + DFFSRX1 \u13_occ0_r_reg[11] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8569), .Q (oc1_cfg_976), .QN ()); + DFFSRX1 \u5_mem_reg[1][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9298), .Q (\u5_mem[1]_81 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9310), .Q (\u5_mem[1]_74 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9302), .Q (\u5_mem[1]_78 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9315), .Q (\u5_mem[1]_70 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8866), .Q (\u3_mem[1]_81 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8869), .Q (\u8_mem[2]_48 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9319), .Q (\u4_mem[3]_130 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9324), .Q (\u4_mem[3]_126 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9329), .Q (\u4_mem[3]_151 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8715), .Q (\u8_mem[0]_105 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8722), .Q (\u3_mem[0]_106 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9339), .Q (\u4_mem[3]_144 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9334), .Q (\u4_mem[3]_148 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9072), .Q (\u8_mem[1]_65 ), .QN ()); + DFFSRX1 \u13_occ0_r_reg[8] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8523), .Q (oc1_cfg), .QN ()); + DFFSRX1 \u13_icc_r_reg[8] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8575), .Q (ic1_cfg), .QN ()); + DFFSRX1 \u8_mem_reg[2][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8882), .Q (\u8_mem[2]_41 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8880), .Q (\u3_mem[1]_78 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8266), .Q (\u4_mem[2]_37 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9350), .Q (\u4_mem[3]_137 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8261), .Q (\u4_mem[3]_133 ), .QN ()); + AOI21X1 g31654(.A0 (n_7166), .A1 (n_1122), .B0 (n_12847), .Y + (n_9506)); + AOI21X1 g31656(.A0 (n_7288), .A1 (n_1208), .B0 (n_9503), .Y (n_9504)); + AOI21X1 g31658(.A0 (n_7164), .A1 (n_1130), .B0 (n_9501), .Y (n_9502)); + AOI21X1 g31659(.A0 (n_7163), .A1 (n_1116), .B0 (n_9499), .Y (n_9500)); + OR2X1 g31660(.A (n_9498), .B (n_9488), .Y (n_9615)); + DFFSRX1 \u4_mem_reg[2][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8270), .Q (\u4_mem[2]_33 ), .QN ()); + OR2X1 g31662(.A (n_9497), .B (n_9486), .Y (n_9612)); + OR2X1 g31670(.A (n_9496), .B (n_9483), .Y (n_9654)); + OR2X1 g31671(.A (n_9495), .B (n_9481), .Y (n_9651)); + AND2X1 g31672(.A (n_5615), .B (ac97_rst_force), .Y (n_9494)); + NAND2X1 g31673(.A (n_5632), .B (ac97_rst_force), .Y (n_9597)); + DFFSRX1 \u3_mem_reg[1][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8897), .Q (\u3_mem[1]_74 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8274), .Q (\u4_mem[2]_58 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8280), .Q (\u4_mem[2]_55 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8284), .Q (\u4_mem[2]_51 ), .QN ()); + AND2X1 g31731(.A (n_5626), .B (ac97_rst_force), .Y (n_9493)); + AND2X1 g31732(.A (n_5625), .B (ac97_rst_force), .Y (n_9492)); + DFFSRX1 \u7_mem_reg[0][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8731), .Q (\u7_mem[0]_120 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8400), .Q (\u3_mem[2]_30 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8924), .Q (\u8_mem[1]_80 ), .QN ()); + AND2X1 g31761(.A (n_1778), .B (ac97_rst_force), .Y (n_9491)); + DFFSRX1 \u3_mem_reg[1][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8908), .Q (\u3_mem[1]_70 ), .QN ()); + AOI21X1 g31766(.A0 (n_1122), .A1 (n_7037), .B0 (n_12848), .Y + (n_9556)); + AOI21X1 g31770(.A0 (n_1208), .A1 (n_7160), .B0 (n_9503), .Y (n_9554)); + DFFSRX1 \u8_mem_reg[1][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8902), .Q (\u8_mem[1]_62 ), .QN ()); + AOI21X1 g31774(.A0 (n_1130), .A1 (n_7035), .B0 (n_9501), .Y (n_9552)); + AOI21X1 g31776(.A0 (n_1116), .A1 (n_7034), .B0 (n_9499), .Y (n_9550)); + DFFSRX1 \u4_mem_reg[2][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8298), .Q (\u4_mem[2]_40 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8313), .Q (\u4_mem[1]_89 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8303), .Q (\u4_mem[1]_68 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8308), .Q (\u4_mem[1]_64 ), .QN ()); + NAND3X1 g30848(.A (n_8848), .B (n_1887), .C (n_7533), .Y (n_9490)); + AOI21X1 g31792(.A0 (n_5398), .A1 (n_9488), .B0 (n_9498), .Y (n_9489)); + AOI21X1 g31794(.A0 (n_4070), .A1 (n_9486), .B0 (n_9497), .Y (n_9487)); + NAND3X1 g30850(.A (n_8844), .B (n_1886), .C (n_7530), .Y (n_9485)); + AOI21X1 g31797(.A0 (n_5394), .A1 (n_9483), .B0 (n_9496), .Y (n_9484)); + AOI21X1 g31798(.A0 (n_4068), .A1 (n_9481), .B0 (n_9495), .Y (n_9482)); + DFFSRX1 \u4_mem_reg[1][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8320), .Q (\u4_mem[1]_86 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9196), .Q (\u8_mem[1]_87 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8724), .Q (\u3_mem[0]_103 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8918), .Q (\u8_mem[1]_84 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8325), .Q (\u4_mem[1]_82 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8336), .Q (\u4_mem[1]_75 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8727), .Q (\u7_mem[0]_96 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9042), .Q (\u7_mem[1]_84 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9069), .Q (\u3_mem[3]_124 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8342), .Q (\u4_mem[1]_71 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8952), .Q (\u7_mem[3]_124 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8935), .Q (\u8_mem[1]_73 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8929), .Q (\u8_mem[1]_77 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8355), .Q (\u3_mem[3]_127 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8371), .Q (\u3_mem[3]_143 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8361), .Q (\u3_mem[3]_151 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8366), .Q (\u3_mem[3]_148 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8739), .Q (\u7_mem[0]_113 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8376), .Q (\u3_mem[3]_140 ), .QN ()); + DFFX1 u14_u0_en_out_l2_reg(.CK (clk_i), .D (n_9480), .Q (n_11507), + .QN ()); + DFFX1 u14_u1_en_out_l2_reg(.CK (clk_i), .D (n_9479), .Q + (u14_u1_en_out_l2), .QN ()); + DFFX1 u14_u2_en_out_l2_reg(.CK (clk_i), .D (n_9478), .Q (n_11533), + .QN ()); + DFFX1 u14_u3_en_out_l2_reg(.CK (clk_i), .D (n_9477), .Q (n_11529), + .QN ()); + DFFX1 u14_u4_en_out_l2_reg(.CK (clk_i), .D (n_9476), .Q (n_11528), + .QN ()); + DFFX1 u14_u5_en_out_l2_reg(.CK (clk_i), .D (n_9475), .Q (n_11530), + .QN ()); + DFFSRX1 \u6_mem_reg[0][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8778), .Q (\u6_mem[0]_102 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8940), .Q (\u8_mem[1]_69 ), .QN ()); + OAI21X1 g30903(.A0 (n_7295), .A1 (n_7526), .B0 (n_8915), .Y (n_9474)); + OAI21X1 g30904(.A0 (n_7294), .A1 (n_7524), .B0 (n_8909), .Y (n_9473)); + DFFSRX1 \u7_mem_reg[3][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8946), .Q (\u7_mem[3]_128 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8381), .Q (\u3_mem[3]_136 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8386), .Q (\u3_mem[3]_132 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8391), .Q (\u3_mem[2]_36 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8750), .Q (\u7_mem[0]_102 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8977), .Q (\u7_mem[3]_135 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8962), .Q (\u7_mem[3]_146 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8956), .Q (\u7_mem[3]_150 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8404), .Q (\u3_mem[2]_54 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8406), .Q (\u3_mem[2]_50 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8412), .Q (\u3_mem[2]_46 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9068), .Q (\u8_mem[3]_129 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9197), .Q (\u8_mem[3]_127 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8967), .Q (\u7_mem[3]_142 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8972), .Q (\u7_mem[3]_139 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8422), .Q (\u8_mem[3]_124 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8427), .Q (\u3_mem[2]_39 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8365), .Q (\u8_mem[3]_149 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8747), .Q (\u7_mem[0]_107 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8753), .Q (\u7_mem[0] ), .QN ()); + DFFSRX1 \u8_mem_reg[3][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8439), .Q (\u8_mem[3]_143 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8434), .Q (\u8_mem[3]_146 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9000), .Q (\u7_mem[2]_53 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8986), .Q (\u7_mem[2]_35 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8982), .Q (\u7_mem[3]_131 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8448), .Q (\u8_mem[3]_139 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8460), .Q (\u3_mem[1]_62 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8456), .Q (\u8_mem[3]_136 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8465), .Q (\u8_mem[3]_131 ), .QN ()); + OR2X1 g35290(.A (n_36), .B (n_11827), .Y (n_9472)); + NAND2X1 g35291(.A (out_slt_25), .B (n_11827), .Y (n_9471)); + OR2X1 g35292(.A (n_324), .B (n_11827), .Y (n_9579)); + NAND2X1 g35293(.A (out_slt_24), .B (n_11827), .Y (n_9470)); + DFFSRX1 \u7_mem_reg[2][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8990), .Q (\u7_mem[2]_31 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8995), .Q (\u7_mem[2]_57 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8471), .Q (\u3_mem[1]_61 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9004), .Q (\u7_mem[2]_49 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9009), .Q (\u7_mem[2]_46 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8759), .Q (\u6_mem[0]_120 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8755), .Q (\u6_mem[0]_96 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9014), .Q (\u7_mem[2]_42 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9019), .Q (\u7_mem[2]_38 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8473), .Q (\u8_mem[2]_34 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8763), .Q (\u6_mem[0]_118 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9025), .Q (\u7_mem[1]_66 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9074), .Q (\u6_mem[3]_129 ), .QN ()); + DFFX1 \u13_crac_dout_r_reg[3] (.CK (clk_i), .D (n_8641), .Q (), .QN + (crac_out_848)); + DFFX1 \u13_crac_dout_r_reg[9] (.CK (clk_i), .D (n_8636), .Q (), .QN + (crac_out_854)); + DFFSRX1 \u7_mem_reg[1][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9030), .Q (\u7_mem[1]_62 ), .QN ()); + DFFSRX1 \u13_icc_r_reg[22] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8592), .Q (ic2_cfg_1049), .QN ()); + DFFX1 \u13_crac_dout_r_reg[14] (.CK (clk_i), .D (n_8649), .Q (), .QN + (crac_out_859)); + DFFSRX1 \u13_occ0_r_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8535), .Q (oc0_cfg_965), .QN ()); + DFFSRX1 \u13_occ0_r_reg[4] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8529), .Q (n_8528), .QN ()); + DFFSRX1 \u13_intm_r_reg[7] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8489), .Q (\u13_intm_r[7] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[22] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8506), .Q (\u13_intm_r[22] ), .QN ()); + DFFSRX1 \u13_icc_r_reg[11] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8620), .Q (ic1_cfg_1036), .QN ()); + DFFSRX1 \u7_mem_reg[1][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9037), .Q (\u7_mem[1]_88 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8767), .Q (\u6_mem[0]_113 ), .QN ()); + DFFSRX1 \u13_icc_r_reg[15] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8610), .Q (ic1_cfg_1040), .QN ()); + DFFSRX1 \u13_icc_r_reg[19] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8601), .Q (ic2_cfg_1046), .QN ()); + DFFSRX1 \u13_crac_r_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8635), .Q (crac_out_861), .QN ()); + DFFSRX1 \u13_crac_r_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8633), .Q (crac_out_862), .QN ()); + DFFSRX1 \u13_crac_r_reg[3] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8631), .Q (crac_out_864), .QN ()); + DFFSRX1 \u13_crac_r_reg[4] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8630), .Q (crac_out_865), .QN ()); + DFFSRX1 \u13_crac_r_reg[5] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8628), .Q (crac_out_866), .QN ()); + DFFSRX1 \u13_crac_r_reg[7] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8626), .Q (crac_out_876), .QN ()); + DFFSRX1 \u13_icc_r_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8624), .Q (ic0_cfg), .QN ()); + DFFSRX1 \u13_icc_r_reg[10] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8622), .Q (ic1_cfg_1035), .QN ()); + DFFSRX1 \u13_icc_r_reg[12] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8618), .Q (n_4736), .QN ()); + DFFSRX1 \u13_icc_r_reg[13] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8616), .Q (n_4734), .QN ()); + DFFSRX1 \u13_icc_r_reg[14] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8613), .Q (ic1_cfg_1039), .QN ()); + DFFSRX1 \u13_icc_r_reg[16] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8608), .Q (ic2_cfg), .QN ()); + DFFSRX1 \u13_icc_r_reg[17] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8606), .Q (ic2_cfg_1044), .QN ()); + DFFSRX1 \u13_icc_r_reg[18] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8604), .Q (ic2_cfg_1045), .QN ()); + DFFSRX1 \u13_icc_r_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8599), .Q (ic0_cfg_1024), .QN ()); + DFFSRX1 \u13_icc_r_reg[20] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8597), .Q (n_5788), .QN ()); + DFFSRX1 \u13_icc_r_reg[21] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8594), .Q (n_5588), .QN ()); + DFFSRX1 \u13_icc_r_reg[23] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8589), .Q (ic2_cfg_1050), .QN ()); + DFFSRX1 \u13_icc_r_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8588), .Q (ic0_cfg_1025), .QN ()); + DFFSRX1 \u13_icc_r_reg[3] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8586), .Q (ic0_cfg_1026), .QN ()); + DFFSRX1 \u13_icc_r_reg[4] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8584), .Q (n_4708), .QN ()); + DFFSRX1 \u13_icc_r_reg[5] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8581), .Q (n_4703), .QN ()); + DFFSRX1 \u13_icc_r_reg[6] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8579), .Q (ic0_cfg_1029), .QN ()); + DFFSRX1 \u13_icc_r_reg[7] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8577), .Q (ic0_cfg_1030), .QN ()); + DFFSRX1 \u13_icc_r_reg[9] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8573), .Q (ic1_cfg_1034), .QN ()); + DFFSRX1 \u13_occ0_r_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8571), .Q (oc0_cfg), .QN ()); + DFFSRX1 \u13_occ0_r_reg[10] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8570), .Q (oc1_cfg_975), .QN ()); + DFFSRX1 \u13_occ0_r_reg[12] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8568), .Q (n_8567), .QN ()); + DFFSRX1 \u13_occ0_r_reg[13] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8566), .Q (n_8565), .QN ()); + DFFSRX1 \u13_occ0_r_reg[14] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8564), .Q (oc1_cfg_979), .QN ()); + DFFSRX1 \u13_occ0_r_reg[16] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8562), .Q (oc2_cfg), .QN ()); + DFFSRX1 \u13_occ0_r_reg[17] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8560), .Q (oc2_cfg_984), .QN ()); + DFFSRX1 \u13_occ0_r_reg[18] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8558), .Q (oc2_cfg_985), .QN ()); + DFFSRX1 \u13_occ0_r_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8555), .Q (oc0_cfg_964), .QN ()); + DFFSRX1 \u13_occ0_r_reg[20] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8554), .Q (oc2_cfg_987), .QN ()); + DFFSRX1 \u13_occ0_r_reg[21] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8551), .Q (n_8550), .QN ()); + DFFSRX1 \u13_occ0_r_reg[23] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8548), .Q (oc2_cfg_990), .QN ()); + DFFSRX1 \u13_occ0_r_reg[24] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8546), .Q (oc3_cfg), .QN ()); + DFFSRX1 \u13_occ0_r_reg[25] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8545), .Q (oc3_cfg_994), .QN ()); + DFFSRX1 \u13_occ0_r_reg[27] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8542), .Q (oc3_cfg_996), .QN ()); + DFFSRX1 \u13_occ0_r_reg[28] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8540), .Q (oc3_cfg_997), .QN ()); + DFFSRX1 \u13_occ0_r_reg[29] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8537), .Q (n_8536), .QN ()); + DFFSRX1 \u13_occ0_r_reg[30] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8534), .Q (oc3_cfg_999), .QN ()); + DFFSRX1 \u13_occ0_r_reg[31] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8532), .Q (oc3_cfg_1000), .QN ()); + DFFSRX1 \u13_occ0_r_reg[3] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8530), .Q (oc0_cfg_966), .QN ()); + DFFSRX1 \u13_occ0_r_reg[5] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8527), .Q (n_8526), .QN ()); + DFFSRX1 \u13_occ0_r_reg[6] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8525), .Q (oc0_cfg_969), .QN ()); + DFFSRX1 \u13_occ0_r_reg[7] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8524), .Q (oc0_cfg_970), .QN ()); + DFFSRX1 \u13_occ0_r_reg[9] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8522), .Q (oc1_cfg_974), .QN ()); + DFFSRX1 \u13_intm_r_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8521), .Q (\u13_intm_r[0] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[10] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8520), .Q (\u13_intm_r[10] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[11] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8518), .Q (\u13_intm_r[11] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[12] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8517), .Q (\u13_intm_r[12] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[13] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8516), .Q (\u13_intm_r[13] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[14] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8515), .Q (\u13_intm_r[14] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[16] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8513), .Q (\u13_intm_r[16] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[17] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8512), .Q (\u13_intm_r[17] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[18] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8511), .Q (\u13_intm_r[18] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[19] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8510), .Q (\u13_intm_r[19] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8509), .Q (\u13_intm_r[1] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[20] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8508), .Q (\u13_intm_r[20] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[21] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8507), .Q (\u13_intm_r[21] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[23] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8505), .Q (\u13_intm_r[23] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[24] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8504), .Q (\u13_intm_r[24] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[25] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8502), .Q (\u13_intm_r[25] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[27] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8498), .Q (\u13_intm_r[27] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[28] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8496), .Q (\u13_intm_r[28] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8494), .Q (\u13_intm_r[2] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[5] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8491), .Q (\u13_intm_r[5] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[6] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8490), .Q (\u13_intm_r[6] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[9] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8487), .Q (\u13_intm_r[9] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[4] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8492), .Q (\u13_intm_r[4] ), .QN ()); + DFFSRX1 \u13_intm_r_reg[15] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8514), .Q (\u13_intm_r[15] ), .QN ()); + DFFX1 \u13_crac_dout_r_reg[0] (.CK (clk_i), .D (n_8655), .Q (), .QN + (crac_out)); + DFFX1 \u13_crac_dout_r_reg[10] (.CK (clk_i), .D (n_8654), .Q (), .QN + (crac_out_855)); + DFFX1 \u13_crac_dout_r_reg[11] (.CK (clk_i), .D (n_8653), .Q (), .QN + (crac_out_856)); + DFFX1 \u13_crac_dout_r_reg[12] (.CK (clk_i), .D (n_8652), .Q (), .QN + (crac_out_857)); + DFFX1 \u13_crac_dout_r_reg[13] (.CK (clk_i), .D (n_8651), .Q (), .QN + (crac_out_858)); + DFFX1 \u13_crac_dout_r_reg[15] (.CK (clk_i), .D (n_8648), .Q (), .QN + (crac_out_860)); + DFFX1 \u13_crac_dout_r_reg[1] (.CK (clk_i), .D (n_8646), .Q (), .QN + (crac_out_846)); + DFFX1 \u13_crac_dout_r_reg[2] (.CK (clk_i), .D (n_8644), .Q (), .QN + (crac_out_847)); + DFFX1 \u13_crac_dout_r_reg[4] (.CK (clk_i), .D (n_8642), .Q (), .QN + (crac_out_849)); + DFFX1 \u13_crac_dout_r_reg[5] (.CK (clk_i), .D (n_8640), .Q (), .QN + (crac_out_850)); + DFFX1 \u13_crac_dout_r_reg[6] (.CK (clk_i), .D (n_8639), .Q (), .QN + (crac_out_851)); + DFFX1 \u13_crac_dout_r_reg[8] (.CK (clk_i), .D (n_8637), .Q (), .QN + (crac_out_853)); + DFFSRX1 \u8_mem_reg[2][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8845), .Q (\u8_mem[2]_32 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8846), .Q (\u3_mem[1]_87 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8475), .Q (\u8_mem[2]_33 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8474), .Q (\u3_mem[1]_88 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8472), .Q (\u8_mem[2]_35 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8470), .Q (\u8_mem[2]_36 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8469), .Q (\u8_mem[2]_37 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8467), .Q (\u8_mem[3] ), .QN ()); + DFFSRX1 \u3_mem_reg[1][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8408), .Q (\u3_mem[1]_89 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8903), .Q (\u8_mem[3]_132 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8463), .Q (\u3_mem[1]_90 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8462), .Q (\u8_mem[3]_133 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8459), .Q (\u8_mem[3]_134 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8455), .Q (\u3_mem[1]_63 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8458), .Q (\u8_mem[3]_135 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8454), .Q (\u8_mem[3]_137 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8450), .Q (\u8_mem[3]_138 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8452), .Q (\u3_mem[1]_64 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8468), .Q (\u8_mem[3]_140 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8447), .Q (\u3_mem[1]_65 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8446), .Q (\u8_mem[3]_122 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8445), .Q (\u3_mem[1]_66 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8443), .Q (\u8_mem[3]_141 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8442), .Q (\u8_mem[3]_142 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8441), .Q (\u3_mem[1]_67 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8437), .Q (\u8_mem[3]_144 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8435), .Q (\u8_mem[3]_145 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8436), .Q (\u3_mem[1]_68 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8350), .Q (\u8_mem[3]_147 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8432), .Q (\u3_mem[2] ), .QN ()); + DFFSRX1 \u8_mem_reg[3][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8431), .Q (\u8_mem[3]_148 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8430), .Q (\u3_mem[2]_38 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8428), .Q (\u8_mem[3]_150 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8426), .Q (\u8_mem[3]_123 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8425), .Q (\u8_mem[3]_151 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9193), .Q (\u8_mem[3]_152 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8424), .Q (\u3_mem[2]_40 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9070), .Q (\u8_mem[3]_125 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8421), .Q (\u3_mem[2]_41 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8420), .Q (\u8_mem[3]_126 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9318), .Q (\u3_mem[2]_42 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8419), .Q (\u8_mem[3]_128 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8418), .Q (\u3_mem[2]_43 ), .QN ()); + DFFSRX1 \u8_mem_reg[3][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8416), .Q (\u8_mem[3]_130 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8415), .Q (\u3_mem[2]_44 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8943), .Q (\u3_mem[2]_45 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8411), .Q (\u3_mem[2]_47 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8410), .Q (\u3_mem[2]_29 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8407), .Q (\u3_mem[2]_49 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8346), .Q (\u3_mem[2]_51 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8405), .Q (\u3_mem[2]_52 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9071), .Q (\u3_mem[2]_53 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8403), .Q (\u3_mem[2]_55 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8402), .Q (\u3_mem[2]_56 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8401), .Q (\u3_mem[2]_57 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8399), .Q (\u3_mem[2]_58 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8398), .Q (\u3_mem[2]_59 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8397), .Q (\u3_mem[2]_31 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8396), .Q (\u3_mem[2]_32 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8395), .Q (\u3_mem[2]_33 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8394), .Q (\u3_mem[2]_34 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8392), .Q (\u3_mem[2]_35 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8390), .Q (\u3_mem[2]_37 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8389), .Q (\u3_mem[3] ), .QN ()); + DFFSRX1 \u3_mem_reg[3][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8388), .Q (\u3_mem[3]_131 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8385), .Q (\u3_mem[3]_133 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8384), .Q (\u3_mem[3]_134 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8382), .Q (\u3_mem[3]_135 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8379), .Q (\u3_mem[3]_137 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8378), .Q (\u3_mem[3]_138 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8377), .Q (\u3_mem[3]_139 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8374), .Q (\u3_mem[3]_122 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9023), .Q (\u3_mem[3]_141 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8373), .Q (\u3_mem[3]_142 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8370), .Q (\u3_mem[3]_144 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8368), .Q (\u3_mem[3]_145 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8367), .Q (\u3_mem[3]_147 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8364), .Q (\u3_mem[3]_149 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8363), .Q (\u3_mem[3]_150 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8362), .Q (\u3_mem[3]_123 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8360), .Q (\u3_mem[3]_152 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8359), .Q (\u3_mem[3]_125 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8358), .Q (\u3_mem[3]_126 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8354), .Q (\u3_mem[3]_128 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8352), .Q (\u3_mem[3]_130 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8348), .Q (\u3_mem[3]_146 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8345), .Q (\u4_mem[1] ), .QN ()); + DFFSRX1 \u4_mem_reg[1][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8344), .Q (\u4_mem[1]_69 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8343), .Q (\u4_mem[1]_70 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8341), .Q (\u4_mem[1]_72 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8340), .Q (\u4_mem[1]_73 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8338), .Q (\u4_mem[1]_74 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8334), .Q (\u4_mem[1]_76 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8332), .Q (\u4_mem[1]_77 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8330), .Q (\u4_mem[1]_78 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8329), .Q (\u4_mem[1]_60 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8328), .Q (\u4_mem[1]_79 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8327), .Q (\u4_mem[1]_80 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8326), .Q (\u4_mem[1]_81 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8324), .Q (\u4_mem[1]_83 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8322), .Q (\u4_mem[1]_84 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8321), .Q (\u4_mem[1]_85 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8319), .Q (\u4_mem[1]_87 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8317), .Q (\u4_mem[1]_88 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8315), .Q (\u4_mem[1]_61 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8311), .Q (\u4_mem[1]_90 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8310), .Q (\u4_mem[1]_62 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8309), .Q (\u4_mem[1]_63 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8306), .Q (\u4_mem[1]_65 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8305), .Q (\u4_mem[1]_66 ), .QN ()); + DFFSRX1 \u4_mem_reg[1][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8304), .Q (\u4_mem[1]_67 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8302), .Q (\u4_mem[2] ), .QN ()); + DFFSRX1 \u4_mem_reg[2][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8301), .Q (\u4_mem[2]_38 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8300), .Q (\u4_mem[2]_39 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8297), .Q (\u4_mem[2]_41 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8296), .Q (\u4_mem[2]_42 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8295), .Q (\u4_mem[2]_43 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8293), .Q (\u4_mem[2]_45 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8291), .Q (\u4_mem[2]_46 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8290), .Q (\u4_mem[2]_47 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8289), .Q (\u4_mem[2]_29 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8287), .Q (\u4_mem[2]_48 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8286), .Q (\u4_mem[2]_49 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8285), .Q (\u4_mem[2]_50 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8283), .Q (\u4_mem[2]_52 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8282), .Q (\u4_mem[2]_53 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8281), .Q (\u4_mem[2]_54 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8278), .Q (\u4_mem[2]_56 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8277), .Q (\u4_mem[2]_57 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8275), .Q (\u4_mem[2]_30 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8273), .Q (\u4_mem[2]_59 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8272), .Q (\u4_mem[2]_31 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8271), .Q (\u4_mem[2]_32 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8269), .Q (\u4_mem[2]_34 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8268), .Q (\u4_mem[2]_35 ), .QN ()); + DFFSRX1 \u4_mem_reg[2][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8267), .Q (\u4_mem[2]_36 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8265), .Q (\u4_mem[3] ), .QN ()); + DFFSRX1 \u4_mem_reg[3][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8264), .Q (\u4_mem[3]_131 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8262), .Q (\u4_mem[3]_132 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8260), .Q (\u4_mem[3]_134 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8259), .Q (\u4_mem[3]_135 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9351), .Q (\u4_mem[3]_136 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9348), .Q (\u4_mem[3]_138 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9347), .Q (\u4_mem[3]_139 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9345), .Q (\u4_mem[3]_140 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9344), .Q (\u4_mem[3]_122 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9343), .Q (\u4_mem[3]_141 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9342), .Q (\u4_mem[3]_142 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9340), .Q (\u4_mem[3]_143 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9338), .Q (\u4_mem[3]_145 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9337), .Q (\u4_mem[3]_146 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9335), .Q (\u4_mem[3]_147 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9332), .Q (\u4_mem[3]_149 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9331), .Q (\u4_mem[3]_150 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9330), .Q (\u4_mem[3]_123 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9328), .Q (\u4_mem[3]_152 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9327), .Q (\u4_mem[3]_124 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9325), .Q (\u4_mem[3]_125 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9322), .Q (\u4_mem[3]_127 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9321), .Q (\u4_mem[3]_128 ), .QN ()); + DFFSRX1 \u4_mem_reg[3][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9320), .Q (\u4_mem[3]_129 ), .QN ()); + DFFSRX1 \u3_mem_reg[2][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9195), .Q (\u3_mem[2]_48 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9317), .Q (\u5_mem[1] ), .QN ()); + DFFSRX1 \u5_mem_reg[1][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9316), .Q (\u5_mem[1]_69 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9314), .Q (\u5_mem[1]_71 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9313), .Q (\u5_mem[1]_72 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9312), .Q (\u5_mem[1]_73 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9060), .Q (\u7_mem[1]_73 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9308), .Q (\u5_mem[1]_75 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9306), .Q (\u5_mem[1]_76 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9304), .Q (\u5_mem[1]_77 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9301), .Q (\u5_mem[1]_60 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9300), .Q (\u5_mem[1]_79 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9299), .Q (\u5_mem[1]_80 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9297), .Q (\u5_mem[1]_82 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9296), .Q (\u5_mem[1]_83 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9294), .Q (\u5_mem[1]_84 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9292), .Q (\u5_mem[1]_86 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9291), .Q (\u5_mem[1]_87 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9289), .Q (\u5_mem[1]_88 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9285), .Q (\u5_mem[1]_89 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9283), .Q (\u5_mem[1]_90 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9282), .Q (\u5_mem[1]_62 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9280), .Q (\u5_mem[1]_64 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9278), .Q (\u5_mem[1]_65 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9277), .Q (\u5_mem[1]_66 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9275), .Q (\u5_mem[1]_68 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9274), .Q (\u5_mem[2] ), .QN ()); + DFFSRX1 \u5_mem_reg[2][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9273), .Q (\u5_mem[2]_38 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9270), .Q (\u5_mem[2]_40 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9269), .Q (\u5_mem[2]_41 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9268), .Q (\u5_mem[2]_42 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9266), .Q (\u5_mem[2]_44 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9265), .Q (\u5_mem[2]_45 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9263), .Q (\u5_mem[2]_46 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9261), .Q (\u5_mem[2]_29 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9259), .Q (\u5_mem[2]_48 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9258), .Q (\u5_mem[2]_49 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9256), .Q (\u5_mem[2]_51 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9255), .Q (\u5_mem[2]_52 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9254), .Q (\u5_mem[2]_53 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9252), .Q (\u5_mem[2]_55 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9250), .Q (\u5_mem[2]_56 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9249), .Q (\u5_mem[2]_57 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9246), .Q (\u5_mem[2]_58 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9245), .Q (\u5_mem[2]_59 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9244), .Q (\u5_mem[2]_31 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9243), .Q (\u5_mem[2]_32 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9242), .Q (\u5_mem[2]_33 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9241), .Q (\u5_mem[2]_34 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9240), .Q (\u5_mem[2]_35 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9238), .Q (\u5_mem[2]_37 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9237), .Q (\u5_mem[3] ), .QN ()); + DFFSRX1 \u5_mem_reg[3][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9236), .Q (\u5_mem[3]_131 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9233), .Q (\u5_mem[3]_133 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9232), .Q (\u5_mem[3]_134 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9231), .Q (\u5_mem[3]_135 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9228), .Q (\u5_mem[3]_137 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9227), .Q (\u5_mem[3]_138 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9226), .Q (\u5_mem[3]_139 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9223), .Q (\u5_mem[3]_122 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9222), .Q (\u5_mem[3]_141 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9221), .Q (\u5_mem[3]_142 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8775), .Q (\u6_mem[0]_107 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9218), .Q (\u5_mem[3]_144 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9217), .Q (\u5_mem[3]_145 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9216), .Q (\u5_mem[3]_146 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9213), .Q (\u5_mem[3]_148 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9211), .Q (\u5_mem[3]_149 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9210), .Q (\u5_mem[3]_150 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9208), .Q (\u5_mem[3]_151 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9207), .Q (\u5_mem[3]_152 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9206), .Q (\u5_mem[3]_124 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9203), .Q (\u5_mem[3]_126 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9201), .Q (\u5_mem[3]_127 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9200), .Q (\u5_mem[3]_128 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9198), .Q (\u5_mem[3]_130 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9192), .Q (\u6_mem[1] ), .QN ()); + DFFSRX1 \u6_mem_reg[1][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9191), .Q (\u6_mem[1]_69 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9189), .Q (\u6_mem[1]_71 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9188), .Q (\u6_mem[1]_72 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9187), .Q (\u6_mem[1]_73 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9183), .Q (\u6_mem[1]_75 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9181), .Q (\u6_mem[1]_76 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9179), .Q (\u6_mem[1]_77 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9177), .Q (\u6_mem[1]_78 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9176), .Q (\u6_mem[1]_60 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9175), .Q (\u6_mem[1]_79 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9174), .Q (\u6_mem[1]_80 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9172), .Q (\u6_mem[1]_82 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9171), .Q (\u6_mem[1]_83 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9169), .Q (\u6_mem[1]_84 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9167), .Q (\u6_mem[1]_86 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9166), .Q (\u6_mem[1]_87 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9164), .Q (\u6_mem[1]_88 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9160), .Q (\u6_mem[1]_89 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9158), .Q (\u6_mem[1]_90 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9157), .Q (\u6_mem[1]_62 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9155), .Q (\u6_mem[1]_64 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9153), .Q (\u6_mem[1]_65 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9152), .Q (\u6_mem[1]_66 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9150), .Q (\u6_mem[1]_68 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9149), .Q (\u6_mem[2] ), .QN ()); + DFFSRX1 \u6_mem_reg[2][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9148), .Q (\u6_mem[2]_38 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9145), .Q (\u6_mem[2]_40 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9144), .Q (\u6_mem[2]_41 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9143), .Q (\u6_mem[2]_42 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9141), .Q (\u6_mem[2]_44 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9140), .Q (\u6_mem[2]_45 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9138), .Q (\u6_mem[2]_46 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9136), .Q (\u6_mem[2]_29 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9134), .Q (\u6_mem[2]_48 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9133), .Q (\u6_mem[2]_49 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9131), .Q (\u6_mem[2]_51 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9130), .Q (\u6_mem[2]_52 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9129), .Q (\u6_mem[2]_53 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9127), .Q (\u6_mem[2]_55 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9125), .Q (\u6_mem[2]_56 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9124), .Q (\u6_mem[2]_57 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9121), .Q (\u6_mem[2]_58 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9120), .Q (\u6_mem[2]_59 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9119), .Q (\u6_mem[2]_31 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9117), .Q (\u6_mem[2]_33 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9116), .Q (\u6_mem[2]_34 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9115), .Q (\u6_mem[2]_35 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9113), .Q (\u6_mem[2]_37 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9112), .Q (\u6_mem[3] ), .QN ()); + DFFSRX1 \u6_mem_reg[3][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9111), .Q (\u6_mem[3]_131 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9108), .Q (\u6_mem[3]_133 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9107), .Q (\u6_mem[3]_134 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9106), .Q (\u6_mem[3]_135 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9103), .Q (\u6_mem[3]_137 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9102), .Q (\u6_mem[3]_138 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9101), .Q (\u6_mem[3]_139 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9098), .Q (\u6_mem[3]_122 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9097), .Q (\u6_mem[3]_141 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9096), .Q (\u6_mem[3]_142 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9093), .Q (\u6_mem[3]_144 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9092), .Q (\u6_mem[3]_145 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9091), .Q (\u6_mem[3]_146 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9088), .Q (\u6_mem[3]_148 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9086), .Q (\u6_mem[3]_149 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9085), .Q (\u6_mem[3]_150 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9083), .Q (\u6_mem[3]_151 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9082), .Q (\u6_mem[3]_152 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9081), .Q (\u6_mem[3]_124 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9078), .Q (\u6_mem[3]_126 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9076), .Q (\u6_mem[3]_127 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9075), .Q (\u6_mem[3]_128 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9073), .Q (\u6_mem[3]_130 ), .QN ()); + DFFSRX1 \u3_mem_reg[3][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8353), .Q (\u3_mem[3]_129 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9066), .Q (\u7_mem[1] ), .QN ()); + DFFSRX1 \u7_mem_reg[1][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9064), .Q (\u7_mem[1]_70 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9062), .Q (\u7_mem[1]_71 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9061), .Q (\u7_mem[1]_72 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9058), .Q (\u7_mem[1]_74 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9056), .Q (\u7_mem[1]_75 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9054), .Q (\u7_mem[1]_76 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9052), .Q (\u7_mem[1]_77 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9050), .Q (\u7_mem[1]_78 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9049), .Q (\u7_mem[1]_60 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9048), .Q (\u7_mem[1]_79 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9046), .Q (\u7_mem[1]_81 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9045), .Q (\u7_mem[1]_82 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9044), .Q (\u7_mem[1]_83 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9041), .Q (\u7_mem[1]_85 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9040), .Q (\u7_mem[1]_86 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9039), .Q (\u7_mem[1]_87 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9035), .Q (\u7_mem[1]_61 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9033), .Q (\u7_mem[1]_89 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9031), .Q (\u7_mem[1]_90 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9029), .Q (\u7_mem[1]_63 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9028), .Q (\u7_mem[1]_64 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9026), .Q (\u7_mem[1]_65 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9024), .Q (\u7_mem[1]_67 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9021), .Q (\u7_mem[1]_68 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9020), .Q (\u7_mem[2] ), .QN ()); + DFFSRX1 \u7_mem_reg[2][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9018), .Q (\u7_mem[2]_39 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9016), .Q (\u7_mem[2]_40 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9015), .Q (\u7_mem[2]_41 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9013), .Q (\u7_mem[2]_43 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9012), .Q (\u7_mem[2]_44 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9011), .Q (\u7_mem[2]_45 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9008), .Q (\u7_mem[2]_47 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9007), .Q (\u7_mem[2]_29 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9005), .Q (\u7_mem[2]_48 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9003), .Q (\u7_mem[2]_50 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9002), .Q (\u7_mem[2]_51 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9001), .Q (\u7_mem[2]_52 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8999), .Q (\u7_mem[2]_54 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8998), .Q (\u7_mem[2]_55 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8996), .Q (\u7_mem[2]_56 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8993), .Q (\u7_mem[2]_30 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8992), .Q (\u7_mem[2]_58 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8991), .Q (\u7_mem[2]_59 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8989), .Q (\u7_mem[2]_32 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8988), .Q (\u7_mem[2]_33 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8987), .Q (\u7_mem[2]_34 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8985), .Q (\u7_mem[2]_36 ), .QN ()); + DFFSRX1 \u7_mem_reg[2][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8984), .Q (\u7_mem[2]_37 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8983), .Q (\u7_mem[3] ), .QN ()); + DFFSRX1 \u7_mem_reg[3][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8980), .Q (\u7_mem[3]_132 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8979), .Q (\u7_mem[3]_133 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8978), .Q (\u7_mem[3]_134 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8975), .Q (\u7_mem[3]_136 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8974), .Q (\u7_mem[3]_137 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8973), .Q (\u7_mem[3]_138 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8970), .Q (\u7_mem[3]_140 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8969), .Q (\u7_mem[3]_122 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8968), .Q (\u7_mem[3]_141 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8770), .Q (\u6_mem[0]_110 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8965), .Q (\u7_mem[3]_143 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8964), .Q (\u7_mem[3]_144 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8963), .Q (\u7_mem[3]_145 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8960), .Q (\u7_mem[3]_147 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8959), .Q (\u7_mem[3]_148 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8957), .Q (\u7_mem[3]_149 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8955), .Q (\u7_mem[3]_123 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8954), .Q (\u7_mem[3]_151 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8953), .Q (\u7_mem[3]_152 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8950), .Q (\u7_mem[3]_125 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8949), .Q (\u7_mem[3]_126 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8947), .Q (\u7_mem[3]_127 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8945), .Q (\u7_mem[3]_129 ), .QN ()); + DFFSRX1 \u7_mem_reg[3][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8944), .Q (\u7_mem[3]_130 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8941), .Q (\u8_mem[1] ), .QN ()); + DFFSRX1 \u8_mem_reg[1][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8939), .Q (\u8_mem[1]_70 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8938), .Q (\u8_mem[1]_71 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8936), .Q (\u8_mem[1]_72 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8934), .Q (\u8_mem[1]_74 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8932), .Q (\u8_mem[1]_75 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8931), .Q (\u8_mem[1]_76 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8928), .Q (\u8_mem[1]_78 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8926), .Q (\u8_mem[1]_60 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8925), .Q (\u8_mem[1]_79 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8922), .Q (\u8_mem[1]_81 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8921), .Q (\u8_mem[1]_82 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8920), .Q (\u8_mem[1]_83 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8916), .Q (\u8_mem[1]_85 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8917), .Q (\u3_mem[1] ), .QN ()); + DFFSRX1 \u8_mem_reg[1][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8914), .Q (\u8_mem[1]_86 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8912), .Q (\u3_mem[1]_69 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8910), .Q (\u8_mem[1]_88 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8907), .Q (\u8_mem[1]_61 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8906), .Q (\u8_mem[1]_89 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8351), .Q (\u8_mem[1]_90 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8905), .Q (\u3_mem[1]_71 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8413), .Q (\u8_mem[1]_63 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8901), .Q (\u3_mem[1]_72 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8900), .Q (\u8_mem[1]_64 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9067), .Q (\u3_mem[1]_73 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8899), .Q (\u8_mem[1]_66 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8896), .Q (\u8_mem[1]_67 ), .QN ()); + DFFSRX1 \u8_mem_reg[1][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8895), .Q (\u8_mem[1]_68 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8892), .Q (\u8_mem[2] ), .QN ()); + DFFSRX1 \u3_mem_reg[1][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8893), .Q (\u3_mem[1]_75 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8890), .Q (\u8_mem[2]_38 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8886), .Q (\u8_mem[2]_39 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8888), .Q (\u3_mem[1]_76 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8885), .Q (\u8_mem[2]_40 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8883), .Q (\u3_mem[1]_77 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8881), .Q (\u8_mem[2]_42 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8879), .Q (\u8_mem[2]_43 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8878), .Q (\u8_mem[2]_44 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8876), .Q (\u8_mem[2]_45 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8356), .Q (\u3_mem[1]_60 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8872), .Q (\u8_mem[2]_47 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8874), .Q (\u3_mem[1]_79 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8871), .Q (\u8_mem[2]_29 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8870), .Q (\u3_mem[1]_80 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8867), .Q (\u8_mem[2]_49 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8865), .Q (\u8_mem[2]_50 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8864), .Q (\u8_mem[2]_51 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8862), .Q (\u8_mem[2]_52 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9063), .Q (\u3_mem[1]_82 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8859), .Q (\u8_mem[2]_54 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8860), .Q (\u3_mem[1]_83 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8858), .Q (\u8_mem[2]_55 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8857), .Q (\u3_mem[1]_84 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8854), .Q (\u8_mem[2]_57 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8851), .Q (\u8_mem[2]_30 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8850), .Q (\u8_mem[2]_58 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8849), .Q (\u8_mem[2]_59 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8347), .Q (\u3_mem[1]_86 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8837), .Q (\u4_mem[0] ), .QN ()); + DFFSRX1 \u4_mem_reg[0][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8838), .Q (\u4_mem[0]_100 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8836), .Q (\u4_mem[0]_101 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8833), .Q (\u4_mem[0]_105 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8830), .Q (\u4_mem[0]_108 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8829), .Q (\u4_mem[0]_91 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8825), .Q (\u4_mem[0]_111 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8823), .Q (\u4_mem[0]_115 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8821), .Q (\u4_mem[0]_117 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8820), .Q (\u4_mem[0]_118 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8822), .Q (\u4_mem[0]_116 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8817), .Q (\u4_mem[0]_92 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8818), .Q (\u4_mem[0]_119 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8815), .Q (\u4_mem[0]_93 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8813), .Q (\u4_mem[0]_95 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8811), .Q (\u4_mem[0]_98 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8808), .Q (\u5_mem[0]_100 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8807), .Q (\u5_mem[0]_101 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8804), .Q (\u5_mem[0]_105 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8801), .Q (\u5_mem[0]_108 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8800), .Q (\u5_mem[0]_91 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8796), .Q (\u5_mem[0]_111 ), .QN ()); + DFFSRX1 \u13_intm_r_reg[8] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8488), .Q (\u13_intm_r[8] ), .QN ()); + DFFSRX1 \u5_mem_reg[0][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8793), .Q (\u5_mem[0]_116 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8792), .Q (\u5_mem[0]_117 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8794), .Q (\u5_mem[0]_115 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8788), .Q (\u5_mem[0]_92 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8789), .Q (\u5_mem[0]_119 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8786), .Q (\u5_mem[0]_93 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8784), .Q (\u5_mem[0]_95 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8782), .Q (\u5_mem[0]_98 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8780), .Q (\u6_mem[0]_100 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8779), .Q (\u6_mem[0]_101 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8776), .Q (\u6_mem[0]_105 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9047), .Q (\u7_mem[1]_80 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8773), .Q (\u6_mem[0]_108 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8772), .Q (\u6_mem[0]_91 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8768), .Q (\u6_mem[0]_111 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8765), .Q (\u6_mem[0]_116 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8764), .Q (\u6_mem[0]_117 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8766), .Q (\u6_mem[0]_115 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8760), .Q (\u6_mem[0]_92 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8761), .Q (\u6_mem[0]_119 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8758), .Q (\u6_mem[0]_93 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8756), .Q (\u6_mem[0]_95 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8754), .Q (\u6_mem[0]_98 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8752), .Q (\u7_mem[0]_100 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8751), .Q (\u7_mem[0]_101 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8748), .Q (\u7_mem[0]_105 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8745), .Q (\u7_mem[0]_108 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8744), .Q (\u7_mem[0]_91 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8740), .Q (\u7_mem[0]_111 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8738), .Q (\u7_mem[0]_115 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8736), .Q (\u7_mem[0]_117 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8735), .Q (\u7_mem[0]_118 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8737), .Q (\u7_mem[0]_116 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8732), .Q (\u7_mem[0]_92 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][29] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8733), .Q (\u7_mem[0]_119 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8730), .Q (\u7_mem[0]_93 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][5] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8728), .Q (\u7_mem[0]_95 ), .QN ()); + DFFSRX1 \u7_mem_reg[0][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8726), .Q (\u7_mem[0]_98 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8725), .Q (\u3_mem[0]_100 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8721), .Q (\u8_mem[0]_100 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][13] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8718), .Q (\u8_mem[0]_103 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8719), .Q (\u3_mem[0]_108 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8717), .Q (\u8_mem[0]_104 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8839), .Q (\u3_mem[0]_109 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][18] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8713), .Q (\u8_mem[0]_108 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8709), .Q (\u8_mem[0]_109 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8711), .Q (\u3_mem[0]_110 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8707), .Q (\u8_mem[0]_110 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][21] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8705), .Q (\u8_mem[0]_111 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8842), .Q (\u3_mem[0]_112 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8703), .Q (\u8_mem[0]_113 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8699), .Q (\u8_mem[0]_114 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8698), .Q (\u8_mem[0]_115 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][24] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8696), .Q (\u3_mem[0]_114 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][25] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8694), .Q (\u3_mem[0]_115 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8810), .Q (\u3_mem[0]_116 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8841), .Q (\u3_mem[0]_118 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8688), .Q (\u8_mem[0]_97 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8687), .Q (\u8_mem[0]_98 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8689), .Q (\u8_mem[0]_96 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8686), .Q (\u8_mem[0]_99 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8685), .Q (\u3_mem[0]_120 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8684), .Q (\u3_mem[0]_93 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8681), .Q (\u3_mem[0]_98 ), .QN ()); + DFFSRX1 \u7_mem_reg[1][10] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9065), .Q (\u7_mem[1]_69 ), .QN ()); + DFFX1 \u13_crac_dout_r_reg[7] (.CK (clk_i), .D (n_8638), .Q (), .QN + (crac_out_852)); + DFFSRX1 \u6_mem_reg[2][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9132), .Q (\u6_mem[2]_50 ), .QN ()); + DFFSRX1 \u6_mem_reg[0][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8781), .Q (\u6_mem[0] ), .QN ()); + DFFSRX1 \u6_mem_reg[3][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9079), .Q (\u6_mem[3]_125 ), .QN ()); + DFFSRX1 \u13_intm_r_reg[26] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8500), .Q (\u13_intm_r[26] ), .QN ()); + DFFSRX1 \u6_mem_reg[3][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9084), .Q (\u6_mem[3]_123 ), .QN ()); + DFFSRX1 \u13_occ0_r_reg[22] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8549), .Q (oc2_cfg_989), .QN ()); + DFFSRX1 \u6_mem_reg[3][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9089), .Q (\u6_mem[3]_147 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9094), .Q (\u6_mem[3]_143 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9104), .Q (\u6_mem[3]_136 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8783), .Q (\u5_mem[0]_96 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9099), .Q (\u6_mem[3]_140 ), .QN ()); + DFFX1 \u1_sr_reg[10] (.CK (bit_clk_pad_i), .D (u1_sr_125), .Q + (u1_sr_126), .QN ()); + NOR2X1 g32613(.A (n_8481), .B (n_11030), .Y (n_9469)); + NOR2X1 g32614(.A (n_8479), .B (n_10940), .Y (n_9468)); + NOR2X1 g32615(.A (n_8478), .B (n_10994), .Y (n_9467)); + NOR2X1 g32616(.A (n_8480), .B (n_5839), .Y (n_9466)); + NOR2X1 g32617(.A (n_8477), .B (n_11086), .Y (n_9465)); + NOR2X1 g32618(.A (n_8476), .B (n_5825), .Y (n_9464)); + DFFSRX1 \u5_mem_reg[0][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8787), .Q (\u5_mem[0]_120 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8795), .Q (\u5_mem[0]_113 ), .QN ()); + DFFSRX1 \u13_crac_r_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8634), .Q (crac_out_863), .QN ()); + DFFSRX1 \u6_mem_reg[2][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9118), .Q (\u6_mem[2]_32 ), .QN ()); + DFFSRX1 \u6_mem_reg[3][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9109), .Q (\u6_mem[3]_132 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9114), .Q (\u6_mem[2]_36 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9122), .Q (\u6_mem[2]_30 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][9] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8680), .Q (\u3_mem[0]_99 ), .QN ()); + DFFSRX1 \u13_occ0_r_reg[26] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8543), .Q (oc3_cfg_995), .QN ()); + DFFSRX1 \u5_mem_reg[0][28] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8791), .Q (\u5_mem[0]_118 ), .QN ()); + DFFSRX1 \u13_intm_r_reg[3] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8493), .Q (\u13_intm_r[3] ), .QN ()); + DFFSRX1 \u6_mem_reg[2][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9128), .Q (\u6_mem[2]_54 ), .QN ()); + OR2X1 g32763(.A (n_8484), .B (n_9352), .Y (n_9463)); + OR2X1 g32764(.A (n_8483), .B (n_8679), .Y (n_9462)); + OR2X1 g32765(.A (n_8482), .B (n_9359), .Y (n_9461)); + DFFSRX1 \u3_mem_reg[0][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8682), .Q (\u3_mem[0]_94 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8798), .Q (\u5_mem[0]_110 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8692), .Q (\u8_mem[0]_121 ), .QN ()); + DFFSRX1 \u6_mem_reg[2][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9142), .Q (\u6_mem[2]_43 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9185), .Q (\u6_mem[1]_74 ), .QN ()); + NAND2X1 g32979(.A (n_8183), .B (n_8678), .Y (n_9460)); + NAND2X1 g32980(.A (n_8179), .B (n_8677), .Y (n_9459)); + DFFSRX1 \u6_mem_reg[2][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9137), .Q (\u6_mem[2]_47 ), .QN ()); + NAND2X1 g32981(.A (n_8178), .B (n_8676), .Y (n_9458)); + NAND2X1 g32982(.A (n_8181), .B (n_8675), .Y (n_9457)); + NAND2X1 g32983(.A (n_8177), .B (n_8674), .Y (n_9456)); + NAND2X1 g32987(.A (n_8175), .B (n_8673), .Y (n_9455)); + AOI21X1 g32990(.A0 (i4_dout_595), .A1 (n_7468), .B0 (n_8485), .Y + (n_9454)); + DFFSRX1 \u6_mem_reg[2][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9147), .Q (\u6_mem[2]_39 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8803), .Q (\u5_mem[0]_107 ), .QN ()); + DFFSRX1 \u13_occ0_r_reg[19] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8556), .Q (oc2_cfg_986), .QN ()); + DFFSRX1 \u5_mem_reg[0][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8806), .Q (\u5_mem[0]_102 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9168), .Q (\u6_mem[1]_85 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][6] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8812), .Q (\u4_mem[0]_96 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9156), .Q (\u6_mem[1]_63 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9151), .Q (\u6_mem[1]_67 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9162), .Q (\u6_mem[1]_61 ), .QN ()); + DFFSRX1 \u5_mem_reg[0][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8809), .Q (\u5_mem[0] ), .QN ()); + DFFSRX1 \u6_mem_reg[1][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9173), .Q (\u6_mem[1]_81 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8691), .Q (\u8_mem[0]_93 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][30] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8816), .Q (\u4_mem[0]_120 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][16] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8714), .Q (\u8_mem[0]_106 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9199), .Q (\u5_mem[3]_129 ), .QN ()); + DFFSRX1 \u6_mem_reg[1][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9190), .Q (\u6_mem[1]_70 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9204), .Q (\u5_mem[3]_125 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8693), .Q (\u8_mem[0]_92 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9239), .Q (\u5_mem[2]_36 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8824), .Q (\u4_mem[0]_113 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][23] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8701), .Q (\u3_mem[0]_113 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][17] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8832), .Q (\u4_mem[0]_107 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9224), .Q (\u5_mem[3]_140 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9214), .Q (\u5_mem[3]_147 ), .QN ()); + DFFSRX1 \u5_mem_reg[3][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9209), .Q (\u5_mem[3]_123 ), .QN ()); + NAND4X1 g33298(.A (n_5620), .B (n_1833), .C (n_8700), .D (n_822), .Y + (n_9453)); + DFFSRX1 \u5_mem_reg[3][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9219), .Q (\u5_mem[3]_143 ), .QN ()); + NAND4X1 g33311(.A (n_6049), .B (n_2646), .C (n_7499), .D (n_1001), .Y + (n_9452)); + NAND4X1 g33322(.A (n_6047), .B (n_2645), .C (n_7496), .D (n_968), .Y + (n_9451)); + DFFSRX1 \u5_mem_reg[3][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9229), .Q (\u5_mem[3]_136 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][27] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8695), .Q (\u8_mem[0]_117 ), .QN ()); + NAND4X1 g33336(.A (n_5618), .B (n_1806), .C (n_7505), .D (n_1256), .Y + (n_9450)); + NAND4X1 g33349(.A (n_5616), .B (n_1926), .C (n_7493), .D (n_1444), .Y + (n_9449)); + NAND4X1 g33363(.A (n_5622), .B (n_1929), .C (n_7490), .D (n_1447), .Y + (n_9448)); + DFFSRX1 \u4_mem_reg[0][20] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8827), .Q (\u4_mem[0]_110 ), .QN ()); + INVX2 g33369(.A (n_9447), .Y (n_9514)); + NOR2X1 g33381(.A (n_7536), .B (u14_u7_en_out_l2), .Y (n_9513)); + DFFSRX1 \u5_mem_reg[3][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9234), .Q (\u5_mem[3]_132 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9247), .Q (\u5_mem[2]_30 ), .QN ()); + DFFSRX1 \u4_mem_reg[0][12] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8835), .Q (\u4_mem[0]_102 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9253), .Q (\u5_mem[2]_54 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8704), .Q (\u8_mem[0]_112 ), .QN ()); + DFFSRX1 \u13_occ0_r_reg[15] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8563), .Q (oc1_cfg_980), .QN ()); + DFFSRX1 \u5_mem_reg[1][2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9287), .Q (\u5_mem[1]_61 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][11] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9272), .Q (\u5_mem[2]_39 ), .QN ()); + DFFSRX1 \u3_mem_reg[1][26] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8852), .Q (\u3_mem[1]_85 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][19] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9262), .Q (\u5_mem[2]_47 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][22] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9257), .Q (\u5_mem[2]_50 ), .QN ()); + DFFSRX1 \u5_mem_reg[2][15] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9267), .Q (\u5_mem[2]_43 ), .QN ()); + DFFSRX1 \u8_mem_reg[2][3] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8349), .Q (\u8_mem[2]_31 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][8] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9276), .Q (\u5_mem[1]_67 ), .QN ()); + DFFSRX1 \u5_mem_reg[1][4] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_9281), .Q (\u5_mem[1]_63 ), .QN ()); + DFFSRX1 \u8_mem_reg[0][1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8708), .Q (\u8_mem[0]_91 ), .QN ()); + DFFSRX1 \u13_occ1_r_reg[11] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8201), .Q (oc5_cfg_1016), .QN ()); + AOI22X1 g31740(.A0 (n_7520), .A1 (n_8207), .B0 (n_565), .B1 (n_7434), + .Y (n_9446)); + AOI21X1 g31779(.A0 (n_9444), .A1 (n_8208), .B0 (n_8206), .Y (n_9445)); + MX2X1 g33980(.A (\u3_mem[0]_101 ), .B (n_3811), .S0 (n_8700), .Y + (n_9443)); + MX2X1 g33985(.A (\u4_mem[0]_103 ), .B (n_3797), .S0 (n_7499), .Y + (n_9442)); + MX2X1 g33986(.A (\u4_mem[0]_104 ), .B (n_3796), .S0 (n_7499), .Y + (n_9441)); + MX2X1 g33988(.A (\u4_mem[0]_106 ), .B (n_3791), .S0 (n_7499), .Y + (n_9440)); + MX2X1 g33991(.A (\u4_mem[0]_109 ), .B (n_3783), .S0 (n_7499), .Y + (n_9439)); + MX2X1 g33995(.A (\u4_mem[0]_112 ), .B (n_3776), .S0 (n_7499), .Y + (n_9437)); + MX2X1 g33997(.A (\u4_mem[0]_114 ), .B (n_3770), .S0 (n_7499), .Y + (n_9435)); + DFFSRX1 \u3_mem_reg[0][0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8253), .Q (\u3_mem[0] ), .QN ()); + MX2X1 g34005(.A (\u4_mem[0]_121 ), .B (n_3759), .S0 (n_7499), .Y + (n_9434)); + MX2X1 g34007(.A (\u4_mem[0]_94 ), .B (n_3756), .S0 (n_7499), .Y + (n_9433)); + MX2X1 g34010(.A (\u4_mem[0]_97 ), .B (n_3754), .S0 (n_7499), .Y + (n_9432)); + MX2X1 g34012(.A (\u4_mem[0]_99 ), .B (n_3752), .S0 (n_7499), .Y + (n_9430)); + MX2X1 g34018(.A (\u5_mem[0]_103 ), .B (n_3624), .S0 (n_7496), .Y + (n_9429)); + MX2X1 g34019(.A (\u5_mem[0]_104 ), .B (n_3734), .S0 (n_7496), .Y + (n_9428)); + MX2X1 g34021(.A (\u5_mem[0]_106 ), .B (n_3731), .S0 (n_7496), .Y + (n_9427)); + MX2X1 g34024(.A (\u5_mem[0]_109 ), .B (n_3725), .S0 (n_7496), .Y + (n_9426)); + MX2X1 g34028(.A (\u5_mem[0]_112 ), .B (n_3717), .S0 (n_7496), .Y + (n_9424)); + MX2X1 g34030(.A (\u5_mem[0]_114 ), .B (n_3714), .S0 (n_7496), .Y + (n_9422)); + MX2X1 g34038(.A (\u5_mem[0]_121 ), .B (n_3698), .S0 (n_7496), .Y + (n_9421)); + MX2X1 g34040(.A (\u5_mem[0]_94 ), .B (n_3696), .S0 (n_7496), .Y + (n_9420)); + MX2X1 g34043(.A (\u5_mem[0]_97 ), .B (n_3694), .S0 (n_7496), .Y + (n_9419)); + MX2X1 g34045(.A (\u5_mem[0]_99 ), .B (n_3692), .S0 (n_7496), .Y + (n_9417)); + MX2X1 g34046(.A (\u3_mem[0]_92 ), .B (n_3820), .S0 (n_8700), .Y + (n_9416)); + MX2X1 g34051(.A (\u6_mem[0]_103 ), .B (n_3679), .S0 (n_7505), .Y + (n_9414)); + MX2X1 g34052(.A (\u6_mem[0]_104 ), .B (n_3567), .S0 (n_7505), .Y + (n_9413)); + MX2X1 g34054(.A (\u6_mem[0]_106 ), .B (n_3675), .S0 (n_7505), .Y + (n_9412)); + MX2X1 g34057(.A (\u6_mem[0]_109 ), .B (n_3573), .S0 (n_7505), .Y + (n_9411)); + MX2X1 g34061(.A (\u6_mem[0]_112 ), .B (n_3611), .S0 (n_7505), .Y + (n_9409)); + MX2X1 g34063(.A (\u6_mem[0]_114 ), .B (n_3614), .S0 (n_7505), .Y + (n_9407)); + MX2X1 g34072(.A (\u6_mem[0]_121 ), .B (n_3666), .S0 (n_7505), .Y + (n_9406)); + MX2X1 g34074(.A (\u6_mem[0]_94 ), .B (n_3648), .S0 (n_7505), .Y + (n_9405)); + MX2X1 g34077(.A (\u6_mem[0]_97 ), .B (n_3663), .S0 (n_7505), .Y + (n_9404)); + MX2X1 g34079(.A (\u6_mem[0]_99 ), .B (n_3658), .S0 (n_7505), .Y + (n_9402)); + MX2X1 g34088(.A (\u7_mem[0]_103 ), .B (n_3647), .S0 (n_7493), .Y + (n_9401)); + MX2X1 g34089(.A (\u7_mem[0]_104 ), .B (n_3684), .S0 (n_7493), .Y + (n_9400)); + MX2X1 g34091(.A (\u7_mem[0]_106 ), .B (n_3792), .S0 (n_7493), .Y + (n_9399)); + MX2X1 g34094(.A (\u7_mem[0]_109 ), .B (n_2635), .S0 (n_7493), .Y + (n_9398)); + MX2X1 g34098(.A (\u7_mem[0]_112 ), .B (n_3641), .S0 (n_7493), .Y + (n_9396)); + MX2X1 g34100(.A (\u7_mem[0]_114 ), .B (n_3639), .S0 (n_7493), .Y + (n_9394)); + MX2X1 g34108(.A (\u7_mem[0]_121 ), .B (n_3635), .S0 (n_7493), .Y + (n_9393)); + MX2X1 g34110(.A (\u7_mem[0]_94 ), .B (n_3619), .S0 (n_7493), .Y + (n_9392)); + MX2X1 g34113(.A (\u7_mem[0]_97 ), .B (n_3623), .S0 (n_7493), .Y + (n_9391)); + MX2X1 g34115(.A (\u7_mem[0]_99 ), .B (n_3626), .S0 (n_7493), .Y + (n_9389)); + MX2X1 g34118(.A (\u3_mem[0]_102 ), .B (n_3812), .S0 (n_8700), .Y + (n_9388)); + MX2X1 g34121(.A (\u3_mem[0]_105 ), .B (n_3804), .S0 (n_8700), .Y + (n_9387)); + MX2X1 g34123(.A (\u8_mem[0] ), .B (n_3604), .S0 (n_7490), .Y + (n_9386)); + MX2X1 g34126(.A (\u8_mem[0]_101 ), .B (n_3814), .S0 (n_7490), .Y + (n_9385)); + MX2X1 g34127(.A (\u8_mem[0]_102 ), .B (n_3817), .S0 (n_7490), .Y + (n_9383)); + MX2X1 g34133(.A (\u3_mem[0]_91 ), .B (n_3598), .S0 (n_8700), .Y + (n_9382)); + MX2X1 g34134(.A (\u8_mem[0]_107 ), .B (n_3825), .S0 (n_7490), .Y + (n_9381)); + MX2X1 g34139(.A (\u3_mem[0]_111 ), .B (n_3593), .S0 (n_8700), .Y + (n_9380)); + MX2X1 g34148(.A (\u8_mem[0]_116 ), .B (n_3589), .S0 (n_7490), .Y + (n_9379)); + MX2X1 g34151(.A (\u8_mem[0]_118 ), .B (n_3686), .S0 (n_7490), .Y + (n_9378)); + MX2X1 g34152(.A (\u8_mem[0]_119 ), .B (n_3587), .S0 (n_7490), .Y + (n_9376)); + MX2X1 g34154(.A (\u8_mem[0]_120 ), .B (n_3748), .S0 (n_7490), .Y + (n_9375)); + MX2X1 g34155(.A (\u3_mem[0]_117 ), .B (n_3585), .S0 (n_8700), .Y + (n_9373)); + MX2X1 g34158(.A (\u8_mem[0]_94 ), .B (n_3837), .S0 (n_7490), .Y + (n_9371)); + MX2X1 g34159(.A (\u8_mem[0]_95 ), .B (n_3583), .S0 (n_7490), .Y + (n_9370)); + MX2X1 g34160(.A (\u3_mem[0]_119 ), .B (n_3582), .S0 (n_8700), .Y + (n_9369)); + MX2X1 g34169(.A (\u3_mem[0]_95 ), .B (n_3771), .S0 (n_8700), .Y + (n_9368)); + MX2X1 g34170(.A (\u3_mem[0]_96 ), .B (n_3574), .S0 (n_8700), .Y + (n_9366)); + AOI21X1 g34174(.A0 (\u8_wp[0] ), .A1 (n_7976), .B0 (n_8248), .Y + (n_9365)); + AOI21X1 g34175(.A0 (n_1419), .A1 (n_7984), .B0 (n_8227), .Y (n_9364)); + AOI21X1 g34176(.A0 (n_798), .A1 (n_7870), .B0 (n_8224), .Y (n_9363)); + AOI21X1 g34177(.A0 (n_1424), .A1 (n_8141), .B0 (n_8241), .Y (n_9362)); + AOI21X1 g34178(.A0 (n_1417), .A1 (n_7758), .B0 (n_8221), .Y (n_9361)); + AOI21X1 g34179(.A0 (n_1421), .A1 (n_7651), .B0 (n_8218), .Y (n_9360)); + DFFX1 u14_u8_en_out_l2_reg(.CK (clk_i), .D (n_9359), .Q + (u14_u8_en_out_l2), .QN ()); + DFFX1 \u12_wb_data_o_reg[4] (.CK (clk_i), .D (n_8233), .Q + (wb_data_o[4]), .QN ()); + DFFX1 \u12_wb_data_o_reg[6] (.CK (clk_i), .D (n_8231), .Q + (wb_data_o[6]), .QN ()); + DFFX1 \u12_wb_data_o_reg[10] (.CK (clk_i), .D (n_8244), .Q + (wb_data_o[10]), .QN ()); + DFFSRX1 \u13_occ1_r_reg[8] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8185), .Q (oc5_cfg), .QN ()); + DFFSRX1 \u13_occ1_r_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8204), .Q (oc4_cfg), .QN ()); + DFFSRX1 \u13_occ1_r_reg[10] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8203), .Q (oc5_cfg_1015), .QN ()); + DFFSRX1 \u13_occ1_r_reg[12] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8200), .Q (n_8199), .QN ()); + DFFSRX1 \u13_occ1_r_reg[13] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8198), .Q (n_8197), .QN ()); + DFFSRX1 \u13_occ1_r_reg[14] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8196), .Q (oc5_cfg_1019), .QN ()); + DFFSRX1 \u13_occ1_r_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8194), .Q (oc4_cfg_1004), .QN ()); + DFFSRX1 \u13_occ1_r_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8193), .Q (oc4_cfg_1005), .QN ()); + DFFSRX1 \u13_occ1_r_reg[3] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8192), .Q (oc4_cfg_1006), .QN ()); + DFFSRX1 \u13_occ1_r_reg[5] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8189), .Q (n_8188), .QN ()); + DFFSRX1 \u13_occ1_r_reg[6] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8187), .Q (oc4_cfg_1009), .QN ()); + DFFSRX1 \u13_occ1_r_reg[7] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8186), .Q (oc4_cfg_1010), .QN ()); + DFFX1 \u1_slt1_reg[7] (.CK (bit_clk_pad_i), .D (n_8258), .Q + (in_slt_749), .QN ()); + DFFX1 \u1_slt2_reg[7] (.CK (bit_clk_pad_i), .D (n_8257), .Q + (in_slt_833), .QN ()); + DFFX1 \u1_slt4_reg[7] (.CK (bit_clk_pad_i), .D (n_8255), .Q + (in_slt_425), .QN ()); + DFFX1 \u1_slt3_reg[7] (.CK (bit_clk_pad_i), .D (n_8256), .Q + (in_slt_403), .QN ()); + DFFSRX1 \u3_mem_reg[0][14] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8252), .Q (\u3_mem[0]_104 ), .QN ()); + DFFSRX1 \u3_mem_reg[0][7] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8249), .Q (\u3_mem[0]_97 ), .QN ()); + DFFX1 u14_u6_full_empty_r_reg(.CK (clk_i), .D (n_8215), .Q + (u14_u6_full_empty_r), .QN ()); + DFFX1 u14_u8_full_empty_r_reg(.CK (clk_i), .D (n_8213), .Q + (u14_u8_full_empty_r), .QN ()); + DFFX1 \u12_wb_data_o_reg[0] (.CK (clk_i), .D (n_8245), .Q + (wb_data_o[0]), .QN ()); + DFFX1 \u12_wb_data_o_reg[14] (.CK (clk_i), .D (n_8237), .Q + (wb_data_o[14]), .QN ()); + DFFX1 \u12_wb_data_o_reg[13] (.CK (clk_i), .D (n_8238), .Q + (wb_data_o[13]), .QN ()); + DFFX1 \u12_wb_data_o_reg[12] (.CK (clk_i), .D (n_8242), .Q + (wb_data_o[12]), .QN ()); + DFFX1 \u12_wb_data_o_reg[11] (.CK (clk_i), .D (n_8243), .Q + (wb_data_o[11]), .QN ()); + DFFX1 \u12_wb_data_o_reg[9] (.CK (clk_i), .D (n_8228), .Q + (wb_data_o[9]), .QN ()); + DFFX1 \u12_wb_data_o_reg[7] (.CK (clk_i), .D (n_8230), .Q + (wb_data_o[7]), .QN ()); + DFFX1 \u12_wb_data_o_reg[15] (.CK (clk_i), .D (n_8236), .Q + (wb_data_o[15]), .QN ()); + DFFX1 \u12_wb_data_o_reg[5] (.CK (clk_i), .D (n_8232), .Q + (wb_data_o[5]), .QN ()); + DFFX1 \u12_wb_data_o_reg[3] (.CK (clk_i), .D (n_8234), .Q + (wb_data_o[3]), .QN ()); + DFFX1 \u12_wb_data_o_reg[8] (.CK (clk_i), .D (n_8229), .Q + (wb_data_o[8]), .QN ()); + DFFX1 \u12_wb_data_o_reg[2] (.CK (clk_i), .D (n_8235), .Q + (wb_data_o[2]), .QN ()); + DFFSRX1 \u13_occ1_r_reg[9] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8184), .Q (oc5_cfg_1014), .QN ()); + DFFSRX1 \u13_occ1_r_reg[15] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8195), .Q (oc5_cfg_1020), .QN ()); + DFFSRX1 \u3_mem_reg[0][31] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_8250), .Q (\u3_mem[0]_121 ), .QN ()); + DFFSRX1 \u13_occ1_r_reg[4] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_8191), .Q (n_8190), .QN ()); + NOR2X1 g32904(.A (n_854), .B (o4_empty), .Y (n_12846)); + NOR2X1 g32906(.A (n_12802), .B (o7_empty), .Y (n_9560)); + NOR2X1 g32965(.A (o4_empty), .B (n_458), .Y (n_9559)); + NOR2X1 g32967(.A (o7_empty), .B (n_422), .Y (n_9558)); + MX2X1 g33185(.A (u1_sr_124), .B (in_slt_750), .S0 (out_le_180), .Y + (n_9357)); + MX2X1 g33186(.A (u1_sr_124), .B (in_slt_834), .S0 (out_le_181), .Y + (n_9356)); + MX2X1 g33187(.A (u1_sr_124), .B (in_slt_404), .S0 (out_le_182), .Y + (n_9355)); + MX2X1 g33188(.A (u1_sr_124), .B (in_slt_426), .S0 (out_le_183), .Y + (n_9354)); + MX2X1 g33189(.A (u1_sr_124), .B (in_slt_448), .S0 (out_le_184), .Y + (n_9353)); + DFFX1 \u0_slt9_r_reg[1] (.CK (bit_clk_pad_i), .D (n_8211), .Q + (u0_slt9_r_168), .QN ()); + AND2X1 g33370(.A (n_9352), .B (u14_u6_en_out_l2), .Y (n_9447)); + DFFX1 \u1_slt6_reg[7] (.CK (bit_clk_pad_i), .D (n_8254), .Q + (in_slt_447), .QN ()); + OAI21X1 g33577(.A0 (n_5098), .A1 (n_9349), .B0 (n_7978), .Y (n_9351)); + OAI21X1 g33578(.A0 (n_5096), .A1 (n_9349), .B0 (n_7975), .Y (n_9350)); + OAI21X1 g33579(.A0 (n_5095), .A1 (n_9346), .B0 (n_7974), .Y (n_9348)); + OAI21X1 g33580(.A0 (n_5094), .A1 (n_9346), .B0 (n_7973), .Y (n_9347)); + OAI21X1 g33581(.A0 (n_5092), .A1 (n_9346), .B0 (n_7972), .Y (n_9345)); + OAI21X1 g33582(.A0 (n_5091), .A1 (n_9346), .B0 (n_7971), .Y (n_9344)); + OAI21X1 g33583(.A0 (n_5090), .A1 (n_8318), .B0 (n_7970), .Y (n_9343)); + OAI21X1 g33584(.A0 (n_5089), .A1 (n_8318), .B0 (n_7969), .Y (n_9342)); + OAI21X1 g33585(.A0 (n_5088), .A1 (n_8318), .B0 (n_7968), .Y (n_9340)); + OAI21X1 g33586(.A0 (n_5087), .A1 (n_8318), .B0 (n_7967), .Y (n_9339)); + OAI21X1 g33587(.A0 (n_5086), .A1 (n_9336), .B0 (n_7966), .Y (n_9338)); + OAI21X1 g33588(.A0 (n_5085), .A1 (n_9336), .B0 (n_7965), .Y (n_9337)); + OAI21X1 g33589(.A0 (n_5084), .A1 (n_9333), .B0 (n_7964), .Y (n_9335)); + OAI21X1 g33590(.A0 (n_5082), .A1 (n_9333), .B0 (n_7963), .Y (n_9334)); + OAI21X1 g33591(.A0 (n_5081), .A1 (n_9333), .B0 (n_7962), .Y (n_9332)); + OAI21X1 g33592(.A0 (n_5080), .A1 (n_9333), .B0 (n_7961), .Y (n_9331)); + OAI21X1 g33593(.A0 (n_5078), .A1 (n_9336), .B0 (n_7960), .Y (n_9330)); + OAI21X1 g33594(.A0 (n_5077), .A1 (n_9336), .B0 (n_7959), .Y (n_9329)); + OAI21X1 g33595(.A0 (n_5075), .A1 (n_9326), .B0 (n_7958), .Y (n_9328)); + OAI21X1 g33596(.A0 (n_5074), .A1 (n_9326), .B0 (n_7956), .Y (n_9327)); + OAI21X1 g33597(.A0 (n_5072), .A1 (n_9349), .B0 (n_7955), .Y (n_9325)); + OAI21X1 g33598(.A0 (n_5071), .A1 (n_9349), .B0 (n_7954), .Y (n_9324)); + OAI21X1 g33599(.A0 (n_5068), .A1 (n_9326), .B0 (n_7953), .Y (n_9322)); + OAI21X1 g33600(.A0 (n_5067), .A1 (n_9326), .B0 (n_7952), .Y (n_9321)); + OAI21X1 g33601(.A0 (n_5065), .A1 (n_9349), .B0 (n_7951), .Y (n_9320)); + OAI21X1 g33602(.A0 (n_5064), .A1 (n_9349), .B0 (n_7950), .Y (n_9319)); + OAI21X1 g33603(.A0 (n_4384), .A1 (n_8856), .B0 (n_8132), .Y (n_9318)); + OAI21X1 g33604(.A0 (n_5049), .A1 (n_9286), .B0 (n_7943), .Y (n_9317)); + OAI21X1 g33605(.A0 (n_5047), .A1 (n_9286), .B0 (n_7942), .Y (n_9316)); + OAI21X1 g33606(.A0 (n_5046), .A1 (n_9307), .B0 (n_7941), .Y (n_9315)); + OAI21X1 g33607(.A0 (n_5023), .A1 (n_9307), .B0 (n_7939), .Y (n_9314)); + OAI21X1 g33608(.A0 (n_5043), .A1 (n_9307), .B0 (n_7938), .Y (n_9313)); + OAI21X1 g33609(.A0 (n_5042), .A1 (n_9286), .B0 (n_7936), .Y (n_9312)); + OAI21X1 g33610(.A0 (n_5040), .A1 (n_9286), .B0 (n_7935), .Y (n_9310)); + OAI21X1 g33611(.A0 (n_5039), .A1 (n_9307), .B0 (n_7934), .Y (n_9308)); + OAI21X1 g33612(.A0 (n_5038), .A1 (n_9307), .B0 (n_7933), .Y (n_9306)); + OAI21X1 g33613(.A0 (n_5035), .A1 (n_9307), .B0 (n_7932), .Y (n_9304)); + OAI21X1 g33614(.A0 (n_5034), .A1 (n_9307), .B0 (n_7930), .Y (n_9302)); + OAI21X1 g33615(.A0 (n_5033), .A1 (n_9286), .B0 (n_7929), .Y (n_9301)); + OAI21X1 g33616(.A0 (n_5032), .A1 (n_9235), .B0 (n_7927), .Y (n_9300)); + OAI21X1 g33617(.A0 (n_5031), .A1 (n_9264), .B0 (n_7925), .Y (n_9299)); + OAI21X1 g33618(.A0 (n_5030), .A1 (n_9286), .B0 (n_7924), .Y (n_9298)); + OAI21X1 g33619(.A0 (n_5029), .A1 (n_9288), .B0 (n_7923), .Y (n_9297)); + OAI21X1 g33620(.A0 (n_5028), .A1 (n_9288), .B0 (n_7922), .Y (n_9296)); + OAI21X1 g33621(.A0 (n_5027), .A1 (n_9290), .B0 (n_7921), .Y (n_9294)); + OAI21X1 g33622(.A0 (n_5026), .A1 (n_9264), .B0 (n_7920), .Y (n_9293)); + OAI21X1 g33623(.A0 (n_5025), .A1 (n_9288), .B0 (n_7919), .Y (n_9292)); + OAI21X1 g33624(.A0 (n_5024), .A1 (n_9290), .B0 (n_7918), .Y (n_9291)); + OAI21X1 g33625(.A0 (n_5022), .A1 (n_9288), .B0 (n_7917), .Y (n_9289)); + OAI21X1 g33626(.A0 (n_5021), .A1 (n_9286), .B0 (n_7916), .Y (n_9287)); + OAI21X1 g33627(.A0 (n_5018), .A1 (n_9235), .B0 (n_7915), .Y (n_9285)); + OAI21X1 g33628(.A0 (n_5017), .A1 (n_9307), .B0 (n_7914), .Y (n_9283)); + OAI21X1 g33629(.A0 (n_5016), .A1 (n_9202), .B0 (n_7913), .Y (n_9282)); + OAI21X1 g33630(.A0 (n_5015), .A1 (n_9286), .B0 (n_7912), .Y (n_9281)); + OAI21X1 g33631(.A0 (n_5014), .A1 (n_9286), .B0 (n_7911), .Y (n_9280)); + OAI21X1 g33632(.A0 (n_5013), .A1 (n_9212), .B0 (n_7910), .Y (n_9278)); + OAI21X1 g33633(.A0 (n_5012), .A1 (n_9307), .B0 (n_7909), .Y (n_9277)); + OAI21X1 g33634(.A0 (n_5141), .A1 (n_9286), .B0 (n_7908), .Y (n_9276)); + OAI21X1 g33635(.A0 (n_5010), .A1 (n_9286), .B0 (n_7907), .Y (n_9275)); + OAI21X1 g33636(.A0 (n_4379), .A1 (n_9286), .B0 (n_7904), .Y (n_9274)); + OAI21X1 g33637(.A0 (n_4377), .A1 (n_9288), .B0 (n_7903), .Y (n_9273)); + OAI21X1 g33638(.A0 (n_4376), .A1 (n_9307), .B0 (n_7902), .Y (n_9272)); + OAI21X1 g33639(.A0 (n_4375), .A1 (n_9307), .B0 (n_7901), .Y (n_9270)); + OAI21X1 g33640(.A0 (n_4542), .A1 (n_9288), .B0 (n_7900), .Y (n_9269)); + OAI21X1 g33641(.A0 (n_4374), .A1 (n_9307), .B0 (n_7899), .Y (n_9268)); + OAI21X1 g33642(.A0 (n_4373), .A1 (n_9290), .B0 (n_7898), .Y (n_9267)); + OAI21X1 g33643(.A0 (n_4372), .A1 (n_9307), .B0 (n_7897), .Y (n_9266)); + OAI21X1 g33644(.A0 (n_4371), .A1 (n_9264), .B0 (n_7896), .Y (n_9265)); + OAI21X1 g33645(.A0 (n_4369), .A1 (n_9307), .B0 (n_7895), .Y (n_9263)); + OAI21X1 g33646(.A0 (n_4276), .A1 (n_9288), .B0 (n_7894), .Y (n_9262)); + OAI21X1 g33647(.A0 (n_4368), .A1 (n_9212), .B0 (n_7893), .Y (n_9261)); + OAI21X1 g33648(.A0 (n_4367), .A1 (n_9290), .B0 (n_7892), .Y (n_9259)); + OAI21X1 g33649(.A0 (n_4365), .A1 (n_9288), .B0 (n_7891), .Y (n_9258)); + OAI21X1 g33650(.A0 (n_4364), .A1 (n_9307), .B0 (n_7890), .Y (n_9257)); + OAI21X1 g33651(.A0 (n_4289), .A1 (n_9286), .B0 (n_7889), .Y (n_9256)); + OAI21X1 g33652(.A0 (n_4363), .A1 (n_9264), .B0 (n_7888), .Y (n_9255)); + OAI21X1 g33653(.A0 (n_4362), .A1 (n_9264), .B0 (n_7887), .Y (n_9254)); + OAI21X1 g33654(.A0 (n_4361), .A1 (n_9235), .B0 (n_7886), .Y (n_9253)); + OAI21X1 g33655(.A0 (n_4360), .A1 (n_9202), .B0 (n_7885), .Y (n_9252)); + OAI21X1 g33656(.A0 (n_4359), .A1 (n_9212), .B0 (n_7884), .Y (n_9250)); + OAI21X1 g33657(.A0 (n_4357), .A1 (n_9264), .B0 (n_7883), .Y (n_9249)); + OAI21X1 g33658(.A0 (n_4300), .A1 (n_9286), .B0 (n_7882), .Y (n_9247)); + OAI21X1 g33659(.A0 (n_4301), .A1 (n_9286), .B0 (n_7881), .Y (n_9246)); + OAI21X1 g33660(.A0 (n_4356), .A1 (n_9235), .B0 (n_7880), .Y (n_9245)); + OAI21X1 g33661(.A0 (n_4355), .A1 (n_9286), .B0 (n_7879), .Y (n_9244)); + OAI21X1 g33662(.A0 (n_4306), .A1 (n_9212), .B0 (n_7878), .Y (n_9243)); + OAI21X1 g33663(.A0 (n_4308), .A1 (n_9202), .B0 (n_7877), .Y (n_9242)); + OAI21X1 g33664(.A0 (n_4354), .A1 (n_9202), .B0 (n_7876), .Y (n_9241)); + OAI21X1 g33665(.A0 (n_4353), .A1 (n_9264), .B0 (n_7875), .Y (n_9240)); + OAI21X1 g33666(.A0 (n_4352), .A1 (n_9264), .B0 (n_7874), .Y (n_9239)); + OAI21X1 g33667(.A0 (n_4351), .A1 (n_9307), .B0 (n_7873), .Y (n_9238)); + OAI21X1 g33668(.A0 (n_5002), .A1 (n_9235), .B0 (n_7872), .Y (n_9237)); + OAI21X1 g33669(.A0 (n_5001), .A1 (n_9235), .B0 (n_7871), .Y (n_9236)); + OAI21X1 g33670(.A0 (n_4999), .A1 (n_9235), .B0 (n_7869), .Y (n_9234)); + OAI21X1 g33671(.A0 (n_4998), .A1 (n_9235), .B0 (n_7868), .Y (n_9233)); + OAI21X1 g33672(.A0 (n_4997), .A1 (n_9230), .B0 (n_7867), .Y (n_9232)); + OAI21X1 g33673(.A0 (n_4995), .A1 (n_9230), .B0 (n_7866), .Y (n_9231)); + OAI21X1 g33674(.A0 (n_4994), .A1 (n_9230), .B0 (n_7865), .Y (n_9229)); + OAI21X1 g33675(.A0 (n_4993), .A1 (n_9230), .B0 (n_7864), .Y (n_9228)); + OAI21X1 g33676(.A0 (n_4992), .A1 (n_9205), .B0 (n_7863), .Y (n_9227)); + OAI21X1 g33677(.A0 (n_4990), .A1 (n_9205), .B0 (n_7862), .Y (n_9226)); + OAI21X1 g33678(.A0 (n_4989), .A1 (n_9205), .B0 (n_7861), .Y (n_9224)); + OAI21X1 g33679(.A0 (n_4987), .A1 (n_9205), .B0 (n_7860), .Y (n_9223)); + OAI21X1 g33680(.A0 (n_4986), .A1 (n_9290), .B0 (n_7859), .Y (n_9222)); + OAI21X1 g33681(.A0 (n_4985), .A1 (n_9290), .B0 (n_7858), .Y (n_9221)); + OAI21X1 g33682(.A0 (n_4984), .A1 (n_9290), .B0 (n_7857), .Y (n_9219)); + OAI21X1 g33683(.A0 (n_4983), .A1 (n_9290), .B0 (n_7856), .Y (n_9218)); + OAI21X1 g33684(.A0 (n_4982), .A1 (n_9230), .B0 (n_7855), .Y (n_9217)); + OAI21X1 g33685(.A0 (n_4981), .A1 (n_9230), .B0 (n_7854), .Y (n_9216)); + OAI21X1 g33686(.A0 (n_4980), .A1 (n_9212), .B0 (n_7853), .Y (n_9214)); + OAI21X1 g33687(.A0 (n_4979), .A1 (n_9212), .B0 (n_7852), .Y (n_9213)); + OAI21X1 g33688(.A0 (n_4978), .A1 (n_9212), .B0 (n_7851), .Y (n_9211)); + OAI21X1 g33689(.A0 (n_4977), .A1 (n_9212), .B0 (n_7850), .Y (n_9210)); + OAI21X1 g33690(.A0 (n_4976), .A1 (n_9230), .B0 (n_7849), .Y (n_9209)); + OAI21X1 g33691(.A0 (n_4974), .A1 (n_9230), .B0 (n_7848), .Y (n_9208)); + OAI21X1 g33692(.A0 (n_4972), .A1 (n_9205), .B0 (n_7847), .Y (n_9207)); + OAI21X1 g33693(.A0 (n_4971), .A1 (n_9205), .B0 (n_7846), .Y (n_9206)); + OAI21X1 g33694(.A0 (n_4970), .A1 (n_9202), .B0 (n_7845), .Y (n_9204)); + OAI21X1 g33695(.A0 (n_4969), .A1 (n_9202), .B0 (n_7844), .Y (n_9203)); + OAI21X1 g33696(.A0 (n_4950), .A1 (n_9205), .B0 (n_7843), .Y (n_9201)); + OAI21X1 g33697(.A0 (n_4968), .A1 (n_9205), .B0 (n_7842), .Y (n_9200)); + OAI21X1 g33698(.A0 (n_4966), .A1 (n_9202), .B0 (n_7841), .Y (n_9199)); + OAI21X1 g33699(.A0 (n_4965), .A1 (n_9202), .B0 (n_7840), .Y (n_9198)); + OAI21X1 g33700(.A0 (n_3858), .A1 (n_8464), .B0 (n_7837), .Y (n_9197)); + OAI21X1 g33701(.A0 (n_4319), .A1 (n_8433), .B0 (n_7596), .Y (n_9196)); + OAI21X1 g33702(.A0 (n_4346), .A1 (n_8856), .B0 (n_7835), .Y (n_9195)); + OAI21X1 g33703(.A0 (n_3850), .A1 (n_8453), .B0 (n_7727), .Y (n_9193)); + OAI21X1 g33704(.A0 (n_4948), .A1 (n_9161), .B0 (n_7832), .Y (n_9192)); + OAI21X1 g33705(.A0 (n_4930), .A1 (n_9161), .B0 (n_7831), .Y (n_9191)); + OAI21X1 g33706(.A0 (n_4947), .A1 (n_9182), .B0 (n_7830), .Y (n_9190)); + OAI21X1 g33707(.A0 (n_4933), .A1 (n_9182), .B0 (n_7828), .Y (n_9189)); + OAI21X1 g33708(.A0 (n_4946), .A1 (n_9182), .B0 (n_7827), .Y (n_9188)); + OAI21X1 g33709(.A0 (n_4938), .A1 (n_9161), .B0 (n_7825), .Y (n_9187)); + OAI21X1 g33710(.A0 (n_4941), .A1 (n_9161), .B0 (n_7824), .Y (n_9185)); + OAI21X1 g33711(.A0 (n_4944), .A1 (n_9182), .B0 (n_7823), .Y (n_9183)); + OAI21X1 g33712(.A0 (n_4945), .A1 (n_9182), .B0 (n_7822), .Y (n_9181)); + OAI21X1 g33713(.A0 (n_4967), .A1 (n_9182), .B0 (n_7821), .Y (n_9179)); + OAI21X1 g33714(.A0 (n_4973), .A1 (n_9182), .B0 (n_7819), .Y (n_9177)); + OAI21X1 g33715(.A0 (n_4943), .A1 (n_9161), .B0 (n_7817), .Y (n_9176)); + OAI21X1 g33716(.A0 (n_4942), .A1 (n_9110), .B0 (n_7815), .Y (n_9175)); + OAI21X1 g33717(.A0 (n_5003), .A1 (n_9139), .B0 (n_7813), .Y (n_9174)); + OAI21X1 g33718(.A0 (n_5004), .A1 (n_9161), .B0 (n_7812), .Y (n_9173)); + OAI21X1 g33719(.A0 (n_5007), .A1 (n_9170), .B0 (n_7811), .Y (n_9172)); + OAI21X1 g33720(.A0 (n_4940), .A1 (n_9170), .B0 (n_7810), .Y (n_9171)); + OAI21X1 g33721(.A0 (n_5008), .A1 (n_9165), .B0 (n_7809), .Y (n_9169)); + OAI21X1 g33722(.A0 (n_5011), .A1 (n_9139), .B0 (n_7808), .Y (n_9168)); + OAI21X1 g33723(.A0 (n_5020), .A1 (n_9087), .B0 (n_7807), .Y (n_9167)); + OAI21X1 g33724(.A0 (n_4939), .A1 (n_9165), .B0 (n_7806), .Y (n_9166)); + OAI21X1 g33725(.A0 (n_5054), .A1 (n_9087), .B0 (n_7804), .Y (n_9164)); + OAI21X1 g33726(.A0 (n_4937), .A1 (n_9161), .B0 (n_7803), .Y (n_9162)); + OAI21X1 g33727(.A0 (n_5140), .A1 (n_9110), .B0 (n_7802), .Y (n_9160)); + OAI21X1 g33728(.A0 (n_4936), .A1 (n_9182), .B0 (n_7801), .Y (n_9158)); + OAI21X1 g33729(.A0 (n_4935), .A1 (n_9077), .B0 (n_7800), .Y (n_9157)); + OAI21X1 g33730(.A0 (n_5097), .A1 (n_9161), .B0 (n_7799), .Y (n_9156)); + OAI21X1 g33731(.A0 (n_5108), .A1 (n_9161), .B0 (n_7798), .Y (n_9155)); + OAI21X1 g33732(.A0 (n_4934), .A1 (n_9170), .B0 (n_7797), .Y (n_9153)); + OAI21X1 g33733(.A0 (n_5113), .A1 (n_9182), .B0 (n_7796), .Y (n_9152)); + OAI21X1 g33734(.A0 (n_5111), .A1 (n_9161), .B0 (n_7795), .Y (n_9151)); + OAI21X1 g33735(.A0 (n_4906), .A1 (n_9161), .B0 (n_7794), .Y (n_9150)); + OAI21X1 g33736(.A0 (n_4443), .A1 (n_9161), .B0 (n_7793), .Y (n_9149)); + OAI21X1 g33737(.A0 (n_4338), .A1 (n_9170), .B0 (n_7792), .Y (n_9148)); + OAI21X1 g33738(.A0 (n_4468), .A1 (n_9182), .B0 (n_7790), .Y (n_9147)); + OAI21X1 g33739(.A0 (n_4476), .A1 (n_9182), .B0 (n_7789), .Y (n_9145)); + OAI21X1 g33740(.A0 (n_4488), .A1 (n_9170), .B0 (n_7788), .Y (n_9144)); + OAI21X1 g33741(.A0 (n_4337), .A1 (n_9182), .B0 (n_7787), .Y (n_9143)); + OAI21X1 g33742(.A0 (n_4498), .A1 (n_9165), .B0 (n_7786), .Y (n_9142)); + OAI21X1 g33743(.A0 (n_4336), .A1 (n_9182), .B0 (n_7785), .Y (n_9141)); + OAI21X1 g33744(.A0 (n_4505), .A1 (n_9139), .B0 (n_7784), .Y (n_9140)); + OAI21X1 g33745(.A0 (n_4515), .A1 (n_9182), .B0 (n_7783), .Y (n_9138)); + OAI21X1 g33746(.A0 (n_4523), .A1 (n_9087), .B0 (n_7782), .Y (n_9137)); + OAI21X1 g33747(.A0 (n_4335), .A1 (n_9170), .B0 (n_7781), .Y (n_9136)); + OAI21X1 g33748(.A0 (n_4525), .A1 (n_9165), .B0 (n_7780), .Y (n_9134)); + OAI21X1 g33749(.A0 (n_4531), .A1 (n_9087), .B0 (n_7779), .Y (n_9133)); + OAI21X1 g33750(.A0 (n_4535), .A1 (n_9182), .B0 (n_7778), .Y (n_9132)); + OAI21X1 g33751(.A0 (n_4334), .A1 (n_9161), .B0 (n_7777), .Y (n_9131)); + OAI21X1 g33752(.A0 (n_4539), .A1 (n_9139), .B0 (n_7776), .Y (n_9130)); + OAI21X1 g33753(.A0 (n_4332), .A1 (n_9139), .B0 (n_7775), .Y (n_9129)); + OAI21X1 g33754(.A0 (n_4543), .A1 (n_9110), .B0 (n_7774), .Y (n_9128)); + OAI21X1 g33755(.A0 (n_4545), .A1 (n_9077), .B0 (n_7773), .Y (n_9127)); + OAI21X1 g33756(.A0 (n_4547), .A1 (n_9170), .B0 (n_7772), .Y (n_9125)); + OAI21X1 g33757(.A0 (n_4358), .A1 (n_9139), .B0 (n_7771), .Y (n_9124)); + OAI21X1 g33758(.A0 (n_4323), .A1 (n_9161), .B0 (n_7770), .Y (n_9122)); + OAI21X1 g33759(.A0 (n_4399), .A1 (n_9161), .B0 (n_7769), .Y (n_9121)); + OAI21X1 g33760(.A0 (n_4398), .A1 (n_9110), .B0 (n_7768), .Y (n_9120)); + OAI21X1 g33761(.A0 (n_4330), .A1 (n_9161), .B0 (n_7767), .Y (n_9119)); + OAI21X1 g33762(.A0 (n_4457), .A1 (n_9170), .B0 (n_7766), .Y (n_9118)); + OAI21X1 g33763(.A0 (n_4401), .A1 (n_9077), .B0 (n_7765), .Y (n_9117)); + OAI21X1 g33764(.A0 (n_4403), .A1 (n_9077), .B0 (n_7764), .Y (n_9116)); + OAI21X1 g33765(.A0 (n_4405), .A1 (n_9139), .B0 (n_7763), .Y (n_9115)); + OAI21X1 g33766(.A0 (n_4415), .A1 (n_9139), .B0 (n_7762), .Y (n_9114)); + OAI21X1 g33767(.A0 (n_4322), .A1 (n_9182), .B0 (n_7761), .Y (n_9113)); + OAI21X1 g33768(.A0 (n_4928), .A1 (n_9110), .B0 (n_7760), .Y (n_9112)); + OAI21X1 g33769(.A0 (n_4927), .A1 (n_9110), .B0 (n_7759), .Y (n_9111)); + OAI21X1 g33770(.A0 (n_4926), .A1 (n_9110), .B0 (n_7757), .Y (n_9109)); + OAI21X1 g33771(.A0 (n_4988), .A1 (n_9110), .B0 (n_7756), .Y (n_9108)); + OAI21X1 g33772(.A0 (n_4925), .A1 (n_9105), .B0 (n_7755), .Y (n_9107)); + OAI21X1 g33773(.A0 (n_4924), .A1 (n_9105), .B0 (n_7754), .Y (n_9106)); + OAI21X1 g33774(.A0 (n_4923), .A1 (n_9105), .B0 (n_7753), .Y (n_9104)); + OAI21X1 g33775(.A0 (n_5036), .A1 (n_9105), .B0 (n_7752), .Y (n_9103)); + OAI21X1 g33776(.A0 (n_5041), .A1 (n_9100), .B0 (n_7751), .Y (n_9102)); + OAI21X1 g33777(.A0 (n_5044), .A1 (n_9100), .B0 (n_7750), .Y (n_9101)); + OAI21X1 g33778(.A0 (n_4922), .A1 (n_9100), .B0 (n_7749), .Y (n_9099)); + OAI21X1 g33779(.A0 (n_5050), .A1 (n_9100), .B0 (n_7748), .Y (n_9098)); + OAI21X1 g33780(.A0 (n_5051), .A1 (n_9165), .B0 (n_7747), .Y (n_9097)); + OAI21X1 g33781(.A0 (n_4921), .A1 (n_9165), .B0 (n_7746), .Y (n_9096)); + OAI21X1 g33782(.A0 (n_5052), .A1 (n_9165), .B0 (n_7745), .Y (n_9094)); + OAI21X1 g33783(.A0 (n_5053), .A1 (n_9165), .B0 (n_7744), .Y (n_9093)); + OAI21X1 g33784(.A0 (n_5055), .A1 (n_9105), .B0 (n_7743), .Y (n_9092)); + OAI21X1 g33785(.A0 (n_5056), .A1 (n_9105), .B0 (n_7742), .Y (n_9091)); + OAI21X1 g33786(.A0 (n_4920), .A1 (n_9087), .B0 (n_7741), .Y (n_9089)); + OAI21X1 g33787(.A0 (n_5060), .A1 (n_9087), .B0 (n_7740), .Y (n_9088)); + OAI21X1 g33788(.A0 (n_5006), .A1 (n_9087), .B0 (n_7739), .Y (n_9086)); + OAI21X1 g33789(.A0 (n_5061), .A1 (n_9087), .B0 (n_7738), .Y (n_9085)); + OAI21X1 g33790(.A0 (n_4919), .A1 (n_9105), .B0 (n_7737), .Y (n_9084)); + OAI21X1 g33791(.A0 (n_5062), .A1 (n_9105), .B0 (n_7736), .Y (n_9083)); + OAI21X1 g33792(.A0 (n_5063), .A1 (n_9080), .B0 (n_7735), .Y (n_9082)); + OAI21X1 g33793(.A0 (n_5109), .A1 (n_9080), .B0 (n_7734), .Y (n_9081)); + OAI21X1 g33794(.A0 (n_4917), .A1 (n_9077), .B0 (n_7733), .Y (n_9079)); + OAI21X1 g33795(.A0 (n_5101), .A1 (n_9077), .B0 (n_7732), .Y (n_9078)); + OAI21X1 g33796(.A0 (n_4916), .A1 (n_9080), .B0 (n_7731), .Y (n_9076)); + OAI21X1 g33797(.A0 (n_4915), .A1 (n_9080), .B0 (n_7730), .Y (n_9075)); + OAI21X1 g33798(.A0 (n_4914), .A1 (n_9077), .B0 (n_7729), .Y (n_9074)); + OAI21X1 g33799(.A0 (n_5058), .A1 (n_9077), .B0 (n_7728), .Y (n_9073)); + OAI21X1 g33800(.A0 (n_4340), .A1 (n_8898), .B0 (n_7588), .Y (n_9072)); + OAI21X1 g33801(.A0 (n_4343), .A1 (n_8440), .B0 (n_8122), .Y (n_9071)); + OAI21X1 g33802(.A0 (n_3852), .A1 (n_8438), .B0 (n_8134), .Y (n_9070)); + OAI21X1 g33803(.A0 (n_5115), .A1 (n_9022), .B0 (n_8077), .Y (n_9069)); + OAI21X1 g33804(.A0 (n_3857), .A1 (n_8930), .B0 (n_8130), .Y (n_9068)); + OAI21X1 g33805(.A0 (n_4867), .A1 (n_8393), .B0 (n_7589), .Y (n_9067)); + OAI21X1 g33806(.A0 (n_4902), .A1 (n_9034), .B0 (n_7722), .Y (n_9066)); + OAI21X1 g33807(.A0 (n_4905), .A1 (n_9034), .B0 (n_7721), .Y (n_9065)); + OAI21X1 g33808(.A0 (n_4918), .A1 (n_9055), .B0 (n_7719), .Y (n_9064)); + OAI21X1 g33809(.A0 (n_4858), .A1 (n_8856), .B0 (n_7568), .Y (n_9063)); + OAI21X1 g33810(.A0 (n_4904), .A1 (n_9055), .B0 (n_7718), .Y (n_9062)); + OAI21X1 g33811(.A0 (n_4929), .A1 (n_9055), .B0 (n_7717), .Y (n_9061)); + OAI21X1 g33812(.A0 (n_4903), .A1 (n_9034), .B0 (n_7716), .Y (n_9060)); + OAI21X1 g33813(.A0 (n_5110), .A1 (n_9034), .B0 (n_7715), .Y (n_9058)); + OAI21X1 g33814(.A0 (n_4901), .A1 (n_9055), .B0 (n_7713), .Y (n_9056)); + OAI21X1 g33815(.A0 (n_4900), .A1 (n_9055), .B0 (n_7712), .Y (n_9054)); + OAI21X1 g33816(.A0 (n_5128), .A1 (n_9055), .B0 (n_7710), .Y (n_9052)); + OAI21X1 g33817(.A0 (n_4932), .A1 (n_9055), .B0 (n_7708), .Y (n_9050)); + OAI21X1 g33818(.A0 (n_5083), .A1 (n_9034), .B0 (n_7707), .Y (n_9049)); + OAI21X1 g33819(.A0 (n_4991), .A1 (n_8981), .B0 (n_7706), .Y (n_9048)); + OAI21X1 g33820(.A0 (n_4899), .A1 (n_9010), .B0 (n_7705), .Y (n_9047)); + OAI21X1 g33821(.A0 (n_4964), .A1 (n_9034), .B0 (n_7704), .Y (n_9046)); + OAI21X1 g33822(.A0 (n_4897), .A1 (n_9043), .B0 (n_7703), .Y (n_9045)); + OAI21X1 g33823(.A0 (n_4975), .A1 (n_9043), .B0 (n_7702), .Y (n_9044)); + OAI21X1 g33824(.A0 (n_4896), .A1 (n_9038), .B0 (n_7701), .Y (n_9042)); + OAI21X1 g33825(.A0 (n_4911), .A1 (n_9010), .B0 (n_7699), .Y (n_9041)); + OAI21X1 g33826(.A0 (n_4895), .A1 (n_9036), .B0 (n_7698), .Y (n_9040)); + OAI21X1 g33827(.A0 (n_5005), .A1 (n_9038), .B0 (n_7696), .Y (n_9039)); + OAI21X1 g33828(.A0 (n_4894), .A1 (n_9036), .B0 (n_7695), .Y (n_9037)); + OAI21X1 g33829(.A0 (n_5119), .A1 (n_9034), .B0 (n_7693), .Y (n_9035)); + OAI21X1 g33830(.A0 (n_4893), .A1 (n_8981), .B0 (n_7692), .Y (n_9033)); + OAI21X1 g33831(.A0 (n_5009), .A1 (n_9055), .B0 (n_7906), .Y (n_9031)); + OAI21X1 g33832(.A0 (n_4892), .A1 (n_8948), .B0 (n_7691), .Y (n_9030)); + OAI21X1 g33833(.A0 (n_5117), .A1 (n_9034), .B0 (n_7690), .Y (n_9029)); + OAI21X1 g33834(.A0 (n_4951), .A1 (n_9034), .B0 (n_7689), .Y (n_9028)); + OAI21X1 g33835(.A0 (n_5070), .A1 (n_9043), .B0 (n_7688), .Y (n_9026)); + OAI21X1 g33836(.A0 (n_4891), .A1 (n_9055), .B0 (n_7687), .Y (n_9025)); + OAI21X1 g33837(.A0 (n_5079), .A1 (n_9034), .B0 (n_7686), .Y (n_9024)); + OAI21X1 g33838(.A0 (n_5045), .A1 (n_9022), .B0 (n_8089), .Y (n_9023)); + OAI21X1 g33839(.A0 (n_4890), .A1 (n_9034), .B0 (n_7685), .Y (n_9021)); + OAI21X1 g33840(.A0 (n_4404), .A1 (n_9034), .B0 (n_7684), .Y (n_9020)); + OAI21X1 g33841(.A0 (n_4406), .A1 (n_9043), .B0 (n_7683), .Y (n_9019)); + OAI21X1 g33842(.A0 (n_4318), .A1 (n_9055), .B0 (n_7682), .Y (n_9018)); + OAI21X1 g33843(.A0 (n_4424), .A1 (n_9055), .B0 (n_7681), .Y (n_9016)); + OAI21X1 g33844(.A0 (n_4317), .A1 (n_9043), .B0 (n_7680), .Y (n_9015)); + OAI21X1 g33845(.A0 (n_4316), .A1 (n_9055), .B0 (n_7679), .Y (n_9014)); + OAI21X1 g33846(.A0 (n_4315), .A1 (n_9038), .B0 (n_7678), .Y (n_9013)); + OAI21X1 g33847(.A0 (n_4452), .A1 (n_9055), .B0 (n_7677), .Y (n_9012)); + OAI21X1 g33848(.A0 (n_4314), .A1 (n_9010), .B0 (n_7676), .Y (n_9011)); + OAI21X1 g33849(.A0 (n_4466), .A1 (n_9055), .B0 (n_7675), .Y (n_9009)); + OAI21X1 g33850(.A0 (n_4313), .A1 (n_9036), .B0 (n_7674), .Y (n_9008)); + OAI21X1 g33851(.A0 (n_4496), .A1 (n_9043), .B0 (n_8078), .Y (n_9007)); + OAI21X1 g33852(.A0 (n_4501), .A1 (n_9038), .B0 (n_7673), .Y (n_9005)); + OAI21X1 g33853(.A0 (n_4510), .A1 (n_9036), .B0 (n_7672), .Y (n_9004)); + OAI21X1 g33854(.A0 (n_4506), .A1 (n_9055), .B0 (n_7671), .Y (n_9003)); + OAI21X1 g33855(.A0 (n_4516), .A1 (n_9034), .B0 (n_7670), .Y (n_9002)); + OAI21X1 g33856(.A0 (n_4481), .A1 (n_9010), .B0 (n_7669), .Y (n_9001)); + OAI21X1 g33857(.A0 (n_4312), .A1 (n_9010), .B0 (n_7668), .Y (n_9000)); + OAI21X1 g33858(.A0 (n_4311), .A1 (n_8981), .B0 (n_7667), .Y (n_8999)); + OAI21X1 g33859(.A0 (n_4529), .A1 (n_8948), .B0 (n_7666), .Y (n_8998)); + OAI21X1 g33860(.A0 (n_4309), .A1 (n_9043), .B0 (n_7665), .Y (n_8996)); + OAI21X1 g33861(.A0 (n_4536), .A1 (n_9010), .B0 (n_8145), .Y (n_8995)); + OAI21X1 g33862(.A0 (n_4538), .A1 (n_9034), .B0 (n_7664), .Y (n_8993)); + OAI21X1 g33863(.A0 (n_4541), .A1 (n_9034), .B0 (n_7663), .Y (n_8992)); + OAI21X1 g33864(.A0 (n_4307), .A1 (n_8981), .B0 (n_7661), .Y (n_8991)); + OAI21X1 g33865(.A0 (n_4546), .A1 (n_9034), .B0 (n_7660), .Y (n_8990)); + OAI21X1 g33866(.A0 (n_4339), .A1 (n_9043), .B0 (n_7659), .Y (n_8989)); + OAI21X1 g33867(.A0 (n_4366), .A1 (n_8948), .B0 (n_7658), .Y (n_8988)); + OAI21X1 g33868(.A0 (n_4305), .A1 (n_8948), .B0 (n_7657), .Y (n_8987)); + OAI21X1 g33869(.A0 (n_4292), .A1 (n_9010), .B0 (n_7656), .Y (n_8986)); + OAI21X1 g33870(.A0 (n_4294), .A1 (n_9010), .B0 (n_7655), .Y (n_8985)); + OAI21X1 g33871(.A0 (n_4303), .A1 (n_9055), .B0 (n_7654), .Y (n_8984)); + OAI21X1 g33872(.A0 (n_4875), .A1 (n_8981), .B0 (n_7653), .Y (n_8983)); + OAI21X1 g33873(.A0 (n_4888), .A1 (n_8981), .B0 (n_7652), .Y (n_8982)); + OAI21X1 g33874(.A0 (n_4907), .A1 (n_8981), .B0 (n_7650), .Y (n_8980)); + OAI21X1 g33875(.A0 (n_4887), .A1 (n_8981), .B0 (n_7649), .Y (n_8979)); + OAI21X1 g33876(.A0 (n_4874), .A1 (n_8976), .B0 (n_7648), .Y (n_8978)); + OAI21X1 g33877(.A0 (n_4886), .A1 (n_8976), .B0 (n_7647), .Y (n_8977)); + OAI21X1 g33878(.A0 (n_4949), .A1 (n_8976), .B0 (n_7646), .Y (n_8975)); + OAI21X1 g33879(.A0 (n_4962), .A1 (n_8976), .B0 (n_7645), .Y (n_8974)); + OAI21X1 g33880(.A0 (n_5076), .A1 (n_8971), .B0 (n_7644), .Y (n_8973)); + OAI21X1 g33881(.A0 (n_4952), .A1 (n_8971), .B0 (n_7643), .Y (n_8972)); + OAI21X1 g33882(.A0 (n_5057), .A1 (n_8971), .B0 (n_7642), .Y (n_8970)); + OAI21X1 g33883(.A0 (n_4884), .A1 (n_8971), .B0 (n_7641), .Y (n_8969)); + OAI21X1 g33884(.A0 (n_5159), .A1 (n_9038), .B0 (n_7640), .Y (n_8968)); + OAI21X1 g33885(.A0 (n_4883), .A1 (n_9038), .B0 (n_7639), .Y (n_8967)); + OAI21X1 g33886(.A0 (n_5073), .A1 (n_9038), .B0 (n_7638), .Y (n_8965)); + OAI21X1 g33887(.A0 (n_4882), .A1 (n_9038), .B0 (n_7637), .Y (n_8964)); + OAI21X1 g33888(.A0 (n_4898), .A1 (n_8961), .B0 (n_7636), .Y (n_8963)); + OAI21X1 g33889(.A0 (n_4881), .A1 (n_8961), .B0 (n_7635), .Y (n_8962)); + OAI21X1 g33890(.A0 (n_4862), .A1 (n_8958), .B0 (n_7634), .Y (n_8960)); + OAI21X1 g33891(.A0 (n_4959), .A1 (n_8958), .B0 (n_7633), .Y (n_8959)); + OAI21X1 g33892(.A0 (n_4876), .A1 (n_8958), .B0 (n_7632), .Y (n_8957)); + OAI21X1 g33893(.A0 (n_4880), .A1 (n_8958), .B0 (n_7631), .Y (n_8956)); + OAI21X1 g33894(.A0 (n_4909), .A1 (n_8961), .B0 (n_7630), .Y (n_8955)); + OAI21X1 g33895(.A0 (n_4879), .A1 (n_8961), .B0 (n_7628), .Y (n_8954)); + OAI21X1 g33896(.A0 (n_4912), .A1 (n_8951), .B0 (n_7627), .Y (n_8953)); + OAI21X1 g33897(.A0 (n_4878), .A1 (n_8951), .B0 (n_7626), .Y (n_8952)); + OAI21X1 g33898(.A0 (n_4957), .A1 (n_8948), .B0 (n_7625), .Y (n_8950)); + OAI21X1 g33899(.A0 (n_4931), .A1 (n_8948), .B0 (n_7624), .Y (n_8949)); + OAI21X1 g33900(.A0 (n_4885), .A1 (n_8951), .B0 (n_7623), .Y (n_8947)); + OAI21X1 g33901(.A0 (n_4956), .A1 (n_8951), .B0 (n_7622), .Y (n_8946)); + OAI21X1 g33902(.A0 (n_5146), .A1 (n_8948), .B0 (n_7621), .Y (n_8945)); + OAI21X1 g33903(.A0 (n_4877), .A1 (n_8948), .B0 (n_7620), .Y (n_8944)); + OAI21X1 g33904(.A0 (n_4484), .A1 (n_8856), .B0 (n_7617), .Y (n_8943)); + OAI21X1 g33905(.A0 (n_4412), .A1 (n_8453), .B0 (n_7982), .Y (n_8941)); + OAI21X1 g33906(.A0 (n_4329), .A1 (n_8891), .B0 (n_7615), .Y (n_8940)); + OAI21X1 g33907(.A0 (n_4288), .A1 (n_8449), .B0 (n_7614), .Y (n_8939)); + OAI21X1 g33908(.A0 (n_4388), .A1 (n_8449), .B0 (n_7948), .Y (n_8938)); + OAI21X1 g33909(.A0 (n_4287), .A1 (n_8457), .B0 (n_7613), .Y (n_8936)); + OAI21X1 g33910(.A0 (n_4391), .A1 (n_8933), .B0 (n_7612), .Y (n_8935)); + OAI21X1 g33911(.A0 (n_4286), .A1 (n_8933), .B0 (n_7611), .Y (n_8934)); + OAI21X1 g33912(.A0 (n_4380), .A1 (n_8930), .B0 (n_7839), .Y (n_8932)); + OAI21X1 g33913(.A0 (n_4285), .A1 (n_8930), .B0 (n_7610), .Y (n_8931)); + OAI21X1 g33914(.A0 (n_4383), .A1 (n_8933), .B0 (n_7608), .Y (n_8929)); + OAI21X1 g33915(.A0 (n_4284), .A1 (n_8933), .B0 (n_7606), .Y (n_8928)); + OAI21X1 g33916(.A0 (n_4385), .A1 (n_8868), .B0 (n_7945), .Y (n_8926)); + OAI21X1 g33917(.A0 (n_4283), .A1 (n_8891), .B0 (n_7605), .Y (n_8925)); + OAI21X1 g33918(.A0 (n_4386), .A1 (n_8457), .B0 (n_7604), .Y (n_8924)); + OAI21X1 g33919(.A0 (n_4282), .A1 (n_8457), .B0 (n_7603), .Y (n_8922)); + OAI21X1 g33920(.A0 (n_4397), .A1 (n_8933), .B0 (n_7949), .Y (n_8921)); + OAI21X1 g33921(.A0 (n_4281), .A1 (n_8891), .B0 (n_7602), .Y (n_8920)); + OAI21X1 g33922(.A0 (n_4400), .A1 (n_8891), .B0 (n_7601), .Y (n_8918)); + OAI21X1 g33923(.A0 (n_4870), .A1 (n_8911), .B0 (n_7600), .Y (n_8917)); + OAI21X1 g33924(.A0 (n_4280), .A1 (n_8438), .B0 (n_7599), .Y (n_8916)); + AOI22X1 g31738(.A0 (n_7449), .A1 (n_7531), .B0 (n_700), .B1 (n_7379), + .Y (n_8915)); + OAI21X1 g33925(.A0 (n_4382), .A1 (n_8438), .B0 (n_7598), .Y (n_8914)); + OAI21X1 g33926(.A0 (n_4869), .A1 (n_8911), .B0 (n_7597), .Y (n_8912)); + OAI21X1 g33927(.A0 (n_4290), .A1 (n_8930), .B0 (n_7564), .Y (n_8910)); + AOI22X1 g31739(.A0 (n_7447), .A1 (n_7528), .B0 (n_569), .B1 (n_7378), + .Y (n_8909)); + OAI21X1 g33928(.A0 (n_4868), .A1 (n_8911), .B0 (n_7957), .Y (n_8908)); + OAI21X1 g33929(.A0 (n_4279), .A1 (n_8930), .B0 (n_7595), .Y (n_8907)); + OAI21X1 g33930(.A0 (n_4393), .A1 (n_8898), .B0 (n_7594), .Y (n_8906)); + OAI21X1 g33931(.A0 (n_5144), .A1 (n_8911), .B0 (n_7593), .Y (n_8905)); + OAI21X1 g33932(.A0 (n_3841), .A1 (n_8449), .B0 (n_8165), .Y (n_8903)); + OAI21X1 g33933(.A0 (n_4402), .A1 (n_8464), .B0 (n_8124), .Y (n_8902)); + OAI21X1 g33934(.A0 (n_5143), .A1 (n_8856), .B0 (n_7591), .Y (n_8901)); + OAI21X1 g33935(.A0 (n_4503), .A1 (n_8894), .B0 (n_7590), .Y (n_8900)); + OAI21X1 g33936(.A0 (n_4302), .A1 (n_8898), .B0 (n_7726), .Y (n_8899)); + OAI21X1 g33937(.A0 (n_4913), .A1 (n_8097), .B0 (n_7725), .Y (n_8897)); + OAI21X1 g33938(.A0 (n_4274), .A1 (n_8898), .B0 (n_7587), .Y (n_8896)); + OAI21X1 g33939(.A0 (n_4275), .A1 (n_8894), .B0 (n_7586), .Y (n_8895)); + OAI21X1 g33940(.A0 (n_4866), .A1 (n_8856), .B0 (n_7585), .Y (n_8893)); + OAI21X1 g33941(.A0 (n_4328), .A1 (n_8891), .B0 (n_7584), .Y (n_8892)); + OAI21X1 g33942(.A0 (n_4273), .A1 (n_8433), .B0 (n_7583), .Y (n_8890)); + OAI21X1 g33943(.A0 (n_4865), .A1 (n_8856), .B0 (n_7791), .Y (n_8888)); + OAI21X1 g33944(.A0 (n_4331), .A1 (n_8433), .B0 (n_7805), .Y (n_8886)); + OAI21X1 g33945(.A0 (n_4344), .A1 (n_8464), .B0 (n_7582), .Y (n_8885)); + OAI21X1 g33946(.A0 (n_4963), .A1 (n_8440), .B0 (n_7581), .Y (n_8883)); + OAI21X1 g33947(.A0 (n_4350), .A1 (n_8433), .B0 (n_8125), .Y (n_8882)); + OAI21X1 g33948(.A0 (n_4494), .A1 (n_8438), .B0 (n_7579), .Y (n_8881)); + OAI21X1 g33949(.A0 (n_4864), .A1 (n_8911), .B0 (n_7578), .Y (n_8880)); + OAI21X1 g33950(.A0 (n_4495), .A1 (n_8438), .B0 (n_7577), .Y (n_8879)); + OAI21X1 g33951(.A0 (n_4497), .A1 (n_8898), .B0 (n_7576), .Y (n_8878)); + OAI21X1 g33952(.A0 (n_4500), .A1 (n_8898), .B0 (n_8076), .Y (n_8876)); + OAI21X1 g33953(.A0 (n_4272), .A1 (n_8898), .B0 (n_7574), .Y (n_8875)); + OAI21X1 g33954(.A0 (n_4861), .A1 (n_8911), .B0 (n_7947), .Y (n_8874)); + OAI21X1 g33955(.A0 (n_4270), .A1 (n_8891), .B0 (n_7580), .Y (n_8872)); + OAI21X1 g33956(.A0 (n_4278), .A1 (n_8868), .B0 (n_7573), .Y (n_8871)); + OAI21X1 g33957(.A0 (n_4872), .A1 (n_8911), .B0 (n_7572), .Y (n_8870)); + OAI21X1 g33958(.A0 (n_4291), .A1 (n_8868), .B0 (n_7616), .Y (n_8869)); + OAI21X1 g33959(.A0 (n_4396), .A1 (n_8868), .B0 (n_7571), .Y (n_8867)); + OAI21X1 g33960(.A0 (n_4860), .A1 (n_8856), .B0 (n_7570), .Y (n_8866)); + OAI21X1 g33961(.A0 (n_4298), .A1 (n_8868), .B0 (n_7700), .Y (n_8865)); + OAI21X1 g33962(.A0 (n_4390), .A1 (n_8453), .B0 (n_7569), .Y (n_8864)); + OAI21X1 g33963(.A0 (n_4304), .A1 (n_8891), .B0 (n_7662), .Y (n_8862)); + OAI21X1 g33964(.A0 (n_4271), .A1 (n_8453), .B0 (n_7567), .Y (n_8861)); + OAI21X1 g33965(.A0 (n_4857), .A1 (n_8097), .B0 (n_7694), .Y (n_8860)); + OAI21X1 g33966(.A0 (n_4326), .A1 (n_8453), .B0 (n_7697), .Y (n_8859)); + OAI21X1 g33967(.A0 (n_4321), .A1 (n_8449), .B0 (n_7566), .Y (n_8858)); + OAI21X1 g33968(.A0 (n_5116), .A1 (n_8856), .B0 (n_7565), .Y (n_8857)); + OAI21X1 g33969(.A0 (n_4434), .A1 (n_8449), .B0 (n_7977), .Y (n_8855)); + OAI21X1 g33970(.A0 (n_4477), .A1 (n_8868), .B0 (n_7563), .Y (n_8854)); + OAI21X1 g33971(.A0 (n_4856), .A1 (n_8856), .B0 (n_7562), .Y (n_8852)); + OAI21X1 g33972(.A0 (n_4479), .A1 (n_8868), .B0 (n_7561), .Y (n_8851)); + OAI21X1 g33973(.A0 (n_4482), .A1 (n_8457), .B0 (n_7560), .Y (n_8850)); + OAI21X1 g33974(.A0 (n_4483), .A1 (n_8933), .B0 (n_8062), .Y (n_8849)); + AOI21X1 g31777(.A0 (n_8847), .A1 (n_7532), .B0 (n_7527), .Y (n_8848)); + OAI21X1 g33975(.A0 (n_5160), .A1 (n_8393), .B0 (n_8068), .Y (n_8846)); + OAI21X1 g33976(.A0 (n_4487), .A1 (n_8933), .B0 (n_8067), .Y (n_8845)); + AOI21X1 g31778(.A0 (n_8843), .A1 (n_7529), .B0 (n_7525), .Y (n_8844)); + MX2X1 g33977(.A (\u3_mem[0]_112 ), .B (n_3834), .S0 (n_8700), .Y + (n_8842)); + MX2X1 g33978(.A (\u3_mem[0]_118 ), .B (n_3584), .S0 (n_8700), .Y + (n_8841)); + MX2X1 g33979(.A (\u3_mem[0]_109 ), .B (n_3823), .S0 (n_8700), .Y + (n_8839)); + MX2X1 g33981(.A (\u4_mem[0]_100 ), .B (n_3802), .S0 (n_7499), .Y + (n_8838)); + MX2X1 g33982(.A (\u4_mem[0] ), .B (n_3803), .S0 (n_7499), .Y + (n_8837)); + MX2X1 g33983(.A (\u4_mem[0]_101 ), .B (n_3801), .S0 (n_7499), .Y + (n_8836)); + MX2X1 g33984(.A (\u4_mem[0]_102 ), .B (n_3799), .S0 (n_7499), .Y + (n_8835)); + MX2X1 g33987(.A (\u4_mem[0]_105 ), .B (n_3795), .S0 (n_7499), .Y + (n_8833)); + MX2X1 g33989(.A (\u4_mem[0]_107 ), .B (n_3788), .S0 (n_7499), .Y + (n_8832)); + MX2X1 g33990(.A (\u4_mem[0]_108 ), .B (n_3784), .S0 (n_7499), .Y + (n_8830)); + MX2X1 g33992(.A (\u4_mem[0]_91 ), .B (n_3780), .S0 (n_7499), .Y + (n_8829)); + MX2X1 g33993(.A (\u4_mem[0]_110 ), .B (n_3779), .S0 (n_7499), .Y + (n_8827)); + MX2X1 g33994(.A (\u4_mem[0]_111 ), .B (n_3777), .S0 (n_7499), .Y + (n_8825)); + MX2X1 g33996(.A (\u4_mem[0]_113 ), .B (n_3773), .S0 (n_7499), .Y + (n_8824)); + MX2X1 g33998(.A (\u4_mem[0]_115 ), .B (n_3768), .S0 (n_7499), .Y + (n_8823)); + MX2X1 g33999(.A (\u4_mem[0]_116 ), .B (n_3766), .S0 (n_7499), .Y + (n_8822)); + MX2X1 g34000(.A (\u4_mem[0]_117 ), .B (n_3764), .S0 (n_7499), .Y + (n_8821)); + MX2X1 g34001(.A (\u4_mem[0]_118 ), .B (n_3763), .S0 (n_7499), .Y + (n_8820)); + MX2X1 g34002(.A (\u4_mem[0]_119 ), .B (n_3762), .S0 (n_7499), .Y + (n_8818)); + MX2X1 g34003(.A (\u4_mem[0]_92 ), .B (n_3761), .S0 (n_7499), .Y + (n_8817)); + MX2X1 g34004(.A (\u4_mem[0]_120 ), .B (n_3760), .S0 (n_7499), .Y + (n_8816)); + MX2X1 g34006(.A (\u4_mem[0]_93 ), .B (n_3757), .S0 (n_7499), .Y + (n_8815)); + MX2X1 g34008(.A (\u4_mem[0]_95 ), .B (n_3790), .S0 (n_7499), .Y + (n_8813)); + MX2X1 g34009(.A (\u4_mem[0]_96 ), .B (n_3755), .S0 (n_7499), .Y + (n_8812)); + MX2X1 g34011(.A (\u4_mem[0]_98 ), .B (n_3753), .S0 (n_7499), .Y + (n_8811)); + MX2X1 g34013(.A (\u3_mem[0]_116 ), .B (n_3586), .S0 (n_8700), .Y + (n_8810)); + MX2X1 g34014(.A (\u5_mem[0] ), .B (n_3741), .S0 (n_7496), .Y + (n_8809)); + MX2X1 g34015(.A (\u5_mem[0]_100 ), .B (n_3739), .S0 (n_7496), .Y + (n_8808)); + MX2X1 g34016(.A (\u5_mem[0]_101 ), .B (n_3737), .S0 (n_7496), .Y + (n_8807)); + MX2X1 g34017(.A (\u5_mem[0]_102 ), .B (n_3735), .S0 (n_7496), .Y + (n_8806)); + MX2X1 g34020(.A (\u5_mem[0]_105 ), .B (n_3732), .S0 (n_7496), .Y + (n_8804)); + MX2X1 g34022(.A (\u5_mem[0]_107 ), .B (n_3728), .S0 (n_7496), .Y + (n_8803)); + MX2X1 g34023(.A (\u5_mem[0]_108 ), .B (n_3727), .S0 (n_7496), .Y + (n_8801)); + MX2X1 g34025(.A (\u5_mem[0]_91 ), .B (n_3724), .S0 (n_7496), .Y + (n_8800)); + MX2X1 g34026(.A (\u5_mem[0]_110 ), .B (n_3722), .S0 (n_7496), .Y + (n_8798)); + MX2X1 g34027(.A (\u5_mem[0]_111 ), .B (n_3719), .S0 (n_7496), .Y + (n_8796)); + MX2X1 g34029(.A (\u5_mem[0]_113 ), .B (n_3715), .S0 (n_7496), .Y + (n_8795)); + MX2X1 g34031(.A (\u5_mem[0]_115 ), .B (n_3712), .S0 (n_7496), .Y + (n_8794)); + MX2X1 g34032(.A (\u5_mem[0]_116 ), .B (n_3709), .S0 (n_7496), .Y + (n_8793)); + MX2X1 g34033(.A (\u5_mem[0]_117 ), .B (n_3656), .S0 (n_7496), .Y + (n_8792)); + MX2X1 g34034(.A (\u5_mem[0]_118 ), .B (n_3707), .S0 (n_7496), .Y + (n_8791)); + MX2X1 g34035(.A (\u5_mem[0]_119 ), .B (n_3704), .S0 (n_7496), .Y + (n_8789)); + MX2X1 g34036(.A (\u5_mem[0]_92 ), .B (n_3700), .S0 (n_7496), .Y + (n_8788)); + MX2X1 g34037(.A (\u5_mem[0]_120 ), .B (n_3699), .S0 (n_7496), .Y + (n_8787)); + MX2X1 g34039(.A (\u5_mem[0]_93 ), .B (n_3697), .S0 (n_7496), .Y + (n_8786)); + MX2X1 g34041(.A (\u5_mem[0]_95 ), .B (n_3690), .S0 (n_7496), .Y + (n_8784)); + MX2X1 g34042(.A (\u5_mem[0]_96 ), .B (n_3688), .S0 (n_7496), .Y + (n_8783)); + MX2X1 g34044(.A (\u5_mem[0]_98 ), .B (n_3693), .S0 (n_7496), .Y + (n_8782)); + MX2X1 g34047(.A (\u6_mem[0] ), .B (n_3683), .S0 (n_7505), .Y + (n_8781)); + MX2X1 g34048(.A (\u6_mem[0]_100 ), .B (n_3682), .S0 (n_7505), .Y + (n_8780)); + MX2X1 g34049(.A (\u6_mem[0]_101 ), .B (n_3565), .S0 (n_7505), .Y + (n_8779)); + MX2X1 g34050(.A (\u6_mem[0]_102 ), .B (n_3681), .S0 (n_7505), .Y + (n_8778)); + MX2X1 g34053(.A (\u6_mem[0]_105 ), .B (n_3676), .S0 (n_7505), .Y + (n_8776)); + MX2X1 g34055(.A (\u6_mem[0]_107 ), .B (n_3576), .S0 (n_7505), .Y + (n_8775)); + MX2X1 g34056(.A (\u6_mem[0]_108 ), .B (n_3674), .S0 (n_7505), .Y + (n_8773)); + MX2X1 g34058(.A (\u6_mem[0]_91 ), .B (n_3630), .S0 (n_7505), .Y + (n_8772)); + MX2X1 g34059(.A (\u6_mem[0]_110 ), .B (n_3609), .S0 (n_7505), .Y + (n_8770)); + MX2X1 g34060(.A (\u6_mem[0]_111 ), .B (n_3608), .S0 (n_7505), .Y + (n_8768)); + MX2X1 g34062(.A (\u6_mem[0]_113 ), .B (n_3671), .S0 (n_7505), .Y + (n_8767)); + MX2X1 g34064(.A (\u6_mem[0]_115 ), .B (n_3615), .S0 (n_7505), .Y + (n_8766)); + MX2X1 g34065(.A (\u6_mem[0]_116 ), .B (n_3670), .S0 (n_7505), .Y + (n_8765)); + MX2X1 g34066(.A (\u6_mem[0]_117 ), .B (n_3617), .S0 (n_7505), .Y + (n_8764)); + MX2X1 g34067(.A (\u6_mem[0]_118 ), .B (n_3621), .S0 (n_7505), .Y + (n_8763)); + MX2X1 g34068(.A (\u6_mem[0]_119 ), .B (n_3633), .S0 (n_7505), .Y + (n_8761)); + MX2X1 g34069(.A (\u6_mem[0]_92 ), .B (n_3668), .S0 (n_7505), .Y + (n_8760)); + MX2X1 g34071(.A (\u6_mem[0]_120 ), .B (n_3667), .S0 (n_7505), .Y + (n_8759)); + MX2X1 g34073(.A (\u6_mem[0]_93 ), .B (n_3628), .S0 (n_7505), .Y + (n_8758)); + MX2X1 g34075(.A (\u6_mem[0]_95 ), .B (n_3664), .S0 (n_7505), .Y + (n_8756)); + MX2X1 g34076(.A (\u6_mem[0]_96 ), .B (n_3652), .S0 (n_7505), .Y + (n_8755)); + MX2X1 g34078(.A (\u6_mem[0]_98 ), .B (n_3660), .S0 (n_7505), .Y + (n_8754)); + MX2X1 g34084(.A (\u7_mem[0] ), .B (n_3710), .S0 (n_7493), .Y + (n_8753)); + MX2X1 g34085(.A (\u7_mem[0]_100 ), .B (n_3677), .S0 (n_7493), .Y + (n_8752)); + MX2X1 g34086(.A (\u7_mem[0]_101 ), .B (n_3806), .S0 (n_7493), .Y + (n_8751)); + MX2X1 g34087(.A (\u7_mem[0]_102 ), .B (n_3786), .S0 (n_7493), .Y + (n_8750)); + MX2X1 g34090(.A (\u7_mem[0]_105 ), .B (n_3645), .S0 (n_7493), .Y + (n_8748)); + MX2X1 g34092(.A (\u7_mem[0]_107 ), .B (n_3644), .S0 (n_7493), .Y + (n_8747)); + MX2X1 g34093(.A (\u7_mem[0]_108 ), .B (n_3564), .S0 (n_7493), .Y + (n_8745)); + MX2X1 g34095(.A (\u7_mem[0]_91 ), .B (n_3566), .S0 (n_7493), .Y + (n_8744)); + MX2X1 g34096(.A (\u7_mem[0]_110 ), .B (n_3642), .S0 (n_7493), .Y + (n_8742)); + MX2X1 g34097(.A (\u7_mem[0]_111 ), .B (n_3568), .S0 (n_7493), .Y + (n_8740)); + MX2X1 g34099(.A (\u7_mem[0]_113 ), .B (n_3569), .S0 (n_7493), .Y + (n_8739)); + MX2X1 g34101(.A (\u7_mem[0]_115 ), .B (n_3571), .S0 (n_7493), .Y + (n_8738)); + MX2X1 g34102(.A (\u7_mem[0]_116 ), .B (n_3638), .S0 (n_7493), .Y + (n_8737)); + MX2X1 g34103(.A (\u7_mem[0]_117 ), .B (n_3607), .S0 (n_7493), .Y + (n_8736)); + MX2X1 g34104(.A (\u7_mem[0]_118 ), .B (n_3636), .S0 (n_7493), .Y + (n_8735)); + MX2X1 g34105(.A (\u7_mem[0]_119 ), .B (n_3610), .S0 (n_7493), .Y + (n_8733)); + MX2X1 g34106(.A (\u7_mem[0]_92 ), .B (n_3612), .S0 (n_7493), .Y + (n_8732)); + MX2X1 g34107(.A (\u7_mem[0]_120 ), .B (n_3613), .S0 (n_7493), .Y + (n_8731)); + MX2X1 g34109(.A (\u7_mem[0]_93 ), .B (n_3616), .S0 (n_7493), .Y + (n_8730)); + MX2X1 g34111(.A (\u7_mem[0]_95 ), .B (n_3620), .S0 (n_7493), .Y + (n_8728)); + MX2X1 g34112(.A (\u7_mem[0]_96 ), .B (n_3631), .S0 (n_7493), .Y + (n_8727)); + MX2X1 g34114(.A (\u7_mem[0]_98 ), .B (n_3625), .S0 (n_7493), .Y + (n_8726)); + MX2X1 g34117(.A (\u3_mem[0]_100 ), .B (n_3809), .S0 (n_8700), .Y + (n_8725)); + MX2X1 g34119(.A (\u3_mem[0]_103 ), .B (n_3606), .S0 (n_8700), .Y + (n_8724)); + MX2X1 g34122(.A (\u3_mem[0]_106 ), .B (n_3603), .S0 (n_7423), .Y + (n_8722)); + MX2X1 g34124(.A (\u8_mem[0]_100 ), .B (n_3602), .S0 (n_7490), .Y + (n_8721)); + MX2X1 g34125(.A (\u3_mem[0]_107 ), .B (n_3815), .S0 (n_8700), .Y + (n_8720)); + MX2X1 g34128(.A (\u3_mem[0]_108 ), .B (n_3601), .S0 (n_8700), .Y + (n_8719)); + MX2X1 g34129(.A (\u8_mem[0]_103 ), .B (n_3818), .S0 (n_7490), .Y + (n_8718)); + MX2X1 g34130(.A (\u8_mem[0]_104 ), .B (n_3600), .S0 (n_7490), .Y + (n_8717)); + MX2X1 g34131(.A (\u8_mem[0]_105 ), .B (n_3824), .S0 (n_7490), .Y + (n_8715)); + MX2X1 g34132(.A (\u8_mem[0]_106 ), .B (n_3599), .S0 (n_7490), .Y + (n_8714)); + MX2X1 g34135(.A (\u8_mem[0]_108 ), .B (n_3596), .S0 (n_7490), .Y + (n_8713)); + MX2X1 g34136(.A (\u3_mem[0]_110 ), .B (n_3595), .S0 (n_8700), .Y + (n_8711)); + MX2X1 g34137(.A (\u8_mem[0]_109 ), .B (n_3827), .S0 (n_7490), .Y + (n_8709)); + MX2X1 g34138(.A (\u8_mem[0]_91 ), .B (n_3828), .S0 (n_7490), .Y + (n_8708)); + MX2X1 g34140(.A (\u8_mem[0]_110 ), .B (n_3830), .S0 (n_7490), .Y + (n_8707)); + MX2X1 g34141(.A (\u8_mem[0]_111 ), .B (n_3831), .S0 (n_7490), .Y + (n_8705)); + MX2X1 g34142(.A (\u8_mem[0]_112 ), .B (n_3833), .S0 (n_7490), .Y + (n_8704)); + MX2X1 g34143(.A (\u8_mem[0]_113 ), .B (n_3836), .S0 (n_7490), .Y + (n_8703)); + MX2X1 g34144(.A (\u3_mem[0]_113 ), .B (n_3592), .S0 (n_8700), .Y + (n_8701)); + MX2X1 g34145(.A (\u8_mem[0]_114 ), .B (n_3838), .S0 (n_7490), .Y + (n_8699)); + MX2X1 g34146(.A (\u8_mem[0]_115 ), .B (n_3590), .S0 (n_7490), .Y + (n_8698)); + MX2X1 g34147(.A (\u3_mem[0]_114 ), .B (n_3627), .S0 (n_8700), .Y + (n_8696)); + MX2X1 g34149(.A (\u8_mem[0]_117 ), .B (n_3651), .S0 (n_7490), .Y + (n_8695)); + MX2X1 g34150(.A (\u3_mem[0]_115 ), .B (n_3588), .S0 (n_8700), .Y + (n_8694)); + MX2X1 g34153(.A (\u8_mem[0]_92 ), .B (n_3746), .S0 (n_7490), .Y + (n_8693)); + MX2X1 g34156(.A (\u8_mem[0]_121 ), .B (n_3822), .S0 (n_7490), .Y + (n_8692)); + MX2X1 g34157(.A (\u8_mem[0]_93 ), .B (n_3832), .S0 (n_7490), .Y + (n_8691)); + MX2X1 g34161(.A (\u8_mem[0]_96 ), .B (n_3750), .S0 (n_7490), .Y + (n_8689)); + MX2X1 g34162(.A (\u8_mem[0]_97 ), .B (n_3570), .S0 (n_7490), .Y + (n_8688)); + MX2X1 g34163(.A (\u8_mem[0]_98 ), .B (n_3649), .S0 (n_7490), .Y + (n_8687)); + MX2X1 g34164(.A (\u8_mem[0]_99 ), .B (n_3580), .S0 (n_7490), .Y + (n_8686)); + MX2X1 g34165(.A (\u3_mem[0]_120 ), .B (n_3579), .S0 (n_8700), .Y + (n_8685)); + MX2X1 g34167(.A (\u3_mem[0]_93 ), .B (n_3744), .S0 (n_7423), .Y + (n_8684)); + MX2X1 g34168(.A (\u3_mem[0]_94 ), .B (n_3575), .S0 (n_8700), .Y + (n_8682)); + MX2X1 g34172(.A (\u3_mem[0]_98 ), .B (n_3572), .S0 (n_8700), .Y + (n_8681)); + MX2X1 g34173(.A (\u3_mem[0]_99 ), .B (n_3751), .S0 (n_8700), .Y + (n_8680)); + DFFX1 u14_u7_en_out_l2_reg(.CK (clk_i), .D (n_8679), .Q + (u14_u7_en_out_l2), .QN ()); + NAND3X1 g34877(.A (n_7490), .B (n_1454), .C (n_8182), .Y (n_8678)); + NAND3X1 g34879(.A (n_7499), .B (n_1450), .C (n_991), .Y (n_8677)); + NAND3X1 g34886(.A (n_7496), .B (n_2175), .C (n_9833), .Y (n_8676)); + NAND3X1 g34894(.A (n_8700), .B (n_2157), .C (n_862), .Y (n_8675)); + NAND3X1 g34895(.A (n_7505), .B (n_1972), .C (n_1873), .Y (n_8674)); + NAND3X1 g34897(.A (n_7493), .B (n_2052), .C (n_1481), .Y (n_8673)); + INVX1 g35294(.A (n_11841), .Y (n_9480)); + OR2X1 g35297(.A (n_5839), .B (n_11827), .Y (n_8671)); + INVX1 g35298(.A (n_8670), .Y (n_9479)); + OR2X1 g35301(.A (n_5831), .B (n_11827), .Y (n_8669)); + INVX1 g35302(.A (n_8667), .Y (n_9478)); + OR2X1 g35305(.A (n_2485), .B (n_11827), .Y (n_8666)); + INVX1 g35306(.A (n_8665), .Y (n_9477)); + OR2X1 g35309(.A (n_5827), .B (n_11827), .Y (n_8664)); + INVX1 g35310(.A (n_8663), .Y (n_9476)); + OR2X1 g35313(.A (n_5825), .B (n_11827), .Y (n_8662)); + INVX1 g35314(.A (n_8661), .Y (n_9475)); + OR2X1 g35317(.A (n_11827), .B (n_12585), .Y (n_8660)); + DFFX1 u14_u7_full_empty_r_reg(.CK (clk_i), .D (n_7557), .Q + (u14_u7_full_empty_r), .QN ()); + DFFX1 u13_ac97_rst_force_reg(.CK (clk_i), .D (n_7523), .Q (), .QN + (ac97_rst_force)); + DFFX1 u13_resume_req_reg(.CK (clk_i), .D (n_7522), .Q (resume_req), + .QN ()); + NOR2X1 g32903(.A (n_976), .B (o3_empty), .Y (n_12848)); + NOR2X1 g32905(.A (n_12804), .B (o6_empty), .Y (n_9503)); + NOR2X1 g32907(.A (n_847), .B (o8_empty), .Y (n_9501)); + NOR2X1 g32908(.A (n_977), .B (o9_empty), .Y (n_9499)); + NOR2X1 g32964(.A (o3_empty), .B (n_459), .Y (n_9498)); + NOR2X1 g32966(.A (o6_empty), .B (n_447), .Y (n_9497)); + NOR2X1 g32971(.A (o8_empty), .B (n_5825), .Y (n_9496)); + NOR2X1 g32973(.A (o9_empty), .B (n_12585), .Y (n_9495)); + MX2X1 g33089(.A (n_392), .B (wb_din), .S0 (n_8643), .Y (n_8655)); + MX2X1 g33090(.A (n_56), .B (wb_din_670), .S0 (n_8643), .Y (n_8654)); + MX2X1 g33091(.A (n_138), .B (wb_din_671), .S0 (n_8643), .Y (n_8653)); + MX2X1 g33092(.A (n_338), .B (wb_din_672), .S0 (n_8643), .Y (n_8652)); + MX2X1 g33093(.A (n_179), .B (wb_din_673), .S0 (n_8643), .Y (n_8651)); + MX2X1 g33094(.A (n_177), .B (wb_din_674), .S0 (n_8643), .Y (n_8649)); + MX2X1 g33095(.A (n_170), .B (wb_din_675), .S0 (n_8643), .Y (n_8648)); + MX2X1 g33096(.A (n_227), .B (wb_din_661), .S0 (n_8643), .Y (n_8646)); + MX2X1 g33097(.A (n_306), .B (wb_din_662), .S0 (n_8643), .Y (n_8644)); + MX2X1 g33098(.A (n_130), .B (wb_din_664), .S0 (n_8643), .Y (n_8642)); + MX2X1 g33099(.A (n_71), .B (wb_din_663), .S0 (n_8643), .Y (n_8641)); + MX2X1 g33100(.A (n_311), .B (wb_din_665), .S0 (n_8643), .Y (n_8640)); + MX2X1 g33101(.A (n_149), .B (wb_din_666), .S0 (n_8643), .Y (n_8639)); + MX2X1 g33102(.A (n_357), .B (wb_din_667), .S0 (n_8643), .Y (n_8638)); + MX2X1 g33103(.A (n_231), .B (wb_din_668), .S0 (n_8643), .Y (n_8637)); + MX2X1 g33104(.A (n_112), .B (wb_din_669), .S0 (n_8643), .Y (n_8636)); + MX2X1 g33105(.A (crac_out_861), .B (wb_din_676), .S0 (n_8643), .Y + (n_8635)); + MX2X1 g33106(.A (crac_out_863), .B (wb_din_678), .S0 (n_8643), .Y + (n_8634)); + MX2X1 g33107(.A (crac_out_862), .B (wb_din_677), .S0 (n_8643), .Y + (n_8633)); + MX2X1 g33108(.A (crac_out_864), .B (wb_din_679), .S0 (n_8643), .Y + (n_8631)); + MX2X1 g33109(.A (crac_out_865), .B (wb_din_680), .S0 (n_8643), .Y + (n_8630)); + MX2X1 g33110(.A (crac_out_866), .B (wb_din_681), .S0 (n_8643), .Y + (n_8628)); + MX2X1 g33111(.A (crac_out_867), .B (wb_din_682), .S0 (n_8643), .Y + (n_8627)); + MX2X1 g33112(.A (crac_out_876), .B (wb_din_691), .S0 (n_8643), .Y + (n_8626)); + MX2X1 g33113(.A (n_11564), .B (wb_din), .S0 (n_8611), .Y (n_8624)); + MX2X1 g33114(.A (n_4738), .B (wb_din_670), .S0 (n_8611), .Y (n_8622)); + MX2X1 g33115(.A (n_4690), .B (wb_din_671), .S0 (n_8611), .Y (n_8620)); + MX2X1 g33116(.A (n_4736), .B (wb_din_672), .S0 (n_8611), .Y (n_8618)); + MX2X1 g33117(.A (n_4734), .B (wb_din_673), .S0 (n_8611), .Y (n_8616)); + MX2X1 g33118(.A (n_4687), .B (wb_din_674), .S0 (n_8611), .Y (n_8613)); + MX2X1 g33119(.A (ic1_cfg_1040), .B (wb_din_675), .S0 (n_8611), .Y + (n_8610)); + MX2X1 g33120(.A (n_11772), .B (wb_din_676), .S0 (n_8611), .Y + (n_8608)); + MX2X1 g33121(.A (ic2_cfg_1044), .B (wb_din_677), .S0 (n_8611), .Y + (n_8606)); + MX2X1 g33122(.A (n_4683), .B (wb_din_678), .S0 (n_8611), .Y (n_8604)); + MX2X1 g33123(.A (n_4706), .B (wb_din_679), .S0 (n_8611), .Y (n_8601)); + MX2X1 g33124(.A (ic0_cfg_1024), .B (wb_din_661), .S0 (n_8611), .Y + (n_8599)); + MX2X1 g33125(.A (n_5788), .B (wb_din_680), .S0 (n_8611), .Y (n_8597)); + MX2X1 g33126(.A (n_5588), .B (wb_din_681), .S0 (n_8611), .Y (n_8594)); + MX2X1 g33127(.A (ic2_cfg_1049), .B (wb_din_682), .S0 (n_8611), .Y + (n_8592)); + MX2X1 g33128(.A (ic2_cfg_1050), .B (wb_din_683), .S0 (n_8611), .Y + (n_8589)); + MX2X1 g33129(.A (n_4713), .B (wb_din_662), .S0 (n_8611), .Y (n_8588)); + MX2X1 g33130(.A (n_4710), .B (wb_din_663), .S0 (n_8611), .Y (n_8586)); + MX2X1 g33131(.A (n_4708), .B (wb_din_664), .S0 (n_8611), .Y (n_8584)); + MX2X1 g33132(.A (n_4703), .B (wb_din_665), .S0 (n_8611), .Y (n_8581)); + MX2X1 g33133(.A (n_4699), .B (wb_din_666), .S0 (n_8611), .Y (n_8579)); + MX2X1 g33134(.A (ic0_cfg_1030), .B (wb_din_667), .S0 (n_8611), .Y + (n_8577)); + MX2X1 g33135(.A (n_11600), .B (wb_din_668), .S0 (n_8611), .Y + (n_8575)); + MX2X1 g33136(.A (ic1_cfg_1034), .B (wb_din_669), .S0 (n_8611), .Y + (n_8573)); + MX2X1 g33137(.A (wb_din), .B (n_862), .S0 (n_8538), .Y (n_8571)); + MX2X1 g33138(.A (wb_din_670), .B (oc1_cfg_975), .S0 (n_8538), .Y + (n_8570)); + MX2X1 g33139(.A (wb_din_671), .B (oc1_cfg_976), .S0 (n_8538), .Y + (n_8569)); + MX2X1 g33140(.A (wb_din_672), .B (n_8567), .S0 (n_8538), .Y (n_8568)); + MX2X1 g33141(.A (wb_din_673), .B (n_8565), .S0 (n_8538), .Y (n_8566)); + MX2X1 g33142(.A (wb_din_674), .B (oc1_cfg_979), .S0 (n_8538), .Y + (n_8564)); + MX2X1 g33143(.A (wb_din_675), .B (oc1_cfg_980), .S0 (n_8538), .Y + (n_8563)); + MX2X1 g33144(.A (wb_din_676), .B (n_9833), .S0 (n_8538), .Y (n_8562)); + MX2X1 g33145(.A (wb_din_677), .B (oc2_cfg_984), .S0 (n_8538), .Y + (n_8560)); + MX2X1 g33146(.A (wb_din_678), .B (oc2_cfg_985), .S0 (n_8538), .Y + (n_8558)); + MX2X1 g33147(.A (wb_din_679), .B (oc2_cfg_986), .S0 (n_8538), .Y + (n_8556)); + MX2X1 g33148(.A (wb_din_661), .B (oc0_cfg_964), .S0 (n_8538), .Y + (n_8555)); + MX2X1 g33149(.A (wb_din_680), .B (oc2_cfg_987), .S0 (n_8538), .Y + (n_8554)); + MX2X1 g33150(.A (wb_din_681), .B (n_8550), .S0 (n_8538), .Y (n_8551)); + MX2X1 g33151(.A (wb_din_682), .B (n_3987), .S0 (n_8538), .Y (n_8549)); + MX2X1 g33152(.A (wb_din_683), .B (oc2_cfg_990), .S0 (n_8538), .Y + (n_8548)); + MX2X1 g33153(.A (wb_din_684), .B (n_1873), .S0 (n_8538), .Y (n_8546)); + MX2X1 g33154(.A (wb_din_685), .B (oc3_cfg_994), .S0 (n_8538), .Y + (n_8545)); + MX2X1 g33155(.A (wb_din_686), .B (oc3_cfg_995), .S0 (n_8538), .Y + (n_8543)); + MX2X1 g33156(.A (wb_din_687), .B (oc3_cfg_996), .S0 (n_8538), .Y + (n_8542)); + MX2X1 g33157(.A (wb_din_688), .B (oc3_cfg_997), .S0 (n_8538), .Y + (n_8540)); + MX2X1 g33158(.A (wb_din_689), .B (n_8536), .S0 (n_8538), .Y (n_8537)); + MX2X1 g33159(.A (wb_din_662), .B (oc0_cfg_965), .S0 (n_8538), .Y + (n_8535)); + MX2X1 g33160(.A (wb_din_690), .B (oc3_cfg_999), .S0 (n_8538), .Y + (n_8534)); + MX2X1 g33161(.A (wb_din_691), .B (oc3_cfg_1000), .S0 (n_8538), .Y + (n_8532)); + MX2X1 g33162(.A (wb_din_663), .B (oc0_cfg_966), .S0 (n_8538), .Y + (n_8530)); + MX2X1 g33163(.A (wb_din_664), .B (n_8528), .S0 (n_8538), .Y (n_8529)); + MX2X1 g33164(.A (wb_din_665), .B (n_8526), .S0 (n_8538), .Y (n_8527)); + MX2X1 g33165(.A (wb_din_666), .B (oc0_cfg_969), .S0 (n_8538), .Y + (n_8525)); + MX2X1 g33166(.A (wb_din_667), .B (oc0_cfg_970), .S0 (n_8538), .Y + (n_8524)); + MX2X1 g33167(.A (wb_din_668), .B (n_991), .S0 (n_8538), .Y (n_8523)); + MX2X1 g33168(.A (wb_din_669), .B (oc1_cfg_974), .S0 (n_8538), .Y + (n_8522)); + MX2X1 g33190(.A (\u13_intm_r[0] ), .B (wb_din), .S0 (n_8519), .Y + (n_8521)); + MX2X1 g33191(.A (\u13_intm_r[10] ), .B (wb_din_670), .S0 (n_8519), .Y + (n_8520)); + MX2X1 g33192(.A (\u13_intm_r[11] ), .B (wb_din_671), .S0 (n_8519), .Y + (n_8518)); + MX2X1 g33193(.A (\u13_intm_r[12] ), .B (wb_din_672), .S0 (n_8519), .Y + (n_8517)); + MX2X1 g33194(.A (\u13_intm_r[13] ), .B (wb_din_673), .S0 (n_8519), .Y + (n_8516)); + MX2X1 g33195(.A (\u13_intm_r[14] ), .B (wb_din_674), .S0 (n_8519), .Y + (n_8515)); + MX2X1 g33196(.A (\u13_intm_r[15] ), .B (wb_din_675), .S0 (n_8519), .Y + (n_8514)); + MX2X1 g33197(.A (\u13_intm_r[16] ), .B (wb_din_676), .S0 (n_8519), .Y + (n_8513)); + MX2X1 g33198(.A (\u13_intm_r[17] ), .B (wb_din_677), .S0 (n_8519), .Y + (n_8512)); + MX2X1 g33199(.A (\u13_intm_r[18] ), .B (wb_din_678), .S0 (n_8519), .Y + (n_8511)); + MX2X1 g33200(.A (\u13_intm_r[19] ), .B (wb_din_679), .S0 (n_8519), .Y + (n_8510)); + MX2X1 g33201(.A (\u13_intm_r[1] ), .B (wb_din_661), .S0 (n_8519), .Y + (n_8509)); + MX2X1 g33202(.A (\u13_intm_r[20] ), .B (wb_din_680), .S0 (n_8519), .Y + (n_8508)); + MX2X1 g33203(.A (\u13_intm_r[21] ), .B (wb_din_681), .S0 (n_8519), .Y + (n_8507)); + MX2X1 g33204(.A (\u13_intm_r[22] ), .B (wb_din_682), .S0 (n_8519), .Y + (n_8506)); + MX2X1 g33205(.A (\u13_intm_r[23] ), .B (wb_din_683), .S0 (n_8519), .Y + (n_8505)); + MX2X1 g33206(.A (\u13_intm_r[24] ), .B (wb_din_684), .S0 (n_8519), .Y + (n_8504)); + MX2X1 g33207(.A (\u13_intm_r[25] ), .B (wb_din_685), .S0 (n_8519), .Y + (n_8502)); + MX2X1 g33208(.A (\u13_intm_r[26] ), .B (wb_din_686), .S0 (n_8519), .Y + (n_8500)); + MX2X1 g33209(.A (\u13_intm_r[27] ), .B (wb_din_687), .S0 (n_8519), .Y + (n_8498)); + MX2X1 g33210(.A (\u13_intm_r[28] ), .B (wb_din_688), .S0 (n_8519), .Y + (n_8496)); + MX2X1 g33211(.A (\u13_intm_r[2] ), .B (wb_din_662), .S0 (n_8519), .Y + (n_8494)); + MX2X1 g33212(.A (\u13_intm_r[3] ), .B (wb_din_663), .S0 (n_8519), .Y + (n_8493)); + MX2X1 g33213(.A (\u13_intm_r[4] ), .B (wb_din_664), .S0 (n_8519), .Y + (n_8492)); + MX2X1 g33214(.A (\u13_intm_r[5] ), .B (wb_din_665), .S0 (n_8519), .Y + (n_8491)); + MX2X1 g33215(.A (\u13_intm_r[6] ), .B (wb_din_666), .S0 (n_8519), .Y + (n_8490)); + MX2X1 g33216(.A (\u13_intm_r[7] ), .B (wb_din_667), .S0 (n_8519), .Y + (n_8489)); + MX2X1 g33217(.A (\u13_intm_r[8] ), .B (wb_din_668), .S0 (n_8519), .Y + (n_8488)); + MX2X1 g33218(.A (\u13_intm_r[9] ), .B (wb_din_669), .S0 (n_8519), .Y + (n_8487)); + INVX1 g33223(.A (o4_empty), .Y (n_9541)); + INVX1 g33227(.A (o7_empty), .Y (n_9536)); + INVX1 g33249(.A (u15_crac_we_r), .Y (n_8486)); + DFFX1 \u1_sr_reg[9] (.CK (bit_clk_pad_i), .D (u1_sr_124), .Q + (u1_sr_125), .QN ()); + AOI21X1 g33260(.A0 (n_7458), .A1 (n_4730), .B0 (n_7353), .Y (n_8485)); + AOI21X1 g33389(.A0 (n_1309), .A1 (n_7480), .B0 (n_1260), .Y (n_8484)); + AOI21X1 g33390(.A0 (n_1126), .A1 (n_7479), .B0 (n_1259), .Y (n_8483)); + AOI21X1 g33391(.A0 (n_1120), .A1 (n_7478), .B0 (n_1289), .Y (n_8482)); + AOI22X1 g33395(.A0 (n_2487), .A1 (n_7490), .B0 (n_7976), .B1 + (\u8_wp[2] ), .Y (n_8481)); + AOI22X1 g33396(.A0 (n_4333), .A1 (n_7423), .B0 (n_8101), .B1 + (\u3_wp[2] ), .Y (n_8480)); + AOI22X1 g33397(.A0 (n_4395), .A1 (n_7499), .B0 (n_7984), .B1 + (\u4_wp[2] ), .Y (n_8479)); + AOI22X1 g33398(.A0 (n_4349), .A1 (n_7496), .B0 (n_7870), .B1 + (\u5_wp[2] ), .Y (n_8478)); + AOI22X1 g33399(.A0 (n_4389), .A1 (n_7505), .B0 (n_7758), .B1 + (\u6_wp[2] ), .Y (n_8477)); + AOI22X1 g33400(.A0 (n_4299), .A1 (n_7493), .B0 (n_7651), .B1 + (\u7_wp[2] ), .Y (n_8476)); + OAI21X1 g33401(.A0 (n_4489), .A1 (n_8464), .B0 (n_8173), .Y (n_8475)); + OAI21X1 g33402(.A0 (n_5122), .A1 (n_8856), .B0 (n_8172), .Y (n_8474)); + OAI21X1 g33403(.A0 (n_4490), .A1 (n_8894), .B0 (n_8070), .Y (n_8473)); + OAI21X1 g33404(.A0 (n_4492), .A1 (n_8868), .B0 (n_8171), .Y (n_8472)); + OAI21X1 g33405(.A0 (n_5158), .A1 (n_8911), .B0 (n_8169), .Y (n_8471)); + OAI21X1 g33406(.A0 (n_4493), .A1 (n_8933), .B0 (n_8072), .Y (n_8470)); + OAI21X1 g33407(.A0 (n_4530), .A1 (n_8464), .B0 (n_8168), .Y (n_8469)); + OAI21X1 g33408(.A0 (n_3867), .A1 (n_8894), .B0 (n_8154), .Y (n_8468)); + OAI21X1 g33409(.A0 (n_3886), .A1 (n_8894), .B0 (n_8118), .Y (n_8467)); + OAI21X1 g33410(.A0 (n_3851), .A1 (n_8464), .B0 (n_7838), .Y (n_8465)); + OAI21X1 g33411(.A0 (n_5155), .A1 (n_8856), .B0 (n_7607), .Y (n_8463)); + OAI21X1 g33412(.A0 (n_3842), .A1 (n_8930), .B0 (n_7609), .Y (n_8462)); + OAI21X1 g33413(.A0 (n_5154), .A1 (n_8911), .B0 (n_8164), .Y (n_8460)); + OAI21X1 g33414(.A0 (n_3889), .A1 (n_8457), .B0 (n_8163), .Y (n_8459)); + OAI21X1 g33415(.A0 (n_3845), .A1 (n_8457), .B0 (n_8162), .Y (n_8458)); + OAI21X1 g33416(.A0 (n_3884), .A1 (n_8433), .B0 (n_8160), .Y (n_8456)); + OAI21X1 g33417(.A0 (n_5153), .A1 (n_8911), .B0 (n_7618), .Y (n_8455)); + OAI21X1 g33418(.A0 (n_3847), .A1 (n_8453), .B0 (n_7629), .Y (n_8454)); + OAI21X1 g33419(.A0 (n_5152), .A1 (n_8097), .B0 (n_8158), .Y (n_8452)); + OAI21X1 g33420(.A0 (n_3843), .A1 (n_8449), .B0 (n_8157), .Y (n_8450)); + OAI21X1 g33421(.A0 (n_3871), .A1 (n_8449), .B0 (n_8156), .Y (n_8448)); + OAI21X1 g33422(.A0 (n_5151), .A1 (n_8097), .B0 (n_7818), .Y (n_8447)); + OAI21X1 g33423(.A0 (n_3869), .A1 (n_8894), .B0 (n_8047), .Y (n_8446)); + OAI21X1 g33424(.A0 (n_5150), .A1 (n_8440), .B0 (n_8058), .Y (n_8445)); + OAI21X1 g33425(.A0 (n_3888), .A1 (n_8464), .B0 (n_8153), .Y (n_8443)); + OAI21X1 g33426(.A0 (n_3874), .A1 (n_8453), .B0 (n_8152), .Y (n_8442)); + OAI21X1 g33427(.A0 (n_5149), .A1 (n_8440), .B0 (n_8064), .Y (n_8441)); + OAI21X1 g33428(.A0 (n_3878), .A1 (n_8438), .B0 (n_8151), .Y (n_8439)); + OAI21X1 g33429(.A0 (n_3880), .A1 (n_8438), .B0 (n_8150), .Y (n_8437)); + OAI21X1 g33430(.A0 (n_5147), .A1 (n_8097), .B0 (n_8069), .Y (n_8436)); + OAI21X1 g33431(.A0 (n_3881), .A1 (n_8438), .B0 (n_8149), .Y (n_8435)); + OAI21X1 g33432(.A0 (n_3883), .A1 (n_8433), .B0 (n_8148), .Y (n_8434)); + OAI21X1 g33433(.A0 (n_4537), .A1 (n_8101), .B0 (n_8071), .Y (n_8432)); + OAI21X1 g33434(.A0 (n_3885), .A1 (n_8433), .B0 (n_8146), .Y (n_8431)); + OAI21X1 g33435(.A0 (n_4348), .A1 (n_8101), .B0 (n_8144), .Y (n_8430)); + OAI21X1 g33436(.A0 (n_3854), .A1 (n_8930), .B0 (n_8143), .Y (n_8428)); + OAI21X1 g33437(.A0 (n_4534), .A1 (n_8440), .B0 (n_8142), .Y (n_8427)); + OAI21X1 g33438(.A0 (n_3855), .A1 (n_8930), .B0 (n_8140), .Y (n_8426)); + OAI21X1 g33439(.A0 (n_3860), .A1 (n_8433), .B0 (n_8139), .Y (n_8425)); + OAI21X1 g33440(.A0 (n_4532), .A1 (n_8393), .B0 (n_8138), .Y (n_8424)); + OAI21X1 g33441(.A0 (n_3864), .A1 (n_8453), .B0 (n_8137), .Y (n_8422)); + OAI21X1 g33442(.A0 (n_4325), .A1 (n_8856), .B0 (n_8136), .Y (n_8421)); + OAI21X1 g33443(.A0 (n_3856), .A1 (n_8457), .B0 (n_8133), .Y (n_8420)); + OAI21X1 g33444(.A0 (n_3861), .A1 (n_8457), .B0 (n_7833), .Y (n_8419)); + OAI21X1 g33445(.A0 (n_4528), .A1 (n_8911), .B0 (n_8131), .Y (n_8418)); + OAI21X1 g33446(.A0 (n_3877), .A1 (n_8449), .B0 (n_7836), .Y (n_8416)); + OAI21X1 g33447(.A0 (n_4296), .A1 (n_8097), .B0 (n_7723), .Y (n_8415)); + OAI21X1 g33448(.A0 (n_4277), .A1 (n_8898), .B0 (n_8126), .Y (n_8413)); + OAI21X1 g33449(.A0 (n_4486), .A1 (n_8856), .B0 (n_8129), .Y (n_8412)); + OAI21X1 g33450(.A0 (n_4347), .A1 (n_8911), .B0 (n_8127), .Y (n_8411)); + OAI21X1 g33451(.A0 (n_4526), .A1 (n_8097), .B0 (n_7724), .Y (n_8410)); + OAI21X1 g33452(.A0 (n_5156), .A1 (n_8911), .B0 (n_8167), .Y (n_8408)); + OAI21X1 g33453(.A0 (n_4474), .A1 (n_8393), .B0 (n_7946), .Y (n_8407)); + OAI21X1 g33454(.A0 (n_4524), .A1 (n_8911), .B0 (n_8060), .Y (n_8406)); + OAI21X1 g33455(.A0 (n_4320), .A1 (n_8101), .B0 (n_8123), .Y (n_8405)); + OAI21X1 g33456(.A0 (n_4522), .A1 (n_8097), .B0 (n_8121), .Y (n_8404)); + OAI21X1 g33457(.A0 (n_4341), .A1 (n_8856), .B0 (n_8120), .Y (n_8403)); + OAI21X1 g33458(.A0 (n_4521), .A1 (n_8101), .B0 (n_8119), .Y (n_8402)); + OAI21X1 g33459(.A0 (n_4520), .A1 (n_8440), .B0 (n_8117), .Y (n_8401)); + OAI21X1 g33460(.A0 (n_4518), .A1 (n_8097), .B0 (n_8116), .Y (n_8400)); + OAI21X1 g33461(.A0 (n_4392), .A1 (n_8393), .B0 (n_8115), .Y (n_8399)); + OAI21X1 g33462(.A0 (n_4480), .A1 (n_8097), .B0 (n_8114), .Y (n_8398)); + OAI21X1 g33463(.A0 (n_4394), .A1 (n_8097), .B0 (n_8113), .Y (n_8397)); + OAI21X1 g33464(.A0 (n_4293), .A1 (n_8856), .B0 (n_8112), .Y (n_8396)); + OAI21X1 g33465(.A0 (n_4324), .A1 (n_8911), .B0 (n_8110), .Y (n_8395)); + OAI21X1 g33466(.A0 (n_4513), .A1 (n_8393), .B0 (n_8109), .Y (n_8394)); + OAI21X1 g33467(.A0 (n_4512), .A1 (n_8440), .B0 (n_8107), .Y (n_8392)); + OAI21X1 g33468(.A0 (n_4517), .A1 (n_8393), .B0 (n_8106), .Y (n_8391)); + OAI21X1 g33469(.A0 (n_4511), .A1 (n_8440), .B0 (n_8105), .Y (n_8390)); + OAI21X1 g33470(.A0 (n_4859), .A1 (n_8387), .B0 (n_8104), .Y (n_8389)); + OAI21X1 g33471(.A0 (n_4873), .A1 (n_8387), .B0 (n_8102), .Y (n_8388)); + OAI21X1 g33472(.A0 (n_4871), .A1 (n_9022), .B0 (n_8100), .Y (n_8386)); + OAI21X1 g33473(.A0 (n_4889), .A1 (n_8383), .B0 (n_8099), .Y (n_8385)); + OAI21X1 g33474(.A0 (n_5139), .A1 (n_8383), .B0 (n_8098), .Y (n_8384)); + OAI21X1 g33475(.A0 (n_4955), .A1 (n_8380), .B0 (n_8096), .Y (n_8382)); + OAI21X1 g33476(.A0 (n_5137), .A1 (n_8380), .B0 (n_8095), .Y (n_8381)); + OAI21X1 g33477(.A0 (n_5136), .A1 (n_8380), .B0 (n_8094), .Y (n_8379)); + OAI21X1 g33478(.A0 (n_5135), .A1 (n_8380), .B0 (n_8093), .Y (n_8378)); + OAI21X1 g33479(.A0 (n_4910), .A1 (n_8375), .B0 (n_8092), .Y (n_8377)); + OAI21X1 g33480(.A0 (n_5134), .A1 (n_8375), .B0 (n_8091), .Y (n_8376)); + OAI21X1 g33481(.A0 (n_5132), .A1 (n_8372), .B0 (n_8090), .Y (n_8374)); + OAI21X1 g33482(.A0 (n_4958), .A1 (n_8372), .B0 (n_8088), .Y (n_8373)); + OAI21X1 g33483(.A0 (n_5093), .A1 (n_8369), .B0 (n_8087), .Y (n_8371)); + OAI21X1 g33484(.A0 (n_5131), .A1 (n_8369), .B0 (n_8061), .Y (n_8370)); + OAI21X1 g33485(.A0 (n_5120), .A1 (n_8372), .B0 (n_8063), .Y (n_8368)); + OAI21X1 g33486(.A0 (n_5129), .A1 (n_8372), .B0 (n_8085), .Y (n_8367)); + OAI21X1 g33487(.A0 (n_5123), .A1 (n_8369), .B0 (n_8084), .Y (n_8366)); + OAI21X1 g33488(.A0 (n_3887), .A1 (n_8894), .B0 (n_8080), .Y (n_8365)); + OAI21X1 g33489(.A0 (n_5142), .A1 (n_8369), .B0 (n_8083), .Y (n_8364)); + OAI21X1 g33490(.A0 (n_5066), .A1 (n_8383), .B0 (n_8081), .Y (n_8363)); + OAI21X1 g33491(.A0 (n_5127), .A1 (n_8383), .B0 (n_8082), .Y (n_8362)); + OAI21X1 g33492(.A0 (n_5130), .A1 (n_8375), .B0 (n_7619), .Y (n_8361)); + OAI21X1 g33493(.A0 (n_4953), .A1 (n_8375), .B0 (n_8079), .Y (n_8360)); + OAI21X1 g33494(.A0 (n_4954), .A1 (n_8357), .B0 (n_8057), .Y (n_8359)); + OAI21X1 g33495(.A0 (n_5125), .A1 (n_8357), .B0 (n_8065), .Y (n_8358)); + OAI21X1 g33496(.A0 (n_4863), .A1 (n_8097), .B0 (n_7575), .Y (n_8356)); + OAI21X1 g33497(.A0 (n_5121), .A1 (n_8357), .B0 (n_8075), .Y (n_8355)); + OAI21X1 g33498(.A0 (n_5124), .A1 (n_8357), .B0 (n_8074), .Y (n_8354)); + OAI21X1 g33499(.A0 (n_4908), .A1 (n_8387), .B0 (n_8073), .Y (n_8353)); + OAI21X1 g33500(.A0 (n_5126), .A1 (n_8387), .B0 (n_7834), .Y (n_8352)); + OAI21X1 g33501(.A0 (n_4527), .A1 (n_8894), .B0 (n_7592), .Y (n_8351)); + OAI21X1 g33502(.A0 (n_3872), .A1 (n_8464), .B0 (n_8147), .Y (n_8350)); + OAI21X1 g33503(.A0 (n_4485), .A1 (n_8891), .B0 (n_7558), .Y (n_8349)); + OAI21X1 g33504(.A0 (n_4960), .A1 (n_9022), .B0 (n_8086), .Y (n_8348)); + OAI21X1 g33505(.A0 (n_4855), .A1 (n_8911), .B0 (n_7559), .Y (n_8347)); + OAI21X1 g33506(.A0 (n_4345), .A1 (n_8393), .B0 (n_8066), .Y (n_8346)); + OAI21X1 g33507(.A0 (n_4473), .A1 (n_8333), .B0 (n_8056), .Y (n_8345)); + OAI21X1 g33508(.A0 (n_4381), .A1 (n_9349), .B0 (n_8055), .Y (n_8344)); + OAI21X1 g33509(.A0 (n_4472), .A1 (n_8333), .B0 (n_8054), .Y (n_8343)); + OAI21X1 g33510(.A0 (n_4470), .A1 (n_9346), .B0 (n_8052), .Y (n_8342)); + OAI21X1 g33511(.A0 (n_4469), .A1 (n_8333), .B0 (n_8051), .Y (n_8341)); + OAI21X1 g33512(.A0 (n_4467), .A1 (n_8333), .B0 (n_8049), .Y (n_8340)); + OAI21X1 g33513(.A0 (n_4465), .A1 (n_9349), .B0 (n_8048), .Y (n_8338)); + OAI21X1 g33514(.A0 (n_4475), .A1 (n_8333), .B0 (n_8046), .Y (n_8336)); + OAI21X1 g33515(.A0 (n_4464), .A1 (n_8333), .B0 (n_8045), .Y (n_8334)); + OAI21X1 g33516(.A0 (n_4463), .A1 (n_9346), .B0 (n_8044), .Y (n_8332)); + OAI21X1 g33517(.A0 (n_4462), .A1 (n_9346), .B0 (n_8042), .Y (n_8330)); + OAI21X1 g33518(.A0 (n_4461), .A1 (n_8333), .B0 (n_8041), .Y (n_8329)); + OAI21X1 g33519(.A0 (n_4460), .A1 (n_9326), .B0 (n_8039), .Y (n_8328)); + OAI21X1 g33520(.A0 (n_4459), .A1 (n_8333), .B0 (n_8037), .Y (n_8327)); + OAI21X1 g33521(.A0 (n_4458), .A1 (n_9349), .B0 (n_8036), .Y (n_8326)); + OAI21X1 g33522(.A0 (n_4456), .A1 (n_9349), .B0 (n_8035), .Y (n_8325)); + OAI21X1 g33523(.A0 (n_4478), .A1 (n_9349), .B0 (n_8034), .Y (n_8324)); + OAI21X1 g33524(.A0 (n_4455), .A1 (n_8318), .B0 (n_8033), .Y (n_8322)); + OAI21X1 g33525(.A0 (n_4454), .A1 (n_8333), .B0 (n_8032), .Y (n_8321)); + OAI21X1 g33526(.A0 (n_4453), .A1 (n_9333), .B0 (n_8031), .Y (n_8320)); + OAI21X1 g33527(.A0 (n_4508), .A1 (n_8318), .B0 (n_8030), .Y (n_8319)); + OAI21X1 g33528(.A0 (n_4514), .A1 (n_9333), .B0 (n_8029), .Y (n_8317)); + OAI21X1 g33529(.A0 (n_4451), .A1 (n_8333), .B0 (n_8028), .Y (n_8315)); + OAI21X1 g33530(.A0 (n_4450), .A1 (n_9326), .B0 (n_8027), .Y (n_8313)); + OAI21X1 g33531(.A0 (n_4449), .A1 (n_8333), .B0 (n_8026), .Y (n_8311)); + OAI21X1 g33532(.A0 (n_4448), .A1 (n_8333), .B0 (n_8025), .Y (n_8310)); + OAI21X1 g33533(.A0 (n_4447), .A1 (n_9336), .B0 (n_8024), .Y (n_8309)); + OAI21X1 g33534(.A0 (n_4446), .A1 (n_9336), .B0 (n_8023), .Y (n_8308)); + OAI21X1 g33535(.A0 (n_4297), .A1 (n_8333), .B0 (n_8022), .Y (n_8306)); + OAI21X1 g33536(.A0 (n_4445), .A1 (n_8318), .B0 (n_8021), .Y (n_8305)); + OAI21X1 g33537(.A0 (n_4444), .A1 (n_8333), .B0 (n_8020), .Y (n_8304)); + OAI21X1 g33538(.A0 (n_4295), .A1 (n_9349), .B0 (n_8019), .Y (n_8303)); + OAI21X1 g33539(.A0 (n_4442), .A1 (n_8333), .B0 (n_8018), .Y (n_8302)); + OAI21X1 g33540(.A0 (n_4441), .A1 (n_9349), .B0 (n_8017), .Y (n_8301)); + OAI21X1 g33541(.A0 (n_4440), .A1 (n_8318), .B0 (n_8016), .Y (n_8300)); + OAI21X1 g33542(.A0 (n_4310), .A1 (n_8318), .B0 (n_8015), .Y (n_8298)); + OAI21X1 g33543(.A0 (n_4438), .A1 (n_9349), .B0 (n_8014), .Y (n_8297)); + OAI21X1 g33544(.A0 (n_4436), .A1 (n_8333), .B0 (n_8013), .Y (n_8296)); + OAI21X1 g33545(.A0 (n_4435), .A1 (n_8318), .B0 (n_8012), .Y (n_8295)); + OAI21X1 g33546(.A0 (n_4433), .A1 (n_8333), .B0 (n_8011), .Y (n_8294)); + OAI21X1 g33547(.A0 (n_4432), .A1 (n_8333), .B0 (n_8010), .Y (n_8293)); + OAI21X1 g33548(.A0 (n_4431), .A1 (n_8333), .B0 (n_8009), .Y (n_8291)); + OAI21X1 g33549(.A0 (n_4430), .A1 (n_9333), .B0 (n_8008), .Y (n_8290)); + OAI21X1 g33550(.A0 (n_4429), .A1 (n_8333), .B0 (n_8007), .Y (n_8289)); + OAI21X1 g33551(.A0 (n_4327), .A1 (n_8318), .B0 (n_8006), .Y (n_8287)); + OAI21X1 g33552(.A0 (n_4428), .A1 (n_9333), .B0 (n_8005), .Y (n_8286)); + OAI21X1 g33553(.A0 (n_4427), .A1 (n_9346), .B0 (n_8004), .Y (n_8285)); + OAI21X1 g33554(.A0 (n_4426), .A1 (n_8333), .B0 (n_8003), .Y (n_8284)); + OAI21X1 g33555(.A0 (n_4425), .A1 (n_8333), .B0 (n_8002), .Y (n_8283)); + OAI21X1 g33556(.A0 (n_4423), .A1 (n_8333), .B0 (n_8001), .Y (n_8282)); + OAI21X1 g33557(.A0 (n_4422), .A1 (n_9326), .B0 (n_8000), .Y (n_8281)); + OAI21X1 g33558(.A0 (n_4421), .A1 (n_8333), .B0 (n_7999), .Y (n_8280)); + OAI21X1 g33559(.A0 (n_4420), .A1 (n_8333), .B0 (n_7998), .Y (n_8278)); + OAI21X1 g33560(.A0 (n_4419), .A1 (n_8333), .B0 (n_7997), .Y (n_8277)); + OAI21X1 g33561(.A0 (n_4418), .A1 (n_8333), .B0 (n_7996), .Y (n_8275)); + OAI21X1 g33562(.A0 (n_4417), .A1 (n_9336), .B0 (n_7995), .Y (n_8274)); + OAI21X1 g33563(.A0 (n_4416), .A1 (n_9326), .B0 (n_7994), .Y (n_8273)); + OAI21X1 g33564(.A0 (n_4414), .A1 (n_9336), .B0 (n_7993), .Y (n_8272)); + OAI21X1 g33565(.A0 (n_4413), .A1 (n_8333), .B0 (n_7992), .Y (n_8271)); + OAI21X1 g33566(.A0 (n_4411), .A1 (n_8333), .B0 (n_7991), .Y (n_8270)); + OAI21X1 g33567(.A0 (n_4410), .A1 (n_8333), .B0 (n_7990), .Y (n_8269)); + OAI21X1 g33568(.A0 (n_4409), .A1 (n_8333), .B0 (n_7989), .Y (n_8268)); + OAI21X1 g33569(.A0 (n_4408), .A1 (n_8333), .B0 (n_7988), .Y (n_8267)); + OAI21X1 g33570(.A0 (n_4407), .A1 (n_8318), .B0 (n_7987), .Y (n_8266)); + OAI21X1 g33571(.A0 (n_5114), .A1 (n_8318), .B0 (n_7986), .Y (n_8265)); + OAI21X1 g33572(.A0 (n_5107), .A1 (n_8318), .B0 (n_7985), .Y (n_8264)); + OAI21X1 g33573(.A0 (n_5105), .A1 (n_8318), .B0 (n_7983), .Y (n_8262)); + OAI21X1 g33574(.A0 (n_5104), .A1 (n_8318), .B0 (n_7981), .Y (n_8261)); + OAI21X1 g33575(.A0 (n_5103), .A1 (n_9349), .B0 (n_7980), .Y (n_8260)); + OAI21X1 g33576(.A0 (n_5099), .A1 (n_9349), .B0 (n_7979), .Y (n_8259)); + MX2X1 g34070(.A (u1_sr_123), .B (in_slt_749), .S0 (out_le_180), .Y + (n_8258)); + MX2X1 g34080(.A (u1_sr_123), .B (in_slt_833), .S0 (out_le_181), .Y + (n_8257)); + MX2X1 g34081(.A (u1_sr_123), .B (in_slt_403), .S0 (out_le_182), .Y + (n_8256)); + MX2X1 g34082(.A (u1_sr_123), .B (in_slt_425), .S0 (out_le_183), .Y + (n_8255)); + MX2X1 g34083(.A (u1_sr_123), .B (in_slt_447), .S0 (out_le_184), .Y + (n_8254)); + MX2X1 g34116(.A (\u3_mem[0] ), .B (n_3808), .S0 (n_7423), .Y + (n_8253)); + MX2X1 g34120(.A (\u3_mem[0]_104 ), .B (n_3813), .S0 (n_7423), .Y + (n_8252)); + MX2X1 g34166(.A (\u3_mem[0]_121 ), .B (n_3577), .S0 (n_7423), .Y + (n_8250)); + MX2X1 g34171(.A (\u3_mem[0]_97 ), .B (n_3654), .S0 (n_7423), .Y + (n_8249)); + DFFX1 u14_u6_en_out_l2_reg(.CK (clk_i), .D (n_9352), .Q (), .QN + (u14_u6_en_out_l2)); + NOR2X1 g34273(.A (\u8_wp[0] ), .B (n_7976), .Y (n_8248)); + NAND2X1 g34306(.A (n_6706), .B (n_7475), .Y (n_8245)); + NAND2X1 g34316(.A (n_6675), .B (n_7459), .Y (n_8244)); + NAND2X1 g34324(.A (n_6705), .B (n_7473), .Y (n_8243)); + NAND2X1 g34326(.A (n_6677), .B (n_7472), .Y (n_8242)); + NOR2X1 g34327(.A (n_1424), .B (n_8141), .Y (n_8241)); + NAND2X1 g34328(.A (n_6676), .B (n_7461), .Y (n_8238)); + NAND2X1 g34331(.A (n_6703), .B (n_7460), .Y (n_8237)); + NAND2X1 g34333(.A (n_6702), .B (n_7471), .Y (n_8236)); + NAND2X1 g34344(.A (n_6738), .B (n_7470), .Y (n_8235)); + NAND2X1 g34347(.A (n_6691), .B (n_7469), .Y (n_8234)); + NAND2X1 g34351(.A (n_6688), .B (n_7467), .Y (n_8233)); + NAND2X1 g34361(.A (n_6687), .B (n_7466), .Y (n_8232)); + NAND2X1 g34368(.A (n_6068), .B (n_7465), .Y (n_8231)); + NAND2X1 g34377(.A (n_6684), .B (n_7464), .Y (n_8230)); + NAND2X1 g34385(.A (n_6683), .B (n_7463), .Y (n_8229)); + NAND2X1 g34393(.A (n_6681), .B (n_7462), .Y (n_8228)); + NOR2X1 g34473(.A (n_1419), .B (n_7984), .Y (n_8227)); + NOR2X1 g34589(.A (n_798), .B (n_7870), .Y (n_8224)); + NOR2X1 g34699(.A (n_1417), .B (n_7758), .Y (n_8221)); + NOR2X1 g34814(.A (n_1421), .B (n_7651), .Y (n_8218)); + MX2X1 g34909(.A (i3_full), .B (u14_u6_full_empty_r), .S0 (n_7389), .Y + (n_8215)); + MX2X1 g34911(.A (i6_full), .B (u14_u8_full_empty_r), .S0 (n_7388), .Y + (n_8213)); + MX2X1 g34916(.A (n_120), .B (u0_slt9_r), .S0 (n_11319), .Y (n_8211)); + INVX1 g35285(.A (n_8210), .Y (n_9359)); + INVX1 g35299(.A (n_7542), .Y (n_8670)); + INVX1 g35303(.A (n_7541), .Y (n_8667)); + INVX1 g35307(.A (n_7539), .Y (n_8665)); + INVX1 g35311(.A (n_7538), .Y (n_8663)); + INVX1 g35315(.A (n_7537), .Y (n_8661)); + DFFX1 \u12_wb_data_o_reg[31] (.CK (clk_i), .D (n_7450), .Q + (wb_data_o[31]), .QN ()); + DFFX1 \u1_slt3_reg[6] (.CK (bit_clk_pad_i), .D (n_7509), .Q + (in_slt_402), .QN ()); + DFFX1 \u1_slt1_reg[6] (.CK (bit_clk_pad_i), .D (n_7507), .Q + (in_slt_748), .QN ()); + DFFX1 \u1_slt2_reg[6] (.CK (bit_clk_pad_i), .D (n_7510), .Q + (in_slt_832), .QN ()); + DFFX1 \u1_slt4_reg[6] (.CK (bit_clk_pad_i), .D (n_7511), .Q + (in_slt_424), .QN ()); + DFFX1 \u12_wb_data_o_reg[23] (.CK (clk_i), .D (n_7482), .Q + (wb_data_o[23]), .QN ()); + DFFX1 \u12_wb_data_o_reg[22] (.CK (clk_i), .D (n_7483), .Q + (wb_data_o[22]), .QN ()); + DFFX1 \u12_wb_data_o_reg[21] (.CK (clk_i), .D (n_7484), .Q + (wb_data_o[21]), .QN ()); + DFFX1 \u12_wb_data_o_reg[16] (.CK (clk_i), .D (n_7488), .Q + (wb_data_o[16]), .QN ()); + DFFX1 \u12_wb_data_o_reg[20] (.CK (clk_i), .D (n_7485), .Q + (wb_data_o[20]), .QN ()); + DFFX1 \u12_wb_data_o_reg[19] (.CK (clk_i), .D (n_7486), .Q + (wb_data_o[19]), .QN ()); + DFFX1 \u12_wb_data_o_reg[17] (.CK (clk_i), .D (n_7487), .Q + (wb_data_o[17]), .QN ()); + DFFX1 \u12_wb_data_o_reg[24] (.CK (clk_i), .D (n_7457), .Q + (wb_data_o[24]), .QN ()); + DFFX1 \u12_wb_data_o_reg[30] (.CK (clk_i), .D (n_7451), .Q + (wb_data_o[30]), .QN ()); + DFFX1 \u12_wb_data_o_reg[28] (.CK (clk_i), .D (n_7453), .Q + (wb_data_o[28]), .QN ()); + DFFX1 \u12_wb_data_o_reg[27] (.CK (clk_i), .D (n_7454), .Q + (wb_data_o[27]), .QN ()); + DFFX1 \u12_wb_data_o_reg[26] (.CK (clk_i), .D (n_7455), .Q + (wb_data_o[26]), .QN ()); + DFFX1 \u12_wb_data_o_reg[29] (.CK (clk_i), .D (n_7452), .Q + (wb_data_o[29]), .QN ()); + DFFX1 \u12_wb_data_o_reg[25] (.CK (clk_i), .D (n_7456), .Q + (wb_data_o[25]), .QN ()); + DFFX1 \u1_slt6_reg[6] (.CK (bit_clk_pad_i), .D (n_7508), .Q + (in_slt_446), .QN ()); + OAI21X1 g32701(.A0 (n_5434), .A1 (n_8208), .B0 (n_8207), .Y (n_8209)); + DFFX1 \u12_wb_data_o_reg[18] (.CK (clk_i), .D (n_7476), .Q + (wb_data_o[18]), .QN ()); + AOI21X1 g32986(.A0 (n_7440), .A1 (n_7441), .B0 (n_8205), .Y (n_8206)); + MX2X1 g33169(.A (wb_din), .B (n_1481), .S0 (n_8202), .Y (n_8204)); + MX2X1 g33170(.A (wb_din_670), .B (oc5_cfg_1015), .S0 (n_8202), .Y + (n_8203)); + MX2X1 g33171(.A (wb_din_671), .B (oc5_cfg_1016), .S0 (n_8202), .Y + (n_8201)); + MX2X1 g33172(.A (wb_din_672), .B (n_8199), .S0 (n_8202), .Y (n_8200)); + MX2X1 g33173(.A (wb_din_673), .B (n_8197), .S0 (n_8202), .Y (n_8198)); + MX2X1 g33174(.A (wb_din_674), .B (n_4688), .S0 (n_8202), .Y (n_8196)); + MX2X1 g33175(.A (wb_din_675), .B (oc5_cfg_1020), .S0 (n_8202), .Y + (n_8195)); + MX2X1 g33176(.A (wb_din_661), .B (oc4_cfg_1004), .S0 (n_8202), .Y + (n_8194)); + MX2X1 g33177(.A (wb_din_662), .B (n_4714), .S0 (n_8202), .Y (n_8193)); + MX2X1 g33178(.A (wb_din_663), .B (n_4711), .S0 (n_8202), .Y (n_8192)); + MX2X1 g33179(.A (wb_din_664), .B (n_8190), .S0 (n_8202), .Y (n_8191)); + MX2X1 g33180(.A (wb_din_665), .B (n_8188), .S0 (n_8202), .Y (n_8189)); + MX2X1 g33181(.A (wb_din_666), .B (n_4701), .S0 (n_8202), .Y (n_8187)); + MX2X1 g33182(.A (wb_din_667), .B (oc4_cfg_1010), .S0 (n_8202), .Y + (n_8186)); + MX2X1 g33183(.A (wb_din_668), .B (n_8182), .S0 (n_8202), .Y (n_8185)); + MX2X1 g33184(.A (wb_din_669), .B (oc5_cfg_1014), .S0 (n_8202), .Y + (n_8184)); + INVX1 g33221(.A (o3_empty), .Y (n_9543)); + DFFSRX1 u4_empty_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_7513), .Q (), .QN (o4_empty)); + INVX1 g33225(.A (o6_empty), .Y (n_9538)); + DFFSRX1 u6_empty_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_7512), .Q (), .QN (o7_empty)); + INVX1 g33229(.A (o8_empty), .Y (n_9534)); + INVX1 g33231(.A (o9_empty), .Y (n_9532)); + DFFX1 u15_crac_we_r_reg(.CK (clk_i), .D (n_8643), .Q (u15_crac_we_r), + .QN ()); + NAND3X1 g33262(.A (n_8182), .B (\u8_wp[1] ), .C (n_7976), .Y + (n_8183)); + NAND3X1 g33263(.A (n_862), .B (n_6838), .C (n_8101), .Y (n_8181)); + NAND3X1 g33274(.A (n_991), .B (n_614), .C (n_7984), .Y (n_8179)); + NAND3X1 g33281(.A (n_9833), .B (n_657), .C (n_7870), .Y (n_8178)); + NAND3X1 g33337(.A (n_1873), .B (n_7048), .C (n_7758), .Y (n_8177)); + NAND3X1 g33372(.A (n_1481), .B (n_6841), .C (n_7651), .Y (n_8175)); + DFFX1 \u1_sr_reg[8] (.CK (bit_clk_pad_i), .D (u1_sr_123), .Q + (u1_sr_124), .QN ()); + NAND2X1 g34234(.A (\u8_mem[2]_33 ), .B (n_7976), .Y (n_8173)); + NAND2X1 g34235(.A (\u3_mem[1]_88 ), .B (n_8101), .Y (n_8172)); + NAND2X1 g34236(.A (\u8_mem[2]_35 ), .B (n_7976), .Y (n_8171)); + NAND2X1 g34237(.A (\u3_mem[1]_61 ), .B (n_8101), .Y (n_8169)); + NAND2X1 g34238(.A (\u8_mem[2]_37 ), .B (n_7976), .Y (n_8168)); + NAND2X1 g34239(.A (\u3_mem[1]_89 ), .B (n_8101), .Y (n_8167)); + NAND2X1 g34240(.A (\u8_mem[3]_132 ), .B (n_7976), .Y (n_8165)); + NAND2X1 g34241(.A (\u3_mem[1]_62 ), .B (n_8101), .Y (n_8164)); + NAND2X1 g34242(.A (\u8_mem[3]_134 ), .B (n_7976), .Y (n_8163)); + NAND2X1 g34243(.A (\u8_mem[3]_135 ), .B (n_7976), .Y (n_8162)); + NAND2X1 g34244(.A (\u8_mem[3]_136 ), .B (n_7976), .Y (n_8160)); + NAND2X1 g34245(.A (\u3_mem[1]_64 ), .B (n_8101), .Y (n_8158)); + NAND2X1 g34246(.A (\u8_mem[3]_138 ), .B (n_7976), .Y (n_8157)); + NAND2X1 g34247(.A (\u8_mem[3]_139 ), .B (n_7976), .Y (n_8156)); + NAND2X1 g34248(.A (\u8_mem[3]_140 ), .B (n_7976), .Y (n_8154)); + NAND2X1 g34249(.A (\u8_mem[3]_141 ), .B (n_7976), .Y (n_8153)); + NAND2X1 g34250(.A (\u8_mem[3]_142 ), .B (n_7976), .Y (n_8152)); + NAND2X1 g34251(.A (\u8_mem[3]_143 ), .B (n_7976), .Y (n_8151)); + NAND2X1 g34252(.A (\u8_mem[3]_144 ), .B (n_7976), .Y (n_8150)); + NAND2X1 g34253(.A (\u8_mem[3]_145 ), .B (n_7976), .Y (n_8149)); + NAND2X1 g34254(.A (\u8_mem[3]_146 ), .B (n_7976), .Y (n_8148)); + NAND2X1 g34255(.A (\u8_mem[3]_147 ), .B (n_7976), .Y (n_8147)); + NAND2X1 g34256(.A (\u8_mem[3]_148 ), .B (n_7976), .Y (n_8146)); + NAND2X1 g34257(.A (\u7_mem[2]_57 ), .B (n_7651), .Y (n_8145)); + NAND2X1 g34258(.A (\u3_mem[2]_38 ), .B (n_8141), .Y (n_8144)); + NAND2X1 g34259(.A (\u8_mem[3]_150 ), .B (n_7976), .Y (n_8143)); + NAND2X1 g34260(.A (\u3_mem[2]_39 ), .B (n_8141), .Y (n_8142)); + NAND2X1 g34261(.A (\u8_mem[3]_123 ), .B (n_7976), .Y (n_8140)); + NAND2X1 g34262(.A (\u8_mem[3]_151 ), .B (n_7976), .Y (n_8139)); + NAND2X1 g34263(.A (\u3_mem[2]_40 ), .B (n_8101), .Y (n_8138)); + NAND2X1 g34264(.A (\u8_mem[3]_124 ), .B (n_7976), .Y (n_8137)); + NAND2X1 g34265(.A (\u3_mem[2]_41 ), .B (n_8101), .Y (n_8136)); + NAND2X1 g34266(.A (\u8_mem[3]_125 ), .B (n_7976), .Y (n_8134)); + NAND2X1 g34267(.A (\u8_mem[3]_126 ), .B (n_7976), .Y (n_8133)); + NAND2X1 g34268(.A (\u3_mem[2]_42 ), .B (n_8141), .Y (n_8132)); + NAND2X1 g34269(.A (\u3_mem[2]_43 ), .B (n_8101), .Y (n_8131)); + NAND2X1 g34270(.A (\u8_mem[3]_129 ), .B (n_7976), .Y (n_8130)); + NAND2X1 g34271(.A (\u3_mem[2]_46 ), .B (n_8101), .Y (n_8129)); + NAND2X1 g34272(.A (\u3_mem[2]_47 ), .B (n_8141), .Y (n_8127)); + NAND2X1 g34274(.A (\u8_mem[1]_63 ), .B (n_7976), .Y (n_8126)); + NAND2X1 g34275(.A (\u8_mem[2]_41 ), .B (n_7976), .Y (n_8125)); + NAND2X1 g34276(.A (\u8_mem[1]_62 ), .B (n_7976), .Y (n_8124)); + NAND2X1 g34277(.A (\u3_mem[2]_52 ), .B (n_8101), .Y (n_8123)); + NAND2X1 g34278(.A (\u3_mem[2]_53 ), .B (n_8141), .Y (n_8122)); + NAND2X1 g34279(.A (\u3_mem[2]_54 ), .B (n_8101), .Y (n_8121)); + NAND2X1 g34280(.A (\u3_mem[2]_55 ), .B (n_8141), .Y (n_8120)); + NAND2X1 g34281(.A (\u3_mem[2]_56 ), .B (n_8141), .Y (n_8119)); + NAND2X1 g34282(.A (\u8_mem[3] ), .B (n_7976), .Y (n_8118)); + NAND2X1 g34283(.A (\u3_mem[2]_57 ), .B (n_8141), .Y (n_8117)); + NAND2X1 g34284(.A (\u3_mem[2]_30 ), .B (n_8101), .Y (n_8116)); + NAND2X1 g34285(.A (\u3_mem[2]_58 ), .B (n_8141), .Y (n_8115)); + NAND2X1 g34286(.A (\u3_mem[2]_59 ), .B (n_8101), .Y (n_8114)); + NAND2X1 g34287(.A (\u3_mem[2]_31 ), .B (n_8101), .Y (n_8113)); + NAND2X1 g34288(.A (\u3_mem[2]_32 ), .B (n_8141), .Y (n_8112)); + NAND2X1 g34289(.A (\u3_mem[2]_33 ), .B (n_8141), .Y (n_8110)); + NAND2X1 g34290(.A (\u3_mem[2]_34 ), .B (n_8101), .Y (n_8109)); + NAND2X1 g34291(.A (\u3_mem[2]_35 ), .B (n_8101), .Y (n_8107)); + NAND2X1 g34292(.A (\u3_mem[2]_36 ), .B (n_8141), .Y (n_8106)); + NAND2X1 g34293(.A (\u3_mem[2]_37 ), .B (n_8101), .Y (n_8105)); + NAND2X1 g34294(.A (\u3_mem[3] ), .B (n_8101), .Y (n_8104)); + NAND2X1 g34295(.A (\u3_mem[3]_131 ), .B (n_8101), .Y (n_8102)); + NAND2X1 g34296(.A (\u3_mem[3]_132 ), .B (n_8101), .Y (n_8100)); + NAND2X1 g34297(.A (\u3_mem[3]_133 ), .B (n_8097), .Y (n_8099)); + NAND2X1 g34298(.A (\u3_mem[3]_134 ), .B (n_8097), .Y (n_8098)); + NAND2X1 g34299(.A (\u3_mem[3]_135 ), .B (n_8101), .Y (n_8096)); + NAND2X1 g34300(.A (\u3_mem[3]_136 ), .B (n_8101), .Y (n_8095)); + NAND2X1 g34301(.A (\u3_mem[3]_137 ), .B (n_8097), .Y (n_8094)); + NAND2X1 g34302(.A (\u3_mem[3]_138 ), .B (n_8097), .Y (n_8093)); + NAND2X1 g34303(.A (\u3_mem[3]_139 ), .B (n_8101), .Y (n_8092)); + NAND2X1 g34304(.A (\u3_mem[3]_140 ), .B (n_8101), .Y (n_8091)); + NAND2X1 g34305(.A (\u3_mem[3]_122 ), .B (n_8101), .Y (n_8090)); + NAND2X1 g34307(.A (\u3_mem[3]_141 ), .B (n_8101), .Y (n_8089)); + NAND2X1 g34308(.A (\u3_mem[3]_142 ), .B (n_8101), .Y (n_8088)); + NAND2X1 g34309(.A (\u3_mem[3]_143 ), .B (n_8101), .Y (n_8087)); + NAND2X1 g34310(.A (\u3_mem[3]_146 ), .B (n_8101), .Y (n_8086)); + NAND2X1 g34311(.A (\u3_mem[3]_147 ), .B (n_8141), .Y (n_8085)); + NAND2X1 g34312(.A (\u3_mem[3]_148 ), .B (n_8141), .Y (n_8084)); + NAND2X1 g34313(.A (\u3_mem[3]_149 ), .B (n_8101), .Y (n_8083)); + NAND2X1 g34315(.A (\u3_mem[3]_123 ), .B (n_8141), .Y (n_8082)); + NAND2X1 g34314(.A (\u3_mem[3]_150 ), .B (n_8101), .Y (n_8081)); + NAND2X1 g34317(.A (\u8_mem[3]_149 ), .B (n_7976), .Y (n_8080)); + NAND2X1 g34318(.A (\u3_mem[3]_152 ), .B (n_8141), .Y (n_8079)); + NAND2X1 g34319(.A (\u7_mem[2]_29 ), .B (n_7651), .Y (n_8078)); + NAND2X1 g34320(.A (\u3_mem[3]_124 ), .B (n_8101), .Y (n_8077)); + NAND2X1 g34321(.A (\u8_mem[2]_45 ), .B (n_7976), .Y (n_8076)); + NAND2X1 g34322(.A (\u3_mem[3]_127 ), .B (n_8141), .Y (n_8075)); + NAND2X1 g34323(.A (\u3_mem[3]_128 ), .B (n_8141), .Y (n_8074)); + NAND2X1 g34325(.A (\u3_mem[3]_129 ), .B (n_8141), .Y (n_8073)); + NAND2X1 g34330(.A (\u8_mem[2]_36 ), .B (n_7976), .Y (n_8072)); + NAND2X1 g34329(.A (\u3_mem[2] ), .B (n_8101), .Y (n_8071)); + NAND2X1 g34332(.A (\u8_mem[2]_34 ), .B (n_7976), .Y (n_8070)); + NAND2X1 g34334(.A (\u3_mem[1]_68 ), .B (n_8101), .Y (n_8069)); + NAND2X1 g34335(.A (\u3_mem[1]_87 ), .B (n_8101), .Y (n_8068)); + NAND2X1 g34336(.A (\u8_mem[2]_32 ), .B (n_7976), .Y (n_8067)); + NAND2X1 g34337(.A (\u3_mem[2]_51 ), .B (n_8101), .Y (n_8066)); + NAND2X1 g34338(.A (\u3_mem[3]_126 ), .B (n_8141), .Y (n_8065)); + NAND2X1 g34339(.A (\u3_mem[1]_67 ), .B (n_8141), .Y (n_8064)); + NAND2X1 g34340(.A (\u3_mem[3]_145 ), .B (n_8097), .Y (n_8063)); + NAND2X1 g34341(.A (\u8_mem[2]_59 ), .B (n_7976), .Y (n_8062)); + NAND2X1 g34342(.A (\u3_mem[3]_144 ), .B (n_8097), .Y (n_8061)); + NAND2X1 g34343(.A (\u3_mem[2]_50 ), .B (n_8101), .Y (n_8060)); + NAND2X1 g34345(.A (\u3_mem[1]_66 ), .B (n_8141), .Y (n_8058)); + NAND2X1 g34346(.A (\u3_mem[3]_125 ), .B (n_8101), .Y (n_8057)); + NAND2X1 g34348(.A (\u4_mem[1] ), .B (n_7984), .Y (n_8056)); + NAND2X1 g34349(.A (\u4_mem[1]_69 ), .B (n_7984), .Y (n_8055)); + NAND2X1 g34350(.A (\u4_mem[1]_70 ), .B (n_7984), .Y (n_8054)); + NAND2X1 g34352(.A (\u4_mem[1]_71 ), .B (n_7984), .Y (n_8052)); + NAND2X1 g34353(.A (\u4_mem[1]_72 ), .B (n_7984), .Y (n_8051)); + NAND2X1 g34354(.A (\u4_mem[1]_73 ), .B (n_7984), .Y (n_8049)); + NAND2X1 g34355(.A (\u4_mem[1]_74 ), .B (n_7984), .Y (n_8048)); + NAND2X1 g34356(.A (\u8_mem[3]_122 ), .B (n_7976), .Y (n_8047)); + NAND2X1 g34357(.A (\u4_mem[1]_75 ), .B (n_7984), .Y (n_8046)); + NAND2X1 g34358(.A (\u4_mem[1]_76 ), .B (n_7984), .Y (n_8045)); + NAND2X1 g34359(.A (\u4_mem[1]_77 ), .B (n_7984), .Y (n_8044)); + NAND2X1 g34360(.A (\u4_mem[1]_78 ), .B (n_7984), .Y (n_8042)); + NAND2X1 g34362(.A (\u4_mem[1]_60 ), .B (n_7984), .Y (n_8041)); + NAND2X1 g34363(.A (\u4_mem[1]_79 ), .B (n_7984), .Y (n_8039)); + NAND2X1 g34364(.A (\u4_mem[1]_80 ), .B (n_7984), .Y (n_8037)); + NAND2X1 g34365(.A (\u4_mem[1]_81 ), .B (n_7984), .Y (n_8036)); + NAND2X1 g34366(.A (\u4_mem[1]_82 ), .B (n_7984), .Y (n_8035)); + NAND2X1 g34367(.A (\u4_mem[1]_83 ), .B (n_7984), .Y (n_8034)); + NAND2X1 g34369(.A (\u4_mem[1]_84 ), .B (n_7984), .Y (n_8033)); + NAND2X1 g34370(.A (\u4_mem[1]_85 ), .B (n_7984), .Y (n_8032)); + NAND2X1 g34371(.A (\u4_mem[1]_86 ), .B (n_7984), .Y (n_8031)); + NAND2X1 g34372(.A (\u4_mem[1]_87 ), .B (n_7984), .Y (n_8030)); + NAND2X1 g34373(.A (\u4_mem[1]_88 ), .B (n_7984), .Y (n_8029)); + NAND2X1 g34374(.A (\u4_mem[1]_61 ), .B (n_7984), .Y (n_8028)); + NAND2X1 g34375(.A (\u4_mem[1]_89 ), .B (n_7984), .Y (n_8027)); + NAND2X1 g34376(.A (\u4_mem[1]_90 ), .B (n_7984), .Y (n_8026)); + NAND2X1 g34378(.A (\u4_mem[1]_62 ), .B (n_7984), .Y (n_8025)); + NAND2X1 g34379(.A (\u4_mem[1]_63 ), .B (n_7984), .Y (n_8024)); + NAND2X1 g34380(.A (\u4_mem[1]_64 ), .B (n_7984), .Y (n_8023)); + NAND2X1 g34381(.A (\u4_mem[1]_65 ), .B (n_7984), .Y (n_8022)); + NAND2X1 g34382(.A (\u4_mem[1]_66 ), .B (n_7984), .Y (n_8021)); + NAND2X1 g34383(.A (\u4_mem[1]_67 ), .B (n_7984), .Y (n_8020)); + NAND2X1 g34384(.A (\u4_mem[1]_68 ), .B (n_7984), .Y (n_8019)); + NAND2X1 g34386(.A (\u4_mem[2] ), .B (n_7984), .Y (n_8018)); + NAND2X1 g34387(.A (\u4_mem[2]_38 ), .B (n_7984), .Y (n_8017)); + NAND2X1 g34388(.A (\u4_mem[2]_39 ), .B (n_7984), .Y (n_8016)); + NAND2X1 g34389(.A (\u4_mem[2]_40 ), .B (n_7984), .Y (n_8015)); + NAND2X1 g34390(.A (\u4_mem[2]_41 ), .B (n_7984), .Y (n_8014)); + NAND2X1 g34391(.A (\u4_mem[2]_42 ), .B (n_7984), .Y (n_8013)); + NAND2X1 g34392(.A (\u4_mem[2]_43 ), .B (n_7984), .Y (n_8012)); + NAND2X1 g34394(.A (\u4_mem[2]_44 ), .B (n_7984), .Y (n_8011)); + NAND2X1 g34395(.A (\u4_mem[2]_45 ), .B (n_7984), .Y (n_8010)); + NAND2X1 g34396(.A (\u4_mem[2]_46 ), .B (n_7984), .Y (n_8009)); + NAND2X1 g34397(.A (\u4_mem[2]_47 ), .B (n_7984), .Y (n_8008)); + NAND2X1 g34398(.A (\u4_mem[2]_29 ), .B (n_7984), .Y (n_8007)); + NAND2X1 g34399(.A (\u4_mem[2]_48 ), .B (n_7984), .Y (n_8006)); + NAND2X1 g34400(.A (\u4_mem[2]_49 ), .B (n_7984), .Y (n_8005)); + NAND2X1 g34401(.A (\u4_mem[2]_50 ), .B (n_7984), .Y (n_8004)); + NAND2X1 g34402(.A (\u4_mem[2]_51 ), .B (n_7984), .Y (n_8003)); + NAND2X1 g34403(.A (\u4_mem[2]_52 ), .B (n_7984), .Y (n_8002)); + NAND2X1 g34415(.A (\u4_mem[2]_53 ), .B (n_7984), .Y (n_8001)); + NAND2X1 g34416(.A (\u4_mem[2]_54 ), .B (n_7984), .Y (n_8000)); + NAND2X1 g34417(.A (\u4_mem[2]_55 ), .B (n_7984), .Y (n_7999)); + NAND2X1 g34418(.A (\u4_mem[2]_56 ), .B (n_7984), .Y (n_7998)); + NAND2X1 g34419(.A (\u4_mem[2]_57 ), .B (n_7984), .Y (n_7997)); + NAND2X1 g34420(.A (\u4_mem[2]_30 ), .B (n_7984), .Y (n_7996)); + NAND2X1 g34421(.A (\u4_mem[2]_58 ), .B (n_7984), .Y (n_7995)); + NAND2X1 g34422(.A (\u4_mem[2]_59 ), .B (n_7984), .Y (n_7994)); + NAND2X1 g34423(.A (\u4_mem[2]_31 ), .B (n_7984), .Y (n_7993)); + NAND2X1 g34424(.A (\u4_mem[2]_32 ), .B (n_7984), .Y (n_7992)); + NAND2X1 g34425(.A (\u4_mem[2]_33 ), .B (n_7984), .Y (n_7991)); + NAND2X1 g34426(.A (\u4_mem[2]_34 ), .B (n_7984), .Y (n_7990)); + NAND2X1 g34427(.A (\u4_mem[2]_35 ), .B (n_7984), .Y (n_7989)); + NAND2X1 g34428(.A (\u4_mem[2]_36 ), .B (n_7984), .Y (n_7988)); + NAND2X1 g34429(.A (\u4_mem[2]_37 ), .B (n_7984), .Y (n_7987)); + NAND2X1 g34430(.A (\u4_mem[3] ), .B (n_7984), .Y (n_7986)); + NAND2X1 g34431(.A (\u4_mem[3]_131 ), .B (n_7984), .Y (n_7985)); + NAND2X1 g34432(.A (\u4_mem[3]_132 ), .B (n_7984), .Y (n_7983)); + NAND2X1 g34433(.A (\u8_mem[1] ), .B (n_7976), .Y (n_7982)); + NAND2X1 g34434(.A (\u4_mem[3]_133 ), .B (n_7984), .Y (n_7981)); + NAND2X1 g34435(.A (\u4_mem[3]_134 ), .B (n_7984), .Y (n_7980)); + NAND2X1 g34436(.A (\u4_mem[3]_135 ), .B (n_7984), .Y (n_7979)); + NAND2X1 g34437(.A (\u4_mem[3]_136 ), .B (n_7984), .Y (n_7978)); + NAND2X1 g34438(.A (\u8_mem[2]_56 ), .B (n_7976), .Y (n_7977)); + NAND2X1 g34439(.A (\u4_mem[3]_137 ), .B (n_7984), .Y (n_7975)); + NAND2X1 g34440(.A (\u4_mem[3]_138 ), .B (n_7984), .Y (n_7974)); + NAND2X1 g34441(.A (\u4_mem[3]_139 ), .B (n_7984), .Y (n_7973)); + NAND2X1 g34442(.A (\u4_mem[3]_140 ), .B (n_7984), .Y (n_7972)); + NAND2X1 g34443(.A (\u4_mem[3]_122 ), .B (n_7984), .Y (n_7971)); + NAND2X1 g34444(.A (\u4_mem[3]_141 ), .B (n_7984), .Y (n_7970)); + NAND2X1 g34452(.A (\u4_mem[3]_142 ), .B (n_7984), .Y (n_7969)); + NAND2X1 g34453(.A (\u4_mem[3]_143 ), .B (n_7984), .Y (n_7968)); + NAND2X1 g34454(.A (\u4_mem[3]_144 ), .B (n_7984), .Y (n_7967)); + NAND2X1 g34455(.A (\u4_mem[3]_145 ), .B (n_7984), .Y (n_7966)); + NAND2X1 g34456(.A (\u4_mem[3]_146 ), .B (n_7984), .Y (n_7965)); + NAND2X1 g34457(.A (\u4_mem[3]_147 ), .B (n_7984), .Y (n_7964)); + NAND2X1 g34458(.A (\u4_mem[3]_148 ), .B (n_7984), .Y (n_7963)); + NAND2X1 g34459(.A (\u4_mem[3]_149 ), .B (n_7984), .Y (n_7962)); + NAND2X1 g34460(.A (\u4_mem[3]_150 ), .B (n_7984), .Y (n_7961)); + NAND2X1 g34461(.A (\u4_mem[3]_123 ), .B (n_7984), .Y (n_7960)); + NAND2X1 g34462(.A (\u4_mem[3]_151 ), .B (n_7984), .Y (n_7959)); + NAND2X1 g34463(.A (\u4_mem[3]_152 ), .B (n_7984), .Y (n_7958)); + NAND2X1 g34464(.A (\u3_mem[1]_70 ), .B (n_8101), .Y (n_7957)); + NAND2X1 g34465(.A (\u4_mem[3]_124 ), .B (n_7984), .Y (n_7956)); + NAND2X1 g34466(.A (\u4_mem[3]_125 ), .B (n_7984), .Y (n_7955)); + NAND2X1 g34467(.A (\u4_mem[3]_126 ), .B (n_7984), .Y (n_7954)); + NAND2X1 g34468(.A (\u4_mem[3]_127 ), .B (n_7984), .Y (n_7953)); + NAND2X1 g34469(.A (\u4_mem[3]_128 ), .B (n_7984), .Y (n_7952)); + NAND2X1 g34470(.A (\u4_mem[3]_129 ), .B (n_7984), .Y (n_7951)); + NAND2X1 g34471(.A (\u4_mem[3]_130 ), .B (n_7984), .Y (n_7950)); + NAND2X1 g34472(.A (\u8_mem[1]_82 ), .B (n_7976), .Y (n_7949)); + NAND2X1 g34474(.A (\u8_mem[1]_71 ), .B (n_7976), .Y (n_7948)); + NAND2X1 g34477(.A (\u3_mem[1]_79 ), .B (n_8101), .Y (n_7947)); + NAND2X1 g34478(.A (\u3_mem[2]_49 ), .B (n_8101), .Y (n_7946)); + NAND2X1 g34488(.A (\u8_mem[1]_60 ), .B (n_7976), .Y (n_7945)); + NAND2X1 g34489(.A (\u5_mem[1] ), .B (n_7870), .Y (n_7943)); + NAND2X1 g34491(.A (\u5_mem[1]_69 ), .B (n_7870), .Y (n_7942)); + NAND2X1 g34492(.A (\u5_mem[1]_70 ), .B (n_7870), .Y (n_7941)); + NAND2X1 g34493(.A (\u5_mem[1]_71 ), .B (n_7870), .Y (n_7939)); + NAND2X1 g34494(.A (\u5_mem[1]_72 ), .B (n_7870), .Y (n_7938)); + NAND2X1 g34495(.A (\u5_mem[1]_73 ), .B (n_7870), .Y (n_7936)); + NAND2X1 g34496(.A (\u5_mem[1]_74 ), .B (n_7870), .Y (n_7935)); + NAND2X1 g34497(.A (\u5_mem[1]_75 ), .B (n_7870), .Y (n_7934)); + NAND2X1 g34498(.A (\u5_mem[1]_76 ), .B (n_7870), .Y (n_7933)); + NAND2X1 g34499(.A (\u5_mem[1]_77 ), .B (n_7870), .Y (n_7932)); + NAND2X1 g34500(.A (\u5_mem[1]_78 ), .B (n_7870), .Y (n_7930)); + NAND2X1 g34501(.A (\u5_mem[1]_60 ), .B (n_7870), .Y (n_7929)); + NAND2X1 g34502(.A (\u5_mem[1]_79 ), .B (n_7870), .Y (n_7927)); + NAND2X1 g34503(.A (\u5_mem[1]_80 ), .B (n_7870), .Y (n_7925)); + NAND2X1 g34504(.A (\u5_mem[1]_81 ), .B (n_7870), .Y (n_7924)); + NAND2X1 g34505(.A (\u5_mem[1]_82 ), .B (n_7870), .Y (n_7923)); + NAND2X1 g34506(.A (\u5_mem[1]_83 ), .B (n_7870), .Y (n_7922)); + NAND2X1 g34507(.A (\u5_mem[1]_84 ), .B (n_7870), .Y (n_7921)); + NAND2X1 g34508(.A (\u5_mem[1]_85 ), .B (n_7870), .Y (n_7920)); + NAND2X1 g34509(.A (\u5_mem[1]_86 ), .B (n_7870), .Y (n_7919)); + NAND2X1 g34510(.A (\u5_mem[1]_87 ), .B (n_7870), .Y (n_7918)); + NAND2X1 g34511(.A (\u5_mem[1]_88 ), .B (n_7870), .Y (n_7917)); + NAND2X1 g34512(.A (\u5_mem[1]_61 ), .B (n_7870), .Y (n_7916)); + NAND2X1 g34513(.A (\u5_mem[1]_89 ), .B (n_7870), .Y (n_7915)); + NAND2X1 g34514(.A (\u5_mem[1]_90 ), .B (n_7870), .Y (n_7914)); + NAND2X1 g34515(.A (\u5_mem[1]_62 ), .B (n_7870), .Y (n_7913)); + NAND2X1 g34516(.A (\u5_mem[1]_63 ), .B (n_7870), .Y (n_7912)); + NAND2X1 g34517(.A (\u5_mem[1]_64 ), .B (n_7870), .Y (n_7911)); + NAND2X1 g34518(.A (\u5_mem[1]_65 ), .B (n_7870), .Y (n_7910)); + NAND2X1 g34519(.A (\u5_mem[1]_66 ), .B (n_7870), .Y (n_7909)); + NAND2X1 g34520(.A (\u5_mem[1]_67 ), .B (n_7870), .Y (n_7908)); + NAND2X1 g34521(.A (\u5_mem[1]_68 ), .B (n_7870), .Y (n_7907)); + NAND2X1 g34522(.A (\u7_mem[1]_90 ), .B (n_7651), .Y (n_7906)); + NAND2X1 g34523(.A (\u5_mem[2] ), .B (n_7870), .Y (n_7904)); + NAND2X1 g34524(.A (\u5_mem[2]_38 ), .B (n_7870), .Y (n_7903)); + NAND2X1 g34525(.A (\u5_mem[2]_39 ), .B (n_7870), .Y (n_7902)); + NAND2X1 g34526(.A (\u5_mem[2]_40 ), .B (n_7870), .Y (n_7901)); + NAND2X1 g34527(.A (\u5_mem[2]_41 ), .B (n_7870), .Y (n_7900)); + NAND2X1 g34528(.A (\u5_mem[2]_42 ), .B (n_7870), .Y (n_7899)); + NAND2X1 g34529(.A (\u5_mem[2]_43 ), .B (n_7870), .Y (n_7898)); + NAND2X1 g34530(.A (\u5_mem[2]_44 ), .B (n_7870), .Y (n_7897)); + NAND2X1 g34531(.A (\u5_mem[2]_45 ), .B (n_7870), .Y (n_7896)); + NAND2X1 g34532(.A (\u5_mem[2]_46 ), .B (n_7870), .Y (n_7895)); + NAND2X1 g34533(.A (\u5_mem[2]_47 ), .B (n_7870), .Y (n_7894)); + NAND2X1 g34534(.A (\u5_mem[2]_29 ), .B (n_7870), .Y (n_7893)); + NAND2X1 g34535(.A (\u5_mem[2]_48 ), .B (n_7870), .Y (n_7892)); + NAND2X1 g34536(.A (\u5_mem[2]_49 ), .B (n_7870), .Y (n_7891)); + NAND2X1 g34537(.A (\u5_mem[2]_50 ), .B (n_7870), .Y (n_7890)); + NAND2X1 g34538(.A (\u5_mem[2]_51 ), .B (n_7870), .Y (n_7889)); + NAND2X1 g34539(.A (\u5_mem[2]_52 ), .B (n_7870), .Y (n_7888)); + NAND2X1 g34540(.A (\u5_mem[2]_53 ), .B (n_7870), .Y (n_7887)); + NAND2X1 g34541(.A (\u5_mem[2]_54 ), .B (n_7870), .Y (n_7886)); + NAND2X1 g34542(.A (\u5_mem[2]_55 ), .B (n_7870), .Y (n_7885)); + NAND2X1 g34543(.A (\u5_mem[2]_56 ), .B (n_7870), .Y (n_7884)); + NAND2X1 g34544(.A (\u5_mem[2]_57 ), .B (n_7870), .Y (n_7883)); + NAND2X1 g34545(.A (\u5_mem[2]_30 ), .B (n_7870), .Y (n_7882)); + NAND2X1 g34546(.A (\u5_mem[2]_58 ), .B (n_7870), .Y (n_7881)); + NAND2X1 g34547(.A (\u5_mem[2]_59 ), .B (n_7870), .Y (n_7880)); + NAND2X1 g34548(.A (\u5_mem[2]_31 ), .B (n_7870), .Y (n_7879)); + NAND2X1 g34549(.A (\u5_mem[2]_32 ), .B (n_7870), .Y (n_7878)); + NAND2X1 g34550(.A (\u5_mem[2]_33 ), .B (n_7870), .Y (n_7877)); + NAND2X1 g34551(.A (\u5_mem[2]_34 ), .B (n_7870), .Y (n_7876)); + NAND2X1 g34552(.A (\u5_mem[2]_35 ), .B (n_7870), .Y (n_7875)); + NAND2X1 g34553(.A (\u5_mem[2]_36 ), .B (n_7870), .Y (n_7874)); + NAND2X1 g34554(.A (\u5_mem[2]_37 ), .B (n_7870), .Y (n_7873)); + NAND2X1 g34555(.A (\u5_mem[3] ), .B (n_7870), .Y (n_7872)); + NAND2X1 g34556(.A (\u5_mem[3]_131 ), .B (n_7870), .Y (n_7871)); + NAND2X1 g34557(.A (\u5_mem[3]_132 ), .B (n_7870), .Y (n_7869)); + NAND2X1 g34558(.A (\u5_mem[3]_133 ), .B (n_7870), .Y (n_7868)); + NAND2X1 g34559(.A (\u5_mem[3]_134 ), .B (n_7870), .Y (n_7867)); + NAND2X1 g34560(.A (\u5_mem[3]_135 ), .B (n_7870), .Y (n_7866)); + NAND2X1 g34561(.A (\u5_mem[3]_136 ), .B (n_7870), .Y (n_7865)); + NAND2X1 g34562(.A (\u5_mem[3]_137 ), .B (n_7870), .Y (n_7864)); + NAND2X1 g34563(.A (\u5_mem[3]_138 ), .B (n_7870), .Y (n_7863)); + NAND2X1 g34564(.A (\u5_mem[3]_139 ), .B (n_7870), .Y (n_7862)); + NAND2X1 g34565(.A (\u5_mem[3]_140 ), .B (n_7870), .Y (n_7861)); + NAND2X1 g34566(.A (\u5_mem[3]_122 ), .B (n_7870), .Y (n_7860)); + NAND2X1 g34567(.A (\u5_mem[3]_141 ), .B (n_7870), .Y (n_7859)); + NAND2X1 g34568(.A (\u5_mem[3]_142 ), .B (n_7870), .Y (n_7858)); + NAND2X1 g34569(.A (\u5_mem[3]_143 ), .B (n_7870), .Y (n_7857)); + NAND2X1 g34570(.A (\u5_mem[3]_144 ), .B (n_7870), .Y (n_7856)); + NAND2X1 g34571(.A (\u5_mem[3]_145 ), .B (n_7870), .Y (n_7855)); + NAND2X1 g34572(.A (\u5_mem[3]_146 ), .B (n_7870), .Y (n_7854)); + NAND2X1 g34573(.A (\u5_mem[3]_147 ), .B (n_7870), .Y (n_7853)); + NAND2X1 g34574(.A (\u5_mem[3]_148 ), .B (n_7870), .Y (n_7852)); + NAND2X1 g34575(.A (\u5_mem[3]_149 ), .B (n_7870), .Y (n_7851)); + NAND2X1 g34576(.A (\u5_mem[3]_150 ), .B (n_7870), .Y (n_7850)); + NAND2X1 g34577(.A (\u5_mem[3]_123 ), .B (n_7870), .Y (n_7849)); + NAND2X1 g34578(.A (\u5_mem[3]_151 ), .B (n_7870), .Y (n_7848)); + NAND2X1 g34579(.A (\u5_mem[3]_152 ), .B (n_7870), .Y (n_7847)); + NAND2X1 g34580(.A (\u5_mem[3]_124 ), .B (n_7870), .Y (n_7846)); + NAND2X1 g34581(.A (\u5_mem[3]_125 ), .B (n_7870), .Y (n_7845)); + NAND2X1 g34582(.A (\u5_mem[3]_126 ), .B (n_7870), .Y (n_7844)); + NAND2X1 g34583(.A (\u5_mem[3]_127 ), .B (n_7870), .Y (n_7843)); + NAND2X1 g34584(.A (\u5_mem[3]_128 ), .B (n_7870), .Y (n_7842)); + NAND2X1 g34585(.A (\u5_mem[3]_129 ), .B (n_7870), .Y (n_7841)); + NAND2X1 g34586(.A (\u5_mem[3]_130 ), .B (n_7870), .Y (n_7840)); + NAND2X1 g34587(.A (\u8_mem[1]_75 ), .B (n_7976), .Y (n_7839)); + NAND2X1 g34588(.A (\u8_mem[3]_131 ), .B (n_7976), .Y (n_7838)); + NAND2X1 g34590(.A (\u8_mem[3]_127 ), .B (n_7976), .Y (n_7837)); + NAND2X1 g34591(.A (\u8_mem[3]_130 ), .B (n_7976), .Y (n_7836)); + NAND2X1 g34592(.A (\u3_mem[2]_48 ), .B (n_8141), .Y (n_7835)); + NAND2X1 g34593(.A (\u3_mem[3]_130 ), .B (n_8101), .Y (n_7834)); + NAND2X1 g34594(.A (\u8_mem[3]_128 ), .B (n_7976), .Y (n_7833)); + NAND2X1 g34598(.A (\u6_mem[1] ), .B (n_7758), .Y (n_7832)); + NAND2X1 g34599(.A (\u6_mem[1]_69 ), .B (n_7758), .Y (n_7831)); + NAND2X1 g34600(.A (\u6_mem[1]_70 ), .B (n_7758), .Y (n_7830)); + NAND2X1 g34601(.A (\u6_mem[1]_71 ), .B (n_7758), .Y (n_7828)); + NAND2X1 g34602(.A (\u6_mem[1]_72 ), .B (n_7758), .Y (n_7827)); + NAND2X1 g34603(.A (\u6_mem[1]_73 ), .B (n_7758), .Y (n_7825)); + NAND2X1 g34604(.A (\u6_mem[1]_74 ), .B (n_7758), .Y (n_7824)); + NAND2X1 g34605(.A (\u6_mem[1]_75 ), .B (n_7758), .Y (n_7823)); + NAND2X1 g34606(.A (\u6_mem[1]_76 ), .B (n_7758), .Y (n_7822)); + NAND2X1 g34607(.A (\u6_mem[1]_77 ), .B (n_7758), .Y (n_7821)); + NAND2X1 g34608(.A (\u6_mem[1]_78 ), .B (n_7758), .Y (n_7819)); + NAND2X1 g34609(.A (\u3_mem[1]_65 ), .B (n_8101), .Y (n_7818)); + NAND2X1 g34610(.A (\u6_mem[1]_60 ), .B (n_7758), .Y (n_7817)); + NAND2X1 g34611(.A (\u6_mem[1]_79 ), .B (n_7758), .Y (n_7815)); + NAND2X1 g34612(.A (\u6_mem[1]_80 ), .B (n_7758), .Y (n_7813)); + NAND2X1 g34613(.A (\u6_mem[1]_81 ), .B (n_7758), .Y (n_7812)); + NAND2X1 g34614(.A (\u6_mem[1]_82 ), .B (n_7758), .Y (n_7811)); + NAND2X1 g34615(.A (\u6_mem[1]_83 ), .B (n_7758), .Y (n_7810)); + NAND2X1 g34616(.A (\u6_mem[1]_84 ), .B (n_7758), .Y (n_7809)); + NAND2X1 g34617(.A (\u6_mem[1]_85 ), .B (n_7758), .Y (n_7808)); + NAND2X1 g34618(.A (\u6_mem[1]_86 ), .B (n_7758), .Y (n_7807)); + NAND2X1 g34619(.A (\u6_mem[1]_87 ), .B (n_7758), .Y (n_7806)); + NAND2X1 g34620(.A (\u8_mem[2]_39 ), .B (n_7976), .Y (n_7805)); + NAND2X1 g34621(.A (\u6_mem[1]_88 ), .B (n_7758), .Y (n_7804)); + NAND2X1 g34622(.A (\u6_mem[1]_61 ), .B (n_7758), .Y (n_7803)); + NAND2X1 g34623(.A (\u6_mem[1]_89 ), .B (n_7758), .Y (n_7802)); + NAND2X1 g34624(.A (\u6_mem[1]_90 ), .B (n_7758), .Y (n_7801)); + NAND2X1 g34625(.A (\u6_mem[1]_62 ), .B (n_7758), .Y (n_7800)); + NAND2X1 g34626(.A (\u6_mem[1]_63 ), .B (n_7758), .Y (n_7799)); + NAND2X1 g34627(.A (\u6_mem[1]_64 ), .B (n_7758), .Y (n_7798)); + NAND2X1 g34628(.A (\u6_mem[1]_65 ), .B (n_7758), .Y (n_7797)); + NAND2X1 g34629(.A (\u6_mem[1]_66 ), .B (n_7758), .Y (n_7796)); + NAND2X1 g34630(.A (\u6_mem[1]_67 ), .B (n_7758), .Y (n_7795)); + NAND2X1 g34631(.A (\u6_mem[1]_68 ), .B (n_7758), .Y (n_7794)); + NAND2X1 g34632(.A (\u6_mem[2] ), .B (n_7758), .Y (n_7793)); + NAND2X1 g34633(.A (\u6_mem[2]_38 ), .B (n_7758), .Y (n_7792)); + NAND2X1 g34634(.A (\u3_mem[1]_76 ), .B (n_8101), .Y (n_7791)); + NAND2X1 g34635(.A (\u6_mem[2]_39 ), .B (n_7758), .Y (n_7790)); + NAND2X1 g34636(.A (\u6_mem[2]_40 ), .B (n_7758), .Y (n_7789)); + NAND2X1 g34637(.A (\u6_mem[2]_41 ), .B (n_7758), .Y (n_7788)); + NAND2X1 g34638(.A (\u6_mem[2]_42 ), .B (n_7758), .Y (n_7787)); + NAND2X1 g34639(.A (\u6_mem[2]_43 ), .B (n_7758), .Y (n_7786)); + NAND2X1 g34640(.A (\u6_mem[2]_44 ), .B (n_7758), .Y (n_7785)); + NAND2X1 g34641(.A (\u6_mem[2]_45 ), .B (n_7758), .Y (n_7784)); + NAND2X1 g34642(.A (\u6_mem[2]_46 ), .B (n_7758), .Y (n_7783)); + NAND2X1 g34643(.A (\u6_mem[2]_47 ), .B (n_7758), .Y (n_7782)); + NAND2X1 g34644(.A (\u6_mem[2]_29 ), .B (n_7758), .Y (n_7781)); + NAND2X1 g34645(.A (\u6_mem[2]_48 ), .B (n_7758), .Y (n_7780)); + NAND2X1 g34646(.A (\u6_mem[2]_49 ), .B (n_7758), .Y (n_7779)); + NAND2X1 g34647(.A (\u6_mem[2]_50 ), .B (n_7758), .Y (n_7778)); + NAND2X1 g34648(.A (\u6_mem[2]_51 ), .B (n_7758), .Y (n_7777)); + NAND2X1 g34649(.A (\u6_mem[2]_52 ), .B (n_7758), .Y (n_7776)); + NAND2X1 g34650(.A (\u6_mem[2]_53 ), .B (n_7758), .Y (n_7775)); + NAND2X1 g34651(.A (\u6_mem[2]_54 ), .B (n_7758), .Y (n_7774)); + NAND2X1 g34652(.A (\u6_mem[2]_55 ), .B (n_7758), .Y (n_7773)); + NAND2X1 g34653(.A (\u6_mem[2]_56 ), .B (n_7758), .Y (n_7772)); + NAND2X1 g34654(.A (\u6_mem[2]_57 ), .B (n_7758), .Y (n_7771)); + NAND2X1 g34655(.A (\u6_mem[2]_30 ), .B (n_7758), .Y (n_7770)); + NAND2X1 g34656(.A (\u6_mem[2]_58 ), .B (n_7758), .Y (n_7769)); + NAND2X1 g34657(.A (\u6_mem[2]_59 ), .B (n_7758), .Y (n_7768)); + NAND2X1 g34658(.A (\u6_mem[2]_31 ), .B (n_7758), .Y (n_7767)); + NAND2X1 g34659(.A (\u6_mem[2]_32 ), .B (n_7758), .Y (n_7766)); + NAND2X1 g34660(.A (\u6_mem[2]_33 ), .B (n_7758), .Y (n_7765)); + NAND2X1 g34661(.A (\u6_mem[2]_34 ), .B (n_7758), .Y (n_7764)); + NAND2X1 g34662(.A (\u6_mem[2]_35 ), .B (n_7758), .Y (n_7763)); + NAND2X1 g34663(.A (\u6_mem[2]_36 ), .B (n_7758), .Y (n_7762)); + NAND2X1 g34664(.A (\u6_mem[2]_37 ), .B (n_7758), .Y (n_7761)); + NAND2X1 g34665(.A (\u6_mem[3] ), .B (n_7758), .Y (n_7760)); + NAND2X1 g34666(.A (\u6_mem[3]_131 ), .B (n_7758), .Y (n_7759)); + NAND2X1 g34667(.A (\u6_mem[3]_132 ), .B (n_7758), .Y (n_7757)); + NAND2X1 g34668(.A (\u6_mem[3]_133 ), .B (n_7758), .Y (n_7756)); + NAND2X1 g34669(.A (\u6_mem[3]_134 ), .B (n_7758), .Y (n_7755)); + NAND2X1 g34670(.A (\u6_mem[3]_135 ), .B (n_7758), .Y (n_7754)); + NAND2X1 g34671(.A (\u6_mem[3]_136 ), .B (n_7758), .Y (n_7753)); + NAND2X1 g34672(.A (\u6_mem[3]_137 ), .B (n_7758), .Y (n_7752)); + NAND2X1 g34673(.A (\u6_mem[3]_138 ), .B (n_7758), .Y (n_7751)); + NAND2X1 g34674(.A (\u6_mem[3]_139 ), .B (n_7758), .Y (n_7750)); + NAND2X1 g34675(.A (\u6_mem[3]_140 ), .B (n_7758), .Y (n_7749)); + NAND2X1 g34676(.A (\u6_mem[3]_122 ), .B (n_7758), .Y (n_7748)); + NAND2X1 g34677(.A (\u6_mem[3]_141 ), .B (n_7758), .Y (n_7747)); + NAND2X1 g34678(.A (\u6_mem[3]_142 ), .B (n_7758), .Y (n_7746)); + NAND2X1 g34679(.A (\u6_mem[3]_143 ), .B (n_7758), .Y (n_7745)); + NAND2X1 g34680(.A (\u6_mem[3]_144 ), .B (n_7758), .Y (n_7744)); + NAND2X1 g34681(.A (\u6_mem[3]_145 ), .B (n_7758), .Y (n_7743)); + NAND2X1 g34682(.A (\u6_mem[3]_146 ), .B (n_7758), .Y (n_7742)); + NAND2X1 g34683(.A (\u6_mem[3]_147 ), .B (n_7758), .Y (n_7741)); + NAND2X1 g34684(.A (\u6_mem[3]_148 ), .B (n_7758), .Y (n_7740)); + NAND2X1 g34685(.A (\u6_mem[3]_149 ), .B (n_7758), .Y (n_7739)); + NAND2X1 g34686(.A (\u6_mem[3]_150 ), .B (n_7758), .Y (n_7738)); + NAND2X1 g34687(.A (\u6_mem[3]_123 ), .B (n_7758), .Y (n_7737)); + NAND2X1 g34688(.A (\u6_mem[3]_151 ), .B (n_7758), .Y (n_7736)); + NAND2X1 g34689(.A (\u6_mem[3]_152 ), .B (n_7758), .Y (n_7735)); + NAND2X1 g34690(.A (\u6_mem[3]_124 ), .B (n_7758), .Y (n_7734)); + NAND2X1 g34691(.A (\u6_mem[3]_125 ), .B (n_7758), .Y (n_7733)); + NAND2X1 g34692(.A (\u6_mem[3]_126 ), .B (n_7758), .Y (n_7732)); + NAND2X1 g34694(.A (\u6_mem[3]_127 ), .B (n_7758), .Y (n_7731)); + NAND2X1 g34695(.A (\u6_mem[3]_128 ), .B (n_7758), .Y (n_7730)); + NAND2X1 g34696(.A (\u6_mem[3]_129 ), .B (n_7758), .Y (n_7729)); + NAND2X1 g34697(.A (\u6_mem[3]_130 ), .B (n_7758), .Y (n_7728)); + NAND2X1 g34698(.A (\u8_mem[3]_152 ), .B (n_7976), .Y (n_7727)); + NAND2X1 g34701(.A (\u8_mem[1]_66 ), .B (n_7976), .Y (n_7726)); + NAND2X1 g34703(.A (\u3_mem[1]_74 ), .B (n_8101), .Y (n_7725)); + NAND2X1 g34713(.A (\u3_mem[2]_29 ), .B (n_8101), .Y (n_7724)); + NAND2X1 g34714(.A (\u3_mem[2]_44 ), .B (n_8141), .Y (n_7723)); + NAND2X1 g34716(.A (\u7_mem[1] ), .B (n_7651), .Y (n_7722)); + NAND2X1 g34717(.A (\u7_mem[1]_69 ), .B (n_7651), .Y (n_7721)); + NAND2X1 g34718(.A (\u7_mem[1]_70 ), .B (n_7651), .Y (n_7719)); + NAND2X1 g34719(.A (\u7_mem[1]_71 ), .B (n_7651), .Y (n_7718)); + NAND2X1 g34720(.A (\u7_mem[1]_72 ), .B (n_7651), .Y (n_7717)); + NAND2X1 g34721(.A (\u7_mem[1]_73 ), .B (n_7651), .Y (n_7716)); + NAND2X1 g34722(.A (\u7_mem[1]_74 ), .B (n_7651), .Y (n_7715)); + NAND2X1 g34723(.A (\u7_mem[1]_75 ), .B (n_7651), .Y (n_7713)); + NAND2X1 g34724(.A (\u7_mem[1]_76 ), .B (n_7651), .Y (n_7712)); + NAND2X1 g34725(.A (\u7_mem[1]_77 ), .B (n_7651), .Y (n_7710)); + NAND2X1 g34726(.A (\u7_mem[1]_78 ), .B (n_7651), .Y (n_7708)); + NAND2X1 g34727(.A (\u7_mem[1]_60 ), .B (n_7651), .Y (n_7707)); + NAND2X1 g34728(.A (\u7_mem[1]_79 ), .B (n_7651), .Y (n_7706)); + NAND2X1 g34729(.A (\u7_mem[1]_80 ), .B (n_7651), .Y (n_7705)); + NAND2X1 g34730(.A (\u7_mem[1]_81 ), .B (n_7651), .Y (n_7704)); + NAND2X1 g34731(.A (\u7_mem[1]_82 ), .B (n_7651), .Y (n_7703)); + NAND2X1 g34732(.A (\u7_mem[1]_83 ), .B (n_7651), .Y (n_7702)); + NAND2X1 g34733(.A (\u7_mem[1]_84 ), .B (n_7651), .Y (n_7701)); + NAND2X1 g34734(.A (\u8_mem[2]_50 ), .B (n_7976), .Y (n_7700)); + NAND2X1 g34735(.A (\u7_mem[1]_85 ), .B (n_7651), .Y (n_7699)); + NAND2X1 g34736(.A (\u7_mem[1]_86 ), .B (n_7651), .Y (n_7698)); + NAND2X1 g34737(.A (\u8_mem[2]_54 ), .B (n_7976), .Y (n_7697)); + NAND2X1 g34738(.A (\u7_mem[1]_87 ), .B (n_7651), .Y (n_7696)); + NAND2X1 g34739(.A (\u7_mem[1]_88 ), .B (n_7651), .Y (n_7695)); + NAND2X1 g34740(.A (\u3_mem[1]_83 ), .B (n_8101), .Y (n_7694)); + NAND2X1 g34741(.A (\u7_mem[1]_61 ), .B (n_7651), .Y (n_7693)); + NAND2X1 g34742(.A (\u7_mem[1]_89 ), .B (n_7651), .Y (n_7692)); + NAND2X1 g34743(.A (\u7_mem[1]_62 ), .B (n_7651), .Y (n_7691)); + NAND2X1 g34744(.A (\u7_mem[1]_63 ), .B (n_7651), .Y (n_7690)); + NAND2X1 g34745(.A (\u7_mem[1]_64 ), .B (n_7651), .Y (n_7689)); + NAND2X1 g34746(.A (\u7_mem[1]_65 ), .B (n_7651), .Y (n_7688)); + NAND2X1 g34747(.A (\u7_mem[1]_66 ), .B (n_7651), .Y (n_7687)); + NAND2X1 g34748(.A (\u7_mem[1]_67 ), .B (n_7651), .Y (n_7686)); + NAND2X1 g34749(.A (\u7_mem[1]_68 ), .B (n_7651), .Y (n_7685)); + NAND2X1 g34750(.A (\u7_mem[2] ), .B (n_7651), .Y (n_7684)); + NAND2X1 g34751(.A (\u7_mem[2]_38 ), .B (n_7651), .Y (n_7683)); + NAND2X1 g34752(.A (\u7_mem[2]_39 ), .B (n_7651), .Y (n_7682)); + NAND2X1 g34753(.A (\u7_mem[2]_40 ), .B (n_7651), .Y (n_7681)); + NAND2X1 g34754(.A (\u7_mem[2]_41 ), .B (n_7651), .Y (n_7680)); + NAND2X1 g34755(.A (\u7_mem[2]_42 ), .B (n_7651), .Y (n_7679)); + NAND2X1 g34756(.A (\u7_mem[2]_43 ), .B (n_7651), .Y (n_7678)); + NAND2X1 g34757(.A (\u7_mem[2]_44 ), .B (n_7651), .Y (n_7677)); + NAND2X1 g34758(.A (\u7_mem[2]_45 ), .B (n_7651), .Y (n_7676)); + NAND2X1 g34759(.A (\u7_mem[2]_46 ), .B (n_7651), .Y (n_7675)); + NAND2X1 g34760(.A (\u7_mem[2]_47 ), .B (n_7651), .Y (n_7674)); + NAND2X1 g34761(.A (\u7_mem[2]_48 ), .B (n_7651), .Y (n_7673)); + NAND2X1 g34762(.A (\u7_mem[2]_49 ), .B (n_7651), .Y (n_7672)); + NAND2X1 g34763(.A (\u7_mem[2]_50 ), .B (n_7651), .Y (n_7671)); + NAND2X1 g34764(.A (\u7_mem[2]_51 ), .B (n_7651), .Y (n_7670)); + NAND2X1 g34765(.A (\u7_mem[2]_52 ), .B (n_7651), .Y (n_7669)); + NAND2X1 g34766(.A (\u7_mem[2]_53 ), .B (n_7651), .Y (n_7668)); + NAND2X1 g34767(.A (\u7_mem[2]_54 ), .B (n_7651), .Y (n_7667)); + NAND2X1 g34768(.A (\u7_mem[2]_55 ), .B (n_7651), .Y (n_7666)); + NAND2X1 g34769(.A (\u7_mem[2]_56 ), .B (n_7651), .Y (n_7665)); + NAND2X1 g34770(.A (\u7_mem[2]_30 ), .B (n_7651), .Y (n_7664)); + NAND2X1 g34771(.A (\u7_mem[2]_58 ), .B (n_7651), .Y (n_7663)); + NAND2X1 g34772(.A (\u8_mem[2]_52 ), .B (n_7976), .Y (n_7662)); + NAND2X1 g34773(.A (\u7_mem[2]_59 ), .B (n_7651), .Y (n_7661)); + NAND2X1 g34774(.A (\u7_mem[2]_31 ), .B (n_7651), .Y (n_7660)); + NAND2X1 g34775(.A (\u7_mem[2]_32 ), .B (n_7651), .Y (n_7659)); + NAND2X1 g34776(.A (\u7_mem[2]_33 ), .B (n_7651), .Y (n_7658)); + NAND2X1 g34777(.A (\u7_mem[2]_34 ), .B (n_7651), .Y (n_7657)); + NAND2X1 g34778(.A (\u7_mem[2]_35 ), .B (n_7651), .Y (n_7656)); + NAND2X1 g34779(.A (\u7_mem[2]_36 ), .B (n_7651), .Y (n_7655)); + NAND2X1 g34780(.A (\u7_mem[2]_37 ), .B (n_7651), .Y (n_7654)); + NAND2X1 g34781(.A (\u7_mem[3] ), .B (n_7651), .Y (n_7653)); + NAND2X1 g34782(.A (\u7_mem[3]_131 ), .B (n_7651), .Y (n_7652)); + NAND2X1 g34783(.A (\u7_mem[3]_132 ), .B (n_7651), .Y (n_7650)); + NAND2X1 g34784(.A (\u7_mem[3]_133 ), .B (n_7651), .Y (n_7649)); + NAND2X1 g34785(.A (\u7_mem[3]_134 ), .B (n_7651), .Y (n_7648)); + NAND2X1 g34786(.A (\u7_mem[3]_135 ), .B (n_7651), .Y (n_7647)); + NAND2X1 g34787(.A (\u7_mem[3]_136 ), .B (n_7651), .Y (n_7646)); + NAND2X1 g34788(.A (\u7_mem[3]_137 ), .B (n_7651), .Y (n_7645)); + NAND2X1 g34789(.A (\u7_mem[3]_138 ), .B (n_7651), .Y (n_7644)); + NAND2X1 g34790(.A (\u7_mem[3]_139 ), .B (n_7651), .Y (n_7643)); + NAND2X1 g34791(.A (\u7_mem[3]_140 ), .B (n_7651), .Y (n_7642)); + NAND2X1 g34792(.A (\u7_mem[3]_122 ), .B (n_7651), .Y (n_7641)); + NAND2X1 g34793(.A (\u7_mem[3]_141 ), .B (n_7651), .Y (n_7640)); + NAND2X1 g34794(.A (\u7_mem[3]_142 ), .B (n_7651), .Y (n_7639)); + NAND2X1 g34795(.A (\u7_mem[3]_143 ), .B (n_7651), .Y (n_7638)); + NAND2X1 g34796(.A (\u7_mem[3]_144 ), .B (n_7651), .Y (n_7637)); + NAND2X1 g34797(.A (\u7_mem[3]_145 ), .B (n_7651), .Y (n_7636)); + NAND2X1 g34798(.A (\u7_mem[3]_146 ), .B (n_7651), .Y (n_7635)); + NAND2X1 g34799(.A (\u7_mem[3]_147 ), .B (n_7651), .Y (n_7634)); + NAND2X1 g34800(.A (\u7_mem[3]_148 ), .B (n_7651), .Y (n_7633)); + NAND2X1 g34801(.A (\u7_mem[3]_149 ), .B (n_7651), .Y (n_7632)); + NAND2X1 g34802(.A (\u7_mem[3]_150 ), .B (n_7651), .Y (n_7631)); + NAND2X1 g34803(.A (\u7_mem[3]_123 ), .B (n_7651), .Y (n_7630)); + NAND2X1 g34804(.A (\u8_mem[3]_137 ), .B (n_7976), .Y (n_7629)); + NAND2X1 g34805(.A (\u7_mem[3]_151 ), .B (n_7651), .Y (n_7628)); + NAND2X1 g34806(.A (\u7_mem[3]_152 ), .B (n_7651), .Y (n_7627)); + NAND2X1 g34807(.A (\u7_mem[3]_124 ), .B (n_7651), .Y (n_7626)); + NAND2X1 g34808(.A (\u7_mem[3]_125 ), .B (n_7651), .Y (n_7625)); + NAND2X1 g34809(.A (\u7_mem[3]_126 ), .B (n_7651), .Y (n_7624)); + NAND2X1 g34810(.A (\u7_mem[3]_127 ), .B (n_7651), .Y (n_7623)); + NAND2X1 g34811(.A (\u7_mem[3]_128 ), .B (n_7651), .Y (n_7622)); + NAND2X1 g34812(.A (\u7_mem[3]_129 ), .B (n_7651), .Y (n_7621)); + NAND2X1 g34813(.A (\u7_mem[3]_130 ), .B (n_7651), .Y (n_7620)); + NAND2X1 g34815(.A (\u3_mem[3]_151 ), .B (n_8097), .Y (n_7619)); + NAND2X1 g34816(.A (\u3_mem[1]_63 ), .B (n_8141), .Y (n_7618)); + NAND2X1 g34817(.A (\u3_mem[2]_45 ), .B (n_8101), .Y (n_7617)); + NAND2X1 g34818(.A (\u8_mem[2]_48 ), .B (n_7976), .Y (n_7616)); + NAND2X1 g34819(.A (\u8_mem[1]_69 ), .B (n_7976), .Y (n_7615)); + NAND2X1 g34820(.A (\u8_mem[1]_70 ), .B (n_7976), .Y (n_7614)); + NAND2X1 g34821(.A (\u8_mem[1]_72 ), .B (n_7976), .Y (n_7613)); + NAND2X1 g34822(.A (\u8_mem[1]_73 ), .B (n_7976), .Y (n_7612)); + NAND2X1 g34823(.A (\u8_mem[1]_74 ), .B (n_7976), .Y (n_7611)); + NAND2X1 g34824(.A (\u8_mem[1]_76 ), .B (n_7976), .Y (n_7610)); + NAND2X1 g34825(.A (\u8_mem[3]_133 ), .B (n_7976), .Y (n_7609)); + NAND2X1 g34826(.A (\u8_mem[1]_77 ), .B (n_7976), .Y (n_7608)); + NAND2X1 g34827(.A (\u3_mem[1]_90 ), .B (n_8101), .Y (n_7607)); + NAND2X1 g34828(.A (\u8_mem[1]_78 ), .B (n_7976), .Y (n_7606)); + NAND2X1 g34829(.A (\u8_mem[1]_79 ), .B (n_7976), .Y (n_7605)); + NAND2X1 g34830(.A (\u8_mem[1]_80 ), .B (n_7976), .Y (n_7604)); + NAND2X1 g34831(.A (\u8_mem[1]_81 ), .B (n_7976), .Y (n_7603)); + NAND2X1 g34832(.A (\u8_mem[1]_83 ), .B (n_7976), .Y (n_7602)); + NAND2X1 g34833(.A (\u8_mem[1]_84 ), .B (n_7976), .Y (n_7601)); + NAND2X1 g34834(.A (\u3_mem[1] ), .B (n_8141), .Y (n_7600)); + NAND2X1 g34835(.A (\u8_mem[1]_85 ), .B (n_7976), .Y (n_7599)); + NAND2X1 g34836(.A (\u8_mem[1]_86 ), .B (n_7976), .Y (n_7598)); + NAND2X1 g34837(.A (\u3_mem[1]_69 ), .B (n_8101), .Y (n_7597)); + NAND2X1 g34838(.A (\u8_mem[1]_87 ), .B (n_7976), .Y (n_7596)); + NAND2X1 g34839(.A (\u8_mem[1]_61 ), .B (n_7976), .Y (n_7595)); + NAND2X1 g34840(.A (\u8_mem[1]_89 ), .B (n_7976), .Y (n_7594)); + NAND2X1 g34841(.A (\u3_mem[1]_71 ), .B (n_8101), .Y (n_7593)); + NAND2X1 g34842(.A (\u8_mem[1]_90 ), .B (n_7976), .Y (n_7592)); + NAND2X1 g34843(.A (\u3_mem[1]_72 ), .B (n_8101), .Y (n_7591)); + NAND2X1 g34844(.A (\u8_mem[1]_64 ), .B (n_7976), .Y (n_7590)); + NAND2X1 g34845(.A (\u3_mem[1]_73 ), .B (n_8141), .Y (n_7589)); + NAND2X1 g34846(.A (\u8_mem[1]_65 ), .B (n_7976), .Y (n_7588)); + NAND2X1 g34847(.A (\u8_mem[1]_67 ), .B (n_7976), .Y (n_7587)); + NAND2X1 g34848(.A (\u8_mem[1]_68 ), .B (n_7976), .Y (n_7586)); + NAND2X1 g34849(.A (\u3_mem[1]_75 ), .B (n_8141), .Y (n_7585)); + NAND2X1 g34850(.A (\u8_mem[2] ), .B (n_7976), .Y (n_7584)); + NAND2X1 g34851(.A (\u8_mem[2]_38 ), .B (n_7976), .Y (n_7583)); + NAND2X1 g34852(.A (\u8_mem[2]_40 ), .B (n_7976), .Y (n_7582)); + NAND2X1 g34853(.A (\u3_mem[1]_77 ), .B (n_8141), .Y (n_7581)); + NAND2X1 g34854(.A (\u8_mem[2]_47 ), .B (n_7976), .Y (n_7580)); + NAND2X1 g34855(.A (\u8_mem[2]_42 ), .B (n_7976), .Y (n_7579)); + NAND2X1 g34856(.A (\u3_mem[1]_78 ), .B (n_8141), .Y (n_7578)); + NAND2X1 g34857(.A (\u8_mem[2]_43 ), .B (n_7976), .Y (n_7577)); + NAND2X1 g34858(.A (\u8_mem[2]_44 ), .B (n_7976), .Y (n_7576)); + NAND2X1 g34859(.A (\u3_mem[1]_60 ), .B (n_8101), .Y (n_7575)); + NAND2X1 g34860(.A (\u8_mem[2]_46 ), .B (n_7976), .Y (n_7574)); + NAND2X1 g34861(.A (\u8_mem[2]_29 ), .B (n_7976), .Y (n_7573)); + NAND2X1 g34862(.A (\u3_mem[1]_80 ), .B (n_8101), .Y (n_7572)); + NAND2X1 g34863(.A (\u8_mem[2]_49 ), .B (n_7976), .Y (n_7571)); + NAND2X1 g34864(.A (\u3_mem[1]_81 ), .B (n_8141), .Y (n_7570)); + NAND2X1 g34865(.A (\u8_mem[2]_51 ), .B (n_7976), .Y (n_7569)); + NAND2X1 g34866(.A (\u3_mem[1]_82 ), .B (n_8101), .Y (n_7568)); + NAND2X1 g34867(.A (\u8_mem[2]_53 ), .B (n_7976), .Y (n_7567)); + NAND2X1 g34868(.A (\u8_mem[2]_55 ), .B (n_7976), .Y (n_7566)); + NAND2X1 g34869(.A (\u3_mem[1]_84 ), .B (n_8101), .Y (n_7565)); + NAND2X1 g34870(.A (\u8_mem[1]_88 ), .B (n_7976), .Y (n_7564)); + NAND2X1 g34871(.A (\u8_mem[2]_57 ), .B (n_7976), .Y (n_7563)); + NAND2X1 g34872(.A (\u3_mem[1]_85 ), .B (n_8101), .Y (n_7562)); + NAND2X1 g34873(.A (\u8_mem[2]_30 ), .B (n_7976), .Y (n_7561)); + NAND2X1 g34874(.A (\u8_mem[2]_58 ), .B (n_7976), .Y (n_7560)); + NAND2X1 g34875(.A (\u3_mem[1]_86 ), .B (n_8141), .Y (n_7559)); + NAND2X1 g34876(.A (\u8_mem[2]_31 ), .B (n_7976), .Y (n_7558)); + MX2X1 g34910(.A (i4_full), .B (u14_u7_full_empty_r), .S0 (n_7357), .Y + (n_7557)); + INVX1 g35286(.A (n_7481), .Y (n_8210)); + NOR2X1 g35300(.A (n_1301), .B (n_12335), .Y (n_7542)); + NOR2X1 g35304(.A (n_1372), .B (n_12335), .Y (n_7541)); + NOR2X1 g35308(.A (n_1355), .B (n_12335), .Y (n_7539)); + NOR2X1 g35312(.A (n_1100), .B (n_12335), .Y (n_7538)); + NOR2X1 g35316(.A (n_7017), .B (n_12335), .Y (n_7537)); + INVX1 g35332(.A (n_7536), .Y (n_8679)); + OAI21X1 g32697(.A0 (n_5595), .A1 (n_7532), .B0 (n_7531), .Y (n_7533)); + OAI21X1 g32699(.A0 (n_5594), .A1 (n_7529), .B0 (n_7528), .Y (n_7530)); + AOI21X1 g32984(.A0 (n_7384), .A1 (n_7385), .B0 (n_7526), .Y (n_7527)); + AOI21X1 g32985(.A0 (n_7381), .A1 (n_7382), .B0 (n_7524), .Y (n_7525)); + DFFSRX1 u3_empty_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_7436), .Q (), .QN (o3_empty)); + DFFSRX1 u5_empty_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_7438), .Q (), .QN (o6_empty)); + DFFSRX1 u7_empty_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_7437), .Q (), .QN (o8_empty)); + DFFSRX1 u8_empty_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_7435), .Q (), .QN (o9_empty)); + AND2X1 g33264(.A (n_7521), .B (wb_din), .Y (n_7523)); + AND2X1 g33275(.A (n_7521), .B (wb_din_661), .Y (n_7522)); + OR2X1 g33394(.A (n_5439), .B (n_7519), .Y (n_7520)); + DFFX1 \u10_rp_reg[2] (.CK (clk_i), .D (n_7372), .Q (\u10_rp[2] ), .QN + ()); + DFFX1 \u11_rp_reg[2] (.CK (clk_i), .D (n_7373), .Q (\u11_rp[2] ), .QN + ()); + INVX2 g34406(.A (n_7518), .Y (n_8643)); + INVX2 g34449(.A (n_7515), .Y (n_8611)); + INVX4 g34475(.A (n_7445), .Y (n_8519)); + INVX4 g34485(.A (n_7514), .Y (n_8538)); + NOR2X1 g34878(.A (n_7367), .B (n_4802), .Y (n_7513)); + NOR2X1 g34893(.A (n_7365), .B (n_4800), .Y (n_7512)); + MX2X1 g34908(.A (u1_sr_122), .B (in_slt_424), .S0 (out_le_183), .Y + (n_7511)); + MX2X1 g34912(.A (u1_sr_122), .B (in_slt_832), .S0 (out_le_181), .Y + (n_7510)); + MX2X1 g34913(.A (u1_sr_122), .B (in_slt_402), .S0 (out_le_182), .Y + (n_7509)); + MX2X1 g34914(.A (u1_sr_122), .B (in_slt_446), .S0 (out_le_184), .Y + (n_7508)); + MX2X1 g34915(.A (u1_sr_122), .B (in_slt_748), .S0 (out_le_180), .Y + (n_7507)); + INVX4 g34977(.A (n_8141), .Y (n_8700)); + NAND2X1 g35272(.A (n_6674), .B (n_7331), .Y (n_7488)); + NAND2X1 g35273(.A (n_6678), .B (n_7330), .Y (n_7487)); + NAND2X1 g35274(.A (n_6699), .B (n_7336), .Y (n_7486)); + NAND2X1 g35276(.A (n_7112), .B (n_7335), .Y (n_7485)); + NAND2X1 g35277(.A (n_6685), .B (n_7333), .Y (n_7484)); + NAND2X1 g35278(.A (n_6690), .B (n_7332), .Y (n_7483)); + NAND2X1 g35279(.A (n_7329), .B (n_6697), .Y (n_7482)); + NOR2X1 g35287(.A (n_7477), .B (n_1119), .Y (n_7481)); + NOR2X1 g35318(.A (\in_valid_s[0] ), .B (n_1308), .Y (n_9352)); + OR2X1 g35319(.A (n_11563), .B (\in_valid_s[0] ), .Y (n_7480)); + NAND2X1 g35320(.A (n_11600), .B (\in_valid_s[1] ), .Y (n_7479)); + OR2X1 g35321(.A (n_11762), .B (n_7477), .Y (n_7478)); + NAND2X1 g35326(.A (n_6745), .B (n_7337), .Y (n_7476)); + INVX1 g35333(.A (n_7395), .Y (n_7536)); + AOI21X1 g35339(.A0 (i4_dout), .A1 (n_7468), .B0 (n_7352), .Y + (n_7475)); + AOI21X1 g35340(.A0 (i4_dout_605), .A1 (n_7468), .B0 (n_7351), .Y + (n_7473)); + AOI21X1 g35341(.A0 (i4_dout_606), .A1 (n_7468), .B0 (n_7350), .Y + (n_7472)); + AOI21X1 g35342(.A0 (i4_dout_609), .A1 (n_7468), .B0 (n_7354), .Y + (n_7471)); + AOI21X1 g35343(.A0 (i4_dout_596), .A1 (n_7468), .B0 (n_7347), .Y + (n_7470)); + AOI21X1 g35344(.A0 (i4_dout_597), .A1 (n_7468), .B0 (n_7346), .Y + (n_7469)); + AOI21X1 g35345(.A0 (i4_dout_598), .A1 (n_7468), .B0 (n_7345), .Y + (n_7467)); + AOI21X1 g35346(.A0 (i4_dout_599), .A1 (n_7468), .B0 (n_7344), .Y + (n_7466)); + AOI21X1 g35347(.A0 (i4_dout_600), .A1 (n_7468), .B0 (n_7343), .Y + (n_7465)); + AOI21X1 g35348(.A0 (i4_dout_601), .A1 (n_7468), .B0 (n_7342), .Y + (n_7464)); + AOI21X1 g35349(.A0 (i4_dout_602), .A1 (n_7468), .B0 (n_7341), .Y + (n_7463)); + AOI21X1 g35350(.A0 (n_7468), .A1 (i4_dout_603), .B0 (n_7340), .Y + (n_7462)); + AOI21X1 g35351(.A0 (i4_dout_607), .A1 (n_7468), .B0 (n_7349), .Y + (n_7461)); + AOI21X1 g35352(.A0 (i4_dout_608), .A1 (n_7297), .B0 (n_7348), .Y + (n_7460)); + AOI21X1 g35356(.A0 (i4_dout_604), .A1 (n_7468), .B0 (n_7339), .Y + (n_7459)); + AOI21X1 g35360(.A0 (n_6972), .A1 (oc0_cfg_964), .B0 (n_7338), .Y + (n_7458)); + NAND2X1 g35444(.A (n_7303), .B (n_6673), .Y (n_7457)); + NAND2X1 g35445(.A (n_7386), .B (n_7012), .Y (n_7456)); + NAND2X1 g35446(.A (n_7301), .B (n_6696), .Y (n_7455)); + NAND2X1 g35447(.A (n_7300), .B (n_6694), .Y (n_7454)); + NAND2X1 g35448(.A (n_7299), .B (n_6693), .Y (n_7453)); + NAND2X1 g35449(.A (n_7296), .B (n_6737), .Y (n_7452)); + NAND2X1 g35450(.A (n_7298), .B (n_6743), .Y (n_7451)); + NAND2X1 g35451(.A (n_6692), .B (n_7302), .Y (n_7450)); + DFFSRX1 \u23_int_set_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_7364), .Q (ic0_int_set_719), .QN ()); + DFFSRX1 \u24_int_set_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_7363), .Q (ic1_int_set_721), .QN ()); + DFFX1 \u11_rp_reg[1] (.CK (clk_i), .D (n_7375), .Q (\u11_rp[1] ), .QN + ()); + DFFX1 \u9_rp_reg[1] (.CK (clk_i), .D (n_7377), .Q (\u9_rp[1] ), .QN + ()); + DFFX1 \u10_rp_reg[1] (.CK (clk_i), .D (n_7376), .Q (\u10_rp[1] ), .QN + ()); + DFFX1 \u11_rp_reg[0] (.CK (clk_i), .D (n_7371), .Q (\u11_rp[0] ), .QN + ()); + DFFX1 \u9_rp_reg[0] (.CK (clk_i), .D (n_7369), .Q (\u9_rp[0] ), .QN + ()); + DFFX1 \u9_rp_reg[2] (.CK (clk_i), .D (n_7374), .Q (\u9_rp[2] ), .QN + ()); + DFFX1 \u10_rp_reg[0] (.CK (clk_i), .D (n_7366), .Q (\u10_rp[0] ), .QN + ()); + DFFX1 \u1_slt1_reg[5] (.CK (bit_clk_pad_i), .D (n_7359), .Q + (in_slt_747), .QN ()); + DFFX1 \u1_slt2_reg[5] (.CK (bit_clk_pad_i), .D (n_7360), .Q + (in_slt_831), .QN ()); + DFFX1 \u1_slt4_reg[5] (.CK (bit_clk_pad_i), .D (n_7362), .Q + (in_slt_423), .QN ()); + DFFX1 \u1_slt3_reg[5] (.CK (bit_clk_pad_i), .D (n_7358), .Q + (in_slt_401), .QN ()); + DFFX1 \u1_slt6_reg[5] (.CK (bit_clk_pad_i), .D (n_7361), .Q + (in_slt_445), .QN ()); + OR2X1 g33392(.A (n_5597), .B (n_7448), .Y (n_7449)); + OR2X1 g33393(.A (n_5596), .B (n_7446), .Y (n_7447)); + DFFSRX1 \u25_int_set_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_7280), .Q (ic2_int_set_723), .QN ()); + AND2X1 g34404(.A (n_7287), .B (n_7443), .Y (n_7521)); + NAND2X1 g34414(.A (n_7444), .B (n_996), .Y (n_7518)); + NAND2X1 g34451(.A (n_6042), .B (n_7442), .Y (n_7515)); + NAND2X1 g34476(.A (n_7444), .B (n_6044), .Y (n_7445)); + AND2X1 g34487(.A (n_7286), .B (n_7443), .Y (n_7514)); + NAND2X2 g34490(.A (n_1225), .B (n_7442), .Y (n_8202)); + NAND2X1 g34710(.A (n_7441), .B (n_7439), .Y (n_8208)); + OR2X1 g34711(.A (i6_status), .B (n_7439), .Y (n_7440)); + NOR2X1 g34882(.A (n_7285), .B (n_2595), .Y (n_7438)); + NOR2X1 g34896(.A (n_12838), .B (n_12837), .Y (n_7437)); + NOR2X1 g34898(.A (n_7282), .B (n_4796), .Y (n_7436)); + NOR2X1 g34899(.A (n_7281), .B (n_3993), .Y (n_7435)); + OR2X1 g34902(.A (n_7434), .B (n_11534), .Y (n_7519)); + INVX1 g34919(.A (n_7428), .Y (n_9110)); + INVX1 g34921(.A (n_7428), .Y (n_9087)); + INVX1 g34922(.A (n_7428), .Y (n_9100)); + INVX1 g34923(.A (n_7428), .Y (n_9077)); + INVX1 g34925(.A (n_7428), .Y (n_9105)); + INVX1 g34926(.A (n_7428), .Y (n_9080)); + INVX1 g34928(.A (n_7428), .Y (n_9170)); + INVX2 g34929(.A (n_7428), .Y (n_9182)); + INVX8 g34952(.A (n_7758), .Y (n_7505)); + INVX1 g34962(.A (n_7428), .Y (n_9165)); + INVX1 g34966(.A (n_7428), .Y (n_9139)); + INVX2 g34968(.A (n_7428), .Y (n_9161)); + INVX2 g34983(.A (n_7423), .Y (n_8097)); + INVX4 g34989(.A (n_7423), .Y (n_8101)); + INVX1 g34992(.A (n_7424), .Y (n_8387)); + INVX1 g34993(.A (n_7424), .Y (n_8357)); + INVX1 g34994(.A (n_7424), .Y (n_8380)); + INVX1 g34995(.A (n_7424), .Y (n_8383)); + INVX1 g34996(.A (n_7424), .Y (n_8372)); + INVX1 g34997(.A (n_7424), .Y (n_8369)); + INVX1 g34998(.A (n_7424), .Y (n_9022)); + INVX1 g34999(.A (n_7424), .Y (n_8375)); + INVX2 g35002(.A (n_7423), .Y (n_8856)); + INVX2 g35012(.A (n_7424), .Y (n_8911)); + INVX1 g35015(.A (n_7424), .Y (n_8393)); + INVX1 g35017(.A (n_7424), .Y (n_8440)); + INVX1 g35036(.A (n_7414), .Y (n_9333)); + INVX1 g35037(.A (n_7414), .Y (n_9346)); + INVX1 g35039(.A (n_7414), .Y (n_9336)); + INVX2 g35040(.A (n_7414), .Y (n_9349)); + INVX1 g35041(.A (n_7414), .Y (n_9326)); + INVX2 g35046(.A (n_7414), .Y (n_8333)); + INVX8 g35067(.A (n_7984), .Y (n_7499)); + INVX2 g35077(.A (n_7414), .Y (n_8318)); + INVX1 g35086(.A (n_7408), .Y (n_9235)); + INVX1 g35088(.A (n_7408), .Y (n_9212)); + INVX1 g35090(.A (n_7408), .Y (n_9202)); + INVX1 g35092(.A (n_7408), .Y (n_9230)); + INVX1 g35093(.A (n_7408), .Y (n_9205)); + INVX2 g35096(.A (n_7408), .Y (n_9307)); + INVX1 g35097(.A (n_7408), .Y (n_9288)); + INVX8 g35119(.A (n_7870), .Y (n_7496)); + INVX1 g35129(.A (n_7408), .Y (n_9290)); + INVX1 g35133(.A (n_7408), .Y (n_9264)); + INVX2 g35135(.A (n_7408), .Y (n_9286)); + INVX1 g35138(.A (n_7402), .Y (n_8981)); + INVX1 g35140(.A (n_7402), .Y (n_8958)); + INVX1 g35141(.A (n_7402), .Y (n_8971)); + INVX1 g35142(.A (n_7402), .Y (n_8948)); + INVX1 g35143(.A (n_7402), .Y (n_8961)); + INVX1 g35144(.A (n_7402), .Y (n_8976)); + INVX1 g35145(.A (n_7402), .Y (n_8951)); + INVX1 g35147(.A (n_7402), .Y (n_9043)); + INVX2 g35148(.A (n_7402), .Y (n_9055)); + INVX1 g35149(.A (n_7402), .Y (n_9036)); + INVX8 g35171(.A (n_7651), .Y (n_7493)); + INVX1 g35181(.A (n_7402), .Y (n_9038)); + INVX1 g35185(.A (n_7402), .Y (n_9010)); + INVX2 g35187(.A (n_7402), .Y (n_9034)); + INVX1 g35190(.A (n_7396), .Y (n_8433)); + INVX1 g35192(.A (n_7396), .Y (n_8453)); + INVX1 g35193(.A (n_7396), .Y (n_8449)); + INVX1 g35195(.A (n_7396), .Y (n_8457)); + INVX1 g35196(.A (n_7396), .Y (n_8438)); + INVX1 g35197(.A (n_7396), .Y (n_8464)); + INVX1 g35199(.A (n_7396), .Y (n_8930)); + INVX1 g35202(.A (n_7396), .Y (n_8868)); + INVX1 g35206(.A (n_7396), .Y (n_8898)); + INVX8 g35223(.A (n_7976), .Y (n_7490)); + INVX1 g35233(.A (n_7396), .Y (n_8894)); + INVX1 g35238(.A (n_7396), .Y (n_8891)); + INVX1 g35239(.A (n_7396), .Y (n_8933)); + DFFX1 \u1_sr_reg[7] (.CK (bit_clk_pad_i), .D (u1_sr_122), .Q + (u1_sr_123), .QN ()); + NOR2X1 g35334(.A (n_7356), .B (n_1124), .Y (n_7395)); + DFFX1 \u0_slt9_r_reg[0] (.CK (bit_clk_pad_i), .D (n_7231), .Q + (u0_slt9_r), .QN ()); + INVX1 g35410(.A (\in_valid_s[0] ), .Y (n_7389)); + INVX1 g35416(.A (n_7477), .Y (n_7388)); + AOI21X1 g33284(.A0 (n_7157), .A1 (n_1230), .B0 (n_7434), .Y (n_7387)); + AOI21X1 g35671(.A0 (i3_dout_588), .A1 (n_6700), .B0 (n_7106), .Y + (n_7386)); + NAND2X1 g34704(.A (n_7385), .B (n_7383), .Y (n_7532)); + OR2X1 g34705(.A (i3_status), .B (n_7383), .Y (n_7384)); + NAND2X1 g34707(.A (n_7382), .B (n_7380), .Y (n_7529)); + OR2X1 g34708(.A (i4_status), .B (n_7380), .Y (n_7381)); + OR2X1 g34900(.A (n_7379), .B (n_11887), .Y (n_7448)); + OR2X1 g34901(.A (n_7378), .B (n_11888), .Y (n_7446)); + INVX8 g34941(.A (o7_we), .Y (n_7758)); + BUFX3 g34969(.A (o7_we), .Y (n_7428)); + CLKBUFX1 g35000(.A (o3_we), .Y (n_7424)); + BUFX3 g35009(.A (o3_we), .Y (n_7423)); + INVX2 g35032(.A (o3_we), .Y (n_8141)); + INVX8 g35056(.A (o4_we), .Y (n_7984)); + BUFX3 g35084(.A (o4_we), .Y (n_7414)); + INVX8 g35108(.A (o6_we), .Y (n_7870)); + CLKBUFX1 g35136(.A (o6_we), .Y (n_7408)); + INVX8 g35160(.A (o8_we), .Y (n_7651)); + BUFX3 g35188(.A (o8_we), .Y (n_7402)); + INVX8 g35212(.A (o9_we), .Y (n_7976)); + CLKBUFX1 g35240(.A (o9_we), .Y (n_7396)); + NOR2X1 g35264(.A (n_7152), .B (n_11563), .Y (n_7377)); + NOR2X1 g35265(.A (n_7150), .B (n_11597), .Y (n_7376)); + NOR2X1 g35266(.A (n_7153), .B (n_11762), .Y (n_7375)); + NOR2X1 g35267(.A (n_7147), .B (n_11563), .Y (n_7374)); + NOR2X1 g35268(.A (n_7146), .B (n_11762), .Y (n_7373)); + NOR2X1 g35269(.A (n_7145), .B (n_11597), .Y (n_7372)); + NOR2X1 g35271(.A (n_7141), .B (n_11762), .Y (n_7371)); + NOR2X1 g35275(.A (n_7143), .B (n_11563), .Y (n_7369)); + NAND3X1 g35280(.A (n_6330), .B (n_7011), .C (n_1460), .Y (n_7367)); + NOR2X1 g35283(.A (n_7142), .B (n_11597), .Y (n_7366)); + NAND3X1 g35325(.A (n_7050), .B (n_5965), .C (n_2271), .Y (n_7365)); + OR2X1 g35357(.A (n_7149), .B (ic0_int_set_719), .Y (n_7364)); + OR2X1 g35358(.A (n_7148), .B (ic1_int_set_721), .Y (n_7363)); + MX2X1 g35363(.A (u1_sr_121), .B (in_slt_423), .S0 (out_le_183), .Y + (n_7362)); + MX2X1 g35364(.A (u1_sr_121), .B (in_slt_445), .S0 (out_le_184), .Y + (n_7361)); + MX2X1 g35365(.A (u1_sr_121), .B (in_slt_831), .S0 (out_le_181), .Y + (n_7360)); + MX2X1 g35366(.A (u1_sr_121), .B (in_slt_747), .S0 (out_le_180), .Y + (n_7359)); + MX2X1 g35370(.A (u1_sr_121), .B (in_slt_401), .S0 (out_le_182), .Y + (n_7358)); + DFFSRX1 valid_s_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (valid_s1), .Q (valid_s), .QN ()); + DFFSRX1 \in_valid_s_reg[0] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (in_valid_s1), .Q (), .QN (\in_valid_s[0] )); + INVX1 g35412(.A (n_7356), .Y (n_7357)); + INVX1 g35417(.A (\in_valid_s[2] ), .Y (n_7477)); + AOI21X1 g35420(.A0 (n_6969), .A1 (n_4693), .B0 (n_7353), .Y (n_7354)); + AOI21X1 g35421(.A0 (n_6974), .A1 (n_4742), .B0 (n_7353), .Y (n_7352)); + AOI21X1 g35422(.A0 (n_6973), .A1 (n_4692), .B0 (n_7353), .Y (n_7351)); + AOI21X1 g35423(.A0 (n_6960), .A1 (n_4737), .B0 (n_7353), .Y (n_7350)); + AOI21X1 g35424(.A0 (n_6971), .A1 (n_4735), .B0 (n_7353), .Y (n_7349)); + AOI21X1 g35425(.A0 (n_6958), .A1 (n_4689), .B0 (n_7353), .Y (n_7348)); + AOI21X1 g35426(.A0 (n_6968), .A1 (n_4715), .B0 (n_7353), .Y (n_7347)); + AOI21X1 g35427(.A0 (n_6967), .A1 (n_4712), .B0 (n_7353), .Y (n_7346)); + AOI21X1 g35428(.A0 (n_6966), .A1 (n_4709), .B0 (n_7353), .Y (n_7345)); + AOI21X1 g35429(.A0 (n_6965), .A1 (n_4704), .B0 (n_7353), .Y (n_7344)); + AOI21X1 g35430(.A0 (n_6964), .A1 (n_4702), .B0 (n_7353), .Y (n_7343)); + AOI21X1 g35431(.A0 (n_6963), .A1 (n_4698), .B0 (n_7353), .Y (n_7342)); + AOI21X1 g35432(.A0 (n_6962), .A1 (n_4697), .B0 (n_7353), .Y (n_7341)); + AOI21X1 g35433(.A0 (n_6961), .A1 (n_4695), .B0 (n_7353), .Y (n_7340)); + AOI21X1 g35434(.A0 (n_6959), .A1 (n_4741), .B0 (n_7353), .Y (n_7339)); + NAND2X1 g35443(.A (n_5276), .B (n_7113), .Y (n_7338)); + DFFX1 \u1_slt2_reg[4] (.CK (bit_clk_pad_i), .D (n_7144), .Q + (in_slt_830), .QN ()); + AOI21X1 g35467(.A0 (i4_dout_612), .A1 (n_7468), .B0 (n_7139), .Y + (n_7337)); + AOI21X1 g35468(.A0 (i4_dout_613), .A1 (n_7468), .B0 (n_7138), .Y + (n_7336)); + AOI21X1 g35470(.A0 (i3_dout_583), .A1 (n_6700), .B0 (n_7137), .Y + (n_7335)); + AOI21X1 g35471(.A0 (i4_dout_615), .A1 (n_7468), .B0 (n_7136), .Y + (n_7333)); + AOI21X1 g35472(.A0 (i4_dout_616), .A1 (n_7468), .B0 (n_7135), .Y + (n_7332)); + AOI21X1 g35473(.A0 (i3_dout_579), .A1 (n_6700), .B0 (n_7134), .Y + (n_7331)); + AOI21X1 g35479(.A0 (i4_dout_611), .A1 (n_7468), .B0 (n_7140), .Y + (n_7330)); + AOI21X1 g35488(.A0 (i4_dout_617), .A1 (n_7468), .B0 (n_7133), .Y + (n_7329)); + AOI21X1 g35565(.A0 (n_6818), .A1 (n_6135), .B0 (n_12145), .Y + (n_7328)); + AOI21X1 g35573(.A0 (n_6825), .A1 (n_6123), .B0 (n_7324), .Y (n_7327)); + AOI21X1 g35574(.A0 (n_6834), .A1 (n_6127), .B0 (n_7324), .Y (n_7326)); + AOI21X1 g35575(.A0 (n_6833), .A1 (n_6126), .B0 (n_7324), .Y (n_7325)); + AOI21X1 g35579(.A0 (n_11539), .A1 (n_11540), .B0 (n_12145), .Y + (n_7320)); + AOI21X1 g35580(.A0 (n_11541), .A1 (n_11542), .B0 (n_12145), .Y + (n_7319)); + AOI21X1 g35596(.A0 (n_6819), .A1 (n_6130), .B0 (n_12145), .Y + (n_7318)); + AOI21X1 g35608(.A0 (n_6823), .A1 (n_6112), .B0 (n_7256), .Y (n_7316)); + AOI21X1 g35609(.A0 (n_6826), .A1 (n_6111), .B0 (n_7256), .Y (n_7315)); + AOI21X1 g35611(.A0 (n_6822), .A1 (n_6109), .B0 (n_7256), .Y (n_7314)); + AOI21X1 g35617(.A0 (n_6766), .A1 (n_6307), .B0 (n_7256), .Y (n_7312)); + AOI21X1 g35618(.A0 (n_5830), .A1 (n_6820), .B0 (n_7256), .Y (n_7311)); + AOI21X1 g35619(.A0 (n_6782), .A1 (n_6305), .B0 (n_7256), .Y (n_7309)); + AOI21X1 g35637(.A0 (n_5914), .A1 (n_6761), .B0 (n_12640), .Y + (n_7306)); + AOI21X1 g35670(.A0 (i3_dout_587), .A1 (n_6700), .B0 (n_7110), .Y + (n_7303)); + AOI21X1 g35716(.A0 (i4_dout_625), .A1 (n_7468), .B0 (n_7111), .Y + (n_7302)); + AOI21X1 g35672(.A0 (i4_dout_620), .A1 (n_7468), .B0 (n_7045), .Y + (n_7301)); + AOI21X1 g35673(.A0 (i4_dout_621), .A1 (n_7468), .B0 (n_7109), .Y + (n_7300)); + AOI21X1 g35674(.A0 (i4_dout_622), .A1 (n_7468), .B0 (n_7108), .Y + (n_7299)); + AOI21X1 g35715(.A0 (i4_dout_624), .A1 (n_7297), .B0 (n_7151), .Y + (n_7298)); + AOI21X1 g35714(.A0 (i4_dout_623), .A1 (n_7468), .B0 (n_7107), .Y + (n_7296)); + DFFX1 \u1_slt3_reg[4] (.CK (bit_clk_pad_i), .D (n_7156), .Q + (in_slt_400), .QN ()); + DFFX1 \u1_slt4_reg[4] (.CK (bit_clk_pad_i), .D (n_7155), .Q + (in_slt_422), .QN ()); + DFFX1 \u1_slt6_reg[4] (.CK (bit_clk_pad_i), .D (n_7154), .Q + (in_slt_444), .QN ()); + AOI21X1 g33282(.A0 (n_7032), .A1 (n_1136), .B0 (n_7379), .Y (n_7295)); + AOI21X1 g33283(.A0 (n_7031), .A1 (n_1105), .B0 (n_7378), .Y (n_7294)); + OAI21X1 g35863(.A0 (n_5678), .A1 (n_11934), .B0 (n_6810), .Y + (n_7292)); + NOR2X1 g34596(.A (o4_status_972), .B (n_458), .Y (n_9548)); + NOR2X1 g34597(.A (o6_status_982), .B (n_447), .Y (n_9486)); + NOR2X1 g34888(.A (o4_status), .B (o4_status_972), .Y (n_7289)); + NOR2X1 g34889(.A (o6_status), .B (o6_status_982), .Y (n_7288)); + DFFX1 u12_o7_we_reg(.CK (clk_i), .D (n_7020), .Q (o7_we), .QN ()); + DFFX1 u12_o3_we_reg(.CK (clk_i), .D (n_7028), .Q (o3_we), .QN ()); + DFFX1 u12_o4_we_reg(.CK (clk_i), .D (n_7027), .Q (o4_we), .QN ()); + DFFX1 u12_o6_we_reg(.CK (clk_i), .D (n_7026), .Q (o6_we), .QN ()); + DFFX1 u12_o8_we_reg(.CK (clk_i), .D (n_7024), .Q (o8_we), .QN ()); + DFFX1 u12_o9_we_reg(.CK (clk_i), .D (n_7023), .Q (o9_we), .QN ()); + NOR2X1 g35281(.A (n_838), .B (rf_we), .Y (n_7287)); + NOR2X1 g35282(.A (rf_we), .B (n_1300), .Y (n_7444)); + NOR2X1 g35284(.A (rf_we), .B (wb_addr_i[4]), .Y (n_7442)); + NOR2X1 g35288(.A (n_2574), .B (rf_we), .Y (n_7286)); + NAND3X1 g35289(.A (n_5944), .B (n_6757), .C (n_2298), .Y (n_7285)); + AND2X1 g35324(.A (n_1230), .B (n_7030), .Y (n_11534)); + NAND2X1 g35329(.A (n_7030), .B (n_11772), .Y (n_7439)); + NAND3X1 g35330(.A (n_6843), .B (n_5637), .C (n_1798), .Y (n_12837)); + NAND3X1 g35331(.A (n_6840), .B (n_6060), .C (n_2232), .Y (n_7282)); + NAND3X1 g35335(.A (n_6837), .B (n_6040), .C (n_2300), .Y (n_7281)); + OR2X1 g35359(.A (n_7018), .B (ic2_int_set_723), .Y (n_7280)); + DFFX1 \u1_sr_reg[6] (.CK (bit_clk_pad_i), .D (u1_sr_121), .Q + (u1_sr_122), .QN ()); + INVX1 g35414(.A (\in_valid_s[1] ), .Y (n_7356)); + DFFSRX1 \in_valid_s_reg[2] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (in_valid_s_2), .Q (\in_valid_s[2] ), .QN ()); + AOI21X1 g35564(.A0 (n_6312), .A1 (n_6137), .B0 (n_7324), .Y (n_7279)); + AOI21X1 g35566(.A0 (n_6313), .A1 (n_6133), .B0 (n_7324), .Y (n_7278)); + AOI21X1 g35567(.A0 (n_6309), .A1 (n_6136), .B0 (n_12145), .Y + (n_7277)); + AOI21X1 g35568(.A0 (n_5897), .A1 (n_6324), .B0 (n_7120), .Y (n_7276)); + AOI21X1 g35570(.A0 (n_6326), .A1 (n_6129), .B0 (n_7324), .Y (n_7275)); + AOI21X1 g35581(.A0 (n_6323), .A1 (n_6125), .B0 (n_12145), .Y + (n_7273)); + AOI21X1 g35583(.A0 (n_6304), .A1 (n_5757), .B0 (n_7214), .Y (n_7271)); + AOI21X1 g35585(.A0 (n_6321), .A1 (n_6132), .B0 (n_7324), .Y (n_7270)); + AOI21X1 g35588(.A0 (n_6320), .A1 (n_5776), .B0 (n_7267), .Y (n_7269)); + AOI21X1 g35589(.A0 (n_6319), .A1 (n_5775), .B0 (n_7267), .Y (n_7268)); + AOI21X1 g35591(.A0 (n_6315), .A1 (n_5773), .B0 (n_7267), .Y (n_7266)); + AOI21X1 g35597(.A0 (n_6314), .A1 (n_6092), .B0 (n_7267), .Y (n_7265)); + AOI21X1 g35598(.A0 (n_5932), .A1 (n_6121), .B0 (n_12604), .Y + (n_7264)); + AOI21X1 g35602(.A0 (n_6140), .A1 (n_5929), .B0 (n_12604), .Y + (n_7262)); + AOI21X1 g35603(.A0 (n_5904), .A1 (n_6117), .B0 (n_12604), .Y + (n_7260)); + AOI21X1 g35604(.A0 (n_6271), .A1 (n_5764), .B0 (n_7267), .Y (n_7258)); + AOI21X1 g35605(.A0 (n_5926), .A1 (n_6116), .B0 (n_7256), .Y (n_7257)); + AOI21X1 g35606(.A0 (n_5925), .A1 (n_6114), .B0 (n_7256), .Y (n_7255)); + AOI21X1 g35607(.A0 (n_5924), .A1 (n_6113), .B0 (n_7256), .Y (n_7254)); + AOI21X1 g35610(.A0 (n_5923), .A1 (n_6138), .B0 (n_7256), .Y (n_7253)); + AOI21X1 g35612(.A0 (n_5922), .A1 (n_6139), .B0 (n_7256), .Y (n_7251)); + AOI21X1 g35613(.A0 (n_5941), .A1 (n_6108), .B0 (n_7256), .Y (n_7250)); + AOI21X1 g35614(.A0 (n_5921), .A1 (n_6103), .B0 (n_7256), .Y (n_7249)); + AOI21X1 g35615(.A0 (n_5920), .A1 (n_6223), .B0 (n_7256), .Y (n_7248)); + AOI21X1 g35616(.A0 (n_5919), .A1 (n_6106), .B0 (n_12640), .Y + (n_7247)); + AOI21X1 g35620(.A0 (n_5918), .A1 (n_6105), .B0 (n_7256), .Y (n_7246)); + AOI21X1 g35621(.A0 (n_5917), .A1 (n_6104), .B0 (n_7256), .Y (n_7245)); + AOI21X1 g35622(.A0 (n_6145), .A1 (n_6283), .B0 (n_7214), .Y (n_7244)); + AOI21X1 g35626(.A0 (n_6300), .A1 (n_6094), .B0 (n_12640), .Y + (n_7241)); + AOI21X1 g35627(.A0 (n_6298), .A1 (n_6122), .B0 (n_12640), .Y + (n_7239)); + AOI21X1 g35629(.A0 (n_6297), .A1 (n_6119), .B0 (n_12640), .Y + (n_7236)); + AOI21X1 g35630(.A0 (n_6296), .A1 (n_6099), .B0 (n_12640), .Y + (n_7235)); + AOI21X1 g35631(.A0 (n_6295), .A1 (n_6097), .B0 (n_12640), .Y + (n_7233)); + AOI21X1 g35632(.A0 (n_6308), .A1 (n_6096), .B0 (n_12640), .Y + (n_7232)); + NOR2X1 g35633(.A (n_11395), .B (out_slt9), .Y (n_7231)); + AOI21X1 g35636(.A0 (n_6293), .A1 (n_6095), .B0 (n_12640), .Y + (n_7230)); + AOI21X1 g35639(.A0 (n_6325), .A1 (n_5756), .B0 (n_7214), .Y (n_7227)); + AOI21X1 g35641(.A0 (n_6290), .A1 (n_5753), .B0 (n_7214), .Y (n_7225)); + AOI21X1 g35645(.A0 (n_6288), .A1 (n_5796), .B0 (n_7214), .Y (n_7219)); + AOI21X1 g35646(.A0 (n_5913), .A1 (n_6093), .B0 (n_7212), .Y (n_7218)); + AOI21X1 g35648(.A0 (n_6287), .A1 (n_5749), .B0 (n_7214), .Y (n_7217)); + AOI21X1 g35651(.A0 (n_6286), .A1 (n_5744), .B0 (n_7212), .Y (n_7216)); + AOI21X1 g35653(.A0 (n_11986), .A1 (n_11987), .B0 (n_7214), .Y + (n_7215)); + AOI21X1 g35655(.A0 (n_6292), .A1 (n_5743), .B0 (n_7212), .Y (n_7213)); + AOI21X1 g35658(.A0 (n_6218), .A1 (n_6282), .B0 (n_7214), .Y (n_7211)); + AOI21X1 g35659(.A0 (n_6166), .A1 (n_6280), .B0 (n_7214), .Y (n_7210)); + AOI21X1 g35660(.A0 (n_6279), .A1 (n_5760), .B0 (n_7214), .Y (n_7209)); + AOI21X1 g35662(.A0 (n_6278), .A1 (n_5767), .B0 (n_7214), .Y (n_7208)); + AOI21X1 g35663(.A0 (n_5906), .A1 (n_6156), .B0 (n_7120), .Y (n_7207)); + AOI21X1 g35664(.A0 (n_5890), .A1 (n_6277), .B0 (n_7120), .Y (n_7205)); + AOI21X1 g35665(.A0 (n_6154), .A1 (n_6275), .B0 (n_7120), .Y (n_7204)); + AOI21X1 g35668(.A0 (n_12046), .A1 (n_12047), .B0 (n_12640), .Y + (n_7203)); + OAI21X1 g35859(.A0 (n_5728), .A1 (n_11934), .B0 (n_6815), .Y + (n_7202)); + OAI21X1 g35860(.A0 (n_6073), .A1 (n_11934), .B0 (n_6812), .Y + (n_7201)); + OAI21X1 g35861(.A0 (n_5727), .A1 (n_11934), .B0 (n_6778), .Y + (n_7199)); + OAI21X1 g35864(.A0 (n_6081), .A1 (n_11934), .B0 (n_6809), .Y + (n_7196)); + OAI21X1 g35868(.A0 (n_5724), .A1 (n_11934), .B0 (n_6793), .Y + (n_7194)); + OAI21X1 g35889(.A0 (n_5554), .A1 (n_7187), .B0 (n_6789), .Y (n_7193)); + DFFSRX1 \u2_to_cnt_reg[5] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_7033), .Q (\u2_to_cnt[5] ), .QN ()); + OAI21X1 g35890(.A0 (n_6075), .A1 (n_7187), .B0 (n_5854), .Y (n_7192)); + OAI21X1 g35891(.A0 (n_6076), .A1 (n_7187), .B0 (n_6787), .Y (n_7190)); + OAI21X1 g35893(.A0 (n_6074), .A1 (n_7187), .B0 (n_5850), .Y (n_7189)); + DFFX1 u13_int_reg(.CK (clk_i), .D (n_7021), .Q (int_o), .QN ()); + OAI21X1 g35896(.A0 (n_5549), .A1 (n_7187), .B0 (n_6817), .Y (n_7188)); + OAI21X1 g35898(.A0 (n_6085), .A1 (n_7187), .B0 (n_6785), .Y (n_7186)); + OAI21X1 g35899(.A0 (n_6069), .A1 (n_7187), .B0 (n_5842), .Y (n_7184)); + OAI21X1 g35904(.A0 (n_5553), .A1 (n_7187), .B0 (n_6780), .Y (n_7183)); + OAI21X1 g35911(.A0 (n_5726), .A1 (n_7088), .B0 (n_6774), .Y (n_7182)); + OAI21X1 g35912(.A0 (n_5688), .A1 (n_7088), .B0 (n_6772), .Y (n_7181)); + OAI21X1 g35913(.A0 (n_6072), .A1 (n_7088), .B0 (n_6206), .Y (n_7179)); + OAI21X1 g35914(.A0 (n_6070), .A1 (n_7088), .B0 (n_6771), .Y (n_7178)); + OAI21X1 g35923(.A0 (n_6084), .A1 (n_11934), .B0 (n_6181), .Y + (n_7177)); + OAI21X1 g35953(.A0 (n_6082), .A1 (n_11934), .B0 (n_6791), .Y + (n_7175)); + DFFSRX1 \u13_ints_r_reg[21] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6753), .Q (\u13_ints_r[21] ), .QN ()); + DFFX1 \u1_slt3_reg[0] (.CK (bit_clk_pad_i), .D (n_6731), .Q + (in_slt3), .QN ()); + DFFSRX1 \u13_ints_r_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6739), .Q (\u13_ints_r[0] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[27] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6755), .Q (\u13_ints_r[27] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[15] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6744), .Q (\u13_ints_r[15] ), .QN ()); + OAI21X1 g35878(.A0 (n_5714), .A1 (n_7115), .B0 (n_6243), .Y (n_7173)); + AOI21X1 g35666(.A0 (n_5938), .A1 (n_5793), .B0 (n_7212), .Y (n_7172)); + NOR2X1 g34595(.A (o3_status_962), .B (n_459), .Y (n_9488)); + NOR2X1 g34693(.A (o7_status_992), .B (n_422), .Y (n_9546)); + NOR2X1 g34700(.A (o8_status_1002), .B (n_5825), .Y (n_9483)); + NOR2X1 g34702(.A (o9_status_1012), .B (n_12585), .Y (n_9481)); + NOR2X1 g34887(.A (o3_status), .B (o3_status_962), .Y (n_7166)); + NOR2X1 g34890(.A (o7_status), .B (o7_status_992), .Y (n_7165)); + NOR2X1 g34891(.A (o8_status), .B (o8_status_1002), .Y (n_7164)); + NOR2X1 g34892(.A (o9_status), .B (o9_status_1012), .Y (n_7163)); + OAI21X1 g35876(.A0 (n_5714), .A1 (n_6995), .B0 (n_5878), .Y (n_7162)); + INVX1 g35250(.A (o4_status_972), .Y (n_7161)); + INVX1 g35252(.A (o6_status_982), .Y (n_7160)); + DFFSRX1 \u2_cnt_reg[7] (.RN (1'b1), .SN (rst_i), .CK (bit_clk_pad_i), + .D (n_6066), .Q (n_1212), .QN ()); + AND2X1 g35322(.A (n_1136), .B (n_6718), .Y (n_11887)); + AND2X1 g35323(.A (n_1105), .B (n_6720), .Y (n_11888)); + NAND2X1 g35327(.A (n_6718), .B (n_11564), .Y (n_7383)); + NAND2X1 g35328(.A (n_6720), .B (n_11600), .Y (n_7380)); + NOR2X1 g35355(.A (i6_status), .B (i6_status_1042), .Y (n_7157)); + MX2X1 g35361(.A (u1_sr_120), .B (in_slt_400), .S0 (out_le_182), .Y + (n_7156)); + MX2X1 g35375(.A (u1_sr_120), .B (in_slt_422), .S0 (out_le_183), .Y + (n_7155)); + MX2X1 g35380(.A (u1_sr_120), .B (in_slt_444), .S0 (out_le_184), .Y + (n_7154)); + DFFSRX1 \in_valid_s_reg[1] (.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (in_valid_s_1), .Q (\in_valid_s[1] ), .QN ()); + AOI21X1 g35465(.A0 (\u11_rp[1] ), .A1 (i6_re), .B0 (n_6750), .Y + (n_7153)); + AOI21X1 g35469(.A0 (i3_re), .A1 (\u9_rp[1] ), .B0 (n_6708), .Y + (n_7152)); + NOR2X1 g35852(.A (n_4662), .B (n_7353), .Y (n_7151)); + AOI21X1 g35474(.A0 (\u10_rp[1] ), .A1 (i4_re), .B0 (n_6707), .Y + (n_7150)); + NOR2X1 g35475(.A (i3_empty), .B (i3_re), .Y (n_7149)); + NOR2X1 g35476(.A (i4_empty), .B (i4_re), .Y (n_7148)); + AOI21X1 g35480(.A0 (i3_re), .A1 (\u9_rp[2] ), .B0 (n_6713), .Y + (n_7147)); + AOI21X1 g35481(.A0 (\u11_rp[2] ), .A1 (i6_re), .B0 (n_6715), .Y + (n_7146)); + AOI21X1 g35482(.A0 (\u10_rp[2] ), .A1 (i4_re), .B0 (n_6711), .Y + (n_7145)); + MX2X1 g35490(.A (u1_sr_120), .B (in_slt_830), .S0 (out_le_181), .Y + (n_7144)); + AOI21X1 g35497(.A0 (i3_re), .A1 (\u9_rp[0] ), .B0 (n_6714), .Y + (n_7143)); + AOI21X1 g35498(.A0 (n_1206), .A1 (i4_re), .B0 (n_6712), .Y (n_7142)); + AOI21X1 g35503(.A0 (\u11_rp[0] ), .A1 (i6_re), .B0 (n_6709), .Y + (n_7141)); + DFFX1 valid_s1_reg(.CK (clk_i), .D (valid), .Q (valid_s1), .QN ()); + DFFX1 \in_valid_s1_reg[0] (.CK (clk_i), .D (in_valid), .Q + (in_valid_s1), .QN ()); + AOI21X1 g35553(.A0 (n_5592), .A1 (n_4731), .B0 (n_7353), .Y (n_7140)); + AOI21X1 g35554(.A0 (n_5584), .A1 (n_4694), .B0 (n_7353), .Y (n_7139)); + AOI21X1 g35555(.A0 (n_5590), .A1 (n_4686), .B0 (n_7353), .Y (n_7138)); + AOI21X1 g35556(.A0 (n_5789), .A1 (n_4727), .B0 (n_7353), .Y (n_7137)); + AOI21X1 g35557(.A0 (n_5589), .A1 (n_4724), .B0 (n_7353), .Y (n_7136)); + AOI21X1 g35558(.A0 (n_5587), .A1 (n_4722), .B0 (n_7353), .Y (n_7135)); + AOI21X1 g35559(.A0 (n_5585), .A1 (n_4721), .B0 (n_7353), .Y (n_7134)); + AOI21X1 g35578(.A0 (n_5586), .A1 (n_3976), .B0 (n_7353), .Y (n_7133)); + AOI21X1 g35590(.A0 (n_5937), .A1 (n_5774), .B0 (n_7267), .Y (n_7132)); + AOI21X1 g35592(.A0 (n_5936), .A1 (n_5771), .B0 (n_12604), .Y + (n_7130)); + AOI21X1 g35593(.A0 (n_5935), .A1 (n_5770), .B0 (n_12604), .Y + (n_7129)); + AOI21X1 g35594(.A0 (n_5934), .A1 (n_5769), .B0 (n_7267), .Y (n_7128)); + AOI21X1 g35595(.A0 (n_5933), .A1 (n_5768), .B0 (n_7267), .Y (n_7127)); + AOI21X1 g35600(.A0 (n_5888), .A1 (n_5931), .B0 (n_12604), .Y + (n_7126)); + AOI21X1 g35623(.A0 (n_5916), .A1 (n_5759), .B0 (n_7212), .Y (n_7124)); + AOI21X1 g35647(.A0 (n_5910), .A1 (n_5745), .B0 (n_7120), .Y (n_7123)); + AOI21X1 g35649(.A0 (n_5911), .A1 (n_5748), .B0 (n_7212), .Y (n_7122)); + AOI21X1 g35650(.A0 (n_5905), .A1 (n_5747), .B0 (n_7120), .Y (n_7121)); + AOI21X1 g35654(.A0 (n_5909), .A1 (n_5790), .B0 (n_7120), .Y (n_7119)); + AOI21X1 g35657(.A0 (n_5908), .A1 (n_5758), .B0 (n_7212), .Y (n_7118)); + AOI21X1 g35661(.A0 (n_5907), .A1 (n_5742), .B0 (n_7120), .Y (n_7117)); + OAI21X1 g35887(.A0 (n_5717), .A1 (n_7115), .B0 (n_6240), .Y (n_7116)); + AOI21X1 g35667(.A0 (n_5939), .A1 (n_5794), .B0 (n_7212), .Y (n_7114)); + AOI22X1 g35709(.A0 (n_5892), .A1 (n_7443), .B0 (\u13_ints_r[1] ), .B1 + (n_3985), .Y (n_7113)); + AOI22X1 g35711(.A0 (n_6686), .A1 (i6_dout_645), .B0 (i4_dout_614), + .B1 (n_7297), .Y (n_7112)); + DFFSRX1 \u2_to_cnt_reg[3] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6065), .Q (\u2_to_cnt[3] ), .QN ()); + NOR2X1 g35832(.A (n_7353), .B (n_5268), .Y (n_7111)); + AOI21X1 g35846(.A0 (n_2586), .A1 (n_4719), .B0 (n_7353), .Y (n_7110)); + AOI21X1 g35849(.A0 (n_2584), .A1 (n_5273), .B0 (n_7353), .Y (n_7109)); + AOI21X1 g35850(.A0 (n_2583), .A1 (n_4716), .B0 (n_7353), .Y (n_7108)); + NOR2X1 g35851(.A (n_4665), .B (n_7353), .Y (n_7107)); + AOI21X1 g35847(.A0 (n_2613), .A1 (n_4718), .B0 (n_7353), .Y (n_7106)); + OAI21X1 g35858(.A0 (n_5701), .A1 (n_11934), .B0 (n_6238), .Y + (n_7105)); + DFFX1 \u2_res_cnt_reg[3] (.CK (clk_i), .D (n_6067), .Q + (\u2_res_cnt[3] ), .QN ()); + OAI21X1 g35867(.A0 (n_5725), .A1 (n_11934), .B0 (n_6253), .Y + (n_7104)); + OAI21X1 g35869(.A0 (n_5729), .A1 (n_11934), .B0 (n_6249), .Y + (n_7103)); + OAI21X1 g35873(.A0 (n_5716), .A1 (n_7115), .B0 (n_5885), .Y (n_7102)); + OAI21X1 g35880(.A0 (n_5711), .A1 (n_7115), .B0 (n_5873), .Y (n_7101)); + OAI21X1 g35881(.A0 (n_5710), .A1 (n_6995), .B0 (n_5871), .Y (n_7100)); + OAI21X1 g35883(.A0 (n_5708), .A1 (n_6995), .B0 (n_5861), .Y (n_7099)); + OAI21X1 g35886(.A0 (n_5720), .A1 (n_7115), .B0 (n_5858), .Y (n_7096)); + OAI21X1 g35888(.A0 (n_5705), .A1 (n_7077), .B0 (n_6236), .Y (n_7095)); + DFFSRX1 \u2_to_cnt_reg[4] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6733), .Q (n_4088), .QN ()); + DFFX1 \u1_slt3_reg[2] (.CK (bit_clk_pad_i), .D (n_6730), .Q + (in_slt_398), .QN ()); + DFFX1 \u1_slt3_reg[1] (.CK (bit_clk_pad_i), .D (n_6732), .Q + (in_slt_397), .QN ()); + DFFX1 \u1_slt4_reg[1] (.CK (bit_clk_pad_i), .D (n_6727), .Q + (in_slt_419), .QN ()); + DFFX1 \u1_slt6_reg[1] (.CK (bit_clk_pad_i), .D (n_6723), .Q + (in_slt_441), .QN ()); + DFFX1 \u1_slt6_reg[2] (.CK (bit_clk_pad_i), .D (n_6722), .Q + (in_slt_442), .QN ()); + DFFX1 u12_wb_ack_o_reg(.CK (clk_i), .D (n_6716), .Q (wb_ack_o), .QN + ()); + DFFSRX1 \u13_ints_r_reg[10] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6740), .Q (\u13_ints_r[10] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[12] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6742), .Q (\u13_ints_r[12] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[13] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6741), .Q (\u13_ints_r[13] ), .QN ()); + OAI21X1 g35895(.A0 (n_5550), .A1 (n_7187), .B0 (n_6232), .Y (n_7094)); + DFFSRX1 \u13_ints_r_reg[16] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6746), .Q (\u13_ints_r[16] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[18] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6672), .Q (\u13_ints_r[18] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[19] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6747), .Q (\u13_ints_r[19] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[22] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6749), .Q (\u13_ints_r[22] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[24] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6751), .Q (\u13_ints_r[24] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[25] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6754), .Q (\u13_ints_r[25] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[28] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6758), .Q (\u13_ints_r[28] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[3] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6759), .Q (\u13_ints_r[3] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[4] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6671), .Q (\u13_ints_r[4] ), .QN ()); + DFFSRX1 \u13_ints_r_reg[7] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6063), .Q (\u13_ints_r[7] ), .QN ()); + OAI21X1 g35897(.A0 (n_5704), .A1 (n_7187), .B0 (n_5846), .Y (n_7093)); + OAI21X1 g35900(.A0 (n_5702), .A1 (n_7187), .B0 (n_5838), .Y (n_7092)); + OAI21X1 g35905(.A0 (n_5693), .A1 (n_7088), .B0 (n_6217), .Y (n_7091)); + OAI21X1 g35906(.A0 (n_5545), .A1 (n_7088), .B0 (n_6215), .Y (n_7090)); + OAI21X1 g35907(.A0 (n_5692), .A1 (n_7088), .B0 (n_6212), .Y (n_7089)); + OAI21X1 g35908(.A0 (n_5671), .A1 (n_7088), .B0 (n_6234), .Y (n_7087)); + OAI21X1 g35909(.A0 (n_5691), .A1 (n_7088), .B0 (n_6210), .Y (n_7085)); + OAI21X1 g35910(.A0 (n_5690), .A1 (n_7088), .B0 (n_6208), .Y (n_7084)); + OAI21X1 g35917(.A0 (n_5696), .A1 (n_7080), .B0 (n_6199), .Y (n_7081)); + OAI21X1 g35919(.A0 (n_5693), .A1 (n_7080), .B0 (n_6197), .Y (n_7079)); + OAI21X1 g35922(.A0 (n_5685), .A1 (n_7077), .B0 (n_6193), .Y (n_7076)); + OAI21X1 g35925(.A0 (n_5682), .A1 (n_7077), .B0 (n_6191), .Y (n_7073)); + OAI21X1 g35928(.A0 (n_5675), .A1 (n_7063), .B0 (n_5816), .Y (n_7069)); + OAI21X1 g35930(.A0 (n_5698), .A1 (n_7077), .B0 (n_6187), .Y (n_7067)); + OAI21X1 g35932(.A0 (n_5677), .A1 (n_7077), .B0 (n_6263), .Y (n_7066)); + OAI21X1 g35933(.A0 (n_5667), .A1 (n_7063), .B0 (n_5812), .Y (n_7065)); + OAI21X1 g35934(.A0 (n_5533), .A1 (n_7063), .B0 (n_6183), .Y (n_7064)); + OAI21X1 g35936(.A0 (n_5668), .A1 (n_7077), .B0 (n_6173), .Y (n_7062)); + OAI21X1 g35939(.A0 (n_5531), .A1 (n_7063), .B0 (n_6169), .Y (n_7060)); + OAI21X1 g35941(.A0 (n_5679), .A1 (n_7077), .B0 (n_6168), .Y (n_7059)); + OAI21X1 g35942(.A0 (n_5673), .A1 (n_7077), .B0 (n_6164), .Y (n_7058)); + OAI21X1 g35943(.A0 (n_5672), .A1 (n_7063), .B0 (n_6221), .Y (n_7057)); + OAI21X1 g35945(.A0 (n_5700), .A1 (n_7077), .B0 (n_6162), .Y (n_7056)); + OAI21X1 g35946(.A0 (n_5684), .A1 (n_7077), .B0 (n_6158), .Y (n_7055)); + OAI21X1 g35947(.A0 (n_5669), .A1 (n_7063), .B0 (n_5801), .Y (n_7054)); + OAI21X1 g35948(.A0 (n_5721), .A1 (n_7063), .B0 (n_5894), .Y (n_7053)); + OAI21X1 g35952(.A0 (n_5572), .A1 (n_7063), .B0 (n_6261), .Y (n_7052)); + OAI21X1 g36195(.A0 (n_7049), .A1 (n_7048), .B0 (n_6268), .Y (n_7050)); + OAI21X1 g35885(.A0 (n_5708), .A1 (n_7115), .B0 (n_6143), .Y (n_7047)); + OAI21X1 g35871(.A0 (n_5722), .A1 (n_11934), .B0 (n_6267), .Y + (n_7046)); + DFFSRX1 \u13_ints_r_reg[6] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6062), .Q (\u13_ints_r[6] ), .QN ()); + DFFX1 \u1_slt6_reg[3] (.CK (bit_clk_pad_i), .D (n_6721), .Q + (in_slt_443), .QN ()); + DFFX1 \u1_slt6_reg[0] (.CK (bit_clk_pad_i), .D (n_6724), .Q + (in_slt6), .QN ()); + DFFX1 \u1_slt4_reg[3] (.CK (bit_clk_pad_i), .D (n_6725), .Q + (in_slt_421), .QN ()); + DFFX1 \u1_slt3_reg[3] (.CK (bit_clk_pad_i), .D (n_6729), .Q + (in_slt_399), .QN ()); + DFFSRX1 \u13_ints_r_reg[9] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6064), .Q (\u13_ints_r[9] ), .QN ()); + AOI21X1 g35848(.A0 (n_2585), .A1 (n_5274), .B0 (n_7353), .Y (n_7045)); + DFFX1 \u1_slt4_reg[2] (.CK (bit_clk_pad_i), .D (n_6726), .Q + (in_slt_420), .QN ()); + DFFX1 \u1_slt4_reg[0] (.CK (bit_clk_pad_i), .D (n_6728), .Q + (in_slt4), .QN ()); + OR2X1 g35676(.A (n_1087), .B (n_7042), .Y (n_7043)); + DFFSRX1 \u2_cnt_reg[1] (.RN (1'b1), .SN (rst_i), .CK (bit_clk_pad_i), + .D (n_5821), .Q (n_866), .QN ()); + DFFSRX1 \u2_to_cnt_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6054), .Q (n_1819), .QN ()); + INVX4 g35795(.A (n_7003), .Y (n_11319)); + INVX1 g35248(.A (o3_status_962), .Y (n_7037)); + DFFX1 \u4_status_reg[1] (.CK (clk_i), .D (n_6050), .Q + (o4_status_972), .QN ()); + DFFX1 \u5_status_reg[1] (.CK (clk_i), .D (n_6048), .Q + (o6_status_982), .QN ()); + INVX1 g35254(.A (o7_status_992), .Y (n_7036)); + INVX1 g35256(.A (o8_status_1002), .Y (n_7035)); + INVX1 g35258(.A (o9_status_1012), .Y (n_7034)); + NOR2X1 g35337(.A (n_6046), .B (u2_bit_clk_e), .Y (n_7033)); + NOR2X1 g35353(.A (i3_status), .B (i3_status_1022), .Y (n_7032)); + NOR2X1 g35354(.A (i4_status), .B (i4_status_1032), .Y (n_7031)); + DFFX1 u12_rf_we_reg(.CK (clk_i), .D (n_6041), .Q (), .QN (rf_we)); + INVX1 g35384(.A (i6_status_1042), .Y (n_7030)); + NOR2X1 g35438(.A (n_7025), .B (n_1133), .Y (n_7028)); + NOR2X1 g35439(.A (n_7019), .B (n_7022), .Y (n_7027)); + NOR2X1 g35440(.A (n_7025), .B (n_1271), .Y (n_7026)); + NOR2X1 g35441(.A (n_7025), .B (n_1216), .Y (n_7024)); + NOR2X1 g35442(.A (n_7022), .B (n_3431), .Y (n_7023)); + NAND3X1 g35464(.A (n_6061), .B (n_729), .C (n_730), .Y (n_7021)); + NOR2X1 g35466(.A (n_6043), .B (n_7019), .Y (n_7020)); + DFFX1 \u2_res_cnt_reg[0] (.CK (clk_i), .D (n_6053), .Q + (\u2_res_cnt[0] ), .QN ()); + NOR2X1 g35477(.A (i6_empty), .B (i6_re), .Y (n_7018)); + DFFX1 \in_valid_s1_reg[2] (.CK (clk_i), .D (in_valid_9), .Q + (in_valid_s_2), .QN ()); + DFFX1 \u1_sr_reg[5] (.CK (bit_clk_pad_i), .D (u1_sr_120), .Q + (u1_sr_121), .QN ()); + OR2X1 g35584(.A (n_7042), .B (n_7017), .Y (n_11426)); + OAI21X1 g35894(.A0 (n_5551), .A1 (n_7187), .B0 (n_5848), .Y (n_7016)); + INVX4 g35762(.A (n_7038), .Y (n_11395)); + AOI21X1 g35675(.A0 (n_440), .A1 (n_679), .B0 (n_7042), .Y (n_7013)); + AOI22X1 g35713(.A0 (n_6686), .A1 (i6_dout_650), .B0 (i4_dout_619), + .B1 (n_7297), .Y (n_7012)); + XOR2X1 g35721(.A (n_95), .B (n_7010), .Y (n_7011)); + INVX8 g35740(.A (n_6999), .Y (n_11389)); + OAI21X1 g35872(.A0 (n_5565), .A1 (n_7115), .B0 (n_5887), .Y (n_6998)); + OAI21X1 g35875(.A0 (n_5563), .A1 (n_7115), .B0 (n_5880), .Y (n_6997)); + OAI21X1 g35877(.A0 (n_5562), .A1 (n_6995), .B0 (n_5877), .Y (n_6996)); + OAI21X1 g35879(.A0 (n_5562), .A1 (n_7115), .B0 (n_5875), .Y (n_6994)); + OAI21X1 g35874(.A0 (n_5564), .A1 (n_7115), .B0 (n_5883), .Y (n_6993)); + DFFSRX1 \u2_cnt_reg[4] (.RN (1'b1), .SN (rst_i), .CK (bit_clk_pad_i), + .D (n_6058), .Q (\u2_cnt[4] ), .QN ()); + DFFSRX1 \u2_cnt_reg[3] (.RN (1'b1), .SN (rst_i), .CK (bit_clk_pad_i), + .D (n_6052), .Q (\u2_cnt[3] ), .QN ()); + DFFSRX1 \u2_to_cnt_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_5976), .Q (\u2_to_cnt[0] ), .QN ()); + DFFSRX1 \u2_to_cnt_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), .D + (n_6025), .Q (\u2_to_cnt[1] ), .QN ()); + DFFSRX1 \u2_cnt_reg[5] (.RN (1'b1), .SN (rst_i), .CK (bit_clk_pad_i), + .D (n_5741), .Q (\u2_cnt[5] ), .QN ()); + DFFSRX1 \u2_cnt_reg[6] (.RN (1'b1), .SN (rst_i), .CK (bit_clk_pad_i), + .D (n_5889), .Q (\u2_cnt[6] ), .QN ()); + DFFSRX1 \u2_cnt_reg[0] (.RN (1'b1), .SN (rst_i), .CK (bit_clk_pad_i), + .D (n_5822), .Q (n_1773), .QN ()); + DFFSRX1 \u2_cnt_reg[2] (.RN (1'b1), .SN (rst_i), .CK (bit_clk_pad_i), + .D (n_5820), .Q (\u2_cnt[2] ), .QN ()); + OR2X1 g35453(.A (u2_sync_resume), .B (u2_sync_beat), .Y (sync_pad_o)); + OAI21X1 g35901(.A0 (n_5548), .A1 (n_7187), .B0 (n_5836), .Y (n_6991)); + OAI21X1 g35902(.A0 (n_5547), .A1 (n_7187), .B0 (n_5834), .Y (n_6990)); + OAI21X1 g35903(.A0 (n_5555), .A1 (n_7187), .B0 (n_5856), .Y (n_6989)); + OAI21X1 g35920(.A0 (n_5545), .A1 (n_7080), .B0 (n_5817), .Y (n_6987)); + OAI21X1 g35931(.A0 (n_5534), .A1 (n_7063), .B0 (n_5814), .Y (n_6984)); + OAI21X1 g35935(.A0 (n_5532), .A1 (n_6981), .B0 (n_5808), .Y (n_6983)); + OAI21X1 g35937(.A0 (n_5530), .A1 (n_6981), .B0 (n_5810), .Y (n_6982)); + OAI21X1 g35940(.A0 (n_5537), .A1 (n_7063), .B0 (n_5824), .Y (n_6979)); + OAI21X1 g35944(.A0 (n_5546), .A1 (n_6981), .B0 (n_5806), .Y (n_6978)); + OAI21X1 g35949(.A0 (n_5529), .A1 (n_7063), .B0 (n_5896), .Y (n_6977)); + OAI21X1 g35950(.A0 (n_5528), .A1 (n_6981), .B0 (n_5799), .Y (n_6976)); + OAI21X1 g35951(.A0 (n_5567), .A1 (n_7063), .B0 (n_5899), .Y (n_6975)); + AOI21X1 g35954(.A0 (n_6972), .A1 (n_862), .B0 (n_5791), .Y (n_6974)); + AOI21X1 g35955(.A0 (n_6972), .A1 (oc1_cfg_976), .B0 (n_5795), .Y + (n_6973)); + AOI21X1 g35956(.A0 (n_6972), .A1 (n_8565), .B0 (n_5765), .Y (n_6971)); + AOI21X1 g35957(.A0 (n_6972), .A1 (oc1_cfg_980), .B0 (n_5763), .Y + (n_6969)); + AOI21X1 g35958(.A0 (n_6972), .A1 (oc0_cfg_965), .B0 (n_5787), .Y + (n_6968)); + AOI21X1 g35959(.A0 (n_6972), .A1 (oc0_cfg_966), .B0 (n_5785), .Y + (n_6967)); + AOI21X1 g35960(.A0 (n_6972), .A1 (n_8528), .B0 (n_5784), .Y (n_6966)); + AOI21X1 g35961(.A0 (n_6972), .A1 (n_8526), .B0 (n_5783), .Y (n_6965)); + AOI21X1 g35962(.A0 (n_6972), .A1 (oc0_cfg_969), .B0 (n_5782), .Y + (n_6964)); + AOI21X1 g35963(.A0 (n_6972), .A1 (oc0_cfg_970), .B0 (n_5781), .Y + (n_6963)); + AOI21X1 g35964(.A0 (n_6972), .A1 (n_991), .B0 (n_5780), .Y (n_6962)); + AOI21X1 g35965(.A0 (n_6972), .A1 (oc1_cfg_974), .B0 (n_5779), .Y + (n_6961)); + AOI21X1 g35966(.A0 (n_6972), .A1 (n_8567), .B0 (n_5761), .Y (n_6960)); + AOI21X1 g35967(.A0 (n_6972), .A1 (oc1_cfg_975), .B0 (n_5786), .Y + (n_6959)); + AOI21X1 g35968(.A0 (n_6972), .A1 (oc1_cfg_979), .B0 (n_5777), .Y + (n_6958)); + MX2X1 g35982(.A (n_6956), .B (n_6925), .S0 (n_5730), .Y (n_6957)); + MX2X1 g35985(.A (n_6954), .B (n_6952), .S0 (n_4783), .Y (n_6955)); + MX2X1 g35987(.A (n_6952), .B (n_6951), .S0 (n_6908), .Y (n_6953)); + MX2X1 g35988(.A (n_6949), .B (n_6920), .S0 (n_969), .Y (n_6950)); + MX2X1 g35989(.A (n_6947), .B (n_6891), .S0 (n_4783), .Y (n_6948)); + MX2X1 g35992(.A (n_6945), .B (n_6913), .S0 (n_5730), .Y (n_6946)); + MX2X1 g35993(.A (n_6942), .B (n_6899), .S0 (n_5730), .Y (n_6943)); + MX2X1 g35994(.A (n_6940), .B (n_6927), .S0 (n_4783), .Y (n_6941)); + MX2X1 g35995(.A (n_6937), .B (n_6906), .S0 (n_4783), .Y (n_6938)); + MX2X1 g36001(.A (n_6935), .B (n_6952), .S0 (n_6898), .Y (n_6936)); + MX2X1 g36003(.A (n_6933), .B (n_6916), .S0 (n_930), .Y (n_6934)); + MX2X1 g36005(.A (n_6931), .B (n_6896), .S0 (n_930), .Y (n_6932)); + MX2X1 g36006(.A (n_6928), .B (n_6927), .S0 (n_6898), .Y (n_6929)); + MX2X1 g36009(.A (n_6925), .B (n_6924), .S0 (n_5371), .Y (n_6926)); + MX2X1 g36014(.A (n_6883), .B (n_6922), .S0 (n_6908), .Y (n_6923)); + MX2X1 g36016(.A (n_6920), .B (n_6919), .S0 (n_6908), .Y (n_6921)); + OAI21X1 g35892(.A0 (n_5552), .A1 (n_7187), .B0 (n_5852), .Y (n_6918)); + MX2X1 g36020(.A (n_6916), .B (n_6915), .S0 (n_6908), .Y (n_6917)); + MX2X1 g36022(.A (n_6913), .B (n_6912), .S0 (n_6908), .Y (n_6914)); + MX2X1 g36023(.A (n_6927), .B (n_6909), .S0 (n_6908), .Y (n_6910)); + MX2X1 g36024(.A (n_6906), .B (n_6905), .S0 (n_6908), .Y (n_6907)); + MX2X1 g36029(.A (n_6902), .B (n_6913), .S0 (n_6898), .Y (n_6903)); + MX2X1 g36035(.A (n_6900), .B (n_6899), .S0 (n_6898), .Y (n_6901)); + MX2X1 g36047(.A (n_6896), .B (n_6895), .S0 (n_6908), .Y (n_6897)); + MX2X1 g36048(.A (n_6893), .B (n_6906), .S0 (n_6898), .Y (n_6894)); + MX2X1 g36051(.A (n_6891), .B (n_6890), .S0 (n_6908), .Y (n_6892)); + MX2X1 g36052(.A (n_6888), .B (n_6891), .S0 (n_930), .Y (n_6889)); + MX2X1 g36056(.A (n_6899), .B (n_6886), .S0 (n_6908), .Y (n_6887)); + MX2X1 g36059(.A (n_6884), .B (n_6883), .S0 (n_4783), .Y (n_6885)); + MX2X1 g36065(.A (n_6881), .B (n_6920), .S0 (n_6898), .Y (n_6882)); + MX2X1 g36066(.A (n_6879), .B (n_6916), .S0 (n_4783), .Y (n_6880)); + MX2X1 g36067(.A (n_6876), .B (n_6896), .S0 (n_969), .Y (n_6877)); + MX2X1 g36070(.A (n_6873), .B (n_6883), .S0 (n_6898), .Y (n_6874)); + MX2X1 g36111(.A (n_509), .B (n_6925), .S0 (n_6898), .Y (n_6871)); + MX2X1 g36133(.A (n_6868), .B (n_6925), .S0 (n_6856), .Y (n_6869)); + MX2X1 g36139(.A (n_6866), .B (n_6883), .S0 (n_6856), .Y (n_6867)); + MX2X1 g36140(.A (n_6864), .B (n_6952), .S0 (n_6856), .Y (n_6865)); + MX2X1 g36141(.A (n_6862), .B (n_6920), .S0 (n_6856), .Y (n_6863)); + MX2X1 g36142(.A (n_6859), .B (n_6916), .S0 (n_6856), .Y (n_6860)); + MX2X1 g36143(.A (n_6857), .B (n_6891), .S0 (n_6856), .Y (n_6858)); + MX2X1 g36144(.A (n_6854), .B (n_6896), .S0 (n_6856), .Y (n_6855)); + MX2X1 g36145(.A (n_6852), .B (n_6913), .S0 (n_6856), .Y (n_6853)); + MX2X1 g36146(.A (n_6849), .B (n_6899), .S0 (n_6856), .Y (n_6850)); + MX2X1 g36147(.A (n_6847), .B (n_6927), .S0 (n_6856), .Y (n_6848)); + MX2X1 g36149(.A (n_6845), .B (n_6906), .S0 (n_6856), .Y (n_6846)); + OAI21X1 g36196(.A0 (n_6842), .A1 (n_6841), .B0 (n_5902), .Y (n_6843)); + OAI21X1 g36197(.A0 (n_6839), .A1 (n_6838), .B0 (n_5901), .Y (n_6840)); + OAI21X1 g36198(.A0 (n_6836), .A1 (\u8_wp[1] ), .B0 (n_5903), .Y + (n_6837)); + NAND2X1 g36315(.A (n_6777), .B (n_6824), .Y (n_6834)); + NAND2X1 g36316(.A (n_12354), .B (n_6824), .Y (n_6833)); + NAND2X1 g36319(.A (n_6807), .B (n_6824), .Y (n_11539)); + NAND2X1 g36320(.A (n_6800), .B (n_145), .Y (n_11541)); + NAND2X1 g36323(.A (n_6821), .B (n_12171), .Y (n_6826)); + NAND2X1 g36347(.A (n_12746), .B (n_6824), .Y (n_6825)); + NAND2X1 g36349(.A (n_6779), .B (n_6821), .Y (n_6823)); + NAND2X1 g36351(.A (n_6786), .B (n_6821), .Y (n_6822)); + NAND2X1 g36358(.A (n_6783), .B (n_6821), .Y (n_6820)); + NAND2X1 g36366(.A (n_6814), .B (n_6824), .Y (n_6819)); + NAND2X1 g36386(.A (n_11925), .B (n_6824), .Y (n_6818)); + NAND2X1 g36411(.A (n_6765), .B (n_6816), .Y (n_6817)); + NAND2X1 g36420(.A (n_6814), .B (n_12531), .Y (n_6815)); + NAND2X1 g36422(.A (n_12746), .B (n_12531), .Y (n_6812)); + NAND2X1 g36427(.A (n_6797), .B (n_12531), .Y (n_6810)); + NAND2X1 g36429(.A (n_6794), .B (n_12531), .Y (n_6809)); + NAND2X1 g36430(.A (n_6807), .B (n_12531), .Y (n_6808)); + NAND2X1 g36431(.A (n_6805), .B (n_12357), .Y (n_6806)); + NAND2X1 g36432(.A (n_6803), .B (n_12357), .Y (n_6804)); + NAND2X1 g36433(.A (n_6800), .B (n_12531), .Y (n_6801)); + NAND2X1 g36438(.A (n_6797), .B (\u4_rp[0] ), .Y (n_11540)); + NAND2X1 g36441(.A (n_6794), .B (\u4_rp[0] ), .Y (n_11542)); + NAND2X1 g36442(.A (n_11925), .B (n_12531), .Y (n_6793)); + NAND2X1 g36494(.A (n_12531), .B (n_6790), .Y (n_6791)); + NAND2X1 g36495(.A (n_12171), .B (n_6816), .Y (n_6789)); + NAND2X1 g36498(.A (n_6786), .B (n_6816), .Y (n_6787)); + NAND2X1 g36508(.A (n_6781), .B (n_6816), .Y (n_6785)); + NAND2X1 g36510(.A (n_6783), .B (n_6816), .Y (n_6784)); + NAND2X1 g36520(.A (n_6781), .B (n_784), .Y (n_6782)); + NAND2X1 g36523(.A (n_6779), .B (n_6816), .Y (n_6780)); + NAND2X1 g36530(.A (n_12531), .B (n_6777), .Y (n_6778)); + NAND2X1 g36546(.A (n_6773), .B (n_6763), .Y (n_6774)); + NAND2X1 g36547(.A (n_6773), .B (n_6769), .Y (n_6772)); + NAND2X1 g36549(.A (n_12411), .B (n_6773), .Y (n_6771)); + NAND2X1 g36567(.A (n_6765), .B (n_784), .Y (n_6766)); + NAND2X1 g36694(.A (n_5699), .B (n_6118), .Y (n_6761)); + NOR2X1 g35823(.A (n_617), .B (n_6752), .Y (n_6759)); + NOR2X1 g35822(.A (n_750), .B (n_6752), .Y (n_6758)); + XOR2X1 g35723(.A (n_116), .B (n_6756), .Y (n_6757)); + NOR2X1 g35821(.A (n_513), .B (n_6752), .Y (n_6755)); + NOR2X1 g35820(.A (n_609), .B (n_6752), .Y (n_6754)); + NOR2X1 g35817(.A (n_453), .B (n_6752), .Y (n_6753)); + NOR2X1 g35819(.A (n_495), .B (n_6752), .Y (n_6751)); + DFFX1 \u2_res_cnt_reg[2] (.CK (clk_i), .D (n_5628), .Q + (\u2_res_cnt[2] ), .QN ()); + AOI21X1 g35677(.A0 (n_1000), .A1 (n_1214), .B0 (i6_re), .Y (n_6750)); + NOR2X1 g35818(.A (n_740), .B (n_6752), .Y (n_6749)); + NOR2X1 g35816(.A (n_580), .B (n_5440), .Y (n_6747)); + NOR2X1 g35814(.A (n_696), .B (n_6752), .Y (n_6746)); + AOI22X1 g35706(.A0 (n_6686), .A1 (i6_dout_643), .B0 (i3_dout_581), + .B1 (n_6700), .Y (n_6745)); + NOR2X1 g35813(.A (n_669), .B (n_6752), .Y (n_6744)); + AOI22X1 g35694(.A0 (n_6686), .A1 (i6_dout_655), .B0 (i3_dout_593), + .B1 (n_6700), .Y (n_6743)); + NOR2X1 g35811(.A (n_677), .B (n_5440), .Y (n_6742)); + NOR2X1 g35812(.A (n_597), .B (n_5440), .Y (n_6741)); + NOR2X1 g35810(.A (n_694), .B (n_6752), .Y (n_6740)); + NOR2X1 g35809(.A (n_980), .B (n_6752), .Y (n_6739)); + DFFX1 u2_valid_reg(.CK (bit_clk_pad_i), .D (n_5611), .Q (valid), .QN + ()); + AOI22X1 g35693(.A0 (n_6686), .A1 (i6_dout_627), .B0 (i3_dout_565), + .B1 (n_6700), .Y (n_6738)); + AOI22X1 g35692(.A0 (n_6686), .A1 (i6_dout_654), .B0 (i3_dout_592), + .B1 (n_6700), .Y (n_6737)); + DFFX1 \u2_res_cnt_reg[1] (.CK (clk_i), .D (n_5627), .Q + (\u2_res_cnt[1] ), .QN ()); + INVX1 g35782(.A (n_6734), .Y (n_7003)); + INVX1 g35769(.A (n_7042), .Y (n_7038)); + DFFX1 \u3_status_reg[1] (.CK (clk_i), .D (n_5621), .Q + (o3_status_962), .QN ()); + DFFX1 \u6_status_reg[1] (.CK (clk_i), .D (n_5619), .Q + (o7_status_992), .QN ()); + DFFX1 \u7_status_reg[1] (.CK (clk_i), .D (n_5617), .Q + (o8_status_1002), .QN ()); + DFFX1 \u8_status_reg[1] (.CK (clk_i), .D (n_5623), .Q + (o9_status_1012), .QN ()); + NOR2X1 g35336(.A (n_5614), .B (u2_bit_clk_e), .Y (n_6733)); + MX2X1 g35362(.A (u1_sr_117), .B (in_slt_397), .S0 (out_le_182), .Y + (n_6732)); + MX2X1 g35367(.A (u1_sr), .B (in_slt3), .S0 (out_le_182), .Y (n_6731)); + MX2X1 g35368(.A (u1_sr_118), .B (in_slt_398), .S0 (out_le_182), .Y + (n_6730)); + MX2X1 g35369(.A (u1_sr_119), .B (in_slt_399), .S0 (out_le_182), .Y + (n_6729)); + MX2X1 g35371(.A (u1_sr), .B (in_slt4), .S0 (out_le_183), .Y (n_6728)); + MX2X1 g35372(.A (u1_sr_117), .B (in_slt_419), .S0 (out_le_183), .Y + (n_6727)); + MX2X1 g35373(.A (u1_sr_118), .B (in_slt_420), .S0 (out_le_183), .Y + (n_6726)); + MX2X1 g35374(.A (u1_sr_119), .B (in_slt_421), .S0 (out_le_183), .Y + (n_6725)); + MX2X1 g35376(.A (u1_sr), .B (in_slt6), .S0 (out_le_184), .Y (n_6724)); + MX2X1 g35377(.A (u1_sr_117), .B (in_slt_441), .S0 (out_le_184), .Y + (n_6723)); + MX2X1 g35378(.A (u1_sr_118), .B (in_slt_442), .S0 (out_le_184), .Y + (n_6722)); + MX2X1 g35379(.A (u1_sr_119), .B (in_slt_443), .S0 (out_le_184), .Y + (n_6721)); + DFFX1 \u11_status_reg[1] (.CK (clk_i), .D (n_5638), .Q + (i6_status_1042), .QN ()); + INVX1 g35387(.A (i4_status_1032), .Y (n_6720)); + INVX1 g35406(.A (i3_status_1022), .Y (n_6718)); + INVX1 g35484(.A (n_6051), .Y (n_6716)); + DFFX1 u10_empty_reg(.CK (clk_i), .D (n_5612), .Q (), .QN (i4_empty)); + DFFX1 u9_empty_reg(.CK (clk_i), .D (n_5613), .Q (), .QN (i3_empty)); + DFFX1 \in_valid_s1_reg[1] (.CK (clk_i), .D (in_valid_8), .Q + (in_valid_s_1), .QN ()); + NOR2X1 g35569(.A (n_1080), .B (i6_re), .Y (n_6715)); + NOR2X1 g35571(.A (i3_re), .B (\u9_rp[0] ), .Y (n_6714)); + NOR2X1 g35572(.A (n_1085), .B (i3_re), .Y (n_6713)); + NOR2X1 g35586(.A (n_1206), .B (i4_re), .Y (n_6712)); + NOR2X1 g35587(.A (n_1039), .B (i4_re), .Y (n_6711)); + NOR2X1 g35652(.A (\u11_rp[0] ), .B (i6_re), .Y (n_6709)); + INVX2 g35744(.A (n_6710), .Y (n_6999)); + AOI21X1 g35678(.A0 (n_877), .A1 (n_1221), .B0 (i3_re), .Y (n_6708)); + AOI21X1 g35679(.A0 (n_1232), .A1 (n_2364), .B0 (i4_re), .Y (n_6707)); + AOI22X1 g35681(.A0 (n_6686), .A1 (i6_dout), .B0 (i3_dout), .B1 + (n_6700), .Y (n_6706)); + AOI22X1 g35682(.A0 (n_6686), .A1 (i6_dout_636), .B0 (i3_dout_574), + .B1 (n_6700), .Y (n_6705)); + AOI22X1 g35683(.A0 (n_6686), .A1 (i6_dout_639), .B0 (i3_dout_577), + .B1 (n_6700), .Y (n_6703)); + AOI22X1 g35684(.A0 (n_6686), .A1 (i6_dout_640), .B0 (i3_dout_578), + .B1 (n_6700), .Y (n_6702)); + AOI22X1 g35685(.A0 (n_6686), .A1 (i6_dout_644), .B0 (i3_dout_582), + .B1 (n_6700), .Y (n_6699)); + AOI22X1 g35688(.A0 (n_6686), .A1 (i6_dout_648), .B0 (i3_dout_586), + .B1 (n_6700), .Y (n_6697)); + AOI22X1 g35689(.A0 (n_6686), .A1 (i6_dout_651), .B0 (i3_dout_589), + .B1 (n_6700), .Y (n_6696)); + AOI22X1 g35690(.A0 (n_6686), .A1 (i6_dout_652), .B0 (i3_dout_590), + .B1 (n_6700), .Y (n_6694)); + AOI22X1 g35691(.A0 (n_6686), .A1 (i6_dout_653), .B0 (i3_dout_591), + .B1 (n_6700), .Y (n_6693)); + AOI22X1 g35695(.A0 (n_6686), .A1 (i6_dout_656), .B0 (i3_dout_594), + .B1 (n_6700), .Y (n_6692)); + AOI22X1 g35696(.A0 (n_6686), .A1 (i6_dout_628), .B0 (i3_dout_566), + .B1 (n_6700), .Y (n_6691)); + AOI22X1 g35687(.A0 (n_6686), .A1 (i6_dout_647), .B0 (i3_dout_585), + .B1 (n_6700), .Y (n_6690)); + AOI22X1 g35697(.A0 (n_6686), .A1 (i6_dout_629), .B0 (i3_dout_567), + .B1 (n_6700), .Y (n_6688)); + AOI22X1 g35698(.A0 (n_6686), .A1 (i6_dout_630), .B0 (i3_dout_568), + .B1 (n_6700), .Y (n_6687)); + AOI22X1 g35686(.A0 (n_6686), .A1 (i6_dout_646), .B0 (i3_dout_584), + .B1 (n_6700), .Y (n_6685)); + AOI22X1 g35700(.A0 (n_6686), .A1 (i6_dout_632), .B0 (i3_dout_570), + .B1 (n_6700), .Y (n_6684)); + AOI22X1 g35701(.A0 (n_6686), .A1 (i6_dout_633), .B0 (i3_dout_571), + .B1 (n_6700), .Y (n_6683)); + AOI22X1 g35702(.A0 (n_6686), .A1 (i6_dout_634), .B0 (n_6700), .B1 + (i3_dout_572), .Y (n_6681)); + AOI22X1 g35703(.A0 (n_6686), .A1 (i6_dout_626), .B0 (i3_dout_564), + .B1 (n_6700), .Y (n_6680)); + AOI22X1 g35704(.A0 (n_6686), .A1 (i6_dout_642), .B0 (i3_dout_580), + .B1 (n_6700), .Y (n_6678)); + AOI22X1 g35705(.A0 (n_6686), .A1 (i6_dout_637), .B0 (i3_dout_575), + .B1 (n_6700), .Y (n_6677)); + AOI22X1 g35707(.A0 (n_6686), .A1 (i6_dout_638), .B0 (i3_dout_576), + .B1 (n_6700), .Y (n_6676)); + AOI22X1 g35708(.A0 (n_6686), .A1 (i6_dout_635), .B0 (i3_dout_573), + .B1 (n_6700), .Y (n_6675)); + AOI22X1 g35710(.A0 (n_6686), .A1 (i6_dout_641), .B0 (i4_dout_610), + .B1 (n_7297), .Y (n_6674)); + AOI22X1 g35712(.A0 (n_6686), .A1 (i6_dout_649), .B0 (i4_dout_618), + .B1 (n_7297), .Y (n_6673)); + NOR2X1 g35815(.A (n_612), .B (n_6752), .Y (n_6672)); + DFFX1 \u2_in_valid_reg[0] (.CK (bit_clk_pad_i), .D (n_5593), .Q + (in_valid), .QN ()); + NOR2X1 g35824(.A (n_733), .B (n_6752), .Y (n_6671)); + MX2X1 g35971(.A (n_461), .B (n_6510), .S0 (n_5409), .Y (n_6670)); + MX2X1 g35972(.A (n_6668), .B (n_6599), .S0 (n_931), .Y (n_6669)); + MX2X1 g35973(.A (n_6666), .B (n_6596), .S0 (n_5341), .Y (n_6667)); + MX2X1 g35974(.A (n_6664), .B (n_6592), .S0 (n_5341), .Y (n_6665)); + MX2X1 g35975(.A (n_6662), .B (n_6589), .S0 (n_5341), .Y (n_6663)); + MX2X1 g35976(.A (n_6660), .B (n_6586), .S0 (n_5341), .Y (n_6661)); + MX2X1 g35981(.A (n_6486), .B (n_6658), .S0 (n_6649), .Y (n_6659)); + MX2X1 g35983(.A (n_6656), .B (n_6646), .S0 (n_4783), .Y (n_6657)); + MX2X1 g35984(.A (n_6654), .B (n_6637), .S0 (n_4783), .Y (n_6655)); + MX2X1 g35990(.A (n_6652), .B (n_6579), .S0 (n_5341), .Y (n_6653)); + MX2X1 g35991(.A (n_6483), .B (n_6650), .S0 (n_6649), .Y (n_6651)); + MX2X1 g35996(.A (n_6647), .B (n_6646), .S0 (n_930), .Y (n_6648)); + MX2X1 g35997(.A (n_6644), .B (n_6618), .S0 (n_6898), .Y (n_6645)); + MX2X1 g35998(.A (n_6641), .B (n_6533), .S0 (n_6898), .Y (n_6642)); + MX2X1 g35999(.A (n_6638), .B (n_6637), .S0 (n_6898), .Y (n_6639)); + MX2X1 g36000(.A (n_6635), .B (n_6582), .S0 (n_6898), .Y (n_6636)); + MX2X1 g36002(.A (n_6633), .B (n_6576), .S0 (n_5341), .Y (n_6634)); + MX2X1 g36004(.A (n_6630), .B (n_6573), .S0 (n_5341), .Y (n_6631)); + MX2X1 g36007(.A (n_6628), .B (n_6560), .S0 (n_6898), .Y (n_6629)); + MX2X1 g36008(.A (n_6547), .B (n_6625), .S0 (n_6649), .Y (n_6626)); + MX2X1 g36010(.A (n_6623), .B (n_6570), .S0 (n_5341), .Y (n_6624)); + MX2X1 g36011(.A (n_6646), .B (n_6620), .S0 (n_6908), .Y (n_6621)); + MX2X1 g36012(.A (n_6618), .B (n_6617), .S0 (n_6908), .Y (n_6619)); + MX2X1 g36013(.A (n_6539), .B (n_6614), .S0 (n_6908), .Y (n_6615)); + MX2X1 g36015(.A (n_6612), .B (n_6566), .S0 (n_5341), .Y (n_6613)); + MX2X1 g36017(.A (n_6610), .B (n_6602), .S0 (n_931), .Y (n_6611)); + MX2X1 g36018(.A (n_6607), .B (n_6563), .S0 (n_5341), .Y (n_6608)); + MX2X1 g36019(.A (n_6514), .B (n_6604), .S0 (n_6649), .Y (n_6605)); + MX2X1 g36026(.A (n_6602), .B (n_6601), .S0 (n_6594), .Y (n_6603)); + MX2X1 g36027(.A (n_6599), .B (n_6598), .S0 (n_6594), .Y (n_6600)); + MX2X1 g36028(.A (n_6596), .B (n_6595), .S0 (n_6594), .Y (n_6597)); + MX2X1 g36030(.A (n_6592), .B (n_6591), .S0 (n_6594), .Y (n_6593)); + MX2X1 g36031(.A (n_6589), .B (n_6588), .S0 (n_6594), .Y (n_6590)); + MX2X1 g36032(.A (n_6586), .B (n_6585), .S0 (n_6594), .Y (n_6587)); + MX2X1 g36038(.A (n_6582), .B (n_6581), .S0 (n_6908), .Y (n_6583)); + MX2X1 g36039(.A (n_6579), .B (n_6578), .S0 (n_6594), .Y (n_6580)); + MX2X1 g36040(.A (n_6576), .B (n_6575), .S0 (n_6594), .Y (n_6577)); + MX2X1 g36041(.A (n_6573), .B (n_6572), .S0 (n_6594), .Y (n_6574)); + MX2X1 g36042(.A (n_6570), .B (n_6569), .S0 (n_6594), .Y (n_6571)); + MX2X1 g36043(.A (n_6566), .B (n_6565), .S0 (n_6594), .Y (n_6567)); + MX2X1 g36044(.A (n_6563), .B (n_6562), .S0 (n_6594), .Y (n_6564)); + MX2X1 g36049(.A (n_6560), .B (n_6559), .S0 (n_5371), .Y (n_6561)); + MX2X1 g36053(.A (n_6544), .B (n_6556), .S0 (n_6649), .Y (n_6557)); + MX2X1 g36054(.A (n_6521), .B (n_6554), .S0 (n_6649), .Y (n_6555)); + MX2X1 g36055(.A (n_6551), .B (n_6618), .S0 (n_4783), .Y (n_6552)); + MX2X1 g36057(.A (n_6548), .B (n_6547), .S0 (n_995), .Y (n_6549)); + MX2X1 g36058(.A (n_6545), .B (n_6544), .S0 (n_6502), .Y (n_6546)); + MX2X1 g36060(.A (n_6542), .B (n_6573), .S0 (n_832), .Y (n_6543)); + MX2X1 g36061(.A (n_6540), .B (n_6539), .S0 (n_4783), .Y (n_6541)); + MX2X1 g36062(.A (n_6537), .B (n_6560), .S0 (n_5730), .Y (n_6538)); + MX2X1 g36063(.A (n_508), .B (n_6589), .S0 (n_6475), .Y (n_6536)); + MX2X1 g36064(.A (n_6534), .B (n_6533), .S0 (n_4783), .Y (n_6535)); + MX2X1 g36068(.A (n_6530), .B (n_6547), .S0 (n_5312), .Y (n_6531)); + MX2X1 g36069(.A (n_6528), .B (n_6582), .S0 (n_4783), .Y (n_6529)); + MX2X1 g36071(.A (n_6526), .B (n_6579), .S0 (n_6475), .Y (n_6527)); + MX2X1 g36072(.A (n_6497), .B (n_6524), .S0 (n_6649), .Y (n_6525)); + MX2X1 g36073(.A (n_6522), .B (n_6521), .S0 (n_6502), .Y (n_6523)); + MX2X1 g36074(.A (n_6519), .B (n_6478), .S0 (n_6502), .Y (n_6520)); + MX2X1 g36075(.A (n_6517), .B (n_6473), .S0 (n_6502), .Y (n_6518)); + MX2X1 g36076(.A (n_6515), .B (n_6514), .S0 (n_6502), .Y (n_6516)); + MX2X1 g36077(.A (n_6511), .B (n_6510), .S0 (n_995), .Y (n_6512)); + MX2X1 g36079(.A (n_6507), .B (n_6465), .S0 (n_995), .Y (n_6508)); + MX2X1 g36081(.A (n_6637), .B (n_6505), .S0 (n_6908), .Y (n_6506)); + MX2X1 g36082(.A (n_6503), .B (n_6459), .S0 (n_6502), .Y (n_6504)); + MX2X1 g36086(.A (n_6500), .B (n_6453), .S0 (n_6502), .Y (n_6501)); + MX2X1 g36087(.A (n_6498), .B (n_6497), .S0 (n_6502), .Y (n_6499)); + MX2X1 g36088(.A (n_6495), .B (n_6539), .S0 (n_6898), .Y (n_6496)); + MX2X1 g36089(.A (n_6492), .B (n_6444), .S0 (n_995), .Y (n_6493)); + MX2X1 g36090(.A (n_6490), .B (n_6442), .S0 (n_6502), .Y (n_6491)); + MX2X1 g36091(.A (n_6487), .B (n_6486), .S0 (n_6502), .Y (n_6488)); + MX2X1 g36092(.A (n_6484), .B (n_6483), .S0 (n_6502), .Y (n_6485)); + MX2X1 g36095(.A (n_419), .B (n_6521), .S0 (n_5312), .Y (n_6481)); + MX2X1 g36096(.A (n_6479), .B (n_6478), .S0 (n_5312), .Y (n_6480)); + MX2X1 g36097(.A (n_6476), .B (n_6602), .S0 (n_6475), .Y (n_6477)); + MX2X1 g36098(.A (n_433), .B (n_6473), .S0 (n_5312), .Y (n_6474)); + MX2X1 g36099(.A (n_6471), .B (n_6514), .S0 (n_5409), .Y (n_6472)); + MX2X1 g36100(.A (n_6468), .B (n_6599), .S0 (n_5407), .Y (n_6469)); + MX2X1 g36101(.A (n_6466), .B (n_6465), .S0 (n_5409), .Y (n_6467)); + MX2X1 g36102(.A (n_6463), .B (n_6596), .S0 (n_5407), .Y (n_6464)); + MX2X1 g36103(.A (n_6460), .B (n_6459), .S0 (n_5312), .Y (n_6461)); + MX2X1 g36104(.A (n_6457), .B (n_6592), .S0 (n_6475), .Y (n_6458)); + MX2X1 g36106(.A (n_6454), .B (n_6453), .S0 (n_932), .Y (n_6455)); + MX2X1 g36107(.A (n_502), .B (n_6586), .S0 (n_6475), .Y (n_6452)); + MX2X1 g36109(.A (n_6533), .B (n_6450), .S0 (n_6908), .Y (n_6451)); + MX2X1 g36113(.A (n_6448), .B (n_6497), .S0 (n_932), .Y (n_6449)); + MX2X1 g36114(.A (n_6445), .B (n_6444), .S0 (n_5312), .Y (n_6446)); + MX2X1 g36115(.A (n_6442), .B (n_6441), .S0 (n_6649), .Y (n_6443)); + MX2X1 g36116(.A (n_6439), .B (n_6442), .S0 (n_5409), .Y (n_6440)); + MX2X1 g36117(.A (n_6437), .B (n_6544), .S0 (n_5312), .Y (n_6438)); + MX2X1 g36118(.A (n_6434), .B (n_6486), .S0 (n_5312), .Y (n_6435)); + MX2X1 g36119(.A (n_6431), .B (n_6483), .S0 (n_5312), .Y (n_6432)); + MX2X1 g36121(.A (n_6478), .B (n_6428), .S0 (n_6649), .Y (n_6429)); + MX2X1 g36122(.A (n_6473), .B (n_6426), .S0 (n_6649), .Y (n_6427)); + MX2X1 g36123(.A (n_6510), .B (n_6424), .S0 (n_6649), .Y (n_6425)); + MX2X1 g36124(.A (n_6465), .B (n_6421), .S0 (n_6649), .Y (n_6422)); + MX2X1 g36125(.A (n_6459), .B (n_6419), .S0 (n_6649), .Y (n_6420)); + MX2X1 g36126(.A (n_6444), .B (n_6417), .S0 (n_6649), .Y (n_6418)); + MX2X1 g36127(.A (n_6415), .B (n_6576), .S0 (n_5407), .Y (n_6416)); + MX2X1 g36128(.A (n_6453), .B (n_6413), .S0 (n_6649), .Y (n_6414)); + MX2X1 g36129(.A (n_6411), .B (n_6570), .S0 (n_832), .Y (n_6412)); + MX2X1 g36130(.A (n_6408), .B (n_6566), .S0 (n_6475), .Y (n_6409)); + MX2X1 g36131(.A (n_6406), .B (n_6563), .S0 (n_6475), .Y (n_6407)); + MX2X1 g36134(.A (n_6404), .B (n_6646), .S0 (n_6856), .Y (n_6405)); + MX2X1 g36135(.A (n_6402), .B (n_6618), .S0 (n_6856), .Y (n_6403)); + MX2X1 g36136(.A (n_6400), .B (n_6539), .S0 (n_6856), .Y (n_6401)); + MX2X1 g36137(.A (n_6398), .B (n_6637), .S0 (n_6856), .Y (n_6399)); + MX2X1 g36138(.A (n_6396), .B (n_6582), .S0 (n_6856), .Y (n_6397)); + MX2X1 g36148(.A (n_6394), .B (n_6560), .S0 (n_6856), .Y (n_6395)); + MX2X1 g36150(.A (n_6392), .B (n_6533), .S0 (n_6856), .Y (n_6393)); + MX2X1 g36151(.A (n_6390), .B (n_6586), .S0 (n_6341), .Y (n_6391)); + MX2X1 g36152(.A (n_6388), .B (n_6453), .S0 (n_6359), .Y (n_6389)); + MX2X1 g36155(.A (n_6386), .B (n_6602), .S0 (n_6341), .Y (n_6387)); + MX2X1 g36156(.A (n_6384), .B (n_6599), .S0 (n_6341), .Y (n_6385)); + MX2X1 g36157(.A (n_6382), .B (n_6596), .S0 (n_6341), .Y (n_6383)); + MX2X1 g36158(.A (n_6380), .B (n_6592), .S0 (n_6341), .Y (n_6381)); + MX2X1 g36159(.A (n_6377), .B (n_6521), .S0 (n_6359), .Y (n_6378)); + MX2X1 g36160(.A (n_6375), .B (n_6589), .S0 (n_6341), .Y (n_6376)); + MX2X1 g36161(.A (n_6372), .B (n_6478), .S0 (n_6359), .Y (n_6373)); + MX2X1 g36162(.A (n_6370), .B (n_6473), .S0 (n_6359), .Y (n_6371)); + MX2X1 g36163(.A (n_6368), .B (n_6514), .S0 (n_6359), .Y (n_6369)); + MX2X1 g36164(.A (n_6366), .B (n_6510), .S0 (n_6359), .Y (n_6367)); + MX2X1 g36166(.A (n_6363), .B (n_6465), .S0 (n_6359), .Y (n_6364)); + MX2X1 g36167(.A (n_6360), .B (n_6459), .S0 (n_6359), .Y (n_6361)); + MX2X1 g36172(.A (n_6357), .B (n_6497), .S0 (n_6359), .Y (n_6358)); + MX2X1 g36173(.A (n_6355), .B (n_6444), .S0 (n_6359), .Y (n_6356)); + MX2X1 g36174(.A (n_6353), .B (n_6442), .S0 (n_6359), .Y (n_6354)); + MX2X1 g36175(.A (n_6351), .B (n_6544), .S0 (n_6359), .Y (n_6352)); + MX2X1 g36176(.A (n_6349), .B (n_6486), .S0 (n_6359), .Y (n_6350)); + MX2X1 g36177(.A (n_6347), .B (n_6547), .S0 (n_6359), .Y (n_6348)); + MX2X1 g36178(.A (n_6344), .B (n_6483), .S0 (n_6359), .Y (n_6345)); + MX2X1 g36180(.A (n_6342), .B (n_6579), .S0 (n_6341), .Y (n_6343)); + MX2X1 g36181(.A (n_6339), .B (n_6576), .S0 (n_6341), .Y (n_6340)); + MX2X1 g36182(.A (n_6337), .B (n_6573), .S0 (n_6341), .Y (n_6338)); + MX2X1 g36183(.A (n_6335), .B (n_6570), .S0 (n_6341), .Y (n_6336)); + MX2X1 g36185(.A (n_6333), .B (n_6563), .S0 (n_6341), .Y (n_6334)); + MX2X1 g36186(.A (n_6331), .B (n_6566), .S0 (n_6341), .Y (n_6332)); + XOR2X1 g36193(.A (n_614), .B (n_6328), .Y (n_6330)); + NAND2X1 g36309(.A (n_6266), .B (n_6824), .Y (n_6326)); + NAND2X1 g36311(.A (n_6161), .B (n_6316), .Y (n_6325)); + NAND2X1 g36314(.A (n_6244), .B (n_2567), .Y (n_6324)); + NAND2X1 g36321(.A (n_12530), .B (n_6824), .Y (n_6323)); + NAND2X1 g36322(.A (n_6254), .B (n_6824), .Y (n_6322)); + NAND2X1 g36324(.A (n_6824), .B (n_6246), .Y (n_6321)); + NAND2X1 g36325(.A (n_5719), .B (n_6318), .Y (n_6320)); + NAND2X1 g36326(.A (n_6142), .B (n_6318), .Y (n_6319)); + NAND2X1 g36327(.A (n_6194), .B (n_6316), .Y (n_6317)); + NAND2X1 g36329(.A (n_6239), .B (n_6318), .Y (n_6315)); + NAND2X1 g36334(.A (n_5713), .B (n_6318), .Y (n_6314)); + NAND2X1 g36339(.A (n_6248), .B (n_6824), .Y (n_6313)); + NAND2X1 g36340(.A (n_6252), .B (n_6824), .Y (n_6312)); + NAND2X1 g36346(.A (n_6237), .B (n_6824), .Y (n_6309)); + NAND2X1 g36353(.A (n_6207), .B (n_12634), .Y (n_6308)); + NAND2X1 g36357(.A (n_6224), .B (n_6821), .Y (n_6307)); + NAND2X1 g36359(.A (n_6226), .B (n_6821), .Y (n_6305)); + NAND2X1 g36363(.A (n_6167), .B (n_6316), .Y (n_6304)); + NAND2X1 g36369(.A (n_5694), .B (n_12634), .Y (n_6300)); + NAND2X1 g36370(.A (n_6216), .B (n_12634), .Y (n_6298)); + NAND2X1 g36371(.A (n_6211), .B (n_12634), .Y (n_6297)); + NAND2X1 g36372(.A (n_6233), .B (n_12634), .Y (n_6296)); + NAND2X1 g36373(.A (n_6209), .B (n_12634), .Y (n_6295)); + NAND2X1 g36376(.A (n_12514), .B (n_12634), .Y (n_6293)); + NAND2X1 g36378(.A (n_6182), .B (n_2567), .Y (n_6292)); + NAND2X1 g36380(.A (n_6235), .B (n_6316), .Y (n_6290)); + NAND2X1 g36381(.A (n_12618), .B (n_6316), .Y (n_6289)); + NAND2X1 g36382(.A (n_12755), .B (n_6316), .Y (n_6288)); + NAND2X1 g36384(.A (n_12116), .B (n_6316), .Y (n_6287)); + NAND2X1 g36387(.A (n_6260), .B (n_2567), .Y (n_6286)); + NAND2X1 g36389(.A (n_6150), .B (n_6316), .Y (n_11987)); + NAND2X1 g36391(.A (n_6176), .B (n_6316), .Y (n_6283)); + NAND2X1 g36393(.A (n_6184), .B (n_6316), .Y (n_6282)); + NAND2X1 g36394(.A (n_11898), .B (n_6316), .Y (n_6280)); + NAND2X1 g36395(.A (n_6172), .B (n_6316), .Y (n_6279)); + NAND2X1 g36397(.A (n_11895), .B (n_6316), .Y (n_6278)); + NAND2X1 g36399(.A (n_6250), .B (n_2567), .Y (n_6277)); + NAND2X1 g36400(.A (n_6159), .B (n_2567), .Y (n_6275)); + NAND2X1 g36401(.A (n_6204), .B (n_12634), .Y (n_12046)); + NAND2X1 g36404(.A (n_5707), .B (n_6318), .Y (n_6271)); + NAND2X1 g36408(.A (n_7049), .B (n_7048), .Y (n_6268)); + NAND2X1 g36412(.A (n_6266), .B (n_12531), .Y (n_6267)); + NAND2X1 g36413(.A (n_6264), .B (n_6201), .Y (n_6265)); + NAND2X1 g36418(.A (n_6165), .B (n_12115), .Y (n_6263)); + NAND2X1 g36419(.A (n_6260), .B (n_6259), .Y (n_6261)); + NAND2X1 g36437(.A (n_6254), .B (n_12531), .Y (n_6255)); + NAND2X1 g36439(.A (n_6252), .B (n_12531), .Y (n_6253)); + NAND2X1 g36440(.A (n_6250), .B (n_1038), .Y (n_6251)); + NAND2X1 g36443(.A (n_6248), .B (n_12531), .Y (n_6249)); + NAND2X1 g36448(.A (n_6244), .B (n_6259), .Y (n_6245)); + NAND2X1 g36457(.A (n_6241), .B (n_5881), .Y (n_6243)); + NAND2X1 g36488(.A (n_6239), .B (n_6141), .Y (n_6240)); + NAND2X1 g36490(.A (n_6237), .B (n_12531), .Y (n_6238)); + NAND2X1 g36492(.A (n_6235), .B (n_12115), .Y (n_6236)); + NAND2X1 g36497(.A (n_6233), .B (n_6773), .Y (n_6234)); + NAND2X1 g36502(.A (n_12368), .B (n_6816), .Y (n_6232)); + NAND2X1 g36511(.A (n_6228), .B (n_6773), .Y (n_6229)); + NAND2X1 g36513(.A (n_6226), .B (n_6816), .Y (n_6227)); + NAND2X1 g36514(.A (n_6224), .B (n_1297), .Y (n_6225)); + NAND2X1 g36515(.A (n_12368), .B (n_784), .Y (n_6223)); + NAND2X1 g36528(.A (n_6153), .B (n_6259), .Y (n_6221)); + NAND2X1 g36529(.A (n_12111), .B (n_12115), .Y (n_6220)); + NAND2X1 g36534(.A (n_6186), .B (n_634), .Y (n_6218)); + NAND2X1 g36535(.A (n_6216), .B (n_6773), .Y (n_6217)); + NAND2X1 g36537(.A (n_12481), .B (n_6773), .Y (n_6215)); + NAND2X1 g36539(.A (n_6211), .B (n_6773), .Y (n_6212)); + NAND2X1 g36541(.A (n_6209), .B (n_6773), .Y (n_6210)); + NAND2X1 g36544(.A (n_6207), .B (n_6773), .Y (n_6208)); + NAND2X1 g36548(.A (n_6147), .B (n_6773), .Y (n_6206)); + NAND2X1 g36552(.A (n_6204), .B (n_6773), .Y (n_6205)); + NAND2X1 g36554(.A (n_6202), .B (n_6201), .Y (n_6203)); + NAND2X1 g36556(.A (n_6228), .B (n_6201), .Y (n_6200)); + NAND2X1 g36557(.A (n_12514), .B (n_6201), .Y (n_6199)); + NAND2X1 g36566(.A (n_11855), .B (n_6201), .Y (n_6197)); + NAND2X1 g36569(.A (n_6194), .B (n_12115), .Y (n_6195)); + NAND2X1 g36570(.A (n_12618), .B (n_12115), .Y (n_6193)); + NAND2X1 g36571(.A (n_12755), .B (n_12115), .Y (n_6191)); + NAND2X1 g36573(.A (n_6144), .B (n_12115), .Y (n_6188)); + NAND2X1 g36575(.A (n_6186), .B (n_12115), .Y (n_6187)); + NAND2X1 g36578(.A (n_6184), .B (n_12115), .Y (n_6185)); + NAND2X1 g36579(.A (n_6182), .B (n_6259), .Y (n_6183)); + NAND2X1 g36580(.A (n_6180), .B (n_12531), .Y (n_6181)); + NAND2X1 g36581(.A (n_11898), .B (n_12115), .Y (n_6179)); + NAND2X1 g36582(.A (n_6176), .B (n_12664), .Y (n_6177)); + NAND2X1 g36583(.A (n_6174), .B (n_634), .Y (n_11986)); + NAND2X1 g36584(.A (n_6172), .B (n_12115), .Y (n_6173)); + NAND2X1 g36588(.A (n_6155), .B (n_6259), .Y (n_6169)); + NAND2X1 g36589(.A (n_6167), .B (n_12115), .Y (n_6168)); + NAND2X1 g36591(.A (n_6165), .B (n_634), .Y (n_6166)); + NAND2X1 g36592(.A (n_6163), .B (n_12115), .Y (n_6164)); + NAND2X1 g36594(.A (n_6161), .B (n_12115), .Y (n_6162)); + NAND2X1 g36595(.A (n_6159), .B (n_6259), .Y (n_6160)); + NAND2X1 g36597(.A (n_6157), .B (n_12115), .Y (n_6158)); + NAND2X1 g36598(.A (n_6155), .B (n_6152), .Y (n_6156)); + NAND2X1 g36600(.A (n_6153), .B (n_6152), .Y (n_6154)); + NAND2X1 g36602(.A (n_6150), .B (n_12664), .Y (n_6151)); + NAND2X1 g36604(.A (n_6147), .B (n_6118), .Y (n_12047)); + NAND2X1 g36606(.A (n_12514), .B (n_6773), .Y (n_6146)); + INVX4 g36607(.A (n_5797), .Y (n_7353)); + NAND2X1 g36609(.A (n_6144), .B (n_634), .Y (n_6145)); + NAND2X1 g36610(.A (n_6142), .B (n_6141), .Y (n_6143)); + NAND2X1 g36611(.A (n_5709), .B (n_6091), .Y (n_6140)); + OAI21X1 g36616(.A0 (n_4629), .A1 (n_5200), .B0 (n_784), .Y (n_6139)); + OAI21X1 g36619(.A0 (n_4576), .A1 (n_5203), .B0 (n_784), .Y (n_6138)); + OAI21X1 g36620(.A0 (n_4569), .A1 (n_5196), .B0 (n_6131), .Y (n_6137)); + OAI21X1 g36621(.A0 (n_4632), .A1 (n_5454), .B0 (n_6134), .Y (n_6136)); + OAI21X1 g36622(.A0 (n_4568), .A1 (n_5463), .B0 (n_6134), .Y (n_6135)); + OAI21X1 g36624(.A0 (n_4586), .A1 (n_5212), .B0 (n_6134), .Y (n_6133)); + OAI21X1 g36625(.A0 (n_4603), .A1 (n_5224), .B0 (n_6131), .Y (n_6132)); + OAI21X1 g36629(.A0 (n_12849), .A1 (n_12850), .B0 (\u4_rp[0] ), .Y + (n_6130)); + OAI21X1 g36630(.A0 (n_12851), .A1 (n_12852), .B0 (\u4_rp[0] ), .Y + (n_6129)); + OAI21X1 g36633(.A0 (n_4609), .A1 (n_5222), .B0 (n_6134), .Y (n_6127)); + OAI21X1 g36634(.A0 (n_4608), .A1 (n_5220), .B0 (n_6131), .Y (n_6126)); + OAI21X1 g36639(.A0 (n_4607), .A1 (n_5219), .B0 (\u4_rp[0] ), .Y + (n_6125)); + OAI21X1 g36640(.A0 (n_4606), .A1 (n_5218), .B0 (\u4_rp[0] ), .Y + (n_6124)); + OAI21X1 g36646(.A0 (n_4595), .A1 (n_5213), .B0 (n_6131), .Y (n_6123)); + OAI21X1 g36661(.A0 (n_5214), .A1 (n_5460), .B0 (n_6118), .Y (n_6122)); + NAND2X1 g36665(.A (n_5538), .B (n_6091), .Y (n_6121)); + OAI21X1 g36666(.A0 (n_5215), .A1 (n_5458), .B0 (n_6118), .Y (n_6119)); + NAND2X1 g36667(.A (n_5557), .B (n_6091), .Y (n_6117)); + OAI21X1 g36670(.A0 (n_12054), .A1 (n_12055), .B0 (n_784), .Y + (n_6116)); + OAI21X1 g36671(.A0 (n_12056), .A1 (n_12057), .B0 (n_784), .Y + (n_6114)); + OAI21X1 g36673(.A0 (n_12048), .A1 (n_12049), .B0 (n_784), .Y + (n_6113)); + OAI21X1 g36674(.A0 (n_12050), .A1 (n_12051), .B0 (n_784), .Y + (n_6112)); + OAI21X1 g36675(.A0 (n_12052), .A1 (n_12053), .B0 (n_784), .Y + (n_6111)); + OAI21X1 g36676(.A0 (n_12058), .A1 (n_12059), .B0 (n_784), .Y + (n_6109)); + OAI21X1 g36678(.A0 (n_4573), .A1 (n_5199), .B0 (n_784), .Y (n_6108)); + OAI21X1 g36680(.A0 (n_5461), .A1 (n_5205), .B0 (n_6118), .Y (n_6106)); + OAI21X1 g36681(.A0 (n_4610), .A1 (n_5197), .B0 (n_784), .Y (n_6105)); + OAI21X1 g36682(.A0 (n_12060), .A1 (n_12061), .B0 (n_784), .Y + (n_6104)); + OAI21X1 g36685(.A0 (n_4572), .A1 (n_5198), .B0 (n_784), .Y (n_6103)); + OAI21X1 g36690(.A0 (n_5451), .A1 (n_5457), .B0 (n_6118), .Y (n_6099)); + OAI21X1 g36691(.A0 (n_5455), .A1 (n_5456), .B0 (n_6118), .Y (n_6097)); + OAI21X1 g36692(.A0 (n_5210), .A1 (n_5202), .B0 (n_6118), .Y (n_6096)); + NAND2X1 g36693(.A (n_5539), .B (n_6118), .Y (n_6095)); + OAI21X1 g36702(.A0 (n_5452), .A1 (n_5453), .B0 (n_6118), .Y (n_6094)); + NAND2X1 g36704(.A (n_5535), .B (n_6152), .Y (n_6093)); + NAND2X1 g36711(.A (n_5559), .B (n_6091), .Y (n_6092)); + AOI21X1 g36724(.A0 (n_6089), .A1 (n_5371), .B0 (n_5570), .Y (n_6090)); + AOI21X1 g36725(.A0 (n_6087), .A1 (n_5371), .B0 (n_5569), .Y (n_6088)); + INVX1 g36781(.A (n_6765), .Y (n_6085)); + INVX1 g36830(.A (n_6777), .Y (n_6084)); + INVX1 g36835(.A (n_12354), .Y (n_6082)); + INVX1 g36840(.A (n_6790), .Y (n_6081)); + INVX1 g36844(.A (n_6803), .Y (n_6080)); + INVX1 g36847(.A (n_6807), .Y (n_6079)); + INVX1 g36849(.A (n_6800), .Y (n_6078)); + INVX1 g36966(.A (n_6805), .Y (n_6077)); + INVX1 g36973(.A (n_12171), .Y (n_6076)); + INVX1 g36979(.A (n_6779), .Y (n_6075)); + INVX1 g36983(.A (n_6786), .Y (n_6074)); + INVX1 g37012(.A (n_6814), .Y (n_6073)); + INVX1 g37043(.A (n_6763), .Y (n_6072)); + INVX1 g37100(.A (n_6769), .Y (n_6070)); + INVX1 g37126(.A (n_6783), .Y (n_6069)); + AOI22X1 g35699(.A0 (n_6686), .A1 (i6_dout_631), .B0 (i3_dout_569), + .B1 (n_6700), .Y (n_6068)); + AND2X1 g33261(.A (n_5633), .B (u2_sync_resume), .Y (n_6067)); + NAND2X1 g33371(.A (n_5635), .B (n_6057), .Y (n_6066)); + NOR2X1 g33382(.A (n_5631), .B (u2_bit_clk_e), .Y (n_6065)); + NOR2X1 g35827(.A (n_666), .B (n_6752), .Y (n_6064)); + NOR2X1 g35826(.A (n_550), .B (n_5440), .Y (n_6063)); + NOR2X1 g35825(.A (n_541), .B (n_5440), .Y (n_6062)); + DFFX1 u12_we1_reg(.CK (clk_i), .D (n_5361), .Q (u12_we1), .QN ()); + NOR2X1 g35669(.A (n_5444), .B (n_1274), .Y (n_6061)); + XOR2X1 g35722(.A (n_214), .B (n_6059), .Y (n_6060)); + DFFX1 \u1_sr_reg[4] (.CK (bit_clk_pad_i), .D (u1_sr_119), .Q + (u1_sr_120), .QN ()); + DFFX1 \u2_in_valid_reg[2] (.CK (bit_clk_pad_i), .D (n_5432), .Q + (in_valid_9), .QN ()); + NAND2X1 g34715(.A (n_5448), .B (n_6057), .Y (n_6058)); + BUFX3 g35776(.A (n_6734), .Y (n_7042)); + AOI21X1 g34904(.A0 (n_4845), .A1 (n_2368), .B0 (n_4805), .Y (n_6056)); + AOI21X1 g34905(.A0 (n_4844), .A1 (n_2302), .B0 (n_4035), .Y (n_6055)); + NOR2X1 g35338(.A (n_5445), .B (u2_bit_clk_e), .Y (n_6054)); + DFFX1 \u10_status_reg[1] (.CK (clk_i), .D (n_5431), .Q + (i4_status_1032), .QN ()); + DFFX1 \u9_status_reg[1] (.CK (clk_i), .D (n_5449), .Q + (i3_status_1022), .QN ()); + AND2X1 g35419(.A (n_5450), .B (u2_sync_resume), .Y (n_6053)); + NAND2X1 g35463(.A (n_2629), .B (n_6057), .Y (n_6052)); + NAND4X1 g35485(.A (n_5249), .B (wb_cyc_i), .C (n_303), .D (wb_stb_i), + .Y (n_6051)); + XOR2X1 g35499(.A (n_6049), .B (n_4842), .Y (n_6050)); + XOR2X1 g35500(.A (n_6047), .B (n_4841), .Y (n_6048)); + AOI22X1 g35507(.A0 (n_5630), .A1 (\u2_to_cnt[5] ), .B0 (n_5629), .B1 + (n_4853), .Y (n_6046)); + DFFX1 u11_empty_reg(.CK (clk_i), .D (n_5383), .Q (), .QN (i6_empty)); + DFFX1 u2_sync_beat_reg(.CK (bit_clk_pad_i), .D (n_5441), .Q + (u2_sync_beat), .QN ()); + NAND2X1 g35560(.A (n_6045), .B (n_5225), .Y (n_7025)); + NAND2X1 g35561(.A (n_6045), .B (n_6044), .Y (n_7022)); + NAND2X1 g35562(.A (n_6045), .B (n_6042), .Y (n_6043)); + AND2X1 g35563(.A (n_5226), .B (n_2608), .Y (n_6041)); + BUFX3 g35760(.A (n_6734), .Y (n_6710)); + XOR2X1 g35726(.A (n_1446), .B (n_12588), .Y (n_6040)); + DFFSRX1 u11_full_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_5443), .Q (i6_full), .QN ()); + MX2X1 g35969(.A (n_6037), .B (n_6017), .S0 (n_5407), .Y (n_6038)); + MX2X1 g35970(.A (n_5983), .B (n_6035), .S0 (n_6649), .Y (n_6036)); + MX2X1 g35977(.A (n_6033), .B (n_6014), .S0 (n_5341), .Y (n_6034)); + MX2X1 g35978(.A (n_6030), .B (n_6011), .S0 (n_931), .Y (n_6031)); + MX2X1 g35979(.A (n_6028), .B (n_6008), .S0 (n_931), .Y (n_6029)); + MX2X1 g35980(.A (n_5987), .B (n_6026), .S0 (n_6649), .Y (n_6027)); + NOR2X1 g35845(.A (n_5404), .B (u2_bit_clk_e), .Y (n_6025)); + MX2X1 g35986(.A (n_5993), .B (n_6023), .S0 (n_6649), .Y (n_6024)); + MX2X1 g36021(.A (n_6021), .B (n_6003), .S0 (n_5341), .Y (n_6022)); + MX2X1 g36025(.A (n_6018), .B (n_6017), .S0 (n_5341), .Y (n_6019)); + MX2X1 g36033(.A (n_6014), .B (n_6013), .S0 (n_6594), .Y (n_6015)); + MX2X1 g36034(.A (n_6011), .B (n_6010), .S0 (n_6594), .Y (n_6012)); + MX2X1 g36036(.A (n_6008), .B (n_6007), .S0 (n_6594), .Y (n_6009)); + MX2X1 g36037(.A (n_5997), .B (n_6005), .S0 (n_6594), .Y (n_6006)); + MX2X1 g36045(.A (n_6003), .B (n_6002), .S0 (n_6594), .Y (n_6004)); + MX2X1 g36046(.A (n_6017), .B (n_6000), .S0 (n_6594), .Y (n_6001)); + MX2X1 g36050(.A (n_5998), .B (n_5997), .S0 (n_5341), .Y (n_5999)); + MX2X1 g36078(.A (n_5994), .B (n_5993), .S0 (n_5312), .Y (n_5995)); + MX2X1 g36083(.A (n_5990), .B (n_5993), .S0 (n_6502), .Y (n_5991)); + MX2X1 g36084(.A (n_5988), .B (n_5987), .S0 (n_6502), .Y (n_5989)); + MX2X1 g36093(.A (n_5984), .B (n_5983), .S0 (n_6502), .Y (n_5985)); + MX2X1 g36094(.A (n_5981), .B (n_5997), .S0 (n_6475), .Y (n_5982)); + MX2X1 g36105(.A (n_5978), .B (n_5987), .S0 (n_5312), .Y (n_5979)); + NOR2X1 g35844(.A (n_5403), .B (u2_bit_clk_e), .Y (n_5976)); + MX2X1 g36108(.A (n_5974), .B (n_6014), .S0 (n_6475), .Y (n_5975)); + MX2X1 g36110(.A (n_501), .B (n_6011), .S0 (n_6475), .Y (n_5973)); + MX2X1 g36112(.A (n_406), .B (n_6008), .S0 (n_6475), .Y (n_5971)); + MX2X1 g36120(.A (n_5969), .B (n_5983), .S0 (n_5312), .Y (n_5970)); + MX2X1 g36132(.A (n_5966), .B (n_6003), .S0 (n_6475), .Y (n_5967)); + XOR2X1 g35724(.A (n_1255), .B (n_5964), .Y (n_5965)); + MX2X1 g36153(.A (n_5962), .B (n_6017), .S0 (n_6341), .Y (n_5963)); + MX2X1 g36154(.A (n_5959), .B (n_5997), .S0 (n_6341), .Y (n_5960)); + MX2X1 g36165(.A (n_5957), .B (n_6014), .S0 (n_6341), .Y (n_5958)); + MX2X1 g36168(.A (n_5955), .B (n_6011), .S0 (n_6341), .Y (n_5956)); + MX2X1 g36169(.A (n_5953), .B (n_5993), .S0 (n_6359), .Y (n_5954)); + MX2X1 g36170(.A (n_5951), .B (n_5987), .S0 (n_6359), .Y (n_5952)); + MX2X1 g36171(.A (n_5949), .B (n_6008), .S0 (n_6341), .Y (n_5950)); + MX2X1 g36179(.A (n_5947), .B (n_5983), .S0 (n_6359), .Y (n_5948)); + MX2X1 g36184(.A (n_5945), .B (n_6003), .S0 (n_6341), .Y (n_5946)); + XOR2X1 g36194(.A (n_657), .B (n_5942), .Y (n_5944)); + DFFX1 \u10_dout_reg[14] (.CK (clk_i), .D (n_5382), .Q (i4_dout_608), + .QN ()); + DFFX1 \u10_dout_reg[15] (.CK (clk_i), .D (n_5393), .Q (i4_dout_609), + .QN ()); + DFFX1 \u10_dout_reg[17] (.CK (clk_i), .D (n_5392), .Q (i4_dout_611), + .QN ()); + DFFX1 \u10_dout_reg[18] (.CK (clk_i), .D (n_5391), .Q (i4_dout_612), + .QN ()); + DFFX1 \u10_dout_reg[19] (.CK (clk_i), .D (n_5390), .Q (i4_dout_613), + .QN ()); + DFFX1 \u10_dout_reg[1] (.CK (clk_i), .D (n_5389), .Q (i4_dout_595), + .QN ()); + DFFX1 \u10_dout_reg[20] (.CK (clk_i), .D (n_5388), .Q (i4_dout_614), + .QN ()); + DFFX1 \u10_dout_reg[21] (.CK (clk_i), .D (n_5387), .Q (i4_dout_615), + .QN ()); + DFFX1 \u10_dout_reg[22] (.CK (clk_i), .D (n_5386), .Q (i4_dout_616), + .QN ()); + DFFX1 \u10_dout_reg[23] (.CK (clk_i), .D (n_5385), .Q (i4_dout_617), + .QN ()); + NAND2X1 g36307(.A (n_6821), .B (n_12626), .Y (n_5941)); + NAND2X1 g36312(.A (n_5893), .B (n_2567), .Y (n_5939)); + NAND2X1 g36313(.A (n_5800), .B (n_2567), .Y (n_5938)); + NAND2X1 g36328(.A (n_5857), .B (n_6318), .Y (n_5937)); + NAND2X1 g36330(.A (n_5886), .B (n_6318), .Y (n_5936)); + NAND2X1 g36331(.A (n_5884), .B (n_6318), .Y (n_5935)); + NAND2X1 g36332(.A (n_5882), .B (n_6318), .Y (n_5934)); + NAND2X1 g36333(.A (n_5879), .B (n_6318), .Y (n_5933)); + NAND2X1 g36335(.A (n_5561), .B (n_6318), .Y (n_5932)); + NAND2X1 g36336(.A (n_5863), .B (n_6318), .Y (n_5931)); + NAND2X1 g36338(.A (n_5865), .B (n_3559), .Y (n_5929)); + NAND2X1 g36344(.A (n_5835), .B (n_6821), .Y (n_5926)); + NAND2X1 g36345(.A (n_5833), .B (n_6821), .Y (n_5925)); + NAND2X1 g36348(.A (n_5855), .B (n_6821), .Y (n_5924)); + NAND2X1 g36350(.A (n_5853), .B (n_6821), .Y (n_5923)); + NAND2X1 g36352(.A (n_6821), .B (n_5851), .Y (n_5922)); + NAND2X1 g36355(.A (n_5847), .B (n_6821), .Y (n_5921)); + NAND2X1 g36356(.A (n_6821), .B (n_5844), .Y (n_5920)); + NAND2X1 g36360(.A (n_5544), .B (n_12634), .Y (n_5919)); + NAND2X1 g36361(.A (n_5841), .B (n_6821), .Y (n_5918)); + NAND2X1 g36362(.A (n_5837), .B (n_6821), .Y (n_5917)); + NAND2X1 g36364(.A (n_5815), .B (n_2567), .Y (n_5916)); + NAND2X1 g36377(.A (n_5541), .B (n_12634), .Y (n_5914)); + NAND2X1 g36383(.A (n_5895), .B (n_2567), .Y (n_5913)); + NAND2X1 g36385(.A (n_5798), .B (n_2567), .Y (n_5911)); + NAND2X1 g36388(.A (n_5813), .B (n_2567), .Y (n_5910)); + NAND2X1 g36390(.A (n_5811), .B (n_2567), .Y (n_5909)); + NAND2X1 g36392(.A (n_5807), .B (n_2567), .Y (n_5908)); + NAND2X1 g36396(.A (n_5809), .B (n_2567), .Y (n_5907)); + NAND2X1 g36398(.A (n_5803), .B (n_2567), .Y (n_5906)); + NAND2X1 g36403(.A (n_5898), .B (n_2567), .Y (n_5905)); + NAND2X1 g36406(.A (n_5859), .B (n_3559), .Y (n_5904)); + NAND2X1 g36407(.A (n_6836), .B (\u8_wp[1] ), .Y (n_5903)); + NAND2X1 g36409(.A (n_6842), .B (n_6841), .Y (n_5902)); + NAND2X1 g36410(.A (n_6839), .B (n_6838), .Y (n_5901)); + NAND2X1 g36421(.A (n_5898), .B (n_6259), .Y (n_5899)); + NAND2X1 g36423(.A (n_5805), .B (n_6152), .Y (n_5897)); + NAND2X1 g36424(.A (n_5895), .B (n_6259), .Y (n_5896)); + NAND2X1 g36425(.A (n_5893), .B (n_6259), .Y (n_5894)); + NOR2X1 g36426(.A (n_838), .B (n_6057), .Y (n_5892)); + NAND2X1 g36428(.A (n_5823), .B (n_6152), .Y (n_5890)); + NAND2X1 g35840(.A (n_4825), .B (n_6057), .Y (n_5889)); + NAND2X1 g36446(.A (n_5874), .B (n_6091), .Y (n_5888)); + NAND2X1 g36451(.A (n_5886), .B (n_6141), .Y (n_5887)); + NAND2X1 g36452(.A (n_5884), .B (n_6141), .Y (n_5885)); + NAND2X1 g36453(.A (n_5882), .B (n_5881), .Y (n_5883)); + NAND2X1 g36454(.A (n_5879), .B (n_5881), .Y (n_5880)); + NAND2X1 g36455(.A (n_5882), .B (n_5876), .Y (n_5878)); + NAND2X1 g36456(.A (n_5879), .B (n_5876), .Y (n_5877)); + NAND2X1 g36458(.A (n_5874), .B (n_6141), .Y (n_5875)); + NAND2X1 g36477(.A (n_12681), .B (n_6141), .Y (n_5873)); + NAND2X1 g36478(.A (n_5874), .B (n_5876), .Y (n_5871)); + NAND2X1 g36479(.A (n_5869), .B (n_1229), .Y (n_5870)); + NAND2X1 g36480(.A (n_5867), .B (n_5876), .Y (n_5868)); + NAND2X1 g36481(.A (n_5865), .B (n_1229), .Y (n_5866)); + NAND2X1 g36482(.A (n_5863), .B (n_5876), .Y (n_5864)); + NAND2X1 g36484(.A (n_5869), .B (n_5876), .Y (n_5862)); + NAND2X1 g36485(.A (n_5865), .B (n_5876), .Y (n_5861)); + NAND2X1 g36486(.A (n_5859), .B (n_5876), .Y (n_5860)); + NAND2X1 g36487(.A (n_5857), .B (n_5881), .Y (n_5858)); + NAND2X1 g36491(.A (n_6816), .B (n_5855), .Y (n_5856)); + NAND2X1 g36496(.A (n_6816), .B (n_5853), .Y (n_5854)); + NAND2X1 g36499(.A (n_6816), .B (n_5851), .Y (n_5852)); + NAND2X1 g36500(.A (n_12626), .B (n_6816), .Y (n_5850)); + NAND2X1 g36501(.A (n_6816), .B (n_5847), .Y (n_5848)); + NAND2X1 g36506(.A (n_5829), .B (n_6816), .Y (n_5846)); + NAND2X1 g36512(.A (n_5844), .B (n_1297), .Y (n_5845)); + NAND2X1 g36516(.A (n_6816), .B (n_5841), .Y (n_5842)); + NOR2X1 g36517(.A (o3_status), .B (n_5839), .Y (n_5840)); + NAND2X1 g36518(.A (n_6816), .B (n_5837), .Y (n_5838)); + NAND2X1 g36519(.A (n_6816), .B (n_5835), .Y (n_5836)); + NAND2X1 g36521(.A (n_6816), .B (n_5833), .Y (n_5834)); + NOR2X1 g36522(.A (o4_status), .B (n_5831), .Y (n_5832)); + NAND2X1 g36527(.A (n_5829), .B (n_784), .Y (n_5830)); + NOR2X1 g36531(.A (o7_status), .B (n_5827), .Y (n_5828)); + NOR2X1 g36532(.A (o8_status), .B (n_5825), .Y (n_5826)); + NAND2X1 g36533(.A (n_5823), .B (n_6259), .Y (n_5824)); + NAND2X1 g36550(.A (n_1773), .B (n_6057), .Y (n_5822)); + NAND2X1 g36551(.A (n_1928), .B (n_6057), .Y (n_5821)); + NAND2X1 g36553(.A (n_1552), .B (n_6057), .Y (n_5820)); + NAND2X1 g36559(.A (n_5818), .B (n_6773), .Y (n_5819)); + NAND2X1 g36564(.A (n_5818), .B (n_6201), .Y (n_5817)); + NAND2X1 g36574(.A (n_5815), .B (n_6259), .Y (n_5816)); + NAND2X1 g36576(.A (n_5813), .B (n_6259), .Y (n_5814)); + NAND2X1 g36577(.A (n_5811), .B (n_6259), .Y (n_5812)); + NAND2X1 g36586(.A (n_5809), .B (n_6259), .Y (n_5810)); + NAND2X1 g36590(.A (n_5807), .B (n_6259), .Y (n_5808)); + NAND2X1 g36593(.A (n_5805), .B (n_6259), .Y (n_5806)); + NAND2X1 g36596(.A (n_5803), .B (n_1038), .Y (n_5804)); + NAND2X1 g36599(.A (n_5800), .B (n_6259), .Y (n_5801)); + NAND2X1 g36601(.A (n_5798), .B (n_6259), .Y (n_5799)); + AND2X1 g36608(.A (n_5384), .B (n_1779), .Y (n_5797)); + OAI21X1 g36615(.A0 (n_5185), .A1 (n_5184), .B0 (n_634), .Y (n_5796)); + NAND2X1 g36618(.A (n_5252), .B (n_3980), .Y (n_5795)); + OAI21X1 g36623(.A0 (n_4611), .A1 (n_5163), .B0 (n_6152), .Y (n_5794)); + OAI21X1 g36626(.A0 (n_5165), .A1 (n_5164), .B0 (n_6152), .Y (n_5793)); + NAND2X1 g36627(.A (n_5278), .B (n_3982), .Y (n_5791)); + OAI21X1 g36632(.A0 (n_4553), .A1 (n_5173), .B0 (n_6152), .Y (n_5790)); + AOI21X1 g36635(.A0 (n_5591), .A1 (n_5788), .B0 (n_5275), .Y (n_5789)); + NAND2X1 g36641(.A (n_5270), .B (n_3975), .Y (n_5787)); + NAND2X1 g36643(.A (n_5279), .B (n_3981), .Y (n_5786)); + NAND2X1 g36644(.A (n_5266), .B (n_3974), .Y (n_5785)); + NAND2X1 g36645(.A (n_5265), .B (n_2582), .Y (n_5784)); + NAND2X1 g36647(.A (n_5263), .B (n_3971), .Y (n_5783)); + NAND2X1 g36648(.A (n_5261), .B (n_2580), .Y (n_5782)); + NAND2X1 g36649(.A (n_5260), .B (n_2579), .Y (n_5781)); + NAND2X1 g36650(.A (n_5258), .B (n_3970), .Y (n_5780)); + NAND2X1 g36651(.A (n_5256), .B (n_3969), .Y (n_5779)); + NAND2X1 g36653(.A (n_5251), .B (n_2614), .Y (n_5777)); + OAI21X1 g36654(.A0 (n_3917), .A1 (n_4599), .B0 (n_6091), .Y (n_5776)); + OAI21X1 g36655(.A0 (n_3916), .A1 (n_4598), .B0 (n_6091), .Y (n_5775)); + OAI21X1 g36656(.A0 (n_4570), .A1 (n_4597), .B0 (n_5772), .Y (n_5774)); + OAI21X1 g36657(.A0 (n_3915), .A1 (n_4596), .B0 (n_5772), .Y (n_5773)); + OAI21X1 g36658(.A0 (n_3914), .A1 (n_4594), .B0 (n_5772), .Y (n_5771)); + OAI21X1 g36659(.A0 (n_4593), .A1 (n_4592), .B0 (n_5772), .Y (n_5770)); + OAI21X1 g36660(.A0 (n_4581), .A1 (n_4591), .B0 (n_5772), .Y (n_5769)); + OAI21X1 g36662(.A0 (n_4590), .A1 (n_4589), .B0 (n_5772), .Y (n_5768)); + OAI21X1 g36663(.A0 (n_5167), .A1 (n_5166), .B0 (n_634), .Y (n_5767)); + NAND2X1 g36664(.A (n_5254), .B (n_3978), .Y (n_5765)); + OAI21X1 g36668(.A0 (n_4587), .A1 (n_5183), .B0 (n_5772), .Y (n_5764)); + NAND2X1 g36672(.A (n_5253), .B (n_2578), .Y (n_5763)); + OAI21X1 g36677(.A0 (n_5188), .A1 (n_5162), .B0 (n_634), .Y (n_5762)); + NAND2X1 g36679(.A (n_5255), .B (n_3966), .Y (n_5761)); + OAI21X1 g36683(.A0 (n_5170), .A1 (n_5168), .B0 (n_634), .Y (n_5760)); + OAI21X1 g36684(.A0 (n_5171), .A1 (n_4580), .B0 (n_6152), .Y (n_5759)); + OAI21X1 g36688(.A0 (n_4574), .A1 (n_5172), .B0 (n_6152), .Y (n_5758)); + OAI21X1 g36697(.A0 (n_5194), .A1 (n_5193), .B0 (n_634), .Y (n_5757)); + OAI21X1 g36698(.A0 (n_4627), .A1 (n_5191), .B0 (n_634), .Y (n_5756)); + OAI21X1 g36700(.A0 (n_5179), .A1 (n_5195), .B0 (n_634), .Y (n_5753)); + OAI21X1 g36701(.A0 (n_5190), .A1 (n_5189), .B0 (n_634), .Y (n_5751)); + OAI21X1 g36705(.A0 (n_5181), .A1 (n_5180), .B0 (n_634), .Y (n_5749)); + OAI21X1 g36706(.A0 (n_4628), .A1 (n_5178), .B0 (n_6152), .Y (n_5748)); + OAI21X1 g36707(.A0 (n_5177), .A1 (n_5176), .B0 (n_6152), .Y (n_5747)); + OAI21X1 g36708(.A0 (n_5174), .A1 (n_5182), .B0 (n_6152), .Y (n_5745)); + OAI21X1 g36709(.A0 (n_4552), .A1 (n_5175), .B0 (n_6152), .Y (n_5744)); + OAI21X1 g36710(.A0 (n_4551), .A1 (n_5161), .B0 (n_6152), .Y (n_5743)); + OAI21X1 g36712(.A0 (n_4571), .A1 (n_5169), .B0 (n_6152), .Y (n_5742)); + NAND2X1 g35839(.A (n_4826), .B (n_6057), .Y (n_5741)); + MX2X1 g36718(.A (\u9_mem[0]_167 ), .B (n_5736), .S0 (n_6856), .Y + (n_5740)); + MX2X1 g36719(.A (\u9_mem[0]_168 ), .B (n_5733), .S0 (n_6856), .Y + (n_5738)); + MX2X1 g36720(.A (\u9_mem[1]_136 ), .B (n_5736), .S0 (n_5730), .Y + (n_5737)); + MX2X1 g36722(.A (\u9_mem[2]_105 ), .B (n_5736), .S0 (n_5732), .Y + (n_5735)); + MX2X1 g36723(.A (\u9_mem[2]_106 ), .B (n_5733), .S0 (n_5732), .Y + (n_5734)); + MX2X1 g36739(.A (\u9_mem[1]_137 ), .B (n_5733), .S0 (n_5730), .Y + (n_5731)); + NAND4X1 g36782(.A (n_3509), .B (n_3056), .C (n_4249), .D (n_2420), .Y + (n_6765)); + INVX1 g36816(.A (n_6252), .Y (n_5729)); + INVX1 g36821(.A (n_6246), .Y (n_5728)); + INVX1 g36826(.A (n_6266), .Y (n_5727)); + NAND4X1 g36831(.A (n_11650), .B (n_11651), .C (n_2906), .D (n_11472), + .Y (n_6777)); + INVX1 g36837(.A (n_6209), .Y (n_5726)); + NAND4X1 g36841(.A (n_4243), .B (n_3517), .C (n_2350), .D (n_4261), .Y + (n_6790)); + NAND4X1 g36842(.A (n_4144), .B (n_2972), .C (n_2260), .D (n_4252), .Y + (n_6797)); + NAND4X1 g36843(.A (n_4147), .B (n_3393), .C (n_2348), .D (n_4260), .Y + (n_6794)); + NAND4X1 g36845(.A (n_4195), .B (n_3108), .C (n_2277), .D (n_4259), .Y + (n_6803)); + NAND4X1 g36848(.A (n_4192), .B (n_1491), .C (n_2314), .D (n_4257), .Y + (n_6807)); + NAND4X1 g36850(.A (n_4208), .B (n_3388), .C (n_2304), .D (n_4256), .Y + (n_6800)); + INVX1 g36851(.A (n_12530), .Y (n_5725)); + INVX1 g36853(.A (n_6254), .Y (n_5724)); + INVX1 g36865(.A (n_6157), .Y (n_5723)); + INVX1 g36868(.A (n_6237), .Y (n_5722)); + INVX1 g36872(.A (n_6244), .Y (n_5721)); + INVX1 g36882(.A (n_5719), .Y (n_5720)); + INVX1 g36890(.A (n_6142), .Y (n_5717)); + INVX1 g36894(.A (n_6239), .Y (n_5716)); + INVX1 g36899(.A (n_6264), .Y (n_5715)); + INVX2 g36903(.A (n_5713), .Y (n_5714)); + INVX1 g36910(.A (n_6241), .Y (n_5711)); + INVX1 g36915(.A (n_5709), .Y (n_5710)); + INVX1 g36924(.A (n_5707), .Y (n_5708)); + INVX1 g36955(.A (n_6161), .Y (n_5705)); + NAND4X1 g36967(.A (n_11670), .B (n_11671), .C (n_1786), .D (n_4250), + .Y (n_6805)); + NAND4X1 g36980(.A (n_3091), .B (n_2925), .C (n_4246), .D (n_1861), .Y + (n_6779)); + NAND4X1 g36984(.A (n_11697), .B (n_11698), .C (n_4164), .D (n_2452), + .Y (n_6786)); + INVX1 g36995(.A (n_12368), .Y (n_5704)); + NAND4X1 g36998(.A (n_12817), .B (n_12818), .C (n_4157), .D (n_2417), + .Y (n_6781)); + INVX1 g36999(.A (n_6224), .Y (n_5703)); + INVX1 g37001(.A (n_6226), .Y (n_5702)); + INVX1 g37008(.A (n_6248), .Y (n_5701)); + INVX1 g37010(.A (n_6167), .Y (n_5700)); + NAND4X1 g37013(.A (n_11654), .B (n_11655), .C (n_1808), .D (n_11476), + .Y (n_6814)); + NAND4X1 g37014(.A (n_1347), .B (n_2999), .C (n_4217), .D (n_3452), .Y + (n_5699)); + INVX1 g37018(.A (n_6174), .Y (n_5698)); + INVX1 g37020(.A (n_6202), .Y (n_5697)); + INVX1 g37022(.A (n_11855), .Y (n_5696)); + INVX2 g37025(.A (n_5694), .Y (n_5693)); + INVX1 g37027(.A (n_6216), .Y (n_5692)); + INVX1 g37033(.A (n_6211), .Y (n_5691)); + INVX1 g37035(.A (n_6233), .Y (n_5690)); + INVX1 g37040(.A (n_6207), .Y (n_5688)); + NAND4X1 g37044(.A (n_4247), .B (n_2200), .C (n_4196), .D (n_1395), .Y + (n_6763)); + INVX1 g37045(.A (n_6204), .Y (n_5687)); + INVX1 g37058(.A (n_6150), .Y (n_5686)); + INVX1 g37062(.A (n_6235), .Y (n_5685)); + INVX1 g37064(.A (n_6163), .Y (n_5684)); + INVX1 g37066(.A (n_6194), .Y (n_5683)); + INVX1 g37070(.A (n_12618), .Y (n_5682)); + INVX1 g37076(.A (n_12116), .Y (n_5680)); + INVX1 g37078(.A (n_6172), .Y (n_5679)); + INVX1 g37080(.A (n_6180), .Y (n_5678)); + INVX1 g37082(.A (n_6144), .Y (n_5677)); + INVX1 g37092(.A (n_6176), .Y (n_5676)); + INVX1 g37096(.A (n_6182), .Y (n_5675)); + NAND4X1 g37101(.A (n_4226), .B (n_2333), .C (n_4123), .D (n_1376), .Y + (n_6769)); + INVX1 g37104(.A (n_11895), .Y (n_5673)); + INVX1 g37106(.A (n_6155), .Y (n_5672)); + INVX1 g37111(.A (n_12481), .Y (n_5671)); + INVX1 g37113(.A (n_6250), .Y (n_5670)); + INVX1 g37115(.A (n_6159), .Y (n_5669)); + INVX1 g37121(.A (n_6184), .Y (n_5668)); + NAND4X1 g37127(.A (n_11514), .B (n_3142), .C (n_11515), .D (n_2414), + .Y (n_6783)); + INVX1 g37130(.A (n_6260), .Y (n_5667)); + OAI21X1 g37377(.A0 (\u11_mem[0]_173 ), .A1 (n_6359), .B0 (n_5239), .Y + (n_5666)); + OAI21X1 g37378(.A0 (\u10_mem[0]_169 ), .A1 (n_6341), .B0 (n_5240), .Y + (n_5665)); + OAI21X1 g37390(.A0 (\u11_mem[0]_170 ), .A1 (n_6359), .B0 (n_5242), .Y + (n_5664)); + OAI21X1 g37391(.A0 (\u10_mem[0]_171 ), .A1 (n_6341), .B0 (n_5235), .Y + (n_5662)); + OAI21X1 g37392(.A0 (\u11_mem[0]_176 ), .A1 (n_6359), .B0 (n_5236), .Y + (n_5660)); + OAI21X1 g37393(.A0 (\u11_mem[0]_180 ), .A1 (n_6359), .B0 (n_5244), .Y + (n_5659)); + OAI21X1 g37394(.A0 (\u11_mem[0]_178 ), .A1 (n_5656), .B0 (n_5233), .Y + (n_5658)); + OAI21X1 g37395(.A0 (\u11_mem[0]_169 ), .A1 (n_5656), .B0 (n_5245), .Y + (n_5657)); + OAI21X1 g37396(.A0 (\u11_mem[0]_171 ), .A1 (n_6359), .B0 (n_5246), .Y + (n_5655)); + OAI21X1 g37397(.A0 (\u11_mem[0]_172 ), .A1 (n_6359), .B0 (n_5241), .Y + (n_5653)); + OAI21X1 g37398(.A0 (\u11_mem[0]_174 ), .A1 (n_6359), .B0 (n_5238), .Y + (n_5651)); + OAI21X1 g37400(.A0 (\u11_mem[0]_175 ), .A1 (n_6359), .B0 (n_5237), .Y + (n_5650)); + OAI21X1 g37401(.A0 (\u10_mem[0]_172 ), .A1 (n_6341), .B0 (n_5232), .Y + (n_5649)); + OAI21X1 g37402(.A0 (\u11_mem[0]_179 ), .A1 (n_6359), .B0 (n_5243), .Y + (n_5648)); + OAI21X1 g37403(.A0 (\u10_mem[0]_173 ), .A1 (n_5645), .B0 (n_5231), .Y + (n_5647)); + OAI21X1 g37404(.A0 (\u10_mem[0]_174 ), .A1 (n_5645), .B0 (n_5230), .Y + (n_5646)); + OAI21X1 g37408(.A0 (\u11_mem[0]_177 ), .A1 (n_6359), .B0 (n_5234), .Y + (n_5644)); + OAI21X1 g37409(.A0 (\u10_mem[0]_179 ), .A1 (n_6341), .B0 (n_5227), .Y + (n_5643)); + OAI21X1 g37410(.A0 (\u10_mem[0]_180 ), .A1 (n_6341), .B0 (n_5228), .Y + (n_5641)); + OAI21X1 g37411(.A0 (\u10_mem[0]_178 ), .A1 (n_6341), .B0 (n_5229), .Y + (n_5639)); + XOR2X1 g35717(.A (n_5442), .B (n_4072), .Y (n_5638)); + XOR2X1 g35725(.A (n_1443), .B (n_5636), .Y (n_5637)); + DFFX1 u12_i4_re_reg(.CK (clk_i), .D (n_4838), .Q (), .QN (i4_re)); + DFFX1 u2_ld_reg(.CK (bit_clk_pad_i), .D (n_4833), .Q (), .QN + (n_6734)); + XOR2X1 g34903(.A (n_1212), .B (n_4103), .Y (n_5635)); + AOI21X1 g34906(.A0 (n_4102), .A1 (n_2513), .B0 (n_2606), .Y (n_5634)); + MX2X1 g34907(.A (n_4101), .B (\u2_res_cnt[3] ), .S0 (n_5632), .Y + (n_5633)); + AOI22X1 g34917(.A0 (n_5630), .A1 (\u2_to_cnt[3] ), .B0 (n_5629), .B1 + (n_4100), .Y (n_5631)); + AND2X1 g35270(.A (n_4846), .B (u2_sync_resume), .Y (n_5628)); + AND2X1 g35452(.A (n_4843), .B (u2_sync_resume), .Y (n_5627)); + MX2X1 g35493(.A (\u26_cnt[1] ), .B (n_794), .S0 (n_5624), .Y + (n_5626)); + MX2X1 g35494(.A (\u26_cnt[2] ), .B (n_1821), .S0 (n_5624), .Y + (n_5625)); + XOR2X1 g35495(.A (n_5622), .B (n_4093), .Y (n_5623)); + XOR2X1 g35496(.A (n_5620), .B (n_4092), .Y (n_5621)); + XOR2X1 g35501(.A (n_5618), .B (n_4091), .Y (n_5619)); + XOR2X1 g35502(.A (n_5616), .B (n_4090), .Y (n_5617)); + XOR2X1 g35504(.A (\u26_cnt[0] ), .B (n_5624), .Y (n_5615)); + AOI22X1 g35506(.A0 (n_5630), .A1 (n_4088), .B0 (n_5629), .B1 + (n_4089), .Y (n_5614)); + DFFSRX1 u9_full_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D (n_4852), + .Q (i3_full), .QN ()); + DFFSRX1 u12_i6_re_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_4828), .Q (), .QN (i6_re)); + DFFX1 \u2_out_le_reg[1] (.CK (bit_clk_pad_i), .D (n_4831), .Q (), .QN + (out_le_180)); + DFFSRX1 u12_i3_re_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_4839), .Q (), .QN (i3_re)); + NOR2X1 g35830(.A (n_4830), .B (n_2622), .Y (n_5613)); + NOR2X1 g35836(.A (n_4835), .B (n_2619), .Y (n_5612)); + DFFX1 \u2_in_valid_reg[1] (.CK (bit_clk_pad_i), .D (n_4840), .Q + (in_valid_8), .QN ()); + DFFX1 \u10_dout_reg[11] (.CK (clk_i), .D (n_4823), .Q (i4_dout_605), + .QN ()); + DFFX1 \u10_dout_reg[0] (.CK (clk_i), .D (n_4824), .Q (i4_dout), .QN + ()); + DFFX1 \u10_dout_reg[10] (.CK (clk_i), .D (n_4807), .Q (i4_dout_604), + .QN ()); + DFFX1 \u10_dout_reg[12] (.CK (clk_i), .D (n_4822), .Q (i4_dout_606), + .QN ()); + DFFX1 \u10_dout_reg[13] (.CK (clk_i), .D (n_4821), .Q (i4_dout_607), + .QN ()); + DFFX1 \u10_dout_reg[25] (.CK (clk_i), .D (n_4818), .Q (i4_dout_619), + .QN ()); + DFFX1 \u10_dout_reg[27] (.CK (clk_i), .D (n_4817), .Q (i4_dout_621), + .QN ()); + DFFX1 \u10_dout_reg[28] (.CK (clk_i), .D (n_4816), .Q (i4_dout_622), + .QN ()); + DFFX1 \u10_dout_reg[29] (.CK (clk_i), .D (n_4815), .Q (i4_dout_623), + .QN ()); + DFFX1 \u10_dout_reg[2] (.CK (clk_i), .D (n_4806), .Q (i4_dout_596), + .QN ()); + DFFX1 \u10_dout_reg[30] (.CK (clk_i), .D (n_4814), .Q (i4_dout_624), + .QN ()); + DFFX1 \u10_dout_reg[3] (.CK (clk_i), .D (n_4813), .Q (i4_dout_597), + .QN ()); + DFFX1 \u10_dout_reg[4] (.CK (clk_i), .D (n_4812), .Q (i4_dout_598), + .QN ()); + DFFX1 \u10_dout_reg[6] (.CK (clk_i), .D (n_4811), .Q (i4_dout_600), + .QN ()); + DFFX1 \u10_dout_reg[7] (.CK (clk_i), .D (n_4810), .Q (i4_dout_601), + .QN ()); + DFFX1 \u10_dout_reg[8] (.CK (clk_i), .D (n_4809), .Q (i4_dout_602), + .QN ()); + DFFX1 \u10_dout_reg[9] (.CK (clk_i), .D (n_4808), .Q (i4_dout_603), + .QN ()); + NAND2X1 g36445(.A (n_3940), .B (n_5466), .Y (n_7010)); + AOI21X1 g36449(.A0 (n_3965), .A1 (n_3995), .B0 (n_4079), .Y (n_5611)); + INVX8 g36469(.A (n_11119), .Y (n_6752)); + NOR2X1 g36503(.A (n_844), .B (i3_status), .Y (n_5597)); + NOR2X1 g36507(.A (n_829), .B (i4_status), .Y (n_5596)); + NOR2X1 g36538(.A (i3_status), .B (n_11563), .Y (n_5595)); + NOR2X1 g36540(.A (i4_status), .B (n_11597), .Y (n_5594)); + INVX1 g36613(.A (n_5430), .Y (n_5593)); + AOI21X1 g36628(.A0 (n_5591), .A1 (ic2_cfg_1044), .B0 (n_4681), .Y + (n_5592)); + AND2X1 g36631(.A (n_3968), .B (n_4707), .Y (n_5590)); + AOI21X1 g36636(.A0 (n_5591), .A1 (n_5588), .B0 (n_4725), .Y (n_5589)); + AOI21X1 g36637(.A0 (n_5591), .A1 (ic2_cfg_1049), .B0 (n_4723), .Y + (n_5587)); + AOI21X1 g36638(.A0 (n_5591), .A1 (ic2_cfg_1050), .B0 (n_4720), .Y + (n_5586)); + AND2X1 g36642(.A (n_3973), .B (n_4733), .Y (n_5585)); + AND2X1 g36669(.A (n_3967), .B (n_4685), .Y (n_5584)); + AOI21X1 g36714(.A0 (n_5582), .A1 (n_6649), .B0 (n_4803), .Y (n_5583)); + AOI21X1 g36717(.A0 (n_5580), .A1 (n_6649), .B0 (n_4804), .Y (n_5581)); + AOI21X1 g36727(.A0 (n_5577), .A1 (n_6594), .B0 (n_4820), .Y (n_5578)); + AOI21X1 g36728(.A0 (n_5575), .A1 (n_6594), .B0 (n_4819), .Y (n_5576)); + NAND4X1 g36817(.A (n_12829), .B (n_12830), .C (n_2849), .D (n_3534), + .Y (n_6252)); + INVX1 g36818(.A (n_5798), .Y (n_5572)); + NAND4X1 g36822(.A (n_11662), .B (n_11663), .C (n_2644), .D (n_3533), + .Y (n_6246)); + INVX1 g36823(.A (n_5859), .Y (n_5571)); + NAND4X1 g36827(.A (n_11656), .B (n_11657), .C (n_3248), .D (n_3547), + .Y (n_6266)); + NOR2X1 g36828(.A (n_5736), .B (n_5371), .Y (n_5570)); + NOR2X1 g36829(.A (n_5733), .B (n_5371), .Y (n_5569)); + NAND4X1 g36838(.A (n_4113), .B (n_2489), .C (n_3112), .D (n_1524), .Y + (n_6209)); + NAND4X1 g36854(.A (n_11666), .B (n_11667), .C (n_3376), .D (n_2634), + .Y (n_6254)); + NAND4X1 g36866(.A (n_12004), .B (n_12005), .C (n_3336), .D (n_2450), + .Y (n_6157)); + NAND4X1 g36869(.A (n_11646), .B (n_11647), .C (n_3166), .D (n_3532), + .Y (n_6237)); + NAND4X1 g36873(.A (n_12038), .B (n_11503), .C (n_12039), .D (n_2453), + .Y (n_6244)); + INVX1 g36874(.A (n_5895), .Y (n_5567)); + INVX1 g36880(.A (n_5867), .Y (n_5566)); + NAND4X1 g36884(.A (n_12807), .B (n_12808), .C (n_3268), .D (n_1327), + .Y (n_5719)); + INVX1 g36885(.A (n_5857), .Y (n_5565)); + INVX1 g36887(.A (n_5886), .Y (n_5564)); + NAND4X1 g36891(.A (n_2322), .B (n_3258), .C (n_3256), .D (n_1548), .Y + (n_6142)); + NAND4X1 g36895(.A (n_2337), .B (n_3254), .C (n_3194), .D (n_1326), .Y + (n_6239)); + INVX1 g36896(.A (n_5884), .Y (n_5563)); + NAND4X1 g36900(.A (n_4118), .B (n_2321), .C (n_3029), .D (n_1362), .Y + (n_6264)); + NAND4X1 g36905(.A (n_12805), .B (n_12806), .C (n_3229), .D (n_1541), + .Y (n_5713)); + INVX2 g36906(.A (n_5561), .Y (n_5562)); + NAND4X1 g36911(.A (n_11966), .B (n_3218), .C (n_11967), .D (n_2406), + .Y (n_6241)); + NAND4X1 g36913(.A (n_3542), .B (n_3212), .C (n_2857), .D (n_2231), .Y + (n_5559)); + NAND4X1 g36916(.A (n_2243), .B (n_3206), .C (n_3205), .D (n_2439), .Y + (n_5709)); + INVX1 g36917(.A (n_5863), .Y (n_5558)); + NAND4X1 g36926(.A (n_12809), .B (n_12810), .C (n_2560), .D (n_1337), + .Y (n_5707)); + NAND4X1 g36928(.A (n_3526), .B (n_3186), .C (n_3288), .D (n_1791), .Y + (n_5557)); + NAND4X1 g36956(.A (n_2927), .B (n_2924), .C (n_3143), .D (n_2402), .Y + (n_6161)); + INVX1 g36964(.A (n_5844), .Y (n_5556)); + INVX1 g36968(.A (n_5835), .Y (n_5555)); + INVX1 g36971(.A (n_5855), .Y (n_5554)); + INVX1 g36975(.A (n_5833), .Y (n_5553)); + NAND4X1 g36978(.A (n_3161), .B (n_2247), .C (n_3514), .D (n_1521), .Y + (n_6147)); + INVX1 g36981(.A (n_5853), .Y (n_5552)); + INVX1 g36987(.A (n_5851), .Y (n_5551)); + INVX1 g36989(.A (n_12626), .Y (n_5550)); + INVX1 g36992(.A (n_5847), .Y (n_5549)); + NAND4X1 g37000(.A (n_12819), .B (n_1415), .C (n_12820), .D (n_2416), + .Y (n_6224)); + NAND4X1 g37002(.A (n_12821), .B (n_2855), .C (n_12822), .D (n_2376), + .Y (n_6226)); + INVX1 g37003(.A (n_5841), .Y (n_5548)); + INVX1 g37005(.A (n_5837), .Y (n_5547)); + NAND4X1 g37009(.A (n_11660), .B (n_11661), .C (n_2355), .D (n_3529), + .Y (n_6248)); + NAND4X1 g37011(.A (n_3014), .B (n_3287), .C (n_2878), .D (n_1532), .Y + (n_6167)); + INVX1 g37016(.A (n_5823), .Y (n_5546)); + NAND4X1 g37019(.A (n_3181), .B (n_2859), .C (n_2996), .D (n_1348), .Y + (n_6174)); + NAND4X1 g37021(.A (n_4199), .B (n_3378), .C (n_2971), .D (n_1354), .Y + (n_6202)); + NAND4X1 g37026(.A (n_4190), .B (n_3171), .C (n_3848), .D (n_1529), .Y + (n_5694)); + NAND4X1 g37028(.A (n_4131), .B (n_2281), .C (n_3188), .D (n_1545), .Y + (n_6216)); + INVX1 g37030(.A (n_5544), .Y (n_5545)); + NAND4X1 g37034(.A (n_4127), .B (n_2294), .C (n_3120), .D (n_1530), .Y + (n_6211)); + NAND4X1 g37036(.A (n_4173), .B (n_2959), .C (n_3093), .D (n_1537), .Y + (n_6233)); + NAND4X1 g37037(.A (n_3489), .B (n_3502), .C (n_2898), .D (n_2405), .Y + (n_6186)); + NAND4X1 g37041(.A (n_4125), .B (n_2331), .C (n_2956), .D (n_1533), .Y + (n_6207)); + NAND4X1 g37046(.A (n_4210), .B (n_1499), .C (n_3277), .D (n_1275), .Y + (n_6204)); + NAND4X1 g37047(.A (n_4204), .B (n_2289), .C (n_2945), .D (n_1531), .Y + (n_6228)); + INVX1 g37049(.A (n_5541), .Y (n_5542)); + NAND4X1 g37054(.A (n_1516), .B (n_3523), .C (n_3483), .D (n_3553), .Y + (n_5539)); + NAND4X1 g37055(.A (n_3540), .B (n_3210), .C (n_3043), .D (n_1624), .Y + (n_5538)); + NAND4X1 g37059(.A (n_12831), .B (n_12832), .C (n_2893), .D (n_1514), + .Y (n_6150)); + NAND4X1 g37063(.A (n_11719), .B (n_11720), .C (n_3208), .D (n_1513), + .Y (n_6235)); + NAND4X1 g37065(.A (n_3278), .B (n_3000), .C (n_3289), .D (n_1323), .Y + (n_6163)); + NAND4X1 g37067(.A (n_11721), .B (n_11722), .C (n_3341), .D (n_2397), + .Y (n_6194)); + INVX1 g37068(.A (n_5809), .Y (n_5537)); + NAND4X1 g37079(.A (n_11729), .B (n_11730), .C (n_2872), .D (n_1518), + .Y (n_6172)); + NAND4X1 g37081(.A (n_12827), .B (n_12828), .C (n_2246), .D (n_3539), + .Y (n_6180)); + NAND4X1 g37083(.A (n_3375), .B (n_3199), .C (n_3119), .D (n_1508), .Y + (n_6144)); + INVX1 g37084(.A (n_5803), .Y (n_5536)); + NAND4X1 g37086(.A (n_2445), .B (n_3398), .C (n_3404), .D (n_2244), .Y + (n_5535)); + INVX1 g37087(.A (n_5898), .Y (n_5534)); + INVX1 g37089(.A (n_5813), .Y (n_5533)); + NAND4X1 g37091(.A (n_3469), .B (n_2894), .C (n_3227), .D (n_2392), .Y + (n_6165)); + NAND4X1 g37093(.A (n_3183), .B (n_1487), .C (n_3126), .D (n_1512), .Y + (n_6176)); + INVX1 g37094(.A (n_5811), .Y (n_5532)); + NAND4X1 g37097(.A (n_11453), .B (n_11454), .C (n_3374), .D (n_2391), + .Y (n_6182)); + INVX1 g37102(.A (n_5815), .Y (n_5531)); + NAND4X1 g37107(.A (n_12036), .B (n_1493), .C (n_12037), .D (n_2399), + .Y (n_6155)); + INVX1 g37108(.A (n_5807), .Y (n_5530)); + NAND4X1 g37110(.A (n_2352), .B (n_3890), .C (n_2850), .D (n_1883), .Y + (n_6153)); + NAND4X1 g37114(.A (n_11741), .B (n_11499), .C (n_11742), .D (n_2435), + .Y (n_6250)); + NAND4X1 g37116(.A (n_12843), .B (n_11501), .C (n_12844), .D (n_2384), + .Y (n_6159)); + INVX1 g37117(.A (n_5800), .Y (n_5529)); + INVX1 g37119(.A (n_5893), .Y (n_5528)); + NAND4X1 g37122(.A (n_3135), .B (n_2917), .C (n_3405), .D (n_1378), .Y + (n_6184)); + NAND4X1 g37131(.A (n_11449), .B (n_11450), .C (n_2846), .D (n_2370), + .Y (n_6260)); + NAND2X1 g37137(.A (n_4854), .B (n_1411), .Y (n_7049)); + NAND2X1 g37140(.A (n_4621), .B (n_3351), .Y (n_6920)); + NAND2X1 g37141(.A (n_4619), .B (n_3373), .Y (n_6916)); + NAND2X1 g37143(.A (n_4625), .B (n_2259), .Y (n_6952)); + NAND2X1 g37144(.A (n_4626), .B (n_2354), .Y (n_6883)); + NAND2X1 g37150(.A (n_4613), .B (n_2255), .Y (n_6906)); + NAND2X1 g37151(.A (n_4618), .B (n_3195), .Y (n_6891)); + NAND2X1 g37155(.A (n_4615), .B (n_3347), .Y (n_6899)); + NAND2X1 g37160(.A (n_4614), .B (n_3515), .Y (n_6927)); + NAND2X1 g37162(.A (n_4584), .B (n_2940), .Y (n_6913)); + NAND2X1 g37193(.A (n_4605), .B (n_3291), .Y (n_6925)); + NAND2X1 g37194(.A (n_4617), .B (n_3416), .Y (n_6896)); + AOI21X1 g37209(.A0 (n_5526), .A1 (n_6649), .B0 (n_4675), .Y (n_5527)); + AOI21X1 g37210(.A0 (n_5524), .A1 (n_6649), .B0 (n_4636), .Y (n_5525)); + AOI21X1 g37216(.A0 (n_5522), .A1 (n_6649), .B0 (n_4635), .Y (n_5523)); + AOI21X1 g37242(.A0 (n_5520), .A1 (n_6594), .B0 (n_4666), .Y (n_5521)); + AOI21X1 g37245(.A0 (n_5518), .A1 (n_6594), .B0 (n_4664), .Y (n_5519)); + AOI21X1 g37246(.A0 (n_5516), .A1 (n_6594), .B0 (n_4663), .Y (n_5517)); + AOI21X1 g37247(.A0 (n_5514), .A1 (n_6594), .B0 (n_4661), .Y (n_5515)); + AOI21X1 g37248(.A0 (n_5512), .A1 (n_6594), .B0 (n_4660), .Y (n_5513)); + AOI21X1 g37253(.A0 (n_5510), .A1 (n_6594), .B0 (n_4658), .Y (n_5511)); + AOI21X1 g37254(.A0 (n_5508), .A1 (n_6649), .B0 (n_4643), .Y (n_5509)); + AOI21X1 g37255(.A0 (n_5506), .A1 (n_6594), .B0 (n_4656), .Y (n_5507)); + AOI21X1 g37256(.A0 (n_5504), .A1 (n_6594), .B0 (n_4655), .Y (n_5505)); + AOI21X1 g37258(.A0 (n_5502), .A1 (n_6649), .B0 (n_4640), .Y (n_5503)); + AOI21X1 g37259(.A0 (n_5500), .A1 (n_6649), .B0 (n_4652), .Y (n_5501)); + AOI21X1 g37261(.A0 (n_5498), .A1 (n_6649), .B0 (n_4650), .Y (n_5499)); + AOI21X1 g37262(.A0 (n_5496), .A1 (n_6649), .B0 (n_4637), .Y (n_5497)); + AOI21X1 g37264(.A0 (n_5494), .A1 (n_6649), .B0 (n_4638), .Y (n_5495)); + AOI21X1 g37265(.A0 (n_5492), .A1 (n_6649), .B0 (n_4649), .Y (n_5493)); + AOI21X1 g37266(.A0 (n_5490), .A1 (n_6649), .B0 (n_4651), .Y (n_5491)); + AOI21X1 g37275(.A0 (n_5488), .A1 (n_6649), .B0 (n_4654), .Y (n_5489)); + OAI21X1 g37379(.A0 (\u9_mem[0]_180 ), .A1 (n_6856), .B0 (n_4647), .Y + (n_5487)); + OAI21X1 g37380(.A0 (\u9_mem[0]_169 ), .A1 (n_6856), .B0 (n_4646), .Y + (n_5486)); + OAI21X1 g37381(.A0 (\u9_mem[0]_170 ), .A1 (n_6856), .B0 (n_4673), .Y + (n_5484)); + OAI21X1 g37382(.A0 (\u9_mem[0]_172 ), .A1 (n_6856), .B0 (n_4672), .Y + (n_5483)); + OAI21X1 g37383(.A0 (\u9_mem[0]_173 ), .A1 (n_5480), .B0 (n_4677), .Y + (n_5482)); + OAI21X1 g37384(.A0 (\u9_mem[0]_174 ), .A1 (n_5480), .B0 (n_4659), .Y + (n_5481)); + OAI21X1 g37385(.A0 (\u9_mem[0]_175 ), .A1 (n_6856), .B0 (n_4671), .Y + (n_5479)); + OAI21X1 g37386(.A0 (\u9_mem[0]_176 ), .A1 (n_6856), .B0 (n_4667), .Y + (n_5477)); + OAI21X1 g37387(.A0 (\u9_mem[0]_177 ), .A1 (n_6856), .B0 (n_4669), .Y + (n_5475)); + OAI21X1 g37388(.A0 (\u9_mem[0]_178 ), .A1 (n_6856), .B0 (n_4668), .Y + (n_5474)); + OAI21X1 g37389(.A0 (\u9_mem[0]_179 ), .A1 (n_6856), .B0 (n_4670), .Y + (n_5473)); + OAI21X1 g37399(.A0 (\u10_mem[0]_170 ), .A1 (n_6341), .B0 (n_4642), .Y + (n_5472)); + OAI21X1 g37405(.A0 (\u10_mem[0]_175 ), .A1 (n_6341), .B0 (n_4641), .Y + (n_5471)); + OAI21X1 g37406(.A0 (\u10_mem[0]_176 ), .A1 (n_6341), .B0 (n_4648), .Y + (n_5470)); + OAI21X1 g37407(.A0 (\u10_mem[0]_177 ), .A1 (n_6341), .B0 (n_4653), .Y + (n_5469)); + OAI21X1 g37412(.A0 (\u9_mem[0]_171 ), .A1 (n_6856), .B0 (n_4639), .Y + (n_5468)); + OAI21X1 g37530(.A0 (n_1894), .A1 (\u4_rp[3] ), .B0 (n_5466), .Y + (n_5467)); + NAND2X1 g37916(.A (n_4200), .B (n_3225), .Y (n_5463)); + NAND2X1 g37920(.A (n_1547), .B (n_4126), .Y (n_5461)); + NAND2X1 g37922(.A (n_4214), .B (n_3389), .Y (n_5460)); + NAND2X1 g37924(.A (n_1535), .B (n_4142), .Y (n_5459)); + NAND2X1 g37925(.A (n_4223), .B (n_2952), .Y (n_5458)); + NAND2X1 g37927(.A (n_4124), .B (n_2479), .Y (n_5457)); + NAND2X1 g37928(.A (n_4203), .B (n_3253), .Y (n_5456)); + NAND2X1 g37930(.A (n_1522), .B (n_4116), .Y (n_5455)); + NAND2X1 g37931(.A (n_4177), .B (n_3516), .Y (n_5454)); + NAND2X1 g37936(.A (n_4222), .B (n_3044), .Y (n_5453)); + NAND2X1 g37943(.A (n_1525), .B (n_4128), .Y (n_5452)); + NAND2X1 g37980(.A (n_1386), .B (n_4148), .Y (n_5451)); + OAI21X1 g35680(.A0 (n_5632), .A1 (\u2_res_cnt[0] ), .B0 (n_4094), .Y + (n_5450)); + XOR2X1 g35718(.A (n_4851), .B (n_2611), .Y (n_5449)); + DFFSRX1 u10_full_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D + (n_4105), .Q (i4_full), .QN ()); + DFFSRX1 \u2_out_le_reg[2] (.RN (1'b1), .SN (1'b1), .CK + (bit_clk_pad_i), .D (n_4077), .Q (), .QN (out_le_181)); + XOR2X1 g35381(.A (\u2_cnt[4] ), .B (n_2632), .Y (n_5448)); + AOI21X1 g35436(.A0 (n_1560), .A1 (n_2302), .B0 (n_3941), .Y (n_5447)); + AOI22X1 g35505(.A0 (n_5630), .A1 (n_1819), .B0 (n_5629), .B1 + (n_1820), .Y (n_5445)); + DFFSRX1 \u2_out_le_reg[4] (.RN (1'b1), .SN (1'b1), .CK + (bit_clk_pad_i), .D (n_4096), .Q (), .QN (out_le_183)); + DFFSRX1 \u2_out_le_reg[5] (.RN (1'b1), .SN (1'b1), .CK + (bit_clk_pad_i), .D (n_4095), .Q (), .QN (out_le_184)); + DFFSRX1 \u2_out_le_reg[3] (.RN (1'b1), .SN (1'b1), .CK + (bit_clk_pad_i), .D (n_4107), .Q (), .QN (out_le_182)); + NAND3X1 g35834(.A (n_4084), .B (n_731), .C (n_577), .Y (n_5444)); + NOR2X1 g35854(.A (n_4087), .B (n_5442), .Y (n_5443)); + NAND2X1 g35843(.A (n_3996), .B (n_4832), .Y (n_5441)); + DFFX1 \u2_out_le_reg[0] (.CK (bit_clk_pad_i), .D (n_3984), .Q + (out_le), .QN ()); + DFFX1 \u9_dout_reg[11] (.CK (clk_i), .D (n_4065), .Q (i3_dout_574), + .QN ()); + DFFX1 \u9_dout_reg[14] (.CK (clk_i), .D (n_4062), .Q (i3_dout_577), + .QN ()); + DFFX1 \u9_dout_reg[18] (.CK (clk_i), .D (n_4058), .Q (i3_dout_581), + .QN ()); + DFFX1 \u9_dout_reg[19] (.CK (clk_i), .D (n_4057), .Q (i3_dout_582), + .QN ()); + DFFX1 \u9_dout_reg[20] (.CK (clk_i), .D (n_4055), .Q (i3_dout_583), + .QN ()); + DFFX1 \u9_dout_reg[21] (.CK (clk_i), .D (n_4054), .Q (i3_dout_584), + .QN ()); + DFFX1 \u9_dout_reg[22] (.CK (clk_i), .D (n_4053), .Q (i3_dout_585), + .QN ()); + DFFX1 \u9_dout_reg[23] (.CK (clk_i), .D (n_4052), .Q (i3_dout_586), + .QN ()); + DFFX1 \u9_dout_reg[24] (.CK (clk_i), .D (n_4051), .Q (i3_dout_587), + .QN ()); + DFFX1 \u9_dout_reg[25] (.CK (clk_i), .D (n_4039), .Q (i3_dout_588), + .QN ()); + DFFX1 \u9_dout_reg[16] (.CK (clk_i), .D (n_4060), .Q (i3_dout_579), + .QN ()); + DFFX1 \u10_dout_reg[16] (.CK (clk_i), .D (n_4342), .Q (i4_dout_610), + .QN ()); + DFFX1 \u9_dout_reg[26] (.CK (clk_i), .D (n_4050), .Q (i3_dout_589), + .QN ()); + DFFX1 \u9_dout_reg[27] (.CK (clk_i), .D (n_4049), .Q (i3_dout_590), + .QN ()); + DFFX1 \u9_dout_reg[28] (.CK (clk_i), .D (n_4048), .Q (i3_dout_591), + .QN ()); + DFFX1 \u9_dout_reg[29] (.CK (clk_i), .D (n_4047), .Q (i3_dout_592), + .QN ()); + DFFX1 \u9_dout_reg[2] (.CK (clk_i), .D (n_4046), .Q (i3_dout_565), + .QN ()); + DFFX1 \u9_dout_reg[30] (.CK (clk_i), .D (n_4045), .Q (i3_dout_593), + .QN ()); + DFFX1 \u9_dout_reg[31] (.CK (clk_i), .D (n_4044), .Q (i3_dout_594), + .QN ()); + DFFX1 \u9_dout_reg[3] (.CK (clk_i), .D (n_4043), .Q (i3_dout_566), + .QN ()); + DFFX1 \u1_sr_reg[3] (.CK (bit_clk_pad_i), .D (u1_sr_118), .Q + (u1_sr_119), .QN ()); + DFFX1 \u9_dout_reg[4] (.CK (clk_i), .D (n_4033), .Q (i3_dout_567), + .QN ()); + DFFX1 \u9_dout_reg[5] (.CK (clk_i), .D (n_4042), .Q (i3_dout_568), + .QN ()); + DFFX1 \u9_dout_reg[6] (.CK (clk_i), .D (n_4041), .Q (i3_dout_569), + .QN ()); + DFFX1 \u9_dout_reg[7] (.CK (clk_i), .D (n_4040), .Q (i3_dout_570), + .QN ()); + DFFX1 \u9_dout_reg[8] (.CK (clk_i), .D (n_3999), .Q (i3_dout_571), + .QN ()); + DFFX1 \u9_dout_reg[9] (.CK (clk_i), .D (n_3997), .Q (i3_dout_572), + .QN ()); + DFFX1 \u10_dout_reg[24] (.CK (clk_i), .D (n_4037), .Q (i4_dout_618), + .QN ()); + DFFX1 \u10_dout_reg[26] (.CK (clk_i), .D (n_4034), .Q (i4_dout_620), + .QN ()); + DFFX1 \u9_dout_reg[13] (.CK (clk_i), .D (n_4063), .Q (i3_dout_576), + .QN ()); + DFFX1 \u11_dout_reg[0] (.CK (clk_i), .D (n_4032), .Q (i6_dout), .QN + ()); + DFFX1 \u11_dout_reg[10] (.CK (clk_i), .D (n_4031), .Q (i6_dout_635), + .QN ()); + DFFX1 \u11_dout_reg[11] (.CK (clk_i), .D (n_4030), .Q (i6_dout_636), + .QN ()); + DFFX1 \u11_dout_reg[12] (.CK (clk_i), .D (n_4029), .Q (i6_dout_637), + .QN ()); + DFFX1 \u11_dout_reg[13] (.CK (clk_i), .D (n_4028), .Q (i6_dout_638), + .QN ()); + DFFX1 \u10_dout_reg[31] (.CK (clk_i), .D (n_3998), .Q (i4_dout_625), + .QN ()); + DFFX1 \u11_dout_reg[14] (.CK (clk_i), .D (n_4027), .Q (i6_dout_639), + .QN ()); + DFFX1 \u11_dout_reg[15] (.CK (clk_i), .D (n_4026), .Q (i6_dout_640), + .QN ()); + DFFX1 \u11_dout_reg[16] (.CK (clk_i), .D (n_4025), .Q (i6_dout_641), + .QN ()); + DFFX1 \u11_dout_reg[17] (.CK (clk_i), .D (n_4024), .Q (i6_dout_642), + .QN ()); + DFFX1 \u11_dout_reg[18] (.CK (clk_i), .D (n_4023), .Q (i6_dout_643), + .QN ()); + DFFX1 \u11_dout_reg[19] (.CK (clk_i), .D (n_4021), .Q (i6_dout_644), + .QN ()); + DFFX1 \u10_dout_reg[5] (.CK (clk_i), .D (n_4022), .Q (i4_dout_599), + .QN ()); + DFFX1 \u11_dout_reg[1] (.CK (clk_i), .D (n_4020), .Q (i6_dout_626), + .QN ()); + DFFX1 \u11_dout_reg[20] (.CK (clk_i), .D (n_4019), .Q (i6_dout_645), + .QN ()); + DFFX1 \u11_dout_reg[21] (.CK (clk_i), .D (n_4018), .Q (i6_dout_646), + .QN ()); + DFFX1 \u11_dout_reg[22] (.CK (clk_i), .D (n_4017), .Q (i6_dout_647), + .QN ()); + DFFX1 \u11_dout_reg[23] (.CK (clk_i), .D (n_4016), .Q (i6_dout_648), + .QN ()); + DFFX1 \u11_dout_reg[24] (.CK (clk_i), .D (n_4015), .Q (i6_dout_649), + .QN ()); + DFFX1 \u11_dout_reg[25] (.CK (clk_i), .D (n_4014), .Q (i6_dout_650), + .QN ()); + DFFX1 \u11_dout_reg[26] (.CK (clk_i), .D (n_4013), .Q (i6_dout_651), + .QN ()); + DFFX1 \u11_dout_reg[27] (.CK (clk_i), .D (n_4012), .Q (i6_dout_652), + .QN ()); + DFFX1 \u11_dout_reg[28] (.CK (clk_i), .D (n_4011), .Q (i6_dout_653), + .QN ()); + DFFX1 \u11_dout_reg[29] (.CK (clk_i), .D (n_4010), .Q (i6_dout_654), + .QN ()); + DFFX1 \u11_dout_reg[2] (.CK (clk_i), .D (n_4009), .Q (i6_dout_627), + .QN ()); + DFFX1 \u11_dout_reg[30] (.CK (clk_i), .D (n_4008), .Q (i6_dout_655), + .QN ()); + DFFX1 \u11_dout_reg[31] (.CK (clk_i), .D (n_4007), .Q (i6_dout_656), + .QN ()); + DFFX1 \u11_dout_reg[3] (.CK (clk_i), .D (n_4006), .Q (i6_dout_628), + .QN ()); + DFFX1 \u11_dout_reg[4] (.CK (clk_i), .D (n_4005), .Q (i6_dout_629), + .QN ()); + DFFX1 \u11_dout_reg[5] (.CK (clk_i), .D (n_4004), .Q (i6_dout_630), + .QN ()); + DFFX1 \u11_dout_reg[6] (.CK (clk_i), .D (n_4038), .Q (i6_dout_631), + .QN ()); + DFFX1 \u11_dout_reg[7] (.CK (clk_i), .D (n_4003), .Q (i6_dout_632), + .QN ()); + DFFX1 \u11_dout_reg[8] (.CK (clk_i), .D (n_4002), .Q (i6_dout_633), + .QN ()); + DFFX1 \u11_dout_reg[9] (.CK (clk_i), .D (n_4001), .Q (i6_dout_634), + .QN ()); + DFFX1 \u9_dout_reg[15] (.CK (clk_i), .D (n_4061), .Q (i3_dout_578), + .QN ()); + DFFX1 \u9_dout_reg[17] (.CK (clk_i), .D (n_4059), .Q (i3_dout_580), + .QN ()); + DFFX1 \u9_dout_reg[0] (.CK (clk_i), .D (n_4067), .Q (i3_dout), .QN + ()); + DFFX1 \u9_dout_reg[12] (.CK (clk_i), .D (n_4064), .Q (i3_dout_575), + .QN ()); + DFFX1 \u9_dout_reg[10] (.CK (clk_i), .D (n_4066), .Q (i3_dout_573), + .QN ()); + DFFX1 \u9_dout_reg[1] (.CK (clk_i), .D (n_4056), .Q (i3_dout_564), + .QN ()); + INVX2 g36475(.A (n_5440), .Y (n_11119)); + NAND2X1 g36489(.A (n_3939), .B (n_4644), .Y (n_6756)); + NOR2X1 g36509(.A (n_807), .B (i6_status), .Y (n_5439)); + NOR2X1 g36525(.A (o6_status), .B (n_2485), .Y (n_5438)); + NOR2X1 g36536(.A (o9_status), .B (n_12585), .Y (n_5436)); + NOR2X1 g36542(.A (i6_status), .B (n_11762), .Y (n_5434)); + AND2X1 g36560(.A (n_4000), .B (n_1212), .Y (n_5432)); + XOR2X1 g35719(.A (n_2612), .B (n_4104), .Y (n_5431)); + AOI21X1 g36614(.A0 (n_2572), .A1 (\u2_cnt[6] ), .B0 (n_1212), .Y + (n_5430)); + MX2X1 g36713(.A (\u11_mem[0]_167 ), .B (n_5413), .S0 (n_6359), .Y + (n_5428)); + MX2X1 g36715(.A (\u10_mem[2]_105 ), .B (n_5418), .S0 (n_5424), .Y + (n_5426)); + MX2X1 g36716(.A (\u10_mem[2]_106 ), .B (n_5422), .S0 (n_5424), .Y + (n_5425)); + MX2X1 g36721(.A (\u10_mem[1]_137 ), .B (n_5422), .S0 (n_5407), .Y + (n_5423)); + OAI21X1 g36729(.A0 (n_2302), .A1 (n_5420), .B0 (n_4036), .Y (n_5421)); + MX2X1 g36731(.A (\u10_mem[0]_167 ), .B (n_5418), .S0 (n_6341), .Y + (n_5419)); + MX2X1 g36732(.A (\u11_mem[0]_168 ), .B (n_5410), .S0 (n_6359), .Y + (n_5416)); + MX2X1 g36733(.A (\u10_mem[0]_168 ), .B (n_5422), .S0 (n_6341), .Y + (n_5415)); + MX2X1 g36735(.A (\u11_mem[1]_136 ), .B (n_5413), .S0 (n_5405), .Y + (n_5414)); + MX2X1 g36737(.A (\u11_mem[2]_105 ), .B (n_5413), .S0 (n_5409), .Y + (n_5412)); + MX2X1 g36738(.A (\u11_mem[2]_106 ), .B (n_5410), .S0 (n_5409), .Y + (n_5411)); + MX2X1 g36740(.A (\u10_mem[1]_136 ), .B (n_5418), .S0 (n_5407), .Y + (n_5408)); + MX2X1 g36742(.A (\u11_mem[1]_137 ), .B (n_5410), .S0 (n_5405), .Y + (n_5406)); + AOI22X1 g36749(.A0 (n_5630), .A1 (\u2_to_cnt[1] ), .B0 (n_5629), .B1 + (n_795), .Y (n_5404)); + XOR2X1 g36750(.A (\u2_to_cnt[0] ), .B (n_5630), .Y (n_5403)); + INVX1 g36752(.A (suspended_o), .Y (n_6057)); + NAND4X1 g36819(.A (n_11445), .B (n_11446), .C (n_2363), .D (n_2393), + .Y (n_5798)); + NAND4X1 g36824(.A (n_12799), .B (n_3192), .C (n_12800), .D (n_1338), + .Y (n_5859)); + NAND2X1 g36846(.A (n_1695), .B (n_3929), .Y (n_5393)); + NAND2X1 g36857(.A (n_4078), .B (n_1249), .Y (n_5392)); + NAND2X1 g36859(.A (n_1691), .B (n_3927), .Y (n_5391)); + NAND2X1 g36860(.A (n_3925), .B (n_1248), .Y (n_5390)); + NAND2X1 g36861(.A (n_1687), .B (n_3923), .Y (n_5389)); + NAND2X1 g36863(.A (n_3922), .B (n_1247), .Y (n_5388)); + NAND2X1 g36864(.A (n_3921), .B (n_1245), .Y (n_5387)); + NAND2X1 g36867(.A (n_2559), .B (n_3919), .Y (n_5386)); + NAND2X1 g36870(.A (n_3918), .B (n_1243), .Y (n_5385)); + NAND4X1 g36875(.A (n_11465), .B (n_11466), .C (n_2509), .D (n_1881), + .Y (n_5895)); + NAND4X1 g36881(.A (n_11494), .B (n_3270), .C (n_11495), .D (n_1324), + .Y (n_5867)); + NAND4X1 g36886(.A (n_12034), .B (n_3261), .C (n_12035), .D (n_1544), + .Y (n_5857)); + NAND4X1 g36888(.A (n_12030), .B (n_3260), .C (n_12031), .D (n_1340), + .Y (n_5886)); + NAND4X1 g36897(.A (n_12032), .B (n_3251), .C (n_12033), .D (n_1542), + .Y (n_5884)); + NAND4X1 g36898(.A (n_12853), .B (n_12854), .C (n_12796), .D (n_1325), + .Y (n_5882)); + NAND4X1 g36902(.A (n_12855), .B (n_12856), .C (n_12798), .D (n_1534), + .Y (n_5879)); + NAND4X1 g36908(.A (n_12841), .B (n_12842), .C (n_12041), .D (n_1333), + .Y (n_5561)); + NAND4X1 g36912(.A (n_12857), .B (n_12858), .C (n_11482), .D (n_1336), + .Y (n_5874)); + NAND4X1 g36918(.A (n_11441), .B (n_3202), .C (n_11442), .D (n_2408), + .Y (n_5863)); + NAND4X1 g36920(.A (n_11443), .B (n_1319), .C (n_11444), .D (n_1335), + .Y (n_5869)); + NAND4X1 g36921(.A (n_11439), .B (n_3193), .C (n_11440), .D (n_2438), + .Y (n_5865)); + NOR2X1 g36942(.A (n_7297), .B (n_4676), .Y (n_5384)); + NOR2X1 g35837(.A (n_4082), .B (n_2618), .Y (n_5383)); + NAND2X1 g36958(.A (n_2563), .B (n_3930), .Y (n_5382)); + NAND4X1 g36965(.A (n_11751), .B (n_11752), .C (n_2229), .D (n_2431), + .Y (n_5844)); + NAND4X1 g36969(.A (n_11713), .B (n_11714), .C (n_2482), .D (n_1869), + .Y (n_5835)); + NAND4X1 g36972(.A (n_11717), .B (n_11718), .C (n_2286), .D (n_2428), + .Y (n_5855)); + NAND4X1 g36976(.A (n_11715), .B (n_11716), .C (n_1810), .D (n_2426), + .Y (n_5833)); + NAND4X1 g36982(.A (n_11707), .B (n_11708), .C (n_2282), .D (n_2447), + .Y (n_5853)); + NAND4X1 g36985(.A (n_3078), .B (n_2868), .C (n_2287), .D (n_2433), .Y + (n_5805)); + NAND4X1 g36988(.A (n_11699), .B (n_11700), .C (n_2278), .D (n_2424), + .Y (n_5851)); + NAND4X1 g36993(.A (n_11703), .B (n_11704), .C (n_2264), .D (n_2423), + .Y (n_5847)); + NAND4X1 g36997(.A (n_4158), .B (n_3125), .C (n_2274), .D (n_2407), .Y + (n_5829)); + NAND4X1 g37004(.A (n_11709), .B (n_11710), .C (n_2276), .D (n_2413), + .Y (n_5841)); + NAND4X1 g37006(.A (n_11711), .B (n_11712), .C (n_2272), .D (n_2398), + .Y (n_5837)); + NAND4X1 g37017(.A (n_11668), .B (n_11669), .C (n_2253), .D (n_2386), + .Y (n_5823)); + NAND4X1 g37029(.A (n_2969), .B (n_3124), .C (n_1809), .D (n_1528), .Y + (n_5818)); + NAND4X1 g37032(.A (n_2966), .B (n_3105), .C (n_2493), .D (n_1526), .Y + (n_5544)); + NAND4X1 g37051(.A (n_3106), .B (n_2943), .C (n_2473), .D (n_1506), .Y + (n_5541)); + NAND4X1 g37069(.A (n_11461), .B (n_11462), .C (n_2237), .D (n_2387), + .Y (n_5809)); + DFFSRX1 u12_re2_reg(.RN (1'b1), .SN (1'b1), .CK (clk_i), .D (n_4086), + .Q (u12_re2), .QN ()); + NAND4X1 g37085(.A (n_11467), .B (n_11468), .C (n_2245), .D (n_2395), + .Y (n_5803)); + NAND4X1 g37088(.A (n_11447), .B (n_11448), .C (n_2338), .D (n_2455), + .Y (n_5898)); + NAND4X1 g37090(.A (n_11451), .B (n_11452), .C (n_2353), .D (n_2457), + .Y (n_5813)); + NAND4X1 g37095(.A (n_11459), .B (n_11460), .C (n_2299), .D (n_2373), + .Y (n_5811)); + NAND4X1 g37103(.A (n_11457), .B (n_11458), .C (n_2128), .D (n_1892), + .Y (n_5815)); + NAND4X1 g37109(.A (n_11455), .B (n_11456), .C (n_1867), .D (n_2390), + .Y (n_5807)); + NAND4X1 g37118(.A (n_11463), .B (n_11464), .C (n_1927), .D (n_2382), + .Y (n_5800)); + NAND4X1 g37120(.A (n_3355), .B (n_2861), .C (n_2295), .D (n_2381), .Y + (n_5893)); + NAND2X1 g37132(.A (n_4269), .B (n_1549), .Y (n_6836)); + NAND2X1 g37133(.A (n_4267), .B (n_2488), .Y (n_6839)); + NOR2X1 g37134(.A (n_4268), .B (n_12079), .Y (n_6328)); + NAND2X1 g37136(.A (n_4266), .B (n_12656), .Y (n_6842)); + NAND2X1 g37138(.A (n_4558), .B (n_1901), .Y (n_6576)); + NAND2X1 g37142(.A (n_3932), .B (n_1925), .Y (n_6560)); + NAND2X1 g37145(.A (n_3933), .B (n_3466), .Y (n_6582)); + NAND2X1 g37146(.A (n_3934), .B (n_3081), .Y (n_6637)); + NAND2X1 g37147(.A (n_3937), .B (n_3223), .Y (n_6533)); + NAND2X1 g37148(.A (n_3938), .B (n_3348), .Y (n_6539)); + NAND2X1 g37149(.A (n_2561), .B (n_4220), .Y (n_6618)); + NAND2X1 g37152(.A (n_2633), .B (n_4239), .Y (n_6646)); + NAND2X1 g37153(.A (n_3905), .B (n_2279), .Y (n_6473)); + NAND2X1 g37157(.A (n_3920), .B (n_2280), .Y (n_6602)); + NAND2X1 g37158(.A (n_3913), .B (n_2357), .Y (n_6599)); + NAND2X1 g37159(.A (n_3910), .B (n_2241), .Y (n_6596)); + NAND2X1 g37161(.A (n_3909), .B (n_1795), .Y (n_6592)); + NAND2X1 g37163(.A (n_3908), .B (n_2273), .Y (n_6521)); + NAND2X1 g37164(.A (n_3907), .B (n_2269), .Y (n_6478)); + NAND2X1 g37165(.A (n_3904), .B (n_2345), .Y (n_6586)); + NAND2X1 g37166(.A (n_3903), .B (n_1564), .Y (n_6514)); + NAND2X1 g37167(.A (n_3902), .B (n_2227), .Y (n_6510)); + NAND2X1 g37169(.A (n_3900), .B (n_2288), .Y (n_6465)); + NAND2X1 g37172(.A (n_3898), .B (n_2326), .Y (n_6453)); + NAND2X1 g37174(.A (n_3899), .B (n_2270), .Y (n_6589)); + NAND2X1 g37175(.A (n_3896), .B (n_2472), .Y (n_6497)); + NAND2X1 g37177(.A (n_3895), .B (n_2329), .Y (n_6444)); + NAND2X1 g37178(.A (n_4567), .B (n_2251), .Y (n_6442)); + NAND2X1 g37179(.A (n_4566), .B (n_2296), .Y (n_6544)); + NAND2X1 g37180(.A (n_4565), .B (n_2252), .Y (n_6486)); + NAND2X1 g37181(.A (n_4563), .B (n_2249), .Y (n_6547)); + NAND2X1 g37182(.A (n_4561), .B (n_2248), .Y (n_6483)); + NAND2X1 g37184(.A (n_4559), .B (n_2290), .Y (n_6579)); + NAND2X1 g37185(.A (n_4557), .B (n_2240), .Y (n_6573)); + NAND2X1 g37187(.A (n_3928), .B (n_2305), .Y (n_6570)); + NAND2X1 g37188(.A (n_4550), .B (n_2334), .Y (n_6566)); + NAND2X1 g37190(.A (n_4555), .B (n_1796), .Y (n_6563)); + NAND2X1 g37192(.A (n_4098), .B (n_2238), .Y (n_6459)); + MX2X1 g37208(.A (\u11_mem[1]_149 ), .B (n_5300), .S0 (n_6502), .Y + (n_5381)); + MX2X1 g37211(.A (\u10_mem[2]_107 ), .B (n_5292), .S0 (n_5341), .Y + (n_5380)); + MX2X1 g37213(.A (\u10_mem[2]_109 ), .B (n_5290), .S0 (n_5424), .Y + (n_5379)); + MX2X1 g37214(.A (\u10_mem[2]_111 ), .B (n_5287), .S0 (n_5341), .Y + (n_5378)); + MX2X1 g37215(.A (\u10_mem[2]_112 ), .B (n_5355), .S0 (n_5341), .Y + (n_5377)); + AOI21X1 g37236(.A0 (n_5374), .A1 (n_5371), .B0 (n_4085), .Y (n_5375)); + AOI21X1 g37237(.A0 (n_5372), .A1 (n_5371), .B0 (n_3949), .Y (n_5373)); + AOI21X1 g37238(.A0 (n_5369), .A1 (n_5371), .B0 (n_3963), .Y (n_5370)); + AOI21X1 g37239(.A0 (n_5367), .A1 (n_5371), .B0 (n_3952), .Y (n_5368)); + AOI21X1 g37240(.A0 (n_5365), .A1 (n_5371), .B0 (n_3955), .Y (n_5366)); + AOI21X1 g37243(.A0 (n_5363), .A1 (n_6594), .B0 (n_3959), .Y (n_5364)); + MX2X1 g37244(.A (\u10_mem[1]_148 ), .B (n_5330), .S0 (n_6475), .Y + (n_5362)); + AND2X1 g35833(.A (n_1285), .B (n_5248), .Y (n_5361)); + AOI21X1 g37249(.A0 (n_5359), .A1 (n_6594), .B0 (n_3958), .Y (n_5360)); + AOI21X1 g37250(.A0 (n_5357), .A1 (n_6594), .B0 (n_3957), .Y (n_5358)); + MX2X1 g37251(.A (\u10_mem[1]_143 ), .B (n_5355), .S0 (n_6475), .Y + (n_5356)); + AOI21X1 g37252(.A0 (n_5352), .A1 (n_6594), .B0 (n_3956), .Y (n_5353)); + AOI21X1 g37257(.A0 (n_5350), .A1 (n_5371), .B0 (n_3953), .Y (n_5351)); + MX2X1 g37263(.A (\u10_mem[1]_149 ), .B (n_5339), .S0 (n_6475), .Y + (n_5349)); + AOI21X1 g37270(.A0 (n_5347), .A1 (n_5371), .B0 (n_3961), .Y (n_5348)); + AOI21X1 g37272(.A0 (n_5345), .A1 (n_5371), .B0 (n_3960), .Y (n_5346)); + AOI21X1 g37273(.A0 (n_5343), .A1 (n_5371), .B0 (n_3950), .Y (n_5344)); + MX2X1 g37277(.A (\u10_mem[2]_116 ), .B (n_5284), .S0 (n_5341), .Y + (n_5342)); + MX2X1 g37278(.A (\u10_mem[2]_118 ), .B (n_5339), .S0 (n_5424), .Y + (n_5340)); + MX2X1 g37280(.A (\u11_mem[1]_148 ), .B (n_5296), .S0 (n_5405), .Y + (n_5338)); + MX2X1 g37281(.A (\u11_mem[2]_107 ), .B (n_5335), .S0 (n_5312), .Y + (n_5337)); + MX2X1 g37282(.A (\u11_mem[1]_138 ), .B (n_5335), .S0 (n_5405), .Y + (n_5336)); + AOI21X1 g37283(.A0 (n_5333), .A1 (n_5371), .B0 (n_3948), .Y (n_5334)); + MX2X1 g37284(.A (\u11_mem[1]_140 ), .B (n_5315), .S0 (n_6502), .Y + (n_5332)); + MX2X1 g37285(.A (\u10_mem[2]_117 ), .B (n_5330), .S0 (n_5341), .Y + (n_5331)); + MX2X1 g37286(.A (\u11_mem[1]_141 ), .B (n_5313), .S0 (n_6502), .Y + (n_5329)); + MX2X1 g37287(.A (\u11_mem[1]_142 ), .B (n_5321), .S0 (n_6502), .Y + (n_5327)); + MX2X1 g37288(.A (\u11_mem[1]_144 ), .B (n_5309), .S0 (n_6502), .Y + (n_5326)); + MX2X1 g37289(.A (\u11_mem[1]_147 ), .B (n_5298), .S0 (n_6502), .Y + (n_5325)); + MX2X1 g37290(.A (\u11_mem[1]_139 ), .B (n_5317), .S0 (n_6502), .Y + (n_5323)); + MX2X1 g37291(.A (\u11_mem[2]_111 ), .B (n_5321), .S0 (n_5409), .Y + (n_5322)); + MX2X1 g37292(.A (\u11_mem[1]_146 ), .B (n_5304), .S0 (n_5405), .Y + (n_5320)); + MX2X1 g37293(.A (\u11_mem[1]_145 ), .B (n_5307), .S0 (n_6502), .Y + (n_5319)); + MX2X1 g37294(.A (\u11_mem[2]_108 ), .B (n_5317), .S0 (n_5409), .Y + (n_5318)); + MX2X1 g37295(.A (\u11_mem[2]_109 ), .B (n_5315), .S0 (n_5312), .Y + (n_5316)); + MX2X1 g37296(.A (\u11_mem[2]_110 ), .B (n_5313), .S0 (n_5312), .Y + (n_5314)); + MX2X1 g37297(.A (\u11_mem[2]_112 ), .B (n_5280), .S0 (n_5312), .Y + (n_5311)); + MX2X1 g37298(.A (\u11_mem[2]_113 ), .B (n_5309), .S0 (n_5312), .Y + (n_5310)); + MX2X1 g37299(.A (\u11_mem[2]_114 ), .B (n_5307), .S0 (n_5312), .Y + (n_5308)); + MX2X1 g37300(.A (\u11_mem[2]_115 ), .B (n_5304), .S0 (n_5312), .Y + (n_5305)); + AOI21X1 g37301(.A0 (n_5302), .A1 (n_5371), .B0 (n_3947), .Y (n_5303)); + MX2X1 g37302(.A (\u11_mem[2]_118 ), .B (n_5300), .S0 (n_5409), .Y + (n_5301)); + MX2X1 g37303(.A (\u11_mem[2]_116 ), .B (n_5298), .S0 (n_5312), .Y + (n_5299)); + MX2X1 g37304(.A (\u11_mem[2]_117 ), .B (n_5296), .S0 (n_5409), .Y + (n_5297)); + AOI21X1 g37305(.A0 (n_5294), .A1 (n_5371), .B0 (n_3946), .Y (n_5295)); + MX2X1 g37306(.A (\u10_mem[1]_138 ), .B (n_5292), .S0 (n_6475), .Y + (n_5293)); + MX2X1 g37308(.A (\u10_mem[1]_140 ), .B (n_5290), .S0 (n_6475), .Y + (n_5291)); + MX2X1 g37309(.A (\u10_mem[1]_141 ), .B (n_5282), .S0 (n_5407), .Y + (n_5289)); + MX2X1 g37310(.A (\u10_mem[1]_142 ), .B (n_5287), .S0 (n_6475), .Y + (n_5288)); + MX2X1 g37311(.A (\u10_mem[1]_147 ), .B (n_5284), .S0 (n_5407), .Y + (n_5285)); + MX2X1 g37312(.A (\u10_mem[2]_110 ), .B (n_5282), .S0 (n_5424), .Y + (n_5283)); + MX2X1 g37314(.A (\u11_mem[1]_143 ), .B (n_5280), .S0 (n_5405), .Y + (n_5281)); + AOI22X1 g37316(.A0 (n_5272), .A1 (\u13_intm_r[10] ), .B0 (n_5277), + .B1 (crac_din_701), .Y (n_5279)); + AOI22X1 g37320(.A0 (n_5272), .A1 (\u13_intm_r[0] ), .B0 (n_5277), .B1 + (crac_din), .Y (n_5278)); + AOI22X1 g37323(.A0 (n_5272), .A1 (\u13_intm_r[1] ), .B0 (n_5277), .B1 + (crac_din_692), .Y (n_5276)); + INVX1 g37325(.A (n_4728), .Y (n_5275)); + AOI22X1 g37339(.A0 (n_5272), .A1 (\u13_intm_r[26] ), .B0 (n_6972), + .B1 (oc3_cfg_995), .Y (n_5274)); + AOI22X1 g37340(.A0 (n_5272), .A1 (\u13_intm_r[27] ), .B0 (n_6972), + .B1 (oc3_cfg_996), .Y (n_5273)); + AOI22X1 g37342(.A0 (n_5272), .A1 (\u13_intm_r[2] ), .B0 (n_5277), .B1 + (crac_din_693), .Y (n_5270)); + AOI22X1 g37344(.A0 (n_5277), .A1 (crac_out_876), .B0 (n_6972), .B1 + (oc3_cfg_1000), .Y (n_5268)); + AOI22X1 g37345(.A0 (n_5272), .A1 (\u13_intm_r[3] ), .B0 (n_5277), .B1 + (crac_din_694), .Y (n_5266)); + AOI22X1 g37347(.A0 (n_5272), .A1 (\u13_intm_r[4] ), .B0 (n_5277), .B1 + (crac_din_695), .Y (n_5265)); + AOI22X1 g37350(.A0 (n_5272), .A1 (\u13_intm_r[5] ), .B0 (n_5277), .B1 + (crac_din_696), .Y (n_5263)); + AOI22X1 g37352(.A0 (n_5272), .A1 (\u13_intm_r[6] ), .B0 (n_5277), .B1 + (crac_din_697), .Y (n_5261)); + AOI22X1 g37354(.A0 (n_5272), .A1 (\u13_intm_r[7] ), .B0 (n_5277), .B1 + (crac_din_698), .Y (n_5260)); + AOI22X1 g37356(.A0 (n_5272), .A1 (\u13_intm_r[8] ), .B0 (n_5277), .B1 + (crac_din_699), .Y (n_5258)); + AOI22X1 g37358(.A0 (n_5272), .A1 (\u13_intm_r[9] ), .B0 (n_5277), .B1 + (crac_din_700), .Y (n_5256)); + AOI22X1 g37361(.A0 (n_5272), .A1 (\u13_intm_r[12] ), .B0 (n_5277), + .B1 (crac_din_703), .Y (n_5255)); + AOI22X1 g37364(.A0 (n_5272), .A1 (\u13_intm_r[13] ), .B0 (n_5277), + .B1 (crac_din_704), .Y (n_5254)); + AOI22X1 g37365(.A0 (n_5272), .A1 (\u13_intm_r[15] ), .B0 (n_5277), + .B1 (crac_din_706), .Y (n_5253)); + AOI22X1 g37367(.A0 (n_5272), .A1 (\u13_intm_r[11] ), .B0 (n_5277), + .B1 (crac_din_702), .Y (n_5252)); + AOI22X1 g37376(.A0 (n_5272), .A1 (\u13_intm_r[14] ), .B0 (n_5277), + .B1 (crac_din_705), .Y (n_5251)); + INVX1 g37415(.A (n_4634), .Y (n_5250)); + NAND2X1 g35831(.A (n_1815), .B (n_5248), .Y (n_5249)); + NAND2X1 g37483(.A (n_5656), .B (n_4232), .Y (n_5246)); + NAND2X1 g37514(.A (n_5656), .B (n_4238), .Y (n_5245)); + NAND2X1 g37533(.A (n_5656), .B (n_4161), .Y (n_5244)); + NAND2X1 g37534(.A (n_5656), .B (n_4193), .Y (n_5243)); + NAND2X1 g37554(.A (n_5656), .B (n_4205), .Y (n_5242)); + NAND2X1 g37555(.A (n_5656), .B (n_4237), .Y (n_5241)); + NAND2X1 g37556(.A (n_5645), .B (n_4111), .Y (n_5240)); + NAND2X1 g37557(.A (n_5656), .B (n_4138), .Y (n_5239)); + NAND2X1 g37558(.A (n_5656), .B (n_4202), .Y (n_5238)); + NAND2X1 g37560(.A (n_5656), .B (n_4207), .Y (n_5237)); + NAND2X1 g37561(.A (n_5656), .B (n_4106), .Y (n_5236)); + NAND2X1 g37562(.A (n_5645), .B (n_4178), .Y (n_5235)); + NAND2X1 g37563(.A (n_5656), .B (n_4133), .Y (n_5234)); + NAND2X1 g37564(.A (n_5656), .B (n_4209), .Y (n_5233)); + NAND2X1 g37565(.A (n_5645), .B (n_4231), .Y (n_5232)); + NAND2X1 g37566(.A (n_5645), .B (n_4230), .Y (n_5231)); + NAND2X1 g37567(.A (n_5645), .B (n_4135), .Y (n_5230)); + NAND2X1 g37571(.A (n_5645), .B (n_4153), .Y (n_5229)); + NAND2X1 g37573(.A (n_5645), .B (n_4206), .Y (n_5228)); + NAND2X1 g37581(.A (n_5645), .B (n_4108), .Y (n_5227)); + NOR2X1 g35829(.A (n_5248), .B (n_5225), .Y (n_5226)); + NAND2X1 g37678(.A (n_4109), .B (n_3134), .Y (n_5224)); + NAND2X1 g37680(.A (n_4112), .B (n_3490), .Y (n_12849)); + NAND2X1 g37684(.A (n_4218), .B (n_2950), .Y (n_5222)); + NAND2X1 g37687(.A (n_4155), .B (n_2926), .Y (n_12851)); + NAND2X1 g37688(.A (n_4136), .B (n_3036), .Y (n_5220)); + NAND2X1 g37694(.A (n_4140), .B (n_3366), .Y (n_5219)); + NAND2X1 g37697(.A (n_4219), .B (n_3362), .Y (n_5218)); + NOR2X1 g35828(.A (n_5248), .B (wb_addr_i[6]), .Y (n_6045)); + NAND2X1 g37718(.A (n_4154), .B (n_3037), .Y (n_12060)); + NAND2X1 g37730(.A (n_1523), .B (n_4234), .Y (n_5215)); + NAND2X1 g37743(.A (n_1328), .B (n_4171), .Y (n_5214)); + NAND2X1 g37794(.A (n_4134), .B (n_3422), .Y (n_5213)); + NAND2X1 g37803(.A (n_4183), .B (n_2700), .Y (n_5212)); + NAND2X1 g37810(.A (n_4198), .B (n_3173), .Y (n_5211)); + NAND2X1 g37813(.A (n_1536), .B (n_4121), .Y (n_5210)); + NAND2X1 g37845(.A (n_4182), .B (n_3162), .Y (n_12054)); + NAND2X1 g37850(.A (n_4167), .B (n_3290), .Y (n_12056)); + NAND2X1 g37854(.A (n_4165), .B (n_3086), .Y (n_12048)); + NAND2X1 g37856(.A (n_4224), .B (n_3437), .Y (n_12050)); + NAND2X1 g37858(.A (n_4117), .B (n_1565), .Y (n_5205)); + NAND2X1 g37860(.A (n_4163), .B (n_3073), .Y (n_12052)); + NAND2X1 g37865(.A (n_4229), .B (n_3070), .Y (n_5203)); + NAND2X1 g37867(.A (n_4120), .B (n_2970), .Y (n_5202)); + NAND2X1 g37870(.A (n_4150), .B (n_3472), .Y (n_12058)); + NAND2X1 g37873(.A (n_4244), .B (n_3057), .Y (n_5200)); + NAND2X1 g37876(.A (n_4159), .B (n_3519), .Y (n_5199)); + NAND2X1 g37878(.A (n_4212), .B (n_2995), .Y (n_5198)); + NAND2X1 g37882(.A (n_4143), .B (n_3041), .Y (n_5197)); + NAND2X1 g37896(.A (n_4236), .B (n_3104), .Y (n_5196)); + NAND2X1 g37935(.A (n_2911), .B (n_2856), .Y (n_5195)); + NAND2X1 g37940(.A (n_2432), .B (n_3315), .Y (n_5194)); + NAND2X1 g37941(.A (n_3354), .B (n_2957), .Y (n_5193)); + NAND2X1 g37944(.A (n_3548), .B (n_3399), .Y (n_12852)); + NAND2X1 g37945(.A (n_3499), .B (n_3482), .Y (n_5191)); + NAND2X1 g37948(.A (n_2437), .B (n_3331), .Y (n_5190)); + NAND2X1 g37950(.A (n_2938), .B (n_3406), .Y (n_5189)); + NAND2X1 g37951(.A (n_2379), .B (n_3184), .Y (n_5188)); + NAND2X1 g37953(.A (n_1811), .B (n_3495), .Y (n_5187)); + NAND2X1 g37954(.A (n_3045), .B (n_3004), .Y (n_5186)); + NAND2X1 g37955(.A (n_2464), .B (n_3122), .Y (n_5185)); + NAND2X1 g37956(.A (n_2871), .B (n_2984), .Y (n_5184)); + NAND2X1 g37957(.A (n_2888), .B (n_3840), .Y (n_5183)); + NAND2X1 g37958(.A (n_3862), .B (n_3136), .Y (n_5182)); + NAND2X1 g37959(.A (n_2456), .B (n_2896), .Y (n_5181)); + NAND2X1 g37960(.A (n_3003), .B (n_3429), .Y (n_5180)); + NAND2X1 g37961(.A (n_2396), .B (n_2844), .Y (n_5179)); + NAND2X1 g37963(.A (n_3419), .B (n_3460), .Y (n_5178)); + NAND2X1 g37964(.A (n_2375), .B (n_2891), .Y (n_5177)); + NAND2X1 g37966(.A (n_2852), .B (n_3160), .Y (n_5176)); + NAND2X1 g37968(.A (n_2867), .B (n_2876), .Y (n_5175)); + NAND2X1 g37969(.A (n_1812), .B (n_3442), .Y (n_5174)); + NAND2X1 g37970(.A (n_2915), .B (n_2935), .Y (n_5173)); + NAND2X1 g37972(.A (n_3158), .B (n_2974), .Y (n_5172)); + NAND2X1 g37974(.A (n_2469), .B (n_3866), .Y (n_5171)); + NAND2X1 g37975(.A (n_2409), .B (n_2870), .Y (n_5170)); + NAND2X1 g37976(.A (n_3074), .B (n_3066), .Y (n_5169)); + NAND2X1 g37977(.A (n_3411), .B (n_3082), .Y (n_5168)); + NAND2X1 g37978(.A (n_2441), .B (n_2913), .Y (n_5167)); + NAND2X1 g37979(.A (n_3213), .B (n_3524), .Y (n_5166)); + NAND2X1 g37981(.A (n_2380), .B (n_3052), .Y (n_5165)); + NAND2X1 g37982(.A (n_3191), .B (n_3030), .Y (n_5164)); + NAND2X1 g37983(.A (n_3282), .B (n_3473), .Y (n_5163)); + NAND2X1 g37985(.A (n_3107), .B (n_2903), .Y (n_5162)); + NAND2X1 g37989(.A (n_2841), .B (n_2997), .Y (n_5161)); + AOI21X1 g37990(.A0 (\u3_mem[1]_87 ), .A1 (n_5157), .B0 (n_2769), .Y + (n_5160)); + AOI21X1 g37992(.A0 (\u7_mem[3]_141 ), .A1 (n_5145), .B0 (n_3407), .Y + (n_5159)); + AOI21X1 g37993(.A0 (\u3_mem[1]_61 ), .A1 (n_5157), .B0 (n_2662), .Y + (n_5158)); + AOI21X1 g37996(.A0 (\u3_mem[1]_89 ), .A1 (n_5157), .B0 (n_2655), .Y + (n_5156)); + AOI21X1 g37998(.A0 (\u3_mem[1]_90 ), .A1 (n_5157), .B0 (n_2728), .Y + (n_5155)); + AOI21X1 g38001(.A0 (\u3_mem[1]_62 ), .A1 (n_5157), .B0 (n_2789), .Y + (n_5154)); + AOI21X1 g38002(.A0 (\u3_mem[1]_63 ), .A1 (n_5157), .B0 (n_2718), .Y + (n_5153)); + AOI21X1 g38004(.A0 (\u3_mem[1]_64 ), .A1 (n_5148), .B0 (n_2679), .Y + (n_5152)); + AOI21X1 g38006(.A0 (\u3_mem[1]_65 ), .A1 (n_5157), .B0 (n_2776), .Y + (n_5151)); + AOI21X1 g38008(.A0 (\u3_mem[1]_66 ), .A1 (n_5157), .B0 (n_2651), .Y + (n_5150)); + AOI21X1 g38009(.A0 (\u3_mem[1]_67 ), .A1 (n_5148), .B0 (n_2781), .Y + (n_5149)); + AOI21X1 g38011(.A0 (\u3_mem[1]_68 ), .A1 (n_5148), .B0 (n_2678), .Y + (n_5147)); + AOI21X1 g38022(.A0 (\u7_mem[3]_129 ), .A1 (n_5145), .B0 (n_3065), .Y + (n_5146)); + AOI21X1 g38026(.A0 (\u3_mem[1]_71 ), .A1 (n_5148), .B0 (n_2830), .Y + (n_5144)); + AOI21X1 g38029(.A0 (\u3_mem[1]_72 ), .A1 (n_5148), .B0 (n_2677), .Y + (n_5143)); + AOI21X1 g38031(.A0 (\u3_mem[3]_149 ), .A1 (n_5138), .B0 (n_3358), .Y + (n_5142)); + AOI21X1 g38034(.A0 (\u5_mem[1]_67 ), .A1 (n_5048), .B0 (n_2774), .Y + (n_5141)); + AOI21X1 g38042(.A0 (\u6_mem[1]_89 ), .A1 (n_5112), .B0 (n_2762), .Y + (n_5140)); + AOI21X1 g38049(.A0 (\u3_mem[3]_134 ), .A1 (n_5138), .B0 (n_2985), .Y + (n_5139)); + AOI21X1 g38051(.A0 (\u3_mem[3]_136 ), .A1 (n_5133), .B0 (n_2851), .Y + (n_5137)); + AOI21X1 g38052(.A0 (\u3_mem[3]_137 ), .A1 (n_5138), .B0 (n_2883), .Y + (n_5136)); + AOI21X1 g38053(.A0 (\u3_mem[3]_138 ), .A1 (n_5138), .B0 (n_3151), .Y + (n_5135)); + AOI21X1 g38055(.A0 (\u3_mem[3]_140 ), .A1 (n_5133), .B0 (n_2905), .Y + (n_5134)); + AOI21X1 g38056(.A0 (\u3_mem[3]_122 ), .A1 (n_5138), .B0 (n_3425), .Y + (n_5132)); + AOI21X1 g38057(.A0 (\u3_mem[3]_144 ), .A1 (n_5138), .B0 (n_3400), .Y + (n_5131)); + AOI21X1 g38059(.A0 (\u3_mem[3]_151 ), .A1 (n_5138), .B0 (n_3392), .Y + (n_5130)); + AOI21X1 g38061(.A0 (\u3_mem[3]_147 ), .A1 (n_5133), .B0 (n_3465), .Y + (n_5129)); + AOI21X1 g38064(.A0 (\u7_mem[1]_77 ), .A1 (n_5118), .B0 (n_2722), .Y + (n_5128)); + AOI21X1 g38065(.A0 (\u3_mem[3]_123 ), .A1 (n_5133), .B0 (n_3067), .Y + (n_5127)); + AOI21X1 g38069(.A0 (\u3_mem[3]_130 ), .A1 (n_5133), .B0 (n_3512), .Y + (n_5126)); + AOI21X1 g38071(.A0 (\u3_mem[3]_126 ), .A1 (n_5133), .B0 (n_2880), .Y + (n_5125)); + AOI21X1 g38075(.A0 (\u3_mem[3]_128 ), .A1 (n_5138), .B0 (n_3370), .Y + (n_5124)); + AOI21X1 g38077(.A0 (\u3_mem[3]_148 ), .A1 (n_5133), .B0 (n_3865), .Y + (n_5123)); + AOI21X1 g38078(.A0 (\u3_mem[1]_88 ), .A1 (n_5148), .B0 (n_2803), .Y + (n_5122)); + AOI21X1 g38080(.A0 (\u3_mem[3]_127 ), .A1 (n_5138), .B0 (n_3426), .Y + (n_5121)); + AOI21X1 g38096(.A0 (\u3_mem[3]_145 ), .A1 (n_5138), .B0 (n_2947), .Y + (n_5120)); + AOI21X1 g38119(.A0 (\u7_mem[1]_61 ), .A1 (n_5118), .B0 (n_2783), .Y + (n_5119)); + AOI21X1 g38123(.A0 (\u7_mem[1]_63 ), .A1 (n_5118), .B0 (n_2738), .Y + (n_5117)); + AOI21X1 g38129(.A0 (\u3_mem[1]_84 ), .A1 (n_5157), .B0 (n_2833), .Y + (n_5116)); + AOI21X1 g38132(.A0 (\u3_mem[3]_124 ), .A1 (n_5138), .B0 (n_2873), .Y + (n_5115)); + AOI21X1 g38151(.A0 (\u4_mem[3] ), .A1 (n_5106), .B0 (n_3313), .Y + (n_5114)); + AOI21X1 g38153(.A0 (\u6_mem[1]_66 ), .A1 (n_5112), .B0 (n_2690), .Y + (n_5113)); + AOI21X1 g38157(.A0 (\u6_mem[1]_67 ), .A1 (n_5019), .B0 (n_2657), .Y + (n_5111)); + AOI21X1 g38165(.A0 (\u7_mem[1]_74 ), .A1 (n_5118), .B0 (n_2670), .Y + (n_5110)); + AOI21X1 g38168(.A0 (\u6_mem[3]_124 ), .A1 (n_5100), .B0 (n_3507), .Y + (n_5109)); + AOI21X1 g38183(.A0 (\u6_mem[1]_64 ), .A1 (n_5112), .B0 (n_2753), .Y + (n_5108)); + AOI21X1 g38185(.A0 (\u4_mem[3]_131 ), .A1 (n_5106), .B0 (n_2882), .Y + (n_5107)); + AOI21X1 g38186(.A0 (\u4_mem[3]_132 ), .A1 (n_5102), .B0 (n_3343), .Y + (n_5105)); + AOI21X1 g38188(.A0 (\u4_mem[3]_133 ), .A1 (n_5106), .B0 (n_3309), .Y + (n_5104)); + AOI21X1 g38189(.A0 (\u4_mem[3]_134 ), .A1 (n_5102), .B0 (n_3307), .Y + (n_5103)); + AOI21X1 g38190(.A0 (\u6_mem[3]_126 ), .A1 (n_5100), .B0 (n_3505), .Y + (n_5101)); + AOI21X1 g38191(.A0 (\u4_mem[3]_135 ), .A1 (n_5102), .B0 (n_3844), .Y + (n_5099)); + AOI21X1 g38193(.A0 (\u4_mem[3]_136 ), .A1 (n_5106), .B0 (n_3305), .Y + (n_5098)); + AOI21X1 g38194(.A0 (\u6_mem[1]_63 ), .A1 (n_5112), .B0 (n_2796), .Y + (n_5097)); + AOI21X1 g38195(.A0 (\u4_mem[3]_137 ), .A1 (n_5106), .B0 (n_3434), .Y + (n_5096)); + AOI21X1 g38196(.A0 (\u4_mem[3]_138 ), .A1 (n_5102), .B0 (n_3302), .Y + (n_5095)); + AOI21X1 g38198(.A0 (\u4_mem[3]_139 ), .A1 (n_5102), .B0 (n_3299), .Y + (n_5094)); + AOI21X1 g38199(.A0 (\u3_mem[3]_143 ), .A1 (n_5138), .B0 (n_2954), .Y + (n_5093)); + AOI21X1 g38200(.A0 (\u4_mem[3]_140 ), .A1 (n_5106), .B0 (n_3487), .Y + (n_5092)); + AOI21X1 g38201(.A0 (\u4_mem[3]_122 ), .A1 (n_5102), .B0 (n_2941), .Y + (n_5091)); + AOI21X1 g38202(.A0 (\u4_mem[3]_141 ), .A1 (n_5106), .B0 (n_3511), .Y + (n_5090)); + AOI21X1 g38203(.A0 (\u4_mem[3]_142 ), .A1 (n_5106), .B0 (n_3295), .Y + (n_5089)); + AOI21X1 g38204(.A0 (\u4_mem[3]_143 ), .A1 (n_5102), .B0 (n_2951), .Y + (n_5088)); + AOI21X1 g38206(.A0 (\u4_mem[3]_144 ), .A1 (n_5102), .B0 (n_3293), .Y + (n_5087)); + AOI21X1 g38207(.A0 (\u4_mem[3]_145 ), .A1 (n_5102), .B0 (n_3185), .Y + (n_5086)); + AOI21X1 g38208(.A0 (\u4_mem[3]_146 ), .A1 (n_5102), .B0 (n_3292), .Y + (n_5085)); + AOI21X1 g38211(.A0 (\u4_mem[3]_147 ), .A1 (n_5102), .B0 (n_2928), .Y + (n_5084)); + AOI21X1 g38212(.A0 (\u7_mem[1]_60 ), .A1 (n_5069), .B0 (n_2673), .Y + (n_5083)); + AOI21X1 g38213(.A0 (\u4_mem[3]_148 ), .A1 (n_5106), .B0 (n_3246), .Y + (n_5082)); + AOI21X1 g38214(.A0 (\u4_mem[3]_149 ), .A1 (n_5106), .B0 (n_2958), .Y + (n_5081)); + AOI21X1 g38215(.A0 (\u4_mem[3]_150 ), .A1 (n_5106), .B0 (n_3506), .Y + (n_5080)); + AOI21X1 g38216(.A0 (\u7_mem[1]_67 ), .A1 (n_5118), .B0 (n_2807), .Y + (n_5079)); + AOI21X1 g38217(.A0 (\u4_mem[3]_123 ), .A1 (n_5102), .B0 (n_2877), .Y + (n_5078)); + AOI21X1 g38219(.A0 (\u4_mem[3]_151 ), .A1 (n_5106), .B0 (n_2865), .Y + (n_5077)); + AOI21X1 g38220(.A0 (\u7_mem[3]_138 ), .A1 (n_4961), .B0 (n_3163), .Y + (n_5076)); + AOI21X1 g38221(.A0 (\u4_mem[3]_152 ), .A1 (n_5106), .B0 (n_3279), .Y + (n_5075)); + AOI21X1 g38222(.A0 (\u4_mem[3]_124 ), .A1 (n_5106), .B0 (n_3280), .Y + (n_5074)); + AOI21X1 g38223(.A0 (\u7_mem[3]_143 ), .A1 (n_5145), .B0 (n_3535), .Y + (n_5073)); + AOI21X1 g38224(.A0 (\u4_mem[3]_125 ), .A1 (n_5106), .B0 (n_2953), .Y + (n_5072)); + AOI21X1 g38225(.A0 (\u4_mem[3]_126 ), .A1 (n_5106), .B0 (n_3525), .Y + (n_5071)); + AOI21X1 g38226(.A0 (\u7_mem[1]_65 ), .A1 (n_5069), .B0 (n_2766), .Y + (n_5070)); + AOI21X1 g38227(.A0 (\u4_mem[3]_127 ), .A1 (n_5102), .B0 (n_2962), .Y + (n_5068)); + AOI21X1 g38228(.A0 (\u4_mem[3]_128 ), .A1 (n_5102), .B0 (n_2810), .Y + (n_5067)); + AOI21X1 g38229(.A0 (\u3_mem[3]_150 ), .A1 (n_5133), .B0 (n_3463), .Y + (n_5066)); + AOI21X1 g38232(.A0 (\u4_mem[3]_129 ), .A1 (n_5102), .B0 (n_2992), .Y + (n_5065)); + AOI21X1 g38234(.A0 (\u4_mem[3]_130 ), .A1 (n_5102), .B0 (n_3007), .Y + (n_5064)); + AOI21X1 g38236(.A0 (\u6_mem[3]_152 ), .A1 (n_5059), .B0 (n_3022), .Y + (n_5063)); + AOI21X1 g38238(.A0 (\u6_mem[3]_151 ), .A1 (n_5100), .B0 (n_2998), .Y + (n_5062)); + AOI21X1 g38244(.A0 (\u6_mem[3]_150 ), .A1 (n_5100), .B0 (n_3235), .Y + (n_5061)); + AOI21X1 g38247(.A0 (\u6_mem[3]_148 ), .A1 (n_5059), .B0 (n_3220), .Y + (n_5060)); + AOI21X1 g38249(.A0 (\u6_mem[3]_130 ), .A1 (n_5100), .B0 (n_2777), .Y + (n_5058)); + AOI21X1 g38251(.A0 (\u7_mem[3]_140 ), .A1 (n_5145), .B0 (n_3242), .Y + (n_5057)); + AOI21X1 g38252(.A0 (\u6_mem[3]_146 ), .A1 (n_5100), .B0 (n_3180), .Y + (n_5056)); + AOI21X1 g38255(.A0 (\u6_mem[3]_145 ), .A1 (n_5059), .B0 (n_3175), .Y + (n_5055)); + AOI21X1 g38256(.A0 (\u6_mem[1]_88 ), .A1 (n_5112), .B0 (n_2697), .Y + (n_5054)); + AOI21X1 g38258(.A0 (\u6_mem[3]_144 ), .A1 (n_5059), .B0 (n_3228), .Y + (n_5053)); + AOI21X1 g38259(.A0 (\u6_mem[3]_143 ), .A1 (n_5059), .B0 (n_3169), .Y + (n_5052)); + AOI21X1 g38260(.A0 (\u6_mem[3]_141 ), .A1 (n_5059), .B0 (n_3177), .Y + (n_5051)); + AOI21X1 g38261(.A0 (\u6_mem[3]_122 ), .A1 (n_5100), .B0 (n_3164), .Y + (n_5050)); + AOI21X1 g38262(.A0 (\u5_mem[1] ), .A1 (n_5048), .B0 (n_2802), .Y + (n_5049)); + AOI21X1 g38263(.A0 (\u5_mem[1]_69 ), .A1 (n_5048), .B0 (n_2760), .Y + (n_5047)); + AOI21X1 g38264(.A0 (\u5_mem[1]_70 ), .A1 (n_5048), .B0 (n_2717), .Y + (n_5046)); + AOI21X1 g38265(.A0 (\u3_mem[3]_141 ), .A1 (n_5133), .B0 (n_3428), .Y + (n_5045)); + AOI21X1 g38266(.A0 (\u6_mem[3]_139 ), .A1 (n_5059), .B0 (n_3344), .Y + (n_5044)); + AOI21X1 g38268(.A0 (\u5_mem[1]_72 ), .A1 (n_5048), .B0 (n_2725), .Y + (n_5043)); + AOI21X1 g38269(.A0 (\u5_mem[1]_73 ), .A1 (n_5048), .B0 (n_2785), .Y + (n_5042)); + AOI21X1 g38270(.A0 (\u6_mem[3]_138 ), .A1 (n_5100), .B0 (n_3357), .Y + (n_5041)); + AOI21X1 g38271(.A0 (\u5_mem[1]_74 ), .A1 (n_5037), .B0 (n_2747), .Y + (n_5040)); + AOI21X1 g38272(.A0 (\u5_mem[1]_75 ), .A1 (n_5048), .B0 (n_2779), .Y + (n_5039)); + AOI21X1 g38273(.A0 (\u5_mem[1]_76 ), .A1 (n_5037), .B0 (n_2726), .Y + (n_5038)); + AOI21X1 g38274(.A0 (\u6_mem[3]_137 ), .A1 (n_5100), .B0 (n_3296), .Y + (n_5036)); + AOI21X1 g38275(.A0 (\u5_mem[1]_77 ), .A1 (n_5037), .B0 (n_2666), .Y + (n_5035)); + AOI21X1 g38276(.A0 (\u5_mem[1]_78 ), .A1 (n_5037), .B0 (n_2799), .Y + (n_5034)); + AOI21X1 g38277(.A0 (\u5_mem[1]_60 ), .A1 (n_5037), .B0 (n_2661), .Y + (n_5033)); + AOI21X1 g38279(.A0 (\u5_mem[1]_79 ), .A1 (n_5037), .B0 (n_2778), .Y + (n_5032)); + AOI21X1 g38280(.A0 (\u5_mem[1]_80 ), .A1 (n_5037), .B0 (n_2754), .Y + (n_5031)); + AOI21X1 g38281(.A0 (\u5_mem[1]_81 ), .A1 (n_5048), .B0 (n_2667), .Y + (n_5030)); + AOI21X1 g38283(.A0 (\u5_mem[1]_82 ), .A1 (n_5048), .B0 (n_2685), .Y + (n_5029)); + AOI21X1 g38284(.A0 (\u5_mem[1]_83 ), .A1 (n_5048), .B0 (n_2669), .Y + (n_5028)); + AOI21X1 g38285(.A0 (\u5_mem[1]_84 ), .A1 (n_5037), .B0 (n_2771), .Y + (n_5027)); + AOI21X1 g38286(.A0 (\u5_mem[1]_85 ), .A1 (n_5048), .B0 (n_2665), .Y + (n_5026)); + AOI21X1 g38287(.A0 (\u5_mem[1]_86 ), .A1 (n_5037), .B0 (n_2823), .Y + (n_5025)); + AOI21X1 g38288(.A0 (\u5_mem[1]_87 ), .A1 (n_5037), .B0 (n_2808), .Y + (n_5024)); + AOI21X1 g38289(.A0 (\u5_mem[1]_71 ), .A1 (n_5048), .B0 (n_2816), .Y + (n_5023)); + AOI21X1 g38290(.A0 (\u5_mem[1]_88 ), .A1 (n_5048), .B0 (n_2806), .Y + (n_5022)); + AOI21X1 g38291(.A0 (\u5_mem[1]_61 ), .A1 (n_5037), .B0 (n_2672), .Y + (n_5021)); + AOI21X1 g38292(.A0 (\u6_mem[1]_86 ), .A1 (n_5019), .B0 (n_2764), .Y + (n_5020)); + AOI21X1 g38293(.A0 (\u5_mem[1]_89 ), .A1 (n_5037), .B0 (n_2828), .Y + (n_5018)); + AOI21X1 g38294(.A0 (\u5_mem[1]_90 ), .A1 (n_5037), .B0 (n_2719), .Y + (n_5017)); + AOI21X1 g38295(.A0 (\u5_mem[1]_62 ), .A1 (n_5037), .B0 (n_2800), .Y + (n_5016)); + AOI21X1 g38296(.A0 (\u5_mem[1]_63 ), .A1 (n_5037), .B0 (n_2967), .Y + (n_5015)); + AOI21X1 g38297(.A0 (\u5_mem[1]_64 ), .A1 (n_5037), .B0 (n_2746), .Y + (n_5014)); + AOI21X1 g38298(.A0 (\u5_mem[1]_65 ), .A1 (n_5048), .B0 (n_2758), .Y + (n_5013)); + AOI21X1 g38299(.A0 (\u5_mem[1]_66 ), .A1 (n_5037), .B0 (n_2835), .Y + (n_5012)); + AOI21X1 g38300(.A0 (\u6_mem[1]_85 ), .A1 (n_5112), .B0 (n_2668), .Y + (n_5011)); + AOI21X1 g38301(.A0 (\u5_mem[1]_68 ), .A1 (n_5048), .B0 (n_2731), .Y + (n_5010)); + AOI21X1 g38304(.A0 (\u7_mem[1]_90 ), .A1 (n_5118), .B0 (n_2837), .Y + (n_5009)); + AOI21X1 g38308(.A0 (\u6_mem[1]_84 ), .A1 (n_5019), .B0 (n_2820), .Y + (n_5008)); + AOI21X1 g38319(.A0 (\u6_mem[1]_82 ), .A1 (n_5112), .B0 (n_2650), .Y + (n_5007)); + AOI21X1 g38328(.A0 (\u6_mem[3]_149 ), .A1 (n_5100), .B0 (n_3234), .Y + (n_5006)); + AOI21X1 g38330(.A0 (\u7_mem[1]_87 ), .A1 (n_5069), .B0 (n_2740), .Y + (n_5005)); + AOI21X1 g38331(.A0 (\u6_mem[1]_81 ), .A1 (n_5019), .B0 (n_2797), .Y + (n_5004)); + AOI21X1 g38335(.A0 (\u6_mem[1]_80 ), .A1 (n_5019), .B0 (n_2660), .Y + (n_5003)); + AOI21X1 g38337(.A0 (\u5_mem[3] ), .A1 (n_5000), .B0 (n_3023), .Y + (n_5002)); + AOI21X1 g38338(.A0 (\u5_mem[3]_131 ), .A1 (n_5000), .B0 (n_3063), .Y + (n_5001)); + AOI21X1 g38339(.A0 (\u5_mem[3]_132 ), .A1 (n_4996), .B0 (n_2929), .Y + (n_4999)); + AOI21X1 g38340(.A0 (\u5_mem[3]_133 ), .A1 (n_5000), .B0 (n_2739), .Y + (n_4998)); + AOI21X1 g38341(.A0 (\u5_mem[3]_134 ), .A1 (n_4996), .B0 (n_2932), .Y + (n_4997)); + AOI21X1 g38342(.A0 (\u5_mem[3]_135 ), .A1 (n_4996), .B0 (n_2934), .Y + (n_4995)); + AOI21X1 g38343(.A0 (\u5_mem[3]_136 ), .A1 (n_5000), .B0 (n_2939), .Y + (n_4994)); + AOI21X1 g38344(.A0 (\u5_mem[3]_137 ), .A1 (n_5000), .B0 (n_3154), .Y + (n_4993)); + AOI21X1 g38345(.A0 (\u5_mem[3]_138 ), .A1 (n_4996), .B0 (n_3133), .Y + (n_4992)); + AOI21X1 g38346(.A0 (\u7_mem[1]_79 ), .A1 (n_5118), .B0 (n_2734), .Y + (n_4991)); + AOI21X1 g38347(.A0 (\u5_mem[3]_139 ), .A1 (n_4996), .B0 (n_2965), .Y + (n_4990)); + AOI21X1 g38348(.A0 (\u5_mem[3]_140 ), .A1 (n_5000), .B0 (n_3132), .Y + (n_4989)); + AOI21X1 g38349(.A0 (\u6_mem[3]_133 ), .A1 (n_5100), .B0 (n_2987), .Y + (n_4988)); + AOI21X1 g38350(.A0 (\u5_mem[3]_122 ), .A1 (n_4996), .B0 (n_2975), .Y + (n_4987)); + AOI21X1 g38351(.A0 (\u5_mem[3]_141 ), .A1 (n_5000), .B0 (n_3449), .Y + (n_4986)); + AOI21X1 g38352(.A0 (\u5_mem[3]_142 ), .A1 (n_5000), .B0 (n_3053), .Y + (n_4985)); + AOI21X1 g38353(.A0 (\u5_mem[3]_143 ), .A1 (n_4996), .B0 (n_3131), .Y + (n_4984)); + AOI21X1 g38354(.A0 (\u5_mem[3]_144 ), .A1 (n_4996), .B0 (n_3129), .Y + (n_4983)); + AOI21X1 g38355(.A0 (\u5_mem[3]_145 ), .A1 (n_4996), .B0 (n_3128), .Y + (n_4982)); + AOI21X1 g38356(.A0 (\u5_mem[3]_146 ), .A1 (n_4996), .B0 (n_3001), .Y + (n_4981)); + AOI21X1 g38357(.A0 (\u5_mem[3]_147 ), .A1 (n_4996), .B0 (n_3006), .Y + (n_4980)); + AOI21X1 g38358(.A0 (\u5_mem[3]_148 ), .A1 (n_5000), .B0 (n_3346), .Y + (n_4979)); + AOI21X1 g38359(.A0 (\u5_mem[3]_149 ), .A1 (n_5000), .B0 (n_3123), .Y + (n_4978)); + AOI21X1 g38360(.A0 (\u5_mem[3]_150 ), .A1 (n_5000), .B0 (n_3010), .Y + (n_4977)); + AOI21X1 g38361(.A0 (\u5_mem[3]_123 ), .A1 (n_4996), .B0 (n_3353), .Y + (n_4976)); + AOI21X1 g38362(.A0 (\u7_mem[1]_83 ), .A1 (n_5118), .B0 (n_2791), .Y + (n_4975)); + AOI21X1 g38363(.A0 (\u5_mem[3]_151 ), .A1 (n_5000), .B0 (n_3018), .Y + (n_4974)); + AOI21X1 g38364(.A0 (\u6_mem[1]_78 ), .A1 (n_5019), .B0 (n_2821), .Y + (n_4973)); + AOI21X1 g38365(.A0 (\u5_mem[3]_152 ), .A1 (n_5000), .B0 (n_3118), .Y + (n_4972)); + AOI21X1 g38366(.A0 (\u5_mem[3]_124 ), .A1 (n_5000), .B0 (n_3116), .Y + (n_4971)); + AOI21X1 g38367(.A0 (\u5_mem[3]_125 ), .A1 (n_5000), .B0 (n_3114), .Y + (n_4970)); + AOI21X1 g38368(.A0 (\u5_mem[3]_126 ), .A1 (n_5000), .B0 (n_3027), .Y + (n_4969)); + AOI21X1 g38369(.A0 (\u5_mem[3]_128 ), .A1 (n_4996), .B0 (n_3111), .Y + (n_4968)); + AOI21X1 g38370(.A0 (\u6_mem[1]_77 ), .A1 (n_5019), .B0 (n_2809), .Y + (n_4967)); + AOI21X1 g38371(.A0 (\u5_mem[3]_129 ), .A1 (n_4996), .B0 (n_2854), .Y + (n_4966)); + AOI21X1 g38372(.A0 (\u5_mem[3]_130 ), .A1 (n_4996), .B0 (n_3058), .Y + (n_4965)); + AOI21X1 g38376(.A0 (\u7_mem[1]_81 ), .A1 (n_5069), .B0 (n_2793), .Y + (n_4964)); + AOI21X1 g38377(.A0 (\u3_mem[1]_77 ), .A1 (n_5157), .B0 (n_2653), .Y + (n_4963)); + AOI21X1 g38379(.A0 (\u7_mem[3]_137 ), .A1 (n_4961), .B0 (n_3455), .Y + (n_4962)); + AOI21X1 g38380(.A0 (\u3_mem[3]_146 ), .A1 (n_5133), .B0 (n_3467), .Y + (n_4960)); + AOI21X1 g38381(.A0 (\u7_mem[3]_148 ), .A1 (n_5145), .B0 (n_2879), .Y + (n_4959)); + AOI21X1 g38386(.A0 (\u3_mem[3]_142 ), .A1 (n_5133), .B0 (n_2961), .Y + (n_4958)); + AOI21X1 g38387(.A0 (\u7_mem[3]_125 ), .A1 (n_5145), .B0 (n_2907), .Y + (n_4957)); + AOI21X1 g38388(.A0 (\u7_mem[3]_128 ), .A1 (n_5145), .B0 (n_3454), .Y + (n_4956)); + AOI21X1 g38390(.A0 (\u3_mem[3]_135 ), .A1 (n_5138), .B0 (n_3478), .Y + (n_4955)); + AOI21X1 g38393(.A0 (\u3_mem[3]_125 ), .A1 (n_5133), .B0 (n_3391), .Y + (n_4954)); + AOI21X1 g38396(.A0 (\u3_mem[3]_152 ), .A1 (n_5133), .B0 (n_3338), .Y + (n_4953)); + AOI21X1 g38397(.A0 (\u7_mem[3]_139 ), .A1 (n_4961), .B0 (n_3198), .Y + (n_4952)); + AOI21X1 g38399(.A0 (\u7_mem[1]_64 ), .A1 (n_5069), .B0 (n_2694), .Y + (n_4951)); + AOI21X1 g38401(.A0 (\u5_mem[3]_127 ), .A1 (n_4996), .B0 (n_3031), .Y + (n_4950)); + AOI21X1 g38403(.A0 (\u7_mem[3]_136 ), .A1 (n_4961), .B0 (n_3501), .Y + (n_4949)); + AOI21X1 g38404(.A0 (\u6_mem[1] ), .A1 (n_5112), .B0 (n_2675), .Y + (n_4948)); + AOI21X1 g38405(.A0 (\u6_mem[1]_70 ), .A1 (n_5112), .B0 (n_2652), .Y + (n_4947)); + AOI21X1 g38407(.A0 (\u6_mem[1]_72 ), .A1 (n_5019), .B0 (n_2682), .Y + (n_4946)); + AOI21X1 g38408(.A0 (\u6_mem[1]_76 ), .A1 (n_5112), .B0 (n_2737), .Y + (n_4945)); + AOI21X1 g38409(.A0 (\u6_mem[1]_75 ), .A1 (n_5112), .B0 (n_2787), .Y + (n_4944)); + AOI21X1 g38410(.A0 (\u6_mem[1]_60 ), .A1 (n_5019), .B0 (n_2709), .Y + (n_4943)); + AOI21X1 g38411(.A0 (\u6_mem[1]_79 ), .A1 (n_5019), .B0 (n_2664), .Y + (n_4942)); + AOI21X1 g38412(.A0 (\u6_mem[1]_74 ), .A1 (n_5112), .B0 (n_2683), .Y + (n_4941)); + AOI21X1 g38414(.A0 (\u6_mem[1]_83 ), .A1 (n_5112), .B0 (n_2817), .Y + (n_4940)); + AOI21X1 g38415(.A0 (\u6_mem[1]_87 ), .A1 (n_5019), .B0 (n_2826), .Y + (n_4939)); + AOI21X1 g38416(.A0 (\u6_mem[1]_73 ), .A1 (n_5019), .B0 (n_2680), .Y + (n_4938)); + AOI21X1 g38417(.A0 (\u6_mem[1]_61 ), .A1 (n_5019), .B0 (n_2824), .Y + (n_4937)); + AOI21X1 g38418(.A0 (\u6_mem[1]_90 ), .A1 (n_5019), .B0 (n_2750), .Y + (n_4936)); + AOI21X1 g38419(.A0 (\u6_mem[1]_62 ), .A1 (n_5019), .B0 (n_2811), .Y + (n_4935)); + AOI21X1 g38420(.A0 (\u6_mem[1]_65 ), .A1 (n_5019), .B0 (n_2727), .Y + (n_4934)); + AOI21X1 g38421(.A0 (\u6_mem[1]_71 ), .A1 (n_5112), .B0 (n_2838), .Y + (n_4933)); + AOI21X1 g38423(.A0 (\u7_mem[1]_78 ), .A1 (n_5069), .B0 (n_2693), .Y + (n_4932)); + AOI21X1 g38427(.A0 (\u7_mem[3]_126 ), .A1 (n_4961), .B0 (n_3032), .Y + (n_4931)); + AOI21X1 g38429(.A0 (\u6_mem[1]_69 ), .A1 (n_5019), .B0 (n_2676), .Y + (n_4930)); + AOI21X1 g38430(.A0 (\u7_mem[1]_72 ), .A1 (n_5118), .B0 (n_2812), .Y + (n_4929)); + AOI21X1 g38437(.A0 (\u6_mem[3] ), .A1 (n_5059), .B0 (n_2964), .Y + (n_4928)); + AOI21X1 g38438(.A0 (\u6_mem[3]_131 ), .A1 (n_5059), .B0 (n_2916), .Y + (n_4927)); + AOI21X1 g38439(.A0 (\u6_mem[3]_132 ), .A1 (n_5059), .B0 (n_3040), .Y + (n_4926)); + AOI21X1 g38440(.A0 (\u6_mem[3]_134 ), .A1 (n_5059), .B0 (n_2946), .Y + (n_4925)); + AOI21X1 g38442(.A0 (\u6_mem[3]_135 ), .A1 (n_5100), .B0 (n_3333), .Y + (n_4924)); + AOI21X1 g38443(.A0 (\u6_mem[3]_136 ), .A1 (n_5059), .B0 (n_3410), .Y + (n_4923)); + AOI21X1 g38445(.A0 (\u6_mem[3]_140 ), .A1 (n_5059), .B0 (n_3121), .Y + (n_4922)); + AOI21X1 g38446(.A0 (\u6_mem[3]_142 ), .A1 (n_5100), .B0 (n_3167), .Y + (n_4921)); + AOI21X1 g38447(.A0 (\u6_mem[3]_147 ), .A1 (n_5100), .B0 (n_3350), .Y + (n_4920)); + AOI21X1 g38448(.A0 (\u6_mem[3]_123 ), .A1 (n_5059), .B0 (n_3285), .Y + (n_4919)); + AOI21X1 g38450(.A0 (\u7_mem[1]_70 ), .A1 (n_5118), .B0 (n_2752), .Y + (n_4918)); + AOI21X1 g38451(.A0 (\u6_mem[3]_125 ), .A1 (n_5059), .B0 (n_3204), .Y + (n_4917)); + AOI21X1 g38452(.A0 (\u6_mem[3]_127 ), .A1 (n_5059), .B0 (n_3318), .Y + (n_4916)); + AOI21X1 g38453(.A0 (\u6_mem[3]_128 ), .A1 (n_5100), .B0 (n_2977), .Y + (n_4915)); + AOI21X1 g38454(.A0 (\u6_mem[3]_129 ), .A1 (n_5100), .B0 (n_3035), .Y + (n_4914)); + AOI21X1 g38455(.A0 (\u3_mem[1]_74 ), .A1 (n_5157), .B0 (n_2743), .Y + (n_4913)); + AOI21X1 g38457(.A0 (\u7_mem[3]_152 ), .A1 (n_4961), .B0 (n_3321), .Y + (n_4912)); + AOI21X1 g38461(.A0 (\u7_mem[1]_85 ), .A1 (n_5069), .B0 (n_2711), .Y + (n_4911)); + AOI21X1 g38464(.A0 (\u3_mem[3]_139 ), .A1 (n_5138), .B0 (n_2902), .Y + (n_4910)); + AOI21X1 g38465(.A0 (\u7_mem[3]_123 ), .A1 (n_5145), .B0 (n_3364), .Y + (n_4909)); + AOI21X1 g38467(.A0 (\u3_mem[3]_129 ), .A1 (n_5133), .B0 (n_3329), .Y + (n_4908)); + AOI21X1 g38471(.A0 (\u7_mem[3]_132 ), .A1 (n_4961), .B0 (n_3079), .Y + (n_4907)); + AOI21X1 g38472(.A0 (\u6_mem[1]_68 ), .A1 (n_5112), .B0 (n_2659), .Y + (n_4906)); + AOI21X1 g38474(.A0 (\u7_mem[1]_69 ), .A1 (n_5118), .B0 (n_2692), .Y + (n_4905)); + AOI21X1 g38476(.A0 (\u7_mem[1]_71 ), .A1 (n_5118), .B0 (n_2701), .Y + (n_4904)); + AOI21X1 g38477(.A0 (\u7_mem[1]_73 ), .A1 (n_5069), .B0 (n_2699), .Y + (n_4903)); + AOI21X1 g38478(.A0 (\u7_mem[1] ), .A1 (n_5069), .B0 (n_2671), .Y + (n_4902)); + AOI21X1 g38479(.A0 (\u7_mem[1]_75 ), .A1 (n_5069), .B0 (n_2674), .Y + (n_4901)); + AOI21X1 g38480(.A0 (\u7_mem[1]_76 ), .A1 (n_5118), .B0 (n_2706), .Y + (n_4900)); + AOI21X1 g38481(.A0 (\u7_mem[1]_80 ), .A1 (n_5069), .B0 (n_2730), .Y + (n_4899)); + AOI21X1 g38482(.A0 (\u7_mem[3]_145 ), .A1 (n_5145), .B0 (n_3103), .Y + (n_4898)); + AOI21X1 g38483(.A0 (\u7_mem[1]_82 ), .A1 (n_5069), .B0 (n_2649), .Y + (n_4897)); + AOI21X1 g38484(.A0 (\u7_mem[1]_84 ), .A1 (n_5069), .B0 (n_2840), .Y + (n_4896)); + AOI21X1 g38485(.A0 (\u7_mem[1]_86 ), .A1 (n_5069), .B0 (n_2656), .Y + (n_4895)); + AOI21X1 g38486(.A0 (\u7_mem[1]_88 ), .A1 (n_5069), .B0 (n_2715), .Y + (n_4894)); + AOI21X1 g38487(.A0 (\u7_mem[1]_89 ), .A1 (n_5069), .B0 (n_2647), .Y + (n_4893)); + AOI21X1 g38488(.A0 (\u7_mem[1]_62 ), .A1 (n_5118), .B0 (n_2805), .Y + (n_4892)); + AOI21X1 g38489(.A0 (\u7_mem[1]_66 ), .A1 (n_5069), .B0 (n_2714), .Y + (n_4891)); + AOI21X1 g38491(.A0 (\u7_mem[1]_68 ), .A1 (n_5118), .B0 (n_2688), .Y + (n_4890)); + AOI21X1 g38495(.A0 (\u3_mem[3]_133 ), .A1 (n_5133), .B0 (n_2912), .Y + (n_4889)); + AOI21X1 g38508(.A0 (\u7_mem[3]_131 ), .A1 (n_5145), .B0 (n_3311), .Y + (n_4888)); + AOI21X1 g38510(.A0 (\u7_mem[3]_133 ), .A1 (n_5145), .B0 (n_3520), .Y + (n_4887)); + AOI21X1 g38511(.A0 (\u7_mem[3]_135 ), .A1 (n_5145), .B0 (n_2930), .Y + (n_4886)); + AOI21X1 g38514(.A0 (\u7_mem[3]_127 ), .A1 (n_4961), .B0 (n_3381), .Y + (n_4885)); + AOI21X1 g38515(.A0 (\u7_mem[3]_122 ), .A1 (n_4961), .B0 (n_3409), .Y + (n_4884)); + AOI21X1 g38516(.A0 (\u7_mem[3]_142 ), .A1 (n_4961), .B0 (n_3076), .Y + (n_4883)); + AOI21X1 g38517(.A0 (\u7_mem[3]_144 ), .A1 (n_4961), .B0 (n_3324), .Y + (n_4882)); + AOI21X1 g38518(.A0 (\u7_mem[3]_146 ), .A1 (n_5145), .B0 (n_2976), .Y + (n_4881)); + AOI21X1 g38521(.A0 (\u7_mem[3]_150 ), .A1 (n_4961), .B0 (n_3417), .Y + (n_4880)); + AOI21X1 g38522(.A0 (\u7_mem[3]_151 ), .A1 (n_4961), .B0 (n_3015), .Y + (n_4879)); + AOI21X1 g38523(.A0 (\u7_mem[3]_124 ), .A1 (n_5145), .B0 (n_3444), .Y + (n_4878)); + AOI21X1 g38524(.A0 (\u7_mem[3]_130 ), .A1 (n_4961), .B0 (n_3446), .Y + (n_4877)); + AOI21X1 g38525(.A0 (\u7_mem[3]_149 ), .A1 (n_4961), .B0 (n_3172), .Y + (n_4876)); + AOI21X1 g38528(.A0 (\u7_mem[3] ), .A1 (n_4961), .B0 (n_2890), .Y + (n_4875)); + AOI21X1 g38530(.A0 (\u7_mem[3]_134 ), .A1 (n_5145), .B0 (n_3342), .Y + (n_4874)); + AOI21X1 g38535(.A0 (\u3_mem[3]_131 ), .A1 (n_5133), .B0 (n_3090), .Y + (n_4873)); + AOI21X1 g38537(.A0 (\u3_mem[1]_80 ), .A1 (n_5148), .B0 (n_2695), .Y + (n_4872)); + AOI21X1 g38538(.A0 (\u3_mem[3]_132 ), .A1 (n_5138), .B0 (n_2858), .Y + (n_4871)); + AOI21X1 g38554(.A0 (\u3_mem[1] ), .A1 (n_5148), .B0 (n_3412), .Y + (n_4870)); + AOI21X1 g38555(.A0 (\u3_mem[1]_69 ), .A1 (n_5148), .B0 (n_2648), .Y + (n_4869)); + AOI21X1 g38557(.A0 (\u3_mem[1]_70 ), .A1 (n_5148), .B0 (n_2698), .Y + (n_4868)); + AOI21X1 g38561(.A0 (\u3_mem[1]_73 ), .A1 (n_5157), .B0 (n_2757), .Y + (n_4867)); + AOI21X1 g38564(.A0 (\u3_mem[1]_75 ), .A1 (n_5157), .B0 (n_2839), .Y + (n_4866)); + AOI21X1 g38566(.A0 (\u3_mem[1]_76 ), .A1 (n_5148), .B0 (n_2813), .Y + (n_4865)); + AOI21X1 g38567(.A0 (\u3_mem[1]_78 ), .A1 (n_5148), .B0 (n_2819), .Y + (n_4864)); + AOI21X1 g38568(.A0 (\u3_mem[1]_60 ), .A1 (n_5148), .B0 (n_2814), .Y + (n_4863)); + AOI21X1 g38570(.A0 (\u7_mem[3]_147 ), .A1 (n_5145), .B0 (n_2909), .Y + (n_4862)); + AOI21X1 g38571(.A0 (\u3_mem[1]_79 ), .A1 (n_5148), .B0 (n_2815), .Y + (n_4861)); + AOI21X1 g38572(.A0 (\u3_mem[1]_81 ), .A1 (n_5148), .B0 (n_2658), .Y + (n_4860)); + AOI21X1 g38573(.A0 (\u3_mem[3] ), .A1 (n_5138), .B0 (n_2937), .Y + (n_4859)); + AOI21X1 g38574(.A0 (\u3_mem[1]_82 ), .A1 (n_5148), .B0 (n_2822), .Y + (n_4858)); + AOI21X1 g38576(.A0 (\u3_mem[1]_83 ), .A1 (n_5157), .B0 (n_2663), .Y + (n_4857)); + AOI21X1 g38578(.A0 (\u3_mem[1]_85 ), .A1 (n_5148), .B0 (n_2704), .Y + (n_4856)); + AOI21X1 g38579(.A0 (\u3_mem[1]_86 ), .A1 (n_5157), .B0 (n_2723), .Y + (n_4855)); + AOI22X1 g38786(.A0 (n_4253), .A1 (n_784), .B0 (n_6821), .B1 (n_762), + .Y (n_4854)); + NAND2X1 g39219(.A (n_12747), .B (\u4_rp[3] ), .Y (n_5466)); + OAI21X1 g35857(.A0 (n_2615), .A1 (\u2_to_cnt[5] ), .B0 (n_2616), .Y + (n_4853)); + NOR2X1 g35856(.A (n_2625), .B (n_4851), .Y (n_4852)); + AOI21X1 g35435(.A0 (n_1558), .A1 (n_2368), .B0 (n_2570), .Y (n_4850)); + AOI21X1 g35437(.A0 (n_1234), .A1 (n_2513), .B0 (n_2569), .Y (n_4848)); + MX2X1 g35483(.A (n_1818), .B (\u2_res_cnt[2] ), .S0 (n_5632), .Y + (n_4846)); + XOR2X1 g35487(.A (\u9_wp[3] ), .B (n_1557), .Y (n_4845)); + XOR2X1 g35489(.A (\u10_wp[3] ), .B (n_1559), .Y (n_4844)); + MX2X1 g35727(.A (n_796), .B (\u2_res_cnt[1] ), .S0 (n_5632), .Y + (n_4843)); + DFFX1 u12_re1_reg(.CK (clk_i), .D (n_2600), .Q (u12_re1), .QN ()); + XOR2X1 g36189(.A (n_1420), .B (n_1790), .Y (n_4842)); + XOR2X1 g36190(.A (n_799), .B (n_1788), .Y (n_4841)); + DFFX1 u2_bit_clk_e_reg(.CK (clk_i), .D (n_2589), .Q (u2_bit_clk_e), + .QN ()); + OR2X1 g36306(.A (n_2597), .B (n_1212), .Y (n_4840)); + NOR2X1 g36414(.A (n_2577), .B (n_4837), .Y (n_4839)); + NOR2X1 g36415(.A (n_3432), .B (n_4837), .Y (n_4838)); + NAND2X1 g36447(.A (n_2565), .B (n_4836), .Y (n_6059)); + NOR2X1 g36476(.A (n_2609), .B (n_1776), .Y (n_5440)); + NAND2X1 g36493(.A (n_3561), .B (n_1291), .Y (n_4835)); + NAND2X1 g36524(.A (n_2566), .B (n_4834), .Y (n_5964)); + INVX1 g36561(.A (n_4832), .Y (n_4833)); + NOR2X1 g36563(.A (n_1114), .B (n_2604), .Y (n_4831)); + NAND2X1 g36585(.A (n_3563), .B (n_2624), .Y (n_4830)); + NOR2X1 g36612(.A (n_2610), .B (n_2587), .Y (n_4828)); + XOR2X1 g36734(.A (\u26_ps_cnt[5] ), .B (n_1775), .Y (n_4827)); + XOR2X1 g36736(.A (\u2_cnt[5] ), .B (n_1774), .Y (n_4826)); + AOI21X1 g36741(.A0 (n_2602), .A1 (\u2_cnt[6] ), .B0 (n_2603), .Y + (n_4825)); + DFFX1 u2_suspended_reg(.CK (clk_i), .D (n_5630), .Q (suspended_o), + .QN ()); + INVX1 g36757(.A (o7_status), .Y (n_5400)); + DFFX1 \u10_status_reg[0] (.CK (clk_i), .D (n_3561), .Q (i4_status), + .QN ()); + INVX1 g36761(.A (o3_status), .Y (n_5398)); + INVX1 g36764(.A (o4_status), .Y (n_5396)); + INVX1 g36770(.A (o8_status), .Y (n_5394)); + DFFX1 \u9_status_reg[0] (.CK (clk_i), .D (n_3563), .Q (i3_status), + .QN ()); + NAND2X1 g36814(.A (n_1862), .B (n_3893), .Y (n_4824)); + NAND2X1 g36820(.A (n_1840), .B (n_2555), .Y (n_4823)); + NAND2X1 g36825(.A (n_1657), .B (n_2554), .Y (n_4822)); + NAND2X1 g36832(.A (n_2527), .B (n_3892), .Y (n_4821)); + NOR2X1 g36856(.A (n_5418), .B (n_6594), .Y (n_4820)); + NOR2X1 g36858(.A (n_5422), .B (n_6594), .Y (n_4819)); + NAND2X1 g36877(.A (n_2551), .B (n_2548), .Y (n_4818)); + NAND2X1 g36892(.A (n_2628), .B (n_1241), .Y (n_4817)); + NAND2X1 g36901(.A (n_2547), .B (n_1239), .Y (n_4816)); + NAND2X1 g36909(.A (n_2540), .B (n_2537), .Y (n_4815)); + NAND2X1 g36922(.A (n_2543), .B (n_1252), .Y (n_4814)); + NAND2X1 g36933(.A (n_2532), .B (n_1237), .Y (n_4813)); + NAND2X1 g36936(.A (n_2531), .B (n_1236), .Y (n_4812)); + NAND2X1 g36943(.A (n_2529), .B (n_1317), .Y (n_4811)); + NAND2X1 g36946(.A (n_2528), .B (n_1235), .Y (n_4810)); + NAND2X1 g36949(.A (n_2526), .B (n_1612), .Y (n_4809)); + NAND2X1 g36952(.A (n_2525), .B (n_2523), .Y (n_4808)); + NAND2X1 g37015(.A (n_2535), .B (n_2510), .Y (n_4807)); + NAND2X1 g37057(.A (n_2536), .B (n_1295), .Y (n_4806)); + NOR2X1 g37072(.A (n_3875), .B (n_2368), .Y (n_4805)); + NOR2X1 g37124(.A (n_5413), .B (n_6649), .Y (n_4804)); + NOR2X1 g37125(.A (n_5410), .B (n_6649), .Y (n_4803)); + NOR2X1 g37135(.A (n_3560), .B (n_12823), .Y (n_5942)); + NAND2X1 g37154(.A (n_2552), .B (n_2303), .Y (n_6017)); + NAND2X1 g37156(.A (n_2521), .B (n_2236), .Y (n_5997)); + NAND2X1 g37168(.A (n_2520), .B (n_2268), .Y (n_6014)); + NAND2X1 g37170(.A (n_2519), .B (n_2261), .Y (n_6011)); + NAND2X1 g37171(.A (n_2516), .B (n_2197), .Y (n_5987)); + NAND2X1 g37173(.A (n_2511), .B (n_2359), .Y (n_6008)); + NAND2X1 g37176(.A (n_2517), .B (n_2922), .Y (n_5993)); + NAND2X1 g37183(.A (n_3894), .B (n_3020), .Y (n_5983)); + NAND2X1 g37191(.A (n_2533), .B (n_2239), .Y (n_6003)); + XOR2X1 g37197(.A (n_1419), .B (n_4801), .Y (n_4802)); + XOR2X1 g37201(.A (n_1417), .B (n_4799), .Y (n_4800)); + XOR2X1 g37203(.A (n_1421), .B (n_4797), .Y (n_12838)); + XOR2X1 g37205(.A (n_1424), .B (n_4795), .Y (n_4796)); + MX2X1 g37207(.A (\u9_mem[1]_140 ), .B (n_4776), .S0 (n_4783), .Y + (n_4794)); + MX2X1 g37212(.A (\u10_mem[2]_108 ), .B (n_4745), .S0 (n_5424), .Y + (n_4793)); + MX2X1 g37217(.A (\u10_mem[1]_146 ), .B (n_4751), .S0 (n_6475), .Y + (n_4792)); + MX2X1 g37218(.A (\u9_mem[1]_138 ), .B (n_4778), .S0 (n_5730), .Y + (n_4791)); + MX2X1 g37219(.A (\u9_mem[1]_139 ), .B (n_4747), .S0 (n_5730), .Y + (n_4790)); + MX2X1 g37220(.A (\u9_mem[1]_141 ), .B (n_4757), .S0 (n_4783), .Y + (n_4789)); + MX2X1 g37221(.A (\u9_mem[1]_143 ), .B (n_4755), .S0 (n_4783), .Y + (n_4788)); + MX2X1 g37222(.A (\u9_mem[1]_145 ), .B (n_4743), .S0 (n_4783), .Y + (n_4786)); + MX2X1 g37223(.A (\u9_mem[1]_146 ), .B (n_4772), .S0 (n_4783), .Y + (n_4785)); + MX2X1 g37224(.A (\u9_mem[1]_147 ), .B (n_4769), .S0 (n_4783), .Y + (n_4784)); + MX2X1 g37225(.A (\u9_mem[1]_148 ), .B (n_4764), .S0 (n_4783), .Y + (n_4782)); + MX2X1 g37226(.A (\u9_mem[1]_149 ), .B (n_4767), .S0 (n_5730), .Y + (n_4781)); + MX2X1 g37227(.A (\u10_mem[1]_145 ), .B (n_4759), .S0 (n_5407), .Y + (n_4780)); + MX2X1 g37228(.A (\u9_mem[2]_107 ), .B (n_4778), .S0 (n_6898), .Y + (n_4779)); + MX2X1 g37229(.A (\u9_mem[2]_109 ), .B (n_4776), .S0 (n_5732), .Y + (n_4777)); + MX2X1 g37230(.A (\u9_mem[2]_111 ), .B (n_4753), .S0 (n_5732), .Y + (n_4775)); + MX2X1 g37231(.A (\u9_mem[2]_113 ), .B (n_4749), .S0 (n_6898), .Y + (n_4774)); + MX2X1 g37232(.A (\u9_mem[2]_115 ), .B (n_4772), .S0 (n_6898), .Y + (n_4773)); + MX2X1 g37233(.A (\u9_mem[2]_116 ), .B (n_4769), .S0 (n_6898), .Y + (n_4770)); + MX2X1 g37234(.A (\u9_mem[2]_118 ), .B (n_4767), .S0 (n_6898), .Y + (n_4768)); + MX2X1 g37235(.A (\u10_mem[1]_144 ), .B (n_4761), .S0 (n_5407), .Y + (n_4766)); + MX2X1 g37241(.A (\u9_mem[2]_117 ), .B (n_4764), .S0 (n_6898), .Y + (n_4765)); + MX2X1 g37260(.A (\u10_mem[2]_113 ), .B (n_4761), .S0 (n_5341), .Y + (n_4762)); + MX2X1 g37267(.A (\u10_mem[2]_114 ), .B (n_4759), .S0 (n_5341), .Y + (n_4760)); + MX2X1 g37268(.A (\u9_mem[2]_110 ), .B (n_4757), .S0 (n_6898), .Y + (n_4758)); + MX2X1 g37269(.A (\u9_mem[2]_112 ), .B (n_4755), .S0 (n_5732), .Y + (n_4756)); + MX2X1 g37271(.A (\u9_mem[1]_142 ), .B (n_4753), .S0 (n_4783), .Y + (n_4754)); + MX2X1 g37274(.A (\u10_mem[2]_115 ), .B (n_4751), .S0 (n_5341), .Y + (n_4752)); + MX2X1 g37276(.A (\u9_mem[1]_144 ), .B (n_4749), .S0 (n_5730), .Y + (n_4750)); + MX2X1 g37279(.A (\u9_mem[2]_108 ), .B (n_4747), .S0 (n_6898), .Y + (n_4748)); + MX2X1 g37307(.A (\u10_mem[1]_139 ), .B (n_4745), .S0 (n_6475), .Y + (n_4746)); + MX2X1 g37313(.A (\u9_mem[2]_114 ), .B (n_4743), .S0 (n_5732), .Y + (n_4744)); + AOI22X1 g37315(.A0 (n_4729), .A1 (n_1481), .B0 (n_5591), .B1 + (n_11564), .Y (n_4742)); + AOI22X1 g37317(.A0 (n_4729), .A1 (oc5_cfg_1015), .B0 (n_5591), .B1 + (n_4738), .Y (n_4741)); + AOI22X1 g37318(.A0 (n_4729), .A1 (n_8199), .B0 (n_5591), .B1 + (n_4736), .Y (n_4737)); + AOI22X1 g37319(.A0 (n_4729), .A1 (n_8197), .B0 (n_5591), .B1 + (n_4734), .Y (n_4735)); + AOI22X1 g37321(.A0 (n_5591), .A1 (n_11772), .B0 (n_6972), .B1 + (n_997), .Y (n_4733)); + AOI22X1 g37322(.A0 (n_5272), .A1 (\u13_intm_r[17] ), .B0 + (\u13_ints_r[17] ), .B1 (n_4726), .Y (n_4731)); + AOI22X1 g37324(.A0 (n_4729), .A1 (oc4_cfg_1004), .B0 (n_5591), .B1 + (ic0_cfg_1024), .Y (n_4730)); + AOI22X1 g37326(.A0 (n_5277), .A1 (crac_out_865), .B0 (n_6972), .B1 + (oc2_cfg_987), .Y (n_4728)); + AOI22X1 g37327(.A0 (n_5272), .A1 (\u13_intm_r[20] ), .B0 + (\u13_ints_r[20] ), .B1 (n_4726), .Y (n_4727)); + INVX1 g37328(.A (n_3991), .Y (n_4725)); + AOI22X1 g37330(.A0 (n_5272), .A1 (\u13_intm_r[21] ), .B0 + (\u13_ints_r[21] ), .B1 (n_4726), .Y (n_4724)); + INVX1 g37331(.A (n_3989), .Y (n_4723)); + AOI22X1 g37333(.A0 (n_5272), .A1 (\u13_intm_r[22] ), .B0 + (\u13_ints_r[22] ), .B1 (n_4726), .Y (n_4722)); + AOI22X1 g37334(.A0 (n_5272), .A1 (\u13_intm_r[16] ), .B0 + (\u13_ints_r[16] ), .B1 (n_4726), .Y (n_4721)); + INVX1 g37335(.A (n_3986), .Y (n_4720)); + AOI22X1 g37337(.A0 (n_5272), .A1 (\u13_intm_r[24] ), .B0 (n_6972), + .B1 (n_1873), .Y (n_4719)); + AOI22X1 g37338(.A0 (n_5272), .A1 (\u13_intm_r[25] ), .B0 (n_6972), + .B1 (oc3_cfg_994), .Y (n_4718)); + AOI22X1 g37341(.A0 (n_5272), .A1 (\u13_intm_r[28] ), .B0 (n_6972), + .B1 (oc3_cfg_997), .Y (n_4716)); + AOI22X1 g37343(.A0 (n_4729), .A1 (n_4714), .B0 (n_5591), .B1 + (n_4713), .Y (n_4715)); + AOI22X1 g37346(.A0 (n_4729), .A1 (n_4711), .B0 (n_5591), .B1 + (n_4710), .Y (n_4712)); + AOI22X1 g37348(.A0 (n_4729), .A1 (n_8190), .B0 (n_5591), .B1 + (n_4708), .Y (n_4709)); + AOI22X1 g37349(.A0 (n_5591), .A1 (n_4706), .B0 (n_6972), .B1 + (oc2_cfg_986), .Y (n_4707)); + AOI22X1 g37351(.A0 (n_4729), .A1 (n_8188), .B0 (n_5591), .B1 + (n_4703), .Y (n_4704)); + AOI22X1 g37353(.A0 (n_4729), .A1 (n_4701), .B0 (n_5591), .B1 + (n_4699), .Y (n_4702)); + AOI22X1 g37355(.A0 (n_4729), .A1 (oc4_cfg_1010), .B0 (n_5591), .B1 + (ic0_cfg_1030), .Y (n_4698)); + AOI22X1 g37357(.A0 (n_4729), .A1 (n_8182), .B0 (n_5591), .B1 + (n_11600), .Y (n_4697)); + AOI22X1 g37359(.A0 (n_4729), .A1 (oc5_cfg_1014), .B0 (n_5591), .B1 + (ic1_cfg_1034), .Y (n_4695)); + AOI22X1 g37362(.A0 (n_5272), .A1 (\u13_intm_r[18] ), .B0 + (\u13_ints_r[18] ), .B1 (n_4726), .Y (n_4694)); + AOI22X1 g37363(.A0 (n_4729), .A1 (oc5_cfg_1020), .B0 (n_5591), .B1 + (ic1_cfg_1040), .Y (n_4693)); + AOI22X1 g37366(.A0 (n_4729), .A1 (oc5_cfg_1016), .B0 (n_5591), .B1 + (n_4690), .Y (n_4692)); + AOI22X1 g37369(.A0 (n_4729), .A1 (n_4688), .B0 (n_5591), .B1 + (n_4687), .Y (n_4689)); + AOI22X1 g37370(.A0 (n_5272), .A1 (\u13_intm_r[19] ), .B0 + (\u13_ints_r[19] ), .B1 (n_4726), .Y (n_4686)); + AOI22X1 g37373(.A0 (n_5591), .A1 (n_4683), .B0 (n_6972), .B1 + (oc2_cfg_985), .Y (n_4685)); + INVX1 g37374(.A (n_3983), .Y (n_4681)); + INVX1 g37414(.A (n_3943), .Y (n_4680)); + INVX1 g37416(.A (n_3945), .Y (n_4679)); + BUFX3 g37441(.A (n_7297), .Y (n_7468)); + NAND2X1 g37475(.A (n_5480), .B (n_2918), .Y (n_4677)); + CLKBUFX3 g37480(.A (n_4676), .Y (n_6700)); + NOR2X1 g37484(.A (n_5317), .B (n_6649), .Y (n_4675)); + NAND2X1 g37486(.A (n_5480), .B (n_2895), .Y (n_4673)); + NAND2X1 g37487(.A (n_5480), .B (n_3470), .Y (n_4672)); + NAND2X1 g37488(.A (n_5480), .B (n_3420), .Y (n_4671)); + NAND2X1 g37489(.A (n_5480), .B (n_3363), .Y (n_4670)); + NAND2X1 g37490(.A (n_5480), .B (n_3138), .Y (n_4669)); + NAND2X1 g37491(.A (n_5480), .B (n_3275), .Y (n_4668)); + NAND2X1 g37493(.A (n_5480), .B (n_3137), .Y (n_4667)); + NOR2X1 g37497(.A (n_5292), .B (n_6594), .Y (n_4666)); + NAND2X1 g37499(.A (n_6972), .B (n_8536), .Y (n_4665)); + NOR2X1 g37500(.A (n_5290), .B (n_6594), .Y (n_4664)); + NOR2X1 g37501(.A (n_5282), .B (n_6594), .Y (n_4663)); + NAND2X1 g37502(.A (n_6972), .B (oc3_cfg_999), .Y (n_4662)); + NOR2X1 g37503(.A (n_5287), .B (n_6594), .Y (n_4661)); + NOR2X1 g37504(.A (n_5355), .B (n_6594), .Y (n_4660)); + NAND2X1 g37507(.A (n_5480), .B (n_3092), .Y (n_4659)); + NOR2X1 g37509(.A (n_5284), .B (n_6594), .Y (n_4658)); + NOR2X1 g37510(.A (n_5330), .B (n_6594), .Y (n_4656)); + NOR2X1 g37511(.A (n_5339), .B (n_6594), .Y (n_4655)); + NOR2X1 g37515(.A (n_5315), .B (n_6649), .Y (n_4654)); + NAND2X1 g37528(.A (n_5645), .B (n_2968), .Y (n_4653)); + NOR2X1 g37529(.A (n_5309), .B (n_6649), .Y (n_4652)); + NOR2X1 g37531(.A (n_5313), .B (n_6649), .Y (n_4651)); + NOR2X1 g37532(.A (n_5304), .B (n_6649), .Y (n_4650)); + NOR2X1 g37535(.A (n_5280), .B (n_6649), .Y (n_4649)); + NAND2X1 g37537(.A (n_5645), .B (n_3061), .Y (n_4648)); + NAND2X1 g37538(.A (n_5480), .B (n_2989), .Y (n_4647)); + NAND2X1 g37546(.A (n_5480), .B (n_3492), .Y (n_4646)); + OAI21X1 g37550(.A0 (n_1205), .A1 (\u5_rp[3] ), .B0 (n_4644), .Y + (n_4645)); + NOR2X1 g37552(.A (n_5296), .B (n_6649), .Y (n_4643)); + NAND2X1 g37559(.A (n_5645), .B (n_2994), .Y (n_4642)); + NAND2X1 g37568(.A (n_5645), .B (n_2886), .Y (n_4641)); + NOR2X1 g37570(.A (n_5307), .B (n_6649), .Y (n_4640)); + NAND2X1 g37579(.A (n_5480), .B (n_3060), .Y (n_4639)); + NOR2X1 g37583(.A (n_5335), .B (n_6649), .Y (n_4638)); + NOR2X1 g37584(.A (n_5321), .B (n_6649), .Y (n_4637)); + NOR2X1 g37585(.A (n_5298), .B (n_6649), .Y (n_4636)); + NOR2X1 g37586(.A (n_5300), .B (n_6649), .Y (n_4635)); + AND2X1 g37592(.A (n_3549), .B (n_4633), .Y (n_4634)); + NAND2X1 g37606(.A (n_3554), .B (n_3497), .Y (n_4632)); + NAND2X1 g37607(.A (n_3521), .B (n_3436), .Y (n_4631)); + NAND2X1 g37608(.A (n_2461), .B (n_2640), .Y (n_4630)); + AOI22X1 g37609(.A0 (in_slt_414), .A1 (n_4623), .B0 (in_slt_402), .B1 + (n_2368), .Y (n_5736)); + NAND2X1 g37611(.A (n_2421), .B (n_3494), .Y (n_4629)); + NAND2X1 g37619(.A (n_2460), .B (n_2638), .Y (n_4628)); + NAND2X1 g37654(.A (n_2459), .B (n_2636), .Y (n_4627)); + AOI22X1 g37660(.A0 (in_slt_412), .A1 (n_1406), .B0 (in_slt_414), .B1 + (n_4624), .Y (n_4626)); + AOI22X1 g37661(.A0 (in_slt_413), .A1 (n_1406), .B0 (in_slt_415), .B1 + (n_4624), .Y (n_4625)); + AOI22X1 g37662(.A0 (in_slt_415), .A1 (n_4623), .B0 (in_slt_403), .B1 + (n_2368), .Y (n_5733)); + AOI22X1 g37663(.A0 (in_slt_397), .A1 (n_1406), .B0 (u9_din_tmp_42), + .B1 (n_2368), .Y (n_4621)); + AOI22X1 g37666(.A0 (in_slt_398), .A1 (n_1406), .B0 (u9_din_tmp_43), + .B1 (n_2368), .Y (n_4619)); + AOI22X1 g37667(.A0 (in_slt_399), .A1 (n_4623), .B0 (u9_din_tmp_44), + .B1 (n_4616), .Y (n_4618)); + AOI22X1 g37668(.A0 (in_slt_400), .A1 (n_1406), .B0 (u9_din_tmp_45), + .B1 (n_4616), .Y (n_4617)); + AOI22X1 g37670(.A0 (in_slt_402), .A1 (n_1406), .B0 (u9_din_tmp_47), + .B1 (n_4616), .Y (n_4615)); + AOI22X1 g37672(.A0 (in_slt_403), .A1 (n_1406), .B0 (u9_din_tmp_48), + .B1 (n_4616), .Y (n_4614)); + AOI22X1 g37674(.A0 (n_3415), .A1 (in_slt_407), .B0 (n_1406), .B1 + (in_slt_405), .Y (n_4613)); + NAND2X1 g37677(.A (n_2374), .B (n_2863), .Y (n_4611)); + NAND2X1 g37681(.A (n_2411), .B (n_3283), .Y (n_4610)); + NAND2X1 g37683(.A (n_2607), .B (n_3401), .Y (n_4609)); + NAND2X1 g37686(.A (n_3552), .B (n_3394), .Y (n_4608)); + NAND2X1 g37693(.A (n_3531), .B (n_3367), .Y (n_4607)); + NAND2X1 g37696(.A (n_3551), .B (n_3297), .Y (n_4606)); + AOI22X1 g37706(.A0 (in_slt3), .A1 (n_1406), .B0 (u9_din_tmp1), .B1 + (n_2368), .Y (n_4605)); + NAND2X1 g37709(.A (n_3550), .B (n_3328), .Y (n_4603)); + NAND2X1 g37710(.A (n_2425), .B (n_3080), .Y (n_12051)); + NAND2X1 g37722(.A (n_2923), .B (n_3159), .Y (n_4601)); + NAND2X1 g37724(.A (n_2446), .B (n_2981), .Y (n_4600)); + NAND2X1 g37737(.A (n_3264), .B (n_2889), .Y (n_4599)); + NAND2X1 g37740(.A (n_3069), .B (n_3846), .Y (n_4598)); + NAND2X1 g37744(.A (n_3176), .B (n_3071), .Y (n_4597)); + NAND2X1 g37746(.A (n_3240), .B (n_3238), .Y (n_4596)); + NAND2X1 g37748(.A (n_3555), .B (n_3493), .Y (n_4595)); + NAND2X1 g37750(.A (n_3130), .B (n_3231), .Y (n_4594)); + NAND2X1 g37752(.A (n_3528), .B (n_2235), .Y (n_4593)); + NAND2X1 g37753(.A (n_3087), .B (n_3224), .Y (n_4592)); + NAND2X1 g37757(.A (n_3274), .B (n_2982), .Y (n_4591)); + NAND2X1 g37758(.A (n_3536), .B (n_2312), .Y (n_4590)); + NAND2X1 g37759(.A (n_3215), .B (n_3214), .Y (n_4589)); + NAND2X1 g37764(.A (n_3538), .B (n_2983), .Y (n_12850)); + NAND2X1 g37770(.A (n_3527), .B (n_2297), .Y (n_4587)); + NAND2X1 g37778(.A (n_3537), .B (n_2897), .Y (n_4586)); + NAND2X1 g37782(.A (n_2403), .B (n_3038), .Y (n_12061)); + AOI22X1 g37783(.A0 (in_slt_401), .A1 (n_1406), .B0 (u9_din_tmp_46), + .B1 (n_2368), .Y (n_4584)); + NAND2X1 g37797(.A (n_2429), .B (n_2908), .Y (n_12055)); + NAND2X1 g37806(.A (n_3544), .B (n_2258), .Y (n_4581)); + NAND2X1 g37835(.A (n_3016), .B (n_3360), .Y (n_4580)); + NAND2X1 g37849(.A (n_2466), .B (n_3094), .Y (n_12057)); + NAND2X1 g37853(.A (n_2448), .B (n_2955), .Y (n_12049)); + NAND2X1 g37859(.A (n_2440), .B (n_3424), .Y (n_12053)); + NAND2X1 g37863(.A (n_2388), .B (n_3480), .Y (n_4576)); + NAND2X1 g37868(.A (n_2458), .B (n_3468), .Y (n_12059)); + NAND2X1 g37872(.A (n_2400), .B (n_3084), .Y (n_4574)); + NAND2X1 g37875(.A (n_2462), .B (n_3054), .Y (n_4573)); + NAND2X1 g37877(.A (n_2418), .B (n_3051), .Y (n_4572)); + NAND2X1 g37883(.A (n_2385), .B (n_3144), .Y (n_4571)); + NAND2X1 g37887(.A (n_3545), .B (n_2496), .Y (n_4570)); + NAND2X1 g37903(.A (n_3557), .B (n_3013), .Y (n_4569)); + NAND2X1 g37907(.A (n_3530), .B (n_3109), .Y (n_4568)); + AOI22X1 g37910(.A0 (u11_din_tmp_45), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_446), .Y (n_4567)); + AOI22X1 g37911(.A0 (u11_din_tmp_46), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_447), .Y (n_4566)); + AOI22X1 g37913(.A0 (u11_din_tmp_47), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_448), .Y (n_4565)); + AOI22X1 g37917(.A0 (u11_din_tmp_48), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_449), .Y (n_4563)); + AOI22X1 g37919(.A0 (u11_din_tmp_49), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_450), .Y (n_4561)); + AOI22X1 g37923(.A0 (u10_din_tmp_43), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_422), .Y (n_4559)); + AOI22X1 g37929(.A0 (u10_din_tmp_44), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_423), .Y (n_4558)); + AOI22X1 g37933(.A0 (u10_din_tmp_45), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_424), .Y (n_4557)); + AOI22X1 g37938(.A0 (u10_din_tmp_48), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_427), .Y (n_4555)); + NAND2X1 g37949(.A (n_2389), .B (n_2367), .Y (n_4553)); + NAND2X1 g37967(.A (n_2383), .B (n_2301), .Y (n_4552)); + NAND2X1 g37971(.A (n_2410), .B (n_1915), .Y (n_4551)); + AOI22X1 g37986(.A0 (u10_din_tmp_47), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_426), .Y (n_4550)); + AOI21X1 g37991(.A0 (\u6_mem[2]_56 ), .A1 (n_4544), .B0 (n_2223), .Y + (n_4547)); + AOI21X1 g37994(.A0 (\u7_mem[2]_31 ), .A1 (n_4540), .B0 (n_2021), .Y + (n_4546)); + AOI21X1 g37995(.A0 (\u6_mem[2]_55 ), .A1 (n_4544), .B0 (n_2082), .Y + (n_4545)); + AOI21X1 g37997(.A0 (\u6_mem[2]_54 ), .A1 (n_4504), .B0 (n_2162), .Y + (n_4543)); + AOI21X1 g37999(.A0 (\u5_mem[2]_41 ), .A1 (n_4378), .B0 (n_1838), .Y + (n_4542)); + AOI21X1 g38003(.A0 (\u7_mem[2]_58 ), .A1 (n_4540), .B0 (n_2222), .Y + (n_4541)); + AOI21X1 g38005(.A0 (\u6_mem[2]_52 ), .A1 (n_4544), .B0 (n_2219), .Y + (n_4539)); + AOI21X1 g38010(.A0 (\u7_mem[2]_30 ), .A1 (n_4540), .B0 (n_2203), .Y + (n_4538)); + AOI21X1 g38012(.A0 (\u3_mem[2] ), .A1 (n_4533), .B0 (n_2105), .Y + (n_4537)); + AOI21X1 g38013(.A0 (\u7_mem[2]_57 ), .A1 (n_4540), .B0 (n_2217), .Y + (n_4536)); + AOI21X1 g38015(.A0 (\u6_mem[2]_50 ), .A1 (n_4544), .B0 (n_2186), .Y + (n_4535)); + AOI21X1 g38016(.A0 (\u3_mem[2]_39 ), .A1 (n_4533), .B0 (n_2075), .Y + (n_4534)); + AOI21X1 g38017(.A0 (\u3_mem[2]_40 ), .A1 (n_4533), .B0 (n_2127), .Y + (n_4532)); + AOI21X1 g38018(.A0 (\u6_mem[2]_49 ), .A1 (n_4544), .B0 (n_1800), .Y + (n_4531)); + AOI21X1 g38019(.A0 (\u8_mem[2]_37 ), .A1 (n_4499), .B0 (n_2196), .Y + (n_4530)); + AOI21X1 g38020(.A0 (\u7_mem[2]_55 ), .A1 (n_4509), .B0 (n_1948), .Y + (n_4529)); + AOI21X1 g38021(.A0 (\u3_mem[2]_43 ), .A1 (n_4533), .B0 (n_2079), .Y + (n_4528)); + AOI21X1 g38024(.A0 (\u8_mem[1]_90 ), .A1 (n_4502), .B0 (n_2351), .Y + (n_4527)); + AOI21X1 g38025(.A0 (\u3_mem[2]_29 ), .A1 (n_4533), .B0 (n_1963), .Y + (n_4526)); + AOI21X1 g38027(.A0 (\u6_mem[2]_48 ), .A1 (n_4544), .B0 (n_2211), .Y + (n_4525)); + AOI21X1 g38030(.A0 (\u3_mem[2]_50 ), .A1 (n_4533), .B0 (n_2147), .Y + (n_4524)); + AOI21X1 g38032(.A0 (\u6_mem[2]_47 ), .A1 (n_4544), .B0 (n_2319), .Y + (n_4523)); + AOI21X1 g38033(.A0 (\u3_mem[2]_54 ), .A1 (n_4519), .B0 (n_1971), .Y + (n_4522)); + AOI21X1 g38035(.A0 (\u3_mem[2]_56 ), .A1 (n_4533), .B0 (n_2195), .Y + (n_4521)); + AOI21X1 g38036(.A0 (\u3_mem[2]_57 ), .A1 (n_4519), .B0 (n_2263), .Y + (n_4520)); + AOI21X1 g38037(.A0 (\u3_mem[2]_30 ), .A1 (n_4519), .B0 (n_2130), .Y + (n_4518)); + AOI21X1 g38038(.A0 (\u3_mem[2]_36 ), .A1 (n_4519), .B0 (n_2032), .Y + (n_4517)); + AOI21X1 g38039(.A0 (\u7_mem[2]_51 ), .A1 (n_4540), .B0 (n_1967), .Y + (n_4516)); + AOI21X1 g38040(.A0 (\u6_mem[2]_46 ), .A1 (n_4544), .B0 (n_2234), .Y + (n_4515)); + AOI21X1 g38041(.A0 (\u4_mem[1]_88 ), .A1 (n_4507), .B0 (n_1999), .Y + (n_4514)); + AOI21X1 g38043(.A0 (\u3_mem[2]_34 ), .A1 (n_4519), .B0 (n_2141), .Y + (n_4513)); + AOI21X1 g38044(.A0 (\u3_mem[2]_35 ), .A1 (n_4519), .B0 (n_1941), .Y + (n_4512)); + AOI21X1 g38045(.A0 (\u3_mem[2]_37 ), .A1 (n_4519), .B0 (n_2027), .Y + (n_4511)); + AOI21X1 g38047(.A0 (\u7_mem[2]_49 ), .A1 (n_4509), .B0 (n_1945), .Y + (n_4510)); + AOI21X1 g38048(.A0 (\u4_mem[1]_87 ), .A1 (n_4507), .B0 (n_2146), .Y + (n_4508)); + AOI21X1 g38050(.A0 (\u7_mem[2]_50 ), .A1 (n_4540), .B0 (n_2199), .Y + (n_4506)); + AOI21X1 g38054(.A0 (\u6_mem[2]_45 ), .A1 (n_4504), .B0 (n_2030), .Y + (n_4505)); + AOI21X1 g38058(.A0 (\u8_mem[1]_64 ), .A1 (n_4502), .B0 (n_1920), .Y + (n_4503)); + AOI21X1 g38060(.A0 (\u7_mem[2]_48 ), .A1 (n_4509), .B0 (n_1964), .Y + (n_4501)); + AOI21X1 g38062(.A0 (\u8_mem[2]_45 ), .A1 (n_4499), .B0 (n_2004), .Y + (n_4500)); + AOI21X1 g38063(.A0 (\u6_mem[2]_43 ), .A1 (n_4504), .B0 (n_1984), .Y + (n_4498)); + AOI21X1 g38067(.A0 (\u8_mem[2]_44 ), .A1 (n_4499), .B0 (n_2153), .Y + (n_4497)); + AOI21X1 g38068(.A0 (\u7_mem[2]_29 ), .A1 (n_4540), .B0 (n_2001), .Y + (n_4496)); + AOI21X1 g38070(.A0 (\u8_mem[2]_43 ), .A1 (n_4491), .B0 (n_1884), .Y + (n_4495)); + AOI21X1 g38073(.A0 (\u8_mem[2]_42 ), .A1 (n_4499), .B0 (n_1993), .Y + (n_4494)); + AOI21X1 g38074(.A0 (\u8_mem[2]_36 ), .A1 (n_4499), .B0 (n_2183), .Y + (n_4493)); + AOI21X1 g38076(.A0 (\u8_mem[2]_35 ), .A1 (n_4491), .B0 (n_2160), .Y + (n_4492)); + AOI21X1 g38079(.A0 (\u8_mem[2]_34 ), .A1 (n_4499), .B0 (n_2174), .Y + (n_4490)); + AOI21X1 g38083(.A0 (\u8_mem[2]_33 ), .A1 (n_4491), .B0 (n_1805), .Y + (n_4489)); + AOI21X1 g38085(.A0 (\u6_mem[2]_41 ), .A1 (n_4504), .B0 (n_1952), .Y + (n_4488)); + AOI21X1 g38086(.A0 (\u8_mem[2]_32 ), .A1 (n_4499), .B0 (n_2165), .Y + (n_4487)); + AOI21X1 g38087(.A0 (\u3_mem[2]_46 ), .A1 (n_4533), .B0 (n_1983), .Y + (n_4486)); + AOI21X1 g38089(.A0 (\u8_mem[2]_31 ), .A1 (n_4491), .B0 (n_2149), .Y + (n_4485)); + AOI21X1 g38090(.A0 (\u3_mem[2]_45 ), .A1 (n_4533), .B0 (n_2072), .Y + (n_4484)); + AOI21X1 g38094(.A0 (\u8_mem[2]_59 ), .A1 (n_4499), .B0 (n_1982), .Y + (n_4483)); + AOI21X1 g38095(.A0 (\u8_mem[2]_58 ), .A1 (n_4491), .B0 (n_2159), .Y + (n_4482)); + AOI21X1 g38097(.A0 (\u7_mem[2]_52 ), .A1 (n_4540), .B0 (n_2104), .Y + (n_4481)); + AOI21X1 g38098(.A0 (\u3_mem[2]_59 ), .A1 (n_4533), .B0 (n_2108), .Y + (n_4480)); + AOI21X1 g38099(.A0 (\u8_mem[2]_30 ), .A1 (n_4491), .B0 (n_2002), .Y + (n_4479)); + AOI21X1 g38100(.A0 (\u4_mem[1]_83 ), .A1 (n_4471), .B0 (n_2115), .Y + (n_4478)); + AOI21X1 g38101(.A0 (\u8_mem[2]_57 ), .A1 (n_4499), .B0 (n_2138), .Y + (n_4477)); + AOI21X1 g38102(.A0 (\u6_mem[2]_40 ), .A1 (n_4504), .B0 (n_2136), .Y + (n_4476)); + AOI21X1 g38103(.A0 (\u4_mem[1]_75 ), .A1 (n_4507), .B0 (n_2065), .Y + (n_4475)); + AOI21X1 g38105(.A0 (\u3_mem[2]_49 ), .A1 (n_4519), .B0 (n_2191), .Y + (n_4474)); + AOI21X1 g38108(.A0 (\u4_mem[1] ), .A1 (n_4507), .B0 (n_2116), .Y + (n_4473)); + AOI21X1 g38109(.A0 (\u4_mem[1]_70 ), .A1 (n_4471), .B0 (n_2207), .Y + (n_4472)); + AOI21X1 g38110(.A0 (\u4_mem[1]_71 ), .A1 (n_4507), .B0 (n_1792), .Y + (n_4470)); + AOI21X1 g38111(.A0 (\u4_mem[1]_72 ), .A1 (n_4507), .B0 (n_2180), .Y + (n_4469)); + AOI21X1 g38112(.A0 (\u6_mem[2]_39 ), .A1 (n_4504), .B0 (n_2173), .Y + (n_4468)); + AOI21X1 g38113(.A0 (\u4_mem[1]_73 ), .A1 (n_4471), .B0 (n_1961), .Y + (n_4467)); + AOI21X1 g38114(.A0 (\u7_mem[2]_46 ), .A1 (n_4509), .B0 (n_2000), .Y + (n_4466)); + AOI21X1 g38115(.A0 (\u4_mem[1]_74 ), .A1 (n_4507), .B0 (n_1957), .Y + (n_4465)); + AOI21X1 g38116(.A0 (\u4_mem[1]_76 ), .A1 (n_4507), .B0 (n_1943), .Y + (n_4464)); + AOI21X1 g38117(.A0 (\u4_mem[1]_77 ), .A1 (n_4471), .B0 (n_2151), .Y + (n_4463)); + AOI21X1 g38118(.A0 (\u4_mem[1]_78 ), .A1 (n_4471), .B0 (n_2161), .Y + (n_4462)); + AOI21X1 g38120(.A0 (\u4_mem[1]_60 ), .A1 (n_4507), .B0 (n_2184), .Y + (n_4461)); + AOI21X1 g38121(.A0 (\u4_mem[1]_79 ), .A1 (n_4471), .B0 (n_2208), .Y + (n_4460)); + AOI21X1 g38122(.A0 (\u4_mem[1]_80 ), .A1 (n_4507), .B0 (n_2063), .Y + (n_4459)); + AOI21X1 g38124(.A0 (\u4_mem[1]_81 ), .A1 (n_4471), .B0 (n_2061), .Y + (n_4458)); + AOI21X1 g38125(.A0 (\u6_mem[2]_32 ), .A1 (n_4544), .B0 (n_2094), .Y + (n_4457)); + AOI21X1 g38126(.A0 (\u4_mem[1]_82 ), .A1 (n_4471), .B0 (n_2070), .Y + (n_4456)); + AOI21X1 g38127(.A0 (\u4_mem[1]_84 ), .A1 (n_4471), .B0 (n_2113), .Y + (n_4455)); + AOI21X1 g38128(.A0 (\u4_mem[1]_85 ), .A1 (n_4507), .B0 (n_1962), .Y + (n_4454)); + AOI21X1 g38130(.A0 (\u4_mem[1]_86 ), .A1 (n_4507), .B0 (n_2074), .Y + (n_4453)); + AOI21X1 g38131(.A0 (\u7_mem[2]_44 ), .A1 (n_4509), .B0 (n_2168), .Y + (n_4452)); + AOI21X1 g38133(.A0 (\u4_mem[1]_61 ), .A1 (n_4507), .B0 (n_2140), .Y + (n_4451)); + AOI21X1 g38135(.A0 (\u4_mem[1]_89 ), .A1 (n_4507), .B0 (n_2471), .Y + (n_4450)); + AOI21X1 g38136(.A0 (\u4_mem[1]_90 ), .A1 (n_4471), .B0 (n_2123), .Y + (n_4449)); + AOI21X1 g38137(.A0 (\u4_mem[1]_62 ), .A1 (n_4471), .B0 (n_2483), .Y + (n_4448)); + AOI21X1 g38138(.A0 (\u4_mem[1]_63 ), .A1 (n_4471), .B0 (n_2109), .Y + (n_4447)); + AOI21X1 g38139(.A0 (\u4_mem[1]_64 ), .A1 (n_4471), .B0 (n_2047), .Y + (n_4446)); + AOI21X1 g38140(.A0 (\u4_mem[1]_66 ), .A1 (n_4471), .B0 (n_1940), .Y + (n_4445)); + AOI21X1 g38141(.A0 (\u4_mem[1]_67 ), .A1 (n_4471), .B0 (n_1958), .Y + (n_4444)); + AOI21X1 g38142(.A0 (\u6_mem[2] ), .A1 (n_4544), .B0 (n_2023), .Y + (n_4443)); + AOI21X1 g38143(.A0 (\u4_mem[2] ), .A1 (n_4439), .B0 (n_2106), .Y + (n_4442)); + AOI21X1 g38144(.A0 (\u4_mem[2]_38 ), .A1 (n_4439), .B0 (n_1947), .Y + (n_4441)); + AOI21X1 g38145(.A0 (\u4_mem[2]_39 ), .A1 (n_4439), .B0 (n_2129), .Y + (n_4440)); + AOI21X1 g38146(.A0 (\u4_mem[2]_41 ), .A1 (n_4439), .B0 (n_2170), .Y + (n_4438)); + AOI21X1 g38147(.A0 (\u4_mem[2]_42 ), .A1 (n_4439), .B0 (n_2111), .Y + (n_4436)); + AOI21X1 g38148(.A0 (\u4_mem[2]_43 ), .A1 (n_4439), .B0 (n_2188), .Y + (n_4435)); + AOI21X1 g38149(.A0 (\u8_mem[2]_56 ), .A1 (n_4491), .B0 (n_1989), .Y + (n_4434)); + AOI21X1 g38150(.A0 (\u4_mem[2]_44 ), .A1 (n_4439), .B0 (n_2110), .Y + (n_4433)); + AOI21X1 g38152(.A0 (\u4_mem[2]_45 ), .A1 (n_4439), .B0 (n_1976), .Y + (n_4432)); + AOI21X1 g38154(.A0 (\u4_mem[2]_46 ), .A1 (n_4439), .B0 (n_2102), .Y + (n_4431)); + AOI21X1 g38155(.A0 (\u4_mem[2]_47 ), .A1 (n_4439), .B0 (n_1969), .Y + (n_4430)); + AOI21X1 g38156(.A0 (\u4_mem[2]_29 ), .A1 (n_4439), .B0 (n_1827), .Y + (n_4429)); + AOI21X1 g38158(.A0 (\u4_mem[2]_49 ), .A1 (n_4439), .B0 (n_1992), .Y + (n_4428)); + AOI21X1 g38159(.A0 (\u4_mem[2]_50 ), .A1 (n_4439), .B0 (n_1991), .Y + (n_4427)); + AOI21X1 g38160(.A0 (\u4_mem[2]_51 ), .A1 (n_4439), .B0 (n_2100), .Y + (n_4426)); + AOI21X1 g38161(.A0 (\u4_mem[2]_52 ), .A1 (n_4439), .B0 (n_1998), .Y + (n_4425)); + AOI21X1 g38162(.A0 (\u7_mem[2]_40 ), .A1 (n_4509), .B0 (n_1994), .Y + (n_4424)); + AOI21X1 g38163(.A0 (\u4_mem[2]_53 ), .A1 (n_4439), .B0 (n_2484), .Y + (n_4423)); + AOI21X1 g38164(.A0 (\u4_mem[2]_54 ), .A1 (n_4439), .B0 (n_2048), .Y + (n_4422)); + AOI21X1 g38166(.A0 (\u4_mem[2]_55 ), .A1 (n_4439), .B0 (n_1970), .Y + (n_4421)); + AOI21X1 g38167(.A0 (\u4_mem[2]_56 ), .A1 (n_4439), .B0 (n_2012), .Y + (n_4420)); + AOI21X1 g38169(.A0 (\u4_mem[2]_57 ), .A1 (n_4439), .B0 (n_2024), .Y + (n_4419)); + AOI21X1 g38170(.A0 (\u4_mem[2]_30 ), .A1 (n_4439), .B0 (n_2205), .Y + (n_4418)); + AOI21X1 g38171(.A0 (\u4_mem[2]_58 ), .A1 (n_4439), .B0 (n_2478), .Y + (n_4417)); + AOI21X1 g38172(.A0 (\u4_mem[2]_59 ), .A1 (n_4439), .B0 (n_1632), .Y + (n_4416)); + AOI21X1 g38173(.A0 (\u6_mem[2]_36 ), .A1 (n_4544), .B0 (n_2089), .Y + (n_4415)); + AOI21X1 g38174(.A0 (\u4_mem[2]_31 ), .A1 (n_4439), .B0 (n_2206), .Y + (n_4414)); + AOI21X1 g38175(.A0 (\u4_mem[2]_32 ), .A1 (n_4439), .B0 (n_2066), .Y + (n_4413)); + AOI21X1 g38176(.A0 (\u8_mem[1] ), .A1 (n_4502), .B0 (n_2091), .Y + (n_4412)); + AOI21X1 g38177(.A0 (\u4_mem[2]_33 ), .A1 (n_4439), .B0 (n_2077), .Y + (n_4411)); + AOI21X1 g38178(.A0 (\u4_mem[2]_34 ), .A1 (n_4439), .B0 (n_2372), .Y + (n_4410)); + AOI21X1 g38179(.A0 (\u4_mem[2]_35 ), .A1 (n_4439), .B0 (n_2095), .Y + (n_4409)); + AOI21X1 g38180(.A0 (\u4_mem[2]_36 ), .A1 (n_4439), .B0 (n_1973), .Y + (n_4408)); + AOI21X1 g38182(.A0 (\u4_mem[2]_37 ), .A1 (n_4439), .B0 (n_2209), .Y + (n_4407)); + AOI21X1 g38184(.A0 (\u7_mem[2]_38 ), .A1 (n_4540), .B0 (n_2087), .Y + (n_4406)); + AOI21X1 g38187(.A0 (\u6_mem[2]_35 ), .A1 (n_4504), .B0 (n_1673), .Y + (n_4405)); + AOI21X1 g38192(.A0 (\u7_mem[2] ), .A1 (n_4540), .B0 (n_2044), .Y + (n_4404)); + AOI21X1 g38197(.A0 (\u6_mem[2]_34 ), .A1 (n_4504), .B0 (n_2037), .Y + (n_4403)); + AOI21X1 g38205(.A0 (\u8_mem[1]_62 ), .A1 (n_4502), .B0 (n_2058), .Y + (n_4402)); + AOI21X1 g38209(.A0 (\u6_mem[2]_33 ), .A1 (n_4504), .B0 (n_2212), .Y + (n_4401)); + AOI21X1 g38210(.A0 (\u8_mem[1]_84 ), .A1 (n_4502), .B0 (n_2156), .Y + (n_4400)); + AOI21X1 g38233(.A0 (\u6_mem[2]_58 ), .A1 (n_4504), .B0 (n_1990), .Y + (n_4399)); + AOI21X1 g38235(.A0 (\u6_mem[2]_59 ), .A1 (n_4544), .B0 (n_2145), .Y + (n_4398)); + AOI21X1 g38237(.A0 (\u8_mem[1]_82 ), .A1 (n_4502), .B0 (n_2053), .Y + (n_4397)); + AOI21X1 g38239(.A0 (\u8_mem[2]_49 ), .A1 (n_4491), .B0 (n_2164), .Y + (n_4396)); + XOR2X1 g38240(.A (n_95), .B (n_5102), .Y (n_4395)); + AOI21X1 g38241(.A0 (\u3_mem[2]_31 ), .A1 (n_4533), .B0 (n_2131), .Y + (n_4394)); + AOI21X1 g38242(.A0 (\u8_mem[1]_89 ), .A1 (n_4387), .B0 (n_2005), .Y + (n_4393)); + AOI21X1 g38243(.A0 (\u3_mem[2]_58 ), .A1 (n_4519), .B0 (n_2086), .Y + (n_4392)); + AOI21X1 g38245(.A0 (\u8_mem[1]_73 ), .A1 (n_4502), .B0 (n_1988), .Y + (n_4391)); + AOI21X1 g38246(.A0 (\u8_mem[2]_51 ), .A1 (n_4499), .B0 (n_2062), .Y + (n_4390)); + XOR2X1 g38248(.A (n_1255), .B (n_5059), .Y (n_4389)); + AOI21X1 g38250(.A0 (\u8_mem[1]_71 ), .A1 (n_4387), .B0 (n_2028), .Y + (n_4388)); + AOI21X1 g38253(.A0 (\u8_mem[1]_80 ), .A1 (n_4387), .B0 (n_2073), .Y + (n_4386)); + AOI21X1 g38254(.A0 (\u8_mem[1]_60 ), .A1 (n_4387), .B0 (n_1981), .Y + (n_4385)); + AOI21X1 g38257(.A0 (\u3_mem[2]_42 ), .A1 (n_4519), .B0 (n_2014), .Y + (n_4384)); + AOI21X1 g38267(.A0 (\u8_mem[1]_77 ), .A1 (n_4387), .B0 (n_2051), .Y + (n_4383)); + AOI21X1 g38278(.A0 (\u8_mem[1]_86 ), .A1 (n_4387), .B0 (n_2214), .Y + (n_4382)); + AOI21X1 g38282(.A0 (\u4_mem[1]_69 ), .A1 (n_4471), .B0 (n_2142), .Y + (n_4381)); + AOI21X1 g38302(.A0 (\u8_mem[1]_75 ), .A1 (n_4387), .B0 (n_2215), .Y + (n_4380)); + AOI21X1 g38303(.A0 (\u5_mem[2] ), .A1 (n_4378), .B0 (n_2210), .Y + (n_4379)); + AOI21X1 g38305(.A0 (\u5_mem[2]_38 ), .A1 (n_4378), .B0 (n_1935), .Y + (n_4377)); + AOI21X1 g38306(.A0 (\u5_mem[2]_39 ), .A1 (n_4378), .B0 (n_2007), .Y + (n_4376)); + AOI21X1 g38307(.A0 (\u5_mem[2]_40 ), .A1 (n_4378), .B0 (n_2221), .Y + (n_4375)); + AOI21X1 g38309(.A0 (\u5_mem[2]_42 ), .A1 (n_4378), .B0 (n_1933), .Y + (n_4374)); + AOI21X1 g38310(.A0 (\u5_mem[2]_43 ), .A1 (n_4370), .B0 (n_2198), .Y + (n_4373)); + AOI21X1 g38311(.A0 (\u5_mem[2]_44 ), .A1 (n_4378), .B0 (n_2167), .Y + (n_4372)); + AOI21X1 g38312(.A0 (\u5_mem[2]_45 ), .A1 (n_4370), .B0 (n_2042), .Y + (n_4371)); + AOI21X1 g38313(.A0 (\u5_mem[2]_46 ), .A1 (n_4370), .B0 (n_2226), .Y + (n_4369)); + AOI21X1 g38314(.A0 (\u5_mem[2]_29 ), .A1 (n_4370), .B0 (n_2114), .Y + (n_4368)); + AOI21X1 g38315(.A0 (\u5_mem[2]_48 ), .A1 (n_4370), .B0 (n_2055), .Y + (n_4367)); + AOI21X1 g38316(.A0 (\u7_mem[2]_33 ), .A1 (n_4509), .B0 (n_2035), .Y + (n_4366)); + AOI21X1 g38317(.A0 (\u5_mem[2]_49 ), .A1 (n_4370), .B0 (n_1954), .Y + (n_4365)); + AOI21X1 g38318(.A0 (\u5_mem[2]_50 ), .A1 (n_4370), .B0 (n_2040), .Y + (n_4364)); + AOI21X1 g38320(.A0 (\u5_mem[2]_52 ), .A1 (n_4378), .B0 (n_2049), .Y + (n_4363)); + AOI21X1 g38321(.A0 (\u5_mem[2]_53 ), .A1 (n_4378), .B0 (n_1939), .Y + (n_4362)); + AOI21X1 g38322(.A0 (\u5_mem[2]_54 ), .A1 (n_4378), .B0 (n_2011), .Y + (n_4361)); + AOI21X1 g38323(.A0 (\u5_mem[2]_55 ), .A1 (n_4370), .B0 (n_1949), .Y + (n_4360)); + AOI21X1 g38324(.A0 (\u5_mem[2]_56 ), .A1 (n_4378), .B0 (n_1951), .Y + (n_4359)); + AOI21X1 g38325(.A0 (\u6_mem[2]_57 ), .A1 (n_4544), .B0 (n_1953), .Y + (n_4358)); + AOI21X1 g38326(.A0 (\u5_mem[2]_57 ), .A1 (n_4370), .B0 (n_2126), .Y + (n_4357)); + AOI21X1 g38327(.A0 (\u5_mem[2]_59 ), .A1 (n_4370), .B0 (n_2225), .Y + (n_4356)); + AOI21X1 g38329(.A0 (\u5_mem[2]_31 ), .A1 (n_4378), .B0 (n_2152), .Y + (n_4355)); + AOI21X1 g38332(.A0 (\u5_mem[2]_34 ), .A1 (n_4378), .B0 (n_2013), .Y + (n_4354)); + AOI21X1 g38333(.A0 (\u5_mem[2]_35 ), .A1 (n_4370), .B0 (n_2015), .Y + (n_4353)); + AOI21X1 g38334(.A0 (\u5_mem[2]_36 ), .A1 (n_4370), .B0 (n_2476), .Y + (n_4352)); + AOI21X1 g38336(.A0 (\u5_mem[2]_37 ), .A1 (n_4370), .B0 (n_1980), .Y + (n_4351)); + AOI21X1 g38374(.A0 (\u8_mem[2]_41 ), .A1 (n_4499), .B0 (n_2292), .Y + (n_4350)); + XOR2X1 g38375(.A (n_116), .B (n_4996), .Y (n_4349)); + AOI21X1 g38382(.A0 (\u3_mem[2]_38 ), .A1 (n_4533), .B0 (n_2010), .Y + (n_4348)); + AOI21X1 g38383(.A0 (\u3_mem[2]_47 ), .A1 (n_4533), .B0 (n_1938), .Y + (n_4347)); + AOI21X1 g38385(.A0 (\u3_mem[2]_48 ), .A1 (n_4519), .B0 (n_2224), .Y + (n_4346)); + AOI21X1 g38391(.A0 (\u3_mem[2]_51 ), .A1 (n_4519), .B0 (n_2003), .Y + (n_4345)); + AOI21X1 g38394(.A0 (\u8_mem[2]_40 ), .A1 (n_4499), .B0 (n_1966), .Y + (n_4344)); + AOI21X1 g38395(.A0 (\u3_mem[2]_53 ), .A1 (n_4519), .B0 (n_2084), .Y + (n_4343)); + NAND2X1 g36855(.A (n_2504), .B (n_1692), .Y (n_4342)); + AOI21X1 g38398(.A0 (\u3_mem[2]_55 ), .A1 (n_4519), .B0 (n_1955), .Y + (n_4341)); + AOI21X1 g38400(.A0 (\u8_mem[1]_65 ), .A1 (n_4502), .B0 (n_2193), .Y + (n_4340)); + AOI21X1 g38406(.A0 (\u7_mem[2]_32 ), .A1 (n_4540), .B0 (n_2204), .Y + (n_4339)); + AOI21X1 g38422(.A0 (\u6_mem[2]_38 ), .A1 (n_4504), .B0 (n_2080), .Y + (n_4338)); + AOI21X1 g38425(.A0 (\u6_mem[2]_42 ), .A1 (n_4504), .B0 (n_1968), .Y + (n_4337)); + AOI21X1 g38426(.A0 (\u6_mem[2]_44 ), .A1 (n_4504), .B0 (n_2190), .Y + (n_4336)); + AOI21X1 g38428(.A0 (\u6_mem[2]_29 ), .A1 (n_4504), .B0 (n_1996), .Y + (n_4335)); + AOI21X1 g38431(.A0 (\u6_mem[2]_51 ), .A1 (n_4504), .B0 (n_2155), .Y + (n_4334)); + XOR2X1 g38432(.A (n_214), .B (n_5138), .Y (n_4333)); + AOI21X1 g38433(.A0 (\u6_mem[2]_53 ), .A1 (n_4504), .B0 (n_1959), .Y + (n_4332)); + AOI21X1 g38434(.A0 (\u8_mem[2]_39 ), .A1 (n_4499), .B0 (n_2143), .Y + (n_4331)); + AOI21X1 g38435(.A0 (\u6_mem[2]_31 ), .A1 (n_4544), .B0 (n_1937), .Y + (n_4330)); + AOI21X1 g38436(.A0 (\u8_mem[1]_69 ), .A1 (n_4502), .B0 (n_2124), .Y + (n_4329)); + AOI21X1 g38441(.A0 (\u8_mem[2] ), .A1 (n_4499), .B0 (n_2092), .Y + (n_4328)); + AOI21X1 g38444(.A0 (\u4_mem[2]_48 ), .A1 (n_935), .B0 (n_1975), .Y + (n_4327)); + AOI21X1 g38449(.A0 (\u8_mem[2]_54 ), .A1 (n_4491), .B0 (n_1986), .Y + (n_4326)); + AOI21X1 g38458(.A0 (\u3_mem[2]_41 ), .A1 (n_4519), .B0 (n_2097), .Y + (n_4325)); + AOI21X1 g38462(.A0 (\u3_mem[2]_33 ), .A1 (n_4519), .B0 (n_2029), .Y + (n_4324)); + AOI21X1 g38463(.A0 (\u6_mem[2]_30 ), .A1 (n_4504), .B0 (n_1974), .Y + (n_4323)); + AOI21X1 g38466(.A0 (\u6_mem[2]_37 ), .A1 (n_4544), .B0 (n_2178), .Y + (n_4322)); + AOI21X1 g38468(.A0 (\u8_mem[2]_55 ), .A1 (n_4499), .B0 (n_1871), .Y + (n_4321)); + AOI21X1 g38473(.A0 (\u3_mem[2]_52 ), .A1 (n_4533), .B0 (n_2121), .Y + (n_4320)); + AOI21X1 g38490(.A0 (\u8_mem[1]_87 ), .A1 (n_4502), .B0 (n_1946), .Y + (n_4319)); + AOI21X1 g38492(.A0 (\u7_mem[2]_39 ), .A1 (n_4540), .B0 (n_2064), .Y + (n_4318)); + AOI21X1 g38493(.A0 (\u7_mem[2]_41 ), .A1 (n_4509), .B0 (n_1995), .Y + (n_4317)); + AOI21X1 g38494(.A0 (\u7_mem[2]_42 ), .A1 (n_4509), .B0 (n_2060), .Y + (n_4316)); + AOI21X1 g38496(.A0 (\u7_mem[2]_43 ), .A1 (n_4509), .B0 (n_2185), .Y + (n_4315)); + AOI21X1 g38497(.A0 (\u7_mem[2]_45 ), .A1 (n_4540), .B0 (n_2117), .Y + (n_4314)); + AOI21X1 g38498(.A0 (\u7_mem[2]_47 ), .A1 (n_4509), .B0 (n_1944), .Y + (n_4313)); + AOI21X1 g38499(.A0 (\u7_mem[2]_53 ), .A1 (n_4509), .B0 (n_2034), .Y + (n_4312)); + AOI21X1 g38500(.A0 (\u7_mem[2]_54 ), .A1 (n_4509), .B0 (n_1977), .Y + (n_4311)); + AOI21X1 g38501(.A0 (\u4_mem[2]_40 ), .A1 (n_4439), .B0 (n_2016), .Y + (n_4310)); + AOI21X1 g38502(.A0 (\u7_mem[2]_56 ), .A1 (n_4509), .B0 (n_2039), .Y + (n_4309)); + AOI21X1 g38503(.A0 (\u5_mem[2]_33 ), .A1 (n_4370), .B0 (n_2132), .Y + (n_4308)); + AOI21X1 g38504(.A0 (\u7_mem[2]_59 ), .A1 (n_4509), .B0 (n_2026), .Y + (n_4307)); + AOI21X1 g38505(.A0 (\u5_mem[2]_32 ), .A1 (n_4370), .B0 (n_2134), .Y + (n_4306)); + AOI21X1 g38506(.A0 (\u7_mem[2]_34 ), .A1 (n_4509), .B0 (n_1997), .Y + (n_4305)); + AOI21X1 g38507(.A0 (\u8_mem[2]_52 ), .A1 (n_4491), .B0 (n_1826), .Y + (n_4304)); + AOI21X1 g38509(.A0 (\u7_mem[2]_37 ), .A1 (n_4540), .B0 (n_2019), .Y + (n_4303)); + AOI21X1 g38513(.A0 (\u8_mem[1]_66 ), .A1 (n_4387), .B0 (n_2046), .Y + (n_4302)); + AOI21X1 g38519(.A0 (\u5_mem[2]_58 ), .A1 (n_4370), .B0 (n_2172), .Y + (n_4301)); + AOI21X1 g38520(.A0 (\u5_mem[2]_30 ), .A1 (n_4378), .B0 (n_2177), .Y + (n_4300)); + XOR2X1 g38526(.A (n_1443), .B (n_4961), .Y (n_4299)); + AOI21X1 g38527(.A0 (\u8_mem[2]_50 ), .A1 (n_4491), .B0 (n_1931), .Y + (n_4298)); + AOI21X1 g38529(.A0 (\u4_mem[1]_65 ), .A1 (n_2470), .B0 (n_2481), .Y + (n_4297)); + AOI21X1 g38531(.A0 (\u3_mem[2]_44 ), .A1 (n_4519), .B0 (n_1934), .Y + (n_4296)); + AOI21X1 g38532(.A0 (\u4_mem[1]_68 ), .A1 (n_4507), .B0 (n_2107), .Y + (n_4295)); + AOI21X1 g38533(.A0 (\u7_mem[2]_36 ), .A1 (n_4509), .B0 (n_2181), .Y + (n_4294)); + AOI21X1 g38534(.A0 (\u3_mem[2]_32 ), .A1 (n_4533), .B0 (n_1950), .Y + (n_4293)); + AOI21X1 g38536(.A0 (\u7_mem[2]_35 ), .A1 (n_4540), .B0 (n_1942), .Y + (n_4292)); + AOI21X1 g38540(.A0 (\u8_mem[2]_48 ), .A1 (n_4491), .B0 (n_2176), .Y + (n_4291)); + AOI21X1 g38541(.A0 (\u8_mem[1]_88 ), .A1 (n_4502), .B0 (n_1987), .Y + (n_4290)); + AOI21X1 g38542(.A0 (\u5_mem[2]_51 ), .A1 (n_4370), .B0 (n_1936), .Y + (n_4289)); + AOI21X1 g38544(.A0 (\u8_mem[1]_70 ), .A1 (n_4387), .B0 (n_1965), .Y + (n_4288)); + AOI21X1 g38545(.A0 (\u8_mem[1]_72 ), .A1 (n_4387), .B0 (n_2119), .Y + (n_4287)); + AOI21X1 g38546(.A0 (\u8_mem[1]_74 ), .A1 (n_4502), .B0 (n_1960), .Y + (n_4286)); + AOI21X1 g38547(.A0 (\u8_mem[1]_76 ), .A1 (n_4502), .B0 (n_2202), .Y + (n_4285)); + AOI21X1 g38548(.A0 (\u8_mem[1]_78 ), .A1 (n_4387), .B0 (n_2122), .Y + (n_4284)); + AOI21X1 g38549(.A0 (\u8_mem[1]_79 ), .A1 (n_4387), .B0 (n_1956), .Y + (n_4283)); + AOI21X1 g38551(.A0 (\u8_mem[1]_81 ), .A1 (n_4387), .B0 (n_2036), .Y + (n_4282)); + AOI21X1 g38552(.A0 (\u8_mem[1]_83 ), .A1 (n_4387), .B0 (n_2098), .Y + (n_4281)); + AOI21X1 g38553(.A0 (\u8_mem[1]_85 ), .A1 (n_4387), .B0 (n_2009), .Y + (n_4280)); + AOI21X1 g38556(.A0 (\u8_mem[1]_61 ), .A1 (n_4387), .B0 (n_2022), .Y + (n_4279)); + AOI21X1 g38558(.A0 (\u8_mem[2]_29 ), .A1 (n_4491), .B0 (n_2018), .Y + (n_4278)); + AOI21X1 g38559(.A0 (\u8_mem[1]_63 ), .A1 (n_4502), .B0 (n_1930), .Y + (n_4277)); + AOI21X1 g38560(.A0 (\u5_mem[2]_47 ), .A1 (n_4378), .B0 (n_1932), .Y + (n_4276)); + AOI21X1 g38562(.A0 (\u8_mem[1]_68 ), .A1 (n_4387), .B0 (n_2069), .Y + (n_4275)); + AOI21X1 g38563(.A0 (\u8_mem[1]_67 ), .A1 (n_4502), .B0 (n_2068), .Y + (n_4274)); + AOI21X1 g38565(.A0 (\u8_mem[2]_38 ), .A1 (n_4491), .B0 (n_1979), .Y + (n_4273)); + AOI21X1 g38569(.A0 (\u8_mem[2]_46 ), .A1 (n_4491), .B0 (n_2056), .Y + (n_4272)); + AOI21X1 g38575(.A0 (\u8_mem[2]_53 ), .A1 (n_4491), .B0 (n_2192), .Y + (n_4271)); + AOI21X1 g38577(.A0 (\u8_mem[2]_47 ), .A1 (n_4491), .B0 (n_2201), .Y + (n_4270)); + AOI22X1 g38781(.A0 (n_12291), .A1 (n_6152), .B0 (n_2567), .B1 + (n_12278), .Y (n_4269)); + OAI21X1 g38782(.A0 (n_12262), .A1 (n_145), .B0 (n_929), .Y (n_4268)); + AOI22X1 g38783(.A0 (n_3316), .A1 (n_634), .B0 (n_6316), .B1 (n_763), + .Y (n_4267)); + AOI22X1 g38785(.A0 (n_3522), .A1 (\u7_rp[0] ), .B0 (n_12634), .B1 + (n_754), .Y (n_4266)); + NAND2X1 g38796(.A (\u4_mem[3]_135 ), .B (n_12744), .Y (n_11651)); + NAND2X1 g38812(.A (\u4_mem[3]_138 ), .B (n_4258), .Y (n_4261)); + NAND2X1 g38816(.A (\u4_mem[3]_140 ), .B (n_12744), .Y (n_4260)); + NAND2X1 g38817(.A (\u4_mem[3]_122 ), .B (n_4258), .Y (n_4259)); + NAND2X1 g38819(.A (\u4_mem[3]_123 ), .B (n_4258), .Y (n_4257)); + NAND2X1 g38820(.A (\u4_mem[3]_124 ), .B (n_4258), .Y (n_4256)); + NAND2X1 g38880(.A (\u4_mem[3]_132 ), .B (n_12744), .Y (n_11655)); + NAND2X1 g39238(.A (\u6_mem[1]_72 ), .B (n_4253), .Y (n_11700)); + NAND2X1 g38945(.A (\u4_mem[3]_139 ), .B (n_12744), .Y (n_4252)); + NAND2X1 g38957(.A (\u4_mem[3]_128 ), .B (n_12744), .Y (n_4251)); + NAND2X1 g38961(.A (\u4_mem[3] ), .B (n_12744), .Y (n_4250)); + NAND2X1 g39008(.A (\u6_mem[1]_76 ), .B (n_12169), .Y (n_4249)); + NAND2X1 g39012(.A (\u7_mem[1]_75 ), .B (n_4225), .Y (n_4247)); + NAND2X1 g39027(.A (\u6_mem[1]_68 ), .B (n_12169), .Y (n_4246)); + NAND2X1 g39028(.A (\u6_mem[1]_88 ), .B (n_4253), .Y (n_4244)); + NAND2X1 g39031(.A (\u4_mem[1]_76 ), .B (n_12259), .Y (n_4243)); + NAND2X1 g39034(.A (\u4_mem[1]_67 ), .B (n_12272), .Y (n_11661)); + NAND2X1 g39039(.A (\u7_mem[1]_82 ), .B (n_4130), .Y (n_4240)); + NAND2X1 g39040(.A (in_slt_406), .B (n_4623), .Y (n_4239)); + INVX1 g39044(.A (n_5335), .Y (n_4238)); + INVX1 g39046(.A (n_5313), .Y (n_4237)); + NAND2X1 g39051(.A (\u4_mem[1]_81 ), .B (n_12270), .Y (n_4236)); + NAND2X1 g39062(.A (\u7_mem[2]_56 ), .B (n_12650), .Y (n_4234)); + NAND2X1 g39075(.A (\u6_mem[1] ), .B (n_12169), .Y (n_11752)); + INVX1 g39086(.A (n_5315), .Y (n_4232)); + INVX1 g39114(.A (n_5282), .Y (n_4231)); + INVX1 g39117(.A (n_5287), .Y (n_4230)); + NAND2X1 g39120(.A (\u6_mem[1]_86 ), .B (n_12169), .Y (n_4229)); + NAND2X1 g39138(.A (\u4_mem[1]_73 ), .B (n_12261), .Y (n_11472)); + NAND2X1 g39146(.A (\u7_mem[1]_76 ), .B (n_4225), .Y (n_4226)); + NAND2X1 g39147(.A (\u6_mem[1]_84 ), .B (n_4253), .Y (n_4224)); + NAND2X1 g39150(.A (\u7_mem[1]_87 ), .B (n_4225), .Y (n_4223)); + NAND2X1 g39164(.A (\u7_mem[1]_83 ), .B (n_4130), .Y (n_4222)); + NAND2X1 g39165(.A (in_slt_407), .B (n_4623), .Y (n_4220)); + NAND2X1 g39174(.A (\u4_mem[1]_80 ), .B (n_12265), .Y (n_4219)); + NAND2X1 g39178(.A (\u4_mem[1]_89 ), .B (n_12267), .Y (n_4218)); + NAND2X1 g39188(.A (\u7_mem[1]_80 ), .B (n_11856), .Y (n_4217)); + NAND2X1 g39204(.A (\u4_mem[1]_64 ), .B (n_12252), .Y (n_11667)); + NAND2X1 g39223(.A (\u7_mem[1]_85 ), .B (n_4225), .Y (n_4214)); + NAND2X1 g39225(.A (\u6_mem[1]_90 ), .B (n_12169), .Y (n_4212)); + NAND2X1 g39240(.A (\u7_mem[1]_61 ), .B (n_4225), .Y (n_4210)); + INVX1 g39242(.A (n_5298), .Y (n_4209)); + NAND2X1 g39249(.A (\u4_mem[1]_62 ), .B (n_12259), .Y (n_4208)); + INVX1 g39256(.A (n_5309), .Y (n_4207)); + INVX1 g39261(.A (n_5339), .Y (n_4206)); + INVX1 g39265(.A (n_5317), .Y (n_4205)); + NAND2X1 g39295(.A (\u7_mem[1]_62 ), .B (n_4225), .Y (n_4204)); + NAND2X1 g39309(.A (\u7_mem[1]_89 ), .B (n_4130), .Y (n_4203)); + INVX1 g39318(.A (n_5280), .Y (n_4202)); + NAND2X1 g39324(.A (\u6_mem[1]_66 ), .B (n_4253), .Y (n_11716)); + NAND2X1 g39331(.A (\u4_mem[1]_82 ), .B (n_12267), .Y (n_4200)); + NAND2X1 g39367(.A (\u7_mem[1] ), .B (n_4130), .Y (n_4199)); + NAND2X1 g39376(.A (\u7_mem[1]_86 ), .B (n_4130), .Y (n_4198)); + NAND2X1 g39396(.A (n_12261), .B (\u4_mem[1]_70 ), .Y (n_11476)); + NAND2X1 g39400(.A (\u7_mem[2]_44 ), .B (n_12641), .Y (n_4196)); + NAND2X1 g39420(.A (\u4_mem[1]_60 ), .B (n_12272), .Y (n_4195)); + INVX1 g39422(.A (n_5296), .Y (n_4193)); + NAND2X1 g39433(.A (\u4_mem[1]_61 ), .B (n_12259), .Y (n_4192)); + NAND2X1 g39445(.A (\u7_mem[1]_81 ), .B (n_4130), .Y (n_4191)); + NAND2X1 g39446(.A (\u7_mem[1]_67 ), .B (n_4130), .Y (n_4190)); + NAND2X1 g39457(.A (\u6_mem[1]_67 ), .B (n_4253), .Y (n_11718)); + NAND2X1 g39461(.A (\u4_mem[1]_71 ), .B (n_12250), .Y (n_11657)); + NAND2X1 g39474(.A (\u6_mem[1]_65 ), .B (n_12169), .Y (n_11714)); + NAND2X1 g39479(.A (\u6_mem[1]_64 ), .B (n_4253), .Y (n_11712)); + NAND2X1 g39486(.A (\u4_mem[1]_83 ), .B (n_12265), .Y (n_4183)); + NAND2X1 g39494(.A (\u6_mem[1]_81 ), .B (n_4253), .Y (n_4182)); + NAND2X1 g39499(.A (\u6_mem[1]_61 ), .B (n_12169), .Y (n_11514)); + INVX1 g39513(.A (n_5290), .Y (n_4178)); + NAND2X1 g39527(.A (\u4_mem[1]_85 ), .B (n_12270), .Y (n_4177)); + NAND2X1 g39530(.A (\u7_mem[2]_50 ), .B (n_12645), .Y (n_4175)); + NAND2X1 g39548(.A (\u7_mem[1]_72 ), .B (n_11856), .Y (n_4173)); + NAND2X1 g39550(.A (\u7_mem[2]_54 ), .B (n_12650), .Y (n_4171)); + NAND2X1 g39555(.A (\u6_mem[1]_74 ), .B (n_4253), .Y (n_11704)); + NAND2X1 g39562(.A (\u6_mem[1]_82 ), .B (n_4253), .Y (n_4167)); + NAND2X1 g39573(.A (\u6_mem[1]_70 ), .B (n_12169), .Y (n_11708)); + NAND2X1 g39578(.A (\u6_mem[1]_83 ), .B (n_4253), .Y (n_4165)); + NAND2X1 g39582(.A (\u6_mem[1]_71 ), .B (n_12169), .Y (n_4164)); + NAND2X1 g39594(.A (\u6_mem[1]_85 ), .B (n_4253), .Y (n_4163)); + INVX1 g39615(.A (n_5300), .Y (n_4161)); + NAND2X1 g39743(.A (\u6_mem[1]_60 ), .B (n_12169), .Y (n_12820)); + NAND2X1 g39622(.A (\u6_mem[1]_89 ), .B (n_12169), .Y (n_4159)); + NAND2X1 g39624(.A (\u6_mem[1]_77 ), .B (n_4253), .Y (n_4158)); + NAND2X1 g39629(.A (\u6_mem[1]_78 ), .B (n_12169), .Y (n_4157)); + NAND2X1 g39632(.A (\u6_mem[1]_62 ), .B (n_12169), .Y (n_12822)); + NAND2X1 g39635(.A (\u4_mem[1]_87 ), .B (n_12267), .Y (n_4155)); + NAND2X1 g39644(.A (\u6_mem[1]_80 ), .B (n_4253), .Y (n_4154)); + INVX1 g39647(.A (n_5284), .Y (n_4153)); + NAND2X1 g39650(.A (\u4_mem[1]_68 ), .B (n_12252), .Y (n_11663)); + NAND2X1 g39658(.A (\u6_mem[1]_87 ), .B (n_4253), .Y (n_4150)); + NAND2X1 g39674(.A (\u7_mem[2]_57 ), .B (n_12650), .Y (n_4148)); + NAND2X1 g39675(.A (\u4_mem[1]_78 ), .B (n_12259), .Y (n_4147)); + NAND2X1 g39678(.A (\u4_mem[1]_75 ), .B (n_12250), .Y (n_12828)); + NAND2X1 g39684(.A (\u4_mem[1]_77 ), .B (n_12250), .Y (n_4144)); + NAND2X1 g39691(.A (\u6_mem[1]_79 ), .B (n_12169), .Y (n_4143)); + NAND2X1 g39695(.A (\u7_mem[2]_55 ), .B (n_12650), .Y (n_4142)); + NAND2X1 g39700(.A (\u4_mem[1]_69 ), .B (n_12250), .Y (n_11647)); + NAND2X1 g39704(.A (\u4_mem[1]_79 ), .B (n_12265), .Y (n_4140)); + NAND2X1 g39718(.A (\u4_mem[1]_65 ), .B (n_12265), .Y (n_12830)); + INVX1 g39722(.A (n_5321), .Y (n_4138)); + NAND2X1 g39739(.A (\u4_mem[1]_66 ), .B (n_12273), .Y (n_11659)); + NAND2X1 g39749(.A (\u4_mem[1]_90 ), .B (n_12270), .Y (n_4136)); + INVX1 g39750(.A (n_5355), .Y (n_4135)); + NAND2X1 g39761(.A (\u4_mem[1]_88 ), .B (n_12267), .Y (n_4134)); + INVX1 g39762(.A (n_5304), .Y (n_4133)); + NAND2X1 g39768(.A (\u7_mem[1]_69 ), .B (n_4130), .Y (n_4131)); + NAND2X1 g39774(.A (\u7_mem[2]_51 ), .B (n_12645), .Y (n_4129)); + NAND2X1 g39779(.A (\u7_mem[2]_52 ), .B (n_12650), .Y (n_4128)); + NAND2X1 g39781(.A (\u7_mem[1]_71 ), .B (n_4130), .Y (n_4127)); + NAND2X1 g39784(.A (\u7_mem[2]_53 ), .B (n_12650), .Y (n_4126)); + NAND2X1 g39790(.A (\u7_mem[1]_74 ), .B (n_4130), .Y (n_4125)); + NAND2X1 g39800(.A (\u7_mem[1]_88 ), .B (n_4130), .Y (n_4124)); + NAND2X1 g39801(.A (\u7_mem[2]_45 ), .B (n_12641), .Y (n_4123)); + NAND2X1 g39803(.A (\u7_mem[2]_59 ), .B (n_12650), .Y (n_4121)); + NAND2X1 g39805(.A (\u7_mem[1]_90 ), .B (n_4225), .Y (n_4120)); + NAND2X1 g39807(.A (\u7_mem[1]_60 ), .B (n_4130), .Y (n_4118)); + NAND2X1 g39808(.A (\u7_mem[1]_84 ), .B (n_4225), .Y (n_4117)); + NAND2X1 g39818(.A (\u7_mem[2]_58 ), .B (n_12650), .Y (n_4116)); + NAND2X1 g39829(.A (\u4_mem[1] ), .B (n_12252), .Y (n_11671)); + NAND2X1 g39833(.A (\u7_mem[1]_70 ), .B (n_4130), .Y (n_4114)); + NAND2X1 g39860(.A (\u7_mem[1]_73 ), .B (n_11856), .Y (n_4113)); + NAND2X1 g39872(.A (\u4_mem[1]_86 ), .B (n_12270), .Y (n_4112)); + INVX1 g39907(.A (n_5292), .Y (n_4111)); + NAND2X1 g39921(.A (\u6_mem[1]_63 ), .B (n_4253), .Y (n_11710)); + NAND2X1 g39932(.A (\u4_mem[1]_84 ), .B (n_12250), .Y (n_4109)); + INVX1 g39934(.A (n_5330), .Y (n_4108)); + NOR2X1 g35855(.A (n_1823), .B (n_1469), .Y (n_4107)); + INVX1 g39619(.A (n_5307), .Y (n_4106)); + NOR2X1 g35853(.A (n_1292), .B (n_4104), .Y (n_4105)); + NAND4X1 g35478(.A (n_2631), .B (\u2_cnt[5] ), .C (\u2_cnt[6] ), .D + (\u2_cnt[4] ), .Y (n_4103)); + XOR2X1 g35486(.A (\u11_wp[3] ), .B (n_1233), .Y (n_4102)); + XOR2X1 g35491(.A (\u2_res_cnt[3] ), .B (n_1278), .Y (n_4101)); + XOR2X1 g35492(.A (\u2_to_cnt[3] ), .B (n_1276), .Y (n_4100)); + AOI22X1 g37942(.A0 (u11_din_tmp_56), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_457), .Y (n_4098)); + NOR2X1 g35835(.A (n_1825), .B (n_1486), .Y (n_4096)); + NOR3X1 g35841(.A (n_1213), .B (n_4076), .C (\u2_cnt[5] ), .Y + (n_4095)); + NAND2X1 g35842(.A (n_5632), .B (\u2_res_cnt[0] ), .Y (n_4094)); + XOR2X1 g36187(.A (n_920), .B (n_1294), .Y (n_4093)); + XOR2X1 g36188(.A (n_1425), .B (n_1269), .Y (n_4092)); + XOR2X1 g36191(.A (n_1418), .B (n_1267), .Y (n_4091)); + XOR2X1 g36192(.A (n_1422), .B (n_1265), .Y (n_4090)); + XOR2X1 g36202(.A (n_4088), .B (n_1282), .Y (n_4089)); + NAND2X1 g36305(.A (n_4081), .B (n_2617), .Y (n_4087)); + NOR2X1 g36416(.A (n_2599), .B (n_1814), .Y (n_4086)); + NOR2X1 g37492(.A (n_4747), .B (n_5371), .Y (n_4085)); + NOR2X1 g36450(.A (n_1794), .B (n_1793), .Y (n_4084)); + NAND2X1 g36504(.A (n_1804), .B (n_4081), .Y (n_4082)); + NAND2X1 g36526(.A (n_1772), .B (n_4080), .Y (n_5636)); + NAND4X1 g36562(.A (n_2378), .B (n_698), .C (n_2596), .D (n_4079), .Y + (n_4832)); + NAND3X1 g36617(.A (n_1284), .B (u12_we2), .C (u12_we1), .Y (n_5248)); + AOI21X1 g37698(.A0 (n_6030), .A1 (n_2553), .B0 (n_2365), .Y (n_4078)); + NOR2X1 g36695(.A (n_1785), .B (n_4076), .Y (n_4077)); + OAI21X1 g36726(.A0 (n_2368), .A1 (n_4074), .B0 (n_1813), .Y (n_4075)); + OAI21X1 g36730(.A0 (n_2513), .A1 (\u11_wp[1] ), .B0 (n_1816), .Y + (n_4073)); + NOR2X1 g35838(.A (n_5632), .B (n_1777), .Y (n_5624)); + XOR2X1 g36746(.A (n_1157), .B (n_1438), .Y (n_4072)); + DFFX1 \u11_status_reg[0] (.CK (clk_i), .D (n_1804), .Q (i6_status), + .QN ()); + DFFX1 \u6_status_reg[0] (.CK (clk_i), .D (n_5618), .Q (o7_status), + .QN ()); + DFFX1 \u3_status_reg[0] (.CK (clk_i), .D (n_5620), .Q (o3_status), + .QN ()); + DFFX1 \u4_status_reg[0] (.CK (clk_i), .D (n_6049), .Q (o4_status), + .QN ()); + DFFX1 \u7_status_reg[0] (.CK (clk_i), .D (n_5616), .Q (o8_status), + .QN ()); + DFFX1 \u1_sr_reg[2] (.CK (bit_clk_pad_i), .D (u1_sr_117), .Q + (u1_sr_118), .QN ()); + NAND2X1 g36784(.A (n_1770), .B (n_1768), .Y (n_4067)); + NAND2X1 g36785(.A (n_1697), .B (n_1848), .Y (n_4066)); + NAND2X1 g36786(.A (n_1765), .B (n_1764), .Y (n_4065)); + NAND2X1 g36787(.A (n_1568), .B (n_1763), .Y (n_4064)); + NAND2X1 g36788(.A (n_1860), .B (n_1761), .Y (n_4063)); + NAND2X1 g36789(.A (n_1639), .B (n_1698), .Y (n_4062)); + NAND2X1 g36790(.A (n_1759), .B (n_1758), .Y (n_4061)); + NAND2X1 g36791(.A (n_1836), .B (n_1753), .Y (n_4060)); + NAND2X1 g36792(.A (n_1752), .B (n_1751), .Y (n_4059)); + NAND2X1 g36793(.A (n_1767), .B (n_1750), .Y (n_4058)); + NAND2X1 g36794(.A (n_1749), .B (n_1834), .Y (n_4057)); + NAND2X1 g36796(.A (n_1747), .B (n_1746), .Y (n_4056)); + NAND2X1 g36797(.A (n_1745), .B (n_1743), .Y (n_4055)); + NAND2X1 g36798(.A (n_1681), .B (n_1741), .Y (n_4054)); + NAND2X1 g36799(.A (n_1739), .B (n_1736), .Y (n_4053)); + NAND2X1 g36800(.A (n_1563), .B (n_1735), .Y (n_4052)); + NAND2X1 g36801(.A (n_1734), .B (n_1699), .Y (n_4051)); + NAND2X1 g36802(.A (n_1705), .B (n_1730), .Y (n_4050)); + NAND2X1 g36803(.A (n_1729), .B (n_1726), .Y (n_4049)); + NAND2X1 g36804(.A (n_1725), .B (n_1722), .Y (n_4048)); + NAND2X1 g36805(.A (n_2501), .B (n_1720), .Y (n_4047)); + NAND2X1 g36806(.A (n_1719), .B (n_1718), .Y (n_4046)); + NAND2X1 g36807(.A (n_2508), .B (n_1858), .Y (n_4045)); + NAND2X1 g36808(.A (n_1717), .B (n_2505), .Y (n_4044)); + NAND2X1 g36809(.A (n_1714), .B (n_1712), .Y (n_4043)); + NAND2X1 g36810(.A (n_1674), .B (n_1710), .Y (n_4042)); + NAND2X1 g36811(.A (n_1694), .B (n_1693), .Y (n_4041)); + NAND2X1 g36813(.A (n_1709), .B (n_1696), .Y (n_4040)); + NAND2X1 g36815(.A (n_1702), .B (n_1731), .Y (n_4039)); + NAND2X1 g36862(.A (n_1572), .B (n_1571), .Y (n_4038)); + NAND2X1 g36871(.A (n_1686), .B (n_1683), .Y (n_4037)); + NAND2X1 g36876(.A (n_1189), .B (n_2302), .Y (n_4036)); + NOR2X1 g36878(.A (n_2486), .B (n_2302), .Y (n_4035)); + NAND2X1 g36879(.A (n_1678), .B (n_1675), .Y (n_4034)); + NAND2X1 g36893(.A (n_1669), .B (n_1711), .Y (n_4033)); + NAND2X1 g36914(.A (n_1672), .B (n_1671), .Y (n_4032)); + NAND2X1 g36919(.A (n_1837), .B (n_1653), .Y (n_4031)); + NAND2X1 g36923(.A (n_1668), .B (n_1667), .Y (n_4030)); + NAND2X1 g36927(.A (n_1666), .B (n_1891), .Y (n_4029)); + NAND2X1 g36930(.A (n_1665), .B (n_1664), .Y (n_4028)); + NAND2X1 g36931(.A (n_1662), .B (n_1661), .Y (n_4027)); + NAND2X1 g36934(.A (n_1660), .B (n_1658), .Y (n_4026)); + NAND2X1 g36935(.A (n_1656), .B (n_1655), .Y (n_4025)); + NAND2X1 g36937(.A (n_1654), .B (n_1652), .Y (n_4024)); + NAND2X1 g36938(.A (n_1651), .B (n_1648), .Y (n_4023)); + NAND2X1 g36939(.A (n_1646), .B (n_1640), .Y (n_4022)); + NAND2X1 g36940(.A (n_1645), .B (n_1642), .Y (n_4021)); + NAND2X1 g36941(.A (n_1638), .B (n_1637), .Y (n_4020)); + NAND2X1 g36944(.A (n_1635), .B (n_1631), .Y (n_4019)); + NAND2X1 g36945(.A (n_1629), .B (n_1625), .Y (n_4018)); + NAND2X1 g36947(.A (n_1757), .B (n_1623), .Y (n_4017)); + NAND2X1 g36948(.A (n_1621), .B (n_1617), .Y (n_4016)); + NAND2X1 g36950(.A (n_1616), .B (n_1613), .Y (n_4015)); + NAND2X1 g36951(.A (n_1611), .B (n_1607), .Y (n_4014)); + NAND2X1 g36953(.A (n_1606), .B (n_1603), .Y (n_4013)); + NAND2X1 g36954(.A (n_1601), .B (n_1855), .Y (n_4012)); + NAND2X1 g36957(.A (n_1597), .B (n_1594), .Y (n_4011)); + NAND2X1 g36959(.A (n_1593), .B (n_1590), .Y (n_4010)); + NAND2X1 g36960(.A (n_1588), .B (n_1587), .Y (n_4009)); + NAND2X1 g36961(.A (n_1586), .B (n_1583), .Y (n_4008)); + NAND2X1 g36962(.A (n_1582), .B (n_1602), .Y (n_4007)); + NAND2X1 g36963(.A (n_1579), .B (n_1578), .Y (n_4006)); + NAND2X1 g36970(.A (n_1577), .B (n_1576), .Y (n_4005)); + NAND2X1 g36977(.A (n_1574), .B (n_1573), .Y (n_4004)); + NAND2X1 g36986(.A (n_1570), .B (n_1689), .Y (n_4003)); + NAND2X1 g36991(.A (n_1569), .B (n_1832), .Y (n_4002)); + NAND2X1 g36994(.A (n_1567), .B (n_1566), .Y (n_4001)); + NAND4X1 g37053(.A (n_3964), .B (n_701), .C (n_711), .D (n_2596), .Y + (n_4000)); + NAND2X1 g37073(.A (n_2503), .B (n_1707), .Y (n_3999)); + NAND2X1 g37128(.A (n_1865), .B (n_1663), .Y (n_3998)); + NAND2X1 g37129(.A (n_2498), .B (n_1706), .Y (n_3997)); + NAND3X1 g37196(.A (n_1782), .B (n_2571), .C (n_3995), .Y (n_3996)); + XOR2X1 g37202(.A (\u26_ps_cnt[4] ), .B (n_1449), .Y (n_3994)); + XOR2X1 g37206(.A (\u8_wp[0] ), .B (n_3992), .Y (n_3993)); + AOI22X1 g37329(.A0 (n_5277), .A1 (crac_out_866), .B0 (n_6972), .B1 + (n_8550), .Y (n_3991)); + AOI22X1 g37332(.A0 (n_5277), .A1 (crac_out_867), .B0 (n_6972), .B1 + (n_3987), .Y (n_3989)); + AOI22X1 g37336(.A0 (n_6972), .A1 (oc2_cfg_990), .B0 (\u13_ints_r[23] + ), .B1 (n_3985), .Y (n_3986)); + INVX1 g37371(.A (n_2593), .Y (n_3984)); + AOI22X1 g37375(.A0 (n_5277), .A1 (crac_out_862), .B0 (n_6972), .B1 + (oc2_cfg_984), .Y (n_3983)); + INVX2 g37444(.A (n_2588), .Y (n_7297)); + NAND2X1 g37447(.A (\u13_ints_r[0] ), .B (n_3979), .Y (n_3982)); + NAND2X1 g37448(.A (\u13_ints_r[10] ), .B (n_3979), .Y (n_3981)); + NAND2X1 g37449(.A (\u13_ints_r[11] ), .B (n_3979), .Y (n_3980)); + NAND2X1 g37450(.A (\u13_ints_r[13] ), .B (n_3979), .Y (n_3978)); + NAND2X1 g37451(.A (n_5272), .B (\u13_intm_r[23] ), .Y (n_3976)); + NAND2X1 g37456(.A (\u13_ints_r[2] ), .B (n_3979), .Y (n_3975)); + NAND2X1 g37457(.A (\u13_ints_r[3] ), .B (n_3979), .Y (n_3974)); + NAND2X1 g37458(.A (n_5277), .B (crac_out_861), .Y (n_3973)); + NAND2X1 g37460(.A (\u13_ints_r[5] ), .B (n_3979), .Y (n_3971)); + NAND2X1 g37463(.A (\u13_ints_r[8] ), .B (n_3979), .Y (n_3970)); + NAND2X1 g37464(.A (n_3979), .B (\u13_ints_r[9] ), .Y (n_3969)); + NAND2X1 g37466(.A (n_5277), .B (crac_out_864), .Y (n_3968)); + NAND2X1 g37468(.A (n_5277), .B (crac_out_863), .Y (n_3967)); + NAND2X1 g37469(.A (\u13_ints_r[12] ), .B (n_3979), .Y (n_3966)); + OR2X1 g37473(.A (n_3964), .B (n_2596), .Y (n_3965)); + INVX1 g37481(.A (n_2576), .Y (n_4676)); + NOR2X1 g37494(.A (n_4749), .B (n_5371), .Y (n_3963)); + NOR2X1 g37495(.A (n_4772), .B (n_5371), .Y (n_3961)); + NOR2X1 g37496(.A (n_4769), .B (n_5371), .Y (n_3960)); + NOR2X1 g37498(.A (n_4745), .B (n_6594), .Y (n_3959)); + NOR2X1 g37505(.A (n_4761), .B (n_6594), .Y (n_3958)); + NOR2X1 g37506(.A (n_4759), .B (n_6594), .Y (n_3957)); + NOR2X1 g37508(.A (n_4751), .B (n_6594), .Y (n_3956)); + NOR2X1 g37512(.A (n_4764), .B (n_5371), .Y (n_3955)); + NOR2X1 g37536(.A (n_4767), .B (n_5371), .Y (n_3953)); + NOR2X1 g37542(.A (n_4743), .B (n_5371), .Y (n_3952)); + NOR2X1 g37551(.A (n_4776), .B (n_5371), .Y (n_3950)); + NOR2X1 g37553(.A (n_4757), .B (n_5371), .Y (n_3949)); + NOR2X1 g37569(.A (n_4753), .B (n_5371), .Y (n_3948)); + NOR2X1 g37577(.A (n_4755), .B (n_5371), .Y (n_3947)); + NOR2X1 g37580(.A (n_4778), .B (n_5371), .Y (n_3946)); + AND2X1 g37587(.A (n_2412), .B (n_3944), .Y (n_3945)); + AND2X1 g37595(.A (n_2371), .B (n_3942), .Y (n_3943)); + NOR2X1 g37596(.A (n_1199), .B (n_2302), .Y (n_3941)); + AOI22X1 g37601(.A0 (n_712), .A1 (n_3556), .B0 (n_145), .B1 (\u4_rp[3] + ), .Y (n_3940)); + AOI22X1 g37605(.A0 (n_785), .A1 (n_3543), .B0 (n_3559), .B1 + (\u5_rp[3] ), .Y (n_3939)); + AOI22X1 g37656(.A0 (u9_din_tmp_53), .A1 (n_2368), .B0 (in_slt_408), + .B1 (n_3935), .Y (n_3938)); + AOI22X1 g37657(.A0 (u9_din_tmp_54), .A1 (n_2368), .B0 (in_slt_409), + .B1 (n_3935), .Y (n_3937)); + AOI22X1 g37658(.A0 (u9_din_tmp_55), .A1 (n_2368), .B0 (in_slt_410), + .B1 (n_3935), .Y (n_3934)); + AOI22X1 g37659(.A0 (u9_din_tmp_56), .A1 (n_2368), .B0 (in_slt_411), + .B1 (n_3935), .Y (n_3933)); + AOI22X1 g37673(.A0 (in_slt_406), .A1 (n_3415), .B0 (in_slt_404), .B1 + (n_3935), .Y (n_3932)); + AOI21X1 g37685(.A0 (n_2558), .A1 (n_6375), .B0 (n_2257), .Y (n_3930)); + AOI21X1 g37691(.A0 (n_6585), .A1 (n_1316), .B0 (n_2346), .Y (n_3929)); + AOI22X1 g37701(.A0 (u10_din_tmp_46), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_425), .Y (n_3928)); + AOI21X1 g37702(.A0 (n_5577), .A1 (n_1316), .B0 (n_2341), .Y (n_3927)); + AOI21X1 g37704(.A0 (n_256), .A1 (n_2553), .B0 (n_2307), .Y (n_3925)); + AOI21X1 g37708(.A0 (n_6007), .A1 (n_1316), .B0 (n_2336), .Y (n_3923)); + AOI21X1 g37711(.A0 (n_98), .A1 (n_2553), .B0 (n_2335), .Y (n_3922)); + AOI21X1 g37714(.A0 (n_39), .A1 (n_2553), .B0 (n_2475), .Y (n_3921)); + AOI22X1 g37717(.A0 (u10_din_tmp_51), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_430), .Y (n_3920)); + AOI21X1 g37720(.A0 (n_5518), .A1 (n_1316), .B0 (n_2332), .Y (n_3919)); + AOI21X1 g37721(.A0 (n_366), .A1 (n_2553), .B0 (n_2327), .Y (n_3918)); + NAND2X1 g37735(.A (n_2404), .B (n_2250), .Y (n_3917)); + NAND2X1 g37739(.A (n_2444), .B (n_2320), .Y (n_3916)); + NAND2X1 g37745(.A (n_2401), .B (n_2317), .Y (n_3915)); + NAND2X1 g37749(.A (n_2443), .B (n_2316), .Y (n_3914)); + AOI22X1 g37861(.A0 (u10_din_tmp_52), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_431), .Y (n_3913)); + AOI22X1 g37874(.A0 (u10_din_tmp_53), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_432), .Y (n_3910)); + AOI22X1 g37879(.A0 (u10_din_tmp_54), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_433), .Y (n_3909)); + AOI22X1 g37880(.A0 (u11_din_tmp1), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_442), .Y (n_3908)); + AOI22X1 g37881(.A0 (u11_din_tmp_51), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_452), .Y (n_3907)); + AOI22X1 g37884(.A0 (u11_din_tmp_52), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_453), .Y (n_3905)); + AOI22X1 g37885(.A0 (u10_din_tmp_56), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_435), .Y (n_3904)); + AOI22X1 g37886(.A0 (u11_din_tmp_53), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_454), .Y (n_3903)); + AOI22X1 g37889(.A0 (u11_din_tmp_54), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_455), .Y (n_3902)); + AOI22X1 g37892(.A0 (u11_din_tmp_55), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_456), .Y (n_3900)); + AOI22X1 g37893(.A0 (u10_din_tmp_55), .A1 (n_3339), .B0 (n_3911), .B1 + (in_slt_434), .Y (n_3899)); + AOI22X1 g37901(.A0 (u11_din_tmp_42), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_443), .Y (n_3898)); + AOI22X1 g37906(.A0 (u11_din_tmp_43), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_444), .Y (n_3896)); + AOI22X1 g37908(.A0 (u11_din_tmp_44), .A1 (n_4560), .B0 (n_4097), .B1 + (in_slt_445), .Y (n_3895)); + AOI22X1 g37921(.A0 (n_4097), .A1 (in_slt_451), .B0 (n_2325), .B1 + (in_slt_449), .Y (n_3894)); + AOI22X1 g37947(.A0 (n_5981), .A1 (n_940), .B0 (n_6005), .B1 (n_1316), + .Y (n_3893)); + AOI22X1 g37962(.A0 (n_6457), .A1 (n_940), .B0 (n_6591), .B1 (n_1316), + .Y (n_3892)); + NAND2X1 g39960(.A (n_11804), .B (\u8_mem[0]_108 ), .Y (n_3890)); + AOI21X1 g38000(.A0 (\u8_mem[3]_134 ), .A1 (n_3879), .B0 (n_1458), .Y + (n_3889)); + AOI21X1 g38007(.A0 (\u8_mem[3]_141 ), .A1 (n_3879), .B0 (n_1504), .Y + (n_3888)); + AOI21X1 g38014(.A0 (\u8_mem[3]_149 ), .A1 (n_3879), .B0 (n_1283), .Y + (n_3887)); + AOI21X1 g38023(.A0 (\u8_mem[3] ), .A1 (n_3879), .B0 (n_1503), .Y + (n_3886)); + AOI21X1 g38046(.A0 (\u8_mem[3]_148 ), .A1 (n_3879), .B0 (n_1476), .Y + (n_3885)); + AOI21X1 g38066(.A0 (\u8_mem[3]_136 ), .A1 (n_3879), .B0 (n_1423), .Y + (n_3884)); + AOI21X1 g38072(.A0 (\u8_mem[3]_146 ), .A1 (n_3879), .B0 (n_1498), .Y + (n_3883)); + AOI21X1 g38081(.A0 (\u8_mem[3]_145 ), .A1 (n_3879), .B0 (n_1496), .Y + (n_3881)); + AOI21X1 g38082(.A0 (\u8_mem[3]_144 ), .A1 (n_3879), .B0 (n_1462), .Y + (n_3880)); + AOI21X1 g38084(.A0 (\u8_mem[3]_143 ), .A1 (n_3879), .B0 (n_1479), .Y + (n_3878)); + NAND2X2 g39945(.A (n_1367), .B (\u8_rp[3] ), .Y (n_4829)); + AOI21X1 g38088(.A0 (\u8_mem[3]_130 ), .A1 (n_3879), .B0 (n_1470), .Y + (n_3877)); + XOR2X1 g38091(.A (\u9_wp[3] ), .B (n_1063), .Y (n_3875)); + AOI21X1 g38092(.A0 (\u8_mem[3]_142 ), .A1 (n_3879), .B0 (n_1492), .Y + (n_3874)); + AOI21X1 g38104(.A0 (\u8_mem[3]_147 ), .A1 (n_3879), .B0 (n_1555), .Y + (n_3872)); + AOI21X1 g38106(.A0 (\u8_mem[3]_139 ), .A1 (n_3879), .B0 (n_1272), .Y + (n_3871)); + AOI21X1 g38107(.A0 (\u8_mem[3]_122 ), .A1 (n_3879), .B0 (n_1490), .Y + (n_3869)); + AOI21X1 g38134(.A0 (\u8_mem[3]_140 ), .A1 (n_3879), .B0 (n_1483), .Y + (n_3867)); + NAND2X1 g39922(.A (\u8_mem[2]_58 ), .B (n_3441), .Y (n_3866)); + NOR2X1 g39336(.A (n_3089), .B (n_2763), .Y (n_3865)); + AOI21X1 g38230(.A0 (\u8_mem[3]_124 ), .A1 (n_3879), .B0 (n_1478), .Y + (n_3864)); + NAND2X1 g39901(.A (\u8_mem[1]_85 ), .B (n_12291), .Y (n_3862)); + AOI21X1 g38373(.A0 (\u8_mem[3]_128 ), .A1 (n_3879), .B0 (n_1480), .Y + (n_3861)); + AOI21X1 g38378(.A0 (\u8_mem[3]_151 ), .A1 (n_3879), .B0 (n_1472), .Y + (n_3860)); + AOI21X1 g38384(.A0 (\u8_mem[3]_127 ), .A1 (n_3879), .B0 (n_1489), .Y + (n_3858)); + AOI21X1 g38389(.A0 (\u8_mem[3]_129 ), .A1 (n_3879), .B0 (n_1477), .Y + (n_3857)); + AOI21X1 g38392(.A0 (\u8_mem[3]_126 ), .A1 (n_3879), .B0 (n_1502), .Y + (n_3856)); + AOI21X1 g38413(.A0 (\u8_mem[3]_123 ), .A1 (n_3879), .B0 (n_1495), .Y + (n_3855)); + AOI21X1 g38424(.A0 (\u8_mem[3]_150 ), .A1 (n_3879), .B0 (n_1273), .Y + (n_3854)); + AOI21X1 g38456(.A0 (\u8_mem[3]_125 ), .A1 (n_3879), .B0 (n_1414), .Y + (n_3852)); + AOI21X1 g38459(.A0 (\u8_mem[3]_131 ), .A1 (n_3879), .B0 (n_1501), .Y + (n_3851)); + AOI21X1 g38460(.A0 (\u8_mem[3]_152 ), .A1 (n_3879), .B0 (n_1466), .Y + (n_3850)); + AOI21X1 g38470(.A0 (n_1484), .A1 (n_760), .B0 (n_1485), .Y (n_3849)); + NAND2X1 g39884(.A (\u7_mem[2]_36 ), .B (n_12645), .Y (n_3848)); + AOI21X1 g38475(.A0 (\u8_mem[3]_137 ), .A1 (n_3879), .B0 (n_1322), .Y + (n_3847)); + NAND2X1 g39879(.A (n_12679), .B (\u5_mem[0]_113 ), .Y (n_3846)); + AOI21X1 g38512(.A0 (\u8_mem[3]_135 ), .A1 (n_3879), .B0 (n_1464), .Y + (n_3845)); + NOR2X1 g39296(.A (n_3486), .B (n_2755), .Y (n_3844)); + AOI21X1 g38539(.A0 (\u8_mem[3]_138 ), .A1 (n_3879), .B0 (n_1457), .Y + (n_3843)); + AOI21X1 g38543(.A0 (\u8_mem[3]_133 ), .A1 (n_3879), .B0 (n_1556), .Y + (n_3842)); + AOI21X1 g38550(.A0 (\u8_mem[3]_132 ), .A1 (n_3879), .B0 (n_1435), .Y + (n_3841)); + NAND2X1 g39873(.A (n_12679), .B (\u5_mem[0]_111 ), .Y (n_3840)); + MX2X1 g38580(.A (\u8_mem[0]_114 ), .B (wb_din_684), .S0 (n_3826), .Y + (n_3838)); + MX2X1 g38581(.A (\u8_mem[0]_94 ), .B (wb_din_664), .S0 (n_3826), .Y + (n_3837)); + MX2X1 g38582(.A (\u8_mem[0]_113 ), .B (wb_din_683), .S0 (n_3826), .Y + (n_3836)); + MX2X1 g38583(.A (\u3_mem[0]_112 ), .B (wb_din_682), .S0 (n_858), .Y + (n_3834)); + MX2X1 g38584(.A (\u8_mem[0]_112 ), .B (wb_din_682), .S0 (n_3826), .Y + (n_3833)); + MX2X1 g38585(.A (\u8_mem[0]_93 ), .B (wb_din_663), .S0 (n_3826), .Y + (n_3832)); + MX2X1 g38586(.A (\u8_mem[0]_111 ), .B (wb_din_681), .S0 (n_3826), .Y + (n_3831)); + MX2X1 g38587(.A (\u8_mem[0]_110 ), .B (wb_din_680), .S0 (n_3826), .Y + (n_3830)); + MX2X1 g38588(.A (\u8_mem[0]_91 ), .B (wb_din_661), .S0 (n_3826), .Y + (n_3828)); + MX2X1 g38589(.A (\u8_mem[0]_109 ), .B (wb_din_679), .S0 (n_3826), .Y + (n_3827)); + MX2X1 g38590(.A (\u8_mem[0]_107 ), .B (wb_din_677), .S0 (n_3826), .Y + (n_3825)); + MX2X1 g38591(.A (\u8_mem[0]_105 ), .B (wb_din_675), .S0 (n_3826), .Y + (n_3824)); + MX2X1 g38592(.A (\u3_mem[0]_109 ), .B (wb_din_679), .S0 (n_3807), .Y + (n_3823)); + MX2X1 g38593(.A (\u8_mem[0]_121 ), .B (wb_din_691), .S0 (n_3826), .Y + (n_3822)); + MX2X1 g38594(.A (\u3_mem[0]_92 ), .B (wb_din_662), .S0 (n_858), .Y + (n_3820)); + MX2X1 g38595(.A (\u8_mem[0]_103 ), .B (wb_din_673), .S0 (n_3826), .Y + (n_3818)); + MX2X1 g38596(.A (\u8_mem[0]_102 ), .B (wb_din_672), .S0 (n_3826), .Y + (n_3817)); + MX2X1 g38597(.A (\u3_mem[0]_107 ), .B (wb_din_677), .S0 (n_3807), .Y + (n_3815)); + MX2X1 g38598(.A (\u8_mem[0]_101 ), .B (wb_din_671), .S0 (n_3826), .Y + (n_3814)); + MX2X1 g38599(.A (\u3_mem[0]_104 ), .B (wb_din_674), .S0 (n_3807), .Y + (n_3813)); + MX2X1 g38600(.A (\u3_mem[0]_102 ), .B (wb_din_672), .S0 (n_3807), .Y + (n_3812)); + MX2X1 g38601(.A (\u3_mem[0]_101 ), .B (wb_din_671), .S0 (n_3807), .Y + (n_3811)); + MX2X1 g38602(.A (\u3_mem[0]_100 ), .B (wb_din_670), .S0 (n_3807), .Y + (n_3809)); + MX2X1 g38603(.A (\u3_mem[0] ), .B (wb_din), .S0 (n_3807), .Y + (n_3808)); + MX2X1 g38604(.A (\u7_mem[0]_101 ), .B (wb_din_671), .S0 (n_913), .Y + (n_3806)); + MX2X1 g38605(.A (\u3_mem[0]_105 ), .B (wb_din_675), .S0 (n_3807), .Y + (n_3804)); + MX2X1 g38606(.A (\u4_mem[0] ), .B (wb_din), .S0 (n_3765), .Y + (n_3803)); + MX2X1 g38607(.A (\u4_mem[0]_100 ), .B (wb_din_670), .S0 (n_3765), .Y + (n_3802)); + MX2X1 g38608(.A (\u4_mem[0]_101 ), .B (wb_din_671), .S0 (n_3765), .Y + (n_3801)); + MX2X1 g38609(.A (\u4_mem[0]_102 ), .B (wb_din_672), .S0 (n_3765), .Y + (n_3799)); + MX2X1 g38610(.A (\u4_mem[0]_103 ), .B (wb_din_673), .S0 (n_3765), .Y + (n_3797)); + MX2X1 g38611(.A (\u4_mem[0]_104 ), .B (wb_din_674), .S0 (n_3765), .Y + (n_3796)); + MX2X1 g38612(.A (\u4_mem[0]_105 ), .B (wb_din_675), .S0 (n_3765), .Y + (n_3795)); + MX2X1 g38613(.A (\u7_mem[0]_106 ), .B (wb_din_676), .S0 (n_3622), .Y + (n_3792)); + MX2X1 g38614(.A (\u4_mem[0]_106 ), .B (wb_din_676), .S0 (n_3765), .Y + (n_3791)); + MX2X1 g38615(.A (\u4_mem[0]_95 ), .B (wb_din_665), .S0 (n_3765), .Y + (n_3790)); + MX2X1 g38616(.A (\u4_mem[0]_107 ), .B (wb_din_677), .S0 (n_835), .Y + (n_3788)); + MX2X1 g38617(.A (\u7_mem[0]_102 ), .B (wb_din_672), .S0 (n_913), .Y + (n_3786)); + MX2X1 g38618(.A (\u4_mem[0]_108 ), .B (wb_din_678), .S0 (n_3765), .Y + (n_3784)); + MX2X1 g38619(.A (\u4_mem[0]_109 ), .B (wb_din_679), .S0 (n_3765), .Y + (n_3783)); + MX2X1 g38620(.A (\u4_mem[0]_91 ), .B (wb_din_661), .S0 (n_3765), .Y + (n_3780)); + MX2X1 g38621(.A (\u4_mem[0]_110 ), .B (wb_din_680), .S0 (n_3765), .Y + (n_3779)); + MX2X1 g38622(.A (\u4_mem[0]_111 ), .B (wb_din_681), .S0 (n_3765), .Y + (n_3777)); + MX2X1 g38623(.A (\u4_mem[0]_112 ), .B (wb_din_682), .S0 (n_3765), .Y + (n_3776)); + MX2X1 g38624(.A (\u4_mem[0]_113 ), .B (wb_din_683), .S0 (n_3765), .Y + (n_3773)); + MX2X1 g38674(.A (\u3_mem[0]_95 ), .B (wb_din_665), .S0 (n_3807), .Y + (n_3771)); + MX2X1 g38625(.A (\u4_mem[0]_114 ), .B (wb_din_684), .S0 (n_3765), .Y + (n_3770)); + MX2X1 g38626(.A (\u4_mem[0]_115 ), .B (wb_din_685), .S0 (n_835), .Y + (n_3768)); + MX2X1 g38627(.A (\u4_mem[0]_116 ), .B (wb_din_686), .S0 (n_3765), .Y + (n_3766)); + MX2X1 g38628(.A (\u4_mem[0]_117 ), .B (wb_din_687), .S0 (n_3765), .Y + (n_3764)); + MX2X1 g38629(.A (\u4_mem[0]_118 ), .B (wb_din_688), .S0 (n_835), .Y + (n_3763)); + MX2X1 g38630(.A (\u4_mem[0]_119 ), .B (wb_din_689), .S0 (n_3765), .Y + (n_3762)); + MX2X1 g38631(.A (\u4_mem[0]_92 ), .B (wb_din_662), .S0 (n_835), .Y + (n_3761)); + MX2X1 g38632(.A (\u4_mem[0]_120 ), .B (wb_din_690), .S0 (n_3765), .Y + (n_3760)); + MX2X1 g38633(.A (\u4_mem[0]_121 ), .B (wb_din_691), .S0 (n_3765), .Y + (n_3759)); + MX2X1 g38634(.A (\u4_mem[0]_93 ), .B (wb_din_663), .S0 (n_3765), .Y + (n_3757)); + MX2X1 g38635(.A (\u4_mem[0]_94 ), .B (wb_din_664), .S0 (n_3765), .Y + (n_3756)); + MX2X1 g38636(.A (\u4_mem[0]_96 ), .B (wb_din_666), .S0 (n_3765), .Y + (n_3755)); + MX2X1 g38637(.A (\u4_mem[0]_97 ), .B (wb_din_667), .S0 (n_3765), .Y + (n_3754)); + MX2X1 g38638(.A (\u4_mem[0]_98 ), .B (wb_din_668), .S0 (n_3765), .Y + (n_3753)); + MX2X1 g38639(.A (\u4_mem[0]_99 ), .B (wb_din_669), .S0 (n_3765), .Y + (n_3752)); + MX2X1 g38640(.A (\u3_mem[0]_99 ), .B (wb_din_669), .S0 (n_858), .Y + (n_3751)); + MX2X1 g38641(.A (\u8_mem[0]_96 ), .B (wb_din_666), .S0 (n_3826), .Y + (n_3750)); + MX2X1 g38642(.A (\u8_mem[0]_120 ), .B (wb_din_690), .S0 (n_3826), .Y + (n_3748)); + MX2X1 g38643(.A (\u8_mem[0]_92 ), .B (wb_din_662), .S0 (n_3826), .Y + (n_3746)); + MX2X1 g38644(.A (\u3_mem[0]_93 ), .B (wb_din_663), .S0 (n_3807), .Y + (n_3744)); + MX2X1 g38645(.A (\u5_mem[0] ), .B (wb_din), .S0 (n_3720), .Y + (n_3741)); + MX2X1 g38646(.A (\u5_mem[0]_100 ), .B (wb_din_670), .S0 (n_3720), .Y + (n_3739)); + MX2X1 g38647(.A (\u5_mem[0]_101 ), .B (wb_din_671), .S0 (n_3720), .Y + (n_3737)); + MX2X1 g38648(.A (\u5_mem[0]_102 ), .B (wb_din_672), .S0 (n_3720), .Y + (n_3735)); + MX2X1 g38649(.A (\u5_mem[0]_104 ), .B (wb_din_674), .S0 (n_3720), .Y + (n_3734)); + MX2X1 g38650(.A (\u5_mem[0]_105 ), .B (wb_din_675), .S0 (n_3720), .Y + (n_3732)); + MX2X1 g38651(.A (\u5_mem[0]_106 ), .B (wb_din_676), .S0 (n_3720), .Y + (n_3731)); + MX2X1 g38652(.A (\u5_mem[0]_107 ), .B (wb_din_677), .S0 (n_3720), .Y + (n_3728)); + MX2X1 g38653(.A (\u5_mem[0]_108 ), .B (wb_din_678), .S0 (n_3720), .Y + (n_3727)); + MX2X1 g38654(.A (\u5_mem[0]_109 ), .B (wb_din_679), .S0 (n_3720), .Y + (n_3725)); + MX2X1 g38655(.A (\u5_mem[0]_91 ), .B (wb_din_661), .S0 (n_3720), .Y + (n_3724)); + MX2X1 g38656(.A (\u5_mem[0]_110 ), .B (wb_din_680), .S0 (n_3720), .Y + (n_3722)); + MX2X1 g38657(.A (\u5_mem[0]_111 ), .B (wb_din_681), .S0 (n_3720), .Y + (n_3719)); + MX2X1 g38658(.A (\u5_mem[0]_112 ), .B (wb_din_682), .S0 (n_3720), .Y + (n_3717)); + MX2X1 g38659(.A (\u5_mem[0]_113 ), .B (wb_din_683), .S0 (n_3720), .Y + (n_3715)); + MX2X1 g38660(.A (\u5_mem[0]_114 ), .B (wb_din_684), .S0 (n_3720), .Y + (n_3714)); + MX2X1 g38661(.A (\u5_mem[0]_115 ), .B (wb_din_685), .S0 (n_841), .Y + (n_3712)); + MX2X1 g38662(.A (\u7_mem[0] ), .B (wb_din), .S0 (n_3622), .Y + (n_3710)); + MX2X1 g38663(.A (\u5_mem[0]_116 ), .B (wb_din_686), .S0 (n_3720), .Y + (n_3709)); + MX2X1 g38664(.A (\u5_mem[0]_118 ), .B (wb_din_688), .S0 (n_3720), .Y + (n_3707)); + MX2X1 g38665(.A (\u5_mem[0]_119 ), .B (wb_din_689), .S0 (n_841), .Y + (n_3704)); + NAND2X1 g39251(.A (\u3_mem[1]_62 ), .B (n_3316), .Y (n_3701)); + MX2X1 g38666(.A (\u5_mem[0]_92 ), .B (wb_din_662), .S0 (n_841), .Y + (n_3700)); + MX2X1 g38667(.A (\u5_mem[0]_120 ), .B (wb_din_690), .S0 (n_3720), .Y + (n_3699)); + MX2X1 g38668(.A (\u5_mem[0]_121 ), .B (wb_din_691), .S0 (n_3720), .Y + (n_3698)); + MX2X1 g38669(.A (\u5_mem[0]_93 ), .B (wb_din_663), .S0 (n_3720), .Y + (n_3697)); + MX2X1 g38670(.A (\u5_mem[0]_94 ), .B (wb_din_664), .S0 (n_3720), .Y + (n_3696)); + MX2X1 g38671(.A (\u5_mem[0]_97 ), .B (wb_din_667), .S0 (n_3720), .Y + (n_3694)); + MX2X1 g38672(.A (\u5_mem[0]_98 ), .B (wb_din_668), .S0 (n_841), .Y + (n_3693)); + MX2X1 g38673(.A (\u5_mem[0]_99 ), .B (wb_din_669), .S0 (n_3720), .Y + (n_3692)); + MX2X1 g38675(.A (\u5_mem[0]_95 ), .B (wb_din_665), .S0 (n_3720), .Y + (n_3690)); + MX2X1 g38676(.A (\u5_mem[0]_96 ), .B (wb_din_666), .S0 (n_3720), .Y + (n_3688)); + MX2X1 g38677(.A (\u8_mem[0]_118 ), .B (wb_din_688), .S0 (n_3826), .Y + (n_3686)); + MX2X1 g38678(.A (\u7_mem[0]_104 ), .B (wb_din_674), .S0 (n_3622), .Y + (n_3684)); + MX2X1 g38679(.A (\u6_mem[0] ), .B (wb_din), .S0 (n_3632), .Y + (n_3683)); + MX2X1 g38680(.A (\u6_mem[0]_100 ), .B (wb_din_670), .S0 (n_813), .Y + (n_3682)); + MX2X1 g38681(.A (\u6_mem[0]_102 ), .B (wb_din_672), .S0 (n_3632), .Y + (n_3681)); + MX2X1 g38682(.A (\u6_mem[0]_103 ), .B (wb_din_673), .S0 (n_3632), .Y + (n_3679)); + MX2X1 g38683(.A (\u7_mem[0]_100 ), .B (wb_din_670), .S0 (n_3622), .Y + (n_3677)); + MX2X1 g38684(.A (\u6_mem[0]_105 ), .B (wb_din_675), .S0 (n_3632), .Y + (n_3676)); + MX2X1 g38685(.A (\u6_mem[0]_106 ), .B (wb_din_676), .S0 (n_3632), .Y + (n_3675)); + MX2X1 g38686(.A (\u6_mem[0]_108 ), .B (wb_din_678), .S0 (n_3632), .Y + (n_3674)); + MX2X1 g38687(.A (\u6_mem[0]_113 ), .B (wb_din_683), .S0 (n_3632), .Y + (n_3671)); + MX2X1 g38688(.A (\u6_mem[0]_116 ), .B (wb_din_686), .S0 (n_3632), .Y + (n_3670)); + NAND2X1 g39266(.A (n_4560), .B (in_slt_449), .Y (n_5317)); + MX2X1 g38689(.A (\u6_mem[0]_92 ), .B (wb_din_662), .S0 (n_3632), .Y + (n_3668)); + MX2X1 g38690(.A (\u6_mem[0]_120 ), .B (wb_din_690), .S0 (n_3632), .Y + (n_3667)); + MX2X1 g38691(.A (\u6_mem[0]_121 ), .B (wb_din_691), .S0 (n_3632), .Y + (n_3666)); + MX2X1 g38692(.A (\u6_mem[0]_95 ), .B (wb_din_665), .S0 (n_3632), .Y + (n_3664)); + MX2X1 g38693(.A (\u6_mem[0]_97 ), .B (wb_din_667), .S0 (n_813), .Y + (n_3663)); + MX2X1 g38694(.A (\u6_mem[0]_98 ), .B (wb_din_668), .S0 (n_813), .Y + (n_3660)); + MX2X1 g38695(.A (\u6_mem[0]_99 ), .B (wb_din_669), .S0 (n_3632), .Y + (n_3658)); + MX2X1 g38696(.A (\u5_mem[0]_117 ), .B (wb_din_687), .S0 (n_3720), .Y + (n_3656)); + MX2X1 g38697(.A (\u3_mem[0]_97 ), .B (wb_din_667), .S0 (n_3807), .Y + (n_3654)); + MX2X1 g38698(.A (\u6_mem[0]_96 ), .B (wb_din_666), .S0 (n_3632), .Y + (n_3652)); + MX2X1 g38699(.A (\u8_mem[0]_117 ), .B (wb_din_687), .S0 (n_3826), .Y + (n_3651)); + MX2X1 g38700(.A (\u8_mem[0]_98 ), .B (wb_din_668), .S0 (n_3826), .Y + (n_3649)); + MX2X1 g38701(.A (\u6_mem[0]_94 ), .B (wb_din_664), .S0 (n_3632), .Y + (n_3648)); + MX2X1 g38702(.A (\u7_mem[0]_103 ), .B (wb_din_673), .S0 (n_3622), .Y + (n_3647)); + MX2X1 g38703(.A (\u7_mem[0]_105 ), .B (wb_din_675), .S0 (n_3622), .Y + (n_3645)); + MX2X1 g38704(.A (\u7_mem[0]_107 ), .B (wb_din_677), .S0 (n_3622), .Y + (n_3644)); + MX2X1 g38706(.A (\u7_mem[0]_110 ), .B (wb_din_680), .S0 (n_913), .Y + (n_3642)); + MX2X1 g38707(.A (\u7_mem[0]_112 ), .B (wb_din_682), .S0 (n_3622), .Y + (n_3641)); + MX2X1 g38708(.A (\u7_mem[0]_114 ), .B (wb_din_684), .S0 (n_3622), .Y + (n_3639)); + MX2X1 g38709(.A (\u7_mem[0]_116 ), .B (wb_din_686), .S0 (n_3622), .Y + (n_3638)); + MX2X1 g38710(.A (\u7_mem[0]_118 ), .B (wb_din_688), .S0 (n_3622), .Y + (n_3636)); + MX2X1 g38711(.A (\u7_mem[0]_121 ), .B (wb_din_691), .S0 (n_3622), .Y + (n_3635)); + MX2X1 g38712(.A (\u6_mem[0]_119 ), .B (wb_din_689), .S0 (n_3632), .Y + (n_3633)); + MX2X1 g38713(.A (\u7_mem[0]_96 ), .B (wb_din_666), .S0 (n_3622), .Y + (n_3631)); + MX2X1 g38714(.A (\u6_mem[0]_91 ), .B (wb_din_661), .S0 (n_3632), .Y + (n_3630)); + MX2X1 g38715(.A (\u6_mem[0]_93 ), .B (wb_din_663), .S0 (n_3632), .Y + (n_3628)); + MX2X1 g38716(.A (\u3_mem[0]_114 ), .B (wb_din_684), .S0 (n_3807), .Y + (n_3627)); + MX2X1 g38717(.A (\u7_mem[0]_99 ), .B (wb_din_669), .S0 (n_3622), .Y + (n_3626)); + MX2X1 g38718(.A (\u7_mem[0]_98 ), .B (wb_din_668), .S0 (n_3622), .Y + (n_3625)); + MX2X1 g38719(.A (\u5_mem[0]_103 ), .B (wb_din_673), .S0 (n_3720), .Y + (n_3624)); + MX2X1 g38720(.A (\u7_mem[0]_97 ), .B (wb_din_667), .S0 (n_3622), .Y + (n_3623)); + MX2X1 g38721(.A (\u6_mem[0]_118 ), .B (wb_din_688), .S0 (n_3632), .Y + (n_3621)); + MX2X1 g38722(.A (\u7_mem[0]_95 ), .B (wb_din_665), .S0 (n_3622), .Y + (n_3620)); + MX2X1 g38723(.A (\u7_mem[0]_94 ), .B (wb_din_664), .S0 (n_3622), .Y + (n_3619)); + MX2X1 g38724(.A (\u6_mem[0]_117 ), .B (wb_din_687), .S0 (n_3632), .Y + (n_3617)); + MX2X1 g38725(.A (\u7_mem[0]_93 ), .B (wb_din_663), .S0 (n_3622), .Y + (n_3616)); + MX2X1 g38726(.A (\u6_mem[0]_115 ), .B (wb_din_685), .S0 (n_3632), .Y + (n_3615)); + MX2X1 g38727(.A (\u6_mem[0]_114 ), .B (wb_din_684), .S0 (n_3632), .Y + (n_3614)); + MX2X1 g38728(.A (\u7_mem[0]_120 ), .B (wb_din_690), .S0 (n_3622), .Y + (n_3613)); + MX2X1 g38729(.A (\u7_mem[0]_92 ), .B (wb_din_662), .S0 (n_3622), .Y + (n_3612)); + MX2X1 g38730(.A (\u6_mem[0]_112 ), .B (wb_din_682), .S0 (n_3632), .Y + (n_3611)); + MX2X1 g38731(.A (\u7_mem[0]_119 ), .B (wb_din_689), .S0 (n_3622), .Y + (n_3610)); + MX2X1 g38732(.A (\u6_mem[0]_110 ), .B (wb_din_680), .S0 (n_3632), .Y + (n_3609)); + MX2X1 g38733(.A (\u6_mem[0]_111 ), .B (wb_din_681), .S0 (n_3632), .Y + (n_3608)); + MX2X1 g38734(.A (\u7_mem[0]_117 ), .B (wb_din_687), .S0 (n_3622), .Y + (n_3607)); + MX2X1 g38735(.A (\u3_mem[0]_103 ), .B (wb_din_673), .S0 (n_3807), .Y + (n_3606)); + MX2X1 g38736(.A (\u8_mem[0] ), .B (wb_din), .S0 (n_3826), .Y + (n_3604)); + MX2X1 g38737(.A (\u3_mem[0]_106 ), .B (wb_din_676), .S0 (n_3807), .Y + (n_3603)); + MX2X1 g38738(.A (\u8_mem[0]_100 ), .B (wb_din_670), .S0 (n_3826), .Y + (n_3602)); + MX2X1 g38739(.A (\u3_mem[0]_108 ), .B (wb_din_678), .S0 (n_3807), .Y + (n_3601)); + MX2X1 g38740(.A (\u8_mem[0]_104 ), .B (wb_din_674), .S0 (n_3826), .Y + (n_3600)); + MX2X1 g38741(.A (\u8_mem[0]_106 ), .B (wb_din_676), .S0 (n_3826), .Y + (n_3599)); + MX2X1 g38742(.A (\u3_mem[0]_91 ), .B (wb_din_661), .S0 (n_3807), .Y + (n_3598)); + MX2X1 g38743(.A (\u8_mem[0]_108 ), .B (wb_din_678), .S0 (n_3826), .Y + (n_3596)); + MX2X1 g38744(.A (\u3_mem[0]_110 ), .B (wb_din_680), .S0 (n_3807), .Y + (n_3595)); + MX2X1 g38745(.A (\u3_mem[0]_111 ), .B (wb_din_681), .S0 (n_3807), .Y + (n_3593)); + MX2X1 g38746(.A (\u3_mem[0]_113 ), .B (wb_din_683), .S0 (n_3807), .Y + (n_3592)); + NAND2X1 g39254(.A (n_12204), .B (\u6_mem[0]_103 ), .Y (n_11699)); + MX2X1 g38747(.A (\u8_mem[0]_115 ), .B (wb_din_685), .S0 (n_3826), .Y + (n_3590)); + MX2X1 g38748(.A (\u8_mem[0]_116 ), .B (wb_din_686), .S0 (n_3826), .Y + (n_3589)); + MX2X1 g38749(.A (\u3_mem[0]_115 ), .B (wb_din_685), .S0 (n_3807), .Y + (n_3588)); + MX2X1 g38750(.A (\u8_mem[0]_119 ), .B (wb_din_689), .S0 (n_3826), .Y + (n_3587)); + MX2X1 g38751(.A (\u3_mem[0]_116 ), .B (wb_din_686), .S0 (n_3807), .Y + (n_3586)); + MX2X1 g38752(.A (\u3_mem[0]_117 ), .B (wb_din_687), .S0 (n_3807), .Y + (n_3585)); + MX2X1 g38753(.A (\u3_mem[0]_118 ), .B (wb_din_688), .S0 (n_3807), .Y + (n_3584)); + MX2X1 g38754(.A (\u8_mem[0]_95 ), .B (wb_din_665), .S0 (n_3826), .Y + (n_3583)); + MX2X1 g38755(.A (\u3_mem[0]_119 ), .B (wb_din_689), .S0 (n_3807), .Y + (n_3582)); + MX2X1 g38756(.A (\u8_mem[0]_99 ), .B (wb_din_669), .S0 (n_3826), .Y + (n_3580)); + MX2X1 g38757(.A (\u3_mem[0]_120 ), .B (wb_din_690), .S0 (n_3807), .Y + (n_3579)); + MX2X1 g38758(.A (\u3_mem[0]_121 ), .B (wb_din_691), .S0 (n_3807), .Y + (n_3577)); + MX2X1 g38759(.A (\u6_mem[0]_107 ), .B (wb_din_677), .S0 (n_3632), .Y + (n_3576)); + MX2X1 g38760(.A (\u3_mem[0]_94 ), .B (wb_din_664), .S0 (n_3807), .Y + (n_3575)); + MX2X1 g38761(.A (\u3_mem[0]_96 ), .B (wb_din_666), .S0 (n_858), .Y + (n_3574)); + MX2X1 g38762(.A (\u6_mem[0]_109 ), .B (wb_din_679), .S0 (n_3632), .Y + (n_3573)); + MX2X1 g38763(.A (\u3_mem[0]_98 ), .B (wb_din_668), .S0 (n_3807), .Y + (n_3572)); + MX2X1 g38764(.A (\u7_mem[0]_115 ), .B (wb_din_685), .S0 (n_3622), .Y + (n_3571)); + MX2X1 g38765(.A (\u8_mem[0]_97 ), .B (wb_din_667), .S0 (n_3826), .Y + (n_3570)); + MX2X1 g38766(.A (\u7_mem[0]_113 ), .B (wb_din_683), .S0 (n_3622), .Y + (n_3569)); + MX2X1 g38767(.A (\u7_mem[0]_111 ), .B (wb_din_681), .S0 (n_3622), .Y + (n_3568)); + MX2X1 g38768(.A (\u6_mem[0]_104 ), .B (wb_din_674), .S0 (n_3632), .Y + (n_3567)); + MX2X1 g38769(.A (\u7_mem[0]_91 ), .B (wb_din_661), .S0 (n_913), .Y + (n_3566)); + MX2X1 g38770(.A (\u6_mem[0]_101 ), .B (wb_din_671), .S0 (n_813), .Y + (n_3565)); + MX2X1 g38771(.A (\u7_mem[0]_108 ), .B (wb_din_678), .S0 (n_3622), .Y + (n_3564)); + INVX1 g38776(.A (n_4851), .Y (n_3563)); + INVX1 g38780(.A (n_4104), .Y (n_3561)); + OAI21X1 g38784(.A0 (n_1412), .A1 (n_3559), .B0 (n_923), .Y (n_3560)); + NAND2X1 g38802(.A (\u4_mem[3]_143 ), .B (n_3556), .Y (n_3557)); + NAND2X1 g38810(.A (\u4_mem[3]_150 ), .B (n_3556), .Y (n_3555)); + NAND2X1 g38811(.A (\u4_mem[3]_147 ), .B (n_3556), .Y (n_3554)); + NAND2X1 g39830(.A (\u7_mem[2]_48 ), .B (n_12654), .Y (n_3553)); + NAND2X1 g38815(.A (\u4_mem[3]_152 ), .B (n_3556), .Y (n_3552)); + NAND2X1 g38823(.A (\u4_mem[3]_142 ), .B (n_3556), .Y (n_3551)); + NAND2X1 g38825(.A (\u4_mem[3]_146 ), .B (n_3556), .Y (n_3550)); + NAND2X1 g38833(.A (n_9641), .B (n_1889), .Y (n_3549)); + NAND2X1 g38835(.A (\u4_mem[3]_149 ), .B (n_3556), .Y (n_3548)); + NAND2X1 g38841(.A (\u4_mem[3]_133 ), .B (n_3546), .Y (n_3547)); + NAND2X1 g38847(.A (\u5_mem[3]_145 ), .B (n_3543), .Y (n_3545)); + NAND2X1 g38854(.A (\u5_mem[3]_149 ), .B (n_3543), .Y (n_3544)); + NAND2X1 g38856(.A (\u5_mem[3]_151 ), .B (n_3543), .Y (n_3542)); + NAND2X1 g38858(.A (\u5_mem[3]_152 ), .B (n_3543), .Y (n_3540)); + NAND2X1 g38867(.A (\u4_mem[3]_137 ), .B (n_3546), .Y (n_3539)); + NAND2X1 g38868(.A (\u4_mem[3]_148 ), .B (n_3556), .Y (n_3538)); + NAND2X1 g38870(.A (\u4_mem[3]_145 ), .B (n_3556), .Y (n_3537)); + NAND2X1 g38883(.A (\u5_mem[3]_150 ), .B (n_3543), .Y (n_3536)); + NOR2X1 g39239(.A (n_4961), .B (n_2792), .Y (n_3535)); + NAND2X1 g38912(.A (\u4_mem[3]_127 ), .B (n_3546), .Y (n_3534)); + NAND2X1 g38914(.A (\u4_mem[3]_130 ), .B (n_3546), .Y (n_3533)); + NAND2X1 g38922(.A (\u4_mem[3]_131 ), .B (n_3546), .Y (n_3532)); + NAND2X1 g38923(.A (\u4_mem[3]_141 ), .B (n_3556), .Y (n_3531)); + NAND2X1 g38939(.A (\u4_mem[3]_144 ), .B (n_3556), .Y (n_3530)); + NAND2X1 g38940(.A (\u4_mem[3]_129 ), .B (n_3546), .Y (n_3529)); + NAND2X1 g38941(.A (\u5_mem[3]_148 ), .B (n_3543), .Y (n_3528)); + NAND2X1 g38984(.A (\u5_mem[3]_142 ), .B (n_3543), .Y (n_3527)); + NAND2X1 g38997(.A (\u5_mem[3]_141 ), .B (n_3543), .Y (n_3526)); + NOR2X1 g39000(.A (n_3486), .B (n_2744), .Y (n_3525)); + NAND2X1 g39001(.A (n_12825), .B (\u3_mem[0]_111 ), .Y (n_3524)); + NAND2X1 g39002(.A (\u7_mem[1]_79 ), .B (n_3522), .Y (n_3523)); + NAND2X1 g39004(.A (\u3_mem[1]_84 ), .B (n_3316), .Y (n_3521)); + NOR2X1 g39005(.A (n_3453), .B (n_2829), .Y (n_3520)); + NAND2X1 g39006(.A (n_12369), .B (\u6_mem[0]_120 ), .Y (n_3519)); + NAND2X1 g39007(.A (n_12826), .B (\u3_mem[0]_100 ), .Y (n_11719)); + NAND2X1 g39009(.A (n_12839), .B (\u4_mem[0]_107 ), .Y (n_3517)); + NAND2X1 g39014(.A (n_12389), .B (\u4_mem[0]_116 ), .Y (n_3516)); + NAND2X1 g39015(.A (n_3415), .B (in_slt_405), .Y (n_3515)); + NAND2X1 g39017(.A (\u7_mem[2]_46 ), .B (n_12645), .Y (n_3514)); + NOR2X1 g39018(.A (n_3089), .B (n_2686), .Y (n_3512)); + NOR2X1 g39019(.A (n_3486), .B (n_2732), .Y (n_3511)); + NAND2X1 g39020(.A (\u6_mem[2]_45 ), .B (n_3474), .Y (n_3509)); + NOR2X1 g39022(.A (n_3332), .B (n_2804), .Y (n_3507)); + NOR2X1 g39023(.A (n_3486), .B (n_3008), .Y (n_3506)); + NOR2X1 g39024(.A (n_3332), .B (n_2744), .Y (n_3505)); + NAND2X1 g39025(.A (n_12826), .B (\u3_mem[0]_108 ), .Y (n_3502)); + NOR2X1 g39026(.A (n_3453), .B (n_2741), .Y (n_3501)); + NAND2X1 g39029(.A (\u3_mem[1]_83 ), .B (n_3316), .Y (n_3499)); + NAND2X1 g39030(.A (\u4_mem[2]_54 ), .B (n_12079), .Y (n_3497)); + NAND2X1 g39032(.A (\u3_mem[2]_57 ), .B (n_3330), .Y (n_3495)); + NAND2X1 g39033(.A (\u6_mem[2]_57 ), .B (n_3423), .Y (n_3494)); + NAND2X1 g39035(.A (\u4_mem[2]_57 ), .B (n_12091), .Y (n_3493)); + INVX1 g39036(.A (n_4778), .Y (n_3492)); + NAND2X1 g39045(.A (n_4560), .B (in_slt_448), .Y (n_5335)); + NAND2X1 g39047(.A (n_4560), .B (in_slt_451), .Y (n_5313)); + NAND2X1 g39048(.A (n_12839), .B (\u4_mem[0]_117 ), .Y (n_3490)); + NAND2X1 g39049(.A (\u3_mem[1]_77 ), .B (n_3316), .Y (n_3489)); + NOR2X1 g39050(.A (n_3486), .B (n_2818), .Y (n_3487)); + NAND2X1 g39058(.A (\u3_mem[1]_68 ), .B (n_3316), .Y (n_12004)); + NAND2X1 g39060(.A (n_3252), .B (\u7_mem[0]_110 ), .Y (n_3483)); + NAND2X1 g39061(.A (n_12825), .B (\u3_mem[0]_114 ), .Y (n_3482)); + NAND2X1 g39065(.A (\u6_mem[2]_55 ), .B (n_3423), .Y (n_3480)); + NOR2X1 g39069(.A (n_3089), .B (n_2755), .Y (n_3478)); + NAND2X1 g39070(.A (\u6_mem[2]_47 ), .B (n_3474), .Y (n_12818)); + NAND2X1 g39071(.A (n_11804), .B (\u8_mem[0]_111 ), .Y (n_3473)); + NAND2X1 g39072(.A (n_12369), .B (\u6_mem[0]_118 ), .Y (n_3472)); + INVX1 g39073(.A (n_4757), .Y (n_3470)); + NAND2X1 g39077(.A (\u3_mem[1]_78 ), .B (n_3316), .Y (n_3469)); + NAND2X1 g39078(.A (\u6_mem[2]_56 ), .B (n_3423), .Y (n_3468)); + NOR2X1 g39079(.A (n_5138), .B (n_2831), .Y (n_3467)); + NAND2X1 g39080(.A (in_slt_413), .B (n_3415), .Y (n_3466)); + NOR2X1 g39081(.A (n_5138), .B (n_2702), .Y (n_3465)); + NOR2X1 g39082(.A (n_3089), .B (n_3008), .Y (n_3463)); + NAND2X1 g39085(.A (n_11804), .B (\u8_mem[0]_113 ), .Y (n_3460)); + NAND2X1 g39087(.A (n_4560), .B (in_slt_450), .Y (n_5315)); + NAND2X1 g39088(.A (n_11798), .B (\u8_mem[0]_100 ), .Y (n_11451)); + NAND2X1 g39089(.A (\u8_mem[1]_69 ), .B (n_12295), .Y (n_11452)); + NOR2X1 g39092(.A (n_3453), .B (n_2786), .Y (n_3455)); + NOR2X1 g39094(.A (n_3453), .B (n_2712), .Y (n_3454)); + NAND2X1 g39095(.A (\u7_mem[2]_49 ), .B (n_12654), .Y (n_3452)); + NAND2X1 g39096(.A (n_12204), .B (\u6_mem[0]_105 ), .Y (n_11703)); + NOR2X1 g39097(.A (n_3117), .B (n_2732), .Y (n_3449)); + NOR2X1 g39108(.A (n_4961), .B (n_2686), .Y (n_3446)); + NOR2X1 g39109(.A (n_3453), .B (n_2804), .Y (n_3444)); + NAND2X1 g39110(.A (\u8_mem[2]_54 ), .B (n_3441), .Y (n_3442)); + NAND2X1 g39112(.A (n_11798), .B (\u8_mem[0]_97 ), .Y (n_11445)); + NAND2X1 g39113(.A (\u8_mem[1]_66 ), .B (n_12295), .Y (n_11446)); + NAND2X1 g39116(.A (n_12369), .B (\u6_mem[0]_115 ), .Y (n_3437)); + NAND2X1 g39118(.A (n_3339), .B (in_slt_430), .Y (n_5287)); + NAND2X1 g39119(.A (n_12826), .B (\u3_mem[0]_115 ), .Y (n_3436)); + NOR2X1 g39124(.A (n_3486), .B (n_2786), .Y (n_3434)); + OR2X1 g39126(.A (n_3431), .B (n_1200), .Y (n_3432)); + NAND2X1 g39129(.A (n_12825), .B (\u3_mem[0]_121 ), .Y (n_3429)); + NAND2X1 g39132(.A (n_1377), .B (\u6_rp[3] ), .Y (n_4834)); + NOR2X1 g39133(.A (n_3089), .B (n_2732), .Y (n_3428)); + NOR2X1 g39136(.A (n_5138), .B (n_2765), .Y (n_3426)); + NOR2X1 g39140(.A (n_3089), .B (n_2707), .Y (n_3425)); + NAND2X1 g39141(.A (\u6_mem[2]_54 ), .B (n_3423), .Y (n_3424)); + NAND2X1 g39142(.A (n_12389), .B (\u4_mem[0]_119 ), .Y (n_3422)); + INVX1 g39143(.A (n_4749), .Y (n_3420)); + NAND2X1 g39145(.A (\u8_mem[1]_82 ), .B (n_12291), .Y (n_3419)); + NOR2X1 g39148(.A (n_3453), .B (n_3008), .Y (n_3417)); + NAND2X1 g39149(.A (in_slt_402), .B (n_3415), .Y (n_3416)); + INVX4 g39157(.A (n_1453), .Y (n_6972)); + NOR2X1 g40205(.A (n_2780), .B (n_2801), .Y (n_3412)); + NAND2X1 g39161(.A (\u3_mem[1]_79 ), .B (n_3316), .Y (n_3411)); + NOR2X1 g39163(.A (n_3332), .B (n_2741), .Y (n_3410)); + NOR2X1 g39167(.A (n_3453), .B (n_2707), .Y (n_3409)); + NOR2X1 g39168(.A (n_3453), .B (n_2732), .Y (n_3407)); + NAND2X1 g39169(.A (n_12826), .B (\u3_mem[0]_117 ), .Y (n_3406)); + NAND2X1 g39170(.A (\u3_mem[2]_30 ), .B (n_12619), .Y (n_3405)); + NAND2X1 g39173(.A (\u8_mem[1]_81 ), .B (n_12291), .Y (n_3404)); + NAND2X1 g39175(.A (\u3_mem[1] ), .B (n_3316), .Y (n_12831)); + NAND2X1 g39176(.A (\u4_mem[2]_58 ), .B (n_12079), .Y (n_3401)); + NOR2X1 g39177(.A (n_3089), .B (n_2684), .Y (n_3400)); + NAND2X1 g39182(.A (\u4_mem[2]_56 ), .B (n_12091), .Y (n_3399)); + NAND2X1 g39183(.A (n_11804), .B (\u8_mem[0]_112 ), .Y (n_3398)); + NAND2X1 g39184(.A (\u3_mem[1]_74 ), .B (n_3316), .Y (n_12833)); + NAND2X1 g39185(.A (\u3_mem[2]_41 ), .B (n_12619), .Y (n_3396)); + NAND2X1 g39186(.A (\u4_mem[2]_59 ), .B (n_12087), .Y (n_3394)); + NAND2X1 g39187(.A (n_12389), .B (\u4_mem[0]_109 ), .Y (n_3393)); + NOR2X1 g39190(.A (n_3089), .B (n_2864), .Y (n_3392)); + NOR2X1 g39191(.A (n_5138), .B (n_2794), .Y (n_3391)); + NAND2X1 g39192(.A (n_11798), .B (\u8_mem[0]_102 ), .Y (n_11453)); + NAND2X1 g39194(.A (n_3252), .B (\u7_mem[0]_116 ), .Y (n_3389)); + NAND2X1 g39195(.A (n_12840), .B (\u4_mem[0]_93 ), .Y (n_3388)); + NAND2X1 g39200(.A (\u3_mem[2]_31 ), .B (n_12619), .Y (n_3383)); + NOR2X1 g39202(.A (n_4961), .B (n_2765), .Y (n_3381)); + NAND2X1 g39203(.A (n_3252), .B (\u7_mem[0] ), .Y (n_3378)); + NAND2X1 g39205(.A (\u4_mem[2]_33 ), .B (n_12087), .Y (n_3376)); + NAND2X1 g39206(.A (\u3_mem[1]_76 ), .B (n_3316), .Y (n_3375)); + NAND2X1 g39207(.A (\u8_mem[1]_71 ), .B (n_12301), .Y (n_3374)); + NAND2X1 g39208(.A (in_slt_400), .B (n_3415), .Y (n_3373)); + NAND2X1 g39209(.A (n_12389), .B (\u4_mem[0]_100 ), .Y (n_11646)); + NOR2X1 g39210(.A (n_3089), .B (n_2712), .Y (n_3370)); + NAND2X1 g39211(.A (\u4_mem[2]_48 ), .B (n_12087), .Y (n_3367)); + NAND2X1 g39212(.A (n_12389), .B (\u4_mem[0]_110 ), .Y (n_3366)); + NOR2X1 g39213(.A (n_3453), .B (n_2782), .Y (n_3364)); + INVX1 g39214(.A (n_4764), .Y (n_3363)); + NAND2X1 g39216(.A (n_12840), .B (\u4_mem[0]_111 ), .Y (n_3362)); + NAND2X1 g39217(.A (\u8_mem[1]_73 ), .B (n_12295), .Y (n_11458)); + NAND2X1 g39218(.A (n_11798), .B (\u8_mem[0]_120 ), .Y (n_3360)); + NOR2X1 g39221(.A (n_3089), .B (n_2767), .Y (n_3358)); + NOR2X1 g39222(.A (n_3332), .B (n_2735), .Y (n_3357)); + NAND2X1 g39226(.A (\u8_mem[1]_64 ), .B (n_12291), .Y (n_3355)); + NAND2X1 g39228(.A (\u3_mem[1]_81 ), .B (n_3316), .Y (n_3354)); + NOR2X1 g39229(.A (n_3117), .B (n_2782), .Y (n_3353)); + NAND2X1 g39230(.A (in_slt_399), .B (n_3415), .Y (n_3351)); + NOR2X1 g39231(.A (n_5059), .B (n_2702), .Y (n_3350)); + NAND2X1 g39232(.A (in_slt_410), .B (n_3415), .Y (n_3348)); + NAND2X1 g39233(.A (in_slt_404), .B (n_3415), .Y (n_3347)); + NOR2X1 g39236(.A (n_3117), .B (n_2763), .Y (n_3346)); + NAND2X1 g39237(.A (n_1404), .B (\u3_rp[3] ), .Y (n_4836)); + NAND2X1 g39243(.A (n_4560), .B (in_slt_457), .Y (n_5298)); + NOR2X1 g39245(.A (n_3332), .B (n_2720), .Y (n_3344)); + NOR2X1 g39252(.A (n_3486), .B (n_2716), .Y (n_3343)); + NOR2X1 g39255(.A (n_4961), .B (n_2681), .Y (n_3342)); + NAND2X1 g39257(.A (n_4560), .B (in_slt_454), .Y (n_5309)); + NAND2X1 g39258(.A (\u3_mem[2]_39 ), .B (n_12619), .Y (n_3341)); + NAND2X1 g39260(.A (\u8_mem[2]_44 ), .B (n_3334), .Y (n_12036)); + NAND2X1 g39262(.A (n_3339), .B (in_slt_437), .Y (n_5339)); + NOR2X1 g39263(.A (n_5138), .B (n_2748), .Y (n_3338)); + NAND2X1 g39267(.A (\u3_mem[2]_37 ), .B (n_12619), .Y (n_3336)); + NAND2X1 g39268(.A (\u8_mem[2]_31 ), .B (n_3334), .Y (n_12038)); + NOR2X1 g39269(.A (n_3332), .B (n_2755), .Y (n_3333)); + NAND2X1 g39272(.A (\u3_mem[2]_55 ), .B (n_3330), .Y (n_3331)); + NOR2X1 g39273(.A (n_5138), .B (n_2772), .Y (n_3329)); + NAND2X1 g39277(.A (\u4_mem[2]_53 ), .B (n_12087), .Y (n_3328)); + NAND2X1 g39278(.A (n_12721), .B (\u3_mem[0]_99 ), .Y (n_12005)); + NOR2X1 g39281(.A (n_4961), .B (n_2684), .Y (n_3324)); + NOR2X1 g39282(.A (n_3453), .B (n_2748), .Y (n_3321)); + NOR2X1 g39284(.A (n_3332), .B (n_2765), .Y (n_3318)); + NAND2X1 g39285(.A (n_3316), .B (\u3_mem[1]_72 ), .Y (n_3317)); + NAND2X1 g39287(.A (\u3_mem[2]_50 ), .B (n_3330), .Y (n_3315)); + NAND2X1 g39288(.A (\u5_mem[1]_63 ), .B (n_3236), .Y (n_12800)); + NOR2X1 g39289(.A (n_3486), .B (n_2801), .Y (n_3313)); + NAND2X1 g39290(.A (n_12204), .B (\u6_mem[0]_101 ), .Y (n_11707)); + NOR2X1 g39291(.A (n_3453), .B (n_2691), .Y (n_3311)); + NOR2X1 g39292(.A (n_5102), .B (n_2829), .Y (n_3309)); + NOR2X1 g39294(.A (n_3486), .B (n_2681), .Y (n_3307)); + NOR2X1 g39297(.A (n_3486), .B (n_2741), .Y (n_3305)); + NOR2X1 g39298(.A (n_3486), .B (n_2735), .Y (n_3302)); + NOR2X1 g39299(.A (n_3486), .B (n_2720), .Y (n_3299)); + NAND2X1 g39300(.A (\u4_mem[2]_49 ), .B (n_12091), .Y (n_3297)); + NOR2X1 g39301(.A (n_3332), .B (n_2786), .Y (n_3296)); + NOR2X1 g39302(.A (n_5102), .B (n_2729), .Y (n_3295)); + NOR2X1 g39304(.A (n_5102), .B (n_2684), .Y (n_3293)); + NOR2X1 g39305(.A (n_3486), .B (n_2831), .Y (n_3292)); + NAND2X1 g39306(.A (in_slt_398), .B (n_3415), .Y (n_3291)); + NAND2X1 g39307(.A (n_12369), .B (\u6_mem[0]_113 ), .Y (n_3290)); + NAND2X1 g39308(.A (\u3_mem[2]_35 ), .B (n_3207), .Y (n_3289)); + NAND2X1 g39310(.A (\u5_mem[1]_79 ), .B (n_3236), .Y (n_3288)); + NAND2X1 g39311(.A (n_12721), .B (\u3_mem[0]_96 ), .Y (n_3287)); + NOR2X1 g39312(.A (n_3332), .B (n_2782), .Y (n_3285)); + NAND2X1 g39313(.A (\u6_mem[2]_48 ), .B (n_3423), .Y (n_3283)); + NAND2X1 g39314(.A (\u8_mem[1]_80 ), .B (n_12291), .Y (n_3282)); + NOR2X1 g39315(.A (n_3486), .B (n_2804), .Y (n_3280)); + NOR2X1 g39316(.A (n_5102), .B (n_2748), .Y (n_3279)); + NAND2X1 g39317(.A (\u3_mem[1]_66 ), .B (n_3316), .Y (n_3278)); + NAND2X1 g39319(.A (n_4560), .B (in_slt_453), .Y (n_5280)); + NAND2X1 g39320(.A (\u7_mem[2]_30 ), .B (n_12654), .Y (n_3277)); + NAND2X1 g39321(.A (\u3_mem[2]_33 ), .B (n_12619), .Y (n_11738)); + INVX1 g39322(.A (n_4769), .Y (n_3275)); + NAND2X1 g39326(.A (\u5_mem[1]_87 ), .B (n_3209), .Y (n_3274)); + NAND2X1 g39327(.A (\u8_mem[1]_61 ), .B (n_12291), .Y (n_12843)); + NAND2X1 g39329(.A (\u5_mem[1] ), .B (n_3236), .Y (n_11495)); + NAND2X1 g39330(.A (n_3259), .B (\u5_mem[0] ), .Y (n_3270)); + NAND2X1 g39334(.A (\u5_mem[1]_65 ), .B (n_3257), .Y (n_12807)); + NAND2X1 g39335(.A (n_3255), .B (\u5_mem[0]_96 ), .Y (n_3268)); + NAND2X1 g39337(.A (n_12826), .B (\u3_mem[0]_101 ), .Y (n_11721)); + NAND2X1 g39338(.A (\u6_mem[2]_40 ), .B (n_3474), .Y (n_11698)); + NAND2X1 g39339(.A (\u5_mem[1]_81 ), .B (n_3239), .Y (n_3264)); + NAND2X1 g39341(.A (\u5_mem[1]_67 ), .B (n_3236), .Y (n_12034)); + NAND2X1 g39342(.A (n_3259), .B (\u5_mem[0]_98 ), .Y (n_3261)); + NAND2X1 g39344(.A (n_3259), .B (\u5_mem[0]_100 ), .Y (n_3260)); + NAND2X1 g39347(.A (\u5_mem[1]_66 ), .B (n_3257), .Y (n_3258)); + NAND2X1 g39348(.A (n_3255), .B (\u5_mem[0]_97 ), .Y (n_3256)); + NAND2X1 g39351(.A (n_3259), .B (\u5_mem[0]_99 ), .Y (n_3254)); + NAND2X1 g39352(.A (n_3252), .B (\u7_mem[0]_120 ), .Y (n_3253)); + NAND2X1 g39353(.A (n_3259), .B (\u5_mem[0]_101 ), .Y (n_3251)); + NAND2X1 g39355(.A (\u8_mem[2]_29 ), .B (n_3334), .Y (n_11741)); + NAND2X1 g39357(.A (\u4_mem[2]_40 ), .B (n_12079), .Y (n_3248)); + NOR2X1 g39358(.A (n_3486), .B (n_2763), .Y (n_3246)); + NAND2X1 g39359(.A (\u5_mem[1]_71 ), .B (n_3236), .Y (n_12796)); + NAND2X1 g39360(.A (n_3259), .B (\u5_mem[0]_102 ), .Y (n_12853)); + NOR2X1 g39362(.A (n_4961), .B (n_2818), .Y (n_3242)); + NAND2X1 g39364(.A (\u5_mem[1]_84 ), .B (n_3239), .Y (n_3240)); + NAND2X1 g39365(.A (n_12679), .B (\u5_mem[0]_115 ), .Y (n_3238)); + NAND2X1 g39366(.A (\u5_mem[1]_72 ), .B (n_3236), .Y (n_12798)); + NOR2X1 g39368(.A (n_3332), .B (n_3008), .Y (n_3235)); + NOR2X1 g39369(.A (n_3332), .B (n_2767), .Y (n_3234)); + NAND2X1 g39371(.A (n_12679), .B (\u5_mem[0]_116 ), .Y (n_3231)); + NAND2X1 g39372(.A (\u5_mem[1]_73 ), .B (n_3257), .Y (n_12805)); + NAND2X2 g39373(.A (n_3259), .B (\u5_mem[0]_104 ), .Y (n_3229)); + NOR2X1 g39374(.A (n_3332), .B (n_2684), .Y (n_3228)); + NAND2X1 g39375(.A (\u3_mem[2]_47 ), .B (n_12619), .Y (n_3227)); + NAND2X1 g39377(.A (\u8_mem[1]_67 ), .B (n_12295), .Y (n_11448)); + NAND2X1 g39378(.A (n_12840), .B (\u4_mem[0]_113 ), .Y (n_3225)); + NAND2X1 g39379(.A (n_12679), .B (\u5_mem[0]_117 ), .Y (n_3224)); + NAND2X1 g39380(.A (in_slt_411), .B (n_3415), .Y (n_3223)); + NAND2X1 g39381(.A (\u5_mem[1]_74 ), .B (n_3236), .Y (n_12842)); + NOR2X1 g39387(.A (n_3332), .B (n_2763), .Y (n_3220)); + NAND2X1 g39388(.A (\u5_mem[1]_75 ), .B (n_3257), .Y (n_3218)); + NAND2X1 g39389(.A (n_3259), .B (\u5_mem[0]_106 ), .Y (n_11966)); + NAND2X1 g39393(.A (\u5_mem[1]_88 ), .B (n_3239), .Y (n_3215)); + NAND2X1 g39394(.A (n_12679), .B (\u5_mem[0]_119 ), .Y (n_3214)); + NAND2X1 g39397(.A (\u3_mem[1]_80 ), .B (n_3316), .Y (n_3213)); + NAND2X1 g39398(.A (n_12679), .B (\u5_mem[0]_120 ), .Y (n_3212)); + NAND2X1 g39402(.A (\u5_mem[1]_90 ), .B (n_3209), .Y (n_3210)); + NAND2X1 g39404(.A (\u3_mem[2]_38 ), .B (n_3207), .Y (n_3208)); + NAND2X1 g39405(.A (\u5_mem[1]_78 ), .B (n_3209), .Y (n_3206)); + NAND2X1 g39406(.A (n_3259), .B (\u5_mem[0]_109 ), .Y (n_3205)); + NOR2X1 g39407(.A (n_5059), .B (n_2794), .Y (n_3204)); + NAND2X1 g39408(.A (n_3255), .B (\u5_mem[0]_91 ), .Y (n_3202)); + NAND2X1 g39411(.A (\u5_mem[1]_61 ), .B (n_3236), .Y (n_11444)); + NAND2X1 g39412(.A (n_12721), .B (\u3_mem[0]_107 ), .Y (n_3199)); + NOR2X1 g39413(.A (n_3453), .B (n_2720), .Y (n_3198)); + NAND2X1 g39414(.A (in_slt_401), .B (n_3415), .Y (n_3195)); + NAND2X1 g39769(.A (\u5_mem[1]_68 ), .B (n_1035), .Y (n_3194)); + NAND2X1 g39415(.A (n_3255), .B (\u5_mem[0]_93 ), .Y (n_3193)); + NAND2X1 g39417(.A (n_3259), .B (\u5_mem[0]_94 ), .Y (n_3192)); + NAND2X1 g39424(.A (\u8_mem[1]_79 ), .B (n_12291), .Y (n_3191)); + NAND2X1 g39425(.A (\u5_mem[1]_64 ), .B (n_3257), .Y (n_12809)); + NAND2X1 g39429(.A (n_12389), .B (\u4_mem[0]_98 ), .Y (n_11660)); + NAND2X1 g39430(.A (\u7_mem[2]_38 ), .B (n_12641), .Y (n_3188)); + NAND2X1 g39434(.A (n_12679), .B (\u5_mem[0]_110 ), .Y (n_3186)); + NOR2X1 g39436(.A (n_3486), .B (n_2790), .Y (n_3185)); + NAND2X1 g39437(.A (\u3_mem[2]_56 ), .B (n_3330), .Y (n_3184)); + NAND2X1 g39439(.A (\u3_mem[1]_60 ), .B (n_3316), .Y (n_3183)); + NAND2X1 g39442(.A (\u3_mem[1]_75 ), .B (n_3316), .Y (n_3181)); + NOR2X1 g39443(.A (n_5059), .B (n_2831), .Y (n_3180)); + NOR2X1 g39444(.A (n_5059), .B (n_2732), .Y (n_3177)); + NAND2X1 g39447(.A (\u5_mem[1]_83 ), .B (n_3239), .Y (n_3176)); + NOR2X1 g39448(.A (n_3332), .B (n_2790), .Y (n_3175)); + NAND2X1 g39449(.A (n_3252), .B (\u7_mem[0]_117 ), .Y (n_3173)); + NOR2X1 g39450(.A (n_3453), .B (n_2767), .Y (n_3172)); + NAND2X1 g39451(.A (n_3252), .B (\u7_mem[0]_98 ), .Y (n_3171)); + NAND2X1 g39452(.A (\u5_mem[1]_62 ), .B (n_3236), .Y (n_11440)); + NOR2X1 g39453(.A (n_3332), .B (n_2792), .Y (n_3169)); + NOR2X1 g39454(.A (n_3332), .B (n_2729), .Y (n_3167)); + NAND2X1 g39455(.A (\u4_mem[2]_38 ), .B (n_12079), .Y (n_3166)); + NAND2X1 g39459(.A (n_12826), .B (\u3_mem[0]_95 ), .Y (n_11737)); + NOR2X1 g39460(.A (n_3332), .B (n_2707), .Y (n_3164)); + NOR2X1 g39462(.A (n_3453), .B (n_2735), .Y (n_3163)); + NAND2X1 g39464(.A (n_12369), .B (\u6_mem[0]_112 ), .Y (n_3162)); + NAND2X1 g39465(.A (\u7_mem[1]_77 ), .B (n_3522), .Y (n_3161)); + NAND2X1 g39467(.A (n_11789), .B (\u8_mem[0]_114 ), .Y (n_3160)); + NAND2X1 g39469(.A (n_12825), .B (\u3_mem[0]_113 ), .Y (n_3159)); + NAND2X1 g39470(.A (\u8_mem[1]_88 ), .B (n_12291), .Y (n_3158)); + NAND2X1 g39472(.A (n_12389), .B (\u4_mem[0]_95 ), .Y (n_11666)); + NAND2X1 g39476(.A (n_11798), .B (\u8_mem[0]_105 ), .Y (n_11461)); + NOR2X1 g39477(.A (n_3117), .B (n_2786), .Y (n_3154)); + NAND2X1 g39478(.A (n_12204), .B (\u6_mem[0]_95 ), .Y (n_11711)); + NOR2X1 g39484(.A (n_5138), .B (n_2735), .Y (n_3151)); + NAND2X1 g39485(.A (n_12721), .B (\u3_mem[0]_93 ), .Y (n_3150)); + NAND2X1 g39763(.A (n_4560), .B (in_slt_456), .Y (n_5304)); + NAND2X1 g39487(.A (n_12204), .B (\u6_mem[0]_94 ), .Y (n_11709)); + NAND2X1 g39489(.A (n_12826), .B (\u3_mem[0] ), .Y (n_12832)); + NAND2X1 g39491(.A (\u8_mem[1]_63 ), .B (n_12295), .Y (n_11464)); + NAND2X1 g39493(.A (\u8_mem[2]_59 ), .B (n_3441), .Y (n_3144)); + NAND2X1 g39496(.A (\u3_mem[2]_36 ), .B (n_12619), .Y (n_3143)); + NAND2X1 g39497(.A (n_12369), .B (\u6_mem[0]_92 ), .Y (n_3142)); + NAND2X1 g39500(.A (n_12840), .B (\u4_mem[0]_104 ), .Y (n_11650)); + INVX1 g39501(.A (n_4772), .Y (n_3138)); + INVX1 g39503(.A (n_4743), .Y (n_3137)); + NAND2X1 g39505(.A (n_11798), .B (\u8_mem[0]_116 ), .Y (n_3136)); + NAND2X1 g39506(.A (\u3_mem[1]_61 ), .B (n_3316), .Y (n_3135)); + NAND2X1 g39507(.A (n_12389), .B (\u4_mem[0]_115 ), .Y (n_3134)); + NOR2X1 g39508(.A (n_3117), .B (n_2735), .Y (n_3133)); + NOR2X1 g39509(.A (n_3117), .B (n_2818), .Y (n_3132)); + NOR2X1 g39511(.A (n_3117), .B (n_2792), .Y (n_3131)); + NAND2X1 g39512(.A (\u5_mem[1]_85 ), .B (n_3239), .Y (n_3130)); + NAND2X1 g39514(.A (n_3339), .B (in_slt_428), .Y (n_5290)); + NOR2X1 g39515(.A (n_3117), .B (n_2684), .Y (n_3129)); + NOR2X1 g39516(.A (n_4996), .B (n_2790), .Y (n_3128)); + NAND2X1 g39517(.A (\u3_mem[2]_29 ), .B (n_12619), .Y (n_3126)); + NAND2X1 g39518(.A (n_12369), .B (\u6_mem[0]_108 ), .Y (n_3125)); + NAND2X1 g39519(.A (\u7_mem[1]_66 ), .B (n_3522), .Y (n_3124)); + NOR2X1 g39520(.A (n_4996), .B (n_2767), .Y (n_3123)); + NAND2X1 g39521(.A (\u3_mem[2]_58 ), .B (n_3330), .Y (n_3122)); + NOR2X1 g39522(.A (n_3332), .B (n_2818), .Y (n_3121)); + NAND2X1 g39523(.A (\u7_mem[2]_40 ), .B (n_12645), .Y (n_3120)); + NAND2X1 g39524(.A (\u3_mem[2]_45 ), .B (n_12619), .Y (n_3119)); + NOR2X1 g39525(.A (n_3117), .B (n_2748), .Y (n_3118)); + NOR2X1 g39526(.A (n_4996), .B (n_2804), .Y (n_3116)); + NOR2X1 g39529(.A (n_4996), .B (n_2794), .Y (n_3114)); + NAND2X1 g39531(.A (\u7_mem[2]_42 ), .B (n_12645), .Y (n_3112)); + NOR2X1 g39532(.A (n_3117), .B (n_2712), .Y (n_3111)); + NAND2X1 g39534(.A (\u4_mem[2]_51 ), .B (n_12091), .Y (n_3109)); + NAND2X1 g39535(.A (n_12839), .B (\u4_mem[0]_91 ), .Y (n_3108)); + NAND2X1 g39536(.A (\u3_mem[1]_87 ), .B (n_3316), .Y (n_3107)); + NAND2X1 g39538(.A (\u7_mem[2]_33 ), .B (n_12654), .Y (n_3106)); + NAND2X1 g39539(.A (\u7_mem[1]_68 ), .B (n_3522), .Y (n_3105)); + NAND2X1 g39540(.A (n_12839), .B (\u4_mem[0]_112 ), .Y (n_3104)); + NOR2X1 g39542(.A (n_3453), .B (n_2790), .Y (n_3103)); + NAND2X1 g39543(.A (\u8_mem[1]_60 ), .B (n_12295), .Y (n_11499)); + NAND2X1 g39545(.A (n_12204), .B (\u6_mem[0] ), .Y (n_11751)); + NAND2X1 g39547(.A (\u8_mem[1]_74 ), .B (n_12295), .Y (n_11462)); + NAND2X1 g39549(.A (\u7_mem[2]_39 ), .B (n_12654), .Y (n_3098)); + NAND2X1 g39551(.A (n_12204), .B (\u6_mem[0]_96 ), .Y (n_11713)); + NAND2X1 g39561(.A (\u6_mem[2]_51 ), .B (n_3423), .Y (n_3094)); + NAND2X1 g39563(.A (\u7_mem[2]_41 ), .B (n_12641), .Y (n_3093)); + INVX1 g39564(.A (n_4755), .Y (n_3092)); + NAND2X1 g39566(.A (\u6_mem[2]_37 ), .B (n_3474), .Y (n_3091)); + NOR2X1 g39567(.A (n_3089), .B (n_2691), .Y (n_3090)); + NAND2X1 g39574(.A (\u8_mem[1]_65 ), .B (n_12295), .Y (n_11466)); + NAND2X1 g39577(.A (\u5_mem[1]_86 ), .B (n_3239), .Y (n_3087)); + NAND2X1 g39579(.A (n_12369), .B (\u6_mem[0]_114 ), .Y (n_3086)); + NAND2X1 g39580(.A (\u8_mem[2]_57 ), .B (n_3441), .Y (n_3084)); + NAND2X1 g39581(.A (n_12204), .B (\u6_mem[0]_102 ), .Y (n_11697)); + NAND2X1 g39583(.A (n_12825), .B (\u3_mem[0]_110 ), .Y (n_3082)); + NAND2X1 g39586(.A (in_slt_412), .B (n_3415), .Y (n_3081)); + NAND2X1 g39587(.A (\u6_mem[2]_53 ), .B (n_3423), .Y (n_3080)); + NOR2X1 g39588(.A (n_3453), .B (n_2716), .Y (n_3079)); + NAND2X1 g39589(.A (\u8_mem[1]_78 ), .B (n_12291), .Y (n_3078)); + NAND2X1 g39590(.A (n_12840), .B (\u4_mem[0] ), .Y (n_11670)); + NOR2X1 g39591(.A (n_4961), .B (n_2729), .Y (n_3076)); + NAND2X1 g39593(.A (\u8_mem[1]_90 ), .B (n_12291), .Y (n_3074)); + NAND2X1 g39595(.A (n_12369), .B (\u6_mem[0]_116 ), .Y (n_3073)); + NAND2X1 g39598(.A (n_12679), .B (\u5_mem[0]_114 ), .Y (n_3071)); + NAND2X1 g39600(.A (n_12204), .B (\u6_mem[0]_117 ), .Y (n_3070)); + NAND2X1 g39601(.A (\u5_mem[1]_82 ), .B (n_3239), .Y (n_3069)); + NOR2X1 g39603(.A (n_3089), .B (n_2782), .Y (n_3067)); + NAND2X1 g39604(.A (n_11789), .B (\u8_mem[0]_121 ), .Y (n_3066)); + NOR2X1 g39605(.A (n_3453), .B (n_2772), .Y (n_3065)); + NOR2X1 g39606(.A (n_3117), .B (n_2691), .Y (n_3063)); + INVX1 g39607(.A (n_4759), .Y (n_3061)); + INVX1 g39609(.A (n_4776), .Y (n_3060)); + NAND2X1 g39611(.A (\u3_mem[1]_63 ), .B (n_12753), .Y (n_11730)); + NOR2X1 g39612(.A (n_3117), .B (n_2686), .Y (n_3058)); + NAND2X1 g39613(.A (n_12204), .B (\u6_mem[0]_119 ), .Y (n_3057)); + NAND2X1 g39616(.A (n_4560), .B (in_slt_459), .Y (n_5300)); + NAND2X1 g39617(.A (n_12369), .B (\u6_mem[0]_107 ), .Y (n_3056)); + NAND2X1 g39620(.A (n_4560), .B (in_slt_455), .Y (n_5307)); + NAND2X1 g39621(.A (\u6_mem[2]_58 ), .B (n_3423), .Y (n_3054)); + NOR2X1 g39741(.A (n_3117), .B (n_2729), .Y (n_3053)); + NAND2X1 g39626(.A (\u8_mem[2]_48 ), .B (n_3441), .Y (n_3052)); + NAND2X1 g39627(.A (\u6_mem[2]_59 ), .B (n_3423), .Y (n_3051)); + NAND2X1 g39628(.A (n_12204), .B (\u6_mem[0]_109 ), .Y (n_12817)); + NAND2X1 g39630(.A (\u6_mem[2]_29 ), .B (n_3474), .Y (n_12819)); + NAND2X1 g39631(.A (\u5_mem[1]_60 ), .B (n_3236), .Y (n_11442)); + NAND2X1 g39633(.A (\u6_mem[2]_31 ), .B (n_3474), .Y (n_12821)); + NAND2X1 g39637(.A (\u3_mem[1]_88 ), .B (n_3316), .Y (n_3045)); + NAND2X1 g39638(.A (n_3252), .B (\u7_mem[0]_114 ), .Y (n_3044)); + NAND2X1 g39639(.A (n_3259), .B (\u5_mem[0]_121 ), .Y (n_3043)); + NAND2X1 g39640(.A (\u8_mem[1] ), .B (n_12295), .Y (n_11468)); + NAND2X1 g39641(.A (n_12369), .B (\u6_mem[0]_110 ), .Y (n_3041)); + NOR2X1 g39642(.A (n_3332), .B (n_2716), .Y (n_3040)); + NAND2X1 g39643(.A (\u6_mem[2]_49 ), .B (n_3423), .Y (n_3038)); + NAND2X1 g39646(.A (n_12204), .B (\u6_mem[0]_111 ), .Y (n_3037)); + NAND2X1 g39648(.A (n_3339), .B (in_slt_435), .Y (n_5284)); + NAND2X1 g39649(.A (n_12389), .B (\u4_mem[0]_121 ), .Y (n_3036)); + NOR2X1 g39652(.A (n_5059), .B (n_2772), .Y (n_3035)); + NOR2X1 g39653(.A (n_3453), .B (n_2744), .Y (n_3032)); + NOR2X1 g39654(.A (n_4996), .B (n_2765), .Y (n_3031)); + NAND2X1 g39655(.A (n_11804), .B (\u8_mem[0]_110 ), .Y (n_3030)); + NAND2X1 g39656(.A (\u7_mem[2]_29 ), .B (n_12645), .Y (n_3029)); + NOR2X1 g39664(.A (n_3117), .B (n_2744), .Y (n_3027)); + NAND2X1 g39676(.A (\u5_mem[1]_76 ), .B (n_3236), .Y (n_11482)); + NOR2X1 g39682(.A (n_3117), .B (n_2801), .Y (n_3023)); + INVX1 g42379(.A (n_9833), .Y (n_10916)); + NOR2X1 g39686(.A (n_3332), .B (n_2748), .Y (n_3022)); + NAND2X1 g39688(.A (u11_din_tmp_50), .B (n_4560), .Y (n_3020)); + NAND2X1 g39690(.A (\u3_mem[2]_43 ), .B (n_3207), .Y (n_3019)); + NOR2X1 g39693(.A (n_3117), .B (n_2864), .Y (n_3018)); + NAND2X1 g39694(.A (\u8_mem[1]_89 ), .B (n_12291), .Y (n_3016)); + NOR2X1 g39696(.A (n_3453), .B (n_2864), .Y (n_3015)); + NAND2X1 g39697(.A (\u3_mem[1]_65 ), .B (n_3316), .Y (n_3014)); + NAND2X1 g39698(.A (\u4_mem[2]_50 ), .B (n_12091), .Y (n_3013)); + NAND2X1 g39699(.A (n_11789), .B (\u8_mem[0]_94 ), .Y (n_11463)); + NOR2X1 g39701(.A (n_3117), .B (n_3008), .Y (n_3010)); + NOR2X1 g39703(.A (n_5102), .B (n_2686), .Y (n_3007)); + NOR2X1 g39707(.A (n_3117), .B (n_2702), .Y (n_3006)); + NAND2X1 g39709(.A (n_11789), .B (\u8_mem[0]_107 ), .Y (n_11668)); + NAND2X1 g39710(.A (n_12825), .B (\u3_mem[0]_119 ), .Y (n_3004)); + NAND2X1 g39711(.A (\u3_mem[1]_90 ), .B (n_3316), .Y (n_3003)); + NAND2X1 g39712(.A (\u5_mem[1]_70 ), .B (n_3236), .Y (n_12032)); + NOR2X1 g39713(.A (n_3117), .B (n_2831), .Y (n_3001)); + NAND2X1 g39715(.A (n_12721), .B (\u3_mem[0]_97 ), .Y (n_3000)); + NAND2X1 g39716(.A (n_3252), .B (\u7_mem[0]_111 ), .Y (n_2999)); + NOR2X1 g39717(.A (n_3332), .B (n_2864), .Y (n_2998)); + NAND2X1 g39720(.A (n_11798), .B (\u8_mem[0]_118 ), .Y (n_2997)); + NAND2X1 g39721(.A (\u3_mem[2]_44 ), .B (n_12619), .Y (n_2996)); + NAND2X1 g39723(.A (n_4560), .B (in_slt_452), .Y (n_5321)); + NAND2X1 g39725(.A (n_12204), .B (\u6_mem[0]_121 ), .Y (n_2995)); + INVX1 g39728(.A (n_4745), .Y (n_2994)); + NAND2X1 g39730(.A (n_3252), .B (\u7_mem[0]_112 ), .Y (n_2993)); + NOR2X1 g39731(.A (n_5102), .B (n_2772), .Y (n_2992)); + INVX1 g39733(.A (n_4767), .Y (n_2989)); + NAND2X1 g39735(.A (n_12839), .B (\u4_mem[0]_96 ), .Y (n_12829)); + NOR2X1 g39738(.A (n_3332), .B (n_2829), .Y (n_2987)); + OR2X1 g39740(.A (n_1052), .B (\u3_rp[3] ), .Y (n_2986)); + NOR2X1 g39742(.A (n_5138), .B (n_2681), .Y (n_2985)); + NAND2X1 g39744(.A (n_12825), .B (\u3_mem[0]_120 ), .Y (n_2984)); + NAND2X1 g39745(.A (\u4_mem[2]_55 ), .B (n_12087), .Y (n_2983)); + NAND2X1 g39746(.A (n_12679), .B (\u5_mem[0]_118 ), .Y (n_2982)); + NAND2X1 g39747(.A (\u3_mem[2]_51 ), .B (n_3330), .Y (n_2981)); + NAND2X1 g39748(.A (n_12389), .B (\u4_mem[0]_101 ), .Y (n_11654)); + NAND2X1 g39751(.A (n_3339), .B (in_slt_431), .Y (n_5355)); + NAND2X1 g39752(.A (n_12389), .B (\u4_mem[0]_97 ), .Y (n_11658)); + NOR2X1 g39753(.A (n_3332), .B (n_2712), .Y (n_2977)); + NOR2X1 g39754(.A (n_4961), .B (n_2831), .Y (n_2976)); + NOR2X1 g39756(.A (n_4996), .B (n_2707), .Y (n_2975)); + NAND2X1 g39757(.A (n_11789), .B (\u8_mem[0]_119 ), .Y (n_2974)); + NAND2X1 g39760(.A (\u8_mem[1]_76 ), .B (n_12295), .Y (n_11669)); + NAND2X1 g39180(.A (n_12389), .B (\u4_mem[0]_108 ), .Y (n_2972)); + NAND2X1 g39765(.A (\u7_mem[2] ), .B (n_12641), .Y (n_2971)); + NAND2X1 g39766(.A (n_3252), .B (\u7_mem[0]_121 ), .Y (n_2970)); + NAND2X1 g39770(.A (\u7_mem[2]_35 ), .B (n_12654), .Y (n_2969)); + INVX1 g39772(.A (n_4751), .Y (n_2968)); + NOR2X1 g40158(.A (n_2784), .B (n_2794), .Y (n_2967)); + NAND2X1 g39776(.A (\u7_mem[2]_37 ), .B (n_12654), .Y (n_2966)); + NOR2X1 g39777(.A (n_4996), .B (n_2720), .Y (n_2965)); + NOR2X1 g39778(.A (n_3332), .B (n_2801), .Y (n_2964)); + NOR2X1 g39782(.A (n_5102), .B (n_2765), .Y (n_2962)); + NOR2X1 g39783(.A (n_3089), .B (n_2729), .Y (n_2961)); + NAND2X1 g39785(.A (n_3252), .B (\u7_mem[0]_103 ), .Y (n_2959)); + NOR2X1 g39787(.A (n_5102), .B (n_2767), .Y (n_2958)); + NAND2X1 g39788(.A (n_12825), .B (\u3_mem[0]_112 ), .Y (n_2957)); + NAND2X1 g39792(.A (\u7_mem[2]_43 ), .B (n_12645), .Y (n_2956)); + NAND2X1 g39793(.A (\u6_mem[2]_52 ), .B (n_3423), .Y (n_2955)); + NOR2X1 g39794(.A (n_3089), .B (n_2792), .Y (n_2954)); + NOR2X1 g39796(.A (n_3486), .B (n_2794), .Y (n_2953)); + NAND2X1 g39797(.A (n_3252), .B (\u7_mem[0]_118 ), .Y (n_2952)); + NOR2X1 g39799(.A (n_3486), .B (n_2792), .Y (n_2951)); + NAND2X1 g39179(.A (n_12839), .B (\u4_mem[0]_120 ), .Y (n_2950)); + NAND2X1 g39802(.A (n_12826), .B (\u3_mem[0]_94 ), .Y (n_11729)); + NOR2X1 g39810(.A (n_3089), .B (n_2790), .Y (n_2947)); + NOR2X1 g39811(.A (n_5059), .B (n_2681), .Y (n_2946)); + NAND2X1 g39812(.A (\u7_mem[2]_31 ), .B (n_12645), .Y (n_2945)); + NAND2X1 g39816(.A (n_3259), .B (\u5_mem[0]_103 ), .Y (n_12855)); + NAND2X1 g39817(.A (\u7_mem[1]_64 ), .B (n_3522), .Y (n_2943)); + NAND2X1 g39819(.A (n_12389), .B (\u4_mem[0]_102 ), .Y (n_11656)); + NOR2X1 g39820(.A (n_3486), .B (n_2707), .Y (n_2941)); + NAND2X1 g39822(.A (in_slt_403), .B (n_3415), .Y (n_2940)); + NOR2X1 g39823(.A (n_4996), .B (n_2741), .Y (n_2939)); + NAND2X1 g39824(.A (\u3_mem[1]_86 ), .B (n_3316), .Y (n_2938)); + NOR2X1 g39826(.A (n_3089), .B (n_2801), .Y (n_2937)); + NAND2X1 g39827(.A (n_11798), .B (\u8_mem[0]_117 ), .Y (n_2935)); + NOR2X1 g39832(.A (n_3117), .B (n_2755), .Y (n_2934)); + NAND2X1 g39834(.A (\u8_mem[1]_62 ), .B (n_12301), .Y (n_11503)); + NOR2X1 g39836(.A (n_3117), .B (n_2681), .Y (n_2932)); + NAND2X1 g39837(.A (n_12826), .B (\u3_mem[0]_105 ), .Y (n_12834)); + NOR2X1 g39838(.A (n_3453), .B (n_2755), .Y (n_2930)); + NOR2X1 g39841(.A (n_3117), .B (n_2716), .Y (n_2929)); + NOR2X1 g39842(.A (n_3486), .B (n_2702), .Y (n_2928)); + NAND2X1 g39843(.A (\u3_mem[1]_67 ), .B (n_3316), .Y (n_2927)); + NAND2X1 g39845(.A (n_12839), .B (\u4_mem[0]_118 ), .Y (n_2926)); + NAND2X1 g39846(.A (n_12369), .B (\u6_mem[0]_99 ), .Y (n_2925)); + NAND2X1 g39849(.A (n_12826), .B (\u3_mem[0]_98 ), .Y (n_2924)); + NAND2X1 g39850(.A (\u3_mem[1]_82 ), .B (n_3316), .Y (n_2923)); + NAND2X1 g39851(.A (n_4560), .B (in_slt_444), .Y (n_2922)); + NAND2X1 g39852(.A (n_11789), .B (\u8_mem[0]_92 ), .Y (n_12844)); + INVX1 g39857(.A (n_4753), .Y (n_2918)); + NAND2X1 g39859(.A (n_12721), .B (\u3_mem[0]_92 ), .Y (n_2917)); + NOR2X1 g39861(.A (n_5059), .B (n_2691), .Y (n_2916)); + NAND2X1 g39862(.A (\u8_mem[1]_86 ), .B (n_12291), .Y (n_2915)); + NAND2X1 g39863(.A (n_12721), .B (\u3_mem[0]_103 ), .Y (n_2914)); + NAND2X1 g39864(.A (\u3_mem[2]_49 ), .B (n_3330), .Y (n_2913)); + NOR2X1 g39865(.A (n_3089), .B (n_2829), .Y (n_2912)); + NAND2X1 g39868(.A (\u3_mem[1]_85 ), .B (n_3316), .Y (n_2911)); + NAND2X1 g39869(.A (n_12204), .B (\u6_mem[0]_98 ), .Y (n_11717)); + NOR2X1 g39874(.A (n_3453), .B (n_2702), .Y (n_2909)); + NAND2X1 g39875(.A (\u6_mem[2]_50 ), .B (n_3423), .Y (n_2908)); + NOR2X1 g39881(.A (n_3453), .B (n_2794), .Y (n_2907)); + NAND2X1 g39883(.A (\u4_mem[2]_42 ), .B (n_12091), .Y (n_2906)); + NOR2X1 g39885(.A (n_3089), .B (n_2818), .Y (n_2905)); + NAND2X1 g39886(.A (\u5_mem[1]_69 ), .B (n_3236), .Y (n_12030)); + NAND2X1 g39887(.A (n_12826), .B (\u3_mem[0]_118 ), .Y (n_2903)); + NOR2X1 g39888(.A (n_3089), .B (n_2720), .Y (n_2902)); + NAND2X1 g39889(.A (n_11798), .B (\u8_mem[0] ), .Y (n_11467)); + NAND2X1 g39890(.A (n_12839), .B (\u4_mem[0]_106 ), .Y (n_12827)); + NAND2X1 g39892(.A (\u3_mem[2]_46 ), .B (n_12619), .Y (n_2898)); + NAND2X1 g39893(.A (\u4_mem[2]_52 ), .B (n_12091), .Y (n_2897)); + NAND2X1 g39894(.A (\u3_mem[2]_59 ), .B (n_3330), .Y (n_2896)); + INVX1 g39895(.A (n_4747), .Y (n_2895)); + NAND2X1 g39898(.A (n_12825), .B (\u3_mem[0]_109 ), .Y (n_2894)); + NAND2X1 g39899(.A (\u3_mem[2] ), .B (n_12619), .Y (n_2893)); + NAND2X1 g39902(.A (\u8_mem[1]_70 ), .B (n_12295), .Y (n_11460)); + NAND2X1 g39903(.A (\u8_mem[2]_52 ), .B (n_3441), .Y (n_2891)); + NOR2X1 g39904(.A (n_3453), .B (n_2801), .Y (n_2890)); + NAND2X1 g39905(.A (n_12679), .B (\u5_mem[0]_112 ), .Y (n_2889)); + NAND2X1 g39906(.A (\u5_mem[1]_80 ), .B (n_3239), .Y (n_2888)); + NAND2X1 g39909(.A (n_11798), .B (\u8_mem[0]_103 ), .Y (n_11455)); + INVX1 g39705(.A (n_4761), .Y (n_2886)); + NOR2X1 g39911(.A (n_3089), .B (n_2786), .Y (n_2883)); + NOR2X1 g39913(.A (n_3486), .B (n_2691), .Y (n_2882)); + NAND2X1 g39914(.A (\u8_mem[1]_72 ), .B (n_12295), .Y (n_11456)); + NOR2X1 g39915(.A (n_3089), .B (n_2744), .Y (n_2880)); + NOR2X1 g39916(.A (n_3453), .B (n_2763), .Y (n_2879)); + NAND2X1 g39917(.A (\u3_mem[2]_34 ), .B (n_3207), .Y (n_2878)); + NOR2X1 g39918(.A (n_3486), .B (n_2782), .Y (n_2877)); + NAND2X1 g39919(.A (n_11804), .B (\u8_mem[0]_115 ), .Y (n_2876)); + NAND2X1 g39920(.A (\u8_mem[1]_75 ), .B (n_12301), .Y (n_12037)); + NAND2X1 g39923(.A (\u3_mem[1]_64 ), .B (n_3316), .Y (n_2874)); + NOR2X1 g39924(.A (n_3089), .B (n_2804), .Y (n_2873)); + NAND2X1 g39926(.A (\u3_mem[2]_32 ), .B (n_3207), .Y (n_2872)); + NAND2X1 g39927(.A (\u3_mem[1]_89 ), .B (n_3316), .Y (n_2871)); + NAND2X1 g39928(.A (\u3_mem[2]_48 ), .B (n_3330), .Y (n_2870)); + NAND2X1 g39929(.A (n_12840), .B (\u4_mem[0]_99 ), .Y (n_11662)); + NAND2X1 g39930(.A (n_11798), .B (\u8_mem[0]_109 ), .Y (n_2868)); + NAND2X1 g39931(.A (\u8_mem[1]_84 ), .B (n_12291), .Y (n_2867)); + NAND2X1 g39935(.A (n_3339), .B (in_slt_436), .Y (n_5330)); + NAND2X1 g39936(.A (n_11789), .B (\u8_mem[0]_93 ), .Y (n_12039)); + NOR2X1 g39937(.A (n_3486), .B (n_2864), .Y (n_2865)); + NAND2X1 g39938(.A (\u8_mem[2]_49 ), .B (n_3441), .Y (n_2863)); + NAND2X1 g39940(.A (n_3259), .B (\u5_mem[0]_105 ), .Y (n_12841)); + NAND2X1 g39942(.A (n_11789), .B (\u8_mem[0]_95 ), .Y (n_2861)); + NAND2X1 g39943(.A (n_3259), .B (\u5_mem[0]_107 ), .Y (n_12857)); + NAND2X1 g39944(.A (n_12721), .B (\u3_mem[0]_106 ), .Y (n_2859)); + NOR2X1 g39946(.A (n_3089), .B (n_2716), .Y (n_2858)); + NAND2X1 g39947(.A (\u5_mem[1]_89 ), .B (n_3236), .Y (n_2857)); + NAND2X1 g39949(.A (n_12825), .B (\u3_mem[0]_116 ), .Y (n_2856)); + NAND2X1 g39951(.A (n_12369), .B (\u6_mem[0]_93 ), .Y (n_2855)); + NOR2X1 g39953(.A (n_3117), .B (n_2772), .Y (n_2854)); + NAND2X1 g39954(.A (n_11798), .B (\u8_mem[0]_101 ), .Y (n_11459)); + NAND2X1 g39956(.A (\u8_mem[1]_83 ), .B (n_12291), .Y (n_2852)); + NOR2X1 g39962(.A (n_3089), .B (n_2741), .Y (n_2851)); + NAND2X1 g39963(.A (\u8_mem[1]_77 ), .B (n_12291), .Y (n_2850)); + NAND2X1 g39964(.A (\u4_mem[2]_34 ), .B (n_12079), .Y (n_2849)); + NAND2X1 g39965(.A (\u3_mem[1]_69 ), .B (n_12753), .Y (n_11720)); + NAND2X1 g39967(.A (n_11804), .B (\u8_mem[0]_91 ), .Y (n_11742)); + NAND2X1 g39968(.A (\u8_mem[1]_68 ), .B (n_12301), .Y (n_2846)); + NAND2X1 g39969(.A (\u3_mem[2]_54 ), .B (n_3330), .Y (n_2844)); + NAND2X1 g39972(.A (n_11798), .B (\u8_mem[0]_99 ), .Y (n_11449)); + NAND2X1 g39974(.A (\u8_mem[1]_87 ), .B (n_12291), .Y (n_2841)); + NOR2X1 g39978(.A (n_2836), .B (n_2831), .Y (n_2840)); + NOR2X1 g39980(.A (n_2832), .B (n_2786), .Y (n_2839)); + NOR2X1 g39981(.A (n_2736), .B (n_2829), .Y (n_2838)); + NOR2X1 g39982(.A (n_2836), .B (n_2748), .Y (n_2837)); + NOR2X1 g39983(.A (n_2827), .B (n_2712), .Y (n_2835)); + NAND2X1 g39166(.A (n_11798), .B (\u8_mem[0]_98 ), .Y (n_11447)); + NOR2X1 g39990(.A (n_2832), .B (n_2831), .Y (n_2833)); + NOR2X1 g39993(.A (n_2832), .B (n_2829), .Y (n_2830)); + NOR2X1 g39998(.A (n_2827), .B (n_2864), .Y (n_2828)); + NOR2X1 g39999(.A (n_2736), .B (n_2767), .Y (n_2826)); + NOR2X1 g40000(.A (n_2736), .B (n_2782), .Y (n_2824)); + NOR2X1 g40008(.A (n_2827), .B (n_2763), .Y (n_2823)); + NOR2X1 g40009(.A (n_1016), .B (n_2684), .Y (n_2822)); + NOR2X1 g40010(.A (n_2696), .B (n_2818), .Y (n_2821)); + NOR2X1 g40015(.A (n_2736), .B (n_2831), .Y (n_2820)); + NOR2X1 g40017(.A (n_2832), .B (n_2818), .Y (n_2819)); + NOR2X1 g40018(.A (n_2749), .B (n_2790), .Y (n_2817)); + NOR2X1 g40020(.A (n_2773), .B (n_2829), .Y (n_2816)); + NOR2X1 g40027(.A (n_1016), .B (n_2732), .Y (n_2815)); + NOR2X1 g40029(.A (n_2775), .B (n_2707), .Y (n_2814)); + NOR2X1 g40030(.A (n_2742), .B (n_2735), .Y (n_2813)); + NOR2X1 g40033(.A (n_2836), .B (n_2681), .Y (n_2812)); + NOR2X1 g40035(.A (n_2761), .B (n_2804), .Y (n_2811)); + NOR2X1 g39685(.A (n_3486), .B (n_2712), .Y (n_2810)); + NOR2X1 g40037(.A (n_2736), .B (n_2720), .Y (n_2809)); + NOR2X1 g40040(.A (n_2827), .B (n_2767), .Y (n_2808)); + NOR2X1 g40043(.A (n_1226), .B (n_2772), .Y (n_2807)); + NOR2X1 g40045(.A (n_2759), .B (n_3008), .Y (n_2806)); + NOR2X1 g40048(.A (n_2836), .B (n_2804), .Y (n_2805)); + NOR2X1 g40051(.A (n_2788), .B (n_3008), .Y (n_2803)); + NOR2X1 g40053(.A (n_2770), .B (n_2801), .Y (n_2802)); + NOR2X1 g40056(.A (n_2784), .B (n_2804), .Y (n_2800)); + NOR2X1 g40057(.A (n_2784), .B (n_2818), .Y (n_2799)); + NOR2X1 g40058(.A (n_1147), .B (n_2792), .Y (n_2797)); + NOR2X1 g40061(.A (n_1147), .B (n_2794), .Y (n_2796)); + NOR2X1 g40063(.A (n_2705), .B (n_2792), .Y (n_2793)); + NOR2X1 g40064(.A (n_1226), .B (n_2790), .Y (n_2791)); + NOR2X1 g40069(.A (n_2788), .B (n_2804), .Y (n_2789)); + NOR2X1 g40071(.A (n_1147), .B (n_2786), .Y (n_2787)); + NOR2X1 g40073(.A (n_2784), .B (n_2755), .Y (n_2785)); + NOR2X1 g40075(.A (n_2721), .B (n_2782), .Y (n_2783)); + NOR2X1 g40077(.A (n_2780), .B (n_2772), .Y (n_2781)); + NOR2X1 g40078(.A (n_1082), .B (n_2786), .Y (n_2779)); + NOR2X1 g40081(.A (n_1082), .B (n_2732), .Y (n_2778)); + NOR2X1 g39679(.A (n_5059), .B (n_2686), .Y (n_2777)); + NOR2X1 g40090(.A (n_2775), .B (n_2765), .Y (n_2776)); + NOR2X1 g40092(.A (n_2773), .B (n_2772), .Y (n_2774)); + NOR2X1 g40093(.A (n_2770), .B (n_2831), .Y (n_2771)); + NOR2X1 g40096(.A (n_1016), .B (n_2767), .Y (n_2769)); + NOR2X1 g40099(.A (n_2751), .B (n_2765), .Y (n_2766)); + NOR2X1 g40105(.A (n_2689), .B (n_2763), .Y (n_2764)); + NOR2X1 g40107(.A (n_2761), .B (n_2864), .Y (n_2762)); + NOR2X1 g40112(.A (n_2759), .B (n_2691), .Y (n_2760)); + NOR2X1 g40116(.A (n_2784), .B (n_2765), .Y (n_2758)); + NOR2X1 g40123(.A (n_1016), .B (n_2755), .Y (n_2757)); + NOR2X1 g40137(.A (n_2784), .B (n_2729), .Y (n_2754)); + NOR2X1 g40139(.A (n_1147), .B (n_2744), .Y (n_2753)); + NOR2X1 g40144(.A (n_2751), .B (n_2716), .Y (n_2752)); + NOR2X1 g40145(.A (n_2749), .B (n_2748), .Y (n_2750)); + NOR2X1 g40148(.A (n_2773), .B (n_2741), .Y (n_2747)); + NOR2X1 g40149(.A (n_1082), .B (n_2744), .Y (n_2746)); + NOR2X1 g40151(.A (n_2742), .B (n_2741), .Y (n_2743)); + NOR2X1 g40152(.A (n_2713), .B (n_2767), .Y (n_2740)); + NOR2X1 g39659(.A (n_3117), .B (n_2829), .Y (n_2739)); + NOR2X1 g40176(.A (n_2705), .B (n_2794), .Y (n_2738)); + NOR2X1 g40177(.A (n_2736), .B (n_2735), .Y (n_2737)); + NOR2X1 g40181(.A (n_1226), .B (n_2732), .Y (n_2734)); + NOR2X1 g40182(.A (n_2784), .B (n_2686), .Y (n_2731)); + NOR2X1 g40183(.A (n_2751), .B (n_2729), .Y (n_2730)); + NOR2X1 g40185(.A (n_2788), .B (n_2748), .Y (n_2728)); + NOR2X1 g40188(.A (n_1147), .B (n_2765), .Y (n_2727)); + NOR2X1 g40191(.A (n_1082), .B (n_2735), .Y (n_2726)); + NOR2X1 g40193(.A (n_1082), .B (n_2681), .Y (n_2725)); + NOR2X1 g40196(.A (n_2775), .B (n_2763), .Y (n_2723)); + NOR2X1 g40199(.A (n_2721), .B (n_2720), .Y (n_2722)); + NOR2X1 g40200(.A (n_2759), .B (n_2748), .Y (n_2719)); + NOR2X1 g40201(.A (n_1016), .B (n_2794), .Y (n_2718)); + NOR2X1 g40202(.A (n_2784), .B (n_2716), .Y (n_2717)); + NOR2X1 g40213(.A (n_2751), .B (n_3008), .Y (n_2715)); + NOR2X1 g40214(.A (n_2713), .B (n_2712), .Y (n_2714)); + NOR2X1 g40219(.A (n_1226), .B (n_2702), .Y (n_2711)); + NOR2X1 g40220(.A (n_1147), .B (n_2707), .Y (n_2709)); + NOR2X1 g40226(.A (n_2705), .B (n_2735), .Y (n_2706)); + NOR2X1 g40231(.A (n_2775), .B (n_2702), .Y (n_2704)); + NOR2X1 g40233(.A (n_2713), .B (n_2829), .Y (n_2701)); + NAND2X1 g39139(.A (n_12389), .B (\u4_mem[0]_114 ), .Y (n_2700)); + NOR2X1 g40236(.A (n_2713), .B (n_2755), .Y (n_2699)); + NOR2X1 g40238(.A (n_2775), .B (n_2716), .Y (n_2698)); + NOR2X1 g40243(.A (n_2696), .B (n_3008), .Y (n_2697)); + NOR2X1 g40246(.A (n_2780), .B (n_2729), .Y (n_2695)); + NOR2X1 g40247(.A (n_2705), .B (n_2744), .Y (n_2694)); + NOR2X1 g40255(.A (n_2721), .B (n_2818), .Y (n_2693)); + NOR2X1 g40263(.A (n_2721), .B (n_2691), .Y (n_2692)); + NOR2X1 g40271(.A (n_2689), .B (n_2712), .Y (n_2690)); + NOR2X1 g40272(.A (n_2705), .B (n_2686), .Y (n_2688)); + NOR2X1 g40281(.A (n_1082), .B (n_2684), .Y (n_2685)); + NOR2X1 g40282(.A (n_1147), .B (n_2741), .Y (n_2683)); + NOR2X1 g40283(.A (n_1147), .B (n_2681), .Y (n_2682)); + NOR2X1 g40284(.A (n_2689), .B (n_2755), .Y (n_2680)); + NOR2X1 g40287(.A (n_2742), .B (n_2744), .Y (n_2679)); + NOR2X1 g40291(.A (n_2780), .B (n_2686), .Y (n_2678)); + NOR2X1 g40292(.A (n_2788), .B (n_2681), .Y (n_2677)); + NOR2X1 g40294(.A (n_2736), .B (n_2691), .Y (n_2676)); + NOR2X1 g40300(.A (n_2736), .B (n_2801), .Y (n_2675)); + NOR2X1 g40303(.A (n_1226), .B (n_2786), .Y (n_2674)); + NOR2X1 g40304(.A (n_2705), .B (n_2707), .Y (n_2673)); + NOR2X1 g40311(.A (n_2770), .B (n_2782), .Y (n_2672)); + NOR2X1 g40313(.A (n_1226), .B (n_2801), .Y (n_2671)); + NOR2X1 g40319(.A (n_2705), .B (n_2741), .Y (n_2670)); + NOR2X1 g40320(.A (n_2770), .B (n_2790), .Y (n_2669)); + NOR2X1 g40321(.A (n_2696), .B (n_2702), .Y (n_2668)); + NOR2X1 g40324(.A (n_1082), .B (n_2792), .Y (n_2667)); + NOR2X1 g40325(.A (n_1082), .B (n_2720), .Y (n_2666)); + NOR2X1 g40326(.A (n_2759), .B (n_2702), .Y (n_2665)); + NOR2X1 g40327(.A (n_2689), .B (n_2732), .Y (n_2664)); + NOR2X1 g40329(.A (n_2742), .B (n_2790), .Y (n_2663)); + NOR2X1 g40330(.A (n_2775), .B (n_2782), .Y (n_2662)); + NOR2X1 g40333(.A (n_2773), .B (n_2707), .Y (n_2661)); + NOR2X1 g40334(.A (n_2761), .B (n_2729), .Y (n_2660)); + NOR2X1 g40344(.A (n_2749), .B (n_2686), .Y (n_2659)); + NOR2X1 g40353(.A (n_2775), .B (n_2792), .Y (n_2658)); + NOR2X1 g40355(.A (n_2761), .B (n_2772), .Y (n_2657)); + NOR2X1 g40356(.A (n_1226), .B (n_2763), .Y (n_2656)); + NOR2X1 g40358(.A (n_1016), .B (n_2864), .Y (n_2655)); + NOR2X1 g40359(.A (n_2775), .B (n_2720), .Y (n_2653)); + NOR2X1 g40361(.A (n_2749), .B (n_2716), .Y (n_2652)); + NOR2X1 g40363(.A (n_1016), .B (n_2712), .Y (n_2651)); + NOR2X1 g40366(.A (n_2696), .B (n_2684), .Y (n_2650)); + NOR2X1 g40376(.A (n_2705), .B (n_2684), .Y (n_2649)); + NOR2X1 g40377(.A (n_1016), .B (n_2691), .Y (n_2648)); + NOR2X1 g40378(.A (n_1226), .B (n_2864), .Y (n_2647)); + XOR2X1 g40380(.A (n_614), .B (n_868), .Y (n_2646)); + XOR2X1 g40387(.A (n_886), .B (n_657), .Y (n_2645)); + NAND2X1 g39134(.A (\u4_mem[2]_37 ), .B (n_12079), .Y (n_2644)); + NAND2X1 g39115(.A (n_3339), .B (in_slt_429), .Y (n_5282)); + NAND2X1 g39076(.A (n_11798), .B (\u8_mem[0]_104 ), .Y (n_11457)); + NAND2X1 g39063(.A (n_11798), .B (\u8_mem[0]_96 ), .Y (n_11465)); + NAND2X1 g39041(.A (\u3_mem[2]_53 ), .B (n_3330), .Y (n_2640)); + NAND2X1 g39013(.A (\u8_mem[2]_51 ), .B (n_3441), .Y (n_2638)); + INVX1 g42381(.A (n_9833), .Y (n_10994)); + INVX1 g42387(.A (n_9833), .Y (n_10921)); + NAND2X1 g39877(.A (\u3_mem[2]_52 ), .B (n_3330), .Y (n_2636)); + MX2X1 g38705(.A (\u7_mem[0]_109 ), .B (wb_din_679), .S0 (n_3622), .Y + (n_2635)); + NAND2X1 g38821(.A (\u4_mem[3]_126 ), .B (n_3546), .Y (n_2634)); + AOI22X1 g37926(.A0 (u9_din_tmp_51), .A1 (n_2368), .B0 (in_slt_408), + .B1 (n_4624), .Y (n_2633)); + INVX1 g35720(.A (n_2631), .Y (n_2632)); + INVX1 g36773(.A (o9_status), .Y (n_4068)); + XOR2X1 g36080(.A (\u26_ps_cnt[3] ), .B (n_1104), .Y (n_2630)); + XOR2X1 g36085(.A (\u2_cnt[3] ), .B (n_1829), .Y (n_2629)); + AOI22X1 g37738(.A0 (n_143), .A1 (n_2530), .B0 (n_2627), .B1 (n_2544), + .Y (n_2628)); + INVX2 g37575(.A (n_5629), .Y (n_5630)); + NAND2X1 g36303(.A (n_2624), .B (n_2621), .Y (n_2625)); + OR2X1 g36310(.A (n_2621), .B (n_3942), .Y (n_2622)); + OR2X1 g36343(.A (n_1290), .B (n_4633), .Y (n_2619)); + OR2X1 g36354(.A (n_2617), .B (n_3944), .Y (n_2618)); + NAND2X1 g36568(.A (n_2615), .B (\u2_to_cnt[5] ), .Y (n_2616)); + NAND2X1 g37470(.A (\u13_ints_r[14] ), .B (n_3985), .Y (n_2614)); + NAND2X1 g39908(.A (n_3339), .B (in_slt_426), .Y (n_5292)); + NAND2X1 g37465(.A (\u13_ints_r[25] ), .B (n_4726), .Y (n_2613)); + XOR2X1 g36747(.A (n_786), .B (n_1164), .Y (n_2612)); + XOR2X1 g36748(.A (n_1188), .B (n_1160), .Y (n_2611)); + INVX1 g36767(.A (o6_status), .Y (n_4070)); + NAND2X1 g36777(.A (n_1258), .B (wb_addr_i[6]), .Y (n_2610)); + NAND2X1 g36778(.A (n_1258), .B (n_2608), .Y (n_2609)); + NAND2X1 g38813(.A (\u4_mem[3]_151 ), .B (n_3556), .Y (n_2607)); + NOR2X1 g36929(.A (n_1025), .B (n_2513), .Y (n_2606)); + NAND2X1 g39559(.A (n_12204), .B (\u6_mem[0]_97 ), .Y (n_11715)); + NAND4X1 g37007(.A (\u2_cnt[2] ), .B (n_1138), .C (n_3995), .D + (n_2596), .Y (n_2604)); + NOR2X1 g37052(.A (n_2602), .B (\u2_cnt[6] ), .Y (n_2603)); + NOR2X1 g37139(.A (n_2599), .B (n_1263), .Y (n_2600)); + AOI21X1 g37195(.A0 (n_2592), .A1 (n_2596), .B0 (n_702), .Y (n_2597)); + XOR2X1 g37198(.A (n_798), .B (n_2594), .Y (n_2595)); + NAND4X1 g37372(.A (n_2592), .B (n_1784), .C (n_701), .D (n_1773), .Y + (n_2593)); + XOR2X1 g37413(.A (u2_bit_clk_r1), .B (u2_bit_clk_r), .Y (n_2589)); + NAND2X1 g37445(.A (n_2575), .B (n_838), .Y (n_2588)); + NAND3X1 g37446(.A (n_593), .B (n_7443), .C (n_2574), .Y (n_2587)); + NAND2X1 g37452(.A (\u13_ints_r[24] ), .B (n_4726), .Y (n_2586)); + NAND2X1 g37453(.A (\u13_ints_r[26] ), .B (n_4726), .Y (n_2585)); + NAND2X1 g37454(.A (\u13_ints_r[27] ), .B (n_4726), .Y (n_2584)); + NAND2X1 g37455(.A (\u13_ints_r[28] ), .B (n_4726), .Y (n_2583)); + NAND2X1 g37459(.A (\u13_ints_r[4] ), .B (n_3985), .Y (n_2582)); + NAND2X1 g37461(.A (\u13_ints_r[6] ), .B (n_3985), .Y (n_2580)); + NAND2X1 g37462(.A (\u13_ints_r[7] ), .B (n_3985), .Y (n_2579)); + NAND2X1 g37467(.A (\u13_ints_r[15] ), .B (n_3985), .Y (n_2578)); + NAND2X1 g37474(.A (n_4726), .B (n_5225), .Y (n_2577)); + NAND2X1 g37482(.A (n_2575), .B (n_2574), .Y (n_2576)); + NAND2X1 g37578(.A (n_1520), .B (n_2571), .Y (n_2572)); + NOR2X1 g37597(.A (n_1209), .B (n_2368), .Y (n_2570)); + NOR2X1 g37599(.A (n_1224), .B (n_2513), .Y (n_2569)); + AOI22X1 g37600(.A0 (n_639), .A1 (n_2468), .B0 (n_2567), .B1 + (\u8_rp[3] ), .Y (n_2568)); + AOI22X1 g37602(.A0 (n_709), .A1 (n_2465), .B0 (n_6821), .B1 + (\u6_rp[3] ), .Y (n_2566)); + AOI22X1 g37603(.A0 (n_664), .A1 (n_2463), .B0 (n_6316), .B1 + (\u3_rp[3] ), .Y (n_2565)); + NAND2X1 g39438(.A (\u3_mem[1]_70 ), .B (n_12753), .Y (n_11722)); + AOI22X1 g37682(.A0 (n_6662), .A1 (n_2553), .B0 (n_6588), .B1 + (n_1316), .Y (n_2563)); + AOI22X1 g37713(.A0 (u9_din_tmp_52), .A1 (n_2368), .B0 (in_slt_409), + .B1 (n_4624), .Y (n_2561)); + NAND2X2 g39428(.A (n_3259), .B (\u5_mem[0]_95 ), .Y (n_2560)); + AOI22X1 g37716(.A0 (n_2558), .A1 (n_2557), .B0 (n_2556), .B1 + (n_2534), .Y (n_2559)); + AOI22X1 g37725(.A0 (n_6668), .A1 (n_2553), .B0 (n_6598), .B1 + (n_1316), .Y (n_2555)); + AOI22X1 g37727(.A0 (n_6666), .A1 (n_2553), .B0 (n_6595), .B1 + (n_1316), .Y (n_2554)); + AOI22X1 g37729(.A0 (n_3911), .A1 (in_slt_429), .B0 (n_2344), .B1 + (in_slt_427), .Y (n_2552)); + AOI22X1 g37731(.A0 (n_2558), .A1 (n_2550), .B0 (n_2549), .B1 + (n_2534), .Y (n_2551)); + AOI22X1 g37732(.A0 (n_147), .A1 (n_940), .B0 (n_5512), .B1 (n_1316), + .Y (n_2548)); + NAND2X1 g39423(.A (n_4560), .B (in_slt_458), .Y (n_5296)); + AOI22X1 g37747(.A0 (n_215), .A1 (n_2530), .B0 (n_2545), .B1 (n_2544), + .Y (n_2547)); + AOI22X1 g37755(.A0 (n_196), .A1 (n_2530), .B0 (n_2542), .B1 (n_2534), + .Y (n_2543)); + AOI22X1 g37756(.A0 (n_2558), .A1 (n_2539), .B0 (n_2538), .B1 (n_940), + .Y (n_2540)); + AOI22X1 g37760(.A0 (n_42), .A1 (n_2553), .B0 (n_5510), .B1 (n_1316), + .Y (n_2537)); + AOI22X1 g37762(.A0 (n_6526), .A1 (n_2530), .B0 (n_6652), .B1 + (n_2534), .Y (n_2536)); + AOI22X1 g37767(.A0 (n_2558), .A1 (n_6386), .B0 (n_6610), .B1 + (n_2534), .Y (n_2535)); + AOI22X1 g37775(.A0 (u10_din_tmp_49), .A1 (n_2302), .B0 (n_3911), .B1 + (in_slt_428), .Y (n_2533)); + AOI22X1 g37777(.A0 (n_6415), .A1 (n_2530), .B0 (n_6633), .B1 + (n_2544), .Y (n_2532)); + AOI22X1 g37787(.A0 (n_6542), .A1 (n_2530), .B0 (n_6630), .B1 + (n_2534), .Y (n_2531)); + AOI22X1 g37804(.A0 (n_6408), .A1 (n_2530), .B0 (n_6612), .B1 + (n_2544), .Y (n_2529)); + AOI22X1 g37812(.A0 (n_6406), .A1 (n_2530), .B0 (n_6607), .B1 + (n_2544), .Y (n_2528)); + AOI22X1 g37815(.A0 (n_2558), .A1 (n_6380), .B0 (n_6664), .B1 + (n_2534), .Y (n_2527)); + AOI22X1 g37819(.A0 (n_2558), .A1 (n_5945), .B0 (n_6021), .B1 + (n_2534), .Y (n_2526)); + AOI22X1 g37825(.A0 (n_2558), .A1 (n_5962), .B0 (n_6037), .B1 (n_940), + .Y (n_2525)); + AOI22X1 g37829(.A0 (n_6018), .A1 (n_2553), .B0 (n_6000), .B1 + (n_1316), .Y (n_2523)); + AOI22X1 g37834(.A0 (n_2344), .A1 (in_slt_436), .B0 (n_2302), .B1 + (in_slt_424), .Y (n_5418)); + AOI22X1 g37843(.A0 (u10_din_tmp1), .A1 (n_2302), .B0 (n_3911), .B1 + (in_slt_420), .Y (n_2521)); + AOI22X1 g37891(.A0 (n_3911), .A1 (in_slt_436), .B0 (n_2344), .B1 + (in_slt_434), .Y (n_2520)); + AOI22X1 g37894(.A0 (n_3911), .A1 (in_slt_437), .B0 (n_2344), .B1 + (in_slt_435), .Y (n_2519)); + AOI22X1 g37895(.A0 (n_4097), .A1 (in_slt_458), .B0 (n_2325), .B1 + (in_slt_456), .Y (n_2517)); + AOI22X1 g37897(.A0 (n_4097), .A1 (in_slt_459), .B0 (n_2325), .B1 + (in_slt_457), .Y (n_2516)); + AOI22X1 g37898(.A0 (n_2325), .A1 (in_slt_458), .B0 (n_2513), .B1 + (in_slt_446), .Y (n_5413)); + AOI22X1 g37899(.A0 (n_2325), .A1 (in_slt_459), .B0 (n_2513), .B1 + (in_slt_447), .Y (n_5410)); + AOI22X1 g37900(.A0 (n_2344), .A1 (in_slt_437), .B0 (n_2302), .B1 + (in_slt_425), .Y (n_5422)); + AOI22X1 g37902(.A0 (u10_din_tmp_42), .A1 (n_2302), .B0 (n_3911), .B1 + (in_slt_421), .Y (n_2511)); + AOI22X1 g37905(.A0 (n_6476), .A1 (n_940), .B0 (n_6601), .B1 (n_1316), + .Y (n_2510)); + NAND2X1 g39891(.A (\u8_mem[2]_34 ), .B (n_2362), .Y (n_2509)); + AOI22X1 g37934(.A0 (n_2502), .A1 (n_2507), .B0 (n_2506), .B1 + (n_1859), .Y (n_2508)); + AOI22X1 g37939(.A0 (n_343), .A1 (n_1835), .B0 (n_5350), .B1 (n_1760), + .Y (n_2505)); + AOI22X1 g37946(.A0 (n_2558), .A1 (n_5957), .B0 (n_5974), .B1 + (n_1839), .Y (n_2504)); + AOI22X1 g37965(.A0 (n_2502), .A1 (n_6394), .B0 (n_6537), .B1 + (n_1859), .Y (n_2503)); + AOI22X1 g37973(.A0 (n_2502), .A1 (n_2500), .B0 (n_2499), .B1 + (n_1835), .Y (n_2501)); + AOI22X1 g37988(.A0 (n_2502), .A1 (n_6845), .B0 (n_6937), .B1 + (n_1859), .Y (n_2498)); + NAND2X1 g39356(.A (\u5_mem[2]_52 ), .B (n_12823), .Y (n_2496)); + NAND2X1 g39354(.A (\u5_mem[2]_39 ), .B (n_12823), .Y (n_12033)); + NAND2X1 g39941(.A (n_2491), .B (\u7_mem[0]_99 ), .Y (n_2493)); + NAND2X1 g39343(.A (\u5_mem[2]_36 ), .B (n_12823), .Y (n_12035)); + NAND2X1 g39789(.A (n_2330), .B (\u7_mem[0]_104 ), .Y (n_2489)); + INVX1 g40886(.A (n_3330), .Y (n_2488)); + XOR2X1 g38218(.A (n_1446), .B (n_507), .Y (n_2487)); + XOR2X1 g38231(.A (\u10_wp[3] ), .B (n_1067), .Y (n_2486)); + NOR2X1 g40146(.A (n_2477), .B (n_2831), .Y (n_2484)); + NOR2X1 g40269(.A (n_2470), .B (n_2804), .Y (n_2483)); + DFFSRX1 \u15_crac_din_reg[6] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1196), .Q (crac_din_697), .QN ()); + NAND2X1 g39878(.A (\u6_mem[2]_34 ), .B (n_2285), .Y (n_2482)); + NOR2X1 g40264(.A (n_2470), .B (n_2765), .Y (n_2481)); + NAND2X1 g39876(.A (n_2491), .B (\u7_mem[0]_119 ), .Y (n_2479)); + NAND2X1 g39871(.A (n_1205), .B (\u5_rp[3] ), .Y (n_4644)); + NOR2X1 g40248(.A (n_2477), .B (n_2864), .Y (n_2478)); + NOR2X1 g40253(.A (n_867), .B (n_2772), .Y (n_2476)); + NOR2X1 g39276(.A (\u10_mem[1]_139 ), .B (n_2364), .Y (n_2475)); + NAND2X1 g39856(.A (\u8_mem[2]_30 ), .B (n_2366), .Y (n_11501)); + NAND2X1 g39835(.A (n_2491), .B (\u7_mem[0]_95 ), .Y (n_2473)); + NAND2X1 g39259(.A (n_2325), .B (in_slt_442), .Y (n_2472)); + NOR2X1 g40232(.A (n_2470), .B (n_2864), .Y (n_2471)); + NAND2X1 g38789(.A (\u8_mem[3]_151 ), .B (n_2468), .Y (n_2469)); + NAND2X1 g38790(.A (\u3_mem[3]_134 ), .B (n_2463), .Y (n_2467)); + NAND2X1 g38791(.A (\u6_mem[3]_144 ), .B (n_2465), .Y (n_2466)); + NAND2X1 g38792(.A (\u3_mem[3]_151 ), .B (n_2463), .Y (n_2464)); + NAND2X1 g38793(.A (\u6_mem[3]_151 ), .B (n_2465), .Y (n_2462)); + NAND2X1 g38794(.A (\u3_mem[3]_146 ), .B (n_2463), .Y (n_2461)); + NAND2X1 g38795(.A (\u8_mem[3]_144 ), .B (n_2468), .Y (n_2460)); + NAND2X1 g38797(.A (\u3_mem[3]_145 ), .B (n_2463), .Y (n_2459)); + NAND2X1 g38800(.A (\u6_mem[3]_149 ), .B (n_2465), .Y (n_2458)); + NAND2X1 g38804(.A (\u8_mem[3]_131 ), .B (n_2468), .Y (n_2457)); + NAND2X1 g38805(.A (\u3_mem[3]_152 ), .B (n_2463), .Y (n_2456)); + NAND2X1 g38807(.A (\u8_mem[3]_129 ), .B (n_2468), .Y (n_2455)); + NAND2X1 g38826(.A (\u8_mem[3]_124 ), .B (n_2468), .Y (n_2453)); + NAND2X1 g38827(.A (\u6_mem[3]_133 ), .B (n_12622), .Y (n_2452)); + NAND2X1 g38828(.A (\u3_mem[3]_130 ), .B (n_2463), .Y (n_2450)); + NAND2X1 g38829(.A (\u6_mem[3]_145 ), .B (n_2465), .Y (n_2448)); + NAND2X1 g38831(.A (\u6_mem[3]_132 ), .B (n_2419), .Y (n_2447)); + NAND2X1 g38832(.A (\u3_mem[3]_144 ), .B (n_2463), .Y (n_2446)); + NAND2X1 g38839(.A (\u8_mem[3]_143 ), .B (n_2468), .Y (n_2445)); + NAND2X1 g38844(.A (\u5_mem[3]_144 ), .B (n_3543), .Y (n_2444)); + NAND2X1 g38849(.A (\u5_mem[3]_147 ), .B (n_3543), .Y (n_2443)); + NAND2X1 g38851(.A (\u3_mem[3]_142 ), .B (n_2463), .Y (n_2441)); + NAND2X1 g38852(.A (\u6_mem[3]_147 ), .B (n_2465), .Y (n_2440)); + NAND2X1 g38859(.A (\u5_mem[3]_140 ), .B (n_3543), .Y (n_2439)); + NAND2X1 g38862(.A (\u5_mem[3]_124 ), .B (n_3543), .Y (n_2438)); + NAND2X1 g38864(.A (\u3_mem[3]_148 ), .B (n_2463), .Y (n_2437)); + NAND2X1 g38871(.A (\u8_mem[3]_122 ), .B (n_2468), .Y (n_2435)); + NAND2X1 g38878(.A (\u8_mem[3]_140 ), .B (n_2468), .Y (n_2433)); + NAND2X1 g38879(.A (\u3_mem[3]_143 ), .B (n_2463), .Y (n_2432)); + NAND2X1 g38882(.A (\u6_mem[3] ), .B (n_2419), .Y (n_2431)); + NAND2X1 g38885(.A (\u6_mem[3]_143 ), .B (n_2465), .Y (n_2429)); + NAND2X1 g38886(.A (\u6_mem[3]_129 ), .B (n_2419), .Y (n_2428)); + NAND2X1 g38888(.A (\u6_mem[3]_128 ), .B (n_2419), .Y (n_2426)); + NAND2X1 g38889(.A (\u6_mem[3]_146 ), .B (n_2465), .Y (n_2425)); + NAND2X1 g38890(.A (\u6_mem[3]_134 ), .B (n_2419), .Y (n_2424)); + NAND2X1 g38891(.A (\u6_mem[3]_136 ), .B (n_2419), .Y (n_2423)); + NAND2X1 g38893(.A (\u6_mem[3]_150 ), .B (n_2465), .Y (n_2421)); + NAND2X1 g38894(.A (\u6_mem[3]_138 ), .B (n_2419), .Y (n_2420)); + NAND2X1 g38895(.A (\u6_mem[3]_152 ), .B (n_2465), .Y (n_2418)); + NAND2X1 g38897(.A (\u6_mem[3]_140 ), .B (n_2419), .Y (n_2417)); + NAND2X1 g38898(.A (\u6_mem[3]_122 ), .B (n_12622), .Y (n_2416)); + NAND2X1 g38899(.A (\u6_mem[3]_123 ), .B (n_12622), .Y (n_2414)); + NAND2X1 g38900(.A (\u6_mem[3]_125 ), .B (n_2419), .Y (n_2413)); + OR2X1 g38901(.A (n_393), .B (n_2513), .Y (n_2412)); + NAND2X1 g38902(.A (\u6_mem[3]_141 ), .B (n_2465), .Y (n_2411)); + NAND2X1 g38903(.A (\u8_mem[3]_149 ), .B (n_2468), .Y (n_2410)); + NAND2X1 g38904(.A (\u3_mem[3]_141 ), .B (n_2463), .Y (n_2409)); + NAND2X1 g38905(.A (\u5_mem[3]_122 ), .B (n_3543), .Y (n_2408)); + NAND2X1 g38906(.A (\u6_mem[3]_139 ), .B (n_2419), .Y (n_2407)); + NAND2X1 g38910(.A (\u5_mem[3]_137 ), .B (n_3543), .Y (n_2406)); + NAND2X1 g38911(.A (\u3_mem[3]_139 ), .B (n_2463), .Y (n_2405)); + NAND2X1 g38916(.A (\u5_mem[3]_143 ), .B (n_3543), .Y (n_2404)); + NAND2X1 g38917(.A (\u6_mem[3]_142 ), .B (n_2465), .Y (n_2403)); + NAND2X1 g38919(.A (\u3_mem[3]_129 ), .B (n_2463), .Y (n_2402)); + NAND2X1 g38921(.A (\u5_mem[3]_146 ), .B (n_3543), .Y (n_2401)); + NAND2X1 g38935(.A (\u8_mem[3]_150 ), .B (n_2468), .Y (n_2400)); + NAND2X1 g38944(.A (\u8_mem[3]_137 ), .B (n_2468), .Y (n_2399)); + NAND2X1 g38946(.A (n_2377), .B (\u2_cnt[3] ), .Y (n_3964)); + NAND2X1 g38948(.A (\u6_mem[3]_126 ), .B (n_12622), .Y (n_2398)); + NAND2X1 g38959(.A (\u3_mem[3]_132 ), .B (n_2463), .Y (n_2397)); + NAND2X1 g38960(.A (\u3_mem[3]_147 ), .B (n_2463), .Y (n_2396)); + NAND2X1 g38963(.A (\u8_mem[3] ), .B (n_2468), .Y (n_2395)); + NAND2X1 g38965(.A (\u8_mem[3]_128 ), .B (n_2468), .Y (n_2393)); + NAND2X1 g38966(.A (\u3_mem[3]_140 ), .B (n_2463), .Y (n_2392)); + NAND2X1 g38969(.A (\u8_mem[3]_133 ), .B (n_2468), .Y (n_2391)); + NAND2X1 g38971(.A (\u8_mem[3]_134 ), .B (n_2468), .Y (n_2390)); + NAND2X1 g38972(.A (\u8_mem[3]_148 ), .B (n_2468), .Y (n_2389)); + NAND2X1 g38973(.A (\u6_mem[3]_148 ), .B (n_2465), .Y (n_2388)); + NAND2X1 g38974(.A (\u8_mem[3]_136 ), .B (n_2468), .Y (n_2387)); + NAND2X1 g38975(.A (\u8_mem[3]_138 ), .B (n_2468), .Y (n_2386)); + NAND2X1 g38977(.A (\u8_mem[3]_152 ), .B (n_2468), .Y (n_2385)); + NAND2X1 g38979(.A (\u8_mem[3]_123 ), .B (n_2468), .Y (n_2384)); + NAND2X1 g38980(.A (\u8_mem[3]_146 ), .B (n_2468), .Y (n_2383)); + NAND2X1 g38981(.A (\u8_mem[3]_125 ), .B (n_2468), .Y (n_2382)); + NAND2X1 g38982(.A (\u8_mem[3]_126 ), .B (n_2468), .Y (n_2381)); + NAND2X1 g38983(.A (\u8_mem[3]_141 ), .B (n_2468), .Y (n_2380)); + NAND2X1 g38988(.A (\u3_mem[3]_149 ), .B (n_2463), .Y (n_2379)); + NOR2X1 g38990(.A (n_1773), .B (n_2377), .Y (n_2378)); + NAND2X1 g38991(.A (\u6_mem[3]_124 ), .B (n_12622), .Y (n_2376)); + NAND2X1 g38993(.A (\u8_mem[3]_145 ), .B (n_2468), .Y (n_2375)); + NAND2X1 g38995(.A (\u8_mem[3]_142 ), .B (n_2468), .Y (n_2374)); + NAND2X1 g38996(.A (\u8_mem[3]_132 ), .B (n_2468), .Y (n_2373)); + NOR2X1 g40157(.A (n_2099), .B (n_2765), .Y (n_2372)); + OR2X1 g38998(.A (n_605), .B (n_2368), .Y (n_2371)); + NAND2X1 g38999(.A (\u8_mem[3]_130 ), .B (n_2468), .Y (n_2370)); + NAND2X1 g39016(.A (n_2468), .B (n_494), .Y (n_2369)); + NAND2X1 g39037(.A (in_slt_404), .B (n_2368), .Y (n_4778)); + NAND2X1 g39042(.A (\u8_mem[2]_55 ), .B (n_2366), .Y (n_2367)); + NOR2X1 g39227(.A (\u10_mem[1]_135 ), .B (n_2364), .Y (n_2365)); + NAND2X1 g39066(.A (\u8_mem[2]_35 ), .B (n_2362), .Y (n_2363)); + NAND2X1 g39084(.A (\u5_mem[2]_42 ), .B (n_12823), .Y (n_12806)); + NAND2X1 g39091(.A (n_2465), .B (n_496), .Y (n_2360)); + NAND2X1 g39093(.A (n_2344), .B (in_slt_419), .Y (n_2359)); + NAND2X1 g39107(.A (n_2344), .B (in_slt_429), .Y (n_2357)); + NAND2X1 g39121(.A (\u4_mem[2]_36 ), .B (n_12079), .Y (n_2355)); + NAND2X1 g39127(.A (in_slt_400), .B (n_2368), .Y (n_2354)); + NAND2X1 g39130(.A (\u8_mem[2]_38 ), .B (n_2362), .Y (n_2353)); + NAND2X1 g39131(.A (\u8_mem[2]_46 ), .B (n_2366), .Y (n_2352)); + NOR2X1 g40206(.A (n_2748), .B (n_2067), .Y (n_2351)); + NAND2X1 g39172(.A (\u4_mem[2]_45 ), .B (n_12079), .Y (n_2350)); + NAND2X1 g39189(.A (\u4_mem[2]_47 ), .B (n_12079), .Y (n_2348)); + NAND2X1 g39215(.A (in_slt_414), .B (n_2368), .Y (n_4764)); + NOR2X1 g39201(.A (\u10_mem[1]_133 ), .B (n_2364), .Y (n_2346)); + NAND2X1 g39224(.A (n_2344), .B (in_slt_433), .Y (n_2345)); + NAND2X1 g39234(.A (\u5_mem[2]_33 ), .B (n_12823), .Y (n_12810)); + NOR2X1 g39244(.A (\u10_mem[1]_136 ), .B (n_2364), .Y (n_2341)); + NAND2X1 g39246(.A (\u5_mem[2]_30 ), .B (n_12823), .Y (n_11443)); + NAND2X1 g39250(.A (\u8_mem[2]_36 ), .B (n_2362), .Y (n_2338)); + NAND2X1 g39253(.A (\u5_mem[2]_37 ), .B (n_12823), .Y (n_2337)); + NOR2X1 g39264(.A (\u10_mem[1]_119 ), .B (n_2364), .Y (n_2336)); + NOR2X1 g39271(.A (\u10_mem[1]_138 ), .B (n_2364), .Y (n_2335)); + NAND2X1 g39274(.A (n_2344), .B (in_slt_424), .Y (n_2334)); + NAND2X1 g39275(.A (n_2491), .B (\u7_mem[0]_107 ), .Y (n_2333)); + NOR2X1 g39283(.A (\u10_mem[1]_140 ), .B (n_2364), .Y (n_2332)); + NAND2X1 g39791(.A (n_2330), .B (\u7_mem[0]_105 ), .Y (n_2331)); + NAND2X1 g39286(.A (n_2325), .B (in_slt_443), .Y (n_2329)); + NOR2X1 g39293(.A (\u10_mem[1]_141 ), .B (n_2364), .Y (n_2327)); + NAND2X1 g39303(.A (n_2325), .B (in_slt_441), .Y (n_2326)); + NAND2X1 g39332(.A (\u5_mem[2] ), .B (n_12823), .Y (n_11494)); + NAND2X1 g39345(.A (\u5_mem[2]_38 ), .B (n_12823), .Y (n_12031)); + NAND2X1 g39346(.A (\u5_mem[2]_35 ), .B (n_12823), .Y (n_2322)); + NAND2X1 g39349(.A (n_2330), .B (\u7_mem[0]_91 ), .Y (n_2321)); + NAND2X1 g39350(.A (\u5_mem[2]_51 ), .B (n_12823), .Y (n_2320)); + NOR2X1 g40190(.A (n_2154), .B (n_2818), .Y (n_2319)); + NAND2X1 g39361(.A (\u5_mem[2]_40 ), .B (n_12823), .Y (n_12854)); + NAND2X1 g39363(.A (\u5_mem[2]_53 ), .B (n_12823), .Y (n_2317)); + NAND2X1 g39370(.A (\u5_mem[2]_54 ), .B (n_12823), .Y (n_2316)); + NAND2X1 g39383(.A (\u5_mem[2]_43 ), .B (n_12823), .Y (n_12041)); + NAND2X1 g39386(.A (\u4_mem[2]_30 ), .B (n_12079), .Y (n_2314)); + NAND2X1 g39392(.A (\u5_mem[2]_57 ), .B (n_12823), .Y (n_2312)); + NAND2X1 g39395(.A (\u5_mem[2]_45 ), .B (n_12823), .Y (n_12858)); + NAND2X1 g39409(.A (\u5_mem[2]_29 ), .B (n_12823), .Y (n_11441)); + NAND2X1 g39416(.A (\u5_mem[2]_31 ), .B (n_12823), .Y (n_11439)); + NAND2X1 g39773(.A (n_2302), .B (in_slt_434), .Y (n_4751)); + NOR2X1 g39418(.A (\u10_mem[1]_137 ), .B (n_2364), .Y (n_2307)); + NAND2X1 g39419(.A (\u5_mem[2]_32 ), .B (n_12823), .Y (n_12799)); + NAND2X1 g39426(.A (n_2344), .B (in_slt_423), .Y (n_2305)); + NAND2X1 g39196(.A (\u4_mem[2]_31 ), .B (n_12079), .Y (n_2304)); + NAND2X1 g39431(.A (u10_din_tmp_50), .B (n_2302), .Y (n_2303)); + NAND2X1 g39432(.A (n_1068), .B (\u7_rp[3] ), .Y (n_4080)); + NAND2X1 g39771(.A (\u8_mem[2]_53 ), .B (n_2366), .Y (n_2301)); + OR2X1 g39198(.A (n_7120), .B (n_2567), .Y (n_2300)); + NAND2X1 g39440(.A (\u8_mem[2]_39 ), .B (n_2362), .Y (n_2299)); + OR2X1 g39441(.A (n_12604), .B (n_3559), .Y (n_2298)); + NAND2X1 g39463(.A (\u5_mem[2]_49 ), .B (n_12823), .Y (n_2297)); + NAND2X1 g39764(.A (n_2325), .B (in_slt_445), .Y (n_2296)); + NAND2X1 g39488(.A (\u8_mem[2]_33 ), .B (n_2362), .Y (n_2295)); + NAND2X1 g39498(.A (n_2330), .B (\u7_mem[0]_102 ), .Y (n_2294)); + NAND2X1 g39504(.A (in_slt_411), .B (n_2368), .Y (n_4743)); + NOR2X1 g40178(.A (n_2681), .B (n_1985), .Y (n_2292)); + NAND2X1 g39528(.A (n_2330), .B (\u7_mem[0]_101 ), .Y (n_2291)); + NAND2X1 g39533(.A (n_2344), .B (in_slt_420), .Y (n_2290)); + NAND2X1 g39541(.A (n_2491), .B (\u7_mem[0]_93 ), .Y (n_2289)); + NAND2X1 g39553(.A (n_2325), .B (in_slt_454), .Y (n_2288)); + NAND2X1 g39554(.A (\u8_mem[2]_47 ), .B (n_2366), .Y (n_2287)); + NAND2X1 g39556(.A (\u6_mem[2]_36 ), .B (n_2285), .Y (n_2286)); + NAND2X1 g39565(.A (in_slt_409), .B (n_2368), .Y (n_4755)); + INVX4 g39571(.A (n_2284), .Y (n_5591)); + NAND2X1 g39734(.A (in_slt_415), .B (n_2368), .Y (n_4767)); + NAND2X1 g39575(.A (\u6_mem[2]_39 ), .B (n_2285), .Y (n_2282)); + NAND2X1 g39576(.A (n_2330), .B (\u7_mem[0]_100 ), .Y (n_2281)); + NAND2X1 g39584(.A (n_2344), .B (in_slt_428), .Y (n_2280)); + NAND2X1 g39585(.A (n_2325), .B (in_slt_451), .Y (n_2279)); + NAND2X1 g39592(.A (\u6_mem[2]_41 ), .B (n_2285), .Y (n_2278)); + NAND2X1 g39599(.A (\u4_mem[2]_29 ), .B (n_12087), .Y (n_2277)); + NAND2X1 g39608(.A (n_2302), .B (in_slt_433), .Y (n_4759)); + NAND2X1 g39610(.A (in_slt_406), .B (n_2368), .Y (n_4776)); + NAND2X1 g39614(.A (\u6_mem[2]_32 ), .B (n_2285), .Y (n_2276)); + NAND2X1 g39623(.A (\u5_mem[2]_44 ), .B (n_12823), .Y (n_11967)); + NAND2X1 g39625(.A (\u6_mem[2]_46 ), .B (n_2285), .Y (n_2274)); + DFFSRX1 \u15_crac_din_reg[9] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1028), .Q (crac_din_700), .QN ()); + NAND2X1 g39634(.A (n_2325), .B (in_slt6), .Y (n_2273)); + NAND2X1 g39636(.A (\u6_mem[2]_33 ), .B (n_2285), .Y (n_2272)); + OR2X1 g39651(.A (n_7256), .B (n_6821), .Y (n_2271)); + NAND2X1 g39657(.A (n_2344), .B (in_slt_432), .Y (n_2270)); + NAND2X1 g39660(.A (n_2325), .B (in_slt_450), .Y (n_2269)); + NAND2X1 g39663(.A (n_2302), .B (in_slt_422), .Y (n_2268)); + NAND2X1 g39681(.A (\u6_mem[2]_43 ), .B (n_2285), .Y (n_2264)); + NOR2X1 g40166(.A (n_2085), .B (n_3008), .Y (n_2263)); + NAND2X1 g39683(.A (n_2302), .B (in_slt_423), .Y (n_2261)); + NAND2X1 g39181(.A (\u4_mem[2]_46 ), .B (n_12079), .Y (n_2260)); + INVX1 g42735(.A (n_991), .Y (n_10945)); + NAND2X1 g39706(.A (n_2302), .B (in_slt_432), .Y (n_4761)); + NAND2X1 g39708(.A (in_slt_401), .B (n_2368), .Y (n_2259)); + NAND2X1 g39714(.A (\u5_mem[2]_56 ), .B (n_12823), .Y (n_2258)); + NOR2X1 g39726(.A (\u10_mem[1]_132 ), .B (n_2364), .Y (n_2257)); + NAND2X1 g39727(.A (\u6_mem[2]_30 ), .B (n_2285), .Y (n_11515)); + NAND2X1 g39729(.A (n_2302), .B (in_slt_427), .Y (n_4745)); + NAND2X1 g39736(.A (u9_din_tmp_50), .B (n_2368), .Y (n_2255)); + NAND2X1 g39737(.A (\u5_mem[2]_34 ), .B (n_12823), .Y (n_12808)); + NAND2X1 g39755(.A (\u8_mem[2]_45 ), .B (n_2362), .Y (n_2253)); + NAND2X1 g39758(.A (n_2325), .B (in_slt_446), .Y (n_2252)); + NAND2X1 g39759(.A (n_2325), .B (in_slt_444), .Y (n_2251)); + NAND2X1 g39724(.A (\u5_mem[2]_50 ), .B (n_12823), .Y (n_2250)); + NAND2X1 g39775(.A (n_2325), .B (in_slt_447), .Y (n_2249)); + NAND2X1 g39780(.A (n_2325), .B (in_slt_448), .Y (n_2248)); + NAND2X1 g39786(.A (n_2491), .B (\u7_mem[0]_108 ), .Y (n_2247)); + NAND2X1 g39795(.A (\u4_mem[2]_44 ), .B (n_12087), .Y (n_2246)); + NAND2X1 g39804(.A (\u8_mem[2] ), .B (n_2362), .Y (n_2245)); + NAND2X1 g39814(.A (\u8_mem[2]_50 ), .B (n_2366), .Y (n_2244)); + NAND2X1 g39828(.A (\u5_mem[2]_47 ), .B (n_12823), .Y (n_2243)); + NAND2X1 g39831(.A (\u5_mem[2]_41 ), .B (n_12823), .Y (n_12856)); + NAND2X1 g39839(.A (n_2344), .B (in_slt_430), .Y (n_2241)); + NAND2X1 g39844(.A (n_2344), .B (in_slt_422), .Y (n_2240)); + NAND2X1 g39847(.A (n_2344), .B (in_slt_426), .Y (n_2239)); + NAND2X1 g39848(.A (n_2325), .B (in_slt_455), .Y (n_2238)); + NAND2X1 g39854(.A (\u8_mem[2]_43 ), .B (n_2362), .Y (n_2237)); + NAND2X1 g39858(.A (in_slt_408), .B (n_2368), .Y (n_4753)); + NAND2X1 g39870(.A (n_2344), .B (in_slt4), .Y (n_2236)); + NAND2X1 g39896(.A (in_slt_405), .B (n_2368), .Y (n_4747)); + NAND2X1 g39925(.A (\u5_mem[2]_55 ), .B (n_12823), .Y (n_2235)); + NOR2X1 g40126(.A (n_2189), .B (n_2720), .Y (n_2234)); + NAND2X1 g39933(.A (\u4_mem[2]_35 ), .B (n_12087), .Y (n_2233)); + OR2X1 g39939(.A (n_7214), .B (n_6316), .Y (n_2232)); + NAND2X1 g39948(.A (\u5_mem[2]_58 ), .B (n_12823), .Y (n_2231)); + NAND2X1 g39950(.A (\u8_mem[2]_40 ), .B (n_2366), .Y (n_11454)); + NAND2X1 g39952(.A (\u6_mem[2] ), .B (n_2285), .Y (n_2229)); + NAND2X1 g39961(.A (n_2325), .B (in_slt_453), .Y (n_2227)); + NOR2X1 g40142(.A (n_867), .B (n_2720), .Y (n_2226)); + NOR2X1 g39976(.A (n_867), .B (n_2748), .Y (n_2225)); + NOR2X1 g39977(.A (n_945), .B (n_2732), .Y (n_2224)); + NOR2X1 g39979(.A (n_2218), .B (n_2767), .Y (n_2223)); + NOR2X1 g39984(.A (n_2216), .B (n_2864), .Y (n_2222)); + NOR2X1 g39985(.A (n_867), .B (n_2829), .Y (n_2221)); + NOR2X1 g39986(.A (n_2218), .B (n_2790), .Y (n_2219)); + NOR2X1 g39988(.A (n_2216), .B (n_3008), .Y (n_2217)); + NOR2X1 g39989(.A (n_2786), .B (n_2067), .Y (n_2215)); + NOR2X1 g39991(.A (n_2763), .B (n_2067), .Y (n_2214)); + NOR2X1 g39992(.A (n_2218), .B (n_2744), .Y (n_2212)); + NOR2X1 g39994(.A (n_2135), .B (n_2732), .Y (n_2211)); + NOR2X1 g39995(.A (n_2171), .B (n_2801), .Y (n_2210)); + NOR2X1 g39996(.A (n_2477), .B (n_2686), .Y (n_2209)); + NOR2X1 g40001(.A (n_821), .B (n_2732), .Y (n_2208)); + NOR2X1 g40002(.A (n_2470), .B (n_2716), .Y (n_2207)); + NOR2X1 g40003(.A (n_2169), .B (n_2804), .Y (n_2206)); + NOR2X1 g40005(.A (n_2477), .B (n_2782), .Y (n_2205)); + NOR2X1 g40006(.A (n_2216), .B (n_2794), .Y (n_2204)); + NOR2X1 g40007(.A (n_2025), .B (n_2782), .Y (n_2203)); + NOR2X1 g40011(.A (n_2735), .B (n_2067), .Y (n_2202)); + NOR2X1 g40012(.A (n_2818), .B (n_1985), .Y (n_2201)); + NAND2X1 g39798(.A (n_2491), .B (\u7_mem[0]_106 ), .Y (n_2200)); + NOR2X1 g40013(.A (n_2216), .B (n_2792), .Y (n_2199)); + NOR2X1 g40016(.A (n_867), .B (n_2741), .Y (n_2198)); + NAND2X1 g39689(.A (n_2513), .B (in_slt_445), .Y (n_2197)); + NOR2X1 g40021(.A (n_2686), .B (n_1985), .Y (n_2196)); + NOR2X1 g40022(.A (n_945), .B (n_2767), .Y (n_2195)); + NOR2X1 g40023(.A (n_2765), .B (n_2067), .Y (n_2193)); + NOR2X1 g40024(.A (n_2831), .B (n_2182), .Y (n_2192)); + NOR2X1 g40025(.A (n_945), .B (n_2729), .Y (n_2191)); + NOR2X1 g40026(.A (n_2189), .B (n_2786), .Y (n_2190)); + NOR2X1 g40028(.A (n_935), .B (n_2741), .Y (n_2188)); + NOR2X1 g40031(.A (n_2144), .B (n_2792), .Y (n_2186)); + NOR2X1 g40032(.A (n_2043), .B (n_2741), .Y (n_2185)); + NOR2X1 g40034(.A (n_2470), .B (n_2707), .Y (n_2184)); + NOR2X1 g40038(.A (n_2772), .B (n_2182), .Y (n_2183)); + NOR2X1 g40039(.A (n_2059), .B (n_2772), .Y (n_2181)); + NOR2X1 g40041(.A (n_2470), .B (n_2681), .Y (n_2180)); + NOR2X1 g40042(.A (n_2093), .B (n_2686), .Y (n_2178)); + NOR2X1 g40047(.A (n_2054), .B (n_2782), .Y (n_2177)); + NOR2X1 g40134(.A (n_2732), .B (n_2137), .Y (n_2176)); + NAND2X1 g40049(.A (n_5048), .B (n_4378), .Y (n_2175)); + NOR2X1 g40050(.A (n_2765), .B (n_2182), .Y (n_2174)); + NOR2X1 g40052(.A (n_941), .B (n_2716), .Y (n_2173)); + NOR2X1 g40133(.A (n_2171), .B (n_2864), .Y (n_2172)); + NOR2X1 g40054(.A (n_2169), .B (n_2681), .Y (n_2170)); + NOR2X1 g40055(.A (n_2038), .B (n_2786), .Y (n_2168)); + NOR2X1 g40059(.A (n_867), .B (n_2786), .Y (n_2167)); + NOR2X1 g40062(.A (n_2794), .B (n_1985), .Y (n_2165)); + NOR2X1 g40065(.A (n_2729), .B (n_1985), .Y (n_2164)); + NOR2X1 g40066(.A (n_2081), .B (n_2702), .Y (n_2162)); + NOR2X1 g40068(.A (n_2470), .B (n_2818), .Y (n_2161)); + NOR2X1 g40070(.A (n_2712), .B (n_1985), .Y (n_2160)); + NOR2X1 g40072(.A (n_2864), .B (n_1985), .Y (n_2159)); + NAND2X1 g40074(.A (n_5157), .B (n_4533), .Y (n_2157)); + NOR2X1 g40076(.A (n_2831), .B (n_2057), .Y (n_2156)); + NOR2X1 g40079(.A (n_2154), .B (n_2684), .Y (n_2155)); + NOR2X1 g40080(.A (n_2786), .B (n_1985), .Y (n_2153)); + NOR2X1 g40082(.A (n_2133), .B (n_2804), .Y (n_2152)); + NOR2X1 g40083(.A (n_821), .B (n_2720), .Y (n_2151)); + NOR2X1 g40084(.A (n_2804), .B (n_1985), .Y (n_2149)); + NOR2X1 g40085(.A (n_945), .B (n_2792), .Y (n_2147)); + NOR2X1 g40086(.A (n_821), .B (n_2767), .Y (n_2146)); + NOR2X1 g40087(.A (n_2144), .B (n_2748), .Y (n_2145)); + NOR2X1 g40088(.A (n_2716), .B (n_1985), .Y (n_2143)); + NOR2X1 g40089(.A (n_2470), .B (n_2691), .Y (n_2142)); + NOR2X1 g40091(.A (n_945), .B (n_2765), .Y (n_2141)); + NOR2X1 g40094(.A (n_2470), .B (n_2782), .Y (n_2140)); + NOR2X1 g40097(.A (n_3008), .B (n_2137), .Y (n_2138)); + NOR2X1 g40098(.A (n_2135), .B (n_2829), .Y (n_2136)); + NOR2X1 g40100(.A (n_2133), .B (n_2794), .Y (n_2134)); + NOR2X1 g40102(.A (n_2041), .B (n_2744), .Y (n_2132)); + NOR2X1 g40103(.A (n_2096), .B (n_2804), .Y (n_2131)); + NOR2X1 g40104(.A (n_2083), .B (n_2782), .Y (n_2130)); + NOR2X1 g40106(.A (n_2169), .B (n_2716), .Y (n_2129)); + NAND2X1 g39220(.A (\u8_mem[2]_42 ), .B (n_2362), .Y (n_2128)); + NOR2X1 g40108(.A (n_2120), .B (n_2829), .Y (n_2127)); + NOR2X1 g40109(.A (n_867), .B (n_3008), .Y (n_2126)); + NOR2X1 g40110(.A (n_2691), .B (n_2067), .Y (n_2124)); + NOR2X1 g40111(.A (n_2470), .B (n_2748), .Y (n_2123)); + NOR2X1 g40113(.A (n_2818), .B (n_2118), .Y (n_2122)); + NOR2X1 g40114(.A (n_2120), .B (n_2790), .Y (n_2121)); + NOR2X1 g40115(.A (n_2681), .B (n_2118), .Y (n_2119)); + NOR2X1 g40117(.A (n_2103), .B (n_2735), .Y (n_2117)); + NOR2X1 g40118(.A (n_2470), .B (n_2801), .Y (n_2116)); + NOR2X1 g40119(.A (n_2470), .B (n_2790), .Y (n_2115)); + NOR2X1 g40125(.A (n_2006), .B (n_2707), .Y (n_2114)); + NOR2X1 g40120(.A (n_2470), .B (n_2831), .Y (n_2113)); + NOR2X1 g40121(.A (n_2477), .B (n_2755), .Y (n_2111)); + NOR2X1 g40122(.A (n_2477), .B (n_2786), .Y (n_2110)); + NOR2X1 g40124(.A (n_2470), .B (n_2794), .Y (n_2109)); + NOR2X1 g40127(.A (n_2071), .B (n_2748), .Y (n_2108)); + NOR2X1 g40128(.A (n_2470), .B (n_2686), .Y (n_2107)); + NOR2X1 g40129(.A (n_2477), .B (n_2801), .Y (n_2106)); + NOR2X1 g40130(.A (n_945), .B (n_2801), .Y (n_2105)); + NOR2X1 g40131(.A (n_2103), .B (n_2790), .Y (n_2104)); + NOR2X1 g40132(.A (n_2477), .B (n_2720), .Y (n_2102)); + NOR2X1 g40135(.A (n_2099), .B (n_2684), .Y (n_2100)); + NOR2X1 g40136(.A (n_2790), .B (n_933), .Y (n_2098)); + NOR2X1 g40138(.A (n_2096), .B (n_2681), .Y (n_2097)); + NOR2X1 g40140(.A (n_935), .B (n_2712), .Y (n_2095)); + NOR2X1 g40141(.A (n_2093), .B (n_2794), .Y (n_2094)); + NOR2X1 g40143(.A (n_2801), .B (n_2137), .Y (n_2092)); + NOR2X1 g40147(.A (n_2801), .B (n_2067), .Y (n_2091)); + NOR2X1 g40150(.A (n_941), .B (n_2772), .Y (n_2089)); + NOR2X1 g40153(.A (n_938), .B (n_2691), .Y (n_2087)); + NOR2X1 g40154(.A (n_2085), .B (n_2864), .Y (n_2086)); + NOR2X1 g40155(.A (n_2083), .B (n_2831), .Y (n_2084)); + NOR2X1 g40156(.A (n_2081), .B (n_2763), .Y (n_2082)); + NOR2X1 g40159(.A (n_2135), .B (n_2691), .Y (n_2080)); + NOR2X1 g40160(.A (n_945), .B (n_2741), .Y (n_2079)); + NOR2X1 g40161(.A (n_935), .B (n_2744), .Y (n_2077)); + NOR2X1 g40162(.A (n_2120), .B (n_2716), .Y (n_2075)); + NOR2X1 g40163(.A (n_2470), .B (n_2763), .Y (n_2074)); + NOR2X1 g40164(.A (n_2729), .B (n_2008), .Y (n_2073)); + NOR2X1 g40165(.A (n_2071), .B (n_2735), .Y (n_2072)); + NOR2X1 g40167(.A (n_2470), .B (n_2684), .Y (n_2070)); + NOR2X1 g40168(.A (n_2686), .B (n_2045), .Y (n_2069)); + NOR2X1 g40169(.A (n_2772), .B (n_2067), .Y (n_2068)); + NOR2X1 g40170(.A (n_2477), .B (n_2794), .Y (n_2066)); + NOR2X1 g40171(.A (n_2470), .B (n_2786), .Y (n_2065)); + NOR2X1 g40172(.A (n_2020), .B (n_2716), .Y (n_2064)); + NOR2X1 g40173(.A (n_2470), .B (n_2729), .Y (n_2063)); + NOR2X1 g40174(.A (n_2684), .B (n_1985), .Y (n_2062)); + NOR2X1 g40175(.A (n_2470), .B (n_2792), .Y (n_2061)); + NOR2X1 g40179(.A (n_2059), .B (n_2755), .Y (n_2060)); + NOR2X1 g40180(.A (n_2804), .B (n_2057), .Y (n_2058)); + NOR2X1 g40184(.A (n_2720), .B (n_1985), .Y (n_2056)); + NOR2X1 g40186(.A (n_2054), .B (n_2732), .Y (n_2055)); + NOR2X1 g40187(.A (n_2684), .B (n_2118), .Y (n_2053)); + NAND2X1 g40192(.A (n_5118), .B (n_4540), .Y (n_2052)); + NAND2X1 g39144(.A (in_slt_410), .B (n_2368), .Y (n_4749)); + NOR2X1 g40194(.A (n_2720), .B (n_933), .Y (n_2051)); + NOR2X1 g40195(.A (n_2133), .B (n_2790), .Y (n_2049)); + NOR2X1 g40197(.A (n_2477), .B (n_2702), .Y (n_2048)); + NOR2X1 g40198(.A (n_2470), .B (n_2744), .Y (n_2047)); + NOR2X1 g40203(.A (n_2712), .B (n_2045), .Y (n_2046)); + NOR2X1 g40204(.A (n_2043), .B (n_2801), .Y (n_2044)); + NOR2X1 g40207(.A (n_2041), .B (n_2735), .Y (n_2042)); + NOR2X1 g40209(.A (n_2171), .B (n_2792), .Y (n_2040)); + NOR2X1 g40210(.A (n_2038), .B (n_2767), .Y (n_2039)); + NOR2X1 g40211(.A (n_2081), .B (n_2765), .Y (n_2037)); + NOR2X1 g40212(.A (n_2792), .B (n_933), .Y (n_2036)); + NOR2X1 g40215(.A (n_2103), .B (n_2744), .Y (n_2035)); + NOR2X1 g40216(.A (n_938), .B (n_2831), .Y (n_2034)); + NOR2X1 g40217(.A (n_945), .B (n_2772), .Y (n_2032)); + NOR2X1 g40218(.A (n_2081), .B (n_2735), .Y (n_2030)); + NOR2X1 g40221(.A (n_2071), .B (n_2744), .Y (n_2029)); + NOR2X1 g40222(.A (n_2829), .B (n_933), .Y (n_2028)); + NOR2X1 g40223(.A (n_2071), .B (n_2686), .Y (n_2027)); + NOR2X1 g40225(.A (n_2025), .B (n_2748), .Y (n_2026)); + NOR2X1 g40227(.A (n_2477), .B (n_3008), .Y (n_2024)); + NOR2X1 g40228(.A (n_2154), .B (n_2801), .Y (n_2023)); + NOR2X1 g40229(.A (n_2782), .B (n_2067), .Y (n_2022)); + NOR2X1 g40230(.A (n_2020), .B (n_2804), .Y (n_2021)); + NOR2X1 g40235(.A (n_938), .B (n_2686), .Y (n_2019)); + NOR2X1 g40239(.A (n_2707), .B (n_1985), .Y (n_2018)); + NOR2X1 g40240(.A (n_935), .B (n_2829), .Y (n_2016)); + NOR2X1 g40241(.A (n_867), .B (n_2712), .Y (n_2015)); + NOR2X1 g40242(.A (n_945), .B (n_2755), .Y (n_2014)); + NOR2X1 g40244(.A (n_2041), .B (n_2765), .Y (n_2013)); + NOR2X1 g40250(.A (n_2099), .B (n_2767), .Y (n_2012)); + NOR2X1 g40251(.A (n_2041), .B (n_2702), .Y (n_2011)); + NOR2X1 g40252(.A (n_2096), .B (n_2691), .Y (n_2010)); + NOR2X1 g40254(.A (n_2702), .B (n_2008), .Y (n_2009)); + NOR2X1 g40256(.A (n_2006), .B (n_2716), .Y (n_2007)); + NOR2X1 g40257(.A (n_2864), .B (n_2057), .Y (n_2005)); + NOR2X1 g40258(.A (n_2735), .B (n_2137), .Y (n_2004)); + NOR2X1 g40259(.A (n_945), .B (n_2684), .Y (n_2003)); + NOR2X1 g40260(.A (n_2782), .B (n_1985), .Y (n_2002)); + NOR2X1 g40262(.A (n_938), .B (n_2707), .Y (n_2001)); + NOR2X1 g40266(.A (n_2020), .B (n_2720), .Y (n_2000)); + NOR2X1 g40267(.A (n_2470), .B (n_3008), .Y (n_1999)); + NOR2X1 g40268(.A (n_935), .B (n_2790), .Y (n_1998)); + NOR2X1 g40270(.A (n_2038), .B (n_2765), .Y (n_1997)); + NOR2X1 g40273(.A (n_2093), .B (n_2707), .Y (n_1996)); + NOR2X1 g40274(.A (n_2038), .B (n_2681), .Y (n_1995)); + NOR2X1 g40275(.A (n_2103), .B (n_2829), .Y (n_1994)); + NOR2X1 g40276(.A (n_2755), .B (n_1985), .Y (n_1993)); + NOR2X1 g40277(.A (n_2477), .B (n_2729), .Y (n_1992)); + NOR2X1 g40279(.A (n_935), .B (n_2792), .Y (n_1991)); + NOR2X1 g40280(.A (n_2154), .B (n_2864), .Y (n_1990)); + NOR2X1 g40285(.A (n_2767), .B (n_1985), .Y (n_1989)); + NOR2X1 g40286(.A (n_2755), .B (n_2118), .Y (n_1988)); + NOR2X1 g40288(.A (n_3008), .B (n_2067), .Y (n_1987)); + NOR2X1 g40289(.A (n_2702), .B (n_1985), .Y (n_1986)); + NOR2X1 g40290(.A (n_941), .B (n_2741), .Y (n_1984)); + NOR2X1 g40293(.A (n_2120), .B (n_2720), .Y (n_1983)); + NOR2X1 g40295(.A (n_2748), .B (n_1985), .Y (n_1982)); + NOR2X1 g40296(.A (n_2707), .B (n_2067), .Y (n_1981)); + NOR2X1 g40297(.A (n_2054), .B (n_2686), .Y (n_1980)); + NOR2X1 g40298(.A (n_2691), .B (n_1985), .Y (n_1979)); + NOR2X1 g40299(.A (n_2025), .B (n_2702), .Y (n_1977)); + NOR2X1 g40301(.A (n_2099), .B (n_2735), .Y (n_1976)); + NOR2X1 g40302(.A (n_935), .B (n_2732), .Y (n_1975)); + NOR2X1 g40305(.A (n_2093), .B (n_2782), .Y (n_1974)); + NOR2X1 g40306(.A (n_2477), .B (n_2772), .Y (n_1973)); + NAND2X1 g40307(.A (n_5112), .B (n_4544), .Y (n_1972)); + NOR2X1 g40308(.A (n_945), .B (n_2702), .Y (n_1971)); + NOR2X1 g40309(.A (n_2477), .B (n_2763), .Y (n_1970)); + NOR2X1 g40310(.A (n_2477), .B (n_2818), .Y (n_1969)); + NOR2X1 g40312(.A (n_2144), .B (n_2755), .Y (n_1968)); + NOR2X1 g40314(.A (n_2020), .B (n_2684), .Y (n_1967)); + NOR2X1 g40315(.A (n_2829), .B (n_1985), .Y (n_1966)); + NOR2X1 g40316(.A (n_2716), .B (n_2067), .Y (n_1965)); + NOR2X1 g40317(.A (n_2059), .B (n_2732), .Y (n_1964)); + NOR2X1 g40318(.A (n_2083), .B (n_2707), .Y (n_1963)); + NOR2X1 g40322(.A (n_2470), .B (n_2702), .Y (n_1962)); + NOR2X1 g40323(.A (n_2470), .B (n_2755), .Y (n_1961)); + NOR2X1 g40328(.A (n_2741), .B (n_2045), .Y (n_1960)); + NOR2X1 g40332(.A (n_2189), .B (n_2831), .Y (n_1959)); + NOR2X1 g40335(.A (n_821), .B (n_2772), .Y (n_1958)); + NOR2X1 g40336(.A (n_2470), .B (n_2741), .Y (n_1957)); + NOR2X1 g40337(.A (n_2732), .B (n_2008), .Y (n_1956)); + NOR2X1 g40338(.A (n_2083), .B (n_2763), .Y (n_1955)); + NOR2X1 g40339(.A (n_2133), .B (n_2729), .Y (n_1954)); + NOR2X1 g40340(.A (n_2144), .B (n_3008), .Y (n_1953)); + NOR2X1 g40341(.A (n_2189), .B (n_2681), .Y (n_1952)); + NOR2X1 g40342(.A (n_867), .B (n_2767), .Y (n_1951)); + NOR2X1 g40343(.A (n_2085), .B (n_2794), .Y (n_1950)); + NOR2X1 g40345(.A (n_867), .B (n_2763), .Y (n_1949)); + NOR2X1 g40346(.A (n_2043), .B (n_2763), .Y (n_1948)); + NOR2X1 g40347(.A (n_2169), .B (n_2691), .Y (n_1947)); + NOR2X1 g40348(.A (n_2767), .B (n_2057), .Y (n_1946)); + NOR2X1 g40349(.A (n_2059), .B (n_2729), .Y (n_1945)); + NOR2X1 g40352(.A (n_2043), .B (n_2818), .Y (n_1944)); + NOR2X1 g40354(.A (n_2470), .B (n_2735), .Y (n_1943)); + NOR2X1 g40357(.A (n_2025), .B (n_2712), .Y (n_1942)); + NOR2X1 g40362(.A (n_2096), .B (n_2712), .Y (n_1941)); + NOR2X1 g40364(.A (n_2470), .B (n_2712), .Y (n_1940)); + NOR2X1 g40365(.A (n_867), .B (n_2831), .Y (n_1939)); + NOR2X1 g40367(.A (n_945), .B (n_2818), .Y (n_1938)); + NOR2X1 g40368(.A (n_2135), .B (n_2804), .Y (n_1937)); + NOR2X1 g40369(.A (n_2006), .B (n_2684), .Y (n_1936)); + NOR2X1 g40370(.A (n_2006), .B (n_2691), .Y (n_1935)); + NOR2X1 g40371(.A (n_2085), .B (n_2786), .Y (n_1934)); + NOR2X1 g40372(.A (n_2054), .B (n_2755), .Y (n_1933)); + NOR2X1 g40373(.A (n_2171), .B (n_2818), .Y (n_1932)); + NOR2X1 g40374(.A (n_2792), .B (n_1985), .Y (n_1931)); + NOR2X1 g40375(.A (n_2794), .B (n_2045), .Y (n_1930)); + XOR2X1 g40385(.A (\u8_wp[1] ), .B (n_12280), .Y (n_1929)); + AOI21X1 g40389(.A0 (\u9_rp[0] ), .A1 (n_4074), .B0 (n_1054), .Y + (n_4851)); + AOI21X1 g40390(.A0 (n_1206), .A1 (n_5420), .B0 (n_1207), .Y (n_4104)); + AOI21X1 g40392(.A0 (n_688), .A1 (n_866), .B0 (n_1824), .Y (n_1928)); + XOR2X1 g40395(.A (n_1421), .B (n_1921), .Y (n_5616)); + XOR2X1 g40397(.A (n_1419), .B (n_1923), .Y (n_6049)); + NAND2X1 g39135(.A (\u8_mem[2]_32 ), .B (n_2362), .Y (n_1927)); + XOR2X1 g40399(.A (n_6841), .B (n_907), .Y (n_1926)); + XOR2X1 g40400(.A (n_1417), .B (n_11585), .Y (n_5618)); + XOR2X1 g40402(.A (n_1424), .B (n_1924), .Y (n_5620)); + NAND2X1 g39123(.A (u9_din_tmp_49), .B (n_2368), .Y (n_1925)); + XOR2X1 g40439(.A (n_6316), .B (n_1924), .Y (n_4795)); + XOR2X1 g40440(.A (n_1923), .B (n_6824), .Y (n_4801)); + XOR2X1 g40441(.A (n_6821), .B (n_11585), .Y (n_4799)); + XOR2X1 g40445(.A (n_12634), .B (n_1921), .Y (n_4797)); + NOR2X1 g40101(.A (n_2744), .B (n_2008), .Y (n_1920)); + NAND2X1 g39074(.A (in_slt_407), .B (n_2368), .Y (n_4757)); + INVX1 g40748(.A (n_3316), .Y (n_1918)); + NAND2X1 g39064(.A (\u8_mem[2]_56 ), .B (n_2366), .Y (n_1915)); + INVX2 g39052(.A (n_1910), .Y (n_3979)); + INVX1 g41046(.A (n_3209), .Y (n_1908)); + DFFSRX1 \u15_crac_din_reg[12] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1193), .Q (crac_din_703), .QN ()); + INVX1 g41109(.A (n_3522), .Y (n_1907)); + INVX2 g41112(.A (n_11852), .Y (n_4225)); + INVX4 g41116(.A (n_11852), .Y (n_4130)); + NAND2X1 g39815(.A (n_2344), .B (in_slt_421), .Y (n_1901)); + INVX1 g41184(.A (n_1899), .Y (n_4623)); + INVX4 g41200(.A (n_1845), .Y (n_4253)); + INVX8 g41313(.A (n_1846), .Y (n_6856)); + INVX4 g41363(.A (n_1851), .Y (n_6341)); + INVX1 g41431(.A (n_3556), .Y (n_1894)); + INVX8 g41496(.A (n_1854), .Y (n_6359)); + NAND2X1 g38962(.A (\u8_mem[3]_135 ), .B (n_2468), .Y (n_1892)); + AOI22X1 g37987(.A0 (n_6471), .A1 (n_1575), .B0 (n_6604), .B1 + (n_1831), .Y (n_1891)); + NAND3X1 g34706(.A (n_4703), .B (n_4708), .C (n_865), .Y (n_1887)); + NAND3X1 g34709(.A (n_4734), .B (n_4736), .C (n_864), .Y (n_1886)); + NAND3X1 g34712(.A (n_5588), .B (n_5788), .C (n_863), .Y (n_1885)); + NOR2X1 g40261(.A (n_2741), .B (n_1985), .Y (n_1884)); + NAND2X1 g38913(.A (\u8_mem[3]_139 ), .B (n_2468), .Y (n_1883)); + NAND2X1 g38915(.A (\u8_mem[3]_127 ), .B (n_2468), .Y (n_1881)); + INVX1 g42706(.A (n_862), .Y (n_11043)); + INVX2 g42727(.A (n_2343), .Y (n_10940)); + NOR2X1 g40265(.A (n_2763), .B (n_1985), .Y (n_1871)); + INVX1 g43038(.A (n_1873), .Y (n_1870)); + NAND2X1 g38884(.A (\u6_mem[3]_127 ), .B (n_2419), .Y (n_1869)); + NAND2X1 g39880(.A (\u8_mem[2]_41 ), .B (n_2362), .Y (n_1867)); + DFFSRX1 \u15_crac_din_reg[1] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1202), .Q (crac_din_692), .QN ()); + NAND2X1 g39900(.A (\u8_mem[2]_37 ), .B (n_2366), .Y (n_11450)); + AOI22X1 g37984(.A0 (n_2558), .A1 (n_1864), .B0 (n_1863), .B1 + (n_2544), .Y (n_1865)); + DFFSRX1 \u15_crac_din_reg[7] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1022), .Q (crac_din_698), .QN ()); + AOI22X1 g37655(.A0 (n_2558), .A1 (n_5959), .B0 (n_5998), .B1 + (n_2544), .Y (n_1862)); + NAND2X1 g38818(.A (\u6_mem[3]_130 ), .B (n_12622), .Y (n_1861)); + DFFSRX1 \u15_crac_din_reg[14] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1030), .Q (crac_din_705), .QN ()); + AOI22X1 g37952(.A0 (n_2502), .A1 (n_6392), .B0 (n_6534), .B1 + (n_1859), .Y (n_1860)); + AOI22X1 g37932(.A0 (n_385), .A1 (n_1835), .B0 (n_5365), .B1 (n_1760), + .Y (n_1858)); + AOI22X1 g37937(.A0 (n_236), .A1 (n_1575), .B0 (n_5502), .B1 (n_1831), + .Y (n_1855)); + INVX2 g41427(.A (n_12747), .Y (n_4258)); + AOI22X1 g37915(.A0 (n_6656), .A1 (n_1859), .B0 (n_6620), .B1 + (n_1760), .Y (n_1848)); + DFFSRX1 \u15_crac_din_reg[10] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1031), .Q (crac_din_701), .QN ()); + DFFSRX1 \u15_crac_din_reg[15] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1083), .Q (crac_din_706), .QN ()); + DFFSRX1 \u15_crac_din_reg[4] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1034), .Q (crac_din_695), .QN ()); + DFFSRX1 \u15_crac_din_reg[8] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1037), .Q (crac_din_699), .QN ()); + AOI22X1 g37904(.A0 (n_2558), .A1 (n_6384), .B0 (n_6468), .B1 + (n_1839), .Y (n_1840)); + DFFSRX1 \u15_crac_din_reg[11] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1029), .Q (crac_din_702), .QN ()); + NOR2X1 g39975(.A (n_867), .B (n_2681), .Y (n_1838)); + AOI22X1 g37888(.A0 (n_1756), .A1 (n_6372), .B0 (n_6519), .B1 + (n_1643), .Y (n_1837)); + DFFSRX1 \u15_crac_din_reg[13] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1192), .Q (crac_din_704), .QN ()); + DFFSRX1 \u15_crac_din_reg[2] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1194), .Q (crac_din_693), .QN ()); + AOI22X1 g37754(.A0 (n_6884), .A1 (n_1859), .B0 (n_6873), .B1 + (n_1835), .Y (n_1836)); + AOI21X1 g37610(.A0 (n_6087), .A1 (n_1760), .B0 (n_1222), .Y (n_1834)); + DFFSRX1 \u15_crac_din_reg[0] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1074), .Q (crac_din), .QN ()); + XOR2X1 g40401(.A (n_6838), .B (n_814), .Y (n_1833)); + AOI22X1 g37866(.A0 (n_6431), .A1 (n_1575), .B0 (n_6650), .B1 + (n_1831), .Y (n_1832)); + NOR2X1 g36374(.A (n_1829), .B (n_698), .Y (n_2631)); + INVX1 g43029(.A (n_1875), .Y (n_11083)); + INVX2 g43028(.A (n_1875), .Y (n_11086)); + DFFSRX1 \u15_crac_din_reg[5] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1197), .Q (crac_din_696), .QN ()); + NOR2X1 g40237(.A (n_2477), .B (n_2707), .Y (n_1827)); + NAND4X1 g36545(.A (n_1014), .B (n_680), .C (\u26_ps_cnt[5] ), .D + (\u26_ps_cnt[4] ), .Y (n_5632)); + NOR2X1 g40004(.A (n_2790), .B (n_1985), .Y (n_1826)); + NAND3X1 g36565(.A (n_1822), .B (n_1824), .C (n_684), .Y (n_1825)); + NAND2X1 g39323(.A (in_slt_413), .B (n_2368), .Y (n_4769)); + NAND3X1 g36696(.A (n_1822), .B (n_1824), .C (\u2_cnt[2] ), .Y + (n_1823)); + XOR2X1 g36743(.A (\u26_cnt[2] ), .B (n_793), .Y (n_1821)); + XOR2X1 g36744(.A (n_1819), .B (n_1553), .Y (n_1820)); + XOR2X1 g36745(.A (\u2_res_cnt[2] ), .B (n_1277), .Y (n_1818)); + DFFX1 \u5_status_reg[0] (.CK (clk_i), .D (n_6047), .Q (o6_status), + .QN ()); + DFFX1 \u8_status_reg[0] (.CK (clk_i), .D (n_5622), .Q (o9_status), + .QN ()); + NAND2X1 g36783(.A (n_825), .B (n_2513), .Y (n_1816)); + OR2X1 g36795(.A (n_1815), .B (wb_addr_i[6]), .Y (n_4837)); + OR2X1 g36812(.A (n_1815), .B (wb_we_i), .Y (n_1814)); + NAND2X1 g36839(.A (n_1204), .B (n_2368), .Y (n_1813)); + NAND2X1 g38809(.A (\u8_mem[3]_147 ), .B (n_2468), .Y (n_1812)); + NAND2X1 g38803(.A (\u3_mem[3]_150 ), .B (n_2463), .Y (n_1811)); + NAND2X1 g39560(.A (\u6_mem[2]_35 ), .B (n_2285), .Y (n_1810)); + NAND2X1 g39552(.A (n_2491), .B (\u7_mem[0]_97 ), .Y (n_1809)); + NAND2X1 g39546(.A (\u4_mem[2]_39 ), .B (n_12079), .Y (n_1808)); + NAND2X1 g39544(.A (n_2491), .B (\u7_mem[0]_113 ), .Y (n_1807)); + XOR2X1 g40403(.A (n_7048), .B (n_888), .Y (n_1806)); + NOR2X1 g40060(.A (n_2744), .B (n_2182), .Y (n_1805)); + INVX1 g38773(.A (n_5442), .Y (n_1804)); + OAI21X1 g37200(.A0 (\u11_rp[1] ), .A1 (n_853), .B0 (n_1121), .Y + (n_4081)); + NAND2X1 g39502(.A (in_slt_412), .B (n_2368), .Y (n_4772)); + NOR2X1 g40044(.A (n_941), .B (n_2729), .Y (n_1800)); + OR2X1 g39475(.A (n_12640), .B (n_12634), .Y (n_1798)); + DFFSRX1 \u15_crac_din_reg[3] (.RN (rst_i), .SN (1'b1), .CK (clk_i), + .D (n_1047), .Q (crac_din_694), .QN ()); + NAND2X1 g39473(.A (n_2344), .B (in_slt_425), .Y (n_1796)); + NAND2X1 g39471(.A (n_2344), .B (in_slt_431), .Y (n_1795)); + NAND4X1 g37360(.A (n_792), .B (n_549), .C (n_728), .D (n_543), .Y + (n_1794)); + NAND4X1 g37368(.A (n_732), .B (n_557), .C (n_574), .D (n_725), .Y + (n_1793)); + NOR2X1 g40036(.A (n_2470), .B (n_2829), .Y (n_1792)); + NAND2X1 g39468(.A (\u5_mem[2]_48 ), .B (n_12823), .Y (n_1791)); + XOR2X1 g37419(.A (n_614), .B (n_765), .Y (n_1790)); + XOR2X1 g37420(.A (n_657), .B (n_771), .Y (n_1788)); + NAND2X1 g39466(.A (\u4_mem[2] ), .B (n_12079), .Y (n_1786)); + DFFX1 \u1_sr_reg[1] (.CK (bit_clk_pad_i), .D (u1_sr), .Q (u1_sr_117), + .QN ()); + NAND2X1 g37471(.A (n_1784), .B (\u2_cnt[5] ), .Y (n_1785)); + NAND2X1 g37472(.A (n_2592), .B (n_688), .Y (n_1782)); + INVX2 g37526(.A (n_1779), .Y (n_6686)); + OR2X1 g37572(.A (n_1777), .B (ac97_reset_pad_o_), .Y (n_1778)); + NAND4X1 g37576(.A (n_1051), .B (n_449), .C (n_742), .D (\u2_to_cnt[0] + ), .Y (n_5629)); + NAND2X1 g37582(.A (n_3985), .B (n_593), .Y (n_1776)); + NAND4X1 g37593(.A (\u26_ps_cnt[3] ), .B (\u26_ps_cnt[1] ), .C + (\u26_ps_cnt[0] ), .D (n_681), .Y (n_1775)); + NAND3X1 g37594(.A (n_1519), .B (n_1773), .C (\u2_cnt[4] ), .Y + (n_1774)); + AOI22X1 g37604(.A0 (n_650), .A1 (n_1546), .B0 (n_12634), .B1 + (\u7_rp[3] ), .Y (n_1772)); + AOI22X1 g37612(.A0 (n_2502), .A1 (n_6868), .B0 (n_6956), .B1 + (n_1859), .Y (n_1770)); + AOI21X1 g37613(.A0 (n_6924), .A1 (n_1760), .B0 (n_1220), .Y (n_1768)); + AOI22X1 g37614(.A0 (n_2502), .A1 (n_349), .B0 (n_1766), .B1 (n_1835), + .Y (n_1767)); + AOI22X1 g37615(.A0 (n_2502), .A1 (n_6402), .B0 (n_6551), .B1 + (n_1859), .Y (n_1765)); + AOI22X1 g37616(.A0 (n_6644), .A1 (n_1835), .B0 (n_6617), .B1 + (n_1760), .Y (n_1764)); + AOI22X1 g37617(.A0 (n_6495), .A1 (n_1835), .B0 (n_6614), .B1 + (n_1760), .Y (n_1763)); + AOI22X1 g37618(.A0 (n_6641), .A1 (n_1835), .B0 (n_6450), .B1 + (n_1760), .Y (n_1761)); + AOI22X1 g37620(.A0 (n_2502), .A1 (n_6396), .B0 (n_6528), .B1 + (n_1859), .Y (n_1759)); + AOI22X1 g37621(.A0 (n_6635), .A1 (n_1835), .B0 (n_6581), .B1 + (n_1760), .Y (n_1758)); + AOI22X1 g37622(.A0 (n_1756), .A1 (n_1755), .B0 (n_1754), .B1 + (n_1643), .Y (n_1757)); + AOI22X1 g37623(.A0 (n_2502), .A1 (n_6866), .B0 (n_6922), .B1 + (n_1760), .Y (n_1753)); + AOI22X1 g37624(.A0 (n_2502), .A1 (n_6864), .B0 (n_6954), .B1 + (n_1859), .Y (n_1752)); + AOI22X1 g37625(.A0 (n_6935), .A1 (n_1835), .B0 (n_6951), .B1 + (n_1760), .Y (n_1751)); + AOI22X1 g37626(.A0 (n_204), .A1 (n_1859), .B0 (n_6089), .B1 (n_1760), + .Y (n_1750)); + AOI22X1 g37627(.A0 (n_2502), .A1 (n_174), .B0 (n_1748), .B1 (n_1859), + .Y (n_1749)); + AOI22X1 g37628(.A0 (n_2502), .A1 (n_6862), .B0 (n_6949), .B1 + (n_1859), .Y (n_1747)); + AOI22X1 g37629(.A0 (n_6881), .A1 (n_1835), .B0 (n_6919), .B1 + (n_1760), .Y (n_1746)); + AOI22X1 g37630(.A0 (n_356), .A1 (n_1859), .B0 (n_1744), .B1 (n_1835), + .Y (n_1745)); + AOI22X1 g37631(.A0 (n_2502), .A1 (n_1742), .B0 (n_5294), .B1 + (n_1760), .Y (n_1743)); + AOI22X1 g37632(.A0 (n_35), .A1 (n_1835), .B0 (n_5374), .B1 (n_1760), + .Y (n_1741)); + AOI22X1 g37633(.A0 (n_2502), .A1 (n_1738), .B0 (n_1737), .B1 + (n_1859), .Y (n_1739)); + AOI22X1 g37634(.A0 (n_198), .A1 (n_1835), .B0 (n_5343), .B1 (n_1760), + .Y (n_1736)); + AOI22X1 g37635(.A0 (n_340), .A1 (n_1859), .B0 (n_5372), .B1 (n_1760), + .Y (n_1735)); + AOI22X1 g37636(.A0 (n_2502), .A1 (n_1733), .B0 (n_1732), .B1 + (n_1859), .Y (n_1734)); + AOI22X1 g37637(.A0 (n_45), .A1 (n_1859), .B0 (n_5302), .B1 (n_1760), + .Y (n_1731)); + AOI22X1 g37638(.A0 (n_365), .A1 (n_1835), .B0 (n_5369), .B1 (n_1760), + .Y (n_1730)); + AOI22X1 g37639(.A0 (n_2502), .A1 (n_1728), .B0 (n_1727), .B1 + (n_1859), .Y (n_1729)); + AOI22X1 g37640(.A0 (n_346), .A1 (n_1835), .B0 (n_5367), .B1 (n_1760), + .Y (n_1726)); + AOI22X1 g37641(.A0 (n_2502), .A1 (n_1724), .B0 (n_1723), .B1 + (n_1859), .Y (n_1725)); + AOI22X1 g37642(.A0 (n_345), .A1 (n_1835), .B0 (n_5347), .B1 (n_1760), + .Y (n_1722)); + AOI22X1 g37643(.A0 (n_206), .A1 (n_1859), .B0 (n_5345), .B1 (n_1760), + .Y (n_1720)); + AOI22X1 g37644(.A0 (n_2502), .A1 (n_6859), .B0 (n_6879), .B1 + (n_1859), .Y (n_1719)); + AOI22X1 g37645(.A0 (n_6933), .A1 (n_1835), .B0 (n_6915), .B1 + (n_1760), .Y (n_1718)); + AOI22X1 g37646(.A0 (n_2502), .A1 (n_1716), .B0 (n_1715), .B1 + (n_1859), .Y (n_1717)); + AOI22X1 g37647(.A0 (n_2502), .A1 (n_6857), .B0 (n_6947), .B1 + (n_1859), .Y (n_1714)); + AOI22X1 g37648(.A0 (n_6888), .A1 (n_1835), .B0 (n_6890), .B1 + (n_1760), .Y (n_1712)); + AOI22X1 g37649(.A0 (n_6931), .A1 (n_1835), .B0 (n_6895), .B1 + (n_1760), .Y (n_1711)); + AOI22X1 g37650(.A0 (n_6902), .A1 (n_1835), .B0 (n_6912), .B1 + (n_1760), .Y (n_1710)); + AOI22X1 g37651(.A0 (n_2502), .A1 (n_6847), .B0 (n_6928), .B1 + (n_1835), .Y (n_1709)); + AOI22X1 g37652(.A0 (n_6628), .A1 (n_1835), .B0 (n_6559), .B1 + (n_1760), .Y (n_1707)); + AOI22X1 g37653(.A0 (n_6893), .A1 (n_1835), .B0 (n_6905), .B1 + (n_1760), .Y (n_1706)); + AOI22X1 g37665(.A0 (n_2502), .A1 (n_1704), .B0 (n_1703), .B1 + (n_1859), .Y (n_1705)); + AOI22X1 g37669(.A0 (n_2502), .A1 (n_1701), .B0 (n_1700), .B1 + (n_1835), .Y (n_1702)); + AOI22X1 g37671(.A0 (n_347), .A1 (n_1835), .B0 (n_5333), .B1 (n_1760), + .Y (n_1699)); + AOI22X1 g37675(.A0 (n_6638), .A1 (n_1835), .B0 (n_6505), .B1 + (n_1760), .Y (n_1698)); + AOI22X1 g37676(.A0 (n_2502), .A1 (n_6404), .B0 (n_6647), .B1 + (n_1835), .Y (n_1697)); + AOI22X1 g37679(.A0 (n_6940), .A1 (n_1859), .B0 (n_6909), .B1 + (n_1760), .Y (n_1696)); + AOI22X1 g37689(.A0 (n_2558), .A1 (n_6390), .B0 (n_6660), .B1 + (n_2544), .Y (n_1695)); + AOI22X1 g37690(.A0 (n_6942), .A1 (n_1859), .B0 (n_6900), .B1 + (n_1835), .Y (n_1694)); + AOI22X1 g37692(.A0 (n_2502), .A1 (n_6849), .B0 (n_6886), .B1 + (n_1760), .Y (n_1693)); + AOI22X1 g37695(.A0 (n_6033), .A1 (n_2544), .B0 (n_6013), .B1 + (n_1316), .Y (n_1692)); + AOI22X1 g37700(.A0 (n_2558), .A1 (n_314), .B0 (n_1690), .B1 (n_2544), + .Y (n_1691)); + AOI22X1 g37703(.A0 (n_6548), .A1 (n_1643), .B0 (n_6625), .B1 + (n_1831), .Y (n_1689)); + AOI22X1 g37707(.A0 (n_2558), .A1 (n_5949), .B0 (n_6028), .B1 + (n_2544), .Y (n_1687)); + AOI22X1 g37726(.A0 (n_2558), .A1 (n_1685), .B0 (n_1684), .B1 + (n_1839), .Y (n_1686)); + AOI22X1 g37728(.A0 (n_9), .A1 (n_2544), .B0 (n_5514), .B1 (n_1316), + .Y (n_1683)); + AOI22X1 g37733(.A0 (n_2502), .A1 (n_1680), .B0 (n_1679), .B1 + (n_1859), .Y (n_1681)); + AOI22X1 g37734(.A0 (n_2558), .A1 (n_1677), .B0 (n_1676), .B1 + (n_1839), .Y (n_1678)); + AOI22X1 g37736(.A0 (n_379), .A1 (n_2544), .B0 (n_5359), .B1 (n_1316), + .Y (n_1675)); + AOI22X1 g37741(.A0 (n_2502), .A1 (n_6852), .B0 (n_6945), .B1 + (n_1859), .Y (n_1674)); + NOR2X1 g39997(.A (n_2218), .B (n_2712), .Y (n_1673)); + AOI22X1 g37761(.A0 (n_1756), .A1 (n_6377), .B0 (n_6522), .B1 + (n_1643), .Y (n_1672)); + AOI21X1 g37763(.A0 (n_6554), .A1 (n_1831), .B0 (n_1215), .Y (n_1671)); + AOI22X1 g37765(.A0 (n_2502), .A1 (n_6854), .B0 (n_6876), .B1 + (n_1859), .Y (n_1669)); + AOI22X1 g37766(.A0 (n_1756), .A1 (n_6370), .B0 (n_6517), .B1 + (n_1643), .Y (n_1668)); + AOI21X1 g37768(.A0 (n_6426), .A1 (n_1831), .B0 (n_1005), .Y (n_1667)); + AOI22X1 g37769(.A0 (n_1756), .A1 (n_6368), .B0 (n_6515), .B1 + (n_1643), .Y (n_1666)); + AOI22X1 g37771(.A0 (n_1756), .A1 (n_6366), .B0 (n_6511), .B1 + (n_1643), .Y (n_1665)); + AOI21X1 g37772(.A0 (n_6424), .A1 (n_1831), .B0 (n_1211), .Y (n_1664)); + AOI22X1 g37773(.A0 (n_162), .A1 (n_1839), .B0 (n_5504), .B1 (n_1316), + .Y (n_1663)); + AOI22X1 g37774(.A0 (n_1756), .A1 (n_6363), .B0 (n_6466), .B1 + (n_1575), .Y (n_1662)); + AOI22X1 g37776(.A0 (n_6507), .A1 (n_1643), .B0 (n_6421), .B1 + (n_1831), .Y (n_1661)); + AOI22X1 g37779(.A0 (n_1756), .A1 (n_6360), .B0 (n_6503), .B1 + (n_1643), .Y (n_1660)); + AOI22X1 g37780(.A0 (n_6460), .A1 (n_1575), .B0 (n_6419), .B1 + (n_1831), .Y (n_1658)); + AOI22X1 g37781(.A0 (n_2558), .A1 (n_6382), .B0 (n_6463), .B1 + (n_1839), .Y (n_1657)); + AOI22X1 g37785(.A0 (n_1756), .A1 (n_5953), .B0 (n_5990), .B1 + (n_1643), .Y (n_1656)); + AOI22X1 g37786(.A0 (n_5994), .A1 (n_1575), .B0 (n_6023), .B1 + (n_1831), .Y (n_1655)); + AOI22X1 g37788(.A0 (n_1756), .A1 (n_5951), .B0 (n_5988), .B1 + (n_1643), .Y (n_1654)); + AOI22X1 g37789(.A0 (n_6479), .A1 (n_1575), .B0 (n_6428), .B1 + (n_1831), .Y (n_1653)); + AOI22X1 g37790(.A0 (n_5978), .A1 (n_1575), .B0 (n_6026), .B1 + (n_1831), .Y (n_1652)); + AOI22X1 g37792(.A0 (n_1756), .A1 (n_334), .B0 (n_1650), .B1 (n_1643), + .Y (n_1651)); + AOI22X1 g37793(.A0 (n_129), .A1 (n_1575), .B0 (n_5580), .B1 (n_1831), + .Y (n_1648)); + AOI22X1 g37795(.A0 (n_2558), .A1 (n_6335), .B0 (n_6623), .B1 + (n_2544), .Y (n_1646)); + AOI22X1 g37796(.A0 (n_1756), .A1 (n_312), .B0 (n_1644), .B1 (n_1643), + .Y (n_1645)); + AOI22X1 g37798(.A0 (n_288), .A1 (n_1575), .B0 (n_5582), .B1 (n_1831), + .Y (n_1642)); + AOI22X1 g37799(.A0 (n_6411), .A1 (n_1839), .B0 (n_6569), .B1 + (n_1316), .Y (n_1640)); + AOI22X1 g37800(.A0 (n_2502), .A1 (n_6398), .B0 (n_6654), .B1 + (n_1859), .Y (n_1639)); + AOI22X1 g37801(.A0 (n_1756), .A1 (n_6388), .B0 (n_6500), .B1 + (n_1643), .Y (n_1638)); + AOI22X1 g37802(.A0 (n_6454), .A1 (n_1575), .B0 (n_6413), .B1 + (n_1831), .Y (n_1637)); + AOI22X1 g37805(.A0 (n_1756), .A1 (n_1634), .B0 (n_1633), .B1 + (n_1643), .Y (n_1635)); + NOR2X1 g40189(.A (n_2477), .B (n_2748), .Y (n_1632)); + AOI22X1 g37807(.A0 (n_81), .A1 (n_1575), .B0 (n_5494), .B1 (n_1831), + .Y (n_1631)); + AOI22X1 g37809(.A0 (n_1756), .A1 (n_1628), .B0 (n_1627), .B1 + (n_1575), .Y (n_1629)); + AOI22X1 g37811(.A0 (n_339), .A1 (n_1643), .B0 (n_5526), .B1 (n_1831), + .Y (n_1625)); + NAND2X1 g39403(.A (\u5_mem[2]_59 ), .B (n_12823), .Y (n_1624)); + AOI22X1 g37814(.A0 (n_279), .A1 (n_1575), .B0 (n_5488), .B1 (n_1831), + .Y (n_1623)); + AOI22X1 g37817(.A0 (n_1756), .A1 (n_1620), .B0 (n_1619), .B1 + (n_1643), .Y (n_1621)); + AOI22X1 g37818(.A0 (n_277), .A1 (n_1575), .B0 (n_5490), .B1 (n_1831), + .Y (n_1617)); + AOI22X1 g37820(.A0 (n_1756), .A1 (n_1615), .B0 (n_1614), .B1 + (n_1643), .Y (n_1616)); + AOI22X1 g37821(.A0 (n_275), .A1 (n_1575), .B0 (n_5496), .B1 (n_1831), + .Y (n_1613)); + AOI22X1 g37822(.A0 (n_5966), .A1 (n_1839), .B0 (n_6002), .B1 + (n_1316), .Y (n_1612)); + AOI22X1 g37823(.A0 (n_1756), .A1 (n_1610), .B0 (n_1609), .B1 + (n_1643), .Y (n_1611)); + AOI22X1 g37824(.A0 (n_270), .A1 (n_1575), .B0 (n_5492), .B1 (n_1831), + .Y (n_1607)); + AOI22X1 g37826(.A0 (n_1756), .A1 (n_1605), .B0 (n_1604), .B1 + (n_1643), .Y (n_1606)); + AOI22X1 g37827(.A0 (n_298), .A1 (n_1575), .B0 (n_5500), .B1 (n_1831), + .Y (n_1603)); + AOI22X1 g37828(.A0 (n_122), .A1 (n_1575), .B0 (n_5522), .B1 (n_1831), + .Y (n_1602)); + AOI22X1 g37830(.A0 (n_1756), .A1 (n_1600), .B0 (n_1599), .B1 + (n_1643), .Y (n_1601)); + AOI22X1 g37831(.A0 (n_1756), .A1 (n_1596), .B0 (n_1595), .B1 + (n_1643), .Y (n_1597)); + AOI22X1 g37832(.A0 (n_188), .A1 (n_1575), .B0 (n_5498), .B1 (n_1831), + .Y (n_1594)); + AOI22X1 g37833(.A0 (n_1756), .A1 (n_1592), .B0 (n_1591), .B1 + (n_1643), .Y (n_1593)); + AOI22X1 g37836(.A0 (n_125), .A1 (n_1575), .B0 (n_5524), .B1 (n_1831), + .Y (n_1590)); + AOI22X1 g37837(.A0 (n_1756), .A1 (n_6357), .B0 (n_6498), .B1 + (n_1643), .Y (n_1588)); + AOI22X1 g37838(.A0 (n_6448), .A1 (n_1575), .B0 (n_6524), .B1 + (n_1831), .Y (n_1587)); + AOI22X1 g37839(.A0 (n_1756), .A1 (n_1585), .B0 (n_1584), .B1 + (n_1643), .Y (n_1586)); + AOI22X1 g37840(.A0 (n_190), .A1 (n_1575), .B0 (n_5508), .B1 (n_1831), + .Y (n_1583)); + AOI22X1 g37841(.A0 (n_1756), .A1 (n_1581), .B0 (n_1580), .B1 + (n_1643), .Y (n_1582)); + AOI22X1 g37842(.A0 (n_1756), .A1 (n_6355), .B0 (n_6492), .B1 + (n_1643), .Y (n_1579)); + AOI22X1 g37844(.A0 (n_6445), .A1 (n_1575), .B0 (n_6417), .B1 + (n_1831), .Y (n_1578)); + AOI22X1 g37846(.A0 (n_1756), .A1 (n_6353), .B0 (n_6490), .B1 + (n_1643), .Y (n_1577)); + AOI22X1 g37847(.A0 (n_6439), .A1 (n_1575), .B0 (n_6441), .B1 + (n_1831), .Y (n_1576)); + AOI22X1 g37848(.A0 (n_1756), .A1 (n_6351), .B0 (n_6545), .B1 + (n_1643), .Y (n_1574)); + AOI22X1 g37851(.A0 (n_6437), .A1 (n_1575), .B0 (n_6556), .B1 + (n_1831), .Y (n_1573)); + AOI22X1 g37852(.A0 (n_1756), .A1 (n_6349), .B0 (n_6487), .B1 + (n_1643), .Y (n_1572)); + AOI22X1 g37855(.A0 (n_6434), .A1 (n_1575), .B0 (n_6658), .B1 + (n_1831), .Y (n_1571)); + AOI22X1 g37857(.A0 (n_1756), .A1 (n_6347), .B0 (n_6530), .B1 + (n_1575), .Y (n_1570)); + AOI22X1 g37862(.A0 (n_1756), .A1 (n_6344), .B0 (n_6484), .B1 + (n_1643), .Y (n_1569)); + AOI22X1 g37864(.A0 (n_2502), .A1 (n_6400), .B0 (n_6540), .B1 + (n_1859), .Y (n_1568)); + AOI22X1 g37869(.A0 (n_1756), .A1 (n_5947), .B0 (n_5984), .B1 + (n_1643), .Y (n_1567)); + AOI22X1 g37871(.A0 (n_5969), .A1 (n_1575), .B0 (n_6035), .B1 + (n_1831), .Y (n_1566)); + NAND2X1 g39971(.A (n_2491), .B (\u7_mem[0]_115 ), .Y (n_1565)); + NAND2X1 g39973(.A (n_2325), .B (in_slt_452), .Y (n_1564)); + AOI22X1 g37909(.A0 (n_2502), .A1 (n_1562), .B0 (n_1561), .B1 + (n_1835), .Y (n_1563)); + ADDHX1 g36199(.A (n_686), .B (\u10_wp[2] ), .CO (n_1559), .S + (n_1560)); + ADDHX1 g36201(.A (n_606), .B (\u9_wp[2] ), .CO (n_1557), .S (n_1558)); + NOR2X1 g39959(.A (n_2829), .B (n_1488), .Y (n_1556)); + NOR2X1 g39955(.A (n_2702), .B (n_1488), .Y (n_1555)); + NAND3X1 g37189(.A (n_1553), .B (n_1281), .C (n_4088), .Y (n_2615)); + INVX1 g41690(.A (n_2302), .Y (n_1889)); + INVX4 g41686(.A (n_1364), .Y (n_3339)); + XOR2X1 g38469(.A (n_684), .B (n_1253), .Y (n_1552)); + NAND2X1 g38799(.A (n_605), .B (n_1142), .Y (n_3942)); + INVX1 g40704(.A (n_2366), .Y (n_1549)); + NAND2X1 g38830(.A (\u5_mem[3]_128 ), .B (n_1543), .Y (n_1548)); + NAND2X1 g38837(.A (\u7_mem[3]_146 ), .B (n_1546), .Y (n_1547)); + NAND2X1 g38838(.A (\u7_mem[3]_131 ), .B (n_1538), .Y (n_1545)); + NAND2X1 g38843(.A (\u5_mem[3]_129 ), .B (n_1543), .Y (n_1544)); + NAND2X1 g38846(.A (\u5_mem[3]_132 ), .B (n_1543), .Y (n_1542)); + NAND2X1 g38850(.A (\u5_mem[3]_135 ), .B (n_1543), .Y (n_1541)); + NAND2X1 g38874(.A (\u7_mem[3]_134 ), .B (n_1538), .Y (n_1537)); + NAND2X1 g38875(.A (\u7_mem[3]_152 ), .B (n_1546), .Y (n_1536)); + NAND2X1 g38876(.A (\u7_mem[3]_148 ), .B (n_1546), .Y (n_1535)); + NAND2X1 g38877(.A (\u5_mem[3]_134 ), .B (n_1543), .Y (n_1534)); + NAND2X1 g38881(.A (\u7_mem[3]_136 ), .B (n_1538), .Y (n_1533)); + NAND2X1 g38908(.A (\u3_mem[3]_127 ), .B (n_1517), .Y (n_1532)); + NAND2X1 g38925(.A (\u7_mem[3]_124 ), .B (n_1538), .Y (n_1531)); + NAND2X1 g38926(.A (\u7_mem[3]_133 ), .B (n_1538), .Y (n_1530)); + NAND2X1 g38927(.A (\u7_mem[3]_129 ), .B (n_1538), .Y (n_1529)); + NAND2X1 g38928(.A (\u7_mem[3]_128 ), .B (n_1538), .Y (n_1528)); + NAND2X1 g38929(.A (\u7_mem[3]_144 ), .B (n_1546), .Y (n_1527)); + NAND2X1 g38930(.A (\u7_mem[3]_130 ), .B (n_1538), .Y (n_1526)); + NAND2X1 g38931(.A (\u7_mem[3]_145 ), .B (n_1546), .Y (n_1525)); + NAND2X1 g38933(.A (\u7_mem[3]_135 ), .B (n_1538), .Y (n_1524)); + NAND2X1 g38934(.A (\u7_mem[3]_149 ), .B (n_1546), .Y (n_1523)); + NAND2X1 g38936(.A (\u7_mem[3]_151 ), .B (n_1546), .Y (n_1522)); + NAND2X1 g38937(.A (\u7_mem[3]_139 ), .B (n_1538), .Y (n_1521)); + INVX1 g38942(.A (n_1519), .Y (n_1520)); + NAND2X1 g38947(.A (\u3_mem[3]_125 ), .B (n_1517), .Y (n_1518)); + NAND2X1 g38950(.A (\u7_mem[3]_141 ), .B (n_1546), .Y (n_1516)); + NAND2X1 g38952(.A (\u3_mem[3]_136 ), .B (n_1517), .Y (n_1515)); + NAND2X1 g38954(.A (\u3_mem[3] ), .B (n_1517), .Y (n_1514)); + NAND2X1 g38956(.A (\u3_mem[3]_131 ), .B (n_1517), .Y (n_1513)); + NAND2X1 g38967(.A (\u3_mem[3]_122 ), .B (n_1517), .Y (n_1512)); + NAND2X1 g38968(.A (\u3_mem[3]_124 ), .B (n_1517), .Y (n_1511)); + NAND2X1 g38987(.A (\u3_mem[3]_138 ), .B (n_1517), .Y (n_1508)); + NAND2X1 g38989(.A (\u3_mem[3]_126 ), .B (n_1517), .Y (n_1507)); + NAND2X1 g38992(.A (\u7_mem[3]_126 ), .B (n_1538), .Y (n_1506)); + NOR2X1 g39003(.A (n_2732), .B (n_1488), .Y (n_1504)); + NOR2X1 g39010(.A (n_2801), .B (n_1488), .Y (n_1503)); + BUFX3 g39055(.A (n_3985), .Y (n_4726)); + NOR2X1 g39068(.A (n_2744), .B (n_1488), .Y (n_1502)); + NOR2X1 g39083(.A (n_2691), .B (n_1488), .Y (n_1501)); + NAND2X1 g39090(.A (n_1546), .B (n_457), .Y (n_1500)); + INVX4 g39105(.A (n_1185), .Y (n_5272)); + NAND3X1 g39111(.A (\u7_mem[0]_92 ), .B (n_907), .C (n_1921), .Y + (n_1499)); + NOR2X1 g39122(.A (n_2831), .B (n_1488), .Y (n_1498)); + NOR2X1 g39125(.A (n_2790), .B (n_1488), .Y (n_1496)); + NOR2X1 g39137(.A (n_2782), .B (n_1488), .Y (n_1495)); + NAND3X1 g39151(.A (\u8_mem[0]_106 ), .B (n_12280), .C (n_691), .Y + (n_1493)); + NOR2X1 g39162(.A (n_2729), .B (n_1488), .Y (n_1492)); + NAND3X1 g39193(.A (\u4_mem[0]_92 ), .B (n_868), .C (n_1923), .Y + (n_1491)); + NOR2X1 g39241(.A (n_2707), .B (n_1488), .Y (n_1490)); + NOR2X1 g39247(.A (n_2765), .B (n_1488), .Y (n_1489)); + NAND3X1 g39270(.A (\u3_mem[0]_91 ), .B (n_814), .C (n_1924), .Y + (n_1487)); + NAND3X1 g39333(.A (n_698), .B (\u2_cnt[5] ), .C (n_456), .Y (n_1486)); + NOR2X1 g39384(.A (n_1484), .B (n_760), .Y (n_1485)); + NOR2X1 g39410(.A (n_2818), .B (n_1488), .Y (n_1483)); + INVX1 g42984(.A (n_1481), .Y (n_11059)); + NOR2X1 g39435(.A (n_2712), .B (n_1488), .Y (n_1480)); + NOR2X1 g39490(.A (n_2792), .B (n_1488), .Y (n_1479)); + INVX1 g42731(.A (n_1473), .Y (n_2343)); + NOR2X1 g39645(.A (n_2804), .B (n_1488), .Y (n_1478)); + NOR2X1 g39692(.A (n_2772), .B (n_1488), .Y (n_1477)); + NOR2X1 g39702(.A (n_2763), .B (n_1488), .Y (n_1476)); + INVX1 g41935(.A (n_8182), .Y (n_11036)); + INVX1 g41938(.A (n_8182), .Y (n_11033)); + NOR2X1 g39809(.A (n_2864), .B (n_1488), .Y (n_1472)); + NOR2X1 g39813(.A (n_2686), .B (n_1488), .Y (n_1470)); + NAND3X1 g39825(.A (\u2_cnt[3] ), .B (n_701), .C (n_456), .Y (n_1469)); + NOR2X1 g39840(.A (n_2748), .B (n_1488), .Y (n_1466)); + NOR2X1 g39853(.A (n_2755), .B (n_1488), .Y (n_1464)); + NOR2X1 g39897(.A (n_2684), .B (n_1488), .Y (n_1462)); + OR2X1 g39171(.A (n_12145), .B (n_6824), .Y (n_1460)); + NOR2X1 g39912(.A (n_2681), .B (n_1488), .Y (n_1458)); + NOR2X1 g39957(.A (n_2735), .B (n_1488), .Y (n_1457)); + NAND2X1 g40019(.A (n_4502), .B (n_4499), .Y (n_1454)); + BUFX3 g41432(.A (n_12743), .Y (n_3556)); + NAND2X1 g40224(.A (n_4507), .B (n_4439), .Y (n_1450)); + OR2X1 g40331(.A (n_910), .B (n_1484), .Y (n_1449)); + AOI22X1 g40382(.A0 (n_494), .A1 (n_1446), .B0 (\u8_rp[3] ), .B1 + (\u8_wp[2] ), .Y (n_1447)); + AOI22X1 g40383(.A0 (n_457), .A1 (n_1443), .B0 (\u7_rp[3] ), .B1 + (\u7_wp[2] ), .Y (n_1444)); + AOI21X1 g40384(.A0 (\u26_ps_cnt[1] ), .A1 (n_529), .B0 (n_819), .Y + (n_1441)); + AOI21X1 g40393(.A0 (\u11_rp[0] ), .A1 (\u11_wp[1] ), .B0 (n_916), .Y + (n_5442)); + INVX1 g40405(.A (n_1231), .Y (n_2575)); + XOR2X1 g40437(.A (\u11_rp[1] ), .B (n_853), .Y (n_1438)); + XOR2X1 g40438(.A (n_1198), .B (n_2567), .Y (n_3992)); + NOR2X1 g39067(.A (n_2716), .B (n_1488), .Y (n_1435)); + INVX2 g40700(.A (n_1434), .Y (n_3441)); + INVX1 g40701(.A (n_1434), .Y (n_3334)); + INVX8 g40754(.A (n_1432), .Y (n_3316)); + INVX2 g40872(.A (n_1430), .Y (n_2705)); + INVX1 g40873(.A (n_1430), .Y (n_2713)); + INVX1 g40875(.A (n_1430), .Y (n_2836)); + INVX1 g40877(.A (n_1430), .Y (n_2721)); + INVX1 g40879(.A (n_1430), .Y (n_2751)); + INVX2 g40884(.A (n_1429), .Y (n_3207)); + INVX2 g40887(.A (n_1429), .Y (n_3330)); + INVX1 g39054(.A (n_3985), .Y (n_1910)); + INVX2 g40944(.A (n_12664), .Y (n_7077)); + INVX2 g40954(.A (n_1427), .Y (n_2784)); + INVX1 g40956(.A (n_1427), .Y (n_2827)); + NOR2X1 g40964(.A (n_1924), .B (n_1424), .Y (n_1425)); + NOR2X1 g39043(.A (n_2741), .B (n_1488), .Y (n_1423)); + NOR2X1 g40979(.A (n_1921), .B (n_1421), .Y (n_1422)); + NOR2X1 g40982(.A (n_1923), .B (n_1419), .Y (n_1420)); + NOR2X1 g40983(.A (n_11585), .B (n_1417), .Y (n_1418)); + INVX2 g41006(.A (n_1416), .Y (n_2775)); + NAND3X1 g39038(.A (\u6_mem[0]_91 ), .B (n_888), .C (n_11585), .Y + (n_1415)); + NOR2X1 g39866(.A (n_2794), .B (n_1488), .Y (n_1414)); + INVX1 g40958(.A (n_1427), .Y (n_2770)); + INVX1 g41043(.A (n_1412), .Y (n_3257)); + INVX2 g41044(.A (n_1412), .Y (n_3239)); + INVX4 g41052(.A (n_1412), .Y (n_3236)); + INVX2 g41139(.A (n_1411), .Y (n_3423)); + INVX2 g41158(.A (n_1409), .Y (n_2736)); + CLKBUFX3 g41183(.A (n_1406), .Y (n_3935)); + INVX1 g41232(.A (n_2463), .Y (n_1404)); + NAND2X1 g41321(.A (n_5225), .B (wb_addr_i[4]), .Y (n_3431)); + INVX1 g41376(.A (n_12682), .Y (n_3255)); + INVX4 g41380(.A (n_1397), .Y (n_3259)); + NAND2X1 g38958(.A (\u7_mem[3]_137 ), .B (n_1546), .Y (n_1395)); + NAND2X1 g38978(.A (\u7_mem[3]_150 ), .B (n_1546), .Y (n_1386)); + NAND2X1 g38976(.A (\u7_mem[3]_132 ), .B (n_1538), .Y (n_1383)); + NAND2X1 g38970(.A (\u3_mem[3]_123 ), .B (n_1517), .Y (n_1378)); + INVX1 g41547(.A (n_2419), .Y (n_1377)); + NAND2X1 g38964(.A (\u7_mem[3]_138 ), .B (n_1546), .Y (n_1376)); + INVX8 g41566(.A (n_1448), .Y (n_3089)); + OR2X1 g41577(.A (n_1374), .B (n_5839), .Y (n_1375)); + INVX8 g41591(.A (n_1509), .Y (n_3332)); + OR2X1 g41598(.A (n_1372), .B (n_2485), .Y (n_1373)); + INVX8 g41609(.A (n_1475), .Y (n_3486)); + INVX4 g41622(.A (n_1205), .Y (n_3543)); + INVX1 g41647(.A (n_2468), .Y (n_1367)); + NAND2X1 g38938(.A (\u7_mem[3]_122 ), .B (n_1538), .Y (n_1362)); + INVX4 g41739(.A (n_1360), .Y (n_4560)); + OR2X1 g41776(.A (n_1355), .B (n_5827), .Y (n_1356)); + NAND2X1 g38924(.A (\u7_mem[3] ), .B (n_1538), .Y (n_1354)); + INVX1 g41932(.A (n_8182), .Y (n_11128)); + INVX1 g41933(.A (n_8182), .Y (n_11030)); + INVX1 g41934(.A (n_8182), .Y (n_11025)); + NAND2X1 g38920(.A (\u3_mem[3]_137 ), .B (n_1517), .Y (n_1348)); + NAND2X1 g38918(.A (\u7_mem[3]_142 ), .B (n_1546), .Y (n_1347)); + NAND2X1 g38907(.A (n_685), .B (n_908), .Y (n_4633)); + NAND2X1 g38896(.A (n_393), .B (n_831), .Y (n_3944)); + INVX2 g42978(.A (n_1481), .Y (n_11144)); + NAND2X1 g38887(.A (\u5_mem[3]_131 ), .B (n_1543), .Y (n_1340)); + NAND2X1 g38872(.A (\u7_mem[3]_143 ), .B (n_1546), .Y (n_1339)); + NAND2X1 g38863(.A (\u5_mem[3]_125 ), .B (n_1543), .Y (n_1338)); + NAND2X1 g38865(.A (\u5_mem[3]_126 ), .B (n_1543), .Y (n_1337)); + NAND2X1 g38855(.A (\u5_mem[3]_138 ), .B (n_1543), .Y (n_1336)); + NAND2X1 g38860(.A (\u5_mem[3]_123 ), .B (n_1543), .Y (n_1335)); + NAND2X1 g38853(.A (\u5_mem[3]_136 ), .B (n_1543), .Y (n_1333)); + INVX1 g41047(.A (n_1412), .Y (n_3209)); + NAND2X1 g38848(.A (\u7_mem[3]_147 ), .B (n_1546), .Y (n_1328)); + NAND2X1 g38842(.A (\u5_mem[3]_127 ), .B (n_1543), .Y (n_1327)); + NAND2X1 g38845(.A (\u5_mem[3]_130 ), .B (n_1543), .Y (n_1326)); + NAND2X1 g38836(.A (\u5_mem[3]_133 ), .B (n_1543), .Y (n_1325)); + NAND2X1 g38840(.A (\u5_mem[3] ), .B (n_1543), .Y (n_1324)); + NAND2X1 g38834(.A (\u3_mem[3]_128 ), .B (n_1517), .Y (n_1323)); + NOR2X1 g39882(.A (n_2786), .B (n_1488), .Y (n_1322)); + INVX4 g41531(.A (n_1320), .Y (n_3252)); + NAND3X1 g39325(.A (\u5_mem[0]_92 ), .B (n_886), .C (n_1033), .Y + (n_1319)); + AOI22X1 g37808(.A0 (n_2558), .A1 (n_6331), .B0 (n_6565), .B1 + (n_1316), .Y (n_1317)); + INVX1 g40955(.A (n_1427), .Y (n_2773)); + INVX2 g41494(.A (n_1072), .Y (n_1854)); + INVX8 g41473(.A (n_1388), .Y (n_3117)); + CLKBUFX3 g41430(.A (n_12743), .Y (n_3546)); + INVX8 g41384(.A (n_1396), .Y (n_6594)); + INVX1 g41368(.A (n_1064), .Y (n_1851)); + INVX2 g41351(.A (n_1134), .Y (n_6908)); + OR2X1 g41320(.A (n_11563), .B (n_1308), .Y (n_1309)); + INVX2 g41312(.A (n_1059), .Y (n_1846)); + INVX2 g41202(.A (n_12172), .Y (n_1845)); + OR2X1 g41212(.A (n_1301), .B (n_5831), .Y (n_1302)); + NAND2X1 g41210(.A (n_5225), .B (n_1300), .Y (n_7019)); + INVX1 g41189(.A (n_1406), .Y (n_1899)); + INVX2 g41175(.A (n_1299), .Y (n_3415)); + INVX1 g41159(.A (n_1409), .Y (n_2749)); + INVX1 g41161(.A (n_1409), .Y (n_2761)); + INVX1 g41153(.A (n_1409), .Y (n_2689)); + INVX1 g41155(.A (n_1409), .Y (n_2696)); + INVX2 g41138(.A (n_1411), .Y (n_3474)); + CLKBUFX3 g41110(.A (n_11851), .Y (n_3522)); + INVX4 g41103(.A (n_1297), .Y (n_7187)); + INVX1 g40959(.A (n_1427), .Y (n_2759)); + AOI22X1 g37890(.A0 (n_2558), .A1 (n_6342), .B0 (n_6578), .B1 + (n_1316), .Y (n_1295)); + XOR2X1 g37417(.A (\u8_wp[1] ), .B (n_12278), .Y (n_1294)); + NAND2X1 g36304(.A (n_1291), .B (n_1290), .Y (n_1292)); + NAND2X1 g37549(.A (n_811), .B (in_slt_742), .Y (n_1289)); + CLKBUFX1 g43031(.A (n_1873), .Y (n_1875)); + NAND3X1 g37527(.A (n_1132), .B (wb_addr_i[6]), .C (n_593), .Y + (n_1779)); + AND2X1 g37513(.A (n_1262), .B (n_1284), .Y (n_1285)); + NOR2X1 g39537(.A (n_2767), .B (n_1488), .Y (n_1283)); + INVX1 g42981(.A (n_1481), .Y (n_11069)); + INVX1 g41005(.A (n_1416), .Y (n_2788)); + AND2X1 g37056(.A (n_1553), .B (n_1281), .Y (n_1282)); + INVX1 g41003(.A (n_1416), .Y (n_2742)); + AND2X1 g36779(.A (n_1277), .B (\u2_res_cnt[2] ), .Y (n_1278)); + AND2X1 g36780(.A (n_1553), .B (n_1819), .Y (n_1276)); + INVX1 g41001(.A (n_1416), .Y (n_2832)); + DFFX1 u12_we2_reg(.CK (clk_i), .D (n_870), .Q (), .QN (u12_we2)); + INVX1 g40998(.A (n_1416), .Y (n_2780)); + NAND2X1 g38814(.A (\u7_mem[3]_123 ), .B (n_1538), .Y (n_1275)); + NAND3X1 g36889(.A (n_576), .B (n_442), .C (n_726), .Y (n_1274)); + INVX8 g41698(.A (n_1363), .Y (n_3453)); + NOR2X1 g39510(.A (n_3008), .B (n_1488), .Y (n_1273)); + NAND3X1 g37186(.A (n_1824), .B (n_684), .C (\u2_cnt[3] ), .Y + (n_4076)); + NOR2X1 g39492(.A (n_2720), .B (n_1488), .Y (n_1272)); + INVX1 g39480(.A (n_1271), .Y (n_4729)); + XOR2X1 g37418(.A (n_6838), .B (n_763), .Y (n_1269)); + XOR2X1 g37421(.A (n_7048), .B (n_762), .Y (n_1267)); + XOR2X1 g37422(.A (n_6841), .B (n_754), .Y (n_1265)); + NAND2X1 g37485(.A (n_1262), .B (n_1006), .Y (n_1263)); + OAI21X1 g37204(.A0 (\u9_rp[1] ), .A1 (\u9_wp[2] ), .B0 (n_984), .Y + (n_2624)); + NAND2X1 g37547(.A (n_843), .B (in_slt_742), .Y (n_1260)); + NAND2X1 g37548(.A (n_974), .B (in_slt_742), .Y (n_1259)); + NAND2X1 g39572(.A (n_6042), .B (n_1300), .Y (n_2284)); + INVX1 g37588(.A (n_1815), .Y (n_1258)); + AOI21X1 g37591(.A0 (n_5225), .A1 (n_675), .B0 (wb_addr_i[6]), .Y + (n_2608)); + AOI22X1 g40381(.A0 (n_496), .A1 (n_1255), .B0 (\u6_rp[3] ), .B1 + (\u6_wp[2] ), .Y (n_1256)); + NAND4X1 g37598(.A (n_1253), .B (n_1227), .C (\u2_cnt[4] ), .D + (\u2_cnt[5] ), .Y (n_2602)); + AOI22X1 g37664(.A0 (n_2558), .A1 (n_1251), .B0 (n_5506), .B1 + (n_1316), .Y (n_1252)); + AOI22X1 g37699(.A0 (n_2558), .A1 (n_5955), .B0 (n_6010), .B1 + (n_1316), .Y (n_1249)); + AOI22X1 g37705(.A0 (n_2558), .A1 (n_337), .B0 (n_5575), .B1 (n_1316), + .Y (n_1248)); + AOI22X1 g37712(.A0 (n_2558), .A1 (n_1246), .B0 (n_5520), .B1 + (n_1316), .Y (n_1247)); + AOI22X1 g37715(.A0 (n_2558), .A1 (n_1244), .B0 (n_5363), .B1 + (n_1316), .Y (n_1245)); + AOI22X1 g37723(.A0 (n_2558), .A1 (n_1242), .B0 (n_5516), .B1 + (n_1316), .Y (n_1243)); + AOI22X1 g37742(.A0 (n_2558), .A1 (n_1240), .B0 (n_5357), .B1 + (n_1316), .Y (n_1241)); + AOI22X1 g37751(.A0 (n_2558), .A1 (n_1238), .B0 (n_5352), .B1 + (n_1316), .Y (n_1239)); + AOI22X1 g37784(.A0 (n_2558), .A1 (n_6339), .B0 (n_6575), .B1 + (n_1316), .Y (n_1237)); + AOI22X1 g37791(.A0 (n_2558), .A1 (n_6337), .B0 (n_6572), .B1 + (n_1316), .Y (n_1236)); + AOI22X1 g37816(.A0 (n_2558), .A1 (n_6333), .B0 (n_6562), .B1 + (n_1316), .Y (n_1235)); + ADDHX1 g36200(.A (n_512), .B (n_853), .CO (n_1233), .S (n_1234)); + NAND3X1 g40406(.A (n_594), .B (wb_addr_i[3]), .C (wb_addr_i[4]), .Y + (n_1231)); + INVX2 g39672(.A (n_1216), .Y (n_5277)); + INVX1 g40820(.A (n_6995), .Y (n_1229)); + INVX4 g40755(.A (n_12752), .Y (n_1432)); + DFFX1 u2_bit_clk_r1_reg(.CK (clk_i), .D (n_719), .Q (), .QN + (u2_bit_clk_r1)); + INVX1 g40702(.A (n_1178), .Y (n_1434)); + AND2X1 g38943(.A (n_1227), .B (n_866), .Y (n_1519)); + NAND2X1 g38953(.A (n_1253), .B (\u2_cnt[2] ), .Y (n_1829)); + AND2X1 g38955(.A (n_701), .B (n_3995), .Y (n_4079)); + INVX2 g40876(.A (n_1226), .Y (n_1430)); + AND2X1 g39057(.A (n_1225), .B (wb_addr_i[4]), .Y (n_3985)); + NOR2X1 g40249(.A (n_995), .B (n_932), .Y (n_1224)); + NAND2X1 g39160(.A (n_6044), .B (n_1300), .Y (n_1453)); + NOR2X1 g39248(.A (\u9_mem[2]_106 ), .B (n_1221), .Y (n_1222)); + INVX4 g41347(.A (n_1134), .Y (n_5371)); + INVX2 g41381(.A (n_12678), .Y (n_1397)); + NOR2X1 g39390(.A (\u9_mem[2] ), .B (n_1221), .Y (n_1220)); + NAND2X1 g39483(.A (n_1225), .B (n_1300), .Y (n_1271)); + INVX2 g42737(.A (n_991), .Y (n_1473)); + NOR2X1 g39677(.A (\u11_mem[2] ), .B (n_1214), .Y (n_1215)); + INVX1 g41939(.A (n_12585), .Y (n_8182)); + NAND3X1 g39719(.A (n_2596), .B (n_1212), .C (n_711), .Y (n_1213)); + INVX8 g41754(.A (n_1103), .Y (n_3765)); + AND2X1 g39821(.A (\u2_cnt[4] ), .B (n_3995), .Y (n_1784)); + NOR2X1 g39867(.A (\u11_mem[2]_100 ), .B (n_1214), .Y (n_1211)); + INVX4 g41594(.A (n_5059), .Y (n_1509)); + INVX1 g40688(.A (n_1180), .Y (n_2057)); + INVX4 g41571(.A (n_5138), .Y (n_1448)); + NOR2X1 g40046(.A (n_969), .B (n_930), .Y (n_1209)); + INVX4 g41476(.A (n_4996), .Y (n_1388)); + INVX1 g41421(.A (n_1208), .Y (n_1391)); + NOR2X1 g41619(.A (n_1206), .B (n_5420), .Y (n_1207)); + XOR2X1 g40446(.A (n_1203), .B (n_4074), .Y (n_1204)); + MX2X1 g40436(.A (crac_din_692), .B (in_slt_831), .S0 (n_1036), .Y + (n_1202)); + INVX1 g41213(.A (n_6042), .Y (n_1200)); + INVX2 g41141(.A (n_1149), .Y (n_1411)); + NOR2X1 g40351(.A (n_832), .B (n_931), .Y (n_1199)); + XOR2X1 g40379(.A (n_798), .B (n_1033), .Y (n_6047)); + XOR2X1 g40391(.A (n_1198), .B (\u8_wp[0] ), .Y (n_5622)); + MX2X1 g40421(.A (crac_din_696), .B (in_slt_835), .S0 (n_1036), .Y + (n_1197)); + MX2X1 g40423(.A (crac_din_697), .B (in_slt_836), .S0 (n_1036), .Y + (n_1196)); + MX2X1 g40427(.A (crac_din_693), .B (in_slt_832), .S0 (n_1036), .Y + (n_1194)); + MX2X1 g40431(.A (crac_din_703), .B (in_slt_842), .S0 (n_1036), .Y + (n_1193)); + MX2X1 g40432(.A (crac_din_704), .B (in_slt_843), .S0 (n_1036), .Y + (n_1192)); + INVX1 g40767(.A (n_1174), .Y (n_2059)); + INVX2 g41021(.A (n_7080), .Y (n_6773)); + XOR2X1 g40444(.A (n_9641), .B (\u10_wp[1] ), .Y (n_1189)); + INVX1 g40761(.A (n_1174), .Y (n_2043)); + XOR2X1 g40447(.A (\u9_rp[1] ), .B (\u9_wp[2] ), .Y (n_1188)); + NAND2X1 g39106(.A (n_6044), .B (wb_addr_i[4]), .Y (n_1185)); + INVX1 g42327(.A (n_1921), .Y (n_1184)); + INVX4 g40686(.A (n_1180), .Y (n_2067)); + INVX1 g40687(.A (n_1180), .Y (n_2008)); + INVX1 g40689(.A (n_1180), .Y (n_2118)); + CLKBUFX3 g40699(.A (n_1178), .Y (n_2362)); + CLKBUFX3 g40705(.A (n_1178), .Y (n_2366)); + INVX1 g40712(.A (n_1176), .Y (n_2218)); + INVX1 g40713(.A (n_1176), .Y (n_2154)); + INVX1 g40717(.A (n_1176), .Y (n_2135)); + INVX1 g40718(.A (n_1176), .Y (n_2081)); + INVX1 g40719(.A (n_1176), .Y (n_2093)); + INVX2 g40730(.A (n_2364), .Y (n_2530)); + INVX1 g40759(.A (n_1174), .Y (n_2216)); + INVX1 g40760(.A (n_1174), .Y (n_2020)); + INVX1 g40764(.A (n_1174), .Y (n_2025)); + INVX1 g40766(.A (n_1174), .Y (n_2038)); + INVX1 g40775(.A (n_1172), .Y (n_2120)); + INVX1 g40779(.A (n_1172), .Y (n_2083)); + INVX1 g40780(.A (n_1172), .Y (n_2096)); + INVX8 g40786(.A (n_1129), .Y (n_1985)); + INVX1 g40836(.A (n_1167), .Y (n_2054)); + INVX1 g40840(.A (n_1167), .Y (n_2041)); + NAND2X1 g40894(.A (n_403), .B (n_5420), .Y (n_1164)); + INVX2 g40897(.A (n_1232), .Y (n_2534)); + INVX1 g40778(.A (n_1172), .Y (n_2071)); + INVX8 g40925(.A (n_1162), .Y (n_5341)); + NAND2X1 g40939(.A (n_121), .B (n_4074), .Y (n_1160)); + INVX1 g40777(.A (n_1172), .Y (n_2085)); + BUFX3 g40951(.A (n_1082), .Y (n_5048)); + INVX8 g40965(.A (n_1158), .Y (n_6898)); + INVX2 g40985(.A (n_6201), .Y (n_7088)); + NAND2X1 g40989(.A (n_487), .B (\u11_wp[1] ), .Y (n_1157)); + INVX4 g40992(.A (n_1156), .Y (n_2344)); + BUFX3 g40996(.A (n_1016), .Y (n_5157)); + INVX2 g41009(.A (n_928), .Y (n_6259)); + INVX1 g41104(.A (n_834), .Y (n_1297)); + CLKBUFX3 g41134(.A (n_1149), .Y (n_2285)); + INVX4 g41148(.A (n_1148), .Y (n_2325)); + BUFX3 g41151(.A (n_1147), .Y (n_5112)); + INVX2 g41162(.A (n_1147), .Y (n_1409)); + CLKBUFX1 g41178(.A (n_1049), .Y (n_4624)); + INVX4 g41193(.A (n_970), .Y (n_1406)); + INVX2 g41197(.A (n_837), .Y (n_6816)); + OR2X1 g41216(.A (n_7017), .B (n_12585), .Y (n_1146)); + INVX4 g41550(.A (n_12621), .Y (n_2419)); + INVX8 g41252(.A (n_1143), .Y (n_2368)); + CLKBUFX1 g41254(.A (n_1142), .Y (n_4616)); + NAND2X1 g41258(.A (n_684), .B (n_687), .Y (n_2377)); + INVX1 g40787(.A (n_1129), .Y (n_2137)); + INVX8 g41278(.A (n_1055), .Y (n_3720)); + INVX2 g41285(.A (n_12535), .Y (n_7214)); + NOR2X1 g41322(.A (n_688), .B (n_701), .Y (n_1138)); + INVX8 g41334(.A (n_1060), .Y (n_3826)); + INVX1 g38985(.A (n_1132), .Y (n_1133)); + INVX1 g41399(.A (n_9717), .Y (n_7212)); + INVX1 g41501(.A (n_1127), .Y (n_1381)); + OR2X1 g41505(.A (n_11597), .B (n_1124), .Y (n_1126)); + INVX8 g41513(.A (n_1076), .Y (n_3807)); + INVX1 g41520(.A (n_1122), .Y (n_1379)); + CLKBUFX3 g41533(.A (n_1084), .Y (n_2491)); + NAND2X1 g41537(.A (\u11_rp[1] ), .B (n_853), .Y (n_1121)); + INVX4 g41549(.A (n_12621), .Y (n_2465)); + BUFX3 g41560(.A (n_5138), .Y (n_5133)); + OR2X1 g41580(.A (n_11762), .B (n_1119), .Y (n_1120)); + INVX4 g41610(.A (n_5102), .Y (n_1475)); + NOR2X1 g38951(.A (n_1114), .B (\u2_cnt[2] ), .Y (n_2592)); + INVX1 g41644(.A (n_12603), .Y (n_7267)); + INVX8 g41664(.A (n_1108), .Y (n_3622)); + INVX1 g41687(.A (n_1107), .Y (n_1364)); + CLKBUFX3 g41691(.A (n_1107), .Y (n_2302)); + INVX1 g40691(.A (n_1180), .Y (n_2045)); + OR2X1 g38932(.A (n_1484), .B (n_680), .Y (n_1104)); + INVX1 g40791(.A (n_1129), .Y (n_2182)); + OR2X1 g41775(.A (n_1100), .B (n_5825), .Y (n_1101)); + INVX1 g42152(.A (n_1924), .Y (n_1096)); + INVX1 g40839(.A (n_1167), .Y (n_2171)); + INVX1 g40837(.A (n_1167), .Y (n_2133)); + INVX8 g40800(.A (n_1090), .Y (n_6502)); + AND2X1 g38822(.A (n_674), .B (n_1372), .Y (n_1087)); + INVX1 g40762(.A (n_1174), .Y (n_2103)); + INVX2 g41538(.A (n_9719), .Y (n_7256)); + XOR2X1 g38402(.A (\u9_rp[2] ), .B (n_737), .Y (n_1085)); + INVX1 g40842(.A (n_1167), .Y (n_2006)); + NOR2X1 g40845(.A (n_8550), .B (n_503), .Y (n_9699)); + INVX1 g41532(.A (n_1084), .Y (n_1320)); + MX2X1 g40434(.A (crac_din_706), .B (in_slt_845), .S0 (n_1036), .Y + (n_1083)); + CLKBUFX3 g41529(.A (n_1084), .Y (n_2330)); + NOR2X1 g35454(.A (n_844), .B (n_632), .Y (n_7379)); + NOR2X1 g35455(.A (n_829), .B (n_631), .Y (n_7378)); + NOR2X1 g35456(.A (n_807), .B (n_630), .Y (n_7434)); + BUFX3 g40952(.A (n_1082), .Y (n_5037)); + INVX2 g40957(.A (n_1082), .Y (n_1427)); + XOR2X1 g38093(.A (\u11_rp[2] ), .B (n_736), .Y (n_1080)); + INVX4 g40917(.A (n_1163), .Y (n_5312)); + INVX2 g40888(.A (n_12614), .Y (n_1429)); + INVX8 g41648(.A (n_1111), .Y (n_2468)); + INVX1 g40863(.A (n_1019), .Y (n_2099)); + MX2X1 g40430(.A (crac_din), .B (in_slt_830), .S0 (n_1036), .Y + (n_1074)); + BUFX3 g41486(.A (n_1072), .Y (n_5656)); + INVX1 g41483(.A (n_1071), .Y (n_1384)); + BUFX3 g41466(.A (n_4996), .Y (n_5000)); + INVX1 g41396(.A (n_9717), .Y (n_7120)); + INVX1 g41392(.A (n_1546), .Y (n_1068)); + INVX1 g41389(.A (n_1067), .Y (n_1396)); + CLKBUFX1 g41357(.A (n_1064), .Y (n_5645)); + INVX1 g41353(.A (n_1134), .Y (n_1063)); + BUFX3 g41304(.A (n_1059), .Y (n_5480)); + NOR2X1 g41240(.A (\u9_rp[0] ), .B (n_4074), .Y (n_1054)); + INVX8 g41231(.A (n_1052), .Y (n_2463)); + NOR2X1 g39966(.A (n_704), .B (\u2_to_cnt[1] ), .Y (n_1051)); + INVX1 g41177(.A (n_1049), .Y (n_1299)); + BUFX3 g41152(.A (n_1147), .Y (n_5019)); + MX2X1 g40429(.A (crac_din_694), .B (in_slt_833), .S0 (n_1036), .Y + (n_1047)); + INVX4 g41129(.A (n_1045), .Y (n_4783)); + INVX4 g41085(.A (n_1042), .Y (n_6475)); + INVX1 g41741(.A (n_1040), .Y (n_1360)); + INVX2 g41064(.A (n_1038), .Y (n_7063)); + XOR2X1 g38181(.A (\u10_rp[2] ), .B (n_638), .Y (n_1039)); + INVX4 g41058(.A (n_1153), .Y (n_4097)); + MX2X1 g40428(.A (crac_din_699), .B (in_slt_838), .S0 (n_1036), .Y + (n_1037)); + MX2X1 g40426(.A (crac_din_695), .B (in_slt_834), .S0 (n_1036), .Y + (n_1034)); + NOR2X1 g39385(.A (n_713), .B (\u26_cnt[0] ), .Y (n_1777)); + INVX4 g41045(.A (n_1035), .Y (n_1412)); + XOR2X1 g40443(.A (n_1033), .B (n_3559), .Y (n_2594)); + MX2X1 g40435(.A (crac_din_701), .B (in_slt_840), .S0 (n_1036), .Y + (n_1031)); + MX2X1 g40433(.A (crac_din_705), .B (in_slt_844), .S0 (n_1036), .Y + (n_1030)); + MX2X1 g40425(.A (crac_din_702), .B (in_slt_841), .S0 (n_1036), .Y + (n_1029)); + BUFX3 g41584(.A (n_5059), .Y (n_5100)); + MX2X1 g40424(.A (crac_din_700), .B (in_slt_839), .S0 (n_1036), .Y + (n_1028)); + INVX8 g41040(.A (n_1027), .Y (n_2470)); + CLKBUFX1 g41732(.A (n_1040), .Y (n_2513)); + XOR2X1 g38028(.A (\u11_wp[3] ), .B (n_695), .Y (n_1025)); + BUFX3 g40871(.A (n_1226), .Y (n_5069)); + NAND2X1 g37543(.A (n_553), .B (in_slt_742), .Y (n_1023)); + MX2X1 g40422(.A (crac_din_698), .B (in_slt_837), .S0 (n_1036), .Y + (n_1022)); + NAND2X1 g37539(.A (n_635), .B (in_slt_742), .Y (n_1021)); + INVX8 g41717(.A (n_1106), .Y (n_3632)); + INVX1 g42990(.A (n_5825), .Y (n_1481)); + INVX4 g40867(.A (n_1019), .Y (n_2477)); + INVX2 g41007(.A (n_1016), .Y (n_1416)); + BUFX3 g40870(.A (n_1226), .Y (n_5118)); + INVX1 g40862(.A (n_1019), .Y (n_2169)); + INVX1 g42390(.A (n_2485), .Y (n_9833)); + BUFX3 g41600(.A (n_5102), .Y (n_5106)); + BUFX3 g40997(.A (n_1016), .Y (n_5148)); + NOR2X1 g37042(.A (\u26_ps_cnt[3] ), .B (n_818), .Y (n_1014)); + DFFX1 \u1_sr_reg[0] (.CK (bit_clk_pad_i), .D (u1_sdata_in_r), .Q + (u1_sr), .QN ()); + INVX4 g40942(.A (n_1159), .Y (n_3911)); + INVX1 g40714(.A (n_1176), .Y (n_2189)); + INVX1 g42507(.A (n_1923), .Y (n_1012)); + NAND2X1 g37540(.A (n_620), .B (in_slt_742), .Y (n_1010)); + NAND2X1 g37541(.A (n_531), .B (in_slt_742), .Y (n_1009)); + NAND2X1 g37544(.A (n_539), .B (in_slt_742), .Y (n_1008)); + NAND2X1 g37545(.A (n_554), .B (in_slt_742), .Y (n_1007)); + INVX1 g40720(.A (n_1176), .Y (n_2144)); + NAND3X1 g37590(.A (n_581), .B (n_1006), .C (u12_re1), .Y (n_1815)); + NOR2X1 g39427(.A (\u11_mem[2]_98 ), .B (n_1214), .Y (n_1005)); + BUFX3 g41696(.A (n_4961), .Y (n_5145)); + INVX4 g40726(.A (n_940), .Y (n_2364)); + INVX4 g41706(.A (n_4961), .Y (n_1363)); + AOI21X1 g40386(.A0 (\u4_rp[3] ), .A1 (\u4_wp[2] ), .B0 (n_441), .Y + (n_1001)); + INVX2 g42391(.A (n_997), .Y (n_2485)); + BUFX3 g40711(.A (n_941), .Y (n_4504)); + INVX2 g40706(.A (n_714), .Y (n_1178)); + AND2X1 g38909(.A (n_869), .B (wb_cyc_i), .Y (n_1284)); + AND2X1 g38986(.A (n_996), .B (n_1300), .Y (n_1132)); + INVX2 g40763(.A (n_938), .Y (n_1174)); + CLKBUFX1 g40807(.A (n_995), .Y (n_5405)); + INVX2 g42860(.A (n_12634), .Y (n_6118)); + INVX1 g42726(.A (n_991), .Y (n_5831)); + INVX2 g40802(.A (n_995), .Y (n_1090)); + NAND2X1 g41778(.A (\u9_rp[1] ), .B (\u9_wp[2] ), .Y (n_984)); + NOR2X1 g41653(.A (\u13_ints_r[0] ), .B (n_1036), .Y (n_980)); + NAND2X1 g39673(.A (n_996), .B (wb_addr_i[4]), .Y (n_1216)); + INVX1 g41617(.A (n_977), .Y (n_1116)); + INVX1 g41521(.A (n_976), .Y (n_1122)); + NOR2X1 g41372(.A (n_8550), .B (oc2_cfg_987), .Y (n_9611)); + AND2X1 g41354(.A (\u9_wp[1] ), .B (\u9_wp[2] ), .Y (n_1134)); + INVX2 g41625(.A (n_909), .Y (n_1205)); + AOI21X1 g40245(.A0 (ic1_cfg_1034), .A1 (n_197), .B0 + (u14_u7_full_empty_r), .Y (n_974)); + CLKBUFX3 g41253(.A (n_840), .Y (n_1143)); + NOR2X1 g41209(.A (n_8565), .B (n_942), .Y (n_9768)); + NAND2X1 g41194(.A (ic0_cfg_1026), .B (n_836), .Y (n_970)); + NAND2X1 g41150(.A (n_431), .B (n_4706), .Y (n_1148)); + CLKBUFX1 g41132(.A (n_969), .Y (n_5730)); + NOR2X1 g41145(.A (n_4703), .B (n_872), .Y (n_8847)); + AOI21X1 g40388(.A0 (\u5_rp[3] ), .A1 (\u5_wp[2] ), .B0 (n_412), .Y + (n_968)); + INVX2 g41041(.A (n_821), .Y (n_1027)); + NAND2X1 g41018(.A (n_8197), .B (n_804), .Y (n_9585)); + INVX2 g40486(.A (wb_din_689), .Y (n_3008)); + INVX2 g40546(.A (wb_din_690), .Y (n_2864)); + INVX4 g40908(.A (n_1000), .Y (n_1643)); + BUFX3 g40771(.A (n_945), .Y (n_4519)); + BUFX3 g40684(.A (n_933), .Y (n_4502)); + NAND2X2 g41008(.A (n_1424), .B (n_626), .Y (n_1016)); + NAND2X1 g40708(.A (n_8565), .B (n_942), .Y (n_9647)); + BUFX3 g40710(.A (n_941), .Y (n_4544)); + INVX2 g40721(.A (n_941), .Y (n_1176)); + CLKBUFX1 g40725(.A (n_940), .Y (n_1839)); + BUFX3 g40757(.A (n_938), .Y (n_4540)); + BUFX3 g40783(.A (n_937), .Y (n_4499)); + NAND2X1 g40995(.A (n_8526), .B (n_924), .Y (n_9591)); + INVX2 g40794(.A (n_937), .Y (n_1129)); + NAND2X1 g40809(.A (n_8188), .B (n_921), .Y (n_9587)); + NAND2X1 g40994(.A (n_434), .B (n_4690), .Y (n_1156)); + NOR2X1 g40830(.A (n_4734), .B (n_936), .Y (n_8843)); + NAND2X1 g40831(.A (n_4734), .B (n_936), .Y (n_7524)); + BUFX3 g40832(.A (n_867), .Y (n_4378)); + INVX1 g40868(.A (n_935), .Y (n_1019)); + CLKBUFX2 g40922(.A (n_932), .Y (n_5409)); + BUFX3 g40770(.A (n_945), .Y (n_4533)); + CLKBUFX1 g40977(.A (n_930), .Y (n_5732)); + NAND2X1 g40984(.A (n_145), .B (n_765), .Y (n_929)); + NAND2X1 g41010(.A (n_590), .B (oc5_cfg_1016), .Y (n_928)); + INVX4 g41011(.A (n_1221), .Y (n_1835)); + NAND2X1 g41059(.A (n_4683), .B (n_667), .Y (n_1153)); + NOR2X1 g40950(.A (n_8526), .B (n_924), .Y (n_9701)); + NOR2X1 g41067(.A (n_5588), .B (n_802), .Y (n_9444)); + NAND2X1 g40943(.A (n_4738), .B (n_625), .Y (n_1159)); + NAND2X1 g41077(.A (n_3559), .B (n_771), .Y (n_923)); + BUFX3 g40784(.A (n_937), .Y (n_4491)); + NAND2X1 g41099(.A (n_8550), .B (n_503), .Y (n_9589)); + INVX1 g41130(.A (n_969), .Y (n_1045)); + NOR2X1 g41144(.A (n_8188), .B (n_921), .Y (n_9697)); + NOR2X1 g41164(.A (n_1198), .B (\u8_wp[0] ), .Y (n_920)); + INVX2 g41173(.A (n_5876), .Y (n_7115)); + NOR2X1 g41230(.A (\u11_rp[0] ), .B (\u11_wp[1] ), .Y (n_916)); + INVX2 g41235(.A (n_839), .Y (n_1052)); + INVX2 g41241(.A (n_603), .Y (n_1756)); + INVX2 g41290(.A (n_604), .Y (n_2502)); + BUFX3 g40900(.A (n_2553), .Y (n_2544)); + NAND2X1 g41390(.A (\u10_wp[1] ), .B (\u10_wp[2] ), .Y (n_1067)); + BUFX3 g41393(.A (n_846), .Y (n_1546)); + INVX1 g41422(.A (n_12803), .Y (n_1208)); + INVX1 g41484(.A (n_12801), .Y (n_1071)); + INVX4 g41572(.A (n_743), .Y (n_5138)); + NAND2X1 g41581(.A (\u26_ps_cnt[3] ), .B (n_760), .Y (n_910)); + INVX4 g41595(.A (n_707), .Y (n_5059)); + INVX2 g41672(.A (n_913), .Y (n_1108)); + INVX4 g41611(.A (n_745), .Y (n_5102)); + BUFX3 g41626(.A (n_909), .Y (n_1543)); + BUFX3 g40758(.A (n_938), .Y (n_4509)); + BUFX3 g40685(.A (n_933), .Y (n_4387)); + INVX1 g41674(.A (n_12144), .Y (n_7324)); + INVX1 g41693(.A (n_823), .Y (n_908)); + INVX4 g41707(.A (n_748), .Y (n_4961)); + INVX1 g41742(.A (n_830), .Y (n_1040)); + INVX1 g41781(.A (n_754), .Y (n_907)); + BUFX3 g40860(.A (n_935), .Y (n_4439)); + INVX2 g40690(.A (n_933), .Y (n_1180)); + INVX1 g42560(.A (n_762), .Y (n_888)); + INVX2 g40781(.A (n_945), .Y (n_1172)); + NAND2X1 g40698(.A (n_4703), .B (n_872), .Y (n_7526)); + AND2X1 g40278(.A (n_476), .B (n_869), .Y (n_870)); + BUFX3 g40833(.A (n_867), .Y (n_4370)); + INVX2 g40838(.A (n_867), .Y (n_1167)); + INVX4 g40815(.A (n_877), .Y (n_1859)); + NOR2X1 g40883(.A (n_688), .B (n_866), .Y (n_1824)); + INVX2 g41534(.A (n_532), .Y (n_1084)); + INVX1 g35457(.A (n_7385), .Y (n_865)); + INVX1 g35459(.A (n_7382), .Y (n_864)); + INVX1 g35461(.A (n_7441), .Y (n_863)); + INVX4 g42718(.A (n_862), .Y (n_5839)); + NAND2X2 g40882(.A (n_411), .B (n_705), .Y (n_1226)); + INVX1 g40916(.A (n_932), .Y (n_1163)); + INVX2 g41511(.A (n_858), .Y (n_1076)); + INVX1 g41502(.A (n_854), .Y (n_1127)); + NOR2X1 g41499(.A (\u11_wp[1] ), .B (n_853), .Y (n_1072)); + INVX4 g41477(.A (n_615), .Y (n_4996)); + INVX4 g41450(.A (n_982), .Y (n_3879)); + INVX4 g41442(.A (n_982), .Y (n_1488)); + INVX1 g41410(.A (n_847), .Y (n_1130)); + BUFX3 g41391(.A (n_846), .Y (n_1538)); + NOR2X1 g41370(.A (\u10_wp[1] ), .B (\u10_wp[2] ), .Y (n_1064)); + INVX2 g41332(.A (n_851), .Y (n_1060)); + INVX1 g41325(.A (n_844), .Y (n_1136)); + AOI21X1 g40234(.A0 (ic0_cfg_1024), .A1 (n_221), .B0 + (u14_u6_full_empty_r), .Y (n_843)); + NOR2X1 g41317(.A (n_4074), .B (\u9_wp[2] ), .Y (n_1059)); + INVX2 g41271(.A (n_841), .Y (n_1055)); + INVX8 g41259(.A (n_914), .Y (n_6649)); + INVX1 g41255(.A (n_840), .Y (n_1142)); + CLKBUFX3 g41236(.A (n_839), .Y (n_1517)); + AND2X1 g41214(.A (n_838), .B (wb_addr_i[3]), .Y (n_6042)); + OR2X1 g41198(.A (oc3_cfg_995), .B (n_471), .Y (n_837)); + NOR2X1 g41179(.A (n_4710), .B (n_836), .Y (n_1049)); + NAND2X2 g41163(.A (n_473), .B (n_751), .Y (n_1147)); + INVX1 g41142(.A (n_781), .Y (n_1149)); + NAND2X1 g41105(.A (oc3_cfg_995), .B (n_471), .Y (n_834)); + CLKBUFX1 g41091(.A (n_832), .Y (n_5407)); + INVX1 g41089(.A (n_832), .Y (n_1042)); + INVX1 g41743(.A (n_830), .Y (n_831)); + INVX2 g41054(.A (n_587), .Y (n_1035)); + INVX2 g41753(.A (n_835), .Y (n_1103)); + INVX4 g41073(.A (n_1214), .Y (n_1575)); + INVX1 g41065(.A (n_6981), .Y (n_1038)); + INVX1 g41748(.A (n_829), .Y (n_1105)); + INVX4 g40930(.A (n_931), .Y (n_1162)); + XOR2X1 g40448(.A (\u11_wp[0] ), .B (\u11_wp[1] ), .Y (n_825)); + INVX1 g41692(.A (n_823), .Y (n_1107)); + AOI21X1 g40394(.A0 (\u3_rp[3] ), .A1 (\u3_wp[2] ), .B0 (n_477), .Y + (n_822)); + AOI21X1 g40396(.A0 (\u10_rp[2] ), .A1 (\u10_wp[3] ), .B0 (n_514), .Y + (n_1290)); + NAND2X2 g40963(.A (n_798), .B (n_734), .Y (n_1082)); + BUFX3 g41032(.A (n_821), .Y (n_4507)); + INVX1 g41078(.A (n_818), .Y (n_819)); + INVX1 g43041(.A (n_1873), .Y (n_5827)); + NAND2X1 g41022(.A (n_808), .B (n_4711), .Y (n_7080)); + INVX1 g42599(.A (n_763), .Y (n_814)); + INVX2 g41722(.A (n_813), .Y (n_1106)); + INVX2 g40971(.A (n_930), .Y (n_1158)); + AOI21X1 g40350(.A0 (ic2_cfg_1044), .A1 (n_209), .B0 + (u14_u8_full_empty_r), .Y (n_811)); + AOI21X1 g40398(.A0 (\u11_rp[2] ), .A1 (\u11_wp[3] ), .B0 (n_522), .Y + (n_2617)); + NOR2X1 g40988(.A (n_808), .B (n_4711), .Y (n_6201)); + INVX4 g41651(.A (n_673), .Y (n_1111)); + INVX1 g41630(.A (n_807), .Y (n_1230)); + INVX1 g40817(.A (n_806), .Y (n_6141)); + INVX1 g40899(.A (n_2553), .Y (n_1232)); + NOR2X1 g40857(.A (n_8197), .B (n_804), .Y (n_9695)); + BUFX3 g41033(.A (n_821), .Y (n_4471)); + NOR2X1 g38798(.A (n_421), .B (wb_addr_i[30]), .Y (n_1262)); + AOI21X1 g40404(.A0 (\u9_rp[2] ), .A1 (\u9_wp[3] ), .B0 (n_478), .Y + (n_2621)); + CLKBUFX1 g40821(.A (n_806), .Y (n_6995)); + OAI21X1 g37199(.A0 (\u10_rp[1] ), .A1 (\u10_wp[2] ), .B0 (n_480), .Y + (n_1291)); + CLKBUFX1 g40936(.A (n_931), .Y (n_5424)); + NAND2X1 g40825(.A (n_5588), .B (n_802), .Y (n_8205)); + NOR2X1 g40980(.A (n_1033), .B (n_798), .Y (n_799)); + INVX1 g40822(.A (n_806), .Y (n_5881)); + ADDHX1 g38774(.A (\u2_res_cnt[1] ), .B (\u2_res_cnt[0] ), .CO + (n_1277), .S (n_796)); + ADDHX1 g38778(.A (\u2_to_cnt[0] ), .B (\u2_to_cnt[1] ), .CO (n_1553), + .S (n_795)); + ADDHX1 g38777(.A (\u26_cnt[0] ), .B (\u26_cnt[1] ), .CO (n_793), .S + (n_794)); + INVX4 g40675(.A (wb_din_670), .Y (n_2691)); + AOI22X1 g40416(.A0 (\u13_intm_r[1] ), .A1 (\u13_ints_r[1] ), .B0 + (\u13_intm_r[3] ), .B1 (\u13_ints_r[3] ), .Y (n_792)); + INVX1 g42329(.A (n_12331), .Y (n_1921)); + INVX2 g40469(.A (wb_din_679), .Y (n_2818)); + XOR2X1 g40442(.A (\u10_rp[1] ), .B (\u10_wp[2] ), .Y (n_786)); + INVX1 g42739(.A (n_458), .Y (n_991)); + NOR2X1 g40709(.A (n_3559), .B (\u5_rp[3] ), .Y (n_785)); + INVX2 g41452(.A (n_507), .Y (n_982)); + NOR2X1 g41133(.A (n_689), .B (\u9_wp[2] ), .Y (n_969)); + NAND2X1 g41143(.A (\u6_rp[2] ), .B (n_11579), .Y (n_781)); + NOR2X1 g41394(.A (n_12332), .B (n_12330), .Y (n_846)); + INVX1 g42745(.A (n_771), .Y (n_886)); + INVX1 g42646(.A (n_765), .Y (n_868)); + INVX1 g42509(.A (n_761), .Y (n_1923)); + INVX2 g42039(.A (n_5772), .Y (n_6318)); + INVX1 g42104(.A (n_1198), .Y (n_757)); + INVX4 g40515(.A (wb_din_671), .Y (n_2716)); + AND2X1 g41777(.A (n_671), .B (n_924), .Y (n_9614)); + AND2X1 g41763(.A (n_744), .B (n_444), .Y (n_835)); + NOR2X1 g41764(.A (n_715), .B (n_294), .Y (n_753)); + NOR2X1 g41750(.A (n_465), .B (n_503), .Y (n_752)); + AND2X1 g41723(.A (n_706), .B (n_751), .Y (n_813)); + NOR2X1 g41724(.A (\u13_ints_r[28] ), .B (n_749), .Y (n_750)); + NOR2X1 g41708(.A (n_705), .B (n_746), .Y (n_748)); + INVX2 g40645(.A (wb_din_688), .Y (n_2767)); + NAND2X1 g40909(.A (n_5), .B (\u11_rp[0] ), .Y (n_1000)); + AND2X1 g41660(.A (n_456), .B (n_711), .Y (n_3995)); + NAND2X1 g40769(.A (n_746), .B (\u7_wp[1] ), .Y (n_938)); + NOR2X1 g41612(.A (n_744), .B (n_444), .Y (n_745)); + INVX4 g40682(.A (wb_din_682), .Y (n_2792)); + NOR2X1 g41573(.A (n_627), .B (n_626), .Y (n_743)); + NOR2X1 g41559(.A (n_742), .B (n_703), .Y (n_1281)); + INVX2 g40529(.A (wb_din_663), .Y (n_2804)); + AND2X1 g41557(.A (n_699), .B (n_872), .Y (n_7531)); + NOR2X1 g41556(.A (n_693), .B (n_942), .Y (n_741)); + NOR2X1 g41464(.A (\u13_ints_r[22] ), .B (n_739), .Y (n_740)); + OR2X1 g41411(.A (n_454), .B (n_418), .Y (n_847)); + INVX2 g41414(.A (n_736), .Y (n_1831)); + AND2X1 g41401(.A (n_590), .B (n_127), .Y (n_9717)); + AND2X1 g41281(.A (n_710), .B (n_734), .Y (n_841)); + AND2X1 g41266(.A (n_598), .B (n_804), .Y (n_9650)); + NOR2X1 g41215(.A (\u13_ints_r[4] ), .B (n_492), .Y (n_733)); + INVX4 g40668(.A (wb_din_676), .Y (n_2786)); + NOR2X1 g41092(.A (n_708), .B (\u10_wp[2] ), .Y (n_832)); + NAND2X1 g41079(.A (n_697), .B (\u26_ps_cnt[0] ), .Y (n_818)); + NOR2X1 g41060(.A (n_621), .B (wb_addr_i[3]), .Y (n_6044)); + AOI22X1 g40410(.A0 (\u13_intm_r[14] ), .A1 (\u13_ints_r[14] ), .B0 + (\u13_intm_r[16] ), .B1 (\u13_ints_r[16] ), .Y (n_732)); + AOI22X1 g40411(.A0 (\u13_intm_r[27] ), .A1 (\u13_ints_r[27] ), .B0 + (\u13_intm_r[28] ), .B1 (\u13_ints_r[28] ), .Y (n_731)); + AOI22X1 g40413(.A0 (\u13_intm_r[21] ), .A1 (\u13_ints_r[21] ), .B0 + (\u13_intm_r[22] ), .B1 (\u13_ints_r[22] ), .Y (n_730)); + AOI22X1 g40414(.A0 (\u13_intm_r[23] ), .A1 (\u13_ints_r[23] ), .B0 + (\u13_intm_r[24] ), .B1 (\u13_ints_r[24] ), .Y (n_729)); + AOI22X1 g40415(.A0 (\u13_intm_r[5] ), .A1 (\u13_ints_r[5] ), .B0 + (\u13_intm_r[6] ), .B1 (\u13_ints_r[6] ), .Y (n_728)); + AOI22X1 g40417(.A0 (\u13_intm_r[19] ), .A1 (\u13_ints_r[19] ), .B0 + (\u13_intm_r[20] ), .B1 (\u13_ints_r[20] ), .Y (n_726)); + AOI22X1 g40418(.A0 (\u13_intm_r[11] ), .A1 (\u13_ints_r[11] ), .B0 + (\u13_intm_r[12] ), .B1 (\u13_ints_r[12] ), .Y (n_725)); + INVX4 g40462(.A (wb_din_664), .Y (n_2794)); + INVX2 g40494(.A (wb_din_685), .Y (n_2831)); + INVX4 g40522(.A (wb_din_681), .Y (n_2729)); + INVX4 g40536(.A (wb_din_662), .Y (n_2782)); + INVX2 g40554(.A (wb_din_669), .Y (n_2686)); + INVX2 g40582(.A (wb_din_661), .Y (n_2707)); + INVX1 g40661(.A (u2_bit_clk_r), .Y (n_719)); + INVX4 g40638(.A (wb_din_683), .Y (n_2684)); + NAND2X1 g40697(.A (n_715), .B (u15_rdd3), .Y (n_716)); + NAND2X2 g40707(.A (n_12274), .B (n_691), .Y (n_714)); + NAND2X1 g40810(.A (n_37), .B (\u26_cnt[2] ), .Y (n_713)); + NAND2X1 g40816(.A (n_53), .B (\u9_rp[0] ), .Y (n_877)); + NOR2X1 g40827(.A (n_145), .B (\u4_rp[3] ), .Y (n_712)); + NOR2X1 g40829(.A (\u2_cnt[4] ), .B (n_711), .Y (n_1822)); + NAND2X2 g40844(.A (n_710), .B (\u5_wp[1] ), .Y (n_867)); + NOR2X1 g40858(.A (n_6821), .B (\u6_rp[3] ), .Y (n_709)); + NAND2X2 g40696(.A (\u8_wp[0] ), .B (n_178), .Y (n_933)); + AND2X1 g40937(.A (n_708), .B (\u10_wp[2] ), .Y (n_931)); + NOR2X1 g41596(.A (n_751), .B (n_706), .Y (n_707)); + AND2X1 g41673(.A (n_746), .B (n_705), .Y (n_913)); + NAND2X1 g40938(.A (n_703), .B (\u2_to_cnt[5] ), .Y (n_704)); + OR2X1 g41218(.A (n_701), .B (n_711), .Y (n_702)); + NOR2X1 g41219(.A (n_699), .B (n_872), .Y (n_700)); + NAND2X1 g41579(.A (n_687), .B (n_698), .Y (n_1114)); + NOR2X1 g41237(.A (n_63), .B (n_600), .Y (n_839)); + OR2X1 g41239(.A (n_697), .B (n_529), .Y (n_1484)); + NOR2X1 g41243(.A (\u13_ints_r[16] ), .B (n_463), .Y (n_696)); + NAND2X1 g41256(.A (n_462), .B (n_836), .Y (n_840)); + INVX1 g41264(.A (n_695), .Y (n_914)); + NOR2X1 g41268(.A (\u13_ints_r[10] ), .B (n_450), .Y (n_694)); + AND2X1 g41654(.A (n_693), .B (n_942), .Y (n_9659)); + NAND2X2 g41302(.A (n_691), .B (n_12281), .Y (n_692)); + NOR2X1 g41303(.A (n_670), .B (n_921), .Y (n_690)); + AND2X1 g40978(.A (n_689), .B (\u9_wp[2] ), .Y (n_930)); + NOR2X1 g41356(.A (n_688), .B (n_687), .Y (n_1253)); + NOR2X1 g41374(.A (n_685), .B (n_708), .Y (n_686)); + NOR2X1 g41402(.A (n_684), .B (n_698), .Y (n_1227)); + NOR2X1 g41406(.A (n_175), .B (n_571), .Y (n_683)); + NOR2X1 g41413(.A (n_680), .B (n_515), .Y (n_681)); + AND2X1 g41424(.A (n_1374), .B (n_1301), .Y (n_679)); + NOR2X1 g41480(.A (\u13_ints_r[12] ), .B (n_676), .Y (n_677)); + AND2X1 g41536(.A (n_701), .B (n_2596), .Y (n_2571)); + NAND2X1 g40795(.A (n_58), .B (\u8_wp[1] ), .Y (n_937)); + INVX1 g41575(.A (n_7443), .Y (n_675)); + AND2X1 g41597(.A (n_1355), .B (n_1100), .Y (n_674)); + OR2X1 g41618(.A (n_469), .B (n_12584), .Y (n_977)); + NOR2X1 g41652(.A (n_12281), .B (n_244), .Y (n_673)); + NOR2X1 g41656(.A (n_671), .B (n_924), .Y (n_672)); + INVX2 g41657(.A (n_481), .Y (n_2558)); + AND2X1 g41659(.A (n_670), .B (n_921), .Y (n_9653)); + NOR2X1 g41710(.A (\u13_ints_r[15] ), .B (n_668), .Y (n_669)); + AND2X1 g41730(.A (n_568), .B (n_936), .Y (n_7528)); + NAND2X1 g41744(.A (n_431), .B (n_667), .Y (n_830)); + NOR2X1 g41745(.A (\u13_ints_r[9] ), .B (n_665), .Y (n_666)); + NOR2X1 g40828(.A (n_6316), .B (\u3_rp[3] ), .Y (n_664)); + INVX2 g40631(.A (wb_din_677), .Y (n_2735)); + INVX1 g42154(.A (n_656), .Y (n_1924)); + CLKBUFX1 g42372(.A (\u10_wp[1] ), .Y (n_5420)); + NOR2X1 g40826(.A (n_12634), .B (\u7_rp[3] ), .Y (n_650)); + INVX1 g43042(.A (n_422), .Y (n_1873)); + INVX1 g43078(.A (n_1033), .Y (n_641)); + INVX1 g43117(.A (n_6824), .Y (n_6131)); + AND2X1 g40808(.A (\u11_wp[1] ), .B (n_520), .Y (n_995)); + NOR2X1 g40811(.A (n_2567), .B (\u8_rp[3] ), .Y (n_639)); + INVX4 g40659(.A (wb_din_675), .Y (n_2741)); + INVX2 g40617(.A (wb_din_673), .Y (n_2681)); + NAND2X1 g40745(.A (n_12281), .B (\u8_rp[1] ), .Y (n_637)); + NOR2X1 g40734(.A (\u10_rp[1] ), .B (n_403), .Y (n_940)); + AOI21X1 g40095(.A0 (oc0_cfg_964), .A1 (in_slt_753), .B0 + (u14_u0_full_empty_r), .Y (n_635)); + INVX4 g40603(.A (wb_din_672), .Y (n_2829)); + INVX2 g40624(.A (wb_din_686), .Y (n_2702)); + OR2X1 g35458(.A (n_632), .B (n_11563), .Y (n_7385)); + OR2X1 g35460(.A (n_11597), .B (n_631), .Y (n_7382)); + OR2X1 g35462(.A (n_11762), .B (n_630), .Y (n_7441)); + INVX4 g40652(.A (wb_din_687), .Y (n_2763)); + AND2X1 g41518(.A (n_627), .B (n_626), .Y (n_858)); + NAND2X1 g41694(.A (n_434), .B (n_625), .Y (n_823)); + INVX2 g41524(.A (n_638), .Y (n_1316)); + INVX1 g42719(.A (n_459), .Y (n_862)); + NOR2X1 g40923(.A (\u11_wp[1] ), .B (n_520), .Y (n_932)); + OR2X1 g41522(.A (n_498), .B (n_459), .Y (n_976)); + AND2X1 g40981(.A (n_621), .B (wb_addr_i[3]), .Y (n_1225)); + AOI21X1 g40014(.A0 (oc1_cfg_974), .A1 (in_slt_752), .B0 + (u14_u1_full_empty_r), .Y (n_620)); + INVX1 g42392(.A (n_447), .Y (n_997)); + AND2X1 g41504(.A (n_564), .B (n_802), .Y (n_8207)); + NOR2X1 g41481(.A (\u13_ints_r[3] ), .B (n_616), .Y (n_617)); + INVX4 g40610(.A (wb_din_665), .Y (n_2744)); + NOR2X1 g41478(.A (n_734), .B (n_710), .Y (n_615)); + NOR2X1 g41412(.A (\u13_ints_r[18] ), .B (n_611), .Y (n_612)); + INVX2 g41417(.A (n_737), .Y (n_1760)); + NOR2X1 g41373(.A (\u13_ints_r[25] ), .B (n_608), .Y (n_609)); + AND2X1 g41339(.A (n_58), .B (n_178), .Y (n_851)); + INVX4 g40596(.A (wb_din_668), .Y (n_2772)); + OR2X1 g41326(.A (n_410), .B (n_11578), .Y (n_844)); + NOR2X1 g41318(.A (n_605), .B (n_689), .Y (n_606)); + NAND2X1 g41291(.A (n_53), .B (n_121), .Y (n_604)); + NAND2X1 g41242(.A (n_5), .B (n_487), .Y (n_603)); + NAND2X1 g41229(.A (n_601), .B (n_600), .Y (n_602)); + NOR2X1 g41217(.A (n_598), .B (n_804), .Y (n_599)); + NOR2X1 g41211(.A (\u13_ints_r[13] ), .B (n_490), .Y (n_597)); + INVX2 g40568(.A (wb_din_666), .Y (n_2765)); + AND2X1 g41174(.A (oc2_cfg_985), .B (n_242), .Y (n_5876)); + NOR2X1 g41106(.A (wb_addr_i[6]), .B (n_593), .Y (n_594)); + OR2X1 g41066(.A (n_590), .B (oc5_cfg_1016), .Y (n_6981)); + OR2X1 g41749(.A (n_523), .B (n_11612), .Y (n_829)); + NAND2X1 g41055(.A (n_12581), .B (\u5_rp[1] ), .Y (n_587)); + NOR2X1 g41627(.A (n_12581), .B (n_12583), .Y (n_909)); + INVX4 g40508(.A (wb_din_684), .Y (n_2790)); + INVX2 g40476(.A (wb_din_691), .Y (n_2748)); + INVX2 g40501(.A (wb_din_678), .Y (n_2720)); + INVX1 g41726(.A (n_2599), .Y (n_581)); + NOR2X1 g41613(.A (\u13_ints_r[19] ), .B (n_525), .Y (n_580)); + INVX4 g40589(.A (wb_din), .Y (n_2801)); + AOI22X1 g40419(.A0 (\u13_intm_r[25] ), .A1 (\u13_ints_r[25] ), .B0 + (\u13_intm_r[26] ), .B1 (\u13_ints_r[26] ), .Y (n_577)); + NOR2X1 g40723(.A (n_8536), .B (n_571), .Y (n_9766)); + AOI22X1 g40412(.A0 (\u13_intm_r[17] ), .A1 (\u13_ints_r[17] ), .B0 + (\u13_intm_r[18] ), .B1 (\u13_ints_r[18] ), .Y (n_576)); + NAND2X1 g41042(.A (\u4_wp[0] ), .B (n_444), .Y (n_821)); + AOI22X1 g40407(.A0 (\u13_intm_r[10] ), .A1 (\u13_ints_r[10] ), .B0 + (\u13_intm_r[9] ), .B1 (\u13_ints_r[9] ), .Y (n_574)); + NAND2X1 g40724(.A (n_8536), .B (n_571), .Y (n_9645)); + INVX4 g40575(.A (wb_din_680), .Y (n_2732)); + INVX2 g40561(.A (wb_din_667), .Y (n_2712)); + NOR2X1 g41578(.A (n_568), .B (n_936), .Y (n_569)); + NAND2X2 g41076(.A (\u11_rp[1] ), .B (n_487), .Y (n_1214)); + NOR2X1 g41425(.A (n_564), .B (n_802), .Y (n_565)); + INVX1 g42531(.A (n_838), .Y (n_2574)); + NAND2X1 g41017(.A (\u9_rp[1] ), .B (n_121), .Y (n_1221)); + INVX4 g40455(.A (wb_din_674), .Y (n_2755)); + AOI22X1 g40420(.A0 (\u13_intm_r[13] ), .A1 (\u13_ints_r[13] ), .B0 + (\u13_intm_r[15] ), .B1 (\u13_ints_r[15] ), .Y (n_557)); + DFFX1 u1_sdata_in_r_reg(.CK (n_77), .D (sdata_pad_i), .Q + (u1_sdata_in_r), .QN ()); + AOI21X1 g40360(.A0 (oc5_cfg_1014), .A1 (in_slt_747), .B0 + (u14_u5_full_empty_r), .Y (n_554)); + NAND2X2 g40782(.A (n_627), .B (\u3_wp[1] ), .Y (n_945)); + AOI21X1 g40067(.A0 (oc3_cfg_994), .A1 (in_slt_749), .B0 + (u14_u3_full_empty_r), .Y (n_553)); + NAND2X2 g40869(.A (n_744), .B (\u4_wp[1] ), .Y (n_935)); + NAND2X1 g41172(.A (\u4_rp[2] ), .B (n_551), .Y (n_552)); + NOR2X1 g41582(.A (\u13_ints_r[7] ), .B (n_488), .Y (n_550)); + AOI22X1 g40408(.A0 (\u13_intm_r[2] ), .A1 (\u13_ints_r[2] ), .B0 + (\u13_intm_r[4] ), .B1 (\u13_ints_r[4] ), .Y (n_549)); + OR2X1 g41631(.A (n_11777), .B (n_518), .Y (n_807)); + NAND2X1 g40824(.A (n_544), .B (oc2_cfg_986), .Y (n_806)); + AOI22X1 g40409(.A0 (\u13_intm_r[7] ), .A1 (\u13_ints_r[7] ), .B0 + (\u13_intm_r[8] ), .B1 (\u13_ints_r[8] ), .Y (n_543)); + NOR2X1 g41289(.A (\u13_ints_r[6] ), .B (n_540), .Y (n_541)); + AOI21X1 g40208(.A0 (oc4_cfg_1004), .A1 (in_slt_748), .B0 + (u14_u4_full_empty_r), .Y (n_539)); + INVX4 g42042(.A (n_3559), .Y (n_5772)); + AND2X1 g40901(.A (\u10_rp[1] ), .B (n_403), .Y (n_2553)); + OR2X1 g41503(.A (n_510), .B (n_458), .Y (n_854)); + NAND2X1 g41535(.A (n_12332), .B (n_12330), .Y (n_532)); + AND2X1 g41544(.A (n_319), .B (n_471), .Y (n_9719)); + AOI21X1 g39987(.A0 (oc2_cfg_984), .A1 (in_slt_750), .B0 + (u14_u2_full_empty_r), .Y (n_531)); + NAND2X1 g40722(.A (n_706), .B (\u6_wp[1] ), .Y (n_941)); + INVX1 g42549(.A (n_528), .Y (n_4711)); + INVX4 g42955(.A (n_710), .Y (n_798)); + INVX1 g42532(.A (n_621), .Y (n_838)); + INVX1 g42471(.A (n_524), .Y (n_3987)); + DFFX1 \u12_dout_reg[7] (.CK (clk_i), .D (wb_data_i[7]), .Q + (wb_din_667), .QN ()); + DFFX1 \u12_dout_reg[4] (.CK (clk_i), .D (wb_data_i[4]), .Q + (wb_din_664), .QN ()); + INVX1 g43014(.A (n_523), .Y (n_4687)); + NOR2X1 g41728(.A (\u11_rp[2] ), .B (\u11_wp[3] ), .Y (n_522)); + DFFX1 \u12_dout_reg[12] (.CK (clk_i), .D (wb_data_i[12]), .Q + (wb_din_672), .QN ()); + INVX1 g42602(.A (n_601), .Y (n_763)); + INVX1 g41907(.A (n_746), .Y (n_1421)); + INVX1 g42511(.A (n_551), .Y (n_521)); + DFFX1 \u12_dout_reg[24] (.CK (clk_i), .D (wb_data_i[24]), .Q + (wb_din_684), .QN ()); + DFFX1 \u12_dout_reg[26] (.CK (clk_i), .D (wb_data_i[26]), .Q + (wb_din_686), .QN ()); + INVX1 g42790(.A (n_520), .Y (n_853)); + NOR2X1 g41238(.A (\u10_rp[2] ), .B (\u10_wp[3] ), .Y (n_514)); + INVX1 g41992(.A (n_667), .Y (n_4706)); + NOR2X1 g41371(.A (\u13_ints_r[27] ), .B (ic2_int_set_723), .Y + (n_513)); + AND2X1 g41355(.A (\u11_wp[0] ), .B (\u11_wp[1] ), .Y (n_512)); + NAND2X1 g41416(.A (\u11_rp[1] ), .B (\u11_rp[0] ), .Y (n_736)); + NAND2X1 g41453(.A (\u8_wp[0] ), .B (\u8_wp[1] ), .Y (n_507)); + NOR2X1 g41479(.A (wb_addr_i[2]), .B (wb_addr_i[3]), .Y (n_996)); + INVX1 g42563(.A (n_782), .Y (n_762)); + INVX1 g42302(.A (n_705), .Y (n_6841)); + DFFX1 \u12_dout_reg[23] (.CK (clk_i), .D (wb_data_i[23]), .Q + (wb_din_683), .QN ()); + NOR2X1 g41267(.A (\u13_ints_r[24] ), .B (ic1_int_set_721), .Y + (n_495)); + INVX1 g42199(.A (n_625), .Y (n_4690)); + INVX1 g41841(.A (wb_addr_i[4]), .Y (n_1300)); + INVX1 g41854(.A (n_808), .Y (n_4714)); + DFFX1 \u12_dout_reg[11] (.CK (clk_i), .D (wb_data_i[11]), .Q + (wb_din_671), .QN ()); + INVX1 g41800(.A (n_593), .Y (n_5225)); + INVX1 g42746(.A (n_12581), .Y (n_771)); + NOR2X1 g41709(.A (wb_we_i), .B (u12_re2), .Y (n_1006)); + OR2X1 g41658(.A (\u10_rp[1] ), .B (\u10_rp[0] ), .Y (n_481)); + NAND2X1 g41655(.A (\u10_rp[1] ), .B (\u10_wp[2] ), .Y (n_480)); + DFFX1 \u12_dout_reg[31] (.CK (clk_i), .D (wb_data_i[31]), .Q + (wb_din_691), .QN ()); + NOR2X1 g41403(.A (\u9_rp[2] ), .B (\u9_wp[3] ), .Y (n_478)); + NOR2X1 g41614(.A (\u3_rp[3] ), .B (\u3_wp[2] ), .Y (n_477)); + AND2X1 g41319(.A (u12_we1), .B (wb_cyc_i), .Y (n_476)); + INVX1 g43064(.A (n_706), .Y (n_473)); + DFFX1 \u12_dout_reg[13] (.CK (clk_i), .D (wb_data_i[13]), .Q + (wb_din_673), .QN ()); + DFFX1 \u12_dout_reg[29] (.CK (clk_i), .D (wb_data_i[29]), .Q + (wb_din_689), .QN ()); + INVX1 g41965(.A (n_744), .Y (n_1419)); + NOR2X1 g41576(.A (wb_addr_i[3]), .B (wb_addr_i[4]), .Y (n_7443)); + INVX1 g42517(.A (n_469), .Y (n_4688)); + INVX1 g42840(.A (n_626), .Y (n_6838)); + DFFX1 \u12_dout_reg[22] (.CK (clk_i), .D (wb_data_i[22]), .Q + (wb_din_682), .QN ()); + INVX1 g42794(.A (n_462), .Y (n_4710)); + INVX1 g42764(.A (n_836), .Y (n_4713)); + NAND2X1 g41528(.A (\u10_rp[1] ), .B (\u10_rp[0] ), .Y (n_638)); + DFFX1 \u12_dout_reg[30] (.CK (clk_i), .D (wb_data_i[30]), .Q + (wb_din_690), .QN ()); + DFFX1 \u12_dout_reg[15] (.CK (clk_i), .D (wb_data_i[15]), .Q + (wb_din_675), .QN ()); + INVX1 g42510(.A (n_551), .Y (n_761)); + INVX4 g41822(.A (n_2567), .Y (n_6152)); + DFFX1 \u12_dout_reg[19] (.CK (clk_i), .D (wb_data_i[19]), .Q + (wb_din_679), .QN ()); + INVX1 g42812(.A (n_454), .Y (n_4701)); + NOR2X1 g41574(.A (\u13_ints_r[21] ), .B (ic0_int_set_719), .Y + (n_453)); + DFFX1 u2_bit_clk_r_reg(.CK (clk_i), .D (bit_clk_pad_i), .Q (), .QN + (u2_bit_clk_r)); + INVX4 g42895(.A (n_6316), .Y (n_634)); + INVX1 g43096(.A (n_689), .Y (n_4074)); + INVX1 g42647(.A (n_445), .Y (n_765)); + INVX2 g42155(.A (n_600), .Y (n_656)); + INVX1 g42697(.A (n_444), .Y (n_614)); + NAND2X1 g41419(.A (\u9_rp[1] ), .B (\u9_rp[0] ), .Y (n_737)); + NOR2X1 g41405(.A (n_8536), .B (oc3_cfg_997), .Y (n_9656)); + NAND2X1 g41407(.A (\u13_intm_r[0] ), .B (\u13_ints_r[0] ), .Y + (n_442)); + AND2X1 g41404(.A (wb_we_i), .B (wb_stb_i), .Y (n_869)); + NOR2X1 g41292(.A (\u4_rp[3] ), .B (\u4_wp[2] ), .Y (n_441)); + NAND2X1 g41265(.A (\u11_wp[1] ), .B (\u11_wp[2] ), .Y (n_695)); + INVX1 g41784(.A (n_12332), .Y (n_754)); + NOR2X1 g41257(.A (out_slt_25), .B (out_slt_24), .Y (n_440)); + INVX1 g41780(.A (n_12332), .Y (n_438)); + INVX4 g42286(.A (n_6821), .Y (n_784)); + INVX1 g42919(.A (n_431), .Y (n_4683)); + DFFX1 \u12_dout_reg[27] (.CK (clk_i), .D (wb_data_i[27]), .Q + (wb_din_687), .QN ()); + INVX1 g42850(.A (n_434), .Y (n_4738)); + INVX1 g43066(.A (n_706), .Y (n_1417)); + DFFX1 \u12_dout_reg[28] (.CK (clk_i), .D (wb_data_i[28]), .Q + (wb_din_688), .QN ()); + NAND2X1 g41727(.A (wb_cyc_i), .B (wb_stb_i), .Y (n_2599)); + INVX4 g42624(.A (n_627), .Y (n_1424)); + DFFX1 \u12_dout_reg[10] (.CK (clk_i), .D (wb_data_i[10]), .Q + (wb_din_670), .QN ()); + DFFX1 \u12_dout_reg[6] (.CK (clk_i), .D (wb_data_i[6]), .Q + (wb_din_666), .QN ()); + DFFX1 \u12_dout_reg[20] (.CK (clk_i), .D (wb_data_i[20]), .Q + (wb_din_680), .QN ()); + OR2X1 g41729(.A (wb_addr_i[31]), .B (wb_addr_i[29]), .Y (n_421)); + DFFX1 \u12_dout_reg[0] (.CK (clk_i), .D (wb_data_i[0]), .Q (wb_din), + .QN ()); + DFFX1 \u12_dout_reg[21] (.CK (clk_i), .D (wb_data_i[21]), .Q + (wb_din_681), .QN ()); + CLKBUFX1 g42994(.A (n_418), .Y (n_5825)); + INVX1 g42960(.A (n_751), .Y (n_7048)); + AND2X1 g41725(.A (\u2_res_cnt[0] ), .B (\u2_res_cnt[2] ), .Y (n_416)); + NOR2X1 g41639(.A (\u2_res_cnt[1] ), .B (\u2_res_cnt[3] ), .Y (n_415)); + DFFX1 \u12_dout_reg[5] (.CK (clk_i), .D (wb_data_i[5]), .Q + (wb_din_665), .QN ()); + DFFX1 \u12_dout_reg[18] (.CK (clk_i), .D (wb_data_i[18]), .Q + (wb_din_678), .QN ()); + NAND2X1 g41545(.A (u15_rdd1), .B (u15_crac_rd), .Y (n_414)); + INVX1 g41910(.A (n_734), .Y (n_657)); + DFFX1 \u12_dout_reg[25] (.CK (clk_i), .D (wb_data_i[25]), .Q + (wb_din_685), .QN ()); + DFFX1 \u12_dout_reg[2] (.CK (clk_i), .D (wb_data_i[2]), .Q + (wb_din_662), .QN ()); + NOR2X1 g41558(.A (\u5_rp[3] ), .B (\u5_wp[2] ), .Y (n_412)); + DFFX1 \u12_dout_reg[9] (.CK (clk_i), .D (wb_data_i[9]), .Q + (wb_din_669), .QN ()); + INVX1 g41905(.A (n_746), .Y (n_411)); + INVX1 g42021(.A (n_410), .Y (n_4699)); + DFFX1 \u12_dout_reg[17] (.CK (clk_i), .D (wb_data_i[17]), .Q + (wb_din_677), .QN ()); + DFFX1 \u12_dout_reg[3] (.CK (clk_i), .D (wb_data_i[3]), .Q + (wb_din_663), .QN ()); + DFFX1 \u12_dout_reg[8] (.CK (clk_i), .D (wb_data_i[8]), .Q + (wb_din_668), .QN ()); + DFFX1 \u12_dout_reg[16] (.CK (clk_i), .D (wb_data_i[16]), .Q + (wb_din_676), .QN ()); + INVX1 g43114(.A (n_145), .Y (n_6134)); + DFFX1 \u12_dout_reg[14] (.CK (clk_i), .D (wb_data_i[14]), .Q + (wb_din_674), .QN ()); + INVX1 g42453(.A (n_403), .Y (n_1206)); + DFFX1 \u12_dout_reg[1] (.CK (clk_i), .D (wb_data_i[1]), .Q + (wb_din_661), .QN ()); + CLKBUFX1 g42105(.A (n_691), .Y (n_1198)); + INVX1 g42349(.A (\u11_mem[3]_65 ), .Y (n_6035)); + INVX1 g42139(.A (\u11_mem[2]_95 ), .Y (n_6431)); + INVX1 g42947(.A (\u9_mem[1]_144 ), .Y (n_1703)); + INVX1 g41803(.A (\u9_mem[2]_105 ), .Y (n_1766)); + INVX1 g42912(.A (\u10_mem[1]_122 ), .Y (n_6542)); + INVX1 g41972(.A (\u11_mem[1]_147 ), .Y (n_1591)); + INVX1 g42401(.A (n_1212), .Y (n_456)); + INVX1 g42005(.A (out_slt_133), .Y (n_401)); + INVX1 g42067(.A (oc1_int_set_709), .Y (n_540)); + INVX1 g42813(.A (oc4_cfg_1009), .Y (n_454)); + INVX1 g43082(.A (out_slt_85), .Y (n_10790)); + INVX1 g41868(.A (\u9_mem[0]_156 ), .Y (n_6847)); + INVX1 g41873(.A (\u9_mem[0]_171 ), .Y (n_1738)); + INVX1 g42010(.A (\u11_mem[3]_85 ), .Y (n_5524)); + INVX1 g42541(.A (\u10_mem[0]_173 ), .Y (n_1685)); + INVX1 g42127(.A (out_slt_139), .Y (n_399)); + INVX1 g43063(.A (out_slt_75), .Y (n_398)); + INVX1 g42374(.A (\u10_wp[1] ), .Y (n_708)); + INVX1 g42119(.A (out_slt4), .Y (n_397)); + INVX1 g42612(.A (out_slt_100), .Y (n_396)); + INVX1 g42652(.A (\u11_mem[1]_146 ), .Y (n_1595)); + INVX1 g42548(.A (\u11_mem[0]_161 ), .Y (n_6368)); + INVX1 g42115(.A (\u10_mem[0]_162 ), .Y (n_6380)); + INVX1 g42829(.A (out_slt_92), .Y (n_394)); + INVX1 g42545(.A (\u10_mem[3]_68 ), .Y (n_6595)); + INVX1 g41924(.A (\u9_mem[3]_60 ), .Y (n_6895)); + INVX1 g41902(.A (\u11_wp[0] ), .Y (n_393)); + INVX1 g42577(.A (crac_out), .Y (n_392)); + INVX1 g42619(.A (out_slt_91), .Y (n_391)); + INVX1 g43099(.A (out_slt_74), .Y (n_389)); + INVX1 g42779(.A (\u10_mem[0]_156 ), .Y (n_6333)); + INVX1 g42520(.A (\u9_mem[0]_162 ), .Y (n_6392)); + INVX1 g43044(.A (oc3_cfg), .Y (n_422)); + INVX1 g42159(.A (\u10_mem[1]_129 ), .Y (n_6468)); + INVX1 g42306(.A (out_slt_131), .Y (n_387)); + INVX1 g42797(.A (\u10_mem[3]_67 ), .Y (n_6598)); + INVX1 g42477(.A (\u9_mem[2]_117 ), .Y (n_385)); + INVX2 g42625(.A (\u3_wp[0] ), .Y (n_627)); + INVX1 g42298(.A (\u9_mem[2]_116 ), .Y (n_2499)); + INVX1 g42179(.A (out_slt_149), .Y (n_384)); + INVX1 g42222(.A (out_slt_178), .Y (n_383)); + INVX1 g41926(.A (\u10_mem[2]_102 ), .Y (n_6660)); + INVX1 g42130(.A (\u10_mem[3] ), .Y (n_6005)); + INVX1 g42204(.A (oc0_int_set_708), .Y (n_492)); + INVX1 g42318(.A (out_slt_88), .Y (n_380)); + INVX1 g42084(.A (\u11_mem[3]_72 ), .Y (n_6023)); + INVX1 g42676(.A (\u10_mem[2]_113 ), .Y (n_379)); + INVX1 g43110(.A (\u11_mem[3]_86 ), .Y (n_5508)); + INVX1 g42227(.A (\u11_mem[1]_144 ), .Y (n_1604)); + INVX1 g41863(.A (\u10_mem[2]_93 ), .Y (n_6612)); + INVX1 g42047(.A (\u10_mem[2]_96 ), .Y (n_6018)); + INVX1 g42681(.A (\u11_mem[1]_148 ), .Y (n_1584)); + INVX1 g41787(.A (out_slt_148), .Y (n_376)); + INVX1 g42617(.A (out_slt_130), .Y (n_375)); + INVX1 g42345(.A (\u11_mem[1]_143 ), .Y (n_1609)); + INVX1 g42080(.A (\u9_mem[1]_125 ), .Y (n_6940)); + INVX1 g42804(.A (out_slt_87), .Y (n_373)); + INVX1 g42651(.A (oc2_int_set_712), .Y (n_450)); + INVX1 g41871(.A (out_slt_165), .Y (n_372)); + INVX1 g43071(.A (\u10_mem[1]_123 ), .Y (n_6411)); + INVX1 g42547(.A (out_slt_89), .Y (n_370)); + INVX1 g42827(.A (\u11_mem[3]_81 ), .Y (n_5492)); + INVX1 g42432(.A (\u10_mem[2]_110 ), .Y (n_366)); + INVX1 g41869(.A (\u9_mem[2]_113 ), .Y (n_365)); + INVX1 g42487(.A (out_slt_128), .Y (n_363)); + INVX1 g42180(.A (\u9_mem[0]_163 ), .Y (n_6398)); + INVX1 g42690(.A (\u9_mem[2]_102 ), .Y (n_6635)); + INVX1 g43069(.A (\u11_mem[3]_80 ), .Y (n_5496)); + INVX1 g41849(.A (out_slt_147), .Y (n_362)); + INVX1 g42723(.A (out_slt_102), .Y (n_361)); + INVX1 g42325(.A (\u11_mem[1]_142 ), .Y (n_1614)); + INVX1 g42568(.A (\u11_mem[0]_174 ), .Y (n_1610)); + INVX1 g42682(.A (\u10_mem[2]_95 ), .Y (n_6021)); + INVX1 g42094(.A (out_slt_164), .Y (n_359)); + INVX1 g42665(.A (\u11_mem[3]_58 ), .Y (n_6524)); + INVX1 g42834(.A (\u11_mem[0]_155 ), .Y (n_6349)); + INVX1 g42479(.A (\u10_mem[3]_66 ), .Y (n_6601)); + INVX1 g41883(.A (\u9_mem[3]_61 ), .Y (n_6912)); + INVX1 g42332(.A (crac_out_852), .Y (n_357)); + INVX2 g42106(.A (\u8_rp[1] ), .Y (n_691)); + INVX1 g42683(.A (\u9_mem[1]_138 ), .Y (n_356)); + INVX1 g42724(.A (out_slt_146), .Y (n_352)); + INVX1 g42637(.A (\u10_mem[2]_98 ), .Y (n_6668)); + INVX1 g41913(.A (\u11_mem[3]_61 ), .Y (n_6556)); + INVX1 g42237(.A (out_slt_90), .Y (n_351)); + INVX1 g42240(.A (\u10_mem[1]_126 ), .Y (n_5966)); + INVX1 g42899(.A (\u10_mem[2]_105 ), .Y (n_1690)); + INVX1 g41855(.A (oc4_cfg_1005), .Y (n_808)); + INVX1 g42925(.A (\u9_mem[0]_167 ), .Y (n_349)); + INVX1 g42177(.A (out_slt_68), .Y (n_348)); + INVX2 g42533(.A (wb_addr_i[2]), .Y (n_621)); + INVX1 g42598(.A (\u11_mem[1]_141 ), .Y (n_1619)); + INVX1 g42456(.A (\u9_mem[2]_111 ), .Y (n_347)); + INVX1 g42246(.A (\u9_mem[2]_98 ), .Y (n_6644)); + INVX1 g41845(.A (\u9_mem[2]_112 ), .Y (n_1700)); + INVX1 g42197(.A (\u9_mem[2]_114 ), .Y (n_346)); + INVX1 g41830(.A (\u11_mem[1]_140 ), .Y (n_1754)); + INVX1 g42049(.A (\u10_mem[0]_178 ), .Y (n_2539)); + INVX1 g42120(.A (\u9_mem[2]_115 ), .Y (n_345)); + INVX1 g42486(.A (\u9_mem[3]_59 ), .Y (n_6890)); + INVX1 g43070(.A (\u11_mem[0]_177 ), .Y (n_1596)); + INVX1 g42228(.A (\u9_mem[2]_118 ), .Y (n_343)); + INVX1 g42593(.A (\u10_mem[2]_115 ), .Y (n_2545)); + INVX1 g42166(.A (\u9_mem[1]_133 ), .Y (n_6528)); + INVX1 g41986(.A (\u11_mem[1]_145 ), .Y (n_1599)); + INVX1 g42742(.A (\u10_mem[0]_160 ), .Y (n_6384)); + INVX1 g42112(.A (\u9_mem[3]_77 ), .Y (n_5374)); + INVX1 g42046(.A (\u9_mem[3]_78 ), .Y (n_5343)); + INVX1 g41859(.A (out_slt_73), .Y (n_341)); + INVX1 g41880(.A (\u2_cnt[3] ), .Y (n_698)); + INVX1 g42911(.A (\u9_mem[3]_80 ), .Y (n_5333)); + INVX1 g42082(.A (\u9_mem[1]_141 ), .Y (n_340)); + INVX1 g42377(.A (\u11_mem[1]_139 ), .Y (n_339)); + INVX1 g42171(.A (\u11_mem[3]_62 ), .Y (n_6658)); + INVX1 g42129(.A (\u9_mem[3]_83 ), .Y (n_5367)); + INVX1 g41927(.A (ic0_int_set_720), .Y (n_739)); + INVX1 g42305(.A (\u9_mem[3]_85 ), .Y (n_5345)); + INVX1 g42788(.A (n_8567), .Y (n_942)); + INVX1 g42175(.A (\u9_mem[3]_87 ), .Y (n_5350)); + INVX1 g41952(.A (\u9_mem[2]_93 ), .Y (n_6900)); + INVX1 g42635(.A (\u10_mem[3]_75 ), .Y (n_5575)); + INVX1 g43061(.A (\u9_mem[0]_159 ), .Y (n_6404)); + INVX1 g43060(.A (\u10_mem[3]_76 ), .Y (n_5520)); + INVX1 g43003(.A (u14_n_134), .Y (n_1124)); + INVX1 g41918(.A (oc3_cfg_996), .Y (n_471)); + INVX1 g42071(.A (u14_n_133), .Y (n_1308)); + INVX1 g43052(.A (out_slt_142), .Y (n_10983)); + INVX1 g42534(.A (\u9_mem[1]_130 ), .Y (n_6540)); + INVX1 g43055(.A (\u10_mem[3]_78 ), .Y (n_5518)); + INVX1 g42524(.A (out_slt_22), .Y (n_1301)); + INVX1 g41844(.A (\u10_mem[3]_80 ), .Y (n_5514)); + INVX1 g42633(.A (ic1_int_set_722), .Y (n_608)); + INVX1 g42220(.A (\u11_mem[0]_175 ), .Y (n_1605)); + INVX1 g42933(.A (crac_out_857), .Y (n_338)); + INVX1 g42763(.A (\u10_mem[3]_83 ), .Y (n_5357)); + INVX1 g42808(.A (\u10_mem[0]_168 ), .Y (n_337)); + INVX1 g42409(.A (\u9_mem[3]_69 ), .Y (n_6450)); + INVX1 g42914(.A (\u9_mem[3]_68 ), .Y (n_6614)); + INVX1 g42948(.A (\u9_mem[3]_70 ), .Y (n_6505)); + INVX1 g42224(.A (n_9641), .Y (n_685)); + INVX1 g42086(.A (out_slt_125), .Y (n_335)); + INVX1 g42754(.A (\u11_mem[0]_167 ), .Y (n_334)); + INVX1 g42833(.A (\u9_mem[2]_103 ), .Y (n_6873)); + INVX1 g42048(.A (out_slt_84), .Y (n_333)); + INVX1 g42169(.A (out_slt_95), .Y (n_332)); + INVX1 g42030(.A (\u10_mem[0]_180 ), .Y (n_1864)); + INVX1 g41988(.A (oc1_int_set_710), .Y (n_488)); + INVX1 g42118(.A (out_slt_96), .Y (n_330)); + INVX1 g42035(.A (out_slt_83), .Y (n_329)); + INVX1 g43056(.A (\u10_mem[2]_94 ), .Y (n_6607)); + INVX1 g42785(.A (\u11_mem[1]_137 ), .Y (n_1644)); + INVX1 g42194(.A (\u11_mem[3]_63 ), .Y (n_6625)); + INVX1 g42070(.A (out_slt_159), .Y (n_328)); + INVX1 g42465(.A (crac_wr), .Y (n_324)); + INVX1 g42757(.A (\u11_mem[1]_123 ), .Y (n_6545)); + INVX1 g41802(.A (\u9_mem[3]_73 ), .Y (n_6951)); + INVX1 g42473(.A (\u10_mem[2]_104 ), .Y (n_6030)); + INVX1 g42636(.A (\u11_mem[3]_64 ), .Y (n_6650)); + INVX1 g43045(.A (\u9_mem[0]_176 ), .Y (n_1728)); + INVX1 g41985(.A (out_slt_163), .Y (n_322)); + INVX1 g42059(.A (\u11_mem[3]_60 ), .Y (n_6441)); + INVX1 g42312(.A (out_slt_94), .Y (n_321)); + INVX1 g42160(.A (out_slt_93), .Y (n_320)); + INVX1 g42908(.A (oc3_cfg_995), .Y (n_319)); + INVX1 g42630(.A (\u10_mem[0]_159 ), .Y (n_6386)); + INVX1 g42408(.A (\u9_mem[0]_164 ), .Y (n_6396)); + INVX1 g43058(.A (\u10_mem[0]_167 ), .Y (n_314)); + INVX1 g42528(.A (\u10_mem[1]_136 ), .Y (n_313)); + INVX1 g42319(.A (\u11_mem[0]_168 ), .Y (n_312)); + INVX1 g42626(.A (\u10_mem[3]_86 ), .Y (n_5506)); + INVX1 g41978(.A (out_slt_162), .Y (n_9952)); + INVX1 g42915(.A (\u9_mem[3]_66 ), .Y (n_6620)); + INVX1 g43088(.A (\u10_mem[3]_81 ), .Y (n_5512)); + INVX1 g42441(.A (\u9_mem[1]_148 ), .Y (n_2506)); + INVX1 g41853(.A (\u7_rp[3] ), .Y (n_457)); + INVX2 g42956(.A (\u5_wp[0] ), .Y (n_710)); + INVX1 g41808(.A (\u11_mem[1]_122 ), .Y (n_6490)); + INVX1 g42250(.A (\u10_mem[2]_118 ), .Y (n_1863)); + INVX1 g42957(.A (out_slt_161), .Y (n_9602)); + INVX1 g42193(.A (crac_out_850), .Y (n_311)); + INVX1 g42217(.A (\u10_mem[3]_74 ), .Y (n_5577)); + INVX1 g42904(.A (oc3_cfg_997), .Y (n_571)); + INVX1 g42397(.A (\u10_mem[0]_179 ), .Y (n_1251)); + INVX1 g42970(.A (\u9_mem[3]_82 ), .Y (n_5369)); + INVX1 g41912(.A (\u5_wp[1] ), .Y (n_734)); + INVX1 g41862(.A (\u9_mem[3]_65 ), .Y (n_6905)); + INVX1 g42857(.A (out_slt_169), .Y (n_308)); + INVX1 g43081(.A (\u9_mem[1]_146 ), .Y (n_1723)); + INVX1 g42304(.A (\u7_wp[1] ), .Y (n_705)); + INVX1 g42594(.A (\u10_mem[3]_72 ), .Y (n_6013)); + INVX1 g43057(.A (\u9_mem[3]_64 ), .Y (n_6559)); + INVX1 g41994(.A (crac_out_847), .Y (n_306)); + INVX1 g42214(.A (out_slt_106), .Y (n_304)); + INVX1 g43086(.A (wb_ack_o), .Y (n_303)); + INVX1 g41903(.A (out_slt_170), .Y (n_302)); + INVX1 g41874(.A (\u9_mem[3]_62 ), .Y (n_6886)); + INVX1 g41977(.A (out_slt_115), .Y (n_300)); + INVX1 g41997(.A (out_slt_140), .Y (n_299)); + INVX1 g42195(.A (\u11_mem[2]_113 ), .Y (n_298)); + INVX1 g42321(.A (\u11_mem[1]_133 ), .Y (n_6503)); + INVX1 g42573(.A (out_slt_174), .Y (n_297)); + INVX1 g42484(.A (out_slt_101), .Y (n_295)); + INVX1 g43089(.A (\u10_mem[0]_177 ), .Y (n_1238)); + INVX1 g42597(.A (\u10_mem[3]_57 ), .Y (n_6007)); + INVX1 g42949(.A (u15_rdd3), .Y (n_294)); + INVX1 g43067(.A (\u6_wp[0] ), .Y (n_706)); + INVX1 g42249(.A (\u10_mem[1]_120 ), .Y (n_6526)); + INVX1 g42050(.A (\u9_mem[1]_140 ), .Y (n_1737)); + INVX1 g42212(.A (out_slt_112), .Y (n_290)); + INVX1 g43050(.A (\u9_mem[0]_154 ), .Y (n_6852)); + INVX1 g43053(.A (\u9_mem[2]_110 ), .Y (n_1561)); + INVX1 g43024(.A (\u11_mem[2]_106 ), .Y (n_288)); + INVX1 g42761(.A (n_866), .Y (n_687)); + INVX1 g43091(.A (out_slt_113), .Y (n_287)); + INVX1 g41831(.A (out_slt_105), .Y (n_10783)); + INVX1 g42653(.A (\u9_mem[2]_89 ), .Y (n_6933)); + INVX1 g41826(.A (dma_req_o[5]), .Y (n_284)); + INVX1 g42369(.A (oc1_cfg_976), .Y (n_283)); + INVX1 g42578(.A (\u9_mem[1]_135 ), .Y (n_6954)); + INVX1 g41892(.A (\u9_mem[0]_160 ), .Y (n_6402)); + INVX1 g42354(.A (\u10_mem[3]_64 ), .Y (n_6002)); + INVX1 g42664(.A (\u11_mem[0]_152 ), .Y (n_6355)); + INVX1 g42843(.A (out_slt_79), .Y (n_282)); + INVX1 g42551(.A (\u10_mem[2]_100 ), .Y (n_6664)); + INVX1 g42096(.A (out_slt_80), .Y (n_281)); + INVX1 g41790(.A (out_slt_145), .Y (n_280)); + INVX1 g42605(.A (\u9_mem[1]_139 ), .Y (n_1679)); + INVX1 g41804(.A (\u9_mem[0]_175 ), .Y (n_1704)); + INVX1 g42824(.A (\u11_mem[2]_109 ), .Y (n_279)); + INVX1 g42700(.A (\u9_mem[1]_124 ), .Y (n_6942)); + INVX1 g41875(.A (dma_req_o[1]), .Y (n_278)); + INVX1 g42780(.A (\u11_mem[2]_110 ), .Y (n_277)); + INVX1 g41829(.A (\u11_mem[1]_132 ), .Y (n_6507)); + INVX1 g42076(.A (\u11_mem[2]_111 ), .Y (n_275)); + INVX4 g42045(.A (n_6091), .Y (n_3559)); + INVX1 g42969(.A (\u11_mem[1]_119 ), .Y (n_6500)); + INVX1 g41789(.A (\u11_mem[3]_82 ), .Y (n_5500)); + INVX1 g42569(.A (out_slt8), .Y (n_273)); + INVX1 g41996(.A (\u10_mem[2]_112 ), .Y (n_2549)); + INVX1 g42832(.A (\u11_mem[1]_120 ), .Y (n_6498)); + INVX1 g42786(.A (\u11_mem[1]_121 ), .Y (n_6492)); + INVX1 g42678(.A (\u9_mem[0]_150 ), .Y (n_6862)); + INVX1 g42376(.A (out_slt_104), .Y (n_10785)); + INVX1 g42001(.A (dma_req_o[0]), .Y (n_271)); + INVX1 g42558(.A (\u11_mem[2]_112 ), .Y (n_270)); + INVX1 g42634(.A (\u9_mem[1]_120 ), .Y (n_6879)); + INVX1 g42394(.A (oc2_cfg), .Y (n_447)); + INVX1 g42370(.A (\u10_mem[1]_147 ), .Y (n_2538)); + INVX1 g42051(.A (\u9_mem[1]_122 ), .Y (n_6876)); + INVX1 g42485(.A (\u11_mem[1]_126 ), .Y (n_6484)); + INVX1 g42580(.A (dma_req_o[4]), .Y (n_268)); + INVX1 g42018(.A (out_slt_78), .Y (n_267)); + INVX1 g42174(.A (\u10_mem[3]_69 ), .Y (n_6591)); + INVX1 g42209(.A (out_slt_110), .Y (n_266)); + INVX1 g42686(.A (out_slt_129), .Y (n_265)); + INVX1 g42845(.A (\u10_mem[1]_128 ), .Y (n_6476)); + INVX1 g42257(.A (out_slt_111), .Y (n_264)); + INVX1 g42629(.A (\u11_mem[2]_98 ), .Y (n_433)); + INVX1 g42924(.A (out_slt_173), .Y (n_263)); + INVX1 g42810(.A (\u10_mem[2]_117 ), .Y (n_2542)); + INVX1 g42656(.A (out_slt_107), .Y (n_262)); + INVX1 g42060(.A (\u9_mem[1]_149 ), .Y (n_1715)); + INVX1 g42856(.A (\u9_mem[1]_127 ), .Y (n_6937)); + INVX1 g42443(.A (out_slt_116), .Y (n_261)); + INVX1 g42407(.A (\u2_cnt[5] ), .Y (n_701)); + INVX1 g35542(.A (i4_full), .Y (n_631)); + INVX1 g35545(.A (i6_full), .Y (n_630)); + INVX1 g41925(.A (\u10_mem[0]_155 ), .Y (n_6331)); + INVX1 g42674(.A (oc2_cfg_987), .Y (n_503)); + INVX1 g43047(.A (n_8199), .Y (n_804)); + INVX1 g42822(.A (\u8_wp[2] ), .Y (n_1446)); + INVX1 g42295(.A (out_slt_134), .Y (n_259)); + INVX1 g41857(.A (oc0_cfg_965), .Y (n_257)); + INVX1 g42008(.A (\u11_mem[0]_165 ), .Y (n_5953)); + INVX1 g42521(.A (\u10_mem[2]_106 ), .Y (n_256)); + INVX1 g41893(.A (\u10_mem[0]_151 ), .Y (n_6342)); + INVX2 g41966(.A (\u4_wp[0] ), .Y (n_744)); + INVX1 g42125(.A (\u9_mem[3]_67 ), .Y (n_6617)); + INVX1 g42670(.A (out_slt_137), .Y (n_254)); + INVX1 g42939(.A (\u10_mem[1]_134 ), .Y (n_5974)); + INVX1 g42138(.A (out_slt3), .Y (n_251)); + INVX1 g42902(.A (\u10_mem[0]_171 ), .Y (n_2557)); + INVX1 g42498(.A (\u10_mem[1]_119 ), .Y (n_406)); + INVX1 g42324(.A (\u10_mem[1]_139 ), .Y (n_249)); + INVX1 g41990(.A (\u11_mem[0]_180 ), .Y (n_1581)); + INVX1 g43084(.A (\u11_mem[2]_90 ), .Y (n_6445)); + INVX1 g42251(.A (out_slt_99), .Y (n_248)); + INVX2 g42156(.A (\u3_rp[1] ), .Y (n_600)); + INVX1 g42007(.A (\u9_mem[0] ), .Y (n_6868)); + INVX1 g43021(.A (n_1773), .Y (n_688)); + INVX1 g42768(.A (oc5_cfg_1015), .Y (n_590)); + INVX1 g42750(.A (\u6_wp[2] ), .Y (n_1255)); + INVX1 g42107(.A (\u8_rp[1] ), .Y (n_244)); + INVX1 g42297(.A (\u9_mem[0]_180 ), .Y (n_1716)); + INVX1 g42137(.A (\u9_mem[0]_153 ), .Y (n_6854)); + INVX1 g42941(.A (out_slt_98), .Y (n_243)); + INVX1 g41919(.A (\u10_mem[3]_62 ), .Y (n_6565)); + INVX1 g42660(.A (\u10_mem[0]_174 ), .Y (n_2550)); + INVX1 g42163(.A (oc2_cfg_986), .Y (n_242)); + INVX1 g42410(.A (\u11_mem[0]_154 ), .Y (n_6351)); + INVX1 g42566(.A (\u9_mem[0]_174 ), .Y (n_1701)); + INVX1 g42489(.A (out_slt_157), .Y (n_240)); + INVX1 g42396(.A (out_slt_155), .Y (n_237)); + INVX1 g42116(.A (\u9_mem[1]_129 ), .Y (n_6551)); + INVX1 g42591(.A (\u11_mem[2]_114 ), .Y (n_236)); + INVX1 g42072(.A (out_slt_108), .Y (n_234)); + INVX1 g42011(.A (\u9_mem[0]_157 ), .Y (n_6394)); + INVX1 g43051(.A (\u10_mem[3]_61 ), .Y (n_6569)); + INVX1 g42334(.A (\u9_mem[2]_92 ), .Y (n_6902)); + INVX4 g42896(.A (\u3_rp[0] ), .Y (n_6316)); + INVX1 g41867(.A (\u10_mem[1]_141 ), .Y (n_232)); + INVX1 g42122(.A (\u10_mem[3]_63 ), .Y (n_6562)); + INVX1 g42097(.A (\u9_mem[0]_179 ), .Y (n_2507)); + INVX1 g42157(.A (\u9_mem[0]_151 ), .Y (n_6859)); + INVX1 g42506(.A (crac_out_853), .Y (n_231)); + INVX1 g41792(.A (out_slt_71), .Y (n_230)); + INVX1 g42412(.A (out_slt_132), .Y (n_229)); + INVX1 g42310(.A (out_slt_154), .Y (n_228)); + INVX1 g42666(.A (crac_out_846), .Y (n_227)); + INVX1 g43002(.A (\u11_mem[1]_124 ), .Y (n_6487)); + INVX1 g42668(.A (\u10_mem[3]_84 ), .Y (n_5352)); + INVX1 g42289(.A (\u9_mem[3]_57 ), .Y (n_6919)); + INVX1 g42973(.A (\u10_mem[1]_124 ), .Y (n_6408)); + INVX1 g41989(.A (\u9_mem[1]_128 ), .Y (n_6656)); + INVX1 g43054(.A (out_slt6), .Y (n_223)); + INVX1 g42414(.A (\u9_mem[1]_137 ), .Y (n_1748)); + INVX1 g42913(.A (\u9_mem[0]_165 ), .Y (n_6866)); + INVX2 g42741(.A (oc1_cfg), .Y (n_458)); + INVX1 g42362(.A (n_4703), .Y (n_699)); + INVX1 g42360(.A (in_slt_739), .Y (n_221)); + INVX1 g42951(.A (\u9_mem[2]_88 ), .Y (n_6881)); + INVX1 g41788(.A (\u11_mem[1]_136 ), .Y (n_1650)); + INVX1 g42024(.A (n_4708), .Y (n_872)); + INVX1 g42098(.A (\u10_mem[0]_163 ), .Y (n_6375)); + INVX1 g42075(.A (out_slt_65), .Y (n_220)); + INVX1 g42348(.A (\u26_ps_cnt[1] ), .Y (n_697)); + INVX1 g41882(.A (\u9_mem[0]_161 ), .Y (n_6400)); + INVX1 g42977(.A (\u9_mem[3]_71 ), .Y (n_6581)); + INVX1 g41779(.A (out_slt_66), .Y (n_10978)); + INVX1 g42701(.A (\u10_mem[0]_164 ), .Y (n_6390)); + INVX1 g41951(.A (out_slt_127), .Y (n_217)); + INVX1 g42352(.A (\u6_rp[3] ), .Y (n_496)); + INVX1 g42233(.A (\u10_mem[0]_161 ), .Y (n_6382)); + INVX1 g42436(.A (\u11_mem[0]_163 ), .Y (n_6363)); + INVX1 g42553(.A (\u10_mem[1]_146 ), .Y (n_215)); + INVX1 g42921(.A (\u10_mem[3]_60 ), .Y (n_6572)); + INVX1 g42254(.A (\u3_wp[2] ), .Y (n_214)); + INVX2 g41801(.A (wb_addr_i[5]), .Y (n_593)); + INVX1 g42202(.A (n_5788), .Y (n_802)); + INVX1 g41811(.A (\u11_mem[0]_164 ), .Y (n_6360)); + INVX1 g42831(.A (out_slt_123), .Y (n_10990)); + INVX1 g42375(.A (\u9_mem[2]_90 ), .Y (n_6888)); + INVX1 g42164(.A (\u10_mem[2]_88 ), .Y (n_6028)); + INVX1 g43083(.A (\u9_mem[2]_91 ), .Y (n_6931)); + INVX1 g42101(.A (oc5_int_set_718), .Y (n_525)); + INVX2 g42454(.A (\u10_rp[0] ), .Y (n_403)); + INVX1 g41923(.A (out_slt_152), .Y (n_212)); + INVX1 g42527(.A (out_slt_70), .Y (n_211)); + INVX1 g42172(.A (\u10_mem[3]_87 ), .Y (n_5504)); + INVX1 g43087(.A (in_slt_736), .Y (n_209)); + INVX1 g42639(.A (oc4_int_set_716), .Y (n_463)); + INVX1 g42446(.A (out_slt_175), .Y (n_208)); + INVX1 g42494(.A (\u10_mem[2]_91 ), .Y (n_6630)); + INVX1 g42481(.A (n_4088), .Y (n_449)); + INVX1 g43129(.A (\u9_mem[1]_147 ), .Y (n_206)); + INVX1 g42167(.A (\u11_mem[2]_89 ), .Y (n_6448)); + INVX1 g41981(.A (\u10_mem[3]_59 ), .Y (n_6575)); + INVX1 g41999(.A (\u9_mem[1]_136 ), .Y (n_204)); + INVX1 g42492(.A (out_slt_172), .Y (n_203)); + INVX1 g42898(.A (\u10_mem[3]_85 ), .Y (n_5510)); + INVX1 g42694(.A (out_slt_126), .Y (n_201)); + INVX1 g42777(.A (out_slt_69), .Y (n_200)); + INVX1 g41921(.A (\u2_to_cnt[3] ), .Y (n_703)); + INVX1 g41810(.A (\u10_mem[3]_82 ), .Y (n_5359)); + INVX1 g42595(.A (\u10_mem[0]_166 ), .Y (n_5955)); + INVX1 g42974(.A (\u9_mem[2]_109 ), .Y (n_198)); + INVX1 g42065(.A (\u11_mem[0]_166 ), .Y (n_5951)); + INVX1 g42830(.A (\u9_mem[1]_145 ), .Y (n_1727)); + INVX1 g41897(.A (oc3_cfg_999), .Y (n_485)); + INVX1 g42353(.A (in_slt_738), .Y (n_197)); + INVX1 g42365(.A (ic2_int_set_724), .Y (n_749)); + INVX1 g41898(.A (\u10_mem[3]_79 ), .Y (n_5516)); + INVX1 g42515(.A (oc0_cfg_969), .Y (n_498)); + INVX1 g41825(.A (out_slt_17), .Y (n_7017)); + INVX1 g42364(.A (out_slt_18), .Y (n_1100)); + INVX1 g42215(.A (\u10_mem[1]_148 ), .Y (n_196)); + INVX1 g42502(.A (\u9_mem[1]_132 ), .Y (n_6654)); + INVX1 g42168(.A (\u10_mem[3]_77 ), .Y (n_5363)); + INVX1 g42340(.A (out_slt_77), .Y (n_195)); + INVX1 g42296(.A (\u11_mem[2]_102 ), .Y (n_6460)); + INVX1 g42587(.A (\u9_mem[0]_177 ), .Y (n_1724)); + INVX1 g43015(.A (ic1_cfg_1039), .Y (n_523)); + INVX1 g42540(.A (\u9_mem[1] ), .Y (n_6956)); + INVX1 g42565(.A (\u6_rp[2] ), .Y (n_192)); + INVX1 g43012(.A (out_slt_166), .Y (n_191)); + INVX1 g42543(.A (\u9_mem[2]_97 ), .Y (n_6647)); + INVX1 g42027(.A (\u11_mem[2]_117 ), .Y (n_190)); + INVX1 g42430(.A (\u11_mem[2]_115 ), .Y (n_188)); + INVX2 g42564(.A (\u6_rp[2] ), .Y (n_782)); + INVX1 g42575(.A (\u10_mem[3]_58 ), .Y (n_6578)); + INVX1 g41885(.A (\u9_mem[2]_94 ), .Y (n_6928)); + INVX1 g42784(.A (ic2_cfg_1049), .Y (n_518)); + INVX1 g42571(.A (\u11_mem[3]_74 ), .Y (n_5580)); + INVX1 g42415(.A (\u11_mem[0]_170 ), .Y (n_1628)); + INVX1 g42470(.A (out_slt_135), .Y (n_186)); + INVX1 g42621(.A (\u11_mem[0]_172 ), .Y (n_1620)); + INVX1 g42835(.A (oc4_int_set_715), .Y (n_668)); + INVX1 g42444(.A (out_slt7), .Y (n_184)); + INVX1 g42114(.A (out_slt_168), .Y (n_183)); + INVX2 g42648(.A (\u4_rp[2] ), .Y (n_445)); + INVX1 g42550(.A (oc4_cfg_1006), .Y (n_528)); + INVX1 g42184(.A (out_slt_144), .Y (n_182)); + INVX1 g43090(.A (\u10_mem[2] ), .Y (n_5998)); + INVX1 g42944(.A (n_8190), .Y (n_921)); + INVX2 g42721(.A (oc0_cfg), .Y (n_459)); + INVX1 g42842(.A (\u3_wp[1] ), .Y (n_626)); + INVX1 g42359(.A (\u10_mem[0]_154 ), .Y (n_6335)); + INVX1 g42476(.A (out_slt_151), .Y (n_181)); + INVX1 g42589(.A (\u9_mem[3]_84 ), .Y (n_5347)); + INVX1 g41850(.A (\u10_mem[0]_175 ), .Y (n_1677)); + INVX1 g42468(.A (crac_out_858), .Y (n_179)); + INVX1 g42582(.A (\u8_wp[1] ), .Y (n_178)); + INVX1 g42322(.A (\u11_mem[2]_88 ), .Y (n_6454)); + INVX1 g42226(.A (crac_out_859), .Y (n_177)); + INVX1 g42962(.A (\u6_wp[1] ), .Y (n_751)); + INVX1 g42033(.A (\u11_mem[3]_76 ), .Y (n_5494)); + INVX1 g42291(.A (n_8536), .Y (n_175)); + INVX1 g42242(.A (\u9_mem[0]_168 ), .Y (n_174)); + INVX1 g42293(.A (\u26_ps_cnt[4] ), .Y (n_515)); + INVX1 g41969(.A (oc3_int_set_714), .Y (n_490)); + INVX1 g41864(.A (\u9_mem[2]_100 ), .Y (n_6641)); + INVX2 g43124(.A (\u4_rp[0] ), .Y (n_6824)); + INVX1 g42438(.A (\u11_mem[2]_91 ), .Y (n_6439)); + INVX1 g42641(.A (n_1819), .Y (n_742)); + INVX1 g43010(.A (\u10_mem[0]_153 ), .Y (n_6337)); + INVX1 g43009(.A (n_1036), .Y (n_715)); + INVX1 g42241(.A (\u11_mem[2]_103 ), .Y (n_5994)); + INVX1 g41955(.A (\u9_mem[1]_134 ), .Y (n_6884)); + INVX1 g42756(.A (oc0_int_set_707), .Y (n_616)); + INVX1 g42081(.A (\u11_mem[3]_70 ), .Y (n_6421)); + INVX1 g42952(.A (\u11_mem[3] ), .Y (n_6554)); + INVX1 g41865(.A (crac_out_860), .Y (n_170)); + INVX1 g42020(.A (\u9_mem[3]_76 ), .Y (n_5294)); + INVX1 g42248(.A (\u10_mem[2]_114 ), .Y (n_2627)); + INVX1 g42335(.A (\u11_mem[3]_57 ), .Y (n_6413)); + INVX1 g42938(.A (\u9_mem[0]_173 ), .Y (n_1733)); + INVX1 g42776(.A (\u9_mem[3]_63 ), .Y (n_6909)); + INVX1 g42803(.A (\u9_mem[1]_121 ), .Y (n_6947)); + INVX1 g42449(.A (n_8565), .Y (n_693)); + INVX1 g43111(.A (\u10_mem[3]_70 ), .Y (n_6588)); + INVX1 g42811(.A (\u11_mem[0]_178 ), .Y (n_1592)); + INVX1 g42500(.A (out_slt_150), .Y (n_167)); + INVX1 g41980(.A (out_slt_109), .Y (n_166)); + INVX1 g42874(.A (\u10_mem[3]_71 ), .Y (n_6585)); + INVX1 g42019(.A (\u11_mem[1]_127 ), .Y (n_5984)); + INVX1 g41809(.A (\u11_mem[2]_97 ), .Y (n_6479)); + INVX1 g42875(.A (out_slt_67), .Y (n_10976)); + INVX1 g42799(.A (out_slt_138), .Y (n_163)); + INVX1 g42900(.A (\u10_mem[1]_149 ), .Y (n_162)); + INVX1 g42966(.A (\u26_ps_cnt[0] ), .Y (n_529)); + INVX1 g41914(.A (out_slt_167), .Y (n_160)); + INVX1 g42570(.A (\u11_mem[3]_73 ), .Y (n_6026)); + INVX1 g43011(.A (\u10_mem[1]_125 ), .Y (n_6406)); + INVX1 g42235(.A (\u10_mem[1] ), .Y (n_5981)); + INVX1 g42472(.A (oc2_cfg_989), .Y (n_524)); + INVX1 g42818(.A (\u2_cnt[2] ), .Y (n_684)); + INVX1 g43049(.A (out_slt_76), .Y (n_157)); + INVX1 g42124(.A (\u11_mem[0] ), .Y (n_6377)); + INVX1 g42482(.A (\u9_mem[0]_178 ), .Y (n_2500)); + INVX1 g42847(.A (\u11_mem[2]_96 ), .Y (n_5969)); + INVX1 g42259(.A (out_slt_86), .Y (n_10788)); + INVX1 g41884(.A (\u11_mem[3]_71 ), .Y (n_6419)); + INVX1 g43001(.A (\u9_mem[2] ), .Y (n_509)); + INVX1 g42663(.A (\u11_mem[2]_101 ), .Y (n_6466)); + INVX1 g42654(.A (out_slt_171), .Y (n_152)); + INVX1 g42791(.A (\u11_wp[2] ), .Y (n_520)); + INVX1 g42585(.A (\u10_mem[1]_130 ), .Y (n_6463)); + INVX1 g41824(.A (\u10_mem[1]_144 ), .Y (n_1676)); + INVX1 g42245(.A (out_slt_176), .Y (n_150)); + INVX1 g42544(.A (\u9_mem[3]_74 ), .Y (n_6089)); + INVX1 g42015(.A (crac_out_851), .Y (n_149)); + INVX1 g42358(.A (\u9_mem[3]_75 ), .Y (n_6087)); + INVX1 g42907(.A (\u10_mem[0]_152 ), .Y (n_6339)); + INVX1 g42516(.A (\u11_mem[0]_159 ), .Y (n_6372)); + INVX1 g42846(.A (\u9_mem[1]_131 ), .Y (n_6534)); + INVX1 g42837(.A (\u10_mem[1]_143 ), .Y (n_147)); + INVX2 g43128(.A (\u4_rp[0] ), .Y (n_145)); + INVX1 g43100(.A (\u10_mem[1]_145 ), .Y (n_143)); + INVX1 g42173(.A (\u9_mem[2]_101 ), .Y (n_6638)); + INVX1 g42234(.A (\u11_mem[2]_104 ), .Y (n_5978)); + INVX1 g42253(.A (\u9_mem[2]_106 ), .Y (n_141)); + INVX1 g42552(.A (\u11_mem[0]_150 ), .Y (n_6388)); + INVX1 g42603(.A (\u3_rp[2] ), .Y (n_601)); + INVX1 g42140(.A (\u11_mem[3]_66 ), .Y (n_6428)); + INVX1 g42535(.A (\u9_mem[3]_79 ), .Y (n_5372)); + INVX1 g42411(.A (\u11_mem[0]_160 ), .Y (n_6370)); + INVX1 g42014(.A (\u10_mem[1]_135 ), .Y (n_501)); + INVX1 g42698(.A (\u4_wp[1] ), .Y (n_444)); + INVX1 g42971(.A (crac_out_856), .Y (n_138)); + INVX1 g42078(.A (\u9_mem[3]_72 ), .Y (n_6922)); + INVX1 g42343(.A (\u10_mem[3]_73 ), .Y (n_6010)); + INVX1 g42022(.A (ic0_cfg_1029), .Y (n_410)); + INVX1 g43068(.A (\u9_mem[3]_86 ), .Y (n_5365)); + INVX1 g42247(.A (\u11_mem[3]_75 ), .Y (n_5582)); + INVX1 g41954(.A (n_8528), .Y (n_924)); + INVX1 g42165(.A (\u11_mem[1] ), .Y (n_6522)); + INVX1 g41930(.A (out_slt_136), .Y (n_134)); + INVX1 g42464(.A (n_8550), .Y (n_465)); + INVX1 g42618(.A (\u9_mem[2]_96 ), .Y (n_6893)); + INVX1 g42200(.A (ic1_cfg_1036), .Y (n_625)); + INVX1 g42851(.A (ic1_cfg_1035), .Y (n_434)); + INVX1 g42579(.A (\u11_mem[0]_179 ), .Y (n_1585)); + INVX1 g42435(.A (n_8526), .Y (n_671)); + INVX1 g42267(.A (crac_out_849), .Y (n_130)); + INVX1 g42416(.A (\u11_mem[2]_105 ), .Y (n_129)); + INVX1 g42074(.A (\u11_mem[0]_176 ), .Y (n_1600)); + INVX1 g42357(.A (oc5_cfg_1016), .Y (n_127)); + INVX1 g42341(.A (\u11_mem[2]_116 ), .Y (n_125)); + INVX1 g41983(.A (n_4734), .Y (n_568)); + INVX1 g42995(.A (oc4_cfg), .Y (n_418)); + INVX1 g41828(.A (\u10_mem[2]_99 ), .Y (n_6666)); + INVX1 g42945(.A (\u11_mem[2]_118 ), .Y (n_122)); + INVX1 g42079(.A (\u9_mem[2]_95 ), .Y (n_6628)); + INVX1 g42053(.A (\u9_rp[0] ), .Y (n_121)); + INVX1 g43085(.A (out_slt_160), .Y (n_120)); + INVX1 g41967(.A (\u11_mem[0]_169 ), .Y (n_1634)); + INVX1 g42088(.A (\u9_mem[1]_126 ), .Y (n_6537)); + INVX2 g43097(.A (\u9_wp[1] ), .Y (n_689)); + INVX1 g42687(.A (\u11_mem[0]_156 ), .Y (n_6347)); + INVX1 g42466(.A (dma_req_o[3]), .Y (n_118)); + INVX1 g42689(.A (out_slt_120), .Y (n_117)); + INVX1 g42123(.A (\u10_mem[2]_89 ), .Y (n_6652)); + INVX1 g42802(.A (\u5_wp[2] ), .Y (n_116)); + INVX1 g42518(.A (oc5_cfg_1019), .Y (n_469)); + INVX1 g42909(.A (\u10_mem[0]_172 ), .Y (n_1242)); + INVX1 g41837(.A (\u2_cnt[4] ), .Y (n_2596)); + INVX1 g43103(.A (\u11_mem[1]_134 ), .Y (n_5990)); + INVX1 g41928(.A (out_slt_119), .Y (n_114)); + INVX1 g42659(.A (out_slt_118), .Y (n_113)); + INVX1 g42693(.A (crac_out_854), .Y (n_112)); + INVX1 g41960(.A (\u11_mem[0]_158 ), .Y (n_5947)); + INVX1 g42099(.A (\u10_mem[0]_170 ), .Y (n_1244)); + INVX1 g42819(.A (out_slt_81), .Y (n_109)); + INVX1 g42753(.A (n_5588), .Y (n_564)); + INVX1 g42219(.A (\u10_mem[0]_176 ), .Y (n_1240)); + INVX1 g41973(.A (\u11_mem[1]_130 ), .Y (n_6515)); + INVX1 g42314(.A (\u11_mem[1]_131 ), .Y (n_6511)); + INVX4 g41823(.A (n_610), .Y (n_2567)); + INVX1 g43016(.A (out_slt_143), .Y (n_10981)); + INVX1 g42519(.A (dma_req_o[2]), .Y (n_105)); + INVX1 g42525(.A (\u11_mem[1]_135 ), .Y (n_5988)); + INVX1 g41991(.A (\u11_mem[0]_162 ), .Y (n_6366)); + INVX1 g42504(.A (out_slt_97), .Y (n_103)); + INVX1 g42032(.A (out_slt_121), .Y (n_102)); + INVX1 g42026(.A (out_slt_124), .Y (n_10988)); + INVX1 g42311(.A (\u9_mem[3]_58 ), .Y (n_6915)); + INVX1 g42191(.A (n_760), .Y (n_680)); + INVX1 g42581(.A (\u11_mem[0]_151 ), .Y (n_6357)); + INVX1 g43109(.A (out_slt_117), .Y (n_101)); + INVX1 g42826(.A (\u10_mem[2]_97 ), .Y (n_6610)); + INVX1 g43023(.A (\u11_mem[1]_128 ), .Y (n_6519)); + INVX1 g42308(.A (\u11_mem[1]_125 ), .Y (n_6548)); + INVX1 g42091(.A (\u10_mem[2]_107 ), .Y (n_98)); + INVX1 g42539(.A (\u11_mem[2] ), .Y (n_419)); + INVX1 g42836(.A (\u10_mem[1]_137 ), .Y (n_96)); + INVX1 g43107(.A (n_1203), .Y (n_605)); + INVX1 g41805(.A (\u4_wp[2] ), .Y (n_95)); + INVX1 g35539(.A (i3_full), .Y (n_632)); + INVX1 g42239(.A (\u10_mem[1]_127 ), .Y (n_6037)); + INVX1 g42501(.A (\u10_mem[1]_131 ), .Y (n_6457)); + INVX1 g42205(.A (\u10_mem[1]_138 ), .Y (n_90)); + INVX1 g42998(.A (\u10_mem[1]_132 ), .Y (n_508)); + INVX1 g42542(.A (\u11_mem[3]_78 ), .Y (n_5488)); + INVX1 g42958(.A (\u11_mem[3]_84 ), .Y (n_5498)); + INVX1 g42025(.A (\u10_mem[1]_140 ), .Y (n_87)); + INVX1 g42876(.A (\u10_mem[2]_101 ), .Y (n_6662)); + INVX1 g42661(.A (out_slt_158), .Y (n_86)); + INVX1 g41861(.A (\u11_mem[2]_92 ), .Y (n_6437)); + INVX1 g41847(.A (out_slt_20), .Y (n_1372)); + INVX1 g42927(.A (out_slt_114), .Y (n_84)); + INVX1 g41974(.A (out_slt_72), .Y (n_82)); + INVX1 g42643(.A (\u11_mem[2]_93 ), .Y (n_6434)); + INVX1 g41970(.A (\u11_mem[2]_107 ), .Y (n_81)); + INVX1 g42762(.A (\u9_mem[0]_152 ), .Y (n_6857)); + INVX1 g42854(.A (out_slt_156), .Y (n_79)); + INVX1 g42586(.A (\u11_mem[3]_83 ), .Y (n_5502)); + INVX1 g42798(.A (\u11_mem[2]_94 ), .Y (n_6530)); + INVX1 g42474(.A (\u11_mem[0]_157 ), .Y (n_6344)); + INVX1 g42596(.A (bit_clk_pad_i), .Y (n_77)); + INVX1 g42439(.A (out_slt_153), .Y (n_76)); + INVX1 g42210(.A (\u9_mem[1]_142 ), .Y (n_1732)); + INVX1 g42567(.A (\u11_mem[3]_67 ), .Y (n_6426)); + INVX1 g42316(.A (n_4736), .Y (n_936)); + INVX1 g41894(.A (\u10_mem[1]_121 ), .Y (n_6415)); + INVX1 g42536(.A (\u9_mem[0]_172 ), .Y (n_1562)); + INVX1 g42557(.A (\u10_mem[1]_133 ), .Y (n_502)); + INVX1 g42344(.A (\u10_mem[1]_142 ), .Y (n_1684)); + INVX1 g42796(.A (ic0_cfg_1026), .Y (n_462)); + INVX1 g42052(.A (oc3_int_set_713), .Y (n_676)); + INVX1 g41794(.A (crac_out_848), .Y (n_71)); + INVX1 g41958(.A (\u7_wp[2] ), .Y (n_1443)); + INVX1 g42922(.A (\u10_mem[2]_103 ), .Y (n_6033)); + INVX1 g41858(.A (\u10_mem[0]_158 ), .Y (n_5962)); + INVX4 g42287(.A (\u6_rp[0] ), .Y (n_6821)); + INVX1 g42029(.A (\u10_mem[0]_157 ), .Y (n_5945)); + INVX1 g43075(.A (\u2_cnt[6] ), .Y (n_711)); + INVX1 g42920(.A (ic2_cfg_1045), .Y (n_431)); + INVX1 g42111(.A (oc0_cfg_966), .Y (n_925)); + INVX1 g42937(.A (oc1_cfg_979), .Y (n_510)); + INVX1 g42631(.A (\u9_mem[3] ), .Y (n_6924)); + INVX1 g41993(.A (ic2_cfg_1046), .Y (n_667)); + INVX1 g42604(.A (\u3_rp[2] ), .Y (n_63)); + INVX1 g41908(.A (\u7_wp[0] ), .Y (n_746)); + INVX1 g41827(.A (\u9_mem[2]_107 ), .Y (n_1744)); + INVX1 g42932(.A (\u10_mem[2]_109 ), .Y (n_2556)); + INVX1 g42256(.A (\u10_mem[2]_92 ), .Y (n_6623)); + INVX1 g42910(.A (\u11_mem[3]_69 ), .Y (n_6424)); + INVX1 g42588(.A (\u11_mem[0]_171 ), .Y (n_1755)); + INVX1 g42680(.A (n_8197), .Y (n_598)); + INVX1 g41956(.A (u14_n_135), .Y (n_1119)); + INVX1 g42062(.A (\u8_wp[0] ), .Y (n_58)); + INVX1 g42236(.A (out_slt_141), .Y (n_57)); + INVX1 g42807(.A (crac_out_855), .Y (n_56)); + INVX1 g42068(.A (\u11_mem[3]_68 ), .Y (n_6604)); + INVX1 g43093(.A (oc2_int_set_711), .Y (n_665)); + INVX1 g42461(.A (\u9_rp[1] ), .Y (n_53)); + INVX1 g42976(.A (\u10_mem[0]_150 ), .Y (n_5949)); + INVX2 g42765(.A (ic0_cfg_1025), .Y (n_836)); + INVX1 g42128(.A (\u9_mem[1]_119 ), .Y (n_6949)); + INVX1 g42207(.A (oc2_cfg_985), .Y (n_544)); + INVX1 g42447(.A (\u11_mem[3]_59 ), .Y (n_6417)); + INVX1 g41962(.A (oc5_int_set_717), .Y (n_611)); + INVX1 g42231(.A (out_slt_23), .Y (n_1374)); + INVX1 g42004(.A (out_slt_19), .Y (n_1355)); + INVX1 g42614(.A (\u9_mem[1]_143 ), .Y (n_45)); + INVX1 g42852(.A (\u10_mem[2]_116 ), .Y (n_42)); + INVX1 g42090(.A (n_8188), .Y (n_670)); + INVX1 g41891(.A (\u11_rp[0] ), .Y (n_487)); + INVX1 g42702(.A (\u10_mem[2]_108 ), .Y (n_39)); + INVX1 g43026(.A (\u9_mem[2]_104 ), .Y (n_6935)); + INVX1 g42009(.A (\u10_mem[0]_165 ), .Y (n_5957)); + INVX1 g42186(.A (\u26_cnt[1] ), .Y (n_37)); + INVX1 g42877(.A (u15_crac_rd), .Y (n_36)); + INVX1 g42355(.A (\u11_mem[0]_153 ), .Y (n_6353)); + INVX1 g42770(.A (\u9_mem[2]_108 ), .Y (n_35)); + INVX1 g42940(.A (\u11_mem[0]_173 ), .Y (n_1615)); + INVX1 g42931(.A (\u11_mem[2]_100 ), .Y (n_461)); + INVX1 g42590(.A (\u11_mem[1]_138 ), .Y (n_1633)); + INVX1 g42323(.A (\u9_mem[3]_81 ), .Y (n_5302)); + INVX1 g42669(.A (\u11_mem[2]_99 ), .Y (n_6471)); + INVX1 g42491(.A (\u10_mem[0]_169 ), .Y (n_1246)); + INVX1 g42218(.A (\u9_mem[0]_155 ), .Y (n_6849)); + INVX1 g42574(.A (\u11_mem[1]_129 ), .Y (n_6517)); + INVX2 g42512(.A (\u4_rp[1] ), .Y (n_551)); + INVX1 g42906(.A (\u9_mem[1]_123 ), .Y (n_6945)); + INVX1 g42793(.A (out_slt_122), .Y (n_22)); + INVX1 g43102(.A (\u11_mem[3]_79 ), .Y (n_5490)); + INVX1 g41807(.A (\u9_mem[0]_166 ), .Y (n_6864)); + INVX1 g42232(.A (\u11_mem[3]_87 ), .Y (n_5522)); + INVX1 g42066(.A (out_slt_103), .Y (n_21)); + INVX1 g42002(.A (\u9_mem[0]_169 ), .Y (n_1742)); + INVX1 g42642(.A (\u9_mem[0]_170 ), .Y (n_1680)); + INVX1 g42299(.A (out_slt_177), .Y (n_19)); + INVX1 g43022(.A (\u9_mem[2]_99 ), .Y (n_6495)); + INVX1 g42968(.A (out_slt_82), .Y (n_16)); + INVX1 g42691(.A (\u10_mem[3]_65 ), .Y (n_6000)); + INVX1 g42338(.A (\u8_rp[3] ), .Y (n_494)); + INVX1 g42916(.A (\u10_mem[2]_90 ), .Y (n_6633)); + INVX1 g42769(.A (\u11_mem[2]_108 ), .Y (n_1627)); + INVX1 g42181(.A (\u11_mem[3]_77 ), .Y (n_5526)); + INVX1 g42182(.A (\u10_mem[2]_111 ), .Y (n_9)); + INVX1 g41961(.A (\u9_mem[0]_158 ), .Y (n_6845)); + INVX1 g42772(.A (\u11_rp[1] ), .Y (n_5)); + INVX1 g42437(.A (\u10_mem[0] ), .Y (n_5959)); + INVX1 g42158(.A (\u11_mem[1]_149 ), .Y (n_1580)); + INVX1 g45344(.A (n_11563), .Y (n_11564)); + CLKBUFX1 g45356(.A (n_11578), .Y (n_11563)); + INVX1 g45357(.A (ic0_cfg), .Y (n_11578)); + INVX1 g45362(.A (n_11586), .Y (n_11585)); + CLKBUFX1 g45364(.A (n_11587), .Y (n_11586)); + INVX2 g45365(.A (n_11579), .Y (n_11587)); + INVX2 g45366(.A (\u6_rp[1] ), .Y (n_11579)); + INVX1 g45378(.A (n_11597), .Y (n_11600)); + CLKBUFX1 g45389(.A (n_11612), .Y (n_11597)); + INVX1 g45390(.A (ic1_cfg), .Y (n_11612)); + INVX1 g45413(.A (n_11762), .Y (n_11772)); + CLKBUFX1 g45417(.A (n_11777), .Y (n_11762)); + INVX1 g45418(.A (ic2_cfg), .Y (n_11777)); + CLKBUFX3 g45429(.A (n_11802), .Y (n_11789)); + INVX4 g45432(.A (n_11797), .Y (n_11798)); + INVX2 g45434(.A (n_11802), .Y (n_11797)); + CLKBUFX3 g45435(.A (n_11802), .Y (n_11804)); + INVX2 g45436(.A (n_692), .Y (n_11802)); + INVX1 g45441(.A (n_11827), .Y (n_11823)); + CLKBUFX1 g45445(.A (n_12335), .Y (n_11827)); + OR2X1 g19(.A (n_1374), .B (n_12340), .Y (n_11841)); + AOI21X1 g30(.A0 (\u4_mem[0]_105 ), .A1 (n_12840), .B0 (n_11842), .Y + (n_11843)); + AND2X1 g34(.A (n_12087), .B (\u4_mem[2]_43 ), .Y (n_11842)); + AOI22X1 g29(.A0 (\u4_mem[3]_136 ), .A1 (n_12744), .B0 (n_12273), .B1 + (\u4_mem[1]_74 ), .Y (n_11846)); + NAND2X2 g33(.A (n_761), .B (n_445), .Y (n_11844)); + NAND2X1 g45447(.A (n_12026), .B (n_12027), .Y (n_11855)); + AOI22X1 g45448(.A0 (\u7_mem[2]_34 ), .A1 (n_12641), .B0 (n_2330), .B1 + (\u7_mem[0]_96 ), .Y (n_12027)); + AOI22X1 g45449(.A0 (\u7_mem[3]_127 ), .A1 (n_1538), .B0 (n_11853), + .B1 (\u7_mem[1]_65 ), .Y (n_12026)); + INVX1 g45450(.A (n_11852), .Y (n_11853)); + INVX4 g35(.A (n_11851), .Y (n_11852)); + INVX2 g36(.A (n_12333), .Y (n_11851)); + INVX1 g45451(.A (n_11852), .Y (n_11856)); + OR2X1 g45452(.A (n_12636), .B (n_12501), .Y (n_11889)); + OR2X1 g32976_dup(.A (n_12636), .B (n_12501), .Y (n_11890)); + OR2X1 g45453(.A (n_9719), .B (n_9668), .Y (n_11891)); + OR2X1 g32970_dup(.A (n_9719), .B (n_9668), .Y (n_11892)); + OR2X1 g45454(.A (n_9717), .B (n_9666), .Y (n_11893)); + OR2X1 g32978_dup(.A (n_9717), .B (n_9666), .Y (n_11894)); + NAND2X1 g41(.A (n_11897), .B (n_11900), .Y (n_11901)); + NAND2X1 g42(.A (n_11895), .B (n_12115), .Y (n_11897)); + NAND4X1 g44(.A (n_2874), .B (n_11737), .C (n_11738), .D (n_1507), .Y + (n_11895)); + NAND2X1 g43(.A (n_11898), .B (n_12664), .Y (n_11900)); + NAND4X1 g45(.A (n_3701), .B (n_3150), .C (n_3383), .D (n_1511), .Y + (n_11898)); + OAI21X1 g16(.A0 (n_11904), .A1 (n_11504), .B0 (n_11905), .Y + (n_11906)); + NAND2X1 g45455(.A (u16_u8_dma_req_r1), .B (n_11903), .Y (n_11904)); + INVX1 g45456(.A (dma_ack_i[8]), .Y (n_11903)); + NAND2X1 g45457(.A (dma_req_o[8]), .B (n_11903), .Y (n_11905)); + NOR2X1 g45458(.A (n_11504), .B (dma_ack_i[8]), .Y (n_11907)); + OAI21X1 g45459(.A0 (n_11908), .A1 (n_11914), .B0 (n_10481), .Y + (n_11919)); + OAI21X1 g49(.A0 (n_5683), .A1 (n_7077), .B0 (n_6220), .Y (n_11908)); + NAND2X1 g45460(.A (n_11911), .B (n_11913), .Y (n_11914)); + NAND3X1 g45461(.A (n_6157), .B (n_6316), .C (n_12535), .Y (n_11911)); + OAI21X1 g45462(.A0 (n_4631), .A1 (n_4630), .B0 (n_11912), .Y + (n_11913)); + AND2X1 g45463(.A (n_634), .B (n_12535), .Y (n_11912)); + OAI21X1 g45464(.A0 (n_11922), .A1 (n_11928), .B0 (n_12149), .Y + (n_12006)); + AOI21X1 g45465(.A0 (n_6322), .A1 (n_6124), .B0 (n_7324), .Y + (n_11922)); + NAND2X1 g45466(.A (n_11923), .B (n_11927), .Y (n_11928)); + NAND2X1 g51(.A (n_12531), .B (n_6246), .Y (n_11923)); + NAND2X1 g45467(.A (n_11925), .B (n_12357), .Y (n_11927)); + NAND3X1 g45468(.A (n_11924), .B (n_11658), .C (n_4251), .Y (n_11925)); + AND2X1 g45469(.A (n_11659), .B (n_2233), .Y (n_11924)); + INVX2 g45472(.A (n_12149), .Y (n_10787)); + INVX4 g45473(.A (n_12357), .Y (n_11934)); + INVX1 g45494(.A (n_12079), .Y (n_12077)); + INVX4 g45496(.A (n_12076), .Y (n_12079)); + INVX4 g45497(.A (n_12076), .Y (n_12087)); + INVX2 g45498(.A (n_12076), .Y (n_12091)); + CLKBUFX3 g45499(.A (n_552), .Y (n_12076)); + NAND4X1 g45509(.A (n_3317), .B (n_2914), .C (n_3396), .D (n_2467), .Y + (n_12111)); + BUFX3 g45511(.A (n_12114), .Y (n_12115)); + NOR2X1 g45512(.A (oc0_cfg_965), .B (n_925), .Y (n_12114)); + NAND4X1 g45513(.A (n_12833), .B (n_12834), .C (n_3019), .D (n_1515), + .Y (n_12116)); + OAI21X1 g45515(.A0 (n_12124), .A1 (n_12125), .B0 (n_12161), .Y + (n_12193)); + AOI21X1 g45516(.A0 (n_12120), .A1 (n_12121), .B0 (n_12640), .Y + (n_12124)); + NAND2X1 g45517(.A (n_6763), .B (\u7_rp[0] ), .Y (n_12120)); + NAND2X1 g48(.A (n_12634), .B (n_6202), .Y (n_12121)); + OAI21X1 g38(.A0 (n_5687), .A1 (n_7088), .B0 (n_6146), .Y (n_12125)); + OAI21X1 g45524(.A0 (n_12135), .A1 (n_12136), .B0 (n_12149), .Y + (n_12140)); + AOI21X1 g45525(.A0 (n_12131), .A1 (n_12132), .B0 (n_12145), .Y + (n_12135)); + NAND2X1 g45526(.A (n_6824), .B (n_6805), .Y (n_12131)); + NAND2X1 g45527(.A (\u4_rp[0] ), .B (n_6180), .Y (n_12132)); + OAI21X1 g45530(.A0 (n_6079), .A1 (n_11934), .B0 (n_12532), .Y + (n_12136)); + OAI21X1 g45534(.A0 (n_12146), .A1 (n_12147), .B0 (n_12149), .Y + (n_12150)); + AOI21X1 g45535(.A0 (n_12142), .A1 (n_12143), .B0 (n_12145), .Y + (n_12146)); + NAND2X1 g45536(.A (n_6790), .B (\u4_rp[0] ), .Y (n_12142)); + NAND2X1 g45537(.A (n_145), .B (n_6803), .Y (n_12143)); + INVX1 g45538(.A (n_12144), .Y (n_12145)); + NOR2X1 g45539(.A (oc1_cfg_975), .B (oc1_cfg_976), .Y (n_12144)); + OAI21X1 g45540(.A0 (n_6078), .A1 (n_11934), .B0 (n_6255), .Y + (n_12147)); + CLKBUFX3 g45541(.A (n_12148), .Y (n_12149)); + NOR2X1 g45542(.A (u14_u1_en_out_l2), .B (n_8670), .Y (n_12148)); + OAI21X1 g45543(.A0 (n_12156), .A1 (n_12157), .B0 (n_12161), .Y + (n_12195)); + AOI21X1 g45544(.A0 (n_12152), .A1 (n_12153), .B0 (n_12640), .Y + (n_12156)); + NAND2X1 g45545(.A (n_6769), .B (\u7_rp[0] ), .Y (n_12152)); + NAND2X1 g45546(.A (n_12634), .B (n_6264), .Y (n_12153)); + OAI21X1 g45549(.A0 (n_5542), .A1 (n_7080), .B0 (n_6200), .Y + (n_12157)); + CLKBUFX3 g45550(.A (n_12503), .Y (n_12161)); + NAND4X1 g45555(.A (n_12164), .B (n_12165), .C (n_12166), .D + (n_12170), .Y (n_12171)); + NAND2X1 g45556(.A (n_12204), .B (\u6_mem[0]_100 ), .Y (n_12164)); + NAND2X1 g45557(.A (n_3474), .B (\u6_mem[2]_38 ), .Y (n_12165)); + NAND2X1 g45558(.A (n_2419), .B (\u6_mem[3]_131 ), .Y (n_12166)); + NAND2X1 g45559(.A (n_12169), .B (\u6_mem[1]_69 ), .Y (n_12170)); + INVX4 g45560(.A (n_12168), .Y (n_12169)); + CLKBUFX2 g45561(.A (n_12167), .Y (n_12168)); + NAND2X2 g45562(.A (n_11587), .B (n_782), .Y (n_12167)); + INVX1 g45563(.A (n_12167), .Y (n_12172)); + BUFX3 g45579(.A (n_12364), .Y (n_12204)); + INVX1 g45581(.A (n_12823), .Y (n_12214)); + INVX2 g45591(.A (n_12384), .Y (n_12244)); + INVX2 g45593(.A (n_12258), .Y (n_12250)); + INVX2 g45594(.A (n_12258), .Y (n_12252)); + INVX1 g45596(.A (n_12250), .Y (n_12256)); + INVX1 g45598(.A (n_12258), .Y (n_12259)); + INVX4 g45599(.A (n_12273), .Y (n_12258)); + INVX1 g45600(.A (n_12261), .Y (n_12262)); + CLKBUFX3 g45601(.A (n_12273), .Y (n_12261)); + INVX2 g45602(.A (n_12269), .Y (n_12265)); + INVX1 g45603(.A (n_12269), .Y (n_12267)); + INVX1 g45604(.A (n_12269), .Y (n_12270)); + INVX2 g45605(.A (n_12273), .Y (n_12269)); + CLKBUFX1 g45606(.A (n_12273), .Y (n_12272)); + INVX4 g45607(.A (n_11844), .Y (n_12273)); + INVX1 g45608(.A (n_12281), .Y (n_12274)); + INVX1 g45611(.A (n_12280), .Y (n_12278)); + CLKBUFX1 g45613(.A (n_12281), .Y (n_12280)); + INVX2 g45614(.A (\u8_rp[2] ), .Y (n_12281)); + INVX4 g45620(.A (n_12303), .Y (n_12291)); + INVX4 g45623(.A (n_12303), .Y (n_12295)); + INVX2 g45624(.A (n_12303), .Y (n_12301)); + INVX4 g45625(.A (n_12304), .Y (n_12303)); + INVX1 g45626(.A (n_637), .Y (n_12304)); + NAND2X1 g9(.A (n_12331), .B (n_12332), .Y (n_12333)); + INVX2 g11(.A (n_12330), .Y (n_12331)); + INVX2 g12(.A (\u7_rp[1] ), .Y (n_12330)); + INVX2 g10(.A (\u7_rp[2] ), .Y (n_12332)); + OR2X1 g18(.A (n_12687), .B (n_12534), .Y (n_12339)); + NOR2X1 g45651(.A (n_1374), .B (n_11507), .Y (n_12334)); + INVX1 g45652(.A (n_12335), .Y (n_12336)); + INVX2 g24(.A (valid_s), .Y (n_12335)); + INVX1 g22(.A (n_12336), .Y (n_12340)); + NAND2X1 g31(.A (n_12355), .B (n_12358), .Y (n_12359)); + NAND2X1 g45662(.A (n_12531), .B (n_12354), .Y (n_12355)); + NAND2X1 g45664(.A (n_11846), .B (n_11843), .Y (n_12354)); + NAND2X1 g32(.A (n_12746), .B (n_12357), .Y (n_12358)); + AND2X1 g37(.A (n_283), .B (oc1_cfg_975), .Y (n_12357)); + NAND4X1 g28(.A (n_12361), .B (n_12362), .C (n_12363), .D (n_12367), + .Y (n_12368)); + NAND2X1 g45667(.A (n_3474), .B (\u6_mem[2]_44 ), .Y (n_12361)); + NAND2X1 g45668(.A (n_12622), .B (\u6_mem[3]_137 ), .Y (n_12362)); + NAND2X1 g45669(.A (\u6_mem[1]_75 ), .B (n_12169), .Y (n_12363)); + NAND2X1 g45670(.A (n_12366), .B (\u6_mem[0]_106 ), .Y (n_12367)); + INVX1 g45671(.A (n_12365), .Y (n_12366)); + INVX2 g45672(.A (n_12364), .Y (n_12365)); + AND2X1 g45673(.A (n_782), .B (n_11579), .Y (n_12364)); + INVX4 g45674(.A (n_12365), .Y (n_12369)); + OAI21X1 g45675(.A0 (n_12371), .A1 (n_11672), .B0 (n_12372), .Y + (n_12373)); + NAND2X1 g17(.A (n_12066), .B (n_12370), .Y (n_12371)); + INVX1 g20(.A (dma_ack_i[6]), .Y (n_12370)); + NAND2X1 g45676(.A (dma_req_o[6]), .B (n_12370), .Y (n_12372)); + NOR2X1 g45677(.A (n_11672), .B (dma_ack_i[6]), .Y (n_12374)); + OAI21X1 g45678(.A0 (n_12376), .A1 (n_11673), .B0 (n_12377), .Y + (n_12378)); + NAND2X1 g45679(.A (n_12067), .B (n_12375), .Y (n_12376)); + INVX1 g45680(.A (dma_ack_i[7]), .Y (n_12375)); + NAND2X1 g45681(.A (dma_req_o[7]), .B (n_12375), .Y (n_12377)); + NOR2X1 g45682(.A (n_11673), .B (dma_ack_i[7]), .Y (n_12379)); + INVX2 g45689(.A (n_12384), .Y (n_12385)); + INVX2 g45690(.A (n_12383), .Y (n_12384)); + NAND2X1 g45691(.A (n_445), .B (n_551), .Y (n_12383)); + INVX4 g45692(.A (n_12385), .Y (n_12389)); + NAND2X2 g45701(.A (n_12399), .B (n_12400), .Y (n_12401)); + INVX1 g45702(.A (n_12581), .Y (n_12399)); + INVX1 g45703(.A (\u5_rp[1] ), .Y (n_12400)); + CLKBUFX1 g45704(.A (n_12400), .Y (n_1033)); + NAND4X1 g45705(.A (n_12403), .B (n_12404), .C (n_12405), .D + (n_12410), .Y (n_12411)); + NAND2X1 g45706(.A (n_4225), .B (\u7_mem[1]_78 ), .Y (n_12403)); + NAND2X1 g45707(.A (n_2491), .B (\u7_mem[0]_109 ), .Y (n_12404)); + NAND2X1 g45708(.A (n_1546), .B (\u7_mem[3]_140 ), .Y (n_12405)); + NAND2X1 g45709(.A (n_12641), .B (\u7_mem[2]_47 ), .Y (n_12410)); + OAI21X1 g45740(.A0 (n_12454), .A1 (n_12460), .B0 (n_10481), .Y + (n_12464)); + OAI21X1 g45741(.A0 (n_5680), .A1 (n_7077), .B0 (n_6188), .Y + (n_12454)); + NAND2X1 g45742(.A (n_12458), .B (n_12459), .Y (n_12460)); + OAI21X1 g45743(.A0 (n_5186), .A1 (n_5187), .B0 (n_12457), .Y + (n_12458)); + AND2X1 g45744(.A (n_634), .B (n_12535), .Y (n_12457)); + NAND3X1 g45747(.A (n_12535), .B (n_6316), .C (n_12111), .Y (n_12459)); + NAND2X1 g45760(.A (n_12479), .B (n_12482), .Y (n_12483)); + OAI21X1 g45761(.A0 (n_5459), .A1 (n_5211), .B0 (n_12478), .Y + (n_12479)); + NOR2X1 g45762(.A (n_12640), .B (n_12634), .Y (n_12478)); + NAND2X1 g45765(.A (n_12480), .B (n_12481), .Y (n_12482)); + NOR2X1 g45766(.A (\u7_rp[0] ), .B (n_12640), .Y (n_12480)); + NAND4X1 g45767(.A (n_4114), .B (n_3098), .C (n_2291), .D (n_1383), .Y + (n_12481)); + OAI21X1 g45779(.A0 (n_12499), .A1 (n_12500), .B0 (n_12504), .Y + (n_12505)); + AOI21X1 g45780(.A0 (n_12495), .A1 (n_12496), .B0 (n_12640), .Y + (n_12499)); + NAND2X1 g45781(.A (n_12634), .B (n_6228), .Y (n_12495)); + NAND2X1 g45782(.A (n_12411), .B (n_6118), .Y (n_12496)); + OAI21X1 g45785(.A0 (n_5542), .A1 (n_7088), .B0 (n_5819), .Y + (n_12500)); + CLKBUFX3 g45786(.A (n_12503), .Y (n_12504)); + CLKBUFX3 g45787(.A (n_12502), .Y (n_12503)); + INVX1 g45788(.A (n_12501), .Y (n_12502)); + OR2X1 g45789(.A (n_11528), .B (n_8663), .Y (n_12501)); + NAND4X1 g45790(.A (n_12506), .B (n_12507), .C (n_12508), .D + (n_12513), .Y (n_12514)); + NAND2X1 g45791(.A (n_4130), .B (\u7_mem[1]_63 ), .Y (n_12506)); + NAND2X1 g45792(.A (n_2330), .B (\u7_mem[0]_94 ), .Y (n_12507)); + NAND2X1 g45793(.A (n_1538), .B (\u7_mem[3]_125 ), .Y (n_12508)); + NAND2X1 g45794(.A (n_12641), .B (\u7_mem[2]_32 ), .Y (n_12513)); + NAND2X1 g45798(.A (n_438), .B (n_12330), .Y (n_12509)); + OAI21X1 g45800(.A0 (n_12520), .A1 (n_12521), .B0 (n_12609), .Y + (n_12813)); + AOI21X1 g45801(.A0 (n_12516), .A1 (n_12517), .B0 (n_12604), .Y + (n_12520)); + NAND2X1 g45802(.A (n_6091), .B (n_12681), .Y (n_12516)); + NAND2X1 g45803(.A (n_5869), .B (n_3559), .Y (n_12517)); + OAI21X1 g45806(.A0 (n_5720), .A1 (n_6995), .B0 (n_5860), .Y + (n_12521)); + NAND2X1 g45810(.A (n_12530), .B (n_12531), .Y (n_12532)); + NAND4X1 g45811(.A (n_12526), .B (n_12527), .C (n_12528), .D + (n_12529), .Y (n_12530)); + NAND2X1 g45812(.A (n_12389), .B (\u4_mem[0]_94 ), .Y (n_12526)); + NAND2X1 g45813(.A (\u4_mem[1]_63 ), .B (n_12252), .Y (n_12527)); + NAND2X1 g45814(.A (n_12087), .B (\u4_mem[2]_32 ), .Y (n_12528)); + NAND2X1 g45815(.A (n_3546), .B (\u4_mem[3]_125 ), .Y (n_12529)); + NOR2X1 g45816(.A (oc1_cfg_975), .B (n_283), .Y (n_12531)); + OAI21X1 g45817(.A0 (n_12533), .A1 (n_12539), .B0 (n_10481), .Y + (n_12543)); + OAI21X1 g45818(.A0 (n_5723), .A1 (n_7077), .B0 (n_6195), .Y + (n_12533)); + NAND2X1 g45819(.A (n_12537), .B (n_12538), .Y (n_12539)); + OAI21X1 g45820(.A0 (n_4601), .A1 (n_4600), .B0 (n_12536), .Y + (n_12537)); + AND2X1 g45821(.A (n_634), .B (n_12535), .Y (n_12536)); + CLKBUFX1 g45822(.A (n_12534), .Y (n_12535)); + AND2X1 g45823(.A (n_257), .B (n_925), .Y (n_12534)); + NAND3X1 g45824(.A (n_6316), .B (n_12535), .C (n_6163), .Y (n_12538)); + INVX2 g45857(.A (\u5_rp[2] ), .Y (n_12581)); + INVX1 g45858(.A (\u5_rp[1] ), .Y (n_12583)); + NOR2X1 g23(.A (n_11128), .B (n_12591), .Y (n_12592)); + CLKBUFX1 g45861(.A (n_12584), .Y (n_12585)); + INVX1 g45862(.A (oc5_cfg), .Y (n_12584)); + AOI21X1 g45863(.A0 (n_12588), .A1 (n_12589), .B0 (n_12590), .Y + (n_12591)); + NAND2X1 g26(.A (n_4829), .B (n_2568), .Y (n_12588)); + AND2X1 g27(.A (n_9703), .B (n_9717), .Y (n_12589)); + NOR2X1 g25(.A (n_12589), .B (n_10663), .Y (n_12590)); + OAI21X1 g45872(.A0 (n_12605), .A1 (n_12606), .B0 (n_12609), .Y + (n_12610)); + AOI21X1 g45873(.A0 (n_12601), .A1 (n_12602), .B0 (n_12604), .Y + (n_12605)); + NAND2X1 g45874(.A (n_3559), .B (n_5867), .Y (n_12601)); + NAND2X1 g45875(.A (n_6091), .B (n_6241), .Y (n_12602)); + INVX1 g45876(.A (n_12603), .Y (n_12604)); + AND2X1 g45877(.A (n_242), .B (n_544), .Y (n_12603)); + OAI21X1 g45878(.A0 (n_5571), .A1 (n_6995), .B0 (n_5862), .Y + (n_12606)); + BUFX3 g45879(.A (n_12608), .Y (n_12609)); + CLKBUFX1 g45880(.A (n_12607), .Y (n_12608)); + NOR2X1 g45881(.A (n_11533), .B (n_8667), .Y (n_12607)); + NAND4X1 g45882(.A (n_12611), .B (n_12612), .C (n_12613), .D + (n_12617), .Y (n_12618)); + NAND2X1 g45883(.A (n_3316), .B (\u3_mem[1]_71 ), .Y (n_12611)); + NAND2X1 g45884(.A (n_12825), .B (\u3_mem[0]_102 ), .Y (n_12612)); + NAND2X1 g45885(.A (n_1517), .B (\u3_mem[3]_133 ), .Y (n_12613)); + NAND2X1 g45886(.A (n_12619), .B (\u3_mem[2]_40 ), .Y (n_12617)); + AND2X1 g45889(.A (n_600), .B (\u3_rp[2] ), .Y (n_12614)); + INVX4 g45890(.A (n_1429), .Y (n_12619)); + NAND3X1 g45891(.A (n_12623), .B (n_12624), .C (n_12625), .Y + (n_12626)); + AOI22X1 g45892(.A0 (\u6_mem[2]_42 ), .A1 (n_2285), .B0 (n_12622), .B1 + (\u6_mem[3]_135 ), .Y (n_12623)); + INVX4 g45893(.A (n_12621), .Y (n_12622)); + INVX4 g45894(.A (n_12620), .Y (n_12621)); + NOR2X1 g45895(.A (n_11579), .B (n_192), .Y (n_12620)); + NAND2X1 g45896(.A (n_12369), .B (\u6_mem[0]_104 ), .Y (n_12624)); + NAND2X1 g45897(.A (n_12169), .B (\u6_mem[1]_73 ), .Y (n_12625)); + NAND2X1 g45898(.A (n_12630), .B (n_12631), .Y (n_12632)); + NAND3X1 g45899(.A (n_12627), .B (n_12636), .C (\u7_rp[0] ), .Y + (n_12630)); + NAND4X1 g45900(.A (n_4175), .B (n_4191), .C (n_2993), .D (n_1339), .Y + (n_12627)); + NAND3X1 g45903(.A (n_12634), .B (n_12636), .C (n_11855), .Y + (n_12631)); + INVX4 g45905(.A (\u7_rp[0] ), .Y (n_12634)); + NAND2X1 g45906(.A (n_12637), .B (n_12638), .Y (n_12639)); + NAND3X1 g45907(.A (n_12635), .B (n_12636), .C (\u7_rp[0] ), .Y + (n_12637)); + NAND4X1 g45908(.A (n_4129), .B (n_4240), .C (n_1807), .D (n_1527), .Y + (n_12635)); + AND2X1 g45909(.A (n_808), .B (n_528), .Y (n_12636)); + NAND3X1 g45910(.A (n_12636), .B (n_12634), .C (n_5818), .Y (n_12638)); + INVX4 g45911(.A (n_12636), .Y (n_12640)); + CLKBUFX3 g45912(.A (n_12662), .Y (n_12641)); + CLKBUFX3 g45914(.A (n_12662), .Y (n_12645)); + INVX2 g45915(.A (n_12659), .Y (n_12650)); + INVX1 g45917(.A (n_12654), .Y (n_12656)); + INVX4 g45919(.A (n_12659), .Y (n_12654)); + INVX2 g45921(.A (n_12662), .Y (n_12659)); + INVX2 g45922(.A (n_12509), .Y (n_12662)); + OAI21X1 g45923(.A0 (n_12663), .A1 (n_12668), .B0 (n_10481), .Y + (n_12672)); + AOI21X1 g45924(.A0 (n_6289), .A1 (n_5762), .B0 (n_7214), .Y + (n_12663)); + NAND2X1 g45925(.A (n_12666), .B (n_12667), .Y (n_12668)); + NAND2X1 g45926(.A (n_12664), .B (n_12755), .Y (n_12666)); + AND2X1 g45927(.A (n_925), .B (oc0_cfg_965), .Y (n_12664)); + NAND2X1 g52(.A (n_6174), .B (n_12115), .Y (n_12667)); + NAND4X1 g45932(.A (n_12674), .B (n_12675), .C (n_12676), .D + (n_12680), .Y (n_12681)); + NAND2X1 g45933(.A (n_3209), .B (\u5_mem[1]_77 ), .Y (n_12674)); + NAND2X1 g45934(.A (n_12823), .B (\u5_mem[2]_46 ), .Y (n_12675)); + NAND2X1 g45935(.A (n_1543), .B (\u5_mem[3]_139 ), .Y (n_12676)); + NAND2X1 g45936(.A (n_12679), .B (\u5_mem[0]_108 ), .Y (n_12680)); + CLKBUFX3 g45937(.A (n_12678), .Y (n_12679)); + INVX2 g45938(.A (n_12677), .Y (n_12678)); + NAND2X1 g45939(.A (n_12583), .B (n_12581), .Y (n_12677)); + INVX1 g45940(.A (n_12678), .Y (n_12682)); + OAI21X1 g45941(.A0 (n_12683), .A1 (n_12686), .B0 (n_12689), .Y + (n_12690)); + AOI21X1 g45942(.A0 (n_6317), .A1 (n_5751), .B0 (n_7214), .Y + (n_12683)); + NAND2X1 g45943(.A (n_12684), .B (n_12685), .Y (n_12686)); + NAND2X1 g45944(.A (n_12664), .B (n_12111), .Y (n_12684)); + NAND2X1 g45945(.A (n_12115), .B (n_12116), .Y (n_12685)); + INVX4 g45946(.A (n_12688), .Y (n_12689)); + CLKBUFX3 g45947(.A (n_12687), .Y (n_12688)); + NAND2X1 g45948(.A (n_12334), .B (n_12336), .Y (n_12687)); + CLKBUFX3 g45962(.A (n_12738), .Y (n_12721)); + INVX4 g45969(.A (n_12738), .Y (n_12735)); + INVX2 g45970(.A (n_602), .Y (n_12738)); + NAND4X1 g45971(.A (n_12739), .B (n_12740), .C (n_12741), .D + (n_12745), .Y (n_12746)); + NAND2X1 g45972(.A (n_12389), .B (\u4_mem[0]_103 ), .Y (n_12739)); + NAND2X1 g39(.A (n_12261), .B (\u4_mem[1]_72 ), .Y (n_12740)); + NAND2X1 g40(.A (\u4_mem[2]_41 ), .B (n_12079), .Y (n_12741)); + NAND2X1 g45973(.A (n_12744), .B (\u4_mem[3]_134 ), .Y (n_12745)); + CLKBUFX3 g45974(.A (n_12743), .Y (n_12744)); + INVX2 g45975(.A (n_12742), .Y (n_12743)); + NAND2X1 g45976(.A (n_521), .B (\u4_rp[2] ), .Y (n_12742)); + INVX1 g45977(.A (n_12743), .Y (n_12747)); + NAND4X1 g45978(.A (n_12748), .B (n_12749), .C (n_12750), .D + (n_12754), .Y (n_12755)); + NAND2X1 g45979(.A (n_12825), .B (\u3_mem[0]_104 ), .Y (n_12748)); + NAND2X1 g45980(.A (n_3207), .B (\u3_mem[2]_42 ), .Y (n_12749)); + NAND2X1 g45981(.A (\u3_mem[3]_135 ), .B (n_2463), .Y (n_12750)); + NAND2X2 g45982(.A (n_12753), .B (\u3_mem[1]_73 ), .Y (n_12754)); + CLKBUFX1 g45983(.A (n_12752), .Y (n_12753)); + INVX2 g45984(.A (n_12751), .Y (n_12752)); + NAND2X1 g45985(.A (n_656), .B (n_601), .Y (n_12751)); + OR2X1 g46001(.A (n_485), .B (n_422), .Y (n_12801)); + OR2X1 g41485_dup(.A (n_485), .B (n_422), .Y (n_12802)); + OR2X1 g46002(.A (n_524), .B (n_447), .Y (n_12803)); + OR2X1 g41423_dup(.A (n_524), .B (n_447), .Y (n_12804)); + INVX8 g46003(.A (n_12401), .Y (n_12823)); + INVX4 g46004(.A (n_12735), .Y (n_12825)); + INVX4 g45968_dup(.A (n_12735), .Y (n_12826)); + INVX4 g46005(.A (n_12244), .Y (n_12839)); + INVX4 g45590_dup(.A (n_12244), .Y (n_12840)); + CLKBUFX1 g46006(.A (n_12846), .Y (n_12845)); + CLKBUFX1 g46007(.A (n_12848), .Y (n_12847)); +endmodule + diff --git a/abc70930/examples/apex4.pla b/abc70930/examples/apex4.pla new file mode 100644 index 00000000..22e7f820 --- /dev/null +++ b/abc70930/examples/apex4.pla @@ -0,0 +1,443 @@ +.i 9 +.o 19 +.p 438 +010110011 0100000000000000011 +100100001 0110000000000000000 +100010100 0100010000000000000 +100101001 0100001000000000000 +001101010 0000001000000001001 +00-0-0001 0000000000001011100 +110101010 0000000000010100000 +010111100 0100000001000000110 +011010111 0100000001000000000 +010111010 0000110000000000000 +110000001 0100000000001010000 +0110-0011 0001100000000000000 +10011-010 0100000000000000000 +101000110 0011000000000000000 +100110110 0000101000000000000 +101110100 0001100000000000000 +111000101 0100000000100000000 +100100100 0000000001100000000 +111001110 0100000000100000000 +111111001 0000000000001100000 +001100100 0000000000100110000 +001101101 0010000000010100000 +-01111101 0100000000000000000 +010001110 0100000010100000000 +001011111 0000010100000000110 +100101110 0100100100000000000 +001011011 0000000010010010000 +011111000 0010100000000000000 +100110100 0000001000001100000 +001101110 0000000100010010000 +010011100 0000000001000110000 +101111101 0000100100000000000 +111010000 0100000000000110000 +101011010 0000010100000000000 +011000001 0000100000000110000 +101101101 0000100001000000000 +011011011 0001000000010010000 +010011111 0000010001000001010 +10111111- 0100000000000000000 +010101010 0010000001000001001 +011101010 0010000000001100000 +11011111- 0100000000000000000 +111111011 0001100000000000000 +001010101 0000010000010101100 +001110111 0010000000000111001 +1001100-1 0010000000000000000 +100100111 0100000000110010000 +011101011 0101000001000000000 +011011101 0000100000010010000 +101110101 0101000001000000000 +001110100 0010000000010011001 +001110010 0001000110000000000 +110011100 0000000000110010000 +110101111 0000001000001100000 +100111111 0001000110000000000 +10-110000 0100000000000010000 +101101100 0100001010000000000 +010000011 0001000010000110000 +-11000011 0001000000000000000 +100001101 0000101100000000000 +010000010 0000100000110100000 +1-0001001 0100100000000000000 +001001110 0001010010000001100 +001110001 0000100011000000000 +00101001- 0000000100000001100 +100100010 0010000001100000000 +011011110 0001110000000000000 +110110000 0000100100001000000 +101000101 0000011000001000000 +100101111 0101010010000000000 +101110110 0100000000110010000 +001110000 0000010001100000000 +011001110 0100000001000110000 +010010100 0000010001100000000 +100010010 0001000001001010000 +100011000 0000100010000110000 +-01001100 0000000000010010000 +001001111 0010100010000001100 +110111110 0001110000000000000 +100110001 0000001110000000000 +001100000 0000101000100000101 +100110101 0000010011000000000 +010010010 0010000000110010000 +111100110 0000010000010010000 +100-10001 0001100000000000000 +100111101 0010010000000110000 +011010100 0001000011000000000 +101011101 0001100000011000000 +010101011 0001001100000001001 +110101100 0001100000000110000 +110101000 0001010001000000000 +001001101 0000101010000001110 +110010100 0000110100000000000 +011000101 0100000001001101100 +111000111 0100001001000000000 +001010000 0010000010001101100 +100011101 0100011010000000000 +1-0110000 0000000000100100000 +10000-011 0001000001000000000 +001011100 0000000011010010000 +101111001 0000000110100000000 +0010100-1 0000000010100000000 +010001-01 0010000000100000000 +110-11011 0000000000010010000 +1110-1011 0000010000000000000 +1001-1011 0000100000100000000 +00110001- 0010000000100000000 +100100110 0101000001010010000 +101010101 0010000000100110000 +-01101011 0001010000000000000 +001001000 0000000011100100000 +110000100 0000010011000000000 +101000-00 0000000010001000000 +010011110 0000000111000001100 +110111100 0000110001000000000 +001101001 0000010100001011010 +10011-001 0010000000100000000 +0100-0001 0000010010000000000 +100111-10 0000100100000000000 +110101101 0010001100000000000 +001101000 0000001010001101100 +-01111011 0001000100000000000 +001000-11 0000000011000000000 +110000101 0000101000010100000 +011100100 0000011001000000000 +011100110 0000100001000110000 +1011-0000 0010000000010000000 +100011011 0010000101001000000 +101-00000 0000001000000100000 +0011-1111 0000001000100000000 +011011100 0010000010010010000 +001010111 0001010001100000000 +110000010 0010000001011000000 +00-000-00 0000000000000010001 +0-1100110 0000000010100000000 +1001010-0 0000000011000000000 +11-001011 0010000000001000000 +011111-01 0011000000000000000 +01-110100 0010000000100000000 +101011001 0000001001001100000 +011101110 0000011000011000000 +101100001 0000000101000110000 +011111011 0010000001011000000 +011101100 0100000011100000000 +1-1001011 0000000010000010000 +-01011010 0000000001100000000 +0-1001011 0000001100000000000 +0110-0000 0000100010000000000 +111001101 0101010010000000000 +111000110 0010000011000000000 +011-00111 0000100010000000000 +01100-011 0000010000100000000 +1101-1011 0000001000000010000 +-11001010 0001010000000000000 +01110011- 0001001000000000000 +100011110 0010110001000000000 +110001-01 0000100100000000000 +011010110 0100000100111000000 +100010110 0001000110010100000 +100001011 0010110000000110000 +110-10010 0000110000000000000 +101-01101 0010010000000000000 +0-1100111 0000000101000000000 +110100-00 0010000000100000000 +01001100- 0000000010010010000 +110101-10 0010000000100000000 +111010100 0000101000001100000 +110-11001 0010000000100000000 +1100-1100 0010010000000000000 +1010101-0 0000010100000000000 +100001111 0010010010001100000 +11000011- 0001000000000110000 +111100011 0000010101000000000 +01010111- 0000010000100001001 +010111111 0010010110000000000 +011110000 0011000010100000000 +111110001 0010000000111000000 +100100011 0000000111100000000 +011100000 0011100001000000000 +011111110 0100001101000000000 +010110101 0010011010000000000 +010100011 0000110010001010000 +111111000 0000010101000000000 +111111101 0010000000111000000 +11101100- 0100000000011000000 +011111100 0001110100000000000 +001111011 0000101010001100000 +-11100001 0010000000100000000 +0111-1000 0000001000100000000 +100100000 0101110000011000000 +010100111 0000100110010100000 +101000010 0001011100000000000 +11001-010 0000001010000000000 +010001000 0010010001001100000 +-11110011 0010000000100000000 +010100101 0000001011100000000 +100--1000 0010000000000000000 +010101000 0001001001000110000 +010010101 0000100101100000110 +111101001 0000001010000110000 +111000100 0101000001000110000 +011001101 0001100100000110000 +001111111 0010010100011000000 +1010-1000 0000001001000000000 +100101100 0001000101010010000 +001110101 0001001110000001001 +0100-101- 0000000010000000000 +011100101 0000110100100000000 +110010001 0001011100000000000 +0-110-010 0000100000000000000 +111001100 0100100100011000000 +101100101 0001000110001100000 +10-001-01 0000000000100000000 +111111010 0000001001001100000 +101111110 0001010010001100000 +1-0001-00 0010000000000000000 +011001000 0001000110001010000 +001--0101 0000000001000000000 +010000101 0100101011000000000 +011011010 0010011000100000000 +110011110 0000111000100000000 +001110011 0010001100010010000 +111010110 0011110000000000000 +11101-111 0010000000100000000 +111011-00 0000100100000000000 +-01-11111 0000000000100000000 +111100111 0001110000100000000 +-10011000 0001110000000000000 +110001110 0001000110011000000 +01011-010 0001000110000000000 +-01100001 0001010000100000000 +010100100 0000000111011000000 +01--00010 0000000100000000000 +011011001 0010101001000000000 +1101110-1 0000000010010010000 +10-10-100 0000010000000000000 +--1011000 0000100000000000000 +-010-0110 0000000001000000000 +10--01011 0000001000000000000 +110110100 0001000110011000000 +100010011 0100010110011000000 +101110010 0000000111100000000 +001001100 0000010110001101110 +110100001 0010000111000000000 +110100011 0010010100001100000 +010100-10 0000010100100000000 +010100000 0000100101001101001 +11101-110 0000001010000000000 +1-01010-1 0000000001000000000 +001111000 0000001101100001001 +00101100- 0010000001100000000 +0100010-0 0000001100100000000 +010000110 0001110011000000000 +001-11110 0000001010100000000 +101101111 0101110000010010000 +-1-011101 0000000010000000000 +00101-101 0000000101100000000 +0101-0010 0010011000000000000 +10100010- 0000100001010000000 +-1011001- 0000000001000000000 +10111100- 0100001001000000000 +1111-1100 0000001100000000000 +10000000- 0000100000110010000 +110100101 0000011101000000000 +010-01111 0000001110000000000 +001010110 0000101000110011111 +001111100 0011011100000000000 +101100-11 0010100010000000000 +11101111- 0000000000110010000 +010111011 0011101001000000000 +11001-1-1 0000000001000000000 +101110111 0010000011010010000 +111001001 0000101001100000000 +0-1001010 0000000111000000000 +100011010 0010101110000000000 +01110100- 0011000001000000000 +11-111-00 0010000000000000000 +11-1-1111 0010000000000000000 +110110-10 0010100010000000000 +011101101 0000001011001010000 +1-110110- 0000010000000000000 +0-1001001 0000000100111000000 +100100101 0011101000010010000 +1-0111011 0100011000010000000 +111110010 0010011100000000000 +11-010-10 0000001000000000000 +111101101 0000101000101100000 +010111001 0000111100100000000 +011001-01 0010001010000000000 +010110001 0001110001011000000 +10100000- 0010000000101100000 +01110-111 0000110001000000000 +111010001 0010000001100110000 +1-1101011 0010010000100000000 +100-11011 0000010010100100000 +100111100 0010100110000110000 +111000000 0010000001110010000 +100010101 0010011101000000000 +01011011- 0000010001010010000 +10100101- 0010000000110010000 +010010110 0001001101100000101 +01111001- 0010000000100110000 +-11000010 0000010001100000000 +101-10001 0010000000110010000 +010000100 0010010101000110000 +10-00-100 0010000000100000000 +110000111 0010111010000000000 +1-00100-0 0010000000100000000 +-100-0000 0010000000100000000 +011000000 0001011101000000000 +011-10011 0000001101000000000 +1111011-0 0000100010100000000 +-11010011 0000010011000000000 +101000111 0010001110100000000 +011010001 0001000101101100000 +1-1100100 0010000101000000000 +010010011 0000000111110010000 +001111010 0000110111000001001 +111-11010 0000100110000000000 +010001011 0000011101011000000 +01110001- 0010000001010010000 +1010--011 0010000000100000000 +010010001 0010001101010010000 +110-01011 0000100110000100000 +10-011001 0001010110000000000 +10-1100-1 0000000001100000000 +010001111 0011110001100000000 +001111001 0000011011100001001 +001110110 0010011101000001001 +0101000-1 0001001101000000000 +01100-01- 0000101000000000000 +110110101 0010101101000000000 +010101100 0010011010001101001 +11001-01- 0010000000100000000 +110001111 0010001010111000000 +010110000 0000111010011001001 +1-1-00011 0010100000000000000 +0101101-0 0000111100000000000 +011010101 0010000011111000000 +110010110 0010000110110010000 +11-01-101 0001000100000000000 +101--0100 0010001000000000000 +001010100 0000001011111001100 +10-000101 0010100101000000000 +101111010 0000101001100110000 +101-01000 0001010110000000000 +111011001 0000111010100000000 +1010--110 0000001100000000000 +01-000110 0010001100100000000 +101010010 0010000111010010000 +11-10-010 0010000000100000000 +1011--011 0000010001000000000 +110110011 0010011100011000000 +110001010 0100111010001100000 +01011-110 0001001010010010000 +110-10111 0001010110000000000 +100011111 0001111000111000000 +10100111- 0000111000100000000 +11111111- 0010001000011000000 +00-0000-- 0000000000000110001 +100111000 0001111010011000000 +011000100 0011101110000000000 +-1100101- 0000000101000000000 +0110-1111 0010001100100000000 +111100000 0001011100010010000 +011111111 0011111000100000000 +1111-100- 0010000000100000000 +100-01010 0100001101100000000 +010010111 0010011101100000000 +1101-1000 0000101110000000000 +111010101 0010001001101100000 +110010-11 0000101011000000000 +1-1100001 0000111010000000000 +111000001 0000000111110010000 +1100--0-0 0000000000100000000 +011001100 0001111000110100000 +001111110 0010110101001010000 +1010-100- 0001110000000000000 +111110000 0010000111001010000 +100010111 0010101101000110000 +011110101 0001111101000000000 +01111110- 0000001011100000000 +-1--00011 0000001000000000000 +011111010 0011010110011000000 +101010111 0000111011100000000 +010111101 0010011100110010000 +-11-01-11 0000000000100000000 +111110100 0000011101010100000 +010101001 0010001111000110000 +1-1011-1- 0010000000000000000 +011110001 0011011100010100000 +100000111 0000011111010010000 +101111100 0010010111100000000 +110100111 0001111001011000000 +101100010 0001011011000110000 +111100-10 0000101011000000000 +101101001 0010101110011000000 +10-000011 0000111010100000000 +11001010- 0010001001010010000 +101100110 0010101101001100000 +101-01110 0001111000100000000 +011010010 0010001101101100000 +10-001110 0001011011000000000 +10000-000 0001011100010010000 +110-11101 0001111000100000000 +101011100 0000101111001010000 +1-0000110 0010001101100000000 +100011100 0011011001101100000 +111110110 0001111001000110000 +0110111-1 0001011101000000000 +010000111 0001001111101100000 +11011000- 0001011011000000000 +101010000 0001101111100000000 +100110111 0011001101101010000 +1101-1001 0010010101100000000 +111100101 0010001110110010000 +110011111 0001101110100110000 +100101101 0010010111110010000 +111001000 0100001111101100000 +0010001-- 0000000011011101110 +010111000 0000011111110010000 +1-0000000 0001101111000000000 +110111010 0011011001110010000 +101101010 0010010111111000000 +011110111 0010101111001100000 +110100110 0000111011101010000 +111110111 0001111111000000000 +01-011000 0001011111000000000 +00-00-0-- 0000000000011001110 +11110-1-0 0001001101000000000 +111110101 0000111011100110000 +001101100 0010011111111000000 +010101101 0001111111001101001 +010001100 0000111111111000011 +111001111 0011101111010100000 +1000000-0 0000111111010010000 +011110110 0001111111101100000 +000------ 0000000000011111111 +.e + diff --git a/abc70930/examples/frg2.blif b/abc70930/examples/frg2.blif new file mode 100644 index 00000000..830c56ec --- /dev/null +++ b/abc70930/examples/frg2.blif @@ -0,0 +1,1867 @@ +.model frg2 +.inputs a b c d e f g h i j k l m n o p q r s t u v w x y z a0 b0 c0 d0 e0 f0 \ +g0 h0 i0 j0 k0 l0 m0 n0 o0 p0 q0 s0 t0 u0 v0 w0 x0 y0 z0 a1 b1 c1 d1 e1 f1 \ +g1 h1 i1 j1 k1 l1 m1 n1 o1 p1 q1 r1 s1 t1 u1 v1 w1 x1 y1 z1 a2 b2 c2 d2 e2 f2 \ +g2 h2 i2 j2 k2 l2 m2 n2 o2 p2 q2 r2 s2 t2 u2 v2 w2 x2 y2 z2 a3 b3 c3 d3 e3 f3 \ +g3 h3 i3 j3 k3 l3 m3 n3 o3 p3 q3 r3 s3 t3 u3 v3 w3 x3 y3 z3 a4 b4 c4 d4 e4 f4 \ +g4 h4 i4 j4 k4 l4 m4 n4 +.outputs o4 p4 q4 r4 s4 t4 u4 v4 w4 x4 y4 z4 a5 b5 c5 d5 e5 f5 g5 h5 i5 j5 k5 \ +l5 m5 n5 o5 p5 q5 r5 s5 t5 u5 v5 w5 x5 y5 z5 a6 b6 c6 d6 e6 f6 g6 h6 i6 j6 k6 \ +l6 m6 n6 o6 p6 q6 r6 s6 t6 u6 v6 w6 x6 y6 z6 a7 b7 c7 d7 e7 f7 g7 h7 i7 j7 k7 \ +l7 m7 n7 o7 p7 q7 r7 s7 t7 u7 v7 w7 x7 y7 z7 a8 b8 c8 d8 e8 f8 g8 h8 i8 j8 k8 \ +l8 m8 n8 o8 p8 q8 r8 s8 t8 u8 v8 w8 x8 y8 z8 a9 b9 c9 d9 e9 f9 g9 h9 i9 j9 k9 \ +l9 m9 n9 o9 p9 q9 r9 s9 t9 u9 v9 w9 +.names g1 o4 +0 1 +.names k0 m0 h33 i33 j33 p4 +-0--0 1 +0-0-0 1 +1--00 1 +--000 1 +.names k0 m0 k33 l33 m33 q4 +-0--0 1 +0-0-0 1 +1--00 1 +--000 1 +.names k0 m0 n33 o33 p33 r4 +-0--0 1 +0-0-0 1 +1--00 1 +--000 1 +.names k0 m0 q33 r33 s33 s4 +-0--0 1 +0-0-0 1 +1--00 1 +--000 1 +.names k0 l0 m3 t33 v4 +--10 1 +11-0 1 +00-0 1 +.names k0 l0 n3 u33 w4 +--10 1 +11-0 1 +00-0 1 +.names k0 l0 o3 v33 x4 +--10 1 +11-0 1 +00-0 1 +.names k0 l0 p3 w33 y4 +--10 1 +11-0 1 +00-0 1 +.names k0 l0 q3 x33 z4 +--10 1 +11-0 1 +00-0 1 +.names k0 l0 r3 y33 a5 +--10 1 +11-0 1 +00-0 1 +.names k0 l0 s3 z33 b5 +--10 1 +11-0 1 +00-0 1 +.names k0 l0 t3 a34 c5 +--10 1 +11-0 1 +00-0 1 +.names m3 m0 d5 +11 1 +.names n3 m0 e5 +11 1 +.names o3 m0 f5 +11 1 +.names p3 m0 g5 +11 1 +.names q3 m0 h5 +11 1 +.names r3 m0 i5 +11 1 +.names s3 m0 j5 +11 1 +.names t3 m0 k5 +11 1 +.names j4 g1 l5 +01 1 +.names b34 n5 +0 1 +.names c34 o5 +0 1 +.names d34 p5 +0 1 +.names e34 q5 +0 1 +.names f34 r5 +0 1 +.names g30 g34 h34 n1 i34 s5 +0--1- 1 +-0-1- 1 +--01- 1 +0---0 1 +-0--0 1 +--0-0 1 +.names g30 g34 h34 n1 i34 t5 +0--1- 1 +-0-1- 1 +--01- 1 +0---0 1 +-0--0 1 +--0-0 1 +.names g30 g34 h34 n1 i34 u5 +0--1- 1 +-0-1- 1 +--01- 1 +0---0 1 +-0--0 1 +--0-0 1 +.names g30 g34 h34 n1 i34 v5 +0--1- 1 +-0-1- 1 +--01- 1 +0---0 1 +-0--0 1 +--0-0 1 +.names g30 g34 h34 n1 i34 w5 +0--1- 1 +-0-1- 1 +--01- 1 +0---0 1 +-0--0 1 +--0-0 1 +.names k34 x5 +0 1 +.names l34 y5 +0 1 +.names m34 z5 +0 1 +.names n34 a6 +0 1 +.names o34 b6 +0 1 +.names p34 c6 +0 1 +.names q34 d6 +0 1 +.names r34 e6 +0 1 +.names s34 f6 +0 1 +.names t34 g6 +0 1 +.names h1 h6 +0 1 +.names i1 i6 +0 1 +.names j1 j6 +0 1 +.names k1 k6 +0 1 +.names l1 l6 +0 1 +.names f1 i4 n6 +11 1 +00 1 +.names c4 b4 v34 o6 +000 1 +.names g15 q0 o0 p6 +001 1 +.names n0 j15 k15 o0 l15 m15 q6 +000--- 1 +---100 1 +.names t15 n0 w15 g1 x15 y15 r6 +0--0-0 1 +-1-0-0 1 +--00-0 1 +0---00 1 +-1--00 1 +--0-00 1 +.names t15 n0 b16 g1 x15 c16 s6 +0--0-0 1 +-1-0-0 1 +--00-0 1 +0---00 1 +-1--00 1 +--0-00 1 +.names t15 n0 f16 g1 x15 g16 t6 +0--0-0 1 +-1-0-0 1 +--00-0 1 +0---00 1 +-1--00 1 +--0-00 1 +.names g1 j16 l1 l16 u6 +-0-0 1 +0-10 1 +.names n0 m1 p0 p16 v6 +-1-0 1 +0-10 1 +.names a17 r16 s16 n1 n0 u16 v16 w6 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 b17 s16 o1 n0 u16 d17 x6 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 g17 s16 p1 n0 u16 i17 y6 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 l17 s16 q1 n0 u16 n17 z6 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 q17 s16 r1 n0 u16 s17 a7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 v17 s16 s1 n0 u16 x17 b7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 a18 s16 t1 n0 u16 c18 c7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 f18 s16 u1 n0 u16 h18 d7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 k18 s16 v1 n0 u16 m18 e7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 p18 s16 w1 n0 u16 r18 f7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 u18 s16 x1 n0 u16 w18 g7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 z18 s16 y1 n0 u16 b19 h7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 e19 s16 z1 n0 u16 g19 i7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 j19 s16 a2 n0 u16 l19 j7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 o19 s16 b2 n0 u16 q19 k7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 t19 s16 c2 n0 u16 v19 l7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 y19 s16 d2 n0 u16 a20 m7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 d20 s16 e2 n0 u16 f20 n7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 i20 s16 f2 n0 u16 k20 o7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 n20 s16 g2 n0 u16 p20 p7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 s20 s16 h2 n0 u16 u20 q7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 x20 s16 i2 n0 u16 z20 r7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names a17 c21 s16 j2 n0 u16 e21 s7 +1--1--0 1 +-0-1--0 1 +--01--0 1 +1---0-0 1 +-0--0-0 1 +--0-0-0 1 +1----00 1 +-0---00 1 +--0--00 1 +.names q0 o0 h21 t7 +010 1 +.names q0 o0 q21 u7 +010 1 +.names q0 o0 x21 v7 +010 1 +.names q0 o0 e22 w7 +010 1 +.names q0 o0 l22 x7 +010 1 +.names q0 o0 s22 y7 +010 1 +.names q0 o0 z22 z7 +010 1 +.names q0 o0 g23 a8 +010 1 +.names q0 o0 n23 b8 +010 1 +.names q0 o0 y23 c8 +010 1 +.names q0 o0 c24 d8 +010 1 +.names q0 o0 g24 e8 +010 1 +.names q0 o0 k24 f8 +010 1 +.names q0 o0 o24 g8 +010 1 +.names q0 o0 s24 h8 +010 1 +.names w24 x24 s23 o0 y24 z24 i8 +000--- 1 +---100 1 +.names a25 b25 c25 o0 d25 e25 j8 +000--- 1 +---100 1 +.names a25 w25 c25 o0 x25 e25 k8 +000--- 1 +---100 1 +.names a25 z25 c25 o0 a26 e25 l8 +000--- 1 +---100 1 +.names a25 c26 c25 o0 d26 e25 m8 +000--- 1 +---100 1 +.names a25 f26 c25 o0 g26 e25 n8 +000--- 1 +---100 1 +.names a25 i26 c25 o0 j26 e25 o8 +000--- 1 +---100 1 +.names a25 l26 c25 o0 m26 e25 p8 +000--- 1 +---100 1 +.names a25 o26 c25 o0 p26 e25 q8 +000--- 1 +---100 1 +.names a25 r26 c25 o0 s26 e25 r8 +000--- 1 +---100 1 +.names a25 u26 c25 o0 v26 e25 s8 +000--- 1 +---100 1 +.names a25 x26 c25 o0 y26 e25 t8 +000--- 1 +---100 1 +.names a25 a27 c25 o0 b27 e25 u8 +000--- 1 +---100 1 +.names a25 d27 c25 o0 e27 e25 v8 +000--- 1 +---100 1 +.names a25 g27 c25 o0 h27 e25 w8 +000--- 1 +---100 1 +.names a25 j27 c25 o0 k27 e25 x8 +000--- 1 +---100 1 +.names a25 m27 c25 o0 n27 e25 y8 +000--- 1 +---100 1 +.names a25 p27 c25 o0 q27 e25 z8 +000--- 1 +---100 1 +.names a25 s27 c25 o0 t27 e25 a9 +000--- 1 +---100 1 +.names a25 v27 c25 o0 w27 e25 b9 +000--- 1 +---100 1 +.names a25 y27 c25 o0 z27 e25 c9 +000--- 1 +---100 1 +.names a25 b28 c25 o0 c28 e25 d9 +000--- 1 +---100 1 +.names a25 e28 c25 o0 f28 e25 e9 +000--- 1 +---100 1 +.names h28 i28 j28 o0 k28 l28 f9 +000--- 1 +---100 1 +.names l4 a17 x3 a29 g9 +--10 1 +10-0 1 +.names y3 d29 o0 e29 h9 +--0- 1 +---0 1 +10-- 1 +.names z3 i29 o0 j29 i9 +--0- 1 +---0 1 +10-- 1 +.names q0 o0 n29 j9 +010 1 +.names x29 y29 z29 o0 a30 b30 c30 k9 +------0 1 +000---- 1 +---100- 1 +.names j30 y29 z29 o0 k30 l30 m30 l9 +------0 1 +000---- 1 +---100- 1 +.names n0 o0 t30 u30 v30 m9 +-100- 1 +01--0 1 +.names e4 b31 o0 c31 n9 +--0- 1 +---0 1 +10-- 1 +.names f4 h31 o0 i31 o9 +--0- 1 +---0 1 +10-- 1 +.names n31 o31 z29 o0 p31 q31 r31 p9 +------0 1 +000---- 1 +---100- 1 +.names y31 a25 z29 o0 z31 a32 c30 q9 +------0 1 +000---- 1 +---100- 1 +.names i4 n1 l4 i32 r9 +1-10 1 +-110 1 +.names k32 l32 j28 o0 m32 n32 s9 +000--- 1 +---100 1 +.names c4 b4 a33 t9 +000 1 +.names m1 c33 u9 +10 1 +.names g15 d33 e33 v9 +0-0 1 +-00 1 +.names k4 a25 w9 +10 1 +.names x0 y0 h1 i1 g35 h35 g15 +-----0 1 +0-1-0- 1 +-0-10- 1 +.names c1 q0 o0 j15 +1-- 1 +-1- 1 +--0 1 +.names t15 e1 d1 k15 +0-- 1 +-1- 1 +--1 1 +.names h1 g1 q0 l15 +0-- 1 +-1- 1 +--1 1 +.names t15 n0 o15 m15 +100 1 +.names d1 e1 c1 o15 +11- 1 +-11 1 +.names l1 k1 p35 t15 +000 1 +.names c1 d1 e1 w15 +00- 1 +0-0 1 +-10 1 +.names t15 e1 n0 x15 +0-- 1 +-1- 1 +--1 1 +.names q0 o0 z15 y15 +1-- 1 +-0- 1 +--0 1 +.names n0 e1 t15 i1 z15 +---1 1 +001- 1 +.names c1 d1 e1 b16 +00- 1 +1-0 1 +-00 1 +.names q0 o0 d16 c16 +1-- 1 +-0- 1 +--0 1 +.names n0 e1 t15 j1 d16 +---1 1 +001- 1 +.names c1 d1 e1 f16 +00- 1 +0-0 1 +-00 1 +.names q0 o0 h16 g16 +1-- 1 +-0- 1 +--0 1 +.names n0 e1 t15 k1 h16 +---1 1 +001- 1 +.names c1 n0 m16 j16 +1-- 1 +-1- 1 +--0 1 +.names n0 e1 t15 q0 o0 l16 +---1- 1 +----0 1 +001-- 1 +.names t15 d1 m16 +10 1 +.names g15 m1 q0 o0 p16 +--1- 1 +---0 1 +01-- 1 +.names l4 o1 r16 +10 1 +.names t15 n0 s16 +0- 1 +-1 1 +.names l4 a17 u16 +0- 1 +-1 1 +.names n1 t15 w16 x16 v16 +---0 1 +000- 1 +.names l4 a17 w16 +10 1 +.names j0 n0 t15 o0 q0 x16 +1--10 1 +-1-10 1 +--010 1 +.names c4 b4 q35 a17 +000 1 +.names l4 p1 b17 +10 1 +.names o1 t15 w16 e17 d17 +---0 1 +000- 1 +.names i0 n0 t15 o0 q0 e17 +1--10 1 +-1-10 1 +--010 1 +.names l4 q1 g17 +10 1 +.names p1 t15 w16 j17 i17 +---0 1 +000- 1 +.names h0 n0 t15 o0 q0 j17 +1--10 1 +-1-10 1 +--010 1 +.names l4 r1 l17 +10 1 +.names q1 t15 w16 o17 n17 +---0 1 +000- 1 +.names g0 n0 t15 o0 q0 o17 +1--10 1 +-1-10 1 +--010 1 +.names l4 s1 q17 +10 1 +.names r1 t15 w16 t17 s17 +---0 1 +000- 1 +.names f0 n0 t15 o0 q0 t17 +1--10 1 +-1-10 1 +--010 1 +.names l4 t1 v17 +10 1 +.names s1 t15 w16 y17 x17 +---0 1 +000- 1 +.names e0 n0 t15 o0 q0 y17 +1--10 1 +-1-10 1 +--010 1 +.names l4 u1 a18 +10 1 +.names t1 t15 w16 d18 c18 +---0 1 +000- 1 +.names d0 n0 t15 o0 q0 d18 +1--10 1 +-1-10 1 +--010 1 +.names l4 v1 f18 +10 1 +.names u1 t15 w16 i18 h18 +---0 1 +000- 1 +.names m0 n0 t15 o0 q0 i18 +1--10 1 +-1-10 1 +--010 1 +.names l4 w1 k18 +10 1 +.names v1 t15 w16 n18 m18 +---0 1 +000- 1 +.names k0 n0 t15 o0 q0 n18 +1--10 1 +-1-10 1 +--010 1 +.names l4 x1 p18 +10 1 +.names w1 t15 w16 s18 r18 +---0 1 +000- 1 +.names l0 n0 t15 o0 q0 s18 +1--10 1 +-1-10 1 +--010 1 +.names l4 y1 u18 +10 1 +.names x1 t15 w16 x18 w18 +---0 1 +000- 1 +.names q n0 t15 o0 q0 x18 +1--10 1 +-1-10 1 +--010 1 +.names l4 z1 z18 +10 1 +.names y1 t15 w16 c19 b19 +---0 1 +000- 1 +.names r n0 t15 o0 q0 c19 +1--10 1 +-1-10 1 +--010 1 +.names l4 a2 e19 +10 1 +.names z1 t15 w16 h19 g19 +---0 1 +000- 1 +.names s n0 t15 o0 q0 h19 +1--10 1 +-1-10 1 +--010 1 +.names l4 b2 j19 +10 1 +.names a2 t15 w16 m19 l19 +---0 1 +000- 1 +.names t n0 t15 o0 q0 m19 +1--10 1 +-1-10 1 +--010 1 +.names l4 c2 o19 +10 1 +.names b2 t15 w16 r19 q19 +---0 1 +000- 1 +.names u n0 t15 o0 q0 r19 +1--10 1 +-1-10 1 +--010 1 +.names l4 d2 t19 +10 1 +.names c2 t15 w16 w19 v19 +---0 1 +000- 1 +.names v n0 t15 o0 q0 w19 +1--10 1 +-1-10 1 +--010 1 +.names l4 e2 y19 +10 1 +.names d2 t15 w16 b20 a20 +---0 1 +000- 1 +.names w n0 t15 o0 q0 b20 +1--10 1 +-1-10 1 +--010 1 +.names l4 f2 d20 +10 1 +.names e2 t15 w16 g20 f20 +---0 1 +000- 1 +.names x n0 t15 o0 q0 g20 +1--10 1 +-1-10 1 +--010 1 +.names l4 g2 i20 +10 1 +.names f2 t15 w16 l20 k20 +---0 1 +000- 1 +.names y n0 t15 o0 q0 l20 +1--10 1 +-1-10 1 +--010 1 +.names l4 h2 n20 +10 1 +.names g2 t15 w16 q20 p20 +---0 1 +000- 1 +.names z n0 t15 o0 q0 q20 +1--10 1 +-1-10 1 +--010 1 +.names l4 i2 s20 +10 1 +.names h2 t15 w16 v20 u20 +---0 1 +000- 1 +.names a0 n0 t15 o0 q0 v20 +1--10 1 +-1-10 1 +--010 1 +.names l4 j2 x20 +10 1 +.names i2 t15 w16 a21 z20 +---0 1 +000- 1 +.names b0 n0 t15 o0 q0 a21 +1--10 1 +-1-10 1 +--010 1 +.names l4 k2 c21 +10 1 +.names j2 t15 w16 f21 e21 +---0 1 +000- 1 +.names c0 n0 t15 o0 q0 f21 +1--10 1 +-1-10 1 +--010 1 +.names m0 s16 i21 a17 j21 k21 l21 h21 +------0 1 +000---- 1 +---000- 1 +.names k0 l0 i a i21 +0--1 1 +-1-1 1 +101- 1 +.names l4 l2 j21 +0- 1 +-1 1 +.names t15 n0 m0 k21 +100 1 +.names m0 n0 t15 a17 l4 k2 l21 +-----1 1 +---01- 1 +001--- 1 +.names m0 s16 r21 a17 s21 k21 t21 q21 +------0 1 +000---- 1 +---000- 1 +.names k0 l0 j b r21 +0--1 1 +-1-1 1 +101- 1 +.names l4 m2 s21 +0- 1 +-1 1 +.names m0 n0 t15 a17 l4 l2 t21 +-----1 1 +---01- 1 +001--- 1 +.names m0 s16 y21 a17 z21 k21 a22 x21 +------0 1 +000---- 1 +---000- 1 +.names k0 l0 k c y21 +0--1 1 +-1-1 1 +101- 1 +.names l4 n2 z21 +0- 1 +-1 1 +.names m0 n0 t15 a17 l4 m2 a22 +-----1 1 +---01- 1 +001--- 1 +.names m0 s16 f22 a17 g22 k21 h22 e22 +------0 1 +000---- 1 +---000- 1 +.names k0 l0 l d f22 +0--1 1 +-1-1 1 +101- 1 +.names l4 o2 g22 +0- 1 +-1 1 +.names m0 n0 t15 a17 l4 n2 h22 +-----1 1 +---01- 1 +001--- 1 +.names m0 s16 m22 a17 n22 k21 o22 l22 +------0 1 +000---- 1 +---000- 1 +.names k0 l0 m e m22 +0--1 1 +-1-1 1 +101- 1 +.names l4 p2 n22 +0- 1 +-1 1 +.names m0 n0 t15 a17 l4 o2 o22 +-----1 1 +---01- 1 +001--- 1 +.names m0 s16 t22 a17 u22 k21 v22 s22 +------0 1 +000---- 1 +---000- 1 +.names k0 l0 n f t22 +0--1 1 +-1-1 1 +101- 1 +.names l4 q2 u22 +0- 1 +-1 1 +.names m0 n0 t15 a17 l4 p2 v22 +-----1 1 +---01- 1 +001--- 1 +.names m0 s16 a23 a17 b23 k21 c23 z22 +------0 1 +000---- 1 +---000- 1 +.names k0 l0 o g a23 +0--1 1 +-1-1 1 +101- 1 +.names l4 r2 b23 +0- 1 +-1 1 +.names m0 n0 t15 a17 l4 q2 c23 +-----1 1 +---01- 1 +001--- 1 +.names m0 s16 h23 a17 i23 k21 j23 g23 +------0 1 +000---- 1 +---000- 1 +.names k0 l0 p h h23 +0--1 1 +-1-1 1 +101- 1 +.names l4 s2 i23 +0- 1 +-1 1 +.names m0 n0 t15 a17 l4 r2 j23 +-----1 1 +---01- 1 +001--- 1 +.names s2 a17 o23 p23 q23 n23 +---00 1 +01--0 1 +0-0-0 1 +-00-0 1 +.names l4 t2 o23 +11 1 +.names n0 m0 w23 p23 +1-- 1 +-1- 1 +--0 1 +.names i r23 s23 l4 s2 t23 q23 +100--- 1 +---010 1 +.names t15 n0 m0 r23 +0-- 1 +-1- 1 +--1 1 +.names k0 l0 s23 +01 1 +10 1 +.names n0 m0 u23 t23 +000 1 +.names k0 l0 t15 u23 +--0 1 +01- 1 +10- 1 +.names k0 l0 t15 w23 +111 1 +001 1 +.names t2 a17 p23 z23 a24 y23 +--0-0 1 +01--0 1 +0--00 1 +-0-00 1 +.names l4 u2 z23 +11 1 +.names j r23 s23 l4 t2 t23 a24 +100--- 1 +---010 1 +.names u2 a17 p23 d24 e24 c24 +--0-0 1 +01--0 1 +0--00 1 +-0-00 1 +.names l4 v2 d24 +11 1 +.names k r23 s23 l4 u2 t23 e24 +100--- 1 +---010 1 +.names v2 a17 p23 h24 i24 g24 +--0-0 1 +01--0 1 +0--00 1 +-0-00 1 +.names l4 w2 h24 +11 1 +.names l r23 s23 l4 v2 t23 i24 +100--- 1 +---010 1 +.names w2 a17 p23 l24 m24 k24 +--0-0 1 +01--0 1 +0--00 1 +-0-00 1 +.names l4 x2 l24 +11 1 +.names m r23 s23 l4 w2 t23 m24 +100--- 1 +---010 1 +.names x2 a17 p23 p24 q24 o24 +--0-0 1 +01--0 1 +0--00 1 +-0-00 1 +.names l4 y2 p24 +11 1 +.names n r23 s23 l4 x2 t23 q24 +100--- 1 +---010 1 +.names y2 a17 p23 t24 u24 s24 +--0-0 1 +01--0 1 +0--00 1 +-0-00 1 +.names l4 z2 t24 +11 1 +.names o r23 s23 l4 y2 t23 u24 +100--- 1 +---010 1 +.names n0 m0 p w24 +1-- 1 +-1- 1 +--0 1 +.names t15 q0 o0 x24 +0-- 1 +-1- 1 +--0 1 +.names z2 q0 y24 +0- 1 +-1 1 +.names m0 s16 s23 l4 a17 z24 +---10 1 +000-- 1 +.names l25 q0 o0 a25 +0-- 1 +-1- 1 +--0 1 +.names k4 b3 j25 b25 +0-- 1 +-0- 1 +--1 1 +.names h1 p25 i1 q25 r25 c25 +----0 1 +10--- 1 +--10- 1 +.names a3 q0 d25 +0- 1 +-1 1 +.names h1 f25 i1 g25 h25 e25 +0-0-0 1 +-00-0 1 +0--00 1 +-0-00 1 +.names j1 i1 o25 f25 +1-- 1 +-1- 1 +--0 1 +.names l1 k1 j1 g25 +1-- 1 +-1- 1 +--1 1 +.names l1 k1 k4 i25 h25 +--0- 1 +---0 1 +11-- 1 +.names l1 j1 j25 k25 i25 +0-00 1 +-000 1 +.names h4 r35 j25 +00 1 +.names k1 j1 l25 m25 k25 +--0- 1 +---0 1 +11-- 1 +.names h1 x0 i1 y0 x34 l25 +----0 1 +10--- 1 +--10- 1 +.names l1 k1 n25 m25 +1-- 1 +-1- 1 +--0 1 +.names j1 i1 h1 n25 +000 1 +.names l1 k1 o25 +00 1 +.names j1 i1 t25 p25 +000 1 +.names l1 k1 j1 q25 +000 1 +.names i1 h1 q25 s25 r25 +1--0 1 +-1-0 1 +--00 1 +.names j1 k1 l1 s25 +11- 1 +1-1 1 +-11 1 +.names l1 k1 t25 +1- 1 +-1 1 +.names k4 c3 j25 w25 +0-- 1 +-0- 1 +--1 1 +.names b3 q0 x25 +0- 1 +-1 1 +.names k4 d3 j25 z25 +0-- 1 +-0- 1 +--1 1 +.names c3 q0 a26 +0- 1 +-1 1 +.names k4 e3 j25 c26 +0-- 1 +-0- 1 +--1 1 +.names d3 q0 d26 +0- 1 +-1 1 +.names k4 f3 j25 f26 +0-- 1 +-0- 1 +--1 1 +.names e3 q0 g26 +0- 1 +-1 1 +.names k4 g3 j25 i26 +0-- 1 +-0- 1 +--1 1 +.names f3 q0 j26 +0- 1 +-1 1 +.names k4 h3 j25 l26 +0-- 1 +-0- 1 +--1 1 +.names g3 q0 m26 +0- 1 +-1 1 +.names k4 i3 j25 o26 +0-- 1 +-0- 1 +--1 1 +.names h3 q0 p26 +0- 1 +-1 1 +.names k4 j3 j25 r26 +0-- 1 +-0- 1 +--1 1 +.names i3 q0 s26 +0- 1 +-1 1 +.names k4 k3 j25 u26 +0-- 1 +-0- 1 +--1 1 +.names j3 q0 v26 +0- 1 +-1 1 +.names k4 l3 j25 x26 +0-- 1 +-0- 1 +--1 1 +.names k3 q0 y26 +0- 1 +-1 1 +.names k4 m3 j25 a27 +0-- 1 +-0- 1 +--1 1 +.names l3 q0 b27 +0- 1 +-1 1 +.names k4 n3 j25 d27 +0-- 1 +-0- 1 +--1 1 +.names m3 q0 e27 +0- 1 +-1 1 +.names k4 o3 j25 g27 +0-- 1 +-0- 1 +--1 1 +.names n3 q0 h27 +0- 1 +-1 1 +.names k4 p3 j25 j27 +0-- 1 +-0- 1 +--1 1 +.names o3 q0 k27 +0- 1 +-1 1 +.names k4 q3 j25 m27 +0-- 1 +-0- 1 +--1 1 +.names p3 q0 n27 +0- 1 +-1 1 +.names k4 r3 j25 p27 +0-- 1 +-0- 1 +--1 1 +.names q3 q0 q27 +0- 1 +-1 1 +.names k4 s3 j25 s27 +0-- 1 +-0- 1 +--1 1 +.names r3 q0 t27 +0- 1 +-1 1 +.names k4 t3 j25 v27 +0-- 1 +-0- 1 +--1 1 +.names s3 q0 w27 +0- 1 +-1 1 +.names k4 u3 j25 y27 +0-- 1 +-0- 1 +--1 1 +.names t3 q0 z27 +0- 1 +-1 1 +.names k4 v3 j25 b28 +0-- 1 +-0- 1 +--1 1 +.names u3 q0 c28 +0- 1 +-1 1 +.names k4 w3 j25 e28 +0-- 1 +-0- 1 +--1 1 +.names v3 q0 f28 +0- 1 +-1 1 +.names q0 o0 h28 +1- 1 +-0 1 +.names k4 j25 l25 i28 +0-- 1 +-1- 1 +--0 1 +.names s0 r28 q25 h1 s28 j28 +0--1- 1 +-0-1- 1 +--01- 1 +0---0 1 +-0--0 1 +--0-0 1 +.names w3 q0 k28 +0- 1 +-1 1 +.names h1 f25 i1 g25 m28 l28 +0-0-0 1 +-00-0 1 +0--00 1 +-0-00 1 +.names k4 j25 n28 m28 +0-- 1 +-1- 1 +--0 1 +.names l1 k1 l25 p28 n28 +0-10 1 +-010 1 +.names i1 h1 g25 q28 p28 +---0 1 +000- 1 +.names k1 l1 j1 q28 +--0 1 +00- 1 +.names i1 h1 r28 +01 1 +.names i1 g25 t0 u28 s28 +0--0 1 +101- 1 +.names u0 w0 j1 o25 v28 w28 u28 +00---0 1 +0-1--0 1 +-00--0 1 +-0-0-0 1 +--10-0 1 +0---00 1 +--0-00 1 +---000 1 +.names l1 k1 v28 +10 1 +.names l1 x28 w28 +00 1 +.names k1 j1 v0 x28 +0-- 1 +-1- 1 +--0 1 +.names l4 x3 a17 b29 a29 +---0 1 +110- 1 +.names n0 t15 o0 q0 b29 +1-10 1 +-010 1 +.names l4 x3 a17 d29 +100 1 +.names t15 n0 q0 f29 e29 +0-00 1 +-100 1 +.names l4 g29 f29 +10 1 +.names y3 x3 a17 g29 +1-- 1 +-1- 1 +--1 1 +.names x3 a17 m29 i29 +000 1 +.names t15 n0 q0 k29 j29 +0-00 1 +-100 1 +.names l4 z3 l29 k29 +100 1 +.names y3 x3 a17 l29 +0-- 1 +-1- 1 +--1 1 +.names l4 y3 m29 +0- 1 +-0 1 +.names o29 p29 s16 a4 n0 q29 r29 n29 +0--0--0 1 +-0-0--0 1 +--00--0 1 +0---0-0 1 +-0--0-0 1 +--0-0-0 1 +0----00 1 +-0---00 1 +--0--00 1 +.names y3 x3 a17 o29 +100 1 +.names l4 a4 z3 p29 +101 1 +.names x3 a17 w29 q29 +1-- 1 +-1- 1 +--0 1 +.names m0 a4 t15 s23 t29 r29 +11--0 1 +1-1-0 1 +-10-0 1 +-1-00 1 +--100 1 +.names t15 n0 u29 v29 t29 +11-- 1 +0-00 1 +.names x3 a17 u29 +1- 1 +-1 1 +.names l4 z3 y3 v29 +0-- 1 +-0- 1 +--0 1 +.names l4 z3 y3 w29 +111 1 +.names o0 g30 h30 x29 +0-- 1 +-0- 1 +--0 1 +.names x3 a17 q0 y29 +1-- 1 +-1- 1 +--1 1 +.names t15 n0 z29 +10 1 +.names b4 q0 a30 +0- 1 +-1 1 +.names a17 e30 f30 t15 n0 b30 +---10 1 +000-- 1 +.names t15 q0 d30 c30 +0-- 1 +-1- 1 +--0 1 +.names o0 n0 m0 d30 +101 1 +.names y3 x3 e30 +0- 1 +-1 1 +.names l4 a4 z3 f30 +0-- 1 +-1- 1 +--0 1 +.names z3 y3 g30 +11 1 +.names l4 b4 a4 h30 +100 1 +.names o0 q30 r30 j30 +0-- 1 +-0- 1 +--0 1 +.names c4 q0 k30 +0- 1 +-1 1 +.names a17 o30 p30 t15 n0 l30 +---10 1 +000-- 1 +.names t15 q0 n30 m30 +0-- 1 +-1- 1 +--0 1 +.names o0 n0 m0 n30 +100 1 +.names z3 y3 x3 o30 +0-- 1 +-0- 1 +--1 1 +.names l4 b4 a4 p30 +0-- 1 +-1- 1 +--1 1 +.names a4 z3 y3 q30 +011 1 +.names l4 c4 b4 r30 +100 1 +.names g1 q0 t30 +1- 1 +-1 1 +.names j25 l25 w30 d4 x30 u30 +---00 1 +010-- 1 +.names t15 q0 v30 +0- 1 +-1 1 +.names k4 d4 w30 +0- 1 +-0 1 +.names k4 j25 l25 x30 +101 1 +.names j25 l25 f31 b31 +010 1 +.names q0 g1 d31 c31 +000 1 +.names j25 l25 e31 t15 n0 d31 +---10 1 +010-- 1 +.names k4 e4 d4 e31 +0-- 1 +-1- 1 +--1 1 +.names k4 d4 f31 +0- 1 +-1 1 +.names j25 l25 m31 h31 +010 1 +.names q0 g1 j31 i31 +000 1 +.names l25 k31 l31 t15 n0 j31 +---10 1 +100-- 1 +.names d4 j25 k31 +1- 1 +-1 1 +.names k4 f4 e4 l31 +0-- 1 +-1- 1 +--0 1 +.names k4 e4 d4 m31 +0-- 1 +-0- 1 +--1 1 +.names o0 v31 w31 n31 +0-- 1 +-0- 1 +--0 1 +.names j25 l25 q0 o31 +1-- 1 +-0- 1 +--1 1 +.names g4 g1 q0 p31 +0-- 1 +-1- 1 +--1 1 +.names l25 k31 u31 t15 n0 q31 +---10 1 +100-- 1 +.names t15 q0 s31 r31 +0-- 1 +-1- 1 +--0 1 +.names o0 t31 s31 +10 1 +.names k0 l0 m0 n0 t31 +---1 1 +011- 1 +101- 1 +.names k4 f4 e4 u31 +0-- 1 +-0- 1 +--0 1 +.names e4 d4 g1 v31 +100 1 +.names k4 g4 f4 w31 +101 1 +.names d32 e32 f32 y31 +0-- 1 +-0- 1 +--0 1 +.names h4 g1 q0 z31 +0-- 1 +-1- 1 +--1 1 +.names l25 b32 c32 t15 n0 a32 +---10 1 +100-- 1 +.names e4 d4 j25 b32 +0-- 1 +-1- 1 +--1 1 +.names k4 g4 f4 c32 +0-- 1 +-1- 1 +--0 1 +.names g1 j25 d32 +00 1 +.names f4 e4 d4 e32 +110 1 +.names k4 h4 g4 f32 +100 1 +.names i4 n1 j32 i32 +--0 1 +11- 1 +.names a17 q0 o0 j32 +001 1 +.names q0 o0 y32 k32 +1-- 1 +-0- 1 +--0 1 +.names g1 j25 l25 l32 +1-- 1 +-1- 1 +--0 1 +.names j4 g1 q0 m32 +0-- 1 +-1- 1 +--1 1 +.names h1 o32 p32 q32 r32 n32 +00--0 1 +0-0-0 1 +1--00 1 +-0-00 1 +--000 1 +.names j1 i1 o32 +00 1 +.names v0 w0 k1 l1 p32 +-00- 1 +0--0 1 +--00 1 +.names i1 s0 q25 q32 +1-- 1 +-0- 1 +--0 1 +.names h1 u0 s32 i1 t32 u32 r32 +-----0 1 +---10- 1 +000--- 1 +.names l1 k1 i1 s32 +1-- 1 +-1- 1 +--1 1 +.names j1 t0 t25 t32 +010 1 +.names n4 k4 w32 u32 +110 1 +.names l1 k1 l25 x32 w32 +--0- 1 +---0 1 +11-- 1 +.names j1 k1 l1 j25 x32 +0--0 1 +-000 1 +.names n4 k4 j4 y32 +110 1 +.names o0 b33 q30 a33 +0-- 1 +-0- 1 +--0 1 +.names m1 q0 b33 +10 1 +.names a17 q0 o0 c33 +1-- 1 +-1- 1 +--0 1 +.names h1 x0 n4 b35 d33 +--0- 1 +---0 1 +10-- 1 +.names l25 d33 q0 o0 e33 +--1- 1 +---0 1 +01-- 1 +.names l0 d3 l3 h33 +00- 1 +1-0 1 +-00 1 +.names l0 d3 l3 i33 +10- 1 +0-0 1 +-00 1 +.names t3 m0 j33 +00 1 +.names l0 c3 k3 k33 +00- 1 +1-0 1 +-00 1 +.names l0 c3 k3 l33 +10- 1 +0-0 1 +-00 1 +.names s3 m0 m33 +00 1 +.names l0 b3 j3 n33 +00- 1 +1-0 1 +-00 1 +.names l0 b3 j3 o33 +10- 1 +0-0 1 +-00 1 +.names r3 m0 p33 +00 1 +.names l0 a3 i3 q33 +00- 1 +1-0 1 +-00 1 +.names l0 a3 i3 r33 +10- 1 +0-0 1 +-00 1 +.names q3 m0 s33 +00 1 +.names k0 l0 m0 e3 t33 +--0- 1 +11-0 1 +00-0 1 +.names k0 l0 m0 f3 u33 +--0- 1 +11-0 1 +00-0 1 +.names k0 l0 m0 g3 v33 +--0- 1 +11-0 1 +00-0 1 +.names k0 l0 m0 h3 w33 +--0- 1 +11-0 1 +00-0 1 +.names k0 l0 m0 i3 x33 +--0- 1 +11-0 1 +00-0 1 +.names k0 l0 m0 j3 y33 +--0- 1 +11-0 1 +00-0 1 +.names k0 l0 m0 k3 z33 +--0- 1 +11-0 1 +00-0 1 +.names k0 l0 m0 l3 a34 +--0- 1 +11-0 1 +00-0 1 +.names k4 h1 n0 b34 +010 1 +.names k4 i1 n0 c34 +010 1 +.names k4 j1 n0 d34 +010 1 +.names k4 k1 n0 e34 +010 1 +.names k4 l1 n0 f34 +010 1 +.names c4 b4 a4 g34 +000 1 +.names f1 i4 h34 +01 1 +10 1 +.names z3 y3 g34 i34 +0-- 1 +-0- 1 +--0 1 +.names k4 m1 h1 k34 +011 1 +.names k4 m1 i1 l34 +011 1 +.names k4 m1 j1 m34 +011 1 +.names k4 m1 k1 n34 +011 1 +.names k4 m1 l1 o34 +011 1 +.names l4 h1 p34 +11 1 +.names l4 i1 q34 +11 1 +.names l4 j1 r34 +11 1 +.names l4 k1 s34 +11 1 +.names l4 l1 t34 +11 1 +.names y3 x3 w34 v34 +0-- 1 +-0- 1 +--0 1 +.names a4 z3 w34 +01 1 +.names z0 j1 a1 k1 b1 l1 x34 +1-1-1- 1 +-01-1- 1 +1--01- 1 +-0-01- 1 +1-1--0 1 +-01--0 1 +1--0-0 1 +-0-0-0 1 +.names i1 y0 j1 z0 d35 b35 +0-0-0 1 +-10-0 1 +0--10 1 +-1-10 1 +.names k1 a1 l1 b1 e35 d35 +----0 1 +10--- 1 +--10- 1 +.names h4 f35 e35 +1- 1 +-0 1 +.names g4 f4 e4 f35 +011 1 +.names f4 e4 o35 g35 +110 1 +.names j1 k1 z0 a1 i35 j35 h35 +----00 1 +00---0 1 +-01--0 1 +0--1-0 1 +--11-0 1 +.names f4 e4 n35 i35 +0-- 1 +-0- 1 +--0 1 +.names b1 n4 l1 i35 k35 j35 +-0--0 1 +---00 1 +0-1-0 1 +.names h4 g4 l35 k35 +000 1 +.names d4 g1 m35 l35 +0-- 1 +-1- 1 +--0 1 +.names f4 e4 m35 +11 1 +.names h4 g4 n35 +00 1 +.names h4 g4 o35 +1- 1 +-1 1 +.names j1 i1 h1 p35 +1-- 1 +-1- 1 +--1 1 +.names y3 x3 w34 q35 +0-- 1 +-1- 1 +--0 1 +.names g4 f4 e4 r35 +1-- 1 +-0- 1 +--0 1 +.names u3 t4 +1 1 +.names v3 u4 +1 1 +.names m4 m5 +1 1 +.names k4 m6 +1 1 +.end diff --git a/abc70930/examples/i10.blif b/abc70930/examples/i10.blif new file mode 100644 index 00000000..98100836 --- /dev/null +++ b/abc70930/examples/i10.blif @@ -0,0 +1,5679 @@ +.model i10 +.inputs V32(0) V32(1) V32(2) V32(3) V56(0) V289(0) V10(0) V13(0) \ + V35(0) V203(0) V288(6) V288(7) V248(0) V249(0) V62(0) V59(0) \ + V174(0) V215(0) V66(0) V70(0) V43(0) V214(0) V37(0) V271(0) V40(0) \ + V45(0) V149(7) V149(6) V149(5) V149(4) V1(0) V7(0) V34(0) V243(0) \ + V244(0) V245(0) V246(0) V247(0) V293(0) V302(0) V270(0) V269(0) \ + V274(0) V202(0) V275(0) V257(7) V257(5) V257(3) V257(1) V257(2) \ + V257(4) V257(6) V9(0) V149(0) V149(1) V149(2) V149(3) V169(1) \ + V165(0) V165(2) V165(4) V165(5) V165(6) V165(7) V165(1) V88(2) \ + V88(3) V55(0) V169(0) V52(0) V5(0) V6(0) V12(0) V11(0) V4(0) \ + V165(3) V51(0) V65(0) V290(0) V279(0) V280(0) V288(4) V288(2) \ + V288(0) V258(0) V229(5) V229(4) V229(3) V229(2) V229(1) V229(0) \ + V223(5) V223(4) V223(3) V223(2) V223(1) V223(0) V189(5) V189(4) \ + V189(3) V189(2) V189(1) V189(0) V183(5) V183(4) V183(3) V183(2) \ + V183(1) V183(0) V239(4) V239(3) V239(2) V239(1) V239(0) V234(4) \ + V234(3) V234(2) V234(1) V234(0) V199(4) V199(3) V199(2) V199(1) \ + V199(0) V194(4) V194(3) V194(2) V194(1) V194(0) V257(0) V32(8) \ + V32(7) V32(6) V32(5) V32(4) V32(11) V32(10) V32(9) V88(1) V88(0) \ + V84(5) V84(4) V84(3) V84(2) V84(1) V84(0) V78(5) V78(4) V2(0) V3(0) \ + V14(0) V213(0) V213(5) V213(4) V213(3) V213(2) V213(1) V268(5) \ + V268(3) V268(1) V268(2) V268(4) V8(0) V60(0) V53(0) V57(0) V109(0) \ + V277(0) V278(0) V259(0) V260(0) V67(0) V68(0) V69(0) V216(0) \ + V175(0) V177(0) V172(0) V171(0) V50(0) V63(0) V71(0) V292(0) \ + V291(0) V91(0) V91(1) V294(0) V207(0) V295(0) V204(0) V205(0) \ + V261(0) V262(0) V100(0) V100(5) V100(4) V100(3) V100(2) V100(1) \ + V240(0) V242(0) V241(0) V33(0) V16(0) V15(0) V101(0) V268(0) \ + V288(1) V288(3) V288(5) V301(0) V108(0) V108(1) V108(2) V108(3) \ + V108(4) V108(5) V124(5) V124(4) V124(3) V124(2) V124(1) V124(0) \ + V132(7) V132(6) V132(5) V132(4) V132(3) V132(2) V132(1) V132(0) \ + V118(5) V118(4) V118(3) V118(2) V118(1) V118(0) V118(7) V118(6) \ + V46(0) V48(0) V102(0) V110(0) V134(1) V134(0) V272(0) V78(2) V78(3) \ + V39(0) V38(0) V42(0) V44(0) V41(0) V78(1) V78(0) V94(0) V94(1) +.outputs V321(2) V356 V357 V373 V375(0) V377 V393(0) V398(0) V410(0) \ + V423(0) V432 V435(0) V500(0) V508(0) V511(0) V512 V527 V537 V538 \ + V539 V540 V541 V542 V543 V544 V545 V546 V547 V548 V572(9) V572(8) \ + V572(7) V572(6) V572(5) V572(4) V572(3) V572(2) V572(1) V572(0) \ + V585(0) V587 V591(0) V597(0) V603(0) V609(0) V620 V621 V630 V634(0) \ + V640(0) V657 V707 V763 V775 V778 V779 V780 V781 V782 V783 V784 V787 \ + V789 V798(0) V801 V802(0) V821(0) V826(0) V966 V986 V1213(11) \ + V1213(10) V1213(9) V1213(8) V1213(7) V1213(6) V1213(5) V1213(4) \ + V1213(3) V1213(2) V1213(1) V1213(0) V1243(9) V1243(8) V1243(7) \ + V1243(6) V1243(5) V1243(4) V1243(3) V1243(2) V1243(1) V1243(0) \ + V1256 V1257 V1258 V1259 V1260 V1261 V1262 V1263 V1264 V1265 V1266 \ + V1267 V1274(0) V1281(0) V1297(4) V1297(3) V1297(2) V1297(1) \ + V1297(0) V1365 V1375 V1378 V1380 V1382 V1384 V1386 V1387 V1392(0) \ + V1423 V1426 V1428 V1429 V1431 V1432 V1439(0) V1440(0) V1451(0) \ + V1459(0) V1467(0) V1470 V1480(0) V1481(0) V1492(0) V1495(0) \ + V1512(3) V1512(2) V1512(1) V1536(0) V1537 V1539 V1552(1) V1552(0) \ + V1613(0) V1613(1) V1620(0) V1629(0) V1645(0) V1652(0) V1669 \ + V1671(0) V1679(0) V1693(0) V1709(4) V1709(3) V1709(2) V1709(1) \ + V1709(0) V1717(0) V1719 V1726(0) V1736 V1741(0) V1745(0) V1757(0) \ + V1758(0) V1759(0) V1760(0) V1771(1) V1771(0) V1781(1) V1781(0) \ + V1829(9) V1829(8) V1829(7) V1829(6) V1829(5) V1829(4) V1829(3) \ + V1829(2) V1829(1) V1829(0) V1832 V1833(0) V1863(0) V1864(0) \ + V1896(0) V1897(0) V1898(0) V1899(0) V1900(0) V1901(0) V1921(5) \ + V1921(4) V1921(3) V1921(2) V1921(1) V1921(0) V1953(1) V1953(7) \ + V1953(6) V1953(5) V1953(4) V1953(3) V1953(2) V1953(0) V1960(1) \ + V1960(0) V1968(0) V1992(1) V1992(0) V650 V651 V652 V653 V654 V655 \ + V656 V1370 V1371 V1372 V1373 V1374 +.names V1243(0) V321(2) +0 1 +.names V451 V322 +0 1 +.names V322 V32(0) V323 +11 1 +.names V446 V327 +0 1 +.names V324 V328 +0 1 +.names V328 V32(1) V327 V329 +111 1 +.names V441 V330 +0 1 +.names V325 V331 +0 1 +.names V331 V330 V32(2) V328 V332 +1111 1 +.names V437 V333 +0 1 +.names V326 V334 +0 1 +.names V334 V328 V32(3) V333 V331 V335 +11111 1 +.names V335 V329 V323 V332 V336(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V1476 V337 +0 1 +.names V695 V338 +0 1 +.names V338 V56(0) V744 V337 V339 +1111 1 +.names V802(0) V721 V340 +11 1 +.names V2011(0) V802(0) V341 +11 1 +.names V339 V342(0) +0 1 +.names V802(0) V343 +0 1 +.names V289(0) V344 +0 1 +.names V56(0) V759(0) V345 +11 1 +.names V345 V346(0) +0 1 +.names V434(0) V1685(0) V347 +11 1 +.names V1685(0) V937(0) V947(0) V348 +111 1 +.names V1685(0) V917(0) V927(0) V349 +111 1 +.names V1685(0) V897(0) V907(0) V350 +111 1 +.names V1685(0) V877(0) V887(0) V351 +111 1 +.names V1685(0) V857(0) V867(0) V352 +111 1 +.names V1685(0) V837(0) V847(0) V353 +111 1 +.names V1685(0) V958(0) V959(0) V354 +111 1 +.names V1685(0) V956(0) V957(0) V355 +111 1 +.names V347 V917(0) V877(0) V837(0) V956(0) V958(0) V857(0) V897(0) \ + V937(0) V356 +111111111 1 +.names V1685(0) V927(0) V887(0) V847(0) V957(0) V959(0) V867(0) \ + V907(0) V947(0) V357 +111111111 1 +.names V947(0) V927(0) V907(0) V887(0) V877(0) V897(0) V917(0) \ + V937(0) V358 +11111111 1 +.names V947(0) V927(0) V867(0) V847(0) V837(0) V857(0) V917(0) \ + V937(0) V359 +11111111 1 +.names V947(0) V907(0) V867(0) V959(0) V958(0) V857(0) V897(0) \ + V937(0) V360 +11111111 1 +.names V348 V361(0) +0 1 +.names V349 V362(0) +0 1 +.names V350 V363(0) +0 1 +.names V351 V364(0) +0 1 +.names V352 V365(0) +0 1 +.names V353 V366(0) +0 1 +.names V354 V367(0) +0 1 +.names V355 V368(0) +0 1 +.names V358 V369(0) +0 1 +.names V359 V370(0) +0 1 +.names V360 V371(0) +0 1 +.names V658(0) V10(0) V372 +11 1 +.names V13(0) V10(0) V373 +11 1 +.names V372 V374(0) +0 1 +.names V789 V1263 V1259 V1387 V780 V778 V787 V1431 V1258 V1425 V1423 \ + V375(0) +----------1 1 +---------1- 1 +--------1-- 1 +-------1--- 1 +------1---- 1 +-----1----- 1 +----1------ 1 +---1------- 1 +--1-------- 1 +-1--------- 1 +1---------- 1 +.names V35(0) V697 V376(0) +-1 1 +1- 1 +.names V203(0) V376(0) V377 +11 1 +.names V701 V766 V378(0) +-1 1 +1- 1 +.names V802(0) V378(0) V379 +11 1 +.names V721 V379 V380(0) +-1 1 +1- 1 +.names V380(0) V381(0) +0 1 +.names V741 V740 V382(0) +-1 1 +1- 1 +.names V362(0) V361(0) V383(0) +-1 1 +1- 1 +.names V364(0) V363(0) V384(0) +-1 1 +1- 1 +.names V366(0) V365(0) V385(0) +-1 1 +1- 1 +.names V368(0) V367(0) V386(0) +-1 1 +1- 1 +.names V383(0) V1838 V387 +11 1 +.names V384(0) V1839 V388 +11 1 +.names V385(0) V1840 V389 +11 1 +.names V386(0) V288(6) V288(7) V390 +111 1 +.names V390 V388 V387 V389 V391(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V394(0) V391(0) V1243(8) V1243(7) V1243(9) V1719 V392 +111111 1 +.names V1572 V392 V1571 V393(0) +--1 1 +-1- 1 +1-- 1 +.names V248(0) V394(0) +0 1 +.names V1719 V248(0) V395 +11 1 +.names V423(0) V395 V396(0) +-1 1 +1- 1 +.names V431 V426 V396(0) V430 V1577 V1575 V1573 V1574 V1576 V1578 \ + V397 +1111111111 1 +.names V397 V398(0) +0 1 +.names V249(0) V399(0) +0 1 +.names V733(0) V730(0) V400 +11 1 +.names V687 V729(0) V401 +11 1 +.names V62(0) V401 V402 +11 1 +.names V1757(0) V403 +0 1 +.names V728 V400 V404(0) +-1 1 +1- 1 +.names V731(0) V515 V734 V405(0) +--1 1 +-1- 1 +1-- 1 +.names V56(0) V404(0) V406 +11 1 +.names V59(0) V405(0) V407 +11 1 +.names V402 V406 V407 V408(0) +--1 1 +-1- 1 +1-- 1 +.names V408(0) V338 V403 V409 +111 1 +.names V409 V410(0) +0 1 +.names V729(0) V687 V411 +11 1 +.names V731(0) V1681(0) V710 V729(0) V721 V412(0) +----1 1 +---1- 1 +--1-- 1 +-1--- 1 +1---- 1 +.names V404(0) V411 V502 V174(0) V413(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V405(0) V1681(0) V414(0) +-1 1 +1- 1 +.names V802(0) V412(0) V415 +11 1 +.names V56(0) V413(0) V416 +11 1 +.names V59(0) V414(0) V417 +11 1 +.names V215(0) V418 +0 1 +.names V338 V66(0) V763 V418 V419 +1111 1 +.names V70(0) V1681(0) V420 +11 1 +.names V1446(0) V2011(0) V421 +11 1 +.names V802(0) V421 V422 +11 1 +.names V422 V1719 V419 V416 V415 V417 V402 V420 V423(0) +-------1 1 +------1- 1 +-----1-- 1 +----1--- 1 +---1---- 1 +--1----- 1 +-1------ 1 +1------- 1 +.names V687 V763 V424(0) +-1 1 +1- 1 +.names V802(0) V424(0) V425 +11 1 +.names V425 V426 +0 1 +.names V1643 V427 +0 1 +.names V1646 V428 +0 1 +.names V1491 V429 +0 1 +.names V43(0) V430 +0 1 +.names V214(0) V431 +0 1 +.names V431 V430 V1685(0) V429 V427 V403 V426 V337 V428 V423(0) \ + V1577 V1575 V1573 V1574 V1576 V1578 V432 +1111111111111111 1 +.names V803(0) V749 V433 +11 1 +.names V433 V434(0) +0 1 +.names V630 V432 V435(0) +-1 1 +1- 1 +.names V37(0) V436(0) +0 1 +.names V1850 V1298 V438 +11 1 +.names V1852 V438 V442 +11 1 +.names V1302 V438 V443 +11 1 +.names V1302 V1852 V444 +11 1 +.names V444 V442 V443 V445(0) +--1 1 +-1- 1 +1-- 1 +.names V1838 V445(0) V447 +11 1 +.names V1307 V445(0) V448 +11 1 +.names V1307 V1838 V449 +11 1 +.names V449 V447 V448 V450(0) +--1 1 +-1- 1 +1-- 1 +.names V330 V333 V453 +11 1 +.names V327 V453 V455 +11 1 +.names V333 V457 +0 1 +.names V452 V458 +0 1 +.names V454 V459 +0 1 +.names V458 V457 V461 +11 1 +.names V459 V461 V463 +11 1 +.names V451 V1852 V2088 V465 +111 1 +.names V464 V2089 V1862(0) V466 +111 1 +.names V465 V466 V467(0) +-1 1 +1- 1 +.names V446 V1852 V2090 V468 +111 1 +.names V462 V2091 V1862(0) V469 +111 1 +.names V468 V469 V470(0) +-1 1 +1- 1 +.names V441 V1852 V2092 V471 +111 1 +.names V460 V2093 V1862(0) V472 +111 1 +.names V471 V472 V473(0) +-1 1 +1- 1 +.names V437 V1852 V2094 V474 +111 1 +.names V457 V2095 V1862(0) V475 +111 1 +.names V474 V475 V476(0) +-1 1 +1- 1 +.names V476(0) V477 +0 1 +.names V473(0) V478 +0 1 +.names V470(0) V479 +0 1 +.names V478 V477 V481 +11 1 +.names V479 V481 V483 +11 1 +.names V451 V1850 V2096 V485 +111 1 +.names V484 V2097 V1861(0) V486 +111 1 +.names V485 V486 V487(0) +-1 1 +1- 1 +.names V446 V1850 V2098 V488 +111 1 +.names V482 V2099 V1861(0) V489 +111 1 +.names V488 V489 V490(0) +-1 1 +1- 1 +.names V441 V1850 V2100 V491 +111 1 +.names V480 V2101 V1861(0) V492 +111 1 +.names V491 V492 V493(0) +-1 1 +1- 1 +.names V437 V1850 V2102 V494 +111 1 +.names V477 V2103 V1861(0) V495 +111 1 +.names V494 V495 V496(0) +-1 1 +1- 1 +.names V271(0) V497 +0 1 +.names V1630(0) V498 +0 1 +.names V498 V497 V499 +11 1 +.names V499 V500(0) +0 1 +.names V733(0) V710 V501 +11 1 +.names V687 V710 V502 +11 1 +.names V611 V769 V501 V721 V727 V503(0) +----1 1 +---1- 1 +--1-- 1 +-1--- 1 +1---- 1 +.names V741 V740 V504(0) +-1 1 +1- 1 +.names V56(0) V503(0) V505 +11 1 +.names V56(0) V504(0) V506 +11 1 +.names V502 V59(0) V507 +11 1 +.names V507 V505 V613 V506 V508(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V509 V510(0) +0 1 +.names V529 V40(0) V511(0) +-1 1 +1- 1 +.names V532(0) V510(0) V512 +11 1 +.names V56(0) V400 V513 +11 1 +.names V728 V56(0) V514 +11 1 +.names V687 V730(0) V515 +11 1 +.names V59(0) V515 V516 +11 1 +.names V733(0) V59(0) V729(0) V517 +111 1 +.names V731(0) V59(0) V518 +11 1 +.names V513 V519 +0 1 +.names V514 V520 +0 1 +.names V516 V521 +0 1 +.names V517 V522 +0 1 +.names V518 V523 +0 1 +.names V402 V524 +0 1 +.names V524 V522 V520 V519 V521 V523 V525 +111111 1 +.names V525 V526 +0 1 +.names V428 V431 V526 V338 V430 V527 +11111 1 +.names V43(0) V528(0) +0 1 +.names V45(0) V528(0) V529 +11 1 +.names V530 V532(0) +0 1 +.names V531 V533(0) +0 1 +.names V56(0) V701 V149(7) V534 +111 1 +.names V1646 V701 V535 +11 1 +.names V535 V534 V536(0) +-1 1 +1- 1 +.names V1213(0) V769 V537 +11 1 +.names V1213(1) V769 V538 +11 1 +.names V1213(2) V769 V539 +11 1 +.names V1213(3) V769 V540 +11 1 +.names V1213(4) V769 V541 +11 1 +.names V1213(5) V769 V542 +11 1 +.names V1213(6) V769 V543 +11 1 +.names V1213(7) V769 V544 +11 1 +.names V1213(8) V769 V545 +11 1 +.names V1213(9) V769 V546 +11 1 +.names V1213(10) V769 V547 +11 1 +.names V1213(11) V769 V548 +11 1 +.names V149(7) V802(0) V727 V2105 V2104 V549 +11111 1 +.names V149(6) V802(0) V727 V2105 V2104 V550 +11111 1 +.names V149(5) V802(0) V727 V2105 V2104 V551 +11111 1 +.names V149(4) V802(0) V727 V2105 V2104 V552 +11111 1 +.names V1884 V2107 V2019(0) V2106 V553 +1111 1 +.names V573 V553 V572(9) +-1 1 +1- 1 +.names V1883 V2107 V2019(0) V2106 V555 +1111 1 +.names V574 V555 V572(8) +-1 1 +1- 1 +.names V1882 V2107 V2019(0) V2106 V557 +1111 1 +.names V575 V557 V572(7) +-1 1 +1- 1 +.names V1881 V2107 V2019(0) V2106 V559 +1111 1 +.names V576 V559 V572(6) +-1 1 +1- 1 +.names V1880 V2107 V2019(0) V2106 V561 +1111 1 +.names V577 V561 V572(5) +-1 1 +1- 1 +.names V1879 V2107 V2019(0) V2106 V563 +1111 1 +.names V578 V563 V572(4) +-1 1 +1- 1 +.names V1878 V2107 V2019(0) V2106 V565 +1111 1 +.names V549 V565 V579 V572(3) +--1 1 +-1- 1 +1-- 1 +.names V1877 V2107 V2019(0) V2106 V567 +1111 1 +.names V550 V567 V580 V572(2) +--1 1 +-1- 1 +1-- 1 +.names V1876 V2107 V2019(0) V2106 V569 +1111 1 +.names V551 V569 V581 V572(1) +--1 1 +-1- 1 +1-- 1 +.names V1875 V2107 V2019(0) V2106 V571 +1111 1 +.names V552 V571 V582 V572(0) +--1 1 +-1- 1 +1-- 1 +.names V1243(9) V802(0) V769 V2108 V2109 V573 +11111 1 +.names V1243(8) V802(0) V769 V2108 V2109 V574 +11111 1 +.names V1243(7) V802(0) V769 V2108 V2109 V575 +11111 1 +.names V1243(6) V802(0) V769 V2108 V2109 V576 +11111 1 +.names V1243(5) V802(0) V769 V2108 V2109 V577 +11111 1 +.names V1243(4) V802(0) V769 V2108 V2109 V578 +11111 1 +.names V1243(3) V802(0) V769 V2108 V2109 V579 +11111 1 +.names V1243(2) V802(0) V769 V2108 V2109 V580 +11111 1 +.names V1243(1) V802(0) V769 V2108 V2109 V581 +11111 1 +.names V1243(0) V802(0) V769 V2108 V2109 V582 +11111 1 +.names V1(0) V583(0) +0 1 +.names V7(0) V584(0) +0 1 +.names V34(0) V585(0) +0 1 +.names V341 V586 +0 1 +.names V588(0) V586 V587 +11 1 +.names V243(0) V588(0) +0 1 +.names V592(0) V243(0) V586 V589 +111 1 +.names V244(0) V588(0) V586 V590 +111 1 +.names V590 V589 V591(0) +-1 1 +1- 1 +.names V244(0) V592(0) +0 1 +.names V243(0) V244(0) V593 +11 1 +.names V598(0) V593 V586 V594 +111 1 +.names V593 V595 +0 1 +.names V245(0) V595 V586 V596 +111 1 +.names V596 V594 V597(0) +-1 1 +1- 1 +.names V245(0) V598(0) +0 1 +.names V593 V245(0) V599 +11 1 +.names V604(0) V599 V586 V600 +111 1 +.names V599 V601 +0 1 +.names V246(0) V601 V586 V602 +111 1 +.names V602 V600 V603(0) +-1 1 +1- 1 +.names V246(0) V604(0) +0 1 +.names V599 V246(0) V605 +11 1 +.names V610(0) V605 V586 V606 +111 1 +.names V605 V607 +0 1 +.names V247(0) V607 V586 V608 +111 1 +.names V608 V606 V609(0) +-1 1 +1- 1 +.names V247(0) V610(0) +0 1 +.names V337 V739 V611 +11 1 +.names V502 V611 V612(0) +-1 1 +1- 1 +.names V741 V62(0) V613 +11 1 +.names V428 V338 V505 V1481(0) V614 +1111 1 +.names V1481(0) V59(0) V612(0) V338 V615 +1111 1 +.names V1481(0) V62(0) V741 V338 V616 +1111 1 +.names V614 V617 +0 1 +.names V615 V618 +0 1 +.names V616 V619 +0 1 +.names V619 V617 V618 V620 +111 1 +.names V533(0) V293(0) V621 +11 1 +.names V533(0) V622(0) +0 1 +.names V745 V62(0) V623 +11 1 +.names V302(0) V624 +0 1 +.names V623 V625 +0 1 +.names V1445 V1647(0) V802(0) V626 +111 1 +.names V59(0) V1445 V1737 V627 +111 1 +.names V745 V56(0) V628 +11 1 +.names V628 V627 V626 V270(0) V629(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V629(0) V624 V625 V630 +111 1 +.names V271(0) V639(0) V269(0) V631 +111 1 +.names V641(0) V639(0) V274(0) V632 +111 1 +.names V632 V631 V633(0) +-1 1 +1- 1 +.names V633(0) V634(0) +0 1 +.names V202(0) V635 +0 1 +.names V642(0) V636 +0 1 +.names V636 V635 V497 V637 +111 1 +.names V639(0) V641(0) V638 +11 1 +.names V637 V639(0) +0 1 +.names V638 V640(0) +0 1 +.names V271(0) V641(0) +0 1 +.names V274(0) V642(0) +0 1 +.names V275(0) V643 +0 1 +.names V257(7) V257(5) V257(3) V257(1) V257(2) V257(4) V257(6) V644 +1111111 1 +.names V257(7) V257(5) V257(3) V257(2) V257(4) V257(6) V645 +111111 1 +.names V257(7) V257(5) V257(3) V257(4) V257(6) V646 +11111 1 +.names V257(7) V257(5) V257(4) V257(6) V647 +1111 1 +.names V257(7) V257(5) V257(6) V648 +111 1 +.names V257(7) V257(6) V649 +11 1 +.names V257(7) V657 +0 1 +.names V13(0) V658(0) +0 1 +.names V9(0) V659(0) +0 1 +.names V149(0) V667(0) +0 1 +.names V149(1) V667(1) +0 1 +.names V149(2) V667(2) +0 1 +.names V149(3) V667(3) +0 1 +.names V149(4) V667(4) +0 1 +.names V149(5) V667(5) +0 1 +.names V149(6) V667(6) +0 1 +.names V149(7) V667(7) +0 1 +.names V149(3) V672(3) +0 1 +.names V149(4) V672(4) +0 1 +.names V149(5) V672(5) +0 1 +.names V149(6) V672(6) +0 1 +.names V149(7) V672(7) +0 1 +.names V667(4) V676(4) +0 1 +.names V667(5) V676(5) +0 1 +.names V667(6) V676(6) +0 1 +.names V667(7) V676(7) +0 1 +.names V149(3) V681(3) +0 1 +.names V149(4) V681(4) +0 1 +.names V149(5) V681(5) +0 1 +.names V149(6) V681(6) +0 1 +.names V149(7) V681(7) +0 1 +.names V667(3) V686(3) +0 1 +.names V667(4) V686(4) +0 1 +.names V667(5) V686(5) +0 1 +.names V667(6) V686(6) +0 1 +.names V667(7) V686(7) +0 1 +.names V1395(0) V169(1) V687 +11 1 +.names V687 V688 +0 1 +.names V165(0) V694(0) +0 1 +.names V165(2) V694(2) +0 1 +.names V165(4) V694(4) +0 1 +.names V165(5) V694(5) +0 1 +.names V165(6) V694(6) +0 1 +.names V165(7) V694(7) +0 1 +.names V694(2) V165(0) V165(1) V695 +111 1 +.names V1747(0) V695 V165(7) V696 +111 1 +.names V203(0) V165(1) V694(0) V165(2) V697 +1111 1 +.names V694(7) V695 V698 +11 1 +.names V698 V699(0) +0 1 +.names V667(2) V667(0) V667(1) V700 +111 1 +.names V667(1) V149(2) V667(0) V701 +111 1 +.names V667(2) V149(1) V667(0) V702 +111 1 +.names V667(1) V149(0) V149(2) V703 +111 1 +.names V149(2) V149(0) V149(1) V704 +111 1 +.names V149(2) V705 +0 1 +.names V705 V149(0) V149(1) V706 +111 1 +.names V667(3) V766 V707 +11 1 +.names V88(2) V709(0) +0 1 +.names V88(3) V709(1) +0 1 +.names V149(3) V766 V710 +11 1 +.names V667(5) V707 V149(4) V711 +111 1 +.names V149(5) V707 V149(4) V712 +111 1 +.names V667(5) V667(4) V707 V709(0) V88(3) V713 +11111 1 +.names V667(5) V667(4) V707 V88(2) V709(1) V714 +11111 1 +.names V667(5) V667(4) V707 V88(2) V88(3) V715 +11111 1 +.names V667(4) V667(3) V766 V149(5) V709(0) V709(1) V716 +111111 1 +.names V667(4) V667(3) V766 V149(5) V709(0) V88(3) V717 +111111 1 +.names V667(4) V667(3) V766 V149(5) V88(2) V709(1) V718 +111111 1 +.names V667(5) V667(4) V707 V709(0) V709(1) V719 +11111 1 +.names V667(4) V667(3) V766 V149(5) V88(2) V88(3) V720 +111111 1 +.names V149(3) V701 V721 +11 1 +.names V667(5) V667(3) V701 V667(4) V722 +1111 1 +.names V149(5) V667(3) V701 V667(4) V723 +1111 1 +.names V667(5) V667(3) V701 V149(4) V724 +1111 1 +.names V149(4) V667(0) V149(1) V149(2) V667(3) V725 +11111 1 +.names V667(4) V667(0) V149(1) V149(2) V667(3) V726 +11111 1 +.names V149(3) V149(2) V149(1) V667(0) V727 +1111 1 +.names V149(5) V667(3) V701 V149(4) V728 +1111 1 +.names V718 V716 V714 V712 V711 V713 V715 V717 V729(0) +-------1 1 +------1- 1 +-----1-- 1 +----1--- 1 +---1---- 1 +--1----- 1 +-1------ 1 +1------- 1 +.names V720 V719 V730(0) +-1 1 +1- 1 +.names V724 V722 V723 V731(0) +--1 1 +-1- 1 +1-- 1 +.names V687 V732 +0 1 +.names V688 V732 V733(0) +-1 1 +1- 1 +.names V729(0) V733(0) V734 +11 1 +.names V676(7) V672(5) V672(3) V702 V672(4) V672(6) V735 +111111 1 +.names V672(7) V672(5) V672(3) V702 V672(4) V676(6) V736 +111111 1 +.names V676(7) V672(5) V672(3) V702 V672(4) V676(6) V737 +111111 1 +.names V672(7) V676(5) V672(3) V702 V672(4) V672(6) V738 +111111 1 +.names V676(7) V676(5) V672(3) V702 V672(4) V672(6) V739 +111111 1 +.names V672(7) V676(5) V672(3) V702 V672(4) V676(6) V740 +111111 1 +.names V676(7) V676(5) V672(3) V702 V672(4) V676(6) V741 +111111 1 +.names V672(7) V672(5) V672(3) V702 V676(4) V672(6) V742 +111111 1 +.names V686(7) V681(5) V681(3) V702 V686(4) V681(6) V743 +111111 1 +.names V681(7) V681(5) V681(3) V702 V686(4) V686(6) V744 +111111 1 +.names V686(7) V681(5) V681(3) V702 V686(4) V686(6) V745 +111111 1 +.names V686(7) V686(5) V681(3) V702 V686(4) V681(6) V746 +111111 1 +.names V681(7) V686(5) V681(3) V702 V686(4) V686(6) V747 +111111 1 +.names V686(7) V686(5) V681(3) V702 V686(4) V686(6) V748 +111111 1 +.names V681(7) V681(5) V686(3) V702 V681(4) V681(6) V749 +111111 1 +.names V686(7) V681(5) V686(3) V702 V681(4) V681(6) V750 +111111 1 +.names V681(7) V681(5) V686(3) V702 V681(4) V686(6) V751 +111111 1 +.names V750 V752 +0 1 +.names V751 V753 +0 1 +.names V749 V754 +0 1 +.names V754 V752 V702 V686(3) V753 V755 +11111 1 +.names V681(7) V681(5) V681(3) V702 V681(4) V681(6) V756 +111111 1 +.names V681(7) V681(3) V686(4) V702 V686(5) V681(6) V757 +111111 1 +.names V757 V755 V756 V758(0) +--1 1 +-1- 1 +1-- 1 +.names V748 V747 V759(0) +-1 1 +1- 1 +.names V55(0) V760 +0 1 +.names V760 V759(0) V343 V761 +111 1 +.names V725 V700 V761 V762(0) +--1 1 +-1- 1 +1-- 1 +.names V169(0) V762(0) V1618 V1617 V1619 V763 +11111 1 +.names V763 V764(0) +0 1 +.names V174(0) V765(0) +0 1 +.names V700 V765(0) V766 +11 1 +.names V747 V765(0) V767 +11 1 +.names V748 V765(0) V768 +11 1 +.names V725 V765(0) V769 +11 1 +.names V758(0) V770 +0 1 +.names V703 V771 +0 1 +.names V706 V772 +0 1 +.names V704 V773 +0 1 +.names V773 V771 V770 V772 V774 +1111 1 +.names V70(0) V1674(0) V763 V964 V498 V775 +11111 1 +.names V765(0) V345 V776 +11 1 +.names V776 V52(0) V777(0) +-1 1 +1- 1 +.names V5(0) V9(0) V778 +11 1 +.names V372 V6(0) V779 +11 1 +.names V9(0) V6(0) V780 +11 1 +.names V777(0) V12(0) V6(0) V781 +111 1 +.names V372 V7(0) V782 +11 1 +.names V5(0) V11(0) V783 +11 1 +.names V7(0) V11(0) V784 +11 1 +.names V584(0) V785 +0 1 +.names V659(0) V786 +0 1 +.names V786 V785 V787 +11 1 +.names V13(0) V1565(0) V788(0) +-1 1 +1- 1 +.names V9(0) V788(0) V4(0) V789 +111 1 +.names V1864(0) V758(0) V790 +11 1 +.names V790 V791 +0 1 +.names V774 V792 +0 1 +.names V1681(0) V793 +0 1 +.names V793 V791 V792 V794 +111 1 +.names V794 V795 +0 1 +.names V817(0) V796 +0 1 +.names V498 V795 V796 V797 +111 1 +.names V797 V798(0) +0 1 +.names V70(0) V694(5) V165(3) V694(4) V694(6) V799 +11111 1 +.names V759(0) V800(0) +0 1 +.names V800(0) V799 V801 +11 1 +.names V52(0) V51(0) V802(0) +-1 1 +1- 1 +.names V802(0) V803(0) +0 1 +.names V740 V804 +0 1 +.names V739 V805 +0 1 +.names V805 V804 V806 +11 1 +.names V696 V302(0) V698 V2002(0) V807(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V65(0) V741 V808 +11 1 +.names V806 V809 +0 1 +.names V1275(0) V810 +0 1 +.names V810 V809 V811 +11 1 +.names V981 V808 V811 V812(0) +--1 1 +-1- 1 +1-- 1 +.names V697 V807(0) V813(0) +-1 1 +1- 1 +.names V699(0) V812(0) V1746(0) V814 +111 1 +.names V1737 V813(0) V815 +11 1 +.names V338 V290(0) V816 +11 1 +.names V816 V302(0) V289(0) V814 V815 V214(0) V696 V817(0) +------1 1 +-----1- 1 +----1-- 1 +---1--- 1 +--1---- 1 +-1----- 1 +1------ 1 +.names V149(5) V340 V818 +11 1 +.names V340 V819 +0 1 +.names V822(0) V819 V820 +11 1 +.names V820 V818 V821(0) +-1 1 +1- 1 +.names V279(0) V822(0) +0 1 +.names V149(4) V340 V823 +11 1 +.names V827(0) V820 V824 +11 1 +.names V280(0) V819 V279(0) V825 +111 1 +.names V825 V823 V824 V826(0) +--1 1 +-1- 1 +1-- 1 +.names V280(0) V827(0) +0 1 +.names V828 V832(0) +0 1 +.names V829 V833(0) +0 1 +.names V830 V834(0) +0 1 +.names V831 V835(0) +0 1 +.names V434(0) V835(0) V833(0) V832(0) V834(0) V1855(0) V836 +111111 1 +.names V836 V837(0) +0 1 +.names V838 V842(0) +0 1 +.names V839 V843(0) +0 1 +.names V840 V844(0) +0 1 +.names V841 V845(0) +0 1 +.names V434(0) V845(0) V843(0) V842(0) V844(0) V288(4) V846 +111111 1 +.names V846 V847(0) +0 1 +.names V848 V852(0) +0 1 +.names V849 V853(0) +0 1 +.names V850 V854(0) +0 1 +.names V851 V855(0) +0 1 +.names V434(0) V855(0) V853(0) V852(0) V854(0) V1840 V856 +111111 1 +.names V856 V857(0) +0 1 +.names V858 V862(0) +0 1 +.names V859 V863(0) +0 1 +.names V860 V864(0) +0 1 +.names V861 V865(0) +0 1 +.names V434(0) V865(0) V863(0) V862(0) V864(0) V1840 V866 +111111 1 +.names V866 V867(0) +0 1 +.names V868 V872(0) +0 1 +.names V869 V873(0) +0 1 +.names V870 V874(0) +0 1 +.names V871 V875(0) +0 1 +.names V434(0) V875(0) V873(0) V872(0) V874(0) V1854(0) V876 +111111 1 +.names V876 V877(0) +0 1 +.names V878 V882(0) +0 1 +.names V879 V883(0) +0 1 +.names V880 V884(0) +0 1 +.names V881 V885(0) +0 1 +.names V434(0) V885(0) V883(0) V882(0) V884(0) V288(2) V886 +111111 1 +.names V886 V887(0) +0 1 +.names V888 V892(0) +0 1 +.names V889 V893(0) +0 1 +.names V890 V894(0) +0 1 +.names V891 V895(0) +0 1 +.names V434(0) V895(0) V893(0) V892(0) V894(0) V1839 V896 +111111 1 +.names V896 V897(0) +0 1 +.names V898 V902(0) +0 1 +.names V899 V903(0) +0 1 +.names V900 V904(0) +0 1 +.names V901 V905(0) +0 1 +.names V434(0) V905(0) V903(0) V902(0) V904(0) V1839 V906 +111111 1 +.names V906 V907(0) +0 1 +.names V908 V912(0) +0 1 +.names V909 V913(0) +0 1 +.names V910 V914(0) +0 1 +.names V911 V915(0) +0 1 +.names V434(0) V915(0) V913(0) V912(0) V914(0) V1853(0) V916 +111111 1 +.names V916 V917(0) +0 1 +.names V918 V922(0) +0 1 +.names V919 V923(0) +0 1 +.names V920 V924(0) +0 1 +.names V921 V925(0) +0 1 +.names V434(0) V925(0) V923(0) V922(0) V924(0) V288(0) V926 +111111 1 +.names V926 V927(0) +0 1 +.names V928 V932(0) +0 1 +.names V929 V933(0) +0 1 +.names V930 V934(0) +0 1 +.names V931 V935(0) +0 1 +.names V434(0) V935(0) V933(0) V932(0) V934(0) V1838 V936 +111111 1 +.names V936 V937(0) +0 1 +.names V938 V942(0) +0 1 +.names V939 V943(0) +0 1 +.names V940 V944(0) +0 1 +.names V941 V945(0) +0 1 +.names V434(0) V945(0) V943(0) V942(0) V944(0) V1838 V946 +111111 1 +.names V946 V947(0) +0 1 +.names V1255(0) V948 +0 1 +.names V1255(1) V949 +0 1 +.names V1255(2) V950 +0 1 +.names V1255(3) V951 +0 1 +.names V434(0) V951 V949 V948 V950 V1856(0) V952 +111111 1 +.names V434(0) V1255(3) V949 V948 V950 V288(6) V953 +111111 1 +.names V434(0) V1255(2) V949 V948 V951 V288(6) V288(7) V954 +1111111 1 +.names V434(0) V949 V948 V1255(2) V1255(3) V288(6) V288(7) V955 +1111111 1 +.names V952 V956(0) +0 1 +.names V953 V957(0) +0 1 +.names V954 V958(0) +0 1 +.names V955 V959(0) +0 1 +.names V802(0) V795 V960 +11 1 +.names V56(0) V763 V759(0) V777(0) V961 +1111 1 +.names V56(0) V758(0) V962 +11 1 +.names V799 V759(0) V963 +11 1 +.names V807(0) V964 +0 1 +.names V963 V961 V960 V962 V965(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V965(0) V964 V498 V966 +111 1 +.names V56(0) V967(0) +0 1 +.names V987(0) V1681(0) V1460(0) V1468(0) V258(0) V968 +11111 1 +.names V968 V969 +0 1 +.names V736 V970 +0 1 +.names V742 V971 +0 1 +.names V743 V972 +0 1 +.names V744 V973 +0 1 +.names V735 V974 +0 1 +.names V746 V975 +0 1 +.names V975 V973 V971 V969 V970 V972 V974 V976 +1111111 1 +.names V961 V977 +0 1 +.names V56(0) V770 V976 V977 V978 +1111 1 +.names V976 V979 +0 1 +.names V967(0) V980 +0 1 +.names V980 V979 V981 +11 1 +.names V721 V2011(0) V501 V982(0) +--1 1 +-1- 1 +1-- 1 +.names V59(0) V982(0) V983 +11 1 +.names V62(0) V1681(0) V984 +11 1 +.names V984 V978 V983 V985(0) +--1 1 +-1- 1 +1-- 1 +.names V985(0) V964 V498 V986 +111 1 +.names V59(0) V987(0) +0 1 +.names V229(5) V1395(0) V2110 V988 +111 1 +.names V229(4) V1395(0) V2110 V989 +111 1 +.names V229(3) V1395(0) V2110 V990 +111 1 +.names V229(2) V1395(0) V2110 V991 +111 1 +.names V229(1) V1395(0) V2110 V992 +111 1 +.names V229(0) V1395(0) V2110 V993 +111 1 +.names V223(5) V1395(0) V2110 V994 +111 1 +.names V223(4) V1395(0) V2110 V995 +111 1 +.names V223(3) V1395(0) V2110 V996 +111 1 +.names V223(2) V1395(0) V2110 V997 +111 1 +.names V223(1) V1395(0) V2110 V998 +111 1 +.names V223(0) V1395(0) V2110 V999 +111 1 +.names V189(5) V2111 V2011(0) V1000 +111 1 +.names V988 V1000 V1023(11) +-1 1 +1- 1 +.names V189(4) V2111 V2011(0) V1002 +111 1 +.names V989 V1002 V1023(10) +-1 1 +1- 1 +.names V189(3) V2111 V2011(0) V1004 +111 1 +.names V990 V1004 V1023(9) +-1 1 +1- 1 +.names V189(2) V2111 V2011(0) V1006 +111 1 +.names V991 V1006 V1023(8) +-1 1 +1- 1 +.names V189(1) V2111 V2011(0) V1008 +111 1 +.names V992 V1008 V1023(7) +-1 1 +1- 1 +.names V189(0) V2111 V2011(0) V1010 +111 1 +.names V993 V1010 V1023(6) +-1 1 +1- 1 +.names V183(5) V2111 V2011(0) V1012 +111 1 +.names V994 V1012 V1023(5) +-1 1 +1- 1 +.names V183(4) V2111 V2011(0) V1014 +111 1 +.names V995 V1014 V1023(4) +-1 1 +1- 1 +.names V183(3) V2111 V2011(0) V1016 +111 1 +.names V996 V1016 V1023(3) +-1 1 +1- 1 +.names V183(2) V2111 V2011(0) V1018 +111 1 +.names V997 V1018 V1023(2) +-1 1 +1- 1 +.names V183(1) V2111 V2011(0) V1020 +111 1 +.names V998 V1020 V1023(1) +-1 1 +1- 1 +.names V183(0) V2111 V2011(0) V1022 +111 1 +.names V999 V1022 V1023(0) +-1 1 +1- 1 +.names V239(4) V1395(0) V2112 V1024 +111 1 +.names V239(3) V1395(0) V2112 V1025 +111 1 +.names V239(2) V1395(0) V2112 V1026 +111 1 +.names V239(1) V1395(0) V2112 V1027 +111 1 +.names V239(0) V1395(0) V2112 V1028 +111 1 +.names V234(4) V1395(0) V2112 V1029 +111 1 +.names V234(3) V1395(0) V2112 V1030 +111 1 +.names V234(2) V1395(0) V2112 V1031 +111 1 +.names V234(1) V1395(0) V2112 V1032 +111 1 +.names V234(0) V1395(0) V2112 V1033 +111 1 +.names V199(4) V2113 V2011(0) V1034 +111 1 +.names V1024 V1034 V1053(9) +-1 1 +1- 1 +.names V199(3) V2113 V2011(0) V1036 +111 1 +.names V1025 V1036 V1053(8) +-1 1 +1- 1 +.names V199(2) V2113 V2011(0) V1038 +111 1 +.names V1026 V1038 V1053(7) +-1 1 +1- 1 +.names V199(1) V2113 V2011(0) V1040 +111 1 +.names V1027 V1040 V1053(6) +-1 1 +1- 1 +.names V199(0) V2113 V2011(0) V1042 +111 1 +.names V1028 V1042 V1053(5) +-1 1 +1- 1 +.names V194(4) V2113 V2011(0) V1044 +111 1 +.names V1029 V1044 V1053(4) +-1 1 +1- 1 +.names V194(3) V2113 V2011(0) V1046 +111 1 +.names V1030 V1046 V1053(3) +-1 1 +1- 1 +.names V194(2) V2113 V2011(0) V1048 +111 1 +.names V1031 V1048 V1053(2) +-1 1 +1- 1 +.names V194(1) V2113 V2011(0) V1050 +111 1 +.names V1032 V1050 V1053(1) +-1 1 +1- 1 +.names V194(0) V2113 V2011(0) V1052 +111 1 +.names V1033 V1052 V1053(0) +-1 1 +1- 1 +.names V257(6) V1681(0) V2115 V2114 V1054 +1111 1 +.names V257(5) V1681(0) V2115 V2114 V1055 +1111 1 +.names V257(4) V1681(0) V2115 V2114 V1056 +1111 1 +.names V257(3) V1681(0) V2115 V2114 V1057 +1111 1 +.names V257(2) V1681(0) V2115 V2114 V1058 +1111 1 +.names V257(1) V1681(0) V2115 V2114 V1059 +1111 1 +.names V257(0) V1681(0) V2115 V2114 V1060 +1111 1 +.names V257(6) V1681(0) V2115 V2114 V1061 +1111 1 +.names V1054 V1070 V1069(11) +-1 1 +1- 1 +.names V1055 V1071 V1069(10) +-1 1 +1- 1 +.names V1056 V1072 V1069(9) +-1 1 +1- 1 +.names V1057 V1073 V1069(8) +-1 1 +1- 1 +.names V1058 V1074 V1069(7) +-1 1 +1- 1 +.names V1059 V1075 V1069(6) +-1 1 +1- 1 +.names V1060 V1076 V1069(5) +-1 1 +1- 1 +.names V1061 V1077 V1069(4) +-1 1 +1- 1 +.names V1023(11) V2117 V2116 V1421(0) V1070 +1111 1 +.names V1023(10) V2117 V2116 V1421(0) V1071 +1111 1 +.names V1023(9) V2117 V2116 V1421(0) V1072 +1111 1 +.names V1023(8) V2117 V2116 V1421(0) V1073 +1111 1 +.names V1023(7) V2117 V2116 V1421(0) V1074 +1111 1 +.names V1023(6) V2117 V2116 V1421(0) V1075 +1111 1 +.names V1023(5) V2117 V2116 V1421(0) V1076 +1111 1 +.names V1023(4) V2117 V2116 V1421(0) V1077 +1111 1 +.names V257(7) V1681(0) V2119 V2118 V1078 +1111 1 +.names V149(7) V987(0) V1446(0) V727 V2121 V2120 V1079 +111111 1 +.names V1087 V1079 V1086(3) +-1 1 +1- 1 +.names V149(6) V987(0) V1446(0) V727 V2121 V2120 V1081 +111111 1 +.names V1088 V1081 V1086(2) +-1 1 +1- 1 +.names V149(5) V987(0) V1446(0) V727 V2121 V2120 V1083 +111111 1 +.names V1089 V1083 V1086(1) +-1 1 +1- 1 +.names V149(4) V987(0) V1446(0) V727 V2121 V2120 V1085 +111111 1 +.names V1078 V1085 V1090 V1086(0) +--1 1 +-1- 1 +1-- 1 +.names V1053(3) V2123 V2122 V1421(0) V1087 +1111 1 +.names V1053(2) V2123 V2122 V1421(0) V1088 +1111 1 +.names V1053(1) V2123 V2122 V1421(0) V1089 +1111 1 +.names V1053(0) V2123 V2122 V1421(0) V1090 +1111 1 +.names V1124(1) V32(8) V1092 +11 1 +.names V1124(1) V32(7) V1093 +11 1 +.names V1124(1) V32(6) V1094 +11 1 +.names V1124(1) V32(5) V1095 +11 1 +.names V1124(1) V32(4) V1096 +11 1 +.names V1124(1) V32(3) V1097 +11 1 +.names V1124(1) V32(2) V1098 +11 1 +.names V1124(1) V32(1) V1099 +11 1 +.names V1124(1) V32(0) V1100 +11 1 +.names V32(11) V2125 V1408(0) V1101 +111 1 +.names V1092 V1101 V1124(13) +-1 1 +1- 1 +.names V32(10) V2125 V1408(0) V1103 +111 1 +.names V1093 V1103 V1124(12) +-1 1 +1- 1 +.names V32(9) V2125 V1408(0) V1105 +111 1 +.names V1094 V1105 V1124(11) +-1 1 +1- 1 +.names V32(8) V2125 V1408(0) V1107 +111 1 +.names V1095 V1107 V1124(10) +-1 1 +1- 1 +.names V32(7) V2125 V1408(0) V1109 +111 1 +.names V1096 V1109 V1124(9) +-1 1 +1- 1 +.names V32(6) V2125 V1408(0) V1111 +111 1 +.names V1097 V1111 V1124(8) +-1 1 +1- 1 +.names V32(5) V2125 V1408(0) V1113 +111 1 +.names V1098 V1113 V1124(7) +-1 1 +1- 1 +.names V32(4) V2125 V1408(0) V1115 +111 1 +.names V1099 V1115 V1124(6) +-1 1 +1- 1 +.names V32(3) V2125 V1408(0) V1117 +111 1 +.names V1100 V1117 V1124(5) +-1 1 +1- 1 +.names V32(2) V2125 V1408(0) V1119 +111 1 +.names V1124(1) V1119 V1124(4) +-1 1 +1- 1 +.names V32(1) V2125 V1408(0) V1121 +111 1 +.names V1124(1) V1121 V1124(3) +-1 1 +1- 1 +.names V32(0) V2125 V1408(0) V1123 +111 1 +.names V1124(1) V1123 V1124(2) +-1 1 +1- 1 +.names V1685(0) V763 V1125 +11 1 +.names V1125 V1126(1) +0 1 +.names V1069(11) V1126(1) V2126 V1127 +111 1 +.names V1069(10) V1126(1) V2126 V1128 +111 1 +.names V1069(9) V1126(1) V2126 V1129 +111 1 +.names V1069(8) V1126(1) V2126 V1130 +111 1 +.names V1069(7) V1126(1) V2126 V1131 +111 1 +.names V1069(6) V1126(1) V2126 V1132 +111 1 +.names V1069(5) V1126(1) V2126 V1133 +111 1 +.names V1124(6) V2127 V1125 V1134 +111 1 +.names V1127 V1134 V1147(11) +-1 1 +1- 1 +.names V1124(5) V2127 V1125 V1136 +111 1 +.names V1128 V1136 V1147(10) +-1 1 +1- 1 +.names V1124(4) V2127 V1125 V1138 +111 1 +.names V1129 V1138 V1147(9) +-1 1 +1- 1 +.names V1124(3) V2127 V1125 V1140 +111 1 +.names V1130 V1140 V1147(8) +-1 1 +1- 1 +.names V1124(2) V2127 V1125 V1142 +111 1 +.names V1131 V1142 V1147(7) +-1 1 +1- 1 +.names V1124(1) V2127 V1125 V1144 +111 1 +.names V1132 V1144 V1147(6) +-1 1 +1- 1 +.names V1408(0) V2125 V2127 V1125 V1146 +1111 1 +.names V1133 V1146 V1147(5) +-1 1 +1- 1 +.names V1421(0) V1053(9) V2123 V2122 V1126(1) V2128 V1148 +111111 1 +.names V1421(0) V1053(8) V2123 V2122 V1126(1) V2128 V1149 +111111 1 +.names V1421(0) V1053(7) V2123 V2122 V1126(1) V2128 V1150 +111111 1 +.names V1421(0) V1053(6) V2123 V2122 V1126(1) V2128 V1151 +111111 1 +.names V1421(0) V1053(5) V2123 V2122 V1126(1) V2128 V1152 +111111 1 +.names V1421(0) V1053(4) V2123 V2122 V1126(1) V2128 V1153 +111111 1 +.names V1086(3) V1126(1) V2128 V1154 +111 1 +.names V1086(2) V1126(1) V2128 V1155 +111 1 +.names V1086(1) V1126(1) V2128 V1156 +111 1 +.names V1086(0) V1126(1) V2128 V1157 +111 1 +.names V1124(1) V32(11) V2129 V1125 V1158 +1111 1 +.names V1148 V1158 V1177(9) +-1 1 +1- 1 +.names V1124(1) V32(10) V2129 V1125 V1160 +1111 1 +.names V1149 V1160 V1177(8) +-1 1 +1- 1 +.names V1124(1) V32(9) V2129 V1125 V1162 +1111 1 +.names V1150 V1162 V1177(7) +-1 1 +1- 1 +.names V1124(13) V2129 V1125 V1164 +111 1 +.names V1151 V1164 V1177(6) +-1 1 +1- 1 +.names V1124(12) V2129 V1125 V1166 +111 1 +.names V1152 V1166 V1177(5) +-1 1 +1- 1 +.names V1124(11) V2129 V1125 V1168 +111 1 +.names V1153 V1168 V1177(4) +-1 1 +1- 1 +.names V1124(10) V2129 V1125 V1170 +111 1 +.names V1154 V1170 V1177(3) +-1 1 +1- 1 +.names V1124(9) V2129 V1125 V1172 +111 1 +.names V1155 V1172 V1177(2) +-1 1 +1- 1 +.names V1124(8) V2129 V1125 V1174 +111 1 +.names V1156 V1174 V1177(1) +-1 1 +1- 1 +.names V1124(7) V2129 V1125 V1176 +111 1 +.names V1157 V1176 V1177(0) +-1 1 +1- 1 +.names V1147(11) V1422(0) V2130 V1178 +111 1 +.names V1147(10) V1422(0) V2130 V1179 +111 1 +.names V1147(9) V1422(0) V2130 V1180 +111 1 +.names V1147(8) V1422(0) V2130 V1181 +111 1 +.names V1147(7) V1422(0) V2130 V1182 +111 1 +.names V1147(6) V1422(0) V2130 V1183 +111 1 +.names V1147(5) V1422(0) V2130 V1184 +111 1 +.names V2126 V1069(4) V1126(1) V1422(0) V2130 V1185 +11111 1 +.names V2126 V1421(0) V1023(3) V2117 V2116 V1126(1) V1422(0) V2130 \ + V1186 +11111111 1 +.names V2126 V1421(0) V1023(2) V2117 V2116 V1126(1) V1422(0) V2130 \ + V1187 +11111111 1 +.names V2126 V1421(0) V1023(1) V2117 V2116 V1126(1) V1422(0) V2130 \ + V1188 +11111111 1 +.names V2126 V1421(0) V1023(0) V2117 V2116 V1126(1) V1422(0) V2130 \ + V1189 +11111111 1 +.names V32(11) V2131 V1417(0) V1190 +111 1 +.names V1178 V1190 V1213(11) +-1 1 +1- 1 +.names V32(10) V2131 V1417(0) V1192 +111 1 +.names V1179 V1192 V1213(10) +-1 1 +1- 1 +.names V32(9) V2131 V1417(0) V1194 +111 1 +.names V1180 V1194 V1213(9) +-1 1 +1- 1 +.names V32(8) V2131 V1417(0) V1196 +111 1 +.names V1181 V1196 V1213(8) +-1 1 +1- 1 +.names V32(7) V2131 V1417(0) V1198 +111 1 +.names V1182 V1198 V1213(7) +-1 1 +1- 1 +.names V32(6) V2131 V1417(0) V1200 +111 1 +.names V1183 V1200 V1213(6) +-1 1 +1- 1 +.names V32(5) V2131 V1417(0) V1202 +111 1 +.names V1184 V1202 V1213(5) +-1 1 +1- 1 +.names V32(4) V2131 V1417(0) V1204 +111 1 +.names V1185 V1204 V1213(4) +-1 1 +1- 1 +.names V32(3) V2131 V1417(0) V1206 +111 1 +.names V1186 V1206 V1213(3) +-1 1 +1- 1 +.names V32(2) V2131 V1417(0) V1208 +111 1 +.names V1187 V1208 V1213(2) +-1 1 +1- 1 +.names V32(1) V2131 V1417(0) V1210 +111 1 +.names V1188 V1210 V1213(1) +-1 1 +1- 1 +.names V32(0) V2131 V1417(0) V1212 +111 1 +.names V1189 V1212 V1213(0) +-1 1 +1- 1 +.names V1177(9) V1422(0) V2132 V1214 +111 1 +.names V1177(8) V1422(0) V2132 V1215 +111 1 +.names V1177(7) V1422(0) V2132 V1216 +111 1 +.names V1177(6) V1422(0) V2132 V1217 +111 1 +.names V1177(5) V1422(0) V2132 V1218 +111 1 +.names V1177(4) V1422(0) V2132 V1219 +111 1 +.names V1177(3) V1422(0) V2132 V1220 +111 1 +.names V1177(2) V1422(0) V2132 V1221 +111 1 +.names V1177(1) V1422(0) V2132 V1222 +111 1 +.names V1177(0) V1422(0) V2132 V1223 +111 1 +.names V88(1) V2133 V1417(0) V1224 +111 1 +.names V1214 V1224 V1243(9) +-1 1 +1- 1 +.names V88(0) V2133 V1417(0) V1226 +111 1 +.names V1215 V1226 V1243(8) +-1 1 +1- 1 +.names V84(5) V2133 V1417(0) V1228 +111 1 +.names V1216 V1228 V1243(7) +-1 1 +1- 1 +.names V84(4) V2133 V1417(0) V1230 +111 1 +.names V1217 V1230 V1243(6) +-1 1 +1- 1 +.names V84(3) V2133 V1417(0) V1232 +111 1 +.names V1218 V1232 V1243(5) +-1 1 +1- 1 +.names V84(2) V2133 V1417(0) V1234 +111 1 +.names V1219 V1234 V1243(4) +-1 1 +1- 1 +.names V84(1) V2133 V1417(0) V1236 +111 1 +.names V1220 V1236 V1243(3) +-1 1 +1- 1 +.names V84(0) V2133 V1417(0) V1238 +111 1 +.names V1221 V1238 V1243(2) +-1 1 +1- 1 +.names V78(5) V2133 V1417(0) V1240 +111 1 +.names V1222 V1240 V1243(1) +-1 1 +1- 1 +.names V78(4) V2133 V1417(0) V1242 +111 1 +.names V1223 V1242 V1243(0) +-1 1 +1- 1 +.names V2126 V1421(0) V1023(3) V2117 V2116 V1126(1) V1422(0) V2134 \ + V1244 +11111111 1 +.names V2126 V1421(0) V1023(2) V2117 V2116 V1126(1) V1422(0) V2134 \ + V1245 +11111111 1 +.names V2126 V1421(0) V1023(1) V2117 V2116 V1126(1) V1422(0) V2134 \ + V1246 +11111111 1 +.names V2126 V1421(0) V1023(0) V2117 V2116 V1126(1) V1422(0) V2134 \ + V1247 +11111111 1 +.names V32(3) V2135 V1417(0) V1248 +111 1 +.names V1244 V1248 V1255(3) +-1 1 +1- 1 +.names V32(2) V2135 V1417(0) V1250 +111 1 +.names V1245 V1250 V1255(2) +-1 1 +1- 1 +.names V32(1) V2135 V1417(0) V1252 +111 1 +.names V1246 V1252 V1255(1) +-1 1 +1- 1 +.names V32(0) V2135 V1417(0) V1254 +111 1 +.names V1247 V1254 V1255(0) +-1 1 +1- 1 +.names V2(0) V372 V1256 +11 1 +.names V2(0) V12(0) V1562 V1560 V1559 V1561 V1563 V1257 +1111111 1 +.names V2(0) V9(0) V1258 +11 1 +.names V3(0) V9(0) V1259 +11 1 +.names V3(0) V11(0) V1260 +11 1 +.names V1275(0) V1260 V1261 +11 1 +.names V4(0) V372 V1262 +11 1 +.names V4(0) V9(0) V1263 +11 1 +.names V4(0) V12(0) V1264 +11 1 +.names V52(0) V1264 V1265 +11 1 +.names V4(0) V11(0) V1266 +11 1 +.names V2(0) V11(0) V1267 +11 1 +.names V728 V727 V769 V501 V400 V726 V721 V1268(0) +------1 1 +-----1- 1 +----1-- 1 +---1--- 1 +--1---- 1 +-1----- 1 +1------ 1 +.names V1268(0) V1269 +0 1 +.names V767 V1270 +0 1 +.names V768 V1271 +0 1 +.names V498 V964 V502 V62(0) V1272 +1111 1 +.names V1720(0) V59(0) V1271 V1269 V1270 V754 V964 V498 V1273 +11111111 1 +.names V1272 V1273 V1274(0) +-1 1 +1- 1 +.names V62(0) V1275(0) +0 1 +.names V735 V56(0) V1276 +11 1 +.names V1276 V1277(0) +0 1 +.names V1984(0) V1278(1) +0 1 +.names V1277(0) V14(0) V213(0) V1278(1) V2136 V1279 +11111 1 +.names V1546(0) V2137 V1984(0) V1280 +111 1 +.names V1279 V1280 V1281(0) +-1 1 +1- 1 +.names V1979 V1282(1) +0 1 +.names V1277(0) V14(0) V213(5) V1282(1) V2138 V1283 +11111 1 +.names V1277(0) V14(0) V213(4) V1282(1) V2138 V1284 +11111 1 +.names V1277(0) V14(0) V213(3) V1282(1) V2138 V1285 +11111 1 +.names V1277(0) V14(0) V213(2) V1282(1) V2138 V1286 +11111 1 +.names V1277(0) V14(0) V213(1) V1282(1) V2138 V1287 +11111 1 +.names V165(7) V2139 V1979 V1288 +111 1 +.names V1283 V1288 V1297(4) +-1 1 +1- 1 +.names V165(6) V2139 V1979 V1290 +111 1 +.names V1284 V1290 V1297(3) +-1 1 +1- 1 +.names V165(5) V2139 V1979 V1292 +111 1 +.names V1285 V1292 V1297(2) +-1 1 +1- 1 +.names V165(4) V2139 V1979 V1294 +111 1 +.names V1286 V1294 V1297(1) +-1 1 +1- 1 +.names V165(3) V2139 V1979 V1296 +111 1 +.names V1287 V1296 V1297(0) +-1 1 +1- 1 +.names V1846 V2025 V1299 +11 1 +.names V1848 V1299 V1303 +11 1 +.names V2029 V1299 V1304 +11 1 +.names V2029 V1848 V1305 +11 1 +.names V1305 V1303 V1304 V1306(0) +--1 1 +-1- 1 +1-- 1 +.names V1839 V1306(0) V1308 +11 1 +.names V2034 V1306(0) V1309 +11 1 +.names V2034 V1839 V1310 +11 1 +.names V1310 V1308 V1309 V1311(0) +--1 1 +-1- 1 +1-- 1 +.names V1298 V1313 +0 1 +.names V1302 V1314 +0 1 +.names V1307 V1315 +0 1 +.names V1314 V1313 V1317 +11 1 +.names V1315 V1317 V1319 +11 1 +.names V1313 V1321 +0 1 +.names V1316 V1322 +0 1 +.names V1318 V1323 +0 1 +.names V1322 V1321 V1325 +11 1 +.names V1323 V1325 V1327 +11 1 +.names V1312 V1848 V2140 V1329 +111 1 +.names V1328 V2141 V1860(0) V1330 +111 1 +.names V1329 V1330 V1331(0) +-1 1 +1- 1 +.names V1307 V1848 V2142 V1332 +111 1 +.names V1326 V2143 V1860(0) V1333 +111 1 +.names V1332 V1333 V1334(0) +-1 1 +1- 1 +.names V1302 V1848 V2144 V1335 +111 1 +.names V1324 V2145 V1860(0) V1336 +111 1 +.names V1335 V1336 V1337(0) +-1 1 +1- 1 +.names V1298 V1848 V2146 V1338 +111 1 +.names V1321 V2147 V1860(0) V1339 +111 1 +.names V1338 V1339 V1340(0) +-1 1 +1- 1 +.names V1340(0) V1341 +0 1 +.names V1337(0) V1342 +0 1 +.names V1334(0) V1343 +0 1 +.names V1342 V1341 V1345 +11 1 +.names V1343 V1345 V1347 +11 1 +.names V1312 V1846 V2148 V1349 +111 1 +.names V1348 V2149 V1859(0) V1350 +111 1 +.names V1349 V1350 V1351(0) +-1 1 +1- 1 +.names V1307 V1846 V2150 V1352 +111 1 +.names V1346 V2151 V1859(0) V1353 +111 1 +.names V1352 V1353 V1354(0) +-1 1 +1- 1 +.names V1302 V1846 V2152 V1355 +111 1 +.names V1344 V2153 V1859(0) V1356 +111 1 +.names V1355 V1356 V1357(0) +-1 1 +1- 1 +.names V1298 V1846 V2154 V1358 +111 1 +.names V1341 V2155 V1859(0) V1359 +111 1 +.names V1358 V1359 V1360(0) +-1 1 +1- 1 +.names V734 V1361 +0 1 +.names V515 V1362 +0 1 +.names V731(0) V1363 +0 1 +.names V738 V1364 +0 1 +.names V498 V964 V805 V1364 V1362 V793 V1361 V1363 V804 V62(0) V1365 +1111111111 1 +.names V268(5) V268(3) V268(1) V268(2) V268(4) V1366 +11111 1 +.names V268(5) V268(3) V268(2) V268(4) V1367 +1111 1 +.names V268(5) V268(3) V268(4) V1368 +111 1 +.names V268(5) V268(4) V1369 +11 1 +.names V268(5) V1375 +0 1 +.names V2010(0) V1376 +0 1 +.names V374(0) V1377 +0 1 +.names V1377 V785 V1376 V1378 +111 1 +.names V2020(0) V1379 +0 1 +.names V1377 V785 V1379 V1380 +111 1 +.names V381(0) V1381 +0 1 +.names V1381 V785 V1377 V1382 +111 1 +.names V342(0) V1383 +0 1 +.names V1383 V785 V1377 V1384 +111 1 +.names V1837(0) V1385 +0 1 +.names V1385 V785 V1377 V1386 +111 1 +.names V9(0) V8(0) V1387 +11 1 +.names V401 V1388(0) +0 1 +.names V741 V1389(0) +0 1 +.names V498 V964 V1389(0) V65(0) V1388(0) V1390 +11111 1 +.names V498 V964 V763 V694(5) V165(3) V694(4) V165(6) V70(0) V1391 +11111111 1 +.names V1391 V1390 V1392(0) +-1 1 +1- 1 +.names V769 V1446(0) V1393 +11 1 +.names V59(0) V56(0) V60(0) V1394(0) +--1 1 +-1- 1 +1-- 1 +.names V701 V700 V1395(0) +-1 1 +1- 1 +.names V59(0) V60(0) V1396(0) +-1 1 +1- 1 +.names V1393 V731(0) V710 V729(0) V721 V1397(0) +----1 1 +---1- 1 +--1-- 1 +-1--- 1 +1---- 1 +.names V56(0) V53(0) V57(0) V1398(0) +--1 1 +-1- 1 +1-- 1 +.names V769 V721 V1399(0) +-1 1 +1- 1 +.names V727 V1400 +0 1 +.names V726 V1401 +0 1 +.names V763 V1394(0) V1402 +11 1 +.names V727 V1445 V1403 +11 1 +.names V727 V1446(0) V1396(0) V1404 +111 1 +.names V1415(0) V1405 +0 1 +.names V1405 V1397(0) V1398(0) V1406 +111 1 +.names V60(0) V1399(0) V1407 +11 1 +.names V1402 V1408(0) +0 1 +.names V769 V1395(0) V726 V1409(0) +--1 1 +-1- 1 +1-- 1 +.names V1407 V1410(0) +0 1 +.names V56(0) V502 V1411 +11 1 +.names V60(0) V502 V1412 +11 1 +.names V56(0) V411 V1413 +11 1 +.names V60(0) V411 V1414 +11 1 +.names V1414 V1412 V1411 V1413 V1415(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V793 V1401 V1400 V53(0) V967(0) V1416 +11111 1 +.names V745 V1406 V1416 V1417(0) +--1 1 +-1- 1 +1-- 1 +.names V765(0) V1409(0) V1418 +11 1 +.names V1417(0) V1419 +0 1 +.names V1410(0) V1420 +0 1 +.names V1418 V1403 V1404 V1421(0) +--1 1 +-1- 1 +1-- 1 +.names V1420 V1419 V1422(0) +-1 1 +1- 1 +.names V1(0) V9(0) V1423 +11 1 +.names V583(0) V1424 +0 1 +.names V786 V1424 V1425 +11 1 +.names V1424 V1377 V1426 +11 1 +.names V658(0) V109(0) V1427 +11 1 +.names V11(0) V1(0) V1428 +11 1 +.names V12(0) V1(0) V1429 +11 1 +.names V1427 V1430 +0 1 +.names V786 V1424 V1430 V1431 +111 1 +.names V66(0) V964 V498 V1432 +111 1 +.names V769 V1433 +0 1 +.names V1441(0) V1434 +0 1 +.names V1434 V1433 V498 V1435 +111 1 +.names V277(0) V769 V1436 +11 1 +.names V1442(0) V1436 V1437(0) +-1 1 +1- 1 +.names V14(0) V1437(0) V1438 +11 1 +.names V746 V1435 V1439(0) +-1 1 +1- 1 +.names V1438 V1440(0) +0 1 +.names V277(0) V1441(0) +0 1 +.names V278(0) V1442(0) +0 1 +.names V769 V277(0) V1443 +11 1 +.names V1443 V1444(0) +0 1 +.names V278(0) V1444(0) V1445 +11 1 +.names V1445 V1446(0) +0 1 +.names V1836 V1830 V1447(0) +-1 1 +1- 1 +.names V1447(0) V14(0) V1452(0) V1448 +111 1 +.names V1447(0) V1449 +0 1 +.names V1449 V14(0) V258(0) V1450 +111 1 +.names V1450 V1448 V1451(0) +-1 1 +1- 1 +.names V258(0) V1452(0) +0 1 +.names V1830 V258(0) V1453 +11 1 +.names V1836 V1452(0) V1454 +11 1 +.names V1454 V1453 V1455(0) +-1 1 +1- 1 +.names V1460(0) V1455(0) V14(0) V1456 +111 1 +.names V1455(0) V1457 +0 1 +.names V259(0) V1457 V14(0) V1458 +111 1 +.names V1458 V1456 V1459(0) +-1 1 +1- 1 +.names V259(0) V1460(0) +0 1 +.names V1453 V259(0) V1461 +11 1 +.names V1454 V1460(0) V1462 +11 1 +.names V1462 V1461 V1463(0) +-1 1 +1- 1 +.names V1468(0) V1463(0) V14(0) V1464 +111 1 +.names V1463(0) V1465 +0 1 +.names V260(0) V1465 V14(0) V1466 +111 1 +.names V1466 V1464 V1467(0) +-1 1 +1- 1 +.names V260(0) V1468(0) +0 1 +.names V737 V1469 +0 1 +.names V1469 V498 V964 V67(0) V1470 +1111 1 +.names V701 V766 V769 V1471(0) +--1 1 +-1- 1 +1-- 1 +.names V739 V745 V744 V1472(0) +--1 1 +-1- 1 +1-- 1 +.names V802(0) V1471(0) V1473 +11 1 +.names V56(0) V1472(0) V1474 +11 1 +.names V1474 V1473 V1475(0) +-1 1 +1- 1 +.names V1597(0) V1475(0) V1476 +11 1 +.names V701 V1477 +0 1 +.names V1477 V1757(0) V1478 +11 1 +.names V802(0) V1757(0) V701 V1479 +111 1 +.names V1479 V1476 V1478 V1480(0) +--1 1 +-1- 1 +1-- 1 +.names V214(0) V1481(0) +0 1 +.names V66(0) V1482 +0 1 +.names V68(0) V1483 +0 1 +.names V69(0) V1484 +0 1 +.names V70(0) V1485 +0 1 +.names V1485 V1483 V1482 V1484 V1486 +1111 1 +.names V1486 V1487 +0 1 +.names V1999(0) V1488 +0 1 +.names V1493(0) V1489 +0 1 +.names V1489 V498 V1487 V1488 V1490 +1111 1 +.names V215(0) V66(0) V1491 +11 1 +.names V1494 V1490 V1492(0) +-1 1 +1- 1 +.names V215(0) V1493(0) +0 1 +.names V1481(0) V216(0) V1494 +11 1 +.names V175(0) V1495(0) +0 1 +.names V2002(0) V1496(0) +0 1 +.names V346(0) V1496(0) V536(0) V1497 +111 1 +.names V1497 V1498(0) +0 1 +.names V2002(0) V1499 +0 1 +.names V346(0) V1500 +0 1 +.names V1500 V1499 V1501 +11 1 +.names V1501 V1502(0) +0 1 +.names V1536(0) V1496(0) V1503 +11 1 +.names V1536(0) V1498(0) V1504 +11 1 +.names V1536(0) V1502(0) V1505 +11 1 +.names V1536(0) V1506 +0 1 +.names V1506 V371(0) V1507 +11 1 +.names V1503 V1507 V1512(3) +-1 1 +1- 1 +.names V1506 V370(0) V1509 +11 1 +.names V1504 V1509 V1512(2) +-1 1 +1- 1 +.names V1506 V369(0) V1511 +11 1 +.names V1505 V1511 V1512(1) +-1 1 +1- 1 +.names V2011(0) V278(0) V1513 +11 1 +.names V177(0) V1514(0) +0 1 +.names V274(0) V1515 +0 1 +.names V1515 V497 V1516 +11 1 +.names V56(0) V172(0) V1517 +11 1 +.names V56(0) V1395(0) V171(0) V1518 +111 1 +.names V1514(0) V1519 +0 1 +.names V248(0) V1520 +0 1 +.names V1513 V1521 +0 1 +.names V1517 V1522 +0 1 +.names V1518 V1523 +0 1 +.names V1523 V1521 V1519 V1520 V1522 V1524 +11111 1 +.names V172(0) V1525 +0 1 +.names V1525 V406 V1526 +11 1 +.names V59(0) V515 V1527 +11 1 +.names V1516 V1528 +0 1 +.names V1524 V1529 +0 1 +.names V1526 V1530 +0 1 +.names V1527 V1531 +0 1 +.names V1531 V1529 V1528 V1530 V1532 +1111 1 +.names V1532 V1533 +0 1 +.names V536(0) V1534 +0 1 +.names V1499 V1533 V1534 V1535 +111 1 +.names V1535 V1536(0) +0 1 +.names V68(0) V964 V498 V1537 +111 1 +.names V50(0) V69(0) V1538(0) +-1 1 +1- 1 +.names V1538(0) V964 V498 V1539 +111 1 +.names V165(3) V1540 +0 1 +.names V165(4) V1541 +0 1 +.names V165(5) V1542 +0 1 +.names V165(6) V1543 +0 1 +.names V165(7) V1544 +0 1 +.names V1544 V1542 V1540 V1541 V1543 V1545 +11111 1 +.names V1646 V1545 V1546(0) +-1 1 +1- 1 +.names V1985 V803(0) V721 V2156 V1547 +1111 1 +.names V1986 V803(0) V721 V2156 V1548 +1111 1 +.names V1243(9) V2157 V379 V1549 +111 1 +.names V1547 V1549 V1552(1) +-1 1 +1- 1 +.names V1243(8) V2157 V379 V1551 +111 1 +.names V1548 V1551 V1552(0) +-1 1 +1- 1 +.names V63(0) V60(0) V1553(0) +-1 1 +1- 1 +.names V730(0) V721 V729(0) V710 V731(0) V769 V1554(0) +-----1 1 +----1- 1 +---1-- 1 +--1--- 1 +-1---- 1 +1----- 1 +.names V57(0) V1554(0) V1555 +11 1 +.names V57(0) V1556 +0 1 +.names V1556 V739 V1557 +11 1 +.names V1553(0) V745 V1558 +11 1 +.names V1555 V1559 +0 1 +.names V1557 V1560 +0 1 +.names V1558 V1561 +0 1 +.names V174(0) V1562 +0 1 +.names V35(0) V1563 +0 1 +.names V202(0) V71(0) V1564 +11 1 +.names V1564 V1565(0) +0 1 +.names V1864(0) V1566 +0 1 +.names V1720(0) V1567 +0 1 +.names V1567 V1566 V1568 +11 1 +.names V1719 V697 V1569 +11 1 +.names V698 V1719 V1570 +11 1 +.names V394(0) V1867 V1719 V1571 +111 1 +.names V394(0) V605 V1719 V247(0) V1572 +1111 1 +.names V1571 V1573 +0 1 +.names V392 V1574 +0 1 +.names V1568 V1575 +0 1 +.names V1569 V1576 +0 1 +.names V1570 V1577 +0 1 +.names V1572 V1578 +0 1 +.names V1593 V1596(0) +0 1 +.names V1594 V1596(1) +0 1 +.names V1596(1) V1596(0) V1597(0) +-1 1 +1- 1 +.names V1610 V1613(0) +0 1 +.names V1611 V1613(1) +0 1 +.names V292(0) V1864(0) V1614 +11 1 +.names V695 V174(0) V1615 +11 1 +.names V2002(0) V174(0) V1616 +11 1 +.names V799 V1617 +0 1 +.names V291(0) V1618 +0 1 +.names V292(0) V1619 +0 1 +.names V799 V1615 V1614 V1616 V1620(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V59(0) V91(0) V1621 +11 1 +.names V62(0) V91(1) V1622 +11 1 +.names V1622 V1621 V1623(0) +-1 1 +1- 1 +.names V739 V1623(0) V1624 +11 1 +.names V294(0) V1625 +0 1 +.names V611 V1626 +0 1 +.names V741 V1627 +0 1 +.names V1627 V1625 V1626 V1628 +111 1 +.names V622(0) V1624 V1628 V1629(0) +--1 1 +-1- 1 +1-- 1 +.names V14(0) V1630(0) +0 1 +.names V769 V766 V1631(0) +-1 1 +1- 1 +.names V768 V740 V741 V739 V1632(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V802(0) V1631(0) V764(0) V1633 +111 1 +.names V701 V802(0) V1634 +11 1 +.names V66(0) V737 V1635 +11 1 +.names V56(0) V1632(0) V1636 +11 1 +.names V763 V66(0) V1637 +11 1 +.names V802(0) V701 V149(7) V1638 +111 1 +.names V687 V766 V1639 +11 1 +.names V1864(0) V701 V1640 +11 1 +.names V1637 V1635 V1633 V1634 V1636 V1641(0) +----1 1 +---1- 1 +--1-- 1 +-1--- 1 +1---- 1 +.names V1640 V768 V1639 V738 V1642(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V336(0) V1641(0) V1643 +11 1 +.names V14(0) V344 V1642(0) V1646 V338 V1644 +11111 1 +.names V1638 V1644 V1643 V1645(0) +--1 1 +-1- 1 +1-- 1 +.names V207(0) V1522 V1646 +11 1 +.names V726 V769 V727 V1647(0) +--1 1 +-1- 1 +1-- 1 +.names V1445 V1647(0) V1648 +11 1 +.names V1648 V1649(0) +0 1 +.names V290(0) V1650 +0 1 +.names V344 V1685(0) V399(0) V1649(0) V295(0) V1650 V1651 +111111 1 +.names V1651 V1652(0) +0 1 +.names V1687(0) V744 V742 V735 V736 V743 V746 V1653(0) +------1 1 +-----1- 1 +----1-- 1 +---1--- 1 +--1---- 1 +-1----- 1 +1------ 1 +.names V1653(0) V1654 +0 1 +.names V1687(0) V1655 +0 1 +.names V805 V804 V1654 V1655 V1627 V1656 +11111 1 +.names V1656 V1657 +0 1 +.names V812(0) V1658 +0 1 +.names V696 V1659 +0 1 +.names V344 V1658 V1499 V1657 V1659 V1660 +11111 1 +.names V1746(0) V1661 +0 1 +.names V344 V1654 V1661 V1662 +111 1 +.names V344 V698 V803(0) V1663 +111 1 +.names V737 V66(0) V1664 +11 1 +.names V1660 V1665 +0 1 +.names V1662 V1666 +0 1 +.names V1663 V1667 +0 1 +.names V1664 V1668 +0 1 +.names V1668 V1666 V1665 V1667 V1669 +1111 1 +.names V204(0) V1670(0) +0 1 +.names V205(0) V1671(0) +0 1 +.names V165(7) V165(6) V165(5) V165(3) V165(4) V261(0) V1670(0) \ + V165(0) V165(1) V165(2) V1672 +1111111111 1 +.names V70(0) V165(7) V261(0) V165(5) V165(3) V165(4) V165(6) \ + V165(0) V165(1) V165(2) V763 V1673 +11111111111 1 +.names V1673 V1672 V1674(0) +-1 1 +1- 1 +.names V987(0) V1460(0) V1468(0) V258(0) V1675 +1111 1 +.names V1680(0) V1676 +0 1 +.names V1675 V1677 +0 1 +.names V498 V1676 V1677 V1678 +111 1 +.names V1678 V1674(0) V1679(0) +-1 1 +1- 1 +.names V262(0) V1680(0) +0 1 +.names V1674(0) V262(0) V1681(0) +-1 1 +1- 1 +.names V1678 V1682 +0 1 +.names V1676 V1682 V1835(0) V1683 +111 1 +.names V1683 V1684(0) +0 1 +.names V1681(0) V1685(0) +0 1 +.names V1678 V262(0) V1686 +11 1 +.names V1674(0) V1686 V1687(0) +-1 1 +1- 1 +.names V736 V56(0) V1688 +11 1 +.names V1688 V1689(0) +0 1 +.names V1983(0) V1690(1) +0 1 +.names V1689(0) V14(0) V100(0) V1690(1) V2158 V1691 +11111 1 +.names V1546(0) V2159 V1983(0) V1692 +111 1 +.names V1691 V1692 V1693(0) +-1 1 +1- 1 +.names V1978 V1694(1) +0 1 +.names V1689(0) V14(0) V100(5) V1694(1) V2160 V1695 +11111 1 +.names V1689(0) V14(0) V100(4) V1694(1) V2160 V1696 +11111 1 +.names V1689(0) V14(0) V100(3) V1694(1) V2160 V1697 +11111 1 +.names V1689(0) V14(0) V100(2) V1694(1) V2160 V1698 +11111 1 +.names V1689(0) V14(0) V100(1) V1694(1) V2160 V1699 +11111 1 +.names V165(7) V2161 V1978 V1700 +111 1 +.names V1695 V1700 V1709(4) +-1 1 +1- 1 +.names V165(6) V2161 V1978 V1702 +111 1 +.names V1696 V1702 V1709(3) +-1 1 +1- 1 +.names V165(5) V2161 V1978 V1704 +111 1 +.names V1697 V1704 V1709(2) +-1 1 +1- 1 +.names V165(4) V2161 V1978 V1706 +111 1 +.names V1698 V1706 V1709(1) +-1 1 +1- 1 +.names V165(3) V2161 V1978 V1708 +111 1 +.names V1699 V1708 V1709(0) +-1 1 +1- 1 +.names V827(0) V721 V1710 +11 1 +.names V721 V421 V1711(0) +-1 1 +1- 1 +.names V802(0) V1711(0) V1712 +11 1 +.names V1710 V1713 +0 1 +.names V1718(0) V1714 +0 1 +.names V697 V1715 +0 1 +.names V338 V1715 V964 V1713 V1714 V1525 V1716 +111111 1 +.names V1716 V1712 V1717(0) +-1 1 +1- 1 +.names V240(0) V1718(0) +0 1 +.names V338 V240(0) V1525 V1719 +111 1 +.names V1719 V1720(0) +0 1 +.names V194(0) V1867 V1721 +11 1 +.names V1536(0) V1722 +0 1 +.names V2011(0) V1721 V1722 V1723 +111 1 +.names V2007(0) V1724 +0 1 +.names V498 V242(0) V1724 V1725 +111 1 +.names V1725 V1723 V1726(0) +-1 1 +1- 1 +.names V1721 V1727(0) +0 1 +.names V727 V769 V1728(0) +-1 1 +1- 1 +.names V241(0) V1728(0) V1729 +11 1 +.names V1477 V1646 V1271 V1364 V733(0) V1730 +11111 1 +.names V1477 V687 V1646 V59(0) V1731 +1111 1 +.names V1477 V59(0) V1646 V768 V1732 +1111 1 +.names V1477 V738 V1646 V62(0) V1733 +1111 1 +.names V1729 V1734 +0 1 +.names V1401 V1734 V1735 +11 1 +.names V344 V698 V1735 V803(0) V1747(0) V1736 +11111 1 +.names V1735 V1737 +0 1 +.names V338 V1730 V1738 +11 1 +.names V338 V1731 V1739 +11 1 +.names V1732 V338 V1740 +11 1 +.names V1733 V1739 V1748 V1738 V1740 V1741(0) +----1 1 +---1- 1 +--1-- 1 +-1--- 1 +1---- 1 +.names V725 V1742 +0 1 +.names V747 V1743 +0 1 +.names V1743 V33(0) V289(0) V1742 V1744 +1111 1 +.names V1744 V1745(0) +0 1 +.names V1741(0) V1746(0) +0 1 +.names V290(0) V1747(0) +0 1 +.names V695 V290(0) V1748 +11 1 +.names V56(0) V751 V1749 +11 1 +.names V16(0) V15(0) V1750 +11 1 +.names V1866(0) V15(0) V1751 +11 1 +.names V16(0) V1865(0) V1752 +11 1 +.names V1749 V1753(0) +0 1 +.names V700 V1752 V1754 +11 1 +.names V101(0) V1753(0) V14(0) V1755 +111 1 +.names V725 V1752 V1756 +11 1 +.names V1751 V1750 V1757(0) +-1 1 +1- 1 +.names V1752 V1751 V1758(0) +-1 1 +1- 1 +.names V1756 V1754 V1755 V1759(0) +--1 1 +-1- 1 +1-- 1 +.names V101(0) V1760(0) +0 1 +.names V745 V1761(0) +0 1 +.names V1763(1) V745 V2162 V1764 +111 1 +.names V1763(0) V745 V2162 V1765 +111 1 +.names V1767(1) V2163 V1761(0) V1768 +111 1 +.names V1764 V1768 V1771(1) +-1 1 +1- 1 +.names V1767(0) V2163 V1761(0) V1770 +111 1 +.names V1765 V1770 V1771(0) +-1 1 +1- 1 +.names V1773(1) V1761(0) V2164 V1774 +111 1 +.names V1773(0) V1761(0) V2164 V1775 +111 1 +.names V1777(1) V2165 V745 V1778 +111 1 +.names V1774 V1778 V1781(1) +-1 1 +1- 1 +.names V1777(0) V2165 V745 V1780 +111 1 +.names V1775 V1780 V1781(0) +-1 1 +1- 1 +.names V1213(2) V1782 +0 1 +.names V1791(8) V37(0) V2166 V1792 +111 1 +.names V1791(7) V37(0) V2166 V1793 +111 1 +.names V1791(6) V37(0) V2166 V1794 +111 1 +.names V1791(5) V37(0) V2166 V1795 +111 1 +.names V1791(4) V37(0) V2166 V1796 +111 1 +.names V1791(3) V37(0) V2166 V1797 +111 1 +.names V1791(2) V37(0) V2166 V1798 +111 1 +.names V1791(1) V37(0) V2166 V1799 +111 1 +.names V1791(0) V37(0) V2166 V1800 +111 1 +.names V1782 V37(0) V2166 V1801 +111 1 +.names V321(2) V2167 V436(0) V1810 +111 1 +.names V1792 V1810 V1829(9) +-1 1 +1- 1 +.names V1809(7) V2167 V436(0) V1812 +111 1 +.names V1793 V1812 V1829(8) +-1 1 +1- 1 +.names V1809(6) V2167 V436(0) V1814 +111 1 +.names V1794 V1814 V1829(7) +-1 1 +1- 1 +.names V1809(5) V2167 V436(0) V1816 +111 1 +.names V1795 V1816 V1829(6) +-1 1 +1- 1 +.names V1809(4) V2167 V436(0) V1818 +111 1 +.names V1796 V1818 V1829(5) +-1 1 +1- 1 +.names V1809(3) V2167 V436(0) V1820 +111 1 +.names V1797 V1820 V1829(4) +-1 1 +1- 1 +.names V1809(2) V2167 V436(0) V1822 +111 1 +.names V1798 V1822 V1829(3) +-1 1 +1- 1 +.names V1809(1) V2167 V436(0) V1824 +111 1 +.names V1799 V1824 V1829(2) +-1 1 +1- 1 +.names V1809(0) V2167 V436(0) V1826 +111 1 +.names V1800 V1826 V1829(1) +-1 1 +1- 1 +.names V321(2) V2167 V436(0) V1828 +111 1 +.names V1801 V1828 V1829(0) +-1 1 +1- 1 +.names V268(0) V1366 V1830 +11 1 +.names V1834 V1830 V1831(0) +-1 1 +1- 1 +.names V14(0) V1831(0) V1832 +11 1 +.names V261(0) V1833(0) +0 1 +.names V1684(0) V261(0) V1834 +11 1 +.names V50(0) V56(0) V62(0) V1835(0) +--1 1 +-1- 1 +1-- 1 +.names V1681(0) V1835(0) V1836 +11 1 +.names V1836 V1837(0) +0 1 +.names V288(1) V288(0) V1838 +11 1 +.names V288(3) V288(2) V1839 +11 1 +.names V288(5) V288(4) V1840 +11 1 +.names V288(4) V1841 +0 1 +.names V288(5) V1841 V1842 +11 1 +.names V288(5) V1843 +0 1 +.names V1843 V288(4) V1844 +11 1 +.names V288(2) V1845 +0 1 +.names V288(3) V1845 V1846 +11 1 +.names V288(3) V1847 +0 1 +.names V1847 V288(2) V1848 +11 1 +.names V288(0) V1849 +0 1 +.names V288(1) V1849 V1850 +11 1 +.names V288(1) V1851 +0 1 +.names V1851 V288(0) V1852 +11 1 +.names V288(1) V288(0) V1853(0) +-1 1 +1- 1 +.names V288(3) V288(2) V1854(0) +-1 1 +1- 1 +.names V288(5) V288(4) V1855(0) +-1 1 +1- 1 +.names V288(7) V288(6) V1856(0) +-1 1 +1- 1 +.names V1842 V1857(0) +0 1 +.names V1844 V1858(0) +0 1 +.names V1846 V1859(0) +0 1 +.names V1848 V1860(0) +0 1 +.names V1850 V1861(0) +0 1 +.names V1852 V1862(0) +0 1 +.names V301(0) V1863(0) +0 1 +.names V302(0) V1864(0) +0 1 +.names V15(0) V1865(0) +0 1 +.names V16(0) V1866(0) +0 1 +.names V199(4) V199(2) V199(0) V194(3) V194(1) V194(2) V194(4) \ + V199(1) V199(3) V1867 +111111111 1 +.names V199(4) V199(2) V199(0) V194(3) V194(2) V194(4) V199(1) \ + V199(3) V1868 +11111111 1 +.names V199(4) V199(2) V199(0) V194(3) V194(4) V199(1) V199(3) V1869 +1111111 1 +.names V199(4) V199(2) V199(0) V194(4) V199(1) V199(3) V1870 +111111 1 +.names V199(4) V199(2) V199(0) V199(1) V199(3) V1871 +11111 1 +.names V199(4) V199(2) V199(1) V199(3) V1872 +1111 1 +.names V199(4) V199(2) V199(3) V1873 +111 1 +.names V199(4) V199(3) V1874 +11 1 +.names V199(4) V1884 +0 1 +.names V769 V1476 V1885 +11 1 +.names V725 V1995 V1886 +11 1 +.names V700 V1995 V1887 +11 1 +.names V1902 V1888 +0 1 +.names V108(0) V1888 V1889 +11 1 +.names V108(1) V1888 V1890 +11 1 +.names V108(2) V1888 V1891 +11 1 +.names V108(3) V1888 V1892 +11 1 +.names V108(4) V1888 V1893 +11 1 +.names V1749 V1894 +0 1 +.names V108(5) V1894 V1895 +11 1 +.names V1889 V1476 V1750 V1896(0) +--1 1 +-1- 1 +1-- 1 +.names V1885 V1890 V1897(0) +-1 1 +1- 1 +.names V1886 V1891 V1898(0) +-1 1 +1- 1 +.names V1887 V1892 V1899(0) +-1 1 +1- 1 +.names V1751 V1893 V1900(0) +-1 1 +1- 1 +.names V1752 V1895 V1901(0) +-1 1 +1- 1 +.names V56(0) V750 V1902 +11 1 +.names V100(5) V736 V2170 V2169 V2168 V1904 +11111 1 +.names V100(4) V736 V2170 V2169 V2168 V1905 +11111 1 +.names V100(3) V736 V2170 V2169 V2168 V1906 +11111 1 +.names V100(2) V736 V2170 V2169 V2168 V1907 +11111 1 +.names V100(1) V736 V2170 V2169 V2168 V1908 +11111 1 +.names V100(0) V736 V2170 V2169 V2168 V1909 +11111 1 +.names V213(5) V2173 V735 V2172 V2171 V1910 +11111 1 +.names V1904 V1910 V1922 V1921(5) +--1 1 +-1- 1 +1-- 1 +.names V213(4) V2173 V735 V2172 V2171 V1912 +11111 1 +.names V1905 V1912 V1923 V1928 V1921(4) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V213(3) V2173 V735 V2172 V2171 V1914 +11111 1 +.names V1906 V1914 V1924 V1929 V1921(3) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V213(2) V2173 V735 V2172 V2171 V1916 +11111 1 +.names V1907 V1916 V1925 V1930 V1921(2) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V213(1) V2173 V735 V2172 V2171 V1918 +11111 1 +.names V1908 V1918 V1926 V1931 V1921(1) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V213(0) V2173 V735 V2172 V2171 V1920 +11111 1 +.names V1909 V1920 V1927 V1932 V1921(0) +---1 1 +--1- 1 +-1-- 1 +1--- 1 +.names V124(5) V2176 V2175 V742 V2174 V1922 +11111 1 +.names V124(4) V2176 V2175 V742 V2174 V1923 +11111 1 +.names V124(3) V2176 V2175 V742 V2174 V1924 +11111 1 +.names V124(2) V2176 V2175 V742 V2174 V1925 +11111 1 +.names V124(1) V2176 V2175 V742 V2174 V1926 +11111 1 +.names V124(0) V2176 V2175 V742 V2174 V1927 +11111 1 +.names V108(4) V2179 V2178 V2177 V750 V1928 +11111 1 +.names V108(3) V2179 V2178 V2177 V750 V1929 +11111 1 +.names V108(2) V2179 V2178 V2177 V750 V1930 +11111 1 +.names V108(1) V2179 V2178 V2177 V750 V1931 +11111 1 +.names V108(0) V2179 V2178 V2177 V750 V1932 +11111 1 +.names V132(7) V742 V2181 V2180 V1933 +1111 1 +.names V132(6) V742 V2181 V2180 V1934 +1111 1 +.names V132(5) V742 V2181 V2180 V1935 +1111 1 +.names V132(4) V742 V2181 V2180 V1936 +1111 1 +.names V132(3) V742 V2181 V2180 V1937 +1111 1 +.names V132(2) V742 V2181 V2180 V1938 +1111 1 +.names V132(1) V742 V2181 V2180 V1953(1) +1111 1 +.names V132(0) V742 V2181 V2180 V1940 +1111 1 +.names V118(5) V2183 V743 V2182 V1941 +1111 1 +.names V1933 V1941 V1953(7) +-1 1 +1- 1 +.names V118(4) V2183 V743 V2182 V1943 +1111 1 +.names V1934 V1943 V1953(6) +-1 1 +1- 1 +.names V118(3) V2183 V743 V2182 V1945 +1111 1 +.names V1935 V1945 V1953(5) +-1 1 +1- 1 +.names V118(2) V2183 V743 V2182 V1947 +1111 1 +.names V1936 V1947 V1953(4) +-1 1 +1- 1 +.names V118(1) V2183 V743 V2182 V1949 +1111 1 +.names V1937 V1949 V1953(3) +-1 1 +1- 1 +.names V118(0) V2183 V743 V2182 V1951 +1111 1 +.names V1938 V1951 V1953(2) +-1 1 +1- 1 +.names V1940 V1954 V1953(0) +-1 1 +1- 1 +.names V108(5) V2185 V2184 V751 V1954 +1111 1 +.names V118(7) V743 V2186 V1955 +111 1 +.names V118(6) V743 V2186 V1956 +111 1 +.names V46(0) V2187 V382(0) V1957 +111 1 +.names V1955 V1957 V1960(1) +-1 1 +1- 1 +.names V48(0) V2187 V382(0) V1959 +111 1 +.names V1956 V1959 V1960(0) +-1 1 +1- 1 +.names V56(0) V743 V1961 +11 1 +.names V1903(4) V1751 V101(0) V1962 +111 1 +.names V102(0) V1758(0) V1963(0) +-1 1 +1- 1 +.names V1961 V1964(0) +0 1 +.names V1962 V1965(0) +0 1 +.names V1969 V1963(0) V700 V1966 +111 1 +.names V110(0) V1965(0) V1964(0) V14(0) V1967 +1111 1 +.names V1967 V1966 V1968(0) +-1 1 +1- 1 +.names V110(0) V1969 +0 1 +.names V288(6) V1970 +0 1 +.names V288(7) V1971 +0 1 +.names V1971 V1970 V1972 +11 1 +.names V288(7) V1970 V1974 +11 1 +.names V1973 V1975(0) +0 1 +.names V1974 V1976(0) +0 1 +.names V702 V700 V1977(0) +-1 1 +1- 1 +.names V695 V1977(0) V290(0) V1978 +111 1 +.names V695 V290(0) V725 V1979 +111 1 +.names V1644 V1980 +0 1 +.names V1977(0) V338 V1646 V1980 V1743 V1981 +11111 1 +.names V725 V338 V1646 V1980 V1743 V1982 +11111 1 +.names V1978 V1981 V1983(0) +-1 1 +1- 1 +.names V1982 V1979 V1984(0) +-1 1 +1- 1 +.names V239(4) V1985 +0 1 +.names V1993 V2010(0) V2006 V2188 V1987 +1111 1 +.names V1994 V2010(0) V2006 V2188 V1988 +1111 1 +.names V134(1) V2017 V2016 V2189 V1989 +1111 1 +.names V1987 V1989 V1992(1) +-1 1 +1- 1 +.names V134(0) V2017 V2016 V2189 V1991 +1111 1 +.names V1988 V1991 V1992(0) +-1 1 +1- 1 +.names V134(1) V1993 +0 1 +.names V67(0) V172(0) V215(0) V1995 +111 1 +.names V1446(0) V261(0) V1737 V803(0) V1996 +1111 1 +.names V261(0) V1737 V803(0) V272(0) V643 V1445 V1997 +111111 1 +.names V1996 V1998(0) +0 1 +.names V1733 V1731 V214(0) V1995 V1730 V1732 V1999(0) +-----1 1 +----1- 1 +---1-- 1 +--1--- 1 +-1---- 1 +1----- 1 +.names V2004(0) V1446(0) V242(0) V803(0) V2011(0) V2000 +11111 1 +.names V134(1) V134(0) V242(0) V803(0) V272(0) V643 V1445 V2001 +1111111 1 +.names V1997 V1999(0) V2000 V1996 V2001 V2002(0) +----1 1 +---1- 1 +--1-- 1 +-1--- 1 +1---- 1 +.names V2007(0) V56(0) V2003 +11 1 +.names V2003 V2004(0) +0 1 +.names V803(0) V1445 V2005 +11 1 +.names V1761(0) V271(0) V642(0) V2006 +111 1 +.names V727 V769 V2007(0) +-1 1 +1- 1 +.names V2005 V2008(0) +0 1 +.names V802(0) V2007(0) V2009 +11 1 +.names V2009 V2010(0) +0 1 +.names V726 V2007(0) V2011(0) +-1 1 +1- 1 +.names V1998(0) V2022(0) V2007(0) V2008(0) V2024(0) V2012 +11111 1 +.names V1998(0) V2024(0) V1446(0) V803(0) V726 V1727(0) V2013 +111111 1 +.names V1727(0) V2006 V1445 V134(0) V134(1) V2014 +11111 1 +.names V803(0) V1446(0) V2011(0) V2015 +111 1 +.names V2009 V2016 +0 1 +.names V2006 V2017 +0 1 +.names V2014 V2012 V2013 V2018(0) +--1 1 +-1- 1 +1-- 1 +.names V2015 V2014 V2019(0) +-1 1 +1- 1 +.names V2018(0) V2020(0) +0 1 +.names V803(0) V1721 V2021 +11 1 +.names V2021 V2022(0) +0 1 +.names V803(0) V248(0) V2023 +11 1 +.names V2023 V2024(0) +0 1 +.names V1842 V1976(0) V2026 +11 1 +.names V1844 V2026 V2030 +11 1 +.names V1975(0) V2026 V2031 +11 1 +.names V1975(0) V1844 V2032 +11 1 +.names V2032 V2030 V2031 V2033(0) +--1 1 +-1- 1 +1-- 1 +.names V1840 V2033(0) V2035 +11 1 +.names V1972 V2033(0) V2036 +11 1 +.names V1972 V1840 V2037 +11 1 +.names V2037 V2035 V2036 V2038(0) +--1 1 +-1- 1 +1-- 1 +.names V2025 V2040 +0 1 +.names V2029 V2041 +0 1 +.names V2034 V2042 +0 1 +.names V2041 V2040 V2044 +11 1 +.names V2042 V2044 V2046 +11 1 +.names V2040 V2048 +0 1 +.names V2043 V2049 +0 1 +.names V2045 V2050 +0 1 +.names V2049 V2048 V2052 +11 1 +.names V2050 V2052 V2054 +11 1 +.names V2039 V1844 V2190 V2056 +111 1 +.names V2055 V2191 V1858(0) V2057 +111 1 +.names V2056 V2057 V2058(0) +-1 1 +1- 1 +.names V2034 V1844 V2192 V2059 +111 1 +.names V2053 V2193 V1858(0) V2060 +111 1 +.names V2059 V2060 V2061(0) +-1 1 +1- 1 +.names V2029 V1844 V2194 V2062 +111 1 +.names V2051 V2195 V1858(0) V2063 +111 1 +.names V2062 V2063 V2064(0) +-1 1 +1- 1 +.names V2025 V1844 V2196 V2065 +111 1 +.names V2048 V2197 V1858(0) V2066 +111 1 +.names V2065 V2066 V2067(0) +-1 1 +1- 1 +.names V2067(0) V2068 +0 1 +.names V2064(0) V2069 +0 1 +.names V2061(0) V2070 +0 1 +.names V2069 V2068 V2072 +11 1 +.names V2070 V2072 V2074 +11 1 +.names V2039 V1842 V2198 V2076 +111 1 +.names V2075 V2199 V1857(0) V2077 +111 1 +.names V2076 V2077 V2078(0) +-1 1 +1- 1 +.names V2034 V1842 V2200 V2079 +111 1 +.names V2073 V2201 V1857(0) V2080 +111 1 +.names V2079 V2080 V2081(0) +-1 1 +1- 1 +.names V2029 V1842 V2202 V2082 +111 1 +.names V2071 V2203 V1857(0) V2083 +111 1 +.names V2082 V2083 V2084(0) +-1 1 +1- 1 +.names V2025 V1842 V2204 V2085 +111 1 +.names V2068 V2205 V1857(0) V2086 +111 1 +.names V2085 V2086 V2087(0) +-1 1 +1- 1 +.names V1862(0) V2088 +0 1 +.names V1852 V2089 +0 1 +.names V1862(0) V2090 +0 1 +.names V1852 V2091 +0 1 +.names V1862(0) V2092 +0 1 +.names V1852 V2093 +0 1 +.names V1862(0) V2094 +0 1 +.names V1852 V2095 +0 1 +.names V1861(0) V2096 +0 1 +.names V1850 V2097 +0 1 +.names V1861(0) V2098 +0 1 +.names V1850 V2099 +0 1 +.names V1861(0) V2100 +0 1 +.names V1850 V2101 +0 1 +.names V1861(0) V2102 +0 1 +.names V1850 V2103 +0 1 +.names V769 V802(0) V2104 +-0 1 +0- 1 +.names V2019(0) V2105 +0 1 +.names V769 V802(0) V2106 +-0 1 +0- 1 +.names V727 V802(0) V2107 +-0 1 +0- 1 +.names V2019(0) V2108 +0 1 +.names V727 V802(0) V2109 +-0 1 +0- 1 +.names V2011(0) V2110 +0 1 +.names V1395(0) V2111 +0 1 +.names V2011(0) V2112 +0 1 +.names V1395(0) V2113 +0 1 +.names V1421(0) V2114 +0 1 +.names V727 V1446(0) V987(0) V2115 +--0 1 +-0- 1 +0-- 1 +.names V727 V1446(0) V987(0) V2116 +--0 1 +-0- 1 +0-- 1 +.names V1681(0) V2117 +0 1 +.names V1421(0) V2118 +0 1 +.names V727 V1446(0) V987(0) V2119 +--0 1 +-0- 1 +0-- 1 +.names V1421(0) V2120 +0 1 +.names V1681(0) V2121 +0 1 +.names V727 V1446(0) V987(0) V2122 +--0 1 +-0- 1 +0-- 1 +.names V1681(0) V2123 +0 1 +.names V1408(0) V2124 +0 1 +.names V2124 V1402 V1124(1) +11 1 +.names V1402 V2125 +0 1 +.names V1125 V2126 +0 1 +.names V1126(1) V2127 +0 1 +.names V1125 V2128 +0 1 +.names V1126(1) V2129 +0 1 +.names V1417(0) V2130 +0 1 +.names V1422(0) V2131 +0 1 +.names V1417(0) V2132 +0 1 +.names V1422(0) V2133 +0 1 +.names V1417(0) V2134 +0 1 +.names V1422(0) V2135 +0 1 +.names V1984(0) V2136 +0 1 +.names V1278(1) V2137 +0 1 +.names V1979 V2138 +0 1 +.names V1282(1) V2139 +0 1 +.names V1860(0) V2140 +0 1 +.names V1848 V2141 +0 1 +.names V1860(0) V2142 +0 1 +.names V1848 V2143 +0 1 +.names V1860(0) V2144 +0 1 +.names V1848 V2145 +0 1 +.names V1860(0) V2146 +0 1 +.names V1848 V2147 +0 1 +.names V1859(0) V2148 +0 1 +.names V1846 V2149 +0 1 +.names V1859(0) V2150 +0 1 +.names V1846 V2151 +0 1 +.names V1859(0) V2152 +0 1 +.names V1846 V2153 +0 1 +.names V1859(0) V2154 +0 1 +.names V1846 V2155 +0 1 +.names V379 V2156 +0 1 +.names V721 V803(0) V2157 +-0 1 +0- 1 +.names V1983(0) V2158 +0 1 +.names V1690(1) V2159 +0 1 +.names V1978 V2160 +0 1 +.names V1694(1) V2161 +0 1 +.names V1761(0) V2162 +0 1 +.names V88(2) V1763(0) +0 1 +.names V88(3) V1763(1) +0 1 +.names V745 V2163 +0 1 +.names V134(0) V1767(0) +0 1 +.names V134(1) V1767(1) +0 1 +.names V745 V2164 +0 1 +.names V1213(10) V1773(0) +0 1 +.names V1213(11) V1773(1) +0 1 +.names V1761(0) V2165 +0 1 +.names V78(2) V1777(0) +0 1 +.names V78(3) V1777(1) +0 1 +.names V436(0) V2166 +0 1 +.names V1243(1) V1791(0) +0 1 +.names V1243(2) V1791(1) +0 1 +.names V1243(3) V1791(2) +0 1 +.names V1243(4) V1791(3) +0 1 +.names V1243(5) V1791(4) +0 1 +.names V1243(6) V1791(5) +0 1 +.names V1243(7) V1791(6) +0 1 +.names V1243(8) V1791(7) +0 1 +.names V1243(9) V1791(8) +0 1 +.names V37(0) V2167 +0 1 +.names V1213(4) V1809(0) +0 1 +.names V1213(5) V1809(1) +0 1 +.names V1213(6) V1809(2) +0 1 +.names V1213(7) V1809(3) +0 1 +.names V1213(8) V1809(4) +0 1 +.names V1213(9) V1809(5) +0 1 +.names V1213(10) V1809(6) +0 1 +.names V1213(11) V1809(7) +0 1 +.names V108(4) V1903(4) +0 1 +.names V750 V2168 +0 1 +.names V742 V2169 +0 1 +.names V735 V2170 +0 1 +.names V750 V2171 +0 1 +.names V742 V2172 +0 1 +.names V736 V2173 +0 1 +.names V750 V2174 +0 1 +.names V735 V2175 +0 1 +.names V736 V2176 +0 1 +.names V742 V2177 +0 1 +.names V735 V2178 +0 1 +.names V736 V2179 +0 1 +.names V751 V2180 +0 1 +.names V743 V2181 +0 1 +.names V751 V2182 +0 1 +.names V742 V2183 +0 1 +.names V743 V2184 +0 1 +.names V742 V2185 +0 1 +.names V382(0) V2186 +0 1 +.names V743 V2187 +0 1 +.names V2016 V2017 V2188 +-0 1 +0- 1 +.names V2006 V2010(0) V2189 +-0 1 +0- 1 +.names V1858(0) V2190 +0 1 +.names V1844 V2191 +0 1 +.names V1858(0) V2192 +0 1 +.names V1844 V2193 +0 1 +.names V1858(0) V2194 +0 1 +.names V1844 V2195 +0 1 +.names V1858(0) V2196 +0 1 +.names V1844 V2197 +0 1 +.names V1857(0) V2198 +0 1 +.names V1842 V2199 +0 1 +.names V1857(0) V2200 +0 1 +.names V1842 V2201 +0 1 +.names V1857(0) V2202 +0 1 +.names V1842 V2203 +0 1 +.names V1857(0) V2204 +0 1 +.names V1842 V2205 +0 1 +.names V451 V2206 +0 1 +.names V32(0) V2207 +0 1 +.names V451 V2207 V2208 +11 1 +.names V2206 V32(0) V2209 +11 1 +.names V2208 V2209 V324 +-1 1 +1- 1 +.names V446 V2210 +0 1 +.names V32(1) V2211 +0 1 +.names V446 V2211 V2212 +11 1 +.names V2210 V32(1) V2213 +11 1 +.names V2212 V2213 V325 +-1 1 +1- 1 +.names V441 V2214 +0 1 +.names V32(2) V2215 +0 1 +.names V441 V2215 V2216 +11 1 +.names V2214 V32(2) V2217 +11 1 +.names V2216 V2217 V326 +-1 1 +1- 1 +.names V1850 V2218 +0 1 +.names V1298 V2219 +0 1 +.names V1850 V2219 V2220 +11 1 +.names V2218 V1298 V2221 +11 1 +.names V2220 V2221 V437 +-1 1 +1- 1 +.names V1852 V2222 +0 1 +.names V1302 V2223 +0 1 +.names V1852 V2223 V2224 +11 1 +.names V2222 V1302 V2225 +11 1 +.names V2224 V2225 V439 +-1 1 +1- 1 +.names V1838 V2226 +0 1 +.names V1307 V2227 +0 1 +.names V1838 V2227 V2228 +11 1 +.names V2226 V1307 V2229 +11 1 +.names V2228 V2229 V440 +-1 1 +1- 1 +.names V439 V2230 +0 1 +.names V438 V2231 +0 1 +.names V439 V2231 V2232 +11 1 +.names V2230 V438 V2233 +11 1 +.names V2232 V2233 V441 +-1 1 +1- 1 +.names V445(0) V2234 +0 1 +.names V440 V2235 +0 1 +.names V445(0) V2235 V2236 +11 1 +.names V2234 V440 V2237 +11 1 +.names V2236 V2237 V446 +-1 1 +1- 1 +.names V1312 V2238 +0 1 +.names V450(0) V2239 +0 1 +.names V1312 V2239 V2240 +11 1 +.names V2238 V450(0) V2241 +11 1 +.names V2240 V2241 V451 +-1 1 +1- 1 +.names V441 V2242 +0 1 +.names V333 V2243 +0 1 +.names V441 V2243 V2244 +11 1 +.names V2242 V333 V2245 +11 1 +.names V2244 V2245 V452 +-1 1 +1- 1 +.names V446 V2246 +0 1 +.names V453 V2247 +0 1 +.names V446 V2247 V2248 +11 1 +.names V2246 V453 V2249 +11 1 +.names V2248 V2249 V454 +-1 1 +1- 1 +.names V451 V2250 +0 1 +.names V455 V2251 +0 1 +.names V451 V2251 V2252 +11 1 +.names V2250 V455 V2253 +11 1 +.names V2252 V2253 V456 +-1 1 +1- 1 +.names V452 V2254 +0 1 +.names V457 V2255 +0 1 +.names V452 V2255 V2256 +11 1 +.names V2254 V457 V2257 +11 1 +.names V2256 V2257 V460 +-1 1 +1- 1 +.names V454 V2258 +0 1 +.names V461 V2259 +0 1 +.names V454 V2259 V2260 +11 1 +.names V2258 V461 V2261 +11 1 +.names V2260 V2261 V462 +-1 1 +1- 1 +.names V456 V2262 +0 1 +.names V463 V2263 +0 1 +.names V456 V2263 V2264 +11 1 +.names V2262 V463 V2265 +11 1 +.names V2264 V2265 V464 +-1 1 +1- 1 +.names V473(0) V2266 +0 1 +.names V477 V2267 +0 1 +.names V473(0) V2267 V2268 +11 1 +.names V2266 V477 V2269 +11 1 +.names V2268 V2269 V480 +-1 1 +1- 1 +.names V470(0) V2270 +0 1 +.names V481 V2271 +0 1 +.names V470(0) V2271 V2272 +11 1 +.names V2270 V481 V2273 +11 1 +.names V2272 V2273 V482 +-1 1 +1- 1 +.names V467(0) V2274 +0 1 +.names V483 V2275 +0 1 +.names V467(0) V2275 V2276 +11 1 +.names V2274 V483 V2277 +11 1 +.names V2276 V2277 V484 +-1 1 +1- 1 +.names V39(0) V2278 +0 1 +.names V38(0) V2279 +0 1 +.names V39(0) V2279 V2280 +11 1 +.names V2278 V38(0) V2281 +11 1 +.names V2280 V2281 V509 +-1 1 +1- 1 +.names V42(0) V2282 +0 1 +.names V44(0) V2283 +0 1 +.names V42(0) V2283 V2284 +11 1 +.names V2282 V44(0) V2285 +11 1 +.names V2284 V2285 V530 +-1 1 +1- 1 +.names V41(0) V2286 +0 1 +.names V45(0) V2287 +0 1 +.names V41(0) V2287 V2288 +11 1 +.names V2286 V45(0) V2289 +11 1 +.names V2288 V2289 V531 +-1 1 +1- 1 +.names V257(0) V2290 +0 1 +.names V644 V2291 +0 1 +.names V257(0) V2291 V2292 +11 1 +.names V2290 V644 V2293 +11 1 +.names V2292 V2293 V650 +-1 1 +1- 1 +.names V257(1) V2294 +0 1 +.names V645 V2295 +0 1 +.names V257(1) V2295 V2296 +11 1 +.names V2294 V645 V2297 +11 1 +.names V2296 V2297 V651 +-1 1 +1- 1 +.names V257(2) V2298 +0 1 +.names V646 V2299 +0 1 +.names V257(2) V2299 V2300 +11 1 +.names V2298 V646 V2301 +11 1 +.names V2300 V2301 V652 +-1 1 +1- 1 +.names V257(3) V2302 +0 1 +.names V647 V2303 +0 1 +.names V257(3) V2303 V2304 +11 1 +.names V2302 V647 V2305 +11 1 +.names V2304 V2305 V653 +-1 1 +1- 1 +.names V257(4) V2306 +0 1 +.names V648 V2307 +0 1 +.names V257(4) V2307 V2308 +11 1 +.names V2306 V648 V2309 +11 1 +.names V2308 V2309 V654 +-1 1 +1- 1 +.names V257(5) V2310 +0 1 +.names V649 V2311 +0 1 +.names V257(5) V2311 V2312 +11 1 +.names V2310 V649 V2313 +11 1 +.names V2312 V2313 V655 +-1 1 +1- 1 +.names V257(6) V2314 +0 1 +.names V257(7) V2315 +0 1 +.names V257(6) V2315 V2316 +11 1 +.names V2314 V257(7) V2317 +11 1 +.names V2316 V2317 V656 +-1 1 +1- 1 +.names V2078(0) V2318 +0 1 +.names V1255(0) V2319 +0 1 +.names V2078(0) V2319 V2320 +11 1 +.names V2318 V1255(0) V2321 +11 1 +.names V2320 V2321 V828 +-1 1 +1- 1 +.names V2081(0) V2322 +0 1 +.names V1255(1) V2323 +0 1 +.names V2081(0) V2323 V2324 +11 1 +.names V2322 V1255(1) V2325 +11 1 +.names V2324 V2325 V829 +-1 1 +1- 1 +.names V2084(0) V2326 +0 1 +.names V1255(2) V2327 +0 1 +.names V2084(0) V2327 V2328 +11 1 +.names V2326 V1255(2) V2329 +11 1 +.names V2328 V2329 V830 +-1 1 +1- 1 +.names V2087(0) V2330 +0 1 +.names V1255(3) V2331 +0 1 +.names V2087(0) V2331 V2332 +11 1 +.names V2330 V1255(3) V2333 +11 1 +.names V2332 V2333 V831 +-1 1 +1- 1 +.names V2058(0) V2334 +0 1 +.names V1255(0) V2335 +0 1 +.names V2058(0) V2335 V2336 +11 1 +.names V2334 V1255(0) V2337 +11 1 +.names V2336 V2337 V838 +-1 1 +1- 1 +.names V2061(0) V2338 +0 1 +.names V1255(1) V2339 +0 1 +.names V2061(0) V2339 V2340 +11 1 +.names V2338 V1255(1) V2341 +11 1 +.names V2340 V2341 V839 +-1 1 +1- 1 +.names V2064(0) V2342 +0 1 +.names V1255(2) V2343 +0 1 +.names V2064(0) V2343 V2344 +11 1 +.names V2342 V1255(2) V2345 +11 1 +.names V2344 V2345 V840 +-1 1 +1- 1 +.names V2067(0) V2346 +0 1 +.names V1255(3) V2347 +0 1 +.names V2067(0) V2347 V2348 +11 1 +.names V2346 V1255(3) V2349 +11 1 +.names V2348 V2349 V841 +-1 1 +1- 1 +.names V2047 V2350 +0 1 +.names V1255(0) V2351 +0 1 +.names V2047 V2351 V2352 +11 1 +.names V2350 V1255(0) V2353 +11 1 +.names V2352 V2353 V848 +-1 1 +1- 1 +.names V2045 V2354 +0 1 +.names V1255(1) V2355 +0 1 +.names V2045 V2355 V2356 +11 1 +.names V2354 V1255(1) V2357 +11 1 +.names V2356 V2357 V849 +-1 1 +1- 1 +.names V2043 V2358 +0 1 +.names V1255(2) V2359 +0 1 +.names V2043 V2359 V2360 +11 1 +.names V2358 V1255(2) V2361 +11 1 +.names V2360 V2361 V850 +-1 1 +1- 1 +.names V2040 V2362 +0 1 +.names V1255(3) V2363 +0 1 +.names V2040 V2363 V2364 +11 1 +.names V2362 V1255(3) V2365 +11 1 +.names V2364 V2365 V851 +-1 1 +1- 1 +.names V2039 V2366 +0 1 +.names V1255(0) V2367 +0 1 +.names V2039 V2367 V2368 +11 1 +.names V2366 V1255(0) V2369 +11 1 +.names V2368 V2369 V858 +-1 1 +1- 1 +.names V2034 V2370 +0 1 +.names V1255(1) V2371 +0 1 +.names V2034 V2371 V2372 +11 1 +.names V2370 V1255(1) V2373 +11 1 +.names V2372 V2373 V859 +-1 1 +1- 1 +.names V2029 V2374 +0 1 +.names V1255(2) V2375 +0 1 +.names V2029 V2375 V2376 +11 1 +.names V2374 V1255(2) V2377 +11 1 +.names V2376 V2377 V860 +-1 1 +1- 1 +.names V2025 V2378 +0 1 +.names V1255(3) V2379 +0 1 +.names V2025 V2379 V2380 +11 1 +.names V2378 V1255(3) V2381 +11 1 +.names V2380 V2381 V861 +-1 1 +1- 1 +.names V1351(0) V2382 +0 1 +.names V1255(0) V2383 +0 1 +.names V1351(0) V2383 V2384 +11 1 +.names V2382 V1255(0) V2385 +11 1 +.names V2384 V2385 V868 +-1 1 +1- 1 +.names V1354(0) V2386 +0 1 +.names V1255(1) V2387 +0 1 +.names V1354(0) V2387 V2388 +11 1 +.names V2386 V1255(1) V2389 +11 1 +.names V2388 V2389 V869 +-1 1 +1- 1 +.names V1357(0) V2390 +0 1 +.names V1255(2) V2391 +0 1 +.names V1357(0) V2391 V2392 +11 1 +.names V2390 V1255(2) V2393 +11 1 +.names V2392 V2393 V870 +-1 1 +1- 1 +.names V1360(0) V2394 +0 1 +.names V1255(3) V2395 +0 1 +.names V1360(0) V2395 V2396 +11 1 +.names V2394 V1255(3) V2397 +11 1 +.names V2396 V2397 V871 +-1 1 +1- 1 +.names V1331(0) V2398 +0 1 +.names V1255(0) V2399 +0 1 +.names V1331(0) V2399 V2400 +11 1 +.names V2398 V1255(0) V2401 +11 1 +.names V2400 V2401 V878 +-1 1 +1- 1 +.names V1334(0) V2402 +0 1 +.names V1255(1) V2403 +0 1 +.names V1334(0) V2403 V2404 +11 1 +.names V2402 V1255(1) V2405 +11 1 +.names V2404 V2405 V879 +-1 1 +1- 1 +.names V1337(0) V2406 +0 1 +.names V1255(2) V2407 +0 1 +.names V1337(0) V2407 V2408 +11 1 +.names V2406 V1255(2) V2409 +11 1 +.names V2408 V2409 V880 +-1 1 +1- 1 +.names V1340(0) V2410 +0 1 +.names V1255(3) V2411 +0 1 +.names V1340(0) V2411 V2412 +11 1 +.names V2410 V1255(3) V2413 +11 1 +.names V2412 V2413 V881 +-1 1 +1- 1 +.names V1320 V2414 +0 1 +.names V1255(0) V2415 +0 1 +.names V1320 V2415 V2416 +11 1 +.names V2414 V1255(0) V2417 +11 1 +.names V2416 V2417 V888 +-1 1 +1- 1 +.names V1318 V2418 +0 1 +.names V1255(1) V2419 +0 1 +.names V1318 V2419 V2420 +11 1 +.names V2418 V1255(1) V2421 +11 1 +.names V2420 V2421 V889 +-1 1 +1- 1 +.names V1316 V2422 +0 1 +.names V1255(2) V2423 +0 1 +.names V1316 V2423 V2424 +11 1 +.names V2422 V1255(2) V2425 +11 1 +.names V2424 V2425 V890 +-1 1 +1- 1 +.names V1313 V2426 +0 1 +.names V1255(3) V2427 +0 1 +.names V1313 V2427 V2428 +11 1 +.names V2426 V1255(3) V2429 +11 1 +.names V2428 V2429 V891 +-1 1 +1- 1 +.names V1312 V2430 +0 1 +.names V1255(0) V2431 +0 1 +.names V1312 V2431 V2432 +11 1 +.names V2430 V1255(0) V2433 +11 1 +.names V2432 V2433 V898 +-1 1 +1- 1 +.names V1307 V2434 +0 1 +.names V1255(1) V2435 +0 1 +.names V1307 V2435 V2436 +11 1 +.names V2434 V1255(1) V2437 +11 1 +.names V2436 V2437 V899 +-1 1 +1- 1 +.names V1302 V2438 +0 1 +.names V1255(2) V2439 +0 1 +.names V1302 V2439 V2440 +11 1 +.names V2438 V1255(2) V2441 +11 1 +.names V2440 V2441 V900 +-1 1 +1- 1 +.names V1298 V2442 +0 1 +.names V1255(3) V2443 +0 1 +.names V1298 V2443 V2444 +11 1 +.names V2442 V1255(3) V2445 +11 1 +.names V2444 V2445 V901 +-1 1 +1- 1 +.names V487(0) V2446 +0 1 +.names V1255(0) V2447 +0 1 +.names V487(0) V2447 V2448 +11 1 +.names V2446 V1255(0) V2449 +11 1 +.names V2448 V2449 V908 +-1 1 +1- 1 +.names V490(0) V2450 +0 1 +.names V1255(1) V2451 +0 1 +.names V490(0) V2451 V2452 +11 1 +.names V2450 V1255(1) V2453 +11 1 +.names V2452 V2453 V909 +-1 1 +1- 1 +.names V493(0) V2454 +0 1 +.names V1255(2) V2455 +0 1 +.names V493(0) V2455 V2456 +11 1 +.names V2454 V1255(2) V2457 +11 1 +.names V2456 V2457 V910 +-1 1 +1- 1 +.names V496(0) V2458 +0 1 +.names V1255(3) V2459 +0 1 +.names V496(0) V2459 V2460 +11 1 +.names V2458 V1255(3) V2461 +11 1 +.names V2460 V2461 V911 +-1 1 +1- 1 +.names V467(0) V2462 +0 1 +.names V1255(0) V2463 +0 1 +.names V467(0) V2463 V2464 +11 1 +.names V2462 V1255(0) V2465 +11 1 +.names V2464 V2465 V918 +-1 1 +1- 1 +.names V470(0) V2466 +0 1 +.names V1255(1) V2467 +0 1 +.names V470(0) V2467 V2468 +11 1 +.names V2466 V1255(1) V2469 +11 1 +.names V2468 V2469 V919 +-1 1 +1- 1 +.names V473(0) V2470 +0 1 +.names V1255(2) V2471 +0 1 +.names V473(0) V2471 V2472 +11 1 +.names V2470 V1255(2) V2473 +11 1 +.names V2472 V2473 V920 +-1 1 +1- 1 +.names V476(0) V2474 +0 1 +.names V1255(3) V2475 +0 1 +.names V476(0) V2475 V2476 +11 1 +.names V2474 V1255(3) V2477 +11 1 +.names V2476 V2477 V921 +-1 1 +1- 1 +.names V456 V2478 +0 1 +.names V1255(0) V2479 +0 1 +.names V456 V2479 V2480 +11 1 +.names V2478 V1255(0) V2481 +11 1 +.names V2480 V2481 V928 +-1 1 +1- 1 +.names V454 V2482 +0 1 +.names V1255(1) V2483 +0 1 +.names V454 V2483 V2484 +11 1 +.names V2482 V1255(1) V2485 +11 1 +.names V2484 V2485 V929 +-1 1 +1- 1 +.names V452 V2486 +0 1 +.names V1255(2) V2487 +0 1 +.names V452 V2487 V2488 +11 1 +.names V2486 V1255(2) V2489 +11 1 +.names V2488 V2489 V930 +-1 1 +1- 1 +.names V333 V2490 +0 1 +.names V1255(3) V2491 +0 1 +.names V333 V2491 V2492 +11 1 +.names V2490 V1255(3) V2493 +11 1 +.names V2492 V2493 V931 +-1 1 +1- 1 +.names V451 V2494 +0 1 +.names V1255(0) V2495 +0 1 +.names V451 V2495 V2496 +11 1 +.names V2494 V1255(0) V2497 +11 1 +.names V2496 V2497 V938 +-1 1 +1- 1 +.names V446 V2498 +0 1 +.names V1255(1) V2499 +0 1 +.names V446 V2499 V2500 +11 1 +.names V2498 V1255(1) V2501 +11 1 +.names V2500 V2501 V939 +-1 1 +1- 1 +.names V441 V2502 +0 1 +.names V1255(2) V2503 +0 1 +.names V441 V2503 V2504 +11 1 +.names V2502 V1255(2) V2505 +11 1 +.names V2504 V2505 V940 +-1 1 +1- 1 +.names V437 V2506 +0 1 +.names V1255(3) V2507 +0 1 +.names V437 V2507 V2508 +11 1 +.names V2506 V1255(3) V2509 +11 1 +.names V2508 V2509 V941 +-1 1 +1- 1 +.names V1846 V2510 +0 1 +.names V2025 V2511 +0 1 +.names V1846 V2511 V2512 +11 1 +.names V2510 V2025 V2513 +11 1 +.names V2512 V2513 V1298 +-1 1 +1- 1 +.names V1848 V2514 +0 1 +.names V2029 V2515 +0 1 +.names V1848 V2515 V2516 +11 1 +.names V2514 V2029 V2517 +11 1 +.names V2516 V2517 V1300 +-1 1 +1- 1 +.names V1839 V2518 +0 1 +.names V2034 V2519 +0 1 +.names V1839 V2519 V2520 +11 1 +.names V2518 V2034 V2521 +11 1 +.names V2520 V2521 V1301 +-1 1 +1- 1 +.names V1300 V2522 +0 1 +.names V1299 V2523 +0 1 +.names V1300 V2523 V2524 +11 1 +.names V2522 V1299 V2525 +11 1 +.names V2524 V2525 V1302 +-1 1 +1- 1 +.names V1306(0) V2526 +0 1 +.names V1301 V2527 +0 1 +.names V1306(0) V2527 V2528 +11 1 +.names V2526 V1301 V2529 +11 1 +.names V2528 V2529 V1307 +-1 1 +1- 1 +.names V2039 V2530 +0 1 +.names V1311(0) V2531 +0 1 +.names V2039 V2531 V2532 +11 1 +.names V2530 V1311(0) V2533 +11 1 +.names V2532 V2533 V1312 +-1 1 +1- 1 +.names V1302 V2534 +0 1 +.names V1313 V2535 +0 1 +.names V1302 V2535 V2536 +11 1 +.names V2534 V1313 V2537 +11 1 +.names V2536 V2537 V1316 +-1 1 +1- 1 +.names V1307 V2538 +0 1 +.names V1317 V2539 +0 1 +.names V1307 V2539 V2540 +11 1 +.names V2538 V1317 V2541 +11 1 +.names V2540 V2541 V1318 +-1 1 +1- 1 +.names V1312 V2542 +0 1 +.names V1319 V2543 +0 1 +.names V1312 V2543 V2544 +11 1 +.names V2542 V1319 V2545 +11 1 +.names V2544 V2545 V1320 +-1 1 +1- 1 +.names V1316 V2546 +0 1 +.names V1321 V2547 +0 1 +.names V1316 V2547 V2548 +11 1 +.names V2546 V1321 V2549 +11 1 +.names V2548 V2549 V1324 +-1 1 +1- 1 +.names V1318 V2550 +0 1 +.names V1325 V2551 +0 1 +.names V1318 V2551 V2552 +11 1 +.names V2550 V1325 V2553 +11 1 +.names V2552 V2553 V1326 +-1 1 +1- 1 +.names V1320 V2554 +0 1 +.names V1327 V2555 +0 1 +.names V1320 V2555 V2556 +11 1 +.names V2554 V1327 V2557 +11 1 +.names V2556 V2557 V1328 +-1 1 +1- 1 +.names V1337(0) V2558 +0 1 +.names V1341 V2559 +0 1 +.names V1337(0) V2559 V2560 +11 1 +.names V2558 V1341 V2561 +11 1 +.names V2560 V2561 V1344 +-1 1 +1- 1 +.names V1334(0) V2562 +0 1 +.names V1345 V2563 +0 1 +.names V1334(0) V2563 V2564 +11 1 +.names V2562 V1345 V2565 +11 1 +.names V2564 V2565 V1346 +-1 1 +1- 1 +.names V1331(0) V2566 +0 1 +.names V1347 V2567 +0 1 +.names V1331(0) V2567 V2568 +11 1 +.names V2566 V1347 V2569 +11 1 +.names V2568 V2569 V1348 +-1 1 +1- 1 +.names V268(0) V2570 +0 1 +.names V1366 V2571 +0 1 +.names V268(0) V2571 V2572 +11 1 +.names V2570 V1366 V2573 +11 1 +.names V2572 V2573 V1370 +-1 1 +1- 1 +.names V268(1) V2574 +0 1 +.names V1367 V2575 +0 1 +.names V268(1) V2575 V2576 +11 1 +.names V2574 V1367 V2577 +11 1 +.names V2576 V2577 V1371 +-1 1 +1- 1 +.names V268(2) V2578 +0 1 +.names V1368 V2579 +0 1 +.names V268(2) V2579 V2580 +11 1 +.names V2578 V1368 V2581 +11 1 +.names V2580 V2581 V1372 +-1 1 +1- 1 +.names V268(3) V2582 +0 1 +.names V1369 V2583 +0 1 +.names V268(3) V2583 V2584 +11 1 +.names V2582 V1369 V2585 +11 1 +.names V2584 V2585 V1373 +-1 1 +1- 1 +.names V268(4) V2586 +0 1 +.names V268(5) V2587 +0 1 +.names V268(4) V2587 V2588 +11 1 +.names V2586 V268(5) V2589 +11 1 +.names V2588 V2589 V1374 +-1 1 +1- 1 +.names V78(1) V2590 +0 1 +.names V78(0) V2591 +0 1 +.names V78(1) V2591 V2592 +11 1 +.names V2590 V78(0) V2593 +11 1 +.names V2592 V2593 V1579 +-1 1 +1- 1 +.names V78(3) V2594 +0 1 +.names V78(2) V2595 +0 1 +.names V78(3) V2595 V2596 +11 1 +.names V2594 V78(2) V2597 +11 1 +.names V2596 V2597 V1580 +-1 1 +1- 1 +.names V78(5) V2598 +0 1 +.names V78(4) V2599 +0 1 +.names V78(5) V2599 V2600 +11 1 +.names V2598 V78(4) V2601 +11 1 +.names V2600 V2601 V1581 +-1 1 +1- 1 +.names V84(1) V2602 +0 1 +.names V84(0) V2603 +0 1 +.names V84(1) V2603 V2604 +11 1 +.names V2602 V84(0) V2605 +11 1 +.names V2604 V2605 V1582 +-1 1 +1- 1 +.names V84(3) V2606 +0 1 +.names V84(2) V2607 +0 1 +.names V84(3) V2607 V2608 +11 1 +.names V2606 V84(2) V2609 +11 1 +.names V2608 V2609 V1583 +-1 1 +1- 1 +.names V84(5) V2610 +0 1 +.names V84(4) V2611 +0 1 +.names V84(5) V2611 V2612 +11 1 +.names V2610 V84(4) V2613 +11 1 +.names V2612 V2613 V1584 +-1 1 +1- 1 +.names V88(1) V2614 +0 1 +.names V88(0) V2615 +0 1 +.names V88(1) V2615 V2616 +11 1 +.names V2614 V88(0) V2617 +11 1 +.names V2616 V2617 V1585 +-1 1 +1- 1 +.names V88(3) V2618 +0 1 +.names V88(2) V2619 +0 1 +.names V88(3) V2619 V2620 +11 1 +.names V2618 V88(2) V2621 +11 1 +.names V2620 V2621 V1586 +-1 1 +1- 1 +.names V1580 V2622 +0 1 +.names V1579 V2623 +0 1 +.names V1580 V2623 V2624 +11 1 +.names V2622 V1579 V2625 +11 1 +.names V2624 V2625 V1587 +-1 1 +1- 1 +.names V1582 V2626 +0 1 +.names V1581 V2627 +0 1 +.names V1582 V2627 V2628 +11 1 +.names V2626 V1581 V2629 +11 1 +.names V2628 V2629 V1588 +-1 1 +1- 1 +.names V1584 V2630 +0 1 +.names V1583 V2631 +0 1 +.names V1584 V2631 V2632 +11 1 +.names V2630 V1583 V2633 +11 1 +.names V2632 V2633 V1589 +-1 1 +1- 1 +.names V1586 V2634 +0 1 +.names V1585 V2635 +0 1 +.names V1586 V2635 V2636 +11 1 +.names V2634 V1585 V2637 +11 1 +.names V2636 V2637 V1590 +-1 1 +1- 1 +.names V1588 V2638 +0 1 +.names V1587 V2639 +0 1 +.names V1588 V2639 V2640 +11 1 +.names V2638 V1587 V2641 +11 1 +.names V2640 V2641 V1591 +-1 1 +1- 1 +.names V1590 V2642 +0 1 +.names V1589 V2643 +0 1 +.names V1590 V2643 V2644 +11 1 +.names V2642 V1589 V2645 +11 1 +.names V2644 V2645 V1592 +-1 1 +1- 1 +.names V94(0) V2646 +0 1 +.names V1591 V2647 +0 1 +.names V94(0) V2647 V2648 +11 1 +.names V2646 V1591 V2649 +11 1 +.names V2648 V2649 V1593 +-1 1 +1- 1 +.names V94(1) V2650 +0 1 +.names V1592 V2651 +0 1 +.names V94(1) V2651 V2652 +11 1 +.names V2650 V1592 V2653 +11 1 +.names V2652 V2653 V1594 +-1 1 +1- 1 +.names V1921(1) V2654 +0 1 +.names V1921(0) V2655 +0 1 +.names V1921(1) V2655 V2656 +11 1 +.names V2654 V1921(0) V2657 +11 1 +.names V2656 V2657 V1598 +-1 1 +1- 1 +.names V1921(3) V2658 +0 1 +.names V1921(2) V2659 +0 1 +.names V1921(3) V2659 V2660 +11 1 +.names V2658 V1921(2) V2661 +11 1 +.names V2660 V2661 V1599 +-1 1 +1- 1 +.names V1921(5) V2662 +0 1 +.names V1921(4) V2663 +0 1 +.names V1921(5) V2663 V2664 +11 1 +.names V2662 V1921(4) V2665 +11 1 +.names V2664 V2665 V1600 +-1 1 +1- 1 +.names V1953(1) V2666 +0 1 +.names V1953(0) V2667 +0 1 +.names V1953(1) V2667 V2668 +11 1 +.names V2666 V1953(0) V2669 +11 1 +.names V2668 V2669 V1601 +-1 1 +1- 1 +.names V1953(3) V2670 +0 1 +.names V1953(2) V2671 +0 1 +.names V1953(3) V2671 V2672 +11 1 +.names V2670 V1953(2) V2673 +11 1 +.names V2672 V2673 V1602 +-1 1 +1- 1 +.names V1953(5) V2674 +0 1 +.names V1953(4) V2675 +0 1 +.names V1953(5) V2675 V2676 +11 1 +.names V2674 V1953(4) V2677 +11 1 +.names V2676 V2677 V1603 +-1 1 +1- 1 +.names V1953(7) V2678 +0 1 +.names V1953(6) V2679 +0 1 +.names V1953(7) V2679 V2680 +11 1 +.names V2678 V1953(6) V2681 +11 1 +.names V2680 V2681 V1604 +-1 1 +1- 1 +.names V1960(1) V2682 +0 1 +.names V1960(0) V2683 +0 1 +.names V1960(1) V2683 V2684 +11 1 +.names V2682 V1960(0) V2685 +11 1 +.names V2684 V2685 V1605 +-1 1 +1- 1 +.names V1599 V2686 +0 1 +.names V1598 V2687 +0 1 +.names V1599 V2687 V2688 +11 1 +.names V2686 V1598 V2689 +11 1 +.names V2688 V2689 V1606 +-1 1 +1- 1 +.names V1601 V2690 +0 1 +.names V1600 V2691 +0 1 +.names V1601 V2691 V2692 +11 1 +.names V2690 V1600 V2693 +11 1 +.names V2692 V2693 V1607 +-1 1 +1- 1 +.names V1603 V2694 +0 1 +.names V1602 V2695 +0 1 +.names V1603 V2695 V2696 +11 1 +.names V2694 V1602 V2697 +11 1 +.names V2696 V2697 V1608 +-1 1 +1- 1 +.names V1605 V2698 +0 1 +.names V1604 V2699 +0 1 +.names V1605 V2699 V2700 +11 1 +.names V2698 V1604 V2701 +11 1 +.names V2700 V2701 V1609 +-1 1 +1- 1 +.names V1607 V2702 +0 1 +.names V1606 V2703 +0 1 +.names V1607 V2703 V2704 +11 1 +.names V2702 V1606 V2705 +11 1 +.names V2704 V2705 V1610 +-1 1 +1- 1 +.names V1609 V2706 +0 1 +.names V1608 V2707 +0 1 +.names V1609 V2707 V2708 +11 1 +.names V2706 V1608 V2709 +11 1 +.names V2708 V2709 V1611 +-1 1 +1- 1 +.names V194(0) V2710 +0 1 +.names V1867 V2711 +0 1 +.names V194(0) V2711 V2712 +11 1 +.names V2710 V1867 V2713 +11 1 +.names V2712 V2713 V1875 +-1 1 +1- 1 +.names V194(1) V2714 +0 1 +.names V1868 V2715 +0 1 +.names V194(1) V2715 V2716 +11 1 +.names V2714 V1868 V2717 +11 1 +.names V2716 V2717 V1876 +-1 1 +1- 1 +.names V194(2) V2718 +0 1 +.names V1869 V2719 +0 1 +.names V194(2) V2719 V2720 +11 1 +.names V2718 V1869 V2721 +11 1 +.names V2720 V2721 V1877 +-1 1 +1- 1 +.names V194(3) V2722 +0 1 +.names V1870 V2723 +0 1 +.names V194(3) V2723 V2724 +11 1 +.names V2722 V1870 V2725 +11 1 +.names V2724 V2725 V1878 +-1 1 +1- 1 +.names V194(4) V2726 +0 1 +.names V1871 V2727 +0 1 +.names V194(4) V2727 V2728 +11 1 +.names V2726 V1871 V2729 +11 1 +.names V2728 V2729 V1879 +-1 1 +1- 1 +.names V199(0) V2730 +0 1 +.names V1872 V2731 +0 1 +.names V199(0) V2731 V2732 +11 1 +.names V2730 V1872 V2733 +11 1 +.names V2732 V2733 V1880 +-1 1 +1- 1 +.names V199(1) V2734 +0 1 +.names V1873 V2735 +0 1 +.names V199(1) V2735 V2736 +11 1 +.names V2734 V1873 V2737 +11 1 +.names V2736 V2737 V1881 +-1 1 +1- 1 +.names V199(2) V2738 +0 1 +.names V1874 V2739 +0 1 +.names V199(2) V2739 V2740 +11 1 +.names V2738 V1874 V2741 +11 1 +.names V2740 V2741 V1882 +-1 1 +1- 1 +.names V199(3) V2742 +0 1 +.names V199(4) V2743 +0 1 +.names V199(3) V2743 V2744 +11 1 +.names V2742 V199(4) V2745 +11 1 +.names V2744 V2745 V1883 +-1 1 +1- 1 +.names V288(7) V2746 +0 1 +.names V288(6) V2747 +0 1 +.names V288(7) V2747 V2748 +11 1 +.names V2746 V288(6) V2749 +11 1 +.names V2748 V2749 V1973 +-1 1 +1- 1 +.names V239(4) V2750 +0 1 +.names V239(3) V2751 +0 1 +.names V239(4) V2751 V2752 +11 1 +.names V2750 V239(3) V2753 +11 1 +.names V2752 V2753 V1986 +-1 1 +1- 1 +.names V134(1) V2754 +0 1 +.names V134(0) V2755 +0 1 +.names V134(1) V2755 V2756 +11 1 +.names V2754 V134(0) V2757 +11 1 +.names V2756 V2757 V1994 +-1 1 +1- 1 +.names V1842 V2758 +0 1 +.names V1976(0) V2759 +0 1 +.names V1842 V2759 V2760 +11 1 +.names V2758 V1976(0) V2761 +11 1 +.names V2760 V2761 V2025 +-1 1 +1- 1 +.names V1844 V2762 +0 1 +.names V1975(0) V2763 +0 1 +.names V1844 V2763 V2764 +11 1 +.names V2762 V1975(0) V2765 +11 1 +.names V2764 V2765 V2027 +-1 1 +1- 1 +.names V1840 V2766 +0 1 +.names V1972 V2767 +0 1 +.names V1840 V2767 V2768 +11 1 +.names V2766 V1972 V2769 +11 1 +.names V2768 V2769 V2028 +-1 1 +1- 1 +.names V2027 V2770 +0 1 +.names V2026 V2771 +0 1 +.names V2027 V2771 V2772 +11 1 +.names V2770 V2026 V2773 +11 1 +.names V2772 V2773 V2029 +-1 1 +1- 1 +.names V2033(0) V2774 +0 1 +.names V2028 V2775 +0 1 +.names V2033(0) V2775 V2776 +11 1 +.names V2774 V2028 V2777 +11 1 +.names V2776 V2777 V2034 +-1 1 +1- 1 +.names V1972 V2778 +0 1 +.names V2038(0) V2779 +0 1 +.names V1972 V2779 V2780 +11 1 +.names V2778 V2038(0) V2781 +11 1 +.names V2780 V2781 V2039 +-1 1 +1- 1 +.names V2029 V2782 +0 1 +.names V2040 V2783 +0 1 +.names V2029 V2783 V2784 +11 1 +.names V2782 V2040 V2785 +11 1 +.names V2784 V2785 V2043 +-1 1 +1- 1 +.names V2034 V2786 +0 1 +.names V2044 V2787 +0 1 +.names V2034 V2787 V2788 +11 1 +.names V2786 V2044 V2789 +11 1 +.names V2788 V2789 V2045 +-1 1 +1- 1 +.names V2039 V2790 +0 1 +.names V2046 V2791 +0 1 +.names V2039 V2791 V2792 +11 1 +.names V2790 V2046 V2793 +11 1 +.names V2792 V2793 V2047 +-1 1 +1- 1 +.names V2043 V2794 +0 1 +.names V2048 V2795 +0 1 +.names V2043 V2795 V2796 +11 1 +.names V2794 V2048 V2797 +11 1 +.names V2796 V2797 V2051 +-1 1 +1- 1 +.names V2045 V2798 +0 1 +.names V2052 V2799 +0 1 +.names V2045 V2799 V2800 +11 1 +.names V2798 V2052 V2801 +11 1 +.names V2800 V2801 V2053 +-1 1 +1- 1 +.names V2047 V2802 +0 1 +.names V2054 V2803 +0 1 +.names V2047 V2803 V2804 +11 1 +.names V2802 V2054 V2805 +11 1 +.names V2804 V2805 V2055 +-1 1 +1- 1 +.names V2064(0) V2806 +0 1 +.names V2068 V2807 +0 1 +.names V2064(0) V2807 V2808 +11 1 +.names V2806 V2068 V2809 +11 1 +.names V2808 V2809 V2071 +-1 1 +1- 1 +.names V2061(0) V2810 +0 1 +.names V2072 V2811 +0 1 +.names V2061(0) V2811 V2812 +11 1 +.names V2810 V2072 V2813 +11 1 +.names V2812 V2813 V2073 +-1 1 +1- 1 +.names V2058(0) V2814 +0 1 +.names V2074 V2815 +0 1 +.names V2058(0) V2815 V2816 +11 1 +.names V2814 V2074 V2817 +11 1 +.names V2816 V2817 V2075 +-1 1 +1- 1 diff --git a/abc70930/examples/pj1.blif b/abc70930/examples/pj1.blif new file mode 100644 index 00000000..efc7e645 --- /dev/null +++ b/abc70930/examples/pj1.blif @@ -0,0 +1,120216 @@ +.model exCombCkt +.inputs 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 \ +27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 \ +53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 \ +79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 \ +104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 \ +123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 \ +142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 \ +161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 \ +180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 \ +199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 \ +218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 \ +237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 \ +256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 \ +275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 \ +294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 \ +313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 \ +332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 \ +351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 \ +370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 \ +389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 \ +408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 \ +427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 \ +446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 \ +465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 \ +484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 \ +503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 \ +522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 \ +541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 \ +560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 \ +579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 \ +598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 \ +617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 \ +636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 \ +655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 \ +674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 \ +693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 \ +712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 \ +731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 \ +750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 \ +769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 \ +788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 \ +807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 \ +826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 \ +845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 \ +864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 \ +883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 \ +902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 \ +921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 \ +940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 \ +959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 \ +978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 \ +997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 \ +1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 \ +1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 \ +1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 \ +1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 \ +1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 \ +1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 \ +1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 \ +1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 \ +1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 \ +1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 \ +1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 \ +1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 \ +1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 \ +1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 \ +1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 \ +1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 \ +1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 \ +1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 \ +1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 \ +1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 \ +1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 \ +1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 \ +1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 \ +1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 \ +1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 \ +1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 \ +1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 \ +1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 \ +1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 \ +1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 \ +1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 \ +1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 \ +1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 \ +1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 \ +1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 \ +1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 \ +1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 \ +1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 \ +1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 \ +1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 \ +1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 \ +1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 \ +1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 \ +1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 \ +1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 \ +1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 \ +1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 \ +1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 \ +1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 \ +1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 \ +1763 1764 1765 1766 1767 1768 +.outputs 56405 56406 56407 56408 56409 56410 56411 56412 56413 56414 56415 \ +56416 56417 56418 56419 56420 56421 56422 56423 56424 56425 56426 56427 56428 \ +56429 56430 56431 56432 56433 56434 56435 56436 56437 56438 56439 56440 56441 \ +56442 56443 56444 56445 56446 56447 56448 56449 56450 56451 56452 56453 56454 \ +56455 56456 56457 56458 56459 56460 56461 56462 56463 56464 56465 56466 56467 \ +56468 56469 56470 56471 56472 56473 56474 56475 56476 56477 56478 56479 56480 \ +56481 56482 56483 56484 56485 56486 56487 56488 56489 56490 56491 56492 56493 \ +56494 56495 56496 56497 56498 56499 56500 56501 56502 56503 56504 56505 56506 \ +56507 56508 56509 56510 56511 56512 56513 56514 56515 56516 56517 56518 56519 \ +56520 56521 56522 56523 56524 56525 56526 56527 56528 56529 56530 56531 56532 \ +56533 56534 56535 56536 56537 56538 56539 56540 56541 56542 56543 56544 56545 \ +56546 56547 56548 56549 56550 56551 56552 56553 56554 56555 56556 56557 56558 \ +56559 56560 56561 56562 56563 56564 56565 56566 56567 56568 56569 56570 56571 \ +56572 56573 56574 56575 56576 56577 56578 56579 56580 56581 56582 56583 56584 \ +56585 56586 56587 56588 56589 56590 56591 56592 56593 56594 56595 56596 56597 \ +56598 56599 56600 56601 56602 56603 56604 56605 56606 56607 56608 56609 56610 \ +56611 56612 56613 56614 56615 56616 56617 56618 56619 56620 56621 56622 56623 \ +56624 56625 56626 56627 56628 56629 56630 56631 56632 56633 56634 56635 56636 \ +56637 56638 56639 56640 56641 56642 56643 56644 56645 56646 56647 56648 56649 \ +56650 56651 56652 56653 56654 56655 56656 56657 56658 56659 56660 56661 56662 \ +56663 56664 56665 56666 56667 56668 56669 56670 56671 56672 56673 56674 56675 \ +56676 56677 56678 56679 56680 56681 56682 56683 56684 56685 56686 56687 56688 \ +56689 56690 56691 56692 56693 56694 56695 56696 56697 56698 56699 56700 56701 \ +56702 56703 56704 56705 56706 56707 56708 56709 56710 56711 56712 56713 56714 \ +56715 56716 56717 56718 56719 56720 56721 56722 56723 56724 56725 56726 56727 \ +56728 56729 56730 56731 56732 56733 56734 56735 56736 56737 56738 56739 56740 \ +56741 56742 56743 56744 56745 56746 56747 56748 56749 56750 56751 56752 56753 \ +56754 56755 56756 56757 56758 56759 56760 56761 56762 56763 56764 56765 56766 \ +56767 56768 56769 56770 56771 56772 56773 56774 56775 56776 56777 56778 56779 \ +56780 56781 56782 56783 56784 56785 56786 56787 56788 56789 56790 56791 56792 \ +56793 56794 56795 56796 56797 56798 56799 56800 56801 56802 56803 56804 56805 \ +56806 56807 56808 56809 56810 56811 56812 56813 56814 56815 56816 56817 56818 \ +56819 56820 56821 56822 56823 56824 56825 56826 56827 56828 56829 56830 56831 \ +56832 56833 56834 56835 56836 56837 56838 56839 56840 56841 56842 56843 56844 \ +56845 56846 56847 56848 56849 56850 56851 56852 56853 56854 56855 56856 56857 \ +56858 56859 56860 56861 56862 56863 56864 56865 56866 56867 56868 56869 56870 \ +56871 56872 56873 56874 56875 56876 56877 56878 56879 56880 56881 56882 56883 \ +56884 56885 56886 56887 56888 56889 56890 56891 56892 56893 56894 56895 56896 \ +56897 56898 56899 56900 56901 56902 56903 56904 56905 56906 56907 56908 56909 \ +56910 56911 56912 56913 56914 56915 56916 56917 56918 56919 56920 56921 56922 \ +56923 56924 56925 56926 56927 56928 56929 56930 56931 56932 56933 56934 56935 \ +56936 56937 56938 56939 56940 56941 56942 56943 56944 56945 56946 56947 56948 \ +56949 56950 56951 56952 56953 56954 56955 56956 56957 56958 56959 56960 56961 \ +56962 56963 56964 56965 56966 56967 56968 56969 56970 56971 56972 56973 56974 \ +56975 56976 56977 56978 56979 56980 56981 56982 56983 56984 56985 56986 56987 \ +56988 56989 56990 56991 56992 56993 56994 56995 56996 56997 56998 56999 57000 \ +57001 57002 57003 57004 57005 57006 57007 57008 57009 57010 57011 57012 57013 \ +57014 57015 57016 57017 57018 57019 57020 57021 57022 57023 57024 57025 57026 \ +57027 57028 57029 57030 57031 57032 57033 57034 57035 57036 57037 57038 57039 \ +57040 57041 57042 57043 57044 57045 57046 57047 57048 57049 57050 57051 57052 \ +57053 57054 57055 57056 57057 57058 57059 57060 57061 57062 57063 57064 57065 \ +57066 57067 57068 57069 57070 57071 57072 57073 57074 57075 57076 57077 57078 \ +57079 57080 57081 57082 57083 57084 57085 57086 57087 57088 57089 57090 57091 \ +57092 57093 57094 57095 57096 57097 57098 57099 57100 57101 57102 57103 57104 \ +57105 57106 57107 57108 57109 57110 57111 57112 57113 57114 57115 57116 57117 \ +57118 57119 57120 57121 57122 57123 57124 57125 57126 57127 57128 57129 57130 \ +57131 57132 57133 57134 57135 57136 57137 57138 57139 57140 57141 57142 57143 \ +57144 57145 57146 57147 57148 57149 57150 57151 57152 57153 57154 57155 57156 \ +57157 57158 57159 57160 57161 57162 57163 57164 57165 57166 57167 57168 57169 \ +57170 57171 57172 57173 57174 57175 57176 57177 57178 57179 57180 57181 57182 \ +57183 57184 57185 57186 57187 57188 57189 57190 57191 57192 57193 57194 57195 \ +57196 57197 57198 57199 57200 57201 57202 57203 57204 57205 57206 57207 57208 \ +57209 57210 57211 57212 57213 57214 57215 57216 57217 57218 57219 57220 57221 \ +57222 57223 57224 57225 57226 57227 57228 57229 57230 57231 57232 57233 57234 \ +57235 57236 57237 57238 57239 57240 57241 57242 57243 57244 57245 57246 57247 \ +57248 57249 57250 57251 57252 57253 57254 57255 57256 57257 57258 57259 57260 \ +57261 57262 57263 57264 57265 57266 57267 57268 57269 57270 57271 57272 57273 \ +57274 57275 57276 57277 57278 57279 57280 57281 57282 57283 57284 57285 57286 \ +57287 57288 57289 57290 57291 57292 57293 57294 57295 57296 57297 57298 57299 \ +57300 57301 57302 57303 57304 57305 57306 57307 57308 57309 57310 57311 57312 \ +57313 57314 57315 57316 57317 57318 57319 57320 57321 57322 57323 57324 57325 \ +57326 57327 57328 57329 57330 57331 57332 57333 57334 57335 57336 57337 57338 \ +57339 57340 57341 57342 57343 57344 57345 57346 57347 57348 57349 57350 57351 \ +57352 57353 57354 57355 57356 57357 57358 57359 57360 57361 57362 57363 57364 \ +57365 57366 57367 57368 57369 57370 57371 57372 57373 57374 57375 57376 57377 \ +57378 57379 57380 57381 57382 57383 57384 57385 57386 57387 57388 57389 57390 \ +57391 57392 57393 57394 57395 57396 57397 57398 57399 57400 57401 57402 57403 \ +57404 57405 57406 57407 57408 57409 57410 57411 57412 57413 57414 57415 57416 \ +57417 57418 57419 57420 57421 57422 57423 57424 57425 57426 57427 57428 57429 \ +57430 57431 57432 57433 57434 57435 57436 57437 57438 57439 57440 57441 57442 \ +57443 57444 57445 57446 57447 57448 57449 57450 57451 57452 57453 57454 57455 \ +57456 57457 57458 57459 57460 57461 57462 57463 57464 57465 57466 57467 +.names 1771 1769 +1 1 +.names 1769 1770 +1 1 +.names 9415 9401 1771 +11 1 +.names 1774 1772 +1 1 +.names 1772 1773 +1 1 +.names 1769 1774 +0 1 +.names 1775 + 1 +.names 1775 1776 +1 1 +.names 1779 1777 +1 1 +.names 1777 1778 +1 1 +.names 9429 9417 1779 +11 1 +.names 1782 1780 +1 1 +.names 1780 1781 +1 1 +.names 1777 1782 +0 1 +.names 1783 +.names 1783 1784 +1 1 +.names 1787 1785 +1 1 +.names 1785 1786 +1 1 +.names 9370 9360 1787 +11 1 +.names 1790 1788 +1 1 +.names 1788 1789 +1 1 +.names 1785 1790 +0 1 +.names 1793 1791 +1 1 +.names 1791 1792 +1 1 +.names 9386 9374 1793 +11 1 +.names 1796 1794 +1 1 +.names 1794 1795 +1 1 +.names 1791 1796 +0 1 +.names 1799 1797 +1 1 +.names 1797 1798 +1 1 +.names 9312 9302 1799 +11 1 +.names 1802 1800 +1 1 +.names 1800 1801 +1 1 +.names 1797 1802 +0 1 +.names 1805 1803 +1 1 +.names 1803 1804 +1 1 +.names 9328 9316 1805 +11 1 +.names 1808 1806 +1 1 +.names 1806 1807 +1 1 +.names 1803 1808 +0 1 +.names 57131 1809 +1 1 +.names 1809 1810 +1 1 +.names 714 57131 +0 1 +.names 714 1812 +1 1 +.names 1809 1813 +1 1 +.names 714 1814 +1 1 +.names 1809 1815 +1 1 +.names 714 1816 +1 1 +.names 1819 1817 +1 1 +.names 1817 1818 +1 1 +.names 9250 9243 1819 +11 1 +.names 1822 1820 +1 1 +.names 1820 1821 +1 1 +.names 1817 1822 +0 1 +.names 1825 1823 +1 1 +.names 1823 1824 +1 1 +.names 9228 9221 1825 +11 1 +.names 1828 1826 +1 1 +.names 1826 1827 +1 1 +.names 1823 1828 +0 1 +.names 715 1829 +1 1 +.names 1832 1830 +1 1 +.names 1830 1831 +1 1 +.names 715 1832 +0 1 +.names 56408 1833 +1 1 +.names 2285 2286 56408 +1- 1 +-1 1 +.names 56407 1835 +1 1 +.names 2302 2303 56407 +1- 1 +-1 1 +.names 56406 1837 +1 1 +.names 2319 2320 56406 +1- 1 +-1 1 +.names 56405 1839 +1 1 +.names 2336 2337 56405 +1- 1 +-1 1 +.names 1783 1841 +1 1 +.names 1844 1842 +1 1 +.names 1842 1843 +1 1 +.names 9126 9118 1844 +11 1 +.names 1847 1845 +1 1 +.names 1845 1846 +1 1 +.names 1842 1847 +0 1 +.names 1850 1848 +1 1 +.names 1848 1849 +1 1 +.names 9033 9026 1850 +11 1 +.names 1853 1851 +1 1 +.names 1851 1852 +1 1 +.names 1848 1853 +0 1 +.names 1856 1854 +1 1 +.names 1854 1855 +1 1 +.names 924 925 1856 +1- 1 +-1 1 +.names 1859 1857 +1 1 +.names 1857 1858 +1 1 +.names 1854 1859 +0 1 +.names 716 1860 +1 1 +.names 1863 1861 +1 1 +.names 1861 1862 +1 1 +.names 8575 0 1863 +11 1 +.names 1866 1864 +1 1 +.names 1864 1865 +1 1 +.names 1861 1866 +0 1 +.names 717 1867 +1 1 +.names 1870 1868 +1 1 +.names 1868 1869 +1 1 +.names 8569 0 1870 +11 1 +.names 1873 1871 +1 1 +.names 1871 1872 +1 1 +.names 1868 1873 +0 1 +.names 1876 1874 +1 1 +.names 1874 1875 +1 1 +.names 8582 2360 1876 +1- 1 +-1 1 +.names 718 1877 +1 1 +.names 1880 1878 +1 1 +.names 1878 1879 +1 1 +.names 8698 8562 1880 +11 1 +.names 1883 1881 +1 1 +.names 1881 1882 +1 1 +.names 8688 8681 1883 +11 1 +.names 1886 1884 +1 1 +.names 1884 1885 +1 1 +.names 8680 8672 1886 +11 1 +.names 1889 1887 +1 1 +.names 1887 1888 +1 1 +.names 8671 8663 1889 +11 1 +.names 1892 1890 +1 1 +.names 1890 1891 +1 1 +.names 8662 8653 1892 +11 1 +.names 1895 1893 +1 1 +.names 1893 1894 +1 1 +.names 8652 8643 1895 +11 1 +.names 1898 1896 +1 1 +.names 1896 1897 +1 1 +.names 8642 8634 1898 +11 1 +.names 1901 1899 +1 1 +.names 1899 1900 +1 1 +.names 8633 8623 1901 +11 1 +.names 1904 1902 +1 1 +.names 1902 1903 +1 1 +.names 8622 8620 1904 +1- 1 +-1 1 +.names 4 1905 +1 1 +.names 3 1906 +1 1 +.names 2 1907 +1 1 +.names 1 1908 +1 1 +.names 0 1909 +1 1 +.names 1912 1910 +1 1 +.names 1910 1911 +1 1 +.names 2401 2403 1912 +01 1 +10 1 +.names 1915 1913 +1 1 +.names 1913 1914 +1 1 +.names 2404 2406 1915 +01 1 +10 1 +.names 1918 1916 +1 1 +.names 1916 1917 +1 1 +.names 2416 2418 1918 +01 1 +10 1 +.names 1921 1919 +1 1 +.names 1919 1920 +1 1 +.names 2427 2429 1921 +01 1 +10 1 +.names 1924 1922 +1 1 +.names 1922 1923 +1 1 +.names 2438 1783 1924 +01 1 +10 1 +.names 1878 1925 +1 1 +.names 1881 1926 +1 1 +.names 1884 1927 +1 1 +.names 1887 1928 +1 1 +.names 1890 1929 +1 1 +.names 1893 1930 +1 1 +.names 1896 1931 +1 1 +.names 1899 1932 +1 1 +.names 1902 1933 +1 1 +.names 1939 1902 1934 +1- 1 +-1 1 +.names 1934 1935 +1 1 +.names 1878 1881 1936 +1- 1 +-1 1 +.names 1936 1884 1937 +1- 1 +-1 1 +.names 1937 1887 1938 +1- 1 +-1 1 +.names 1938 1896 1939 +1- 1 +-1 1 +.names 1890 1940 +1 1 +.names 1893 1941 +1 1 +.names 1899 1942 +1 1 +.names 715 1943 +1 1 +.names 1878 1944 +1 1 +.names 1952 1902 1945 +1- 1 +-1 1 +.names 1945 1946 +1 1 +.names 1881 1884 1947 +1- 1 +-1 1 +.names 1947 1887 1948 +1- 1 +-1 1 +.names 1948 1890 1949 +1- 1 +-1 1 +.names 1949 1893 1950 +1- 1 +-1 1 +.names 1950 1896 1951 +1- 1 +-1 1 +.names 1951 1899 1952 +1- 1 +-1 1 +.names 1878 1953 +1 1 +.names 1961 1902 1954 +1- 1 +-1 1 +.names 1954 1955 +1 1 +.names 1881 1884 1956 +1- 1 +-1 1 +.names 1956 1887 1957 +1- 1 +-1 1 +.names 1957 1890 1958 +1- 1 +-1 1 +.names 1958 1893 1959 +1- 1 +-1 1 +.names 1959 1896 1960 +1- 1 +-1 1 +.names 1960 1899 1961 +1- 1 +-1 1 +.names 1878 1962 +1 1 +.names 1970 1902 1963 +1- 1 +-1 1 +.names 1963 1964 +1 1 +.names 1881 1884 1965 +1- 1 +-1 1 +.names 1965 1887 1966 +1- 1 +-1 1 +.names 1966 1890 1967 +1- 1 +-1 1 +.names 1967 1893 1968 +1- 1 +-1 1 +.names 1968 1896 1969 +1- 1 +-1 1 +.names 1969 1899 1970 +1- 1 +-1 1 +.names 1890 1971 +1 1 +.names 1893 1972 +1 1 +.names 1884 1973 +1 1 +.names 1976 1974 +1 1 +.names 1974 1975 +1 1 +.names 5363 5361 1976 +1- 1 +-1 1 +.names 1979 1977 +1 1 +.names 1977 1978 +1 1 +.names 1974 1979 +0 1 +.names 1982 1980 +1 1 +.names 1980 1981 +1 1 +.names 719 1982 +0 1 +.names 719 1983 +1 1 +.names 1986 1984 +1 1 +.names 1984 1985 +1 1 +.names 726 56666 1986 +11 1 +.names 1984 1987 +0 1 +.names 1987 1988 +1 1 +.names 719 1989 +1 1 +.names 1992 1990 +1 1 +.names 1990 1991 +1 1 +.names 3075 3073 1992 +11 1 +.names 1990 1993 +0 1 +.names 1993 1994 +1 1 +.names 1998 2001 1995 +1- 1 +-1 1 +.names 1995 1996 +1 1 +.names 1770 1783 1997 +11 1 +.names 1783 1997 1998 +1- 1 +-1 1 +.names 9399 715 1999 +11 1 +.names 1999 2000 +1 1 +.names 1773 2000 2001 +11 1 +.names 2005 2006 2002 +1- 1 +-1 1 +.names 2002 2003 +1 1 +.names 1778 1775 2004 +11 1 +.names 1783 2004 2005 +1- 1 +-1 1 +.names 1781 1769 2006 +11 1 +.names 2010 2011 2007 +1- 1 +-1 1 +.names 2007 2008 +1 1 +.names 1778 1776 2009 +11 1 +.names 1783 2009 2010 +1- 1 +-1 1 +.names 1781 1996 2011 +11 1 +.names 2015 2018 2012 +1- 1 +-1 1 +.names 2012 2013 +1 1 +.names 1786 1784 2014 +11 1 +.names 1783 2014 2015 +1- 1 +-1 1 +.names 9356 9330 2016 +11 1 +.names 2016 2017 +1 1 +.names 1789 2017 2018 +11 1 +.names 2022 2023 2019 +1- 1 +-1 1 +.names 2019 2020 +1 1 +.names 1792 1775 2021 +11 1 +.names 1783 2021 2022 +1- 1 +-1 1 +.names 1795 1785 2023 +11 1 +.names 2027 2028 2024 +1- 1 +-1 1 +.names 2024 2025 +1 1 +.names 1792 1775 2026 +11 1 +.names 1783 2026 2027 +1- 1 +-1 1 +.names 1795 2013 2028 +11 1 +.names 2032 2035 2029 +1- 1 +-1 1 +.names 2029 2030 +1 1 +.names 1798 1783 2031 +11 1 +.names 1783 2031 2032 +1- 1 +-1 1 +.names 9298 715 2033 +11 1 +.names 2033 2034 +1 1 +.names 1801 2034 2035 +11 1 +.names 2039 2040 2036 +1- 1 +-1 1 +.names 2036 2037 +1 1 +.names 1804 1775 2038 +11 1 +.names 1783 2038 2039 +1- 1 +-1 1 +.names 1807 1797 2040 +11 1 +.names 2044 2045 2041 +1- 1 +-1 1 +.names 2041 2042 +1 1 +.names 1804 1775 2043 +11 1 +.names 1783 2043 2044 +1- 1 +-1 1 +.names 1807 2030 2045 +11 1 +.names 2048 2049 56596 +1- 1 +-1 1 +.names 1810 1783 2047 +11 1 +.names 1783 2047 2048 +1- 1 +-1 1 +.names 1812 2003 2049 +11 1 +.names 2052 2053 56595 +1- 1 +-1 1 +.names 1810 1783 2051 +11 1 +.names 1783 2051 2052 +1- 1 +-1 1 +.names 1812 2008 2053 +11 1 +.names 2056 2057 56598 +1- 1 +-1 1 +.names 1813 1783 2055 +11 1 +.names 1783 2055 2056 +1- 1 +-1 1 +.names 1814 2020 2057 +11 1 +.names 2060 2061 56597 +1- 1 +-1 1 +.names 1813 1783 2059 +11 1 +.names 1783 2059 2060 +1- 1 +-1 1 +.names 1814 2025 2061 +11 1 +.names 2064 2065 56558 +1- 1 +-1 1 +.names 1815 1783 2063 +11 1 +.names 1783 2063 2064 +1- 1 +-1 1 +.names 1816 2037 2065 +11 1 +.names 2068 2069 56557 +1- 1 +-1 1 +.names 1815 1783 2067 +11 1 +.names 1783 2067 2068 +1- 1 +-1 1 +.names 1816 2042 2069 +11 1 +.names 2074 2077 56766 +1- 1 +-1 1 +.names 9285 9273 2071 +11 1 +.names 2071 2072 +1 1 +.names 1818 2072 2073 +11 1 +.names 1783 2073 2074 +1- 1 +-1 1 +.names 9242 936 2075 +11 1 +.names 2075 2076 +1 1 +.names 1821 2076 2077 +11 1 +.names 2082 2085 56767 +1- 1 +-1 1 +.names 9268 9256 2079 +11 1 +.names 2079 2080 +1 1 +.names 1824 2080 2081 +11 1 +.names 1783 2081 2082 +1- 1 +-1 1 +.names 9220 935 2083 +11 1 +.names 2083 2084 +1 1 +.names 1827 2084 2085 +11 1 +.names 2091 2094 2086 +1- 1 +-1 1 +.names 2086 2087 +1 1 +.names 9206 9199 2088 +11 1 +.names 2088 2089 +1 1 +.names 1829 2089 2090 +11 1 +.names 1783 2090 2091 +1- 1 +-1 1 +.names 9198 8562 2092 +11 1 +.names 2092 2093 +1 1 +.names 1831 2093 2094 +11 1 +.names 2097 2098 56413 +1- 1 +-1 1 +.names 1843 1833 2096 +11 1 +.names 1783 2096 2097 +1- 1 +-1 1 +.names 1846 1783 2098 +11 1 +.names 2101 2102 56412 +1- 1 +-1 1 +.names 1843 1835 2100 +11 1 +.names 1783 2100 2101 +1- 1 +-1 1 +.names 1846 1841 2102 +11 1 +.names 2105 2106 56411 +1- 1 +-1 1 +.names 1843 1837 2104 +11 1 +.names 1783 2104 2105 +1- 1 +-1 1 +.names 1846 1783 2106 +11 1 +.names 2109 2110 56410 +1- 1 +-1 1 +.names 1843 1839 2108 +11 1 +.names 1783 2108 2109 +1- 1 +-1 1 +.names 1846 1783 2110 +11 1 +.names 2114 2117 56768 +1- 1 +-1 1 +.names 7168 56630 +0 1 +.names 1849 56630 2113 +11 1 +.names 1783 2113 2114 +1- 1 +-1 1 +.names 9025 937 2115 +11 1 +.names 2115 2116 +1 1 +.names 1852 2116 2117 +11 1 +.names 2121 2122 2118 +1- 1 +-1 1 +.names 2118 2119 +1 1 +.names 1855 1775 2120 +11 1 +.names 1783 2120 2121 +1- 1 +-1 1 +.names 1858 715 2122 +11 1 +.names 2126 2127 2123 +1- 1 +-1 1 +.names 2123 2124 +1 1 +.names 1862 716 2125 +11 1 +.names 1783 2125 2126 +1- 1 +-1 1 +.names 1865 1783 2127 +11 1 +.names 2131 2134 2128 +1- 1 +-1 1 +.names 2128 2129 +1 1 +.names 1862 1783 2130 +11 1 +.names 1783 2130 2131 +1- 1 +-1 1 +.names 717 2132 +0 1 +.names 2132 2133 +1 1 +.names 1865 2133 2134 +11 1 +.names 2138 2139 2135 +1- 1 +-1 1 +.names 2135 2136 +1 1 +.names 1862 1860 2137 +11 1 +.names 1783 2137 2138 +1- 1 +-1 1 +.names 1865 717 2139 +11 1 +.names 2145 2146 2140 +1- 1 +-1 1 +.names 2140 2141 +1 1 +.names 716 2142 +0 1 +.names 2142 2143 +1 1 +.names 1862 2143 2144 +11 1 +.names 1783 2144 2145 +1- 1 +-1 1 +.names 1865 1783 2146 +11 1 +.names 2150 2151 2147 +1- 1 +-1 1 +.names 2147 2148 +1 1 +.names 1869 716 2149 +11 1 +.names 1783 2149 2150 +1- 1 +-1 1 +.names 1872 1783 2151 +11 1 +.names 2155 2157 2152 +1- 1 +-1 1 +.names 2152 2153 +1 1 +.names 1869 1783 2154 +11 1 +.names 1783 2154 2155 +1- 1 +-1 1 +.names 2132 2156 +1 1 +.names 1872 2156 2157 +11 1 +.names 2161 2162 2158 +1- 1 +-1 1 +.names 2158 2159 +1 1 +.names 1869 716 2160 +11 1 +.names 1783 2160 2161 +1- 1 +-1 1 +.names 1872 1867 2162 +11 1 +.names 2167 2168 2163 +1- 1 +-1 1 +.names 2163 2164 +1 1 +.names 2142 2165 +1 1 +.names 1869 2165 2166 +11 1 +.names 1783 2166 2167 +1- 1 +-1 1 +.names 1872 1783 2168 +11 1 +.names 2187 2188 56414 +1- 1 +-1 1 +.names 1879 1874 2170 +11 1 +.names 1783 2170 2171 +1- 1 +-1 1 +.names 1882 1854 2172 +11 1 +.names 2171 2172 2173 +1- 1 +-1 1 +.names 923 8580 2174 +11 1 +.names 2174 2175 +1 1 +.names 1885 2175 2176 +11 1 +.names 2173 2176 2177 +1- 1 +-1 1 +.names 1888 718 2178 +11 1 +.names 2177 2178 2179 +1- 1 +-1 1 +.names 1891 2124 2180 +11 1 +.names 2179 2180 2181 +1- 1 +-1 1 +.names 1894 2148 2182 +11 1 +.names 2181 2182 2183 +1- 1 +-1 1 +.names 1897 718 2184 +11 1 +.names 2183 2184 2185 +1- 1 +-1 1 +.names 1900 1783 2186 +11 1 +.names 2185 2186 2187 +1- 1 +-1 1 +.names 1903 1783 2188 +11 1 +.names 2205 2206 56415 +1- 1 +-1 1 +.names 1879 1875 2190 +11 1 +.names 1783 2190 2191 +1- 1 +-1 1 +.names 1882 2119 2192 +11 1 +.names 2191 2192 2193 +1- 1 +-1 1 +.names 1885 1775 2194 +11 1 +.names 2193 2194 2195 +1- 1 +-1 1 +.names 1888 1877 2196 +11 1 +.names 2195 2196 2197 +1- 1 +-1 1 +.names 1891 2129 2198 +11 1 +.names 2197 2198 2199 +1- 1 +-1 1 +.names 1894 2153 2200 +11 1 +.names 2199 2200 2201 +1- 1 +-1 1 +.names 1897 1783 2202 +11 1 +.names 2201 2202 2203 +1- 1 +-1 1 +.names 1900 1783 2204 +11 1 +.names 2203 2204 2205 +1- 1 +-1 1 +.names 1903 1783 2206 +11 1 +.names 2225 2226 56416 +1- 1 +-1 1 +.names 1879 1874 2208 +11 1 +.names 1783 2208 2209 +1- 1 +-1 1 +.names 1882 1857 2210 +11 1 +.names 2209 2210 2211 +1- 1 +-1 1 +.names 2175 2212 +0 1 +.names 2212 2213 +1 1 +.names 1885 2213 2214 +11 1 +.names 2211 2214 2215 +1- 1 +-1 1 +.names 1888 1783 2216 +11 1 +.names 2215 2216 2217 +1- 1 +-1 1 +.names 1891 2136 2218 +11 1 +.names 2217 2218 2219 +1- 1 +-1 1 +.names 1894 2159 2220 +11 1 +.names 2219 2220 2221 +1- 1 +-1 1 +.names 1897 718 2222 +11 1 +.names 2221 2222 2223 +1- 1 +-1 1 +.names 1900 1783 2224 +11 1 +.names 2223 2224 2225 +1- 1 +-1 1 +.names 1903 1783 2226 +11 1 +.names 2250 2251 2227 +1- 1 +-1 1 +.names 2227 2228 +1 1 +.names 1874 2229 +0 1 +.names 2229 2230 +1 1 +.names 1879 2230 2231 +11 1 +.names 1783 2231 2232 +1- 1 +-1 1 +.names 1882 1783 2233 +11 1 +.names 2232 2233 2234 +1- 1 +-1 1 +.names 1885 1783 2235 +11 1 +.names 2234 2235 2236 +1- 1 +-1 1 +.names 718 2237 +0 1 +.names 2237 2238 +1 1 +.names 1888 2238 2239 +11 1 +.names 2236 2239 2240 +1- 1 +-1 1 +.names 1891 1783 2241 +11 1 +.names 2240 2241 2242 +1- 1 +-1 1 +.names 1894 1783 2243 +11 1 +.names 2242 2243 2244 +1- 1 +-1 1 +.names 2237 2245 +1 1 +.names 1897 2245 2246 +11 1 +.names 2244 2246 2247 +1- 1 +-1 1 +.names 2237 2248 +1 1 +.names 1900 2248 2249 +11 1 +.names 2247 2249 2250 +1- 1 +-1 1 +.names 1903 1775 2251 +11 1 +.names 2268 2269 56409 +1- 1 +-1 1 +.names 1925 4 2253 +11 1 +.names 1783 2253 2254 +1- 1 +-1 1 +.names 1926 1783 2255 +11 1 +.names 2254 2255 2256 +1- 1 +-1 1 +.names 1927 1910 2257 +11 1 +.names 2256 2257 2258 +1- 1 +-1 1 +.names 1928 1905 2259 +11 1 +.names 2258 2259 2260 +1- 1 +-1 1 +.names 1929 1911 2261 +11 1 +.names 2260 2261 2262 +1- 1 +-1 1 +.names 1930 1910 2263 +11 1 +.names 2262 2263 2264 +1- 1 +-1 1 +.names 1931 4 2265 +11 1 +.names 2264 2265 2266 +1- 1 +-1 1 +.names 1932 4 2267 +11 1 +.names 2266 2267 2268 +1- 1 +-1 1 +.names 1933 4 2269 +11 1 +.names 1925 3 2270 +11 1 +.names 1783 2270 2271 +1- 1 +-1 1 +.names 1926 1783 2272 +11 1 +.names 2271 2272 2273 +1- 1 +-1 1 +.names 1927 1913 2274 +11 1 +.names 2273 2274 2275 +1- 1 +-1 1 +.names 1928 1906 2276 +11 1 +.names 2275 2276 2277 +1- 1 +-1 1 +.names 1929 1914 2278 +11 1 +.names 2277 2278 2279 +1- 1 +-1 1 +.names 1930 1913 2280 +11 1 +.names 2279 2280 2281 +1- 1 +-1 1 +.names 1931 3 2282 +11 1 +.names 2281 2282 2283 +1- 1 +-1 1 +.names 1932 3 2284 +11 1 +.names 2283 2284 2285 +1- 1 +-1 1 +.names 1933 3 2286 +11 1 +.names 1925 2 2287 +11 1 +.names 1783 2287 2288 +1- 1 +-1 1 +.names 1926 1783 2289 +11 1 +.names 2288 2289 2290 +1- 1 +-1 1 +.names 1927 1916 2291 +11 1 +.names 2290 2291 2292 +1- 1 +-1 1 +.names 1928 1907 2293 +11 1 +.names 2292 2293 2294 +1- 1 +-1 1 +.names 1929 1917 2295 +11 1 +.names 2294 2295 2296 +1- 1 +-1 1 +.names 1930 1916 2297 +11 1 +.names 2296 2297 2298 +1- 1 +-1 1 +.names 1931 2 2299 +11 1 +.names 2298 2299 2300 +1- 1 +-1 1 +.names 1932 2 2301 +11 1 +.names 2300 2301 2302 +1- 1 +-1 1 +.names 1933 2 2303 +11 1 +.names 1925 1 2304 +11 1 +.names 1783 2304 2305 +1- 1 +-1 1 +.names 1926 1783 2306 +11 1 +.names 2305 2306 2307 +1- 1 +-1 1 +.names 1927 1919 2308 +11 1 +.names 2307 2308 2309 +1- 1 +-1 1 +.names 1928 1908 2310 +11 1 +.names 2309 2310 2311 +1- 1 +-1 1 +.names 1929 1920 2312 +11 1 +.names 2311 2312 2313 +1- 1 +-1 1 +.names 1930 1919 2314 +11 1 +.names 2313 2314 2315 +1- 1 +-1 1 +.names 1931 1 2316 +11 1 +.names 2315 2316 2317 +1- 1 +-1 1 +.names 1932 1 2318 +11 1 +.names 2317 2318 2319 +1- 1 +-1 1 +.names 1933 1 2320 +11 1 +.names 1925 0 2321 +11 1 +.names 1783 2321 2322 +1- 1 +-1 1 +.names 1926 1775 2323 +11 1 +.names 2322 2323 2324 +1- 1 +-1 1 +.names 1927 1922 2325 +11 1 +.names 2324 2325 2326 +1- 1 +-1 1 +.names 1928 1909 2327 +11 1 +.names 2326 2327 2328 +1- 1 +-1 1 +.names 1929 1923 2329 +11 1 +.names 2328 2329 2330 +1- 1 +-1 1 +.names 1930 1922 2331 +11 1 +.names 2330 2331 2332 +1- 1 +-1 1 +.names 1931 0 2333 +11 1 +.names 2332 2333 2334 +1- 1 +-1 1 +.names 1932 0 2335 +11 1 +.names 2334 2335 2336 +1- 1 +-1 1 +.names 1933 0 2337 +11 1 +.names 2344 2345 56769 +1- 1 +-1 1 +.names 1935 1783 2339 +11 1 +.names 1783 2339 2340 +1- 1 +-1 1 +.names 1940 2141 2341 +11 1 +.names 2340 2341 2342 +1- 1 +-1 1 +.names 1941 2164 2343 +11 1 +.names 2342 2343 2344 +1- 1 +-1 1 +.names 1942 718 2345 +11 1 +.names 2350 2351 56770 +1- 1 +-1 1 +.names 4171 9432 2347 +11 1 +.names 2347 2348 +1 1 +.names 1944 2348 2349 +11 1 +.names 1783 2349 2350 +1- 1 +-1 1 +.names 1946 1943 2351 +11 1 +.names 2356 2357 56771 +1- 1 +-1 1 +.names 4169 9430 2353 +11 1 +.names 2353 2354 +1 1 +.names 1953 2354 2355 +11 1 +.names 1783 2355 2356 +1- 1 +-1 1 +.names 1955 716 2357 +11 1 +.names 2362 2363 56772 +1- 1 +-1 1 +.names 4167 9431 2359 +11 1 +.names 2359 2360 +1 1 +.names 1962 2360 2361 +11 1 +.names 1783 2361 2362 +1- 1 +-1 1 +.names 1964 720 2363 +11 1 +.names 2369 2372 2364 +1- 1 +-1 1 +.names 2364 2365 +1 1 +.names 1971 1775 2366 +11 1 +.names 1783 2366 2367 +1- 1 +-1 1 +.names 1972 1775 2368 +11 1 +.names 2367 2368 2369 +1- 1 +-1 1 +.names 8579 2370 +0 1 +.names 2370 2371 +1 1 +.names 1973 2371 2372 +11 1 +.names 2376 2379 2373 +1- 1 +-1 1 +.names 2373 2374 +1 1 +.names 1975 1783 2375 +11 1 +.names 1783 2375 2376 +1- 1 +-1 1 +.names 2385 2377 +0 1 +.names 2377 2378 +1 1 +.names 1978 2378 2379 +11 1 +.names 2383 2386 2380 +1- 1 +-1 1 +.names 2380 2381 +1 1 +.names 1975 1783 2382 +11 1 +.names 1783 2382 2383 +1- 1 +-1 1 +.names 5357 5351 2384 +1- 1 +-1 1 +.names 2384 2385 +1 1 +.names 1978 2385 2386 +11 1 +.names 2391 2394 56773 +1- 1 +-1 1 +.names 2396 2397 2388 +1- 1 +-1 1 +.names 2388 2389 +1 1 +.names 1981 2389 2390 +11 1 +.names 1783 2390 2391 +1- 1 +-1 1 +.names 2399 2400 2392 +1- 1 +-1 1 +.names 2392 2393 +1 1 +.names 1983 2393 2394 +11 1 +.names 1985 1775 2395 +11 1 +.names 1783 2395 2396 +1- 1 +-1 1 +.names 1988 719 2397 +11 1 +.names 1991 1783 2398 +11 1 +.names 1783 2398 2399 +1- 1 +-1 1 +.names 1994 1989 2400 +11 1 +.names 1783 4 2401 +01 1 +10 1 +.names 2411 2415 2402 +1- 1 +-1 1 +.names 2402 2403 +1 1 +.names 1783 3 2404 +01 1 +10 1 +.names 2423 2426 2405 +1- 1 +-1 1 +.names 2405 2406 +1 1 +.names 2406 1783 2407 +1- 1 +-1 1 +.names 2407 2408 +0 1 +.names 3 2409 +0 1 +.names 2408 2409 2410 +1- 1 +-1 1 +.names 2410 2411 +0 1 +.names 2406 2412 +0 1 +.names 1783 2413 +0 1 +.names 2412 2413 2414 +1- 1 +-1 1 +.names 2414 2415 +0 1 +.names 1783 2 2416 +01 1 +10 1 +.names 2434 2437 2417 +1- 1 +-1 1 +.names 2417 2418 +1 1 +.names 2418 1783 2419 +1- 1 +-1 1 +.names 2419 2420 +0 1 +.names 2 2421 +0 1 +.names 2420 2421 2422 +1- 1 +-1 1 +.names 2422 2423 +0 1 +.names 2418 2424 +0 1 +.names 2424 2413 2425 +1- 1 +-1 1 +.names 2425 2426 +0 1 +.names 1783 1 2427 +01 1 +10 1 +.names 2443 2446 2428 +1- 1 +-1 1 +.names 2428 2429 +1 1 +.names 2429 1783 2430 +1- 1 +-1 1 +.names 2430 2431 +0 1 +.names 1 2432 +0 1 +.names 2431 2432 2433 +1- 1 +-1 1 +.names 2433 2434 +0 1 +.names 2429 2435 +0 1 +.names 2435 2413 2436 +1- 1 +-1 1 +.names 2436 2437 +0 1 +.names 2365 0 2438 +01 1 +10 1 +.names 1783 2365 2439 +1- 1 +-1 1 +.names 2439 2440 +0 1 +.names 0 2441 +0 1 +.names 2440 2441 2442 +1- 1 +-1 1 +.names 2442 2443 +0 1 +.names 2365 2444 +0 1 +.names 2413 2444 2445 +1- 1 +-1 1 +.names 2445 2446 +0 1 +.names 721 2447 +0 1 +.names 56775 56776 2448 +1- 1 +-1 1 +.names 2448 2449 +1 1 +.names 2478 56782 56775 +1- 1 +-1 1 +.names 2470 2476 56776 +1- 1 +-1 1 +.names 2449 56777 2452 +1- 1 +-1 1 +.names 2452 2453 +1 1 +.names 2462 2468 56777 +1- 1 +-1 1 +.names 2453 56778 2455 +1- 1 +-1 1 +.names 2455 2456 +1 1 +.names 56780 56781 56778 +1- 1 +-1 1 +.names 2456 56779 +0 1 +.names 10138 56780 +0 1 +.names 10136 56781 +0 1 +.names 2464 2466 2461 +1- 1 +-1 1 +.names 2461 2462 +1 1 +.names 10062 2463 +0 1 +.names 2463 2464 +1 1 +.names 10060 2465 +0 1 +.names 2465 2466 +1 1 +.names 10052 2467 +0 1 +.names 2467 2468 +1 1 +.names 2472 2474 2469 +1- 1 +-1 1 +.names 2469 2470 +1 1 +.names 10032 2471 +0 1 +.names 2471 2472 +1 1 +.names 10064 2473 +0 1 +.names 2473 2474 +1 1 +.names 10054 2475 +0 1 +.names 2475 2476 +1 1 +.names 2480 2482 2477 +1- 1 +-1 1 +.names 2477 2478 +1 1 +.names 10066 2479 +0 1 +.names 2479 2480 +1 1 +.names 10058 2481 +0 1 +.names 2481 2482 +1 1 +.names 10056 56782 +0 1 +.names 2487 722 2484 +11 1 +.names 2484 2485 +1 1 +.names 9819 2486 +0 1 +.names 2486 2487 +1 1 +.names 2491 722 2488 +11 1 +.names 2488 2489 +1 1 +.names 9869 2490 +0 1 +.names 2490 2491 +1 1 +.names 2495 723 2492 +11 1 +.names 2492 2493 +1 1 +.names 9857 2494 +0 1 +.names 2494 2495 +1 1 +.names 2493 2489 2496 +1- 1 +-1 1 +.names 2496 2497 +1 1 +.names 2497 2485 56784 +1- 1 +-1 1 +.names 56786 56787 2499 +1- 1 +-1 1 +.names 2499 2500 +1 1 +.names 2495 723 56786 +11 1 +.names 2522 2505 56787 +1- 1 +-1 1 +.names 2500 56788 +0 1 +.names 2487 723 2504 +11 1 +.names 2504 2505 +1 1 +.names 2491 723 2506 +11 1 +.names 2506 2507 +1 1 +.names 2495 722 2508 +11 1 +.names 2508 2509 +1 1 +.names 2513 2509 2510 +1- 1 +-1 1 +.names 2510 2511 +1 1 +.names 9897 2512 +0 1 +.names 2512 2513 +1 1 +.names 2511 56789 2514 +1- 1 +-1 1 +.names 2514 2515 +1 1 +.names 9885 56789 +0 1 +.names 2515 2520 2517 +1- 1 +-1 1 +.names 2517 2518 +1 1 +.names 9799 2519 +0 1 +.names 2519 2520 +1 1 +.names 2518 2507 2521 +1- 1 +-1 1 +.names 2521 2522 +1 1 +.names 56791 56789 2523 +1- 1 +-1 1 +.names 2523 2524 +1 1 +.names 2536 723 56791 +11 1 +.names 2524 56792 2526 +1- 1 +-1 1 +.names 2526 2527 +1 1 +.names 2534 722 56792 +11 1 +.names 2527 56793 2529 +1- 1 +-1 1 +.names 2529 2530 +1 1 +.names 2495 723 56793 +11 1 +.names 2530 56794 +0 1 +.names 2491 2487 2533 +1- 1 +-1 1 +.names 2533 2534 +1 1 +.names 2491 2487 2535 +1- 1 +-1 1 +.names 2535 2536 +1 1 +.names 56796 56797 2537 +1- 1 +-1 1 +.names 2537 2538 +1 1 +.names 10238 56796 +0 1 +.names 10240 56797 +0 1 +.names 2538 56798 2541 +1- 1 +-1 1 +.names 2541 2542 +1 1 +.names 10242 56798 +0 1 +.names 2542 56799 2544 +1- 1 +-1 1 +.names 2544 2545 +1 1 +.names 10254 56799 +0 1 +.names 2545 56800 +0 1 +.names 56802 56803 2548 +1- 1 +-1 1 +.names 2548 2549 +1 1 +.names 2577 2579 56802 +1- 1 +-1 1 +.names 56807 56781 56803 +1- 1 +-1 1 +.names 2549 56804 2552 +1- 1 +-1 1 +.names 2552 2553 +1 1 +.names 2574 2570 56804 +1- 1 +-1 1 +.names 2553 56805 2555 +1- 1 +-1 1 +.names 2555 2556 +1 1 +.names 2566 2562 56805 +1- 1 +-1 1 +.names 2556 56806 +0 1 +.names 722 723 2559 +1- 1 +-1 1 +.names 2559 2560 +1 1 +.names 2564 2560 2561 +11 1 +.names 2561 2562 +1 1 +.names 9793 2563 +0 1 +.names 2563 2564 +1 1 +.names 9843 2565 +0 1 +.names 2565 2566 +1 1 +.names 722 723 2567 +1- 1 +-1 1 +.names 2567 2568 +1 1 +.names 2572 2568 2569 +11 1 +.names 2569 2570 +1 1 +.names 10256 2571 +0 1 +.names 2571 2572 +1 1 +.names 10258 2573 +0 1 +.names 2573 2574 +1 1 +.names 10195 56807 +0 1 +.names 9827 2576 +0 1 +.names 2576 2577 +1 1 +.names 9811 2578 +0 1 +.names 2578 2579 +1 1 +.names 724 2580 +0 1 +.names 2580 2581 +1 1 +.names 725 2581 2582 +11 1 +.names 2582 2583 +1 1 +.names 726 2584 +0 1 +.names 616 2585 +0 1 +.names 2585 2586 +1 1 +.names 725 617 2587 +11 1 +.names 2587 2588 +1 1 +.names 2588 2586 2589 +11 1 +.names 2589 2590 +1 1 +.names 725 2591 +0 1 +.names 2591 2592 +1 1 +.names 727 2592 2593 +11 1 +.names 2593 2594 +1 1 +.names 2597 2599 56810 +1- 1 +-1 1 +.names 9893 2596 +0 1 +.names 2596 2597 +1 1 +.names 9877 2598 +0 1 +.names 2598 2599 +1 1 +.names 617 2600 +0 1 +.names 2600 2601 +1 1 +.names 2601 616 2602 +11 1 +.names 2602 2603 +1 1 +.names 728 2603 2604 +1- 1 +-1 1 +.names 2604 2605 +1 1 +.names 56813 56814 +0 1 +.names 2623 2611 56813 +1- 1 +-1 1 +.names 722 723 2608 +1- 1 +-1 1 +.names 2608 2609 +1 1 +.names 2597 2609 2610 +11 1 +.names 2610 2611 +1 1 +.names 722 723 2612 +1- 1 +-1 1 +.names 2612 2613 +1 1 +.names 2617 2613 2614 +11 1 +.names 2614 2615 +1 1 +.names 9875 2616 +0 1 +.names 2616 2617 +1 1 +.names 2621 2599 2618 +1- 1 +-1 1 +.names 2618 2619 +1 1 +.names 10262 2620 +0 1 +.names 2620 2621 +1 1 +.names 2619 2615 2622 +1- 1 +-1 1 +.names 2622 2623 +1 1 +.names 56816 2624 +0 1 +.names 2624 2625 +1 1 +.names 2653 56829 56816 +1- 1 +-1 1 +.names 56817 2627 +0 1 +.names 2627 2628 +1 1 +.names 56819 56820 56817 +1- 1 +-1 1 +.names 2628 2625 56818 +11 1 +.names 9837 56819 +0 1 +.names 9823 56820 +0 1 +.names 56821 56822 2633 +1- 1 +-1 1 +.names 2633 2634 +1 1 +.names 9871 56821 +0 1 +.names 10230 56822 +0 1 +.names 2634 56823 2637 +1- 1 +-1 1 +.names 2637 2638 +1 1 +.names 10228 56823 +0 1 +.names 2638 56824 2640 +1- 1 +-1 1 +.names 2640 2641 +1 1 +.names 10171 56824 +0 1 +.names 2641 56825 2643 +1- 1 +-1 1 +.names 2643 2644 +1 1 +.names 10226 56825 +0 1 +.names 2644 56826 2646 +1- 1 +-1 1 +.names 2646 2647 +1 1 +.names 10224 56826 +0 1 +.names 2647 56827 2649 +1- 1 +-1 1 +.names 2649 2650 +1 1 +.names 10084 56827 +0 1 +.names 2650 56828 2652 +1- 1 +-1 1 +.names 2652 2653 +1 1 +.names 10142 56828 +0 1 +.names 10140 56829 +0 1 +.names 56632 56631 +0 1 +.names 2664 2661 56632 +1- 1 +-1 1 +.names 729 2658 +0 1 +.names 2658 2659 +1 1 +.names 56830 2659 2660 +11 1 +.names 2660 2661 +1 1 +.names 849 733 56830 +11 1 +.names 730 731 2663 +1- 1 +-1 1 +.names 2663 2664 +1 1 +.names 732 733 56832 +11 1 +.names 56835 56836 2666 +1- 1 +-1 1 +.names 2666 2667 +1 1 +.names 2674 2676 56835 +1- 1 +-1 1 +.names 56838 56839 56836 +1- 1 +-1 1 +.names 2667 56837 +0 1 +.names 4221 4417 56838 +11 1 +.names 4221 4415 56839 +11 1 +.names 4221 4403 2673 +11 1 +.names 2673 2674 +1 1 +.names 4221 4401 2675 +11 1 +.names 2675 2676 +1 1 +.names 734 2677 +0 1 +.names 2677 2678 +1 1 +.names 735 2679 +0 1 +.names 2679 2680 +1 1 +.names 2680 2678 2681 +11 1 +.names 2681 2682 +1 1 +.names 2584 2683 +1 1 +.names 736 2683 2684 +11 1 +.names 2684 2685 +1 1 +.names 2689 2685 2686 +11 1 +.names 2686 2687 +1 1 +.names 750 2866 2688 +1- 1 +-1 1 +.names 2688 2689 +1 1 +.names 2687 2682 2690 +11 1 +.names 2690 2691 +1 1 +.names 2677 2692 +1 1 +.names 2679 2693 +1 1 +.names 2693 2692 2694 +11 1 +.names 2694 2695 +1 1 +.names 2584 2696 +1 1 +.names 736 2696 2697 +11 1 +.names 2697 2698 +1 1 +.names 2702 2698 2699 +11 1 +.names 2699 2700 +1 1 +.names 751 2868 2701 +1- 1 +-1 1 +.names 2701 2702 +1 1 +.names 2700 2695 2703 +11 1 +.names 2703 2704 +1 1 +.names 2677 2705 +1 1 +.names 2679 2706 +1 1 +.names 2706 2705 2707 +11 1 +.names 2707 2708 +1 1 +.names 2584 2709 +1 1 +.names 736 2709 2710 +11 1 +.names 2710 2711 +1 1 +.names 737 2711 2712 +11 1 +.names 2712 2713 +1 1 +.names 2713 2708 2714 +11 1 +.names 2714 2715 +1 1 +.names 2677 2716 +1 1 +.names 2679 2717 +1 1 +.names 2717 2716 2718 +11 1 +.names 2718 2719 +1 1 +.names 2584 2720 +1 1 +.names 736 2720 2721 +11 1 +.names 2721 2722 +1 1 +.names 2726 2722 2723 +11 1 +.names 2723 2724 +1 1 +.names 752 2870 2725 +1- 1 +-1 1 +.names 2725 2726 +1 1 +.names 2724 2719 2727 +11 1 +.names 2727 2728 +1 1 +.names 2677 2729 +1 1 +.names 2679 2730 +1 1 +.names 2730 2729 2731 +11 1 +.names 2731 2732 +1 1 +.names 2584 2733 +1 1 +.names 736 2733 2734 +11 1 +.names 2734 2735 +1 1 +.names 2739 2735 2736 +11 1 +.names 2736 2737 +1 1 +.names 753 2872 2738 +1- 1 +-1 1 +.names 2738 2739 +1 1 +.names 2737 2732 56840 +11 1 +.names 2677 2741 +1 1 +.names 2679 2742 +1 1 +.names 2742 2741 2743 +11 1 +.names 2743 2744 +1 1 +.names 2584 2745 +1 1 +.names 736 2745 2746 +11 1 +.names 2746 2747 +1 1 +.names 738 2747 2748 +11 1 +.names 2748 2749 +1 1 +.names 2749 2744 56841 +11 1 +.names 2677 2751 +1 1 +.names 2679 2752 +1 1 +.names 2752 2751 2753 +11 1 +.names 2753 2754 +1 1 +.names 2584 2755 +1 1 +.names 736 2755 2756 +11 1 +.names 2756 2757 +1 1 +.names 739 2757 2758 +11 1 +.names 2758 2759 +1 1 +.names 2759 2754 56842 +11 1 +.names 2677 2761 +1 1 +.names 2679 2762 +1 1 +.names 2762 2761 2763 +11 1 +.names 2763 2764 +1 1 +.names 2584 2765 +1 1 +.names 736 2765 2766 +11 1 +.names 2766 2767 +1 1 +.names 740 2767 2768 +11 1 +.names 2768 2769 +1 1 +.names 2769 2764 56843 +11 1 +.names 2677 2771 +1 1 +.names 2679 2772 +1 1 +.names 2772 2771 2773 +11 1 +.names 2773 2774 +1 1 +.names 2584 2775 +1 1 +.names 736 2775 2776 +11 1 +.names 2776 2777 +1 1 +.names 741 2777 2778 +11 1 +.names 2778 2779 +1 1 +.names 2779 2774 2780 +11 1 +.names 2780 2781 +1 1 +.names 2677 2782 +1 1 +.names 2679 2783 +1 1 +.names 2783 2782 2784 +11 1 +.names 2784 2785 +1 1 +.names 2584 2786 +1 1 +.names 736 2786 2787 +11 1 +.names 2787 2788 +1 1 +.names 742 2788 2789 +11 1 +.names 2789 2790 +1 1 +.names 2790 2785 2791 +11 1 +.names 2791 2792 +1 1 +.names 2677 2793 +1 1 +.names 2679 2794 +1 1 +.names 2794 2793 2795 +11 1 +.names 2795 2796 +1 1 +.names 2584 2797 +1 1 +.names 736 2797 2798 +11 1 +.names 2798 2799 +1 1 +.names 743 2799 2800 +11 1 +.names 2800 2801 +1 1 +.names 2801 2796 56844 +11 1 +.names 2677 2803 +1 1 +.names 2679 2804 +1 1 +.names 2804 2803 2805 +11 1 +.names 2805 2806 +1 1 +.names 2584 2807 +1 1 +.names 736 2807 2808 +11 1 +.names 2808 2809 +1 1 +.names 744 2809 2810 +11 1 +.names 2810 2811 +1 1 +.names 2811 2806 2812 +11 1 +.names 2812 2813 +1 1 +.names 2677 2814 +1 1 +.names 2679 2815 +1 1 +.names 2815 2814 2816 +11 1 +.names 2816 2817 +1 1 +.names 2584 2818 +1 1 +.names 736 2818 2819 +11 1 +.names 2819 2820 +1 1 +.names 745 2820 2821 +11 1 +.names 2821 2822 +1 1 +.names 2822 2817 56845 +11 1 +.names 2677 2824 +1 1 +.names 2679 2825 +1 1 +.names 2825 2824 2826 +11 1 +.names 2826 2827 +1 1 +.names 2584 2828 +1 1 +.names 736 2828 2829 +11 1 +.names 2829 2830 +1 1 +.names 746 2830 2831 +11 1 +.names 2831 2832 +1 1 +.names 2832 2827 56846 +11 1 +.names 2677 2834 +1 1 +.names 2679 2835 +1 1 +.names 2835 2834 2836 +11 1 +.names 2836 2837 +1 1 +.names 2584 2838 +1 1 +.names 736 2838 2839 +11 1 +.names 2839 2840 +1 1 +.names 747 2840 2841 +11 1 +.names 2841 2842 +1 1 +.names 2842 2837 2843 +11 1 +.names 2843 2844 +1 1 +.names 2677 2845 +1 1 +.names 2679 2846 +1 1 +.names 2846 2845 2847 +11 1 +.names 2847 2848 +1 1 +.names 2584 2849 +1 1 +.names 736 2849 2850 +11 1 +.names 2850 2851 +1 1 +.names 748 2851 2852 +11 1 +.names 2852 2853 +1 1 +.names 2853 2848 56847 +11 1 +.names 2677 2855 +1 1 +.names 2679 2856 +1 1 +.names 2856 2855 2857 +11 1 +.names 2857 2858 +1 1 +.names 2584 2859 +1 1 +.names 736 2859 2860 +11 1 +.names 2860 2861 +1 1 +.names 749 2861 2862 +11 1 +.names 2862 2863 +1 1 +.names 2863 2858 56848 +11 1 +.names 2914 2911 2865 +11 1 +.names 2865 2866 +1 1 +.names 2910 472 2867 +11 1 +.names 2867 2868 +1 1 +.names 2906 2903 2869 +11 1 +.names 2869 2870 +1 1 +.names 2890 472 2871 +11 1 +.names 2871 2872 +1 1 +.names 754 2876 2873 +1- 1 +-1 1 +.names 2873 2874 +1 1 +.names 2946 2943 2875 +11 1 +.names 2875 2876 +1 1 +.names 755 2880 2877 +1- 1 +-1 1 +.names 2877 2878 +1 1 +.names 2942 201 2879 +11 1 +.names 2879 2880 +1 1 +.names 756 2884 2881 +1- 1 +-1 1 +.names 2881 2882 +1 1 +.names 2938 2935 2883 +11 1 +.names 2883 2884 +1 1 +.names 757 2888 2885 +1- 1 +-1 1 +.names 2885 2886 +1 1 +.names 2950 201 2887 +11 1 +.names 2887 2888 +1 1 +.names 474 473 2889 +11 1 +.names 2889 2890 +1 1 +.names 472 2891 +0 1 +.names 2891 2892 +1 1 +.names 474 473 2893 +11 1 +.names 2893 2894 +1 1 +.names 2894 2892 2895 +11 1 +.names 2895 2896 +1 1 +.names 473 2897 +0 1 +.names 2897 2898 +1 1 +.names 474 2898 2899 +11 1 +.names 2899 2900 +1 1 +.names 2900 472 2901 +11 1 +.names 2901 2902 +1 1 +.names 2891 2903 +1 1 +.names 2897 2904 +1 1 +.names 474 2904 2905 +11 1 +.names 2905 2906 +1 1 +.names 474 2907 +0 1 +.names 2907 2908 +1 1 +.names 2908 473 2909 +11 1 +.names 2909 2910 +1 1 +.names 2891 2911 +1 1 +.names 2907 2912 +1 1 +.names 2912 473 2913 +11 1 +.names 2913 2914 +1 1 +.names 2897 2915 +1 1 +.names 2907 2916 +1 1 +.names 2916 2915 2917 +11 1 +.names 2917 2918 +1 1 +.names 2918 472 2919 +11 1 +.names 2919 2920 +1 1 +.names 203 202 2921 +11 1 +.names 2921 2922 +1 1 +.names 2922 201 56850 +11 1 +.names 201 2924 +0 1 +.names 2924 2925 +1 1 +.names 203 202 2926 +11 1 +.names 2926 2927 +1 1 +.names 2927 2925 56851 +11 1 +.names 202 2929 +0 1 +.names 2929 2930 +1 1 +.names 203 2930 2931 +11 1 +.names 2931 2932 +1 1 +.names 2932 201 2933 +11 1 +.names 2933 2934 +1 1 +.names 2924 2935 +1 1 +.names 2929 2936 +1 1 +.names 203 2936 2937 +11 1 +.names 2937 2938 +1 1 +.names 203 2939 +0 1 +.names 2939 2940 +1 1 +.names 2940 202 2941 +11 1 +.names 2941 2942 +1 1 +.names 2924 2943 +1 1 +.names 2939 2944 +1 1 +.names 2944 202 2945 +11 1 +.names 2945 2946 +1 1 +.names 2929 2947 +1 1 +.names 2939 2948 +1 1 +.names 2948 2947 2949 +11 1 +.names 2949 2950 +1 1 +.names 56853 56854 2951 +1- 1 +-1 1 +.names 2951 2952 +1 1 +.names 4221 4223 56853 +11 1 +.names 4221 4225 56854 +11 1 +.names 2952 56855 2955 +1- 1 +-1 1 +.names 2955 2956 +1 1 +.names 4221 4227 56855 +11 1 +.names 2956 56856 2958 +1- 1 +-1 1 +.names 2958 2959 +1 1 +.names 4221 4229 56856 +11 1 +.names 2959 56857 2961 +1- 1 +-1 1 +.names 2961 2962 +1 1 +.names 4221 4231 56857 +11 1 +.names 2962 56858 2964 +1- 1 +-1 1 +.names 2964 2965 +1 1 +.names 4221 4233 56858 +11 1 +.names 2965 56859 2967 +1- 1 +-1 1 +.names 2967 2968 +1 1 +.names 4221 4235 56859 +11 1 +.names 2968 56860 2970 +1- 1 +-1 1 +.names 2970 2971 +1 1 +.names 4221 4237 56860 +11 1 +.names 2971 56861 2973 +1- 1 +-1 1 +.names 2973 2974 +1 1 +.names 4221 4239 56861 +11 1 +.names 2974 56862 2976 +1- 1 +-1 1 +.names 2976 2977 +1 1 +.names 4221 4241 56862 +11 1 +.names 2977 56863 2979 +1- 1 +-1 1 +.names 2979 2980 +1 1 +.names 4221 4243 56863 +11 1 +.names 2980 56864 2982 +1- 1 +-1 1 +.names 2982 2983 +1 1 +.names 4221 4245 56864 +11 1 +.names 2983 56865 2985 +1- 1 +-1 1 +.names 2985 2986 +1 1 +.names 4221 4247 56865 +11 1 +.names 2986 56866 2988 +1- 1 +-1 1 +.names 2988 2989 +1 1 +.names 4221 4249 56866 +11 1 +.names 2989 56867 2991 +1- 1 +-1 1 +.names 2991 2992 +1 1 +.names 3012 3010 56867 +1- 1 +-1 1 +.names 2992 56868 2994 +1- 1 +-1 1 +.names 2994 2995 +1 1 +.names 3008 3005 56868 +1- 1 +-1 1 +.names 2995 56869 2997 +1- 1 +-1 1 +.names 2997 2998 +1 1 +.names 4221 4255 56869 +11 1 +.names 2998 56870 3000 +1- 1 +-1 1 +.names 3000 3001 +1 1 +.names 4221 4257 56870 +11 1 +.names 3001 56871 +0 1 +.names 56872 722 3004 +11 1 +.names 3004 3005 +1 1 +.names 4221 4319 56872 +11 1 +.names 4221 4253 3007 +11 1 +.names 3007 3008 +1 1 +.names 56872 723 3009 +11 1 +.names 3009 3010 +1 1 +.names 4221 4251 3011 +11 1 +.names 3011 3012 +1 1 +.names 56874 56875 3013 +1- 1 +-1 1 +.names 3013 3014 +1 1 +.names 4221 4277 56874 +11 1 +.names 4221 4279 56875 +11 1 +.names 3014 56876 3017 +1- 1 +-1 1 +.names 3017 3018 +1 1 +.names 4221 4281 56876 +11 1 +.names 3018 56877 3020 +1- 1 +-1 1 +.names 3020 3021 +1 1 +.names 4221 4283 56877 +11 1 +.names 3021 56878 3023 +1- 1 +-1 1 +.names 3023 3024 +1 1 +.names 4221 4285 56878 +11 1 +.names 3024 56879 3026 +1- 1 +-1 1 +.names 3026 3027 +1 1 +.names 4221 4287 56879 +11 1 +.names 3027 56880 3029 +1- 1 +-1 1 +.names 3029 3030 +1 1 +.names 4221 4289 56880 +11 1 +.names 3030 56881 3032 +1- 1 +-1 1 +.names 3032 3033 +1 1 +.names 4221 4291 56881 +11 1 +.names 3033 56882 3035 +1- 1 +-1 1 +.names 3035 3036 +1 1 +.names 4221 4293 56882 +11 1 +.names 3036 56883 3038 +1- 1 +-1 1 +.names 3038 3039 +1 1 +.names 4221 4295 56883 +11 1 +.names 3039 56884 3041 +1- 1 +-1 1 +.names 3041 3042 +1 1 +.names 4221 4297 56884 +11 1 +.names 3042 56885 3044 +1- 1 +-1 1 +.names 3044 3045 +1 1 +.names 4221 4299 56885 +11 1 +.names 3045 56886 3047 +1- 1 +-1 1 +.names 3047 3048 +1 1 +.names 4221 4301 56886 +11 1 +.names 3048 56887 3050 +1- 1 +-1 1 +.names 3050 3051 +1 1 +.names 4221 4303 56887 +11 1 +.names 3051 56888 3053 +1- 1 +-1 1 +.names 3053 3054 +1 1 +.names 4221 4305 56888 +11 1 +.names 3054 56889 3056 +1- 1 +-1 1 +.names 3056 3057 +1 1 +.names 4221 4307 56889 +11 1 +.names 3057 56890 3059 +1- 1 +-1 1 +.names 3059 3060 +1 1 +.names 4221 4309 56890 +11 1 +.names 3060 56891 3062 +1- 1 +-1 1 +.names 3062 3063 +1 1 +.names 4221 4311 56891 +11 1 +.names 3063 56892 3065 +1- 1 +-1 1 +.names 3065 3066 +1 1 +.names 4221 4313 56892 +11 1 +.names 3066 56893 3068 +1- 1 +-1 1 +.names 3068 3069 +1 1 +.names 4221 4315 56893 +11 1 +.names 3069 56894 +0 1 +.names 56666 3072 +0 1 +.names 3072 3073 +1 1 +.names 3079 760 56666 +1- 1 +-1 1 +.names 2584 3075 +1 1 +.names 758 3076 +0 1 +.names 3076 3077 +1 1 +.names 759 3077 3078 +11 1 +.names 3078 3079 +1 1 +.names 3076 3080 +1 1 +.names 2584 3081 +1 1 +.names 3081 56830 3082 +11 1 +.names 3082 3083 +1 1 +.names 3083 733 3084 +11 1 +.names 3084 3085 +1 1 +.names 3085 3080 56665 +11 1 +.names 761 3087 +0 1 +.names 3087 3088 +1 1 +.names 3092 3094 3089 +11 1 +.names 3089 3090 +1 1 +.names 3233 3231 3091 +11 1 +.names 3091 3092 +1 1 +.names 21896 21897 3093 +11 1 +.names 3093 3094 +1 1 +.names 3090 762 3095 +11 1 +.names 3095 3096 +1 1 +.names 3096 3088 3097 +11 1 +.names 3097 3098 +1 1 +.names 763 3099 +0 1 +.names 3099 3100 +1 1 +.names 3104 3106 3101 +11 1 +.names 3101 3102 +1 1 +.names 3239 3237 3103 +11 1 +.names 3103 3104 +1 1 +.names 21795 21796 3105 +11 1 +.names 3105 3106 +1 1 +.names 3102 764 3107 +11 1 +.names 3107 3108 +1 1 +.names 3108 3100 3109 +11 1 +.names 3109 3110 +1 1 +.names 3114 3111 +0 1 +.names 3111 3112 +1 1 +.names 20679 20682 3113 +11 1 +.names 3113 3114 +1 1 +.names 2447 3115 +1 1 +.names 204 3116 +0 1 +.names 3116 3117 +1 1 +.names 3117 3115 3118 +11 1 +.names 3118 3119 +1 1 +.names 3119 3123 3120 +11 1 +.names 3120 3121 +1 1 +.names 3186 3175 3122 +11 1 +.names 3122 3123 +1 1 +.names 3121 3112 3124 +11 1 +.names 3124 3125 +1 1 +.names 3125 3129 3126 +11 1 +.names 3126 3127 +1 1 +.names 20787 20790 3128 +11 1 +.names 3128 3129 +1 1 +.names 3127 3133 3130 +11 1 +.names 3130 3131 +1 1 +.names 4219 4217 3132 +11 1 +.names 3132 3133 +1 1 +.names 2447 3134 +1 1 +.names 3116 3135 +1 1 +.names 3135 3134 3136 +11 1 +.names 3136 3137 +1 1 +.names 3137 3123 3138 +11 1 +.names 3138 3139 +1 1 +.names 3139 3114 3140 +11 1 +.names 3140 3141 +1 1 +.names 3141 3133 3142 +11 1 +.names 3142 3143 +1 1 +.names 3147 3149 3144 +1- 1 +-1 1 +.names 3144 3145 +1 1 +.names 3154 763 3146 +11 1 +.names 3146 3147 +1 1 +.names 3152 761 3148 +11 1 +.names 3148 3149 +1 1 +.names 3145 736 56895 +11 1 +.names 3094 3092 3151 +11 1 +.names 3151 3152 +1 1 +.names 3106 3104 3153 +11 1 +.names 3153 3154 +1 1 +.names 3157 3123 56896 +11 1 +.names 4216 4214 3156 +11 1 +.names 3156 3157 +1 1 +.names 2447 3158 +1 1 +.names 3114 3129 3159 +1- 1 +-1 1 +.names 3159 3160 +1 1 +.names 3160 3161 +0 1 +.names 3161 3162 +1 1 +.names 3114 3129 3163 +1- 1 +-1 1 +.names 3163 3164 +1 1 +.names 3164 204 3165 +11 1 +.names 3165 3166 +1 1 +.names 3166 3162 3167 +1- 1 +-1 1 +.names 3167 3168 +1 1 +.names 3123 3168 3169 +11 1 +.names 3169 3170 +1 1 +.names 3170 3158 3171 +11 1 +.names 3171 3172 +1 1 +.names 3172 3133 56897 +11 1 +.names 56898 3174 +0 1 +.names 3174 3175 +1 1 +.names 11054 11057 56898 +11 1 +.names 3180 3177 +0 1 +.names 3177 3178 +1 1 +.names 21195 21196 3179 +11 1 +.names 3179 3180 +1 1 +.names 3184 3181 +0 1 +.names 3181 3182 +1 1 +.names 21004 21005 3183 +11 1 +.names 3183 3184 +1 1 +.names 3182 3178 3185 +11 1 +.names 3185 3186 +1 1 +.names 2447 3187 +1 1 +.names 3191 3193 3188 +1- 1 +-1 1 +.names 3188 3189 +1 1 +.names 3212 3214 3190 +11 1 +.names 3190 3191 +1 1 +.names 3104 3210 3192 +11 1 +.names 3192 3193 +1 1 +.names 3189 3197 3194 +1- 1 +-1 1 +.names 3194 3195 +1 1 +.names 3206 3208 3196 +11 1 +.names 3196 3197 +1 1 +.names 3195 3201 3198 +1- 1 +-1 1 +.names 3198 3199 +1 1 +.names 3092 3204 3200 +11 1 +.names 3200 3201 +1 1 +.names 3199 3187 56899 +11 1 +.names 21330 21331 3203 +11 1 +.names 3203 3204 +1 1 +.names 3236 3234 3205 +11 1 +.names 3205 3206 +1 1 +.names 21580 21581 3207 +11 1 +.names 3207 3208 +1 1 +.names 21245 21246 3209 +11 1 +.names 3209 3210 +1 1 +.names 3242 3240 3211 +11 1 +.names 3211 3212 +1 1 +.names 21397 21398 3213 +11 1 +.names 3213 3214 +1 1 +.names 2447 3215 +1 1 +.names 3206 3092 3216 +1- 1 +-1 1 +.names 3216 3217 +1 1 +.names 3217 56843 3218 +1- 1 +-1 1 +.names 3218 3219 +1 1 +.names 3219 3131 3220 +1- 1 +-1 1 +.names 3220 3221 +1 1 +.names 3221 3215 56900 +11 1 +.names 2447 3223 +1 1 +.names 3212 3104 3224 +1- 1 +-1 1 +.names 3224 3225 +1 1 +.names 3225 56842 3226 +1- 1 +-1 1 +.names 3226 3227 +1 1 +.names 3227 3143 3228 +1- 1 +-1 1 +.names 3228 3229 +1 1 +.names 3229 3223 56901 +11 1 +.names 3174 3231 +1 1 +.names 3157 3180 3232 +11 1 +.names 3232 3233 +1 1 +.names 3174 3234 +1 1 +.names 3133 3180 3235 +11 1 +.names 3235 3236 +1 1 +.names 3174 3237 +1 1 +.names 3157 3184 3238 +11 1 +.names 3238 3239 +1 1 +.names 3174 3240 +1 1 +.names 3133 3184 3241 +11 1 +.names 3241 3242 +1 1 +.names 2679 3243 +1 1 +.names 765 766 3244 +1- 1 +-1 1 +.names 3244 3245 +1 1 +.names 3245 767 3246 +1- 1 +-1 1 +.names 3246 3247 +1 1 +.names 3247 56898 3248 +11 1 +.names 3248 3249 +1 1 +.names 3249 3243 3250 +11 1 +.names 3250 3251 +1 1 +.names 3251 736 56902 +11 1 +.names 768 3253 +0 1 +.names 3253 3254 +1 1 +.names 3257 3254 56903 +11 1 +.names 3271 774 3256 +11 1 +.names 3256 3257 +1 1 +.names 769 770 3258 +11 1 +.names 3258 3259 +1 1 +.names 3259 3260 +0 1 +.names 3260 3261 +1 1 +.names 3265 771 3262 +11 1 +.names 3262 3263 +1 1 +.names 3291 3295 3264 +11 1 +.names 3264 3265 +1 1 +.names 3263 3261 3266 +11 1 +.names 3266 3267 +1 1 +.names 3267 772 3268 +11 1 +.names 3268 3269 +1 1 +.names 3269 773 3270 +11 1 +.names 3270 3271 +1 1 +.names 3275 3277 3272 +11 1 +.names 3272 3273 +1 1 +.names 3323 3321 3274 +1- 1 +-1 1 +.names 3274 3275 +1 1 +.names 3319 3317 3276 +1- 1 +-1 1 +.names 3276 3277 +1 1 +.names 3273 3281 3278 +11 1 +.names 3278 3279 +1 1 +.names 3315 3313 3280 +1- 1 +-1 1 +.names 3280 3281 +1 1 +.names 3279 3285 3282 +11 1 +.names 3282 3283 +1 1 +.names 3311 3309 3284 +1- 1 +-1 1 +.names 3284 3285 +1 1 +.names 3283 3289 3286 +11 1 +.names 3286 3287 +1 1 +.names 3307 3305 3288 +1- 1 +-1 1 +.names 3288 3289 +1 1 +.names 3287 3293 3290 +11 1 +.names 3290 3291 +1 1 +.names 3303 3301 3292 +1- 1 +-1 1 +.names 3292 3293 +1 1 +.names 3299 3297 3294 +1- 1 +-1 1 +.names 3294 3295 +1 1 +.names 775 3296 +0 1 +.names 3296 3297 +1 1 +.names 6386 3298 +0 1 +.names 3298 3299 +1 1 +.names 776 3300 +0 1 +.names 3300 3301 +1 1 +.names 6388 3302 +0 1 +.names 3302 3303 +1 1 +.names 777 3304 +0 1 +.names 3304 3305 +1 1 +.names 6390 3306 +0 1 +.names 3306 3307 +1 1 +.names 778 3308 +0 1 +.names 3308 3309 +1 1 +.names 6392 3310 +0 1 +.names 3310 3311 +1 1 +.names 779 3312 +0 1 +.names 3312 3313 +1 1 +.names 20545 20546 3314 +11 1 +.names 3314 3315 +1 1 +.names 780 3316 +0 1 +.names 3316 3317 +1 1 +.names 6394 3318 +0 1 +.names 3318 3319 +1 1 +.names 781 3320 +0 1 +.names 3320 3321 +1 1 +.names 20501 20502 3322 +11 1 +.names 3322 3323 +1 1 +.names 3253 3324 +1 1 +.names 3327 3324 56904 +11 1 +.names 3341 785 3326 +11 1 +.names 3326 3327 +1 1 +.names 769 782 3328 +11 1 +.names 3328 3329 +1 1 +.names 3329 3330 +0 1 +.names 3330 3331 +1 1 +.names 3335 771 3332 +11 1 +.names 3332 3333 +1 1 +.names 3361 3365 3334 +11 1 +.names 3334 3335 +1 1 +.names 3333 3331 3336 +11 1 +.names 3336 3337 +1 1 +.names 3337 783 3338 +11 1 +.names 3338 3339 +1 1 +.names 3339 784 3340 +11 1 +.names 3340 3341 +1 1 +.names 3345 3347 3342 +11 1 +.names 3342 3343 +1 1 +.names 3393 3391 3344 +1- 1 +-1 1 +.names 3344 3345 +1 1 +.names 3389 3387 3346 +1- 1 +-1 1 +.names 3346 3347 +1 1 +.names 3343 3351 3348 +11 1 +.names 3348 3349 +1 1 +.names 3385 3383 3350 +1- 1 +-1 1 +.names 3350 3351 +1 1 +.names 3349 3355 3352 +11 1 +.names 3352 3353 +1 1 +.names 3381 3379 3354 +1- 1 +-1 1 +.names 3354 3355 +1 1 +.names 3353 3359 3356 +11 1 +.names 3356 3357 +1 1 +.names 3377 3375 3358 +1- 1 +-1 1 +.names 3358 3359 +1 1 +.names 3357 3363 3360 +11 1 +.names 3360 3361 +1 1 +.names 3373 3371 3362 +1- 1 +-1 1 +.names 3362 3363 +1 1 +.names 3369 3367 3364 +1- 1 +-1 1 +.names 3364 3365 +1 1 +.names 786 3366 +0 1 +.names 3366 3367 +1 1 +.names 6396 3368 +0 1 +.names 3368 3369 +1 1 +.names 787 3370 +0 1 +.names 3370 3371 +1 1 +.names 6398 3372 +0 1 +.names 3372 3373 +1 1 +.names 788 3374 +0 1 +.names 3374 3375 +1 1 +.names 6400 3376 +0 1 +.names 3376 3377 +1 1 +.names 789 3378 +0 1 +.names 3378 3379 +1 1 +.names 6402 3380 +0 1 +.names 3380 3381 +1 1 +.names 790 3382 +0 1 +.names 3382 3383 +1 1 +.names 20355 20356 3384 +11 1 +.names 3384 3385 +1 1 +.names 791 3386 +0 1 +.names 3386 3387 +1 1 +.names 6404 3388 +0 1 +.names 3388 3389 +1 1 +.names 792 3390 +0 1 +.names 3390 3391 +1 1 +.names 20310 20311 3392 +11 1 +.names 3392 3393 +1 1 +.names 793 3394 +0 1 +.names 3394 3395 +1 1 +.names 714 3395 56905 +11 1 +.names 2584 3397 +1 1 +.names 3397 794 56906 +1- 1 +-1 1 +.names 3401 3403 56907 +11 1 +.names 3446 3450 3400 +11 1 +.names 3400 3401 +1 1 +.names 3426 736 3402 +11 1 +.names 3402 3403 +1 1 +.names 772 3404 +0 1 +.names 3404 3405 +1 1 +.names 769 770 3406 +11 1 +.names 3406 3407 +1 1 +.names 3407 3408 +0 1 +.names 3408 3409 +1 1 +.names 3413 773 3410 +11 1 +.names 3410 3411 +1 1 +.names 3574 56731 3412 +1- 1 +-1 1 +.names 3412 3413 +1 1 +.names 773 3414 +0 1 +.names 3414 3415 +1 1 +.names 56419 3415 3416 +11 1 +.names 3416 3417 +1 1 +.names 6747 736 56419 +11 1 +.names 3417 3411 3419 +1- 1 +-1 1 +.names 3419 3420 +1 1 +.names 3420 3409 3421 +11 1 +.names 3421 3422 +1 1 +.names 3422 774 3423 +11 1 +.names 3423 3424 +1 1 +.names 3424 3405 3425 +11 1 +.names 3425 3426 +1 1 +.names 3430 3432 3427 +11 1 +.names 3427 3428 +1 1 +.names 3471 3469 3429 +1- 1 +-1 1 +.names 3429 3430 +1 1 +.names 3468 3466 3431 +1- 1 +-1 1 +.names 3431 3432 +1 1 +.names 3428 3436 3433 +11 1 +.names 3433 3434 +1 1 +.names 3465 3463 3435 +1- 1 +-1 1 +.names 3435 3436 +1 1 +.names 3434 3440 3437 +11 1 +.names 3437 3438 +1 1 +.names 3462 3460 3439 +1- 1 +-1 1 +.names 3439 3440 +1 1 +.names 3438 3444 3441 +11 1 +.names 3441 3442 +1 1 +.names 3459 3457 3443 +1- 1 +-1 1 +.names 3443 3444 +1 1 +.names 3442 3448 3445 +11 1 +.names 3445 3446 +1 1 +.names 3456 3454 3447 +1- 1 +-1 1 +.names 3447 3448 +1 1 +.names 3453 3451 3449 +1- 1 +-1 1 +.names 3449 3450 +1 1 +.names 3296 3451 +1 1 +.names 6406 3452 +0 1 +.names 3452 3453 +1 1 +.names 3300 3454 +1 1 +.names 6409 3455 +0 1 +.names 3455 3456 +1 1 +.names 3304 3457 +1 1 +.names 6412 3458 +0 1 +.names 3458 3459 +1 1 +.names 3308 3460 +1 1 +.names 6415 3461 +0 1 +.names 3461 3462 +1 1 +.names 3312 3463 +1 1 +.names 20164 20165 3464 +11 1 +.names 3464 3465 +1 1 +.names 3316 3466 +1 1 +.names 6418 3467 +0 1 +.names 3467 3468 +1 1 +.names 3320 3469 +1 1 +.names 20120 20121 3470 +11 1 +.names 3470 3471 +1 1 +.names 3394 3472 +1 1 +.names 714 3472 56908 +11 1 +.names 2584 3474 +1 1 +.names 3474 794 56909 +1- 1 +-1 1 +.names 3478 3480 56910 +11 1 +.names 3520 3524 3477 +11 1 +.names 3477 3478 +1 1 +.names 3500 736 3479 +11 1 +.names 3479 3480 +1 1 +.names 783 3481 +0 1 +.names 3481 3482 +1 1 +.names 769 782 3483 +11 1 +.names 3483 3484 +1 1 +.names 3484 3485 +0 1 +.names 3485 3486 +1 1 +.names 3413 784 3487 +11 1 +.names 3487 3488 +1 1 +.names 784 3489 +0 1 +.names 3489 3490 +1 1 +.names 56419 3490 3491 +11 1 +.names 3491 3492 +1 1 +.names 3492 3488 3493 +1- 1 +-1 1 +.names 3493 3494 +1 1 +.names 3494 3486 3495 +11 1 +.names 3495 3496 +1 1 +.names 3496 785 3497 +11 1 +.names 3497 3498 +1 1 +.names 3498 3482 3499 +11 1 +.names 3499 3500 +1 1 +.names 3504 3506 3501 +11 1 +.names 3501 3502 +1 1 +.names 3545 3543 3503 +1- 1 +-1 1 +.names 3503 3504 +1 1 +.names 3542 3540 3505 +1- 1 +-1 1 +.names 3505 3506 +1 1 +.names 3502 3510 3507 +11 1 +.names 3507 3508 +1 1 +.names 3539 3537 3509 +1- 1 +-1 1 +.names 3509 3510 +1 1 +.names 3508 3514 3511 +11 1 +.names 3511 3512 +1 1 +.names 3536 3534 3513 +1- 1 +-1 1 +.names 3513 3514 +1 1 +.names 3512 3518 3515 +11 1 +.names 3515 3516 +1 1 +.names 3533 3531 3517 +1- 1 +-1 1 +.names 3517 3518 +1 1 +.names 3516 3522 3519 +11 1 +.names 3519 3520 +1 1 +.names 3530 3528 3521 +1- 1 +-1 1 +.names 3521 3522 +1 1 +.names 3527 3525 3523 +1- 1 +-1 1 +.names 3523 3524 +1 1 +.names 3366 3525 +1 1 +.names 6421 3526 +0 1 +.names 3526 3527 +1 1 +.names 3370 3528 +1 1 +.names 6423 3529 +0 1 +.names 3529 3530 +1 1 +.names 3374 3531 +1 1 +.names 6425 3532 +0 1 +.names 3532 3533 +1 1 +.names 3378 3534 +1 1 +.names 6427 3535 +0 1 +.names 3535 3536 +1 1 +.names 3382 3537 +1 1 +.names 19973 19974 3538 +11 1 +.names 3538 3539 +1 1 +.names 3386 3540 +1 1 +.names 6429 3541 +0 1 +.names 3541 3542 +1 1 +.names 3390 3543 +1 1 +.names 19920 19921 3544 +11 1 +.names 3544 3545 +1 1 +.names 3549 795 3546 +11 1 +.names 3546 3547 +1 1 +.names 3570 3560 3548 +11 1 +.names 3548 3549 +1 1 +.names 3547 796 3550 +11 1 +.names 3550 3551 +1 1 +.names 3551 733 56911 +11 1 +.names 3556 3558 3553 +1- 1 +-1 1 +.names 3553 3554 +1 1 +.names 17212 17213 3555 +11 1 +.names 3555 3556 +1 1 +.names 17039 16936 3557 +11 1 +.names 3557 3558 +1 1 +.names 3554 3562 3559 +1- 1 +-1 1 +.names 3559 3560 +1 1 +.names 16523 16524 3561 +11 1 +.names 3561 3562 +1 1 +.names 3566 3568 3563 +1- 1 +-1 1 +.names 3563 3564 +1 1 +.names 16045 16046 3565 +11 1 +.names 3565 3566 +1 1 +.names 15867 15762 3567 +11 1 +.names 3567 3568 +1 1 +.names 3564 3572 3569 +1- 1 +-1 1 +.names 3569 3570 +1 1 +.names 15349 15350 3571 +11 1 +.names 3571 3572 +1 1 +.names 56420 56912 3573 +1- 1 +-1 1 +.names 3573 3574 +1 1 +.names 6755 736 56420 +11 1 +.names 843 736 56912 +11 1 +.names 5325 841 56731 +11 1 +.names 56419 56420 3578 +1- 1 +-1 1 +.names 3578 3579 +1 1 +.names 3579 56912 3580 +1- 1 +-1 1 +.names 3580 3581 +1 1 +.names 3581 56731 3582 +1- 1 +-1 1 +.names 3582 3583 +1 1 +.names 797 3583 3584 +11 1 +.names 3584 3585 +1 1 +.names 798 799 3586 +1- 1 +-1 1 +.names 3586 3587 +1 1 +.names 3587 3585 56914 +1- 1 +-1 1 +.names 3592 795 3589 +11 1 +.names 3589 3590 +1 1 +.names 3613 3603 3591 +11 1 +.names 3591 3592 +1 1 +.names 3590 797 3593 +11 1 +.names 3593 3594 +1 1 +.names 3594 800 56915 +11 1 +.names 3599 3601 3596 +1- 1 +-1 1 +.names 3596 3597 +1 1 +.names 19518 19519 3598 +11 1 +.names 3598 3599 +1 1 +.names 19345 19242 3600 +11 1 +.names 3600 3601 +1 1 +.names 3597 3605 3602 +1- 1 +-1 1 +.names 3602 3603 +1 1 +.names 18840 18841 3604 +11 1 +.names 3604 3605 +1 1 +.names 3609 3611 3606 +1- 1 +-1 1 +.names 3606 3607 +1 1 +.names 18366 18367 3608 +11 1 +.names 3608 3609 +1 1 +.names 18188 18083 3610 +11 1 +.names 3610 3611 +1 1 +.names 3607 3615 3612 +1- 1 +-1 1 +.names 3612 3613 +1 1 +.names 17681 17682 3614 +11 1 +.names 3614 3615 +1 1 +.names 801 802 56916 +1- 1 +-1 1 +.names 3620 3622 3617 +1- 1 +-1 1 +.names 3617 3618 +1 1 +.names 808 3636 3619 +11 1 +.names 3619 3620 +1 1 +.names 3634 3636 3621 +11 1 +.names 3621 3622 +1 1 +.names 3626 803 3623 +1- 1 +-1 1 +.names 3623 3624 +1 1 +.names 808 3642 3625 +11 1 +.names 3625 3626 +1 1 +.names 3624 3630 3627 +1- 1 +-1 1 +.names 3627 3628 +1 1 +.names 3640 3642 3629 +11 1 +.names 3629 3630 +1 1 +.names 804 805 3631 +11 1 +.names 3631 3632 +1 1 +.names 3632 806 3633 +11 1 +.names 3633 3634 +1 1 +.names 56383 56387 3635 +1- 1 +-1 1 +.names 3635 3636 +1 1 +.names 804 805 3637 +11 1 +.names 3637 3638 +1 1 +.names 3638 806 3639 +11 1 +.names 3639 3640 +1 1 +.names 56376 56380 3641 +1- 1 +-1 1 +.names 3641 3642 +1 1 +.names 804 807 3643 +11 1 +.names 3643 3644 +1 1 +.names 3644 3647 56917 +11 1 +.names 56391 56395 3646 +1- 1 +-1 1 +.names 3646 3647 +1 1 +.names 804 807 3648 +11 1 +.names 3648 3649 +1 1 +.names 3649 3636 56919 +11 1 +.names 804 807 3651 +11 1 +.names 3651 3652 +1 1 +.names 3652 3642 56921 +11 1 +.names 56928 56929 +0 1 +.names 4792 827 56928 +1- 1 +-1 1 +.names 475 3656 +0 1 +.names 3656 3657 +1 1 +.names 809 3658 +0 1 +.names 3658 3659 +1 1 +.names 3659 476 3660 +11 1 +.names 3660 3661 +1 1 +.names 3661 3657 3662 +11 1 +.names 3662 3663 +1 1 +.names 3667 3669 3664 +1- 1 +-1 1 +.names 3664 3665 +1 1 +.names 3683 3680 3666 +11 1 +.names 3666 3667 +1 1 +.names 3676 810 3668 +11 1 +.names 3668 3669 +1 1 +.names 3665 3673 3670 +1- 1 +-1 1 +.names 3670 3671 +1 1 +.names 3679 475 3672 +11 1 +.names 3672 3673 +1 1 +.names 3671 3674 +0 1 +.names 3674 3675 +1 1 +.names 3658 3676 +1 1 +.names 3658 3677 +1 1 +.names 3677 476 3678 +11 1 +.names 3678 3679 +1 1 +.names 3656 3680 +1 1 +.names 3658 3681 +1 1 +.names 3681 476 3682 +11 1 +.names 3682 3683 +1 1 +.names 56821 56822 3684 +1- 1 +-1 1 +.names 3684 3685 +1 1 +.names 3685 56823 3686 +1- 1 +-1 1 +.names 3686 3687 +1 1 +.names 3687 56824 3688 +1- 1 +-1 1 +.names 3688 3689 +1 1 +.names 3689 56825 3690 +1- 1 +-1 1 +.names 3690 3691 +1 1 +.names 3691 56826 3692 +1- 1 +-1 1 +.names 3692 3693 +1 1 +.names 3693 56931 3694 +1- 1 +-1 1 +.names 3694 3695 +1 1 +.names 10222 56931 +0 1 +.names 3695 56932 3697 +1- 1 +-1 1 +.names 3697 3698 +1 1 +.names 10199 56932 +0 1 +.names 3698 56933 3700 +1- 1 +-1 1 +.names 3700 3701 +1 1 +.names 9873 56933 +0 1 +.names 3701 56934 3703 +1- 1 +-1 1 +.names 3703 3704 +1 1 +.names 9903 56934 +0 1 +.names 3704 56935 3706 +1- 1 +-1 1 +.names 3706 3707 +1 1 +.names 9853 56935 +0 1 +.names 3707 56936 3709 +1- 1 +-1 1 +.names 3709 3710 +1 1 +.names 10169 56936 +0 1 +.names 3710 56819 3712 +1- 1 +-1 1 +.names 3712 3713 +1 1 +.names 3713 56820 3714 +1- 1 +-1 1 +.names 3714 3715 +1 1 +.names 3715 56937 3716 +1- 1 +-1 1 +.names 3716 3717 +1 1 +.names 9813 56937 +0 1 +.names 3717 56807 3719 +1- 1 +-1 1 +.names 3719 3720 +1 1 +.names 3720 56828 3721 +1- 1 +-1 1 +.names 3721 3722 +1 1 +.names 3722 56829 3723 +1- 1 +-1 1 +.names 3723 3724 +1 1 +.names 3724 56780 3725 +1- 1 +-1 1 +.names 3725 3726 +1 1 +.names 3726 56781 3727 +1- 1 +-1 1 +.names 3727 3728 +1 1 +.names 3728 2480 3729 +1- 1 +-1 1 +.names 3729 3730 +1 1 +.names 3730 2472 3731 +1- 1 +-1 1 +.names 3731 3732 +1 1 +.names 3732 2474 3733 +1- 1 +-1 1 +.names 3733 3734 +1 1 +.names 3734 2464 3735 +1- 1 +-1 1 +.names 3735 3736 +1 1 +.names 3736 2466 3737 +1- 1 +-1 1 +.names 3737 3738 +1 1 +.names 3738 2482 3739 +1- 1 +-1 1 +.names 3739 3740 +1 1 +.names 3740 56782 3741 +1- 1 +-1 1 +.names 3741 3742 +1 1 +.names 3742 2476 3743 +1- 1 +-1 1 +.names 3743 3744 +1 1 +.names 3744 2468 3745 +1- 1 +-1 1 +.names 3745 3746 +1 1 +.names 56929 3747 +1 1 +.names 3747 3746 56938 +11 1 +.names 56940 2480 3749 +1- 1 +-1 1 +.names 3749 3750 +1 1 +.names 9891 56940 +0 1 +.names 3750 2472 3752 +1- 1 +-1 1 +.names 3752 3753 +1 1 +.names 3753 2474 3754 +1- 1 +-1 1 +.names 3754 3755 +1 1 +.names 3755 2464 3756 +1- 1 +-1 1 +.names 3756 3757 +1 1 +.names 3757 2466 3758 +1- 1 +-1 1 +.names 3758 3759 +1 1 +.names 3759 2482 3760 +1- 1 +-1 1 +.names 3760 3761 +1 1 +.names 3761 56782 3762 +1- 1 +-1 1 +.names 3762 3763 +1 1 +.names 3763 2476 3764 +1- 1 +-1 1 +.names 3764 3765 +1 1 +.names 3765 2468 3766 +1- 1 +-1 1 +.names 3766 3767 +1 1 +.names 3767 3771 3768 +1- 1 +-1 1 +.names 3768 3769 +1 1 +.names 4221 4431 3770 +11 1 +.names 3770 3771 +1 1 +.names 3769 3775 3772 +1- 1 +-1 1 +.names 3772 3773 +1 1 +.names 4221 4429 3774 +11 1 +.names 3774 3775 +1 1 +.names 3773 3779 3776 +1- 1 +-1 1 +.names 3776 3777 +1 1 +.names 4221 4427 3778 +11 1 +.names 3778 3779 +1 1 +.names 3777 3783 3780 +1- 1 +-1 1 +.names 3780 3781 +1 1 +.names 4221 4425 3782 +11 1 +.names 3782 3783 +1 1 +.names 3781 3787 3784 +1- 1 +-1 1 +.names 3784 3785 +1 1 +.names 4221 4423 3786 +11 1 +.names 3786 3787 +1 1 +.names 3785 56838 3788 +1- 1 +-1 1 +.names 3788 3789 +1 1 +.names 3789 56839 3790 +1- 1 +-1 1 +.names 3790 3791 +1 1 +.names 3791 3795 3792 +1- 1 +-1 1 +.names 3792 3793 +1 1 +.names 4221 4413 3794 +11 1 +.names 3794 3795 +1 1 +.names 3793 3799 3796 +1- 1 +-1 1 +.names 3796 3797 +1 1 +.names 4221 4411 3798 +11 1 +.names 3798 3799 +1 1 +.names 3797 3803 3800 +1- 1 +-1 1 +.names 3800 3801 +1 1 +.names 4221 4409 3802 +11 1 +.names 3802 3803 +1 1 +.names 3801 2674 3804 +1- 1 +-1 1 +.names 3804 3805 +1 1 +.names 3805 2676 3806 +1- 1 +-1 1 +.names 3806 3807 +1 1 +.names 3807 3811 3808 +1- 1 +-1 1 +.names 3808 3809 +1 1 +.names 4221 4399 3810 +11 1 +.names 3810 3811 +1 1 +.names 3809 3815 3812 +1- 1 +-1 1 +.names 3812 3813 +1 1 +.names 4221 4397 3814 +11 1 +.names 3814 3815 +1 1 +.names 3813 3819 3816 +1- 1 +-1 1 +.names 3816 3817 +1 1 +.names 4221 4395 3818 +11 1 +.names 3818 3819 +1 1 +.names 3817 3823 3820 +1- 1 +-1 1 +.names 3820 3821 +1 1 +.names 4221 4393 3822 +11 1 +.names 3822 3823 +1 1 +.names 3821 3827 3824 +1- 1 +-1 1 +.names 3824 3825 +1 1 +.names 4221 4391 3826 +11 1 +.names 3826 3827 +1 1 +.names 3825 56941 3828 +1- 1 +-1 1 +.names 3828 3829 +1 1 +.names 4221 4384 56941 +11 1 +.names 3829 3834 3831 +1- 1 +-1 1 +.names 3831 3832 +1 1 +.names 4221 4382 3833 +11 1 +.names 3833 3834 +1 1 +.names 3832 3838 3835 +1- 1 +-1 1 +.names 3835 3836 +1 1 +.names 4221 4380 3837 +11 1 +.names 3837 3838 +1 1 +.names 3836 3842 3839 +1- 1 +-1 1 +.names 3839 3840 +1 1 +.names 4221 4378 3841 +11 1 +.names 3841 3842 +1 1 +.names 3840 56942 3843 +1- 1 +-1 1 +.names 3843 3844 +1 1 +.names 4221 4372 56942 +11 1 +.names 3844 56943 3846 +1- 1 +-1 1 +.names 3846 3847 +1 1 +.names 4221 4370 56943 +11 1 +.names 3847 3852 3849 +1- 1 +-1 1 +.names 3849 3850 +1 1 +.names 4221 4368 3851 +11 1 +.names 3851 3852 +1 1 +.names 3850 3856 3853 +1- 1 +-1 1 +.names 3853 3854 +1 1 +.names 4221 4366 3855 +11 1 +.names 3855 3856 +1 1 +.names 3854 3860 3857 +1- 1 +-1 1 +.names 3857 3858 +1 1 +.names 4221 4364 3859 +11 1 +.names 3859 3860 +1 1 +.names 3858 56944 3861 +1- 1 +-1 1 +.names 3861 3862 +1 1 +.names 4221 4358 56944 +11 1 +.names 3862 56945 3864 +1- 1 +-1 1 +.names 3864 3865 +1 1 +.names 4221 4356 56945 +11 1 +.names 3865 3870 3867 +1- 1 +-1 1 +.names 3867 3868 +1 1 +.names 4221 4354 3869 +11 1 +.names 3869 3870 +1 1 +.names 3868 3874 3871 +1- 1 +-1 1 +.names 3871 3872 +1 1 +.names 4221 4352 3873 +11 1 +.names 3873 3874 +1 1 +.names 3872 56946 3875 +1- 1 +-1 1 +.names 3875 3876 +1 1 +.names 4221 4346 56946 +11 1 +.names 3876 56947 3878 +1- 1 +-1 1 +.names 3878 3879 +1 1 +.names 4221 4344 56947 +11 1 +.names 3879 3884 3881 +1- 1 +-1 1 +.names 3881 3882 +1 1 +.names 4221 4342 3883 +11 1 +.names 3883 3884 +1 1 +.names 3882 3888 3885 +1- 1 +-1 1 +.names 3885 3886 +1 1 +.names 4221 4340 3887 +11 1 +.names 3887 3888 +1 1 +.names 3886 3892 3889 +1- 1 +-1 1 +.names 3889 3890 +1 1 +.names 4221 4338 3891 +11 1 +.names 3891 3892 +1 1 +.names 3890 3896 3893 +1- 1 +-1 1 +.names 3893 3894 +1 1 +.names 4221 4329 3895 +11 1 +.names 3895 3896 +1 1 +.names 3894 3900 3897 +1- 1 +-1 1 +.names 3897 3898 +1 1 +.names 4221 4327 3899 +11 1 +.names 3899 3900 +1 1 +.names 3898 3904 3901 +1- 1 +-1 1 +.names 3901 3902 +1 1 +.names 4221 4321 3903 +11 1 +.names 3903 3904 +1 1 +.names 3902 56948 3905 +1- 1 +-1 1 +.names 3905 3906 +1 1 +.names 4221 4259 56948 +11 1 +.names 56929 3908 +1 1 +.names 3908 3906 56949 +11 1 +.names 2591 3910 +1 1 +.names 811 3910 3911 +11 1 +.names 3911 3912 +1 1 +.names 2591 3913 +1 1 +.names 812 3913 3914 +11 1 +.names 3914 3915 +1 1 +.names 2591 3916 +1 1 +.names 813 3916 3917 +11 1 +.names 3917 3918 +1 1 +.names 814 3922 3919 +1- 1 +-1 1 +.names 3919 3920 +1 1 +.names 3932 2884 3921 +1- 1 +-1 1 +.names 3921 3922 +1 1 +.names 2591 3923 +1 1 +.names 815 3923 3924 +11 1 +.names 3924 3925 +1 1 +.names 2591 3926 +1 1 +.names 816 3926 3927 +11 1 +.names 3927 3928 +1 1 +.names 2888 2876 3929 +1- 1 +-1 1 +.names 3929 3930 +1 1 +.names 3930 2880 3931 +1- 1 +-1 1 +.names 3931 3932 +1 1 +.names 56951 56952 3933 +1- 1 +-1 1 +.names 3933 3934 +1 1 +.names 56961 56962 56951 +1- 1 +-1 1 +.names 4055 56960 56952 +1- 1 +-1 1 +.names 3934 56953 3937 +1- 1 +-1 1 +.names 3937 3938 +1 1 +.names 4053 56874 56953 +1- 1 +-1 1 +.names 3938 56954 3940 +1- 1 +-1 1 +.names 3940 3941 +1 1 +.names 4013 2579 56954 +1- 1 +-1 1 +.names 3941 56955 3943 +1- 1 +-1 1 +.names 3943 3944 +1 1 +.names 3981 2495 56955 +1- 1 +-1 1 +.names 3944 56956 3946 +1- 1 +-1 1 +.names 3946 3947 +1 1 +.names 3973 2597 56956 +1- 1 +-1 1 +.names 3947 1783 3949 +1- 1 +-1 1 +.names 3949 3950 +1 1 +.names 3950 56957 +0 1 +.names 3955 2621 3952 +1- 1 +-1 1 +.names 3952 3953 +1 1 +.names 10203 3954 +0 1 +.names 3954 3955 +1 1 +.names 3953 2599 3956 +1- 1 +-1 1 +.names 3956 3957 +1 1 +.names 3957 3961 3958 +1- 1 +-1 1 +.names 3958 3959 +1 1 +.names 10181 3960 +0 1 +.names 3960 3961 +1 1 +.names 3959 56941 3962 +1- 1 +-1 1 +.names 3962 3963 +1 1 +.names 3963 56942 3964 +1- 1 +-1 1 +.names 3964 3965 +1 1 +.names 3965 56943 3966 +1- 1 +-1 1 +.names 3966 3967 +1 1 +.names 3967 3971 3968 +1- 1 +-1 1 +.names 3968 3969 +1 1 +.names 9911 3970 +0 1 +.names 3970 3971 +1 1 +.names 3969 2617 3972 +1- 1 +-1 1 +.names 3972 3973 +1 1 +.names 2513 56789 3974 +1- 1 +-1 1 +.names 3974 3975 +1 1 +.names 3975 2520 3976 +1- 1 +-1 1 +.names 3976 3977 +1 1 +.names 3977 2491 3978 +1- 1 +-1 1 +.names 3978 3979 +1 1 +.names 3979 2487 3980 +1- 1 +-1 1 +.names 3980 3981 +1 1 +.names 2566 3985 3982 +1- 1 +-1 1 +.names 3982 3983 +1 1 +.names 10201 3984 +0 1 +.names 3984 3985 +1 1 +.names 3983 2574 3986 +1- 1 +-1 1 +.names 3986 3987 +1 1 +.names 3987 56799 3988 +1- 1 +-1 1 +.names 3988 3989 +1 1 +.names 3989 56807 3990 +1- 1 +-1 1 +.names 3990 3991 +1 1 +.names 3991 56781 3992 +1- 1 +-1 1 +.names 3992 3993 +1 1 +.names 3993 56798 3994 +1- 1 +-1 1 +.names 3994 3995 +1 1 +.names 3995 56797 3996 +1- 1 +-1 1 +.names 3996 3997 +1 1 +.names 3997 56796 3998 +1- 1 +-1 1 +.names 3998 3999 +1 1 +.names 3999 4003 4000 +1- 1 +-1 1 +.names 4000 4001 +1 1 +.names 10068 4002 +0 1 +.names 4002 4003 +1 1 +.names 4001 4007 4004 +1- 1 +-1 1 +.names 4004 4005 +1 1 +.names 10260 4006 +0 1 +.names 4006 4007 +1 1 +.names 4005 2572 4008 +1- 1 +-1 1 +.names 4008 4009 +1 1 +.names 4009 2564 4010 +1- 1 +-1 1 +.names 4010 4011 +1 1 +.names 4011 2577 4012 +1- 1 +-1 1 +.names 4012 4013 +1 1 +.names 4017 56893 4014 +1- 1 +-1 1 +.names 4014 4015 +1 1 +.names 4221 4317 4016 +11 1 +.names 4016 4017 +1 1 +.names 4015 56892 4018 +1- 1 +-1 1 +.names 4018 4019 +1 1 +.names 4019 56891 4020 +1- 1 +-1 1 +.names 4020 4021 +1 1 +.names 4021 56890 4022 +1- 1 +-1 1 +.names 4022 4023 +1 1 +.names 4023 56889 4024 +1- 1 +-1 1 +.names 4024 4025 +1 1 +.names 4025 56888 4026 +1- 1 +-1 1 +.names 4026 4027 +1 1 +.names 4027 56887 4028 +1- 1 +-1 1 +.names 4028 4029 +1 1 +.names 4029 56886 4030 +1- 1 +-1 1 +.names 4030 4031 +1 1 +.names 4031 56885 4032 +1- 1 +-1 1 +.names 4032 4033 +1 1 +.names 4033 56884 4034 +1- 1 +-1 1 +.names 4034 4035 +1 1 +.names 4035 56883 4036 +1- 1 +-1 1 +.names 4036 4037 +1 1 +.names 4037 56882 4038 +1- 1 +-1 1 +.names 4038 4039 +1 1 +.names 4039 56881 4040 +1- 1 +-1 1 +.names 4040 4041 +1 1 +.names 4041 56880 4042 +1- 1 +-1 1 +.names 4042 4043 +1 1 +.names 4043 56879 4044 +1- 1 +-1 1 +.names 4044 4045 +1 1 +.names 4045 56878 4046 +1- 1 +-1 1 +.names 4046 4047 +1 1 +.names 4047 56877 4048 +1- 1 +-1 1 +.names 4048 4049 +1 1 +.names 4049 56876 4050 +1- 1 +-1 1 +.names 4050 4051 +1 1 +.names 4051 56875 4052 +1- 1 +-1 1 +.names 4052 4053 +1 1 +.names 56958 56959 4054 +1- 1 +-1 1 +.names 4054 4055 +1 1 +.names 10197 56958 +0 1 +.names 10175 56959 +0 1 +.names 9787 56960 +0 1 +.names 10173 56961 +0 1 +.names 4221 4389 56962 +11 1 +.names 56964 56965 +0 1 +.names 4090 4066 56964 +1- 1 +-1 1 +.names 722 723 4063 +1- 1 +-1 1 +.names 4063 4064 +1 1 +.names 2564 4064 4065 +11 1 +.names 4065 4066 +1 1 +.names 722 723 4067 +1- 1 +-1 1 +.names 4067 4068 +1 1 +.names 2572 4068 4069 +11 1 +.names 4069 4070 +1 1 +.names 722 723 4071 +1- 1 +-1 1 +.names 4071 4072 +1 1 +.names 4007 4072 4073 +11 1 +.names 4073 4074 +1 1 +.names 2566 3985 4075 +1- 1 +-1 1 +.names 4075 4076 +1 1 +.names 4076 2574 4077 +1- 1 +-1 1 +.names 4077 4078 +1 1 +.names 4078 56807 4079 +1- 1 +-1 1 +.names 4079 4080 +1 1 +.names 4080 56781 4081 +1- 1 +-1 1 +.names 4081 4082 +1 1 +.names 4082 2577 4083 +1- 1 +-1 1 +.names 4083 4084 +1 1 +.names 4084 2579 4085 +1- 1 +-1 1 +.names 4085 4086 +1 1 +.names 4086 4074 4087 +1- 1 +-1 1 +.names 4087 4088 +1 1 +.names 4088 4070 4089 +1- 1 +-1 1 +.names 4089 4090 +1 1 +.names 817 807 4091 +11 1 +.names 4091 4092 +1 1 +.names 2495 2491 4093 +1- 1 +-1 1 +.names 4093 4094 +1 1 +.names 4094 2487 56969 +1- 1 +-1 1 +.names 2513 56789 4096 +1- 1 +-1 1 +.names 4096 4097 +1 1 +.names 4097 2520 56970 +1- 1 +-1 1 +.names 818 736 4099 +11 1 +.names 4099 4100 +1 1 +.names 722 723 4101 +1- 1 +-1 1 +.names 4101 4102 +1 1 +.names 2491 4102 4103 +11 1 +.names 4103 4104 +1 1 +.names 56961 722 4105 +11 1 +.names 4105 4106 +1 1 +.names 56789 56827 4107 +1- 1 +-1 1 +.names 4107 4108 +1 1 +.names 4108 4106 4109 +1- 1 +-1 1 +.names 4109 4110 +1 1 +.names 4110 56821 4111 +1- 1 +-1 1 +.names 4111 4112 +1 1 +.names 4112 56822 4113 +1- 1 +-1 1 +.names 4113 4114 +1 1 +.names 4114 56823 4115 +1- 1 +-1 1 +.names 4115 4116 +1 1 +.names 4116 56824 4117 +1- 1 +-1 1 +.names 4117 4118 +1 1 +.names 4118 56825 4119 +1- 1 +-1 1 +.names 4119 4120 +1 1 +.names 4120 56826 4121 +1- 1 +-1 1 +.names 4121 4122 +1 1 +.names 4122 56931 4123 +1- 1 +-1 1 +.names 4123 4124 +1 1 +.names 4124 56932 4125 +1- 1 +-1 1 +.names 4125 4126 +1 1 +.names 4126 56933 4127 +1- 1 +-1 1 +.names 4127 4128 +1 1 +.names 4128 56934 4129 +1- 1 +-1 1 +.names 4129 4130 +1 1 +.names 4130 56935 4131 +1- 1 +-1 1 +.names 4131 4132 +1 1 +.names 4132 56936 4133 +1- 1 +-1 1 +.names 4133 4134 +1 1 +.names 4134 56931 4135 +1- 1 +-1 1 +.names 4135 4136 +1 1 +.names 4136 56932 4137 +1- 1 +-1 1 +.names 4137 4138 +1 1 +.names 4138 56819 4139 +1- 1 +-1 1 +.names 4139 4140 +1 1 +.names 4140 56820 4141 +1- 1 +-1 1 +.names 4141 4142 +1 1 +.names 4142 56828 4143 +1- 1 +-1 1 +.names 4143 4144 +1 1 +.names 4144 56829 4145 +1- 1 +-1 1 +.names 4145 4146 +1 1 +.names 4146 4104 56972 +1- 1 +-1 1 +.names 2513 56789 4148 +1- 1 +-1 1 +.names 4148 4149 +1 1 +.names 4149 2520 56974 +1- 1 +-1 1 +.names 819 736 4151 +11 1 +.names 4151 4152 +1 1 +.names 722 723 4153 +1- 1 +-1 1 +.names 4153 4154 +1 1 +.names 2487 4154 4155 +11 1 +.names 4155 4156 +1 1 +.names 722 723 4157 +1- 1 +-1 1 +.names 4157 4158 +1 1 +.names 2491 4158 4159 +11 1 +.names 4159 4160 +1 1 +.names 56789 4160 4161 +1- 1 +-1 1 +.names 4161 4162 +1 1 +.names 4162 2520 4163 +1- 1 +-1 1 +.names 4163 4164 +1 1 +.names 4164 4156 56976 +1- 1 +-1 1 +.names 820 736 4166 +11 1 +.names 4166 4167 +1 1 +.names 821 736 4168 +11 1 +.names 4168 4169 +1 1 +.names 822 736 4170 +11 1 +.names 4170 4171 +1 1 +.names 2600 4172 +1 1 +.names 4172 616 4173 +11 1 +.names 4173 4174 +1 1 +.names 2585 4175 +1 1 +.names 617 4175 4176 +11 1 +.names 4176 4177 +1 1 +.names 4177 4174 4178 +1- 1 +-1 1 +.names 4178 4179 +1 1 +.names 725 4179 4180 +11 1 +.names 4180 4181 +1 1 +.names 823 4181 4182 +1- 1 +-1 1 +.names 4182 4183 +1 1 +.names 4183 736 4184 +11 1 +.names 4184 4185 +1 1 +.names 56981 2597 4186 +11 1 +.names 4186 4187 +1 1 +.names 11217 11220 56981 +11 1 +.names 4187 723 4189 +11 1 +.names 4189 4190 +1 1 +.names 2597 722 4191 +11 1 +.names 4191 4192 +1 1 +.names 56981 3971 4193 +11 1 +.names 4193 4194 +1 1 +.names 4194 723 4195 +11 1 +.names 4195 4196 +1 1 +.names 56981 2617 4197 +11 1 +.names 4197 4198 +1 1 +.names 4198 723 4199 +11 1 +.names 4199 4200 +1 1 +.names 2617 722 4201 +11 1 +.names 4201 4202 +1 1 +.names 2621 2599 4203 +1- 1 +-1 1 +.names 4203 4204 +1 1 +.names 4204 4202 4205 +1- 1 +-1 1 +.names 4205 4206 +1 1 +.names 4206 4200 4207 +1- 1 +-1 1 +.names 4207 4208 +1 1 +.names 4208 4196 4209 +1- 1 +-1 1 +.names 4209 4210 +1 1 +.names 4210 4192 4211 +1- 1 +-1 1 +.names 4211 4212 +1 1 +.names 4212 4190 56982 +1- 1 +-1 1 +.names 2679 4214 +1 1 +.names 766 736 4215 +11 1 +.names 4215 4216 +1 1 +.names 2679 4217 +1 1 +.names 765 736 4218 +11 1 +.names 4218 4219 +1 1 +.names 10030 4220 +0 1 +.names 4220 4221 +1 1 +.names 10400 4222 +0 1 +.names 4222 4223 +1 1 +.names 10420 4224 +0 1 +.names 4224 4225 +1 1 +.names 10412 4226 +0 1 +.names 4226 4227 +1 1 +.names 10398 4228 +0 1 +.names 4228 4229 +1 1 +.names 10426 4230 +0 1 +.names 4230 4231 +1 1 +.names 10388 4232 +0 1 +.names 4232 4233 +1 1 +.names 10376 4234 +0 1 +.names 4234 4235 +1 1 +.names 10416 4236 +0 1 +.names 4236 4237 +1 1 +.names 10548 4238 +0 1 +.names 4238 4239 +1 1 +.names 10390 4240 +0 1 +.names 4240 4241 +1 1 +.names 10570 4242 +0 1 +.names 4242 4243 +1 1 +.names 10404 4244 +0 1 +.names 4244 4245 +1 1 +.names 10428 4246 +0 1 +.names 4246 4247 +1 1 +.names 10410 4248 +0 1 +.names 4248 4249 +1 1 +.names 10583 4250 +0 1 +.names 4250 4251 +1 1 +.names 10378 4252 +0 1 +.names 4252 4253 +1 1 +.names 10396 4254 +0 1 +.names 4254 4255 +1 1 +.names 10430 4256 +0 1 +.names 4256 4257 +1 1 +.names 10572 4258 +0 1 +.names 4258 4259 +1 1 +.names 4221 4263 4260 +11 1 +.names 4260 4261 +1 1 +.names 10585 4262 +0 1 +.names 4262 4263 +1 1 +.names 4221 4267 4264 +11 1 +.names 4264 4265 +1 1 +.names 10587 4266 +0 1 +.names 4266 4267 +1 1 +.names 4221 4271 4268 +11 1 +.names 4268 4269 +1 1 +.names 10589 4270 +0 1 +.names 4270 4271 +1 1 +.names 4221 4275 4272 +11 1 +.names 4272 4273 +1 1 +.names 10591 4274 +0 1 +.names 4274 4275 +1 1 +.names 10424 4276 +0 1 +.names 4276 4277 +1 1 +.names 10568 4278 +0 1 +.names 4278 4279 +1 1 +.names 10593 4280 +0 1 +.names 4280 4281 +1 1 +.names 10595 4282 +0 1 +.names 4282 4283 +1 1 +.names 10562 4284 +0 1 +.names 4284 4285 +1 1 +.names 10597 4286 +0 1 +.names 4286 4287 +1 1 +.names 10599 4288 +0 1 +.names 4288 4289 +1 1 +.names 10406 4290 +0 1 +.names 4290 4291 +1 1 +.names 10574 4292 +0 1 +.names 4292 4293 +1 1 +.names 10414 4294 +0 1 +.names 4294 4295 +1 1 +.names 10552 4296 +0 1 +.names 4296 4297 +1 1 +.names 10394 4298 +0 1 +.names 4298 4299 +1 1 +.names 10566 4300 +0 1 +.names 4300 4301 +1 1 +.names 10386 4302 +0 1 +.names 4302 4303 +1 1 +.names 10601 4304 +0 1 +.names 4304 4305 +1 1 +.names 10603 4306 +0 1 +.names 4306 4307 +1 1 +.names 10560 4308 +0 1 +.names 4308 4309 +1 1 +.names 10605 4310 +0 1 +.names 4310 4311 +1 1 +.names 10607 4312 +0 1 +.names 4312 4313 +1 1 +.names 10609 4314 +0 1 +.names 4314 4315 +1 1 +.names 10580 4316 +0 1 +.names 4316 4317 +1 1 +.names 10611 4318 +0 1 +.names 4318 4319 +1 1 +.names 10613 4320 +0 1 +.names 4320 4321 +1 1 +.names 4221 4325 4322 +11 1 +.names 4322 4323 +1 1 +.names 10615 4324 +0 1 +.names 4324 4325 +1 1 +.names 10617 4326 +0 1 +.names 4326 4327 +1 1 +.names 10619 4328 +0 1 +.names 4328 4329 +1 1 +.names 4221 4333 4330 +11 1 +.names 4330 4331 +1 1 +.names 10621 4332 +0 1 +.names 4332 4333 +1 1 +.names 4221 4336 56986 +11 1 +.names 10623 4335 +0 1 +.names 4335 4336 +1 1 +.names 10625 4337 +0 1 +.names 4337 4338 +1 1 +.names 10627 4339 +0 1 +.names 4339 4340 +1 1 +.names 10629 4341 +0 1 +.names 4341 4342 +1 1 +.names 10631 4343 +0 1 +.names 4343 4344 +1 1 +.names 10633 4345 +0 1 +.names 4345 4346 +1 1 +.names 4221 4350 4347 +11 1 +.names 4347 4348 +1 1 +.names 10635 4349 +0 1 +.names 4349 4350 +1 1 +.names 10556 4351 +0 1 +.names 4351 4352 +1 1 +.names 10637 4353 +0 1 +.names 4353 4354 +1 1 +.names 10432 4355 +0 1 +.names 4355 4356 +1 1 +.names 10639 4357 +0 1 +.names 4357 4358 +1 1 +.names 4221 4362 4359 +11 1 +.names 4359 4360 +1 1 +.names 10641 4361 +0 1 +.names 4361 4362 +1 1 +.names 10564 4363 +0 1 +.names 4363 4364 +1 1 +.names 10643 4365 +0 1 +.names 4365 4366 +1 1 +.names 10645 4367 +0 1 +.names 4367 4368 +1 1 +.names 10647 4369 +0 1 +.names 4369 4370 +1 1 +.names 10649 4371 +0 1 +.names 4371 4372 +1 1 +.names 4221 4376 4373 +11 1 +.names 4373 4374 +1 1 +.names 10651 4375 +0 1 +.names 4375 4376 +1 1 +.names 10554 4377 +0 1 +.names 4377 4378 +1 1 +.names 10653 4379 +0 1 +.names 4379 4380 +1 1 +.names 10655 4381 +0 1 +.names 4381 4382 +1 1 +.names 10657 4383 +0 1 +.names 4383 4384 +1 1 +.names 4221 4387 56987 +11 1 +.names 10659 4386 +0 1 +.names 4386 4387 +1 1 +.names 10661 4388 +0 1 +.names 4388 4389 +1 1 +.names 10558 4390 +0 1 +.names 4390 4391 +1 1 +.names 10663 4392 +0 1 +.names 4392 4393 +1 1 +.names 10665 4394 +0 1 +.names 4394 4395 +1 1 +.names 10382 4396 +0 1 +.names 4396 4397 +1 1 +.names 10578 4398 +0 1 +.names 4398 4399 +1 1 +.names 10392 4400 +0 1 +.names 4400 4401 +1 1 +.names 10667 4402 +0 1 +.names 4402 4403 +1 1 +.names 4221 4407 4404 +11 1 +.names 4404 4405 +1 1 +.names 10402 4406 +0 1 +.names 4406 4407 +1 1 +.names 10550 4408 +0 1 +.names 4408 4409 +1 1 +.names 10669 4410 +0 1 +.names 4410 4411 +1 1 +.names 10671 4412 +0 1 +.names 4412 4413 +1 1 +.names 10422 4414 +0 1 +.names 4414 4415 +1 1 +.names 10673 4416 +0 1 +.names 4416 4417 +1 1 +.names 4221 4421 4418 +11 1 +.names 4418 4419 +1 1 +.names 10675 4420 +0 1 +.names 4420 4421 +1 1 +.names 10677 4422 +0 1 +.names 4422 4423 +1 1 +.names 10679 4424 +0 1 +.names 4424 4425 +1 1 +.names 10681 4426 +0 1 +.names 4426 4427 +1 1 +.names 10683 4428 +0 1 +.names 4428 4429 +1 1 +.names 10576 4430 +0 1 +.names 4430 4431 +1 1 +.names 4435 4437 4432 +1- 1 +-1 1 +.names 4432 4433 +1 1 +.names 9851 4434 +0 1 +.names 4434 4435 +1 1 +.names 9791 4436 +0 1 +.names 4436 4437 +1 1 +.names 4433 4441 4438 +1- 1 +-1 1 +.names 4438 4439 +1 1 +.names 9909 4440 +0 1 +.names 4440 4441 +1 1 +.names 4439 4445 4442 +1- 1 +-1 1 +.names 4442 4443 +1 1 +.names 9863 4444 +0 1 +.names 4444 4445 +1 1 +.names 4443 4449 4446 +1- 1 +-1 1 +.names 4446 4447 +1 1 +.names 9817 4448 +0 1 +.names 4448 4449 +1 1 +.names 4447 4453 4450 +1- 1 +-1 1 +.names 4450 4451 +1 1 +.names 9797 4452 +0 1 +.names 4452 4453 +1 1 +.names 4451 4457 4454 +1- 1 +-1 1 +.names 4454 4455 +1 1 +.names 9801 4456 +0 1 +.names 4456 4457 +1 1 +.names 4455 4461 4458 +1- 1 +-1 1 +.names 4458 4459 +1 1 +.names 9815 4460 +0 1 +.names 4460 4461 +1 1 +.names 4459 4465 4462 +1- 1 +-1 1 +.names 4462 4463 +1 1 +.names 9899 4464 +0 1 +.names 4464 4465 +1 1 +.names 4463 4469 4466 +1- 1 +-1 1 +.names 4466 4467 +1 1 +.names 9855 4468 +0 1 +.names 4468 4469 +1 1 +.names 4467 4473 4470 +1- 1 +-1 1 +.names 4470 4471 +1 1 +.names 10252 4472 +0 1 +.names 4472 4473 +1 1 +.names 4471 4477 4474 +1- 1 +-1 1 +.names 4474 4475 +1 1 +.names 9879 4476 +0 1 +.names 4476 4477 +1 1 +.names 4475 4481 4478 +1- 1 +-1 1 +.names 4478 4479 +1 1 +.names 9901 4480 +0 1 +.names 4480 4481 +1 1 +.names 4479 4485 4482 +1- 1 +-1 1 +.names 4482 4483 +1 1 +.names 10250 4484 +0 1 +.names 4484 4485 +1 1 +.names 4483 4489 4486 +1- 1 +-1 1 +.names 4486 4487 +1 1 +.names 10248 4488 +0 1 +.names 4488 4489 +1 1 +.names 4487 4493 4490 +1- 1 +-1 1 +.names 4490 4491 +1 1 +.names 10179 4492 +0 1 +.names 4492 4493 +1 1 +.names 4491 4497 4494 +1- 1 +-1 1 +.names 4494 4495 +1 1 +.names 10246 4496 +0 1 +.names 4496 4497 +1 1 +.names 4495 4501 4498 +1- 1 +-1 1 +.names 4498 4499 +1 1 +.names 9829 4500 +0 1 +.names 4500 4501 +1 1 +.names 4499 4505 4502 +1- 1 +-1 1 +.names 4502 4503 +1 1 +.names 9847 4504 +0 1 +.names 4504 4505 +1 1 +.names 4503 4509 4506 +1- 1 +-1 1 +.names 4506 4507 +1 1 +.names 10244 4508 +0 1 +.names 4508 4509 +1 1 +.names 4507 4513 4510 +1- 1 +-1 1 +.names 4510 4511 +1 1 +.names 10234 4512 +0 1 +.names 4512 4513 +1 1 +.names 4511 4517 4514 +1- 1 +-1 1 +.names 4514 4515 +1 1 +.names 10236 4516 +0 1 +.names 4516 4517 +1 1 +.names 4515 4521 4518 +1- 1 +-1 1 +.names 4518 4519 +1 1 +.names 10191 4520 +0 1 +.names 4520 4521 +1 1 +.names 4519 4525 4522 +1- 1 +-1 1 +.names 4522 4523 +1 1 +.names 10232 4524 +0 1 +.names 4524 4525 +1 1 +.names 4523 771 56988 +11 1 +.names 824 736 56989 +11 1 +.names 825 736 56991 +11 1 +.names 56993 56994 4529 +1- 1 +-1 1 +.names 4529 4530 +1 1 +.names 5287 771 56993 +11 1 +.names 5665 771 56994 +11 1 +.names 4530 4536 4533 +1- 1 +-1 1 +.names 4533 4534 +1 1 +.names 10207 4535 +0 1 +.names 4535 4536 +1 1 +.names 4534 4540 4537 +1- 1 +-1 1 +.names 4537 4538 +1 1 +.names 10322 4539 +0 1 +.names 4539 4540 +1 1 +.names 4538 4544 4541 +1- 1 +-1 1 +.names 4541 4542 +1 1 +.names 10320 4543 +0 1 +.names 4543 4544 +1 1 +.names 4542 4548 4545 +1- 1 +-1 1 +.names 4545 4546 +1 1 +.names 10318 4547 +0 1 +.names 4547 4548 +1 1 +.names 4546 4552 4549 +1- 1 +-1 1 +.names 4549 4550 +1 1 +.names 10316 4551 +0 1 +.names 4551 4552 +1 1 +.names 4550 4556 4553 +1- 1 +-1 1 +.names 4553 4554 +1 1 +.names 10314 4555 +0 1 +.names 4555 4556 +1 1 +.names 4554 4560 4557 +1- 1 +-1 1 +.names 4557 4558 +1 1 +.names 10312 4559 +0 1 +.names 4559 4560 +1 1 +.names 4558 4564 4561 +1- 1 +-1 1 +.names 4561 4562 +1 1 +.names 9895 4563 +0 1 +.names 4563 4564 +1 1 +.names 4562 4568 4565 +1- 1 +-1 1 +.names 4565 4566 +1 1 +.names 10187 4567 +0 1 +.names 4567 4568 +1 1 +.names 4566 4572 4569 +1- 1 +-1 1 +.names 4569 4570 +1 1 +.names 9809 4571 +0 1 +.names 4571 4572 +1 1 +.names 4570 4576 4573 +1- 1 +-1 1 +.names 4573 4574 +1 1 +.names 10310 4575 +0 1 +.names 4575 4576 +1 1 +.names 4574 4580 4577 +1- 1 +-1 1 +.names 4577 4578 +1 1 +.names 10308 4579 +0 1 +.names 4579 4580 +1 1 +.names 4578 4584 4581 +1- 1 +-1 1 +.names 4581 4582 +1 1 +.names 10177 4583 +0 1 +.names 4583 4584 +1 1 +.names 4582 4588 4585 +1- 1 +-1 1 +.names 4585 4586 +1 1 +.names 9861 4587 +0 1 +.names 4587 4588 +1 1 +.names 4586 4592 4589 +1- 1 +-1 1 +.names 4589 4590 +1 1 +.names 10306 4591 +0 1 +.names 4591 4592 +1 1 +.names 4590 4596 4593 +1- 1 +-1 1 +.names 4593 4594 +1 1 +.names 9849 4595 +0 1 +.names 4595 4596 +1 1 +.names 4594 4600 4597 +1- 1 +-1 1 +.names 4597 4598 +1 1 +.names 10209 4599 +0 1 +.names 4599 4600 +1 1 +.names 4598 4604 4601 +1- 1 +-1 1 +.names 4601 4602 +1 1 +.names 9805 4603 +0 1 +.names 4603 4604 +1 1 +.names 4602 4608 4605 +1- 1 +-1 1 +.names 4605 4606 +1 1 +.names 10276 4607 +0 1 +.names 4607 4608 +1 1 +.names 4606 4612 4609 +1- 1 +-1 1 +.names 4609 4610 +1 1 +.names 10189 4611 +0 1 +.names 4611 4612 +1 1 +.names 4610 4616 4613 +1- 1 +-1 1 +.names 4613 4614 +1 1 +.names 10193 4615 +0 1 +.names 4615 4616 +1 1 +.names 4614 56937 4617 +1- 1 +-1 1 +.names 4617 4618 +1 1 +.names 4618 56807 4619 +1- 1 +-1 1 +.names 4619 4620 +1 1 +.names 4620 56780 4621 +1- 1 +-1 1 +.names 4621 4622 +1 1 +.names 4622 56781 4623 +1- 1 +-1 1 +.names 4623 4624 +1 1 +.names 4624 56987 4625 +1- 1 +-1 1 +.names 4625 4626 +1 1 +.names 4626 56986 4627 +1- 1 +-1 1 +.names 4627 4628 +1 1 +.names 4628 4017 4629 +1- 1 +-1 1 +.names 4629 4630 +1 1 +.names 4630 56893 4631 +1- 1 +-1 1 +.names 4631 4632 +1 1 +.names 4632 56892 4633 +1- 1 +-1 1 +.names 4633 4634 +1 1 +.names 4634 56891 4635 +1- 1 +-1 1 +.names 4635 4636 +1 1 +.names 4636 56890 4637 +1- 1 +-1 1 +.names 4637 4638 +1 1 +.names 4638 56889 4639 +1- 1 +-1 1 +.names 4639 4640 +1 1 +.names 4640 56888 4641 +1- 1 +-1 1 +.names 4641 4642 +1 1 +.names 4642 56887 4643 +1- 1 +-1 1 +.names 4643 4644 +1 1 +.names 4644 56886 4645 +1- 1 +-1 1 +.names 4645 4646 +1 1 +.names 4646 56885 4647 +1- 1 +-1 1 +.names 4647 4648 +1 1 +.names 4648 56884 4649 +1- 1 +-1 1 +.names 4649 4650 +1 1 +.names 4650 56883 4651 +1- 1 +-1 1 +.names 4651 4652 +1 1 +.names 4652 56882 4653 +1- 1 +-1 1 +.names 4653 4654 +1 1 +.names 4654 56881 4655 +1- 1 +-1 1 +.names 4655 4656 +1 1 +.names 4656 56880 4657 +1- 1 +-1 1 +.names 4657 4658 +1 1 +.names 4658 56879 4659 +1- 1 +-1 1 +.names 4659 4660 +1 1 +.names 4660 56878 4661 +1- 1 +-1 1 +.names 4661 4662 +1 1 +.names 4662 56877 4663 +1- 1 +-1 1 +.names 4663 4664 +1 1 +.names 4664 56876 4665 +1- 1 +-1 1 +.names 4665 4666 +1 1 +.names 4666 56875 4667 +1- 1 +-1 1 +.names 4667 4668 +1 1 +.names 4668 56874 4669 +1- 1 +-1 1 +.names 4669 4670 +1 1 +.names 4670 4273 4671 +1- 1 +-1 1 +.names 4671 4672 +1 1 +.names 4672 4269 4673 +1- 1 +-1 1 +.names 4673 4674 +1 1 +.names 4674 4265 4675 +1- 1 +-1 1 +.names 4675 4676 +1 1 +.names 4676 4360 4677 +1- 1 +-1 1 +.names 4677 4678 +1 1 +.names 4678 4261 4679 +1- 1 +-1 1 +.names 4679 4680 +1 1 +.names 4680 4681 +0 1 +.names 4681 4682 +1 1 +.names 4685 4682 56995 +1- 1 +-1 1 +.names 5158 771 4684 +11 1 +.names 4684 4685 +1 1 +.names 4685 56988 4686 +1- 1 +-1 1 +.names 4686 4687 +1 1 +.names 4687 3955 4688 +1- 1 +-1 1 +.names 4688 4689 +1 1 +.names 4689 3971 4690 +1- 1 +-1 1 +.names 4690 4691 +1 1 +.names 4691 2621 4692 +1- 1 +-1 1 +.names 4692 4693 +1 1 +.names 4693 2617 4694 +1- 1 +-1 1 +.names 4694 4695 +1 1 +.names 4695 56958 4696 +1- 1 +-1 1 +.names 4696 4697 +1 1 +.names 4697 56959 4698 +1- 1 +-1 1 +.names 4698 4699 +1 1 +.names 4699 56960 4700 +1- 1 +-1 1 +.names 4700 4701 +1 1 +.names 4701 2513 4702 +1- 1 +-1 1 +.names 4702 4703 +1 1 +.names 4703 2495 4704 +1- 1 +-1 1 +.names 4704 4705 +1 1 +.names 4705 56789 4706 +1- 1 +-1 1 +.names 4706 4707 +1 1 +.names 4707 2491 4708 +1- 1 +-1 1 +.names 4708 4709 +1 1 +.names 4709 2520 4710 +1- 1 +-1 1 +.names 4710 4711 +1 1 +.names 4711 2487 4712 +1- 1 +-1 1 +.names 4712 4713 +1 1 +.names 4713 2566 4714 +1- 1 +-1 1 +.names 4714 4715 +1 1 +.names 4715 2564 4716 +1- 1 +-1 1 +.names 4716 4717 +1 1 +.names 4717 3985 4718 +1- 1 +-1 1 +.names 4718 4719 +1 1 +.names 4719 4007 4720 +1- 1 +-1 1 +.names 4720 4721 +1 1 +.names 4721 2574 4722 +1- 1 +-1 1 +.names 4722 4723 +1 1 +.names 4723 2572 4724 +1- 1 +-1 1 +.names 4724 4725 +1 1 +.names 4725 56961 4726 +1- 1 +-1 1 +.names 4726 4727 +1 1 +.names 4727 56931 4728 +1- 1 +-1 1 +.names 4728 4729 +1 1 +.names 4729 56932 4730 +1- 1 +-1 1 +.names 4730 4731 +1 1 +.names 4731 56933 4732 +1- 1 +-1 1 +.names 4732 4733 +1 1 +.names 4733 56934 4734 +1- 1 +-1 1 +.names 4734 4735 +1 1 +.names 4735 56935 4736 +1- 1 +-1 1 +.names 4736 4737 +1 1 +.names 4737 56936 4738 +1- 1 +-1 1 +.names 4738 4739 +1 1 +.names 4739 56819 4740 +1- 1 +-1 1 +.names 4740 4741 +1 1 +.names 4741 56820 4742 +1- 1 +-1 1 +.names 4742 4743 +1 1 +.names 4743 2482 4744 +1- 1 +-1 1 +.names 4744 4745 +1 1 +.names 4745 56782 4746 +1- 1 +-1 1 +.names 4746 4747 +1 1 +.names 4747 2476 4748 +1- 1 +-1 1 +.names 4748 4749 +1 1 +.names 4749 2468 4750 +1- 1 +-1 1 +.names 4750 4751 +1 1 +.names 4751 56962 4752 +1- 1 +-1 1 +.names 4752 4753 +1 1 +.names 4753 56941 4754 +1- 1 +-1 1 +.names 4754 4755 +1 1 +.names 4755 56942 4756 +1- 1 +-1 1 +.names 4756 4757 +1 1 +.names 4757 56943 4758 +1- 1 +-1 1 +.names 4758 4759 +1 1 +.names 4759 3852 4760 +1- 1 +-1 1 +.names 4760 4761 +1 1 +.names 4761 3856 4762 +1- 1 +-1 1 +.names 4762 4763 +1 1 +.names 4763 3860 4764 +1- 1 +-1 1 +.names 4764 4765 +1 1 +.names 4765 56944 4766 +1- 1 +-1 1 +.names 4766 4767 +1 1 +.names 4767 56945 4768 +1- 1 +-1 1 +.names 4768 4769 +1 1 +.names 4769 3870 4770 +1- 1 +-1 1 +.names 4770 4771 +1 1 +.names 4771 3874 4772 +1- 1 +-1 1 +.names 4772 4773 +1 1 +.names 4773 56946 4774 +1- 1 +-1 1 +.names 4774 4775 +1 1 +.names 4775 56947 4776 +1- 1 +-1 1 +.names 4776 4777 +1 1 +.names 4777 3884 4778 +1- 1 +-1 1 +.names 4778 4779 +1 1 +.names 4779 3888 4780 +1- 1 +-1 1 +.names 4780 4781 +1 1 +.names 4781 3892 4782 +1- 1 +-1 1 +.names 4782 4783 +1 1 +.names 4783 3896 4784 +1- 1 +-1 1 +.names 4784 4785 +1 1 +.names 4785 3900 4786 +1- 1 +-1 1 +.names 4786 4787 +1 1 +.names 4787 56872 56996 +1- 1 +-1 1 +.names 826 4789 +0 1 +.names 4789 4790 +1 1 +.names 4790 4685 4791 +1- 1 +-1 1 +.names 4791 4792 +1 1 +.names 828 829 4793 +11 1 +.names 4793 4794 +1 1 +.names 830 829 4795 +1- 1 +-1 1 +.names 4795 4796 +1 1 +.names 831 4796 4797 +11 1 +.names 4797 4798 +1 1 +.names 4798 4794 4799 +1- 1 +-1 1 +.names 4799 4800 +1 1 +.names 4800 733 56997 +11 1 +.names 2480 3787 4802 +1- 1 +-1 1 +.names 4802 4803 +1 1 +.names 4803 3803 4804 +1- 1 +-1 1 +.names 4804 4805 +1 1 +.names 4805 3827 4806 +1- 1 +-1 1 +.names 4806 4807 +1 1 +.names 4807 3842 4808 +1- 1 +-1 1 +.names 4808 4809 +1 1 +.names 4809 2482 4810 +1- 1 +-1 1 +.names 4810 4811 +1 1 +.names 4811 56782 4812 +1- 1 +-1 1 +.names 4812 4813 +1 1 +.names 4813 3860 4814 +1- 1 +-1 1 +.names 4814 4815 +1 1 +.names 4815 3874 4816 +1- 1 +-1 1 +.names 4816 4817 +1 1 +.names 4817 3892 4818 +1- 1 +-1 1 +.names 4818 4819 +1 1 +.names 4819 3900 57000 +1- 1 +-1 1 +.names 2472 2474 4821 +1- 1 +-1 1 +.names 4821 4822 +1 1 +.names 4822 3779 4823 +1- 1 +-1 1 +.names 4823 4824 +1 1 +.names 4824 3783 4825 +1- 1 +-1 1 +.names 4825 4826 +1 1 +.names 4826 3795 4827 +1- 1 +-1 1 +.names 4827 4828 +1 1 +.names 4828 3799 4829 +1- 1 +-1 1 +.names 4829 4830 +1 1 +.names 4830 3819 4831 +1- 1 +-1 1 +.names 4831 4832 +1 1 +.names 4832 3823 4833 +1- 1 +-1 1 +.names 4833 4834 +1 1 +.names 4834 3834 4835 +1- 1 +-1 1 +.names 4835 4836 +1 1 +.names 4836 3838 4837 +1- 1 +-1 1 +.names 4837 4838 +1 1 +.names 4838 2476 4839 +1- 1 +-1 1 +.names 4839 4840 +1 1 +.names 4840 3856 4841 +1- 1 +-1 1 +.names 4841 4842 +1 1 +.names 4842 3870 4843 +1- 1 +-1 1 +.names 4843 4844 +1 1 +.names 4844 3888 4845 +1- 1 +-1 1 +.names 4845 4846 +1 1 +.names 4846 3896 57003 +1- 1 +-1 1 +.names 769 4848 +0 1 +.names 4848 4849 +1 1 +.names 4419 56838 4850 +1- 1 +-1 1 +.names 4850 4851 +1 1 +.names 4851 56839 4852 +1- 1 +-1 1 +.names 4852 4853 +1 1 +.names 4853 2674 4854 +1- 1 +-1 1 +.names 4854 4855 +1 1 +.names 4855 2676 4856 +1- 1 +-1 1 +.names 4856 4857 +1 1 +.names 4857 56987 4858 +1- 1 +-1 1 +.names 4858 4859 +1 1 +.names 4859 56944 4860 +1- 1 +-1 1 +.names 4860 4861 +1 1 +.names 4861 56945 4862 +1- 1 +-1 1 +.names 4862 4863 +1 1 +.names 4863 56946 4864 +1- 1 +-1 1 +.names 4864 4865 +1 1 +.names 4865 56947 4866 +1- 1 +-1 1 +.names 4866 4867 +1 1 +.names 4867 56986 4868 +1- 1 +-1 1 +.names 4868 4869 +1 1 +.names 4869 56872 4870 +1- 1 +-1 1 +.names 4870 4871 +1 1 +.names 4871 56890 4872 +1- 1 +-1 1 +.names 4872 4873 +1 1 +.names 4873 56888 4874 +1- 1 +-1 1 +.names 4874 4875 +1 1 +.names 4875 56887 4876 +1- 1 +-1 1 +.names 4876 4877 +1 1 +.names 4877 56886 4878 +1- 1 +-1 1 +.names 4878 4879 +1 1 +.names 4879 56885 4880 +1- 1 +-1 1 +.names 4880 4881 +1 1 +.names 4881 56884 4882 +1- 1 +-1 1 +.names 4882 4883 +1 1 +.names 4883 56883 4884 +1- 1 +-1 1 +.names 4884 4885 +1 1 +.names 4885 56882 4886 +1- 1 +-1 1 +.names 4886 4887 +1 1 +.names 4887 56881 4888 +1- 1 +-1 1 +.names 4888 4889 +1 1 +.names 4889 56880 4890 +1- 1 +-1 1 +.names 4890 4891 +1 1 +.names 4891 56879 4892 +1- 1 +-1 1 +.names 4892 4893 +1 1 +.names 4893 56878 4894 +1- 1 +-1 1 +.names 4894 4895 +1 1 +.names 4895 56877 4896 +1- 1 +-1 1 +.names 4896 4897 +1 1 +.names 4897 56876 4898 +1- 1 +-1 1 +.names 4898 4899 +1 1 +.names 4899 56875 4900 +1- 1 +-1 1 +.names 4900 4901 +1 1 +.names 4901 56874 4902 +1- 1 +-1 1 +.names 4902 4903 +1 1 +.names 4903 3012 4904 +1- 1 +-1 1 +.names 4904 4905 +1 1 +.names 4905 56865 4906 +1- 1 +-1 1 +.names 4906 4907 +1 1 +.names 4907 56864 4908 +1- 1 +-1 1 +.names 4908 4909 +1 1 +.names 4909 56863 4910 +1- 1 +-1 1 +.names 4910 4911 +1 1 +.names 4911 56862 4912 +1- 1 +-1 1 +.names 4912 4913 +1 1 +.names 4913 56861 4914 +1- 1 +-1 1 +.names 4914 4915 +1 1 +.names 4915 56860 4916 +1- 1 +-1 1 +.names 4916 4917 +1 1 +.names 4917 56859 4918 +1- 1 +-1 1 +.names 4918 4919 +1 1 +.names 4919 56858 4920 +1- 1 +-1 1 +.names 4920 4921 +1 1 +.names 4921 56857 4922 +1- 1 +-1 1 +.names 4922 4923 +1 1 +.names 4923 56856 4924 +1- 1 +-1 1 +.names 4924 4925 +1 1 +.names 4925 56855 4926 +1- 1 +-1 1 +.names 4926 4927 +1 1 +.names 4927 56854 4928 +1- 1 +-1 1 +.names 4928 4929 +1 1 +.names 4929 56853 4930 +1- 1 +-1 1 +.names 4930 4931 +1 1 +.names 4931 771 4932 +11 1 +.names 4932 4933 +1 1 +.names 4933 4849 57004 +11 1 +.names 4938 4940 4935 +1- 1 +-1 1 +.names 4935 4936 +1 1 +.names 10300 4937 +0 1 +.names 4937 4938 +1 1 +.names 10298 4939 +0 1 +.names 4939 4940 +1 1 +.names 4936 4944 4941 +1- 1 +-1 1 +.names 4941 4942 +1 1 +.names 10296 4943 +0 1 +.names 4943 4944 +1 1 +.names 4942 4948 4945 +1- 1 +-1 1 +.names 4945 4946 +1 1 +.names 10294 4947 +0 1 +.names 4947 4948 +1 1 +.names 4946 4952 4949 +1- 1 +-1 1 +.names 4949 4950 +1 1 +.names 10292 4951 +0 1 +.names 4951 4952 +1 1 +.names 4950 57005 4953 +1- 1 +-1 1 +.names 4953 4954 +1 1 +.names 10290 57005 +0 1 +.names 4954 57006 4956 +1- 1 +-1 1 +.names 4956 4957 +1 1 +.names 10288 57006 +0 1 +.names 4957 57007 4959 +1- 1 +-1 1 +.names 4959 4960 +1 1 +.names 10286 57007 +0 1 +.names 4960 4965 4962 +1- 1 +-1 1 +.names 4962 4963 +1 1 +.names 10100 4964 +0 1 +.names 4964 4965 +1 1 +.names 4963 4969 4966 +1- 1 +-1 1 +.names 4966 4967 +1 1 +.names 9803 4968 +0 1 +.names 4968 4969 +1 1 +.names 4967 4973 4970 +1- 1 +-1 1 +.names 4970 4971 +1 1 +.names 10205 4972 +0 1 +.names 4972 4973 +1 1 +.names 4971 4977 4974 +1- 1 +-1 1 +.names 4974 4975 +1 1 +.names 9865 4976 +0 1 +.names 4976 4977 +1 1 +.names 4975 4981 4978 +1- 1 +-1 1 +.names 4978 4979 +1 1 +.names 10284 4980 +0 1 +.names 4980 4981 +1 1 +.names 4979 57008 4982 +1- 1 +-1 1 +.names 4982 4983 +1 1 +.names 10185 57008 +0 1 +.names 4983 57009 4985 +1- 1 +-1 1 +.names 4985 4986 +1 1 +.names 10280 57009 +0 1 +.names 4986 57010 4988 +1- 1 +-1 1 +.names 4988 4989 +1 1 +.names 10278 57010 +0 1 +.names 4989 4994 4991 +1- 1 +-1 1 +.names 4991 4992 +1 1 +.names 10274 4993 +0 1 +.names 4993 4994 +1 1 +.names 4992 4998 4995 +1- 1 +-1 1 +.names 4995 4996 +1 1 +.names 10272 4997 +0 1 +.names 4997 4998 +1 1 +.names 4996 5002 4999 +1- 1 +-1 1 +.names 4999 5000 +1 1 +.names 10270 5001 +0 1 +.names 5001 5002 +1 1 +.names 5000 5006 5003 +1- 1 +-1 1 +.names 5003 5004 +1 1 +.names 10268 5005 +0 1 +.names 5005 5006 +1 1 +.names 5004 5010 5007 +1- 1 +-1 1 +.names 5007 5008 +1 1 +.names 10266 5009 +0 1 +.names 5009 5010 +1 1 +.names 5008 5014 5011 +1- 1 +-1 1 +.names 5011 5012 +1 1 +.names 10264 5013 +0 1 +.names 5013 5014 +1 1 +.names 5012 5018 5015 +1- 1 +-1 1 +.names 5015 5016 +1 1 +.names 9807 5017 +0 1 +.names 5017 5018 +1 1 +.names 5016 5022 5019 +1- 1 +-1 1 +.names 5019 5020 +1 1 +.names 10167 5021 +0 1 +.names 5021 5022 +1 1 +.names 5020 5026 5023 +1- 1 +-1 1 +.names 5023 5024 +1 1 +.names 9841 5025 +0 1 +.names 5025 5026 +1 1 +.names 5024 5030 5027 +1- 1 +-1 1 +.names 5027 5028 +1 1 +.names 9907 5029 +0 1 +.names 5029 5030 +1 1 +.names 5028 5034 5031 +1- 1 +-1 1 +.names 5031 5032 +1 1 +.names 9867 5033 +0 1 +.names 5033 5034 +1 1 +.names 5032 5038 5035 +1- 1 +-1 1 +.names 5035 5036 +1 1 +.names 10220 5037 +0 1 +.names 5037 5038 +1 1 +.names 5036 5042 5039 +1- 1 +-1 1 +.names 5039 5040 +1 1 +.names 9887 5041 +0 1 +.names 5041 5042 +1 1 +.names 5040 5046 5043 +1- 1 +-1 1 +.names 5043 5044 +1 1 +.names 9789 5045 +0 1 +.names 5045 5046 +1 1 +.names 5044 5050 5047 +1- 1 +-1 1 +.names 5047 5048 +1 1 +.names 10132 5049 +0 1 +.names 5049 5050 +1 1 +.names 5048 5054 5051 +1- 1 +-1 1 +.names 5051 5052 +1 1 +.names 10130 5053 +0 1 +.names 5053 5054 +1 1 +.names 5052 5058 5055 +1- 1 +-1 1 +.names 5055 5056 +1 1 +.names 10128 5057 +0 1 +.names 5057 5058 +1 1 +.names 5056 5062 5059 +1- 1 +-1 1 +.names 5059 5060 +1 1 +.names 10126 5061 +0 1 +.names 5061 5062 +1 1 +.names 5060 5066 5063 +1- 1 +-1 1 +.names 5063 5064 +1 1 +.names 10211 5065 +0 1 +.names 5065 5066 +1 1 +.names 5064 5070 5067 +1- 1 +-1 1 +.names 5067 5068 +1 1 +.names 10124 5069 +0 1 +.names 5069 5070 +1 1 +.names 5068 5074 5071 +1- 1 +-1 1 +.names 5071 5072 +1 1 +.names 10122 5073 +0 1 +.names 5073 5074 +1 1 +.names 5072 5078 5075 +1- 1 +-1 1 +.names 5075 5076 +1 1 +.names 10120 5077 +0 1 +.names 5077 5078 +1 1 +.names 5076 5082 5079 +1- 1 +-1 1 +.names 5079 5080 +1 1 +.names 10118 5081 +0 1 +.names 5081 5082 +1 1 +.names 5080 5086 5083 +1- 1 +-1 1 +.names 5083 5084 +1 1 +.names 10116 5085 +0 1 +.names 5085 5086 +1 1 +.names 5084 5090 5087 +1- 1 +-1 1 +.names 5087 5088 +1 1 +.names 10114 5089 +0 1 +.names 5089 5090 +1 1 +.names 5088 5094 5091 +1- 1 +-1 1 +.names 5091 5092 +1 1 +.names 10112 5093 +0 1 +.names 5093 5094 +1 1 +.names 5092 5098 5095 +1- 1 +-1 1 +.names 5095 5096 +1 1 +.names 10110 5097 +0 1 +.names 5097 5098 +1 1 +.names 5096 5102 5099 +1- 1 +-1 1 +.names 5099 5100 +1 1 +.names 10108 5101 +0 1 +.names 5101 5102 +1 1 +.names 5100 5106 5103 +1- 1 +-1 1 +.names 5103 5104 +1 1 +.names 10106 5105 +0 1 +.names 5105 5106 +1 1 +.names 5104 5110 5107 +1- 1 +-1 1 +.names 5107 5108 +1 1 +.names 10090 5109 +0 1 +.names 5109 5110 +1 1 +.names 5108 5114 5111 +1- 1 +-1 1 +.names 5111 5112 +1 1 +.names 10094 5113 +0 1 +.names 5113 5114 +1 1 +.names 5112 5118 5115 +1- 1 +-1 1 +.names 5115 5116 +1 1 +.names 10092 5117 +0 1 +.names 5117 5118 +1 1 +.names 5116 5122 5119 +1- 1 +-1 1 +.names 5119 5120 +1 1 +.names 10082 5121 +0 1 +.names 5121 5122 +1 1 +.names 5120 5126 5123 +1- 1 +-1 1 +.names 5123 5124 +1 1 +.names 10080 5125 +0 1 +.names 5125 5126 +1 1 +.names 5124 5130 5127 +1- 1 +-1 1 +.names 5127 5128 +1 1 +.names 10078 5129 +0 1 +.names 5129 5130 +1 1 +.names 5128 5134 5131 +1- 1 +-1 1 +.names 5131 5132 +1 1 +.names 10076 5133 +0 1 +.names 5133 5134 +1 1 +.names 5132 5138 5135 +1- 1 +-1 1 +.names 5135 5136 +1 1 +.names 10074 5137 +0 1 +.names 5137 5138 +1 1 +.names 5136 5142 5139 +1- 1 +-1 1 +.names 5139 5140 +1 1 +.names 10072 5141 +0 1 +.names 5141 5142 +1 1 +.names 5140 5146 5143 +1- 1 +-1 1 +.names 5143 5144 +1 1 +.names 10070 5145 +0 1 +.names 5145 5146 +1 1 +.names 5144 4419 5147 +1- 1 +-1 1 +.names 5147 5148 +1 1 +.names 5148 4405 5149 +1- 1 +-1 1 +.names 5149 5150 +1 1 +.names 5150 4374 5151 +1- 1 +-1 1 +.names 5151 5152 +1 1 +.names 5152 4348 5153 +1- 1 +-1 1 +.names 5153 5154 +1 1 +.names 5154 4331 5155 +1- 1 +-1 1 +.names 5155 5156 +1 1 +.names 5156 4323 5157 +1- 1 +-1 1 +.names 5157 5158 +1 1 +.names 4360 771 57011 +11 1 +.names 4469 832 5160 +11 1 +.names 5160 5161 +1 1 +.names 5165 5167 5162 +1- 1 +-1 1 +.names 5162 5163 +1 1 +.names 9883 5164 +0 1 +.names 5164 5165 +1 1 +.names 9845 5166 +0 1 +.names 5166 5167 +1 1 +.names 5163 5171 5168 +1- 1 +-1 1 +.names 5168 5169 +1 1 +.names 9835 5170 +0 1 +.names 5170 5171 +1 1 +.names 5169 5175 5172 +1- 1 +-1 1 +.names 5172 5173 +1 1 +.names 10304 5174 +0 1 +.names 5174 5175 +1 1 +.names 5173 5179 5176 +1- 1 +-1 1 +.names 5176 5177 +1 1 +.names 10302 5178 +0 1 +.names 5178 5179 +1 1 +.names 5177 5183 5180 +1- 1 +-1 1 +.names 5180 5181 +1 1 +.names 10183 5182 +0 1 +.names 5182 5183 +1 1 +.names 5181 5187 5184 +1- 1 +-1 1 +.names 5184 5185 +1 1 +.names 9821 5186 +0 1 +.names 5186 5187 +1 1 +.names 5185 5191 5188 +1- 1 +-1 1 +.names 5188 5189 +1 1 +.names 9795 5190 +0 1 +.names 5190 5191 +1 1 +.names 5189 5195 5192 +1- 1 +-1 1 +.names 5192 5193 +1 1 +.names 10218 5194 +0 1 +.names 5194 5195 +1 1 +.names 5193 5199 5196 +1- 1 +-1 1 +.names 5196 5197 +1 1 +.names 9859 5198 +0 1 +.names 5198 5199 +1 1 +.names 5197 5203 5200 +1- 1 +-1 1 +.names 5200 5201 +1 1 +.names 9785 5202 +0 1 +.names 5202 5203 +1 1 +.names 5201 5207 5204 +1- 1 +-1 1 +.names 5204 5205 +1 1 +.names 10214 5206 +0 1 +.names 5206 5207 +1 1 +.names 5205 5211 5208 +1- 1 +-1 1 +.names 5208 5209 +1 1 +.names 9905 5210 +0 1 +.names 5210 5211 +1 1 +.names 5209 5215 5212 +1- 1 +-1 1 +.names 5212 5213 +1 1 +.names 10156 5214 +0 1 +.names 5214 5215 +1 1 +.names 5213 5219 5216 +1- 1 +-1 1 +.names 5216 5217 +1 1 +.names 10154 5218 +0 1 +.names 5218 5219 +1 1 +.names 5217 5223 5220 +1- 1 +-1 1 +.names 5220 5221 +1 1 +.names 10144 5222 +0 1 +.names 5222 5223 +1 1 +.names 5221 5227 5224 +1- 1 +-1 1 +.names 5224 5225 +1 1 +.names 10098 5226 +0 1 +.names 5226 5227 +1 1 +.names 5225 5231 5228 +1- 1 +-1 1 +.names 5228 5229 +1 1 +.names 10096 5230 +0 1 +.names 5230 5231 +1 1 +.names 5229 5235 5232 +1- 1 +-1 1 +.names 5232 5233 +1 1 +.names 10034 5234 +0 1 +.names 5234 5235 +1 1 +.names 5233 5239 5236 +1- 1 +-1 1 +.names 5236 5237 +1 1 +.names 9889 5238 +0 1 +.names 5238 5239 +1 1 +.names 5237 5243 5240 +1- 1 +-1 1 +.names 5240 5241 +1 1 +.names 9881 5242 +0 1 +.names 5242 5243 +1 1 +.names 5241 5247 5244 +1- 1 +-1 1 +.names 5244 5245 +1 1 +.names 10216 5246 +0 1 +.names 5246 5247 +1 1 +.names 5245 5251 5248 +1- 1 +-1 1 +.names 5248 5249 +1 1 +.names 9825 5250 +0 1 +.names 5250 5251 +1 1 +.names 5249 5255 5252 +1- 1 +-1 1 +.names 5252 5253 +1 1 +.names 10104 5254 +0 1 +.names 5254 5255 +1 1 +.names 5253 5259 5256 +1- 1 +-1 1 +.names 5256 5257 +1 1 +.names 10086 5258 +0 1 +.names 5258 5259 +1 1 +.names 5257 5263 5260 +1- 1 +-1 1 +.names 5260 5261 +1 1 +.names 10088 5262 +0 1 +.names 5262 5263 +1 1 +.names 5261 5267 5264 +1- 1 +-1 1 +.names 5264 5265 +1 1 +.names 10282 5266 +0 1 +.names 5266 5267 +1 1 +.names 5265 5271 5268 +1- 1 +-1 1 +.names 5268 5269 +1 1 +.names 9833 5270 +0 1 +.names 5270 5271 +1 1 +.names 5269 5275 5272 +1- 1 +-1 1 +.names 5272 5273 +1 1 +.names 10134 5274 +0 1 +.names 5274 5275 +1 1 +.names 5273 5279 5276 +1- 1 +-1 1 +.names 5276 5277 +1 1 +.names 9831 5278 +0 1 +.names 5278 5279 +1 1 +.names 5277 5283 5280 +1- 1 +-1 1 +.names 5280 5281 +1 1 +.names 10146 5282 +0 1 +.names 5282 5283 +1 1 +.names 5281 5161 5284 +1- 1 +-1 1 +.names 5284 5285 +1 1 +.names 5285 5289 5286 +1- 1 +-1 1 +.names 5286 5287 +1 1 +.names 6739 6743 5288 +1- 1 +-1 1 +.names 5288 5289 +1 1 +.names 833 736 56559 +11 1 +.names 834 736 56560 +11 1 +.names 835 736 56561 +11 1 +.names 836 736 56562 +11 1 +.names 2674 722 57015 +11 1 +.names 2676 722 57016 +11 1 +.names 837 736 56457 +11 1 +.names 838 736 56458 +11 1 +.names 839 736 56459 +11 1 +.names 840 736 56460 +11 1 +.names 56592 56591 5300 +11 1 +.names 5300 5301 +1 1 +.names 6857 56592 +0 1 +.names 6861 56591 +0 1 +.names 841 5304 +0 1 +.names 5304 5305 +1 1 +.names 5305 5301 5306 +1- 1 +-1 1 +.names 5306 5307 +1 1 +.names 56912 5307 57018 +11 1 +.names 842 736 57019 +11 1 +.names 56945 56839 5310 +1- 1 +-1 1 +.names 5310 5311 +1 1 +.names 5311 56944 5312 +1- 1 +-1 1 +.names 5312 5313 +1 1 +.names 5313 56838 5314 +1- 1 +-1 1 +.names 5314 5315 +1 1 +.names 56942 56943 5316 +1- 1 +-1 1 +.names 5316 5317 +1 1 +.names 5317 56941 5318 +1- 1 +-1 1 +.names 5318 5319 +1 1 +.names 5319 3904 5320 +1- 1 +-1 1 +.names 5320 5321 +1 1 +.names 5321 5315 57021 +1- 1 +-1 1 +.names 3904 771 57023 +11 1 +.names 844 736 5324 +11 1 +.names 5324 5325 +1 1 +.names 845 736 5326 +11 1 +.names 5326 5327 +1 1 +.names 5327 841 56732 +11 1 +.names 846 736 5329 +11 1 +.names 5329 5330 +1 1 +.names 5330 841 56733 +11 1 +.names 847 736 5332 +11 1 +.names 5332 5333 +1 1 +.names 5333 848 57025 +11 1 +.names 56942 56943 5335 +1- 1 +-1 1 +.names 5335 5336 +1 1 +.names 5336 56941 57027 +1- 1 +-1 1 +.names 56419 56457 5338 +1- 1 +-1 1 +.names 5338 5339 +1 1 +.names 5339 56459 5340 +1- 1 +-1 1 +.names 5340 5341 +1 1 +.names 5341 56559 5342 +1- 1 +-1 1 +.names 5342 5343 +1 1 +.names 5343 56561 57029 +1- 1 +-1 1 +.names 3658 5345 +1 1 +.names 725 5345 5346 +11 1 +.names 5346 5347 +1 1 +.names 850 851 5348 +1- 1 +-1 1 +.names 5348 5349 +1 1 +.names 5349 5353 5350 +11 1 +.names 5350 5351 +1 1 +.names 365 5367 5352 +11 1 +.names 5352 5353 +1 1 +.names 852 853 5354 +1- 1 +-1 1 +.names 5354 5355 +1 1 +.names 5355 5359 5356 +11 1 +.names 5356 5357 +1 1 +.names 365 364 5358 +11 1 +.names 5358 5359 +1 1 +.names 854 5353 5360 +11 1 +.names 5360 5361 +1 1 +.names 855 5359 5362 +11 1 +.names 5362 5363 +1 1 +.names 852 855 5364 +1- 1 +-1 1 +.names 5364 5365 +1 1 +.names 364 5366 +0 1 +.names 5366 5367 +1 1 +.names 3658 5368 +1 1 +.names 856 5368 5369 +11 1 +.names 5369 5370 +1 1 +.names 857 809 5371 +1- 1 +-1 1 +.names 5371 5372 +1 1 +.names 5372 3133 5373 +1- 1 +-1 1 +.names 5373 5374 +1 1 +.names 3658 5375 +1 1 +.names 56696 56695 5376 +11 1 +.names 5376 5377 +1 1 +.names 42524 42528 56696 +1- 1 +-1 1 +.names 42516 42520 56695 +1- 1 +-1 1 +.names 858 5377 5380 +1- 1 +-1 1 +.names 5380 5381 +1 1 +.names 5381 5375 5382 +11 1 +.names 5382 5383 +1 1 +.names 859 809 5384 +1- 1 +-1 1 +.names 5384 5385 +1 1 +.names 3658 5386 +1 1 +.names 56697 860 5387 +01 1 +10 1 +.names 5387 5388 +1 1 +.names 42532 42536 56697 +1- 1 +-1 1 +.names 5388 5386 5390 +11 1 +.names 5390 5391 +1 1 +.names 3658 5392 +1 1 +.names 861 5392 5393 +11 1 +.names 5393 5394 +1 1 +.names 2472 2476 5395 +1- 1 +-1 1 +.names 5395 5396 +1 1 +.names 5396 3783 5397 +1- 1 +-1 1 +.names 5397 5398 +1 1 +.names 5398 3799 5399 +1- 1 +-1 1 +.names 5399 5400 +1 1 +.names 5400 3823 5401 +1- 1 +-1 1 +.names 5401 5402 +1 1 +.names 5402 3838 5403 +1- 1 +-1 1 +.names 5403 5404 +1 1 +.names 5404 3856 5405 +1- 1 +-1 1 +.names 5405 5406 +1 1 +.names 5406 3870 5407 +1- 1 +-1 1 +.names 5407 5408 +1 1 +.names 5408 3888 5409 +1- 1 +-1 1 +.names 5409 5410 +1 1 +.names 5410 3896 5411 +1- 1 +-1 1 +.names 5411 5412 +1 1 +.names 5412 2474 5413 +1- 1 +-1 1 +.names 5413 5414 +1 1 +.names 5414 3779 5415 +1- 1 +-1 1 +.names 5415 5416 +1 1 +.names 5416 3795 5417 +1- 1 +-1 1 +.names 5417 5418 +1 1 +.names 5418 3819 5419 +1- 1 +-1 1 +.names 5419 5420 +1 1 +.names 5420 3834 57033 +1- 1 +-1 1 +.names 2480 2482 5422 +1- 1 +-1 1 +.names 5422 5423 +1 1 +.names 5423 56782 5424 +1- 1 +-1 1 +.names 5424 5425 +1 1 +.names 5425 3787 5426 +1- 1 +-1 1 +.names 5426 5427 +1 1 +.names 5427 3803 5428 +1- 1 +-1 1 +.names 5428 5429 +1 1 +.names 5429 3827 5430 +1- 1 +-1 1 +.names 5430 5431 +1 1 +.names 5431 3842 5432 +1- 1 +-1 1 +.names 5432 5433 +1 1 +.names 5433 3860 5434 +1- 1 +-1 1 +.names 5434 5435 +1 1 +.names 5435 3874 5436 +1- 1 +-1 1 +.names 5436 5437 +1 1 +.names 5437 3892 5438 +1- 1 +-1 1 +.names 5438 5439 +1 1 +.names 5439 3900 57034 +1- 1 +-1 1 +.names 2480 2472 5441 +1- 1 +-1 1 +.names 5441 5442 +1 1 +.names 5442 2474 5443 +1- 1 +-1 1 +.names 5443 5444 +1 1 +.names 5444 2464 5445 +1- 1 +-1 1 +.names 5445 5446 +1 1 +.names 5446 2466 5447 +1- 1 +-1 1 +.names 5447 5448 +1 1 +.names 5448 3771 5449 +1- 1 +-1 1 +.names 5449 5450 +1 1 +.names 5450 3775 5451 +1- 1 +-1 1 +.names 5451 5452 +1 1 +.names 5452 3779 5453 +1- 1 +-1 1 +.names 5453 5454 +1 1 +.names 5454 3783 5455 +1- 1 +-1 1 +.names 5455 5456 +1 1 +.names 5456 3787 5457 +1- 1 +-1 1 +.names 5457 5458 +1 1 +.names 5458 3795 5459 +1- 1 +-1 1 +.names 5459 5460 +1 1 +.names 5460 3799 5461 +1- 1 +-1 1 +.names 5461 5462 +1 1 +.names 5462 3803 5463 +1- 1 +-1 1 +.names 5463 5464 +1 1 +.names 5464 3811 5465 +1- 1 +-1 1 +.names 5465 5466 +1 1 +.names 5466 3815 5467 +1- 1 +-1 1 +.names 5467 5468 +1 1 +.names 5468 3819 5469 +1- 1 +-1 1 +.names 5469 5470 +1 1 +.names 5470 3823 5471 +1- 1 +-1 1 +.names 5471 5472 +1 1 +.names 5472 3827 5473 +1- 1 +-1 1 +.names 5473 5474 +1 1 +.names 5474 3834 5475 +1- 1 +-1 1 +.names 5475 5476 +1 1 +.names 5476 3838 5477 +1- 1 +-1 1 +.names 5477 5478 +1 1 +.names 5478 3842 57035 +1- 1 +-1 1 +.names 2482 56782 5480 +1- 1 +-1 1 +.names 5480 5481 +1 1 +.names 5481 2476 5482 +1- 1 +-1 1 +.names 5482 5483 +1 1 +.names 5483 2468 5484 +1- 1 +-1 1 +.names 5484 5485 +1 1 +.names 5485 3852 5486 +1- 1 +-1 1 +.names 5486 5487 +1 1 +.names 5487 3856 5488 +1- 1 +-1 1 +.names 5488 5489 +1 1 +.names 5489 3860 5490 +1- 1 +-1 1 +.names 5490 5491 +1 1 +.names 5491 3870 5492 +1- 1 +-1 1 +.names 5492 5493 +1 1 +.names 5493 3874 5494 +1- 1 +-1 1 +.names 5494 5495 +1 1 +.names 5495 3884 5496 +1- 1 +-1 1 +.names 5496 5497 +1 1 +.names 5497 3888 5498 +1- 1 +-1 1 +.names 5498 5499 +1 1 +.names 5499 3892 5500 +1- 1 +-1 1 +.names 5500 5501 +1 1 +.names 5501 3896 5502 +1- 1 +-1 1 +.names 5502 5503 +1 1 +.names 5503 3900 57036 +1- 1 +-1 1 +.names 3811 3815 5505 +1- 1 +-1 1 +.names 5505 5506 +1 1 +.names 5506 3819 5507 +1- 1 +-1 1 +.names 5507 5508 +1 1 +.names 5508 3823 5509 +1- 1 +-1 1 +.names 5509 5510 +1 1 +.names 5510 3827 5511 +1- 1 +-1 1 +.names 5511 5512 +1 1 +.names 5512 3834 5513 +1- 1 +-1 1 +.names 5513 5514 +1 1 +.names 5514 3838 5515 +1- 1 +-1 1 +.names 5515 5516 +1 1 +.names 5516 3842 5517 +1- 1 +-1 1 +.names 5517 5518 +1 1 +.names 5518 3884 5519 +1- 1 +-1 1 +.names 5519 5520 +1 1 +.names 5520 3888 5521 +1- 1 +-1 1 +.names 5521 5522 +1 1 +.names 5522 3892 5523 +1- 1 +-1 1 +.names 5523 5524 +1 1 +.names 5524 3896 5525 +1- 1 +-1 1 +.names 5525 5526 +1 1 +.names 5526 3900 57037 +1- 1 +-1 1 +.names 2474 2466 5528 +1- 1 +-1 1 +.names 5528 5529 +1 1 +.names 5529 3771 5530 +1- 1 +-1 1 +.names 5530 5531 +1 1 +.names 5531 3779 5532 +1- 1 +-1 1 +.names 5532 5533 +1 1 +.names 5533 3795 5534 +1- 1 +-1 1 +.names 5534 5535 +1 1 +.names 5535 3811 5536 +1- 1 +-1 1 +.names 5536 5537 +1 1 +.names 5537 3819 5538 +1- 1 +-1 1 +.names 5538 5539 +1 1 +.names 5539 3834 5540 +1- 1 +-1 1 +.names 5540 5541 +1 1 +.names 5541 57038 +0 1 +.names 3795 3799 5543 +1- 1 +-1 1 +.names 5543 5544 +1 1 +.names 5544 3803 5545 +1- 1 +-1 1 +.names 5545 5546 +1 1 +.names 5546 3834 5547 +1- 1 +-1 1 +.names 5547 5548 +1 1 +.names 5548 3838 5549 +1- 1 +-1 1 +.names 5549 5550 +1 1 +.names 5550 3842 5551 +1- 1 +-1 1 +.names 5551 5552 +1 1 +.names 5552 3870 5553 +1- 1 +-1 1 +.names 5553 5554 +1 1 +.names 5554 3874 5555 +1- 1 +-1 1 +.names 5555 5556 +1 1 +.names 5556 3896 5557 +1- 1 +-1 1 +.names 5557 5558 +1 1 +.names 5558 3900 57039 +1- 1 +-1 1 +.names 2679 5560 +1 1 +.names 862 863 5561 +1- 1 +-1 1 +.names 5561 5562 +1 1 +.names 5562 864 5563 +1- 1 +-1 1 +.names 5563 5564 +1 1 +.names 5564 865 5565 +1- 1 +-1 1 +.names 5565 5566 +1 1 +.names 5566 866 5567 +1- 1 +-1 1 +.names 5567 5568 +1 1 +.names 5568 867 5569 +1- 1 +-1 1 +.names 5569 5570 +1 1 +.names 5570 2920 5571 +1- 1 +-1 1 +.names 5571 5572 +1 1 +.names 5572 736 5573 +11 1 +.names 5573 5574 +1 1 +.names 5574 5560 5575 +11 1 +.names 5575 5576 +1 1 +.names 2679 5577 +1 1 +.names 868 869 5578 +1- 1 +-1 1 +.names 5578 5579 +1 1 +.names 5579 870 5580 +1- 1 +-1 1 +.names 5580 5581 +1 1 +.names 5581 871 5582 +1- 1 +-1 1 +.names 5582 5583 +1 1 +.names 5583 736 5584 +11 1 +.names 5584 5585 +1 1 +.names 5585 5577 5586 +11 1 +.names 5586 5587 +1 1 +.names 2679 5588 +1 1 +.names 872 873 5589 +1- 1 +-1 1 +.names 5589 5590 +1 1 +.names 5590 874 5591 +1- 1 +-1 1 +.names 5591 5592 +1 1 +.names 5592 875 5593 +1- 1 +-1 1 +.names 5593 5594 +1 1 +.names 5594 736 5595 +11 1 +.names 5595 5596 +1 1 +.names 5596 5588 5597 +11 1 +.names 5597 5598 +1 1 +.names 2679 5599 +1 1 +.names 876 877 5600 +1- 1 +-1 1 +.names 5600 5601 +1 1 +.names 5601 878 5602 +1- 1 +-1 1 +.names 5602 5603 +1 1 +.names 5603 879 5604 +1- 1 +-1 1 +.names 5604 5605 +1 1 +.names 5605 736 5606 +11 1 +.names 5606 5607 +1 1 +.names 5607 5599 5608 +11 1 +.names 5608 5609 +1 1 +.names 2679 5610 +1 1 +.names 880 881 5611 +1- 1 +-1 1 +.names 5611 5612 +1 1 +.names 5612 882 5613 +1- 1 +-1 1 +.names 5613 5614 +1 1 +.names 5614 872 5615 +1- 1 +-1 1 +.names 5615 5616 +1 1 +.names 5616 873 5617 +1- 1 +-1 1 +.names 5617 5618 +1 1 +.names 5618 869 5619 +1- 1 +-1 1 +.names 5619 5620 +1 1 +.names 5620 871 5621 +1- 1 +-1 1 +.names 5621 5622 +1 1 +.names 5622 883 5623 +1- 1 +-1 1 +.names 5623 5624 +1 1 +.names 5624 736 5625 +11 1 +.names 5625 5626 +1 1 +.names 5626 5610 5627 +11 1 +.names 5627 5628 +1 1 +.names 5022 5026 5629 +1- 1 +-1 1 +.names 5629 5630 +1 1 +.names 5630 5030 5631 +1- 1 +-1 1 +.names 5631 5632 +1 1 +.names 5632 5034 5633 +1- 1 +-1 1 +.names 5633 5634 +1 1 +.names 5634 5038 5635 +1- 1 +-1 1 +.names 5635 5636 +1 1 +.names 5636 5042 5637 +1- 1 +-1 1 +.names 5637 5638 +1 1 +.names 5638 4419 5639 +1- 1 +-1 1 +.names 5639 5640 +1 1 +.names 5640 4405 5641 +1- 1 +-1 1 +.names 5641 5642 +1 1 +.names 5642 4374 5643 +1- 1 +-1 1 +.names 5643 5644 +1 1 +.names 5644 4348 57041 +1- 1 +-1 1 +.names 884 736 5646 +11 1 +.names 5646 5647 +1 1 +.names 5647 769 57042 +11 1 +.names 885 736 57044 +11 1 +.names 2584 5650 +1 1 +.names 886 57068 5651 +11 1 +.names 5651 5652 +1 1 +.names 5658 736 57068 +11 1 +.names 5652 5650 57069 +11 1 +.names 887 2902 5655 +1- 1 +-1 1 +.names 5655 5656 +1 1 +.names 5656 2896 5657 +1- 1 +-1 1 +.names 5657 5658 +1 1 +.names 56872 722 5659 +11 1 +.names 5659 5660 +1 1 +.names 3008 722 5661 +11 1 +.names 5661 5662 +1 1 +.names 5662 5660 57071 +1- 1 +-1 1 +.names 4221 6707 5664 +11 1 +.names 5664 5665 +1 1 +.names 888 5666 +0 1 +.names 889 5667 +0 1 +.names 5667 5668 +1 1 +.names 5668 890 5669 +11 1 +.names 5669 5670 +1 1 +.names 5666 5671 +1 1 +.names 5671 5670 57074 +1- 1 +-1 1 +.names 37 5673 +0 1 +.names 5673 5674 +1 1 +.names 38 5675 +0 1 +.names 5675 5676 +1 1 +.names 39 5677 +0 1 +.names 5677 5678 +1 1 +.names 40 5679 +0 1 +.names 5679 5680 +1 1 +.names 41 5681 +0 1 +.names 5681 5682 +1 1 +.names 42 5683 +0 1 +.names 5683 5684 +1 1 +.names 43 5685 +0 1 +.names 5685 5686 +1 1 +.names 44 5687 +0 1 +.names 5687 5688 +1 1 +.names 45 5689 +0 1 +.names 5689 5690 +1 1 +.names 46 5691 +0 1 +.names 5691 5692 +1 1 +.names 47 5693 +0 1 +.names 5693 5694 +1 1 +.names 48 5695 +0 1 +.names 5695 5696 +1 1 +.names 49 5697 +0 1 +.names 5697 5698 +1 1 +.names 50 5699 +0 1 +.names 5699 5700 +1 1 +.names 51 5701 +0 1 +.names 5701 5702 +1 1 +.names 52 5703 +0 1 +.names 5703 5704 +1 1 +.names 53 5705 +0 1 +.names 5705 5706 +1 1 +.names 54 5707 +0 1 +.names 5707 5708 +1 1 +.names 55 5709 +0 1 +.names 5709 5710 +1 1 +.names 56 5711 +0 1 +.names 5711 5712 +1 1 +.names 57 5713 +0 1 +.names 5713 5714 +1 1 +.names 58 5715 +0 1 +.names 5715 5716 +1 1 +.names 59 5717 +0 1 +.names 5717 5718 +1 1 +.names 60 5719 +0 1 +.names 5719 5720 +1 1 +.names 61 5721 +0 1 +.names 5721 5722 +1 1 +.names 62 5723 +0 1 +.names 5723 5724 +1 1 +.names 63 5725 +0 1 +.names 5725 5726 +1 1 +.names 64 5727 +0 1 +.names 5727 5728 +1 1 +.names 65 5729 +0 1 +.names 5729 5730 +1 1 +.names 66 5731 +0 1 +.names 5731 5732 +1 1 +.names 67 5733 +0 1 +.names 5733 5734 +1 1 +.names 68 5735 +0 1 +.names 5735 5736 +1 1 +.names 72 5737 +0 1 +.names 5737 5738 +1 1 +.names 5738 71 5739 +11 1 +.names 5739 5740 +1 1 +.names 5740 70 5741 +11 1 +.names 5741 5742 +1 1 +.names 5742 69 5743 +11 1 +.names 5743 5744 +1 1 +.names 69 5745 +0 1 +.names 5745 5746 +1 1 +.names 5737 5747 +1 1 +.names 5747 71 5748 +11 1 +.names 5748 5749 +1 1 +.names 5749 70 5750 +11 1 +.names 5750 5751 +1 1 +.names 5751 5746 5752 +11 1 +.names 5752 5753 +1 1 +.names 71 5754 +0 1 +.names 5754 5755 +1 1 +.names 72 5755 5756 +11 1 +.names 5756 5757 +1 1 +.names 5757 70 5758 +11 1 +.names 5758 5759 +1 1 +.names 5759 69 5760 +11 1 +.names 5760 5761 +1 1 +.names 5745 5762 +1 1 +.names 5754 5763 +1 1 +.names 72 5763 5764 +11 1 +.names 5764 5765 +1 1 +.names 5765 70 5766 +11 1 +.names 5766 5767 +1 1 +.names 5767 5762 5768 +11 1 +.names 5768 5769 +1 1 +.names 5769 3133 5770 +1- 1 +-1 1 +.names 5770 5771 +1 1 +.names 2591 5772 +1 1 +.names 891 5772 5773 +11 1 +.names 5773 5774 +1 1 +.names 70 5775 +0 1 +.names 5775 5776 +1 1 +.names 5754 5777 +1 1 +.names 72 5777 5778 +11 1 +.names 5778 5779 +1 1 +.names 5779 5776 5780 +11 1 +.names 5780 5781 +1 1 +.names 5781 69 5782 +11 1 +.names 5782 5783 +1 1 +.names 5783 5774 5784 +1- 1 +-1 1 +.names 5784 5785 +1 1 +.names 892 5786 +0 1 +.names 56594 5787 +0 1 +.names 5787 5788 +1 1 +.names 6849 56594 +0 1 +.names 56599 56563 5790 +01 1 +10 1 +.names 5790 5791 +1 1 +.names 7292 56599 +0 1 +.names 6973 56563 +0 1 +.names 56600 56564 5794 +01 1 +10 1 +.names 5794 5795 +1 1 +.names 7288 56600 +0 1 +.names 6969 56564 +0 1 +.names 56601 56565 5798 +01 1 +10 1 +.names 5798 5799 +1 1 +.names 7284 56601 +0 1 +.names 6965 56565 +0 1 +.names 56602 56566 5802 +01 1 +10 1 +.names 5802 5803 +1 1 +.names 7280 56602 +0 1 +.names 6961 56566 +0 1 +.names 56603 56567 5806 +01 1 +10 1 +.names 5806 5807 +1 1 +.names 7276 56603 +0 1 +.names 6957 56567 +0 1 +.names 56604 56568 5810 +01 1 +10 1 +.names 5810 5811 +1 1 +.names 7272 56604 +0 1 +.names 6953 56568 +0 1 +.names 56605 56569 5814 +01 1 +10 1 +.names 5814 5815 +1 1 +.names 7268 56605 +0 1 +.names 6949 56569 +0 1 +.names 56606 56570 5818 +01 1 +10 1 +.names 5818 5819 +1 1 +.names 7264 56606 +0 1 +.names 6945 56570 +0 1 +.names 56607 56571 5822 +01 1 +10 1 +.names 5822 5823 +1 1 +.names 7260 56607 +0 1 +.names 6941 56571 +0 1 +.names 56608 56572 5826 +01 1 +10 1 +.names 5826 5827 +1 1 +.names 7256 56608 +0 1 +.names 6937 56572 +0 1 +.names 56609 56573 5830 +01 1 +10 1 +.names 5830 5831 +1 1 +.names 7252 56609 +0 1 +.names 6933 56573 +0 1 +.names 56610 56574 5834 +01 1 +10 1 +.names 5834 5835 +1 1 +.names 7248 56610 +0 1 +.names 6929 56574 +0 1 +.names 56611 56575 5838 +01 1 +10 1 +.names 5838 5839 +1 1 +.names 7244 56611 +0 1 +.names 6925 56575 +0 1 +.names 56612 56576 5842 +01 1 +10 1 +.names 5842 5843 +1 1 +.names 7240 56612 +0 1 +.names 6921 56576 +0 1 +.names 56613 56577 5846 +01 1 +10 1 +.names 5846 5847 +1 1 +.names 7236 56613 +0 1 +.names 6917 56577 +0 1 +.names 56614 56578 5850 +01 1 +10 1 +.names 5850 5851 +1 1 +.names 7232 56614 +0 1 +.names 6913 56578 +0 1 +.names 56615 56579 5854 +01 1 +10 1 +.names 5854 5855 +1 1 +.names 7228 56615 +0 1 +.names 6909 56579 +0 1 +.names 56616 56580 5858 +01 1 +10 1 +.names 5858 5859 +1 1 +.names 7224 56616 +0 1 +.names 6905 56580 +0 1 +.names 56617 56581 5862 +01 1 +10 1 +.names 5862 5863 +1 1 +.names 7220 56617 +0 1 +.names 6901 56581 +0 1 +.names 56618 56582 5866 +01 1 +10 1 +.names 5866 5867 +1 1 +.names 7216 56618 +0 1 +.names 6897 56582 +0 1 +.names 56619 56583 5870 +01 1 +10 1 +.names 5870 5871 +1 1 +.names 7212 56619 +0 1 +.names 6893 56583 +0 1 +.names 56620 56584 5874 +01 1 +10 1 +.names 5874 5875 +1 1 +.names 7208 56620 +0 1 +.names 6889 56584 +0 1 +.names 56621 56585 5878 +01 1 +10 1 +.names 5878 5879 +1 1 +.names 7204 56621 +0 1 +.names 6885 56585 +0 1 +.names 56622 56586 5882 +01 1 +10 1 +.names 5882 5883 +1 1 +.names 7200 56622 +0 1 +.names 6881 56586 +0 1 +.names 56623 56587 5886 +01 1 +10 1 +.names 5886 5887 +1 1 +.names 7196 56623 +0 1 +.names 6877 56587 +0 1 +.names 56624 56588 5890 +01 1 +10 1 +.names 5890 5891 +1 1 +.names 7192 56624 +0 1 +.names 6873 56588 +0 1 +.names 56625 56589 5894 +01 1 +10 1 +.names 5894 5895 +1 1 +.names 7188 56625 +0 1 +.names 6869 56589 +0 1 +.names 56626 56590 5898 +01 1 +10 1 +.names 5898 5899 +1 1 +.names 7184 56626 +0 1 +.names 6865 56590 +0 1 +.names 56627 56591 5902 +01 1 +10 1 +.names 5902 5903 +1 1 +.names 7180 56627 +0 1 +.names 56628 56592 5905 +01 1 +10 1 +.names 5905 5906 +1 1 +.names 7176 56628 +0 1 +.names 56629 56593 5908 +01 1 +10 1 +.names 5908 5909 +1 1 +.names 7172 56629 +0 1 +.names 6853 56593 +0 1 +.names 56630 56594 5912 +01 1 +10 1 +.names 5912 5913 +1 1 +.names 56563 56599 5914 +11 1 +.names 5914 5915 +1 1 +.names 56564 56600 5916 +11 1 +.names 5916 5917 +1 1 +.names 56565 56601 5918 +11 1 +.names 5918 5919 +1 1 +.names 56566 56602 5920 +11 1 +.names 5920 5921 +1 1 +.names 56567 56603 5922 +11 1 +.names 5922 5923 +1 1 +.names 56568 56604 5924 +11 1 +.names 5924 5925 +1 1 +.names 56569 56605 5926 +11 1 +.names 5926 5927 +1 1 +.names 56570 56606 5928 +11 1 +.names 5928 5929 +1 1 +.names 56571 56607 5930 +11 1 +.names 5930 5931 +1 1 +.names 56572 56608 5932 +11 1 +.names 5932 5933 +1 1 +.names 56573 56609 5934 +11 1 +.names 5934 5935 +1 1 +.names 56574 56610 5936 +11 1 +.names 5936 5937 +1 1 +.names 56575 56611 5938 +11 1 +.names 5938 5939 +1 1 +.names 56576 56612 5940 +11 1 +.names 5940 5941 +1 1 +.names 56577 56613 5942 +11 1 +.names 5942 5943 +1 1 +.names 56578 56614 5944 +11 1 +.names 5944 5945 +1 1 +.names 56579 56615 5946 +11 1 +.names 5946 5947 +1 1 +.names 56580 56616 5948 +11 1 +.names 5948 5949 +1 1 +.names 56581 56617 5950 +11 1 +.names 5950 5951 +1 1 +.names 56582 56618 5952 +11 1 +.names 5952 5953 +1 1 +.names 56583 56619 5954 +11 1 +.names 5954 5955 +1 1 +.names 56584 56620 5956 +11 1 +.names 5956 5957 +1 1 +.names 56585 56621 5958 +11 1 +.names 5958 5959 +1 1 +.names 56586 56622 5960 +11 1 +.names 5960 5961 +1 1 +.names 56587 56623 5962 +11 1 +.names 5962 5963 +1 1 +.names 56588 56624 5964 +11 1 +.names 5964 5965 +1 1 +.names 56589 56625 5966 +11 1 +.names 5966 5967 +1 1 +.names 56590 56626 5968 +11 1 +.names 5968 5969 +1 1 +.names 56591 56627 5970 +11 1 +.names 5970 5971 +1 1 +.names 56592 56628 5972 +11 1 +.names 5972 5973 +1 1 +.names 56593 56629 5974 +11 1 +.names 5974 5975 +1 1 +.names 56594 56630 5976 +11 1 +.names 5976 5977 +1 1 +.names 56563 56599 5978 +1- 1 +-1 1 +.names 5978 5979 +1 1 +.names 56564 56600 5980 +1- 1 +-1 1 +.names 5980 5981 +1 1 +.names 56565 56601 5982 +1- 1 +-1 1 +.names 5982 5983 +1 1 +.names 56566 56602 5984 +1- 1 +-1 1 +.names 5984 5985 +1 1 +.names 56567 56603 5986 +1- 1 +-1 1 +.names 5986 5987 +1 1 +.names 56568 56604 5988 +1- 1 +-1 1 +.names 5988 5989 +1 1 +.names 56569 56605 5990 +1- 1 +-1 1 +.names 5990 5991 +1 1 +.names 56570 56606 5992 +1- 1 +-1 1 +.names 5992 5993 +1 1 +.names 56571 56607 5994 +1- 1 +-1 1 +.names 5994 5995 +1 1 +.names 56572 56608 5996 +1- 1 +-1 1 +.names 5996 5997 +1 1 +.names 56573 56609 5998 +1- 1 +-1 1 +.names 5998 5999 +1 1 +.names 56574 56610 6000 +1- 1 +-1 1 +.names 6000 6001 +1 1 +.names 56575 56611 6002 +1- 1 +-1 1 +.names 6002 6003 +1 1 +.names 56576 56612 6004 +1- 1 +-1 1 +.names 6004 6005 +1 1 +.names 56577 56613 6006 +1- 1 +-1 1 +.names 6006 6007 +1 1 +.names 56578 56614 6008 +1- 1 +-1 1 +.names 6008 6009 +1 1 +.names 56579 56615 6010 +1- 1 +-1 1 +.names 6010 6011 +1 1 +.names 56580 56616 6012 +1- 1 +-1 1 +.names 6012 6013 +1 1 +.names 56581 56617 6014 +1- 1 +-1 1 +.names 6014 6015 +1 1 +.names 56582 56618 6016 +1- 1 +-1 1 +.names 6016 6017 +1 1 +.names 56583 56619 6018 +1- 1 +-1 1 +.names 6018 6019 +1 1 +.names 56584 56620 6020 +1- 1 +-1 1 +.names 6020 6021 +1 1 +.names 56585 56621 6022 +1- 1 +-1 1 +.names 6022 6023 +1 1 +.names 56586 56622 6024 +1- 1 +-1 1 +.names 6024 6025 +1 1 +.names 56587 56623 6026 +1- 1 +-1 1 +.names 6026 6027 +1 1 +.names 56588 56624 6028 +1- 1 +-1 1 +.names 6028 6029 +1 1 +.names 56589 56625 6030 +1- 1 +-1 1 +.names 6030 6031 +1 1 +.names 56590 56626 6032 +1- 1 +-1 1 +.names 6032 6033 +1 1 +.names 56591 56627 6034 +1- 1 +-1 1 +.names 6034 6035 +1 1 +.names 56592 56628 6036 +1- 1 +-1 1 +.names 6036 6037 +1 1 +.names 56593 56629 6038 +1- 1 +-1 1 +.names 6038 6039 +1 1 +.names 56594 56630 6040 +1- 1 +-1 1 +.names 6040 6041 +1 1 +.names 6045 6042 +0 1 +.names 6042 6043 +1 1 +.names 26505 26533 6044 +1- 1 +-1 1 +.names 6044 6045 +1 1 +.names 6049 6046 +0 1 +.names 6046 6047 +1 1 +.names 25939 25967 6048 +1- 1 +-1 1 +.names 6048 6049 +1 1 +.names 6053 6050 +0 1 +.names 6050 6051 +1 1 +.names 26855 26856 6052 +1- 1 +-1 1 +.names 6052 6053 +1 1 +.names 6057 6054 +0 1 +.names 6054 6055 +1 1 +.names 27235 27260 6056 +1- 1 +-1 1 +.names 6056 6057 +1 1 +.names 6061 6058 +0 1 +.names 6058 6059 +1 1 +.names 27281 27306 6060 +1- 1 +-1 1 +.names 6060 6061 +1 1 +.names 6065 6062 +0 1 +.names 6062 6063 +1 1 +.names 26889 26912 6064 +1- 1 +-1 1 +.names 6064 6065 +1 1 +.names 6069 6066 +0 1 +.names 6066 6067 +1 1 +.names 25997 26000 6068 +1- 1 +-1 1 +.names 6068 6069 +1 1 +.names 6073 6070 +0 1 +.names 6070 6071 +1 1 +.names 26544 26573 6072 +1- 1 +-1 1 +.names 6072 6073 +1 1 +.names 6077 6074 +0 1 +.names 6074 6075 +1 1 +.names 26043 26046 6076 +1- 1 +-1 1 +.names 6076 6077 +1 1 +.names 6081 6078 +0 1 +.names 6078 6079 +1 1 +.names 26324 26325 6080 +1- 1 +-1 1 +.names 6080 6081 +1 1 +.names 6085 6082 +0 1 +.names 6082 6083 +1 1 +.names 26107 26133 6084 +1- 1 +-1 1 +.names 6084 6085 +1 1 +.names 6089 6086 +0 1 +.names 6086 6087 +1 1 +.names 26400 26426 6088 +1- 1 +-1 1 +.names 6088 6089 +1 1 +.names 6093 6090 +0 1 +.names 6090 6091 +1 1 +.names 27085 27110 6092 +1- 1 +-1 1 +.names 6092 6093 +1 1 +.names 6097 6094 +0 1 +.names 6094 6095 +1 1 +.names 26931 26934 6096 +1- 1 +-1 1 +.names 6096 6097 +1 1 +.names 6101 6098 +0 1 +.names 6098 6099 +1 1 +.names 26993 27018 6100 +1- 1 +-1 1 +.names 6100 6101 +1 1 +.names 6105 6102 +0 1 +.names 6102 6103 +1 1 +.names 27327 27350 6104 +1- 1 +-1 1 +.names 6104 6105 +1 1 +.names 6109 6106 +0 1 +.names 6106 6107 +1 1 +.names 26679 26680 6108 +1- 1 +-1 1 +.names 6108 6109 +1 1 +.names 6113 6110 +0 1 +.names 6110 6111 +1 1 +.names 26167 26168 6112 +1- 1 +-1 1 +.names 6112 6113 +1 1 +.names 6117 6114 +0 1 +.names 6114 6115 +1 1 +.names 26625 26626 6116 +1- 1 +-1 1 +.names 6116 6117 +1 1 +.names 6121 6118 +0 1 +.names 6118 6119 +1 1 +.names 26244 26247 6120 +1- 1 +-1 1 +.names 6120 6121 +1 1 +.names 6125 6122 +0 1 +.names 6122 6123 +1 1 +.names 27388 27389 6124 +1- 1 +-1 1 +.names 6124 6125 +1 1 +.names 6129 6126 +0 1 +.names 6126 6127 +1 1 +.names 26797 26822 6128 +1- 1 +-1 1 +.names 6128 6129 +1 1 +.names 6133 6130 +0 1 +.names 6130 6131 +1 1 +.names 25887 25917 6132 +1- 1 +-1 1 +.names 6132 6133 +1 1 +.names 6137 6134 +0 1 +.names 6134 6135 +1 1 +.names 26692 26717 6136 +1- 1 +-1 1 +.names 6136 6137 +1 1 +.names 6141 6138 +0 1 +.names 6138 6139 +1 1 +.names 26444 26447 6140 +1- 1 +-1 1 +.names 6140 6141 +1 1 +.names 6145 6142 +0 1 +.names 6142 6143 +1 1 +.names 26366 26367 6144 +1- 1 +-1 1 +.names 6144 6145 +1 1 +.names 6149 6146 +0 1 +.names 6146 6147 +1 1 +.names 27131 27156 6148 +1- 1 +-1 1 +.names 6148 6149 +1 1 +.names 6153 6150 +0 1 +.names 6150 6151 +1 1 +.names 27173 27176 6152 +1- 1 +-1 1 +.names 6152 6153 +1 1 +.names 6157 6154 +0 1 +.names 6154 6155 +1 1 +.names 27039 27064 6156 +1- 1 +-1 1 +.names 6156 6157 +1 1 +.names 6161 6158 +0 1 +.names 6158 6159 +1 1 +.names 27420 27445 6160 +1- 1 +-1 1 +.names 6160 6161 +1 1 +.names 6165 6162 +0 1 +.names 6162 6163 +1 1 +.names 26215 26216 6164 +1- 1 +-1 1 +.names 6164 6165 +1 1 +.names 6169 6166 +0 1 +.names 6166 6167 +1 1 +.names 26734 26737 6168 +1- 1 +-1 1 +.names 6168 6169 +1 1 +.names 6173 6170 +0 1 +.names 6170 6171 +1 1 +.names 25550 25551 6172 +1- 1 +-1 1 +.names 6172 6173 +1 1 +.names 6177 6174 +0 1 +.names 6174 6175 +1 1 +.names 25333 25334 6176 +1- 1 +-1 1 +.names 6176 6177 +1 1 +.names 6181 6178 +0 1 +.names 6178 6179 +1 1 +.names 25567 25568 6180 +1- 1 +-1 1 +.names 6180 6181 +1 1 +.names 6185 6182 +0 1 +.names 6182 6183 +1 1 +.names 25803 25804 6184 +1- 1 +-1 1 +.names 6184 6185 +1 1 +.names 6189 6186 +0 1 +.names 6186 6187 +1 1 +.names 25820 25821 6188 +1- 1 +-1 1 +.names 6188 6189 +1 1 +.names 6193 6190 +0 1 +.names 6190 6191 +1 1 +.names 25584 25585 6192 +1- 1 +-1 1 +.names 6192 6193 +1 1 +.names 6197 6194 +0 1 +.names 6194 6195 +1 1 +.names 25350 25351 6196 +1- 1 +-1 1 +.names 6196 6197 +1 1 +.names 6201 6198 +0 1 +.names 6198 6199 +1 1 +.names 25595 25598 6200 +1- 1 +-1 1 +.names 6200 6201 +1 1 +.names 6205 6202 +0 1 +.names 6202 6203 +1 1 +.names 25396 25397 6204 +1- 1 +-1 1 +.names 6204 6205 +1 1 +.names 6209 6206 +0 1 +.names 6206 6207 +1 1 +.names 25475 25478 6208 +1- 1 +-1 1 +.names 6208 6209 +1 1 +.names 6213 6210 +0 1 +.names 6210 6211 +1 1 +.names 25402 25415 6212 +1- 1 +-1 1 +.names 6212 6213 +1 1 +.names 6217 6214 +0 1 +.names 6214 6215 +1 1 +.names 25517 25518 6216 +1- 1 +-1 1 +.names 6216 6217 +1 1 +.names 6221 6218 +0 1 +.names 6218 6219 +1 1 +.names 25769 25770 6220 +1- 1 +-1 1 +.names 6220 6221 +1 1 +.names 6225 6222 +0 1 +.names 6222 6223 +1 1 +.names 25701 25702 6224 +1- 1 +-1 1 +.names 6224 6225 +1 1 +.names 6229 6226 +0 1 +.names 6226 6227 +1 1 +.names 25712 25715 6228 +1- 1 +-1 1 +.names 6228 6229 +1 1 +.names 6233 6230 +0 1 +.names 6230 6231 +1 1 +.names 25836 25837 6232 +1- 1 +-1 1 +.names 6232 6233 +1 1 +.names 6237 6234 +0 1 +.names 6234 6235 +1 1 +.names 25634 25635 6236 +1- 1 +-1 1 +.names 6236 6237 +1 1 +.names 6241 6238 +0 1 +.names 6238 6239 +1 1 +.names 25434 25435 6240 +1- 1 +-1 1 +.names 6240 6241 +1 1 +.names 6245 6242 +0 1 +.names 6242 6243 +1 1 +.names 25623 25624 6244 +1- 1 +-1 1 +.names 6244 6245 +1 1 +.names 6249 6246 +0 1 +.names 6246 6247 +1 1 +.names 25463 25464 6248 +1- 1 +-1 1 +.names 6248 6249 +1 1 +.names 6253 6250 +0 1 +.names 6250 6251 +1 1 +.names 25853 25854 6252 +1- 1 +-1 1 +.names 6252 6253 +1 1 +.names 6257 6254 +0 1 +.names 6254 6255 +1 1 +.names 25684 25685 6256 +1- 1 +-1 1 +.names 6256 6257 +1 1 +.names 6261 6258 +0 1 +.names 6258 6259 +1 1 +.names 25363 25366 6260 +1- 1 +-1 1 +.names 6260 6261 +1 1 +.names 6265 6262 +0 1 +.names 6262 6263 +1 1 +.names 25651 25652 6264 +1- 1 +-1 1 +.names 6264 6265 +1 1 +.names 6269 6266 +0 1 +.names 6266 6267 +1 1 +.names 25528 25531 6268 +1- 1 +-1 1 +.names 6268 6269 +1 1 +.names 6273 6270 +0 1 +.names 6270 6271 +1 1 +.names 25505 25506 6272 +1- 1 +-1 1 +.names 6272 6273 +1 1 +.names 6277 6274 +0 1 +.names 6274 6275 +1 1 +.names 25752 25753 6276 +1- 1 +-1 1 +.names 6276 6277 +1 1 +.names 6281 6278 +0 1 +.names 6278 6279 +1 1 +.names 25786 25787 6280 +1- 1 +-1 1 +.names 6280 6281 +1 1 +.names 6285 6282 +0 1 +.names 6282 6283 +1 1 +.names 25735 25736 6284 +1- 1 +-1 1 +.names 6284 6285 +1 1 +.names 6289 6286 +0 1 +.names 6286 6287 +1 1 +.names 25864 25867 6288 +1- 1 +-1 1 +.names 6288 6289 +1 1 +.names 6293 6290 +0 1 +.names 6290 6291 +1 1 +.names 25440 25443 6292 +1- 1 +-1 1 +.names 6292 6293 +1 1 +.names 6297 6294 +0 1 +.names 6294 6295 +1 1 +.names 25667 25668 6296 +1- 1 +-1 1 +.names 6296 6297 +1 1 +.names 374 6298 +0 1 +.names 6298 6299 +1 1 +.names 375 6299 6300 +11 1 +.names 6300 6301 +1 1 +.names 375 374 6302 +11 1 +.names 6302 6303 +1 1 +.names 575 574 6304 +11 1 +.names 6304 6305 +1 1 +.names 6305 573 6306 +11 1 +.names 6306 6307 +1 1 +.names 573 6308 +0 1 +.names 6308 6309 +1 1 +.names 575 574 6310 +11 1 +.names 6310 6311 +1 1 +.names 6311 6309 6312 +11 1 +.names 6312 6313 +1 1 +.names 574 6314 +0 1 +.names 6314 6315 +1 1 +.names 575 6315 6316 +11 1 +.names 6316 6317 +1 1 +.names 6317 573 6318 +11 1 +.names 6318 6319 +1 1 +.names 6308 6320 +1 1 +.names 6314 6321 +1 1 +.names 575 6321 6322 +11 1 +.names 6322 6323 +1 1 +.names 6323 6320 6324 +11 1 +.names 6324 6325 +1 1 +.names 575 6326 +0 1 +.names 6326 6327 +1 1 +.names 6327 574 6328 +11 1 +.names 6328 6329 +1 1 +.names 6329 573 6330 +11 1 +.names 6330 6331 +1 1 +.names 6308 6332 +1 1 +.names 6326 6333 +1 1 +.names 6333 574 6334 +11 1 +.names 6334 6335 +1 1 +.names 6335 6332 6336 +11 1 +.names 6336 6337 +1 1 +.names 6314 6338 +1 1 +.names 6326 6339 +1 1 +.names 6339 6338 6340 +11 1 +.names 6340 6341 +1 1 +.names 6341 573 6342 +11 1 +.names 6342 6343 +1 1 +.names 301 6344 +0 1 +.names 6344 6345 +1 1 +.names 6345 300 6346 +11 1 +.names 6346 6347 +1 1 +.names 300 6348 +0 1 +.names 6348 6349 +1 1 +.names 301 6349 6350 +11 1 +.names 6350 6351 +1 1 +.names 301 300 6352 +11 1 +.names 6352 6353 +1 1 +.names 6356 57078 +0 1 +.names 10850 10853 6355 +1- 1 +-1 1 +.names 6355 6356 +1 1 +.names 6359 57080 +0 1 +.names 10764 10767 6358 +1- 1 +-1 1 +.names 6358 6359 +1 1 +.names 893 6360 +0 1 +.names 6360 6361 +1 1 +.names 892 6361 6362 +11 1 +.names 6362 6363 +1 1 +.names 6363 57081 +0 1 +.names 759 758 57082 +11 1 +.names 2792 6366 +0 1 +.names 6366 6367 +1 1 +.names 3131 6367 6368 +11 1 +.names 6368 6369 +1 1 +.names 2781 6370 +0 1 +.names 6370 6371 +1 1 +.names 3143 6371 6372 +11 1 +.names 6372 6373 +1 1 +.names 894 57083 +0 1 +.names 895 6375 +0 1 +.names 6375 6376 +1 1 +.names 6380 733 6377 +11 1 +.names 6377 6378 +1 1 +.names 56400 56404 6379 +1- 1 +-1 1 +.names 6379 6380 +1 1 +.names 6378 896 6381 +11 1 +.names 6381 6382 +1 1 +.names 6382 6376 57084 +11 1 +.names 897 57085 +0 1 +.names 898 236 6385 +01 1 +10 1 +.names 6385 6386 +1 1 +.names 899 237 6387 +01 1 +10 1 +.names 6387 6388 +1 1 +.names 900 238 6389 +01 1 +10 1 +.names 6389 6390 +1 1 +.names 901 239 6391 +01 1 +10 1 +.names 6391 6392 +1 1 +.names 902 248 6393 +01 1 +10 1 +.names 6393 6394 +1 1 +.names 903 236 6395 +01 1 +10 1 +.names 6395 6396 +1 1 +.names 904 237 6397 +01 1 +10 1 +.names 6397 6398 +1 1 +.names 905 238 6399 +01 1 +10 1 +.names 6399 6400 +1 1 +.names 906 239 6401 +01 1 +10 1 +.names 6401 6402 +1 1 +.names 907 248 6403 +01 1 +10 1 +.names 6403 6404 +1 1 +.names 898 56667 6405 +01 1 +10 1 +.names 6405 6406 +1 1 +.names 43424 43426 56667 +1- 1 +-1 1 +.names 899 56668 6408 +01 1 +10 1 +.names 6408 6409 +1 1 +.names 43416 43418 56668 +1- 1 +-1 1 +.names 900 56669 6411 +01 1 +10 1 +.names 6411 6412 +1 1 +.names 43408 43410 56669 +1- 1 +-1 1 +.names 901 56670 6414 +01 1 +10 1 +.names 6414 6415 +1 1 +.names 43401 43402 56670 +1- 1 +-1 1 +.names 902 56679 6417 +01 1 +10 1 +.names 6417 6418 +1 1 +.names 43031 43035 56679 +1- 1 +-1 1 +.names 903 56667 6420 +01 1 +10 1 +.names 6420 6421 +1 1 +.names 904 56668 6422 +01 1 +10 1 +.names 6422 6423 +1 1 +.names 905 56669 6424 +01 1 +10 1 +.names 6424 6425 +1 1 +.names 906 56670 6426 +01 1 +10 1 +.names 6426 6427 +1 1 +.names 907 56679 6428 +01 1 +10 1 +.names 6428 6429 +1 1 +.names 57131 6430 +1 1 +.names 6430 56848 6431 +1- 1 +-1 1 +.names 6431 6432 +1 1 +.names 6432 908 57086 +1- 1 +-1 1 +.names 714 908 6434 +11 1 +.names 6434 6435 +1 1 +.names 57131 6436 +1 1 +.names 909 6437 +0 1 +.names 6437 6438 +1 1 +.names 57131 6439 +1 1 +.names 57131 6440 +1 1 +.names 57131 6441 +1 1 +.names 57131 6442 +1 1 +.names 57131 6443 +1 1 +.names 57131 6444 +1 1 +.names 57131 6445 +1 1 +.names 57131 6446 +1 1 +.names 57131 6447 +1 1 +.names 57131 6448 +1 1 +.names 6448 2844 57087 +1- 1 +-1 1 +.names 57131 6450 +1 1 +.names 57131 6451 +1 1 +.names 6451 2813 57088 +1- 1 +-1 1 +.names 3098 57089 +0 1 +.names 3131 2792 57090 +1- 1 +-1 1 +.names 3110 57091 +0 1 +.names 3143 2781 57092 +1- 1 +-1 1 +.names 3131 56843 57093 +1- 1 +-1 1 +.names 57089 6458 +1 1 +.names 6458 714 57094 +11 1 +.names 3143 56842 57095 +1- 1 +-1 1 +.names 57091 6461 +1 1 +.names 6461 714 57096 +11 1 +.names 57131 6463 +1 1 +.names 57131 6464 +1 1 +.names 57131 6465 +1 1 +.names 57131 6466 +1 1 +.names 57131 6467 +1 1 +.names 57131 6468 +1 1 +.names 57131 6469 +1 1 +.names 57131 6470 +1 1 +.names 57131 6471 +1 1 +.names 57131 6472 +1 1 +.names 910 6473 +0 1 +.names 6473 6474 +1 1 +.names 911 6474 57097 +11 1 +.names 56713 57098 +0 1 +.names 27621 27625 56713 +1- 1 +-1 1 +.names 57131 6478 +1 1 +.names 57131 6479 +1 1 +.names 57131 6480 +1 1 +.names 6480 56840 57099 +1- 1 +-1 1 +.names 57083 6482 +1 1 +.names 2728 6482 57100 +11 1 +.names 57131 6484 +1 1 +.names 57131 6485 +1 1 +.names 912 6486 +0 1 +.names 6486 6487 +1 1 +.names 57084 6487 6488 +11 1 +.names 6488 6489 +1 1 +.names 6489 714 6490 +11 1 +.names 6490 6491 +1 1 +.names 6486 6492 +1 1 +.names 57084 6492 6493 +11 1 +.names 6493 6494 +1 1 +.names 57101 6494 57102 +1- 1 +-1 1 +.names 6497 2715 57101 +1- 1 +-1 1 +.names 57131 6497 +1 1 +.names 57083 6498 +1 1 +.names 2704 6498 57103 +11 1 +.names 57131 6500 +1 1 +.names 57083 6501 +1 1 +.names 2691 6501 6502 +11 1 +.names 6502 6503 +1 1 +.names 57131 6504 +1 1 +.names 6504 6503 57104 +1- 1 +-1 1 +.names 4431 4429 6506 +1- 1 +-1 1 +.names 6506 6507 +1 1 +.names 6507 4427 6508 +1- 1 +-1 1 +.names 6508 6509 +1 1 +.names 6509 4425 6510 +1- 1 +-1 1 +.names 6510 6511 +1 1 +.names 6511 4423 6512 +1- 1 +-1 1 +.names 6512 6513 +1 1 +.names 6513 4421 6514 +1- 1 +-1 1 +.names 6514 6515 +1 1 +.names 6515 4417 6516 +1- 1 +-1 1 +.names 6516 6517 +1 1 +.names 6517 4415 6518 +1- 1 +-1 1 +.names 6518 6519 +1 1 +.names 6519 4413 6520 +1- 1 +-1 1 +.names 6520 6521 +1 1 +.names 6521 4411 6522 +1- 1 +-1 1 +.names 6522 6523 +1 1 +.names 6523 4409 6524 +1- 1 +-1 1 +.names 6524 6525 +1 1 +.names 6525 4407 6526 +1- 1 +-1 1 +.names 6526 6527 +1 1 +.names 6527 4403 6528 +1- 1 +-1 1 +.names 6528 6529 +1 1 +.names 6529 4401 6530 +1- 1 +-1 1 +.names 6530 6531 +1 1 +.names 6531 4399 6532 +1- 1 +-1 1 +.names 6532 6533 +1 1 +.names 6533 4397 6534 +1- 1 +-1 1 +.names 6534 6535 +1 1 +.names 6535 4395 6536 +1- 1 +-1 1 +.names 6536 6537 +1 1 +.names 6537 4393 6538 +1- 1 +-1 1 +.names 6538 6539 +1 1 +.names 6539 4391 6540 +1- 1 +-1 1 +.names 6540 6541 +1 1 +.names 6541 4389 6542 +1- 1 +-1 1 +.names 6542 6543 +1 1 +.names 6543 4387 6544 +1- 1 +-1 1 +.names 6544 6545 +1 1 +.names 6545 4384 6546 +1- 1 +-1 1 +.names 6546 6547 +1 1 +.names 6547 4382 6548 +1- 1 +-1 1 +.names 6548 6549 +1 1 +.names 6549 4380 6550 +1- 1 +-1 1 +.names 6550 6551 +1 1 +.names 6551 4378 6552 +1- 1 +-1 1 +.names 6552 6553 +1 1 +.names 6553 4376 6554 +1- 1 +-1 1 +.names 6554 6555 +1 1 +.names 6555 4372 6556 +1- 1 +-1 1 +.names 6556 6557 +1 1 +.names 6557 4370 6558 +1- 1 +-1 1 +.names 6558 6559 +1 1 +.names 6559 4368 6560 +1- 1 +-1 1 +.names 6560 6561 +1 1 +.names 6561 4366 6562 +1- 1 +-1 1 +.names 6562 6563 +1 1 +.names 6563 4364 6564 +1- 1 +-1 1 +.names 6564 6565 +1 1 +.names 6565 4362 6566 +1- 1 +-1 1 +.names 6566 6567 +1 1 +.names 6567 4358 6568 +1- 1 +-1 1 +.names 6568 6569 +1 1 +.names 6569 4356 6570 +1- 1 +-1 1 +.names 6570 6571 +1 1 +.names 6571 4354 6572 +1- 1 +-1 1 +.names 6572 6573 +1 1 +.names 6573 4352 6574 +1- 1 +-1 1 +.names 6574 6575 +1 1 +.names 6575 4350 6576 +1- 1 +-1 1 +.names 6576 6577 +1 1 +.names 6577 4346 6578 +1- 1 +-1 1 +.names 6578 6579 +1 1 +.names 6579 4344 6580 +1- 1 +-1 1 +.names 6580 6581 +1 1 +.names 6581 4342 6582 +1- 1 +-1 1 +.names 6582 6583 +1 1 +.names 6583 4340 6584 +1- 1 +-1 1 +.names 6584 6585 +1 1 +.names 6585 4338 6586 +1- 1 +-1 1 +.names 6586 6587 +1 1 +.names 6587 4336 6588 +1- 1 +-1 1 +.names 6588 6589 +1 1 +.names 6589 4333 6590 +1- 1 +-1 1 +.names 6590 6591 +1 1 +.names 6591 4329 6592 +1- 1 +-1 1 +.names 6592 6593 +1 1 +.names 6593 4327 6594 +1- 1 +-1 1 +.names 6594 6595 +1 1 +.names 6595 4325 6596 +1- 1 +-1 1 +.names 6596 6597 +1 1 +.names 6597 4321 6598 +1- 1 +-1 1 +.names 6598 6599 +1 1 +.names 6599 4319 6600 +1- 1 +-1 1 +.names 6600 6601 +1 1 +.names 6601 4317 6602 +1- 1 +-1 1 +.names 6602 6603 +1 1 +.names 6603 4315 6604 +1- 1 +-1 1 +.names 6604 6605 +1 1 +.names 6605 4313 6606 +1- 1 +-1 1 +.names 6606 6607 +1 1 +.names 6607 4311 6608 +1- 1 +-1 1 +.names 6608 6609 +1 1 +.names 6609 4309 6610 +1- 1 +-1 1 +.names 6610 6611 +1 1 +.names 6611 4307 6612 +1- 1 +-1 1 +.names 6612 6613 +1 1 +.names 6613 4305 6614 +1- 1 +-1 1 +.names 6614 6615 +1 1 +.names 6615 4303 6616 +1- 1 +-1 1 +.names 6616 6617 +1 1 +.names 6617 4301 6618 +1- 1 +-1 1 +.names 6618 6619 +1 1 +.names 6619 4299 6620 +1- 1 +-1 1 +.names 6620 6621 +1 1 +.names 6621 4297 6622 +1- 1 +-1 1 +.names 6622 6623 +1 1 +.names 6623 4295 6624 +1- 1 +-1 1 +.names 6624 6625 +1 1 +.names 6625 4293 6626 +1- 1 +-1 1 +.names 6626 6627 +1 1 +.names 6627 4291 6628 +1- 1 +-1 1 +.names 6628 6629 +1 1 +.names 6629 4289 6630 +1- 1 +-1 1 +.names 6630 6631 +1 1 +.names 6631 4287 6632 +1- 1 +-1 1 +.names 6632 6633 +1 1 +.names 6633 4285 6634 +1- 1 +-1 1 +.names 6634 6635 +1 1 +.names 6635 4283 6636 +1- 1 +-1 1 +.names 6636 6637 +1 1 +.names 6637 4281 6638 +1- 1 +-1 1 +.names 6638 6639 +1 1 +.names 6639 4279 6640 +1- 1 +-1 1 +.names 6640 6641 +1 1 +.names 6641 4277 6642 +1- 1 +-1 1 +.names 6642 6643 +1 1 +.names 6643 4275 6644 +1- 1 +-1 1 +.names 6644 6645 +1 1 +.names 6645 4271 6646 +1- 1 +-1 1 +.names 6646 6647 +1 1 +.names 6647 4267 6648 +1- 1 +-1 1 +.names 6648 6649 +1 1 +.names 6649 4263 6650 +1- 1 +-1 1 +.names 6650 6651 +1 1 +.names 6651 4259 6652 +1- 1 +-1 1 +.names 6652 6653 +1 1 +.names 6653 4257 6654 +1- 1 +-1 1 +.names 6654 6655 +1 1 +.names 6655 4255 6656 +1- 1 +-1 1 +.names 6656 6657 +1 1 +.names 6657 4253 6658 +1- 1 +-1 1 +.names 6658 6659 +1 1 +.names 6659 4251 6660 +1- 1 +-1 1 +.names 6660 6661 +1 1 +.names 6661 4249 6662 +1- 1 +-1 1 +.names 6662 6663 +1 1 +.names 6663 4247 6664 +1- 1 +-1 1 +.names 6664 6665 +1 1 +.names 6665 4245 6666 +1- 1 +-1 1 +.names 6666 6667 +1 1 +.names 6667 4243 6668 +1- 1 +-1 1 +.names 6668 6669 +1 1 +.names 6669 4241 6670 +1- 1 +-1 1 +.names 6670 6671 +1 1 +.names 6671 4239 6672 +1- 1 +-1 1 +.names 6672 6673 +1 1 +.names 6673 4237 6674 +1- 1 +-1 1 +.names 6674 6675 +1 1 +.names 6675 4235 6676 +1- 1 +-1 1 +.names 6676 6677 +1 1 +.names 6677 4233 6678 +1- 1 +-1 1 +.names 6678 6679 +1 1 +.names 6679 4231 6680 +1- 1 +-1 1 +.names 6680 6681 +1 1 +.names 6681 4229 6682 +1- 1 +-1 1 +.names 6682 6683 +1 1 +.names 6683 4227 6684 +1- 1 +-1 1 +.names 6684 6685 +1 1 +.names 6685 4225 6686 +1- 1 +-1 1 +.names 6686 6687 +1 1 +.names 6687 4223 6688 +1- 1 +-1 1 +.names 6688 6689 +1 1 +.names 6689 6693 6690 +1- 1 +-1 1 +.names 6690 6691 +1 1 +.names 10418 6692 +0 1 +.names 6692 6693 +1 1 +.names 6691 6697 6694 +1- 1 +-1 1 +.names 6694 6695 +1 1 +.names 10408 6696 +0 1 +.names 6696 6697 +1 1 +.names 6695 6701 6698 +1- 1 +-1 1 +.names 6698 6699 +1 1 +.names 10380 6700 +0 1 +.names 6700 6701 +1 1 +.names 6699 6705 6702 +1- 1 +-1 1 +.names 6702 6703 +1 1 +.names 10384 6704 +0 1 +.names 6704 6705 +1 1 +.names 6703 6706 +0 1 +.names 6706 6707 +1 1 +.names 6711 6713 6708 +1- 1 +-1 1 +.names 6708 6709 +1 1 +.names 9839 6710 +0 1 +.names 6710 6711 +1 1 +.names 10102 6712 +0 1 +.names 6712 6713 +1 1 +.names 6709 6717 6714 +1- 1 +-1 1 +.names 6714 6715 +1 1 +.names 10050 6716 +0 1 +.names 6716 6717 +1 1 +.names 6715 6721 6718 +1- 1 +-1 1 +.names 6718 6719 +1 1 +.names 10048 6720 +0 1 +.names 6720 6721 +1 1 +.names 6719 6725 6722 +1- 1 +-1 1 +.names 6722 6723 +1 1 +.names 10046 6724 +0 1 +.names 6724 6725 +1 1 +.names 6723 6729 6726 +1- 1 +-1 1 +.names 6726 6727 +1 1 +.names 10044 6728 +0 1 +.names 6728 6729 +1 1 +.names 6727 6733 6730 +1- 1 +-1 1 +.names 6730 6731 +1 1 +.names 10042 6732 +0 1 +.names 6732 6733 +1 1 +.names 6731 6737 6734 +1- 1 +-1 1 +.names 6734 6735 +1 1 +.names 10040 6736 +0 1 +.names 6736 6737 +1 1 +.names 6735 6741 6738 +1- 1 +-1 1 +.names 6738 6739 +1 1 +.names 10038 6740 +0 1 +.names 6740 6741 +1 1 +.names 10036 6742 +0 1 +.names 6742 6743 +1 1 +.names 364 799 6744 +1- 1 +-1 1 +.names 6744 6745 +1 1 +.names 6745 809 6746 +1- 1 +-1 1 +.names 6746 6747 +1 1 +.names 3658 6748 +1 1 +.names 5366 6749 +1 1 +.names 365 6749 6750 +11 1 +.names 6750 6751 +1 1 +.names 6751 798 6752 +1- 1 +-1 1 +.names 6752 6753 +1 1 +.names 6753 6748 6754 +11 1 +.names 6754 6755 +1 1 +.names 5587 3647 6756 +11 1 +.names 6756 6757 +1 1 +.names 5598 3642 6758 +11 1 +.names 6758 6759 +1 1 +.names 3636 6760 +0 1 +.names 6760 6761 +1 1 +.names 5609 6761 6762 +11 1 +.names 6762 6763 +1 1 +.names 5628 3636 6764 +11 1 +.names 6764 6765 +1 1 +.names 6765 6763 6766 +1- 1 +-1 1 +.names 6766 6767 +1 1 +.names 6767 6759 6768 +1- 1 +-1 1 +.names 6768 6769 +1 1 +.names 6769 6757 6770 +1- 1 +-1 1 +.names 6770 6771 +1 1 +.names 6771 5576 6772 +1- 1 +-1 1 +.names 6772 6773 +1 1 +.names 6773 724 57105 +1- 1 +-1 1 +.names 6778 6775 +0 1 +.names 6775 6776 +1 1 +.names 5347 6777 +0 1 +.names 6777 6778 +1 1 +.names 6775 6779 +1 1 +.names 6775 6780 +1 1 +.names 6784 6781 +0 1 +.names 6781 6782 +1 1 +.names 10685 10686 6783 +1- 1 +-1 1 +.names 6783 6784 +1 1 +.names 6782 6785 +1 1 +.names 6782 6786 +1 1 +.names 6789 6787 +1 1 +.names 6787 6788 +1 1 +.names 6791 6789 +0 1 +.names 959 6790 +0 1 +.names 6790 6791 +1 1 +.names 6795 6792 +0 1 +.names 6792 6793 +1 1 +.names 960 6794 +0 1 +.names 6794 6795 +1 1 +.names 6792 6796 +1 1 +.names 6796 6797 +1 1 +.names 6796 6798 +1 1 +.names 6792 6799 +1 1 +.names 6799 6800 +1 1 +.names 6799 6801 +1 1 +.names 6793 6802 +1 1 +.names 6793 6803 +1 1 +.names 6806 6804 +1 1 +.names 6804 6805 +1 1 +.names 6808 6806 +1 1 +.names 6804 6807 +1 1 +.names 6810 6808 +0 1 +.names 10689 10692 6809 +1- 1 +-1 1 +.names 6809 6810 +1 1 +.names 6814 6811 +0 1 +.names 6811 6812 +1 1 +.names 1783 10693 6813 +1- 1 +-1 1 +.names 6813 6814 +1 1 +.names 6812 6815 +1 1 +.names 6812 6816 +1 1 +.names 6812 6817 +1 1 +.names 6820 6818 +1 1 +.names 6818 6819 +1 1 +.names 6840 6820 +0 1 +.names 6820 6821 +1 1 +.names 6821 6822 +1 1 +.names 6826 6823 +0 1 +.names 6823 6824 +1 1 +.names 6838 6825 +0 1 +.names 6825 6826 +1 1 +.names 6830 6827 +0 1 +.names 6827 6828 +1 1 +.names 10702 10703 6829 +1- 1 +-1 1 +.names 6829 6830 +1 1 +.names 6834 6831 +0 1 +.names 6831 6832 +1 1 +.names 6819 6833 +0 1 +.names 6833 6834 +1 1 +.names 6827 6835 +1 1 +.names 6806 6836 +1 1 +.names 6812 6837 +1 1 +.names 6835 6838 +1 1 +.names 10714 10701 6839 +1- 1 +-1 1 +.names 6839 6840 +1 1 +.names 6821 6841 +1 1 +.names 6821 6842 +1 1 +.names 6806 6843 +1 1 +.names 913 6844 +1 1 +.names 6828 6845 +1 1 +.names 6828 6846 +1 1 +.names 6828 6847 +1 1 +.names 6851 6848 +0 1 +.names 6848 6849 +1 1 +.names 23551 23554 6850 +1- 1 +-1 1 +.names 6850 6851 +1 1 +.names 6855 6852 +0 1 +.names 6852 6853 +1 1 +.names 22987 22990 6854 +1- 1 +-1 1 +.names 6854 6855 +1 1 +.names 6859 6856 +0 1 +.names 6856 6857 +1 1 +.names 24068 24071 6858 +1- 1 +-1 1 +.names 6858 6859 +1 1 +.names 6863 6860 +0 1 +.names 6860 6861 +1 1 +.names 23720 23723 6862 +1- 1 +-1 1 +.names 6862 6863 +1 1 +.names 6867 6864 +0 1 +.names 6864 6865 +1 1 +.names 23855 23858 6866 +1- 1 +-1 1 +.names 6866 6867 +1 1 +.names 6871 6868 +0 1 +.names 6868 6869 +1 1 +.names 23808 23811 6870 +1- 1 +-1 1 +.names 6870 6871 +1 1 +.names 6875 6872 +0 1 +.names 6872 6873 +1 1 +.names 23118 23121 6874 +1- 1 +-1 1 +.names 6874 6875 +1 1 +.names 6879 6876 +0 1 +.names 6876 6877 +1 1 +.names 23203 23206 6878 +1- 1 +-1 1 +.names 6878 6879 +1 1 +.names 6883 6880 +0 1 +.names 6880 6881 +1 1 +.names 23507 23510 6882 +1- 1 +-1 1 +.names 6882 6883 +1 1 +.names 6887 6884 +0 1 +.names 6884 6885 +1 1 +.names 22724 22727 6886 +1- 1 +-1 1 +.names 6886 6887 +1 1 +.names 6891 6888 +0 1 +.names 6888 6889 +1 1 +.names 23589 23592 6890 +1- 1 +-1 1 +.names 6890 6891 +1 1 +.names 6895 6892 +0 1 +.names 6892 6893 +1 1 +.names 24059 24060 6894 +1- 1 +-1 1 +.names 6894 6895 +1 1 +.names 6899 6896 +0 1 +.names 6896 6897 +1 1 +.names 23030 23033 6898 +1- 1 +-1 1 +.names 6898 6899 +1 1 +.names 6903 6900 +0 1 +.names 6900 6901 +1 1 +.names 23295 23296 6902 +1- 1 +-1 1 +.names 6902 6903 +1 1 +.names 6907 6904 +0 1 +.names 6904 6905 +1 1 +.names 22944 22947 6906 +1- 1 +-1 1 +.names 6906 6907 +1 1 +.names 6911 6908 +0 1 +.names 6908 6909 +1 1 +.names 23492 23495 6910 +1- 1 +-1 1 +.names 6910 6911 +1 1 +.names 6915 6912 +0 1 +.names 6912 6913 +1 1 +.names 23981 23984 6914 +1- 1 +-1 1 +.names 6914 6915 +1 1 +.names 6919 6916 +0 1 +.names 6916 6917 +1 1 +.names 23676 23679 6918 +1- 1 +-1 1 +.names 6918 6919 +1 1 +.names 6923 6920 +0 1 +.names 6920 6921 +1 1 +.names 23661 23664 6922 +1- 1 +-1 1 +.names 6922 6923 +1 1 +.names 6927 6924 +0 1 +.names 6924 6925 +1 1 +.names 23793 23796 6926 +1- 1 +-1 1 +.names 6926 6927 +1 1 +.names 6931 6928 +0 1 +.names 6928 6929 +1 1 +.names 23159 23162 6930 +1- 1 +-1 1 +.names 6930 6931 +1 1 +.names 6935 6932 +0 1 +.names 6932 6933 +1 1 +.names 22934 22935 6934 +1- 1 +-1 1 +.names 6934 6935 +1 1 +.names 6939 6936 +0 1 +.names 6936 6937 +1 1 +.names 23102 23105 6938 +1- 1 +-1 1 +.names 6938 6939 +1 1 +.names 6943 6940 +0 1 +.names 6940 6941 +1 1 +.names 22849 22852 6942 +1- 1 +-1 1 +.names 6942 6943 +1 1 +.names 6947 6944 +0 1 +.names 6944 6945 +1 1 +.names 23354 23357 6946 +1- 1 +-1 1 +.names 6946 6947 +1 1 +.names 6951 6948 +0 1 +.names 6948 6949 +1 1 +.names 22780 22781 6950 +1- 1 +-1 1 +.names 6950 6951 +1 1 +.names 6955 6952 +0 1 +.names 6952 6953 +1 1 +.names 23417 23420 6954 +1- 1 +-1 1 +.names 6954 6955 +1 1 +.names 6959 6956 +0 1 +.names 6956 6957 +1 1 +.names 23939 23942 6958 +1- 1 +-1 1 +.names 6958 6959 +1 1 +.names 6963 6960 +0 1 +.names 6960 6961 +1 1 +.names 23924 23927 6962 +1- 1 +-1 1 +.names 6962 6963 +1 1 +.names 6967 6964 +0 1 +.names 6964 6965 +1 1 +.names 23369 23372 6966 +1- 1 +-1 1 +.names 6966 6967 +1 1 +.names 6971 6968 +0 1 +.names 6968 6969 +1 1 +.names 22804 22807 6970 +1- 1 +-1 1 +.names 6970 6971 +1 1 +.names 6975 6972 +0 1 +.names 6972 6973 +1 1 +.names 23242 23245 6974 +1- 1 +-1 1 +.names 6974 6975 +1 1 +.names 6948 6976 +1 1 +.names 6888 6977 +1 1 +.names 6924 6978 +1 1 +.names 6876 6979 +1 1 +.names 6936 6980 +1 1 +.names 6968 6981 +1 1 +.names 6916 6982 +1 1 +.names 6940 6983 +1 1 +.names 6884 6984 +1 1 +.names 6972 6985 +1 1 +.names 6912 6986 +1 1 +.names 6920 6987 +1 1 +.names 6892 6988 +1 1 +.names 6880 6989 +1 1 +.names 6944 6990 +1 1 +.names 6952 6991 +1 1 +.names 6900 6992 +1 1 +.names 6872 6993 +1 1 +.names 6864 6994 +1 1 +.names 6932 6995 +1 1 +.names 6960 6996 +1 1 +.names 6928 6997 +1 1 +.names 6904 6998 +1 1 +.names 6860 6999 +1 1 +.names 6964 7000 +1 1 +.names 6908 7001 +1 1 +.names 6896 7002 +1 1 +.names 6956 7003 +1 1 +.names 6868 7004 +1 1 +.names 6856 7005 +1 1 +.names 6852 7006 +1 1 +.names 6848 7007 +1 1 +.names 6976 7008 +0 1 +.names 7008 7009 +1 1 +.names 6977 7010 +0 1 +.names 7010 7011 +1 1 +.names 6978 7012 +0 1 +.names 7012 7013 +1 1 +.names 6979 7014 +0 1 +.names 7014 7015 +1 1 +.names 6980 7016 +0 1 +.names 7016 7017 +1 1 +.names 6981 7018 +0 1 +.names 7018 7019 +1 1 +.names 6982 7020 +0 1 +.names 7020 7021 +1 1 +.names 6983 7022 +0 1 +.names 7022 7023 +1 1 +.names 6984 7024 +0 1 +.names 7024 7025 +1 1 +.names 6985 7026 +0 1 +.names 7026 7027 +1 1 +.names 6986 7028 +0 1 +.names 7028 7029 +1 1 +.names 6987 7030 +0 1 +.names 7030 7031 +1 1 +.names 6988 7032 +0 1 +.names 7032 7033 +1 1 +.names 6989 7034 +0 1 +.names 7034 7035 +1 1 +.names 6990 7036 +0 1 +.names 7036 7037 +1 1 +.names 6991 7038 +0 1 +.names 7038 7039 +1 1 +.names 6992 7040 +0 1 +.names 7040 7041 +1 1 +.names 6993 7042 +0 1 +.names 7042 7043 +1 1 +.names 6994 7044 +0 1 +.names 7044 7045 +1 1 +.names 6995 7046 +0 1 +.names 7046 7047 +1 1 +.names 6996 7048 +0 1 +.names 7048 7049 +1 1 +.names 6997 7050 +0 1 +.names 7050 7051 +1 1 +.names 6998 7052 +0 1 +.names 7052 7053 +1 1 +.names 6999 7054 +0 1 +.names 7054 7055 +1 1 +.names 7000 7056 +0 1 +.names 7056 7057 +1 1 +.names 7001 7058 +0 1 +.names 7058 7059 +1 1 +.names 7002 7060 +0 1 +.names 7060 7061 +1 1 +.names 7003 7062 +0 1 +.names 7062 7063 +1 1 +.names 7004 7064 +0 1 +.names 7064 7065 +1 1 +.names 7005 7066 +0 1 +.names 7066 7067 +1 1 +.names 7006 7068 +0 1 +.names 7068 7069 +1 1 +.names 7007 7070 +0 1 +.names 7070 7071 +1 1 +.names 7008 7072 +1 1 +.names 7010 7073 +1 1 +.names 7012 7074 +1 1 +.names 7014 7075 +1 1 +.names 7016 7076 +1 1 +.names 7018 7077 +1 1 +.names 7020 7078 +1 1 +.names 7022 7079 +1 1 +.names 7024 7080 +1 1 +.names 7026 7081 +1 1 +.names 7028 7082 +1 1 +.names 7030 7083 +1 1 +.names 7032 7084 +1 1 +.names 7034 7085 +1 1 +.names 7036 7086 +1 1 +.names 7038 7087 +1 1 +.names 7040 7088 +1 1 +.names 7042 7089 +1 1 +.names 7044 7090 +1 1 +.names 7046 7091 +1 1 +.names 7048 7092 +1 1 +.names 7050 7093 +1 1 +.names 7052 7094 +1 1 +.names 7054 7095 +1 1 +.names 7056 7096 +1 1 +.names 7058 7097 +1 1 +.names 7060 7098 +1 1 +.names 7062 7099 +1 1 +.names 7064 7100 +1 1 +.names 7066 7101 +1 1 +.names 7068 7102 +1 1 +.names 7070 7103 +1 1 +.names 7106 7104 +0 1 +.names 7104 7105 +1 1 +.names 6794 7106 +1 1 +.names 7110 7107 +0 1 +.names 7107 7108 +1 1 +.names 10740 10703 7109 +1- 1 +-1 1 +.names 7109 7110 +1 1 +.names 7114 7111 +0 1 +.names 7111 7112 +1 1 +.names 1783 10729 7113 +1- 1 +-1 1 +.names 7113 7114 +1 1 +.names 7118 7115 +0 1 +.names 7115 7116 +1 1 +.names 10728 10704 7117 +1- 1 +-1 1 +.names 7117 7118 +1 1 +.names 7122 7119 +0 1 +.names 7119 7120 +1 1 +.names 10737 10705 7121 +1- 1 +-1 1 +.names 7121 7122 +1 1 +.names 7125 7123 +1 1 +.names 7123 7124 +1 1 +.names 7127 7125 +1 1 +.names 7123 7126 +1 1 +.names 7129 7127 +0 1 +.names 10789 10792 7128 +1- 1 +-1 1 +.names 7128 7129 +1 1 +.names 7133 7130 +0 1 +.names 7130 7131 +1 1 +.names 1783 10793 7132 +1- 1 +-1 1 +.names 7132 7133 +1 1 +.names 7131 7134 +1 1 +.names 7131 7135 +1 1 +.names 7131 7136 +1 1 +.names 7139 7137 +1 1 +.names 7137 7138 +1 1 +.names 7159 7139 +0 1 +.names 7139 7140 +1 1 +.names 7140 7141 +1 1 +.names 7145 7142 +0 1 +.names 7142 7143 +1 1 +.names 7157 7144 +0 1 +.names 7144 7145 +1 1 +.names 7149 7146 +0 1 +.names 7146 7147 +1 1 +.names 10802 10803 7148 +1- 1 +-1 1 +.names 7148 7149 +1 1 +.names 7153 7150 +0 1 +.names 7150 7151 +1 1 +.names 7138 7152 +0 1 +.names 7152 7153 +1 1 +.names 7146 7154 +1 1 +.names 7125 7155 +1 1 +.names 7131 7156 +1 1 +.names 7154 7157 +1 1 +.names 10814 10801 7158 +1- 1 +-1 1 +.names 7158 7159 +1 1 +.names 7140 7160 +1 1 +.names 7140 7161 +1 1 +.names 7125 7162 +1 1 +.names 914 7163 +1 1 +.names 7147 7164 +1 1 +.names 7147 7165 +1 1 +.names 7147 7166 +1 1 +.names 7170 7167 +0 1 +.names 7167 7168 +1 1 +.names 24842 24845 7169 +1- 1 +-1 1 +.names 7169 7170 +1 1 +.names 7174 7171 +0 1 +.names 7171 7172 +1 1 +.names 24346 24349 7173 +1- 1 +-1 1 +.names 7173 7174 +1 1 +.names 7178 7175 +0 1 +.names 7175 7176 +1 1 +.names 25290 25293 7177 +1- 1 +-1 1 +.names 7177 7178 +1 1 +.names 7182 7179 +0 1 +.names 7179 7180 +1 1 +.names 24987 24990 7181 +1- 1 +-1 1 +.names 7181 7182 +1 1 +.names 7186 7183 +0 1 +.names 7183 7184 +1 1 +.names 25106 25109 7185 +1- 1 +-1 1 +.names 7185 7186 +1 1 +.names 7190 7187 +0 1 +.names 7187 7188 +1 1 +.names 25064 25067 7189 +1- 1 +-1 1 +.names 7189 7190 +1 1 +.names 7194 7191 +0 1 +.names 7191 7192 +1 1 +.names 24460 24463 7193 +1- 1 +-1 1 +.names 7193 7194 +1 1 +.names 7198 7195 +0 1 +.names 7195 7196 +1 1 +.names 24533 24536 7197 +1- 1 +-1 1 +.names 7197 7198 +1 1 +.names 7202 7199 +0 1 +.names 7199 7200 +1 1 +.names 24804 24807 7201 +1- 1 +-1 1 +.names 7201 7202 +1 1 +.names 7206 7203 +0 1 +.names 7203 7204 +1 1 +.names 24115 24118 7205 +1- 1 +-1 1 +.names 7205 7206 +1 1 +.names 7210 7207 +0 1 +.names 7207 7208 +1 1 +.names 24874 24877 7209 +1- 1 +-1 1 +.names 7209 7210 +1 1 +.names 7214 7211 +0 1 +.names 7211 7212 +1 1 +.names 25282 25283 7213 +1- 1 +-1 1 +.names 7213 7214 +1 1 +.names 7218 7215 +0 1 +.names 7215 7216 +1 1 +.names 24384 24387 7217 +1- 1 +-1 1 +.names 7217 7218 +1 1 +.names 7222 7219 +0 1 +.names 7219 7220 +1 1 +.names 24619 24620 7221 +1- 1 +-1 1 +.names 7221 7222 +1 1 +.names 7226 7223 +0 1 +.names 7223 7224 +1 1 +.names 24309 24312 7225 +1- 1 +-1 1 +.names 7225 7226 +1 1 +.names 7230 7227 +0 1 +.names 7227 7228 +1 1 +.names 24790 24793 7229 +1- 1 +-1 1 +.names 7229 7230 +1 1 +.names 7234 7231 +0 1 +.names 7231 7232 +1 1 +.names 25215 25218 7233 +1- 1 +-1 1 +.names 7233 7234 +1 1 +.names 7238 7235 +0 1 +.names 7235 7236 +1 1 +.names 24949 24952 7237 +1- 1 +-1 1 +.names 7237 7238 +1 1 +.names 7242 7239 +0 1 +.names 7239 7240 +1 1 +.names 24935 24938 7241 +1- 1 +-1 1 +.names 7241 7242 +1 1 +.names 7246 7243 +0 1 +.names 7243 7244 +1 1 +.names 25050 25053 7245 +1- 1 +-1 1 +.names 7245 7246 +1 1 +.names 7250 7247 +0 1 +.names 7247 7248 +1 1 +.names 24495 24498 7249 +1- 1 +-1 1 +.names 7249 7250 +1 1 +.names 7254 7251 +0 1 +.names 7251 7252 +1 1 +.names 24300 24301 7253 +1- 1 +-1 1 +.names 7253 7254 +1 1 +.names 7258 7255 +0 1 +.names 7255 7256 +1 1 +.names 24445 24448 7257 +1- 1 +-1 1 +.names 7257 7258 +1 1 +.names 7262 7259 +0 1 +.names 7259 7260 +1 1 +.names 24225 24228 7261 +1- 1 +-1 1 +.names 7261 7262 +1 1 +.names 7266 7263 +0 1 +.names 7263 7264 +1 1 +.names 24667 24670 7265 +1- 1 +-1 1 +.names 7265 7266 +1 1 +.names 7270 7267 +0 1 +.names 7267 7268 +1 1 +.names 24165 24166 7269 +1- 1 +-1 1 +.names 7269 7270 +1 1 +.names 7274 7271 +0 1 +.names 7271 7272 +1 1 +.names 24725 24728 7273 +1- 1 +-1 1 +.names 7273 7274 +1 1 +.names 7278 7275 +0 1 +.names 7275 7276 +1 1 +.names 25178 25181 7277 +1- 1 +-1 1 +.names 7277 7278 +1 1 +.names 7282 7279 +0 1 +.names 7279 7280 +1 1 +.names 25164 25167 7281 +1- 1 +-1 1 +.names 7281 7282 +1 1 +.names 7286 7283 +0 1 +.names 7283 7284 +1 1 +.names 24682 24685 7285 +1- 1 +-1 1 +.names 7285 7286 +1 1 +.names 7290 7287 +0 1 +.names 7287 7288 +1 1 +.names 24186 24189 7289 +1- 1 +-1 1 +.names 7289 7290 +1 1 +.names 7294 7291 +0 1 +.names 7291 7292 +1 1 +.names 24568 24571 7293 +1- 1 +-1 1 +.names 7293 7294 +1 1 +.names 7167 7295 +1 1 +.names 7295 7296 +0 1 +.names 7296 7297 +1 1 +.names 7171 7298 +1 1 +.names 7298 7299 +0 1 +.names 7299 7300 +1 1 +.names 7175 7301 +1 1 +.names 7301 7302 +0 1 +.names 7302 7303 +1 1 +.names 7179 7304 +1 1 +.names 7304 7305 +0 1 +.names 7305 7306 +1 1 +.names 7183 7307 +1 1 +.names 7307 7308 +0 1 +.names 7308 7309 +1 1 +.names 7187 7310 +1 1 +.names 7310 7311 +0 1 +.names 7311 7312 +1 1 +.names 7191 7313 +1 1 +.names 7313 7314 +0 1 +.names 7314 7315 +1 1 +.names 7195 7316 +1 1 +.names 7316 7317 +0 1 +.names 7317 7318 +1 1 +.names 7199 7319 +1 1 +.names 7319 7320 +0 1 +.names 7320 7321 +1 1 +.names 7203 7322 +1 1 +.names 7322 7323 +0 1 +.names 7323 7324 +1 1 +.names 7207 7325 +1 1 +.names 7325 7326 +0 1 +.names 7326 7327 +1 1 +.names 7211 7328 +1 1 +.names 7328 7329 +0 1 +.names 7329 7330 +1 1 +.names 7215 7331 +1 1 +.names 7331 7332 +0 1 +.names 7332 7333 +1 1 +.names 7219 7334 +1 1 +.names 7334 7335 +0 1 +.names 7335 7336 +1 1 +.names 7223 7337 +1 1 +.names 7337 7338 +0 1 +.names 7338 7339 +1 1 +.names 7227 7340 +1 1 +.names 7340 7341 +0 1 +.names 7341 7342 +1 1 +.names 7231 7343 +1 1 +.names 7343 7344 +0 1 +.names 7344 7345 +1 1 +.names 7235 7346 +1 1 +.names 7346 7347 +0 1 +.names 7347 7348 +1 1 +.names 7239 7349 +1 1 +.names 7349 7350 +0 1 +.names 7350 7351 +1 1 +.names 7243 7352 +1 1 +.names 7352 7353 +0 1 +.names 7353 7354 +1 1 +.names 7247 7355 +1 1 +.names 7355 7356 +0 1 +.names 7356 7357 +1 1 +.names 7251 7358 +1 1 +.names 7358 7359 +0 1 +.names 7359 7360 +1 1 +.names 7255 7361 +1 1 +.names 7361 7362 +0 1 +.names 7362 7363 +1 1 +.names 7259 7364 +1 1 +.names 7364 7365 +0 1 +.names 7365 7366 +1 1 +.names 7263 7367 +1 1 +.names 7367 7368 +0 1 +.names 7368 7369 +1 1 +.names 7267 7370 +1 1 +.names 7370 7371 +0 1 +.names 7371 7372 +1 1 +.names 7271 7373 +1 1 +.names 7373 7374 +0 1 +.names 7374 7375 +1 1 +.names 7275 7376 +1 1 +.names 7376 7377 +0 1 +.names 7377 7378 +1 1 +.names 7279 7379 +1 1 +.names 7379 7380 +0 1 +.names 7380 7381 +1 1 +.names 7283 7382 +1 1 +.names 7382 7383 +0 1 +.names 7383 7384 +1 1 +.names 7287 7385 +1 1 +.names 7385 7386 +0 1 +.names 7386 7387 +1 1 +.names 7291 7388 +1 1 +.names 7388 7389 +0 1 +.names 7389 7390 +1 1 +.names 7394 7391 +0 1 +.names 7391 7392 +1 1 +.names 10829 10803 7393 +1- 1 +-1 1 +.names 7393 7394 +1 1 +.names 7398 7395 +0 1 +.names 7395 7396 +1 1 +.names 1783 10818 7397 +1- 1 +-1 1 +.names 7397 7398 +1 1 +.names 7402 7399 +0 1 +.names 7399 7400 +1 1 +.names 10817 10804 7401 +1- 1 +-1 1 +.names 7401 7402 +1 1 +.names 7406 7403 +0 1 +.names 7403 7404 +1 1 +.names 10826 10805 7405 +1- 1 +-1 1 +.names 7405 7406 +1 1 +.names 7410 7407 +0 1 +.names 7407 7408 +1 1 +.names 6353 10870 7409 +1- 1 +-1 1 +.names 7409 7410 +1 1 +.names 7414 7411 +0 1 +.names 7411 7412 +1 1 +.names 10873 10874 7413 +1- 1 +-1 1 +.names 7413 7414 +1 1 +.names 7412 7415 +1 1 +.names 7412 7416 +1 1 +.names 7412 7417 +1 1 +.names 7408 7418 +1 1 +.names 7408 7419 +1 1 +.names 7408 7420 +1 1 +.names 7424 7421 +0 1 +.names 7421 7422 +1 1 +.names 6353 7423 +0 1 +.names 7423 7424 +1 1 +.names 7422 7425 +1 1 +.names 7412 7426 +1 1 +.names 7422 7427 +1 1 +.names 7422 7428 +1 1 +.names 7422 7429 +1 1 +.names 7432 7430 +1 1 +.names 7430 7431 +1 1 +.names 7460 7432 +0 1 +.names 7430 7433 +1 1 +.names 7430 7434 +1 1 +.names 7437 7435 +1 1 +.names 7435 7436 +1 1 +.names 7440 7437 +0 1 +.names 7435 7438 +1 1 +.names 7446 10882 7439 +1- 1 +-1 1 +.names 7439 7440 +1 1 +.names 7443 7441 +1 1 +.names 7441 7442 +1 1 +.names 7462 7443 +0 1 +.names 7446 7444 +1 1 +.names 7444 7445 +1 1 +.names 7495 7446 +0 1 +.names 7449 7447 +1 1 +.names 7447 7448 +1 1 +.names 7485 7449 +0 1 +.names 7453 7450 +0 1 +.names 7450 7451 +1 1 +.names 10891 10892 7452 +1- 1 +-1 1 +.names 7452 7453 +1 1 +.names 7449 7454 +1 1 +.names 7454 7455 +1 1 +.names 7454 7456 +1 1 +.names 7444 7457 +1 1 +.names 7444 7458 +1 1 +.names 10876 10879 7459 +1- 1 +-1 1 +.names 7459 7460 +1 1 +.names 10910 10895 7461 +1- 1 +-1 1 +.names 7461 7462 +1 1 +.names 7443 7463 +1 1 +.names 7466 7464 +1 1 +.names 7464 7465 +1 1 +.names 7472 7466 +0 1 +.names 7470 7467 +0 1 +.names 7467 7468 +1 1 +.names 7448 7469 +0 1 +.names 7469 7470 +1 1 +.names 10888 10885 7471 +1- 1 +-1 1 +.names 7471 7472 +1 1 +.names 7435 7473 +1 1 +.names 7466 7474 +1 1 +.names 7474 7475 +1 1 +.names 7463 7476 +1 1 +.names 7463 7477 +1 1 +.names 7463 7478 +1 1 +.names 6343 7479 +1 1 +.names 7451 7480 +1 1 +.names 7451 7481 +1 1 +.names 7450 7482 +1 1 +.names 7482 7483 +1 1 +.names 10902 10903 7484 +1- 1 +-1 1 +.names 7484 7485 +1 1 +.names 7474 7486 +1 1 +.names 7474 7487 +1 1 +.names 6325 7488 +1 1 +.names 6331 7489 +1 1 +.names 6337 7490 +1 1 +.names 7466 7491 +1 1 +.names 7430 7492 +1 1 +.names 7491 7493 +1 1 +.names 7479 7494 +0 1 +.names 7494 7495 +1 1 +.names 7491 7496 +1 1 +.names 7499 7497 +0 1 +.names 7497 7498 +1 1 +.names 2591 7499 +1 1 +.names 7497 7500 +1 1 +.names 7500 7501 +1 1 +.names 7500 7502 +1 1 +.names 7497 7503 +1 1 +.names 7503 7504 +1 1 +.names 7503 7505 +1 1 +.names 7498 7506 +1 1 +.names 7498 7507 +1 1 +.names 7510 7508 +1 1 +.names 7508 7509 +1 1 +.names 7512 7510 +0 1 +.names 6303 7511 +0 1 +.names 7511 7512 +1 1 +.names 7515 7513 +1 1 +.names 7513 7514 +1 1 +.names 7519 7515 +0 1 +.names 7513 7516 +1 1 +.names 7513 7517 +1 1 +.names 10912 10913 7518 +1- 1 +-1 1 +.names 7518 7519 +1 1 +.names 7508 7520 +1 1 +.names 7508 7521 +1 1 +.names 7515 7522 +1 1 +.names 7525 7523 +1 1 +.names 7523 7524 +1 1 +.names 7527 7525 +0 1 +.names 971 7526 +0 1 +.names 7526 7527 +1 1 +.names 7530 7528 +1 1 +.names 7528 7529 +1 1 +.names 7534 7530 +0 1 +.names 7528 7531 +1 1 +.names 7528 7532 +1 1 +.names 11091 11092 7533 +1- 1 +-1 1 +.names 7533 7534 +1 1 +.names 7523 7535 +1 1 +.names 7523 7536 +1 1 +.names 7530 7537 +1 1 +.names 7540 7538 +1 1 +.names 7538 7539 +1 1 +.names 7541 7540 +0 1 +.names 7526 7541 +1 1 +.names 7544 7542 +1 1 +.names 7542 7543 +1 1 +.names 7548 7544 +0 1 +.names 7542 7545 +1 1 +.names 7542 7546 +1 1 +.names 11094 11092 7547 +1- 1 +-1 1 +.names 7547 7548 +1 1 +.names 7538 7549 +1 1 +.names 7538 7550 +1 1 +.names 7544 7551 +1 1 +.names 7555 7552 +0 1 +.names 7552 7553 +1 1 +.names 2605 7554 +0 1 +.names 7554 7555 +1 1 +.names 7552 7556 +1 1 +.names 7556 7557 +1 1 +.names 7556 7558 +1 1 +.names 7552 7559 +1 1 +.names 7559 7560 +1 1 +.names 7559 7561 +1 1 +.names 7553 7562 +1 1 +.names 7553 7563 +1 1 +.names 7566 7564 +1 1 +.names 7564 7565 +1 1 +.names 7568 7566 +0 1 +.names 2594 7567 +0 1 +.names 7567 7568 +1 1 +.names 7571 7569 +1 1 +.names 7569 7570 +1 1 +.names 7575 7571 +0 1 +.names 7569 7572 +1 1 +.names 7569 7573 +1 1 +.names 11105 11106 7574 +1- 1 +-1 1 +.names 7574 7575 +1 1 +.names 7564 7576 +1 1 +.names 7564 7577 +1 1 +.names 7571 7578 +1 1 +.names 7581 7579 +1 1 +.names 7579 7580 +1 1 +.names 7583 7581 +1 1 +.names 7579 7582 +1 1 +.names 7585 7583 +0 1 +.names 11402 11405 7584 +1- 1 +-1 1 +.names 7584 7585 +1 1 +.names 7589 7586 +0 1 +.names 7586 7587 +1 1 +.names 1783 11406 7588 +1- 1 +-1 1 +.names 7588 7589 +1 1 +.names 7587 7590 +1 1 +.names 7587 7591 +1 1 +.names 7587 7592 +1 1 +.names 7595 7593 +1 1 +.names 7593 7594 +1 1 +.names 7615 7595 +0 1 +.names 7595 7596 +1 1 +.names 7596 7597 +1 1 +.names 7601 7598 +0 1 +.names 7598 7599 +1 1 +.names 7613 7600 +0 1 +.names 7600 7601 +1 1 +.names 7605 7602 +0 1 +.names 7602 7603 +1 1 +.names 11415 11416 7604 +1- 1 +-1 1 +.names 7604 7605 +1 1 +.names 7609 7606 +0 1 +.names 7606 7607 +1 1 +.names 7594 7608 +0 1 +.names 7608 7609 +1 1 +.names 7602 7610 +1 1 +.names 7581 7611 +1 1 +.names 7587 7612 +1 1 +.names 7610 7613 +1 1 +.names 11427 11414 7614 +1- 1 +-1 1 +.names 7614 7615 +1 1 +.names 7596 7616 +1 1 +.names 7596 7617 +1 1 +.names 7581 7618 +1 1 +.names 915 7619 +1 1 +.names 7603 7620 +1 1 +.names 7603 7621 +1 1 +.names 7603 7622 +1 1 +.names 7625 7623 +1 1 +.names 7623 7624 +1 1 +.names 7627 7625 +0 1 +.names 976 7626 +0 1 +.names 7626 7627 +1 1 +.names 7630 7628 +1 1 +.names 7628 7629 +1 1 +.names 7634 7630 +0 1 +.names 7628 7631 +1 1 +.names 7628 7632 +1 1 +.names 11429 11430 7633 +1- 1 +-1 1 +.names 7633 7634 +1 1 +.names 7623 7635 +1 1 +.names 7623 7636 +1 1 +.names 7630 7637 +1 1 +.names 7640 7638 +1 1 +.names 7638 7639 +1 1 +.names 7642 7640 +0 1 +.names 22315 22316 7641 +1- 1 +-1 1 +.names 7641 7642 +1 1 +.names 7645 7643 +1 1 +.names 7643 7644 +1 1 +.names 7647 7645 +0 1 +.names 22298 22299 7646 +1- 1 +-1 1 +.names 7646 7647 +1 1 +.names 7650 7648 +1 1 +.names 7648 7649 +1 1 +.names 7652 7650 +0 1 +.names 22333 22334 7651 +1- 1 +-1 1 +.names 7651 7652 +1 1 +.names 7655 7653 +1 1 +.names 7653 7654 +1 1 +.names 7657 7655 +0 1 +.names 22367 22368 7656 +1- 1 +-1 1 +.names 7656 7657 +1 1 +.names 7661 7658 +0 1 +.names 7658 7659 +1 1 +.names 22350 22351 7660 +1- 1 +-1 1 +.names 7660 7661 +1 1 +.names 4152 7662 +0 1 +.names 7662 7663 +1 1 +.names 7670 7674 7664 +1- 1 +-1 1 +.names 7664 7665 +1 1 +.names 916 7666 +0 1 +.names 8092 7667 +0 1 +.names 7667 7668 +1 1 +.names 7668 7669 +0 1 +.names 7666 7669 7670 +11 1 +.names 8086 7671 +0 1 +.names 7671 7672 +1 1 +.names 7672 7673 +0 1 +.names 916 7673 7674 +11 1 +.names 7680 7684 7675 +1- 1 +-1 1 +.names 7675 7676 +1 1 +.names 8030 7677 +0 1 +.names 7677 7678 +1 1 +.names 7678 7679 +0 1 +.names 7666 7679 7680 +11 1 +.names 8058 7681 +0 1 +.names 7681 7682 +1 1 +.names 7682 7683 +0 1 +.names 916 7683 7684 +11 1 +.names 7690 7694 7685 +1- 1 +-1 1 +.names 7685 7686 +1 1 +.names 8010 7687 +0 1 +.names 7687 7688 +1 1 +.names 7688 7689 +0 1 +.names 7666 7689 7690 +11 1 +.names 8008 7691 +0 1 +.names 7691 7692 +1 1 +.names 7692 7693 +0 1 +.names 916 7693 7694 +11 1 +.names 7700 7704 7695 +1- 1 +-1 1 +.names 7695 7696 +1 1 +.names 8012 7697 +0 1 +.names 7697 7698 +1 1 +.names 7698 7699 +0 1 +.names 7666 7699 7700 +11 1 +.names 8006 7701 +0 1 +.names 7701 7702 +1 1 +.names 7702 7703 +0 1 +.names 916 7703 7704 +11 1 +.names 7710 7714 7705 +1- 1 +-1 1 +.names 7705 7706 +1 1 +.names 8014 7707 +0 1 +.names 7707 7708 +1 1 +.names 7708 7709 +0 1 +.names 7666 7709 7710 +11 1 +.names 8004 7711 +0 1 +.names 7711 7712 +1 1 +.names 7712 7713 +0 1 +.names 916 7713 7714 +11 1 +.names 7720 7724 7715 +1- 1 +-1 1 +.names 7715 7716 +1 1 +.names 8016 7717 +0 1 +.names 7717 7718 +1 1 +.names 7718 7719 +0 1 +.names 7666 7719 7720 +11 1 +.names 8002 7721 +0 1 +.names 7721 7722 +1 1 +.names 7722 7723 +0 1 +.names 916 7723 7724 +11 1 +.names 7730 7734 7725 +1- 1 +-1 1 +.names 7725 7726 +1 1 +.names 8018 7727 +0 1 +.names 7727 7728 +1 1 +.names 7728 7729 +0 1 +.names 7666 7729 7730 +11 1 +.names 8000 7731 +0 1 +.names 7731 7732 +1 1 +.names 7732 7733 +0 1 +.names 916 7733 7734 +11 1 +.names 7740 7744 7735 +1- 1 +-1 1 +.names 7735 7736 +1 1 +.names 8020 7737 +0 1 +.names 7737 7738 +1 1 +.names 7738 7739 +0 1 +.names 7666 7739 7740 +11 1 +.names 7998 7741 +0 1 +.names 7741 7742 +1 1 +.names 7742 7743 +0 1 +.names 916 7743 7744 +11 1 +.names 7750 7754 7745 +1- 1 +-1 1 +.names 7745 7746 +1 1 +.names 8022 7747 +0 1 +.names 7747 7748 +1 1 +.names 7748 7749 +0 1 +.names 7666 7749 7750 +11 1 +.names 7996 7751 +0 1 +.names 7751 7752 +1 1 +.names 7752 7753 +0 1 +.names 916 7753 7754 +11 1 +.names 7760 7764 7755 +1- 1 +-1 1 +.names 7755 7756 +1 1 +.names 8024 7757 +0 1 +.names 7757 7758 +1 1 +.names 7758 7759 +0 1 +.names 7666 7759 7760 +11 1 +.names 7994 7761 +0 1 +.names 7761 7762 +1 1 +.names 7762 7763 +0 1 +.names 916 7763 7764 +11 1 +.names 7770 7774 7765 +1- 1 +-1 1 +.names 7765 7766 +1 1 +.names 8026 7767 +0 1 +.names 7767 7768 +1 1 +.names 7768 7769 +0 1 +.names 7666 7769 7770 +11 1 +.names 7992 7771 +0 1 +.names 7771 7772 +1 1 +.names 7772 7773 +0 1 +.names 916 7773 7774 +11 1 +.names 7780 7784 7775 +1- 1 +-1 1 +.names 7775 7776 +1 1 +.names 8052 7777 +0 1 +.names 7777 7778 +1 1 +.names 7778 7779 +0 1 +.names 7666 7779 7780 +11 1 +.names 8082 7781 +0 1 +.names 7781 7782 +1 1 +.names 7782 7783 +0 1 +.names 916 7783 7784 +11 1 +.names 7790 7794 7785 +1- 1 +-1 1 +.names 7785 7786 +1 1 +.names 8028 7787 +0 1 +.names 7787 7788 +1 1 +.names 7788 7789 +0 1 +.names 7666 7789 7790 +11 1 +.names 7990 7791 +0 1 +.names 7791 7792 +1 1 +.names 7792 7793 +0 1 +.names 916 7793 7794 +11 1 +.names 7800 7804 7795 +1- 1 +-1 1 +.names 7795 7796 +1 1 +.names 8119 7797 +0 1 +.names 7797 7798 +1 1 +.names 7798 7799 +0 1 +.names 7666 7799 7800 +11 1 +.names 7988 7801 +0 1 +.names 7801 7802 +1 1 +.names 7802 7803 +0 1 +.names 916 7803 7804 +11 1 +.names 7810 7814 7805 +1- 1 +-1 1 +.names 7805 7806 +1 1 +.names 8080 7807 +0 1 +.names 7807 7808 +1 1 +.names 7808 7809 +0 1 +.names 7666 7809 7810 +11 1 +.names 7986 7811 +0 1 +.names 7811 7812 +1 1 +.names 7812 7813 +0 1 +.names 916 7813 7814 +11 1 +.names 7820 7824 7815 +1- 1 +-1 1 +.names 7815 7816 +1 1 +.names 8078 7817 +0 1 +.names 7817 7818 +1 1 +.names 7818 7819 +0 1 +.names 7666 7819 7820 +11 1 +.names 7984 7821 +0 1 +.names 7821 7822 +1 1 +.names 7822 7823 +0 1 +.names 916 7823 7824 +11 1 +.names 7830 7834 7825 +1- 1 +-1 1 +.names 7825 7826 +1 1 +.names 8076 7827 +0 1 +.names 7827 7828 +1 1 +.names 7828 7829 +0 1 +.names 7666 7829 7830 +11 1 +.names 7982 7831 +0 1 +.names 7831 7832 +1 1 +.names 7832 7833 +0 1 +.names 916 7833 7834 +11 1 +.names 7840 7844 7835 +1- 1 +-1 1 +.names 7835 7836 +1 1 +.names 8074 7837 +0 1 +.names 7837 7838 +1 1 +.names 7838 7839 +0 1 +.names 7666 7839 7840 +11 1 +.names 7980 7841 +0 1 +.names 7841 7842 +1 1 +.names 7842 7843 +0 1 +.names 916 7843 7844 +11 1 +.names 7850 7854 7845 +1- 1 +-1 1 +.names 7845 7846 +1 1 +.names 8072 7847 +0 1 +.names 7847 7848 +1 1 +.names 7848 7849 +0 1 +.names 7666 7849 7850 +11 1 +.names 7978 7851 +0 1 +.names 7851 7852 +1 1 +.names 7852 7853 +0 1 +.names 916 7853 7854 +11 1 +.names 7860 7864 7855 +1- 1 +-1 1 +.names 7855 7856 +1 1 +.names 8068 7857 +0 1 +.names 7857 7858 +1 1 +.names 7858 7859 +0 1 +.names 7666 7859 7860 +11 1 +.names 8044 7861 +0 1 +.names 7861 7862 +1 1 +.names 7862 7863 +0 1 +.names 916 7863 7864 +11 1 +.names 7870 7874 7865 +1- 1 +-1 1 +.names 7865 7866 +1 1 +.names 8070 7867 +0 1 +.names 7867 7868 +1 1 +.names 7868 7869 +0 1 +.names 7666 7869 7870 +11 1 +.names 8042 7871 +0 1 +.names 7871 7872 +1 1 +.names 7872 7873 +0 1 +.names 916 7873 7874 +11 1 +.names 7880 7884 7875 +1- 1 +-1 1 +.names 7875 7876 +1 1 +.names 8090 7877 +0 1 +.names 7877 7878 +1 1 +.names 7878 7879 +0 1 +.names 7666 7879 7880 +11 1 +.names 8040 7881 +0 1 +.names 7881 7882 +1 1 +.names 7882 7883 +0 1 +.names 916 7883 7884 +11 1 +.names 7890 7894 7885 +1- 1 +-1 1 +.names 7885 7886 +1 1 +.names 8050 7887 +0 1 +.names 7887 7888 +1 1 +.names 7888 7889 +0 1 +.names 7666 7889 7890 +11 1 +.names 8084 7891 +0 1 +.names 7891 7892 +1 1 +.names 7892 7893 +0 1 +.names 916 7893 7894 +11 1 +.names 7900 7904 7895 +1- 1 +-1 1 +.names 7895 7896 +1 1 +.names 8088 7897 +0 1 +.names 7897 7898 +1 1 +.names 7898 7899 +0 1 +.names 7666 7899 7900 +11 1 +.names 8038 7901 +0 1 +.names 7901 7902 +1 1 +.names 7902 7903 +0 1 +.names 916 7903 7904 +11 1 +.names 7910 7914 7905 +1- 1 +-1 1 +.names 7905 7906 +1 1 +.names 8115 7907 +0 1 +.names 7907 7908 +1 1 +.names 7908 7909 +0 1 +.names 7666 7909 7910 +11 1 +.names 8136 7911 +0 1 +.names 7911 7912 +1 1 +.names 7912 7913 +0 1 +.names 916 7913 7914 +11 1 +.names 7920 7924 7915 +1- 1 +-1 1 +.names 7915 7916 +1 1 +.names 8048 7917 +0 1 +.names 7917 7918 +1 1 +.names 7918 7919 +0 1 +.names 7666 7919 7920 +11 1 +.names 8054 7921 +0 1 +.names 7921 7922 +1 1 +.names 7922 7923 +0 1 +.names 916 7923 7924 +11 1 +.names 7930 7934 7925 +1- 1 +-1 1 +.names 7925 7926 +1 1 +.names 8046 7927 +0 1 +.names 7927 7928 +1 1 +.names 7928 7929 +0 1 +.names 7666 7929 7930 +11 1 +.names 8056 7931 +0 1 +.names 7931 7932 +1 1 +.names 7932 7933 +0 1 +.names 916 7933 7934 +11 1 +.names 7940 7944 7935 +1- 1 +-1 1 +.names 7935 7936 +1 1 +.names 8036 7937 +0 1 +.names 7937 7938 +1 1 +.names 7938 7939 +0 1 +.names 7666 7939 7940 +11 1 +.names 8066 7941 +0 1 +.names 7941 7942 +1 1 +.names 7942 7943 +0 1 +.names 916 7943 7944 +11 1 +.names 7950 7954 7945 +1- 1 +-1 1 +.names 7945 7946 +1 1 +.names 8034 7947 +0 1 +.names 7947 7948 +1 1 +.names 7948 7949 +0 1 +.names 7666 7949 7950 +11 1 +.names 8064 7951 +0 1 +.names 7951 7952 +1 1 +.names 7952 7953 +0 1 +.names 916 7953 7954 +11 1 +.names 7960 7964 7955 +1- 1 +-1 1 +.names 7955 7956 +1 1 +.names 8032 7957 +0 1 +.names 7957 7958 +1 1 +.names 7958 7959 +0 1 +.names 7666 7959 7960 +11 1 +.names 8062 7961 +0 1 +.names 7961 7962 +1 1 +.names 7962 7963 +0 1 +.names 916 7963 7964 +11 1 +.names 7970 7974 7965 +1- 1 +-1 1 +.names 7965 7966 +1 1 +.names 8107 7967 +0 1 +.names 7967 7968 +1 1 +.names 7968 7969 +0 1 +.names 7666 7969 7970 +11 1 +.names 8060 7971 +0 1 +.names 7971 7972 +1 1 +.names 7972 7973 +0 1 +.names 916 7973 7974 +11 1 +.names 7663 7975 +1 1 +.names 7975 7976 +1 1 +.names 13683 13687 7977 +1- 1 +-1 1 +.names 7977 7978 +1 1 +.names 13800 13801 7979 +1- 1 +-1 1 +.names 7979 7980 +1 1 +.names 13695 13699 7981 +1- 1 +-1 1 +.names 7981 7982 +1 1 +.names 13702 13703 7983 +1- 1 +-1 1 +.names 7983 7984 +1 1 +.names 13712 13713 7985 +1- 1 +-1 1 +.names 7985 7986 +1 1 +.names 13716 13717 7987 +1- 1 +-1 1 +.names 7987 7988 +1 1 +.names 13804 13805 7989 +1- 1 +-1 1 +.names 7989 7990 +1 1 +.names 13810 13811 7991 +1- 1 +-1 1 +.names 7991 7992 +1 1 +.names 13836 13837 7993 +1- 1 +-1 1 +.names 7993 7994 +1 1 +.names 13688 13689 7995 +1- 1 +-1 1 +.names 7995 7996 +1 1 +.names 13714 13715 7997 +1- 1 +-1 1 +.names 7997 7998 +1 1 +.names 13690 13691 7999 +1- 1 +-1 1 +.names 7999 8000 +1 1 +.names 13707 13711 8001 +1- 1 +-1 1 +.names 8001 8002 +1 1 +.names 13700 13701 8003 +1- 1 +-1 1 +.names 8003 8004 +1 1 +.names 13814 13815 8005 +1- 1 +-1 1 +.names 8005 8006 +1 1 +.names 13818 13819 8007 +1- 1 +-1 1 +.names 8007 8008 +1 1 +.names 13735 13739 8009 +1- 1 +-1 1 +.names 8009 8010 +1 1 +.names 13753 13757 8011 +1- 1 +-1 1 +.names 8011 8012 +1 1 +.names 13521 13525 8013 +1- 1 +-1 1 +.names 8013 8014 +1 1 +.names 13529 13533 8015 +1- 1 +-1 1 +.names 8015 8016 +1 1 +.names 13537 13541 8017 +1- 1 +-1 1 +.names 8017 8018 +1 1 +.names 13545 13549 8019 +1- 1 +-1 1 +.names 8019 8020 +1 1 +.names 13806 13807 8021 +1- 1 +-1 1 +.names 8021 8022 +1 1 +.names 13553 13557 8023 +1- 1 +-1 1 +.names 8023 8024 +1 1 +.names 13787 13791 8025 +1- 1 +-1 1 +.names 8025 8026 +1 1 +.names 13777 13781 8027 +1- 1 +-1 1 +.names 8027 8028 +1 1 +.names 13513 13517 8029 +1- 1 +-1 1 +.names 8029 8030 +1 1 +.names 13720 13721 8031 +1- 1 +-1 1 +.names 8031 8032 +1 1 +.names 13727 13731 8033 +1- 1 +-1 1 +.names 8033 8034 +1 1 +.names 13722 13723 8035 +1- 1 +-1 1 +.names 8035 8036 +1 1 +.names 13760 13761 8037 +1- 1 +-1 1 +.names 8037 8038 +1 1 +.names 13762 13763 8039 +1- 1 +-1 1 +.names 8039 8040 +1 1 +.names 13718 13719 8041 +1- 1 +-1 1 +.names 8041 8042 +1 1 +.names 13745 13749 8043 +1- 1 +-1 1 +.names 8043 8044 +1 1 +.names 13758 13759 8045 +1- 1 +-1 1 +.names 8045 8046 +1 1 +.names 13649 13653 8047 +1- 1 +-1 1 +.names 8047 8048 +1 1 +.names 13633 13637 8049 +1- 1 +-1 1 +.names 8049 8050 +1 1 +.names 13561 13565 8051 +1- 1 +-1 1 +.names 8051 8052 +1 1 +.names 13826 13827 8053 +1- 1 +-1 1 +.names 8053 8054 +1 1 +.names 13822 13823 8055 +1- 1 +-1 1 +.names 8055 8056 +1 1 +.names 13772 13773 8057 +1- 1 +-1 1 +.names 8057 8058 +1 1 +.names 13820 13821 8059 +1- 1 +-1 1 +.names 8059 8060 +1 1 +.names 13828 13829 8061 +1- 1 +-1 1 +.names 8061 8062 +1 1 +.names 13782 13783 8063 +1- 1 +-1 1 +.names 8063 8064 +1 1 +.names 13824 13825 8065 +1- 1 +-1 1 +.names 8065 8066 +1 1 +.names 13609 13613 8067 +1- 1 +-1 1 +.names 8067 8068 +1 1 +.names 13617 13621 8069 +1- 1 +-1 1 +.names 8069 8070 +1 1 +.names 13601 13605 8071 +1- 1 +-1 1 +.names 8071 8072 +1 1 +.names 13593 13597 8073 +1- 1 +-1 1 +.names 8073 8074 +1 1 +.names 13585 13589 8075 +1- 1 +-1 1 +.names 8075 8076 +1 1 +.names 13577 13581 8077 +1- 1 +-1 1 +.names 8077 8078 +1 1 +.names 13569 13573 8079 +1- 1 +-1 1 +.names 8079 8080 +1 1 +.names 13796 13797 8081 +1- 1 +-1 1 +.names 8081 8082 +1 1 +.names 13830 13831 8083 +1- 1 +-1 1 +.names 8083 8084 +1 1 +.names 13794 13795 8085 +1- 1 +-1 1 +.names 8085 8086 +1 1 +.names 13641 13645 8087 +1- 1 +-1 1 +.names 8087 8088 +1 1 +.names 13625 13629 8089 +1- 1 +-1 1 +.names 8089 8090 +1 1 +.names 13505 13509 8091 +1- 1 +-1 1 +.names 8091 8092 +1 1 +.names 8097 8098 8093 +1- 1 +-1 1 +.names 8093 8094 +1 1 +.names 32869 32872 8095 +1- 1 +-1 1 +.names 8095 8096 +1 1 +.names 8096 8097 +0 1 +.names 4100 8098 +0 1 +.names 8102 8099 +0 1 +.names 8099 8100 +1 1 +.names 8104 8105 8101 +11 1 +.names 8101 8102 +1 1 +.names 7663 8103 +1 1 +.names 8103 8104 +0 1 +.names 8094 8105 +0 1 +.names 13657 13661 8106 +1- 1 +-1 1 +.names 8106 8107 +1 1 +.names 8110 8108 +0 1 +.names 8108 8109 +1 1 +.names 8100 8110 +1 1 +.names 8109 8111 +1 1 +.names 8109 8112 +1 1 +.names 8100 8113 +1 1 +.names 13767 13771 8114 +1- 1 +-1 1 +.names 8114 8115 +1 1 +.names 8100 8116 +1 1 +.names 8100 8117 +1 1 +.names 13675 13679 8118 +1- 1 +-1 1 +.names 8118 8119 +1 1 +.names 8109 8120 +1 1 +.names 8124 8121 +0 1 +.names 8121 8122 +1 1 +.names 13665 13669 8123 +1- 1 +-1 1 +.names 8123 8124 +1 1 +.names 8128 8125 +0 1 +.names 8125 8126 +1 1 +.names 13832 13833 8127 +1- 1 +-1 1 +.names 8127 8128 +1 1 +.names 8132 8134 8129 +1- 1 +-1 1 +.names 8129 8130 +1 1 +.names 8122 8131 +0 1 +.names 7666 8131 8132 +11 1 +.names 8126 8133 +0 1 +.names 916 8133 8134 +11 1 +.names 13740 13741 8135 +1- 1 +-1 1 +.names 8135 8136 +1 1 +.names 8140 8137 +0 1 +.names 8137 8138 +1 1 +.names 22384 22385 8139 +1- 1 +-1 1 +.names 8139 8140 +1 1 +.names 8143 8141 +1 1 +.names 8141 8142 +1 1 +.names 8145 8143 +1 1 +.names 8141 8144 +1 1 +.names 8147 8145 +0 1 +.names 14301 14304 8146 +1- 1 +-1 1 +.names 8146 8147 +1 1 +.names 8151 8148 +0 1 +.names 8148 8149 +1 1 +.names 1783 14305 8150 +1- 1 +-1 1 +.names 8150 8151 +1 1 +.names 8149 8152 +1 1 +.names 8149 8153 +1 1 +.names 8149 8154 +1 1 +.names 8157 8155 +1 1 +.names 8155 8156 +1 1 +.names 8177 8157 +0 1 +.names 8157 8158 +1 1 +.names 8158 8159 +1 1 +.names 8163 8160 +0 1 +.names 8160 8161 +1 1 +.names 8175 8162 +0 1 +.names 8162 8163 +1 1 +.names 8167 8164 +0 1 +.names 8164 8165 +1 1 +.names 14314 14315 8166 +1- 1 +-1 1 +.names 8166 8167 +1 1 +.names 8171 8168 +0 1 +.names 8168 8169 +1 1 +.names 8156 8170 +0 1 +.names 8170 8171 +1 1 +.names 8164 8172 +1 1 +.names 8143 8173 +1 1 +.names 8149 8174 +1 1 +.names 8172 8175 +1 1 +.names 14326 14313 8176 +1- 1 +-1 1 +.names 8176 8177 +1 1 +.names 8158 8178 +1 1 +.names 8158 8179 +1 1 +.names 8143 8180 +1 1 +.names 917 8181 +1 1 +.names 8165 8182 +1 1 +.names 8165 8183 +1 1 +.names 8165 8184 +1 1 +.names 8187 8185 +1 1 +.names 8185 8186 +1 1 +.names 8189 8187 +1 1 +.names 8185 8188 +1 1 +.names 8191 8189 +0 1 +.names 14329 14332 8190 +1- 1 +-1 1 +.names 8190 8191 +1 1 +.names 8195 8192 +0 1 +.names 8192 8193 +1 1 +.names 1783 14333 8194 +1- 1 +-1 1 +.names 8194 8195 +1 1 +.names 8193 8196 +1 1 +.names 8193 8197 +1 1 +.names 8193 8198 +1 1 +.names 8201 8199 +1 1 +.names 8199 8200 +1 1 +.names 8221 8201 +0 1 +.names 8201 8202 +1 1 +.names 8202 8203 +1 1 +.names 8207 8204 +0 1 +.names 8204 8205 +1 1 +.names 8219 8206 +0 1 +.names 8206 8207 +1 1 +.names 8211 8208 +0 1 +.names 8208 8209 +1 1 +.names 14342 14343 8210 +1- 1 +-1 1 +.names 8210 8211 +1 1 +.names 8215 8212 +0 1 +.names 8212 8213 +1 1 +.names 8200 8214 +0 1 +.names 8214 8215 +1 1 +.names 8208 8216 +1 1 +.names 8187 8217 +1 1 +.names 8193 8218 +1 1 +.names 8216 8219 +1 1 +.names 14354 14341 8220 +1- 1 +-1 1 +.names 8220 8221 +1 1 +.names 8202 8222 +1 1 +.names 8202 8223 +1 1 +.names 8187 8224 +1 1 +.names 918 8225 +1 1 +.names 8209 8226 +1 1 +.names 8209 8227 +1 1 +.names 8209 8228 +1 1 +.names 8232 8229 +0 1 +.names 8229 8230 +1 1 +.names 984 8231 +0 1 +.names 8231 8232 +1 1 +.names 8229 8233 +1 1 +.names 8233 8234 +1 1 +.names 8233 8235 +1 1 +.names 8229 8236 +1 1 +.names 8236 8237 +1 1 +.names 8236 8238 +1 1 +.names 8230 8239 +1 1 +.names 8230 8240 +1 1 +.names 8243 8241 +1 1 +.names 8241 8242 +1 1 +.names 8245 8243 +0 1 +.names 3628 8244 +0 1 +.names 8244 8245 +1 1 +.names 8248 8246 +1 1 +.names 8246 8247 +1 1 +.names 8252 8248 +0 1 +.names 8246 8249 +1 1 +.names 8246 8250 +1 1 +.names 14356 14357 8251 +1- 1 +-1 1 +.names 8251 8252 +1 1 +.names 8241 8253 +1 1 +.names 8241 8254 +1 1 +.names 8248 8255 +1 1 +.names 8258 8256 +1 1 +.names 8256 8257 +1 1 +.names 8286 8258 +0 1 +.names 8256 8259 +1 1 +.names 8256 8260 +1 1 +.names 8263 8261 +1 1 +.names 8261 8262 +1 1 +.names 8266 8263 +0 1 +.names 8261 8264 +1 1 +.names 8272 14365 8265 +1- 1 +-1 1 +.names 8265 8266 +1 1 +.names 8269 8267 +1 1 +.names 8267 8268 +1 1 +.names 8288 8269 +0 1 +.names 8272 8270 +1 1 +.names 8270 8271 +1 1 +.names 8321 8272 +0 1 +.names 8275 8273 +1 1 +.names 8273 8274 +1 1 +.names 8311 8275 +0 1 +.names 8279 8276 +0 1 +.names 8276 8277 +1 1 +.names 14374 14375 8278 +1- 1 +-1 1 +.names 8278 8279 +1 1 +.names 8275 8280 +1 1 +.names 8280 8281 +1 1 +.names 8280 8282 +1 1 +.names 8270 8283 +1 1 +.names 8270 8284 +1 1 +.names 14359 14362 8285 +1- 1 +-1 1 +.names 8285 8286 +1 1 +.names 14393 14378 8287 +1- 1 +-1 1 +.names 8287 8288 +1 1 +.names 8269 8289 +1 1 +.names 8292 8290 +1 1 +.names 8290 8291 +1 1 +.names 8298 8292 +0 1 +.names 8296 8293 +0 1 +.names 8293 8294 +1 1 +.names 8274 8295 +0 1 +.names 8295 8296 +1 1 +.names 14371 14368 8297 +1- 1 +-1 1 +.names 8297 8298 +1 1 +.names 8261 8299 +1 1 +.names 8292 8300 +1 1 +.names 8300 8301 +1 1 +.names 8289 8302 +1 1 +.names 8289 8303 +1 1 +.names 8289 8304 +1 1 +.names 3928 8305 +1 1 +.names 8277 8306 +1 1 +.names 8277 8307 +1 1 +.names 8276 8308 +1 1 +.names 8308 8309 +1 1 +.names 14385 14386 8310 +1- 1 +-1 1 +.names 8310 8311 +1 1 +.names 8300 8312 +1 1 +.names 8300 8313 +1 1 +.names 3918 8314 +1 1 +.names 3920 8315 +1 1 +.names 3925 8316 +1 1 +.names 8292 8317 +1 1 +.names 8256 8318 +1 1 +.names 8317 8319 +1 1 +.names 8305 8320 +0 1 +.names 8320 8321 +1 1 +.names 8317 8322 +1 1 +.names 8325 8323 +1 1 +.names 8323 8324 +1 1 +.names 8327 8325 +1 1 +.names 8323 8326 +1 1 +.names 8329 8327 +0 1 +.names 14396 14399 8328 +1- 1 +-1 1 +.names 8328 8329 +1 1 +.names 8333 8330 +0 1 +.names 8330 8331 +1 1 +.names 1783 14400 8332 +1- 1 +-1 1 +.names 8332 8333 +1 1 +.names 8331 8334 +1 1 +.names 8331 8335 +1 1 +.names 8331 8336 +1 1 +.names 8339 8337 +1 1 +.names 8337 8338 +1 1 +.names 8359 8339 +0 1 +.names 8339 8340 +1 1 +.names 8340 8341 +1 1 +.names 8345 8342 +0 1 +.names 8342 8343 +1 1 +.names 8357 8344 +0 1 +.names 8344 8345 +1 1 +.names 8349 8346 +0 1 +.names 8346 8347 +1 1 +.names 14409 14410 8348 +1- 1 +-1 1 +.names 8348 8349 +1 1 +.names 8353 8350 +0 1 +.names 8350 8351 +1 1 +.names 8338 8352 +0 1 +.names 8352 8353 +1 1 +.names 8346 8354 +1 1 +.names 8325 8355 +1 1 +.names 8331 8356 +1 1 +.names 8354 8357 +1 1 +.names 14421 14408 8358 +1- 1 +-1 1 +.names 8358 8359 +1 1 +.names 8340 8360 +1 1 +.names 8340 8361 +1 1 +.names 8325 8362 +1 1 +.names 919 8363 +1 1 +.names 8347 8364 +1 1 +.names 8347 8365 +1 1 +.names 8347 8366 +1 1 +.names 8369 8367 +1 1 +.names 8367 8368 +1 1 +.names 8397 8369 +0 1 +.names 8367 8370 +1 1 +.names 8367 8371 +1 1 +.names 8374 8372 +1 1 +.names 8372 8373 +1 1 +.names 8377 8374 +0 1 +.names 8372 8375 +1 1 +.names 8383 14429 8376 +1- 1 +-1 1 +.names 8376 8377 +1 1 +.names 8380 8378 +1 1 +.names 8378 8379 +1 1 +.names 8399 8380 +0 1 +.names 8383 8381 +1 1 +.names 8381 8382 +1 1 +.names 8432 8383 +0 1 +.names 8386 8384 +1 1 +.names 8384 8385 +1 1 +.names 8422 8386 +0 1 +.names 8390 8387 +0 1 +.names 8387 8388 +1 1 +.names 14438 14439 8389 +1- 1 +-1 1 +.names 8389 8390 +1 1 +.names 8386 8391 +1 1 +.names 8391 8392 +1 1 +.names 8391 8393 +1 1 +.names 8381 8394 +1 1 +.names 8381 8395 +1 1 +.names 14423 14426 8396 +1- 1 +-1 1 +.names 8396 8397 +1 1 +.names 14456 14442 8398 +1- 1 +-1 1 +.names 8398 8399 +1 1 +.names 8380 8400 +1 1 +.names 8403 8401 +1 1 +.names 8401 8402 +1 1 +.names 8409 8403 +0 1 +.names 8407 8404 +0 1 +.names 8404 8405 +1 1 +.names 8385 8406 +0 1 +.names 8406 8407 +1 1 +.names 14435 14432 8408 +1- 1 +-1 1 +.names 8408 8409 +1 1 +.names 8372 8410 +1 1 +.names 8403 8411 +1 1 +.names 8411 8412 +1 1 +.names 8400 8413 +1 1 +.names 8400 8414 +1 1 +.names 8400 8415 +1 1 +.names 809 8416 +1 1 +.names 8388 8417 +1 1 +.names 8388 8418 +1 1 +.names 8387 8419 +1 1 +.names 8419 8420 +1 1 +.names 14449 2591 8421 +1- 1 +-1 1 +.names 8421 8422 +1 1 +.names 8411 8423 +1 1 +.names 8411 8424 +1 1 +.names 5761 8425 +1 1 +.names 5771 8426 +1 1 +.names 5785 8427 +1 1 +.names 8403 8428 +1 1 +.names 8367 8429 +1 1 +.names 8428 8430 +1 1 +.names 8416 8431 +0 1 +.names 8431 8432 +1 1 +.names 8428 8433 +1 1 +.names 8437 8434 +0 1 +.names 8434 8435 +1 1 +.names 3675 14457 8436 +1- 1 +-1 1 +.names 8436 8437 +1 1 +.names 8441 8438 +0 1 +.names 8438 8439 +1 1 +.names 14460 14461 8440 +1- 1 +-1 1 +.names 8440 8441 +1 1 +.names 8439 8442 +1 1 +.names 8439 8443 +1 1 +.names 8439 8444 +1 1 +.names 8435 8445 +1 1 +.names 8435 8446 +1 1 +.names 8435 8447 +1 1 +.names 8451 8448 +0 1 +.names 8448 8449 +1 1 +.names 3675 8450 +0 1 +.names 8450 8451 +1 1 +.names 8449 8452 +1 1 +.names 8439 8453 +1 1 +.names 8449 8454 +1 1 +.names 8449 8455 +1 1 +.names 8449 8456 +1 1 +.names 8459 8457 +1 1 +.names 8457 8458 +1 1 +.names 8461 8459 +0 1 +.names 2583 8460 +0 1 +.names 8460 8461 +1 1 +.names 8464 8462 +1 1 +.names 8462 8463 +1 1 +.names 8468 8464 +0 1 +.names 8462 8465 +1 1 +.names 8462 8466 +1 1 +.names 14751 2580 8467 +1- 1 +-1 1 +.names 8467 8468 +1 1 +.names 8457 8469 +1 1 +.names 8457 8470 +1 1 +.names 8464 8471 +1 1 +.names 8475 8472 +0 1 +.names 8472 8473 +1 1 +.names 988 8474 +0 1 +.names 8474 8475 +1 1 +.names 8472 8476 +1 1 +.names 8476 8477 +1 1 +.names 8476 8478 +1 1 +.names 8472 8479 +1 1 +.names 8479 8480 +1 1 +.names 8479 8481 +1 1 +.names 8473 8482 +1 1 +.names 8473 8483 +1 1 +.names 8487 8484 +0 1 +.names 8484 8485 +1 1 +.names 2896 8486 +0 1 +.names 8486 8487 +1 1 +.names 8484 8488 +1 1 +.names 8488 8489 +1 1 +.names 8488 8490 +1 1 +.names 8484 8491 +1 1 +.names 8491 8492 +1 1 +.names 8491 8493 +1 1 +.names 8485 8494 +1 1 +.names 8485 8495 +1 1 +.names 8499 8496 +0 1 +.names 8496 8497 +1 1 +.names 890 8498 +0 1 +.names 8498 8499 +1 1 +.names 8496 8500 +1 1 +.names 8500 8501 +1 1 +.names 8500 8502 +1 1 +.names 8496 8503 +1 1 +.names 8503 8504 +1 1 +.names 8503 8505 +1 1 +.names 8497 8506 +1 1 +.names 8497 8507 +1 1 +.names 8511 8508 +0 1 +.names 8508 8509 +1 1 +.names 989 8510 +0 1 +.names 8510 8511 +1 1 +.names 8508 8512 +1 1 +.names 8512 8513 +1 1 +.names 8512 8514 +1 1 +.names 8508 8515 +1 1 +.names 8515 8516 +1 1 +.names 8515 8517 +1 1 +.names 8509 8518 +1 1 +.names 8509 8519 +1 1 +.names 8522 8520 +1 1 +.names 8520 8521 +1 1 +.names 8524 8522 +0 1 +.names 732 8523 +0 1 +.names 8523 8524 +1 1 +.names 8527 8525 +1 1 +.names 8525 8526 +1 1 +.names 8531 8527 +0 1 +.names 8525 8528 +1 1 +.names 8525 8529 +1 1 +.names 14753 14754 8530 +1- 1 +-1 1 +.names 8530 8531 +1 1 +.names 8520 8532 +1 1 +.names 8520 8533 +1 1 +.names 8527 8534 +1 1 +.names 8537 8535 +0 1 +.names 8535 8536 +1 1 +.names 1982 8537 +1 1 +.names 8535 8538 +1 1 +.names 8538 8539 +1 1 +.names 8538 8540 +1 1 +.names 8535 8541 +1 1 +.names 8541 8542 +1 1 +.names 8541 8543 +1 1 +.names 8536 8544 +1 1 +.names 8536 8545 +1 1 +.names 8549 8546 +0 1 +.names 8546 8547 +1 1 +.names 991 8548 +0 1 +.names 8548 8549 +1 1 +.names 8546 8550 +1 1 +.names 8550 8551 +1 1 +.names 8550 8552 +1 1 +.names 8546 8553 +1 1 +.names 8553 8554 +1 1 +.names 8553 8555 +1 1 +.names 8547 8556 +1 1 +.names 8547 8557 +1 1 +.names 2354 2360 8558 +1- 1 +-1 1 +.names 8558 8559 +1 1 +.names 920 8559 57106 +11 1 +.names 921 8561 +0 1 +.names 8561 8562 +1 1 +.names 2228 57107 +0 1 +.names 4 3 8564 +11 1 +.names 8564 8565 +1 1 +.names 8565 2 8566 +11 1 +.names 8566 8567 +1 1 +.names 8567 1 8568 +11 1 +.names 8568 8569 +1 1 +.names 4 3 8570 +11 1 +.names 8570 8571 +1 1 +.names 8571 2 8572 +11 1 +.names 8572 8573 +1 1 +.names 8573 1 8574 +11 1 +.names 8574 8575 +1 1 +.names 922 8576 +0 1 +.names 8576 8577 +1 1 +.names 923 8577 8578 +11 1 +.names 8578 8579 +1 1 +.names 8576 8580 +1 1 +.names 2348 2354 8581 +1- 1 +-1 1 +.names 8581 8582 +1 1 +.names 8562 8583 +0 1 +.names 8583 8584 +1 1 +.names 926 8585 +0 1 +.names 8585 8586 +1 1 +.names 927 8587 +0 1 +.names 8587 8588 +1 1 +.names 928 8589 +0 1 +.names 8589 8590 +1 1 +.names 8590 8588 8591 +11 1 +.names 8591 8592 +1 1 +.names 8592 8586 8593 +11 1 +.names 8593 8594 +1 1 +.names 8594 8584 8595 +11 1 +.names 8595 8596 +1 1 +.names 926 8562 8597 +11 1 +.names 8597 8598 +1 1 +.names 8598 8596 8599 +1- 1 +-1 1 +.names 8599 8600 +1 1 +.names 8587 8601 +1 1 +.names 8589 8602 +1 1 +.names 929 8602 8603 +11 1 +.names 8603 8604 +1 1 +.names 8604 8601 8605 +11 1 +.names 8605 8606 +1 1 +.names 8606 8600 8607 +1- 1 +-1 1 +.names 8607 8608 +1 1 +.names 928 8562 8609 +11 1 +.names 8609 8610 +1 1 +.names 8610 8608 8611 +1- 1 +-1 1 +.names 8611 8612 +1 1 +.names 928 926 8613 +11 1 +.names 8613 8614 +1 1 +.names 8614 8612 8615 +1- 1 +-1 1 +.names 8615 8616 +1 1 +.names 927 8562 8617 +11 1 +.names 8617 8618 +1 1 +.names 8618 8616 8619 +1- 1 +-1 1 +.names 8619 8620 +1 1 +.names 927 926 8621 +11 1 +.names 8621 8622 +1 1 +.names 8583 8623 +1 1 +.names 8587 8624 +1 1 +.names 8589 8625 +1 1 +.names 929 8626 +0 1 +.names 8626 8627 +1 1 +.names 8627 8625 8628 +11 1 +.names 8628 8629 +1 1 +.names 8629 8624 8630 +11 1 +.names 8630 8631 +1 1 +.names 8631 926 8632 +11 1 +.names 8632 8633 +1 1 +.names 8583 8634 +1 1 +.names 8585 8635 +1 1 +.names 8589 8636 +1 1 +.names 929 8636 8637 +11 1 +.names 8637 8638 +1 1 +.names 8638 927 8639 +11 1 +.names 8639 8640 +1 1 +.names 8640 8635 8641 +11 1 +.names 8641 8642 +1 1 +.names 8583 8643 +1 1 +.names 8585 8644 +1 1 +.names 8587 8645 +1 1 +.names 8626 8646 +1 1 +.names 8646 928 8647 +11 1 +.names 8647 8648 +1 1 +.names 8648 8645 8649 +11 1 +.names 8649 8650 +1 1 +.names 8650 8644 8651 +11 1 +.names 8651 8652 +1 1 +.names 8583 8653 +1 1 +.names 8585 8654 +1 1 +.names 8589 8655 +1 1 +.names 8626 8656 +1 1 +.names 8656 8655 8657 +11 1 +.names 8657 8658 +1 1 +.names 8658 927 8659 +11 1 +.names 8659 8660 +1 1 +.names 8660 8654 8661 +11 1 +.names 8661 8662 +1 1 +.names 8583 8663 +1 1 +.names 8585 8664 +1 1 +.names 8587 8665 +1 1 +.names 929 928 8666 +11 1 +.names 8666 8667 +1 1 +.names 8667 8665 8668 +11 1 +.names 8668 8669 +1 1 +.names 8669 8664 8670 +11 1 +.names 8670 8671 +1 1 +.names 8583 8672 +1 1 +.names 8585 8673 +1 1 +.names 8626 8674 +1 1 +.names 8674 928 8675 +11 1 +.names 8675 8676 +1 1 +.names 8676 927 8677 +11 1 +.names 8677 8678 +1 1 +.names 8678 8673 8679 +11 1 +.names 8679 8680 +1 1 +.names 8583 8681 +1 1 +.names 8585 8682 +1 1 +.names 929 928 8683 +11 1 +.names 8683 8684 +1 1 +.names 8684 927 8685 +11 1 +.names 8685 8686 +1 1 +.names 8686 8682 8687 +11 1 +.names 8687 8688 +1 1 +.names 8585 8689 +1 1 +.names 8587 8690 +1 1 +.names 8589 8691 +1 1 +.names 8626 8692 +1 1 +.names 8692 8691 8693 +11 1 +.names 8693 8694 +1 1 +.names 8694 8690 8695 +11 1 +.names 8695 8696 +1 1 +.names 8696 8689 8697 +11 1 +.names 8697 8698 +1 1 +.names 8583 8699 +1 1 +.names 8585 8700 +1 1 +.names 929 928 8701 +11 1 +.names 8701 8702 +1 1 +.names 8702 927 8703 +11 1 +.names 8703 8704 +1 1 +.names 8704 8700 8705 +11 1 +.names 8705 8706 +1 1 +.names 8706 8699 8707 +11 1 +.names 8707 8708 +1 1 +.names 8583 8709 +1 1 +.names 8585 8710 +1 1 +.names 8587 8711 +1 1 +.names 929 928 8712 +11 1 +.names 8712 8713 +1 1 +.names 8713 8711 8714 +11 1 +.names 8714 8715 +1 1 +.names 8715 8710 8716 +11 1 +.names 8716 8717 +1 1 +.names 8717 8709 8718 +11 1 +.names 8718 8719 +1 1 +.names 8719 8708 8720 +1- 1 +-1 1 +.names 8720 8721 +1 1 +.names 8721 57108 +0 1 +.names 8583 8723 +1 1 +.names 8585 8724 +1 1 +.names 8589 8725 +1 1 +.names 8626 8726 +1 1 +.names 8726 8725 8727 +11 1 +.names 8727 8728 +1 1 +.names 8728 927 8729 +11 1 +.names 8729 8730 +1 1 +.names 8730 8724 8731 +11 1 +.names 8731 8732 +1 1 +.names 8732 8723 8733 +11 1 +.names 8733 8734 +1 1 +.names 8583 8735 +1 1 +.names 8585 8736 +1 1 +.names 8587 8737 +1 1 +.names 929 928 8738 +11 1 +.names 8738 8739 +1 1 +.names 8739 8737 8740 +11 1 +.names 8740 8741 +1 1 +.names 8741 8736 8742 +11 1 +.names 8742 8743 +1 1 +.names 8743 8735 8744 +11 1 +.names 8744 8745 +1 1 +.names 8745 930 8746 +11 1 +.names 8746 8747 +1 1 +.names 8583 8748 +1 1 +.names 8585 8749 +1 1 +.names 8626 8750 +1 1 +.names 8750 928 8751 +11 1 +.names 8751 8752 +1 1 +.names 8752 927 8753 +11 1 +.names 8753 8754 +1 1 +.names 8754 8749 8755 +11 1 +.names 8755 8756 +1 1 +.names 8756 8748 8757 +11 1 +.names 8757 8758 +1 1 +.names 8758 931 8759 +11 1 +.names 8759 8760 +1 1 +.names 932 8761 +0 1 +.names 8761 8762 +1 1 +.names 8583 8763 +1 1 +.names 8585 8764 +1 1 +.names 929 928 8765 +11 1 +.names 8765 8766 +1 1 +.names 8766 927 8767 +11 1 +.names 8767 8768 +1 1 +.names 8768 8764 8769 +11 1 +.names 8769 8770 +1 1 +.names 8770 8763 8771 +11 1 +.names 8771 8772 +1 1 +.names 8772 8762 8773 +11 1 +.names 8773 8774 +1 1 +.names 8774 8760 8775 +1- 1 +-1 1 +.names 8775 8776 +1 1 +.names 8776 8747 8777 +1- 1 +-1 1 +.names 8777 8778 +1 1 +.names 8778 8734 57109 +1- 1 +-1 1 +.names 716 720 8780 +1- 1 +-1 1 +.names 8780 8781 +1 1 +.names 56769 8782 +0 1 +.names 8782 8783 +1 1 +.names 56416 8784 +0 1 +.names 8784 8785 +1 1 +.names 56415 8786 +0 1 +.names 8786 8787 +1 1 +.names 56414 8788 +0 1 +.names 8788 8789 +1 1 +.names 8789 8787 8790 +11 1 +.names 8790 8791 +1 1 +.names 8791 8785 8792 +11 1 +.names 8792 8793 +1 1 +.names 8793 8783 8794 +11 1 +.names 8794 8795 +1 1 +.names 8795 2228 8796 +11 1 +.names 8796 8797 +1 1 +.names 8797 8798 +0 1 +.names 8798 8799 +1 1 +.names 8799 8781 8800 +11 1 +.names 8800 8801 +1 1 +.names 8801 933 57110 +11 1 +.names 8585 8803 +1 1 +.names 8587 8804 +1 1 +.names 8589 8805 +1 1 +.names 8626 8806 +1 1 +.names 8806 8805 8807 +11 1 +.names 8807 8808 +1 1 +.names 8808 8804 8809 +11 1 +.names 8809 8810 +1 1 +.names 8810 8803 8811 +11 1 +.names 8811 8812 +1 1 +.names 8812 8562 8813 +11 1 +.names 8813 8814 +1 1 +.names 4171 4169 8815 +1- 1 +-1 1 +.names 8815 8816 +1 1 +.names 8816 4167 8817 +1- 1 +-1 1 +.names 8817 8818 +1 1 +.names 8818 8819 +0 1 +.names 8819 8820 +1 1 +.names 8820 8814 8821 +11 1 +.names 8821 8822 +1 1 +.names 8583 8823 +1 1 +.names 8587 8824 +1 1 +.names 8589 8825 +1 1 +.names 8626 8826 +1 1 +.names 8826 8825 8827 +11 1 +.names 8827 8828 +1 1 +.names 8828 8824 8829 +11 1 +.names 8829 8830 +1 1 +.names 8830 926 8831 +11 1 +.names 8831 8832 +1 1 +.names 8832 8823 8833 +11 1 +.names 8833 8834 +1 1 +.names 8583 8835 +1 1 +.names 8585 8836 +1 1 +.names 8587 8837 +1 1 +.names 929 928 8838 +11 1 +.names 8838 8839 +1 1 +.names 8839 8837 8840 +11 1 +.names 8840 8841 +1 1 +.names 8841 8836 8842 +11 1 +.names 8842 8843 +1 1 +.names 8843 8835 8844 +11 1 +.names 8844 8845 +1 1 +.names 8583 8846 +1 1 +.names 8585 8847 +1 1 +.names 8589 8848 +1 1 +.names 929 8848 8849 +11 1 +.names 8849 8850 +1 1 +.names 8850 927 8851 +11 1 +.names 8851 8852 +1 1 +.names 8852 8847 8853 +11 1 +.names 8853 8854 +1 1 +.names 8854 8846 8855 +11 1 +.names 8855 8856 +1 1 +.names 8856 8845 8857 +1- 1 +-1 1 +.names 8857 8858 +1 1 +.names 8858 8834 8859 +1- 1 +-1 1 +.names 8859 8860 +1 1 +.names 8860 8822 57111 +1- 1 +-1 1 +.names 8583 8862 +1 1 +.names 8585 8863 +1 1 +.names 929 928 8864 +11 1 +.names 8864 8865 +1 1 +.names 8865 927 8866 +11 1 +.names 8866 8867 +1 1 +.names 8867 8863 8868 +11 1 +.names 8868 8869 +1 1 +.names 8869 8862 8870 +11 1 +.names 8870 8871 +1 1 +.names 8871 720 57112 +11 1 +.names 8583 8873 +1 1 +.names 8585 8874 +1 1 +.names 929 928 8875 +11 1 +.names 8875 8876 +1 1 +.names 8876 927 8877 +11 1 +.names 8877 8878 +1 1 +.names 8878 8874 8879 +11 1 +.names 8879 8880 +1 1 +.names 8880 8873 8881 +11 1 +.names 8881 8882 +1 1 +.names 8882 716 57113 +11 1 +.names 8583 8884 +1 1 +.names 8585 8885 +1 1 +.names 929 928 8886 +11 1 +.names 8886 8887 +1 1 +.names 8887 927 8888 +11 1 +.names 8888 8889 +1 1 +.names 8889 8885 8890 +11 1 +.names 8890 8891 +1 1 +.names 8891 8884 8892 +11 1 +.names 8892 8893 +1 1 +.names 8893 715 57114 +11 1 +.names 57131 8895 +1 1 +.names 934 933 8896 +1- 1 +-1 1 +.names 8896 8897 +1 1 +.names 8897 8895 57115 +1- 1 +-1 1 +.names 8583 8899 +1 1 +.names 8585 8900 +1 1 +.names 929 928 8901 +11 1 +.names 8901 8902 +1 1 +.names 8902 927 8903 +11 1 +.names 8903 8904 +1 1 +.names 8904 8900 8905 +11 1 +.names 8905 8906 +1 1 +.names 8906 8899 8907 +11 1 +.names 8907 8908 +1 1 +.names 57131 8909 +1 1 +.names 8909 8908 57116 +1- 1 +-1 1 +.names 57131 8911 +1 1 +.names 8585 8912 +1 1 +.names 8587 8913 +1 1 +.names 8589 8914 +1 1 +.names 8626 8915 +1 1 +.names 8915 8914 8916 +11 1 +.names 8916 8917 +1 1 +.names 8917 8913 8918 +11 1 +.names 8918 8919 +1 1 +.names 8919 8912 8920 +11 1 +.names 8920 8921 +1 1 +.names 8921 8562 8922 +11 1 +.names 8922 8923 +1 1 +.names 8923 8911 57117 +1- 1 +-1 1 +.names 57131 8925 +1 1 +.names 8585 8926 +1 1 +.names 8587 8927 +1 1 +.names 8589 8928 +1 1 +.names 8626 8929 +1 1 +.names 8929 8928 8930 +11 1 +.names 8930 8931 +1 1 +.names 8931 8927 8932 +11 1 +.names 8932 8933 +1 1 +.names 8933 8926 8934 +11 1 +.names 8934 8935 +1 1 +.names 8935 8562 8936 +11 1 +.names 8936 8937 +1 1 +.names 8937 8925 57118 +1- 1 +-1 1 +.names 57131 8939 +1 1 +.names 8585 8940 +1 1 +.names 8587 8941 +1 1 +.names 8589 8942 +1 1 +.names 8626 8943 +1 1 +.names 8943 8942 8944 +11 1 +.names 8944 8945 +1 1 +.names 8945 8941 8946 +11 1 +.names 8946 8947 +1 1 +.names 8947 8940 8948 +11 1 +.names 8948 8949 +1 1 +.names 8949 8562 8950 +11 1 +.names 8950 8951 +1 1 +.names 8951 8939 57119 +1- 1 +-1 1 +.names 8583 8953 +1 1 +.names 8585 8954 +1 1 +.names 929 928 8955 +11 1 +.names 8955 8956 +1 1 +.names 8956 927 8957 +11 1 +.names 8957 8958 +1 1 +.names 8958 8954 8959 +11 1 +.names 8959 8960 +1 1 +.names 8960 8953 8961 +11 1 +.names 8961 8962 +1 1 +.names 8962 715 57120 +1- 1 +-1 1 +.names 8583 8964 +1 1 +.names 8585 8965 +1 1 +.names 929 928 8966 +11 1 +.names 8966 8967 +1 1 +.names 8967 927 8968 +11 1 +.names 8968 8969 +1 1 +.names 8969 8965 8970 +11 1 +.names 8970 8971 +1 1 +.names 8971 8964 57121 +11 1 +.names 8583 8973 +1 1 +.names 8585 8974 +1 1 +.names 929 928 8975 +11 1 +.names 8975 8976 +1 1 +.names 8976 927 8977 +11 1 +.names 8977 8978 +1 1 +.names 8978 8974 8979 +11 1 +.names 8979 8980 +1 1 +.names 8980 8973 57122 +11 1 +.names 8583 8982 +1 1 +.names 8585 8983 +1 1 +.names 929 928 8984 +11 1 +.names 8984 8985 +1 1 +.names 8985 927 8986 +11 1 +.names 8986 8987 +1 1 +.names 8987 8983 8988 +11 1 +.names 8988 8989 +1 1 +.names 8989 8982 57123 +11 1 +.names 935 8991 +0 1 +.names 8991 8992 +1 1 +.names 8583 8993 +1 1 +.names 8587 8994 +1 1 +.names 8589 8995 +1 1 +.names 8626 8996 +1 1 +.names 8996 8995 8997 +11 1 +.names 8997 8998 +1 1 +.names 8998 8994 8999 +11 1 +.names 8999 9000 +1 1 +.names 9000 926 9001 +11 1 +.names 9001 9002 +1 1 +.names 9002 8993 9003 +11 1 +.names 9003 9004 +1 1 +.names 9004 9005 +0 1 +.names 9005 9006 +1 1 +.names 720 9006 9007 +11 1 +.names 9007 9008 +1 1 +.names 9008 8992 9009 +11 1 +.names 9009 9010 +1 1 +.names 715 9010 57124 +1- 1 +-1 1 +.names 2080 935 9012 +1- 1 +-1 1 +.names 9012 9013 +1 1 +.names 9013 9014 +0 1 +.names 9014 9015 +1 1 +.names 56772 9015 9016 +11 1 +.names 9016 9017 +1 1 +.names 2072 936 9018 +1- 1 +-1 1 +.names 9018 9019 +1 1 +.names 9019 9020 +0 1 +.names 9020 9021 +1 1 +.names 56771 9021 9022 +11 1 +.names 9022 9023 +1 1 +.names 9023 9017 9024 +1- 1 +-1 1 +.names 9024 9025 +1 1 +.names 57107 9026 +1 1 +.names 8782 9027 +1 1 +.names 56414 56415 9028 +11 1 +.names 9028 9029 +1 1 +.names 9029 56416 9030 +11 1 +.names 9030 9031 +1 1 +.names 9031 9027 9032 +11 1 +.names 9032 9033 +1 1 +.names 57107 9034 +1 1 +.names 8784 9035 +1 1 +.names 8786 9036 +1 1 +.names 8788 9037 +1 1 +.names 9037 9036 9038 +11 1 +.names 9038 9039 +1 1 +.names 9039 9035 9040 +11 1 +.names 9040 9041 +1 1 +.names 9041 56769 9042 +11 1 +.names 9042 9043 +1 1 +.names 9043 9034 57125 +11 1 +.names 57107 9045 +1 1 +.names 8782 9046 +1 1 +.names 8786 9047 +1 1 +.names 8788 9048 +1 1 +.names 9048 9047 9049 +11 1 +.names 9049 9050 +1 1 +.names 9050 56416 9051 +11 1 +.names 9051 9052 +1 1 +.names 9052 9046 9053 +11 1 +.names 9053 9054 +1 1 +.names 9054 9045 9055 +11 1 +.names 9055 9056 +1 1 +.names 56772 9057 +0 1 +.names 9057 9058 +1 1 +.names 57107 9059 +1 1 +.names 8782 9060 +1 1 +.names 8784 9061 +1 1 +.names 56414 56415 9062 +11 1 +.names 9062 9063 +1 1 +.names 9063 9061 9064 +11 1 +.names 9064 9065 +1 1 +.names 9065 9060 9066 +11 1 +.names 9066 9067 +1 1 +.names 9067 9059 9068 +11 1 +.names 9068 9069 +1 1 +.names 9069 937 9070 +11 1 +.names 9070 9071 +1 1 +.names 9071 9058 9072 +11 1 +.names 9072 9073 +1 1 +.names 5787 9074 +1 1 +.names 57107 9075 +1 1 +.names 8782 9076 +1 1 +.names 56414 56415 9077 +11 1 +.names 9077 9078 +1 1 +.names 9078 56416 9079 +11 1 +.names 9079 9080 +1 1 +.names 9080 9076 9081 +11 1 +.names 9081 9082 +1 1 +.names 9082 9075 9083 +11 1 +.names 9083 9084 +1 1 +.names 9084 9074 9085 +11 1 +.names 9085 9086 +1 1 +.names 9086 9073 9087 +1- 1 +-1 1 +.names 9087 9088 +1 1 +.names 9088 9056 57126 +1- 1 +-1 1 +.names 57107 9090 +1 1 +.names 8782 9091 +1 1 +.names 8784 9092 +1 1 +.names 56414 56415 9093 +11 1 +.names 9093 9094 +1 1 +.names 9094 9092 9095 +11 1 +.names 9095 9096 +1 1 +.names 9096 9091 9097 +11 1 +.names 9097 9098 +1 1 +.names 9098 9090 9099 +11 1 +.names 9099 9100 +1 1 +.names 9100 56409 9101 +11 1 +.names 9101 9102 +1 1 +.names 56771 56772 9103 +1- 1 +-1 1 +.names 9103 9104 +1 1 +.names 57107 9105 +1 1 +.names 8782 9106 +1 1 +.names 56414 56415 9107 +11 1 +.names 9107 9108 +1 1 +.names 9108 56416 9109 +11 1 +.names 9109 9110 +1 1 +.names 9110 9106 9111 +11 1 +.names 9111 9112 +1 1 +.names 9112 9105 9113 +11 1 +.names 9113 9114 +1 1 +.names 9114 9104 9115 +1- 1 +-1 1 +.names 9115 9116 +1 1 +.names 9116 9102 57127 +1- 1 +-1 1 +.names 57107 9118 +1 1 +.names 8782 9119 +1 1 +.names 8784 9120 +1 1 +.names 56414 56415 9121 +11 1 +.names 9121 9122 +1 1 +.names 9122 9120 9123 +11 1 +.names 9123 9124 +1 1 +.names 9124 9119 9125 +11 1 +.names 9125 9126 +1 1 +.names 57107 9127 +1 1 +.names 8782 9128 +1 1 +.names 56414 56415 9129 +11 1 +.names 9129 9130 +1 1 +.names 9130 56416 9131 +11 1 +.names 9131 9132 +1 1 +.names 9132 9128 9133 +11 1 +.names 9133 9134 +1 1 +.names 9134 9127 57128 +11 1 +.names 56771 56772 57129 +1- 1 +-1 1 +.names 57107 9137 +1 1 +.names 8782 9138 +1 1 +.names 8784 9139 +1 1 +.names 56414 56415 9140 +11 1 +.names 9140 9141 +1 1 +.names 9141 9139 9142 +11 1 +.names 9142 9143 +1 1 +.names 9143 9138 9144 +11 1 +.names 9144 9145 +1 1 +.names 9145 9137 9146 +11 1 +.names 9146 9147 +1 1 +.names 938 9147 9148 +1- 1 +-1 1 +.names 9148 9149 +1 1 +.names 9149 57130 +0 1 +.names 56769 717 9151 +11 1 +.names 9151 9152 +1 1 +.names 8583 9153 +1 1 +.names 8585 9154 +1 1 +.names 929 928 9155 +11 1 +.names 9155 9156 +1 1 +.names 9156 927 9157 +11 1 +.names 9157 9158 +1 1 +.names 9158 9154 9159 +11 1 +.names 9159 9160 +1 1 +.names 9160 9153 9161 +11 1 +.names 9161 9162 +1 1 +.names 9162 934 9163 +11 1 +.names 9163 9164 +1 1 +.names 57131 9165 +1 1 +.names 9165 9164 9166 +1- 1 +-1 1 +.names 9166 9167 +1 1 +.names 9167 9152 57132 +1- 1 +-1 1 +.names 720 939 9169 +11 1 +.names 9169 9170 +1 1 +.names 933 9170 9171 +1- 1 +-1 1 +.names 9171 9172 +1 1 +.names 8583 9173 +1 1 +.names 8585 9174 +1 1 +.names 929 928 9175 +11 1 +.names 9175 9176 +1 1 +.names 9176 927 9177 +11 1 +.names 9177 9178 +1 1 +.names 9178 9174 9179 +11 1 +.names 9179 9180 +1 1 +.names 9180 9173 9181 +11 1 +.names 9181 9182 +1 1 +.names 9182 9172 9183 +11 1 +.names 9183 9184 +1 1 +.names 57131 9185 +1 1 +.names 9185 9184 57133 +1- 1 +-1 1 +.names 57131 9187 +1 1 +.names 9187 2087 57134 +1- 1 +-1 1 +.names 8585 9189 +1 1 +.names 8587 9190 +1 1 +.names 8589 9191 +1 1 +.names 8626 9192 +1 1 +.names 9192 9191 9193 +11 1 +.names 9193 9194 +1 1 +.names 9194 9190 9195 +11 1 +.names 9195 9196 +1 1 +.names 9196 9189 9197 +11 1 +.names 9197 9198 +1 1 +.names 8583 9199 +1 1 +.names 8585 9200 +1 1 +.names 929 928 9201 +11 1 +.names 9201 9202 +1 1 +.names 9202 927 9203 +11 1 +.names 9203 9204 +1 1 +.names 9204 9200 9205 +11 1 +.names 9205 9206 +1 1 +.names 8585 9207 +1 1 +.names 8587 9208 +1 1 +.names 8589 9209 +1 1 +.names 8626 9210 +1 1 +.names 9210 9209 9211 +11 1 +.names 9211 9212 +1 1 +.names 9212 9208 9213 +11 1 +.names 9213 9214 +1 1 +.names 9214 9207 9215 +11 1 +.names 9215 9216 +1 1 +.names 9216 8562 9217 +11 1 +.names 9217 9218 +1 1 +.names 9218 9219 +0 1 +.names 9219 9220 +1 1 +.names 8583 9221 +1 1 +.names 8585 9222 +1 1 +.names 929 928 9223 +11 1 +.names 9223 9224 +1 1 +.names 9224 927 9225 +11 1 +.names 9225 9226 +1 1 +.names 9226 9222 9227 +11 1 +.names 9227 9228 +1 1 +.names 8585 9229 +1 1 +.names 8587 9230 +1 1 +.names 8589 9231 +1 1 +.names 8626 9232 +1 1 +.names 9232 9231 9233 +11 1 +.names 9233 9234 +1 1 +.names 9234 9230 9235 +11 1 +.names 9235 9236 +1 1 +.names 9236 9229 9237 +11 1 +.names 9237 9238 +1 1 +.names 9238 8562 9239 +11 1 +.names 9239 9240 +1 1 +.names 9240 9241 +0 1 +.names 9241 9242 +1 1 +.names 8583 9243 +1 1 +.names 8585 9244 +1 1 +.names 929 928 9245 +11 1 +.names 9245 9246 +1 1 +.names 9246 927 9247 +11 1 +.names 9247 9248 +1 1 +.names 9248 9244 9249 +11 1 +.names 9249 9250 +1 1 +.names 940 9251 +0 1 +.names 9251 9252 +1 1 +.names 939 933 9253 +1- 1 +-1 1 +.names 9253 9254 +1 1 +.names 9254 9252 9255 +1- 1 +-1 1 +.names 9255 9256 +1 1 +.names 8583 9257 +1 1 +.names 8585 9258 +1 1 +.names 929 928 9259 +11 1 +.names 9259 9260 +1 1 +.names 9260 927 9261 +11 1 +.names 9261 9262 +1 1 +.names 9262 9258 9263 +11 1 +.names 9263 9264 +1 1 +.names 9264 9257 9265 +11 1 +.names 9265 9266 +1 1 +.names 9266 720 9267 +11 1 +.names 9267 9268 +1 1 +.names 9251 9269 +1 1 +.names 939 933 9270 +1- 1 +-1 1 +.names 9270 9271 +1 1 +.names 9271 9269 9272 +1- 1 +-1 1 +.names 9272 9273 +1 1 +.names 8583 9274 +1 1 +.names 8585 9275 +1 1 +.names 929 928 9276 +11 1 +.names 9276 9277 +1 1 +.names 9277 927 9278 +11 1 +.names 9278 9279 +1 1 +.names 9279 9275 9280 +11 1 +.names 9280 9281 +1 1 +.names 9281 9274 9282 +11 1 +.names 9282 9283 +1 1 +.names 9283 716 9284 +11 1 +.names 9284 9285 +1 1 +.names 8583 9286 +1 1 +.names 8585 9287 +1 1 +.names 8587 9288 +1 1 +.names 929 928 9289 +11 1 +.names 9289 9290 +1 1 +.names 9290 9288 9291 +11 1 +.names 9291 9292 +1 1 +.names 9292 9287 9293 +11 1 +.names 9293 9294 +1 1 +.names 9294 9286 9295 +11 1 +.names 9295 9296 +1 1 +.names 9296 9297 +0 1 +.names 9297 9298 +1 1 +.names 715 716 9299 +1- 1 +-1 1 +.names 9299 9300 +1 1 +.names 9300 720 9301 +1- 1 +-1 1 +.names 9301 9302 +1 1 +.names 8583 9303 +1 1 +.names 8585 9304 +1 1 +.names 929 928 9305 +11 1 +.names 9305 9306 +1 1 +.names 9306 927 9307 +11 1 +.names 9307 9308 +1 1 +.names 9308 9304 9309 +11 1 +.names 9309 9310 +1 1 +.names 9310 9303 9311 +11 1 +.names 9311 9312 +1 1 +.names 2348 2354 9313 +1- 1 +-1 1 +.names 9313 9314 +1 1 +.names 9314 2360 9315 +1- 1 +-1 1 +.names 9315 9316 +1 1 +.names 8585 9317 +1 1 +.names 8587 9318 +1 1 +.names 8589 9319 +1 1 +.names 8626 9320 +1 1 +.names 9320 9319 9321 +11 1 +.names 9321 9322 +1 1 +.names 9322 9318 9323 +11 1 +.names 9323 9324 +1 1 +.names 9324 9317 9325 +11 1 +.names 9325 9326 +1 1 +.names 9326 8562 9327 +11 1 +.names 9327 9328 +1 1 +.names 716 720 9329 +1- 1 +-1 1 +.names 9329 9330 +1 1 +.names 8583 9331 +1 1 +.names 8585 9332 +1 1 +.names 8587 9333 +1 1 +.names 8626 9334 +1 1 +.names 9334 928 9335 +11 1 +.names 9335 9336 +1 1 +.names 9336 9333 9337 +11 1 +.names 9337 9338 +1 1 +.names 9338 9332 9339 +11 1 +.names 9339 9340 +1 1 +.names 9340 9331 9341 +11 1 +.names 9341 9342 +1 1 +.names 8583 9343 +1 1 +.names 8585 9344 +1 1 +.names 8589 9345 +1 1 +.names 8626 9346 +1 1 +.names 9346 9345 9347 +11 1 +.names 9347 9348 +1 1 +.names 9348 927 9349 +11 1 +.names 9349 9350 +1 1 +.names 9350 9344 9351 +11 1 +.names 9351 9352 +1 1 +.names 9352 9343 9353 +11 1 +.names 9353 9354 +1 1 +.names 9354 9342 9355 +1- 1 +-1 1 +.names 9355 9356 +1 1 +.names 715 716 9357 +1- 1 +-1 1 +.names 9357 9358 +1 1 +.names 9358 941 9359 +1- 1 +-1 1 +.names 9359 9360 +1 1 +.names 8583 9361 +1 1 +.names 8585 9362 +1 1 +.names 929 928 9363 +11 1 +.names 9363 9364 +1 1 +.names 9364 927 9365 +11 1 +.names 9365 9366 +1 1 +.names 9366 9362 9367 +11 1 +.names 9367 9368 +1 1 +.names 9368 9361 9369 +11 1 +.names 9369 9370 +1 1 +.names 2348 2354 9371 +1- 1 +-1 1 +.names 9371 9372 +1 1 +.names 9372 2360 9373 +1- 1 +-1 1 +.names 9373 9374 +1 1 +.names 8585 9375 +1 1 +.names 8587 9376 +1 1 +.names 8589 9377 +1 1 +.names 8626 9378 +1 1 +.names 9378 9377 9379 +11 1 +.names 9379 9380 +1 1 +.names 9380 9376 9381 +11 1 +.names 9381 9382 +1 1 +.names 9382 9375 9383 +11 1 +.names 9383 9384 +1 1 +.names 9384 8562 9385 +11 1 +.names 9385 9386 +1 1 +.names 8583 9387 +1 1 +.names 8585 9388 +1 1 +.names 8587 9389 +1 1 +.names 929 928 9390 +11 1 +.names 9390 9391 +1 1 +.names 9391 9389 9392 +11 1 +.names 9392 9393 +1 1 +.names 9393 9388 9394 +11 1 +.names 9394 9395 +1 1 +.names 9395 9387 9396 +11 1 +.names 9396 9397 +1 1 +.names 9397 9398 +0 1 +.names 9398 9399 +1 1 +.names 716 720 9400 +1- 1 +-1 1 +.names 9400 9401 +1 1 +.names 8583 9402 +1 1 +.names 8587 9403 +1 1 +.names 8589 9404 +1 1 +.names 8626 9405 +1 1 +.names 9405 9404 9406 +11 1 +.names 9406 9407 +1 1 +.names 9407 9403 9408 +11 1 +.names 9408 9409 +1 1 +.names 9409 926 9410 +11 1 +.names 9410 9411 +1 1 +.names 9411 9402 9412 +11 1 +.names 9412 9413 +1 1 +.names 9413 9414 +0 1 +.names 9414 9415 +1 1 +.names 716 720 9416 +1- 1 +-1 1 +.names 9416 9417 +1 1 +.names 8583 9418 +1 1 +.names 8585 9419 +1 1 +.names 929 928 9420 +11 1 +.names 9420 9421 +1 1 +.names 9421 927 9422 +11 1 +.names 9422 9423 +1 1 +.names 9423 9419 9424 +11 1 +.names 9424 9425 +1 1 +.names 9425 9418 9426 +11 1 +.names 9426 9427 +1 1 +.names 9427 56769 9428 +1- 1 +-1 1 +.names 9428 9429 +1 1 +.names 2679 9430 +1 1 +.names 2679 9431 +1 1 +.names 2679 9432 +1 1 +.names 9435 9433 +1 1 +.names 9433 9434 +1 1 +.names 9437 9435 +0 1 +.names 6500 9436 +0 1 +.names 9436 9437 +1 1 +.names 9435 9438 +1 1 +.names 9438 9439 +1 1 +.names 9433 9440 +1 1 +.names 9444 9441 +0 1 +.names 9441 9442 +1 1 +.names 14759 9443 +0 1 +.names 9443 9444 +1 1 +.names 9448 9445 +0 1 +.names 9445 9446 +1 1 +.names 14757 14758 9447 +1- 1 +-1 1 +.names 9447 9448 +1 1 +.names 9451 9449 +1 1 +.names 9449 9450 +1 1 +.names 9456 9451 +0 1 +.names 9451 9452 +1 1 +.names 9452 9453 +1 1 +.names 9452 9454 +1 1 +.names 6484 9455 +0 1 +.names 9455 9456 +1 1 +.names 9460 9457 +0 1 +.names 9457 9458 +1 1 +.names 6479 9459 +0 1 +.names 9459 9460 +1 1 +.names 9464 9461 +0 1 +.names 9461 9462 +1 1 +.names 6478 9463 +0 1 +.names 9463 9464 +1 1 +.names 9468 9465 +0 1 +.names 9465 9466 +1 1 +.names 6472 9467 +0 1 +.names 9467 9468 +1 1 +.names 9472 9469 +0 1 +.names 9469 9470 +1 1 +.names 6471 9471 +0 1 +.names 9471 9472 +1 1 +.names 9476 9473 +0 1 +.names 9473 9474 +1 1 +.names 6470 9475 +0 1 +.names 9475 9476 +1 1 +.names 9480 9477 +0 1 +.names 9477 9478 +1 1 +.names 6469 9479 +0 1 +.names 9479 9480 +1 1 +.names 9484 9481 +0 1 +.names 9481 9482 +1 1 +.names 6468 9483 +0 1 +.names 9483 9484 +1 1 +.names 9488 9485 +0 1 +.names 9485 9486 +1 1 +.names 6467 9487 +0 1 +.names 9487 9488 +1 1 +.names 9492 9489 +0 1 +.names 9489 9490 +1 1 +.names 6466 9491 +0 1 +.names 9491 9492 +1 1 +.names 9496 9493 +0 1 +.names 9493 9494 +1 1 +.names 6465 9495 +0 1 +.names 9495 9496 +1 1 +.names 9500 9497 +0 1 +.names 9497 9498 +1 1 +.names 6464 9499 +0 1 +.names 9499 9500 +1 1 +.names 9504 9501 +0 1 +.names 9501 9502 +1 1 +.names 6463 9503 +0 1 +.names 9503 9504 +1 1 +.names 9508 9505 +0 1 +.names 9505 9506 +1 1 +.names 6450 9507 +0 1 +.names 9507 9508 +1 1 +.names 9505 9509 +1 1 +.names 9509 9510 +1 1 +.names 9509 9511 +1 1 +.names 9505 9512 +1 1 +.names 9512 9513 +1 1 +.names 9512 9514 +1 1 +.names 9506 9515 +1 1 +.names 9506 9516 +1 1 +.names 9520 9517 +0 1 +.names 9517 9518 +1 1 +.names 6447 9519 +0 1 +.names 9519 9520 +1 1 +.names 9524 9521 +0 1 +.names 9521 9522 +1 1 +.names 6446 9523 +0 1 +.names 9523 9524 +1 1 +.names 9521 9525 +1 1 +.names 9521 9526 +1 1 +.names 9530 9527 +0 1 +.names 9527 9528 +1 1 +.names 6445 9529 +0 1 +.names 9529 9530 +1 1 +.names 9527 9531 +1 1 +.names 9527 9532 +1 1 +.names 9536 9533 +0 1 +.names 9533 9534 +1 1 +.names 6444 9535 +0 1 +.names 9535 9536 +1 1 +.names 9540 9537 +0 1 +.names 9537 9538 +1 1 +.names 6443 9539 +0 1 +.names 9539 9540 +1 1 +.names 9537 9541 +1 1 +.names 9545 9542 +0 1 +.names 9542 9543 +1 1 +.names 6442 9544 +0 1 +.names 9544 9545 +1 1 +.names 9549 9546 +0 1 +.names 9546 9547 +1 1 +.names 6441 9548 +0 1 +.names 9548 9549 +1 1 +.names 9553 9550 +0 1 +.names 9550 9551 +1 1 +.names 6440 9552 +0 1 +.names 9552 9553 +1 1 +.names 9550 9554 +1 1 +.names 9558 9555 +0 1 +.names 9555 9556 +1 1 +.names 6439 9557 +0 1 +.names 9557 9558 +1 1 +.names 9561 9559 +1 1 +.names 9559 9560 +1 1 +.names 9563 9561 +0 1 +.names 6436 9562 +0 1 +.names 9562 9563 +1 1 +.names 9566 9564 +1 1 +.names 9564 9565 +1 1 +.names 9569 9566 +0 1 +.names 9564 9567 +1 1 +.names 14946 14947 9568 +1- 1 +-1 1 +.names 9568 9569 +1 1 +.names 9559 9570 +1 1 +.names 9566 9571 +1 1 +.names 9571 9572 +1 1 +.names 9564 9573 +1 1 +.names 9559 9574 +1 1 +.names 9559 9575 +1 1 +.names 942 943 9576 +1- 1 +-1 1 +.names 9576 9577 +1 1 +.names 9577 944 9578 +1- 1 +-1 1 +.names 9578 9579 +1 1 +.names 9579 945 9580 +1- 1 +-1 1 +.names 9580 9581 +1 1 +.names 9581 946 9582 +1- 1 +-1 1 +.names 9582 9583 +1 1 +.names 947 948 9584 +1- 1 +-1 1 +.names 9584 9585 +1 1 +.names 9585 949 9586 +1- 1 +-1 1 +.names 9586 9587 +1 1 +.names 9587 950 9588 +1- 1 +-1 1 +.names 9588 9589 +1 1 +.names 951 952 9590 +1- 1 +-1 1 +.names 9590 9591 +1 1 +.names 9591 953 9592 +1- 1 +-1 1 +.names 9592 9593 +1 1 +.names 9593 954 9594 +1- 1 +-1 1 +.names 9594 9595 +1 1 +.names 955 2886 9596 +1- 1 +-1 1 +.names 9596 9597 +1 1 +.names 9597 2882 9598 +1- 1 +-1 1 +.names 9598 9599 +1 1 +.names 9599 956 9600 +1- 1 +-1 1 +.names 9600 9601 +1 1 +.names 9604 9602 +1 1 +.names 9602 9603 +1 1 +.names 9642 9604 +0 1 +.names 9607 9605 +1 1 +.names 9605 9606 +1 1 +.names 9609 9607 +0 1 +.names 15160 15149 9608 +1- 1 +-1 1 +.names 9608 9609 +1 1 +.names 9612 9610 +1 1 +.names 9610 9611 +1 1 +.names 9615 9612 +0 1 +.names 9610 9613 +1 1 +.names 15165 15166 9614 +1- 1 +-1 1 +.names 9614 9615 +1 1 +.names 9618 9616 +1 1 +.names 9616 9617 +1 1 +.names 9648 9618 +0 1 +.names 9616 9619 +1 1 +.names 9622 9620 +1 1 +.names 9620 9621 +1 1 +.names 9624 9622 +0 1 +.names 15147 15148 9623 +1- 1 +-1 1 +.names 9623 9624 +1 1 +.names 9620 9625 +1 1 +.names 9622 9626 +1 1 +.names 9626 9627 +1 1 +.names 9607 9628 +1 1 +.names 9628 9629 +1 1 +.names 9628 9630 +1 1 +.names 9634 9631 +0 1 +.names 9631 9632 +1 1 +.names 15152 15154 9633 +1- 1 +-1 1 +.names 9633 9634 +1 1 +.names 9632 9635 +1 1 +.names 9632 9636 +1 1 +.names 9610 9637 +1 1 +.names 9616 9638 +1 1 +.names 957 9639 +1 1 +.names 9632 9640 +1 1 +.names 15130 15150 9641 +1- 1 +-1 1 +.names 9641 9642 +1 1 +.names 9602 9643 +1 1 +.names 9632 9644 +1 1 +.names 9605 9645 +1 1 +.names 958 9646 +1 1 +.names 15135 15136 9647 +1- 1 +-1 1 +.names 9647 9648 +1 1 +.names 9620 9649 +1 1 +.names 9602 9650 +1 1 +.names 9628 9651 +1 1 +.names 9654 9652 +1 1 +.names 9652 9653 +1 1 +.names 9656 9654 +0 1 +.names 6373 9655 +0 1 +.names 9655 9656 +1 1 +.names 9654 9657 +1 1 +.names 9657 9658 +1 1 +.names 9652 9659 +1 1 +.names 9662 9660 +1 1 +.names 9660 9661 +1 1 +.names 9664 9662 +0 1 +.names 6369 9663 +0 1 +.names 9663 9664 +1 1 +.names 9662 9665 +1 1 +.names 9665 9666 +1 1 +.names 9660 9667 +1 1 +.names 9671 9668 +0 1 +.names 9668 9669 +1 1 +.names 9675 21951 9670 +1- 1 +-1 1 +.names 9670 9671 +1 1 +.names 9669 9672 +1 1 +.names 9675 9673 +1 1 +.names 9673 9674 +1 1 +.names 9677 9675 +0 1 +.names 3143 9676 +0 1 +.names 9676 9677 +1 1 +.names 9681 9678 +0 1 +.names 9678 9679 +1 1 +.names 21949 21950 9680 +1- 1 +-1 1 +.names 9680 9681 +1 1 +.names 9669 9682 +1 1 +.names 9679 9683 +1 1 +.names 9679 9684 +1 1 +.names 9687 9685 +0 1 +.names 9685 9686 +1 1 +.names 9676 9687 +1 1 +.names 9691 9688 +0 1 +.names 9688 9689 +1 1 +.names 9695 21964 9690 +1- 1 +-1 1 +.names 9690 9691 +1 1 +.names 9689 9692 +1 1 +.names 9695 9693 +1 1 +.names 9693 9694 +1 1 +.names 9697 9695 +0 1 +.names 3131 9696 +0 1 +.names 9696 9697 +1 1 +.names 9701 9698 +0 1 +.names 9698 9699 +1 1 +.names 21962 21963 9700 +1- 1 +-1 1 +.names 9700 9701 +1 1 +.names 9689 9702 +1 1 +.names 9699 9703 +1 1 +.names 9699 9704 +1 1 +.names 9707 9705 +0 1 +.names 9705 9706 +1 1 +.names 9696 9707 +1 1 +.names 9711 9708 +0 1 +.names 9708 9709 +1 1 +.names 51437 51436 9710 +1- 1 +-1 1 +.names 9710 9711 +1 1 +.names 9715 9712 +0 1 +.names 9712 9713 +1 1 +.names 51435 51436 9714 +1- 1 +-1 1 +.names 9714 9715 +1 1 +.names 9719 9716 +0 1 +.names 9716 9717 +1 1 +.names 51439 51443 9718 +1- 1 +-1 1 +.names 9718 9719 +1 1 +.names 9723 9720 +0 1 +.names 9720 9721 +1 1 +.names 51437 51443 9722 +1- 1 +-1 1 +.names 9722 9723 +1 1 +.names 9727 9724 +0 1 +.names 9724 9725 +1 1 +.names 51438 51443 9726 +1- 1 +-1 1 +.names 9726 9727 +1 1 +.names 9731 9728 +0 1 +.names 9728 9729 +1 1 +.names 51437 51444 9730 +1- 1 +-1 1 +.names 9730 9731 +1 1 +.names 9735 9732 +0 1 +.names 9732 9733 +1 1 +.names 51435 51444 9734 +1- 1 +-1 1 +.names 9734 9735 +1 1 +.names 9739 9736 +0 1 +.names 9736 9737 +1 1 +.names 51444 51438 9738 +1- 1 +-1 1 +.names 9738 9739 +1 1 +.names 9743 9740 +0 1 +.names 9740 9741 +1 1 +.names 51439 51440 9742 +1- 1 +-1 1 +.names 9742 9743 +1 1 +.names 9747 9744 +0 1 +.names 9744 9745 +1 1 +.names 51438 51436 9746 +1- 1 +-1 1 +.names 9746 9747 +1 1 +.names 9751 9748 +0 1 +.names 9748 9749 +1 1 +.names 51437 51440 9750 +1- 1 +-1 1 +.names 9750 9751 +1 1 +.names 9755 9752 +0 1 +.names 9752 9753 +1 1 +.names 51435 51440 9754 +1- 1 +-1 1 +.names 9754 9755 +1 1 +.names 9759 9756 +0 1 +.names 9756 9757 +1 1 +.names 51440 51438 9758 +1- 1 +-1 1 +.names 9758 9759 +1 1 +.names 9763 9760 +0 1 +.names 9760 9761 +1 1 +.names 51439 51436 9762 +1- 1 +-1 1 +.names 9762 9763 +1 1 +.names 583 9764 +0 1 +.names 9764 9765 +1 1 +.names 582 9766 +0 1 +.names 9766 9767 +1 1 +.names 581 9768 +0 1 +.names 9768 9769 +1 1 +.names 579 9770 +0 1 +.names 9770 9771 +1 1 +.names 577 9772 +0 1 +.names 9772 9773 +1 1 +.names 576 9774 +0 1 +.names 9774 9775 +1 1 +.names 9779 9776 +0 1 +.names 9776 9777 +1 1 +.names 51449 51456 9778 +1- 1 +-1 1 +.names 9778 9779 +1 1 +.names 9783 9780 +0 1 +.names 9780 9781 +1 1 +.names 51450 51452 9782 +1- 1 +-1 1 +.names 9782 9783 +1 1 +.names 22007 22062 9784 +1- 1 +-1 1 +.names 9784 9785 +1 1 +.names 21996 22069 9786 +1- 1 +-1 1 +.names 9786 9787 +1 1 +.names 22004 22062 9788 +1- 1 +-1 1 +.names 9788 9789 +1 1 +.names 22013 22071 9790 +1- 1 +-1 1 +.names 9790 9791 +1 1 +.names 21997 22069 9792 +1- 1 +-1 1 +.names 9792 9793 +1 1 +.names 21994 22062 9794 +1- 1 +-1 1 +.names 9794 9795 +1 1 +.names 22068 22070 9796 +1- 1 +-1 1 +.names 9796 9797 +1 1 +.names 22006 22069 9798 +1- 1 +-1 1 +.names 9798 9799 +1 1 +.names 22059 22070 9800 +1- 1 +-1 1 +.names 9800 9801 +1 1 +.names 21997 21998 9802 +1- 1 +-1 1 +.names 9802 9803 +1 1 +.names 21980 22109 9804 +1- 1 +-1 1 +.names 9804 9805 +1 1 +.names 22008 22107 9806 +1- 1 +-1 1 +.names 9806 9807 +1 1 +.names 22066 22018 9808 +1- 1 +-1 1 +.names 9808 9809 +1 1 +.names 22069 22012 9810 +1- 1 +-1 1 +.names 9810 9811 +1 1 +.names 22108 22001 9812 +1- 1 +-1 1 +.names 9812 9813 +1 1 +.names 21982 22070 9814 +1- 1 +-1 1 +.names 9814 9815 +1 1 +.names 21985 22070 9816 +1- 1 +-1 1 +.names 9816 9817 +1 1 +.names 22005 22069 9818 +1- 1 +-1 1 +.names 9818 9819 +1 1 +.names 21995 22062 9820 +1- 1 +-1 1 +.names 9820 9821 +1 1 +.names 22003 22108 9822 +1- 1 +-1 1 +.names 9822 9823 +1 1 +.names 22062 22063 9824 +1- 1 +-1 1 +.names 9824 9825 +1 1 +.names 22003 22069 9826 +1- 1 +-1 1 +.names 9826 9827 +1 1 +.names 21982 22104 9828 +1- 1 +-1 1 +.names 9828 9829 +1 1 +.names 22068 22107 9830 +1- 1 +-1 1 +.names 9830 9831 +1 1 +.names 21997 22062 9832 +1- 1 +-1 1 +.names 9832 9833 +1 1 +.names 21980 22069 9834 +1- 1 +-1 1 +.names 9834 9835 +1 1 +.names 22058 22108 9836 +1- 1 +-1 1 +.names 9836 9837 +1 1 +.names 22008 22062 9838 +1- 1 +-1 1 +.names 9838 9839 +1 1 +.names 21988 22107 9840 +1- 1 +-1 1 +.names 9840 9841 +1 1 +.names 22004 22069 9842 +1- 1 +-1 1 +.names 9842 9843 +1 1 +.names 22070 22063 9844 +1- 1 +-1 1 +.names 9844 9845 +1 1 +.names 22106 22104 9846 +1- 1 +-1 1 +.names 9846 9847 +1 1 +.names 21997 22066 9848 +1- 1 +-1 1 +.names 9848 9849 +1 1 +.names 22014 22071 9850 +1- 1 +-1 1 +.names 9850 9851 +1 1 +.names 21994 22108 9852 +1- 1 +-1 1 +.names 9852 9853 +1 1 +.names 21994 22069 9854 +1- 1 +-1 1 +.names 9854 9855 +1 1 +.names 22069 21989 9856 +1- 1 +-1 1 +.names 9856 9857 +1 1 +.names 21991 22062 9858 +1- 1 +-1 1 +.names 9858 9859 +1 1 +.names 21988 22066 9860 +1- 1 +-1 1 +.names 9860 9861 +1 1 +.names 22071 21973 9862 +1- 1 +-1 1 +.names 9862 9863 +1 1 +.names 22015 22011 9864 +1- 1 +-1 1 +.names 9864 9865 +1 1 +.names 21997 22107 9866 +1- 1 +-1 1 +.names 9866 9867 +1 1 +.names 22007 22069 9868 +1- 1 +-1 1 +.names 9868 9869 +1 1 +.names 22064 22063 9870 +1- 1 +-1 1 +.names 9870 9871 +1 1 +.names 22022 22108 9872 +1- 1 +-1 1 +.names 9872 9873 +1 1 +.names 21976 22071 9874 +1- 1 +-1 1 +.names 9874 9875 +1 1 +.names 21993 22069 9876 +1- 1 +-1 1 +.names 9876 9877 +1 1 +.names 22105 22012 9878 +1- 1 +-1 1 +.names 9878 9879 +1 1 +.names 22062 21973 9880 +1- 1 +-1 1 +.names 9880 9881 +1 1 +.names 21988 22070 9882 +1- 1 +-1 1 +.names 9882 9883 +1 1 +.names 22008 22069 9884 +1- 1 +-1 1 +.names 9884 9885 +1 1 +.names 21980 22062 9886 +1- 1 +-1 1 +.names 9886 9887 +1 1 +.names 22003 22062 9888 +1- 1 +-1 1 +.names 9888 9889 +1 1 +.names 22107 22018 9890 +1- 1 +-1 1 +.names 9890 9891 +1 1 +.names 21991 22069 9892 +1- 1 +-1 1 +.names 9892 9893 +1 1 +.names 22067 22012 9894 +1- 1 +-1 1 +.names 9894 9895 +1 1 +.names 22000 22069 9896 +1- 1 +-1 1 +.names 9896 9897 +1 1 +.names 21995 22069 9898 +1- 1 +-1 1 +.names 9898 9899 +1 1 +.names 22104 21989 9900 +1- 1 +-1 1 +.names 9900 9901 +1 1 +.names 22014 22108 9902 +1- 1 +-1 1 +.names 9902 9903 +1 1 +.names 22005 22062 9904 +1- 1 +-1 1 +.names 9904 9905 +1 1 +.names 21984 22107 9906 +1- 1 +-1 1 +.names 9906 9907 +1 1 +.names 21975 22071 9908 +1- 1 +-1 1 +.names 9908 9909 +1 1 +.names 22015 22071 9910 +1- 1 +-1 1 +.names 9910 9911 +1 1 +.names 9915 9912 +0 1 +.names 9912 9913 +1 1 +.names 51451 51447 9914 +1- 1 +-1 1 +.names 9914 9915 +1 1 +.names 9913 9916 +1 1 +.names 9913 9917 +1 1 +.names 9913 9918 +1 1 +.names 9922 9919 +0 1 +.names 9919 9920 +1 1 +.names 51451 51452 9921 +1- 1 +-1 1 +.names 9921 9922 +1 1 +.names 9920 9923 +1 1 +.names 9920 9924 +1 1 +.names 9920 9925 +1 1 +.names 9929 9926 +0 1 +.names 9926 9927 +1 1 +.names 51451 51456 9928 +1- 1 +-1 1 +.names 9928 9929 +1 1 +.names 9927 9930 +1 1 +.names 9927 9931 +1 1 +.names 9927 9932 +1 1 +.names 9936 9933 +0 1 +.names 9933 9934 +1 1 +.names 51451 51455 9935 +1- 1 +-1 1 +.names 9935 9936 +1 1 +.names 9934 9937 +1 1 +.names 9934 9938 +1 1 +.names 9934 9939 +1 1 +.names 9943 9940 +0 1 +.names 9940 9941 +1 1 +.names 51450 51447 9942 +1- 1 +-1 1 +.names 9942 9943 +1 1 +.names 9941 9944 +1 1 +.names 9941 9945 +1 1 +.names 9949 9946 +0 1 +.names 9946 9947 +1 1 +.names 51450 51456 9948 +1- 1 +-1 1 +.names 9948 9949 +1 1 +.names 9947 9950 +1 1 +.names 9947 9951 +1 1 +.names 9947 9952 +1 1 +.names 9956 9953 +0 1 +.names 9953 9954 +1 1 +.names 51450 51455 9955 +1- 1 +-1 1 +.names 9955 9956 +1 1 +.names 9954 9957 +1 1 +.names 9954 9958 +1 1 +.names 9954 9959 +1 1 +.names 9963 9960 +0 1 +.names 9960 9961 +1 1 +.names 51449 51447 9962 +1- 1 +-1 1 +.names 9962 9963 +1 1 +.names 9961 9964 +1 1 +.names 9961 9965 +1 1 +.names 9961 9966 +1 1 +.names 9970 9967 +0 1 +.names 9967 9968 +1 1 +.names 51449 51452 9969 +1- 1 +-1 1 +.names 9969 9970 +1 1 +.names 9968 9971 +1 1 +.names 9968 9972 +1 1 +.names 9968 9973 +1 1 +.names 9977 9974 +0 1 +.names 9974 9975 +1 1 +.names 51449 51455 9976 +1- 1 +-1 1 +.names 9976 9977 +1 1 +.names 9975 9978 +1 1 +.names 9975 9979 +1 1 +.names 9975 9980 +1 1 +.names 9781 9981 +1 1 +.names 9781 9982 +1 1 +.names 9781 9983 +1 1 +.names 9987 9984 +0 1 +.names 9984 9985 +1 1 +.names 51455 51448 9986 +1- 1 +-1 1 +.names 9986 9987 +1 1 +.names 9985 9988 +1 1 +.names 9985 9989 +1 1 +.names 9985 9990 +1 1 +.names 9994 9991 +0 1 +.names 9991 9992 +1 1 +.names 51435 51443 9993 +1- 1 +-1 1 +.names 9993 9994 +1 1 +.names 9716 9995 +1 1 +.names 9999 9996 +0 1 +.names 9996 9997 +1 1 +.names 51452 51448 9998 +1- 1 +-1 1 +.names 9998 9999 +1 1 +.names 9997 10000 +1 1 +.names 9997 10001 +1 1 +.names 9997 10002 +1 1 +.names 10006 10003 +0 1 +.names 10003 10004 +1 1 +.names 51456 51448 10005 +1- 1 +-1 1 +.names 10005 10006 +1 1 +.names 10004 10007 +1 1 +.names 10004 10008 +1 1 +.names 10004 10009 +1 1 +.names 10013 10010 +0 1 +.names 10010 10011 +1 1 +.names 51439 51444 10012 +1- 1 +-1 1 +.names 10012 10013 +1 1 +.names 9760 10014 +1 1 +.names 9740 10015 +1 1 +.names 9777 10016 +1 1 +.names 9777 10017 +1 1 +.names 9777 10018 +1 1 +.names 9708 10019 +1 1 +.names 9748 10020 +1 1 +.names 9728 10021 +1 1 +.names 9752 10022 +1 1 +.names 9732 10023 +1 1 +.names 9712 10024 +1 1 +.names 9744 10025 +1 1 +.names 10028 10026 +0 1 +.names 10026 10027 +1 1 +.names 580 10028 +1 1 +.names 21997 21999 10029 +1- 1 +-1 1 +.names 10029 10030 +1 1 +.names 21982 22019 10031 +1- 1 +-1 1 +.names 10031 10032 +1 1 +.names 21982 22055 10033 +1- 1 +-1 1 +.names 10033 10034 +1 1 +.names 22004 21999 10035 +1- 1 +-1 1 +.names 10035 10036 +1 1 +.names 22005 21999 10037 +1- 1 +-1 1 +.names 10037 10038 +1 1 +.names 22006 21999 10039 +1- 1 +-1 1 +.names 10039 10040 +1 1 +.names 22007 21999 10041 +1- 1 +-1 1 +.names 10041 10042 +1 1 +.names 22008 21999 10043 +1- 1 +-1 1 +.names 10043 10044 +1 1 +.names 21989 21999 10045 +1- 1 +-1 1 +.names 10045 10046 +1 1 +.names 22000 21999 10047 +1- 1 +-1 1 +.names 10047 10048 +1 1 +.names 22001 22002 10049 +1- 1 +-1 1 +.names 10049 10050 +1 1 +.names 22003 22002 10051 +1- 1 +-1 1 +.names 10051 10052 +1 1 +.names 21991 22002 10053 +1- 1 +-1 1 +.names 10053 10054 +1 1 +.names 21993 22002 10055 +1- 1 +-1 1 +.names 10055 10056 +1 1 +.names 21994 22002 10057 +1- 1 +-1 1 +.names 10057 10058 +1 1 +.names 21995 22002 10059 +1- 1 +-1 1 +.names 10059 10060 +1 1 +.names 21980 22002 10061 +1- 1 +-1 1 +.names 10061 10062 +1 1 +.names 21996 22002 10063 +1- 1 +-1 1 +.names 10063 10064 +1 1 +.names 22004 22019 10065 +1- 1 +-1 1 +.names 10065 10066 +1 1 +.names 22005 22019 10067 +1- 1 +-1 1 +.names 10067 10068 +1 1 +.names 22006 22019 10069 +1- 1 +-1 1 +.names 10069 10070 +1 1 +.names 21986 22019 10071 +1- 1 +-1 1 +.names 10071 10072 +1 1 +.names 22016 22019 10073 +1- 1 +-1 1 +.names 10073 10074 +1 1 +.names 22018 22019 10075 +1- 1 +-1 1 +.names 10075 10076 +1 1 +.names 22009 22019 10077 +1- 1 +-1 1 +.names 10077 10078 +1 1 +.names 21973 22020 10079 +1- 1 +-1 1 +.names 10079 10080 +1 1 +.names 22003 22020 10081 +1- 1 +-1 1 +.names 10081 10082 +1 1 +.names 21976 22020 10083 +1- 1 +-1 1 +.names 10083 10084 +1 1 +.names 22021 22020 10085 +1- 1 +-1 1 +.names 10085 10086 +1 1 +.names 21978 22020 10087 +1- 1 +-1 1 +.names 10087 10088 +1 1 +.names 21979 22020 10089 +1- 1 +-1 1 +.names 10089 10090 +1 1 +.names 22022 22020 10091 +1- 1 +-1 1 +.names 10091 10092 +1 1 +.names 21983 22020 10093 +1- 1 +-1 1 +.names 10093 10094 +1 1 +.names 22059 22055 10095 +1- 1 +-1 1 +.names 10095 10096 +1 1 +.names 21988 22055 10097 +1- 1 +-1 1 +.names 10097 10098 +1 1 +.names 22060 22055 10099 +1- 1 +-1 1 +.names 10099 10100 +1 1 +.names 22007 22055 10101 +1- 1 +-1 1 +.names 10101 10102 +1 1 +.names 22016 22055 10103 +1- 1 +-1 1 +.names 10103 10104 +1 1 +.names 22018 22055 10105 +1- 1 +-1 1 +.names 10105 10106 +1 1 +.names 22000 22055 10107 +1- 1 +-1 1 +.names 10107 10108 +1 1 +.names 22012 22056 10109 +1- 1 +-1 1 +.names 10109 10110 +1 1 +.names 22057 22056 10111 +1- 1 +-1 1 +.names 10111 10112 +1 1 +.names 22058 22056 10113 +1- 1 +-1 1 +.names 10113 10114 +1 1 +.names 22021 22056 10115 +1- 1 +-1 1 +.names 10115 10116 +1 1 +.names 22013 22056 10117 +1- 1 +-1 1 +.names 10117 10118 +1 1 +.names 21979 22056 10119 +1- 1 +-1 1 +.names 10119 10120 +1 1 +.names 22022 22056 10121 +1- 1 +-1 1 +.names 10121 10122 +1 1 +.names 21983 22056 10123 +1- 1 +-1 1 +.names 10123 10124 +1 1 +.names 21984 21981 10125 +1- 1 +-1 1 +.names 10125 10126 +1 1 +.names 21988 21981 10127 +1- 1 +-1 1 +.names 10127 10128 +1 1 +.names 21990 21981 10129 +1- 1 +-1 1 +.names 10129 10130 +1 1 +.names 21986 21981 10131 +1- 1 +-1 1 +.names 10131 10132 +1 1 +.names 21985 21981 10133 +1- 1 +-1 1 +.names 10133 10134 +1 1 +.names 21989 21981 10135 +1- 1 +-1 1 +.names 10135 10136 +1 1 +.names 21987 21981 10137 +1- 1 +-1 1 +.names 10137 10138 +1 1 +.names 21973 21974 10139 +1- 1 +-1 1 +.names 10139 10140 +1 1 +.names 21975 21974 10141 +1- 1 +-1 1 +.names 10141 10142 +1 1 +.names 21976 21974 10143 +1- 1 +-1 1 +.names 10143 10144 +1 1 +.names 21977 21974 10145 +1- 1 +-1 1 +.names 10145 10146 +1 1 +.names 10149 57135 +0 1 +.names 21978 21974 10148 +1- 1 +-1 1 +.names 10148 10149 +1 1 +.names 10152 57136 +0 1 +.names 21979 21974 10151 +1- 1 +-1 1 +.names 10151 10152 +1 1 +.names 21980 21974 10153 +1- 1 +-1 1 +.names 10153 10154 +1 1 +.names 21983 21974 10155 +1- 1 +-1 1 +.names 10155 10156 +1 1 +.names 578 10157 +0 1 +.names 10157 10158 +1 1 +.names 10162 10159 +0 1 +.names 10159 10160 +1 1 +.names 51447 51448 10161 +1- 1 +-1 1 +.names 10161 10162 +1 1 +.names 10160 10163 +1 1 +.names 9773 10164 +0 1 +.names 10164 10165 +1 1 +.names 21990 22107 10166 +1- 1 +-1 1 +.names 10166 10167 +1 1 +.names 22021 22108 10168 +1- 1 +-1 1 +.names 10168 10169 +1 1 +.names 21990 22064 10170 +1- 1 +-1 1 +.names 10170 10171 +1 1 +.names 22021 22065 10172 +1- 1 +-1 1 +.names 10172 10173 +1 1 +.names 22060 22070 10174 +1- 1 +-1 1 +.names 10174 10175 +1 1 +.names 21990 22066 10176 +1- 1 +-1 1 +.names 10176 10177 +1 1 +.names 22060 22104 10178 +1- 1 +-1 1 +.names 10178 10179 +1 1 +.names 21977 22105 10180 +1- 1 +-1 1 +.names 10180 10181 +1 1 +.names 22021 22109 10182 +1- 1 +-1 1 +.names 10182 10183 +1 1 +.names 21977 22011 10184 +1- 1 +-1 1 +.names 10184 10185 +1 1 +.names 21987 22066 10186 +1- 1 +-1 1 +.names 10186 10187 +1 1 +.names 22009 22010 10188 +1- 1 +-1 1 +.names 10188 10189 +1 1 +.names 21987 22064 10190 +1- 1 +-1 1 +.names 10190 10191 +1 1 +.names 22009 22104 10192 +1- 1 +-1 1 +.names 10192 10193 +1 1 +.names 22009 22107 10194 +1- 1 +-1 1 +.names 10194 10195 +1 1 +.names 21987 22070 10196 +1- 1 +-1 1 +.names 10196 10197 +1 1 +.names 22017 22108 10198 +1- 1 +-1 1 +.names 10198 10199 +1 1 +.names 22017 22105 10200 +1- 1 +-1 1 +.names 10200 10201 +1 1 +.names 22017 22071 10202 +1- 1 +-1 1 +.names 10202 10203 +1 1 +.names 22017 22011 10204 +1- 1 +-1 1 +.names 10204 10205 +1 1 +.names 21983 22067 10206 +1- 1 +-1 1 +.names 10206 10207 +1 1 +.names 22017 22109 10208 +1- 1 +-1 1 +.names 10208 10209 +1 1 +.names 21981 21982 10210 +1- 1 +-1 1 +.names 10210 10211 +1 1 +.names 10160 10212 +1 1 +.names 22006 22062 10213 +1- 1 +-1 1 +.names 10213 10214 +1 1 +.names 22000 22062 10215 +1- 1 +-1 1 +.names 10215 10216 +1 1 +.names 21993 22062 10217 +1- 1 +-1 1 +.names 10217 10218 +1 1 +.names 21996 22062 10219 +1- 1 +-1 1 +.names 10219 10220 +1 1 +.names 21982 22064 10221 +1- 1 +-1 1 +.names 10221 10222 +1 1 +.names 21984 22064 10223 +1- 1 +-1 1 +.names 10223 10224 +1 1 +.names 22005 22064 10225 +1- 1 +-1 1 +.names 10225 10226 +1 1 +.names 22007 22064 10227 +1- 1 +-1 1 +.names 10227 10228 +1 1 +.names 22016 22064 10229 +1- 1 +-1 1 +.names 10229 10230 +1 1 +.names 22065 22001 10231 +1- 1 +-1 1 +.names 10231 10232 +1 1 +.names 22057 22065 10233 +1- 1 +-1 1 +.names 10233 10234 +1 1 +.names 21991 22065 10235 +1- 1 +-1 1 +.names 10235 10236 +1 1 +.names 21978 22065 10237 +1- 1 +-1 1 +.names 10237 10238 +1 1 +.names 21995 22065 10239 +1- 1 +-1 1 +.names 10239 10240 +1 1 +.names 22015 22065 10241 +1- 1 +-1 1 +.names 10241 10242 +1 1 +.names 21996 22065 10243 +1- 1 +-1 1 +.names 10243 10244 +1 1 +.names 22059 22104 10245 +1- 1 +-1 1 +.names 10245 10246 +1 1 +.names 22068 22104 10247 +1- 1 +-1 1 +.names 10247 10248 +1 1 +.names 22016 22104 10249 +1- 1 +-1 1 +.names 10249 10250 +1 1 +.names 22057 22105 10251 +1- 1 +-1 1 +.names 10251 10252 +1 1 +.names 21976 22105 10253 +1- 1 +-1 1 +.names 10253 10254 +1 1 +.names 22013 22105 10255 +1- 1 +-1 1 +.names 10255 10256 +1 1 +.names 22014 22105 10257 +1- 1 +-1 1 +.names 10257 10258 +1 1 +.names 22015 22105 10259 +1- 1 +-1 1 +.names 10259 10260 +1 1 +.names 21993 22071 10261 +1- 1 +-1 1 +.names 10261 10262 +1 1 +.names 21997 22010 10263 +1- 1 +-1 1 +.names 10263 10264 +1 1 +.names 22004 22010 10265 +1- 1 +-1 1 +.names 10265 10266 +1 1 +.names 22005 22010 10267 +1- 1 +-1 1 +.names 10267 10268 +1 1 +.names 22006 22010 10269 +1- 1 +-1 1 +.names 10269 10270 +1 1 +.names 21986 22010 10271 +1- 1 +-1 1 +.names 10271 10272 +1 1 +.names 22016 22010 10273 +1- 1 +-1 1 +.names 10273 10274 +1 1 +.names 22011 22012 10275 +1- 1 +-1 1 +.names 10275 10276 +1 1 +.names 21975 22011 10277 +1- 1 +-1 1 +.names 10277 10278 +1 1 +.names 21991 22011 10279 +1- 1 +-1 1 +.names 10279 10280 +1 1 +.names 22013 22011 10281 +1- 1 +-1 1 +.names 10281 10282 +1 1 +.names 22014 22011 10283 +1- 1 +-1 1 +.names 10283 10284 +1 1 +.names 21991 21992 10285 +1- 1 +-1 1 +.names 10285 10286 +1 1 +.names 21993 21992 10287 +1- 1 +-1 1 +.names 10287 10288 +1 1 +.names 21994 21992 10289 +1- 1 +-1 1 +.names 10289 10290 +1 1 +.names 21995 21992 10291 +1- 1 +-1 1 +.names 10291 10292 +1 1 +.names 21980 21992 10293 +1- 1 +-1 1 +.names 10293 10294 +1 1 +.names 21996 21992 10295 +1- 1 +-1 1 +.names 10295 10296 +1 1 +.names 21982 22061 10297 +1- 1 +-1 1 +.names 10297 10298 +1 1 +.names 22059 22061 10299 +1- 1 +-1 1 +.names 10299 10300 +1 1 +.names 21978 22109 10301 +1- 1 +-1 1 +.names 10301 10302 +1 1 +.names 22014 22109 10303 +1- 1 +-1 1 +.names 10303 10304 +1 1 +.names 21984 22066 10305 +1- 1 +-1 1 +.names 10305 10306 +1 1 +.names 22068 22066 10307 +1- 1 +-1 1 +.names 10307 10308 +1 1 +.names 22008 22066 10309 +1- 1 +-1 1 +.names 10309 10310 +1 1 +.names 21975 22067 10311 +1- 1 +-1 1 +.names 10311 10312 +1 1 +.names 22058 22067 10313 +1- 1 +-1 1 +.names 10313 10314 +1 1 +.names 21993 22067 10315 +1- 1 +-1 1 +.names 10315 10316 +1 1 +.names 22013 22067 10317 +1- 1 +-1 1 +.names 10317 10318 +1 1 +.names 21979 22067 10319 +1- 1 +-1 1 +.names 10319 10320 +1 1 +.names 22015 22067 10321 +1- 1 +-1 1 +.names 10321 10322 +1 1 +.names 10326 10323 +0 1 +.names 10323 10324 +1 1 +.names 51465 51462 10325 +1- 1 +-1 1 +.names 10325 10326 +1 1 +.names 10330 10327 +0 1 +.names 10327 10328 +1 1 +.names 51464 51462 10329 +1- 1 +-1 1 +.names 10329 10330 +1 1 +.names 10334 10331 +0 1 +.names 10331 10332 +1 1 +.names 51463 51462 10333 +1- 1 +-1 1 +.names 10333 10334 +1 1 +.names 10338 10335 +0 1 +.names 10335 10336 +1 1 +.names 51461 51462 10337 +1- 1 +-1 1 +.names 10337 10338 +1 1 +.names 10342 10339 +0 1 +.names 10339 10340 +1 1 +.names 51465 51466 10341 +1- 1 +-1 1 +.names 10341 10342 +1 1 +.names 10346 10343 +0 1 +.names 10343 10344 +1 1 +.names 51464 51466 10345 +1- 1 +-1 1 +.names 10345 10346 +1 1 +.names 10350 10347 +0 1 +.names 10347 10348 +1 1 +.names 51463 51466 10349 +1- 1 +-1 1 +.names 10349 10350 +1 1 +.names 10354 10351 +0 1 +.names 10351 10352 +1 1 +.names 51466 51461 10353 +1- 1 +-1 1 +.names 10353 10354 +1 1 +.names 373 10355 +0 1 +.names 10355 10356 +1 1 +.names 372 10357 +0 1 +.names 10357 10358 +1 1 +.names 371 10359 +0 1 +.names 10359 10360 +1 1 +.names 369 10361 +0 1 +.names 10361 10362 +1 1 +.names 367 10363 +0 1 +.names 10363 10364 +1 1 +.names 366 10365 +0 1 +.names 10365 10366 +1 1 +.names 10370 10367 +0 1 +.names 10367 10368 +1 1 +.names 51471 51478 10369 +1- 1 +-1 1 +.names 10369 10370 +1 1 +.names 10374 10371 +0 1 +.names 10371 10372 +1 1 +.names 51472 51474 10373 +1- 1 +-1 1 +.names 10373 10374 +1 1 +.names 22121 22182 10375 +1- 1 +-1 1 +.names 10375 10376 +1 1 +.names 22141 22189 10377 +1- 1 +-1 1 +.names 10377 10378 +1 1 +.names 22119 22182 10379 +1- 1 +-1 1 +.names 10379 10380 +1 1 +.names 22185 22223 10381 +1- 1 +-1 1 +.names 10381 10382 +1 1 +.names 22118 22182 10383 +1- 1 +-1 1 +.names 10383 10384 +1 1 +.names 22125 22126 10385 +1- 1 +-1 1 +.names 10385 10386 +1 1 +.names 22185 22182 10387 +1- 1 +-1 1 +.names 10387 10388 +1 1 +.names 22187 22123 10389 +1- 1 +-1 1 +.names 10389 10390 +1 1 +.names 22177 22178 10391 +1- 1 +-1 1 +.names 10391 10392 +1 1 +.names 22122 22123 10393 +1- 1 +-1 1 +.names 10393 10394 +1 1 +.names 22142 22189 10395 +1- 1 +-1 1 +.names 10395 10396 +1 1 +.names 22184 22182 10397 +1- 1 +-1 1 +.names 10397 10398 +1 1 +.names 22182 22183 10399 +1- 1 +-1 1 +.names 10399 10400 +1 1 +.names 22133 22178 10401 +1- 1 +-1 1 +.names 10401 10402 +1 1 +.names 22189 22111 10403 +1- 1 +-1 1 +.names 10403 10404 +1 1 +.names 22143 22138 10405 +1- 1 +-1 1 +.names 10405 10406 +1 1 +.names 22186 22182 10407 +1- 1 +-1 1 +.names 10407 10408 +1 1 +.names 22190 22189 10409 +1- 1 +-1 1 +.names 10409 10410 +1 1 +.names 22113 22182 10411 +1- 1 +-1 1 +.names 10411 10412 +1 1 +.names 22133 22122 10413 +1- 1 +-1 1 +.names 10413 10414 +1 1 +.names 22133 22187 10415 +1- 1 +-1 1 +.names 10415 10416 +1 1 +.names 22120 22182 10417 +1- 1 +-1 1 +.names 10417 10418 +1 1 +.names 22140 22182 10419 +1- 1 +-1 1 +.names 10419 10420 +1 1 +.names 22175 22139 10421 +1- 1 +-1 1 +.names 10421 10422 +1 1 +.names 22136 22137 10423 +1- 1 +-1 1 +.names 10423 10424 +1 1 +.names 22114 22182 10425 +1- 1 +-1 1 +.names 10425 10426 +1 1 +.names 22176 22189 10427 +1- 1 +-1 1 +.names 10427 10428 +1 1 +.names 22143 22189 10429 +1- 1 +-1 1 +.names 10429 10430 +1 1 +.names 22171 22126 10431 +1- 1 +-1 1 +.names 10431 10432 +1 1 +.names 10436 10433 +0 1 +.names 10433 10434 +1 1 +.names 51473 51469 10435 +1- 1 +-1 1 +.names 10435 10436 +1 1 +.names 10434 10437 +1 1 +.names 10434 10438 +1 1 +.names 10434 10439 +1 1 +.names 10443 10440 +0 1 +.names 10440 10441 +1 1 +.names 51473 51474 10442 +1- 1 +-1 1 +.names 10442 10443 +1 1 +.names 10441 10444 +1 1 +.names 10441 10445 +1 1 +.names 10449 10446 +0 1 +.names 10446 10447 +1 1 +.names 51473 51478 10448 +1- 1 +-1 1 +.names 10448 10449 +1 1 +.names 10447 10450 +1 1 +.names 10447 10451 +1 1 +.names 10447 10452 +1 1 +.names 10456 10453 +0 1 +.names 10453 10454 +1 1 +.names 51473 51477 10455 +1- 1 +-1 1 +.names 10455 10456 +1 1 +.names 10454 10457 +1 1 +.names 10454 10458 +1 1 +.names 10454 10459 +1 1 +.names 10463 10460 +0 1 +.names 10460 10461 +1 1 +.names 51472 51469 10462 +1- 1 +-1 1 +.names 10462 10463 +1 1 +.names 10461 10464 +1 1 +.names 10461 10465 +1 1 +.names 10469 10466 +0 1 +.names 10466 10467 +1 1 +.names 51472 51478 10468 +1- 1 +-1 1 +.names 10468 10469 +1 1 +.names 10467 10470 +1 1 +.names 10467 10471 +1 1 +.names 10467 10472 +1 1 +.names 10476 10473 +0 1 +.names 10473 10474 +1 1 +.names 51472 51477 10475 +1- 1 +-1 1 +.names 10475 10476 +1 1 +.names 10474 10477 +1 1 +.names 10474 10478 +1 1 +.names 10474 10479 +1 1 +.names 10483 10480 +0 1 +.names 10480 10481 +1 1 +.names 51471 51469 10482 +1- 1 +-1 1 +.names 10482 10483 +1 1 +.names 10481 10484 +1 1 +.names 10481 10485 +1 1 +.names 10481 10486 +1 1 +.names 10490 10487 +0 1 +.names 10487 10488 +1 1 +.names 51471 51474 10489 +1- 1 +-1 1 +.names 10489 10490 +1 1 +.names 10488 10491 +1 1 +.names 10488 10492 +1 1 +.names 10488 10493 +1 1 +.names 10497 10494 +0 1 +.names 10494 10495 +1 1 +.names 51471 51477 10496 +1- 1 +-1 1 +.names 10496 10497 +1 1 +.names 10495 10498 +1 1 +.names 10495 10499 +1 1 +.names 10495 10500 +1 1 +.names 10372 10501 +1 1 +.names 10372 10502 +1 1 +.names 10372 10503 +1 1 +.names 10507 10504 +0 1 +.names 10504 10505 +1 1 +.names 51477 51470 10506 +1- 1 +-1 1 +.names 10506 10507 +1 1 +.names 10505 10508 +1 1 +.names 10505 10509 +1 1 +.names 10505 10510 +1 1 +.names 10331 10511 +1 1 +.names 10327 10512 +1 1 +.names 10323 10513 +1 1 +.names 10517 10514 +0 1 +.names 10514 10515 +1 1 +.names 51474 51470 10516 +1- 1 +-1 1 +.names 10516 10517 +1 1 +.names 10515 10518 +1 1 +.names 10515 10519 +1 1 +.names 10515 10520 +1 1 +.names 10524 10521 +0 1 +.names 10521 10522 +1 1 +.names 51478 51470 10523 +1- 1 +-1 1 +.names 10523 10524 +1 1 +.names 10522 10525 +1 1 +.names 10522 10526 +1 1 +.names 10522 10527 +1 1 +.names 10339 10528 +1 1 +.names 10368 10529 +1 1 +.names 10368 10530 +1 1 +.names 10368 10531 +1 1 +.names 10343 10532 +1 1 +.names 10347 10533 +1 1 +.names 10335 10534 +1 1 +.names 10537 10535 +0 1 +.names 10535 10536 +1 1 +.names 370 10537 +1 1 +.names 368 10538 +0 1 +.names 10538 10539 +1 1 +.names 10543 10540 +0 1 +.names 10540 10541 +1 1 +.names 51469 51470 10542 +1- 1 +-1 1 +.names 10542 10543 +1 1 +.names 10541 10544 +1 1 +.names 10364 10545 +0 1 +.names 10545 10546 +1 1 +.names 22134 22187 10547 +1- 1 +-1 1 +.names 10547 10548 +1 1 +.names 22180 22178 10549 +1- 1 +-1 1 +.names 10549 10550 +1 1 +.names 22134 22122 10551 +1- 1 +-1 1 +.names 10551 10552 +1 1 +.names 22180 22225 10553 +1- 1 +-1 1 +.names 10553 10554 +1 1 +.names 22134 22172 10555 +1- 1 +-1 1 +.names 10555 10556 +1 1 +.names 22224 22223 10557 +1- 1 +-1 1 +.names 10557 10558 +1 1 +.names 22129 22125 10559 +1- 1 +-1 1 +.names 10559 10560 +1 1 +.names 22129 22138 10561 +1- 1 +-1 1 +.names 10561 10562 +1 1 +.names 22129 22171 10563 +1- 1 +-1 1 +.names 10563 10564 +1 1 +.names 22124 22122 10565 +1- 1 +-1 1 +.names 10565 10566 +1 1 +.names 22124 22136 10567 +1- 1 +-1 1 +.names 10567 10568 +1 1 +.names 22188 22187 10569 +1- 1 +-1 1 +.names 10569 10570 +1 1 +.names 22146 22189 10571 +1- 1 +-1 1 +.names 10571 10572 +1 1 +.names 22146 22138 10573 +1- 1 +-1 1 +.names 10573 10574 +1 1 +.names 22135 22175 10575 +1- 1 +-1 1 +.names 10575 10576 +1 1 +.names 22146 22223 10577 +1- 1 +-1 1 +.names 10577 10578 +1 1 +.names 22135 22125 10579 +1- 1 +-1 1 +.names 10579 10580 +1 1 +.names 10541 10581 +1 1 +.names 22113 22189 10582 +1- 1 +-1 1 +.names 10582 10583 +1 1 +.names 22118 22136 10584 +1- 1 +-1 1 +.names 10584 10585 +1 1 +.names 22119 22136 10586 +1- 1 +-1 1 +.names 10586 10587 +1 1 +.names 22144 22136 10588 +1- 1 +-1 1 +.names 10588 10589 +1 1 +.names 22145 22136 10590 +1- 1 +-1 1 +.names 10590 10591 +1 1 +.names 22138 22139 10592 +1- 1 +-1 1 +.names 10592 10593 +1 1 +.names 22140 22138 10594 +1- 1 +-1 1 +.names 10594 10595 +1 1 +.names 22141 22138 10596 +1- 1 +-1 1 +.names 10596 10597 +1 1 +.names 22142 22138 10598 +1- 1 +-1 1 +.names 10598 10599 +1 1 +.names 22127 22125 10600 +1- 1 +-1 1 +.names 10600 10601 +1 1 +.names 22128 22125 10602 +1- 1 +-1 1 +.names 10602 10603 +1 1 +.names 22130 22125 10604 +1- 1 +-1 1 +.names 10604 10605 +1 1 +.names 22131 22125 10606 +1- 1 +-1 1 +.names 10606 10607 +1 1 +.names 22132 22125 10608 +1- 1 +-1 1 +.names 10608 10609 +1 1 +.names 22115 22116 10610 +1- 1 +-1 1 +.names 10610 10611 +1 1 +.names 22117 22116 10612 +1- 1 +-1 1 +.names 10612 10613 +1 1 +.names 22118 22116 10614 +1- 1 +-1 1 +.names 10614 10615 +1 1 +.names 22119 22116 10616 +1- 1 +-1 1 +.names 10616 10617 +1 1 +.names 22120 22116 10618 +1- 1 +-1 1 +.names 10618 10619 +1 1 +.names 22110 22111 10620 +1- 1 +-1 1 +.names 10620 10621 +1 1 +.names 22112 22110 10622 +1- 1 +-1 1 +.names 10622 10623 +1 1 +.names 22113 22110 10624 +1- 1 +-1 1 +.names 10624 10625 +1 1 +.names 22114 22110 10626 +1- 1 +-1 1 +.names 10626 10627 +1 1 +.names 22121 22110 10628 +1- 1 +-1 1 +.names 10628 10629 +1 1 +.names 22115 22172 10630 +1- 1 +-1 1 +.names 10630 10631 +1 1 +.names 22173 22172 10632 +1- 1 +-1 1 +.names 10632 10633 +1 1 +.names 22118 22172 10634 +1- 1 +-1 1 +.names 10634 10635 +1 1 +.names 22174 22172 10636 +1- 1 +-1 1 +.names 10636 10637 +1 1 +.names 22127 22171 10638 +1- 1 +-1 1 +.names 10638 10639 +1 1 +.names 22128 22171 10640 +1- 1 +-1 1 +.names 10640 10641 +1 1 +.names 22114 22171 10642 +1- 1 +-1 1 +.names 10642 10643 +1 1 +.names 22121 22171 10644 +1- 1 +-1 1 +.names 10644 10645 +1 1 +.names 22177 22225 10646 +1- 1 +-1 1 +.names 10646 10647 +1 1 +.names 22179 22225 10648 +1- 1 +-1 1 +.names 10648 10649 +1 1 +.names 22226 22225 10650 +1- 1 +-1 1 +.names 10650 10651 +1 1 +.names 22181 22225 10652 +1- 1 +-1 1 +.names 10652 10653 +1 1 +.names 22174 22225 10654 +1- 1 +-1 1 +.names 10654 10655 +1 1 +.names 22223 22126 10656 +1- 1 +-1 1 +.names 10656 10657 +1 1 +.names 22176 22223 10658 +1- 1 +-1 1 +.names 10658 10659 +1 1 +.names 22190 22223 10660 +1- 1 +-1 1 +.names 10660 10661 +1 1 +.names 22130 22223 10662 +1- 1 +-1 1 +.names 10662 10663 +1 1 +.names 22142 22223 10664 +1- 1 +-1 1 +.names 10664 10665 +1 1 +.names 22179 22178 10666 +1- 1 +-1 1 +.names 10666 10667 +1 1 +.names 22181 22178 10668 +1- 1 +-1 1 +.names 10668 10669 +1 1 +.names 22120 22178 10670 +1- 1 +-1 1 +.names 10670 10671 +1 1 +.names 22176 22175 10672 +1- 1 +-1 1 +.names 10672 10673 +1 1 +.names 22128 22175 10674 +1- 1 +-1 1 +.names 10674 10675 +1 1 +.names 22113 22175 10676 +1- 1 +-1 1 +.names 10676 10677 +1 1 +.names 22141 22175 10678 +1- 1 +-1 1 +.names 10678 10679 +1 1 +.names 22131 22175 10680 +1- 1 +-1 1 +.names 10680 10681 +1 1 +.names 22143 22175 10682 +1- 1 +-1 1 +.names 10682 10683 +1 1 +.names 6790 10684 +1 1 +.names 10684 10685 +0 1 +.names 4092 10686 +0 1 +.names 2413 10693 10687 +11 1 +.names 10687 10688 +1 1 +.names 10688 10689 +0 1 +.names 10713 10690 +0 1 +.names 10690 10691 +1 1 +.names 10691 10692 +0 1 +.names 6844 10693 +0 1 +.names 10693 10694 +1 1 +.names 10694 10695 +0 1 +.names 10704 10705 10696 +11 1 +.names 10696 10697 +1 1 +.names 10697 10698 +0 1 +.names 10695 10698 10699 +1- 1 +-1 1 +.names 2413 10700 +1 1 +.names 10700 10701 +0 1 +.names 10699 10701 10702 +1- 1 +-1 1 +.names 961 10703 +0 1 +.names 962 10704 +0 1 +.names 963 10705 +0 1 +.names 10705 10706 +1 1 +.names 10706 10707 +0 1 +.names 10707 10708 +1 1 +.names 10693 10709 +1 1 +.names 10709 10710 +0 1 +.names 10708 10711 +0 1 +.names 10710 10711 10712 +1- 1 +-1 1 +.names 10704 10713 +1 1 +.names 10712 10690 10714 +1- 1 +-1 1 +.names 10721 10725 10715 +1- 1 +-1 1 +.names 10715 10716 +1 1 +.names 7105 10717 +0 1 +.names 268 10718 +0 1 +.names 10718 10719 +1 1 +.names 10719 10720 +0 1 +.names 10717 10720 10721 +11 1 +.names 964 10722 +0 1 +.names 10722 10723 +1 1 +.names 10723 10724 +0 1 +.names 7105 10724 10725 +11 1 +.names 10729 2413 10726 +11 1 +.names 10726 10727 +1 1 +.names 10727 10728 +0 1 +.names 913 10729 +0 1 +.names 10705 10704 10730 +11 1 +.names 10730 10731 +1 1 +.names 2413 10732 +1 1 +.names 10729 10733 +1 1 +.names 10733 10734 +0 1 +.names 962 10734 10735 +1- 1 +-1 1 +.names 10732 10736 +0 1 +.names 10735 10736 10737 +1- 1 +-1 1 +.names 10731 10738 +0 1 +.names 913 10738 10739 +1- 1 +-1 1 +.names 10739 10736 10740 +1- 1 +-1 1 +.names 10743 2413 10741 +11 1 +.names 10741 10742 +1 1 +.names 7116 10743 +0 1 +.names 7108 10744 +0 1 +.names 10744 10745 +1 1 +.names 10748 10749 10746 +1- 1 +-1 1 +.names 10746 10747 +1 1 +.names 10742 10748 +0 1 +.names 10745 10749 +0 1 +.names 10756 10758 10750 +1- 1 +-1 1 +.names 10750 10751 +1 1 +.names 7112 10752 +0 1 +.names 10770 10773 10753 +11 1 +.names 10753 10754 +1 1 +.names 10754 10755 +0 1 +.names 10752 10755 10756 +11 1 +.names 965 10757 +0 1 +.names 7112 10757 10758 +11 1 +.names 10743 10763 10759 +1- 1 +-1 1 +.names 10759 10760 +1 1 +.names 45107 45110 10761 +1- 1 +-1 1 +.names 10761 10762 +1 1 +.names 10762 10763 +0 1 +.names 10751 10764 +0 1 +.names 10784 10760 10765 +11 1 +.names 10765 10766 +1 1 +.names 10766 10767 +0 1 +.names 7120 10768 +0 1 +.names 10768 10769 +1 1 +.names 10747 10770 +0 1 +.names 10774 10775 10771 +1- 1 +-1 1 +.names 10771 10772 +1 1 +.names 10772 10773 +0 1 +.names 10769 10774 +0 1 +.names 10716 10775 +0 1 +.names 10778 10744 10776 +1- 1 +-1 1 +.names 10776 10777 +1 1 +.names 966 10778 +0 1 +.names 10768 10786 10779 +1- 1 +-1 1 +.names 10779 10780 +1 1 +.names 10777 10780 10781 +11 1 +.names 2413 10782 +1 1 +.names 10782 10783 +1 1 +.names 10781 10783 10784 +11 1 +.names 46273 46276 56461 +1- 1 +-1 1 +.names 56461 10786 +0 1 +.names 2413 10793 10787 +11 1 +.names 10787 10788 +1 1 +.names 10788 10789 +0 1 +.names 10813 10790 +0 1 +.names 10790 10791 +1 1 +.names 10791 10792 +0 1 +.names 7163 10793 +0 1 +.names 10793 10794 +1 1 +.names 10794 10795 +0 1 +.names 10804 10805 10796 +11 1 +.names 10796 10797 +1 1 +.names 10797 10798 +0 1 +.names 10795 10798 10799 +1- 1 +-1 1 +.names 2413 10800 +1 1 +.names 10800 10801 +0 1 +.names 10799 10801 10802 +1- 1 +-1 1 +.names 967 10803 +0 1 +.names 968 10804 +0 1 +.names 969 10805 +0 1 +.names 10805 10806 +1 1 +.names 10806 10807 +0 1 +.names 10807 10808 +1 1 +.names 10793 10809 +1 1 +.names 10809 10810 +0 1 +.names 10808 10811 +0 1 +.names 10810 10811 10812 +1- 1 +-1 1 +.names 10804 10813 +1 1 +.names 10812 10790 10814 +1- 1 +-1 1 +.names 10818 2413 10815 +11 1 +.names 10815 10816 +1 1 +.names 10816 10817 +0 1 +.names 914 10818 +0 1 +.names 10805 10804 10819 +11 1 +.names 10819 10820 +1 1 +.names 2413 10821 +1 1 +.names 10818 10822 +1 1 +.names 10822 10823 +0 1 +.names 968 10823 10824 +1- 1 +-1 1 +.names 10821 10825 +0 1 +.names 10824 10825 10826 +1- 1 +-1 1 +.names 10820 10827 +0 1 +.names 914 10827 10828 +1- 1 +-1 1 +.names 10828 10825 10829 +1- 1 +-1 1 +.names 10832 2413 10830 +11 1 +.names 10830 10831 +1 1 +.names 7400 10832 +0 1 +.names 7392 10833 +0 1 +.names 10833 10834 +1 1 +.names 10837 10838 10835 +1- 1 +-1 1 +.names 10835 10836 +1 1 +.names 10831 10837 +0 1 +.names 10834 10838 +0 1 +.names 10845 10847 10839 +1- 1 +-1 1 +.names 10839 10840 +1 1 +.names 7396 10841 +0 1 +.names 10856 10859 10842 +11 1 +.names 10842 10843 +1 1 +.names 10843 10844 +0 1 +.names 10841 10844 10845 +11 1 +.names 970 10846 +0 1 +.names 7396 10846 10847 +11 1 +.names 10832 10763 10848 +1- 1 +-1 1 +.names 10848 10849 +1 1 +.names 10840 10850 +0 1 +.names 10869 10849 10851 +11 1 +.names 10851 10852 +1 1 +.names 10852 10853 +0 1 +.names 7404 10854 +0 1 +.names 10854 10855 +1 1 +.names 10836 10856 +0 1 +.names 10860 10861 10857 +1- 1 +-1 1 +.names 10857 10858 +1 1 +.names 10858 10859 +0 1 +.names 10855 10860 +0 1 +.names 650 10861 +0 1 +.names 10778 10833 10862 +1- 1 +-1 1 +.names 10862 10863 +1 1 +.names 10854 10786 10864 +1- 1 +-1 1 +.names 10864 10865 +1 1 +.names 10863 10865 10866 +11 1 +.names 2413 10867 +1 1 +.names 10867 10868 +1 1 +.names 10866 10868 10869 +11 1 +.names 6351 10870 +0 1 +.names 10870 7423 10871 +11 1 +.names 10871 10872 +1 1 +.names 10872 10873 +0 1 +.names 6347 10874 +0 1 +.names 7488 10875 +0 1 +.names 7479 10875 10876 +1- 1 +-1 1 +.names 10885 10882 10877 +11 1 +.names 10877 10878 +1 1 +.names 10878 10879 +0 1 +.names 10882 10875 10880 +11 1 +.names 10880 10881 +1 1 +.names 7490 10882 +0 1 +.names 10885 10875 10883 +11 1 +.names 10883 10884 +1 1 +.names 7489 10885 +0 1 +.names 10882 7494 10886 +11 1 +.names 10886 10887 +1 1 +.names 10887 10888 +0 1 +.names 7479 7490 10889 +1- 1 +-1 1 +.names 10884 10890 +0 1 +.names 10889 10890 10891 +1- 1 +-1 1 +.names 6319 10892 +0 1 +.names 10895 10885 10893 +11 1 +.names 10893 10894 +1 1 +.names 6313 10895 +0 1 +.names 7494 10892 10896 +11 1 +.names 10896 10897 +1 1 +.names 10897 10898 +0 1 +.names 10894 10899 +0 1 +.names 10898 10899 10900 +1- 1 +-1 1 +.names 10881 10901 +0 1 +.names 10900 10901 10902 +1- 1 +-1 1 +.names 6307 10903 +0 1 +.names 10885 10875 10904 +11 1 +.names 10904 10905 +1 1 +.names 10882 10906 +1 1 +.names 10906 10907 +0 1 +.names 10907 10898 10908 +1- 1 +-1 1 +.names 10905 10909 +0 1 +.names 10908 10909 10910 +1- 1 +-1 1 +.names 7511 10911 +1 1 +.names 10911 10912 +0 1 +.names 6301 10913 +0 1 +.names 10918 10921 10914 +11 1 +.names 10914 10915 +1 1 +.names 28174 28175 10916 +1- 1 +-1 1 +.names 10916 10917 +1 1 +.names 10917 10918 +0 1 +.names 28046 28047 10919 +1- 1 +-1 1 +.names 10919 10920 +1 1 +.names 10920 10921 +0 1 +.names 10926 10929 10922 +11 1 +.names 10922 10923 +1 1 +.names 27739 27740 10924 +1- 1 +-1 1 +.names 10924 10925 +1 1 +.names 10925 10926 +0 1 +.names 27838 27839 10927 +1- 1 +-1 1 +.names 10927 10928 +1 1 +.names 10928 10929 +0 1 +.names 10932 10933 10930 +1- 1 +-1 1 +.names 10930 10931 +1 1 +.names 10915 10932 +0 1 +.names 10923 10933 +0 1 +.names 10938 10941 10934 +11 1 +.names 10934 10935 +1 1 +.names 28126 28127 10936 +1- 1 +-1 1 +.names 10936 10937 +1 1 +.names 10937 10938 +0 1 +.names 27772 27773 10939 +1- 1 +-1 1 +.names 10939 10940 +1 1 +.names 10940 10941 +0 1 +.names 10946 10949 10942 +11 1 +.names 10942 10943 +1 1 +.names 27934 27935 10944 +1- 1 +-1 1 +.names 10944 10945 +1 1 +.names 10945 10946 +0 1 +.names 27870 27871 10947 +1- 1 +-1 1 +.names 10947 10948 +1 1 +.names 10948 10949 +0 1 +.names 10952 10953 10950 +1- 1 +-1 1 +.names 10950 10951 +1 1 +.names 10935 10952 +0 1 +.names 10943 10953 +0 1 +.names 10956 10957 10954 +11 1 +.names 10954 10955 +1 1 +.names 10931 10956 +0 1 +.names 10951 10957 +0 1 +.names 10962 10965 10958 +11 1 +.names 10958 10959 +1 1 +.names 27789 27790 10960 +1- 1 +-1 1 +.names 10960 10961 +1 1 +.names 10961 10962 +0 1 +.names 28078 28079 10963 +1- 1 +-1 1 +.names 10963 10964 +1 1 +.names 10964 10965 +0 1 +.names 10970 10973 10966 +11 1 +.names 10966 10967 +1 1 +.names 28142 28143 10968 +1- 1 +-1 1 +.names 10968 10969 +1 1 +.names 10969 10970 +0 1 +.names 27886 27887 10971 +1- 1 +-1 1 +.names 10971 10972 +1 1 +.names 10972 10973 +0 1 +.names 10976 10977 10974 +1- 1 +-1 1 +.names 10974 10975 +1 1 +.names 10959 10976 +0 1 +.names 10967 10977 +0 1 +.names 10982 10985 10978 +11 1 +.names 10978 10979 +1 1 +.names 28062 28063 10980 +1- 1 +-1 1 +.names 10980 10981 +1 1 +.names 10981 10982 +0 1 +.names 27755 27756 10983 +1- 1 +-1 1 +.names 10983 10984 +1 1 +.names 10984 10985 +0 1 +.names 10990 10993 10986 +11 1 +.names 10986 10987 +1 1 +.names 27854 27855 10988 +1- 1 +-1 1 +.names 10988 10989 +1 1 +.names 10989 10990 +0 1 +.names 27705 27706 10991 +1- 1 +-1 1 +.names 10991 10992 +1 1 +.names 10992 10993 +0 1 +.names 10996 10997 10994 +1- 1 +-1 1 +.names 10994 10995 +1 1 +.names 10979 10996 +0 1 +.names 10987 10997 +0 1 +.names 11000 11001 10998 +11 1 +.names 10998 10999 +1 1 +.names 10975 11000 +0 1 +.names 10995 11001 +0 1 +.names 11004 11005 11002 +1- 1 +-1 1 +.names 11002 11003 +1 1 +.names 10955 11004 +0 1 +.names 10999 11005 +0 1 +.names 11010 11013 11006 +11 1 +.names 11006 11007 +1 1 +.names 27918 27919 11008 +1- 1 +-1 1 +.names 11008 11009 +1 1 +.names 11009 11010 +0 1 +.names 28014 28015 11011 +1- 1 +-1 1 +.names 11011 11012 +1 1 +.names 11012 11013 +0 1 +.names 11018 11021 11014 +11 1 +.names 11014 11015 +1 1 +.names 28190 28191 11016 +1- 1 +-1 1 +.names 11016 11017 +1 1 +.names 11017 11018 +0 1 +.names 27966 27967 11019 +1- 1 +-1 1 +.names 11019 11020 +1 1 +.names 11020 11021 +0 1 +.names 11026 11029 11022 +11 1 +.names 11022 11023 +1 1 +.names 27822 27823 11024 +1- 1 +-1 1 +.names 11024 11025 +1 1 +.names 11025 11026 +0 1 +.names 28158 28159 11027 +1- 1 +-1 1 +.names 11027 11028 +1 1 +.names 11028 11029 +0 1 +.names 11034 11037 11030 +11 1 +.names 11030 11031 +1 1 +.names 27998 27999 11032 +1- 1 +-1 1 +.names 11032 11033 +1 1 +.names 11033 11034 +0 1 +.names 27950 27951 11035 +1- 1 +-1 1 +.names 11035 11036 +1 1 +.names 11036 11037 +0 1 +.names 11042 11045 11038 +11 1 +.names 11038 11039 +1 1 +.names 27806 27807 11040 +1- 1 +-1 1 +.names 11040 11041 +1 1 +.names 11041 11042 +0 1 +.names 27982 27983 11043 +1- 1 +-1 1 +.names 11043 11044 +1 1 +.names 11044 11045 +0 1 +.names 11050 11053 11046 +11 1 +.names 11046 11047 +1 1 +.names 28110 28111 11048 +1- 1 +-1 1 +.names 11048 11049 +1 1 +.names 11049 11050 +0 1 +.names 28206 28207 11051 +1- 1 +-1 1 +.names 11051 11052 +1 1 +.names 11052 11053 +0 1 +.names 11003 11054 +0 1 +.names 11060 11063 11055 +1- 1 +-1 1 +.names 11055 11056 +1 1 +.names 11056 11057 +0 1 +.names 11081 11031 11058 +11 1 +.names 11058 11059 +1 1 +.names 11059 11060 +0 1 +.names 11083 11061 +0 1 +.names 11061 11062 +1 1 +.names 11062 11063 +0 1 +.names 11068 11071 11064 +11 1 +.names 11064 11065 +1 1 +.names 28094 28095 11066 +1- 1 +-1 1 +.names 11066 11067 +1 1 +.names 11067 11068 +0 1 +.names 27902 27903 11069 +1- 1 +-1 1 +.names 11069 11070 +1 1 +.names 11070 11071 +0 1 +.names 11076 11079 11072 +11 1 +.names 11072 11073 +1 1 +.names 27722 27723 11074 +1- 1 +-1 1 +.names 11074 11075 +1 1 +.names 11075 11076 +0 1 +.names 28030 28031 11077 +1- 1 +-1 1 +.names 11077 11078 +1 1 +.names 11078 11079 +0 1 +.names 11007 11015 11080 +11 1 +.names 11080 11023 11081 +11 1 +.names 11088 11089 11082 +1- 1 +-1 1 +.names 11082 11083 +1 1 +.names 11039 11084 +0 1 +.names 11047 11085 +0 1 +.names 11084 11085 11086 +1- 1 +-1 1 +.names 11065 11087 +0 1 +.names 11086 11087 11088 +1- 1 +-1 1 +.names 11073 11089 +0 1 +.names 7526 11090 +1 1 +.names 11090 11091 +0 1 +.names 972 11092 +0 1 +.names 7526 11093 +1 1 +.names 11093 11094 +0 1 +.names 8098 11099 11095 +1- 1 +-1 1 +.names 11095 11096 +1 1 +.names 11101 11103 11097 +01 1 +10 1 +.names 11097 11098 +1 1 +.names 11098 11099 +0 1 +.names 29066 29067 11100 +1- 1 +-1 1 +.names 11100 11101 +1 1 +.names 28517 28518 11102 +1- 1 +-1 1 +.names 11102 11103 +1 1 +.names 7567 11104 +1 1 +.names 11104 11105 +0 1 +.names 2590 11106 +0 1 +.names 11110 11107 +0 1 +.names 11107 11108 +1 1 +.names 31616 31619 11109 +11 1 +.names 11109 11110 +1 1 +.names 11114 11111 +0 1 +.names 11111 11112 +1 1 +.names 32108 32109 11113 +11 1 +.names 11113 11114 +1 1 +.names 11118 11115 +0 1 +.names 11115 11116 +1 1 +.names 32108 32109 11117 +1- 1 +-1 1 +.names 11117 11118 +1 1 +.names 11122 11119 +0 1 +.names 11119 11120 +1 1 +.names 31741 31742 11121 +1- 1 +-1 1 +.names 11121 11122 +1 1 +.names 11126 11123 +0 1 +.names 11123 11124 +1 1 +.names 31624 31625 11125 +1- 1 +-1 1 +.names 11125 11126 +1 1 +.names 11130 11127 +0 1 +.names 11127 11128 +1 1 +.names 31405 31406 11129 +1- 1 +-1 1 +.names 11129 11130 +1 1 +.names 11134 11131 +0 1 +.names 11131 11132 +1 1 +.names 30927 30928 11133 +1- 1 +-1 1 +.names 11133 11134 +1 1 +.names 11138 11135 +0 1 +.names 11135 11136 +1 1 +.names 31929 31930 11137 +1- 1 +-1 1 +.names 11137 11138 +1 1 +.names 11142 11139 +0 1 +.names 11139 11140 +1 1 +.names 31504 31505 11141 +1- 1 +-1 1 +.names 11141 11142 +1 1 +.names 11146 11143 +0 1 +.names 11143 11144 +1 1 +.names 31739 31740 11145 +11 1 +.names 11145 11146 +1 1 +.names 11150 11147 +0 1 +.names 11147 11148 +1 1 +.names 31317 31318 11149 +11 1 +.names 11149 11150 +1 1 +.names 11154 11151 +0 1 +.names 11151 11152 +1 1 +.names 31739 31740 11153 +1- 1 +-1 1 +.names 11153 11154 +1 1 +.names 11158 11155 +0 1 +.names 11155 11156 +1 1 +.names 31317 31318 11157 +1- 1 +-1 1 +.names 11157 11158 +1 1 +.names 11162 11159 +0 1 +.names 11159 11160 +1 1 +.names 31159 31160 11161 +1- 1 +-1 1 +.names 11161 11162 +1 1 +.names 11166 11163 +0 1 +.names 11163 11164 +1 1 +.names 31315 31316 11165 +11 1 +.names 11165 11166 +1 1 +.names 11170 11167 +0 1 +.names 11167 11168 +1 1 +.names 31502 31503 11169 +1- 1 +-1 1 +.names 11169 11170 +1 1 +.names 11174 11171 +0 1 +.names 11171 11172 +1 1 +.names 31927 31928 11173 +1- 1 +-1 1 +.names 11173 11174 +1 1 +.names 11178 11175 +0 1 +.names 11175 11176 +1 1 +.names 31374 31375 11177 +11 1 +.names 11177 11178 +1 1 +.names 11182 11179 +0 1 +.names 11179 11180 +1 1 +.names 31924 31925 11181 +11 1 +.names 11181 11182 +1 1 +.names 11186 11183 +0 1 +.names 11183 11184 +1 1 +.names 30929 30930 11185 +11 1 +.names 11185 11186 +1 1 +.names 11190 11187 +0 1 +.names 11187 11188 +1 1 +.names 32110 32111 11189 +1- 1 +-1 1 +.names 11189 11190 +1 1 +.names 11194 11191 +0 1 +.names 11191 11192 +1 1 +.names 31407 31408 11193 +1- 1 +-1 1 +.names 11193 11194 +1 1 +.names 11198 11195 +0 1 +.names 11195 11196 +1 1 +.names 31319 31320 11197 +11 1 +.names 11197 11198 +1 1 +.names 11202 11199 +0 1 +.names 11199 11200 +1 1 +.names 31631 31632 11201 +1- 1 +-1 1 +.names 11201 11202 +1 1 +.names 11206 11203 +0 1 +.names 11203 11204 +1 1 +.names 31931 31932 11205 +1- 1 +-1 1 +.names 11205 11206 +1 1 +.names 11211 11214 11207 +11 1 +.names 11207 11208 +1 1 +.names 11399 11209 +0 1 +.names 11209 11210 +1 1 +.names 11210 11211 +0 1 +.names 11397 11212 +0 1 +.names 11212 11213 +1 1 +.names 11213 11214 +0 1 +.names 30925 30926 11215 +11 1 +.names 11215 11216 +1 1 +.names 11216 11217 +0 1 +.names 11243 11218 +0 1 +.names 11218 11219 +1 1 +.names 11219 11220 +0 1 +.names 11224 11221 +0 1 +.names 11221 11222 +1 1 +.names 31492 31495 11223 +11 1 +.names 11223 11224 +1 1 +.names 4185 11225 +1 1 +.names 11229 11226 +0 1 +.names 11226 11227 +1 1 +.names 31407 31408 11228 +11 1 +.names 11228 11229 +1 1 +.names 11233 11230 +0 1 +.names 11230 11231 +1 1 +.names 31180 11232 +0 1 +.names 11232 11233 +1 1 +.names 11237 11234 +0 1 +.names 11234 11235 +1 1 +.names 31926 30857 11236 +11 1 +.names 11236 11237 +1 1 +.names 11241 11238 +0 1 +.names 11238 11239 +1 1 +.names 31405 31406 11240 +11 1 +.names 11240 11241 +1 1 +.names 31498 31501 11242 +11 1 +.names 11242 11243 +1 1 +.names 11247 11244 +0 1 +.names 11244 11245 +1 1 +.names 31924 31925 11246 +1- 1 +-1 1 +.names 11246 11247 +1 1 +.names 11251 11248 +0 1 +.names 11248 11249 +1 1 +.names 30851 30852 11250 +11 1 +.names 11250 11251 +1 1 +.names 11222 11252 +0 1 +.names 11252 11253 +1 1 +.names 11257 11254 +0 1 +.names 11254 11255 +1 1 +.names 31620 31621 11256 +11 1 +.names 11256 11257 +1 1 +.names 11261 11258 +0 1 +.names 11258 11259 +1 1 +.names 31163 31164 11260 +11 1 +.names 11260 11261 +1 1 +.names 11265 11262 +0 1 +.names 11262 11263 +1 1 +.names 31622 31623 11264 +11 1 +.names 11264 11265 +1 1 +.names 11269 11266 +0 1 +.names 11266 11267 +1 1 +.names 31931 31932 11268 +11 1 +.names 11268 11269 +1 1 +.names 11273 11270 +0 1 +.names 11270 11271 +1 1 +.names 31165 31166 11272 +11 1 +.names 11272 11273 +1 1 +.names 11208 11274 +1 1 +.names 11278 11275 +0 1 +.names 11275 11276 +1 1 +.names 11212 11209 11277 +11 1 +.names 11277 11278 +1 1 +.names 11217 11279 +1 1 +.names 11283 11280 +0 1 +.names 11280 11281 +1 1 +.names 31502 31503 11282 +11 1 +.names 11282 11283 +1 1 +.names 11287 11284 +0 1 +.names 11284 11285 +1 1 +.names 30925 30926 11286 +1- 1 +-1 1 +.names 11286 11287 +1 1 +.names 11291 11288 +0 1 +.names 11288 11289 +1 1 +.names 31315 31316 11290 +1- 1 +-1 1 +.names 11290 11291 +1 1 +.names 11295 11292 +0 1 +.names 11292 11293 +1 1 +.names 31927 31928 11294 +11 1 +.names 11294 11295 +1 1 +.names 11299 11296 +0 1 +.names 11296 11297 +1 1 +.names 31663 31664 11298 +11 1 +.names 11298 11299 +1 1 +.names 11303 11300 +0 1 +.names 11300 11301 +1 1 +.names 31663 31664 11302 +1- 1 +-1 1 +.names 11302 11303 +1 1 +.names 11307 11304 +0 1 +.names 11304 11305 +1 1 +.names 31159 31160 11306 +11 1 +.names 11306 11307 +1 1 +.names 11311 11308 +0 1 +.names 11308 11309 +1 1 +.names 11393 11310 +0 1 +.names 11310 11311 +1 1 +.names 11315 11312 +0 1 +.names 11312 11313 +1 1 +.names 31380 31381 11314 +1- 1 +-1 1 +.names 11314 11315 +1 1 +.names 11319 11316 +0 1 +.names 11316 11317 +1 1 +.names 30851 30852 11318 +1- 1 +-1 1 +.names 11318 11319 +1 1 +.names 11323 11320 +0 1 +.names 11320 11321 +1 1 +.names 31382 31383 11322 +11 1 +.names 11322 11323 +1 1 +.names 11327 11324 +0 1 +.names 11324 11325 +1 1 +.names 31504 31505 11326 +11 1 +.names 11326 11327 +1 1 +.names 11331 11328 +0 1 +.names 11328 11329 +1 1 +.names 31161 31162 11330 +1- 1 +-1 1 +.names 11330 11331 +1 1 +.names 11335 11332 +0 1 +.names 11332 11333 +1 1 +.names 31382 31383 11334 +1- 1 +-1 1 +.names 11334 11335 +1 1 +.names 11339 11336 +0 1 +.names 11336 11337 +1 1 +.names 30927 30928 11338 +11 1 +.names 11338 11339 +1 1 +.names 11343 11340 +0 1 +.names 11340 11341 +1 1 +.names 31620 31621 11342 +1- 1 +-1 1 +.names 11342 11343 +1 1 +.names 11347 11344 +0 1 +.names 11344 11345 +1 1 +.names 31624 31625 11346 +11 1 +.names 11346 11347 +1 1 +.names 11351 11348 +0 1 +.names 11348 11349 +1 1 +.names 31319 31320 11350 +1- 1 +-1 1 +.names 11350 11351 +1 1 +.names 11355 11352 +0 1 +.names 11352 11353 +1 1 +.names 31631 31632 11354 +11 1 +.names 11354 11355 +1 1 +.names 11359 11356 +0 1 +.names 11356 11357 +1 1 +.names 31163 31164 11358 +1- 1 +-1 1 +.names 11358 11359 +1 1 +.names 11363 11360 +0 1 +.names 11360 11361 +1 1 +.names 31622 31623 11362 +1- 1 +-1 1 +.names 11362 11363 +1 1 +.names 11367 11364 +0 1 +.names 11364 11365 +1 1 +.names 31374 31375 11366 +1- 1 +-1 1 +.names 11366 11367 +1 1 +.names 11371 11368 +0 1 +.names 11368 11369 +1 1 +.names 30929 30930 11370 +1- 1 +-1 1 +.names 11370 11371 +1 1 +.names 11375 11372 +0 1 +.names 11372 11373 +1 1 +.names 31165 31166 11374 +1- 1 +-1 1 +.names 11374 11375 +1 1 +.names 11379 11376 +0 1 +.names 11376 11377 +1 1 +.names 32110 32111 11378 +11 1 +.names 11378 11379 +1 1 +.names 11383 11380 +0 1 +.names 11380 11381 +1 1 +.names 31161 31162 11382 +11 1 +.names 11382 11383 +1 1 +.names 11387 11384 +0 1 +.names 11384 11385 +1 1 +.names 31380 31381 11386 +11 1 +.names 11386 11387 +1 1 +.names 11391 11388 +0 1 +.names 11388 11389 +1 1 +.names 31741 31742 11390 +11 1 +.names 11390 11391 +1 1 +.names 11395 11392 +0 1 +.names 11392 11393 +1 1 +.names 31929 31930 11394 +11 1 +.names 11394 11395 +1 1 +.names 30019 30023 11396 +1- 1 +-1 1 +.names 11396 11397 +1 1 +.names 30435 30436 11398 +1- 1 +-1 1 +.names 11398 11399 +1 1 +.names 2413 11406 11400 +11 1 +.names 11400 11401 +1 1 +.names 11401 11402 +0 1 +.names 11426 11403 +0 1 +.names 11403 11404 +1 1 +.names 11404 11405 +0 1 +.names 7619 11406 +0 1 +.names 11406 11407 +1 1 +.names 11407 11408 +0 1 +.names 11417 11418 11409 +11 1 +.names 11409 11410 +1 1 +.names 11410 11411 +0 1 +.names 11408 11411 11412 +1- 1 +-1 1 +.names 2413 11413 +1 1 +.names 11413 11414 +0 1 +.names 11412 11414 11415 +1- 1 +-1 1 +.names 973 11416 +0 1 +.names 974 11417 +0 1 +.names 975 11418 +0 1 +.names 11418 11419 +1 1 +.names 11419 11420 +0 1 +.names 11420 11421 +1 1 +.names 11406 11422 +1 1 +.names 11422 11423 +0 1 +.names 11421 11424 +0 1 +.names 11423 11424 11425 +1- 1 +-1 1 +.names 11417 11426 +1 1 +.names 11425 11403 11427 +1- 1 +-1 1 +.names 7626 11428 +1 1 +.names 11428 11429 +0 1 +.names 977 11430 +0 1 +.names 11437 11441 11431 +1- 1 +-1 1 +.names 11431 11432 +1 1 +.names 7654 11433 +0 1 +.names 12750 12754 11434 +1- 1 +-1 1 +.names 11434 11435 +1 1 +.names 11435 11436 +0 1 +.names 11433 11436 11437 +11 1 +.names 12692 12696 11438 +1- 1 +-1 1 +.names 11438 11439 +1 1 +.names 11439 11440 +0 1 +.names 7654 11440 11441 +11 1 +.names 11447 11451 11442 +1- 1 +-1 1 +.names 11442 11443 +1 1 +.names 12758 12762 11444 +1- 1 +-1 1 +.names 11444 11445 +1 1 +.names 11445 11446 +0 1 +.names 11433 11446 11447 +11 1 +.names 12702 12706 11448 +1- 1 +-1 1 +.names 11448 11449 +1 1 +.names 11449 11450 +0 1 +.names 7654 11450 11451 +11 1 +.names 11457 11461 11452 +1- 1 +-1 1 +.names 11452 11453 +1 1 +.names 12766 12770 11454 +1- 1 +-1 1 +.names 11454 11455 +1 1 +.names 11455 11456 +0 1 +.names 11433 11456 11457 +11 1 +.names 12710 12714 11458 +1- 1 +-1 1 +.names 11458 11459 +1 1 +.names 11459 11460 +0 1 +.names 7654 11460 11461 +11 1 +.names 11467 11471 11462 +1- 1 +-1 1 +.names 11462 11463 +1 1 +.names 12774 12778 11464 +1- 1 +-1 1 +.names 11464 11465 +1 1 +.names 11465 11466 +0 1 +.names 11433 11466 11467 +11 1 +.names 12718 12722 11468 +1- 1 +-1 1 +.names 11468 11469 +1 1 +.names 11469 11470 +0 1 +.names 7654 11470 11471 +11 1 +.names 11477 11481 11472 +1- 1 +-1 1 +.names 11472 11473 +1 1 +.names 12790 12794 11474 +1- 1 +-1 1 +.names 11474 11475 +1 1 +.names 11475 11476 +0 1 +.names 11433 11476 11477 +11 1 +.names 12726 12730 11478 +1- 1 +-1 1 +.names 11478 11479 +1 1 +.names 11479 11480 +0 1 +.names 7654 11480 11481 +11 1 +.names 11487 11488 11482 +1- 1 +-1 1 +.names 11482 11483 +1 1 +.names 12811 12812 11484 +1- 1 +-1 1 +.names 11484 11485 +1 1 +.names 11485 11486 +0 1 +.names 11433 11486 11487 +11 1 +.names 7654 11446 11488 +11 1 +.names 11494 11498 11489 +1- 1 +-1 1 +.names 11489 11490 +1 1 +.names 12960 12964 11491 +1- 1 +-1 1 +.names 11491 11492 +1 1 +.names 11492 11493 +0 1 +.names 11433 11493 11494 +11 1 +.names 12782 12786 11495 +1- 1 +-1 1 +.names 11495 11496 +1 1 +.names 11496 11497 +0 1 +.names 7654 11497 11498 +11 1 +.names 11504 11508 11499 +1- 1 +-1 1 +.names 11499 11500 +1 1 +.names 12851 12852 11501 +1- 1 +-1 1 +.names 11501 11502 +1 1 +.names 11502 11503 +0 1 +.names 11433 11503 11504 +11 1 +.names 12836 12837 11505 +1- 1 +-1 1 +.names 11505 11506 +1 1 +.names 11506 11507 +0 1 +.names 7654 11507 11508 +11 1 +.names 11511 11515 11509 +1- 1 +-1 1 +.names 11509 11510 +1 1 +.names 11433 11450 11511 +11 1 +.names 13020 13024 11512 +1- 1 +-1 1 +.names 11512 11513 +1 1 +.names 11513 11514 +0 1 +.names 7654 11514 11515 +11 1 +.names 11521 11525 11516 +1- 1 +-1 1 +.names 11516 11517 +1 1 +.names 12854 12855 11518 +1- 1 +-1 1 +.names 11518 11519 +1 1 +.names 11519 11520 +0 1 +.names 11433 11520 11521 +11 1 +.names 12952 12953 11522 +1- 1 +-1 1 +.names 11522 11523 +1 1 +.names 11523 11524 +0 1 +.names 7654 11524 11525 +11 1 +.names 11531 11535 11526 +1- 1 +-1 1 +.names 11526 11527 +1 1 +.names 12856 12860 11528 +1- 1 +-1 1 +.names 11528 11529 +1 1 +.names 11529 11530 +0 1 +.names 11433 11530 11531 +11 1 +.names 13040 13041 11532 +1- 1 +-1 1 +.names 11532 11533 +1 1 +.names 11533 11534 +0 1 +.names 7654 11534 11535 +11 1 +.names 11541 11545 11536 +1- 1 +-1 1 +.names 11536 11537 +1 1 +.names 12866 12867 11538 +1- 1 +-1 1 +.names 11538 11539 +1 1 +.names 11539 11540 +0 1 +.names 11433 11540 11541 +11 1 +.names 12936 12937 11542 +1- 1 +-1 1 +.names 11542 11543 +1 1 +.names 11543 11544 +0 1 +.names 7654 11544 11545 +11 1 +.names 11551 11555 11546 +1- 1 +-1 1 +.names 11546 11547 +1 1 +.names 12868 12869 11548 +1- 1 +-1 1 +.names 11548 11549 +1 1 +.names 11549 11550 +0 1 +.names 11433 11550 11551 +11 1 +.names 12978 12979 11552 +1- 1 +-1 1 +.names 11552 11553 +1 1 +.names 11553 11554 +0 1 +.names 7654 11554 11555 +11 1 +.names 11561 11565 11556 +1- 1 +-1 1 +.names 11556 11557 +1 1 +.names 13000 13001 11558 +1- 1 +-1 1 +.names 11558 11559 +1 1 +.names 11559 11560 +0 1 +.names 11433 11560 11561 +11 1 +.names 12974 12975 11562 +1- 1 +-1 1 +.names 11562 11563 +1 1 +.names 11563 11564 +0 1 +.names 7654 11564 11565 +11 1 +.names 11568 11572 11566 +1- 1 +-1 1 +.names 11566 11567 +1 1 +.names 11433 11460 11568 +11 1 +.names 13025 13029 11569 +1- 1 +-1 1 +.names 11569 11570 +1 1 +.names 11570 11571 +0 1 +.names 7654 11571 11572 +11 1 +.names 11578 11582 11573 +1- 1 +-1 1 +.names 11573 11574 +1 1 +.names 12875 12876 11575 +1- 1 +-1 1 +.names 11575 11576 +1 1 +.names 11576 11577 +0 1 +.names 11433 11577 11578 +11 1 +.names 12924 12925 11579 +1- 1 +-1 1 +.names 11579 11580 +1 1 +.names 11580 11581 +0 1 +.names 7654 11581 11582 +11 1 +.names 11588 11589 11583 +1- 1 +-1 1 +.names 11583 11584 +1 1 +.names 12887 12891 11585 +1- 1 +-1 1 +.names 11585 11586 +1 1 +.names 11586 11587 +0 1 +.names 11433 11587 11588 +11 1 +.names 7654 11550 11589 +11 1 +.names 11593 11597 11590 +1- 1 +-1 1 +.names 11590 11591 +1 1 +.names 8113 11592 +0 1 +.names 11433 11592 11593 +11 1 +.names 12944 12945 11594 +1- 1 +-1 1 +.names 11594 11595 +1 1 +.names 11595 11596 +0 1 +.names 7654 11596 11597 +11 1 +.names 11600 11604 11598 +1- 1 +-1 1 +.names 11598 11599 +1 1 +.names 11433 11470 11600 +11 1 +.names 12877 12881 11601 +1- 1 +-1 1 +.names 11601 11602 +1 1 +.names 11602 11603 +0 1 +.names 7654 11603 11604 +11 1 +.names 11608 11609 11605 +1- 1 +-1 1 +.names 11605 11606 +1 1 +.names 8116 11607 +0 1 +.names 11433 11607 11608 +11 1 +.names 7654 11587 11609 +11 1 +.names 11613 11617 11610 +1- 1 +-1 1 +.names 11610 11611 +1 1 +.names 8117 11612 +0 1 +.names 11433 11612 11613 +11 1 +.names 12929 12930 11614 +1- 1 +-1 1 +.names 11614 11615 +1 1 +.names 11615 11616 +0 1 +.names 7654 11616 11617 +11 1 +.names 11620 11624 11618 +1- 1 +-1 1 +.names 11618 11619 +1 1 +.names 11433 11480 11620 +11 1 +.names 12892 12896 11621 +1- 1 +-1 1 +.names 11621 11622 +1 1 +.names 11622 11623 +0 1 +.names 7654 11623 11624 +11 1 +.names 11630 11634 11625 +1- 1 +-1 1 +.names 11625 11626 +1 1 +.names 12734 12738 11627 +1- 1 +-1 1 +.names 11627 11628 +1 1 +.names 11628 11629 +0 1 +.names 11433 11629 11630 +11 1 +.names 12900 12904 11631 +1- 1 +-1 1 +.names 11631 11632 +1 1 +.names 11632 11633 +0 1 +.names 7654 11633 11634 +11 1 +.names 11640 11644 11635 +1- 1 +-1 1 +.names 11635 11636 +1 1 +.names 12742 12746 11637 +1- 1 +-1 1 +.names 11637 11638 +1 1 +.names 11638 11639 +0 1 +.names 11433 11639 11640 +11 1 +.names 12905 12909 11641 +1- 1 +-1 1 +.names 11641 11642 +1 1 +.names 11642 11643 +0 1 +.names 7654 11643 11644 +11 1 +.names 11649 11653 11645 +1- 1 +-1 1 +.names 11645 11646 +1 1 +.names 11433 11647 +1 1 +.names 11647 11648 +0 1 +.names 11648 11520 11649 +11 1 +.names 12934 12935 11650 +1- 1 +-1 1 +.names 11650 11651 +1 1 +.names 11651 11652 +0 1 +.names 11647 11652 11653 +11 1 +.names 11658 11662 11654 +1- 1 +-1 1 +.names 11654 11655 +1 1 +.names 11433 11656 +1 1 +.names 11656 11657 +0 1 +.names 11657 11560 11658 +11 1 +.names 12915 12916 11659 +1- 1 +-1 1 +.names 11659 11660 +1 1 +.names 11660 11661 +0 1 +.names 11656 11661 11662 +11 1 +.names 11670 11671 11663 +1- 1 +-1 1 +.names 11663 11664 +1 1 +.names 11433 11665 +1 1 +.names 11665 11666 +0 1 +.names 12846 12847 11667 +1- 1 +-1 1 +.names 11667 11668 +1 1 +.names 11668 11669 +0 1 +.names 11666 11669 11670 +11 1 +.names 11665 11554 11671 +11 1 +.names 11679 11680 11672 +1- 1 +-1 1 +.names 11672 11673 +1 1 +.names 11433 11674 +1 1 +.names 11674 11675 +0 1 +.names 12841 12842 11676 +1- 1 +-1 1 +.names 11676 11677 +1 1 +.names 11677 11678 +0 1 +.names 11675 11678 11679 +11 1 +.names 11674 11544 11680 +11 1 +.names 11686 11687 11681 +1- 1 +-1 1 +.names 11681 11682 +1 1 +.names 12967 12971 11683 +1- 1 +-1 1 +.names 11683 11684 +1 1 +.names 11684 11685 +0 1 +.names 11657 11685 11686 +11 1 +.names 11656 11564 11687 +11 1 +.names 11612 11688 +1 1 +.names 11691 11695 11689 +1- 1 +-1 1 +.names 11689 11690 +1 1 +.names 11657 11661 11691 +11 1 +.names 11688 11692 +0 1 +.names 11692 11693 +1 1 +.names 11693 11694 +0 1 +.names 11656 11694 11695 +11 1 +.names 11607 11696 +1 1 +.names 11696 11697 +0 1 +.names 11697 11698 +1 1 +.names 11701 11703 11699 +1- 1 +-1 1 +.names 11699 11700 +1 1 +.names 11666 11577 11701 +11 1 +.names 11698 11702 +0 1 +.names 11665 11702 11703 +11 1 +.names 11709 11713 11704 +1- 1 +-1 1 +.names 11704 11705 +1 1 +.names 11818 11706 +0 1 +.names 11706 11707 +1 1 +.names 11707 11708 +0 1 +.names 11708 11534 11709 +11 1 +.names 13017 13018 11710 +1- 1 +-1 1 +.names 11710 11711 +1 1 +.names 11711 11712 +0 1 +.names 11707 11712 11713 +11 1 +.names 11716 11720 11714 +1- 1 +-1 1 +.names 11714 11715 +1 1 +.names 11666 11456 11716 +11 1 +.names 12816 12817 11717 +1- 1 +-1 1 +.names 11717 11718 +1 1 +.names 11718 11719 +0 1 +.names 11665 11719 11720 +11 1 +.names 11725 11729 11721 +1- 1 +-1 1 +.names 11721 11722 +1 1 +.names 11433 11723 +1 1 +.names 11723 11724 +0 1 +.names 11724 11493 11725 +11 1 +.names 12987 12988 11726 +1- 1 +-1 1 +.names 11726 11727 +1 1 +.names 11727 11728 +0 1 +.names 11723 11728 11729 +11 1 +.names 11735 11736 11730 +1- 1 +-1 1 +.names 11730 11731 +1 1 +.names 12798 12802 11732 +1- 1 +-1 1 +.names 11732 11733 +1 1 +.names 11733 11734 +0 1 +.names 11724 11734 11735 +11 1 +.names 11723 11712 11736 +11 1 +.names 11433 11737 +1 1 +.names 11741 11742 11738 +1- 1 +-1 1 +.names 11738 11739 +1 1 +.names 11737 11740 +0 1 +.names 11740 11652 11741 +11 1 +.names 11737 11592 11742 +11 1 +.names 11745 11749 11743 +1- 1 +-1 1 +.names 11743 11744 +1 1 +.names 11433 11633 11745 +11 1 +.names 13030 13034 11746 +1- 1 +-1 1 +.names 11746 11747 +1 1 +.names 11747 11748 +0 1 +.names 7654 11748 11749 +11 1 +.names 11757 11758 11750 +1- 1 +-1 1 +.names 11750 11751 +1 1 +.names 11433 11752 +1 1 +.names 11752 11753 +0 1 +.names 12922 12923 11754 +1- 1 +-1 1 +.names 11754 11755 +1 1 +.names 11755 11756 +0 1 +.names 11753 11756 11757 +11 1 +.names 11752 11607 11758 +11 1 +.names 11761 11762 11759 +1- 1 +-1 1 +.names 11759 11760 +1 1 +.names 11666 11486 11761 +11 1 +.names 11665 11507 11762 +11 1 +.names 11724 11763 +1 1 +.names 11767 11768 11764 +1- 1 +-1 1 +.names 11764 11765 +1 1 +.names 11763 11766 +0 1 +.names 11766 11678 11767 +11 1 +.names 11763 11719 11768 +11 1 +.names 11771 11772 11769 +1- 1 +-1 1 +.names 11769 11770 +1 1 +.names 11657 11503 11771 +11 1 +.names 11656 11581 11772 +11 1 +.names 11775 11779 11773 +1- 1 +-1 1 +.names 11773 11774 +1 1 +.names 11648 11476 11775 +11 1 +.names 12826 12827 11776 +1- 1 +-1 1 +.names 11776 11777 +1 1 +.names 11777 11778 +0 1 +.names 11647 11778 11779 +11 1 +.names 11648 11780 +1 1 +.names 11784 11785 11781 +1- 1 +-1 1 +.names 11781 11782 +1 1 +.names 11780 11783 +0 1 +.names 11783 11734 11784 +11 1 +.names 11780 11639 11785 +11 1 +.names 11793 11797 11786 +1- 1 +-1 1 +.names 11786 11787 +1 1 +.names 11666 11788 +1 1 +.names 11788 11789 +0 1 +.names 12996 12997 11790 +1- 1 +-1 1 +.names 11790 11791 +1 1 +.names 11791 11792 +0 1 +.names 11789 11792 11793 +11 1 +.names 12976 12977 11794 +1- 1 +-1 1 +.names 11794 11795 +1 1 +.names 11795 11796 +0 1 +.names 11788 11796 11797 +11 1 +.names 11740 11798 +1 1 +.names 11798 11799 +0 1 +.names 11799 11800 +1 1 +.names 11804 11805 11801 +1- 1 +-1 1 +.names 11801 11802 +1 1 +.names 11800 11803 +0 1 +.names 11803 11530 11804 +11 1 +.names 11800 11756 11805 +11 1 +.names 11724 11806 +1 1 +.names 11806 11807 +0 1 +.names 11807 11808 +1 1 +.names 11815 11816 11809 +1- 1 +-1 1 +.names 11809 11810 +1 1 +.names 11808 11811 +0 1 +.names 12831 12832 11812 +1- 1 +-1 1 +.names 11812 11813 +1 1 +.names 11813 11814 +0 1 +.names 11811 11814 11815 +11 1 +.names 11808 11524 11816 +11 1 +.names 11706 11817 +1 1 +.names 11433 11818 +1 1 +.names 11822 11823 11819 +1- 1 +-1 1 +.names 11819 11820 +1 1 +.names 11817 11821 +0 1 +.names 11821 11685 11822 +11 1 +.names 11817 11778 11823 +11 1 +.names 11829 11830 11824 +1- 1 +-1 1 +.names 11824 11825 +1 1 +.names 12882 12886 11826 +1- 1 +-1 1 +.names 11826 11827 +1 1 +.names 11827 11828 +0 1 +.names 11648 11828 11829 +11 1 +.names 11647 11612 11830 +11 1 +.names 11833 11837 11831 +1- 1 +-1 1 +.names 11831 11832 +1 1 +.names 11708 11669 11833 +11 1 +.names 12821 12822 11834 +1- 1 +-1 1 +.names 11834 11835 +1 1 +.names 11835 11836 +0 1 +.names 11707 11836 11837 +11 1 +.names 11840 11841 11838 +1- 1 +-1 1 +.names 11838 11839 +1 1 +.names 11753 11466 11840 +11 1 +.names 11752 11836 11841 +11 1 +.names 11844 11848 11842 +1- 1 +-1 1 +.names 11842 11843 +1 1 +.names 11708 11796 11844 +11 1 +.names 12806 12807 11845 +1- 1 +-1 1 +.names 11845 11846 +1 1 +.names 11846 11847 +0 1 +.names 11707 11847 11848 +11 1 +.names 11433 11849 +1 1 +.names 11853 11857 11850 +1- 1 +-1 1 +.names 11850 11851 +1 1 +.names 11849 11852 +0 1 +.names 11852 11629 11853 +11 1 +.names 13035 13036 11854 +1- 1 +-1 1 +.names 11854 11855 +1 1 +.names 11855 11856 +0 1 +.names 11849 11856 11857 +11 1 +.names 11433 11858 +1 1 +.names 11862 11866 11859 +1- 1 +-1 1 +.names 11859 11860 +1 1 +.names 11858 11861 +0 1 +.names 11861 11792 11862 +11 1 +.names 12861 12865 11863 +1- 1 +-1 1 +.names 11863 11864 +1 1 +.names 11864 11865 +0 1 +.names 11858 11865 11866 +11 1 +.names 11869 11873 11867 +1- 1 +-1 1 +.names 11867 11868 +1 1 +.names 11433 11440 11869 +11 1 +.names 12980 12984 11870 +1- 1 +-1 1 +.names 11870 11871 +1 1 +.names 11871 11872 +0 1 +.names 7654 11872 11873 +11 1 +.names 11876 11877 11874 +1- 1 +-1 1 +.names 11874 11875 +1 1 +.names 11657 11436 11876 +11 1 +.names 11656 11847 11877 +11 1 +.names 11657 11878 +1 1 +.names 11878 11879 +0 1 +.names 11879 11880 +1 1 +.names 11884 11885 11881 +1- 1 +-1 1 +.names 11881 11882 +1 1 +.names 11880 11883 +0 1 +.names 11883 11540 11884 +11 1 +.names 11880 11828 11885 +11 1 +.names 11891 11895 11886 +1- 1 +-1 1 +.names 11886 11887 +1 1 +.names 12989 12993 11888 +1- 1 +-1 1 +.names 11888 11889 +1 1 +.names 11889 11890 +0 1 +.names 11724 11890 11891 +11 1 +.names 13012 13013 11892 +1- 1 +-1 1 +.names 11892 11893 +1 1 +.names 11893 11894 +0 1 +.names 11723 11894 11895 +11 1 +.names 11433 11896 +1 1 +.names 11900 11901 11897 +1- 1 +-1 1 +.names 11897 11898 +1 1 +.names 11896 11899 +0 1 +.names 11899 11894 11900 +11 1 +.names 11896 11497 11901 +11 1 +.names 11753 11902 +1 1 +.names 11906 11907 11903 +1- 1 +-1 1 +.names 11903 11904 +1 1 +.names 11902 11905 +0 1 +.names 11905 11596 11906 +11 1 +.names 11902 11865 11907 +11 1 +.names 11910 11911 11908 +1- 1 +-1 1 +.names 11908 11909 +1 1 +.names 11433 11814 11910 +11 1 +.names 7654 11856 11911 +11 1 +.names 11914 11918 11912 +1- 1 +-1 1 +.names 11912 11913 +1 1 +.names 11433 11643 11914 +11 1 +.names 13002 13006 11915 +1- 1 +-1 1 +.names 11915 11916 +1 1 +.names 11916 11917 +0 1 +.names 7654 11917 11918 +11 1 +.names 11675 11919 +1 1 +.names 11919 11920 +0 1 +.names 11920 11921 +1 1 +.names 11928 11929 11922 +1- 1 +-1 1 +.names 11922 11923 +1 1 +.names 11921 11924 +0 1 +.names 12870 12874 11925 +1- 1 +-1 1 +.names 11925 11926 +1 1 +.names 11926 11927 +0 1 +.names 11924 11927 11928 +11 1 +.names 11921 11616 11929 +11 1 +.names 11932 11936 11930 +1- 1 +-1 1 +.names 11930 11931 +1 1 +.names 11708 11927 11932 +11 1 +.names 13042 13043 11933 +1- 1 +-1 1 +.names 11933 11934 +1 1 +.names 11934 11935 +0 1 +.names 11707 11935 11936 +11 1 +.names 11433 11937 +1 1 +.names 11941 11942 11938 +1- 1 +-1 1 +.names 11938 11939 +1 1 +.names 11937 11940 +0 1 +.names 11940 11728 11941 +11 1 +.names 11937 11935 11942 +11 1 +.names 11947 11949 11943 +1- 1 +-1 1 +.names 11943 11944 +1 1 +.names 7649 11945 +0 1 +.names 11567 11946 +0 1 +.names 11945 11946 11947 +11 1 +.names 11744 11948 +0 1 +.names 7649 11948 11949 +11 1 +.names 11953 11955 11950 +1- 1 +-1 1 +.names 11950 11951 +1 1 +.names 11898 11952 +0 1 +.names 11945 11952 11953 +11 1 +.names 11432 11954 +0 1 +.names 7649 11954 11955 +11 1 +.names 11959 11961 11956 +1- 1 +-1 1 +.names 11956 11957 +1 1 +.names 11473 11958 +0 1 +.names 11945 11958 11959 +11 1 +.names 11443 11960 +0 1 +.names 7649 11960 11961 +11 1 +.names 11965 11967 11962 +1- 1 +-1 1 +.names 11962 11963 +1 1 +.names 11851 11964 +0 1 +.names 11945 11964 11965 +11 1 +.names 11453 11966 +0 1 +.names 7649 11966 11967 +11 1 +.names 11971 11972 11968 +1- 1 +-1 1 +.names 11968 11969 +1 1 +.names 11875 11970 +0 1 +.names 11945 11970 11971 +11 1 +.names 7649 11952 11972 +11 1 +.names 11976 11977 11973 +1- 1 +-1 1 +.names 11973 11974 +1 1 +.names 11715 11975 +0 1 +.names 11945 11975 11976 +11 1 +.names 7649 11964 11977 +11 1 +.names 11981 11983 11978 +1- 1 +-1 1 +.names 11978 11979 +1 1 +.names 11839 11980 +0 1 +.names 11945 11980 11981 +11 1 +.names 11782 11982 +0 1 +.names 7649 11982 11983 +11 1 +.names 11987 11988 11984 +1- 1 +-1 1 +.names 11984 11985 +1 1 +.names 11490 11986 +0 1 +.names 11945 11986 11987 +11 1 +.names 7649 11970 11988 +11 1 +.names 11992 11993 11989 +1- 1 +-1 1 +.names 11989 11990 +1 1 +.names 11909 11991 +0 1 +.names 11945 11991 11992 +11 1 +.names 7649 11975 11993 +11 1 +.names 11997 11998 11994 +1- 1 +-1 1 +.names 11994 11995 +1 1 +.names 11731 11996 +0 1 +.names 11945 11996 11997 +11 1 +.names 7649 11980 11998 +11 1 +.names 12002 12004 11999 +1- 1 +-1 1 +.names 11999 12000 +1 1 +.names 11760 12001 +0 1 +.names 11945 12001 12002 +11 1 +.names 11774 12003 +0 1 +.names 7649 12003 12004 +11 1 +.names 12008 12010 12005 +1- 1 +-1 1 +.names 12005 12006 +1 1 +.names 11722 12007 +0 1 +.names 11945 12007 12008 +11 1 +.names 11843 12009 +0 1 +.names 7649 12009 12010 +11 1 +.names 12014 12016 12011 +1- 1 +-1 1 +.names 12011 12012 +1 1 +.names 11810 12013 +0 1 +.names 11945 12013 12014 +11 1 +.names 11765 12015 +0 1 +.names 7649 12015 12016 +11 1 +.names 12020 12022 12017 +1- 1 +-1 1 +.names 12017 12018 +1 1 +.names 11887 12019 +0 1 +.names 11945 12019 12020 +11 1 +.names 11868 12021 +0 1 +.names 7649 12021 12022 +11 1 +.names 12026 12028 12023 +1- 1 +-1 1 +.names 12023 12024 +1 1 +.names 11517 12025 +0 1 +.names 11945 12025 12026 +11 1 +.names 11673 12027 +0 1 +.names 7649 12027 12028 +11 1 +.names 12032 12034 12029 +1- 1 +-1 1 +.names 12029 12030 +1 1 +.names 11619 12031 +0 1 +.names 11945 12031 12032 +11 1 +.names 11510 12033 +0 1 +.names 7649 12033 12034 +11 1 +.names 12038 12039 12035 +1- 1 +-1 1 +.names 12035 12036 +1 1 +.names 11537 12037 +0 1 +.names 11945 12037 12038 +11 1 +.names 7649 12025 12039 +11 1 +.names 12043 12045 12040 +1- 1 +-1 1 +.names 12040 12041 +1 1 +.names 11547 12042 +0 1 +.names 11945 12042 12043 +11 1 +.names 11527 12044 +0 1 +.names 7649 12044 12045 +11 1 +.names 12049 12051 12046 +1- 1 +-1 1 +.names 12046 12047 +1 1 +.names 11904 12048 +0 1 +.names 11945 12048 12049 +11 1 +.names 11931 12050 +0 1 +.names 7649 12050 12051 +11 1 +.names 12055 12056 12052 +1- 1 +-1 1 +.names 12052 12053 +1 1 +.names 11626 12054 +0 1 +.names 11945 12054 12055 +11 1 +.names 7649 11946 12056 +11 1 +.names 12060 12062 12057 +1- 1 +-1 1 +.names 12057 12058 +1 1 +.names 11591 12059 +0 1 +.names 11945 12059 12060 +11 1 +.names 11923 12061 +0 1 +.names 7649 12061 12062 +11 1 +.names 12066 12067 12063 +1- 1 +-1 1 +.names 12063 12064 +1 1 +.names 11611 12065 +0 1 +.names 11945 12065 12066 +11 1 +.names 7649 12059 12067 +11 1 +.names 12071 12073 12068 +1- 1 +-1 1 +.names 12068 12069 +1 1 +.names 11690 12070 +0 1 +.names 11945 12070 12071 +11 1 +.names 11700 12072 +0 1 +.names 7649 12072 12073 +11 1 +.names 12077 12079 12074 +1- 1 +-1 1 +.names 12074 12075 +1 1 +.names 11636 12076 +0 1 +.names 11945 12076 12077 +11 1 +.names 11599 12078 +0 1 +.names 7649 12078 12079 +11 1 +.names 12083 12085 12080 +1- 1 +-1 1 +.names 12080 12081 +1 1 +.names 8112 12082 +0 1 +.names 11945 12082 12083 +11 1 +.names 11825 12084 +0 1 +.names 7649 12084 12085 +11 1 +.names 12088 12090 12086 +1- 1 +-1 1 +.names 12086 12087 +1 1 +.names 11945 12082 12088 +11 1 +.names 11606 12089 +0 1 +.names 7649 12089 12090 +11 1 +.names 12093 12094 12091 +1- 1 +-1 1 +.names 12091 12092 +1 1 +.names 11945 12082 12093 +11 1 +.names 7649 12065 12094 +11 1 +.names 12098 12099 12095 +1- 1 +-1 1 +.names 12095 12096 +1 1 +.names 8120 12097 +0 1 +.names 11945 12097 12098 +11 1 +.names 7649 12070 12099 +11 1 +.names 12102 12103 12100 +1- 1 +-1 1 +.names 12100 12101 +1 1 +.names 11945 11954 12102 +11 1 +.names 7649 12019 12103 +11 1 +.names 12106 12107 12104 +1- 1 +-1 1 +.names 12104 12105 +1 1 +.names 11945 11960 12106 +11 1 +.names 7649 12031 12107 +11 1 +.names 12110 12111 12108 +1- 1 +-1 1 +.names 12108 12109 +1 1 +.names 11945 11966 12110 +11 1 +.names 7649 12054 12111 +11 1 +.names 12115 12116 12112 +1- 1 +-1 1 +.names 12112 12113 +1 1 +.names 11463 12114 +0 1 +.names 11945 12114 12115 +11 1 +.names 7649 12076 12116 +11 1 +.names 12122 12123 12117 +1- 1 +-1 1 +.names 12117 12118 +1 1 +.names 11945 12119 +1 1 +.names 12119 12120 +0 1 +.names 11739 12121 +0 1 +.names 12120 12121 12122 +11 1 +.names 12119 12084 12123 +11 1 +.names 12129 12130 12124 +1- 1 +-1 1 +.names 12124 12125 +1 1 +.names 11945 12126 +1 1 +.names 12126 12127 +0 1 +.names 11751 12128 +0 1 +.names 12127 12128 12129 +11 1 +.names 12126 12089 12130 +11 1 +.names 12136 12137 12131 +1- 1 +-1 1 +.names 12131 12132 +1 1 +.names 11945 12133 +1 1 +.names 12133 12134 +0 1 +.names 11882 12135 +0 1 +.names 12134 12135 12136 +11 1 +.names 12133 12121 12137 +11 1 +.names 12143 12144 12138 +1- 1 +-1 1 +.names 12138 12139 +1 1 +.names 11945 12140 +1 1 +.names 12140 12141 +0 1 +.names 11584 12142 +0 1 +.names 12141 12142 12143 +11 1 +.names 12140 12128 12144 +11 1 +.names 12150 12151 12145 +1- 1 +-1 1 +.names 12145 12146 +1 1 +.names 11945 12147 +1 1 +.names 12147 12148 +0 1 +.names 11646 12149 +0 1 +.names 12148 12149 12150 +11 1 +.names 12147 12135 12151 +11 1 +.names 12157 12158 12152 +1- 1 +-1 1 +.names 12152 12153 +1 1 +.names 11945 12154 +1 1 +.names 12154 12155 +0 1 +.names 11664 12156 +0 1 +.names 12155 12156 12157 +11 1 +.names 12154 12044 12158 +11 1 +.names 12162 12163 12159 +1- 1 +-1 1 +.names 12159 12160 +1 1 +.names 11802 12161 +0 1 +.names 12155 12161 12162 +11 1 +.names 12154 12142 12163 +11 1 +.names 12166 12167 12164 +1- 1 +-1 1 +.names 12164 12165 +1 1 +.names 12155 12037 12166 +11 1 +.names 12154 12149 12167 +11 1 +.names 12171 12172 12168 +1- 1 +-1 1 +.names 12168 12169 +1 1 +.names 11860 12170 +0 1 +.names 12134 12170 12171 +11 1 +.names 12133 12050 12172 +11 1 +.names 12175 12176 12173 +1- 1 +-1 1 +.names 12173 12174 +1 1 +.names 12120 12042 12175 +11 1 +.names 12119 12161 12176 +11 1 +.names 12182 12184 12177 +1- 1 +-1 1 +.names 12177 12178 +1 1 +.names 12277 12179 +0 1 +.names 12179 12180 +1 1 +.names 12180 12181 +0 1 +.names 12181 12072 12182 +11 1 +.names 11655 12183 +0 1 +.names 12180 12183 12184 +11 1 +.names 12189 12190 12185 +1- 1 +-1 1 +.names 12185 12186 +1 1 +.names 12179 12187 +1 1 +.names 12187 12188 +0 1 +.names 12188 12027 12189 +11 1 +.names 12187 12013 12190 +11 1 +.names 12196 12198 12191 +1- 1 +-1 1 +.names 12191 12192 +1 1 +.names 12201 12193 +0 1 +.names 12193 12194 +1 1 +.names 12194 12195 +0 1 +.names 12195 12156 12196 +11 1 +.names 11705 12197 +0 1 +.names 12194 12197 12198 +11 1 +.names 12203 12205 12199 +1- 1 +-1 1 +.names 12199 12200 +1 1 +.names 11945 12201 +1 1 +.names 11500 12202 +0 1 +.names 12193 12202 12203 +11 1 +.names 11682 12204 +0 1 +.names 12201 12204 12205 +11 1 +.names 12209 12211 12206 +1- 1 +-1 1 +.names 12206 12207 +1 1 +.names 11770 12208 +0 1 +.names 12141 12208 12209 +11 1 +.names 11557 12210 +0 1 +.names 12140 12210 12211 +11 1 +.names 12216 12218 12212 +1- 1 +-1 1 +.names 12212 12213 +1 1 +.names 12127 12214 +1 1 +.names 12214 12215 +0 1 +.names 12215 12202 12216 +11 1 +.names 11820 12217 +0 1 +.names 12214 12217 12218 +11 1 +.names 12222 12223 12219 +1- 1 +-1 1 +.names 12219 12220 +1 1 +.names 11574 12221 +0 1 +.names 12155 12221 12222 +11 1 +.names 12154 12183 12223 +11 1 +.names 12226 12227 12224 +1- 1 +-1 1 +.names 12224 12225 +1 1 +.names 12155 12001 12226 +11 1 +.names 12154 12217 12227 +11 1 +.names 12148 12228 +1 1 +.names 12232 12233 12229 +1- 1 +-1 1 +.names 12229 12230 +1 1 +.names 12228 12231 +0 1 +.names 12231 12221 12232 +11 1 +.names 12228 12210 12233 +11 1 +.names 12236 12238 12234 +1- 1 +-1 1 +.names 12234 12235 +1 1 +.names 12120 12007 12236 +11 1 +.names 11787 12237 +0 1 +.names 12119 12237 12238 +11 1 +.names 12241 12242 12239 +1- 1 +-1 1 +.names 12239 12240 +1 1 +.names 12120 12048 12241 +11 1 +.names 12119 12061 12242 +11 1 +.names 12245 12247 12243 +1- 1 +-1 1 +.names 12243 12244 +1 1 +.names 12120 11958 12245 +11 1 +.names 11483 12246 +0 1 +.names 12119 12246 12247 +11 1 +.names 12250 12252 12248 +1- 1 +-1 1 +.names 12248 12249 +1 1 +.names 11945 12078 12250 +11 1 +.names 11913 12251 +0 1 +.names 7649 12251 12252 +11 1 +.names 12257 12259 12253 +1- 1 +-1 1 +.names 12253 12254 +1 1 +.names 12179 12255 +1 1 +.names 12255 12256 +0 1 +.names 12256 12197 12257 +11 1 +.names 11832 12258 +0 1 +.names 12255 12258 12259 +11 1 +.names 12264 12265 12260 +1- 1 +-1 1 +.names 12260 12261 +1 1 +.names 12193 12262 +1 1 +.names 12262 12263 +0 1 +.names 12263 12208 12264 +11 1 +.names 12262 12204 12265 +11 1 +.names 12268 12269 12266 +1- 1 +-1 1 +.names 12266 12267 +1 1 +.names 12215 11982 12268 +11 1 +.names 12214 12114 12269 +11 1 +.names 11945 12270 +1 1 +.names 12274 12275 12271 +1- 1 +-1 1 +.names 12271 12272 +1 1 +.names 12270 12273 +0 1 +.names 12273 12246 12274 +11 1 +.names 12270 12003 12275 +11 1 +.names 12179 12276 +1 1 +.names 11945 12277 +1 1 +.names 12281 12283 12278 +1- 1 +-1 1 +.names 12278 12279 +1 1 +.names 12276 12280 +0 1 +.names 12280 12170 12281 +11 1 +.names 11939 12282 +0 1 +.names 12276 12282 12283 +11 1 +.names 12193 12284 +1 1 +.names 12288 12289 12285 +1- 1 +-1 1 +.names 12285 12286 +1 1 +.names 12284 12287 +0 1 +.names 12287 12258 12288 +11 1 +.names 12284 11996 12289 +11 1 +.names 12294 12295 12290 +1- 1 +-1 1 +.names 12290 12291 +1 1 +.names 11945 12292 +1 1 +.names 12292 12293 +0 1 +.names 12293 12237 12294 +11 1 +.names 12292 12282 12295 +11 1 +.names 12298 12299 12296 +1- 1 +-1 1 +.names 12296 12297 +1 1 +.names 12179 11991 12298 +11 1 +.names 12277 12015 12299 +11 1 +.names 12193 12300 +1 1 +.names 12300 12301 +0 1 +.names 12301 12302 +1 1 +.names 12306 12307 12303 +1- 1 +-1 1 +.names 12303 12304 +1 1 +.names 12302 12305 +0 1 +.names 12305 11986 12306 +11 1 +.names 12302 12009 12307 +11 1 +.names 12312 12314 12308 +1- 1 +-1 1 +.names 12308 12309 +1 1 +.names 7644 12310 +0 1 +.names 12018 12311 +0 1 +.names 12310 12311 12312 +11 1 +.names 11944 12313 +0 1 +.names 7644 12313 12314 +11 1 +.names 12318 12320 12315 +1- 1 +-1 1 +.names 12315 12316 +1 1 +.names 11963 12317 +0 1 +.names 12310 12317 12318 +11 1 +.names 11951 12319 +0 1 +.names 7644 12319 12320 +11 1 +.names 12324 12326 12321 +1- 1 +-1 1 +.names 12321 12322 +1 1 +.names 12267 12323 +0 1 +.names 12310 12323 12324 +11 1 +.names 11957 12325 +0 1 +.names 7644 12325 12326 +11 1 +.names 12330 12331 12327 +1- 1 +-1 1 +.names 12327 12328 +1 1 +.names 12244 12329 +0 1 +.names 12310 12329 12330 +11 1 +.names 7644 12323 12331 +11 1 +.names 12335 12336 12332 +1- 1 +-1 1 +.names 12332 12333 +1 1 +.names 11979 12334 +0 1 +.names 12310 12334 12335 +11 1 +.names 7644 12329 12336 +11 1 +.names 12340 12342 12337 +1- 1 +-1 1 +.names 12337 12338 +1 1 +.names 11985 12339 +0 1 +.names 12310 12339 12340 +11 1 +.names 11974 12341 +0 1 +.names 7644 12341 12342 +11 1 +.names 12346 12347 12343 +1- 1 +-1 1 +.names 12343 12344 +1 1 +.names 12272 12345 +0 1 +.names 12310 12345 12346 +11 1 +.names 7644 12334 12347 +11 1 +.names 12351 12352 12348 +1- 1 +-1 1 +.names 12348 12349 +1 1 +.names 11990 12350 +0 1 +.names 12310 12350 12351 +11 1 +.names 7644 12339 12352 +11 1 +.names 12356 12358 12353 +1- 1 +-1 1 +.names 12353 12354 +1 1 +.names 12030 12355 +0 1 +.names 12310 12355 12356 +11 1 +.names 12249 12357 +0 1 +.names 7644 12357 12358 +11 1 +.names 12362 12364 12359 +1- 1 +-1 1 +.names 12359 12360 +1 1 +.names 12000 12361 +0 1 +.names 12310 12361 12362 +11 1 +.names 11995 12363 +0 1 +.names 7644 12363 12364 +11 1 +.names 12368 12370 12365 +1- 1 +-1 1 +.names 12365 12366 +1 1 +.names 12225 12367 +0 1 +.names 12310 12367 12368 +11 1 +.names 12286 12369 +0 1 +.names 7644 12369 12370 +11 1 +.names 12374 12376 12371 +1- 1 +-1 1 +.names 12371 12372 +1 1 +.names 12012 12373 +0 1 +.names 12310 12373 12374 +11 1 +.names 12006 12375 +0 1 +.names 7644 12375 12376 +11 1 +.names 12380 12381 12377 +1- 1 +-1 1 +.names 12377 12378 +1 1 +.names 12053 12379 +0 1 +.names 12310 12379 12380 +11 1 +.names 7644 12311 12381 +11 1 +.names 12385 12387 12382 +1- 1 +-1 1 +.names 12382 12383 +1 1 +.names 12200 12384 +0 1 +.names 12310 12384 12385 +11 1 +.names 12192 12386 +0 1 +.names 7644 12386 12387 +11 1 +.names 12391 12393 12388 +1- 1 +-1 1 +.names 12388 12389 +1 1 +.names 12024 12390 +0 1 +.names 12310 12390 12391 +11 1 +.names 12291 12392 +0 1 +.names 7644 12392 12393 +11 1 +.names 12397 12399 12394 +1- 1 +-1 1 +.names 12394 12395 +1 1 +.names 12036 12396 +0 1 +.names 12310 12396 12397 +11 1 +.names 12279 12398 +0 1 +.names 7644 12398 12399 +11 1 +.names 12403 12404 12400 +1- 1 +-1 1 +.names 12400 12401 +1 1 +.names 12075 12402 +0 1 +.names 12310 12402 12403 +11 1 +.names 7644 12355 12404 +11 1 +.names 12408 12410 12405 +1- 1 +-1 1 +.names 12405 12406 +1 1 +.names 12047 12407 +0 1 +.names 12310 12407 12408 +11 1 +.names 12165 12409 +0 1 +.names 7644 12409 12410 +11 1 +.names 12414 12416 12411 +1- 1 +-1 1 +.names 12411 12412 +1 1 +.names 12230 12413 +0 1 +.names 12310 12413 12414 +11 1 +.names 12174 12415 +0 1 +.names 7644 12415 12416 +11 1 +.names 12420 12421 12417 +1- 1 +-1 1 +.names 12417 12418 +1 1 +.names 12101 12419 +0 1 +.names 12310 12419 12420 +11 1 +.names 7644 12379 12421 +11 1 +.names 12425 12427 12422 +1- 1 +-1 1 +.names 12422 12423 +1 1 +.names 12058 12424 +0 1 +.names 12310 12424 12425 +11 1 +.names 12132 12426 +0 1 +.names 7644 12426 12427 +11 1 +.names 12431 12433 12428 +1- 1 +-1 1 +.names 12428 12429 +1 1 +.names 12069 12430 +0 1 +.names 12310 12430 12431 +11 1 +.names 12125 12432 +0 1 +.names 7644 12432 12433 +11 1 +.names 12437 12438 12434 +1- 1 +-1 1 +.names 12434 12435 +1 1 +.names 12087 12436 +0 1 +.names 12310 12436 12437 +11 1 +.names 7644 12430 12438 +11 1 +.names 12442 12443 12439 +1- 1 +-1 1 +.names 12439 12440 +1 1 +.names 12105 12441 +0 1 +.names 12310 12441 12442 +11 1 +.names 7644 12402 12443 +11 1 +.names 12447 12448 12444 +1- 1 +-1 1 +.names 12444 12445 +1 1 +.names 12109 12446 +0 1 +.names 12310 12446 12447 +11 1 +.names 7644 12419 12448 +11 1 +.names 12451 12452 12449 +1- 1 +-1 1 +.names 12449 12450 +1 1 +.names 12310 12319 12451 +11 1 +.names 7644 12446 12452 +11 1 +.names 12455 12457 12453 +1- 1 +-1 1 +.names 12453 12454 +1 1 +.names 12310 12325 12455 +11 1 +.names 12113 12456 +0 1 +.names 7644 12456 12457 +11 1 +.names 12310 12458 +1 1 +.names 12463 12465 12459 +1- 1 +-1 1 +.names 12459 12460 +1 1 +.names 12458 12461 +0 1 +.names 12064 12462 +0 1 +.names 12461 12462 12463 +11 1 +.names 12081 12464 +0 1 +.names 12458 12464 12465 +11 1 +.names 12310 12466 +1 1 +.names 12471 12473 12467 +1- 1 +-1 1 +.names 12467 12468 +1 1 +.names 12466 12469 +0 1 +.names 12160 12470 +0 1 +.names 12469 12470 12471 +11 1 +.names 12220 12472 +0 1 +.names 12466 12472 12473 +11 1 +.names 12310 12474 +1 1 +.names 12478 12480 12475 +1- 1 +-1 1 +.names 12475 12476 +1 1 +.names 12474 12477 +0 1 +.names 12477 12436 12478 +11 1 +.names 12096 12479 +0 1 +.names 12474 12479 12480 +11 1 +.names 12310 12481 +1 1 +.names 12485 12487 12482 +1- 1 +-1 1 +.names 12482 12483 +1 1 +.names 12481 12484 +0 1 +.names 12484 12424 12485 +11 1 +.names 12118 12486 +0 1 +.names 12481 12486 12487 +11 1 +.names 12310 12488 +1 1 +.names 12492 12493 12489 +1- 1 +-1 1 +.names 12489 12490 +1 1 +.names 12488 12491 +0 1 +.names 12491 12390 12492 +11 1 +.names 12488 12398 12493 +11 1 +.names 12310 12494 +1 1 +.names 12499 12501 12495 +1- 1 +-1 1 +.names 12495 12496 +1 1 +.names 12494 12497 +0 1 +.names 12041 12498 +0 1 +.names 12497 12498 12499 +11 1 +.names 12207 12500 +0 1 +.names 12494 12500 12501 +11 1 +.names 12310 12502 +1 1 +.names 12507 12509 12503 +1- 1 +-1 1 +.names 12503 12504 +1 1 +.names 12502 12505 +0 1 +.names 12139 12506 +0 1 +.names 12505 12506 12507 +11 1 +.names 12178 12508 +0 1 +.names 12502 12508 12509 +11 1 +.names 12310 12510 +1 1 +.names 12514 12516 12511 +1- 1 +-1 1 +.names 12511 12512 +1 1 +.names 12510 12513 +0 1 +.names 12513 12396 12514 +11 1 +.names 12169 12515 +0 1 +.names 12510 12515 12516 +11 1 +.names 12310 12517 +1 1 +.names 12521 12522 12518 +1- 1 +-1 1 +.names 12518 12519 +1 1 +.names 12517 12520 +0 1 +.names 12520 12361 12521 +11 1 +.names 12517 12369 12522 +11 1 +.names 12527 12528 12523 +1- 1 +-1 1 +.names 12523 12524 +1 1 +.names 12310 12525 +1 1 +.names 12525 12526 +0 1 +.names 12526 12479 12527 +11 1 +.names 12525 11607 12528 +11 1 +.names 12310 12529 +1 1 +.names 12534 12536 12530 +1- 1 +-1 1 +.names 12530 12531 +1 1 +.names 12529 12532 +0 1 +.names 12146 12533 +0 1 +.names 12532 12533 12534 +11 1 +.names 12240 12535 +0 1 +.names 12529 12535 12536 +11 1 +.names 12539 12537 +0 1 +.names 12537 12538 +1 1 +.names 12310 12539 +1 1 +.names 12543 12544 12540 +1- 1 +-1 1 +.names 12540 12541 +1 1 +.names 12538 12542 +0 1 +.names 12542 12432 12543 +11 1 +.names 12538 12508 12544 +11 1 +.names 12548 12550 12545 +1- 1 +-1 1 +.names 12545 12546 +1 1 +.names 12153 12547 +0 1 +.names 12537 12547 12548 +11 1 +.names 12261 12549 +0 1 +.names 12539 12549 12550 +11 1 +.names 12556 12557 12551 +1- 1 +-1 1 +.names 12551 12552 +1 1 +.names 12565 12553 +0 1 +.names 12553 12554 +1 1 +.names 12554 12555 +0 1 +.names 12555 12426 12556 +11 1 +.names 12554 12535 12557 +11 1 +.names 12560 12562 12558 +1- 1 +-1 1 +.names 12558 12559 +1 1 +.names 12537 12367 12560 +11 1 +.names 12254 12561 +0 1 +.names 12539 12561 12562 +11 1 +.names 12566 12568 12563 +1- 1 +-1 1 +.names 12563 12564 +1 1 +.names 12310 12565 +1 1 +.names 12553 12373 12566 +11 1 +.names 12235 12567 +0 1 +.names 12565 12567 12568 +11 1 +.names 12572 12573 12569 +1- 1 +-1 1 +.names 12569 12570 +1 1 +.names 12213 12571 +0 1 +.names 12553 12571 12572 +11 1 +.names 12565 12386 12573 +11 1 +.names 12577 12578 12574 +1- 1 +-1 1 +.names 12574 12575 +1 1 +.names 12297 12576 +0 1 +.names 12537 12576 12577 +11 1 +.names 12539 12375 12578 +11 1 +.names 12581 12582 12579 +1- 1 +-1 1 +.names 12579 12580 +1 1 +.names 12526 12549 12581 +11 1 +.names 12525 12498 12582 +11 1 +.names 12587 12588 12583 +1- 1 +-1 1 +.names 12583 12584 +1 1 +.names 12553 12585 +1 1 +.names 12585 12586 +0 1 +.names 12586 12571 12587 +11 1 +.names 12585 12561 12588 +11 1 +.names 12310 12589 +1 1 +.names 12589 12590 +0 1 +.names 12590 12591 +1 1 +.names 12596 12597 12592 +1- 1 +-1 1 +.names 12592 12593 +1 1 +.names 12591 12594 +0 1 +.names 12186 12595 +0 1 +.names 12594 12595 12596 +11 1 +.names 12591 12567 12597 +11 1 +.names 12310 12598 +1 1 +.names 12598 12599 +0 1 +.names 12599 12600 +1 1 +.names 12604 12605 12601 +1- 1 +-1 1 +.names 12601 12602 +1 1 +.names 12600 12603 +0 1 +.names 12603 12462 12604 +11 1 +.names 12600 12486 12605 +11 1 +.names 12310 12606 +1 1 +.names 12606 12607 +0 1 +.names 12607 12608 +1 1 +.names 12612 12614 12609 +1- 1 +-1 1 +.names 12609 12610 +1 1 +.names 12608 12611 +0 1 +.names 12611 12341 12612 +11 1 +.names 11969 12613 +0 1 +.names 12608 12613 12614 +11 1 +.names 12617 12618 12615 +1- 1 +-1 1 +.names 12615 12616 +1 1 +.names 12520 12384 12617 +11 1 +.names 12517 12547 12618 +11 1 +.names 12621 12622 12619 +1- 1 +-1 1 +.names 12619 12620 +1 1 +.names 12491 12317 12621 +11 1 +.names 12488 12613 12622 +11 1 +.names 12310 12623 +1 1 +.names 12623 12624 +0 1 +.names 12624 12625 +1 1 +.names 12629 12630 12626 +1- 1 +-1 1 +.names 12626 12627 +1 1 +.names 12625 12628 +0 1 +.names 12628 12409 12629 +11 1 +.names 12625 12515 12630 +11 1 +.names 12633 12635 12631 +1- 1 +-1 1 +.names 12631 12632 +1 1 +.names 12513 12350 12633 +11 1 +.names 12304 12634 +0 1 +.names 12510 12634 12635 +11 1 +.names 12638 12639 12636 +1- 1 +-1 1 +.names 12636 12637 +1 1 +.names 12497 12595 12638 +11 1 +.names 12494 12392 12639 +11 1 +.names 12310 12640 +1 1 +.names 12640 12641 +0 1 +.names 12641 12642 +1 1 +.names 12646 12647 12643 +1- 1 +-1 1 +.names 12643 12644 +1 1 +.names 12642 12645 +0 1 +.names 12645 12533 12646 +11 1 +.names 12642 12407 12647 +11 1 +.names 12650 12651 12648 +1- 1 +-1 1 +.names 12648 12649 +1 1 +.names 12477 12441 12650 +11 1 +.names 12474 12456 12651 +11 1 +.names 12654 12655 12652 +1- 1 +-1 1 +.names 12652 12653 +1 1 +.names 12469 12472 12654 +11 1 +.names 12466 12506 12655 +11 1 +.names 12658 12659 12656 +1- 1 +-1 1 +.names 12656 12657 +1 1 +.names 12505 12413 12658 +11 1 +.names 12502 12470 12659 +11 1 +.names 12662 12663 12660 +1- 1 +-1 1 +.names 12660 12661 +1 1 +.names 12461 12500 12662 +11 1 +.names 12458 12415 12663 +11 1 +.names 12667 12668 12664 +1- 1 +-1 1 +.names 12664 12665 +1 1 +.names 12092 12666 +0 1 +.names 12532 12666 12667 +11 1 +.names 12529 11612 12668 +11 1 +.names 12671 12672 12669 +1- 1 +-1 1 +.names 12669 12670 +1 1 +.names 12484 12345 12671 +11 1 +.names 12481 12363 12672 +11 1 +.names 12677 12678 12673 +1- 1 +-1 1 +.names 12673 12674 +1 1 +.names 12553 12675 +1 1 +.names 12675 12676 +0 1 +.names 12676 12666 12677 +11 1 +.names 12675 12464 12678 +11 1 +.names 12310 12679 +1 1 +.names 12679 12680 +0 1 +.names 12680 12681 +1 1 +.names 12685 12686 12682 +1- 1 +-1 1 +.names 12682 12683 +1 1 +.names 12681 12684 +0 1 +.names 12684 12576 12685 +11 1 +.names 12681 12634 12686 +11 1 +.names 8138 12687 +1 1 +.names 12687 12688 +0 1 +.names 14136 14138 12689 +1- 1 +-1 1 +.names 12689 12690 +1 1 +.names 12690 12691 +0 1 +.names 12688 12691 12692 +11 1 +.names 14082 14084 12693 +1- 1 +-1 1 +.names 12693 12694 +1 1 +.names 12694 12695 +0 1 +.names 12687 12695 12696 +11 1 +.names 8138 12697 +1 1 +.names 12697 12698 +0 1 +.names 14140 14142 12699 +1- 1 +-1 1 +.names 12699 12700 +1 1 +.names 12700 12701 +0 1 +.names 12698 12701 12702 +11 1 +.names 14086 14088 12703 +1- 1 +-1 1 +.names 12703 12704 +1 1 +.names 12704 12705 +0 1 +.names 12697 12705 12706 +11 1 +.names 14144 14146 12707 +1- 1 +-1 1 +.names 12707 12708 +1 1 +.names 12708 12709 +0 1 +.names 12698 12709 12710 +11 1 +.names 14090 14092 12711 +1- 1 +-1 1 +.names 12711 12712 +1 1 +.names 12712 12713 +0 1 +.names 12697 12713 12714 +11 1 +.names 14148 14150 12715 +1- 1 +-1 1 +.names 12715 12716 +1 1 +.names 12716 12717 +0 1 +.names 12698 12717 12718 +11 1 +.names 14226 14228 12719 +1- 1 +-1 1 +.names 12719 12720 +1 1 +.names 12720 12721 +0 1 +.names 12697 12721 12722 +11 1 +.names 14156 14158 12723 +1- 1 +-1 1 +.names 12723 12724 +1 1 +.names 12724 12725 +0 1 +.names 12698 12725 12726 +11 1 +.names 14232 14234 12727 +1- 1 +-1 1 +.names 12727 12728 +1 1 +.names 12728 12729 +0 1 +.names 12697 12729 12730 +11 1 +.names 14159 14160 12731 +1- 1 +-1 1 +.names 12731 12732 +1 1 +.names 12732 12733 +0 1 +.names 12688 12733 12734 +11 1 +.names 14094 14096 12735 +1- 1 +-1 1 +.names 12735 12736 +1 1 +.names 12736 12737 +0 1 +.names 12687 12737 12738 +11 1 +.names 14248 14249 12739 +1- 1 +-1 1 +.names 12739 12740 +1 1 +.names 12740 12741 +0 1 +.names 12698 12741 12742 +11 1 +.names 14100 14102 12743 +1- 1 +-1 1 +.names 12743 12744 +1 1 +.names 12744 12745 +0 1 +.names 12697 12745 12746 +11 1 +.names 14161 14163 12747 +1- 1 +-1 1 +.names 12747 12748 +1 1 +.names 12748 12749 +0 1 +.names 12698 12749 12750 +11 1 +.names 14104 14106 12751 +1- 1 +-1 1 +.names 12751 12752 +1 1 +.names 12752 12753 +0 1 +.names 12697 12753 12754 +11 1 +.names 14164 14166 12755 +1- 1 +-1 1 +.names 12755 12756 +1 1 +.names 12756 12757 +0 1 +.names 12688 12757 12758 +11 1 +.names 14108 14110 12759 +1- 1 +-1 1 +.names 12759 12760 +1 1 +.names 12760 12761 +0 1 +.names 12687 12761 12762 +11 1 +.names 14167 14169 12763 +1- 1 +-1 1 +.names 12763 12764 +1 1 +.names 12764 12765 +0 1 +.names 12688 12765 12766 +11 1 +.names 14112 14114 12767 +1- 1 +-1 1 +.names 12767 12768 +1 1 +.names 12768 12769 +0 1 +.names 12687 12769 12770 +11 1 +.names 14211 14212 12771 +1- 1 +-1 1 +.names 12771 12772 +1 1 +.names 12772 12773 +0 1 +.names 12698 12773 12774 +11 1 +.names 14116 14118 12775 +1- 1 +-1 1 +.names 12775 12776 +1 1 +.names 12776 12777 +0 1 +.names 12697 12777 12778 +11 1 +.names 14216 14217 12779 +1- 1 +-1 1 +.names 12779 12780 +1 1 +.names 12780 12781 +0 1 +.names 12688 12781 12782 +11 1 +.names 14120 14122 12783 +1- 1 +-1 1 +.names 12783 12784 +1 1 +.names 12784 12785 +0 1 +.names 12687 12785 12786 +11 1 +.names 14259 14260 12787 +1- 1 +-1 1 +.names 12787 12788 +1 1 +.names 12788 12789 +0 1 +.names 12698 12789 12790 +11 1 +.names 14124 14126 12791 +1- 1 +-1 1 +.names 12791 12792 +1 1 +.names 12792 12793 +0 1 +.names 12697 12793 12794 +11 1 +.names 14170 14172 12795 +1- 1 +-1 1 +.names 12795 12796 +1 1 +.names 12796 12797 +0 1 +.names 12688 12797 12798 +11 1 +.names 14132 14134 12799 +1- 1 +-1 1 +.names 12799 12800 +1 1 +.names 12800 12801 +0 1 +.names 12687 12801 12802 +11 1 +.names 14288 14289 12803 +1- 1 +-1 1 +.names 12803 12804 +1 1 +.names 12804 12805 +0 1 +.names 12688 12805 12806 +11 1 +.names 12687 12691 12807 +11 1 +.names 14277 14278 12808 +1- 1 +-1 1 +.names 12808 12809 +1 1 +.names 12809 12810 +0 1 +.names 12698 12810 12811 +11 1 +.names 12697 12701 12812 +11 1 +.names 14244 14245 12813 +1- 1 +-1 1 +.names 12813 12814 +1 1 +.names 12814 12815 +0 1 +.names 12698 12815 12816 +11 1 +.names 12697 12709 12817 +11 1 +.names 14256 14257 12818 +1- 1 +-1 1 +.names 12818 12819 +1 1 +.names 12819 12820 +0 1 +.names 12698 12820 12821 +11 1 +.names 12697 12717 12822 +11 1 +.names 14176 14178 12823 +1- 1 +-1 1 +.names 12823 12824 +1 1 +.names 12824 12825 +0 1 +.names 12688 12825 12826 +11 1 +.names 12687 12725 12827 +11 1 +.names 14273 14274 12828 +1- 1 +-1 1 +.names 12828 12829 +1 1 +.names 12829 12830 +0 1 +.names 12688 12830 12831 +11 1 +.names 12687 12733 12832 +11 1 +.names 14186 14187 12833 +1- 1 +-1 1 +.names 12833 12834 +1 1 +.names 12834 12835 +0 1 +.names 12688 12835 12836 +11 1 +.names 12687 12757 12837 +11 1 +.names 14292 14293 12838 +1- 1 +-1 1 +.names 12838 12839 +1 1 +.names 12839 12840 +0 1 +.names 12698 12840 12841 +11 1 +.names 12697 12765 12842 +11 1 +.names 14188 14189 12843 +1- 1 +-1 1 +.names 12843 12844 +1 1 +.names 12844 12845 +0 1 +.names 12688 12845 12846 +11 1 +.names 12687 12773 12847 +11 1 +.names 14202 14203 12848 +1- 1 +-1 1 +.names 12848 12849 +1 1 +.names 12849 12850 +0 1 +.names 12698 12850 12851 +11 1 +.names 12697 12810 12852 +11 1 +.names 8111 12853 +0 1 +.names 12688 12853 12854 +11 1 +.names 12687 12830 12855 +11 1 +.names 12698 12853 12856 +11 1 +.names 14179 14180 12857 +1- 1 +-1 1 +.names 12857 12858 +1 1 +.names 12858 12859 +0 1 +.names 12697 12859 12860 +11 1 +.names 12698 12097 12861 +11 1 +.names 14184 14185 12862 +1- 1 +-1 1 +.names 12862 12863 +1 1 +.names 12863 12864 +0 1 +.names 12697 12864 12865 +11 1 +.names 12688 12082 12866 +11 1 +.names 12687 12840 12867 +11 1 +.names 12698 12097 12868 +11 1 +.names 12697 12845 12869 +11 1 +.names 12688 12853 12870 +11 1 +.names 14206 14207 12871 +1- 1 +-1 1 +.names 12871 12872 +1 1 +.names 12872 12873 +0 1 +.names 12687 12873 12874 +11 1 +.names 12698 12097 12875 +11 1 +.names 12697 12850 12876 +11 1 +.names 12698 12777 12877 +11 1 +.names 14264 14266 12878 +1- 1 +-1 1 +.names 12878 12879 +1 1 +.names 12879 12880 +0 1 +.names 12697 12880 12881 +11 1 +.names 12688 12097 12882 +11 1 +.names 14252 14253 12883 +1- 1 +-1 1 +.names 12883 12884 +1 1 +.names 12884 12885 +0 1 +.names 12687 12885 12886 +11 1 +.names 12698 12082 12887 +11 1 +.names 14192 14193 12888 +1- 1 +-1 1 +.names 12888 12889 +1 1 +.names 12889 12890 +0 1 +.names 12697 12890 12891 +11 1 +.names 12698 12793 12892 +11 1 +.names 14283 14285 12893 +1- 1 +-1 1 +.names 12893 12894 +1 1 +.names 12894 12895 +0 1 +.names 12697 12895 12896 +11 1 +.names 14128 14130 12897 +1- 1 +-1 1 +.names 12897 12898 +1 1 +.names 12898 12899 +0 1 +.names 12688 12899 12900 +11 1 +.names 14197 14199 12901 +1- 1 +-1 1 +.names 12901 12902 +1 1 +.names 12902 12903 +0 1 +.names 12687 12903 12904 +11 1 +.names 12698 12801 12905 +11 1 +.names 14297 14298 12906 +1- 1 +-1 1 +.names 12906 12907 +1 1 +.names 12907 12908 +0 1 +.names 12697 12908 12909 +11 1 +.names 12688 12910 +1 1 +.names 12910 12911 +0 1 +.names 14194 14195 12912 +1- 1 +-1 1 +.names 12912 12913 +1 1 +.names 12913 12914 +0 1 +.names 12911 12914 12915 +11 1 +.names 12910 12097 12916 +11 1 +.names 12688 12917 +1 1 +.names 12917 12918 +0 1 +.names 14190 14191 12919 +1- 1 +-1 1 +.names 12919 12920 +1 1 +.names 12920 12921 +0 1 +.names 12918 12921 12922 +11 1 +.names 12917 12082 12923 +11 1 +.names 12918 12835 12924 +11 1 +.names 12917 12853 12925 +11 1 +.names 14240 14241 12926 +1- 1 +-1 1 +.names 12926 12927 +1 1 +.names 12927 12928 +0 1 +.names 12918 12928 12929 +11 1 +.names 12917 12853 12930 +11 1 +.names 14246 14247 12931 +1- 1 +-1 1 +.names 12931 12932 +1 1 +.names 12932 12933 +0 1 +.names 12918 12933 12934 +11 1 +.names 12917 12853 12935 +11 1 +.names 12918 12815 12936 +11 1 +.names 12917 12885 12937 +11 1 +.names 12947 12938 +0 1 +.names 12938 12939 +1 1 +.names 12939 12940 +0 1 +.names 14208 14209 12941 +1- 1 +-1 1 +.names 12941 12942 +1 1 +.names 12942 12943 +0 1 +.names 12940 12943 12944 +11 1 +.names 12939 12853 12945 +11 1 +.names 12938 12946 +1 1 +.names 8138 12947 +1 1 +.names 12946 12948 +0 1 +.names 14281 14282 12949 +1- 1 +-1 1 +.names 12949 12950 +1 1 +.names 12950 12951 +0 1 +.names 12948 12951 12952 +11 1 +.names 12946 12933 12953 +11 1 +.names 12938 12954 +1 1 +.names 12938 12955 +1 1 +.names 12955 12956 +0 1 +.names 14152 14154 12957 +1- 1 +-1 1 +.names 12957 12958 +1 1 +.names 12958 12959 +0 1 +.names 12956 12959 12960 +11 1 +.names 14173 14175 12961 +1- 1 +-1 1 +.names 12961 12962 +1 1 +.names 12962 12963 +0 1 +.names 12955 12963 12964 +11 1 +.names 12698 12965 +1 1 +.names 12965 12966 +0 1 +.names 12966 12789 12967 +11 1 +.names 14269 14270 12968 +1- 1 +-1 1 +.names 12968 12969 +1 1 +.names 12969 12970 +0 1 +.names 12965 12970 12971 +11 1 +.names 12688 12972 +1 1 +.names 12972 12973 +0 1 +.names 12973 12825 12974 +11 1 +.names 12972 12914 12975 +11 1 +.names 12911 12749 12976 +11 1 +.names 12910 12864 12977 +11 1 +.names 12966 12820 12978 +11 1 +.names 12965 12890 12979 +11 1 +.names 12698 12753 12980 +11 1 +.names 14222 14224 12981 +1- 1 +-1 1 +.names 12981 12982 +1 1 +.names 12982 12983 +0 1 +.names 12697 12983 12984 +11 1 +.names 12688 12985 +1 1 +.names 12985 12986 +0 1 +.names 12986 12781 12987 +11 1 +.names 12985 12873 12988 +11 1 +.names 12688 12785 12989 +11 1 +.names 14229 14231 12990 +1- 1 +-1 1 +.names 12990 12991 +1 1 +.names 12991 12992 +0 1 +.names 12687 12992 12993 +11 1 +.names 12940 12994 +1 1 +.names 12994 12995 +0 1 +.names 12995 12943 12996 +11 1 +.names 12994 12805 12997 +11 1 +.names 12918 12998 +1 1 +.names 12998 12999 +0 1 +.names 12999 12082 13000 +11 1 +.names 12998 12970 13001 +11 1 +.names 12688 12745 13002 +11 1 +.names 14219 14221 13003 +1- 1 +-1 1 +.names 13003 13004 +1 1 +.names 13004 13005 +0 1 +.names 12687 13005 13006 +11 1 +.names 12688 13007 +1 1 +.names 13007 13008 +0 1 +.names 14235 14237 13009 +1- 1 +-1 1 +.names 13009 13010 +1 1 +.names 13010 13011 +0 1 +.names 13008 13011 13012 +11 1 +.names 13007 12959 13013 +11 1 +.names 13019 13014 +0 1 +.names 13014 13015 +1 1 +.names 13015 13016 +0 1 +.names 13016 12741 13017 +11 1 +.names 13015 12859 13018 +11 1 +.names 12918 13019 +1 1 +.names 12688 12761 13020 +11 1 +.names 14261 14263 13021 +1- 1 +-1 1 +.names 13021 13022 +1 1 +.names 13022 13023 +0 1 +.names 12687 13023 13024 +11 1 +.names 12688 12769 13025 +11 1 +.names 14181 14183 13026 +1- 1 +-1 1 +.names 13026 13027 +1 1 +.names 13027 13028 +0 1 +.names 12687 13028 13029 +11 1 +.names 12698 12737 13030 +11 1 +.names 14076 14078 13031 +1- 1 +-1 1 +.names 13031 13032 +1 1 +.names 13032 13033 +0 1 +.names 12697 13033 13034 +11 1 +.names 12966 12899 13035 +11 1 +.names 12965 12951 13036 +11 1 +.names 12954 13037 +0 1 +.names 13037 13038 +1 1 +.names 13038 13039 +0 1 +.names 13039 12921 13040 +11 1 +.names 13038 12797 13041 +11 1 +.names 12966 12963 13042 +11 1 +.names 12965 12928 13043 +11 1 +.names 13051 13055 13044 +1- 1 +-1 1 +.names 13044 13045 +1 1 +.names 7975 13046 +1 1 +.names 13046 13047 +0 1 +.names 33695 33696 13048 +1- 1 +-1 1 +.names 13048 13049 +1 1 +.names 13049 13050 +0 1 +.names 13047 13050 13051 +11 1 +.names 32642 32643 13052 +1- 1 +-1 1 +.names 13052 13053 +1 1 +.names 13053 13054 +0 1 +.names 13046 13054 13055 +11 1 +.names 13063 13067 13056 +1- 1 +-1 1 +.names 13056 13057 +1 1 +.names 7975 13058 +1 1 +.names 13058 13059 +0 1 +.names 33710 33711 13060 +1- 1 +-1 1 +.names 13060 13061 +1 1 +.names 13061 13062 +0 1 +.names 13059 13062 13063 +11 1 +.names 32327 32330 13064 +1- 1 +-1 1 +.names 13064 13065 +1 1 +.names 13065 13066 +0 1 +.names 13058 13066 13067 +11 1 +.names 13075 13079 13068 +1- 1 +-1 1 +.names 13068 13069 +1 1 +.names 7975 13070 +1 1 +.names 13070 13071 +0 1 +.names 33817 33818 13072 +1- 1 +-1 1 +.names 13072 13073 +1 1 +.names 13073 13074 +0 1 +.names 13071 13074 13075 +11 1 +.names 32815 32818 13076 +1- 1 +-1 1 +.names 13076 13077 +1 1 +.names 13077 13078 +0 1 +.names 13070 13078 13079 +11 1 +.names 13085 13089 13080 +1- 1 +-1 1 +.names 13080 13081 +1 1 +.names 33604 33605 13082 +1- 1 +-1 1 +.names 13082 13083 +1 1 +.names 13083 13084 +0 1 +.names 13059 13084 13085 +11 1 +.names 33246 33249 13086 +1- 1 +-1 1 +.names 13086 13087 +1 1 +.names 13087 13088 +0 1 +.names 13058 13088 13089 +11 1 +.names 13095 13099 13090 +1- 1 +-1 1 +.names 13090 13091 +1 1 +.names 33449 33450 13092 +1- 1 +-1 1 +.names 13092 13093 +1 1 +.names 13093 13094 +0 1 +.names 13071 13094 13095 +11 1 +.names 32977 32980 13096 +1- 1 +-1 1 +.names 13096 13097 +1 1 +.names 13097 13098 +0 1 +.names 13070 13098 13099 +11 1 +.names 13107 13111 13100 +1- 1 +-1 1 +.names 13100 13101 +1 1 +.names 7975 13102 +1 1 +.names 13102 13103 +0 1 +.names 33589 33590 13104 +1- 1 +-1 1 +.names 13104 13105 +1 1 +.names 13105 13106 +0 1 +.names 13103 13106 13107 +11 1 +.names 32962 32965 13108 +1- 1 +-1 1 +.names 13108 13109 +1 1 +.names 13109 13110 +0 1 +.names 13102 13110 13111 +11 1 +.names 13117 13121 13112 +1- 1 +-1 1 +.names 13112 13113 +1 1 +.names 33482 33483 13114 +1- 1 +-1 1 +.names 13114 13115 +1 1 +.names 13115 13116 +0 1 +.names 13071 13116 13117 +11 1 +.names 33079 33082 13118 +1- 1 +-1 1 +.names 13118 13119 +1 1 +.names 13119 13120 +0 1 +.names 13070 13120 13121 +11 1 +.names 13129 13133 13122 +1- 1 +-1 1 +.names 13122 13123 +1 1 +.names 7975 13124 +1 1 +.names 13124 13125 +0 1 +.names 33832 33833 13126 +1- 1 +-1 1 +.names 13126 13127 +1 1 +.names 13127 13128 +0 1 +.names 13125 13128 13129 +11 1 +.names 32517 32520 13130 +1- 1 +-1 1 +.names 13130 13131 +1 1 +.names 13131 13132 +0 1 +.names 13124 13132 13133 +11 1 +.names 13139 13143 13134 +1- 1 +-1 1 +.names 13134 13135 +1 1 +.names 33680 33681 13136 +1- 1 +-1 1 +.names 13136 13137 +1 1 +.names 13137 13138 +0 1 +.names 13103 13138 13139 +11 1 +.names 32317 32318 13140 +1- 1 +-1 1 +.names 13140 13141 +1 1 +.names 13141 13142 +0 1 +.names 13102 13142 13143 +11 1 +.names 13149 13153 13144 +1- 1 +-1 1 +.names 13144 13145 +1 1 +.names 33401 33402 13146 +1- 1 +-1 1 +.names 13146 13147 +1 1 +.names 13147 13148 +0 1 +.names 13103 13148 13149 +11 1 +.names 32465 32468 13150 +1- 1 +-1 1 +.names 13150 13151 +1 1 +.names 13151 13152 +0 1 +.names 13102 13152 13153 +11 1 +.names 13159 13163 13154 +1- 1 +-1 1 +.names 13154 13155 +1 1 +.names 33619 33620 13156 +1- 1 +-1 1 +.names 13156 13157 +1 1 +.names 13157 13158 +0 1 +.names 13047 13158 13159 +11 1 +.names 32242 32245 13160 +1- 1 +-1 1 +.names 13160 13161 +1 1 +.names 13161 13162 +0 1 +.names 13046 13162 13163 +11 1 +.names 13169 13173 13164 +1- 1 +-1 1 +.names 13164 13165 +1 1 +.names 33559 33560 13166 +1- 1 +-1 1 +.names 13166 13167 +1 1 +.names 13167 13168 +0 1 +.names 13047 13168 13169 +11 1 +.names 32692 32695 13170 +1- 1 +-1 1 +.names 13170 13171 +1 1 +.names 13171 13172 +0 1 +.names 13046 13172 13173 +11 1 +.names 13179 13183 13174 +1- 1 +-1 1 +.names 13174 13175 +1 1 +.names 33528 33529 13176 +1- 1 +-1 1 +.names 13176 13177 +1 1 +.names 13177 13178 +0 1 +.names 13125 13178 13179 +11 1 +.names 32180 32181 13180 +1- 1 +-1 1 +.names 13180 13181 +1 1 +.names 13181 13182 +0 1 +.names 13124 13182 13183 +11 1 +.names 13189 13193 13184 +1- 1 +-1 1 +.names 13184 13185 +1 1 +.names 33756 33757 13186 +1- 1 +-1 1 +.names 13186 13187 +1 1 +.names 13187 13188 +0 1 +.names 13125 13188 13189 +11 1 +.names 32750 32753 13190 +1- 1 +-1 1 +.names 13190 13191 +1 1 +.names 13191 13192 +0 1 +.names 13124 13192 13193 +11 1 +.names 13199 13203 13194 +1- 1 +-1 1 +.names 13194 13195 +1 1 +.names 33771 33772 13196 +1- 1 +-1 1 +.names 13196 13197 +1 1 +.names 13197 13198 +0 1 +.names 13059 13198 13199 +11 1 +.names 33209 33212 13200 +1- 1 +-1 1 +.names 13200 13201 +1 1 +.names 13201 13202 +0 1 +.names 13058 13202 13203 +11 1 +.names 13209 13213 13204 +1- 1 +-1 1 +.names 13204 13205 +1 1 +.names 33725 33726 13206 +1- 1 +-1 1 +.names 13206 13207 +1 1 +.names 13207 13208 +0 1 +.names 13103 13208 13209 +11 1 +.names 33195 33198 13210 +1- 1 +-1 1 +.names 13210 13211 +1 1 +.names 13211 13212 +0 1 +.names 13102 13212 13213 +11 1 +.names 13219 13223 13214 +1- 1 +-1 1 +.names 13214 13215 +1 1 +.names 33848 33849 13216 +1- 1 +-1 1 +.names 13216 13217 +1 1 +.names 13217 13218 +0 1 +.names 13047 13218 13219 +11 1 +.names 32707 32710 13220 +1- 1 +-1 1 +.names 13220 13221 +1 1 +.names 13221 13222 +0 1 +.names 13046 13222 13223 +11 1 +.names 13229 13233 13224 +1- 1 +-1 1 +.names 13224 13225 +1 1 +.names 33467 33468 13226 +1- 1 +-1 1 +.names 13226 13227 +1 1 +.names 13227 13228 +0 1 +.names 13059 13228 13229 +11 1 +.names 32203 32206 13230 +1- 1 +-1 1 +.names 13230 13231 +1 1 +.names 13231 13232 +0 1 +.names 13058 13232 13233 +11 1 +.names 13239 13243 13234 +1- 1 +-1 1 +.names 13234 13235 +1 1 +.names 33634 33635 13236 +1- 1 +-1 1 +.names 13236 13237 +1 1 +.names 13237 13238 +0 1 +.names 13125 13238 13239 +11 1 +.names 32590 32593 13240 +1- 1 +-1 1 +.names 13240 13241 +1 1 +.names 13241 13242 +0 1 +.names 13124 13242 13243 +11 1 +.names 13246 13247 13244 +1- 1 +-1 1 +.names 13244 13245 +1 1 +.names 13125 13242 13246 +11 1 +.names 13124 13238 13247 +11 1 +.names 13250 13251 13248 +1- 1 +-1 1 +.names 13248 13249 +1 1 +.names 13125 13232 13250 +11 1 +.names 13124 13228 13251 +11 1 +.names 13254 13255 13252 +1- 1 +-1 1 +.names 13252 13253 +1 1 +.names 13071 13222 13254 +11 1 +.names 13070 13218 13255 +11 1 +.names 13258 13259 13256 +1- 1 +-1 1 +.names 13256 13257 +1 1 +.names 13103 13212 13258 +11 1 +.names 13102 13208 13259 +11 1 +.names 13262 13263 13260 +1- 1 +-1 1 +.names 13260 13261 +1 1 +.names 13047 13202 13262 +11 1 +.names 13046 13198 13263 +11 1 +.names 13266 13267 13264 +1- 1 +-1 1 +.names 13264 13265 +1 1 +.names 13071 13192 13266 +11 1 +.names 13070 13188 13267 +11 1 +.names 13270 13271 13268 +1- 1 +-1 1 +.names 13268 13269 +1 1 +.names 13103 13182 13270 +11 1 +.names 13102 13178 13271 +11 1 +.names 13274 13275 13272 +1- 1 +-1 1 +.names 13272 13273 +1 1 +.names 13071 13172 13274 +11 1 +.names 13070 13168 13275 +11 1 +.names 13278 13279 13276 +1- 1 +-1 1 +.names 13276 13277 +1 1 +.names 13125 13152 13278 +11 1 +.names 13124 13148 13279 +11 1 +.names 13284 13285 13280 +1- 1 +-1 1 +.names 13280 13281 +1 1 +.names 7975 13282 +1 1 +.names 13282 13283 +0 1 +.names 13283 13142 13284 +11 1 +.names 13282 13138 13285 +11 1 +.names 13288 13289 13286 +1- 1 +-1 1 +.names 13286 13287 +1 1 +.names 13047 13132 13288 +11 1 +.names 13046 13128 13289 +11 1 +.names 13292 13293 13290 +1- 1 +-1 1 +.names 13290 13291 +1 1 +.names 13059 13120 13292 +11 1 +.names 13058 13116 13293 +11 1 +.names 13296 13297 13294 +1- 1 +-1 1 +.names 13294 13295 +1 1 +.names 13059 13110 13296 +11 1 +.names 13058 13106 13297 +11 1 +.names 13300 13301 13298 +1- 1 +-1 1 +.names 13298 13299 +1 1 +.names 13047 13098 13300 +11 1 +.names 13046 13094 13301 +11 1 +.names 13304 13305 13302 +1- 1 +-1 1 +.names 13302 13303 +1 1 +.names 13071 13088 13304 +11 1 +.names 13070 13084 13305 +11 1 +.names 13308 13309 13306 +1- 1 +-1 1 +.names 13306 13307 +1 1 +.names 13103 13078 13308 +11 1 +.names 13102 13074 13309 +11 1 +.names 13312 13313 13310 +1- 1 +-1 1 +.names 13310 13311 +1 1 +.names 13283 13066 13312 +11 1 +.names 13282 13062 13313 +11 1 +.names 13316 13317 13314 +1- 1 +-1 1 +.names 13314 13315 +1 1 +.names 13283 13054 13316 +11 1 +.names 13282 13050 13317 +11 1 +.names 13323 13327 13318 +1- 1 +-1 1 +.names 13318 13319 +1 1 +.names 32403 32406 13320 +1- 1 +-1 1 +.names 13320 13321 +1 1 +.names 13321 13322 +0 1 +.names 13283 13322 13323 +11 1 +.names 33740 33741 13324 +1- 1 +-1 1 +.names 13324 13325 +1 1 +.names 13325 13326 +0 1 +.names 13282 13326 13327 +11 1 +.names 13333 13337 13328 +1- 1 +-1 1 +.names 13328 13329 +1 1 +.names 33314 33315 13330 +1- 1 +-1 1 +.names 13330 13331 +1 1 +.names 13331 13332 +0 1 +.names 13103 13332 13333 +11 1 +.names 33543 33544 13334 +1- 1 +-1 1 +.names 13334 13335 +1 1 +.names 13335 13336 +0 1 +.names 13102 13336 13337 +11 1 +.names 13343 13347 13338 +1- 1 +-1 1 +.names 13338 13339 +1 1 +.names 32900 32903 13340 +1- 1 +-1 1 +.names 13340 13341 +1 1 +.names 13341 13342 +0 1 +.names 13283 13342 13343 +11 1 +.names 33433 33434 13344 +1- 1 +-1 1 +.names 13344 13345 +1 1 +.names 13345 13346 +0 1 +.names 13282 13346 13347 +11 1 +.names 13353 13357 13348 +1- 1 +-1 1 +.names 13348 13349 +1 1 +.names 32130 32133 13350 +1- 1 +-1 1 +.names 13350 13351 +1 1 +.names 13351 13352 +0 1 +.names 13103 13352 13353 +11 1 +.names 33513 33514 13354 +1- 1 +-1 1 +.names 13354 13355 +1 1 +.names 13355 13356 +0 1 +.names 13102 13356 13357 +11 1 +.names 13363 13367 13358 +1- 1 +-1 1 +.names 13358 13359 +1 1 +.names 32830 32833 13360 +1- 1 +-1 1 +.names 13360 13361 +1 1 +.names 13361 13362 +0 1 +.names 13125 13362 13363 +11 1 +.names 33417 33418 13364 +1- 1 +-1 1 +.names 13364 13365 +1 1 +.names 13365 13366 +0 1 +.names 13124 13366 13367 +11 1 +.names 13373 13377 13368 +1- 1 +-1 1 +.names 13368 13369 +1 1 +.names 32556 32559 13370 +1- 1 +-1 1 +.names 13370 13371 +1 1 +.names 13371 13372 +0 1 +.names 13047 13372 13373 +11 1 +.names 33574 33575 13374 +1- 1 +-1 1 +.names 13374 13375 +1 1 +.names 13375 13376 +0 1 +.names 13046 13376 13377 +11 1 +.names 13383 13387 13378 +1- 1 +-1 1 +.names 13378 13379 +1 1 +.names 32481 32484 13380 +1- 1 +-1 1 +.names 13380 13381 +1 1 +.names 13381 13382 +0 1 +.names 13283 13382 13383 +11 1 +.names 33385 33386 13384 +1- 1 +-1 1 +.names 13384 13385 +1 1 +.names 13385 13386 +0 1 +.names 13282 13386 13387 +11 1 +.names 13393 13397 13388 +1- 1 +-1 1 +.names 13388 13389 +1 1 +.names 33094 33097 13390 +1- 1 +-1 1 +.names 13390 13391 +1 1 +.names 13391 13392 +0 1 +.names 13059 13392 13393 +11 1 +.names 33665 33666 13394 +1- 1 +-1 1 +.names 13394 13395 +1 1 +.names 13395 13396 +0 1 +.names 13058 13396 13397 +11 1 +.names 13403 13407 13398 +1- 1 +-1 1 +.names 13398 13399 +1 1 +.names 33136 33139 13400 +1- 1 +-1 1 +.names 13400 13401 +1 1 +.names 13401 13402 +0 1 +.names 13071 13402 13403 +11 1 +.names 33802 33803 13404 +1- 1 +-1 1 +.names 13404 13405 +1 1 +.names 13405 13406 +0 1 +.names 13070 13406 13407 +11 1 +.names 13413 13417 13408 +1- 1 +-1 1 +.names 13408 13409 +1 1 +.names 33016 33019 13410 +1- 1 +-1 1 +.names 13410 13411 +1 1 +.names 13411 13412 +0 1 +.names 13059 13412 13413 +11 1 +.names 33786 33787 13414 +1- 1 +-1 1 +.names 13414 13415 +1 1 +.names 13415 13416 +0 1 +.names 13058 13416 13417 +11 1 +.names 13423 13427 13418 +1- 1 +-1 1 +.names 13418 13419 +1 1 +.names 33323 33326 13420 +1- 1 +-1 1 +.names 13420 13421 +1 1 +.names 13421 13422 +0 1 +.names 13283 13422 13423 +11 1 +.names 33650 33651 13424 +1- 1 +-1 1 +.names 13424 13425 +1 1 +.names 13425 13426 +0 1 +.names 13282 13426 13427 +11 1 +.names 13433 13437 13428 +1- 1 +-1 1 +.names 13428 13429 +1 1 +.names 32365 32368 13430 +1- 1 +-1 1 +.names 13430 13431 +1 1 +.names 13431 13432 +0 1 +.names 13125 13432 13433 +11 1 +.names 33369 33370 13434 +1- 1 +-1 1 +.names 13434 13435 +1 1 +.names 13435 13436 +0 1 +.names 13124 13436 13437 +11 1 +.names 13440 13444 13438 +1- 1 +-1 1 +.names 13438 13439 +1 1 +.names 13283 8097 13440 +11 1 +.names 33498 33499 13441 +1- 1 +-1 1 +.names 13441 13442 +1 1 +.names 13442 13443 +0 1 +.names 13282 13443 13444 +11 1 +.names 13447 13448 13445 +1- 1 +-1 1 +.names 13445 13446 +1 1 +.names 13059 13386 13447 +11 1 +.names 13058 13382 13448 +11 1 +.names 13451 13452 13449 +1- 1 +-1 1 +.names 13449 13450 +1 1 +.names 13047 13346 13451 +11 1 +.names 13046 13342 13452 +11 1 +.names 13455 13456 13453 +1- 1 +-1 1 +.names 13453 13454 +1 1 +.names 13125 13426 13455 +11 1 +.names 13124 13422 13456 +11 1 +.names 13459 13460 13457 +1- 1 +-1 1 +.names 13457 13458 +1 1 +.names 13059 13443 13459 +11 1 +.names 13058 8097 13460 +11 1 +.names 13463 13464 13461 +1- 1 +-1 1 +.names 13461 13462 +1 1 +.names 13059 13336 13463 +11 1 +.names 13058 13332 13464 +11 1 +.names 13467 13468 13465 +1- 1 +-1 1 +.names 13465 13466 +1 1 +.names 13071 13416 13467 +11 1 +.names 13070 13412 13468 +11 1 +.names 13471 13472 13469 +1- 1 +-1 1 +.names 13469 13470 +1 1 +.names 13071 13326 13471 +11 1 +.names 13070 13322 13472 +11 1 +.names 13475 13476 13473 +1- 1 +-1 1 +.names 13473 13474 +1 1 +.names 13047 13436 13475 +11 1 +.names 13046 13432 13476 +11 1 +.names 13479 13480 13477 +1- 1 +-1 1 +.names 13477 13478 +1 1 +.names 13103 13366 13479 +11 1 +.names 13102 13362 13480 +11 1 +.names 13483 13484 13481 +1- 1 +-1 1 +.names 13481 13482 +1 1 +.names 13283 13396 13483 +11 1 +.names 13282 13392 13484 +11 1 +.names 13487 13488 13485 +1- 1 +-1 1 +.names 13485 13486 +1 1 +.names 13103 13162 13487 +11 1 +.names 13102 13158 13488 +11 1 +.names 13491 13492 13489 +1- 1 +-1 1 +.names 13489 13490 +1 1 +.names 13047 13406 13491 +11 1 +.names 13046 13402 13492 +11 1 +.names 13495 13496 13493 +1- 1 +-1 1 +.names 13493 13494 +1 1 +.names 13125 13376 13495 +11 1 +.names 13124 13372 13496 +11 1 +.names 13499 13500 13497 +1- 1 +-1 1 +.names 13497 13498 +1 1 +.names 13071 13356 13499 +11 1 +.names 13070 13352 13500 +11 1 +.names 7976 13501 +0 1 +.names 13840 13842 13502 +1- 1 +-1 1 +.names 13502 13503 +1 1 +.names 13503 13504 +0 1 +.names 13501 13504 13505 +11 1 +.names 13914 13916 13506 +1- 1 +-1 1 +.names 13506 13507 +1 1 +.names 13507 13508 +0 1 +.names 7976 13508 13509 +11 1 +.names 13844 13846 13510 +1- 1 +-1 1 +.names 13510 13511 +1 1 +.names 13511 13512 +0 1 +.names 13501 13512 13513 +11 1 +.names 13935 13937 13514 +1- 1 +-1 1 +.names 13514 13515 +1 1 +.names 13515 13516 +0 1 +.names 7976 13516 13517 +11 1 +.names 14017 14018 13518 +1- 1 +-1 1 +.names 13518 13519 +1 1 +.names 13519 13520 +0 1 +.names 13501 13520 13521 +11 1 +.names 14053 14054 13522 +1- 1 +-1 1 +.names 13522 13523 +1 1 +.names 13523 13524 +0 1 +.names 7976 13524 13525 +11 1 +.names 13854 13856 13526 +1- 1 +-1 1 +.names 13526 13527 +1 1 +.names 13527 13528 +0 1 +.names 13501 13528 13529 +11 1 +.names 13976 13978 13530 +1- 1 +-1 1 +.names 13530 13531 +1 1 +.names 13531 13532 +0 1 +.names 7976 13532 13533 +11 1 +.names 13858 13859 13534 +1- 1 +-1 1 +.names 13534 13535 +1 1 +.names 13535 13536 +0 1 +.names 13501 13536 13537 +11 1 +.names 14055 14056 13538 +1- 1 +-1 1 +.names 13538 13539 +1 1 +.names 13539 13540 +0 1 +.names 7976 13540 13541 +11 1 +.names 13861 13862 13542 +1- 1 +-1 1 +.names 13542 13543 +1 1 +.names 13543 13544 +0 1 +.names 13501 13544 13545 +11 1 +.names 13941 13943 13546 +1- 1 +-1 1 +.names 13546 13547 +1 1 +.names 13547 13548 +0 1 +.names 7976 13548 13549 +11 1 +.names 13867 13868 13550 +1- 1 +-1 1 +.names 13550 13551 +1 1 +.names 13551 13552 +0 1 +.names 13501 13552 13553 +11 1 +.names 13982 13984 13554 +1- 1 +-1 1 +.names 13554 13555 +1 1 +.names 13555 13556 +0 1 +.names 7976 13556 13557 +11 1 +.names 13873 13874 13558 +1- 1 +-1 1 +.names 13558 13559 +1 1 +.names 13559 13560 +0 1 +.names 13501 13560 13561 +11 1 +.names 14067 14068 13562 +1- 1 +-1 1 +.names 13562 13563 +1 1 +.names 13563 13564 +0 1 +.names 7976 13564 13565 +11 1 +.names 14071 14072 13566 +1- 1 +-1 1 +.names 13566 13567 +1 1 +.names 13567 13568 +0 1 +.names 13501 13568 13569 +11 1 +.names 14004 14006 13570 +1- 1 +-1 1 +.names 13570 13571 +1 1 +.names 13571 13572 +0 1 +.names 7976 13572 13573 +11 1 +.names 13879 13881 13574 +1- 1 +-1 1 +.names 13574 13575 +1 1 +.names 13575 13576 +0 1 +.names 13501 13576 13577 +11 1 +.names 14063 14064 13578 +1- 1 +-1 1 +.names 13578 13579 +1 1 +.names 13579 13580 +0 1 +.names 7976 13580 13581 +11 1 +.names 14042 14043 13582 +1- 1 +-1 1 +.names 13582 13583 +1 1 +.names 13583 13584 +0 1 +.names 13501 13584 13585 +11 1 +.names 13952 13954 13586 +1- 1 +-1 1 +.names 13586 13587 +1 1 +.names 13587 13588 +0 1 +.names 7976 13588 13589 +11 1 +.names 13883 13885 13590 +1- 1 +-1 1 +.names 13590 13591 +1 1 +.names 13591 13592 +0 1 +.names 13501 13592 13593 +11 1 +.names 13902 13904 13594 +1- 1 +-1 1 +.names 13594 13595 +1 1 +.names 13595 13596 +0 1 +.names 7976 13596 13597 +11 1 +.names 14030 14031 13598 +1- 1 +-1 1 +.names 13598 13599 +1 1 +.names 13599 13600 +0 1 +.names 13501 13600 13601 +11 1 +.names 13995 13996 13602 +1- 1 +-1 1 +.names 13602 13603 +1 1 +.names 13603 13604 +0 1 +.names 7976 13604 13605 +11 1 +.names 13887 13889 13606 +1- 1 +-1 1 +.names 13606 13607 +1 1 +.names 13607 13608 +0 1 +.names 13501 13608 13609 +11 1 +.names 13898 13900 13610 +1- 1 +-1 1 +.names 13610 13611 +1 1 +.names 13611 13612 +0 1 +.names 7976 13612 13613 +11 1 +.names 14046 14047 13614 +1- 1 +-1 1 +.names 13614 13615 +1 1 +.names 13615 13616 +0 1 +.names 13501 13616 13617 +11 1 +.names 14065 14066 13618 +1- 1 +-1 1 +.names 13618 13619 +1 1 +.names 13619 13620 +0 1 +.names 7976 13620 13621 +11 1 +.names 14014 14016 13622 +1- 1 +-1 1 +.names 13622 13623 +1 1 +.names 13623 13624 +0 1 +.names 13501 13624 13625 +11 1 +.names 13894 13896 13626 +1- 1 +-1 1 +.names 13626 13627 +1 1 +.names 13627 13628 +0 1 +.names 7976 13628 13629 +11 1 +.names 13891 13892 13630 +1- 1 +-1 1 +.names 13630 13631 +1 1 +.names 13631 13632 +0 1 +.names 13501 13632 13633 +11 1 +.names 13970 13972 13634 +1- 1 +-1 1 +.names 13634 13635 +1 1 +.names 13635 13636 +0 1 +.names 7976 13636 13637 +11 1 +.names 14032 14033 13638 +1- 1 +-1 1 +.names 13638 13639 +1 1 +.names 13639 13640 +0 1 +.names 13501 13640 13641 +11 1 +.names 14059 14060 13642 +1- 1 +-1 1 +.names 13642 13643 +1 1 +.names 13643 13644 +0 1 +.names 7976 13644 13645 +11 1 +.names 13906 13907 13646 +1- 1 +-1 1 +.names 13646 13647 +1 1 +.names 13647 13648 +0 1 +.names 13501 13648 13649 +11 1 +.names 14026 14027 13650 +1- 1 +-1 1 +.names 13650 13651 +1 1 +.names 13651 13652 +0 1 +.names 7976 13652 13653 +11 1 +.names 13922 13923 13654 +1- 1 +-1 1 +.names 13654 13655 +1 1 +.names 13655 13656 +0 1 +.names 13501 13656 13657 +11 1 +.names 13958 13960 13658 +1- 1 +-1 1 +.names 13658 13659 +1 1 +.names 13659 13660 +0 1 +.names 7976 13660 13661 +11 1 +.names 13924 13925 13662 +1- 1 +-1 1 +.names 13662 13663 +1 1 +.names 13663 13664 +0 1 +.names 13501 13664 13665 +11 1 +.names 13993 13994 13666 +1- 1 +-1 1 +.names 13666 13667 +1 1 +.names 13667 13668 +0 1 +.names 7976 13668 13669 +11 1 +.names 13501 13670 +1 1 +.names 13670 13671 +0 1 +.names 14038 14039 13672 +1- 1 +-1 1 +.names 13672 13673 +1 1 +.names 13673 13674 +0 1 +.names 13671 13674 13675 +11 1 +.names 14048 14050 13676 +1- 1 +-1 1 +.names 13676 13677 +1 1 +.names 13677 13678 +0 1 +.names 13670 13678 13679 +11 1 +.names 13912 13913 13680 +1- 1 +-1 1 +.names 13680 13681 +1 1 +.names 13681 13682 +0 1 +.names 13671 13682 13683 +11 1 +.names 14001 14002 13684 +1- 1 +-1 1 +.names 13684 13685 +1 1 +.names 13685 13686 +0 1 +.names 13670 13686 13687 +11 1 +.names 13671 13528 13688 +11 1 +.names 13670 13532 13689 +11 1 +.names 13671 13544 13690 +11 1 +.names 13670 13548 13691 +11 1 +.names 13918 13920 13692 +1- 1 +-1 1 +.names 13692 13693 +1 1 +.names 13693 13694 +0 1 +.names 13671 13694 13695 +11 1 +.names 14034 14035 13696 +1- 1 +-1 1 +.names 13696 13697 +1 1 +.names 13697 13698 +0 1 +.names 13670 13698 13699 +11 1 +.names 13671 13552 13700 +11 1 +.names 13670 13556 13701 +11 1 +.names 13671 13656 13702 +11 1 +.names 13670 13660 13703 +11 1 +.names 13864 13865 13704 +1- 1 +-1 1 +.names 13704 13705 +1 1 +.names 13705 13706 +0 1 +.names 13671 13706 13707 +11 1 +.names 14022 14023 13708 +1- 1 +-1 1 +.names 13708 13709 +1 1 +.names 13709 13710 +0 1 +.names 13670 13710 13711 +11 1 +.names 13671 13664 13712 +11 1 +.names 13670 13668 13713 +11 1 +.names 13671 13536 13714 +11 1 +.names 13670 13540 13715 +11 1 +.names 13671 13512 13716 +11 1 +.names 13670 13516 13717 +11 1 +.names 13671 13648 13718 +11 1 +.names 13670 13652 13719 +11 1 +.names 13671 13698 13720 +11 1 +.names 13670 13694 13721 +11 1 +.names 13671 13686 13722 +11 1 +.names 13670 13682 13723 +11 1 +.names 13947 13949 13724 +1- 1 +-1 1 +.names 13724 13725 +1 1 +.names 13725 13726 +0 1 +.names 13671 13726 13727 +11 1 +.names 14057 14058 13728 +1- 1 +-1 1 +.names 13728 13729 +1 1 +.names 13729 13730 +0 1 +.names 13670 13730 13731 +11 1 +.names 14069 14070 13732 +1- 1 +-1 1 +.names 13732 13733 +1 1 +.names 13733 13734 +0 1 +.names 13671 13734 13735 +11 1 +.names 13848 13849 13736 +1- 1 +-1 1 +.names 13736 13737 +1 1 +.names 13737 13738 +0 1 +.names 13670 13738 13739 +11 1 +.names 13671 13504 13740 +11 1 +.names 13670 13508 13741 +11 1 +.names 13909 13910 13742 +1- 1 +-1 1 +.names 13742 13743 +1 1 +.names 13743 13744 +0 1 +.names 13671 13744 13745 +11 1 +.names 13964 13966 13746 +1- 1 +-1 1 +.names 13746 13747 +1 1 +.names 13747 13748 +0 1 +.names 13670 13748 13749 +11 1 +.names 13929 13931 13750 +1- 1 +-1 1 +.names 13750 13751 +1 1 +.names 13751 13752 +0 1 +.names 13671 13752 13753 +11 1 +.names 13851 13852 13754 +1- 1 +-1 1 +.names 13754 13755 +1 1 +.names 13755 13756 +0 1 +.names 13670 13756 13757 +11 1 +.names 13671 13748 13758 +11 1 +.names 13670 13744 13759 +11 1 +.names 13671 13560 13760 +11 1 +.names 13670 13564 13761 +11 1 +.names 13671 13632 13762 +11 1 +.names 13670 13636 13763 +11 1 +.names 14010 14012 13764 +1- 1 +-1 1 +.names 13764 13765 +1 1 +.names 13765 13766 +0 1 +.names 13671 13766 13767 +11 1 +.names 14020 14021 13768 +1- 1 +-1 1 +.names 13768 13769 +1 1 +.names 13769 13770 +0 1 +.names 13670 13770 13771 +11 1 +.names 13671 13678 13772 +11 1 +.names 13670 13674 13773 +11 1 +.names 13988 13990 13774 +1- 1 +-1 1 +.names 13774 13775 +1 1 +.names 13775 13776 +0 1 +.names 13671 13776 13777 +11 1 +.names 13876 13877 13778 +1- 1 +-1 1 +.names 13778 13779 +1 1 +.names 13779 13780 +0 1 +.names 13670 13780 13781 +11 1 +.names 13671 13592 13782 +11 1 +.names 13670 13596 13783 +11 1 +.names 14024 14025 13784 +1- 1 +-1 1 +.names 13784 13785 +1 1 +.names 13785 13786 +0 1 +.names 13671 13786 13787 +11 1 +.names 13870 13871 13788 +1- 1 +-1 1 +.names 13788 13789 +1 1 +.names 13789 13790 +0 1 +.names 13670 13790 13791 +11 1 +.names 13671 13792 +1 1 +.names 13792 13793 +0 1 +.names 13793 13766 13794 +11 1 +.names 13792 13770 13795 +11 1 +.names 13671 13640 13796 +11 1 +.names 13670 13644 13797 +11 1 +.names 13671 13798 +1 1 +.names 13798 13799 +0 1 +.names 13799 13726 13800 +11 1 +.names 13798 13730 13801 +11 1 +.names 13671 13802 +1 1 +.names 13802 13803 +0 1 +.names 13803 13734 13804 +11 1 +.names 13802 13738 13805 +11 1 +.names 13671 13710 13806 +11 1 +.names 13670 13706 13807 +11 1 +.names 13671 13808 +1 1 +.names 13808 13809 +0 1 +.names 13809 13752 13810 +11 1 +.names 13808 13756 13811 +11 1 +.names 13671 13812 +1 1 +.names 13812 13813 +0 1 +.names 13813 13786 13814 +11 1 +.names 13812 13790 13815 +11 1 +.names 13671 13816 +1 1 +.names 13816 13817 +0 1 +.names 13817 13776 13818 +11 1 +.names 13816 13780 13819 +11 1 +.names 13671 13576 13820 +11 1 +.names 13670 13580 13821 +11 1 +.names 13671 13608 13822 +11 1 +.names 13670 13612 13823 +11 1 +.names 13671 13600 13824 +11 1 +.names 13670 13604 13825 +11 1 +.names 13671 13616 13826 +11 1 +.names 13670 13620 13827 +11 1 +.names 13671 13584 13828 +11 1 +.names 13670 13588 13829 +11 1 +.names 13671 13624 13830 +11 1 +.names 13670 13628 13831 +11 1 +.names 13501 13572 13832 +11 1 +.names 7976 13568 13833 +11 1 +.names 13671 13834 +1 1 +.names 13834 13835 +0 1 +.names 13835 13524 13836 +11 1 +.names 13834 13520 13837 +11 1 +.names 7639 13838 +0 1 +.names 12354 13839 +0 1 +.names 13838 13839 13840 +11 1 +.names 12309 13841 +0 1 +.names 7639 13841 13842 +11 1 +.names 12322 13843 +0 1 +.names 13838 13843 13844 +11 1 +.names 12316 13845 +0 1 +.names 7639 13845 13846 +11 1 +.names 12620 13847 +0 1 +.names 13838 13847 13848 +11 1 +.names 7639 13843 13849 +11 1 +.names 12328 13850 +0 1 +.names 13838 13850 13851 +11 1 +.names 7639 13847 13852 +11 1 +.names 12333 13853 +0 1 +.names 13838 13853 13854 +11 1 +.names 12610 13855 +0 1 +.names 7639 13855 13856 +11 1 +.names 12338 13857 +0 1 +.names 13838 13857 13858 +11 1 +.names 7639 13853 13859 +11 1 +.names 12344 13860 +0 1 +.names 13838 13860 13861 +11 1 +.names 7639 13857 13862 +11 1 +.names 12349 13863 +0 1 +.names 13838 13863 13864 +11 1 +.names 7639 13860 13865 +11 1 +.names 12670 13866 +0 1 +.names 13838 13866 13867 +11 1 +.names 7639 13863 13868 +11 1 +.names 12632 13869 +0 1 +.names 13838 13869 13870 +11 1 +.names 7639 13866 13871 +11 1 +.names 12378 13872 +0 1 +.names 13838 13872 13873 +11 1 +.names 7639 13839 13874 +11 1 +.names 12360 13875 +0 1 +.names 13838 13875 13876 +11 1 +.names 7639 13869 13877 +11 1 +.names 12575 13878 +0 1 +.names 13838 13878 13879 +11 1 +.names 12519 13880 +0 1 +.names 7639 13880 13881 +11 1 +.names 12372 13882 +0 1 +.names 13838 13882 13883 +11 1 +.names 12366 13884 +0 1 +.names 7639 13884 13885 +11 1 +.names 12564 13886 +0 1 +.names 13838 13886 13887 +11 1 +.names 12559 13888 +0 1 +.names 7639 13888 13889 +11 1 +.names 12401 13890 +0 1 +.names 13838 13890 13891 +11 1 +.names 7639 13872 13892 +11 1 +.names 12616 13893 +0 1 +.names 13838 13893 13894 +11 1 +.names 12389 13895 +0 1 +.names 7639 13895 13896 +11 1 +.names 12546 13897 +0 1 +.names 13838 13897 13898 +11 1 +.names 12490 13899 +0 1 +.names 7639 13899 13900 +11 1 +.names 12580 13901 +0 1 +.names 13838 13901 13902 +11 1 +.names 12395 13903 +0 1 +.names 7639 13903 13904 +11 1 +.names 12418 13905 +0 1 +.names 13838 13905 13906 +11 1 +.names 7639 13890 13907 +11 1 +.names 12440 13908 +0 1 +.names 13838 13908 13909 +11 1 +.names 7639 13905 13910 +11 1 +.names 12445 13911 +0 1 +.names 13838 13911 13912 +11 1 +.names 7639 13908 13913 +11 1 +.names 13838 12097 13914 +11 1 +.names 12524 13915 +0 1 +.names 7639 13915 13916 +11 1 +.names 12450 13917 +0 1 +.names 13838 13917 13918 +11 1 +.names 12649 13919 +0 1 +.names 7639 13919 13920 +11 1 +.names 12454 13921 +0 1 +.names 13838 13921 13922 +11 1 +.names 7639 13917 13923 +11 1 +.names 13838 13845 13924 +11 1 +.names 7639 13921 13925 +11 1 +.names 13838 13926 +1 1 +.names 13926 13927 +0 1 +.names 12653 13928 +0 1 +.names 13927 13928 13929 +11 1 +.names 12423 13930 +0 1 +.names 13926 13930 13931 +11 1 +.names 13838 13932 +1 1 +.names 13932 13933 +0 1 +.names 12504 13934 +0 1 +.names 13933 13934 13935 +11 1 +.names 12483 13936 +0 1 +.names 13932 13936 13937 +11 1 +.names 13838 13938 +1 1 +.names 13938 13939 +0 1 +.names 12657 13940 +0 1 +.names 13939 13940 13941 +11 1 +.names 12531 13942 +0 1 +.names 13938 13942 13943 +11 1 +.names 13838 13944 +1 1 +.names 13944 13945 +0 1 +.names 12429 13946 +0 1 +.names 13945 13946 13947 +11 1 +.names 12460 13948 +0 1 +.names 13944 13948 13949 +11 1 +.names 13838 13950 +1 1 +.names 13950 13951 +0 1 +.names 13951 13901 13952 +11 1 +.names 12512 13953 +0 1 +.names 13950 13953 13954 +11 1 +.names 13838 13955 +1 1 +.names 13955 13956 +0 1 +.names 12541 13957 +0 1 +.names 13956 13957 13958 +11 1 +.names 12602 13959 +0 1 +.names 13955 13959 13960 +11 1 +.names 13838 13961 +1 1 +.names 13961 13962 +0 1 +.names 12435 13963 +0 1 +.names 13962 13963 13964 +11 1 +.names 12674 13965 +0 1 +.names 13961 13965 13966 +11 1 +.names 13838 13967 +1 1 +.names 13967 13968 +0 1 +.names 12476 13969 +0 1 +.names 13968 13969 13970 +11 1 +.names 12665 13971 +0 1 +.names 13967 13971 13972 +11 1 +.names 13838 13973 +1 1 +.names 13973 13974 +0 1 +.names 12468 13975 +0 1 +.names 13974 13975 13976 +11 1 +.names 12552 13977 +0 1 +.names 13973 13977 13978 +11 1 +.names 13838 13979 +1 1 +.names 13979 13980 +0 1 +.names 12412 13981 +0 1 +.names 13980 13981 13982 +11 1 +.names 12644 13983 +0 1 +.names 13979 13983 13984 +11 1 +.names 13838 13985 +1 1 +.names 13985 13986 +0 1 +.names 12661 13987 +0 1 +.names 13986 13987 13988 +11 1 +.names 12406 13989 +0 1 +.names 13985 13989 13990 +11 1 +.names 13939 13991 +1 1 +.names 13991 13992 +0 1 +.names 13992 13957 13993 +11 1 +.names 13991 13936 13994 +11 1 +.names 13962 13897 13995 +11 1 +.names 13961 13903 13996 +11 1 +.names 13999 13997 +0 1 +.names 13997 13998 +1 1 +.names 13838 13999 +1 1 +.names 13998 14000 +0 1 +.names 14000 13963 14001 +11 1 +.names 13998 13948 14002 +11 1 +.names 12496 14003 +0 1 +.names 13997 14003 14004 +11 1 +.names 12627 14005 +0 1 +.names 13999 14005 14006 +11 1 +.names 13838 14007 +1 1 +.names 14007 14008 +0 1 +.names 12637 14009 +0 1 +.names 14008 14009 14010 +11 1 +.names 12383 14011 +0 1 +.names 14007 14011 14012 +11 1 +.names 12584 14013 +0 1 +.names 13956 14013 14014 +11 1 +.names 12593 14015 +0 1 +.names 13955 14015 14016 +11 1 +.names 14008 13850 14017 +11 1 +.names 14007 13855 14018 +11 1 +.names 12570 14019 +0 1 +.names 13986 14019 14020 +11 1 +.names 13985 14009 14021 +11 1 +.names 14000 13940 14022 +11 1 +.names 13998 13983 14023 +11 1 +.names 13992 13981 14024 +11 1 +.names 13991 13989 14025 +11 1 +.names 13992 13969 14026 +11 1 +.names 13991 13965 14027 +11 1 +.names 13997 14028 +1 1 +.names 14028 14029 +0 1 +.names 14029 13888 14030 +11 1 +.names 14028 13882 14031 +11 1 +.names 13945 14015 14032 +11 1 +.names 13944 14019 14033 +11 1 +.names 13927 13959 14034 +11 1 +.names 13926 13946 14035 +11 1 +.names 13974 14036 +1 1 +.names 14036 14037 +0 1 +.names 14037 13987 14038 +11 1 +.names 14036 14005 14039 +11 1 +.names 13951 14040 +1 1 +.names 14040 14041 +0 1 +.names 14041 13884 14042 +11 1 +.names 14040 13878 14043 +11 1 +.names 14008 14044 +1 1 +.names 14044 14045 +0 1 +.names 14045 14013 14046 +11 1 +.names 14044 13886 14047 +11 1 +.names 13945 13875 14048 +11 1 +.names 12683 14049 +0 1 +.names 13944 14049 14050 +11 1 +.names 14008 14051 +1 1 +.names 14051 14052 +0 1 +.names 14052 13928 14053 +11 1 +.names 14051 13977 14054 +11 1 +.names 13992 13975 14055 +11 1 +.names 13991 13942 14056 +11 1 +.names 13933 13911 14057 +11 1 +.names 13932 13919 14058 +11 1 +.names 13997 14011 14059 +11 1 +.names 13999 13895 14060 +11 1 +.names 13968 14061 +1 1 +.names 14061 14062 +0 1 +.names 14062 14003 14063 +11 1 +.names 14061 13953 14064 +11 1 +.names 13980 13893 14065 +11 1 +.names 13979 13899 14066 +11 1 +.names 14029 13915 14067 +11 1 +.names 14028 13971 14068 +11 1 +.names 14029 13934 14069 +11 1 +.names 14028 13930 14070 +11 1 +.names 14029 13880 14071 +11 1 +.names 14028 14049 14072 +11 1 +.names 7659 14073 +1 1 +.names 14073 14074 +0 1 +.names 13245 14075 +0 1 +.names 14074 14075 14076 +11 1 +.names 13458 14077 +0 1 +.names 14073 14077 14078 +11 1 +.names 7659 14079 +1 1 +.names 14079 14080 +0 1 +.names 13281 14081 +0 1 +.names 14080 14081 14082 +11 1 +.names 13450 14083 +0 1 +.names 14079 14083 14084 +11 1 +.names 13287 14085 +0 1 +.names 14074 14085 14086 +11 1 +.names 13462 14087 +0 1 +.names 14073 14087 14088 +11 1 +.names 13291 14089 +0 1 +.names 14080 14089 14090 +11 1 +.names 13470 14091 +0 1 +.names 14079 14091 14092 +11 1 +.names 13307 14093 +0 1 +.names 14074 14093 14094 +11 1 +.names 13081 14095 +0 1 +.names 14073 14095 14096 +11 1 +.names 7659 14097 +1 1 +.names 14097 14098 +0 1 +.names 13311 14099 +0 1 +.names 14098 14099 14100 +11 1 +.names 13091 14101 +0 1 +.names 14097 14101 14102 +11 1 +.names 13315 14103 +0 1 +.names 14080 14103 14104 +11 1 +.names 13101 14105 +0 1 +.names 14079 14105 14106 +11 1 +.names 13319 14107 +0 1 +.names 14098 14107 14108 +11 1 +.names 13113 14109 +0 1 +.names 14097 14109 14110 +11 1 +.names 13329 14111 +0 1 +.names 14098 14111 14112 +11 1 +.names 13123 14113 +0 1 +.names 14097 14113 14114 +11 1 +.names 13339 14115 +0 1 +.names 14074 14115 14116 +11 1 +.names 13135 14117 +0 1 +.names 14073 14117 14118 +11 1 +.names 13349 14119 +0 1 +.names 14098 14119 14120 +11 1 +.names 13145 14121 +0 1 +.names 14097 14121 14122 +11 1 +.names 13359 14123 +0 1 +.names 14080 14123 14124 +11 1 +.names 13155 14125 +0 1 +.names 14079 14125 14126 +11 1 +.names 13369 14127 +0 1 +.names 14098 14127 14128 +11 1 +.names 13165 14129 +0 1 +.names 14097 14129 14130 +11 1 +.names 13379 14131 +0 1 +.names 14080 14131 14132 +11 1 +.names 13175 14133 +0 1 +.names 14079 14133 14134 +11 1 +.names 13389 14135 +0 1 +.names 14098 14135 14136 +11 1 +.names 13185 14137 +0 1 +.names 14097 14137 14138 +11 1 +.names 13399 14139 +0 1 +.names 14098 14139 14140 +11 1 +.names 13195 14141 +0 1 +.names 14097 14141 14142 +11 1 +.names 13409 14143 +0 1 +.names 14074 14143 14144 +11 1 +.names 13205 14145 +0 1 +.names 14073 14145 14146 +11 1 +.names 13419 14147 +0 1 +.names 14098 14147 14148 +11 1 +.names 13215 14149 +0 1 +.names 14097 14149 14150 +11 1 +.names 13429 14151 +0 1 +.names 14074 14151 14152 +11 1 +.names 13225 14153 +0 1 +.names 14073 14153 14154 +11 1 +.names 13439 14155 +0 1 +.names 14098 14155 14156 +11 1 +.names 13235 14157 +0 1 +.names 14097 14157 14158 +11 1 +.names 14080 11592 14159 +11 1 +.names 14079 14075 14160 +11 1 +.names 14080 11607 14161 +11 1 +.names 13253 14162 +0 1 +.names 14079 14162 14163 +11 1 +.names 14080 11607 14164 +11 1 +.names 13257 14165 +0 1 +.names 14079 14165 14166 +11 1 +.names 14074 11607 14167 +11 1 +.names 13261 14168 +0 1 +.names 14073 14168 14169 +11 1 +.names 14074 11592 14170 +11 1 +.names 13277 14171 +0 1 +.names 14073 14171 14172 +11 1 +.names 14080 11612 14173 +11 1 +.names 13299 14174 +0 1 +.names 14079 14174 14175 +11 1 +.names 14074 11607 14176 +11 1 +.names 13303 14177 +0 1 +.names 14073 14177 14178 +11 1 +.names 14080 11612 14179 +11 1 +.names 14079 14099 14180 +11 1 +.names 14080 14168 14181 +11 1 +.names 13490 14182 +0 1 +.names 14079 14182 14183 +11 1 +.names 14080 11592 14184 +11 1 +.names 14079 14103 14185 +11 1 +.names 14080 11607 14186 +11 1 +.names 14079 14107 14187 +11 1 +.names 14074 11607 14188 +11 1 +.names 14073 14115 14189 +11 1 +.names 14074 8108 14190 +11 1 +.names 14073 14131 14191 +11 1 +.names 14074 11612 14192 +11 1 +.names 14073 14147 14193 +11 1 +.names 14074 11612 14194 +11 1 +.names 14073 14155 14195 +11 1 +.names 13486 14196 +0 1 +.names 14080 14196 14197 +11 1 +.names 13478 14198 +0 1 +.names 14079 14198 14199 +11 1 +.names 14098 14200 +1 1 +.names 14200 14201 +0 1 +.names 14201 14139 14202 +11 1 +.names 14200 11607 14203 +11 1 +.names 14098 14204 +1 1 +.names 14204 14205 +0 1 +.names 14205 14119 14206 +11 1 +.names 14204 11607 14207 +11 1 +.names 14201 14135 14208 +11 1 +.names 14200 11612 14209 +11 1 +.names 13265 14210 +0 1 +.names 14201 14210 14211 +11 1 +.names 14200 11612 14212 +11 1 +.names 14098 14213 +1 1 +.names 14213 14214 +0 1 +.names 13269 14215 +0 1 +.names 14214 14215 14216 +11 1 +.names 14213 8108 14217 +11 1 +.names 13249 14218 +0 1 +.names 14074 14218 14219 +11 1 +.names 13474 14220 +0 1 +.names 14073 14220 14221 +11 1 +.names 14074 14162 14222 +11 1 +.names 13454 14223 +0 1 +.names 14073 14223 14224 +11 1 +.names 13295 14225 +0 1 +.names 14098 14225 14226 +11 1 +.names 13045 14227 +0 1 +.names 14097 14227 14228 +11 1 +.names 14080 14215 14229 +11 1 +.names 13446 14230 +0 1 +.names 14079 14230 14231 +11 1 +.names 14074 14177 14232 +11 1 +.names 13069 14233 +0 1 +.names 14073 14233 14234 +11 1 +.names 14074 14174 14235 +11 1 +.names 13057 14236 +0 1 +.names 14073 14236 14237 +11 1 +.names 14074 14238 +1 1 +.names 14238 14239 +0 1 +.names 14239 14151 14240 +11 1 +.names 14238 8108 14241 +11 1 +.names 14080 14242 +1 1 +.names 14242 14243 +0 1 +.names 14243 14089 14244 +11 1 +.names 14242 11592 14245 +11 1 +.names 14239 14127 14246 +11 1 +.names 14238 11612 14247 +11 1 +.names 14243 14218 14248 +11 1 +.names 14242 8108 14249 +11 1 +.names 14080 14250 +1 1 +.names 14250 14251 +0 1 +.names 14251 14143 14252 +11 1 +.names 14250 11592 14253 +11 1 +.names 14080 14254 +1 1 +.names 14254 14255 +0 1 +.names 14255 14225 14256 +11 1 +.names 14254 8108 14257 +11 1 +.names 13273 14258 +0 1 +.names 14243 14258 14259 +11 1 +.names 14242 11612 14260 +11 1 +.names 14080 14165 14261 +11 1 +.names 13466 14262 +0 1 +.names 14079 14262 14263 +11 1 +.names 14074 14210 14264 +11 1 +.names 13482 14265 +0 1 +.names 14073 14265 14266 +11 1 +.names 14080 14267 +1 1 +.names 14267 14268 +0 1 +.names 14268 14123 14269 +11 1 +.names 14267 11607 14270 +11 1 +.names 14098 14271 +1 1 +.names 14271 14272 +0 1 +.names 14272 14093 14273 +11 1 +.names 14271 11612 14274 +11 1 +.names 14074 14275 +1 1 +.names 14275 14276 +0 1 +.names 14276 14085 14277 +11 1 +.names 14275 11592 14278 +11 1 +.names 14098 14279 +1 1 +.names 14279 14280 +0 1 +.names 14280 14196 14281 +11 1 +.names 14279 11592 14282 +11 1 +.names 14074 14258 14283 +11 1 +.names 13494 14284 +0 1 +.names 14073 14284 14285 +11 1 +.names 14074 14286 +1 1 +.names 14286 14287 +0 1 +.names 14287 14081 14288 +11 1 +.names 14286 8108 14289 +11 1 +.names 14074 14290 +1 1 +.names 14290 14291 +0 1 +.names 14291 14111 14292 +11 1 +.names 14290 11592 14293 +11 1 +.names 14080 14294 +1 1 +.names 14294 14295 +0 1 +.names 13498 14296 +0 1 +.names 14295 14296 14297 +11 1 +.names 14294 14171 14298 +11 1 +.names 2413 14305 14299 +11 1 +.names 14299 14300 +1 1 +.names 14300 14301 +0 1 +.names 14325 14302 +0 1 +.names 14302 14303 +1 1 +.names 14303 14304 +0 1 +.names 8181 14305 +0 1 +.names 14305 14306 +1 1 +.names 14306 14307 +0 1 +.names 14316 14317 14308 +11 1 +.names 14308 14309 +1 1 +.names 14309 14310 +0 1 +.names 14307 14310 14311 +1- 1 +-1 1 +.names 2413 14312 +1 1 +.names 14312 14313 +0 1 +.names 14311 14313 14314 +1- 1 +-1 1 +.names 978 14315 +0 1 +.names 979 14316 +0 1 +.names 980 14317 +0 1 +.names 14317 14318 +1 1 +.names 14318 14319 +0 1 +.names 14319 14320 +1 1 +.names 14305 14321 +1 1 +.names 14321 14322 +0 1 +.names 14320 14323 +0 1 +.names 14322 14323 14324 +1- 1 +-1 1 +.names 14316 14325 +1 1 +.names 14324 14302 14326 +1- 1 +-1 1 +.names 2413 14333 14327 +11 1 +.names 14327 14328 +1 1 +.names 14328 14329 +0 1 +.names 14353 14330 +0 1 +.names 14330 14331 +1 1 +.names 14331 14332 +0 1 +.names 8225 14333 +0 1 +.names 14333 14334 +1 1 +.names 14334 14335 +0 1 +.names 14344 14345 14336 +11 1 +.names 14336 14337 +1 1 +.names 14337 14338 +0 1 +.names 14335 14338 14339 +1- 1 +-1 1 +.names 2413 14340 +1 1 +.names 14340 14341 +0 1 +.names 14339 14341 14342 +1- 1 +-1 1 +.names 981 14343 +0 1 +.names 982 14344 +0 1 +.names 983 14345 +0 1 +.names 14345 14346 +1 1 +.names 14346 14347 +0 1 +.names 14347 14348 +1 1 +.names 14333 14349 +1 1 +.names 14349 14350 +0 1 +.names 14348 14351 +0 1 +.names 14350 14351 14352 +1- 1 +-1 1 +.names 14344 14353 +1 1 +.names 14352 14330 14354 +1- 1 +-1 1 +.names 8244 14355 +1 1 +.names 14355 14356 +0 1 +.names 3618 14357 +0 1 +.names 8314 14358 +0 1 +.names 8305 14358 14359 +1- 1 +-1 1 +.names 14368 14365 14360 +11 1 +.names 14360 14361 +1 1 +.names 14361 14362 +0 1 +.names 14365 14358 14363 +11 1 +.names 14363 14364 +1 1 +.names 8316 14365 +0 1 +.names 14368 14358 14366 +11 1 +.names 14366 14367 +1 1 +.names 8315 14368 +0 1 +.names 14365 8320 14369 +11 1 +.names 14369 14370 +1 1 +.names 14370 14371 +0 1 +.names 8305 8316 14372 +1- 1 +-1 1 +.names 14367 14373 +0 1 +.names 14372 14373 14374 +1- 1 +-1 1 +.names 3915 14375 +0 1 +.names 14378 14368 14376 +11 1 +.names 14376 14377 +1 1 +.names 3912 14378 +0 1 +.names 8320 14375 14379 +11 1 +.names 14379 14380 +1 1 +.names 14380 14381 +0 1 +.names 14377 14382 +0 1 +.names 14381 14382 14383 +1- 1 +-1 1 +.names 14364 14384 +0 1 +.names 14383 14384 14385 +1- 1 +-1 1 +.names 2934 14386 +0 1 +.names 14368 14358 14387 +11 1 +.names 14387 14388 +1 1 +.names 14365 14389 +1 1 +.names 14389 14390 +0 1 +.names 14390 14381 14391 +1- 1 +-1 1 +.names 14388 14392 +0 1 +.names 14391 14392 14393 +1- 1 +-1 1 +.names 2413 14400 14394 +11 1 +.names 14394 14395 +1 1 +.names 14395 14396 +0 1 +.names 14420 14397 +0 1 +.names 14397 14398 +1 1 +.names 14398 14399 +0 1 +.names 8363 14400 +0 1 +.names 14400 14401 +1 1 +.names 14401 14402 +0 1 +.names 14411 14412 14403 +11 1 +.names 14403 14404 +1 1 +.names 14404 14405 +0 1 +.names 14402 14405 14406 +1- 1 +-1 1 +.names 2413 14407 +1 1 +.names 14407 14408 +0 1 +.names 14406 14408 14409 +1- 1 +-1 1 +.names 985 14410 +0 1 +.names 986 14411 +0 1 +.names 987 14412 +0 1 +.names 14412 14413 +1 1 +.names 14413 14414 +0 1 +.names 14414 14415 +1 1 +.names 14400 14416 +1 1 +.names 14416 14417 +0 1 +.names 14415 14418 +0 1 +.names 14417 14418 14419 +1- 1 +-1 1 +.names 14411 14420 +1 1 +.names 14419 14397 14421 +1- 1 +-1 1 +.names 8425 14422 +0 1 +.names 8416 14422 14423 +1- 1 +-1 1 +.names 14432 14429 14424 +11 1 +.names 14424 14425 +1 1 +.names 14425 14426 +0 1 +.names 14429 14422 14427 +11 1 +.names 14427 14428 +1 1 +.names 8427 14429 +0 1 +.names 14432 14422 14430 +11 1 +.names 14430 14431 +1 1 +.names 8426 14432 +0 1 +.names 14429 8431 14433 +11 1 +.names 14433 14434 +1 1 +.names 14434 14435 +0 1 +.names 8416 8427 14436 +1- 1 +-1 1 +.names 14431 14437 +0 1 +.names 14436 14437 14438 +1- 1 +-1 1 +.names 5753 14439 +0 1 +.names 14442 14432 14440 +11 1 +.names 14440 14441 +1 1 +.names 5744 14442 +0 1 +.names 8431 14439 14443 +11 1 +.names 14443 14444 +1 1 +.names 14444 14445 +0 1 +.names 14441 14446 +0 1 +.names 14445 14446 14447 +1- 1 +-1 1 +.names 14428 14448 +0 1 +.names 14447 14448 14449 +1- 1 +-1 1 +.names 14432 14422 14450 +11 1 +.names 14450 14451 +1 1 +.names 14429 14452 +1 1 +.names 14452 14453 +0 1 +.names 14453 14445 14454 +1- 1 +-1 1 +.names 14451 14455 +0 1 +.names 14454 14455 14456 +1- 1 +-1 1 +.names 3669 14457 +0 1 +.names 14457 8450 14458 +11 1 +.names 14458 14459 +1 1 +.names 14459 14460 +0 1 +.names 3673 14461 +0 1 +.names 14465 14462 +0 1 +.names 14462 14463 +1 1 +.names 43193 43196 14464 +11 1 +.names 14464 14465 +1 1 +.names 14469 14466 +0 1 +.names 14466 14467 +1 1 +.names 43675 43676 14468 +11 1 +.names 14468 14469 +1 1 +.names 14473 14470 +0 1 +.names 14470 14471 +1 1 +.names 43675 43676 14472 +1- 1 +-1 1 +.names 14472 14473 +1 1 +.names 14477 14474 +0 1 +.names 14474 14475 +1 1 +.names 43320 43321 14476 +1- 1 +-1 1 +.names 14476 14477 +1 1 +.names 14481 14478 +0 1 +.names 14478 14479 +1 1 +.names 43201 43202 14480 +1- 1 +-1 1 +.names 14480 14481 +1 1 +.names 14485 14482 +0 1 +.names 14482 14483 +1 1 +.names 43010 43011 14484 +1- 1 +-1 1 +.names 14484 14485 +1 1 +.names 14489 14486 +0 1 +.names 14486 14487 +1 1 +.names 42562 42563 14488 +1- 1 +-1 1 +.names 14488 14489 +1 1 +.names 14493 14490 +0 1 +.names 14490 14491 +1 1 +.names 43504 43505 14492 +1- 1 +-1 1 +.names 14492 14493 +1 1 +.names 14497 14494 +0 1 +.names 14494 14495 +1 1 +.names 43090 43091 14496 +1- 1 +-1 1 +.names 14496 14497 +1 1 +.names 14501 14498 +0 1 +.names 14498 14499 +1 1 +.names 43318 43319 14500 +11 1 +.names 14500 14501 +1 1 +.names 14505 14502 +0 1 +.names 14502 14503 +1 1 +.names 42940 42941 14504 +11 1 +.names 14504 14505 +1 1 +.names 14509 14506 +0 1 +.names 14506 14507 +1 1 +.names 43318 43319 14508 +1- 1 +-1 1 +.names 14508 14509 +1 1 +.names 14513 14510 +0 1 +.names 14510 14511 +1 1 +.names 42940 42941 14512 +1- 1 +-1 1 +.names 14512 14513 +1 1 +.names 14517 14514 +0 1 +.names 14514 14515 +1 1 +.names 42786 42787 14516 +1- 1 +-1 1 +.names 14516 14517 +1 1 +.names 14521 14518 +0 1 +.names 14518 14519 +1 1 +.names 42938 42939 14520 +11 1 +.names 14520 14521 +1 1 +.names 14525 14522 +0 1 +.names 14522 14523 +1 1 +.names 43088 43089 14524 +1- 1 +-1 1 +.names 14524 14525 +1 1 +.names 14529 14526 +0 1 +.names 14526 14527 +1 1 +.names 43502 43503 14528 +1- 1 +-1 1 +.names 14528 14529 +1 1 +.names 14533 14530 +0 1 +.names 14530 14531 +1 1 +.names 42993 42994 14532 +11 1 +.names 14532 14533 +1 1 +.names 14537 14534 +0 1 +.names 14534 14535 +1 1 +.names 43499 43500 14536 +11 1 +.names 14536 14537 +1 1 +.names 14541 14538 +0 1 +.names 14538 14539 +1 1 +.names 42564 42565 14540 +11 1 +.names 14540 14541 +1 1 +.names 14545 14542 +0 1 +.names 14542 14543 +1 1 +.names 43677 43678 14544 +1- 1 +-1 1 +.names 14544 14545 +1 1 +.names 14549 14546 +0 1 +.names 14546 14547 +1 1 +.names 43012 43013 14548 +1- 1 +-1 1 +.names 14548 14549 +1 1 +.names 14553 14550 +0 1 +.names 14550 14551 +1 1 +.names 42942 42943 14552 +11 1 +.names 14552 14553 +1 1 +.names 14557 14554 +0 1 +.names 14554 14555 +1 1 +.names 43210 43211 14556 +1- 1 +-1 1 +.names 14556 14557 +1 1 +.names 14561 14558 +0 1 +.names 14558 14559 +1 1 +.names 43506 43507 14560 +1- 1 +-1 1 +.names 14560 14561 +1 1 +.names 14566 14569 14562 +11 1 +.names 14562 14563 +1 1 +.names 14749 14564 +0 1 +.names 14564 14565 +1 1 +.names 14565 14566 +0 1 +.names 14747 14567 +0 1 +.names 14567 14568 +1 1 +.names 14568 14569 +0 1 +.names 14573 14570 +0 1 +.names 14570 14571 +1 1 +.names 43084 43087 14572 +11 1 +.names 14572 14573 +1 1 +.names 3663 14574 +1 1 +.names 14578 14575 +0 1 +.names 14575 14576 +1 1 +.names 43012 43013 14577 +11 1 +.names 14577 14578 +1 1 +.names 14582 14579 +0 1 +.names 14579 14580 +1 1 +.names 42807 14581 +0 1 +.names 14581 14582 +1 1 +.names 14586 14583 +0 1 +.names 14583 14584 +1 1 +.names 43501 42495 14585 +11 1 +.names 14585 14586 +1 1 +.names 14590 14587 +0 1 +.names 14587 14588 +1 1 +.names 43010 43011 14589 +11 1 +.names 14589 14590 +1 1 +.names 14594 14591 +0 1 +.names 14591 14592 +1 1 +.names 43499 43500 14593 +1- 1 +-1 1 +.names 14593 14594 +1 1 +.names 14598 14595 +0 1 +.names 14595 14596 +1 1 +.names 42489 42490 14597 +11 1 +.names 14597 14598 +1 1 +.names 14571 14599 +0 1 +.names 14599 14600 +1 1 +.names 14604 14601 +0 1 +.names 14601 14602 +1 1 +.names 43197 43198 14603 +11 1 +.names 14603 14604 +1 1 +.names 14608 14605 +0 1 +.names 14605 14606 +1 1 +.names 42790 42791 14607 +11 1 +.names 14607 14608 +1 1 +.names 14612 14609 +0 1 +.names 14609 14610 +1 1 +.names 43199 43200 14611 +11 1 +.names 14611 14612 +1 1 +.names 14616 14613 +0 1 +.names 14613 14614 +1 1 +.names 43506 43507 14615 +11 1 +.names 14615 14616 +1 1 +.names 14620 14617 +0 1 +.names 14617 14618 +1 1 +.names 42792 42793 14619 +11 1 +.names 14619 14620 +1 1 +.names 14563 14621 +1 1 +.names 14625 14622 +0 1 +.names 14622 14623 +1 1 +.names 14567 14564 14624 +11 1 +.names 14624 14625 +1 1 +.names 14629 14626 +0 1 +.names 14626 14627 +1 1 +.names 42560 42561 14628 +11 1 +.names 14628 14629 +1 1 +.names 14633 14630 +0 1 +.names 14630 14631 +1 1 +.names 43088 43089 14632 +11 1 +.names 14632 14633 +1 1 +.names 14637 14634 +0 1 +.names 14634 14635 +1 1 +.names 42560 42561 14636 +1- 1 +-1 1 +.names 14636 14637 +1 1 +.names 14641 14638 +0 1 +.names 14638 14639 +1 1 +.names 42938 42939 14640 +1- 1 +-1 1 +.names 14640 14641 +1 1 +.names 14645 14642 +0 1 +.names 14642 14643 +1 1 +.names 43502 43503 14644 +11 1 +.names 14644 14645 +1 1 +.names 14649 14646 +0 1 +.names 14646 14647 +1 1 +.names 43242 43243 14648 +11 1 +.names 14648 14649 +1 1 +.names 14653 14650 +0 1 +.names 14650 14651 +1 1 +.names 43242 43243 14652 +1- 1 +-1 1 +.names 14652 14653 +1 1 +.names 14657 14654 +0 1 +.names 14654 14655 +1 1 +.names 42786 42787 14656 +11 1 +.names 14656 14657 +1 1 +.names 14661 14658 +0 1 +.names 14658 14659 +1 1 +.names 14743 14660 +0 1 +.names 14660 14661 +1 1 +.names 14665 14662 +0 1 +.names 14662 14663 +1 1 +.names 42999 43000 14664 +1- 1 +-1 1 +.names 14664 14665 +1 1 +.names 14669 14666 +0 1 +.names 14666 14667 +1 1 +.names 42489 42490 14668 +1- 1 +-1 1 +.names 14668 14669 +1 1 +.names 14673 14670 +0 1 +.names 14670 14671 +1 1 +.names 43001 43002 14672 +11 1 +.names 14672 14673 +1 1 +.names 14677 14674 +0 1 +.names 14674 14675 +1 1 +.names 43090 43091 14676 +11 1 +.names 14676 14677 +1 1 +.names 14681 14678 +0 1 +.names 14678 14679 +1 1 +.names 42788 42789 14680 +1- 1 +-1 1 +.names 14680 14681 +1 1 +.names 14685 14682 +0 1 +.names 14682 14683 +1 1 +.names 43001 43002 14684 +1- 1 +-1 1 +.names 14684 14685 +1 1 +.names 14689 14686 +0 1 +.names 14686 14687 +1 1 +.names 42562 42563 14688 +11 1 +.names 14688 14689 +1 1 +.names 14693 14690 +0 1 +.names 14690 14691 +1 1 +.names 43197 43198 14692 +1- 1 +-1 1 +.names 14692 14693 +1 1 +.names 14697 14694 +0 1 +.names 14694 14695 +1 1 +.names 43201 43202 14696 +11 1 +.names 14696 14697 +1 1 +.names 14701 14698 +0 1 +.names 14698 14699 +1 1 +.names 42942 42943 14700 +1- 1 +-1 1 +.names 14700 14701 +1 1 +.names 14705 14702 +0 1 +.names 14702 14703 +1 1 +.names 43210 43211 14704 +11 1 +.names 14704 14705 +1 1 +.names 14709 14706 +0 1 +.names 14706 14707 +1 1 +.names 42790 42791 14708 +1- 1 +-1 1 +.names 14708 14709 +1 1 +.names 14713 14710 +0 1 +.names 14710 14711 +1 1 +.names 43199 43200 14712 +1- 1 +-1 1 +.names 14712 14713 +1 1 +.names 14717 14714 +0 1 +.names 14714 14715 +1 1 +.names 42993 42994 14716 +1- 1 +-1 1 +.names 14716 14717 +1 1 +.names 14721 14718 +0 1 +.names 14718 14719 +1 1 +.names 42564 42565 14720 +1- 1 +-1 1 +.names 14720 14721 +1 1 +.names 14725 14722 +0 1 +.names 14722 14723 +1 1 +.names 42792 42793 14724 +1- 1 +-1 1 +.names 14724 14725 +1 1 +.names 14729 14726 +0 1 +.names 14726 14727 +1 1 +.names 43677 43678 14728 +11 1 +.names 14728 14729 +1 1 +.names 14733 14730 +0 1 +.names 14730 14731 +1 1 +.names 42788 42789 14732 +11 1 +.names 14732 14733 +1 1 +.names 14737 14734 +0 1 +.names 14734 14735 +1 1 +.names 42999 43000 14736 +11 1 +.names 14736 14737 +1 1 +.names 14741 14738 +0 1 +.names 14738 14739 +1 1 +.names 43320 43321 14740 +11 1 +.names 14740 14741 +1 1 +.names 14745 14742 +0 1 +.names 14742 14743 +1 1 +.names 43504 43505 14744 +11 1 +.names 14744 14745 +1 1 +.names 40959 40987 14746 +1- 1 +-1 1 +.names 14746 14747 +1 1 +.names 42147 42148 14748 +1- 1 +-1 1 +.names 14748 14749 +1 1 +.names 8460 14750 +1 1 +.names 14750 14751 +0 1 +.names 8523 14752 +1 1 +.names 14752 14753 +0 1 +.names 990 14754 +0 1 +.names 6491 14755 +0 1 +.names 14755 14756 +1 1 +.names 14756 14757 +0 1 +.names 6485 14758 +0 1 +.names 14757 14759 +1 1 +.names 56730 14760 +0 1 +.names 14760 14761 +1 1 +.names 27599 27603 56730 +1- 1 +-1 1 +.names 14765 14766 14763 +11 1 +.names 14763 14764 +1 1 +.names 9446 14765 +0 1 +.names 14761 14766 +0 1 +.names 14771 14772 14767 +1- 1 +-1 1 +.names 14767 14768 +1 1 +.names 9442 14769 +0 1 +.names 14764 14770 +0 1 +.names 14769 14770 14771 +11 1 +.names 9442 2413 14772 +11 1 +.names 14765 14773 +1 1 +.names 2413 14774 +1 1 +.names 14778 14779 57137 +1- 1 +-1 1 +.names 14774 14776 +0 1 +.names 14773 14777 +0 1 +.names 14776 14777 14778 +11 1 +.names 14768 14779 +0 1 +.names 14785 14788 57138 +1- 1 +-1 1 +.names 9458 14781 +0 1 +.names 56721 14782 +0 1 +.names 14782 14783 +1 1 +.names 14783 14784 +0 1 +.names 14781 14784 14785 +11 1 +.names 2413 14786 +1 1 +.names 14786 14787 +0 1 +.names 9458 14787 14788 +11 1 +.names 27468 27472 56721 +1- 1 +-1 1 +.names 14795 14798 57139 +1- 1 +-1 1 +.names 9462 14791 +0 1 +.names 56714 14792 +0 1 +.names 14792 14793 +1 1 +.names 14793 14794 +0 1 +.names 14791 14794 14795 +11 1 +.names 2413 14796 +1 1 +.names 14796 14797 +0 1 +.names 9462 14797 14798 +11 1 +.names 27670 27674 56714 +1- 1 +-1 1 +.names 14805 14808 57140 +1- 1 +-1 1 +.names 9466 14801 +0 1 +.names 56712 14802 +0 1 +.names 14802 14803 +1 1 +.names 14803 14804 +0 1 +.names 14801 14804 14805 +11 1 +.names 2413 14806 +1 1 +.names 14806 14807 +0 1 +.names 9466 14807 14808 +11 1 +.names 27614 27618 56712 +1- 1 +-1 1 +.names 14815 14818 57141 +1- 1 +-1 1 +.names 9470 14811 +0 1 +.names 56711 14812 +0 1 +.names 14812 14813 +1 1 +.names 14813 14814 +0 1 +.names 14811 14814 14815 +11 1 +.names 2413 14816 +1 1 +.names 14816 14817 +0 1 +.names 9470 14817 14818 +11 1 +.names 27635 27639 56711 +1- 1 +-1 1 +.names 14825 14828 57142 +1- 1 +-1 1 +.names 9474 14821 +0 1 +.names 56710 14822 +0 1 +.names 14822 14823 +1 1 +.names 14823 14824 +0 1 +.names 14821 14824 14825 +11 1 +.names 2413 14826 +1 1 +.names 14826 14827 +0 1 +.names 9474 14827 14828 +11 1 +.names 27543 27547 56710 +1- 1 +-1 1 +.names 14835 14838 57143 +1- 1 +-1 1 +.names 9478 14831 +0 1 +.names 56709 14832 +0 1 +.names 14832 14833 +1 1 +.names 14833 14834 +0 1 +.names 14831 14834 14835 +11 1 +.names 2413 14836 +1 1 +.names 14836 14837 +0 1 +.names 9478 14837 14838 +11 1 +.names 27514 27518 56709 +1- 1 +-1 1 +.names 14845 14848 57144 +1- 1 +-1 1 +.names 9482 14841 +0 1 +.names 56708 14842 +0 1 +.names 14842 14843 +1 1 +.names 14843 14844 +0 1 +.names 14841 14844 14845 +11 1 +.names 2413 14846 +1 1 +.names 14846 14847 +0 1 +.names 9482 14847 14848 +11 1 +.names 27528 27532 56708 +1- 1 +-1 1 +.names 14855 14858 57145 +1- 1 +-1 1 +.names 9486 14851 +0 1 +.names 56707 14852 +0 1 +.names 14852 14853 +1 1 +.names 14853 14854 +0 1 +.names 14851 14854 14855 +11 1 +.names 2413 14856 +1 1 +.names 14856 14857 +0 1 +.names 9486 14857 14858 +11 1 +.names 27507 27511 56707 +1- 1 +-1 1 +.names 14865 14868 57146 +1- 1 +-1 1 +.names 9490 14861 +0 1 +.names 56706 14862 +0 1 +.names 14862 14863 +1 1 +.names 14863 14864 +0 1 +.names 14861 14864 14865 +11 1 +.names 2413 14866 +1 1 +.names 14866 14867 +0 1 +.names 9490 14867 14868 +11 1 +.names 27571 27575 56706 +1- 1 +-1 1 +.names 14875 14878 57147 +1- 1 +-1 1 +.names 9494 14871 +0 1 +.names 56705 14872 +0 1 +.names 14872 14873 +1 1 +.names 14873 14874 +0 1 +.names 14871 14874 14875 +11 1 +.names 2413 14876 +1 1 +.names 14876 14877 +0 1 +.names 9494 14877 14878 +11 1 +.names 27460 27464 56705 +1- 1 +-1 1 +.names 14885 14889 57148 +1- 1 +-1 1 +.names 9498 14881 +0 1 +.names 56704 14882 +0 1 +.names 14882 14883 +1 1 +.names 14883 14884 +0 1 +.names 14881 14884 14885 +11 1 +.names 1775 14886 +0 1 +.names 14886 14887 +1 1 +.names 14887 14888 +0 1 +.names 9498 14888 14889 +11 1 +.names 27564 27568 56704 +1- 1 +-1 1 +.names 14896 14899 57149 +1- 1 +-1 1 +.names 9502 14892 +0 1 +.names 56703 14893 +0 1 +.names 14893 14894 +1 1 +.names 14894 14895 +0 1 +.names 14892 14895 14896 +11 1 +.names 2413 14897 +1 1 +.names 14897 14898 +0 1 +.names 9502 14898 14899 +11 1 +.names 27663 27667 56703 +1- 1 +-1 1 +.names 14905 14908 57150 +1- 1 +-1 1 +.names 9518 14902 +0 1 +.names 14760 14903 +1 1 +.names 14903 14904 +0 1 +.names 14902 14904 14905 +11 1 +.names 2413 14906 +1 1 +.names 14906 14907 +0 1 +.names 9518 14907 14908 +11 1 +.names 14913 14916 57151 +1- 1 +-1 1 +.names 9534 14910 +0 1 +.names 14822 14911 +1 1 +.names 14911 14912 +0 1 +.names 14910 14912 14913 +11 1 +.names 2413 14914 +1 1 +.names 14914 14915 +0 1 +.names 9534 14915 14916 +11 1 +.names 14921 14924 57152 +1- 1 +-1 1 +.names 9543 14918 +0 1 +.names 14852 14919 +1 1 +.names 14919 14920 +0 1 +.names 14918 14920 14921 +11 1 +.names 2413 14922 +1 1 +.names 14922 14923 +0 1 +.names 9543 14923 14924 +11 1 +.names 14930 14933 57153 +1- 1 +-1 1 +.names 9547 14926 +0 1 +.names 56702 14927 +0 1 +.names 14927 14928 +1 1 +.names 14928 14929 +0 1 +.names 14926 14929 14930 +11 1 +.names 2413 14931 +1 1 +.names 14931 14932 +0 1 +.names 9547 14932 14933 +11 1 +.names 27656 27660 56702 +1- 1 +-1 1 +.names 14940 14943 57154 +1- 1 +-1 1 +.names 9556 14936 +0 1 +.names 56699 14937 +0 1 +.names 14937 14938 +1 1 +.names 14938 14939 +0 1 +.names 14936 14939 14940 +11 1 +.names 2413 14941 +1 1 +.names 14941 14942 +0 1 +.names 9556 14942 14943 +11 1 +.names 27491 27495 56699 +1- 1 +-1 1 +.names 9562 14945 +1 1 +.names 14945 14946 +0 1 +.names 6435 14947 +0 1 +.names 14951 14948 +0 1 +.names 14948 14949 +1 1 +.names 1538 47772 14950 +1- 1 +-1 1 +.names 14950 14951 +1 1 +.names 14955 14952 +0 1 +.names 14952 14953 +1 1 +.names 47775 47776 14954 +1- 1 +-1 1 +.names 14954 14955 +1 1 +.names 14953 14956 +1 1 +.names 14953 14957 +1 1 +.names 14953 14958 +1 1 +.names 14949 14959 +1 1 +.names 14949 14960 +1 1 +.names 14949 14961 +1 1 +.names 14965 14962 +0 1 +.names 14962 14963 +1 1 +.names 1538 14964 +0 1 +.names 14964 14965 +1 1 +.names 14963 14966 +1 1 +.names 14953 14967 +1 1 +.names 14963 14968 +1 1 +.names 14963 14969 +1 1 +.names 14963 14970 +1 1 +.names 14974 14971 +0 1 +.names 14971 14972 +1 1 +.names 955 47777 14973 +1- 1 +-1 1 +.names 14973 14974 +1 1 +.names 14978 14975 +0 1 +.names 14975 14976 +1 1 +.names 47780 47781 14977 +1- 1 +-1 1 +.names 14977 14978 +1 1 +.names 14976 14979 +1 1 +.names 14976 14980 +1 1 +.names 14976 14981 +1 1 +.names 14972 14982 +1 1 +.names 14972 14983 +1 1 +.names 14972 14984 +1 1 +.names 14988 14985 +0 1 +.names 14985 14986 +1 1 +.names 955 14987 +0 1 +.names 14987 14988 +1 1 +.names 14986 14989 +1 1 +.names 14976 14990 +1 1 +.names 14986 14991 +1 1 +.names 14986 14992 +1 1 +.names 14986 14993 +1 1 +.names 14997 14994 +0 1 +.names 14994 14995 +1 1 +.names 951 47782 14996 +1- 1 +-1 1 +.names 14996 14997 +1 1 +.names 15001 14998 +0 1 +.names 14998 14999 +1 1 +.names 47785 47786 15000 +1- 1 +-1 1 +.names 15000 15001 +1 1 +.names 14999 15002 +1 1 +.names 14999 15003 +1 1 +.names 14999 15004 +1 1 +.names 14995 15005 +1 1 +.names 14995 15006 +1 1 +.names 14995 15007 +1 1 +.names 15011 15008 +0 1 +.names 15008 15009 +1 1 +.names 951 15010 +0 1 +.names 15010 15011 +1 1 +.names 15009 15012 +1 1 +.names 14999 15013 +1 1 +.names 15009 15014 +1 1 +.names 15009 15015 +1 1 +.names 15009 15016 +1 1 +.names 15020 15017 +0 1 +.names 15017 15018 +1 1 +.names 947 47787 15019 +1- 1 +-1 1 +.names 15019 15020 +1 1 +.names 15024 15021 +0 1 +.names 15021 15022 +1 1 +.names 47790 47791 15023 +1- 1 +-1 1 +.names 15023 15024 +1 1 +.names 15022 15025 +1 1 +.names 15022 15026 +1 1 +.names 15022 15027 +1 1 +.names 15018 15028 +1 1 +.names 15018 15029 +1 1 +.names 15018 15030 +1 1 +.names 15034 15031 +0 1 +.names 15031 15032 +1 1 +.names 947 15033 +0 1 +.names 15033 15034 +1 1 +.names 15032 15035 +1 1 +.names 15022 15036 +1 1 +.names 15032 15037 +1 1 +.names 15032 15038 +1 1 +.names 15032 15039 +1 1 +.names 15042 15040 +1 1 +.names 15040 15041 +1 1 +.names 15044 15042 +1 1 +.names 15040 15043 +1 1 +.names 15046 15044 +0 1 +.names 47794 47797 15045 +1- 1 +-1 1 +.names 15045 15046 +1 1 +.names 15050 15047 +0 1 +.names 15047 15048 +1 1 +.names 1783 47798 15049 +1- 1 +-1 1 +.names 15049 15050 +1 1 +.names 15048 15051 +1 1 +.names 15048 15052 +1 1 +.names 15048 15053 +1 1 +.names 15056 15054 +1 1 +.names 15054 15055 +1 1 +.names 15076 15056 +0 1 +.names 15056 15057 +1 1 +.names 15057 15058 +1 1 +.names 15062 15059 +0 1 +.names 15059 15060 +1 1 +.names 15074 15061 +0 1 +.names 15061 15062 +1 1 +.names 15066 15063 +0 1 +.names 15063 15064 +1 1 +.names 47807 47808 15065 +1- 1 +-1 1 +.names 15065 15066 +1 1 +.names 15070 15067 +0 1 +.names 15067 15068 +1 1 +.names 15055 15069 +0 1 +.names 15069 15070 +1 1 +.names 15063 15071 +1 1 +.names 15042 15072 +1 1 +.names 15048 15073 +1 1 +.names 15071 15074 +1 1 +.names 47819 47806 15075 +1- 1 +-1 1 +.names 15075 15076 +1 1 +.names 15057 15077 +1 1 +.names 15057 15078 +1 1 +.names 15042 15079 +1 1 +.names 942 15080 +1 1 +.names 15064 15081 +1 1 +.names 15064 15082 +1 1 +.names 15064 15083 +1 1 +.names 15086 15084 +1 1 +.names 15084 15085 +1 1 +.names 15088 15086 +1 1 +.names 15084 15087 +1 1 +.names 15090 15088 +0 1 +.names 47822 47825 15089 +1- 1 +-1 1 +.names 15089 15090 +1 1 +.names 15094 15091 +0 1 +.names 15091 15092 +1 1 +.names 1783 47826 15093 +1- 1 +-1 1 +.names 15093 15094 +1 1 +.names 15092 15095 +1 1 +.names 15092 15096 +1 1 +.names 15092 15097 +1 1 +.names 15100 15098 +1 1 +.names 15098 15099 +1 1 +.names 15120 15100 +0 1 +.names 15100 15101 +1 1 +.names 15101 15102 +1 1 +.names 15106 15103 +0 1 +.names 15103 15104 +1 1 +.names 15118 15105 +0 1 +.names 15105 15106 +1 1 +.names 15110 15107 +0 1 +.names 15107 15108 +1 1 +.names 47835 47836 15109 +1- 1 +-1 1 +.names 15109 15110 +1 1 +.names 15114 15111 +0 1 +.names 15111 15112 +1 1 +.names 15099 15113 +0 1 +.names 15113 15114 +1 1 +.names 15107 15115 +1 1 +.names 15086 15116 +1 1 +.names 15092 15117 +1 1 +.names 15115 15118 +1 1 +.names 47847 47834 15119 +1- 1 +-1 1 +.names 15119 15120 +1 1 +.names 15101 15121 +1 1 +.names 15101 15122 +1 1 +.names 15086 15123 +1 1 +.names 9583 15124 +1 1 +.names 15108 15125 +1 1 +.names 15108 15126 +1 1 +.names 15108 15127 +1 1 +.names 2413 15155 15128 +11 1 +.names 15128 15129 +1 1 +.names 15129 15130 +0 1 +.names 9646 15130 15131 +1- 1 +-1 1 +.names 15149 15156 15132 +11 1 +.names 15132 15133 +1 1 +.names 15133 15134 +0 1 +.names 15131 15134 15135 +1- 1 +-1 1 +.names 992 15136 +0 1 +.names 15155 2413 15137 +11 1 +.names 15137 15138 +1 1 +.names 15138 15139 +0 1 +.names 15136 15149 15140 +11 1 +.names 15140 15141 +1 1 +.names 15141 15142 +0 1 +.names 15139 15142 15143 +1- 1 +-1 1 +.names 15156 15150 15144 +11 1 +.names 15144 15145 +1 1 +.names 15145 15146 +0 1 +.names 15143 15146 15147 +1- 1 +-1 1 +.names 993 15148 +0 1 +.names 9639 15149 +0 1 +.names 9646 15150 +0 1 +.names 2413 15151 +1 1 +.names 15151 15152 +0 1 +.names 994 15153 +1 1 +.names 15153 15154 +0 1 +.names 994 15155 +0 1 +.names 995 15156 +0 1 +.names 15150 15155 15157 +11 1 +.names 15157 15158 +1 1 +.names 15158 15159 +0 1 +.names 1783 15159 15160 +1- 1 +-1 1 +.names 15164 15149 15161 +11 1 +.names 15161 15162 +1 1 +.names 15156 15163 +1 1 +.names 15163 15164 +0 1 +.names 1783 15159 15165 +1- 1 +-1 1 +.names 15162 15166 +0 1 +.names 15169 15170 15167 +1- 1 +-1 1 +.names 15167 15168 +1 1 +.names 996 15169 +0 1 +.names 997 15170 +0 1 +.names 15174 15171 +0 1 +.names 15171 15172 +1 1 +.names 15195 15173 +0 1 +.names 15173 15174 +1 1 +.names 15183 15187 15175 +1- 1 +-1 1 +.names 15175 15176 +1 1 +.names 15460 15739 15177 +11 1 +.names 15177 15178 +1 1 +.names 15178 15179 +0 1 +.names 15462 15466 15180 +1- 1 +-1 1 +.names 15180 15181 +1 1 +.names 15181 15182 +0 1 +.names 15179 15182 15183 +11 1 +.names 15481 15184 +0 1 +.names 15184 15185 +1 1 +.names 15185 15186 +0 1 +.names 15178 15186 15187 +11 1 +.names 15191 15188 +0 1 +.names 15188 15189 +1 1 +.names 15612 15615 15190 +1- 1 +-1 1 +.names 15190 15191 +1 1 +.names 15194 15192 +0 1 +.names 15192 15193 +1 1 +.names 999 998 15194 +01 1 +10 1 +.names 1001 1000 15195 +01 1 +10 1 +.names 15198 15196 +0 1 +.names 15196 15197 +1 1 +.names 1003 1002 15198 +01 1 +10 1 +.names 15201 15199 +0 1 +.names 15199 15200 +1 1 +.names 1005 1004 15201 +01 1 +10 1 +.names 15210 15213 15202 +1- 1 +-1 1 +.names 15202 15203 +1 1 +.names 15666 15668 15204 +11 1 +.names 15204 15205 +1 1 +.names 15205 15206 +0 1 +.names 15543 15280 15207 +11 1 +.names 15207 15208 +1 1 +.names 15208 15209 +0 1 +.names 15206 15209 15210 +11 1 +.names 15607 15211 +0 1 +.names 15211 15212 +1 1 +.names 15212 15213 +0 1 +.names 15217 15214 +0 1 +.names 15214 15215 +1 1 +.names 15298 15301 15216 +1- 1 +-1 1 +.names 15216 15217 +1 1 +.names 15224 15227 15218 +11 1 +.names 15218 15219 +1 1 +.names 15369 15370 15220 +1- 1 +-1 1 +.names 15220 15221 +1 1 +.names 15221 15222 +0 1 +.names 15215 15223 +0 1 +.names 15222 15223 15224 +1- 1 +-1 1 +.names 15228 15229 15225 +1- 1 +-1 1 +.names 15225 15226 +1 1 +.names 15226 15227 +0 1 +.names 15203 15228 +0 1 +.names 15189 15229 +0 1 +.names 15238 15229 15230 +1- 1 +-1 1 +.names 15230 15231 +1 1 +.names 15269 15232 +0 1 +.names 15232 15233 +1 1 +.names 15233 15234 +0 1 +.names 15265 15267 15235 +1- 1 +-1 1 +.names 15235 15236 +1 1 +.names 15236 15237 +0 1 +.names 15234 15237 15238 +11 1 +.names 15223 15243 15239 +1- 1 +-1 1 +.names 15239 15240 +1 1 +.names 1008 1007 15241 +01 1 +10 1 +.names 15241 15242 +1 1 +.names 15242 15243 +0 1 +.names 15248 15251 15244 +11 1 +.names 15244 15245 +1 1 +.names 15256 15260 15246 +1- 1 +-1 1 +.names 15246 15247 +1 1 +.names 15247 15248 +0 1 +.names 15427 15475 15249 +11 1 +.names 15249 15250 +1 1 +.names 15250 15251 +0 1 +.names 15172 15252 +0 1 +.names 15486 15487 15253 +1- 1 +-1 1 +.names 15253 15254 +1 1 +.names 15254 15255 +0 1 +.names 15252 15255 15256 +11 1 +.names 15489 15427 15257 +1- 1 +-1 1 +.names 15257 15258 +1 1 +.names 15258 15259 +0 1 +.names 15172 15259 15260 +11 1 +.names 15193 15261 +0 1 +.names 15261 15262 +1 1 +.names 15262 15263 +0 1 +.names 1006 15264 +0 1 +.names 15263 15264 15265 +11 1 +.names 998 15266 +0 1 +.names 15262 15266 15267 +11 1 +.names 15271 15261 15268 +1- 1 +-1 1 +.names 15268 15269 +1 1 +.names 1027 1006 15270 +01 1 +10 1 +.names 15270 15271 +1 1 +.names 15275 15278 15272 +1- 1 +-1 1 +.names 15272 15273 +1 1 +.names 1008 1007 15274 +01 1 +10 1 +.names 15274 15275 +1 1 +.names 15468 15470 15276 +11 1 +.names 15276 15277 +1 1 +.names 15277 15278 +0 1 +.names 15286 15289 15279 +1- 1 +-1 1 +.names 15279 15280 +1 1 +.names 15574 15281 +0 1 +.names 15281 15282 +1 1 +.names 15541 1783 15283 +01 1 +10 1 +.names 15283 15284 +1 1 +.names 15284 15285 +0 1 +.names 15282 15285 15286 +1- 1 +-1 1 +.names 15648 15579 15287 +11 1 +.names 15287 15288 +1 1 +.names 15288 15289 +0 1 +.names 15564 15552 15290 +1- 1 +-1 1 +.names 15290 15291 +1 1 +.names 15588 15292 +0 1 +.names 15292 15293 +1 1 +.names 15291 15293 15294 +1- 1 +-1 1 +.names 15540 1783 15295 +01 1 +10 1 +.names 15295 15296 +1 1 +.names 15296 15297 +0 1 +.names 15294 15297 15298 +1- 1 +-1 1 +.names 15591 15299 +0 1 +.names 15299 15300 +1 1 +.names 15300 15301 +0 1 +.names 15309 15312 15302 +1- 1 +-1 1 +.names 15302 15303 +1 1 +.names 15326 15304 +0 1 +.names 15304 15305 +1 1 +.names 15394 15397 15306 +11 1 +.names 15306 15307 +1 1 +.names 15307 15308 +0 1 +.names 15305 15308 15309 +1- 1 +-1 1 +.names 15200 15399 15310 +11 1 +.names 15310 15311 +1 1 +.names 15311 15312 +0 1 +.names 15321 15324 15313 +1- 1 +-1 1 +.names 15313 15314 +1 1 +.names 15638 15315 +0 1 +.names 15315 15316 +1 1 +.names 15316 15317 +0 1 +.names 15718 15719 15318 +11 1 +.names 15318 15319 +1 1 +.names 15319 15320 +0 1 +.names 15317 15320 15321 +11 1 +.names 2413 15322 +1 1 +.names 15322 15323 +0 1 +.names 15316 15323 15324 +11 1 +.names 15327 15325 +0 1 +.names 15325 15326 +1 1 +.names 1010 1009 15327 +01 1 +10 1 +.names 15332 15335 15328 +11 1 +.names 15328 15329 +1 1 +.names 15503 15506 15330 +1- 1 +-1 1 +.names 15330 15331 +1 1 +.names 15331 15332 +0 1 +.names 15526 15368 15333 +1- 1 +-1 1 +.names 15333 15334 +1 1 +.names 15334 15335 +0 1 +.names 15303 15336 +0 1 +.names 15336 15337 +1 1 +.names 15217 15341 15338 +1- 1 +-1 1 +.names 15338 15339 +1 1 +.names 1026 1025 15340 +01 1 +10 1 +.names 15340 15341 +1 1 +.names 15344 15304 15342 +11 1 +.names 15342 15343 +1 1 +.names 1010 15344 +0 1 +.names 15219 15345 +0 1 +.names 15492 15493 15346 +11 1 +.names 15346 15347 +1 1 +.names 15347 15348 +0 1 +.names 15345 15348 15349 +1- 1 +-1 1 +.names 15329 15350 +0 1 +.names 15354 15351 +0 1 +.names 15351 15352 +1 1 +.names 15478 15479 15353 +1- 1 +-1 1 +.names 15353 15354 +1 1 +.names 15358 15355 +0 1 +.names 15355 15356 +1 1 +.names 15416 15420 15357 +1- 1 +-1 1 +.names 15357 15358 +1 1 +.names 15747 15620 15359 +1- 1 +-1 1 +.names 15359 15360 +1 1 +.names 15360 15361 +0 1 +.names 15521 15524 15362 +1- 1 +-1 1 +.names 15362 15363 +1 1 +.names 15363 15364 +0 1 +.names 15361 15364 15365 +1- 1 +-1 1 +.names 15372 15385 15366 +1- 1 +-1 1 +.names 15366 15367 +1 1 +.names 15367 15368 +0 1 +.names 15365 15368 15369 +1- 1 +-1 1 +.names 15356 15370 +0 1 +.names 15379 15382 15371 +1- 1 +-1 1 +.names 15371 15372 +1 1 +.names 15586 15373 +0 1 +.names 15373 15374 +1 1 +.names 15374 15375 +0 1 +.names 15532 15536 15376 +1- 1 +-1 1 +.names 15376 15377 +1 1 +.names 15377 15378 +0 1 +.names 15375 15378 15379 +11 1 +.names 15663 15665 15380 +1- 1 +-1 1 +.names 15380 15381 +1 1 +.names 15381 15382 +0 1 +.names 15440 15442 15383 +11 1 +.names 15383 15384 +1 1 +.names 15384 15385 +0 1 +.names 15390 15391 15386 +11 1 +.names 15386 15387 +1 1 +.names 15514 15515 15388 +1- 1 +-1 1 +.names 15388 15389 +1 1 +.names 15389 15390 +0 1 +.names 15314 15391 +0 1 +.names 1022 1021 15392 +01 1 +10 1 +.names 15392 15393 +1 1 +.names 15393 15394 +0 1 +.names 15197 15395 +0 1 +.names 15395 15396 +1 1 +.names 15396 15397 +0 1 +.names 15400 15398 +0 1 +.names 15398 15399 +1 1 +.names 1012 1011 15400 +01 1 +10 1 +.names 15408 15411 15401 +1- 1 +-1 1 +.names 15401 15402 +1 1 +.names 1008 15403 +0 1 +.names 15403 15404 +1 1 +.names 15404 15405 +0 1 +.names 15278 15406 +1 1 +.names 15406 15407 +0 1 +.names 15405 15407 15408 +11 1 +.names 15591 15619 15409 +1- 1 +-1 1 +.names 15409 15410 +1 1 +.names 15410 15411 +0 1 +.names 15494 15412 +0 1 +.names 15412 15413 +1 1 +.names 15413 15414 +0 1 +.names 15245 15415 +0 1 +.names 15414 15415 15416 +11 1 +.names 1024 15417 +0 1 +.names 15417 15418 +1 1 +.names 15418 15419 +0 1 +.names 15413 15419 15420 +11 1 +.names 15423 15421 +0 1 +.names 15421 15422 +1 1 +.names 1014 1013 15423 +01 1 +10 1 +.names 15422 15424 +1 1 +.names 15432 15435 15425 +1- 1 +-1 1 +.names 15425 15426 +1 1 +.names 15424 15427 +0 1 +.names 15539 15428 +0 1 +.names 15428 15429 +1 1 +.names 15429 15430 +0 1 +.names 15427 15430 15431 +1- 1 +-1 1 +.names 15431 15171 15432 +1- 1 +-1 1 +.names 15496 15433 +0 1 +.names 15433 15434 +1 1 +.names 15434 15435 +0 1 +.names 15457 15436 +0 1 +.names 15436 15437 +1 1 +.names 15426 15438 +0 1 +.names 15438 15439 +1 1 +.names 15437 15439 15440 +11 1 +.names 15745 15460 15441 +11 1 +.names 15441 15442 +1 1 +.names 15445 15443 +0 1 +.names 15443 15444 +1 1 +.names 1016 1015 15445 +01 1 +10 1 +.names 15448 15446 +0 1 +.names 15446 15447 +1 1 +.names 1018 1017 15448 +01 1 +10 1 +.names 1020 1019 15449 +01 1 +10 1 +.names 15449 15450 +1 1 +.names 15455 15436 15451 +11 1 +.names 15451 15452 +1 1 +.names 15538 15430 15453 +1- 1 +-1 1 +.names 15453 15454 +1 1 +.names 15454 15455 +0 1 +.names 15510 15511 15456 +1- 1 +-1 1 +.names 15456 15457 +1 1 +.names 15399 15458 +0 1 +.names 15458 15459 +1 1 +.names 15459 15460 +0 1 +.names 1018 15461 +0 1 +.names 15460 15461 15462 +11 1 +.names 15658 15463 +0 1 +.names 15463 15464 +1 1 +.names 15464 15465 +0 1 +.names 15459 15465 15466 +11 1 +.names 15459 15467 +1 1 +.names 15452 15337 15468 +11 1 +.names 15339 15469 +0 1 +.names 15469 15470 +1 1 +.names 1005 15471 +0 1 +.names 15471 15472 +1 1 +.names 1013 15473 +0 1 +.names 15473 15474 +1 1 +.names 15474 15475 +0 1 +.names 15437 15476 +0 1 +.names 15439 15477 +0 1 +.names 15476 15477 15478 +1- 1 +-1 1 +.names 15337 15479 +0 1 +.names 15484 15485 15480 +1- 1 +-1 1 +.names 15480 15481 +1 1 +.names 15444 15482 +0 1 +.names 1016 15483 +1 1 +.names 15482 15483 15484 +11 1 +.names 15444 1019 15485 +11 1 +.names 15427 15170 15486 +1- 1 +-1 1 +.names 15168 15487 +0 1 +.names 1001 15488 +0 1 +.names 15488 15489 +1 1 +.names 15273 15490 +0 1 +.names 15490 15491 +1 1 +.names 15491 15492 +0 1 +.names 15402 15493 +0 1 +.names 15433 15494 +1 1 +.names 1024 1023 15495 +01 1 +10 1 +.names 15495 15496 +1 1 +.names 15240 15521 15497 +1- 1 +-1 1 +.names 15497 15498 +1 1 +.names 15498 15499 +0 1 +.names 15524 15521 15500 +1- 1 +-1 1 +.names 15500 15501 +1 1 +.names 15501 15502 +0 1 +.names 15499 15502 15503 +1- 1 +-1 1 +.names 15621 15622 15504 +11 1 +.names 15504 15505 +1 1 +.names 15505 15506 +0 1 +.names 15450 15507 +0 1 +.names 15507 15508 +1 1 +.names 15508 15509 +0 1 +.names 15509 15482 15510 +1- 1 +-1 1 +.names 15447 15511 +0 1 +.names 15467 15476 15512 +1- 1 +-1 1 +.names 15512 15513 +1 1 +.names 15414 15415 15514 +11 1 +.names 15413 15419 15515 +11 1 +.names 15519 15520 15516 +1- 1 +-1 1 +.names 15516 15517 +1 1 +.names 1025 15518 +0 1 +.names 15518 15519 +1 1 +.names 15341 15520 +0 1 +.names 15352 15521 +0 1 +.names 15517 15522 +0 1 +.names 15522 15523 +1 1 +.names 15523 15524 +0 1 +.names 15387 15525 +0 1 +.names 15231 15525 15526 +1- 1 +-1 1 +.names 15394 15397 15527 +11 1 +.names 15527 15528 +1 1 +.names 1003 15529 +0 1 +.names 15529 15530 +1 1 +.names 15530 15531 +0 1 +.names 15394 15531 15532 +11 1 +.names 1021 15533 +0 1 +.names 15533 15534 +1 1 +.names 15534 15535 +0 1 +.names 15393 15535 15536 +11 1 +.names 15427 15435 15537 +1- 1 +-1 1 +.names 15537 15171 15538 +1- 1 +-1 1 +.names 996 997 15539 +01 1 +10 1 +.names 2413 15540 +1 1 +.names 2413 15541 +1 1 +.names 15670 15674 15542 +1- 1 +-1 1 +.names 15542 15543 +1 1 +.names 2413 15544 +1 1 +.names 2413 15549 15545 +1- 1 +-1 1 +.names 15545 15546 +1 1 +.names 15547 +.names 15547 15548 +1 1 +.names 15548 15549 +0 1 +.names 15558 15561 15550 +1- 1 +-1 1 +.names 15550 15551 +1 1 +.names 15566 15552 +0 1 +.names 15552 15553 +1 1 +.names 15553 15554 +0 1 +.names 2413 15734 15555 +1- 1 +-1 1 +.names 15555 15556 +1 1 +.names 15556 15557 +0 1 +.names 15554 15557 15558 +11 1 +.names 2413 15559 +1 1 +.names 15559 15560 +0 1 +.names 15553 15560 15561 +11 1 +.names 1783 15631 15562 +01 1 +10 1 +.names 15562 15563 +1 1 +.names 15563 15564 +0 1 +.names 1783 15632 15565 +01 1 +10 1 +.names 15565 15566 +1 1 +.names 15570 15567 +0 1 +.names 15567 15568 +1 1 +.names 2413 15569 +1 1 +.names 15569 1783 15570 +01 1 +10 1 +.names 15568 15571 +0 1 +.names 15571 15572 +1 1 +.names 15549 15573 +1 1 +.names 15544 1783 15574 +01 1 +10 1 +.names 15282 15575 +0 1 +.names 15575 15576 +1 1 +.names 15577 +.names 15577 15578 +1 1 +.names 15578 15579 +0 1 +.names 15579 15580 +1 1 +.names 15584 15581 +0 1 +.names 15581 15582 +1 1 +.names 15624 15583 +0 1 +.names 15583 15584 +1 1 +.names 15661 15740 15585 +11 1 +.names 15585 15586 +1 1 +.names 15589 1783 15587 +01 1 +10 1 +.names 15587 15588 +1 1 +.names 2413 15589 +1 1 +.names 15602 15605 15590 +1- 1 +-1 1 +.names 15590 15591 +1 1 +.names 15636 15572 15592 +11 1 +.names 15592 15593 +1 1 +.names 15593 15594 +0 1 +.names 15640 15573 15595 +11 1 +.names 15595 15596 +1 1 +.names 15596 15597 +0 1 +.names 15594 15597 15598 +1- 1 +-1 1 +.names 15650 15580 15599 +11 1 +.names 15599 15600 +1 1 +.names 15600 15601 +0 1 +.names 15598 15601 15602 +1- 1 +-1 1 +.names 15656 15653 15603 +11 1 +.names 15603 15604 +1 1 +.names 15604 15605 +0 1 +.names 15629 15581 15606 +1- 1 +-1 1 +.names 15606 15607 +1 1 +.names 15582 15608 +0 1 +.names 15687 15688 15609 +11 1 +.names 15609 15610 +1 1 +.names 15610 15611 +0 1 +.names 15608 15611 15612 +11 1 +.names 2413 15613 +1 1 +.names 15613 15614 +0 1 +.names 15582 15614 15615 +11 1 +.names 15411 15616 +1 1 +.names 15696 15698 15617 +1- 1 +-1 1 +.names 15617 15618 +1 1 +.names 15618 15619 +0 1 +.names 15513 15620 +0 1 +.names 15620 15209 15621 +11 1 +.names 15616 15622 +0 1 +.names 2413 15623 +1 1 +.names 15624 +.names 15568 15548 15625 +1- 1 +-1 1 +.names 15655 15626 +0 1 +.names 15626 15627 +1 1 +.names 15627 15628 +0 1 +.names 15625 15628 15629 +1- 1 +-1 1 +.names 15564 15630 +1 1 +.names 2413 15631 +1 1 +.names 2413 15632 +1 1 +.names 2413 15633 +1 1 +.names 1783 15633 15634 +01 1 +10 1 +.names 15634 15635 +1 1 +.names 15635 15584 15636 +11 1 +.names 15639 15637 +0 1 +.names 15637 15638 +1 1 +.names 15639 +.names 15576 15638 15640 +11 1 +.names 15644 15641 +0 1 +.names 15641 15642 +1 1 +.names 1783 15645 15643 +01 1 +10 1 +.names 15643 15644 +1 1 +.names 2413 15645 +1 1 +.names 15646 +.names 15646 15647 +1 1 +.names 15647 15648 +0 1 +.names 15648 15649 +1 1 +.names 15649 15644 15650 +11 1 +.names 2413 15651 +1 1 +.names 1783 15651 15652 +01 1 +10 1 +.names 15652 15653 +1 1 +.names 2413 15654 +1 1 +.names 15654 15623 15655 +01 1 +10 1 +.names 15627 15284 15656 +11 1 +.names 1011 15657 +0 1 +.names 15657 15658 +1 1 +.names 15200 15659 +0 1 +.names 15659 15660 +1 1 +.names 15660 15661 +0 1 +.names 15343 15662 +0 1 +.names 15661 15662 15663 +11 1 +.names 15472 15664 +0 1 +.names 15660 15664 15665 +11 1 +.names 15280 15666 +0 1 +.names 15391 15667 +1 1 +.names 15667 15668 +0 1 +.names 15541 15669 +0 1 +.names 15285 15669 15670 +11 1 +.names 15725 15726 15671 +1- 1 +-1 1 +.names 15671 15672 +1 1 +.names 15672 15673 +0 1 +.names 15284 15673 15674 +11 1 +.names 15678 15680 15675 +1- 1 +-1 1 +.names 15675 15676 +1 1 +.names 15546 15677 +0 1 +.names 15571 15677 15678 +11 1 +.names 15569 15679 +0 1 +.names 15568 15679 15680 +11 1 +.names 15683 15686 15681 +11 1 +.names 15681 15682 +1 1 +.names 15654 15683 +0 1 +.names 15702 15703 15684 +1- 1 +-1 1 +.names 15684 15685 +1 1 +.names 15685 15686 +0 1 +.names 15682 15687 +0 1 +.names 15676 15688 +0 1 +.names 15693 15694 15689 +11 1 +.names 15689 15690 +1 1 +.names 15732 15733 15691 +11 1 +.names 15691 15692 +1 1 +.names 15692 15693 +0 1 +.names 15551 15694 +0 1 +.names 15540 15695 +0 1 +.names 15297 15695 15696 +11 1 +.names 15690 15697 +0 1 +.names 15296 15697 15698 +11 1 +.names 15623 15699 +0 1 +.names 15683 15699 15700 +11 1 +.names 15573 15701 +0 1 +.names 15700 15701 15702 +1- 1 +-1 1 +.names 15572 15703 +0 1 +.names 2413 15704 +1 1 +.names 15707 15708 15705 +11 1 +.names 15705 15706 +1 1 +.names 15653 15707 +0 1 +.names 15704 15708 +0 1 +.names 15714 15717 15709 +1- 1 +-1 1 +.names 15709 15710 +1 1 +.names 15642 15711 +0 1 +.names 15737 15736 15712 +11 1 +.names 15712 15713 +1 1 +.names 15711 15713 15714 +11 1 +.names 1783 15653 15715 +11 1 +.names 15715 15716 +1 1 +.names 15642 15716 15717 +11 1 +.names 15710 15718 +0 1 +.names 15706 15719 +0 1 +.names 15722 15723 15720 +1- 1 +-1 1 +.names 15720 15721 +1 1 +.names 15579 1783 15722 +11 1 +.names 15578 1783 15723 +11 1 +.names 15721 15724 +0 1 +.names 15575 15724 15725 +11 1 +.names 15282 2413 15726 +11 1 +.names 2413 15727 +1 1 +.names 15730 15731 15728 +1- 1 +-1 1 +.names 15728 15729 +1 1 +.names 15552 15292 15730 +1- 1 +-1 1 +.names 15630 15731 +0 1 +.names 15729 15732 +0 1 +.names 15727 15733 +0 1 +.names 15589 15734 +0 1 +.names 2413 15735 +1 1 +.names 15735 15736 +1 1 +.names 15653 1783 15737 +11 1 +.names 15511 15738 +1 1 +.names 15738 15739 +0 1 +.names 15305 15740 +0 1 +.names 15740 15661 15741 +11 1 +.names 15741 15742 +1 1 +.names 15742 15743 +0 1 +.names 15528 15744 +0 1 +.names 15743 15744 15745 +1- 1 +-1 1 +.names 15176 15746 +0 1 +.names 15426 15746 15747 +1- 1 +-1 1 +.names 15169 15750 15748 +1- 1 +-1 1 +.names 15748 15749 +1 1 +.names 1028 15750 +0 1 +.names 15754 15751 +0 1 +.names 15751 15752 +1 1 +.names 15777 15753 +0 1 +.names 15753 15754 +1 1 +.names 15759 15762 15755 +1- 1 +-1 1 +.names 15755 15756 +1 1 +.names 15769 15773 15757 +1- 1 +-1 1 +.names 15757 15758 +1 1 +.names 15758 15759 +0 1 +.names 15812 15763 15760 +1- 1 +-1 1 +.names 15760 15761 +1 1 +.names 15761 15762 +0 1 +.names 15775 15763 +0 1 +.names 15763 15764 +1 1 +.names 15764 15765 +0 1 +.names 1027 15766 +0 1 +.names 15766 15767 +1 1 +.names 15767 15768 +0 1 +.names 15765 15768 15769 +11 1 +.names 999 15770 +0 1 +.names 15770 15771 +1 1 +.names 15771 15772 +0 1 +.names 15764 15772 15773 +11 1 +.names 15776 15774 +0 1 +.names 15774 15775 +1 1 +.names 999 1029 15776 +01 1 +10 1 +.names 1030 1000 15777 +01 1 +10 1 +.names 15780 15778 +0 1 +.names 15778 15779 +1 1 +.names 1031 1002 15780 +01 1 +10 1 +.names 15783 15781 +0 1 +.names 15781 15782 +1 1 +.names 1032 1004 15783 +01 1 +10 1 +.names 15787 15784 +0 1 +.names 15784 15785 +1 1 +.names 15839 15842 15786 +1- 1 +-1 1 +.names 15786 15787 +1 1 +.names 15790 15793 15788 +1- 1 +-1 1 +.names 15788 15789 +1 1 +.names 15785 15790 +0 1 +.names 1033 1007 15791 +01 1 +10 1 +.names 15791 15792 +1 1 +.names 15792 15793 +0 1 +.names 15798 15801 15794 +11 1 +.names 15794 15795 +1 1 +.names 15806 15810 15796 +1- 1 +-1 1 +.names 15796 15797 +1 1 +.names 15797 15798 +0 1 +.names 16089 15799 +0 1 +.names 15799 15800 +1 1 +.names 15800 15801 +0 1 +.names 15752 15802 +0 1 +.names 15873 15874 15803 +1- 1 +-1 1 +.names 15803 15804 +1 1 +.names 15804 15805 +0 1 +.names 15802 15805 15806 +11 1 +.names 16310 15872 15807 +1- 1 +-1 1 +.names 15807 15808 +1 1 +.names 15808 15809 +0 1 +.names 15752 15809 15810 +11 1 +.names 1027 1043 15811 +01 1 +10 1 +.names 15811 15812 +1 1 +.names 15816 15819 15813 +1- 1 +-1 1 +.names 15813 15814 +1 1 +.names 1033 1007 15815 +01 1 +10 1 +.names 15815 15816 +1 1 +.names 16007 16009 15817 +11 1 +.names 15817 15818 +1 1 +.names 15818 15819 +0 1 +.names 15827 15830 15820 +1- 1 +-1 1 +.names 15820 15821 +1 1 +.names 16159 15822 +0 1 +.names 15822 15823 +1 1 +.names 16130 1783 15824 +01 1 +10 1 +.names 15824 15825 +1 1 +.names 15825 15826 +0 1 +.names 15823 15826 15827 +1- 1 +-1 1 +.names 16272 16164 15828 +11 1 +.names 15828 15829 +1 1 +.names 15829 15830 +0 1 +.names 16134 16137 15831 +1- 1 +-1 1 +.names 15831 15832 +1 1 +.names 16177 15833 +0 1 +.names 15833 15834 +1 1 +.names 15832 15834 15835 +1- 1 +-1 1 +.names 16129 1783 15836 +01 1 +10 1 +.names 15836 15837 +1 1 +.names 15837 15838 +0 1 +.names 15835 15838 15839 +1- 1 +-1 1 +.names 16180 15840 +0 1 +.names 15840 15841 +1 1 +.names 15841 15842 +0 1 +.names 15850 15853 15843 +1- 1 +-1 1 +.names 15843 15844 +1 1 +.names 15855 15845 +0 1 +.names 15845 15846 +1 1 +.names 15893 15896 15847 +11 1 +.names 15847 15848 +1 1 +.names 15848 15849 +0 1 +.names 15846 15849 15850 +1- 1 +-1 1 +.names 15782 15898 15851 +11 1 +.names 15851 15852 +1 1 +.names 15852 15853 +0 1 +.names 15856 15854 +0 1 +.names 15854 15855 +1 1 +.names 1034 1009 15856 +01 1 +10 1 +.names 15844 15857 +0 1 +.names 15857 15858 +1 1 +.names 15787 15862 15859 +1- 1 +-1 1 +.names 15859 15860 +1 1 +.names 1026 1042 15861 +01 1 +10 1 +.names 15861 15862 +1 1 +.names 15866 15863 +0 1 +.names 15863 15864 +1 1 +.names 16021 16022 15865 +1- 1 +-1 1 +.names 15865 15866 +1 1 +.names 15814 15867 +0 1 +.names 1023 15868 +0 1 +.names 15868 15869 +1 1 +.names 15901 15870 +1 1 +.names 15870 15871 +1 1 +.names 15871 15872 +0 1 +.names 15169 15872 15873 +1- 1 +-1 1 +.names 15749 15874 +0 1 +.names 15878 15879 15875 +1- 1 +-1 1 +.names 15875 15876 +1 1 +.names 1026 15877 +0 1 +.names 15877 15878 +1 1 +.names 15862 15879 +0 1 +.names 15884 15886 15880 +1- 1 +-1 1 +.names 15880 15881 +1 1 +.names 15876 15882 +0 1 +.names 15882 15883 +1 1 +.names 15883 15884 +0 1 +.names 15863 15885 +1 1 +.names 15885 15886 +0 1 +.names 15890 15887 +0 1 +.names 15887 15888 +1 1 +.names 16102 15907 15889 +1- 1 +-1 1 +.names 15889 15890 +1 1 +.names 1022 1040 15891 +01 1 +10 1 +.names 15891 15892 +1 1 +.names 15892 15893 +0 1 +.names 15779 15894 +0 1 +.names 15894 15895 +1 1 +.names 15895 15896 +0 1 +.names 15899 15897 +0 1 +.names 15897 15898 +1 1 +.names 1012 1035 15899 +01 1 +10 1 +.names 15819 15900 +1 1 +.names 15902 15901 +0 1 +.names 1014 1036 15902 +01 1 +10 1 +.names 15909 15912 15903 +1- 1 +-1 1 +.names 15903 15904 +1 1 +.names 16107 15905 +0 1 +.names 15905 15906 +1 1 +.names 15906 15907 +0 1 +.names 15872 15907 15908 +1- 1 +-1 1 +.names 15908 15751 15909 +1- 1 +-1 1 +.names 16083 15910 +0 1 +.names 15910 15911 +1 1 +.names 15911 15912 +0 1 +.names 15919 15921 15913 +11 1 +.names 15913 15914 +1 1 +.names 15967 15915 +0 1 +.names 15915 15916 +1 1 +.names 15904 15917 +0 1 +.names 15917 15918 +1 1 +.names 15916 15918 15919 +11 1 +.names 16340 16341 15920 +11 1 +.names 15920 15921 +1 1 +.names 15932 15784 15922 +11 1 +.names 15922 15923 +1 1 +.names 15939 15942 15924 +11 1 +.names 15924 15925 +1 1 +.names 15925 15926 +0 1 +.names 16069 16070 15927 +1- 1 +-1 1 +.names 15927 15928 +1 1 +.names 15928 15929 +0 1 +.names 15926 15929 15930 +1- 1 +-1 1 +.names 15881 15931 +0 1 +.names 15930 15931 15932 +1- 1 +-1 1 +.names 16019 15933 +0 1 +.names 15933 15934 +1 1 +.names 15934 15935 +0 1 +.names 16005 16006 15936 +1- 1 +-1 1 +.names 15936 15937 +1 1 +.names 15937 15938 +0 1 +.names 15935 15938 15939 +1- 1 +-1 1 +.names 16085 16087 15940 +1- 1 +-1 1 +.names 15940 15941 +1 1 +.names 15941 15942 +0 1 +.names 15947 15938 15943 +11 1 +.names 15943 15944 +1 1 +.names 16282 16283 15945 +1- 1 +-1 1 +.names 15945 15946 +1 1 +.names 15946 15947 +0 1 +.names 15952 15955 15948 +11 1 +.names 15948 15949 +1 1 +.names 16106 15931 15950 +1- 1 +-1 1 +.names 15950 15951 +1 1 +.names 15951 15952 +0 1 +.names 16080 16081 15953 +1- 1 +-1 1 +.names 15953 15954 +1 1 +.names 15954 15955 +0 1 +.names 15958 15956 +0 1 +.names 15956 15957 +1 1 +.names 1037 1015 15958 +01 1 +10 1 +.names 15961 15959 +0 1 +.names 15959 15960 +1 1 +.names 1038 1017 15961 +01 1 +10 1 +.names 1020 1039 15962 +01 1 +10 1 +.names 15962 15963 +1 1 +.names 15887 15915 15964 +11 1 +.names 15964 15965 +1 1 +.names 16054 15978 15966 +1- 1 +-1 1 +.names 15966 15967 +1 1 +.names 1015 15968 +1 1 +.names 15973 15975 15969 +1- 1 +-1 1 +.names 15969 15970 +1 1 +.names 15957 15971 +0 1 +.names 15968 15972 +0 1 +.names 15971 15972 15973 +11 1 +.names 1020 15974 +0 1 +.names 15957 15974 15975 +11 1 +.names 15982 15986 15976 +1- 1 +-1 1 +.names 15976 15977 +1 1 +.names 15960 15978 +0 1 +.names 15978 15979 +1 1 +.names 15979 15980 +0 1 +.names 15970 15981 +0 1 +.names 15980 15981 15982 +11 1 +.names 1017 15983 +0 1 +.names 15983 15984 +1 1 +.names 15984 15985 +0 1 +.names 15979 15985 15986 +11 1 +.names 15989 15987 +1 1 +.names 15987 15988 +1 1 +.names 15898 15989 +0 1 +.names 1012 15990 +0 1 +.names 15990 15991 +1 1 +.names 15994 15995 15992 +11 1 +.names 15992 15993 +1 1 +.names 15916 15994 +0 1 +.names 15988 15995 +0 1 +.names 15998 15999 15996 +1- 1 +-1 1 +.names 15996 15997 +1 1 +.names 15977 15998 +0 1 +.names 15993 15999 +0 1 +.names 15995 16004 16000 +1- 1 +-1 1 +.names 16000 16001 +1 1 +.names 15991 16002 +0 1 +.names 16002 16003 +1 1 +.names 16003 16004 +0 1 +.names 15997 16005 +0 1 +.names 16001 16006 +0 1 +.names 15965 15858 16007 +11 1 +.names 15860 16008 +0 1 +.names 16008 16009 +1 1 +.names 16013 16016 16010 +11 1 +.names 16010 16011 +1 1 +.names 15867 16012 +1 1 +.names 16012 16013 +0 1 +.names 16172 16173 16014 +1- 1 +-1 1 +.names 16014 16015 +1 1 +.names 16015 16016 +0 1 +.names 1014 16017 +1 1 +.names 15888 16018 +0 1 +.names 16018 16019 +1 1 +.names 15918 16020 +0 1 +.names 15994 16020 16021 +1- 1 +-1 1 +.names 15858 16022 +0 1 +.names 16031 16034 16023 +11 1 +.names 16023 16024 +1 1 +.names 16169 16025 +0 1 +.names 16025 16026 +1 1 +.names 16026 16027 +0 1 +.names 15900 16028 +0 1 +.names 16028 16029 +1 1 +.names 16029 16030 +0 1 +.names 16027 16030 16031 +1- 1 +-1 1 +.names 16114 16117 16032 +1- 1 +-1 1 +.names 16032 16033 +1 1 +.names 16033 16034 +0 1 +.names 16037 16038 16035 +1- 1 +-1 1 +.names 16035 16036 +1 1 +.names 16024 16037 +0 1 +.names 16011 16038 +0 1 +.names 16036 16039 +0 1 +.names 16039 16040 +1 1 +.names 16040 16041 +0 1 +.names 15923 16042 +0 1 +.names 16042 16043 +1 1 +.names 16043 16044 +0 1 +.names 16041 16044 16045 +1- 1 +-1 1 +.names 15949 16046 +0 1 +.names 16049 16050 16047 +1- 1 +-1 1 +.names 16047 16048 +1 1 +.names 15912 15869 16049 +11 1 +.names 15911 15795 16050 +11 1 +.names 15963 16051 +0 1 +.names 16051 16052 +1 1 +.names 16052 16053 +0 1 +.names 16053 15971 16054 +1- 1 +-1 1 +.names 16063 16066 16055 +1- 1 +-1 1 +.names 16055 16056 +1 1 +.names 16175 16057 +0 1 +.names 16057 16058 +1 1 +.names 16058 16059 +0 1 +.names 16096 16100 16060 +1- 1 +-1 1 +.names 16060 16061 +1 1 +.names 16061 16062 +0 1 +.names 16059 16062 16063 +11 1 +.names 16252 16254 16064 +1- 1 +-1 1 +.names 16064 16065 +1 1 +.names 16065 16066 +0 1 +.names 16056 16067 +0 1 +.names 16067 16068 +1 1 +.names 16068 16069 +0 1 +.names 15914 16070 +0 1 +.names 16074 16076 16071 +11 1 +.names 16071 16072 +1 1 +.names 16180 16242 16073 +1- 1 +-1 1 +.names 16073 16074 +1 1 +.names 16222 16223 16075 +1- 1 +-1 1 +.names 16075 16076 +1 1 +.names 15944 16077 +0 1 +.names 16077 15929 16078 +1- 1 +-1 1 +.names 16048 16079 +0 1 +.names 16078 16079 16080 +1- 1 +-1 1 +.names 16072 16081 +0 1 +.names 1041 1023 16082 +01 1 +10 1 +.names 16082 16083 +1 1 +.names 15795 16084 +0 1 +.names 15910 16084 16085 +11 1 +.names 15869 16086 +0 1 +.names 16083 16086 16087 +11 1 +.names 15871 16090 16088 +1- 1 +-1 1 +.names 16088 16089 +1 1 +.names 16017 16090 +0 1 +.names 15893 15896 16091 +11 1 +.names 16091 16092 +1 1 +.names 1002 16093 +0 1 +.names 16093 16094 +1 1 +.names 16094 16095 +0 1 +.names 15893 16095 16096 +11 1 +.names 1022 16097 +0 1 +.names 16097 16098 +1 1 +.names 16098 16099 +0 1 +.names 15892 16099 16100 +11 1 +.names 15872 15912 16101 +1- 1 +-1 1 +.names 16101 15751 16102 +1- 1 +-1 1 +.names 15789 16105 16103 +1- 1 +-1 1 +.names 16103 16104 +1 1 +.names 15864 16105 +0 1 +.names 16104 16106 +0 1 +.names 996 1028 16107 +01 1 +10 1 +.names 16167 16108 +0 1 +.names 16108 16109 +1 1 +.names 16109 16110 +0 1 +.names 16212 16213 16111 +11 1 +.names 16111 16112 +1 1 +.names 16112 16113 +0 1 +.names 16110 16113 16114 +11 1 +.names 2413 16115 +1 1 +.names 16115 16116 +0 1 +.names 16109 16116 16117 +11 1 +.names 16034 16118 +1 1 +.names 16126 16128 16119 +1- 1 +-1 1 +.names 16119 16120 +1 1 +.names 16262 16121 +0 1 +.names 16121 16122 +1 1 +.names 16122 16123 +0 1 +.names 16324 16325 16124 +11 1 +.names 16124 16125 +1 1 +.names 16123 16125 16126 +11 1 +.names 2413 16127 +1 1 +.names 16122 16127 16128 +11 1 +.names 2413 16129 +1 1 +.names 2413 16130 +1 1 +.names 2413 16131 +1 1 +.names 1783 16256 16132 +01 1 +10 1 +.names 16132 16133 +1 1 +.names 16133 16134 +0 1 +.names 1783 16146 16135 +01 1 +10 1 +.names 16135 16136 +1 1 +.names 16136 16137 +0 1 +.names 16145 16148 16138 +1- 1 +-1 1 +.names 16138 16139 +1 1 +.names 16137 16140 +1 1 +.names 16140 16141 +0 1 +.names 2413 16331 16142 +1- 1 +-1 1 +.names 16142 16143 +1 1 +.names 16143 16144 +0 1 +.names 16141 16144 16145 +11 1 +.names 2413 16146 +1 1 +.names 16146 16147 +0 1 +.names 16140 16147 16148 +11 1 +.names 16152 16149 +0 1 +.names 16149 16150 +1 1 +.names 2413 16151 +1 1 +.names 16151 1783 16152 +01 1 +10 1 +.names 16150 16153 +0 1 +.names 16153 16154 +1 1 +.names 16155 +.names 16155 16156 +1 1 +.names 16156 16157 +0 1 +.names 16157 16158 +1 1 +.names 16131 1783 16159 +01 1 +10 1 +.names 15823 16160 +0 1 +.names 16160 16161 +1 1 +.names 16162 +.names 16162 16163 +1 1 +.names 16163 16164 +0 1 +.names 16164 16165 +1 1 +.names 16214 16166 +0 1 +.names 16166 16167 +1 1 +.names 1007 16168 +0 1 +.names 16168 16169 +1 1 +.names 16231 16232 16170 +1- 1 +-1 1 +.names 16170 16171 +1 1 +.names 16171 16172 +0 1 +.names 16074 16173 +0 1 +.names 16250 16335 16174 +11 1 +.names 16174 16175 +1 1 +.names 16178 1783 16176 +01 1 +10 1 +.names 16176 16177 +1 1 +.names 2413 16178 +1 1 +.names 16191 16194 16179 +1- 1 +-1 1 +.names 16179 16180 +1 1 +.names 16260 16154 16181 +11 1 +.names 16181 16182 +1 1 +.names 16182 16183 +0 1 +.names 16264 16158 16184 +11 1 +.names 16184 16185 +1 1 +.names 16185 16186 +0 1 +.names 16183 16186 16187 +1- 1 +-1 1 +.names 16274 16165 16188 +11 1 +.names 16188 16189 +1 1 +.names 16189 16190 +0 1 +.names 16187 16190 16191 +1- 1 +-1 1 +.names 16280 16277 16192 +11 1 +.names 16192 16193 +1 1 +.names 16193 16194 +0 1 +.names 16198 16195 +0 1 +.names 16195 16196 +1 1 +.names 16219 16108 16197 +1- 1 +-1 1 +.names 16197 16198 +1 1 +.names 2413 16199 +1 1 +.names 16204 16205 16200 +11 1 +.names 16200 16201 +1 1 +.names 16287 16288 16202 +1- 1 +-1 1 +.names 16202 16203 +1 1 +.names 16203 16204 +0 1 +.names 16199 16205 +0 1 +.names 16210 16211 16206 +1- 1 +-1 1 +.names 16206 16207 +1 1 +.names 1783 16156 16208 +11 1 +.names 16208 16209 +1 1 +.names 16153 16209 16210 +11 1 +.names 16150 1783 16211 +11 1 +.names 16207 16212 +0 1 +.names 16201 16213 +0 1 +.names 16214 +.names 16150 16156 16215 +1- 1 +-1 1 +.names 16279 16216 +0 1 +.names 16216 16217 +1 1 +.names 16217 16218 +0 1 +.names 16215 16218 16219 +1- 1 +-1 1 +.names 16298 16300 16220 +1- 1 +-1 1 +.names 16220 16221 +1 1 +.names 16221 16222 +0 1 +.names 15821 16223 +0 1 +.names 16076 16224 +0 1 +.names 16224 16225 +1 1 +.names 16228 16223 16226 +11 1 +.names 16226 16227 +1 1 +.names 16120 16228 +0 1 +.names 16227 16229 +0 1 +.names 16225 16230 +0 1 +.names 16229 16230 16231 +11 1 +.names 16196 16232 +0 1 +.names 2413 16233 +1 1 +.names 16237 16241 16234 +1- 1 +-1 1 +.names 16234 16235 +1 1 +.names 16233 16236 +0 1 +.names 15838 16236 16237 +11 1 +.names 16307 16308 16238 +11 1 +.names 16238 16239 +1 1 +.names 16239 16240 +0 1 +.names 15837 16240 16241 +11 1 +.names 16235 16242 +0 1 +.names 1004 16243 +0 1 +.names 16243 16244 +1 1 +.names 16247 15845 16245 +11 1 +.names 16245 16246 +1 1 +.names 1009 16247 +0 1 +.names 15782 16248 +0 1 +.names 16248 16249 +1 1 +.names 16249 16250 +0 1 +.names 16246 16251 +0 1 +.names 16250 16251 16252 +11 1 +.names 16244 16253 +0 1 +.names 16249 16253 16254 +11 1 +.names 16134 16255 +1 1 +.names 2413 16256 +1 1 +.names 2413 16257 +1 1 +.names 1783 16257 16258 +01 1 +10 1 +.names 16258 16259 +1 1 +.names 16259 16167 16260 +11 1 +.names 16263 16261 +0 1 +.names 16261 16262 +1 1 +.names 16263 +.names 16161 16262 16264 +11 1 +.names 16268 16265 +0 1 +.names 16265 16266 +1 1 +.names 1783 16269 16267 +01 1 +10 1 +.names 16267 16268 +1 1 +.names 2413 16269 +1 1 +.names 16270 +.names 16270 16271 +1 1 +.names 16271 16272 +0 1 +.names 16272 16273 +1 1 +.names 16273 16268 16274 +11 1 +.names 2413 16275 +1 1 +.names 1783 16275 16276 +01 1 +10 1 +.names 16276 16277 +1 1 +.names 2413 16278 +1 1 +.names 16278 16199 16279 +01 1 +10 1 +.names 16217 15825 16280 +11 1 +.names 15756 16281 +0 1 +.names 16228 16281 16282 +1- 1 +-1 1 +.names 16118 16283 +0 1 +.names 16278 16284 +0 1 +.names 16284 16205 16285 +11 1 +.names 16158 16286 +0 1 +.names 16285 16286 16287 +1- 1 +-1 1 +.names 16154 16288 +0 1 +.names 16294 16295 16289 +1- 1 +-1 1 +.names 16289 16290 +1 1 +.names 16328 16329 16291 +1- 1 +-1 1 +.names 16291 16292 +1 1 +.names 16292 16293 +0 1 +.names 16160 16293 16294 +11 1 +.names 15823 2413 16295 +11 1 +.names 2413 16296 +1 1 +.names 16296 16297 +0 1 +.names 15826 16297 16298 +11 1 +.names 16290 16299 +0 1 +.names 15825 16299 16300 +11 1 +.names 16303 16306 16301 +11 1 +.names 16301 16302 +1 1 +.names 16256 16303 +0 1 +.names 16326 16327 16304 +1- 1 +-1 1 +.names 16304 16305 +1 1 +.names 16305 16306 +0 1 +.names 16302 16307 +0 1 +.names 16139 16308 +0 1 +.names 1000 16309 +0 1 +.names 16309 16310 +1 1 +.names 16313 16314 16311 +11 1 +.names 16311 16312 +1 1 +.names 16277 16313 +0 1 +.names 16275 16314 +0 1 +.names 16320 16323 16315 +1- 1 +-1 1 +.names 16315 16316 +1 1 +.names 16266 16317 +0 1 +.names 16334 16333 16318 +11 1 +.names 16318 16319 +1 1 +.names 16317 16319 16320 +11 1 +.names 1783 16277 16321 +11 1 +.names 16321 16322 +1 1 +.names 16266 16322 16323 +11 1 +.names 16316 16324 +0 1 +.names 16312 16325 +0 1 +.names 16137 15833 16326 +1- 1 +-1 1 +.names 16255 16327 +0 1 +.names 16164 1783 16328 +11 1 +.names 16163 1783 16329 +11 1 +.names 2413 16330 +1 1 +.names 16330 16331 +0 1 +.names 2413 16332 +1 1 +.names 16332 16333 +1 1 +.names 16277 1783 16334 +11 1 +.names 15846 16335 +0 1 +.names 16335 16250 16336 +11 1 +.names 16336 16337 +1 1 +.names 16337 16338 +0 1 +.names 16092 16339 +0 1 +.names 16338 16339 16340 +1- 1 +-1 1 +.names 15987 16341 +0 1 +.names 15169 16344 16342 +1- 1 +-1 1 +.names 16342 16343 +1 1 +.names 1044 16344 +0 1 +.names 16348 16345 +0 1 +.names 16345 16346 +1 1 +.names 16369 16347 +0 1 +.names 16347 16348 +1 1 +.names 16357 16361 16349 +1- 1 +-1 1 +.names 16349 16350 +1 1 +.names 16634 16913 16351 +11 1 +.names 16351 16352 +1 1 +.names 16352 16353 +0 1 +.names 16636 16640 16354 +1- 1 +-1 1 +.names 16354 16355 +1 1 +.names 16355 16356 +0 1 +.names 16353 16356 16357 +11 1 +.names 16655 16358 +0 1 +.names 16358 16359 +1 1 +.names 16359 16360 +0 1 +.names 16352 16360 16361 +11 1 +.names 16365 16362 +0 1 +.names 16362 16363 +1 1 +.names 16786 16789 16364 +1- 1 +-1 1 +.names 16364 16365 +1 1 +.names 16368 16366 +0 1 +.names 16366 16367 +1 1 +.names 999 1045 16368 +01 1 +10 1 +.names 1046 1000 16369 +01 1 +10 1 +.names 16372 16370 +0 1 +.names 16370 16371 +1 1 +.names 1047 1002 16372 +01 1 +10 1 +.names 16375 16373 +0 1 +.names 16373 16374 +1 1 +.names 1048 1004 16375 +01 1 +10 1 +.names 16384 16387 16376 +1- 1 +-1 1 +.names 16376 16377 +1 1 +.names 16840 16842 16378 +11 1 +.names 16378 16379 +1 1 +.names 16379 16380 +0 1 +.names 16717 16454 16381 +11 1 +.names 16381 16382 +1 1 +.names 16382 16383 +0 1 +.names 16380 16383 16384 +11 1 +.names 16781 16385 +0 1 +.names 16385 16386 +1 1 +.names 16386 16387 +0 1 +.names 16391 16388 +0 1 +.names 16388 16389 +1 1 +.names 16472 16475 16390 +1- 1 +-1 1 +.names 16390 16391 +1 1 +.names 16398 16401 16392 +11 1 +.names 16392 16393 +1 1 +.names 16543 16544 16394 +1- 1 +-1 1 +.names 16394 16395 +1 1 +.names 16395 16396 +0 1 +.names 16389 16397 +0 1 +.names 16396 16397 16398 +1- 1 +-1 1 +.names 16402 16403 16399 +1- 1 +-1 1 +.names 16399 16400 +1 1 +.names 16400 16401 +0 1 +.names 16377 16402 +0 1 +.names 16363 16403 +0 1 +.names 16412 16403 16404 +1- 1 +-1 1 +.names 16404 16405 +1 1 +.names 16443 16406 +0 1 +.names 16406 16407 +1 1 +.names 16407 16408 +0 1 +.names 16439 16441 16409 +1- 1 +-1 1 +.names 16409 16410 +1 1 +.names 16410 16411 +0 1 +.names 16408 16411 16412 +11 1 +.names 16397 16417 16413 +1- 1 +-1 1 +.names 16413 16414 +1 1 +.names 1050 1007 16415 +01 1 +10 1 +.names 16415 16416 +1 1 +.names 16416 16417 +0 1 +.names 16422 16425 16418 +11 1 +.names 16418 16419 +1 1 +.names 16430 16434 16420 +1- 1 +-1 1 +.names 16420 16421 +1 1 +.names 16421 16422 +0 1 +.names 16601 16649 16423 +11 1 +.names 16423 16424 +1 1 +.names 16424 16425 +0 1 +.names 16346 16426 +0 1 +.names 16660 16661 16427 +1- 1 +-1 1 +.names 16427 16428 +1 1 +.names 16428 16429 +0 1 +.names 16426 16429 16430 +11 1 +.names 16663 16601 16431 +1- 1 +-1 1 +.names 16431 16432 +1 1 +.names 16432 16433 +0 1 +.names 16346 16433 16434 +11 1 +.names 16367 16435 +0 1 +.names 16435 16436 +1 1 +.names 16436 16437 +0 1 +.names 1049 16438 +0 1 +.names 16437 16438 16439 +11 1 +.names 1045 16440 +0 1 +.names 16436 16440 16441 +11 1 +.names 16445 16435 16442 +1- 1 +-1 1 +.names 16442 16443 +1 1 +.names 1027 1049 16444 +01 1 +10 1 +.names 16444 16445 +1 1 +.names 16449 16452 16446 +1- 1 +-1 1 +.names 16446 16447 +1 1 +.names 1050 1007 16448 +01 1 +10 1 +.names 16448 16449 +1 1 +.names 16642 16644 16450 +11 1 +.names 16450 16451 +1 1 +.names 16451 16452 +0 1 +.names 16460 16463 16453 +1- 1 +-1 1 +.names 16453 16454 +1 1 +.names 16748 16455 +0 1 +.names 16455 16456 +1 1 +.names 16715 1783 16457 +01 1 +10 1 +.names 16457 16458 +1 1 +.names 16458 16459 +0 1 +.names 16456 16459 16460 +1- 1 +-1 1 +.names 16822 16753 16461 +11 1 +.names 16461 16462 +1 1 +.names 16462 16463 +0 1 +.names 16738 16726 16464 +1- 1 +-1 1 +.names 16464 16465 +1 1 +.names 16762 16466 +0 1 +.names 16466 16467 +1 1 +.names 16465 16467 16468 +1- 1 +-1 1 +.names 16714 1783 16469 +01 1 +10 1 +.names 16469 16470 +1 1 +.names 16470 16471 +0 1 +.names 16468 16471 16472 +1- 1 +-1 1 +.names 16765 16473 +0 1 +.names 16473 16474 +1 1 +.names 16474 16475 +0 1 +.names 16483 16486 16476 +1- 1 +-1 1 +.names 16476 16477 +1 1 +.names 16500 16478 +0 1 +.names 16478 16479 +1 1 +.names 16568 16571 16480 +11 1 +.names 16480 16481 +1 1 +.names 16481 16482 +0 1 +.names 16479 16482 16483 +1- 1 +-1 1 +.names 16374 16573 16484 +11 1 +.names 16484 16485 +1 1 +.names 16485 16486 +0 1 +.names 16495 16498 16487 +1- 1 +-1 1 +.names 16487 16488 +1 1 +.names 16812 16489 +0 1 +.names 16489 16490 +1 1 +.names 16490 16491 +0 1 +.names 16892 16893 16492 +11 1 +.names 16492 16493 +1 1 +.names 16493 16494 +0 1 +.names 16491 16494 16495 +11 1 +.names 2413 16496 +1 1 +.names 16496 16497 +0 1 +.names 16490 16497 16498 +11 1 +.names 16501 16499 +0 1 +.names 16499 16500 +1 1 +.names 1051 1009 16501 +01 1 +10 1 +.names 16506 16509 16502 +11 1 +.names 16502 16503 +1 1 +.names 16677 16680 16504 +1- 1 +-1 1 +.names 16504 16505 +1 1 +.names 16505 16506 +0 1 +.names 16700 16542 16507 +1- 1 +-1 1 +.names 16507 16508 +1 1 +.names 16508 16509 +0 1 +.names 16477 16510 +0 1 +.names 16510 16511 +1 1 +.names 16391 16515 16512 +1- 1 +-1 1 +.names 16512 16513 +1 1 +.names 1026 1059 16514 +01 1 +10 1 +.names 16514 16515 +1 1 +.names 16518 16478 16516 +11 1 +.names 16516 16517 +1 1 +.names 1051 16518 +0 1 +.names 16393 16519 +0 1 +.names 16666 16667 16520 +11 1 +.names 16520 16521 +1 1 +.names 16521 16522 +0 1 +.names 16519 16522 16523 +1- 1 +-1 1 +.names 16503 16524 +0 1 +.names 16528 16525 +0 1 +.names 16525 16526 +1 1 +.names 16652 16653 16527 +1- 1 +-1 1 +.names 16527 16528 +1 1 +.names 16532 16529 +0 1 +.names 16529 16530 +1 1 +.names 16590 16594 16531 +1- 1 +-1 1 +.names 16531 16532 +1 1 +.names 16921 16794 16533 +1- 1 +-1 1 +.names 16533 16534 +1 1 +.names 16534 16535 +0 1 +.names 16695 16698 16536 +1- 1 +-1 1 +.names 16536 16537 +1 1 +.names 16537 16538 +0 1 +.names 16535 16538 16539 +1- 1 +-1 1 +.names 16546 16559 16540 +1- 1 +-1 1 +.names 16540 16541 +1 1 +.names 16541 16542 +0 1 +.names 16539 16542 16543 +1- 1 +-1 1 +.names 16530 16544 +0 1 +.names 16553 16556 16545 +1- 1 +-1 1 +.names 16545 16546 +1 1 +.names 16760 16547 +0 1 +.names 16547 16548 +1 1 +.names 16548 16549 +0 1 +.names 16706 16710 16550 +1- 1 +-1 1 +.names 16550 16551 +1 1 +.names 16551 16552 +0 1 +.names 16549 16552 16553 +11 1 +.names 16837 16839 16554 +1- 1 +-1 1 +.names 16554 16555 +1 1 +.names 16555 16556 +0 1 +.names 16614 16616 16557 +11 1 +.names 16557 16558 +1 1 +.names 16558 16559 +0 1 +.names 16564 16565 16560 +11 1 +.names 16560 16561 +1 1 +.names 16688 16689 16562 +1- 1 +-1 1 +.names 16562 16563 +1 1 +.names 16563 16564 +0 1 +.names 16488 16565 +0 1 +.names 1022 1057 16566 +01 1 +10 1 +.names 16566 16567 +1 1 +.names 16567 16568 +0 1 +.names 16371 16569 +0 1 +.names 16569 16570 +1 1 +.names 16570 16571 +0 1 +.names 16574 16572 +0 1 +.names 16572 16573 +1 1 +.names 1012 1052 16574 +01 1 +10 1 +.names 16582 16585 16575 +1- 1 +-1 1 +.names 16575 16576 +1 1 +.names 1050 16577 +0 1 +.names 16577 16578 +1 1 +.names 16578 16579 +0 1 +.names 16452 16580 +1 1 +.names 16580 16581 +0 1 +.names 16579 16581 16582 +11 1 +.names 16765 16793 16583 +1- 1 +-1 1 +.names 16583 16584 +1 1 +.names 16584 16585 +0 1 +.names 16668 16586 +0 1 +.names 16586 16587 +1 1 +.names 16587 16588 +0 1 +.names 16419 16589 +0 1 +.names 16588 16589 16590 +11 1 +.names 1058 16591 +0 1 +.names 16591 16592 +1 1 +.names 16592 16593 +0 1 +.names 16587 16593 16594 +11 1 +.names 16597 16595 +0 1 +.names 16595 16596 +1 1 +.names 1014 1053 16597 +01 1 +10 1 +.names 16596 16598 +1 1 +.names 16606 16609 16599 +1- 1 +-1 1 +.names 16599 16600 +1 1 +.names 16598 16601 +0 1 +.names 16713 16602 +0 1 +.names 16602 16603 +1 1 +.names 16603 16604 +0 1 +.names 16601 16604 16605 +1- 1 +-1 1 +.names 16605 16345 16606 +1- 1 +-1 1 +.names 16670 16607 +0 1 +.names 16607 16608 +1 1 +.names 16608 16609 +0 1 +.names 16631 16610 +0 1 +.names 16610 16611 +1 1 +.names 16600 16612 +0 1 +.names 16612 16613 +1 1 +.names 16611 16613 16614 +11 1 +.names 16919 16634 16615 +11 1 +.names 16615 16616 +1 1 +.names 16619 16617 +0 1 +.names 16617 16618 +1 1 +.names 1054 1015 16619 +01 1 +10 1 +.names 16622 16620 +0 1 +.names 16620 16621 +1 1 +.names 1055 1017 16622 +01 1 +10 1 +.names 1020 1056 16623 +01 1 +10 1 +.names 16623 16624 +1 1 +.names 16629 16610 16625 +11 1 +.names 16625 16626 +1 1 +.names 16712 16604 16627 +1- 1 +-1 1 +.names 16627 16628 +1 1 +.names 16628 16629 +0 1 +.names 16684 16685 16630 +1- 1 +-1 1 +.names 16630 16631 +1 1 +.names 16573 16632 +0 1 +.names 16632 16633 +1 1 +.names 16633 16634 +0 1 +.names 1055 16635 +0 1 +.names 16634 16635 16636 +11 1 +.names 16832 16637 +0 1 +.names 16637 16638 +1 1 +.names 16638 16639 +0 1 +.names 16633 16639 16640 +11 1 +.names 16633 16641 +1 1 +.names 16626 16511 16642 +11 1 +.names 16513 16643 +0 1 +.names 16643 16644 +1 1 +.names 1048 16645 +0 1 +.names 16645 16646 +1 1 +.names 1053 16647 +0 1 +.names 16647 16648 +1 1 +.names 16648 16649 +0 1 +.names 16611 16650 +0 1 +.names 16613 16651 +0 1 +.names 16650 16651 16652 +1- 1 +-1 1 +.names 16511 16653 +0 1 +.names 16658 16659 16654 +1- 1 +-1 1 +.names 16654 16655 +1 1 +.names 16618 16656 +0 1 +.names 1054 16657 +1 1 +.names 16656 16657 16658 +11 1 +.names 16618 1056 16659 +11 1 +.names 16601 16344 16660 +1- 1 +-1 1 +.names 16343 16661 +0 1 +.names 1046 16662 +0 1 +.names 16662 16663 +1 1 +.names 16447 16664 +0 1 +.names 16664 16665 +1 1 +.names 16665 16666 +0 1 +.names 16576 16667 +0 1 +.names 16607 16668 +1 1 +.names 1058 1023 16669 +01 1 +10 1 +.names 16669 16670 +1 1 +.names 16414 16695 16671 +1- 1 +-1 1 +.names 16671 16672 +1 1 +.names 16672 16673 +0 1 +.names 16698 16695 16674 +1- 1 +-1 1 +.names 16674 16675 +1 1 +.names 16675 16676 +0 1 +.names 16673 16676 16677 +1- 1 +-1 1 +.names 16795 16796 16678 +11 1 +.names 16678 16679 +1 1 +.names 16679 16680 +0 1 +.names 16624 16681 +0 1 +.names 16681 16682 +1 1 +.names 16682 16683 +0 1 +.names 16683 16656 16684 +1- 1 +-1 1 +.names 16621 16685 +0 1 +.names 16641 16650 16686 +1- 1 +-1 1 +.names 16686 16687 +1 1 +.names 16588 16589 16688 +11 1 +.names 16587 16593 16689 +11 1 +.names 16693 16694 16690 +1- 1 +-1 1 +.names 16690 16691 +1 1 +.names 1059 16692 +0 1 +.names 16692 16693 +1 1 +.names 16515 16694 +0 1 +.names 16526 16695 +0 1 +.names 16691 16696 +0 1 +.names 16696 16697 +1 1 +.names 16697 16698 +0 1 +.names 16561 16699 +0 1 +.names 16405 16699 16700 +1- 1 +-1 1 +.names 16568 16571 16701 +11 1 +.names 16701 16702 +1 1 +.names 1047 16703 +0 1 +.names 16703 16704 +1 1 +.names 16704 16705 +0 1 +.names 16568 16705 16706 +11 1 +.names 1057 16707 +0 1 +.names 16707 16708 +1 1 +.names 16708 16709 +0 1 +.names 16567 16709 16710 +11 1 +.names 16601 16609 16711 +1- 1 +-1 1 +.names 16711 16345 16712 +1- 1 +-1 1 +.names 996 1044 16713 +01 1 +10 1 +.names 2413 16714 +1 1 +.names 2413 16715 +1 1 +.names 16844 16848 16716 +1- 1 +-1 1 +.names 16716 16717 +1 1 +.names 2413 16718 +1 1 +.names 2413 16723 16719 +1- 1 +-1 1 +.names 16719 16720 +1 1 +.names 16721 +.names 16721 16722 +1 1 +.names 16722 16723 +0 1 +.names 16732 16735 16724 +1- 1 +-1 1 +.names 16724 16725 +1 1 +.names 16740 16726 +0 1 +.names 16726 16727 +1 1 +.names 16727 16728 +0 1 +.names 2413 16908 16729 +1- 1 +-1 1 +.names 16729 16730 +1 1 +.names 16730 16731 +0 1 +.names 16728 16731 16732 +11 1 +.names 2413 16733 +1 1 +.names 16733 16734 +0 1 +.names 16727 16734 16735 +11 1 +.names 1783 16805 16736 +01 1 +10 1 +.names 16736 16737 +1 1 +.names 16737 16738 +0 1 +.names 1783 16806 16739 +01 1 +10 1 +.names 16739 16740 +1 1 +.names 16744 16741 +0 1 +.names 16741 16742 +1 1 +.names 2413 16743 +1 1 +.names 16743 1783 16744 +01 1 +10 1 +.names 16742 16745 +0 1 +.names 16745 16746 +1 1 +.names 16723 16747 +1 1 +.names 16718 1783 16748 +01 1 +10 1 +.names 16456 16749 +0 1 +.names 16749 16750 +1 1 +.names 16751 +.names 16751 16752 +1 1 +.names 16752 16753 +0 1 +.names 16753 16754 +1 1 +.names 16758 16755 +0 1 +.names 16755 16756 +1 1 +.names 16798 16757 +0 1 +.names 16757 16758 +1 1 +.names 16835 16914 16759 +11 1 +.names 16759 16760 +1 1 +.names 16763 1783 16761 +01 1 +10 1 +.names 16761 16762 +1 1 +.names 2413 16763 +1 1 +.names 16776 16779 16764 +1- 1 +-1 1 +.names 16764 16765 +1 1 +.names 16810 16746 16766 +11 1 +.names 16766 16767 +1 1 +.names 16767 16768 +0 1 +.names 16814 16747 16769 +11 1 +.names 16769 16770 +1 1 +.names 16770 16771 +0 1 +.names 16768 16771 16772 +1- 1 +-1 1 +.names 16824 16754 16773 +11 1 +.names 16773 16774 +1 1 +.names 16774 16775 +0 1 +.names 16772 16775 16776 +1- 1 +-1 1 +.names 16830 16827 16777 +11 1 +.names 16777 16778 +1 1 +.names 16778 16779 +0 1 +.names 16803 16755 16780 +1- 1 +-1 1 +.names 16780 16781 +1 1 +.names 16756 16782 +0 1 +.names 16861 16862 16783 +11 1 +.names 16783 16784 +1 1 +.names 16784 16785 +0 1 +.names 16782 16785 16786 +11 1 +.names 2413 16787 +1 1 +.names 16787 16788 +0 1 +.names 16756 16788 16789 +11 1 +.names 16585 16790 +1 1 +.names 16870 16872 16791 +1- 1 +-1 1 +.names 16791 16792 +1 1 +.names 16792 16793 +0 1 +.names 16687 16794 +0 1 +.names 16794 16383 16795 +11 1 +.names 16790 16796 +0 1 +.names 2413 16797 +1 1 +.names 16798 +.names 16742 16722 16799 +1- 1 +-1 1 +.names 16829 16800 +0 1 +.names 16800 16801 +1 1 +.names 16801 16802 +0 1 +.names 16799 16802 16803 +1- 1 +-1 1 +.names 16738 16804 +1 1 +.names 2413 16805 +1 1 +.names 2413 16806 +1 1 +.names 2413 16807 +1 1 +.names 1783 16807 16808 +01 1 +10 1 +.names 16808 16809 +1 1 +.names 16809 16758 16810 +11 1 +.names 16813 16811 +0 1 +.names 16811 16812 +1 1 +.names 16813 +.names 16750 16812 16814 +11 1 +.names 16818 16815 +0 1 +.names 16815 16816 +1 1 +.names 1783 16819 16817 +01 1 +10 1 +.names 16817 16818 +1 1 +.names 2413 16819 +1 1 +.names 16820 +.names 16820 16821 +1 1 +.names 16821 16822 +0 1 +.names 16822 16823 +1 1 +.names 16823 16818 16824 +11 1 +.names 2413 16825 +1 1 +.names 1783 16825 16826 +01 1 +10 1 +.names 16826 16827 +1 1 +.names 2413 16828 +1 1 +.names 16828 16797 16829 +01 1 +10 1 +.names 16801 16458 16830 +11 1 +.names 1052 16831 +0 1 +.names 16831 16832 +1 1 +.names 16374 16833 +0 1 +.names 16833 16834 +1 1 +.names 16834 16835 +0 1 +.names 16517 16836 +0 1 +.names 16835 16836 16837 +11 1 +.names 16646 16838 +0 1 +.names 16834 16838 16839 +11 1 +.names 16454 16840 +0 1 +.names 16565 16841 +1 1 +.names 16841 16842 +0 1 +.names 16715 16843 +0 1 +.names 16459 16843 16844 +11 1 +.names 16899 16900 16845 +1- 1 +-1 1 +.names 16845 16846 +1 1 +.names 16846 16847 +0 1 +.names 16458 16847 16848 +11 1 +.names 16852 16854 16849 +1- 1 +-1 1 +.names 16849 16850 +1 1 +.names 16720 16851 +0 1 +.names 16745 16851 16852 +11 1 +.names 16743 16853 +0 1 +.names 16742 16853 16854 +11 1 +.names 16857 16860 16855 +11 1 +.names 16855 16856 +1 1 +.names 16828 16857 +0 1 +.names 16876 16877 16858 +1- 1 +-1 1 +.names 16858 16859 +1 1 +.names 16859 16860 +0 1 +.names 16856 16861 +0 1 +.names 16850 16862 +0 1 +.names 16867 16868 16863 +11 1 +.names 16863 16864 +1 1 +.names 16906 16907 16865 +11 1 +.names 16865 16866 +1 1 +.names 16866 16867 +0 1 +.names 16725 16868 +0 1 +.names 16714 16869 +0 1 +.names 16471 16869 16870 +11 1 +.names 16864 16871 +0 1 +.names 16470 16871 16872 +11 1 +.names 16797 16873 +0 1 +.names 16857 16873 16874 +11 1 +.names 16747 16875 +0 1 +.names 16874 16875 16876 +1- 1 +-1 1 +.names 16746 16877 +0 1 +.names 2413 16878 +1 1 +.names 16881 16882 16879 +11 1 +.names 16879 16880 +1 1 +.names 16827 16881 +0 1 +.names 16878 16882 +0 1 +.names 16888 16891 16883 +1- 1 +-1 1 +.names 16883 16884 +1 1 +.names 16816 16885 +0 1 +.names 16911 16910 16886 +11 1 +.names 16886 16887 +1 1 +.names 16885 16887 16888 +11 1 +.names 1783 16827 16889 +11 1 +.names 16889 16890 +1 1 +.names 16816 16890 16891 +11 1 +.names 16884 16892 +0 1 +.names 16880 16893 +0 1 +.names 16896 16897 16894 +1- 1 +-1 1 +.names 16894 16895 +1 1 +.names 16753 1783 16896 +11 1 +.names 16752 1783 16897 +11 1 +.names 16895 16898 +0 1 +.names 16749 16898 16899 +11 1 +.names 16456 2413 16900 +11 1 +.names 2413 16901 +1 1 +.names 16904 16905 16902 +1- 1 +-1 1 +.names 16902 16903 +1 1 +.names 16726 16466 16904 +1- 1 +-1 1 +.names 16804 16905 +0 1 +.names 16903 16906 +0 1 +.names 16901 16907 +0 1 +.names 16763 16908 +0 1 +.names 2413 16909 +1 1 +.names 16909 16910 +1 1 +.names 16827 1783 16911 +11 1 +.names 16685 16912 +1 1 +.names 16912 16913 +0 1 +.names 16479 16914 +0 1 +.names 16914 16835 16915 +11 1 +.names 16915 16916 +1 1 +.names 16916 16917 +0 1 +.names 16702 16918 +0 1 +.names 16917 16918 16919 +1- 1 +-1 1 +.names 16350 16920 +0 1 +.names 16600 16920 16921 +1- 1 +-1 1 +.names 15169 16924 16922 +1- 1 +-1 1 +.names 16922 16923 +1 1 +.names 1060 16924 +0 1 +.names 16928 16925 +0 1 +.names 16925 16926 +1 1 +.names 16949 16927 +0 1 +.names 16927 16928 +1 1 +.names 16933 16936 16929 +1- 1 +-1 1 +.names 16929 16930 +1 1 +.names 16942 16945 16931 +1- 1 +-1 1 +.names 16931 16932 +1 1 +.names 16932 16933 +0 1 +.names 16984 16937 16934 +1- 1 +-1 1 +.names 16934 16935 +1 1 +.names 16935 16936 +0 1 +.names 16947 16937 +0 1 +.names 16937 16938 +1 1 +.names 16938 16939 +0 1 +.names 15766 16940 +1 1 +.names 16940 16941 +0 1 +.names 16939 16941 16942 +11 1 +.names 15770 16943 +1 1 +.names 16943 16944 +0 1 +.names 16938 16944 16945 +11 1 +.names 16948 16946 +0 1 +.names 16946 16947 +1 1 +.names 999 1061 16948 +01 1 +10 1 +.names 1062 1000 16949 +01 1 +10 1 +.names 16952 16950 +0 1 +.names 16950 16951 +1 1 +.names 1063 1002 16952 +01 1 +10 1 +.names 16955 16953 +0 1 +.names 16953 16954 +1 1 +.names 1064 1004 16955 +01 1 +10 1 +.names 16959 16956 +0 1 +.names 16956 16957 +1 1 +.names 17011 17014 16958 +1- 1 +-1 1 +.names 16958 16959 +1 1 +.names 16962 16965 16960 +1- 1 +-1 1 +.names 16960 16961 +1 1 +.names 16957 16962 +0 1 +.names 1065 1007 16963 +01 1 +10 1 +.names 16963 16964 +1 1 +.names 16964 16965 +0 1 +.names 16970 16973 16966 +11 1 +.names 16966 16967 +1 1 +.names 16978 16982 16968 +1- 1 +-1 1 +.names 16968 16969 +1 1 +.names 16969 16970 +0 1 +.names 17256 16971 +0 1 +.names 16971 16972 +1 1 +.names 16972 16973 +0 1 +.names 16926 16974 +0 1 +.names 17044 17045 16975 +1- 1 +-1 1 +.names 16975 16976 +1 1 +.names 16976 16977 +0 1 +.names 16974 16977 16978 +11 1 +.names 17471 17043 16979 +1- 1 +-1 1 +.names 16979 16980 +1 1 +.names 16980 16981 +0 1 +.names 16926 16981 16982 +11 1 +.names 1027 1075 16983 +01 1 +10 1 +.names 16983 16984 +1 1 +.names 16988 16991 16985 +1- 1 +-1 1 +.names 16985 16986 +1 1 +.names 1065 1007 16987 +01 1 +10 1 +.names 16987 16988 +1 1 +.names 17174 17176 16989 +11 1 +.names 16989 16990 +1 1 +.names 16990 16991 +0 1 +.names 16999 17002 16992 +1- 1 +-1 1 +.names 16992 16993 +1 1 +.names 17324 16994 +0 1 +.names 16994 16995 +1 1 +.names 17295 1783 16996 +01 1 +10 1 +.names 16996 16997 +1 1 +.names 16997 16998 +0 1 +.names 16995 16998 16999 +1- 1 +-1 1 +.names 17434 17329 17000 +11 1 +.names 17000 17001 +1 1 +.names 17001 17002 +0 1 +.names 17299 17302 17003 +1- 1 +-1 1 +.names 17003 17004 +1 1 +.names 17341 17005 +0 1 +.names 17005 17006 +1 1 +.names 17004 17006 17007 +1- 1 +-1 1 +.names 17294 1783 17008 +01 1 +10 1 +.names 17008 17009 +1 1 +.names 17009 17010 +0 1 +.names 17007 17010 17011 +1- 1 +-1 1 +.names 17344 17012 +0 1 +.names 17012 17013 +1 1 +.names 17013 17014 +0 1 +.names 17022 17025 17015 +1- 1 +-1 1 +.names 17015 17016 +1 1 +.names 17027 17017 +0 1 +.names 17017 17018 +1 1 +.names 17063 17066 17019 +11 1 +.names 17019 17020 +1 1 +.names 17020 17021 +0 1 +.names 17018 17021 17022 +1- 1 +-1 1 +.names 16954 17068 17023 +11 1 +.names 17023 17024 +1 1 +.names 17024 17025 +0 1 +.names 17028 17026 +0 1 +.names 17026 17027 +1 1 +.names 1066 1009 17028 +01 1 +10 1 +.names 17016 17029 +0 1 +.names 17029 17030 +1 1 +.names 16959 17034 17031 +1- 1 +-1 1 +.names 17031 17032 +1 1 +.names 1026 1074 17033 +01 1 +10 1 +.names 17033 17034 +1 1 +.names 17038 17035 +0 1 +.names 17035 17036 +1 1 +.names 17188 17189 17037 +1- 1 +-1 1 +.names 17037 17038 +1 1 +.names 16986 17039 +0 1 +.names 15868 17040 +1 1 +.names 17071 17041 +1 1 +.names 17041 17042 +1 1 +.names 17042 17043 +0 1 +.names 15169 17043 17044 +1- 1 +-1 1 +.names 16923 17045 +0 1 +.names 17048 17049 17046 +1- 1 +-1 1 +.names 17046 17047 +1 1 +.names 15877 17048 +1 1 +.names 17034 17049 +0 1 +.names 17054 17056 17050 +1- 1 +-1 1 +.names 17050 17051 +1 1 +.names 17047 17052 +0 1 +.names 17052 17053 +1 1 +.names 17053 17054 +0 1 +.names 17035 17055 +1 1 +.names 17055 17056 +0 1 +.names 17060 17057 +0 1 +.names 17057 17058 +1 1 +.names 17267 17077 17059 +1- 1 +-1 1 +.names 17059 17060 +1 1 +.names 1022 1072 17061 +01 1 +10 1 +.names 17061 17062 +1 1 +.names 17062 17063 +0 1 +.names 16951 17064 +0 1 +.names 17064 17065 +1 1 +.names 17065 17066 +0 1 +.names 17069 17067 +0 1 +.names 17067 17068 +1 1 +.names 1012 1067 17069 +01 1 +10 1 +.names 16991 17070 +1 1 +.names 17072 17071 +0 1 +.names 1014 1068 17072 +01 1 +10 1 +.names 17079 17082 17073 +1- 1 +-1 1 +.names 17073 17074 +1 1 +.names 17272 17075 +0 1 +.names 17075 17076 +1 1 +.names 17076 17077 +0 1 +.names 17043 17077 17078 +1- 1 +-1 1 +.names 17078 16925 17079 +1- 1 +-1 1 +.names 17250 17080 +0 1 +.names 17080 17081 +1 1 +.names 17081 17082 +0 1 +.names 17089 17091 17083 +11 1 +.names 17083 17084 +1 1 +.names 17137 17085 +0 1 +.names 17085 17086 +1 1 +.names 17074 17087 +0 1 +.names 17087 17088 +1 1 +.names 17086 17088 17089 +11 1 +.names 17501 17502 17090 +11 1 +.names 17090 17091 +1 1 +.names 17102 16956 17092 +11 1 +.names 17092 17093 +1 1 +.names 17109 17112 17094 +11 1 +.names 17094 17095 +1 1 +.names 17095 17096 +0 1 +.names 17236 17237 17097 +1- 1 +-1 1 +.names 17097 17098 +1 1 +.names 17098 17099 +0 1 +.names 17096 17099 17100 +1- 1 +-1 1 +.names 17051 17101 +0 1 +.names 17100 17101 17102 +1- 1 +-1 1 +.names 17186 17103 +0 1 +.names 17103 17104 +1 1 +.names 17104 17105 +0 1 +.names 17172 17173 17106 +1- 1 +-1 1 +.names 17106 17107 +1 1 +.names 17107 17108 +0 1 +.names 17105 17108 17109 +1- 1 +-1 1 +.names 17252 17254 17110 +1- 1 +-1 1 +.names 17110 17111 +1 1 +.names 17111 17112 +0 1 +.names 17117 17108 17113 +11 1 +.names 17113 17114 +1 1 +.names 17444 17445 17115 +1- 1 +-1 1 +.names 17115 17116 +1 1 +.names 17116 17117 +0 1 +.names 17122 17125 17118 +11 1 +.names 17118 17119 +1 1 +.names 17271 17101 17120 +1- 1 +-1 1 +.names 17120 17121 +1 1 +.names 17121 17122 +0 1 +.names 17247 17248 17123 +1- 1 +-1 1 +.names 17123 17124 +1 1 +.names 17124 17125 +0 1 +.names 17128 17126 +0 1 +.names 17126 17127 +1 1 +.names 1069 1015 17128 +01 1 +10 1 +.names 17131 17129 +0 1 +.names 17129 17130 +1 1 +.names 1070 1017 17131 +01 1 +10 1 +.names 1020 1071 17132 +01 1 +10 1 +.names 17132 17133 +1 1 +.names 17057 17085 17134 +11 1 +.names 17134 17135 +1 1 +.names 17221 17147 17136 +1- 1 +-1 1 +.names 17136 17137 +1 1 +.names 1015 17138 +1 1 +.names 17143 17144 17139 +1- 1 +-1 1 +.names 17139 17140 +1 1 +.names 17127 17141 +0 1 +.names 17138 17142 +0 1 +.names 17141 17142 17143 +11 1 +.names 17127 15974 17144 +11 1 +.names 17151 17154 17145 +1- 1 +-1 1 +.names 17145 17146 +1 1 +.names 17130 17147 +0 1 +.names 17147 17148 +1 1 +.names 17148 17149 +0 1 +.names 17140 17150 +0 1 +.names 17149 17150 17151 +11 1 +.names 15983 17152 +1 1 +.names 17152 17153 +0 1 +.names 17148 17153 17154 +11 1 +.names 17157 17155 +1 1 +.names 17155 17156 +1 1 +.names 17068 17157 +0 1 +.names 15990 17158 +1 1 +.names 17161 17162 17159 +11 1 +.names 17159 17160 +1 1 +.names 17086 17161 +0 1 +.names 17156 17162 +0 1 +.names 17165 17166 17163 +1- 1 +-1 1 +.names 17163 17164 +1 1 +.names 17146 17165 +0 1 +.names 17160 17166 +0 1 +.names 17162 17171 17167 +1- 1 +-1 1 +.names 17167 17168 +1 1 +.names 17158 17169 +0 1 +.names 17169 17170 +1 1 +.names 17170 17171 +0 1 +.names 17164 17172 +0 1 +.names 17168 17173 +0 1 +.names 17135 17030 17174 +11 1 +.names 17032 17175 +0 1 +.names 17175 17176 +1 1 +.names 17180 17183 17177 +11 1 +.names 17177 17178 +1 1 +.names 17039 17179 +1 1 +.names 17179 17180 +0 1 +.names 17336 17337 17181 +1- 1 +-1 1 +.names 17181 17182 +1 1 +.names 17182 17183 +0 1 +.names 1014 17184 +1 1 +.names 17058 17185 +0 1 +.names 17185 17186 +1 1 +.names 17088 17187 +0 1 +.names 17161 17187 17188 +1- 1 +-1 1 +.names 17030 17189 +0 1 +.names 17198 17201 17190 +11 1 +.names 17190 17191 +1 1 +.names 17333 17192 +0 1 +.names 17192 17193 +1 1 +.names 17193 17194 +0 1 +.names 17070 17195 +0 1 +.names 17195 17196 +1 1 +.names 17196 17197 +0 1 +.names 17194 17197 17198 +1- 1 +-1 1 +.names 17279 17282 17199 +1- 1 +-1 1 +.names 17199 17200 +1 1 +.names 17200 17201 +0 1 +.names 17204 17205 17202 +1- 1 +-1 1 +.names 17202 17203 +1 1 +.names 17191 17204 +0 1 +.names 17178 17205 +0 1 +.names 17203 17206 +0 1 +.names 17206 17207 +1 1 +.names 17207 17208 +0 1 +.names 17093 17209 +0 1 +.names 17209 17210 +1 1 +.names 17210 17211 +0 1 +.names 17208 17211 17212 +1- 1 +-1 1 +.names 17119 17213 +0 1 +.names 17216 17217 17214 +1- 1 +-1 1 +.names 17214 17215 +1 1 +.names 17082 17040 17216 +11 1 +.names 17081 16967 17217 +11 1 +.names 17133 17218 +0 1 +.names 17218 17219 +1 1 +.names 17219 17220 +0 1 +.names 17220 17141 17221 +1- 1 +-1 1 +.names 17230 17233 17222 +1- 1 +-1 1 +.names 17222 17223 +1 1 +.names 17339 17224 +0 1 +.names 17224 17225 +1 1 +.names 17225 17226 +0 1 +.names 17262 17265 17227 +1- 1 +-1 1 +.names 17227 17228 +1 1 +.names 17228 17229 +0 1 +.names 17226 17229 17230 +11 1 +.names 17414 17416 17231 +1- 1 +-1 1 +.names 17231 17232 +1 1 +.names 17232 17233 +0 1 +.names 17223 17234 +0 1 +.names 17234 17235 +1 1 +.names 17235 17236 +0 1 +.names 17084 17237 +0 1 +.names 17241 17243 17238 +11 1 +.names 17238 17239 +1 1 +.names 17344 17406 17240 +1- 1 +-1 1 +.names 17240 17241 +1 1 +.names 17386 17387 17242 +1- 1 +-1 1 +.names 17242 17243 +1 1 +.names 17114 17244 +0 1 +.names 17244 17099 17245 +1- 1 +-1 1 +.names 17215 17246 +0 1 +.names 17245 17246 17247 +1- 1 +-1 1 +.names 17239 17248 +0 1 +.names 1073 1023 17249 +01 1 +10 1 +.names 17249 17250 +1 1 +.names 16967 17251 +0 1 +.names 17080 17251 17252 +11 1 +.names 17040 17253 +0 1 +.names 17250 17253 17254 +11 1 +.names 17042 17257 17255 +1- 1 +-1 1 +.names 17255 17256 +1 1 +.names 17184 17257 +0 1 +.names 17063 17066 17258 +11 1 +.names 17258 17259 +1 1 +.names 16093 17260 +1 1 +.names 17260 17261 +0 1 +.names 17063 17261 17262 +11 1 +.names 16097 17263 +1 1 +.names 17263 17264 +0 1 +.names 17062 17264 17265 +11 1 +.names 17043 17082 17266 +1- 1 +-1 1 +.names 17266 16925 17267 +1- 1 +-1 1 +.names 16961 17270 17268 +1- 1 +-1 1 +.names 17268 17269 +1 1 +.names 17036 17270 +0 1 +.names 17269 17271 +0 1 +.names 996 1060 17272 +01 1 +10 1 +.names 17332 17273 +0 1 +.names 17273 17274 +1 1 +.names 17274 17275 +0 1 +.names 17376 17377 17276 +11 1 +.names 17276 17277 +1 1 +.names 17277 17278 +0 1 +.names 17275 17278 17279 +11 1 +.names 2413 17280 +1 1 +.names 17280 17281 +0 1 +.names 17274 17281 17282 +11 1 +.names 17201 17283 +1 1 +.names 17291 17293 17284 +1- 1 +-1 1 +.names 17284 17285 +1 1 +.names 17424 17286 +0 1 +.names 17286 17287 +1 1 +.names 17287 17288 +0 1 +.names 17485 17486 17289 +11 1 +.names 17289 17290 +1 1 +.names 17288 17290 17291 +11 1 +.names 2413 17292 +1 1 +.names 17287 17292 17293 +11 1 +.names 2413 17294 +1 1 +.names 2413 17295 +1 1 +.names 2413 17296 +1 1 +.names 1783 17418 17297 +01 1 +10 1 +.names 17297 17298 +1 1 +.names 17298 17299 +0 1 +.names 1783 17311 17300 +01 1 +10 1 +.names 17300 17301 +1 1 +.names 17301 17302 +0 1 +.names 17310 17313 17303 +1- 1 +-1 1 +.names 17303 17304 +1 1 +.names 17302 17305 +1 1 +.names 17305 17306 +0 1 +.names 2413 17492 17307 +1- 1 +-1 1 +.names 17307 17308 +1 1 +.names 17308 17309 +0 1 +.names 17306 17309 17310 +11 1 +.names 2413 17311 +1 1 +.names 17311 17312 +0 1 +.names 17305 17312 17313 +11 1 +.names 17317 17314 +0 1 +.names 17314 17315 +1 1 +.names 2413 17316 +1 1 +.names 17316 1783 17317 +01 1 +10 1 +.names 17315 17318 +0 1 +.names 17318 17319 +1 1 +.names 17320 +.names 17320 17321 +1 1 +.names 17321 17322 +0 1 +.names 17322 17323 +1 1 +.names 17296 1783 17324 +01 1 +10 1 +.names 16995 17325 +0 1 +.names 17325 17326 +1 1 +.names 17327 +.names 17327 17328 +1 1 +.names 17328 17329 +0 1 +.names 17329 17330 +1 1 +.names 17378 17331 +0 1 +.names 17331 17332 +1 1 +.names 16168 17333 +1 1 +.names 17395 17396 17334 +1- 1 +-1 1 +.names 17334 17335 +1 1 +.names 17335 17336 +0 1 +.names 17241 17337 +0 1 +.names 17412 17496 17338 +11 1 +.names 17338 17339 +1 1 +.names 17342 1783 17340 +01 1 +10 1 +.names 17340 17341 +1 1 +.names 2413 17342 +1 1 +.names 17355 17358 17343 +1- 1 +-1 1 +.names 17343 17344 +1 1 +.names 17422 17319 17345 +11 1 +.names 17345 17346 +1 1 +.names 17346 17347 +0 1 +.names 17426 17323 17348 +11 1 +.names 17348 17349 +1 1 +.names 17349 17350 +0 1 +.names 17347 17350 17351 +1- 1 +-1 1 +.names 17436 17330 17352 +11 1 +.names 17352 17353 +1 1 +.names 17353 17354 +0 1 +.names 17351 17354 17355 +1- 1 +-1 1 +.names 17442 17439 17356 +11 1 +.names 17356 17357 +1 1 +.names 17357 17358 +0 1 +.names 17362 17359 +0 1 +.names 17359 17360 +1 1 +.names 17383 17273 17361 +1- 1 +-1 1 +.names 17361 17362 +1 1 +.names 2413 17363 +1 1 +.names 17368 17369 17364 +11 1 +.names 17364 17365 +1 1 +.names 17449 17450 17366 +1- 1 +-1 1 +.names 17366 17367 +1 1 +.names 17367 17368 +0 1 +.names 17363 17369 +0 1 +.names 17374 17375 17370 +1- 1 +-1 1 +.names 17370 17371 +1 1 +.names 1783 17321 17372 +11 1 +.names 17372 17373 +1 1 +.names 17318 17373 17374 +11 1 +.names 17315 1783 17375 +11 1 +.names 17371 17376 +0 1 +.names 17365 17377 +0 1 +.names 17378 +.names 17315 17321 17379 +1- 1 +-1 1 +.names 17441 17380 +0 1 +.names 17380 17381 +1 1 +.names 17381 17382 +0 1 +.names 17379 17382 17383 +1- 1 +-1 1 +.names 17460 17462 17384 +1- 1 +-1 1 +.names 17384 17385 +1 1 +.names 17385 17386 +0 1 +.names 16993 17387 +0 1 +.names 17243 17388 +0 1 +.names 17388 17389 +1 1 +.names 17392 17387 17390 +11 1 +.names 17390 17391 +1 1 +.names 17285 17392 +0 1 +.names 17391 17393 +0 1 +.names 17389 17394 +0 1 +.names 17393 17394 17395 +11 1 +.names 17360 17396 +0 1 +.names 2413 17397 +1 1 +.names 17401 17405 17398 +1- 1 +-1 1 +.names 17398 17399 +1 1 +.names 17397 17400 +0 1 +.names 17010 17400 17401 +11 1 +.names 17469 17470 17402 +11 1 +.names 17402 17403 +1 1 +.names 17403 17404 +0 1 +.names 17009 17404 17405 +11 1 +.names 17399 17406 +0 1 +.names 16243 17407 +1 1 +.names 16247 17017 17408 +11 1 +.names 17408 17409 +1 1 +.names 16954 17410 +0 1 +.names 17410 17411 +1 1 +.names 17411 17412 +0 1 +.names 17409 17413 +0 1 +.names 17412 17413 17414 +11 1 +.names 17407 17415 +0 1 +.names 17411 17415 17416 +11 1 +.names 17299 17417 +1 1 +.names 2413 17418 +1 1 +.names 2413 17419 +1 1 +.names 1783 17419 17420 +01 1 +10 1 +.names 17420 17421 +1 1 +.names 17421 17332 17422 +11 1 +.names 17425 17423 +0 1 +.names 17423 17424 +1 1 +.names 17425 +.names 17326 17424 17426 +11 1 +.names 17430 17427 +0 1 +.names 17427 17428 +1 1 +.names 1783 17431 17429 +01 1 +10 1 +.names 17429 17430 +1 1 +.names 2413 17431 +1 1 +.names 17432 +.names 17432 17433 +1 1 +.names 17433 17434 +0 1 +.names 17434 17435 +1 1 +.names 17435 17430 17436 +11 1 +.names 2413 17437 +1 1 +.names 1783 17437 17438 +01 1 +10 1 +.names 17438 17439 +1 1 +.names 2413 17440 +1 1 +.names 17440 17363 17441 +01 1 +10 1 +.names 17381 16997 17442 +11 1 +.names 16930 17443 +0 1 +.names 17392 17443 17444 +1- 1 +-1 1 +.names 17283 17445 +0 1 +.names 17440 17446 +0 1 +.names 17446 17369 17447 +11 1 +.names 17323 17448 +0 1 +.names 17447 17448 17449 +1- 1 +-1 1 +.names 17319 17450 +0 1 +.names 17456 17457 17451 +1- 1 +-1 1 +.names 17451 17452 +1 1 +.names 17489 17490 17453 +1- 1 +-1 1 +.names 17453 17454 +1 1 +.names 17454 17455 +0 1 +.names 17325 17455 17456 +11 1 +.names 16995 2413 17457 +11 1 +.names 2413 17458 +1 1 +.names 17458 17459 +0 1 +.names 16998 17459 17460 +11 1 +.names 17452 17461 +0 1 +.names 16997 17461 17462 +11 1 +.names 17465 17468 17463 +11 1 +.names 17463 17464 +1 1 +.names 17418 17465 +0 1 +.names 17487 17488 17466 +1- 1 +-1 1 +.names 17466 17467 +1 1 +.names 17467 17468 +0 1 +.names 17464 17469 +0 1 +.names 17304 17470 +0 1 +.names 16309 17471 +1 1 +.names 17474 17475 17472 +11 1 +.names 17472 17473 +1 1 +.names 17439 17474 +0 1 +.names 17437 17475 +0 1 +.names 17481 17484 17476 +1- 1 +-1 1 +.names 17476 17477 +1 1 +.names 17428 17478 +0 1 +.names 17495 17494 17479 +11 1 +.names 17479 17480 +1 1 +.names 17478 17480 17481 +11 1 +.names 1783 17439 17482 +11 1 +.names 17482 17483 +1 1 +.names 17428 17483 17484 +11 1 +.names 17477 17485 +0 1 +.names 17473 17486 +0 1 +.names 17302 17005 17487 +1- 1 +-1 1 +.names 17417 17488 +0 1 +.names 17329 1783 17489 +11 1 +.names 17328 1783 17490 +11 1 +.names 2413 17491 +1 1 +.names 17491 17492 +0 1 +.names 2413 17493 +1 1 +.names 17493 17494 +1 1 +.names 17439 1783 17495 +11 1 +.names 17018 17496 +0 1 +.names 17496 17412 17497 +11 1 +.names 17497 17498 +1 1 +.names 17498 17499 +0 1 +.names 17259 17500 +0 1 +.names 17499 17500 17501 +1- 1 +-1 1 +.names 17155 17502 +0 1 +.names 17505 15170 17503 +1- 1 +-1 1 +.names 17503 17504 +1 1 +.names 1076 17505 +0 1 +.names 17509 17506 +0 1 +.names 17506 17507 +1 1 +.names 17530 17508 +0 1 +.names 17508 17509 +1 1 +.names 17518 17522 17510 +1- 1 +-1 1 +.names 17510 17511 +1 1 +.names 17790 18061 17512 +11 1 +.names 17512 17513 +1 1 +.names 17513 17514 +0 1 +.names 17791 17795 17515 +1- 1 +-1 1 +.names 17515 17516 +1 1 +.names 17516 17517 +0 1 +.names 17514 17517 17518 +11 1 +.names 17808 17519 +0 1 +.names 17519 17520 +1 1 +.names 17520 17521 +0 1 +.names 17513 17521 17522 +11 1 +.names 17526 17523 +0 1 +.names 17523 17524 +1 1 +.names 17935 17938 17525 +1- 1 +-1 1 +.names 17525 17526 +1 1 +.names 17529 17527 +0 1 +.names 17527 17528 +1 1 +.names 1077 998 17529 +01 1 +10 1 +.names 1001 1078 17530 +01 1 +10 1 +.names 17533 17531 +0 1 +.names 17531 17532 +1 1 +.names 1003 1079 17533 +01 1 +10 1 +.names 17536 17534 +0 1 +.names 17534 17535 +1 1 +.names 1005 1080 17536 +01 1 +10 1 +.names 17545 17548 17537 +1- 1 +-1 1 +.names 17537 17538 +1 1 +.names 17988 17990 17539 +11 1 +.names 17539 17540 +1 1 +.names 17540 17541 +0 1 +.names 17866 17613 17542 +11 1 +.names 17542 17543 +1 1 +.names 17543 17544 +0 1 +.names 17541 17544 17545 +11 1 +.names 17930 17546 +0 1 +.names 17546 17547 +1 1 +.names 17547 17548 +0 1 +.names 17552 17549 +0 1 +.names 17549 17550 +1 1 +.names 17631 17634 17551 +1- 1 +-1 1 +.names 17551 17552 +1 1 +.names 17559 17562 17553 +11 1 +.names 17553 17554 +1 1 +.names 17701 17702 17555 +1- 1 +-1 1 +.names 17555 17556 +1 1 +.names 17556 17557 +0 1 +.names 17550 17558 +0 1 +.names 17557 17558 17559 +1- 1 +-1 1 +.names 17563 17564 17560 +1- 1 +-1 1 +.names 17560 17561 +1 1 +.names 17561 17562 +0 1 +.names 17538 17563 +0 1 +.names 17524 17564 +0 1 +.names 17573 17564 17565 +1- 1 +-1 1 +.names 17565 17566 +1 1 +.names 17602 17567 +0 1 +.names 17567 17568 +1 1 +.names 17568 17569 +0 1 +.names 17599 17600 17570 +1- 1 +-1 1 +.names 17570 17571 +1 1 +.names 17571 17572 +0 1 +.names 17569 17572 17573 +11 1 +.names 17558 17578 17574 +1- 1 +-1 1 +.names 17574 17575 +1 1 +.names 1008 1081 17576 +01 1 +10 1 +.names 17576 17577 +1 1 +.names 17577 17578 +0 1 +.names 17583 17586 17579 +11 1 +.names 17579 17580 +1 1 +.names 17591 17595 17581 +1- 1 +-1 1 +.names 17581 17582 +1 1 +.names 17582 17583 +0 1 +.names 17757 17802 17584 +11 1 +.names 17584 17585 +1 1 +.names 17585 17586 +0 1 +.names 17507 17587 +0 1 +.names 17813 17814 17588 +1- 1 +-1 1 +.names 17588 17589 +1 1 +.names 17589 17590 +0 1 +.names 17587 17590 17591 +11 1 +.names 17815 17757 17592 +1- 1 +-1 1 +.names 17592 17593 +1 1 +.names 17593 17594 +0 1 +.names 17507 17594 17595 +11 1 +.names 17528 17596 +0 1 +.names 17596 17597 +1 1 +.names 17597 17598 +0 1 +.names 17598 15264 17599 +11 1 +.names 17597 15266 17600 +11 1 +.names 17604 17596 17601 +1- 1 +-1 1 +.names 17601 17602 +1 1 +.names 1091 1006 17603 +01 1 +10 1 +.names 17603 17604 +1 1 +.names 17608 17611 17605 +1- 1 +-1 1 +.names 17605 17606 +1 1 +.names 1008 1081 17607 +01 1 +10 1 +.names 17607 17608 +1 1 +.names 17797 17799 17609 +11 1 +.names 17609 17610 +1 1 +.names 17610 17611 +0 1 +.names 17619 17622 17612 +1- 1 +-1 1 +.names 17612 17613 +1 1 +.names 17897 17614 +0 1 +.names 17614 17615 +1 1 +.names 17864 1783 17616 +01 1 +10 1 +.names 17616 17617 +1 1 +.names 17617 17618 +0 1 +.names 17615 17618 17619 +1- 1 +-1 1 +.names 17971 17902 17620 +11 1 +.names 17620 17621 +1 1 +.names 17621 17622 +0 1 +.names 17887 17875 17623 +1- 1 +-1 1 +.names 17623 17624 +1 1 +.names 17911 17625 +0 1 +.names 17625 17626 +1 1 +.names 17624 17626 17627 +1- 1 +-1 1 +.names 17863 1783 17628 +01 1 +10 1 +.names 17628 17629 +1 1 +.names 17629 17630 +0 1 +.names 17627 17630 17631 +1- 1 +-1 1 +.names 17914 17632 +0 1 +.names 17632 17633 +1 1 +.names 17633 17634 +0 1 +.names 17642 17645 17635 +1- 1 +-1 1 +.names 17635 17636 +1 1 +.names 17659 17637 +0 1 +.names 17637 17638 +1 1 +.names 17726 17729 17639 +11 1 +.names 17639 17640 +1 1 +.names 17640 17641 +0 1 +.names 17638 17641 17642 +1- 1 +-1 1 +.names 17535 17731 17643 +11 1 +.names 17643 17644 +1 1 +.names 17644 17645 +0 1 +.names 17654 17657 17646 +1- 1 +-1 1 +.names 17646 17647 +1 1 +.names 17961 17648 +0 1 +.names 17648 17649 +1 1 +.names 17649 17650 +0 1 +.names 18040 18041 17651 +11 1 +.names 17651 17652 +1 1 +.names 17652 17653 +0 1 +.names 17650 17653 17654 +11 1 +.names 2413 17655 +1 1 +.names 17655 17656 +0 1 +.names 17649 17656 17657 +11 1 +.names 17660 17658 +0 1 +.names 17658 17659 +1 1 +.names 1010 1082 17660 +01 1 +10 1 +.names 17665 17668 17661 +11 1 +.names 17661 17662 +1 1 +.names 17829 17832 17663 +1- 1 +-1 1 +.names 17663 17664 +1 1 +.names 17664 17665 +0 1 +.names 17851 17700 17666 +1- 1 +-1 1 +.names 17666 17667 +1 1 +.names 17667 17668 +0 1 +.names 17636 17669 +0 1 +.names 17669 17670 +1 1 +.names 17552 17674 17671 +1- 1 +-1 1 +.names 17671 17672 +1 1 +.names 1090 1025 17673 +01 1 +10 1 +.names 17673 17674 +1 1 +.names 15344 17637 17675 +11 1 +.names 17675 17676 +1 1 +.names 17554 17677 +0 1 +.names 17818 17819 17678 +11 1 +.names 17678 17679 +1 1 +.names 17679 17680 +0 1 +.names 17677 17680 17681 +1- 1 +-1 1 +.names 17662 17682 +0 1 +.names 17686 17683 +0 1 +.names 17683 17684 +1 1 +.names 17805 17806 17685 +1- 1 +-1 1 +.names 17685 17686 +1 1 +.names 17690 17687 +0 1 +.names 17687 17688 +1 1 +.names 17747 17750 17689 +1- 1 +-1 1 +.names 17689 17690 +1 1 +.names 18069 17943 17691 +1- 1 +-1 1 +.names 17691 17692 +1 1 +.names 17692 17693 +0 1 +.names 17846 17849 17694 +1- 1 +-1 1 +.names 17694 17695 +1 1 +.names 17695 17696 +0 1 +.names 17693 17696 17697 +1- 1 +-1 1 +.names 17704 17717 17698 +1- 1 +-1 1 +.names 17698 17699 +1 1 +.names 17699 17700 +0 1 +.names 17697 17700 17701 +1- 1 +-1 1 +.names 17688 17702 +0 1 +.names 17711 17714 17703 +1- 1 +-1 1 +.names 17703 17704 +1 1 +.names 17909 17705 +0 1 +.names 17705 17706 +1 1 +.names 17706 17707 +0 1 +.names 17856 17859 17708 +1- 1 +-1 1 +.names 17708 17709 +1 1 +.names 17709 17710 +0 1 +.names 17707 17710 17711 +11 1 +.names 17985 17987 17712 +1- 1 +-1 1 +.names 17712 17713 +1 1 +.names 17713 17714 +0 1 +.names 17770 17772 17715 +11 1 +.names 17715 17716 +1 1 +.names 17716 17717 +0 1 +.names 17722 17723 17718 +11 1 +.names 17718 17719 +1 1 +.names 17840 17841 17720 +1- 1 +-1 1 +.names 17720 17721 +1 1 +.names 17721 17722 +0 1 +.names 17647 17723 +0 1 +.names 1088 1021 17724 +01 1 +10 1 +.names 17724 17725 +1 1 +.names 17725 17726 +0 1 +.names 17532 17727 +0 1 +.names 17727 17728 +1 1 +.names 17728 17729 +0 1 +.names 17732 17730 +0 1 +.names 17730 17731 +1 1 +.names 1083 1011 17732 +01 1 +10 1 +.names 17739 17742 17733 +1- 1 +-1 1 +.names 17733 17734 +1 1 +.names 15403 17735 +1 1 +.names 17735 17736 +0 1 +.names 17611 17737 +1 1 +.names 17737 17738 +0 1 +.names 17736 17738 17739 +11 1 +.names 17914 17942 17740 +1- 1 +-1 1 +.names 17740 17741 +1 1 +.names 17741 17742 +0 1 +.names 17820 17743 +0 1 +.names 17743 17744 +1 1 +.names 17744 17745 +0 1 +.names 17580 17746 +0 1 +.names 17745 17746 17747 +11 1 +.names 15417 17748 +1 1 +.names 17748 17749 +0 1 +.names 17744 17749 17750 +11 1 +.names 17753 17751 +0 1 +.names 17751 17752 +1 1 +.names 1084 1013 17753 +01 1 +10 1 +.names 17752 17754 +1 1 +.names 17762 17765 17755 +1- 1 +-1 1 +.names 17755 17756 +1 1 +.names 17754 17757 +0 1 +.names 17862 17758 +0 1 +.names 17758 17759 +1 1 +.names 17759 17760 +0 1 +.names 17757 17760 17761 +1- 1 +-1 1 +.names 17761 17506 17762 +1- 1 +-1 1 +.names 17822 17763 +0 1 +.names 17763 17764 +1 1 +.names 17764 17765 +0 1 +.names 17787 17766 +0 1 +.names 17766 17767 +1 1 +.names 17756 17768 +0 1 +.names 17768 17769 +1 1 +.names 17767 17769 17770 +11 1 +.names 18067 17790 17771 +11 1 +.names 17771 17772 +1 1 +.names 17775 17773 +0 1 +.names 17773 17774 +1 1 +.names 1016 1085 17775 +01 1 +10 1 +.names 17778 17776 +0 1 +.names 17776 17777 +1 1 +.names 1018 1086 17778 +01 1 +10 1 +.names 1087 1019 17779 +01 1 +10 1 +.names 17779 17780 +1 1 +.names 17785 17766 17781 +11 1 +.names 17781 17782 +1 1 +.names 17861 17760 17783 +1- 1 +-1 1 +.names 17783 17784 +1 1 +.names 17784 17785 +0 1 +.names 17836 17837 17786 +1- 1 +-1 1 +.names 17786 17787 +1 1 +.names 17731 17788 +0 1 +.names 17788 17789 +1 1 +.names 17789 17790 +0 1 +.names 17790 15461 17791 +11 1 +.names 17980 17792 +0 1 +.names 17792 17793 +1 1 +.names 17793 17794 +0 1 +.names 17789 17794 17795 +11 1 +.names 17789 17796 +1 1 +.names 17782 17670 17797 +11 1 +.names 17672 17798 +0 1 +.names 17798 17799 +1 1 +.names 15471 17800 +1 1 +.names 15473 17801 +1 1 +.names 17801 17802 +0 1 +.names 17767 17803 +0 1 +.names 17769 17804 +0 1 +.names 17803 17804 17805 +1- 1 +-1 1 +.names 17670 17806 +0 1 +.names 17811 17812 17807 +1- 1 +-1 1 +.names 17807 17808 +1 1 +.names 17774 17809 +0 1 +.names 1016 17810 +1 1 +.names 17809 17810 17811 +11 1 +.names 17774 1019 17812 +11 1 +.names 17757 15170 17813 +1- 1 +-1 1 +.names 17504 17814 +0 1 +.names 15488 17815 +1 1 +.names 17606 17816 +0 1 +.names 17816 17817 +1 1 +.names 17817 17818 +0 1 +.names 17734 17819 +0 1 +.names 17763 17820 +1 1 +.names 1024 1089 17821 +01 1 +10 1 +.names 17821 17822 +1 1 +.names 17575 17846 17823 +1- 1 +-1 1 +.names 17823 17824 +1 1 +.names 17824 17825 +0 1 +.names 17849 17846 17826 +1- 1 +-1 1 +.names 17826 17827 +1 1 +.names 17827 17828 +0 1 +.names 17825 17828 17829 +1- 1 +-1 1 +.names 17944 17945 17830 +11 1 +.names 17830 17831 +1 1 +.names 17831 17832 +0 1 +.names 17780 17833 +0 1 +.names 17833 17834 +1 1 +.names 17834 17835 +0 1 +.names 17835 17809 17836 +1- 1 +-1 1 +.names 17777 17837 +0 1 +.names 17796 17803 17838 +1- 1 +-1 1 +.names 17838 17839 +1 1 +.names 17745 17746 17840 +11 1 +.names 17744 17749 17841 +11 1 +.names 17844 17845 17842 +1- 1 +-1 1 +.names 17842 17843 +1 1 +.names 15518 17844 +1 1 +.names 17674 17845 +0 1 +.names 17684 17846 +0 1 +.names 17843 17847 +0 1 +.names 17847 17848 +1 1 +.names 17848 17849 +0 1 +.names 17719 17850 +0 1 +.names 17566 17850 17851 +1- 1 +-1 1 +.names 17726 17729 17852 +11 1 +.names 17852 17853 +1 1 +.names 15529 17854 +1 1 +.names 17854 17855 +0 1 +.names 17726 17855 17856 +11 1 +.names 15533 17857 +1 1 +.names 17857 17858 +0 1 +.names 17725 17858 17859 +11 1 +.names 17757 17765 17860 +1- 1 +-1 1 +.names 17860 17506 17861 +1- 1 +-1 1 +.names 1076 997 17862 +01 1 +10 1 +.names 2413 17863 +1 1 +.names 2413 17864 +1 1 +.names 17992 17996 17865 +1- 1 +-1 1 +.names 17865 17866 +1 1 +.names 2413 17867 +1 1 +.names 2413 17872 17868 +1- 1 +-1 1 +.names 17868 17869 +1 1 +.names 17870 +.names 17870 17871 +1 1 +.names 17871 17872 +0 1 +.names 17881 17884 17873 +1- 1 +-1 1 +.names 17873 17874 +1 1 +.names 17889 17875 +0 1 +.names 17875 17876 +1 1 +.names 17876 17877 +0 1 +.names 2413 18056 17878 +1- 1 +-1 1 +.names 17878 17879 +1 1 +.names 17879 17880 +0 1 +.names 17877 17880 17881 +11 1 +.names 2413 17882 +1 1 +.names 17882 17883 +0 1 +.names 17876 17883 17884 +11 1 +.names 1783 17954 17885 +01 1 +10 1 +.names 17885 17886 +1 1 +.names 17886 17887 +0 1 +.names 1783 17955 17888 +01 1 +10 1 +.names 17888 17889 +1 1 +.names 17893 17890 +0 1 +.names 17890 17891 +1 1 +.names 2413 17892 +1 1 +.names 17892 1783 17893 +01 1 +10 1 +.names 17891 17894 +0 1 +.names 17894 17895 +1 1 +.names 17872 17896 +1 1 +.names 17867 1783 17897 +01 1 +10 1 +.names 17615 17898 +0 1 +.names 17898 17899 +1 1 +.names 17900 +.names 17900 17901 +1 1 +.names 17901 17902 +0 1 +.names 17902 17903 +1 1 +.names 17907 17904 +0 1 +.names 17904 17905 +1 1 +.names 17947 17906 +0 1 +.names 17906 17907 +1 1 +.names 17983 18062 17908 +11 1 +.names 17908 17909 +1 1 +.names 17912 1783 17910 +01 1 +10 1 +.names 17910 17911 +1 1 +.names 2413 17912 +1 1 +.names 17925 17928 17913 +1- 1 +-1 1 +.names 17913 17914 +1 1 +.names 17959 17895 17915 +11 1 +.names 17915 17916 +1 1 +.names 17916 17917 +0 1 +.names 17963 17896 17918 +11 1 +.names 17918 17919 +1 1 +.names 17919 17920 +0 1 +.names 17917 17920 17921 +1- 1 +-1 1 +.names 17973 17903 17922 +11 1 +.names 17922 17923 +1 1 +.names 17923 17924 +0 1 +.names 17921 17924 17925 +1- 1 +-1 1 +.names 17979 17976 17926 +11 1 +.names 17926 17927 +1 1 +.names 17927 17928 +0 1 +.names 17952 17904 17929 +1- 1 +-1 1 +.names 17929 17930 +1 1 +.names 17905 17931 +0 1 +.names 18009 18010 17932 +11 1 +.names 17932 17933 +1 1 +.names 17933 17934 +0 1 +.names 17931 17934 17935 +11 1 +.names 2413 17936 +1 1 +.names 17936 17937 +0 1 +.names 17905 17937 17938 +11 1 +.names 17742 17939 +1 1 +.names 18018 18020 17940 +1- 1 +-1 1 +.names 17940 17941 +1 1 +.names 17941 17942 +0 1 +.names 17839 17943 +0 1 +.names 17943 17544 17944 +11 1 +.names 17939 17945 +0 1 +.names 2413 17946 +1 1 +.names 17947 +.names 17891 17871 17948 +1- 1 +-1 1 +.names 17978 17949 +0 1 +.names 17949 17950 +1 1 +.names 17950 17951 +0 1 +.names 17948 17951 17952 +1- 1 +-1 1 +.names 17887 17953 +1 1 +.names 2413 17954 +1 1 +.names 2413 17955 +1 1 +.names 2413 17956 +1 1 +.names 1783 17956 17957 +01 1 +10 1 +.names 17957 17958 +1 1 +.names 17958 17907 17959 +11 1 +.names 17962 17960 +0 1 +.names 17960 17961 +1 1 +.names 17962 +.names 17899 17961 17963 +11 1 +.names 17967 17964 +0 1 +.names 17964 17965 +1 1 +.names 1783 17968 17966 +01 1 +10 1 +.names 17966 17967 +1 1 +.names 2413 17968 +1 1 +.names 17969 +.names 17969 17970 +1 1 +.names 17970 17971 +0 1 +.names 17971 17972 +1 1 +.names 17972 17967 17973 +11 1 +.names 2413 17974 +1 1 +.names 1783 17974 17975 +01 1 +10 1 +.names 17975 17976 +1 1 +.names 2413 17977 +1 1 +.names 17977 17946 17978 +01 1 +10 1 +.names 17950 17617 17979 +11 1 +.names 15657 17980 +1 1 +.names 17535 17981 +0 1 +.names 17981 17982 +1 1 +.names 17982 17983 +0 1 +.names 17676 17984 +0 1 +.names 17983 17984 17985 +11 1 +.names 17800 17986 +0 1 +.names 17982 17986 17987 +11 1 +.names 17613 17988 +0 1 +.names 17723 17989 +1 1 +.names 17989 17990 +0 1 +.names 17864 17991 +0 1 +.names 17618 17991 17992 +11 1 +.names 18047 18048 17993 +1- 1 +-1 1 +.names 17993 17994 +1 1 +.names 17994 17995 +0 1 +.names 17617 17995 17996 +11 1 +.names 18000 18002 17997 +1- 1 +-1 1 +.names 17997 17998 +1 1 +.names 17869 17999 +0 1 +.names 17894 17999 18000 +11 1 +.names 17892 18001 +0 1 +.names 17891 18001 18002 +11 1 +.names 18005 18008 18003 +11 1 +.names 18003 18004 +1 1 +.names 17977 18005 +0 1 +.names 18024 18025 18006 +1- 1 +-1 1 +.names 18006 18007 +1 1 +.names 18007 18008 +0 1 +.names 18004 18009 +0 1 +.names 17998 18010 +0 1 +.names 18015 18016 18011 +11 1 +.names 18011 18012 +1 1 +.names 18054 18055 18013 +11 1 +.names 18013 18014 +1 1 +.names 18014 18015 +0 1 +.names 17874 18016 +0 1 +.names 17863 18017 +0 1 +.names 17630 18017 18018 +11 1 +.names 18012 18019 +0 1 +.names 17629 18019 18020 +11 1 +.names 17946 18021 +0 1 +.names 18005 18021 18022 +11 1 +.names 17896 18023 +0 1 +.names 18022 18023 18024 +1- 1 +-1 1 +.names 17895 18025 +0 1 +.names 2413 18026 +1 1 +.names 18029 18030 18027 +11 1 +.names 18027 18028 +1 1 +.names 17976 18029 +0 1 +.names 18026 18030 +0 1 +.names 18036 18039 18031 +1- 1 +-1 1 +.names 18031 18032 +1 1 +.names 17965 18033 +0 1 +.names 18059 18058 18034 +11 1 +.names 18034 18035 +1 1 +.names 18033 18035 18036 +11 1 +.names 1783 17976 18037 +11 1 +.names 18037 18038 +1 1 +.names 17965 18038 18039 +11 1 +.names 18032 18040 +0 1 +.names 18028 18041 +0 1 +.names 18044 18045 18042 +1- 1 +-1 1 +.names 18042 18043 +1 1 +.names 17902 1783 18044 +11 1 +.names 17901 1783 18045 +11 1 +.names 18043 18046 +0 1 +.names 17898 18046 18047 +11 1 +.names 17615 2413 18048 +11 1 +.names 2413 18049 +1 1 +.names 18052 18053 18050 +1- 1 +-1 1 +.names 18050 18051 +1 1 +.names 17875 17625 18052 +1- 1 +-1 1 +.names 17953 18053 +0 1 +.names 18051 18054 +0 1 +.names 18049 18055 +0 1 +.names 17912 18056 +0 1 +.names 2413 18057 +1 1 +.names 18057 18058 +1 1 +.names 17976 1783 18059 +11 1 +.names 17837 18060 +1 1 +.names 18060 18061 +0 1 +.names 17638 18062 +0 1 +.names 18062 17983 18063 +11 1 +.names 18063 18064 +1 1 +.names 18064 18065 +0 1 +.names 17853 18066 +0 1 +.names 18065 18066 18067 +1- 1 +-1 1 +.names 17511 18068 +0 1 +.names 17756 18068 18069 +1- 1 +-1 1 +.names 17505 15750 18070 +1- 1 +-1 1 +.names 18070 18071 +1 1 +.names 18075 18072 +0 1 +.names 18072 18073 +1 1 +.names 18098 18074 +0 1 +.names 18074 18075 +1 1 +.names 18080 18083 18076 +1- 1 +-1 1 +.names 18076 18077 +1 1 +.names 18090 18094 18078 +1- 1 +-1 1 +.names 18078 18079 +1 1 +.names 18079 18080 +0 1 +.names 18133 18084 18081 +1- 1 +-1 1 +.names 18081 18082 +1 1 +.names 18082 18083 +0 1 +.names 18096 18084 +0 1 +.names 18084 18085 +1 1 +.names 18085 18086 +0 1 +.names 1091 18087 +0 1 +.names 18087 18088 +1 1 +.names 18088 18089 +0 1 +.names 18086 18089 18090 +11 1 +.names 1077 18091 +0 1 +.names 18091 18092 +1 1 +.names 18092 18093 +0 1 +.names 18085 18093 18094 +11 1 +.names 18097 18095 +0 1 +.names 18095 18096 +1 1 +.names 1077 1029 18097 +01 1 +10 1 +.names 1030 1078 18098 +01 1 +10 1 +.names 18101 18099 +0 1 +.names 18099 18100 +1 1 +.names 1031 1079 18101 +01 1 +10 1 +.names 18104 18102 +0 1 +.names 18102 18103 +1 1 +.names 1032 1080 18104 +01 1 +10 1 +.names 18108 18105 +0 1 +.names 18105 18106 +1 1 +.names 18160 18163 18107 +1- 1 +-1 1 +.names 18107 18108 +1 1 +.names 18111 18114 18109 +1- 1 +-1 1 +.names 18109 18110 +1 1 +.names 18106 18111 +0 1 +.names 1033 1081 18112 +01 1 +10 1 +.names 18112 18113 +1 1 +.names 18113 18114 +0 1 +.names 18119 18122 18115 +11 1 +.names 18115 18116 +1 1 +.names 18127 18131 18117 +1- 1 +-1 1 +.names 18117 18118 +1 1 +.names 18118 18119 +0 1 +.names 18410 18120 +0 1 +.names 18120 18121 +1 1 +.names 18121 18122 +0 1 +.names 18073 18123 +0 1 +.names 18194 18195 18124 +1- 1 +-1 1 +.names 18124 18125 +1 1 +.names 18125 18126 +0 1 +.names 18123 18126 18127 +11 1 +.names 18631 18193 18128 +1- 1 +-1 1 +.names 18128 18129 +1 1 +.names 18129 18130 +0 1 +.names 18073 18130 18131 +11 1 +.names 1091 1043 18132 +01 1 +10 1 +.names 18132 18133 +1 1 +.names 18137 18140 18134 +1- 1 +-1 1 +.names 18134 18135 +1 1 +.names 1033 1081 18136 +01 1 +10 1 +.names 18136 18137 +1 1 +.names 18328 18330 18138 +11 1 +.names 18138 18139 +1 1 +.names 18139 18140 +0 1 +.names 18148 18151 18141 +1- 1 +-1 1 +.names 18141 18142 +1 1 +.names 18480 18143 +0 1 +.names 18143 18144 +1 1 +.names 18451 1783 18145 +01 1 +10 1 +.names 18145 18146 +1 1 +.names 18146 18147 +0 1 +.names 18144 18147 18148 +1- 1 +-1 1 +.names 18593 18485 18149 +11 1 +.names 18149 18150 +1 1 +.names 18150 18151 +0 1 +.names 18455 18458 18152 +1- 1 +-1 1 +.names 18152 18153 +1 1 +.names 18498 18154 +0 1 +.names 18154 18155 +1 1 +.names 18153 18155 18156 +1- 1 +-1 1 +.names 18450 1783 18157 +01 1 +10 1 +.names 18157 18158 +1 1 +.names 18158 18159 +0 1 +.names 18156 18159 18160 +1- 1 +-1 1 +.names 18501 18161 +0 1 +.names 18161 18162 +1 1 +.names 18162 18163 +0 1 +.names 18171 18174 18164 +1- 1 +-1 1 +.names 18164 18165 +1 1 +.names 18176 18166 +0 1 +.names 18166 18167 +1 1 +.names 18214 18217 18168 +11 1 +.names 18168 18169 +1 1 +.names 18169 18170 +0 1 +.names 18167 18170 18171 +1- 1 +-1 1 +.names 18103 18219 18172 +11 1 +.names 18172 18173 +1 1 +.names 18173 18174 +0 1 +.names 18177 18175 +0 1 +.names 18175 18176 +1 1 +.names 1034 1082 18177 +01 1 +10 1 +.names 18165 18178 +0 1 +.names 18178 18179 +1 1 +.names 18108 18183 18180 +1- 1 +-1 1 +.names 18180 18181 +1 1 +.names 1090 1042 18182 +01 1 +10 1 +.names 18182 18183 +1 1 +.names 18187 18184 +0 1 +.names 18184 18185 +1 1 +.names 18342 18343 18186 +1- 1 +-1 1 +.names 18186 18187 +1 1 +.names 18135 18188 +0 1 +.names 1089 18189 +0 1 +.names 18189 18190 +1 1 +.names 18222 18191 +1 1 +.names 18191 18192 +1 1 +.names 18192 18193 +0 1 +.names 17505 18193 18194 +1- 1 +-1 1 +.names 18071 18195 +0 1 +.names 18199 18200 18196 +1- 1 +-1 1 +.names 18196 18197 +1 1 +.names 1090 18198 +0 1 +.names 18198 18199 +1 1 +.names 18183 18200 +0 1 +.names 18205 18207 18201 +1- 1 +-1 1 +.names 18201 18202 +1 1 +.names 18197 18203 +0 1 +.names 18203 18204 +1 1 +.names 18204 18205 +0 1 +.names 18184 18206 +1 1 +.names 18206 18207 +0 1 +.names 18211 18208 +0 1 +.names 18208 18209 +1 1 +.names 18423 18228 18210 +1- 1 +-1 1 +.names 18210 18211 +1 1 +.names 1088 1040 18212 +01 1 +10 1 +.names 18212 18213 +1 1 +.names 18213 18214 +0 1 +.names 18100 18215 +0 1 +.names 18215 18216 +1 1 +.names 18216 18217 +0 1 +.names 18220 18218 +0 1 +.names 18218 18219 +1 1 +.names 1083 1035 18220 +01 1 +10 1 +.names 18140 18221 +1 1 +.names 18223 18222 +0 1 +.names 1084 1036 18223 +01 1 +10 1 +.names 18230 18233 18224 +1- 1 +-1 1 +.names 18224 18225 +1 1 +.names 18428 18226 +0 1 +.names 18226 18227 +1 1 +.names 18227 18228 +0 1 +.names 18193 18228 18229 +1- 1 +-1 1 +.names 18229 18072 18230 +1- 1 +-1 1 +.names 18404 18231 +0 1 +.names 18231 18232 +1 1 +.names 18232 18233 +0 1 +.names 18240 18242 18234 +11 1 +.names 18234 18235 +1 1 +.names 18288 18236 +0 1 +.names 18236 18237 +1 1 +.names 18225 18238 +0 1 +.names 18238 18239 +1 1 +.names 18237 18239 18240 +11 1 +.names 18661 18662 18241 +11 1 +.names 18241 18242 +1 1 +.names 18253 18105 18243 +11 1 +.names 18243 18244 +1 1 +.names 18260 18263 18245 +11 1 +.names 18245 18246 +1 1 +.names 18246 18247 +0 1 +.names 18390 18391 18248 +1- 1 +-1 1 +.names 18248 18249 +1 1 +.names 18249 18250 +0 1 +.names 18247 18250 18251 +1- 1 +-1 1 +.names 18202 18252 +0 1 +.names 18251 18252 18253 +1- 1 +-1 1 +.names 18340 18254 +0 1 +.names 18254 18255 +1 1 +.names 18255 18256 +0 1 +.names 18326 18327 18257 +1- 1 +-1 1 +.names 18257 18258 +1 1 +.names 18258 18259 +0 1 +.names 18256 18259 18260 +1- 1 +-1 1 +.names 18406 18408 18261 +1- 1 +-1 1 +.names 18261 18262 +1 1 +.names 18262 18263 +0 1 +.names 18268 18259 18264 +11 1 +.names 18264 18265 +1 1 +.names 18603 18604 18266 +1- 1 +-1 1 +.names 18266 18267 +1 1 +.names 18267 18268 +0 1 +.names 18273 18276 18269 +11 1 +.names 18269 18270 +1 1 +.names 18427 18252 18271 +1- 1 +-1 1 +.names 18271 18272 +1 1 +.names 18272 18273 +0 1 +.names 18401 18402 18274 +1- 1 +-1 1 +.names 18274 18275 +1 1 +.names 18275 18276 +0 1 +.names 18279 18277 +0 1 +.names 18277 18278 +1 1 +.names 1037 1085 18279 +01 1 +10 1 +.names 18282 18280 +0 1 +.names 18280 18281 +1 1 +.names 1038 1086 18282 +01 1 +10 1 +.names 1087 1039 18283 +01 1 +10 1 +.names 18283 18284 +1 1 +.names 18208 18236 18285 +11 1 +.names 18285 18286 +1 1 +.names 18375 18299 18287 +1- 1 +-1 1 +.names 18287 18288 +1 1 +.names 1085 18289 +1 1 +.names 18294 18296 18290 +1- 1 +-1 1 +.names 18290 18291 +1 1 +.names 18278 18292 +0 1 +.names 18289 18293 +0 1 +.names 18292 18293 18294 +11 1 +.names 1087 18295 +0 1 +.names 18278 18295 18296 +11 1 +.names 18303 18307 18297 +1- 1 +-1 1 +.names 18297 18298 +1 1 +.names 18281 18299 +0 1 +.names 18299 18300 +1 1 +.names 18300 18301 +0 1 +.names 18291 18302 +0 1 +.names 18301 18302 18303 +11 1 +.names 1086 18304 +0 1 +.names 18304 18305 +1 1 +.names 18305 18306 +0 1 +.names 18300 18306 18307 +11 1 +.names 18310 18308 +1 1 +.names 18308 18309 +1 1 +.names 18219 18310 +0 1 +.names 1083 18311 +0 1 +.names 18311 18312 +1 1 +.names 18315 18316 18313 +11 1 +.names 18313 18314 +1 1 +.names 18237 18315 +0 1 +.names 18309 18316 +0 1 +.names 18319 18320 18317 +1- 1 +-1 1 +.names 18317 18318 +1 1 +.names 18298 18319 +0 1 +.names 18314 18320 +0 1 +.names 18316 18325 18321 +1- 1 +-1 1 +.names 18321 18322 +1 1 +.names 18312 18323 +0 1 +.names 18323 18324 +1 1 +.names 18324 18325 +0 1 +.names 18318 18326 +0 1 +.names 18322 18327 +0 1 +.names 18286 18179 18328 +11 1 +.names 18181 18329 +0 1 +.names 18329 18330 +1 1 +.names 18334 18337 18331 +11 1 +.names 18331 18332 +1 1 +.names 18188 18333 +1 1 +.names 18333 18334 +0 1 +.names 18493 18494 18335 +1- 1 +-1 1 +.names 18335 18336 +1 1 +.names 18336 18337 +0 1 +.names 1084 18338 +1 1 +.names 18209 18339 +0 1 +.names 18339 18340 +1 1 +.names 18239 18341 +0 1 +.names 18315 18341 18342 +1- 1 +-1 1 +.names 18179 18343 +0 1 +.names 18352 18355 18344 +11 1 +.names 18344 18345 +1 1 +.names 18490 18346 +0 1 +.names 18346 18347 +1 1 +.names 18347 18348 +0 1 +.names 18221 18349 +0 1 +.names 18349 18350 +1 1 +.names 18350 18351 +0 1 +.names 18348 18351 18352 +1- 1 +-1 1 +.names 18435 18438 18353 +1- 1 +-1 1 +.names 18353 18354 +1 1 +.names 18354 18355 +0 1 +.names 18358 18359 18356 +1- 1 +-1 1 +.names 18356 18357 +1 1 +.names 18345 18358 +0 1 +.names 18332 18359 +0 1 +.names 18357 18360 +0 1 +.names 18360 18361 +1 1 +.names 18361 18362 +0 1 +.names 18244 18363 +0 1 +.names 18363 18364 +1 1 +.names 18364 18365 +0 1 +.names 18362 18365 18366 +1- 1 +-1 1 +.names 18270 18367 +0 1 +.names 18370 18371 18368 +1- 1 +-1 1 +.names 18368 18369 +1 1 +.names 18233 18190 18370 +11 1 +.names 18232 18116 18371 +11 1 +.names 18284 18372 +0 1 +.names 18372 18373 +1 1 +.names 18373 18374 +0 1 +.names 18374 18292 18375 +1- 1 +-1 1 +.names 18384 18387 18376 +1- 1 +-1 1 +.names 18376 18377 +1 1 +.names 18496 18378 +0 1 +.names 18378 18379 +1 1 +.names 18379 18380 +0 1 +.names 18417 18421 18381 +1- 1 +-1 1 +.names 18381 18382 +1 1 +.names 18382 18383 +0 1 +.names 18380 18383 18384 +11 1 +.names 18573 18575 18385 +1- 1 +-1 1 +.names 18385 18386 +1 1 +.names 18386 18387 +0 1 +.names 18377 18388 +0 1 +.names 18388 18389 +1 1 +.names 18389 18390 +0 1 +.names 18235 18391 +0 1 +.names 18395 18397 18392 +11 1 +.names 18392 18393 +1 1 +.names 18501 18563 18394 +1- 1 +-1 1 +.names 18394 18395 +1 1 +.names 18543 18544 18396 +1- 1 +-1 1 +.names 18396 18397 +1 1 +.names 18265 18398 +0 1 +.names 18398 18250 18399 +1- 1 +-1 1 +.names 18369 18400 +0 1 +.names 18399 18400 18401 +1- 1 +-1 1 +.names 18393 18402 +0 1 +.names 1041 1089 18403 +01 1 +10 1 +.names 18403 18404 +1 1 +.names 18116 18405 +0 1 +.names 18231 18405 18406 +11 1 +.names 18190 18407 +0 1 +.names 18404 18407 18408 +11 1 +.names 18192 18411 18409 +1- 1 +-1 1 +.names 18409 18410 +1 1 +.names 18338 18411 +0 1 +.names 18214 18217 18412 +11 1 +.names 18412 18413 +1 1 +.names 1079 18414 +0 1 +.names 18414 18415 +1 1 +.names 18415 18416 +0 1 +.names 18214 18416 18417 +11 1 +.names 1088 18418 +0 1 +.names 18418 18419 +1 1 +.names 18419 18420 +0 1 +.names 18213 18420 18421 +11 1 +.names 18193 18233 18422 +1- 1 +-1 1 +.names 18422 18072 18423 +1- 1 +-1 1 +.names 18110 18426 18424 +1- 1 +-1 1 +.names 18424 18425 +1 1 +.names 18185 18426 +0 1 +.names 18425 18427 +0 1 +.names 1076 1028 18428 +01 1 +10 1 +.names 18488 18429 +0 1 +.names 18429 18430 +1 1 +.names 18430 18431 +0 1 +.names 18533 18534 18432 +11 1 +.names 18432 18433 +1 1 +.names 18433 18434 +0 1 +.names 18431 18434 18435 +11 1 +.names 2413 18436 +1 1 +.names 18436 18437 +0 1 +.names 18430 18437 18438 +11 1 +.names 18355 18439 +1 1 +.names 18447 18449 18440 +1- 1 +-1 1 +.names 18440 18441 +1 1 +.names 18583 18442 +0 1 +.names 18442 18443 +1 1 +.names 18443 18444 +0 1 +.names 18645 18646 18445 +11 1 +.names 18445 18446 +1 1 +.names 18444 18446 18447 +11 1 +.names 2413 18448 +1 1 +.names 18443 18448 18449 +11 1 +.names 2413 18450 +1 1 +.names 2413 18451 +1 1 +.names 2413 18452 +1 1 +.names 1783 18577 18453 +01 1 +10 1 +.names 18453 18454 +1 1 +.names 18454 18455 +0 1 +.names 1783 18467 18456 +01 1 +10 1 +.names 18456 18457 +1 1 +.names 18457 18458 +0 1 +.names 18466 18469 18459 +1- 1 +-1 1 +.names 18459 18460 +1 1 +.names 18458 18461 +1 1 +.names 18461 18462 +0 1 +.names 2413 18652 18463 +1- 1 +-1 1 +.names 18463 18464 +1 1 +.names 18464 18465 +0 1 +.names 18462 18465 18466 +11 1 +.names 2413 18467 +1 1 +.names 18467 18468 +0 1 +.names 18461 18468 18469 +11 1 +.names 18473 18470 +0 1 +.names 18470 18471 +1 1 +.names 2413 18472 +1 1 +.names 18472 1783 18473 +01 1 +10 1 +.names 18471 18474 +0 1 +.names 18474 18475 +1 1 +.names 18476 +.names 18476 18477 +1 1 +.names 18477 18478 +0 1 +.names 18478 18479 +1 1 +.names 18452 1783 18480 +01 1 +10 1 +.names 18144 18481 +0 1 +.names 18481 18482 +1 1 +.names 18483 +.names 18483 18484 +1 1 +.names 18484 18485 +0 1 +.names 18485 18486 +1 1 +.names 18535 18487 +0 1 +.names 18487 18488 +1 1 +.names 1081 18489 +0 1 +.names 18489 18490 +1 1 +.names 18552 18553 18491 +1- 1 +-1 1 +.names 18491 18492 +1 1 +.names 18492 18493 +0 1 +.names 18395 18494 +0 1 +.names 18571 18656 18495 +11 1 +.names 18495 18496 +1 1 +.names 18499 1783 18497 +01 1 +10 1 +.names 18497 18498 +1 1 +.names 2413 18499 +1 1 +.names 18512 18515 18500 +1- 1 +-1 1 +.names 18500 18501 +1 1 +.names 18581 18475 18502 +11 1 +.names 18502 18503 +1 1 +.names 18503 18504 +0 1 +.names 18585 18479 18505 +11 1 +.names 18505 18506 +1 1 +.names 18506 18507 +0 1 +.names 18504 18507 18508 +1- 1 +-1 1 +.names 18595 18486 18509 +11 1 +.names 18509 18510 +1 1 +.names 18510 18511 +0 1 +.names 18508 18511 18512 +1- 1 +-1 1 +.names 18601 18598 18513 +11 1 +.names 18513 18514 +1 1 +.names 18514 18515 +0 1 +.names 18519 18516 +0 1 +.names 18516 18517 +1 1 +.names 18540 18429 18518 +1- 1 +-1 1 +.names 18518 18519 +1 1 +.names 2413 18520 +1 1 +.names 18525 18526 18521 +11 1 +.names 18521 18522 +1 1 +.names 18608 18609 18523 +1- 1 +-1 1 +.names 18523 18524 +1 1 +.names 18524 18525 +0 1 +.names 18520 18526 +0 1 +.names 18531 18532 18527 +1- 1 +-1 1 +.names 18527 18528 +1 1 +.names 1783 18477 18529 +11 1 +.names 18529 18530 +1 1 +.names 18474 18530 18531 +11 1 +.names 18471 1783 18532 +11 1 +.names 18528 18533 +0 1 +.names 18522 18534 +0 1 +.names 18535 +.names 18471 18477 18536 +1- 1 +-1 1 +.names 18600 18537 +0 1 +.names 18537 18538 +1 1 +.names 18538 18539 +0 1 +.names 18536 18539 18540 +1- 1 +-1 1 +.names 18619 18621 18541 +1- 1 +-1 1 +.names 18541 18542 +1 1 +.names 18542 18543 +0 1 +.names 18142 18544 +0 1 +.names 18397 18545 +0 1 +.names 18545 18546 +1 1 +.names 18549 18544 18547 +11 1 +.names 18547 18548 +1 1 +.names 18441 18549 +0 1 +.names 18548 18550 +0 1 +.names 18546 18551 +0 1 +.names 18550 18551 18552 +11 1 +.names 18517 18553 +0 1 +.names 2413 18554 +1 1 +.names 18558 18562 18555 +1- 1 +-1 1 +.names 18555 18556 +1 1 +.names 18554 18557 +0 1 +.names 18159 18557 18558 +11 1 +.names 18628 18629 18559 +11 1 +.names 18559 18560 +1 1 +.names 18560 18561 +0 1 +.names 18158 18561 18562 +11 1 +.names 18556 18563 +0 1 +.names 1080 18564 +0 1 +.names 18564 18565 +1 1 +.names 18568 18166 18566 +11 1 +.names 18566 18567 +1 1 +.names 1082 18568 +0 1 +.names 18103 18569 +0 1 +.names 18569 18570 +1 1 +.names 18570 18571 +0 1 +.names 18567 18572 +0 1 +.names 18571 18572 18573 +11 1 +.names 18565 18574 +0 1 +.names 18570 18574 18575 +11 1 +.names 18455 18576 +1 1 +.names 2413 18577 +1 1 +.names 2413 18578 +1 1 +.names 1783 18578 18579 +01 1 +10 1 +.names 18579 18580 +1 1 +.names 18580 18488 18581 +11 1 +.names 18584 18582 +0 1 +.names 18582 18583 +1 1 +.names 18584 +.names 18482 18583 18585 +11 1 +.names 18589 18586 +0 1 +.names 18586 18587 +1 1 +.names 1783 18590 18588 +01 1 +10 1 +.names 18588 18589 +1 1 +.names 2413 18590 +1 1 +.names 18591 +.names 18591 18592 +1 1 +.names 18592 18593 +0 1 +.names 18593 18594 +1 1 +.names 18594 18589 18595 +11 1 +.names 2413 18596 +1 1 +.names 1783 18596 18597 +01 1 +10 1 +.names 18597 18598 +1 1 +.names 2413 18599 +1 1 +.names 18599 18520 18600 +01 1 +10 1 +.names 18538 18146 18601 +11 1 +.names 18077 18602 +0 1 +.names 18549 18602 18603 +1- 1 +-1 1 +.names 18439 18604 +0 1 +.names 18599 18605 +0 1 +.names 18605 18526 18606 +11 1 +.names 18479 18607 +0 1 +.names 18606 18607 18608 +1- 1 +-1 1 +.names 18475 18609 +0 1 +.names 18615 18616 18610 +1- 1 +-1 1 +.names 18610 18611 +1 1 +.names 18649 18650 18612 +1- 1 +-1 1 +.names 18612 18613 +1 1 +.names 18613 18614 +0 1 +.names 18481 18614 18615 +11 1 +.names 18144 2413 18616 +11 1 +.names 2413 18617 +1 1 +.names 18617 18618 +0 1 +.names 18147 18618 18619 +11 1 +.names 18611 18620 +0 1 +.names 18146 18620 18621 +11 1 +.names 18624 18627 18622 +11 1 +.names 18622 18623 +1 1 +.names 18577 18624 +0 1 +.names 18647 18648 18625 +1- 1 +-1 1 +.names 18625 18626 +1 1 +.names 18626 18627 +0 1 +.names 18623 18628 +0 1 +.names 18460 18629 +0 1 +.names 1078 18630 +0 1 +.names 18630 18631 +1 1 +.names 18634 18635 18632 +11 1 +.names 18632 18633 +1 1 +.names 18598 18634 +0 1 +.names 18596 18635 +0 1 +.names 18641 18644 18636 +1- 1 +-1 1 +.names 18636 18637 +1 1 +.names 18587 18638 +0 1 +.names 18655 18654 18639 +11 1 +.names 18639 18640 +1 1 +.names 18638 18640 18641 +11 1 +.names 1783 18598 18642 +11 1 +.names 18642 18643 +1 1 +.names 18587 18643 18644 +11 1 +.names 18637 18645 +0 1 +.names 18633 18646 +0 1 +.names 18458 18154 18647 +1- 1 +-1 1 +.names 18576 18648 +0 1 +.names 18485 1783 18649 +11 1 +.names 18484 1783 18650 +11 1 +.names 2413 18651 +1 1 +.names 18651 18652 +0 1 +.names 2413 18653 +1 1 +.names 18653 18654 +1 1 +.names 18598 1783 18655 +11 1 +.names 18167 18656 +0 1 +.names 18656 18571 18657 +11 1 +.names 18657 18658 +1 1 +.names 18658 18659 +0 1 +.names 18413 18660 +0 1 +.names 18659 18660 18661 +1- 1 +-1 1 +.names 18308 18662 +0 1 +.names 17505 16344 18663 +1- 1 +-1 1 +.names 18663 18664 +1 1 +.names 18668 18665 +0 1 +.names 18665 18666 +1 1 +.names 18689 18667 +0 1 +.names 18667 18668 +1 1 +.names 18677 18681 18669 +1- 1 +-1 1 +.names 18669 18670 +1 1 +.names 18949 19220 18671 +11 1 +.names 18671 18672 +1 1 +.names 18672 18673 +0 1 +.names 18950 18954 18674 +1- 1 +-1 1 +.names 18674 18675 +1 1 +.names 18675 18676 +0 1 +.names 18673 18676 18677 +11 1 +.names 18967 18678 +0 1 +.names 18678 18679 +1 1 +.names 18679 18680 +0 1 +.names 18672 18680 18681 +11 1 +.names 18685 18682 +0 1 +.names 18682 18683 +1 1 +.names 19094 19097 18684 +1- 1 +-1 1 +.names 18684 18685 +1 1 +.names 18688 18686 +0 1 +.names 18686 18687 +1 1 +.names 1077 1045 18688 +01 1 +10 1 +.names 1046 1078 18689 +01 1 +10 1 +.names 18692 18690 +0 1 +.names 18690 18691 +1 1 +.names 1047 1079 18692 +01 1 +10 1 +.names 18695 18693 +0 1 +.names 18693 18694 +1 1 +.names 1048 1080 18695 +01 1 +10 1 +.names 18704 18707 18696 +1- 1 +-1 1 +.names 18696 18697 +1 1 +.names 19147 19149 18698 +11 1 +.names 18698 18699 +1 1 +.names 18699 18700 +0 1 +.names 19025 18772 18701 +11 1 +.names 18701 18702 +1 1 +.names 18702 18703 +0 1 +.names 18700 18703 18704 +11 1 +.names 19089 18705 +0 1 +.names 18705 18706 +1 1 +.names 18706 18707 +0 1 +.names 18711 18708 +0 1 +.names 18708 18709 +1 1 +.names 18790 18793 18710 +1- 1 +-1 1 +.names 18710 18711 +1 1 +.names 18718 18721 18712 +11 1 +.names 18712 18713 +1 1 +.names 18860 18861 18714 +1- 1 +-1 1 +.names 18714 18715 +1 1 +.names 18715 18716 +0 1 +.names 18709 18717 +0 1 +.names 18716 18717 18718 +1- 1 +-1 1 +.names 18722 18723 18719 +1- 1 +-1 1 +.names 18719 18720 +1 1 +.names 18720 18721 +0 1 +.names 18697 18722 +0 1 +.names 18683 18723 +0 1 +.names 18732 18723 18724 +1- 1 +-1 1 +.names 18724 18725 +1 1 +.names 18761 18726 +0 1 +.names 18726 18727 +1 1 +.names 18727 18728 +0 1 +.names 18758 18759 18729 +1- 1 +-1 1 +.names 18729 18730 +1 1 +.names 18730 18731 +0 1 +.names 18728 18731 18732 +11 1 +.names 18717 18737 18733 +1- 1 +-1 1 +.names 18733 18734 +1 1 +.names 1050 1081 18735 +01 1 +10 1 +.names 18735 18736 +1 1 +.names 18736 18737 +0 1 +.names 18742 18745 18738 +11 1 +.names 18738 18739 +1 1 +.names 18750 18754 18740 +1- 1 +-1 1 +.names 18740 18741 +1 1 +.names 18741 18742 +0 1 +.names 18916 18961 18743 +11 1 +.names 18743 18744 +1 1 +.names 18744 18745 +0 1 +.names 18666 18746 +0 1 +.names 18972 18973 18747 +1- 1 +-1 1 +.names 18747 18748 +1 1 +.names 18748 18749 +0 1 +.names 18746 18749 18750 +11 1 +.names 18974 18916 18751 +1- 1 +-1 1 +.names 18751 18752 +1 1 +.names 18752 18753 +0 1 +.names 18666 18753 18754 +11 1 +.names 18687 18755 +0 1 +.names 18755 18756 +1 1 +.names 18756 18757 +0 1 +.names 18757 16438 18758 +11 1 +.names 18756 16440 18759 +11 1 +.names 18763 18755 18760 +1- 1 +-1 1 +.names 18760 18761 +1 1 +.names 1091 1049 18762 +01 1 +10 1 +.names 18762 18763 +1 1 +.names 18767 18770 18764 +1- 1 +-1 1 +.names 18764 18765 +1 1 +.names 1050 1081 18766 +01 1 +10 1 +.names 18766 18767 +1 1 +.names 18956 18958 18768 +11 1 +.names 18768 18769 +1 1 +.names 18769 18770 +0 1 +.names 18778 18781 18771 +1- 1 +-1 1 +.names 18771 18772 +1 1 +.names 19056 18773 +0 1 +.names 18773 18774 +1 1 +.names 19023 1783 18775 +01 1 +10 1 +.names 18775 18776 +1 1 +.names 18776 18777 +0 1 +.names 18774 18777 18778 +1- 1 +-1 1 +.names 19130 19061 18779 +11 1 +.names 18779 18780 +1 1 +.names 18780 18781 +0 1 +.names 19046 19034 18782 +1- 1 +-1 1 +.names 18782 18783 +1 1 +.names 19070 18784 +0 1 +.names 18784 18785 +1 1 +.names 18783 18785 18786 +1- 1 +-1 1 +.names 19022 1783 18787 +01 1 +10 1 +.names 18787 18788 +1 1 +.names 18788 18789 +0 1 +.names 18786 18789 18790 +1- 1 +-1 1 +.names 19073 18791 +0 1 +.names 18791 18792 +1 1 +.names 18792 18793 +0 1 +.names 18801 18804 18794 +1- 1 +-1 1 +.names 18794 18795 +1 1 +.names 18818 18796 +0 1 +.names 18796 18797 +1 1 +.names 18885 18888 18798 +11 1 +.names 18798 18799 +1 1 +.names 18799 18800 +0 1 +.names 18797 18800 18801 +1- 1 +-1 1 +.names 18694 18890 18802 +11 1 +.names 18802 18803 +1 1 +.names 18803 18804 +0 1 +.names 18813 18816 18805 +1- 1 +-1 1 +.names 18805 18806 +1 1 +.names 19120 18807 +0 1 +.names 18807 18808 +1 1 +.names 18808 18809 +0 1 +.names 19199 19200 18810 +11 1 +.names 18810 18811 +1 1 +.names 18811 18812 +0 1 +.names 18809 18812 18813 +11 1 +.names 2413 18814 +1 1 +.names 18814 18815 +0 1 +.names 18808 18815 18816 +11 1 +.names 18819 18817 +0 1 +.names 18817 18818 +1 1 +.names 1051 1082 18819 +01 1 +10 1 +.names 18824 18827 18820 +11 1 +.names 18820 18821 +1 1 +.names 18988 18991 18822 +1- 1 +-1 1 +.names 18822 18823 +1 1 +.names 18823 18824 +0 1 +.names 19010 18859 18825 +1- 1 +-1 1 +.names 18825 18826 +1 1 +.names 18826 18827 +0 1 +.names 18795 18828 +0 1 +.names 18828 18829 +1 1 +.names 18711 18833 18830 +1- 1 +-1 1 +.names 18830 18831 +1 1 +.names 1090 1059 18832 +01 1 +10 1 +.names 18832 18833 +1 1 +.names 16518 18796 18834 +11 1 +.names 18834 18835 +1 1 +.names 18713 18836 +0 1 +.names 18977 18978 18837 +11 1 +.names 18837 18838 +1 1 +.names 18838 18839 +0 1 +.names 18836 18839 18840 +1- 1 +-1 1 +.names 18821 18841 +0 1 +.names 18845 18842 +0 1 +.names 18842 18843 +1 1 +.names 18964 18965 18844 +1- 1 +-1 1 +.names 18844 18845 +1 1 +.names 18849 18846 +0 1 +.names 18846 18847 +1 1 +.names 18906 18909 18848 +1- 1 +-1 1 +.names 18848 18849 +1 1 +.names 19228 19102 18850 +1- 1 +-1 1 +.names 18850 18851 +1 1 +.names 18851 18852 +0 1 +.names 19005 19008 18853 +1- 1 +-1 1 +.names 18853 18854 +1 1 +.names 18854 18855 +0 1 +.names 18852 18855 18856 +1- 1 +-1 1 +.names 18863 18876 18857 +1- 1 +-1 1 +.names 18857 18858 +1 1 +.names 18858 18859 +0 1 +.names 18856 18859 18860 +1- 1 +-1 1 +.names 18847 18861 +0 1 +.names 18870 18873 18862 +1- 1 +-1 1 +.names 18862 18863 +1 1 +.names 19068 18864 +0 1 +.names 18864 18865 +1 1 +.names 18865 18866 +0 1 +.names 19015 19018 18867 +1- 1 +-1 1 +.names 18867 18868 +1 1 +.names 18868 18869 +0 1 +.names 18866 18869 18870 +11 1 +.names 19144 19146 18871 +1- 1 +-1 1 +.names 18871 18872 +1 1 +.names 18872 18873 +0 1 +.names 18929 18931 18874 +11 1 +.names 18874 18875 +1 1 +.names 18875 18876 +0 1 +.names 18881 18882 18877 +11 1 +.names 18877 18878 +1 1 +.names 18999 19000 18879 +1- 1 +-1 1 +.names 18879 18880 +1 1 +.names 18880 18881 +0 1 +.names 18806 18882 +0 1 +.names 1088 1057 18883 +01 1 +10 1 +.names 18883 18884 +1 1 +.names 18884 18885 +0 1 +.names 18691 18886 +0 1 +.names 18886 18887 +1 1 +.names 18887 18888 +0 1 +.names 18891 18889 +0 1 +.names 18889 18890 +1 1 +.names 1083 1052 18891 +01 1 +10 1 +.names 18898 18901 18892 +1- 1 +-1 1 +.names 18892 18893 +1 1 +.names 16577 18894 +1 1 +.names 18894 18895 +0 1 +.names 18770 18896 +1 1 +.names 18896 18897 +0 1 +.names 18895 18897 18898 +11 1 +.names 19073 19101 18899 +1- 1 +-1 1 +.names 18899 18900 +1 1 +.names 18900 18901 +0 1 +.names 18979 18902 +0 1 +.names 18902 18903 +1 1 +.names 18903 18904 +0 1 +.names 18739 18905 +0 1 +.names 18904 18905 18906 +11 1 +.names 16591 18907 +1 1 +.names 18907 18908 +0 1 +.names 18903 18908 18909 +11 1 +.names 18912 18910 +0 1 +.names 18910 18911 +1 1 +.names 1084 1053 18912 +01 1 +10 1 +.names 18911 18913 +1 1 +.names 18921 18924 18914 +1- 1 +-1 1 +.names 18914 18915 +1 1 +.names 18913 18916 +0 1 +.names 19021 18917 +0 1 +.names 18917 18918 +1 1 +.names 18918 18919 +0 1 +.names 18916 18919 18920 +1- 1 +-1 1 +.names 18920 18665 18921 +1- 1 +-1 1 +.names 18981 18922 +0 1 +.names 18922 18923 +1 1 +.names 18923 18924 +0 1 +.names 18946 18925 +0 1 +.names 18925 18926 +1 1 +.names 18915 18927 +0 1 +.names 18927 18928 +1 1 +.names 18926 18928 18929 +11 1 +.names 19226 18949 18930 +11 1 +.names 18930 18931 +1 1 +.names 18934 18932 +0 1 +.names 18932 18933 +1 1 +.names 1054 1085 18934 +01 1 +10 1 +.names 18937 18935 +0 1 +.names 18935 18936 +1 1 +.names 1055 1086 18937 +01 1 +10 1 +.names 1087 1056 18938 +01 1 +10 1 +.names 18938 18939 +1 1 +.names 18944 18925 18940 +11 1 +.names 18940 18941 +1 1 +.names 19020 18919 18942 +1- 1 +-1 1 +.names 18942 18943 +1 1 +.names 18943 18944 +0 1 +.names 18995 18996 18945 +1- 1 +-1 1 +.names 18945 18946 +1 1 +.names 18890 18947 +0 1 +.names 18947 18948 +1 1 +.names 18948 18949 +0 1 +.names 18949 16635 18950 +11 1 +.names 19139 18951 +0 1 +.names 18951 18952 +1 1 +.names 18952 18953 +0 1 +.names 18948 18953 18954 +11 1 +.names 18948 18955 +1 1 +.names 18941 18829 18956 +11 1 +.names 18831 18957 +0 1 +.names 18957 18958 +1 1 +.names 16645 18959 +1 1 +.names 16647 18960 +1 1 +.names 18960 18961 +0 1 +.names 18926 18962 +0 1 +.names 18928 18963 +0 1 +.names 18962 18963 18964 +1- 1 +-1 1 +.names 18829 18965 +0 1 +.names 18970 18971 18966 +1- 1 +-1 1 +.names 18966 18967 +1 1 +.names 18933 18968 +0 1 +.names 1054 18969 +1 1 +.names 18968 18969 18970 +11 1 +.names 18933 1056 18971 +11 1 +.names 18916 16344 18972 +1- 1 +-1 1 +.names 18664 18973 +0 1 +.names 16662 18974 +1 1 +.names 18765 18975 +0 1 +.names 18975 18976 +1 1 +.names 18976 18977 +0 1 +.names 18893 18978 +0 1 +.names 18922 18979 +1 1 +.names 1058 1089 18980 +01 1 +10 1 +.names 18980 18981 +1 1 +.names 18734 19005 18982 +1- 1 +-1 1 +.names 18982 18983 +1 1 +.names 18983 18984 +0 1 +.names 19008 19005 18985 +1- 1 +-1 1 +.names 18985 18986 +1 1 +.names 18986 18987 +0 1 +.names 18984 18987 18988 +1- 1 +-1 1 +.names 19103 19104 18989 +11 1 +.names 18989 18990 +1 1 +.names 18990 18991 +0 1 +.names 18939 18992 +0 1 +.names 18992 18993 +1 1 +.names 18993 18994 +0 1 +.names 18994 18968 18995 +1- 1 +-1 1 +.names 18936 18996 +0 1 +.names 18955 18962 18997 +1- 1 +-1 1 +.names 18997 18998 +1 1 +.names 18904 18905 18999 +11 1 +.names 18903 18908 19000 +11 1 +.names 19003 19004 19001 +1- 1 +-1 1 +.names 19001 19002 +1 1 +.names 16692 19003 +1 1 +.names 18833 19004 +0 1 +.names 18843 19005 +0 1 +.names 19002 19006 +0 1 +.names 19006 19007 +1 1 +.names 19007 19008 +0 1 +.names 18878 19009 +0 1 +.names 18725 19009 19010 +1- 1 +-1 1 +.names 18885 18888 19011 +11 1 +.names 19011 19012 +1 1 +.names 16703 19013 +1 1 +.names 19013 19014 +0 1 +.names 18885 19014 19015 +11 1 +.names 16707 19016 +1 1 +.names 19016 19017 +0 1 +.names 18884 19017 19018 +11 1 +.names 18916 18924 19019 +1- 1 +-1 1 +.names 19019 18665 19020 +1- 1 +-1 1 +.names 1076 1044 19021 +01 1 +10 1 +.names 2413 19022 +1 1 +.names 2413 19023 +1 1 +.names 19151 19155 19024 +1- 1 +-1 1 +.names 19024 19025 +1 1 +.names 2413 19026 +1 1 +.names 2413 19031 19027 +1- 1 +-1 1 +.names 19027 19028 +1 1 +.names 19029 +.names 19029 19030 +1 1 +.names 19030 19031 +0 1 +.names 19040 19043 19032 +1- 1 +-1 1 +.names 19032 19033 +1 1 +.names 19048 19034 +0 1 +.names 19034 19035 +1 1 +.names 19035 19036 +0 1 +.names 2413 19215 19037 +1- 1 +-1 1 +.names 19037 19038 +1 1 +.names 19038 19039 +0 1 +.names 19036 19039 19040 +11 1 +.names 2413 19041 +1 1 +.names 19041 19042 +0 1 +.names 19035 19042 19043 +11 1 +.names 1783 19113 19044 +01 1 +10 1 +.names 19044 19045 +1 1 +.names 19045 19046 +0 1 +.names 1783 19114 19047 +01 1 +10 1 +.names 19047 19048 +1 1 +.names 19052 19049 +0 1 +.names 19049 19050 +1 1 +.names 2413 19051 +1 1 +.names 19051 1783 19052 +01 1 +10 1 +.names 19050 19053 +0 1 +.names 19053 19054 +1 1 +.names 19031 19055 +1 1 +.names 19026 1783 19056 +01 1 +10 1 +.names 18774 19057 +0 1 +.names 19057 19058 +1 1 +.names 19059 +.names 19059 19060 +1 1 +.names 19060 19061 +0 1 +.names 19061 19062 +1 1 +.names 19066 19063 +0 1 +.names 19063 19064 +1 1 +.names 19106 19065 +0 1 +.names 19065 19066 +1 1 +.names 19142 19221 19067 +11 1 +.names 19067 19068 +1 1 +.names 19071 1783 19069 +01 1 +10 1 +.names 19069 19070 +1 1 +.names 2413 19071 +1 1 +.names 19084 19087 19072 +1- 1 +-1 1 +.names 19072 19073 +1 1 +.names 19118 19054 19074 +11 1 +.names 19074 19075 +1 1 +.names 19075 19076 +0 1 +.names 19122 19055 19077 +11 1 +.names 19077 19078 +1 1 +.names 19078 19079 +0 1 +.names 19076 19079 19080 +1- 1 +-1 1 +.names 19132 19062 19081 +11 1 +.names 19081 19082 +1 1 +.names 19082 19083 +0 1 +.names 19080 19083 19084 +1- 1 +-1 1 +.names 19138 19135 19085 +11 1 +.names 19085 19086 +1 1 +.names 19086 19087 +0 1 +.names 19111 19063 19088 +1- 1 +-1 1 +.names 19088 19089 +1 1 +.names 19064 19090 +0 1 +.names 19168 19169 19091 +11 1 +.names 19091 19092 +1 1 +.names 19092 19093 +0 1 +.names 19090 19093 19094 +11 1 +.names 2413 19095 +1 1 +.names 19095 19096 +0 1 +.names 19064 19096 19097 +11 1 +.names 18901 19098 +1 1 +.names 19177 19179 19099 +1- 1 +-1 1 +.names 19099 19100 +1 1 +.names 19100 19101 +0 1 +.names 18998 19102 +0 1 +.names 19102 18703 19103 +11 1 +.names 19098 19104 +0 1 +.names 2413 19105 +1 1 +.names 19106 +.names 19050 19030 19107 +1- 1 +-1 1 +.names 19137 19108 +0 1 +.names 19108 19109 +1 1 +.names 19109 19110 +0 1 +.names 19107 19110 19111 +1- 1 +-1 1 +.names 19046 19112 +1 1 +.names 2413 19113 +1 1 +.names 2413 19114 +1 1 +.names 2413 19115 +1 1 +.names 1783 19115 19116 +01 1 +10 1 +.names 19116 19117 +1 1 +.names 19117 19066 19118 +11 1 +.names 19121 19119 +0 1 +.names 19119 19120 +1 1 +.names 19121 +.names 19058 19120 19122 +11 1 +.names 19126 19123 +0 1 +.names 19123 19124 +1 1 +.names 1783 19127 19125 +01 1 +10 1 +.names 19125 19126 +1 1 +.names 2413 19127 +1 1 +.names 19128 +.names 19128 19129 +1 1 +.names 19129 19130 +0 1 +.names 19130 19131 +1 1 +.names 19131 19126 19132 +11 1 +.names 2413 19133 +1 1 +.names 1783 19133 19134 +01 1 +10 1 +.names 19134 19135 +1 1 +.names 2413 19136 +1 1 +.names 19136 19105 19137 +01 1 +10 1 +.names 19109 18776 19138 +11 1 +.names 16831 19139 +1 1 +.names 18694 19140 +0 1 +.names 19140 19141 +1 1 +.names 19141 19142 +0 1 +.names 18835 19143 +0 1 +.names 19142 19143 19144 +11 1 +.names 18959 19145 +0 1 +.names 19141 19145 19146 +11 1 +.names 18772 19147 +0 1 +.names 18882 19148 +1 1 +.names 19148 19149 +0 1 +.names 19023 19150 +0 1 +.names 18777 19150 19151 +11 1 +.names 19206 19207 19152 +1- 1 +-1 1 +.names 19152 19153 +1 1 +.names 19153 19154 +0 1 +.names 18776 19154 19155 +11 1 +.names 19159 19161 19156 +1- 1 +-1 1 +.names 19156 19157 +1 1 +.names 19028 19158 +0 1 +.names 19053 19158 19159 +11 1 +.names 19051 19160 +0 1 +.names 19050 19160 19161 +11 1 +.names 19164 19167 19162 +11 1 +.names 19162 19163 +1 1 +.names 19136 19164 +0 1 +.names 19183 19184 19165 +1- 1 +-1 1 +.names 19165 19166 +1 1 +.names 19166 19167 +0 1 +.names 19163 19168 +0 1 +.names 19157 19169 +0 1 +.names 19174 19175 19170 +11 1 +.names 19170 19171 +1 1 +.names 19213 19214 19172 +11 1 +.names 19172 19173 +1 1 +.names 19173 19174 +0 1 +.names 19033 19175 +0 1 +.names 19022 19176 +0 1 +.names 18789 19176 19177 +11 1 +.names 19171 19178 +0 1 +.names 18788 19178 19179 +11 1 +.names 19105 19180 +0 1 +.names 19164 19180 19181 +11 1 +.names 19055 19182 +0 1 +.names 19181 19182 19183 +1- 1 +-1 1 +.names 19054 19184 +0 1 +.names 2413 19185 +1 1 +.names 19188 19189 19186 +11 1 +.names 19186 19187 +1 1 +.names 19135 19188 +0 1 +.names 19185 19189 +0 1 +.names 19195 19198 19190 +1- 1 +-1 1 +.names 19190 19191 +1 1 +.names 19124 19192 +0 1 +.names 19218 19217 19193 +11 1 +.names 19193 19194 +1 1 +.names 19192 19194 19195 +11 1 +.names 1783 19135 19196 +11 1 +.names 19196 19197 +1 1 +.names 19124 19197 19198 +11 1 +.names 19191 19199 +0 1 +.names 19187 19200 +0 1 +.names 19203 19204 19201 +1- 1 +-1 1 +.names 19201 19202 +1 1 +.names 19061 1783 19203 +11 1 +.names 19060 1783 19204 +11 1 +.names 19202 19205 +0 1 +.names 19057 19205 19206 +11 1 +.names 18774 2413 19207 +11 1 +.names 2413 19208 +1 1 +.names 19211 19212 19209 +1- 1 +-1 1 +.names 19209 19210 +1 1 +.names 19034 18784 19211 +1- 1 +-1 1 +.names 19112 19212 +0 1 +.names 19210 19213 +0 1 +.names 19208 19214 +0 1 +.names 19071 19215 +0 1 +.names 2413 19216 +1 1 +.names 19216 19217 +1 1 +.names 19135 1783 19218 +11 1 +.names 18996 19219 +1 1 +.names 19219 19220 +0 1 +.names 18797 19221 +0 1 +.names 19221 19142 19222 +11 1 +.names 19222 19223 +1 1 +.names 19223 19224 +0 1 +.names 19012 19225 +0 1 +.names 19224 19225 19226 +1- 1 +-1 1 +.names 18670 19227 +0 1 +.names 18915 19227 19228 +1- 1 +-1 1 +.names 17505 16924 19229 +1- 1 +-1 1 +.names 19229 19230 +1 1 +.names 19234 19231 +0 1 +.names 19231 19232 +1 1 +.names 19255 19233 +0 1 +.names 19233 19234 +1 1 +.names 19239 19242 19235 +1- 1 +-1 1 +.names 19235 19236 +1 1 +.names 19248 19251 19237 +1- 1 +-1 1 +.names 19237 19238 +1 1 +.names 19238 19239 +0 1 +.names 19290 19243 19240 +1- 1 +-1 1 +.names 19240 19241 +1 1 +.names 19241 19242 +0 1 +.names 19253 19243 +0 1 +.names 19243 19244 +1 1 +.names 19244 19245 +0 1 +.names 18087 19246 +1 1 +.names 19246 19247 +0 1 +.names 19245 19247 19248 +11 1 +.names 18091 19249 +1 1 +.names 19249 19250 +0 1 +.names 19244 19250 19251 +11 1 +.names 19254 19252 +0 1 +.names 19252 19253 +1 1 +.names 1077 1061 19254 +01 1 +10 1 +.names 1062 1078 19255 +01 1 +10 1 +.names 19258 19256 +0 1 +.names 19256 19257 +1 1 +.names 1063 1079 19258 +01 1 +10 1 +.names 19261 19259 +0 1 +.names 19259 19260 +1 1 +.names 1064 1080 19261 +01 1 +10 1 +.names 19265 19262 +0 1 +.names 19262 19263 +1 1 +.names 19317 19320 19264 +1- 1 +-1 1 +.names 19264 19265 +1 1 +.names 19268 19271 19266 +1- 1 +-1 1 +.names 19266 19267 +1 1 +.names 19263 19268 +0 1 +.names 1065 1081 19269 +01 1 +10 1 +.names 19269 19270 +1 1 +.names 19270 19271 +0 1 +.names 19276 19279 19272 +11 1 +.names 19272 19273 +1 1 +.names 19284 19288 19274 +1- 1 +-1 1 +.names 19274 19275 +1 1 +.names 19275 19276 +0 1 +.names 19562 19277 +0 1 +.names 19277 19278 +1 1 +.names 19278 19279 +0 1 +.names 19232 19280 +0 1 +.names 19350 19351 19281 +1- 1 +-1 1 +.names 19281 19282 +1 1 +.names 19282 19283 +0 1 +.names 19280 19283 19284 +11 1 +.names 19777 19349 19285 +1- 1 +-1 1 +.names 19285 19286 +1 1 +.names 19286 19287 +0 1 +.names 19232 19287 19288 +11 1 +.names 1091 1075 19289 +01 1 +10 1 +.names 19289 19290 +1 1 +.names 19294 19297 19291 +1- 1 +-1 1 +.names 19291 19292 +1 1 +.names 1065 1081 19293 +01 1 +10 1 +.names 19293 19294 +1 1 +.names 19480 19482 19295 +11 1 +.names 19295 19296 +1 1 +.names 19296 19297 +0 1 +.names 19305 19308 19298 +1- 1 +-1 1 +.names 19298 19299 +1 1 +.names 19630 19300 +0 1 +.names 19300 19301 +1 1 +.names 19601 1783 19302 +01 1 +10 1 +.names 19302 19303 +1 1 +.names 19303 19304 +0 1 +.names 19301 19304 19305 +1- 1 +-1 1 +.names 19740 19635 19306 +11 1 +.names 19306 19307 +1 1 +.names 19307 19308 +0 1 +.names 19605 19608 19309 +1- 1 +-1 1 +.names 19309 19310 +1 1 +.names 19647 19311 +0 1 +.names 19311 19312 +1 1 +.names 19310 19312 19313 +1- 1 +-1 1 +.names 19600 1783 19314 +01 1 +10 1 +.names 19314 19315 +1 1 +.names 19315 19316 +0 1 +.names 19313 19316 19317 +1- 1 +-1 1 +.names 19650 19318 +0 1 +.names 19318 19319 +1 1 +.names 19319 19320 +0 1 +.names 19328 19331 19321 +1- 1 +-1 1 +.names 19321 19322 +1 1 +.names 19333 19323 +0 1 +.names 19323 19324 +1 1 +.names 19369 19372 19325 +11 1 +.names 19325 19326 +1 1 +.names 19326 19327 +0 1 +.names 19324 19327 19328 +1- 1 +-1 1 +.names 19260 19374 19329 +11 1 +.names 19329 19330 +1 1 +.names 19330 19331 +0 1 +.names 19334 19332 +0 1 +.names 19332 19333 +1 1 +.names 1066 1082 19334 +01 1 +10 1 +.names 19322 19335 +0 1 +.names 19335 19336 +1 1 +.names 19265 19340 19337 +1- 1 +-1 1 +.names 19337 19338 +1 1 +.names 1090 1074 19339 +01 1 +10 1 +.names 19339 19340 +1 1 +.names 19344 19341 +0 1 +.names 19341 19342 +1 1 +.names 19494 19495 19343 +1- 1 +-1 1 +.names 19343 19344 +1 1 +.names 19292 19345 +0 1 +.names 18189 19346 +1 1 +.names 19377 19347 +1 1 +.names 19347 19348 +1 1 +.names 19348 19349 +0 1 +.names 17505 19349 19350 +1- 1 +-1 1 +.names 19230 19351 +0 1 +.names 19354 19355 19352 +1- 1 +-1 1 +.names 19352 19353 +1 1 +.names 18198 19354 +1 1 +.names 19340 19355 +0 1 +.names 19360 19362 19356 +1- 1 +-1 1 +.names 19356 19357 +1 1 +.names 19353 19358 +0 1 +.names 19358 19359 +1 1 +.names 19359 19360 +0 1 +.names 19341 19361 +1 1 +.names 19361 19362 +0 1 +.names 19366 19363 +0 1 +.names 19363 19364 +1 1 +.names 19573 19383 19365 +1- 1 +-1 1 +.names 19365 19366 +1 1 +.names 1088 1072 19367 +01 1 +10 1 +.names 19367 19368 +1 1 +.names 19368 19369 +0 1 +.names 19257 19370 +0 1 +.names 19370 19371 +1 1 +.names 19371 19372 +0 1 +.names 19375 19373 +0 1 +.names 19373 19374 +1 1 +.names 1083 1067 19375 +01 1 +10 1 +.names 19297 19376 +1 1 +.names 19378 19377 +0 1 +.names 1084 1068 19378 +01 1 +10 1 +.names 19385 19388 19379 +1- 1 +-1 1 +.names 19379 19380 +1 1 +.names 19578 19381 +0 1 +.names 19381 19382 +1 1 +.names 19382 19383 +0 1 +.names 19349 19383 19384 +1- 1 +-1 1 +.names 19384 19231 19385 +1- 1 +-1 1 +.names 19556 19386 +0 1 +.names 19386 19387 +1 1 +.names 19387 19388 +0 1 +.names 19395 19397 19389 +11 1 +.names 19389 19390 +1 1 +.names 19443 19391 +0 1 +.names 19391 19392 +1 1 +.names 19380 19393 +0 1 +.names 19393 19394 +1 1 +.names 19392 19394 19395 +11 1 +.names 19807 19808 19396 +11 1 +.names 19396 19397 +1 1 +.names 19408 19262 19398 +11 1 +.names 19398 19399 +1 1 +.names 19415 19418 19400 +11 1 +.names 19400 19401 +1 1 +.names 19401 19402 +0 1 +.names 19542 19543 19403 +1- 1 +-1 1 +.names 19403 19404 +1 1 +.names 19404 19405 +0 1 +.names 19402 19405 19406 +1- 1 +-1 1 +.names 19357 19407 +0 1 +.names 19406 19407 19408 +1- 1 +-1 1 +.names 19492 19409 +0 1 +.names 19409 19410 +1 1 +.names 19410 19411 +0 1 +.names 19478 19479 19412 +1- 1 +-1 1 +.names 19412 19413 +1 1 +.names 19413 19414 +0 1 +.names 19411 19414 19415 +1- 1 +-1 1 +.names 19558 19560 19416 +1- 1 +-1 1 +.names 19416 19417 +1 1 +.names 19417 19418 +0 1 +.names 19423 19414 19419 +11 1 +.names 19419 19420 +1 1 +.names 19750 19751 19421 +1- 1 +-1 1 +.names 19421 19422 +1 1 +.names 19422 19423 +0 1 +.names 19428 19431 19424 +11 1 +.names 19424 19425 +1 1 +.names 19577 19407 19426 +1- 1 +-1 1 +.names 19426 19427 +1 1 +.names 19427 19428 +0 1 +.names 19553 19554 19429 +1- 1 +-1 1 +.names 19429 19430 +1 1 +.names 19430 19431 +0 1 +.names 19434 19432 +0 1 +.names 19432 19433 +1 1 +.names 1069 1085 19434 +01 1 +10 1 +.names 19437 19435 +0 1 +.names 19435 19436 +1 1 +.names 1070 1086 19437 +01 1 +10 1 +.names 1087 1071 19438 +01 1 +10 1 +.names 19438 19439 +1 1 +.names 19363 19391 19440 +11 1 +.names 19440 19441 +1 1 +.names 19527 19453 19442 +1- 1 +-1 1 +.names 19442 19443 +1 1 +.names 1085 19444 +1 1 +.names 19449 19450 19445 +1- 1 +-1 1 +.names 19445 19446 +1 1 +.names 19433 19447 +0 1 +.names 19444 19448 +0 1 +.names 19447 19448 19449 +11 1 +.names 19433 18295 19450 +11 1 +.names 19457 19460 19451 +1- 1 +-1 1 +.names 19451 19452 +1 1 +.names 19436 19453 +0 1 +.names 19453 19454 +1 1 +.names 19454 19455 +0 1 +.names 19446 19456 +0 1 +.names 19455 19456 19457 +11 1 +.names 18304 19458 +1 1 +.names 19458 19459 +0 1 +.names 19454 19459 19460 +11 1 +.names 19463 19461 +1 1 +.names 19461 19462 +1 1 +.names 19374 19463 +0 1 +.names 18311 19464 +1 1 +.names 19467 19468 19465 +11 1 +.names 19465 19466 +1 1 +.names 19392 19467 +0 1 +.names 19462 19468 +0 1 +.names 19471 19472 19469 +1- 1 +-1 1 +.names 19469 19470 +1 1 +.names 19452 19471 +0 1 +.names 19466 19472 +0 1 +.names 19468 19477 19473 +1- 1 +-1 1 +.names 19473 19474 +1 1 +.names 19464 19475 +0 1 +.names 19475 19476 +1 1 +.names 19476 19477 +0 1 +.names 19470 19478 +0 1 +.names 19474 19479 +0 1 +.names 19441 19336 19480 +11 1 +.names 19338 19481 +0 1 +.names 19481 19482 +1 1 +.names 19486 19489 19483 +11 1 +.names 19483 19484 +1 1 +.names 19345 19485 +1 1 +.names 19485 19486 +0 1 +.names 19642 19643 19487 +1- 1 +-1 1 +.names 19487 19488 +1 1 +.names 19488 19489 +0 1 +.names 1084 19490 +1 1 +.names 19364 19491 +0 1 +.names 19491 19492 +1 1 +.names 19394 19493 +0 1 +.names 19467 19493 19494 +1- 1 +-1 1 +.names 19336 19495 +0 1 +.names 19504 19507 19496 +11 1 +.names 19496 19497 +1 1 +.names 19639 19498 +0 1 +.names 19498 19499 +1 1 +.names 19499 19500 +0 1 +.names 19376 19501 +0 1 +.names 19501 19502 +1 1 +.names 19502 19503 +0 1 +.names 19500 19503 19504 +1- 1 +-1 1 +.names 19585 19588 19505 +1- 1 +-1 1 +.names 19505 19506 +1 1 +.names 19506 19507 +0 1 +.names 19510 19511 19508 +1- 1 +-1 1 +.names 19508 19509 +1 1 +.names 19497 19510 +0 1 +.names 19484 19511 +0 1 +.names 19509 19512 +0 1 +.names 19512 19513 +1 1 +.names 19513 19514 +0 1 +.names 19399 19515 +0 1 +.names 19515 19516 +1 1 +.names 19516 19517 +0 1 +.names 19514 19517 19518 +1- 1 +-1 1 +.names 19425 19519 +0 1 +.names 19522 19523 19520 +1- 1 +-1 1 +.names 19520 19521 +1 1 +.names 19388 19346 19522 +11 1 +.names 19387 19273 19523 +11 1 +.names 19439 19524 +0 1 +.names 19524 19525 +1 1 +.names 19525 19526 +0 1 +.names 19526 19447 19527 +1- 1 +-1 1 +.names 19536 19539 19528 +1- 1 +-1 1 +.names 19528 19529 +1 1 +.names 19645 19530 +0 1 +.names 19530 19531 +1 1 +.names 19531 19532 +0 1 +.names 19568 19571 19533 +1- 1 +-1 1 +.names 19533 19534 +1 1 +.names 19534 19535 +0 1 +.names 19532 19535 19536 +11 1 +.names 19720 19722 19537 +1- 1 +-1 1 +.names 19537 19538 +1 1 +.names 19538 19539 +0 1 +.names 19529 19540 +0 1 +.names 19540 19541 +1 1 +.names 19541 19542 +0 1 +.names 19390 19543 +0 1 +.names 19547 19549 19544 +11 1 +.names 19544 19545 +1 1 +.names 19650 19712 19546 +1- 1 +-1 1 +.names 19546 19547 +1 1 +.names 19692 19693 19548 +1- 1 +-1 1 +.names 19548 19549 +1 1 +.names 19420 19550 +0 1 +.names 19550 19405 19551 +1- 1 +-1 1 +.names 19521 19552 +0 1 +.names 19551 19552 19553 +1- 1 +-1 1 +.names 19545 19554 +0 1 +.names 1073 1089 19555 +01 1 +10 1 +.names 19555 19556 +1 1 +.names 19273 19557 +0 1 +.names 19386 19557 19558 +11 1 +.names 19346 19559 +0 1 +.names 19556 19559 19560 +11 1 +.names 19348 19563 19561 +1- 1 +-1 1 +.names 19561 19562 +1 1 +.names 19490 19563 +0 1 +.names 19369 19372 19564 +11 1 +.names 19564 19565 +1 1 +.names 18414 19566 +1 1 +.names 19566 19567 +0 1 +.names 19369 19567 19568 +11 1 +.names 18418 19569 +1 1 +.names 19569 19570 +0 1 +.names 19368 19570 19571 +11 1 +.names 19349 19388 19572 +1- 1 +-1 1 +.names 19572 19231 19573 +1- 1 +-1 1 +.names 19267 19576 19574 +1- 1 +-1 1 +.names 19574 19575 +1 1 +.names 19342 19576 +0 1 +.names 19575 19577 +0 1 +.names 1076 1060 19578 +01 1 +10 1 +.names 19638 19579 +0 1 +.names 19579 19580 +1 1 +.names 19580 19581 +0 1 +.names 19682 19683 19582 +11 1 +.names 19582 19583 +1 1 +.names 19583 19584 +0 1 +.names 19581 19584 19585 +11 1 +.names 2413 19586 +1 1 +.names 19586 19587 +0 1 +.names 19580 19587 19588 +11 1 +.names 19507 19589 +1 1 +.names 19597 19599 19590 +1- 1 +-1 1 +.names 19590 19591 +1 1 +.names 19730 19592 +0 1 +.names 19592 19593 +1 1 +.names 19593 19594 +0 1 +.names 19791 19792 19595 +11 1 +.names 19595 19596 +1 1 +.names 19594 19596 19597 +11 1 +.names 2413 19598 +1 1 +.names 19593 19598 19599 +11 1 +.names 2413 19600 +1 1 +.names 2413 19601 +1 1 +.names 2413 19602 +1 1 +.names 1783 19724 19603 +01 1 +10 1 +.names 19603 19604 +1 1 +.names 19604 19605 +0 1 +.names 1783 19617 19606 +01 1 +10 1 +.names 19606 19607 +1 1 +.names 19607 19608 +0 1 +.names 19616 19619 19609 +1- 1 +-1 1 +.names 19609 19610 +1 1 +.names 19608 19611 +1 1 +.names 19611 19612 +0 1 +.names 2413 19798 19613 +1- 1 +-1 1 +.names 19613 19614 +1 1 +.names 19614 19615 +0 1 +.names 19612 19615 19616 +11 1 +.names 2413 19617 +1 1 +.names 19617 19618 +0 1 +.names 19611 19618 19619 +11 1 +.names 19623 19620 +0 1 +.names 19620 19621 +1 1 +.names 2413 19622 +1 1 +.names 19622 1783 19623 +01 1 +10 1 +.names 19621 19624 +0 1 +.names 19624 19625 +1 1 +.names 19626 +.names 19626 19627 +1 1 +.names 19627 19628 +0 1 +.names 19628 19629 +1 1 +.names 19602 1783 19630 +01 1 +10 1 +.names 19301 19631 +0 1 +.names 19631 19632 +1 1 +.names 19633 +.names 19633 19634 +1 1 +.names 19634 19635 +0 1 +.names 19635 19636 +1 1 +.names 19684 19637 +0 1 +.names 19637 19638 +1 1 +.names 18489 19639 +1 1 +.names 19701 19702 19640 +1- 1 +-1 1 +.names 19640 19641 +1 1 +.names 19641 19642 +0 1 +.names 19547 19643 +0 1 +.names 19718 19802 19644 +11 1 +.names 19644 19645 +1 1 +.names 19648 1783 19646 +01 1 +10 1 +.names 19646 19647 +1 1 +.names 2413 19648 +1 1 +.names 19661 19664 19649 +1- 1 +-1 1 +.names 19649 19650 +1 1 +.names 19728 19625 19651 +11 1 +.names 19651 19652 +1 1 +.names 19652 19653 +0 1 +.names 19732 19629 19654 +11 1 +.names 19654 19655 +1 1 +.names 19655 19656 +0 1 +.names 19653 19656 19657 +1- 1 +-1 1 +.names 19742 19636 19658 +11 1 +.names 19658 19659 +1 1 +.names 19659 19660 +0 1 +.names 19657 19660 19661 +1- 1 +-1 1 +.names 19748 19745 19662 +11 1 +.names 19662 19663 +1 1 +.names 19663 19664 +0 1 +.names 19668 19665 +0 1 +.names 19665 19666 +1 1 +.names 19689 19579 19667 +1- 1 +-1 1 +.names 19667 19668 +1 1 +.names 2413 19669 +1 1 +.names 19674 19675 19670 +11 1 +.names 19670 19671 +1 1 +.names 19755 19756 19672 +1- 1 +-1 1 +.names 19672 19673 +1 1 +.names 19673 19674 +0 1 +.names 19669 19675 +0 1 +.names 19680 19681 19676 +1- 1 +-1 1 +.names 19676 19677 +1 1 +.names 1783 19627 19678 +11 1 +.names 19678 19679 +1 1 +.names 19624 19679 19680 +11 1 +.names 19621 1783 19681 +11 1 +.names 19677 19682 +0 1 +.names 19671 19683 +0 1 +.names 19684 +.names 19621 19627 19685 +1- 1 +-1 1 +.names 19747 19686 +0 1 +.names 19686 19687 +1 1 +.names 19687 19688 +0 1 +.names 19685 19688 19689 +1- 1 +-1 1 +.names 19766 19768 19690 +1- 1 +-1 1 +.names 19690 19691 +1 1 +.names 19691 19692 +0 1 +.names 19299 19693 +0 1 +.names 19549 19694 +0 1 +.names 19694 19695 +1 1 +.names 19698 19693 19696 +11 1 +.names 19696 19697 +1 1 +.names 19591 19698 +0 1 +.names 19697 19699 +0 1 +.names 19695 19700 +0 1 +.names 19699 19700 19701 +11 1 +.names 19666 19702 +0 1 +.names 2413 19703 +1 1 +.names 19707 19711 19704 +1- 1 +-1 1 +.names 19704 19705 +1 1 +.names 19703 19706 +0 1 +.names 19316 19706 19707 +11 1 +.names 19775 19776 19708 +11 1 +.names 19708 19709 +1 1 +.names 19709 19710 +0 1 +.names 19315 19710 19711 +11 1 +.names 19705 19712 +0 1 +.names 18564 19713 +1 1 +.names 18568 19323 19714 +11 1 +.names 19714 19715 +1 1 +.names 19260 19716 +0 1 +.names 19716 19717 +1 1 +.names 19717 19718 +0 1 +.names 19715 19719 +0 1 +.names 19718 19719 19720 +11 1 +.names 19713 19721 +0 1 +.names 19717 19721 19722 +11 1 +.names 19605 19723 +1 1 +.names 2413 19724 +1 1 +.names 2413 19725 +1 1 +.names 1783 19725 19726 +01 1 +10 1 +.names 19726 19727 +1 1 +.names 19727 19638 19728 +11 1 +.names 19731 19729 +0 1 +.names 19729 19730 +1 1 +.names 19731 +.names 19632 19730 19732 +11 1 +.names 19736 19733 +0 1 +.names 19733 19734 +1 1 +.names 1783 19737 19735 +01 1 +10 1 +.names 19735 19736 +1 1 +.names 2413 19737 +1 1 +.names 19738 +.names 19738 19739 +1 1 +.names 19739 19740 +0 1 +.names 19740 19741 +1 1 +.names 19741 19736 19742 +11 1 +.names 2413 19743 +1 1 +.names 1783 19743 19744 +01 1 +10 1 +.names 19744 19745 +1 1 +.names 2413 19746 +1 1 +.names 19746 19669 19747 +01 1 +10 1 +.names 19687 19303 19748 +11 1 +.names 19236 19749 +0 1 +.names 19698 19749 19750 +1- 1 +-1 1 +.names 19589 19751 +0 1 +.names 19746 19752 +0 1 +.names 19752 19675 19753 +11 1 +.names 19629 19754 +0 1 +.names 19753 19754 19755 +1- 1 +-1 1 +.names 19625 19756 +0 1 +.names 19762 19763 19757 +1- 1 +-1 1 +.names 19757 19758 +1 1 +.names 19795 19796 19759 +1- 1 +-1 1 +.names 19759 19760 +1 1 +.names 19760 19761 +0 1 +.names 19631 19761 19762 +11 1 +.names 19301 2413 19763 +11 1 +.names 2413 19764 +1 1 +.names 19764 19765 +0 1 +.names 19304 19765 19766 +11 1 +.names 19758 19767 +0 1 +.names 19303 19767 19768 +11 1 +.names 19771 19774 19769 +11 1 +.names 19769 19770 +1 1 +.names 19724 19771 +0 1 +.names 19793 19794 19772 +1- 1 +-1 1 +.names 19772 19773 +1 1 +.names 19773 19774 +0 1 +.names 19770 19775 +0 1 +.names 19610 19776 +0 1 +.names 18630 19777 +1 1 +.names 19780 19781 19778 +11 1 +.names 19778 19779 +1 1 +.names 19745 19780 +0 1 +.names 19743 19781 +0 1 +.names 19787 19790 19782 +1- 1 +-1 1 +.names 19782 19783 +1 1 +.names 19734 19784 +0 1 +.names 19801 19800 19785 +11 1 +.names 19785 19786 +1 1 +.names 19784 19786 19787 +11 1 +.names 1783 19745 19788 +11 1 +.names 19788 19789 +1 1 +.names 19734 19789 19790 +11 1 +.names 19783 19791 +0 1 +.names 19779 19792 +0 1 +.names 19608 19311 19793 +1- 1 +-1 1 +.names 19723 19794 +0 1 +.names 19635 1783 19795 +11 1 +.names 19634 1783 19796 +11 1 +.names 2413 19797 +1 1 +.names 19797 19798 +0 1 +.names 2413 19799 +1 1 +.names 19799 19800 +1 1 +.names 19745 1783 19801 +11 1 +.names 19324 19802 +0 1 +.names 19802 19718 19803 +11 1 +.names 19803 19804 +1 1 +.names 19804 19805 +0 1 +.names 19565 19806 +0 1 +.names 19805 19806 19807 +1- 1 +-1 1 +.names 19461 19808 +0 1 +.names 19812 19809 +0 1 +.names 19809 19810 +1 1 +.names 42733 42737 56688 +1- 1 +-1 1 +.names 1092 56688 19812 +01 1 +10 1 +.names 19815 19813 +0 1 +.names 19813 19814 +1 1 +.names 1093 1783 19815 +01 1 +10 1 +.names 19819 19816 +0 1 +.names 19816 19817 +1 1 +.names 42960 42964 56684 +1- 1 +-1 1 +.names 1094 56684 19819 +01 1 +10 1 +.names 19822 19810 19820 +11 1 +.names 19820 19821 +1 1 +.names 19814 19817 19822 +11 1 +.names 19826 19823 +0 1 +.names 19823 19824 +1 1 +.names 42952 42956 56686 +1- 1 +-1 1 +.names 1095 56686 19826 +01 1 +10 1 +.names 19830 19827 +0 1 +.names 19827 19828 +1 1 +.names 43614 43618 56694 +1- 1 +-1 1 +.names 1096 56694 19830 +01 1 +10 1 +.names 19834 19831 +0 1 +.names 19831 19832 +1 1 +.names 43039 43043 56680 +1- 1 +-1 1 +.names 1097 56680 19834 +01 1 +10 1 +.names 19839 19840 19835 +1- 1 +-1 1 +.names 19835 19836 +1 1 +.names 19824 19837 +0 1 +.names 19828 19838 +0 1 +.names 19837 19838 19839 +1- 1 +-1 1 +.names 19832 19840 +0 1 +.names 19836 19841 +0 1 +.names 19841 19842 +1 1 +.names 1098 56692 19843 +01 1 +10 1 +.names 19843 19844 +1 1 +.names 43600 43604 56692 +1- 1 +-1 1 +.names 1099 56685 19846 +01 1 +10 1 +.names 19846 19847 +1 1 +.names 42974 42978 56685 +1- 1 +-1 1 +.names 19851 19852 19849 +11 1 +.names 19849 19850 +1 1 +.names 19844 19851 +0 1 +.names 19847 19852 +0 1 +.names 1100 56696 19853 +01 1 +10 1 +.names 19853 19854 +1 1 +.names 1101 1783 19855 +01 1 +10 1 +.names 19855 19856 +1 1 +.names 19859 19860 19857 +11 1 +.names 19857 19858 +1 1 +.names 19854 19859 +0 1 +.names 19856 19860 +0 1 +.names 19867 19868 19861 +1- 1 +-1 1 +.names 19861 19862 +1 1 +.names 19821 19863 +0 1 +.names 19842 19864 +0 1 +.names 19863 19864 19865 +1- 1 +-1 1 +.names 19850 19866 +0 1 +.names 19865 19866 19867 +1- 1 +-1 1 +.names 19858 19868 +0 1 +.names 19872 19869 +0 1 +.names 19869 19870 +1 1 +.names 42749 42753 56690 +1- 1 +-1 1 +.names 1102 56690 19872 +01 1 +10 1 +.names 19876 19873 +0 1 +.names 19873 19874 +1 1 +.names 42725 42729 56687 +1- 1 +-1 1 +.names 1103 56687 19876 +01 1 +10 1 +.names 19880 19877 +0 1 +.names 19877 19878 +1 1 +.names 42741 42745 56689 +1- 1 +-1 1 +.names 1104 56689 19880 +01 1 +10 1 +.names 19883 19878 19881 +11 1 +.names 19881 19882 +1 1 +.names 19870 19874 19883 +11 1 +.names 19886 19884 +0 1 +.names 19884 19885 +1 1 +.names 1105 56695 19886 +01 1 +10 1 +.names 19890 19887 +0 1 +.names 19887 19888 +1 1 +.names 42966 42970 56683 +1- 1 +-1 1 +.names 1106 56683 19890 +01 1 +10 1 +.names 19893 19891 +0 1 +.names 19891 19892 +1 1 +.names 19893 +.names 19896 19892 19894 +11 1 +.names 19894 19895 +1 1 +.names 19885 19888 19896 +11 1 +.names 1107 56691 19897 +01 1 +10 1 +.names 19897 19898 +1 1 +.names 43592 43596 56691 +1- 1 +-1 1 +.names 1108 56693 19900 +01 1 +10 1 +.names 19900 19901 +1 1 +.names 43608 43612 56693 +1- 1 +-1 1 +.names 19905 19906 19903 +11 1 +.names 19903 19904 +1 1 +.names 19898 19905 +0 1 +.names 19901 19906 +0 1 +.names 1109 56681 19907 +01 1 +10 1 +.names 19907 19908 +1 1 +.names 43047 43051 56681 +1- 1 +-1 1 +.names 19916 19919 19910 +1- 1 +-1 1 +.names 19910 19911 +1 1 +.names 19882 19912 +0 1 +.names 19895 19913 +0 1 +.names 19912 19913 19914 +1- 1 +-1 1 +.names 19904 19915 +0 1 +.names 19914 19915 19916 +1- 1 +-1 1 +.names 19925 19928 19917 +11 1 +.names 19917 19918 +1 1 +.names 19918 19919 +0 1 +.names 19862 19920 +0 1 +.names 19911 19921 +0 1 +.names 56682 19922 +0 1 +.names 19922 19923 +1 1 +.names 43055 43059 56682 +1- 1 +-1 1 +.names 19908 19925 +0 1 +.names 19929 19926 +0 1 +.names 19926 19927 +1 1 +.names 19927 19928 +0 1 +.names 1110 19923 19929 +01 1 +10 1 +.names 19933 19930 +0 1 +.names 19930 19931 +1 1 +.names 42888 42892 56673 +1- 1 +-1 1 +.names 1111 56673 19933 +01 1 +10 1 +.names 19937 19934 +0 1 +.names 19934 19935 +1 1 +.names 42896 42900 56672 +1- 1 +-1 1 +.names 56672 1112 19937 +01 1 +10 1 +.names 19943 19944 19938 +1- 1 +-1 1 +.names 19938 19939 +1 1 +.names 20021 20022 19940 +1- 1 +-1 1 +.names 19940 19941 +1 1 +.names 19931 19942 +0 1 +.names 19941 19942 19943 +1- 1 +-1 1 +.names 19935 19944 +0 1 +.names 19948 19945 +0 1 +.names 19945 19946 +1 1 +.names 42906 42908 56674 +1- 1 +-1 1 +.names 56674 1113 19948 +01 1 +10 1 +.names 19952 19949 +0 1 +.names 19949 19950 +1 1 +.names 42914 42916 56671 +1- 1 +-1 1 +.names 56671 1114 19952 +01 1 +10 1 +.names 19955 19956 19953 +1- 1 +-1 1 +.names 19953 19954 +1 1 +.names 19946 19955 +0 1 +.names 19950 19956 +0 1 +.names 19960 19957 +0 1 +.names 19957 19958 +1 1 +.names 43645 43646 56678 +1- 1 +-1 1 +.names 56678 1115 19960 +01 1 +10 1 +.names 19964 19961 +0 1 +.names 19961 19962 +1 1 +.names 43638 43642 56675 +1- 1 +-1 1 +.names 56675 1116 19964 +01 1 +10 1 +.names 19968 19965 +0 1 +.names 19965 19966 +1 1 +.names 43624 43626 56677 +1- 1 +-1 1 +.names 56677 1117 19968 +01 1 +10 1 +.names 19979 19982 19969 +1- 1 +-1 1 +.names 19969 19970 +1 1 +.names 19970 19971 +0 1 +.names 19939 19972 +0 1 +.names 19971 19972 19973 +11 1 +.names 19954 19974 +0 1 +.names 19958 19975 +0 1 +.names 19962 19976 +0 1 +.names 19975 19976 19977 +1- 1 +-1 1 +.names 19966 19978 +0 1 +.names 19977 19978 19979 +1- 1 +-1 1 +.names 19984 19980 +0 1 +.names 19980 19981 +1 1 +.names 19981 19982 +0 1 +.names 43630 43634 56676 +1- 1 +-1 1 +.names 56676 1118 19984 +01 1 +10 1 +.names 19989 19992 19985 +11 1 +.names 19985 19986 +1 1 +.names 19987 +.names 19987 19988 +1 1 +.names 19988 19989 +0 1 +.names 19990 +.names 19990 19991 +1 1 +.names 19991 19992 +0 1 +.names 19997 20000 19993 +11 1 +.names 19993 19994 +1 1 +.names 19995 +.names 19995 19996 +1 1 +.names 19996 19997 +0 1 +.names 19998 +.names 19998 19999 +1 1 +.names 19999 20000 +0 1 +.names 20005 20008 20001 +11 1 +.names 20001 20002 +1 1 +.names 20003 +.names 20003 20004 +1 1 +.names 20004 20005 +0 1 +.names 20006 +.names 20006 20007 +1 1 +.names 20007 20008 +0 1 +.names 20013 20016 20009 +11 1 +.names 20009 20010 +1 1 +.names 20011 +.names 20011 20012 +1 1 +.names 20012 20013 +0 1 +.names 20014 +.names 20014 20015 +1 1 +.names 20015 20016 +0 1 +.names 20010 20017 +0 1 +.names 20002 20018 +0 1 +.names 20017 20018 20019 +1- 1 +-1 1 +.names 19994 20020 +0 1 +.names 20019 20020 20021 +1- 1 +-1 1 +.names 19986 20022 +0 1 +.names 20025 20023 +0 1 +.names 20023 20024 +1 1 +.names 1119 56688 20025 +01 1 +10 1 +.names 20028 20026 +0 1 +.names 20026 20027 +1 1 +.names 1120 1783 20028 +01 1 +10 1 +.names 20031 20029 +0 1 +.names 20029 20030 +1 1 +.names 1121 56684 20031 +01 1 +10 1 +.names 20034 20024 20032 +11 1 +.names 20032 20033 +1 1 +.names 20027 20030 20034 +11 1 +.names 20037 20035 +0 1 +.names 20035 20036 +1 1 +.names 1122 56686 20037 +01 1 +10 1 +.names 20040 20038 +0 1 +.names 20038 20039 +1 1 +.names 1123 56694 20040 +01 1 +10 1 +.names 20043 20041 +0 1 +.names 20041 20042 +1 1 +.names 1124 56680 20043 +01 1 +10 1 +.names 20048 20049 20044 +1- 1 +-1 1 +.names 20044 20045 +1 1 +.names 20036 20046 +0 1 +.names 20039 20047 +0 1 +.names 20046 20047 20048 +1- 1 +-1 1 +.names 20042 20049 +0 1 +.names 20045 20050 +0 1 +.names 20050 20051 +1 1 +.names 1125 56692 20052 +01 1 +10 1 +.names 20052 20053 +1 1 +.names 1126 56685 20054 +01 1 +10 1 +.names 20054 20055 +1 1 +.names 20058 20059 20056 +11 1 +.names 20056 20057 +1 1 +.names 20053 20058 +0 1 +.names 20055 20059 +0 1 +.names 1127 56696 20060 +01 1 +10 1 +.names 20060 20061 +1 1 +.names 1128 1783 20062 +01 1 +10 1 +.names 20062 20063 +1 1 +.names 20066 20067 20064 +11 1 +.names 20064 20065 +1 1 +.names 20061 20066 +0 1 +.names 20063 20067 +0 1 +.names 20074 20075 20068 +1- 1 +-1 1 +.names 20068 20069 +1 1 +.names 20033 20070 +0 1 +.names 20051 20071 +0 1 +.names 20070 20071 20072 +1- 1 +-1 1 +.names 20057 20073 +0 1 +.names 20072 20073 20074 +1- 1 +-1 1 +.names 20065 20075 +0 1 +.names 20078 20076 +0 1 +.names 20076 20077 +1 1 +.names 1129 56690 20078 +01 1 +10 1 +.names 20081 20079 +0 1 +.names 20079 20080 +1 1 +.names 1130 56687 20081 +01 1 +10 1 +.names 20084 20082 +0 1 +.names 20082 20083 +1 1 +.names 1131 56689 20084 +01 1 +10 1 +.names 20087 20083 20085 +11 1 +.names 20085 20086 +1 1 +.names 20077 20080 20087 +11 1 +.names 20090 20088 +0 1 +.names 20088 20089 +1 1 +.names 1132 56695 20090 +01 1 +10 1 +.names 20093 20091 +0 1 +.names 20091 20092 +1 1 +.names 1133 56683 20093 +01 1 +10 1 +.names 20096 20094 +0 1 +.names 20094 20095 +1 1 +.names 20096 +.names 20099 20095 20097 +11 1 +.names 20097 20098 +1 1 +.names 20089 20092 20099 +11 1 +.names 1134 56691 20100 +01 1 +10 1 +.names 20100 20101 +1 1 +.names 1135 56693 20102 +01 1 +10 1 +.names 20102 20103 +1 1 +.names 20106 20107 20104 +11 1 +.names 20104 20105 +1 1 +.names 20101 20106 +0 1 +.names 20103 20107 +0 1 +.names 1136 56681 20108 +01 1 +10 1 +.names 20108 20109 +1 1 +.names 20116 20119 20110 +1- 1 +-1 1 +.names 20110 20111 +1 1 +.names 20086 20112 +0 1 +.names 20098 20113 +0 1 +.names 20112 20113 20114 +1- 1 +-1 1 +.names 20105 20115 +0 1 +.names 20114 20115 20116 +1- 1 +-1 1 +.names 20123 20126 20117 +11 1 +.names 20117 20118 +1 1 +.names 20118 20119 +0 1 +.names 20069 20120 +0 1 +.names 20111 20121 +0 1 +.names 19922 20122 +1 1 +.names 20109 20123 +0 1 +.names 20127 20124 +0 1 +.names 20124 20125 +1 1 +.names 20125 20126 +0 1 +.names 1137 20122 20127 +01 1 +10 1 +.names 20130 20128 +0 1 +.names 20128 20129 +1 1 +.names 1138 56673 20130 +01 1 +10 1 +.names 20133 20131 +0 1 +.names 20131 20132 +1 1 +.names 56672 1139 20133 +01 1 +10 1 +.names 20139 20140 20134 +1- 1 +-1 1 +.names 20134 20135 +1 1 +.names 20211 20212 20136 +1- 1 +-1 1 +.names 20136 20137 +1 1 +.names 20129 20138 +0 1 +.names 20137 20138 20139 +1- 1 +-1 1 +.names 20132 20140 +0 1 +.names 20143 20141 +0 1 +.names 20141 20142 +1 1 +.names 56674 1140 20143 +01 1 +10 1 +.names 20146 20144 +0 1 +.names 20144 20145 +1 1 +.names 56671 1141 20146 +01 1 +10 1 +.names 20149 20150 20147 +1- 1 +-1 1 +.names 20147 20148 +1 1 +.names 20142 20149 +0 1 +.names 20145 20150 +0 1 +.names 20153 20151 +0 1 +.names 20151 20152 +1 1 +.names 56678 1142 20153 +01 1 +10 1 +.names 20156 20154 +0 1 +.names 20154 20155 +1 1 +.names 56675 1143 20156 +01 1 +10 1 +.names 20159 20157 +0 1 +.names 20157 20158 +1 1 +.names 56677 1144 20159 +01 1 +10 1 +.names 20170 20173 20160 +1- 1 +-1 1 +.names 20160 20161 +1 1 +.names 20161 20162 +0 1 +.names 20135 20163 +0 1 +.names 20162 20163 20164 +11 1 +.names 20148 20165 +0 1 +.names 20152 20166 +0 1 +.names 20155 20167 +0 1 +.names 20166 20167 20168 +1- 1 +-1 1 +.names 20158 20169 +0 1 +.names 20168 20169 20170 +1- 1 +-1 1 +.names 20174 20171 +0 1 +.names 20171 20172 +1 1 +.names 20172 20173 +0 1 +.names 56676 1145 20174 +01 1 +10 1 +.names 20179 20182 20175 +11 1 +.names 20175 20176 +1 1 +.names 20177 +.names 20177 20178 +1 1 +.names 20178 20179 +0 1 +.names 20180 +.names 20180 20181 +1 1 +.names 20181 20182 +0 1 +.names 20187 20190 20183 +11 1 +.names 20183 20184 +1 1 +.names 20185 +.names 20185 20186 +1 1 +.names 20186 20187 +0 1 +.names 20188 +.names 20188 20189 +1 1 +.names 20189 20190 +0 1 +.names 20195 20198 20191 +11 1 +.names 20191 20192 +1 1 +.names 20193 +.names 20193 20194 +1 1 +.names 20194 20195 +0 1 +.names 20196 +.names 20196 20197 +1 1 +.names 20197 20198 +0 1 +.names 20203 20206 20199 +11 1 +.names 20199 20200 +1 1 +.names 20201 +.names 20201 20202 +1 1 +.names 20202 20203 +0 1 +.names 20204 +.names 20204 20205 +1 1 +.names 20205 20206 +0 1 +.names 20200 20207 +0 1 +.names 20192 20208 +0 1 +.names 20207 20208 20209 +1- 1 +-1 1 +.names 20184 20210 +0 1 +.names 20209 20210 20211 +1- 1 +-1 1 +.names 20176 20212 +0 1 +.names 20215 20213 +0 1 +.names 20213 20214 +1 1 +.names 1092 257 20215 +01 1 +10 1 +.names 20218 20216 +0 1 +.names 20216 20217 +1 1 +.names 1093 267 20218 +01 1 +10 1 +.names 20221 20219 +0 1 +.names 20219 20220 +1 1 +.names 1094 253 20221 +01 1 +10 1 +.names 20224 20214 20222 +11 1 +.names 20222 20223 +1 1 +.names 20217 20220 20224 +11 1 +.names 20227 20225 +0 1 +.names 20225 20226 +1 1 +.names 1095 255 20227 +01 1 +10 1 +.names 20230 20228 +0 1 +.names 20228 20229 +1 1 +.names 1096 263 20230 +01 1 +10 1 +.names 20233 20231 +0 1 +.names 20231 20232 +1 1 +.names 1097 249 20233 +01 1 +10 1 +.names 20238 20239 20234 +1- 1 +-1 1 +.names 20234 20235 +1 1 +.names 20226 20236 +0 1 +.names 20229 20237 +0 1 +.names 20236 20237 20238 +1- 1 +-1 1 +.names 20232 20239 +0 1 +.names 20235 20240 +0 1 +.names 20240 20241 +1 1 +.names 1098 261 20242 +01 1 +10 1 +.names 20242 20243 +1 1 +.names 1099 254 20244 +01 1 +10 1 +.names 20244 20245 +1 1 +.names 20248 20249 20246 +11 1 +.names 20246 20247 +1 1 +.names 20243 20248 +0 1 +.names 20245 20249 +0 1 +.names 1100 265 20250 +01 1 +10 1 +.names 20250 20251 +1 1 +.names 1101 266 20252 +01 1 +10 1 +.names 20252 20253 +1 1 +.names 20256 20257 20254 +11 1 +.names 20254 20255 +1 1 +.names 20251 20256 +0 1 +.names 20253 20257 +0 1 +.names 20264 20265 20258 +1- 1 +-1 1 +.names 20258 20259 +1 1 +.names 20223 20260 +0 1 +.names 20241 20261 +0 1 +.names 20260 20261 20262 +1- 1 +-1 1 +.names 20247 20263 +0 1 +.names 20262 20263 20264 +1- 1 +-1 1 +.names 20255 20265 +0 1 +.names 20268 20266 +0 1 +.names 20266 20267 +1 1 +.names 1102 259 20268 +01 1 +10 1 +.names 20271 20269 +0 1 +.names 20269 20270 +1 1 +.names 1103 256 20271 +01 1 +10 1 +.names 20274 20272 +0 1 +.names 20272 20273 +1 1 +.names 1104 258 20274 +01 1 +10 1 +.names 20277 20273 20275 +11 1 +.names 20275 20276 +1 1 +.names 20267 20270 20277 +11 1 +.names 20280 20278 +0 1 +.names 20278 20279 +1 1 +.names 1105 264 20280 +01 1 +10 1 +.names 20283 20281 +0 1 +.names 20281 20282 +1 1 +.names 1106 252 20283 +01 1 +10 1 +.names 20286 20284 +0 1 +.names 20284 20285 +1 1 +.names 20286 +.names 20289 20285 20287 +11 1 +.names 20287 20288 +1 1 +.names 20279 20282 20289 +11 1 +.names 1107 260 20290 +01 1 +10 1 +.names 20290 20291 +1 1 +.names 1108 262 20292 +01 1 +10 1 +.names 20292 20293 +1 1 +.names 20296 20297 20294 +11 1 +.names 20294 20295 +1 1 +.names 20291 20296 +0 1 +.names 20293 20297 +0 1 +.names 1109 250 20298 +01 1 +10 1 +.names 20298 20299 +1 1 +.names 20306 20309 20300 +1- 1 +-1 1 +.names 20300 20301 +1 1 +.names 20276 20302 +0 1 +.names 20288 20303 +0 1 +.names 20302 20303 20304 +1- 1 +-1 1 +.names 20295 20305 +0 1 +.names 20304 20305 20306 +1- 1 +-1 1 +.names 20314 20317 20307 +11 1 +.names 20307 20308 +1 1 +.names 20308 20309 +0 1 +.names 20259 20310 +0 1 +.names 20301 20311 +0 1 +.names 251 20312 +0 1 +.names 20312 20313 +1 1 +.names 20299 20314 +0 1 +.names 20318 20315 +0 1 +.names 20315 20316 +1 1 +.names 20316 20317 +0 1 +.names 1110 20313 20318 +01 1 +10 1 +.names 20321 20319 +0 1 +.names 20319 20320 +1 1 +.names 1111 242 20321 +01 1 +10 1 +.names 20324 20322 +0 1 +.names 20322 20323 +1 1 +.names 241 1112 20324 +01 1 +10 1 +.names 20330 20331 20325 +1- 1 +-1 1 +.names 20325 20326 +1 1 +.names 20402 20403 20327 +1- 1 +-1 1 +.names 20327 20328 +1 1 +.names 20320 20329 +0 1 +.names 20328 20329 20330 +1- 1 +-1 1 +.names 20323 20331 +0 1 +.names 20334 20332 +0 1 +.names 20332 20333 +1 1 +.names 243 1113 20334 +01 1 +10 1 +.names 20337 20335 +0 1 +.names 20335 20336 +1 1 +.names 240 1114 20337 +01 1 +10 1 +.names 20340 20341 20338 +1- 1 +-1 1 +.names 20338 20339 +1 1 +.names 20333 20340 +0 1 +.names 20336 20341 +0 1 +.names 20344 20342 +0 1 +.names 20342 20343 +1 1 +.names 247 1115 20344 +01 1 +10 1 +.names 20347 20345 +0 1 +.names 20345 20346 +1 1 +.names 244 1116 20347 +01 1 +10 1 +.names 20350 20348 +0 1 +.names 20348 20349 +1 1 +.names 246 1117 20350 +01 1 +10 1 +.names 20361 20364 20351 +1- 1 +-1 1 +.names 20351 20352 +1 1 +.names 20352 20353 +0 1 +.names 20326 20354 +0 1 +.names 20353 20354 20355 +11 1 +.names 20339 20356 +0 1 +.names 20343 20357 +0 1 +.names 20346 20358 +0 1 +.names 20357 20358 20359 +1- 1 +-1 1 +.names 20349 20360 +0 1 +.names 20359 20360 20361 +1- 1 +-1 1 +.names 20365 20362 +0 1 +.names 20362 20363 +1 1 +.names 20363 20364 +0 1 +.names 245 1118 20365 +01 1 +10 1 +.names 20370 20373 20366 +11 1 +.names 20366 20367 +1 1 +.names 20368 +.names 20368 20369 +1 1 +.names 20369 20370 +0 1 +.names 20371 +.names 20371 20372 +1 1 +.names 20372 20373 +0 1 +.names 20378 20381 20374 +11 1 +.names 20374 20375 +1 1 +.names 20376 +.names 20376 20377 +1 1 +.names 20377 20378 +0 1 +.names 20379 +.names 20379 20380 +1 1 +.names 20380 20381 +0 1 +.names 20386 20389 20382 +11 1 +.names 20382 20383 +1 1 +.names 20384 +.names 20384 20385 +1 1 +.names 20385 20386 +0 1 +.names 20387 +.names 20387 20388 +1 1 +.names 20388 20389 +0 1 +.names 20394 20397 20390 +11 1 +.names 20390 20391 +1 1 +.names 20392 +.names 20392 20393 +1 1 +.names 20393 20394 +0 1 +.names 20395 +.names 20395 20396 +1 1 +.names 20396 20397 +0 1 +.names 20391 20398 +0 1 +.names 20383 20399 +0 1 +.names 20398 20399 20400 +1- 1 +-1 1 +.names 20375 20401 +0 1 +.names 20400 20401 20402 +1- 1 +-1 1 +.names 20367 20403 +0 1 +.names 20406 20404 +0 1 +.names 20404 20405 +1 1 +.names 1119 257 20406 +01 1 +10 1 +.names 20409 20407 +0 1 +.names 20407 20408 +1 1 +.names 1120 267 20409 +01 1 +10 1 +.names 20412 20410 +0 1 +.names 20410 20411 +1 1 +.names 1121 253 20412 +01 1 +10 1 +.names 20415 20405 20413 +11 1 +.names 20413 20414 +1 1 +.names 20408 20411 20415 +11 1 +.names 20418 20416 +0 1 +.names 20416 20417 +1 1 +.names 1122 255 20418 +01 1 +10 1 +.names 20421 20419 +0 1 +.names 20419 20420 +1 1 +.names 1123 263 20421 +01 1 +10 1 +.names 20424 20422 +0 1 +.names 20422 20423 +1 1 +.names 1124 249 20424 +01 1 +10 1 +.names 20429 20430 20425 +1- 1 +-1 1 +.names 20425 20426 +1 1 +.names 20417 20427 +0 1 +.names 20420 20428 +0 1 +.names 20427 20428 20429 +1- 1 +-1 1 +.names 20423 20430 +0 1 +.names 20426 20431 +0 1 +.names 20431 20432 +1 1 +.names 1125 261 20433 +01 1 +10 1 +.names 20433 20434 +1 1 +.names 1126 254 20435 +01 1 +10 1 +.names 20435 20436 +1 1 +.names 20439 20440 20437 +11 1 +.names 20437 20438 +1 1 +.names 20434 20439 +0 1 +.names 20436 20440 +0 1 +.names 1127 265 20441 +01 1 +10 1 +.names 20441 20442 +1 1 +.names 1128 266 20443 +01 1 +10 1 +.names 20443 20444 +1 1 +.names 20447 20448 20445 +11 1 +.names 20445 20446 +1 1 +.names 20442 20447 +0 1 +.names 20444 20448 +0 1 +.names 20455 20456 20449 +1- 1 +-1 1 +.names 20449 20450 +1 1 +.names 20414 20451 +0 1 +.names 20432 20452 +0 1 +.names 20451 20452 20453 +1- 1 +-1 1 +.names 20438 20454 +0 1 +.names 20453 20454 20455 +1- 1 +-1 1 +.names 20446 20456 +0 1 +.names 20459 20457 +0 1 +.names 20457 20458 +1 1 +.names 1129 259 20459 +01 1 +10 1 +.names 20462 20460 +0 1 +.names 20460 20461 +1 1 +.names 1130 256 20462 +01 1 +10 1 +.names 20465 20463 +0 1 +.names 20463 20464 +1 1 +.names 1131 258 20465 +01 1 +10 1 +.names 20468 20464 20466 +11 1 +.names 20466 20467 +1 1 +.names 20458 20461 20468 +11 1 +.names 20471 20469 +0 1 +.names 20469 20470 +1 1 +.names 1132 264 20471 +01 1 +10 1 +.names 20474 20472 +0 1 +.names 20472 20473 +1 1 +.names 1133 252 20474 +01 1 +10 1 +.names 20477 20475 +0 1 +.names 20475 20476 +1 1 +.names 20477 +.names 20480 20476 20478 +11 1 +.names 20478 20479 +1 1 +.names 20470 20473 20480 +11 1 +.names 1134 260 20481 +01 1 +10 1 +.names 20481 20482 +1 1 +.names 1135 262 20483 +01 1 +10 1 +.names 20483 20484 +1 1 +.names 20487 20488 20485 +11 1 +.names 20485 20486 +1 1 +.names 20482 20487 +0 1 +.names 20484 20488 +0 1 +.names 1136 250 20489 +01 1 +10 1 +.names 20489 20490 +1 1 +.names 20497 20500 20491 +1- 1 +-1 1 +.names 20491 20492 +1 1 +.names 20467 20493 +0 1 +.names 20479 20494 +0 1 +.names 20493 20494 20495 +1- 1 +-1 1 +.names 20486 20496 +0 1 +.names 20495 20496 20497 +1- 1 +-1 1 +.names 20504 20507 20498 +11 1 +.names 20498 20499 +1 1 +.names 20499 20500 +0 1 +.names 20450 20501 +0 1 +.names 20492 20502 +0 1 +.names 20312 20503 +1 1 +.names 20490 20504 +0 1 +.names 20508 20505 +0 1 +.names 20505 20506 +1 1 +.names 20506 20507 +0 1 +.names 1137 20503 20508 +01 1 +10 1 +.names 20511 20509 +0 1 +.names 20509 20510 +1 1 +.names 1138 242 20511 +01 1 +10 1 +.names 20514 20512 +0 1 +.names 20512 20513 +1 1 +.names 241 1139 20514 +01 1 +10 1 +.names 20520 20521 20515 +1- 1 +-1 1 +.names 20515 20516 +1 1 +.names 20592 20593 20517 +1- 1 +-1 1 +.names 20517 20518 +1 1 +.names 20510 20519 +0 1 +.names 20518 20519 20520 +1- 1 +-1 1 +.names 20513 20521 +0 1 +.names 20524 20522 +0 1 +.names 20522 20523 +1 1 +.names 243 1140 20524 +01 1 +10 1 +.names 20527 20525 +0 1 +.names 20525 20526 +1 1 +.names 240 1141 20527 +01 1 +10 1 +.names 20530 20531 20528 +1- 1 +-1 1 +.names 20528 20529 +1 1 +.names 20523 20530 +0 1 +.names 20526 20531 +0 1 +.names 20534 20532 +0 1 +.names 20532 20533 +1 1 +.names 247 1142 20534 +01 1 +10 1 +.names 20537 20535 +0 1 +.names 20535 20536 +1 1 +.names 244 1143 20537 +01 1 +10 1 +.names 20540 20538 +0 1 +.names 20538 20539 +1 1 +.names 246 1144 20540 +01 1 +10 1 +.names 20551 20554 20541 +1- 1 +-1 1 +.names 20541 20542 +1 1 +.names 20542 20543 +0 1 +.names 20516 20544 +0 1 +.names 20543 20544 20545 +11 1 +.names 20529 20546 +0 1 +.names 20533 20547 +0 1 +.names 20536 20548 +0 1 +.names 20547 20548 20549 +1- 1 +-1 1 +.names 20539 20550 +0 1 +.names 20549 20550 20551 +1- 1 +-1 1 +.names 20555 20552 +0 1 +.names 20552 20553 +1 1 +.names 20553 20554 +0 1 +.names 245 1145 20555 +01 1 +10 1 +.names 20560 20563 20556 +11 1 +.names 20556 20557 +1 1 +.names 20558 +.names 20558 20559 +1 1 +.names 20559 20560 +0 1 +.names 20561 +.names 20561 20562 +1 1 +.names 20562 20563 +0 1 +.names 20568 20571 20564 +11 1 +.names 20564 20565 +1 1 +.names 20566 +.names 20566 20567 +1 1 +.names 20567 20568 +0 1 +.names 20569 +.names 20569 20570 +1 1 +.names 20570 20571 +0 1 +.names 20576 20579 20572 +11 1 +.names 20572 20573 +1 1 +.names 20574 +.names 20574 20575 +1 1 +.names 20575 20576 +0 1 +.names 20577 +.names 20577 20578 +1 1 +.names 20578 20579 +0 1 +.names 20584 20587 20580 +11 1 +.names 20580 20581 +1 1 +.names 20582 +.names 20582 20583 +1 1 +.names 20583 20584 +0 1 +.names 20585 +.names 20585 20586 +1 1 +.names 20586 20587 +0 1 +.names 20581 20588 +0 1 +.names 20573 20589 +0 1 +.names 20588 20589 20590 +1- 1 +-1 1 +.names 20565 20591 +0 1 +.names 20590 20591 20592 +1- 1 +-1 1 +.names 20557 20593 +0 1 +.names 2413 20598 20594 +1- 1 +-1 1 +.names 20594 20595 +1 1 +.names 1783 508 20596 +01 1 +10 1 +.names 20596 20597 +1 1 +.names 20597 20598 +0 1 +.names 20601 20602 20599 +11 1 +.names 20599 20600 +1 1 +.names 1146 20601 +0 1 +.names 1147 20602 +0 1 +.names 20605 20606 20603 +11 1 +.names 20603 20604 +1 1 +.names 1148 20605 +0 1 +.names 1149 20606 +0 1 +.names 20609 20610 20607 +1- 1 +-1 1 +.names 20607 20608 +1 1 +.names 20600 20609 +0 1 +.names 20604 20610 +0 1 +.names 20613 20614 20611 +11 1 +.names 20611 20612 +1 1 +.names 1150 20613 +0 1 +.names 1151 20614 +0 1 +.names 20617 20618 20615 +11 1 +.names 20615 20616 +1 1 +.names 1152 20617 +0 1 +.names 1153 20618 +0 1 +.names 20621 20622 20619 +1- 1 +-1 1 +.names 20619 20620 +1 1 +.names 20612 20621 +0 1 +.names 20616 20622 +0 1 +.names 20625 20626 20623 +11 1 +.names 20623 20624 +1 1 +.names 20608 20625 +0 1 +.names 20620 20626 +0 1 +.names 20629 2413 20627 +11 1 +.names 20627 20628 +1 1 +.names 1154 20629 +0 1 +.names 20632 20633 20630 +11 1 +.names 20630 20631 +1 1 +.names 1155 20632 +0 1 +.names 1156 20633 +0 1 +.names 20636 20637 20634 +1- 1 +-1 1 +.names 20634 20635 +1 1 +.names 20628 20636 +0 1 +.names 20631 20637 +0 1 +.names 20640 20641 20638 +11 1 +.names 20638 20639 +1 1 +.names 1157 20640 +0 1 +.names 1158 20641 +0 1 +.names 20644 20645 20642 +11 1 +.names 20642 20643 +1 1 +.names 1159 20644 +0 1 +.names 1160 20645 +0 1 +.names 20648 20649 20646 +1- 1 +-1 1 +.names 20646 20647 +1 1 +.names 20639 20648 +0 1 +.names 20643 20649 +0 1 +.names 20652 20653 20650 +11 1 +.names 20650 20651 +1 1 +.names 20635 20652 +0 1 +.names 20647 20653 +0 1 +.names 20656 20657 20654 +1- 1 +-1 1 +.names 20654 20655 +1 1 +.names 20624 20656 +0 1 +.names 20651 20657 +0 1 +.names 20660 20661 20658 +11 1 +.names 20658 20659 +1 1 +.names 1161 20660 +0 1 +.names 1162 20661 +0 1 +.names 20664 20665 20662 +11 1 +.names 20662 20663 +1 1 +.names 1163 20664 +0 1 +.names 1164 20665 +0 1 +.names 20668 20669 20666 +11 1 +.names 20666 20667 +1 1 +.names 1165 20668 +0 1 +.names 1166 20669 +0 1 +.names 20672 20673 20670 +11 1 +.names 20670 20671 +1 1 +.names 1167 20672 +0 1 +.names 1168 20673 +0 1 +.names 2413 20674 +1 1 +.names 20674 20675 +1 1 +.names 20678 2413 20676 +11 1 +.names 20676 20677 +1 1 +.names 1169 20678 +0 1 +.names 20655 20679 +0 1 +.names 20685 20688 20680 +1- 1 +-1 1 +.names 20680 20681 +1 1 +.names 20681 20682 +0 1 +.names 20698 20671 20683 +11 1 +.names 20683 20684 +1 1 +.names 20684 20685 +0 1 +.names 20700 20686 +0 1 +.names 20686 20687 +1 1 +.names 20687 20688 +0 1 +.names 20691 20692 20689 +11 1 +.names 20689 20690 +1 1 +.names 1170 20691 +0 1 +.names 1171 20692 +0 1 +.names 20695 20696 20693 +11 1 +.names 20693 20694 +1 1 +.names 1172 20695 +0 1 +.names 1173 20696 +0 1 +.names 20659 20663 20697 +11 1 +.names 20697 20667 20698 +11 1 +.names 20705 20706 20699 +1- 1 +-1 1 +.names 20699 20700 +1 1 +.names 20675 20701 +0 1 +.names 20677 20702 +0 1 +.names 20701 20702 20703 +1- 1 +-1 1 +.names 20690 20704 +0 1 +.names 20703 20704 20705 +1- 1 +-1 1 +.names 20694 20706 +0 1 +.names 20709 20710 20707 +11 1 +.names 20707 20708 +1 1 +.names 1174 20709 +0 1 +.names 1175 20710 +0 1 +.names 20713 20714 20711 +11 1 +.names 20711 20712 +1 1 +.names 1176 20713 +0 1 +.names 1177 20714 +0 1 +.names 20717 20718 20715 +1- 1 +-1 1 +.names 20715 20716 +1 1 +.names 20708 20717 +0 1 +.names 20712 20718 +0 1 +.names 20721 20722 20719 +11 1 +.names 20719 20720 +1 1 +.names 1178 20721 +0 1 +.names 1179 20722 +0 1 +.names 20725 20726 20723 +11 1 +.names 20723 20724 +1 1 +.names 1180 20725 +0 1 +.names 1181 20726 +0 1 +.names 20729 20730 20727 +1- 1 +-1 1 +.names 20727 20728 +1 1 +.names 20720 20729 +0 1 +.names 20724 20730 +0 1 +.names 20733 20734 20731 +11 1 +.names 20731 20732 +1 1 +.names 20716 20733 +0 1 +.names 20728 20734 +0 1 +.names 20737 2413 20735 +11 1 +.names 20735 20736 +1 1 +.names 1182 20737 +0 1 +.names 20740 20741 20738 +11 1 +.names 20738 20739 +1 1 +.names 1183 20740 +0 1 +.names 1184 20741 +0 1 +.names 20744 20745 20742 +1- 1 +-1 1 +.names 20742 20743 +1 1 +.names 20736 20744 +0 1 +.names 20739 20745 +0 1 +.names 20748 20749 20746 +11 1 +.names 20746 20747 +1 1 +.names 1185 20748 +0 1 +.names 1186 20749 +0 1 +.names 20752 20753 20750 +11 1 +.names 20750 20751 +1 1 +.names 1187 20752 +0 1 +.names 1188 20753 +0 1 +.names 20756 20757 20754 +1- 1 +-1 1 +.names 20754 20755 +1 1 +.names 20747 20756 +0 1 +.names 20751 20757 +0 1 +.names 20760 20761 20758 +11 1 +.names 20758 20759 +1 1 +.names 20743 20760 +0 1 +.names 20755 20761 +0 1 +.names 20764 20765 20762 +1- 1 +-1 1 +.names 20762 20763 +1 1 +.names 20732 20764 +0 1 +.names 20759 20765 +0 1 +.names 20768 20769 20766 +11 1 +.names 20766 20767 +1 1 +.names 1189 20768 +0 1 +.names 1190 20769 +0 1 +.names 20772 20773 20770 +11 1 +.names 20770 20771 +1 1 +.names 1191 20772 +0 1 +.names 1192 20773 +0 1 +.names 20776 20777 20774 +11 1 +.names 20774 20775 +1 1 +.names 1193 20776 +0 1 +.names 1194 20777 +0 1 +.names 20780 20781 20778 +11 1 +.names 20778 20779 +1 1 +.names 1195 20780 +0 1 +.names 1196 20781 +0 1 +.names 2413 20782 +1 1 +.names 20782 20783 +1 1 +.names 20786 2413 20784 +11 1 +.names 20784 20785 +1 1 +.names 1197 20786 +0 1 +.names 20763 20787 +0 1 +.names 20793 20796 20788 +1- 1 +-1 1 +.names 20788 20789 +1 1 +.names 20789 20790 +0 1 +.names 20806 20779 20791 +11 1 +.names 20791 20792 +1 1 +.names 20792 20793 +0 1 +.names 20808 20794 +0 1 +.names 20794 20795 +1 1 +.names 20795 20796 +0 1 +.names 20799 20800 20797 +11 1 +.names 20797 20798 +1 1 +.names 1198 20799 +0 1 +.names 1199 20800 +0 1 +.names 20803 20804 20801 +11 1 +.names 20801 20802 +1 1 +.names 1200 20803 +0 1 +.names 1201 20804 +0 1 +.names 20767 20771 20805 +11 1 +.names 20805 20775 20806 +11 1 +.names 20813 20814 20807 +1- 1 +-1 1 +.names 20807 20808 +1 1 +.names 20783 20809 +0 1 +.names 20785 20810 +0 1 +.names 20809 20810 20811 +1- 1 +-1 1 +.names 20798 20812 +0 1 +.names 20811 20812 20813 +1- 1 +-1 1 +.names 20802 20814 +0 1 +.names 20819 20822 20815 +1- 1 +-1 1 +.names 20815 20816 +1 1 +.names 20853 20817 +0 1 +.names 20817 20818 +1 1 +.names 20818 20819 +0 1 +.names 20854 20820 +0 1 +.names 20820 20821 +1 1 +.names 20821 20822 +0 1 +.names 20827 20830 20823 +1- 1 +-1 1 +.names 20823 20824 +1 1 +.names 20840 20825 +0 1 +.names 20825 20826 +1 1 +.names 20826 20827 +0 1 +.names 20842 20828 +0 1 +.names 20828 20829 +1 1 +.names 20829 20830 +0 1 +.names 20835 20838 20831 +1- 1 +-1 1 +.names 20831 20832 +1 1 +.names 20844 20833 +0 1 +.names 20833 20834 +1 1 +.names 20834 20835 +0 1 +.names 20845 20836 +0 1 +.names 20836 20837 +1 1 +.names 20837 20838 +0 1 +.names 27550 27554 56723 +1- 1 +-1 1 +.names 56723 1148 20840 +01 1 +10 1 +.names 27592 27596 56722 +1- 1 +-1 1 +.names 56722 1173 20842 +01 1 +10 1 +.names 27536 27540 56724 +1- 1 +-1 1 +.names 56724 1164 20844 +01 1 +10 1 +.names 56721 1163 20845 +01 1 +10 1 +.names 20848 20846 +0 1 +.names 20846 20847 +1 1 +.names 56709 1158 20848 +01 1 +10 1 +.names 20852 20849 +0 1 +.names 20849 20850 +1 1 +.names 27585 27589 56715 +1- 1 +-1 1 +.names 56715 1157 20852 +01 1 +10 1 +.names 56710 1159 20853 +01 1 +10 1 +.names 56713 1170 20854 +01 1 +10 1 +.names 20858 20855 +0 1 +.names 20855 20856 +1 1 +.names 27607 27611 56720 +1- 1 +-1 1 +.names 56720 1165 20858 +01 1 +10 1 +.names 20862 20859 +0 1 +.names 20859 20860 +1 1 +.names 27578 27582 56717 +1- 1 +-1 1 +.names 56717 1168 20862 +01 1 +10 1 +.names 20866 20863 +0 1 +.names 20863 20864 +1 1 +.names 27521 27525 56718 +1- 1 +-1 1 +.names 56718 1154 20866 +01 1 +10 1 +.names 20870 20867 +0 1 +.names 20867 20868 +1 1 +.names 27677 27681 56719 +1- 1 +-1 1 +.names 56719 1152 20870 +01 1 +10 1 +.names 20873 20871 +0 1 +.names 20871 20872 +1 1 +.names 56705 1166 20873 +01 1 +10 1 +.names 20876 20874 +0 1 +.names 20874 20875 +1 1 +.names 56703 1167 20876 +01 1 +10 1 +.names 20879 20877 +0 1 +.names 20877 20878 +1 1 +.names 56704 1155 20879 +01 1 +10 1 +.names 20882 20880 +0 1 +.names 20880 20881 +1 1 +.names 56706 1162 20882 +01 1 +10 1 +.names 20885 20886 20883 +11 1 +.names 20883 20884 +1 1 +.names 20832 20885 +0 1 +.names 20824 20886 +0 1 +.names 20893 20894 20887 +1- 1 +-1 1 +.names 20887 20888 +1 1 +.names 20856 20889 +0 1 +.names 20860 20890 +0 1 +.names 20889 20890 20891 +1- 1 +-1 1 +.names 20864 20892 +0 1 +.names 20891 20892 20893 +1- 1 +-1 1 +.names 20868 20894 +0 1 +.names 20901 20902 20895 +1- 1 +-1 1 +.names 20895 20896 +1 1 +.names 20872 20897 +0 1 +.names 20875 20898 +0 1 +.names 20897 20898 20899 +1- 1 +-1 1 +.names 20878 20900 +0 1 +.names 20899 20900 20901 +1- 1 +-1 1 +.names 20881 20902 +0 1 +.names 20905 20906 20903 +1- 1 +-1 1 +.names 20903 20904 +1 1 +.names 20847 20905 +0 1 +.names 20850 20906 +0 1 +.names 20909 20910 20907 +11 1 +.names 20907 20908 +1 1 +.names 20816 20909 +0 1 +.names 20904 20910 +0 1 +.names 20915 20916 20911 +1- 1 +-1 1 +.names 20911 20912 +1 1 +.names 20896 20888 20913 +1- 1 +-1 1 +.names 20884 20914 +0 1 +.names 20913 20914 20915 +1- 1 +-1 1 +.names 20908 20916 +0 1 +.names 20920 20917 +0 1 +.names 20917 20918 +1 1 +.names 27649 27653 56726 +1- 1 +-1 1 +.names 56726 1153 20920 +01 1 +10 1 +.names 20924 20921 +0 1 +.names 20921 20922 +1 1 +.names 27642 27646 56725 +1- 1 +-1 1 +.names 56725 1171 20924 +01 1 +10 1 +.names 20927 20925 +0 1 +.names 20925 20926 +1 1 +.names 20927 +.names 20930 20928 +0 1 +.names 20928 20929 +1 1 +.names 20930 +.names 20934 20929 20931 +11 1 +.names 20931 20932 +1 1 +.names 20918 20922 20933 +11 1 +.names 20933 20926 20934 +11 1 +.names 20937 20935 +0 1 +.names 20935 20936 +1 1 +.names 56708 1161 20937 +01 1 +10 1 +.names 20941 20938 +0 1 +.names 20938 20939 +1 1 +.names 27557 27561 56701 +1- 1 +-1 1 +.names 56701 1149 20941 +01 1 +10 1 +.names 20944 20942 +0 1 +.names 20942 20943 +1 1 +.names 56702 1160 20944 +01 1 +10 1 +.names 20947 20945 +0 1 +.names 20945 20946 +1 1 +.names 56707 1172 20947 +01 1 +10 1 +.names 20954 20955 20948 +1- 1 +-1 1 +.names 20948 20949 +1 1 +.names 20936 20950 +0 1 +.names 20939 20951 +0 1 +.names 20950 20951 20952 +1- 1 +-1 1 +.names 20943 20953 +0 1 +.names 20952 20953 20954 +1- 1 +-1 1 +.names 20946 20955 +0 1 +.names 20949 20956 +0 1 +.names 20956 20957 +1 1 +.names 20960 20958 +0 1 +.names 20958 20959 +1 1 +.names 56714 1147 20960 +01 1 +10 1 +.names 20964 20961 +0 1 +.names 20961 20962 +1 1 +.names 27475 27479 56716 +1- 1 +-1 1 +.names 56716 1146 20964 +01 1 +10 1 +.names 20967 20968 20965 +1- 1 +-1 1 +.names 20965 20966 +1 1 +.names 20959 20967 +0 1 +.names 20962 20968 +0 1 +.names 20971 20969 +0 1 +.names 20969 20970 +1 1 +.names 56712 1156 20971 +01 1 +10 1 +.names 20974 20972 +0 1 +.names 20972 20973 +1 1 +.names 56711 1151 20974 +01 1 +10 1 +.names 20977 20978 20975 +1- 1 +-1 1 +.names 20975 20976 +1 1 +.names 20970 20977 +0 1 +.names 20973 20978 +0 1 +.names 20981 20982 20979 +11 1 +.names 20979 20980 +1 1 +.names 20966 20981 +0 1 +.names 20976 20982 +0 1 +.names 20985 20983 +0 1 +.names 20983 20984 +1 1 +.names 20985 +.names 20989 20986 +0 1 +.names 20986 20987 +1 1 +.names 27684 27688 56728 +1- 1 +-1 1 +.names 56728 1150 20989 +01 1 +10 1 +.names 20992 20993 20990 +1- 1 +-1 1 +.names 20990 20991 +1 1 +.names 20984 20992 +0 1 +.names 20987 20993 +0 1 +.names 21000 21003 20994 +1- 1 +-1 1 +.names 20994 20995 +1 1 +.names 20932 20996 +0 1 +.names 20957 20997 +0 1 +.names 20996 20997 20998 +1- 1 +-1 1 +.names 20980 20999 +0 1 +.names 20998 20999 21000 +1- 1 +-1 1 +.names 21010 21013 21001 +11 1 +.names 21001 21002 +1 1 +.names 21002 21003 +0 1 +.names 20912 21004 +0 1 +.names 20995 21005 +0 1 +.names 21009 21006 +0 1 +.names 21006 21007 +1 1 +.names 27628 27632 56727 +1- 1 +-1 1 +.names 56727 1169 21009 +01 1 +10 1 +.names 20991 21010 +0 1 +.names 21014 21017 21011 +1- 1 +-1 1 +.names 21011 21012 +1 1 +.names 21012 21013 +0 1 +.names 21007 21014 +0 1 +.names 21018 21015 +0 1 +.names 21015 21016 +1 1 +.names 21016 21017 +0 1 +.names 21018 +.names 21023 21026 21019 +1- 1 +-1 1 +.names 21019 21020 +1 1 +.names 21053 21021 +0 1 +.names 21021 21022 +1 1 +.names 21022 21023 +0 1 +.names 21054 21024 +0 1 +.names 21024 21025 +1 1 +.names 21025 21026 +0 1 +.names 21031 21034 21027 +1- 1 +-1 1 +.names 21027 21028 +1 1 +.names 21043 21029 +0 1 +.names 21029 21030 +1 1 +.names 21030 21031 +0 1 +.names 21044 21032 +0 1 +.names 21032 21033 +1 1 +.names 21033 21034 +0 1 +.names 21039 21042 21035 +1- 1 +-1 1 +.names 21035 21036 +1 1 +.names 21045 21037 +0 1 +.names 21037 21038 +1 1 +.names 21038 21039 +0 1 +.names 21046 21040 +0 1 +.names 21040 21041 +1 1 +.names 21041 21042 +0 1 +.names 56723 1176 21043 +01 1 +10 1 +.names 56722 1201 21044 +01 1 +10 1 +.names 56724 1192 21045 +01 1 +10 1 +.names 56721 1191 21046 +01 1 +10 1 +.names 21049 21047 +0 1 +.names 21047 21048 +1 1 +.names 56709 1186 21049 +01 1 +10 1 +.names 21052 21050 +0 1 +.names 21050 21051 +1 1 +.names 56715 1185 21052 +01 1 +10 1 +.names 56710 1187 21053 +01 1 +10 1 +.names 56713 1198 21054 +01 1 +10 1 +.names 21057 21055 +0 1 +.names 21055 21056 +1 1 +.names 56720 1193 21057 +01 1 +10 1 +.names 21060 21058 +0 1 +.names 21058 21059 +1 1 +.names 56717 1196 21060 +01 1 +10 1 +.names 21063 21061 +0 1 +.names 21061 21062 +1 1 +.names 56718 1182 21063 +01 1 +10 1 +.names 21066 21064 +0 1 +.names 21064 21065 +1 1 +.names 56719 1180 21066 +01 1 +10 1 +.names 21069 21067 +0 1 +.names 21067 21068 +1 1 +.names 56705 1194 21069 +01 1 +10 1 +.names 21072 21070 +0 1 +.names 21070 21071 +1 1 +.names 56703 1195 21072 +01 1 +10 1 +.names 21075 21073 +0 1 +.names 21073 21074 +1 1 +.names 56704 1183 21075 +01 1 +10 1 +.names 21078 21076 +0 1 +.names 21076 21077 +1 1 +.names 56706 1190 21078 +01 1 +10 1 +.names 21081 21082 21079 +11 1 +.names 21079 21080 +1 1 +.names 21036 21081 +0 1 +.names 21028 21082 +0 1 +.names 21089 21090 21083 +1- 1 +-1 1 +.names 21083 21084 +1 1 +.names 21056 21085 +0 1 +.names 21059 21086 +0 1 +.names 21085 21086 21087 +1- 1 +-1 1 +.names 21062 21088 +0 1 +.names 21087 21088 21089 +1- 1 +-1 1 +.names 21065 21090 +0 1 +.names 21097 21098 21091 +1- 1 +-1 1 +.names 21091 21092 +1 1 +.names 21068 21093 +0 1 +.names 21071 21094 +0 1 +.names 21093 21094 21095 +1- 1 +-1 1 +.names 21074 21096 +0 1 +.names 21095 21096 21097 +1- 1 +-1 1 +.names 21077 21098 +0 1 +.names 21101 21102 21099 +1- 1 +-1 1 +.names 21099 21100 +1 1 +.names 21048 21101 +0 1 +.names 21051 21102 +0 1 +.names 21105 21106 21103 +11 1 +.names 21103 21104 +1 1 +.names 21020 21105 +0 1 +.names 21100 21106 +0 1 +.names 21111 21112 21107 +1- 1 +-1 1 +.names 21107 21108 +1 1 +.names 21092 21084 21109 +1- 1 +-1 1 +.names 21080 21110 +0 1 +.names 21109 21110 21111 +1- 1 +-1 1 +.names 21104 21112 +0 1 +.names 21115 21113 +0 1 +.names 21113 21114 +1 1 +.names 56726 1181 21115 +01 1 +10 1 +.names 21118 21116 +0 1 +.names 21116 21117 +1 1 +.names 56725 1199 21118 +01 1 +10 1 +.names 21121 21119 +0 1 +.names 21119 21120 +1 1 +.names 21121 +.names 21124 21122 +0 1 +.names 21122 21123 +1 1 +.names 21124 +.names 21128 21123 21125 +11 1 +.names 21125 21126 +1 1 +.names 21114 21117 21127 +11 1 +.names 21127 21120 21128 +11 1 +.names 21131 21129 +0 1 +.names 21129 21130 +1 1 +.names 56708 1189 21131 +01 1 +10 1 +.names 21134 21132 +0 1 +.names 21132 21133 +1 1 +.names 56701 1177 21134 +01 1 +10 1 +.names 21137 21135 +0 1 +.names 21135 21136 +1 1 +.names 56702 1188 21137 +01 1 +10 1 +.names 21140 21138 +0 1 +.names 21138 21139 +1 1 +.names 56707 1200 21140 +01 1 +10 1 +.names 21147 21148 21141 +1- 1 +-1 1 +.names 21141 21142 +1 1 +.names 21130 21143 +0 1 +.names 21133 21144 +0 1 +.names 21143 21144 21145 +1- 1 +-1 1 +.names 21136 21146 +0 1 +.names 21145 21146 21147 +1- 1 +-1 1 +.names 21139 21148 +0 1 +.names 21142 21149 +0 1 +.names 21149 21150 +1 1 +.names 21153 21151 +0 1 +.names 21151 21152 +1 1 +.names 56714 1175 21153 +01 1 +10 1 +.names 21156 21154 +0 1 +.names 21154 21155 +1 1 +.names 56716 1174 21156 +01 1 +10 1 +.names 21159 21160 21157 +1- 1 +-1 1 +.names 21157 21158 +1 1 +.names 21152 21159 +0 1 +.names 21155 21160 +0 1 +.names 21163 21161 +0 1 +.names 21161 21162 +1 1 +.names 56712 1184 21163 +01 1 +10 1 +.names 21166 21164 +0 1 +.names 21164 21165 +1 1 +.names 56711 1179 21166 +01 1 +10 1 +.names 21169 21170 21167 +1- 1 +-1 1 +.names 21167 21168 +1 1 +.names 21162 21169 +0 1 +.names 21165 21170 +0 1 +.names 21173 21174 21171 +11 1 +.names 21171 21172 +1 1 +.names 21158 21173 +0 1 +.names 21168 21174 +0 1 +.names 21177 21175 +0 1 +.names 21175 21176 +1 1 +.names 21177 +.names 21180 21178 +0 1 +.names 21178 21179 +1 1 +.names 56728 1178 21180 +01 1 +10 1 +.names 21183 21184 21181 +1- 1 +-1 1 +.names 21181 21182 +1 1 +.names 21176 21183 +0 1 +.names 21179 21184 +0 1 +.names 21191 21194 21185 +1- 1 +-1 1 +.names 21185 21186 +1 1 +.names 21126 21187 +0 1 +.names 21150 21188 +0 1 +.names 21187 21188 21189 +1- 1 +-1 1 +.names 21172 21190 +0 1 +.names 21189 21190 21191 +1- 1 +-1 1 +.names 21200 21203 21192 +11 1 +.names 21192 21193 +1 1 +.names 21193 21194 +0 1 +.names 21108 21195 +0 1 +.names 21186 21196 +0 1 +.names 21199 21197 +0 1 +.names 21197 21198 +1 1 +.names 56727 1197 21199 +01 1 +10 1 +.names 21182 21200 +0 1 +.names 21204 21207 21201 +1- 1 +-1 1 +.names 21201 21202 +1 1 +.names 21202 21203 +0 1 +.names 21198 21204 +0 1 +.names 21208 21205 +0 1 +.names 21205 21206 +1 1 +.names 21206 21207 +0 1 +.names 21208 +.names 21211 21209 +0 1 +.names 21209 21210 +1 1 +.names 1783 1202 21211 +01 1 +10 1 +.names 21214 21212 +0 1 +.names 21212 21213 +1 1 +.names 1203 1783 21214 +01 1 +10 1 +.names 21220 21221 21215 +1- 1 +-1 1 +.names 21215 21216 +1 1 +.names 21292 21293 21217 +1- 1 +-1 1 +.names 21217 21218 +1 1 +.names 21210 21219 +0 1 +.names 21218 21219 21220 +1- 1 +-1 1 +.names 21213 21221 +0 1 +.names 21224 21222 +0 1 +.names 21222 21223 +1 1 +.names 1204 1783 21224 +01 1 +10 1 +.names 21227 21225 +0 1 +.names 21225 21226 +1 1 +.names 1205 1783 21227 +01 1 +10 1 +.names 21230 21231 21228 +1- 1 +-1 1 +.names 21228 21229 +1 1 +.names 21223 21230 +0 1 +.names 21226 21231 +0 1 +.names 21234 21232 +0 1 +.names 21232 21233 +1 1 +.names 1206 1783 21234 +01 1 +10 1 +.names 21237 21235 +0 1 +.names 21235 21236 +1 1 +.names 1207 1783 21237 +01 1 +10 1 +.names 21240 21238 +0 1 +.names 21238 21239 +1 1 +.names 1208 1783 21240 +01 1 +10 1 +.names 21251 21254 21241 +1- 1 +-1 1 +.names 21241 21242 +1 1 +.names 21242 21243 +0 1 +.names 21216 21244 +0 1 +.names 21243 21244 21245 +11 1 +.names 21229 21246 +0 1 +.names 21233 21247 +0 1 +.names 21236 21248 +0 1 +.names 21247 21248 21249 +1- 1 +-1 1 +.names 21239 21250 +0 1 +.names 21249 21250 21251 +1- 1 +-1 1 +.names 21255 21252 +0 1 +.names 21252 21253 +1 1 +.names 21253 21254 +0 1 +.names 1209 1783 21255 +01 1 +10 1 +.names 21260 21263 21256 +11 1 +.names 21256 21257 +1 1 +.names 21258 +.names 21258 21259 +1 1 +.names 21259 21260 +0 1 +.names 21261 +.names 21261 21262 +1 1 +.names 21262 21263 +0 1 +.names 21268 21271 21264 +11 1 +.names 21264 21265 +1 1 +.names 21266 +.names 21266 21267 +1 1 +.names 21267 21268 +0 1 +.names 21269 +.names 21269 21270 +1 1 +.names 21270 21271 +0 1 +.names 21276 21279 21272 +11 1 +.names 21272 21273 +1 1 +.names 21274 +.names 21274 21275 +1 1 +.names 21275 21276 +0 1 +.names 21277 +.names 21277 21278 +1 1 +.names 21278 21279 +0 1 +.names 21284 21287 21280 +11 1 +.names 21280 21281 +1 1 +.names 21282 +.names 21282 21283 +1 1 +.names 21283 21284 +0 1 +.names 21285 +.names 21285 21286 +1 1 +.names 21286 21287 +0 1 +.names 21281 21288 +0 1 +.names 21273 21289 +0 1 +.names 21288 21289 21290 +1- 1 +-1 1 +.names 21265 21291 +0 1 +.names 21290 21291 21292 +1- 1 +-1 1 +.names 21257 21293 +0 1 +.names 21296 21294 +0 1 +.names 21294 21295 +1 1 +.names 1783 1210 21296 +01 1 +10 1 +.names 21299 21297 +0 1 +.names 21297 21298 +1 1 +.names 1211 1783 21299 +01 1 +10 1 +.names 21305 21306 21300 +1- 1 +-1 1 +.names 21300 21301 +1 1 +.names 21377 21378 21302 +1- 1 +-1 1 +.names 21302 21303 +1 1 +.names 21295 21304 +0 1 +.names 21303 21304 21305 +1- 1 +-1 1 +.names 21298 21306 +0 1 +.names 21309 21307 +0 1 +.names 21307 21308 +1 1 +.names 1212 1783 21309 +01 1 +10 1 +.names 21312 21310 +0 1 +.names 21310 21311 +1 1 +.names 1213 1783 21312 +01 1 +10 1 +.names 21315 21316 21313 +1- 1 +-1 1 +.names 21313 21314 +1 1 +.names 21308 21315 +0 1 +.names 21311 21316 +0 1 +.names 21319 21317 +0 1 +.names 21317 21318 +1 1 +.names 1214 1783 21319 +01 1 +10 1 +.names 21322 21320 +0 1 +.names 21320 21321 +1 1 +.names 1215 1783 21322 +01 1 +10 1 +.names 21325 21323 +0 1 +.names 21323 21324 +1 1 +.names 1216 1783 21325 +01 1 +10 1 +.names 21336 21339 21326 +1- 1 +-1 1 +.names 21326 21327 +1 1 +.names 21327 21328 +0 1 +.names 21301 21329 +0 1 +.names 21328 21329 21330 +11 1 +.names 21314 21331 +0 1 +.names 21318 21332 +0 1 +.names 21321 21333 +0 1 +.names 21332 21333 21334 +1- 1 +-1 1 +.names 21324 21335 +0 1 +.names 21334 21335 21336 +1- 1 +-1 1 +.names 21340 21337 +0 1 +.names 21337 21338 +1 1 +.names 21338 21339 +0 1 +.names 1217 1783 21340 +01 1 +10 1 +.names 21345 21348 21341 +11 1 +.names 21341 21342 +1 1 +.names 21343 +.names 21343 21344 +1 1 +.names 21344 21345 +0 1 +.names 21346 +.names 21346 21347 +1 1 +.names 21347 21348 +0 1 +.names 21353 21356 21349 +11 1 +.names 21349 21350 +1 1 +.names 21351 +.names 21351 21352 +1 1 +.names 21352 21353 +0 1 +.names 21354 +.names 21354 21355 +1 1 +.names 21355 21356 +0 1 +.names 21361 21364 21357 +11 1 +.names 21357 21358 +1 1 +.names 21359 +.names 21359 21360 +1 1 +.names 21360 21361 +0 1 +.names 21362 +.names 21362 21363 +1 1 +.names 21363 21364 +0 1 +.names 21369 21372 21365 +11 1 +.names 21365 21366 +1 1 +.names 21367 +.names 21367 21368 +1 1 +.names 21368 21369 +0 1 +.names 21370 +.names 21370 21371 +1 1 +.names 21371 21372 +0 1 +.names 21366 21373 +0 1 +.names 21358 21374 +0 1 +.names 21373 21374 21375 +1- 1 +-1 1 +.names 21350 21376 +0 1 +.names 21375 21376 21377 +1- 1 +-1 1 +.names 21342 21378 +0 1 +.names 21382 21379 +0 1 +.names 21379 21380 +1 1 +.names 50447 50335 21381 +11 1 +.names 21381 21382 +1 1 +.names 21386 21383 +0 1 +.names 21383 21384 +1 1 +.names 50499 21385 +1 1 +.names 21385 21386 +1 1 +.names 21390 21387 +0 1 +.names 21387 21388 +1 1 +.names 50423 50424 21389 +1- 1 +-1 1 +.names 21389 21390 +1 1 +.names 21394 21391 +0 1 +.names 21391 21392 +1 1 +.names 50495 50497 21393 +11 1 +.names 21393 21394 +1 1 +.names 50471 2413 21395 +11 1 +.names 21395 21396 +1 1 +.names 21396 21397 +0 1 +.names 21392 21398 +0 1 +.names 21402 21399 +0 1 +.names 21399 21400 +1 1 +.names 50408 2413 21401 +1- 1 +-1 1 +.names 21401 21402 +1 1 +.names 21406 21403 +0 1 +.names 21403 21404 +1 1 +.names 50383 2413 21405 +11 1 +.names 21405 21406 +1 1 +.names 21410 21407 +0 1 +.names 21407 21408 +1 1 +.names 2413 50315 21409 +1- 1 +-1 1 +.names 21409 21410 +1 1 +.names 2413 21411 +1 1 +.names 21411 21412 +0 1 +.names 21412 21413 +1 1 +.names 1775 21414 +1 1 +.names 14886 2413 21415 +11 1 +.names 21415 21416 +1 1 +.names 21422 21425 21417 +1- 1 +-1 1 +.names 21417 21418 +1 1 +.names 21414 21419 +0 1 +.names 1205 21420 +1 1 +.names 21420 21421 +0 1 +.names 21419 21421 21422 +11 1 +.names 21434 21435 21423 +11 1 +.names 21423 21424 +1 1 +.names 21424 21425 +0 1 +.names 21429 21426 +0 1 +.names 21426 21427 +1 1 +.names 50359 2413 21428 +11 1 +.names 21428 21429 +1 1 +.names 21433 21430 +0 1 +.names 21430 21431 +1 1 +.names 50320 21469 21432 +1- 1 +-1 1 +.names 21432 21433 +1 1 +.names 1205 1783 21434 +1- 1 +-1 1 +.names 21416 21435 +0 1 +.names 21439 21436 +0 1 +.names 21436 21437 +1 1 +.names 50418 21438 +0 1 +.names 21438 21439 +1 1 +.names 21443 21440 +0 1 +.names 21440 21441 +1 1 +.names 50315 2413 21442 +11 1 +.names 21442 21443 +1 1 +.names 21447 21444 +0 1 +.names 21444 21445 +1 1 +.names 50470 2413 21446 +11 1 +.names 21446 21447 +1 1 +.names 21451 21448 +0 1 +.names 21448 21449 +1 1 +.names 50470 2413 21450 +1- 1 +-1 1 +.names 21450 21451 +1 1 +.names 21455 21452 +0 1 +.names 21452 21453 +1 1 +.names 50359 2413 21454 +1- 1 +-1 1 +.names 21454 21455 +1 1 +.names 21459 21456 +0 1 +.names 21456 21457 +1 1 +.names 50408 2413 21458 +11 1 +.names 21458 21459 +1 1 +.names 21397 21460 +1 1 +.names 21464 21461 +0 1 +.names 21461 21462 +1 1 +.names 50471 2413 21463 +1- 1 +-1 1 +.names 21463 21464 +1 1 +.names 21468 21465 +0 1 +.names 21465 21466 +1 1 +.names 50383 2413 21467 +1- 1 +-1 1 +.names 21467 21468 +1 1 +.names 21472 21469 +0 1 +.names 21469 21470 +1 1 +.names 50498 2413 21471 +1- 1 +-1 1 +.names 21471 21472 +1 1 +.names 21476 21473 +0 1 +.names 21473 21474 +1 1 +.names 50644 50556 21475 +11 1 +.names 21475 21476 +1 1 +.names 21480 21477 +0 1 +.names 21477 21478 +1 1 +.names 50685 21479 +1 1 +.names 21479 21480 +1 1 +.names 21484 21481 +0 1 +.names 21481 21482 +1 1 +.names 50624 50625 21483 +1- 1 +-1 1 +.names 21483 21484 +1 1 +.names 21488 21485 +0 1 +.names 21485 21486 +1 1 +.names 50408 14886 21487 +1- 1 +-1 1 +.names 21487 21488 +1 1 +.names 21492 21489 +0 1 +.names 21489 21490 +1 1 +.names 50383 14886 21491 +11 1 +.names 21491 21492 +1 1 +.names 21496 21493 +0 1 +.names 21493 21494 +1 1 +.names 14886 50315 21495 +1- 1 +-1 1 +.names 21495 21496 +1 1 +.names 2413 21497 +1 1 +.names 21497 21498 +0 1 +.names 21498 21499 +1 1 +.names 1775 21500 +1 1 +.names 14886 2413 21501 +11 1 +.names 21501 21502 +1 1 +.names 21508 21511 21503 +1- 1 +-1 1 +.names 21503 21504 +1 1 +.names 21500 21505 +0 1 +.names 1205 21506 +1 1 +.names 21506 21507 +0 1 +.names 21505 21507 21508 +11 1 +.names 21520 21521 21509 +11 1 +.names 21509 21510 +1 1 +.names 21510 21511 +0 1 +.names 21515 21512 +0 1 +.names 21512 21513 +1 1 +.names 50359 14886 21514 +11 1 +.names 21514 21515 +1 1 +.names 21519 21516 +0 1 +.names 21516 21517 +1 1 +.names 50541 21558 21518 +1- 1 +-1 1 +.names 21518 21519 +1 1 +.names 1205 1783 21520 +1- 1 +-1 1 +.names 21502 21521 +0 1 +.names 21525 21522 +0 1 +.names 21522 21523 +1 1 +.names 50620 21524 +0 1 +.names 21524 21525 +1 1 +.names 21529 21526 +0 1 +.names 21526 21527 +1 1 +.names 50315 14886 21528 +11 1 +.names 21528 21529 +1 1 +.names 21533 21530 +0 1 +.names 21530 21531 +1 1 +.names 50470 14886 21532 +11 1 +.names 21532 21533 +1 1 +.names 21537 21534 +0 1 +.names 21534 21535 +1 1 +.names 50470 14886 21536 +1- 1 +-1 1 +.names 21536 21537 +1 1 +.names 21541 21538 +0 1 +.names 21538 21539 +1 1 +.names 50359 14886 21540 +1- 1 +-1 1 +.names 21540 21541 +1 1 +.names 21545 21542 +0 1 +.names 21542 21543 +1 1 +.names 50408 14886 21544 +11 1 +.names 21544 21545 +1 1 +.names 21549 21546 +0 1 +.names 21546 21547 +1 1 +.names 50471 14886 21548 +11 1 +.names 21548 21549 +1 1 +.names 21553 21550 +0 1 +.names 21550 21551 +1 1 +.names 50471 14886 21552 +1- 1 +-1 1 +.names 21552 21553 +1 1 +.names 21557 21554 +0 1 +.names 21554 21555 +1 1 +.names 50383 14886 21556 +1- 1 +-1 1 +.names 21556 21557 +1 1 +.names 21561 21558 +0 1 +.names 21558 21559 +1 1 +.names 50498 14886 21560 +1- 1 +-1 1 +.names 21560 21561 +1 1 +.names 21565 21562 +0 1 +.names 21562 21563 +1 1 +.names 50851 50739 21564 +11 1 +.names 21564 21565 +1 1 +.names 21569 21566 +0 1 +.names 21566 21567 +1 1 +.names 50903 21568 +1 1 +.names 21568 21569 +1 1 +.names 21573 21570 +0 1 +.names 21570 21571 +1 1 +.names 50827 50828 21572 +1- 1 +-1 1 +.names 21572 21573 +1 1 +.names 21577 21574 +0 1 +.names 21574 21575 +1 1 +.names 50899 50901 21576 +11 1 +.names 21576 21577 +1 1 +.names 50875 2413 21578 +11 1 +.names 21578 21579 +1 1 +.names 21579 21580 +0 1 +.names 21575 21581 +0 1 +.names 21585 21582 +0 1 +.names 21582 21583 +1 1 +.names 50812 2413 21584 +1- 1 +-1 1 +.names 21584 21585 +1 1 +.names 21589 21586 +0 1 +.names 21586 21587 +1 1 +.names 50787 2413 21588 +11 1 +.names 21588 21589 +1 1 +.names 21593 21590 +0 1 +.names 21590 21591 +1 1 +.names 2413 50719 21592 +1- 1 +-1 1 +.names 21592 21593 +1 1 +.names 2413 21594 +1 1 +.names 21594 21595 +0 1 +.names 21595 21596 +1 1 +.names 1775 21597 +1 1 +.names 14886 2413 21598 +11 1 +.names 21598 21599 +1 1 +.names 21605 21608 21600 +1- 1 +-1 1 +.names 21600 21601 +1 1 +.names 21597 21602 +0 1 +.names 1213 21603 +1 1 +.names 21603 21604 +0 1 +.names 21602 21604 21605 +11 1 +.names 21617 21618 21606 +11 1 +.names 21606 21607 +1 1 +.names 21607 21608 +0 1 +.names 21612 21609 +0 1 +.names 21609 21610 +1 1 +.names 50763 2413 21611 +11 1 +.names 21611 21612 +1 1 +.names 21616 21613 +0 1 +.names 21613 21614 +1 1 +.names 50724 21652 21615 +1- 1 +-1 1 +.names 21615 21616 +1 1 +.names 1213 1783 21617 +1- 1 +-1 1 +.names 21599 21618 +0 1 +.names 21622 21619 +0 1 +.names 21619 21620 +1 1 +.names 50822 21621 +0 1 +.names 21621 21622 +1 1 +.names 21626 21623 +0 1 +.names 21623 21624 +1 1 +.names 50719 2413 21625 +11 1 +.names 21625 21626 +1 1 +.names 21630 21627 +0 1 +.names 21627 21628 +1 1 +.names 50874 2413 21629 +11 1 +.names 21629 21630 +1 1 +.names 21634 21631 +0 1 +.names 21631 21632 +1 1 +.names 50874 2413 21633 +1- 1 +-1 1 +.names 21633 21634 +1 1 +.names 21638 21635 +0 1 +.names 21635 21636 +1 1 +.names 50763 2413 21637 +1- 1 +-1 1 +.names 21637 21638 +1 1 +.names 21642 21639 +0 1 +.names 21639 21640 +1 1 +.names 50812 2413 21641 +11 1 +.names 21641 21642 +1 1 +.names 21580 21643 +1 1 +.names 21647 21644 +0 1 +.names 21644 21645 +1 1 +.names 50875 2413 21646 +1- 1 +-1 1 +.names 21646 21647 +1 1 +.names 21651 21648 +0 1 +.names 21648 21649 +1 1 +.names 50787 2413 21650 +1- 1 +-1 1 +.names 21650 21651 +1 1 +.names 21655 21652 +0 1 +.names 21652 21653 +1 1 +.names 50902 2413 21654 +1- 1 +-1 1 +.names 21654 21655 +1 1 +.names 21659 21656 +0 1 +.names 21656 21657 +1 1 +.names 51048 50960 21658 +11 1 +.names 21658 21659 +1 1 +.names 21663 21660 +0 1 +.names 21660 21661 +1 1 +.names 51089 21662 +1 1 +.names 21662 21663 +1 1 +.names 21667 21664 +0 1 +.names 21664 21665 +1 1 +.names 51028 51029 21666 +1- 1 +-1 1 +.names 21666 21667 +1 1 +.names 21671 21668 +0 1 +.names 21668 21669 +1 1 +.names 50812 14886 21670 +1- 1 +-1 1 +.names 21670 21671 +1 1 +.names 21675 21672 +0 1 +.names 21672 21673 +1 1 +.names 50787 14886 21674 +11 1 +.names 21674 21675 +1 1 +.names 21679 21676 +0 1 +.names 21676 21677 +1 1 +.names 14886 50719 21678 +1- 1 +-1 1 +.names 21678 21679 +1 1 +.names 2413 21680 +1 1 +.names 21680 21681 +0 1 +.names 21681 21682 +1 1 +.names 1775 21683 +1 1 +.names 14886 2413 21684 +11 1 +.names 21684 21685 +1 1 +.names 21691 21694 21686 +1- 1 +-1 1 +.names 21686 21687 +1 1 +.names 21683 21688 +0 1 +.names 1213 21689 +1 1 +.names 21689 21690 +0 1 +.names 21688 21690 21691 +11 1 +.names 21703 21704 21692 +11 1 +.names 21692 21693 +1 1 +.names 21693 21694 +0 1 +.names 21698 21695 +0 1 +.names 21695 21696 +1 1 +.names 50763 14886 21697 +11 1 +.names 21697 21698 +1 1 +.names 21702 21699 +0 1 +.names 21699 21700 +1 1 +.names 50945 21741 21701 +1- 1 +-1 1 +.names 21701 21702 +1 1 +.names 1213 1783 21703 +1- 1 +-1 1 +.names 21685 21704 +0 1 +.names 21708 21705 +0 1 +.names 21705 21706 +1 1 +.names 51024 21707 +0 1 +.names 21707 21708 +1 1 +.names 21712 21709 +0 1 +.names 21709 21710 +1 1 +.names 50719 14886 21711 +11 1 +.names 21711 21712 +1 1 +.names 21716 21713 +0 1 +.names 21713 21714 +1 1 +.names 50874 14886 21715 +11 1 +.names 21715 21716 +1 1 +.names 21720 21717 +0 1 +.names 21717 21718 +1 1 +.names 50874 14886 21719 +1- 1 +-1 1 +.names 21719 21720 +1 1 +.names 21724 21721 +0 1 +.names 21721 21722 +1 1 +.names 50763 14886 21723 +1- 1 +-1 1 +.names 21723 21724 +1 1 +.names 21728 21725 +0 1 +.names 21725 21726 +1 1 +.names 50812 14886 21727 +11 1 +.names 21727 21728 +1 1 +.names 21732 21729 +0 1 +.names 21729 21730 +1 1 +.names 50875 14886 21731 +11 1 +.names 21731 21732 +1 1 +.names 21736 21733 +0 1 +.names 21733 21734 +1 1 +.names 50875 14886 21735 +1- 1 +-1 1 +.names 21735 21736 +1 1 +.names 21740 21737 +0 1 +.names 21737 21738 +1 1 +.names 50787 14886 21739 +1- 1 +-1 1 +.names 21739 21740 +1 1 +.names 21744 21741 +0 1 +.names 21741 21742 +1 1 +.names 50902 14886 21743 +1- 1 +-1 1 +.names 21743 21744 +1 1 +.names 21749 21745 +0 1 +.names 21745 21746 +1 1 +.names 50707 50708 21747 +1- 1 +-1 1 +.names 21747 21748 +1 1 +.names 1783 21748 21749 +01 1 +10 1 +.names 21754 21750 +0 1 +.names 21750 21751 +1 1 +.names 50677 50679 21752 +1- 1 +-1 1 +.names 21752 21753 +1 1 +.names 21753 1783 21754 +01 1 +10 1 +.names 21760 21761 21755 +1- 1 +-1 1 +.names 21755 21756 +1 1 +.names 21844 21845 21757 +1- 1 +-1 1 +.names 21757 21758 +1 1 +.names 21746 21759 +0 1 +.names 21758 21759 21760 +1- 1 +-1 1 +.names 21751 21761 +0 1 +.names 21766 21762 +0 1 +.names 21762 21763 +1 1 +.names 50716 50718 21764 +1- 1 +-1 1 +.names 21764 21765 +1 1 +.names 21765 1783 21766 +01 1 +10 1 +.names 21771 21767 +0 1 +.names 21767 21768 +1 1 +.names 50670 50671 21769 +1- 1 +-1 1 +.names 21769 21770 +1 1 +.names 21770 1783 21771 +01 1 +10 1 +.names 21774 21775 21772 +1- 1 +-1 1 +.names 21772 21773 +1 1 +.names 21763 21774 +0 1 +.names 21768 21775 +0 1 +.names 21780 21776 +0 1 +.names 21776 21777 +1 1 +.names 50596 50598 21778 +1- 1 +-1 1 +.names 21778 21779 +1 1 +.names 21779 1783 21780 +01 1 +10 1 +.names 21785 21781 +0 1 +.names 21781 21782 +1 1 +.names 50631 50635 21783 +1- 1 +-1 1 +.names 21783 21784 +1 1 +.names 21784 1783 21785 +01 1 +10 1 +.names 21790 21786 +0 1 +.names 21786 21787 +1 1 +.names 50586 50590 21788 +1- 1 +-1 1 +.names 21788 21789 +1 1 +.names 21789 1783 21790 +01 1 +10 1 +.names 21801 21804 21791 +1- 1 +-1 1 +.names 21791 21792 +1 1 +.names 21792 21793 +0 1 +.names 21756 21794 +0 1 +.names 21793 21794 21795 +11 1 +.names 21773 21796 +0 1 +.names 21777 21797 +0 1 +.names 21782 21798 +0 1 +.names 21797 21798 21799 +1- 1 +-1 1 +.names 21787 21800 +0 1 +.names 21799 21800 21801 +1- 1 +-1 1 +.names 21807 21802 +0 1 +.names 21802 21803 +1 1 +.names 21803 21804 +0 1 +.names 50639 50643 21805 +1- 1 +-1 1 +.names 21805 21806 +1 1 +.names 21806 1783 21807 +01 1 +10 1 +.names 21812 21815 21808 +11 1 +.names 21808 21809 +1 1 +.names 21810 +.names 21810 21811 +1 1 +.names 21811 21812 +0 1 +.names 21813 +.names 21813 21814 +1 1 +.names 21814 21815 +0 1 +.names 21820 21823 21816 +11 1 +.names 21816 21817 +1 1 +.names 21818 +.names 21818 21819 +1 1 +.names 21819 21820 +0 1 +.names 21821 +.names 21821 21822 +1 1 +.names 21822 21823 +0 1 +.names 21828 21831 21824 +11 1 +.names 21824 21825 +1 1 +.names 21826 +.names 21826 21827 +1 1 +.names 21827 21828 +0 1 +.names 21829 +.names 21829 21830 +1 1 +.names 21830 21831 +0 1 +.names 21836 21839 21832 +11 1 +.names 21832 21833 +1 1 +.names 21834 +.names 21834 21835 +1 1 +.names 21835 21836 +0 1 +.names 21837 +.names 21837 21838 +1 1 +.names 21838 21839 +0 1 +.names 21833 21840 +0 1 +.names 21825 21841 +0 1 +.names 21840 21841 21842 +1- 1 +-1 1 +.names 21817 21843 +0 1 +.names 21842 21843 21844 +1- 1 +-1 1 +.names 21809 21845 +0 1 +.names 21850 21846 +0 1 +.names 21846 21847 +1 1 +.names 51111 51112 21848 +1- 1 +-1 1 +.names 21848 21849 +1 1 +.names 1783 21849 21850 +01 1 +10 1 +.names 21855 21851 +0 1 +.names 21851 21852 +1 1 +.names 51081 51083 21853 +1- 1 +-1 1 +.names 21853 21854 +1 1 +.names 21854 1783 21855 +01 1 +10 1 +.names 21861 21862 21856 +1- 1 +-1 1 +.names 21856 21857 +1 1 +.names 21945 21946 21858 +1- 1 +-1 1 +.names 21858 21859 +1 1 +.names 21847 21860 +0 1 +.names 21859 21860 21861 +1- 1 +-1 1 +.names 21852 21862 +0 1 +.names 21867 21863 +0 1 +.names 21863 21864 +1 1 +.names 51120 51122 21865 +1- 1 +-1 1 +.names 21865 21866 +1 1 +.names 21866 1783 21867 +01 1 +10 1 +.names 21872 21868 +0 1 +.names 21868 21869 +1 1 +.names 51074 51075 21870 +1- 1 +-1 1 +.names 21870 21871 +1 1 +.names 21871 1783 21872 +01 1 +10 1 +.names 21875 21876 21873 +1- 1 +-1 1 +.names 21873 21874 +1 1 +.names 21864 21875 +0 1 +.names 21869 21876 +0 1 +.names 21881 21877 +0 1 +.names 21877 21878 +1 1 +.names 51000 51002 21879 +1- 1 +-1 1 +.names 21879 21880 +1 1 +.names 21880 1783 21881 +01 1 +10 1 +.names 21886 21882 +0 1 +.names 21882 21883 +1 1 +.names 51035 51039 21884 +1- 1 +-1 1 +.names 21884 21885 +1 1 +.names 21885 1783 21886 +01 1 +10 1 +.names 21891 21887 +0 1 +.names 21887 21888 +1 1 +.names 50990 50994 21889 +1- 1 +-1 1 +.names 21889 21890 +1 1 +.names 21890 1783 21891 +01 1 +10 1 +.names 21902 21905 21892 +1- 1 +-1 1 +.names 21892 21893 +1 1 +.names 21893 21894 +0 1 +.names 21857 21895 +0 1 +.names 21894 21895 21896 +11 1 +.names 21874 21897 +0 1 +.names 21878 21898 +0 1 +.names 21883 21899 +0 1 +.names 21898 21899 21900 +1- 1 +-1 1 +.names 21888 21901 +0 1 +.names 21900 21901 21902 +1- 1 +-1 1 +.names 21908 21903 +0 1 +.names 21903 21904 +1 1 +.names 21904 21905 +0 1 +.names 51043 51047 21906 +1- 1 +-1 1 +.names 21906 21907 +1 1 +.names 21907 1783 21908 +01 1 +10 1 +.names 21913 21916 21909 +11 1 +.names 21909 21910 +1 1 +.names 21911 +.names 21911 21912 +1 1 +.names 21912 21913 +0 1 +.names 21914 +.names 21914 21915 +1 1 +.names 21915 21916 +0 1 +.names 21921 21924 21917 +11 1 +.names 21917 21918 +1 1 +.names 21919 +.names 21919 21920 +1 1 +.names 21920 21921 +0 1 +.names 21922 +.names 21922 21923 +1 1 +.names 21923 21924 +0 1 +.names 21929 21932 21925 +11 1 +.names 21925 21926 +1 1 +.names 21927 +.names 21927 21928 +1 1 +.names 21928 21929 +0 1 +.names 21930 +.names 21930 21931 +1 1 +.names 21931 21932 +0 1 +.names 21937 21940 21933 +11 1 +.names 21933 21934 +1 1 +.names 21935 +.names 21935 21936 +1 1 +.names 21936 21937 +0 1 +.names 21938 +.names 21938 21939 +1 1 +.names 21939 21940 +0 1 +.names 21934 21941 +0 1 +.names 21926 21942 +0 1 +.names 21941 21942 21943 +1- 1 +-1 1 +.names 21918 21944 +0 1 +.names 21943 21944 21945 +1- 1 +-1 1 +.names 21910 21946 +0 1 +.names 21951 9676 21947 +11 1 +.names 21947 21948 +1 1 +.names 21948 21949 +0 1 +.names 3104 21950 +0 1 +.names 3212 21951 +0 1 +.names 21956 21959 57155 +1- 1 +-1 1 +.names 9686 21953 +0 1 +.names 14792 21954 +1 1 +.names 21954 21955 +0 1 +.names 21953 21955 21956 +11 1 +.names 14886 21957 +1 1 +.names 21957 21958 +0 1 +.names 9686 21958 21959 +11 1 +.names 21964 9696 21960 +11 1 +.names 21960 21961 +1 1 +.names 21961 21962 +0 1 +.names 3092 21963 +0 1 +.names 3206 21964 +0 1 +.names 21969 21972 57156 +1- 1 +-1 1 +.names 9706 21966 +0 1 +.names 14792 21967 +1 1 +.names 21967 21968 +0 1 +.names 21966 21968 21969 +11 1 +.names 14886 21970 +1 1 +.names 21970 21971 +0 1 +.names 9706 21971 21972 +11 1 +.names 10009 21973 +0 1 +.names 9761 21974 +0 1 +.names 10017 21975 +0 1 +.names 9951 21976 +0 1 +.names 9932 21977 +0 1 +.names 9989 21978 +0 1 +.names 9980 21979 +0 1 +.names 9957 21980 +0 1 +.names 10014 21981 +0 1 +.names 10163 21982 +0 1 +.names 9939 21983 +0 1 +.names 9966 21984 +0 1 +.names 9972 21985 +0 1 +.names 10002 21986 +0 1 +.names 9924 21987 +0 1 +.names 9945 21988 +0 1 +.names 9982 21989 +0 1 +.names 9918 21990 +0 1 +.names 9950 21991 +0 1 +.names 9725 21992 +0 1 +.names 9930 21993 +0 1 +.names 9988 21994 +0 1 +.names 9978 21995 +0 1 +.names 9937 21996 +0 1 +.names 10212 21997 +0 1 +.names 10011 21998 +0 1 +.names 9745 21999 +0 1 +.names 9923 22000 +0 1 +.names 10007 22001 +0 1 +.names 10025 22002 +0 1 +.names 10016 22003 +0 1 +.names 9964 22004 +0 1 +.names 9944 22005 +0 1 +.names 9916 22006 +0 1 +.names 10000 22007 +0 1 +.names 9971 22008 +0 1 +.names 9925 22009 +0 1 +.names 10021 22010 +0 1 +.names 9729 22011 +0 1 +.names 10008 22012 +0 1 +.names 9990 22013 +0 1 +.names 9979 22014 +0 1 +.names 9959 22015 +0 1 +.names 9973 22016 +0 1 +.names 9938 22017 +0 1 +.names 9983 22018 +0 1 +.names 10024 22019 +0 1 +.names 9713 22020 +0 1 +.names 9931 22021 +0 1 +.names 9958 22022 +0 1 +.names 22026 22023 +0 1 +.names 22023 22024 +1 1 +.names 51442 10026 22025 +1- 1 +-1 1 +.names 22025 22026 +1 1 +.names 22030 22027 +0 1 +.names 22027 22028 +1 1 +.names 51441 9768 22029 +1- 1 +-1 1 +.names 22029 22030 +1 1 +.names 22034 22031 +0 1 +.names 22031 22032 +1 1 +.names 9768 10026 22033 +1- 1 +-1 1 +.names 22033 22034 +1 1 +.names 22038 22035 +0 1 +.names 22035 22036 +1 1 +.names 9766 9764 22037 +1- 1 +-1 1 +.names 22037 22038 +1 1 +.names 22042 22039 +0 1 +.names 22039 22040 +1 1 +.names 51442 51441 22041 +1- 1 +-1 1 +.names 22041 22042 +1 1 +.names 22046 22043 +0 1 +.names 22043 22044 +1 1 +.names 51433 51434 22045 +1- 1 +-1 1 +.names 22045 22046 +1 1 +.names 22050 22047 +0 1 +.names 22047 22048 +1 1 +.names 51433 9766 22049 +1- 1 +-1 1 +.names 22049 22050 +1 1 +.names 22054 22051 +0 1 +.names 22051 22052 +1 1 +.names 51434 9764 22053 +1- 1 +-1 1 +.names 22053 22054 +1 1 +.names 9709 22055 +0 1 +.names 10019 22056 +0 1 +.names 10018 22057 +0 1 +.names 9952 22058 +0 1 +.names 9965 22059 +0 1 +.names 9917 22060 +0 1 +.names 9992 22061 +0 1 +.names 9757 22062 +0 1 +.names 9981 22063 +0 1 +.names 10020 22064 +0 1 +.names 9749 22065 +0 1 +.names 9995 22066 +0 1 +.names 9717 22067 +0 1 +.names 10001 22068 +0 1 +.names 9737 22069 +0 1 +.names 10023 22070 +0 1 +.names 9733 22071 +0 1 +.names 22075 22072 +0 1 +.names 22072 22073 +1 1 +.names 10164 9774 22074 +1- 1 +-1 1 +.names 22074 22075 +1 1 +.names 22079 22076 +0 1 +.names 22076 22077 +1 1 +.names 51454 51453 22078 +1- 1 +-1 1 +.names 22078 22079 +1 1 +.names 22083 22080 +0 1 +.names 22080 22081 +1 1 +.names 51453 9774 22082 +1- 1 +-1 1 +.names 22082 22083 +1 1 +.names 22087 22084 +0 1 +.names 22084 22085 +1 1 +.names 9770 10157 22086 +1- 1 +-1 1 +.names 22086 22087 +1 1 +.names 22091 22088 +0 1 +.names 22088 22089 +1 1 +.names 10164 51454 22090 +1- 1 +-1 1 +.names 22090 22091 +1 1 +.names 22095 22092 +0 1 +.names 22092 22093 +1 1 +.names 51446 51445 22094 +1- 1 +-1 1 +.names 22094 22095 +1 1 +.names 22099 22096 +0 1 +.names 22096 22097 +1 1 +.names 51446 10157 22098 +1- 1 +-1 1 +.names 22098 22099 +1 1 +.names 22103 22100 +0 1 +.names 22100 22101 +1 1 +.names 51445 9770 22102 +1- 1 +-1 1 +.names 22102 22103 +1 1 +.names 10015 22104 +0 1 +.names 9741 22105 +0 1 +.names 9941 22106 +0 1 +.names 9753 22107 +0 1 +.names 10022 22108 +0 1 +.names 9721 22109 +0 1 +.names 10336 22110 +0 1 +.names 10527 22111 +0 1 +.names 10529 22112 +0 1 +.names 10450 22113 +0 1 +.names 10498 22114 +0 1 +.names 10544 22115 +0 1 +.names 10534 22116 +0 1 +.names 10484 22117 +0 1 +.names 10464 22118 +0 1 +.names 10437 22119 +0 1 +.names 10491 22120 +0 1 +.names 10457 22121 +0 1 +.names 10528 22122 +0 1 +.names 10501 22123 +0 1 +.names 10445 22124 +0 1 +.names 10340 22125 +0 1 +.names 10525 22126 +0 1 +.names 10531 22127 +0 1 +.names 10472 22128 +0 1 +.names 10452 22129 +0 1 +.names 10509 22130 +0 1 +.names 10500 22131 +0 1 +.names 10478 22132 +0 1 +.names 10465 22133 +0 1 +.names 10438 22134 +0 1 +.names 10459 22135 +0 1 +.names 10532 22136 +0 1 +.names 10503 22137 +0 1 +.names 10344 22138 +0 1 +.names 10526 22139 +0 1 +.names 10470 22140 +0 1 +.names 10510 22141 +0 1 +.names 10499 22142 +0 1 +.names 10479 22143 +0 1 +.names 10520 22144 +0 1 +.names 10493 22145 +0 1 +.names 10458 22146 +0 1 +.names 22150 22147 +0 1 +.names 22147 22148 +1 1 +.names 51460 10535 22149 +1- 1 +-1 1 +.names 22149 22150 +1 1 +.names 22154 22151 +0 1 +.names 22151 22152 +1 1 +.names 51459 10359 22153 +1- 1 +-1 1 +.names 22153 22154 +1 1 +.names 22158 22155 +0 1 +.names 22155 22156 +1 1 +.names 10359 10535 22157 +1- 1 +-1 1 +.names 22157 22158 +1 1 +.names 22162 22159 +0 1 +.names 22159 22160 +1 1 +.names 51460 51459 22161 +1- 1 +-1 1 +.names 22161 22162 +1 1 +.names 22166 22163 +0 1 +.names 22163 22164 +1 1 +.names 51457 51458 22165 +1- 1 +-1 1 +.names 22165 22166 +1 1 +.names 22170 22167 +0 1 +.names 22167 22168 +1 1 +.names 51457 10357 22169 +1- 1 +-1 1 +.names 22169 22170 +1 1 +.names 10332 22171 +0 1 +.names 10511 22172 +0 1 +.names 10485 22173 +0 1 +.names 10492 22174 +0 1 +.names 10324 22175 +0 1 +.names 10530 22176 +0 1 +.names 10581 22177 +0 1 +.names 10513 22178 +0 1 +.names 10486 22179 +0 1 +.names 10439 22180 +0 1 +.names 10519 22181 +0 1 +.names 10352 22182 +0 1 +.names 10502 22183 +0 1 +.names 10508 22184 +0 1 +.names 10477 22185 +0 1 +.names 10518 22186 +0 1 +.names 10533 22187 +0 1 +.names 10444 22188 +0 1 +.names 10348 22189 +0 1 +.names 10471 22190 +0 1 +.names 22194 22191 +0 1 +.names 22191 22192 +1 1 +.names 10545 10365 22193 +1- 1 +-1 1 +.names 22193 22194 +1 1 +.names 22198 22195 +0 1 +.names 22195 22196 +1 1 +.names 51476 51475 22197 +1- 1 +-1 1 +.names 22197 22198 +1 1 +.names 22202 22199 +0 1 +.names 22199 22200 +1 1 +.names 51475 10365 22201 +1- 1 +-1 1 +.names 22201 22202 +1 1 +.names 22206 22203 +0 1 +.names 22203 22204 +1 1 +.names 10361 10538 22205 +1- 1 +-1 1 +.names 22205 22206 +1 1 +.names 22210 22207 +0 1 +.names 22207 22208 +1 1 +.names 10545 51476 22209 +1- 1 +-1 1 +.names 22209 22210 +1 1 +.names 22214 22211 +0 1 +.names 22211 22212 +1 1 +.names 51468 51467 22213 +1- 1 +-1 1 +.names 22213 22214 +1 1 +.names 22218 22215 +0 1 +.names 22215 22216 +1 1 +.names 51468 10538 22217 +1- 1 +-1 1 +.names 22217 22218 +1 1 +.names 22222 22219 +0 1 +.names 22219 22220 +1 1 +.names 51467 10361 22221 +1- 1 +-1 1 +.names 22221 22222 +1 1 +.names 10328 22223 +0 1 +.names 10451 22224 +0 1 +.names 10512 22225 +0 1 +.names 10461 22226 +0 1 +.names 22232 22236 56417 +1- 1 +-1 1 +.names 6776 22228 +0 1 +.names 5370 22229 +0 1 +.names 22229 22230 +1 1 +.names 22230 22231 +0 1 +.names 22228 22231 22232 +11 1 +.names 2381 22233 +0 1 +.names 22233 22234 +1 1 +.names 22234 22235 +0 1 +.names 6776 22235 22236 +11 1 +.names 22241 22245 56418 +1- 1 +-1 1 +.names 5374 22238 +0 1 +.names 22238 22239 +1 1 +.names 22239 22240 +0 1 +.names 22228 22240 22241 +11 1 +.names 2374 22242 +0 1 +.names 22242 22243 +1 1 +.names 22243 22244 +0 1 +.names 6776 22244 22245 +11 1 +.names 22251 22254 56421 +1- 1 +-1 1 +.names 6780 22247 +0 1 +.names 5383 22248 +0 1 +.names 22248 22249 +1 1 +.names 22249 22250 +0 1 +.names 22247 22250 22251 +11 1 +.names 2413 22252 +1 1 +.names 22252 22253 +0 1 +.names 6780 22253 22254 +11 1 +.names 22260 22263 56424 +1- 1 +-1 1 +.names 6779 22256 +0 1 +.names 5394 22257 +0 1 +.names 22257 22258 +1 1 +.names 22258 22259 +0 1 +.names 22256 22259 22260 +11 1 +.names 2413 22261 +1 1 +.names 22261 22262 +0 1 +.names 6779 22262 22263 +11 1 +.names 22268 22272 56422 +1- 1 +-1 1 +.names 5385 22265 +0 1 +.names 22265 22266 +1 1 +.names 22266 22267 +0 1 +.names 22247 22267 22268 +11 1 +.names 5365 22269 +0 1 +.names 22269 22270 +1 1 +.names 22270 22271 +0 1 +.names 6780 22271 22272 +11 1 +.names 22277 22280 56423 +1- 1 +-1 1 +.names 5391 22274 +0 1 +.names 22274 22275 +1 1 +.names 22275 22276 +0 1 +.names 22256 22276 22277 +11 1 +.names 2413 22278 +1 1 +.names 22278 22279 +0 1 +.names 6779 22279 22280 +11 1 +.names 22287 22289 22281 +1- 1 +-1 1 +.names 22281 22282 +1 1 +.names 6788 22283 +0 1 +.names 22290 22293 22284 +11 1 +.names 22284 22285 +1 1 +.names 22285 22286 +0 1 +.names 22283 22286 22287 +11 1 +.names 56564 22288 +0 1 +.names 6788 22288 22289 +11 1 +.names 6786 22290 +0 1 +.names 1218 22291 +0 1 +.names 22291 22292 +1 1 +.names 22292 22293 +0 1 +.names 22290 22294 +1 1 +.names 22294 22295 +0 1 +.names 22288 22296 +1 1 +.names 22296 22297 +0 1 +.names 22295 22297 22298 +11 1 +.names 22282 22299 +0 1 +.names 22305 22307 22300 +1- 1 +-1 1 +.names 22300 22301 +1 1 +.names 22290 22310 22302 +11 1 +.names 22302 22303 +1 1 +.names 22303 22304 +0 1 +.names 22283 22304 22305 +11 1 +.names 56563 22306 +0 1 +.names 6788 22306 22307 +11 1 +.names 1219 22308 +0 1 +.names 22308 22309 +1 1 +.names 22309 22310 +0 1 +.names 22290 22311 +1 1 +.names 22311 22312 +0 1 +.names 22306 22313 +1 1 +.names 22313 22314 +0 1 +.names 22312 22314 22315 +11 1 +.names 22301 22316 +0 1 +.names 6785 22317 +0 1 +.names 22317 22318 +1 1 +.names 22324 22326 22319 +1- 1 +-1 1 +.names 22319 22320 +1 1 +.names 22317 22329 22321 +11 1 +.names 22321 22322 +1 1 +.names 22322 22323 +0 1 +.names 22283 22323 22324 +11 1 +.names 56565 22325 +0 1 +.names 6788 22325 22326 +11 1 +.names 1220 22327 +0 1 +.names 22327 22328 +1 1 +.names 22328 22329 +0 1 +.names 22325 22330 +1 1 +.names 22318 22331 +0 1 +.names 22330 22332 +0 1 +.names 22331 22332 22333 +11 1 +.names 22320 22334 +0 1 +.names 22317 22335 +1 1 +.names 22341 22342 22336 +1- 1 +-1 1 +.names 22336 22337 +1 1 +.names 22317 22345 22338 +11 1 +.names 22338 22339 +1 1 +.names 22339 22340 +0 1 +.names 22283 22340 22341 +11 1 +.names 6788 2413 22342 +11 1 +.names 1221 22343 +0 1 +.names 22343 22344 +1 1 +.names 22344 22345 +0 1 +.names 56568 22346 +0 1 +.names 22346 22347 +1 1 +.names 22335 22348 +0 1 +.names 22347 22349 +0 1 +.names 22348 22349 22350 +11 1 +.names 22337 22351 +0 1 +.names 22317 22352 +1 1 +.names 22358 22360 22353 +1- 1 +-1 1 +.names 22353 22354 +1 1 +.names 22317 22363 22355 +11 1 +.names 22355 22356 +1 1 +.names 22356 22357 +0 1 +.names 22283 22357 22358 +11 1 +.names 56566 22359 +0 1 +.names 6788 22359 22360 +11 1 +.names 1222 22361 +0 1 +.names 22361 22362 +1 1 +.names 22362 22363 +0 1 +.names 22359 22364 +1 1 +.names 22352 22365 +0 1 +.names 22364 22366 +0 1 +.names 22365 22366 22367 +11 1 +.names 22354 22368 +0 1 +.names 22290 22369 +1 1 +.names 22375 22377 22370 +1- 1 +-1 1 +.names 22370 22371 +1 1 +.names 22290 22380 22372 +11 1 +.names 22372 22373 +1 1 +.names 22373 22374 +0 1 +.names 22283 22374 22375 +11 1 +.names 56567 22376 +0 1 +.names 6788 22376 22377 +11 1 +.names 1223 22378 +0 1 +.names 22378 22379 +1 1 +.names 22379 22380 +0 1 +.names 22376 22381 +1 1 +.names 22369 22382 +0 1 +.names 22381 22383 +0 1 +.names 22382 22383 22384 +11 1 +.names 22371 22385 +0 1 +.names 22392 22396 22386 +1- 1 +-1 1 +.names 22386 22387 +1 1 +.names 6803 22388 +0 1 +.names 274 22389 +0 1 +.names 22389 22390 +1 1 +.names 22390 22391 +0 1 +.names 22388 22391 22392 +11 1 +.names 1224 22393 +0 1 +.names 22393 22394 +1 1 +.names 22394 22395 +0 1 +.names 6803 22395 22396 +11 1 +.names 22403 22407 22397 +1- 1 +-1 1 +.names 22397 22398 +1 1 +.names 6797 22399 +0 1 +.names 290 22400 +0 1 +.names 22400 22401 +1 1 +.names 22401 22402 +0 1 +.names 22399 22402 22403 +11 1 +.names 1225 22404 +0 1 +.names 22404 22405 +1 1 +.names 22405 22406 +0 1 +.names 6797 22406 22407 +11 1 +.names 22413 22417 22408 +1- 1 +-1 1 +.names 22408 22409 +1 1 +.names 285 22410 +0 1 +.names 22410 22411 +1 1 +.names 22411 22412 +0 1 +.names 22388 22412 22413 +11 1 +.names 1226 22414 +0 1 +.names 22414 22415 +1 1 +.names 22415 22416 +0 1 +.names 6803 22416 22417 +11 1 +.names 22423 22427 22418 +1- 1 +-1 1 +.names 22418 22419 +1 1 +.names 298 22420 +0 1 +.names 22420 22421 +1 1 +.names 22421 22422 +0 1 +.names 22399 22422 22423 +11 1 +.names 1227 22424 +0 1 +.names 22424 22425 +1 1 +.names 22425 22426 +0 1 +.names 6797 22426 22427 +11 1 +.names 22433 22436 22428 +1- 1 +-1 1 +.names 22428 22429 +1 1 +.names 6798 22430 +0 1 +.names 10718 22431 +1 1 +.names 22431 22432 +0 1 +.names 22430 22432 22433 +11 1 +.names 10722 22434 +1 1 +.names 22434 22435 +0 1 +.names 6798 22435 22436 +11 1 +.names 22443 22447 22437 +1- 1 +-1 1 +.names 22437 22438 +1 1 +.names 6800 22439 +0 1 +.names 269 22440 +0 1 +.names 22440 22441 +1 1 +.names 22441 22442 +0 1 +.names 22439 22442 22443 +11 1 +.names 1228 22444 +0 1 +.names 22444 22445 +1 1 +.names 22445 22446 +0 1 +.names 6800 22446 22447 +11 1 +.names 22453 22457 22448 +1- 1 +-1 1 +.names 22448 22449 +1 1 +.names 276 22450 +0 1 +.names 22450 22451 +1 1 +.names 22451 22452 +0 1 +.names 22439 22452 22453 +11 1 +.names 1229 22454 +0 1 +.names 22454 22455 +1 1 +.names 22455 22456 +0 1 +.names 6800 22456 22457 +11 1 +.names 22463 22467 22458 +1- 1 +-1 1 +.names 22458 22459 +1 1 +.names 278 22460 +0 1 +.names 22460 22461 +1 1 +.names 22461 22462 +0 1 +.names 22399 22462 22463 +11 1 +.names 1230 22464 +0 1 +.names 22464 22465 +1 1 +.names 22465 22466 +0 1 +.names 6797 22466 22467 +11 1 +.names 22473 22477 22468 +1- 1 +-1 1 +.names 22468 22469 +1 1 +.names 287 22470 +0 1 +.names 22470 22471 +1 1 +.names 22471 22472 +0 1 +.names 22439 22472 22473 +11 1 +.names 1231 22474 +0 1 +.names 22474 22475 +1 1 +.names 22475 22476 +0 1 +.names 6800 22476 22477 +11 1 +.names 22483 22487 22478 +1- 1 +-1 1 +.names 22478 22479 +1 1 +.names 277 22480 +0 1 +.names 22480 22481 +1 1 +.names 22481 22482 +0 1 +.names 22388 22482 22483 +11 1 +.names 1232 22484 +0 1 +.names 22484 22485 +1 1 +.names 22485 22486 +0 1 +.names 6803 22486 22487 +11 1 +.names 22494 22498 22488 +1- 1 +-1 1 +.names 22488 22489 +1 1 +.names 6802 22490 +0 1 +.names 293 22491 +0 1 +.names 22491 22492 +1 1 +.names 22492 22493 +0 1 +.names 22490 22493 22494 +11 1 +.names 1233 22495 +0 1 +.names 22495 22496 +1 1 +.names 22496 22497 +0 1 +.names 6802 22497 22498 +11 1 +.names 22504 22508 22499 +1- 1 +-1 1 +.names 22499 22500 +1 1 +.names 279 22501 +0 1 +.names 22501 22502 +1 1 +.names 22502 22503 +0 1 +.names 22430 22503 22504 +11 1 +.names 1234 22505 +0 1 +.names 22505 22506 +1 1 +.names 22506 22507 +0 1 +.names 6798 22507 22508 +11 1 +.names 22514 22518 22509 +1- 1 +-1 1 +.names 22509 22510 +1 1 +.names 292 22511 +0 1 +.names 22511 22512 +1 1 +.names 22512 22513 +0 1 +.names 22430 22513 22514 +11 1 +.names 1235 22515 +0 1 +.names 22515 22516 +1 1 +.names 22516 22517 +0 1 +.names 6798 22517 22518 +11 1 +.names 22524 22528 22519 +1- 1 +-1 1 +.names 22519 22520 +1 1 +.names 270 22521 +0 1 +.names 22521 22522 +1 1 +.names 22522 22523 +0 1 +.names 22430 22523 22524 +11 1 +.names 1236 22525 +0 1 +.names 22525 22526 +1 1 +.names 22526 22527 +0 1 +.names 6798 22527 22528 +11 1 +.names 22534 22538 22529 +1- 1 +-1 1 +.names 22529 22530 +1 1 +.names 273 22531 +0 1 +.names 22531 22532 +1 1 +.names 22532 22533 +0 1 +.names 22490 22533 22534 +11 1 +.names 1237 22535 +0 1 +.names 22535 22536 +1 1 +.names 22536 22537 +0 1 +.names 6802 22537 22538 +11 1 +.names 22544 22548 22539 +1- 1 +-1 1 +.names 22539 22540 +1 1 +.names 275 22541 +0 1 +.names 22541 22542 +1 1 +.names 22542 22543 +0 1 +.names 22399 22543 22544 +11 1 +.names 1238 22545 +0 1 +.names 22545 22546 +1 1 +.names 22546 22547 +0 1 +.names 6797 22547 22548 +11 1 +.names 22554 22558 22549 +1- 1 +-1 1 +.names 22549 22550 +1 1 +.names 286 22551 +0 1 +.names 22551 22552 +1 1 +.names 22552 22553 +0 1 +.names 22490 22553 22554 +11 1 +.names 1239 22555 +0 1 +.names 22555 22556 +1 1 +.names 22556 22557 +0 1 +.names 6802 22557 22558 +11 1 +.names 22564 22568 22559 +1- 1 +-1 1 +.names 22559 22560 +1 1 +.names 284 22561 +0 1 +.names 22561 22562 +1 1 +.names 22562 22563 +0 1 +.names 22439 22563 22564 +11 1 +.names 1240 22565 +0 1 +.names 22565 22566 +1 1 +.names 22566 22567 +0 1 +.names 6800 22567 22568 +11 1 +.names 22574 22578 22569 +1- 1 +-1 1 +.names 22569 22570 +1 1 +.names 291 22571 +0 1 +.names 22571 22572 +1 1 +.names 22572 22573 +0 1 +.names 22439 22573 22574 +11 1 +.names 1241 22575 +0 1 +.names 22575 22576 +1 1 +.names 22576 22577 +0 1 +.names 6800 22577 22578 +11 1 +.names 22584 22588 22579 +1- 1 +-1 1 +.names 22579 22580 +1 1 +.names 299 22581 +0 1 +.names 22581 22582 +1 1 +.names 22582 22583 +0 1 +.names 22388 22583 22584 +11 1 +.names 1242 22585 +0 1 +.names 22585 22586 +1 1 +.names 22586 22587 +0 1 +.names 6803 22587 22588 +11 1 +.names 22595 22599 22589 +1- 1 +-1 1 +.names 22589 22590 +1 1 +.names 6801 22591 +0 1 +.names 289 22592 +0 1 +.names 22592 22593 +1 1 +.names 22593 22594 +0 1 +.names 22591 22594 22595 +11 1 +.names 1243 22596 +0 1 +.names 22596 22597 +1 1 +.names 22597 22598 +0 1 +.names 6801 22598 22599 +11 1 +.names 22605 22609 22600 +1- 1 +-1 1 +.names 22600 22601 +1 1 +.names 281 22602 +0 1 +.names 22602 22603 +1 1 +.names 22603 22604 +0 1 +.names 22591 22604 22605 +11 1 +.names 1244 22606 +0 1 +.names 22606 22607 +1 1 +.names 22607 22608 +0 1 +.names 6801 22608 22609 +11 1 +.names 22615 22619 22610 +1- 1 +-1 1 +.names 22610 22611 +1 1 +.names 282 22612 +0 1 +.names 22612 22613 +1 1 +.names 22613 22614 +0 1 +.names 22490 22614 22615 +11 1 +.names 1245 22616 +0 1 +.names 22616 22617 +1 1 +.names 22617 22618 +0 1 +.names 6802 22618 22619 +11 1 +.names 22625 22629 22620 +1- 1 +-1 1 +.names 22620 22621 +1 1 +.names 296 22622 +0 1 +.names 22622 22623 +1 1 +.names 22623 22624 +0 1 +.names 22399 22624 22625 +11 1 +.names 1246 22626 +0 1 +.names 22626 22627 +1 1 +.names 22627 22628 +0 1 +.names 6797 22628 22629 +11 1 +.names 22635 22639 22630 +1- 1 +-1 1 +.names 22630 22631 +1 1 +.names 280 22632 +0 1 +.names 22632 22633 +1 1 +.names 22633 22634 +0 1 +.names 22430 22634 22635 +11 1 +.names 1247 22636 +0 1 +.names 22636 22637 +1 1 +.names 22637 22638 +0 1 +.names 6798 22638 22639 +11 1 +.names 22645 22649 22640 +1- 1 +-1 1 +.names 22640 22641 +1 1 +.names 294 22642 +0 1 +.names 22642 22643 +1 1 +.names 22643 22644 +0 1 +.names 22388 22644 22645 +11 1 +.names 1248 22646 +0 1 +.names 22646 22647 +1 1 +.names 22647 22648 +0 1 +.names 6803 22648 22649 +11 1 +.names 22655 22659 22650 +1- 1 +-1 1 +.names 22650 22651 +1 1 +.names 295 22652 +0 1 +.names 22652 22653 +1 1 +.names 22653 22654 +0 1 +.names 22388 22654 22655 +11 1 +.names 1249 22656 +0 1 +.names 22656 22657 +1 1 +.names 22657 22658 +0 1 +.names 6803 22658 22659 +11 1 +.names 22665 22669 22660 +1- 1 +-1 1 +.names 22660 22661 +1 1 +.names 271 22662 +0 1 +.names 22662 22663 +1 1 +.names 22663 22664 +0 1 +.names 22591 22664 22665 +11 1 +.names 1250 22666 +0 1 +.names 22666 22667 +1 1 +.names 22667 22668 +0 1 +.names 6801 22668 22669 +11 1 +.names 22675 22679 22670 +1- 1 +-1 1 +.names 22670 22671 +1 1 +.names 272 22672 +0 1 +.names 22672 22673 +1 1 +.names 22673 22674 +0 1 +.names 22591 22674 22675 +11 1 +.names 1251 22676 +0 1 +.names 22676 22677 +1 1 +.names 22677 22678 +0 1 +.names 6801 22678 22679 +11 1 +.names 22685 22689 22680 +1- 1 +-1 1 +.names 22680 22681 +1 1 +.names 283 22682 +0 1 +.names 22682 22683 +1 1 +.names 22683 22684 +0 1 +.names 22591 22684 22685 +11 1 +.names 1252 22686 +0 1 +.names 22686 22687 +1 1 +.names 22687 22688 +0 1 +.names 6801 22688 22689 +11 1 +.names 22695 22699 22690 +1- 1 +-1 1 +.names 22690 22691 +1 1 +.names 288 22692 +0 1 +.names 22692 22693 +1 1 +.names 22693 22694 +0 1 +.names 22490 22694 22695 +11 1 +.names 1253 22696 +0 1 +.names 22696 22697 +1 1 +.names 22697 22698 +0 1 +.names 6802 22698 22699 +11 1 +.names 22705 22709 22700 +1- 1 +-1 1 +.names 22700 22701 +1 1 +.names 297 22702 +0 1 +.names 22702 22703 +1 1 +.names 22703 22704 +0 1 +.names 22490 22704 22705 +11 1 +.names 1254 22706 +0 1 +.names 22706 22707 +1 1 +.names 22707 22708 +0 1 +.names 6802 22708 22709 +11 1 +.names 22712 22713 22710 +1- 1 +-1 1 +.names 22710 22711 +1 1 +.names 6815 22712 +0 1 +.names 1255 22713 +0 1 +.names 22718 22719 22714 +1- 1 +-1 1 +.names 22714 22715 +1 1 +.names 45082 45086 22716 +1- 1 +-1 1 +.names 22716 22717 +1 1 +.names 22717 22718 +0 1 +.names 6836 22719 +0 1 +.names 22731 22732 22720 +1- 1 +-1 1 +.names 22720 22721 +1 1 +.names 22721 22722 +0 1 +.names 22715 22723 +0 1 +.names 22722 22723 22724 +1- 1 +-1 1 +.names 22735 22737 22725 +11 1 +.names 22725 22726 +1 1 +.names 22726 22727 +0 1 +.names 22748 22749 22728 +11 1 +.names 22728 22729 +1 1 +.names 22729 22730 +0 1 +.names 2413 22730 22731 +11 1 +.names 1783 2413 22732 +11 1 +.names 6825 22750 22733 +1- 1 +-1 1 +.names 22733 22734 +1 1 +.names 22734 22711 22735 +11 1 +.names 6833 22752 22736 +1- 1 +-1 1 +.names 22736 22737 +1 1 +.names 22742 22743 22738 +1- 1 +-1 1 +.names 22738 22739 +1 1 +.names 22712 22740 +1 1 +.names 22740 22741 +0 1 +.names 6836 22741 22742 +1- 1 +-1 1 +.names 22398 22743 +0 1 +.names 6838 22747 22744 +1- 1 +-1 1 +.names 22744 22745 +1 1 +.names 6833 22746 +1 1 +.names 22746 22747 +0 1 +.names 22739 22748 +0 1 +.names 22745 22749 +0 1 +.names 1256 22750 +0 1 +.names 46251 46254 56483 +1- 1 +-1 1 +.names 56483 22752 +0 1 +.names 22757 22719 22753 +1- 1 +-1 1 +.names 22753 22754 +1 1 +.names 45073 45077 22755 +1- 1 +-1 1 +.names 22755 22756 +1 1 +.names 22756 22757 +0 1 +.names 22764 22766 22758 +1- 1 +-1 1 +.names 22758 22759 +1 1 +.names 6837 22760 +0 1 +.names 22777 22778 22761 +11 1 +.names 22761 22762 +1 1 +.names 22762 22763 +0 1 +.names 22760 22763 22764 +11 1 +.names 1257 22765 +0 1 +.names 6837 22765 22766 +11 1 +.names 22771 22772 22767 +1- 1 +-1 1 +.names 22767 22768 +1 1 +.names 6833 22769 +1 1 +.names 22769 22770 +0 1 +.names 6847 22770 22771 +1- 1 +-1 1 +.names 22387 22772 +0 1 +.names 6836 22776 22773 +1- 1 +-1 1 +.names 22773 22774 +1 1 +.names 2413 22775 +1 1 +.names 22775 22776 +0 1 +.names 22768 22777 +0 1 +.names 22774 22778 +0 1 +.names 22796 22797 22779 +1- 1 +-1 1 +.names 22779 22780 +1 1 +.names 22759 22781 +0 1 +.names 6833 22785 22782 +1- 1 +-1 1 +.names 22782 22783 +1 1 +.names 46243 46246 56467 +1- 1 +-1 1 +.names 56467 22785 +0 1 +.names 2413 22786 +1 1 +.names 22786 22787 +1 1 +.names 22790 22791 22788 +1- 1 +-1 1 +.names 22788 22789 +1 1 +.names 1258 22790 +0 1 +.names 6847 22791 +0 1 +.names 22787 22792 +0 1 +.names 22789 22793 +0 1 +.names 22792 22793 22794 +1- 1 +-1 1 +.names 22783 22795 +0 1 +.names 22794 22795 22796 +1- 1 +-1 1 +.names 22754 22797 +0 1 +.names 22812 22816 22798 +1- 1 +-1 1 +.names 22798 22799 +1 1 +.names 22799 22800 +0 1 +.names 2413 22801 +1 1 +.names 22801 22802 +1 1 +.names 22802 22803 +0 1 +.names 22800 22803 22804 +1- 1 +-1 1 +.names 22821 22823 22805 +11 1 +.names 22805 22806 +1 1 +.names 22806 22807 +0 1 +.names 6807 22808 +0 1 +.names 22830 22831 22809 +11 1 +.names 22809 22810 +1 1 +.names 22810 22811 +0 1 +.names 22808 22811 22812 +11 1 +.names 45115 45119 22813 +1- 1 +-1 1 +.names 22813 22814 +1 1 +.names 22814 22815 +0 1 +.names 6807 22815 22816 +11 1 +.names 22760 22841 22817 +1- 1 +-1 1 +.names 22817 22818 +1 1 +.names 6825 22842 22819 +1- 1 +-1 1 +.names 22819 22820 +1 1 +.names 22818 22820 22821 +11 1 +.names 22833 22834 22822 +1- 1 +-1 1 +.names 22822 22823 +1 1 +.names 6838 22827 22824 +1- 1 +-1 1 +.names 22824 22825 +1 1 +.names 2413 22826 +1 1 +.names 22826 22827 +0 1 +.names 22839 22840 22828 +1- 1 +-1 1 +.names 22828 22829 +1 1 +.names 22829 22830 +0 1 +.names 22825 22831 +0 1 +.names 46281 46284 56462 +1- 1 +-1 1 +.names 56462 22833 +0 1 +.names 6822 22834 +0 1 +.names 22834 22835 +1 1 +.names 22835 22836 +0 1 +.names 22760 22837 +1 1 +.names 22837 22838 +0 1 +.names 22836 22838 22839 +1- 1 +-1 1 +.names 22438 22840 +0 1 +.names 1259 22841 +0 1 +.names 1260 22842 +0 1 +.names 22857 22861 22843 +1- 1 +-1 1 +.names 22843 22844 +1 1 +.names 22844 22845 +0 1 +.names 2413 22846 +1 1 +.names 22846 22847 +1 1 +.names 22847 22848 +0 1 +.names 22845 22848 22849 +1- 1 +-1 1 +.names 22881 22882 22850 +11 1 +.names 22850 22851 +1 1 +.names 22851 22852 +0 1 +.names 6843 22853 +0 1 +.names 22868 22869 22854 +11 1 +.names 22854 22855 +1 1 +.names 22855 22856 +0 1 +.names 22853 22856 22857 +11 1 +.names 45123 45127 22858 +1- 1 +-1 1 +.names 22858 22859 +1 1 +.names 22859 22860 +0 1 +.names 6843 22860 22861 +11 1 +.names 6842 22865 22862 +1- 1 +-1 1 +.names 22862 22863 +1 1 +.names 2413 22864 +1 1 +.names 22864 22865 +0 1 +.names 22889 22890 22866 +1- 1 +-1 1 +.names 22866 22867 +1 1 +.names 22867 22868 +0 1 +.names 22863 22869 +0 1 +.names 22873 22874 22870 +1- 1 +-1 1 +.names 22870 22871 +1 1 +.names 46288 46291 56469 +1- 1 +-1 1 +.names 56469 22873 +0 1 +.names 6842 22874 +0 1 +.names 22877 22878 22875 +1- 1 +-1 1 +.names 22875 22876 +1 1 +.names 1261 6816 22877 +11 1 +.names 22871 22878 +0 1 +.names 6846 1262 22879 +11 1 +.names 22879 22880 +1 1 +.names 22880 22881 +0 1 +.names 22876 22882 +0 1 +.names 6816 22883 +0 1 +.names 22883 22884 +1 1 +.names 6846 22885 +0 1 +.names 22885 22886 +1 1 +.names 22886 22887 +0 1 +.names 22884 22888 +0 1 +.names 22887 22888 22889 +1- 1 +-1 1 +.names 22449 22890 +0 1 +.names 22883 22893 22891 +1- 1 +-1 1 +.names 22891 22892 +1 1 +.names 1263 22893 +0 1 +.names 22897 6833 22894 +1- 1 +-1 1 +.names 22894 22895 +1 1 +.names 46295 46298 56471 +1- 1 +-1 1 +.names 56471 22897 +0 1 +.names 6845 22901 22898 +1- 1 +-1 1 +.names 22898 22899 +1 1 +.names 2413 22900 +1 1 +.names 22900 22901 +0 1 +.names 22907 22911 22902 +1- 1 +-1 1 +.names 22902 22903 +1 1 +.names 22914 22915 22904 +11 1 +.names 22904 22905 +1 1 +.names 22905 22906 +0 1 +.names 22853 22906 22907 +11 1 +.names 45131 45135 22908 +1- 1 +-1 1 +.names 22908 22909 +1 1 +.names 22909 22910 +0 1 +.names 6843 22910 22911 +11 1 +.names 22918 22919 22912 +1- 1 +-1 1 +.names 22912 22913 +1 1 +.names 22913 22914 +0 1 +.names 22899 22915 +0 1 +.names 22883 22916 +1 1 +.names 22916 22917 +0 1 +.names 6819 22917 22918 +1- 1 +-1 1 +.names 22459 22919 +0 1 +.names 22926 22927 22920 +1- 1 +-1 1 +.names 22920 22921 +1 1 +.names 22892 22922 +0 1 +.names 22936 22937 22923 +1- 1 +-1 1 +.names 22923 22924 +1 1 +.names 22924 22925 +0 1 +.names 22922 22925 22926 +1- 1 +-1 1 +.names 22895 22927 +0 1 +.names 22930 22933 22928 +11 1 +.names 22928 22929 +1 1 +.names 22921 22930 +0 1 +.names 1783 22931 +1 1 +.names 22931 22932 +1 1 +.names 22932 22933 +0 1 +.names 22903 22934 +0 1 +.names 22929 22935 +0 1 +.names 6845 22936 +0 1 +.names 1264 22937 +0 1 +.names 22952 22955 22938 +1- 1 +-1 1 +.names 22938 22939 +1 1 +.names 22939 22940 +0 1 +.names 2413 22941 +1 1 +.names 22941 22942 +1 1 +.names 22942 22943 +0 1 +.names 22940 22943 22944 +1- 1 +-1 1 +.names 22980 22973 22945 +11 1 +.names 22945 22946 +1 1 +.names 22946 22947 +0 1 +.names 6832 22948 +0 1 +.names 22967 22968 22949 +11 1 +.names 22949 22950 +1 1 +.names 22950 22951 +0 1 +.names 22948 22951 22952 +11 1 +.names 46258 46261 56478 +1- 1 +-1 1 +.names 56478 22954 +0 1 +.names 6832 22954 22955 +11 1 +.names 6836 22958 22956 +1- 1 +-1 1 +.names 22956 22957 +1 1 +.names 22409 22958 +0 1 +.names 22963 22965 22959 +1- 1 +-1 1 +.names 22959 22960 +1 1 +.names 22966 2413 22961 +11 1 +.names 22961 22962 +1 1 +.names 22962 22963 +0 1 +.names 22791 22964 +1 1 +.names 22964 22965 +0 1 +.names 6817 22966 +0 1 +.names 22960 22967 +0 1 +.names 22957 22968 +0 1 +.names 22966 22971 22969 +1- 1 +-1 1 +.names 22969 22970 +1 1 +.names 1265 22971 +0 1 +.names 22976 22719 22972 +1- 1 +-1 1 +.names 22972 22973 +1 1 +.names 45090 45094 22974 +1- 1 +-1 1 +.names 22974 22975 +1 1 +.names 22975 22976 +0 1 +.names 22791 22979 22977 +1- 1 +-1 1 +.names 22977 22978 +1 1 +.names 1266 22979 +0 1 +.names 22978 22970 22980 +11 1 +.names 22995 22999 22981 +1- 1 +-1 1 +.names 22981 22982 +1 1 +.names 22982 22983 +0 1 +.names 2413 22984 +1 1 +.names 22984 22985 +1 1 +.names 22985 22986 +0 1 +.names 22983 22986 22987 +1- 1 +-1 1 +.names 23021 23022 22988 +11 1 +.names 22988 22989 +1 1 +.names 22989 22990 +0 1 +.names 6805 22991 +0 1 +.names 23016 23017 22992 +11 1 +.names 22992 22993 +1 1 +.names 22993 22994 +0 1 +.names 22991 22994 22995 +11 1 +.names 45098 45102 22996 +1- 1 +-1 1 +.names 22996 22997 +1 1 +.names 22997 22998 +0 1 +.names 6805 22998 22999 +11 1 +.names 23002 23005 23000 +1- 1 +-1 1 +.names 23000 23001 +1 1 +.names 6815 1267 23002 +11 1 +.names 23023 22885 23003 +1- 1 +-1 1 +.names 23003 23004 +1 1 +.names 23004 23005 +0 1 +.names 23010 23011 23006 +1- 1 +-1 1 +.names 23006 23007 +1 1 +.names 22712 23008 +1 1 +.names 23008 23009 +0 1 +.names 6841 23009 23010 +1- 1 +-1 1 +.names 22419 23011 +0 1 +.names 6846 23015 23012 +1- 1 +-1 1 +.names 23012 23013 +1 1 +.names 2413 23014 +1 1 +.names 23014 23015 +0 1 +.names 23007 23016 +0 1 +.names 23013 23017 +0 1 +.names 56491 6841 23018 +11 1 +.names 23018 23019 +1 1 +.names 46265 46268 56491 +1- 1 +-1 1 +.names 23019 23021 +0 1 +.names 23001 23022 +0 1 +.names 1268 23023 +0 1 +.names 23037 23041 23024 +1- 1 +-1 1 +.names 23024 23025 +1 1 +.names 23025 23026 +0 1 +.names 2413 23027 +1 1 +.names 23027 23028 +1 1 +.names 23028 23029 +0 1 +.names 23026 23029 23030 +1- 1 +-1 1 +.names 23046 23048 23031 +11 1 +.names 23031 23032 +1 1 +.names 23032 23033 +0 1 +.names 23059 23060 23034 +11 1 +.names 23034 23035 +1 1 +.names 23035 23036 +0 1 +.names 22853 23036 23037 +11 1 +.names 45139 45143 23038 +1- 1 +-1 1 +.names 23038 23039 +1 1 +.names 23039 23040 +0 1 +.names 6843 23040 23041 +11 1 +.names 22760 23064 23042 +1- 1 +-1 1 +.names 23042 23043 +1 1 +.names 6825 23065 23044 +1- 1 +-1 1 +.names 23044 23045 +1 1 +.names 23043 23045 23046 +11 1 +.names 23062 23063 23047 +1- 1 +-1 1 +.names 23047 23048 +1 1 +.names 23053 23054 23049 +1- 1 +-1 1 +.names 23049 23050 +1 1 +.names 22760 23051 +1 1 +.names 23051 23052 +0 1 +.names 6841 23052 23053 +1- 1 +-1 1 +.names 22469 23054 +0 1 +.names 6838 23058 23055 +1- 1 +-1 1 +.names 23055 23056 +1 1 +.names 2413 23057 +1 1 +.names 23057 23058 +0 1 +.names 23056 23059 +0 1 +.names 23050 23060 +0 1 +.names 46302 46305 56480 +1- 1 +-1 1 +.names 56480 23062 +0 1 +.names 6841 23063 +0 1 +.names 1269 23064 +0 1 +.names 1270 23065 +0 1 +.names 23071 23075 23066 +1- 1 +-1 1 +.names 23066 23067 +1 1 +.names 23082 23083 23068 +11 1 +.names 23068 23069 +1 1 +.names 23069 23070 +0 1 +.names 22853 23070 23071 +11 1 +.names 45147 45151 23072 +1- 1 +-1 1 +.names 23072 23073 +1 1 +.names 23073 23074 +0 1 +.names 6843 23074 23075 +11 1 +.names 1783 23079 23076 +1- 1 +-1 1 +.names 23076 23077 +1 1 +.names 22885 23078 +1 1 +.names 23078 23079 +0 1 +.names 23090 23091 23080 +1- 1 +-1 1 +.names 23080 23081 +1 1 +.names 23081 23082 +0 1 +.names 23077 23083 +0 1 +.names 23087 22834 23084 +1- 1 +-1 1 +.names 23084 23085 +1 1 +.names 46309 46312 56470 +1- 1 +-1 1 +.names 56470 23087 +0 1 +.names 22760 23088 +1 1 +.names 23088 23089 +0 1 +.names 6822 23089 23090 +1- 1 +-1 1 +.names 22479 23091 +0 1 +.names 23100 23101 23092 +1- 1 +-1 1 +.names 23092 23093 +1 1 +.names 22760 23110 23094 +1- 1 +-1 1 +.names 23094 23095 +1 1 +.names 23095 23096 +0 1 +.names 22885 23111 23097 +1- 1 +-1 1 +.names 23097 23098 +1 1 +.names 23098 23099 +0 1 +.names 23096 23099 23100 +1- 1 +-1 1 +.names 23085 23101 +0 1 +.names 23067 23102 +0 1 +.names 23108 23109 23103 +11 1 +.names 23103 23104 +1 1 +.names 23104 23105 +0 1 +.names 1783 23106 +1 1 +.names 23106 23107 +1 1 +.names 23093 23108 +0 1 +.names 23107 23109 +0 1 +.names 1271 23110 +0 1 +.names 1272 23111 +0 1 +.names 23125 23129 23112 +1- 1 +-1 1 +.names 23112 23113 +1 1 +.names 23113 23114 +0 1 +.names 2413 23115 +1 1 +.names 23115 23116 +1 1 +.names 23116 23117 +0 1 +.names 23114 23117 23118 +1- 1 +-1 1 +.names 23152 23143 23119 +11 1 +.names 23119 23120 +1 1 +.names 23120 23121 +0 1 +.names 23140 23141 23122 +11 1 +.names 23122 23123 +1 1 +.names 23123 23124 +0 1 +.names 22853 23124 23125 +11 1 +.names 45156 45160 23126 +1- 1 +-1 1 +.names 23126 23127 +1 1 +.names 23127 23128 +0 1 +.names 6843 23128 23129 +11 1 +.names 23134 23135 23130 +1- 1 +-1 1 +.names 23130 23131 +1 1 +.names 22712 23132 +1 1 +.names 23132 23133 +0 1 +.names 6841 23133 23134 +1- 1 +-1 1 +.names 22489 23135 +0 1 +.names 6847 23139 23136 +1- 1 +-1 1 +.names 23136 23137 +1 1 +.names 2413 23138 +1 1 +.names 23138 23139 +0 1 +.names 23131 23140 +0 1 +.names 23137 23141 +0 1 +.names 23145 23063 23142 +1- 1 +-1 1 +.names 23142 23143 +1 1 +.names 46317 46320 56486 +1- 1 +-1 1 +.names 56486 23145 +0 1 +.names 22712 23148 23146 +1- 1 +-1 1 +.names 23146 23147 +1 1 +.names 1273 23148 +0 1 +.names 22791 23151 23149 +1- 1 +-1 1 +.names 23149 23150 +1 1 +.names 1274 23151 +0 1 +.names 23150 23147 23152 +11 1 +.names 23166 23170 23153 +1- 1 +-1 1 +.names 23153 23154 +1 1 +.names 23154 23155 +0 1 +.names 2413 23156 +1 1 +.names 23156 23157 +1 1 +.names 23157 23158 +0 1 +.names 23155 23158 23159 +1- 1 +-1 1 +.names 23175 23177 23160 +11 1 +.names 23160 23161 +1 1 +.names 23161 23162 +0 1 +.names 23188 23189 23163 +11 1 +.names 23163 23164 +1 1 +.names 23164 23165 +0 1 +.names 22991 23165 23166 +11 1 +.names 45164 45168 23167 +1- 1 +-1 1 +.names 23167 23168 +1 1 +.names 23168 23169 +0 1 +.names 6805 23169 23170 +11 1 +.names 22712 23193 23171 +1- 1 +-1 1 +.names 23171 23172 +1 1 +.names 6825 23192 23173 +1- 1 +-1 1 +.names 23173 23174 +1 1 +.names 23172 23174 23175 +11 1 +.names 23191 6833 23176 +1- 1 +-1 1 +.names 23176 23177 +1 1 +.names 6819 23180 23178 +1- 1 +-1 1 +.names 23178 23179 +1 1 +.names 22500 23180 +0 1 +.names 23185 23187 23181 +1- 1 +-1 1 +.names 23181 23182 +1 1 +.names 22712 2413 23183 +11 1 +.names 23183 23184 +1 1 +.names 23184 23185 +0 1 +.names 6825 23186 +1 1 +.names 23186 23187 +0 1 +.names 23182 23188 +0 1 +.names 23179 23189 +0 1 +.names 46324 46327 56472 +1- 1 +-1 1 +.names 56472 23191 +0 1 +.names 1275 23192 +0 1 +.names 1276 23193 +0 1 +.names 23196 22712 23194 +1- 1 +-1 1 +.names 23194 23195 +1 1 +.names 1277 23196 +0 1 +.names 23210 23214 23197 +1- 1 +-1 1 +.names 23197 23198 +1 1 +.names 23198 23199 +0 1 +.names 2413 23200 +1 1 +.names 23200 23201 +1 1 +.names 23201 23202 +0 1 +.names 23199 23202 23203 +1- 1 +-1 1 +.names 23234 23235 23204 +11 1 +.names 23204 23205 +1 1 +.names 23205 23206 +0 1 +.names 23229 23230 23207 +11 1 +.names 23207 23208 +1 1 +.names 23208 23209 +0 1 +.names 22991 23209 23210 +11 1 +.names 45172 45176 23211 +1- 1 +-1 1 +.names 23211 23212 +1 1 +.names 23212 23213 +0 1 +.names 6805 23213 23214 +11 1 +.names 23217 23218 23215 +1- 1 +-1 1 +.names 23215 23216 +1 1 +.names 6846 1278 23217 +11 1 +.names 23195 23218 +0 1 +.names 23223 23224 23219 +1- 1 +-1 1 +.names 23219 23220 +1 1 +.names 22712 23221 +1 1 +.names 23221 23222 +0 1 +.names 6841 23222 23223 +1- 1 +-1 1 +.names 22510 23224 +0 1 +.names 6846 23228 23225 +1- 1 +-1 1 +.names 23225 23226 +1 1 +.names 2413 23227 +1 1 +.names 23227 23228 +0 1 +.names 23220 23229 +0 1 +.names 23226 23230 +0 1 +.names 56485 6841 23231 +11 1 +.names 23231 23232 +1 1 +.names 46331 46334 56485 +1- 1 +-1 1 +.names 23232 23234 +0 1 +.names 23216 23235 +0 1 +.names 23249 23250 23236 +1- 1 +-1 1 +.names 23236 23237 +1 1 +.names 23237 23238 +0 1 +.names 2413 23239 +1 1 +.names 23239 23240 +1 1 +.names 23240 23241 +0 1 +.names 23238 23241 23242 +1- 1 +-1 1 +.names 23271 23272 23243 +11 1 +.names 23243 23244 +1 1 +.names 23244 23245 +0 1 +.names 23261 23262 23246 +11 1 +.names 23246 23247 +1 1 +.names 23247 23248 +0 1 +.names 22808 23248 23249 +11 1 +.names 6807 10763 23250 +11 1 +.names 23255 23256 23251 +1- 1 +-1 1 +.names 23251 23252 +1 1 +.names 22883 23253 +1 1 +.names 23253 23254 +0 1 +.names 6845 23254 23255 +1- 1 +-1 1 +.names 22429 23256 +0 1 +.names 6819 23260 23257 +1- 1 +-1 1 +.names 23257 23258 +1 1 +.names 2413 23259 +1 1 +.names 23259 23260 +0 1 +.names 23252 23261 +0 1 +.names 23258 23262 +0 1 +.names 10786 6833 23263 +1- 1 +-1 1 +.names 23263 23264 +1 1 +.names 23267 23268 23265 +1- 1 +-1 1 +.names 23265 23266 +1 1 +.names 6816 965 23267 +11 1 +.names 23264 23268 +0 1 +.names 6845 966 23269 +11 1 +.names 23269 23270 +1 1 +.names 23270 23271 +0 1 +.names 23266 23272 +0 1 +.names 23279 23281 23273 +1- 1 +-1 1 +.names 23273 23274 +1 1 +.names 6824 23275 +0 1 +.names 23292 23293 23276 +11 1 +.names 23276 23277 +1 1 +.names 23277 23278 +0 1 +.names 23275 23278 23279 +11 1 +.names 1279 23280 +0 1 +.names 6824 23280 23281 +11 1 +.names 6836 23284 23282 +1- 1 +-1 1 +.names 23282 23283 +1 1 +.names 22550 23284 +0 1 +.names 23289 23291 23285 +1- 1 +-1 1 +.names 23285 23286 +1 1 +.names 22883 2413 23287 +11 1 +.names 23287 23288 +1 1 +.names 23288 23289 +0 1 +.names 6833 23290 +1 1 +.names 23290 23291 +0 1 +.names 23286 23292 +0 1 +.names 23283 23293 +0 1 +.names 23309 23312 23294 +1- 1 +-1 1 +.names 23294 23295 +1 1 +.names 23274 23296 +0 1 +.names 23300 6833 23297 +1- 1 +-1 1 +.names 23297 23298 +1 1 +.names 46359 46362 56479 +1- 1 +-1 1 +.names 56479 23300 +0 1 +.names 23298 23301 +0 1 +.names 23315 22719 23302 +1- 1 +-1 1 +.names 23302 23303 +1 1 +.names 23303 23304 +0 1 +.names 23301 23304 23305 +1- 1 +-1 1 +.names 23316 22883 23306 +1- 1 +-1 1 +.names 23306 23307 +1 1 +.names 23307 23308 +0 1 +.names 23305 23308 23309 +1- 1 +-1 1 +.names 2413 23310 +1 1 +.names 23310 23311 +1 1 +.names 23311 23312 +0 1 +.names 45204 45208 23313 +1- 1 +-1 1 +.names 23313 23314 +1 1 +.names 23314 23315 +0 1 +.names 1280 23316 +0 1 +.names 23322 23326 23317 +1- 1 +-1 1 +.names 23317 23318 +1 1 +.names 23337 23338 23319 +11 1 +.names 23319 23320 +1 1 +.names 23320 23321 +0 1 +.names 22991 23321 23322 +11 1 +.names 45196 45200 23323 +1- 1 +-1 1 +.names 23323 23324 +1 1 +.names 23324 23325 +0 1 +.names 6805 23325 23326 +11 1 +.names 23331 23332 23327 +1- 1 +-1 1 +.names 23327 23328 +1 1 +.names 22883 23329 +1 1 +.names 23329 23330 +0 1 +.names 6822 23330 23331 +1- 1 +-1 1 +.names 22540 23332 +0 1 +.names 6838 23336 23333 +1- 1 +-1 1 +.names 23333 23334 +1 1 +.names 2413 23335 +1 1 +.names 23335 23336 +0 1 +.names 23328 23337 +0 1 +.names 23334 23338 +0 1 +.names 6825 23341 23339 +1- 1 +-1 1 +.names 23339 23340 +1 1 +.names 1281 23341 +0 1 +.names 23345 22834 23342 +1- 1 +-1 1 +.names 23342 23343 +1 1 +.names 46352 46355 56468 +1- 1 +-1 1 +.names 56468 23345 +0 1 +.names 23352 23353 23346 +1- 1 +-1 1 +.names 23346 23347 +1 1 +.names 23340 23348 +0 1 +.names 22883 23362 23349 +1- 1 +-1 1 +.names 23349 23350 +1 1 +.names 23350 23351 +0 1 +.names 23348 23351 23352 +1- 1 +-1 1 +.names 23343 23353 +0 1 +.names 23318 23354 +0 1 +.names 23358 23361 23355 +11 1 +.names 23355 23356 +1 1 +.names 23356 23357 +0 1 +.names 23347 23358 +0 1 +.names 1783 23359 +1 1 +.names 23359 23360 +1 1 +.names 23360 23361 +0 1 +.names 1282 23362 +0 1 +.names 23376 23380 23363 +1- 1 +-1 1 +.names 23363 23364 +1 1 +.names 23364 23365 +0 1 +.names 2413 23366 +1 1 +.names 23366 23367 +1 1 +.names 23367 23368 +0 1 +.names 23365 23368 23369 +1- 1 +-1 1 +.names 23383 23386 23370 +11 1 +.names 23370 23371 +1 1 +.names 23371 23372 +0 1 +.names 23393 23394 23373 +11 1 +.names 23373 23374 +1 1 +.names 23374 23375 +0 1 +.names 22991 23375 23376 +11 1 +.names 45180 45184 23377 +1- 1 +-1 1 +.names 23377 23378 +1 1 +.names 23378 23379 +0 1 +.names 6805 23379 23380 +11 1 +.names 23400 1283 23381 +11 1 +.names 23381 23382 +1 1 +.names 23382 23383 +0 1 +.names 23402 23403 23384 +1- 1 +-1 1 +.names 23384 23385 +1 1 +.names 23385 23386 +0 1 +.names 6819 23390 23387 +1- 1 +-1 1 +.names 23387 23388 +1 1 +.names 2413 23389 +1 1 +.names 23389 23390 +0 1 +.names 23406 23407 23391 +1- 1 +-1 1 +.names 23391 23392 +1 1 +.names 23392 23393 +0 1 +.names 23388 23394 +0 1 +.names 23398 6833 23395 +1- 1 +-1 1 +.names 23395 23396 +1 1 +.names 46338 46341 56463 +1- 1 +-1 1 +.names 56463 23398 +0 1 +.names 23404 23399 +0 1 +.names 23399 23400 +1 1 +.names 22966 23401 +1 1 +.names 6817 1284 23402 +11 1 +.names 23396 23403 +0 1 +.names 22791 23404 +1 1 +.names 23401 23405 +0 1 +.names 23399 23405 23406 +1- 1 +-1 1 +.names 22520 23407 +0 1 +.names 23410 22760 23408 +1- 1 +-1 1 +.names 23408 23409 +1 1 +.names 1285 23410 +0 1 +.names 23424 23428 23411 +1- 1 +-1 1 +.names 23411 23412 +1 1 +.names 23412 23413 +0 1 +.names 2413 23414 +1 1 +.names 23414 23415 +1 1 +.names 23415 23416 +0 1 +.names 23413 23416 23417 +1- 1 +-1 1 +.names 23431 23434 23418 +11 1 +.names 23418 23419 +1 1 +.names 23419 23420 +0 1 +.names 23439 23442 23421 +11 1 +.names 23421 23422 +1 1 +.names 23422 23423 +0 1 +.names 22808 23423 23424 +11 1 +.names 45188 45192 23425 +1- 1 +-1 1 +.names 23425 23426 +1 1 +.names 23426 23427 +0 1 +.names 6807 23427 23428 +11 1 +.names 23444 23429 +0 1 +.names 23429 23430 +1 1 +.names 23430 23431 +0 1 +.names 23453 23454 23432 +1- 1 +-1 1 +.names 23432 23433 +1 1 +.names 23433 23434 +0 1 +.names 6846 23438 23435 +1- 1 +-1 1 +.names 23435 23436 +1 1 +.names 2413 23437 +1 1 +.names 23437 23438 +0 1 +.names 23436 23439 +0 1 +.names 23451 23452 23440 +1- 1 +-1 1 +.names 23440 23441 +1 1 +.names 23441 23442 +0 1 +.names 23446 22834 23443 +1- 1 +-1 1 +.names 23443 23444 +1 1 +.names 46345 46348 56466 +1- 1 +-1 1 +.names 56466 23446 +0 1 +.names 22834 23447 +1 1 +.names 23447 23448 +0 1 +.names 22760 23449 +1 1 +.names 23449 23450 +0 1 +.names 23448 23450 23451 +1- 1 +-1 1 +.names 22530 23452 +0 1 +.names 6846 1286 23453 +11 1 +.names 23409 23454 +0 1 +.names 22883 23457 23455 +1- 1 +-1 1 +.names 23455 23456 +1 1 +.names 1287 23457 +0 1 +.names 23463 23467 23458 +1- 1 +-1 1 +.names 23458 23459 +1 1 +.names 23478 23479 23460 +11 1 +.names 23460 23461 +1 1 +.names 23461 23462 +0 1 +.names 22853 23462 23463 +11 1 +.names 45212 45216 23464 +1- 1 +-1 1 +.names 23464 23465 +1 1 +.names 23465 23466 +0 1 +.names 6843 23466 23467 +11 1 +.names 23472 23473 23468 +1- 1 +-1 1 +.names 23468 23469 +1 1 +.names 22883 23470 +1 1 +.names 23470 23471 +0 1 +.names 6822 23471 23472 +1- 1 +-1 1 +.names 22560 23473 +0 1 +.names 6838 23477 23474 +1- 1 +-1 1 +.names 23474 23475 +1 1 +.names 2413 23476 +1 1 +.names 23476 23477 +0 1 +.names 23469 23478 +0 1 +.names 23475 23479 +0 1 +.names 23483 22834 23480 +1- 1 +-1 1 +.names 23480 23481 +1 1 +.names 46366 46369 56477 +1- 1 +-1 1 +.names 56477 23483 +0 1 +.names 23490 23491 23484 +1- 1 +-1 1 +.names 23484 23485 +1 1 +.names 23456 23486 +0 1 +.names 6825 23500 23487 +1- 1 +-1 1 +.names 23487 23488 +1 1 +.names 23488 23489 +0 1 +.names 23486 23489 23490 +1- 1 +-1 1 +.names 23481 23491 +0 1 +.names 23459 23492 +0 1 +.names 23498 23499 23493 +11 1 +.names 23493 23494 +1 1 +.names 23494 23495 +0 1 +.names 1783 23496 +1 1 +.names 23496 23497 +1 1 +.names 23485 23498 +0 1 +.names 23497 23499 +0 1 +.names 1288 23500 +0 1 +.names 23514 23518 23501 +1- 1 +-1 1 +.names 23501 23502 +1 1 +.names 23502 23503 +0 1 +.names 2413 23504 +1 1 +.names 23504 23505 +1 1 +.names 23505 23506 +0 1 +.names 23503 23506 23507 +1- 1 +-1 1 +.names 23541 23532 23508 +11 1 +.names 23508 23509 +1 1 +.names 23509 23510 +0 1 +.names 23529 23530 23511 +11 1 +.names 23511 23512 +1 1 +.names 23512 23513 +0 1 +.names 22991 23513 23514 +11 1 +.names 45220 45224 23515 +1- 1 +-1 1 +.names 23515 23516 +1 1 +.names 23516 23517 +0 1 +.names 6805 23517 23518 +11 1 +.names 23523 23524 23519 +1- 1 +-1 1 +.names 23519 23520 +1 1 +.names 22966 23521 +1 1 +.names 23521 23522 +0 1 +.names 6842 23522 23523 +1- 1 +-1 1 +.names 22570 23524 +0 1 +.names 6847 23528 23525 +1- 1 +-1 1 +.names 23525 23526 +1 1 +.names 2413 23527 +1 1 +.names 23527 23528 +0 1 +.names 23520 23529 +0 1 +.names 23526 23530 +0 1 +.names 23534 22874 23531 +1- 1 +-1 1 +.names 23531 23532 +1 1 +.names 46373 46376 56484 +1- 1 +-1 1 +.names 56484 23534 +0 1 +.names 22966 23537 23535 +1- 1 +-1 1 +.names 23535 23536 +1 1 +.names 1289 23537 +0 1 +.names 22791 23540 23538 +1- 1 +-1 1 +.names 23538 23539 +1 1 +.names 1290 23540 +0 1 +.names 23539 23536 23541 +11 1 +.names 22966 23544 23542 +1- 1 +-1 1 +.names 23542 23543 +1 1 +.names 1291 23544 +0 1 +.names 23558 23562 23545 +1- 1 +-1 1 +.names 23545 23546 +1 1 +.names 23546 23547 +0 1 +.names 2413 23548 +1 1 +.names 23548 23549 +1 1 +.names 23549 23550 +0 1 +.names 23547 23550 23551 +1- 1 +-1 1 +.names 23565 23567 23552 +11 1 +.names 23552 23553 +1 1 +.names 23553 23554 +0 1 +.names 23578 23579 23555 +11 1 +.names 23555 23556 +1 1 +.names 23556 23557 +0 1 +.names 22808 23557 23558 +11 1 +.names 45228 45232 23559 +1- 1 +-1 1 +.names 23559 23560 +1 1 +.names 23560 23561 +0 1 +.names 6807 23561 23562 +11 1 +.names 22936 23582 23563 +1- 1 +-1 1 +.names 23563 23564 +1 1 +.names 23543 23564 23565 +11 1 +.names 23581 22874 23566 +1- 1 +-1 1 +.names 23566 23567 +1 1 +.names 23572 23573 23568 +1- 1 +-1 1 +.names 23568 23569 +1 1 +.names 22966 23570 +1 1 +.names 23570 23571 +0 1 +.names 6842 23571 23572 +1- 1 +-1 1 +.names 22580 23573 +0 1 +.names 6845 23577 23574 +1- 1 +-1 1 +.names 23574 23575 +1 1 +.names 2413 23576 +1 1 +.names 23576 23577 +0 1 +.names 23569 23578 +0 1 +.names 23575 23579 +0 1 +.names 46380 46383 56492 +1- 1 +-1 1 +.names 56492 23581 +0 1 +.names 1292 23582 +0 1 +.names 23596 23600 23583 +1- 1 +-1 1 +.names 23583 23584 +1 1 +.names 23584 23585 +0 1 +.names 2413 23586 +1 1 +.names 23586 23587 +1 1 +.names 23587 23588 +0 1 +.names 23585 23588 23589 +1- 1 +-1 1 +.names 23605 23607 23590 +11 1 +.names 23590 23591 +1 1 +.names 23591 23592 +0 1 +.names 23618 23619 23593 +11 1 +.names 23593 23594 +1 1 +.names 23594 23595 +0 1 +.names 22853 23595 23596 +11 1 +.names 45237 45241 23597 +1- 1 +-1 1 +.names 23597 23598 +1 1 +.names 23598 23599 +0 1 +.names 6843 23599 23600 +11 1 +.names 22966 23623 23601 +1- 1 +-1 1 +.names 23601 23602 +1 1 +.names 22936 23622 23603 +1- 1 +-1 1 +.names 23603 23604 +1 1 +.names 23602 23604 23605 +11 1 +.names 23621 23063 23606 +1- 1 +-1 1 +.names 23606 23607 +1 1 +.names 23612 23613 23608 +1- 1 +-1 1 +.names 23608 23609 +1 1 +.names 22966 23610 +1 1 +.names 23610 23611 +0 1 +.names 6841 23611 23612 +1- 1 +-1 1 +.names 22590 23613 +0 1 +.names 6845 23617 23614 +1- 1 +-1 1 +.names 23614 23615 +1 1 +.names 2413 23616 +1 1 +.names 23616 23617 +0 1 +.names 23609 23618 +0 1 +.names 23615 23619 +0 1 +.names 46388 46391 56482 +1- 1 +-1 1 +.names 56482 23621 +0 1 +.names 1293 23622 +0 1 +.names 1294 23623 +0 1 +.names 22966 23626 23624 +1- 1 +-1 1 +.names 23624 23625 +1 1 +.names 1295 23626 +0 1 +.names 23632 23636 23627 +1- 1 +-1 1 +.names 23627 23628 +1 1 +.names 23647 23648 23629 +11 1 +.names 23629 23630 +1 1 +.names 23630 23631 +0 1 +.names 22853 23631 23632 +11 1 +.names 45245 45249 23633 +1- 1 +-1 1 +.names 23633 23634 +1 1 +.names 23634 23635 +0 1 +.names 6843 23635 23636 +11 1 +.names 23641 23642 23637 +1- 1 +-1 1 +.names 23637 23638 +1 1 +.names 22966 23639 +1 1 +.names 23639 23640 +0 1 +.names 6822 23640 23641 +1- 1 +-1 1 +.names 22601 23642 +0 1 +.names 6845 23646 23643 +1- 1 +-1 1 +.names 23643 23644 +1 1 +.names 2413 23645 +1 1 +.names 23645 23646 +0 1 +.names 23638 23647 +0 1 +.names 23644 23648 +0 1 +.names 23652 22834 23649 +1- 1 +-1 1 +.names 23649 23650 +1 1 +.names 46395 46398 56474 +1- 1 +-1 1 +.names 56474 23652 +0 1 +.names 23659 23660 23653 +1- 1 +-1 1 +.names 23653 23654 +1 1 +.names 23625 23655 +0 1 +.names 22936 23669 23656 +1- 1 +-1 1 +.names 23656 23657 +1 1 +.names 23657 23658 +0 1 +.names 23655 23658 23659 +1- 1 +-1 1 +.names 23650 23660 +0 1 +.names 23628 23661 +0 1 +.names 23667 23668 23662 +11 1 +.names 23662 23663 +1 1 +.names 23663 23664 +0 1 +.names 1783 23665 +1 1 +.names 23665 23666 +1 1 +.names 23654 23667 +0 1 +.names 23666 23668 +0 1 +.names 1296 23669 +0 1 +.names 23683 23687 23670 +1- 1 +-1 1 +.names 23670 23671 +1 1 +.names 23671 23672 +0 1 +.names 2413 23673 +1 1 +.names 23673 23674 +1 1 +.names 23674 23675 +0 1 +.names 23672 23675 23676 +1- 1 +-1 1 +.names 23692 23694 23677 +11 1 +.names 23677 23678 +1 1 +.names 23678 23679 +0 1 +.names 23705 23706 23680 +11 1 +.names 23680 23681 +1 1 +.names 23681 23682 +0 1 +.names 22853 23682 23683 +11 1 +.names 45253 45257 23684 +1- 1 +-1 1 +.names 23684 23685 +1 1 +.names 23685 23686 +0 1 +.names 6843 23686 23687 +11 1 +.names 6825 23707 23688 +1- 1 +-1 1 +.names 23688 23689 +1 1 +.names 22712 23710 23690 +1- 1 +-1 1 +.names 23690 23691 +1 1 +.names 23689 23691 23692 +11 1 +.names 23709 23063 23693 +1- 1 +-1 1 +.names 23693 23694 +1 1 +.names 23699 23700 23695 +1- 1 +-1 1 +.names 23695 23696 +1 1 +.names 22712 23697 +1 1 +.names 23697 23698 +0 1 +.names 6841 23698 23699 +1- 1 +-1 1 +.names 22611 23700 +0 1 +.names 1783 23704 23701 +1- 1 +-1 1 +.names 23701 23702 +1 1 +.names 6825 23703 +1 1 +.names 23703 23704 +0 1 +.names 23696 23705 +0 1 +.names 23702 23706 +0 1 +.names 1297 23707 +0 1 +.names 46402 46405 56475 +1- 1 +-1 1 +.names 56475 23709 +0 1 +.names 1298 23710 +0 1 +.names 23713 22712 23711 +1- 1 +-1 1 +.names 23711 23712 +1 1 +.names 1299 23713 +0 1 +.names 23727 23731 23714 +1- 1 +-1 1 +.names 23714 23715 +1 1 +.names 23715 23716 +0 1 +.names 2413 23717 +1 1 +.names 23717 23718 +1 1 +.names 23718 23719 +0 1 +.names 23716 23719 23720 +1- 1 +-1 1 +.names 23734 23737 23721 +11 1 +.names 23721 23722 +1 1 +.names 23722 23723 +0 1 +.names 23748 23749 23724 +11 1 +.names 23724 23725 +1 1 +.names 23725 23726 +0 1 +.names 22808 23726 23727 +11 1 +.names 45261 45265 23728 +1- 1 +-1 1 +.names 23728 23729 +1 1 +.names 23729 23730 +0 1 +.names 6807 23730 23731 +11 1 +.names 23753 23732 +0 1 +.names 23732 23733 +1 1 +.names 23733 23734 +0 1 +.names 23750 23751 23735 +1- 1 +-1 1 +.names 23735 23736 +1 1 +.names 23736 23737 +0 1 +.names 23742 23743 23738 +1- 1 +-1 1 +.names 23738 23739 +1 1 +.names 22712 23740 +1 1 +.names 23740 23741 +0 1 +.names 6842 23741 23742 +1- 1 +-1 1 +.names 22621 23743 +0 1 +.names 6838 23747 23744 +1- 1 +-1 1 +.names 23744 23745 +1 1 +.names 2413 23746 +1 1 +.names 23746 23747 +0 1 +.names 23739 23748 +0 1 +.names 23745 23749 +0 1 +.names 6838 1300 23750 +11 1 +.names 23712 23751 +0 1 +.names 23755 22874 23752 +1- 1 +-1 1 +.names 23752 23753 +1 1 +.names 46409 46412 56489 +1- 1 +-1 1 +.names 56489 23755 +0 1 +.names 22966 23758 23756 +1- 1 +-1 1 +.names 23756 23757 +1 1 +.names 1301 23758 +0 1 +.names 23764 23768 23759 +1- 1 +-1 1 +.names 23759 23760 +1 1 +.names 23779 23780 23761 +11 1 +.names 23761 23762 +1 1 +.names 23762 23763 +0 1 +.names 22808 23763 23764 +11 1 +.names 45269 45273 23765 +1- 1 +-1 1 +.names 23765 23766 +1 1 +.names 23766 23767 +0 1 +.names 6807 23767 23768 +11 1 +.names 23773 23774 23769 +1- 1 +-1 1 +.names 23769 23770 +1 1 +.names 22966 23771 +1 1 +.names 23771 23772 +0 1 +.names 6822 23772 23773 +1- 1 +-1 1 +.names 22631 23774 +0 1 +.names 6845 23778 23775 +1- 1 +-1 1 +.names 23775 23776 +1 1 +.names 2413 23777 +1 1 +.names 23777 23778 +0 1 +.names 23770 23779 +0 1 +.names 23776 23780 +0 1 +.names 23784 22834 23781 +1- 1 +-1 1 +.names 23781 23782 +1 1 +.names 46416 46419 56473 +1- 1 +-1 1 +.names 56473 23784 +0 1 +.names 23791 23792 23785 +1- 1 +-1 1 +.names 23785 23786 +1 1 +.names 23757 23787 +0 1 +.names 22936 23801 23788 +1- 1 +-1 1 +.names 23788 23789 +1 1 +.names 23789 23790 +0 1 +.names 23787 23790 23791 +1- 1 +-1 1 +.names 23782 23792 +0 1 +.names 23760 23793 +0 1 +.names 23799 23800 23794 +11 1 +.names 23794 23795 +1 1 +.names 23795 23796 +0 1 +.names 1783 23797 +1 1 +.names 23797 23798 +1 1 +.names 23786 23799 +0 1 +.names 23798 23800 +0 1 +.names 1302 23801 +0 1 +.names 23815 23819 23802 +1- 1 +-1 1 +.names 23802 23803 +1 1 +.names 23803 23804 +0 1 +.names 2413 23805 +1 1 +.names 23805 23806 +1 1 +.names 23806 23807 +0 1 +.names 23804 23807 23808 +1- 1 +-1 1 +.names 23822 23825 23809 +11 1 +.names 23809 23810 +1 1 +.names 23810 23811 +0 1 +.names 23832 23833 23812 +11 1 +.names 23812 23813 +1 1 +.names 23813 23814 +0 1 +.names 22808 23814 23815 +11 1 +.names 45277 45281 23816 +1- 1 +-1 1 +.names 23816 23817 +1 1 +.names 23817 23818 +0 1 +.names 6807 23818 23819 +11 1 +.names 6846 1303 23820 +11 1 +.names 23820 23821 +1 1 +.names 23821 23822 +0 1 +.names 23839 23840 23823 +1- 1 +-1 1 +.names 23823 23824 +1 1 +.names 23824 23825 +0 1 +.names 6819 23829 23826 +1- 1 +-1 1 +.names 23826 23827 +1 1 +.names 2413 23828 +1 1 +.names 23828 23829 +0 1 +.names 23844 23845 23830 +1- 1 +-1 1 +.names 23830 23831 +1 1 +.names 23831 23832 +0 1 +.names 23827 23833 +0 1 +.names 23837 6833 23834 +1- 1 +-1 1 +.names 23834 23835 +1 1 +.names 46423 46426 56487 +1- 1 +-1 1 +.names 56487 23837 +0 1 +.names 22760 23838 +1 1 +.names 6837 1304 23839 +11 1 +.names 23835 23840 +0 1 +.names 22885 23841 +1 1 +.names 23841 23842 +0 1 +.names 23838 23843 +0 1 +.names 23842 23843 23844 +1- 1 +-1 1 +.names 22641 23845 +0 1 +.names 22966 23848 23846 +1- 1 +-1 1 +.names 23846 23847 +1 1 +.names 1305 23848 +0 1 +.names 23862 23866 23849 +1- 1 +-1 1 +.names 23849 23850 +1 1 +.names 23850 23851 +0 1 +.names 2413 23852 +1 1 +.names 23852 23853 +1 1 +.names 23853 23854 +0 1 +.names 23851 23854 23855 +1- 1 +-1 1 +.names 23886 23880 23856 +11 1 +.names 23856 23857 +1 1 +.names 23857 23858 +0 1 +.names 23877 23878 23859 +11 1 +.names 23859 23860 +1 1 +.names 23860 23861 +0 1 +.names 22991 23861 23862 +11 1 +.names 45285 45289 23863 +1- 1 +-1 1 +.names 23863 23864 +1 1 +.names 23864 23865 +0 1 +.names 6805 23865 23866 +11 1 +.names 23871 23872 23867 +1- 1 +-1 1 +.names 23867 23868 +1 1 +.names 22966 23869 +1 1 +.names 23869 23870 +0 1 +.names 6842 23870 23871 +1- 1 +-1 1 +.names 22651 23872 +0 1 +.names 6847 23876 23873 +1- 1 +-1 1 +.names 23873 23874 +1 1 +.names 2413 23875 +1 1 +.names 23875 23876 +0 1 +.names 23868 23877 +0 1 +.names 23874 23878 +0 1 +.names 23882 22874 23879 +1- 1 +-1 1 +.names 23879 23880 +1 1 +.names 46430 46433 56488 +1- 1 +-1 1 +.names 56488 23882 +0 1 +.names 22791 23885 23883 +1- 1 +-1 1 +.names 23883 23884 +1 1 +.names 1306 23885 +0 1 +.names 23884 23847 23886 +11 1 +.names 22883 23889 23887 +1- 1 +-1 1 +.names 23887 23888 +1 1 +.names 1307 23889 +0 1 +.names 23895 23899 23890 +1- 1 +-1 1 +.names 23890 23891 +1 1 +.names 23906 23907 23892 +11 1 +.names 23892 23893 +1 1 +.names 23893 23894 +0 1 +.names 22853 23894 23895 +11 1 +.names 45293 45297 23896 +1- 1 +-1 1 +.names 23896 23897 +1 1 +.names 23897 23898 +0 1 +.names 6843 23898 23899 +11 1 +.names 6846 23903 23900 +1- 1 +-1 1 +.names 23900 23901 +1 1 +.names 2413 23902 +1 1 +.names 23902 23903 +0 1 +.names 23914 23915 23904 +1- 1 +-1 1 +.names 23904 23905 +1 1 +.names 23905 23906 +0 1 +.names 23901 23907 +0 1 +.names 23911 22834 23908 +1- 1 +-1 1 +.names 23908 23909 +1 1 +.names 46437 46440 56464 +1- 1 +-1 1 +.names 56464 23911 +0 1 +.names 22883 23912 +1 1 +.names 23912 23913 +0 1 +.names 6822 23913 23914 +1- 1 +-1 1 +.names 22661 23915 +0 1 +.names 23922 23923 23916 +1- 1 +-1 1 +.names 23916 23917 +1 1 +.names 23888 23918 +0 1 +.names 22885 23932 23919 +1- 1 +-1 1 +.names 23919 23920 +1 1 +.names 23920 23921 +0 1 +.names 23918 23921 23922 +1- 1 +-1 1 +.names 23909 23923 +0 1 +.names 23891 23924 +0 1 +.names 23930 23931 23925 +11 1 +.names 23925 23926 +1 1 +.names 23926 23927 +0 1 +.names 1783 23928 +1 1 +.names 23928 23929 +1 1 +.names 23917 23930 +0 1 +.names 23929 23931 +0 1 +.names 1308 23932 +0 1 +.names 23946 23948 23933 +1- 1 +-1 1 +.names 23933 23934 +1 1 +.names 23934 23935 +0 1 +.names 23972 6833 23936 +1- 1 +-1 1 +.names 23936 23937 +1 1 +.names 23937 23938 +0 1 +.names 23935 23938 23939 +1- 1 +-1 1 +.names 23951 23954 23940 +11 1 +.names 23940 23941 +1 1 +.names 23941 23942 +0 1 +.names 23969 23970 23943 +11 1 +.names 23943 23944 +1 1 +.names 23944 23945 +0 1 +.names 23275 23945 23946 +11 1 +.names 1309 23947 +0 1 +.names 6824 23947 23948 +11 1 +.names 23974 6836 23949 +11 1 +.names 23949 23950 +1 1 +.names 23950 23951 +0 1 +.names 23955 23958 23952 +1- 1 +-1 1 +.names 23952 23953 +1 1 +.names 23953 23954 +0 1 +.names 6816 1310 23955 +11 1 +.names 2413 23956 +1 1 +.names 23956 23957 +1 1 +.names 23957 23958 +0 1 +.names 23963 23964 23959 +1- 1 +-1 1 +.names 23959 23960 +1 1 +.names 2413 23961 +1 1 +.names 23961 23962 +0 1 +.names 6836 23962 23963 +1- 1 +-1 1 +.names 22671 23964 +0 1 +.names 6819 23968 23965 +1- 1 +-1 1 +.names 23965 23966 +1 1 +.names 22883 23967 +1 1 +.names 23967 23968 +0 1 +.names 23960 23969 +0 1 +.names 23966 23970 +0 1 +.names 46444 46447 56465 +1- 1 +-1 1 +.names 56465 23972 +0 1 +.names 45301 45305 23973 +1- 1 +-1 1 +.names 23973 23974 +1 1 +.names 23988 23992 23975 +1- 1 +-1 1 +.names 23975 23976 +1 1 +.names 23976 23977 +0 1 +.names 2413 23978 +1 1 +.names 23978 23979 +1 1 +.names 23979 23980 +0 1 +.names 23977 23980 23981 +1- 1 +-1 1 +.names 24015 24006 23982 +11 1 +.names 23982 23983 +1 1 +.names 23983 23984 +0 1 +.names 24003 24004 23985 +11 1 +.names 23985 23986 +1 1 +.names 23986 23987 +0 1 +.names 22853 23987 23988 +11 1 +.names 45309 45313 23989 +1- 1 +-1 1 +.names 23989 23990 +1 1 +.names 23990 23991 +0 1 +.names 6843 23991 23992 +11 1 +.names 23997 23998 23993 +1- 1 +-1 1 +.names 23993 23994 +1 1 +.names 22760 23995 +1 1 +.names 23995 23996 +0 1 +.names 6842 23996 23997 +1- 1 +-1 1 +.names 22681 23998 +0 1 +.names 6847 24002 23999 +1- 1 +-1 1 +.names 23999 24000 +1 1 +.names 2413 24001 +1 1 +.names 24001 24002 +0 1 +.names 23994 24003 +0 1 +.names 24000 24004 +0 1 +.names 24008 22874 24005 +1- 1 +-1 1 +.names 24005 24006 +1 1 +.names 46451 46454 56476 +1- 1 +-1 1 +.names 56476 24008 +0 1 +.names 22760 24011 24009 +1- 1 +-1 1 +.names 24009 24010 +1 1 +.names 1311 24011 +0 1 +.names 22791 24014 24012 +1- 1 +-1 1 +.names 24012 24013 +1 1 +.names 1312 24014 +0 1 +.names 24013 24010 24015 +11 1 +.names 22712 24018 24016 +1- 1 +-1 1 +.names 24016 24017 +1 1 +.names 1313 24018 +0 1 +.names 24022 6833 24019 +1- 1 +-1 1 +.names 24019 24020 +1 1 +.names 46458 46461 56481 +1- 1 +-1 1 +.names 56481 24022 +0 1 +.names 24027 24028 24023 +1- 1 +-1 1 +.names 24023 24024 +1 1 +.names 22712 24025 +1 1 +.names 24025 24026 +0 1 +.names 6819 24026 24027 +1- 1 +-1 1 +.names 22691 24028 +0 1 +.names 6847 24032 24029 +1- 1 +-1 1 +.names 24029 24030 +1 1 +.names 2413 24031 +1 1 +.names 24031 24032 +0 1 +.names 24038 24042 24033 +1- 1 +-1 1 +.names 24033 24034 +1 1 +.names 24043 24044 24035 +11 1 +.names 24035 24036 +1 1 +.names 24036 24037 +0 1 +.names 22853 24037 24038 +11 1 +.names 45317 45321 24039 +1- 1 +-1 1 +.names 24039 24040 +1 1 +.names 24040 24041 +0 1 +.names 6843 24041 24042 +11 1 +.names 24024 24043 +0 1 +.names 24030 24044 +0 1 +.names 24051 24052 24045 +1- 1 +-1 1 +.names 24045 24046 +1 1 +.names 22791 24061 24047 +1- 1 +-1 1 +.names 24047 24048 +1 1 +.names 24048 24049 +0 1 +.names 24017 24050 +0 1 +.names 24049 24050 24051 +1- 1 +-1 1 +.names 24020 24052 +0 1 +.names 24055 24058 24053 +11 1 +.names 24053 24054 +1 1 +.names 24046 24055 +0 1 +.names 1783 24056 +1 1 +.names 24056 24057 +1 1 +.names 24057 24058 +0 1 +.names 24034 24059 +0 1 +.names 24054 24060 +0 1 +.names 1314 24061 +0 1 +.names 24075 24079 24062 +1- 1 +-1 1 +.names 24062 24063 +1 1 +.names 24063 24064 +0 1 +.names 2413 24065 +1 1 +.names 24065 24066 +1 1 +.names 24066 24067 +0 1 +.names 24064 24067 24068 +1- 1 +-1 1 +.names 24082 24085 24069 +11 1 +.names 24069 24070 +1 1 +.names 24070 24071 +0 1 +.names 24092 24093 24072 +11 1 +.names 24072 24073 +1 1 +.names 24073 24074 +0 1 +.names 22853 24074 24075 +11 1 +.names 45325 45329 24076 +1- 1 +-1 1 +.names 24076 24077 +1 1 +.names 24077 24078 +0 1 +.names 6843 24078 24079 +11 1 +.names 6845 1315 24080 +11 1 +.names 24080 24081 +1 1 +.names 24081 24082 +0 1 +.names 24102 24103 24083 +1- 1 +-1 1 +.names 24083 24084 +1 1 +.names 24084 24085 +0 1 +.names 6842 24089 24086 +1- 1 +-1 1 +.names 24086 24087 +1 1 +.names 2413 24088 +1 1 +.names 24088 24089 +0 1 +.names 24100 24101 24090 +1- 1 +-1 1 +.names 24090 24091 +1 1 +.names 24091 24092 +0 1 +.names 24087 24093 +0 1 +.names 24097 22874 24094 +1- 1 +-1 1 +.names 24094 24095 +1 1 +.names 46465 46468 56490 +1- 1 +-1 1 +.names 56490 24097 +0 1 +.names 22760 24098 +1 1 +.names 24098 24099 +0 1 +.names 6845 24099 24100 +1- 1 +-1 1 +.names 22701 24101 +0 1 +.names 6837 1316 24102 +11 1 +.names 24095 24103 +0 1 +.names 24106 24107 24104 +1- 1 +-1 1 +.names 24104 24105 +1 1 +.names 7134 24106 +0 1 +.names 1317 24107 +0 1 +.names 22718 24110 24108 +1- 1 +-1 1 +.names 24108 24109 +1 1 +.names 7155 24110 +0 1 +.names 24122 24123 24111 +1- 1 +-1 1 +.names 24111 24112 +1 1 +.names 24112 24113 +0 1 +.names 24109 24114 +0 1 +.names 24113 24114 24115 +1- 1 +-1 1 +.names 24126 24128 24116 +11 1 +.names 24116 24117 +1 1 +.names 24117 24118 +0 1 +.names 24139 24140 24119 +11 1 +.names 24119 24120 +1 1 +.names 24120 24121 +0 1 +.names 2413 24121 24122 +11 1 +.names 1783 2413 24123 +11 1 +.names 7144 22750 24124 +1- 1 +-1 1 +.names 24124 24125 +1 1 +.names 24125 24105 24126 +11 1 +.names 7152 22752 24127 +1- 1 +-1 1 +.names 24127 24128 +1 1 +.names 24133 24134 24129 +1- 1 +-1 1 +.names 24129 24130 +1 1 +.names 24106 24131 +1 1 +.names 24131 24132 +0 1 +.names 7155 24132 24133 +1- 1 +-1 1 +.names 672 24134 +0 1 +.names 7157 24138 24135 +1- 1 +-1 1 +.names 24135 24136 +1 1 +.names 7152 24137 +1 1 +.names 24137 24138 +0 1 +.names 24130 24139 +0 1 +.names 24136 24140 +0 1 +.names 22757 24110 24141 +1- 1 +-1 1 +.names 24141 24142 +1 1 +.names 24149 24151 24143 +1- 1 +-1 1 +.names 24143 24144 +1 1 +.names 7156 24145 +0 1 +.names 24162 24163 24146 +11 1 +.names 24146 24147 +1 1 +.names 24147 24148 +0 1 +.names 24145 24148 24149 +11 1 +.names 1318 24150 +0 1 +.names 7156 24150 24151 +11 1 +.names 24156 24157 24152 +1- 1 +-1 1 +.names 24152 24153 +1 1 +.names 7152 24154 +1 1 +.names 24154 24155 +0 1 +.names 7166 24155 24156 +1- 1 +-1 1 +.names 656 24157 +0 1 +.names 7155 24161 24158 +1- 1 +-1 1 +.names 24158 24159 +1 1 +.names 2413 24160 +1 1 +.names 24160 24161 +0 1 +.names 24153 24162 +0 1 +.names 24159 24163 +0 1 +.names 24178 24179 24164 +1- 1 +-1 1 +.names 24164 24165 +1 1 +.names 24144 24166 +0 1 +.names 7152 22785 24167 +1- 1 +-1 1 +.names 24167 24168 +1 1 +.names 2413 24169 +1 1 +.names 24169 24170 +1 1 +.names 22790 24173 24171 +1- 1 +-1 1 +.names 24171 24172 +1 1 +.names 7166 24173 +0 1 +.names 24170 24174 +0 1 +.names 24172 24175 +0 1 +.names 24174 24175 24176 +1- 1 +-1 1 +.names 24168 24177 +0 1 +.names 24176 24177 24178 +1- 1 +-1 1 +.names 24142 24179 +0 1 +.names 24194 24195 24180 +1- 1 +-1 1 +.names 24180 24181 +1 1 +.names 24181 24182 +0 1 +.names 2413 24183 +1 1 +.names 24183 24184 +1 1 +.names 24184 24185 +0 1 +.names 24182 24185 24186 +1- 1 +-1 1 +.names 24200 24202 24187 +11 1 +.names 24187 24188 +1 1 +.names 24188 24189 +0 1 +.names 7126 24190 +0 1 +.names 24209 24210 24191 +11 1 +.names 24191 24192 +1 1 +.names 24192 24193 +0 1 +.names 24190 24193 24194 +11 1 +.names 7126 22815 24195 +11 1 +.names 24145 24218 24196 +1- 1 +-1 1 +.names 24196 24197 +1 1 +.names 7144 22842 24198 +1- 1 +-1 1 +.names 24198 24199 +1 1 +.names 24197 24199 24200 +11 1 +.names 22833 24211 24201 +1- 1 +-1 1 +.names 24201 24202 +1 1 +.names 7157 24206 24203 +1- 1 +-1 1 +.names 24203 24204 +1 1 +.names 2413 24205 +1 1 +.names 24205 24206 +0 1 +.names 24216 24217 24207 +1- 1 +-1 1 +.names 24207 24208 +1 1 +.names 24208 24209 +0 1 +.names 24204 24210 +0 1 +.names 7141 24211 +0 1 +.names 24211 24212 +1 1 +.names 24212 24213 +0 1 +.names 24145 24214 +1 1 +.names 24214 24215 +0 1 +.names 24213 24215 24216 +1- 1 +-1 1 +.names 651 24217 +0 1 +.names 1319 24218 +0 1 +.names 24233 24234 24219 +1- 1 +-1 1 +.names 24219 24220 +1 1 +.names 24220 24221 +0 1 +.names 2413 24222 +1 1 +.names 24222 24223 +1 1 +.names 24223 24224 +0 1 +.names 24221 24224 24225 +1- 1 +-1 1 +.names 24252 24253 24226 +11 1 +.names 24226 24227 +1 1 +.names 24227 24228 +0 1 +.names 7162 24229 +0 1 +.names 24241 24242 24230 +11 1 +.names 24230 24231 +1 1 +.names 24231 24232 +0 1 +.names 24229 24232 24233 +11 1 +.names 7162 22860 24234 +11 1 +.names 7161 24238 24235 +1- 1 +-1 1 +.names 24235 24236 +1 1 +.names 2413 24237 +1 1 +.names 24237 24238 +0 1 +.names 24260 24261 24239 +1- 1 +-1 1 +.names 24239 24240 +1 1 +.names 24240 24241 +0 1 +.names 24236 24242 +0 1 +.names 22873 24245 24243 +1- 1 +-1 1 +.names 24243 24244 +1 1 +.names 7161 24245 +0 1 +.names 24248 24249 24246 +1- 1 +-1 1 +.names 24246 24247 +1 1 +.names 1320 7135 24248 +11 1 +.names 24244 24249 +0 1 +.names 7165 1262 24250 +11 1 +.names 24250 24251 +1 1 +.names 24251 24252 +0 1 +.names 24247 24253 +0 1 +.names 7135 24254 +0 1 +.names 24254 24255 +1 1 +.names 7165 24256 +0 1 +.names 24256 24257 +1 1 +.names 24257 24258 +0 1 +.names 24255 24259 +0 1 +.names 24258 24259 24260 +1- 1 +-1 1 +.names 658 24261 +0 1 +.names 24254 24264 24262 +1- 1 +-1 1 +.names 24262 24263 +1 1 +.names 1321 24264 +0 1 +.names 22897 7152 24265 +1- 1 +-1 1 +.names 24265 24266 +1 1 +.names 7164 24270 24267 +1- 1 +-1 1 +.names 24267 24268 +1 1 +.names 2413 24269 +1 1 +.names 24269 24270 +0 1 +.names 24276 24277 24271 +1- 1 +-1 1 +.names 24271 24272 +1 1 +.names 24280 24281 24273 +11 1 +.names 24273 24274 +1 1 +.names 24274 24275 +0 1 +.names 24229 24275 24276 +11 1 +.names 7162 22910 24277 +11 1 +.names 24284 24285 24278 +1- 1 +-1 1 +.names 24278 24279 +1 1 +.names 24279 24280 +0 1 +.names 24268 24281 +0 1 +.names 24254 24282 +1 1 +.names 24282 24283 +0 1 +.names 7138 24283 24284 +1- 1 +-1 1 +.names 660 24285 +0 1 +.names 24292 24293 24286 +1- 1 +-1 1 +.names 24286 24287 +1 1 +.names 24263 24288 +0 1 +.names 24302 22937 24289 +1- 1 +-1 1 +.names 24289 24290 +1 1 +.names 24290 24291 +0 1 +.names 24288 24291 24292 +1- 1 +-1 1 +.names 24266 24293 +0 1 +.names 24296 24299 24294 +11 1 +.names 24294 24295 +1 1 +.names 24287 24296 +0 1 +.names 1783 24297 +1 1 +.names 24297 24298 +1 1 +.names 24298 24299 +0 1 +.names 24272 24300 +0 1 +.names 24295 24301 +0 1 +.names 7164 24302 +0 1 +.names 24317 24318 24303 +1- 1 +-1 1 +.names 24303 24304 +1 1 +.names 24304 24305 +0 1 +.names 2413 24306 +1 1 +.names 24306 24307 +1 1 +.names 24307 24308 +0 1 +.names 24305 24308 24309 +1- 1 +-1 1 +.names 24339 24336 24310 +11 1 +.names 24310 24311 +1 1 +.names 24311 24312 +0 1 +.names 7151 24313 +0 1 +.names 24330 24331 24314 +11 1 +.names 24314 24315 +1 1 +.names 24315 24316 +0 1 +.names 24313 24316 24317 +11 1 +.names 7151 22954 24318 +11 1 +.names 7155 24321 24319 +1- 1 +-1 1 +.names 24319 24320 +1 1 +.names 667 24321 +0 1 +.names 24326 24328 24322 +1- 1 +-1 1 +.names 24322 24323 +1 1 +.names 24329 2413 24324 +11 1 +.names 24324 24325 +1 1 +.names 24325 24326 +0 1 +.names 24173 24327 +1 1 +.names 24327 24328 +0 1 +.names 7136 24329 +0 1 +.names 24323 24330 +0 1 +.names 24320 24331 +0 1 +.names 24329 24334 24332 +1- 1 +-1 1 +.names 24332 24333 +1 1 +.names 1322 24334 +0 1 +.names 22976 24110 24335 +1- 1 +-1 1 +.names 24335 24336 +1 1 +.names 24173 22979 24337 +1- 1 +-1 1 +.names 24337 24338 +1 1 +.names 24338 24333 24339 +11 1 +.names 24354 24355 24340 +1- 1 +-1 1 +.names 24340 24341 +1 1 +.names 24341 24342 +0 1 +.names 2413 24343 +1 1 +.names 24343 24344 +1 1 +.names 24344 24345 +0 1 +.names 24342 24345 24346 +1- 1 +-1 1 +.names 24376 24377 24347 +11 1 +.names 24347 24348 +1 1 +.names 24348 24349 +0 1 +.names 7124 24350 +0 1 +.names 24372 24373 24351 +11 1 +.names 24351 24352 +1 1 +.names 24352 24353 +0 1 +.names 24350 24353 24354 +11 1 +.names 7124 22998 24355 +11 1 +.names 24358 24361 24356 +1- 1 +-1 1 +.names 24356 24357 +1 1 +.names 7134 1323 24358 +11 1 +.names 23023 24256 24359 +1- 1 +-1 1 +.names 24359 24360 +1 1 +.names 24360 24361 +0 1 +.names 24366 24367 24362 +1- 1 +-1 1 +.names 24362 24363 +1 1 +.names 24106 24364 +1 1 +.names 24364 24365 +0 1 +.names 7160 24365 24366 +1- 1 +-1 1 +.names 680 24367 +0 1 +.names 7165 24371 24368 +1- 1 +-1 1 +.names 24368 24369 +1 1 +.names 2413 24370 +1 1 +.names 24370 24371 +0 1 +.names 24363 24372 +0 1 +.names 24369 24373 +0 1 +.names 56491 7160 24374 +11 1 +.names 24374 24375 +1 1 +.names 24375 24376 +0 1 +.names 24357 24377 +0 1 +.names 24391 24392 24378 +1- 1 +-1 1 +.names 24378 24379 +1 1 +.names 24379 24380 +0 1 +.names 2413 24381 +1 1 +.names 24381 24382 +1 1 +.names 24382 24383 +0 1 +.names 24380 24383 24384 +1- 1 +-1 1 +.names 24397 24399 24385 +11 1 +.names 24385 24386 +1 1 +.names 24386 24387 +0 1 +.names 24410 24411 24388 +11 1 +.names 24388 24389 +1 1 +.names 24389 24390 +0 1 +.names 24229 24390 24391 +11 1 +.names 7162 23040 24392 +11 1 +.names 24145 24413 24393 +1- 1 +-1 1 +.names 24393 24394 +1 1 +.names 7144 23065 24395 +1- 1 +-1 1 +.names 24395 24396 +1 1 +.names 24394 24396 24397 +11 1 +.names 23062 24412 24398 +1- 1 +-1 1 +.names 24398 24399 +1 1 +.names 24404 24405 24400 +1- 1 +-1 1 +.names 24400 24401 +1 1 +.names 24145 24402 +1 1 +.names 24402 24403 +0 1 +.names 7160 24403 24404 +1- 1 +-1 1 +.names 669 24405 +0 1 +.names 7157 24409 24406 +1- 1 +-1 1 +.names 24406 24407 +1 1 +.names 2413 24408 +1 1 +.names 24408 24409 +0 1 +.names 24407 24410 +0 1 +.names 24401 24411 +0 1 +.names 7160 24412 +0 1 +.names 1324 24413 +0 1 +.names 24419 24420 24414 +1- 1 +-1 1 +.names 24414 24415 +1 1 +.names 24427 24428 24416 +11 1 +.names 24416 24417 +1 1 +.names 24417 24418 +0 1 +.names 24229 24418 24419 +11 1 +.names 7162 23074 24420 +11 1 +.names 1783 24424 24421 +1- 1 +-1 1 +.names 24421 24422 +1 1 +.names 24256 24423 +1 1 +.names 24423 24424 +0 1 +.names 24433 24434 24425 +1- 1 +-1 1 +.names 24425 24426 +1 1 +.names 24426 24427 +0 1 +.names 24422 24428 +0 1 +.names 23087 24211 24429 +1- 1 +-1 1 +.names 24429 24430 +1 1 +.names 24145 24431 +1 1 +.names 24431 24432 +0 1 +.names 7141 24432 24433 +1- 1 +-1 1 +.names 659 24434 +0 1 +.names 24443 24444 24435 +1- 1 +-1 1 +.names 24435 24436 +1 1 +.names 24145 24453 24437 +1- 1 +-1 1 +.names 24437 24438 +1 1 +.names 24438 24439 +0 1 +.names 24256 23111 24440 +1- 1 +-1 1 +.names 24440 24441 +1 1 +.names 24441 24442 +0 1 +.names 24439 24442 24443 +1- 1 +-1 1 +.names 24430 24444 +0 1 +.names 24415 24445 +0 1 +.names 24451 24452 24446 +11 1 +.names 24446 24447 +1 1 +.names 24447 24448 +0 1 +.names 1783 24449 +1 1 +.names 24449 24450 +1 1 +.names 24436 24451 +0 1 +.names 24450 24452 +0 1 +.names 1325 24453 +0 1 +.names 24467 24468 24454 +1- 1 +-1 1 +.names 24454 24455 +1 1 +.names 24455 24456 +0 1 +.names 2413 24457 +1 1 +.names 24457 24458 +1 1 +.names 24458 24459 +0 1 +.names 24456 24459 24460 +1- 1 +-1 1 +.names 24488 24482 24461 +11 1 +.names 24461 24462 +1 1 +.names 24462 24463 +0 1 +.names 24479 24480 24464 +11 1 +.names 24464 24465 +1 1 +.names 24465 24466 +0 1 +.names 24229 24466 24467 +11 1 +.names 7162 23128 24468 +11 1 +.names 24473 24474 24469 +1- 1 +-1 1 +.names 24469 24470 +1 1 +.names 24106 24471 +1 1 +.names 24471 24472 +0 1 +.names 7160 24472 24473 +1- 1 +-1 1 +.names 675 24474 +0 1 +.names 7166 24478 24475 +1- 1 +-1 1 +.names 24475 24476 +1 1 +.names 2413 24477 +1 1 +.names 24477 24478 +0 1 +.names 24470 24479 +0 1 +.names 24476 24480 +0 1 +.names 23145 24412 24481 +1- 1 +-1 1 +.names 24481 24482 +1 1 +.names 24106 24485 24483 +1- 1 +-1 1 +.names 24483 24484 +1 1 +.names 1326 24485 +0 1 +.names 24173 23151 24486 +1- 1 +-1 1 +.names 24486 24487 +1 1 +.names 24487 24484 24488 +11 1 +.names 24502 24503 24489 +1- 1 +-1 1 +.names 24489 24490 +1 1 +.names 24490 24491 +0 1 +.names 2413 24492 +1 1 +.names 24492 24493 +1 1 +.names 24493 24494 +0 1 +.names 24491 24494 24495 +1- 1 +-1 1 +.names 24508 24510 24496 +11 1 +.names 24496 24497 +1 1 +.names 24497 24498 +0 1 +.names 24521 24522 24499 +11 1 +.names 24499 24500 +1 1 +.names 24500 24501 +0 1 +.names 24350 24501 24502 +11 1 +.names 7124 23169 24503 +11 1 +.names 24106 24523 24504 +1- 1 +-1 1 +.names 24504 24505 +1 1 +.names 7144 23192 24506 +1- 1 +-1 1 +.names 24506 24507 +1 1 +.names 24505 24507 24508 +11 1 +.names 23191 7152 24509 +1- 1 +-1 1 +.names 24509 24510 +1 1 +.names 7138 24513 24511 +1- 1 +-1 1 +.names 24511 24512 +1 1 +.names 661 24513 +0 1 +.names 24518 24520 24514 +1- 1 +-1 1 +.names 24514 24515 +1 1 +.names 24106 2413 24516 +11 1 +.names 24516 24517 +1 1 +.names 24517 24518 +0 1 +.names 7144 24519 +1 1 +.names 24519 24520 +0 1 +.names 24515 24521 +0 1 +.names 24512 24522 +0 1 +.names 1327 24523 +0 1 +.names 24526 24106 24524 +1- 1 +-1 1 +.names 24524 24525 +1 1 +.names 1328 24526 +0 1 +.names 24540 24541 24527 +1- 1 +-1 1 +.names 24527 24528 +1 1 +.names 24528 24529 +0 1 +.names 2413 24530 +1 1 +.names 24530 24531 +1 1 +.names 24531 24532 +0 1 +.names 24529 24532 24533 +1- 1 +-1 1 +.names 24560 24561 24534 +11 1 +.names 24534 24535 +1 1 +.names 24535 24536 +0 1 +.names 24556 24557 24537 +11 1 +.names 24537 24538 +1 1 +.names 24538 24539 +0 1 +.names 24350 24539 24540 +11 1 +.names 7124 23213 24541 +11 1 +.names 24544 24545 24542 +1- 1 +-1 1 +.names 24542 24543 +1 1 +.names 7165 1278 24544 +11 1 +.names 24525 24545 +0 1 +.names 24550 24551 24546 +1- 1 +-1 1 +.names 24546 24547 +1 1 +.names 24106 24548 +1 1 +.names 24548 24549 +0 1 +.names 7160 24549 24550 +1- 1 +-1 1 +.names 674 24551 +0 1 +.names 7165 24555 24552 +1- 1 +-1 1 +.names 24552 24553 +1 1 +.names 2413 24554 +1 1 +.names 24554 24555 +0 1 +.names 24547 24556 +0 1 +.names 24553 24557 +0 1 +.names 56485 7160 24558 +11 1 +.names 24558 24559 +1 1 +.names 24559 24560 +0 1 +.names 24543 24561 +0 1 +.names 24575 24576 24562 +1- 1 +-1 1 +.names 24562 24563 +1 1 +.names 24563 24564 +0 1 +.names 2413 24565 +1 1 +.names 24565 24566 +1 1 +.names 24566 24567 +0 1 +.names 24564 24567 24568 +1- 1 +-1 1 +.names 24596 24597 24569 +11 1 +.names 24569 24570 +1 1 +.names 24570 24571 +0 1 +.names 24586 24587 24572 +11 1 +.names 24572 24573 +1 1 +.names 24573 24574 +0 1 +.names 24190 24574 24575 +11 1 +.names 7126 10763 24576 +11 1 +.names 24581 10861 24577 +1- 1 +-1 1 +.names 24577 24578 +1 1 +.names 24254 24579 +1 1 +.names 24579 24580 +0 1 +.names 7164 24580 24581 +1- 1 +-1 1 +.names 7138 24585 24582 +1- 1 +-1 1 +.names 24582 24583 +1 1 +.names 2413 24584 +1 1 +.names 24584 24585 +0 1 +.names 24578 24586 +0 1 +.names 24583 24587 +0 1 +.names 10786 7152 24588 +1- 1 +-1 1 +.names 24588 24589 +1 1 +.names 24592 24593 24590 +1- 1 +-1 1 +.names 24590 24591 +1 1 +.names 7135 970 24592 +11 1 +.names 24589 24593 +0 1 +.names 7164 966 24594 +11 1 +.names 24594 24595 +1 1 +.names 24595 24596 +0 1 +.names 24591 24597 +0 1 +.names 24604 24605 24598 +1- 1 +-1 1 +.names 24598 24599 +1 1 +.names 7143 24600 +0 1 +.names 24616 24617 24601 +11 1 +.names 24601 24602 +1 1 +.names 24602 24603 +0 1 +.names 24600 24603 24604 +11 1 +.names 7143 23280 24605 +11 1 +.names 7155 24608 24606 +1- 1 +-1 1 +.names 24606 24607 +1 1 +.names 668 24608 +0 1 +.names 24613 24615 24609 +1- 1 +-1 1 +.names 24609 24610 +1 1 +.names 24254 2413 24611 +11 1 +.names 24611 24612 +1 1 +.names 24612 24613 +0 1 +.names 7152 24614 +1 1 +.names 24614 24615 +0 1 +.names 24610 24616 +0 1 +.names 24607 24617 +0 1 +.names 24631 24634 24618 +1- 1 +-1 1 +.names 24618 24619 +1 1 +.names 24599 24620 +0 1 +.names 23300 7152 24621 +1- 1 +-1 1 +.names 24621 24622 +1 1 +.names 24622 24623 +0 1 +.names 23315 24110 24624 +1- 1 +-1 1 +.names 24624 24625 +1 1 +.names 24625 24626 +0 1 +.names 24623 24626 24627 +1- 1 +-1 1 +.names 24635 24254 24628 +1- 1 +-1 1 +.names 24628 24629 +1 1 +.names 24629 24630 +0 1 +.names 24627 24630 24631 +1- 1 +-1 1 +.names 2413 24632 +1 1 +.names 24632 24633 +1 1 +.names 24633 24634 +0 1 +.names 1329 24635 +0 1 +.names 24641 24642 24636 +1- 1 +-1 1 +.names 24636 24637 +1 1 +.names 24653 24654 24638 +11 1 +.names 24638 24639 +1 1 +.names 24639 24640 +0 1 +.names 24350 24640 24641 +11 1 +.names 7124 23325 24642 +11 1 +.names 24647 24648 24643 +1- 1 +-1 1 +.names 24643 24644 +1 1 +.names 24254 24645 +1 1 +.names 24645 24646 +0 1 +.names 7141 24646 24647 +1- 1 +-1 1 +.names 657 24648 +0 1 +.names 7157 24652 24649 +1- 1 +-1 1 +.names 24649 24650 +1 1 +.names 2413 24651 +1 1 +.names 24651 24652 +0 1 +.names 24644 24653 +0 1 +.names 24650 24654 +0 1 +.names 7144 23341 24655 +1- 1 +-1 1 +.names 24655 24656 +1 1 +.names 23345 24211 24657 +1- 1 +-1 1 +.names 24657 24658 +1 1 +.names 24665 24666 24659 +1- 1 +-1 1 +.names 24659 24660 +1 1 +.names 24656 24661 +0 1 +.names 24254 24675 24662 +1- 1 +-1 1 +.names 24662 24663 +1 1 +.names 24663 24664 +0 1 +.names 24661 24664 24665 +1- 1 +-1 1 +.names 24658 24666 +0 1 +.names 24637 24667 +0 1 +.names 24671 24674 24668 +11 1 +.names 24668 24669 +1 1 +.names 24669 24670 +0 1 +.names 24660 24671 +0 1 +.names 1783 24672 +1 1 +.names 24672 24673 +1 1 +.names 24673 24674 +0 1 +.names 1330 24675 +0 1 +.names 24689 24690 24676 +1- 1 +-1 1 +.names 24676 24677 +1 1 +.names 24677 24678 +0 1 +.names 2413 24679 +1 1 +.names 24679 24680 +1 1 +.names 24680 24681 +0 1 +.names 24678 24681 24682 +1- 1 +-1 1 +.names 24693 24696 24683 +11 1 +.names 24683 24684 +1 1 +.names 24684 24685 +0 1 +.names 24703 24704 24686 +11 1 +.names 24686 24687 +1 1 +.names 24687 24688 +0 1 +.names 24350 24688 24689 +11 1 +.names 7124 23379 24690 +11 1 +.names 24708 1283 24691 +11 1 +.names 24691 24692 +1 1 +.names 24692 24693 +0 1 +.names 24710 24711 24694 +1- 1 +-1 1 +.names 24694 24695 +1 1 +.names 24695 24696 +0 1 +.names 7138 24700 24697 +1- 1 +-1 1 +.names 24697 24698 +1 1 +.names 2413 24699 +1 1 +.names 24699 24700 +0 1 +.names 24714 24715 24701 +1- 1 +-1 1 +.names 24701 24702 +1 1 +.names 24702 24703 +0 1 +.names 24698 24704 +0 1 +.names 23398 7152 24705 +1- 1 +-1 1 +.names 24705 24706 +1 1 +.names 24712 24707 +0 1 +.names 24707 24708 +1 1 +.names 24329 24709 +1 1 +.names 7136 1331 24710 +11 1 +.names 24706 24711 +0 1 +.names 24173 24712 +1 1 +.names 24709 24713 +0 1 +.names 24707 24713 24714 +1- 1 +-1 1 +.names 652 24715 +0 1 +.names 24718 24145 24716 +1- 1 +-1 1 +.names 24716 24717 +1 1 +.names 1332 24718 +0 1 +.names 24732 24733 24719 +1- 1 +-1 1 +.names 24719 24720 +1 1 +.names 24720 24721 +0 1 +.names 2413 24722 +1 1 +.names 24722 24723 +1 1 +.names 24723 24724 +0 1 +.names 24721 24724 24725 +1- 1 +-1 1 +.names 24736 24739 24726 +11 1 +.names 24726 24727 +1 1 +.names 24727 24728 +0 1 +.names 24744 24747 24729 +11 1 +.names 24729 24730 +1 1 +.names 24730 24731 +0 1 +.names 24190 24731 24732 +11 1 +.names 7126 23427 24733 +11 1 +.names 24749 24734 +0 1 +.names 24734 24735 +1 1 +.names 24735 24736 +0 1 +.names 24756 24757 24737 +1- 1 +-1 1 +.names 24737 24738 +1 1 +.names 24738 24739 +0 1 +.names 7165 24743 24740 +1- 1 +-1 1 +.names 24740 24741 +1 1 +.names 2413 24742 +1 1 +.names 24742 24743 +0 1 +.names 24741 24744 +0 1 +.names 24754 24755 24745 +1- 1 +-1 1 +.names 24745 24746 +1 1 +.names 24746 24747 +0 1 +.names 23446 24211 24748 +1- 1 +-1 1 +.names 24748 24749 +1 1 +.names 24211 24750 +1 1 +.names 24750 24751 +0 1 +.names 24145 24752 +1 1 +.names 24752 24753 +0 1 +.names 24751 24753 24754 +1- 1 +-1 1 +.names 655 24755 +0 1 +.names 7165 1286 24756 +11 1 +.names 24717 24757 +0 1 +.names 24254 24760 24758 +1- 1 +-1 1 +.names 24758 24759 +1 1 +.names 1333 24760 +0 1 +.names 24766 24767 24761 +1- 1 +-1 1 +.names 24761 24762 +1 1 +.names 24778 24779 24763 +11 1 +.names 24763 24764 +1 1 +.names 24764 24765 +0 1 +.names 24229 24765 24766 +11 1 +.names 7162 23466 24767 +11 1 +.names 24772 24773 24768 +1- 1 +-1 1 +.names 24768 24769 +1 1 +.names 24254 24770 +1 1 +.names 24770 24771 +0 1 +.names 7141 24771 24772 +1- 1 +-1 1 +.names 666 24773 +0 1 +.names 7157 24777 24774 +1- 1 +-1 1 +.names 24774 24775 +1 1 +.names 2413 24776 +1 1 +.names 24776 24777 +0 1 +.names 24769 24778 +0 1 +.names 24775 24779 +0 1 +.names 23483 24211 24780 +1- 1 +-1 1 +.names 24780 24781 +1 1 +.names 24788 24789 24782 +1- 1 +-1 1 +.names 24782 24783 +1 1 +.names 24759 24784 +0 1 +.names 7144 23500 24785 +1- 1 +-1 1 +.names 24785 24786 +1 1 +.names 24786 24787 +0 1 +.names 24784 24787 24788 +1- 1 +-1 1 +.names 24781 24789 +0 1 +.names 24762 24790 +0 1 +.names 24796 24797 24791 +11 1 +.names 24791 24792 +1 1 +.names 24792 24793 +0 1 +.names 1783 24794 +1 1 +.names 24794 24795 +1 1 +.names 24783 24796 +0 1 +.names 24795 24797 +0 1 +.names 24811 24812 24798 +1- 1 +-1 1 +.names 24798 24799 +1 1 +.names 24799 24800 +0 1 +.names 2413 24801 +1 1 +.names 24801 24802 +1 1 +.names 24802 24803 +0 1 +.names 24800 24803 24804 +1- 1 +-1 1 +.names 24832 24826 24805 +11 1 +.names 24805 24806 +1 1 +.names 24806 24807 +0 1 +.names 24823 24824 24808 +11 1 +.names 24808 24809 +1 1 +.names 24809 24810 +0 1 +.names 24350 24810 24811 +11 1 +.names 7124 23517 24812 +11 1 +.names 24817 24818 24813 +1- 1 +-1 1 +.names 24813 24814 +1 1 +.names 24329 24815 +1 1 +.names 24815 24816 +0 1 +.names 7161 24816 24817 +1- 1 +-1 1 +.names 673 24818 +0 1 +.names 7166 24822 24819 +1- 1 +-1 1 +.names 24819 24820 +1 1 +.names 2413 24821 +1 1 +.names 24821 24822 +0 1 +.names 24814 24823 +0 1 +.names 24820 24824 +0 1 +.names 23534 24245 24825 +1- 1 +-1 1 +.names 24825 24826 +1 1 +.names 24329 24829 24827 +1- 1 +-1 1 +.names 24827 24828 +1 1 +.names 1334 24829 +0 1 +.names 24173 23540 24830 +1- 1 +-1 1 +.names 24830 24831 +1 1 +.names 24831 24828 24832 +11 1 +.names 24329 24835 24833 +1- 1 +-1 1 +.names 24833 24834 +1 1 +.names 1335 24835 +0 1 +.names 24849 24850 24836 +1- 1 +-1 1 +.names 24836 24837 +1 1 +.names 24837 24838 +0 1 +.names 2413 24839 +1 1 +.names 24839 24840 +1 1 +.names 24840 24841 +0 1 +.names 24838 24841 24842 +1- 1 +-1 1 +.names 24853 24855 24843 +11 1 +.names 24843 24844 +1 1 +.names 24844 24845 +0 1 +.names 24866 24867 24846 +11 1 +.names 24846 24847 +1 1 +.names 24847 24848 +0 1 +.names 24190 24848 24849 +11 1 +.names 7126 23561 24850 +11 1 +.names 24302 23582 24851 +1- 1 +-1 1 +.names 24851 24852 +1 1 +.names 24834 24852 24853 +11 1 +.names 23581 24245 24854 +1- 1 +-1 1 +.names 24854 24855 +1 1 +.names 24860 24861 24856 +1- 1 +-1 1 +.names 24856 24857 +1 1 +.names 24329 24858 +1 1 +.names 24858 24859 +0 1 +.names 7161 24859 24860 +1- 1 +-1 1 +.names 681 24861 +0 1 +.names 7164 24865 24862 +1- 1 +-1 1 +.names 24862 24863 +1 1 +.names 2413 24864 +1 1 +.names 24864 24865 +0 1 +.names 24857 24866 +0 1 +.names 24863 24867 +0 1 +.names 24881 24882 24868 +1- 1 +-1 1 +.names 24868 24869 +1 1 +.names 24869 24870 +0 1 +.names 2413 24871 +1 1 +.names 24871 24872 +1 1 +.names 24872 24873 +0 1 +.names 24870 24873 24874 +1- 1 +-1 1 +.names 24887 24889 24875 +11 1 +.names 24875 24876 +1 1 +.names 24876 24877 +0 1 +.names 24900 24901 24878 +11 1 +.names 24878 24879 +1 1 +.names 24879 24880 +0 1 +.names 24229 24880 24881 +11 1 +.names 7162 23599 24882 +11 1 +.names 24329 24902 24883 +1- 1 +-1 1 +.names 24883 24884 +1 1 +.names 24302 23622 24885 +1- 1 +-1 1 +.names 24885 24886 +1 1 +.names 24884 24886 24887 +11 1 +.names 23621 24412 24888 +1- 1 +-1 1 +.names 24888 24889 +1 1 +.names 24894 24895 24890 +1- 1 +-1 1 +.names 24890 24891 +1 1 +.names 24329 24892 +1 1 +.names 24892 24893 +0 1 +.names 7160 24893 24894 +1- 1 +-1 1 +.names 671 24895 +0 1 +.names 7164 24899 24896 +1- 1 +-1 1 +.names 24896 24897 +1 1 +.names 2413 24898 +1 1 +.names 24898 24899 +0 1 +.names 24891 24900 +0 1 +.names 24897 24901 +0 1 +.names 1336 24902 +0 1 +.names 24329 24905 24903 +1- 1 +-1 1 +.names 24903 24904 +1 1 +.names 1337 24905 +0 1 +.names 24911 24912 24906 +1- 1 +-1 1 +.names 24906 24907 +1 1 +.names 24923 24924 24908 +11 1 +.names 24908 24909 +1 1 +.names 24909 24910 +0 1 +.names 24229 24910 24911 +11 1 +.names 7162 23635 24912 +11 1 +.names 24917 24918 24913 +1- 1 +-1 1 +.names 24913 24914 +1 1 +.names 24329 24915 +1 1 +.names 24915 24916 +0 1 +.names 7141 24916 24917 +1- 1 +-1 1 +.names 663 24918 +0 1 +.names 7164 24922 24919 +1- 1 +-1 1 +.names 24919 24920 +1 1 +.names 2413 24921 +1 1 +.names 24921 24922 +0 1 +.names 24914 24923 +0 1 +.names 24920 24924 +0 1 +.names 23652 24211 24925 +1- 1 +-1 1 +.names 24925 24926 +1 1 +.names 24933 24934 24927 +1- 1 +-1 1 +.names 24927 24928 +1 1 +.names 24904 24929 +0 1 +.names 24302 23669 24930 +1- 1 +-1 1 +.names 24930 24931 +1 1 +.names 24931 24932 +0 1 +.names 24929 24932 24933 +1- 1 +-1 1 +.names 24926 24934 +0 1 +.names 24907 24935 +0 1 +.names 24941 24942 24936 +11 1 +.names 24936 24937 +1 1 +.names 24937 24938 +0 1 +.names 1783 24939 +1 1 +.names 24939 24940 +1 1 +.names 24928 24941 +0 1 +.names 24940 24942 +0 1 +.names 24956 24957 24943 +1- 1 +-1 1 +.names 24943 24944 +1 1 +.names 24944 24945 +0 1 +.names 2413 24946 +1 1 +.names 24946 24947 +1 1 +.names 24947 24948 +0 1 +.names 24945 24948 24949 +1- 1 +-1 1 +.names 24962 24964 24950 +11 1 +.names 24950 24951 +1 1 +.names 24951 24952 +0 1 +.names 24975 24976 24953 +11 1 +.names 24953 24954 +1 1 +.names 24954 24955 +0 1 +.names 24229 24955 24956 +11 1 +.names 7162 23686 24957 +11 1 +.names 7144 23707 24958 +1- 1 +-1 1 +.names 24958 24959 +1 1 +.names 24106 24977 24960 +1- 1 +-1 1 +.names 24960 24961 +1 1 +.names 24959 24961 24962 +11 1 +.names 23709 24412 24963 +1- 1 +-1 1 +.names 24963 24964 +1 1 +.names 24969 24970 24965 +1- 1 +-1 1 +.names 24965 24966 +1 1 +.names 24106 24967 +1 1 +.names 24967 24968 +0 1 +.names 7160 24968 24969 +1- 1 +-1 1 +.names 664 24970 +0 1 +.names 1783 24974 24971 +1- 1 +-1 1 +.names 24971 24972 +1 1 +.names 7144 24973 +1 1 +.names 24973 24974 +0 1 +.names 24966 24975 +0 1 +.names 24972 24976 +0 1 +.names 1338 24977 +0 1 +.names 24980 24106 24978 +1- 1 +-1 1 +.names 24978 24979 +1 1 +.names 1339 24980 +0 1 +.names 24994 24995 24981 +1- 1 +-1 1 +.names 24981 24982 +1 1 +.names 24982 24983 +0 1 +.names 2413 24984 +1 1 +.names 24984 24985 +1 1 +.names 24985 24986 +0 1 +.names 24983 24986 24987 +1- 1 +-1 1 +.names 24998 25001 24988 +11 1 +.names 24988 24989 +1 1 +.names 24989 24990 +0 1 +.names 25012 25013 24991 +11 1 +.names 24991 24992 +1 1 +.names 24992 24993 +0 1 +.names 24190 24993 24994 +11 1 +.names 7126 23730 24995 +11 1 +.names 25017 24996 +0 1 +.names 24996 24997 +1 1 +.names 24997 24998 +0 1 +.names 25014 25015 24999 +1- 1 +-1 1 +.names 24999 25000 +1 1 +.names 25000 25001 +0 1 +.names 25006 25007 25002 +1- 1 +-1 1 +.names 25002 25003 +1 1 +.names 24106 25004 +1 1 +.names 25004 25005 +0 1 +.names 7161 25005 25006 +1- 1 +-1 1 +.names 678 25007 +0 1 +.names 7157 25011 25008 +1- 1 +-1 1 +.names 25008 25009 +1 1 +.names 2413 25010 +1 1 +.names 25010 25011 +0 1 +.names 25003 25012 +0 1 +.names 25009 25013 +0 1 +.names 7157 1300 25014 +11 1 +.names 24979 25015 +0 1 +.names 23755 24245 25016 +1- 1 +-1 1 +.names 25016 25017 +1 1 +.names 24329 25020 25018 +1- 1 +-1 1 +.names 25018 25019 +1 1 +.names 1340 25020 +0 1 +.names 25026 25027 25021 +1- 1 +-1 1 +.names 25021 25022 +1 1 +.names 25038 25039 25023 +11 1 +.names 25023 25024 +1 1 +.names 25024 25025 +0 1 +.names 24190 25025 25026 +11 1 +.names 7126 23767 25027 +11 1 +.names 25032 25033 25028 +1- 1 +-1 1 +.names 25028 25029 +1 1 +.names 24329 25030 +1 1 +.names 25030 25031 +0 1 +.names 7141 25031 25032 +1- 1 +-1 1 +.names 662 25033 +0 1 +.names 7164 25037 25034 +1- 1 +-1 1 +.names 25034 25035 +1 1 +.names 2413 25036 +1 1 +.names 25036 25037 +0 1 +.names 25029 25038 +0 1 +.names 25035 25039 +0 1 +.names 23784 24211 25040 +1- 1 +-1 1 +.names 25040 25041 +1 1 +.names 25048 25049 25042 +1- 1 +-1 1 +.names 25042 25043 +1 1 +.names 25019 25044 +0 1 +.names 24302 23801 25045 +1- 1 +-1 1 +.names 25045 25046 +1 1 +.names 25046 25047 +0 1 +.names 25044 25047 25048 +1- 1 +-1 1 +.names 25041 25049 +0 1 +.names 25022 25050 +0 1 +.names 25056 25057 25051 +11 1 +.names 25051 25052 +1 1 +.names 25052 25053 +0 1 +.names 1783 25054 +1 1 +.names 25054 25055 +1 1 +.names 25043 25056 +0 1 +.names 25055 25057 +0 1 +.names 25071 25072 25058 +1- 1 +-1 1 +.names 25058 25059 +1 1 +.names 25059 25060 +0 1 +.names 2413 25061 +1 1 +.names 25061 25062 +1 1 +.names 25062 25063 +0 1 +.names 25060 25063 25064 +1- 1 +-1 1 +.names 25075 25078 25065 +11 1 +.names 25065 25066 +1 1 +.names 25066 25067 +0 1 +.names 25085 25086 25068 +11 1 +.names 25068 25069 +1 1 +.names 25069 25070 +0 1 +.names 24190 25070 25071 +11 1 +.names 7126 23818 25072 +11 1 +.names 7165 1303 25073 +11 1 +.names 25073 25074 +1 1 +.names 25074 25075 +0 1 +.names 25090 25091 25076 +1- 1 +-1 1 +.names 25076 25077 +1 1 +.names 25077 25078 +0 1 +.names 7138 25082 25079 +1- 1 +-1 1 +.names 25079 25080 +1 1 +.names 2413 25081 +1 1 +.names 25081 25082 +0 1 +.names 25095 25096 25083 +1- 1 +-1 1 +.names 25083 25084 +1 1 +.names 25084 25085 +0 1 +.names 25080 25086 +0 1 +.names 23837 7152 25087 +1- 1 +-1 1 +.names 25087 25088 +1 1 +.names 24145 25089 +1 1 +.names 7156 1341 25090 +11 1 +.names 25088 25091 +0 1 +.names 24256 25092 +1 1 +.names 25092 25093 +0 1 +.names 25089 25094 +0 1 +.names 25093 25094 25095 +1- 1 +-1 1 +.names 676 25096 +0 1 +.names 24329 25099 25097 +1- 1 +-1 1 +.names 25097 25098 +1 1 +.names 1342 25099 +0 1 +.names 25113 25114 25100 +1- 1 +-1 1 +.names 25100 25101 +1 1 +.names 25101 25102 +0 1 +.names 2413 25103 +1 1 +.names 25103 25104 +1 1 +.names 25104 25105 +0 1 +.names 25102 25105 25106 +1- 1 +-1 1 +.names 25131 25128 25107 +11 1 +.names 25107 25108 +1 1 +.names 25108 25109 +0 1 +.names 25125 25126 25110 +11 1 +.names 25110 25111 +1 1 +.names 25111 25112 +0 1 +.names 24350 25112 25113 +11 1 +.names 7124 23865 25114 +11 1 +.names 25119 25120 25115 +1- 1 +-1 1 +.names 25115 25116 +1 1 +.names 24329 25117 +1 1 +.names 25117 25118 +0 1 +.names 7161 25118 25119 +1- 1 +-1 1 +.names 677 25120 +0 1 +.names 7166 25124 25121 +1- 1 +-1 1 +.names 25121 25122 +1 1 +.names 2413 25123 +1 1 +.names 25123 25124 +0 1 +.names 25116 25125 +0 1 +.names 25122 25126 +0 1 +.names 23882 24245 25127 +1- 1 +-1 1 +.names 25127 25128 +1 1 +.names 24173 23885 25129 +1- 1 +-1 1 +.names 25129 25130 +1 1 +.names 25130 25098 25131 +11 1 +.names 24254 25134 25132 +1- 1 +-1 1 +.names 25132 25133 +1 1 +.names 1343 25134 +0 1 +.names 25140 25141 25135 +1- 1 +-1 1 +.names 25135 25136 +1 1 +.names 25148 25149 25137 +11 1 +.names 25137 25138 +1 1 +.names 25138 25139 +0 1 +.names 24229 25139 25140 +11 1 +.names 7162 23898 25141 +11 1 +.names 7165 25145 25142 +1- 1 +-1 1 +.names 25142 25143 +1 1 +.names 2413 25144 +1 1 +.names 25144 25145 +0 1 +.names 25154 25155 25146 +1- 1 +-1 1 +.names 25146 25147 +1 1 +.names 25147 25148 +0 1 +.names 25143 25149 +0 1 +.names 23911 24211 25150 +1- 1 +-1 1 +.names 25150 25151 +1 1 +.names 24254 25152 +1 1 +.names 25152 25153 +0 1 +.names 7141 25153 25154 +1- 1 +-1 1 +.names 653 25155 +0 1 +.names 25162 25163 25156 +1- 1 +-1 1 +.names 25156 25157 +1 1 +.names 25133 25158 +0 1 +.names 24256 23932 25159 +1- 1 +-1 1 +.names 25159 25160 +1 1 +.names 25160 25161 +0 1 +.names 25158 25161 25162 +1- 1 +-1 1 +.names 25151 25163 +0 1 +.names 25136 25164 +0 1 +.names 25170 25171 25165 +11 1 +.names 25165 25166 +1 1 +.names 25166 25167 +0 1 +.names 1783 25168 +1 1 +.names 25168 25169 +1 1 +.names 25157 25170 +0 1 +.names 25169 25171 +0 1 +.names 25185 25186 25172 +1- 1 +-1 1 +.names 25172 25173 +1 1 +.names 25173 25174 +0 1 +.names 23972 7152 25175 +1- 1 +-1 1 +.names 25175 25176 +1 1 +.names 25176 25177 +0 1 +.names 25174 25177 25178 +1- 1 +-1 1 +.names 25189 25192 25179 +11 1 +.names 25179 25180 +1 1 +.names 25180 25181 +0 1 +.names 25207 25208 25182 +11 1 +.names 25182 25183 +1 1 +.names 25183 25184 +0 1 +.names 24600 25184 25185 +11 1 +.names 7143 23947 25186 +11 1 +.names 23974 7155 25187 +11 1 +.names 25187 25188 +1 1 +.names 25188 25189 +0 1 +.names 25193 25196 25190 +1- 1 +-1 1 +.names 25190 25191 +1 1 +.names 25191 25192 +0 1 +.names 7135 1344 25193 +11 1 +.names 2413 25194 +1 1 +.names 25194 25195 +1 1 +.names 25195 25196 +0 1 +.names 25201 25202 25197 +1- 1 +-1 1 +.names 25197 25198 +1 1 +.names 2413 25199 +1 1 +.names 25199 25200 +0 1 +.names 7155 25200 25201 +1- 1 +-1 1 +.names 654 25202 +0 1 +.names 7138 25206 25203 +1- 1 +-1 1 +.names 25203 25204 +1 1 +.names 24254 25205 +1 1 +.names 25205 25206 +0 1 +.names 25198 25207 +0 1 +.names 25204 25208 +0 1 +.names 25222 25223 25209 +1- 1 +-1 1 +.names 25209 25210 +1 1 +.names 25210 25211 +0 1 +.names 2413 25212 +1 1 +.names 25212 25213 +1 1 +.names 25213 25214 +0 1 +.names 25211 25214 25215 +1- 1 +-1 1 +.names 25243 25237 25216 +11 1 +.names 25216 25217 +1 1 +.names 25217 25218 +0 1 +.names 25234 25235 25219 +11 1 +.names 25219 25220 +1 1 +.names 25220 25221 +0 1 +.names 24229 25221 25222 +11 1 +.names 7162 23991 25223 +11 1 +.names 25228 25229 25224 +1- 1 +-1 1 +.names 25224 25225 +1 1 +.names 24145 25226 +1 1 +.names 25226 25227 +0 1 +.names 7161 25227 25228 +1- 1 +-1 1 +.names 665 25229 +0 1 +.names 7166 25233 25230 +1- 1 +-1 1 +.names 25230 25231 +1 1 +.names 2413 25232 +1 1 +.names 25232 25233 +0 1 +.names 25225 25234 +0 1 +.names 25231 25235 +0 1 +.names 24008 24245 25236 +1- 1 +-1 1 +.names 25236 25237 +1 1 +.names 24145 25240 25238 +1- 1 +-1 1 +.names 25238 25239 +1 1 +.names 1345 25240 +0 1 +.names 24173 24014 25241 +1- 1 +-1 1 +.names 25241 25242 +1 1 +.names 25242 25239 25243 +11 1 +.names 24106 25246 25244 +1- 1 +-1 1 +.names 25244 25245 +1 1 +.names 1346 25246 +0 1 +.names 24022 7152 25247 +1- 1 +-1 1 +.names 25247 25248 +1 1 +.names 25253 25254 25249 +1- 1 +-1 1 +.names 25249 25250 +1 1 +.names 24106 25251 +1 1 +.names 25251 25252 +0 1 +.names 7138 25252 25253 +1- 1 +-1 1 +.names 670 25254 +0 1 +.names 7166 25258 25255 +1- 1 +-1 1 +.names 25255 25256 +1 1 +.names 2413 25257 +1 1 +.names 25257 25258 +0 1 +.names 25264 25265 25259 +1- 1 +-1 1 +.names 25259 25260 +1 1 +.names 25266 25267 25261 +11 1 +.names 25261 25262 +1 1 +.names 25262 25263 +0 1 +.names 24229 25263 25264 +11 1 +.names 7162 24041 25265 +11 1 +.names 25250 25266 +0 1 +.names 25256 25267 +0 1 +.names 25274 25275 25268 +1- 1 +-1 1 +.names 25268 25269 +1 1 +.names 24173 24061 25270 +1- 1 +-1 1 +.names 25270 25271 +1 1 +.names 25271 25272 +0 1 +.names 25245 25273 +0 1 +.names 25272 25273 25274 +1- 1 +-1 1 +.names 25248 25275 +0 1 +.names 25278 25281 25276 +11 1 +.names 25276 25277 +1 1 +.names 25269 25278 +0 1 +.names 1783 25279 +1 1 +.names 25279 25280 +1 1 +.names 25280 25281 +0 1 +.names 25260 25282 +0 1 +.names 25277 25283 +0 1 +.names 25297 25298 25284 +1- 1 +-1 1 +.names 25284 25285 +1 1 +.names 25285 25286 +0 1 +.names 2413 25287 +1 1 +.names 25287 25288 +1 1 +.names 25288 25289 +0 1 +.names 25286 25289 25290 +1- 1 +-1 1 +.names 25301 25304 25291 +11 1 +.names 25291 25292 +1 1 +.names 25292 25293 +0 1 +.names 25311 25312 25294 +11 1 +.names 25294 25295 +1 1 +.names 25295 25296 +0 1 +.names 24229 25296 25297 +11 1 +.names 7162 24078 25298 +11 1 +.names 7164 1315 25299 +11 1 +.names 25299 25300 +1 1 +.names 25300 25301 +0 1 +.names 25319 25320 25302 +1- 1 +-1 1 +.names 25302 25303 +1 1 +.names 25303 25304 +0 1 +.names 7161 25308 25305 +1- 1 +-1 1 +.names 25305 25306 +1 1 +.names 2413 25307 +1 1 +.names 25307 25308 +0 1 +.names 25317 25318 25309 +1- 1 +-1 1 +.names 25309 25310 +1 1 +.names 25310 25311 +0 1 +.names 25306 25312 +0 1 +.names 24097 24245 25313 +1- 1 +-1 1 +.names 25313 25314 +1 1 +.names 24145 25315 +1 1 +.names 25315 25316 +0 1 +.names 7164 25316 25317 +1- 1 +-1 1 +.names 679 25318 +0 1 +.names 7156 1347 25319 +11 1 +.names 25314 25320 +0 1 +.names 25327 25328 25321 +1- 1 +-1 1 +.names 25321 25322 +1 1 +.names 7425 25323 +0 1 +.names 25330 25331 25324 +11 1 +.names 25324 25325 +1 1 +.names 25325 25326 +0 1 +.names 25323 25326 25327 +11 1 +.names 7425 2413 25328 +11 1 +.names 7417 25329 +0 1 +.names 7019 25329 25330 +11 1 +.names 7418 25331 +0 1 +.names 25337 25338 25332 +1- 1 +-1 1 +.names 25332 25333 +1 1 +.names 25322 25334 +0 1 +.names 2413 25331 25335 +1- 1 +-1 1 +.names 25335 25336 +1 1 +.names 6 7417 25337 +11 1 +.names 25336 25338 +0 1 +.names 25345 25347 25339 +1- 1 +-1 1 +.names 25339 25340 +1 1 +.names 7420 25341 +0 1 +.names 25348 25323 25342 +11 1 +.names 25342 25343 +1 1 +.names 25343 25344 +0 1 +.names 25341 25344 25345 +11 1 +.names 7063 25346 +0 1 +.names 7420 25346 25347 +11 1 +.names 7009 25329 25348 +11 1 +.names 25355 25356 25349 +1- 1 +-1 1 +.names 25349 25350 +1 1 +.names 25340 25351 +0 1 +.names 25354 25329 25352 +1- 1 +-1 1 +.names 25352 25353 +1 1 +.names 11 25354 +0 1 +.names 7425 7049 25355 +11 1 +.names 25353 25356 +0 1 +.names 25360 25361 25357 +11 1 +.names 25357 25358 +1 1 +.names 7416 25359 +0 1 +.names 7025 25359 25360 +11 1 +.names 7428 25361 +0 1 +.names 25375 25376 25362 +1- 1 +-1 1 +.names 25362 25363 +1 1 +.names 25369 25371 25364 +1- 1 +-1 1 +.names 25364 25365 +1 1 +.names 25365 25366 +0 1 +.names 7419 25367 +0 1 +.names 25358 25368 +0 1 +.names 25367 25368 25369 +11 1 +.names 7033 25370 +0 1 +.names 7419 25370 25371 +11 1 +.names 25374 25359 25372 +1- 1 +-1 1 +.names 25372 25373 +1 1 +.names 27 25374 +0 1 +.names 7428 7061 25375 +11 1 +.names 25373 25376 +0 1 +.names 25382 25384 25377 +1- 1 +-1 1 +.names 25377 25378 +1 1 +.names 25386 25331 25379 +11 1 +.names 25379 25380 +1 1 +.names 25380 25381 +0 1 +.names 25361 25381 25382 +11 1 +.names 7039 25383 +0 1 +.names 7428 25383 25384 +11 1 +.names 7415 25385 +0 1 +.names 7023 25385 25386 +11 1 +.names 25389 25331 25387 +1- 1 +-1 1 +.names 25387 25388 +1 1 +.names 7009 25389 +0 1 +.names 25392 25393 25390 +1- 1 +-1 1 +.names 25390 25391 +1 1 +.names 13 7415 25392 +11 1 +.names 25388 25393 +0 1 +.names 25391 25394 +0 1 +.names 25394 25395 +1 1 +.names 25395 25396 +0 1 +.names 25378 25397 +0 1 +.names 25400 25331 25398 +1- 1 +-1 1 +.names 25398 25399 +1 1 +.names 7023 25400 +0 1 +.names 25403 25404 25401 +1- 1 +-1 1 +.names 25401 25402 +1 1 +.names 15 7417 25403 +11 1 +.names 25399 25404 +0 1 +.names 25407 25331 25405 +11 1 +.names 25405 25406 +1 1 +.names 7047 25329 25407 +11 1 +.names 25412 25414 25408 +1- 1 +-1 1 +.names 25408 25409 +1 1 +.names 7429 25410 +0 1 +.names 25406 25411 +0 1 +.names 25410 25411 25412 +11 1 +.names 7037 25413 +0 1 +.names 7429 25413 25414 +11 1 +.names 25409 25415 +0 1 +.names 25421 25423 25416 +1- 1 +-1 1 +.names 25416 25417 +1 1 +.names 25424 25331 25418 +11 1 +.names 25418 25419 +1 1 +.names 25419 25420 +0 1 +.names 25361 25420 25421 +11 1 +.names 7021 25422 +0 1 +.names 7428 25422 25423 +11 1 +.names 7053 25385 25424 +11 1 +.names 25427 25331 25425 +1- 1 +-1 1 +.names 25425 25426 +1 1 +.names 7029 25427 +0 1 +.names 25430 25431 25428 +1- 1 +-1 1 +.names 25428 25429 +1 1 +.names 22 7415 25430 +11 1 +.names 25426 25431 +0 1 +.names 25429 25432 +0 1 +.names 25432 25433 +1 1 +.names 25433 25434 +0 1 +.names 25417 25435 +0 1 +.names 25438 25361 25436 +11 1 +.names 25436 25437 +1 1 +.names 7069 25359 25438 +11 1 +.names 25451 25452 25439 +1- 1 +-1 1 +.names 25439 25440 +1 1 +.names 25445 25447 25441 +1- 1 +-1 1 +.names 25441 25442 +1 1 +.names 25442 25443 +0 1 +.names 25437 25444 +0 1 +.names 25367 25444 25445 +11 1 +.names 7055 25446 +0 1 +.names 7419 25446 25447 +11 1 +.names 25450 25359 25448 +1- 1 +-1 1 +.names 25448 25449 +1 1 +.names 35 25450 +0 1 +.names 7428 7045 25451 +11 1 +.names 25449 25452 +0 1 +.names 25458 25460 25453 +1- 1 +-1 1 +.names 25453 25454 +1 1 +.names 25461 25331 25455 +11 1 +.names 25455 25456 +1 1 +.names 25456 25457 +0 1 +.names 25323 25457 25458 +11 1 +.names 7059 25459 +0 1 +.names 7425 25459 25460 +11 1 +.names 7061 25329 25461 +11 1 +.names 25468 25469 25462 +1- 1 +-1 1 +.names 25462 25463 +1 1 +.names 25454 25464 +0 1 +.names 25467 25331 25465 +1- 1 +-1 1 +.names 25465 25466 +1 1 +.names 7053 25467 +0 1 +.names 24 7417 25468 +11 1 +.names 25466 25469 +0 1 +.names 25472 25473 25470 +11 1 +.names 25470 25471 +1 1 +.names 7017 25359 25472 +11 1 +.names 7427 25473 +0 1 +.names 25485 25486 25474 +1- 1 +-1 1 +.names 25474 25475 +1 1 +.names 25480 25481 25476 +1- 1 +-1 1 +.names 25476 25477 +1 1 +.names 25477 25478 +0 1 +.names 25471 25479 +0 1 +.names 25367 25479 25480 +11 1 +.names 7419 25413 25481 +11 1 +.names 25484 25359 25482 +1- 1 +-1 1 +.names 25482 25483 +1 1 +.names 14 25484 +0 1 +.names 7427 7009 25485 +11 1 +.names 25483 25486 +0 1 +.names 25492 25494 25487 +1- 1 +-1 1 +.names 25487 25488 +1 1 +.names 25495 25331 25489 +11 1 +.names 25489 25490 +1 1 +.names 25490 25491 +0 1 +.names 25323 25491 25492 +11 1 +.names 7025 25493 +0 1 +.names 7425 25493 25494 +11 1 +.names 7043 25385 25495 +11 1 +.names 25498 25331 25496 +1- 1 +-1 1 +.names 25496 25497 +1 1 +.names 7035 25498 +0 1 +.names 25501 25502 25499 +1- 1 +-1 1 +.names 25499 25500 +1 1 +.names 30 7415 25501 +11 1 +.names 25497 25502 +0 1 +.names 25500 25503 +0 1 +.names 25503 25504 +1 1 +.names 25504 25505 +0 1 +.names 25488 25506 +0 1 +.names 25512 25514 25507 +1- 1 +-1 1 +.names 25507 25508 +1 1 +.names 25515 25410 25509 +11 1 +.names 25509 25510 +1 1 +.names 25510 25511 +0 1 +.names 25341 25511 25512 +11 1 +.names 7017 25513 +0 1 +.names 7420 25513 25514 +11 1 +.names 7051 25385 25515 +11 1 +.names 25522 25523 25516 +1- 1 +-1 1 +.names 25516 25517 +1 1 +.names 25508 25518 +0 1 +.names 25521 25385 25519 +1- 1 +-1 1 +.names 25519 25520 +1 1 +.names 16 25521 +0 1 +.names 7429 7023 25522 +11 1 +.names 25520 25523 +0 1 +.names 25526 25473 25524 +11 1 +.names 25524 25525 +1 1 +.names 7015 25359 25526 +11 1 +.names 25535 25538 25527 +1- 1 +-1 1 +.names 25527 25528 +1 1 +.names 25533 25534 25529 +1- 1 +-1 1 +.names 25529 25530 +1 1 +.names 25530 25531 +0 1 +.names 25525 25532 +0 1 +.names 25341 25532 25533 +11 1 +.names 7420 25493 25534 +11 1 +.names 29 7416 25535 +11 1 +.names 25539 25473 25536 +1- 1 +-1 1 +.names 25536 25537 +1 1 +.names 25537 25538 +0 1 +.names 7011 25539 +0 1 +.names 25545 25546 25540 +1- 1 +-1 1 +.names 25540 25541 +1 1 +.names 25548 25361 25542 +11 1 +.names 25542 25543 +1 1 +.names 25543 25544 +0 1 +.names 25341 25544 25545 +11 1 +.names 7420 2413 25546 +11 1 +.names 7426 25547 +0 1 +.names 7027 25547 25548 +11 1 +.names 25555 25556 25549 +1- 1 +-1 1 +.names 25549 25550 +1 1 +.names 25541 25551 +0 1 +.names 25554 25547 25552 +1- 1 +-1 1 +.names 25552 25553 +1 1 +.names 5 25554 +0 1 +.names 7428 1783 25555 +11 1 +.names 25553 25556 +0 1 +.names 25562 25564 25557 +1- 1 +-1 1 +.names 25557 25558 +1 1 +.names 25565 25361 25559 +11 1 +.names 25559 25560 +1 1 +.names 25560 25561 +0 1 +.names 25341 25561 25562 +11 1 +.names 7027 25563 +0 1 +.names 7420 25563 25564 +11 1 +.names 7057 25385 25565 +11 1 +.names 25572 25573 25566 +1- 1 +-1 1 +.names 25566 25567 +1 1 +.names 25558 25568 +0 1 +.names 25571 25385 25569 +1- 1 +-1 1 +.names 25569 25570 +1 1 +.names 7 25571 +0 1 +.names 7428 1783 25572 +11 1 +.names 25570 25573 +0 1 +.names 25579 25581 25574 +1- 1 +-1 1 +.names 25574 25575 +1 1 +.names 25582 25323 25576 +11 1 +.names 25576 25577 +1 1 +.names 25577 25578 +0 1 +.names 25547 25578 25579 +11 1 +.names 10 25580 +0 1 +.names 7426 25580 25581 +11 1 +.names 7039 25367 25582 +11 1 +.names 25586 25589 25583 +1- 1 +-1 1 +.names 25583 25584 +1 1 +.names 25575 25585 +0 1 +.names 7425 7057 25586 +11 1 +.names 25590 25367 25587 +1- 1 +-1 1 +.names 25587 25588 +1 1 +.names 25588 25589 +0 1 +.names 7049 25590 +0 1 +.names 25593 25473 25591 +11 1 +.names 25591 25592 +1 1 +.names 7037 25359 25593 +11 1 +.names 25605 25606 25594 +1- 1 +-1 1 +.names 25594 25595 +1 1 +.names 25600 25601 25596 +1- 1 +-1 1 +.names 25596 25597 +1 1 +.names 25597 25598 +0 1 +.names 25592 25599 +0 1 +.names 25367 25599 25600 +11 1 +.names 7419 25383 25601 +11 1 +.names 25604 25359 25602 +1- 1 +-1 1 +.names 25602 25603 +1 1 +.names 12 25604 +0 1 +.names 7427 7063 25605 +11 1 +.names 25603 25606 +0 1 +.names 25612 25613 25607 +1- 1 +-1 1 +.names 25607 25608 +1 1 +.names 25614 25331 25609 +11 1 +.names 25609 25610 +1 1 +.names 25610 25611 +0 1 +.names 25410 25611 25612 +11 1 +.names 7429 25427 25613 +11 1 +.names 7041 25385 25614 +11 1 +.names 25459 25331 25615 +1- 1 +-1 1 +.names 25615 25616 +1 1 +.names 25619 25620 25617 +1- 1 +-1 1 +.names 25617 25618 +1 1 +.names 23 7415 25619 +11 1 +.names 25616 25620 +0 1 +.names 25618 25621 +0 1 +.names 25621 25622 +1 1 +.names 25622 25623 +0 1 +.names 25608 25624 +0 1 +.names 25630 25631 25625 +1- 1 +-1 1 +.names 25625 25626 +1 1 +.names 25632 25323 25627 +11 1 +.names 25627 25628 +1 1 +.names 25628 25629 +0 1 +.names 25341 25629 25630 +11 1 +.names 7420 25422 25631 +11 1 +.names 7059 25547 25632 +11 1 +.names 25639 25640 25633 +1- 1 +-1 1 +.names 25633 25634 +1 1 +.names 25626 25635 +0 1 +.names 25638 25547 25636 +1- 1 +-1 1 +.names 25636 25637 +1 1 +.names 21 25638 +0 1 +.names 7425 7031 25639 +11 1 +.names 25637 25640 +0 1 +.names 25646 25648 25641 +1- 1 +-1 1 +.names 25641 25642 +1 1 +.names 25649 25473 25643 +11 1 +.names 25643 25644 +1 1 +.names 25644 25645 +0 1 +.names 25547 25645 25646 +11 1 +.names 28 25647 +0 1 +.names 7426 25647 25648 +11 1 +.names 7035 25367 25649 +11 1 +.names 25655 25656 25650 +1- 1 +-1 1 +.names 25650 25651 +1 1 +.names 25642 25652 +0 1 +.names 25539 25367 25653 +1- 1 +-1 1 +.names 25653 25654 +1 1 +.names 7033 7427 25655 +11 1 +.names 25654 25656 +0 1 +.names 25662 25664 25657 +1- 1 +-1 1 +.names 25657 25658 +1 1 +.names 25665 25410 25659 +11 1 +.names 25659 25660 +1 1 +.names 25660 25661 +0 1 +.names 25367 25661 25662 +11 1 +.names 7067 25663 +0 1 +.names 7419 25663 25664 +11 1 +.names 7071 25547 25665 +11 1 +.names 25669 25672 25666 +1- 1 +-1 1 +.names 25666 25667 +1 1 +.names 25658 25668 +0 1 +.names 7429 7055 25669 +11 1 +.names 25673 25547 25670 +1- 1 +-1 1 +.names 25670 25671 +1 1 +.names 25671 25672 +0 1 +.names 36 25673 +0 1 +.names 25679 25681 25674 +1- 1 +-1 1 +.names 25674 25675 +1 1 +.names 25682 25323 25676 +11 1 +.names 25676 25677 +1 1 +.names 25677 25678 +0 1 +.names 25547 25678 25679 +11 1 +.names 26 25680 +0 1 +.names 7426 25680 25681 +11 1 +.names 7011 25331 25682 +11 1 +.names 25689 25690 25683 +1- 1 +-1 1 +.names 25683 25684 +1 1 +.names 25675 25685 +0 1 +.names 25688 25331 25686 +1- 1 +-1 1 +.names 25686 25687 +1 1 +.names 7061 25688 +0 1 +.names 7041 7425 25689 +11 1 +.names 25687 25690 +0 1 +.names 25696 25698 25691 +1- 1 +-1 1 +.names 25691 25692 +1 1 +.names 25699 25410 25693 +11 1 +.names 25693 25694 +1 1 +.names 25694 25695 +0 1 +.names 25329 25695 25696 +11 1 +.names 18 25697 +0 1 +.names 7417 25697 25698 +11 1 +.names 7031 25341 25699 +11 1 +.names 25706 25707 25700 +1- 1 +-1 1 +.names 25700 25701 +1 1 +.names 25692 25702 +0 1 +.names 25705 25341 25703 +1- 1 +-1 1 +.names 25703 25704 +1 1 +.names 7051 25705 +0 1 +.names 7429 7047 25706 +11 1 +.names 25704 25707 +0 1 +.names 25710 25323 25708 +11 1 +.names 25708 25709 +1 1 +.names 7021 25359 25710 +11 1 +.names 25719 25720 25711 +1- 1 +-1 1 +.names 25711 25712 +1 1 +.names 25722 25724 25713 +1- 1 +-1 1 +.names 25713 25714 +1 1 +.names 25714 25715 +0 1 +.names 25718 25359 25716 +1- 1 +-1 1 +.names 25716 25717 +1 1 +.names 19 25718 +0 1 +.names 7425 7051 25719 +11 1 +.names 25717 25720 +0 1 +.names 25709 25721 +0 1 +.names 25367 25721 25722 +11 1 +.names 7013 25723 +0 1 +.names 7419 25723 25724 +11 1 +.names 25730 25732 25725 +1- 1 +-1 1 +.names 25725 25726 +1 1 +.names 25733 25323 25727 +11 1 +.names 25727 25728 +1 1 +.names 25728 25729 +0 1 +.names 25329 25729 25730 +11 1 +.names 33 25731 +0 1 +.names 7417 25731 25732 +11 1 +.names 7055 25367 25733 +11 1 +.names 25740 25741 25734 +1- 1 +-1 1 +.names 25734 25735 +1 1 +.names 25726 25736 +0 1 +.names 25739 25367 25737 +1- 1 +-1 1 +.names 25737 25738 +1 1 +.names 7065 25739 +0 1 +.names 7425 7043 25740 +11 1 +.names 25738 25741 +0 1 +.names 25747 25749 25742 +1- 1 +-1 1 +.names 25742 25743 +1 1 +.names 25750 25473 25744 +11 1 +.names 25744 25745 +1 1 +.names 25745 25746 +0 1 +.names 25547 25746 25747 +11 1 +.names 31 25748 +0 1 +.names 7426 25748 25749 +11 1 +.names 7065 25331 25750 +11 1 +.names 25757 25758 25751 +1- 1 +-1 1 +.names 25751 25752 +1 1 +.names 25743 25753 +0 1 +.names 25756 25331 25754 +1- 1 +-1 1 +.names 25754 25755 +1 1 +.names 7015 25756 +0 1 +.names 7427 7035 25757 +11 1 +.names 25755 25758 +0 1 +.names 25764 25766 25759 +1- 1 +-1 1 +.names 25759 25760 +1 1 +.names 25767 25473 25761 +11 1 +.names 25761 25762 +1 1 +.names 25762 25763 +0 1 +.names 25547 25763 25764 +11 1 +.names 17 25765 +0 1 +.names 7426 25765 25766 +11 1 +.names 7013 25341 25767 +11 1 +.names 25774 25775 25768 +1- 1 +-1 1 +.names 25768 25769 +1 1 +.names 25760 25770 +0 1 +.names 25773 25341 25771 +1- 1 +-1 1 +.names 25771 25772 +1 1 +.names 7047 25773 +0 1 +.names 7427 7017 25774 +11 1 +.names 25772 25775 +0 1 +.names 25781 25783 25776 +1- 1 +-1 1 +.names 25776 25777 +1 1 +.names 25784 25361 25778 +11 1 +.names 25778 25779 +1 1 +.names 25779 25780 +0 1 +.names 25385 25780 25781 +11 1 +.names 32 25782 +0 1 +.names 7415 25782 25783 +11 1 +.names 7045 25367 25784 +11 1 +.names 25791 25792 25785 +1- 1 +-1 1 +.names 25785 25786 +1 1 +.names 25777 25787 +0 1 +.names 25790 25367 25788 +1- 1 +-1 1 +.names 25788 25789 +1 1 +.names 7043 25790 +0 1 +.names 7428 7015 25791 +11 1 +.names 25789 25792 +0 1 +.names 25798 25800 25793 +1- 1 +-1 1 +.names 25793 25794 +1 1 +.names 25801 25410 25795 +11 1 +.names 25795 25796 +1 1 +.names 25796 25797 +0 1 +.names 25341 25797 25798 +11 1 +.names 7019 25799 +0 1 +.names 7420 25799 25800 +11 1 +.names 7049 25329 25801 +11 1 +.names 25808 25809 25802 +1- 1 +-1 1 +.names 25802 25803 +1 1 +.names 25794 25804 +0 1 +.names 25807 25329 25805 +1- 1 +-1 1 +.names 25805 25806 +1 1 +.names 8 25807 +0 1 +.names 7429 7027 25808 +11 1 +.names 25806 25809 +0 1 +.names 25815 25817 25810 +1- 1 +-1 1 +.names 25810 25811 +1 1 +.names 25818 25410 25812 +11 1 +.names 25812 25813 +1 1 +.names 25813 25814 +0 1 +.names 25341 25814 25815 +11 1 +.names 7057 25816 +0 1 +.names 7420 25816 25817 +11 1 +.names 7063 25329 25818 +11 1 +.names 25822 25825 25819 +1- 1 +-1 1 +.names 25819 25820 +1 1 +.names 25811 25821 +0 1 +.names 9 7417 25822 +11 1 +.names 25799 25410 25823 +1- 1 +-1 1 +.names 25823 25824 +1 1 +.names 25824 25825 +0 1 +.names 25831 25833 25826 +1- 1 +-1 1 +.names 25826 25827 +1 1 +.names 25834 25473 25828 +11 1 +.names 25828 25829 +1 1 +.names 25829 25830 +0 1 +.names 25385 25830 25831 +11 1 +.names 20 25832 +0 1 +.names 7415 25832 25833 +11 1 +.names 7029 25341 25834 +11 1 +.names 25838 25841 25835 +1- 1 +-1 1 +.names 25835 25836 +1 1 +.names 25827 25837 +0 1 +.names 7427 7013 25838 +11 1 +.names 25842 25341 25839 +1- 1 +-1 1 +.names 25839 25840 +1 1 +.names 25840 25841 +0 1 +.names 7031 25842 +0 1 +.names 25848 25850 25843 +1- 1 +-1 1 +.names 25843 25844 +1 1 +.names 25851 25361 25845 +11 1 +.names 25845 25846 +1 1 +.names 25846 25847 +0 1 +.names 25329 25847 25848 +11 1 +.names 25 25849 +0 1 +.names 7417 25849 25850 +11 1 +.names 7033 25367 25851 +11 1 +.names 25858 25859 25852 +1- 1 +-1 1 +.names 25852 25853 +1 1 +.names 25844 25854 +0 1 +.names 25857 25367 25855 +1- 1 +-1 1 +.names 25855 25856 +1 1 +.names 7041 25857 +0 1 +.names 7053 7428 25858 +11 1 +.names 25856 25859 +0 1 +.names 25862 25410 25860 +11 1 +.names 25860 25861 +1 1 +.names 7067 25359 25862 +11 1 +.names 25875 25876 25863 +1- 1 +-1 1 +.names 25863 25864 +1 1 +.names 25869 25871 25865 +1- 1 +-1 1 +.names 25865 25866 +1 1 +.names 25866 25867 +0 1 +.names 25861 25868 +0 1 +.names 25367 25868 25869 +11 1 +.names 7045 25870 +0 1 +.names 7419 25870 25871 +11 1 +.names 25874 25359 25872 +1- 1 +-1 1 +.names 25872 25873 +1 1 +.names 34 25874 +0 1 +.names 7429 7065 25875 +11 1 +.names 25873 25876 +0 1 +.names 25883 25885 25877 +1- 1 +-1 1 +.names 25877 25878 +1 1 +.names 7445 25879 +0 1 +.names 25915 25916 25880 +11 1 +.names 25880 25881 +1 1 +.names 25881 25882 +0 1 +.names 25879 25882 25883 +11 1 +.names 398 25884 +0 1 +.names 7445 25884 25885 +11 1 +.names 25894 25897 25886 +1- 1 +-1 1 +.names 25886 25887 +1 1 +.names 25925 25926 25888 +11 1 +.names 25888 25889 +1 1 +.names 25889 25890 +0 1 +.names 25928 25929 25891 +11 1 +.names 25891 25892 +1 1 +.names 25892 25893 +0 1 +.names 25890 25893 25894 +1- 1 +-1 1 +.names 25922 25924 25895 +11 1 +.names 25895 25896 +1 1 +.names 25896 25897 +0 1 +.names 25903 25904 25898 +1- 1 +-1 1 +.names 25898 25899 +1 1 +.names 7465 25900 +0 1 +.names 25900 25901 +1 1 +.names 25901 25902 +0 1 +.names 7480 25902 25903 +1- 1 +-1 1 +.names 7324 25904 +0 1 +.names 25907 25908 25905 +11 1 +.names 25905 25906 +1 1 +.names 7434 25907 +0 1 +.names 7455 25908 +0 1 +.names 25911 25912 25909 +11 1 +.names 25909 25910 +1 1 +.names 7442 25911 +0 1 +.names 7438 25912 +0 1 +.names 25918 25919 25913 +1- 1 +-1 1 +.names 25913 25914 +1 1 +.names 25914 25915 +0 1 +.names 25899 25916 +0 1 +.names 25878 25917 +0 1 +.names 25906 25918 +0 1 +.names 25910 25919 +0 1 +.names 47869 47870 56447 +1- 1 +-1 1 +.names 56447 25921 +0 1 +.names 25921 25911 25922 +1- 1 +-1 1 +.names 7480 25923 +0 1 +.names 25923 25493 25924 +1- 1 +-1 1 +.names 25900 25921 25925 +1- 1 +-1 1 +.names 2413 25908 25926 +1- 1 +-1 1 +.names 704 25927 +0 1 +.names 25907 25927 25928 +1- 1 +-1 1 +.names 25912 25493 25929 +1- 1 +-1 1 +.names 25935 25937 25930 +1- 1 +-1 1 +.names 25930 25931 +1 1 +.names 25965 25966 25932 +11 1 +.names 25932 25933 +1 1 +.names 25933 25934 +0 1 +.names 25879 25934 25935 +11 1 +.names 377 25936 +0 1 +.names 7445 25936 25937 +11 1 +.names 25946 25949 25938 +1- 1 +-1 1 +.names 25938 25939 +1 1 +.names 25970 25971 25940 +11 1 +.names 25940 25941 +1 1 +.names 25941 25942 +0 1 +.names 25975 25976 25943 +11 1 +.names 25943 25944 +1 1 +.names 25944 25945 +0 1 +.names 25942 25945 25946 +1- 1 +-1 1 +.names 25977 25979 25947 +11 1 +.names 25947 25948 +1 1 +.names 25948 25949 +0 1 +.names 25955 25956 25950 +1- 1 +-1 1 +.names 25950 25951 +1 1 +.names 7486 25952 +0 1 +.names 25952 25953 +1 1 +.names 25953 25954 +0 1 +.names 7483 25954 25955 +1- 1 +-1 1 +.names 7387 25956 +0 1 +.names 25959 25908 25957 +11 1 +.names 25957 25958 +1 1 +.names 7433 25959 +0 1 +.names 25911 25962 25960 +11 1 +.names 25960 25961 +1 1 +.names 7473 25962 +0 1 +.names 25972 25973 25963 +1- 1 +-1 1 +.names 25963 25964 +1 1 +.names 25964 25965 +0 1 +.names 25951 25966 +0 1 +.names 25931 25967 +0 1 +.names 47976 47977 56426 +1- 1 +-1 1 +.names 56426 25969 +0 1 +.names 25952 25969 25970 +1- 1 +-1 1 +.names 2413 25908 25971 +1- 1 +-1 1 +.names 25958 25972 +0 1 +.names 25961 25973 +0 1 +.names 683 25974 +0 1 +.names 25959 25974 25975 +1- 1 +-1 1 +.names 25962 25799 25976 +1- 1 +-1 1 +.names 2413 25911 25977 +1- 1 +-1 1 +.names 7483 25978 +0 1 +.names 25978 2413 25979 +1- 1 +-1 1 +.names 7469 25980 +1 1 +.names 25984 25985 25981 +1- 1 +-1 1 +.names 25981 25982 +1 1 +.names 25980 25983 +0 1 +.names 7481 25983 25984 +1- 1 +-1 1 +.names 7372 25985 +0 1 +.names 25988 25989 25986 +11 1 +.names 25986 25987 +1 1 +.names 7431 25988 +0 1 +.names 7476 25989 +0 1 +.names 25994 25995 25990 +11 1 +.names 25990 25991 +1 1 +.names 26019 26022 25992 +1- 1 +-1 1 +.names 25992 25993 +1 1 +.names 25993 25994 +0 1 +.names 25982 25995 +0 1 +.names 26030 26031 25996 +1- 1 +-1 1 +.names 25996 25997 +1 1 +.names 26005 26007 25998 +1- 1 +-1 1 +.names 25998 25999 +1 1 +.names 25999 26000 +0 1 +.names 7458 26001 +0 1 +.names 26001 26002 +1 1 +.names 26002 26003 +0 1 +.names 382 26004 +0 1 +.names 26003 26004 26005 +11 1 +.names 25991 26006 +0 1 +.names 26002 26006 26007 +11 1 +.names 26010 26013 26008 +11 1 +.names 26008 26009 +1 1 +.names 2413 7469 26010 +1- 1 +-1 1 +.names 47946 47947 56431 +1- 1 +-1 1 +.names 56431 26012 +0 1 +.names 26012 25989 26013 +1- 1 +-1 1 +.names 26016 26018 26014 +11 1 +.names 26014 26015 +1 1 +.names 25962 25389 26016 +1- 1 +-1 1 +.names 7481 26017 +0 1 +.names 26017 25389 26018 +1- 1 +-1 1 +.names 25987 26019 +0 1 +.names 25962 25952 26020 +11 1 +.names 26020 26021 +1 1 +.names 26021 26022 +0 1 +.names 26026 26027 26023 +11 1 +.names 26023 26024 +1 1 +.names 688 26025 +0 1 +.names 25988 26025 26026 +1- 1 +-1 1 +.names 25952 26012 26027 +1- 1 +-1 1 +.names 26015 26028 +0 1 +.names 26024 26029 +0 1 +.names 26028 26029 26030 +1- 1 +-1 1 +.names 26009 26031 +0 1 +.names 26034 26035 26032 +1- 1 +-1 1 +.names 26032 26033 +1 1 +.names 7457 26034 +0 1 +.names 384 26035 +0 1 +.names 26040 2413 26036 +1- 1 +-1 1 +.names 26036 26037 +1 1 +.names 26084 26038 +0 1 +.names 26038 26039 +1 1 +.names 26039 26040 +0 1 +.names 26096 26097 26041 +11 1 +.names 26041 26042 +1 1 +.names 26042 26043 +0 1 +.names 26051 26052 26044 +1- 1 +-1 1 +.names 26044 26045 +1 1 +.names 26045 26046 +0 1 +.names 7436 26047 +0 1 +.names 26079 26082 26048 +11 1 +.names 26048 26049 +1 1 +.names 26049 26050 +0 1 +.names 26047 26050 26051 +11 1 +.names 7436 25400 26052 +11 1 +.names 26055 26058 26053 +1- 1 +-1 1 +.names 26053 26054 +1 1 +.names 26033 26055 +0 1 +.names 7496 26056 +0 1 +.names 26056 26057 +1 1 +.names 26057 26058 +0 1 +.names 26055 26063 26059 +1- 1 +-1 1 +.names 26059 26060 +1 1 +.names 56433 26061 +0 1 +.names 26061 26062 +1 1 +.names 26062 26063 +0 1 +.names 48021 48022 56433 +1- 1 +-1 1 +.names 26067 26070 26065 +1- 1 +-1 1 +.names 26065 26066 +1 1 +.names 26054 26060 26067 +11 1 +.names 26086 26087 26068 +11 1 +.names 26068 26069 +1 1 +.names 26069 26070 +0 1 +.names 26075 26078 26071 +1- 1 +-1 1 +.names 26071 26072 +1 1 +.names 26083 26034 26073 +11 1 +.names 26073 26074 +1 1 +.names 26074 26075 +0 1 +.names 26056 26017 26076 +11 1 +.names 26076 26077 +1 1 +.names 26077 26078 +0 1 +.names 26072 26079 +0 1 +.names 26090 26091 26080 +1- 1 +-1 1 +.names 26080 26081 +1 1 +.names 26081 26082 +0 1 +.names 7478 26083 +0 1 +.names 7469 26084 +1 1 +.names 690 26085 +0 1 +.names 25959 26085 26086 +1- 1 +-1 1 +.names 26017 25400 26087 +1- 1 +-1 1 +.names 25959 26088 +1 1 +.names 7366 26089 +0 1 +.names 26038 26089 26090 +1- 1 +-1 1 +.names 26088 26091 +0 1 +.names 26094 26095 26092 +1- 1 +-1 1 +.names 26092 26093 +1 1 +.names 7478 56433 26094 +11 1 +.names 26037 26095 +0 1 +.names 26066 26096 +0 1 +.names 26093 26097 +0 1 +.names 26103 26105 26098 +1- 1 +-1 1 +.names 26098 26099 +1 1 +.names 26131 26132 26100 +11 1 +.names 26100 26101 +1 1 +.names 26101 26102 +0 1 +.names 26034 26102 26103 +11 1 +.names 386 26104 +0 1 +.names 7457 26104 26105 +11 1 +.names 26114 26117 26106 +1- 1 +-1 1 +.names 26106 26107 +1 1 +.names 26136 26137 26108 +11 1 +.names 26108 26109 +1 1 +.names 26109 26110 +0 1 +.names 26143 26144 26111 +11 1 +.names 26111 26112 +1 1 +.names 26112 26113 +0 1 +.names 26110 26113 26114 +1- 1 +-1 1 +.names 26138 26139 26115 +11 1 +.names 26115 26116 +1 1 +.names 26116 26117 +0 1 +.names 26122 26123 26118 +1- 1 +-1 1 +.names 26118 26119 +1 1 +.names 25900 26120 +1 1 +.names 26120 26121 +0 1 +.names 7481 26121 26122 +1- 1 +-1 1 +.names 7360 26123 +0 1 +.names 25959 26126 26124 +11 1 +.names 26124 26125 +1 1 +.names 7456 26126 +0 1 +.names 25911 25912 26127 +11 1 +.names 26127 26128 +1 1 +.names 26140 26141 26129 +1- 1 +-1 1 +.names 26129 26130 +1 1 +.names 26130 26131 +0 1 +.names 26119 26132 +0 1 +.names 26099 26133 +0 1 +.names 48061 48064 56435 +1- 1 +-1 1 +.names 56435 26135 +0 1 +.names 25900 26135 26136 +1- 1 +-1 1 +.names 2413 26126 26137 +1- 1 +-1 1 +.names 26135 25911 26138 +1- 1 +-1 1 +.names 26017 25773 26139 +1- 1 +-1 1 +.names 26125 26140 +0 1 +.names 26128 26141 +0 1 +.names 692 26142 +0 1 +.names 25959 26142 26143 +1- 1 +-1 1 +.names 25912 25773 26144 +1- 1 +-1 1 +.names 26150 26152 26145 +1- 1 +-1 1 +.names 26145 26146 +1 1 +.names 26164 26165 26147 +11 1 +.names 26147 26148 +1 1 +.names 26148 26149 +0 1 +.names 26034 26149 26150 +11 1 +.names 393 26151 +0 1 +.names 7457 26151 26152 +11 1 +.names 26158 26159 26153 +1- 1 +-1 1 +.names 26153 26154 +1 1 +.names 7487 26155 +0 1 +.names 26155 26156 +1 1 +.names 26156 26157 +0 1 +.names 7483 26157 26158 +1- 1 +-1 1 +.names 7339 26159 +0 1 +.names 25959 26126 26160 +11 1 +.names 26160 26161 +1 1 +.names 26181 26182 26162 +1- 1 +-1 1 +.names 26162 26163 +1 1 +.names 26163 26164 +0 1 +.names 26154 26165 +0 1 +.names 26190 26191 26166 +1- 1 +-1 1 +.names 26166 26167 +1 1 +.names 26146 26168 +0 1 +.names 26173 26174 26169 +11 1 +.names 26169 26170 +1 1 +.names 48095 48127 56442 +1- 1 +-1 1 +.names 56442 26172 +0 1 +.names 26155 26172 26173 +1- 1 +-1 1 +.names 2413 26126 26174 +1- 1 +-1 1 +.names 26083 25962 26175 +11 1 +.names 26175 26176 +1 1 +.names 26179 26180 26177 +11 1 +.names 26177 26178 +1 1 +.names 26172 26083 26179 +1- 1 +-1 1 +.names 25978 25467 26180 +1- 1 +-1 1 +.names 26161 26181 +0 1 +.names 26176 26182 +0 1 +.names 26186 26187 26183 +11 1 +.names 26183 26184 +1 1 +.names 699 26185 +0 1 +.names 25959 26185 26186 +1- 1 +-1 1 +.names 25962 25467 26187 +1- 1 +-1 1 +.names 26170 26188 +0 1 +.names 26184 26189 +0 1 +.names 26188 26189 26190 +1- 1 +-1 1 +.names 26178 26191 +0 1 +.names 26197 26199 26192 +1- 1 +-1 1 +.names 26192 26193 +1 1 +.names 26212 26213 26194 +11 1 +.names 26194 26195 +1 1 +.names 26195 26196 +0 1 +.names 25907 26196 26197 +11 1 +.names 712 26198 +0 1 +.names 7434 26198 26199 +11 1 +.names 26204 26205 26200 +1- 1 +-1 1 +.names 26200 26201 +1 1 +.names 25908 26202 +1 1 +.names 26202 26203 +0 1 +.names 7480 26203 26204 +1- 1 +-1 1 +.names 7300 26205 +0 1 +.names 25900 26034 26206 +11 1 +.names 26206 26207 +1 1 +.names 25911 26047 26208 +11 1 +.names 26208 26209 +1 1 +.names 26224 26225 26210 +1- 1 +-1 1 +.names 26210 26211 +1 1 +.names 26211 26212 +0 1 +.names 26201 26213 +0 1 +.names 26237 26238 26214 +1- 1 +-1 1 +.names 26214 26215 +1 1 +.names 26193 26216 +0 1 +.names 26221 26223 26217 +11 1 +.names 26217 26218 +1 1 +.names 48152 48177 56455 +1- 1 +-1 1 +.names 56455 26220 +0 1 +.names 26220 25911 26221 +1- 1 +-1 1 +.names 7069 26222 +0 1 +.names 25923 26222 26223 +1- 1 +-1 1 +.names 26207 26224 +0 1 +.names 26209 26225 +0 1 +.names 26228 26230 26226 +11 1 +.names 26226 26227 +1 1 +.names 2413 25908 26228 +1- 1 +-1 1 +.names 406 26229 +0 1 +.names 26034 26229 26230 +1- 1 +-1 1 +.names 26233 26234 26231 +11 1 +.names 26231 26232 +1 1 +.names 25900 26220 26233 +1- 1 +-1 1 +.names 26047 26222 26234 +1- 1 +-1 1 +.names 26227 26235 +0 1 +.names 26232 26236 +0 1 +.names 26235 26236 26237 +1- 1 +-1 1 +.names 26218 26238 +0 1 +.names 26241 26034 26239 +1- 1 +-1 1 +.names 26239 26240 +1 1 +.names 395 26241 +0 1 +.names 26251 26252 26242 +1- 1 +-1 1 +.names 26242 26243 +1 1 +.names 26243 26244 +0 1 +.names 26266 26269 26245 +11 1 +.names 26245 26246 +1 1 +.names 26246 26247 +0 1 +.names 26289 26290 26248 +11 1 +.names 26248 26249 +1 1 +.names 26249 26250 +0 1 +.names 26017 26250 26251 +11 1 +.names 7481 25688 26252 +11 1 +.names 26255 26258 26253 +1- 1 +-1 1 +.names 26253 26254 +1 1 +.names 26240 26255 +0 1 +.names 7475 26256 +0 1 +.names 26256 26257 +1 1 +.names 26257 26258 +0 1 +.names 26255 26263 26259 +1- 1 +-1 1 +.names 26259 26260 +1 1 +.names 56444 26261 +0 1 +.names 26261 26262 +1 1 +.names 26262 26263 +0 1 +.names 26270 26273 26264 +1- 1 +-1 1 +.names 26264 26265 +1 1 +.names 26265 26266 +0 1 +.names 26292 26295 26267 +1- 1 +-1 1 +.names 26267 26268 +1 1 +.names 26268 26269 +0 1 +.names 26254 26260 26270 +11 1 +.names 26296 26298 26271 +11 1 +.names 26271 26272 +1 1 +.names 26272 26273 +0 1 +.names 26277 26280 26274 +1- 1 +-1 1 +.names 26274 26275 +1 1 +.names 7333 26276 +0 1 +.names 7455 26276 26277 +1- 1 +-1 1 +.names 7492 26278 +0 1 +.names 26278 26279 +1 1 +.names 26279 26280 +0 1 +.names 26285 26288 26281 +1- 1 +-1 1 +.names 26281 26282 +1 1 +.names 26083 26034 26283 +11 1 +.names 26283 26284 +1 1 +.names 26284 26285 +0 1 +.names 26047 26256 26286 +11 1 +.names 26286 26287 +1 1 +.names 26287 26288 +0 1 +.names 26282 26289 +0 1 +.names 26275 26290 +0 1 +.names 48191 48221 56444 +1- 1 +-1 1 +.names 7478 56444 26292 +11 1 +.names 26047 25688 26293 +1- 1 +-1 1 +.names 26293 26294 +1 1 +.names 26294 26295 +0 1 +.names 25908 2413 26296 +1- 1 +-1 1 +.names 701 26297 +0 1 +.names 26297 26278 26298 +1- 1 +-1 1 +.names 26301 26302 26299 +11 1 +.names 26299 26300 +1 1 +.names 25912 25513 26301 +1- 1 +-1 1 +.names 25978 25513 26302 +1- 1 +-1 1 +.names 25912 26155 26303 +11 1 +.names 26303 26304 +1 1 +.names 25908 26305 +1 1 +.names 26309 26310 26306 +1- 1 +-1 1 +.names 26306 26307 +1 1 +.names 26305 26308 +0 1 +.names 7483 26308 26309 +1- 1 +-1 1 +.names 7363 26310 +0 1 +.names 26315 26316 26311 +11 1 +.names 26311 26312 +1 1 +.names 26339 26340 26313 +1- 1 +-1 1 +.names 26313 26314 +1 1 +.names 26314 26315 +0 1 +.names 26307 26316 +0 1 +.names 26320 26322 26317 +1- 1 +-1 1 +.names 26317 26318 +1 1 +.names 26312 26319 +0 1 +.names 26001 26319 26320 +11 1 +.names 385 26321 +0 1 +.names 7458 26321 26322 +11 1 +.names 26343 26344 26323 +1- 1 +-1 1 +.names 26323 26324 +1 1 +.names 26318 26325 +0 1 +.names 26328 26331 26326 +11 1 +.names 26326 26327 +1 1 +.names 2413 25908 26328 +1- 1 +-1 1 +.names 48251 48276 56434 +1- 1 +-1 1 +.names 56434 26330 +0 1 +.names 26330 25989 26331 +1- 1 +-1 1 +.names 26335 26336 26332 +11 1 +.names 26332 26333 +1 1 +.names 691 26334 +0 1 +.names 25988 26334 26335 +1- 1 +-1 1 +.names 26155 26330 26336 +1- 1 +-1 1 +.names 25988 25989 26337 +11 1 +.names 26337 26338 +1 1 +.names 26338 26339 +0 1 +.names 26304 26340 +0 1 +.names 26300 26341 +0 1 +.names 26333 26342 +0 1 +.names 26341 26342 26343 +1- 1 +-1 1 +.names 26327 26344 +0 1 +.names 26350 26352 26345 +1- 1 +-1 1 +.names 26345 26346 +1 1 +.names 26363 26364 26347 +11 1 +.names 26347 26348 +1 1 +.names 26348 26349 +0 1 +.names 26001 26349 26350 +11 1 +.names 401 26351 +0 1 +.names 7458 26351 26352 +11 1 +.names 26357 26358 26353 +1- 1 +-1 1 +.names 26353 26354 +1 1 +.names 26056 26355 +1 1 +.names 26355 26356 +0 1 +.names 7483 26356 26357 +1- 1 +-1 1 +.names 7315 26358 +0 1 +.names 25907 26126 26359 +11 1 +.names 26359 26360 +1 1 +.names 26376 26377 26361 +1- 1 +-1 1 +.names 26361 26362 +1 1 +.names 26362 26363 +0 1 +.names 26354 26364 +0 1 +.names 26386 26387 26365 +1- 1 +-1 1 +.names 26365 26366 +1 1 +.names 26346 26367 +0 1 +.names 26372 26373 26368 +11 1 +.names 26368 26369 +1 1 +.names 48292 48295 56450 +1- 1 +-1 1 +.names 56450 26371 +0 1 +.names 26056 26371 26372 +1- 1 +-1 1 +.names 2413 26126 26373 +1- 1 +-1 1 +.names 26083 25962 26374 +11 1 +.names 26374 26375 +1 1 +.names 26360 26376 +0 1 +.names 26375 26377 +0 1 +.names 26380 26381 26378 +11 1 +.names 26378 26379 +1 1 +.names 26371 26083 26380 +1- 1 +-1 1 +.names 25978 25790 26381 +1- 1 +-1 1 +.names 26369 26382 +0 1 +.names 26389 26390 26383 +11 1 +.names 26383 26384 +1 1 +.names 26384 26385 +0 1 +.names 26382 26385 26386 +1- 1 +-1 1 +.names 26379 26387 +0 1 +.names 707 26388 +0 1 +.names 25907 26388 26389 +1- 1 +-1 1 +.names 25962 25790 26390 +1- 1 +-1 1 +.names 26396 26398 26391 +1- 1 +-1 1 +.names 26391 26392 +1 1 +.names 26424 26425 26393 +11 1 +.names 26393 26394 +1 1 +.names 26394 26395 +0 1 +.names 25907 26395 26396 +11 1 +.names 693 26397 +0 1 +.names 7434 26397 26398 +11 1 +.names 26407 26410 26399 +1- 1 +-1 1 +.names 26399 26400 +1 1 +.names 26431 26433 26401 +11 1 +.names 26401 26402 +1 1 +.names 26402 26403 +0 1 +.names 26436 26437 26404 +11 1 +.names 26404 26405 +1 1 +.names 26405 26406 +0 1 +.names 26403 26406 26407 +1- 1 +-1 1 +.names 26429 26430 26408 +11 1 +.names 26408 26409 +1 1 +.names 26409 26410 +0 1 +.names 26415 26416 26411 +1- 1 +-1 1 +.names 26411 26412 +1 1 +.names 7469 26413 +1 1 +.names 26413 26414 +0 1 +.names 7483 26414 26415 +1- 1 +-1 1 +.names 7357 26416 +0 1 +.names 26419 25879 26417 +11 1 +.names 26417 26418 +1 1 +.names 7493 26419 +0 1 +.names 25911 26047 26420 +11 1 +.names 26420 26421 +1 1 +.names 26434 26435 26422 +1- 1 +-1 1 +.names 26422 26423 +1 1 +.names 26423 26424 +0 1 +.names 26412 26425 +0 1 +.names 26392 26426 +0 1 +.names 48349 48352 56436 +1- 1 +-1 1 +.names 56436 26428 +0 1 +.names 26428 25911 26429 +1- 1 +-1 1 +.names 25978 25705 26430 +1- 1 +-1 1 +.names 2413 7469 26431 +1- 1 +-1 1 +.names 387 26432 +0 1 +.names 25879 26432 26433 +1- 1 +-1 1 +.names 26418 26434 +0 1 +.names 26421 26435 +0 1 +.names 26419 26428 26436 +1- 1 +-1 1 +.names 26047 25705 26437 +1- 1 +-1 1 +.names 7469 26438 +1 1 +.names 25879 26441 26439 +1- 1 +-1 1 +.names 26439 26440 +1 1 +.names 400 26441 +0 1 +.names 26451 26452 26442 +1- 1 +-1 1 +.names 26442 26443 +1 1 +.names 26443 26444 +0 1 +.names 26465 26468 26445 +11 1 +.names 26445 26446 +1 1 +.names 26446 26447 +0 1 +.names 26486 26487 26448 +11 1 +.names 26448 26449 +1 1 +.names 26449 26450 +0 1 +.names 26017 26450 26451 +11 1 +.names 7481 25756 26452 +11 1 +.names 26455 26457 26453 +1- 1 +-1 1 +.names 26453 26454 +1 1 +.names 26440 26455 +0 1 +.names 26256 26456 +1 1 +.names 26456 26457 +0 1 +.names 26455 26462 26458 +1- 1 +-1 1 +.names 26458 26459 +1 1 +.names 56449 26460 +0 1 +.names 26460 26461 +1 1 +.names 26461 26462 +0 1 +.names 26469 26472 26463 +1- 1 +-1 1 +.names 26463 26464 +1 1 +.names 26464 26465 +0 1 +.names 26494 26495 26466 +1- 1 +-1 1 +.names 26466 26467 +1 1 +.names 26467 26468 +0 1 +.names 26454 26459 26469 +11 1 +.names 26489 26490 26470 +11 1 +.names 26470 26471 +1 1 +.names 26471 26472 +0 1 +.names 26476 26477 26473 +1- 1 +-1 1 +.names 26473 26474 +1 1 +.names 26438 26475 +0 1 +.names 7476 26475 26476 +1- 1 +-1 1 +.names 7318 26477 +0 1 +.names 26482 26485 26478 +1- 1 +-1 1 +.names 26478 26479 +1 1 +.names 25879 25959 26480 +11 1 +.names 26480 26481 +1 1 +.names 26481 26482 +0 1 +.names 25962 26256 26483 +11 1 +.names 26483 26484 +1 1 +.names 26484 26485 +0 1 +.names 26474 26486 +0 1 +.names 26479 26487 +0 1 +.names 706 26488 +0 1 +.names 25959 26488 26489 +1- 1 +-1 1 +.names 7469 2413 26490 +1- 1 +-1 1 +.names 26460 25989 26491 +1- 1 +-1 1 +.names 26491 26492 +1 1 +.names 48425 48428 56449 +1- 1 +-1 1 +.names 7473 7015 26494 +11 1 +.names 26492 26495 +0 1 +.names 26501 26503 26496 +1- 1 +-1 1 +.names 26496 26497 +1 1 +.names 26531 26532 26498 +11 1 +.names 26498 26499 +1 1 +.names 26499 26500 +0 1 +.names 25879 26500 26501 +11 1 +.names 376 26502 +0 1 +.names 7445 26502 26503 +11 1 +.names 26512 26515 26504 +1- 1 +-1 1 +.names 26504 26505 +1 1 +.names 26534 26535 26506 +11 1 +.names 26506 26507 +1 1 +.names 26507 26508 +0 1 +.names 26537 26540 26509 +11 1 +.names 26509 26510 +1 1 +.names 26510 26511 +0 1 +.names 26508 26511 26512 +1- 1 +-1 1 +.names 26541 26542 26513 +11 1 +.names 26513 26514 +1 1 +.names 26514 26515 +0 1 +.names 26521 26522 26516 +1- 1 +-1 1 +.names 26516 26517 +1 1 +.names 7477 26518 +0 1 +.names 26518 26519 +1 1 +.names 26519 26520 +0 1 +.names 7455 26520 26521 +1- 1 +-1 1 +.names 7390 26522 +0 1 +.names 26527 26530 26523 +1- 1 +-1 1 +.names 26523 26524 +1 1 +.names 25923 25988 26525 +11 1 +.names 26525 26526 +1 1 +.names 26526 26527 +0 1 +.names 25912 26256 26528 +11 1 +.names 26528 26529 +1 1 +.names 26529 26530 +0 1 +.names 26524 26531 +0 1 +.names 26517 26532 +0 1 +.names 26497 26533 +0 1 +.names 2413 25908 26534 +1- 1 +-1 1 +.names 2413 26518 26535 +1- 1 +-1 1 +.names 682 26536 +0 1 +.names 25988 26536 26537 +1- 1 +-1 1 +.names 48472 48473 56425 +1- 1 +-1 1 +.names 56425 26539 +0 1 +.names 26256 26539 26540 +1- 1 +-1 1 +.names 25912 25563 26541 +1- 1 +-1 1 +.names 25923 2413 26542 +1- 1 +-1 1 +.names 26551 26554 26543 +1- 1 +-1 1 +.names 26543 26544 +1 1 +.names 26587 26588 26545 +11 1 +.names 26545 26546 +1 1 +.names 26546 26547 +0 1 +.names 26585 26586 26548 +11 1 +.names 26548 26549 +1 1 +.names 26549 26550 +0 1 +.names 26547 26550 26551 +1- 1 +-1 1 +.names 26574 26577 26552 +11 1 +.names 26552 26553 +1 1 +.names 26553 26554 +0 1 +.names 26559 26560 26555 +1- 1 +-1 1 +.names 26555 26556 +1 1 +.names 7469 26557 +1 1 +.names 26557 26558 +0 1 +.names 7483 26558 26559 +1- 1 +-1 1 +.names 7369 26560 +0 1 +.names 26278 25989 26561 +11 1 +.names 26561 26562 +1 1 +.names 25912 25952 26563 +11 1 +.names 26563 26564 +1 1 +.names 26569 26570 26565 +11 1 +.names 26565 26566 +1 1 +.names 26582 26583 26567 +1- 1 +-1 1 +.names 26567 26568 +1 1 +.names 26568 26569 +0 1 +.names 26556 26570 +0 1 +.names 26579 26581 26571 +1- 1 +-1 1 +.names 26571 26572 +1 1 +.names 26572 26573 +0 1 +.names 2413 7469 26574 +1- 1 +-1 1 +.names 48502 48528 56432 +1- 1 +-1 1 +.names 56432 26576 +0 1 +.names 26576 25989 26577 +1- 1 +-1 1 +.names 26566 26578 +0 1 +.names 26001 26578 26579 +11 1 +.names 383 26580 +0 1 +.names 7458 26580 26581 +11 1 +.names 26562 26582 +0 1 +.names 26564 26583 +0 1 +.names 689 26584 +0 1 +.names 26278 26584 26585 +1- 1 +-1 1 +.names 25952 26576 26586 +1- 1 +-1 1 +.names 25912 25413 26587 +1- 1 +-1 1 +.names 25978 25413 26588 +1- 1 +-1 1 +.names 26594 26596 26589 +1- 1 +-1 1 +.names 26589 26590 +1 1 +.names 26609 26610 26591 +11 1 +.names 26591 26592 +1 1 +.names 26592 26593 +0 1 +.names 25879 26593 26594 +11 1 +.names 394 26595 +0 1 +.names 7445 26595 26596 +11 1 +.names 26601 26602 26597 +1- 1 +-1 1 +.names 26597 26598 +1 1 +.names 7469 26599 +1 1 +.names 26599 26600 +0 1 +.names 7481 26600 26601 +1- 1 +-1 1 +.names 7336 26602 +0 1 +.names 25900 25912 26603 +11 1 +.names 26603 26604 +1 1 +.names 26518 25988 26605 +11 1 +.names 26605 26606 +1 1 +.names 26621 26622 26607 +1- 1 +-1 1 +.names 26607 26608 +1 1 +.names 26608 26609 +0 1 +.names 26598 26610 +0 1 +.names 26615 26616 26611 +11 1 +.names 26611 26612 +1 1 +.names 48548 48575 56443 +1- 1 +-1 1 +.names 56443 26614 +0 1 +.names 25900 26614 26615 +1- 1 +-1 1 +.names 7469 2413 26616 +1- 1 +-1 1 +.names 26619 26620 26617 +11 1 +.names 26617 26618 +1 1 +.names 26614 26518 26619 +1- 1 +-1 1 +.names 26017 25857 26620 +1- 1 +-1 1 +.names 26604 26621 +0 1 +.names 26606 26622 +0 1 +.names 26629 26618 26623 +11 1 +.names 26623 26624 +1 1 +.names 26624 26625 +0 1 +.names 26590 26626 +0 1 +.names 26631 26632 26627 +11 1 +.names 26627 26628 +1 1 +.names 26612 26628 26629 +11 1 +.names 700 26630 +0 1 +.names 25988 26630 26631 +1- 1 +-1 1 +.names 25912 25857 26632 +1- 1 +-1 1 +.names 26126 26633 +1 1 +.names 26419 26637 26634 +1- 1 +-1 1 +.names 26634 26635 +1 1 +.names 48595 48619 56441 +1- 1 +-1 1 +.names 56441 26637 +0 1 +.names 26643 26645 26638 +1- 1 +-1 1 +.names 26638 26639 +1 1 +.names 26676 26677 26640 +11 1 +.names 26640 26641 +1 1 +.names 26641 26642 +0 1 +.names 26278 26642 26643 +11 1 +.names 698 26644 +0 1 +.names 7492 26644 26645 +11 1 +.names 26648 26650 26646 +11 1 +.names 26646 26647 +1 1 +.names 2413 26126 26648 +1- 1 +-1 1 +.names 392 26649 +0 1 +.names 26034 26649 26650 +1- 1 +-1 1 +.names 26663 26664 26651 +1- 1 +-1 1 +.names 26651 26652 +1 1 +.names 25978 25459 26653 +1- 1 +-1 1 +.names 26653 26654 +1 1 +.names 26654 26655 +0 1 +.names 26637 25989 26656 +1- 1 +-1 1 +.names 26656 26657 +1 1 +.names 26657 26658 +0 1 +.names 26655 26658 26659 +1- 1 +-1 1 +.names 26047 25459 26660 +1- 1 +-1 1 +.names 26660 26661 +1 1 +.names 26661 26662 +0 1 +.names 26659 26662 26663 +1- 1 +-1 1 +.names 26635 26664 +0 1 +.names 26668 26669 26665 +1- 1 +-1 1 +.names 26665 26666 +1 1 +.names 26633 26667 +0 1 +.names 7483 26667 26668 +1- 1 +-1 1 +.names 7342 26669 +0 1 +.names 26419 26034 26670 +11 1 +.names 26670 26671 +1 1 +.names 25989 26047 26672 +11 1 +.names 26672 26673 +1 1 +.names 26681 26682 26674 +1- 1 +-1 1 +.names 26674 26675 +1 1 +.names 26675 26676 +0 1 +.names 26666 26677 +0 1 +.names 26639 26678 +0 1 +.names 26652 26678 26679 +1- 1 +-1 1 +.names 26647 26680 +0 1 +.names 26671 26681 +0 1 +.names 26673 26682 +0 1 +.names 26688 26690 26683 +1- 1 +-1 1 +.names 26683 26684 +1 1 +.names 26715 26716 26685 +11 1 +.names 26685 26686 +1 1 +.names 26686 26687 +0 1 +.names 25959 26687 26688 +11 1 +.names 705 26689 +0 1 +.names 7433 26689 26690 +11 1 +.names 26699 26702 26691 +1- 1 +-1 1 +.names 26691 26692 +1 1 +.names 26718 26720 26693 +11 1 +.names 26693 26694 +1 1 +.names 26694 26695 +0 1 +.names 26725 26726 26696 +11 1 +.names 26696 26697 +1 1 +.names 26697 26698 +0 1 +.names 26695 26698 26699 +1- 1 +-1 1 +.names 26727 26728 26700 +11 1 +.names 26700 26701 +1 1 +.names 26701 26702 +0 1 +.names 26707 26708 26703 +1- 1 +-1 1 +.names 26703 26704 +1 1 +.names 7469 26705 +1 1 +.names 26705 26706 +0 1 +.names 7480 26706 26707 +1- 1 +-1 1 +.names 7321 26708 +0 1 +.names 26419 26047 26709 +11 1 +.names 26709 26710 +1 1 +.names 25911 26001 26711 +11 1 +.names 26711 26712 +1 1 +.names 26721 26722 26713 +1- 1 +-1 1 +.names 26713 26714 +1 1 +.names 26714 26715 +0 1 +.names 26704 26716 +0 1 +.names 26684 26717 +0 1 +.names 2413 7469 26718 +1- 1 +-1 1 +.names 399 26719 +0 1 +.names 26001 26719 26720 +1- 1 +-1 1 +.names 26710 26721 +0 1 +.names 26712 26722 +0 1 +.names 48634 48664 56448 +1- 1 +-1 1 +.names 56448 26724 +0 1 +.names 26419 26724 26725 +1- 1 +-1 1 +.names 26047 25498 26726 +1- 1 +-1 1 +.names 26724 25911 26727 +1- 1 +-1 1 +.names 25923 25498 26728 +1- 1 +-1 1 +.names 26731 26001 26729 +1- 1 +-1 1 +.names 26729 26730 +1 1 +.names 407 26731 +0 1 +.names 26741 26743 26732 +1- 1 +-1 1 +.names 26732 26733 +1 1 +.names 26733 26734 +0 1 +.names 26756 26759 26735 +11 1 +.names 26735 26736 +1 1 +.names 26736 26737 +0 1 +.names 26776 26777 26738 +11 1 +.names 26738 26739 +1 1 +.names 26739 26740 +0 1 +.names 26047 26740 26741 +11 1 +.names 7071 26742 +0 1 +.names 7436 26742 26743 +11 1 +.names 26746 26748 26744 +1- 1 +-1 1 +.names 26744 26745 +1 1 +.names 26730 26746 +0 1 +.names 25952 26747 +1 1 +.names 26747 26748 +0 1 +.names 26746 26753 26749 +1- 1 +-1 1 +.names 26749 26750 +1 1 +.names 56456 26751 +0 1 +.names 26751 26752 +1 1 +.names 26752 26753 +0 1 +.names 26760 26763 26754 +1- 1 +-1 1 +.names 26754 26755 +1 1 +.names 26755 26756 +0 1 +.names 26779 26782 26757 +1- 1 +-1 1 +.names 26757 26758 +1 1 +.names 26758 26759 +0 1 +.names 26745 26750 26760 +11 1 +.names 26783 26784 26761 +11 1 +.names 26761 26762 +1 1 +.names 26762 26763 +0 1 +.names 26768 26769 26764 +1- 1 +-1 1 +.names 26764 26765 +1 1 +.names 7469 26766 +1 1 +.names 26766 26767 +0 1 +.names 7431 26767 26768 +1- 1 +-1 1 +.names 7297 26769 +0 1 +.names 25923 26518 26770 +11 1 +.names 26770 26771 +1 1 +.names 25952 26001 26772 +11 1 +.names 26772 26773 +1 1 +.names 26785 26786 26774 +1- 1 +-1 1 +.names 26774 26775 +1 1 +.names 26775 26776 +0 1 +.names 26765 26777 +0 1 +.names 48681 48702 56456 +1- 1 +-1 1 +.names 7477 56456 26779 +11 1 +.names 26787 25988 26780 +1- 1 +-1 1 +.names 26780 26781 +1 1 +.names 26781 26782 +0 1 +.names 7469 2413 26783 +1- 1 +-1 1 +.names 25923 26742 26784 +1- 1 +-1 1 +.names 26771 26785 +0 1 +.names 26773 26786 +0 1 +.names 713 26787 +0 1 +.names 26793 26795 26788 +1- 1 +-1 1 +.names 26788 26789 +1 1 +.names 26820 26821 26790 +11 1 +.names 26790 26791 +1 1 +.names 26791 26792 +0 1 +.names 25879 26792 26793 +11 1 +.names 397 26794 +0 1 +.names 7445 26794 26795 +11 1 +.names 26804 26807 26796 +1- 1 +-1 1 +.names 26796 26797 +1 1 +.names 26827 26828 26798 +11 1 +.names 26798 26799 +1 1 +.names 26799 26800 +0 1 +.names 26832 26833 26801 +11 1 +.names 26801 26802 +1 1 +.names 26802 26803 +0 1 +.names 26800 26803 26804 +1- 1 +-1 1 +.names 26825 26826 26805 +11 1 +.names 26805 26806 +1 1 +.names 26806 26807 +0 1 +.names 26812 26813 26808 +1- 1 +-1 1 +.names 26808 26809 +1 1 +.names 26256 26810 +1 1 +.names 26810 26811 +0 1 +.names 7480 26811 26812 +1- 1 +-1 1 +.names 7327 26813 +0 1 +.names 26278 26126 26814 +11 1 +.names 26814 26815 +1 1 +.names 26518 26047 26816 +11 1 +.names 26816 26817 +1 1 +.names 26829 26830 26818 +1- 1 +-1 1 +.names 26818 26819 +1 1 +.names 26819 26820 +0 1 +.names 26809 26821 +0 1 +.names 26789 26822 +0 1 +.names 48743 48746 56446 +1- 1 +-1 1 +.names 56446 26824 +0 1 +.names 26824 26518 26825 +1- 1 +-1 1 +.names 25923 25539 26826 +1- 1 +-1 1 +.names 26256 26824 26827 +1- 1 +-1 1 +.names 2413 26126 26828 +1- 1 +-1 1 +.names 26815 26829 +0 1 +.names 26817 26830 +0 1 +.names 703 26831 +0 1 +.names 26278 26831 26832 +1- 1 +-1 1 +.names 26047 25539 26833 +1- 1 +-1 1 +.names 26839 26841 26834 +1- 1 +-1 1 +.names 26834 26835 +1 1 +.names 26852 26853 26836 +11 1 +.names 26836 26837 +1 1 +.names 26837 26838 +0 1 +.names 26034 26838 26839 +11 1 +.names 378 26840 +0 1 +.names 7457 26840 26841 +11 1 +.names 26846 26847 26842 +1- 1 +-1 1 +.names 26842 26843 +1 1 +.names 26056 26844 +1 1 +.names 26844 26845 +0 1 +.names 7483 26845 26846 +1- 1 +-1 1 +.names 7384 26847 +0 1 +.names 26278 26126 26848 +11 1 +.names 26848 26849 +1 1 +.names 26869 26870 26850 +1- 1 +-1 1 +.names 26850 26851 +1 1 +.names 26851 26852 +0 1 +.names 26843 26853 +0 1 +.names 26878 26879 26854 +1- 1 +-1 1 +.names 26854 26855 +1 1 +.names 26835 26856 +0 1 +.names 26083 25962 26857 +11 1 +.names 26857 26858 +1 1 +.names 26863 26864 26859 +11 1 +.names 26859 26860 +1 1 +.names 48785 48788 56427 +1- 1 +-1 1 +.names 56427 26862 +0 1 +.names 26056 26862 26863 +1- 1 +-1 1 +.names 2413 26126 26864 +1- 1 +-1 1 +.names 26867 26868 26865 +11 1 +.names 26865 26866 +1 1 +.names 26862 26083 26867 +1- 1 +-1 1 +.names 25978 25816 26868 +1- 1 +-1 1 +.names 26849 26869 +0 1 +.names 26858 26870 +0 1 +.names 26874 26875 26871 +11 1 +.names 26871 26872 +1 1 +.names 684 26873 +0 1 +.names 26278 26873 26874 +1- 1 +-1 1 +.names 25962 25816 26875 +1- 1 +-1 1 +.names 26860 26876 +0 1 +.names 26872 26877 +0 1 +.names 26876 26877 26878 +1- 1 +-1 1 +.names 26866 26879 +0 1 +.names 26885 26887 26880 +1- 1 +-1 1 +.names 26880 26881 +1 1 +.names 26910 26911 26882 +11 1 +.names 26882 26883 +1 1 +.names 26883 26884 +0 1 +.names 25988 26884 26885 +11 1 +.names 687 26886 +0 1 +.names 7431 26886 26887 +11 1 +.names 26896 26899 26888 +1- 1 +-1 1 +.names 26888 26889 +1 1 +.names 26917 26919 26890 +11 1 +.names 26890 26891 +1 1 +.names 26891 26892 +0 1 +.names 26922 26923 26893 +11 1 +.names 26893 26894 +1 1 +.names 26894 26895 +0 1 +.names 26892 26895 26896 +1- 1 +-1 1 +.names 26915 26916 26897 +11 1 +.names 26897 26898 +1 1 +.names 26898 26899 +0 1 +.names 26904 26905 26900 +1- 1 +-1 1 +.names 26900 26901 +1 1 +.names 7469 26902 +1 1 +.names 26902 26903 +0 1 +.names 7481 26903 26904 +1- 1 +-1 1 +.names 7375 26905 +0 1 +.names 25989 25879 26906 +11 1 +.names 26906 26907 +1 1 +.names 26924 26925 26908 +1- 1 +-1 1 +.names 26908 26909 +1 1 +.names 26909 26910 +0 1 +.names 26901 26911 +0 1 +.names 26881 26912 +0 1 +.names 48824 48850 56430 +1- 1 +-1 1 +.names 56430 26914 +0 1 +.names 25989 26914 26915 +1- 1 +-1 1 +.names 26017 25383 26916 +1- 1 +-1 1 +.names 7469 2413 26917 +1- 1 +-1 1 +.names 381 26918 +0 1 +.names 25879 26918 26919 +1- 1 +-1 1 +.names 26155 25962 26920 +11 1 +.names 26920 26921 +1 1 +.names 26155 26914 26922 +1- 1 +-1 1 +.names 25962 25383 26923 +1- 1 +-1 1 +.names 26921 26924 +0 1 +.names 26907 26925 +0 1 +.names 26001 26928 26926 +1- 1 +-1 1 +.names 26926 26927 +1 1 +.names 389 26928 +0 1 +.names 26980 26981 26929 +11 1 +.names 26929 26930 +1 1 +.names 26930 26931 +0 1 +.names 26938 26939 26932 +1- 1 +-1 1 +.names 26932 26933 +1 1 +.names 26933 26934 +0 1 +.names 26959 26962 26935 +11 1 +.names 26935 26936 +1 1 +.names 26936 26937 +0 1 +.names 25923 26937 26938 +11 1 +.names 7480 25842 26939 +11 1 +.names 26942 26944 26940 +1- 1 +-1 1 +.names 26940 26941 +1 1 +.names 26927 26942 +0 1 +.names 26155 26943 +1 1 +.names 26943 26944 +0 1 +.names 26942 26949 26945 +1- 1 +-1 1 +.names 26945 26946 +1 1 +.names 56438 26947 +0 1 +.names 26947 26948 +1 1 +.names 26948 26949 +0 1 +.names 48871 48890 56438 +1- 1 +-1 1 +.names 26955 26958 26951 +1- 1 +-1 1 +.names 26951 26952 +1 1 +.names 26001 25988 26953 +11 1 +.names 26953 26954 +1 1 +.names 26954 26955 +0 1 +.names 25962 26155 26956 +11 1 +.names 26956 26957 +1 1 +.names 26957 26958 +0 1 +.names 26952 26959 +0 1 +.names 26976 26977 26960 +1- 1 +-1 1 +.names 26960 26961 +1 1 +.names 26961 26962 +0 1 +.names 26966 26967 26963 +11 1 +.names 26963 26964 +1 1 +.names 695 26965 +0 1 +.names 25988 26965 26966 +1- 1 +-1 1 +.names 7469 2413 26967 +1- 1 +-1 1 +.names 25962 25842 26968 +1- 1 +-1 1 +.names 26968 26969 +1 1 +.names 26972 26973 26970 +1- 1 +-1 1 +.names 26970 26971 +1 1 +.names 7478 56438 26972 +11 1 +.names 26969 26973 +0 1 +.names 7469 26974 +1 1 +.names 26974 26975 +0 1 +.names 7478 26975 26976 +1- 1 +-1 1 +.names 7351 26977 +0 1 +.names 26982 26983 26978 +1- 1 +-1 1 +.names 26978 26979 +1 1 +.names 26979 26980 +0 1 +.names 26971 26981 +0 1 +.names 26941 26946 26982 +11 1 +.names 26964 26983 +0 1 +.names 26989 26991 26984 +1- 1 +-1 1 +.names 26984 26985 +1 1 +.names 27016 27017 26986 +11 1 +.names 26986 26987 +1 1 +.names 26987 26988 +0 1 +.names 26001 26988 26989 +11 1 +.names 390 26990 +0 1 +.names 7458 26990 26991 +11 1 +.names 27000 27003 26992 +1- 1 +-1 1 +.names 26992 26993 +1 1 +.names 27021 27022 26994 +11 1 +.names 26994 26995 +1 1 +.names 26995 26996 +0 1 +.names 27028 27029 26997 +11 1 +.names 26997 26998 +1 1 +.names 26998 26999 +0 1 +.names 26996 26999 27000 +1- 1 +-1 1 +.names 27023 27024 27001 +11 1 +.names 27001 27002 +1 1 +.names 27002 27003 +0 1 +.names 27008 27009 27004 +1- 1 +-1 1 +.names 27004 27005 +1 1 +.names 26056 27006 +1 1 +.names 27006 27007 +0 1 +.names 7480 27007 27008 +1- 1 +-1 1 +.names 7348 27009 +0 1 +.names 25959 26126 27010 +11 1 +.names 27010 27011 +1 1 +.names 25911 26047 27012 +11 1 +.names 27012 27013 +1 1 +.names 27025 27026 27014 +1- 1 +-1 1 +.names 27014 27015 +1 1 +.names 27015 27016 +0 1 +.names 27005 27017 +0 1 +.names 26985 27018 +0 1 +.names 48930 48931 56439 +1- 1 +-1 1 +.names 56439 27020 +0 1 +.names 26056 27020 27021 +1- 1 +-1 1 +.names 2413 26126 27022 +1- 1 +-1 1 +.names 27020 25911 27023 +1- 1 +-1 1 +.names 25923 25422 27024 +1- 1 +-1 1 +.names 27011 27025 +0 1 +.names 27013 27026 +0 1 +.names 696 27027 +0 1 +.names 25959 27027 27028 +1- 1 +-1 1 +.names 26047 25422 27029 +1- 1 +-1 1 +.names 27035 27037 27030 +1- 1 +-1 1 +.names 27030 27031 +1 1 +.names 27062 27063 27032 +11 1 +.names 27032 27033 +1 1 +.names 27033 27034 +0 1 +.names 26034 27034 27035 +11 1 +.names 404 27036 +0 1 +.names 7457 27036 27037 +11 1 +.names 27046 27049 27038 +1- 1 +-1 1 +.names 27038 27039 +1 1 +.names 27071 27072 27040 +11 1 +.names 27040 27041 +1 1 +.names 27041 27042 +0 1 +.names 27074 27075 27043 +11 1 +.names 27043 27044 +1 1 +.names 27044 27045 +0 1 +.names 27042 27045 27046 +1- 1 +-1 1 +.names 27067 27068 27047 +11 1 +.names 27047 27048 +1 1 +.names 27048 27049 +0 1 +.names 27054 27055 27050 +1- 1 +-1 1 +.names 27050 27051 +1 1 +.names 25900 27052 +1 1 +.names 27052 27053 +0 1 +.names 7483 27053 27054 +1- 1 +-1 1 +.names 7306 27055 +0 1 +.names 25959 26126 27056 +11 1 +.names 27056 27057 +1 1 +.names 26518 26047 27058 +11 1 +.names 27058 27059 +1 1 +.names 27069 27070 27060 +1- 1 +-1 1 +.names 27060 27061 +1 1 +.names 27061 27062 +0 1 +.names 27051 27063 +0 1 +.names 27031 27064 +0 1 +.names 49006 49007 56453 +1- 1 +-1 1 +.names 56453 27066 +0 1 +.names 27066 26518 27067 +1- 1 +-1 1 +.names 25978 25446 27068 +1- 1 +-1 1 +.names 27057 27069 +0 1 +.names 27059 27070 +0 1 +.names 25900 27066 27071 +1- 1 +-1 1 +.names 2413 26126 27072 +1- 1 +-1 1 +.names 710 27073 +0 1 +.names 25959 27073 27074 +1- 1 +-1 1 +.names 26047 25446 27075 +1- 1 +-1 1 +.names 27081 27083 27076 +1- 1 +-1 1 +.names 27076 27077 +1 1 +.names 27108 27109 27078 +11 1 +.names 27078 27079 +1 1 +.names 27079 27080 +0 1 +.names 26278 27080 27081 +11 1 +.names 694 27082 +0 1 +.names 7492 27082 27083 +11 1 +.names 27092 27095 27084 +1- 1 +-1 1 +.names 27084 27085 +1 1 +.names 27111 27113 27086 +11 1 +.names 27086 27087 +1 1 +.names 27087 27088 +0 1 +.names 27120 27121 27089 +11 1 +.names 27089 27090 +1 1 +.names 27090 27091 +0 1 +.names 27088 27091 27092 +1- 1 +-1 1 +.names 27116 27117 27093 +11 1 +.names 27093 27094 +1 1 +.names 27094 27095 +0 1 +.names 27100 27101 27096 +1- 1 +-1 1 +.names 27096 27097 +1 1 +.names 25908 27098 +1 1 +.names 27098 27099 +0 1 +.names 7481 27099 27100 +1- 1 +-1 1 +.names 7354 27101 +0 1 +.names 26419 26001 27102 +11 1 +.names 27102 27103 +1 1 +.names 25911 25912 27104 +11 1 +.names 27104 27105 +1 1 +.names 27118 27119 27106 +1- 1 +-1 1 +.names 27106 27107 +1 1 +.names 27107 27108 +0 1 +.names 27097 27109 +0 1 +.names 27077 27110 +0 1 +.names 2413 25908 27111 +1- 1 +-1 1 +.names 388 27112 +0 1 +.names 26001 27112 27113 +1- 1 +-1 1 +.names 49033 49034 56437 +1- 1 +-1 1 +.names 56437 27115 +0 1 +.names 27115 25911 27116 +1- 1 +-1 1 +.names 26017 25723 27117 +1- 1 +-1 1 +.names 27103 27118 +0 1 +.names 27105 27119 +0 1 +.names 26419 27115 27120 +1- 1 +-1 1 +.names 25912 25723 27121 +1- 1 +-1 1 +.names 27127 27129 27122 +1- 1 +-1 1 +.names 27122 27123 +1 1 +.names 27154 27155 27124 +11 1 +.names 27124 27125 +1 1 +.names 27125 27126 +0 1 +.names 25879 27126 27127 +11 1 +.names 402 27128 +0 1 +.names 7445 27128 27129 +11 1 +.names 27138 27141 27130 +1- 1 +-1 1 +.names 27130 27131 +1 1 +.names 27166 27167 27132 +11 1 +.names 27132 27133 +1 1 +.names 27133 27134 +0 1 +.names 27164 27165 27135 +11 1 +.names 27135 27136 +1 1 +.names 27136 27137 +0 1 +.names 27134 27137 27138 +1- 1 +-1 1 +.names 27161 27162 27139 +11 1 +.names 27139 27140 +1 1 +.names 27140 27141 +0 1 +.names 27146 27147 27142 +1- 1 +-1 1 +.names 27142 27143 +1 1 +.names 26256 27144 +1 1 +.names 27144 27145 +0 1 +.names 7481 27145 27146 +1- 1 +-1 1 +.names 7312 27147 +0 1 +.names 26278 25908 27148 +11 1 +.names 27148 27149 +1 1 +.names 25911 26047 27150 +11 1 +.names 27150 27151 +1 1 +.names 27157 27158 27152 +1- 1 +-1 1 +.names 27152 27153 +1 1 +.names 27153 27154 +0 1 +.names 27143 27155 +0 1 +.names 27123 27156 +0 1 +.names 27149 27157 +0 1 +.names 27151 27158 +0 1 +.names 49059 49089 56451 +1- 1 +-1 1 +.names 56451 27160 +0 1 +.names 27160 25911 27161 +1- 1 +-1 1 +.names 26017 25739 27162 +1- 1 +-1 1 +.names 708 27163 +0 1 +.names 26278 27163 27164 +1- 1 +-1 1 +.names 26047 25739 27165 +1- 1 +-1 1 +.names 26256 27160 27166 +1- 1 +-1 1 +.names 2413 25908 27167 +1- 1 +-1 1 +.names 27170 25879 27168 +1- 1 +-1 1 +.names 27168 27169 +1 1 +.names 403 27170 +0 1 +.names 27194 27197 27171 +11 1 +.names 27171 27172 +1 1 +.names 27172 27173 +0 1 +.names 27180 27181 27174 +1- 1 +-1 1 +.names 27174 27175 +1 1 +.names 27175 27176 +0 1 +.names 27216 27217 27177 +11 1 +.names 27177 27178 +1 1 +.names 27178 27179 +0 1 +.names 25912 27179 27180 +11 1 +.names 7438 25870 27181 +11 1 +.names 27184 27186 27182 +1- 1 +-1 1 +.names 27182 27183 +1 1 +.names 27169 27184 +0 1 +.names 25900 27185 +1 1 +.names 27185 27186 +0 1 +.names 27184 27191 27187 +1- 1 +-1 1 +.names 27187 27188 +1 1 +.names 56452 27189 +0 1 +.names 27189 27190 +1 1 +.names 27190 27191 +0 1 +.names 27198 27201 27192 +1- 1 +-1 1 +.names 27192 27193 +1 1 +.names 27193 27194 +0 1 +.names 27221 27224 27195 +1- 1 +-1 1 +.names 27195 27196 +1 1 +.names 27196 27197 +0 1 +.names 27183 27188 27198 +11 1 +.names 27218 27219 27199 +11 1 +.names 27199 27200 +1 1 +.names 27200 27201 +0 1 +.names 27206 27207 27202 +1- 1 +-1 1 +.names 27202 27203 +1 1 +.names 25908 27204 +1 1 +.names 27204 27205 +0 1 +.names 7431 27205 27206 +1- 1 +-1 1 +.names 7309 27207 +0 1 +.names 27212 27215 27208 +1- 1 +-1 1 +.names 27208 27209 +1 1 +.names 26083 25879 27210 +11 1 +.names 27210 27211 +1 1 +.names 27211 27212 +0 1 +.names 25900 26017 27213 +11 1 +.names 27213 27214 +1 1 +.names 27214 27215 +0 1 +.names 27209 27216 +0 1 +.names 27203 27217 +0 1 +.names 25908 2413 27218 +1- 1 +-1 1 +.names 26017 25870 27219 +1- 1 +-1 1 +.names 49113 49139 56452 +1- 1 +-1 1 +.names 7478 56452 27221 +11 1 +.names 27225 25988 27222 +1- 1 +-1 1 +.names 27222 27223 +1 1 +.names 27223 27224 +0 1 +.names 709 27225 +0 1 +.names 27231 27233 27226 +1- 1 +-1 1 +.names 27226 27227 +1 1 +.names 27258 27259 27228 +11 1 +.names 27228 27229 +1 1 +.names 27229 27230 +0 1 +.names 26034 27230 27231 +11 1 +.names 379 27232 +0 1 +.names 7457 27232 27233 +11 1 +.names 27242 27245 27234 +1- 1 +-1 1 +.names 27234 27235 +1 1 +.names 27267 27268 27236 +11 1 +.names 27236 27237 +1 1 +.names 27237 27238 +0 1 +.names 27270 27271 27239 +11 1 +.names 27239 27240 +1 1 +.names 27240 27241 +0 1 +.names 27238 27241 27242 +1- 1 +-1 1 +.names 27263 27264 27243 +11 1 +.names 27243 27244 +1 1 +.names 27244 27245 +0 1 +.names 27250 27251 27246 +1- 1 +-1 1 +.names 27246 27247 +1 1 +.names 25900 27248 +1 1 +.names 27248 27249 +0 1 +.names 7483 27249 27250 +1- 1 +-1 1 +.names 7381 27251 +0 1 +.names 26278 26126 27252 +11 1 +.names 27252 27253 +1 1 +.names 26518 25912 27254 +11 1 +.names 27254 27255 +1 1 +.names 27265 27266 27256 +1- 1 +-1 1 +.names 27256 27257 +1 1 +.names 27257 27258 +0 1 +.names 27247 27259 +0 1 +.names 27227 27260 +0 1 +.names 49168 49171 56428 +1- 1 +-1 1 +.names 56428 27262 +0 1 +.names 27262 26518 27263 +1- 1 +-1 1 +.names 25978 25590 27264 +1- 1 +-1 1 +.names 27253 27265 +0 1 +.names 27255 27266 +0 1 +.names 25900 27262 27267 +1- 1 +-1 1 +.names 2413 26126 27268 +1- 1 +-1 1 +.names 685 27269 +0 1 +.names 26278 27269 27270 +1- 1 +-1 1 +.names 25912 25590 27271 +1- 1 +-1 1 +.names 27277 27279 27272 +1- 1 +-1 1 +.names 27272 27273 +1 1 +.names 27304 27305 27274 +11 1 +.names 27274 27275 +1 1 +.names 27275 27276 +0 1 +.names 26034 27276 27277 +11 1 +.names 380 27278 +0 1 +.names 7457 27278 27279 +11 1 +.names 27288 27291 27280 +1- 1 +-1 1 +.names 27280 27281 +1 1 +.names 27313 27314 27282 +11 1 +.names 27282 27283 +1 1 +.names 27283 27284 +0 1 +.names 27316 27317 27285 +11 1 +.names 27285 27286 +1 1 +.names 27286 27287 +0 1 +.names 27284 27287 27288 +1- 1 +-1 1 +.names 27309 27310 27289 +11 1 +.names 27289 27290 +1 1 +.names 27290 27291 +0 1 +.names 27296 27297 27292 +1- 1 +-1 1 +.names 27292 27293 +1 1 +.names 26056 27294 +1 1 +.names 27294 27295 +0 1 +.names 7481 27295 27296 +1- 1 +-1 1 +.names 7378 27297 +0 1 +.names 25907 25908 27298 +11 1 +.names 27298 27299 +1 1 +.names 25911 25912 27300 +11 1 +.names 27300 27301 +1 1 +.names 27311 27312 27302 +1- 1 +-1 1 +.names 27302 27303 +1 1 +.names 27303 27304 +0 1 +.names 27293 27305 +0 1 +.names 27273 27306 +0 1 +.names 49214 49217 56429 +1- 1 +-1 1 +.names 56429 27308 +0 1 +.names 27308 25911 27309 +1- 1 +-1 1 +.names 26017 25346 27310 +1- 1 +-1 1 +.names 27299 27311 +0 1 +.names 27301 27312 +0 1 +.names 26056 27308 27313 +1- 1 +-1 1 +.names 2413 25908 27314 +1- 1 +-1 1 +.names 686 27315 +0 1 +.names 25907 27315 27316 +1- 1 +-1 1 +.names 25912 25346 27317 +1- 1 +-1 1 +.names 27324 27325 27318 +1- 1 +-1 1 +.names 27318 27319 +1 1 +.names 7468 27320 +0 1 +.names 27348 27349 27321 +11 1 +.names 27321 27322 +1 1 +.names 27322 27323 +0 1 +.names 27320 27323 27324 +11 1 +.names 7468 2413 27325 +11 1 +.names 27334 27337 27326 +1- 1 +-1 1 +.names 27326 27327 +1 1 +.names 27358 27360 27328 +11 1 +.names 27328 27329 +1 1 +.names 27329 27330 +0 1 +.names 27363 27364 27331 +11 1 +.names 27331 27332 +1 1 +.names 27332 27333 +0 1 +.names 27330 27333 27334 +1- 1 +-1 1 +.names 27352 27355 27335 +11 1 +.names 27335 27336 +1 1 +.names 27336 27337 +0 1 +.names 27341 27343 27338 +1- 1 +-1 1 +.names 27338 27339 +1 1 +.names 7345 27340 +0 1 +.names 7445 27340 27341 +1- 1 +-1 1 +.names 25907 27342 +1 1 +.names 27342 27343 +0 1 +.names 25923 25989 27344 +11 1 +.names 27344 27345 +1 1 +.names 27361 27362 27346 +1- 1 +-1 1 +.names 27346 27347 +1 1 +.names 27347 27348 +0 1 +.names 27339 27349 +0 1 +.names 27319 27350 +0 1 +.names 697 27351 +0 1 +.names 25907 27351 27352 +1- 1 +-1 1 +.names 49262 49265 56440 +1- 1 +-1 1 +.names 56440 27354 +0 1 +.names 25989 27354 27355 +1- 1 +-1 1 +.names 25962 26155 27356 +11 1 +.names 27356 27357 +1 1 +.names 25962 25427 27358 +1- 1 +-1 1 +.names 391 27359 +0 1 +.names 25879 27359 27360 +1- 1 +-1 1 +.names 27345 27361 +0 1 +.names 27357 27362 +0 1 +.names 25923 25427 27363 +1- 1 +-1 1 +.names 26155 27354 27364 +1- 1 +-1 1 +.names 27370 27372 27365 +1- 1 +-1 1 +.names 27365 27366 +1 1 +.names 27385 27386 27367 +11 1 +.names 27367 27368 +1 1 +.names 27368 27369 +0 1 +.names 26034 27369 27370 +11 1 +.names 396 27371 +0 1 +.names 7457 27371 27372 +11 1 +.names 27377 27378 27373 +1- 1 +-1 1 +.names 27373 27374 +1 1 +.names 7469 27375 +1 1 +.names 27375 27376 +0 1 +.names 7480 27376 27377 +1- 1 +-1 1 +.names 7330 27378 +0 1 +.names 25907 25989 27379 +11 1 +.names 27379 27380 +1 1 +.names 26047 26155 27381 +11 1 +.names 27381 27382 +1 1 +.names 27409 27410 27383 +1- 1 +-1 1 +.names 27383 27384 +1 1 +.names 27384 27385 +0 1 +.names 27374 27386 +0 1 +.names 27407 27408 27387 +1- 1 +-1 1 +.names 27387 27388 +1 1 +.names 27366 27389 +0 1 +.names 27393 27396 27390 +11 1 +.names 27390 27391 +1 1 +.names 702 27392 +0 1 +.names 25907 27392 27393 +1- 1 +-1 1 +.names 49298 49322 56445 +1- 1 +-1 1 +.names 56445 27395 +0 1 +.names 26155 27395 27396 +1- 1 +-1 1 +.names 27399 27400 27397 +11 1 +.names 27397 27398 +1 1 +.names 26047 25370 27399 +1- 1 +-1 1 +.names 25923 25370 27400 +1- 1 +-1 1 +.names 27403 27404 27401 +11 1 +.names 27401 27402 +1 1 +.names 2413 7469 27403 +1- 1 +-1 1 +.names 27395 25989 27404 +1- 1 +-1 1 +.names 27398 27405 +0 1 +.names 27391 27406 +0 1 +.names 27405 27406 27407 +1- 1 +-1 1 +.names 27402 27408 +0 1 +.names 27380 27409 +0 1 +.names 27382 27410 +0 1 +.names 27416 27418 27411 +1- 1 +-1 1 +.names 27411 27412 +1 1 +.names 27443 27444 27413 +11 1 +.names 27413 27414 +1 1 +.names 27414 27415 +0 1 +.names 26001 27415 27416 +11 1 +.names 405 27417 +0 1 +.names 7458 27417 27418 +11 1 +.names 27427 27430 27419 +1- 1 +-1 1 +.names 27419 27420 +1 1 +.names 27448 27449 27421 +11 1 +.names 27421 27422 +1 1 +.names 27422 27423 +0 1 +.names 27453 27454 27424 +11 1 +.names 27424 27425 +1 1 +.names 27425 27426 +0 1 +.names 27423 27426 27427 +1- 1 +-1 1 +.names 27450 27451 27428 +11 1 +.names 27428 27429 +1 1 +.names 27429 27430 +0 1 +.names 27435 27436 27431 +1- 1 +-1 1 +.names 27431 27432 +1 1 +.names 26256 27433 +1 1 +.names 27433 27434 +0 1 +.names 7480 27434 27435 +1- 1 +-1 1 +.names 7303 27436 +0 1 +.names 25907 26126 27437 +11 1 +.names 27437 27438 +1 1 +.names 25911 25912 27439 +11 1 +.names 27439 27440 +1 1 +.names 27455 27456 27441 +1- 1 +-1 1 +.names 27441 27442 +1 1 +.names 27442 27443 +0 1 +.names 27432 27444 +0 1 +.names 27412 27445 +0 1 +.names 49354 49357 56454 +1- 1 +-1 1 +.names 56454 27447 +0 1 +.names 26256 27447 27448 +1- 1 +-1 1 +.names 2413 26126 27449 +1- 1 +-1 1 +.names 27447 25911 27450 +1- 1 +-1 1 +.names 25923 25663 27451 +1- 1 +-1 1 +.names 711 27452 +0 1 +.names 25907 27452 27453 +1- 1 +-1 1 +.names 25912 25663 27454 +1- 1 +-1 1 +.names 27438 27455 +0 1 +.names 27440 27456 +0 1 +.names 7507 27457 +0 1 +.names 25389 27458 +1 1 +.names 27458 27459 +0 1 +.names 27457 27459 27460 +11 1 +.names 624 27461 +0 1 +.names 27461 27462 +1 1 +.names 27462 27463 +0 1 +.names 7507 27463 27464 +11 1 +.names 7501 27465 +0 1 +.names 25493 27466 +1 1 +.names 27466 27467 +0 1 +.names 27465 27467 27468 +11 1 +.names 640 27469 +0 1 +.names 27469 27470 +1 1 +.names 27470 27471 +0 1 +.names 7501 27471 27472 +11 1 +.names 25467 27473 +1 1 +.names 27473 27474 +0 1 +.names 27457 27474 27475 +11 1 +.names 635 27476 +0 1 +.names 27476 27477 +1 1 +.names 27477 27478 +0 1 +.names 7507 27478 27479 +11 1 +.names 27483 27487 56729 +1- 1 +-1 1 +.names 26222 27481 +1 1 +.names 27481 27482 +0 1 +.names 27465 27482 27483 +11 1 +.names 648 27484 +0 1 +.names 27484 27485 +1 1 +.names 27485 27486 +0 1 +.names 7501 27486 27487 +11 1 +.names 7502 27488 +0 1 +.names 25563 27489 +1 1 +.names 27489 27490 +0 1 +.names 27488 27490 27491 +11 1 +.names 618 27492 +0 1 +.names 27492 27493 +1 1 +.names 27493 27494 +0 1 +.names 7502 27494 27495 +11 1 +.names 27500 27504 56700 +1- 1 +-1 1 +.names 7504 27497 +0 1 +.names 25799 27498 +1 1 +.names 27498 27499 +0 1 +.names 27497 27499 27500 +11 1 +.names 619 27501 +0 1 +.names 27501 27502 +1 1 +.names 27502 27503 +0 1 +.names 7504 27503 27504 +11 1 +.names 25400 27505 +1 1 +.names 27505 27506 +0 1 +.names 27497 27506 27507 +11 1 +.names 626 27508 +0 1 +.names 27508 27509 +1 1 +.names 27509 27510 +0 1 +.names 7504 27510 27511 +11 1 +.names 25773 27512 +1 1 +.names 27512 27513 +0 1 +.names 27465 27513 27514 +11 1 +.names 628 27515 +0 1 +.names 27515 27516 +1 1 +.names 27516 27517 +0 1 +.names 7501 27517 27518 +11 1 +.names 25688 27519 +1 1 +.names 27519 27520 +0 1 +.names 27497 27520 27521 +11 1 +.names 637 27522 +0 1 +.names 27522 27523 +1 1 +.names 27523 27524 +0 1 +.names 7504 27524 27525 +11 1 +.names 25513 27526 +1 1 +.names 27526 27527 +0 1 +.names 27457 27527 27528 +11 1 +.names 627 27529 +0 1 +.names 27529 27530 +1 1 +.names 27530 27531 +0 1 +.names 7507 27531 27532 +11 1 +.names 7506 27533 +0 1 +.names 25790 27534 +1 1 +.names 27534 27535 +0 1 +.names 27533 27535 27536 +11 1 +.names 643 27537 +0 1 +.names 27537 27538 +1 1 +.names 27538 27539 +0 1 +.names 7506 27539 27540 +11 1 +.names 25705 27541 +1 1 +.names 27541 27542 +0 1 +.names 27488 27542 27543 +11 1 +.names 629 27544 +0 1 +.names 27544 27545 +1 1 +.names 27545 27546 +0 1 +.names 7502 27546 27547 +11 1 +.names 25756 27548 +1 1 +.names 27548 27549 +0 1 +.names 27488 27549 27550 +11 1 +.names 642 27551 +0 1 +.names 27551 27552 +1 1 +.names 27552 27553 +0 1 +.names 7502 27553 27554 +11 1 +.names 25816 27555 +1 1 +.names 27555 27556 +0 1 +.names 27488 27556 27557 +11 1 +.names 620 27558 +0 1 +.names 27558 27559 +1 1 +.names 27559 27560 +0 1 +.names 7502 27560 27561 +11 1 +.names 25383 27562 +1 1 +.names 27562 27563 +0 1 +.names 27533 27563 27564 +11 1 +.names 623 27565 +0 1 +.names 27565 27566 +1 1 +.names 27566 27567 +0 1 +.names 7506 27567 27568 +11 1 +.names 25413 27569 +1 1 +.names 27569 27570 +0 1 +.names 27465 27570 27571 +11 1 +.names 625 27572 +0 1 +.names 27572 27573 +1 1 +.names 27573 27574 +0 1 +.names 7501 27574 27575 +11 1 +.names 25857 27576 +1 1 +.names 27576 27577 +0 1 +.names 27533 27577 27578 +11 1 +.names 636 27579 +0 1 +.names 27579 27580 +1 1 +.names 27580 27581 +0 1 +.names 7506 27581 27582 +11 1 +.names 25459 27583 +1 1 +.names 27583 27584 +0 1 +.names 27497 27584 27585 +11 1 +.names 634 27586 +0 1 +.names 27586 27587 +1 1 +.names 27587 27588 +0 1 +.names 7504 27588 27589 +11 1 +.names 25498 27590 +1 1 +.names 27590 27591 +0 1 +.names 27497 27591 27592 +11 1 +.names 641 27593 +0 1 +.names 27593 27594 +1 1 +.names 27594 27595 +0 1 +.names 7504 27595 27596 +11 1 +.names 26742 27597 +1 1 +.names 27597 27598 +0 1 +.names 27457 27598 27599 +11 1 +.names 649 27600 +0 1 +.names 27600 27601 +1 1 +.names 27601 27602 +0 1 +.names 7507 27602 27603 +11 1 +.names 7505 27604 +0 1 +.names 25539 27605 +1 1 +.names 27605 27606 +0 1 +.names 27604 27606 27607 +11 1 +.names 639 27608 +0 1 +.names 27608 27609 +1 1 +.names 27609 27610 +0 1 +.names 7505 27610 27611 +11 1 +.names 25842 27612 +1 1 +.names 27612 27613 +0 1 +.names 27604 27613 27614 +11 1 +.names 631 27615 +0 1 +.names 27615 27616 +1 1 +.names 27616 27617 +0 1 +.names 7505 27617 27618 +11 1 +.names 25422 27619 +1 1 +.names 27619 27620 +0 1 +.names 27533 27620 27621 +11 1 +.names 632 27622 +0 1 +.names 27622 27623 +1 1 +.names 27623 27624 +0 1 +.names 7506 27624 27625 +11 1 +.names 25446 27626 +1 1 +.names 27626 27627 +0 1 +.names 27465 27627 27628 +11 1 +.names 646 27629 +0 1 +.names 27629 27630 +1 1 +.names 27630 27631 +0 1 +.names 7501 27631 27632 +11 1 +.names 25723 27633 +1 1 +.names 27633 27634 +0 1 +.names 27488 27634 27635 +11 1 +.names 630 27636 +0 1 +.names 27636 27637 +1 1 +.names 27637 27638 +0 1 +.names 7502 27638 27639 +11 1 +.names 25739 27640 +1 1 +.names 27640 27641 +0 1 +.names 27457 27641 27642 +11 1 +.names 644 27643 +0 1 +.names 27643 27644 +1 1 +.names 27644 27645 +0 1 +.names 7507 27645 27646 +11 1 +.names 25870 27647 +1 1 +.names 27647 27648 +0 1 +.names 27457 27648 27649 +11 1 +.names 645 27650 +0 1 +.names 27650 27651 +1 1 +.names 27651 27652 +0 1 +.names 7507 27652 27653 +11 1 +.names 25590 27654 +1 1 +.names 27654 27655 +0 1 +.names 27604 27655 27656 +11 1 +.names 621 27657 +0 1 +.names 27657 27658 +1 1 +.names 27658 27659 +0 1 +.names 7505 27659 27660 +11 1 +.names 25346 27661 +1 1 +.names 27661 27662 +0 1 +.names 27604 27662 27663 +11 1 +.names 622 27664 +0 1 +.names 27664 27665 +1 1 +.names 27665 27666 +0 1 +.names 7505 27666 27667 +11 1 +.names 25427 27668 +1 1 +.names 27668 27669 +0 1 +.names 27604 27669 27670 +11 1 +.names 633 27671 +0 1 +.names 27671 27672 +1 1 +.names 27672 27673 +0 1 +.names 7505 27673 27674 +11 1 +.names 25370 27675 +1 1 +.names 27675 27676 +0 1 +.names 27533 27676 27677 +11 1 +.names 638 27678 +0 1 +.names 27678 27679 +1 1 +.names 27679 27680 +0 1 +.names 7506 27680 27681 +11 1 +.names 25663 27682 +1 1 +.names 27682 27683 +0 1 +.names 27533 27683 27684 +11 1 +.names 647 27685 +0 1 +.names 27685 27686 +1 1 +.names 27686 27687 +0 1 +.names 7506 27687 27688 +11 1 +.names 27695 27696 27689 +1- 1 +-1 1 +.names 27689 27690 +1 1 +.names 7521 27691 +0 1 +.names 27697 27700 27692 +11 1 +.names 27692 27693 +1 1 +.names 27693 27694 +0 1 +.names 27691 27694 27695 +11 1 +.names 7521 25956 27696 +11 1 +.names 7522 27697 +0 1 +.names 7077 27698 +0 1 +.names 27698 27699 +1 1 +.names 27699 27700 +0 1 +.names 27501 27701 +1 1 +.names 27701 27702 +0 1 +.names 27697 27703 +1 1 +.names 27703 27704 +0 1 +.names 27702 27704 27705 +11 1 +.names 27690 27706 +0 1 +.names 27713 27714 27707 +1- 1 +-1 1 +.names 27707 27708 +1 1 +.names 7509 27709 +0 1 +.names 27697 27717 27710 +11 1 +.names 27710 27711 +1 1 +.names 27711 27712 +0 1 +.names 27709 27712 27713 +11 1 +.names 7509 25985 27714 +11 1 +.names 7072 27715 +0 1 +.names 27715 27716 +1 1 +.names 27716 27717 +0 1 +.names 27461 27718 +1 1 +.names 27718 27719 +0 1 +.names 27697 27720 +1 1 +.names 27720 27721 +0 1 +.names 27719 27721 27722 +11 1 +.names 27708 27723 +0 1 +.names 7516 27724 +0 1 +.names 27724 27725 +1 1 +.names 27724 27730 27726 +11 1 +.names 27726 27727 +1 1 +.names 7080 27728 +0 1 +.names 27728 27729 +1 1 +.names 27729 27730 +0 1 +.names 27734 27735 27731 +1- 1 +-1 1 +.names 27731 27732 +1 1 +.names 27727 27733 +0 1 +.names 27709 27733 27734 +11 1 +.names 7509 25904 27735 +11 1 +.names 27469 27736 +1 1 +.names 27725 27737 +0 1 +.names 27736 27738 +0 1 +.names 27737 27738 27739 +11 1 +.names 27732 27740 +0 1 +.names 27724 27741 +1 1 +.names 27724 27746 27742 +11 1 +.names 27742 27743 +1 1 +.names 7079 27744 +0 1 +.names 27744 27745 +1 1 +.names 27745 27746 +0 1 +.names 27750 27751 27747 +1- 1 +-1 1 +.names 27747 27748 +1 1 +.names 27743 27749 +0 1 +.names 27691 27749 27750 +11 1 +.names 7521 26089 27751 +11 1 +.names 27741 27752 +0 1 +.names 27508 27753 +1 1 +.names 27753 27754 +0 1 +.names 27752 27754 27755 +11 1 +.names 27748 27756 +0 1 +.names 27762 27763 27757 +1- 1 +-1 1 +.names 27757 27758 +1 1 +.names 27764 27767 27759 +11 1 +.names 27759 27760 +1 1 +.names 27760 27761 +0 1 +.names 27691 27761 27762 +11 1 +.names 7521 26123 27763 +11 1 +.names 7514 27764 +0 1 +.names 7091 27765 +0 1 +.names 27765 27766 +1 1 +.names 27766 27767 +0 1 +.names 27515 27768 +1 1 +.names 27768 27769 +0 1 +.names 27764 27770 +1 1 +.names 27770 27771 +0 1 +.names 27769 27771 27772 +11 1 +.names 27758 27773 +0 1 +.names 27779 27780 27774 +1- 1 +-1 1 +.names 27774 27775 +1 1 +.names 27781 27784 27776 +11 1 +.names 27776 27777 +1 1 +.names 27777 27778 +0 1 +.names 27691 27778 27779 +11 1 +.names 7521 26159 27780 +11 1 +.names 7517 27781 +0 1 +.names 7094 27782 +0 1 +.names 27782 27783 +1 1 +.names 27783 27784 +0 1 +.names 27476 27785 +1 1 +.names 27785 27786 +0 1 +.names 27781 27787 +1 1 +.names 27787 27788 +0 1 +.names 27786 27788 27789 +11 1 +.names 27775 27790 +0 1 +.names 27797 27798 27791 +1- 1 +-1 1 +.names 27791 27792 +1 1 +.names 7520 27793 +0 1 +.names 27764 27801 27794 +11 1 +.names 27794 27795 +1 1 +.names 27795 27796 +0 1 +.names 27793 27796 27797 +11 1 +.names 7520 26205 27798 +11 1 +.names 7102 27799 +0 1 +.names 27799 27800 +1 1 +.names 27800 27801 +0 1 +.names 27484 27802 +1 1 +.names 27802 27803 +0 1 +.names 27764 27804 +1 1 +.names 27804 27805 +0 1 +.names 27803 27805 27806 +11 1 +.names 27792 27807 +0 1 +.names 27813 27814 27808 +1- 1 +-1 1 +.names 27808 27809 +1 1 +.names 27781 27817 27810 +11 1 +.names 27810 27811 +1 1 +.names 27811 27812 +0 1 +.names 27709 27812 27813 +11 1 +.names 7509 26276 27814 +11 1 +.names 7098 27815 +0 1 +.names 27815 27816 +1 1 +.names 27816 27817 +0 1 +.names 27522 27818 +1 1 +.names 27818 27819 +0 1 +.names 27781 27820 +1 1 +.names 27820 27821 +0 1 +.names 27819 27821 27822 +11 1 +.names 27809 27823 +0 1 +.names 27829 27830 27824 +1- 1 +-1 1 +.names 27824 27825 +1 1 +.names 27764 27833 27826 +11 1 +.names 27826 27827 +1 1 +.names 27827 27828 +0 1 +.names 27691 27828 27829 +11 1 +.names 7521 26522 27830 +11 1 +.names 7081 27831 +0 1 +.names 27831 27832 +1 1 +.names 27832 27833 +0 1 +.names 27492 27834 +1 1 +.names 27834 27835 +0 1 +.names 27764 27836 +1 1 +.names 27836 27837 +0 1 +.names 27835 27837 27838 +11 1 +.names 27825 27839 +0 1 +.names 27724 27840 +1 1 +.names 27724 27845 27841 +11 1 +.names 27841 27842 +1 1 +.names 7076 27843 +0 1 +.names 27843 27844 +1 1 +.names 27844 27845 +0 1 +.names 27849 27850 27846 +1- 1 +-1 1 +.names 27846 27847 +1 1 +.names 27842 27848 +0 1 +.names 27793 27848 27849 +11 1 +.names 7520 26310 27850 +11 1 +.names 27529 27851 +1 1 +.names 27840 27852 +0 1 +.names 27851 27853 +0 1 +.names 27852 27853 27854 +11 1 +.names 27847 27855 +0 1 +.names 27724 27856 +1 1 +.names 27724 27861 27857 +11 1 +.names 27857 27858 +1 1 +.names 7089 27859 +0 1 +.names 27859 27860 +1 1 +.names 27860 27861 +0 1 +.names 27865 27866 27862 +1- 1 +-1 1 +.names 27862 27863 +1 1 +.names 27858 27864 +0 1 +.names 27709 27864 27865 +11 1 +.names 7509 26358 27866 +11 1 +.names 27537 27867 +1 1 +.names 27856 27868 +0 1 +.names 27867 27869 +0 1 +.names 27868 27869 27870 +11 1 +.names 27863 27871 +0 1 +.names 27877 27878 27872 +1- 1 +-1 1 +.names 27872 27873 +1 1 +.names 27764 27881 27874 +11 1 +.names 27874 27875 +1 1 +.names 27875 27876 +0 1 +.names 27691 27876 27877 +11 1 +.names 7521 26416 27878 +11 1 +.names 7093 27879 +0 1 +.names 27879 27880 +1 1 +.names 27880 27881 +0 1 +.names 27544 27882 +1 1 +.names 27882 27883 +0 1 +.names 27764 27884 +1 1 +.names 27884 27885 +0 1 +.names 27883 27885 27886 +11 1 +.names 27873 27887 +0 1 +.names 27893 27894 27888 +1- 1 +-1 1 +.names 27888 27889 +1 1 +.names 27764 27897 27890 +11 1 +.names 27890 27891 +1 1 +.names 27891 27892 +0 1 +.names 27709 27892 27893 +11 1 +.names 7509 26477 27894 +11 1 +.names 7075 27895 +0 1 +.names 27895 27896 +1 1 +.names 27896 27897 +0 1 +.names 27551 27898 +1 1 +.names 27898 27899 +0 1 +.names 27764 27900 +1 1 +.names 27900 27901 +0 1 +.names 27899 27901 27902 +11 1 +.names 27889 27903 +0 1 +.names 27909 27910 27904 +1- 1 +-1 1 +.names 27904 27905 +1 1 +.names 27764 27913 27906 +11 1 +.names 27906 27907 +1 1 +.names 27907 27908 +0 1 +.names 27709 27908 27909 +11 1 +.names 7509 26560 27910 +11 1 +.names 7086 27911 +0 1 +.names 27911 27912 +1 1 +.names 27912 27913 +0 1 +.names 27572 27914 +1 1 +.names 27914 27915 +0 1 +.names 27764 27916 +1 1 +.names 27916 27917 +0 1 +.names 27915 27917 27918 +11 1 +.names 27905 27919 +0 1 +.names 27925 27926 27920 +1- 1 +-1 1 +.names 27920 27921 +1 1 +.names 27781 27929 27922 +11 1 +.names 27922 27923 +1 1 +.names 27923 27924 +0 1 +.names 27709 27924 27925 +11 1 +.names 7509 26602 27926 +11 1 +.names 7088 27927 +0 1 +.names 27927 27928 +1 1 +.names 27928 27929 +0 1 +.names 27579 27930 +1 1 +.names 27930 27931 +0 1 +.names 27781 27932 +1 1 +.names 27932 27933 +0 1 +.names 27931 27933 27934 +11 1 +.names 27921 27935 +0 1 +.names 27941 27942 27936 +1- 1 +-1 1 +.names 27936 27937 +1 1 +.names 27697 27945 27938 +11 1 +.names 27938 27939 +1 1 +.names 27939 27940 +0 1 +.names 27793 27940 27941 +11 1 +.names 7520 26669 27942 +11 1 +.names 7097 27943 +0 1 +.names 27943 27944 +1 1 +.names 27944 27945 +0 1 +.names 27586 27946 +1 1 +.names 27946 27947 +0 1 +.names 27697 27948 +1 1 +.names 27948 27949 +0 1 +.names 27947 27949 27950 +11 1 +.names 27937 27951 +0 1 +.names 27957 27958 27952 +1- 1 +-1 1 +.names 27952 27953 +1 1 +.names 27764 27961 27954 +11 1 +.names 27954 27955 +1 1 +.names 27955 27956 +0 1 +.names 27793 27956 27957 +11 1 +.names 7520 26708 27958 +11 1 +.names 7085 27959 +0 1 +.names 27959 27960 +1 1 +.names 27960 27961 +0 1 +.names 27764 27962 +1 1 +.names 27962 27963 +0 1 +.names 27593 27964 +1 1 +.names 27964 27965 +0 1 +.names 27963 27965 27966 +11 1 +.names 27953 27967 +0 1 +.names 27724 27968 +1 1 +.names 27724 27973 27969 +11 1 +.names 27969 27970 +1 1 +.names 7103 27971 +0 1 +.names 27971 27972 +1 1 +.names 27972 27973 +0 1 +.names 27977 27978 27974 +1- 1 +-1 1 +.names 27974 27975 +1 1 +.names 27970 27976 +0 1 +.names 27691 27976 27977 +11 1 +.names 7521 26769 27978 +11 1 +.names 27600 27979 +1 1 +.names 27968 27980 +0 1 +.names 27979 27981 +0 1 +.names 27980 27981 27982 +11 1 +.names 27975 27983 +0 1 +.names 27989 27990 27984 +1- 1 +-1 1 +.names 27984 27985 +1 1 +.names 27724 27993 27986 +11 1 +.names 27986 27987 +1 1 +.names 27987 27988 +0 1 +.names 27691 27988 27989 +11 1 +.names 7521 26847 27990 +11 1 +.names 7096 27991 +0 1 +.names 27991 27992 +1 1 +.names 27992 27993 +0 1 +.names 27558 27994 +1 1 +.names 27994 27995 +0 1 +.names 27724 27996 +1 1 +.names 27996 27997 +0 1 +.names 27995 27997 27998 +11 1 +.names 27985 27999 +0 1 +.names 28005 28006 28000 +1- 1 +-1 1 +.names 28000 28001 +1 1 +.names 27781 28009 28002 +11 1 +.names 28002 28003 +1 1 +.names 28003 28004 +0 1 +.names 27793 28004 28005 +11 1 +.names 7520 26905 28006 +11 1 +.names 7087 28007 +0 1 +.names 28007 28008 +1 1 +.names 28008 28009 +0 1 +.names 27565 28010 +1 1 +.names 28010 28011 +0 1 +.names 27781 28012 +1 1 +.names 28012 28013 +0 1 +.names 28011 28013 28014 +11 1 +.names 28001 28015 +0 1 +.names 28021 28022 28016 +1- 1 +-1 1 +.names 28016 28017 +1 1 +.names 27781 28025 28018 +11 1 +.names 28018 28019 +1 1 +.names 28019 28020 +0 1 +.names 27793 28020 28021 +11 1 +.names 7520 26813 28022 +11 1 +.names 7073 28023 +0 1 +.names 28023 28024 +1 1 +.names 28024 28025 +0 1 +.names 27608 28026 +1 1 +.names 28026 28027 +0 1 +.names 27781 28028 +1 1 +.names 28028 28029 +0 1 +.names 28027 28029 28030 +11 1 +.names 28017 28031 +0 1 +.names 28037 28038 28032 +1- 1 +-1 1 +.names 28032 28033 +1 1 +.names 27781 28041 28034 +11 1 +.names 28034 28035 +1 1 +.names 28035 28036 +0 1 +.names 27691 28036 28037 +11 1 +.names 7521 26977 28038 +11 1 +.names 7083 28039 +0 1 +.names 28039 28040 +1 1 +.names 28040 28041 +0 1 +.names 27615 28042 +1 1 +.names 28042 28043 +0 1 +.names 27781 28044 +1 1 +.names 28044 28045 +0 1 +.names 28043 28045 28046 +11 1 +.names 28033 28047 +0 1 +.names 28053 28054 28048 +1- 1 +-1 1 +.names 28048 28049 +1 1 +.names 27724 28057 28050 +11 1 +.names 28050 28051 +1 1 +.names 28051 28052 +0 1 +.names 27709 28052 28053 +11 1 +.names 7509 27009 28054 +11 1 +.names 7078 28055 +0 1 +.names 28055 28056 +1 1 +.names 28056 28057 +0 1 +.names 27724 28058 +1 1 +.names 28058 28059 +0 1 +.names 27622 28060 +1 1 +.names 28060 28061 +0 1 +.names 28059 28061 28062 +11 1 +.names 28049 28063 +0 1 +.names 27724 28064 +1 1 +.names 27724 28069 28065 +11 1 +.names 28065 28066 +1 1 +.names 7095 28067 +0 1 +.names 28067 28068 +1 1 +.names 28068 28069 +0 1 +.names 28073 28074 28070 +1- 1 +-1 1 +.names 28070 28071 +1 1 +.names 28066 28072 +0 1 +.names 27793 28072 28073 +11 1 +.names 7520 27055 28074 +11 1 +.names 27629 28075 +1 1 +.names 28064 28076 +0 1 +.names 28075 28077 +0 1 +.names 28076 28077 28078 +11 1 +.names 28071 28079 +0 1 +.names 28085 28086 28080 +1- 1 +-1 1 +.names 28080 28081 +1 1 +.names 27764 28089 28082 +11 1 +.names 28082 28083 +1 1 +.names 28083 28084 +0 1 +.names 27793 28084 28085 +11 1 +.names 7520 27101 28086 +11 1 +.names 7074 28087 +0 1 +.names 28087 28088 +1 1 +.names 28088 28089 +0 1 +.names 27636 28090 +1 1 +.names 28090 28091 +0 1 +.names 27764 28092 +1 1 +.names 28092 28093 +0 1 +.names 28091 28093 28094 +11 1 +.names 28081 28095 +0 1 +.names 28101 28102 28096 +1- 1 +-1 1 +.names 28096 28097 +1 1 +.names 27781 28105 28098 +11 1 +.names 28098 28099 +1 1 +.names 28099 28100 +0 1 +.names 27793 28100 28101 +11 1 +.names 7520 27147 28102 +11 1 +.names 7100 28103 +0 1 +.names 28103 28104 +1 1 +.names 28104 28105 +0 1 +.names 27643 28106 +1 1 +.names 28106 28107 +0 1 +.names 27781 28108 +1 1 +.names 28108 28109 +0 1 +.names 28107 28109 28110 +11 1 +.names 28097 28111 +0 1 +.names 27724 28112 +1 1 +.names 27724 28117 28113 +11 1 +.names 28113 28114 +1 1 +.names 7090 28115 +0 1 +.names 28115 28116 +1 1 +.names 28116 28117 +0 1 +.names 28121 28122 28118 +1- 1 +-1 1 +.names 28118 28119 +1 1 +.names 28114 28120 +0 1 +.names 27691 28120 28121 +11 1 +.names 7521 27207 28122 +11 1 +.names 27650 28123 +1 1 +.names 28112 28124 +0 1 +.names 28123 28125 +0 1 +.names 28124 28125 28126 +11 1 +.names 28119 28127 +0 1 +.names 28133 28134 28128 +1- 1 +-1 1 +.names 28128 28129 +1 1 +.names 27781 28137 28130 +11 1 +.names 28130 28131 +1 1 +.names 28131 28132 +0 1 +.names 27793 28132 28133 +11 1 +.names 7520 27251 28134 +11 1 +.names 7092 28135 +0 1 +.names 28135 28136 +1 1 +.names 28136 28137 +0 1 +.names 27657 28138 +1 1 +.names 28138 28139 +0 1 +.names 27781 28140 +1 1 +.names 28140 28141 +0 1 +.names 28139 28141 28142 +11 1 +.names 28129 28143 +0 1 +.names 28149 28150 28144 +1- 1 +-1 1 +.names 28144 28145 +1 1 +.names 27781 28153 28146 +11 1 +.names 28146 28147 +1 1 +.names 28147 28148 +0 1 +.names 27709 28148 28149 +11 1 +.names 7509 27297 28150 +11 1 +.names 7099 28151 +0 1 +.names 28151 28152 +1 1 +.names 28152 28153 +0 1 +.names 27664 28154 +1 1 +.names 28154 28155 +0 1 +.names 27781 28156 +1 1 +.names 28156 28157 +0 1 +.names 28155 28157 28158 +11 1 +.names 28145 28159 +0 1 +.names 27724 28160 +1 1 +.names 27724 28165 28161 +11 1 +.names 28161 28162 +1 1 +.names 7082 28163 +0 1 +.names 28163 28164 +1 1 +.names 28164 28165 +0 1 +.names 28169 28170 28166 +1- 1 +-1 1 +.names 28166 28167 +1 1 +.names 28162 28168 +0 1 +.names 27793 28168 28169 +11 1 +.names 7520 27340 28170 +11 1 +.names 28160 28171 +0 1 +.names 27671 28172 +1 1 +.names 28172 28173 +0 1 +.names 28171 28173 28174 +11 1 +.names 28167 28175 +0 1 +.names 28181 28182 28176 +1- 1 +-1 1 +.names 28176 28177 +1 1 +.names 27697 28185 28178 +11 1 +.names 28178 28179 +1 1 +.names 28179 28180 +0 1 +.names 27709 28180 28181 +11 1 +.names 7509 27378 28182 +11 1 +.names 7084 28183 +0 1 +.names 28183 28184 +1 1 +.names 28184 28185 +0 1 +.names 27678 28186 +1 1 +.names 28186 28187 +0 1 +.names 27697 28188 +1 1 +.names 28188 28189 +0 1 +.names 28187 28189 28190 +11 1 +.names 28177 28191 +0 1 +.names 28197 28198 28192 +1- 1 +-1 1 +.names 28192 28193 +1 1 +.names 27764 28201 28194 +11 1 +.names 28194 28195 +1 1 +.names 28195 28196 +0 1 +.names 27691 28196 28197 +11 1 +.names 7521 27436 28198 +11 1 +.names 7101 28199 +0 1 +.names 28199 28200 +1 1 +.names 28200 28201 +0 1 +.names 27685 28202 +1 1 +.names 28202 28203 +0 1 +.names 27764 28204 +1 1 +.names 28204 28205 +0 1 +.names 28203 28205 28206 +11 1 +.names 28193 28207 +0 1 +.names 28214 28215 28208 +1- 1 +-1 1 +.names 28208 28209 +1 1 +.names 7536 28210 +0 1 +.names 28216 28218 28211 +11 1 +.names 28211 28212 +1 1 +.names 28212 28213 +0 1 +.names 28210 28213 28214 +11 1 +.names 7536 27698 28215 +11 1 +.names 7537 28216 +0 1 +.names 25956 28217 +1 1 +.names 28217 28218 +0 1 +.names 28225 28226 28219 +1- 1 +-1 1 +.names 28219 28220 +1 1 +.names 2413 28221 +1 1 +.names 28221 28222 +0 1 +.names 28216 28223 +1 1 +.names 28223 28224 +0 1 +.names 28222 28224 28225 +11 1 +.names 28209 28226 +0 1 +.names 28233 28234 28227 +1- 1 +-1 1 +.names 28227 28228 +1 1 +.names 7524 28229 +0 1 +.names 28216 28236 28230 +11 1 +.names 28230 28231 +1 1 +.names 28231 28232 +0 1 +.names 28229 28232 28233 +11 1 +.names 7524 27715 28234 +11 1 +.names 25985 28235 +1 1 +.names 28235 28236 +0 1 +.names 28243 28244 28237 +1- 1 +-1 1 +.names 28237 28238 +1 1 +.names 25985 28239 +1 1 +.names 28239 28240 +0 1 +.names 28216 28241 +1 1 +.names 28241 28242 +0 1 +.names 28240 28242 28243 +11 1 +.names 28228 28244 +0 1 +.names 7531 28245 +0 1 +.names 28245 28246 +1 1 +.names 28245 28250 28247 +11 1 +.names 28247 28248 +1 1 +.names 25904 28249 +1 1 +.names 28249 28250 +0 1 +.names 28254 28255 28251 +1- 1 +-1 1 +.names 28251 28252 +1 1 +.names 28248 28253 +0 1 +.names 28229 28253 28254 +11 1 +.names 7524 27728 28255 +11 1 +.names 25904 28256 +1 1 +.names 28261 28262 28257 +1- 1 +-1 1 +.names 28257 28258 +1 1 +.names 28246 28259 +0 1 +.names 28256 28260 +0 1 +.names 28259 28260 28261 +11 1 +.names 28252 28262 +0 1 +.names 28245 28263 +1 1 +.names 28245 28267 28264 +11 1 +.names 28264 28265 +1 1 +.names 26089 28266 +1 1 +.names 28266 28267 +0 1 +.names 28271 28272 28268 +1- 1 +-1 1 +.names 28268 28269 +1 1 +.names 28265 28270 +0 1 +.names 28210 28270 28271 +11 1 +.names 7536 27744 28272 +11 1 +.names 28278 28279 28273 +1- 1 +-1 1 +.names 28273 28274 +1 1 +.names 28263 28275 +0 1 +.names 26089 28276 +1 1 +.names 28276 28277 +0 1 +.names 28275 28277 28278 +11 1 +.names 28269 28279 +0 1 +.names 28285 28286 28280 +1- 1 +-1 1 +.names 28280 28281 +1 1 +.names 28287 28289 28282 +11 1 +.names 28282 28283 +1 1 +.names 28283 28284 +0 1 +.names 28210 28284 28285 +11 1 +.names 7536 27765 28286 +11 1 +.names 7529 28287 +0 1 +.names 26123 28288 +1 1 +.names 28288 28289 +0 1 +.names 28296 28297 28290 +1- 1 +-1 1 +.names 28290 28291 +1 1 +.names 26123 28292 +1 1 +.names 28292 28293 +0 1 +.names 28287 28294 +1 1 +.names 28294 28295 +0 1 +.names 28293 28295 28296 +11 1 +.names 28281 28297 +0 1 +.names 28303 28304 28298 +1- 1 +-1 1 +.names 28298 28299 +1 1 +.names 28305 28307 28300 +11 1 +.names 28300 28301 +1 1 +.names 28301 28302 +0 1 +.names 28210 28302 28303 +11 1 +.names 7536 27782 28304 +11 1 +.names 7532 28305 +0 1 +.names 26159 28306 +1 1 +.names 28306 28307 +0 1 +.names 28314 28315 28308 +1- 1 +-1 1 +.names 28308 28309 +1 1 +.names 26159 28310 +1 1 +.names 28310 28311 +0 1 +.names 28305 28312 +1 1 +.names 28312 28313 +0 1 +.names 28311 28313 28314 +11 1 +.names 28299 28315 +0 1 +.names 28322 28323 28316 +1- 1 +-1 1 +.names 28316 28317 +1 1 +.names 7535 28318 +0 1 +.names 28287 28325 28319 +11 1 +.names 28319 28320 +1 1 +.names 28320 28321 +0 1 +.names 28318 28321 28322 +11 1 +.names 7535 27799 28323 +11 1 +.names 26205 28324 +1 1 +.names 28324 28325 +0 1 +.names 28332 28333 28326 +1- 1 +-1 1 +.names 28326 28327 +1 1 +.names 2413 28328 +1 1 +.names 28328 28329 +0 1 +.names 28287 28330 +1 1 +.names 28330 28331 +0 1 +.names 28329 28331 28332 +11 1 +.names 28317 28333 +0 1 +.names 28339 28340 28334 +1- 1 +-1 1 +.names 28334 28335 +1 1 +.names 28305 28342 28336 +11 1 +.names 28336 28337 +1 1 +.names 28337 28338 +0 1 +.names 28229 28338 28339 +11 1 +.names 7524 27815 28340 +11 1 +.names 26276 28341 +1 1 +.names 28341 28342 +0 1 +.names 28349 28350 28343 +1- 1 +-1 1 +.names 28343 28344 +1 1 +.names 26276 28345 +1 1 +.names 28345 28346 +0 1 +.names 28305 28347 +1 1 +.names 28347 28348 +0 1 +.names 28346 28348 28349 +11 1 +.names 28335 28350 +0 1 +.names 28356 28357 28351 +1- 1 +-1 1 +.names 28351 28352 +1 1 +.names 28287 28359 28353 +11 1 +.names 28353 28354 +1 1 +.names 28354 28355 +0 1 +.names 28210 28355 28356 +11 1 +.names 7536 27831 28357 +11 1 +.names 26522 28358 +1 1 +.names 28358 28359 +0 1 +.names 28366 28367 28360 +1- 1 +-1 1 +.names 28360 28361 +1 1 +.names 2413 28362 +1 1 +.names 28362 28363 +0 1 +.names 28287 28364 +1 1 +.names 28364 28365 +0 1 +.names 28363 28365 28366 +11 1 +.names 28352 28367 +0 1 +.names 28245 28368 +1 1 +.names 28245 28372 28369 +11 1 +.names 28369 28370 +1 1 +.names 26310 28371 +1 1 +.names 28371 28372 +0 1 +.names 28376 28377 28373 +1- 1 +-1 1 +.names 28373 28374 +1 1 +.names 28370 28375 +0 1 +.names 28318 28375 28376 +11 1 +.names 7535 27843 28377 +11 1 +.names 26310 28378 +1 1 +.names 28383 28384 28379 +1- 1 +-1 1 +.names 28379 28380 +1 1 +.names 28368 28381 +0 1 +.names 28378 28382 +0 1 +.names 28381 28382 28383 +11 1 +.names 28374 28384 +0 1 +.names 28245 28385 +1 1 +.names 28245 28389 28386 +11 1 +.names 28386 28387 +1 1 +.names 26358 28388 +1 1 +.names 28388 28389 +0 1 +.names 28393 28394 28390 +1- 1 +-1 1 +.names 28390 28391 +1 1 +.names 28387 28392 +0 1 +.names 28229 28392 28393 +11 1 +.names 7524 27859 28394 +11 1 +.names 26358 28395 +1 1 +.names 28400 28401 28396 +1- 1 +-1 1 +.names 28396 28397 +1 1 +.names 28385 28398 +0 1 +.names 28395 28399 +0 1 +.names 28398 28399 28400 +11 1 +.names 28391 28401 +0 1 +.names 28407 28408 28402 +1- 1 +-1 1 +.names 28402 28403 +1 1 +.names 28287 28410 28404 +11 1 +.names 28404 28405 +1 1 +.names 28405 28406 +0 1 +.names 28210 28406 28407 +11 1 +.names 7536 27879 28408 +11 1 +.names 26416 28409 +1 1 +.names 28409 28410 +0 1 +.names 28417 28418 28411 +1- 1 +-1 1 +.names 28411 28412 +1 1 +.names 26416 28413 +1 1 +.names 28413 28414 +0 1 +.names 28287 28415 +1 1 +.names 28415 28416 +0 1 +.names 28414 28416 28417 +11 1 +.names 28403 28418 +0 1 +.names 28424 28425 28419 +1- 1 +-1 1 +.names 28419 28420 +1 1 +.names 28287 28427 28421 +11 1 +.names 28421 28422 +1 1 +.names 28422 28423 +0 1 +.names 28229 28423 28424 +11 1 +.names 7524 27895 28425 +11 1 +.names 26477 28426 +1 1 +.names 28426 28427 +0 1 +.names 28434 28435 28428 +1- 1 +-1 1 +.names 28428 28429 +1 1 +.names 26477 28430 +1 1 +.names 28430 28431 +0 1 +.names 28287 28432 +1 1 +.names 28432 28433 +0 1 +.names 28431 28433 28434 +11 1 +.names 28420 28435 +0 1 +.names 28441 28442 28436 +1- 1 +-1 1 +.names 28436 28437 +1 1 +.names 28287 28444 28438 +11 1 +.names 28438 28439 +1 1 +.names 28439 28440 +0 1 +.names 28229 28440 28441 +11 1 +.names 7524 27911 28442 +11 1 +.names 26560 28443 +1 1 +.names 28443 28444 +0 1 +.names 28451 28452 28445 +1- 1 +-1 1 +.names 28445 28446 +1 1 +.names 26560 28447 +1 1 +.names 28447 28448 +0 1 +.names 28287 28449 +1 1 +.names 28449 28450 +0 1 +.names 28448 28450 28451 +11 1 +.names 28437 28452 +0 1 +.names 28458 28459 28453 +1- 1 +-1 1 +.names 28453 28454 +1 1 +.names 28305 28461 28455 +11 1 +.names 28455 28456 +1 1 +.names 28456 28457 +0 1 +.names 28229 28457 28458 +11 1 +.names 7524 27927 28459 +11 1 +.names 26602 28460 +1 1 +.names 28460 28461 +0 1 +.names 28468 28469 28462 +1- 1 +-1 1 +.names 28462 28463 +1 1 +.names 26602 28464 +1 1 +.names 28464 28465 +0 1 +.names 28305 28466 +1 1 +.names 28466 28467 +0 1 +.names 28465 28467 28468 +11 1 +.names 28454 28469 +0 1 +.names 28475 28476 28470 +1- 1 +-1 1 +.names 28470 28471 +1 1 +.names 28216 28478 28472 +11 1 +.names 28472 28473 +1 1 +.names 28473 28474 +0 1 +.names 28318 28474 28475 +11 1 +.names 7535 27943 28476 +11 1 +.names 26669 28477 +1 1 +.names 28477 28478 +0 1 +.names 28485 28486 28479 +1- 1 +-1 1 +.names 28479 28480 +1 1 +.names 26669 28481 +1 1 +.names 28481 28482 +0 1 +.names 28216 28483 +1 1 +.names 28483 28484 +0 1 +.names 28482 28484 28485 +11 1 +.names 28471 28486 +0 1 +.names 28492 28493 28487 +1- 1 +-1 1 +.names 28487 28488 +1 1 +.names 28287 28495 28489 +11 1 +.names 28489 28490 +1 1 +.names 28490 28491 +0 1 +.names 28318 28491 28492 +11 1 +.names 7535 27959 28493 +11 1 +.names 26708 28494 +1 1 +.names 28494 28495 +0 1 +.names 28502 28503 28496 +1- 1 +-1 1 +.names 28496 28497 +1 1 +.names 28287 28498 +1 1 +.names 28498 28499 +0 1 +.names 26708 28500 +1 1 +.names 28500 28501 +0 1 +.names 28499 28501 28502 +11 1 +.names 28488 28503 +0 1 +.names 28245 28504 +1 1 +.names 28245 28508 28505 +11 1 +.names 28505 28506 +1 1 +.names 26769 28507 +1 1 +.names 28507 28508 +0 1 +.names 28512 28513 28509 +1- 1 +-1 1 +.names 28509 28510 +1 1 +.names 28506 28511 +0 1 +.names 28210 28511 28512 +11 1 +.names 7536 27971 28513 +11 1 +.names 2413 28514 +1 1 +.names 28504 28515 +0 1 +.names 28514 28516 +0 1 +.names 28515 28516 28517 +11 1 +.names 28510 28518 +0 1 +.names 28524 28525 28519 +1- 1 +-1 1 +.names 28519 28520 +1 1 +.names 28245 28527 28521 +11 1 +.names 28521 28522 +1 1 +.names 28522 28523 +0 1 +.names 28210 28523 28524 +11 1 +.names 7536 27991 28525 +11 1 +.names 26847 28526 +1 1 +.names 28526 28527 +0 1 +.names 28534 28535 28528 +1- 1 +-1 1 +.names 28528 28529 +1 1 +.names 26847 28530 +1 1 +.names 28530 28531 +0 1 +.names 28245 28532 +1 1 +.names 28532 28533 +0 1 +.names 28531 28533 28534 +11 1 +.names 28520 28535 +0 1 +.names 28541 28542 28536 +1- 1 +-1 1 +.names 28536 28537 +1 1 +.names 28305 28544 28538 +11 1 +.names 28538 28539 +1 1 +.names 28539 28540 +0 1 +.names 28318 28540 28541 +11 1 +.names 7535 28007 28542 +11 1 +.names 26905 28543 +1 1 +.names 28543 28544 +0 1 +.names 28551 28552 28545 +1- 1 +-1 1 +.names 28545 28546 +1 1 +.names 26905 28547 +1 1 +.names 28547 28548 +0 1 +.names 28305 28549 +1 1 +.names 28549 28550 +0 1 +.names 28548 28550 28551 +11 1 +.names 28537 28552 +0 1 +.names 28558 28559 28553 +1- 1 +-1 1 +.names 28553 28554 +1 1 +.names 28305 28561 28555 +11 1 +.names 28555 28556 +1 1 +.names 28556 28557 +0 1 +.names 28318 28557 28558 +11 1 +.names 7535 28023 28559 +11 1 +.names 26813 28560 +1 1 +.names 28560 28561 +0 1 +.names 28568 28569 28562 +1- 1 +-1 1 +.names 28562 28563 +1 1 +.names 26813 28564 +1 1 +.names 28564 28565 +0 1 +.names 28305 28566 +1 1 +.names 28566 28567 +0 1 +.names 28565 28567 28568 +11 1 +.names 28554 28569 +0 1 +.names 28575 28576 28570 +1- 1 +-1 1 +.names 28570 28571 +1 1 +.names 28305 28578 28572 +11 1 +.names 28572 28573 +1 1 +.names 28573 28574 +0 1 +.names 28210 28574 28575 +11 1 +.names 7536 28039 28576 +11 1 +.names 26977 28577 +1 1 +.names 28577 28578 +0 1 +.names 28585 28586 28579 +1- 1 +-1 1 +.names 28579 28580 +1 1 +.names 26977 28581 +1 1 +.names 28581 28582 +0 1 +.names 28305 28583 +1 1 +.names 28583 28584 +0 1 +.names 28582 28584 28585 +11 1 +.names 28571 28586 +0 1 +.names 28592 28593 28587 +1- 1 +-1 1 +.names 28587 28588 +1 1 +.names 28245 28595 28589 +11 1 +.names 28589 28590 +1 1 +.names 28590 28591 +0 1 +.names 28229 28591 28592 +11 1 +.names 7524 28055 28593 +11 1 +.names 27009 28594 +1 1 +.names 28594 28595 +0 1 +.names 28602 28603 28596 +1- 1 +-1 1 +.names 28596 28597 +1 1 +.names 28245 28598 +1 1 +.names 28598 28599 +0 1 +.names 27009 28600 +1 1 +.names 28600 28601 +0 1 +.names 28599 28601 28602 +11 1 +.names 28588 28603 +0 1 +.names 28245 28604 +1 1 +.names 28245 28608 28605 +11 1 +.names 28605 28606 +1 1 +.names 27055 28607 +1 1 +.names 28607 28608 +0 1 +.names 28612 28613 28609 +1- 1 +-1 1 +.names 28609 28610 +1 1 +.names 28606 28611 +0 1 +.names 28318 28611 28612 +11 1 +.names 7535 28067 28613 +11 1 +.names 27055 28614 +1 1 +.names 28619 28620 28615 +1- 1 +-1 1 +.names 28615 28616 +1 1 +.names 28604 28617 +0 1 +.names 28614 28618 +0 1 +.names 28617 28618 28619 +11 1 +.names 28610 28620 +0 1 +.names 28626 28627 28621 +1- 1 +-1 1 +.names 28621 28622 +1 1 +.names 28287 28629 28623 +11 1 +.names 28623 28624 +1 1 +.names 28624 28625 +0 1 +.names 28318 28625 28626 +11 1 +.names 7535 28087 28627 +11 1 +.names 27101 28628 +1 1 +.names 28628 28629 +0 1 +.names 28636 28637 28630 +1- 1 +-1 1 +.names 28630 28631 +1 1 +.names 27101 28632 +1 1 +.names 28632 28633 +0 1 +.names 28287 28634 +1 1 +.names 28634 28635 +0 1 +.names 28633 28635 28636 +11 1 +.names 28622 28637 +0 1 +.names 28643 28644 28638 +1- 1 +-1 1 +.names 28638 28639 +1 1 +.names 28305 28646 28640 +11 1 +.names 28640 28641 +1 1 +.names 28641 28642 +0 1 +.names 28318 28642 28643 +11 1 +.names 7535 28103 28644 +11 1 +.names 27147 28645 +1 1 +.names 28645 28646 +0 1 +.names 28653 28654 28647 +1- 1 +-1 1 +.names 28647 28648 +1 1 +.names 27147 28649 +1 1 +.names 28649 28650 +0 1 +.names 28305 28651 +1 1 +.names 28651 28652 +0 1 +.names 28650 28652 28653 +11 1 +.names 28639 28654 +0 1 +.names 28245 28655 +1 1 +.names 28245 28659 28656 +11 1 +.names 28656 28657 +1 1 +.names 27207 28658 +1 1 +.names 28658 28659 +0 1 +.names 28663 28664 28660 +1- 1 +-1 1 +.names 28660 28661 +1 1 +.names 28657 28662 +0 1 +.names 28210 28662 28663 +11 1 +.names 7536 28115 28664 +11 1 +.names 27207 28665 +1 1 +.names 28670 28671 28666 +1- 1 +-1 1 +.names 28666 28667 +1 1 +.names 28655 28668 +0 1 +.names 28665 28669 +0 1 +.names 28668 28669 28670 +11 1 +.names 28661 28671 +0 1 +.names 28677 28678 28672 +1- 1 +-1 1 +.names 28672 28673 +1 1 +.names 28305 28680 28674 +11 1 +.names 28674 28675 +1 1 +.names 28675 28676 +0 1 +.names 28318 28676 28677 +11 1 +.names 7535 28135 28678 +11 1 +.names 27251 28679 +1 1 +.names 28679 28680 +0 1 +.names 28687 28688 28681 +1- 1 +-1 1 +.names 28681 28682 +1 1 +.names 27251 28683 +1 1 +.names 28683 28684 +0 1 +.names 28305 28685 +1 1 +.names 28685 28686 +0 1 +.names 28684 28686 28687 +11 1 +.names 28673 28688 +0 1 +.names 28694 28695 28689 +1- 1 +-1 1 +.names 28689 28690 +1 1 +.names 28305 28697 28691 +11 1 +.names 28691 28692 +1 1 +.names 28692 28693 +0 1 +.names 28229 28693 28694 +11 1 +.names 7524 28151 28695 +11 1 +.names 27297 28696 +1 1 +.names 28696 28697 +0 1 +.names 28704 28705 28698 +1- 1 +-1 1 +.names 28698 28699 +1 1 +.names 27297 28700 +1 1 +.names 28700 28701 +0 1 +.names 28305 28702 +1 1 +.names 28702 28703 +0 1 +.names 28701 28703 28704 +11 1 +.names 28690 28705 +0 1 +.names 28245 28706 +1 1 +.names 28245 28710 28707 +11 1 +.names 28707 28708 +1 1 +.names 27340 28709 +1 1 +.names 28709 28710 +0 1 +.names 28714 28715 28711 +1- 1 +-1 1 +.names 28711 28712 +1 1 +.names 28708 28713 +0 1 +.names 28318 28713 28714 +11 1 +.names 7535 28163 28715 +11 1 +.names 28721 28722 28716 +1- 1 +-1 1 +.names 28716 28717 +1 1 +.names 28706 28718 +0 1 +.names 27340 28719 +1 1 +.names 28719 28720 +0 1 +.names 28718 28720 28721 +11 1 +.names 28712 28722 +0 1 +.names 28728 28729 28723 +1- 1 +-1 1 +.names 28723 28724 +1 1 +.names 28216 28731 28725 +11 1 +.names 28725 28726 +1 1 +.names 28726 28727 +0 1 +.names 28229 28727 28728 +11 1 +.names 7524 28183 28729 +11 1 +.names 27378 28730 +1 1 +.names 28730 28731 +0 1 +.names 28738 28739 28732 +1- 1 +-1 1 +.names 28732 28733 +1 1 +.names 27378 28734 +1 1 +.names 28734 28735 +0 1 +.names 28216 28736 +1 1 +.names 28736 28737 +0 1 +.names 28735 28737 28738 +11 1 +.names 28724 28739 +0 1 +.names 28745 28746 28740 +1- 1 +-1 1 +.names 28740 28741 +1 1 +.names 28287 28748 28742 +11 1 +.names 28742 28743 +1 1 +.names 28743 28744 +0 1 +.names 28210 28744 28745 +11 1 +.names 7536 28199 28746 +11 1 +.names 27436 28747 +1 1 +.names 28747 28748 +0 1 +.names 28755 28756 28749 +1- 1 +-1 1 +.names 28749 28750 +1 1 +.names 27436 28751 +1 1 +.names 28751 28752 +0 1 +.names 28287 28753 +1 1 +.names 28753 28754 +0 1 +.names 28752 28754 28755 +11 1 +.names 28741 28756 +0 1 +.names 28763 28764 28757 +1- 1 +-1 1 +.names 28757 28758 +1 1 +.names 7550 28759 +0 1 +.names 28765 28767 28760 +11 1 +.names 28760 28761 +1 1 +.names 28761 28762 +0 1 +.names 28759 28762 28763 +11 1 +.names 7550 2413 28764 +11 1 +.names 7551 28765 +0 1 +.names 27698 28766 +1 1 +.names 28766 28767 +0 1 +.names 28774 28775 28768 +1- 1 +-1 1 +.names 28768 28769 +1 1 +.names 2413 28770 +1 1 +.names 28770 28771 +0 1 +.names 28765 28772 +1 1 +.names 28772 28773 +0 1 +.names 28771 28773 28774 +11 1 +.names 28758 28775 +0 1 +.names 28782 28783 28776 +1- 1 +-1 1 +.names 28776 28777 +1 1 +.names 7539 28778 +0 1 +.names 28765 28785 28779 +11 1 +.names 28779 28780 +1 1 +.names 28780 28781 +0 1 +.names 28778 28781 28782 +11 1 +.names 7539 2413 28783 +11 1 +.names 27715 28784 +1 1 +.names 28784 28785 +0 1 +.names 28792 28793 28786 +1- 1 +-1 1 +.names 28786 28787 +1 1 +.names 27715 28788 +1 1 +.names 28788 28789 +0 1 +.names 28765 28790 +1 1 +.names 28790 28791 +0 1 +.names 28789 28791 28792 +11 1 +.names 28777 28793 +0 1 +.names 7545 28794 +0 1 +.names 28794 28795 +1 1 +.names 28794 28799 28796 +11 1 +.names 28796 28797 +1 1 +.names 27728 28798 +1 1 +.names 28798 28799 +0 1 +.names 28803 28804 28800 +1- 1 +-1 1 +.names 28800 28801 +1 1 +.names 28797 28802 +0 1 +.names 28778 28802 28803 +11 1 +.names 7539 2413 28804 +11 1 +.names 27728 28805 +1 1 +.names 28810 28811 28806 +1- 1 +-1 1 +.names 28806 28807 +1 1 +.names 28795 28808 +0 1 +.names 28805 28809 +0 1 +.names 28808 28809 28810 +11 1 +.names 28801 28811 +0 1 +.names 28794 28812 +1 1 +.names 28794 28816 28813 +11 1 +.names 28813 28814 +1 1 +.names 27744 28815 +1 1 +.names 28815 28816 +0 1 +.names 28820 28821 28817 +1- 1 +-1 1 +.names 28817 28818 +1 1 +.names 28814 28819 +0 1 +.names 28759 28819 28820 +11 1 +.names 7550 2413 28821 +11 1 +.names 28827 28828 28822 +1- 1 +-1 1 +.names 28822 28823 +1 1 +.names 28812 28824 +0 1 +.names 27744 28825 +1 1 +.names 28825 28826 +0 1 +.names 28824 28826 28827 +11 1 +.names 28818 28828 +0 1 +.names 28834 28835 28829 +1- 1 +-1 1 +.names 28829 28830 +1 1 +.names 28836 28838 28831 +11 1 +.names 28831 28832 +1 1 +.names 28832 28833 +0 1 +.names 28759 28833 28834 +11 1 +.names 7550 2413 28835 +11 1 +.names 7543 28836 +0 1 +.names 27765 28837 +1 1 +.names 28837 28838 +0 1 +.names 28845 28846 28839 +1- 1 +-1 1 +.names 28839 28840 +1 1 +.names 27765 28841 +1 1 +.names 28841 28842 +0 1 +.names 28836 28843 +1 1 +.names 28843 28844 +0 1 +.names 28842 28844 28845 +11 1 +.names 28830 28846 +0 1 +.names 28852 28853 28847 +1- 1 +-1 1 +.names 28847 28848 +1 1 +.names 28854 28856 28849 +11 1 +.names 28849 28850 +1 1 +.names 28850 28851 +0 1 +.names 28759 28851 28852 +11 1 +.names 7550 2413 28853 +11 1 +.names 7546 28854 +0 1 +.names 27782 28855 +1 1 +.names 28855 28856 +0 1 +.names 28863 28864 28857 +1- 1 +-1 1 +.names 28857 28858 +1 1 +.names 27782 28859 +1 1 +.names 28859 28860 +0 1 +.names 28854 28861 +1 1 +.names 28861 28862 +0 1 +.names 28860 28862 28863 +11 1 +.names 28848 28864 +0 1 +.names 28871 28872 28865 +1- 1 +-1 1 +.names 28865 28866 +1 1 +.names 7549 28867 +0 1 +.names 28836 28874 28868 +11 1 +.names 28868 28869 +1 1 +.names 28869 28870 +0 1 +.names 28867 28870 28871 +11 1 +.names 7549 2413 28872 +11 1 +.names 27799 28873 +1 1 +.names 28873 28874 +0 1 +.names 28881 28882 28875 +1- 1 +-1 1 +.names 28875 28876 +1 1 +.names 2413 28877 +1 1 +.names 28877 28878 +0 1 +.names 28836 28879 +1 1 +.names 28879 28880 +0 1 +.names 28878 28880 28881 +11 1 +.names 28866 28882 +0 1 +.names 28888 28889 28883 +1- 1 +-1 1 +.names 28883 28884 +1 1 +.names 28854 28891 28885 +11 1 +.names 28885 28886 +1 1 +.names 28886 28887 +0 1 +.names 28778 28887 28888 +11 1 +.names 7539 2413 28889 +11 1 +.names 27815 28890 +1 1 +.names 28890 28891 +0 1 +.names 28898 28899 28892 +1- 1 +-1 1 +.names 28892 28893 +1 1 +.names 27815 28894 +1 1 +.names 28894 28895 +0 1 +.names 28854 28896 +1 1 +.names 28896 28897 +0 1 +.names 28895 28897 28898 +11 1 +.names 28884 28899 +0 1 +.names 28905 28906 28900 +1- 1 +-1 1 +.names 28900 28901 +1 1 +.names 28836 28908 28902 +11 1 +.names 28902 28903 +1 1 +.names 28903 28904 +0 1 +.names 28759 28904 28905 +11 1 +.names 7550 2413 28906 +11 1 +.names 27831 28907 +1 1 +.names 28907 28908 +0 1 +.names 28915 28916 28909 +1- 1 +-1 1 +.names 28909 28910 +1 1 +.names 2413 28911 +1 1 +.names 28911 28912 +0 1 +.names 28836 28913 +1 1 +.names 28913 28914 +0 1 +.names 28912 28914 28915 +11 1 +.names 28901 28916 +0 1 +.names 28794 28917 +1 1 +.names 28794 28921 28918 +11 1 +.names 28918 28919 +1 1 +.names 27843 28920 +1 1 +.names 28920 28921 +0 1 +.names 28925 28926 28922 +1- 1 +-1 1 +.names 28922 28923 +1 1 +.names 28919 28924 +0 1 +.names 28867 28924 28925 +11 1 +.names 7549 2413 28926 +11 1 +.names 27843 28927 +1 1 +.names 28932 28933 28928 +1- 1 +-1 1 +.names 28928 28929 +1 1 +.names 28917 28930 +0 1 +.names 28927 28931 +0 1 +.names 28930 28931 28932 +11 1 +.names 28923 28933 +0 1 +.names 28794 28934 +1 1 +.names 28794 28938 28935 +11 1 +.names 28935 28936 +1 1 +.names 27859 28937 +1 1 +.names 28937 28938 +0 1 +.names 28942 28943 28939 +1- 1 +-1 1 +.names 28939 28940 +1 1 +.names 28936 28941 +0 1 +.names 28778 28941 28942 +11 1 +.names 7539 2413 28943 +11 1 +.names 27859 28944 +1 1 +.names 28949 28950 28945 +1- 1 +-1 1 +.names 28945 28946 +1 1 +.names 28934 28947 +0 1 +.names 28944 28948 +0 1 +.names 28947 28948 28949 +11 1 +.names 28940 28950 +0 1 +.names 28956 28957 28951 +1- 1 +-1 1 +.names 28951 28952 +1 1 +.names 28836 28959 28953 +11 1 +.names 28953 28954 +1 1 +.names 28954 28955 +0 1 +.names 28759 28955 28956 +11 1 +.names 7550 2413 28957 +11 1 +.names 27879 28958 +1 1 +.names 28958 28959 +0 1 +.names 28966 28967 28960 +1- 1 +-1 1 +.names 28960 28961 +1 1 +.names 27879 28962 +1 1 +.names 28962 28963 +0 1 +.names 28836 28964 +1 1 +.names 28964 28965 +0 1 +.names 28963 28965 28966 +11 1 +.names 28952 28967 +0 1 +.names 28973 28974 28968 +1- 1 +-1 1 +.names 28968 28969 +1 1 +.names 28836 28976 28970 +11 1 +.names 28970 28971 +1 1 +.names 28971 28972 +0 1 +.names 28778 28972 28973 +11 1 +.names 7539 2413 28974 +11 1 +.names 27895 28975 +1 1 +.names 28975 28976 +0 1 +.names 28983 28984 28977 +1- 1 +-1 1 +.names 28977 28978 +1 1 +.names 27895 28979 +1 1 +.names 28979 28980 +0 1 +.names 28836 28981 +1 1 +.names 28981 28982 +0 1 +.names 28980 28982 28983 +11 1 +.names 28969 28984 +0 1 +.names 28990 28991 28985 +1- 1 +-1 1 +.names 28985 28986 +1 1 +.names 28836 28993 28987 +11 1 +.names 28987 28988 +1 1 +.names 28988 28989 +0 1 +.names 28778 28989 28990 +11 1 +.names 7539 2413 28991 +11 1 +.names 27911 28992 +1 1 +.names 28992 28993 +0 1 +.names 29000 29001 28994 +1- 1 +-1 1 +.names 28994 28995 +1 1 +.names 27911 28996 +1 1 +.names 28996 28997 +0 1 +.names 28836 28998 +1 1 +.names 28998 28999 +0 1 +.names 28997 28999 29000 +11 1 +.names 28986 29001 +0 1 +.names 29007 29008 29002 +1- 1 +-1 1 +.names 29002 29003 +1 1 +.names 28854 29010 29004 +11 1 +.names 29004 29005 +1 1 +.names 29005 29006 +0 1 +.names 28778 29006 29007 +11 1 +.names 7539 2413 29008 +11 1 +.names 27927 29009 +1 1 +.names 29009 29010 +0 1 +.names 29017 29018 29011 +1- 1 +-1 1 +.names 29011 29012 +1 1 +.names 27927 29013 +1 1 +.names 29013 29014 +0 1 +.names 28854 29015 +1 1 +.names 29015 29016 +0 1 +.names 29014 29016 29017 +11 1 +.names 29003 29018 +0 1 +.names 29024 29025 29019 +1- 1 +-1 1 +.names 29019 29020 +1 1 +.names 28765 29027 29021 +11 1 +.names 29021 29022 +1 1 +.names 29022 29023 +0 1 +.names 28867 29023 29024 +11 1 +.names 7549 2413 29025 +11 1 +.names 27943 29026 +1 1 +.names 29026 29027 +0 1 +.names 29034 29035 29028 +1- 1 +-1 1 +.names 29028 29029 +1 1 +.names 27943 29030 +1 1 +.names 29030 29031 +0 1 +.names 28765 29032 +1 1 +.names 29032 29033 +0 1 +.names 29031 29033 29034 +11 1 +.names 29020 29035 +0 1 +.names 29041 29042 29036 +1- 1 +-1 1 +.names 29036 29037 +1 1 +.names 28836 29044 29038 +11 1 +.names 29038 29039 +1 1 +.names 29039 29040 +0 1 +.names 28867 29040 29041 +11 1 +.names 7549 2413 29042 +11 1 +.names 27959 29043 +1 1 +.names 29043 29044 +0 1 +.names 29051 29052 29045 +1- 1 +-1 1 +.names 29045 29046 +1 1 +.names 28836 29047 +1 1 +.names 29047 29048 +0 1 +.names 27959 29049 +1 1 +.names 29049 29050 +0 1 +.names 29048 29050 29051 +11 1 +.names 29037 29052 +0 1 +.names 28794 29053 +1 1 +.names 28794 29057 29054 +11 1 +.names 29054 29055 +1 1 +.names 27971 29056 +1 1 +.names 29056 29057 +0 1 +.names 29061 29062 29058 +1- 1 +-1 1 +.names 29058 29059 +1 1 +.names 29055 29060 +0 1 +.names 28759 29060 29061 +11 1 +.names 7550 2413 29062 +11 1 +.names 2413 29063 +1 1 +.names 29053 29064 +0 1 +.names 29063 29065 +0 1 +.names 29064 29065 29066 +11 1 +.names 29059 29067 +0 1 +.names 29073 29074 29068 +1- 1 +-1 1 +.names 29068 29069 +1 1 +.names 28794 29076 29070 +11 1 +.names 29070 29071 +1 1 +.names 29071 29072 +0 1 +.names 28759 29072 29073 +11 1 +.names 7550 2413 29074 +11 1 +.names 27991 29075 +1 1 +.names 29075 29076 +0 1 +.names 29083 29084 29077 +1- 1 +-1 1 +.names 29077 29078 +1 1 +.names 27991 29079 +1 1 +.names 29079 29080 +0 1 +.names 28794 29081 +1 1 +.names 29081 29082 +0 1 +.names 29080 29082 29083 +11 1 +.names 29069 29084 +0 1 +.names 29090 29091 29085 +1- 1 +-1 1 +.names 29085 29086 +1 1 +.names 28854 29093 29087 +11 1 +.names 29087 29088 +1 1 +.names 29088 29089 +0 1 +.names 28867 29089 29090 +11 1 +.names 7549 2413 29091 +11 1 +.names 28007 29092 +1 1 +.names 29092 29093 +0 1 +.names 29100 29101 29094 +1- 1 +-1 1 +.names 29094 29095 +1 1 +.names 28007 29096 +1 1 +.names 29096 29097 +0 1 +.names 28854 29098 +1 1 +.names 29098 29099 +0 1 +.names 29097 29099 29100 +11 1 +.names 29086 29101 +0 1 +.names 29107 29108 29102 +1- 1 +-1 1 +.names 29102 29103 +1 1 +.names 28854 29110 29104 +11 1 +.names 29104 29105 +1 1 +.names 29105 29106 +0 1 +.names 28867 29106 29107 +11 1 +.names 7549 2413 29108 +11 1 +.names 28023 29109 +1 1 +.names 29109 29110 +0 1 +.names 29117 29118 29111 +1- 1 +-1 1 +.names 29111 29112 +1 1 +.names 28023 29113 +1 1 +.names 29113 29114 +0 1 +.names 28854 29115 +1 1 +.names 29115 29116 +0 1 +.names 29114 29116 29117 +11 1 +.names 29103 29118 +0 1 +.names 29124 29125 29119 +1- 1 +-1 1 +.names 29119 29120 +1 1 +.names 28854 29127 29121 +11 1 +.names 29121 29122 +1 1 +.names 29122 29123 +0 1 +.names 28759 29123 29124 +11 1 +.names 7550 2413 29125 +11 1 +.names 28039 29126 +1 1 +.names 29126 29127 +0 1 +.names 29134 29135 29128 +1- 1 +-1 1 +.names 29128 29129 +1 1 +.names 28039 29130 +1 1 +.names 29130 29131 +0 1 +.names 28854 29132 +1 1 +.names 29132 29133 +0 1 +.names 29131 29133 29134 +11 1 +.names 29120 29135 +0 1 +.names 29141 29142 29136 +1- 1 +-1 1 +.names 29136 29137 +1 1 +.names 28794 29144 29138 +11 1 +.names 29138 29139 +1 1 +.names 29139 29140 +0 1 +.names 28778 29140 29141 +11 1 +.names 7539 2413 29142 +11 1 +.names 28055 29143 +1 1 +.names 29143 29144 +0 1 +.names 29151 29152 29145 +1- 1 +-1 1 +.names 29145 29146 +1 1 +.names 28794 29147 +1 1 +.names 29147 29148 +0 1 +.names 28055 29149 +1 1 +.names 29149 29150 +0 1 +.names 29148 29150 29151 +11 1 +.names 29137 29152 +0 1 +.names 28794 29153 +1 1 +.names 28794 29157 29154 +11 1 +.names 29154 29155 +1 1 +.names 28067 29156 +1 1 +.names 29156 29157 +0 1 +.names 29161 29162 29158 +1- 1 +-1 1 +.names 29158 29159 +1 1 +.names 29155 29160 +0 1 +.names 28867 29160 29161 +11 1 +.names 7549 2413 29162 +11 1 +.names 28067 29163 +1 1 +.names 29168 29169 29164 +1- 1 +-1 1 +.names 29164 29165 +1 1 +.names 29153 29166 +0 1 +.names 29163 29167 +0 1 +.names 29166 29167 29168 +11 1 +.names 29159 29169 +0 1 +.names 29175 29176 29170 +1- 1 +-1 1 +.names 29170 29171 +1 1 +.names 28836 29178 29172 +11 1 +.names 29172 29173 +1 1 +.names 29173 29174 +0 1 +.names 28867 29174 29175 +11 1 +.names 7549 2413 29176 +11 1 +.names 28087 29177 +1 1 +.names 29177 29178 +0 1 +.names 29185 29186 29179 +1- 1 +-1 1 +.names 29179 29180 +1 1 +.names 28087 29181 +1 1 +.names 29181 29182 +0 1 +.names 28836 29183 +1 1 +.names 29183 29184 +0 1 +.names 29182 29184 29185 +11 1 +.names 29171 29186 +0 1 +.names 29192 29193 29187 +1- 1 +-1 1 +.names 29187 29188 +1 1 +.names 28854 29195 29189 +11 1 +.names 29189 29190 +1 1 +.names 29190 29191 +0 1 +.names 28867 29191 29192 +11 1 +.names 7549 2413 29193 +11 1 +.names 28103 29194 +1 1 +.names 29194 29195 +0 1 +.names 29202 29203 29196 +1- 1 +-1 1 +.names 29196 29197 +1 1 +.names 28103 29198 +1 1 +.names 29198 29199 +0 1 +.names 28854 29200 +1 1 +.names 29200 29201 +0 1 +.names 29199 29201 29202 +11 1 +.names 29188 29203 +0 1 +.names 28794 29204 +1 1 +.names 28794 29208 29205 +11 1 +.names 29205 29206 +1 1 +.names 28115 29207 +1 1 +.names 29207 29208 +0 1 +.names 29212 29213 29209 +1- 1 +-1 1 +.names 29209 29210 +1 1 +.names 29206 29211 +0 1 +.names 28759 29211 29212 +11 1 +.names 7550 2413 29213 +11 1 +.names 28115 29214 +1 1 +.names 29219 29220 29215 +1- 1 +-1 1 +.names 29215 29216 +1 1 +.names 29204 29217 +0 1 +.names 29214 29218 +0 1 +.names 29217 29218 29219 +11 1 +.names 29210 29220 +0 1 +.names 29226 29227 29221 +1- 1 +-1 1 +.names 29221 29222 +1 1 +.names 28854 29229 29223 +11 1 +.names 29223 29224 +1 1 +.names 29224 29225 +0 1 +.names 28867 29225 29226 +11 1 +.names 7549 2413 29227 +11 1 +.names 28135 29228 +1 1 +.names 29228 29229 +0 1 +.names 29236 29237 29230 +1- 1 +-1 1 +.names 29230 29231 +1 1 +.names 28135 29232 +1 1 +.names 29232 29233 +0 1 +.names 28854 29234 +1 1 +.names 29234 29235 +0 1 +.names 29233 29235 29236 +11 1 +.names 29222 29237 +0 1 +.names 29243 29244 29238 +1- 1 +-1 1 +.names 29238 29239 +1 1 +.names 28854 29246 29240 +11 1 +.names 29240 29241 +1 1 +.names 29241 29242 +0 1 +.names 28778 29242 29243 +11 1 +.names 7539 2413 29244 +11 1 +.names 28151 29245 +1 1 +.names 29245 29246 +0 1 +.names 29253 29254 29247 +1- 1 +-1 1 +.names 29247 29248 +1 1 +.names 28151 29249 +1 1 +.names 29249 29250 +0 1 +.names 28854 29251 +1 1 +.names 29251 29252 +0 1 +.names 29250 29252 29253 +11 1 +.names 29239 29254 +0 1 +.names 28794 29255 +1 1 +.names 28794 29259 29256 +11 1 +.names 29256 29257 +1 1 +.names 28163 29258 +1 1 +.names 29258 29259 +0 1 +.names 29263 29264 29260 +1- 1 +-1 1 +.names 29260 29261 +1 1 +.names 29257 29262 +0 1 +.names 28867 29262 29263 +11 1 +.names 7549 2413 29264 +11 1 +.names 29270 29271 29265 +1- 1 +-1 1 +.names 29265 29266 +1 1 +.names 29255 29267 +0 1 +.names 28163 29268 +1 1 +.names 29268 29269 +0 1 +.names 29267 29269 29270 +11 1 +.names 29261 29271 +0 1 +.names 29277 29278 29272 +1- 1 +-1 1 +.names 29272 29273 +1 1 +.names 28765 29280 29274 +11 1 +.names 29274 29275 +1 1 +.names 29275 29276 +0 1 +.names 28778 29276 29277 +11 1 +.names 7539 2413 29278 +11 1 +.names 28183 29279 +1 1 +.names 29279 29280 +0 1 +.names 29287 29288 29281 +1- 1 +-1 1 +.names 29281 29282 +1 1 +.names 28183 29283 +1 1 +.names 29283 29284 +0 1 +.names 28765 29285 +1 1 +.names 29285 29286 +0 1 +.names 29284 29286 29287 +11 1 +.names 29273 29288 +0 1 +.names 29294 29295 29289 +1- 1 +-1 1 +.names 29289 29290 +1 1 +.names 28836 29297 29291 +11 1 +.names 29291 29292 +1 1 +.names 29292 29293 +0 1 +.names 28759 29293 29294 +11 1 +.names 7550 2413 29295 +11 1 +.names 28199 29296 +1 1 +.names 29296 29297 +0 1 +.names 29304 29305 29298 +1- 1 +-1 1 +.names 29298 29299 +1 1 +.names 28199 29300 +1 1 +.names 29300 29301 +0 1 +.names 28836 29302 +1 1 +.names 29302 29303 +0 1 +.names 29301 29303 29304 +11 1 +.names 29290 29305 +0 1 +.names 29310 29313 29306 +1- 1 +-1 1 +.names 29306 29307 +1 1 +.names 28529 29690 29308 +01 1 +10 1 +.names 29308 29309 +1 1 +.names 29309 29310 +0 1 +.names 29387 29389 29311 +11 1 +.names 29311 29312 +1 1 +.names 29312 29313 +0 1 +.names 29317 29319 29314 +11 1 +.names 29314 29315 +1 1 +.names 29459 29316 +0 1 +.names 29316 29317 +1 1 +.names 29307 29318 +0 1 +.names 29318 29319 +1 1 +.names 29328 29330 29320 +1- 1 +-1 1 +.names 29320 29321 +1 1 +.names 29361 29322 +0 1 +.names 29322 29323 +1 1 +.names 29323 29324 +0 1 +.names 29715 29609 29325 +11 1 +.names 29325 29326 +1 1 +.names 29326 29327 +0 1 +.names 29324 29327 29328 +11 1 +.names 28412 29329 +0 1 +.names 29323 29329 29330 +11 1 +.names 29339 29341 29331 +1- 1 +-1 1 +.names 29331 29332 +1 1 +.names 29596 29333 +0 1 +.names 29333 29334 +1 1 +.names 29334 29335 +0 1 +.names 29710 29713 29336 +1- 1 +-1 1 +.names 29336 29337 +1 1 +.names 29337 29338 +0 1 +.names 29335 29338 29339 +11 1 +.names 28717 29340 +0 1 +.names 29334 29340 29341 +11 1 +.names 29347 29349 29342 +1- 1 +-1 1 +.names 29342 29343 +1 1 +.names 29607 29609 29344 +11 1 +.names 29344 29345 +1 1 +.names 29345 29346 +0 1 +.names 29324 29346 29347 +11 1 +.names 28961 29348 +0 1 +.names 29323 29348 29349 +11 1 +.names 29355 29357 29350 +1- 1 +-1 1 +.names 29350 29351 +1 1 +.names 29601 29604 29352 +1- 1 +-1 1 +.names 29352 29353 +1 1 +.names 29353 29354 +0 1 +.names 29335 29354 29355 +11 1 +.names 29266 29356 +0 1 +.names 29334 29356 29357 +11 1 +.names 29364 29366 29358 +11 1 +.names 29358 29359 +1 1 +.names 28412 29605 29360 +01 1 +10 1 +.names 29360 29361 +1 1 +.names 29609 29362 +0 1 +.names 29362 29363 +1 1 +.names 29361 29363 29364 +11 1 +.names 29646 29365 +0 1 +.names 29365 29366 +1 1 +.names 29370 29359 29367 +11 1 +.names 29367 29368 +1 1 +.names 28995 29777 29369 +01 1 +10 1 +.names 29369 29370 +1 1 +.names 29380 29382 29371 +11 1 +.names 29371 29372 +1 1 +.names 28616 29672 29373 +01 1 +10 1 +.names 29373 29374 +1 1 +.names 28327 29670 29375 +01 1 +10 1 +.names 29375 29376 +1 1 +.names 29374 29376 29377 +11 1 +.names 28750 29668 29378 +01 1 +10 1 +.names 29378 29379 +1 1 +.names 29377 29379 29380 +11 1 +.names 11103 29611 29381 +01 1 +10 1 +.names 29381 29382 +1 1 +.names 28682 29556 29383 +01 1 +10 1 +.names 29383 29384 +1 1 +.names 29397 29399 29385 +11 1 +.names 29385 29386 +1 1 +.names 29384 29386 29387 +11 1 +.names 29545 29388 +0 1 +.names 29388 29389 +1 1 +.names 28893 29748 29390 +01 1 +10 1 +.names 29390 29391 +1 1 +.names 28480 29750 29392 +01 1 +10 1 +.names 29392 29393 +1 1 +.names 29391 29393 29394 +11 1 +.names 29554 29395 +0 1 +.names 29395 29396 +1 1 +.names 29394 29396 29397 +11 1 +.names 29405 29407 29398 +11 1 +.names 29398 29399 +1 1 +.names 29755 29757 29400 +11 1 +.names 29400 29401 +1 1 +.names 29569 29402 +0 1 +.names 29402 29403 +1 1 +.names 29401 29403 29404 +11 1 +.names 29404 29372 29405 +11 1 +.names 28733 29752 29406 +01 1 +10 1 +.names 29406 29407 +1 1 +.names 29414 29416 29408 +11 1 +.names 29408 29409 +1 1 +.names 28238 29776 29410 +01 1 +10 1 +.names 29410 29411 +1 1 +.names 28546 29771 29412 +01 1 +10 1 +.names 29412 29413 +1 1 +.names 29411 29413 29414 +11 1 +.names 29548 29415 +0 1 +.names 29415 29416 +1 1 +.names 29420 29417 +0 1 +.names 29417 29418 +1 1 +.names 29572 29573 29419 +1- 1 +-1 1 +.names 29419 29420 +1 1 +.names 29429 29430 29421 +11 1 +.names 29421 29422 +1 1 +.names 29372 29423 +0 1 +.names 29687 29574 29424 +1- 1 +-1 1 +.names 29424 29425 +1 1 +.names 29425 29426 +0 1 +.names 29423 29426 29427 +1- 1 +-1 1 +.names 29319 29428 +0 1 +.names 29427 29428 29429 +11 1 +.names 29418 29430 +0 1 +.names 29440 29443 29431 +11 1 +.names 29431 29432 +1 1 +.names 29386 29433 +0 1 +.names 29661 29662 29434 +1- 1 +-1 1 +.names 29434 29435 +1 1 +.names 29435 29436 +0 1 +.names 29433 29436 29437 +1- 1 +-1 1 +.names 29078 29438 +0 1 +.names 29313 29438 29439 +1- 1 +-1 1 +.names 29437 29439 29440 +11 1 +.names 29625 29626 29441 +1- 1 +-1 1 +.names 29441 29442 +1 1 +.names 29442 29443 +0 1 +.names 29447 29444 +0 1 +.names 29444 29445 +1 1 +.names 29643 29644 29446 +1- 1 +-1 1 +.names 29446 29447 +1 1 +.names 29443 29448 +1 1 +.names 29452 29445 29449 +11 1 +.names 29449 29450 +1 1 +.names 29351 29448 29451 +11 1 +.names 29451 29343 29452 +11 1 +.names 29464 29467 29453 +11 1 +.names 29453 29454 +1 1 +.names 29561 29562 29455 +1- 1 +-1 1 +.names 29455 29456 +1 1 +.names 29456 29457 +0 1 +.names 29485 29488 29458 +1- 1 +-1 1 +.names 29458 29459 +1 1 +.names 29457 29316 29460 +1- 1 +-1 1 +.names 29417 29574 29461 +1- 1 +-1 1 +.names 29461 29462 +1 1 +.names 29462 29463 +0 1 +.names 29460 29463 29464 +11 1 +.names 29592 29593 29465 +1- 1 +-1 1 +.names 29465 29466 +1 1 +.names 29466 29467 +0 1 +.names 29313 29472 29468 +1- 1 +-1 1 +.names 29468 29469 +1 1 +.names 29078 28529 29470 +01 1 +10 1 +.names 29470 29471 +1 1 +.names 29471 29472 +0 1 +.names 29479 29482 29473 +11 1 +.names 29473 29474 +1 1 +.names 29469 29475 +0 1 +.names 29454 29476 +0 1 +.names 29475 29476 29477 +1- 1 +-1 1 +.names 29450 29478 +0 1 +.names 29477 29478 29479 +1- 1 +-1 1 +.names 29432 29480 +0 1 +.names 29422 29481 +0 1 +.names 29480 29481 29482 +1- 1 +-1 1 +.names 28361 29689 29483 +01 1 +10 1 +.names 29483 29484 +1 1 +.names 29484 29485 +0 1 +.names 28220 29558 29486 +01 1 +10 1 +.names 29486 29487 +1 1 +.names 29487 29488 +0 1 +.names 29492 29489 +0 1 +.names 29489 29490 +1 1 +.names 29695 29573 29491 +1- 1 +-1 1 +.names 29491 29492 +1 1 +.names 29499 29500 29493 +11 1 +.names 29493 29494 +1 1 +.names 29744 29701 29495 +1- 1 +-1 1 +.names 29495 29496 +1 1 +.names 29496 29497 +0 1 +.names 29423 29497 29498 +1- 1 +-1 1 +.names 29498 29428 29499 +11 1 +.names 29490 29500 +0 1 +.names 29509 29512 29501 +11 1 +.names 29501 29502 +1 1 +.names 29742 29743 29503 +1- 1 +-1 1 +.names 29503 29504 +1 1 +.names 29504 29505 +0 1 +.names 29433 29505 29506 +1- 1 +-1 1 +.names 28529 29507 +0 1 +.names 29313 29507 29508 +1- 1 +-1 1 +.names 29506 29508 29509 +11 1 +.names 29708 29709 29510 +1- 1 +-1 1 +.names 29510 29511 +1 1 +.names 29511 29512 +0 1 +.names 29516 29513 +0 1 +.names 29513 29514 +1 1 +.names 29737 29738 29515 +1- 1 +-1 1 +.names 29515 29516 +1 1 +.names 29520 29517 +0 1 +.names 29517 29518 +1 1 +.names 29722 29723 29519 +1- 1 +-1 1 +.names 29519 29520 +1 1 +.names 29524 29514 29521 +11 1 +.names 29521 29522 +1 1 +.names 29332 29518 29523 +11 1 +.names 29523 29321 29524 +11 1 +.names 29534 29512 29525 +11 1 +.names 29525 29526 +1 1 +.names 29691 29692 29527 +1- 1 +-1 1 +.names 29527 29528 +1 1 +.names 29528 29529 +0 1 +.names 29529 29316 29530 +1- 1 +-1 1 +.names 29701 29489 29531 +1- 1 +-1 1 +.names 29531 29532 +1 1 +.names 29532 29533 +0 1 +.names 29530 29533 29534 +11 1 +.names 29540 29543 29535 +11 1 +.names 29535 29536 +1 1 +.names 29526 29537 +0 1 +.names 29475 29537 29538 +1- 1 +-1 1 +.names 29522 29539 +0 1 +.names 29538 29539 29540 +1- 1 +-1 1 +.names 29502 29541 +0 1 +.names 29494 29542 +0 1 +.names 29541 29542 29543 +1- 1 +-1 1 +.names 29551 29552 29544 +1- 1 +-1 1 +.names 29544 29545 +1 1 +.names 29413 29546 +0 1 +.names 28699 29773 29547 +01 1 +10 1 +.names 29547 29548 +1 1 +.names 29546 29415 29549 +1- 1 +-1 1 +.names 29411 29550 +0 1 +.names 29549 29550 29551 +1- 1 +-1 1 +.names 29368 29552 +0 1 +.names 29768 29758 29553 +1- 1 +-1 1 +.names 29553 29554 +1 1 +.names 29231 29555 +0 1 +.names 29555 29556 +1 1 +.names 28769 29557 +0 1 +.names 29557 29558 +1 1 +.names 29488 29559 +1 1 +.names 29559 29560 +0 1 +.names 29560 28910 29561 +11 1 +.names 29559 28769 29562 +11 1 +.names 29567 29402 29563 +1- 1 +-1 1 +.names 29563 29564 +1 1 +.names 29802 29803 29565 +1- 1 +-1 1 +.names 29565 29566 +1 1 +.names 29566 29567 +0 1 +.names 29683 29686 29568 +1- 1 +-1 1 +.names 29568 29569 +1 1 +.names 29788 29789 29570 +1- 1 +-1 1 +.names 29570 29571 +1 1 +.names 29571 29572 +0 1 +.names 29399 29573 +0 1 +.names 29564 29574 +0 1 +.names 29046 29575 +0 1 +.names 29575 29576 +1 1 +.names 28497 29576 29577 +01 1 +10 1 +.names 29577 29578 +1 1 +.names 29578 29579 +0 1 +.names 29579 29580 +1 1 +.names 29584 29581 +0 1 +.names 29581 29582 +1 1 +.names 29823 29808 29583 +1- 1 +-1 1 +.names 29583 29584 +1 1 +.names 29587 29590 29585 +1- 1 +-1 1 +.names 29585 29586 +1 1 +.names 29582 29282 29587 +11 1 +.names 29815 29816 29588 +1- 1 +-1 1 +.names 29588 29589 +1 1 +.names 29589 29590 +0 1 +.names 29580 29591 +0 1 +.names 29591 29586 29592 +11 1 +.names 29580 29046 29593 +11 1 +.names 29340 29594 +1 1 +.names 29266 29594 29595 +01 1 +10 1 +.names 29595 29596 +1 1 +.names 29600 29597 +0 1 +.names 29597 29598 +1 1 +.names 29843 29653 29599 +1- 1 +-1 1 +.names 29599 29600 +1 1 +.names 29598 29180 29601 +11 1 +.names 29833 29834 29602 +1- 1 +-1 1 +.names 29602 29603 +1 1 +.names 29603 29604 +0 1 +.names 29348 29605 +1 1 +.names 29860 29861 29606 +1- 1 +-1 1 +.names 29606 29607 +1 1 +.names 29868 29869 29608 +1- 1 +-1 1 +.names 29608 29609 +1 1 +.names 11101 29610 +0 1 +.names 29610 29611 +1 1 +.names 29382 29612 +0 1 +.names 29612 29613 +1 1 +.names 29617 29614 +0 1 +.names 29614 29615 +1 1 +.names 29881 29665 29616 +1- 1 +-1 1 +.names 29616 29617 +1 1 +.names 29620 29623 29618 +1- 1 +-1 1 +.names 29618 29619 +1 1 +.names 29615 29165 29620 +11 1 +.names 29874 29875 29621 +1- 1 +-1 1 +.names 29621 29622 +1 1 +.names 29622 29623 +0 1 +.names 29613 29624 +0 1 +.names 29624 29619 29625 +11 1 +.names 29613 11101 29626 +11 1 +.names 29370 29627 +0 1 +.names 29627 29628 +1 1 +.names 29635 29639 29629 +11 1 +.names 29629 29630 +1 1 +.names 28995 29631 +0 1 +.names 29628 29632 +0 1 +.names 29631 29632 29633 +1- 1 +-1 1 +.names 29359 29634 +0 1 +.names 29633 29634 29635 +1- 1 +-1 1 +.names 29889 29890 29636 +1- 1 +-1 1 +.names 29636 29637 +1 1 +.names 29637 29638 +0 1 +.names 29552 29638 29639 +1- 1 +-1 1 +.names 29384 29640 +0 1 +.names 29388 29640 29641 +11 1 +.names 29556 29642 +0 1 +.names 29641 29642 29643 +11 1 +.names 29630 29644 +0 1 +.names 29654 29657 29645 +1- 1 +-1 1 +.names 29645 29646 +1 1 +.names 29180 29837 29647 +01 1 +10 1 +.names 29647 29648 +1 1 +.names 29648 29649 +0 1 +.names 29649 29333 29650 +1- 1 +-1 1 +.names 28580 29835 29651 +01 1 +10 1 +.names 29651 29652 +1 1 +.names 29652 29653 +0 1 +.names 29650 29653 29654 +1- 1 +-1 1 +.names 28597 29825 29655 +01 1 +10 1 +.names 29655 29656 +1 1 +.names 29656 29657 +0 1 +.names 29343 29658 +0 1 +.names 29365 29658 29659 +11 1 +.names 29351 29660 +0 1 +.names 29659 29660 29661 +1- 1 +-1 1 +.names 29445 29662 +0 1 +.names 29379 29663 +0 1 +.names 29663 29664 +1 1 +.names 29376 29665 +0 1 +.names 29665 29666 +1 1 +.names 29299 29667 +0 1 +.names 29667 29668 +1 1 +.names 28876 29669 +0 1 +.names 29669 29670 +1 1 +.names 29165 29671 +0 1 +.names 29671 29672 +1 1 +.names 28429 29892 29673 +01 1 +10 1 +.names 29673 29674 +1 1 +.names 29674 29675 +0 1 +.names 28648 29894 29676 +01 1 +10 1 +.names 29676 29677 +1 1 +.names 29677 29678 +0 1 +.names 29675 29678 29679 +1- 1 +-1 1 +.names 29216 29791 29680 +01 1 +10 1 +.names 29680 29681 +1 1 +.names 29681 29682 +0 1 +.names 29679 29682 29683 +1- 1 +-1 1 +.names 28397 29897 29684 +01 1 +10 1 +.names 29684 29685 +1 1 +.names 29685 29686 +0 1 +.names 29466 29403 29687 +11 1 +.names 28910 29688 +0 1 +.names 29688 29689 +1 1 +.names 29438 29690 +1 1 +.names 29560 28361 29691 +11 1 +.names 29559 28220 29692 +11 1 +.names 29916 29917 29693 +1- 1 +-1 1 +.names 29693 29694 +1 1 +.names 29694 29695 +0 1 +.names 29700 29402 29696 +1- 1 +-1 1 +.names 29696 29697 +1 1 +.names 29904 29905 29698 +1- 1 +-1 1 +.names 29698 29699 +1 1 +.names 29699 29700 +0 1 +.names 29697 29701 +0 1 +.names 29704 29707 29702 +1- 1 +-1 1 +.names 29702 29703 +1 1 +.names 29615 28616 29704 +11 1 +.names 29923 29924 29705 +1- 1 +-1 1 +.names 29705 29706 +1 1 +.names 29706 29707 +0 1 +.names 29624 29703 29708 +11 1 +.names 29613 11103 29709 +11 1 +.names 29598 28631 29710 +11 1 +.names 29930 29931 29711 +1- 1 +-1 1 +.names 29711 29712 +1 1 +.names 29712 29713 +0 1 +.names 29936 29937 29714 +1- 1 +-1 1 +.names 29714 29715 +1 1 +.names 29718 29721 29716 +1- 1 +-1 1 +.names 29716 29717 +1 1 +.names 29582 28733 29718 +11 1 +.names 29943 29944 29719 +1- 1 +-1 1 +.names 29719 29720 +1 1 +.names 29720 29721 +0 1 +.names 29591 29717 29722 +11 1 +.names 29580 28497 29723 +11 1 +.names 29728 29732 29724 +11 1 +.names 29724 29725 +1 1 +.names 28446 29726 +0 1 +.names 29726 29632 29727 +1- 1 +-1 1 +.names 29727 29634 29728 +1- 1 +-1 1 +.names 29953 29954 29729 +1- 1 +-1 1 +.names 29729 29730 +1 1 +.names 29730 29731 +0 1 +.names 29552 29731 29732 +1- 1 +-1 1 +.names 28682 29733 +0 1 +.names 29733 29734 +1 1 +.names 29388 29640 29735 +11 1 +.names 29734 29736 +0 1 +.names 29735 29736 29737 +11 1 +.names 29725 29738 +0 1 +.names 29321 29739 +0 1 +.names 29365 29739 29740 +11 1 +.names 29332 29741 +0 1 +.names 29740 29741 29742 +1- 1 +-1 1 +.names 29514 29743 +0 1 +.names 29520 29403 29744 +11 1 +.names 29391 29745 +0 1 +.names 29745 29746 +1 1 +.names 28344 29747 +0 1 +.names 29747 29748 +1 1 +.names 29029 29749 +0 1 +.names 29749 29750 +1 1 +.names 29282 29751 +0 1 +.names 29751 29752 +1 1 +.names 28563 29817 29753 +01 1 +10 1 +.names 29753 29754 +1 1 +.names 29754 29578 29755 +11 1 +.names 28258 29805 29756 +01 1 +10 1 +.names 29756 29757 +1 1 +.names 29761 29758 +0 1 +.names 29758 29759 +1 1 +.names 28463 29763 29760 +01 1 +10 1 +.names 29760 29761 +1 1 +.names 29012 29762 +0 1 +.names 29762 29763 +1 1 +.names 28858 29764 +0 1 +.names 29764 29765 +1 1 +.names 28309 29765 29766 +01 1 +10 1 +.names 29766 29767 +1 1 +.names 29767 29768 +0 1 +.names 29546 29769 +1 1 +.names 29095 29770 +0 1 +.names 29770 29771 +1 1 +.names 29248 29772 +0 1 +.names 29772 29773 +1 1 +.names 29550 29774 +1 1 +.names 28787 29775 +0 1 +.names 29775 29776 +1 1 +.names 29726 29777 +1 1 +.names 29783 29786 29778 +1- 1 +-1 1 +.names 29778 29779 +1 1 +.names 29393 29780 +0 1 +.names 29395 29780 29781 +11 1 +.names 29750 29782 +0 1 +.names 29781 29782 29783 +11 1 +.names 29961 29962 29784 +1- 1 +-1 1 +.names 29784 29785 +1 1 +.names 29785 29786 +0 1 +.names 29746 29787 +0 1 +.names 29787 29779 29788 +11 1 +.names 29746 28893 29789 +11 1 +.names 28667 29790 +0 1 +.names 29790 29791 +1 1 +.names 29682 29792 +1 1 +.names 29678 29793 +1 1 +.names 29799 29800 29794 +1- 1 +-1 1 +.names 29794 29795 +1 1 +.names 29793 29796 +0 1 +.names 29964 29965 29797 +1- 1 +-1 1 +.names 29797 29798 +1 1 +.names 29796 29798 29799 +11 1 +.names 29793 29197 29800 +11 1 +.names 29792 29801 +0 1 +.names 29801 29795 29802 +11 1 +.names 29792 29216 29803 +11 1 +.names 28807 29804 +0 1 +.names 29804 29805 +1 1 +.names 29757 29806 +0 1 +.names 29806 29807 +1 1 +.names 29754 29808 +0 1 +.names 29808 29809 +1 1 +.names 29812 29813 29810 +1- 1 +-1 1 +.names 29810 29811 +1 1 +.names 29112 29812 +0 1 +.names 29809 29813 +0 1 +.names 29807 29814 +0 1 +.names 29814 29811 29815 +11 1 +.names 29807 29805 29816 +11 1 +.names 29812 29817 +1 1 +.names 28733 29818 +0 1 +.names 29818 29819 +1 1 +.names 29819 29820 +0 1 +.names 29752 29821 +0 1 +.names 29820 29821 29822 +11 1 +.names 29822 29806 29823 +1- 1 +-1 1 +.names 29146 29824 +0 1 +.names 29824 29825 +1 1 +.names 29657 29826 +1 1 +.names 29653 29827 +1 1 +.names 29830 29831 29828 +1- 1 +-1 1 +.names 29828 29829 +1 1 +.names 29129 29830 +0 1 +.names 29827 29831 +0 1 +.names 29826 29832 +0 1 +.names 29832 29829 29833 +11 1 +.names 29826 29825 29834 +11 1 +.names 29830 29835 +1 1 +.names 28631 29836 +0 1 +.names 29836 29837 +1 1 +.names 29180 29838 +0 1 +.names 29838 29839 +1 1 +.names 29839 29840 +0 1 +.names 29837 29841 +0 1 +.names 29840 29841 29842 +11 1 +.names 29842 29657 29843 +1- 1 +-1 1 +.names 28840 29844 +0 1 +.names 29844 29845 +1 1 +.names 28291 29845 29846 +01 1 +10 1 +.names 29846 29847 +1 1 +.names 29847 29848 +0 1 +.names 29848 29849 +1 1 +.names 29853 29850 +0 1 +.names 29850 29851 +1 1 +.names 28929 29867 29852 +01 1 +10 1 +.names 29852 29853 +1 1 +.names 29857 29858 29854 +1- 1 +-1 1 +.names 29854 29855 +1 1 +.names 29851 29856 +0 1 +.names 29856 28823 29857 +11 1 +.names 29851 28929 29858 +11 1 +.names 29849 29859 +0 1 +.names 29859 29855 29860 +11 1 +.names 29849 28840 29861 +11 1 +.names 28823 29862 +0 1 +.names 29862 29863 +1 1 +.names 28274 29863 29864 +01 1 +10 1 +.names 29864 29865 +1 1 +.names 28380 29866 +0 1 +.names 29866 29867 +1 1 +.names 29848 29850 29868 +1- 1 +-1 1 +.names 29865 29869 +0 1 +.names 29667 29872 29870 +1- 1 +-1 1 +.names 29870 29871 +1 1 +.names 29664 29872 +0 1 +.names 29666 29873 +0 1 +.names 29873 29871 29874 +11 1 +.names 29666 29670 29875 +11 1 +.names 28616 29876 +0 1 +.names 29876 29877 +1 1 +.names 29877 29878 +0 1 +.names 29672 29879 +0 1 +.names 29878 29879 29880 +11 1 +.names 29880 29663 29881 +1- 1 +-1 1 +.names 29887 29888 29882 +1- 1 +-1 1 +.names 29882 29883 +1 1 +.names 29774 29884 +0 1 +.names 29770 29966 29885 +1- 1 +-1 1 +.names 29885 29886 +1 1 +.names 29884 29886 29887 +11 1 +.names 29774 29776 29888 +11 1 +.names 29409 29248 29889 +11 1 +.names 29883 29890 +0 1 +.names 28978 29891 +0 1 +.names 29891 29892 +1 1 +.names 29197 29893 +0 1 +.names 29893 29894 +1 1 +.names 29686 29895 +1 1 +.names 28946 29896 +0 1 +.names 29896 29897 +1 1 +.names 29902 29903 29898 +1- 1 +-1 1 +.names 29898 29899 +1 1 +.names 29967 29968 29900 +1- 1 +-1 1 +.names 29900 29901 +1 1 +.names 29796 29901 29902 +11 1 +.names 29793 28648 29903 +11 1 +.names 29801 29899 29904 +11 1 +.names 29792 28667 29905 +11 1 +.names 28480 29906 +0 1 +.names 29906 29907 +1 1 +.names 29912 29915 29908 +1- 1 +-1 1 +.names 29908 29909 +1 1 +.names 29395 29780 29910 +11 1 +.names 29907 29911 +0 1 +.names 29910 29911 29912 +11 1 +.names 29974 29975 29913 +1- 1 +-1 1 +.names 29913 29914 +1 1 +.names 29914 29915 +0 1 +.names 29787 29909 29916 +11 1 +.names 29746 28344 29917 +11 1 +.names 28327 29918 +0 1 +.names 29918 29919 +1 1 +.names 29922 29872 29920 +1- 1 +-1 1 +.names 29920 29921 +1 1 +.names 28750 29922 +0 1 +.names 29873 29921 29923 +11 1 +.names 29666 29919 29924 +11 1 +.names 28597 29925 +0 1 +.names 29925 29926 +1 1 +.names 29929 29831 29927 +1- 1 +-1 1 +.names 29927 29928 +1 1 +.names 28580 29929 +0 1 +.names 29832 29928 29930 +11 1 +.names 29826 29926 29931 +11 1 +.names 29934 29935 29932 +1- 1 +-1 1 +.names 29932 29933 +1 1 +.names 29856 28274 29934 +11 1 +.names 29851 28380 29935 +11 1 +.names 29859 29933 29936 +11 1 +.names 29849 28291 29937 +11 1 +.names 28258 29938 +0 1 +.names 29938 29939 +1 1 +.names 29942 29813 29940 +1- 1 +-1 1 +.names 29940 29941 +1 1 +.names 28563 29942 +0 1 +.names 29814 29941 29943 +11 1 +.names 29807 29939 29944 +11 1 +.names 28238 29945 +0 1 +.names 29945 29946 +1 1 +.names 29951 29952 29947 +1- 1 +-1 1 +.names 29947 29948 +1 1 +.names 29976 29966 29949 +1- 1 +-1 1 +.names 29949 29950 +1 1 +.names 29884 29950 29951 +11 1 +.names 29774 29946 29952 +11 1 +.names 29409 28699 29953 +11 1 +.names 29948 29954 +0 1 +.names 28309 29955 +0 1 +.names 29955 29956 +1 1 +.names 29764 29959 29957 +1- 1 +-1 1 +.names 29957 29958 +1 1 +.names 29956 29959 +0 1 +.names 29759 29960 +0 1 +.names 29960 29958 29961 +11 1 +.names 29759 29763 29962 +11 1 +.names 29895 29963 +0 1 +.names 29963 28978 29964 +11 1 +.names 29895 28946 29965 +11 1 +.names 29769 29966 +0 1 +.names 29963 28429 29967 +11 1 +.names 29895 28397 29968 +11 1 +.names 28463 29969 +0 1 +.names 29969 29970 +1 1 +.names 29955 29973 29971 +1- 1 +-1 1 +.names 29971 29972 +1 1 +.names 29765 29973 +0 1 +.names 29960 29972 29974 +11 1 +.names 29759 29970 29975 +11 1 +.names 28546 29976 +0 1 +.names 11096 29977 +1 1 +.names 29983 29987 29978 +1- 1 +-1 1 +.names 29978 29979 +1 1 +.names 7563 29980 +0 1 +.names 6194 29981 +1 1 +.names 29981 29982 +0 1 +.names 29980 29982 29983 +11 1 +.names 6195 29984 +0 1 +.names 29984 29985 +1 1 +.names 29985 29986 +0 1 +.names 7563 29986 29987 +11 1 +.names 29993 29997 29988 +1- 1 +-1 1 +.names 29988 29989 +1 1 +.names 7557 29990 +0 1 +.names 6258 29991 +1 1 +.names 29991 29992 +0 1 +.names 29990 29992 29993 +11 1 +.names 6259 29994 +0 1 +.names 29994 29995 +1 1 +.names 29995 29996 +0 1 +.names 7557 29996 29997 +11 1 +.names 30002 30006 29998 +1- 1 +-1 1 +.names 29998 29999 +1 1 +.names 6238 30000 +1 1 +.names 30000 30001 +0 1 +.names 29980 30001 30002 +11 1 +.names 6239 30003 +0 1 +.names 30003 30004 +1 1 +.names 30004 30005 +0 1 +.names 7563 30005 30006 +11 1 +.names 30011 30015 30007 +1- 1 +-1 1 +.names 30007 30008 +1 1 +.names 6290 30009 +1 1 +.names 30009 30010 +0 1 +.names 29990 30010 30011 +11 1 +.names 6291 30012 +0 1 +.names 30012 30013 +1 1 +.names 30013 30014 +0 1 +.names 7557 30014 30015 +11 1 +.names 7558 30016 +0 1 +.names 6170 30017 +1 1 +.names 30017 30018 +0 1 +.names 30016 30018 30019 +11 1 +.names 6171 30020 +0 1 +.names 30020 30021 +1 1 +.names 30021 30022 +0 1 +.names 7558 30022 30023 +11 1 +.names 30029 30033 30024 +1- 1 +-1 1 +.names 30024 30025 +1 1 +.names 7560 30026 +0 1 +.names 6174 30027 +1 1 +.names 30027 30028 +0 1 +.names 30026 30028 30029 +11 1 +.names 6175 30030 +0 1 +.names 30030 30031 +1 1 +.names 30031 30032 +0 1 +.names 7560 30032 30033 +11 1 +.names 30038 30042 30034 +1- 1 +-1 1 +.names 30034 30035 +1 1 +.names 6202 30036 +1 1 +.names 30036 30037 +0 1 +.names 30026 30037 30038 +11 1 +.names 6203 30039 +0 1 +.names 30039 30040 +1 1 +.names 30040 30041 +0 1 +.names 7560 30041 30042 +11 1 +.names 30047 30051 30043 +1- 1 +-1 1 +.names 30043 30044 +1 1 +.names 6210 30045 +1 1 +.names 30045 30046 +0 1 +.names 29990 30046 30047 +11 1 +.names 6211 30048 +0 1 +.names 30048 30049 +1 1 +.names 30049 30050 +0 1 +.names 7557 30050 30051 +11 1 +.names 30056 30060 30052 +1- 1 +-1 1 +.names 30052 30053 +1 1 +.names 6246 30054 +1 1 +.names 30054 30055 +0 1 +.names 30026 30055 30056 +11 1 +.names 6247 30057 +0 1 +.names 30057 30058 +1 1 +.names 30058 30059 +0 1 +.names 7560 30059 30060 +11 1 +.names 30065 30069 30061 +1- 1 +-1 1 +.names 30061 30062 +1 1 +.names 6206 30063 +1 1 +.names 30063 30064 +0 1 +.names 29980 30064 30065 +11 1 +.names 6207 30066 +0 1 +.names 30066 30067 +1 1 +.names 30067 30068 +0 1 +.names 7563 30068 30069 +11 1 +.names 30075 30079 30070 +1- 1 +-1 1 +.names 30070 30071 +1 1 +.names 7562 30072 +0 1 +.names 6270 30073 +1 1 +.names 30073 30074 +0 1 +.names 30072 30074 30075 +11 1 +.names 6271 30076 +0 1 +.names 30076 30077 +1 1 +.names 30077 30078 +0 1 +.names 7562 30078 30079 +11 1 +.names 30084 30088 30080 +1- 1 +-1 1 +.names 30080 30081 +1 1 +.names 6214 30082 +1 1 +.names 30082 30083 +0 1 +.names 30016 30083 30084 +11 1 +.names 6215 30085 +0 1 +.names 30085 30086 +1 1 +.names 30086 30087 +0 1 +.names 7558 30087 30088 +11 1 +.names 30093 30097 30089 +1- 1 +-1 1 +.names 30089 30090 +1 1 +.names 6266 30091 +1 1 +.names 30091 30092 +0 1 +.names 30016 30092 30093 +11 1 +.names 6267 30094 +0 1 +.names 30094 30095 +1 1 +.names 30095 30096 +0 1 +.names 7558 30096 30097 +11 1 +.names 30102 30106 30098 +1- 1 +-1 1 +.names 30098 30099 +1 1 +.names 6178 30100 +1 1 +.names 30100 30101 +0 1 +.names 30016 30101 30102 +11 1 +.names 6179 30103 +0 1 +.names 30103 30104 +1 1 +.names 30104 30105 +0 1 +.names 7558 30105 30106 +11 1 +.names 30111 30115 30107 +1- 1 +-1 1 +.names 30107 30108 +1 1 +.names 6190 30109 +1 1 +.names 30109 30110 +0 1 +.names 30072 30110 30111 +11 1 +.names 6191 30112 +0 1 +.names 30112 30113 +1 1 +.names 30113 30114 +0 1 +.names 7562 30114 30115 +11 1 +.names 30120 30124 30116 +1- 1 +-1 1 +.names 30116 30117 +1 1 +.names 6198 30118 +1 1 +.names 30118 30119 +0 1 +.names 29990 30119 30120 +11 1 +.names 6199 30121 +0 1 +.names 30121 30122 +1 1 +.names 30122 30123 +0 1 +.names 7557 30123 30124 +11 1 +.names 30129 30133 30125 +1- 1 +-1 1 +.names 30125 30126 +1 1 +.names 6242 30127 +1 1 +.names 30127 30128 +0 1 +.names 30072 30128 30129 +11 1 +.names 6243 30130 +0 1 +.names 30130 30131 +1 1 +.names 30131 30132 +0 1 +.names 7562 30132 30133 +11 1 +.names 30138 30142 30134 +1- 1 +-1 1 +.names 30134 30135 +1 1 +.names 6234 30136 +1 1 +.names 30136 30137 +0 1 +.names 30026 30137 30138 +11 1 +.names 6235 30139 +0 1 +.names 30139 30140 +1 1 +.names 30140 30141 +0 1 +.names 7560 30141 30142 +11 1 +.names 30147 30151 30143 +1- 1 +-1 1 +.names 30143 30144 +1 1 +.names 6262 30145 +1 1 +.names 30145 30146 +0 1 +.names 30026 30146 30147 +11 1 +.names 6263 30148 +0 1 +.names 30148 30149 +1 1 +.names 30149 30150 +0 1 +.names 7560 30150 30151 +11 1 +.names 30156 30160 30152 +1- 1 +-1 1 +.names 30152 30153 +1 1 +.names 6294 30154 +1 1 +.names 30154 30155 +0 1 +.names 29980 30155 30156 +11 1 +.names 6295 30157 +0 1 +.names 30157 30158 +1 1 +.names 30158 30159 +0 1 +.names 7563 30159 30160 +11 1 +.names 30166 30170 30161 +1- 1 +-1 1 +.names 30161 30162 +1 1 +.names 7561 30163 +0 1 +.names 6254 30164 +1 1 +.names 30164 30165 +0 1 +.names 30163 30165 30166 +11 1 +.names 6255 30167 +0 1 +.names 30167 30168 +1 1 +.names 30168 30169 +0 1 +.names 7561 30169 30170 +11 1 +.names 30175 30179 30171 +1- 1 +-1 1 +.names 30171 30172 +1 1 +.names 6222 30173 +1 1 +.names 30173 30174 +0 1 +.names 30163 30174 30175 +11 1 +.names 6223 30176 +0 1 +.names 30176 30177 +1 1 +.names 30177 30178 +0 1 +.names 7561 30178 30179 +11 1 +.names 30184 30188 30180 +1- 1 +-1 1 +.names 30180 30181 +1 1 +.names 6226 30182 +1 1 +.names 30182 30183 +0 1 +.names 30072 30183 30184 +11 1 +.names 6227 30185 +0 1 +.names 30185 30186 +1 1 +.names 30186 30187 +0 1 +.names 7562 30187 30188 +11 1 +.names 30193 30197 30189 +1- 1 +-1 1 +.names 30189 30190 +1 1 +.names 6282 30191 +1 1 +.names 30191 30192 +0 1 +.names 29990 30192 30193 +11 1 +.names 6283 30194 +0 1 +.names 30194 30195 +1 1 +.names 30195 30196 +0 1 +.names 7557 30196 30197 +11 1 +.names 30202 30206 30198 +1- 1 +-1 1 +.names 30198 30199 +1 1 +.names 6218 30200 +1 1 +.names 30200 30201 +0 1 +.names 30016 30201 30202 +11 1 +.names 6219 30203 +0 1 +.names 30203 30204 +1 1 +.names 30204 30205 +0 1 +.names 7558 30205 30206 +11 1 +.names 30211 30215 30207 +1- 1 +-1 1 +.names 30207 30208 +1 1 +.names 6274 30209 +1 1 +.names 30209 30210 +0 1 +.names 29980 30210 30211 +11 1 +.names 6275 30212 +0 1 +.names 30212 30213 +1 1 +.names 30213 30214 +0 1 +.names 7563 30214 30215 +11 1 +.names 30220 30224 30216 +1- 1 +-1 1 +.names 30216 30217 +1 1 +.names 6278 30218 +1 1 +.names 30218 30219 +0 1 +.names 29980 30219 30220 +11 1 +.names 6279 30221 +0 1 +.names 30221 30222 +1 1 +.names 30222 30223 +0 1 +.names 7563 30223 30224 +11 1 +.names 30229 30233 30225 +1- 1 +-1 1 +.names 30225 30226 +1 1 +.names 6182 30227 +1 1 +.names 30227 30228 +0 1 +.names 30163 30228 30229 +11 1 +.names 6183 30230 +0 1 +.names 30230 30231 +1 1 +.names 30231 30232 +0 1 +.names 7561 30232 30233 +11 1 +.names 30238 30242 30234 +1- 1 +-1 1 +.names 30234 30235 +1 1 +.names 6186 30236 +1 1 +.names 30236 30237 +0 1 +.names 30163 30237 30238 +11 1 +.names 6187 30239 +0 1 +.names 30239 30240 +1 1 +.names 30240 30241 +0 1 +.names 7561 30241 30242 +11 1 +.names 30247 30251 30243 +1- 1 +-1 1 +.names 30243 30244 +1 1 +.names 6230 30245 +1 1 +.names 30245 30246 +0 1 +.names 30163 30246 30247 +11 1 +.names 6231 30248 +0 1 +.names 30248 30249 +1 1 +.names 30249 30250 +0 1 +.names 7561 30250 30251 +11 1 +.names 30256 30260 30252 +1- 1 +-1 1 +.names 30252 30253 +1 1 +.names 6250 30254 +1 1 +.names 30254 30255 +0 1 +.names 30072 30255 30256 +11 1 +.names 6251 30257 +0 1 +.names 30257 30258 +1 1 +.names 30258 30259 +0 1 +.names 7562 30259 30260 +11 1 +.names 30265 30269 30261 +1- 1 +-1 1 +.names 30261 30262 +1 1 +.names 6286 30263 +1 1 +.names 30263 30264 +0 1 +.names 30072 30264 30265 +11 1 +.names 6287 30266 +0 1 +.names 30266 30267 +1 1 +.names 30267 30268 +0 1 +.names 7562 30268 30269 +11 1 +.names 30276 30277 30270 +1- 1 +-1 1 +.names 30270 30271 +1 1 +.names 7577 30272 +0 1 +.names 30278 30280 30273 +11 1 +.names 30273 30274 +1 1 +.names 30274 30275 +0 1 +.names 30272 30275 30276 +11 1 +.names 7577 2413 30277 +11 1 +.names 7578 30278 +0 1 +.names 6046 30279 +1 1 +.names 30279 30280 +0 1 +.names 30288 30289 30281 +1- 1 +-1 1 +.names 30281 30282 +1 1 +.names 6047 30283 +0 1 +.names 30283 30284 +1 1 +.names 30284 30285 +0 1 +.names 30278 30286 +1 1 +.names 30286 30287 +0 1 +.names 30285 30287 30288 +11 1 +.names 30271 30289 +0 1 +.names 30296 30297 30290 +1- 1 +-1 1 +.names 30290 30291 +1 1 +.names 7565 30292 +0 1 +.names 30278 30299 30293 +11 1 +.names 30293 30294 +1 1 +.names 30294 30295 +0 1 +.names 30292 30295 30296 +11 1 +.names 7565 2413 30297 +11 1 +.names 6066 30298 +1 1 +.names 30298 30299 +0 1 +.names 30307 30308 30300 +1- 1 +-1 1 +.names 30300 30301 +1 1 +.names 6067 30302 +0 1 +.names 30302 30303 +1 1 +.names 30303 30304 +0 1 +.names 30278 30305 +1 1 +.names 30305 30306 +0 1 +.names 30304 30306 30307 +11 1 +.names 30291 30308 +0 1 +.names 7572 30309 +0 1 +.names 30309 30310 +1 1 +.names 30309 30314 30311 +11 1 +.names 30311 30312 +1 1 +.names 6130 30313 +1 1 +.names 30313 30314 +0 1 +.names 30318 30319 30315 +1- 1 +-1 1 +.names 30315 30316 +1 1 +.names 30312 30317 +0 1 +.names 30292 30317 30318 +11 1 +.names 7565 2413 30319 +11 1 +.names 6131 30320 +0 1 +.names 30320 30321 +1 1 +.names 30326 30327 30322 +1- 1 +-1 1 +.names 30322 30323 +1 1 +.names 30310 30324 +0 1 +.names 30321 30325 +0 1 +.names 30324 30325 30326 +11 1 +.names 30316 30327 +0 1 +.names 30309 30328 +1 1 +.names 30309 30332 30329 +11 1 +.names 30329 30330 +1 1 +.names 6074 30331 +1 1 +.names 30331 30332 +0 1 +.names 30336 30337 30333 +1- 1 +-1 1 +.names 30333 30334 +1 1 +.names 30330 30335 +0 1 +.names 30272 30335 30336 +11 1 +.names 7577 2413 30337 +11 1 +.names 30344 30345 30338 +1- 1 +-1 1 +.names 30338 30339 +1 1 +.names 30328 30340 +0 1 +.names 6075 30341 +0 1 +.names 30341 30342 +1 1 +.names 30342 30343 +0 1 +.names 30340 30343 30344 +11 1 +.names 30334 30345 +0 1 +.names 30351 30352 30346 +1- 1 +-1 1 +.names 30346 30347 +1 1 +.names 30353 30355 30348 +11 1 +.names 30348 30349 +1 1 +.names 30349 30350 +0 1 +.names 30272 30350 30351 +11 1 +.names 7577 2413 30352 +11 1 +.names 7570 30353 +0 1 +.names 6082 30354 +1 1 +.names 30354 30355 +0 1 +.names 30363 30364 30356 +1- 1 +-1 1 +.names 30356 30357 +1 1 +.names 6083 30358 +0 1 +.names 30358 30359 +1 1 +.names 30359 30360 +0 1 +.names 30353 30361 +1 1 +.names 30361 30362 +0 1 +.names 30360 30362 30363 +11 1 +.names 30347 30364 +0 1 +.names 30370 30371 30365 +1- 1 +-1 1 +.names 30365 30366 +1 1 +.names 30372 30374 30367 +11 1 +.names 30367 30368 +1 1 +.names 30368 30369 +0 1 +.names 30272 30369 30370 +11 1 +.names 7577 2413 30371 +11 1 +.names 7573 30372 +0 1 +.names 6110 30373 +1 1 +.names 30373 30374 +0 1 +.names 30382 30383 30375 +1- 1 +-1 1 +.names 30375 30376 +1 1 +.names 6111 30377 +0 1 +.names 30377 30378 +1 1 +.names 30378 30379 +0 1 +.names 30372 30380 +1 1 +.names 30380 30381 +0 1 +.names 30379 30381 30382 +11 1 +.names 30366 30383 +0 1 +.names 30390 30391 30384 +1- 1 +-1 1 +.names 30384 30385 +1 1 +.names 7576 30386 +0 1 +.names 30353 30393 30387 +11 1 +.names 30387 30388 +1 1 +.names 30388 30389 +0 1 +.names 30386 30389 30390 +11 1 +.names 7576 2413 30391 +11 1 +.names 6162 30392 +1 1 +.names 30392 30393 +0 1 +.names 30401 30402 30394 +1- 1 +-1 1 +.names 30394 30395 +1 1 +.names 6163 30396 +0 1 +.names 30396 30397 +1 1 +.names 30397 30398 +0 1 +.names 30353 30399 +1 1 +.names 30399 30400 +0 1 +.names 30398 30400 30401 +11 1 +.names 30385 30402 +0 1 +.names 30408 30409 30403 +1- 1 +-1 1 +.names 30403 30404 +1 1 +.names 30372 30411 30405 +11 1 +.names 30405 30406 +1 1 +.names 30406 30407 +0 1 +.names 30292 30407 30408 +11 1 +.names 7565 2413 30409 +11 1 +.names 6118 30410 +1 1 +.names 30410 30411 +0 1 +.names 30419 30420 30412 +1- 1 +-1 1 +.names 30412 30413 +1 1 +.names 6119 30414 +0 1 +.names 30414 30415 +1 1 +.names 30415 30416 +0 1 +.names 30372 30417 +1 1 +.names 30417 30418 +0 1 +.names 30416 30418 30419 +11 1 +.names 30404 30420 +0 1 +.names 30426 30427 30421 +1- 1 +-1 1 +.names 30421 30422 +1 1 +.names 30353 30429 30423 +11 1 +.names 30423 30424 +1 1 +.names 30424 30425 +0 1 +.names 30272 30425 30426 +11 1 +.names 7577 2413 30427 +11 1 +.names 6042 30428 +1 1 +.names 30428 30429 +0 1 +.names 6043 30430 +0 1 +.names 30430 30431 +1 1 +.names 30431 30432 +0 1 +.names 30353 30433 +1 1 +.names 30433 30434 +0 1 +.names 30432 30434 30435 +11 1 +.names 30422 30436 +0 1 +.names 30309 30437 +1 1 +.names 30309 30441 30438 +11 1 +.names 30438 30439 +1 1 +.names 6078 30440 +1 1 +.names 30440 30441 +0 1 +.names 30445 30446 30442 +1- 1 +-1 1 +.names 30442 30443 +1 1 +.names 30439 30444 +0 1 +.names 30386 30444 30445 +11 1 +.names 7576 2413 30446 +11 1 +.names 6079 30447 +0 1 +.names 30447 30448 +1 1 +.names 30453 30454 30449 +1- 1 +-1 1 +.names 30449 30450 +1 1 +.names 30437 30451 +0 1 +.names 30448 30452 +0 1 +.names 30451 30452 30453 +11 1 +.names 30443 30454 +0 1 +.names 30309 30455 +1 1 +.names 30309 30459 30456 +11 1 +.names 30456 30457 +1 1 +.names 6142 30458 +1 1 +.names 30458 30459 +0 1 +.names 30463 30464 30460 +1- 1 +-1 1 +.names 30460 30461 +1 1 +.names 30457 30462 +0 1 +.names 30292 30462 30463 +11 1 +.names 7565 2413 30464 +11 1 +.names 6143 30465 +0 1 +.names 30465 30466 +1 1 +.names 30471 30472 30467 +1- 1 +-1 1 +.names 30467 30468 +1 1 +.names 30455 30469 +0 1 +.names 30466 30470 +0 1 +.names 30469 30470 30471 +11 1 +.names 30461 30472 +0 1 +.names 30478 30479 30473 +1- 1 +-1 1 +.names 30473 30474 +1 1 +.names 30353 30481 30475 +11 1 +.names 30475 30476 +1 1 +.names 30476 30477 +0 1 +.names 30272 30477 30478 +11 1 +.names 7577 2413 30479 +11 1 +.names 6086 30480 +1 1 +.names 30480 30481 +0 1 +.names 30489 30490 30482 +1- 1 +-1 1 +.names 30482 30483 +1 1 +.names 6087 30484 +0 1 +.names 30484 30485 +1 1 +.names 30485 30486 +0 1 +.names 30353 30487 +1 1 +.names 30487 30488 +0 1 +.names 30486 30488 30489 +11 1 +.names 30474 30490 +0 1 +.names 30496 30497 30491 +1- 1 +-1 1 +.names 30491 30492 +1 1 +.names 30353 30499 30493 +11 1 +.names 30493 30494 +1 1 +.names 30494 30495 +0 1 +.names 30292 30495 30496 +11 1 +.names 7565 2413 30497 +11 1 +.names 6138 30498 +1 1 +.names 30498 30499 +0 1 +.names 30507 30508 30500 +1- 1 +-1 1 +.names 30500 30501 +1 1 +.names 6139 30502 +0 1 +.names 30502 30503 +1 1 +.names 30503 30504 +0 1 +.names 30353 30505 +1 1 +.names 30505 30506 +0 1 +.names 30504 30506 30507 +11 1 +.names 30492 30508 +0 1 +.names 30514 30515 30509 +1- 1 +-1 1 +.names 30509 30510 +1 1 +.names 30353 30517 30511 +11 1 +.names 30511 30512 +1 1 +.names 30512 30513 +0 1 +.names 30292 30513 30514 +11 1 +.names 7565 2413 30515 +11 1 +.names 6070 30516 +1 1 +.names 30516 30517 +0 1 +.names 30525 30526 30518 +1- 1 +-1 1 +.names 30518 30519 +1 1 +.names 6071 30520 +0 1 +.names 30520 30521 +1 1 +.names 30521 30522 +0 1 +.names 30353 30523 +1 1 +.names 30523 30524 +0 1 +.names 30522 30524 30525 +11 1 +.names 30510 30526 +0 1 +.names 30532 30533 30527 +1- 1 +-1 1 +.names 30527 30528 +1 1 +.names 30372 30535 30529 +11 1 +.names 30529 30530 +1 1 +.names 30530 30531 +0 1 +.names 30292 30531 30532 +11 1 +.names 7565 2413 30533 +11 1 +.names 6114 30534 +1 1 +.names 30534 30535 +0 1 +.names 30543 30544 30536 +1- 1 +-1 1 +.names 30536 30537 +1 1 +.names 6115 30538 +0 1 +.names 30538 30539 +1 1 +.names 30539 30540 +0 1 +.names 30372 30541 +1 1 +.names 30541 30542 +0 1 +.names 30540 30542 30543 +11 1 +.names 30528 30544 +0 1 +.names 30550 30551 30545 +1- 1 +-1 1 +.names 30545 30546 +1 1 +.names 30278 30553 30547 +11 1 +.names 30547 30548 +1 1 +.names 30548 30549 +0 1 +.names 30386 30549 30550 +11 1 +.names 7576 2413 30551 +11 1 +.names 6106 30552 +1 1 +.names 30552 30553 +0 1 +.names 30561 30562 30554 +1- 1 +-1 1 +.names 30554 30555 +1 1 +.names 6107 30556 +0 1 +.names 30556 30557 +1 1 +.names 30557 30558 +0 1 +.names 30278 30559 +1 1 +.names 30559 30560 +0 1 +.names 30558 30560 30561 +11 1 +.names 30546 30562 +0 1 +.names 30568 30569 30563 +1- 1 +-1 1 +.names 30563 30564 +1 1 +.names 30353 30571 30565 +11 1 +.names 30565 30566 +1 1 +.names 30566 30567 +0 1 +.names 30386 30567 30568 +11 1 +.names 7576 2413 30569 +11 1 +.names 6134 30570 +1 1 +.names 30570 30571 +0 1 +.names 30579 30580 30572 +1- 1 +-1 1 +.names 30572 30573 +1 1 +.names 30353 30574 +1 1 +.names 30574 30575 +0 1 +.names 6135 30576 +0 1 +.names 30576 30577 +1 1 +.names 30577 30578 +0 1 +.names 30575 30578 30579 +11 1 +.names 30564 30580 +0 1 +.names 30309 30581 +1 1 +.names 30309 30585 30582 +11 1 +.names 30582 30583 +1 1 +.names 6166 30584 +1 1 +.names 30584 30585 +0 1 +.names 30589 30590 30586 +1- 1 +-1 1 +.names 30586 30587 +1 1 +.names 30583 30588 +0 1 +.names 30272 30588 30589 +11 1 +.names 7577 2413 30590 +11 1 +.names 6167 30591 +0 1 +.names 30591 30592 +1 1 +.names 30597 30598 30593 +1- 1 +-1 1 +.names 30593 30594 +1 1 +.names 30581 30595 +0 1 +.names 30592 30596 +0 1 +.names 30595 30596 30597 +11 1 +.names 30587 30598 +0 1 +.names 30604 30605 30599 +1- 1 +-1 1 +.names 30599 30600 +1 1 +.names 30309 30607 30601 +11 1 +.names 30601 30602 +1 1 +.names 30602 30603 +0 1 +.names 30272 30603 30604 +11 1 +.names 7577 2413 30605 +11 1 +.names 6050 30606 +1 1 +.names 30606 30607 +0 1 +.names 30615 30616 30608 +1- 1 +-1 1 +.names 30608 30609 +1 1 +.names 6051 30610 +0 1 +.names 30610 30611 +1 1 +.names 30611 30612 +0 1 +.names 30309 30613 +1 1 +.names 30613 30614 +0 1 +.names 30612 30614 30615 +11 1 +.names 30600 30616 +0 1 +.names 30622 30623 30617 +1- 1 +-1 1 +.names 30617 30618 +1 1 +.names 30372 30625 30619 +11 1 +.names 30619 30620 +1 1 +.names 30620 30621 +0 1 +.names 30386 30621 30622 +11 1 +.names 7576 2413 30623 +11 1 +.names 6062 30624 +1 1 +.names 30624 30625 +0 1 +.names 30633 30634 30626 +1- 1 +-1 1 +.names 30626 30627 +1 1 +.names 6063 30628 +0 1 +.names 30628 30629 +1 1 +.names 30629 30630 +0 1 +.names 30372 30631 +1 1 +.names 30631 30632 +0 1 +.names 30630 30632 30633 +11 1 +.names 30618 30634 +0 1 +.names 30640 30641 30635 +1- 1 +-1 1 +.names 30635 30636 +1 1 +.names 30372 30643 30637 +11 1 +.names 30637 30638 +1 1 +.names 30638 30639 +0 1 +.names 30386 30639 30640 +11 1 +.names 7576 2413 30641 +11 1 +.names 6126 30642 +1 1 +.names 30642 30643 +0 1 +.names 30651 30652 30644 +1- 1 +-1 1 +.names 30644 30645 +1 1 +.names 6127 30646 +0 1 +.names 30646 30647 +1 1 +.names 30647 30648 +0 1 +.names 30372 30649 +1 1 +.names 30649 30650 +0 1 +.names 30648 30650 30651 +11 1 +.names 30636 30652 +0 1 +.names 30658 30659 30653 +1- 1 +-1 1 +.names 30653 30654 +1 1 +.names 30372 30661 30655 +11 1 +.names 30655 30656 +1 1 +.names 30656 30657 +0 1 +.names 30272 30657 30658 +11 1 +.names 7577 2413 30659 +11 1 +.names 6094 30660 +1 1 +.names 30660 30661 +0 1 +.names 30669 30670 30662 +1- 1 +-1 1 +.names 30662 30663 +1 1 +.names 6095 30664 +0 1 +.names 30664 30665 +1 1 +.names 30665 30666 +0 1 +.names 30372 30667 +1 1 +.names 30667 30668 +0 1 +.names 30666 30668 30669 +11 1 +.names 30654 30670 +0 1 +.names 30676 30677 30671 +1- 1 +-1 1 +.names 30671 30672 +1 1 +.names 30309 30679 30673 +11 1 +.names 30673 30674 +1 1 +.names 30674 30675 +0 1 +.names 30292 30675 30676 +11 1 +.names 7565 2413 30677 +11 1 +.names 6098 30678 +1 1 +.names 30678 30679 +0 1 +.names 30687 30688 30680 +1- 1 +-1 1 +.names 30680 30681 +1 1 +.names 30309 30682 +1 1 +.names 30682 30683 +0 1 +.names 6099 30684 +0 1 +.names 30684 30685 +1 1 +.names 30685 30686 +0 1 +.names 30683 30686 30687 +11 1 +.names 30672 30688 +0 1 +.names 30309 30689 +1 1 +.names 30309 30693 30690 +11 1 +.names 30690 30691 +1 1 +.names 6154 30692 +1 1 +.names 30692 30693 +0 1 +.names 30697 30698 30694 +1- 1 +-1 1 +.names 30694 30695 +1 1 +.names 30691 30696 +0 1 +.names 30386 30696 30697 +11 1 +.names 7576 2413 30698 +11 1 +.names 6155 30699 +0 1 +.names 30699 30700 +1 1 +.names 30705 30706 30701 +1- 1 +-1 1 +.names 30701 30702 +1 1 +.names 30689 30703 +0 1 +.names 30700 30704 +0 1 +.names 30703 30704 30705 +11 1 +.names 30695 30706 +0 1 +.names 30712 30713 30707 +1- 1 +-1 1 +.names 30707 30708 +1 1 +.names 30353 30715 30709 +11 1 +.names 30709 30710 +1 1 +.names 30710 30711 +0 1 +.names 30386 30711 30712 +11 1 +.names 7576 2413 30713 +11 1 +.names 6090 30714 +1 1 +.names 30714 30715 +0 1 +.names 30723 30724 30716 +1- 1 +-1 1 +.names 30716 30717 +1 1 +.names 6091 30718 +0 1 +.names 30718 30719 +1 1 +.names 30719 30720 +0 1 +.names 30353 30721 +1 1 +.names 30721 30722 +0 1 +.names 30720 30722 30723 +11 1 +.names 30708 30724 +0 1 +.names 30730 30731 30725 +1- 1 +-1 1 +.names 30725 30726 +1 1 +.names 30372 30733 30727 +11 1 +.names 30727 30728 +1 1 +.names 30728 30729 +0 1 +.names 30386 30729 30730 +11 1 +.names 7576 2413 30731 +11 1 +.names 6146 30732 +1 1 +.names 30732 30733 +0 1 +.names 30741 30742 30734 +1- 1 +-1 1 +.names 30734 30735 +1 1 +.names 6147 30736 +0 1 +.names 30736 30737 +1 1 +.names 30737 30738 +0 1 +.names 30372 30739 +1 1 +.names 30739 30740 +0 1 +.names 30738 30740 30741 +11 1 +.names 30726 30742 +0 1 +.names 30309 30743 +1 1 +.names 30309 30747 30744 +11 1 +.names 30744 30745 +1 1 +.names 6150 30746 +1 1 +.names 30746 30747 +0 1 +.names 30751 30752 30748 +1- 1 +-1 1 +.names 30748 30749 +1 1 +.names 30745 30750 +0 1 +.names 30272 30750 30751 +11 1 +.names 7577 2413 30752 +11 1 +.names 6151 30753 +0 1 +.names 30753 30754 +1 1 +.names 30759 30760 30755 +1- 1 +-1 1 +.names 30755 30756 +1 1 +.names 30743 30757 +0 1 +.names 30754 30758 +0 1 +.names 30757 30758 30759 +11 1 +.names 30749 30760 +0 1 +.names 30766 30767 30761 +1- 1 +-1 1 +.names 30761 30762 +1 1 +.names 30372 30769 30763 +11 1 +.names 30763 30764 +1 1 +.names 30764 30765 +0 1 +.names 30386 30765 30766 +11 1 +.names 7576 2413 30767 +11 1 +.names 6054 30768 +1 1 +.names 30768 30769 +0 1 +.names 30777 30778 30770 +1- 1 +-1 1 +.names 30770 30771 +1 1 +.names 6055 30772 +0 1 +.names 30772 30773 +1 1 +.names 30773 30774 +0 1 +.names 30372 30775 +1 1 +.names 30775 30776 +0 1 +.names 30774 30776 30777 +11 1 +.names 30762 30778 +0 1 +.names 30784 30785 30779 +1- 1 +-1 1 +.names 30779 30780 +1 1 +.names 30372 30787 30781 +11 1 +.names 30781 30782 +1 1 +.names 30782 30783 +0 1 +.names 30292 30783 30784 +11 1 +.names 7565 2413 30785 +11 1 +.names 6058 30786 +1 1 +.names 30786 30787 +0 1 +.names 30795 30796 30788 +1- 1 +-1 1 +.names 30788 30789 +1 1 +.names 6059 30790 +0 1 +.names 30790 30791 +1 1 +.names 30791 30792 +0 1 +.names 30372 30793 +1 1 +.names 30793 30794 +0 1 +.names 30792 30794 30795 +11 1 +.names 30780 30796 +0 1 +.names 30309 30797 +1 1 +.names 30309 30801 30798 +11 1 +.names 30798 30799 +1 1 +.names 6102 30800 +1 1 +.names 30800 30801 +0 1 +.names 30805 30806 30802 +1- 1 +-1 1 +.names 30802 30803 +1 1 +.names 30799 30804 +0 1 +.names 30386 30804 30805 +11 1 +.names 7576 2413 30806 +11 1 +.names 30813 30814 30807 +1- 1 +-1 1 +.names 30807 30808 +1 1 +.names 30797 30809 +0 1 +.names 6103 30810 +0 1 +.names 30810 30811 +1 1 +.names 30811 30812 +0 1 +.names 30809 30812 30813 +11 1 +.names 30803 30814 +0 1 +.names 30820 30821 30815 +1- 1 +-1 1 +.names 30815 30816 +1 1 +.names 30278 30823 30817 +11 1 +.names 30817 30818 +1 1 +.names 30818 30819 +0 1 +.names 30292 30819 30820 +11 1 +.names 7565 2413 30821 +11 1 +.names 6122 30822 +1 1 +.names 30822 30823 +0 1 +.names 30831 30832 30824 +1- 1 +-1 1 +.names 30824 30825 +1 1 +.names 6123 30826 +0 1 +.names 30826 30827 +1 1 +.names 30827 30828 +0 1 +.names 30278 30829 +1 1 +.names 30829 30830 +0 1 +.names 30828 30830 30831 +11 1 +.names 30816 30832 +0 1 +.names 30838 30839 30833 +1- 1 +-1 1 +.names 30833 30834 +1 1 +.names 30353 30841 30835 +11 1 +.names 30835 30836 +1 1 +.names 30836 30837 +0 1 +.names 30272 30837 30838 +11 1 +.names 7577 2413 30839 +11 1 +.names 6158 30840 +1 1 +.names 30840 30841 +0 1 +.names 30849 30850 30842 +1- 1 +-1 1 +.names 30842 30843 +1 1 +.names 6159 30844 +0 1 +.names 30844 30845 +1 1 +.names 30845 30846 +0 1 +.names 30353 30847 +1 1 +.names 30847 30848 +0 1 +.names 30846 30848 30849 +11 1 +.names 30834 30850 +0 1 +.names 30144 30851 +0 1 +.names 30573 30852 +0 1 +.names 30861 30864 30853 +11 1 +.names 30853 30854 +1 1 +.names 31416 31419 30855 +1- 1 +-1 1 +.names 30855 30856 +1 1 +.names 30856 30857 +0 1 +.names 31148 31400 30858 +11 1 +.names 30858 30859 +1 1 +.names 30859 30860 +0 1 +.names 30857 30860 30861 +1- 1 +-1 1 +.names 31404 31154 30862 +1- 1 +-1 1 +.names 30862 30863 +1 1 +.names 30863 30864 +0 1 +.names 30860 30869 30865 +1- 1 +-1 1 +.names 30865 30866 +1 1 +.names 31415 31175 30867 +11 1 +.names 30867 30868 +1 1 +.names 30868 30869 +0 1 +.names 30873 30870 +0 1 +.names 30870 30871 +1 1 +.names 31863 30872 +0 1 +.names 30872 30873 +1 1 +.names 30879 30883 56661 +1- 1 +-1 1 +.names 31526 30875 +0 1 +.names 30875 30876 +1 1 +.names 30876 30877 +0 1 +.names 30871 30878 +0 1 +.names 30877 30878 30879 +11 1 +.names 30924 30880 +0 1 +.names 30880 30881 +1 1 +.names 30881 30882 +0 1 +.names 30876 30882 30883 +11 1 +.names 30888 30892 56662 +1- 1 +-1 1 +.names 30922 30885 +0 1 +.names 30885 30886 +1 1 +.names 30886 30887 +0 1 +.names 30877 30887 30888 +11 1 +.names 30920 30889 +0 1 +.names 30889 30890 +1 1 +.names 30890 30891 +0 1 +.names 30876 30891 30892 +11 1 +.names 30897 30901 56663 +1- 1 +-1 1 +.names 30918 30894 +0 1 +.names 30894 30895 +1 1 +.names 30895 30896 +0 1 +.names 30877 30896 30897 +11 1 +.names 30916 30898 +0 1 +.names 30898 30899 +1 1 +.names 30899 30900 +0 1 +.names 30876 30900 30901 +11 1 +.names 30906 30910 56664 +1- 1 +-1 1 +.names 30914 30903 +0 1 +.names 30903 30904 +1 1 +.names 30904 30905 +0 1 +.names 30877 30905 30906 +11 1 +.names 30912 30907 +0 1 +.names 30907 30908 +1 1 +.names 30908 30909 +0 1 +.names 30876 30909 30910 +11 1 +.names 31910 31882 30911 +01 1 +10 1 +.names 30911 30912 +1 1 +.names 31900 30913 +0 1 +.names 30913 30914 +1 1 +.names 31899 31865 30915 +01 1 +10 1 +.names 30915 30916 +1 1 +.names 31913 30917 +0 1 +.names 30917 30918 +1 1 +.names 31915 31917 30919 +01 1 +10 1 +.names 30919 30920 +1 1 +.names 31918 30921 +0 1 +.names 30921 30922 +1 1 +.names 31919 30923 +0 1 +.names 30923 30924 +1 1 +.names 30153 30925 +0 1 +.names 30594 30926 +0 1 +.names 30135 30927 +0 1 +.names 30555 30928 +0 1 +.names 30235 30929 +0 1 +.names 30789 30930 +0 1 +.names 11284 11288 30931 +1- 1 +-1 1 +.names 30931 30932 +1 1 +.names 11163 11280 30933 +11 1 +.names 30933 30934 +1 1 +.names 30937 30938 30935 +1- 1 +-1 1 +.names 30935 30936 +1 1 +.names 11156 30937 +0 1 +.names 11144 30938 +0 1 +.names 30944 30945 30939 +1- 1 +-1 1 +.names 30939 30940 +1 1 +.names 11305 30941 +0 1 +.names 11249 30942 +0 1 +.names 30941 30942 30943 +1- 1 +-1 1 +.names 30943 30938 30944 +1- 1 +-1 1 +.names 11148 30945 +0 1 +.names 30948 30949 30946 +1- 1 +-1 1 +.names 30946 30947 +1 1 +.names 30945 30938 30948 +1- 1 +-1 1 +.names 11160 30949 +0 1 +.names 30945 30949 30950 +1- 1 +-1 1 +.names 30950 30951 +1 1 +.names 11156 30945 30952 +1- 1 +-1 1 +.names 30952 30953 +1 1 +.names 30957 30960 30954 +1- 1 +-1 1 +.names 30954 30955 +1 1 +.names 30951 30956 +0 1 +.names 11156 30956 30957 +1- 1 +-1 1 +.names 31008 30942 30958 +1- 1 +-1 1 +.names 30958 30959 +1 1 +.names 30959 30960 +0 1 +.names 30964 30956 30961 +1- 1 +-1 1 +.names 30961 30962 +1 1 +.names 30937 30963 +1 1 +.names 30963 30964 +0 1 +.names 11152 30938 30965 +1- 1 +-1 1 +.names 30965 30966 +1 1 +.names 30972 30973 30967 +1- 1 +-1 1 +.names 30967 30968 +1 1 +.names 30947 30969 +0 1 +.names 11152 30969 30970 +1- 1 +-1 1 +.names 30940 30971 +0 1 +.names 30970 30971 30972 +1- 1 +-1 1 +.names 30936 30973 +0 1 +.names 11301 30976 30974 +1- 1 +-1 1 +.names 30974 30975 +1 1 +.names 11297 30976 +0 1 +.names 11160 30941 30977 +1- 1 +-1 1 +.names 30977 30978 +1 1 +.names 30982 30955 30979 +01 1 +10 1 +.names 30979 30980 +1 1 +.names 30966 30981 +0 1 +.names 30981 30982 +1 1 +.names 30985 30983 +0 1 +.names 30983 30984 +1 1 +.names 30966 30962 30985 +01 1 +10 1 +.names 30989 30968 30986 +01 1 +10 1 +.names 30986 30987 +1 1 +.names 30975 30988 +0 1 +.names 30988 30989 +1 1 +.names 30989 30993 30990 +01 1 +10 1 +.names 30990 30991 +1 1 +.names 31007 30969 30992 +1- 1 +-1 1 +.names 30992 30993 +1 1 +.names 30996 30949 30994 +11 1 +.names 30994 30995 +1 1 +.names 30941 30942 30996 +1- 1 +-1 1 +.names 30995 30953 30997 +01 1 +10 1 +.names 30997 30998 +1 1 +.names 31001 30999 +0 1 +.names 30999 31000 +1 1 +.names 30953 11160 31001 +01 1 +10 1 +.names 31004 31002 +0 1 +.names 31002 31003 +1 1 +.names 30978 11249 31004 +01 1 +10 1 +.names 30978 31005 +0 1 +.names 31005 31006 +1 1 +.names 11152 30973 31007 +1- 1 +-1 1 +.names 30941 30945 31008 +1- 1 +-1 1 +.names 31011 31012 31009 +1- 1 +-1 1 +.names 31009 31010 +1 1 +.names 11200 31011 +0 1 +.names 11196 31012 +0 1 +.names 31017 31018 31013 +1- 1 +-1 1 +.names 31013 31014 +1 1 +.names 11267 31015 +0 1 +.names 11353 31016 +0 1 +.names 31015 31016 31017 +1- 1 +-1 1 +.names 11263 31018 +0 1 +.names 31021 31016 31019 +1- 1 +-1 1 +.names 31019 31020 +1 1 +.names 11204 31021 +0 1 +.names 31025 31026 31022 +1- 1 +-1 1 +.names 31022 31023 +1 1 +.names 31020 31024 +0 1 +.names 11200 31024 31025 +1- 1 +-1 1 +.names 31014 31026 +0 1 +.names 31030 31024 31027 +1- 1 +-1 1 +.names 31027 31028 +1 1 +.names 31011 31029 +1 1 +.names 31029 31030 +0 1 +.names 11349 31012 31031 +1- 1 +-1 1 +.names 31031 31032 +1 1 +.names 31043 31046 31033 +1- 1 +-1 1 +.names 31033 31034 +1 1 +.names 31010 31035 +0 1 +.names 31084 31021 31036 +1- 1 +-1 1 +.names 31036 31037 +1 1 +.names 31037 31038 +0 1 +.names 31035 31038 31039 +1- 1 +-1 1 +.names 31083 31012 31040 +1- 1 +-1 1 +.names 31040 31041 +1 1 +.names 31041 31042 +0 1 +.names 31039 31042 31043 +1- 1 +-1 1 +.names 11349 31044 +0 1 +.names 31044 31045 +1 1 +.names 31045 31046 +0 1 +.names 11357 31049 31047 +1- 1 +-1 1 +.names 31047 31048 +1 1 +.names 11259 31049 +0 1 +.names 11204 31015 31050 +1- 1 +-1 1 +.names 31050 31051 +1 1 +.names 31054 31051 31052 +01 1 +10 1 +.names 31052 31053 +1 1 +.names 31018 31054 +1 1 +.names 31058 31023 31055 +01 1 +10 1 +.names 31055 31056 +1 1 +.names 31032 31057 +0 1 +.names 31057 31058 +1 1 +.names 31062 31034 31059 +01 1 +10 1 +.names 31059 31060 +1 1 +.names 31048 31061 +0 1 +.names 31061 31062 +1 1 +.names 31062 31066 31063 +01 1 +10 1 +.names 31063 31064 +1 1 +.names 31085 31038 31065 +1- 1 +-1 1 +.names 31065 31066 +1 1 +.names 31069 31021 31067 +11 1 +.names 31067 31068 +1 1 +.names 31015 31018 31069 +1- 1 +-1 1 +.names 31072 31070 +0 1 +.names 31070 31071 +1 1 +.names 31032 31028 31072 +01 1 +10 1 +.names 31068 31076 31073 +01 1 +10 1 +.names 31073 31074 +1 1 +.names 11200 31016 31075 +1- 1 +-1 1 +.names 31075 31076 +1 1 +.names 31079 31077 +0 1 +.names 31077 31078 +1 1 +.names 31076 11204 31079 +01 1 +10 1 +.names 31051 31080 +0 1 +.names 31080 31081 +1 1 +.names 31015 31018 31082 +1- 1 +-1 1 +.names 31082 31016 31083 +1- 1 +-1 1 +.names 31016 31012 31084 +1- 1 +-1 1 +.names 11349 31035 31085 +1- 1 +-1 1 +.names 31089 31086 +0 1 +.names 31086 31087 +1 1 +.names 31969 31088 +0 1 +.names 31088 31089 +1 1 +.names 31095 31099 56653 +1- 1 +-1 1 +.names 31658 31091 +1 1 +.names 31091 31092 +1 1 +.names 31092 31093 +0 1 +.names 31087 31094 +0 1 +.names 31093 31094 31095 +11 1 +.names 31140 31096 +0 1 +.names 31096 31097 +1 1 +.names 31097 31098 +0 1 +.names 31092 31098 31099 +11 1 +.names 31104 31108 56654 +1- 1 +-1 1 +.names 31138 31101 +0 1 +.names 31101 31102 +1 1 +.names 31102 31103 +0 1 +.names 31093 31103 31104 +11 1 +.names 31136 31105 +0 1 +.names 31105 31106 +1 1 +.names 31106 31107 +0 1 +.names 31092 31107 31108 +11 1 +.names 31113 31117 56655 +1- 1 +-1 1 +.names 31134 31110 +0 1 +.names 31110 31111 +1 1 +.names 31111 31112 +0 1 +.names 31093 31112 31113 +11 1 +.names 31132 31114 +0 1 +.names 31114 31115 +1 1 +.names 31115 31116 +0 1 +.names 31092 31116 31117 +11 1 +.names 31122 31126 56656 +1- 1 +-1 1 +.names 31130 31119 +0 1 +.names 31119 31120 +1 1 +.names 31120 31121 +0 1 +.names 31093 31121 31122 +11 1 +.names 31128 31123 +0 1 +.names 31123 31124 +1 1 +.names 31124 31125 +0 1 +.names 31092 31125 31126 +11 1 +.names 31992 31967 31127 +01 1 +10 1 +.names 31127 31128 +1 1 +.names 31990 31129 +0 1 +.names 31129 31130 +1 1 +.names 31987 31989 31131 +01 1 +10 1 +.names 31131 31132 +1 1 +.names 31997 31133 +0 1 +.names 31133 31134 +1 1 +.names 31985 31954 31135 +01 1 +10 1 +.names 31135 31136 +1 1 +.names 31998 31137 +0 1 +.names 31137 31138 +1 1 +.names 31983 31969 31139 +01 1 +10 1 +.names 31139 31140 +1 1 +.names 31145 31148 31141 +11 1 +.names 31141 31142 +1 1 +.names 31510 31511 31143 +1- 1 +-1 1 +.names 31143 31144 +1 1 +.names 31144 31145 +0 1 +.names 32082 32085 31146 +1- 1 +-1 1 +.names 31146 31147 +1 1 +.names 31147 31148 +0 1 +.names 31142 31149 +1 1 +.names 31155 31158 31150 +1- 1 +-1 1 +.names 31150 31151 +1 1 +.names 32091 31152 +0 1 +.names 31152 31153 +1 1 +.names 31153 31154 +0 1 +.names 31154 31145 31155 +11 1 +.names 31513 31514 31156 +11 1 +.names 31156 31157 +1 1 +.names 31157 31158 +0 1 +.names 30090 31159 +0 1 +.names 30501 31160 +0 1 +.names 30126 31161 +0 1 +.names 30537 31162 +0 1 +.names 30081 31163 +0 1 +.names 30483 31164 +0 1 +.names 30226 31165 +0 1 +.names 30771 31166 +0 1 +.names 11135 11139 31167 +1- 1 +-1 1 +.names 31167 31168 +1 1 +.names 11324 11320 31169 +11 1 +.names 31169 31170 +1 1 +.names 31174 31171 +0 1 +.names 31171 31172 +1 1 +.names 31671 31173 +0 1 +.names 31173 31174 +1 1 +.names 31178 31175 +0 1 +.names 31175 31176 +1 1 +.names 31666 31667 31177 +1- 1 +-1 1 +.names 31177 31178 +1 1 +.names 31183 31184 31179 +1- 1 +-1 1 +.names 31179 31180 +1 1 +.names 31172 31181 +0 1 +.names 31176 31182 +0 1 +.names 31181 31182 31183 +11 1 +.names 11224 31174 31184 +11 1 +.names 31189 31185 +0 1 +.names 31185 31186 +1 1 +.names 11192 31190 31187 +1- 1 +-1 1 +.names 31187 31188 +1 1 +.names 31188 11369 31189 +01 1 +10 1 +.names 11227 31190 +0 1 +.names 31195 31198 31191 +1- 1 +-1 1 +.names 31191 31192 +1 1 +.names 11192 31193 +0 1 +.names 31193 31194 +1 1 +.names 31194 31195 +0 1 +.names 31245 31190 31196 +1- 1 +-1 1 +.names 31196 31197 +1 1 +.names 31197 31198 +0 1 +.names 11188 31201 31199 +1- 1 +-1 1 +.names 31199 31200 +1 1 +.names 11377 31201 +0 1 +.names 31211 31214 31202 +1- 1 +-1 1 +.names 31202 31203 +1 1 +.names 31249 31190 31204 +1- 1 +-1 1 +.names 31204 31205 +1 1 +.names 31205 31206 +0 1 +.names 11188 31206 31207 +1- 1 +-1 1 +.names 31251 31201 31208 +1- 1 +-1 1 +.names 31208 31209 +1 1 +.names 31209 31210 +0 1 +.names 31207 31210 31211 +1- 1 +-1 1 +.names 31193 31201 31212 +1- 1 +-1 1 +.names 31212 31213 +1 1 +.names 31213 31214 +0 1 +.names 11361 31018 31215 +1- 1 +-1 1 +.names 31215 31216 +1 1 +.names 11369 31219 31217 +1- 1 +-1 1 +.names 31217 31218 +1 1 +.names 11184 31219 +0 1 +.names 31223 31218 31220 +01 1 +10 1 +.names 31220 31221 +1 1 +.names 11271 31222 +0 1 +.names 31222 31223 +1 1 +.names 31227 31188 31224 +01 1 +10 1 +.names 31224 31225 +1 1 +.names 31257 31245 31226 +11 1 +.names 31226 31227 +1 1 +.names 31231 31233 31228 +01 1 +10 1 +.names 31228 31229 +1 1 +.names 31200 31230 +0 1 +.names 31230 31231 +1 1 +.names 31255 31256 31232 +1- 1 +-1 1 +.names 31232 31233 +1 1 +.names 31236 31234 +0 1 +.names 31234 31235 +1 1 +.names 31200 31192 31236 +01 1 +10 1 +.names 31240 31203 31237 +01 1 +10 1 +.names 31237 31238 +1 1 +.names 31216 31239 +0 1 +.names 31239 31240 +1 1 +.names 31240 31244 31241 +01 1 +10 1 +.names 31241 31242 +1 1 +.names 31254 31206 31243 +1- 1 +-1 1 +.names 31243 31244 +1 1 +.names 11369 31245 +0 1 +.names 31248 31222 31246 +1- 1 +-1 1 +.names 31246 31247 +1 1 +.names 31219 31190 31248 +1- 1 +-1 1 +.names 31245 31201 31249 +1- 1 +-1 1 +.names 31219 31222 31250 +1- 1 +-1 1 +.names 31250 31190 31251 +1- 1 +-1 1 +.names 31218 31252 +0 1 +.names 31252 31253 +1 1 +.names 11188 31214 31254 +1- 1 +-1 1 +.names 11192 31198 31255 +1- 1 +-1 1 +.names 31247 31256 +0 1 +.names 31219 31222 31257 +1- 1 +-1 1 +.names 31262 31266 56639 +1- 1 +-1 1 +.names 31235 31259 +0 1 +.names 31259 31260 +1 1 +.names 31260 31261 +0 1 +.names 11252 31261 31262 +11 1 +.names 31229 31263 +0 1 +.names 31263 31264 +1 1 +.names 31264 31265 +0 1 +.names 11222 31265 31266 +11 1 +.names 31271 31275 56638 +1- 1 +-1 1 +.names 31186 31268 +0 1 +.names 31268 31269 +1 1 +.names 31269 31270 +0 1 +.names 11252 31270 31271 +11 1 +.names 31225 31272 +0 1 +.names 31272 31273 +1 1 +.names 31273 31274 +0 1 +.names 11222 31274 31275 +11 1 +.names 31238 31276 +0 1 +.names 31276 31277 +1 1 +.names 31242 31278 +0 1 +.names 31278 31279 +1 1 +.names 31282 31284 56640 +1- 1 +-1 1 +.names 31279 31281 +0 1 +.names 11252 31281 31282 +11 1 +.names 31277 31283 +0 1 +.names 11222 31283 31284 +11 1 +.names 31221 31285 +0 1 +.names 31285 31286 +1 1 +.names 31253 31287 +0 1 +.names 31287 31288 +1 1 +.names 31291 31293 56637 +1- 1 +-1 1 +.names 31288 31290 +0 1 +.names 11252 31290 31291 +11 1 +.names 31286 31292 +0 1 +.names 11222 31292 31293 +11 1 +.names 11119 11123 31294 +1- 1 +-1 1 +.names 31294 31295 +1 1 +.names 11344 11258 31296 +11 1 +.names 31296 31297 +1 1 +.names 31302 31305 31298 +1- 1 +-1 1 +.names 31298 31299 +1 1 +.names 11304 11248 31300 +11 1 +.names 31300 31301 +1 1 +.names 31301 31302 +0 1 +.names 11143 11147 31303 +11 1 +.names 31303 31304 +1 1 +.names 31304 31305 +0 1 +.names 31311 31314 31306 +11 1 +.names 31306 31307 +1 1 +.names 11155 11159 31308 +1- 1 +-1 1 +.names 31308 31309 +1 1 +.names 31309 31310 +0 1 +.names 31310 31305 31311 +1- 1 +-1 1 +.names 11300 11151 31312 +1- 1 +-1 1 +.names 31312 31313 +1 1 +.names 31313 31314 +0 1 +.names 30008 31315 +0 1 +.names 30395 31316 +0 1 +.names 30071 31317 +0 1 +.names 30468 31318 +0 1 +.names 30044 31319 +0 1 +.names 30357 31320 +0 1 +.names 31324 31321 +0 1 +.names 31321 31322 +1 1 +.names 31562 31323 +0 1 +.names 31323 31324 +1 1 +.names 31330 31334 56652 +1- 1 +-1 1 +.names 11108 31326 +0 1 +.names 31363 31327 +0 1 +.names 31327 31328 +1 1 +.names 31328 31329 +0 1 +.names 31326 31329 31330 +11 1 +.names 31361 31331 +0 1 +.names 31331 31332 +1 1 +.names 31332 31333 +0 1 +.names 11108 31333 31334 +11 1 +.names 31339 31343 56650 +1- 1 +-1 1 +.names 31371 31336 +0 1 +.names 31336 31337 +1 1 +.names 31337 31338 +0 1 +.names 31326 31338 31339 +11 1 +.names 31369 31340 +0 1 +.names 31340 31341 +1 1 +.names 31341 31342 +0 1 +.names 11108 31342 31343 +11 1 +.names 31346 31350 56649 +1- 1 +-1 1 +.names 31322 31345 +0 1 +.names 31326 31345 31346 +11 1 +.names 31373 31347 +0 1 +.names 31347 31348 +1 1 +.names 31348 31349 +0 1 +.names 11108 31349 31350 +11 1 +.names 31355 31359 56651 +1- 1 +-1 1 +.names 31367 31352 +0 1 +.names 31352 31353 +1 1 +.names 31353 31354 +0 1 +.names 31326 31354 31355 +11 1 +.names 31365 31356 +0 1 +.names 31356 31357 +1 1 +.names 31357 31358 +0 1 +.names 11108 31358 31359 +11 1 +.names 31591 31559 31360 +01 1 +10 1 +.names 31360 31361 +1 1 +.names 31583 31362 +0 1 +.names 31362 31363 +1 1 +.names 31580 31582 31364 +01 1 +10 1 +.names 31364 31365 +1 1 +.names 31594 31366 +0 1 +.names 31366 31367 +1 1 +.names 31578 31546 31368 +01 1 +10 1 +.names 31368 31369 +1 1 +.names 31595 31370 +0 1 +.names 31370 31371 +1 1 +.names 31576 31562 31372 +01 1 +10 1 +.names 31372 31373 +1 1 +.names 30099 31374 +0 1 +.names 30609 31375 +0 1 +.names 11360 11187 31376 +1- 1 +-1 1 +.names 31376 31377 +1 1 +.names 11376 11226 31378 +11 1 +.names 31378 31379 +1 1 +.names 29989 31380 +0 1 +.names 30323 31381 +0 1 +.names 30053 31382 +0 1 +.names 30413 31383 +0 1 +.names 31386 31389 31384 +11 1 +.names 31384 31385 +1 1 +.names 31299 31386 +0 1 +.names 31604 31607 31387 +1- 1 +-1 1 +.names 31387 31388 +1 1 +.names 31388 31389 +0 1 +.names 31395 31397 31390 +11 1 +.names 31390 31391 +1 1 +.names 31611 31612 31392 +11 1 +.names 31392 31393 +1 1 +.names 31393 31394 +0 1 +.names 31389 31394 31395 +1- 1 +-1 1 +.names 31307 31396 +0 1 +.names 31396 31394 31397 +1- 1 +-1 1 +.names 32096 32097 31398 +1- 1 +-1 1 +.names 31398 31399 +1 1 +.names 31399 31400 +0 1 +.names 32099 32100 31401 +11 1 +.names 31401 31402 +1 1 +.names 31402 31403 +0 1 +.names 31403 31148 31404 +11 1 +.names 29999 31405 +0 1 +.names 30376 31406 +0 1 +.names 30108 31407 +0 1 +.names 30627 31408 +0 1 +.names 11384 11392 31409 +11 1 +.names 31409 31410 +1 1 +.names 11316 11312 31411 +1- 1 +-1 1 +.names 31411 31412 +1 1 +.names 31648 31649 31413 +1- 1 +-1 1 +.names 31413 31414 +1 1 +.names 31414 31415 +0 1 +.names 31171 31415 31416 +11 1 +.names 31651 31652 31417 +11 1 +.names 31417 31418 +1 1 +.names 31418 31419 +0 1 +.names 31424 31425 31420 +11 1 +.names 31420 31421 +1 1 +.names 31151 31422 +0 1 +.names 31385 31423 +0 1 +.names 31422 31423 31424 +1- 1 +-1 1 +.names 31391 31425 +0 1 +.names 31423 31428 31426 +1- 1 +-1 1 +.names 31426 31427 +1 1 +.names 31149 31428 +0 1 +.names 31432 31429 +0 1 +.names 31429 31430 +1 1 +.names 31722 31431 +0 1 +.names 31431 31432 +1 1 +.names 31436 31440 56645 +1- 1 +-1 1 +.names 11235 31434 +0 1 +.names 31430 31435 +0 1 +.names 31434 31435 31436 +11 1 +.names 31481 31437 +0 1 +.names 31437 31438 +1 1 +.names 31438 31439 +0 1 +.names 11235 31439 31440 +11 1 +.names 31445 31449 56646 +1- 1 +-1 1 +.names 31479 31442 +0 1 +.names 31442 31443 +1 1 +.names 31443 31444 +0 1 +.names 31434 31444 31445 +11 1 +.names 31477 31446 +0 1 +.names 31446 31447 +1 1 +.names 31447 31448 +0 1 +.names 11235 31448 31449 +11 1 +.names 31454 31458 56647 +1- 1 +-1 1 +.names 31475 31451 +0 1 +.names 31451 31452 +1 1 +.names 31452 31453 +0 1 +.names 31434 31453 31454 +11 1 +.names 31473 31455 +0 1 +.names 31455 31456 +1 1 +.names 31456 31457 +0 1 +.names 11235 31457 31458 +11 1 +.names 31463 31467 56648 +1- 1 +-1 1 +.names 31471 31460 +0 1 +.names 31460 31461 +1 1 +.names 31461 31462 +0 1 +.names 31434 31462 31463 +11 1 +.names 31469 31464 +0 1 +.names 31464 31465 +1 1 +.names 31465 31466 +0 1 +.names 11235 31466 31467 +11 1 +.names 31728 31701 31468 +01 1 +10 1 +.names 31468 31469 +1 1 +.names 31729 31470 +0 1 +.names 31470 31471 +1 1 +.names 31725 31687 31472 +01 1 +10 1 +.names 31472 31473 +1 1 +.names 31726 31474 +0 1 +.names 31474 31475 +1 1 +.names 31731 31685 31476 +01 1 +10 1 +.names 31476 31477 +1 1 +.names 31733 31478 +0 1 +.names 31478 31479 +1 1 +.names 31723 31722 31480 +01 1 +10 1 +.names 31480 31481 +1 1 +.names 11352 11195 31482 +11 1 +.names 31482 31483 +1 1 +.names 11356 11348 31484 +1- 1 +-1 1 +.names 31484 31485 +1 1 +.names 31657 11244 31486 +1- 1 +-1 1 +.names 31486 31487 +1 1 +.names 31487 31488 +0 1 +.names 11175 11179 31489 +11 1 +.names 31489 31490 +1 1 +.names 31490 31491 +0 1 +.names 31488 31491 31492 +1- 1 +-1 1 +.names 11372 11364 31493 +1- 1 +-1 1 +.names 31493 31494 +1 1 +.names 31494 31495 +0 1 +.names 31421 31496 +0 1 +.names 31496 31497 +1 1 +.names 11107 31496 31498 +1- 1 +-1 1 +.names 31427 31499 +0 1 +.names 31499 31500 +1 1 +.names 31497 31500 31501 +1- 1 +-1 1 +.names 30262 31502 +0 1 +.names 30843 31503 +0 1 +.names 30253 31504 +0 1 +.names 30825 31505 +0 1 +.names 11183 11270 31506 +11 1 +.names 31506 31507 +1 1 +.names 11191 11368 31508 +1- 1 +-1 1 +.names 31508 31509 +1 1 +.names 31170 31510 +0 1 +.names 31410 31511 +0 1 +.names 31168 31512 +0 1 +.names 31512 31511 31513 +1- 1 +-1 1 +.names 31412 31514 +0 1 +.names 31520 31524 31515 +11 1 +.names 31515 31516 +1 1 +.names 32104 32107 31517 +11 1 +.names 31517 31518 +1 1 +.names 31518 31519 +0 1 +.names 31519 11234 31520 +1- 1 +-1 1 +.names 30860 32103 31521 +1- 1 +-1 1 +.names 31521 31522 +1 1 +.names 31522 31523 +0 1 +.names 31519 31523 31524 +1- 1 +-1 1 +.names 31516 31525 +0 1 +.names 31525 31526 +1 1 +.names 11199 11203 31527 +1- 1 +-1 1 +.names 31527 31528 +1 1 +.names 11266 11262 31529 +11 1 +.names 31529 31530 +1 1 +.names 31533 31534 31531 +1- 1 +-1 1 +.names 31531 31532 +1 1 +.names 11337 31533 +0 1 +.names 11255 31534 +0 1 +.names 31537 31538 31535 +1- 1 +-1 1 +.names 31535 31536 +1 1 +.names 11132 31537 +0 1 +.names 11239 31538 +0 1 +.names 31543 31544 31539 +1- 1 +-1 1 +.names 31539 31540 +1 1 +.names 11128 31541 +0 1 +.names 31541 31542 +1 1 +.names 31542 31543 +0 1 +.names 31536 31544 +0 1 +.names 11128 31538 31545 +1- 1 +-1 1 +.names 31545 31546 +1 1 +.names 11329 31549 31547 +1- 1 +-1 1 +.names 31547 31548 +1 1 +.names 11381 31549 +0 1 +.names 31554 31557 31550 +1- 1 +-1 1 +.names 31550 31551 +1 1 +.names 31597 31572 31552 +11 1 +.names 31552 31553 +1 1 +.names 31553 31554 +0 1 +.names 31596 31538 31555 +1- 1 +-1 1 +.names 31555 31556 +1 1 +.names 31556 31557 +0 1 +.names 11333 31560 31558 +1- 1 +-1 1 +.names 31558 31559 +1 1 +.names 11321 31560 +0 1 +.names 11132 31533 31561 +1- 1 +-1 1 +.names 31561 31562 +1 1 +.names 31571 31574 31563 +1- 1 +-1 1 +.names 31563 31564 +1 1 +.names 31541 31538 31565 +11 1 +.names 31565 31566 +1 1 +.names 31566 31567 +0 1 +.names 31575 31549 31568 +1- 1 +-1 1 +.names 31568 31569 +1 1 +.names 31569 31570 +0 1 +.names 31567 31570 31571 +11 1 +.names 11329 31572 +0 1 +.names 31572 31573 +1 1 +.names 31573 31574 +0 1 +.names 31541 31537 31575 +11 1 +.names 31534 31576 +1 1 +.names 31603 31537 31577 +11 1 +.names 31577 31578 +1 1 +.names 31548 31579 +0 1 +.names 31579 31580 +1 1 +.names 31601 31602 31581 +1- 1 +-1 1 +.names 31581 31582 +1 1 +.names 31559 31551 31583 +01 1 +10 1 +.names 31588 31589 31584 +11 1 +.names 31584 31585 +1 1 +.names 31538 31549 31586 +1- 1 +-1 1 +.names 31586 31587 +1 1 +.names 31587 31588 +0 1 +.names 31532 31589 +0 1 +.names 31592 31593 31590 +11 1 +.names 31590 31591 +1 1 +.names 31585 31592 +0 1 +.names 31564 31593 +0 1 +.names 31540 31548 31594 +01 1 +10 1 +.names 31546 11132 31595 +01 1 +10 1 +.names 31537 31549 31596 +1- 1 +-1 1 +.names 31541 31549 31597 +1- 1 +-1 1 +.names 31600 31538 31598 +1- 1 +-1 1 +.names 31598 31599 +1 1 +.names 31534 31533 31600 +1- 1 +-1 1 +.names 11128 31544 31601 +1- 1 +-1 1 +.names 31599 31602 +0 1 +.names 31533 31534 31603 +1- 1 +-1 1 +.names 30934 31604 +0 1 +.names 11292 11296 31605 +11 1 +.names 31605 31606 +1 1 +.names 31606 31607 +0 1 +.names 11167 11171 31608 +1- 1 +-1 1 +.names 31608 31609 +1 1 +.names 31609 31610 +0 1 +.names 31610 31604 31611 +1- 1 +-1 1 +.names 30932 31612 +0 1 +.names 31415 31400 31613 +11 1 +.names 31613 31614 +1 1 +.names 31614 31615 +0 1 +.names 11230 31615 31616 +1- 1 +-1 1 +.names 32116 31617 +0 1 +.names 31617 31618 +1 1 +.names 31618 31619 +0 1 +.names 30244 31620 +0 1 +.names 30808 31621 +0 1 +.names 30117 31622 +0 1 +.names 30519 31623 +0 1 +.names 30199 31624 +0 1 +.names 30717 31625 +0 1 +.names 31428 31615 31626 +1- 1 +-1 1 +.names 31626 31627 +1 1 +.names 31630 31422 31628 +11 1 +.names 31628 31629 +1 1 +.names 31619 31428 31630 +1- 1 +-1 1 +.names 30062 31631 +0 1 +.names 30450 31632 +0 1 +.names 11212 31633 +1 1 +.names 11209 31634 +1 1 +.names 31637 11212 31635 +11 1 +.names 31635 31636 +1 1 +.names 4185 31637 +0 1 +.names 31637 11209 31638 +11 1 +.names 31638 31639 +1 1 +.names 31642 31643 31640 +11 1 +.names 31640 31641 +1 1 +.names 31636 31642 +0 1 +.names 31639 31643 +0 1 +.names 31646 31647 31644 +1- 1 +-1 1 +.names 31644 31645 +1 1 +.names 31633 31634 31646 +11 1 +.names 31641 31647 +0 1 +.names 31530 31648 +0 1 +.names 31483 31649 +0 1 +.names 31528 31650 +0 1 +.names 31650 31649 31651 +1- 1 +-1 1 +.names 31485 31652 +0 1 +.names 11340 11115 31653 +1- 1 +-1 1 +.names 31653 31654 +1 1 +.names 11111 11388 31655 +11 1 +.names 31655 31656 +1 1 +.names 31645 31657 +0 1 +.names 31661 31662 31658 +1- 1 +-1 1 +.names 11253 31659 +0 1 +.names 30866 31660 +0 1 +.names 31659 31660 31661 +11 1 +.names 30854 31662 +0 1 +.names 30217 31663 +0 1 +.names 30756 31664 +0 1 +.names 31379 31665 +0 1 +.names 31665 31666 +1 1 +.names 31507 31667 +0 1 +.names 31377 31668 +0 1 +.names 31668 31669 +1 1 +.names 31672 31673 31670 +1- 1 +-1 1 +.names 31670 31671 +1 1 +.names 31509 31379 31672 +11 1 +.names 31669 31673 +0 1 +.names 31679 31680 31674 +1- 1 +-1 1 +.names 31674 31675 +1 1 +.names 11345 31676 +0 1 +.names 31676 31049 31677 +1- 1 +-1 1 +.names 11389 31678 +0 1 +.names 31677 31678 31679 +1- 1 +-1 1 +.names 11112 31680 +0 1 +.names 31683 31678 31681 +1- 1 +-1 1 +.names 31681 31682 +1 1 +.names 11124 31683 +0 1 +.names 11120 31678 31684 +1- 1 +-1 1 +.names 31684 31685 +1 1 +.names 31689 31692 31686 +1- 1 +-1 1 +.names 31686 31687 +1 1 +.names 31682 31688 +0 1 +.names 11120 31688 31689 +1- 1 +-1 1 +.names 31738 31049 31690 +1- 1 +-1 1 +.names 31690 31691 +1 1 +.names 31691 31692 +0 1 +.names 31697 31688 31693 +1- 1 +-1 1 +.names 31693 31694 +1 1 +.names 11120 31695 +0 1 +.names 31695 31696 +1 1 +.names 31696 31697 +0 1 +.names 11116 31680 31698 +1- 1 +-1 1 +.names 31698 31699 +1 1 +.names 31707 31710 31700 +1- 1 +-1 1 +.names 31700 31701 +1 1 +.names 31675 31702 +0 1 +.names 11116 31702 31703 +1- 1 +-1 1 +.names 31695 31680 31704 +1- 1 +-1 1 +.names 31704 31705 +1 1 +.names 31705 31706 +0 1 +.names 31703 31706 31707 +1- 1 +-1 1 +.names 31737 31683 31708 +1- 1 +-1 1 +.names 31708 31709 +1 1 +.names 31709 31710 +0 1 +.names 31715 31718 31711 +1- 1 +-1 1 +.names 31711 31712 +1 1 +.names 31735 31736 31713 +11 1 +.names 31713 31714 +1 1 +.names 31714 31715 +0 1 +.names 31734 31683 31716 +1- 1 +-1 1 +.names 31716 31717 +1 1 +.names 31717 31718 +0 1 +.names 11341 31534 31719 +1- 1 +-1 1 +.names 31719 31720 +1 1 +.names 11124 31676 31721 +1- 1 +-1 1 +.names 31721 31722 +1 1 +.names 31049 31723 +1 1 +.names 31699 31724 +0 1 +.names 31724 31725 +1 1 +.names 31699 31694 31726 +01 1 +10 1 +.names 31720 31727 +0 1 +.names 31727 31728 +1 1 +.names 31720 31712 31729 +01 1 +10 1 +.names 31732 31683 31730 +11 1 +.names 31730 31731 +1 1 +.names 31676 31049 31732 +1- 1 +-1 1 +.names 31685 11124 31733 +01 1 +10 1 +.names 31678 31680 31734 +1- 1 +-1 1 +.names 31695 31680 31735 +1- 1 +-1 1 +.names 11116 31736 +0 1 +.names 31678 31680 31737 +1- 1 +-1 1 +.names 31676 31678 31738 +1- 1 +-1 1 +.names 30208 31739 +0 1 +.names 30735 31740 +0 1 +.names 30172 31741 +0 1 +.names 30663 31742 +0 1 +.names 31745 31746 31743 +1- 1 +-1 1 +.names 31743 31744 +1 1 +.names 11245 31745 +0 1 +.names 11176 31746 +0 1 +.names 31750 31751 31747 +1- 1 +-1 1 +.names 31747 31748 +1 1 +.names 11180 31749 +0 1 +.names 14886 31749 31750 +1- 1 +-1 1 +.names 11276 31751 +0 1 +.names 11245 31749 31752 +1- 1 +-1 1 +.names 31752 31753 +1 1 +.names 31757 31760 31754 +1- 1 +-1 1 +.names 31754 31755 +1 1 +.names 31745 31756 +1 1 +.names 31756 31757 +0 1 +.names 31805 31749 31758 +1- 1 +-1 1 +.names 31758 31759 +1 1 +.names 31759 31760 +0 1 +.names 11365 31746 31761 +1- 1 +-1 1 +.names 31761 31762 +1 1 +.names 31772 31773 31763 +1- 1 +-1 1 +.names 31763 31764 +1 1 +.names 31815 31746 31765 +1- 1 +-1 1 +.names 31765 31766 +1 1 +.names 31766 31767 +0 1 +.names 11365 31767 31768 +1- 1 +-1 1 +.names 31813 31805 31769 +1- 1 +-1 1 +.names 31769 31770 +1 1 +.names 31770 31771 +0 1 +.names 31768 31771 31772 +1- 1 +-1 1 +.names 31744 31773 +0 1 +.names 31776 31779 31774 +1- 1 +-1 1 +.names 31774 31775 +1 1 +.names 11365 31773 31776 +1- 1 +-1 1 +.names 31816 31805 31777 +1- 1 +-1 1 +.names 31777 31778 +1 1 +.names 31778 31779 +0 1 +.names 11373 31222 31780 +1- 1 +-1 1 +.names 31780 31781 +1 1 +.names 11274 31751 31782 +1- 1 +-1 1 +.names 31782 31783 +1 1 +.names 31786 31783 31784 +01 1 +10 1 +.names 31784 31785 +1 1 +.names 14886 31786 +1 1 +.names 31790 31792 31787 +01 1 +10 1 +.names 31787 31788 +1 1 +.names 31762 31789 +0 1 +.names 31789 31790 +1 1 +.names 31817 31818 31791 +1- 1 +-1 1 +.names 31791 31792 +1 1 +.names 31795 31793 +0 1 +.names 31793 31794 +1 1 +.names 31762 31755 31795 +01 1 +10 1 +.names 31799 31764 31796 +01 1 +10 1 +.names 31796 31797 +1 1 +.names 31781 31798 +0 1 +.names 31798 31799 +1 1 +.names 31799 31775 31800 +01 1 +10 1 +.names 31800 31801 +1 1 +.names 31804 31805 31802 +11 1 +.names 31802 31803 +1 1 +.names 31751 14886 31804 +1- 1 +-1 1 +.names 11274 31805 +0 1 +.names 31803 31753 31806 +01 1 +10 1 +.names 31806 31807 +1 1 +.names 31810 31808 +0 1 +.names 31808 31809 +1 1 +.names 31753 11274 31810 +01 1 +10 1 +.names 31783 31811 +0 1 +.names 31811 31812 +1 1 +.names 31749 31746 31813 +1- 1 +-1 1 +.names 31751 14886 31814 +1- 1 +-1 1 +.names 31814 31749 31815 +1- 1 +-1 1 +.names 31749 31746 31816 +1- 1 +-1 1 +.names 11245 31760 31817 +1- 1 +-1 1 +.names 31748 31818 +0 1 +.names 11225 31819 +0 1 +.names 31819 31820 +1 1 +.names 31823 31824 56636 +1- 1 +-1 1 +.names 31820 31822 +0 1 +.names 31822 31797 31823 +11 1 +.names 31820 31801 31824 +11 1 +.names 31788 31825 +0 1 +.names 31825 31826 +1 1 +.names 31794 31827 +0 1 +.names 31827 31828 +1 1 +.names 31831 31833 56635 +1- 1 +-1 1 +.names 31828 31830 +0 1 +.names 31819 31830 31831 +11 1 +.names 31826 31832 +0 1 +.names 11225 31832 31833 +11 1 +.names 31807 31834 +0 1 +.names 31834 31835 +1 1 +.names 31809 31836 +0 1 +.names 31836 31837 +1 1 +.names 31840 31842 56634 +1- 1 +-1 1 +.names 31837 31839 +0 1 +.names 31819 31839 31840 +11 1 +.names 31835 31841 +0 1 +.names 11225 31841 31842 +11 1 +.names 31785 31843 +0 1 +.names 31843 31844 +1 1 +.names 31812 31845 +0 1 +.names 31845 31846 +1 1 +.names 31849 31851 56633 +1- 1 +-1 1 +.names 31846 31848 +0 1 +.names 31819 31848 31849 +11 1 +.names 31844 31850 +0 1 +.names 11225 31850 31851 +11 1 +.names 31854 31855 31852 +1- 1 +-1 1 +.names 31852 31853 +1 1 +.names 11172 31854 +0 1 +.names 11281 31855 +0 1 +.names 31860 31861 31856 +1- 1 +-1 1 +.names 31856 31857 +1 1 +.names 11168 31858 +0 1 +.names 31858 31859 +1 1 +.names 31859 31860 +0 1 +.names 31853 31861 +0 1 +.names 11172 31884 31862 +1- 1 +-1 1 +.names 31862 31863 +1 1 +.names 31866 31869 31864 +1- 1 +-1 1 +.names 31864 31865 +1 1 +.names 11168 31861 31866 +1- 1 +-1 1 +.names 31922 31855 31867 +1- 1 +-1 1 +.names 31867 31868 +1 1 +.names 31868 31869 +0 1 +.names 11289 31872 31870 +1- 1 +-1 1 +.names 31870 31871 +1 1 +.names 11164 31872 +0 1 +.names 31877 31880 31873 +1- 1 +-1 1 +.names 31873 31874 +1 1 +.names 31921 31894 31875 +11 1 +.names 31875 31876 +1 1 +.names 31876 31877 +0 1 +.names 31920 31855 31878 +1- 1 +-1 1 +.names 31878 31879 +1 1 +.names 31879 31880 +0 1 +.names 11285 31883 31881 +1- 1 +-1 1 +.names 31881 31882 +1 1 +.names 11279 31883 +0 1 +.names 11293 31884 +0 1 +.names 31893 31896 31885 +1- 1 +-1 1 +.names 31885 31886 +1 1 +.names 31858 31855 31887 +11 1 +.names 31887 31888 +1 1 +.names 31888 31889 +0 1 +.names 31897 31872 31890 +1- 1 +-1 1 +.names 31890 31891 +1 1 +.names 31891 31892 +0 1 +.names 31889 31892 31893 +11 1 +.names 11289 31894 +0 1 +.names 31894 31895 +1 1 +.names 31895 31896 +0 1 +.names 31858 31854 31897 +11 1 +.names 31871 31898 +0 1 +.names 31898 31899 +1 1 +.names 31882 31874 31900 +01 1 +10 1 +.names 31905 31908 31901 +11 1 +.names 31901 31902 +1 1 +.names 31855 31872 31903 +1- 1 +-1 1 +.names 31903 31904 +1 1 +.names 31904 31905 +0 1 +.names 31884 30976 31906 +1- 1 +-1 1 +.names 31906 31907 +1 1 +.names 31907 31908 +0 1 +.names 31911 31912 31909 +11 1 +.names 31909 31910 +1 1 +.names 31902 31911 +0 1 +.names 31886 31912 +0 1 +.names 31857 31871 31913 +01 1 +10 1 +.names 31923 31854 31914 +11 1 +.names 31914 31915 +1 1 +.names 11168 31855 31916 +1- 1 +-1 1 +.names 31916 31917 +1 1 +.names 31917 11172 31918 +01 1 +10 1 +.names 31863 11297 31919 +01 1 +10 1 +.names 31854 31872 31920 +1- 1 +-1 1 +.names 31858 31872 31921 +1- 1 +-1 1 +.names 30976 31884 31922 +1- 1 +-1 1 +.names 31884 30976 31923 +1- 1 +-1 1 +.names 30025 31924 +0 1 +.names 30282 31925 +0 1 +.names 11252 30869 31926 +1- 1 +-1 1 +.names 30190 31927 +0 1 +.names 30702 31928 +0 1 +.names 30645 31929 +0 1 +.names 30162 31930 +0 1 +.names 30035 31931 +0 1 +.names 30339 31932 +0 1 +.names 31937 31938 31933 +1- 1 +-1 1 +.names 31933 31934 +1 1 +.names 11231 31935 +0 1 +.names 31627 31936 +0 1 +.names 31935 31936 31937 +11 1 +.names 31629 31938 +0 1 +.names 31934 31939 +1 1 +.names 31942 31560 31940 +1- 1 +-1 1 +.names 31940 31941 +1 1 +.names 11325 31942 +0 1 +.names 31945 31946 31943 +1- 1 +-1 1 +.names 31943 31944 +1 1 +.names 11140 31945 +0 1 +.names 11309 31946 +0 1 +.names 31951 31952 31947 +1- 1 +-1 1 +.names 31947 31948 +1 1 +.names 11136 31949 +0 1 +.names 31949 31950 +1 1 +.names 31950 31951 +0 1 +.names 31944 31952 +0 1 +.names 11136 31946 31953 +1- 1 +-1 1 +.names 31953 31954 +1 1 +.names 11313 31957 31955 +1- 1 +-1 1 +.names 31955 31956 +1 1 +.names 11385 31957 +0 1 +.names 31962 31965 31958 +1- 1 +-1 1 +.names 31958 31959 +1 1 +.names 32000 31979 31960 +11 1 +.names 31960 31961 +1 1 +.names 31961 31962 +0 1 +.names 31999 31946 31963 +1- 1 +-1 1 +.names 31963 31964 +1 1 +.names 31964 31965 +0 1 +.names 11317 30942 31966 +1- 1 +-1 1 +.names 31966 31967 +1 1 +.names 11140 31942 31968 +1- 1 +-1 1 +.names 31968 31969 +1 1 +.names 31978 31981 31970 +1- 1 +-1 1 +.names 31970 31971 +1 1 +.names 31946 31949 31972 +11 1 +.names 31972 31973 +1 1 +.names 31973 31974 +0 1 +.names 31982 31957 31975 +1- 1 +-1 1 +.names 31975 31976 +1 1 +.names 31976 31977 +0 1 +.names 31974 31977 31978 +11 1 +.names 11313 31979 +0 1 +.names 31979 31980 +1 1 +.names 31980 31981 +0 1 +.names 31945 31949 31982 +11 1 +.names 31560 31983 +1 1 +.names 32010 31945 31984 +11 1 +.names 31984 31985 +1 1 +.names 31956 31986 +0 1 +.names 31986 31987 +1 1 +.names 32008 32009 31988 +1- 1 +-1 1 +.names 31988 31989 +1 1 +.names 31967 31959 31990 +01 1 +10 1 +.names 31995 31996 31991 +11 1 +.names 31991 31992 +1 1 +.names 32003 32004 31993 +11 1 +.names 31993 31994 +1 1 +.names 31994 31995 +0 1 +.names 31971 31996 +0 1 +.names 31948 31956 31997 +01 1 +10 1 +.names 31954 11140 31998 +01 1 +10 1 +.names 31945 31957 31999 +1- 1 +-1 1 +.names 31949 31957 32000 +1- 1 +-1 1 +.names 31946 31957 32001 +1- 1 +-1 1 +.names 32001 32002 +1 1 +.names 32002 32003 +0 1 +.names 31941 32004 +0 1 +.names 32007 31946 32005 +1- 1 +-1 1 +.names 32005 32006 +1 1 +.names 31560 31942 32007 +1- 1 +-1 1 +.names 11136 31952 32008 +1- 1 +-1 1 +.names 32006 32009 +0 1 +.names 31942 31560 32010 +1- 1 +-1 1 +.names 31006 32011 +0 1 +.names 32011 32012 +1 1 +.names 30991 32013 +0 1 +.names 32013 32014 +1 1 +.names 32018 32022 56657 +1- 1 +-1 1 +.names 31939 32016 +0 1 +.names 32012 32017 +0 1 +.names 32016 32017 32018 +11 1 +.names 31003 32019 +0 1 +.names 32019 32020 +1 1 +.names 32020 32021 +0 1 +.names 31939 32021 32022 +11 1 +.names 32027 32031 56658 +1- 1 +-1 1 +.names 31000 32024 +0 1 +.names 32024 32025 +1 1 +.names 32025 32026 +0 1 +.names 32016 32026 32027 +11 1 +.names 30998 32028 +0 1 +.names 32028 32029 +1 1 +.names 32029 32030 +0 1 +.names 31939 32030 32031 +11 1 +.names 32036 32040 56659 +1- 1 +-1 1 +.names 30984 32033 +0 1 +.names 32033 32034 +1 1 +.names 32034 32035 +0 1 +.names 32016 32035 32036 +11 1 +.names 30980 32037 +0 1 +.names 32037 32038 +1 1 +.names 32038 32039 +0 1 +.names 31939 32039 32040 +11 1 +.names 32043 32047 56660 +1- 1 +-1 1 +.names 32014 32042 +0 1 +.names 32016 32042 32043 +11 1 +.names 30987 32044 +0 1 +.names 32044 32045 +1 1 +.names 32045 32046 +0 1 +.names 31939 32046 32047 +11 1 +.names 31056 32048 +0 1 +.names 32048 32049 +1 1 +.names 32054 32056 56643 +1- 1 +-1 1 +.names 31071 32051 +0 1 +.names 32051 32052 +1 1 +.names 32052 32053 +0 1 +.names 11230 32053 32054 +11 1 +.names 32049 32055 +0 1 +.names 11233 32055 32056 +11 1 +.names 32061 32065 56642 +1- 1 +-1 1 +.names 31078 32058 +0 1 +.names 32058 32059 +1 1 +.names 32059 32060 +0 1 +.names 11230 32060 32061 +11 1 +.names 31074 32062 +0 1 +.names 32062 32063 +1 1 +.names 32063 32064 +0 1 +.names 11233 32064 32065 +11 1 +.names 32070 32074 56641 +1- 1 +-1 1 +.names 31081 32067 +0 1 +.names 32067 32068 +1 1 +.names 32068 32069 +0 1 +.names 11230 32069 32070 +11 1 +.names 31053 32071 +0 1 +.names 32071 32072 +1 1 +.names 32072 32073 +0 1 +.names 11233 32073 32074 +11 1 +.names 11230 32075 +1 1 +.names 32078 32079 56644 +1- 1 +-1 1 +.names 32075 32077 +0 1 +.names 32077 31060 32078 +11 1 +.names 32075 31064 32079 +11 1 +.names 11380 11238 32080 +11 1 +.names 32080 32081 +1 1 +.names 32081 32082 +0 1 +.names 11336 11254 32083 +11 1 +.names 32083 32084 +1 1 +.names 32084 32085 +0 1 +.names 32089 32086 +0 1 +.names 32086 32087 +1 1 +.names 11332 11328 32088 +1- 1 +-1 1 +.names 32088 32089 +1 1 +.names 32094 32095 32090 +1- 1 +-1 1 +.names 32090 32091 +1 1 +.names 11127 11131 32092 +1- 1 +-1 1 +.names 32092 32093 +1 1 +.names 32093 32081 32094 +11 1 +.names 32087 32095 +0 1 +.names 31297 32096 +0 1 +.names 31656 32097 +0 1 +.names 31295 32098 +0 1 +.names 32098 32097 32099 +1- 1 +-1 1 +.names 31654 32100 +0 1 +.names 31145 31386 32101 +11 1 +.names 32101 32102 +1 1 +.names 32102 32103 +0 1 +.names 30864 32103 32104 +1- 1 +-1 1 +.names 32117 31396 32105 +1- 1 +-1 1 +.names 32105 32106 +1 1 +.names 32106 32107 +0 1 +.names 30181 32108 +0 1 +.names 30681 32109 +0 1 +.names 29979 32110 +0 1 +.names 30301 32111 +0 1 +.names 32114 31403 32112 +1- 1 +-1 1 +.names 32112 32113 +1 1 +.names 31400 31419 32114 +11 1 +.names 32113 32115 +0 1 +.names 32115 32116 +1 1 +.names 31386 31158 32117 +11 1 +.names 32120 32121 32118 +1- 1 +-1 1 +.names 32118 32119 +1 1 +.names 7590 32120 +0 1 +.names 1348 32121 +0 1 +.names 32124 32125 32122 +1- 1 +-1 1 +.names 32122 32123 +1 1 +.names 56630 32124 +0 1 +.names 7611 32125 +0 1 +.names 32137 32138 32126 +1- 1 +-1 1 +.names 32126 32127 +1 1 +.names 32127 32128 +0 1 +.names 32123 32129 +0 1 +.names 32128 32129 32130 +1- 1 +-1 1 +.names 32141 32143 32131 +11 1 +.names 32131 32132 +1 1 +.names 32132 32133 +0 1 +.names 32153 32154 32134 +11 1 +.names 32134 32135 +1 1 +.names 32135 32136 +0 1 +.names 2413 32136 32137 +11 1 +.names 1783 2413 32138 +11 1 +.names 7600 32155 32139 +1- 1 +-1 1 +.names 32139 32140 +1 1 +.names 32140 32119 32141 +11 1 +.names 7608 32156 32142 +1- 1 +-1 1 +.names 32142 32143 +1 1 +.names 32148 2413 32144 +1- 1 +-1 1 +.names 32144 32145 +1 1 +.names 32120 32146 +1 1 +.names 32146 32147 +0 1 +.names 7611 32147 32148 +1- 1 +-1 1 +.names 7613 32152 32149 +1- 1 +-1 1 +.names 32149 32150 +1 1 +.names 7608 32151 +1 1 +.names 32151 32152 +0 1 +.names 32145 32153 +0 1 +.names 32150 32154 +0 1 +.names 56585 32155 +0 1 +.names 56621 32156 +0 1 +.names 32124 32125 32157 +1- 1 +-1 1 +.names 32157 32158 +1 1 +.names 32165 32167 32159 +1- 1 +-1 1 +.names 32159 32160 +1 1 +.names 7612 32161 +0 1 +.names 32177 32178 32162 +11 1 +.names 32162 32163 +1 1 +.names 32163 32164 +0 1 +.names 32161 32164 32165 +11 1 +.names 1349 32166 +0 1 +.names 7612 32166 32167 +11 1 +.names 32172 2413 32168 +1- 1 +-1 1 +.names 32168 32169 +1 1 +.names 7608 32170 +1 1 +.names 32170 32171 +0 1 +.names 7622 32171 32172 +1- 1 +-1 1 +.names 7611 32176 32173 +1- 1 +-1 1 +.names 32173 32174 +1 1 +.names 2413 32175 +1 1 +.names 32175 32176 +0 1 +.names 32169 32177 +0 1 +.names 32174 32178 +0 1 +.names 32195 32196 32179 +1- 1 +-1 1 +.names 32179 32180 +1 1 +.names 32160 32181 +0 1 +.names 7608 32184 32182 +1- 1 +-1 1 +.names 32182 32183 +1 1 +.names 56605 32184 +0 1 +.names 2413 32185 +1 1 +.names 32185 32186 +1 1 +.names 32189 32190 32187 +1- 1 +-1 1 +.names 32187 32188 +1 1 +.names 56569 32189 +0 1 +.names 7622 32190 +0 1 +.names 32186 32191 +0 1 +.names 32188 32192 +0 1 +.names 32191 32192 32193 +1- 1 +-1 1 +.names 32183 32194 +0 1 +.names 32193 32194 32195 +1- 1 +-1 1 +.names 32158 32196 +0 1 +.names 32211 32212 32197 +1- 1 +-1 1 +.names 32197 32198 +1 1 +.names 32198 32199 +0 1 +.names 2413 32200 +1 1 +.names 32200 32201 +1 1 +.names 32201 32202 +0 1 +.names 32199 32202 32203 +1- 1 +-1 1 +.names 32217 32219 32204 +11 1 +.names 32204 32205 +1 1 +.names 32205 32206 +0 1 +.names 7582 32207 +0 1 +.names 32226 32227 32208 +11 1 +.names 32208 32209 +1 1 +.names 32209 32210 +0 1 +.names 32207 32210 32211 +11 1 +.names 7582 32124 32212 +11 1 +.names 32161 32235 32213 +1- 1 +-1 1 +.names 32213 32214 +1 1 +.names 7600 22288 32215 +1- 1 +-1 1 +.names 32215 32216 +1 1 +.names 32214 32216 32217 +11 1 +.names 32228 32229 32218 +1- 1 +-1 1 +.names 32218 32219 +1 1 +.names 7613 32223 32220 +1- 1 +-1 1 +.names 32220 32221 +1 1 +.names 2413 32222 +1 1 +.names 32222 32223 +0 1 +.names 32234 2413 32224 +1- 1 +-1 1 +.names 32224 32225 +1 1 +.names 32225 32226 +0 1 +.names 32221 32227 +0 1 +.names 56600 32228 +0 1 +.names 7597 32229 +0 1 +.names 32229 32230 +1 1 +.names 32230 32231 +0 1 +.names 32161 32232 +1 1 +.names 32232 32233 +0 1 +.names 32231 32233 32234 +1- 1 +-1 1 +.names 1350 32235 +0 1 +.names 32250 32251 32236 +1- 1 +-1 1 +.names 32236 32237 +1 1 +.names 32237 32238 +0 1 +.names 2413 32239 +1 1 +.names 32239 32240 +1 1 +.names 32240 32241 +0 1 +.names 32238 32241 32242 +1- 1 +-1 1 +.names 32270 32271 32243 +11 1 +.names 32243 32244 +1 1 +.names 32244 32245 +0 1 +.names 7618 32246 +0 1 +.names 32258 32259 32247 +11 1 +.names 32247 32248 +1 1 +.names 32248 32249 +0 1 +.names 32246 32249 32250 +11 1 +.names 7618 32124 32251 +11 1 +.names 7617 32255 32252 +1- 1 +-1 1 +.names 32252 32253 +1 1 +.names 2413 32254 +1 1 +.names 32254 32255 +0 1 +.names 32278 2413 32256 +1- 1 +-1 1 +.names 32256 32257 +1 1 +.names 32257 32258 +0 1 +.names 32253 32259 +0 1 +.names 32262 32263 32260 +1- 1 +-1 1 +.names 32260 32261 +1 1 +.names 56607 32262 +0 1 +.names 7617 32263 +0 1 +.names 32266 32267 32264 +1- 1 +-1 1 +.names 32264 32265 +1 1 +.names 1351 7591 32266 +11 1 +.names 32261 32267 +0 1 +.names 7621 56571 32268 +11 1 +.names 32268 32269 +1 1 +.names 32269 32270 +0 1 +.names 32265 32271 +0 1 +.names 7591 32272 +0 1 +.names 32272 32273 +1 1 +.names 7621 32274 +0 1 +.names 32274 32275 +1 1 +.names 32275 32276 +0 1 +.names 32273 32277 +0 1 +.names 32276 32277 32278 +1- 1 +-1 1 +.names 32272 32281 32279 +1- 1 +-1 1 +.names 32279 32280 +1 1 +.names 1352 32281 +0 1 +.names 32284 7608 32282 +1- 1 +-1 1 +.names 32282 32283 +1 1 +.names 56609 32284 +0 1 +.names 7620 32288 32285 +1- 1 +-1 1 +.names 32285 32286 +1 1 +.names 2413 32287 +1 1 +.names 32287 32288 +0 1 +.names 32294 32295 32289 +1- 1 +-1 1 +.names 32289 32290 +1 1 +.names 32298 32299 32291 +11 1 +.names 32291 32292 +1 1 +.names 32292 32293 +0 1 +.names 32246 32293 32294 +11 1 +.names 7618 32124 32295 +11 1 +.names 32302 2413 32296 +1- 1 +-1 1 +.names 32296 32297 +1 1 +.names 32297 32298 +0 1 +.names 32286 32299 +0 1 +.names 32272 32300 +1 1 +.names 32300 32301 +0 1 +.names 7594 32301 32302 +1- 1 +-1 1 +.names 32309 32310 32303 +1- 1 +-1 1 +.names 32303 32304 +1 1 +.names 32280 32305 +0 1 +.names 32319 32320 32306 +1- 1 +-1 1 +.names 32306 32307 +1 1 +.names 32307 32308 +0 1 +.names 32305 32308 32309 +1- 1 +-1 1 +.names 32283 32310 +0 1 +.names 32313 32316 32311 +11 1 +.names 32311 32312 +1 1 +.names 32304 32313 +0 1 +.names 1783 32314 +1 1 +.names 32314 32315 +1 1 +.names 32315 32316 +0 1 +.names 32290 32317 +0 1 +.names 32312 32318 +0 1 +.names 7620 32319 +0 1 +.names 56573 32320 +0 1 +.names 32335 32337 32321 +1- 1 +-1 1 +.names 32321 32322 +1 1 +.names 32322 32323 +0 1 +.names 2413 32324 +1 1 +.names 32324 32325 +1 1 +.names 32325 32326 +0 1 +.names 32323 32326 32327 +1- 1 +-1 1 +.names 32358 32354 32328 +11 1 +.names 32328 32329 +1 1 +.names 32329 32330 +0 1 +.names 7607 32331 +0 1 +.names 32348 32349 32332 +11 1 +.names 32332 32333 +1 1 +.names 32333 32334 +0 1 +.names 32331 32334 32335 +11 1 +.names 56616 32336 +0 1 +.names 7607 32336 32337 +11 1 +.names 7611 2413 32338 +1- 1 +-1 1 +.names 32338 32339 +1 1 +.names 32344 32346 32340 +1- 1 +-1 1 +.names 32340 32341 +1 1 +.names 32347 2413 32342 +11 1 +.names 32342 32343 +1 1 +.names 32343 32344 +0 1 +.names 32190 32345 +1 1 +.names 32345 32346 +0 1 +.names 7592 32347 +0 1 +.names 32341 32348 +0 1 +.names 32339 32349 +0 1 +.names 32347 32352 32350 +1- 1 +-1 1 +.names 32350 32351 +1 1 +.names 1353 32352 +0 1 +.names 32124 32125 32353 +1- 1 +-1 1 +.names 32353 32354 +1 1 +.names 32190 32357 32355 +1- 1 +-1 1 +.names 32355 32356 +1 1 +.names 56580 32357 +0 1 +.names 32356 32351 32358 +11 1 +.names 32373 32374 32359 +1- 1 +-1 1 +.names 32359 32360 +1 1 +.names 32360 32361 +0 1 +.names 2413 32362 +1 1 +.names 32362 32363 +1 1 +.names 32363 32364 +0 1 +.names 32361 32364 32365 +1- 1 +-1 1 +.names 32394 32395 32366 +11 1 +.names 32366 32367 +1 1 +.names 32367 32368 +0 1 +.names 7580 32369 +0 1 +.names 32390 32391 32370 +11 1 +.names 32370 32371 +1 1 +.names 32371 32372 +0 1 +.names 32369 32372 32373 +11 1 +.names 7580 32124 32374 +11 1 +.names 32377 32380 32375 +1- 1 +-1 1 +.names 32375 32376 +1 1 +.names 7590 1354 32377 +11 1 +.names 32396 32274 32378 +1- 1 +-1 1 +.names 32378 32379 +1 1 +.names 32379 32380 +0 1 +.names 32385 2413 32381 +1- 1 +-1 1 +.names 32381 32382 +1 1 +.names 32120 32383 +1 1 +.names 32383 32384 +0 1 +.names 7616 32384 32385 +1- 1 +-1 1 +.names 7621 32389 32386 +1- 1 +-1 1 +.names 32386 32387 +1 1 +.names 2413 32388 +1 1 +.names 32388 32389 +0 1 +.names 32382 32390 +0 1 +.names 32387 32391 +0 1 +.names 56629 7616 32392 +11 1 +.names 32392 32393 +1 1 +.names 32393 32394 +0 1 +.names 32376 32395 +0 1 +.names 56593 32396 +0 1 +.names 32410 32411 32397 +1- 1 +-1 1 +.names 32397 32398 +1 1 +.names 32398 32399 +0 1 +.names 2413 32400 +1 1 +.names 32400 32401 +1 1 +.names 32401 32402 +0 1 +.names 32399 32402 32403 +1- 1 +-1 1 +.names 32416 32418 32404 +11 1 +.names 32404 32405 +1 1 +.names 32405 32406 +0 1 +.names 32428 32429 32407 +11 1 +.names 32407 32408 +1 1 +.names 32408 32409 +0 1 +.names 32246 32409 32410 +11 1 +.names 7618 32124 32411 +11 1 +.names 32161 32432 32412 +1- 1 +-1 1 +.names 32412 32413 +1 1 +.names 7600 32433 32414 +1- 1 +-1 1 +.names 32414 32415 +1 1 +.names 32413 32415 32416 +11 1 +.names 32430 32431 32417 +1- 1 +-1 1 +.names 32417 32418 +1 1 +.names 32423 2413 32419 +1- 1 +-1 1 +.names 32419 32420 +1 1 +.names 32161 32421 +1 1 +.names 32421 32422 +0 1 +.names 7616 32422 32423 +1- 1 +-1 1 +.names 7613 32427 32424 +1- 1 +-1 1 +.names 32424 32425 +1 1 +.names 2413 32426 +1 1 +.names 32426 32427 +0 1 +.names 32425 32428 +0 1 +.names 32420 32429 +0 1 +.names 56618 32430 +0 1 +.names 7616 32431 +0 1 +.names 1355 32432 +0 1 +.names 56582 32433 +0 1 +.names 32439 32440 32434 +1- 1 +-1 1 +.names 32434 32435 +1 1 +.names 32447 32448 32436 +11 1 +.names 32436 32437 +1 1 +.names 32437 32438 +0 1 +.names 32246 32438 32439 +11 1 +.names 7618 32124 32440 +11 1 +.names 1783 32444 32441 +1- 1 +-1 1 +.names 32441 32442 +1 1 +.names 32274 32443 +1 1 +.names 32443 32444 +0 1 +.names 32454 2413 32445 +1- 1 +-1 1 +.names 32445 32446 +1 1 +.names 32446 32447 +0 1 +.names 32442 32448 +0 1 +.names 32451 32229 32449 +1- 1 +-1 1 +.names 32449 32450 +1 1 +.names 56608 32451 +0 1 +.names 32161 32452 +1 1 +.names 32452 32453 +0 1 +.names 7597 32453 32454 +1- 1 +-1 1 +.names 32463 32464 32455 +1- 1 +-1 1 +.names 32455 32456 +1 1 +.names 32161 32473 32457 +1- 1 +-1 1 +.names 32457 32458 +1 1 +.names 32458 32459 +0 1 +.names 32274 32474 32460 +1- 1 +-1 1 +.names 32460 32461 +1 1 +.names 32461 32462 +0 1 +.names 32459 32462 32463 +1- 1 +-1 1 +.names 32450 32464 +0 1 +.names 32435 32465 +0 1 +.names 32471 32472 32466 +11 1 +.names 32466 32467 +1 1 +.names 32467 32468 +0 1 +.names 1783 32469 +1 1 +.names 32469 32470 +1 1 +.names 32456 32471 +0 1 +.names 32470 32472 +0 1 +.names 1356 32473 +0 1 +.names 56572 32474 +0 1 +.names 32488 32489 32475 +1- 1 +-1 1 +.names 32475 32476 +1 1 +.names 32476 32477 +0 1 +.names 2413 32478 +1 1 +.names 32478 32479 +1 1 +.names 32479 32480 +0 1 +.names 32477 32480 32481 +1- 1 +-1 1 +.names 32510 32502 32482 +11 1 +.names 32482 32483 +1 1 +.names 32483 32484 +0 1 +.names 32499 32500 32485 +11 1 +.names 32485 32486 +1 1 +.names 32486 32487 +0 1 +.names 32246 32487 32488 +11 1 +.names 7618 32124 32489 +11 1 +.names 32494 2413 32490 +1- 1 +-1 1 +.names 32490 32491 +1 1 +.names 32120 32492 +1 1 +.names 32492 32493 +0 1 +.names 7616 32493 32494 +1- 1 +-1 1 +.names 7622 32498 32495 +1- 1 +-1 1 +.names 32495 32496 +1 1 +.names 2413 32497 +1 1 +.names 32497 32498 +0 1 +.names 32491 32499 +0 1 +.names 32496 32500 +0 1 +.names 32503 32431 32501 +1- 1 +-1 1 +.names 32501 32502 +1 1 +.names 56624 32503 +0 1 +.names 32120 32506 32504 +1- 1 +-1 1 +.names 32504 32505 +1 1 +.names 1357 32506 +0 1 +.names 32190 32509 32507 +1- 1 +-1 1 +.names 32507 32508 +1 1 +.names 56588 32509 +0 1 +.names 32508 32505 32510 +11 1 +.names 32524 32525 32511 +1- 1 +-1 1 +.names 32511 32512 +1 1 +.names 32512 32513 +0 1 +.names 2413 32514 +1 1 +.names 32514 32515 +1 1 +.names 32515 32516 +0 1 +.names 32513 32516 32517 +1- 1 +-1 1 +.names 32530 32532 32518 +11 1 +.names 32518 32519 +1 1 +.names 32519 32520 +0 1 +.names 32542 32543 32521 +11 1 +.names 32521 32522 +1 1 +.names 32522 32523 +0 1 +.names 32369 32523 32524 +11 1 +.names 7580 32124 32525 +11 1 +.names 32120 32546 32526 +1- 1 +-1 1 +.names 32526 32527 +1 1 +.names 7600 32545 32528 +1- 1 +-1 1 +.names 32528 32529 +1 1 +.names 32527 32529 32530 +11 1 +.names 32544 7608 32531 +1- 1 +-1 1 +.names 32531 32532 +1 1 +.names 7594 2413 32533 +1- 1 +-1 1 +.names 32533 32534 +1 1 +.names 32539 32541 32535 +1- 1 +-1 1 +.names 32535 32536 +1 1 +.names 32120 2413 32537 +11 1 +.names 32537 32538 +1 1 +.names 32538 32539 +0 1 +.names 7600 32540 +1 1 +.names 32540 32541 +0 1 +.names 32536 32542 +0 1 +.names 32534 32543 +0 1 +.names 56610 32544 +0 1 +.names 56574 32545 +0 1 +.names 1358 32546 +0 1 +.names 32549 32120 32547 +1- 1 +-1 1 +.names 32547 32548 +1 1 +.names 1359 32549 +0 1 +.names 32563 32564 32550 +1- 1 +-1 1 +.names 32550 32551 +1 1 +.names 32551 32552 +0 1 +.names 2413 32553 +1 1 +.names 32553 32554 +1 1 +.names 32554 32555 +0 1 +.names 32552 32555 32556 +1- 1 +-1 1 +.names 32582 32583 32557 +11 1 +.names 32557 32558 +1 1 +.names 32558 32559 +0 1 +.names 32578 32579 32560 +11 1 +.names 32560 32561 +1 1 +.names 32561 32562 +0 1 +.names 32369 32562 32563 +11 1 +.names 7580 32124 32564 +11 1 +.names 32567 32568 32565 +1- 1 +-1 1 +.names 32565 32566 +1 1 +.names 7621 56587 32567 +11 1 +.names 32548 32568 +0 1 +.names 32573 2413 32569 +1- 1 +-1 1 +.names 32569 32570 +1 1 +.names 32120 32571 +1 1 +.names 32571 32572 +0 1 +.names 7616 32572 32573 +1- 1 +-1 1 +.names 7621 32577 32574 +1- 1 +-1 1 +.names 32574 32575 +1 1 +.names 2413 32576 +1 1 +.names 32576 32577 +0 1 +.names 32570 32578 +0 1 +.names 32575 32579 +0 1 +.names 56623 7616 32580 +11 1 +.names 32580 32581 +1 1 +.names 32581 32582 +0 1 +.names 32566 32583 +0 1 +.names 32597 32598 32584 +1- 1 +-1 1 +.names 32584 32585 +1 1 +.names 32585 32586 +0 1 +.names 2413 32587 +1 1 +.names 32587 32588 +1 1 +.names 32588 32589 +0 1 +.names 32586 32589 32590 +1- 1 +-1 1 +.names 32619 32620 32591 +11 1 +.names 32591 32592 +1 1 +.names 32592 32593 +0 1 +.names 32608 32609 32594 +11 1 +.names 32594 32595 +1 1 +.names 32595 32596 +0 1 +.names 32207 32596 32597 +11 1 +.names 7582 32124 32598 +11 1 +.names 32603 2413 32599 +1- 1 +-1 1 +.names 32599 32600 +1 1 +.names 32272 32601 +1 1 +.names 32601 32602 +0 1 +.names 7620 32602 32603 +1- 1 +-1 1 +.names 7594 32607 32604 +1- 1 +-1 1 +.names 32604 32605 +1 1 +.names 2413 32606 +1 1 +.names 32606 32607 +0 1 +.names 32600 32608 +0 1 +.names 32605 32609 +0 1 +.names 32612 7608 32610 +1- 1 +-1 1 +.names 32610 32611 +1 1 +.names 56599 32612 +0 1 +.names 32615 32616 32613 +1- 1 +-1 1 +.names 32613 32614 +1 1 +.names 7591 1360 32615 +11 1 +.names 32611 32616 +0 1 +.names 7620 56563 32617 +11 1 +.names 32617 32618 +1 1 +.names 32618 32619 +0 1 +.names 32614 32620 +0 1 +.names 32627 32629 32621 +1- 1 +-1 1 +.names 32621 32622 +1 1 +.names 7599 32623 +0 1 +.names 32639 32640 32624 +11 1 +.names 32624 32625 +1 1 +.names 32625 32626 +0 1 +.names 32623 32626 32627 +11 1 +.names 56581 32628 +0 1 +.names 7599 32628 32629 +11 1 +.names 7611 2413 32630 +1- 1 +-1 1 +.names 32630 32631 +1 1 +.names 32636 32638 32632 +1- 1 +-1 1 +.names 32632 32633 +1 1 +.names 32272 2413 32634 +11 1 +.names 32634 32635 +1 1 +.names 32635 32636 +0 1 +.names 7608 32637 +1 1 +.names 32637 32638 +0 1 +.names 32633 32639 +0 1 +.names 32631 32640 +0 1 +.names 32655 32658 32641 +1- 1 +-1 1 +.names 32641 32642 +1 1 +.names 32622 32643 +0 1 +.names 32646 7608 32644 +1- 1 +-1 1 +.names 32644 32645 +1 1 +.names 56617 32646 +0 1 +.names 32645 32647 +0 1 +.names 32124 32125 32648 +1- 1 +-1 1 +.names 32648 32649 +1 1 +.names 32649 32650 +0 1 +.names 32647 32650 32651 +1- 1 +-1 1 +.names 32659 32272 32652 +1- 1 +-1 1 +.names 32652 32653 +1 1 +.names 32653 32654 +0 1 +.names 32651 32654 32655 +1- 1 +-1 1 +.names 2413 32656 +1 1 +.names 32656 32657 +1 1 +.names 32657 32658 +0 1 +.names 1361 32659 +0 1 +.names 32665 32666 32660 +1- 1 +-1 1 +.names 32660 32661 +1 1 +.names 32676 32677 32662 +11 1 +.names 32662 32663 +1 1 +.names 32663 32664 +0 1 +.names 32369 32664 32665 +11 1 +.names 7580 32124 32666 +11 1 +.names 32671 2413 32667 +1- 1 +-1 1 +.names 32667 32668 +1 1 +.names 32272 32669 +1 1 +.names 32669 32670 +0 1 +.names 7597 32670 32671 +1- 1 +-1 1 +.names 7613 32675 32672 +1- 1 +-1 1 +.names 32672 32673 +1 1 +.names 2413 32674 +1 1 +.names 32674 32675 +0 1 +.names 32668 32676 +0 1 +.names 32673 32677 +0 1 +.names 7600 32680 32678 +1- 1 +-1 1 +.names 32678 32679 +1 1 +.names 56570 32680 +0 1 +.names 32683 32229 32681 +1- 1 +-1 1 +.names 32681 32682 +1 1 +.names 56606 32683 +0 1 +.names 32690 32691 32684 +1- 1 +-1 1 +.names 32684 32685 +1 1 +.names 32679 32686 +0 1 +.names 32272 32700 32687 +1- 1 +-1 1 +.names 32687 32688 +1 1 +.names 32688 32689 +0 1 +.names 32686 32689 32690 +1- 1 +-1 1 +.names 32682 32691 +0 1 +.names 32661 32692 +0 1 +.names 32696 32699 32693 +11 1 +.names 32693 32694 +1 1 +.names 32694 32695 +0 1 +.names 32685 32696 +0 1 +.names 1783 32697 +1 1 +.names 32697 32698 +1 1 +.names 32698 32699 +0 1 +.names 1362 32700 +0 1 +.names 32714 32715 32701 +1- 1 +-1 1 +.names 32701 32702 +1 1 +.names 32702 32703 +0 1 +.names 2413 32704 +1 1 +.names 32704 32705 +1 1 +.names 32705 32706 +0 1 +.names 32703 32706 32707 +1- 1 +-1 1 +.names 32718 32721 32708 +11 1 +.names 32708 32709 +1 1 +.names 32709 32710 +0 1 +.names 32728 32729 32711 +11 1 +.names 32711 32712 +1 1 +.names 32712 32713 +0 1 +.names 32369 32713 32714 +11 1 +.names 7580 32124 32715 +11 1 +.names 32734 56565 32716 +11 1 +.names 32716 32717 +1 1 +.names 32717 32718 +0 1 +.names 32736 32737 32719 +1- 1 +-1 1 +.names 32719 32720 +1 1 +.names 32720 32721 +0 1 +.names 7594 32725 32722 +1- 1 +-1 1 +.names 32722 32723 +1 1 +.names 2413 32724 +1 1 +.names 32724 32725 +0 1 +.names 32740 2413 32726 +1- 1 +-1 1 +.names 32726 32727 +1 1 +.names 32727 32728 +0 1 +.names 32723 32729 +0 1 +.names 32732 7608 32730 +1- 1 +-1 1 +.names 32730 32731 +1 1 +.names 56601 32732 +0 1 +.names 32738 32733 +0 1 +.names 32733 32734 +1 1 +.names 32347 32735 +1 1 +.names 7592 1363 32736 +11 1 +.names 32731 32737 +0 1 +.names 32190 32738 +1 1 +.names 32735 32739 +0 1 +.names 32733 32739 32740 +1- 1 +-1 1 +.names 32743 32161 32741 +1- 1 +-1 1 +.names 32741 32742 +1 1 +.names 1364 32743 +0 1 +.names 32757 32758 32744 +1- 1 +-1 1 +.names 32744 32745 +1 1 +.names 32745 32746 +0 1 +.names 2413 32747 +1 1 +.names 32747 32748 +1 1 +.names 32748 32749 +0 1 +.names 32746 32749 32750 +1- 1 +-1 1 +.names 32761 32764 32751 +11 1 +.names 32751 32752 +1 1 +.names 32752 32753 +0 1 +.names 32769 32772 32754 +11 1 +.names 32754 32755 +1 1 +.names 32755 32756 +0 1 +.names 32207 32756 32757 +11 1 +.names 7582 32124 32758 +11 1 +.names 32774 32759 +0 1 +.names 32759 32760 +1 1 +.names 32760 32761 +0 1 +.names 32781 32782 32762 +1- 1 +-1 1 +.names 32762 32763 +1 1 +.names 32763 32764 +0 1 +.names 7621 32768 32765 +1- 1 +-1 1 +.names 32765 32766 +1 1 +.names 2413 32767 +1 1 +.names 32767 32768 +0 1 +.names 32766 32769 +0 1 +.names 32780 2413 32770 +1- 1 +-1 1 +.names 32770 32771 +1 1 +.names 32771 32772 +0 1 +.names 32775 32229 32773 +1- 1 +-1 1 +.names 32773 32774 +1 1 +.names 56604 32775 +0 1 +.names 32229 32776 +1 1 +.names 32776 32777 +0 1 +.names 32161 32778 +1 1 +.names 32778 32779 +0 1 +.names 32777 32779 32780 +1- 1 +-1 1 +.names 7621 56568 32781 +11 1 +.names 32742 32782 +0 1 +.names 32272 32785 32783 +1- 1 +-1 1 +.names 32783 32784 +1 1 +.names 1365 32785 +0 1 +.names 32791 32792 32786 +1- 1 +-1 1 +.names 32786 32787 +1 1 +.names 32802 32803 32788 +11 1 +.names 32788 32789 +1 1 +.names 32789 32790 +0 1 +.names 32246 32790 32791 +11 1 +.names 7618 32124 32792 +11 1 +.names 32797 2413 32793 +1- 1 +-1 1 +.names 32793 32794 +1 1 +.names 32272 32795 +1 1 +.names 32795 32796 +0 1 +.names 7597 32796 32797 +1- 1 +-1 1 +.names 7613 32801 32798 +1- 1 +-1 1 +.names 32798 32799 +1 1 +.names 2413 32800 +1 1 +.names 32800 32801 +0 1 +.names 32794 32802 +0 1 +.names 32799 32803 +0 1 +.names 32806 32229 32804 +1- 1 +-1 1 +.names 32804 32805 +1 1 +.names 56615 32806 +0 1 +.names 32813 32814 32807 +1- 1 +-1 1 +.names 32807 32808 +1 1 +.names 32784 32809 +0 1 +.names 7600 32823 32810 +1- 1 +-1 1 +.names 32810 32811 +1 1 +.names 32811 32812 +0 1 +.names 32809 32812 32813 +1- 1 +-1 1 +.names 32805 32814 +0 1 +.names 32787 32815 +0 1 +.names 32821 32822 32816 +11 1 +.names 32816 32817 +1 1 +.names 32817 32818 +0 1 +.names 1783 32819 +1 1 +.names 32819 32820 +1 1 +.names 32808 32821 +0 1 +.names 32820 32822 +0 1 +.names 56579 32823 +0 1 +.names 32837 32838 32824 +1- 1 +-1 1 +.names 32824 32825 +1 1 +.names 32825 32826 +0 1 +.names 2413 32827 +1 1 +.names 32827 32828 +1 1 +.names 32828 32829 +0 1 +.names 32826 32829 32830 +1- 1 +-1 1 +.names 32859 32851 32831 +11 1 +.names 32831 32832 +1 1 +.names 32832 32833 +0 1 +.names 32848 32849 32834 +11 1 +.names 32834 32835 +1 1 +.names 32835 32836 +0 1 +.names 32369 32836 32837 +11 1 +.names 7580 32124 32838 +11 1 +.names 32843 2413 32839 +1- 1 +-1 1 +.names 32839 32840 +1 1 +.names 32347 32841 +1 1 +.names 32841 32842 +0 1 +.names 7617 32842 32843 +1- 1 +-1 1 +.names 7622 32847 32844 +1- 1 +-1 1 +.names 32844 32845 +1 1 +.names 2413 32846 +1 1 +.names 32846 32847 +0 1 +.names 32840 32848 +0 1 +.names 32845 32849 +0 1 +.names 32852 32263 32850 +1- 1 +-1 1 +.names 32850 32851 +1 1 +.names 56622 32852 +0 1 +.names 32347 32855 32853 +1- 1 +-1 1 +.names 32853 32854 +1 1 +.names 1366 32855 +0 1 +.names 32190 32858 32856 +1- 1 +-1 1 +.names 32856 32857 +1 1 +.names 56586 32858 +0 1 +.names 32857 32854 32859 +11 1 +.names 32347 32862 32860 +1- 1 +-1 1 +.names 32860 32861 +1 1 +.names 1367 32862 +0 1 +.names 32876 32877 32863 +1- 1 +-1 1 +.names 32863 32864 +1 1 +.names 32864 32865 +0 1 +.names 2413 32866 +1 1 +.names 32866 32867 +1 1 +.names 32867 32868 +0 1 +.names 32865 32868 32869 +1- 1 +-1 1 +.names 32880 32882 32870 +11 1 +.names 32870 32871 +1 1 +.names 32871 32872 +0 1 +.names 32892 32893 32873 +11 1 +.names 32873 32874 +1 1 +.names 32874 32875 +0 1 +.names 32207 32875 32876 +11 1 +.names 7582 32124 32877 +11 1 +.names 32319 5787 32878 +1- 1 +-1 1 +.names 32878 32879 +1 1 +.names 32861 32879 32880 +11 1 +.names 32124 32263 32881 +1- 1 +-1 1 +.names 32881 32882 +1 1 +.names 32887 2413 32883 +1- 1 +-1 1 +.names 32883 32884 +1 1 +.names 32347 32885 +1 1 +.names 32885 32886 +0 1 +.names 7617 32886 32887 +1- 1 +-1 1 +.names 7620 32891 32888 +1- 1 +-1 1 +.names 32888 32889 +1 1 +.names 2413 32890 +1 1 +.names 32890 32891 +0 1 +.names 32884 32892 +0 1 +.names 32889 32893 +0 1 +.names 32907 32908 32894 +1- 1 +-1 1 +.names 32894 32895 +1 1 +.names 32895 32896 +0 1 +.names 2413 32897 +1 1 +.names 32897 32898 +1 1 +.names 32898 32899 +0 1 +.names 32896 32899 32900 +1- 1 +-1 1 +.names 32913 32915 32901 +11 1 +.names 32901 32902 +1 1 +.names 32902 32903 +0 1 +.names 32925 32926 32904 +11 1 +.names 32904 32905 +1 1 +.names 32905 32906 +0 1 +.names 32246 32906 32907 +11 1 +.names 7618 32124 32908 +11 1 +.names 32347 32929 32909 +1- 1 +-1 1 +.names 32909 32910 +1 1 +.names 32319 32928 32911 +1- 1 +-1 1 +.names 32911 32912 +1 1 +.names 32910 32912 32913 +11 1 +.names 32927 32431 32914 +1- 1 +-1 1 +.names 32914 32915 +1 1 +.names 32920 2413 32916 +1- 1 +-1 1 +.names 32916 32917 +1 1 +.names 32347 32918 +1 1 +.names 32918 32919 +0 1 +.names 7616 32919 32920 +1- 1 +-1 1 +.names 7620 32924 32921 +1- 1 +-1 1 +.names 32921 32922 +1 1 +.names 2413 32923 +1 1 +.names 32923 32924 +0 1 +.names 32917 32925 +0 1 +.names 32922 32926 +0 1 +.names 56620 32927 +0 1 +.names 56584 32928 +0 1 +.names 1368 32929 +0 1 +.names 32347 32932 32930 +1- 1 +-1 1 +.names 32930 32931 +1 1 +.names 1369 32932 +0 1 +.names 32938 32939 32933 +1- 1 +-1 1 +.names 32933 32934 +1 1 +.names 32949 32950 32935 +11 1 +.names 32935 32936 +1 1 +.names 32936 32937 +0 1 +.names 32246 32937 32938 +11 1 +.names 7618 32124 32939 +11 1 +.names 32944 2413 32940 +1- 1 +-1 1 +.names 32940 32941 +1 1 +.names 32347 32942 +1 1 +.names 32942 32943 +0 1 +.names 7597 32943 32944 +1- 1 +-1 1 +.names 7620 32948 32945 +1- 1 +-1 1 +.names 32945 32946 +1 1 +.names 2413 32947 +1 1 +.names 32947 32948 +0 1 +.names 32941 32949 +0 1 +.names 32946 32950 +0 1 +.names 32953 32229 32951 +1- 1 +-1 1 +.names 32951 32952 +1 1 +.names 56612 32953 +0 1 +.names 32960 32961 32954 +1- 1 +-1 1 +.names 32954 32955 +1 1 +.names 32931 32956 +0 1 +.names 32319 32970 32957 +1- 1 +-1 1 +.names 32957 32958 +1 1 +.names 32958 32959 +0 1 +.names 32956 32959 32960 +1- 1 +-1 1 +.names 32952 32961 +0 1 +.names 32934 32962 +0 1 +.names 32968 32969 32963 +11 1 +.names 32963 32964 +1 1 +.names 32964 32965 +0 1 +.names 1783 32966 +1 1 +.names 32966 32967 +1 1 +.names 32955 32968 +0 1 +.names 32967 32969 +0 1 +.names 56576 32970 +0 1 +.names 32984 32985 32971 +1- 1 +-1 1 +.names 32971 32972 +1 1 +.names 32972 32973 +0 1 +.names 2413 32974 +1 1 +.names 32974 32975 +1 1 +.names 32975 32976 +0 1 +.names 32973 32976 32977 +1- 1 +-1 1 +.names 32990 32992 32978 +11 1 +.names 32978 32979 +1 1 +.names 32979 32980 +0 1 +.names 33002 33003 32981 +11 1 +.names 32981 32982 +1 1 +.names 32982 32983 +0 1 +.names 32246 32983 32984 +11 1 +.names 7618 32124 32985 +11 1 +.names 7600 33004 32986 +1- 1 +-1 1 +.names 32986 32987 +1 1 +.names 32120 33006 32988 +1- 1 +-1 1 +.names 32988 32989 +1 1 +.names 32987 32989 32990 +11 1 +.names 33005 32431 32991 +1- 1 +-1 1 +.names 32991 32992 +1 1 +.names 32997 2413 32993 +1- 1 +-1 1 +.names 32993 32994 +1 1 +.names 32120 32995 +1 1 +.names 32995 32996 +0 1 +.names 7616 32996 32997 +1- 1 +-1 1 +.names 1783 33001 32998 +1- 1 +-1 1 +.names 32998 32999 +1 1 +.names 7600 33000 +1 1 +.names 33000 33001 +0 1 +.names 32994 33002 +0 1 +.names 32999 33003 +0 1 +.names 56577 33004 +0 1 +.names 56613 33005 +0 1 +.names 1370 33006 +0 1 +.names 33009 32120 33007 +1- 1 +-1 1 +.names 33007 33008 +1 1 +.names 1371 33009 +0 1 +.names 33023 33024 33010 +1- 1 +-1 1 +.names 33010 33011 +1 1 +.names 33011 33012 +0 1 +.names 2413 33013 +1 1 +.names 33013 33014 +1 1 +.names 33014 33015 +0 1 +.names 33012 33015 33016 +1- 1 +-1 1 +.names 33027 33030 33017 +11 1 +.names 33017 33018 +1 1 +.names 33018 33019 +0 1 +.names 33040 33041 33020 +11 1 +.names 33020 33021 +1 1 +.names 33021 33022 +0 1 +.names 32207 33022 33023 +11 1 +.names 7582 32124 33024 +11 1 +.names 33045 33025 +0 1 +.names 33025 33026 +1 1 +.names 33026 33027 +0 1 +.names 33042 33043 33028 +1- 1 +-1 1 +.names 33028 33029 +1 1 +.names 33029 33030 +0 1 +.names 33035 2413 33031 +1- 1 +-1 1 +.names 33031 33032 +1 1 +.names 32120 33033 +1 1 +.names 33033 33034 +0 1 +.names 7617 33034 33035 +1- 1 +-1 1 +.names 7613 33039 33036 +1- 1 +-1 1 +.names 33036 33037 +1 1 +.names 2413 33038 +1 1 +.names 33038 33039 +0 1 +.names 33032 33040 +0 1 +.names 33037 33041 +0 1 +.names 7613 56591 33042 +11 1 +.names 33008 33043 +0 1 +.names 33046 32263 33044 +1- 1 +-1 1 +.names 33044 33045 +1 1 +.names 56627 33046 +0 1 +.names 32347 33049 33047 +1- 1 +-1 1 +.names 33047 33048 +1 1 +.names 1372 33049 +0 1 +.names 33055 33056 33050 +1- 1 +-1 1 +.names 33050 33051 +1 1 +.names 33066 33067 33052 +11 1 +.names 33052 33053 +1 1 +.names 33053 33054 +0 1 +.names 32207 33054 33055 +11 1 +.names 7582 32124 33056 +11 1 +.names 33061 2413 33057 +1- 1 +-1 1 +.names 33057 33058 +1 1 +.names 32347 33059 +1 1 +.names 33059 33060 +0 1 +.names 7597 33060 33061 +1- 1 +-1 1 +.names 7620 33065 33062 +1- 1 +-1 1 +.names 33062 33063 +1 1 +.names 2413 33064 +1 1 +.names 33064 33065 +0 1 +.names 33058 33066 +0 1 +.names 33063 33067 +0 1 +.names 33070 32229 33068 +1- 1 +-1 1 +.names 33068 33069 +1 1 +.names 56611 33070 +0 1 +.names 33077 33078 33071 +1- 1 +-1 1 +.names 33071 33072 +1 1 +.names 33048 33073 +0 1 +.names 32319 33087 33074 +1- 1 +-1 1 +.names 33074 33075 +1 1 +.names 33075 33076 +0 1 +.names 33073 33076 33077 +1- 1 +-1 1 +.names 33069 33078 +0 1 +.names 33051 33079 +0 1 +.names 33085 33086 33080 +11 1 +.names 33080 33081 +1 1 +.names 33081 33082 +0 1 +.names 1783 33083 +1 1 +.names 33083 33084 +1 1 +.names 33072 33085 +0 1 +.names 33084 33086 +0 1 +.names 56575 33087 +0 1 +.names 33101 33102 33088 +1- 1 +-1 1 +.names 33088 33089 +1 1 +.names 33089 33090 +0 1 +.names 2413 33091 +1 1 +.names 33091 33092 +1 1 +.names 33092 33093 +0 1 +.names 33090 33093 33094 +1- 1 +-1 1 +.names 33105 33108 33095 +11 1 +.names 33095 33096 +1 1 +.names 33096 33097 +0 1 +.names 33115 33116 33098 +11 1 +.names 33098 33099 +1 1 +.names 33099 33100 +0 1 +.names 32207 33100 33101 +11 1 +.names 7582 32124 33102 +11 1 +.names 7621 56589 33103 +11 1 +.names 33103 33104 +1 1 +.names 33104 33105 +0 1 +.names 33121 33122 33106 +1- 1 +-1 1 +.names 33106 33107 +1 1 +.names 33107 33108 +0 1 +.names 7594 33112 33109 +1- 1 +-1 1 +.names 33109 33110 +1 1 +.names 2413 33111 +1 1 +.names 33111 33112 +0 1 +.names 33126 2413 33113 +1- 1 +-1 1 +.names 33113 33114 +1 1 +.names 33114 33115 +0 1 +.names 33110 33116 +0 1 +.names 33119 7608 33117 +1- 1 +-1 1 +.names 33117 33118 +1 1 +.names 56625 33119 +0 1 +.names 32161 33120 +1 1 +.names 7612 1373 33121 +11 1 +.names 33118 33122 +0 1 +.names 32274 33123 +1 1 +.names 33123 33124 +0 1 +.names 33120 33125 +0 1 +.names 33124 33125 33126 +1- 1 +-1 1 +.names 32347 33129 33127 +1- 1 +-1 1 +.names 33127 33128 +1 1 +.names 1374 33129 +0 1 +.names 33143 33144 33130 +1- 1 +-1 1 +.names 33130 33131 +1 1 +.names 33131 33132 +0 1 +.names 2413 33133 +1 1 +.names 33133 33134 +1 1 +.names 33134 33135 +0 1 +.names 33132 33135 33136 +1- 1 +-1 1 +.names 33162 33157 33137 +11 1 +.names 33137 33138 +1 1 +.names 33138 33139 +0 1 +.names 33154 33155 33140 +11 1 +.names 33140 33141 +1 1 +.names 33141 33142 +0 1 +.names 32369 33142 33143 +11 1 +.names 7580 32124 33144 +11 1 +.names 33149 2413 33145 +1- 1 +-1 1 +.names 33145 33146 +1 1 +.names 32347 33147 +1 1 +.names 33147 33148 +0 1 +.names 7617 33148 33149 +1- 1 +-1 1 +.names 7622 33153 33150 +1- 1 +-1 1 +.names 33150 33151 +1 1 +.names 2413 33152 +1 1 +.names 33152 33153 +0 1 +.names 33146 33154 +0 1 +.names 33151 33155 +0 1 +.names 33158 32263 33156 +1- 1 +-1 1 +.names 33156 33157 +1 1 +.names 56626 33158 +0 1 +.names 32190 33161 33159 +1- 1 +-1 1 +.names 33159 33160 +1 1 +.names 56590 33161 +0 1 +.names 33160 33128 33162 +11 1 +.names 32272 33165 33163 +1- 1 +-1 1 +.names 33163 33164 +1 1 +.names 1375 33165 +0 1 +.names 33171 33172 33166 +1- 1 +-1 1 +.names 33166 33167 +1 1 +.names 33179 33180 33168 +11 1 +.names 33168 33169 +1 1 +.names 33169 33170 +0 1 +.names 32246 33170 33171 +11 1 +.names 7618 32124 33172 +11 1 +.names 7621 33176 33173 +1- 1 +-1 1 +.names 33173 33174 +1 1 +.names 2413 33175 +1 1 +.names 33175 33176 +0 1 +.names 33186 2413 33177 +1- 1 +-1 1 +.names 33177 33178 +1 1 +.names 33178 33179 +0 1 +.names 33174 33180 +0 1 +.names 33183 32229 33181 +1- 1 +-1 1 +.names 33181 33182 +1 1 +.names 56602 33183 +0 1 +.names 32272 33184 +1 1 +.names 33184 33185 +0 1 +.names 7597 33185 33186 +1- 1 +-1 1 +.names 33193 33194 33187 +1- 1 +-1 1 +.names 33187 33188 +1 1 +.names 33164 33189 +0 1 +.names 32274 22359 33190 +1- 1 +-1 1 +.names 33190 33191 +1 1 +.names 33191 33192 +0 1 +.names 33189 33192 33193 +1- 1 +-1 1 +.names 33182 33194 +0 1 +.names 33167 33195 +0 1 +.names 33201 33202 33196 +11 1 +.names 33196 33197 +1 1 +.names 33197 33198 +0 1 +.names 1783 33199 +1 1 +.names 33199 33200 +1 1 +.names 33188 33201 +0 1 +.names 33200 33202 +0 1 +.names 33216 33217 33203 +1- 1 +-1 1 +.names 33203 33204 +1 1 +.names 33204 33205 +0 1 +.names 33239 7608 33206 +1- 1 +-1 1 +.names 33206 33207 +1 1 +.names 33207 33208 +0 1 +.names 33205 33208 33209 +1- 1 +-1 1 +.names 33220 33223 33210 +11 1 +.names 33210 33211 +1 1 +.names 33211 33212 +0 1 +.names 33237 33238 33213 +11 1 +.names 33213 33214 +1 1 +.names 33214 33215 +0 1 +.names 32623 33215 33216 +11 1 +.names 7599 22376 33217 +11 1 +.names 56630 7611 33218 +11 1 +.names 33218 33219 +1 1 +.names 33219 33220 +0 1 +.names 33224 33227 33221 +1- 1 +-1 1 +.names 33221 33222 +1 1 +.names 33222 33223 +0 1 +.names 7591 1376 33224 +11 1 +.names 2413 33225 +1 1 +.names 33225 33226 +1 1 +.names 33226 33227 +0 1 +.names 33232 2413 33228 +1- 1 +-1 1 +.names 33228 33229 +1 1 +.names 2413 33230 +1 1 +.names 33230 33231 +0 1 +.names 7611 33231 33232 +1- 1 +-1 1 +.names 7594 33236 33233 +1- 1 +-1 1 +.names 33233 33234 +1 1 +.names 32272 33235 +1 1 +.names 33235 33236 +0 1 +.names 33229 33237 +0 1 +.names 33234 33238 +0 1 +.names 56603 33239 +0 1 +.names 33253 33254 33240 +1- 1 +-1 1 +.names 33240 33241 +1 1 +.names 33241 33242 +0 1 +.names 2413 33243 +1 1 +.names 33243 33244 +1 1 +.names 33244 33245 +0 1 +.names 33242 33245 33246 +1- 1 +-1 1 +.names 33275 33267 33247 +11 1 +.names 33247 33248 +1 1 +.names 33248 33249 +0 1 +.names 33264 33265 33250 +11 1 +.names 33250 33251 +1 1 +.names 33251 33252 +0 1 +.names 32246 33252 33253 +11 1 +.names 7618 32124 33254 +11 1 +.names 33259 2413 33255 +1- 1 +-1 1 +.names 33255 33256 +1 1 +.names 32161 33257 +1 1 +.names 33257 33258 +0 1 +.names 7617 33258 33259 +1- 1 +-1 1 +.names 7622 33263 33260 +1- 1 +-1 1 +.names 33260 33261 +1 1 +.names 2413 33262 +1 1 +.names 33262 33263 +0 1 +.names 33256 33264 +0 1 +.names 33261 33265 +0 1 +.names 33268 32263 33266 +1- 1 +-1 1 +.names 33266 33267 +1 1 +.names 56614 33268 +0 1 +.names 32161 33271 33269 +1- 1 +-1 1 +.names 33269 33270 +1 1 +.names 1377 33271 +0 1 +.names 32190 33274 33272 +1- 1 +-1 1 +.names 33272 33273 +1 1 +.names 56578 33274 +0 1 +.names 33273 33270 33275 +11 1 +.names 32120 33278 33276 +1- 1 +-1 1 +.names 33276 33277 +1 1 +.names 1378 33278 +0 1 +.names 33281 7608 33279 +1- 1 +-1 1 +.names 33279 33280 +1 1 +.names 56619 33281 +0 1 +.names 33286 2413 33282 +1- 1 +-1 1 +.names 33282 33283 +1 1 +.names 32120 33284 +1 1 +.names 33284 33285 +0 1 +.names 7594 33285 33286 +1- 1 +-1 1 +.names 7622 33290 33287 +1- 1 +-1 1 +.names 33287 33288 +1 1 +.names 2413 33289 +1 1 +.names 33289 33290 +0 1 +.names 33296 33297 33291 +1- 1 +-1 1 +.names 33291 33292 +1 1 +.names 33298 33299 33293 +11 1 +.names 33293 33294 +1 1 +.names 33294 33295 +0 1 +.names 32246 33295 33296 +11 1 +.names 7618 32124 33297 +11 1 +.names 33283 33298 +0 1 +.names 33288 33299 +0 1 +.names 33306 33307 33300 +1- 1 +-1 1 +.names 33300 33301 +1 1 +.names 32190 33316 33302 +1- 1 +-1 1 +.names 33302 33303 +1 1 +.names 33303 33304 +0 1 +.names 33277 33305 +0 1 +.names 33304 33305 33306 +1- 1 +-1 1 +.names 33280 33307 +0 1 +.names 33310 33313 33308 +11 1 +.names 33308 33309 +1 1 +.names 33301 33310 +0 1 +.names 1783 33311 +1 1 +.names 33311 33312 +1 1 +.names 33312 33313 +0 1 +.names 33292 33314 +0 1 +.names 33309 33315 +0 1 +.names 56583 33316 +0 1 +.names 33330 33331 33317 +1- 1 +-1 1 +.names 33317 33318 +1 1 +.names 33318 33319 +0 1 +.names 2413 33320 +1 1 +.names 33320 33321 +1 1 +.names 33321 33322 +0 1 +.names 33319 33322 33323 +1- 1 +-1 1 +.names 33334 33337 33324 +11 1 +.names 33324 33325 +1 1 +.names 33325 33326 +0 1 +.names 33344 33345 33327 +11 1 +.names 33327 33328 +1 1 +.names 33328 33329 +0 1 +.names 32246 33329 33330 +11 1 +.names 7618 32124 33331 +11 1 +.names 7620 56592 33332 +11 1 +.names 33332 33333 +1 1 +.names 33333 33334 +0 1 +.names 33352 33353 33335 +1- 1 +-1 1 +.names 33335 33336 +1 1 +.names 33336 33337 +0 1 +.names 7617 33341 33338 +1- 1 +-1 1 +.names 33338 33339 +1 1 +.names 2413 33340 +1 1 +.names 33340 33341 +0 1 +.names 33351 2413 33342 +1- 1 +-1 1 +.names 33342 33343 +1 1 +.names 33343 33344 +0 1 +.names 33339 33345 +0 1 +.names 33348 32263 33346 +1- 1 +-1 1 +.names 33346 33347 +1 1 +.names 56628 33348 +0 1 +.names 32161 33349 +1 1 +.names 33349 33350 +0 1 +.names 7620 33350 33351 +1- 1 +-1 1 +.names 7612 1379 33352 +11 1 +.names 33347 33353 +0 1 +.names 33360 33361 33354 +1- 1 +-1 1 +.names 33354 33355 +1 1 +.names 7636 33356 +0 1 +.names 33362 33364 33357 +11 1 +.names 33357 33358 +1 1 +.names 33358 33359 +0 1 +.names 33356 33359 33360 +11 1 +.names 7636 32235 33361 +11 1 +.names 7637 33362 +0 1 +.names 2413 33363 +1 1 +.names 33363 33364 +0 1 +.names 32228 33365 +1 1 +.names 33365 33366 +0 1 +.names 33362 33367 +1 1 +.names 33367 33368 +0 1 +.names 33366 33368 33369 +11 1 +.names 33355 33370 +0 1 +.names 33377 33378 33371 +1- 1 +-1 1 +.names 33371 33372 +1 1 +.names 7624 33373 +0 1 +.names 33362 33380 33374 +11 1 +.names 33374 33375 +1 1 +.names 33375 33376 +0 1 +.names 33373 33376 33377 +11 1 +.names 7624 32166 33378 +11 1 +.names 2413 33379 +1 1 +.names 33379 33380 +0 1 +.names 32184 33381 +1 1 +.names 33381 33382 +0 1 +.names 33362 33383 +1 1 +.names 33383 33384 +0 1 +.names 33382 33384 33385 +11 1 +.names 33372 33386 +0 1 +.names 7631 33387 +0 1 +.names 33387 33388 +1 1 +.names 33387 33392 33389 +11 1 +.names 33389 33390 +1 1 +.names 2413 33391 +1 1 +.names 33391 33392 +0 1 +.names 33396 33397 33393 +1- 1 +-1 1 +.names 33393 33394 +1 1 +.names 33390 33395 +0 1 +.names 33373 33395 33396 +11 1 +.names 7624 32121 33397 +11 1 +.names 32156 33398 +1 1 +.names 33388 33399 +0 1 +.names 33398 33400 +0 1 +.names 33399 33400 33401 +11 1 +.names 33394 33402 +0 1 +.names 33387 33403 +1 1 +.names 33387 33407 33404 +11 1 +.names 33404 33405 +1 1 +.names 2413 33406 +1 1 +.names 33406 33407 +0 1 +.names 33411 33413 33408 +1- 1 +-1 1 +.names 33408 33409 +1 1 +.names 33405 33410 +0 1 +.names 33356 33410 33411 +11 1 +.names 1351 33412 +0 1 +.names 7636 33412 33413 +11 1 +.names 33403 33414 +0 1 +.names 32262 33415 +1 1 +.names 33415 33416 +0 1 +.names 33414 33416 33417 +11 1 +.names 33409 33418 +0 1 +.names 33424 33425 33419 +1- 1 +-1 1 +.names 33419 33420 +1 1 +.names 33426 33428 33421 +11 1 +.names 33421 33422 +1 1 +.names 33422 33423 +0 1 +.names 33356 33423 33424 +11 1 +.names 7636 32281 33425 +11 1 +.names 7629 33426 +0 1 +.names 2413 33427 +1 1 +.names 33427 33428 +0 1 +.names 32284 33429 +1 1 +.names 33429 33430 +0 1 +.names 33426 33431 +1 1 +.names 33431 33432 +0 1 +.names 33430 33432 33433 +11 1 +.names 33420 33434 +0 1 +.names 33440 33441 33435 +1- 1 +-1 1 +.names 33435 33436 +1 1 +.names 33442 33444 33437 +11 1 +.names 33437 33438 +1 1 +.names 33438 33439 +0 1 +.names 33356 33439 33440 +11 1 +.names 7636 32352 33441 +11 1 +.names 7632 33442 +0 1 +.names 2413 33443 +1 1 +.names 33443 33444 +0 1 +.names 32336 33445 +1 1 +.names 33445 33446 +0 1 +.names 33442 33447 +1 1 +.names 33447 33448 +0 1 +.names 33446 33448 33449 +11 1 +.names 33436 33450 +0 1 +.names 33457 33459 33451 +1- 1 +-1 1 +.names 33451 33452 +1 1 +.names 7635 33453 +0 1 +.names 33426 33461 33454 +11 1 +.names 33454 33455 +1 1 +.names 33455 33456 +0 1 +.names 33453 33456 33457 +11 1 +.names 1354 33458 +0 1 +.names 7635 33458 33459 +11 1 +.names 2413 33460 +1 1 +.names 33460 33461 +0 1 +.names 56629 33462 +0 1 +.names 33462 33463 +1 1 +.names 33463 33464 +0 1 +.names 33426 33465 +1 1 +.names 33465 33466 +0 1 +.names 33464 33466 33467 +11 1 +.names 33452 33468 +0 1 +.names 33474 33475 33469 +1- 1 +-1 1 +.names 33469 33470 +1 1 +.names 33442 33477 33471 +11 1 +.names 33471 33472 +1 1 +.names 33472 33473 +0 1 +.names 33373 33473 33474 +11 1 +.names 7624 32432 33475 +11 1 +.names 2413 33476 +1 1 +.names 33476 33477 +0 1 +.names 32430 33478 +1 1 +.names 33478 33479 +0 1 +.names 33442 33480 +1 1 +.names 33480 33481 +0 1 +.names 33479 33481 33482 +11 1 +.names 33470 33483 +0 1 +.names 33489 33491 33484 +1- 1 +-1 1 +.names 33484 33485 +1 1 +.names 33426 33493 33486 +11 1 +.names 33486 33487 +1 1 +.names 33487 33488 +0 1 +.names 33356 33488 33489 +11 1 +.names 1360 33490 +0 1 +.names 7636 33490 33491 +11 1 +.names 2413 33492 +1 1 +.names 33492 33493 +0 1 +.names 32612 33494 +1 1 +.names 33494 33495 +0 1 +.names 33426 33496 +1 1 +.names 33496 33497 +0 1 +.names 33495 33497 33498 +11 1 +.names 33485 33499 +0 1 +.names 33387 33500 +1 1 +.names 33387 33504 33501 +11 1 +.names 33501 33502 +1 1 +.names 2413 33503 +1 1 +.names 33503 33504 +0 1 +.names 33508 33509 33505 +1- 1 +-1 1 +.names 33505 33506 +1 1 +.names 33502 33507 +0 1 +.names 33453 33507 33508 +11 1 +.names 7635 32473 33509 +11 1 +.names 32451 33510 +1 1 +.names 33500 33511 +0 1 +.names 33510 33512 +0 1 +.names 33511 33512 33513 +11 1 +.names 33506 33514 +0 1 +.names 33387 33515 +1 1 +.names 33387 33519 33516 +11 1 +.names 33516 33517 +1 1 +.names 2413 33518 +1 1 +.names 33518 33519 +0 1 +.names 33523 33524 33520 +1- 1 +-1 1 +.names 33520 33521 +1 1 +.names 33517 33522 +0 1 +.names 33373 33522 33523 +11 1 +.names 7624 32506 33524 +11 1 +.names 32503 33525 +1 1 +.names 33515 33526 +0 1 +.names 33525 33527 +0 1 +.names 33526 33527 33528 +11 1 +.names 33521 33529 +0 1 +.names 33535 33536 33530 +1- 1 +-1 1 +.names 33530 33531 +1 1 +.names 33426 33538 33532 +11 1 +.names 33532 33533 +1 1 +.names 33533 33534 +0 1 +.names 33356 33534 33535 +11 1 +.names 7636 32546 33536 +11 1 +.names 2413 33537 +1 1 +.names 33537 33538 +0 1 +.names 32544 33539 +1 1 +.names 33539 33540 +0 1 +.names 33426 33541 +1 1 +.names 33541 33542 +0 1 +.names 33540 33542 33543 +11 1 +.names 33531 33544 +0 1 +.names 33550 33551 33545 +1- 1 +-1 1 +.names 33545 33546 +1 1 +.names 33426 33553 33547 +11 1 +.names 33547 33548 +1 1 +.names 33548 33549 +0 1 +.names 33373 33549 33550 +11 1 +.names 7624 32549 33551 +11 1 +.names 2413 33552 +1 1 +.names 33552 33553 +0 1 +.names 56623 33554 +0 1 +.names 33554 33555 +1 1 +.names 33555 33556 +0 1 +.names 33426 33557 +1 1 +.names 33557 33558 +0 1 +.names 33556 33558 33559 +11 1 +.names 33546 33560 +0 1 +.names 33566 33567 33561 +1- 1 +-1 1 +.names 33561 33562 +1 1 +.names 33426 33569 33563 +11 1 +.names 33563 33564 +1 1 +.names 33564 33565 +0 1 +.names 33373 33565 33566 +11 1 +.names 7624 32700 33567 +11 1 +.names 2413 33568 +1 1 +.names 33568 33569 +0 1 +.names 32683 33570 +1 1 +.names 33570 33571 +0 1 +.names 33426 33572 +1 1 +.names 33572 33573 +0 1 +.names 33571 33573 33574 +11 1 +.names 33562 33575 +0 1 +.names 33581 33582 33576 +1- 1 +-1 1 +.names 33576 33577 +1 1 +.names 33442 33584 33578 +11 1 +.names 33578 33579 +1 1 +.names 33579 33580 +0 1 +.names 33373 33580 33581 +11 1 +.names 7624 32659 33582 +11 1 +.names 2413 33583 +1 1 +.names 33583 33584 +0 1 +.names 32646 33585 +1 1 +.names 33585 33586 +0 1 +.names 33442 33587 +1 1 +.names 33587 33588 +0 1 +.names 33586 33588 33589 +11 1 +.names 33577 33590 +0 1 +.names 33596 33597 33591 +1- 1 +-1 1 +.names 33591 33592 +1 1 +.names 33362 33599 33593 +11 1 +.names 33593 33594 +1 1 +.names 33594 33595 +0 1 +.names 33453 33595 33596 +11 1 +.names 7635 32785 33597 +11 1 +.names 2413 33598 +1 1 +.names 33598 33599 +0 1 +.names 32806 33600 +1 1 +.names 33600 33601 +0 1 +.names 33362 33602 +1 1 +.names 33602 33603 +0 1 +.names 33601 33603 33604 +11 1 +.names 33592 33605 +0 1 +.names 33611 33612 33606 +1- 1 +-1 1 +.names 33606 33607 +1 1 +.names 33426 33614 33608 +11 1 +.names 33608 33609 +1 1 +.names 33609 33610 +0 1 +.names 33453 33610 33611 +11 1 +.names 7635 32855 33612 +11 1 +.names 2413 33613 +1 1 +.names 33613 33614 +0 1 +.names 33426 33615 +1 1 +.names 33615 33616 +0 1 +.names 32852 33617 +1 1 +.names 33617 33618 +0 1 +.names 33616 33618 33619 +11 1 +.names 33607 33620 +0 1 +.names 33387 33621 +1 1 +.names 33387 33625 33622 +11 1 +.names 33622 33623 +1 1 +.names 2413 33624 +1 1 +.names 33624 33625 +0 1 +.names 33629 33630 33626 +1- 1 +-1 1 +.names 33626 33627 +1 1 +.names 33623 33628 +0 1 +.names 33356 33628 33629 +11 1 +.names 7636 32862 33630 +11 1 +.names 32124 33631 +1 1 +.names 33621 33632 +0 1 +.names 33631 33633 +0 1 +.names 33632 33633 33634 +11 1 +.names 33627 33635 +0 1 +.names 33641 33643 33636 +1- 1 +-1 1 +.names 33636 33637 +1 1 +.names 33387 33645 33638 +11 1 +.names 33638 33639 +1 1 +.names 33639 33640 +0 1 +.names 33356 33640 33641 +11 1 +.names 1363 33642 +0 1 +.names 7636 33642 33643 +11 1 +.names 2413 33644 +1 1 +.names 33644 33645 +0 1 +.names 32732 33646 +1 1 +.names 33646 33647 +0 1 +.names 33387 33648 +1 1 +.names 33648 33649 +0 1 +.names 33647 33649 33650 +11 1 +.names 33637 33651 +0 1 +.names 33657 33658 33652 +1- 1 +-1 1 +.names 33652 33653 +1 1 +.names 33442 33660 33654 +11 1 +.names 33654 33655 +1 1 +.names 33655 33656 +0 1 +.names 33453 33656 33657 +11 1 +.names 7635 32743 33658 +11 1 +.names 2413 33659 +1 1 +.names 33659 33660 +0 1 +.names 32775 33661 +1 1 +.names 33661 33662 +0 1 +.names 33442 33663 +1 1 +.names 33663 33664 +0 1 +.names 33662 33664 33665 +11 1 +.names 33653 33666 +0 1 +.names 33672 33673 33667 +1- 1 +-1 1 +.names 33667 33668 +1 1 +.names 33442 33675 33669 +11 1 +.names 33669 33670 +1 1 +.names 33670 33671 +0 1 +.names 33453 33671 33672 +11 1 +.names 7635 32929 33673 +11 1 +.names 2413 33674 +1 1 +.names 33674 33675 +0 1 +.names 32927 33676 +1 1 +.names 33676 33677 +0 1 +.names 33442 33678 +1 1 +.names 33678 33679 +0 1 +.names 33677 33679 33680 +11 1 +.names 33668 33681 +0 1 +.names 33687 33688 33682 +1- 1 +-1 1 +.names 33682 33683 +1 1 +.names 33442 33690 33684 +11 1 +.names 33684 33685 +1 1 +.names 33685 33686 +0 1 +.names 33356 33686 33687 +11 1 +.names 7636 32932 33688 +11 1 +.names 2413 33689 +1 1 +.names 33689 33690 +0 1 +.names 32953 33691 +1 1 +.names 33691 33692 +0 1 +.names 33442 33693 +1 1 +.names 33693 33694 +0 1 +.names 33692 33694 33695 +11 1 +.names 33683 33696 +0 1 +.names 33702 33703 33697 +1- 1 +-1 1 +.names 33697 33698 +1 1 +.names 33387 33705 33699 +11 1 +.names 33699 33700 +1 1 +.names 33700 33701 +0 1 +.names 33373 33701 33702 +11 1 +.names 7624 33006 33703 +11 1 +.names 2413 33704 +1 1 +.names 33704 33705 +0 1 +.names 33387 33706 +1 1 +.names 33706 33707 +0 1 +.names 33005 33708 +1 1 +.names 33708 33709 +0 1 +.names 33707 33709 33710 +11 1 +.names 33698 33711 +0 1 +.names 33387 33712 +1 1 +.names 33387 33716 33713 +11 1 +.names 33713 33714 +1 1 +.names 2413 33715 +1 1 +.names 33715 33716 +0 1 +.names 33720 33721 33717 +1- 1 +-1 1 +.names 33717 33718 +1 1 +.names 33714 33719 +0 1 +.names 33453 33719 33720 +11 1 +.names 7635 33009 33721 +11 1 +.names 33046 33722 +1 1 +.names 33712 33723 +0 1 +.names 33722 33724 +0 1 +.names 33723 33724 33725 +11 1 +.names 33718 33726 +0 1 +.names 33732 33733 33727 +1- 1 +-1 1 +.names 33727 33728 +1 1 +.names 33426 33735 33729 +11 1 +.names 33729 33730 +1 1 +.names 33730 33731 +0 1 +.names 33453 33731 33732 +11 1 +.names 7635 33049 33733 +11 1 +.names 2413 33734 +1 1 +.names 33734 33735 +0 1 +.names 33070 33736 +1 1 +.names 33736 33737 +0 1 +.names 33426 33738 +1 1 +.names 33738 33739 +0 1 +.names 33737 33739 33740 +11 1 +.names 33728 33741 +0 1 +.names 33747 33749 33742 +1- 1 +-1 1 +.names 33742 33743 +1 1 +.names 33442 33751 33744 +11 1 +.names 33744 33745 +1 1 +.names 33745 33746 +0 1 +.names 33453 33746 33747 +11 1 +.names 1373 33748 +0 1 +.names 7635 33748 33749 +11 1 +.names 2413 33750 +1 1 +.names 33750 33751 +0 1 +.names 33119 33752 +1 1 +.names 33752 33753 +0 1 +.names 33442 33754 +1 1 +.names 33754 33755 +0 1 +.names 33753 33755 33756 +11 1 +.names 33743 33757 +0 1 +.names 33387 33758 +1 1 +.names 33387 33762 33759 +11 1 +.names 33759 33760 +1 1 +.names 2413 33761 +1 1 +.names 33761 33762 +0 1 +.names 33766 33767 33763 +1- 1 +-1 1 +.names 33763 33764 +1 1 +.names 33760 33765 +0 1 +.names 33356 33765 33766 +11 1 +.names 7636 33129 33767 +11 1 +.names 33158 33768 +1 1 +.names 33758 33769 +0 1 +.names 33768 33770 +0 1 +.names 33769 33770 33771 +11 1 +.names 33764 33772 +0 1 +.names 33778 33779 33773 +1- 1 +-1 1 +.names 33773 33774 +1 1 +.names 33442 33781 33775 +11 1 +.names 33775 33776 +1 1 +.names 33776 33777 +0 1 +.names 33453 33777 33778 +11 1 +.names 7635 33165 33779 +11 1 +.names 2413 33780 +1 1 +.names 33780 33781 +0 1 +.names 33183 33782 +1 1 +.names 33782 33783 +0 1 +.names 33442 33784 +1 1 +.names 33784 33785 +0 1 +.names 33783 33785 33786 +11 1 +.names 33774 33787 +0 1 +.names 33793 33795 33788 +1- 1 +-1 1 +.names 33788 33789 +1 1 +.names 33442 33797 33790 +11 1 +.names 33790 33791 +1 1 +.names 33791 33792 +0 1 +.names 33373 33792 33793 +11 1 +.names 1376 33794 +0 1 +.names 7624 33794 33795 +11 1 +.names 2413 33796 +1 1 +.names 33796 33797 +0 1 +.names 33239 33798 +1 1 +.names 33798 33799 +0 1 +.names 33442 33800 +1 1 +.names 33800 33801 +0 1 +.names 33799 33801 33802 +11 1 +.names 33789 33803 +0 1 +.names 33387 33804 +1 1 +.names 33387 33808 33805 +11 1 +.names 33805 33806 +1 1 +.names 2413 33807 +1 1 +.names 33807 33808 +0 1 +.names 33812 33813 33809 +1- 1 +-1 1 +.names 33809 33810 +1 1 +.names 33806 33811 +0 1 +.names 33453 33811 33812 +11 1 +.names 7635 33271 33813 +11 1 +.names 33804 33814 +0 1 +.names 33268 33815 +1 1 +.names 33815 33816 +0 1 +.names 33814 33816 33817 +11 1 +.names 33810 33818 +0 1 +.names 33824 33825 33819 +1- 1 +-1 1 +.names 33819 33820 +1 1 +.names 33362 33827 33821 +11 1 +.names 33821 33822 +1 1 +.names 33822 33823 +0 1 +.names 33373 33823 33824 +11 1 +.names 7624 33278 33825 +11 1 +.names 2413 33826 +1 1 +.names 33826 33827 +0 1 +.names 33281 33828 +1 1 +.names 33828 33829 +0 1 +.names 33362 33830 +1 1 +.names 33830 33831 +0 1 +.names 33829 33831 33832 +11 1 +.names 33820 33833 +0 1 +.names 33839 33841 33834 +1- 1 +-1 1 +.names 33834 33835 +1 1 +.names 33426 33843 33836 +11 1 +.names 33836 33837 +1 1 +.names 33837 33838 +0 1 +.names 33356 33838 33839 +11 1 +.names 1379 33840 +0 1 +.names 7636 33840 33841 +11 1 +.names 2413 33842 +1 1 +.names 33842 33843 +0 1 +.names 33348 33844 +1 1 +.names 33844 33845 +0 1 +.names 33426 33846 +1 1 +.names 33846 33847 +0 1 +.names 33845 33847 33848 +11 1 +.names 33835 33849 +0 1 +.names 33852 32155 33850 +1- 1 +-1 1 +.names 33850 33851 +1 1 +.names 8152 33852 +0 1 +.names 33855 33856 33853 +1- 1 +-1 1 +.names 33853 33854 +1 1 +.names 258 33855 +0 1 +.names 8173 33856 +0 1 +.names 33863 33866 33857 +1- 1 +-1 1 +.names 33857 33858 +1 1 +.names 33870 33871 33859 +1- 1 +-1 1 +.names 33859 33860 +1 1 +.names 33860 33861 +0 1 +.names 33854 33862 +0 1 +.names 33861 33862 33863 +1- 1 +-1 1 +.names 33874 33876 33864 +11 1 +.names 33864 33865 +1 1 +.names 33865 33866 +0 1 +.names 33887 33888 33867 +11 1 +.names 33867 33868 +1 1 +.names 33868 33869 +0 1 +.names 2413 33869 33870 +11 1 +.names 1783 2413 33871 +11 1 +.names 8162 33889 33872 +1- 1 +-1 1 +.names 33872 33873 +1 1 +.names 33873 33851 33874 +11 1 +.names 8170 33890 33875 +1- 1 +-1 1 +.names 33875 33876 +1 1 +.names 33881 33882 33877 +1- 1 +-1 1 +.names 33877 33878 +1 1 +.names 33852 33879 +1 1 +.names 33879 33880 +0 1 +.names 8173 33880 33881 +1- 1 +-1 1 +.names 6023 33882 +0 1 +.names 8175 33886 33883 +1- 1 +-1 1 +.names 33883 33884 +1 1 +.names 8170 33885 +1 1 +.names 33885 33886 +0 1 +.names 33878 33887 +0 1 +.names 33884 33888 +0 1 +.names 5959 33889 +0 1 +.names 5879 33890 +0 1 +.names 33893 33856 33891 +1- 1 +-1 1 +.names 33891 33892 +1 1 +.names 242 33893 +0 1 +.names 33900 33901 33894 +1- 1 +-1 1 +.names 33894 33895 +1 1 +.names 8174 33896 +0 1 +.names 33912 33913 33897 +11 1 +.names 33897 33898 +1 1 +.names 33898 33899 +0 1 +.names 33896 33899 33900 +11 1 +.names 8174 32189 33901 +11 1 +.names 33906 33907 33902 +1- 1 +-1 1 +.names 33902 33903 +1 1 +.names 8170 33904 +1 1 +.names 33904 33905 +0 1 +.names 8184 33905 33906 +1- 1 +-1 1 +.names 5991 33907 +0 1 +.names 8173 33911 33908 +1- 1 +-1 1 +.names 33908 33909 +1 1 +.names 2413 33910 +1 1 +.names 33910 33911 +0 1 +.names 33903 33912 +0 1 +.names 33909 33913 +0 1 +.names 33917 33918 33914 +1- 1 +-1 1 +.names 33914 33915 +1 1 +.names 33932 33933 33916 +1- 1 +-1 1 +.names 33916 33917 +1 1 +.names 33895 33918 +0 1 +.names 8170 33921 33919 +1- 1 +-1 1 +.names 33919 33920 +1 1 +.names 5815 33921 +0 1 +.names 2413 33922 +1 1 +.names 33922 33923 +1 1 +.names 33926 33927 33924 +1- 1 +-1 1 +.names 33924 33925 +1 1 +.names 5927 33926 +0 1 +.names 8184 33927 +0 1 +.names 33923 33928 +0 1 +.names 33925 33929 +0 1 +.names 33928 33929 33930 +1- 1 +-1 1 +.names 33920 33931 +0 1 +.names 33930 33931 33932 +1- 1 +-1 1 +.names 33892 33933 +0 1 +.names 33942 33945 33934 +1- 1 +-1 1 +.names 33934 33935 +1 1 +.names 33950 33952 33936 +1- 1 +-1 1 +.names 33936 33937 +1 1 +.names 33937 33938 +0 1 +.names 2413 33939 +1 1 +.names 33939 33940 +1 1 +.names 33940 33941 +0 1 +.names 33938 33941 33942 +1- 1 +-1 1 +.names 33957 33959 33943 +11 1 +.names 33943 33944 +1 1 +.names 33944 33945 +0 1 +.names 8144 33946 +0 1 +.names 33966 33967 33947 +11 1 +.names 33947 33948 +1 1 +.names 33948 33949 +0 1 +.names 33946 33949 33950 +11 1 +.names 237 33951 +0 1 +.names 8144 33951 33952 +11 1 +.names 33896 22288 33953 +1- 1 +-1 1 +.names 33953 33954 +1 1 +.names 8162 33976 33955 +1- 1 +-1 1 +.names 33955 33956 +1 1 +.names 33954 33956 33957 +11 1 +.names 33968 33969 33958 +1- 1 +-1 1 +.names 33958 33959 +1 1 +.names 8175 33963 33960 +1- 1 +-1 1 +.names 33960 33961 +1 1 +.names 2413 33962 +1 1 +.names 33962 33963 +0 1 +.names 33974 33975 33964 +1- 1 +-1 1 +.names 33964 33965 +1 1 +.names 33965 33966 +0 1 +.names 33961 33967 +0 1 +.names 5795 33968 +0 1 +.names 8159 33969 +0 1 +.names 33969 33970 +1 1 +.names 33970 33971 +0 1 +.names 33896 33972 +1 1 +.names 33972 33973 +0 1 +.names 33971 33973 33974 +1- 1 +-1 1 +.names 5981 33975 +0 1 +.names 5917 33976 +0 1 +.names 33985 33988 33977 +1- 1 +-1 1 +.names 33977 33978 +1 1 +.names 33993 33995 33979 +1- 1 +-1 1 +.names 33979 33980 +1 1 +.names 33980 33981 +0 1 +.names 2413 33982 +1 1 +.names 33982 33983 +1 1 +.names 33983 33984 +0 1 +.names 33981 33984 33985 +1- 1 +-1 1 +.names 34014 34015 33986 +11 1 +.names 33986 33987 +1 1 +.names 33987 33988 +0 1 +.names 8180 33989 +0 1 +.names 34002 34003 33990 +11 1 +.names 33990 33991 +1 1 +.names 33991 33992 +0 1 +.names 33989 33992 33993 +11 1 +.names 244 33994 +0 1 +.names 8180 33994 33995 +11 1 +.names 8179 33999 33996 +1- 1 +-1 1 +.names 33996 33997 +1 1 +.names 2413 33998 +1 1 +.names 33998 33999 +0 1 +.names 34022 34023 34000 +1- 1 +-1 1 +.names 34000 34001 +1 1 +.names 34001 34002 +0 1 +.names 33997 34003 +0 1 +.names 34006 34007 34004 +1- 1 +-1 1 +.names 34004 34005 +1 1 +.names 5823 34006 +0 1 +.names 8179 34007 +0 1 +.names 34010 34011 34008 +1- 1 +-1 1 +.names 34008 34009 +1 1 +.names 56571 8153 34010 +11 1 +.names 34005 34011 +0 1 +.names 8183 5931 34012 +11 1 +.names 34012 34013 +1 1 +.names 34013 34014 +0 1 +.names 34009 34015 +0 1 +.names 8153 34016 +0 1 +.names 34016 34017 +1 1 +.names 8183 34018 +0 1 +.names 34018 34019 +1 1 +.names 34019 34020 +0 1 +.names 34017 34021 +0 1 +.names 34020 34021 34022 +1- 1 +-1 1 +.names 5995 34023 +0 1 +.names 34016 32320 34024 +1- 1 +-1 1 +.names 34024 34025 +1 1 +.names 34028 8170 34026 +1- 1 +-1 1 +.names 34026 34027 +1 1 +.names 5831 34028 +0 1 +.names 8182 34032 34029 +1- 1 +-1 1 +.names 34029 34030 +1 1 +.names 2413 34031 +1 1 +.names 34031 34032 +0 1 +.names 34038 34040 34033 +1- 1 +-1 1 +.names 34033 34034 +1 1 +.names 34043 34044 34035 +11 1 +.names 34035 34036 +1 1 +.names 34036 34037 +0 1 +.names 33989 34037 34038 +11 1 +.names 246 34039 +0 1 +.names 8180 34039 34040 +11 1 +.names 34047 34048 34041 +1- 1 +-1 1 +.names 34041 34042 +1 1 +.names 34042 34043 +0 1 +.names 34030 34044 +0 1 +.names 34016 34045 +1 1 +.names 34045 34046 +0 1 +.names 8156 34046 34047 +1- 1 +-1 1 +.names 5999 34048 +0 1 +.names 34055 34056 34049 +1- 1 +-1 1 +.names 34049 34050 +1 1 +.names 34025 34051 +0 1 +.names 34067 34068 34052 +1- 1 +-1 1 +.names 34052 34053 +1 1 +.names 34053 34054 +0 1 +.names 34051 34054 34055 +1- 1 +-1 1 +.names 34027 34056 +0 1 +.names 34059 34062 34057 +11 1 +.names 34057 34058 +1 1 +.names 34050 34059 +0 1 +.names 1783 34060 +1 1 +.names 34060 34061 +1 1 +.names 34061 34062 +0 1 +.names 34065 34066 34063 +1- 1 +-1 1 +.names 34063 34064 +1 1 +.names 34034 34065 +0 1 +.names 34058 34066 +0 1 +.names 8182 34067 +0 1 +.names 5935 34068 +0 1 +.names 34077 34080 34069 +1- 1 +-1 1 +.names 34069 34070 +1 1 +.names 34085 34087 34071 +1- 1 +-1 1 +.names 34071 34072 +1 1 +.names 34072 34073 +0 1 +.names 2413 34074 +1 1 +.names 34074 34075 +1 1 +.names 34075 34076 +0 1 +.names 34073 34076 34077 +1- 1 +-1 1 +.names 34109 34104 34078 +11 1 +.names 34078 34079 +1 1 +.names 34079 34080 +0 1 +.names 8169 34081 +0 1 +.names 34099 34100 34082 +11 1 +.names 34082 34083 +1 1 +.names 34083 34084 +0 1 +.names 34081 34084 34085 +11 1 +.names 5859 34086 +0 1 +.names 8169 34086 34087 +11 1 +.names 8173 34090 34088 +1- 1 +-1 1 +.names 34088 34089 +1 1 +.names 6013 34090 +0 1 +.names 34095 34097 34091 +1- 1 +-1 1 +.names 34091 34092 +1 1 +.names 34098 2413 34093 +11 1 +.names 34093 34094 +1 1 +.names 34094 34095 +0 1 +.names 33927 34096 +1 1 +.names 34096 34097 +0 1 +.names 8154 34098 +0 1 +.names 34092 34099 +0 1 +.names 34089 34100 +0 1 +.names 34098 32357 34101 +1- 1 +-1 1 +.names 34101 34102 +1 1 +.names 34105 33856 34103 +1- 1 +-1 1 +.names 34103 34104 +1 1 +.names 253 34105 +0 1 +.names 33927 34108 34106 +1- 1 +-1 1 +.names 34106 34107 +1 1 +.names 5949 34108 +0 1 +.names 34107 34102 34109 +11 1 +.names 34118 34121 34110 +1- 1 +-1 1 +.names 34110 34111 +1 1 +.names 34126 34128 34112 +1- 1 +-1 1 +.names 34112 34113 +1 1 +.names 34113 34114 +0 1 +.names 2413 34115 +1 1 +.names 34115 34116 +1 1 +.names 34116 34117 +0 1 +.names 34114 34117 34118 +1- 1 +-1 1 +.names 34149 34150 34119 +11 1 +.names 34119 34120 +1 1 +.names 34120 34121 +0 1 +.names 8142 34122 +0 1 +.names 34145 34146 34123 +11 1 +.names 34123 34124 +1 1 +.names 34124 34125 +0 1 +.names 34122 34125 34126 +11 1 +.names 266 34127 +0 1 +.names 8142 34127 34128 +11 1 +.names 34131 34134 34129 +1- 1 +-1 1 +.names 34129 34130 +1 1 +.names 8152 56593 34131 +11 1 +.names 34151 34018 34132 +1- 1 +-1 1 +.names 34132 34133 +1 1 +.names 34133 34134 +0 1 +.names 34139 34140 34135 +1- 1 +-1 1 +.names 34135 34136 +1 1 +.names 33852 34137 +1 1 +.names 34137 34138 +0 1 +.names 8178 34138 34139 +1- 1 +-1 1 +.names 6039 34140 +0 1 +.names 8183 34144 34141 +1- 1 +-1 1 +.names 34141 34142 +1 1 +.names 2413 34143 +1 1 +.names 34143 34144 +0 1 +.names 34136 34145 +0 1 +.names 34142 34146 +0 1 +.names 5909 8178 34147 +11 1 +.names 34147 34148 +1 1 +.names 34148 34149 +0 1 +.names 34130 34150 +0 1 +.names 5975 34151 +0 1 +.names 34160 34163 34152 +1- 1 +-1 1 +.names 34152 34153 +1 1 +.names 34167 34169 34154 +1- 1 +-1 1 +.names 34154 34155 +1 1 +.names 34155 34156 +0 1 +.names 2413 34157 +1 1 +.names 34157 34158 +1 1 +.names 34158 34159 +0 1 +.names 34156 34159 34160 +1- 1 +-1 1 +.names 34174 34176 34161 +11 1 +.names 34161 34162 +1 1 +.names 34162 34163 +0 1 +.names 34187 34188 34164 +11 1 +.names 34164 34165 +1 1 +.names 34165 34166 +0 1 +.names 33989 34166 34167 +11 1 +.names 255 34168 +0 1 +.names 8180 34168 34169 +11 1 +.names 33896 32433 34170 +1- 1 +-1 1 +.names 34170 34171 +1 1 +.names 8162 34191 34172 +1- 1 +-1 1 +.names 34172 34173 +1 1 +.names 34171 34173 34174 +11 1 +.names 34189 34190 34175 +1- 1 +-1 1 +.names 34175 34176 +1 1 +.names 34181 34182 34177 +1- 1 +-1 1 +.names 34177 34178 +1 1 +.names 33896 34179 +1 1 +.names 34179 34180 +0 1 +.names 8178 34180 34181 +1- 1 +-1 1 +.names 6017 34182 +0 1 +.names 8175 34186 34183 +1- 1 +-1 1 +.names 34183 34184 +1 1 +.names 2413 34185 +1 1 +.names 34185 34186 +0 1 +.names 34184 34187 +0 1 +.names 34178 34188 +0 1 +.names 5867 34189 +0 1 +.names 8178 34190 +0 1 +.names 5953 34191 +0 1 +.names 34197 34199 34192 +1- 1 +-1 1 +.names 34192 34193 +1 1 +.names 34206 34207 34194 +11 1 +.names 34194 34195 +1 1 +.names 34195 34196 +0 1 +.names 33989 34196 34197 +11 1 +.names 245 34198 +0 1 +.names 8180 34198 34199 +11 1 +.names 1783 34203 34200 +1- 1 +-1 1 +.names 34200 34201 +1 1 +.names 34018 34202 +1 1 +.names 34202 34203 +0 1 +.names 34213 34214 34204 +1- 1 +-1 1 +.names 34204 34205 +1 1 +.names 34205 34206 +0 1 +.names 34201 34207 +0 1 +.names 34210 33969 34208 +1- 1 +-1 1 +.names 34208 34209 +1 1 +.names 5827 34210 +0 1 +.names 33896 34211 +1 1 +.names 34211 34212 +0 1 +.names 8159 34212 34213 +1- 1 +-1 1 +.names 5997 34214 +0 1 +.names 34223 34224 34215 +1- 1 +-1 1 +.names 34215 34216 +1 1 +.names 33896 32474 34217 +1- 1 +-1 1 +.names 34217 34218 +1 1 +.names 34218 34219 +0 1 +.names 34018 34235 34220 +1- 1 +-1 1 +.names 34220 34221 +1 1 +.names 34221 34222 +0 1 +.names 34219 34222 34223 +1- 1 +-1 1 +.names 34209 34224 +0 1 +.names 34227 34230 34225 +1- 1 +-1 1 +.names 34225 34226 +1 1 +.names 34193 34227 +0 1 +.names 34233 34234 34228 +11 1 +.names 34228 34229 +1 1 +.names 34229 34230 +0 1 +.names 1783 34231 +1 1 +.names 34231 34232 +1 1 +.names 34216 34233 +0 1 +.names 34232 34234 +0 1 +.names 5933 34235 +0 1 +.names 34244 34247 34236 +1- 1 +-1 1 +.names 34236 34237 +1 1 +.names 34251 34253 34238 +1- 1 +-1 1 +.names 34238 34239 +1 1 +.names 34239 34240 +0 1 +.names 2413 34241 +1 1 +.names 34241 34242 +1 1 +.names 34242 34243 +0 1 +.names 34240 34243 34244 +1- 1 +-1 1 +.names 34274 34267 34245 +11 1 +.names 34245 34246 +1 1 +.names 34246 34247 +0 1 +.names 34264 34265 34248 +11 1 +.names 34248 34249 +1 1 +.names 34249 34250 +0 1 +.names 33989 34250 34251 +11 1 +.names 261 34252 +0 1 +.names 8180 34252 34253 +11 1 +.names 34258 34259 34254 +1- 1 +-1 1 +.names 34254 34255 +1 1 +.names 33852 34256 +1 1 +.names 34256 34257 +0 1 +.names 8178 34257 34258 +1- 1 +-1 1 +.names 6029 34259 +0 1 +.names 8184 34263 34260 +1- 1 +-1 1 +.names 34260 34261 +1 1 +.names 2413 34262 +1 1 +.names 34262 34263 +0 1 +.names 34255 34264 +0 1 +.names 34261 34265 +0 1 +.names 34268 34190 34266 +1- 1 +-1 1 +.names 34266 34267 +1 1 +.names 5891 34268 +0 1 +.names 33852 32509 34269 +1- 1 +-1 1 +.names 34269 34270 +1 1 +.names 33927 34273 34271 +1- 1 +-1 1 +.names 34271 34272 +1 1 +.names 5965 34273 +0 1 +.names 34272 34270 34274 +11 1 +.names 34283 34286 34275 +1- 1 +-1 1 +.names 34275 34276 +1 1 +.names 34290 34292 34277 +1- 1 +-1 1 +.names 34277 34278 +1 1 +.names 34278 34279 +0 1 +.names 2413 34280 +1 1 +.names 34280 34281 +1 1 +.names 34281 34282 +0 1 +.names 34279 34282 34283 +1- 1 +-1 1 +.names 34297 34299 34284 +11 1 +.names 34284 34285 +1 1 +.names 34285 34286 +0 1 +.names 34310 34311 34287 +11 1 +.names 34287 34288 +1 1 +.names 34288 34289 +0 1 +.names 34122 34289 34290 +11 1 +.names 247 34291 +0 1 +.names 8142 34291 34292 +11 1 +.names 33852 32545 34293 +1- 1 +-1 1 +.names 34293 34294 +1 1 +.names 8162 34313 34295 +1- 1 +-1 1 +.names 34295 34296 +1 1 +.names 34294 34296 34297 +11 1 +.names 34312 8170 34298 +1- 1 +-1 1 +.names 34298 34299 +1 1 +.names 8156 34302 34300 +1- 1 +-1 1 +.names 34300 34301 +1 1 +.names 6001 34302 +0 1 +.names 34307 34309 34303 +1- 1 +-1 1 +.names 34303 34304 +1 1 +.names 33852 2413 34305 +11 1 +.names 34305 34306 +1 1 +.names 34306 34307 +0 1 +.names 8162 34308 +1 1 +.names 34308 34309 +0 1 +.names 34304 34310 +0 1 +.names 34301 34311 +0 1 +.names 5835 34312 +0 1 +.names 5937 34313 +0 1 +.names 34316 33852 34314 +1- 1 +-1 1 +.names 34314 34315 +1 1 +.names 56587 34316 +0 1 +.names 34325 34328 34317 +1- 1 +-1 1 +.names 34317 34318 +1 1 +.names 34332 34334 34319 +1- 1 +-1 1 +.names 34319 34320 +1 1 +.names 34320 34321 +0 1 +.names 2413 34322 +1 1 +.names 34322 34323 +1 1 +.names 34323 34324 +0 1 +.names 34321 34324 34325 +1- 1 +-1 1 +.names 34353 34354 34326 +11 1 +.names 34326 34327 +1 1 +.names 34327 34328 +0 1 +.names 34349 34350 34329 +11 1 +.names 34329 34330 +1 1 +.names 34330 34331 +0 1 +.names 34122 34331 34332 +11 1 +.names 260 34333 +0 1 +.names 8142 34333 34334 +11 1 +.names 34337 34338 34335 +1- 1 +-1 1 +.names 34335 34336 +1 1 +.names 8183 5963 34337 +11 1 +.names 34315 34338 +0 1 +.names 34343 34344 34339 +1- 1 +-1 1 +.names 34339 34340 +1 1 +.names 33852 34341 +1 1 +.names 34341 34342 +0 1 +.names 8178 34342 34343 +1- 1 +-1 1 +.names 6027 34344 +0 1 +.names 8183 34348 34345 +1- 1 +-1 1 +.names 34345 34346 +1 1 +.names 2413 34347 +1 1 +.names 34347 34348 +0 1 +.names 34340 34349 +0 1 +.names 34346 34350 +0 1 +.names 5887 8178 34351 +11 1 +.names 34351 34352 +1 1 +.names 34352 34353 +0 1 +.names 34336 34354 +0 1 +.names 34363 34366 34355 +1- 1 +-1 1 +.names 34355 34356 +1 1 +.names 34370 34372 34357 +1- 1 +-1 1 +.names 34357 34358 +1 1 +.names 34358 34359 +0 1 +.names 2413 34360 +1 1 +.names 34360 34361 +1 1 +.names 34361 34362 +0 1 +.names 34359 34362 34363 +1- 1 +-1 1 +.names 34394 34395 34364 +11 1 +.names 34364 34365 +1 1 +.names 34365 34366 +0 1 +.names 34383 34384 34367 +11 1 +.names 34367 34368 +1 1 +.names 34368 34369 +0 1 +.names 33946 34369 34370 +11 1 +.names 236 34371 +0 1 +.names 8144 34371 34372 +11 1 +.names 34377 34378 34373 +1- 1 +-1 1 +.names 34373 34374 +1 1 +.names 34016 34375 +1 1 +.names 34375 34376 +0 1 +.names 8182 34376 34377 +1- 1 +-1 1 +.names 5979 34378 +0 1 +.names 8156 34382 34379 +1- 1 +-1 1 +.names 34379 34380 +1 1 +.names 2413 34381 +1 1 +.names 34381 34382 +0 1 +.names 34374 34383 +0 1 +.names 34380 34384 +0 1 +.names 34387 8170 34385 +1- 1 +-1 1 +.names 34385 34386 +1 1 +.names 5791 34387 +0 1 +.names 34390 34391 34388 +1- 1 +-1 1 +.names 34388 34389 +1 1 +.names 8153 56563 34390 +11 1 +.names 34386 34391 +0 1 +.names 8182 5915 34392 +11 1 +.names 34392 34393 +1 1 +.names 34393 34394 +0 1 +.names 34389 34395 +0 1 +.names 34402 34404 34396 +1- 1 +-1 1 +.names 34396 34397 +1 1 +.names 8161 34398 +0 1 +.names 34415 34416 34399 +11 1 +.names 34399 34400 +1 1 +.names 34400 34401 +0 1 +.names 34398 34401 34402 +11 1 +.names 5951 34403 +0 1 +.names 8161 34403 34404 +11 1 +.names 8173 34407 34405 +1- 1 +-1 1 +.names 34405 34406 +1 1 +.names 6015 34407 +0 1 +.names 34412 34414 34408 +1- 1 +-1 1 +.names 34408 34409 +1 1 +.names 34016 2413 34410 +11 1 +.names 34410 34411 +1 1 +.names 34411 34412 +0 1 +.names 8170 34413 +1 1 +.names 34413 34414 +0 1 +.names 34409 34415 +0 1 +.names 34406 34416 +0 1 +.names 34420 34421 34417 +1- 1 +-1 1 +.names 34417 34418 +1 1 +.names 34433 34436 34419 +1- 1 +-1 1 +.names 34419 34420 +1 1 +.names 34397 34421 +0 1 +.names 34424 8170 34422 +1- 1 +-1 1 +.names 34422 34423 +1 1 +.names 5863 34424 +0 1 +.names 34423 34425 +0 1 +.names 34437 33856 34426 +1- 1 +-1 1 +.names 34426 34427 +1 1 +.names 34427 34428 +0 1 +.names 34425 34428 34429 +1- 1 +-1 1 +.names 32628 34016 34430 +1- 1 +-1 1 +.names 34430 34431 +1 1 +.names 34431 34432 +0 1 +.names 34429 34432 34433 +1- 1 +-1 1 +.names 2413 34434 +1 1 +.names 34434 34435 +1 1 +.names 34435 34436 +0 1 +.names 254 34437 +0 1 +.names 34443 34445 34438 +1- 1 +-1 1 +.names 34438 34439 +1 1 +.names 34456 34457 34440 +11 1 +.names 34440 34441 +1 1 +.names 34441 34442 +0 1 +.names 34122 34442 34443 +11 1 +.names 243 34444 +0 1 +.names 8142 34444 34445 +11 1 +.names 34450 34451 34446 +1- 1 +-1 1 +.names 34446 34447 +1 1 +.names 34016 34448 +1 1 +.names 34448 34449 +0 1 +.names 8159 34449 34450 +1- 1 +-1 1 +.names 5993 34451 +0 1 +.names 8175 34455 34452 +1- 1 +-1 1 +.names 34452 34453 +1 1 +.names 2413 34454 +1 1 +.names 34454 34455 +0 1 +.names 34447 34456 +0 1 +.names 34453 34457 +0 1 +.names 8162 34460 34458 +1- 1 +-1 1 +.names 34458 34459 +1 1 +.names 5929 34460 +0 1 +.names 34463 33969 34461 +1- 1 +-1 1 +.names 34461 34462 +1 1 +.names 5819 34463 +0 1 +.names 34470 34471 34464 +1- 1 +-1 1 +.names 34464 34465 +1 1 +.names 34459 34466 +0 1 +.names 34016 32680 34467 +1- 1 +-1 1 +.names 34467 34468 +1 1 +.names 34468 34469 +0 1 +.names 34466 34469 34470 +1- 1 +-1 1 +.names 34462 34471 +0 1 +.names 34474 34477 34472 +1- 1 +-1 1 +.names 34472 34473 +1 1 +.names 34439 34474 +0 1 +.names 34478 34481 34475 +11 1 +.names 34475 34476 +1 1 +.names 34476 34477 +0 1 +.names 34465 34478 +0 1 +.names 1783 34479 +1 1 +.names 34479 34480 +1 1 +.names 34480 34481 +0 1 +.names 34490 34493 34482 +1- 1 +-1 1 +.names 34482 34483 +1 1 +.names 34497 34499 34484 +1- 1 +-1 1 +.names 34484 34485 +1 1 +.names 34485 34486 +0 1 +.names 2413 34487 +1 1 +.names 34487 34488 +1 1 +.names 34488 34489 +0 1 +.names 34486 34489 34490 +1- 1 +-1 1 +.names 34502 34505 34491 +11 1 +.names 34491 34492 +1 1 +.names 34492 34493 +0 1 +.names 34512 34513 34494 +11 1 +.names 34494 34495 +1 1 +.names 34495 34496 +0 1 +.names 34122 34496 34497 +11 1 +.names 238 34498 +0 1 +.names 8142 34498 34499 +11 1 +.names 34518 5919 34500 +11 1 +.names 34500 34501 +1 1 +.names 34501 34502 +0 1 +.names 34520 34521 34503 +1- 1 +-1 1 +.names 34503 34504 +1 1 +.names 34504 34505 +0 1 +.names 8156 34509 34506 +1- 1 +-1 1 +.names 34506 34507 +1 1 +.names 2413 34508 +1 1 +.names 34508 34509 +0 1 +.names 34524 34525 34510 +1- 1 +-1 1 +.names 34510 34511 +1 1 +.names 34511 34512 +0 1 +.names 34507 34513 +0 1 +.names 34516 8170 34514 +1- 1 +-1 1 +.names 34514 34515 +1 1 +.names 5799 34516 +0 1 +.names 34522 34517 +0 1 +.names 34517 34518 +1 1 +.names 34098 34519 +1 1 +.names 8154 56565 34520 +11 1 +.names 34515 34521 +0 1 +.names 33927 34522 +1 1 +.names 34519 34523 +0 1 +.names 34517 34523 34524 +1- 1 +-1 1 +.names 5983 34525 +0 1 +.names 22346 33896 34526 +1- 1 +-1 1 +.names 34526 34527 +1 1 +.names 34536 34539 34528 +1- 1 +-1 1 +.names 34528 34529 +1 1 +.names 34543 34545 34530 +1- 1 +-1 1 +.names 34530 34531 +1 1 +.names 34531 34532 +0 1 +.names 2413 34533 +1 1 +.names 34533 34534 +1 1 +.names 34534 34535 +0 1 +.names 34532 34535 34536 +1- 1 +-1 1 +.names 34548 34551 34537 +11 1 +.names 34537 34538 +1 1 +.names 34538 34539 +0 1 +.names 34556 34559 34540 +11 1 +.names 34540 34541 +1 1 +.names 34541 34542 +0 1 +.names 33946 34542 34543 +11 1 +.names 241 34544 +0 1 +.names 8144 34544 34545 +11 1 +.names 34561 34546 +0 1 +.names 34546 34547 +1 1 +.names 34547 34548 +0 1 +.names 34569 34570 34549 +1- 1 +-1 1 +.names 34549 34550 +1 1 +.names 34550 34551 +0 1 +.names 8183 34555 34552 +1- 1 +-1 1 +.names 34552 34553 +1 1 +.names 2413 34554 +1 1 +.names 34554 34555 +0 1 +.names 34553 34556 +0 1 +.names 34567 34568 34557 +1- 1 +-1 1 +.names 34557 34558 +1 1 +.names 34558 34559 +0 1 +.names 34562 33969 34560 +1- 1 +-1 1 +.names 34560 34561 +1 1 +.names 5811 34562 +0 1 +.names 33969 34563 +1 1 +.names 34563 34564 +0 1 +.names 33896 34565 +1 1 +.names 34565 34566 +0 1 +.names 34564 34566 34567 +1- 1 +-1 1 +.names 5989 34568 +0 1 +.names 8183 5925 34569 +11 1 +.names 34527 34570 +0 1 +.names 34016 32823 34571 +1- 1 +-1 1 +.names 34571 34572 +1 1 +.names 34578 34580 34573 +1- 1 +-1 1 +.names 34573 34574 +1 1 +.names 34591 34592 34575 +11 1 +.names 34575 34576 +1 1 +.names 34576 34577 +0 1 +.names 33989 34577 34578 +11 1 +.names 252 34579 +0 1 +.names 8180 34579 34580 +11 1 +.names 34585 34586 34581 +1- 1 +-1 1 +.names 34581 34582 +1 1 +.names 34016 34583 +1 1 +.names 34583 34584 +0 1 +.names 8159 34584 34585 +1- 1 +-1 1 +.names 6011 34586 +0 1 +.names 8175 34590 34587 +1- 1 +-1 1 +.names 34587 34588 +1 1 +.names 2413 34589 +1 1 +.names 34589 34590 +0 1 +.names 34582 34591 +0 1 +.names 34588 34592 +0 1 +.names 34595 33969 34593 +1- 1 +-1 1 +.names 34593 34594 +1 1 +.names 5855 34595 +0 1 +.names 34602 34603 34596 +1- 1 +-1 1 +.names 34596 34597 +1 1 +.names 34572 34598 +0 1 +.names 8162 34614 34599 +1- 1 +-1 1 +.names 34599 34600 +1 1 +.names 34600 34601 +0 1 +.names 34598 34601 34602 +1- 1 +-1 1 +.names 34594 34603 +0 1 +.names 34606 34609 34604 +1- 1 +-1 1 +.names 34604 34605 +1 1 +.names 34574 34606 +0 1 +.names 34612 34613 34607 +11 1 +.names 34607 34608 +1 1 +.names 34608 34609 +0 1 +.names 1783 34610 +1 1 +.names 34610 34611 +1 1 +.names 34597 34612 +0 1 +.names 34611 34613 +0 1 +.names 5947 34614 +0 1 +.names 34623 34626 34615 +1- 1 +-1 1 +.names 34615 34616 +1 1 +.names 34630 34632 34617 +1- 1 +-1 1 +.names 34617 34618 +1 1 +.names 34618 34619 +0 1 +.names 2413 34620 +1 1 +.names 34620 34621 +1 1 +.names 34621 34622 +0 1 +.names 34619 34622 34623 +1- 1 +-1 1 +.names 34653 34646 34624 +11 1 +.names 34624 34625 +1 1 +.names 34625 34626 +0 1 +.names 34643 34644 34627 +11 1 +.names 34627 34628 +1 1 +.names 34628 34629 +0 1 +.names 34122 34629 34630 +11 1 +.names 259 34631 +0 1 +.names 8142 34631 34632 +11 1 +.names 34637 34638 34633 +1- 1 +-1 1 +.names 34633 34634 +1 1 +.names 34098 34635 +1 1 +.names 34635 34636 +0 1 +.names 8179 34636 34637 +1- 1 +-1 1 +.names 6025 34638 +0 1 +.names 8184 34642 34639 +1- 1 +-1 1 +.names 34639 34640 +1 1 +.names 2413 34641 +1 1 +.names 34641 34642 +0 1 +.names 34634 34643 +0 1 +.names 34640 34644 +0 1 +.names 34647 34007 34645 +1- 1 +-1 1 +.names 34645 34646 +1 1 +.names 5883 34647 +0 1 +.names 34098 32858 34648 +1- 1 +-1 1 +.names 34648 34649 +1 1 +.names 33927 34652 34650 +1- 1 +-1 1 +.names 34650 34651 +1 1 +.names 5961 34652 +0 1 +.names 34651 34649 34653 +11 1 +.names 34098 34656 34654 +1- 1 +-1 1 +.names 34654 34655 +1 1 +.names 5788 34656 +0 1 +.names 34665 34668 34657 +1- 1 +-1 1 +.names 34657 34658 +1 1 +.names 34672 34674 34659 +1- 1 +-1 1 +.names 34659 34660 +1 1 +.names 34660 34661 +0 1 +.names 2413 34662 +1 1 +.names 34662 34663 +1 1 +.names 34663 34664 +0 1 +.names 34661 34664 34665 +1- 1 +-1 1 +.names 34677 34679 34666 +11 1 +.names 34666 34667 +1 1 +.names 34667 34668 +0 1 +.names 34690 34691 34669 +11 1 +.names 34669 34670 +1 1 +.names 34670 34671 +0 1 +.names 33946 34671 34672 +11 1 +.names 267 34673 +0 1 +.names 8144 34673 34674 +11 1 +.names 34067 34693 34675 +1- 1 +-1 1 +.names 34675 34676 +1 1 +.names 34655 34676 34677 +11 1 +.names 34692 34007 34678 +1- 1 +-1 1 +.names 34678 34679 +1 1 +.names 34684 34685 34680 +1- 1 +-1 1 +.names 34680 34681 +1 1 +.names 34098 34682 +1 1 +.names 34682 34683 +0 1 +.names 8179 34683 34684 +1- 1 +-1 1 +.names 6041 34685 +0 1 +.names 8182 34689 34686 +1- 1 +-1 1 +.names 34686 34687 +1 1 +.names 2413 34688 +1 1 +.names 34688 34689 +0 1 +.names 34681 34690 +0 1 +.names 34687 34691 +0 1 +.names 5913 34692 +0 1 +.names 5977 34693 +0 1 +.names 34702 34705 34694 +1- 1 +-1 1 +.names 34694 34695 +1 1 +.names 34709 34711 34696 +1- 1 +-1 1 +.names 34696 34697 +1 1 +.names 34697 34698 +0 1 +.names 2413 34699 +1 1 +.names 34699 34700 +1 1 +.names 34700 34701 +0 1 +.names 34698 34701 34702 +1- 1 +-1 1 +.names 34716 34718 34703 +11 1 +.names 34703 34704 +1 1 +.names 34704 34705 +0 1 +.names 34729 34730 34706 +11 1 +.names 34706 34707 +1 1 +.names 34707 34708 +0 1 +.names 33989 34708 34709 +11 1 +.names 257 34710 +0 1 +.names 8180 34710 34711 +11 1 +.names 34098 32928 34712 +1- 1 +-1 1 +.names 34712 34713 +1 1 +.names 34067 34732 34714 +1- 1 +-1 1 +.names 34714 34715 +1 1 +.names 34713 34715 34716 +11 1 +.names 34731 34190 34717 +1- 1 +-1 1 +.names 34717 34718 +1 1 +.names 34723 34724 34719 +1- 1 +-1 1 +.names 34719 34720 +1 1 +.names 34098 34721 +1 1 +.names 34721 34722 +0 1 +.names 8178 34722 34723 +1- 1 +-1 1 +.names 6021 34724 +0 1 +.names 8182 34728 34725 +1- 1 +-1 1 +.names 34725 34726 +1 1 +.names 2413 34727 +1 1 +.names 34727 34728 +0 1 +.names 34720 34729 +0 1 +.names 34726 34730 +0 1 +.names 5875 34731 +0 1 +.names 5957 34732 +0 1 +.names 34098 32970 34733 +1- 1 +-1 1 +.names 34733 34734 +1 1 +.names 34740 34742 34735 +1- 1 +-1 1 +.names 34735 34736 +1 1 +.names 34753 34754 34737 +11 1 +.names 34737 34738 +1 1 +.names 34738 34739 +0 1 +.names 33989 34739 34740 +11 1 +.names 249 34741 +0 1 +.names 8180 34741 34742 +11 1 +.names 34747 34748 34743 +1- 1 +-1 1 +.names 34743 34744 +1 1 +.names 34098 34745 +1 1 +.names 34745 34746 +0 1 +.names 8159 34746 34747 +1- 1 +-1 1 +.names 6005 34748 +0 1 +.names 8182 34752 34749 +1- 1 +-1 1 +.names 34749 34750 +1 1 +.names 2413 34751 +1 1 +.names 34751 34752 +0 1 +.names 34744 34753 +0 1 +.names 34750 34754 +0 1 +.names 34757 33969 34755 +1- 1 +-1 1 +.names 34755 34756 +1 1 +.names 5843 34757 +0 1 +.names 34764 34765 34758 +1- 1 +-1 1 +.names 34758 34759 +1 1 +.names 34734 34760 +0 1 +.names 34067 34776 34761 +1- 1 +-1 1 +.names 34761 34762 +1 1 +.names 34762 34763 +0 1 +.names 34760 34763 34764 +1- 1 +-1 1 +.names 34756 34765 +0 1 +.names 34768 34771 34766 +1- 1 +-1 1 +.names 34766 34767 +1 1 +.names 34736 34768 +0 1 +.names 34774 34775 34769 +11 1 +.names 34769 34770 +1 1 +.names 34770 34771 +0 1 +.names 1783 34772 +1 1 +.names 34772 34773 +1 1 +.names 34759 34774 +0 1 +.names 34773 34775 +0 1 +.names 5941 34776 +0 1 +.names 34785 34788 34777 +1- 1 +-1 1 +.names 34777 34778 +1 1 +.names 34792 34794 34779 +1- 1 +-1 1 +.names 34779 34780 +1 1 +.names 34780 34781 +0 1 +.names 2413 34782 +1 1 +.names 34782 34783 +1 1 +.names 34783 34784 +0 1 +.names 34781 34784 34785 +1- 1 +-1 1 +.names 34799 34801 34786 +11 1 +.names 34786 34787 +1 1 +.names 34787 34788 +0 1 +.names 34812 34813 34789 +11 1 +.names 34789 34790 +1 1 +.names 34790 34791 +0 1 +.names 33989 34791 34792 +11 1 +.names 250 34793 +0 1 +.names 8180 34793 34794 +11 1 +.names 8162 34814 34795 +1- 1 +-1 1 +.names 34795 34796 +1 1 +.names 33852 33004 34797 +1- 1 +-1 1 +.names 34797 34798 +1 1 +.names 34796 34798 34799 +11 1 +.names 34815 34190 34800 +1- 1 +-1 1 +.names 34800 34801 +1 1 +.names 34806 34807 34802 +1- 1 +-1 1 +.names 34802 34803 +1 1 +.names 33852 34804 +1 1 +.names 34804 34805 +0 1 +.names 8178 34805 34806 +1- 1 +-1 1 +.names 6007 34807 +0 1 +.names 1783 34811 34808 +1- 1 +-1 1 +.names 34808 34809 +1 1 +.names 8162 34810 +1 1 +.names 34810 34811 +0 1 +.names 34803 34812 +0 1 +.names 34809 34813 +0 1 +.names 5943 34814 +0 1 +.names 5847 34815 +0 1 +.names 34818 33852 34816 +1- 1 +-1 1 +.names 34816 34817 +1 1 +.names 56591 34818 +0 1 +.names 34827 34830 34819 +1- 1 +-1 1 +.names 34819 34820 +1 1 +.names 34834 34836 34821 +1- 1 +-1 1 +.names 34821 34822 +1 1 +.names 34822 34823 +0 1 +.names 2413 34824 +1 1 +.names 34824 34825 +1 1 +.names 34825 34826 +0 1 +.names 34823 34826 34827 +1- 1 +-1 1 +.names 34839 34842 34828 +11 1 +.names 34828 34829 +1 1 +.names 34829 34830 +0 1 +.names 34853 34854 34831 +11 1 +.names 34831 34832 +1 1 +.names 34832 34833 +0 1 +.names 33946 34833 34834 +11 1 +.names 264 34835 +0 1 +.names 8144 34835 34836 +11 1 +.names 34858 34837 +0 1 +.names 34837 34838 +1 1 +.names 34838 34839 +0 1 +.names 34855 34856 34840 +1- 1 +-1 1 +.names 34840 34841 +1 1 +.names 34841 34842 +0 1 +.names 34847 34848 34843 +1- 1 +-1 1 +.names 34843 34844 +1 1 +.names 33852 34845 +1 1 +.names 34845 34846 +0 1 +.names 8179 34846 34847 +1- 1 +-1 1 +.names 6035 34848 +0 1 +.names 8175 34852 34849 +1- 1 +-1 1 +.names 34849 34850 +1 1 +.names 2413 34851 +1 1 +.names 34851 34852 +0 1 +.names 34844 34853 +0 1 +.names 34850 34854 +0 1 +.names 8175 5971 34855 +11 1 +.names 34817 34856 +0 1 +.names 34859 34007 34857 +1- 1 +-1 1 +.names 34857 34858 +1 1 +.names 5903 34859 +0 1 +.names 34098 33087 34860 +1- 1 +-1 1 +.names 34860 34861 +1 1 +.names 34867 34869 34862 +1- 1 +-1 1 +.names 34862 34863 +1 1 +.names 34880 34881 34864 +11 1 +.names 34864 34865 +1 1 +.names 34865 34866 +0 1 +.names 33946 34866 34867 +11 1 +.names 248 34868 +0 1 +.names 8144 34868 34869 +11 1 +.names 34874 34875 34870 +1- 1 +-1 1 +.names 34870 34871 +1 1 +.names 34098 34872 +1 1 +.names 34872 34873 +0 1 +.names 8159 34873 34874 +1- 1 +-1 1 +.names 6003 34875 +0 1 +.names 8182 34879 34876 +1- 1 +-1 1 +.names 34876 34877 +1 1 +.names 2413 34878 +1 1 +.names 34878 34879 +0 1 +.names 34871 34880 +0 1 +.names 34877 34881 +0 1 +.names 34884 33969 34882 +1- 1 +-1 1 +.names 34882 34883 +1 1 +.names 5839 34884 +0 1 +.names 34891 34892 34885 +1- 1 +-1 1 +.names 34885 34886 +1 1 +.names 34861 34887 +0 1 +.names 34067 34903 34888 +1- 1 +-1 1 +.names 34888 34889 +1 1 +.names 34889 34890 +0 1 +.names 34887 34890 34891 +1- 1 +-1 1 +.names 34883 34892 +0 1 +.names 34895 34898 34893 +1- 1 +-1 1 +.names 34893 34894 +1 1 +.names 34863 34895 +0 1 +.names 34901 34902 34896 +11 1 +.names 34896 34897 +1 1 +.names 34897 34898 +0 1 +.names 1783 34899 +1 1 +.names 34899 34900 +1 1 +.names 34886 34901 +0 1 +.names 34900 34902 +0 1 +.names 5939 34903 +0 1 +.names 34912 34915 34904 +1- 1 +-1 1 +.names 34904 34905 +1 1 +.names 34919 34921 34906 +1- 1 +-1 1 +.names 34906 34907 +1 1 +.names 34907 34908 +0 1 +.names 2413 34909 +1 1 +.names 34909 34910 +1 1 +.names 34910 34911 +0 1 +.names 34908 34911 34912 +1- 1 +-1 1 +.names 34924 34927 34913 +11 1 +.names 34913 34914 +1 1 +.names 34914 34915 +0 1 +.names 34934 34935 34916 +11 1 +.names 34916 34917 +1 1 +.names 34917 34918 +0 1 +.names 33946 34918 34919 +11 1 +.names 262 34920 +0 1 +.names 8144 34920 34921 +11 1 +.names 8183 5967 34922 +11 1 +.names 34922 34923 +1 1 +.names 34923 34924 +0 1 +.names 34940 34941 34925 +1- 1 +-1 1 +.names 34925 34926 +1 1 +.names 34926 34927 +0 1 +.names 8156 34931 34928 +1- 1 +-1 1 +.names 34928 34929 +1 1 +.names 2413 34930 +1 1 +.names 34930 34931 +0 1 +.names 34945 34946 34932 +1- 1 +-1 1 +.names 34932 34933 +1 1 +.names 34933 34934 +0 1 +.names 34929 34935 +0 1 +.names 34938 8170 34936 +1- 1 +-1 1 +.names 34936 34937 +1 1 +.names 5895 34938 +0 1 +.names 33896 34939 +1 1 +.names 8174 56589 34940 +11 1 +.names 34937 34941 +0 1 +.names 34018 34942 +1 1 +.names 34942 34943 +0 1 +.names 34939 34944 +0 1 +.names 34943 34944 34945 +1- 1 +-1 1 +.names 6031 34946 +0 1 +.names 34098 33161 34947 +1- 1 +-1 1 +.names 34947 34948 +1 1 +.names 34957 34960 34949 +1- 1 +-1 1 +.names 34949 34950 +1 1 +.names 34964 34966 34951 +1- 1 +-1 1 +.names 34951 34952 +1 1 +.names 34952 34953 +0 1 +.names 2413 34954 +1 1 +.names 34954 34955 +1 1 +.names 34955 34956 +0 1 +.names 34953 34956 34957 +1- 1 +-1 1 +.names 34985 34980 34958 +11 1 +.names 34958 34959 +1 1 +.names 34959 34960 +0 1 +.names 34977 34978 34961 +11 1 +.names 34961 34962 +1 1 +.names 34962 34963 +0 1 +.names 34122 34963 34964 +11 1 +.names 263 34965 +0 1 +.names 8142 34965 34966 +11 1 +.names 34971 34972 34967 +1- 1 +-1 1 +.names 34967 34968 +1 1 +.names 34098 34969 +1 1 +.names 34969 34970 +0 1 +.names 8179 34970 34971 +1- 1 +-1 1 +.names 6033 34972 +0 1 +.names 8184 34976 34973 +1- 1 +-1 1 +.names 34973 34974 +1 1 +.names 2413 34975 +1 1 +.names 34975 34976 +0 1 +.names 34968 34977 +0 1 +.names 34974 34978 +0 1 +.names 34981 34007 34979 +1- 1 +-1 1 +.names 34979 34980 +1 1 +.names 5899 34981 +0 1 +.names 33927 34984 34982 +1- 1 +-1 1 +.names 34982 34983 +1 1 +.names 5969 34984 +0 1 +.names 34983 34948 34985 +11 1 +.names 34016 22359 34986 +1- 1 +-1 1 +.names 34986 34987 +1 1 +.names 34993 34995 34988 +1- 1 +-1 1 +.names 34988 34989 +1 1 +.names 35002 35003 34990 +11 1 +.names 34990 34991 +1 1 +.names 34991 34992 +0 1 +.names 33989 34992 34993 +11 1 +.names 239 34994 +0 1 +.names 8180 34994 34995 +11 1 +.names 8183 34999 34996 +1- 1 +-1 1 +.names 34996 34997 +1 1 +.names 2413 34998 +1 1 +.names 34998 34999 +0 1 +.names 35009 35010 35000 +1- 1 +-1 1 +.names 35000 35001 +1 1 +.names 35001 35002 +0 1 +.names 34997 35003 +0 1 +.names 35006 33969 35004 +1- 1 +-1 1 +.names 35004 35005 +1 1 +.names 5803 35006 +0 1 +.names 34016 35007 +1 1 +.names 35007 35008 +0 1 +.names 8159 35008 35009 +1- 1 +-1 1 +.names 5985 35010 +0 1 +.names 35017 35018 35011 +1- 1 +-1 1 +.names 35011 35012 +1 1 +.names 34987 35013 +0 1 +.names 34018 35029 35014 +1- 1 +-1 1 +.names 35014 35015 +1 1 +.names 35015 35016 +0 1 +.names 35013 35016 35017 +1- 1 +-1 1 +.names 35005 35018 +0 1 +.names 35021 35024 35019 +1- 1 +-1 1 +.names 35019 35020 +1 1 +.names 34989 35021 +0 1 +.names 35027 35028 35022 +11 1 +.names 35022 35023 +1 1 +.names 35023 35024 +0 1 +.names 1783 35025 +1 1 +.names 35025 35026 +1 1 +.names 35012 35027 +0 1 +.names 35026 35028 +0 1 +.names 5921 35029 +0 1 +.names 35038 35041 35030 +1- 1 +-1 1 +.names 35030 35031 +1 1 +.names 35045 35047 35032 +1- 1 +-1 1 +.names 35032 35033 +1 1 +.names 35033 35034 +0 1 +.names 35070 8170 35035 +1- 1 +-1 1 +.names 35035 35036 +1 1 +.names 35036 35037 +0 1 +.names 35034 35037 35038 +1- 1 +-1 1 +.names 35050 35053 35039 +11 1 +.names 35039 35040 +1 1 +.names 35040 35041 +0 1 +.names 35068 35069 35042 +11 1 +.names 35042 35043 +1 1 +.names 35043 35044 +0 1 +.names 34398 35044 35045 +11 1 +.names 5923 35046 +0 1 +.names 8161 35046 35047 +11 1 +.names 240 8173 35048 +11 1 +.names 35048 35049 +1 1 +.names 35049 35050 +0 1 +.names 35054 35057 35051 +1- 1 +-1 1 +.names 35051 35052 +1 1 +.names 35052 35053 +0 1 +.names 8153 56567 35054 +11 1 +.names 2413 35055 +1 1 +.names 35055 35056 +1 1 +.names 35056 35057 +0 1 +.names 35062 35063 35058 +1- 1 +-1 1 +.names 35058 35059 +1 1 +.names 2413 35060 +1 1 +.names 35060 35061 +0 1 +.names 8173 35061 35062 +1- 1 +-1 1 +.names 5987 35063 +0 1 +.names 8156 35067 35064 +1- 1 +-1 1 +.names 35064 35065 +1 1 +.names 34016 35066 +1 1 +.names 35066 35067 +0 1 +.names 35059 35068 +0 1 +.names 35065 35069 +0 1 +.names 5807 35070 +0 1 +.names 35079 35082 35071 +1- 1 +-1 1 +.names 35071 35072 +1 1 +.names 35086 35087 35073 +1- 1 +-1 1 +.names 35073 35074 +1 1 +.names 35074 35075 +0 1 +.names 2413 35076 +1 1 +.names 35076 35077 +1 1 +.names 35077 35078 +0 1 +.names 35075 35078 35079 +1- 1 +-1 1 +.names 35108 35101 35080 +11 1 +.names 35080 35081 +1 1 +.names 35081 35082 +0 1 +.names 35098 35099 35083 +11 1 +.names 35083 35084 +1 1 +.names 35084 35085 +0 1 +.names 33989 35085 35086 +11 1 +.names 8180 20312 35087 +11 1 +.names 35092 35093 35088 +1- 1 +-1 1 +.names 35088 35089 +1 1 +.names 33896 35090 +1 1 +.names 35090 35091 +0 1 +.names 8179 35091 35092 +1- 1 +-1 1 +.names 6009 35093 +0 1 +.names 8184 35097 35094 +1- 1 +-1 1 +.names 35094 35095 +1 1 +.names 2413 35096 +1 1 +.names 35096 35097 +0 1 +.names 35089 35098 +0 1 +.names 35095 35099 +0 1 +.names 35102 34007 35100 +1- 1 +-1 1 +.names 35100 35101 +1 1 +.names 5851 35102 +0 1 +.names 33896 33274 35103 +1- 1 +-1 1 +.names 35103 35104 +1 1 +.names 33927 35107 35105 +1- 1 +-1 1 +.names 35105 35106 +1 1 +.names 5945 35107 +0 1 +.names 35106 35104 35108 +11 1 +.names 33852 33316 35109 +1- 1 +-1 1 +.names 35109 35110 +1 1 +.names 35113 8170 35111 +1- 1 +-1 1 +.names 35111 35112 +1 1 +.names 5871 35113 +0 1 +.names 35118 35119 35114 +1- 1 +-1 1 +.names 35114 35115 +1 1 +.names 33852 35116 +1 1 +.names 35116 35117 +0 1 +.names 8156 35117 35118 +1- 1 +-1 1 +.names 6019 35119 +0 1 +.names 8184 35123 35120 +1- 1 +-1 1 +.names 35120 35121 +1 1 +.names 2413 35122 +1 1 +.names 35122 35123 +0 1 +.names 35129 35131 35124 +1- 1 +-1 1 +.names 35124 35125 +1 1 +.names 35132 35133 35126 +11 1 +.names 35126 35127 +1 1 +.names 35127 35128 +0 1 +.names 33989 35128 35129 +11 1 +.names 256 35130 +0 1 +.names 8180 35130 35131 +11 1 +.names 35115 35132 +0 1 +.names 35121 35133 +0 1 +.names 35140 35141 35134 +1- 1 +-1 1 +.names 35134 35135 +1 1 +.names 33927 35152 35136 +1- 1 +-1 1 +.names 35136 35137 +1 1 +.names 35137 35138 +0 1 +.names 35110 35139 +0 1 +.names 35138 35139 35140 +1- 1 +-1 1 +.names 35112 35141 +0 1 +.names 35144 35147 35142 +11 1 +.names 35142 35143 +1 1 +.names 35135 35144 +0 1 +.names 1783 35145 +1 1 +.names 35145 35146 +1 1 +.names 35146 35147 +0 1 +.names 35150 35151 35148 +1- 1 +-1 1 +.names 35148 35149 +1 1 +.names 35125 35150 +0 1 +.names 35143 35151 +0 1 +.names 5955 35152 +0 1 +.names 35161 35164 35153 +1- 1 +-1 1 +.names 35153 35154 +1 1 +.names 35168 35170 35155 +1- 1 +-1 1 +.names 35155 35156 +1 1 +.names 35156 35157 +0 1 +.names 2413 35158 +1 1 +.names 35158 35159 +1 1 +.names 35159 35160 +0 1 +.names 35157 35160 35161 +1- 1 +-1 1 +.names 35173 35176 35162 +11 1 +.names 35162 35163 +1 1 +.names 35163 35164 +0 1 +.names 35183 35184 35165 +11 1 +.names 35165 35166 +1 1 +.names 35166 35167 +0 1 +.names 33989 35167 35168 +11 1 +.names 265 35169 +0 1 +.names 8180 35169 35170 +11 1 +.names 8182 5973 35171 +11 1 +.names 35171 35172 +1 1 +.names 35172 35173 +0 1 +.names 35192 35193 35174 +1- 1 +-1 1 +.names 35174 35175 +1 1 +.names 35175 35176 +0 1 +.names 8179 35180 35177 +1- 1 +-1 1 +.names 35177 35178 +1 1 +.names 2413 35179 +1 1 +.names 35179 35180 +0 1 +.names 35190 35191 35181 +1- 1 +-1 1 +.names 35181 35182 +1 1 +.names 35182 35183 +0 1 +.names 35178 35184 +0 1 +.names 35187 34007 35185 +1- 1 +-1 1 +.names 35185 35186 +1 1 +.names 5906 35187 +0 1 +.names 33896 35188 +1 1 +.names 35188 35189 +0 1 +.names 8182 35189 35190 +1- 1 +-1 1 +.names 6037 35191 +0 1 +.names 8174 56592 35192 +11 1 +.names 35186 35193 +0 1 +.names 35196 33274 35194 +1- 1 +-1 1 +.names 35194 35195 +1 1 +.names 8196 35196 +0 1 +.names 2413 35199 35197 +1- 1 +-1 1 +.names 35197 35198 +1 1 +.names 8217 35199 +0 1 +.names 35206 35209 35200 +1- 1 +-1 1 +.names 35200 35201 +1 1 +.names 35213 35214 35202 +1- 1 +-1 1 +.names 35202 35203 +1 1 +.names 35203 35204 +0 1 +.names 35198 35205 +0 1 +.names 35204 35205 35206 +1- 1 +-1 1 +.names 35217 35219 35207 +11 1 +.names 35207 35208 +1 1 +.names 35208 35209 +0 1 +.names 35232 35233 35210 +11 1 +.names 35210 35211 +1 1 +.names 35211 35212 +0 1 +.names 2413 35212 35213 +11 1 +.names 1783 2413 35214 +11 1 +.names 8206 5787 35215 +1- 1 +-1 1 +.names 35215 35216 +1 1 +.names 35216 35195 35217 +11 1 +.names 8214 32680 35218 +1- 1 +-1 1 +.names 35218 35219 +1 1 +.names 35224 35227 35220 +1- 1 +-1 1 +.names 35220 35221 +1 1 +.names 35196 35222 +1 1 +.names 35222 35223 +0 1 +.names 8217 35223 35224 +1- 1 +-1 1 +.names 39175 39176 35225 +1- 1 +-1 1 +.names 35225 35226 +1 1 +.names 35226 35227 +0 1 +.names 8219 35231 35228 +1- 1 +-1 1 +.names 35228 35229 +1 1 +.names 8214 35230 +1 1 +.names 35230 35231 +0 1 +.names 35221 35232 +0 1 +.names 35229 35233 +0 1 +.names 32189 35199 35234 +1- 1 +-1 1 +.names 35234 35235 +1 1 +.names 35242 35243 35236 +1- 1 +-1 1 +.names 35236 35237 +1 1 +.names 8218 35238 +0 1 +.names 35253 35254 35239 +11 1 +.names 35239 35240 +1 1 +.names 35240 35241 +0 1 +.names 35238 35241 35242 +11 1 +.names 8218 32189 35243 +11 1 +.names 35248 32189 35244 +1- 1 +-1 1 +.names 35244 35245 +1 1 +.names 8214 35246 +1 1 +.names 35246 35247 +0 1 +.names 8228 35247 35248 +1- 1 +-1 1 +.names 8217 35252 35249 +1- 1 +-1 1 +.names 35249 35250 +1 1 +.names 2413 35251 +1 1 +.names 35251 35252 +0 1 +.names 35245 35253 +0 1 +.names 35250 35254 +0 1 +.names 35258 35259 35255 +1- 1 +-1 1 +.names 35255 35256 +1 1 +.names 35271 35272 35257 +1- 1 +-1 1 +.names 35257 35258 +1 1 +.names 35237 35259 +0 1 +.names 8214 32189 35260 +1- 1 +-1 1 +.names 35260 35261 +1 1 +.names 2413 35262 +1 1 +.names 35262 35263 +1 1 +.names 5787 35266 35264 +1- 1 +-1 1 +.names 35264 35265 +1 1 +.names 8228 35266 +0 1 +.names 35263 35267 +0 1 +.names 35265 35268 +0 1 +.names 35267 35268 35269 +1- 1 +-1 1 +.names 35261 35270 +0 1 +.names 35269 35270 35271 +1- 1 +-1 1 +.names 35235 35272 +0 1 +.names 35281 35284 35273 +1- 1 +-1 1 +.names 35273 35274 +1 1 +.names 35289 35290 35275 +1- 1 +-1 1 +.names 35275 35276 +1 1 +.names 35276 35277 +0 1 +.names 2413 35278 +1 1 +.names 35278 35279 +1 1 +.names 35279 35280 +0 1 +.names 35277 35280 35281 +1- 1 +-1 1 +.names 35295 35297 35282 +11 1 +.names 35282 35283 +1 1 +.names 35283 35284 +0 1 +.names 8188 35285 +0 1 +.names 35304 35305 35286 +11 1 +.names 35286 35287 +1 1 +.names 35287 35288 +0 1 +.names 35285 35288 35289 +11 1 +.names 8188 22288 35290 +11 1 +.names 35238 22288 35291 +1- 1 +-1 1 +.names 35291 35292 +1 1 +.names 8206 5787 35293 +1- 1 +-1 1 +.names 35293 35294 +1 1 +.names 35292 35294 35295 +11 1 +.names 22288 35306 35296 +1- 1 +-1 1 +.names 35296 35297 +1 1 +.names 8219 35301 35298 +1- 1 +-1 1 +.names 35298 35299 +1 1 +.names 2413 35300 +1 1 +.names 35300 35301 +0 1 +.names 35311 22288 35302 +1- 1 +-1 1 +.names 35302 35303 +1 1 +.names 35303 35304 +0 1 +.names 35299 35305 +0 1 +.names 8203 35306 +0 1 +.names 35306 35307 +1 1 +.names 35307 35308 +0 1 +.names 35238 35309 +1 1 +.names 35309 35310 +0 1 +.names 35308 35310 35311 +1- 1 +-1 1 +.names 35320 35323 35312 +1- 1 +-1 1 +.names 35312 35313 +1 1 +.names 35328 35330 35314 +1- 1 +-1 1 +.names 35314 35315 +1 1 +.names 35315 35316 +0 1 +.names 2413 35317 +1 1 +.names 35317 35318 +1 1 +.names 35318 35319 +0 1 +.names 35316 35319 35320 +1- 1 +-1 1 +.names 35348 35349 35321 +11 1 +.names 35321 35322 +1 1 +.names 35322 35323 +0 1 +.names 8224 35324 +0 1 +.names 35337 35338 35325 +11 1 +.names 35325 35326 +1 1 +.names 35326 35327 +0 1 +.names 35324 35327 35328 +11 1 +.names 56571 35329 +0 1 +.names 8224 35329 35330 +11 1 +.names 8223 35334 35331 +1- 1 +-1 1 +.names 35331 35332 +1 1 +.names 2413 35333 +1 1 +.names 35333 35334 +0 1 +.names 35356 35329 35335 +1- 1 +-1 1 +.names 35335 35336 +1 1 +.names 35336 35337 +0 1 +.names 35332 35338 +0 1 +.names 32680 35341 35339 +1- 1 +-1 1 +.names 35339 35340 +1 1 +.names 8223 35341 +0 1 +.names 35344 35345 35342 +1- 1 +-1 1 +.names 35342 35343 +1 1 +.names 56571 8197 35344 +11 1 +.names 35340 35345 +0 1 +.names 8227 56594 35346 +11 1 +.names 35346 35347 +1 1 +.names 35347 35348 +0 1 +.names 35343 35349 +0 1 +.names 8197 35350 +0 1 +.names 35350 35351 +1 1 +.names 8227 35352 +0 1 +.names 35352 35353 +1 1 +.names 35353 35354 +0 1 +.names 35351 35355 +0 1 +.names 35354 35355 35356 +1- 1 +-1 1 +.names 35350 32320 35357 +1- 1 +-1 1 +.names 35357 35358 +1 1 +.names 32680 8214 35359 +1- 1 +-1 1 +.names 35359 35360 +1 1 +.names 8226 35364 35361 +1- 1 +-1 1 +.names 35361 35362 +1 1 +.names 2413 35363 +1 1 +.names 35363 35364 +0 1 +.names 35370 35371 35365 +1- 1 +-1 1 +.names 35365 35366 +1 1 +.names 35374 35375 35367 +11 1 +.names 35367 35368 +1 1 +.names 35368 35369 +0 1 +.names 35324 35369 35370 +11 1 +.names 8224 32320 35371 +11 1 +.names 35378 32320 35372 +1- 1 +-1 1 +.names 35372 35373 +1 1 +.names 35373 35374 +0 1 +.names 35362 35375 +0 1 +.names 35350 35376 +1 1 +.names 35376 35377 +0 1 +.names 8200 35377 35378 +1- 1 +-1 1 +.names 35385 35386 35379 +1- 1 +-1 1 +.names 35379 35380 +1 1 +.names 35358 35381 +0 1 +.names 35397 5787 35382 +1- 1 +-1 1 +.names 35382 35383 +1 1 +.names 35383 35384 +0 1 +.names 35381 35384 35385 +1- 1 +-1 1 +.names 35360 35386 +0 1 +.names 35389 35392 35387 +11 1 +.names 35387 35388 +1 1 +.names 35380 35389 +0 1 +.names 1783 35390 +1 1 +.names 35390 35391 +1 1 +.names 35391 35392 +0 1 +.names 35395 35396 35393 +1- 1 +-1 1 +.names 35393 35394 +1 1 +.names 35366 35395 +0 1 +.names 35388 35396 +0 1 +.names 8226 35397 +0 1 +.names 35406 35409 35398 +1- 1 +-1 1 +.names 35398 35399 +1 1 +.names 35414 35415 35400 +1- 1 +-1 1 +.names 35400 35401 +1 1 +.names 35401 35402 +0 1 +.names 2413 35403 +1 1 +.names 35403 35404 +1 1 +.names 35404 35405 +0 1 +.names 35402 35405 35406 +1- 1 +-1 1 +.names 35437 35434 35407 +11 1 +.names 35407 35408 +1 1 +.names 35408 35409 +0 1 +.names 8213 35410 +0 1 +.names 35429 35430 35411 +11 1 +.names 35411 35412 +1 1 +.names 35412 35413 +0 1 +.names 35410 35413 35414 +11 1 +.names 8213 32680 35415 +11 1 +.names 8217 35420 35416 +1- 1 +-1 1 +.names 35416 35417 +1 1 +.names 39197 39200 35418 +1- 1 +-1 1 +.names 35418 35419 +1 1 +.names 35419 35420 +0 1 +.names 35425 35427 35421 +1- 1 +-1 1 +.names 35421 35422 +1 1 +.names 35428 2413 35423 +11 1 +.names 35423 35424 +1 1 +.names 35424 35425 +0 1 +.names 35266 35426 +1 1 +.names 35426 35427 +0 1 +.names 8198 35428 +0 1 +.names 35422 35429 +0 1 +.names 35417 35430 +0 1 +.names 35428 33274 35431 +1- 1 +-1 1 +.names 35431 35432 +1 1 +.names 2413 35199 35433 +1- 1 +-1 1 +.names 35433 35434 +1 1 +.names 35266 5787 35435 +1- 1 +-1 1 +.names 35435 35436 +1 1 +.names 35436 35432 35437 +11 1 +.names 35446 35449 35438 +1- 1 +-1 1 +.names 35438 35439 +1 1 +.names 35454 35455 35440 +1- 1 +-1 1 +.names 35440 35441 +1 1 +.names 35441 35442 +0 1 +.names 2413 35443 +1 1 +.names 35443 35444 +1 1 +.names 35444 35445 +0 1 +.names 35442 35445 35446 +1- 1 +-1 1 +.names 35478 35479 35447 +11 1 +.names 35447 35448 +1 1 +.names 35448 35449 +0 1 +.names 8186 35450 +0 1 +.names 35474 35475 35451 +11 1 +.names 35451 35452 +1 1 +.names 35452 35453 +0 1 +.names 35450 35453 35454 +11 1 +.names 8186 2413 35455 +11 1 +.names 35458 35461 35456 +1- 1 +-1 1 +.names 35456 35457 +1 1 +.names 8196 56578 35458 +11 1 +.names 5787 35352 35459 +1- 1 +-1 1 +.names 35459 35460 +1 1 +.names 35460 35461 +0 1 +.names 35466 35469 35462 +1- 1 +-1 1 +.names 35462 35463 +1 1 +.names 35196 35464 +1 1 +.names 35464 35465 +0 1 +.names 8222 35465 35466 +1- 1 +-1 1 +.names 39961 39964 35467 +1- 1 +-1 1 +.names 35467 35468 +1 1 +.names 35468 35469 +0 1 +.names 8227 35473 35470 +1- 1 +-1 1 +.names 35470 35471 +1 1 +.names 2413 35472 +1 1 +.names 35472 35473 +0 1 +.names 35463 35474 +0 1 +.names 35471 35475 +0 1 +.names 56570 8222 35476 +11 1 +.names 35476 35477 +1 1 +.names 35477 35478 +0 1 +.names 35457 35479 +0 1 +.names 35488 35491 35480 +1- 1 +-1 1 +.names 35480 35481 +1 1 +.names 35495 35496 35482 +1- 1 +-1 1 +.names 35482 35483 +1 1 +.names 35483 35484 +0 1 +.names 2413 35485 +1 1 +.names 35485 35486 +1 1 +.names 35486 35487 +0 1 +.names 35484 35487 35488 +1- 1 +-1 1 +.names 35501 35503 35489 +11 1 +.names 35489 35490 +1 1 +.names 35490 35491 +0 1 +.names 35516 35517 35492 +11 1 +.names 35492 35493 +1 1 +.names 35493 35494 +0 1 +.names 35324 35494 35495 +11 1 +.names 8224 2413 35496 +11 1 +.names 35238 33274 35497 +1- 1 +-1 1 +.names 35497 35498 +1 1 +.names 8206 5787 35499 +1- 1 +-1 1 +.names 35499 35500 +1 1 +.names 35498 35500 35501 +11 1 +.names 32680 35518 35502 +1- 1 +-1 1 +.names 35502 35503 +1 1 +.names 35508 35511 35504 +1- 1 +-1 1 +.names 35504 35505 +1 1 +.names 35238 35506 +1 1 +.names 35506 35507 +0 1 +.names 8222 35507 35508 +1- 1 +-1 1 +.names 40174 40177 35509 +1- 1 +-1 1 +.names 35509 35510 +1 1 +.names 35510 35511 +0 1 +.names 8219 35515 35512 +1- 1 +-1 1 +.names 35512 35513 +1 1 +.names 2413 35514 +1 1 +.names 35514 35515 +0 1 +.names 35513 35516 +0 1 +.names 35505 35517 +0 1 +.names 8222 35518 +0 1 +.names 35524 35525 35519 +1- 1 +-1 1 +.names 35519 35520 +1 1 +.names 35532 35533 35521 +11 1 +.names 35521 35522 +1 1 +.names 35522 35523 +0 1 +.names 35324 35523 35524 +11 1 +.names 8224 32474 35525 +11 1 +.names 1783 35529 35526 +1- 1 +-1 1 +.names 35526 35527 +1 1 +.names 35352 35528 +1 1 +.names 35528 35529 +0 1 +.names 35538 32474 35530 +1- 1 +-1 1 +.names 35530 35531 +1 1 +.names 35531 35532 +0 1 +.names 35527 35533 +0 1 +.names 32680 35306 35534 +1- 1 +-1 1 +.names 35534 35535 +1 1 +.names 35238 35536 +1 1 +.names 35536 35537 +0 1 +.names 8203 35537 35538 +1- 1 +-1 1 +.names 35547 35548 35539 +1- 1 +-1 1 +.names 35539 35540 +1 1 +.names 35238 32474 35541 +1- 1 +-1 1 +.names 35541 35542 +1 1 +.names 35542 35543 +0 1 +.names 35352 5787 35544 +1- 1 +-1 1 +.names 35544 35545 +1 1 +.names 35545 35546 +0 1 +.names 35543 35546 35547 +1- 1 +-1 1 +.names 35535 35548 +0 1 +.names 35551 35554 35549 +1- 1 +-1 1 +.names 35549 35550 +1 1 +.names 35520 35551 +0 1 +.names 35557 35558 35552 +11 1 +.names 35552 35553 +1 1 +.names 35553 35554 +0 1 +.names 1783 35555 +1 1 +.names 35555 35556 +1 1 +.names 35540 35557 +0 1 +.names 35556 35558 +0 1 +.names 35567 35570 35559 +1- 1 +-1 1 +.names 35559 35560 +1 1 +.names 35574 35575 35561 +1- 1 +-1 1 +.names 35561 35562 +1 1 +.names 35562 35563 +0 1 +.names 2413 35564 +1 1 +.names 35564 35565 +1 1 +.names 35565 35566 +0 1 +.names 35563 35566 35567 +1- 1 +-1 1 +.names 35596 35591 35568 +11 1 +.names 35568 35569 +1 1 +.names 35569 35570 +0 1 +.names 35588 35589 35571 +11 1 +.names 35571 35572 +1 1 +.names 35572 35573 +0 1 +.names 35324 35573 35574 +11 1 +.names 8224 2413 35575 +11 1 +.names 35580 35583 35576 +1- 1 +-1 1 +.names 35576 35577 +1 1 +.names 35196 35578 +1 1 +.names 35578 35579 +0 1 +.names 8222 35579 35580 +1- 1 +-1 1 +.names 39460 39463 35581 +1- 1 +-1 1 +.names 35581 35582 +1 1 +.names 35582 35583 +0 1 +.names 8228 35587 35584 +1- 1 +-1 1 +.names 35584 35585 +1 1 +.names 2413 35586 +1 1 +.names 35586 35587 +0 1 +.names 35577 35588 +0 1 +.names 35585 35589 +0 1 +.names 32680 35518 35590 +1- 1 +-1 1 +.names 35590 35591 +1 1 +.names 35196 33274 35592 +1- 1 +-1 1 +.names 35592 35593 +1 1 +.names 35266 5787 35594 +1- 1 +-1 1 +.names 35594 35595 +1 1 +.names 35595 35593 35596 +11 1 +.names 35605 35608 35597 +1- 1 +-1 1 +.names 35597 35598 +1 1 +.names 35612 35613 35599 +1- 1 +-1 1 +.names 35599 35600 +1 1 +.names 35600 35601 +0 1 +.names 2413 35602 +1 1 +.names 35602 35603 +1 1 +.names 35603 35604 +0 1 +.names 35601 35604 35605 +1- 1 +-1 1 +.names 35618 35620 35606 +11 1 +.names 35606 35607 +1 1 +.names 35607 35608 +0 1 +.names 35630 35631 35609 +11 1 +.names 35609 35610 +1 1 +.names 35610 35611 +0 1 +.names 35450 35611 35612 +11 1 +.names 8186 32545 35613 +11 1 +.names 35196 32545 35614 +1- 1 +-1 1 +.names 35614 35615 +1 1 +.names 8206 5787 35616 +1- 1 +-1 1 +.names 35616 35617 +1 1 +.names 35615 35617 35618 +11 1 +.names 32680 8214 35619 +1- 1 +-1 1 +.names 35619 35620 +1 1 +.names 8200 32545 35621 +1- 1 +-1 1 +.names 35621 35622 +1 1 +.names 35627 35629 35623 +1- 1 +-1 1 +.names 35623 35624 +1 1 +.names 35196 2413 35625 +11 1 +.names 35625 35626 +1 1 +.names 35626 35627 +0 1 +.names 8206 35628 +1 1 +.names 35628 35629 +0 1 +.names 35624 35630 +0 1 +.names 35622 35631 +0 1 +.names 33274 35196 35632 +1- 1 +-1 1 +.names 35632 35633 +1 1 +.names 35642 35645 35634 +1- 1 +-1 1 +.names 35634 35635 +1 1 +.names 35649 35650 35636 +1- 1 +-1 1 +.names 35636 35637 +1 1 +.names 35637 35638 +0 1 +.names 2413 35639 +1 1 +.names 35639 35640 +1 1 +.names 35640 35641 +0 1 +.names 35638 35641 35642 +1- 1 +-1 1 +.names 35671 35672 35643 +11 1 +.names 35643 35644 +1 1 +.names 35644 35645 +0 1 +.names 35667 35668 35646 +11 1 +.names 35646 35647 +1 1 +.names 35647 35648 +0 1 +.names 35450 35648 35649 +11 1 +.names 8186 2413 35650 +11 1 +.names 35653 35654 35651 +1- 1 +-1 1 +.names 35651 35652 +1 1 +.names 8227 56594 35653 +11 1 +.names 35633 35654 +0 1 +.names 35659 35662 35655 +1- 1 +-1 1 +.names 35655 35656 +1 1 +.names 35196 35657 +1 1 +.names 35657 35658 +0 1 +.names 8222 35658 35659 +1- 1 +-1 1 +.names 39237 39240 35660 +1- 1 +-1 1 +.names 35660 35661 +1 1 +.names 35661 35662 +0 1 +.names 8227 35666 35663 +1- 1 +-1 1 +.names 35663 35664 +1 1 +.names 2413 35665 +1 1 +.names 35665 35666 +0 1 +.names 35656 35667 +0 1 +.names 35664 35668 +0 1 +.names 56570 8222 35669 +11 1 +.names 35669 35670 +1 1 +.names 35670 35671 +0 1 +.names 35652 35672 +0 1 +.names 35681 35684 35673 +1- 1 +-1 1 +.names 35673 35674 +1 1 +.names 35688 35689 35675 +1- 1 +-1 1 +.names 35675 35676 +1 1 +.names 35676 35677 +0 1 +.names 2413 35678 +1 1 +.names 35678 35679 +1 1 +.names 35679 35680 +0 1 +.names 35677 35680 35681 +1- 1 +-1 1 +.names 35709 35710 35682 +11 1 +.names 35682 35683 +1 1 +.names 35683 35684 +0 1 +.names 35699 35700 35685 +11 1 +.names 35685 35686 +1 1 +.names 35686 35687 +0 1 +.names 35285 35687 35688 +11 1 +.names 8188 22306 35689 +11 1 +.names 35694 22306 35690 +1- 1 +-1 1 +.names 35690 35691 +1 1 +.names 35350 35692 +1 1 +.names 35692 35693 +0 1 +.names 8226 35693 35694 +1- 1 +-1 1 +.names 8200 35698 35695 +1- 1 +-1 1 +.names 35695 35696 +1 1 +.names 2413 35697 +1 1 +.names 35697 35698 +0 1 +.names 35691 35699 +0 1 +.names 35696 35700 +0 1 +.names 22306 8214 35701 +1- 1 +-1 1 +.names 35701 35702 +1 1 +.names 35705 35706 35703 +1- 1 +-1 1 +.names 35703 35704 +1 1 +.names 8197 56563 35705 +11 1 +.names 35702 35706 +0 1 +.names 8226 56594 35707 +11 1 +.names 35707 35708 +1 1 +.names 35708 35709 +0 1 +.names 35704 35710 +0 1 +.names 35717 35718 35711 +1- 1 +-1 1 +.names 35711 35712 +1 1 +.names 8205 35713 +0 1 +.names 35731 35732 35714 +11 1 +.names 35714 35715 +1 1 +.names 35715 35716 +0 1 +.names 35713 35716 35717 +11 1 +.names 8205 5787 35718 +11 1 +.names 8217 35723 35719 +1- 1 +-1 1 +.names 35719 35720 +1 1 +.names 39697 39700 35721 +1- 1 +-1 1 +.names 35721 35722 +1 1 +.names 35722 35723 +0 1 +.names 35728 35730 35724 +1- 1 +-1 1 +.names 35724 35725 +1 1 +.names 35350 2413 35726 +11 1 +.names 35726 35727 +1 1 +.names 35727 35728 +0 1 +.names 8214 35729 +1 1 +.names 35729 35730 +0 1 +.names 35725 35731 +0 1 +.names 35720 35732 +0 1 +.names 35736 35737 35733 +1- 1 +-1 1 +.names 35733 35734 +1 1 +.names 35748 35751 35735 +1- 1 +-1 1 +.names 35735 35736 +1 1 +.names 35712 35737 +0 1 +.names 32680 8214 35738 +1- 1 +-1 1 +.names 35738 35739 +1 1 +.names 35739 35740 +0 1 +.names 2413 35199 35741 +1- 1 +-1 1 +.names 35741 35742 +1 1 +.names 35742 35743 +0 1 +.names 35740 35743 35744 +1- 1 +-1 1 +.names 33274 35350 35745 +1- 1 +-1 1 +.names 35745 35746 +1 1 +.names 35746 35747 +0 1 +.names 35744 35747 35748 +1- 1 +-1 1 +.names 2413 35749 +1 1 +.names 35749 35750 +1 1 +.names 35750 35751 +0 1 +.names 35757 35758 35752 +1- 1 +-1 1 +.names 35752 35753 +1 1 +.names 35768 35769 35754 +11 1 +.names 35754 35755 +1 1 +.names 35755 35756 +0 1 +.names 35450 35756 35757 +11 1 +.names 8186 32680 35758 +11 1 +.names 35763 32680 35759 +1- 1 +-1 1 +.names 35759 35760 +1 1 +.names 35350 35761 +1 1 +.names 35761 35762 +0 1 +.names 8203 35762 35763 +1- 1 +-1 1 +.names 8219 35767 35764 +1- 1 +-1 1 +.names 35764 35765 +1 1 +.names 2413 35766 +1 1 +.names 35766 35767 +0 1 +.names 35760 35768 +0 1 +.names 35765 35769 +0 1 +.names 8206 5787 35770 +1- 1 +-1 1 +.names 35770 35771 +1 1 +.names 32680 35306 35772 +1- 1 +-1 1 +.names 35772 35773 +1 1 +.names 35780 35781 35774 +1- 1 +-1 1 +.names 35774 35775 +1 1 +.names 35771 35776 +0 1 +.names 35350 32680 35777 +1- 1 +-1 1 +.names 35777 35778 +1 1 +.names 35778 35779 +0 1 +.names 35776 35779 35780 +1- 1 +-1 1 +.names 35773 35781 +0 1 +.names 35784 35787 35782 +1- 1 +-1 1 +.names 35782 35783 +1 1 +.names 35753 35784 +0 1 +.names 35788 35791 35785 +11 1 +.names 35785 35786 +1 1 +.names 35786 35787 +0 1 +.names 35775 35788 +0 1 +.names 1783 35789 +1 1 +.names 35789 35790 +1 1 +.names 35790 35791 +0 1 +.names 35800 35803 35792 +1- 1 +-1 1 +.names 35792 35793 +1 1 +.names 35807 35808 35794 +1- 1 +-1 1 +.names 35794 35795 +1 1 +.names 35795 35796 +0 1 +.names 2413 35797 +1 1 +.names 35797 35798 +1 1 +.names 35798 35799 +0 1 +.names 35796 35799 35800 +1- 1 +-1 1 +.names 35811 35814 35801 +11 1 +.names 35801 35802 +1 1 +.names 35802 35803 +0 1 +.names 35821 35822 35804 +11 1 +.names 35804 35805 +1 1 +.names 35805 35806 +0 1 +.names 35450 35806 35807 +11 1 +.names 8186 22325 35808 +11 1 +.names 35826 56594 35809 +11 1 +.names 35809 35810 +1 1 +.names 35810 35811 +0 1 +.names 35828 35829 35812 +1- 1 +-1 1 +.names 35812 35813 +1 1 +.names 35813 35814 +0 1 +.names 8200 35818 35815 +1- 1 +-1 1 +.names 35815 35816 +1 1 +.names 2413 35817 +1 1 +.names 35817 35818 +0 1 +.names 35832 22325 35819 +1- 1 +-1 1 +.names 35819 35820 +1 1 +.names 35820 35821 +0 1 +.names 35816 35822 +0 1 +.names 22325 8214 35823 +1- 1 +-1 1 +.names 35823 35824 +1 1 +.names 35830 35825 +0 1 +.names 35825 35826 +1 1 +.names 35428 35827 +1 1 +.names 8198 56565 35828 +11 1 +.names 35824 35829 +0 1 +.names 35266 35830 +1 1 +.names 35827 35831 +0 1 +.names 35825 35831 35832 +1- 1 +-1 1 +.names 22346 35238 35833 +1- 1 +-1 1 +.names 35833 35834 +1 1 +.names 35843 35846 35835 +1- 1 +-1 1 +.names 35835 35836 +1 1 +.names 35850 35851 35837 +1- 1 +-1 1 +.names 35837 35838 +1 1 +.names 35838 35839 +0 1 +.names 2413 35840 +1 1 +.names 35840 35841 +1 1 +.names 35841 35842 +0 1 +.names 35839 35842 35843 +1- 1 +-1 1 +.names 35854 35857 35844 +11 1 +.names 35844 35845 +1 1 +.names 35845 35846 +0 1 +.names 35862 35865 35847 +11 1 +.names 35847 35848 +1 1 +.names 35848 35849 +0 1 +.names 35285 35849 35850 +11 1 +.names 8188 22346 35851 +11 1 +.names 35867 35852 +0 1 +.names 35852 35853 +1 1 +.names 35853 35854 +0 1 +.names 35873 35874 35855 +1- 1 +-1 1 +.names 35855 35856 +1 1 +.names 35856 35857 +0 1 +.names 8227 35861 35858 +1- 1 +-1 1 +.names 35858 35859 +1 1 +.names 2413 35860 +1 1 +.names 35860 35861 +0 1 +.names 35859 35862 +0 1 +.names 35872 22346 35863 +1- 1 +-1 1 +.names 35863 35864 +1 1 +.names 35864 35865 +0 1 +.names 22346 35306 35866 +1- 1 +-1 1 +.names 35866 35867 +1 1 +.names 35306 35868 +1 1 +.names 35868 35869 +0 1 +.names 35238 35870 +1 1 +.names 35870 35871 +0 1 +.names 35869 35871 35872 +1- 1 +-1 1 +.names 8227 56594 35873 +11 1 +.names 35834 35874 +0 1 +.names 35350 33274 35875 +1- 1 +-1 1 +.names 35875 35876 +1 1 +.names 35882 35883 35877 +1- 1 +-1 1 +.names 35877 35878 +1 1 +.names 35896 35897 35879 +11 1 +.names 35879 35880 +1 1 +.names 35880 35881 +0 1 +.names 35324 35881 35882 +11 1 +.names 8224 2413 35883 +11 1 +.names 35888 35891 35884 +1- 1 +-1 1 +.names 35884 35885 +1 1 +.names 35350 35886 +1 1 +.names 35886 35887 +0 1 +.names 8203 35887 35888 +1- 1 +-1 1 +.names 39583 39586 35889 +1- 1 +-1 1 +.names 35889 35890 +1 1 +.names 35890 35891 +0 1 +.names 8219 35895 35892 +1- 1 +-1 1 +.names 35892 35893 +1 1 +.names 2413 35894 +1 1 +.names 35894 35895 +0 1 +.names 35885 35896 +0 1 +.names 35893 35897 +0 1 +.names 32680 35306 35898 +1- 1 +-1 1 +.names 35898 35899 +1 1 +.names 35906 35907 35900 +1- 1 +-1 1 +.names 35900 35901 +1 1 +.names 35876 35902 +0 1 +.names 8206 5787 35903 +1- 1 +-1 1 +.names 35903 35904 +1 1 +.names 35904 35905 +0 1 +.names 35902 35905 35906 +1- 1 +-1 1 +.names 35899 35907 +0 1 +.names 35910 35913 35908 +1- 1 +-1 1 +.names 35908 35909 +1 1 +.names 35878 35910 +0 1 +.names 35916 35917 35911 +11 1 +.names 35911 35912 +1 1 +.names 35912 35913 +0 1 +.names 1783 35914 +1 1 +.names 35914 35915 +1 1 +.names 35901 35916 +0 1 +.names 35915 35917 +0 1 +.names 35926 35929 35918 +1- 1 +-1 1 +.names 35918 35919 +1 1 +.names 35933 35934 35920 +1- 1 +-1 1 +.names 35920 35921 +1 1 +.names 35921 35922 +0 1 +.names 2413 35923 +1 1 +.names 35923 35924 +1 1 +.names 35924 35925 +0 1 +.names 35922 35925 35926 +1- 1 +-1 1 +.names 35955 35950 35927 +11 1 +.names 35927 35928 +1 1 +.names 35928 35929 +0 1 +.names 35947 35948 35930 +11 1 +.names 35930 35931 +1 1 +.names 35931 35932 +0 1 +.names 35450 35932 35933 +11 1 +.names 8186 2413 35934 +11 1 +.names 35939 35942 35935 +1- 1 +-1 1 +.names 35935 35936 +1 1 +.names 35428 35937 +1 1 +.names 35937 35938 +0 1 +.names 8223 35938 35939 +1- 1 +-1 1 +.names 39683 39686 35940 +1- 1 +-1 1 +.names 35940 35941 +1 1 +.names 35941 35942 +0 1 +.names 8228 35946 35943 +1- 1 +-1 1 +.names 35943 35944 +1 1 +.names 2413 35945 +1 1 +.names 35945 35946 +0 1 +.names 35936 35947 +0 1 +.names 35944 35948 +0 1 +.names 32680 35341 35949 +1- 1 +-1 1 +.names 35949 35950 +1 1 +.names 35428 33274 35951 +1- 1 +-1 1 +.names 35951 35952 +1 1 +.names 35266 5787 35953 +1- 1 +-1 1 +.names 35953 35954 +1 1 +.names 35954 35952 35955 +11 1 +.names 35428 33274 35956 +1- 1 +-1 1 +.names 35956 35957 +1 1 +.names 35966 35969 35958 +1- 1 +-1 1 +.names 35958 35959 +1 1 +.names 35973 35974 35960 +1- 1 +-1 1 +.names 35960 35961 +1 1 +.names 35961 35962 +0 1 +.names 2413 35963 +1 1 +.names 35963 35964 +1 1 +.names 35964 35965 +0 1 +.names 35962 35965 35966 +1- 1 +-1 1 +.names 35977 35979 35967 +11 1 +.names 35967 35968 +1 1 +.names 35968 35969 +0 1 +.names 35992 35993 35970 +11 1 +.names 35970 35971 +1 1 +.names 35971 35972 +0 1 +.names 35285 35972 35973 +11 1 +.names 8188 2413 35974 +11 1 +.names 35397 5787 35975 +1- 1 +-1 1 +.names 35975 35976 +1 1 +.names 35957 35976 35977 +11 1 +.names 32680 35341 35978 +1- 1 +-1 1 +.names 35978 35979 +1 1 +.names 35984 35987 35980 +1- 1 +-1 1 +.names 35980 35981 +1 1 +.names 35428 35982 +1 1 +.names 35982 35983 +0 1 +.names 8223 35983 35984 +1- 1 +-1 1 +.names 40226 40229 35985 +1- 1 +-1 1 +.names 35985 35986 +1 1 +.names 35986 35987 +0 1 +.names 8226 35991 35988 +1- 1 +-1 1 +.names 35988 35989 +1 1 +.names 2413 35990 +1 1 +.names 35990 35991 +0 1 +.names 35981 35992 +0 1 +.names 35989 35993 +0 1 +.names 36002 36005 35994 +1- 1 +-1 1 +.names 35994 35995 +1 1 +.names 36009 36010 35996 +1- 1 +-1 1 +.names 35996 35997 +1 1 +.names 35997 35998 +0 1 +.names 2413 35999 +1 1 +.names 35999 36000 +1 1 +.names 36000 36001 +0 1 +.names 35998 36001 36002 +1- 1 +-1 1 +.names 36015 36017 36003 +11 1 +.names 36003 36004 +1 1 +.names 36004 36005 +0 1 +.names 36030 36031 36006 +11 1 +.names 36006 36007 +1 1 +.names 36007 36008 +0 1 +.names 35324 36008 36009 +11 1 +.names 8224 2413 36010 +11 1 +.names 35428 33274 36011 +1- 1 +-1 1 +.names 36011 36012 +1 1 +.names 35397 5787 36013 +1- 1 +-1 1 +.names 36013 36014 +1 1 +.names 36012 36014 36015 +11 1 +.names 32680 35518 36016 +1- 1 +-1 1 +.names 36016 36017 +1 1 +.names 36022 36025 36018 +1- 1 +-1 1 +.names 36018 36019 +1 1 +.names 35428 36020 +1 1 +.names 36020 36021 +0 1 +.names 8222 36021 36022 +1- 1 +-1 1 +.names 39738 39741 36023 +1- 1 +-1 1 +.names 36023 36024 +1 1 +.names 36024 36025 +0 1 +.names 8226 36029 36026 +1- 1 +-1 1 +.names 36026 36027 +1 1 +.names 2413 36028 +1 1 +.names 36028 36029 +0 1 +.names 36019 36030 +0 1 +.names 36027 36031 +0 1 +.names 35428 32970 36032 +1- 1 +-1 1 +.names 36032 36033 +1 1 +.names 36039 36040 36034 +1- 1 +-1 1 +.names 36034 36035 +1 1 +.names 36050 36051 36036 +11 1 +.names 36036 36037 +1 1 +.names 36037 36038 +0 1 +.names 35324 36038 36039 +11 1 +.names 8224 32970 36040 +11 1 +.names 36045 32970 36041 +1- 1 +-1 1 +.names 36041 36042 +1 1 +.names 35428 36043 +1 1 +.names 36043 36044 +0 1 +.names 8203 36044 36045 +1- 1 +-1 1 +.names 8226 36049 36046 +1- 1 +-1 1 +.names 36046 36047 +1 1 +.names 2413 36048 +1 1 +.names 36048 36049 +0 1 +.names 36042 36050 +0 1 +.names 36047 36051 +0 1 +.names 32680 35306 36052 +1- 1 +-1 1 +.names 36052 36053 +1 1 +.names 36060 36061 36054 +1- 1 +-1 1 +.names 36054 36055 +1 1 +.names 36033 36056 +0 1 +.names 35397 5787 36057 +1- 1 +-1 1 +.names 36057 36058 +1 1 +.names 36058 36059 +0 1 +.names 36056 36059 36060 +1- 1 +-1 1 +.names 36053 36061 +0 1 +.names 36064 36067 36062 +1- 1 +-1 1 +.names 36062 36063 +1 1 +.names 36035 36064 +0 1 +.names 36070 36071 36065 +11 1 +.names 36065 36066 +1 1 +.names 36066 36067 +0 1 +.names 1783 36068 +1 1 +.names 36068 36069 +1 1 +.names 36055 36070 +0 1 +.names 36069 36071 +0 1 +.names 36080 36083 36072 +1- 1 +-1 1 +.names 36072 36073 +1 1 +.names 36087 36088 36074 +1- 1 +-1 1 +.names 36074 36075 +1 1 +.names 36075 36076 +0 1 +.names 2413 36077 +1 1 +.names 36077 36078 +1 1 +.names 36078 36079 +0 1 +.names 36076 36079 36080 +1- 1 +-1 1 +.names 36093 36095 36081 +11 1 +.names 36081 36082 +1 1 +.names 36082 36083 +0 1 +.names 36105 36106 36084 +11 1 +.names 36084 36085 +1 1 +.names 36085 36086 +0 1 +.names 35324 36086 36087 +11 1 +.names 8224 33004 36088 +11 1 +.names 8206 5787 36089 +1- 1 +-1 1 +.names 36089 36090 +1 1 +.names 35196 33004 36091 +1- 1 +-1 1 +.names 36091 36092 +1 1 +.names 36090 36092 36093 +11 1 +.names 32680 35518 36094 +1- 1 +-1 1 +.names 36094 36095 +1 1 +.names 36100 33004 36096 +1- 1 +-1 1 +.names 36096 36097 +1 1 +.names 35196 36098 +1 1 +.names 36098 36099 +0 1 +.names 8222 36099 36100 +1- 1 +-1 1 +.names 1783 36104 36101 +1- 1 +-1 1 +.names 36101 36102 +1 1 +.names 8206 36103 +1 1 +.names 36103 36104 +0 1 +.names 36097 36105 +0 1 +.names 36102 36106 +0 1 +.names 33274 35196 36107 +1- 1 +-1 1 +.names 36107 36108 +1 1 +.names 36117 36120 36109 +1- 1 +-1 1 +.names 36109 36110 +1 1 +.names 36124 36125 36111 +1- 1 +-1 1 +.names 36111 36112 +1 1 +.names 36112 36113 +0 1 +.names 2413 36114 +1 1 +.names 36114 36115 +1 1 +.names 36115 36116 +0 1 +.names 36113 36116 36117 +1- 1 +-1 1 +.names 36128 36131 36118 +11 1 +.names 36118 36119 +1 1 +.names 36119 36120 +0 1 +.names 36144 36145 36121 +11 1 +.names 36121 36122 +1 1 +.names 36122 36123 +0 1 +.names 35285 36123 36124 +11 1 +.names 8188 2413 36125 +11 1 +.names 36149 36126 +0 1 +.names 36126 36127 +1 1 +.names 36127 36128 +0 1 +.names 36146 36147 36129 +1- 1 +-1 1 +.names 36129 36130 +1 1 +.names 36130 36131 +0 1 +.names 36136 36139 36132 +1- 1 +-1 1 +.names 36132 36133 +1 1 +.names 35196 36134 +1 1 +.names 36134 36135 +0 1 +.names 8223 36135 36136 +1- 1 +-1 1 +.names 40060 40063 36137 +1- 1 +-1 1 +.names 36137 36138 +1 1 +.names 36138 36139 +0 1 +.names 8219 36143 36140 +1- 1 +-1 1 +.names 36140 36141 +1 1 +.names 2413 36142 +1 1 +.names 36142 36143 +0 1 +.names 36133 36144 +0 1 +.names 36141 36145 +0 1 +.names 8219 56594 36146 +11 1 +.names 36108 36147 +0 1 +.names 32680 35341 36148 +1- 1 +-1 1 +.names 36148 36149 +1 1 +.names 35428 33087 36150 +1- 1 +-1 1 +.names 36150 36151 +1 1 +.names 36157 36158 36152 +1- 1 +-1 1 +.names 36152 36153 +1 1 +.names 36168 36169 36154 +11 1 +.names 36154 36155 +1 1 +.names 36155 36156 +0 1 +.names 35285 36156 36157 +11 1 +.names 8188 33087 36158 +11 1 +.names 36163 33087 36159 +1- 1 +-1 1 +.names 36159 36160 +1 1 +.names 35428 36161 +1 1 +.names 36161 36162 +0 1 +.names 8203 36162 36163 +1- 1 +-1 1 +.names 8226 36167 36164 +1- 1 +-1 1 +.names 36164 36165 +1 1 +.names 2413 36166 +1 1 +.names 36166 36167 +0 1 +.names 36160 36168 +0 1 +.names 36165 36169 +0 1 +.names 32680 35306 36170 +1- 1 +-1 1 +.names 36170 36171 +1 1 +.names 36178 36179 36172 +1- 1 +-1 1 +.names 36172 36173 +1 1 +.names 36151 36174 +0 1 +.names 35397 5787 36175 +1- 1 +-1 1 +.names 36175 36176 +1 1 +.names 36176 36177 +0 1 +.names 36174 36177 36178 +1- 1 +-1 1 +.names 36171 36179 +0 1 +.names 36182 36185 36180 +1- 1 +-1 1 +.names 36180 36181 +1 1 +.names 36153 36182 +0 1 +.names 36188 36189 36183 +11 1 +.names 36183 36184 +1 1 +.names 36184 36185 +0 1 +.names 1783 36186 +1 1 +.names 36186 36187 +1 1 +.names 36173 36188 +0 1 +.names 36187 36189 +0 1 +.names 36198 36201 36190 +1- 1 +-1 1 +.names 36190 36191 +1 1 +.names 36205 36206 36192 +1- 1 +-1 1 +.names 36192 36193 +1 1 +.names 36193 36194 +0 1 +.names 2413 36195 +1 1 +.names 36195 36196 +1 1 +.names 36196 36197 +0 1 +.names 36194 36197 36198 +1- 1 +-1 1 +.names 36209 36212 36199 +11 1 +.names 36199 36200 +1 1 +.names 36200 36201 +0 1 +.names 36219 36220 36202 +11 1 +.names 36202 36203 +1 1 +.names 36203 36204 +0 1 +.names 35285 36204 36205 +11 1 +.names 8188 2413 36206 +11 1 +.names 8227 56594 36207 +11 1 +.names 36207 36208 +1 1 +.names 36208 36209 +0 1 +.names 36224 36225 36210 +1- 1 +-1 1 +.names 36210 36211 +1 1 +.names 36211 36212 +0 1 +.names 8200 36216 36213 +1- 1 +-1 1 +.names 36213 36214 +1 1 +.names 2413 36215 +1 1 +.names 36215 36216 +0 1 +.names 36229 36232 36217 +1- 1 +-1 1 +.names 36217 36218 +1 1 +.names 36218 36219 +0 1 +.names 36214 36220 +0 1 +.names 32680 8214 36221 +1- 1 +-1 1 +.names 36221 36222 +1 1 +.names 35238 36223 +1 1 +.names 8218 56578 36224 +11 1 +.names 36222 36225 +0 1 +.names 35352 36226 +1 1 +.names 36226 36227 +0 1 +.names 36223 36228 +0 1 +.names 36227 36228 36229 +1- 1 +-1 1 +.names 39311 39312 36230 +1- 1 +-1 1 +.names 36230 36231 +1 1 +.names 36231 36232 +0 1 +.names 35428 33274 36233 +1- 1 +-1 1 +.names 36233 36234 +1 1 +.names 36243 36246 36235 +1- 1 +-1 1 +.names 36235 36236 +1 1 +.names 36250 36251 36237 +1- 1 +-1 1 +.names 36237 36238 +1 1 +.names 36238 36239 +0 1 +.names 2413 36240 +1 1 +.names 36240 36241 +1 1 +.names 36241 36242 +0 1 +.names 36239 36242 36243 +1- 1 +-1 1 +.names 36270 36267 36244 +11 1 +.names 36244 36245 +1 1 +.names 36245 36246 +0 1 +.names 36264 36265 36247 +11 1 +.names 36247 36248 +1 1 +.names 36248 36249 +0 1 +.names 35450 36249 36250 +11 1 +.names 8186 2413 36251 +11 1 +.names 36256 36259 36252 +1- 1 +-1 1 +.names 36252 36253 +1 1 +.names 35428 36254 +1 1 +.names 36254 36255 +0 1 +.names 8223 36255 36256 +1- 1 +-1 1 +.names 39510 39513 36257 +1- 1 +-1 1 +.names 36257 36258 +1 1 +.names 36258 36259 +0 1 +.names 8228 36263 36260 +1- 1 +-1 1 +.names 36260 36261 +1 1 +.names 2413 36262 +1 1 +.names 36262 36263 +0 1 +.names 36253 36264 +0 1 +.names 36261 36265 +0 1 +.names 32680 35341 36266 +1- 1 +-1 1 +.names 36266 36267 +1 1 +.names 35266 5787 36268 +1- 1 +-1 1 +.names 36268 36269 +1 1 +.names 36269 36234 36270 +11 1 +.names 35350 22359 36271 +1- 1 +-1 1 +.names 36271 36272 +1 1 +.names 36278 36279 36273 +1- 1 +-1 1 +.names 36273 36274 +1 1 +.names 36286 36287 36275 +11 1 +.names 36275 36276 +1 1 +.names 36276 36277 +0 1 +.names 35324 36277 36278 +11 1 +.names 8224 22359 36279 +11 1 +.names 8227 36283 36280 +1- 1 +-1 1 +.names 36280 36281 +1 1 +.names 2413 36282 +1 1 +.names 36282 36283 +0 1 +.names 36292 22359 36284 +1- 1 +-1 1 +.names 36284 36285 +1 1 +.names 36285 36286 +0 1 +.names 36281 36287 +0 1 +.names 22359 35306 36288 +1- 1 +-1 1 +.names 36288 36289 +1 1 +.names 35350 36290 +1 1 +.names 36290 36291 +0 1 +.names 8203 36291 36292 +1- 1 +-1 1 +.names 36299 36300 36293 +1- 1 +-1 1 +.names 36293 36294 +1 1 +.names 36272 36295 +0 1 +.names 35352 5787 36296 +1- 1 +-1 1 +.names 36296 36297 +1 1 +.names 36297 36298 +0 1 +.names 36295 36298 36299 +1- 1 +-1 1 +.names 36289 36300 +0 1 +.names 36303 36306 36301 +1- 1 +-1 1 +.names 36301 36302 +1 1 +.names 36274 36303 +0 1 +.names 36309 36310 36304 +11 1 +.names 36304 36305 +1 1 +.names 36305 36306 +0 1 +.names 1783 36307 +1 1 +.names 36307 36308 +1 1 +.names 36294 36309 +0 1 +.names 36308 36310 +0 1 +.names 36319 36322 36311 +1- 1 +-1 1 +.names 36311 36312 +1 1 +.names 36326 36327 36313 +1- 1 +-1 1 +.names 36313 36314 +1 1 +.names 36314 36315 +0 1 +.names 22376 8214 36316 +1- 1 +-1 1 +.names 36316 36317 +1 1 +.names 36317 36318 +0 1 +.names 36315 36318 36319 +1- 1 +-1 1 +.names 36330 36333 36320 +11 1 +.names 36320 36321 +1 1 +.names 36321 36322 +0 1 +.names 36347 36348 36323 +11 1 +.names 36323 36324 +1 1 +.names 36324 36325 +0 1 +.names 35713 36325 36326 +11 1 +.names 8205 5787 36327 +11 1 +.names 56567 8217 36328 +11 1 +.names 36328 36329 +1 1 +.names 36329 36330 +0 1 +.names 36334 36337 36331 +1- 1 +-1 1 +.names 36331 36332 +1 1 +.names 36332 36333 +0 1 +.names 8197 56567 36334 +11 1 +.names 2413 36335 +1 1 +.names 36335 36336 +1 1 +.names 36336 36337 +0 1 +.names 36342 22376 36338 +1- 1 +-1 1 +.names 36338 36339 +1 1 +.names 2413 36340 +1 1 +.names 36340 36341 +0 1 +.names 8217 36341 36342 +1- 1 +-1 1 +.names 8200 36346 36343 +1- 1 +-1 1 +.names 36343 36344 +1 1 +.names 35350 36345 +1 1 +.names 36345 36346 +0 1 +.names 36339 36347 +0 1 +.names 36344 36348 +0 1 +.names 36357 36360 36349 +1- 1 +-1 1 +.names 36349 36350 +1 1 +.names 36364 36365 36351 +1- 1 +-1 1 +.names 36351 36352 +1 1 +.names 36352 36353 +0 1 +.names 2413 36354 +1 1 +.names 36354 36355 +1 1 +.names 36355 36356 +0 1 +.names 36353 36356 36357 +1- 1 +-1 1 +.names 36383 36378 36358 +11 1 +.names 36358 36359 +1 1 +.names 36359 36360 +0 1 +.names 36375 36376 36361 +11 1 +.names 36361 36362 +1 1 +.names 36362 36363 +0 1 +.names 35324 36363 36364 +11 1 +.names 8224 33274 36365 +11 1 +.names 36370 33274 36366 +1- 1 +-1 1 +.names 36366 36367 +1 1 +.names 35238 36368 +1 1 +.names 36368 36369 +0 1 +.names 8223 36369 36370 +1- 1 +-1 1 +.names 8228 36374 36371 +1- 1 +-1 1 +.names 36371 36372 +1 1 +.names 2413 36373 +1 1 +.names 36373 36374 +0 1 +.names 36367 36375 +0 1 +.names 36372 36376 +0 1 +.names 32680 35341 36377 +1- 1 +-1 1 +.names 36377 36378 +1 1 +.names 35238 33274 36379 +1- 1 +-1 1 +.names 36379 36380 +1 1 +.names 35266 5787 36381 +1- 1 +-1 1 +.names 36381 36382 +1 1 +.names 36382 36380 36383 +11 1 +.names 35196 33274 36384 +1- 1 +-1 1 +.names 36384 36385 +1 1 +.names 32680 8214 36386 +1- 1 +-1 1 +.names 36386 36387 +1 1 +.names 36392 36395 36388 +1- 1 +-1 1 +.names 36388 36389 +1 1 +.names 35196 36390 +1 1 +.names 36390 36391 +0 1 +.names 8200 36391 36392 +1- 1 +-1 1 +.names 40189 40192 36393 +1- 1 +-1 1 +.names 36393 36394 +1 1 +.names 36394 36395 +0 1 +.names 8228 36399 36396 +1- 1 +-1 1 +.names 36396 36397 +1 1 +.names 2413 36398 +1 1 +.names 36398 36399 +0 1 +.names 36405 36406 36400 +1- 1 +-1 1 +.names 36400 36401 +1 1 +.names 36407 36408 36402 +11 1 +.names 36402 36403 +1 1 +.names 36403 36404 +0 1 +.names 35324 36404 36405 +11 1 +.names 8224 2413 36406 +11 1 +.names 36389 36407 +0 1 +.names 36397 36408 +0 1 +.names 36415 36416 36409 +1- 1 +-1 1 +.names 36409 36410 +1 1 +.names 35266 5787 36411 +1- 1 +-1 1 +.names 36411 36412 +1 1 +.names 36412 36413 +0 1 +.names 36385 36414 +0 1 +.names 36413 36414 36415 +1- 1 +-1 1 +.names 36387 36416 +0 1 +.names 36419 36422 36417 +11 1 +.names 36417 36418 +1 1 +.names 36410 36419 +0 1 +.names 1783 36420 +1 1 +.names 36420 36421 +1 1 +.names 36421 36422 +0 1 +.names 36425 36426 36423 +1- 1 +-1 1 +.names 36423 36424 +1 1 +.names 36401 36425 +0 1 +.names 36418 36426 +0 1 +.names 36435 36438 36427 +1- 1 +-1 1 +.names 36427 36428 +1 1 +.names 36442 36443 36429 +1- 1 +-1 1 +.names 36429 36430 +1 1 +.names 36430 36431 +0 1 +.names 2413 36432 +1 1 +.names 36432 36433 +1 1 +.names 36433 36434 +0 1 +.names 36431 36434 36435 +1- 1 +-1 1 +.names 36446 36449 36436 +11 1 +.names 36436 36437 +1 1 +.names 36437 36438 +0 1 +.names 36456 36457 36439 +11 1 +.names 36439 36440 +1 1 +.names 36440 36441 +0 1 +.names 35324 36441 36442 +11 1 +.names 8224 2413 36443 +11 1 +.names 8226 56594 36444 +11 1 +.names 36444 36445 +1 1 +.names 36445 36446 +0 1 +.names 36466 36467 36447 +1- 1 +-1 1 +.names 36447 36448 +1 1 +.names 36448 36449 +0 1 +.names 8223 36453 36450 +1- 1 +-1 1 +.names 36450 36451 +1 1 +.names 2413 36452 +1 1 +.names 36452 36453 +0 1 +.names 36462 36465 36454 +1- 1 +-1 1 +.names 36454 36455 +1 1 +.names 36455 36456 +0 1 +.names 36451 36457 +0 1 +.names 32680 35341 36458 +1- 1 +-1 1 +.names 36458 36459 +1 1 +.names 35238 36460 +1 1 +.names 36460 36461 +0 1 +.names 8226 36461 36462 +1- 1 +-1 1 +.names 39946 39949 36463 +1- 1 +-1 1 +.names 36463 36464 +1 1 +.names 36464 36465 +0 1 +.names 8218 56578 36466 +11 1 +.names 36459 36467 +0 1 +.names 36474 36478 36468 +1- 1 +-1 1 +.names 36468 36469 +1 1 +.names 8240 36470 +0 1 +.names 35256 36471 +0 1 +.names 36471 36472 +1 1 +.names 36472 36473 +0 1 +.names 36470 36473 36474 +11 1 +.names 33915 36475 +0 1 +.names 36475 36476 +1 1 +.names 36476 36477 +0 1 +.names 8240 36477 36478 +11 1 +.names 36485 36489 36479 +1- 1 +-1 1 +.names 36479 36480 +1 1 +.names 8234 36481 +0 1 +.names 35201 36482 +0 1 +.names 36482 36483 +1 1 +.names 36483 36484 +0 1 +.names 36481 36484 36485 +11 1 +.names 33858 36486 +0 1 +.names 36486 36487 +1 1 +.names 36487 36488 +0 1 +.names 8234 36488 36489 +11 1 +.names 36495 36499 36490 +1- 1 +-1 1 +.names 36490 36491 +1 1 +.names 35399 36492 +0 1 +.names 36492 36493 +1 1 +.names 36493 36494 +0 1 +.names 36470 36494 36495 +11 1 +.names 34070 36496 +0 1 +.names 36496 36497 +1 1 +.names 36497 36498 +0 1 +.names 8240 36498 36499 +11 1 +.names 36505 36509 36500 +1- 1 +-1 1 +.names 36500 36501 +1 1 +.names 35439 36502 +0 1 +.names 36502 36503 +1 1 +.names 36503 36504 +0 1 +.names 36481 36504 36505 +11 1 +.names 34111 36506 +0 1 +.names 36506 36507 +1 1 +.names 36507 36508 +0 1 +.names 8234 36508 36509 +11 1 +.names 36516 36520 36510 +1- 1 +-1 1 +.names 36510 36511 +1 1 +.names 8235 36512 +0 1 +.names 35674 36513 +0 1 +.names 36513 36514 +1 1 +.names 36514 36515 +0 1 +.names 36512 36515 36516 +11 1 +.names 34356 36517 +0 1 +.names 36517 36518 +1 1 +.names 36518 36519 +0 1 +.names 8235 36519 36520 +11 1 +.names 36527 36531 36521 +1- 1 +-1 1 +.names 36521 36522 +1 1 +.names 8237 36523 +0 1 +.names 35274 36524 +0 1 +.names 36524 36525 +1 1 +.names 36525 36526 +0 1 +.names 36523 36526 36527 +11 1 +.names 33935 36528 +0 1 +.names 36528 36529 +1 1 +.names 36529 36530 +0 1 +.names 8237 36530 36531 +11 1 +.names 36537 36541 36532 +1- 1 +-1 1 +.names 36532 36533 +1 1 +.names 35313 36534 +0 1 +.names 36534 36535 +1 1 +.names 36535 36536 +0 1 +.names 36523 36536 36537 +11 1 +.names 33978 36538 +0 1 +.names 36538 36539 +1 1 +.names 36539 36540 +0 1 +.names 8237 36540 36541 +11 1 +.names 36547 36551 36542 +1- 1 +-1 1 +.names 36542 36543 +1 1 +.names 35394 36544 +0 1 +.names 36544 36545 +1 1 +.names 36545 36546 +0 1 +.names 36481 36546 36547 +11 1 +.names 34064 36548 +0 1 +.names 36548 36549 +1 1 +.names 36549 36550 +0 1 +.names 8234 36550 36551 +11 1 +.names 36557 36561 36552 +1- 1 +-1 1 +.names 36552 36553 +1 1 +.names 35481 36554 +0 1 +.names 36554 36555 +1 1 +.names 36555 36556 +0 1 +.names 36523 36556 36557 +11 1 +.names 34153 36558 +0 1 +.names 36558 36559 +1 1 +.names 36559 36560 +0 1 +.names 8237 36560 36561 +11 1 +.names 36567 36571 36562 +1- 1 +-1 1 +.names 36562 36563 +1 1 +.names 35550 36564 +0 1 +.names 36564 36565 +1 1 +.names 36565 36566 +0 1 +.names 36470 36566 36567 +11 1 +.names 34226 36568 +0 1 +.names 36568 36569 +1 1 +.names 36569 36570 +0 1 +.names 8240 36570 36571 +11 1 +.names 36578 36582 36572 +1- 1 +-1 1 +.names 36572 36573 +1 1 +.names 8239 36574 +0 1 +.names 35560 36575 +0 1 +.names 36575 36576 +1 1 +.names 36576 36577 +0 1 +.names 36574 36577 36578 +11 1 +.names 34237 36579 +0 1 +.names 36579 36580 +1 1 +.names 36580 36581 +0 1 +.names 8239 36581 36582 +11 1 +.names 36588 36592 36583 +1- 1 +-1 1 +.names 36583 36584 +1 1 +.names 35598 36585 +0 1 +.names 36585 36586 +1 1 +.names 36586 36587 +0 1 +.names 36512 36587 36588 +11 1 +.names 34276 36589 +0 1 +.names 36589 36590 +1 1 +.names 36590 36591 +0 1 +.names 8235 36591 36592 +11 1 +.names 36598 36602 36593 +1- 1 +-1 1 +.names 36593 36594 +1 1 +.names 35635 36595 +0 1 +.names 36595 36596 +1 1 +.names 36596 36597 +0 1 +.names 36512 36597 36598 +11 1 +.names 34318 36599 +0 1 +.names 36599 36600 +1 1 +.names 36600 36601 +0 1 +.names 8235 36601 36602 +11 1 +.names 36608 36612 36603 +1- 1 +-1 1 +.names 36603 36604 +1 1 +.names 35793 36605 +0 1 +.names 36605 36606 +1 1 +.names 36606 36607 +0 1 +.names 36512 36607 36608 +11 1 +.names 34483 36609 +0 1 +.names 36609 36610 +1 1 +.names 36610 36611 +0 1 +.names 8235 36611 36612 +11 1 +.names 36618 36622 36613 +1- 1 +-1 1 +.names 36613 36614 +1 1 +.names 35836 36615 +0 1 +.names 36615 36616 +1 1 +.names 36616 36617 +0 1 +.names 36574 36617 36618 +11 1 +.names 34529 36619 +0 1 +.names 36619 36620 +1 1 +.names 36620 36621 +0 1 +.names 8239 36621 36622 +11 1 +.names 36628 36632 36623 +1- 1 +-1 1 +.names 36623 36624 +1 1 +.names 35783 36625 +0 1 +.names 36625 36626 +1 1 +.names 36626 36627 +0 1 +.names 36481 36627 36628 +11 1 +.names 34473 36629 +0 1 +.names 36629 36630 +1 1 +.names 36630 36631 +0 1 +.names 8234 36631 36632 +11 1 +.names 36638 36642 36633 +1- 1 +-1 1 +.names 36633 36634 +1 1 +.names 35734 36635 +0 1 +.names 36635 36636 +1 1 +.names 36636 36637 +0 1 +.names 36574 36637 36638 +11 1 +.names 34418 36639 +0 1 +.names 36639 36640 +1 1 +.names 36640 36641 +0 1 +.names 8239 36641 36642 +11 1 +.names 36648 36652 36643 +1- 1 +-1 1 +.names 36643 36644 +1 1 +.names 35909 36645 +0 1 +.names 36645 36646 +1 1 +.names 36646 36647 +0 1 +.names 36523 36647 36648 +11 1 +.names 34605 36649 +0 1 +.names 36649 36650 +1 1 +.names 36650 36651 +0 1 +.names 8237 36651 36652 +11 1 +.names 36658 36662 36653 +1- 1 +-1 1 +.names 36653 36654 +1 1 +.names 35919 36655 +0 1 +.names 36655 36656 +1 1 +.names 36656 36657 +0 1 +.names 36523 36657 36658 +11 1 +.names 34616 36659 +0 1 +.names 36659 36660 +1 1 +.names 36660 36661 +0 1 +.names 8237 36661 36662 +11 1 +.names 36668 36672 36663 +1- 1 +-1 1 +.names 36663 36664 +1 1 +.names 35959 36665 +0 1 +.names 36665 36666 +1 1 +.names 36666 36667 +0 1 +.names 36470 36667 36668 +11 1 +.names 34658 36669 +0 1 +.names 36669 36670 +1 1 +.names 36670 36671 +0 1 +.names 8240 36671 36672 +11 1 +.names 36679 36683 36673 +1- 1 +-1 1 +.names 36673 36674 +1 1 +.names 8238 36675 +0 1 +.names 35995 36676 +0 1 +.names 36676 36677 +1 1 +.names 36677 36678 +0 1 +.names 36675 36678 36679 +11 1 +.names 34695 36680 +0 1 +.names 36680 36681 +1 1 +.names 36681 36682 +0 1 +.names 8238 36682 36683 +11 1 +.names 36689 36693 36684 +1- 1 +-1 1 +.names 36684 36685 +1 1 +.names 36063 36686 +0 1 +.names 36686 36687 +1 1 +.names 36687 36688 +0 1 +.names 36675 36688 36689 +11 1 +.names 34767 36690 +0 1 +.names 36690 36691 +1 1 +.names 36691 36692 +0 1 +.names 8238 36692 36693 +11 1 +.names 36699 36703 36694 +1- 1 +-1 1 +.names 36694 36695 +1 1 +.names 36073 36696 +0 1 +.names 36696 36697 +1 1 +.names 36697 36698 +0 1 +.names 36574 36698 36699 +11 1 +.names 34778 36700 +0 1 +.names 36700 36701 +1 1 +.names 36701 36702 +0 1 +.names 8239 36702 36703 +11 1 +.names 36709 36713 36704 +1- 1 +-1 1 +.names 36704 36705 +1 1 +.names 36110 36706 +0 1 +.names 36706 36707 +1 1 +.names 36707 36708 +0 1 +.names 36481 36708 36709 +11 1 +.names 34820 36710 +0 1 +.names 36710 36711 +1 1 +.names 36711 36712 +0 1 +.names 8234 36712 36713 +11 1 +.names 36719 36723 36714 +1- 1 +-1 1 +.names 36714 36715 +1 1 +.names 36181 36716 +0 1 +.names 36716 36717 +1 1 +.names 36717 36718 +0 1 +.names 36512 36718 36719 +11 1 +.names 34894 36720 +0 1 +.names 36720 36721 +1 1 +.names 36721 36722 +0 1 +.names 8235 36722 36723 +11 1 +.names 36729 36733 36724 +1- 1 +-1 1 +.names 36724 36725 +1 1 +.names 36191 36726 +0 1 +.names 36726 36727 +1 1 +.names 36727 36728 +0 1 +.names 36470 36728 36729 +11 1 +.names 34905 36730 +0 1 +.names 36730 36731 +1 1 +.names 36731 36732 +0 1 +.names 8240 36732 36733 +11 1 +.names 36739 36743 36734 +1- 1 +-1 1 +.names 36734 36735 +1 1 +.names 36236 36736 +0 1 +.names 36736 36737 +1 1 +.names 36737 36738 +0 1 +.names 36470 36738 36739 +11 1 +.names 34950 36740 +0 1 +.names 36740 36741 +1 1 +.names 36741 36742 +0 1 +.names 8240 36742 36743 +11 1 +.names 36749 36753 36744 +1- 1 +-1 1 +.names 36744 36745 +1 1 +.names 36302 36746 +0 1 +.names 36746 36747 +1 1 +.names 36747 36748 +0 1 +.names 36675 36748 36749 +11 1 +.names 35020 36750 +0 1 +.names 36750 36751 +1 1 +.names 36751 36752 +0 1 +.names 8238 36752 36753 +11 1 +.names 36759 36763 36754 +1- 1 +-1 1 +.names 36754 36755 +1 1 +.names 36312 36756 +0 1 +.names 36756 36757 +1 1 +.names 36757 36758 +0 1 +.names 36675 36758 36759 +11 1 +.names 35031 36760 +0 1 +.names 36760 36761 +1 1 +.names 36761 36762 +0 1 +.names 8238 36762 36763 +11 1 +.names 36769 36773 36764 +1- 1 +-1 1 +.names 36764 36765 +1 1 +.names 36350 36766 +0 1 +.names 36766 36767 +1 1 +.names 36767 36768 +0 1 +.names 36675 36768 36769 +11 1 +.names 35072 36770 +0 1 +.names 36770 36771 +1 1 +.names 36771 36772 +0 1 +.names 8238 36772 36773 +11 1 +.names 36779 36783 36774 +1- 1 +-1 1 +.names 36774 36775 +1 1 +.names 36424 36776 +0 1 +.names 36776 36777 +1 1 +.names 36777 36778 +0 1 +.names 36574 36778 36779 +11 1 +.names 35149 36780 +0 1 +.names 36780 36781 +1 1 +.names 36781 36782 +0 1 +.names 8239 36782 36783 +11 1 +.names 36789 36793 36784 +1- 1 +-1 1 +.names 36784 36785 +1 1 +.names 36428 36786 +0 1 +.names 36786 36787 +1 1 +.names 36787 36788 +0 1 +.names 36574 36788 36789 +11 1 +.names 35154 36790 +0 1 +.names 36790 36791 +1 1 +.names 36791 36792 +0 1 +.names 8239 36792 36793 +11 1 +.names 36800 36801 36794 +1- 1 +-1 1 +.names 36794 36795 +1 1 +.names 8254 36796 +0 1 +.names 36802 36804 36797 +11 1 +.names 36797 36798 +1 1 +.names 36798 36799 +0 1 +.names 36796 36799 36800 +11 1 +.names 8254 2413 36801 +11 1 +.names 8255 36802 +0 1 +.names 14886 36803 +1 1 +.names 36803 36804 +0 1 +.names 36811 36812 36805 +1- 1 +-1 1 +.names 36805 36806 +1 1 +.names 2413 36807 +1 1 +.names 36807 36808 +0 1 +.names 36802 36809 +1 1 +.names 36809 36810 +0 1 +.names 36808 36810 36811 +11 1 +.names 36795 36812 +0 1 +.names 36819 36820 36813 +1- 1 +-1 1 +.names 36813 36814 +1 1 +.names 8242 36815 +0 1 +.names 36802 36822 36816 +11 1 +.names 36816 36817 +1 1 +.names 36817 36818 +0 1 +.names 36815 36818 36819 +11 1 +.names 8242 2413 36820 +11 1 +.names 14886 36821 +1 1 +.names 36821 36822 +0 1 +.names 36829 36830 36823 +1- 1 +-1 1 +.names 36823 36824 +1 1 +.names 2413 36825 +1 1 +.names 36825 36826 +0 1 +.names 36802 36827 +1 1 +.names 36827 36828 +0 1 +.names 36826 36828 36829 +11 1 +.names 36814 36830 +0 1 +.names 8249 36831 +0 1 +.names 36831 36832 +1 1 +.names 36831 36836 36833 +11 1 +.names 36833 36834 +1 1 +.names 14886 36835 +1 1 +.names 36835 36836 +0 1 +.names 36840 36841 36837 +1- 1 +-1 1 +.names 36837 36838 +1 1 +.names 36834 36839 +0 1 +.names 36815 36839 36840 +11 1 +.names 8242 2413 36841 +11 1 +.names 2413 36842 +1 1 +.names 36847 36848 36843 +1- 1 +-1 1 +.names 36843 36844 +1 1 +.names 36832 36845 +0 1 +.names 36842 36846 +0 1 +.names 36845 36846 36847 +11 1 +.names 36838 36848 +0 1 +.names 36831 36849 +1 1 +.names 36831 36853 36850 +11 1 +.names 36850 36851 +1 1 +.names 14886 36852 +1 1 +.names 36852 36853 +0 1 +.names 36857 36858 36854 +1- 1 +-1 1 +.names 36854 36855 +1 1 +.names 36851 36856 +0 1 +.names 36796 36856 36857 +11 1 +.names 8254 2413 36858 +11 1 +.names 36864 36865 36859 +1- 1 +-1 1 +.names 36859 36860 +1 1 +.names 36849 36861 +0 1 +.names 2413 36862 +1 1 +.names 36862 36863 +0 1 +.names 36861 36863 36864 +11 1 +.names 36855 36865 +0 1 +.names 36871 36872 36866 +1- 1 +-1 1 +.names 36866 36867 +1 1 +.names 36873 36875 36868 +11 1 +.names 36868 36869 +1 1 +.names 36869 36870 +0 1 +.names 36796 36870 36871 +11 1 +.names 8254 2413 36872 +11 1 +.names 8247 36873 +0 1 +.names 14886 36874 +1 1 +.names 36874 36875 +0 1 +.names 36882 36883 36876 +1- 1 +-1 1 +.names 36876 36877 +1 1 +.names 2413 36878 +1 1 +.names 36878 36879 +0 1 +.names 36873 36880 +1 1 +.names 36880 36881 +0 1 +.names 36879 36881 36882 +11 1 +.names 36867 36883 +0 1 +.names 36889 36890 36884 +1- 1 +-1 1 +.names 36884 36885 +1 1 +.names 36891 36893 36886 +11 1 +.names 36886 36887 +1 1 +.names 36887 36888 +0 1 +.names 36796 36888 36889 +11 1 +.names 8254 2413 36890 +11 1 +.names 8250 36891 +0 1 +.names 14886 36892 +1 1 +.names 36892 36893 +0 1 +.names 36900 36901 36894 +1- 1 +-1 1 +.names 36894 36895 +1 1 +.names 2413 36896 +1 1 +.names 36896 36897 +0 1 +.names 36891 36898 +1 1 +.names 36898 36899 +0 1 +.names 36897 36899 36900 +11 1 +.names 36885 36901 +0 1 +.names 36908 36909 36902 +1- 1 +-1 1 +.names 36902 36903 +1 1 +.names 8253 36904 +0 1 +.names 36873 36911 36905 +11 1 +.names 36905 36906 +1 1 +.names 36906 36907 +0 1 +.names 36904 36907 36908 +11 1 +.names 8253 2413 36909 +11 1 +.names 14886 36910 +1 1 +.names 36910 36911 +0 1 +.names 36918 36919 36912 +1- 1 +-1 1 +.names 36912 36913 +1 1 +.names 2413 36914 +1 1 +.names 36914 36915 +0 1 +.names 36873 36916 +1 1 +.names 36916 36917 +0 1 +.names 36915 36917 36918 +11 1 +.names 36903 36919 +0 1 +.names 36925 36926 36920 +1- 1 +-1 1 +.names 36920 36921 +1 1 +.names 36891 36928 36922 +11 1 +.names 36922 36923 +1 1 +.names 36923 36924 +0 1 +.names 36815 36924 36925 +11 1 +.names 8242 2413 36926 +11 1 +.names 14886 36927 +1 1 +.names 36927 36928 +0 1 +.names 36935 36936 36929 +1- 1 +-1 1 +.names 36929 36930 +1 1 +.names 2413 36931 +1 1 +.names 36931 36932 +0 1 +.names 36891 36933 +1 1 +.names 36933 36934 +0 1 +.names 36932 36934 36935 +11 1 +.names 36921 36936 +0 1 +.names 36942 36943 36937 +1- 1 +-1 1 +.names 36937 36938 +1 1 +.names 36873 36945 36939 +11 1 +.names 36939 36940 +1 1 +.names 36940 36941 +0 1 +.names 36796 36941 36942 +11 1 +.names 8254 14886 36943 +11 1 +.names 14886 36944 +1 1 +.names 36944 36945 +0 1 +.names 36952 36953 36946 +1- 1 +-1 1 +.names 36946 36947 +1 1 +.names 2413 36948 +1 1 +.names 36948 36949 +0 1 +.names 36873 36950 +1 1 +.names 36950 36951 +0 1 +.names 36949 36951 36952 +11 1 +.names 36938 36953 +0 1 +.names 36831 36954 +1 1 +.names 36831 36958 36955 +11 1 +.names 36955 36956 +1 1 +.names 14886 36957 +1 1 +.names 36957 36958 +0 1 +.names 36962 36963 36959 +1- 1 +-1 1 +.names 36959 36960 +1 1 +.names 36956 36961 +0 1 +.names 36904 36961 36962 +11 1 +.names 8253 2413 36963 +11 1 +.names 2413 36964 +1 1 +.names 36969 36970 36965 +1- 1 +-1 1 +.names 36965 36966 +1 1 +.names 36954 36967 +0 1 +.names 36964 36968 +0 1 +.names 36967 36968 36969 +11 1 +.names 36960 36970 +0 1 +.names 36831 36971 +1 1 +.names 36831 36975 36972 +11 1 +.names 36972 36973 +1 1 +.names 14886 36974 +1 1 +.names 36974 36975 +0 1 +.names 36979 36980 36976 +1- 1 +-1 1 +.names 36976 36977 +1 1 +.names 36973 36978 +0 1 +.names 36815 36978 36979 +11 1 +.names 8242 2413 36980 +11 1 +.names 2413 36981 +1 1 +.names 36986 36987 36982 +1- 1 +-1 1 +.names 36982 36983 +1 1 +.names 36971 36984 +0 1 +.names 36981 36985 +0 1 +.names 36984 36985 36986 +11 1 +.names 36977 36987 +0 1 +.names 36993 36994 36988 +1- 1 +-1 1 +.names 36988 36989 +1 1 +.names 36873 36996 36990 +11 1 +.names 36990 36991 +1 1 +.names 36991 36992 +0 1 +.names 36796 36992 36993 +11 1 +.names 8254 2413 36994 +11 1 +.names 14886 36995 +1 1 +.names 36995 36996 +0 1 +.names 37003 37004 36997 +1- 1 +-1 1 +.names 36997 36998 +1 1 +.names 2413 36999 +1 1 +.names 36999 37000 +0 1 +.names 36873 37001 +1 1 +.names 37001 37002 +0 1 +.names 37000 37002 37003 +11 1 +.names 36989 37004 +0 1 +.names 37010 37011 37005 +1- 1 +-1 1 +.names 37005 37006 +1 1 +.names 36873 37013 37007 +11 1 +.names 37007 37008 +1 1 +.names 37008 37009 +0 1 +.names 36815 37009 37010 +11 1 +.names 8242 2413 37011 +11 1 +.names 14886 37012 +1 1 +.names 37012 37013 +0 1 +.names 37020 37021 37014 +1- 1 +-1 1 +.names 37014 37015 +1 1 +.names 2413 37016 +1 1 +.names 37016 37017 +0 1 +.names 36873 37018 +1 1 +.names 37018 37019 +0 1 +.names 37017 37019 37020 +11 1 +.names 37006 37021 +0 1 +.names 37027 37028 37022 +1- 1 +-1 1 +.names 37022 37023 +1 1 +.names 36873 37030 37024 +11 1 +.names 37024 37025 +1 1 +.names 37025 37026 +0 1 +.names 36815 37026 37027 +11 1 +.names 8242 2413 37028 +11 1 +.names 14886 37029 +1 1 +.names 37029 37030 +0 1 +.names 37037 37038 37031 +1- 1 +-1 1 +.names 37031 37032 +1 1 +.names 2413 37033 +1 1 +.names 37033 37034 +0 1 +.names 36873 37035 +1 1 +.names 37035 37036 +0 1 +.names 37034 37036 37037 +11 1 +.names 37023 37038 +0 1 +.names 37044 37045 37039 +1- 1 +-1 1 +.names 37039 37040 +1 1 +.names 36891 37047 37041 +11 1 +.names 37041 37042 +1 1 +.names 37042 37043 +0 1 +.names 36815 37043 37044 +11 1 +.names 8242 2413 37045 +11 1 +.names 14886 37046 +1 1 +.names 37046 37047 +0 1 +.names 37054 37055 37048 +1- 1 +-1 1 +.names 37048 37049 +1 1 +.names 2413 37050 +1 1 +.names 37050 37051 +0 1 +.names 36891 37052 +1 1 +.names 37052 37053 +0 1 +.names 37051 37053 37054 +11 1 +.names 37040 37055 +0 1 +.names 37061 37062 37056 +1- 1 +-1 1 +.names 37056 37057 +1 1 +.names 36802 37064 37058 +11 1 +.names 37058 37059 +1 1 +.names 37059 37060 +0 1 +.names 36904 37060 37061 +11 1 +.names 8253 2413 37062 +11 1 +.names 14886 37063 +1 1 +.names 37063 37064 +0 1 +.names 37071 37072 37065 +1- 1 +-1 1 +.names 37065 37066 +1 1 +.names 2413 37067 +1 1 +.names 37067 37068 +0 1 +.names 36802 37069 +1 1 +.names 37069 37070 +0 1 +.names 37068 37070 37071 +11 1 +.names 37057 37072 +0 1 +.names 37078 37079 37073 +1- 1 +-1 1 +.names 37073 37074 +1 1 +.names 36873 37081 37075 +11 1 +.names 37075 37076 +1 1 +.names 37076 37077 +0 1 +.names 36904 37077 37078 +11 1 +.names 8253 2413 37079 +11 1 +.names 14886 37080 +1 1 +.names 37080 37081 +0 1 +.names 37088 37089 37082 +1- 1 +-1 1 +.names 37082 37083 +1 1 +.names 36873 37084 +1 1 +.names 37084 37085 +0 1 +.names 2413 37086 +1 1 +.names 37086 37087 +0 1 +.names 37085 37087 37088 +11 1 +.names 37074 37089 +0 1 +.names 36831 37090 +1 1 +.names 36831 37094 37091 +11 1 +.names 37091 37092 +1 1 +.names 14886 37093 +1 1 +.names 37093 37094 +0 1 +.names 37098 37099 37095 +1- 1 +-1 1 +.names 37095 37096 +1 1 +.names 37092 37097 +0 1 +.names 36796 37097 37098 +11 1 +.names 8254 2413 37099 +11 1 +.names 2413 37100 +1 1 +.names 37105 37106 37101 +1- 1 +-1 1 +.names 37101 37102 +1 1 +.names 37090 37103 +0 1 +.names 37100 37104 +0 1 +.names 37103 37104 37105 +11 1 +.names 37096 37106 +0 1 +.names 37112 37113 37107 +1- 1 +-1 1 +.names 37107 37108 +1 1 +.names 36831 37115 37109 +11 1 +.names 37109 37110 +1 1 +.names 37110 37111 +0 1 +.names 36796 37111 37112 +11 1 +.names 8254 2413 37113 +11 1 +.names 14886 37114 +1 1 +.names 37114 37115 +0 1 +.names 37122 37123 37116 +1- 1 +-1 1 +.names 37116 37117 +1 1 +.names 2413 37118 +1 1 +.names 37118 37119 +0 1 +.names 36831 37120 +1 1 +.names 37120 37121 +0 1 +.names 37119 37121 37122 +11 1 +.names 37108 37123 +0 1 +.names 37129 37130 37124 +1- 1 +-1 1 +.names 37124 37125 +1 1 +.names 36891 37132 37126 +11 1 +.names 37126 37127 +1 1 +.names 37127 37128 +0 1 +.names 36904 37128 37129 +11 1 +.names 8253 2413 37130 +11 1 +.names 14886 37131 +1 1 +.names 37131 37132 +0 1 +.names 37139 37140 37133 +1- 1 +-1 1 +.names 37133 37134 +1 1 +.names 2413 37135 +1 1 +.names 37135 37136 +0 1 +.names 36891 37137 +1 1 +.names 37137 37138 +0 1 +.names 37136 37138 37139 +11 1 +.names 37125 37140 +0 1 +.names 37146 37147 37141 +1- 1 +-1 1 +.names 37141 37142 +1 1 +.names 36891 37149 37143 +11 1 +.names 37143 37144 +1 1 +.names 37144 37145 +0 1 +.names 36904 37145 37146 +11 1 +.names 8253 2413 37147 +11 1 +.names 14886 37148 +1 1 +.names 37148 37149 +0 1 +.names 37156 37157 37150 +1- 1 +-1 1 +.names 37150 37151 +1 1 +.names 2413 37152 +1 1 +.names 37152 37153 +0 1 +.names 36891 37154 +1 1 +.names 37154 37155 +0 1 +.names 37153 37155 37156 +11 1 +.names 37142 37157 +0 1 +.names 37163 37164 37158 +1- 1 +-1 1 +.names 37158 37159 +1 1 +.names 36891 37166 37160 +11 1 +.names 37160 37161 +1 1 +.names 37161 37162 +0 1 +.names 36796 37162 37163 +11 1 +.names 8254 2413 37164 +11 1 +.names 14886 37165 +1 1 +.names 37165 37166 +0 1 +.names 37173 37174 37167 +1- 1 +-1 1 +.names 37167 37168 +1 1 +.names 2413 37169 +1 1 +.names 37169 37170 +0 1 +.names 36891 37171 +1 1 +.names 37171 37172 +0 1 +.names 37170 37172 37173 +11 1 +.names 37159 37174 +0 1 +.names 37180 37181 37175 +1- 1 +-1 1 +.names 37175 37176 +1 1 +.names 36831 37183 37177 +11 1 +.names 37177 37178 +1 1 +.names 37178 37179 +0 1 +.names 36815 37179 37180 +11 1 +.names 8242 2413 37181 +11 1 +.names 14886 37182 +1 1 +.names 37182 37183 +0 1 +.names 37190 37191 37184 +1- 1 +-1 1 +.names 37184 37185 +1 1 +.names 36831 37186 +1 1 +.names 37186 37187 +0 1 +.names 2413 37188 +1 1 +.names 37188 37189 +0 1 +.names 37187 37189 37190 +11 1 +.names 37176 37191 +0 1 +.names 36831 37192 +1 1 +.names 36831 37196 37193 +11 1 +.names 37193 37194 +1 1 +.names 14886 37195 +1 1 +.names 37195 37196 +0 1 +.names 37200 37201 37197 +1- 1 +-1 1 +.names 37197 37198 +1 1 +.names 37194 37199 +0 1 +.names 36904 37199 37200 +11 1 +.names 8253 2413 37201 +11 1 +.names 2413 37202 +1 1 +.names 37207 37208 37203 +1- 1 +-1 1 +.names 37203 37204 +1 1 +.names 37192 37205 +0 1 +.names 37202 37206 +0 1 +.names 37205 37206 37207 +11 1 +.names 37198 37208 +0 1 +.names 37214 37215 37209 +1- 1 +-1 1 +.names 37209 37210 +1 1 +.names 36873 37217 37211 +11 1 +.names 37211 37212 +1 1 +.names 37212 37213 +0 1 +.names 36904 37213 37214 +11 1 +.names 8253 2413 37215 +11 1 +.names 14886 37216 +1 1 +.names 37216 37217 +0 1 +.names 37224 37225 37218 +1- 1 +-1 1 +.names 37218 37219 +1 1 +.names 2413 37220 +1 1 +.names 37220 37221 +0 1 +.names 36873 37222 +1 1 +.names 37222 37223 +0 1 +.names 37221 37223 37224 +11 1 +.names 37210 37225 +0 1 +.names 37231 37232 37226 +1- 1 +-1 1 +.names 37226 37227 +1 1 +.names 36891 37234 37228 +11 1 +.names 37228 37229 +1 1 +.names 37229 37230 +0 1 +.names 36904 37230 37231 +11 1 +.names 8253 2413 37232 +11 1 +.names 14886 37233 +1 1 +.names 37233 37234 +0 1 +.names 37241 37242 37235 +1- 1 +-1 1 +.names 37235 37236 +1 1 +.names 2413 37237 +1 1 +.names 37237 37238 +0 1 +.names 36891 37239 +1 1 +.names 37239 37240 +0 1 +.names 37238 37240 37241 +11 1 +.names 37227 37242 +0 1 +.names 36831 37243 +1 1 +.names 36831 37247 37244 +11 1 +.names 37244 37245 +1 1 +.names 14886 37246 +1 1 +.names 37246 37247 +0 1 +.names 37251 37252 37248 +1- 1 +-1 1 +.names 37248 37249 +1 1 +.names 37245 37250 +0 1 +.names 36796 37250 37251 +11 1 +.names 8254 2413 37252 +11 1 +.names 2413 37253 +1 1 +.names 37258 37259 37254 +1- 1 +-1 1 +.names 37254 37255 +1 1 +.names 37243 37256 +0 1 +.names 37253 37257 +0 1 +.names 37256 37257 37258 +11 1 +.names 37249 37259 +0 1 +.names 37265 37266 37260 +1- 1 +-1 1 +.names 37260 37261 +1 1 +.names 36891 37268 37262 +11 1 +.names 37262 37263 +1 1 +.names 37263 37264 +0 1 +.names 36904 37264 37265 +11 1 +.names 8253 2413 37266 +11 1 +.names 14886 37267 +1 1 +.names 37267 37268 +0 1 +.names 37275 37276 37269 +1- 1 +-1 1 +.names 37269 37270 +1 1 +.names 2413 37271 +1 1 +.names 37271 37272 +0 1 +.names 36891 37273 +1 1 +.names 37273 37274 +0 1 +.names 37272 37274 37275 +11 1 +.names 37261 37276 +0 1 +.names 37282 37283 37277 +1- 1 +-1 1 +.names 37277 37278 +1 1 +.names 36891 37285 37279 +11 1 +.names 37279 37280 +1 1 +.names 37280 37281 +0 1 +.names 36815 37281 37282 +11 1 +.names 8242 2413 37283 +11 1 +.names 14886 37284 +1 1 +.names 37284 37285 +0 1 +.names 37292 37293 37286 +1- 1 +-1 1 +.names 37286 37287 +1 1 +.names 2413 37288 +1 1 +.names 37288 37289 +0 1 +.names 36891 37290 +1 1 +.names 37290 37291 +0 1 +.names 37289 37291 37292 +11 1 +.names 37278 37293 +0 1 +.names 36831 37294 +1 1 +.names 36831 37298 37295 +11 1 +.names 37295 37296 +1 1 +.names 14886 37297 +1 1 +.names 37297 37298 +0 1 +.names 37302 37303 37299 +1- 1 +-1 1 +.names 37299 37300 +1 1 +.names 37296 37301 +0 1 +.names 36904 37301 37302 +11 1 +.names 8253 2413 37303 +11 1 +.names 37309 37310 37304 +1- 1 +-1 1 +.names 37304 37305 +1 1 +.names 37294 37306 +0 1 +.names 2413 37307 +1 1 +.names 37307 37308 +0 1 +.names 37306 37308 37309 +11 1 +.names 37300 37310 +0 1 +.names 37316 37317 37311 +1- 1 +-1 1 +.names 37311 37312 +1 1 +.names 36802 37319 37313 +11 1 +.names 37313 37314 +1 1 +.names 37314 37315 +0 1 +.names 36815 37315 37316 +11 1 +.names 8242 2413 37317 +11 1 +.names 14886 37318 +1 1 +.names 37318 37319 +0 1 +.names 37326 37327 37320 +1- 1 +-1 1 +.names 37320 37321 +1 1 +.names 2413 37322 +1 1 +.names 37322 37323 +0 1 +.names 36802 37324 +1 1 +.names 37324 37325 +0 1 +.names 37323 37325 37326 +11 1 +.names 37312 37327 +0 1 +.names 37333 37334 37328 +1- 1 +-1 1 +.names 37328 37329 +1 1 +.names 36873 37336 37330 +11 1 +.names 37330 37331 +1 1 +.names 37331 37332 +0 1 +.names 36796 37332 37333 +11 1 +.names 8254 2413 37334 +11 1 +.names 14886 37335 +1 1 +.names 37335 37336 +0 1 +.names 37343 37344 37337 +1- 1 +-1 1 +.names 37337 37338 +1 1 +.names 2413 37339 +1 1 +.names 37339 37340 +0 1 +.names 36873 37341 +1 1 +.names 37341 37342 +0 1 +.names 37340 37342 37343 +11 1 +.names 37329 37344 +0 1 +.names 37351 37353 37345 +1- 1 +-1 1 +.names 37345 37346 +1 1 +.names 8271 37347 +0 1 +.names 37382 37383 37348 +11 1 +.names 37348 37349 +1 1 +.names 37349 37350 +0 1 +.names 37347 37350 37351 +11 1 +.names 36844 37352 +0 1 +.names 8271 37352 37353 +11 1 +.names 37362 37365 37354 +1- 1 +-1 1 +.names 37354 37355 +1 1 +.names 37397 37399 37356 +11 1 +.names 37356 37357 +1 1 +.names 37357 37358 +0 1 +.names 37401 37403 37359 +11 1 +.names 37359 37360 +1 1 +.names 37360 37361 +0 1 +.names 37358 37361 37362 +1- 1 +-1 1 +.names 37390 37393 37363 +11 1 +.names 37363 37364 +1 1 +.names 37364 37365 +0 1 +.names 37371 32155 37366 +1- 1 +-1 1 +.names 37366 37367 +1 1 +.names 8291 37368 +0 1 +.names 37368 37369 +1 1 +.names 37369 37370 +0 1 +.names 8306 37370 37371 +1- 1 +-1 1 +.names 37374 37375 37372 +11 1 +.names 37372 37373 +1 1 +.names 8260 37374 +0 1 +.names 8281 37375 +0 1 +.names 37378 37379 37376 +11 1 +.names 37376 37377 +1 1 +.names 8268 37378 +0 1 +.names 8264 37379 +0 1 +.names 37387 37388 37380 +1- 1 +-1 1 +.names 37380 37381 +1 1 +.names 37381 37382 +0 1 +.names 37367 37383 +0 1 +.names 37355 37386 37384 +1- 1 +-1 1 +.names 37384 37385 +1 1 +.names 37346 37386 +0 1 +.names 37373 37387 +0 1 +.names 37377 37388 +0 1 +.names 56655 37389 +0 1 +.names 37389 37378 37390 +1- 1 +-1 1 +.names 8306 37391 +0 1 +.names 7806 37392 +0 1 +.names 37391 37392 37393 +1- 1 +-1 1 +.names 55082 55085 37394 +1- 1 +-1 1 +.names 37394 37395 +1 1 +.names 37395 37396 +0 1 +.names 37368 37396 37397 +1- 1 +-1 1 +.names 159 37398 +0 1 +.names 37398 37375 37399 +1- 1 +-1 1 +.names 36480 37400 +0 1 +.names 37374 37400 37401 +1- 1 +-1 1 +.names 430 37402 +0 1 +.names 37379 37402 37403 +1- 1 +-1 1 +.names 37409 37411 37404 +1- 1 +-1 1 +.names 37404 37405 +1 1 +.names 37438 37439 37406 +11 1 +.names 37406 37407 +1 1 +.names 37407 37408 +0 1 +.names 37347 37408 37409 +11 1 +.names 36806 37410 +0 1 +.names 8271 37410 37411 +11 1 +.names 37420 37423 37412 +1- 1 +-1 1 +.names 37412 37413 +1 1 +.names 37446 37448 37414 +11 1 +.names 37414 37415 +1 1 +.names 37415 37416 +0 1 +.names 37452 37454 37417 +11 1 +.names 37417 37418 +1 1 +.names 37418 37419 +0 1 +.names 37416 37419 37420 +1- 1 +-1 1 +.names 37456 37459 37421 +11 1 +.names 37421 37422 +1 1 +.names 37422 37423 +0 1 +.names 37429 22288 37424 +1- 1 +-1 1 +.names 37424 37425 +1 1 +.names 8312 37426 +0 1 +.names 37426 37427 +1 1 +.names 37427 37428 +0 1 +.names 8309 37428 37429 +1- 1 +-1 1 +.names 37432 37375 37430 +11 1 +.names 37430 37431 +1 1 +.names 8259 37432 +0 1 +.names 37378 37435 37433 +11 1 +.names 37433 37434 +1 1 +.names 8299 37435 +0 1 +.names 37449 37450 37436 +1- 1 +-1 1 +.names 37436 37437 +1 1 +.names 37437 37438 +0 1 +.names 37425 37439 +0 1 +.names 37413 37442 37440 +1- 1 +-1 1 +.names 37440 37441 +1 1 +.names 37405 37442 +0 1 +.names 55158 55161 37443 +1- 1 +-1 1 +.names 37443 37444 +1 1 +.names 37444 37445 +0 1 +.names 37426 37445 37446 +1- 1 +-1 1 +.names 138 37447 +0 1 +.names 37447 37375 37448 +1- 1 +-1 1 +.names 37431 37449 +0 1 +.names 37434 37450 +0 1 +.names 36522 37451 +0 1 +.names 37432 37451 37452 +1- 1 +-1 1 +.names 409 37453 +0 1 +.names 37435 37453 37454 +1- 1 +-1 1 +.names 56634 37455 +0 1 +.names 37455 37378 37456 +1- 1 +-1 1 +.names 8309 37457 +0 1 +.names 7776 37458 +0 1 +.names 37457 37458 37459 +1- 1 +-1 1 +.names 8295 37460 +1 1 +.names 37464 32189 37461 +1- 1 +-1 1 +.names 37461 37462 +1 1 +.names 37460 37463 +0 1 +.names 8307 37463 37464 +1- 1 +-1 1 +.names 37467 37468 37465 +11 1 +.names 37465 37466 +1 1 +.names 8257 37467 +0 1 +.names 8302 37468 +0 1 +.names 37473 37474 37469 +11 1 +.names 37469 37470 +1 1 +.names 37502 37505 37471 +1- 1 +-1 1 +.names 37471 37472 +1 1 +.names 37472 37473 +0 1 +.names 37462 37474 +0 1 +.names 37478 37481 37475 +1- 1 +-1 1 +.names 37475 37476 +1 1 +.names 37516 37517 37477 +1- 1 +-1 1 +.names 37477 37478 +1 1 +.names 37486 37488 37479 +1- 1 +-1 1 +.names 37479 37480 +1 1 +.names 37480 37481 +0 1 +.names 8284 37482 +0 1 +.names 37482 37483 +1 1 +.names 37483 37484 +0 1 +.names 36824 37485 +0 1 +.names 37484 37485 37486 +11 1 +.names 37470 37487 +0 1 +.names 37483 37487 37488 +11 1 +.names 37492 37494 37489 +11 1 +.names 37489 37490 +1 1 +.names 143 37491 +0 1 +.names 37491 8295 37492 +1- 1 +-1 1 +.names 56639 37493 +0 1 +.names 37493 37468 37494 +1- 1 +-1 1 +.names 37498 37501 37495 +11 1 +.names 37495 37496 +1 1 +.names 414 37497 +0 1 +.names 37435 37497 37498 +1- 1 +-1 1 +.names 8307 37499 +0 1 +.names 7946 37500 +0 1 +.names 37499 37500 37501 +1- 1 +-1 1 +.names 37466 37502 +0 1 +.names 37435 37426 37503 +11 1 +.names 37503 37504 +1 1 +.names 37504 37505 +0 1 +.names 37509 37513 37506 +11 1 +.names 37506 37507 +1 1 +.names 36469 37508 +0 1 +.names 37467 37508 37509 +1- 1 +-1 1 +.names 55135 55136 37510 +1- 1 +-1 1 +.names 37510 37511 +1 1 +.names 37511 37512 +0 1 +.names 37426 37512 37513 +1- 1 +-1 1 +.names 37496 37514 +0 1 +.names 37507 37515 +0 1 +.names 37514 37515 37516 +1- 1 +-1 1 +.names 37490 37517 +0 1 +.names 37520 37521 37518 +1- 1 +-1 1 +.names 37518 37519 +1 1 +.names 8283 37520 +0 1 +.names 36860 37521 +0 1 +.names 37526 37527 37522 +1- 1 +-1 1 +.names 37522 37523 +1 1 +.names 37575 37524 +0 1 +.names 37524 37525 +1 1 +.names 37525 37526 +0 1 +.names 145 37527 +0 1 +.names 37532 37535 37528 +1- 1 +-1 1 +.names 37528 37529 +1 1 +.names 37587 37588 37530 +11 1 +.names 37530 37531 +1 1 +.names 37531 37532 +0 1 +.names 37540 37542 37533 +1- 1 +-1 1 +.names 37533 37534 +1 1 +.names 37534 37535 +0 1 +.names 8262 37536 +0 1 +.names 37570 37573 37537 +11 1 +.names 37537 37538 +1 1 +.names 37538 37539 +0 1 +.names 37536 37539 37540 +11 1 +.names 416 37541 +0 1 +.names 8262 37541 37542 +11 1 +.names 37545 37548 37543 +1- 1 +-1 1 +.names 37543 37544 +1 1 +.names 37519 37545 +0 1 +.names 8322 37546 +0 1 +.names 37546 37547 +1 1 +.names 37547 37548 +0 1 +.names 37545 37553 37549 +1- 1 +-1 1 +.names 37549 37550 +1 1 +.names 37555 37551 +0 1 +.names 37551 37552 +1 1 +.names 37552 37553 +0 1 +.names 55200 55203 37554 +1- 1 +-1 1 +.names 37554 37555 +1 1 +.names 37558 37561 37556 +1- 1 +-1 1 +.names 37556 37557 +1 1 +.names 37544 37550 37558 +11 1 +.names 37577 37579 37559 +11 1 +.names 37559 37560 +1 1 +.names 37560 37561 +0 1 +.names 37566 37569 37562 +1- 1 +-1 1 +.names 37562 37563 +1 1 +.names 37574 37520 37564 +11 1 +.names 37564 37565 +1 1 +.names 37565 37566 +0 1 +.names 37546 37499 37567 +11 1 +.names 37567 37568 +1 1 +.names 37568 37569 +0 1 +.names 37563 37570 +0 1 +.names 37581 37582 37571 +1- 1 +-1 1 +.names 37571 37572 +1 1 +.names 37572 37573 +0 1 +.names 8304 37574 +0 1 +.names 8295 37575 +1 1 +.names 36533 37576 +0 1 +.names 37432 37576 37577 +1- 1 +-1 1 +.names 7966 37578 +0 1 +.names 37499 37578 37579 +1- 1 +-1 1 +.names 37432 37580 +1 1 +.names 37524 35329 37581 +1- 1 +-1 1 +.names 37580 37582 +0 1 +.names 37585 37586 37583 +1- 1 +-1 1 +.names 37583 37584 +1 1 +.names 8304 56641 37585 +11 1 +.names 37523 37586 +0 1 +.names 37557 37587 +0 1 +.names 37584 37588 +0 1 +.names 37594 37596 37589 +1- 1 +-1 1 +.names 37589 37590 +1 1 +.names 37621 37622 37591 +11 1 +.names 37591 37592 +1 1 +.names 37592 37593 +0 1 +.names 37520 37593 37594 +11 1 +.names 36877 37595 +0 1 +.names 8283 37595 37596 +11 1 +.names 37605 37608 37597 +1- 1 +-1 1 +.names 37597 37598 +1 1 +.names 37629 37631 37599 +11 1 +.names 37599 37600 +1 1 +.names 37600 37601 +0 1 +.names 37639 37641 37602 +11 1 +.names 37602 37603 +1 1 +.names 37603 37604 +0 1 +.names 37601 37604 37605 +1- 1 +-1 1 +.names 37633 37635 37606 +11 1 +.names 37606 37607 +1 1 +.names 37607 37608 +0 1 +.names 37613 32320 37609 +1- 1 +-1 1 +.names 37609 37610 +1 1 +.names 37368 37611 +1 1 +.names 37611 37612 +0 1 +.names 8307 37612 37613 +1- 1 +-1 1 +.names 37432 37616 37614 +11 1 +.names 37614 37615 +1 1 +.names 8282 37616 +0 1 +.names 37378 37379 37617 +11 1 +.names 37617 37618 +1 1 +.names 37636 37637 37619 +1- 1 +-1 1 +.names 37619 37620 +1 1 +.names 37620 37621 +0 1 +.names 37610 37622 +0 1 +.names 37598 37625 37623 +1- 1 +-1 1 +.names 37623 37624 +1 1 +.names 37590 37625 +0 1 +.names 55279 55280 37626 +1- 1 +-1 1 +.names 37626 37627 +1 1 +.names 37627 37628 +0 1 +.names 37368 37628 37629 +1- 1 +-1 1 +.names 147 37630 +0 1 +.names 37630 37616 37631 +1- 1 +-1 1 +.names 56643 37632 +0 1 +.names 37632 37378 37633 +1- 1 +-1 1 +.names 7676 37634 +0 1 +.names 37499 37634 37635 +1- 1 +-1 1 +.names 37615 37636 +0 1 +.names 37618 37637 +0 1 +.names 36543 37638 +0 1 +.names 37432 37638 37639 +1- 1 +-1 1 +.names 418 37640 +0 1 +.names 37379 37640 37641 +1- 1 +-1 1 +.names 37647 37649 37642 +1- 1 +-1 1 +.names 37642 37643 +1 1 +.names 37660 37661 37644 +11 1 +.names 37644 37645 +1 1 +.names 37645 37646 +0 1 +.names 37520 37646 37647 +11 1 +.names 36895 37648 +0 1 +.names 8283 37648 37649 +11 1 +.names 37655 32357 37650 +1- 1 +-1 1 +.names 37650 37651 +1 1 +.names 8313 37652 +0 1 +.names 37652 37653 +1 1 +.names 37653 37654 +0 1 +.names 8309 37654 37655 +1- 1 +-1 1 +.names 37432 37616 37656 +11 1 +.names 37656 37657 +1 1 +.names 37683 37684 37658 +1- 1 +-1 1 +.names 37658 37659 +1 1 +.names 37659 37660 +0 1 +.names 37651 37661 +0 1 +.names 37665 37666 37662 +1- 1 +-1 1 +.names 37662 37663 +1 1 +.names 37693 37694 37664 +1- 1 +-1 1 +.names 37664 37665 +1 1 +.names 37643 37666 +0 1 +.names 37672 37674 37667 +11 1 +.names 37667 37668 +1 1 +.names 55289 55292 37669 +1- 1 +-1 1 +.names 37669 37670 +1 1 +.names 37670 37671 +0 1 +.names 37652 37671 37672 +1- 1 +-1 1 +.names 154 37673 +0 1 +.names 37673 37616 37674 +1- 1 +-1 1 +.names 37574 37435 37675 +11 1 +.names 37675 37676 +1 1 +.names 37680 37682 37677 +11 1 +.names 37677 37678 +1 1 +.names 56650 37679 +0 1 +.names 37679 37574 37680 +1- 1 +-1 1 +.names 7746 37681 +0 1 +.names 37457 37681 37682 +1- 1 +-1 1 +.names 37657 37683 +0 1 +.names 37676 37684 +0 1 +.names 37688 37690 37685 +11 1 +.names 37685 37686 +1 1 +.names 36491 37687 +0 1 +.names 37432 37687 37688 +1- 1 +-1 1 +.names 425 37689 +0 1 +.names 37435 37689 37690 +1- 1 +-1 1 +.names 37668 37691 +0 1 +.names 37686 37692 +0 1 +.names 37691 37692 37693 +1- 1 +-1 1 +.names 37678 37694 +0 1 +.names 37700 37702 37695 +1- 1 +-1 1 +.names 37695 37696 +1 1 +.names 37714 37715 37697 +11 1 +.names 37697 37698 +1 1 +.names 37698 37699 +0 1 +.names 37374 37699 37700 +11 1 +.names 36501 37701 +0 1 +.names 8260 37701 37702 +11 1 +.names 37707 32396 37703 +1- 1 +-1 1 +.names 37703 37704 +1 1 +.names 37375 37705 +1 1 +.names 37705 37706 +0 1 +.names 8306 37706 37707 +1- 1 +-1 1 +.names 37368 37520 37708 +11 1 +.names 37708 37709 +1 1 +.names 37378 37536 37710 +11 1 +.names 37710 37711 +1 1 +.names 37727 37728 37712 +1- 1 +-1 1 +.names 37712 37713 +1 1 +.names 37713 37714 +0 1 +.names 37704 37715 +0 1 +.names 37719 37720 37716 +1- 1 +-1 1 +.names 37716 37717 +1 1 +.names 37745 37746 37718 +1- 1 +-1 1 +.names 37718 37719 +1 1 +.names 37696 37720 +0 1 +.names 37724 37726 37721 +11 1 +.names 37721 37722 +1 1 +.names 56663 37723 +0 1 +.names 37723 37378 37724 +1- 1 +-1 1 +.names 7896 37725 +0 1 +.names 37391 37725 37726 +1- 1 +-1 1 +.names 37709 37727 +0 1 +.names 37711 37728 +0 1 +.names 37732 37734 37729 +11 1 +.names 37729 37730 +1 1 +.names 167 37731 +0 1 +.names 37731 37375 37732 +1- 1 +-1 1 +.names 36913 37733 +0 1 +.names 37520 37733 37734 +1- 1 +-1 1 +.names 37740 37742 37735 +11 1 +.names 37735 37736 +1 1 +.names 55329 55332 37737 +1- 1 +-1 1 +.names 37737 37738 +1 1 +.names 37738 37739 +0 1 +.names 37368 37739 37740 +1- 1 +-1 1 +.names 438 37741 +0 1 +.names 37536 37741 37742 +1- 1 +-1 1 +.names 37730 37743 +0 1 +.names 37736 37744 +0 1 +.names 37743 37744 37745 +1- 1 +-1 1 +.names 37722 37746 +0 1 +.names 37749 37520 37747 +1- 1 +-1 1 +.names 37747 37748 +1 1 +.names 36930 37749 +0 1 +.names 37754 37757 37750 +1- 1 +-1 1 +.names 37750 37751 +1 1 +.names 37761 37763 37752 +1- 1 +-1 1 +.names 37752 37753 +1 1 +.names 37753 37754 +0 1 +.names 37777 37780 37755 +11 1 +.names 37755 37756 +1 1 +.names 37756 37757 +0 1 +.names 37799 37800 37758 +11 1 +.names 37758 37759 +1 1 +.names 37759 37760 +0 1 +.names 37499 37760 37761 +11 1 +.names 7766 37762 +0 1 +.names 8307 37762 37763 +11 1 +.names 37766 37769 37764 +1- 1 +-1 1 +.names 37764 37765 +1 1 +.names 37748 37766 +0 1 +.names 8301 37767 +0 1 +.names 37767 37768 +1 1 +.names 37768 37769 +0 1 +.names 37766 37774 37770 +1- 1 +-1 1 +.names 37770 37771 +1 1 +.names 37810 37772 +0 1 +.names 37772 37773 +1 1 +.names 37773 37774 +0 1 +.names 37781 37784 37775 +1- 1 +-1 1 +.names 37775 37776 +1 1 +.names 37776 37777 +0 1 +.names 37801 37804 37778 +1- 1 +-1 1 +.names 37778 37779 +1 1 +.names 37779 37780 +0 1 +.names 37765 37771 37781 +11 1 +.names 37806 37808 37782 +11 1 +.names 37782 37783 +1 1 +.names 37783 37784 +0 1 +.names 37787 37790 37785 +1- 1 +-1 1 +.names 37785 37786 +1 1 +.names 8281 32433 37787 +1- 1 +-1 1 +.names 8318 37788 +0 1 +.names 37788 37789 +1 1 +.names 37789 37790 +0 1 +.names 37795 37798 37791 +1- 1 +-1 1 +.names 37791 37792 +1 1 +.names 37574 37520 37793 +11 1 +.names 37793 37794 +1 1 +.names 37794 37795 +0 1 +.names 37536 37767 37796 +11 1 +.names 37796 37797 +1 1 +.names 37797 37798 +0 1 +.names 37792 37799 +0 1 +.names 37786 37800 +0 1 +.names 8304 56652 37801 +11 1 +.names 37536 37811 37802 +1- 1 +-1 1 +.names 37802 37803 +1 1 +.names 37803 37804 +0 1 +.names 156 37805 +0 1 +.names 37375 37805 37806 +1- 1 +-1 1 +.names 36553 37807 +0 1 +.names 37807 37788 37808 +1- 1 +-1 1 +.names 55369 55372 37809 +1- 1 +-1 1 +.names 37809 37810 +1 1 +.names 427 37811 +0 1 +.names 37815 37817 37812 +11 1 +.names 37812 37813 +1 1 +.names 417 37814 +0 1 +.names 37379 37814 37815 +1- 1 +-1 1 +.names 8130 37816 +0 1 +.names 37457 37816 37817 +1- 1 +-1 1 +.names 37379 37652 37818 +11 1 +.names 37818 37819 +1 1 +.names 37375 37820 +1 1 +.names 37824 32474 37821 +1- 1 +-1 1 +.names 37821 37822 +1 1 +.names 37820 37823 +0 1 +.names 8309 37823 37824 +1- 1 +-1 1 +.names 37829 37830 37825 +11 1 +.names 37825 37826 +1 1 +.names 37858 37859 37827 +1- 1 +-1 1 +.names 37827 37828 +1 1 +.names 37828 37829 +0 1 +.names 37822 37830 +0 1 +.names 37834 37836 37831 +1- 1 +-1 1 +.names 37831 37832 +1 1 +.names 37826 37833 +0 1 +.names 37482 37833 37834 +11 1 +.names 36966 37835 +0 1 +.names 8284 37835 37836 +11 1 +.names 37840 37841 37837 +1- 1 +-1 1 +.names 37837 37838 +1 1 +.names 37862 37863 37839 +1- 1 +-1 1 +.names 37839 37840 +1 1 +.names 37832 37841 +0 1 +.names 37845 37847 37842 +11 1 +.names 37842 37843 +1 1 +.names 146 37844 +0 1 +.names 37844 37375 37845 +1- 1 +-1 1 +.names 56642 37846 +0 1 +.names 37846 37468 37847 +1- 1 +-1 1 +.names 37851 37855 37848 +11 1 +.names 37848 37849 +1 1 +.names 36563 37850 +0 1 +.names 37467 37850 37851 +1- 1 +-1 1 +.names 55435 55438 37852 +1- 1 +-1 1 +.names 37852 37853 +1 1 +.names 37853 37854 +0 1 +.names 37652 37854 37855 +1- 1 +-1 1 +.names 37467 37468 37856 +11 1 +.names 37856 37857 +1 1 +.names 37857 37858 +0 1 +.names 37819 37859 +0 1 +.names 37813 37860 +0 1 +.names 37849 37861 +0 1 +.names 37860 37861 37862 +1- 1 +-1 1 +.names 37843 37863 +0 1 +.names 37869 37871 37864 +1- 1 +-1 1 +.names 37864 37865 +1 1 +.names 37881 37882 37866 +11 1 +.names 37866 37867 +1 1 +.names 37867 37868 +0 1 +.names 37482 37868 37869 +11 1 +.names 36983 37870 +0 1 +.names 8284 37870 37871 +11 1 +.names 37876 32509 37872 +1- 1 +-1 1 +.names 37872 37873 +1 1 +.names 37546 37874 +1 1 +.names 37874 37875 +0 1 +.names 8309 37875 37876 +1- 1 +-1 1 +.names 37374 37616 37877 +11 1 +.names 37877 37878 +1 1 +.names 37898 37899 37879 +1- 1 +-1 1 +.names 37879 37880 +1 1 +.names 37880 37881 +0 1 +.names 37873 37882 +0 1 +.names 37886 37887 37883 +1- 1 +-1 1 +.names 37883 37884 +1 1 +.names 37910 37911 37885 +1- 1 +-1 1 +.names 37885 37886 +1 1 +.names 37865 37887 +0 1 +.names 37893 37895 37888 +11 1 +.names 37888 37889 +1 1 +.names 55451 55454 37890 +1- 1 +-1 1 +.names 37890 37891 +1 1 +.names 37891 37892 +0 1 +.names 37546 37892 37893 +1- 1 +-1 1 +.names 162 37894 +0 1 +.names 37894 37616 37895 +1- 1 +-1 1 +.names 37574 37435 37896 +11 1 +.names 37896 37897 +1 1 +.names 37878 37898 +0 1 +.names 37897 37899 +0 1 +.names 37903 37905 37900 +11 1 +.names 37900 37901 +1 1 +.names 56658 37902 +0 1 +.names 37902 37574 37903 +1- 1 +-1 1 +.names 7836 37904 +0 1 +.names 37457 37904 37905 +1- 1 +-1 1 +.names 37889 37906 +0 1 +.names 37913 37915 37907 +11 1 +.names 37907 37908 +1 1 +.names 37908 37909 +0 1 +.names 37906 37909 37910 +1- 1 +-1 1 +.names 37901 37911 +0 1 +.names 36573 37912 +0 1 +.names 37374 37912 37913 +1- 1 +-1 1 +.names 433 37914 +0 1 +.names 37435 37914 37915 +1- 1 +-1 1 +.names 37921 37923 37916 +1- 1 +-1 1 +.names 37916 37917 +1 1 +.names 37948 37949 37918 +11 1 +.names 37918 37919 +1 1 +.names 37919 37920 +0 1 +.names 37374 37920 37921 +11 1 +.names 36584 37922 +0 1 +.names 8260 37922 37923 +11 1 +.names 37932 37935 37924 +1- 1 +-1 1 +.names 37924 37925 +1 1 +.names 37958 37960 37926 +11 1 +.names 37926 37927 +1 1 +.names 37927 37928 +0 1 +.names 37966 37968 37929 +11 1 +.names 37929 37930 +1 1 +.names 37930 37931 +0 1 +.names 37928 37931 37932 +1- 1 +-1 1 +.names 37954 37956 37933 +11 1 +.names 37933 37934 +1 1 +.names 37934 37935 +0 1 +.names 37940 32545 37936 +1- 1 +-1 1 +.names 37936 37937 +1 1 +.names 8295 37938 +1 1 +.names 37938 37939 +0 1 +.names 8309 37939 37940 +1- 1 +-1 1 +.names 37943 37347 37941 +11 1 +.names 37941 37942 +1 1 +.names 8319 37943 +0 1 +.names 37378 37536 37944 +11 1 +.names 37944 37945 +1 1 +.names 37961 37962 37946 +1- 1 +-1 1 +.names 37946 37947 +1 1 +.names 37947 37948 +0 1 +.names 37937 37949 +0 1 +.names 37925 37952 37950 +1- 1 +-1 1 +.names 37950 37951 +1 1 +.names 37917 37952 +0 1 +.names 56644 37953 +0 1 +.names 37953 37378 37954 +1- 1 +-1 1 +.names 7686 37955 +0 1 +.names 37457 37955 37956 +1- 1 +-1 1 +.names 148 37957 +0 1 +.names 37957 8295 37958 +1- 1 +-1 1 +.names 36998 37959 +0 1 +.names 37347 37959 37960 +1- 1 +-1 1 +.names 37942 37961 +0 1 +.names 37945 37962 +0 1 +.names 55489 55492 37963 +1- 1 +-1 1 +.names 37963 37964 +1 1 +.names 37964 37965 +0 1 +.names 37943 37965 37966 +1- 1 +-1 1 +.names 419 37967 +0 1 +.names 37536 37967 37968 +1- 1 +-1 1 +.names 8295 37969 +1 1 +.names 37347 37972 37970 +1- 1 +-1 1 +.names 37970 37971 +1 1 +.names 37015 37972 +0 1 +.names 37977 37980 37973 +1- 1 +-1 1 +.names 37973 37974 +1 1 +.names 37984 37986 37975 +1- 1 +-1 1 +.names 37975 37976 +1 1 +.names 37976 37977 +0 1 +.names 37999 38002 37978 +11 1 +.names 37978 37979 +1 1 +.names 37979 37980 +0 1 +.names 38019 38020 37981 +11 1 +.names 37981 37982 +1 1 +.names 37982 37983 +0 1 +.names 37499 37983 37984 +11 1 +.names 7826 37985 +0 1 +.names 8307 37985 37986 +11 1 +.names 37989 37991 37987 +1- 1 +-1 1 +.names 37987 37988 +1 1 +.names 37971 37989 +0 1 +.names 37767 37990 +1 1 +.names 37990 37991 +0 1 +.names 37989 37996 37992 +1- 1 +-1 1 +.names 37992 37993 +1 1 +.names 38029 37994 +0 1 +.names 37994 37995 +1 1 +.names 37995 37996 +0 1 +.names 38003 38006 37997 +1- 1 +-1 1 +.names 37997 37998 +1 1 +.names 37998 37999 +0 1 +.names 38030 38031 38000 +1- 1 +-1 1 +.names 38000 38001 +1 1 +.names 38001 38002 +0 1 +.names 37988 37993 38003 +11 1 +.names 38022 38024 38004 +11 1 +.names 38004 38005 +1 1 +.names 38005 38006 +0 1 +.names 38010 34316 38007 +1- 1 +-1 1 +.names 38007 38008 +1 1 +.names 37969 38009 +0 1 +.names 8302 38009 38010 +1- 1 +-1 1 +.names 38015 38018 38011 +1- 1 +-1 1 +.names 38011 38012 +1 1 +.names 37347 37432 38013 +11 1 +.names 38013 38014 +1 1 +.names 38014 38015 +0 1 +.names 37435 37767 38016 +11 1 +.names 38016 38017 +1 1 +.names 38017 38018 +0 1 +.names 38008 38019 +0 1 +.names 38012 38020 +0 1 +.names 36594 38021 +0 1 +.names 37432 38021 38022 +1- 1 +-1 1 +.names 161 38023 +0 1 +.names 8295 38023 38024 +1- 1 +-1 1 +.names 38027 37468 38025 +1- 1 +-1 1 +.names 38025 38026 +1 1 +.names 56657 38027 +0 1 +.names 55530 55533 38028 +1- 1 +-1 1 +.names 38028 38029 +1 1 +.names 8299 432 38030 +11 1 +.names 38026 38031 +0 1 +.names 38037 38039 38032 +1- 1 +-1 1 +.names 38032 38033 +1 1 +.names 38066 38067 38034 +11 1 +.names 38034 38035 +1 1 +.names 38035 38036 +0 1 +.names 37347 38036 38037 +11 1 +.names 36947 38038 +0 1 +.names 8271 38038 38039 +11 1 +.names 38048 38051 38040 +1- 1 +-1 1 +.names 38040 38041 +1 1 +.names 38072 38074 38042 +11 1 +.names 38042 38043 +1 1 +.names 38043 38044 +0 1 +.names 38076 38080 38045 +11 1 +.names 38045 38046 +1 1 +.names 38046 38047 +0 1 +.names 38044 38047 38048 +1- 1 +-1 1 +.names 38082 38084 38049 +11 1 +.names 38049 38050 +1 1 +.names 38050 38051 +0 1 +.names 38057 22306 38052 +1- 1 +-1 1 +.names 38052 38053 +1 1 +.names 8303 38054 +0 1 +.names 38054 38055 +1 1 +.names 38055 38056 +0 1 +.names 8281 38056 38057 +1- 1 +-1 1 +.names 38062 38065 38058 +1- 1 +-1 1 +.names 38058 38059 +1 1 +.names 37391 37467 38060 +11 1 +.names 38060 38061 +1 1 +.names 38061 38062 +0 1 +.names 37379 37767 38063 +11 1 +.names 38063 38064 +1 1 +.names 38064 38065 +0 1 +.names 38059 38066 +0 1 +.names 38053 38067 +0 1 +.names 38041 38070 38068 +1- 1 +-1 1 +.names 38068 38069 +1 1 +.names 38033 38070 +0 1 +.names 137 38071 +0 1 +.names 38071 37375 38072 +1- 1 +-1 1 +.names 56633 38073 +0 1 +.names 38073 38054 38074 +1- 1 +-1 1 +.names 36511 38075 +0 1 +.names 37467 38075 38076 +1- 1 +-1 1 +.names 55566 55569 38077 +1- 1 +-1 1 +.names 38077 38078 +1 1 +.names 38078 38079 +0 1 +.names 37767 38079 38080 +1- 1 +-1 1 +.names 408 38081 +0 1 +.names 37379 38081 38082 +1- 1 +-1 1 +.names 7665 38083 +0 1 +.names 37391 38083 38084 +1- 1 +-1 1 +.names 38093 38096 38085 +1- 1 +-1 1 +.names 38085 38086 +1 1 +.names 38134 38136 38087 +11 1 +.names 38087 38088 +1 1 +.names 38088 38089 +0 1 +.names 38128 38132 38090 +11 1 +.names 38090 38091 +1 1 +.names 38091 38092 +0 1 +.names 38089 38092 38093 +1- 1 +-1 1 +.names 38118 38120 38094 +11 1 +.names 38094 38095 +1 1 +.names 38095 38096 +0 1 +.names 38101 32680 38097 +1- 1 +-1 1 +.names 38097 38098 +1 1 +.names 8295 38099 +1 1 +.names 38099 38100 +0 1 +.names 8309 38100 38101 +1- 1 +-1 1 +.names 37788 37468 38102 +11 1 +.names 38102 38103 +1 1 +.names 37379 37426 38104 +11 1 +.names 38104 38105 +1 1 +.names 38110 38111 38106 +11 1 +.names 38106 38107 +1 1 +.names 38125 38126 38108 +1- 1 +-1 1 +.names 38108 38109 +1 1 +.names 38109 38110 +0 1 +.names 38098 38111 +0 1 +.names 38086 38116 38112 +1- 1 +-1 1 +.names 38112 38113 +1 1 +.names 38122 38124 38114 +1- 1 +-1 1 +.names 38114 38115 +1 1 +.names 38115 38116 +0 1 +.names 144 38117 +0 1 +.names 38117 8295 38118 +1- 1 +-1 1 +.names 56640 38119 +0 1 +.names 38119 37468 38120 +1- 1 +-1 1 +.names 38107 38121 +0 1 +.names 37482 38121 38122 +11 1 +.names 37032 38123 +0 1 +.names 8284 38123 38124 +11 1 +.names 38103 38125 +0 1 +.names 38105 38126 +0 1 +.names 36624 38127 +0 1 +.names 37788 38127 38128 +1- 1 +-1 1 +.names 55674 55677 38129 +1- 1 +-1 1 +.names 38129 38130 +1 1 +.names 38130 38131 +0 1 +.names 37426 38131 38132 +1- 1 +-1 1 +.names 415 38133 +0 1 +.names 37379 38133 38134 +1- 1 +-1 1 +.names 7956 38135 +0 1 +.names 37457 38135 38136 +1- 1 +-1 1 +.names 38142 38144 38137 +1- 1 +-1 1 +.names 38137 38138 +1 1 +.names 38156 38157 38139 +11 1 +.names 38139 38140 +1 1 +.names 38140 38141 +0 1 +.names 37347 38141 38142 +11 1 +.names 37049 38143 +0 1 +.names 8271 38143 38144 +11 1 +.names 38149 32628 38145 +1- 1 +-1 1 +.names 38145 38146 +1 1 +.names 8295 38147 +1 1 +.names 38147 38148 +0 1 +.names 8307 38148 38149 +1- 1 +-1 1 +.names 37368 37379 38150 +11 1 +.names 38150 38151 +1 1 +.names 38054 37467 38152 +11 1 +.names 38152 38153 +1 1 +.names 38172 38173 38154 +1- 1 +-1 1 +.names 38154 38155 +1 1 +.names 38155 38156 +0 1 +.names 38146 38157 +0 1 +.names 38163 38165 38158 +11 1 +.names 38158 38159 +1 1 +.names 55621 55622 38160 +1- 1 +-1 1 +.names 38160 38161 +1 1 +.names 38161 38162 +0 1 +.names 37368 38162 38163 +1- 1 +-1 1 +.names 155 38164 +0 1 +.names 8295 38164 38165 +1- 1 +-1 1 +.names 38169 38171 38166 +11 1 +.names 38166 38167 +1 1 +.names 56651 38168 +0 1 +.names 38168 38054 38169 +1- 1 +-1 1 +.names 7756 38170 +0 1 +.names 37499 38170 38171 +1- 1 +-1 1 +.names 38151 38172 +0 1 +.names 38153 38173 +0 1 +.names 38178 38179 38174 +1- 1 +-1 1 +.names 38174 38175 +1 1 +.names 38182 38167 38176 +11 1 +.names 38176 38177 +1 1 +.names 38177 38178 +0 1 +.names 38138 38179 +0 1 +.names 38184 38186 38180 +11 1 +.names 38180 38181 +1 1 +.names 38159 38181 38182 +11 1 +.names 36634 38183 +0 1 +.names 37467 38183 38184 +1- 1 +-1 1 +.names 426 38185 +0 1 +.names 37379 38185 38186 +1- 1 +-1 1 +.names 37616 38187 +1 1 +.names 37943 38192 38188 +1- 1 +-1 1 +.names 38188 38189 +1 1 +.names 55803 55806 38190 +1- 1 +-1 1 +.names 38190 38191 +1 1 +.names 38191 38192 +0 1 +.names 38198 38200 38193 +1- 1 +-1 1 +.names 38193 38194 +1 1 +.names 38231 38232 38195 +11 1 +.names 38195 38196 +1 1 +.names 38196 38197 +0 1 +.names 37788 38197 38198 +11 1 +.names 36644 38199 +0 1 +.names 8318 38199 38200 +11 1 +.names 38204 38206 38201 +11 1 +.names 38201 38202 +1 1 +.names 153 38203 +0 1 +.names 38203 37616 38204 +1- 1 +-1 1 +.names 37066 38205 +0 1 +.names 37520 38205 38206 +1- 1 +-1 1 +.names 38219 38220 38207 +1- 1 +-1 1 +.names 38207 38208 +1 1 +.names 37457 38238 38209 +1- 1 +-1 1 +.names 38209 38210 +1 1 +.names 38210 38211 +0 1 +.names 38239 37468 38212 +1- 1 +-1 1 +.names 38212 38213 +1 1 +.names 38213 38214 +0 1 +.names 38211 38214 38215 +1- 1 +-1 1 +.names 37536 38242 38216 +1- 1 +-1 1 +.names 38216 38217 +1 1 +.names 38217 38218 +0 1 +.names 38215 38218 38219 +1- 1 +-1 1 +.names 38189 38220 +0 1 +.names 38224 32823 38221 +1- 1 +-1 1 +.names 38221 38222 +1 1 +.names 38187 38223 +0 1 +.names 8309 38223 38224 +1- 1 +-1 1 +.names 37943 37520 38225 +11 1 +.names 38225 38226 +1 1 +.names 37468 37536 38227 +11 1 +.names 38227 38228 +1 1 +.names 38240 38241 38229 +1- 1 +-1 1 +.names 38229 38230 +1 1 +.names 38230 38231 +0 1 +.names 38222 38232 +0 1 +.names 38236 38237 38233 +1- 1 +-1 1 +.names 38233 38234 +1 1 +.names 38194 38235 +0 1 +.names 38208 38235 38236 +1- 1 +-1 1 +.names 38202 38237 +0 1 +.names 7736 38238 +0 1 +.names 56649 38239 +0 1 +.names 38226 38240 +0 1 +.names 38228 38241 +0 1 +.names 424 38242 +0 1 +.names 38248 38250 38243 +1- 1 +-1 1 +.names 38243 38244 +1 1 +.names 38274 38275 38245 +11 1 +.names 38245 38246 +1 1 +.names 38246 38247 +0 1 +.names 37432 38247 38248 +11 1 +.names 36654 38249 +0 1 +.names 8259 38249 38250 +11 1 +.names 38259 38262 38251 +1- 1 +-1 1 +.names 38251 38252 +1 1 +.names 38280 38282 38253 +11 1 +.names 38253 38254 +1 1 +.names 38254 38255 +0 1 +.names 38288 38290 38256 +11 1 +.names 38256 38257 +1 1 +.names 38257 38258 +0 1 +.names 38255 38258 38259 +1- 1 +-1 1 +.names 38292 38294 38260 +11 1 +.names 38260 38261 +1 1 +.names 38261 38262 +0 1 +.names 38267 32858 38263 +1- 1 +-1 1 +.names 38263 38264 +1 1 +.names 8295 38265 +1 1 +.names 38265 38266 +0 1 +.names 8306 38266 38267 +1- 1 +-1 1 +.names 37943 37536 38268 +11 1 +.names 38268 38269 +1 1 +.names 37378 37482 38270 +11 1 +.names 38270 38271 +1 1 +.names 38283 38284 38272 +1- 1 +-1 1 +.names 38272 38273 +1 1 +.names 38273 38274 +0 1 +.names 38264 38275 +0 1 +.names 38252 38278 38276 +1- 1 +-1 1 +.names 38276 38277 +1 1 +.names 38244 38278 +0 1 +.names 160 38279 +0 1 +.names 38279 8295 38280 +1- 1 +-1 1 +.names 37083 38281 +0 1 +.names 37482 38281 38282 +1- 1 +-1 1 +.names 38269 38283 +0 1 +.names 38271 38284 +0 1 +.names 55818 55821 38285 +1- 1 +-1 1 +.names 38285 38286 +1 1 +.names 38286 38287 +0 1 +.names 37943 38287 38288 +1- 1 +-1 1 +.names 431 38289 +0 1 +.names 37536 38289 38290 +1- 1 +-1 1 +.names 56656 38291 +0 1 +.names 38291 37378 38292 +1- 1 +-1 1 +.names 7816 38293 +0 1 +.names 37391 38293 38294 +1- 1 +-1 1 +.names 38297 37482 38295 +1- 1 +-1 1 +.names 38295 38296 +1 1 +.names 37102 38297 +0 1 +.names 38302 38305 38298 +1- 1 +-1 1 +.names 38298 38299 +1 1 +.names 38309 38311 38300 +1- 1 +-1 1 +.names 38300 38301 +1 1 +.names 38301 38302 +0 1 +.names 38324 38327 38303 +11 1 +.names 38303 38304 +1 1 +.names 38304 38305 +0 1 +.names 38343 38344 38306 +11 1 +.names 38306 38307 +1 1 +.names 38307 38308 +0 1 +.names 37536 38308 38309 +11 1 +.names 439 38310 +0 1 +.names 8262 38310 38311 +11 1 +.names 38314 38316 38312 +1- 1 +-1 1 +.names 38312 38313 +1 1 +.names 38296 38314 +0 1 +.names 37426 38315 +1 1 +.names 38315 38316 +0 1 +.names 38314 38321 38317 +1- 1 +-1 1 +.names 38317 38318 +1 1 +.names 38356 38319 +0 1 +.names 38319 38320 +1 1 +.names 38320 38321 +0 1 +.names 38328 38331 38322 +1- 1 +-1 1 +.names 38322 38323 +1 1 +.names 38323 38324 +0 1 +.names 38345 38348 38325 +1- 1 +-1 1 +.names 38325 38326 +1 1 +.names 38326 38327 +0 1 +.names 38313 38318 38328 +11 1 +.names 38350 38352 38329 +11 1 +.names 38329 38330 +1 1 +.names 38330 38331 +0 1 +.names 38336 5787 38332 +1- 1 +-1 1 +.names 38332 38333 +1 1 +.names 8295 38334 +1 1 +.names 38334 38335 +0 1 +.names 8257 38335 38336 +1- 1 +-1 1 +.names 37391 38054 38337 +11 1 +.names 38337 38338 +1 1 +.names 37426 37482 38339 +11 1 +.names 38339 38340 +1 1 +.names 38353 38354 38341 +1- 1 +-1 1 +.names 38341 38342 +1 1 +.names 38342 38343 +0 1 +.names 38333 38344 +0 1 +.names 8303 56664 38345 +11 1 +.names 38357 37467 38346 +1- 1 +-1 1 +.names 38346 38347 +1 1 +.names 38347 38348 +0 1 +.names 168 38349 +0 1 +.names 8295 38349 38350 +1- 1 +-1 1 +.names 7906 38351 +0 1 +.names 37391 38351 38352 +1- 1 +-1 1 +.names 38338 38353 +0 1 +.names 38340 38354 +0 1 +.names 55859 55862 38355 +1- 1 +-1 1 +.names 38355 38356 +1 1 +.names 36664 38357 +0 1 +.names 38363 38365 38358 +1- 1 +-1 1 +.names 38358 38359 +1 1 +.names 38389 38390 38360 +11 1 +.names 38360 38361 +1 1 +.names 38361 38362 +0 1 +.names 37347 38362 38363 +11 1 +.names 37151 38364 +0 1 +.names 8271 38364 38365 +11 1 +.names 38374 38377 38366 +1- 1 +-1 1 +.names 38366 38367 +1 1 +.names 38401 38403 38368 +11 1 +.names 38368 38369 +1 1 +.names 38369 38370 +0 1 +.names 38407 38409 38371 +11 1 +.names 38371 38372 +1 1 +.names 38372 38373 +0 1 +.names 38370 38373 38374 +1- 1 +-1 1 +.names 38395 38397 38375 +11 1 +.names 38375 38376 +1 1 +.names 38376 38377 +0 1 +.names 38382 32928 38378 +1- 1 +-1 1 +.names 38378 38379 +1 1 +.names 37767 38380 +1 1 +.names 38380 38381 +0 1 +.names 8306 38381 38382 +1- 1 +-1 1 +.names 37788 37616 38383 +11 1 +.names 38383 38384 +1 1 +.names 38054 37536 38385 +11 1 +.names 38385 38386 +1 1 +.names 38404 38405 38387 +1- 1 +-1 1 +.names 38387 38388 +1 1 +.names 38388 38389 +0 1 +.names 38379 38390 +0 1 +.names 38367 38393 38391 +1- 1 +-1 1 +.names 38391 38392 +1 1 +.names 38359 38393 +0 1 +.names 56654 38394 +0 1 +.names 38394 38054 38395 +1- 1 +-1 1 +.names 7796 38396 +0 1 +.names 37391 38396 38397 +1- 1 +-1 1 +.names 55894 55897 38398 +1- 1 +-1 1 +.names 38398 38399 +1 1 +.names 38399 38400 +0 1 +.names 37767 38400 38401 +1- 1 +-1 1 +.names 158 38402 +0 1 +.names 38402 37616 38403 +1- 1 +-1 1 +.names 38384 38404 +0 1 +.names 38386 38405 +0 1 +.names 36674 38406 +0 1 +.names 37788 38406 38407 +1- 1 +-1 1 +.names 429 38408 +0 1 +.names 37536 38408 38409 +1- 1 +-1 1 +.names 38415 38417 38410 +1- 1 +-1 1 +.names 38410 38411 +1 1 +.names 38427 38428 38412 +11 1 +.names 38412 38413 +1 1 +.names 38413 38414 +0 1 +.names 37520 38414 38415 +11 1 +.names 37117 38416 +0 1 +.names 8283 38416 38417 +11 1 +.names 38422 22325 38418 +1- 1 +-1 1 +.names 38418 38419 +1 1 +.names 37546 38420 +1 1 +.names 38420 38421 +0 1 +.names 8309 38421 38422 +1- 1 +-1 1 +.names 37788 37616 38423 +11 1 +.names 38423 38424 +1 1 +.names 38450 38451 38425 +1- 1 +-1 1 +.names 38425 38426 +1 1 +.names 38426 38427 +0 1 +.names 38419 38428 +0 1 +.names 38432 38433 38429 +1- 1 +-1 1 +.names 38429 38430 +1 1 +.names 38460 38461 38431 +1- 1 +-1 1 +.names 38431 38432 +1 1 +.names 38411 38433 +0 1 +.names 37574 37435 38434 +11 1 +.names 38434 38435 +1 1 +.names 38441 38443 38436 +11 1 +.names 38436 38437 +1 1 +.names 55689 55692 38438 +1- 1 +-1 1 +.names 38438 38439 +1 1 +.names 38439 38440 +0 1 +.names 37546 38440 38441 +1- 1 +-1 1 +.names 139 38442 +0 1 +.names 38442 37616 38443 +1- 1 +-1 1 +.names 38447 38449 38444 +11 1 +.names 38444 38445 +1 1 +.names 56635 38446 +0 1 +.names 38446 37574 38447 +1- 1 +-1 1 +.names 7886 38448 +0 1 +.names 37457 38448 38449 +1- 1 +-1 1 +.names 38424 38450 +0 1 +.names 38435 38451 +0 1 +.names 38455 38457 38452 +11 1 +.names 38452 38453 +1 1 +.names 36604 38454 +0 1 +.names 37788 38454 38455 +1- 1 +-1 1 +.names 410 38456 +0 1 +.names 37435 38456 38457 +1- 1 +-1 1 +.names 38437 38458 +0 1 +.names 38453 38459 +0 1 +.names 38458 38459 38460 +1- 1 +-1 1 +.names 38445 38461 +0 1 +.names 38467 38469 38462 +1- 1 +-1 1 +.names 38462 38463 +1 1 +.names 38491 38492 38464 +11 1 +.names 38464 38465 +1 1 +.names 38465 38466 +0 1 +.names 37467 38466 38467 +11 1 +.names 36614 38468 +0 1 +.names 8257 38468 38469 +11 1 +.names 38478 38481 38470 +1- 1 +-1 1 +.names 38470 38471 +1 1 +.names 38501 38503 38472 +11 1 +.names 38472 38473 +1 1 +.names 38473 38474 +0 1 +.names 38509 38511 38475 +11 1 +.names 38475 38476 +1 1 +.names 38476 38477 +0 1 +.names 38474 38477 38478 +1- 1 +-1 1 +.names 38497 38499 38479 +11 1 +.names 38479 38480 +1 1 +.names 38480 38481 +0 1 +.names 38486 22346 38482 +1- 1 +-1 1 +.names 38482 38483 +1 1 +.names 8295 38484 +1 1 +.names 38484 38485 +0 1 +.names 8307 38485 38486 +1- 1 +-1 1 +.names 37468 37347 38487 +11 1 +.names 38487 38488 +1 1 +.names 38512 38513 38489 +1- 1 +-1 1 +.names 38489 38490 +1 1 +.names 38490 38491 +0 1 +.names 38483 38492 +0 1 +.names 38471 38495 38493 +1- 1 +-1 1 +.names 38493 38494 +1 1 +.names 38463 38495 +0 1 +.names 56638 38496 +0 1 +.names 37468 38496 38497 +1- 1 +-1 1 +.names 7936 38498 +0 1 +.names 37499 38498 38499 +1- 1 +-1 1 +.names 142 38500 +0 1 +.names 8295 38500 38501 +1- 1 +-1 1 +.names 37134 38502 +0 1 +.names 37347 38502 38503 +1- 1 +-1 1 +.names 37652 37435 38504 +11 1 +.names 38504 38505 +1 1 +.names 55734 55737 38506 +1- 1 +-1 1 +.names 38506 38507 +1 1 +.names 38507 38508 +0 1 +.names 37652 38508 38509 +1- 1 +-1 1 +.names 413 38510 +0 1 +.names 37435 38510 38511 +1- 1 +-1 1 +.names 38505 38512 +0 1 +.names 38488 38513 +0 1 +.names 37482 38516 38514 +1- 1 +-1 1 +.names 38514 38515 +1 1 +.names 37168 38516 +0 1 +.names 38521 38524 38517 +1- 1 +-1 1 +.names 38517 38518 +1 1 +.names 38573 38574 38519 +11 1 +.names 38519 38520 +1 1 +.names 38520 38521 +0 1 +.names 38528 38530 38522 +1- 1 +-1 1 +.names 38522 38523 +1 1 +.names 38523 38524 +0 1 +.names 38551 38554 38525 +11 1 +.names 38525 38526 +1 1 +.names 38526 38527 +0 1 +.names 37391 38527 38528 +11 1 +.names 7706 38529 +0 1 +.names 8306 38529 38530 +11 1 +.names 38533 38535 38531 +1- 1 +-1 1 +.names 38531 38532 +1 1 +.names 38515 38533 +0 1 +.names 37652 38534 +1 1 +.names 38534 38535 +0 1 +.names 38533 38540 38536 +1- 1 +-1 1 +.names 38536 38537 +1 1 +.names 38542 38538 +0 1 +.names 38538 38539 +1 1 +.names 38539 38540 +0 1 +.names 55960 55963 38541 +1- 1 +-1 1 +.names 38541 38542 +1 1 +.names 38547 38550 38543 +1- 1 +-1 1 +.names 38543 38544 +1 1 +.names 37482 37467 38545 +11 1 +.names 38545 38546 +1 1 +.names 38546 38547 +0 1 +.names 37435 37652 38548 +11 1 +.names 38548 38549 +1 1 +.names 38549 38550 +0 1 +.names 38544 38551 +0 1 +.names 38570 32970 38552 +1- 1 +-1 1 +.names 38552 38553 +1 1 +.names 38553 38554 +0 1 +.names 38558 38560 38555 +11 1 +.names 38555 38556 +1 1 +.names 36685 38557 +0 1 +.names 37467 38557 38558 +1- 1 +-1 1 +.names 150 38559 +0 1 +.names 8295 38559 38560 +1- 1 +-1 1 +.names 37435 38563 38561 +1- 1 +-1 1 +.names 38561 38562 +1 1 +.names 421 38563 +0 1 +.names 38566 38567 38564 +1- 1 +-1 1 +.names 38564 38565 +1 1 +.names 8304 56646 38566 +11 1 +.names 38562 38567 +0 1 +.names 8295 38568 +1 1 +.names 38568 38569 +0 1 +.names 8304 38569 38570 +1- 1 +-1 1 +.names 38575 38576 38571 +1- 1 +-1 1 +.names 38571 38572 +1 1 +.names 38572 38573 +0 1 +.names 38565 38574 +0 1 +.names 38532 38537 38575 +11 1 +.names 38556 38576 +0 1 +.names 38582 38584 38577 +1- 1 +-1 1 +.names 38577 38578 +1 1 +.names 38608 38609 38579 +11 1 +.names 38579 38580 +1 1 +.names 38580 38581 +0 1 +.names 37482 38581 38582 +11 1 +.names 37185 38583 +0 1 +.names 8284 38583 38584 +11 1 +.names 38593 38596 38585 +1- 1 +-1 1 +.names 38585 38586 +1 1 +.names 38616 38618 38587 +11 1 +.names 38587 38588 +1 1 +.names 38588 38589 +0 1 +.names 38626 38628 38590 +11 1 +.names 38590 38591 +1 1 +.names 38591 38592 +0 1 +.names 38589 38592 38593 +1- 1 +-1 1 +.names 38620 38622 38594 +11 1 +.names 38594 38595 +1 1 +.names 38595 38596 +0 1 +.names 38601 33004 38597 +1- 1 +-1 1 +.names 38597 38598 +1 1 +.names 37546 38599 +1 1 +.names 38599 38600 +0 1 +.names 8306 38600 38601 +1- 1 +-1 1 +.names 37432 37616 38602 +11 1 +.names 38602 38603 +1 1 +.names 37378 37536 38604 +11 1 +.names 38604 38605 +1 1 +.names 38623 38624 38606 +1- 1 +-1 1 +.names 38606 38607 +1 1 +.names 38607 38608 +0 1 +.names 38598 38609 +0 1 +.names 38586 38612 38610 +1- 1 +-1 1 +.names 38610 38611 +1 1 +.names 38578 38612 +0 1 +.names 55975 55978 38613 +1- 1 +-1 1 +.names 38613 38614 +1 1 +.names 38614 38615 +0 1 +.names 37546 38615 38616 +1- 1 +-1 1 +.names 151 38617 +0 1 +.names 38617 37616 38618 +1- 1 +-1 1 +.names 56647 38619 +0 1 +.names 38619 37378 38620 +1- 1 +-1 1 +.names 7716 38621 +0 1 +.names 37391 38621 38622 +1- 1 +-1 1 +.names 38603 38623 +0 1 +.names 38605 38624 +0 1 +.names 36695 38625 +0 1 +.names 37432 38625 38626 +1- 1 +-1 1 +.names 422 38627 +0 1 +.names 37536 38627 38628 +1- 1 +-1 1 +.names 38634 38636 38629 +1- 1 +-1 1 +.names 38629 38630 +1 1 +.names 38660 38661 38631 +11 1 +.names 38631 38632 +1 1 +.names 38632 38633 +0 1 +.names 37520 38633 38634 +11 1 +.names 37204 38635 +0 1 +.names 8283 38635 38636 +11 1 +.names 38645 38648 38637 +1- 1 +-1 1 +.names 38637 38638 +1 1 +.names 38674 38676 38639 +11 1 +.names 38639 38640 +1 1 +.names 38640 38641 +0 1 +.names 38678 38680 38642 +11 1 +.names 38642 38643 +1 1 +.names 38643 38644 +0 1 +.names 38641 38644 38645 +1- 1 +-1 1 +.names 38666 38668 38646 +11 1 +.names 38646 38647 +1 1 +.names 38647 38648 +0 1 +.names 38653 34818 38649 +1- 1 +-1 1 +.names 38649 38650 +1 1 +.names 37368 38651 +1 1 +.names 38651 38652 +0 1 +.names 8309 38652 38653 +1- 1 +-1 1 +.names 37432 37616 38654 +11 1 +.names 38654 38655 +1 1 +.names 38054 37536 38656 +11 1 +.names 38656 38657 +1 1 +.names 38669 38670 38658 +1- 1 +-1 1 +.names 38658 38659 +1 1 +.names 38659 38660 +0 1 +.names 38650 38661 +0 1 +.names 38638 38664 38662 +1- 1 +-1 1 +.names 38662 38663 +1 1 +.names 38630 38664 +0 1 +.names 56661 38665 +0 1 +.names 38665 38054 38666 +1- 1 +-1 1 +.names 7866 38667 +0 1 +.names 37457 38667 38668 +1- 1 +-1 1 +.names 38655 38669 +0 1 +.names 38657 38670 +0 1 +.names 56016 56019 38671 +1- 1 +-1 1 +.names 38671 38672 +1 1 +.names 38672 38673 +0 1 +.names 37368 38673 38674 +1- 1 +-1 1 +.names 165 38675 +0 1 +.names 38675 37616 38676 +1- 1 +-1 1 +.names 36705 38677 +0 1 +.names 37432 38677 38678 +1- 1 +-1 1 +.names 436 38679 +0 1 +.names 37536 38679 38680 +1- 1 +-1 1 +.names 38686 38688 38681 +1- 1 +-1 1 +.names 38681 38682 +1 1 +.names 38712 38713 38683 +11 1 +.names 38683 38684 +1 1 +.names 38684 38685 +0 1 +.names 37788 38685 38686 +11 1 +.names 36715 38687 +0 1 +.names 8318 38687 38688 +11 1 +.names 38697 38700 38689 +1- 1 +-1 1 +.names 38689 38690 +1 1 +.names 38718 38720 38691 +11 1 +.names 38691 38692 +1 1 +.names 38692 38693 +0 1 +.names 38730 38732 38694 +11 1 +.names 38694 38695 +1 1 +.names 38695 38696 +0 1 +.names 38693 38696 38697 +1- 1 +-1 1 +.names 38722 38724 38698 +11 1 +.names 38698 38699 +1 1 +.names 38699 38700 +0 1 +.names 38705 33087 38701 +1- 1 +-1 1 +.names 38701 38702 +1 1 +.names 37375 38703 +1 1 +.names 38703 38704 +0 1 +.names 8307 38704 38705 +1- 1 +-1 1 +.names 37943 37482 38706 +11 1 +.names 38706 38707 +1 1 +.names 37378 37379 38708 +11 1 +.names 38708 38709 +1 1 +.names 38725 38726 38710 +1- 1 +-1 1 +.names 38710 38711 +1 1 +.names 38711 38712 +0 1 +.names 38702 38713 +0 1 +.names 38690 38716 38714 +1- 1 +-1 1 +.names 38714 38715 +1 1 +.names 38682 38716 +0 1 +.names 149 38717 +0 1 +.names 38717 37375 38718 +1- 1 +-1 1 +.names 37219 38719 +0 1 +.names 37482 38719 38720 +1- 1 +-1 1 +.names 56645 38721 +0 1 +.names 38721 37378 38722 +1- 1 +-1 1 +.names 7696 38723 +0 1 +.names 37499 38723 38724 +1- 1 +-1 1 +.names 38707 38725 +0 1 +.names 38709 38726 +0 1 +.names 56083 56086 38727 +1- 1 +-1 1 +.names 38727 38728 +1 1 +.names 38728 38729 +0 1 +.names 37943 38729 38730 +1- 1 +-1 1 +.names 420 38731 +0 1 +.names 37379 38731 38732 +1- 1 +-1 1 +.names 38738 38740 38733 +1- 1 +-1 1 +.names 38733 38734 +1 1 +.names 38765 38766 38735 +11 1 +.names 38735 38736 +1 1 +.names 38736 38737 +0 1 +.names 37347 38737 38738 +11 1 +.names 37236 38739 +0 1 +.names 8271 38739 38740 +11 1 +.names 38749 38752 38741 +1- 1 +-1 1 +.names 38741 38742 +1 1 +.names 38783 38785 38743 +11 1 +.names 38743 38744 +1 1 +.names 38744 38745 +0 1 +.names 38777 38779 38746 +11 1 +.names 38746 38747 +1 1 +.names 38747 38748 +0 1 +.names 38745 38748 38749 +1- 1 +-1 1 +.names 38773 38775 38750 +11 1 +.names 38750 38751 +1 1 +.names 38751 38752 +0 1 +.names 38757 38758 38753 +1- 1 +-1 1 +.names 38753 38754 +1 1 +.names 37767 38755 +1 1 +.names 38755 38756 +0 1 +.names 8307 38756 38757 +1- 1 +-1 1 +.names 56589 38758 +0 1 +.names 37788 37375 38759 +11 1 +.names 38759 38760 +1 1 +.names 37378 37536 38761 +11 1 +.names 38761 38762 +1 1 +.names 38770 38771 38763 +1- 1 +-1 1 +.names 38763 38764 +1 1 +.names 38764 38765 +0 1 +.names 38754 38766 +0 1 +.names 38742 38769 38767 +1- 1 +-1 1 +.names 38767 38768 +1 1 +.names 38734 38769 +0 1 +.names 38760 38770 +0 1 +.names 38762 38771 +0 1 +.names 56659 38772 +0 1 +.names 38772 37378 38773 +1- 1 +-1 1 +.names 7846 38774 +0 1 +.names 37499 38774 38775 +1- 1 +-1 1 +.names 36725 38776 +0 1 +.names 37788 38776 38777 +1- 1 +-1 1 +.names 434 38778 +0 1 +.names 37536 38778 38779 +1- 1 +-1 1 +.names 56098 56101 38780 +1- 1 +-1 1 +.names 38780 38781 +1 1 +.names 38781 38782 +0 1 +.names 37767 38782 38783 +1- 1 +-1 1 +.names 163 38784 +0 1 +.names 38784 37375 38785 +1- 1 +-1 1 +.names 38788 37347 38786 +1- 1 +-1 1 +.names 38786 38787 +1 1 +.names 37255 38788 +0 1 +.names 38793 38796 38789 +1- 1 +-1 1 +.names 38789 38790 +1 1 +.names 38815 38818 38791 +11 1 +.names 38791 38792 +1 1 +.names 38792 38793 +0 1 +.names 38800 38802 38794 +1- 1 +-1 1 +.names 38794 38795 +1 1 +.names 38795 38796 +0 1 +.names 38836 38837 38797 +11 1 +.names 38797 38798 +1 1 +.names 38798 38799 +0 1 +.names 37379 38799 38800 +11 1 +.names 435 38801 +0 1 +.names 8264 38801 38802 +11 1 +.names 38805 38807 38803 +1- 1 +-1 1 +.names 38803 38804 +1 1 +.names 38787 38805 +0 1 +.names 37368 38806 +1 1 +.names 38806 38807 +0 1 +.names 38805 38812 38808 +1- 1 +-1 1 +.names 38808 38809 +1 1 +.names 38847 38810 +0 1 +.names 38810 38811 +1 1 +.names 38811 38812 +0 1 +.names 38819 38822 38813 +1- 1 +-1 1 +.names 38813 38814 +1 1 +.names 38814 38815 +0 1 +.names 38842 38845 38816 +1- 1 +-1 1 +.names 38816 38817 +1 1 +.names 38817 38818 +0 1 +.names 38804 38809 38819 +11 1 +.names 38839 38841 38820 +11 1 +.names 38820 38821 +1 1 +.names 38821 38822 +0 1 +.names 38827 33161 38823 +1- 1 +-1 1 +.names 38823 38824 +1 1 +.names 37375 38825 +1 1 +.names 38825 38826 +0 1 +.names 8257 38826 38827 +1- 1 +-1 1 +.names 38832 38835 38828 +1- 1 +-1 1 +.names 38828 38829 +1 1 +.names 37574 37347 38830 +11 1 +.names 38830 38831 +1 1 +.names 38831 38832 +0 1 +.names 37368 37499 38833 +11 1 +.names 38833 38834 +1 1 +.names 38834 38835 +0 1 +.names 38829 38836 +0 1 +.names 38824 38837 +0 1 +.names 164 38838 +0 1 +.names 37375 38838 38839 +1- 1 +-1 1 +.names 7856 38840 +0 1 +.names 37499 38840 38841 +1- 1 +-1 1 +.names 8304 56660 38842 +11 1 +.names 38848 37467 38843 +1- 1 +-1 1 +.names 38843 38844 +1 1 +.names 38844 38845 +0 1 +.names 56142 56145 38846 +1- 1 +-1 1 +.names 38846 38847 +1 1 +.names 36735 38848 +0 1 +.names 38854 38856 38849 +1- 1 +-1 1 +.names 38849 38850 +1 1 +.names 38880 38881 38851 +11 1 +.names 38851 38852 +1 1 +.names 38852 38853 +0 1 +.names 37520 38853 38854 +11 1 +.names 37270 38855 +0 1 +.names 8283 38855 38856 +11 1 +.names 38865 38868 38857 +1- 1 +-1 1 +.names 38857 38858 +1 1 +.names 38894 38896 38859 +11 1 +.names 38859 38860 +1 1 +.names 38860 38861 +0 1 +.names 38898 38900 38862 +11 1 +.names 38862 38863 +1 1 +.names 38863 38864 +0 1 +.names 38861 38864 38865 +1- 1 +-1 1 +.names 38886 38888 38866 +11 1 +.names 38866 38867 +1 1 +.names 38867 38868 +0 1 +.names 38873 22359 38869 +1- 1 +-1 1 +.names 38869 38870 +1 1 +.names 37368 38871 +1 1 +.names 38871 38872 +0 1 +.names 8309 38872 38873 +1- 1 +-1 1 +.names 37788 37616 38874 +11 1 +.names 38874 38875 +1 1 +.names 38054 37379 38876 +11 1 +.names 38876 38877 +1 1 +.names 38889 38890 38878 +1- 1 +-1 1 +.names 38878 38879 +1 1 +.names 38879 38880 +0 1 +.names 38870 38881 +0 1 +.names 38858 38884 38882 +1- 1 +-1 1 +.names 38882 38883 +1 1 +.names 38850 38884 +0 1 +.names 56636 38885 +0 1 +.names 38885 38054 38886 +1- 1 +-1 1 +.names 7916 38887 +0 1 +.names 37457 38887 38888 +1- 1 +-1 1 +.names 38875 38889 +0 1 +.names 38877 38890 +0 1 +.names 56205 56208 38891 +1- 1 +-1 1 +.names 38891 38892 +1 1 +.names 38892 38893 +0 1 +.names 37368 38893 38894 +1- 1 +-1 1 +.names 140 38895 +0 1 +.names 38895 37616 38896 +1- 1 +-1 1 +.names 36745 38897 +0 1 +.names 37788 38897 38898 +1- 1 +-1 1 +.names 411 38899 +0 1 +.names 37379 38899 38900 +1- 1 +-1 1 +.names 38906 38908 38901 +1- 1 +-1 1 +.names 38901 38902 +1 1 +.names 38932 38933 38903 +11 1 +.names 38903 38904 +1 1 +.names 38904 38905 +0 1 +.names 37520 38905 38906 +11 1 +.names 37287 38907 +0 1 +.names 8283 38907 38908 +11 1 +.names 38917 38920 38909 +1- 1 +-1 1 +.names 38909 38910 +1 1 +.names 38946 38948 38911 +11 1 +.names 38911 38912 +1 1 +.names 38912 38913 +0 1 +.names 38950 38952 38914 +11 1 +.names 38914 38915 +1 1 +.names 38915 38916 +0 1 +.names 38913 38916 38917 +1- 1 +-1 1 +.names 38938 38940 38918 +11 1 +.names 38918 38919 +1 1 +.names 38919 38920 +0 1 +.names 38925 22376 38921 +1- 1 +-1 1 +.names 38921 38922 +1 1 +.names 37546 38923 +1 1 +.names 38923 38924 +0 1 +.names 8307 38924 38925 +1- 1 +-1 1 +.names 37374 37375 38926 +11 1 +.names 38926 38927 +1 1 +.names 37378 37379 38928 +11 1 +.names 38928 38929 +1 1 +.names 38941 38942 38930 +1- 1 +-1 1 +.names 38930 38931 +1 1 +.names 38931 38932 +0 1 +.names 38922 38933 +0 1 +.names 38910 38936 38934 +1- 1 +-1 1 +.names 38934 38935 +1 1 +.names 38902 38936 +0 1 +.names 56637 38937 +0 1 +.names 38937 37378 38938 +1- 1 +-1 1 +.names 7926 38939 +0 1 +.names 37499 38939 38940 +1- 1 +-1 1 +.names 38927 38941 +0 1 +.names 38929 38942 +0 1 +.names 56220 56223 38943 +1- 1 +-1 1 +.names 38943 38944 +1 1 +.names 38944 38945 +0 1 +.names 37546 38945 38946 +1- 1 +-1 1 +.names 141 38947 +0 1 +.names 38947 37375 38948 +1- 1 +-1 1 +.names 36755 38949 +0 1 +.names 37374 38949 38950 +1- 1 +-1 1 +.names 412 38951 +0 1 +.names 37379 38951 38952 +1- 1 +-1 1 +.names 38959 38961 38953 +1- 1 +-1 1 +.names 38953 38954 +1 1 +.names 8294 38955 +0 1 +.names 38983 38984 38956 +11 1 +.names 38956 38957 +1 1 +.names 38957 38958 +0 1 +.names 38955 38958 38959 +11 1 +.names 152 38960 +0 1 +.names 8294 38960 38961 +11 1 +.names 38970 38973 38962 +1- 1 +-1 1 +.names 38962 38963 +1 1 +.names 38995 38997 38964 +11 1 +.names 38964 38965 +1 1 +.names 38965 38966 +0 1 +.names 39001 39005 38967 +11 1 +.names 38967 38968 +1 1 +.names 38968 38969 +0 1 +.names 38966 38969 38970 +1- 1 +-1 1 +.names 38989 38991 38971 +11 1 +.names 38971 38972 +1 1 +.names 38972 38973 +0 1 +.names 38976 38978 38974 +1- 1 +-1 1 +.names 38974 38975 +1 1 +.names 8271 33274 38976 +1- 1 +-1 1 +.names 37374 38977 +1 1 +.names 38977 38978 +0 1 +.names 37391 37468 38979 +11 1 +.names 38979 38980 +1 1 +.names 38998 38999 38981 +1- 1 +-1 1 +.names 38981 38982 +1 1 +.names 38982 38983 +0 1 +.names 38975 38984 +0 1 +.names 38963 38987 38985 +1- 1 +-1 1 +.names 38985 38986 +1 1 +.names 38954 38987 +0 1 +.names 36765 38988 +0 1 +.names 37374 38988 38989 +1- 1 +-1 1 +.names 56648 38990 +0 1 +.names 37468 38990 38991 +1- 1 +-1 1 +.names 37435 37652 38992 +11 1 +.names 38992 38993 +1 1 +.names 423 38994 +0 1 +.names 37435 38994 38995 +1- 1 +-1 1 +.names 37305 38996 +0 1 +.names 37347 38996 38997 +1- 1 +-1 1 +.names 38980 38998 +0 1 +.names 38993 38999 +0 1 +.names 7726 39000 +0 1 +.names 37391 39000 39001 +1- 1 +-1 1 +.names 56259 56262 39002 +1- 1 +-1 1 +.names 39002 39003 +1 1 +.names 39003 39004 +0 1 +.names 37652 39004 39005 +1- 1 +-1 1 +.names 39011 39013 39006 +1- 1 +-1 1 +.names 39006 39007 +1 1 +.names 39025 39026 39008 +11 1 +.names 39008 39009 +1 1 +.names 39009 39010 +0 1 +.names 37520 39010 39011 +11 1 +.names 37321 39012 +0 1 +.names 8283 39012 39013 +11 1 +.names 39018 33316 39014 +1- 1 +-1 1 +.names 39014 39015 +1 1 +.names 8295 39016 +1 1 +.names 39016 39017 +0 1 +.names 8306 39017 39018 +1- 1 +-1 1 +.names 37374 37468 39019 +11 1 +.names 39019 39020 +1 1 +.names 37536 37652 39021 +11 1 +.names 39021 39022 +1 1 +.names 39056 39057 39023 +1- 1 +-1 1 +.names 39023 39024 +1 1 +.names 39024 39025 +0 1 +.names 39015 39026 +0 1 +.names 39030 39031 39027 +1- 1 +-1 1 +.names 39027 39028 +1 1 +.names 39054 39055 39029 +1- 1 +-1 1 +.names 39029 39030 +1 1 +.names 39007 39031 +0 1 +.names 39035 39039 39032 +11 1 +.names 39032 39033 +1 1 +.names 36775 39034 +0 1 +.names 37374 39034 39035 +1- 1 +-1 1 +.names 56331 56332 39036 +1- 1 +-1 1 +.names 39036 39037 +1 1 +.names 39037 39038 +0 1 +.names 37652 39038 39039 +1- 1 +-1 1 +.names 39043 39045 39040 +11 1 +.names 39040 39041 +1 1 +.names 428 39042 +0 1 +.names 37536 39042 39043 +1- 1 +-1 1 +.names 7786 39044 +0 1 +.names 37391 39044 39045 +1- 1 +-1 1 +.names 39049 39051 39046 +11 1 +.names 39046 39047 +1 1 +.names 157 39048 +0 1 +.names 39048 8295 39049 +1- 1 +-1 1 +.names 56653 39050 +0 1 +.names 39050 37468 39051 +1- 1 +-1 1 +.names 39041 39052 +0 1 +.names 39033 39053 +0 1 +.names 39052 39053 39054 +1- 1 +-1 1 +.names 39047 39055 +0 1 +.names 39020 39056 +0 1 +.names 39022 39057 +0 1 +.names 39063 39065 39058 +1- 1 +-1 1 +.names 39058 39059 +1 1 +.names 39090 39091 39060 +11 1 +.names 39060 39061 +1 1 +.names 39061 39062 +0 1 +.names 37482 39062 39063 +11 1 +.names 37338 39064 +0 1 +.names 8284 39064 39065 +11 1 +.names 39074 39077 39066 +1- 1 +-1 1 +.names 39066 39067 +1 1 +.names 39098 39100 39068 +11 1 +.names 39068 39069 +1 1 +.names 39069 39070 +0 1 +.names 39106 39108 39071 +11 1 +.names 39071 39072 +1 1 +.names 39072 39073 +0 1 +.names 39070 39073 39074 +1- 1 +-1 1 +.names 39102 39104 39075 +11 1 +.names 39075 39076 +1 1 +.names 39076 39077 +0 1 +.names 39082 39083 39078 +1- 1 +-1 1 +.names 39078 39079 +1 1 +.names 37767 39080 +1 1 +.names 39080 39081 +0 1 +.names 8306 39081 39082 +1- 1 +-1 1 +.names 56592 39083 +0 1 +.names 37374 37616 39084 +11 1 +.names 39084 39085 +1 1 +.names 37378 37379 39086 +11 1 +.names 39086 39087 +1 1 +.names 39109 39110 39088 +1- 1 +-1 1 +.names 39088 39089 +1 1 +.names 39089 39090 +0 1 +.names 39079 39091 +0 1 +.names 39067 39094 39092 +1- 1 +-1 1 +.names 39092 39093 +1 1 +.names 39059 39094 +0 1 +.names 56340 56343 39095 +1- 1 +-1 1 +.names 39095 39096 +1 1 +.names 39096 39097 +0 1 +.names 37767 39097 39098 +1- 1 +-1 1 +.names 166 39099 +0 1 +.names 39099 37616 39100 +1- 1 +-1 1 +.names 56662 39101 +0 1 +.names 39101 37378 39102 +1- 1 +-1 1 +.names 7876 39103 +0 1 +.names 37391 39103 39104 +1- 1 +-1 1 +.names 36785 39105 +0 1 +.names 37374 39105 39106 +1- 1 +-1 1 +.names 437 39107 +0 1 +.names 37379 39107 39108 +1- 1 +-1 1 +.names 39085 39109 +0 1 +.names 39087 39110 +0 1 +.names 39113 39114 39111 +1- 1 +-1 1 +.names 39111 39112 +1 1 +.names 8334 39113 +0 1 +.names 1380 39114 +0 1 +.names 39114 39117 39115 +1- 1 +-1 1 +.names 39115 39116 +1 1 +.names 8355 39117 +0 1 +.names 39124 39127 39118 +1- 1 +-1 1 +.names 39118 39119 +1 1 +.names 39131 39132 39120 +1- 1 +-1 1 +.names 39120 39121 +1 1 +.names 39121 39122 +0 1 +.names 39116 39123 +0 1 +.names 39122 39123 39124 +1- 1 +-1 1 +.names 39135 39137 39125 +11 1 +.names 39125 39126 +1 1 +.names 39126 39127 +0 1 +.names 39148 39149 39128 +11 1 +.names 39128 39129 +1 1 +.names 39129 39130 +0 1 +.names 2413 39130 39131 +11 1 +.names 1783 2413 39132 +11 1 +.names 8344 39150 39133 +1- 1 +-1 1 +.names 39133 39134 +1 1 +.names 39134 39112 39135 +11 1 +.names 8352 39114 39136 +1- 1 +-1 1 +.names 39136 39137 +1 1 +.names 39142 39143 39138 +1- 1 +-1 1 +.names 39138 39139 +1 1 +.names 39113 39140 +1 1 +.names 39140 39141 +0 1 +.names 8355 39141 39142 +1- 1 +-1 1 +.names 1381 39143 +0 1 +.names 8357 39147 39144 +1- 1 +-1 1 +.names 39144 39145 +1 1 +.names 8352 39146 +1 1 +.names 39146 39147 +0 1 +.names 39139 39148 +0 1 +.names 39145 39149 +0 1 +.names 1382 39150 +0 1 +.names 39153 39117 39151 +1- 1 +-1 1 +.names 39151 39152 +1 1 +.names 1383 39153 +0 1 +.names 39160 39162 39154 +1- 1 +-1 1 +.names 39154 39155 +1 1 +.names 8356 39156 +0 1 +.names 39172 39173 39157 +11 1 +.names 39157 39158 +1 1 +.names 39158 39159 +0 1 +.names 39156 39159 39160 +11 1 +.names 1384 39161 +0 1 +.names 8356 39161 39162 +11 1 +.names 39167 39150 39163 +1- 1 +-1 1 +.names 39163 39164 +1 1 +.names 8352 39165 +1 1 +.names 39165 39166 +0 1 +.names 8366 39166 39167 +1- 1 +-1 1 +.names 8355 39171 39168 +1- 1 +-1 1 +.names 39168 39169 +1 1 +.names 2413 39170 +1 1 +.names 39170 39171 +0 1 +.names 39164 39172 +0 1 +.names 39169 39173 +0 1 +.names 39189 39190 39174 +1- 1 +-1 1 +.names 39174 39175 +1 1 +.names 39155 39176 +0 1 +.names 8352 39150 39177 +1- 1 +-1 1 +.names 39177 39178 +1 1 +.names 2413 39179 +1 1 +.names 39179 39180 +1 1 +.names 39183 39184 39181 +1- 1 +-1 1 +.names 39181 39182 +1 1 +.names 1385 39183 +0 1 +.names 8366 39184 +0 1 +.names 39180 39185 +0 1 +.names 39182 39186 +0 1 +.names 39185 39186 39187 +1- 1 +-1 1 +.names 39178 39188 +0 1 +.names 39187 39188 39189 +1- 1 +-1 1 +.names 39152 39190 +0 1 +.names 39205 39207 39191 +1- 1 +-1 1 +.names 39191 39192 +1 1 +.names 39192 39193 +0 1 +.names 2413 39194 +1 1 +.names 39194 39195 +1 1 +.names 39195 39196 +0 1 +.names 39193 39196 39197 +1- 1 +-1 1 +.names 39212 39214 39198 +11 1 +.names 39198 39199 +1 1 +.names 39199 39200 +0 1 +.names 8326 39201 +0 1 +.names 39221 39222 39202 +11 1 +.names 39202 39203 +1 1 +.names 39203 39204 +0 1 +.names 39201 39204 39205 +11 1 +.names 1386 39206 +0 1 +.names 8326 39206 39207 +11 1 +.names 39156 2413 39208 +1- 1 +-1 1 +.names 39208 39209 +1 1 +.names 8344 39230 39210 +1- 1 +-1 1 +.names 39210 39211 +1 1 +.names 39209 39211 39212 +11 1 +.names 39223 39224 39213 +1- 1 +-1 1 +.names 39213 39214 +1 1 +.names 8357 39218 39215 +1- 1 +-1 1 +.names 39215 39216 +1 1 +.names 2413 39217 +1 1 +.names 39217 39218 +0 1 +.names 39229 39223 39219 +1- 1 +-1 1 +.names 39219 39220 +1 1 +.names 39220 39221 +0 1 +.names 39216 39222 +0 1 +.names 1387 39223 +0 1 +.names 8341 39224 +0 1 +.names 39224 39225 +1 1 +.names 39225 39226 +0 1 +.names 39156 39227 +1 1 +.names 39227 39228 +0 1 +.names 39226 39228 39229 +1- 1 +-1 1 +.names 1388 39230 +0 1 +.names 39245 39246 39231 +1- 1 +-1 1 +.names 39231 39232 +1 1 +.names 39232 39233 +0 1 +.names 2413 39234 +1 1 +.names 39234 39235 +1 1 +.names 39235 39236 +0 1 +.names 39233 39236 39237 +1- 1 +-1 1 +.names 39264 39265 39238 +11 1 +.names 39238 39239 +1 1 +.names 39239 39240 +0 1 +.names 8362 39241 +0 1 +.names 39253 39254 39242 +11 1 +.names 39242 39243 +1 1 +.names 39243 39244 +0 1 +.names 39241 39244 39245 +11 1 +.names 8362 39114 39246 +11 1 +.names 8361 39250 39247 +1- 1 +-1 1 +.names 39247 39248 +1 1 +.names 2413 39249 +1 1 +.names 39249 39250 +0 1 +.names 39272 39273 39251 +1- 1 +-1 1 +.names 39251 39252 +1 1 +.names 39252 39253 +0 1 +.names 39248 39254 +0 1 +.names 39114 39257 39255 +1- 1 +-1 1 +.names 39255 39256 +1 1 +.names 8361 39257 +0 1 +.names 39260 39261 39258 +1- 1 +-1 1 +.names 39258 39259 +1 1 +.names 1382 8335 39260 +11 1 +.names 39256 39261 +0 1 +.names 8365 1389 39262 +11 1 +.names 39262 39263 +1 1 +.names 39263 39264 +0 1 +.names 39259 39265 +0 1 +.names 8335 39266 +0 1 +.names 39266 39267 +1 1 +.names 8365 39268 +0 1 +.names 39268 39269 +1 1 +.names 39269 39270 +0 1 +.names 39267 39271 +0 1 +.names 39270 39271 39272 +1- 1 +-1 1 +.names 1390 39273 +0 1 +.names 39266 39114 39274 +1- 1 +-1 1 +.names 39274 39275 +1 1 +.names 39114 8352 39276 +1- 1 +-1 1 +.names 39276 39277 +1 1 +.names 8364 39281 39278 +1- 1 +-1 1 +.names 39278 39279 +1 1 +.names 2413 39280 +1 1 +.names 39280 39281 +0 1 +.names 39287 39288 39282 +1- 1 +-1 1 +.names 39282 39283 +1 1 +.names 39291 39292 39284 +11 1 +.names 39284 39285 +1 1 +.names 39285 39286 +0 1 +.names 39241 39286 39287 +11 1 +.names 8362 39114 39288 +11 1 +.names 39295 39296 39289 +1- 1 +-1 1 +.names 39289 39290 +1 1 +.names 39290 39291 +0 1 +.names 39279 39292 +0 1 +.names 39266 39293 +1 1 +.names 39293 39294 +0 1 +.names 8338 39294 39295 +1- 1 +-1 1 +.names 1391 39296 +0 1 +.names 39303 39304 39297 +1- 1 +-1 1 +.names 39297 39298 +1 1 +.names 39275 39299 +0 1 +.names 39313 39314 39300 +1- 1 +-1 1 +.names 39300 39301 +1 1 +.names 39301 39302 +0 1 +.names 39299 39302 39303 +1- 1 +-1 1 +.names 39277 39304 +0 1 +.names 39307 39310 39305 +11 1 +.names 39305 39306 +1 1 +.names 39298 39307 +0 1 +.names 1783 39308 +1 1 +.names 39308 39309 +1 1 +.names 39309 39310 +0 1 +.names 39283 39311 +0 1 +.names 39306 39312 +0 1 +.names 8364 39313 +0 1 +.names 1392 39314 +0 1 +.names 39323 39326 39315 +1- 1 +-1 1 +.names 39315 39316 +1 1 +.names 39331 39332 39317 +1- 1 +-1 1 +.names 39317 39318 +1 1 +.names 39318 39319 +0 1 +.names 2413 39320 +1 1 +.names 39320 39321 +1 1 +.names 39321 39322 +0 1 +.names 39319 39322 39323 +1- 1 +-1 1 +.names 39351 39348 39324 +11 1 +.names 39324 39325 +1 1 +.names 39325 39326 +0 1 +.names 8351 39327 +0 1 +.names 39343 39344 39328 +11 1 +.names 39328 39329 +1 1 +.names 39329 39330 +0 1 +.names 39327 39330 39331 +11 1 +.names 8351 39114 39332 +11 1 +.names 8355 39143 39333 +1- 1 +-1 1 +.names 39333 39334 +1 1 +.names 39339 39341 39335 +1- 1 +-1 1 +.names 39335 39336 +1 1 +.names 39342 2413 39337 +11 1 +.names 39337 39338 +1 1 +.names 39338 39339 +0 1 +.names 39184 39340 +1 1 +.names 39340 39341 +0 1 +.names 8336 39342 +0 1 +.names 39336 39343 +0 1 +.names 39334 39344 +0 1 +.names 39342 39114 39345 +1- 1 +-1 1 +.names 39345 39346 +1 1 +.names 39114 39117 39347 +1- 1 +-1 1 +.names 39347 39348 +1 1 +.names 39184 39223 39349 +1- 1 +-1 1 +.names 39349 39350 +1 1 +.names 39350 39346 39351 +11 1 +.names 39360 39363 39352 +1- 1 +-1 1 +.names 39352 39353 +1 1 +.names 39368 39369 39354 +1- 1 +-1 1 +.names 39354 39355 +1 1 +.names 39355 39356 +0 1 +.names 2413 39357 +1 1 +.names 39357 39358 +1 1 +.names 39358 39359 +0 1 +.names 39356 39359 39360 +1- 1 +-1 1 +.names 39389 39390 39361 +11 1 +.names 39361 39362 +1 1 +.names 39362 39363 +0 1 +.names 8324 39364 +0 1 +.names 39385 39386 39365 +11 1 +.names 39365 39366 +1 1 +.names 39366 39367 +0 1 +.names 39364 39367 39368 +11 1 +.names 8324 39114 39369 +11 1 +.names 39372 39375 39370 +1- 1 +-1 1 +.names 39370 39371 +1 1 +.names 8334 1380 39372 +11 1 +.names 39391 39268 39373 +1- 1 +-1 1 +.names 39373 39374 +1 1 +.names 39374 39375 +0 1 +.names 39380 39143 39376 +1- 1 +-1 1 +.names 39376 39377 +1 1 +.names 39113 39378 +1 1 +.names 39378 39379 +0 1 +.names 8360 39379 39380 +1- 1 +-1 1 +.names 8365 39384 39381 +1- 1 +-1 1 +.names 39381 39382 +1 1 +.names 2413 39383 +1 1 +.names 39383 39384 +0 1 +.names 39377 39385 +0 1 +.names 39382 39386 +0 1 +.names 1380 8360 39387 +11 1 +.names 39387 39388 +1 1 +.names 39388 39389 +0 1 +.names 39371 39390 +0 1 +.names 1393 39391 +0 1 +.names 39400 39403 39392 +1- 1 +-1 1 +.names 39392 39393 +1 1 +.names 39407 39408 39394 +1- 1 +-1 1 +.names 39394 39395 +1 1 +.names 39395 39396 +0 1 +.names 2413 39397 +1 1 +.names 39397 39398 +1 1 +.names 39398 39399 +0 1 +.names 39396 39399 39400 +1- 1 +-1 1 +.names 39413 39415 39401 +11 1 +.names 39401 39402 +1 1 +.names 39402 39403 +0 1 +.names 39425 39426 39404 +11 1 +.names 39404 39405 +1 1 +.names 39405 39406 +0 1 +.names 39241 39406 39407 +11 1 +.names 8362 39114 39408 +11 1 +.names 39156 39114 39409 +1- 1 +-1 1 +.names 39409 39410 +1 1 +.names 8344 39428 39411 +1- 1 +-1 1 +.names 39411 39412 +1 1 +.names 39410 39412 39413 +11 1 +.names 39114 39427 39414 +1- 1 +-1 1 +.names 39414 39415 +1 1 +.names 39420 39143 39416 +1- 1 +-1 1 +.names 39416 39417 +1 1 +.names 39156 39418 +1 1 +.names 39418 39419 +0 1 +.names 8360 39419 39420 +1- 1 +-1 1 +.names 8357 39424 39421 +1- 1 +-1 1 +.names 39421 39422 +1 1 +.names 2413 39423 +1 1 +.names 39423 39424 +0 1 +.names 39422 39425 +0 1 +.names 39417 39426 +0 1 +.names 8360 39427 +0 1 +.names 1394 39428 +0 1 +.names 39434 39435 39429 +1- 1 +-1 1 +.names 39429 39430 +1 1 +.names 39442 39443 39431 +11 1 +.names 39431 39432 +1 1 +.names 39432 39433 +0 1 +.names 39241 39433 39434 +11 1 +.names 8362 39114 39435 +11 1 +.names 1783 39439 39436 +1- 1 +-1 1 +.names 39436 39437 +1 1 +.names 39268 39438 +1 1 +.names 39438 39439 +0 1 +.names 39448 39449 39440 +1- 1 +-1 1 +.names 39440 39441 +1 1 +.names 39441 39442 +0 1 +.names 39437 39443 +0 1 +.names 39114 39224 39444 +1- 1 +-1 1 +.names 39444 39445 +1 1 +.names 39156 39446 +1 1 +.names 39446 39447 +0 1 +.names 8341 39447 39448 +1- 1 +-1 1 +.names 1395 39449 +0 1 +.names 39458 39459 39450 +1- 1 +-1 1 +.names 39450 39451 +1 1 +.names 39156 39114 39452 +1- 1 +-1 1 +.names 39452 39453 +1 1 +.names 39453 39454 +0 1 +.names 39268 39468 39455 +1- 1 +-1 1 +.names 39455 39456 +1 1 +.names 39456 39457 +0 1 +.names 39454 39457 39458 +1- 1 +-1 1 +.names 39445 39459 +0 1 +.names 39430 39460 +0 1 +.names 39466 39467 39461 +11 1 +.names 39461 39462 +1 1 +.names 39462 39463 +0 1 +.names 1783 39464 +1 1 +.names 39464 39465 +1 1 +.names 39451 39466 +0 1 +.names 39465 39467 +0 1 +.names 1396 39468 +0 1 +.names 39477 39480 39469 +1- 1 +-1 1 +.names 39469 39470 +1 1 +.names 39484 39485 39471 +1- 1 +-1 1 +.names 39471 39472 +1 1 +.names 39472 39473 +0 1 +.names 2413 39474 +1 1 +.names 39474 39475 +1 1 +.names 39475 39476 +0 1 +.names 39473 39476 39477 +1- 1 +-1 1 +.names 39503 39498 39478 +11 1 +.names 39478 39479 +1 1 +.names 39479 39480 +0 1 +.names 39495 39496 39481 +11 1 +.names 39481 39482 +1 1 +.names 39482 39483 +0 1 +.names 39241 39483 39484 +11 1 +.names 8362 39114 39485 +11 1 +.names 39490 39143 39486 +1- 1 +-1 1 +.names 39486 39487 +1 1 +.names 39113 39488 +1 1 +.names 39488 39489 +0 1 +.names 8360 39489 39490 +1- 1 +-1 1 +.names 8366 39494 39491 +1- 1 +-1 1 +.names 39491 39492 +1 1 +.names 2413 39493 +1 1 +.names 39493 39494 +0 1 +.names 39487 39495 +0 1 +.names 39492 39496 +0 1 +.names 39114 39427 39497 +1- 1 +-1 1 +.names 39497 39498 +1 1 +.names 39113 39114 39499 +1- 1 +-1 1 +.names 39499 39500 +1 1 +.names 39184 39449 39501 +1- 1 +-1 1 +.names 39501 39502 +1 1 +.names 39502 39500 39503 +11 1 +.names 39517 39518 39504 +1- 1 +-1 1 +.names 39504 39505 +1 1 +.names 39505 39506 +0 1 +.names 2413 39507 +1 1 +.names 39507 39508 +1 1 +.names 39508 39509 +0 1 +.names 39506 39509 39510 +1- 1 +-1 1 +.names 39523 39525 39511 +11 1 +.names 39511 39512 +1 1 +.names 39512 39513 +0 1 +.names 39536 39537 39514 +11 1 +.names 39514 39515 +1 1 +.names 39515 39516 +0 1 +.names 39364 39516 39517 +11 1 +.names 8324 39114 39518 +11 1 +.names 39113 39114 39519 +1- 1 +-1 1 +.names 39519 39520 +1 1 +.names 8344 39538 39521 +1- 1 +-1 1 +.names 39521 39522 +1 1 +.names 39520 39522 39523 +11 1 +.names 39114 8352 39524 +1- 1 +-1 1 +.names 39524 39525 +1 1 +.names 8338 39528 39526 +1- 1 +-1 1 +.names 39526 39527 +1 1 +.names 1397 39528 +0 1 +.names 39533 39535 39529 +1- 1 +-1 1 +.names 39529 39530 +1 1 +.names 39113 2413 39531 +11 1 +.names 39531 39532 +1 1 +.names 39532 39533 +0 1 +.names 8344 39534 +1 1 +.names 39534 39535 +0 1 +.names 39530 39536 +0 1 +.names 39527 39537 +0 1 +.names 1398 39538 +0 1 +.names 39114 39113 39539 +1- 1 +-1 1 +.names 39539 39540 +1 1 +.names 39549 39552 39541 +1- 1 +-1 1 +.names 39541 39542 +1 1 +.names 39556 39557 39543 +1- 1 +-1 1 +.names 39543 39544 +1 1 +.names 39544 39545 +0 1 +.names 2413 39546 +1 1 +.names 39546 39547 +1 1 +.names 39547 39548 +0 1 +.names 39545 39548 39549 +1- 1 +-1 1 +.names 39575 39576 39550 +11 1 +.names 39550 39551 +1 1 +.names 39551 39552 +0 1 +.names 39571 39572 39553 +11 1 +.names 39553 39554 +1 1 +.names 39554 39555 +0 1 +.names 39364 39555 39556 +11 1 +.names 8324 39114 39557 +11 1 +.names 39560 39561 39558 +1- 1 +-1 1 +.names 39558 39559 +1 1 +.names 8365 1390 39560 +11 1 +.names 39540 39561 +0 1 +.names 39566 39143 39562 +1- 1 +-1 1 +.names 39562 39563 +1 1 +.names 39113 39564 +1 1 +.names 39564 39565 +0 1 +.names 8360 39565 39566 +1- 1 +-1 1 +.names 8365 39570 39567 +1- 1 +-1 1 +.names 39567 39568 +1 1 +.names 2413 39569 +1 1 +.names 39569 39570 +0 1 +.names 39563 39571 +0 1 +.names 39568 39572 +0 1 +.names 1380 8360 39573 +11 1 +.names 39573 39574 +1 1 +.names 39574 39575 +0 1 +.names 39559 39576 +0 1 +.names 39590 39591 39577 +1- 1 +-1 1 +.names 39577 39578 +1 1 +.names 39578 39579 +0 1 +.names 2413 39580 +1 1 +.names 39580 39581 +1 1 +.names 39581 39582 +0 1 +.names 39579 39582 39583 +1- 1 +-1 1 +.names 39611 39612 39584 +11 1 +.names 39584 39585 +1 1 +.names 39585 39586 +0 1 +.names 39601 39602 39587 +11 1 +.names 39587 39588 +1 1 +.names 39588 39589 +0 1 +.names 39201 39589 39590 +11 1 +.names 8326 2413 39591 +11 1 +.names 39596 39206 39592 +1- 1 +-1 1 +.names 39592 39593 +1 1 +.names 39266 39594 +1 1 +.names 39594 39595 +0 1 +.names 8364 39595 39596 +1- 1 +-1 1 +.names 8338 39600 39597 +1- 1 +-1 1 +.names 39597 39598 +1 1 +.names 2413 39599 +1 1 +.names 39599 39600 +0 1 +.names 39593 39601 +0 1 +.names 39598 39602 +0 1 +.names 39206 8352 39603 +1- 1 +-1 1 +.names 39603 39604 +1 1 +.names 39607 39608 39605 +1- 1 +-1 1 +.names 39605 39606 +1 1 +.names 8335 1783 39607 +11 1 +.names 39604 39608 +0 1 +.names 8364 1399 39609 +11 1 +.names 39609 39610 +1 1 +.names 39610 39611 +0 1 +.names 39606 39612 +0 1 +.names 39619 39621 39613 +1- 1 +-1 1 +.names 39613 39614 +1 1 +.names 8343 39615 +0 1 +.names 39631 39632 39616 +11 1 +.names 39616 39617 +1 1 +.names 39617 39618 +0 1 +.names 39615 39618 39619 +11 1 +.names 1400 39620 +0 1 +.names 8343 39620 39621 +11 1 +.names 8355 39143 39622 +1- 1 +-1 1 +.names 39622 39623 +1 1 +.names 39628 39630 39624 +1- 1 +-1 1 +.names 39624 39625 +1 1 +.names 39266 2413 39626 +11 1 +.names 39626 39627 +1 1 +.names 39627 39628 +0 1 +.names 8352 39629 +1 1 +.names 39629 39630 +0 1 +.names 39625 39631 +0 1 +.names 39623 39632 +0 1 +.names 39636 39637 39633 +1- 1 +-1 1 +.names 39633 39634 +1 1 +.names 39648 39651 39635 +1- 1 +-1 1 +.names 39635 39636 +1 1 +.names 39614 39637 +0 1 +.names 39114 8352 39638 +1- 1 +-1 1 +.names 39638 39639 +1 1 +.names 39639 39640 +0 1 +.names 39114 39117 39641 +1- 1 +-1 1 +.names 39641 39642 +1 1 +.names 39642 39643 +0 1 +.names 39640 39643 39644 +1- 1 +-1 1 +.names 39114 39266 39645 +1- 1 +-1 1 +.names 39645 39646 +1 1 +.names 39646 39647 +0 1 +.names 39644 39647 39648 +1- 1 +-1 1 +.names 2413 39649 +1 1 +.names 39649 39650 +1 1 +.names 39650 39651 +0 1 +.names 39657 39658 39652 +1- 1 +-1 1 +.names 39652 39653 +1 1 +.names 39668 39669 39654 +11 1 +.names 39654 39655 +1 1 +.names 39655 39656 +0 1 +.names 39364 39656 39657 +11 1 +.names 8324 39150 39658 +11 1 +.names 39663 39114 39659 +1- 1 +-1 1 +.names 39659 39660 +1 1 +.names 39266 39661 +1 1 +.names 39661 39662 +0 1 +.names 8341 39662 39663 +1- 1 +-1 1 +.names 8357 39667 39664 +1- 1 +-1 1 +.names 39664 39665 +1 1 +.names 2413 39666 +1 1 +.names 39666 39667 +0 1 +.names 39660 39668 +0 1 +.names 39665 39669 +0 1 +.names 8344 39672 39670 +1- 1 +-1 1 +.names 39670 39671 +1 1 +.names 1401 39672 +0 1 +.names 39114 39224 39673 +1- 1 +-1 1 +.names 39673 39674 +1 1 +.names 39681 39682 39675 +1- 1 +-1 1 +.names 39675 39676 +1 1 +.names 39671 39677 +0 1 +.names 39266 39153 39678 +1- 1 +-1 1 +.names 39678 39679 +1 1 +.names 39679 39680 +0 1 +.names 39677 39680 39681 +1- 1 +-1 1 +.names 39674 39682 +0 1 +.names 39653 39683 +0 1 +.names 39687 39690 39684 +11 1 +.names 39684 39685 +1 1 +.names 39685 39686 +0 1 +.names 39676 39687 +0 1 +.names 1783 39688 +1 1 +.names 39688 39689 +1 1 +.names 39689 39690 +0 1 +.names 39704 39705 39691 +1- 1 +-1 1 +.names 39691 39692 +1 1 +.names 39692 39693 +0 1 +.names 2413 39694 +1 1 +.names 39694 39695 +1 1 +.names 39695 39696 +0 1 +.names 39693 39696 39697 +1- 1 +-1 1 +.names 39708 39711 39698 +11 1 +.names 39698 39699 +1 1 +.names 39699 39700 +0 1 +.names 39718 39719 39701 +11 1 +.names 39701 39702 +1 1 +.names 39702 39703 +0 1 +.names 39364 39703 39704 +11 1 +.names 8324 39223 39705 +11 1 +.names 39723 1402 39706 +11 1 +.names 39706 39707 +1 1 +.names 39707 39708 +0 1 +.names 39725 39726 39709 +1- 1 +-1 1 +.names 39709 39710 +1 1 +.names 39710 39711 +0 1 +.names 8338 39715 39712 +1- 1 +-1 1 +.names 39712 39713 +1 1 +.names 2413 39714 +1 1 +.names 39714 39715 +0 1 +.names 39729 39620 39716 +1- 1 +-1 1 +.names 39716 39717 +1 1 +.names 39717 39718 +0 1 +.names 39713 39719 +0 1 +.names 39620 8352 39720 +1- 1 +-1 1 +.names 39720 39721 +1 1 +.names 39727 39722 +0 1 +.names 39722 39723 +1 1 +.names 39342 39724 +1 1 +.names 8336 1386 39725 +11 1 +.names 39721 39726 +0 1 +.names 39184 39727 +1 1 +.names 39724 39728 +0 1 +.names 39722 39728 39729 +1- 1 +-1 1 +.names 39428 39156 39730 +1- 1 +-1 1 +.names 39730 39731 +1 1 +.names 39745 39746 39732 +1- 1 +-1 1 +.names 39732 39733 +1 1 +.names 39733 39734 +0 1 +.names 2413 39735 +1 1 +.names 39735 39736 +1 1 +.names 39736 39737 +0 1 +.names 39734 39737 39738 +1- 1 +-1 1 +.names 39749 39752 39739 +11 1 +.names 39739 39740 +1 1 +.names 39740 39741 +0 1 +.names 39757 39760 39742 +11 1 +.names 39742 39743 +1 1 +.names 39743 39744 +0 1 +.names 39201 39744 39745 +11 1 +.names 8326 39161 39746 +11 1 +.names 39762 39747 +0 1 +.names 39747 39748 +1 1 +.names 39748 39749 +0 1 +.names 39768 39769 39750 +1- 1 +-1 1 +.names 39750 39751 +1 1 +.names 39751 39752 +0 1 +.names 8365 39756 39753 +1- 1 +-1 1 +.names 39753 39754 +1 1 +.names 2413 39755 +1 1 +.names 39755 39756 +0 1 +.names 39754 39757 +0 1 +.names 39767 39153 39758 +1- 1 +-1 1 +.names 39758 39759 +1 1 +.names 39759 39760 +0 1 +.names 39153 39224 39761 +1- 1 +-1 1 +.names 39761 39762 +1 1 +.names 39224 39763 +1 1 +.names 39763 39764 +0 1 +.names 39156 39765 +1 1 +.names 39765 39766 +0 1 +.names 39764 39766 39767 +1- 1 +-1 1 +.names 8365 1403 39768 +11 1 +.names 39731 39769 +0 1 +.names 39266 39114 39770 +1- 1 +-1 1 +.names 39770 39771 +1 1 +.names 39777 39778 39772 +1- 1 +-1 1 +.names 39772 39773 +1 1 +.names 39788 39789 39774 +11 1 +.names 39774 39775 +1 1 +.names 39775 39776 +0 1 +.names 39241 39776 39777 +11 1 +.names 8362 39114 39778 +11 1 +.names 39783 39143 39779 +1- 1 +-1 1 +.names 39779 39780 +1 1 +.names 39266 39781 +1 1 +.names 39781 39782 +0 1 +.names 8341 39782 39783 +1- 1 +-1 1 +.names 8357 39787 39784 +1- 1 +-1 1 +.names 39784 39785 +1 1 +.names 2413 39786 +1 1 +.names 39786 39787 +0 1 +.names 39780 39788 +0 1 +.names 39785 39789 +0 1 +.names 39114 39224 39790 +1- 1 +-1 1 +.names 39790 39791 +1 1 +.names 39798 39799 39792 +1- 1 +-1 1 +.names 39792 39793 +1 1 +.names 39771 39794 +0 1 +.names 8344 39206 39795 +1- 1 +-1 1 +.names 39795 39796 +1 1 +.names 39796 39797 +0 1 +.names 39794 39797 39798 +1- 1 +-1 1 +.names 39791 39799 +0 1 +.names 39802 39805 39800 +1- 1 +-1 1 +.names 39800 39801 +1 1 +.names 39773 39802 +0 1 +.names 39808 39809 39803 +11 1 +.names 39803 39804 +1 1 +.names 39804 39805 +0 1 +.names 1783 39806 +1 1 +.names 39806 39807 +1 1 +.names 39793 39808 +0 1 +.names 39807 39809 +0 1 +.names 39818 39821 39810 +1- 1 +-1 1 +.names 39810 39811 +1 1 +.names 39825 39826 39812 +1- 1 +-1 1 +.names 39812 39813 +1 1 +.names 39813 39814 +0 1 +.names 2413 39815 +1 1 +.names 39815 39816 +1 1 +.names 39816 39817 +0 1 +.names 39814 39817 39818 +1- 1 +-1 1 +.names 39844 39839 39819 +11 1 +.names 39819 39820 +1 1 +.names 39820 39821 +0 1 +.names 39836 39837 39822 +11 1 +.names 39822 39823 +1 1 +.names 39823 39824 +0 1 +.names 39364 39824 39825 +11 1 +.names 8324 39114 39826 +11 1 +.names 39831 39143 39827 +1- 1 +-1 1 +.names 39827 39828 +1 1 +.names 39342 39829 +1 1 +.names 39829 39830 +0 1 +.names 8361 39830 39831 +1- 1 +-1 1 +.names 8366 39835 39832 +1- 1 +-1 1 +.names 39832 39833 +1 1 +.names 2413 39834 +1 1 +.names 39834 39835 +0 1 +.names 39828 39836 +0 1 +.names 39833 39837 +0 1 +.names 39114 39257 39838 +1- 1 +-1 1 +.names 39838 39839 +1 1 +.names 39342 39114 39840 +1- 1 +-1 1 +.names 39840 39841 +1 1 +.names 39184 39114 39842 +1- 1 +-1 1 +.names 39842 39843 +1 1 +.names 39843 39841 39844 +11 1 +.names 39342 39114 39845 +1- 1 +-1 1 +.names 39845 39846 +1 1 +.names 39855 39858 39847 +1- 1 +-1 1 +.names 39847 39848 +1 1 +.names 39862 39863 39849 +1- 1 +-1 1 +.names 39849 39850 +1 1 +.names 39850 39851 +0 1 +.names 2413 39852 +1 1 +.names 39852 39853 +1 1 +.names 39853 39854 +0 1 +.names 39851 39854 39855 +1- 1 +-1 1 +.names 39866 39868 39856 +11 1 +.names 39856 39857 +1 1 +.names 39857 39858 +0 1 +.names 39878 39879 39859 +11 1 +.names 39859 39860 +1 1 +.names 39860 39861 +0 1 +.names 39201 39861 39862 +11 1 +.names 8326 39114 39863 +11 1 +.names 39313 39143 39864 +1- 1 +-1 1 +.names 39864 39865 +1 1 +.names 39846 39865 39866 +11 1 +.names 39114 39257 39867 +1- 1 +-1 1 +.names 39867 39868 +1 1 +.names 39873 39143 39869 +1- 1 +-1 1 +.names 39869 39870 +1 1 +.names 39342 39871 +1 1 +.names 39871 39872 +0 1 +.names 8361 39872 39873 +1- 1 +-1 1 +.names 8364 39877 39874 +1- 1 +-1 1 +.names 39874 39875 +1 1 +.names 2413 39876 +1 1 +.names 39876 39877 +0 1 +.names 39870 39878 +0 1 +.names 39875 39879 +0 1 +.names 39888 39891 39880 +1- 1 +-1 1 +.names 39880 39881 +1 1 +.names 39895 39896 39882 +1- 1 +-1 1 +.names 39882 39883 +1 1 +.names 39883 39884 +0 1 +.names 2413 39885 +1 1 +.names 39885 39886 +1 1 +.names 39886 39887 +0 1 +.names 39884 39887 39888 +1- 1 +-1 1 +.names 39901 39903 39889 +11 1 +.names 39889 39890 +1 1 +.names 39890 39891 +0 1 +.names 39913 39914 39892 +11 1 +.names 39892 39893 +1 1 +.names 39893 39894 +0 1 +.names 39241 39894 39895 +11 1 +.names 8362 39114 39896 +11 1 +.names 39342 39114 39897 +1- 1 +-1 1 +.names 39897 39898 +1 1 +.names 39313 39153 39899 +1- 1 +-1 1 +.names 39899 39900 +1 1 +.names 39898 39900 39901 +11 1 +.names 39114 39427 39902 +1- 1 +-1 1 +.names 39902 39903 +1 1 +.names 39908 39143 39904 +1- 1 +-1 1 +.names 39904 39905 +1 1 +.names 39342 39906 +1 1 +.names 39906 39907 +0 1 +.names 8360 39907 39908 +1- 1 +-1 1 +.names 8364 39912 39909 +1- 1 +-1 1 +.names 39909 39910 +1 1 +.names 2413 39911 +1 1 +.names 39911 39912 +0 1 +.names 39905 39913 +0 1 +.names 39910 39914 +0 1 +.names 39342 39114 39915 +1- 1 +-1 1 +.names 39915 39916 +1 1 +.names 39922 39923 39917 +1- 1 +-1 1 +.names 39917 39918 +1 1 +.names 39934 39935 39919 +11 1 +.names 39919 39920 +1 1 +.names 39920 39921 +0 1 +.names 39241 39921 39922 +11 1 +.names 8362 39114 39923 +11 1 +.names 39928 39929 39924 +1- 1 +-1 1 +.names 39924 39925 +1 1 +.names 39342 39926 +1 1 +.names 39926 39927 +0 1 +.names 8341 39927 39928 +1- 1 +-1 1 +.names 1404 39929 +0 1 +.names 8364 39933 39930 +1- 1 +-1 1 +.names 39930 39931 +1 1 +.names 2413 39932 +1 1 +.names 39932 39933 +0 1 +.names 39925 39934 +0 1 +.names 39931 39935 +0 1 +.names 39114 39224 39936 +1- 1 +-1 1 +.names 39936 39937 +1 1 +.names 39944 39945 39938 +1- 1 +-1 1 +.names 39938 39939 +1 1 +.names 39916 39940 +0 1 +.names 39313 39954 39941 +1- 1 +-1 1 +.names 39941 39942 +1 1 +.names 39942 39943 +0 1 +.names 39940 39943 39944 +1- 1 +-1 1 +.names 39937 39945 +0 1 +.names 39918 39946 +0 1 +.names 39952 39953 39947 +11 1 +.names 39947 39948 +1 1 +.names 39948 39949 +0 1 +.names 1783 39950 +1 1 +.names 39950 39951 +1 1 +.names 39939 39952 +0 1 +.names 39951 39953 +0 1 +.names 1405 39954 +0 1 +.names 39968 39969 39955 +1- 1 +-1 1 +.names 39955 39956 +1 1 +.names 39956 39957 +0 1 +.names 2413 39958 +1 1 +.names 39958 39959 +1 1 +.names 39959 39960 +0 1 +.names 39957 39960 39961 +1- 1 +-1 1 +.names 39974 39976 39962 +11 1 +.names 39962 39963 +1 1 +.names 39963 39964 +0 1 +.names 39986 39987 39965 +11 1 +.names 39965 39966 +1 1 +.names 39966 39967 +0 1 +.names 39241 39967 39968 +11 1 +.names 8362 39114 39969 +11 1 +.names 8344 39988 39970 +1- 1 +-1 1 +.names 39970 39971 +1 1 +.names 39113 39114 39972 +1- 1 +-1 1 +.names 39972 39973 +1 1 +.names 39971 39973 39974 +11 1 +.names 39114 39427 39975 +1- 1 +-1 1 +.names 39975 39976 +1 1 +.names 39981 39391 39977 +1- 1 +-1 1 +.names 39977 39978 +1 1 +.names 39113 39979 +1 1 +.names 39979 39980 +0 1 +.names 8360 39980 39981 +1- 1 +-1 1 +.names 1783 39985 39982 +1- 1 +-1 1 +.names 39982 39983 +1 1 +.names 8344 39984 +1 1 +.names 39984 39985 +0 1 +.names 39978 39986 +0 1 +.names 39983 39987 +0 1 +.names 1406 39988 +0 1 +.names 39114 39113 39989 +1- 1 +-1 1 +.names 39989 39990 +1 1 +.names 39999 40002 39991 +1- 1 +-1 1 +.names 39991 39992 +1 1 +.names 40006 40007 39993 +1- 1 +-1 1 +.names 39993 39994 +1 1 +.names 39994 39995 +0 1 +.names 2413 39996 +1 1 +.names 39996 39997 +1 1 +.names 39997 39998 +0 1 +.names 39995 39998 39999 +1- 1 +-1 1 +.names 40010 40013 40000 +11 1 +.names 40000 40001 +1 1 +.names 40001 40002 +0 1 +.names 40023 40024 40003 +11 1 +.names 40003 40004 +1 1 +.names 40004 40005 +0 1 +.names 39201 40005 40006 +11 1 +.names 8326 39114 40007 +11 1 +.names 40028 40008 +0 1 +.names 40008 40009 +1 1 +.names 40009 40010 +0 1 +.names 40025 40026 40011 +1- 1 +-1 1 +.names 40011 40012 +1 1 +.names 40012 40013 +0 1 +.names 40018 39143 40014 +1- 1 +-1 1 +.names 40014 40015 +1 1 +.names 39113 40016 +1 1 +.names 40016 40017 +0 1 +.names 8361 40017 40018 +1- 1 +-1 1 +.names 8357 40022 40019 +1- 1 +-1 1 +.names 40019 40020 +1 1 +.names 2413 40021 +1 1 +.names 40021 40022 +0 1 +.names 40015 40023 +0 1 +.names 40020 40024 +0 1 +.names 8357 1407 40025 +11 1 +.names 39990 40026 +0 1 +.names 39114 39257 40027 +1- 1 +-1 1 +.names 40027 40028 +1 1 +.names 39342 39114 40029 +1- 1 +-1 1 +.names 40029 40030 +1 1 +.names 40036 40037 40031 +1- 1 +-1 1 +.names 40031 40032 +1 1 +.names 40048 40049 40033 +11 1 +.names 40033 40034 +1 1 +.names 40034 40035 +0 1 +.names 39201 40035 40036 +11 1 +.names 8326 39114 40037 +11 1 +.names 40042 40043 40038 +1- 1 +-1 1 +.names 40038 40039 +1 1 +.names 39342 40040 +1 1 +.names 40040 40041 +0 1 +.names 8341 40041 40042 +1- 1 +-1 1 +.names 1407 40043 +0 1 +.names 8364 40047 40044 +1- 1 +-1 1 +.names 40044 40045 +1 1 +.names 2413 40046 +1 1 +.names 40046 40047 +0 1 +.names 40039 40048 +0 1 +.names 40045 40049 +0 1 +.names 39114 39224 40050 +1- 1 +-1 1 +.names 40050 40051 +1 1 +.names 40058 40059 40052 +1- 1 +-1 1 +.names 40052 40053 +1 1 +.names 40030 40054 +0 1 +.names 39313 40068 40055 +1- 1 +-1 1 +.names 40055 40056 +1 1 +.names 40056 40057 +0 1 +.names 40054 40057 40058 +1- 1 +-1 1 +.names 40051 40059 +0 1 +.names 40032 40060 +0 1 +.names 40066 40067 40061 +11 1 +.names 40061 40062 +1 1 +.names 40062 40063 +0 1 +.names 1783 40064 +1 1 +.names 40064 40065 +1 1 +.names 40053 40066 +0 1 +.names 40065 40067 +0 1 +.names 1408 40068 +0 1 +.names 40077 40080 40069 +1- 1 +-1 1 +.names 40069 40070 +1 1 +.names 40084 40085 40071 +1- 1 +-1 1 +.names 40071 40072 +1 1 +.names 40072 40073 +0 1 +.names 2413 40074 +1 1 +.names 40074 40075 +1 1 +.names 40075 40076 +0 1 +.names 40073 40076 40077 +1- 1 +-1 1 +.names 40088 40091 40078 +11 1 +.names 40078 40079 +1 1 +.names 40079 40080 +0 1 +.names 40098 40099 40081 +11 1 +.names 40081 40082 +1 1 +.names 40082 40083 +0 1 +.names 39201 40083 40084 +11 1 +.names 8326 39114 40085 +11 1 +.names 8365 1391 40086 +11 1 +.names 40086 40087 +1 1 +.names 40087 40088 +0 1 +.names 40103 40104 40089 +1- 1 +-1 1 +.names 40089 40090 +1 1 +.names 40090 40091 +0 1 +.names 8338 40095 40092 +1- 1 +-1 1 +.names 40092 40093 +1 1 +.names 2413 40094 +1 1 +.names 40094 40095 +0 1 +.names 40108 39143 40096 +1- 1 +-1 1 +.names 40096 40097 +1 1 +.names 40097 40098 +0 1 +.names 40093 40099 +0 1 +.names 39114 8352 40100 +1- 1 +-1 1 +.names 40100 40101 +1 1 +.names 39156 40102 +1 1 +.names 8356 1380 40103 +11 1 +.names 40101 40104 +0 1 +.names 39268 40105 +1 1 +.names 40105 40106 +0 1 +.names 40102 40107 +0 1 +.names 40106 40107 40108 +1- 1 +-1 1 +.names 39342 39114 40109 +1- 1 +-1 1 +.names 40109 40110 +1 1 +.names 40119 40122 40111 +1- 1 +-1 1 +.names 40111 40112 +1 1 +.names 40126 40127 40113 +1- 1 +-1 1 +.names 40113 40114 +1 1 +.names 40114 40115 +0 1 +.names 2413 40116 +1 1 +.names 40116 40117 +1 1 +.names 40117 40118 +0 1 +.names 40115 40118 40119 +1- 1 +-1 1 +.names 40143 40140 40120 +11 1 +.names 40120 40121 +1 1 +.names 40121 40122 +0 1 +.names 40137 40138 40123 +11 1 +.names 40123 40124 +1 1 +.names 40124 40125 +0 1 +.names 39364 40125 40126 +11 1 +.names 8324 39114 40127 +11 1 +.names 40132 39143 40128 +1- 1 +-1 1 +.names 40128 40129 +1 1 +.names 39342 40130 +1 1 +.names 40130 40131 +0 1 +.names 8361 40131 40132 +1- 1 +-1 1 +.names 8366 40136 40133 +1- 1 +-1 1 +.names 40133 40134 +1 1 +.names 2413 40135 +1 1 +.names 40135 40136 +0 1 +.names 40129 40137 +0 1 +.names 40134 40138 +0 1 +.names 39114 39257 40139 +1- 1 +-1 1 +.names 40139 40140 +1 1 +.names 39184 39528 40141 +1- 1 +-1 1 +.names 40141 40142 +1 1 +.names 40142 40110 40143 +11 1 +.names 39266 39223 40144 +1- 1 +-1 1 +.names 40144 40145 +1 1 +.names 40151 40152 40146 +1- 1 +-1 1 +.names 40146 40147 +1 1 +.names 40159 40160 40148 +11 1 +.names 40148 40149 +1 1 +.names 40149 40150 +0 1 +.names 39241 40150 40151 +11 1 +.names 8362 39620 40152 +11 1 +.names 8365 40156 40153 +1- 1 +-1 1 +.names 40153 40154 +1 1 +.names 2413 40155 +1 1 +.names 40155 40156 +0 1 +.names 40165 39428 40157 +1- 1 +-1 1 +.names 40157 40158 +1 1 +.names 40158 40159 +0 1 +.names 40154 40160 +0 1 +.names 39428 39224 40161 +1- 1 +-1 1 +.names 40161 40162 +1 1 +.names 39266 40163 +1 1 +.names 40163 40164 +0 1 +.names 8341 40164 40165 +1- 1 +-1 1 +.names 40172 40173 40166 +1- 1 +-1 1 +.names 40166 40167 +1 1 +.names 40145 40168 +0 1 +.names 39268 40182 40169 +1- 1 +-1 1 +.names 40169 40170 +1 1 +.names 40170 40171 +0 1 +.names 40168 40171 40172 +1- 1 +-1 1 +.names 40162 40173 +0 1 +.names 40147 40174 +0 1 +.names 40180 40181 40175 +11 1 +.names 40175 40176 +1 1 +.names 40176 40177 +0 1 +.names 1783 40178 +1 1 +.names 40178 40179 +1 1 +.names 40167 40180 +0 1 +.names 40179 40181 +0 1 +.names 1409 40182 +0 1 +.names 40196 40198 40183 +1- 1 +-1 1 +.names 40183 40184 +1 1 +.names 40184 40185 +0 1 +.names 39161 8352 40186 +1- 1 +-1 1 +.names 40186 40187 +1 1 +.names 40187 40188 +0 1 +.names 40185 40188 40189 +1- 1 +-1 1 +.names 40201 40204 40190 +11 1 +.names 40190 40191 +1 1 +.names 40191 40192 +0 1 +.names 40218 40219 40193 +11 1 +.names 40193 40194 +1 1 +.names 40194 40195 +0 1 +.names 39615 40195 40196 +11 1 +.names 1410 40197 +0 1 +.names 8343 40197 40198 +11 1 +.names 1394 8355 40199 +11 1 +.names 40199 40200 +1 1 +.names 40200 40201 +0 1 +.names 40205 40208 40202 +1- 1 +-1 1 +.names 40202 40203 +1 1 +.names 40203 40204 +0 1 +.names 8335 1400 40205 +11 1 +.names 2413 40206 +1 1 +.names 40206 40207 +1 1 +.names 40207 40208 +0 1 +.names 40213 39161 40209 +1- 1 +-1 1 +.names 40209 40210 +1 1 +.names 2413 40211 +1 1 +.names 40211 40212 +0 1 +.names 8355 40212 40213 +1- 1 +-1 1 +.names 8338 40217 40214 +1- 1 +-1 1 +.names 40214 40215 +1 1 +.names 39266 40216 +1 1 +.names 40216 40217 +0 1 +.names 40210 40218 +0 1 +.names 40215 40219 +0 1 +.names 40233 40234 40220 +1- 1 +-1 1 +.names 40220 40221 +1 1 +.names 40221 40222 +0 1 +.names 2413 40223 +1 1 +.names 40223 40224 +1 1 +.names 40224 40225 +0 1 +.names 40222 40225 40226 +1- 1 +-1 1 +.names 40253 40247 40227 +11 1 +.names 40227 40228 +1 1 +.names 40228 40229 +0 1 +.names 40244 40245 40230 +11 1 +.names 40230 40231 +1 1 +.names 40231 40232 +0 1 +.names 39241 40232 40233 +11 1 +.names 8362 39114 40234 +11 1 +.names 40239 39143 40235 +1- 1 +-1 1 +.names 40235 40236 +1 1 +.names 39156 40237 +1 1 +.names 40237 40238 +0 1 +.names 8361 40238 40239 +1- 1 +-1 1 +.names 8366 40243 40240 +1- 1 +-1 1 +.names 40240 40241 +1 1 +.names 2413 40242 +1 1 +.names 40242 40243 +0 1 +.names 40236 40244 +0 1 +.names 40241 40245 +0 1 +.names 39114 39257 40246 +1- 1 +-1 1 +.names 40246 40247 +1 1 +.names 39156 39114 40248 +1- 1 +-1 1 +.names 40248 40249 +1 1 +.names 39184 40252 40250 +1- 1 +-1 1 +.names 40250 40251 +1 1 +.names 1411 40252 +0 1 +.names 40251 40249 40253 +11 1 +.names 39113 39114 40254 +1- 1 +-1 1 +.names 40254 40255 +1 1 +.names 39114 8352 40256 +1- 1 +-1 1 +.names 40256 40257 +1 1 +.names 40262 39143 40258 +1- 1 +-1 1 +.names 40258 40259 +1 1 +.names 39113 40260 +1 1 +.names 40260 40261 +0 1 +.names 8338 40261 40262 +1- 1 +-1 1 +.names 8366 40266 40263 +1- 1 +-1 1 +.names 40263 40264 +1 1 +.names 2413 40265 +1 1 +.names 40265 40266 +0 1 +.names 40272 40273 40267 +1- 1 +-1 1 +.names 40267 40268 +1 1 +.names 40274 40275 40269 +11 1 +.names 40269 40270 +1 1 +.names 40270 40271 +0 1 +.names 39241 40271 40272 +11 1 +.names 8362 39114 40273 +11 1 +.names 40259 40274 +0 1 +.names 40264 40275 +0 1 +.names 40282 40283 40276 +1- 1 +-1 1 +.names 40276 40277 +1 1 +.names 39184 39161 40278 +1- 1 +-1 1 +.names 40278 40279 +1 1 +.names 40279 40280 +0 1 +.names 40255 40281 +0 1 +.names 40280 40281 40282 +1- 1 +-1 1 +.names 40257 40283 +0 1 +.names 40286 40289 40284 +11 1 +.names 40284 40285 +1 1 +.names 40277 40286 +0 1 +.names 1783 40287 +1 1 +.names 40287 40288 +1 1 +.names 40288 40289 +0 1 +.names 40292 40293 40290 +1- 1 +-1 1 +.names 40290 40291 +1 1 +.names 40268 40292 +0 1 +.names 40285 40293 +0 1 +.names 40302 40305 40294 +1- 1 +-1 1 +.names 40294 40295 +1 1 +.names 40309 40310 40296 +1- 1 +-1 1 +.names 40296 40297 +1 1 +.names 40297 40298 +0 1 +.names 2413 40299 +1 1 +.names 40299 40300 +1 1 +.names 40300 40301 +0 1 +.names 40298 40301 40302 +1- 1 +-1 1 +.names 40313 40316 40303 +11 1 +.names 40303 40304 +1 1 +.names 40304 40305 +0 1 +.names 40323 40324 40306 +11 1 +.names 40306 40307 +1 1 +.names 40307 40308 +0 1 +.names 39241 40308 40309 +11 1 +.names 8362 39114 40310 +11 1 +.names 8364 1404 40311 +11 1 +.names 40311 40312 +1 1 +.names 40312 40313 +0 1 +.names 40330 40331 40314 +1- 1 +-1 1 +.names 40314 40315 +1 1 +.names 40315 40316 +0 1 +.names 8361 40320 40317 +1- 1 +-1 1 +.names 40317 40318 +1 1 +.names 2413 40319 +1 1 +.names 40319 40320 +0 1 +.names 40329 39143 40321 +1- 1 +-1 1 +.names 40321 40322 +1 1 +.names 40322 40323 +0 1 +.names 40318 40324 +0 1 +.names 39114 39257 40325 +1- 1 +-1 1 +.names 40325 40326 +1 1 +.names 39156 40327 +1 1 +.names 40327 40328 +0 1 +.names 8364 40328 40329 +1- 1 +-1 1 +.names 8356 1380 40330 +11 1 +.names 40326 40331 +0 1 +.names 40338 40340 40332 +1- 1 +-1 1 +.names 40332 40333 +1 1 +.names 8382 40334 +0 1 +.names 40370 40371 40335 +11 1 +.names 40335 40336 +1 1 +.names 40336 40337 +0 1 +.names 40334 40337 40338 +11 1 +.names 191 40339 +0 1 +.names 8382 40339 40340 +11 1 +.names 40349 40352 40341 +1- 1 +-1 1 +.names 40341 40342 +1 1 +.names 40380 40382 40343 +11 1 +.names 40343 40344 +1 1 +.names 40344 40345 +0 1 +.names 40383 40384 40346 +11 1 +.names 40346 40347 +1 1 +.names 40347 40348 +0 1 +.names 40345 40348 40349 +1- 1 +-1 1 +.names 40377 40379 40350 +11 1 +.names 40350 40351 +1 1 +.names 40351 40352 +0 1 +.names 40358 40359 40353 +1- 1 +-1 1 +.names 40353 40354 +1 1 +.names 8402 40355 +0 1 +.names 40355 40356 +1 1 +.names 40356 40357 +0 1 +.names 8417 40357 40358 +1- 1 +-1 1 +.names 324 40359 +0 1 +.names 40362 40363 40360 +11 1 +.names 40360 40361 +1 1 +.names 8371 40362 +0 1 +.names 8392 40363 +0 1 +.names 40366 40367 40364 +11 1 +.names 40364 40365 +1 1 +.names 8379 40366 +0 1 +.names 8375 40367 +0 1 +.names 40375 40376 40368 +1- 1 +-1 1 +.names 40368 40369 +1 1 +.names 40369 40370 +0 1 +.names 40354 40371 +0 1 +.names 40342 40374 40372 +1- 1 +-1 1 +.names 40372 40373 +1 1 +.names 40333 40374 +0 1 +.names 40361 40375 +0 1 +.names 40365 40376 +0 1 +.names 25921 40366 40377 +1- 1 +-1 1 +.names 8417 40378 +0 1 +.names 40378 25921 40379 +1- 1 +-1 1 +.names 40355 27728 40380 +1- 1 +-1 1 +.names 606 40381 +0 1 +.names 40381 40363 40382 +1- 1 +-1 1 +.names 40362 25904 40383 +1- 1 +-1 1 +.names 40367 27728 40384 +1- 1 +-1 1 +.names 40390 40392 40385 +1- 1 +-1 1 +.names 40385 40386 +1 1 +.names 40420 40421 40387 +11 1 +.names 40387 40388 +1 1 +.names 40388 40389 +0 1 +.names 40334 40389 40390 +11 1 +.names 170 40391 +0 1 +.names 8382 40391 40392 +11 1 +.names 40401 40404 40393 +1- 1 +-1 1 +.names 40393 40394 +1 1 +.names 40425 40427 40395 +11 1 +.names 40395 40396 +1 1 +.names 40396 40397 +0 1 +.names 40430 40431 40398 +11 1 +.names 40398 40399 +1 1 +.names 40399 40400 +0 1 +.names 40397 40400 40401 +1- 1 +-1 1 +.names 40432 40434 40402 +11 1 +.names 40402 40403 +1 1 +.names 40403 40404 +0 1 +.names 40410 40411 40405 +1- 1 +-1 1 +.names 40405 40406 +1 1 +.names 8423 40407 +0 1 +.names 40407 40408 +1 1 +.names 40408 40409 +0 1 +.names 8420 40409 40410 +1- 1 +-1 1 +.names 303 40411 +0 1 +.names 40414 40363 40412 +11 1 +.names 40412 40413 +1 1 +.names 8370 40414 +0 1 +.names 40366 40417 40415 +11 1 +.names 40415 40416 +1 1 +.names 8410 40417 +0 1 +.names 40428 40429 40418 +1- 1 +-1 1 +.names 40418 40419 +1 1 +.names 40419 40420 +0 1 +.names 40406 40421 +0 1 +.names 40394 40424 40422 +1- 1 +-1 1 +.names 40422 40423 +1 1 +.names 40386 40424 +0 1 +.names 40407 2413 40425 +1- 1 +-1 1 +.names 585 40426 +0 1 +.names 40426 40363 40427 +1- 1 +-1 1 +.names 40413 40428 +0 1 +.names 40416 40429 +0 1 +.names 40414 2413 40430 +1- 1 +-1 1 +.names 40417 27698 40431 +1- 1 +-1 1 +.names 25969 40366 40432 +1- 1 +-1 1 +.names 8420 40433 +0 1 +.names 40433 25969 40434 +1- 1 +-1 1 +.names 8406 40435 +1 1 +.names 40439 40440 40436 +1- 1 +-1 1 +.names 40436 40437 +1 1 +.names 40435 40438 +0 1 +.names 8418 40438 40439 +1- 1 +-1 1 +.names 308 40440 +0 1 +.names 40443 40444 40441 +11 1 +.names 40441 40442 +1 1 +.names 8368 40443 +0 1 +.names 8413 40444 +0 1 +.names 40449 40450 40445 +11 1 +.names 40445 40446 +1 1 +.names 40475 40478 40447 +1- 1 +-1 1 +.names 40447 40448 +1 1 +.names 40448 40449 +0 1 +.names 40437 40450 +0 1 +.names 40454 40457 40451 +1- 1 +-1 1 +.names 40451 40452 +1 1 +.names 40485 40486 40453 +1- 1 +-1 1 +.names 40453 40454 +1 1 +.names 40462 40464 40455 +1- 1 +-1 1 +.names 40455 40456 +1 1 +.names 40456 40457 +0 1 +.names 8395 40458 +0 1 +.names 40458 40459 +1 1 +.names 40459 40460 +0 1 +.names 175 40461 +0 1 +.names 40460 40461 40462 +11 1 +.names 40446 40463 +0 1 +.names 40459 40463 40464 +11 1 +.names 40468 40469 40465 +11 1 +.names 40465 40466 +1 1 +.names 590 40467 +0 1 +.names 40467 8406 40468 +1- 1 +-1 1 +.names 26012 40444 40469 +1- 1 +-1 1 +.names 40472 40474 40470 +11 1 +.names 40470 40471 +1 1 +.names 40417 27715 40472 +1- 1 +-1 1 +.names 8418 40473 +0 1 +.names 40473 26012 40474 +1- 1 +-1 1 +.names 40442 40475 +0 1 +.names 40417 40407 40476 +11 1 +.names 40476 40477 +1 1 +.names 40477 40478 +0 1 +.names 40481 40482 40479 +11 1 +.names 40479 40480 +1 1 +.names 40443 25985 40481 +1- 1 +-1 1 +.names 40407 27715 40482 +1- 1 +-1 1 +.names 40471 40483 +0 1 +.names 40480 40484 +0 1 +.names 40483 40484 40485 +1- 1 +-1 1 +.names 40466 40486 +0 1 +.names 40489 40490 40487 +1- 1 +-1 1 +.names 40487 40488 +1 1 +.names 8394 40489 +0 1 +.names 177 40490 +0 1 +.names 40495 40496 40491 +1- 1 +-1 1 +.names 40491 40492 +1 1 +.names 40540 40493 +0 1 +.names 40493 40494 +1 1 +.names 40494 40495 +0 1 +.names 592 40496 +0 1 +.names 40501 40504 40497 +1- 1 +-1 1 +.names 40497 40498 +1 1 +.names 40551 40552 40499 +11 1 +.names 40499 40500 +1 1 +.names 40500 40501 +0 1 +.names 40509 40510 40502 +1- 1 +-1 1 +.names 40502 40503 +1 1 +.names 40503 40504 +0 1 +.names 8373 40505 +0 1 +.names 40535 40538 40506 +11 1 +.names 40506 40507 +1 1 +.names 40507 40508 +0 1 +.names 40505 40508 40509 +11 1 +.names 8373 27744 40510 +11 1 +.names 40513 40516 40511 +1- 1 +-1 1 +.names 40511 40512 +1 1 +.names 40488 40513 +0 1 +.names 8433 40514 +0 1 +.names 40514 40515 +1 1 +.names 40515 40516 +0 1 +.names 40513 40520 40517 +1- 1 +-1 1 +.names 40517 40518 +1 1 +.names 27744 40519 +1 1 +.names 40519 40520 +0 1 +.names 40523 40526 40521 +1- 1 +-1 1 +.names 40521 40522 +1 1 +.names 40512 40518 40523 +11 1 +.names 40541 40542 40524 +11 1 +.names 40524 40525 +1 1 +.names 40525 40526 +0 1 +.names 40531 40534 40527 +1- 1 +-1 1 +.names 40527 40528 +1 1 +.names 40539 40489 40529 +11 1 +.names 40529 40530 +1 1 +.names 40530 40531 +0 1 +.names 40514 40473 40532 +11 1 +.names 40532 40533 +1 1 +.names 40533 40534 +0 1 +.names 40528 40535 +0 1 +.names 40545 40546 40536 +1- 1 +-1 1 +.names 40536 40537 +1 1 +.names 40537 40538 +0 1 +.names 8415 40539 +0 1 +.names 8406 40540 +1 1 +.names 40414 26089 40541 +1- 1 +-1 1 +.names 40473 26061 40542 +1- 1 +-1 1 +.names 40414 40543 +1 1 +.names 310 40544 +0 1 +.names 40493 40544 40545 +1- 1 +-1 1 +.names 40543 40546 +0 1 +.names 40549 40550 40547 +1- 1 +-1 1 +.names 40547 40548 +1 1 +.names 8415 56433 40549 +11 1 +.names 40492 40550 +0 1 +.names 40522 40551 +0 1 +.names 40548 40552 +0 1 +.names 40558 40560 40553 +1- 1 +-1 1 +.names 40553 40554 +1 1 +.names 40586 40587 40555 +11 1 +.names 40555 40556 +1 1 +.names 40556 40557 +0 1 +.names 40489 40557 40558 +11 1 +.names 179 40559 +0 1 +.names 8394 40559 40560 +11 1 +.names 40569 40572 40561 +1- 1 +-1 1 +.names 40561 40562 +1 1 +.names 40591 40593 40563 +11 1 +.names 40563 40564 +1 1 +.names 40564 40565 +0 1 +.names 40598 40599 40566 +11 1 +.names 40566 40567 +1 1 +.names 40567 40568 +0 1 +.names 40565 40568 40569 +1- 1 +-1 1 +.names 40594 40595 40570 +11 1 +.names 40570 40571 +1 1 +.names 40571 40572 +0 1 +.names 40577 40578 40573 +1- 1 +-1 1 +.names 40573 40574 +1 1 +.names 40355 40575 +1 1 +.names 40575 40576 +0 1 +.names 8418 40576 40577 +1- 1 +-1 1 +.names 312 40578 +0 1 +.names 40414 40581 40579 +11 1 +.names 40579 40580 +1 1 +.names 8393 40581 +0 1 +.names 40366 40367 40582 +11 1 +.names 40582 40583 +1 1 +.names 40596 40597 40584 +1- 1 +-1 1 +.names 40584 40585 +1 1 +.names 40585 40586 +0 1 +.names 40574 40587 +0 1 +.names 40562 40590 40588 +1- 1 +-1 1 +.names 40588 40589 +1 1 +.names 40554 40590 +0 1 +.names 40355 27765 40591 +1- 1 +-1 1 +.names 594 40592 +0 1 +.names 40592 40581 40593 +1- 1 +-1 1 +.names 26135 40366 40594 +1- 1 +-1 1 +.names 40473 26135 40595 +1- 1 +-1 1 +.names 40580 40596 +0 1 +.names 40583 40597 +0 1 +.names 40414 26123 40598 +1- 1 +-1 1 +.names 40367 27765 40599 +1- 1 +-1 1 +.names 40605 40607 40600 +1- 1 +-1 1 +.names 40600 40601 +1 1 +.names 40619 40620 40602 +11 1 +.names 40602 40603 +1 1 +.names 40603 40604 +0 1 +.names 40489 40604 40605 +11 1 +.names 186 40606 +0 1 +.names 8394 40606 40607 +11 1 +.names 40613 40614 40608 +1- 1 +-1 1 +.names 40608 40609 +1 1 +.names 8424 40610 +0 1 +.names 40610 40611 +1 1 +.names 40611 40612 +0 1 +.names 8420 40612 40613 +1- 1 +-1 1 +.names 319 40614 +0 1 +.names 40414 40581 40615 +11 1 +.names 40615 40616 +1 1 +.names 40637 40638 40617 +1- 1 +-1 1 +.names 40617 40618 +1 1 +.names 40618 40619 +0 1 +.names 40609 40620 +0 1 +.names 40624 40625 40621 +1- 1 +-1 1 +.names 40621 40622 +1 1 +.names 40645 40646 40623 +1- 1 +-1 1 +.names 40623 40624 +1 1 +.names 40601 40625 +0 1 +.names 40628 40630 40626 +11 1 +.names 40626 40627 +1 1 +.names 40610 27782 40628 +1- 1 +-1 1 +.names 601 40629 +0 1 +.names 40629 40581 40630 +1- 1 +-1 1 +.names 40539 40417 40631 +11 1 +.names 40631 40632 +1 1 +.names 40635 40636 40633 +11 1 +.names 40633 40634 +1 1 +.names 26172 40539 40635 +1- 1 +-1 1 +.names 40433 26172 40636 +1- 1 +-1 1 +.names 40616 40637 +0 1 +.names 40632 40638 +0 1 +.names 40641 40642 40639 +11 1 +.names 40639 40640 +1 1 +.names 40414 26159 40641 +1- 1 +-1 1 +.names 40417 27782 40642 +1- 1 +-1 1 +.names 40627 40643 +0 1 +.names 40640 40644 +0 1 +.names 40643 40644 40645 +1- 1 +-1 1 +.names 40634 40646 +0 1 +.names 40652 40653 40647 +1- 1 +-1 1 +.names 40647 40648 +1 1 +.names 40666 40667 40649 +11 1 +.names 40649 40650 +1 1 +.names 40650 40651 +0 1 +.names 40362 40651 40652 +11 1 +.names 8371 26205 40653 +11 1 +.names 40658 40659 40654 +1- 1 +-1 1 +.names 40654 40655 +1 1 +.names 40363 40656 +1 1 +.names 40656 40657 +0 1 +.names 8417 40657 40658 +1- 1 +-1 1 +.names 332 40659 +0 1 +.names 40355 40489 40660 +11 1 +.names 40660 40661 +1 1 +.names 40366 40505 40662 +11 1 +.names 40662 40663 +1 1 +.names 40677 40678 40664 +1- 1 +-1 1 +.names 40664 40665 +1 1 +.names 40665 40666 +0 1 +.names 40655 40667 +0 1 +.names 40671 40672 40668 +1- 1 +-1 1 +.names 40668 40669 +1 1 +.names 40691 40692 40670 +1- 1 +-1 1 +.names 40670 40671 +1 1 +.names 40648 40672 +0 1 +.names 40675 40676 40673 +11 1 +.names 40673 40674 +1 1 +.names 26220 40366 40675 +1- 1 +-1 1 +.names 40378 26220 40676 +1- 1 +-1 1 +.names 40661 40677 +0 1 +.names 40663 40678 +0 1 +.names 40682 40684 40679 +11 1 +.names 40679 40680 +1 1 +.names 614 40681 +0 1 +.names 40681 40363 40682 +1- 1 +-1 1 +.names 199 40683 +0 1 +.names 40489 40683 40684 +1- 1 +-1 1 +.names 40687 40688 40685 +11 1 +.names 40685 40686 +1 1 +.names 40355 27799 40687 +1- 1 +-1 1 +.names 40505 27799 40688 +1- 1 +-1 1 +.names 40680 40689 +0 1 +.names 40686 40690 +0 1 +.names 40689 40690 40691 +1- 1 +-1 1 +.names 40674 40692 +0 1 +.names 40695 40489 40693 +1- 1 +-1 1 +.names 40693 40694 +1 1 +.names 188 40695 +0 1 +.names 40700 40703 40696 +1- 1 +-1 1 +.names 40696 40697 +1 1 +.names 40707 40708 40698 +1- 1 +-1 1 +.names 40698 40699 +1 1 +.names 40699 40700 +0 1 +.names 40721 40724 40701 +11 1 +.names 40701 40702 +1 1 +.names 40702 40703 +0 1 +.names 40744 40745 40704 +11 1 +.names 40704 40705 +1 1 +.names 40705 40706 +0 1 +.names 40473 40706 40707 +11 1 +.names 8418 26261 40708 +11 1 +.names 40711 40714 40709 +1- 1 +-1 1 +.names 40709 40710 +1 1 +.names 40694 40711 +0 1 +.names 8412 40712 +0 1 +.names 40712 40713 +1 1 +.names 40713 40714 +0 1 +.names 40711 40718 40715 +1- 1 +-1 1 +.names 40715 40716 +1 1 +.names 27815 40717 +1 1 +.names 40717 40718 +0 1 +.names 40725 40728 40719 +1- 1 +-1 1 +.names 40719 40720 +1 1 +.names 40720 40721 +0 1 +.names 40746 40749 40722 +1- 1 +-1 1 +.names 40722 40723 +1 1 +.names 40723 40724 +0 1 +.names 40710 40716 40725 +11 1 +.names 40751 40752 40726 +11 1 +.names 40726 40727 +1 1 +.names 40727 40728 +0 1 +.names 40732 40735 40729 +1- 1 +-1 1 +.names 40729 40730 +1 1 +.names 321 40731 +0 1 +.names 8392 40731 40732 +1- 1 +-1 1 +.names 8429 40733 +0 1 +.names 40733 40734 +1 1 +.names 40734 40735 +0 1 +.names 40740 40743 40736 +1- 1 +-1 1 +.names 40736 40737 +1 1 +.names 40539 40489 40738 +11 1 +.names 40738 40739 +1 1 +.names 40739 40740 +0 1 +.names 40505 40712 40741 +11 1 +.names 40741 40742 +1 1 +.names 40742 40743 +0 1 +.names 40737 40744 +0 1 +.names 40730 40745 +0 1 +.names 8415 56444 40746 +11 1 +.names 40505 27815 40747 +1- 1 +-1 1 +.names 40747 40748 +1 1 +.names 40748 40749 +0 1 +.names 603 40750 +0 1 +.names 40363 40750 40751 +1- 1 +-1 1 +.names 26276 40733 40752 +1- 1 +-1 1 +.names 40755 40756 40753 +11 1 +.names 40753 40754 +1 1 +.names 40367 27843 40755 +1- 1 +-1 1 +.names 40433 26330 40756 +1- 1 +-1 1 +.names 40367 40610 40757 +11 1 +.names 40757 40758 +1 1 +.names 40363 40759 +1 1 +.names 40763 40764 40760 +1- 1 +-1 1 +.names 40760 40761 +1 1 +.names 40759 40762 +0 1 +.names 8420 40762 40763 +1- 1 +-1 1 +.names 311 40764 +0 1 +.names 40769 40770 40765 +11 1 +.names 40765 40766 +1 1 +.names 40793 40794 40767 +1- 1 +-1 1 +.names 40767 40768 +1 1 +.names 40768 40769 +0 1 +.names 40761 40770 +0 1 +.names 40774 40776 40771 +1- 1 +-1 1 +.names 40771 40772 +1 1 +.names 40766 40773 +0 1 +.names 40458 40773 40774 +11 1 +.names 178 40775 +0 1 +.names 8395 40775 40776 +11 1 +.names 40780 40781 40777 +1- 1 +-1 1 +.names 40777 40778 +1 1 +.names 40797 40798 40779 +1- 1 +-1 1 +.names 40779 40780 +1 1 +.names 40772 40781 +0 1 +.names 40785 40786 40782 +11 1 +.names 40782 40783 +1 1 +.names 593 40784 +0 1 +.names 40784 40363 40785 +1- 1 +-1 1 +.names 26330 40444 40786 +1- 1 +-1 1 +.names 40789 40790 40787 +11 1 +.names 40787 40788 +1 1 +.names 40443 26310 40789 +1- 1 +-1 1 +.names 40610 27843 40790 +1- 1 +-1 1 +.names 40443 40444 40791 +11 1 +.names 40791 40792 +1 1 +.names 40792 40793 +0 1 +.names 40758 40794 +0 1 +.names 40754 40795 +0 1 +.names 40788 40796 +0 1 +.names 40795 40796 40797 +1- 1 +-1 1 +.names 40783 40798 +0 1 +.names 40804 40806 40799 +1- 1 +-1 1 +.names 40799 40800 +1 1 +.names 40817 40818 40801 +11 1 +.names 40801 40802 +1 1 +.names 40802 40803 +0 1 +.names 40458 40803 40804 +11 1 +.names 194 40805 +0 1 +.names 8395 40805 40806 +11 1 +.names 40811 40812 40807 +1- 1 +-1 1 +.names 40807 40808 +1 1 +.names 40514 40809 +1 1 +.names 40809 40810 +0 1 +.names 8420 40810 40811 +1- 1 +-1 1 +.names 327 40812 +0 1 +.names 40362 40581 40813 +11 1 +.names 40813 40814 +1 1 +.names 40831 40832 40815 +1- 1 +-1 1 +.names 40815 40816 +1 1 +.names 40816 40817 +0 1 +.names 40808 40818 +0 1 +.names 40822 40823 40819 +1- 1 +-1 1 +.names 40819 40820 +1 1 +.names 40841 40842 40821 +1- 1 +-1 1 +.names 40821 40822 +1 1 +.names 40800 40823 +0 1 +.names 40826 40828 40824 +11 1 +.names 40824 40825 +1 1 +.names 40514 27859 40826 +1- 1 +-1 1 +.names 609 40827 +0 1 +.names 40827 40581 40828 +1- 1 +-1 1 +.names 40539 40417 40829 +11 1 +.names 40829 40830 +1 1 +.names 40814 40831 +0 1 +.names 40830 40832 +0 1 +.names 40835 40836 40833 +11 1 +.names 40833 40834 +1 1 +.names 26371 40539 40835 +1- 1 +-1 1 +.names 40433 26371 40836 +1- 1 +-1 1 +.names 40825 40837 +0 1 +.names 40843 40844 40838 +11 1 +.names 40838 40839 +1 1 +.names 40839 40840 +0 1 +.names 40837 40840 40841 +1- 1 +-1 1 +.names 40834 40842 +0 1 +.names 40362 26358 40843 +1- 1 +-1 1 +.names 40417 27859 40844 +1- 1 +-1 1 +.names 40850 40851 40845 +1- 1 +-1 1 +.names 40845 40846 +1 1 +.names 40877 40878 40847 +11 1 +.names 40847 40848 +1 1 +.names 40848 40849 +0 1 +.names 40362 40849 40850 +11 1 +.names 8371 26416 40851 +11 1 +.names 40860 40863 40852 +1- 1 +-1 1 +.names 40852 40853 +1 1 +.names 40885 40887 40854 +11 1 +.names 40854 40855 +1 1 +.names 40855 40856 +0 1 +.names 40890 40891 40857 +11 1 +.names 40857 40858 +1 1 +.names 40858 40859 +0 1 +.names 40856 40859 40860 +1- 1 +-1 1 +.names 40882 40883 40861 +11 1 +.names 40861 40862 +1 1 +.names 40862 40863 +0 1 +.names 40868 40869 40864 +1- 1 +-1 1 +.names 40864 40865 +1 1 +.names 8406 40866 +1 1 +.names 40866 40867 +0 1 +.names 8420 40867 40868 +1- 1 +-1 1 +.names 313 40869 +0 1 +.names 40872 40334 40870 +11 1 +.names 40870 40871 +1 1 +.names 8430 40872 +0 1 +.names 40366 40505 40873 +11 1 +.names 40873 40874 +1 1 +.names 40888 40889 40875 +1- 1 +-1 1 +.names 40875 40876 +1 1 +.names 40876 40877 +0 1 +.names 40865 40878 +0 1 +.names 40853 40881 40879 +1- 1 +-1 1 +.names 40879 40880 +1 1 +.names 40846 40881 +0 1 +.names 26428 40366 40882 +1- 1 +-1 1 +.names 40433 26428 40883 +1- 1 +-1 1 +.names 595 40884 +0 1 +.names 40884 8406 40885 +1- 1 +-1 1 +.names 180 40886 +0 1 +.names 40334 40886 40887 +1- 1 +-1 1 +.names 40871 40888 +0 1 +.names 40874 40889 +0 1 +.names 40872 27879 40890 +1- 1 +-1 1 +.names 40505 27879 40891 +1- 1 +-1 1 +.names 8406 40892 +1 1 +.names 40334 40895 40893 +1- 1 +-1 1 +.names 40893 40894 +1 1 +.names 193 40895 +0 1 +.names 40900 40903 40896 +1- 1 +-1 1 +.names 40896 40897 +1 1 +.names 40907 40908 40898 +1- 1 +-1 1 +.names 40898 40899 +1 1 +.names 40899 40900 +0 1 +.names 40920 40923 40901 +11 1 +.names 40901 40902 +1 1 +.names 40902 40903 +0 1 +.names 40941 40942 40904 +11 1 +.names 40904 40905 +1 1 +.names 40905 40906 +0 1 +.names 40473 40906 40907 +11 1 +.names 8418 26460 40908 +11 1 +.names 40911 40913 40909 +1- 1 +-1 1 +.names 40909 40910 +1 1 +.names 40894 40911 +0 1 +.names 40712 40912 +1 1 +.names 40912 40913 +0 1 +.names 40911 40917 40914 +1- 1 +-1 1 +.names 40914 40915 +1 1 +.names 27895 40916 +1 1 +.names 40916 40917 +0 1 +.names 40924 40927 40918 +1- 1 +-1 1 +.names 40918 40919 +1 1 +.names 40919 40920 +0 1 +.names 40948 40949 40921 +1- 1 +-1 1 +.names 40921 40922 +1 1 +.names 40922 40923 +0 1 +.names 40910 40915 40924 +11 1 +.names 40943 40945 40925 +11 1 +.names 40925 40926 +1 1 +.names 40926 40927 +0 1 +.names 40931 40932 40928 +1- 1 +-1 1 +.names 40928 40929 +1 1 +.names 40892 40930 +0 1 +.names 8413 40930 40931 +1- 1 +-1 1 +.names 326 40932 +0 1 +.names 40937 40940 40933 +1- 1 +-1 1 +.names 40933 40934 +1 1 +.names 40334 40414 40935 +11 1 +.names 40935 40936 +1 1 +.names 40936 40937 +0 1 +.names 40417 40712 40938 +11 1 +.names 40938 40939 +1 1 +.names 40939 40940 +0 1 +.names 40929 40941 +0 1 +.names 40934 40942 +0 1 +.names 40414 26477 40943 +1- 1 +-1 1 +.names 608 40944 +0 1 +.names 8406 40944 40945 +1- 1 +-1 1 +.names 26460 40444 40946 +1- 1 +-1 1 +.names 40946 40947 +1 1 +.names 8410 7075 40948 +11 1 +.names 40947 40949 +0 1 +.names 40955 40957 40950 +1- 1 +-1 1 +.names 40950 40951 +1 1 +.names 40985 40986 40952 +11 1 +.names 40952 40953 +1 1 +.names 40953 40954 +0 1 +.names 40334 40954 40955 +11 1 +.names 169 40956 +0 1 +.names 8382 40956 40957 +11 1 +.names 40966 40969 40958 +1- 1 +-1 1 +.names 40958 40959 +1 1 +.names 40989 40990 40960 +11 1 +.names 40960 40961 +1 1 +.names 40961 40962 +0 1 +.names 40991 40992 40963 +11 1 +.names 40963 40964 +1 1 +.names 40964 40965 +0 1 +.names 40962 40965 40966 +1- 1 +-1 1 +.names 40993 40994 40967 +11 1 +.names 40967 40968 +1 1 +.names 40968 40969 +0 1 +.names 40975 40976 40970 +1- 1 +-1 1 +.names 40970 40971 +1 1 +.names 8414 40972 +0 1 +.names 40972 40973 +1 1 +.names 40973 40974 +0 1 +.names 8392 40974 40975 +1- 1 +-1 1 +.names 302 40976 +0 1 +.names 40981 40984 40977 +1- 1 +-1 1 +.names 40977 40978 +1 1 +.names 40378 40443 40979 +11 1 +.names 40979 40980 +1 1 +.names 40980 40981 +0 1 +.names 40367 40712 40982 +11 1 +.names 40982 40983 +1 1 +.names 40983 40984 +0 1 +.names 40978 40985 +0 1 +.names 40971 40986 +0 1 +.names 40951 40987 +0 1 +.names 584 40988 +0 1 +.names 40988 40363 40989 +1- 1 +-1 1 +.names 26539 40972 40990 +1- 1 +-1 1 +.names 40443 2413 40991 +1- 1 +-1 1 +.names 40712 2413 40992 +1- 1 +-1 1 +.names 40367 27831 40993 +1- 1 +-1 1 +.names 40378 26539 40994 +1- 1 +-1 1 +.names 41003 41006 40995 +1- 1 +-1 1 +.names 40995 40996 +1 1 +.names 41039 41040 40997 +11 1 +.names 40997 40998 +1 1 +.names 40998 40999 +0 1 +.names 41037 41038 41000 +11 1 +.names 41000 41001 +1 1 +.names 41001 41002 +0 1 +.names 40999 41002 41003 +1- 1 +-1 1 +.names 41029 41030 41004 +11 1 +.names 41004 41005 +1 1 +.names 41005 41006 +0 1 +.names 41011 41012 41007 +1- 1 +-1 1 +.names 41007 41008 +1 1 +.names 8406 41009 +1 1 +.names 41009 41010 +0 1 +.names 8420 41010 41011 +1- 1 +-1 1 +.names 309 41012 +0 1 +.names 40733 40444 41013 +11 1 +.names 41013 41014 +1 1 +.names 40367 40407 41015 +11 1 +.names 41015 41016 +1 1 +.names 41021 41022 41017 +11 1 +.names 41017 41018 +1 1 +.names 41035 41036 41019 +1- 1 +-1 1 +.names 41019 41020 +1 1 +.names 41020 41021 +0 1 +.names 41008 41022 +0 1 +.names 40996 41027 41023 +1- 1 +-1 1 +.names 41023 41024 +1 1 +.names 41032 41034 41025 +1- 1 +-1 1 +.names 41025 41026 +1 1 +.names 41026 41027 +0 1 +.names 591 41028 +0 1 +.names 41028 8406 41029 +1- 1 +-1 1 +.names 26576 40444 41030 +1- 1 +-1 1 +.names 41018 41031 +0 1 +.names 40458 41031 41032 +11 1 +.names 176 41033 +0 1 +.names 8395 41033 41034 +11 1 +.names 41014 41035 +0 1 +.names 41016 41036 +0 1 +.names 40733 26560 41037 +1- 1 +-1 1 +.names 40407 27911 41038 +1- 1 +-1 1 +.names 40367 27911 41039 +1- 1 +-1 1 +.names 40433 26576 41040 +1- 1 +-1 1 +.names 41046 41048 41041 +1- 1 +-1 1 +.names 41041 41042 +1 1 +.names 41061 41062 41043 +11 1 +.names 41043 41044 +1 1 +.names 41044 41045 +0 1 +.names 40334 41045 41046 +11 1 +.names 187 41047 +0 1 +.names 8382 41047 41048 +11 1 +.names 41053 41054 41049 +1- 1 +-1 1 +.names 41049 41050 +1 1 +.names 8406 41051 +1 1 +.names 41051 41052 +0 1 +.names 8418 41052 41053 +1- 1 +-1 1 +.names 320 41054 +0 1 +.names 40355 40367 41055 +11 1 +.names 41055 41056 +1 1 +.names 40972 40443 41057 +11 1 +.names 41057 41058 +1 1 +.names 41072 41073 41059 +1- 1 +-1 1 +.names 41059 41060 +1 1 +.names 41060 41061 +0 1 +.names 41050 41062 +0 1 +.names 41065 41067 41063 +11 1 +.names 41063 41064 +1 1 +.names 40355 27927 41065 +1- 1 +-1 1 +.names 602 41066 +0 1 +.names 8406 41066 41067 +1- 1 +-1 1 +.names 41070 41071 41068 +11 1 +.names 41068 41069 +1 1 +.names 26614 40972 41070 +1- 1 +-1 1 +.names 40473 26614 41071 +1- 1 +-1 1 +.names 41056 41072 +0 1 +.names 41058 41073 +0 1 +.names 41078 41079 41074 +1- 1 +-1 1 +.names 41074 41075 +1 1 +.names 41082 41069 41076 +11 1 +.names 41076 41077 +1 1 +.names 41077 41078 +0 1 +.names 41042 41079 +0 1 +.names 41083 41084 41080 +11 1 +.names 41080 41081 +1 1 +.names 41064 41081 41082 +11 1 +.names 40443 26602 41083 +1- 1 +-1 1 +.names 40367 27927 41084 +1- 1 +-1 1 +.names 40581 41085 +1 1 +.names 40872 27943 41086 +1- 1 +-1 1 +.names 41086 41087 +1 1 +.names 41093 41094 41088 +1- 1 +-1 1 +.names 41088 41089 +1 1 +.names 41126 41127 41090 +11 1 +.names 41090 41091 +1 1 +.names 41091 41092 +0 1 +.names 40733 41092 41093 +11 1 +.names 8429 26669 41094 +11 1 +.names 41098 41100 41095 +11 1 +.names 41095 41096 +1 1 +.names 600 41097 +0 1 +.names 41097 40581 41098 +1- 1 +-1 1 +.names 185 41099 +0 1 +.names 40489 41099 41100 +1- 1 +-1 1 +.names 41113 41114 41101 +1- 1 +-1 1 +.names 41101 41102 +1 1 +.names 40433 26637 41103 +1- 1 +-1 1 +.names 41103 41104 +1 1 +.names 41104 41105 +0 1 +.names 26637 40444 41106 +1- 1 +-1 1 +.names 41106 41107 +1 1 +.names 41107 41108 +0 1 +.names 41105 41108 41109 +1- 1 +-1 1 +.names 40505 27943 41110 +1- 1 +-1 1 +.names 41110 41111 +1 1 +.names 41111 41112 +0 1 +.names 41109 41112 41113 +1- 1 +-1 1 +.names 41087 41114 +0 1 +.names 41118 41119 41115 +1- 1 +-1 1 +.names 41115 41116 +1 1 +.names 41085 41117 +0 1 +.names 8420 41117 41118 +1- 1 +-1 1 +.names 318 41119 +0 1 +.names 40872 40489 41120 +11 1 +.names 41120 41121 +1 1 +.names 40444 40505 41122 +11 1 +.names 41122 41123 +1 1 +.names 41133 41134 41124 +1- 1 +-1 1 +.names 41124 41125 +1 1 +.names 41125 41126 +0 1 +.names 41116 41127 +0 1 +.names 41131 41132 41128 +1- 1 +-1 1 +.names 41128 41129 +1 1 +.names 41089 41130 +0 1 +.names 41102 41130 41131 +1- 1 +-1 1 +.names 41096 41132 +0 1 +.names 41121 41133 +0 1 +.names 41123 41134 +0 1 +.names 41140 41141 41135 +1- 1 +-1 1 +.names 41135 41136 +1 1 +.names 41166 41167 41137 +11 1 +.names 41137 41138 +1 1 +.names 41138 41139 +0 1 +.names 40414 41139 41140 +11 1 +.names 8370 26708 41141 +11 1 +.names 41150 41153 41142 +1- 1 +-1 1 +.names 41142 41143 +1 1 +.names 41172 41174 41144 +11 1 +.names 41144 41145 +1 1 +.names 41145 41146 +0 1 +.names 41177 41178 41147 +11 1 +.names 41147 41148 +1 1 +.names 41148 41149 +0 1 +.names 41146 41149 41150 +1- 1 +-1 1 +.names 41179 41180 41151 +11 1 +.names 41151 41152 +1 1 +.names 41152 41153 +0 1 +.names 41158 41159 41154 +1- 1 +-1 1 +.names 41154 41155 +1 1 +.names 8406 41156 +1 1 +.names 41156 41157 +0 1 +.names 8417 41157 41158 +1- 1 +-1 1 +.names 325 41159 +0 1 +.names 40872 40505 41160 +11 1 +.names 41160 41161 +1 1 +.names 40366 40458 41162 +11 1 +.names 41162 41163 +1 1 +.names 41175 41176 41164 +1- 1 +-1 1 +.names 41164 41165 +1 1 +.names 41165 41166 +0 1 +.names 41155 41167 +0 1 +.names 41143 41170 41168 +1- 1 +-1 1 +.names 41168 41169 +1 1 +.names 41136 41170 +0 1 +.names 607 41171 +0 1 +.names 41171 8406 41172 +1- 1 +-1 1 +.names 192 41173 +0 1 +.names 40458 41173 41174 +1- 1 +-1 1 +.names 41161 41175 +0 1 +.names 41163 41176 +0 1 +.names 40872 27959 41177 +1- 1 +-1 1 +.names 40505 27959 41178 +1- 1 +-1 1 +.names 26724 40366 41179 +1- 1 +-1 1 +.names 40378 26724 41180 +1- 1 +-1 1 +.names 41183 40458 41181 +1- 1 +-1 1 +.names 41181 41182 +1 1 +.names 200 41183 +0 1 +.names 41188 41191 41184 +1- 1 +-1 1 +.names 41184 41185 +1 1 +.names 41195 41196 41186 +1- 1 +-1 1 +.names 41186 41187 +1 1 +.names 41187 41188 +0 1 +.names 41208 41211 41189 +11 1 +.names 41189 41190 +1 1 +.names 41190 41191 +0 1 +.names 41228 41229 41192 +11 1 +.names 41192 41193 +1 1 +.names 41193 41194 +0 1 +.names 40505 41194 41195 +11 1 +.names 8373 27971 41196 +11 1 +.names 41199 41201 41197 +1- 1 +-1 1 +.names 41197 41198 +1 1 +.names 41182 41199 +0 1 +.names 40407 41200 +1 1 +.names 41200 41201 +0 1 +.names 41199 41205 41202 +1- 1 +-1 1 +.names 41202 41203 +1 1 +.names 27971 41204 +1 1 +.names 41204 41205 +0 1 +.names 41212 41215 41206 +1- 1 +-1 1 +.names 41206 41207 +1 1 +.names 41207 41208 +0 1 +.names 41230 41233 41209 +1- 1 +-1 1 +.names 41209 41210 +1 1 +.names 41210 41211 +0 1 +.names 41198 41203 41212 +11 1 +.names 41235 41236 41213 +11 1 +.names 41213 41214 +1 1 +.names 41214 41215 +0 1 +.names 41220 41221 41216 +1- 1 +-1 1 +.names 41216 41217 +1 1 +.names 8406 41218 +1 1 +.names 41218 41219 +0 1 +.names 8368 41219 41220 +1- 1 +-1 1 +.names 333 41221 +0 1 +.names 40378 40972 41222 +11 1 +.names 41222 41223 +1 1 +.names 40407 40458 41224 +11 1 +.names 41224 41225 +1 1 +.names 41237 41238 41226 +1- 1 +-1 1 +.names 41226 41227 +1 1 +.names 41227 41228 +0 1 +.names 41217 41229 +0 1 +.names 8414 56456 41230 +11 1 +.names 26769 40443 41231 +1- 1 +-1 1 +.names 41231 41232 +1 1 +.names 41232 41233 +0 1 +.names 615 41234 +0 1 +.names 8406 41234 41235 +1- 1 +-1 1 +.names 40378 26751 41236 +1- 1 +-1 1 +.names 41223 41237 +0 1 +.names 41225 41238 +0 1 +.names 41244 41246 41239 +1- 1 +-1 1 +.names 41239 41240 +1 1 +.names 41271 41272 41241 +11 1 +.names 41241 41242 +1 1 +.names 41242 41243 +0 1 +.names 40334 41243 41244 +11 1 +.names 190 41245 +0 1 +.names 8382 41245 41246 +11 1 +.names 41255 41258 41247 +1- 1 +-1 1 +.names 41247 41248 +1 1 +.names 41278 41280 41249 +11 1 +.names 41249 41250 +1 1 +.names 41250 41251 +0 1 +.names 41283 41284 41252 +11 1 +.names 41252 41253 +1 1 +.names 41253 41254 +0 1 +.names 41251 41254 41255 +1- 1 +-1 1 +.names 41276 41277 41256 +11 1 +.names 41256 41257 +1 1 +.names 41257 41258 +0 1 +.names 41263 41264 41259 +1- 1 +-1 1 +.names 41259 41260 +1 1 +.names 40712 41261 +1 1 +.names 41261 41262 +0 1 +.names 8417 41262 41263 +1- 1 +-1 1 +.names 323 41264 +0 1 +.names 40733 40581 41265 +11 1 +.names 41265 41266 +1 1 +.names 40972 40505 41267 +11 1 +.names 41267 41268 +1 1 +.names 41281 41282 41269 +1- 1 +-1 1 +.names 41269 41270 +1 1 +.names 41270 41271 +0 1 +.names 41260 41272 +0 1 +.names 41248 41275 41273 +1- 1 +-1 1 +.names 41273 41274 +1 1 +.names 41240 41275 +0 1 +.names 26824 40972 41276 +1- 1 +-1 1 +.names 40378 26824 41277 +1- 1 +-1 1 +.names 40712 28023 41278 +1- 1 +-1 1 +.names 605 41279 +0 1 +.names 41279 40581 41280 +1- 1 +-1 1 +.names 41266 41281 +0 1 +.names 41268 41282 +0 1 +.names 40733 26813 41283 +1- 1 +-1 1 +.names 40505 28023 41284 +1- 1 +-1 1 +.names 41290 41292 41285 +1- 1 +-1 1 +.names 41285 41286 +1 1 +.names 41303 41304 41287 +11 1 +.names 41287 41288 +1 1 +.names 41288 41289 +0 1 +.names 40489 41289 41290 +11 1 +.names 171 41291 +0 1 +.names 8394 41291 41292 +11 1 +.names 41297 41298 41293 +1- 1 +-1 1 +.names 41293 41294 +1 1 +.names 40514 41295 +1 1 +.names 41295 41296 +0 1 +.names 8420 41296 41297 +1- 1 +-1 1 +.names 304 41298 +0 1 +.names 40733 40581 41299 +11 1 +.names 41299 41300 +1 1 +.names 41321 41322 41301 +1- 1 +-1 1 +.names 41301 41302 +1 1 +.names 41302 41303 +0 1 +.names 41294 41304 +0 1 +.names 41308 41309 41305 +1- 1 +-1 1 +.names 41305 41306 +1 1 +.names 41329 41330 41307 +1- 1 +-1 1 +.names 41307 41308 +1 1 +.names 41286 41309 +0 1 +.names 40539 40417 41310 +11 1 +.names 41310 41311 +1 1 +.names 41314 41316 41312 +11 1 +.names 41312 41313 +1 1 +.names 40514 27991 41314 +1- 1 +-1 1 +.names 586 41315 +0 1 +.names 41315 40581 41316 +1- 1 +-1 1 +.names 41319 41320 41317 +11 1 +.names 41317 41318 +1 1 +.names 26862 40539 41319 +1- 1 +-1 1 +.names 40433 26862 41320 +1- 1 +-1 1 +.names 41300 41321 +0 1 +.names 41311 41322 +0 1 +.names 41325 41326 41323 +11 1 +.names 41323 41324 +1 1 +.names 40733 26847 41325 +1- 1 +-1 1 +.names 40417 27991 41326 +1- 1 +-1 1 +.names 41313 41327 +0 1 +.names 41324 41328 +0 1 +.names 41327 41328 41329 +1- 1 +-1 1 +.names 41318 41330 +0 1 +.names 41336 41337 41331 +1- 1 +-1 1 +.names 41331 41332 +1 1 +.names 41360 41361 41333 +11 1 +.names 41333 41334 +1 1 +.names 41334 41335 +0 1 +.names 40443 41335 41336 +11 1 +.names 8368 26905 41337 +11 1 +.names 41346 41349 41338 +1- 1 +-1 1 +.names 41338 41339 +1 1 +.names 41368 41370 41340 +11 1 +.names 41340 41341 +1 1 +.names 41341 41342 +0 1 +.names 41373 41374 41343 +11 1 +.names 41343 41344 +1 1 +.names 41344 41345 +0 1 +.names 41342 41345 41346 +1- 1 +-1 1 +.names 41365 41366 41347 +11 1 +.names 41347 41348 +1 1 +.names 41348 41349 +0 1 +.names 41354 41355 41350 +1- 1 +-1 1 +.names 41350 41351 +1 1 +.names 8406 41352 +1 1 +.names 41352 41353 +0 1 +.names 8418 41353 41354 +1- 1 +-1 1 +.names 307 41355 +0 1 +.names 40444 40334 41356 +11 1 +.names 41356 41357 +1 1 +.names 41375 41376 41358 +1- 1 +-1 1 +.names 41358 41359 +1 1 +.names 41359 41360 +0 1 +.names 41351 41361 +0 1 +.names 41339 41364 41362 +1- 1 +-1 1 +.names 41362 41363 +1 1 +.names 41332 41364 +0 1 +.names 40444 14886 41365 +1- 1 +-1 1 +.names 40473 26914 41366 +1- 1 +-1 1 +.names 589 41367 +0 1 +.names 8406 41367 41368 +1- 1 +-1 1 +.names 174 41369 +0 1 +.names 40334 41369 41370 +1- 1 +-1 1 +.names 40610 40417 41371 +11 1 +.names 41371 41372 +1 1 +.names 40610 28007 41373 +1- 1 +-1 1 +.names 40417 28007 41374 +1- 1 +-1 1 +.names 41372 41375 +0 1 +.names 41357 41376 +0 1 +.names 40458 41379 41377 +1- 1 +-1 1 +.names 41377 41378 +1 1 +.names 182 41379 +0 1 +.names 41384 41387 41380 +1- 1 +-1 1 +.names 41380 41381 +1 1 +.names 41431 41432 41382 +11 1 +.names 41382 41383 +1 1 +.names 41383 41384 +0 1 +.names 41391 41392 41385 +1- 1 +-1 1 +.names 41385 41386 +1 1 +.names 41386 41387 +0 1 +.names 41410 41413 41388 +11 1 +.names 41388 41389 +1 1 +.names 41389 41390 +0 1 +.names 40378 41390 41391 +11 1 +.names 8417 26947 41392 +11 1 +.names 41395 41397 41393 +1- 1 +-1 1 +.names 41393 41394 +1 1 +.names 41378 41395 +0 1 +.names 40610 41396 +1 1 +.names 41396 41397 +0 1 +.names 41395 41401 41398 +1- 1 +-1 1 +.names 41398 41399 +1 1 +.names 28039 41400 +1 1 +.names 41400 41401 +0 1 +.names 41406 41409 41402 +1- 1 +-1 1 +.names 41402 41403 +1 1 +.names 40458 40443 41404 +11 1 +.names 41404 41405 +1 1 +.names 41405 41406 +0 1 +.names 40417 40610 41407 +11 1 +.names 41407 41408 +1 1 +.names 41408 41409 +0 1 +.names 41403 41410 +0 1 +.names 41427 41428 41411 +1- 1 +-1 1 +.names 41411 41412 +1 1 +.names 41412 41413 +0 1 +.names 41416 41418 41414 +11 1 +.names 41414 41415 +1 1 +.names 40443 26977 41416 +1- 1 +-1 1 +.names 597 41417 +0 1 +.names 8406 41417 41418 +1- 1 +-1 1 +.names 40417 28039 41419 +1- 1 +-1 1 +.names 41419 41420 +1 1 +.names 41423 41424 41421 +1- 1 +-1 1 +.names 41421 41422 +1 1 +.names 8415 56438 41423 +11 1 +.names 41420 41424 +0 1 +.names 8406 41425 +1 1 +.names 41425 41426 +0 1 +.names 8415 41426 41427 +1- 1 +-1 1 +.names 315 41428 +0 1 +.names 41433 41434 41429 +1- 1 +-1 1 +.names 41429 41430 +1 1 +.names 41430 41431 +0 1 +.names 41422 41432 +0 1 +.names 41394 41399 41433 +11 1 +.names 41415 41434 +0 1 +.names 41440 41442 41435 +1- 1 +-1 1 +.names 41435 41436 +1 1 +.names 41467 41468 41437 +11 1 +.names 41437 41438 +1 1 +.names 41438 41439 +0 1 +.names 40458 41439 41440 +11 1 +.names 183 41441 +0 1 +.names 8395 41441 41442 +11 1 +.names 41451 41454 41443 +1- 1 +-1 1 +.names 41443 41444 +1 1 +.names 41472 41474 41445 +11 1 +.names 41445 41446 +1 1 +.names 41446 41447 +0 1 +.names 41479 41480 41448 +11 1 +.names 41448 41449 +1 1 +.names 41449 41450 +0 1 +.names 41447 41450 41451 +1- 1 +-1 1 +.names 41475 41476 41452 +11 1 +.names 41452 41453 +1 1 +.names 41453 41454 +0 1 +.names 41459 41460 41455 +1- 1 +-1 1 +.names 41455 41456 +1 1 +.names 40514 41457 +1 1 +.names 41457 41458 +0 1 +.names 8417 41458 41459 +1- 1 +-1 1 +.names 316 41460 +0 1 +.names 40414 40581 41461 +11 1 +.names 41461 41462 +1 1 +.names 40366 40505 41463 +11 1 +.names 41463 41464 +1 1 +.names 41477 41478 41465 +1- 1 +-1 1 +.names 41465 41466 +1 1 +.names 41466 41467 +0 1 +.names 41456 41468 +0 1 +.names 41444 41471 41469 +1- 1 +-1 1 +.names 41469 41470 +1 1 +.names 41436 41471 +0 1 +.names 40514 28055 41472 +1- 1 +-1 1 +.names 598 41473 +0 1 +.names 41473 40581 41474 +1- 1 +-1 1 +.names 27020 40366 41475 +1- 1 +-1 1 +.names 40378 27020 41476 +1- 1 +-1 1 +.names 41462 41477 +0 1 +.names 41464 41478 +0 1 +.names 40414 27009 41479 +1- 1 +-1 1 +.names 40505 28055 41480 +1- 1 +-1 1 +.names 41486 41488 41481 +1- 1 +-1 1 +.names 41481 41482 +1 1 +.names 41513 41514 41483 +11 1 +.names 41483 41484 +1 1 +.names 41484 41485 +0 1 +.names 40489 41485 41486 +11 1 +.names 197 41487 +0 1 +.names 8394 41487 41488 +11 1 +.names 41497 41500 41489 +1- 1 +-1 1 +.names 41489 41490 +1 1 +.names 41522 41524 41491 +11 1 +.names 41491 41492 +1 1 +.names 41492 41493 +0 1 +.names 41525 41526 41494 +11 1 +.names 41494 41495 +1 1 +.names 41495 41496 +0 1 +.names 41493 41496 41497 +1- 1 +-1 1 +.names 41518 41519 41498 +11 1 +.names 41498 41499 +1 1 +.names 41499 41500 +0 1 +.names 41505 41506 41501 +1- 1 +-1 1 +.names 41501 41502 +1 1 +.names 40355 41503 +1 1 +.names 41503 41504 +0 1 +.names 8420 41504 41505 +1- 1 +-1 1 +.names 330 41506 +0 1 +.names 40414 40581 41507 +11 1 +.names 41507 41508 +1 1 +.names 40972 40505 41509 +11 1 +.names 41509 41510 +1 1 +.names 41520 41521 41511 +1- 1 +-1 1 +.names 41511 41512 +1 1 +.names 41512 41513 +0 1 +.names 41502 41514 +0 1 +.names 41490 41517 41515 +1- 1 +-1 1 +.names 41515 41516 +1 1 +.names 41482 41517 +0 1 +.names 27066 40972 41518 +1- 1 +-1 1 +.names 40433 27066 41519 +1- 1 +-1 1 +.names 41508 41520 +0 1 +.names 41510 41521 +0 1 +.names 40355 28067 41522 +1- 1 +-1 1 +.names 612 41523 +0 1 +.names 41523 40581 41524 +1- 1 +-1 1 +.names 40414 27055 41525 +1- 1 +-1 1 +.names 40505 28067 41526 +1- 1 +-1 1 +.names 41532 41533 41527 +1- 1 +-1 1 +.names 41527 41528 +1 1 +.names 41558 41559 41529 +11 1 +.names 41529 41530 +1 1 +.names 41530 41531 +0 1 +.names 40733 41531 41532 +11 1 +.names 8429 27101 41533 +11 1 +.names 41542 41545 41534 +1- 1 +-1 1 +.names 41534 41535 +1 1 +.names 41564 41566 41536 +11 1 +.names 41536 41537 +1 1 +.names 41537 41538 +0 1 +.names 41571 41572 41539 +11 1 +.names 41539 41540 +1 1 +.names 41540 41541 +0 1 +.names 41538 41541 41542 +1- 1 +-1 1 +.names 41567 41568 41543 +11 1 +.names 41543 41544 +1 1 +.names 41544 41545 +0 1 +.names 41550 41551 41546 +1- 1 +-1 1 +.names 41546 41547 +1 1 +.names 40363 41548 +1 1 +.names 41548 41549 +0 1 +.names 8418 41549 41550 +1- 1 +-1 1 +.names 314 41551 +0 1 +.names 40872 40458 41552 +11 1 +.names 41552 41553 +1 1 +.names 40366 40367 41554 +11 1 +.names 41554 41555 +1 1 +.names 41569 41570 41556 +1- 1 +-1 1 +.names 41556 41557 +1 1 +.names 41557 41558 +0 1 +.names 41547 41559 +0 1 +.names 41535 41562 41560 +1- 1 +-1 1 +.names 41560 41561 +1 1 +.names 41528 41562 +0 1 +.names 596 41563 +0 1 +.names 41563 40363 41564 +1- 1 +-1 1 +.names 181 41565 +0 1 +.names 40458 41565 41566 +1- 1 +-1 1 +.names 27115 40366 41567 +1- 1 +-1 1 +.names 40473 27115 41568 +1- 1 +-1 1 +.names 41553 41569 +0 1 +.names 41555 41570 +0 1 +.names 40872 28087 41571 +1- 1 +-1 1 +.names 40367 28087 41572 +1- 1 +-1 1 +.names 41578 41580 41573 +1- 1 +-1 1 +.names 41573 41574 +1 1 +.names 41605 41606 41575 +11 1 +.names 41575 41576 +1 1 +.names 41576 41577 +0 1 +.names 40334 41577 41578 +11 1 +.names 195 41579 +0 1 +.names 8382 41579 41580 +11 1 +.names 41589 41592 41581 +1- 1 +-1 1 +.names 41581 41582 +1 1 +.names 41616 41618 41583 +11 1 +.names 41583 41584 +1 1 +.names 41584 41585 +0 1 +.names 41614 41615 41586 +11 1 +.names 41586 41587 +1 1 +.names 41587 41588 +0 1 +.names 41585 41588 41589 +1- 1 +-1 1 +.names 41612 41613 41590 +11 1 +.names 41590 41591 +1 1 +.names 41591 41592 +0 1 +.names 41597 41598 41593 +1- 1 +-1 1 +.names 41593 41594 +1 1 +.names 40712 41595 +1 1 +.names 41595 41596 +0 1 +.names 8418 41596 41597 +1- 1 +-1 1 +.names 328 41598 +0 1 +.names 40733 40363 41599 +11 1 +.names 41599 41600 +1 1 +.names 40366 40505 41601 +11 1 +.names 41601 41602 +1 1 +.names 41610 41611 41603 +1- 1 +-1 1 +.names 41603 41604 +1 1 +.names 41604 41605 +0 1 +.names 41594 41606 +0 1 +.names 41582 41609 41607 +1- 1 +-1 1 +.names 41607 41608 +1 1 +.names 41574 41609 +0 1 +.names 41600 41610 +0 1 +.names 41602 41611 +0 1 +.names 27160 40366 41612 +1- 1 +-1 1 +.names 40473 27160 41613 +1- 1 +-1 1 +.names 40733 27147 41614 +1- 1 +-1 1 +.names 40505 28103 41615 +1- 1 +-1 1 +.names 40712 28103 41616 +1- 1 +-1 1 +.names 610 41617 +0 1 +.names 41617 40363 41618 +1- 1 +-1 1 +.names 41621 40334 41619 +1- 1 +-1 1 +.names 41619 41620 +1 1 +.names 196 41621 +0 1 +.names 41626 41629 41622 +1- 1 +-1 1 +.names 41622 41623 +1 1 +.names 41646 41649 41624 +11 1 +.names 41624 41625 +1 1 +.names 41625 41626 +0 1 +.names 41633 41634 41627 +1- 1 +-1 1 +.names 41627 41628 +1 1 +.names 41628 41629 +0 1 +.names 41668 41669 41630 +11 1 +.names 41630 41631 +1 1 +.names 41631 41632 +0 1 +.names 40367 41632 41633 +11 1 +.names 8375 28115 41634 +11 1 +.names 41637 41639 41635 +1- 1 +-1 1 +.names 41635 41636 +1 1 +.names 41620 41637 +0 1 +.names 40355 41638 +1 1 +.names 41638 41639 +0 1 +.names 41637 41643 41640 +1- 1 +-1 1 +.names 41640 41641 +1 1 +.names 28115 41642 +1 1 +.names 41642 41643 +0 1 +.names 41650 41653 41644 +1- 1 +-1 1 +.names 41644 41645 +1 1 +.names 41645 41646 +0 1 +.names 41673 41676 41647 +1- 1 +-1 1 +.names 41647 41648 +1 1 +.names 41648 41649 +0 1 +.names 41636 41641 41650 +11 1 +.names 41671 41672 41651 +11 1 +.names 41651 41652 +1 1 +.names 41652 41653 +0 1 +.names 41658 41659 41654 +1- 1 +-1 1 +.names 41654 41655 +1 1 +.names 40363 41656 +1 1 +.names 41656 41657 +0 1 +.names 8368 41657 41658 +1- 1 +-1 1 +.names 329 41659 +0 1 +.names 41664 41667 41660 +1- 1 +-1 1 +.names 41660 41661 +1 1 +.names 40539 40334 41662 +11 1 +.names 41662 41663 +1 1 +.names 41663 41664 +0 1 +.names 40355 40473 41665 +11 1 +.names 41665 41666 +1 1 +.names 41666 41667 +0 1 +.names 41661 41668 +0 1 +.names 41655 41669 +0 1 +.names 611 41670 +0 1 +.names 40363 41670 41671 +1- 1 +-1 1 +.names 40473 27189 41672 +1- 1 +-1 1 +.names 8415 56452 41673 +11 1 +.names 27207 40443 41674 +1- 1 +-1 1 +.names 41674 41675 +1 1 +.names 41675 41676 +0 1 +.names 41682 41684 41677 +1- 1 +-1 1 +.names 41677 41678 +1 1 +.names 41709 41710 41679 +11 1 +.names 41679 41680 +1 1 +.names 41680 41681 +0 1 +.names 40489 41681 41682 +11 1 +.names 172 41683 +0 1 +.names 8394 41683 41684 +11 1 +.names 41693 41696 41685 +1- 1 +-1 1 +.names 41685 41686 +1 1 +.names 41718 41720 41687 +11 1 +.names 41687 41688 +1 1 +.names 41688 41689 +0 1 +.names 41721 41722 41690 +11 1 +.names 41690 41691 +1 1 +.names 41691 41692 +0 1 +.names 41689 41692 41693 +1- 1 +-1 1 +.names 41714 41715 41694 +11 1 +.names 41694 41695 +1 1 +.names 41695 41696 +0 1 +.names 41701 41702 41697 +1- 1 +-1 1 +.names 41697 41698 +1 1 +.names 40355 41699 +1 1 +.names 41699 41700 +0 1 +.names 8420 41700 41701 +1- 1 +-1 1 +.names 305 41702 +0 1 +.names 40733 40581 41703 +11 1 +.names 41703 41704 +1 1 +.names 40972 40367 41705 +11 1 +.names 41705 41706 +1 1 +.names 41716 41717 41707 +1- 1 +-1 1 +.names 41707 41708 +1 1 +.names 41708 41709 +0 1 +.names 41698 41710 +0 1 +.names 41686 41713 41711 +1- 1 +-1 1 +.names 41711 41712 +1 1 +.names 41678 41713 +0 1 +.names 27262 40972 41714 +1- 1 +-1 1 +.names 40433 27262 41715 +1- 1 +-1 1 +.names 41704 41716 +0 1 +.names 41706 41717 +0 1 +.names 40355 28135 41718 +1- 1 +-1 1 +.names 587 41719 +0 1 +.names 41719 40581 41720 +1- 1 +-1 1 +.names 40733 27251 41721 +1- 1 +-1 1 +.names 40367 28135 41722 +1- 1 +-1 1 +.names 41728 41730 41723 +1- 1 +-1 1 +.names 41723 41724 +1 1 +.names 41755 41756 41725 +11 1 +.names 41725 41726 +1 1 +.names 41726 41727 +0 1 +.names 40489 41727 41728 +11 1 +.names 173 41729 +0 1 +.names 8394 41729 41730 +11 1 +.names 41739 41742 41731 +1- 1 +-1 1 +.names 41731 41732 +1 1 +.names 41764 41766 41733 +11 1 +.names 41733 41734 +1 1 +.names 41734 41735 +0 1 +.names 41767 41768 41736 +11 1 +.names 41736 41737 +1 1 +.names 41737 41738 +0 1 +.names 41735 41738 41739 +1- 1 +-1 1 +.names 41760 41761 41740 +11 1 +.names 41740 41741 +1 1 +.names 41741 41742 +0 1 +.names 41747 41748 41743 +1- 1 +-1 1 +.names 41743 41744 +1 1 +.names 40514 41745 +1 1 +.names 41745 41746 +0 1 +.names 8418 41746 41747 +1- 1 +-1 1 +.names 306 41748 +0 1 +.names 40362 40363 41749 +11 1 +.names 41749 41750 +1 1 +.names 40366 40367 41751 +11 1 +.names 41751 41752 +1 1 +.names 41762 41763 41753 +1- 1 +-1 1 +.names 41753 41754 +1 1 +.names 41754 41755 +0 1 +.names 41744 41756 +0 1 +.names 41732 41759 41757 +1- 1 +-1 1 +.names 41757 41758 +1 1 +.names 41724 41759 +0 1 +.names 2413 40366 41760 +1- 1 +-1 1 +.names 40473 27308 41761 +1- 1 +-1 1 +.names 41750 41762 +0 1 +.names 41752 41763 +0 1 +.names 40514 28151 41764 +1- 1 +-1 1 +.names 588 41765 +0 1 +.names 41765 40363 41766 +1- 1 +-1 1 +.names 40362 27297 41767 +1- 1 +-1 1 +.names 40367 28151 41768 +1- 1 +-1 1 +.names 41775 41777 41769 +1- 1 +-1 1 +.names 41769 41770 +1 1 +.names 8405 41771 +0 1 +.names 41800 41801 41772 +11 1 +.names 41772 41773 +1 1 +.names 41773 41774 +0 1 +.names 41771 41774 41775 +11 1 +.names 599 41776 +0 1 +.names 8405 41776 41777 +11 1 +.names 41786 41789 41778 +1- 1 +-1 1 +.names 41778 41779 +1 1 +.names 41809 41811 41780 +11 1 +.names 41780 41781 +1 1 +.names 41781 41782 +0 1 +.names 41814 41815 41783 +11 1 +.names 41783 41784 +1 1 +.names 41784 41785 +0 1 +.names 41782 41785 41786 +1- 1 +-1 1 +.names 41805 41806 41787 +11 1 +.names 41787 41788 +1 1 +.names 41788 41789 +0 1 +.names 41793 41795 41790 +1- 1 +-1 1 +.names 41790 41791 +1 1 +.names 317 41792 +0 1 +.names 8382 41792 41793 +1- 1 +-1 1 +.names 40362 41794 +1 1 +.names 41794 41795 +0 1 +.names 40378 40444 41796 +11 1 +.names 41796 41797 +1 1 +.names 41812 41813 41798 +1- 1 +-1 1 +.names 41798 41799 +1 1 +.names 41799 41800 +0 1 +.names 41791 41801 +0 1 +.names 41779 41804 41802 +1- 1 +-1 1 +.names 41802 41803 +1 1 +.names 41770 41804 +0 1 +.names 40362 27340 41805 +1- 1 +-1 1 +.names 40444 27354 41806 +1- 1 +-1 1 +.names 40417 40610 41807 +11 1 +.names 41807 41808 +1 1 +.names 40417 28163 41809 +1- 1 +-1 1 +.names 184 41810 +0 1 +.names 40334 41810 41811 +1- 1 +-1 1 +.names 41797 41812 +0 1 +.names 41808 41813 +0 1 +.names 40378 27354 41814 +1- 1 +-1 1 +.names 40610 28163 41815 +1- 1 +-1 1 +.names 41821 41823 41816 +1- 1 +-1 1 +.names 41816 41817 +1 1 +.names 41836 41837 41818 +11 1 +.names 41818 41819 +1 1 +.names 41819 41820 +0 1 +.names 40489 41820 41821 +11 1 +.names 189 41822 +0 1 +.names 8394 41822 41823 +11 1 +.names 41828 41829 41824 +1- 1 +-1 1 +.names 41824 41825 +1 1 +.names 8406 41826 +1 1 +.names 41826 41827 +0 1 +.names 8417 41827 41828 +1- 1 +-1 1 +.names 322 41829 +0 1 +.names 40362 40444 41830 +11 1 +.names 41830 41831 +1 1 +.names 40505 40610 41832 +11 1 +.names 41832 41833 +1 1 +.names 41860 41861 41834 +1- 1 +-1 1 +.names 41834 41835 +1 1 +.names 41835 41836 +0 1 +.names 41825 41837 +0 1 +.names 41841 41842 41838 +1- 1 +-1 1 +.names 41838 41839 +1 1 +.names 41858 41859 41840 +1- 1 +-1 1 +.names 41840 41841 +1 1 +.names 41817 41842 +0 1 +.names 41845 41846 41843 +11 1 +.names 41843 41844 +1 1 +.names 40362 27378 41845 +1- 1 +-1 1 +.names 40610 28183 41846 +1- 1 +-1 1 +.names 41849 41850 41847 +11 1 +.names 41847 41848 +1 1 +.names 40505 28183 41849 +1- 1 +-1 1 +.names 40378 27395 41850 +1- 1 +-1 1 +.names 41854 41855 41851 +11 1 +.names 41851 41852 +1 1 +.names 604 41853 +0 1 +.names 41853 8406 41854 +1- 1 +-1 1 +.names 27395 40444 41855 +1- 1 +-1 1 +.names 41848 41856 +0 1 +.names 41844 41857 +0 1 +.names 41856 41857 41858 +1- 1 +-1 1 +.names 41852 41859 +0 1 +.names 41831 41860 +0 1 +.names 41833 41861 +0 1 +.names 41867 41869 41862 +1- 1 +-1 1 +.names 41862 41863 +1 1 +.names 41894 41895 41864 +11 1 +.names 41864 41865 +1 1 +.names 41865 41866 +0 1 +.names 40458 41866 41867 +11 1 +.names 198 41868 +0 1 +.names 8395 41868 41869 +11 1 +.names 41878 41881 41870 +1- 1 +-1 1 +.names 41870 41871 +1 1 +.names 41899 41901 41872 +11 1 +.names 41872 41873 +1 1 +.names 41873 41874 +0 1 +.names 41904 41905 41875 +11 1 +.names 41875 41876 +1 1 +.names 41876 41877 +0 1 +.names 41874 41877 41878 +1- 1 +-1 1 +.names 41902 41903 41879 +11 1 +.names 41879 41880 +1 1 +.names 41880 41881 +0 1 +.names 41886 41887 41882 +1- 1 +-1 1 +.names 41882 41883 +1 1 +.names 40712 41884 +1 1 +.names 41884 41885 +0 1 +.names 8417 41885 41886 +1- 1 +-1 1 +.names 331 41887 +0 1 +.names 40362 40581 41888 +11 1 +.names 41888 41889 +1 1 +.names 40366 40367 41890 +11 1 +.names 41890 41891 +1 1 +.names 41906 41907 41892 +1- 1 +-1 1 +.names 41892 41893 +1 1 +.names 41893 41894 +0 1 +.names 41883 41895 +0 1 +.names 41871 41898 41896 +1- 1 +-1 1 +.names 41896 41897 +1 1 +.names 41863 41898 +0 1 +.names 40712 28199 41899 +1- 1 +-1 1 +.names 613 41900 +0 1 +.names 41900 40581 41901 +1- 1 +-1 1 +.names 27447 40366 41902 +1- 1 +-1 1 +.names 40378 27447 41903 +1- 1 +-1 1 +.names 40362 27436 41904 +1- 1 +-1 1 +.names 40367 28199 41905 +1- 1 +-1 1 +.names 41889 41906 +0 1 +.names 41891 41907 +0 1 +.names 41914 41915 41908 +1- 1 +-1 1 +.names 41908 41909 +1 1 +.names 8452 41910 +0 1 +.names 41917 41918 41911 +11 1 +.names 41911 41912 +1 1 +.names 41912 41913 +0 1 +.names 41910 41913 41914 +11 1 +.names 8452 2413 41915 +11 1 +.names 8444 41916 +0 1 +.names 5676 41916 41917 +11 1 +.names 8445 41918 +0 1 +.names 41922 41923 41919 +1- 1 +-1 1 +.names 41919 41920 +1 1 +.names 41926 41927 41921 +1- 1 +-1 1 +.names 41921 41922 +1 1 +.names 41909 41923 +0 1 +.names 35420 41918 41924 +1- 1 +-1 1 +.names 41924 41925 +1 1 +.names 38 8444 41926 +11 1 +.names 41925 41927 +0 1 +.names 41934 41935 41928 +1- 1 +-1 1 +.names 41928 41929 +1 1 +.names 8447 41930 +0 1 +.names 41936 41910 41931 +11 1 +.names 41931 41932 +1 1 +.names 41932 41933 +0 1 +.names 41930 41933 41934 +11 1 +.names 8447 35227 41935 +11 1 +.names 5686 41916 41936 +11 1 +.names 41940 41941 41937 +1- 1 +-1 1 +.names 41937 41938 +1 1 +.names 41944 41945 41939 +1- 1 +-1 1 +.names 41939 41940 +1 1 +.names 41929 41941 +0 1 +.names 5685 41916 41942 +1- 1 +-1 1 +.names 41942 41943 +1 1 +.names 8452 1783 41944 +11 1 +.names 41943 41945 +0 1 +.names 41949 41950 41946 +11 1 +.names 41946 41947 +1 1 +.names 8443 41948 +0 1 +.names 5718 41948 41949 +11 1 +.names 8455 41950 +0 1 +.names 41954 41957 41951 +1- 1 +-1 1 +.names 41951 41952 +1 1 +.names 41965 41966 41953 +1- 1 +-1 1 +.names 41953 41954 +1 1 +.names 41960 41962 41955 +1- 1 +-1 1 +.names 41955 41956 +1 1 +.names 41956 41957 +0 1 +.names 8446 41958 +0 1 +.names 41947 41959 +0 1 +.names 41958 41959 41960 +11 1 +.names 39119 41961 +0 1 +.names 8446 41961 41962 +11 1 +.names 5717 41948 41963 +1- 1 +-1 1 +.names 41963 41964 +1 1 +.names 8455 1783 41965 +11 1 +.names 41964 41966 +0 1 +.names 41972 41973 41967 +1- 1 +-1 1 +.names 41967 41968 +1 1 +.names 41975 41918 41969 +11 1 +.names 41969 41970 +1 1 +.names 41970 41971 +0 1 +.names 41950 41971 41972 +11 1 +.names 8455 2413 41973 +11 1 +.names 8442 41974 +0 1 +.names 5690 41974 41975 +11 1 +.names 35662 41918 41976 +1- 1 +-1 1 +.names 41976 41977 +1 1 +.names 41980 41981 41978 +1- 1 +-1 1 +.names 41978 41979 +1 1 +.names 45 8442 41980 +11 1 +.names 41977 41981 +0 1 +.names 41979 41982 +0 1 +.names 41982 41983 +1 1 +.names 41986 41987 41984 +1- 1 +-1 1 +.names 41984 41985 +1 1 +.names 41983 41986 +0 1 +.names 41968 41987 +0 1 +.names 36232 41918 41988 +1- 1 +-1 1 +.names 41988 41989 +1 1 +.names 41992 41993 41990 +1- 1 +-1 1 +.names 41990 41991 +1 1 +.names 47 8444 41992 +11 1 +.names 41989 41993 +0 1 +.names 41996 41918 41994 +11 1 +.names 41994 41995 +1 1 +.names 5694 41916 41996 +11 1 +.names 42001 42002 41997 +1- 1 +-1 1 +.names 41997 41998 +1 1 +.names 8456 41999 +0 1 +.names 41995 42000 +0 1 +.names 41999 42000 42001 +11 1 +.names 8456 2413 42002 +11 1 +.names 41991 42005 42003 +1- 1 +-1 1 +.names 42003 42004 +1 1 +.names 41998 42005 +0 1 +.names 42011 42012 42006 +1- 1 +-1 1 +.names 42006 42007 +1 1 +.names 42013 41918 42008 +11 1 +.names 42008 42009 +1 1 +.names 42009 42010 +0 1 +.names 41950 42010 42011 +11 1 +.names 8455 2413 42012 +11 1 +.names 5708 41974 42013 +11 1 +.names 42016 41918 42014 +1- 1 +-1 1 +.names 42014 42015 +1 1 +.names 39316 42016 +0 1 +.names 42019 42020 42017 +1- 1 +-1 1 +.names 42017 42018 +1 1 +.names 54 8442 42019 +11 1 +.names 42015 42020 +0 1 +.names 42018 42021 +0 1 +.names 42021 42022 +1 1 +.names 42025 42026 42023 +1- 1 +-1 1 +.names 42023 42024 +1 1 +.names 42022 42025 +0 1 +.names 42007 42026 +0 1 +.names 42029 41950 42027 +11 1 +.names 42027 42028 +1 1 +.names 5734 41948 42029 +11 1 +.names 42033 42036 42030 +1- 1 +-1 1 +.names 42030 42031 +1 1 +.names 42043 42044 42032 +1- 1 +-1 1 +.names 42032 42033 +1 1 +.names 42038 42040 42034 +1- 1 +-1 1 +.names 42034 42035 +1 1 +.names 42035 42036 +0 1 +.names 42028 42037 +0 1 +.names 41958 42037 42038 +11 1 +.names 39353 42039 +0 1 +.names 8446 42039 42040 +11 1 +.names 5733 41948 42041 +1- 1 +-1 1 +.names 42041 42042 +1 1 +.names 8455 1783 42043 +11 1 +.names 42042 42044 +0 1 +.names 42050 42051 42045 +1- 1 +-1 1 +.names 42045 42046 +1 1 +.names 42052 41918 42047 +11 1 +.names 42047 42048 +1 1 +.names 42048 42049 +0 1 +.names 41910 42049 42050 +11 1 +.names 8452 2413 42051 +11 1 +.names 5712 41916 42052 +11 1 +.names 42056 42057 42053 +1- 1 +-1 1 +.names 42053 42054 +1 1 +.names 42061 42062 42055 +1- 1 +-1 1 +.names 42055 42056 +1 1 +.names 42046 42057 +0 1 +.names 42060 41918 42058 +1- 1 +-1 1 +.names 42058 42059 +1 1 +.names 39393 42060 +0 1 +.names 56 8444 42061 +11 1 +.names 42059 42062 +0 1 +.names 42065 42066 42063 +11 1 +.names 42063 42064 +1 1 +.names 5692 41948 42065 +11 1 +.names 8454 42066 +0 1 +.names 42070 42073 42067 +1- 1 +-1 1 +.names 42067 42068 +1 1 +.names 42079 42080 42069 +1- 1 +-1 1 +.names 42069 42070 +1 1 +.names 42075 42076 42071 +1- 1 +-1 1 +.names 42071 42072 +1 1 +.names 42072 42073 +0 1 +.names 42064 42074 +0 1 +.names 41958 42074 42075 +11 1 +.names 8446 35583 42076 +11 1 +.names 5691 41948 42077 +1- 1 +-1 1 +.names 42077 42078 +1 1 +.names 8454 1783 42079 +11 1 +.names 42078 42080 +0 1 +.names 42086 42087 42081 +1- 1 +-1 1 +.names 42081 42082 +1 1 +.names 42088 41918 42083 +11 1 +.names 42083 42084 +1 1 +.names 42084 42085 +0 1 +.names 41910 42085 42086 +11 1 +.names 8452 2413 42087 +11 1 +.names 5724 41974 42088 +11 1 +.names 42091 41918 42089 +1- 1 +-1 1 +.names 42089 42090 +1 1 +.names 39470 42091 +0 1 +.names 42094 42095 42092 +1- 1 +-1 1 +.names 42092 42093 +1 1 +.names 62 8442 42094 +11 1 +.names 42090 42095 +0 1 +.names 42093 42096 +0 1 +.names 42096 42097 +1 1 +.names 42100 42101 42098 +1- 1 +-1 1 +.names 42098 42099 +1 1 +.names 42097 42100 +0 1 +.names 42082 42101 +0 1 +.names 42107 42108 42102 +1- 1 +-1 1 +.names 42102 42103 +1 1 +.names 42109 41999 42104 +11 1 +.names 42104 42105 +1 1 +.names 42105 42106 +0 1 +.names 41930 42106 42107 +11 1 +.names 8447 36259 42108 +11 1 +.names 5696 41974 42109 +11 1 +.names 42113 42114 42110 +1- 1 +-1 1 +.names 42110 42111 +1 1 +.names 42117 42118 42112 +1- 1 +-1 1 +.names 42112 42113 +1 1 +.names 42103 42114 +0 1 +.names 5695 41974 42115 +1- 1 +-1 1 +.names 42115 42116 +1 1 +.names 8456 1783 42117 +11 1 +.names 42116 42118 +0 1 +.names 42121 42066 42119 +11 1 +.names 42119 42120 +1 1 +.names 5722 41948 42121 +11 1 +.names 42125 42128 42122 +1- 1 +-1 1 +.names 42122 42123 +1 1 +.names 42133 42136 42124 +1- 1 +-1 1 +.names 42124 42125 +1 1 +.names 42130 42132 42126 +1- 1 +-1 1 +.names 42126 42127 +1 1 +.names 42127 42128 +0 1 +.names 42120 42129 +0 1 +.names 41930 42129 42130 +11 1 +.names 39542 42131 +0 1 +.names 8447 42131 42132 +11 1 +.names 61 8443 42133 +11 1 +.names 2413 42066 42134 +1- 1 +-1 1 +.names 42134 42135 +1 1 +.names 42135 42136 +0 1 +.names 42142 42143 42137 +1- 1 +-1 1 +.names 42137 42138 +1 1 +.names 42145 41950 42139 +11 1 +.names 42139 42140 +1 1 +.names 42140 42141 +0 1 +.names 41930 42141 42142 +11 1 +.names 8447 35891 42143 +11 1 +.names 8453 42144 +0 1 +.names 5674 42144 42145 +11 1 +.names 42151 42152 42146 +1- 1 +-1 1 +.names 42146 42147 +1 1 +.names 42138 42148 +0 1 +.names 5673 42144 42149 +1- 1 +-1 1 +.names 42149 42150 +1 1 +.names 8455 1783 42151 +11 1 +.names 42150 42152 +0 1 +.names 42158 42159 42153 +1- 1 +-1 1 +.names 42153 42154 +1 1 +.names 42160 41950 42155 +11 1 +.names 42155 42156 +1 1 +.names 42156 42157 +0 1 +.names 41930 42157 42158 +11 1 +.names 8447 35723 42159 +11 1 +.names 5678 41974 42160 +11 1 +.names 42164 42165 42161 +1- 1 +-1 1 +.names 42161 42162 +1 1 +.names 42168 42169 42163 +1- 1 +-1 1 +.names 42163 42164 +1 1 +.names 42154 42165 +0 1 +.names 5677 41974 42166 +1- 1 +-1 1 +.names 42166 42167 +1 1 +.names 8455 1783 42168 +11 1 +.names 42167 42169 +0 1 +.names 42175 42176 42170 +1- 1 +-1 1 +.names 42170 42171 +1 1 +.names 42177 41910 42172 +11 1 +.names 42172 42173 +1 1 +.names 42173 42174 +0 1 +.names 42144 42174 42175 +11 1 +.names 8453 5683 42176 +11 1 +.names 5684 41958 42177 +11 1 +.names 42181 42182 42178 +1- 1 +-1 1 +.names 42178 42179 +1 1 +.names 42183 42186 42180 +1- 1 +-1 1 +.names 42180 42181 +1 1 +.names 42171 42182 +0 1 +.names 8452 1783 42183 +11 1 +.names 36025 41958 42184 +1- 1 +-1 1 +.names 42184 42185 +1 1 +.names 42185 42186 +0 1 +.names 42189 42066 42187 +11 1 +.names 42187 42188 +1 1 +.names 5688 41948 42189 +11 1 +.names 42193 42196 42190 +1- 1 +-1 1 +.names 42190 42191 +1 1 +.names 42202 42203 42192 +1- 1 +-1 1 +.names 42192 42193 +1 1 +.names 42198 42199 42194 +1- 1 +-1 1 +.names 42194 42195 +1 1 +.names 42195 42196 +0 1 +.names 42188 42197 +0 1 +.names 41958 42197 42198 +11 1 +.names 8446 35942 42199 +11 1 +.names 5687 41948 42200 +1- 1 +-1 1 +.names 42200 42201 +1 1 +.names 8454 1783 42202 +11 1 +.names 42201 42203 +0 1 +.names 42209 42210 42204 +1- 1 +-1 1 +.names 42204 42205 +1 1 +.names 42211 41918 42206 +11 1 +.names 42206 42207 +1 1 +.names 42207 42208 +0 1 +.names 41999 42208 42209 +11 1 +.names 8456 2413 42210 +11 1 +.names 5710 41974 42211 +11 1 +.names 42214 41918 42212 +1- 1 +-1 1 +.names 42212 42213 +1 1 +.names 39634 42214 +0 1 +.names 42217 42218 42215 +1- 1 +-1 1 +.names 42215 42216 +1 1 +.names 55 8442 42217 +11 1 +.names 42213 42218 +0 1 +.names 42216 42219 +0 1 +.names 42219 42220 +1 1 +.names 42223 42224 42221 +1- 1 +-1 1 +.names 42221 42222 +1 1 +.names 42220 42223 +0 1 +.names 42205 42224 +0 1 +.names 42230 42232 42225 +1- 1 +-1 1 +.names 42225 42226 +1 1 +.names 42233 41910 42227 +11 1 +.names 42227 42228 +1 1 +.names 42228 42229 +0 1 +.names 41930 42229 42230 +11 1 +.names 39801 42231 +0 1 +.names 8447 42231 42232 +11 1 +.names 5706 42144 42233 +11 1 +.names 42237 42238 42234 +1- 1 +-1 1 +.names 42234 42235 +1 1 +.names 42241 42242 42236 +1- 1 +-1 1 +.names 42236 42237 +1 1 +.names 42226 42238 +0 1 +.names 5705 42144 42239 +1- 1 +-1 1 +.names 42239 42240 +1 1 +.names 8452 1783 42241 +11 1 +.names 42240 42242 +0 1 +.names 42248 42249 42243 +1- 1 +-1 1 +.names 42243 42244 +1 1 +.names 42250 42066 42245 +11 1 +.names 42245 42246 +1 1 +.names 42246 42247 +0 1 +.names 42144 42247 42248 +11 1 +.names 8453 5719 42249 +11 1 +.names 5720 41958 42250 +11 1 +.names 42254 42255 42251 +1- 1 +-1 1 +.names 42251 42252 +1 1 +.names 42259 42260 42253 +1- 1 +-1 1 +.names 42253 42254 +1 1 +.names 42244 42255 +0 1 +.names 42258 41958 42256 +1- 1 +-1 1 +.names 42256 42257 +1 1 +.names 39811 42258 +0 1 +.names 1783 8454 42259 +11 1 +.names 42257 42260 +0 1 +.names 42266 42268 42261 +1- 1 +-1 1 +.names 42261 42262 +1 1 +.names 42269 41999 42263 +11 1 +.names 42263 42264 +1 1 +.names 42264 42265 +0 1 +.names 41958 42265 42266 +11 1 +.names 39848 42267 +0 1 +.names 8446 42267 42268 +11 1 +.names 5736 42144 42269 +11 1 +.names 42273 42274 42270 +1- 1 +-1 1 +.names 42270 42271 +1 1 +.names 42275 42278 42272 +1- 1 +-1 1 +.names 42272 42273 +1 1 +.names 42262 42274 +0 1 +.names 8456 1783 42275 +11 1 +.names 5735 42144 42276 +1- 1 +-1 1 +.names 42276 42277 +1 1 +.names 42277 42278 +0 1 +.names 42284 42285 42279 +1- 1 +-1 1 +.names 42279 42280 +1 1 +.names 42286 41910 42281 +11 1 +.names 42281 42282 +1 1 +.names 42282 42283 +0 1 +.names 42144 42283 42284 +11 1 +.names 8453 5715 42285 +11 1 +.names 5716 41918 42286 +11 1 +.names 42290 42291 42287 +1- 1 +-1 1 +.names 42287 42288 +1 1 +.names 42295 42296 42289 +1- 1 +-1 1 +.names 42289 42290 +1 1 +.names 42280 42291 +0 1 +.names 42294 41918 42292 +1- 1 +-1 1 +.names 42292 42293 +1 1 +.names 39881 42294 +0 1 +.names 1783 8452 42295 +11 1 +.names 42293 42296 +0 1 +.names 42302 42303 42297 +1- 1 +-1 1 +.names 42297 42298 +1 1 +.names 42304 41999 42299 +11 1 +.names 42299 42300 +1 1 +.names 42300 42301 +0 1 +.names 41916 42301 42302 +11 1 +.names 8444 5699 42303 +11 1 +.names 5700 41930 42304 +11 1 +.names 42308 42309 42305 +1- 1 +-1 1 +.names 42305 42306 +1 1 +.names 42312 42313 42307 +1- 1 +-1 1 +.names 42307 42308 +1 1 +.names 42298 42309 +0 1 +.names 36465 41930 42310 +1- 1 +-1 1 +.names 42310 42311 +1 1 +.names 8456 1783 42312 +11 1 +.names 42311 42313 +0 1 +.names 42316 41910 42314 +11 1 +.names 42314 42315 +1 1 +.names 5702 41948 42316 +11 1 +.names 42320 42323 42317 +1- 1 +-1 1 +.names 42317 42318 +1 1 +.names 42326 42327 42319 +1- 1 +-1 1 +.names 42319 42320 +1 1 +.names 42329 42330 42321 +1- 1 +-1 1 +.names 42321 42322 +1 1 +.names 42322 42323 +0 1 +.names 5701 41948 42324 +1- 1 +-1 1 +.names 42324 42325 +1 1 +.names 8452 1783 42326 +11 1 +.names 42325 42327 +0 1 +.names 42315 42328 +0 1 +.names 41958 42328 42329 +11 1 +.names 8446 35469 42330 +11 1 +.names 42336 42337 42331 +1- 1 +-1 1 +.names 42331 42332 +1 1 +.names 42338 41910 42333 +11 1 +.names 42333 42334 +1 1 +.names 42334 42335 +0 1 +.names 41916 42335 42336 +11 1 +.names 8444 5729 42337 +11 1 +.names 5730 41958 42338 +11 1 +.names 42342 42343 42339 +1- 1 +-1 1 +.names 42339 42340 +1 1 +.names 42347 42348 42341 +1- 1 +-1 1 +.names 42341 42342 +1 1 +.names 42332 42343 +0 1 +.names 42346 41958 42344 +1- 1 +-1 1 +.names 42344 42345 +1 1 +.names 39992 42346 +0 1 +.names 8452 1783 42347 +11 1 +.names 42345 42348 +0 1 +.names 42354 42355 42349 +1- 1 +-1 1 +.names 42349 42350 +1 1 +.names 42356 42066 42351 +11 1 +.names 42351 42352 +1 1 +.names 42352 42353 +0 1 +.names 42144 42353 42354 +11 1 +.names 8453 5725 42355 +11 1 +.names 5726 41918 42356 +11 1 +.names 42360 42361 42357 +1- 1 +-1 1 +.names 42357 42358 +1 1 +.names 42365 42366 42359 +1- 1 +-1 1 +.names 42359 42360 +1 1 +.names 42350 42361 +0 1 +.names 42364 41918 42362 +1- 1 +-1 1 +.names 42362 42363 +1 1 +.names 40070 42364 +0 1 +.names 8454 1783 42365 +11 1 +.names 42363 42366 +0 1 +.names 42372 42373 42367 +1- 1 +-1 1 +.names 42367 42368 +1 1 +.names 42374 42066 42369 +11 1 +.names 42369 42370 +1 1 +.names 42370 42371 +0 1 +.names 42144 42371 42372 +11 1 +.names 8453 5697 42373 +11 1 +.names 5698 41930 42374 +11 1 +.names 42378 42379 42375 +1- 1 +-1 1 +.names 42375 42376 +1 1 +.names 42382 42383 42377 +1- 1 +-1 1 +.names 42377 42378 +1 1 +.names 42368 42379 +0 1 +.names 36139 41930 42380 +1- 1 +-1 1 +.names 42380 42381 +1 1 +.names 8454 1783 42382 +11 1 +.names 42381 42383 +0 1 +.names 42389 42390 42384 +1- 1 +-1 1 +.names 42384 42385 +1 1 +.names 42391 41950 42386 +11 1 +.names 42386 42387 +1 1 +.names 42387 42388 +0 1 +.names 41974 42388 42389 +11 1 +.names 8442 5727 42390 +11 1 +.names 5728 41958 42391 +11 1 +.names 42395 42396 42392 +1- 1 +-1 1 +.names 42392 42393 +1 1 +.names 42400 42401 42394 +1- 1 +-1 1 +.names 42394 42395 +1 1 +.names 42385 42396 +0 1 +.names 42399 41958 42397 +1- 1 +-1 1 +.names 42397 42398 +1 1 +.names 40112 42399 +0 1 +.names 8455 1783 42400 +11 1 +.names 42398 42401 +0 1 +.names 42407 42408 42402 +1- 1 +-1 1 +.names 42402 42403 +1 1 +.names 42409 41999 42404 +11 1 +.names 42404 42405 +1 1 +.names 42405 42406 +0 1 +.names 41930 42406 42407 +11 1 +.names 8447 35511 42408 +11 1 +.names 5680 41916 42409 +11 1 +.names 42413 42414 42410 +1- 1 +-1 1 +.names 42410 42411 +1 1 +.names 42417 42418 42412 +1- 1 +-1 1 +.names 42412 42413 +1 1 +.names 42403 42414 +0 1 +.names 5679 41916 42415 +1- 1 +-1 1 +.names 42415 42416 +1 1 +.names 8456 1783 42417 +11 1 +.names 42416 42418 +0 1 +.names 42424 42425 42419 +1- 1 +-1 1 +.names 42419 42420 +1 1 +.names 42426 41999 42421 +11 1 +.names 42421 42422 +1 1 +.names 42422 42423 +0 1 +.names 41930 42423 42424 +11 1 +.names 8447 36395 42425 +11 1 +.names 5682 41916 42426 +11 1 +.names 42430 42431 42427 +1- 1 +-1 1 +.names 42427 42428 +1 1 +.names 42432 42435 42429 +1- 1 +-1 1 +.names 42429 42430 +1 1 +.names 42420 42431 +0 1 +.names 41 8444 42432 +11 1 +.names 2413 41999 42433 +1- 1 +-1 1 +.names 42433 42434 +1 1 +.names 42434 42435 +0 1 +.names 42441 42442 42436 +1- 1 +-1 1 +.names 42436 42437 +1 1 +.names 42443 42066 42438 +11 1 +.names 42438 42439 +1 1 +.names 42439 42440 +0 1 +.names 41974 42440 42441 +11 1 +.names 8442 5703 42442 +11 1 +.names 5704 41930 42443 +11 1 +.names 42447 42448 42444 +1- 1 +-1 1 +.names 42444 42445 +1 1 +.names 42449 42452 42446 +1- 1 +-1 1 +.names 42446 42447 +1 1 +.names 42437 42448 +0 1 +.names 8454 1783 42449 +11 1 +.names 35987 41930 42450 +1- 1 +-1 1 +.names 42450 42451 +1 1 +.names 42451 42452 +0 1 +.names 42458 42459 42453 +1- 1 +-1 1 +.names 42453 42454 +1 1 +.names 42460 41950 42455 +11 1 +.names 42455 42456 +1 1 +.names 42456 42457 +0 1 +.names 41916 42457 42458 +11 1 +.names 8444 5713 42459 +11 1 +.names 5714 41958 42460 +11 1 +.names 42464 42465 42461 +1- 1 +-1 1 +.names 42461 42462 +1 1 +.names 42469 42470 42463 +1- 1 +-1 1 +.names 42463 42464 +1 1 +.names 42454 42465 +0 1 +.names 42468 41958 42466 +1- 1 +-1 1 +.names 42466 42467 +1 1 +.names 40291 42468 +0 1 +.names 1783 8455 42469 +11 1 +.names 42467 42470 +0 1 +.names 42473 41999 42471 +11 1 +.names 42471 42472 +1 1 +.names 5732 41948 42473 +11 1 +.names 42477 42480 42474 +1- 1 +-1 1 +.names 42474 42475 +1 1 +.names 42487 42488 42476 +1- 1 +-1 1 +.names 42476 42477 +1 1 +.names 42482 42484 42478 +1- 1 +-1 1 +.names 42478 42479 +1 1 +.names 42479 42480 +0 1 +.names 42472 42481 +0 1 +.names 41958 42481 42482 +11 1 +.names 40295 42483 +0 1 +.names 8446 42483 42484 +11 1 +.names 5731 41948 42485 +1- 1 +-1 1 +.names 42485 42486 +1 1 +.names 8456 1783 42487 +11 1 +.names 42486 42488 +0 1 +.names 41169 42489 +0 1 +.names 42252 42490 +0 1 +.names 42499 42502 42491 +11 1 +.names 42491 42492 +1 1 +.names 43021 43024 42493 +1- 1 +-1 1 +.names 42493 42494 +1 1 +.names 42494 42495 +0 1 +.names 42775 43005 42496 +11 1 +.names 42496 42497 +1 1 +.names 42497 42498 +0 1 +.names 42495 42498 42499 +1- 1 +-1 1 +.names 43009 42781 42500 +1- 1 +-1 1 +.names 42500 42501 +1 1 +.names 42501 42502 +0 1 +.names 42498 42507 42503 +1- 1 +-1 1 +.names 42503 42504 +1 1 +.names 43020 42802 42505 +11 1 +.names 42505 42506 +1 1 +.names 42506 42507 +0 1 +.names 42511 42508 +0 1 +.names 42508 42509 +1 1 +.names 43438 42510 +0 1 +.names 42510 42511 +1 1 +.names 43112 42512 +0 1 +.names 42512 42513 +1 1 +.names 42513 42514 +0 1 +.names 42509 42515 +0 1 +.names 42514 42515 42516 +11 1 +.names 42559 42517 +0 1 +.names 42517 42518 +1 1 +.names 42518 42519 +0 1 +.names 42513 42519 42520 +11 1 +.names 42557 42521 +0 1 +.names 42521 42522 +1 1 +.names 42522 42523 +0 1 +.names 42514 42523 42524 +11 1 +.names 42555 42525 +0 1 +.names 42525 42526 +1 1 +.names 42526 42527 +0 1 +.names 42513 42527 42528 +11 1 +.names 42553 42529 +0 1 +.names 42529 42530 +1 1 +.names 42530 42531 +0 1 +.names 42514 42531 42532 +11 1 +.names 42551 42533 +0 1 +.names 42533 42534 +1 1 +.names 42534 42535 +0 1 +.names 42513 42535 42536 +11 1 +.names 42541 42545 56698 +1- 1 +-1 1 +.names 42549 42538 +0 1 +.names 42538 42539 +1 1 +.names 42539 42540 +0 1 +.names 42514 42540 42541 +11 1 +.names 42547 42542 +0 1 +.names 42542 42543 +1 1 +.names 42543 42544 +0 1 +.names 42513 42544 42545 +11 1 +.names 43485 43457 42546 +01 1 +10 1 +.names 42546 42547 +1 1 +.names 43475 42548 +0 1 +.names 42548 42549 +1 1 +.names 43474 43440 42550 +01 1 +10 1 +.names 42550 42551 +1 1 +.names 43488 42552 +0 1 +.names 42552 42553 +1 1 +.names 43490 43492 42554 +01 1 +10 1 +.names 42554 42555 +1 1 +.names 43493 42556 +0 1 +.names 42556 42557 +1 1 +.names 43494 42558 +0 1 +.names 42558 42559 +1 1 +.names 41185 42560 +0 1 +.names 42271 42561 +0 1 +.names 41129 42562 +0 1 +.names 42235 42563 +0 1 +.names 41758 42564 +0 1 +.names 42428 42565 +0 1 +.names 42568 42569 42566 +1- 1 +-1 1 +.names 42566 42567 +1 1 +.names 14511 42568 +0 1 +.names 14499 42569 +0 1 +.names 42575 42576 42570 +1- 1 +-1 1 +.names 42570 42571 +1 1 +.names 14655 42572 +0 1 +.names 14596 42573 +0 1 +.names 42572 42573 42574 +1- 1 +-1 1 +.names 42574 42569 42575 +1- 1 +-1 1 +.names 14503 42576 +0 1 +.names 42579 42580 42577 +1- 1 +-1 1 +.names 42577 42578 +1 1 +.names 42576 42569 42579 +1- 1 +-1 1 +.names 14515 42580 +0 1 +.names 42576 42580 42581 +1- 1 +-1 1 +.names 42581 42582 +1 1 +.names 14511 42576 42583 +1- 1 +-1 1 +.names 42583 42584 +1 1 +.names 42588 42591 42585 +1- 1 +-1 1 +.names 42585 42586 +1 1 +.names 42582 42587 +0 1 +.names 14511 42587 42588 +1- 1 +-1 1 +.names 42639 42573 42589 +1- 1 +-1 1 +.names 42589 42590 +1 1 +.names 42590 42591 +0 1 +.names 42595 42587 42592 +1- 1 +-1 1 +.names 42592 42593 +1 1 +.names 42568 42594 +1 1 +.names 42594 42595 +0 1 +.names 14507 42569 42596 +1- 1 +-1 1 +.names 42596 42597 +1 1 +.names 42603 42604 42598 +1- 1 +-1 1 +.names 42598 42599 +1 1 +.names 42578 42600 +0 1 +.names 14507 42600 42601 +1- 1 +-1 1 +.names 42571 42602 +0 1 +.names 42601 42602 42603 +1- 1 +-1 1 +.names 42567 42604 +0 1 +.names 14651 42607 42605 +1- 1 +-1 1 +.names 42605 42606 +1 1 +.names 14647 42607 +0 1 +.names 14515 42572 42608 +1- 1 +-1 1 +.names 42608 42609 +1 1 +.names 42613 42586 42610 +01 1 +10 1 +.names 42610 42611 +1 1 +.names 42597 42612 +0 1 +.names 42612 42613 +1 1 +.names 42616 42614 +0 1 +.names 42614 42615 +1 1 +.names 42597 42593 42616 +01 1 +10 1 +.names 42620 42599 42617 +01 1 +10 1 +.names 42617 42618 +1 1 +.names 42606 42619 +0 1 +.names 42619 42620 +1 1 +.names 42620 42624 42621 +01 1 +10 1 +.names 42621 42622 +1 1 +.names 42638 42600 42623 +1- 1 +-1 1 +.names 42623 42624 +1 1 +.names 42627 42580 42625 +11 1 +.names 42625 42626 +1 1 +.names 42572 42573 42627 +1- 1 +-1 1 +.names 42626 42584 42628 +01 1 +10 1 +.names 42628 42629 +1 1 +.names 42632 42630 +0 1 +.names 42630 42631 +1 1 +.names 42584 14515 42632 +01 1 +10 1 +.names 42635 42633 +0 1 +.names 42633 42634 +1 1 +.names 42609 14596 42635 +01 1 +10 1 +.names 42609 42636 +0 1 +.names 42636 42637 +1 1 +.names 14507 42604 42638 +1- 1 +-1 1 +.names 42572 42576 42639 +1- 1 +-1 1 +.names 42642 42643 42640 +1- 1 +-1 1 +.names 42640 42641 +1 1 +.names 14555 42642 +0 1 +.names 14551 42643 +0 1 +.names 42648 42649 42644 +1- 1 +-1 1 +.names 42644 42645 +1 1 +.names 14614 42646 +0 1 +.names 14703 42647 +0 1 +.names 42646 42647 42648 +1- 1 +-1 1 +.names 14610 42649 +0 1 +.names 42652 42647 42650 +1- 1 +-1 1 +.names 42650 42651 +1 1 +.names 14559 42652 +0 1 +.names 42656 42657 42653 +1- 1 +-1 1 +.names 42653 42654 +1 1 +.names 42651 42655 +0 1 +.names 14555 42655 42656 +1- 1 +-1 1 +.names 42645 42657 +0 1 +.names 42661 42655 42658 +1- 1 +-1 1 +.names 42658 42659 +1 1 +.names 42642 42660 +1 1 +.names 42660 42661 +0 1 +.names 14699 42643 42662 +1- 1 +-1 1 +.names 42662 42663 +1 1 +.names 42674 42677 42664 +1- 1 +-1 1 +.names 42664 42665 +1 1 +.names 42641 42666 +0 1 +.names 42715 42652 42667 +1- 1 +-1 1 +.names 42667 42668 +1 1 +.names 42668 42669 +0 1 +.names 42666 42669 42670 +1- 1 +-1 1 +.names 42714 42643 42671 +1- 1 +-1 1 +.names 42671 42672 +1 1 +.names 42672 42673 +0 1 +.names 42670 42673 42674 +1- 1 +-1 1 +.names 14699 42675 +0 1 +.names 42675 42676 +1 1 +.names 42676 42677 +0 1 +.names 14707 42680 42678 +1- 1 +-1 1 +.names 42678 42679 +1 1 +.names 14606 42680 +0 1 +.names 14559 42646 42681 +1- 1 +-1 1 +.names 42681 42682 +1 1 +.names 42685 42682 42683 +01 1 +10 1 +.names 42683 42684 +1 1 +.names 42649 42685 +1 1 +.names 42689 42654 42686 +01 1 +10 1 +.names 42686 42687 +1 1 +.names 42663 42688 +0 1 +.names 42688 42689 +1 1 +.names 42693 42665 42690 +01 1 +10 1 +.names 42690 42691 +1 1 +.names 42679 42692 +0 1 +.names 42692 42693 +1 1 +.names 42693 42697 42694 +01 1 +10 1 +.names 42694 42695 +1 1 +.names 42716 42669 42696 +1- 1 +-1 1 +.names 42696 42697 +1 1 +.names 42700 42652 42698 +11 1 +.names 42698 42699 +1 1 +.names 42646 42649 42700 +1- 1 +-1 1 +.names 42703 42701 +0 1 +.names 42701 42702 +1 1 +.names 42663 42659 42703 +01 1 +10 1 +.names 42699 42707 42704 +01 1 +10 1 +.names 42704 42705 +1 1 +.names 14555 42647 42706 +1- 1 +-1 1 +.names 42706 42707 +1 1 +.names 42710 42708 +0 1 +.names 42708 42709 +1 1 +.names 42707 14559 42710 +01 1 +10 1 +.names 42682 42711 +0 1 +.names 42711 42712 +1 1 +.names 42646 42649 42713 +1- 1 +-1 1 +.names 42713 42647 42714 +1- 1 +-1 1 +.names 42647 42643 42715 +1- 1 +-1 1 +.names 14699 42666 42716 +1- 1 +-1 1 +.names 42720 42717 +0 1 +.names 42717 42718 +1 1 +.names 43544 42719 +0 1 +.names 42719 42720 +1 1 +.names 43237 42721 +1 1 +.names 42721 42722 +1 1 +.names 42722 42723 +0 1 +.names 42718 42724 +0 1 +.names 42723 42724 42725 +11 1 +.names 42767 42726 +0 1 +.names 42726 42727 +1 1 +.names 42727 42728 +0 1 +.names 42722 42728 42729 +11 1 +.names 42765 42730 +0 1 +.names 42730 42731 +1 1 +.names 42731 42732 +0 1 +.names 42723 42732 42733 +11 1 +.names 42763 42734 +0 1 +.names 42734 42735 +1 1 +.names 42735 42736 +0 1 +.names 42722 42736 42737 +11 1 +.names 42761 42738 +0 1 +.names 42738 42739 +1 1 +.names 42739 42740 +0 1 +.names 42723 42740 42741 +11 1 +.names 42759 42742 +0 1 +.names 42742 42743 +1 1 +.names 42743 42744 +0 1 +.names 42722 42744 42745 +11 1 +.names 42757 42746 +0 1 +.names 42746 42747 +1 1 +.names 42747 42748 +0 1 +.names 42723 42748 42749 +11 1 +.names 42755 42750 +0 1 +.names 42750 42751 +1 1 +.names 42751 42752 +0 1 +.names 42722 42752 42753 +11 1 +.names 43567 43542 42754 +01 1 +10 1 +.names 42754 42755 +1 1 +.names 43565 42756 +0 1 +.names 42756 42757 +1 1 +.names 43562 43564 42758 +01 1 +10 1 +.names 42758 42759 +1 1 +.names 43572 42760 +0 1 +.names 42760 42761 +1 1 +.names 43560 43529 42762 +01 1 +10 1 +.names 42762 42763 +1 1 +.names 43573 42764 +0 1 +.names 42764 42765 +1 1 +.names 43558 43544 42766 +01 1 +10 1 +.names 42766 42767 +1 1 +.names 42772 42775 42768 +11 1 +.names 42768 42769 +1 1 +.names 43096 43097 42770 +1- 1 +-1 1 +.names 42770 42771 +1 1 +.names 42771 42772 +0 1 +.names 43649 43652 42773 +1- 1 +-1 1 +.names 42773 42774 +1 1 +.names 42774 42775 +0 1 +.names 42769 42776 +1 1 +.names 42782 42785 42777 +1- 1 +-1 1 +.names 42777 42778 +1 1 +.names 43658 42779 +0 1 +.names 42779 42780 +1 1 +.names 42780 42781 +0 1 +.names 42781 42772 42782 +11 1 +.names 43099 43100 42783 +11 1 +.names 42783 42784 +1 1 +.names 42784 42785 +0 1 +.names 40897 42786 +0 1 +.names 42123 42787 +0 1 +.names 41075 42788 +0 1 +.names 42222 42789 +0 1 +.names 40880 42790 +0 1 +.names 42111 42791 +0 1 +.names 41712 42792 +0 1 +.names 42411 42793 +0 1 +.names 14490 14494 42794 +1- 1 +-1 1 +.names 42794 42795 +1 1 +.names 14674 14670 42796 +11 1 +.names 42796 42797 +1 1 +.names 42801 42798 +0 1 +.names 42798 42799 +1 1 +.names 43250 42800 +0 1 +.names 42800 42801 +1 1 +.names 42805 42802 +0 1 +.names 42802 42803 +1 1 +.names 43245 43246 42804 +1- 1 +-1 1 +.names 42804 42805 +1 1 +.names 42810 42811 42806 +1- 1 +-1 1 +.names 42806 42807 +1 1 +.names 42799 42808 +0 1 +.names 42803 42809 +0 1 +.names 42808 42809 42810 +11 1 +.names 14573 42801 42811 +11 1 +.names 42816 42812 +0 1 +.names 42812 42813 +1 1 +.names 14547 42817 42814 +1- 1 +-1 1 +.names 42814 42815 +1 1 +.names 42815 14719 42816 +01 1 +10 1 +.names 14576 42817 +0 1 +.names 42822 42825 42818 +1- 1 +-1 1 +.names 42818 42819 +1 1 +.names 14547 42820 +0 1 +.names 42820 42821 +1 1 +.names 42821 42822 +0 1 +.names 42872 42817 42823 +1- 1 +-1 1 +.names 42823 42824 +1 1 +.names 42824 42825 +0 1 +.names 14543 42828 42826 +1- 1 +-1 1 +.names 42826 42827 +1 1 +.names 14727 42828 +0 1 +.names 42838 42841 42829 +1- 1 +-1 1 +.names 42829 42830 +1 1 +.names 42876 42817 42831 +1- 1 +-1 1 +.names 42831 42832 +1 1 +.names 42832 42833 +0 1 +.names 14543 42833 42834 +1- 1 +-1 1 +.names 42878 42828 42835 +1- 1 +-1 1 +.names 42835 42836 +1 1 +.names 42836 42837 +0 1 +.names 42834 42837 42838 +1- 1 +-1 1 +.names 42820 42828 42839 +1- 1 +-1 1 +.names 42839 42840 +1 1 +.names 42840 42841 +0 1 +.names 14711 42649 42842 +1- 1 +-1 1 +.names 42842 42843 +1 1 +.names 14719 42846 42844 +1- 1 +-1 1 +.names 42844 42845 +1 1 +.names 14539 42846 +0 1 +.names 42850 42845 42847 +01 1 +10 1 +.names 42847 42848 +1 1 +.names 14618 42849 +0 1 +.names 42849 42850 +1 1 +.names 42854 42815 42851 +01 1 +10 1 +.names 42851 42852 +1 1 +.names 42884 42872 42853 +11 1 +.names 42853 42854 +1 1 +.names 42858 42860 42855 +01 1 +10 1 +.names 42855 42856 +1 1 +.names 42827 42857 +0 1 +.names 42857 42858 +1 1 +.names 42882 42883 42859 +1- 1 +-1 1 +.names 42859 42860 +1 1 +.names 42863 42861 +0 1 +.names 42861 42862 +1 1 +.names 42827 42819 42863 +01 1 +10 1 +.names 42867 42830 42864 +01 1 +10 1 +.names 42864 42865 +1 1 +.names 42843 42866 +0 1 +.names 42866 42867 +1 1 +.names 42867 42871 42868 +01 1 +10 1 +.names 42868 42869 +1 1 +.names 42881 42833 42870 +1- 1 +-1 1 +.names 42870 42871 +1 1 +.names 14719 42872 +0 1 +.names 42875 42849 42873 +1- 1 +-1 1 +.names 42873 42874 +1 1 +.names 42846 42817 42875 +1- 1 +-1 1 +.names 42872 42828 42876 +1- 1 +-1 1 +.names 42846 42849 42877 +1- 1 +-1 1 +.names 42877 42817 42878 +1- 1 +-1 1 +.names 42845 42879 +0 1 +.names 42879 42880 +1 1 +.names 14543 42841 42881 +1- 1 +-1 1 +.names 14547 42825 42882 +1- 1 +-1 1 +.names 42874 42883 +0 1 +.names 42846 42849 42884 +1- 1 +-1 1 +.names 42862 42885 +0 1 +.names 42885 42886 +1 1 +.names 42886 42887 +0 1 +.names 14599 42887 42888 +11 1 +.names 42856 42889 +0 1 +.names 42889 42890 +1 1 +.names 42890 42891 +0 1 +.names 14571 42891 42892 +11 1 +.names 42813 42893 +0 1 +.names 42893 42894 +1 1 +.names 42894 42895 +0 1 +.names 14599 42895 42896 +11 1 +.names 42852 42897 +0 1 +.names 42897 42898 +1 1 +.names 42898 42899 +0 1 +.names 14571 42899 42900 +11 1 +.names 42865 42901 +0 1 +.names 42901 42902 +1 1 +.names 42869 42903 +0 1 +.names 42903 42904 +1 1 +.names 42904 42905 +0 1 +.names 14599 42905 42906 +11 1 +.names 42902 42907 +0 1 +.names 14571 42907 42908 +11 1 +.names 42848 42909 +0 1 +.names 42909 42910 +1 1 +.names 42880 42911 +0 1 +.names 42911 42912 +1 1 +.names 42912 42913 +0 1 +.names 14599 42913 42914 +11 1 +.names 42910 42915 +0 1 +.names 14571 42915 42916 +11 1 +.names 14474 14478 42917 +1- 1 +-1 1 +.names 42917 42918 +1 1 +.names 14694 14605 42919 +11 1 +.names 42919 42920 +1 1 +.names 42925 42928 42921 +1- 1 +-1 1 +.names 42921 42922 +1 1 +.names 14654 14595 42923 +11 1 +.names 42923 42924 +1 1 +.names 42924 42925 +0 1 +.names 14498 14502 42926 +11 1 +.names 42926 42927 +1 1 +.names 42927 42928 +0 1 +.names 42934 42937 42929 +11 1 +.names 42929 42930 +1 1 +.names 14510 14514 42931 +1- 1 +-1 1 +.names 42931 42932 +1 1 +.names 42932 42933 +0 1 +.names 42933 42928 42934 +1- 1 +-1 1 +.names 14650 14506 42935 +1- 1 +-1 1 +.names 42935 42936 +1 1 +.names 42936 42937 +0 1 +.names 40669 42938 +0 1 +.names 42031 42939 +0 1 +.names 40820 42940 +0 1 +.names 42099 42941 +0 1 +.names 40589 42942 +0 1 +.names 42004 42943 +0 1 +.names 42947 42944 +0 1 +.names 42944 42945 +1 1 +.names 43148 42946 +0 1 +.names 42946 42947 +1 1 +.names 14463 42948 +0 1 +.names 42982 42949 +0 1 +.names 42949 42950 +1 1 +.names 42950 42951 +0 1 +.names 42948 42951 42952 +11 1 +.names 42980 42953 +0 1 +.names 42953 42954 +1 1 +.names 42954 42955 +0 1 +.names 14463 42955 42956 +11 1 +.names 42990 42957 +0 1 +.names 42957 42958 +1 1 +.names 42958 42959 +0 1 +.names 42948 42959 42960 +11 1 +.names 42988 42961 +0 1 +.names 42961 42962 +1 1 +.names 42962 42963 +0 1 +.names 14463 42963 42964 +11 1 +.names 42945 42965 +0 1 +.names 42948 42965 42966 +11 1 +.names 42992 42967 +0 1 +.names 42967 42968 +1 1 +.names 42968 42969 +0 1 +.names 14463 42969 42970 +11 1 +.names 42986 42971 +0 1 +.names 42971 42972 +1 1 +.names 42972 42973 +0 1 +.names 42948 42973 42974 +11 1 +.names 42984 42975 +0 1 +.names 42975 42976 +1 1 +.names 42976 42977 +0 1 +.names 14463 42977 42978 +11 1 +.names 43177 43145 42979 +01 1 +10 1 +.names 42979 42980 +1 1 +.names 43169 42981 +0 1 +.names 42981 42982 +1 1 +.names 43166 43168 42983 +01 1 +10 1 +.names 42983 42984 +1 1 +.names 43180 42985 +0 1 +.names 42985 42986 +1 1 +.names 43164 43132 42987 +01 1 +10 1 +.names 42987 42988 +1 1 +.names 43181 42989 +0 1 +.names 42989 42990 +1 1 +.names 43162 43148 42991 +01 1 +10 1 +.names 42991 42992 +1 1 +.names 41306 42993 +0 1 +.names 42162 42994 +0 1 +.names 14710 14542 42995 +1- 1 +-1 1 +.names 42995 42996 +1 1 +.names 14726 14575 42997 +11 1 +.names 42997 42998 +1 1 +.names 40373 42999 +0 1 +.names 41952 43000 +0 1 +.names 40697 43001 +0 1 +.names 42054 43002 +0 1 +.names 43663 43664 43003 +1- 1 +-1 1 +.names 43003 43004 +1 1 +.names 43004 43005 +0 1 +.names 43666 43667 43006 +11 1 +.names 43006 43007 +1 1 +.names 43007 43008 +0 1 +.names 43008 42775 43009 +11 1 +.names 40622 43010 +0 1 +.names 42024 43011 +0 1 +.names 41363 43012 +0 1 +.names 42179 43013 +0 1 +.names 14734 14742 43014 +11 1 +.names 43014 43015 +1 1 +.names 14666 14662 43016 +1- 1 +-1 1 +.names 43016 43017 +1 1 +.names 43227 43228 43018 +1- 1 +-1 1 +.names 43018 43019 +1 1 +.names 43019 43020 +0 1 +.names 42798 43020 43021 +11 1 +.names 43230 43231 43022 +11 1 +.names 43022 43023 +1 1 +.names 43023 43024 +0 1 +.names 43028 43025 +0 1 +.names 43025 43026 +1 1 +.names 43301 43027 +0 1 +.names 43027 43028 +1 1 +.names 14584 43029 +0 1 +.names 43026 43030 +0 1 +.names 43029 43030 43031 +11 1 +.names 43073 43032 +0 1 +.names 43032 43033 +1 1 +.names 43033 43034 +0 1 +.names 14584 43034 43035 +11 1 +.names 43071 43036 +0 1 +.names 43036 43037 +1 1 +.names 43037 43038 +0 1 +.names 43029 43038 43039 +11 1 +.names 43069 43040 +0 1 +.names 43040 43041 +1 1 +.names 43041 43042 +0 1 +.names 14584 43042 43043 +11 1 +.names 43067 43044 +0 1 +.names 43044 43045 +1 1 +.names 43045 43046 +0 1 +.names 43029 43046 43047 +11 1 +.names 43065 43048 +0 1 +.names 43048 43049 +1 1 +.names 43049 43050 +0 1 +.names 14584 43050 43051 +11 1 +.names 43063 43052 +0 1 +.names 43052 43053 +1 1 +.names 43053 43054 +0 1 +.names 43029 43054 43055 +11 1 +.names 43061 43056 +0 1 +.names 43056 43057 +1 1 +.names 43057 43058 +0 1 +.names 14584 43058 43059 +11 1 +.names 43307 43280 43060 +01 1 +10 1 +.names 43060 43061 +1 1 +.names 43308 43062 +0 1 +.names 43062 43063 +1 1 +.names 43304 43266 43064 +01 1 +10 1 +.names 43064 43065 +1 1 +.names 43305 43066 +0 1 +.names 43066 43067 +1 1 +.names 43310 43264 43068 +01 1 +10 1 +.names 43068 43069 +1 1 +.names 43312 43070 +0 1 +.names 43070 43071 +1 1 +.names 43302 43301 43072 +01 1 +10 1 +.names 43072 43073 +1 1 +.names 14702 14550 43074 +11 1 +.names 43074 43075 +1 1 +.names 14706 14698 43076 +1- 1 +-1 1 +.names 43076 43077 +1 1 +.names 43236 14591 43078 +1- 1 +-1 1 +.names 43078 43079 +1 1 +.names 43079 43080 +0 1 +.names 14530 14534 43081 +11 1 +.names 43081 43082 +1 1 +.names 43082 43083 +0 1 +.names 43080 43083 43084 +1- 1 +-1 1 +.names 14722 14714 43085 +1- 1 +-1 1 +.names 43085 43086 +1 1 +.names 43086 43087 +0 1 +.names 41897 43088 +0 1 +.names 42475 43089 +0 1 +.names 41839 43090 +0 1 +.names 42462 43091 +0 1 +.names 14538 14617 43092 +11 1 +.names 43092 43093 +1 1 +.names 14546 14718 43094 +1- 1 +-1 1 +.names 43094 43095 +1 1 +.names 42797 43096 +0 1 +.names 43015 43097 +0 1 +.names 42795 43098 +0 1 +.names 43098 43097 43099 +1- 1 +-1 1 +.names 43017 43100 +0 1 +.names 43106 43110 43101 +11 1 +.names 43101 43102 +1 1 +.names 43671 43674 43103 +11 1 +.names 43103 43104 +1 1 +.names 43104 43105 +0 1 +.names 43105 14583 43106 +1- 1 +-1 1 +.names 42498 43670 43107 +1- 1 +-1 1 +.names 43107 43108 +1 1 +.names 43108 43109 +0 1 +.names 43105 43109 43110 +1- 1 +-1 1 +.names 43102 43111 +0 1 +.names 43111 43112 +1 1 +.names 14554 14558 43113 +1- 1 +-1 1 +.names 43113 43114 +1 1 +.names 14613 14609 43115 +11 1 +.names 43115 43116 +1 1 +.names 43119 43120 43117 +1- 1 +-1 1 +.names 43117 43118 +1 1 +.names 14687 43119 +0 1 +.names 14602 43120 +0 1 +.names 43123 43124 43121 +1- 1 +-1 1 +.names 43121 43122 +1 1 +.names 14487 43123 +0 1 +.names 14588 43124 +0 1 +.names 43129 43130 43125 +1- 1 +-1 1 +.names 43125 43126 +1 1 +.names 14483 43127 +0 1 +.names 43127 43128 +1 1 +.names 43128 43129 +0 1 +.names 43122 43130 +0 1 +.names 14483 43124 43131 +1- 1 +-1 1 +.names 43131 43132 +1 1 +.names 14679 43135 43133 +1- 1 +-1 1 +.names 43133 43134 +1 1 +.names 14731 43135 +0 1 +.names 43140 43143 43136 +1- 1 +-1 1 +.names 43136 43137 +1 1 +.names 43183 43158 43138 +11 1 +.names 43138 43139 +1 1 +.names 43139 43140 +0 1 +.names 43182 43124 43141 +1- 1 +-1 1 +.names 43141 43142 +1 1 +.names 43142 43143 +0 1 +.names 14683 43146 43144 +1- 1 +-1 1 +.names 43144 43145 +1 1 +.names 14671 43146 +0 1 +.names 14487 43119 43147 +1- 1 +-1 1 +.names 43147 43148 +1 1 +.names 43157 43160 43149 +1- 1 +-1 1 +.names 43149 43150 +1 1 +.names 43127 43124 43151 +11 1 +.names 43151 43152 +1 1 +.names 43152 43153 +0 1 +.names 43161 43135 43154 +1- 1 +-1 1 +.names 43154 43155 +1 1 +.names 43155 43156 +0 1 +.names 43153 43156 43157 +11 1 +.names 14679 43158 +0 1 +.names 43158 43159 +1 1 +.names 43159 43160 +0 1 +.names 43127 43123 43161 +11 1 +.names 43120 43162 +1 1 +.names 43189 43123 43163 +11 1 +.names 43163 43164 +1 1 +.names 43134 43165 +0 1 +.names 43165 43166 +1 1 +.names 43187 43188 43167 +1- 1 +-1 1 +.names 43167 43168 +1 1 +.names 43145 43137 43169 +01 1 +10 1 +.names 43174 43175 43170 +11 1 +.names 43170 43171 +1 1 +.names 43124 43135 43172 +1- 1 +-1 1 +.names 43172 43173 +1 1 +.names 43173 43174 +0 1 +.names 43118 43175 +0 1 +.names 43178 43179 43176 +11 1 +.names 43176 43177 +1 1 +.names 43171 43178 +0 1 +.names 43150 43179 +0 1 +.names 43126 43134 43180 +01 1 +10 1 +.names 43132 14487 43181 +01 1 +10 1 +.names 43123 43135 43182 +1- 1 +-1 1 +.names 43127 43135 43183 +1- 1 +-1 1 +.names 43186 43124 43184 +1- 1 +-1 1 +.names 43184 43185 +1 1 +.names 43120 43119 43186 +1- 1 +-1 1 +.names 14483 43130 43187 +1- 1 +-1 1 +.names 43185 43188 +0 1 +.names 43119 43120 43189 +1- 1 +-1 1 +.names 43020 43005 43190 +11 1 +.names 43190 43191 +1 1 +.names 43191 43192 +0 1 +.names 14579 43192 43193 +1- 1 +-1 1 +.names 43683 43194 +0 1 +.names 43194 43195 +1 1 +.names 43195 43196 +0 1 +.names 41803 43197 +0 1 +.names 42445 43198 +0 1 +.names 41024 43199 +0 1 +.names 42191 43200 +0 1 +.names 41561 43201 +0 1 +.names 42376 43202 +0 1 +.names 43205 43192 43203 +1- 1 +-1 1 +.names 43203 43204 +1 1 +.names 42776 43205 +0 1 +.names 43208 43209 43206 +11 1 +.names 43206 43207 +1 1 +.names 43196 43205 43208 +1- 1 +-1 1 +.names 42778 43209 +0 1 +.names 40778 43210 +0 1 +.names 42068 43211 +0 1 +.names 14567 43212 +1 1 +.names 14564 43213 +1 1 +.names 43216 14567 43214 +11 1 +.names 43214 43215 +1 1 +.names 3663 43216 +0 1 +.names 43216 14564 43217 +11 1 +.names 43217 43218 +1 1 +.names 43221 43222 43219 +11 1 +.names 43219 43220 +1 1 +.names 43215 43221 +0 1 +.names 43218 43222 +0 1 +.names 43225 43226 43223 +1- 1 +-1 1 +.names 43223 43224 +1 1 +.names 43212 43213 43225 +11 1 +.names 43220 43226 +0 1 +.names 43116 43227 +0 1 +.names 43075 43228 +0 1 +.names 43114 43229 +0 1 +.names 43229 43228 43230 +1- 1 +-1 1 +.names 43077 43231 +0 1 +.names 14690 14470 43232 +1- 1 +-1 1 +.names 43232 43233 +1 1 +.names 14466 14738 43234 +11 1 +.names 43234 43235 +1 1 +.names 43224 43236 +0 1 +.names 43240 43241 43237 +1- 1 +-1 1 +.names 14600 43238 +0 1 +.names 42504 43239 +0 1 +.names 43238 43239 43240 +11 1 +.names 42492 43241 +0 1 +.names 41623 43242 +0 1 +.names 42393 43243 +0 1 +.names 42998 43244 +0 1 +.names 43244 43245 +1 1 +.names 43093 43246 +0 1 +.names 42996 43247 +0 1 +.names 43247 43248 +1 1 +.names 43251 43252 43249 +1- 1 +-1 1 +.names 43249 43250 +1 1 +.names 43095 42998 43251 +11 1 +.names 43248 43252 +0 1 +.names 43258 43259 43253 +1- 1 +-1 1 +.names 43253 43254 +1 1 +.names 14695 43255 +0 1 +.names 43255 42680 43256 +1- 1 +-1 1 +.names 14739 43257 +0 1 +.names 43256 43257 43258 +1- 1 +-1 1 +.names 14467 43259 +0 1 +.names 43262 43257 43260 +1- 1 +-1 1 +.names 43260 43261 +1 1 +.names 14479 43262 +0 1 +.names 14475 43257 43263 +1- 1 +-1 1 +.names 43263 43264 +1 1 +.names 43268 43271 43265 +1- 1 +-1 1 +.names 43265 43266 +1 1 +.names 43261 43267 +0 1 +.names 14475 43267 43268 +1- 1 +-1 1 +.names 43317 42680 43269 +1- 1 +-1 1 +.names 43269 43270 +1 1 +.names 43270 43271 +0 1 +.names 43276 43267 43272 +1- 1 +-1 1 +.names 43272 43273 +1 1 +.names 14475 43274 +0 1 +.names 43274 43275 +1 1 +.names 43275 43276 +0 1 +.names 14471 43259 43277 +1- 1 +-1 1 +.names 43277 43278 +1 1 +.names 43286 43289 43279 +1- 1 +-1 1 +.names 43279 43280 +1 1 +.names 43254 43281 +0 1 +.names 14471 43281 43282 +1- 1 +-1 1 +.names 43274 43259 43283 +1- 1 +-1 1 +.names 43283 43284 +1 1 +.names 43284 43285 +0 1 +.names 43282 43285 43286 +1- 1 +-1 1 +.names 43316 43262 43287 +1- 1 +-1 1 +.names 43287 43288 +1 1 +.names 43288 43289 +0 1 +.names 43294 43297 43290 +1- 1 +-1 1 +.names 43290 43291 +1 1 +.names 43314 43315 43292 +11 1 +.names 43292 43293 +1 1 +.names 43293 43294 +0 1 +.names 43313 43262 43295 +1- 1 +-1 1 +.names 43295 43296 +1 1 +.names 43296 43297 +0 1 +.names 14691 43120 43298 +1- 1 +-1 1 +.names 43298 43299 +1 1 +.names 14479 43255 43300 +1- 1 +-1 1 +.names 43300 43301 +1 1 +.names 42680 43302 +1 1 +.names 43278 43303 +0 1 +.names 43303 43304 +1 1 +.names 43278 43273 43305 +01 1 +10 1 +.names 43299 43306 +0 1 +.names 43306 43307 +1 1 +.names 43299 43291 43308 +01 1 +10 1 +.names 43311 43262 43309 +11 1 +.names 43309 43310 +1 1 +.names 43255 42680 43311 +1- 1 +-1 1 +.names 43264 14479 43312 +01 1 +10 1 +.names 43257 43259 43313 +1- 1 +-1 1 +.names 43274 43259 43314 +1- 1 +-1 1 +.names 14471 43315 +0 1 +.names 43257 43259 43316 +1- 1 +-1 1 +.names 43255 43257 43317 +1- 1 +-1 1 +.names 41608 43318 +0 1 +.names 42358 43319 +0 1 +.names 41381 43320 +0 1 +.names 42306 43321 +0 1 +.names 43324 43325 43322 +1- 1 +-1 1 +.names 43322 43323 +1 1 +.names 14592 43324 +0 1 +.names 14531 43325 +0 1 +.names 43329 43330 43326 +1- 1 +-1 1 +.names 43326 43327 +1 1 +.names 14535 43328 +0 1 +.names 14886 43328 43329 +1- 1 +-1 1 +.names 14623 43330 +0 1 +.names 14592 43328 43331 +1- 1 +-1 1 +.names 43331 43332 +1 1 +.names 43336 43339 43333 +1- 1 +-1 1 +.names 43333 43334 +1 1 +.names 43324 43335 +1 1 +.names 43335 43336 +0 1 +.names 43384 43328 43337 +1- 1 +-1 1 +.names 43337 43338 +1 1 +.names 43338 43339 +0 1 +.names 14715 43325 43340 +1- 1 +-1 1 +.names 43340 43341 +1 1 +.names 43351 43352 43342 +1- 1 +-1 1 +.names 43342 43343 +1 1 +.names 43394 43325 43344 +1- 1 +-1 1 +.names 43344 43345 +1 1 +.names 43345 43346 +0 1 +.names 14715 43346 43347 +1- 1 +-1 1 +.names 43392 43384 43348 +1- 1 +-1 1 +.names 43348 43349 +1 1 +.names 43349 43350 +0 1 +.names 43347 43350 43351 +1- 1 +-1 1 +.names 43323 43352 +0 1 +.names 43355 43358 43353 +1- 1 +-1 1 +.names 43353 43354 +1 1 +.names 14715 43352 43355 +1- 1 +-1 1 +.names 43395 43384 43356 +1- 1 +-1 1 +.names 43356 43357 +1 1 +.names 43357 43358 +0 1 +.names 14723 42849 43359 +1- 1 +-1 1 +.names 43359 43360 +1 1 +.names 14621 43330 43361 +1- 1 +-1 1 +.names 43361 43362 +1 1 +.names 43365 43362 43363 +01 1 +10 1 +.names 43363 43364 +1 1 +.names 14886 43365 +1 1 +.names 43369 43371 43366 +01 1 +10 1 +.names 43366 43367 +1 1 +.names 43341 43368 +0 1 +.names 43368 43369 +1 1 +.names 43396 43397 43370 +1- 1 +-1 1 +.names 43370 43371 +1 1 +.names 43374 43372 +0 1 +.names 43372 43373 +1 1 +.names 43341 43334 43374 +01 1 +10 1 +.names 43378 43343 43375 +01 1 +10 1 +.names 43375 43376 +1 1 +.names 43360 43377 +0 1 +.names 43377 43378 +1 1 +.names 43378 43354 43379 +01 1 +10 1 +.names 43379 43380 +1 1 +.names 43383 43384 43381 +11 1 +.names 43381 43382 +1 1 +.names 43330 14886 43383 +1- 1 +-1 1 +.names 14621 43384 +0 1 +.names 43382 43332 43385 +01 1 +10 1 +.names 43385 43386 +1 1 +.names 43389 43387 +0 1 +.names 43387 43388 +1 1 +.names 43332 14621 43389 +01 1 +10 1 +.names 43362 43390 +0 1 +.names 43390 43391 +1 1 +.names 43328 43325 43392 +1- 1 +-1 1 +.names 43330 14886 43393 +1- 1 +-1 1 +.names 43393 43328 43394 +1- 1 +-1 1 +.names 43328 43325 43395 +1- 1 +-1 1 +.names 14592 43339 43396 +1- 1 +-1 1 +.names 43327 43397 +0 1 +.names 14574 43398 +0 1 +.names 43398 43399 +1 1 +.names 43399 43400 +0 1 +.names 43400 43376 43401 +11 1 +.names 43399 43380 43402 +11 1 +.names 43367 43403 +0 1 +.names 43403 43404 +1 1 +.names 43373 43405 +0 1 +.names 43405 43406 +1 1 +.names 43406 43407 +0 1 +.names 43398 43407 43408 +11 1 +.names 43404 43409 +0 1 +.names 14574 43409 43410 +11 1 +.names 43386 43411 +0 1 +.names 43411 43412 +1 1 +.names 43388 43413 +0 1 +.names 43413 43414 +1 1 +.names 43414 43415 +0 1 +.names 43398 43415 43416 +11 1 +.names 43412 43417 +0 1 +.names 14574 43417 43418 +11 1 +.names 43364 43419 +0 1 +.names 43419 43420 +1 1 +.names 43391 43421 +0 1 +.names 43421 43422 +1 1 +.names 43422 43423 +0 1 +.names 43398 43423 43424 +11 1 +.names 43420 43425 +0 1 +.names 14574 43425 43426 +11 1 +.names 43429 43430 43427 +1- 1 +-1 1 +.names 43427 43428 +1 1 +.names 14527 43429 +0 1 +.names 14631 43430 +0 1 +.names 43435 43436 43431 +1- 1 +-1 1 +.names 43431 43432 +1 1 +.names 14523 43433 +0 1 +.names 43433 43434 +1 1 +.names 43434 43435 +0 1 +.names 43428 43436 +0 1 +.names 14527 43459 43437 +1- 1 +-1 1 +.names 43437 43438 +1 1 +.names 43441 43444 43439 +1- 1 +-1 1 +.names 43439 43440 +1 1 +.names 14523 43436 43441 +1- 1 +-1 1 +.names 43497 43430 43442 +1- 1 +-1 1 +.names 43442 43443 +1 1 +.names 43443 43444 +0 1 +.names 14639 43447 43445 +1- 1 +-1 1 +.names 43445 43446 +1 1 +.names 14519 43447 +0 1 +.names 43452 43455 43448 +1- 1 +-1 1 +.names 43448 43449 +1 1 +.names 43496 43469 43450 +11 1 +.names 43450 43451 +1 1 +.names 43451 43452 +0 1 +.names 43495 43430 43453 +1- 1 +-1 1 +.names 43453 43454 +1 1 +.names 43454 43455 +0 1 +.names 14635 43458 43456 +1- 1 +-1 1 +.names 43456 43457 +1 1 +.names 14627 43458 +0 1 +.names 14643 43459 +0 1 +.names 43468 43471 43460 +1- 1 +-1 1 +.names 43460 43461 +1 1 +.names 43433 43430 43462 +11 1 +.names 43462 43463 +1 1 +.names 43463 43464 +0 1 +.names 43472 43447 43465 +1- 1 +-1 1 +.names 43465 43466 +1 1 +.names 43466 43467 +0 1 +.names 43464 43467 43468 +11 1 +.names 14639 43469 +0 1 +.names 43469 43470 +1 1 +.names 43470 43471 +0 1 +.names 43433 43429 43472 +11 1 +.names 43446 43473 +0 1 +.names 43473 43474 +1 1 +.names 43457 43449 43475 +01 1 +10 1 +.names 43480 43483 43476 +11 1 +.names 43476 43477 +1 1 +.names 43430 43447 43478 +1- 1 +-1 1 +.names 43478 43479 +1 1 +.names 43479 43480 +0 1 +.names 43459 42607 43481 +1- 1 +-1 1 +.names 43481 43482 +1 1 +.names 43482 43483 +0 1 +.names 43486 43487 43484 +11 1 +.names 43484 43485 +1 1 +.names 43477 43486 +0 1 +.names 43461 43487 +0 1 +.names 43432 43446 43488 +01 1 +10 1 +.names 43498 43429 43489 +11 1 +.names 43489 43490 +1 1 +.names 14523 43430 43491 +1- 1 +-1 1 +.names 43491 43492 +1 1 +.names 43492 14527 43493 +01 1 +10 1 +.names 43438 14647 43494 +01 1 +10 1 +.names 43429 43447 43495 +1- 1 +-1 1 +.names 43433 43447 43496 +1- 1 +-1 1 +.names 42607 43459 43497 +1- 1 +-1 1 +.names 43459 42607 43498 +1- 1 +-1 1 +.names 40423 43499 +0 1 +.names 41920 43500 +0 1 +.names 14599 42507 43501 +1- 1 +-1 1 +.names 41516 43502 +0 1 +.names 42340 43503 +0 1 +.names 42288 43504 +0 1 +.names 41274 43505 +0 1 +.names 40498 43506 +0 1 +.names 41985 43507 +0 1 +.names 43512 43513 43508 +1- 1 +-1 1 +.names 43508 43509 +1 1 +.names 14580 43510 +0 1 +.names 43204 43511 +0 1 +.names 43510 43511 43512 +11 1 +.names 43207 43513 +0 1 +.names 43509 43514 +1 1 +.names 43517 43146 43515 +1- 1 +-1 1 +.names 43515 43516 +1 1 +.names 14675 43517 +0 1 +.names 43520 43521 43518 +1- 1 +-1 1 +.names 43518 43519 +1 1 +.names 14495 43520 +0 1 +.names 14659 43521 +0 1 +.names 43526 43527 43522 +1- 1 +-1 1 +.names 43522 43523 +1 1 +.names 14491 43524 +0 1 +.names 43524 43525 +1 1 +.names 43525 43526 +0 1 +.names 43519 43527 +0 1 +.names 14491 43521 43528 +1- 1 +-1 1 +.names 43528 43529 +1 1 +.names 14663 43532 43530 +1- 1 +-1 1 +.names 43530 43531 +1 1 +.names 14735 43532 +0 1 +.names 43537 43540 43533 +1- 1 +-1 1 +.names 43533 43534 +1 1 +.names 43575 43554 43535 +11 1 +.names 43535 43536 +1 1 +.names 43536 43537 +0 1 +.names 43574 43521 43538 +1- 1 +-1 1 +.names 43538 43539 +1 1 +.names 43539 43540 +0 1 +.names 14667 42573 43541 +1- 1 +-1 1 +.names 43541 43542 +1 1 +.names 14495 43517 43543 +1- 1 +-1 1 +.names 43543 43544 +1 1 +.names 43553 43556 43545 +1- 1 +-1 1 +.names 43545 43546 +1 1 +.names 43521 43524 43547 +11 1 +.names 43547 43548 +1 1 +.names 43548 43549 +0 1 +.names 43557 43532 43550 +1- 1 +-1 1 +.names 43550 43551 +1 1 +.names 43551 43552 +0 1 +.names 43549 43552 43553 +11 1 +.names 14663 43554 +0 1 +.names 43554 43555 +1 1 +.names 43555 43556 +0 1 +.names 43520 43524 43557 +11 1 +.names 43146 43558 +1 1 +.names 43585 43520 43559 +11 1 +.names 43559 43560 +1 1 +.names 43531 43561 +0 1 +.names 43561 43562 +1 1 +.names 43583 43584 43563 +1- 1 +-1 1 +.names 43563 43564 +1 1 +.names 43542 43534 43565 +01 1 +10 1 +.names 43570 43571 43566 +11 1 +.names 43566 43567 +1 1 +.names 43578 43579 43568 +11 1 +.names 43568 43569 +1 1 +.names 43569 43570 +0 1 +.names 43546 43571 +0 1 +.names 43523 43531 43572 +01 1 +10 1 +.names 43529 14495 43573 +01 1 +10 1 +.names 43520 43532 43574 +1- 1 +-1 1 +.names 43524 43532 43575 +1- 1 +-1 1 +.names 43521 43532 43576 +1- 1 +-1 1 +.names 43576 43577 +1 1 +.names 43577 43578 +0 1 +.names 43516 43579 +0 1 +.names 43582 43521 43580 +1- 1 +-1 1 +.names 43580 43581 +1 1 +.names 43146 43517 43582 +1- 1 +-1 1 +.names 14491 43527 43583 +1- 1 +-1 1 +.names 43581 43584 +0 1 +.names 43517 43146 43585 +1- 1 +-1 1 +.names 42637 43586 +0 1 +.names 43586 43587 +1 1 +.names 42622 43588 +0 1 +.names 43588 43589 +1 1 +.names 43514 43590 +0 1 +.names 43587 43591 +0 1 +.names 43590 43591 43592 +11 1 +.names 42634 43593 +0 1 +.names 43593 43594 +1 1 +.names 43594 43595 +0 1 +.names 43514 43595 43596 +11 1 +.names 42631 43597 +0 1 +.names 43597 43598 +1 1 +.names 43598 43599 +0 1 +.names 43590 43599 43600 +11 1 +.names 42629 43601 +0 1 +.names 43601 43602 +1 1 +.names 43602 43603 +0 1 +.names 43514 43603 43604 +11 1 +.names 42615 43605 +0 1 +.names 43605 43606 +1 1 +.names 43606 43607 +0 1 +.names 43590 43607 43608 +11 1 +.names 42611 43609 +0 1 +.names 43609 43610 +1 1 +.names 43610 43611 +0 1 +.names 43514 43611 43612 +11 1 +.names 43589 43613 +0 1 +.names 43590 43613 43614 +11 1 +.names 42618 43615 +0 1 +.names 43615 43616 +1 1 +.names 43616 43617 +0 1 +.names 43514 43617 43618 +11 1 +.names 42687 43619 +0 1 +.names 43619 43620 +1 1 +.names 42702 43621 +0 1 +.names 43621 43622 +1 1 +.names 43622 43623 +0 1 +.names 14579 43623 43624 +11 1 +.names 43620 43625 +0 1 +.names 14582 43625 43626 +11 1 +.names 42709 43627 +0 1 +.names 43627 43628 +1 1 +.names 43628 43629 +0 1 +.names 14579 43629 43630 +11 1 +.names 42705 43631 +0 1 +.names 43631 43632 +1 1 +.names 43632 43633 +0 1 +.names 14582 43633 43634 +11 1 +.names 42712 43635 +0 1 +.names 43635 43636 +1 1 +.names 43636 43637 +0 1 +.names 14579 43637 43638 +11 1 +.names 42684 43639 +0 1 +.names 43639 43640 +1 1 +.names 43640 43641 +0 1 +.names 14582 43641 43642 +11 1 +.names 14579 43643 +1 1 +.names 43643 43644 +0 1 +.names 43644 42691 43645 +11 1 +.names 43643 42695 43646 +11 1 +.names 14730 14587 43647 +11 1 +.names 43647 43648 +1 1 +.names 43648 43649 +0 1 +.names 14686 14601 43650 +11 1 +.names 43650 43651 +1 1 +.names 43651 43652 +0 1 +.names 43656 43653 +0 1 +.names 43653 43654 +1 1 +.names 14682 14678 43655 +1- 1 +-1 1 +.names 43655 43656 +1 1 +.names 43661 43662 43657 +1- 1 +-1 1 +.names 43657 43658 +1 1 +.names 14482 14486 43659 +1- 1 +-1 1 +.names 43659 43660 +1 1 +.names 43660 43648 43661 +11 1 +.names 43654 43662 +0 1 +.names 42920 43663 +0 1 +.names 43235 43664 +0 1 +.names 42918 43665 +0 1 +.names 43665 43664 43666 +1- 1 +-1 1 +.names 43233 43667 +0 1 +.names 42772 43684 43668 +11 1 +.names 43668 43669 +1 1 +.names 43669 43670 +0 1 +.names 42502 43670 43671 +1- 1 +-1 1 +.names 43685 43686 43672 +1- 1 +-1 1 +.names 43672 43673 +1 1 +.names 43673 43674 +0 1 +.names 41470 43675 +0 1 +.names 42318 43676 +0 1 +.names 40452 43677 +0 1 +.names 41938 43678 +0 1 +.names 43681 43008 43679 +1- 1 +-1 1 +.names 43679 43680 +1 1 +.names 43005 43024 43681 +11 1 +.names 43680 43682 +0 1 +.names 43682 43683 +1 1 +.names 42922 43684 +0 1 +.names 43684 42785 43685 +11 1 +.names 42930 43686 +0 1 +.names 43693 43694 43687 +1- 1 +-1 1 +.names 43687 43688 +1 1 +.names 8470 43689 +0 1 +.names 43695 43698 43690 +11 1 +.names 43690 43691 +1 1 +.names 43691 43692 +0 1 +.names 43689 43692 43693 +11 1 +.names 8470 27501 43694 +11 1 +.names 8471 43695 +0 1 +.names 56668 43696 +0 1 +.names 43696 43697 +1 1 +.names 43697 43698 +0 1 +.names 43705 43706 56735 +1- 1 +-1 1 +.names 74 43700 +0 1 +.names 43700 43701 +1 1 +.names 43701 43702 +0 1 +.names 43695 43703 +1 1 +.names 43703 43704 +0 1 +.names 43702 43704 43705 +11 1 +.names 43688 43706 +0 1 +.names 43713 43714 43707 +1- 1 +-1 1 +.names 43707 43708 +1 1 +.names 8458 43709 +0 1 +.names 43695 43717 43710 +11 1 +.names 43710 43711 +1 1 +.names 43711 43712 +0 1 +.names 43709 43712 43713 +11 1 +.names 8458 27461 43714 +11 1 +.names 56673 43715 +0 1 +.names 43715 43716 +1 1 +.names 43716 43717 +0 1 +.names 43724 43725 56740 +1- 1 +-1 1 +.names 79 43719 +0 1 +.names 43719 43720 +1 1 +.names 43720 43721 +0 1 +.names 43695 43722 +1 1 +.names 43722 43723 +0 1 +.names 43721 43723 43724 +11 1 +.names 43708 43725 +0 1 +.names 8465 43726 +0 1 +.names 43726 43727 +1 1 +.names 43726 43732 43728 +11 1 +.names 43728 43729 +1 1 +.names 56689 43730 +0 1 +.names 43730 43731 +1 1 +.names 43731 43732 +0 1 +.names 43736 43737 43733 +1- 1 +-1 1 +.names 43733 43734 +1 1 +.names 43729 43735 +0 1 +.names 43709 43735 43736 +11 1 +.names 8458 27469 43737 +11 1 +.names 95 43738 +0 1 +.names 43738 43739 +1 1 +.names 43743 43744 56756 +1- 1 +-1 1 +.names 43727 43741 +0 1 +.names 43739 43742 +0 1 +.names 43741 43742 43743 +11 1 +.names 43734 43744 +0 1 +.names 43726 43745 +1 1 +.names 43726 43750 43746 +11 1 +.names 43746 43747 +1 1 +.names 56675 43748 +0 1 +.names 43748 43749 +1 1 +.names 43749 43750 +0 1 +.names 43754 43755 43751 +1- 1 +-1 1 +.names 43751 43752 +1 1 +.names 43747 43753 +0 1 +.names 43689 43753 43754 +11 1 +.names 8470 27508 43755 +11 1 +.names 43761 43762 56742 +1- 1 +-1 1 +.names 43745 43757 +0 1 +.names 81 43758 +0 1 +.names 43758 43759 +1 1 +.names 43759 43760 +0 1 +.names 43757 43760 43761 +11 1 +.names 43752 43762 +0 1 +.names 43768 43769 43763 +1- 1 +-1 1 +.names 43763 43764 +1 1 +.names 43770 43773 43765 +11 1 +.names 43765 43766 +1 1 +.names 43766 43767 +0 1 +.names 43689 43767 43768 +11 1 +.names 8470 27515 43769 +11 1 +.names 8463 43770 +0 1 +.names 56677 43771 +0 1 +.names 43771 43772 +1 1 +.names 43772 43773 +0 1 +.names 43780 43781 56744 +1- 1 +-1 1 +.names 83 43775 +0 1 +.names 43775 43776 +1 1 +.names 43776 43777 +0 1 +.names 43770 43778 +1 1 +.names 43778 43779 +0 1 +.names 43777 43779 43780 +11 1 +.names 43764 43781 +0 1 +.names 43787 43788 43782 +1- 1 +-1 1 +.names 43782 43783 +1 1 +.names 43789 43792 43784 +11 1 +.names 43784 43785 +1 1 +.names 43785 43786 +0 1 +.names 43689 43786 43787 +11 1 +.names 8470 27476 43788 +11 1 +.names 8466 43789 +0 1 +.names 56684 43790 +0 1 +.names 43790 43791 +1 1 +.names 43791 43792 +0 1 +.names 43799 43800 56751 +1- 1 +-1 1 +.names 90 43794 +0 1 +.names 43794 43795 +1 1 +.names 43795 43796 +0 1 +.names 43789 43797 +1 1 +.names 43797 43798 +0 1 +.names 43796 43798 43799 +11 1 +.names 43783 43800 +0 1 +.names 43807 43808 43801 +1- 1 +-1 1 +.names 43801 43802 +1 1 +.names 8469 43803 +0 1 +.names 43770 43811 43804 +11 1 +.names 43804 43805 +1 1 +.names 43805 43806 +0 1 +.names 43803 43806 43807 +11 1 +.names 8469 27484 43808 +11 1 +.names 56697 43809 +0 1 +.names 43809 43810 +1 1 +.names 43810 43811 +0 1 +.names 43818 43819 56764 +1- 1 +-1 1 +.names 103 43813 +0 1 +.names 43813 43814 +1 1 +.names 43814 43815 +0 1 +.names 43770 43816 +1 1 +.names 43816 43817 +0 1 +.names 43815 43817 43818 +11 1 +.names 43802 43819 +0 1 +.names 43825 43826 43820 +1- 1 +-1 1 +.names 43820 43821 +1 1 +.names 43789 43829 43822 +11 1 +.names 43822 43823 +1 1 +.names 43823 43824 +0 1 +.names 43709 43824 43825 +11 1 +.names 8458 27522 43826 +11 1 +.names 56686 43827 +0 1 +.names 43827 43828 +1 1 +.names 43828 43829 +0 1 +.names 43836 43837 56753 +1- 1 +-1 1 +.names 92 43831 +0 1 +.names 43831 43832 +1 1 +.names 43832 43833 +0 1 +.names 43789 43834 +1 1 +.names 43834 43835 +0 1 +.names 43833 43835 43836 +11 1 +.names 43821 43837 +0 1 +.names 43843 43844 43838 +1- 1 +-1 1 +.names 43838 43839 +1 1 +.names 43770 43847 43840 +11 1 +.names 43840 43841 +1 1 +.names 43841 43842 +0 1 +.names 43689 43842 43843 +11 1 +.names 8470 27492 43844 +11 1 +.names 56667 43845 +0 1 +.names 43845 43846 +1 1 +.names 43846 43847 +0 1 +.names 43854 43855 56734 +1- 1 +-1 1 +.names 73 43849 +0 1 +.names 43849 43850 +1 1 +.names 43850 43851 +0 1 +.names 43770 43852 +1 1 +.names 43852 43853 +0 1 +.names 43851 43853 43854 +11 1 +.names 43839 43855 +0 1 +.names 43726 43856 +1 1 +.names 43726 43861 43857 +11 1 +.names 43857 43858 +1 1 +.names 56676 43859 +0 1 +.names 43859 43860 +1 1 +.names 43860 43861 +0 1 +.names 43865 43866 43862 +1- 1 +-1 1 +.names 43862 43863 +1 1 +.names 43858 43864 +0 1 +.names 43803 43864 43865 +11 1 +.names 8469 27529 43866 +11 1 +.names 82 43867 +0 1 +.names 43867 43868 +1 1 +.names 43872 43873 56743 +1- 1 +-1 1 +.names 43856 43870 +0 1 +.names 43868 43871 +0 1 +.names 43870 43871 43872 +11 1 +.names 43863 43873 +0 1 +.names 43726 43874 +1 1 +.names 43726 43879 43875 +11 1 +.names 43875 43876 +1 1 +.names 56692 43877 +0 1 +.names 43877 43878 +1 1 +.names 43878 43879 +0 1 +.names 43883 43884 43880 +1- 1 +-1 1 +.names 43880 43881 +1 1 +.names 43876 43882 +0 1 +.names 43709 43882 43883 +11 1 +.names 8458 27537 43884 +11 1 +.names 98 43885 +0 1 +.names 43885 43886 +1 1 +.names 43890 43891 56759 +1- 1 +-1 1 +.names 43874 43888 +0 1 +.names 43886 43889 +0 1 +.names 43888 43889 43890 +11 1 +.names 43881 43891 +0 1 +.names 43897 43898 43892 +1- 1 +-1 1 +.names 43892 43893 +1 1 +.names 43770 43901 43894 +11 1 +.names 43894 43895 +1 1 +.names 43895 43896 +0 1 +.names 43689 43896 43897 +11 1 +.names 8470 27544 43898 +11 1 +.names 56678 43899 +0 1 +.names 43899 43900 +1 1 +.names 43900 43901 +0 1 +.names 43908 43909 56745 +1- 1 +-1 1 +.names 84 43903 +0 1 +.names 43903 43904 +1 1 +.names 43904 43905 +0 1 +.names 43770 43906 +1 1 +.names 43906 43907 +0 1 +.names 43905 43907 43908 +11 1 +.names 43893 43909 +0 1 +.names 43915 43916 43910 +1- 1 +-1 1 +.names 43910 43911 +1 1 +.names 43770 43919 43912 +11 1 +.names 43912 43913 +1 1 +.names 43913 43914 +0 1 +.names 43709 43914 43915 +11 1 +.names 8458 27551 43916 +11 1 +.names 56691 43917 +0 1 +.names 43917 43918 +1 1 +.names 43918 43919 +0 1 +.names 43926 43927 56758 +1- 1 +-1 1 +.names 97 43921 +0 1 +.names 43921 43922 +1 1 +.names 43922 43923 +0 1 +.names 43770 43924 +1 1 +.names 43924 43925 +0 1 +.names 43923 43925 43926 +11 1 +.names 43911 43927 +0 1 +.names 43933 43934 43928 +1- 1 +-1 1 +.names 43928 43929 +1 1 +.names 43770 43937 43930 +11 1 +.names 43930 43931 +1 1 +.names 43931 43932 +0 1 +.names 43709 43932 43933 +11 1 +.names 8458 27572 43934 +11 1 +.names 56674 43935 +0 1 +.names 43935 43936 +1 1 +.names 43936 43937 +0 1 +.names 43944 43945 56741 +1- 1 +-1 1 +.names 80 43939 +0 1 +.names 43939 43940 +1 1 +.names 43940 43941 +0 1 +.names 43770 43942 +1 1 +.names 43942 43943 +0 1 +.names 43941 43943 43944 +11 1 +.names 43929 43945 +0 1 +.names 43951 43952 43946 +1- 1 +-1 1 +.names 43946 43947 +1 1 +.names 43789 43955 43948 +11 1 +.names 43948 43949 +1 1 +.names 43949 43950 +0 1 +.names 43709 43950 43951 +11 1 +.names 8458 27579 43952 +11 1 +.names 56685 43953 +0 1 +.names 43953 43954 +1 1 +.names 43954 43955 +0 1 +.names 43962 43963 56752 +1- 1 +-1 1 +.names 91 43957 +0 1 +.names 43957 43958 +1 1 +.names 43958 43959 +0 1 +.names 43789 43960 +1 1 +.names 43960 43961 +0 1 +.names 43959 43961 43962 +11 1 +.names 43947 43963 +0 1 +.names 43969 43970 43964 +1- 1 +-1 1 +.names 43964 43965 +1 1 +.names 43695 43973 43966 +11 1 +.names 43966 43967 +1 1 +.names 43967 43968 +0 1 +.names 43803 43968 43969 +11 1 +.names 8469 27586 43970 +11 1 +.names 56683 43971 +0 1 +.names 43971 43972 +1 1 +.names 43972 43973 +0 1 +.names 43980 43981 56750 +1- 1 +-1 1 +.names 89 43975 +0 1 +.names 43975 43976 +1 1 +.names 43976 43977 +0 1 +.names 43695 43978 +1 1 +.names 43978 43979 +0 1 +.names 43977 43979 43980 +11 1 +.names 43965 43981 +0 1 +.names 43987 43988 43982 +1- 1 +-1 1 +.names 43982 43983 +1 1 +.names 43770 43991 43984 +11 1 +.names 43984 43985 +1 1 +.names 43985 43986 +0 1 +.names 43803 43986 43987 +11 1 +.names 8469 27593 43988 +11 1 +.names 56690 43989 +0 1 +.names 43989 43990 +1 1 +.names 43990 43991 +0 1 +.names 43998 43999 56757 +1- 1 +-1 1 +.names 43770 43993 +1 1 +.names 43993 43994 +0 1 +.names 96 43995 +0 1 +.names 43995 43996 +1 1 +.names 43996 43997 +0 1 +.names 43994 43997 43998 +11 1 +.names 43983 43999 +0 1 +.names 43726 44000 +1 1 +.names 43726 44005 44001 +11 1 +.names 44001 44002 +1 1 +.names 56698 44003 +0 1 +.names 44003 44004 +1 1 +.names 44004 44005 +0 1 +.names 44009 44010 44006 +1- 1 +-1 1 +.names 44006 44007 +1 1 +.names 44002 44008 +0 1 +.names 43689 44008 44009 +11 1 +.names 8470 27600 44010 +11 1 +.names 104 44011 +0 1 +.names 44011 44012 +1 1 +.names 44016 44017 56765 +1- 1 +-1 1 +.names 44000 44014 +0 1 +.names 44012 44015 +0 1 +.names 44014 44015 44016 +11 1 +.names 44007 44017 +0 1 +.names 44023 44024 44018 +1- 1 +-1 1 +.names 44018 44019 +1 1 +.names 43726 44027 44020 +11 1 +.names 44020 44021 +1 1 +.names 44021 44022 +0 1 +.names 43689 44022 44023 +11 1 +.names 8470 27558 44024 +11 1 +.names 56669 44025 +0 1 +.names 44025 44026 +1 1 +.names 44026 44027 +0 1 +.names 44034 44035 56736 +1- 1 +-1 1 +.names 75 44029 +0 1 +.names 44029 44030 +1 1 +.names 44030 44031 +0 1 +.names 43726 44032 +1 1 +.names 44032 44033 +0 1 +.names 44031 44033 44034 +11 1 +.names 44019 44035 +0 1 +.names 44041 44042 44036 +1- 1 +-1 1 +.names 44036 44037 +1 1 +.names 43789 44045 44038 +11 1 +.names 44038 44039 +1 1 +.names 44039 44040 +0 1 +.names 43803 44040 44041 +11 1 +.names 8469 27565 44042 +11 1 +.names 56672 44043 +0 1 +.names 44043 44044 +1 1 +.names 44044 44045 +0 1 +.names 44052 44053 56739 +1- 1 +-1 1 +.names 78 44047 +0 1 +.names 44047 44048 +1 1 +.names 44048 44049 +0 1 +.names 43789 44050 +1 1 +.names 44050 44051 +0 1 +.names 44049 44051 44052 +11 1 +.names 44037 44053 +0 1 +.names 44059 44060 44054 +1- 1 +-1 1 +.names 44054 44055 +1 1 +.names 43789 44063 44056 +11 1 +.names 44056 44057 +1 1 +.names 44057 44058 +0 1 +.names 43803 44058 44059 +11 1 +.names 8469 27608 44060 +11 1 +.names 56688 44061 +0 1 +.names 44061 44062 +1 1 +.names 44062 44063 +0 1 +.names 44070 44071 56755 +1- 1 +-1 1 +.names 94 44065 +0 1 +.names 44065 44066 +1 1 +.names 44066 44067 +0 1 +.names 43789 44068 +1 1 +.names 44068 44069 +0 1 +.names 44067 44069 44070 +11 1 +.names 44055 44071 +0 1 +.names 44077 44078 44072 +1- 1 +-1 1 +.names 44072 44073 +1 1 +.names 43789 44081 44074 +11 1 +.names 44074 44075 +1 1 +.names 44075 44076 +0 1 +.names 43689 44076 44077 +11 1 +.names 8470 27615 44078 +11 1 +.names 56680 44079 +0 1 +.names 44079 44080 +1 1 +.names 44080 44081 +0 1 +.names 44088 44089 56747 +1- 1 +-1 1 +.names 86 44083 +0 1 +.names 44083 44084 +1 1 +.names 44084 44085 +0 1 +.names 43789 44086 +1 1 +.names 44086 44087 +0 1 +.names 44085 44087 44088 +11 1 +.names 44073 44089 +0 1 +.names 44095 44096 44090 +1- 1 +-1 1 +.names 44090 44091 +1 1 +.names 43726 44099 44092 +11 1 +.names 44092 44093 +1 1 +.names 44093 44094 +0 1 +.names 43709 44094 44095 +11 1 +.names 8458 27622 44096 +11 1 +.names 56681 44097 +0 1 +.names 44097 44098 +1 1 +.names 44098 44099 +0 1 +.names 44106 44107 56748 +1- 1 +-1 1 +.names 43726 44101 +1 1 +.names 44101 44102 +0 1 +.names 87 44103 +0 1 +.names 44103 44104 +1 1 +.names 44104 44105 +0 1 +.names 44102 44105 44106 +11 1 +.names 44091 44107 +0 1 +.names 43726 44108 +1 1 +.names 43726 44113 44109 +11 1 +.names 44109 44110 +1 1 +.names 56695 44111 +0 1 +.names 44111 44112 +1 1 +.names 44112 44113 +0 1 +.names 44117 44118 44114 +1- 1 +-1 1 +.names 44114 44115 +1 1 +.names 44110 44116 +0 1 +.names 43803 44116 44117 +11 1 +.names 8469 27629 44118 +11 1 +.names 101 44119 +0 1 +.names 44119 44120 +1 1 +.names 44124 44125 56762 +1- 1 +-1 1 +.names 44108 44122 +0 1 +.names 44120 44123 +0 1 +.names 44122 44123 44124 +11 1 +.names 44115 44125 +0 1 +.names 44131 44132 44126 +1- 1 +-1 1 +.names 44126 44127 +1 1 +.names 43770 44135 44128 +11 1 +.names 44128 44129 +1 1 +.names 44129 44130 +0 1 +.names 43803 44130 44131 +11 1 +.names 8469 27636 44132 +11 1 +.names 56679 44133 +0 1 +.names 44133 44134 +1 1 +.names 44134 44135 +0 1 +.names 44142 44143 56746 +1- 1 +-1 1 +.names 85 44137 +0 1 +.names 44137 44138 +1 1 +.names 44138 44139 +0 1 +.names 43770 44140 +1 1 +.names 44140 44141 +0 1 +.names 44139 44141 44142 +11 1 +.names 44127 44143 +0 1 +.names 44149 44150 44144 +1- 1 +-1 1 +.names 44144 44145 +1 1 +.names 43789 44153 44146 +11 1 +.names 44146 44147 +1 1 +.names 44147 44148 +0 1 +.names 43803 44148 44149 +11 1 +.names 8469 27643 44150 +11 1 +.names 56693 44151 +0 1 +.names 44151 44152 +1 1 +.names 44152 44153 +0 1 +.names 44160 44161 56760 +1- 1 +-1 1 +.names 99 44155 +0 1 +.names 44155 44156 +1 1 +.names 44156 44157 +0 1 +.names 43789 44158 +1 1 +.names 44158 44159 +0 1 +.names 44157 44159 44160 +11 1 +.names 44145 44161 +0 1 +.names 43726 44162 +1 1 +.names 43726 44167 44163 +11 1 +.names 44163 44164 +1 1 +.names 56694 44165 +0 1 +.names 44165 44166 +1 1 +.names 44166 44167 +0 1 +.names 44171 44172 44168 +1- 1 +-1 1 +.names 44168 44169 +1 1 +.names 44164 44170 +0 1 +.names 43689 44170 44171 +11 1 +.names 8470 27650 44172 +11 1 +.names 100 44173 +0 1 +.names 44173 44174 +1 1 +.names 44178 44179 56761 +1- 1 +-1 1 +.names 44162 44176 +0 1 +.names 44174 44177 +0 1 +.names 44176 44177 44178 +11 1 +.names 44169 44179 +0 1 +.names 44185 44186 44180 +1- 1 +-1 1 +.names 44180 44181 +1 1 +.names 43789 44189 44182 +11 1 +.names 44182 44183 +1 1 +.names 44183 44184 +0 1 +.names 43803 44184 44185 +11 1 +.names 8469 27657 44186 +11 1 +.names 56670 44187 +0 1 +.names 44187 44188 +1 1 +.names 44188 44189 +0 1 +.names 44196 44197 56737 +1- 1 +-1 1 +.names 76 44191 +0 1 +.names 44191 44192 +1 1 +.names 44192 44193 +0 1 +.names 43789 44194 +1 1 +.names 44194 44195 +0 1 +.names 44193 44195 44196 +11 1 +.names 44181 44197 +0 1 +.names 44203 44204 44198 +1- 1 +-1 1 +.names 44198 44199 +1 1 +.names 43789 44207 44200 +11 1 +.names 44200 44201 +1 1 +.names 44201 44202 +0 1 +.names 43709 44202 44203 +11 1 +.names 8458 27664 44204 +11 1 +.names 56671 44205 +0 1 +.names 44205 44206 +1 1 +.names 44206 44207 +0 1 +.names 44214 44215 56738 +1- 1 +-1 1 +.names 77 44209 +0 1 +.names 44209 44210 +1 1 +.names 44210 44211 +0 1 +.names 43789 44212 +1 1 +.names 44212 44213 +0 1 +.names 44211 44213 44214 +11 1 +.names 44199 44215 +0 1 +.names 43726 44216 +1 1 +.names 43726 44220 44217 +11 1 +.names 44217 44218 +1 1 +.names 19922 44219 +1 1 +.names 44219 44220 +0 1 +.names 44224 44225 44221 +1- 1 +-1 1 +.names 44221 44222 +1 1 +.names 44218 44223 +0 1 +.names 43803 44223 44224 +11 1 +.names 8469 27671 44225 +11 1 +.names 44231 44232 56749 +1- 1 +-1 1 +.names 44216 44227 +0 1 +.names 88 44228 +0 1 +.names 44228 44229 +1 1 +.names 44229 44230 +0 1 +.names 44227 44230 44231 +11 1 +.names 44222 44232 +0 1 +.names 44238 44239 44233 +1- 1 +-1 1 +.names 44233 44234 +1 1 +.names 43695 44242 44235 +11 1 +.names 44235 44236 +1 1 +.names 44236 44237 +0 1 +.names 43709 44237 44238 +11 1 +.names 8458 27678 44239 +11 1 +.names 56687 44240 +0 1 +.names 44240 44241 +1 1 +.names 44241 44242 +0 1 +.names 44249 44250 56754 +1- 1 +-1 1 +.names 93 44244 +0 1 +.names 44244 44245 +1 1 +.names 44245 44246 +0 1 +.names 43695 44247 +1 1 +.names 44247 44248 +0 1 +.names 44246 44248 44249 +11 1 +.names 44234 44250 +0 1 +.names 44256 44257 44251 +1- 1 +-1 1 +.names 44251 44252 +1 1 +.names 43770 44260 44253 +11 1 +.names 44253 44254 +1 1 +.names 44254 44255 +0 1 +.names 43689 44255 44256 +11 1 +.names 8470 27685 44257 +11 1 +.names 56696 44258 +0 1 +.names 44258 44259 +1 1 +.names 44259 44260 +0 1 +.names 44267 44268 56763 +1- 1 +-1 1 +.names 102 44262 +0 1 +.names 44262 44263 +1 1 +.names 44263 44264 +0 1 +.names 43770 44265 +1 1 +.names 44265 44266 +0 1 +.names 44264 44266 44267 +11 1 +.names 44252 44268 +0 1 +.names 44273 44276 56531 +1- 1 +-1 1 +.names 8483 44270 +0 1 +.names 25985 44271 +1 1 +.names 44271 44272 +0 1 +.names 44270 44272 44273 +11 1 +.names 37491 44274 +1 1 +.names 44274 44275 +0 1 +.names 8483 44275 44276 +11 1 +.names 44281 44284 56547 +1- 1 +-1 1 +.names 8477 44278 +0 1 +.names 25904 44279 +1 1 +.names 44279 44280 +0 1 +.names 44278 44280 44281 +11 1 +.names 37398 44282 +1 1 +.names 44282 44283 +0 1 +.names 8477 44283 44284 +11 1 +.names 44288 44291 56542 +1- 1 +-1 1 +.names 26159 44286 +1 1 +.names 44286 44287 +0 1 +.names 44270 44287 44288 +11 1 +.names 37673 44289 +1 1 +.names 44289 44290 +0 1 +.names 8483 44290 44291 +11 1 +.names 44295 44298 56555 +1- 1 +-1 1 +.names 26205 44293 +1 1 +.names 44293 44294 +0 1 +.names 44278 44294 44295 +11 1 +.names 37731 44296 +1 1 +.names 44296 44297 +0 1 +.names 8477 44297 44298 +11 1 +.names 44303 44306 56525 +1- 1 +-1 1 +.names 8478 44300 +0 1 +.names 26522 44301 +1 1 +.names 44301 44302 +0 1 +.names 44300 44302 44303 +11 1 +.names 38071 44304 +1 1 +.names 44304 44305 +0 1 +.names 8478 44305 44306 +11 1 +.names 44311 44314 56526 +1- 1 +-1 1 +.names 8480 44308 +0 1 +.names 25956 44309 +1 1 +.names 44309 44310 +0 1 +.names 44308 44310 44311 +11 1 +.names 37447 44312 +1 1 +.names 44312 44313 +0 1 +.names 8480 44313 44314 +11 1 +.names 44318 44321 56533 +1- 1 +-1 1 +.names 26089 44316 +1 1 +.names 44316 44317 +0 1 +.names 44308 44317 44318 +11 1 +.names 37527 44319 +1 1 +.names 44319 44320 +0 1 +.names 8480 44320 44321 +11 1 +.names 44325 44328 56535 +1- 1 +-1 1 +.names 26123 44323 +1 1 +.names 44323 44324 +0 1 +.names 44278 44324 44325 +11 1 +.names 37630 44326 +1 1 +.names 44326 44327 +0 1 +.names 8477 44327 44328 +11 1 +.names 44332 44335 56544 +1- 1 +-1 1 +.names 26276 44330 +1 1 +.names 44330 44331 +0 1 +.names 44308 44331 44332 +11 1 +.names 37805 44333 +1 1 +.names 44333 44334 +0 1 +.names 8480 44334 44335 +11 1 +.names 44339 44342 56534 +1- 1 +-1 1 +.names 26310 44337 +1 1 +.names 44337 44338 +0 1 +.names 44270 44338 44339 +11 1 +.names 37844 44340 +1 1 +.names 44340 44341 +0 1 +.names 8483 44341 44342 +11 1 +.names 44347 44350 56550 +1- 1 +-1 1 +.names 8482 44344 +0 1 +.names 26358 44345 +1 1 +.names 44345 44346 +0 1 +.names 44344 44346 44347 +11 1 +.names 37894 44348 +1 1 +.names 44348 44349 +0 1 +.names 8482 44349 44350 +11 1 +.names 44354 44357 56536 +1- 1 +-1 1 +.names 26416 44352 +1 1 +.names 44352 44353 +0 1 +.names 44300 44353 44354 +11 1 +.names 37957 44355 +1 1 +.names 44355 44356 +0 1 +.names 8478 44356 44357 +11 1 +.names 44361 44364 56549 +1- 1 +-1 1 +.names 26477 44359 +1 1 +.names 44359 44360 +0 1 +.names 44300 44360 44361 +11 1 +.names 38023 44362 +1 1 +.names 44362 44363 +0 1 +.names 8478 44363 44364 +11 1 +.names 44368 44371 56527 +1- 1 +-1 1 +.names 26847 44366 +1 1 +.names 44366 44367 +0 1 +.names 44300 44367 44368 +11 1 +.names 38442 44369 +1 1 +.names 44369 44370 +0 1 +.names 8478 44370 44371 +11 1 +.names 44375 44378 56530 +1- 1 +-1 1 +.names 26905 44373 +1 1 +.names 44373 44374 +0 1 +.names 44344 44374 44375 +11 1 +.names 38500 44376 +1 1 +.names 44376 44377 +0 1 +.names 8482 44377 44378 +11 1 +.names 44382 44385 56532 +1- 1 +-1 1 +.names 26560 44380 +1 1 +.names 44380 44381 +0 1 +.names 44278 44381 44382 +11 1 +.names 38117 44383 +1 1 +.names 44383 44384 +0 1 +.names 8477 44384 44385 +11 1 +.names 44389 44392 56543 +1- 1 +-1 1 +.names 26602 44387 +1 1 +.names 44387 44388 +0 1 +.names 44344 44388 44389 +11 1 +.names 38164 44390 +1 1 +.names 44390 44391 +0 1 +.names 8482 44391 44392 +11 1 +.names 44396 44399 56541 +1- 1 +-1 1 +.names 26669 44394 +1 1 +.names 44394 44395 +0 1 +.names 44308 44395 44396 +11 1 +.names 38203 44397 +1 1 +.names 44397 44398 +0 1 +.names 8480 44398 44399 +11 1 +.names 44403 44406 56548 +1- 1 +-1 1 +.names 26708 44401 +1 1 +.names 44401 44402 +0 1 +.names 44308 44402 44403 +11 1 +.names 38279 44404 +1 1 +.names 44404 44405 +0 1 +.names 8480 44405 44406 +11 1 +.names 44410 44413 56556 +1- 1 +-1 1 +.names 26769 44408 +1 1 +.names 44408 44409 +0 1 +.names 44270 44409 44410 +11 1 +.names 38349 44411 +1 1 +.names 44411 44412 +0 1 +.names 8483 44412 44413 +11 1 +.names 44418 44421 56546 +1- 1 +-1 1 +.names 8481 44415 +0 1 +.names 26813 44416 +1 1 +.names 44416 44417 +0 1 +.names 44415 44417 44418 +11 1 +.names 38402 44419 +1 1 +.names 44419 44420 +0 1 +.names 8481 44420 44421 +11 1 +.names 44425 44428 56538 +1- 1 +-1 1 +.names 26977 44423 +1 1 +.names 44423 44424 +0 1 +.names 44415 44424 44425 +11 1 +.names 38559 44426 +1 1 +.names 44426 44427 +0 1 +.names 8481 44427 44428 +11 1 +.names 44432 44435 56539 +1- 1 +-1 1 +.names 27009 44430 +1 1 +.names 44430 44431 +0 1 +.names 44344 44431 44432 +11 1 +.names 38617 44433 +1 1 +.names 44433 44434 +0 1 +.names 8482 44434 44435 +11 1 +.names 44439 44442 56553 +1- 1 +-1 1 +.names 27055 44437 +1 1 +.names 44437 44438 +0 1 +.names 44278 44438 44439 +11 1 +.names 38675 44440 +1 1 +.names 44440 44441 +0 1 +.names 8477 44441 44442 +11 1 +.names 44446 44449 56537 +1- 1 +-1 1 +.names 27101 44444 +1 1 +.names 44444 44445 +0 1 +.names 44300 44445 44446 +11 1 +.names 38717 44447 +1 1 +.names 44447 44448 +0 1 +.names 8478 44448 44449 +11 1 +.names 44453 44456 56551 +1- 1 +-1 1 +.names 27147 44451 +1 1 +.names 44451 44452 +0 1 +.names 44270 44452 44453 +11 1 +.names 38784 44454 +1 1 +.names 44454 44455 +0 1 +.names 8483 44455 44456 +11 1 +.names 44460 44463 56552 +1- 1 +-1 1 +.names 27207 44458 +1 1 +.names 44458 44459 +0 1 +.names 44270 44459 44460 +11 1 +.names 38838 44461 +1 1 +.names 44461 44462 +0 1 +.names 8483 44462 44463 +11 1 +.names 44467 44470 56528 +1- 1 +-1 1 +.names 27251 44465 +1 1 +.names 44465 44466 +0 1 +.names 44415 44466 44467 +11 1 +.names 38895 44468 +1 1 +.names 44468 44469 +0 1 +.names 8481 44469 44470 +11 1 +.names 44474 44477 56529 +1- 1 +-1 1 +.names 27297 44472 +1 1 +.names 44472 44473 +0 1 +.names 44415 44473 44474 +11 1 +.names 38947 44475 +1 1 +.names 44475 44476 +0 1 +.names 8481 44476 44477 +11 1 +.names 44481 44484 56540 +1- 1 +-1 1 +.names 27340 44479 +1 1 +.names 44479 44480 +0 1 +.names 44415 44480 44481 +11 1 +.names 38960 44482 +1 1 +.names 44482 44483 +0 1 +.names 8481 44483 44484 +11 1 +.names 44488 44491 56545 +1- 1 +-1 1 +.names 27378 44486 +1 1 +.names 44486 44487 +0 1 +.names 44344 44487 44488 +11 1 +.names 39048 44489 +1 1 +.names 44489 44490 +0 1 +.names 8482 44490 44491 +11 1 +.names 44495 44498 56554 +1- 1 +-1 1 +.names 27436 44493 +1 1 +.names 44493 44494 +0 1 +.names 44344 44494 44495 +11 1 +.names 39099 44496 +1 1 +.names 44496 44497 +0 1 +.names 8482 44497 44498 +11 1 +.names 44503 44507 56499 +1- 1 +-1 1 +.names 8495 44500 +0 1 +.names 14872 44501 +1 1 +.names 44501 44502 +0 1 +.names 44500 44502 44503 +11 1 +.names 1412 44504 +0 1 +.names 44504 44505 +1 1 +.names 44505 44506 +0 1 +.names 8495 44506 44507 +11 1 +.names 44512 44516 56515 +1- 1 +-1 1 +.names 8489 44509 +0 1 +.names 14782 44510 +1 1 +.names 44510 44511 +0 1 +.names 44509 44511 44512 +11 1 +.names 1413 44513 +0 1 +.names 44513 44514 +1 1 +.names 44514 44515 +0 1 +.names 8489 44515 44516 +11 1 +.names 44521 44525 56510 +1- 1 +-1 1 +.names 56716 44518 +0 1 +.names 44518 44519 +1 1 +.names 44519 44520 +0 1 +.names 44500 44520 44521 +11 1 +.names 1414 44522 +0 1 +.names 44522 44523 +1 1 +.names 44523 44524 +0 1 +.names 8495 44524 44525 +11 1 +.names 44530 44534 56523 +1- 1 +-1 1 +.names 56729 44527 +0 1 +.names 44527 44528 +1 1 +.names 44528 44529 +0 1 +.names 44509 44529 44530 +11 1 +.names 1415 44531 +0 1 +.names 44531 44532 +1 1 +.names 44532 44533 +0 1 +.names 8489 44533 44534 +11 1 +.names 44539 44542 56493 +1- 1 +-1 1 +.names 8490 44536 +0 1 +.names 14937 44537 +1 1 +.names 44537 44538 +0 1 +.names 44536 44538 44539 +11 1 +.names 2413 44540 +1 1 +.names 44540 44541 +0 1 +.names 8490 44541 44542 +11 1 +.names 44548 44551 56494 +1- 1 +-1 1 +.names 8492 44544 +0 1 +.names 56700 44545 +0 1 +.names 44545 44546 +1 1 +.names 44546 44547 +0 1 +.names 44544 44547 44548 +11 1 +.names 2413 44549 +1 1 +.names 44549 44550 +0 1 +.names 8492 44550 44551 +11 1 +.names 44555 44559 56501 +1- 1 +-1 1 +.names 14852 44553 +1 1 +.names 44553 44554 +0 1 +.names 44544 44554 44555 +11 1 +.names 1416 44556 +0 1 +.names 44556 44557 +1 1 +.names 44557 44558 +0 1 +.names 8492 44558 44559 +11 1 +.names 44563 44567 56503 +1- 1 +-1 1 +.names 14832 44561 +1 1 +.names 44561 44562 +0 1 +.names 44509 44562 44563 +11 1 +.names 1417 44564 +0 1 +.names 44564 44565 +1 1 +.names 44565 44566 +0 1 +.names 8489 44566 44567 +11 1 +.names 44572 44576 56512 +1- 1 +-1 1 +.names 56718 44569 +0 1 +.names 44569 44570 +1 1 +.names 44570 44571 +0 1 +.names 44544 44571 44572 +11 1 +.names 1418 44573 +0 1 +.names 44573 44574 +1 1 +.names 44574 44575 +0 1 +.names 8492 44575 44576 +11 1 +.names 44580 44584 56502 +1- 1 +-1 1 +.names 14842 44578 +1 1 +.names 44578 44579 +0 1 +.names 44500 44579 44580 +11 1 +.names 1419 44581 +0 1 +.names 44581 44582 +1 1 +.names 44582 44583 +0 1 +.names 8495 44583 44584 +11 1 +.names 44590 44594 56518 +1- 1 +-1 1 +.names 8494 44586 +0 1 +.names 56724 44587 +0 1 +.names 44587 44588 +1 1 +.names 44588 44589 +0 1 +.names 44586 44589 44590 +11 1 +.names 1420 44591 +0 1 +.names 44591 44592 +1 1 +.names 44592 44593 +0 1 +.names 8494 44593 44594 +11 1 +.names 44598 44602 56504 +1- 1 +-1 1 +.names 14822 44596 +1 1 +.names 44596 44597 +0 1 +.names 44536 44597 44598 +11 1 +.names 1421 44599 +0 1 +.names 44599 44600 +1 1 +.names 44600 44601 +0 1 +.names 8490 44601 44602 +11 1 +.names 44607 44611 56517 +1- 1 +-1 1 +.names 56723 44604 +0 1 +.names 44604 44605 +1 1 +.names 44605 44606 +0 1 +.names 44536 44606 44607 +11 1 +.names 1422 44608 +0 1 +.names 44608 44609 +1 1 +.names 44609 44610 +0 1 +.names 8490 44610 44611 +11 1 +.names 44616 44620 56495 +1- 1 +-1 1 +.names 56701 44613 +0 1 +.names 44613 44614 +1 1 +.names 44614 44615 +0 1 +.names 44536 44615 44616 +11 1 +.names 1423 44617 +0 1 +.names 44617 44618 +1 1 +.names 44618 44619 +0 1 +.names 8490 44619 44620 +11 1 +.names 44624 44628 56498 +1- 1 +-1 1 +.names 14882 44622 +1 1 +.names 44622 44623 +0 1 +.names 44586 44623 44624 +11 1 +.names 1424 44625 +0 1 +.names 44625 44626 +1 1 +.names 44626 44627 +0 1 +.names 8494 44627 44628 +11 1 +.names 44632 44636 56500 +1- 1 +-1 1 +.names 14862 44630 +1 1 +.names 44630 44631 +0 1 +.names 44509 44631 44632 +11 1 +.names 1425 44633 +0 1 +.names 44633 44634 +1 1 +.names 44634 44635 +0 1 +.names 8489 44635 44636 +11 1 +.names 44641 44645 56511 +1- 1 +-1 1 +.names 56717 44638 +0 1 +.names 44638 44639 +1 1 +.names 44639 44640 +0 1 +.names 44586 44640 44641 +11 1 +.names 1426 44642 +0 1 +.names 44642 44643 +1 1 +.names 44643 44644 +0 1 +.names 8494 44644 44645 +11 1 +.names 44650 44654 56509 +1- 1 +-1 1 +.names 56715 44647 +0 1 +.names 44647 44648 +1 1 +.names 44648 44649 +0 1 +.names 44544 44649 44650 +11 1 +.names 1427 44651 +0 1 +.names 44651 44652 +1 1 +.names 44652 44653 +0 1 +.names 8492 44653 44654 +11 1 +.names 44659 44663 56516 +1- 1 +-1 1 +.names 56722 44656 +0 1 +.names 44656 44657 +1 1 +.names 44657 44658 +0 1 +.names 44544 44658 44659 +11 1 +.names 1428 44660 +0 1 +.names 44660 44661 +1 1 +.names 44661 44662 +0 1 +.names 8492 44662 44663 +11 1 +.names 44667 44671 56524 +1- 1 +-1 1 +.names 14760 44665 +1 1 +.names 44665 44666 +0 1 +.names 44500 44666 44667 +11 1 +.names 1429 44668 +0 1 +.names 44668 44669 +1 1 +.names 44669 44670 +0 1 +.names 8495 44670 44671 +11 1 +.names 44677 44681 56514 +1- 1 +-1 1 +.names 8493 44673 +0 1 +.names 56720 44674 +0 1 +.names 44674 44675 +1 1 +.names 44675 44676 +0 1 +.names 44673 44676 44677 +11 1 +.names 1430 44678 +0 1 +.names 44678 44679 +1 1 +.names 44679 44680 +0 1 +.names 8493 44680 44681 +11 1 +.names 44685 44689 56506 +1- 1 +-1 1 +.names 14802 44683 +1 1 +.names 44683 44684 +0 1 +.names 44673 44684 44685 +11 1 +.names 1431 44686 +0 1 +.names 44686 44687 +1 1 +.names 44687 44688 +0 1 +.names 8493 44688 44689 +11 1 +.names 44693 44697 56507 +1- 1 +-1 1 +.names 57098 44691 +1 1 +.names 44691 44692 +0 1 +.names 44586 44692 44693 +11 1 +.names 1432 44694 +0 1 +.names 44694 44695 +1 1 +.names 44695 44696 +0 1 +.names 8494 44696 44697 +11 1 +.names 44702 44706 56521 +1- 1 +-1 1 +.names 56727 44699 +0 1 +.names 44699 44700 +1 1 +.names 44700 44701 +0 1 +.names 44509 44701 44702 +11 1 +.names 1433 44703 +0 1 +.names 44703 44704 +1 1 +.names 44704 44705 +0 1 +.names 8489 44705 44706 +11 1 +.names 44710 44714 56505 +1- 1 +-1 1 +.names 14812 44708 +1 1 +.names 44708 44709 +0 1 +.names 44536 44709 44710 +11 1 +.names 1434 44711 +0 1 +.names 44711 44712 +1 1 +.names 44712 44713 +0 1 +.names 8490 44713 44714 +11 1 +.names 44719 44723 56519 +1- 1 +-1 1 +.names 56725 44716 +0 1 +.names 44716 44717 +1 1 +.names 44717 44718 +0 1 +.names 44500 44718 44719 +11 1 +.names 1435 44720 +0 1 +.names 44720 44721 +1 1 +.names 44721 44722 +0 1 +.names 8495 44722 44723 +11 1 +.names 44728 44732 56520 +1- 1 +-1 1 +.names 56726 44725 +0 1 +.names 44725 44726 +1 1 +.names 44726 44727 +0 1 +.names 44500 44727 44728 +11 1 +.names 1436 44729 +0 1 +.names 44729 44730 +1 1 +.names 44730 44731 +0 1 +.names 8495 44731 44732 +11 1 +.names 44736 44740 56496 +1- 1 +-1 1 +.names 14927 44734 +1 1 +.names 44734 44735 +0 1 +.names 44673 44735 44736 +11 1 +.names 1437 44737 +0 1 +.names 44737 44738 +1 1 +.names 44738 44739 +0 1 +.names 8493 44739 44740 +11 1 +.names 44744 44748 56497 +1- 1 +-1 1 +.names 14893 44742 +1 1 +.names 44742 44743 +0 1 +.names 44673 44743 44744 +11 1 +.names 1438 44745 +0 1 +.names 44745 44746 +1 1 +.names 44746 44747 +0 1 +.names 8493 44747 44748 +11 1 +.names 44752 44756 56508 +1- 1 +-1 1 +.names 14792 44750 +1 1 +.names 44750 44751 +0 1 +.names 44673 44751 44752 +11 1 +.names 1439 44753 +0 1 +.names 44753 44754 +1 1 +.names 44754 44755 +0 1 +.names 8493 44755 44756 +11 1 +.names 44761 44765 56513 +1- 1 +-1 1 +.names 56719 44758 +0 1 +.names 44758 44759 +1 1 +.names 44759 44760 +0 1 +.names 44586 44760 44761 +11 1 +.names 1440 44762 +0 1 +.names 44762 44763 +1 1 +.names 44763 44764 +0 1 +.names 8494 44764 44765 +11 1 +.names 44770 44774 56522 +1- 1 +-1 1 +.names 56728 44767 +0 1 +.names 44767 44768 +1 1 +.names 44768 44769 +0 1 +.names 44586 44769 44770 +11 1 +.names 1441 44771 +0 1 +.names 44771 44772 +1 1 +.names 44772 44773 +0 1 +.names 8494 44773 44774 +11 1 +.names 44780 44784 57157 +1- 1 +-1 1 +.names 8507 44776 +0 1 +.names 37476 44777 +0 1 +.names 44777 44778 +1 1 +.names 44778 44779 +0 1 +.names 44776 44779 44780 +11 1 +.names 515 44781 +0 1 +.names 44781 44782 +1 1 +.names 44782 44783 +0 1 +.names 8507 44783 44784 +11 1 +.names 44790 44794 57158 +1- 1 +-1 1 +.names 8501 44786 +0 1 +.names 37385 44787 +0 1 +.names 44787 44788 +1 1 +.names 44788 44789 +0 1 +.names 44786 44789 44790 +11 1 +.names 531 44791 +0 1 +.names 44791 44792 +1 1 +.names 44792 44793 +0 1 +.names 8501 44793 44794 +11 1 +.names 44799 44803 57159 +1- 1 +-1 1 +.names 37663 44796 +0 1 +.names 44796 44797 +1 1 +.names 44797 44798 +0 1 +.names 44776 44798 44799 +11 1 +.names 526 44800 +0 1 +.names 44800 44801 +1 1 +.names 44801 44802 +0 1 +.names 8507 44802 44803 +11 1 +.names 44808 44812 57160 +1- 1 +-1 1 +.names 37717 44805 +0 1 +.names 44805 44806 +1 1 +.names 44806 44807 +0 1 +.names 44786 44807 44808 +11 1 +.names 539 44809 +0 1 +.names 44809 44810 +1 1 +.names 44810 44811 +0 1 +.names 8501 44811 44812 +11 1 +.names 44818 44822 57161 +1- 1 +-1 1 +.names 8502 44814 +0 1 +.names 38069 44815 +0 1 +.names 44815 44816 +1 1 +.names 44816 44817 +0 1 +.names 44814 44817 44818 +11 1 +.names 509 44819 +0 1 +.names 44819 44820 +1 1 +.names 44820 44821 +0 1 +.names 8502 44821 44822 +11 1 +.names 44828 44832 57162 +1- 1 +-1 1 +.names 8504 44824 +0 1 +.names 37441 44825 +0 1 +.names 44825 44826 +1 1 +.names 44826 44827 +0 1 +.names 44824 44827 44828 +11 1 +.names 510 44829 +0 1 +.names 44829 44830 +1 1 +.names 44830 44831 +0 1 +.names 8504 44831 44832 +11 1 +.names 44837 44841 57163 +1- 1 +-1 1 +.names 37529 44834 +0 1 +.names 44834 44835 +1 1 +.names 44835 44836 +0 1 +.names 44824 44836 44837 +11 1 +.names 517 44838 +0 1 +.names 44838 44839 +1 1 +.names 44839 44840 +0 1 +.names 8504 44840 44841 +11 1 +.names 44846 44850 57164 +1- 1 +-1 1 +.names 37624 44843 +0 1 +.names 44843 44844 +1 1 +.names 44844 44845 +0 1 +.names 44786 44845 44846 +11 1 +.names 519 44847 +0 1 +.names 44847 44848 +1 1 +.names 44848 44849 +0 1 +.names 8501 44849 44850 +11 1 +.names 44855 44859 57165 +1- 1 +-1 1 +.names 37751 44852 +0 1 +.names 44852 44853 +1 1 +.names 44853 44854 +0 1 +.names 44824 44854 44855 +11 1 +.names 528 44856 +0 1 +.names 44856 44857 +1 1 +.names 44857 44858 +0 1 +.names 8504 44858 44859 +11 1 +.names 44864 44868 57166 +1- 1 +-1 1 +.names 37838 44861 +0 1 +.names 44861 44862 +1 1 +.names 44862 44863 +0 1 +.names 44776 44863 44864 +11 1 +.names 518 44865 +0 1 +.names 44865 44866 +1 1 +.names 44866 44867 +0 1 +.names 8507 44867 44868 +11 1 +.names 44874 44878 57167 +1- 1 +-1 1 +.names 8506 44870 +0 1 +.names 37884 44871 +0 1 +.names 44871 44872 +1 1 +.names 44872 44873 +0 1 +.names 44870 44873 44874 +11 1 +.names 534 44875 +0 1 +.names 44875 44876 +1 1 +.names 44876 44877 +0 1 +.names 8506 44877 44878 +11 1 +.names 44883 44887 57168 +1- 1 +-1 1 +.names 37951 44880 +0 1 +.names 44880 44881 +1 1 +.names 44881 44882 +0 1 +.names 44814 44882 44883 +11 1 +.names 520 44884 +0 1 +.names 44884 44885 +1 1 +.names 44885 44886 +0 1 +.names 8502 44886 44887 +11 1 +.names 44892 44896 57169 +1- 1 +-1 1 +.names 37974 44889 +0 1 +.names 44889 44890 +1 1 +.names 44890 44891 +0 1 +.names 44814 44891 44892 +11 1 +.names 533 44893 +0 1 +.names 44893 44894 +1 1 +.names 44894 44895 +0 1 +.names 8502 44895 44896 +11 1 +.names 44901 44905 57170 +1- 1 +-1 1 +.names 38430 44898 +0 1 +.names 44898 44899 +1 1 +.names 44899 44900 +0 1 +.names 44814 44900 44901 +11 1 +.names 511 44902 +0 1 +.names 44902 44903 +1 1 +.names 44903 44904 +0 1 +.names 8502 44904 44905 +11 1 +.names 44910 44914 57171 +1- 1 +-1 1 +.names 38494 44907 +0 1 +.names 44907 44908 +1 1 +.names 44908 44909 +0 1 +.names 44870 44909 44910 +11 1 +.names 514 44911 +0 1 +.names 44911 44912 +1 1 +.names 44912 44913 +0 1 +.names 8506 44913 44914 +11 1 +.names 44919 44923 57172 +1- 1 +-1 1 +.names 38113 44916 +0 1 +.names 44916 44917 +1 1 +.names 44917 44918 +0 1 +.names 44786 44918 44919 +11 1 +.names 516 44920 +0 1 +.names 44920 44921 +1 1 +.names 44921 44922 +0 1 +.names 8501 44922 44923 +11 1 +.names 44928 44932 57173 +1- 1 +-1 1 +.names 38175 44925 +0 1 +.names 44925 44926 +1 1 +.names 44926 44927 +0 1 +.names 44870 44927 44928 +11 1 +.names 527 44929 +0 1 +.names 44929 44930 +1 1 +.names 44930 44931 +0 1 +.names 8506 44931 44932 +11 1 +.names 44937 44941 57174 +1- 1 +-1 1 +.names 38234 44934 +0 1 +.names 44934 44935 +1 1 +.names 44935 44936 +0 1 +.names 44824 44936 44937 +11 1 +.names 525 44938 +0 1 +.names 44938 44939 +1 1 +.names 44939 44940 +0 1 +.names 8504 44940 44941 +11 1 +.names 44946 44950 57175 +1- 1 +-1 1 +.names 38277 44943 +0 1 +.names 44943 44944 +1 1 +.names 44944 44945 +0 1 +.names 44824 44945 44946 +11 1 +.names 532 44947 +0 1 +.names 44947 44948 +1 1 +.names 44948 44949 +0 1 +.names 8504 44949 44950 +11 1 +.names 44955 44959 57176 +1- 1 +-1 1 +.names 38299 44952 +0 1 +.names 44952 44953 +1 1 +.names 44953 44954 +0 1 +.names 44776 44954 44955 +11 1 +.names 540 44956 +0 1 +.names 44956 44957 +1 1 +.names 44957 44958 +0 1 +.names 8507 44958 44959 +11 1 +.names 44965 44969 57177 +1- 1 +-1 1 +.names 8505 44961 +0 1 +.names 38392 44962 +0 1 +.names 44962 44963 +1 1 +.names 44963 44964 +0 1 +.names 44961 44964 44965 +11 1 +.names 530 44966 +0 1 +.names 44966 44967 +1 1 +.names 44967 44968 +0 1 +.names 8505 44968 44969 +11 1 +.names 44974 44978 57178 +1- 1 +-1 1 +.names 38518 44971 +0 1 +.names 44971 44972 +1 1 +.names 44972 44973 +0 1 +.names 44961 44973 44974 +11 1 +.names 522 44975 +0 1 +.names 44975 44976 +1 1 +.names 44976 44977 +0 1 +.names 8505 44977 44978 +11 1 +.names 44983 44987 57179 +1- 1 +-1 1 +.names 38611 44980 +0 1 +.names 44980 44981 +1 1 +.names 44981 44982 +0 1 +.names 44870 44982 44983 +11 1 +.names 523 44984 +0 1 +.names 44984 44985 +1 1 +.names 44985 44986 +0 1 +.names 8506 44986 44987 +11 1 +.names 44992 44996 57180 +1- 1 +-1 1 +.names 38663 44989 +0 1 +.names 44989 44990 +1 1 +.names 44990 44991 +0 1 +.names 44786 44991 44992 +11 1 +.names 537 44993 +0 1 +.names 44993 44994 +1 1 +.names 44994 44995 +0 1 +.names 8501 44995 44996 +11 1 +.names 45001 45005 57181 +1- 1 +-1 1 +.names 38715 44998 +0 1 +.names 44998 44999 +1 1 +.names 44999 45000 +0 1 +.names 44814 45000 45001 +11 1 +.names 521 45002 +0 1 +.names 45002 45003 +1 1 +.names 45003 45004 +0 1 +.names 8502 45004 45005 +11 1 +.names 45010 45014 57182 +1- 1 +-1 1 +.names 38768 45007 +0 1 +.names 45007 45008 +1 1 +.names 45008 45009 +0 1 +.names 44776 45009 45010 +11 1 +.names 535 45011 +0 1 +.names 45011 45012 +1 1 +.names 45012 45013 +0 1 +.names 8507 45013 45014 +11 1 +.names 45019 45023 57183 +1- 1 +-1 1 +.names 38790 45016 +0 1 +.names 45016 45017 +1 1 +.names 45017 45018 +0 1 +.names 44776 45018 45019 +11 1 +.names 536 45020 +0 1 +.names 45020 45021 +1 1 +.names 45021 45022 +0 1 +.names 8507 45022 45023 +11 1 +.names 45028 45032 57184 +1- 1 +-1 1 +.names 38883 45025 +0 1 +.names 45025 45026 +1 1 +.names 45026 45027 +0 1 +.names 44961 45027 45028 +11 1 +.names 512 45029 +0 1 +.names 45029 45030 +1 1 +.names 45030 45031 +0 1 +.names 8505 45031 45032 +11 1 +.names 45037 45041 57185 +1- 1 +-1 1 +.names 38935 45034 +0 1 +.names 45034 45035 +1 1 +.names 45035 45036 +0 1 +.names 44961 45036 45037 +11 1 +.names 513 45038 +0 1 +.names 45038 45039 +1 1 +.names 45039 45040 +0 1 +.names 8505 45040 45041 +11 1 +.names 45046 45050 57186 +1- 1 +-1 1 +.names 38986 45043 +0 1 +.names 45043 45044 +1 1 +.names 45044 45045 +0 1 +.names 44961 45045 45046 +11 1 +.names 524 45047 +0 1 +.names 45047 45048 +1 1 +.names 45048 45049 +0 1 +.names 8505 45049 45050 +11 1 +.names 45055 45059 57187 +1- 1 +-1 1 +.names 39028 45052 +0 1 +.names 45052 45053 +1 1 +.names 45053 45054 +0 1 +.names 44870 45054 45055 +11 1 +.names 529 45056 +0 1 +.names 45056 45057 +1 1 +.names 45057 45058 +0 1 +.names 8506 45058 45059 +11 1 +.names 45064 45068 57188 +1- 1 +-1 1 +.names 39093 45061 +0 1 +.names 45061 45062 +1 1 +.names 45062 45063 +0 1 +.names 44870 45063 45064 +11 1 +.names 538 45065 +0 1 +.names 45065 45066 +1 1 +.names 45066 45067 +0 1 +.names 8506 45067 45068 +11 1 +.names 8519 45069 +0 1 +.names 1442 45070 +0 1 +.names 45070 45071 +1 1 +.names 45071 45072 +0 1 +.names 45069 45072 45073 +11 1 +.names 210 45074 +0 1 +.names 45074 45075 +1 1 +.names 45075 45076 +0 1 +.names 8519 45076 45077 +11 1 +.names 8513 45078 +0 1 +.names 1443 45079 +0 1 +.names 45079 45080 +1 1 +.names 45080 45081 +0 1 +.names 45078 45081 45082 +11 1 +.names 226 45083 +0 1 +.names 45083 45084 +1 1 +.names 45084 45085 +0 1 +.names 8513 45085 45086 +11 1 +.names 1444 45087 +0 1 +.names 45087 45088 +1 1 +.names 45088 45089 +0 1 +.names 45069 45089 45090 +11 1 +.names 221 45091 +0 1 +.names 45091 45092 +1 1 +.names 45092 45093 +0 1 +.names 8519 45093 45094 +11 1 +.names 1445 45095 +0 1 +.names 45095 45096 +1 1 +.names 45096 45097 +0 1 +.names 45078 45097 45098 +11 1 +.names 234 45099 +0 1 +.names 45099 45100 +1 1 +.names 45100 45101 +0 1 +.names 8513 45101 45102 +11 1 +.names 8514 45103 +0 1 +.names 1446 45104 +0 1 +.names 45104 45105 +1 1 +.names 45105 45106 +0 1 +.names 45103 45106 45107 +11 1 +.names 3116 45108 +1 1 +.names 45108 45109 +0 1 +.names 8514 45109 45110 +11 1 +.names 8516 45111 +0 1 +.names 1447 45112 +0 1 +.names 45112 45113 +1 1 +.names 45113 45114 +0 1 +.names 45111 45114 45115 +11 1 +.names 205 45116 +0 1 +.names 45116 45117 +1 1 +.names 45117 45118 +0 1 +.names 8516 45118 45119 +11 1 +.names 1448 45120 +0 1 +.names 45120 45121 +1 1 +.names 45121 45122 +0 1 +.names 45111 45122 45123 +11 1 +.names 212 45124 +0 1 +.names 45124 45125 +1 1 +.names 45125 45126 +0 1 +.names 8516 45126 45127 +11 1 +.names 1449 45128 +0 1 +.names 45128 45129 +1 1 +.names 45129 45130 +0 1 +.names 45078 45130 45131 +11 1 +.names 214 45132 +0 1 +.names 45132 45133 +1 1 +.names 45133 45134 +0 1 +.names 8513 45134 45135 +11 1 +.names 1450 45136 +0 1 +.names 45136 45137 +1 1 +.names 45137 45138 +0 1 +.names 45111 45138 45139 +11 1 +.names 223 45140 +0 1 +.names 45140 45141 +1 1 +.names 45141 45142 +0 1 +.names 8516 45142 45143 +11 1 +.names 1451 45144 +0 1 +.names 45144 45145 +1 1 +.names 45145 45146 +0 1 +.names 45069 45146 45147 +11 1 +.names 213 45148 +0 1 +.names 45148 45149 +1 1 +.names 45149 45150 +0 1 +.names 8519 45150 45151 +11 1 +.names 8518 45152 +0 1 +.names 1452 45153 +0 1 +.names 45153 45154 +1 1 +.names 45154 45155 +0 1 +.names 45152 45155 45156 +11 1 +.names 229 45157 +0 1 +.names 45157 45158 +1 1 +.names 45158 45159 +0 1 +.names 8518 45159 45160 +11 1 +.names 1453 45161 +0 1 +.names 45161 45162 +1 1 +.names 45162 45163 +0 1 +.names 45103 45163 45164 +11 1 +.names 215 45165 +0 1 +.names 45165 45166 +1 1 +.names 45166 45167 +0 1 +.names 8514 45167 45168 +11 1 +.names 1454 45169 +0 1 +.names 45169 45170 +1 1 +.names 45170 45171 +0 1 +.names 45103 45171 45172 +11 1 +.names 228 45173 +0 1 +.names 45173 45174 +1 1 +.names 45174 45175 +0 1 +.names 8514 45175 45176 +11 1 +.names 1455 45177 +0 1 +.names 45177 45178 +1 1 +.names 45178 45179 +0 1 +.names 45103 45179 45180 +11 1 +.names 206 45181 +0 1 +.names 45181 45182 +1 1 +.names 45182 45183 +0 1 +.names 8514 45183 45184 +11 1 +.names 1456 45185 +0 1 +.names 45185 45186 +1 1 +.names 45186 45187 +0 1 +.names 45152 45187 45188 +11 1 +.names 209 45189 +0 1 +.names 45189 45190 +1 1 +.names 45190 45191 +0 1 +.names 8518 45191 45192 +11 1 +.names 1457 45193 +0 1 +.names 45193 45194 +1 1 +.names 45194 45195 +0 1 +.names 45078 45195 45196 +11 1 +.names 211 45197 +0 1 +.names 45197 45198 +1 1 +.names 45198 45199 +0 1 +.names 8513 45199 45200 +11 1 +.names 1458 45201 +0 1 +.names 45201 45202 +1 1 +.names 45202 45203 +0 1 +.names 45152 45203 45204 +11 1 +.names 222 45205 +0 1 +.names 45205 45206 +1 1 +.names 45206 45207 +0 1 +.names 8518 45207 45208 +11 1 +.names 1459 45209 +0 1 +.names 45209 45210 +1 1 +.names 45210 45211 +0 1 +.names 45111 45211 45212 +11 1 +.names 220 45213 +0 1 +.names 45213 45214 +1 1 +.names 45214 45215 +0 1 +.names 8516 45215 45216 +11 1 +.names 1460 45217 +0 1 +.names 45217 45218 +1 1 +.names 45218 45219 +0 1 +.names 45111 45219 45220 +11 1 +.names 227 45221 +0 1 +.names 45221 45222 +1 1 +.names 45222 45223 +0 1 +.names 8516 45223 45224 +11 1 +.names 1461 45225 +0 1 +.names 45225 45226 +1 1 +.names 45226 45227 +0 1 +.names 45069 45227 45228 +11 1 +.names 235 45229 +0 1 +.names 45229 45230 +1 1 +.names 45230 45231 +0 1 +.names 8519 45231 45232 +11 1 +.names 8517 45233 +0 1 +.names 1462 45234 +0 1 +.names 45234 45235 +1 1 +.names 45235 45236 +0 1 +.names 45233 45236 45237 +11 1 +.names 225 45238 +0 1 +.names 45238 45239 +1 1 +.names 45239 45240 +0 1 +.names 8517 45240 45241 +11 1 +.names 1463 45242 +0 1 +.names 45242 45243 +1 1 +.names 45243 45244 +0 1 +.names 45233 45244 45245 +11 1 +.names 217 45246 +0 1 +.names 45246 45247 +1 1 +.names 45247 45248 +0 1 +.names 8517 45248 45249 +11 1 +.names 1464 45250 +0 1 +.names 45250 45251 +1 1 +.names 45251 45252 +0 1 +.names 45152 45252 45253 +11 1 +.names 218 45254 +0 1 +.names 45254 45255 +1 1 +.names 45255 45256 +0 1 +.names 8518 45256 45257 +11 1 +.names 1465 45258 +0 1 +.names 45258 45259 +1 1 +.names 45259 45260 +0 1 +.names 45078 45260 45261 +11 1 +.names 232 45262 +0 1 +.names 45262 45263 +1 1 +.names 45263 45264 +0 1 +.names 8513 45264 45265 +11 1 +.names 1466 45266 +0 1 +.names 45266 45267 +1 1 +.names 45267 45268 +0 1 +.names 45103 45268 45269 +11 1 +.names 216 45270 +0 1 +.names 45270 45271 +1 1 +.names 45271 45272 +0 1 +.names 8514 45272 45273 +11 1 +.names 1467 45274 +0 1 +.names 45274 45275 +1 1 +.names 45275 45276 +0 1 +.names 45069 45276 45277 +11 1 +.names 230 45278 +0 1 +.names 45278 45279 +1 1 +.names 45279 45280 +0 1 +.names 8519 45280 45281 +11 1 +.names 1468 45282 +0 1 +.names 45282 45283 +1 1 +.names 45283 45284 +0 1 +.names 45069 45284 45285 +11 1 +.names 231 45286 +0 1 +.names 45286 45287 +1 1 +.names 45287 45288 +0 1 +.names 8519 45288 45289 +11 1 +.names 1469 45290 +0 1 +.names 45290 45291 +1 1 +.names 45291 45292 +0 1 +.names 45233 45292 45293 +11 1 +.names 207 45294 +0 1 +.names 45294 45295 +1 1 +.names 45295 45296 +0 1 +.names 8517 45296 45297 +11 1 +.names 1470 45298 +0 1 +.names 45298 45299 +1 1 +.names 45299 45300 +0 1 +.names 45233 45300 45301 +11 1 +.names 208 45302 +0 1 +.names 45302 45303 +1 1 +.names 45303 45304 +0 1 +.names 8517 45304 45305 +11 1 +.names 1471 45306 +0 1 +.names 45306 45307 +1 1 +.names 45307 45308 +0 1 +.names 45233 45308 45309 +11 1 +.names 219 45310 +0 1 +.names 45310 45311 +1 1 +.names 45311 45312 +0 1 +.names 8517 45312 45313 +11 1 +.names 1472 45314 +0 1 +.names 45314 45315 +1 1 +.names 45315 45316 +0 1 +.names 45152 45316 45317 +11 1 +.names 224 45318 +0 1 +.names 45318 45319 +1 1 +.names 45319 45320 +0 1 +.names 8518 45320 45321 +11 1 +.names 1473 45322 +0 1 +.names 45322 45323 +1 1 +.names 45323 45324 +0 1 +.names 45152 45324 45325 +11 1 +.names 233 45326 +0 1 +.names 45326 45327 +1 1 +.names 45327 45328 +0 1 +.names 8518 45328 45329 +11 1 +.names 45336 45338 45330 +1- 1 +-1 1 +.names 45330 45331 +1 1 +.names 8533 45332 +0 1 +.names 45339 45342 45333 +11 1 +.names 45333 45334 +1 1 +.names 45334 45335 +0 1 +.names 45332 45335 45336 +11 1 +.names 106 45337 +0 1 +.names 8533 45337 45338 +11 1 +.names 8534 45339 +0 1 +.names 542 45340 +0 1 +.names 45340 45341 +1 1 +.names 45341 45342 +0 1 +.names 45349 45350 57189 +1- 1 +-1 1 +.names 441 45344 +0 1 +.names 45344 45345 +1 1 +.names 45345 45346 +0 1 +.names 45339 45347 +1 1 +.names 45347 45348 +0 1 +.names 45346 45348 45349 +11 1 +.names 45331 45350 +0 1 +.names 45357 45359 45351 +1- 1 +-1 1 +.names 45351 45352 +1 1 +.names 8521 45353 +0 1 +.names 45339 45362 45354 +11 1 +.names 45354 45355 +1 1 +.names 45355 45356 +0 1 +.names 45353 45356 45357 +11 1 +.names 111 45358 +0 1 +.names 8521 45358 45359 +11 1 +.names 547 45360 +0 1 +.names 45360 45361 +1 1 +.names 45361 45362 +0 1 +.names 45369 45370 57190 +1- 1 +-1 1 +.names 446 45364 +0 1 +.names 45364 45365 +1 1 +.names 45365 45366 +0 1 +.names 45339 45367 +1 1 +.names 45367 45368 +0 1 +.names 45366 45368 45369 +11 1 +.names 45352 45370 +0 1 +.names 8528 45371 +0 1 +.names 45371 45372 +1 1 +.names 45371 45377 45373 +11 1 +.names 45373 45374 +1 1 +.names 563 45375 +0 1 +.names 45375 45376 +1 1 +.names 45376 45377 +0 1 +.names 45381 45383 45378 +1- 1 +-1 1 +.names 45378 45379 +1 1 +.names 45374 45380 +0 1 +.names 45353 45380 45381 +11 1 +.names 127 45382 +0 1 +.names 8521 45382 45383 +11 1 +.names 462 45384 +0 1 +.names 45384 45385 +1 1 +.names 45389 45390 57191 +1- 1 +-1 1 +.names 45372 45387 +0 1 +.names 45385 45388 +0 1 +.names 45387 45388 45389 +11 1 +.names 45379 45390 +0 1 +.names 45371 45391 +1 1 +.names 45371 45396 45392 +11 1 +.names 45392 45393 +1 1 +.names 549 45394 +0 1 +.names 45394 45395 +1 1 +.names 45395 45396 +0 1 +.names 45400 45402 45397 +1- 1 +-1 1 +.names 45397 45398 +1 1 +.names 45393 45399 +0 1 +.names 45332 45399 45400 +11 1 +.names 113 45401 +0 1 +.names 8533 45401 45402 +11 1 +.names 45408 45409 57192 +1- 1 +-1 1 +.names 45391 45404 +0 1 +.names 448 45405 +0 1 +.names 45405 45406 +1 1 +.names 45406 45407 +0 1 +.names 45404 45407 45408 +11 1 +.names 45398 45409 +0 1 +.names 45415 45417 45410 +1- 1 +-1 1 +.names 45410 45411 +1 1 +.names 45418 45421 45412 +11 1 +.names 45412 45413 +1 1 +.names 45413 45414 +0 1 +.names 45332 45414 45415 +11 1 +.names 115 45416 +0 1 +.names 8533 45416 45417 +11 1 +.names 8526 45418 +0 1 +.names 551 45419 +0 1 +.names 45419 45420 +1 1 +.names 45420 45421 +0 1 +.names 45428 45429 57193 +1- 1 +-1 1 +.names 450 45423 +0 1 +.names 45423 45424 +1 1 +.names 45424 45425 +0 1 +.names 45418 45426 +1 1 +.names 45426 45427 +0 1 +.names 45425 45427 45428 +11 1 +.names 45411 45429 +0 1 +.names 45435 45437 45430 +1- 1 +-1 1 +.names 45430 45431 +1 1 +.names 45438 45441 45432 +11 1 +.names 45432 45433 +1 1 +.names 45433 45434 +0 1 +.names 45332 45434 45435 +11 1 +.names 122 45436 +0 1 +.names 8533 45436 45437 +11 1 +.names 8529 45438 +0 1 +.names 558 45439 +0 1 +.names 45439 45440 +1 1 +.names 45440 45441 +0 1 +.names 45448 45449 57194 +1- 1 +-1 1 +.names 457 45443 +0 1 +.names 45443 45444 +1 1 +.names 45444 45445 +0 1 +.names 45438 45446 +1 1 +.names 45446 45447 +0 1 +.names 45445 45447 45448 +11 1 +.names 45431 45449 +0 1 +.names 45456 45458 45450 +1- 1 +-1 1 +.names 45450 45451 +1 1 +.names 8532 45452 +0 1 +.names 45418 45461 45453 +11 1 +.names 45453 45454 +1 1 +.names 45454 45455 +0 1 +.names 45452 45455 45456 +11 1 +.names 135 45457 +0 1 +.names 8532 45457 45458 +11 1 +.names 571 45459 +0 1 +.names 45459 45460 +1 1 +.names 45460 45461 +0 1 +.names 45468 45469 57195 +1- 1 +-1 1 +.names 470 45463 +0 1 +.names 45463 45464 +1 1 +.names 45464 45465 +0 1 +.names 45418 45466 +1 1 +.names 45466 45467 +0 1 +.names 45465 45467 45468 +11 1 +.names 45451 45469 +0 1 +.names 45475 45477 45470 +1- 1 +-1 1 +.names 45470 45471 +1 1 +.names 45438 45480 45472 +11 1 +.names 45472 45473 +1 1 +.names 45473 45474 +0 1 +.names 45353 45474 45475 +11 1 +.names 124 45476 +0 1 +.names 8521 45476 45477 +11 1 +.names 560 45478 +0 1 +.names 45478 45479 +1 1 +.names 45479 45480 +0 1 +.names 45487 45488 57196 +1- 1 +-1 1 +.names 459 45482 +0 1 +.names 45482 45483 +1 1 +.names 45483 45484 +0 1 +.names 45438 45485 +1 1 +.names 45485 45486 +0 1 +.names 45484 45486 45487 +11 1 +.names 45471 45488 +0 1 +.names 45494 45496 45489 +1- 1 +-1 1 +.names 45489 45490 +1 1 +.names 45418 45499 45491 +11 1 +.names 45491 45492 +1 1 +.names 45492 45493 +0 1 +.names 45332 45493 45494 +11 1 +.names 105 45495 +0 1 +.names 8533 45495 45496 +11 1 +.names 541 45497 +0 1 +.names 45497 45498 +1 1 +.names 45498 45499 +0 1 +.names 45506 45507 57197 +1- 1 +-1 1 +.names 440 45501 +0 1 +.names 45501 45502 +1 1 +.names 45502 45503 +0 1 +.names 45418 45504 +1 1 +.names 45504 45505 +0 1 +.names 45503 45505 45506 +11 1 +.names 45490 45507 +0 1 +.names 45371 45508 +1 1 +.names 45371 45513 45509 +11 1 +.names 45509 45510 +1 1 +.names 550 45511 +0 1 +.names 45511 45512 +1 1 +.names 45512 45513 +0 1 +.names 45517 45519 45514 +1- 1 +-1 1 +.names 45514 45515 +1 1 +.names 45510 45516 +0 1 +.names 45452 45516 45517 +11 1 +.names 114 45518 +0 1 +.names 8532 45518 45519 +11 1 +.names 449 45520 +0 1 +.names 45520 45521 +1 1 +.names 45525 45526 57198 +1- 1 +-1 1 +.names 45508 45523 +0 1 +.names 45521 45524 +0 1 +.names 45523 45524 45525 +11 1 +.names 45515 45526 +0 1 +.names 45371 45527 +1 1 +.names 45371 45532 45528 +11 1 +.names 45528 45529 +1 1 +.names 566 45530 +0 1 +.names 45530 45531 +1 1 +.names 45531 45532 +0 1 +.names 45536 45538 45533 +1- 1 +-1 1 +.names 45533 45534 +1 1 +.names 45529 45535 +0 1 +.names 45353 45535 45536 +11 1 +.names 130 45537 +0 1 +.names 8521 45537 45538 +11 1 +.names 465 45539 +0 1 +.names 45539 45540 +1 1 +.names 45544 45545 57199 +1- 1 +-1 1 +.names 45527 45542 +0 1 +.names 45540 45543 +0 1 +.names 45542 45543 45544 +11 1 +.names 45534 45545 +0 1 +.names 45551 45553 45546 +1- 1 +-1 1 +.names 45546 45547 +1 1 +.names 45418 45556 45548 +11 1 +.names 45548 45549 +1 1 +.names 45549 45550 +0 1 +.names 45332 45550 45551 +11 1 +.names 116 45552 +0 1 +.names 8533 45552 45553 +11 1 +.names 552 45554 +0 1 +.names 45554 45555 +1 1 +.names 45555 45556 +0 1 +.names 45563 45564 57200 +1- 1 +-1 1 +.names 451 45558 +0 1 +.names 45558 45559 +1 1 +.names 45559 45560 +0 1 +.names 45418 45561 +1 1 +.names 45561 45562 +0 1 +.names 45560 45562 45563 +11 1 +.names 45547 45564 +0 1 +.names 45570 45572 45565 +1- 1 +-1 1 +.names 45565 45566 +1 1 +.names 45418 45575 45567 +11 1 +.names 45567 45568 +1 1 +.names 45568 45569 +0 1 +.names 45353 45569 45570 +11 1 +.names 129 45571 +0 1 +.names 8521 45571 45572 +11 1 +.names 565 45573 +0 1 +.names 45573 45574 +1 1 +.names 45574 45575 +0 1 +.names 45582 45583 57201 +1- 1 +-1 1 +.names 464 45577 +0 1 +.names 45577 45578 +1 1 +.names 45578 45579 +0 1 +.names 45418 45580 +1 1 +.names 45580 45581 +0 1 +.names 45579 45581 45582 +11 1 +.names 45566 45583 +0 1 +.names 45589 45591 45584 +1- 1 +-1 1 +.names 45584 45585 +1 1 +.names 45418 45594 45586 +11 1 +.names 45586 45587 +1 1 +.names 45587 45588 +0 1 +.names 45353 45588 45589 +11 1 +.names 112 45590 +0 1 +.names 8521 45590 45591 +11 1 +.names 548 45592 +0 1 +.names 45592 45593 +1 1 +.names 45593 45594 +0 1 +.names 45601 45602 57202 +1- 1 +-1 1 +.names 447 45596 +0 1 +.names 45596 45597 +1 1 +.names 45597 45598 +0 1 +.names 45418 45599 +1 1 +.names 45599 45600 +0 1 +.names 45598 45600 45601 +11 1 +.names 45585 45602 +0 1 +.names 45608 45610 45603 +1- 1 +-1 1 +.names 45603 45604 +1 1 +.names 45438 45613 45605 +11 1 +.names 45605 45606 +1 1 +.names 45606 45607 +0 1 +.names 45353 45607 45608 +11 1 +.names 123 45609 +0 1 +.names 8521 45609 45610 +11 1 +.names 559 45611 +0 1 +.names 45611 45612 +1 1 +.names 45612 45613 +0 1 +.names 45620 45621 57203 +1- 1 +-1 1 +.names 458 45615 +0 1 +.names 45615 45616 +1 1 +.names 45616 45617 +0 1 +.names 45438 45618 +1 1 +.names 45618 45619 +0 1 +.names 45617 45619 45620 +11 1 +.names 45604 45621 +0 1 +.names 45627 45629 45622 +1- 1 +-1 1 +.names 45622 45623 +1 1 +.names 45339 45632 45624 +11 1 +.names 45624 45625 +1 1 +.names 45625 45626 +0 1 +.names 45452 45626 45627 +11 1 +.names 121 45628 +0 1 +.names 8532 45628 45629 +11 1 +.names 557 45630 +0 1 +.names 45630 45631 +1 1 +.names 45631 45632 +0 1 +.names 45639 45640 57204 +1- 1 +-1 1 +.names 456 45634 +0 1 +.names 45634 45635 +1 1 +.names 45635 45636 +0 1 +.names 45339 45637 +1 1 +.names 45637 45638 +0 1 +.names 45636 45638 45639 +11 1 +.names 45623 45640 +0 1 +.names 45646 45648 45641 +1- 1 +-1 1 +.names 45641 45642 +1 1 +.names 45418 45651 45643 +11 1 +.names 45643 45644 +1 1 +.names 45644 45645 +0 1 +.names 45452 45645 45646 +11 1 +.names 128 45647 +0 1 +.names 8532 45647 45648 +11 1 +.names 564 45649 +0 1 +.names 45649 45650 +1 1 +.names 45650 45651 +0 1 +.names 45658 45659 57205 +1- 1 +-1 1 +.names 45418 45653 +1 1 +.names 45653 45654 +0 1 +.names 463 45655 +0 1 +.names 45655 45656 +1 1 +.names 45656 45657 +0 1 +.names 45654 45657 45658 +11 1 +.names 45642 45659 +0 1 +.names 45371 45660 +1 1 +.names 45371 45665 45661 +11 1 +.names 45661 45662 +1 1 +.names 572 45663 +0 1 +.names 45663 45664 +1 1 +.names 45664 45665 +0 1 +.names 45669 45671 45666 +1- 1 +-1 1 +.names 45666 45667 +1 1 +.names 45662 45668 +0 1 +.names 45332 45668 45669 +11 1 +.names 136 45670 +0 1 +.names 8533 45670 45671 +11 1 +.names 471 45672 +0 1 +.names 45672 45673 +1 1 +.names 45677 45678 57206 +1- 1 +-1 1 +.names 45660 45675 +0 1 +.names 45673 45676 +0 1 +.names 45675 45676 45677 +11 1 +.names 45667 45678 +0 1 +.names 45684 45686 45679 +1- 1 +-1 1 +.names 45679 45680 +1 1 +.names 45371 45689 45681 +11 1 +.names 45681 45682 +1 1 +.names 45682 45683 +0 1 +.names 45332 45683 45684 +11 1 +.names 107 45685 +0 1 +.names 8533 45685 45686 +11 1 +.names 543 45687 +0 1 +.names 45687 45688 +1 1 +.names 45688 45689 +0 1 +.names 45696 45697 57207 +1- 1 +-1 1 +.names 442 45691 +0 1 +.names 45691 45692 +1 1 +.names 45692 45693 +0 1 +.names 45371 45694 +1 1 +.names 45694 45695 +0 1 +.names 45693 45695 45696 +11 1 +.names 45680 45697 +0 1 +.names 45703 45705 45698 +1- 1 +-1 1 +.names 45698 45699 +1 1 +.names 45438 45708 45700 +11 1 +.names 45700 45701 +1 1 +.names 45701 45702 +0 1 +.names 45452 45702 45703 +11 1 +.names 110 45704 +0 1 +.names 8532 45704 45705 +11 1 +.names 546 45706 +0 1 +.names 45706 45707 +1 1 +.names 45707 45708 +0 1 +.names 45715 45716 57208 +1- 1 +-1 1 +.names 445 45710 +0 1 +.names 45710 45711 +1 1 +.names 45711 45712 +0 1 +.names 45438 45713 +1 1 +.names 45713 45714 +0 1 +.names 45712 45714 45715 +11 1 +.names 45699 45716 +0 1 +.names 45722 45724 45717 +1- 1 +-1 1 +.names 45717 45718 +1 1 +.names 45438 45727 45719 +11 1 +.names 45719 45720 +1 1 +.names 45720 45721 +0 1 +.names 45452 45721 45722 +11 1 +.names 126 45723 +0 1 +.names 8532 45723 45724 +11 1 +.names 562 45725 +0 1 +.names 45725 45726 +1 1 +.names 45726 45727 +0 1 +.names 45734 45735 57209 +1- 1 +-1 1 +.names 461 45729 +0 1 +.names 45729 45730 +1 1 +.names 45730 45731 +0 1 +.names 45438 45732 +1 1 +.names 45732 45733 +0 1 +.names 45731 45733 45734 +11 1 +.names 45718 45735 +0 1 +.names 45741 45743 45736 +1- 1 +-1 1 +.names 45736 45737 +1 1 +.names 45438 45746 45738 +11 1 +.names 45738 45739 +1 1 +.names 45739 45740 +0 1 +.names 45332 45740 45741 +11 1 +.names 118 45742 +0 1 +.names 8533 45742 45743 +11 1 +.names 554 45744 +0 1 +.names 45744 45745 +1 1 +.names 45745 45746 +0 1 +.names 45753 45754 57210 +1- 1 +-1 1 +.names 453 45748 +0 1 +.names 45748 45749 +1 1 +.names 45749 45750 +0 1 +.names 45438 45751 +1 1 +.names 45751 45752 +0 1 +.names 45750 45752 45753 +11 1 +.names 45737 45754 +0 1 +.names 45760 45762 45755 +1- 1 +-1 1 +.names 45755 45756 +1 1 +.names 45371 45765 45757 +11 1 +.names 45757 45758 +1 1 +.names 45758 45759 +0 1 +.names 45353 45759 45760 +11 1 +.names 119 45761 +0 1 +.names 8521 45761 45762 +11 1 +.names 555 45763 +0 1 +.names 45763 45764 +1 1 +.names 45764 45765 +0 1 +.names 45772 45773 57211 +1- 1 +-1 1 +.names 45371 45767 +1 1 +.names 45767 45768 +0 1 +.names 454 45769 +0 1 +.names 45769 45770 +1 1 +.names 45770 45771 +0 1 +.names 45768 45771 45772 +11 1 +.names 45756 45773 +0 1 +.names 45371 45774 +1 1 +.names 45371 45779 45775 +11 1 +.names 45775 45776 +1 1 +.names 569 45777 +0 1 +.names 45777 45778 +1 1 +.names 45778 45779 +0 1 +.names 45783 45785 45780 +1- 1 +-1 1 +.names 45780 45781 +1 1 +.names 45776 45782 +0 1 +.names 45452 45782 45783 +11 1 +.names 133 45784 +0 1 +.names 8532 45784 45785 +11 1 +.names 468 45786 +0 1 +.names 45786 45787 +1 1 +.names 45791 45792 57212 +1- 1 +-1 1 +.names 45774 45789 +0 1 +.names 45787 45790 +0 1 +.names 45789 45790 45791 +11 1 +.names 45781 45792 +0 1 +.names 45798 45800 45793 +1- 1 +-1 1 +.names 45793 45794 +1 1 +.names 45418 45803 45795 +11 1 +.names 45795 45796 +1 1 +.names 45796 45797 +0 1 +.names 45452 45797 45798 +11 1 +.names 117 45799 +0 1 +.names 8532 45799 45800 +11 1 +.names 553 45801 +0 1 +.names 45801 45802 +1 1 +.names 45802 45803 +0 1 +.names 45810 45811 57213 +1- 1 +-1 1 +.names 452 45805 +0 1 +.names 45805 45806 +1 1 +.names 45806 45807 +0 1 +.names 45418 45808 +1 1 +.names 45808 45809 +0 1 +.names 45807 45809 45810 +11 1 +.names 45794 45811 +0 1 +.names 45817 45819 45812 +1- 1 +-1 1 +.names 45812 45813 +1 1 +.names 45438 45822 45814 +11 1 +.names 45814 45815 +1 1 +.names 45815 45816 +0 1 +.names 45452 45816 45817 +11 1 +.names 131 45818 +0 1 +.names 8532 45818 45819 +11 1 +.names 567 45820 +0 1 +.names 45820 45821 +1 1 +.names 45821 45822 +0 1 +.names 45829 45830 57214 +1- 1 +-1 1 +.names 466 45824 +0 1 +.names 45824 45825 +1 1 +.names 45825 45826 +0 1 +.names 45438 45827 +1 1 +.names 45827 45828 +0 1 +.names 45826 45828 45829 +11 1 +.names 45813 45830 +0 1 +.names 45371 45831 +1 1 +.names 45371 45836 45832 +11 1 +.names 45832 45833 +1 1 +.names 568 45834 +0 1 +.names 45834 45835 +1 1 +.names 45835 45836 +0 1 +.names 45840 45842 45837 +1- 1 +-1 1 +.names 45837 45838 +1 1 +.names 45833 45839 +0 1 +.names 45332 45839 45840 +11 1 +.names 132 45841 +0 1 +.names 8533 45841 45842 +11 1 +.names 467 45843 +0 1 +.names 45843 45844 +1 1 +.names 45848 45849 57215 +1- 1 +-1 1 +.names 45831 45846 +0 1 +.names 45844 45847 +0 1 +.names 45846 45847 45848 +11 1 +.names 45838 45849 +0 1 +.names 45855 45857 45850 +1- 1 +-1 1 +.names 45850 45851 +1 1 +.names 45438 45860 45852 +11 1 +.names 45852 45853 +1 1 +.names 45853 45854 +0 1 +.names 45452 45854 45855 +11 1 +.names 108 45856 +0 1 +.names 8532 45856 45857 +11 1 +.names 544 45858 +0 1 +.names 45858 45859 +1 1 +.names 45859 45860 +0 1 +.names 45867 45868 57216 +1- 1 +-1 1 +.names 443 45862 +0 1 +.names 45862 45863 +1 1 +.names 45863 45864 +0 1 +.names 45438 45865 +1 1 +.names 45865 45866 +0 1 +.names 45864 45866 45867 +11 1 +.names 45851 45868 +0 1 +.names 45874 45876 45869 +1- 1 +-1 1 +.names 45869 45870 +1 1 +.names 45438 45879 45871 +11 1 +.names 45871 45872 +1 1 +.names 45872 45873 +0 1 +.names 45353 45873 45874 +11 1 +.names 109 45875 +0 1 +.names 8521 45875 45876 +11 1 +.names 545 45877 +0 1 +.names 45877 45878 +1 1 +.names 45878 45879 +0 1 +.names 45886 45887 57217 +1- 1 +-1 1 +.names 444 45881 +0 1 +.names 45881 45882 +1 1 +.names 45882 45883 +0 1 +.names 45438 45884 +1 1 +.names 45884 45885 +0 1 +.names 45883 45885 45886 +11 1 +.names 45870 45887 +0 1 +.names 45371 45888 +1 1 +.names 45371 45893 45889 +11 1 +.names 45889 45890 +1 1 +.names 556 45891 +0 1 +.names 45891 45892 +1 1 +.names 45892 45893 +0 1 +.names 45897 45899 45894 +1- 1 +-1 1 +.names 45894 45895 +1 1 +.names 45890 45896 +0 1 +.names 45452 45896 45897 +11 1 +.names 120 45898 +0 1 +.names 8532 45898 45899 +11 1 +.names 45905 45906 57218 +1- 1 +-1 1 +.names 45888 45901 +0 1 +.names 455 45902 +0 1 +.names 45902 45903 +1 1 +.names 45903 45904 +0 1 +.names 45901 45904 45905 +11 1 +.names 45895 45906 +0 1 +.names 45912 45914 45907 +1- 1 +-1 1 +.names 45907 45908 +1 1 +.names 45339 45917 45909 +11 1 +.names 45909 45910 +1 1 +.names 45910 45911 +0 1 +.names 45353 45911 45912 +11 1 +.names 125 45913 +0 1 +.names 8521 45913 45914 +11 1 +.names 561 45915 +0 1 +.names 45915 45916 +1 1 +.names 45916 45917 +0 1 +.names 45924 45925 57219 +1- 1 +-1 1 +.names 460 45919 +0 1 +.names 45919 45920 +1 1 +.names 45920 45921 +0 1 +.names 45339 45922 +1 1 +.names 45922 45923 +0 1 +.names 45921 45923 45924 +11 1 +.names 45908 45925 +0 1 +.names 45931 45933 45926 +1- 1 +-1 1 +.names 45926 45927 +1 1 +.names 45418 45936 45928 +11 1 +.names 45928 45929 +1 1 +.names 45929 45930 +0 1 +.names 45332 45930 45931 +11 1 +.names 134 45932 +0 1 +.names 8533 45932 45933 +11 1 +.names 570 45934 +0 1 +.names 45934 45935 +1 1 +.names 45935 45936 +0 1 +.names 45943 45944 57220 +1- 1 +-1 1 +.names 469 45938 +0 1 +.names 45938 45939 +1 1 +.names 45939 45940 +0 1 +.names 45418 45941 +1 1 +.names 45941 45942 +0 1 +.names 45940 45942 45943 +11 1 +.names 45927 45944 +0 1 +.names 45950 45954 57221 +1- 1 +-1 1 +.names 8545 45946 +0 1 +.names 57190 45947 +0 1 +.names 45947 45948 +1 1 +.names 45948 45949 +0 1 +.names 45946 45949 45950 +11 1 +.names 1474 45951 +0 1 +.names 45951 45952 +1 1 +.names 45952 45953 +0 1 +.names 8545 45953 45954 +11 1 +.names 45960 45964 57222 +1- 1 +-1 1 +.names 8539 45956 +0 1 +.names 57191 45957 +0 1 +.names 45957 45958 +1 1 +.names 45958 45959 +0 1 +.names 45956 45959 45960 +11 1 +.names 1475 45961 +0 1 +.names 45961 45962 +1 1 +.names 45962 45963 +0 1 +.names 8539 45963 45964 +11 1 +.names 45969 45973 57223 +1- 1 +-1 1 +.names 57194 45966 +0 1 +.names 45966 45967 +1 1 +.names 45967 45968 +0 1 +.names 45946 45968 45969 +11 1 +.names 1476 45970 +0 1 +.names 45970 45971 +1 1 +.names 45971 45972 +0 1 +.names 8545 45972 45973 +11 1 +.names 45978 45982 57224 +1- 1 +-1 1 +.names 57195 45975 +0 1 +.names 45975 45976 +1 1 +.names 45976 45977 +0 1 +.names 45956 45977 45978 +11 1 +.names 1477 45979 +0 1 +.names 45979 45980 +1 1 +.names 45980 45981 +0 1 +.names 8539 45981 45982 +11 1 +.names 45988 45992 57225 +1- 1 +-1 1 +.names 8540 45984 +0 1 +.names 57197 45985 +0 1 +.names 45985 45986 +1 1 +.names 45986 45987 +0 1 +.names 45984 45987 45988 +11 1 +.names 1478 45989 +0 1 +.names 45989 45990 +1 1 +.names 45990 45991 +0 1 +.names 8540 45991 45992 +11 1 +.names 45998 46002 57226 +1- 1 +-1 1 +.names 8542 45994 +0 1 +.names 57189 45995 +0 1 +.names 45995 45996 +1 1 +.names 45996 45997 +0 1 +.names 45994 45997 45998 +11 1 +.names 1479 45999 +0 1 +.names 45999 46000 +1 1 +.names 46000 46001 +0 1 +.names 8542 46001 46002 +11 1 +.names 46007 46011 57227 +1- 1 +-1 1 +.names 57192 46004 +0 1 +.names 46004 46005 +1 1 +.names 46005 46006 +0 1 +.names 45994 46006 46007 +11 1 +.names 1480 46008 +0 1 +.names 46008 46009 +1 1 +.names 46009 46010 +0 1 +.names 8542 46010 46011 +11 1 +.names 46016 46020 57228 +1- 1 +-1 1 +.names 57193 46013 +0 1 +.names 46013 46014 +1 1 +.names 46014 46015 +0 1 +.names 45956 46015 46016 +11 1 +.names 1481 46017 +0 1 +.names 46017 46018 +1 1 +.names 46018 46019 +0 1 +.names 8539 46019 46020 +11 1 +.names 46025 46029 57229 +1- 1 +-1 1 +.names 57196 46022 +0 1 +.names 46022 46023 +1 1 +.names 46023 46024 +0 1 +.names 45994 46024 46025 +11 1 +.names 1482 46026 +0 1 +.names 46026 46027 +1 1 +.names 46027 46028 +0 1 +.names 8542 46028 46029 +11 1 +.names 46034 46038 57230 +1- 1 +-1 1 +.names 57198 46031 +0 1 +.names 46031 46032 +1 1 +.names 46032 46033 +0 1 +.names 45946 46033 46034 +11 1 +.names 1483 46035 +0 1 +.names 46035 46036 +1 1 +.names 46036 46037 +0 1 +.names 8545 46037 46038 +11 1 +.names 46044 46048 57231 +1- 1 +-1 1 +.names 8544 46040 +0 1 +.names 57199 46041 +0 1 +.names 46041 46042 +1 1 +.names 46042 46043 +0 1 +.names 46040 46043 46044 +11 1 +.names 1484 46045 +0 1 +.names 46045 46046 +1 1 +.names 46046 46047 +0 1 +.names 8544 46047 46048 +11 1 +.names 46053 46057 57232 +1- 1 +-1 1 +.names 57200 46050 +0 1 +.names 46050 46051 +1 1 +.names 46051 46052 +0 1 +.names 45984 46052 46053 +11 1 +.names 1485 46054 +0 1 +.names 46054 46055 +1 1 +.names 46055 46056 +0 1 +.names 8540 46056 46057 +11 1 +.names 46062 46066 57233 +1- 1 +-1 1 +.names 57201 46059 +0 1 +.names 46059 46060 +1 1 +.names 46060 46061 +0 1 +.names 45984 46061 46062 +11 1 +.names 1486 46063 +0 1 +.names 46063 46064 +1 1 +.names 46064 46065 +0 1 +.names 8540 46065 46066 +11 1 +.names 46071 46075 57234 +1- 1 +-1 1 +.names 57207 46068 +0 1 +.names 46068 46069 +1 1 +.names 46069 46070 +0 1 +.names 45984 46070 46071 +11 1 +.names 1487 46072 +0 1 +.names 46072 46073 +1 1 +.names 46073 46074 +0 1 +.names 8540 46074 46075 +11 1 +.names 46080 46084 57235 +1- 1 +-1 1 +.names 57208 46077 +0 1 +.names 46077 46078 +1 1 +.names 46078 46079 +0 1 +.names 46040 46079 46080 +11 1 +.names 1488 46081 +0 1 +.names 46081 46082 +1 1 +.names 46082 46083 +0 1 +.names 8544 46083 46084 +11 1 +.names 46089 46093 57236 +1- 1 +-1 1 +.names 57202 46086 +0 1 +.names 46086 46087 +1 1 +.names 46087 46088 +0 1 +.names 45956 46088 46089 +11 1 +.names 1489 46090 +0 1 +.names 46090 46091 +1 1 +.names 46091 46092 +0 1 +.names 8539 46092 46093 +11 1 +.names 46098 46102 57237 +1- 1 +-1 1 +.names 57203 46095 +0 1 +.names 46095 46096 +1 1 +.names 46096 46097 +0 1 +.names 46040 46097 46098 +11 1 +.names 1490 46099 +0 1 +.names 46099 46100 +1 1 +.names 46100 46101 +0 1 +.names 8544 46101 46102 +11 1 +.names 46107 46111 57238 +1- 1 +-1 1 +.names 57204 46104 +0 1 +.names 46104 46105 +1 1 +.names 46105 46106 +0 1 +.names 45994 46106 46107 +11 1 +.names 1491 46108 +0 1 +.names 46108 46109 +1 1 +.names 46109 46110 +0 1 +.names 8542 46110 46111 +11 1 +.names 46116 46120 57239 +1- 1 +-1 1 +.names 57205 46113 +0 1 +.names 46113 46114 +1 1 +.names 46114 46115 +0 1 +.names 45994 46115 46116 +11 1 +.names 1492 46117 +0 1 +.names 46117 46118 +1 1 +.names 46118 46119 +0 1 +.names 8542 46119 46120 +11 1 +.names 46125 46129 57240 +1- 1 +-1 1 +.names 57206 46122 +0 1 +.names 46122 46123 +1 1 +.names 46123 46124 +0 1 +.names 45946 46124 46125 +11 1 +.names 1493 46126 +0 1 +.names 46126 46127 +1 1 +.names 46127 46128 +0 1 +.names 8545 46128 46129 +11 1 +.names 46135 46139 57241 +1- 1 +-1 1 +.names 8543 46131 +0 1 +.names 57209 46132 +0 1 +.names 46132 46133 +1 1 +.names 46133 46134 +0 1 +.names 46131 46134 46135 +11 1 +.names 1494 46136 +0 1 +.names 46136 46137 +1 1 +.names 46137 46138 +0 1 +.names 8543 46138 46139 +11 1 +.names 46144 46148 57242 +1- 1 +-1 1 +.names 57210 46141 +0 1 +.names 46141 46142 +1 1 +.names 46142 46143 +0 1 +.names 46131 46143 46144 +11 1 +.names 1495 46145 +0 1 +.names 46145 46146 +1 1 +.names 46146 46147 +0 1 +.names 8543 46147 46148 +11 1 +.names 46153 46157 57243 +1- 1 +-1 1 +.names 57211 46150 +0 1 +.names 46150 46151 +1 1 +.names 46151 46152 +0 1 +.names 46040 46152 46153 +11 1 +.names 1496 46154 +0 1 +.names 46154 46155 +1 1 +.names 46155 46156 +0 1 +.names 8544 46156 46157 +11 1 +.names 46162 46166 57244 +1- 1 +-1 1 +.names 57212 46159 +0 1 +.names 46159 46160 +1 1 +.names 46160 46161 +0 1 +.names 45956 46161 46162 +11 1 +.names 1497 46163 +0 1 +.names 46163 46164 +1 1 +.names 46164 46165 +0 1 +.names 8539 46165 46166 +11 1 +.names 46171 46175 57245 +1- 1 +-1 1 +.names 57213 46168 +0 1 +.names 46168 46169 +1 1 +.names 46169 46170 +0 1 +.names 45984 46170 46171 +11 1 +.names 1498 46172 +0 1 +.names 46172 46173 +1 1 +.names 46173 46174 +0 1 +.names 8540 46174 46175 +11 1 +.names 46180 46184 57246 +1- 1 +-1 1 +.names 57214 46177 +0 1 +.names 46177 46178 +1 1 +.names 46178 46179 +0 1 +.names 45946 46179 46180 +11 1 +.names 1499 46181 +0 1 +.names 46181 46182 +1 1 +.names 46182 46183 +0 1 +.names 8545 46183 46184 +11 1 +.names 46189 46193 57247 +1- 1 +-1 1 +.names 57215 46186 +0 1 +.names 46186 46187 +1 1 +.names 46187 46188 +0 1 +.names 45946 46188 46189 +11 1 +.names 1500 46190 +0 1 +.names 46190 46191 +1 1 +.names 46191 46192 +0 1 +.names 8545 46192 46193 +11 1 +.names 46198 46202 57248 +1- 1 +-1 1 +.names 57216 46195 +0 1 +.names 46195 46196 +1 1 +.names 46196 46197 +0 1 +.names 46131 46197 46198 +11 1 +.names 1501 46199 +0 1 +.names 46199 46200 +1 1 +.names 46200 46201 +0 1 +.names 8543 46201 46202 +11 1 +.names 46207 46211 57249 +1- 1 +-1 1 +.names 57217 46204 +0 1 +.names 46204 46205 +1 1 +.names 46205 46206 +0 1 +.names 46131 46206 46207 +11 1 +.names 1502 46208 +0 1 +.names 46208 46209 +1 1 +.names 46209 46210 +0 1 +.names 8543 46210 46211 +11 1 +.names 46216 46220 57250 +1- 1 +-1 1 +.names 57218 46213 +0 1 +.names 46213 46214 +1 1 +.names 46214 46215 +0 1 +.names 46131 46215 46216 +11 1 +.names 1503 46217 +0 1 +.names 46217 46218 +1 1 +.names 46218 46219 +0 1 +.names 8543 46219 46220 +11 1 +.names 46225 46229 57251 +1- 1 +-1 1 +.names 57219 46222 +0 1 +.names 46222 46223 +1 1 +.names 46223 46224 +0 1 +.names 46040 46224 46225 +11 1 +.names 1504 46226 +0 1 +.names 46226 46227 +1 1 +.names 46227 46228 +0 1 +.names 8544 46228 46229 +11 1 +.names 46234 46238 57252 +1- 1 +-1 1 +.names 57220 46231 +0 1 +.names 46231 46232 +1 1 +.names 46232 46233 +0 1 +.names 46040 46233 46234 +11 1 +.names 1505 46235 +0 1 +.names 46235 46236 +1 1 +.names 46236 46237 +0 1 +.names 8544 46237 46238 +11 1 +.names 8557 46239 +0 1 +.names 1506 46240 +0 1 +.names 46240 46241 +1 1 +.names 46241 46242 +0 1 +.names 46239 46242 46243 +11 1 +.names 45074 46244 +1 1 +.names 46244 46245 +0 1 +.names 8557 46245 46246 +11 1 +.names 8551 46247 +0 1 +.names 1507 46248 +0 1 +.names 46248 46249 +1 1 +.names 46249 46250 +0 1 +.names 46247 46250 46251 +11 1 +.names 45083 46252 +1 1 +.names 46252 46253 +0 1 +.names 8551 46253 46254 +11 1 +.names 1508 46255 +0 1 +.names 46255 46256 +1 1 +.names 46256 46257 +0 1 +.names 46239 46257 46258 +11 1 +.names 45091 46259 +1 1 +.names 46259 46260 +0 1 +.names 8557 46260 46261 +11 1 +.names 1509 46262 +0 1 +.names 46262 46263 +1 1 +.names 46263 46264 +0 1 +.names 46247 46264 46265 +11 1 +.names 45099 46266 +1 1 +.names 46266 46267 +0 1 +.names 8551 46267 46268 +11 1 +.names 8552 46269 +0 1 +.names 1510 46270 +0 1 +.names 46270 46271 +1 1 +.names 46271 46272 +0 1 +.names 46269 46272 46273 +11 1 +.names 3116 46274 +1 1 +.names 46274 46275 +0 1 +.names 8552 46275 46276 +11 1 +.names 8554 46277 +0 1 +.names 1511 46278 +0 1 +.names 46278 46279 +1 1 +.names 46279 46280 +0 1 +.names 46277 46280 46281 +11 1 +.names 45116 46282 +1 1 +.names 46282 46283 +0 1 +.names 8554 46283 46284 +11 1 +.names 1512 46285 +0 1 +.names 46285 46286 +1 1 +.names 46286 46287 +0 1 +.names 46277 46287 46288 +11 1 +.names 45124 46289 +1 1 +.names 46289 46290 +0 1 +.names 8554 46290 46291 +11 1 +.names 1513 46292 +0 1 +.names 46292 46293 +1 1 +.names 46293 46294 +0 1 +.names 46247 46294 46295 +11 1 +.names 45132 46296 +1 1 +.names 46296 46297 +0 1 +.names 8551 46297 46298 +11 1 +.names 1514 46299 +0 1 +.names 46299 46300 +1 1 +.names 46300 46301 +0 1 +.names 46277 46301 46302 +11 1 +.names 45140 46303 +1 1 +.names 46303 46304 +0 1 +.names 8554 46304 46305 +11 1 +.names 1515 46306 +0 1 +.names 46306 46307 +1 1 +.names 46307 46308 +0 1 +.names 46239 46308 46309 +11 1 +.names 45148 46310 +1 1 +.names 46310 46311 +0 1 +.names 8557 46311 46312 +11 1 +.names 8556 46313 +0 1 +.names 1516 46314 +0 1 +.names 46314 46315 +1 1 +.names 46315 46316 +0 1 +.names 46313 46316 46317 +11 1 +.names 45157 46318 +1 1 +.names 46318 46319 +0 1 +.names 8556 46319 46320 +11 1 +.names 1517 46321 +0 1 +.names 46321 46322 +1 1 +.names 46322 46323 +0 1 +.names 46269 46323 46324 +11 1 +.names 45165 46325 +1 1 +.names 46325 46326 +0 1 +.names 8552 46326 46327 +11 1 +.names 1518 46328 +0 1 +.names 46328 46329 +1 1 +.names 46329 46330 +0 1 +.names 46269 46330 46331 +11 1 +.names 45173 46332 +1 1 +.names 46332 46333 +0 1 +.names 8552 46333 46334 +11 1 +.names 1519 46335 +0 1 +.names 46335 46336 +1 1 +.names 46336 46337 +0 1 +.names 46269 46337 46338 +11 1 +.names 45181 46339 +1 1 +.names 46339 46340 +0 1 +.names 8552 46340 46341 +11 1 +.names 1520 46342 +0 1 +.names 46342 46343 +1 1 +.names 46343 46344 +0 1 +.names 46313 46344 46345 +11 1 +.names 45189 46346 +1 1 +.names 46346 46347 +0 1 +.names 8556 46347 46348 +11 1 +.names 1521 46349 +0 1 +.names 46349 46350 +1 1 +.names 46350 46351 +0 1 +.names 46247 46351 46352 +11 1 +.names 45197 46353 +1 1 +.names 46353 46354 +0 1 +.names 8551 46354 46355 +11 1 +.names 1522 46356 +0 1 +.names 46356 46357 +1 1 +.names 46357 46358 +0 1 +.names 46313 46358 46359 +11 1 +.names 45205 46360 +1 1 +.names 46360 46361 +0 1 +.names 8556 46361 46362 +11 1 +.names 1523 46363 +0 1 +.names 46363 46364 +1 1 +.names 46364 46365 +0 1 +.names 46277 46365 46366 +11 1 +.names 45213 46367 +1 1 +.names 46367 46368 +0 1 +.names 8554 46368 46369 +11 1 +.names 1524 46370 +0 1 +.names 46370 46371 +1 1 +.names 46371 46372 +0 1 +.names 46277 46372 46373 +11 1 +.names 45221 46374 +1 1 +.names 46374 46375 +0 1 +.names 8554 46375 46376 +11 1 +.names 1525 46377 +0 1 +.names 46377 46378 +1 1 +.names 46378 46379 +0 1 +.names 46239 46379 46380 +11 1 +.names 45229 46381 +1 1 +.names 46381 46382 +0 1 +.names 8557 46382 46383 +11 1 +.names 8555 46384 +0 1 +.names 1526 46385 +0 1 +.names 46385 46386 +1 1 +.names 46386 46387 +0 1 +.names 46384 46387 46388 +11 1 +.names 45238 46389 +1 1 +.names 46389 46390 +0 1 +.names 8555 46390 46391 +11 1 +.names 1527 46392 +0 1 +.names 46392 46393 +1 1 +.names 46393 46394 +0 1 +.names 46384 46394 46395 +11 1 +.names 45246 46396 +1 1 +.names 46396 46397 +0 1 +.names 8555 46397 46398 +11 1 +.names 1528 46399 +0 1 +.names 46399 46400 +1 1 +.names 46400 46401 +0 1 +.names 46313 46401 46402 +11 1 +.names 45254 46403 +1 1 +.names 46403 46404 +0 1 +.names 8556 46404 46405 +11 1 +.names 1529 46406 +0 1 +.names 46406 46407 +1 1 +.names 46407 46408 +0 1 +.names 46247 46408 46409 +11 1 +.names 45262 46410 +1 1 +.names 46410 46411 +0 1 +.names 8551 46411 46412 +11 1 +.names 1530 46413 +0 1 +.names 46413 46414 +1 1 +.names 46414 46415 +0 1 +.names 46269 46415 46416 +11 1 +.names 45270 46417 +1 1 +.names 46417 46418 +0 1 +.names 8552 46418 46419 +11 1 +.names 1531 46420 +0 1 +.names 46420 46421 +1 1 +.names 46421 46422 +0 1 +.names 46239 46422 46423 +11 1 +.names 45278 46424 +1 1 +.names 46424 46425 +0 1 +.names 8557 46425 46426 +11 1 +.names 1532 46427 +0 1 +.names 46427 46428 +1 1 +.names 46428 46429 +0 1 +.names 46239 46429 46430 +11 1 +.names 45286 46431 +1 1 +.names 46431 46432 +0 1 +.names 8557 46432 46433 +11 1 +.names 1533 46434 +0 1 +.names 46434 46435 +1 1 +.names 46435 46436 +0 1 +.names 46384 46436 46437 +11 1 +.names 45294 46438 +1 1 +.names 46438 46439 +0 1 +.names 8555 46439 46440 +11 1 +.names 1534 46441 +0 1 +.names 46441 46442 +1 1 +.names 46442 46443 +0 1 +.names 46384 46443 46444 +11 1 +.names 45302 46445 +1 1 +.names 46445 46446 +0 1 +.names 8555 46446 46447 +11 1 +.names 1535 46448 +0 1 +.names 46448 46449 +1 1 +.names 46449 46450 +0 1 +.names 46384 46450 46451 +11 1 +.names 45310 46452 +1 1 +.names 46452 46453 +0 1 +.names 8555 46453 46454 +11 1 +.names 1536 46455 +0 1 +.names 46455 46456 +1 1 +.names 46456 46457 +0 1 +.names 46313 46457 46458 +11 1 +.names 45318 46459 +1 1 +.names 46459 46460 +0 1 +.names 8556 46460 46461 +11 1 +.names 1537 46462 +0 1 +.names 46462 46463 +1 1 +.names 46463 46464 +0 1 +.names 46313 46464 46465 +11 1 +.names 45326 46466 +1 1 +.names 46466 46467 +0 1 +.names 8556 46467 46468 +11 1 +.names 46473 46476 57253 +1- 1 +-1 1 +.names 9440 46470 +0 1 +.names 14852 46471 +1 1 +.names 46471 46472 +0 1 +.names 46470 46472 46473 +11 1 +.names 14886 46474 +1 1 +.names 46474 46475 +0 1 +.names 9440 46475 46476 +11 1 +.names 46481 46484 57254 +1- 1 +-1 1 +.names 9434 46478 +0 1 +.names 44604 46479 +1 1 +.names 46479 46480 +0 1 +.names 46478 46480 46481 +11 1 +.names 2413 46482 +1 1 +.names 46482 46483 +0 1 +.names 9434 46483 46484 +11 1 +.names 46488 46491 57255 +1- 1 +-1 1 +.names 44569 46486 +1 1 +.names 46486 46487 +0 1 +.names 46470 46487 46488 +11 1 +.names 14886 46489 +1 1 +.names 46489 46490 +0 1 +.names 9440 46490 46491 +11 1 +.names 46496 46499 57256 +1- 1 +-1 1 +.names 9439 46493 +0 1 +.names 44613 46494 +1 1 +.names 46494 46495 +0 1 +.names 46493 46495 46496 +11 1 +.names 14886 46497 +1 1 +.names 46497 46498 +0 1 +.names 9439 46498 46499 +11 1 +.names 46503 46506 57257 +1- 1 +-1 1 +.names 14927 46501 +1 1 +.names 46501 46502 +0 1 +.names 46478 46502 46503 +11 1 +.names 14886 46504 +1 1 +.names 46504 46505 +0 1 +.names 9434 46505 46506 +11 1 +.names 46510 46513 57258 +1- 1 +-1 1 +.names 14832 46508 +1 1 +.names 46508 46509 +0 1 +.names 46478 46509 46510 +11 1 +.names 14886 46511 +1 1 +.names 46511 46512 +0 1 +.names 9434 46512 46513 +11 1 +.names 46517 46520 57259 +1- 1 +-1 1 +.names 14812 46515 +1 1 +.names 46515 46516 +0 1 +.names 46470 46516 46517 +11 1 +.names 14886 46518 +1 1 +.names 46518 46519 +0 1 +.names 9440 46519 46520 +11 1 +.names 46524 46527 57260 +1- 1 +-1 1 +.names 44674 46522 +1 1 +.names 46522 46523 +0 1 +.names 46493 46523 46524 +11 1 +.names 14886 46525 +1 1 +.names 46525 46526 +0 1 +.names 9439 46526 46527 +11 1 +.names 46531 46534 57261 +1- 1 +-1 1 +.names 14822 46529 +1 1 +.names 46529 46530 +0 1 +.names 46493 46530 46531 +11 1 +.names 14886 46532 +1 1 +.names 46532 46533 +0 1 +.names 9439 46533 46534 +11 1 +.names 46538 46541 57262 +1- 1 +-1 1 +.names 44725 46536 +1 1 +.names 46536 46537 +0 1 +.names 46470 46537 46538 +11 1 +.names 2413 46539 +1 1 +.names 46539 46540 +0 1 +.names 9440 46540 46541 +11 1 +.names 46545 46548 57263 +1- 1 +-1 1 +.names 14802 46543 +1 1 +.names 46543 46544 +0 1 +.names 46478 46544 46545 +11 1 +.names 14886 46546 +1 1 +.names 46546 46547 +0 1 +.names 9434 46547 46548 +11 1 +.names 46552 46555 57264 +1- 1 +-1 1 +.names 44716 46550 +1 1 +.names 46550 46551 +0 1 +.names 46493 46551 46552 +11 1 +.names 2413 46553 +1 1 +.names 46553 46554 +0 1 +.names 9439 46554 46555 +11 1 +.names 46559 46562 57265 +1- 1 +-1 1 +.names 14893 46557 +1 1 +.names 46557 46558 +0 1 +.names 46470 46558 46559 +11 1 +.names 14886 46560 +1 1 +.names 46560 46561 +0 1 +.names 9440 46561 46562 +11 1 +.names 46566 46569 57266 +1- 1 +-1 1 +.names 14862 46564 +1 1 +.names 46564 46565 +0 1 +.names 46493 46565 46566 +11 1 +.names 14886 46567 +1 1 +.names 46567 46568 +0 1 +.names 9439 46568 46569 +11 1 +.names 46573 46576 57267 +1- 1 +-1 1 +.names 14842 46571 +1 1 +.names 46571 46572 +0 1 +.names 46470 46572 46573 +11 1 +.names 14886 46574 +1 1 +.names 46574 46575 +0 1 +.names 9440 46575 46576 +11 1 +.names 46580 46583 57268 +1- 1 +-1 1 +.names 44758 46578 +1 1 +.names 46578 46579 +0 1 +.names 46478 46579 46580 +11 1 +.names 14886 46581 +1 1 +.names 46581 46582 +0 1 +.names 9434 46582 46583 +11 1 +.names 46587 46590 57269 +1- 1 +-1 1 +.names 44638 46585 +1 1 +.names 46585 46586 +0 1 +.names 46478 46586 46587 +11 1 +.names 14886 46588 +1 1 +.names 46588 46589 +0 1 +.names 9434 46589 46590 +11 1 +.names 46594 46597 57270 +1- 1 +-1 1 +.names 44587 46592 +1 1 +.names 46592 46593 +0 1 +.names 46493 46593 46594 +11 1 +.names 2413 46595 +1 1 +.names 46595 46596 +0 1 +.names 9439 46596 46597 +11 1 +.names 46601 46604 57271 +1- 1 +-1 1 +.names 44656 46599 +1 1 +.names 46599 46600 +0 1 +.names 46478 46600 46601 +11 1 +.names 2413 46602 +1 1 +.names 46602 46603 +0 1 +.names 9434 46603 46604 +11 1 +.names 46608 46611 57272 +1- 1 +-1 1 +.names 14792 46606 +1 1 +.names 46606 46607 +0 1 +.names 46470 46607 46608 +11 1 +.names 14886 46609 +1 1 +.names 46609 46610 +0 1 +.names 9440 46610 46611 +11 1 +.names 46615 46618 57273 +1- 1 +-1 1 +.names 44647 46613 +1 1 +.names 46613 46614 +0 1 +.names 46470 46614 46615 +11 1 +.names 14886 46616 +1 1 +.names 46616 46617 +0 1 +.names 9440 46617 46618 +11 1 +.names 46622 46625 57274 +1- 1 +-1 1 +.names 44527 46620 +1 1 +.names 46620 46621 +0 1 +.names 46493 46621 46622 +11 1 +.names 2413 46623 +1 1 +.names 46623 46624 +0 1 +.names 9439 46624 46625 +11 1 +.names 46629 46632 57275 +1- 1 +-1 1 +.names 57098 46627 +1 1 +.names 46627 46628 +0 1 +.names 46493 46628 46629 +11 1 +.names 14886 46630 +1 1 +.names 46630 46631 +0 1 +.names 9439 46631 46632 +11 1 +.names 46636 46639 57276 +1- 1 +-1 1 +.names 44699 46634 +1 1 +.names 46634 46635 +0 1 +.names 46478 46635 46636 +11 1 +.names 2413 46637 +1 1 +.names 46637 46638 +0 1 +.names 9434 46638 46639 +11 1 +.names 46643 46646 57277 +1- 1 +-1 1 +.names 44767 46641 +1 1 +.names 46641 46642 +0 1 +.names 46493 46642 46643 +11 1 +.names 2413 46644 +1 1 +.names 46644 46645 +0 1 +.names 9439 46645 46646 +11 1 +.names 46650 46653 57278 +1- 1 +-1 1 +.names 14882 46648 +1 1 +.names 46648 46649 +0 1 +.names 46478 46649 46650 +11 1 +.names 14886 46651 +1 1 +.names 46651 46652 +0 1 +.names 9434 46652 46653 +11 1 +.names 46657 46660 57279 +1- 1 +-1 1 +.names 14872 46655 +1 1 +.names 46655 46656 +0 1 +.names 46470 46656 46657 +11 1 +.names 14886 46658 +1 1 +.names 46658 46659 +0 1 +.names 9440 46659 46660 +11 1 +.names 46664 46667 57280 +1- 1 +-1 1 +.names 44518 46662 +1 1 +.names 46662 46663 +0 1 +.names 46470 46663 46664 +11 1 +.names 14886 46665 +1 1 +.names 46665 46666 +0 1 +.names 9440 46666 46667 +11 1 +.names 46671 46674 57281 +1- 1 +-1 1 +.names 14782 46669 +1 1 +.names 46669 46670 +0 1 +.names 46493 46670 46671 +11 1 +.names 2413 46672 +1 1 +.names 46672 46673 +0 1 +.names 9439 46673 46674 +11 1 +.names 46678 46681 57282 +1- 1 +-1 1 +.names 14760 46676 +1 1 +.names 46676 46677 +0 1 +.names 46478 46677 46678 +11 1 +.names 2413 46679 +1 1 +.names 46679 46680 +0 1 +.names 9434 46680 46681 +11 1 +.names 46686 46689 57283 +1- 1 +-1 1 +.names 9454 46683 +0 1 +.names 14852 46684 +1 1 +.names 46684 46685 +0 1 +.names 46683 46685 46686 +11 1 +.names 2413 46687 +1 1 +.names 46687 46688 +0 1 +.names 9454 46688 46689 +11 1 +.names 46694 46697 57284 +1- 1 +-1 1 +.names 9450 46691 +0 1 +.names 44604 46692 +1 1 +.names 46692 46693 +0 1 +.names 46691 46693 46694 +11 1 +.names 2413 46695 +1 1 +.names 46695 46696 +0 1 +.names 9450 46696 46697 +11 1 +.names 46701 46704 57285 +1- 1 +-1 1 +.names 44569 46699 +1 1 +.names 46699 46700 +0 1 +.names 46683 46700 46701 +11 1 +.names 2413 46702 +1 1 +.names 46702 46703 +0 1 +.names 9454 46703 46704 +11 1 +.names 46709 46712 57286 +1- 1 +-1 1 +.names 9453 46706 +0 1 +.names 44613 46707 +1 1 +.names 46707 46708 +0 1 +.names 46706 46708 46709 +11 1 +.names 2413 46710 +1 1 +.names 46710 46711 +0 1 +.names 9453 46711 46712 +11 1 +.names 46716 46719 57287 +1- 1 +-1 1 +.names 14927 46714 +1 1 +.names 46714 46715 +0 1 +.names 46706 46715 46716 +11 1 +.names 2413 46717 +1 1 +.names 46717 46718 +0 1 +.names 9453 46718 46719 +11 1 +.names 46723 46726 57288 +1- 1 +-1 1 +.names 14832 46721 +1 1 +.names 46721 46722 +0 1 +.names 46691 46722 46723 +11 1 +.names 2413 46724 +1 1 +.names 46724 46725 +0 1 +.names 9450 46725 46726 +11 1 +.names 46730 46733 57289 +1- 1 +-1 1 +.names 14812 46728 +1 1 +.names 46728 46729 +0 1 +.names 46706 46729 46730 +11 1 +.names 2413 46731 +1 1 +.names 46731 46732 +0 1 +.names 9453 46732 46733 +11 1 +.names 46737 46740 57290 +1- 1 +-1 1 +.names 44674 46735 +1 1 +.names 46735 46736 +0 1 +.names 46706 46736 46737 +11 1 +.names 2413 46738 +1 1 +.names 46738 46739 +0 1 +.names 9453 46739 46740 +11 1 +.names 46744 46747 57291 +1- 1 +-1 1 +.names 14822 46742 +1 1 +.names 46742 46743 +0 1 +.names 46691 46743 46744 +11 1 +.names 2413 46745 +1 1 +.names 46745 46746 +0 1 +.names 9450 46746 46747 +11 1 +.names 46751 46754 57292 +1- 1 +-1 1 +.names 44725 46749 +1 1 +.names 46749 46750 +0 1 +.names 46691 46750 46751 +11 1 +.names 2413 46752 +1 1 +.names 46752 46753 +0 1 +.names 9450 46753 46754 +11 1 +.names 46758 46761 57293 +1- 1 +-1 1 +.names 14802 46756 +1 1 +.names 46756 46757 +0 1 +.names 46683 46757 46758 +11 1 +.names 2413 46759 +1 1 +.names 46759 46760 +0 1 +.names 9454 46760 46761 +11 1 +.names 46765 46768 57294 +1- 1 +-1 1 +.names 44716 46763 +1 1 +.names 46763 46764 +0 1 +.names 46683 46764 46765 +11 1 +.names 2413 46766 +1 1 +.names 46766 46767 +0 1 +.names 9454 46767 46768 +11 1 +.names 46772 46775 57295 +1- 1 +-1 1 +.names 14893 46770 +1 1 +.names 46770 46771 +0 1 +.names 46683 46771 46772 +11 1 +.names 2413 46773 +1 1 +.names 46773 46774 +0 1 +.names 9454 46774 46775 +11 1 +.names 46779 46782 57296 +1- 1 +-1 1 +.names 14862 46777 +1 1 +.names 46777 46778 +0 1 +.names 46706 46778 46779 +11 1 +.names 2413 46780 +1 1 +.names 46780 46781 +0 1 +.names 9453 46781 46782 +11 1 +.names 46786 46789 57297 +1- 1 +-1 1 +.names 14842 46784 +1 1 +.names 46784 46785 +0 1 +.names 46683 46785 46786 +11 1 +.names 2413 46787 +1 1 +.names 46787 46788 +0 1 +.names 9454 46788 46789 +11 1 +.names 46793 46796 57298 +1- 1 +-1 1 +.names 44758 46791 +1 1 +.names 46791 46792 +0 1 +.names 46706 46792 46793 +11 1 +.names 2413 46794 +1 1 +.names 46794 46795 +0 1 +.names 9453 46795 46796 +11 1 +.names 46800 46803 57299 +1- 1 +-1 1 +.names 44638 46798 +1 1 +.names 46798 46799 +0 1 +.names 46683 46799 46800 +11 1 +.names 2413 46801 +1 1 +.names 46801 46802 +0 1 +.names 9454 46802 46803 +11 1 +.names 46807 46810 57300 +1- 1 +-1 1 +.names 44587 46805 +1 1 +.names 46805 46806 +0 1 +.names 46691 46806 46807 +11 1 +.names 2413 46808 +1 1 +.names 46808 46809 +0 1 +.names 9450 46809 46810 +11 1 +.names 46814 46817 57301 +1- 1 +-1 1 +.names 44656 46812 +1 1 +.names 46812 46813 +0 1 +.names 46691 46813 46814 +11 1 +.names 2413 46815 +1 1 +.names 46815 46816 +0 1 +.names 9450 46816 46817 +11 1 +.names 46821 46824 57302 +1- 1 +-1 1 +.names 14792 46819 +1 1 +.names 46819 46820 +0 1 +.names 46706 46820 46821 +11 1 +.names 2413 46822 +1 1 +.names 46822 46823 +0 1 +.names 9453 46823 46824 +11 1 +.names 46828 46831 57303 +1- 1 +-1 1 +.names 44647 46826 +1 1 +.names 46826 46827 +0 1 +.names 46683 46827 46828 +11 1 +.names 2413 46829 +1 1 +.names 46829 46830 +0 1 +.names 9454 46830 46831 +11 1 +.names 46835 46838 57304 +1- 1 +-1 1 +.names 44527 46833 +1 1 +.names 46833 46834 +0 1 +.names 46706 46834 46835 +11 1 +.names 2413 46836 +1 1 +.names 46836 46837 +0 1 +.names 9453 46837 46838 +11 1 +.names 46842 46845 57305 +1- 1 +-1 1 +.names 57098 46840 +1 1 +.names 46840 46841 +0 1 +.names 46691 46841 46842 +11 1 +.names 2413 46843 +1 1 +.names 46843 46844 +0 1 +.names 9450 46844 46845 +11 1 +.names 46849 46852 57306 +1- 1 +-1 1 +.names 44699 46847 +1 1 +.names 46847 46848 +0 1 +.names 46683 46848 46849 +11 1 +.names 2413 46850 +1 1 +.names 46850 46851 +0 1 +.names 9454 46851 46852 +11 1 +.names 46856 46859 57307 +1- 1 +-1 1 +.names 44767 46854 +1 1 +.names 46854 46855 +0 1 +.names 46706 46855 46856 +11 1 +.names 2413 46857 +1 1 +.names 46857 46858 +0 1 +.names 9453 46858 46859 +11 1 +.names 46863 46866 57308 +1- 1 +-1 1 +.names 14882 46861 +1 1 +.names 46861 46862 +0 1 +.names 46691 46862 46863 +11 1 +.names 2413 46864 +1 1 +.names 46864 46865 +0 1 +.names 9450 46865 46866 +11 1 +.names 46870 46873 57309 +1- 1 +-1 1 +.names 14872 46868 +1 1 +.names 46868 46869 +0 1 +.names 46691 46869 46870 +11 1 +.names 2413 46871 +1 1 +.names 46871 46872 +0 1 +.names 9450 46872 46873 +11 1 +.names 46877 46880 57310 +1- 1 +-1 1 +.names 44518 46875 +1 1 +.names 46875 46876 +0 1 +.names 46706 46876 46877 +11 1 +.names 2413 46878 +1 1 +.names 46878 46879 +0 1 +.names 9453 46879 46880 +11 1 +.names 46884 46887 57311 +1- 1 +-1 1 +.names 14782 46882 +1 1 +.names 46882 46883 +0 1 +.names 46691 46883 46884 +11 1 +.names 2413 46885 +1 1 +.names 46885 46886 +0 1 +.names 9450 46886 46887 +11 1 +.names 46892 46895 57312 +1- 1 +-1 1 +.names 9516 46889 +0 1 +.names 14872 46890 +1 1 +.names 46890 46891 +0 1 +.names 46889 46891 46892 +11 1 +.names 2413 46893 +1 1 +.names 46893 46894 +0 1 +.names 9516 46894 46895 +11 1 +.names 46900 46903 57313 +1- 1 +-1 1 +.names 9510 46897 +0 1 +.names 14782 46898 +1 1 +.names 46898 46899 +0 1 +.names 46897 46899 46900 +11 1 +.names 2413 46901 +1 1 +.names 46901 46902 +0 1 +.names 9510 46902 46903 +11 1 +.names 46907 46910 57314 +1- 1 +-1 1 +.names 44518 46905 +1 1 +.names 46905 46906 +0 1 +.names 46889 46906 46907 +11 1 +.names 2413 46908 +1 1 +.names 46908 46909 +0 1 +.names 9516 46909 46910 +11 1 +.names 46914 46917 57315 +1- 1 +-1 1 +.names 44527 46912 +1 1 +.names 46912 46913 +0 1 +.names 46897 46913 46914 +11 1 +.names 2413 46915 +1 1 +.names 46915 46916 +0 1 +.names 9510 46916 46917 +11 1 +.names 46922 46925 57316 +1- 1 +-1 1 +.names 9511 46919 +0 1 +.names 14937 46920 +1 1 +.names 46920 46921 +0 1 +.names 46919 46921 46922 +11 1 +.names 2413 46923 +1 1 +.names 46923 46924 +0 1 +.names 9511 46924 46925 +11 1 +.names 46930 46933 57317 +1- 1 +-1 1 +.names 9513 46927 +0 1 +.names 44545 46928 +1 1 +.names 46928 46929 +0 1 +.names 46927 46929 46930 +11 1 +.names 2413 46931 +1 1 +.names 46931 46932 +0 1 +.names 9513 46932 46933 +11 1 +.names 46937 46940 57318 +1- 1 +-1 1 +.names 14852 46935 +1 1 +.names 46935 46936 +0 1 +.names 46927 46936 46937 +11 1 +.names 2413 46938 +1 1 +.names 46938 46939 +0 1 +.names 9513 46939 46940 +11 1 +.names 46944 46947 57319 +1- 1 +-1 1 +.names 14832 46942 +1 1 +.names 46942 46943 +0 1 +.names 46897 46943 46944 +11 1 +.names 2413 46945 +1 1 +.names 46945 46946 +0 1 +.names 9510 46946 46947 +11 1 +.names 46951 46954 57320 +1- 1 +-1 1 +.names 44569 46949 +1 1 +.names 46949 46950 +0 1 +.names 46927 46950 46951 +11 1 +.names 2413 46952 +1 1 +.names 46952 46953 +0 1 +.names 9513 46953 46954 +11 1 +.names 46958 46961 57321 +1- 1 +-1 1 +.names 14842 46956 +1 1 +.names 46956 46957 +0 1 +.names 46889 46957 46958 +11 1 +.names 2413 46959 +1 1 +.names 46959 46960 +0 1 +.names 9516 46960 46961 +11 1 +.names 46966 46969 57322 +1- 1 +-1 1 +.names 9515 46963 +0 1 +.names 44587 46964 +1 1 +.names 46964 46965 +0 1 +.names 46963 46965 46966 +11 1 +.names 2413 46967 +1 1 +.names 46967 46968 +0 1 +.names 9515 46968 46969 +11 1 +.names 46973 46976 57323 +1- 1 +-1 1 +.names 14822 46971 +1 1 +.names 46971 46972 +0 1 +.names 46919 46972 46973 +11 1 +.names 2413 46974 +1 1 +.names 46974 46975 +0 1 +.names 9511 46975 46976 +11 1 +.names 46980 46983 57324 +1- 1 +-1 1 +.names 44604 46978 +1 1 +.names 46978 46979 +0 1 +.names 46919 46979 46980 +11 1 +.names 2413 46981 +1 1 +.names 46981 46982 +0 1 +.names 9511 46982 46983 +11 1 +.names 46987 46990 57325 +1- 1 +-1 1 +.names 44613 46985 +1 1 +.names 46985 46986 +0 1 +.names 46919 46986 46987 +11 1 +.names 2413 46988 +1 1 +.names 46988 46989 +0 1 +.names 9511 46989 46990 +11 1 +.names 46994 46997 57326 +1- 1 +-1 1 +.names 14882 46992 +1 1 +.names 46992 46993 +0 1 +.names 46963 46993 46994 +11 1 +.names 2413 46995 +1 1 +.names 46995 46996 +0 1 +.names 9515 46996 46997 +11 1 +.names 47001 47004 57327 +1- 1 +-1 1 +.names 14862 46999 +1 1 +.names 46999 47000 +0 1 +.names 46897 47000 47001 +11 1 +.names 2413 47002 +1 1 +.names 47002 47003 +0 1 +.names 9510 47003 47004 +11 1 +.names 47008 47011 57328 +1- 1 +-1 1 +.names 44638 47006 +1 1 +.names 47006 47007 +0 1 +.names 46963 47007 47008 +11 1 +.names 2413 47009 +1 1 +.names 47009 47010 +0 1 +.names 9515 47010 47011 +11 1 +.names 47015 47018 57329 +1- 1 +-1 1 +.names 44647 47013 +1 1 +.names 47013 47014 +0 1 +.names 46927 47014 47015 +11 1 +.names 2413 47016 +1 1 +.names 47016 47017 +0 1 +.names 9513 47017 47018 +11 1 +.names 47022 47025 57330 +1- 1 +-1 1 +.names 44656 47020 +1 1 +.names 47020 47021 +0 1 +.names 46927 47021 47022 +11 1 +.names 2413 47023 +1 1 +.names 47023 47024 +0 1 +.names 9513 47024 47025 +11 1 +.names 47029 47032 57331 +1- 1 +-1 1 +.names 14760 47027 +1 1 +.names 47027 47028 +0 1 +.names 46889 47028 47029 +11 1 +.names 2413 47030 +1 1 +.names 47030 47031 +0 1 +.names 9516 47031 47032 +11 1 +.names 47037 47040 57332 +1- 1 +-1 1 +.names 9514 47034 +0 1 +.names 44674 47035 +1 1 +.names 47035 47036 +0 1 +.names 47034 47036 47037 +11 1 +.names 2413 47038 +1 1 +.names 47038 47039 +0 1 +.names 9514 47039 47040 +11 1 +.names 47044 47047 57333 +1- 1 +-1 1 +.names 14802 47042 +1 1 +.names 47042 47043 +0 1 +.names 47034 47043 47044 +11 1 +.names 2413 47045 +1 1 +.names 47045 47046 +0 1 +.names 9514 47046 47047 +11 1 +.names 47051 47054 57334 +1- 1 +-1 1 +.names 57098 47049 +1 1 +.names 47049 47050 +0 1 +.names 46963 47050 47051 +11 1 +.names 2413 47052 +1 1 +.names 47052 47053 +0 1 +.names 9515 47053 47054 +11 1 +.names 47058 47061 57335 +1- 1 +-1 1 +.names 44699 47056 +1 1 +.names 47056 47057 +0 1 +.names 46897 47057 47058 +11 1 +.names 2413 47059 +1 1 +.names 47059 47060 +0 1 +.names 9510 47060 47061 +11 1 +.names 47065 47068 57336 +1- 1 +-1 1 +.names 14812 47063 +1 1 +.names 47063 47064 +0 1 +.names 46919 47064 47065 +11 1 +.names 2413 47066 +1 1 +.names 47066 47067 +0 1 +.names 9511 47067 47068 +11 1 +.names 47072 47075 57337 +1- 1 +-1 1 +.names 44716 47070 +1 1 +.names 47070 47071 +0 1 +.names 46889 47071 47072 +11 1 +.names 2413 47073 +1 1 +.names 47073 47074 +0 1 +.names 9516 47074 47075 +11 1 +.names 47079 47082 57338 +1- 1 +-1 1 +.names 44725 47077 +1 1 +.names 47077 47078 +0 1 +.names 46889 47078 47079 +11 1 +.names 2413 47080 +1 1 +.names 47080 47081 +0 1 +.names 9516 47081 47082 +11 1 +.names 47086 47089 57339 +1- 1 +-1 1 +.names 14927 47084 +1 1 +.names 47084 47085 +0 1 +.names 47034 47085 47086 +11 1 +.names 2413 47087 +1 1 +.names 47087 47088 +0 1 +.names 9514 47088 47089 +11 1 +.names 47093 47096 57340 +1- 1 +-1 1 +.names 14893 47091 +1 1 +.names 47091 47092 +0 1 +.names 47034 47092 47093 +11 1 +.names 2413 47094 +1 1 +.names 47094 47095 +0 1 +.names 9514 47095 47096 +11 1 +.names 47100 47103 57341 +1- 1 +-1 1 +.names 14792 47098 +1 1 +.names 47098 47099 +0 1 +.names 47034 47099 47100 +11 1 +.names 2413 47101 +1 1 +.names 47101 47102 +0 1 +.names 9514 47102 47103 +11 1 +.names 47107 47110 57342 +1- 1 +-1 1 +.names 44758 47105 +1 1 +.names 47105 47106 +0 1 +.names 46963 47106 47107 +11 1 +.names 2413 47108 +1 1 +.names 47108 47109 +0 1 +.names 9515 47109 47110 +11 1 +.names 47114 47117 57343 +1- 1 +-1 1 +.names 44767 47112 +1 1 +.names 47112 47113 +0 1 +.names 46963 47113 47114 +11 1 +.names 2413 47115 +1 1 +.names 47115 47116 +0 1 +.names 9515 47116 47117 +11 1 +.names 47122 47125 57344 +1- 1 +-1 1 +.names 9522 47119 +0 1 +.names 44527 47120 +1 1 +.names 47120 47121 +0 1 +.names 47119 47121 47122 +11 1 +.names 2413 47123 +1 1 +.names 47123 47124 +0 1 +.names 9522 47124 47125 +11 1 +.names 47129 47132 57345 +1- 1 +-1 1 +.names 44604 47127 +1 1 +.names 47127 47128 +0 1 +.names 47119 47128 47129 +11 1 +.names 2413 47130 +1 1 +.names 47130 47131 +0 1 +.names 9522 47131 47132 +11 1 +.names 47137 47140 57346 +1- 1 +-1 1 +.names 9525 47134 +0 1 +.names 44587 47135 +1 1 +.names 47135 47136 +0 1 +.names 47134 47136 47137 +11 1 +.names 2413 47138 +1 1 +.names 47138 47139 +0 1 +.names 9525 47139 47140 +11 1 +.names 47145 47148 57347 +1- 1 +-1 1 +.names 9526 47142 +0 1 +.names 44716 47143 +1 1 +.names 47143 47144 +0 1 +.names 47142 47144 47145 +11 1 +.names 2413 47146 +1 1 +.names 47146 47147 +0 1 +.names 9526 47147 47148 +11 1 +.names 47152 47155 57348 +1- 1 +-1 1 +.names 44767 47150 +1 1 +.names 47150 47151 +0 1 +.names 47142 47151 47152 +11 1 +.names 2413 47153 +1 1 +.names 47153 47154 +0 1 +.names 9526 47154 47155 +11 1 +.names 47159 47162 57349 +1- 1 +-1 1 +.names 44725 47157 +1 1 +.names 47157 47158 +0 1 +.names 47134 47158 47159 +11 1 +.names 2413 47160 +1 1 +.names 47160 47161 +0 1 +.names 9525 47161 47162 +11 1 +.names 47166 47169 57350 +1- 1 +-1 1 +.names 44699 47164 +1 1 +.names 47164 47165 +0 1 +.names 47142 47165 47166 +11 1 +.names 2413 47167 +1 1 +.names 47167 47168 +0 1 +.names 9526 47168 47169 +11 1 +.names 47174 47177 57351 +1- 1 +-1 1 +.names 9528 47171 +0 1 +.names 14782 47172 +1 1 +.names 47172 47173 +0 1 +.names 47171 47173 47174 +11 1 +.names 2413 47175 +1 1 +.names 47175 47176 +0 1 +.names 9528 47176 47177 +11 1 +.names 47181 47184 57352 +1- 1 +-1 1 +.names 44647 47179 +1 1 +.names 47179 47180 +0 1 +.names 47171 47180 47181 +11 1 +.names 2413 47182 +1 1 +.names 47182 47183 +0 1 +.names 9528 47183 47184 +11 1 +.names 47189 47192 57353 +1- 1 +-1 1 +.names 9531 47186 +0 1 +.names 44518 47187 +1 1 +.names 47187 47188 +0 1 +.names 47186 47188 47189 +11 1 +.names 2413 47190 +1 1 +.names 47190 47191 +0 1 +.names 9531 47191 47192 +11 1 +.names 47197 47200 57354 +1- 1 +-1 1 +.names 9532 47194 +0 1 +.names 44638 47195 +1 1 +.names 47195 47196 +0 1 +.names 47194 47196 47197 +11 1 +.names 2413 47198 +1 1 +.names 47198 47199 +0 1 +.names 9532 47199 47200 +11 1 +.names 47204 47207 57355 +1- 1 +-1 1 +.names 44674 47202 +1 1 +.names 47202 47203 +0 1 +.names 47194 47203 47204 +11 1 +.names 2413 47205 +1 1 +.names 47205 47206 +0 1 +.names 9532 47206 47207 +11 1 +.names 47211 47214 57356 +1- 1 +-1 1 +.names 44569 47209 +1 1 +.names 47209 47210 +0 1 +.names 47186 47210 47211 +11 1 +.names 2413 47212 +1 1 +.names 47212 47213 +0 1 +.names 9531 47213 47214 +11 1 +.names 47218 47221 57357 +1- 1 +-1 1 +.names 44758 47216 +1 1 +.names 47216 47217 +0 1 +.names 47194 47217 47218 +11 1 +.names 2413 47219 +1 1 +.names 47219 47220 +0 1 +.names 9532 47220 47221 +11 1 +.names 47226 47229 57358 +1- 1 +-1 1 +.names 9541 47223 +0 1 +.names 14842 47224 +1 1 +.names 47224 47225 +0 1 +.names 47223 47225 47226 +11 1 +.names 2413 47227 +1 1 +.names 47227 47228 +0 1 +.names 9541 47228 47229 +11 1 +.names 47234 47237 57359 +1- 1 +-1 1 +.names 9538 47231 +0 1 +.names 14832 47232 +1 1 +.names 47232 47233 +0 1 +.names 47231 47233 47234 +11 1 +.names 2413 47235 +1 1 +.names 47235 47236 +0 1 +.names 9538 47236 47237 +11 1 +.names 47242 47245 57360 +1- 1 +-1 1 +.names 9554 47239 +0 1 +.names 44545 47240 +1 1 +.names 47240 47241 +0 1 +.names 47239 47241 47242 +11 1 +.names 2413 47243 +1 1 +.names 47243 47244 +0 1 +.names 9554 47244 47245 +11 1 +.names 47250 47253 57361 +1- 1 +-1 1 +.names 9551 47247 +0 1 +.names 44613 47248 +1 1 +.names 47248 47249 +0 1 +.names 47247 47249 47250 +11 1 +.names 2413 47251 +1 1 +.names 47251 47252 +0 1 +.names 9551 47252 47253 +11 1 +.names 47260 47262 47254 +1- 1 +-1 1 +.names 47254 47255 +1 1 +.names 9565 47256 +0 1 +.names 47263 47265 47257 +11 1 +.names 47257 47258 +1 1 +.names 47258 47259 +0 1 +.names 47256 47259 47260 +11 1 +.names 335 47261 +0 1 +.names 9565 47261 47262 +11 1 +.names 9574 47263 +0 1 +.names 14927 47264 +1 1 +.names 47264 47265 +0 1 +.names 47271 47272 57362 +1- 1 +-1 1 +.names 47263 47267 +1 1 +.names 47267 47268 +0 1 +.names 14886 47269 +1 1 +.names 47269 47270 +0 1 +.names 47268 47270 47271 +11 1 +.names 47255 47272 +0 1 +.names 47279 47280 47273 +1- 1 +-1 1 +.names 47273 47274 +1 1 +.names 9575 47275 +0 1 +.names 47281 47283 47276 +11 1 +.names 47276 47277 +1 1 +.names 47277 47278 +0 1 +.names 47275 47278 47279 +11 1 +.names 9575 14886 47280 +11 1 +.names 9572 47281 +0 1 +.names 14852 47282 +1 1 +.names 47282 47283 +0 1 +.names 47290 47291 57363 +1- 1 +-1 1 +.names 47281 47285 +1 1 +.names 47285 47286 +0 1 +.names 340 47287 +0 1 +.names 47287 47288 +1 1 +.names 47288 47289 +0 1 +.names 47286 47289 47290 +11 1 +.names 47274 47291 +0 1 +.names 47298 47300 47292 +1- 1 +-1 1 +.names 47292 47293 +1 1 +.names 9567 47294 +0 1 +.names 47263 47302 47295 +11 1 +.names 47295 47296 +1 1 +.names 47296 47297 +0 1 +.names 47294 47297 47298 +11 1 +.names 356 47299 +0 1 +.names 9567 47299 47300 +11 1 +.names 44604 47301 +1 1 +.names 47301 47302 +0 1 +.names 47308 47309 57364 +1- 1 +-1 1 +.names 47263 47304 +1 1 +.names 47304 47305 +0 1 +.names 2413 47306 +1 1 +.names 47306 47307 +0 1 +.names 47305 47307 47308 +11 1 +.names 47293 47309 +0 1 +.names 47316 47317 47310 +1- 1 +-1 1 +.names 47310 47311 +1 1 +.names 9570 47312 +0 1 +.names 47294 47319 47313 +11 1 +.names 47313 47314 +1 1 +.names 47314 47315 +0 1 +.names 47312 47315 47316 +11 1 +.names 9570 14886 47317 +11 1 +.names 14832 47318 +1 1 +.names 47318 47319 +0 1 +.names 47326 47327 57365 +1- 1 +-1 1 +.names 47294 47321 +1 1 +.names 47321 47322 +0 1 +.names 342 47323 +0 1 +.names 47323 47324 +1 1 +.names 47324 47325 +0 1 +.names 47322 47325 47326 +11 1 +.names 47311 47327 +0 1 +.names 47256 47328 +1 1 +.names 47256 47332 47329 +11 1 +.names 47329 47330 +1 1 +.names 14812 47331 +1 1 +.names 47331 47332 +0 1 +.names 47336 47337 47333 +1- 1 +-1 1 +.names 47333 47334 +1 1 +.names 47330 47335 +0 1 +.names 47275 47335 47336 +11 1 +.names 9575 14886 47337 +11 1 +.names 344 47338 +0 1 +.names 47338 47339 +1 1 +.names 47343 47344 57366 +1- 1 +-1 1 +.names 47328 47341 +0 1 +.names 47339 47342 +0 1 +.names 47341 47342 47343 +11 1 +.names 47334 47344 +0 1 +.names 47351 47353 47345 +1- 1 +-1 1 +.names 47345 47346 +1 1 +.names 9573 47347 +0 1 +.names 47263 47355 47348 +11 1 +.names 47348 47349 +1 1 +.names 47349 47350 +0 1 +.names 47347 47350 47351 +11 1 +.names 351 47352 +0 1 +.names 9573 47352 47353 +11 1 +.names 44569 47354 +1 1 +.names 47354 47355 +0 1 +.names 47361 47362 57367 +1- 1 +-1 1 +.names 47263 47357 +1 1 +.names 47357 47358 +0 1 +.names 14886 47359 +1 1 +.names 47359 47360 +0 1 +.names 47358 47360 47361 +11 1 +.names 47346 47362 +0 1 +.names 47369 47370 47363 +1- 1 +-1 1 +.names 47363 47364 +1 1 +.names 9560 47365 +0 1 +.names 47281 47372 47366 +11 1 +.names 47366 47367 +1 1 +.names 47367 47368 +0 1 +.names 47365 47368 47369 +11 1 +.names 9560 14886 47370 +11 1 +.names 44674 47371 +1 1 +.names 47371 47372 +0 1 +.names 47379 47380 57368 +1- 1 +-1 1 +.names 47281 47374 +1 1 +.names 47374 47375 +0 1 +.names 353 47376 +0 1 +.names 47376 47377 +1 1 +.names 47377 47378 +0 1 +.names 47375 47378 47379 +11 1 +.names 47364 47380 +0 1 +.names 47386 47387 47381 +1- 1 +-1 1 +.names 47381 47382 +1 1 +.names 47347 47389 47383 +11 1 +.names 47383 47384 +1 1 +.names 47384 47385 +0 1 +.names 47365 47385 47386 +11 1 +.names 9560 14886 47387 +11 1 +.names 44613 47388 +1 1 +.names 47388 47389 +0 1 +.names 47396 47397 57369 +1- 1 +-1 1 +.names 334 47391 +0 1 +.names 47391 47392 +1 1 +.names 47392 47393 +0 1 +.names 47347 47394 +1 1 +.names 47394 47395 +0 1 +.names 47393 47395 47396 +11 1 +.names 47382 47397 +0 1 +.names 47294 47398 +1 1 +.names 47404 47405 47399 +1- 1 +-1 1 +.names 47399 47400 +1 1 +.names 47294 47407 47401 +11 1 +.names 47401 47402 +1 1 +.names 47402 47403 +0 1 +.names 47275 47403 47404 +11 1 +.names 9575 14886 47405 +11 1 +.names 14822 47406 +1 1 +.names 47406 47407 +0 1 +.names 343 47408 +0 1 +.names 47408 47409 +1 1 +.names 47413 47414 57370 +1- 1 +-1 1 +.names 47398 47411 +0 1 +.names 47409 47412 +0 1 +.names 47411 47412 47413 +11 1 +.names 47400 47414 +0 1 +.names 47420 47422 47415 +1- 1 +-1 1 +.names 47415 47416 +1 1 +.names 47263 47424 47417 +11 1 +.names 47417 47418 +1 1 +.names 47418 47419 +0 1 +.names 47256 47419 47420 +11 1 +.names 359 47421 +0 1 +.names 9565 47421 47422 +11 1 +.names 44725 47423 +1 1 +.names 47423 47424 +0 1 +.names 47430 47431 57371 +1- 1 +-1 1 +.names 2413 47426 +1 1 +.names 47426 47427 +0 1 +.names 47263 47428 +1 1 +.names 47428 47429 +0 1 +.names 47427 47429 47430 +11 1 +.names 47416 47431 +0 1 +.names 47437 47438 47432 +1- 1 +-1 1 +.names 47432 47433 +1 1 +.names 47281 47440 47434 +11 1 +.names 47434 47435 +1 1 +.names 47435 47436 +0 1 +.names 47312 47436 47437 +11 1 +.names 9570 14886 47438 +11 1 +.names 14802 47439 +1 1 +.names 47439 47440 +0 1 +.names 47447 47448 57372 +1- 1 +-1 1 +.names 47281 47442 +1 1 +.names 47442 47443 +0 1 +.names 345 47444 +0 1 +.names 47444 47445 +1 1 +.names 47445 47446 +0 1 +.names 47443 47446 47447 +11 1 +.names 47433 47448 +0 1 +.names 47454 47456 47449 +1- 1 +-1 1 +.names 47449 47450 +1 1 +.names 47263 47458 47451 +11 1 +.names 47451 47452 +1 1 +.names 47452 47453 +0 1 +.names 47294 47453 47454 +11 1 +.names 358 47455 +0 1 +.names 9567 47455 47456 +11 1 +.names 44716 47457 +1 1 +.names 47457 47458 +0 1 +.names 47464 47465 57373 +1- 1 +-1 1 +.names 47263 47460 +1 1 +.names 47460 47461 +0 1 +.names 2413 47462 +1 1 +.names 47462 47463 +0 1 +.names 47461 47463 47464 +11 1 +.names 47450 47465 +0 1 +.names 47471 47472 47466 +1- 1 +-1 1 +.names 47466 47467 +1 1 +.names 47294 47474 47468 +11 1 +.names 47468 47469 +1 1 +.names 47469 47470 +0 1 +.names 47312 47470 47471 +11 1 +.names 9570 14886 47472 +11 1 +.names 14842 47473 +1 1 +.names 47473 47474 +0 1 +.names 47481 47482 57374 +1- 1 +-1 1 +.names 47294 47476 +1 1 +.names 47476 47477 +0 1 +.names 341 47478 +0 1 +.names 47478 47479 +1 1 +.names 47479 47480 +0 1 +.names 47477 47480 47481 +11 1 +.names 47467 47482 +0 1 +.names 47488 47489 47483 +1- 1 +-1 1 +.names 47483 47484 +1 1 +.names 47281 47491 47485 +11 1 +.names 47485 47486 +1 1 +.names 47486 47487 +0 1 +.names 47275 47487 47488 +11 1 +.names 9575 14886 47489 +11 1 +.names 44758 47490 +1 1 +.names 47490 47491 +0 1 +.names 47498 47499 57375 +1- 1 +-1 1 +.names 47281 47493 +1 1 +.names 47493 47494 +0 1 +.names 352 47495 +0 1 +.names 47495 47496 +1 1 +.names 47496 47497 +0 1 +.names 47494 47497 47498 +11 1 +.names 47484 47499 +0 1 +.names 47505 47506 47500 +1- 1 +-1 1 +.names 47500 47501 +1 1 +.names 47347 47508 47502 +11 1 +.names 47502 47503 +1 1 +.names 47503 47504 +0 1 +.names 47365 47504 47505 +11 1 +.names 9560 14886 47506 +11 1 +.names 44638 47507 +1 1 +.names 47507 47508 +0 1 +.names 47515 47516 57376 +1- 1 +-1 1 +.names 350 47510 +0 1 +.names 47510 47511 +1 1 +.names 47511 47512 +0 1 +.names 47347 47513 +1 1 +.names 47513 47514 +0 1 +.names 47512 47514 47515 +11 1 +.names 47501 47516 +0 1 +.names 47347 47517 +1 1 +.names 47523 47524 47518 +1- 1 +-1 1 +.names 47518 47519 +1 1 +.names 47347 47526 47520 +11 1 +.names 47520 47521 +1 1 +.names 47521 47522 +0 1 +.names 47275 47522 47523 +11 1 +.names 9575 2413 47524 +11 1 +.names 44587 47525 +1 1 +.names 47525 47526 +0 1 +.names 357 47527 +0 1 +.names 47527 47528 +1 1 +.names 47532 47533 57377 +1- 1 +-1 1 +.names 47517 47530 +0 1 +.names 47528 47531 +0 1 +.names 47530 47531 47532 +11 1 +.names 47519 47533 +0 1 +.names 47539 47540 47534 +1- 1 +-1 1 +.names 47534 47535 +1 1 +.names 47294 47542 47536 +11 1 +.names 47536 47537 +1 1 +.names 47537 47538 +0 1 +.names 47312 47538 47539 +11 1 +.names 9570 14886 47540 +11 1 +.names 14893 47541 +1 1 +.names 47541 47542 +0 1 +.names 47549 47550 57378 +1- 1 +-1 1 +.names 47294 47544 +1 1 +.names 47544 47545 +0 1 +.names 336 47546 +0 1 +.names 47546 47547 +1 1 +.names 47547 47548 +0 1 +.names 47545 47548 47549 +11 1 +.names 47535 47550 +0 1 +.names 47556 47557 47551 +1- 1 +-1 1 +.names 47551 47552 +1 1 +.names 47294 47559 47553 +11 1 +.names 47553 47554 +1 1 +.names 47554 47555 +0 1 +.names 47312 47555 47556 +11 1 +.names 9570 14886 47557 +11 1 +.names 14862 47558 +1 1 +.names 47558 47559 +0 1 +.names 47566 47567 57379 +1- 1 +-1 1 +.names 47294 47561 +1 1 +.names 47561 47562 +0 1 +.names 339 47563 +0 1 +.names 47563 47564 +1 1 +.names 47564 47565 +0 1 +.names 47562 47565 47566 +11 1 +.names 47552 47567 +0 1 +.names 47256 47568 +1 1 +.names 47574 47575 47569 +1- 1 +-1 1 +.names 47569 47570 +1 1 +.names 47256 47577 47571 +11 1 +.names 47571 47572 +1 1 +.names 47572 47573 +0 1 +.names 47275 47573 47574 +11 1 +.names 9575 2413 47575 +11 1 +.names 44656 47576 +1 1 +.names 47576 47577 +0 1 +.names 355 47578 +0 1 +.names 47578 47579 +1 1 +.names 47583 47584 57380 +1- 1 +-1 1 +.names 47568 47581 +0 1 +.names 47579 47582 +0 1 +.names 47581 47582 47583 +11 1 +.names 47570 47584 +0 1 +.names 47590 47591 47585 +1- 1 +-1 1 +.names 47585 47586 +1 1 +.names 47347 47593 47587 +11 1 +.names 47587 47588 +1 1 +.names 47588 47589 +0 1 +.names 47365 47589 47590 +11 1 +.names 9560 14886 47591 +11 1 +.names 14792 47592 +1 1 +.names 47592 47593 +0 1 +.names 47600 47601 57381 +1- 1 +-1 1 +.names 47347 47595 +1 1 +.names 47595 47596 +0 1 +.names 347 47597 +0 1 +.names 47597 47598 +1 1 +.names 47598 47599 +0 1 +.names 47596 47599 47600 +11 1 +.names 47586 47601 +0 1 +.names 47607 47608 47602 +1- 1 +-1 1 +.names 47602 47603 +1 1 +.names 47256 47610 47604 +11 1 +.names 47604 47605 +1 1 +.names 47605 47606 +0 1 +.names 47365 47606 47607 +11 1 +.names 9560 14886 47608 +11 1 +.names 44647 47609 +1 1 +.names 47609 47610 +0 1 +.names 47617 47618 57382 +1- 1 +-1 1 +.names 47256 47612 +1 1 +.names 47612 47613 +0 1 +.names 348 47614 +0 1 +.names 47614 47615 +1 1 +.names 47615 47616 +0 1 +.names 47613 47616 47617 +11 1 +.names 47603 47618 +0 1 +.names 47624 47625 47619 +1- 1 +-1 1 +.names 47619 47620 +1 1 +.names 47256 47627 47621 +11 1 +.names 47621 47622 +1 1 +.names 47622 47623 +0 1 +.names 47312 47623 47624 +11 1 +.names 9570 2413 47625 +11 1 +.names 44527 47626 +1 1 +.names 47626 47627 +0 1 +.names 47634 47635 57383 +1- 1 +-1 1 +.names 47256 47629 +1 1 +.names 47629 47630 +0 1 +.names 362 47631 +0 1 +.names 47631 47632 +1 1 +.names 47632 47633 +0 1 +.names 47630 47633 47634 +11 1 +.names 47620 47635 +0 1 +.names 47641 47642 47636 +1- 1 +-1 1 +.names 47636 47637 +1 1 +.names 47281 47644 47638 +11 1 +.names 47638 47639 +1 1 +.names 47639 47640 +0 1 +.names 47312 47640 47641 +11 1 +.names 9570 14886 47642 +11 1 +.names 57098 47643 +1 1 +.names 47643 47644 +0 1 +.names 47651 47652 57384 +1- 1 +-1 1 +.names 47281 47646 +1 1 +.names 47646 47647 +0 1 +.names 346 47648 +0 1 +.names 47648 47649 +1 1 +.names 47649 47650 +0 1 +.names 47647 47650 47651 +11 1 +.names 47637 47652 +0 1 +.names 47658 47659 47653 +1- 1 +-1 1 +.names 47653 47654 +1 1 +.names 47281 47661 47655 +11 1 +.names 47655 47656 +1 1 +.names 47656 47657 +0 1 +.names 47275 47657 47658 +11 1 +.names 9575 2413 47659 +11 1 +.names 44699 47660 +1 1 +.names 47660 47661 +0 1 +.names 47668 47669 57385 +1- 1 +-1 1 +.names 47281 47663 +1 1 +.names 47663 47664 +0 1 +.names 360 47665 +0 1 +.names 47665 47666 +1 1 +.names 47666 47667 +0 1 +.names 47664 47667 47668 +11 1 +.names 47654 47669 +0 1 +.names 47675 47676 47670 +1- 1 +-1 1 +.names 47670 47671 +1 1 +.names 47347 47678 47672 +11 1 +.names 47672 47673 +1 1 +.names 47673 47674 +0 1 +.names 47365 47674 47675 +11 1 +.names 9560 2413 47676 +11 1 +.names 44767 47677 +1 1 +.names 47677 47678 +0 1 +.names 47685 47686 57386 +1- 1 +-1 1 +.names 47347 47680 +1 1 +.names 47680 47681 +0 1 +.names 361 47682 +0 1 +.names 47682 47683 +1 1 +.names 47683 47684 +0 1 +.names 47681 47684 47685 +11 1 +.names 47671 47686 +0 1 +.names 47692 47693 47687 +1- 1 +-1 1 +.names 47687 47688 +1 1 +.names 47281 47695 47689 +11 1 +.names 47689 47690 +1 1 +.names 47690 47691 +0 1 +.names 47275 47691 47692 +11 1 +.names 9575 14886 47693 +11 1 +.names 14882 47694 +1 1 +.names 47694 47695 +0 1 +.names 47702 47703 57387 +1- 1 +-1 1 +.names 337 47697 +0 1 +.names 47697 47698 +1 1 +.names 47698 47699 +0 1 +.names 47281 47700 +1 1 +.names 47700 47701 +0 1 +.names 47699 47701 47702 +11 1 +.names 47688 47703 +0 1 +.names 47709 47710 47704 +1- 1 +-1 1 +.names 47704 47705 +1 1 +.names 47281 47712 47706 +11 1 +.names 47706 47707 +1 1 +.names 47707 47708 +0 1 +.names 47365 47708 47709 +11 1 +.names 9560 14886 47710 +11 1 +.names 14872 47711 +1 1 +.names 47711 47712 +0 1 +.names 47719 47720 57388 +1- 1 +-1 1 +.names 47281 47714 +1 1 +.names 47714 47715 +0 1 +.names 338 47716 +0 1 +.names 47716 47717 +1 1 +.names 47717 47718 +0 1 +.names 47715 47718 47719 +11 1 +.names 47705 47720 +0 1 +.names 47726 47728 47721 +1- 1 +-1 1 +.names 47721 47722 +1 1 +.names 47263 47730 47723 +11 1 +.names 47723 47724 +1 1 +.names 47724 47725 +0 1 +.names 47347 47725 47726 +11 1 +.names 349 47727 +0 1 +.names 9573 47727 47728 +11 1 +.names 44518 47729 +1 1 +.names 47729 47730 +0 1 +.names 47736 47737 57389 +1- 1 +-1 1 +.names 47263 47732 +1 1 +.names 47732 47733 +0 1 +.names 14886 47734 +1 1 +.names 47734 47735 +0 1 +.names 47733 47735 47736 +11 1 +.names 47722 47737 +0 1 +.names 47743 47744 47738 +1- 1 +-1 1 +.names 47738 47739 +1 1 +.names 47281 47746 47740 +11 1 +.names 47740 47741 +1 1 +.names 47741 47742 +0 1 +.names 47312 47742 47743 +11 1 +.names 9570 2413 47744 +11 1 +.names 14782 47745 +1 1 +.names 47745 47746 +0 1 +.names 47753 47754 57390 +1- 1 +-1 1 +.names 47281 47748 +1 1 +.names 47748 47749 +0 1 +.names 354 47750 +0 1 +.names 47750 47751 +1 1 +.names 47751 47752 +0 1 +.names 47749 47752 47753 +11 1 +.names 47739 47754 +0 1 +.names 47760 47761 47755 +1- 1 +-1 1 +.names 47755 47756 +1 1 +.names 47256 47763 47757 +11 1 +.names 47757 47758 +1 1 +.names 47758 47759 +0 1 +.names 47365 47759 47760 +11 1 +.names 9560 2413 47761 +11 1 +.names 14760 47762 +1 1 +.names 47762 47763 +0 1 +.names 47770 47771 57391 +1- 1 +-1 1 +.names 47256 47765 +1 1 +.names 47765 47766 +0 1 +.names 363 47767 +0 1 +.names 47767 47768 +1 1 +.names 47768 47769 +0 1 +.names 47766 47769 47770 +11 1 +.names 47756 47771 +0 1 +.names 2878 47772 +0 1 +.names 47772 14964 47773 +11 1 +.names 47773 47774 +1 1 +.names 47774 47775 +0 1 +.names 2874 47776 +0 1 +.names 2886 47777 +0 1 +.names 47777 14987 47778 +11 1 +.names 47778 47779 +1 1 +.names 47779 47780 +0 1 +.names 2882 47781 +0 1 +.names 952 47782 +0 1 +.names 47782 15010 47783 +11 1 +.names 47783 47784 +1 1 +.names 47784 47785 +0 1 +.names 953 47786 +0 1 +.names 948 47787 +0 1 +.names 47787 15033 47788 +11 1 +.names 47788 47789 +1 1 +.names 47789 47790 +0 1 +.names 949 47791 +0 1 +.names 2413 47798 47792 +11 1 +.names 47792 47793 +1 1 +.names 47793 47794 +0 1 +.names 47818 47795 +0 1 +.names 47795 47796 +1 1 +.names 47796 47797 +0 1 +.names 15080 47798 +0 1 +.names 47798 47799 +1 1 +.names 47799 47800 +0 1 +.names 47809 47810 47801 +11 1 +.names 47801 47802 +1 1 +.names 47802 47803 +0 1 +.names 47800 47803 47804 +1- 1 +-1 1 +.names 2413 47805 +1 1 +.names 47805 47806 +0 1 +.names 47804 47806 47807 +1- 1 +-1 1 +.names 945 47808 +0 1 +.names 943 47809 +0 1 +.names 944 47810 +0 1 +.names 47810 47811 +1 1 +.names 47811 47812 +0 1 +.names 47812 47813 +1 1 +.names 47798 47814 +1 1 +.names 47814 47815 +0 1 +.names 47813 47816 +0 1 +.names 47815 47816 47817 +1- 1 +-1 1 +.names 47809 47818 +1 1 +.names 47817 47795 47819 +1- 1 +-1 1 +.names 2413 47826 47820 +11 1 +.names 47820 47821 +1 1 +.names 47821 47822 +0 1 +.names 47846 47823 +0 1 +.names 47823 47824 +1 1 +.names 47824 47825 +0 1 +.names 15124 47826 +0 1 +.names 47826 47827 +1 1 +.names 47827 47828 +0 1 +.names 47837 47838 47829 +11 1 +.names 47829 47830 +1 1 +.names 47830 47831 +0 1 +.names 47828 47831 47832 +1- 1 +-1 1 +.names 2413 47833 +1 1 +.names 47833 47834 +0 1 +.names 47832 47834 47835 +1- 1 +-1 1 +.names 9601 47836 +0 1 +.names 9589 47837 +0 1 +.names 9595 47838 +0 1 +.names 47838 47839 +1 1 +.names 47839 47840 +0 1 +.names 47840 47841 +1 1 +.names 47826 47842 +1 1 +.names 47842 47843 +0 1 +.names 47841 47844 +0 1 +.names 47843 47844 47845 +1- 1 +-1 1 +.names 47837 47846 +1 1 +.names 47845 47823 47847 +1- 1 +-1 1 +.names 47854 47855 47848 +1- 1 +-1 1 +.names 47848 47849 +1 1 +.names 9627 47850 +0 1 +.names 47891 47851 +0 1 +.names 47851 47852 +1 1 +.names 47852 47853 +0 1 +.names 47850 47853 47854 +11 1 +.names 9627 44513 47855 +11 1 +.names 2413 47859 47856 +11 1 +.names 47856 47857 +1 1 +.names 40359 47858 +1 1 +.names 47858 47859 +0 1 +.names 47862 47863 47860 +11 1 +.names 47860 47861 +1 1 +.names 9619 47862 +0 1 +.names 9635 47863 +0 1 +.names 47866 47867 47864 +11 1 +.names 47864 47865 +1 1 +.names 9651 47866 +0 1 +.names 9611 47867 +0 1 +.names 47883 47884 47868 +1- 1 +-1 1 +.names 47868 47869 +1 1 +.names 47849 47870 +0 1 +.names 47874 47876 47871 +11 1 +.names 47871 47872 +1 1 +.names 797 47873 +0 1 +.names 47866 47873 47874 +1- 1 +-1 1 +.names 1539 47875 +0 1 +.names 47863 47875 47876 +1- 1 +-1 1 +.names 47885 47888 47877 +11 1 +.names 47877 47878 +1 1 +.names 47878 47879 +0 1 +.names 47899 47901 47880 +11 1 +.names 47880 47881 +1 1 +.names 47881 47882 +0 1 +.names 47879 47882 47883 +1- 1 +-1 1 +.names 47872 47884 +0 1 +.names 2413 47885 +1 1 +.names 9643 47886 +0 1 +.names 1540 47887 +0 1 +.names 47886 47887 47888 +1- 1 +-1 1 +.names 47886 47889 +1 1 +.names 47896 47897 47890 +1- 1 +-1 1 +.names 47890 47891 +1 1 +.names 47857 47892 +0 1 +.names 47889 47893 +0 1 +.names 47892 47893 47894 +1- 1 +-1 1 +.names 47861 47895 +0 1 +.names 47894 47895 47896 +1- 1 +-1 1 +.names 47865 47897 +0 1 +.names 1541 47898 +0 1 +.names 47898 47862 47899 +1- 1 +-1 1 +.names 1542 47900 +0 1 +.names 47867 47900 47901 +1- 1 +-1 1 +.names 9621 47902 +0 1 +.names 47902 47903 +1 1 +.names 47909 47911 47904 +1- 1 +-1 1 +.names 47904 47905 +1 1 +.names 47925 47926 47906 +11 1 +.names 47906 47907 +1 1 +.names 47907 47908 +0 1 +.names 47863 47908 47909 +11 1 +.names 1543 47910 +0 1 +.names 9635 47910 47911 +11 1 +.names 47914 47915 47912 +1- 1 +-1 1 +.names 47912 47913 +1 1 +.names 9619 40440 47914 +1- 1 +-1 1 +.names 47903 47915 +0 1 +.names 47920 47923 47916 +1- 1 +-1 1 +.names 47916 47917 +1 1 +.names 47924 47867 47918 +11 1 +.names 47918 47919 +1 1 +.names 47919 47920 +0 1 +.names 47948 2413 47921 +11 1 +.names 47921 47922 +1 1 +.names 47922 47923 +0 1 +.names 9606 47924 +0 1 +.names 47917 47925 +0 1 +.names 47913 47926 +0 1 +.names 47930 47931 47927 +11 1 +.names 47927 47928 +1 1 +.names 1544 47929 +0 1 +.names 47867 47929 47930 +1- 1 +-1 1 +.names 47924 3253 47931 +1- 1 +-1 1 +.names 47941 47943 47932 +11 1 +.names 47932 47933 +1 1 +.names 44504 47902 47934 +1- 1 +-1 1 +.names 47934 47935 +1 1 +.names 47950 47862 47936 +1- 1 +-1 1 +.names 47936 47937 +1 1 +.names 47935 47937 47938 +11 1 +.names 47948 47949 47939 +1- 1 +-1 1 +.names 47939 47940 +1 1 +.names 47938 47940 47941 +11 1 +.names 2413 47942 +1 1 +.names 47942 47943 +1 1 +.names 47905 47944 +0 1 +.names 47933 47945 +0 1 +.names 47944 47945 47946 +1- 1 +-1 1 +.names 47928 47947 +0 1 +.names 9650 47948 +0 1 +.names 1545 47949 +0 1 +.names 1546 47950 +0 1 +.names 47956 47957 47951 +1- 1 +-1 1 +.names 47951 47952 +1 1 +.names 47973 47974 47953 +11 1 +.names 47953 47954 +1 1 +.names 47954 47955 +0 1 +.names 2413 47955 47956 +11 1 +.names 1783 2413 47957 +11 1 +.names 47961 47963 47958 +11 1 +.names 47958 47959 +1 1 +.names 9613 47960 +0 1 +.names 47960 2413 47961 +1- 1 +-1 1 +.names 9617 47962 +0 1 +.names 2413 47962 47963 +1- 1 +-1 1 +.names 47966 47968 47964 +1- 1 +-1 1 +.names 47964 47965 +1 1 +.names 9625 40411 47966 +1- 1 +-1 1 +.names 47924 47967 +1 1 +.names 47967 47968 +0 1 +.names 47962 47960 47969 +11 1 +.names 47969 47970 +1 1 +.names 47986 47987 47971 +1- 1 +-1 1 +.names 47971 47972 +1 1 +.names 47972 47973 +0 1 +.names 47965 47974 +0 1 +.names 47996 47997 47975 +1- 1 +-1 1 +.names 47975 47976 +1 1 +.names 47952 47977 +0 1 +.names 47981 47983 47978 +11 1 +.names 47978 47979 +1 1 +.names 9625 47980 +0 1 +.names 47980 2413 47981 +1- 1 +-1 1 +.names 1547 47982 +0 1 +.names 47924 47982 47983 +1- 1 +-1 1 +.names 47992 47948 47984 +11 1 +.names 47984 47985 +1 1 +.names 47985 47986 +0 1 +.names 47970 47987 +0 1 +.names 47991 47993 47988 +11 1 +.names 47988 47989 +1 1 +.names 1548 47990 +0 1 +.names 47948 47990 47991 +1- 1 +-1 1 +.names 9640 47992 +0 1 +.names 47992 2413 47993 +1- 1 +-1 1 +.names 47989 47994 +0 1 +.names 47959 47995 +0 1 +.names 47994 47995 47996 +1- 1 +-1 1 +.names 47979 47997 +0 1 +.names 47962 47998 +1 1 +.names 48004 48005 47999 +1- 1 +-1 1 +.names 47999 48000 +1 1 +.names 48018 48019 48001 +11 1 +.names 48001 48002 +1 1 +.names 48002 48003 +0 1 +.names 2413 48003 48004 +11 1 +.names 1783 2413 48005 +11 1 +.names 48009 40544 48006 +1- 1 +-1 1 +.names 48006 48007 +1 1 +.names 47998 48008 +0 1 +.names 9603 48008 48009 +1- 1 +-1 1 +.names 48014 48017 48010 +1- 1 +-1 1 +.names 48010 48011 +1 1 +.names 48043 47980 48012 +11 1 +.names 48012 48013 +1 1 +.names 48013 48014 +0 1 +.names 47960 47866 48015 +11 1 +.names 48015 48016 +1 1 +.names 48016 48017 +0 1 +.names 48011 48018 +0 1 +.names 48007 48019 +0 1 +.names 48039 48040 48020 +1- 1 +-1 1 +.names 48020 48021 +1 1 +.names 48000 48022 +0 1 +.names 48025 48027 48023 +11 1 +.names 48023 48024 +1 1 +.names 47980 44556 48025 +1- 1 +-1 1 +.names 1549 48026 +0 1 +.names 47866 48026 48027 +1- 1 +-1 1 +.names 48031 48034 48028 +11 1 +.names 48028 48029 +1 1 +.names 1550 48030 +0 1 +.names 47960 48030 48031 +1- 1 +-1 1 +.names 9603 48032 +0 1 +.names 1551 48033 +0 1 +.names 48032 48033 48034 +1- 1 +-1 1 +.names 48029 48035 +0 1 +.names 48042 48045 48036 +11 1 +.names 48036 48037 +1 1 +.names 48037 48038 +0 1 +.names 48035 48038 48039 +1- 1 +-1 1 +.names 48024 48040 +0 1 +.names 1552 48041 +0 1 +.names 47962 48041 48042 +1- 1 +-1 1 +.names 9636 48043 +0 1 +.names 1553 48044 +0 1 +.names 48043 48044 48045 +1- 1 +-1 1 +.names 48050 48053 48046 +1- 1 +-1 1 +.names 48046 48047 +1 1 +.names 48068 47867 48048 +11 1 +.names 48048 48049 +1 1 +.names 48049 48050 +0 1 +.names 47924 47992 48051 +11 1 +.names 48051 48052 +1 1 +.names 48052 48053 +0 1 +.names 48056 48059 48054 +11 1 +.names 48054 48055 +1 1 +.names 48047 48056 +0 1 +.names 48072 48073 48057 +1- 1 +-1 1 +.names 48057 48058 +1 1 +.names 48058 48059 +0 1 +.names 48087 48090 48060 +1- 1 +-1 1 +.names 48060 48061 +1 1 +.names 48076 48078 48062 +1- 1 +-1 1 +.names 48062 48063 +1 1 +.names 48063 48064 +0 1 +.names 48069 48070 48065 +11 1 +.names 48065 48066 +1 1 +.names 1554 48067 +0 1 +.names 9638 48068 +0 1 +.names 48067 48068 48069 +1- 1 +-1 1 +.names 47850 44564 48070 +1- 1 +-1 1 +.names 47886 48071 +1 1 +.names 9627 40578 48072 +1- 1 +-1 1 +.names 48071 48073 +0 1 +.names 2413 48074 +1 1 +.names 48074 48075 +0 1 +.names 48075 2413 48076 +11 1 +.names 48055 48077 +0 1 +.names 48074 48077 48078 +11 1 +.names 48082 48084 48079 +11 1 +.names 48079 48080 +1 1 +.names 1555 48081 +0 1 +.names 47886 48081 48082 +1- 1 +-1 1 +.names 1556 48083 +0 1 +.names 47992 48083 48084 +1- 1 +-1 1 +.names 48066 48085 +0 1 +.names 48080 48086 +0 1 +.names 48085 48086 48087 +1- 1 +-1 1 +.names 48091 48093 48088 +11 1 +.names 48088 48089 +1 1 +.names 48089 48090 +0 1 +.names 47924 5304 48091 +1- 1 +-1 1 +.names 1557 48092 +0 1 +.names 47867 48092 48093 +1- 1 +-1 1 +.names 48102 48105 48094 +1- 1 +-1 1 +.names 48094 48095 +1 1 +.names 48140 48142 48096 +11 1 +.names 48096 48097 +1 1 +.names 48097 48098 +0 1 +.names 48133 48135 48099 +11 1 +.names 48099 48100 +1 1 +.names 48100 48101 +0 1 +.names 48098 48101 48102 +1- 1 +-1 1 +.names 48136 48138 48103 +11 1 +.names 48103 48104 +1 1 +.names 48104 48105 +0 1 +.names 48108 47850 48106 +11 1 +.names 48106 48107 +1 1 +.names 9630 48108 +0 1 +.names 47960 48043 48109 +11 1 +.names 48109 48110 +1 1 +.names 48113 48114 48111 +1- 1 +-1 1 +.names 48111 48112 +1 1 +.names 48107 48113 +0 1 +.names 48110 48114 +0 1 +.names 48068 48115 +1 1 +.names 48119 40614 48116 +1- 1 +-1 1 +.names 48116 48117 +1 1 +.names 48115 48118 +0 1 +.names 9650 48118 48119 +1- 1 +-1 1 +.names 48122 48123 48120 +11 1 +.names 48120 48121 +1 1 +.names 48112 48122 +0 1 +.names 48117 48123 +0 1 +.names 2413 48124 +1 1 +.names 48129 48131 48125 +1- 1 +-1 1 +.names 48125 48126 +1 1 +.names 48126 48127 +0 1 +.names 48124 48128 +0 1 +.names 48128 2413 48129 +11 1 +.names 48121 48130 +0 1 +.names 48124 48130 48131 +11 1 +.names 1558 48132 +0 1 +.names 47960 48132 48133 +1- 1 +-1 1 +.names 1559 48134 +0 1 +.names 47948 48134 48135 +1- 1 +-1 1 +.names 47850 44522 48136 +1- 1 +-1 1 +.names 1560 48137 +0 1 +.names 48108 48137 48138 +1- 1 +-1 1 +.names 1561 48139 +0 1 +.names 48139 48068 48140 +1- 1 +-1 1 +.names 1562 48141 +0 1 +.names 48043 48141 48142 +1- 1 +-1 1 +.names 48068 48143 +1 1 +.names 48149 48150 48144 +1- 1 +-1 1 +.names 48144 48145 +1 1 +.names 48175 48176 48146 +11 1 +.names 48146 48147 +1 1 +.names 48147 48148 +0 1 +.names 2413 48148 48149 +11 1 +.names 1783 2413 48150 +11 1 +.names 48159 48162 48151 +1- 1 +-1 1 +.names 48151 48152 +1 1 +.names 48179 48181 48153 +11 1 +.names 48153 48154 +1 1 +.names 48154 48155 +0 1 +.names 48185 48187 48156 +11 1 +.names 48156 48157 +1 1 +.names 48157 48158 +0 1 +.names 48155 48158 48159 +1- 1 +-1 1 +.names 48188 48189 48160 +11 1 +.names 48160 48161 +1 1 +.names 48161 48162 +0 1 +.names 48166 40659 48163 +1- 1 +-1 1 +.names 48163 48164 +1 1 +.names 48143 48165 +0 1 +.names 9643 48165 48166 +1- 1 +-1 1 +.names 48171 48174 48167 +1- 1 +-1 1 +.names 48167 48168 +1 1 +.names 48182 48183 48169 +11 1 +.names 48169 48170 +1 1 +.names 48170 48171 +0 1 +.names 47960 47924 48172 +11 1 +.names 48172 48173 +1 1 +.names 48173 48174 +0 1 +.names 48168 48175 +0 1 +.names 48164 48176 +0 1 +.names 48145 48177 +0 1 +.names 1563 48178 +0 1 +.names 47960 48178 48179 +1- 1 +-1 1 +.names 1564 48180 +0 1 +.names 48180 47886 48181 +1- 1 +-1 1 +.names 9644 48182 +0 1 +.names 9649 48183 +0 1 +.names 1565 48184 +0 1 +.names 48068 48184 48185 +1- 1 +-1 1 +.names 1566 48186 +0 1 +.names 48182 48186 48187 +1- 1 +-1 1 +.names 48183 44531 48188 +1- 1 +-1 1 +.names 47924 2413 48189 +1- 1 +-1 1 +.names 48198 48201 48190 +1- 1 +-1 1 +.names 48190 48191 +1 1 +.names 48237 48238 48192 +11 1 +.names 48192 48193 +1 1 +.names 48193 48194 +0 1 +.names 48229 48231 48195 +11 1 +.names 48195 48196 +1 1 +.names 48196 48197 +0 1 +.names 48194 48197 48198 +1- 1 +-1 1 +.names 48240 48242 48199 +11 1 +.names 48199 48200 +1 1 +.names 48200 48201 +0 1 +.names 48204 48206 48202 +1- 1 +-1 1 +.names 48202 48203 +1 1 +.names 9621 40731 48204 +1- 1 +-1 1 +.names 47886 48205 +1 1 +.names 48205 48206 +0 1 +.names 48211 48214 48207 +1- 1 +-1 1 +.names 48207 48208 +1 1 +.names 48222 48182 48209 +11 1 +.names 48209 48210 +1 1 +.names 48210 48211 +0 1 +.names 47862 47867 48212 +11 1 +.names 48212 48213 +1 1 +.names 48213 48214 +0 1 +.names 48217 48218 48215 +11 1 +.names 48215 48216 +1 1 +.names 48208 48217 +0 1 +.names 48203 48218 +0 1 +.names 48225 48227 48219 +1- 1 +-1 1 +.names 48219 48220 +1 1 +.names 48220 48221 +0 1 +.names 9629 48222 +0 1 +.names 2413 48223 +1 1 +.names 48223 48224 +0 1 +.names 48224 2413 48225 +11 1 +.names 48216 48226 +0 1 +.names 48223 48226 48227 +11 1 +.names 1567 48228 +0 1 +.names 48228 47886 48229 +1- 1 +-1 1 +.names 1568 48230 +0 1 +.names 48182 48230 48231 +1- 1 +-1 1 +.names 48234 48232 +0 1 +.names 48232 48233 +1 1 +.names 47862 48234 +1 1 +.names 1569 48235 +0 1 +.names 48233 48236 +0 1 +.names 48235 48236 48237 +1- 1 +-1 1 +.names 47902 44573 48238 +1- 1 +-1 1 +.names 1570 48239 +0 1 +.names 48222 48239 48240 +1- 1 +-1 1 +.names 1571 48241 +0 1 +.names 47867 48241 48242 +1- 1 +-1 1 +.names 48248 48249 48243 +1- 1 +-1 1 +.names 48243 48244 +1 1 +.names 48274 48275 48245 +11 1 +.names 48245 48246 +1 1 +.names 48246 48247 +0 1 +.names 2413 48247 48248 +11 1 +.names 1783 2413 48249 +11 1 +.names 48258 48261 48250 +1- 1 +-1 1 +.names 48250 48251 +1 1 +.names 48285 48287 48252 +11 1 +.names 48252 48253 +1 1 +.names 48253 48254 +0 1 +.names 48278 48280 48255 +11 1 +.names 48255 48256 +1 1 +.names 48256 48257 +0 1 +.names 48254 48257 48258 +1- 1 +-1 1 +.names 48281 48283 48259 +11 1 +.names 48259 48260 +1 1 +.names 48260 48261 +0 1 +.names 48264 48266 48262 +1- 1 +-1 1 +.names 48262 48263 +1 1 +.names 9621 40764 48264 +1- 1 +-1 1 +.names 47924 48265 +1 1 +.names 48265 48266 +0 1 +.names 47863 48032 48267 +11 1 +.names 48267 48268 +1 1 +.names 47962 48271 48269 +11 1 +.names 48269 48270 +1 1 +.names 9637 48271 +0 1 +.names 48288 48289 48272 +1- 1 +-1 1 +.names 48272 48273 +1 1 +.names 48273 48274 +0 1 +.names 48263 48275 +0 1 +.names 48244 48276 +0 1 +.names 1572 48277 +0 1 +.names 48271 48277 48278 +1- 1 +-1 1 +.names 1573 48279 +0 1 +.names 48279 47962 48280 +1- 1 +-1 1 +.names 47902 44581 48281 +1- 1 +-1 1 +.names 848 48282 +0 1 +.names 47924 48282 48283 +1- 1 +-1 1 +.names 1574 48284 +0 1 +.names 48032 48284 48285 +1- 1 +-1 1 +.names 1575 48286 +0 1 +.names 47863 48286 48287 +1- 1 +-1 1 +.names 48268 48288 +0 1 +.names 48270 48289 +0 1 +.names 48300 48303 48290 +11 1 +.names 48290 48291 +1 1 +.names 48291 48292 +0 1 +.names 48306 48309 48293 +11 1 +.names 48293 48294 +1 1 +.names 48294 48295 +0 1 +.names 1576 48296 +0 1 +.names 48296 48297 +1 1 +.names 48334 48336 48298 +1- 1 +-1 1 +.names 48298 48299 +1 1 +.names 48299 48300 +0 1 +.names 48345 48346 48301 +1- 1 +-1 1 +.names 48301 48302 +1 1 +.names 48302 48303 +0 1 +.names 48343 48344 48304 +1- 1 +-1 1 +.names 48304 48305 +1 1 +.names 48305 48306 +0 1 +.names 48310 48313 48307 +1- 1 +-1 1 +.names 48307 48308 +1 1 +.names 48308 48309 +0 1 +.names 9617 1577 48310 +11 1 +.names 47960 48342 48311 +1- 1 +-1 1 +.names 48311 48312 +1 1 +.names 48312 48313 +0 1 +.names 2413 48317 48314 +11 1 +.names 48314 48315 +1 1 +.names 40812 48316 +1 1 +.names 48316 48317 +0 1 +.names 47992 47850 48318 +11 1 +.names 48318 48319 +1 1 +.names 47960 48222 48320 +11 1 +.names 48320 48321 +1 1 +.names 48329 48330 48322 +1- 1 +-1 1 +.names 48322 48323 +1 1 +.names 48321 48324 +0 1 +.names 47962 48325 +1 1 +.names 48325 48326 +0 1 +.names 48324 48326 48327 +1- 1 +-1 1 +.names 48319 48328 +0 1 +.names 48327 48328 48329 +1- 1 +-1 1 +.names 48315 48330 +0 1 +.names 48032 48331 +1 1 +.names 48331 48332 +0 1 +.names 48297 48333 +0 1 +.names 48332 48333 48334 +11 1 +.names 48323 48335 +0 1 +.names 48331 48335 48336 +11 1 +.names 47992 48339 48337 +1- 1 +-1 1 +.names 48337 48338 +1 1 +.names 1578 48339 +0 1 +.names 47850 44591 48340 +1- 1 +-1 1 +.names 48340 48341 +1 1 +.names 1579 48342 +0 1 +.names 9629 1783 48343 +11 1 +.names 48341 48344 +0 1 +.names 1783 48345 +1 1 +.names 48338 48346 +0 1 +.names 48357 48360 48347 +11 1 +.names 48347 48348 +1 1 +.names 48348 48349 +0 1 +.names 48363 48366 48350 +11 1 +.names 48350 48351 +1 1 +.names 48351 48352 +0 1 +.names 1580 48353 +0 1 +.names 48353 48354 +1 1 +.names 48382 48384 48355 +1- 1 +-1 1 +.names 48355 48356 +1 1 +.names 48356 48357 +0 1 +.names 48398 48399 48358 +1- 1 +-1 1 +.names 48358 48359 +1 1 +.names 48359 48360 +0 1 +.names 48367 48370 48361 +1- 1 +-1 1 +.names 48361 48362 +1 1 +.names 48362 48363 +0 1 +.names 48400 48401 48364 +1- 1 +-1 1 +.names 48364 48365 +1 1 +.names 48365 48366 +0 1 +.names 9630 1581 48367 +11 1 +.names 47850 44599 48368 +1- 1 +-1 1 +.names 48368 48369 +1 1 +.names 48369 48370 +0 1 +.names 2413 48374 48371 +11 1 +.names 48371 48372 +1 1 +.names 40869 48373 +1 1 +.names 48373 48374 +0 1 +.names 47850 47992 48375 +11 1 +.names 48375 48376 +1 1 +.names 47867 48108 48377 +11 1 +.names 48377 48378 +1 1 +.names 48390 48391 48379 +1- 1 +-1 1 +.names 48379 48380 +1 1 +.names 48380 48381 +0 1 +.names 47886 48381 48382 +11 1 +.names 48354 48383 +0 1 +.names 9643 48383 48384 +11 1 +.names 48378 48385 +0 1 +.names 48068 48386 +1 1 +.names 48386 48387 +0 1 +.names 48385 48387 48388 +1- 1 +-1 1 +.names 48376 48389 +0 1 +.names 48388 48389 48390 +1- 1 +-1 1 +.names 48372 48391 +0 1 +.names 47867 48394 48392 +1- 1 +-1 1 +.names 48392 48393 +1 1 +.names 1582 48394 +0 1 +.names 47992 48397 48395 +1- 1 +-1 1 +.names 48395 48396 +1 1 +.names 1583 48397 +0 1 +.names 1783 48398 +1 1 +.names 48396 48399 +0 1 +.names 9638 1584 48400 +11 1 +.names 48393 48401 +0 1 +.names 48405 48406 48402 +11 1 +.names 48402 48403 +1 1 +.names 1585 48404 +0 1 +.names 48404 47962 48405 +1- 1 +-1 1 +.names 47902 44608 48406 +1- 1 +-1 1 +.names 48409 48411 48407 +1- 1 +-1 1 +.names 48407 48408 +1 1 +.names 9621 40932 48409 +1- 1 +-1 1 +.names 48032 48410 +1 1 +.names 48410 48411 +0 1 +.names 48416 48419 48412 +1- 1 +-1 1 +.names 48412 48413 +1 1 +.names 47962 47960 48414 +11 1 +.names 48414 48415 +1 1 +.names 48415 48416 +0 1 +.names 48222 48182 48417 +11 1 +.names 48417 48418 +1 1 +.names 48418 48419 +0 1 +.names 48422 48423 48420 +11 1 +.names 48420 48421 +1 1 +.names 48413 48422 +0 1 +.names 48408 48423 +0 1 +.names 48443 48444 48424 +1- 1 +-1 1 +.names 48424 48425 +1 1 +.names 48436 48438 48426 +1- 1 +-1 1 +.names 48426 48427 +1 1 +.names 48427 48428 +0 1 +.names 48431 48433 48429 +11 1 +.names 48429 48430 +1 1 +.names 48222 2413 48431 +1- 1 +-1 1 +.names 1586 48432 +0 1 +.names 47960 48432 48433 +1- 1 +-1 1 +.names 2413 48434 +1 1 +.names 48434 48435 +0 1 +.names 48435 2413 48436 +11 1 +.names 48421 48437 +0 1 +.names 48434 48437 48438 +11 1 +.names 48403 48439 +0 1 +.names 48446 48448 48440 +11 1 +.names 48440 48441 +1 1 +.names 48441 48442 +0 1 +.names 48439 48442 48443 +1- 1 +-1 1 +.names 48430 48444 +0 1 +.names 1587 48445 +0 1 +.names 48032 48445 48446 +1- 1 +-1 1 +.names 1588 48447 +0 1 +.names 48182 48447 48448 +1- 1 +-1 1 +.names 48454 48455 48449 +1- 1 +-1 1 +.names 48449 48450 +1 1 +.names 48469 48470 48451 +11 1 +.names 48451 48452 +1 1 +.names 48452 48453 +0 1 +.names 48043 48453 48454 +11 1 +.names 9636 2413 48455 +11 1 +.names 48458 48460 48456 +1- 1 +-1 1 +.names 48456 48457 +1 1 +.names 9627 40976 48458 +1- 1 +-1 1 +.names 48032 48459 +1 1 +.names 48459 48460 +0 1 +.names 48465 48468 48461 +1- 1 +-1 1 +.names 48461 48462 +1 1 +.names 2413 47862 48463 +11 1 +.names 48463 48464 +1 1 +.names 48464 48465 +0 1 +.names 48271 48108 48466 +11 1 +.names 48466 48467 +1 1 +.names 48467 48468 +0 1 +.names 48462 48469 +0 1 +.names 48457 48470 +0 1 +.names 48492 48493 48471 +1- 1 +-1 1 +.names 48471 48472 +1 1 +.names 48450 48473 +0 1 +.names 2413 48474 +1 1 +.names 2413 48475 +1 1 +.names 48478 48479 48476 +11 1 +.names 48476 48477 +1 1 +.names 48271 2413 48478 +1- 1 +-1 1 +.names 47850 2413 48479 +1- 1 +-1 1 +.names 48483 48484 48480 +11 1 +.names 48480 48481 +1 1 +.names 1589 48482 +0 1 +.names 48032 48482 48483 +1- 1 +-1 1 +.names 2413 47862 48484 +1- 1 +-1 1 +.names 48488 48489 48485 +11 1 +.names 48485 48486 +1 1 +.names 1590 48487 +0 1 +.names 48108 48487 48488 +1- 1 +-1 1 +.names 48474 48475 48489 +1- 1 +-1 1 +.names 48477 48490 +0 1 +.names 48481 48491 +0 1 +.names 48490 48491 48492 +1- 1 +-1 1 +.names 48486 48493 +0 1 +.names 48499 48500 48494 +1- 1 +-1 1 +.names 48494 48495 +1 1 +.names 48526 48527 48496 +11 1 +.names 48496 48497 +1 1 +.names 48497 48498 +0 1 +.names 2413 48498 48499 +11 1 +.names 1783 2413 48500 +11 1 +.names 48509 48512 48501 +1- 1 +-1 1 +.names 48501 48502 +1 1 +.names 48538 48539 48503 +11 1 +.names 48503 48504 +1 1 +.names 48504 48505 +0 1 +.names 48534 48536 48506 +11 1 +.names 48506 48507 +1 1 +.names 48507 48508 +0 1 +.names 48505 48508 48509 +1- 1 +-1 1 +.names 48530 48532 48510 +11 1 +.names 48510 48511 +1 1 +.names 48511 48512 +0 1 +.names 48515 48517 48513 +1- 1 +-1 1 +.names 48513 48514 +1 1 +.names 9649 41012 48515 +1- 1 +-1 1 +.names 48068 48516 +1 1 +.names 48516 48517 +0 1 +.names 48522 48525 48518 +1- 1 +-1 1 +.names 48518 48519 +1 1 +.names 47886 47863 48520 +11 1 +.names 48520 48521 +1 1 +.names 48521 48522 +0 1 +.names 48271 47924 48523 +11 1 +.names 48523 48524 +1 1 +.names 48524 48525 +0 1 +.names 48519 48526 +0 1 +.names 48514 48527 +0 1 +.names 48495 48528 +0 1 +.names 1591 48529 +0 1 +.names 47886 48529 48530 +1- 1 +-1 1 +.names 1592 48531 +0 1 +.names 47924 48531 48532 +1- 1 +-1 1 +.names 1593 48533 +0 1 +.names 48068 48533 48534 +1- 1 +-1 1 +.names 1594 48535 +0 1 +.names 47863 48535 48536 +1- 1 +-1 1 +.names 1595 48537 +0 1 +.names 48271 48537 48538 +1- 1 +-1 1 +.names 48183 44633 48539 +1- 1 +-1 1 +.names 48545 48546 48540 +1- 1 +-1 1 +.names 48540 48541 +1 1 +.names 48573 48574 48542 +11 1 +.names 48542 48543 +1 1 +.names 48543 48544 +0 1 +.names 2413 48544 48545 +11 1 +.names 1783 2413 48546 +11 1 +.names 48555 48558 48547 +1- 1 +-1 1 +.names 48547 48548 +1 1 +.names 48580 48582 48549 +11 1 +.names 48549 48550 +1 1 +.names 48550 48551 +0 1 +.names 48584 48586 48552 +11 1 +.names 48552 48553 +1 1 +.names 48553 48554 +0 1 +.names 48551 48554 48555 +1- 1 +-1 1 +.names 48576 48578 48556 +11 1 +.names 48556 48557 +1 1 +.names 48557 48558 +0 1 +.names 48561 48564 48559 +1- 1 +-1 1 +.names 48559 48560 +1 1 +.names 9625 41054 48561 +1- 1 +-1 1 +.names 9645 48562 +0 1 +.names 48562 48563 +1 1 +.names 48563 48564 +0 1 +.names 48569 48572 48565 +1- 1 +-1 1 +.names 48565 48566 +1 1 +.names 47862 48271 48567 +11 1 +.names 48567 48568 +1 1 +.names 48568 48569 +0 1 +.names 48182 47948 48570 +11 1 +.names 48570 48571 +1 1 +.names 48571 48572 +0 1 +.names 48566 48573 +0 1 +.names 48560 48574 +0 1 +.names 48541 48575 +0 1 +.names 47980 44642 48576 +1- 1 +-1 1 +.names 1596 48577 +0 1 +.names 48562 48577 48578 +1- 1 +-1 1 +.names 1597 48579 +0 1 +.names 48271 48579 48580 +1- 1 +-1 1 +.names 1598 48581 +0 1 +.names 48581 47862 48582 +1- 1 +-1 1 +.names 1599 48583 +0 1 +.names 47948 48583 48584 +1- 1 +-1 1 +.names 1600 48585 +0 1 +.names 48182 48585 48586 +1- 1 +-1 1 +.names 48592 48593 48587 +1- 1 +-1 1 +.names 48587 48588 +1 1 +.names 48617 48618 48589 +11 1 +.names 48589 48590 +1 1 +.names 48590 48591 +0 1 +.names 2413 48591 48592 +11 1 +.names 1783 2413 48593 +11 1 +.names 48602 48605 48594 +1- 1 +-1 1 +.names 48594 48595 +1 1 +.names 48625 48626 48596 +11 1 +.names 48596 48597 +1 1 +.names 48597 48598 +0 1 +.names 48628 48630 48599 +11 1 +.names 48599 48600 +1 1 +.names 48600 48601 +0 1 +.names 48598 48601 48602 +1- 1 +-1 1 +.names 48621 48623 48603 +11 1 +.names 48603 48604 +1 1 +.names 48604 48605 +0 1 +.names 48608 48610 48606 +1- 1 +-1 1 +.names 48606 48607 +1 1 +.names 9625 41119 48608 +1- 1 +-1 1 +.names 47886 48609 +1 1 +.names 48609 48610 +0 1 +.names 47866 47863 48611 +11 1 +.names 48611 48612 +1 1 +.names 48068 48271 48613 +11 1 +.names 48613 48614 +1 1 +.names 48631 48632 48615 +1- 1 +-1 1 +.names 48615 48616 +1 1 +.names 48616 48617 +0 1 +.names 48607 48618 +0 1 +.names 48588 48619 +0 1 +.names 1601 48620 +0 1 +.names 47866 48620 48621 +1- 1 +-1 1 +.names 1602 48622 +0 1 +.names 48271 48622 48623 +1- 1 +-1 1 +.names 1603 48624 +0 1 +.names 48624 48068 48625 +1- 1 +-1 1 +.names 47980 44651 48626 +1- 1 +-1 1 +.names 1604 48627 +0 1 +.names 47886 48627 48628 +1- 1 +-1 1 +.names 1605 48629 +0 1 +.names 47863 48629 48630 +1- 1 +-1 1 +.names 48612 48631 +0 1 +.names 48614 48632 +0 1 +.names 48641 48644 48633 +1- 1 +-1 1 +.names 48633 48634 +1 1 +.names 48675 48676 48635 +11 1 +.names 48635 48636 +1 1 +.names 48636 48637 +0 1 +.names 48671 48673 48638 +11 1 +.names 48638 48639 +1 1 +.names 48639 48640 +0 1 +.names 48637 48640 48641 +1- 1 +-1 1 +.names 48677 48679 48642 +11 1 +.names 48642 48643 +1 1 +.names 48643 48644 +0 1 +.names 48647 48649 48645 +1- 1 +-1 1 +.names 48645 48646 +1 1 +.names 9625 41159 48647 +1- 1 +-1 1 +.names 48032 48648 +1 1 +.names 48648 48649 +0 1 +.names 48654 48657 48650 +1- 1 +-1 1 +.names 48650 48651 +1 1 +.names 48222 47992 48652 +11 1 +.names 48652 48653 +1 1 +.names 48653 48654 +0 1 +.names 48068 47867 48655 +11 1 +.names 48655 48656 +1 1 +.names 48656 48657 +0 1 +.names 48660 48661 48658 +11 1 +.names 48658 48659 +1 1 +.names 48651 48660 +0 1 +.names 48646 48661 +0 1 +.names 48667 48669 48662 +1- 1 +-1 1 +.names 48662 48663 +1 1 +.names 48663 48664 +0 1 +.names 2413 48665 +1 1 +.names 48665 48666 +0 1 +.names 48666 2413 48667 +11 1 +.names 48659 48668 +0 1 +.names 48665 48668 48669 +11 1 +.names 1606 48670 +0 1 +.names 48670 48032 48671 +1- 1 +-1 1 +.names 1607 48672 +0 1 +.names 47992 48672 48673 +1- 1 +-1 1 +.names 1608 48674 +0 1 +.names 48674 48068 48675 +1- 1 +-1 1 +.names 47980 44660 48676 +1- 1 +-1 1 +.names 48222 2413 48677 +1- 1 +-1 1 +.names 1609 48678 +0 1 +.names 47867 48678 48679 +1- 1 +-1 1 +.names 48688 48691 48680 +1- 1 +-1 1 +.names 48680 48681 +1 1 +.names 48710 48711 48682 +11 1 +.names 48682 48683 +1 1 +.names 48683 48684 +0 1 +.names 48704 48706 48685 +11 1 +.names 48685 48686 +1 1 +.names 48686 48687 +0 1 +.names 48684 48687 48688 +1- 1 +-1 1 +.names 48707 48708 48689 +11 1 +.names 48689 48690 +1 1 +.names 48690 48691 +0 1 +.names 48695 2413 48692 +11 1 +.names 48692 48693 +1 1 +.names 41221 48694 +1 1 +.names 48694 48695 +0 1 +.names 47948 48183 48696 +11 1 +.names 48696 48697 +1 1 +.names 47867 48562 48698 +11 1 +.names 48698 48699 +1 1 +.names 48714 48717 48700 +1- 1 +-1 1 +.names 48700 48701 +1 1 +.names 48701 48702 +0 1 +.names 1610 48703 +0 1 +.names 48703 47863 48704 +1- 1 +-1 1 +.names 1611 48705 +0 1 +.names 47948 48705 48706 +1- 1 +-1 1 +.names 48183 44668 48707 +1- 1 +-1 1 +.names 48562 2413 48708 +1- 1 +-1 1 +.names 1612 48709 +0 1 +.names 47867 48709 48710 +1- 1 +-1 1 +.names 2413 48711 +1 1 +.names 48723 48724 48712 +1- 1 +-1 1 +.names 48712 48713 +1 1 +.names 48068 48713 48714 +11 1 +.names 1613 48715 +0 1 +.names 48715 48716 +1 1 +.names 9638 48716 48717 +11 1 +.names 47863 48718 +1 1 +.names 48693 48719 +0 1 +.names 48718 48720 +0 1 +.names 48719 48720 48721 +1- 1 +-1 1 +.names 48697 48722 +0 1 +.names 48721 48722 48723 +1- 1 +-1 1 +.names 48699 48724 +0 1 +.names 48727 48729 48725 +1- 1 +-1 1 +.names 48725 48726 +1 1 +.names 9621 41264 48727 +1- 1 +-1 1 +.names 48032 48728 +1 1 +.names 48728 48729 +0 1 +.names 48734 48737 48730 +1- 1 +-1 1 +.names 48730 48731 +1 1 +.names 48068 47960 48732 +11 1 +.names 48732 48733 +1 1 +.names 48733 48734 +0 1 +.names 48108 47992 48735 +11 1 +.names 48735 48736 +1 1 +.names 48736 48737 +0 1 +.names 48740 48741 48738 +11 1 +.names 48738 48739 +1 1 +.names 48731 48740 +0 1 +.names 48726 48741 +0 1 +.names 48759 48760 48742 +1- 1 +-1 1 +.names 48742 48743 +1 1 +.names 48766 48767 48744 +1- 1 +-1 1 +.names 48744 48745 +1 1 +.names 48745 48746 +0 1 +.names 48750 48752 48747 +11 1 +.names 48747 48748 +1 1 +.names 1614 48749 +0 1 +.names 48108 48749 48750 +1- 1 +-1 1 +.names 1615 48751 +0 1 +.names 47960 48751 48752 +1- 1 +-1 1 +.names 48769 48770 48753 +11 1 +.names 48753 48754 +1 1 +.names 48754 48755 +0 1 +.names 48762 48764 48756 +11 1 +.names 48756 48757 +1 1 +.names 48757 48758 +0 1 +.names 48755 48758 48759 +1- 1 +-1 1 +.names 48748 48760 +0 1 +.names 1616 48761 +0 1 +.names 48761 48032 48762 +1- 1 +-1 1 +.names 1617 48763 +0 1 +.names 47992 48763 48764 +1- 1 +-1 1 +.names 48739 48765 +0 1 +.names 2413 48765 48766 +11 1 +.names 1783 2413 48767 +11 1 +.names 1618 48768 +0 1 +.names 48768 48068 48769 +1- 1 +-1 1 +.names 47902 44678 48770 +1- 1 +-1 1 +.names 48775 41298 48771 +1- 1 +-1 1 +.names 48771 48772 +1 1 +.names 47902 48773 +1 1 +.names 48773 48774 +0 1 +.names 9650 48774 48775 +1- 1 +-1 1 +.names 48043 48271 48776 +11 1 +.names 48776 48777 +1 1 +.names 48782 48783 48778 +11 1 +.names 48778 48779 +1 1 +.names 48805 48806 48780 +1- 1 +-1 1 +.names 48780 48781 +1 1 +.names 48781 48782 +0 1 +.names 48772 48783 +0 1 +.names 48814 48815 48784 +1- 1 +-1 1 +.names 48784 48785 +1 1 +.names 48803 48804 48786 +1- 1 +-1 1 +.names 48786 48787 +1 1 +.names 48787 48788 +0 1 +.names 47962 48562 48789 +11 1 +.names 48789 48790 +1 1 +.names 48793 48795 48791 +11 1 +.names 48791 48792 +1 1 +.names 47902 44617 48793 +1- 1 +-1 1 +.names 1619 48794 +0 1 +.names 48562 48794 48795 +1- 1 +-1 1 +.names 48799 48801 48796 +11 1 +.names 48796 48797 +1 1 +.names 1620 48798 +0 1 +.names 48271 48798 48799 +1- 1 +-1 1 +.names 1621 48800 +0 1 +.names 47948 48800 48801 +1- 1 +-1 1 +.names 48779 48802 +0 1 +.names 2413 48802 48803 +11 1 +.names 1783 2413 48804 +11 1 +.names 48790 48805 +0 1 +.names 48777 48806 +0 1 +.names 48810 48811 48807 +11 1 +.names 48807 48808 +1 1 +.names 1622 48809 +0 1 +.names 47962 48809 48810 +1- 1 +-1 1 +.names 48043 2413 48811 +1- 1 +-1 1 +.names 48797 48812 +0 1 +.names 48808 48813 +0 1 +.names 48812 48813 48814 +1- 1 +-1 1 +.names 48792 48815 +0 1 +.names 48821 48822 48816 +1- 1 +-1 1 +.names 48816 48817 +1 1 +.names 48848 48849 48818 +11 1 +.names 48818 48819 +1 1 +.names 48819 48820 +0 1 +.names 2413 48820 48821 +11 1 +.names 1783 2413 48822 +11 1 +.names 48831 48834 48823 +1- 1 +-1 1 +.names 48823 48824 +1 1 +.names 48858 48860 48825 +11 1 +.names 48825 48826 +1 1 +.names 48826 48827 +0 1 +.names 48854 48856 48828 +11 1 +.names 48828 48829 +1 1 +.names 48829 48830 +0 1 +.names 48827 48830 48831 +1- 1 +-1 1 +.names 48851 48852 48832 +11 1 +.names 48832 48833 +1 1 +.names 48833 48834 +0 1 +.names 48837 48839 48835 +1- 1 +-1 1 +.names 48835 48836 +1 1 +.names 9621 41355 48837 +1- 1 +-1 1 +.names 48562 48838 +1 1 +.names 48838 48839 +0 1 +.names 48844 48847 48840 +1- 1 +-1 1 +.names 48840 48841 +1 1 +.names 47862 48271 48842 +11 1 +.names 48842 48843 +1 1 +.names 48843 48844 +0 1 +.names 48182 47948 48845 +11 1 +.names 48845 48846 +1 1 +.names 48846 48847 +0 1 +.names 48841 48848 +0 1 +.names 48836 48849 +0 1 +.names 48817 48850 +0 1 +.names 47902 44625 48851 +1- 1 +-1 1 +.names 48562 4848 48852 +1- 1 +-1 1 +.names 1623 48853 +0 1 +.names 48271 48853 48854 +1- 1 +-1 1 +.names 1624 48855 +0 1 +.names 48855 47862 48856 +1- 1 +-1 1 +.names 1625 48857 +0 1 +.names 47948 48857 48858 +1- 1 +-1 1 +.names 1626 48859 +0 1 +.names 48182 48859 48860 +1- 1 +-1 1 +.names 47962 48861 +1 1 +.names 48867 48869 48862 +1- 1 +-1 1 +.names 48862 48863 +1 1 +.names 48899 48900 48864 +11 1 +.names 48864 48865 +1 1 +.names 48865 48866 +0 1 +.names 47992 48866 48867 +11 1 +.names 1627 48868 +0 1 +.names 9640 48868 48869 +11 1 +.names 48878 48881 48870 +1- 1 +-1 1 +.names 48870 48871 +1 1 +.names 48904 48906 48872 +11 1 +.names 48872 48873 +1 1 +.names 48873 48874 +0 1 +.names 48891 48893 48875 +11 1 +.names 48875 48876 +1 1 +.names 48876 48877 +0 1 +.names 48874 48877 48878 +1- 1 +-1 1 +.names 48894 48896 48879 +11 1 +.names 48879 48880 +1 1 +.names 48880 48881 +0 1 +.names 48885 41428 48882 +1- 1 +-1 1 +.names 48882 48883 +1 1 +.names 48861 48884 +0 1 +.names 9603 48884 48885 +1- 1 +-1 1 +.names 48562 2413 48886 +11 1 +.names 48886 48887 +1 1 +.names 48271 48183 48888 +11 1 +.names 48888 48889 +1 1 +.names 48863 48890 +0 1 +.names 2413 48891 +1 1 +.names 1628 48892 +0 1 +.names 48271 48892 48893 +1- 1 +-1 1 +.names 48183 44686 48894 +1- 1 +-1 1 +.names 795 48895 +0 1 +.names 48562 48895 48896 +1- 1 +-1 1 +.names 48901 48902 48897 +1- 1 +-1 1 +.names 48897 48898 +1 1 +.names 48898 48899 +0 1 +.names 48883 48900 +0 1 +.names 48887 48901 +0 1 +.names 48889 48902 +0 1 +.names 1629 48903 +0 1 +.names 48032 48903 48904 +1- 1 +-1 1 +.names 1630 48905 +0 1 +.names 48905 47962 48906 +1- 1 +-1 1 +.names 47962 48907 +1 1 +.names 48913 48914 48908 +1- 1 +-1 1 +.names 48908 48909 +1 1 +.names 48927 48928 48910 +11 1 +.names 48910 48911 +1 1 +.names 48911 48912 +0 1 +.names 2413 48912 48913 +11 1 +.names 1783 2413 48914 +11 1 +.names 48917 48918 48915 +1- 1 +-1 1 +.names 48915 48916 +1 1 +.names 9649 41460 48917 +1- 1 +-1 1 +.names 48907 48918 +0 1 +.names 48923 48926 48919 +1- 1 +-1 1 +.names 48919 48920 +1 1 +.names 47948 47992 48921 +11 1 +.names 48921 48922 +1 1 +.names 48922 48923 +0 1 +.names 47867 47924 48924 +11 1 +.names 48924 48925 +1 1 +.names 48925 48926 +0 1 +.names 48920 48927 +0 1 +.names 48916 48928 +0 1 +.names 48945 48948 48929 +1- 1 +-1 1 +.names 48929 48930 +1 1 +.names 48909 48931 +0 1 +.names 48935 48937 48932 +11 1 +.names 48932 48933 +1 1 +.names 1631 48934 +0 1 +.names 48934 47962 48935 +1- 1 +-1 1 +.names 1632 48936 +0 1 +.names 47992 48936 48937 +1- 1 +-1 1 +.names 48941 48942 48938 +11 1 +.names 48938 48939 +1 1 +.names 1633 48940 +0 1 +.names 47867 48940 48941 +1- 1 +-1 1 +.names 48183 44694 48942 +1- 1 +-1 1 +.names 48939 48943 +0 1 +.names 48933 48944 +0 1 +.names 48943 48944 48945 +1- 1 +-1 1 +.names 48950 48952 48946 +11 1 +.names 48946 48947 +1 1 +.names 48947 48948 +0 1 +.names 1634 48949 +0 1 +.names 48949 47948 48950 +1- 1 +-1 1 +.names 57097 48951 +0 1 +.names 47924 48951 48952 +1- 1 +-1 1 +.names 47960 47866 48953 +11 1 +.names 48953 48954 +1 1 +.names 47962 48955 +1 1 +.names 48043 47850 48956 +11 1 +.names 48956 48957 +1 1 +.names 2413 48961 48958 +11 1 +.names 48958 48959 +1 1 +.names 41506 48960 +1 1 +.names 48960 48961 +0 1 +.names 48968 48969 48962 +1- 1 +-1 1 +.names 48962 48963 +1 1 +.names 48954 48964 +0 1 +.names 48955 48965 +0 1 +.names 48964 48965 48966 +1- 1 +-1 1 +.names 48957 48967 +0 1 +.names 48966 48967 48968 +1- 1 +-1 1 +.names 48959 48969 +0 1 +.names 1635 48970 +0 1 +.names 48970 48971 +1 1 +.names 48975 48977 48972 +1- 1 +-1 1 +.names 48972 48973 +1 1 +.names 48963 48974 +0 1 +.names 48032 48974 48975 +11 1 +.names 48971 48976 +0 1 +.names 9603 48976 48977 +11 1 +.names 48043 48980 48978 +1- 1 +-1 1 +.names 48978 48979 +1 1 +.names 1636 48980 +0 1 +.names 48983 48986 48981 +11 1 +.names 48981 48982 +1 1 +.names 48973 48983 +0 1 +.names 49008 49009 48984 +1- 1 +-1 1 +.names 48984 48985 +1 1 +.names 48985 48986 +0 1 +.names 47850 44703 48987 +1- 1 +-1 1 +.names 48987 48988 +1 1 +.names 47960 48989 +1 1 +.names 48989 48990 +0 1 +.names 48990 48991 +1 1 +.names 48994 48995 48992 +1- 1 +-1 1 +.names 48992 48993 +1 1 +.names 48991 48994 +0 1 +.names 1637 48995 +0 1 +.names 48998 48999 48996 +1- 1 +-1 1 +.names 48996 48997 +1 1 +.names 9617 1638 48998 +11 1 +.names 48993 48999 +0 1 +.names 49004 49005 49000 +11 1 +.names 49000 49001 +1 1 +.names 49010 49011 49002 +1- 1 +-1 1 +.names 49002 49003 +1 1 +.names 49003 49004 +0 1 +.names 48997 49005 +0 1 +.names 48982 49006 +0 1 +.names 49001 49007 +0 1 +.names 1783 49008 +1 1 +.names 48979 49009 +0 1 +.names 9651 1783 49010 +11 1 +.names 48988 49011 +0 1 +.names 49017 49018 49012 +1- 1 +-1 1 +.names 49012 49013 +1 1 +.names 49030 49031 49014 +11 1 +.names 49014 49015 +1 1 +.names 49015 49016 +0 1 +.names 2413 49016 49017 +11 1 +.names 1783 2413 49018 +11 1 +.names 49021 49023 49019 +1- 1 +-1 1 +.names 49019 49020 +1 1 +.names 9625 41551 49021 +1- 1 +-1 1 +.names 47866 49022 +1 1 +.names 49022 49023 +0 1 +.names 47863 48032 49024 +11 1 +.names 49024 49025 +1 1 +.names 47962 48271 49026 +11 1 +.names 49026 49027 +1 1 +.names 49056 49057 49028 +1- 1 +-1 1 +.names 49028 49029 +1 1 +.names 49029 49030 +0 1 +.names 49020 49031 +0 1 +.names 49045 49048 49032 +1- 1 +-1 1 +.names 49032 49033 +1 1 +.names 49013 49034 +0 1 +.names 49038 49040 49035 +11 1 +.names 49035 49036 +1 1 +.names 1639 49037 +0 1 +.names 48271 49037 49038 +1- 1 +-1 1 +.names 1640 49039 +0 1 +.names 49039 47962 49040 +1- 1 +-1 1 +.names 49053 49055 49041 +11 1 +.names 49041 49042 +1 1 +.names 49042 49043 +0 1 +.names 49036 49044 +0 1 +.names 49043 49044 49045 +1- 1 +-1 1 +.names 49049 49051 49046 +11 1 +.names 49046 49047 +1 1 +.names 49047 49048 +0 1 +.names 47980 44711 49049 +1- 1 +-1 1 +.names 1641 49050 +0 1 +.names 47866 49050 49051 +1- 1 +-1 1 +.names 1642 49052 +0 1 +.names 48032 49052 49053 +1- 1 +-1 1 +.names 1643 49054 +0 1 +.names 47863 49054 49055 +1- 1 +-1 1 +.names 49025 49056 +0 1 +.names 49027 49057 +0 1 +.names 49066 49069 49058 +1- 1 +-1 1 +.names 49058 49059 +1 1 +.names 49102 49104 49060 +11 1 +.names 49060 49061 +1 1 +.names 49061 49062 +0 1 +.names 49099 49101 49063 +11 1 +.names 49063 49064 +1 1 +.names 49064 49065 +0 1 +.names 49062 49065 49066 +1- 1 +-1 1 +.names 49091 49092 49067 +11 1 +.names 49067 49068 +1 1 +.names 49068 49069 +0 1 +.names 49074 41598 49070 +1- 1 +-1 1 +.names 49070 49071 +1 1 +.names 47980 49072 +1 1 +.names 49072 49073 +0 1 +.names 9629 49073 49074 +1- 1 +-1 1 +.names 49079 49082 49075 +1- 1 +-1 1 +.names 49075 49076 +1 1 +.names 2413 47886 49077 +11 1 +.names 49077 49078 +1 1 +.names 49078 49079 +0 1 +.names 47862 47867 49080 +11 1 +.names 49080 49081 +1 1 +.names 49081 49082 +0 1 +.names 49085 49086 49083 +11 1 +.names 49083 49084 +1 1 +.names 49076 49085 +0 1 +.names 49071 49086 +0 1 +.names 49096 49098 49087 +1- 1 +-1 1 +.names 49087 49088 +1 1 +.names 49088 49089 +0 1 +.names 1644 49090 +0 1 +.names 49090 47862 49091 +1- 1 +-1 1 +.names 2413 48222 49092 +1- 1 +-1 1 +.names 48182 49093 +1 1 +.names 49093 49094 +0 1 +.names 1645 49095 +0 1 +.names 49094 49095 49096 +11 1 +.names 49084 49097 +0 1 +.names 49093 49097 49098 +11 1 +.names 2413 49099 +1 1 +.names 1646 49100 +0 1 +.names 47867 49100 49101 +1- 1 +-1 1 +.names 47980 44720 49102 +1- 1 +-1 1 +.names 1647 49103 +0 1 +.names 47886 49103 49104 +1- 1 +-1 1 +.names 49110 49111 49105 +1- 1 +-1 1 +.names 49105 49106 +1 1 +.names 49137 49138 49107 +11 1 +.names 49107 49108 +1 1 +.names 49108 49109 +0 1 +.names 2413 49109 49110 +11 1 +.names 1783 2413 49111 +11 1 +.names 49120 49123 49112 +1- 1 +-1 1 +.names 49112 49113 +1 1 +.names 49147 49149 49114 +11 1 +.names 49114 49115 +1 1 +.names 49115 49116 +0 1 +.names 49143 49145 49117 +11 1 +.names 49117 49118 +1 1 +.names 49118 49119 +0 1 +.names 49116 49119 49120 +1- 1 +-1 1 +.names 49140 49141 49121 +11 1 +.names 49121 49122 +1 1 +.names 49122 49123 +0 1 +.names 49126 49128 49124 +1- 1 +-1 1 +.names 49124 49125 +1 1 +.names 9621 41659 49126 +1- 1 +-1 1 +.names 48108 49127 +1 1 +.names 49127 49128 +0 1 +.names 49133 49136 49129 +1- 1 +-1 1 +.names 49129 49130 +1 1 +.names 47862 48271 49131 +11 1 +.names 49131 49132 +1 1 +.names 49132 49133 +0 1 +.names 48182 47948 49134 +11 1 +.names 49134 49135 +1 1 +.names 49135 49136 +0 1 +.names 49130 49137 +0 1 +.names 49125 49138 +0 1 +.names 49106 49139 +0 1 +.names 47902 44729 49140 +1- 1 +-1 1 +.names 48108 2413 49141 +1- 1 +-1 1 +.names 1648 49142 +0 1 +.names 48271 49142 49143 +1- 1 +-1 1 +.names 1649 49144 +0 1 +.names 47862 49144 49145 +1- 1 +-1 1 +.names 1650 49146 +0 1 +.names 47948 49146 49147 +1- 1 +-1 1 +.names 1651 49148 +0 1 +.names 48182 49148 49149 +1- 1 +-1 1 +.names 49152 49154 49150 +1- 1 +-1 1 +.names 49150 49151 +1 1 +.names 9649 41702 49152 +1- 1 +-1 1 +.names 47886 49153 +1 1 +.names 49153 49154 +0 1 +.names 49159 49162 49155 +1- 1 +-1 1 +.names 49155 49156 +1 1 +.names 2413 47862 49157 +11 1 +.names 49157 49158 +1 1 +.names 49158 49159 +0 1 +.names 48271 47924 49160 +11 1 +.names 49160 49161 +1 1 +.names 49161 49162 +0 1 +.names 49165 49166 49163 +11 1 +.names 49163 49164 +1 1 +.names 49156 49165 +0 1 +.names 49151 49166 +0 1 +.names 49190 49191 49167 +1- 1 +-1 1 +.names 49167 49168 +1 1 +.names 49193 49195 49169 +1- 1 +-1 1 +.names 49169 49170 +1 1 +.names 49170 49171 +0 1 +.names 49174 49176 49172 +11 1 +.names 49172 49173 +1 1 +.names 2413 49174 +1 1 +.names 1652 49175 +0 1 +.names 47924 49175 49176 +1- 1 +-1 1 +.names 49180 49181 49177 +11 1 +.names 49177 49178 +1 1 +.names 1653 49179 +0 1 +.names 48271 49179 49180 +1- 1 +-1 1 +.names 48183 44737 49181 +1- 1 +-1 1 +.names 49185 49187 49182 +11 1 +.names 49182 49183 +1 1 +.names 1654 49184 +0 1 +.names 47886 49184 49185 +1- 1 +-1 1 +.names 1655 49186 +0 1 +.names 49186 47862 49187 +1- 1 +-1 1 +.names 49178 49188 +0 1 +.names 49183 49189 +0 1 +.names 49188 49189 49190 +1- 1 +-1 1 +.names 49173 49191 +0 1 +.names 49164 49192 +0 1 +.names 48043 49192 49193 +11 1 +.names 1656 49194 +0 1 +.names 9636 49194 49195 +11 1 +.names 49198 49200 49196 +1- 1 +-1 1 +.names 49196 49197 +1 1 +.names 9627 41748 49198 +1- 1 +-1 1 +.names 48068 49199 +1 1 +.names 49199 49200 +0 1 +.names 49205 49208 49201 +1- 1 +-1 1 +.names 49201 49202 +1 1 +.names 48032 2413 49203 +11 1 +.names 49203 49204 +1 1 +.names 49204 49205 +0 1 +.names 47960 48108 49206 +11 1 +.names 49206 49207 +1 1 +.names 49207 49208 +0 1 +.names 49211 49212 49209 +11 1 +.names 49209 49210 +1 1 +.names 49202 49211 +0 1 +.names 49197 49212 +0 1 +.names 49233 49236 49213 +1- 1 +-1 1 +.names 49213 49214 +1 1 +.names 49226 49228 49215 +1- 1 +-1 1 +.names 49215 49216 +1 1 +.names 49216 49217 +0 1 +.names 49220 49222 49218 +11 1 +.names 49218 49219 +1 1 +.names 2413 49220 +1 1 +.names 1657 49221 +0 1 +.names 48108 49221 49222 +1- 1 +-1 1 +.names 48043 49223 +1 1 +.names 49223 49224 +0 1 +.names 1658 49225 +0 1 +.names 49224 49225 49226 +11 1 +.names 49210 49227 +0 1 +.names 49223 49227 49228 +11 1 +.names 49219 49229 +0 1 +.names 49241 49243 49230 +11 1 +.names 49230 49231 +1 1 +.names 49231 49232 +0 1 +.names 49229 49232 49233 +1- 1 +-1 1 +.names 49238 49239 49234 +11 1 +.names 49234 49235 +1 1 +.names 49235 49236 +0 1 +.names 1659 49237 +0 1 +.names 47960 49237 49238 +1- 1 +-1 1 +.names 47850 44745 49239 +1- 1 +-1 1 +.names 1660 49240 +0 1 +.names 48032 49240 49241 +1- 1 +-1 1 +.names 1661 49242 +0 1 +.names 48068 49242 49243 +1- 1 +-1 1 +.names 49246 49248 49244 +1- 1 +-1 1 +.names 49244 49245 +1 1 +.names 9627 41792 49246 +1- 1 +-1 1 +.names 48032 49247 +1 1 +.names 49247 49248 +0 1 +.names 49253 49256 49249 +1- 1 +-1 1 +.names 49249 49250 +1 1 +.names 2413 47862 49251 +11 1 +.names 49251 49252 +1 1 +.names 49252 49253 +0 1 +.names 47960 48562 49254 +11 1 +.names 49254 49255 +1 1 +.names 49255 49256 +0 1 +.names 49259 49260 49257 +11 1 +.names 49257 49258 +1 1 +.names 49250 49259 +0 1 +.names 49245 49260 +0 1 +.names 49280 49281 49261 +1- 1 +-1 1 +.names 49261 49262 +1 1 +.names 49287 49289 49263 +1- 1 +-1 1 +.names 49263 49264 +1 1 +.names 49264 49265 +0 1 +.names 49268 49270 49266 +11 1 +.names 49266 49267 +1 1 +.names 2413 49268 +1 1 +.names 832 49269 +0 1 +.names 48562 49269 49270 +1- 1 +-1 1 +.names 49274 49275 49271 +11 1 +.names 49271 49272 +1 1 +.names 1662 49273 +0 1 +.names 47960 49273 49274 +1- 1 +-1 1 +.names 47850 44753 49275 +1- 1 +-1 1 +.names 49267 49276 +0 1 +.names 49283 49285 49277 +11 1 +.names 49277 49278 +1 1 +.names 49278 49279 +0 1 +.names 49276 49279 49280 +1- 1 +-1 1 +.names 49272 49281 +0 1 +.names 1663 49282 +0 1 +.names 48032 49282 49283 +1- 1 +-1 1 +.names 1664 49284 +0 1 +.names 49284 47862 49285 +1- 1 +-1 1 +.names 49258 49286 +0 1 +.names 47863 49286 49287 +11 1 +.names 1665 49288 +0 1 +.names 9635 49288 49289 +11 1 +.names 49295 49296 49290 +1- 1 +-1 1 +.names 49290 49291 +1 1 +.names 49320 49321 49292 +11 1 +.names 49292 49293 +1 1 +.names 49293 49294 +0 1 +.names 2413 49294 49295 +11 1 +.names 1783 2413 49296 +11 1 +.names 49305 49308 49297 +1- 1 +-1 1 +.names 49297 49298 +1 1 +.names 49327 49329 49299 +11 1 +.names 49299 49300 +1 1 +.names 49300 49301 +0 1 +.names 49333 49335 49302 +11 1 +.names 49302 49303 +1 1 +.names 49303 49304 +0 1 +.names 49301 49304 49305 +1- 1 +-1 1 +.names 49323 49325 49306 +11 1 +.names 49306 49307 +1 1 +.names 49307 49308 +0 1 +.names 49311 49313 49309 +1- 1 +-1 1 +.names 49309 49310 +1 1 +.names 9625 41829 49311 +1- 1 +-1 1 +.names 48562 49312 +1 1 +.names 49312 49313 +0 1 +.names 48043 47886 49314 +11 1 +.names 49314 49315 +1 1 +.names 47862 48271 49316 +11 1 +.names 49316 49317 +1 1 +.names 49330 49331 49318 +1- 1 +-1 1 +.names 49318 49319 +1 1 +.names 49319 49320 +0 1 +.names 49310 49321 +0 1 +.names 49291 49322 +0 1 +.names 47980 44762 49323 +1- 1 +-1 1 +.names 1666 49324 +0 1 +.names 48562 49324 49325 +1- 1 +-1 1 +.names 1667 49326 +0 1 +.names 48271 49326 49327 +1- 1 +-1 1 +.names 1668 49328 +0 1 +.names 49328 47862 49329 +1- 1 +-1 1 +.names 49315 49330 +0 1 +.names 49317 49331 +0 1 +.names 1669 49332 +0 1 +.names 47886 49332 49333 +1- 1 +-1 1 +.names 1670 49334 +0 1 +.names 48043 49334 49335 +1- 1 +-1 1 +.names 48068 49336 +1 1 +.names 49340 41887 49337 +1- 1 +-1 1 +.names 49337 49338 +1 1 +.names 49336 49339 +0 1 +.names 9643 49339 49340 +1- 1 +-1 1 +.names 49345 49348 49341 +1- 1 +-1 1 +.names 49341 49342 +1 1 +.names 48183 2413 49343 +11 1 +.names 49343 49344 +1 1 +.names 49344 49345 +0 1 +.names 47960 48562 49346 +11 1 +.names 49346 49347 +1 1 +.names 49347 49348 +0 1 +.names 49351 49352 49349 +11 1 +.names 49349 49350 +1 1 +.names 49342 49351 +0 1 +.names 49338 49352 +0 1 +.names 49378 49379 49353 +1- 1 +-1 1 +.names 49353 49354 +1 1 +.names 49361 49363 49355 +1- 1 +-1 1 +.names 49355 49356 +1 1 +.names 49356 49357 +0 1 +.names 48182 49358 +1 1 +.names 49358 49359 +0 1 +.names 1671 49360 +0 1 +.names 49359 49360 49361 +11 1 +.names 49350 49362 +0 1 +.names 49358 49362 49363 +11 1 +.names 49367 49369 49364 +11 1 +.names 49364 49365 +1 1 +.names 1672 49366 +0 1 +.names 47960 49366 49367 +1- 1 +-1 1 +.names 1673 49368 +0 1 +.names 48068 49368 49369 +1- 1 +-1 1 +.names 49372 49373 49370 +11 1 +.names 49370 49371 +1 1 +.names 48183 44771 49372 +1- 1 +-1 1 +.names 48562 2413 49373 +1- 1 +-1 1 +.names 49365 49374 +0 1 +.names 49381 49382 49375 +11 1 +.names 49375 49376 +1 1 +.names 49376 49377 +0 1 +.names 49374 49377 49378 +1- 1 +-1 1 +.names 49371 49379 +0 1 +.names 1674 49380 +0 1 +.names 47886 49380 49381 +1- 1 +-1 1 +.names 2413 49382 +1 1 +.names 49387 49390 49383 +1- 1 +-1 1 +.names 49383 49384 +1 1 +.names 479 49691 49385 +01 1 +10 1 +.names 49385 49386 +1 1 +.names 49386 49387 +0 1 +.names 49442 49444 49388 +11 1 +.names 49388 49389 +1 1 +.names 49389 49390 +0 1 +.names 49399 49401 49391 +1- 1 +-1 1 +.names 49391 49392 +1 1 +.names 49416 49393 +0 1 +.names 49393 49394 +1 1 +.names 49394 49395 +0 1 +.names 49610 49612 49396 +11 1 +.names 49396 49397 +1 1 +.names 49397 49398 +0 1 +.names 49395 49398 49399 +11 1 +.names 1675 49400 +0 1 +.names 49394 49400 49401 +11 1 +.names 49410 49412 49402 +1- 1 +-1 1 +.names 49402 49403 +1 1 +.names 49599 49404 +0 1 +.names 49404 49405 +1 1 +.names 49405 49406 +0 1 +.names 49604 49607 49407 +1- 1 +-1 1 +.names 49407 49408 +1 1 +.names 49408 49409 +0 1 +.names 49406 49409 49410 +11 1 +.names 1676 49411 +0 1 +.names 49405 49411 49412 +11 1 +.names 49419 49421 49413 +11 1 +.names 49413 49414 +1 1 +.names 488 49608 49415 +01 1 +10 1 +.names 49415 49416 +1 1 +.names 49612 49417 +0 1 +.names 49417 49418 +1 1 +.names 49416 49418 49419 +11 1 +.names 49648 49420 +0 1 +.names 49420 49421 +1 1 +.names 49425 49414 49422 +11 1 +.names 49422 49423 +1 1 +.names 1683 49725 49424 +01 1 +10 1 +.names 49424 49425 +1 1 +.names 49435 49437 49426 +11 1 +.names 49426 49427 +1 1 +.names 505 49674 49428 +01 1 +10 1 +.names 49428 49429 +1 1 +.names 507 49672 49430 +01 1 +10 1 +.names 49430 49431 +1 1 +.names 49429 49431 49432 +11 1 +.names 506 49670 49433 +01 1 +10 1 +.names 49433 49434 +1 1 +.names 49432 49434 49435 +11 1 +.names 508 49613 49436 +01 1 +10 1 +.names 49436 49437 +1 1 +.names 480 49559 49438 +01 1 +10 1 +.names 49438 49439 +1 1 +.names 49452 49454 49440 +11 1 +.names 49440 49441 +1 1 +.names 49439 49441 49442 +11 1 +.names 49548 49443 +0 1 +.names 49443 49444 +1 1 +.names 1686 49695 49445 +01 1 +10 1 +.names 49445 49446 +1 1 +.names 493 49697 49447 +01 1 +10 1 +.names 49447 49448 +1 1 +.names 49446 49448 49449 +11 1 +.names 49557 49450 +0 1 +.names 49450 49451 +1 1 +.names 49449 49451 49452 +11 1 +.names 49460 49462 49453 +11 1 +.names 49453 49454 +1 1 +.names 49702 49704 49455 +11 1 +.names 49455 49456 +1 1 +.names 49571 49457 +0 1 +.names 49457 49458 +1 1 +.names 49456 49458 49459 +11 1 +.names 49459 49427 49460 +11 1 +.names 497 49699 49461 +01 1 +10 1 +.names 49461 49462 +1 1 +.names 49469 49471 49463 +11 1 +.names 49463 49464 +1 1 +.names 483 49723 49465 +01 1 +10 1 +.names 49465 49466 +1 1 +.names 482 49718 49467 +01 1 +10 1 +.names 49467 49468 +1 1 +.names 49466 49468 49469 +11 1 +.names 49551 49470 +0 1 +.names 49470 49471 +1 1 +.names 49475 49472 +0 1 +.names 49472 49473 +1 1 +.names 49574 49575 49474 +1- 1 +-1 1 +.names 49474 49475 +1 1 +.names 49384 49476 +0 1 +.names 49476 49477 +1 1 +.names 49486 49487 49478 +11 1 +.names 49478 49479 +1 1 +.names 49427 49480 +0 1 +.names 49689 49576 49481 +1- 1 +-1 1 +.names 49481 49482 +1 1 +.names 49482 49483 +0 1 +.names 49480 49483 49484 +1- 1 +-1 1 +.names 49477 49485 +0 1 +.names 49484 49485 49486 +11 1 +.names 49473 49487 +0 1 +.names 49497 49500 49488 +11 1 +.names 49488 49489 +1 1 +.names 49441 49490 +0 1 +.names 49663 49664 49491 +1- 1 +-1 1 +.names 49491 49492 +1 1 +.names 49492 49493 +0 1 +.names 49490 49493 49494 +1- 1 +-1 1 +.names 1677 49495 +0 1 +.names 49390 49495 49496 +1- 1 +-1 1 +.names 49494 49496 49497 +11 1 +.names 49627 49628 49498 +1- 1 +-1 1 +.names 49498 49499 +1 1 +.names 49499 49500 +0 1 +.names 49504 49501 +0 1 +.names 49501 49502 +1 1 +.names 49645 49646 49503 +1- 1 +-1 1 +.names 49503 49504 +1 1 +.names 49500 49505 +1 1 +.names 49509 49502 49506 +11 1 +.names 49506 49507 +1 1 +.names 49403 49505 49508 +11 1 +.names 49508 49392 49509 +11 1 +.names 49522 49525 49510 +11 1 +.names 49510 49511 +1 1 +.names 49563 49564 49512 +1- 1 +-1 1 +.names 49512 49513 +1 1 +.names 49513 49514 +0 1 +.names 49543 49546 49515 +1- 1 +-1 1 +.names 49515 49516 +1 1 +.names 49516 49517 +0 1 +.names 49514 49517 49518 +1- 1 +-1 1 +.names 49472 49576 49519 +1- 1 +-1 1 +.names 49519 49520 +1 1 +.names 49520 49521 +0 1 +.names 49518 49521 49522 +11 1 +.names 49594 49595 49523 +1- 1 +-1 1 +.names 49523 49524 +1 1 +.names 49524 49525 +0 1 +.names 49390 49530 49526 +1- 1 +-1 1 +.names 49526 49527 +1 1 +.names 1677 479 49528 +01 1 +10 1 +.names 49528 49529 +1 1 +.names 49529 49530 +0 1 +.names 49537 49540 49531 +11 1 +.names 49531 49532 +1 1 +.names 49527 49533 +0 1 +.names 49511 49534 +0 1 +.names 49533 49534 49535 +1- 1 +-1 1 +.names 49507 49536 +0 1 +.names 49535 49536 49537 +1- 1 +-1 1 +.names 49489 49538 +0 1 +.names 49479 49539 +0 1 +.names 49538 49539 49540 +1- 1 +-1 1 +.names 477 49690 49541 +01 1 +10 1 +.names 49541 49542 +1 1 +.names 49542 49543 +0 1 +.names 478 49560 49544 +01 1 +10 1 +.names 49544 49545 +1 1 +.names 49545 49546 +0 1 +.names 49554 49555 49547 +1- 1 +-1 1 +.names 49547 49548 +1 1 +.names 49468 49549 +0 1 +.names 481 49720 49550 +01 1 +10 1 +.names 49550 49551 +1 1 +.names 49549 49470 49552 +1- 1 +-1 1 +.names 49466 49553 +0 1 +.names 49552 49553 49554 +1- 1 +-1 1 +.names 49423 49555 +0 1 +.names 49715 49705 49556 +1- 1 +-1 1 +.names 49556 49557 +1 1 +.names 1678 49558 +0 1 +.names 49558 49559 +1 1 +.names 2413 49560 +1 1 +.names 49546 49561 +1 1 +.names 49561 49562 +0 1 +.names 49562 1783 49563 +11 1 +.names 49561 1783 49564 +11 1 +.names 49569 49457 49565 +1- 1 +-1 1 +.names 49565 49566 +1 1 +.names 49750 49751 49567 +1- 1 +-1 1 +.names 49567 49568 +1 1 +.names 49568 49569 +0 1 +.names 49685 49688 49570 +1- 1 +-1 1 +.names 49570 49571 +1 1 +.names 49736 49737 49572 +1- 1 +-1 1 +.names 49572 49573 +1 1 +.names 49573 49574 +0 1 +.names 49454 49575 +0 1 +.names 49566 49576 +0 1 +.names 1679 49577 +0 1 +.names 49577 49578 +1 1 +.names 500 49578 49579 +01 1 +10 1 +.names 49579 49580 +1 1 +.names 49580 49581 +0 1 +.names 49581 49582 +1 1 +.names 49586 49583 +0 1 +.names 49583 49584 +1 1 +.names 49771 49756 49585 +1- 1 +-1 1 +.names 49585 49586 +1 1 +.names 49589 49592 49587 +1- 1 +-1 1 +.names 49587 49588 +1 1 +.names 49584 1680 49589 +11 1 +.names 49763 49764 49590 +1- 1 +-1 1 +.names 49590 49591 +1 1 +.names 49591 49592 +0 1 +.names 49582 49593 +0 1 +.names 49593 49588 49594 +11 1 +.names 49582 1679 49595 +11 1 +.names 492 49596 +0 1 +.names 49596 49597 +1 1 +.names 1676 49597 49598 +01 1 +10 1 +.names 49598 49599 +1 1 +.names 49603 49600 +0 1 +.names 49600 49601 +1 1 +.names 49791 49655 49602 +1- 1 +-1 1 +.names 49602 49603 +1 1 +.names 49601 1681 49604 +11 1 +.names 49781 49782 49605 +1- 1 +-1 1 +.names 49605 49606 +1 1 +.names 49606 49607 +0 1 +.names 49400 49608 +1 1 +.names 49808 49809 49609 +1- 1 +-1 1 +.names 49609 49610 +1 1 +.names 49816 49817 49611 +1- 1 +-1 1 +.names 49611 49612 +1 1 +.names 2413 49613 +1 1 +.names 49437 49614 +0 1 +.names 49614 49615 +1 1 +.names 49619 49616 +0 1 +.names 49616 49617 +1 1 +.names 49829 49667 49618 +1- 1 +-1 1 +.names 49618 49619 +1 1 +.names 49622 49625 49620 +1- 1 +-1 1 +.names 49620 49621 +1 1 +.names 49617 1682 49622 +11 1 +.names 49822 49823 49623 +1- 1 +-1 1 +.names 49623 49624 +1 1 +.names 49624 49625 +0 1 +.names 49615 49626 +0 1 +.names 49626 49621 49627 +11 1 +.names 49615 1783 49628 +11 1 +.names 49425 49629 +0 1 +.names 49629 49630 +1 1 +.names 49637 49641 49631 +11 1 +.names 49631 49632 +1 1 +.names 1683 49633 +0 1 +.names 49630 49634 +0 1 +.names 49633 49634 49635 +1- 1 +-1 1 +.names 49414 49636 +0 1 +.names 49635 49636 49637 +1- 1 +-1 1 +.names 49837 49838 49638 +1- 1 +-1 1 +.names 49638 49639 +1 1 +.names 49639 49640 +0 1 +.names 49555 49640 49641 +1- 1 +-1 1 +.names 49439 49642 +0 1 +.names 49443 49642 49643 +11 1 +.names 49559 49644 +0 1 +.names 49643 49644 49645 +11 1 +.names 49632 49646 +0 1 +.names 49656 49659 49647 +1- 1 +-1 1 +.names 49647 49648 +1 1 +.names 1681 49785 49649 +01 1 +10 1 +.names 49649 49650 +1 1 +.names 49650 49651 +0 1 +.names 49651 49404 49652 +1- 1 +-1 1 +.names 490 49783 49653 +01 1 +10 1 +.names 49653 49654 +1 1 +.names 49654 49655 +0 1 +.names 49652 49655 49656 +1- 1 +-1 1 +.names 491 49773 49657 +01 1 +10 1 +.names 49657 49658 +1 1 +.names 49658 49659 +0 1 +.names 49392 49660 +0 1 +.names 49420 49660 49661 +11 1 +.names 49403 49662 +0 1 +.names 49661 49662 49663 +1- 1 +-1 1 +.names 49502 49664 +0 1 +.names 49434 49665 +0 1 +.names 49665 49666 +1 1 +.names 49431 49667 +0 1 +.names 49667 49668 +1 1 +.names 1684 49669 +0 1 +.names 49669 49670 +1 1 +.names 1685 49671 +0 1 +.names 49671 49672 +1 1 +.names 1682 49673 +0 1 +.names 49673 49674 +1 1 +.names 501 49840 49675 +01 1 +10 1 +.names 49675 49676 +1 1 +.names 49676 49677 +0 1 +.names 503 49842 49678 +01 1 +10 1 +.names 49678 49679 +1 1 +.names 49679 49680 +0 1 +.names 49677 49680 49681 +1- 1 +-1 1 +.names 1693 49739 49682 +01 1 +10 1 +.names 49682 49683 +1 1 +.names 49683 49684 +0 1 +.names 49681 49684 49685 +1- 1 +-1 1 +.names 502 49845 49686 +01 1 +10 1 +.names 49686 49687 +1 1 +.names 49687 49688 +0 1 +.names 49524 49458 49689 +11 1 +.names 2413 49690 +1 1 +.names 49495 49691 +1 1 +.names 49446 49692 +0 1 +.names 49692 49693 +1 1 +.names 496 49694 +0 1 +.names 49694 49695 +1 1 +.names 1687 49696 +0 1 +.names 49696 49697 +1 1 +.names 1680 49698 +0 1 +.names 49698 49699 +1 1 +.names 498 49765 49700 +01 1 +10 1 +.names 49700 49701 +1 1 +.names 49701 49580 49702 +11 1 +.names 499 49753 49703 +01 1 +10 1 +.names 49703 49704 +1 1 +.names 49708 49705 +0 1 +.names 49705 49706 +1 1 +.names 495 49710 49707 +01 1 +10 1 +.names 49707 49708 +1 1 +.names 1688 49709 +0 1 +.names 49709 49710 +1 1 +.names 1689 49711 +0 1 +.names 49711 49712 +1 1 +.names 494 49712 49713 +01 1 +10 1 +.names 49713 49714 +1 1 +.names 49714 49715 +0 1 +.names 49549 49716 +1 1 +.names 1690 49717 +0 1 +.names 49717 49718 +1 1 +.names 1691 49719 +0 1 +.names 49719 49720 +1 1 +.names 49553 49721 +1 1 +.names 1692 49722 +0 1 +.names 49722 49723 +1 1 +.names 484 49724 +0 1 +.names 49724 49725 +1 1 +.names 49731 49734 49726 +1- 1 +-1 1 +.names 49726 49727 +1 1 +.names 49448 49728 +0 1 +.names 49450 49728 49729 +11 1 +.names 49697 49730 +0 1 +.names 49729 49730 49731 +11 1 +.names 49852 49853 49732 +1- 1 +-1 1 +.names 49732 49733 +1 1 +.names 49733 49734 +0 1 +.names 49693 49735 +0 1 +.names 49735 49727 49736 +11 1 +.names 49693 1686 49737 +11 1 +.names 504 49738 +0 1 +.names 49738 49739 +1 1 +.names 49684 49740 +1 1 +.names 49680 49741 +1 1 +.names 49747 49748 49742 +1- 1 +-1 1 +.names 49742 49743 +1 1 +.names 49741 49744 +0 1 +.names 49855 49856 49745 +1- 1 +-1 1 +.names 49745 49746 +1 1 +.names 49744 49746 49747 +11 1 +.names 49741 1694 49748 +11 1 +.names 49740 49749 +0 1 +.names 49749 49743 49750 +11 1 +.names 49740 1693 49751 +11 1 +.names 1695 49752 +0 1 +.names 49752 49753 +1 1 +.names 49704 49754 +0 1 +.names 49754 49755 +1 1 +.names 49701 49756 +0 1 +.names 49756 49757 +1 1 +.names 49760 49761 49758 +1- 1 +-1 1 +.names 49758 49759 +1 1 +.names 1696 49760 +0 1 +.names 49757 49761 +0 1 +.names 49755 49762 +0 1 +.names 49762 49759 49763 +11 1 +.names 49755 49753 49764 +11 1 +.names 49760 49765 +1 1 +.names 497 49766 +0 1 +.names 49766 49767 +1 1 +.names 49767 49768 +0 1 +.names 49699 49769 +0 1 +.names 49768 49769 49770 +11 1 +.names 49770 49754 49771 +1- 1 +-1 1 +.names 1697 49772 +0 1 +.names 49772 49773 +1 1 +.names 49659 49774 +1 1 +.names 49655 49775 +1 1 +.names 49778 49779 49776 +1- 1 +-1 1 +.names 49776 49777 +1 1 +.names 1698 49778 +0 1 +.names 49775 49779 +0 1 +.names 49774 49780 +0 1 +.names 49780 49777 49781 +11 1 +.names 49774 49773 49782 +11 1 +.names 49778 49783 +1 1 +.names 489 49784 +0 1 +.names 49784 49785 +1 1 +.names 1681 49786 +0 1 +.names 49786 49787 +1 1 +.names 49787 49788 +0 1 +.names 49785 49789 +0 1 +.names 49788 49789 49790 +11 1 +.names 49790 49659 49791 +1- 1 +-1 1 +.names 1699 49792 +0 1 +.names 49792 49793 +1 1 +.names 487 49793 49794 +01 1 +10 1 +.names 49794 49795 +1 1 +.names 49795 49796 +0 1 +.names 49796 49797 +1 1 +.names 49801 49798 +0 1 +.names 49798 49799 +1 1 +.names 1700 49815 49800 +01 1 +10 1 +.names 49800 49801 +1 1 +.names 49805 49806 49802 +1- 1 +-1 1 +.names 49802 49803 +1 1 +.names 49799 49804 +0 1 +.names 49804 1701 49805 +11 1 +.names 49799 1700 49806 +11 1 +.names 49797 49807 +0 1 +.names 49807 49803 49808 +11 1 +.names 49797 1699 49809 +11 1 +.names 1701 49810 +0 1 +.names 49810 49811 +1 1 +.names 485 49811 49812 +01 1 +10 1 +.names 49812 49813 +1 1 +.names 486 49814 +0 1 +.names 49814 49815 +1 1 +.names 49796 49798 49816 +1- 1 +-1 1 +.names 49813 49817 +0 1 +.names 49669 49820 49818 +1- 1 +-1 1 +.names 49818 49819 +1 1 +.names 49666 49820 +0 1 +.names 49668 49821 +0 1 +.names 49821 49819 49822 +11 1 +.names 49668 49672 49823 +11 1 +.names 505 49824 +0 1 +.names 49824 49825 +1 1 +.names 49825 49826 +0 1 +.names 49674 49827 +0 1 +.names 49826 49827 49828 +11 1 +.names 49828 49665 49829 +1- 1 +-1 1 +.names 49835 49836 49830 +1- 1 +-1 1 +.names 49830 49831 +1 1 +.names 49721 49832 +0 1 +.names 49717 49857 49833 +1- 1 +-1 1 +.names 49833 49834 +1 1 +.names 49832 49834 49835 +11 1 +.names 49721 49723 49836 +11 1 +.names 49464 1691 49837 +11 1 +.names 49831 49838 +0 1 +.names 1702 49839 +0 1 +.names 49839 49840 +1 1 +.names 1694 49841 +0 1 +.names 49841 49842 +1 1 +.names 49688 49843 +1 1 +.names 1703 49844 +0 1 +.names 49844 49845 +1 1 +.names 494 49846 +0 1 +.names 49846 49847 +1 1 +.names 49711 49850 49848 +1- 1 +-1 1 +.names 49848 49849 +1 1 +.names 49847 49850 +0 1 +.names 49706 49851 +0 1 +.names 49851 49849 49852 +11 1 +.names 49706 49710 49853 +11 1 +.names 49843 49854 +0 1 +.names 49854 1702 49855 +11 1 +.names 49843 1703 49856 +11 1 +.names 49716 49857 +0 1 +.names 20595 49858 +1 1 +.names 49863 49867 57392 +1- 1 +-1 1 +.names 9659 49860 +0 1 +.names 14852 49861 +1 1 +.names 49861 49862 +0 1 +.names 49860 49862 49863 +11 1 +.names 1704 49864 +0 1 +.names 49864 49865 +1 1 +.names 49865 49866 +0 1 +.names 9659 49866 49867 +11 1 +.names 49872 49876 57393 +1- 1 +-1 1 +.names 9653 49869 +0 1 +.names 44604 49870 +1 1 +.names 49870 49871 +0 1 +.names 49869 49871 49872 +11 1 +.names 1705 49873 +0 1 +.names 49873 49874 +1 1 +.names 49874 49875 +0 1 +.names 9653 49875 49876 +11 1 +.names 49880 49884 57394 +1- 1 +-1 1 +.names 44569 49878 +1 1 +.names 49878 49879 +0 1 +.names 49860 49879 49880 +11 1 +.names 1706 49881 +0 1 +.names 49881 49882 +1 1 +.names 49882 49883 +0 1 +.names 9659 49883 49884 +11 1 +.names 49889 49893 57395 +1- 1 +-1 1 +.names 9658 49886 +0 1 +.names 44613 49887 +1 1 +.names 49887 49888 +0 1 +.names 49886 49888 49889 +11 1 +.names 1707 49890 +0 1 +.names 49890 49891 +1 1 +.names 49891 49892 +0 1 +.names 9658 49892 49893 +11 1 +.names 49897 49901 57396 +1- 1 +-1 1 +.names 14927 49895 +1 1 +.names 49895 49896 +0 1 +.names 49869 49896 49897 +11 1 +.names 1708 49898 +0 1 +.names 49898 49899 +1 1 +.names 49899 49900 +0 1 +.names 9653 49900 49901 +11 1 +.names 49905 49909 57397 +1- 1 +-1 1 +.names 14832 49903 +1 1 +.names 49903 49904 +0 1 +.names 49869 49904 49905 +11 1 +.names 1709 49906 +0 1 +.names 49906 49907 +1 1 +.names 49907 49908 +0 1 +.names 9653 49908 49909 +11 1 +.names 49913 49917 57398 +1- 1 +-1 1 +.names 14812 49911 +1 1 +.names 49911 49912 +0 1 +.names 49860 49912 49913 +11 1 +.names 1710 49914 +0 1 +.names 49914 49915 +1 1 +.names 49915 49916 +0 1 +.names 9659 49916 49917 +11 1 +.names 49921 49925 57399 +1- 1 +-1 1 +.names 44674 49919 +1 1 +.names 49919 49920 +0 1 +.names 49886 49920 49921 +11 1 +.names 1711 49922 +0 1 +.names 49922 49923 +1 1 +.names 49923 49924 +0 1 +.names 9658 49924 49925 +11 1 +.names 49929 49933 57400 +1- 1 +-1 1 +.names 14822 49927 +1 1 +.names 49927 49928 +0 1 +.names 49886 49928 49929 +11 1 +.names 1712 49930 +0 1 +.names 49930 49931 +1 1 +.names 49931 49932 +0 1 +.names 9658 49932 49933 +11 1 +.names 49937 49941 57401 +1- 1 +-1 1 +.names 44725 49935 +1 1 +.names 49935 49936 +0 1 +.names 49860 49936 49937 +11 1 +.names 1713 49938 +0 1 +.names 49938 49939 +1 1 +.names 49939 49940 +0 1 +.names 9659 49940 49941 +11 1 +.names 49945 49949 57402 +1- 1 +-1 1 +.names 14802 49943 +1 1 +.names 49943 49944 +0 1 +.names 49869 49944 49945 +11 1 +.names 1714 49946 +0 1 +.names 49946 49947 +1 1 +.names 49947 49948 +0 1 +.names 9653 49948 49949 +11 1 +.names 49953 49957 57403 +1- 1 +-1 1 +.names 44716 49951 +1 1 +.names 49951 49952 +0 1 +.names 49886 49952 49953 +11 1 +.names 1715 49954 +0 1 +.names 49954 49955 +1 1 +.names 49955 49956 +0 1 +.names 9658 49956 49957 +11 1 +.names 49961 49965 57404 +1- 1 +-1 1 +.names 14893 49959 +1 1 +.names 49959 49960 +0 1 +.names 49860 49960 49961 +11 1 +.names 1716 49962 +0 1 +.names 49962 49963 +1 1 +.names 49963 49964 +0 1 +.names 9659 49964 49965 +11 1 +.names 49969 49973 57405 +1- 1 +-1 1 +.names 14862 49967 +1 1 +.names 49967 49968 +0 1 +.names 49886 49968 49969 +11 1 +.names 1717 49970 +0 1 +.names 49970 49971 +1 1 +.names 49971 49972 +0 1 +.names 9658 49972 49973 +11 1 +.names 49977 49981 57406 +1- 1 +-1 1 +.names 14842 49975 +1 1 +.names 49975 49976 +0 1 +.names 49860 49976 49977 +11 1 +.names 1718 49978 +0 1 +.names 49978 49979 +1 1 +.names 49979 49980 +0 1 +.names 9659 49980 49981 +11 1 +.names 49985 49989 57407 +1- 1 +-1 1 +.names 44758 49983 +1 1 +.names 49983 49984 +0 1 +.names 49869 49984 49985 +11 1 +.names 1719 49986 +0 1 +.names 49986 49987 +1 1 +.names 49987 49988 +0 1 +.names 9653 49988 49989 +11 1 +.names 49993 49997 57408 +1- 1 +-1 1 +.names 44638 49991 +1 1 +.names 49991 49992 +0 1 +.names 49869 49992 49993 +11 1 +.names 1720 49994 +0 1 +.names 49994 49995 +1 1 +.names 49995 49996 +0 1 +.names 9653 49996 49997 +11 1 +.names 50001 50005 57409 +1- 1 +-1 1 +.names 44587 49999 +1 1 +.names 49999 50000 +0 1 +.names 49886 50000 50001 +11 1 +.names 1721 50002 +0 1 +.names 50002 50003 +1 1 +.names 50003 50004 +0 1 +.names 9658 50004 50005 +11 1 +.names 50009 50013 57410 +1- 1 +-1 1 +.names 44656 50007 +1 1 +.names 50007 50008 +0 1 +.names 49869 50008 50009 +11 1 +.names 1722 50010 +0 1 +.names 50010 50011 +1 1 +.names 50011 50012 +0 1 +.names 9653 50012 50013 +11 1 +.names 50017 50021 57411 +1- 1 +-1 1 +.names 14792 50015 +1 1 +.names 50015 50016 +0 1 +.names 49860 50016 50017 +11 1 +.names 1723 50018 +0 1 +.names 50018 50019 +1 1 +.names 50019 50020 +0 1 +.names 9659 50020 50021 +11 1 +.names 50025 50029 57412 +1- 1 +-1 1 +.names 44647 50023 +1 1 +.names 50023 50024 +0 1 +.names 49860 50024 50025 +11 1 +.names 1724 50026 +0 1 +.names 50026 50027 +1 1 +.names 50027 50028 +0 1 +.names 9659 50028 50029 +11 1 +.names 50033 50037 57413 +1- 1 +-1 1 +.names 44527 50031 +1 1 +.names 50031 50032 +0 1 +.names 49886 50032 50033 +11 1 +.names 1725 50034 +0 1 +.names 50034 50035 +1 1 +.names 50035 50036 +0 1 +.names 9658 50036 50037 +11 1 +.names 50041 50045 57414 +1- 1 +-1 1 +.names 57098 50039 +1 1 +.names 50039 50040 +0 1 +.names 49886 50040 50041 +11 1 +.names 1726 50042 +0 1 +.names 50042 50043 +1 1 +.names 50043 50044 +0 1 +.names 9658 50044 50045 +11 1 +.names 50049 50053 57415 +1- 1 +-1 1 +.names 44699 50047 +1 1 +.names 50047 50048 +0 1 +.names 49869 50048 50049 +11 1 +.names 1727 50050 +0 1 +.names 50050 50051 +1 1 +.names 50051 50052 +0 1 +.names 9653 50052 50053 +11 1 +.names 50057 50061 57416 +1- 1 +-1 1 +.names 44767 50055 +1 1 +.names 50055 50056 +0 1 +.names 49886 50056 50057 +11 1 +.names 1728 50058 +0 1 +.names 50058 50059 +1 1 +.names 50059 50060 +0 1 +.names 9658 50060 50061 +11 1 +.names 50065 50069 57417 +1- 1 +-1 1 +.names 14882 50063 +1 1 +.names 50063 50064 +0 1 +.names 49869 50064 50065 +11 1 +.names 1729 50066 +0 1 +.names 50066 50067 +1 1 +.names 50067 50068 +0 1 +.names 9653 50068 50069 +11 1 +.names 50073 50077 57418 +1- 1 +-1 1 +.names 14872 50071 +1 1 +.names 50071 50072 +0 1 +.names 49860 50072 50073 +11 1 +.names 1730 50074 +0 1 +.names 50074 50075 +1 1 +.names 50075 50076 +0 1 +.names 9659 50076 50077 +11 1 +.names 50081 50085 57419 +1- 1 +-1 1 +.names 44518 50079 +1 1 +.names 50079 50080 +0 1 +.names 49860 50080 50081 +11 1 +.names 1731 50082 +0 1 +.names 50082 50083 +1 1 +.names 50083 50084 +0 1 +.names 9659 50084 50085 +11 1 +.names 50089 50093 57420 +1- 1 +-1 1 +.names 14782 50087 +1 1 +.names 50087 50088 +0 1 +.names 49886 50088 50089 +11 1 +.names 1732 50090 +0 1 +.names 50090 50091 +1 1 +.names 50091 50092 +0 1 +.names 9658 50092 50093 +11 1 +.names 50097 50101 57421 +1- 1 +-1 1 +.names 14760 50095 +1 1 +.names 50095 50096 +0 1 +.names 49869 50096 50097 +11 1 +.names 1733 50098 +0 1 +.names 50098 50099 +1 1 +.names 50099 50100 +0 1 +.names 9653 50100 50101 +11 1 +.names 50106 50109 57422 +1- 1 +-1 1 +.names 9667 50103 +0 1 +.names 14852 50104 +1 1 +.names 50104 50105 +0 1 +.names 50103 50105 50106 +11 1 +.names 49864 50107 +1 1 +.names 50107 50108 +0 1 +.names 9667 50108 50109 +11 1 +.names 50114 50117 57423 +1- 1 +-1 1 +.names 9661 50111 +0 1 +.names 44604 50112 +1 1 +.names 50112 50113 +0 1 +.names 50111 50113 50114 +11 1 +.names 49873 50115 +1 1 +.names 50115 50116 +0 1 +.names 9661 50116 50117 +11 1 +.names 50121 50124 57424 +1- 1 +-1 1 +.names 44569 50119 +1 1 +.names 50119 50120 +0 1 +.names 50103 50120 50121 +11 1 +.names 49881 50122 +1 1 +.names 50122 50123 +0 1 +.names 9667 50123 50124 +11 1 +.names 50129 50132 57425 +1- 1 +-1 1 +.names 9666 50126 +0 1 +.names 44613 50127 +1 1 +.names 50127 50128 +0 1 +.names 50126 50128 50129 +11 1 +.names 49890 50130 +1 1 +.names 50130 50131 +0 1 +.names 9666 50131 50132 +11 1 +.names 50136 50139 57426 +1- 1 +-1 1 +.names 14927 50134 +1 1 +.names 50134 50135 +0 1 +.names 50111 50135 50136 +11 1 +.names 49898 50137 +1 1 +.names 50137 50138 +0 1 +.names 9661 50138 50139 +11 1 +.names 50143 50146 57427 +1- 1 +-1 1 +.names 14832 50141 +1 1 +.names 50141 50142 +0 1 +.names 50111 50142 50143 +11 1 +.names 49906 50144 +1 1 +.names 50144 50145 +0 1 +.names 9661 50145 50146 +11 1 +.names 50150 50153 57428 +1- 1 +-1 1 +.names 14812 50148 +1 1 +.names 50148 50149 +0 1 +.names 50103 50149 50150 +11 1 +.names 49914 50151 +1 1 +.names 50151 50152 +0 1 +.names 9667 50152 50153 +11 1 +.names 50157 50160 57429 +1- 1 +-1 1 +.names 44674 50155 +1 1 +.names 50155 50156 +0 1 +.names 50126 50156 50157 +11 1 +.names 49922 50158 +1 1 +.names 50158 50159 +0 1 +.names 9666 50159 50160 +11 1 +.names 50164 50167 57430 +1- 1 +-1 1 +.names 14822 50162 +1 1 +.names 50162 50163 +0 1 +.names 50126 50163 50164 +11 1 +.names 49930 50165 +1 1 +.names 50165 50166 +0 1 +.names 9666 50166 50167 +11 1 +.names 50171 50174 57431 +1- 1 +-1 1 +.names 44725 50169 +1 1 +.names 50169 50170 +0 1 +.names 50103 50170 50171 +11 1 +.names 49938 50172 +1 1 +.names 50172 50173 +0 1 +.names 9667 50173 50174 +11 1 +.names 50178 50181 57432 +1- 1 +-1 1 +.names 14802 50176 +1 1 +.names 50176 50177 +0 1 +.names 50111 50177 50178 +11 1 +.names 49946 50179 +1 1 +.names 50179 50180 +0 1 +.names 9661 50180 50181 +11 1 +.names 50185 50188 57433 +1- 1 +-1 1 +.names 44716 50183 +1 1 +.names 50183 50184 +0 1 +.names 50126 50184 50185 +11 1 +.names 49954 50186 +1 1 +.names 50186 50187 +0 1 +.names 9666 50187 50188 +11 1 +.names 50192 50195 57434 +1- 1 +-1 1 +.names 14893 50190 +1 1 +.names 50190 50191 +0 1 +.names 50103 50191 50192 +11 1 +.names 49962 50193 +1 1 +.names 50193 50194 +0 1 +.names 9667 50194 50195 +11 1 +.names 50199 50202 57435 +1- 1 +-1 1 +.names 14862 50197 +1 1 +.names 50197 50198 +0 1 +.names 50126 50198 50199 +11 1 +.names 49970 50200 +1 1 +.names 50200 50201 +0 1 +.names 9666 50201 50202 +11 1 +.names 50206 50209 57436 +1- 1 +-1 1 +.names 14842 50204 +1 1 +.names 50204 50205 +0 1 +.names 50103 50205 50206 +11 1 +.names 49978 50207 +1 1 +.names 50207 50208 +0 1 +.names 9667 50208 50209 +11 1 +.names 50213 50216 57437 +1- 1 +-1 1 +.names 44758 50211 +1 1 +.names 50211 50212 +0 1 +.names 50111 50212 50213 +11 1 +.names 49986 50214 +1 1 +.names 50214 50215 +0 1 +.names 9661 50215 50216 +11 1 +.names 50220 50223 57438 +1- 1 +-1 1 +.names 44638 50218 +1 1 +.names 50218 50219 +0 1 +.names 50111 50219 50220 +11 1 +.names 49994 50221 +1 1 +.names 50221 50222 +0 1 +.names 9661 50222 50223 +11 1 +.names 50227 50230 57439 +1- 1 +-1 1 +.names 44587 50225 +1 1 +.names 50225 50226 +0 1 +.names 50126 50226 50227 +11 1 +.names 50002 50228 +1 1 +.names 50228 50229 +0 1 +.names 9666 50229 50230 +11 1 +.names 50234 50237 57440 +1- 1 +-1 1 +.names 44656 50232 +1 1 +.names 50232 50233 +0 1 +.names 50111 50233 50234 +11 1 +.names 50010 50235 +1 1 +.names 50235 50236 +0 1 +.names 9661 50236 50237 +11 1 +.names 50241 50244 57441 +1- 1 +-1 1 +.names 14792 50239 +1 1 +.names 50239 50240 +0 1 +.names 50103 50240 50241 +11 1 +.names 50018 50242 +1 1 +.names 50242 50243 +0 1 +.names 9667 50243 50244 +11 1 +.names 50248 50251 57442 +1- 1 +-1 1 +.names 44647 50246 +1 1 +.names 50246 50247 +0 1 +.names 50103 50247 50248 +11 1 +.names 50026 50249 +1 1 +.names 50249 50250 +0 1 +.names 9667 50250 50251 +11 1 +.names 50255 50258 57443 +1- 1 +-1 1 +.names 44527 50253 +1 1 +.names 50253 50254 +0 1 +.names 50126 50254 50255 +11 1 +.names 50034 50256 +1 1 +.names 50256 50257 +0 1 +.names 9666 50257 50258 +11 1 +.names 50262 50265 57444 +1- 1 +-1 1 +.names 57098 50260 +1 1 +.names 50260 50261 +0 1 +.names 50126 50261 50262 +11 1 +.names 50042 50263 +1 1 +.names 50263 50264 +0 1 +.names 9666 50264 50265 +11 1 +.names 50269 50272 57445 +1- 1 +-1 1 +.names 44699 50267 +1 1 +.names 50267 50268 +0 1 +.names 50111 50268 50269 +11 1 +.names 50050 50270 +1 1 +.names 50270 50271 +0 1 +.names 9661 50271 50272 +11 1 +.names 50276 50279 57446 +1- 1 +-1 1 +.names 44767 50274 +1 1 +.names 50274 50275 +0 1 +.names 50126 50275 50276 +11 1 +.names 50058 50277 +1 1 +.names 50277 50278 +0 1 +.names 9666 50278 50279 +11 1 +.names 50283 50286 57447 +1- 1 +-1 1 +.names 14882 50281 +1 1 +.names 50281 50282 +0 1 +.names 50111 50282 50283 +11 1 +.names 50066 50284 +1 1 +.names 50284 50285 +0 1 +.names 9661 50285 50286 +11 1 +.names 50290 50293 57448 +1- 1 +-1 1 +.names 14872 50288 +1 1 +.names 50288 50289 +0 1 +.names 50103 50289 50290 +11 1 +.names 50074 50291 +1 1 +.names 50291 50292 +0 1 +.names 9667 50292 50293 +11 1 +.names 50297 50300 57449 +1- 1 +-1 1 +.names 44518 50295 +1 1 +.names 50295 50296 +0 1 +.names 50103 50296 50297 +11 1 +.names 50082 50298 +1 1 +.names 50298 50299 +0 1 +.names 9667 50299 50300 +11 1 +.names 50304 50307 57450 +1- 1 +-1 1 +.names 14782 50302 +1 1 +.names 50302 50303 +0 1 +.names 50126 50303 50304 +11 1 +.names 50090 50305 +1 1 +.names 50305 50306 +0 1 +.names 9666 50306 50307 +11 1 +.names 50311 50314 57451 +1- 1 +-1 1 +.names 14760 50309 +1 1 +.names 50309 50310 +0 1 +.names 50111 50310 50311 +11 1 +.names 50098 50312 +1 1 +.names 50312 50313 +0 1 +.names 9661 50313 50314 +11 1 +.names 1204 50315 +0 1 +.names 21452 21465 50316 +1- 1 +-1 1 +.names 50316 50317 +1 1 +.names 21426 21440 50318 +11 1 +.names 50318 50319 +1 1 +.names 21418 50320 +0 1 +.names 50324 50321 +0 1 +.names 50321 50322 +1 1 +.names 50319 50323 +0 1 +.names 50323 50324 +1 1 +.names 50327 50330 50325 +1- 1 +-1 1 +.names 50325 50326 +1 1 +.names 50322 50327 +0 1 +.names 21383 21456 50328 +11 1 +.names 50328 50329 +1 1 +.names 50329 50330 +0 1 +.names 50336 50337 50331 +11 1 +.names 50331 50332 +1 1 +.names 21399 21407 50333 +1- 1 +-1 1 +.names 50333 50334 +1 1 +.names 50334 50335 +0 1 +.names 50335 50323 50336 +1- 1 +-1 1 +.names 50317 50337 +0 1 +.names 50342 50338 +0 1 +.names 50338 50339 +1 1 +.names 21462 50343 50340 +1- 1 +-1 1 +.names 50340 50341 +1 1 +.names 50341 21449 50342 +01 1 +10 1 +.names 21460 50343 +0 1 +.names 21449 50346 50344 +1- 1 +-1 1 +.names 50344 50345 +1 1 +.names 21445 50346 +0 1 +.names 50350 50345 50347 +01 1 +10 1 +.names 50347 50348 +1 1 +.names 21404 50349 +0 1 +.names 50349 50350 +1 1 +.names 50354 50341 50351 +01 1 +10 1 +.names 50351 50352 +1 1 +.names 50355 50356 50353 +11 1 +.names 50353 50354 +1 1 +.names 50346 50349 50355 +1- 1 +-1 1 +.names 21449 50356 +0 1 +.names 50345 50357 +0 1 +.names 50357 50358 +1 1 +.names 1207 50359 +0 1 +.names 50358 50360 +0 1 +.names 50360 50361 +1 1 +.names 50368 50372 50362 +1- 1 +-1 1 +.names 50362 50363 +1 1 +.names 50489 50364 +1 1 +.names 50364 50365 +1 1 +.names 50365 50366 +0 1 +.names 50361 50367 +0 1 +.names 50366 50367 50368 +11 1 +.names 50348 50369 +0 1 +.names 50369 50370 +1 1 +.names 50370 50371 +0 1 +.names 50365 50371 50372 +11 1 +.names 50352 50373 +0 1 +.names 50373 50374 +1 1 +.names 50380 50382 50375 +1- 1 +-1 1 +.names 50375 50376 +1 1 +.names 50339 50377 +0 1 +.names 50377 50378 +1 1 +.names 50378 50379 +0 1 +.names 50366 50379 50380 +11 1 +.names 50374 50381 +0 1 +.names 50365 50381 50382 +11 1 +.names 1209 50383 +0 1 +.names 21403 21444 50384 +11 1 +.names 50384 50385 +1 1 +.names 21448 21461 50386 +1- 1 +-1 1 +.names 50386 50387 +1 1 +.names 50392 50388 +0 1 +.names 50388 50389 +1 1 +.names 21466 50349 50390 +1- 1 +-1 1 +.names 50390 50391 +1 1 +.names 50391 21453 50392 +01 1 +10 1 +.names 21453 50395 50393 +1- 1 +-1 1 +.names 50393 50394 +1 1 +.names 21427 50395 +0 1 +.names 50399 50394 50396 +01 1 +10 1 +.names 50396 50397 +1 1 +.names 21441 50398 +0 1 +.names 50398 50399 +1 1 +.names 50403 50391 50400 +01 1 +10 1 +.names 50400 50401 +1 1 +.names 50404 50405 50402 +11 1 +.names 50402 50403 +1 1 +.names 50395 50398 50404 +1- 1 +-1 1 +.names 21453 50405 +0 1 +.names 50394 50406 +0 1 +.names 50406 50407 +1 1 +.names 1202 50408 +0 1 +.names 50412 50413 50409 +11 1 +.names 50409 50410 +1 1 +.names 50385 50411 +0 1 +.names 50337 50411 50412 +1- 1 +-1 1 +.names 50387 50413 +0 1 +.names 50416 50414 +1 1 +.names 50414 50415 +1 1 +.names 50411 50323 50416 +1- 1 +-1 1 +.names 50425 50420 50417 +1- 1 +-1 1 +.names 50417 50418 +1 1 +.names 14886 50419 +1 1 +.names 50419 50420 +0 1 +.names 50420 50421 +1 1 +.names 1205 50422 +0 1 +.names 50422 50423 +1 1 +.names 50421 50424 +0 1 +.names 50423 50425 +0 1 +.names 50407 50426 +0 1 +.names 50426 50427 +1 1 +.names 50432 50436 50428 +1- 1 +-1 1 +.names 50428 50429 +1 1 +.names 21380 50430 +0 1 +.names 50427 50431 +0 1 +.names 50430 50431 50432 +11 1 +.names 50397 50433 +0 1 +.names 50433 50434 +1 1 +.names 50434 50435 +0 1 +.names 21380 50435 50436 +11 1 +.names 50442 50446 50437 +1- 1 +-1 1 +.names 50437 50438 +1 1 +.names 50389 50439 +0 1 +.names 50439 50440 +1 1 +.names 50440 50441 +0 1 +.names 50430 50441 50442 +11 1 +.names 50401 50443 +0 1 +.names 50443 50444 +1 1 +.names 50444 50445 +0 1 +.names 21380 50445 50446 +11 1 +.names 21430 50330 50447 +1- 1 +-1 1 +.names 21470 50450 50448 +1- 1 +-1 1 +.names 50448 50449 +1 1 +.names 21384 50450 +0 1 +.names 50453 50455 50451 +01 1 +10 1 +.names 50451 50452 +1 1 +.names 14886 50453 +1 1 +.names 21388 50460 50454 +1- 1 +-1 1 +.names 50454 50455 +1 1 +.names 50459 50449 50456 +01 1 +10 1 +.names 50456 50457 +1 1 +.names 50461 50462 50458 +11 1 +.names 50458 50459 +1 1 +.names 21437 50460 +0 1 +.names 50460 14886 50461 +1- 1 +-1 1 +.names 21388 50462 +0 1 +.names 50466 50463 +0 1 +.names 50463 50464 +1 1 +.names 21388 50460 50465 +1- 1 +-1 1 +.names 50465 50466 +1 1 +.names 50469 50467 +0 1 +.names 50467 50468 +1 1 +.names 50449 21388 50469 +01 1 +10 1 +.names 1208 50470 +0 1 +.names 1206 50471 +0 1 +.names 50477 50478 50472 +1- 1 +-1 1 +.names 50472 50473 +1 1 +.names 21413 50474 +0 1 +.names 50474 50475 +1 1 +.names 50475 50476 +0 1 +.names 50476 50452 50477 +11 1 +.names 50475 50464 50478 +11 1 +.names 50468 50479 +0 1 +.names 50479 50480 +1 1 +.names 50457 50481 +0 1 +.names 50481 50482 +1 1 +.names 50486 50488 50483 +1- 1 +-1 1 +.names 50483 50484 +1 1 +.names 50482 50485 +0 1 +.names 50476 50485 50486 +11 1 +.names 50480 50487 +0 1 +.names 50475 50487 50488 +11 1 +.names 50492 50493 50489 +1- 1 +-1 1 +.names 21431 50490 +0 1 +.names 50326 50491 +0 1 +.names 50490 50491 50492 +11 1 +.names 50332 50493 +0 1 +.names 50410 50494 +0 1 +.names 21379 50494 50495 +1- 1 +-1 1 +.names 50415 50496 +0 1 +.names 50496 50494 50497 +1- 1 +-1 1 +.names 1203 50498 +0 1 +.names 50498 2413 50499 +11 1 +.names 50504 50500 +0 1 +.names 50500 50501 +1 1 +.names 21408 50398 50502 +1- 1 +-1 1 +.names 50502 50503 +1 1 +.names 50503 21400 50504 +01 1 +10 1 +.names 50508 50505 +0 1 +.names 50505 50506 +1 1 +.names 21400 50509 50507 +1- 1 +-1 1 +.names 50507 50508 +1 1 +.names 21457 50509 +0 1 +.names 50512 50508 50510 +01 1 +10 1 +.names 50510 50511 +1 1 +.names 50450 50512 +1 1 +.names 50503 50516 50513 +01 1 +10 1 +.names 50513 50514 +1 1 +.names 50517 50518 50515 +11 1 +.names 50515 50516 +1 1 +.names 50509 50450 50517 +1- 1 +-1 1 +.names 21400 50518 +0 1 +.names 50523 50524 50519 +1- 1 +-1 1 +.names 50519 50520 +1 1 +.names 21430 50521 +1 1 +.names 50521 50522 +0 1 +.names 50522 50511 50523 +11 1 +.names 50521 50506 50524 +11 1 +.names 50501 50525 +0 1 +.names 50525 50526 +1 1 +.names 50534 50536 50527 +1- 1 +-1 1 +.names 50527 50528 +1 1 +.names 50521 50529 +1 1 +.names 50529 50530 +0 1 +.names 50514 50531 +0 1 +.names 50531 50532 +1 1 +.names 50532 50533 +0 1 +.names 50530 50533 50534 +11 1 +.names 50526 50535 +0 1 +.names 50529 50535 50536 +11 1 +.names 21538 21554 50537 +1- 1 +-1 1 +.names 50537 50538 +1 1 +.names 21512 21526 50539 +11 1 +.names 50539 50540 +1 1 +.names 21504 50541 +0 1 +.names 50545 50542 +0 1 +.names 50542 50543 +1 1 +.names 50540 50544 +0 1 +.names 50544 50545 +1 1 +.names 50548 50551 50546 +1- 1 +-1 1 +.names 50546 50547 +1 1 +.names 50543 50548 +0 1 +.names 21477 21542 50549 +11 1 +.names 50549 50550 +1 1 +.names 50550 50551 +0 1 +.names 50557 50558 50552 +11 1 +.names 50552 50553 +1 1 +.names 21485 21493 50554 +1- 1 +-1 1 +.names 50554 50555 +1 1 +.names 50555 50556 +0 1 +.names 50556 50544 50557 +1- 1 +-1 1 +.names 50538 50558 +0 1 +.names 50563 50559 +0 1 +.names 50559 50560 +1 1 +.names 21551 50564 50561 +1- 1 +-1 1 +.names 50561 50562 +1 1 +.names 50562 21535 50563 +01 1 +10 1 +.names 21547 50564 +0 1 +.names 21535 50567 50565 +1- 1 +-1 1 +.names 50565 50566 +1 1 +.names 21531 50567 +0 1 +.names 50571 50566 50568 +01 1 +10 1 +.names 50568 50569 +1 1 +.names 21490 50570 +0 1 +.names 50570 50571 +1 1 +.names 50575 50562 50572 +01 1 +10 1 +.names 50572 50573 +1 1 +.names 50576 50577 50574 +11 1 +.names 50574 50575 +1 1 +.names 50567 50570 50576 +1- 1 +-1 1 +.names 21535 50577 +0 1 +.names 50566 50578 +0 1 +.names 50578 50579 +1 1 +.names 50579 50580 +0 1 +.names 50580 50581 +1 1 +.names 50680 50582 +1 1 +.names 50582 50583 +1 1 +.names 50583 50584 +0 1 +.names 50581 50585 +0 1 +.names 50584 50585 50586 +11 1 +.names 50569 50587 +0 1 +.names 50587 50588 +1 1 +.names 50588 50589 +0 1 +.names 50583 50589 50590 +11 1 +.names 50573 50591 +0 1 +.names 50591 50592 +1 1 +.names 50560 50593 +0 1 +.names 50593 50594 +1 1 +.names 50594 50595 +0 1 +.names 50584 50595 50596 +11 1 +.names 50592 50597 +0 1 +.names 50583 50597 50598 +11 1 +.names 50603 50599 +0 1 +.names 50599 50600 +1 1 +.names 21555 50570 50601 +1- 1 +-1 1 +.names 50601 50602 +1 1 +.names 50602 21539 50603 +01 1 +10 1 +.names 21539 50606 50604 +1- 1 +-1 1 +.names 50604 50605 +1 1 +.names 21513 50606 +0 1 +.names 50610 50605 50607 +01 1 +10 1 +.names 50607 50608 +1 1 +.names 21527 50609 +0 1 +.names 50609 50610 +1 1 +.names 50614 50602 50611 +01 1 +10 1 +.names 50611 50612 +1 1 +.names 50615 50616 50613 +11 1 +.names 50613 50614 +1 1 +.names 50606 50609 50615 +1- 1 +-1 1 +.names 21539 50616 +0 1 +.names 50605 50617 +0 1 +.names 50617 50618 +1 1 +.names 50626 50622 50619 +1- 1 +-1 1 +.names 50619 50620 +1 1 +.names 14886 50621 +1 1 +.names 50621 50622 +0 1 +.names 50622 50623 +1 1 +.names 50422 50624 +1 1 +.names 50623 50625 +0 1 +.names 50624 50626 +0 1 +.names 50618 50627 +0 1 +.names 50627 50628 +1 1 +.names 21474 50629 +0 1 +.names 50628 50630 +0 1 +.names 50629 50630 50631 +11 1 +.names 50608 50632 +0 1 +.names 50632 50633 +1 1 +.names 50633 50634 +0 1 +.names 21474 50634 50635 +11 1 +.names 50600 50636 +0 1 +.names 50636 50637 +1 1 +.names 50637 50638 +0 1 +.names 50629 50638 50639 +11 1 +.names 50612 50640 +0 1 +.names 50640 50641 +1 1 +.names 50641 50642 +0 1 +.names 21474 50642 50643 +11 1 +.names 21516 50551 50644 +1- 1 +-1 1 +.names 21559 50647 50645 +1- 1 +-1 1 +.names 50645 50646 +1 1 +.names 21478 50647 +0 1 +.names 50650 50652 50648 +01 1 +10 1 +.names 50648 50649 +1 1 +.names 14886 50650 +1 1 +.names 21482 50657 50651 +1- 1 +-1 1 +.names 50651 50652 +1 1 +.names 50656 50646 50653 +01 1 +10 1 +.names 50653 50654 +1 1 +.names 50658 50659 50655 +11 1 +.names 50655 50656 +1 1 +.names 21523 50657 +0 1 +.names 50657 14886 50658 +1- 1 +-1 1 +.names 21482 50659 +0 1 +.names 50663 50660 +0 1 +.names 50660 50661 +1 1 +.names 21482 50657 50662 +1- 1 +-1 1 +.names 50662 50663 +1 1 +.names 50666 50664 +0 1 +.names 50664 50665 +1 1 +.names 50646 21482 50666 +01 1 +10 1 +.names 21499 50667 +0 1 +.names 50667 50668 +1 1 +.names 50668 50669 +0 1 +.names 50669 50649 50670 +11 1 +.names 50668 50661 50671 +11 1 +.names 50665 50672 +0 1 +.names 50672 50673 +1 1 +.names 50654 50674 +0 1 +.names 50674 50675 +1 1 +.names 50675 50676 +0 1 +.names 50669 50676 50677 +11 1 +.names 50673 50678 +0 1 +.names 50668 50678 50679 +11 1 +.names 50683 50684 50680 +1- 1 +-1 1 +.names 21517 50681 +0 1 +.names 50547 50682 +0 1 +.names 50681 50682 50683 +11 1 +.names 50553 50684 +0 1 +.names 50498 14886 50685 +11 1 +.names 50690 50686 +0 1 +.names 50686 50687 +1 1 +.names 21494 50609 50688 +1- 1 +-1 1 +.names 50688 50689 +1 1 +.names 50689 21486 50690 +01 1 +10 1 +.names 50694 50691 +0 1 +.names 50691 50692 +1 1 +.names 21486 50695 50693 +1- 1 +-1 1 +.names 50693 50694 +1 1 +.names 21543 50695 +0 1 +.names 50698 50694 50696 +01 1 +10 1 +.names 50696 50697 +1 1 +.names 50647 50698 +1 1 +.names 50689 50702 50699 +01 1 +10 1 +.names 50699 50700 +1 1 +.names 50703 50704 50701 +11 1 +.names 50701 50702 +1 1 +.names 50695 50647 50703 +1- 1 +-1 1 +.names 21486 50704 +0 1 +.names 21516 50705 +1 1 +.names 50705 50706 +0 1 +.names 50706 50697 50707 +11 1 +.names 50705 50692 50708 +11 1 +.names 50687 50709 +0 1 +.names 50709 50710 +1 1 +.names 50705 50711 +1 1 +.names 50711 50712 +0 1 +.names 50700 50713 +0 1 +.names 50713 50714 +1 1 +.names 50714 50715 +0 1 +.names 50712 50715 50716 +11 1 +.names 50710 50717 +0 1 +.names 50711 50717 50718 +11 1 +.names 1212 50719 +0 1 +.names 21635 21648 50720 +1- 1 +-1 1 +.names 50720 50721 +1 1 +.names 21609 21623 50722 +11 1 +.names 50722 50723 +1 1 +.names 21601 50724 +0 1 +.names 50728 50725 +0 1 +.names 50725 50726 +1 1 +.names 50723 50727 +0 1 +.names 50727 50728 +1 1 +.names 50731 50734 50729 +1- 1 +-1 1 +.names 50729 50730 +1 1 +.names 50726 50731 +0 1 +.names 21566 21639 50732 +11 1 +.names 50732 50733 +1 1 +.names 50733 50734 +0 1 +.names 50740 50741 50735 +11 1 +.names 50735 50736 +1 1 +.names 21582 21590 50737 +1- 1 +-1 1 +.names 50737 50738 +1 1 +.names 50738 50739 +0 1 +.names 50739 50727 50740 +1- 1 +-1 1 +.names 50721 50741 +0 1 +.names 50746 50742 +0 1 +.names 50742 50743 +1 1 +.names 21645 50747 50744 +1- 1 +-1 1 +.names 50744 50745 +1 1 +.names 50745 21632 50746 +01 1 +10 1 +.names 21643 50747 +0 1 +.names 21632 50750 50748 +1- 1 +-1 1 +.names 50748 50749 +1 1 +.names 21628 50750 +0 1 +.names 50754 50749 50751 +01 1 +10 1 +.names 50751 50752 +1 1 +.names 21587 50753 +0 1 +.names 50753 50754 +1 1 +.names 50758 50745 50755 +01 1 +10 1 +.names 50755 50756 +1 1 +.names 50759 50760 50757 +11 1 +.names 50757 50758 +1 1 +.names 50750 50753 50759 +1- 1 +-1 1 +.names 21632 50760 +0 1 +.names 50749 50761 +0 1 +.names 50761 50762 +1 1 +.names 1215 50763 +0 1 +.names 50762 50764 +0 1 +.names 50764 50765 +1 1 +.names 50772 50776 50766 +1- 1 +-1 1 +.names 50766 50767 +1 1 +.names 50893 50768 +1 1 +.names 50768 50769 +1 1 +.names 50769 50770 +0 1 +.names 50765 50771 +0 1 +.names 50770 50771 50772 +11 1 +.names 50752 50773 +0 1 +.names 50773 50774 +1 1 +.names 50774 50775 +0 1 +.names 50769 50775 50776 +11 1 +.names 50756 50777 +0 1 +.names 50777 50778 +1 1 +.names 50784 50786 50779 +1- 1 +-1 1 +.names 50779 50780 +1 1 +.names 50743 50781 +0 1 +.names 50781 50782 +1 1 +.names 50782 50783 +0 1 +.names 50770 50783 50784 +11 1 +.names 50778 50785 +0 1 +.names 50769 50785 50786 +11 1 +.names 1217 50787 +0 1 +.names 21586 21627 50788 +11 1 +.names 50788 50789 +1 1 +.names 21631 21644 50790 +1- 1 +-1 1 +.names 50790 50791 +1 1 +.names 50796 50792 +0 1 +.names 50792 50793 +1 1 +.names 21649 50753 50794 +1- 1 +-1 1 +.names 50794 50795 +1 1 +.names 50795 21636 50796 +01 1 +10 1 +.names 21636 50799 50797 +1- 1 +-1 1 +.names 50797 50798 +1 1 +.names 21610 50799 +0 1 +.names 50803 50798 50800 +01 1 +10 1 +.names 50800 50801 +1 1 +.names 21624 50802 +0 1 +.names 50802 50803 +1 1 +.names 50807 50795 50804 +01 1 +10 1 +.names 50804 50805 +1 1 +.names 50808 50809 50806 +11 1 +.names 50806 50807 +1 1 +.names 50799 50802 50808 +1- 1 +-1 1 +.names 21636 50809 +0 1 +.names 50798 50810 +0 1 +.names 50810 50811 +1 1 +.names 1210 50812 +0 1 +.names 50816 50817 50813 +11 1 +.names 50813 50814 +1 1 +.names 50789 50815 +0 1 +.names 50741 50815 50816 +1- 1 +-1 1 +.names 50791 50817 +0 1 +.names 50820 50818 +1 1 +.names 50818 50819 +1 1 +.names 50815 50727 50820 +1- 1 +-1 1 +.names 50829 50824 50821 +1- 1 +-1 1 +.names 50821 50822 +1 1 +.names 14886 50823 +1 1 +.names 50823 50824 +0 1 +.names 50824 50825 +1 1 +.names 1213 50826 +0 1 +.names 50826 50827 +1 1 +.names 50825 50828 +0 1 +.names 50827 50829 +0 1 +.names 50811 50830 +0 1 +.names 50830 50831 +1 1 +.names 50836 50840 50832 +1- 1 +-1 1 +.names 50832 50833 +1 1 +.names 21563 50834 +0 1 +.names 50831 50835 +0 1 +.names 50834 50835 50836 +11 1 +.names 50801 50837 +0 1 +.names 50837 50838 +1 1 +.names 50838 50839 +0 1 +.names 21563 50839 50840 +11 1 +.names 50846 50850 50841 +1- 1 +-1 1 +.names 50841 50842 +1 1 +.names 50793 50843 +0 1 +.names 50843 50844 +1 1 +.names 50844 50845 +0 1 +.names 50834 50845 50846 +11 1 +.names 50805 50847 +0 1 +.names 50847 50848 +1 1 +.names 50848 50849 +0 1 +.names 21563 50849 50850 +11 1 +.names 21613 50734 50851 +1- 1 +-1 1 +.names 21653 50854 50852 +1- 1 +-1 1 +.names 50852 50853 +1 1 +.names 21567 50854 +0 1 +.names 50857 50859 50855 +01 1 +10 1 +.names 50855 50856 +1 1 +.names 14886 50857 +1 1 +.names 21571 50864 50858 +1- 1 +-1 1 +.names 50858 50859 +1 1 +.names 50863 50853 50860 +01 1 +10 1 +.names 50860 50861 +1 1 +.names 50865 50866 50862 +11 1 +.names 50862 50863 +1 1 +.names 21620 50864 +0 1 +.names 50864 14886 50865 +1- 1 +-1 1 +.names 21571 50866 +0 1 +.names 50870 50867 +0 1 +.names 50867 50868 +1 1 +.names 21571 50864 50869 +1- 1 +-1 1 +.names 50869 50870 +1 1 +.names 50873 50871 +0 1 +.names 50871 50872 +1 1 +.names 50853 21571 50873 +01 1 +10 1 +.names 1216 50874 +0 1 +.names 1214 50875 +0 1 +.names 50881 50882 50876 +1- 1 +-1 1 +.names 50876 50877 +1 1 +.names 21596 50878 +0 1 +.names 50878 50879 +1 1 +.names 50879 50880 +0 1 +.names 50880 50856 50881 +11 1 +.names 50879 50868 50882 +11 1 +.names 50872 50883 +0 1 +.names 50883 50884 +1 1 +.names 50861 50885 +0 1 +.names 50885 50886 +1 1 +.names 50890 50892 50887 +1- 1 +-1 1 +.names 50887 50888 +1 1 +.names 50886 50889 +0 1 +.names 50880 50889 50890 +11 1 +.names 50884 50891 +0 1 +.names 50879 50891 50892 +11 1 +.names 50896 50897 50893 +1- 1 +-1 1 +.names 21614 50894 +0 1 +.names 50730 50895 +0 1 +.names 50894 50895 50896 +11 1 +.names 50736 50897 +0 1 +.names 50814 50898 +0 1 +.names 21562 50898 50899 +1- 1 +-1 1 +.names 50819 50900 +0 1 +.names 50900 50898 50901 +1- 1 +-1 1 +.names 1211 50902 +0 1 +.names 50902 2413 50903 +11 1 +.names 50908 50904 +0 1 +.names 50904 50905 +1 1 +.names 21591 50802 50906 +1- 1 +-1 1 +.names 50906 50907 +1 1 +.names 50907 21583 50908 +01 1 +10 1 +.names 50912 50909 +0 1 +.names 50909 50910 +1 1 +.names 21583 50913 50911 +1- 1 +-1 1 +.names 50911 50912 +1 1 +.names 21640 50913 +0 1 +.names 50916 50912 50914 +01 1 +10 1 +.names 50914 50915 +1 1 +.names 50854 50916 +1 1 +.names 50907 50920 50917 +01 1 +10 1 +.names 50917 50918 +1 1 +.names 50921 50922 50919 +11 1 +.names 50919 50920 +1 1 +.names 50913 50854 50921 +1- 1 +-1 1 +.names 21583 50922 +0 1 +.names 50927 50928 50923 +1- 1 +-1 1 +.names 50923 50924 +1 1 +.names 21613 50925 +1 1 +.names 50925 50926 +0 1 +.names 50926 50915 50927 +11 1 +.names 50925 50910 50928 +11 1 +.names 50905 50929 +0 1 +.names 50929 50930 +1 1 +.names 50938 50940 50931 +1- 1 +-1 1 +.names 50931 50932 +1 1 +.names 50925 50933 +1 1 +.names 50933 50934 +0 1 +.names 50918 50935 +0 1 +.names 50935 50936 +1 1 +.names 50936 50937 +0 1 +.names 50934 50937 50938 +11 1 +.names 50930 50939 +0 1 +.names 50933 50939 50940 +11 1 +.names 21721 21737 50941 +1- 1 +-1 1 +.names 50941 50942 +1 1 +.names 21695 21709 50943 +11 1 +.names 50943 50944 +1 1 +.names 21687 50945 +0 1 +.names 50949 50946 +0 1 +.names 50946 50947 +1 1 +.names 50944 50948 +0 1 +.names 50948 50949 +1 1 +.names 50952 50955 50950 +1- 1 +-1 1 +.names 50950 50951 +1 1 +.names 50947 50952 +0 1 +.names 21660 21725 50953 +11 1 +.names 50953 50954 +1 1 +.names 50954 50955 +0 1 +.names 50961 50962 50956 +11 1 +.names 50956 50957 +1 1 +.names 21668 21676 50958 +1- 1 +-1 1 +.names 50958 50959 +1 1 +.names 50959 50960 +0 1 +.names 50960 50948 50961 +1- 1 +-1 1 +.names 50942 50962 +0 1 +.names 50967 50963 +0 1 +.names 50963 50964 +1 1 +.names 21734 50968 50965 +1- 1 +-1 1 +.names 50965 50966 +1 1 +.names 50966 21718 50967 +01 1 +10 1 +.names 21730 50968 +0 1 +.names 21718 50971 50969 +1- 1 +-1 1 +.names 50969 50970 +1 1 +.names 21714 50971 +0 1 +.names 50975 50970 50972 +01 1 +10 1 +.names 50972 50973 +1 1 +.names 21673 50974 +0 1 +.names 50974 50975 +1 1 +.names 50979 50966 50976 +01 1 +10 1 +.names 50976 50977 +1 1 +.names 50980 50981 50978 +11 1 +.names 50978 50979 +1 1 +.names 50971 50974 50980 +1- 1 +-1 1 +.names 21718 50981 +0 1 +.names 50970 50982 +0 1 +.names 50982 50983 +1 1 +.names 50983 50984 +0 1 +.names 50984 50985 +1 1 +.names 51084 50986 +1 1 +.names 50986 50987 +1 1 +.names 50987 50988 +0 1 +.names 50985 50989 +0 1 +.names 50988 50989 50990 +11 1 +.names 50973 50991 +0 1 +.names 50991 50992 +1 1 +.names 50992 50993 +0 1 +.names 50987 50993 50994 +11 1 +.names 50977 50995 +0 1 +.names 50995 50996 +1 1 +.names 50964 50997 +0 1 +.names 50997 50998 +1 1 +.names 50998 50999 +0 1 +.names 50988 50999 51000 +11 1 +.names 50996 51001 +0 1 +.names 50987 51001 51002 +11 1 +.names 51007 51003 +0 1 +.names 51003 51004 +1 1 +.names 21738 50974 51005 +1- 1 +-1 1 +.names 51005 51006 +1 1 +.names 51006 21722 51007 +01 1 +10 1 +.names 21722 51010 51008 +1- 1 +-1 1 +.names 51008 51009 +1 1 +.names 21696 51010 +0 1 +.names 51014 51009 51011 +01 1 +10 1 +.names 51011 51012 +1 1 +.names 21710 51013 +0 1 +.names 51013 51014 +1 1 +.names 51018 51006 51015 +01 1 +10 1 +.names 51015 51016 +1 1 +.names 51019 51020 51017 +11 1 +.names 51017 51018 +1 1 +.names 51010 51013 51019 +1- 1 +-1 1 +.names 21722 51020 +0 1 +.names 51009 51021 +0 1 +.names 51021 51022 +1 1 +.names 51030 51026 51023 +1- 1 +-1 1 +.names 51023 51024 +1 1 +.names 14886 51025 +1 1 +.names 51025 51026 +0 1 +.names 51026 51027 +1 1 +.names 50826 51028 +1 1 +.names 51027 51029 +0 1 +.names 51028 51030 +0 1 +.names 51022 51031 +0 1 +.names 51031 51032 +1 1 +.names 21657 51033 +0 1 +.names 51032 51034 +0 1 +.names 51033 51034 51035 +11 1 +.names 51012 51036 +0 1 +.names 51036 51037 +1 1 +.names 51037 51038 +0 1 +.names 21657 51038 51039 +11 1 +.names 51004 51040 +0 1 +.names 51040 51041 +1 1 +.names 51041 51042 +0 1 +.names 51033 51042 51043 +11 1 +.names 51016 51044 +0 1 +.names 51044 51045 +1 1 +.names 51045 51046 +0 1 +.names 21657 51046 51047 +11 1 +.names 21699 50955 51048 +1- 1 +-1 1 +.names 21742 51051 51049 +1- 1 +-1 1 +.names 51049 51050 +1 1 +.names 21661 51051 +0 1 +.names 51054 51056 51052 +01 1 +10 1 +.names 51052 51053 +1 1 +.names 14886 51054 +1 1 +.names 21665 51061 51055 +1- 1 +-1 1 +.names 51055 51056 +1 1 +.names 51060 51050 51057 +01 1 +10 1 +.names 51057 51058 +1 1 +.names 51062 51063 51059 +11 1 +.names 51059 51060 +1 1 +.names 21706 51061 +0 1 +.names 51061 14886 51062 +1- 1 +-1 1 +.names 21665 51063 +0 1 +.names 51067 51064 +0 1 +.names 51064 51065 +1 1 +.names 21665 51061 51066 +1- 1 +-1 1 +.names 51066 51067 +1 1 +.names 51070 51068 +0 1 +.names 51068 51069 +1 1 +.names 51050 21665 51070 +01 1 +10 1 +.names 21682 51071 +0 1 +.names 51071 51072 +1 1 +.names 51072 51073 +0 1 +.names 51073 51053 51074 +11 1 +.names 51072 51065 51075 +11 1 +.names 51069 51076 +0 1 +.names 51076 51077 +1 1 +.names 51058 51078 +0 1 +.names 51078 51079 +1 1 +.names 51079 51080 +0 1 +.names 51073 51080 51081 +11 1 +.names 51077 51082 +0 1 +.names 51072 51082 51083 +11 1 +.names 51087 51088 51084 +1- 1 +-1 1 +.names 21700 51085 +0 1 +.names 50951 51086 +0 1 +.names 51085 51086 51087 +11 1 +.names 50957 51088 +0 1 +.names 50902 14886 51089 +11 1 +.names 51094 51090 +0 1 +.names 51090 51091 +1 1 +.names 21677 51013 51092 +1- 1 +-1 1 +.names 51092 51093 +1 1 +.names 51093 21669 51094 +01 1 +10 1 +.names 51098 51095 +0 1 +.names 51095 51096 +1 1 +.names 21669 51099 51097 +1- 1 +-1 1 +.names 51097 51098 +1 1 +.names 21726 51099 +0 1 +.names 51102 51098 51100 +01 1 +10 1 +.names 51100 51101 +1 1 +.names 51051 51102 +1 1 +.names 51093 51106 51103 +01 1 +10 1 +.names 51103 51104 +1 1 +.names 51107 51108 51105 +11 1 +.names 51105 51106 +1 1 +.names 51099 51051 51107 +1- 1 +-1 1 +.names 21669 51108 +0 1 +.names 21699 51109 +1 1 +.names 51109 51110 +0 1 +.names 51110 51101 51111 +11 1 +.names 51109 51096 51112 +11 1 +.names 51091 51113 +0 1 +.names 51113 51114 +1 1 +.names 51109 51115 +1 1 +.names 51115 51116 +0 1 +.names 51104 51117 +0 1 +.names 51117 51118 +1 1 +.names 51118 51119 +0 1 +.names 51116 51119 51120 +11 1 +.names 51114 51121 +0 1 +.names 51115 51121 51122 +11 1 +.names 51125 51126 51123 +1- 1 +-1 1 +.names 51123 51124 +1 1 +.names 50484 51125 +0 1 +.names 9682 51126 +0 1 +.names 51129 51130 51127 +1- 1 +-1 1 +.names 51127 51128 +1 1 +.names 9674 1783 51129 +11 1 +.names 51124 51130 +0 1 +.names 51133 51134 51131 +11 1 +.names 51131 51132 +1 1 +.names 56700 51126 51133 +11 1 +.names 9674 51134 +0 1 +.names 51139 51141 51135 +1- 1 +-1 1 +.names 51135 51136 +1 1 +.names 9684 51137 +0 1 +.names 51132 51138 +0 1 +.names 51137 51138 51139 +11 1 +.names 21753 51140 +0 1 +.names 9684 51140 51141 +11 1 +.names 51128 51143 57452 +1- 1 +-1 1 +.names 51136 51143 +0 1 +.names 51146 51126 51144 +1- 1 +-1 1 +.names 51144 51145 +1 1 +.names 50363 51146 +0 1 +.names 51149 51150 51147 +1- 1 +-1 1 +.names 51147 51148 +1 1 +.names 9674 1783 51149 +11 1 +.names 51145 51150 +0 1 +.names 51153 51134 51151 +11 1 +.names 51151 51152 +1 1 +.names 56705 51126 51153 +11 1 +.names 51157 51159 51154 +1- 1 +-1 1 +.names 51154 51155 +1 1 +.names 51152 51156 +0 1 +.names 51137 51156 51157 +11 1 +.names 21789 51158 +0 1 +.names 9684 51158 51159 +11 1 +.names 51148 51161 57453 +1- 1 +-1 1 +.names 51155 51161 +0 1 +.names 51164 51126 51162 +1- 1 +-1 1 +.names 51162 51163 +1 1 +.names 50473 51164 +0 1 +.names 51167 51168 51165 +1- 1 +-1 1 +.names 51165 51166 +1 1 +.names 1775 9674 51167 +11 1 +.names 51163 51168 +0 1 +.names 51171 51134 51169 +11 1 +.names 51169 51170 +1 1 +.names 56699 51126 51171 +11 1 +.names 51175 51177 51172 +1- 1 +-1 1 +.names 51172 51173 +1 1 +.names 51170 51174 +0 1 +.names 51137 51174 51175 +11 1 +.names 21770 51176 +0 1 +.names 9684 51176 51177 +11 1 +.names 51166 51179 57454 +1- 1 +-1 1 +.names 51173 51179 +0 1 +.names 51183 51184 51180 +11 1 +.names 51180 51181 +1 1 +.names 9683 51182 +0 1 +.names 56701 51182 51183 +11 1 +.names 9672 51184 +0 1 +.names 51187 51190 57455 +1- 1 +-1 1 +.names 51196 51199 51186 +1- 1 +-1 1 +.names 51186 51187 +1 1 +.names 51193 51195 51188 +1- 1 +-1 1 +.names 51188 51189 +1 1 +.names 51189 51190 +0 1 +.names 51134 51191 +1 1 +.names 51191 51192 +0 1 +.names 51192 2413 51193 +11 1 +.names 51181 51194 +0 1 +.names 51191 51194 51195 +11 1 +.names 21748 9683 51196 +11 1 +.names 51200 51184 51197 +1- 1 +-1 1 +.names 51197 51198 +1 1 +.names 51198 51199 +0 1 +.names 50520 51200 +0 1 +.names 51206 51208 51201 +1- 1 +-1 1 +.names 51201 51202 +1 1 +.names 51209 51134 51203 +11 1 +.names 51203 51204 +1 1 +.names 51204 51205 +0 1 +.names 51137 51205 51206 +11 1 +.names 21806 51207 +0 1 +.names 9684 51207 51208 +11 1 +.names 56704 51184 51209 +11 1 +.names 51212 51213 57456 +1- 1 +-1 1 +.names 51214 51217 51211 +1- 1 +-1 1 +.names 51211 51212 +1 1 +.names 51202 51213 +0 1 +.names 1783 9674 51214 +11 1 +.names 51218 51184 51215 +1- 1 +-1 1 +.names 51215 51216 +1 1 +.names 51216 51217 +0 1 +.names 50438 51218 +0 1 +.names 51221 51184 51219 +11 1 +.names 51219 51220 +1 1 +.names 56706 51182 51221 +11 1 +.names 51226 51228 51222 +1- 1 +-1 1 +.names 51222 51223 +1 1 +.names 51134 51224 +1 1 +.names 51224 51225 +0 1 +.names 51225 2413 51226 +11 1 +.names 51220 51227 +0 1 +.names 51224 51227 51228 +11 1 +.names 51231 51234 51229 +1- 1 +-1 1 +.names 51229 51230 +1 1 +.names 21779 9683 51231 +11 1 +.names 51235 51184 51232 +1- 1 +-1 1 +.names 51232 51233 +1 1 +.names 51233 51234 +0 1 +.names 50376 51235 +0 1 +.names 51230 51236 +0 1 +.names 51236 51237 +1 1 +.names 51239 51240 57457 +1- 1 +-1 1 +.names 51237 51239 +0 1 +.names 51223 51240 +0 1 +.names 51243 51184 51241 +11 1 +.names 51241 51242 +1 1 +.names 56702 51182 51243 +11 1 +.names 51246 51249 57458 +1- 1 +-1 1 +.names 51255 51258 51245 +1- 1 +-1 1 +.names 51245 51246 +1 1 +.names 51252 51254 51247 +1- 1 +-1 1 +.names 51247 51248 +1 1 +.names 51248 51249 +0 1 +.names 51134 51250 +1 1 +.names 51250 51251 +0 1 +.names 51251 2413 51252 +11 1 +.names 51242 51253 +0 1 +.names 51250 51253 51254 +11 1 +.names 21765 9683 51255 +11 1 +.names 51259 51184 51256 +1- 1 +-1 1 +.names 51256 51257 +1 1 +.names 51257 51258 +0 1 +.names 50528 51259 +0 1 +.names 51262 51126 51260 +1- 1 +-1 1 +.names 51260 51261 +1 1 +.names 50429 51262 +0 1 +.names 51265 51266 51263 +1- 1 +-1 1 +.names 51263 51264 +1 1 +.names 1783 9674 51265 +11 1 +.names 51261 51266 +0 1 +.names 51269 51134 51267 +11 1 +.names 51267 51268 +1 1 +.names 56703 51126 51269 +11 1 +.names 51273 51275 51270 +1- 1 +-1 1 +.names 51270 51271 +1 1 +.names 51268 51272 +0 1 +.names 51137 51272 51273 +11 1 +.names 21784 51274 +0 1 +.names 9684 51274 51275 +11 1 +.names 51264 51277 57459 +1- 1 +-1 1 +.names 51271 51277 +0 1 +.names 51280 51281 51278 +1- 1 +-1 1 +.names 51278 51279 +1 1 +.names 50888 51280 +0 1 +.names 9702 51281 +0 1 +.names 51284 51285 51282 +1- 1 +-1 1 +.names 51282 51283 +1 1 +.names 9694 1783 51284 +11 1 +.names 51279 51285 +0 1 +.names 51288 51289 51286 +11 1 +.names 51286 51287 +1 1 +.names 56700 51281 51288 +11 1 +.names 9694 51289 +0 1 +.names 51294 51296 51290 +1- 1 +-1 1 +.names 51290 51291 +1 1 +.names 9704 51292 +0 1 +.names 51287 51293 +0 1 +.names 51292 51293 51294 +11 1 +.names 21854 51295 +0 1 +.names 9704 51295 51296 +11 1 +.names 51283 51298 57460 +1- 1 +-1 1 +.names 51291 51298 +0 1 +.names 51301 51281 51299 +1- 1 +-1 1 +.names 51299 51300 +1 1 +.names 50767 51301 +0 1 +.names 51304 51305 51302 +1- 1 +-1 1 +.names 51302 51303 +1 1 +.names 9694 1783 51304 +11 1 +.names 51300 51305 +0 1 +.names 51308 51289 51306 +11 1 +.names 51306 51307 +1 1 +.names 56705 51281 51308 +11 1 +.names 51312 51314 51309 +1- 1 +-1 1 +.names 51309 51310 +1 1 +.names 51307 51311 +0 1 +.names 51292 51311 51312 +11 1 +.names 21890 51313 +0 1 +.names 9704 51313 51314 +11 1 +.names 51303 51316 57461 +1- 1 +-1 1 +.names 51310 51316 +0 1 +.names 51319 51281 51317 +1- 1 +-1 1 +.names 51317 51318 +1 1 +.names 50877 51319 +0 1 +.names 51322 51323 51320 +1- 1 +-1 1 +.names 51320 51321 +1 1 +.names 1775 9694 51322 +11 1 +.names 51318 51323 +0 1 +.names 51326 51289 51324 +11 1 +.names 51324 51325 +1 1 +.names 56699 51281 51326 +11 1 +.names 51330 51332 51327 +1- 1 +-1 1 +.names 51327 51328 +1 1 +.names 51325 51329 +0 1 +.names 51292 51329 51330 +11 1 +.names 21871 51331 +0 1 +.names 9704 51331 51332 +11 1 +.names 51321 51334 57462 +1- 1 +-1 1 +.names 51328 51334 +0 1 +.names 51338 51339 51335 +11 1 +.names 51335 51336 +1 1 +.names 9703 51337 +0 1 +.names 56701 51337 51338 +11 1 +.names 9692 51339 +0 1 +.names 51342 51345 57463 +1- 1 +-1 1 +.names 51351 51354 51341 +1- 1 +-1 1 +.names 51341 51342 +1 1 +.names 51348 51350 51343 +1- 1 +-1 1 +.names 51343 51344 +1 1 +.names 51344 51345 +0 1 +.names 51289 51346 +1 1 +.names 51346 51347 +0 1 +.names 51347 2413 51348 +11 1 +.names 51336 51349 +0 1 +.names 51346 51349 51350 +11 1 +.names 21849 9703 51351 +11 1 +.names 51355 51339 51352 +1- 1 +-1 1 +.names 51352 51353 +1 1 +.names 51353 51354 +0 1 +.names 50924 51355 +0 1 +.names 51361 51363 51356 +1- 1 +-1 1 +.names 51356 51357 +1 1 +.names 51364 51289 51358 +11 1 +.names 51358 51359 +1 1 +.names 51359 51360 +0 1 +.names 51292 51360 51361 +11 1 +.names 21907 51362 +0 1 +.names 9704 51362 51363 +11 1 +.names 56704 51339 51364 +11 1 +.names 51367 51368 57464 +1- 1 +-1 1 +.names 51369 51372 51366 +1- 1 +-1 1 +.names 51366 51367 +1 1 +.names 51357 51368 +0 1 +.names 1783 9694 51369 +11 1 +.names 51373 51339 51370 +1- 1 +-1 1 +.names 51370 51371 +1 1 +.names 51371 51372 +0 1 +.names 50842 51373 +0 1 +.names 51376 51339 51374 +11 1 +.names 51374 51375 +1 1 +.names 56706 51337 51376 +11 1 +.names 51381 51383 51377 +1- 1 +-1 1 +.names 51377 51378 +1 1 +.names 51289 51379 +1 1 +.names 51379 51380 +0 1 +.names 51380 2413 51381 +11 1 +.names 51375 51382 +0 1 +.names 51379 51382 51383 +11 1 +.names 51386 51389 51384 +1- 1 +-1 1 +.names 51384 51385 +1 1 +.names 21880 9703 51386 +11 1 +.names 51390 51339 51387 +1- 1 +-1 1 +.names 51387 51388 +1 1 +.names 51388 51389 +0 1 +.names 50780 51390 +0 1 +.names 51385 51391 +0 1 +.names 51391 51392 +1 1 +.names 51394 51395 57465 +1- 1 +-1 1 +.names 51392 51394 +0 1 +.names 51378 51395 +0 1 +.names 51398 51339 51396 +11 1 +.names 51396 51397 +1 1 +.names 56702 51337 51398 +11 1 +.names 51401 51404 57466 +1- 1 +-1 1 +.names 51410 51413 51400 +1- 1 +-1 1 +.names 51400 51401 +1 1 +.names 51407 51409 51402 +1- 1 +-1 1 +.names 51402 51403 +1 1 +.names 51403 51404 +0 1 +.names 51289 51405 +1 1 +.names 51405 51406 +0 1 +.names 51406 2413 51407 +11 1 +.names 51397 51408 +0 1 +.names 51405 51408 51409 +11 1 +.names 21866 9703 51410 +11 1 +.names 51414 51339 51411 +1- 1 +-1 1 +.names 51411 51412 +1 1 +.names 51412 51413 +0 1 +.names 50932 51414 +0 1 +.names 51417 51281 51415 +1- 1 +-1 1 +.names 51415 51416 +1 1 +.names 50833 51417 +0 1 +.names 51420 51421 51418 +1- 1 +-1 1 +.names 51418 51419 +1 1 +.names 1783 9694 51420 +11 1 +.names 51416 51421 +0 1 +.names 51424 51289 51422 +11 1 +.names 51422 51423 +1 1 +.names 56703 51281 51424 +11 1 +.names 51428 51430 51425 +1- 1 +-1 1 +.names 51425 51426 +1 1 +.names 51423 51427 +0 1 +.names 51292 51427 51428 +11 1 +.names 21885 51429 +0 1 +.names 9704 51429 51430 +11 1 +.names 51419 51432 57467 +1- 1 +-1 1 +.names 51426 51432 +0 1 +.names 9765 51433 +0 1 +.names 9767 51434 +0 1 +.names 22028 51435 +0 1 +.names 22036 51436 +0 1 +.names 22024 51437 +0 1 +.names 22032 51438 +0 1 +.names 22040 51439 +0 1 +.names 22052 51440 +0 1 +.names 10027 51441 +0 1 +.names 9769 51442 +0 1 +.names 22044 51443 +0 1 +.names 22048 51444 +0 1 +.names 10158 51445 +0 1 +.names 9771 51446 +0 1 +.names 22085 51447 +0 1 +.names 22081 51448 +0 1 +.names 22077 51449 +0 1 +.names 22073 51450 +0 1 +.names 22089 51451 +0 1 +.names 22101 51452 +0 1 +.names 10165 51453 +0 1 +.names 9775 51454 +0 1 +.names 22093 51455 +0 1 +.names 22097 51456 +0 1 +.names 10356 51457 +0 1 +.names 10358 51458 +0 1 +.names 10536 51459 +0 1 +.names 10360 51460 +0 1 +.names 22156 51461 +0 1 +.names 22164 51462 +0 1 +.names 22152 51463 +0 1 +.names 22148 51464 +0 1 +.names 22160 51465 +0 1 +.names 22168 51466 +0 1 +.names 10539 51467 +0 1 +.names 10362 51468 +0 1 +.names 22204 51469 +0 1 +.names 22200 51470 +0 1 +.names 22196 51471 +0 1 +.names 22192 51472 +0 1 +.names 22208 51473 +0 1 +.names 22220 51474 +0 1 +.names 10546 51475 +0 1 +.names 10366 51476 +0 1 +.names 22212 51477 +0 1 +.names 22216 51478 +0 1 +.names 51485 51487 51479 +1- 1 +-1 1 +.names 51479 51480 +1 1 +.names 14966 51481 +0 1 +.names 51489 51490 51482 +11 1 +.names 51482 51483 +1 1 +.names 51483 51484 +0 1 +.names 51481 51484 51485 +11 1 +.names 478 51486 +0 1 +.names 14966 51486 51487 +11 1 +.names 14958 51488 +0 1 +.names 303 51488 51489 +11 1 +.names 14959 51490 +0 1 +.names 51494 51495 51491 +1- 1 +-1 1 +.names 51491 51492 +1 1 +.names 51498 51499 51493 +1- 1 +-1 1 +.names 51493 51494 +1 1 +.names 51480 51495 +0 1 +.names 2413 51490 51496 +1- 1 +-1 1 +.names 51496 51497 +1 1 +.names 1783 14958 51498 +11 1 +.names 51497 51499 +0 1 +.names 51506 51507 51500 +1- 1 +-1 1 +.names 51500 51501 +1 1 +.names 14961 51502 +0 1 +.names 51508 51481 51503 +11 1 +.names 51503 51504 +1 1 +.names 51504 51505 +0 1 +.names 51502 51505 51506 +11 1 +.names 14961 47950 51507 +11 1 +.names 308 51488 51508 +11 1 +.names 51512 51513 51509 +1- 1 +-1 1 +.names 51509 51510 +1 1 +.names 51516 51517 51511 +1- 1 +-1 1 +.names 51511 51512 +1 1 +.names 51501 51513 +0 1 +.names 44504 51488 51514 +1- 1 +-1 1 +.names 51514 51515 +1 1 +.names 14966 483 51516 +11 1 +.names 51515 51517 +0 1 +.names 51521 51522 51518 +11 1 +.names 51518 51519 +1 1 +.names 14957 51520 +0 1 +.names 324 51520 51521 +11 1 +.names 14969 51522 +0 1 +.names 51526 51529 51523 +1- 1 +-1 1 +.names 51523 51524 +1 1 +.names 51536 51537 51525 +1- 1 +-1 1 +.names 51525 51526 +1 1 +.names 51532 51533 51527 +1- 1 +-1 1 +.names 51527 51528 +1 1 +.names 51528 51529 +0 1 +.names 14960 51530 +0 1 +.names 51519 51531 +0 1 +.names 51530 51531 51532 +11 1 +.names 14960 47898 51533 +11 1 +.names 44513 51520 51534 +1- 1 +-1 1 +.names 51534 51535 +1 1 +.names 14969 499 51536 +11 1 +.names 51535 51537 +0 1 +.names 51543 51545 51538 +1- 1 +-1 1 +.names 51538 51539 +1 1 +.names 51547 51490 51540 +11 1 +.names 51540 51541 +1 1 +.names 51541 51542 +0 1 +.names 51522 51542 51543 +11 1 +.names 485 51544 +0 1 +.names 14969 51544 51545 +11 1 +.names 14956 51546 +0 1 +.names 310 51546 51547 +11 1 +.names 48041 51490 51548 +1- 1 +-1 1 +.names 51548 51549 +1 1 +.names 51552 51553 51550 +1- 1 +-1 1 +.names 51550 51551 +1 1 +.names 1416 14956 51552 +11 1 +.names 51549 51553 +0 1 +.names 51551 51554 +0 1 +.names 51554 51555 +1 1 +.names 51558 51559 51556 +1- 1 +-1 1 +.names 51556 51557 +1 1 +.names 51555 51558 +0 1 +.names 51539 51559 +0 1 +.names 48067 51490 51560 +1- 1 +-1 1 +.names 51560 51561 +1 1 +.names 51564 51565 51562 +1- 1 +-1 1 +.names 51562 51563 +1 1 +.names 1417 14958 51564 +11 1 +.names 51561 51565 +0 1 +.names 51568 51490 51566 +11 1 +.names 51566 51567 +1 1 +.names 312 51488 51568 +11 1 +.names 51573 51575 51569 +1- 1 +-1 1 +.names 51569 51570 +1 1 +.names 14970 51571 +0 1 +.names 51567 51572 +0 1 +.names 51571 51572 51573 +11 1 +.names 487 51574 +0 1 +.names 14970 51574 51575 +11 1 +.names 51563 51578 51576 +1- 1 +-1 1 +.names 51576 51577 +1 1 +.names 51570 51578 +0 1 +.names 51584 51585 51579 +1- 1 +-1 1 +.names 51579 51580 +1 1 +.names 51586 51490 51581 +11 1 +.names 51581 51582 +1 1 +.names 51582 51583 +0 1 +.names 51522 51583 51584 +11 1 +.names 14969 49846 51585 +11 1 +.names 319 51546 51586 +11 1 +.names 48139 51490 51587 +1- 1 +-1 1 +.names 51587 51588 +1 1 +.names 51591 51592 51589 +1- 1 +-1 1 +.names 51589 51590 +1 1 +.names 1414 14956 51591 +11 1 +.names 51588 51592 +0 1 +.names 51590 51593 +0 1 +.names 51593 51594 +1 1 +.names 51597 51598 51595 +1- 1 +-1 1 +.names 51595 51596 +1 1 +.names 51594 51597 +0 1 +.names 51580 51598 +0 1 +.names 51601 51522 51599 +11 1 +.names 51599 51600 +1 1 +.names 332 51520 51601 +11 1 +.names 51605 51608 51602 +1- 1 +-1 1 +.names 51602 51603 +1 1 +.names 51614 51615 51604 +1- 1 +-1 1 +.names 51604 51605 +1 1 +.names 51610 51611 51606 +1- 1 +-1 1 +.names 51606 51607 +1 1 +.names 51607 51608 +0 1 +.names 51600 51609 +0 1 +.names 51530 51609 51610 +11 1 +.names 14960 48184 51611 +11 1 +.names 44531 51520 51612 +1- 1 +-1 1 +.names 51612 51613 +1 1 +.names 14969 507 51614 +11 1 +.names 51613 51615 +0 1 +.names 51621 51622 51616 +1- 1 +-1 1 +.names 51616 51617 +1 1 +.names 51623 51490 51618 +11 1 +.names 51618 51619 +1 1 +.names 51619 51620 +0 1 +.names 51481 51620 51621 +11 1 +.names 14966 49694 51622 +11 1 +.names 321 51488 51623 +11 1 +.names 51627 51628 51624 +1- 1 +-1 1 +.names 51624 51625 +1 1 +.names 51631 51632 51626 +1- 1 +-1 1 +.names 51626 51627 +1 1 +.names 51617 51628 +0 1 +.names 48235 51490 51629 +1- 1 +-1 1 +.names 51629 51630 +1 1 +.names 1418 14958 51631 +11 1 +.names 51630 51632 +0 1 +.names 51635 51636 51633 +11 1 +.names 51633 51634 +1 1 +.names 311 51520 51635 +11 1 +.names 14968 51636 +0 1 +.names 51640 51643 51637 +1- 1 +-1 1 +.names 51637 51638 +1 1 +.names 51649 51650 51639 +1- 1 +-1 1 +.names 51639 51640 +1 1 +.names 51645 51646 51641 +1- 1 +-1 1 +.names 51641 51642 +1 1 +.names 51642 51643 +0 1 +.names 51634 51644 +0 1 +.names 51530 51644 51645 +11 1 +.names 14960 48279 51646 +11 1 +.names 44581 51520 51647 +1- 1 +-1 1 +.names 51647 51648 +1 1 +.names 14968 486 51649 +11 1 +.names 51648 51650 +0 1 +.names 51656 51658 51651 +1- 1 +-1 1 +.names 51651 51652 +1 1 +.names 51659 51490 51653 +11 1 +.names 51653 51654 +1 1 +.names 51654 51655 +0 1 +.names 51481 51655 51656 +11 1 +.names 502 51657 +0 1 +.names 14966 51657 51658 +11 1 +.names 327 51546 51659 +11 1 +.names 51662 51490 51660 +1- 1 +-1 1 +.names 51660 51661 +1 1 +.names 1577 51662 +0 1 +.names 51665 51666 51663 +1- 1 +-1 1 +.names 51663 51664 +1 1 +.names 1420 14956 51665 +11 1 +.names 51661 51666 +0 1 +.names 51664 51667 +0 1 +.names 51667 51668 +1 1 +.names 51671 51672 51669 +1- 1 +-1 1 +.names 51669 51670 +1 1 +.names 51668 51671 +0 1 +.names 51652 51672 +0 1 +.names 51678 51680 51673 +1- 1 +-1 1 +.names 51673 51674 +1 1 +.names 51681 51571 51675 +11 1 +.names 51675 51676 +1 1 +.names 51676 51677 +0 1 +.names 51502 51677 51678 +11 1 +.names 1584 51679 +0 1 +.names 14961 51679 51680 +11 1 +.names 313 51546 51681 +11 1 +.names 51685 51686 51682 +1- 1 +-1 1 +.names 51682 51683 +1 1 +.names 51689 51690 51684 +1- 1 +-1 1 +.names 51684 51685 +1 1 +.names 51674 51686 +0 1 +.names 44599 51546 51687 +1- 1 +-1 1 +.names 51687 51688 +1 1 +.names 14970 488 51689 +11 1 +.names 51688 51690 +0 1 +.names 51693 51636 51691 +11 1 +.names 51691 51692 +1 1 +.names 326 51520 51693 +11 1 +.names 51697 51700 51694 +1- 1 +-1 1 +.names 51694 51695 +1 1 +.names 51704 51707 51696 +1- 1 +-1 1 +.names 51696 51697 +1 1 +.names 51702 51703 51698 +1- 1 +-1 1 +.names 51698 51699 +1 1 +.names 51699 51700 +0 1 +.names 51692 51701 +0 1 +.names 51502 51701 51702 +11 1 +.names 14961 48404 51703 +11 1 +.names 1422 14957 51704 +11 1 +.names 51708 51636 51705 +1- 1 +-1 1 +.names 51705 51706 +1 1 +.names 51706 51707 +0 1 +.names 501 51708 +0 1 +.names 51714 51715 51709 +1- 1 +-1 1 +.names 51709 51710 +1 1 +.names 51717 51522 51711 +11 1 +.names 51711 51712 +1 1 +.names 51712 51713 +0 1 +.names 51502 51713 51714 +11 1 +.names 14961 2413 51715 +11 1 +.names 14967 51716 +0 1 +.names 302 51716 51717 +11 1 +.names 51721 51722 51718 +1- 1 +-1 1 +.names 51718 51719 +1 1 +.names 51725 51726 51720 +1- 1 +-1 1 +.names 51720 51721 +1 1 +.names 51710 51722 +0 1 +.names 2413 51716 51723 +1- 1 +-1 1 +.names 51723 51724 +1 1 +.names 14969 477 51725 +11 1 +.names 51724 51726 +0 1 +.names 51732 51733 51727 +1- 1 +-1 1 +.names 51727 51728 +1 1 +.names 51734 51522 51729 +11 1 +.names 51729 51730 +1 1 +.names 51730 51731 +0 1 +.names 51502 51731 51732 +11 1 +.names 14961 48809 51733 +11 1 +.names 304 51546 51734 +11 1 +.names 51738 51739 51735 +1- 1 +-1 1 +.names 51735 51736 +1 1 +.names 51742 51743 51737 +1- 1 +-1 1 +.names 51737 51738 +1 1 +.names 51728 51739 +0 1 +.names 44617 51546 51740 +1- 1 +-1 1 +.names 51740 51741 +1 1 +.names 14969 479 51742 +11 1 +.names 51741 51743 +0 1 +.names 51749 51750 51744 +1- 1 +-1 1 +.names 51744 51745 +1 1 +.names 51751 51481 51746 +11 1 +.names 51746 51747 +1 1 +.names 51747 51748 +0 1 +.names 51716 51748 51749 +11 1 +.names 14967 44625 51750 +11 1 +.names 307 51530 51751 +11 1 +.names 51755 51756 51752 +1- 1 +-1 1 +.names 51752 51753 +1 1 +.names 51757 51760 51754 +1- 1 +-1 1 +.names 51754 51755 +1 1 +.names 51745 51756 +0 1 +.names 14966 482 51757 +11 1 +.names 48855 51530 51758 +1- 1 +-1 1 +.names 51758 51759 +1 1 +.names 51759 51760 +0 1 +.names 51763 51636 51761 +11 1 +.names 51761 51762 +1 1 +.names 309 51520 51763 +11 1 +.names 51767 51770 51764 +1- 1 +-1 1 +.names 51764 51765 +1 1 +.names 51776 51777 51766 +1- 1 +-1 1 +.names 51766 51767 +1 1 +.names 51772 51773 51768 +1- 1 +-1 1 +.names 51768 51769 +1 1 +.names 51769 51770 +0 1 +.names 51762 51771 +0 1 +.names 51530 51771 51772 +11 1 +.names 14960 48533 51773 +11 1 +.names 44633 51520 51774 +1- 1 +-1 1 +.names 51774 51775 +1 1 +.names 14968 484 51776 +11 1 +.names 51775 51777 +0 1 +.names 51783 51785 51778 +1- 1 +-1 1 +.names 51778 51779 +1 1 +.names 51786 51490 51780 +11 1 +.names 51780 51781 +1 1 +.names 51781 51782 +0 1 +.names 51571 51782 51783 +11 1 +.names 495 51784 +0 1 +.names 14970 51784 51785 +11 1 +.names 320 51546 51786 +11 1 +.names 48581 51490 51787 +1- 1 +-1 1 +.names 51787 51788 +1 1 +.names 51791 51792 51789 +1- 1 +-1 1 +.names 51789 51790 +1 1 +.names 1426 14956 51791 +11 1 +.names 51788 51792 +0 1 +.names 51790 51793 +0 1 +.names 51793 51794 +1 1 +.names 51797 51798 51795 +1- 1 +-1 1 +.names 51795 51796 +1 1 +.names 51794 51797 +0 1 +.names 51779 51798 +0 1 +.names 51804 51805 51799 +1- 1 +-1 1 +.names 51799 51800 +1 1 +.names 51806 51481 51801 +11 1 +.names 51801 51802 +1 1 +.names 51802 51803 +0 1 +.names 51502 51803 51804 +11 1 +.names 14961 48624 51805 +11 1 +.names 318 51716 51806 +11 1 +.names 51810 51811 51807 +1- 1 +-1 1 +.names 51807 51808 +1 1 +.names 51814 51815 51809 +1- 1 +-1 1 +.names 51809 51810 +1 1 +.names 51800 51811 +0 1 +.names 44651 51716 51812 +1- 1 +-1 1 +.names 51812 51813 +1 1 +.names 14966 493 51814 +11 1 +.names 51813 51815 +0 1 +.names 51821 51822 51816 +1- 1 +-1 1 +.names 51816 51817 +1 1 +.names 51823 51636 51818 +11 1 +.names 51818 51819 +1 1 +.names 51819 51820 +0 1 +.names 51716 51820 51821 +11 1 +.names 14967 44660 51822 +11 1 +.names 325 51530 51823 +11 1 +.names 51827 51828 51824 +1- 1 +-1 1 +.names 51824 51825 +1 1 +.names 51831 51832 51826 +1- 1 +-1 1 +.names 51826 51827 +1 1 +.names 51817 51828 +0 1 +.names 48674 51530 51829 +1- 1 +-1 1 +.names 51829 51830 +1 1 +.names 500 14968 51831 +11 1 +.names 51830 51832 +0 1 +.names 51838 51839 51833 +1- 1 +-1 1 +.names 51833 51834 +1 1 +.names 51840 51571 51835 +11 1 +.names 51835 51836 +1 1 +.names 51836 51837 +0 1 +.names 51530 51837 51838 +11 1 +.names 14960 48715 51839 +11 1 +.names 333 51716 51840 +11 1 +.names 51844 51845 51841 +1- 1 +-1 1 +.names 51841 51842 +1 1 +.names 51846 51849 51843 +1- 1 +-1 1 +.names 51843 51844 +1 1 +.names 51834 51845 +0 1 +.names 14970 508 51846 +11 1 +.names 44668 51716 51847 +1- 1 +-1 1 +.names 51847 51848 +1 1 +.names 51848 51849 +0 1 +.names 51855 51856 51850 +1- 1 +-1 1 +.names 51850 51851 +1 1 +.names 51857 51481 51852 +11 1 +.names 51852 51853 +1 1 +.names 51853 51854 +0 1 +.names 51716 51854 51855 +11 1 +.names 14967 44678 51856 +11 1 +.names 323 51490 51857 +11 1 +.names 51861 51862 51858 +1- 1 +-1 1 +.names 51858 51859 +1 1 +.names 51865 51866 51860 +1- 1 +-1 1 +.names 51860 51861 +1 1 +.names 51851 51862 +0 1 +.names 48768 51490 51863 +1- 1 +-1 1 +.names 51863 51864 +1 1 +.names 498 14966 51865 +11 1 +.names 51864 51866 +0 1 +.names 51872 51873 51867 +1- 1 +-1 1 +.names 51867 51868 +1 1 +.names 51874 51571 51869 +11 1 +.names 51869 51870 +1 1 +.names 51870 51871 +0 1 +.names 51488 51871 51872 +11 1 +.names 14958 44686 51873 +11 1 +.names 315 51502 51874 +11 1 +.names 51878 51879 51875 +1- 1 +-1 1 +.names 51875 51876 +1 1 +.names 51882 51883 51877 +1- 1 +-1 1 +.names 51877 51878 +1 1 +.names 51868 51879 +0 1 +.names 48905 51502 51880 +1- 1 +-1 1 +.names 51880 51881 +1 1 +.names 14970 490 51882 +11 1 +.names 51881 51883 +0 1 +.names 51886 51481 51884 +11 1 +.names 51884 51885 +1 1 +.names 316 51520 51886 +11 1 +.names 51890 51893 51887 +1- 1 +-1 1 +.names 51887 51888 +1 1 +.names 51896 51897 51889 +1- 1 +-1 1 +.names 51889 51890 +1 1 +.names 51899 51900 51891 +1- 1 +-1 1 +.names 51891 51892 +1 1 +.names 51892 51893 +0 1 +.names 44694 51520 51894 +1- 1 +-1 1 +.names 51894 51895 +1 1 +.names 14966 491 51896 +11 1 +.names 51895 51897 +0 1 +.names 51885 51898 +0 1 +.names 51530 51898 51899 +11 1 +.names 14960 48934 51900 +11 1 +.names 51906 51907 51901 +1- 1 +-1 1 +.names 51901 51902 +1 1 +.names 51908 51481 51903 +11 1 +.names 51903 51904 +1 1 +.names 51904 51905 +0 1 +.names 51488 51905 51906 +11 1 +.names 14958 44703 51907 +11 1 +.names 330 51530 51908 +11 1 +.names 51912 51913 51909 +1- 1 +-1 1 +.names 51909 51910 +1 1 +.names 51917 51918 51911 +1- 1 +-1 1 +.names 51911 51912 +1 1 +.names 51902 51913 +0 1 +.names 51916 51530 51914 +1- 1 +-1 1 +.names 51914 51915 +1 1 +.names 1638 51916 +0 1 +.names 14966 505 51917 +11 1 +.names 51915 51918 +0 1 +.names 51924 51925 51919 +1- 1 +-1 1 +.names 51919 51920 +1 1 +.names 51926 51636 51921 +11 1 +.names 51921 51922 +1 1 +.names 51922 51923 +0 1 +.names 51716 51923 51924 +11 1 +.names 14967 44720 51925 +11 1 +.names 328 51490 51926 +11 1 +.names 51930 51931 51927 +1- 1 +-1 1 +.names 51927 51928 +1 1 +.names 51934 51935 51929 +1- 1 +-1 1 +.names 51929 51930 +1 1 +.names 51920 51931 +0 1 +.names 49090 51490 51932 +1- 1 +-1 1 +.names 51932 51933 +1 1 +.names 14968 503 51934 +11 1 +.names 51933 51935 +0 1 +.names 51941 51942 51936 +1- 1 +-1 1 +.names 51936 51937 +1 1 +.names 51943 51636 51938 +11 1 +.names 51938 51939 +1 1 +.names 51939 51940 +0 1 +.names 51716 51940 51941 +11 1 +.names 14967 44711 51942 +11 1 +.names 314 51502 51943 +11 1 +.names 51947 51948 51944 +1- 1 +-1 1 +.names 51944 51945 +1 1 +.names 51951 51952 51946 +1- 1 +-1 1 +.names 51946 51947 +1 1 +.names 51937 51948 +0 1 +.names 49039 51502 51949 +1- 1 +-1 1 +.names 51949 51950 +1 1 +.names 14968 489 51951 +11 1 +.names 51950 51952 +0 1 +.names 51958 51959 51953 +1- 1 +-1 1 +.names 51953 51954 +1 1 +.names 51960 51522 51955 +11 1 +.names 51955 51956 +1 1 +.names 51956 51957 +0 1 +.names 51546 51957 51958 +11 1 +.names 14956 44729 51959 +11 1 +.names 329 51530 51960 +11 1 +.names 51964 51965 51961 +1- 1 +-1 1 +.names 51961 51962 +1 1 +.names 51968 51969 51963 +1- 1 +-1 1 +.names 51963 51964 +1 1 +.names 51954 51965 +0 1 +.names 49144 51530 51966 +1- 1 +-1 1 +.names 51966 51967 +1 1 +.names 14969 504 51968 +11 1 +.names 51967 51969 +0 1 +.names 51975 51976 51970 +1- 1 +-1 1 +.names 51970 51971 +1 1 +.names 51977 51571 51972 +11 1 +.names 51972 51973 +1 1 +.names 51973 51974 +0 1 +.names 51502 51974 51975 +11 1 +.names 14961 49186 51976 +11 1 +.names 305 51488 51977 +11 1 +.names 51981 51982 51978 +1- 1 +-1 1 +.names 51978 51979 +1 1 +.names 51985 51986 51980 +1- 1 +-1 1 +.names 51980 51981 +1 1 +.names 51971 51982 +0 1 +.names 44737 51488 51983 +1- 1 +-1 1 +.names 51983 51984 +1 1 +.names 14970 480 51985 +11 1 +.names 51984 51986 +0 1 +.names 51992 51993 51987 +1- 1 +-1 1 +.names 51987 51988 +1 1 +.names 51994 51571 51989 +11 1 +.names 51989 51990 +1 1 +.names 51990 51991 +0 1 +.names 51502 51991 51992 +11 1 +.names 14961 49242 51993 +11 1 +.names 306 51488 51994 +11 1 +.names 51998 51999 51995 +1- 1 +-1 1 +.names 51995 51996 +1 1 +.names 52000 52003 51997 +1- 1 +-1 1 +.names 51997 51998 +1 1 +.names 51988 51999 +0 1 +.names 1438 14958 52000 +11 1 +.names 52004 51571 52001 +1- 1 +-1 1 +.names 52001 52002 +1 1 +.names 52002 52003 +0 1 +.names 481 52004 +0 1 +.names 52010 52011 52005 +1- 1 +-1 1 +.names 52005 52006 +1 1 +.names 52012 51636 52007 +11 1 +.names 52007 52008 +1 1 +.names 52008 52009 +0 1 +.names 51546 52009 52010 +11 1 +.names 14956 44753 52011 +11 1 +.names 317 51502 52012 +11 1 +.names 52016 52017 52013 +1- 1 +-1 1 +.names 52013 52014 +1 1 +.names 52018 52021 52015 +1- 1 +-1 1 +.names 52015 52016 +1 1 +.names 52006 52017 +0 1 +.names 14968 492 52018 +11 1 +.names 49284 51502 52019 +1- 1 +-1 1 +.names 52019 52020 +1 1 +.names 52020 52021 +0 1 +.names 52027 52028 52022 +1- 1 +-1 1 +.names 52022 52023 +1 1 +.names 52029 51522 52024 +11 1 +.names 52024 52025 +1 1 +.names 52025 52026 +0 1 +.names 51488 52026 52027 +11 1 +.names 14958 44762 52028 +11 1 +.names 322 51530 52029 +11 1 +.names 52033 52034 52030 +1- 1 +-1 1 +.names 52030 52031 +1 1 +.names 52037 52038 52032 +1- 1 +-1 1 +.names 52032 52033 +1 1 +.names 52023 52034 +0 1 +.names 49328 51530 52035 +1- 1 +-1 1 +.names 52035 52036 +1 1 +.names 497 14969 52037 +11 1 +.names 52036 52038 +0 1 +.names 52041 51571 52039 +11 1 +.names 52039 52040 +1 1 +.names 331 51520 52041 +11 1 +.names 52045 52048 52042 +1- 1 +-1 1 +.names 52042 52043 +1 1 +.names 52054 52055 52044 +1- 1 +-1 1 +.names 52044 52045 +1 1 +.names 52050 52051 52046 +1- 1 +-1 1 +.names 52046 52047 +1 1 +.names 52047 52048 +0 1 +.names 52040 52049 +0 1 +.names 51530 52049 52050 +11 1 +.names 14960 49368 52051 +11 1 +.names 44771 51520 52052 +1- 1 +-1 1 +.names 52052 52053 +1 1 +.names 14970 506 52054 +11 1 +.names 52053 52055 +0 1 +.names 52062 52063 52056 +1- 1 +-1 1 +.names 52056 52057 +1 1 +.names 14989 52058 +0 1 +.names 52065 52066 52059 +11 1 +.names 52059 52060 +1 1 +.names 52060 52061 +0 1 +.names 52058 52061 52062 +11 1 +.names 14989 2413 52063 +11 1 +.names 14981 52064 +0 1 +.names 1783 52064 52065 +11 1 +.names 14982 52066 +0 1 +.names 52070 52071 52067 +1- 1 +-1 1 +.names 52067 52068 +1 1 +.names 52074 52075 52069 +1- 1 +-1 1 +.names 52069 52070 +1 1 +.names 52057 52071 +0 1 +.names 47982 52066 52072 +1- 1 +-1 1 +.names 52072 52073 +1 1 +.names 1783 14981 52074 +11 1 +.names 52073 52075 +0 1 +.names 52082 52083 52076 +1- 1 +-1 1 +.names 52076 52077 +1 1 +.names 14984 52078 +0 1 +.names 52084 52058 52079 +11 1 +.names 52079 52080 +1 1 +.names 52080 52081 +0 1 +.names 52078 52081 52082 +11 1 +.names 14984 3253 52083 +11 1 +.names 1692 52064 52084 +11 1 +.names 52088 52089 52085 +1- 1 +-1 1 +.names 52085 52086 +1 1 +.names 52092 52093 52087 +1- 1 +-1 1 +.names 52087 52088 +1 1 +.names 52077 52089 +0 1 +.names 47929 52064 52090 +1- 1 +-1 1 +.names 52090 52091 +1 1 +.names 14989 1543 52092 +11 1 +.names 52091 52093 +0 1 +.names 52097 52098 52094 +11 1 +.names 52094 52095 +1 1 +.names 14980 52096 +0 1 +.names 1695 52096 52097 +11 1 +.names 14992 52098 +0 1 +.names 52102 52105 52099 +1- 1 +-1 1 +.names 52099 52100 +1 1 +.names 52112 52113 52101 +1- 1 +-1 1 +.names 52101 52102 +1 1 +.names 52108 52109 52103 +1- 1 +-1 1 +.names 52103 52104 +1 1 +.names 52104 52105 +0 1 +.names 14983 52106 +0 1 +.names 52095 52107 +0 1 +.names 52106 52107 52108 +11 1 +.names 14983 47873 52109 +11 1 +.names 47900 52096 52110 +1- 1 +-1 1 +.names 52110 52111 +1 1 +.names 14992 1539 52112 +11 1 +.names 52111 52113 +0 1 +.names 52119 52120 52114 +1- 1 +-1 1 +.names 52114 52115 +1 1 +.names 52122 52066 52116 +11 1 +.names 52116 52117 +1 1 +.names 52117 52118 +0 1 +.names 52098 52118 52119 +11 1 +.names 14992 48044 52120 +11 1 +.names 14979 52121 +0 1 +.names 1701 52121 52122 +11 1 +.names 48026 52066 52123 +1- 1 +-1 1 +.names 52123 52124 +1 1 +.names 52127 52128 52125 +1- 1 +-1 1 +.names 52125 52126 +1 1 +.names 1550 14979 52127 +11 1 +.names 52124 52128 +0 1 +.names 52126 52129 +0 1 +.names 52129 52130 +1 1 +.names 52133 52134 52131 +1- 1 +-1 1 +.names 52131 52132 +1 1 +.names 52130 52133 +0 1 +.names 52115 52134 +0 1 +.names 5304 52066 52135 +1- 1 +-1 1 +.names 52135 52136 +1 1 +.names 52139 52140 52137 +1- 1 +-1 1 +.names 52137 52138 +1 1 +.names 1557 14981 52139 +11 1 +.names 52136 52140 +0 1 +.names 52143 52066 52141 +11 1 +.names 52141 52142 +1 1 +.names 1699 52064 52143 +11 1 +.names 52148 52149 52144 +1- 1 +-1 1 +.names 52144 52145 +1 1 +.names 14993 52146 +0 1 +.names 52142 52147 +0 1 +.names 52146 52147 52148 +11 1 +.names 14993 48083 52149 +11 1 +.names 52138 52152 52150 +1- 1 +-1 1 +.names 52150 52151 +1 1 +.names 52145 52152 +0 1 +.names 52158 52159 52153 +1- 1 +-1 1 +.names 52153 52154 +1 1 +.names 52160 52066 52155 +11 1 +.names 52155 52156 +1 1 +.names 52156 52157 +0 1 +.names 52098 52157 52158 +11 1 +.names 14992 48141 52159 +11 1 +.names 1689 52121 52160 +11 1 +.names 48137 52066 52161 +1- 1 +-1 1 +.names 52161 52162 +1 1 +.names 52165 52166 52163 +1- 1 +-1 1 +.names 52163 52164 +1 1 +.names 1558 14979 52165 +11 1 +.names 52162 52166 +0 1 +.names 52164 52167 +0 1 +.names 52167 52168 +1 1 +.names 52171 52172 52169 +1- 1 +-1 1 +.names 52169 52170 +1 1 +.names 52168 52171 +0 1 +.names 52154 52172 +0 1 +.names 52175 52098 52173 +11 1 +.names 52173 52174 +1 1 +.names 1685 52096 52175 +11 1 +.names 52179 52182 52176 +1- 1 +-1 1 +.names 52176 52177 +1 1 +.names 52188 52189 52178 +1- 1 +-1 1 +.names 52178 52179 +1 1 +.names 52184 52185 52180 +1- 1 +-1 1 +.names 52180 52181 +1 1 +.names 52181 52182 +0 1 +.names 52174 52183 +0 1 +.names 52106 52183 52184 +11 1 +.names 14983 2413 52185 +11 1 +.names 48178 52096 52186 +1- 1 +-1 1 +.names 52186 52187 +1 1 +.names 14992 1566 52188 +11 1 +.names 52187 52189 +0 1 +.names 52195 52196 52190 +1- 1 +-1 1 +.names 52190 52191 +1 1 +.names 52197 52066 52192 +11 1 +.names 52192 52193 +1 1 +.names 52193 52194 +0 1 +.names 52058 52194 52195 +11 1 +.names 14989 48230 52196 +11 1 +.names 1686 52064 52197 +11 1 +.names 52201 52202 52198 +1- 1 +-1 1 +.names 52198 52199 +1 1 +.names 52205 52206 52200 +1- 1 +-1 1 +.names 52200 52201 +1 1 +.names 52191 52202 +0 1 +.names 48239 52066 52203 +1- 1 +-1 1 +.names 52203 52204 +1 1 +.names 1571 14981 52205 +11 1 +.names 52204 52206 +0 1 +.names 52209 52210 52207 +11 1 +.names 52207 52208 +1 1 +.names 1700 52096 52209 +11 1 +.names 14991 52210 +0 1 +.names 52214 52217 52211 +1- 1 +-1 1 +.names 52211 52212 +1 1 +.names 52223 52224 52213 +1- 1 +-1 1 +.names 52213 52214 +1 1 +.names 52219 52220 52215 +1- 1 +-1 1 +.names 52215 52216 +1 1 +.names 52216 52217 +0 1 +.names 52208 52218 +0 1 +.names 52106 52218 52219 +11 1 +.names 14983 48282 52220 +11 1 +.names 48277 52096 52221 +1- 1 +-1 1 +.names 52221 52222 +1 1 +.names 14991 1575 52223 +11 1 +.names 52222 52224 +0 1 +.names 52230 52231 52225 +1- 1 +-1 1 +.names 52225 52226 +1 1 +.names 52232 52066 52227 +11 1 +.names 52227 52228 +1 1 +.names 52228 52229 +0 1 +.names 52058 52229 52230 +11 1 +.names 14989 48339 52231 +11 1 +.names 1703 52121 52232 +11 1 +.names 2413 52066 52233 +1- 1 +-1 1 +.names 52233 52234 +1 1 +.names 52237 52238 52235 +1- 1 +-1 1 +.names 52235 52236 +1 1 +.names 1579 14979 52237 +11 1 +.names 52234 52238 +0 1 +.names 52236 52239 +0 1 +.names 52239 52240 +1 1 +.names 52243 52244 52241 +1- 1 +-1 1 +.names 52241 52242 +1 1 +.names 52240 52243 +0 1 +.names 52226 52244 +0 1 +.names 52250 52252 52245 +1- 1 +-1 1 +.names 52245 52246 +1 1 +.names 52253 52146 52247 +11 1 +.names 52247 52248 +1 1 +.names 52248 52249 +0 1 +.names 52078 52249 52250 +11 1 +.names 1581 52251 +0 1 +.names 14984 52251 52252 +11 1 +.names 1675 52121 52253 +11 1 +.names 52257 52258 52254 +1- 1 +-1 1 +.names 52254 52255 +1 1 +.names 52261 52262 52256 +1- 1 +-1 1 +.names 52256 52257 +1 1 +.names 52246 52258 +0 1 +.names 48394 52121 52259 +1- 1 +-1 1 +.names 52259 52260 +1 1 +.names 14993 1583 52261 +11 1 +.names 52260 52262 +0 1 +.names 52265 52210 52263 +11 1 +.names 52263 52264 +1 1 +.names 1702 52096 52265 +11 1 +.names 52269 52272 52266 +1- 1 +-1 1 +.names 52266 52267 +1 1 +.names 52276 52279 52268 +1- 1 +-1 1 +.names 52268 52269 +1 1 +.names 52274 52275 52270 +1- 1 +-1 1 +.names 52270 52271 +1 1 +.names 52271 52272 +0 1 +.names 52264 52273 +0 1 +.names 52078 52273 52274 +11 1 +.names 14984 2413 52275 +11 1 +.names 1586 14980 52276 +11 1 +.names 48447 52210 52277 +1- 1 +-1 1 +.names 52277 52278 +1 1 +.names 52278 52279 +0 1 +.names 52285 52286 52280 +1- 1 +-1 1 +.names 52280 52281 +1 1 +.names 52288 52098 52282 +11 1 +.names 52282 52283 +1 1 +.names 52283 52284 +0 1 +.names 52078 52284 52285 +11 1 +.names 14984 48487 52286 +11 1 +.names 14990 52287 +0 1 +.names 1783 52287 52288 +11 1 +.names 52292 52293 52289 +1- 1 +-1 1 +.names 52289 52290 +1 1 +.names 52296 52297 52291 +1- 1 +-1 1 +.names 52291 52292 +1 1 +.names 52281 52293 +0 1 +.names 2413 52287 52294 +1- 1 +-1 1 +.names 52294 52295 +1 1 +.names 14992 1783 52296 +11 1 +.names 52295 52297 +0 1 +.names 52303 52304 52298 +1- 1 +-1 1 +.names 52298 52299 +1 1 +.names 52305 52098 52300 +11 1 +.names 52300 52301 +1 1 +.names 52301 52302 +0 1 +.names 52078 52302 52303 +11 1 +.names 14984 48794 52304 +11 1 +.names 1677 52121 52305 +11 1 +.names 52309 52310 52306 +1- 1 +-1 1 +.names 52306 52307 +1 1 +.names 52313 52314 52308 +1- 1 +-1 1 +.names 52308 52309 +1 1 +.names 52299 52310 +0 1 +.names 48798 52121 52311 +1- 1 +-1 1 +.names 52311 52312 +1 1 +.names 14992 1783 52313 +11 1 +.names 52312 52314 +0 1 +.names 52320 52321 52315 +1- 1 +-1 1 +.names 52315 52316 +1 1 +.names 52322 52058 52317 +11 1 +.names 52317 52318 +1 1 +.names 52318 52319 +0 1 +.names 52287 52319 52320 +11 1 +.names 14990 48853 52321 +11 1 +.names 1690 52106 52322 +11 1 +.names 52326 52327 52323 +1- 1 +-1 1 +.names 52323 52324 +1 1 +.names 52328 52331 52325 +1- 1 +-1 1 +.names 52325 52326 +1 1 +.names 52316 52327 +0 1 +.names 14989 1626 52328 +11 1 +.names 4848 52106 52329 +1- 1 +-1 1 +.names 52329 52330 +1 1 +.names 52330 52331 +0 1 +.names 52334 52210 52332 +11 1 +.names 52332 52333 +1 1 +.names 1683 52096 52334 +11 1 +.names 52338 52341 52335 +1- 1 +-1 1 +.names 52335 52336 +1 1 +.names 52347 52348 52337 +1- 1 +-1 1 +.names 52337 52338 +1 1 +.names 52343 52344 52339 +1- 1 +-1 1 +.names 52339 52340 +1 1 +.names 52340 52341 +0 1 +.names 52333 52342 +0 1 +.names 52106 52342 52343 +11 1 +.names 14983 48531 52344 +11 1 +.names 48537 52096 52345 +1- 1 +-1 1 +.names 52345 52346 +1 1 +.names 14991 1594 52347 +11 1 +.names 52346 52348 +0 1 +.names 52354 52355 52349 +1- 1 +-1 1 +.names 52349 52350 +1 1 +.names 52356 52066 52351 +11 1 +.names 52351 52352 +1 1 +.names 52352 52353 +0 1 +.names 52146 52353 52354 +11 1 +.names 14993 48585 52355 +11 1 +.names 1688 52121 52356 +11 1 +.names 48577 52066 52357 +1- 1 +-1 1 +.names 52357 52358 +1 1 +.names 52361 52362 52359 +1- 1 +-1 1 +.names 52359 52360 +1 1 +.names 1597 14979 52361 +11 1 +.names 52358 52362 +0 1 +.names 52360 52363 +0 1 +.names 52363 52364 +1 1 +.names 52367 52368 52365 +1- 1 +-1 1 +.names 52365 52366 +1 1 +.names 52364 52367 +0 1 +.names 52350 52368 +0 1 +.names 52374 52375 52369 +1- 1 +-1 1 +.names 52369 52370 +1 1 +.names 52376 52058 52371 +11 1 +.names 52371 52372 +1 1 +.names 52372 52373 +0 1 +.names 52078 52373 52374 +11 1 +.names 14984 48620 52375 +11 1 +.names 1687 52287 52376 +11 1 +.names 52380 52381 52377 +1- 1 +-1 1 +.names 52377 52378 +1 1 +.names 52384 52385 52379 +1- 1 +-1 1 +.names 52379 52380 +1 1 +.names 52370 52381 +0 1 +.names 48622 52287 52382 +1- 1 +-1 1 +.names 52382 52383 +1 1 +.names 14989 1605 52384 +11 1 +.names 52383 52385 +0 1 +.names 52391 52392 52386 +1- 1 +-1 1 +.names 52386 52387 +1 1 +.names 52393 52210 52388 +11 1 +.names 52388 52389 +1 1 +.names 52389 52390 +0 1 +.names 52287 52390 52391 +11 1 +.names 14990 48678 52392 +11 1 +.names 1679 52106 52393 +11 1 +.names 52397 52398 52394 +1- 1 +-1 1 +.names 52394 52395 +1 1 +.names 52401 52402 52396 +1- 1 +-1 1 +.names 52396 52397 +1 1 +.names 52387 52398 +0 1 +.names 2413 52106 52399 +1- 1 +-1 1 +.names 52399 52400 +1 1 +.names 1607 14991 52401 +11 1 +.names 52400 52402 +0 1 +.names 52408 52409 52403 +1- 1 +-1 1 +.names 52403 52404 +1 1 +.names 52410 52146 52405 +11 1 +.names 52405 52406 +1 1 +.names 52406 52407 +0 1 +.names 52106 52407 52408 +11 1 +.names 14983 2413 52409 +11 1 +.names 896 52287 52410 +11 1 +.names 52414 52415 52411 +1- 1 +-1 1 +.names 52411 52412 +1 1 +.names 52416 52419 52413 +1- 1 +-1 1 +.names 52413 52414 +1 1 +.names 52404 52415 +0 1 +.names 14993 1610 52416 +11 1 +.names 48709 52287 52417 +1- 1 +-1 1 +.names 52417 52418 +1 1 +.names 52418 52419 +0 1 +.names 52425 52426 52420 +1- 1 +-1 1 +.names 52420 52421 +1 1 +.names 52427 52058 52422 +11 1 +.names 52422 52423 +1 1 +.names 52423 52424 +0 1 +.names 52287 52424 52425 +11 1 +.names 14990 48751 52426 +11 1 +.names 1696 52066 52427 +11 1 +.names 52431 52432 52428 +1- 1 +-1 1 +.names 52428 52429 +1 1 +.names 52435 52436 52430 +1- 1 +-1 1 +.names 52430 52431 +1 1 +.names 52421 52432 +0 1 +.names 48749 52066 52433 +1- 1 +-1 1 +.names 52433 52434 +1 1 +.names 1617 14989 52435 +11 1 +.names 52434 52436 +0 1 +.names 52442 52443 52437 +1- 1 +-1 1 +.names 52437 52438 +1 1 +.names 52444 52146 52439 +11 1 +.names 52439 52440 +1 1 +.names 52440 52441 +0 1 +.names 52064 52441 52442 +11 1 +.names 14981 48892 52443 +11 1 +.names 1698 52078 52444 +11 1 +.names 52448 52449 52445 +1- 1 +-1 1 +.names 52445 52446 +1 1 +.names 52452 52453 52447 +1- 1 +-1 1 +.names 52447 52448 +1 1 +.names 52438 52449 +0 1 +.names 48895 52078 52450 +1- 1 +-1 1 +.names 52450 52451 +1 1 +.names 14993 1627 52452 +11 1 +.names 52451 52453 +0 1 +.names 52456 52058 52454 +11 1 +.names 52454 52455 +1 1 +.names 1697 52096 52456 +11 1 +.names 52460 52463 52457 +1- 1 +-1 1 +.names 52457 52458 +1 1 +.names 52466 52467 52459 +1- 1 +-1 1 +.names 52459 52460 +1 1 +.names 52469 52470 52461 +1- 1 +-1 1 +.names 52461 52462 +1 1 +.names 52462 52463 +0 1 +.names 48940 52096 52464 +1- 1 +-1 1 +.names 52464 52465 +1 1 +.names 14989 1632 52466 +11 1 +.names 52465 52467 +0 1 +.names 52455 52468 +0 1 +.names 52106 52468 52469 +11 1 +.names 14983 48951 52470 +11 1 +.names 52476 52477 52471 +1- 1 +-1 1 +.names 52471 52472 +1 1 +.names 52478 52058 52473 +11 1 +.names 52473 52474 +1 1 +.names 52474 52475 +0 1 +.names 52064 52475 52476 +11 1 +.names 14981 48995 52477 +11 1 +.names 1682 52106 52478 +11 1 +.names 52482 52483 52479 +1- 1 +-1 1 +.names 52479 52480 +1 1 +.names 52486 52487 52481 +1- 1 +-1 1 +.names 52481 52482 +1 1 +.names 52472 52483 +0 1 +.names 2413 52106 52484 +1- 1 +-1 1 +.names 52484 52485 +1 1 +.names 14989 1636 52486 +11 1 +.names 52485 52487 +0 1 +.names 52493 52494 52488 +1- 1 +-1 1 +.names 52488 52489 +1 1 +.names 52495 52210 52490 +11 1 +.names 52490 52491 +1 1 +.names 52491 52492 +0 1 +.names 52287 52492 52493 +11 1 +.names 14990 49100 52494 +11 1 +.names 1694 52066 52495 +11 1 +.names 52499 52500 52496 +1- 1 +-1 1 +.names 52496 52497 +1 1 +.names 52503 52504 52498 +1- 1 +-1 1 +.names 52498 52499 +1 1 +.names 52489 52500 +0 1 +.names 2413 52066 52501 +1- 1 +-1 1 +.names 52501 52502 +1 1 +.names 14991 1645 52503 +11 1 +.names 52502 52504 +0 1 +.names 52510 52511 52505 +1- 1 +-1 1 +.names 52505 52506 +1 1 +.names 52512 52210 52507 +11 1 +.names 52507 52508 +1 1 +.names 52508 52509 +0 1 +.names 52287 52509 52510 +11 1 +.names 14990 49037 52511 +11 1 +.names 1681 52078 52512 +11 1 +.names 52516 52517 52513 +1- 1 +-1 1 +.names 52513 52514 +1 1 +.names 52520 52521 52515 +1- 1 +-1 1 +.names 52515 52516 +1 1 +.names 52506 52517 +0 1 +.names 49050 52078 52518 +1- 1 +-1 1 +.names 52518 52519 +1 1 +.names 14991 1643 52520 +11 1 +.names 52519 52521 +0 1 +.names 52527 52528 52522 +1- 1 +-1 1 +.names 52522 52523 +1 1 +.names 52529 52098 52524 +11 1 +.names 52524 52525 +1 1 +.names 52525 52526 +0 1 +.names 52121 52526 52527 +11 1 +.names 14979 49142 52528 +11 1 +.names 1693 52106 52529 +11 1 +.names 52533 52534 52530 +1- 1 +-1 1 +.names 52530 52531 +1 1 +.names 52537 52538 52532 +1- 1 +-1 1 +.names 52532 52533 +1 1 +.names 52523 52534 +0 1 +.names 2413 52106 52535 +1- 1 +-1 1 +.names 52535 52536 +1 1 +.names 14992 1651 52537 +11 1 +.names 52536 52538 +0 1 +.names 52544 52545 52539 +1- 1 +-1 1 +.names 52539 52540 +1 1 +.names 52546 52146 52541 +11 1 +.names 52541 52542 +1 1 +.names 52542 52543 +0 1 +.names 52078 52543 52544 +11 1 +.names 14984 49175 52545 +11 1 +.names 1678 52064 52546 +11 1 +.names 52550 52551 52547 +1- 1 +-1 1 +.names 52547 52548 +1 1 +.names 52554 52555 52549 +1- 1 +-1 1 +.names 52549 52550 +1 1 +.names 52540 52551 +0 1 +.names 49179 52064 52552 +1- 1 +-1 1 +.names 52552 52553 +1 1 +.names 14993 1656 52554 +11 1 +.names 52553 52555 +0 1 +.names 52561 52562 52556 +1- 1 +-1 1 +.names 52556 52557 +1 1 +.names 52563 52146 52558 +11 1 +.names 52558 52559 +1 1 +.names 52559 52560 +0 1 +.names 52078 52560 52561 +11 1 +.names 14984 49221 52562 +11 1 +.names 1691 52064 52563 +11 1 +.names 52567 52568 52564 +1- 1 +-1 1 +.names 52564 52565 +1 1 +.names 52569 52572 52566 +1- 1 +-1 1 +.names 52566 52567 +1 1 +.names 52557 52568 +0 1 +.names 1659 14981 52569 +11 1 +.names 49225 52146 52570 +1- 1 +-1 1 +.names 52570 52571 +1 1 +.names 52571 52572 +0 1 +.names 52578 52579 52573 +1- 1 +-1 1 +.names 52573 52574 +1 1 +.names 52580 52210 52575 +11 1 +.names 52575 52576 +1 1 +.names 52576 52577 +0 1 +.names 52121 52577 52578 +11 1 +.names 14979 49273 52579 +11 1 +.names 1676 52078 52580 +11 1 +.names 52584 52585 52581 +1- 1 +-1 1 +.names 52581 52582 +1 1 +.names 52586 52589 52583 +1- 1 +-1 1 +.names 52583 52584 +1 1 +.names 52574 52585 +0 1 +.names 14991 1665 52586 +11 1 +.names 49269 52078 52587 +1- 1 +-1 1 +.names 52587 52588 +1 1 +.names 52588 52589 +0 1 +.names 52595 52596 52590 +1- 1 +-1 1 +.names 52590 52591 +1 1 +.names 52597 52098 52592 +11 1 +.names 52592 52593 +1 1 +.names 52593 52594 +0 1 +.names 52064 52594 52595 +11 1 +.names 14981 49326 52596 +11 1 +.names 1680 52106 52597 +11 1 +.names 52601 52602 52598 +1- 1 +-1 1 +.names 52598 52599 +1 1 +.names 52605 52606 52600 +1- 1 +-1 1 +.names 52600 52601 +1 1 +.names 52591 52602 +0 1 +.names 49324 52106 52603 +1- 1 +-1 1 +.names 52603 52604 +1 1 +.names 1670 14992 52605 +11 1 +.names 52604 52606 +0 1 +.names 52609 52146 52607 +11 1 +.names 52607 52608 +1 1 +.names 1684 52096 52609 +11 1 +.names 52613 52616 52610 +1- 1 +-1 1 +.names 52610 52611 +1 1 +.names 52622 52623 52612 +1- 1 +-1 1 +.names 52612 52613 +1 1 +.names 52618 52619 52614 +1- 1 +-1 1 +.names 52614 52615 +1 1 +.names 52615 52616 +0 1 +.names 52608 52617 +0 1 +.names 52106 52617 52618 +11 1 +.names 14983 2413 52619 +11 1 +.names 49366 52096 52620 +1- 1 +-1 1 +.names 52620 52621 +1 1 +.names 14993 1671 52622 +11 1 +.names 52621 52623 +0 1 +.names 52630 52631 52624 +1- 1 +-1 1 +.names 52624 52625 +1 1 +.names 15012 52626 +0 1 +.names 52633 52634 52627 +11 1 +.names 52627 52628 +1 1 +.names 52628 52629 +0 1 +.names 52626 52629 52630 +11 1 +.names 15012 2413 52631 +11 1 +.names 15004 52632 +0 1 +.names 1203 52632 52633 +11 1 +.names 15005 52634 +0 1 +.names 52638 52639 52635 +1- 1 +-1 1 +.names 52635 52636 +1 1 +.names 52642 52643 52637 +1- 1 +-1 1 +.names 52637 52638 +1 1 +.names 52625 52639 +0 1 +.names 2413 52634 52640 +1- 1 +-1 1 +.names 52640 52641 +1 1 +.names 1211 15004 52642 +11 1 +.names 52641 52643 +0 1 +.names 52650 52651 52644 +1- 1 +-1 1 +.names 52644 52645 +1 1 +.names 15007 52646 +0 1 +.names 52652 52626 52647 +11 1 +.names 52647 52648 +1 1 +.names 52648 52649 +0 1 +.names 52646 52649 52650 +11 1 +.names 15007 20669 52651 +11 1 +.names 1208 52632 52652 +11 1 +.names 52656 52657 52653 +1- 1 +-1 1 +.names 52653 52654 +1 1 +.names 52660 52661 52655 +1- 1 +-1 1 +.names 52655 52656 +1 1 +.names 52645 52657 +0 1 +.names 50874 52632 52658 +1- 1 +-1 1 +.names 52658 52659 +1 1 +.names 15012 1194 52660 +11 1 +.names 52659 52661 +0 1 +.names 52665 52666 52662 +11 1 +.names 52662 52663 +1 1 +.names 15003 52664 +0 1 +.names 1783 52664 52665 +11 1 +.names 15015 52666 +0 1 +.names 52670 52673 52667 +1- 1 +-1 1 +.names 52667 52668 +1 1 +.names 52680 52681 52669 +1- 1 +-1 1 +.names 52669 52670 +1 1 +.names 52676 52677 52671 +1- 1 +-1 1 +.names 52671 52672 +1 1 +.names 52672 52673 +0 1 +.names 15006 52674 +0 1 +.names 52663 52675 +0 1 +.names 52674 52675 52676 +11 1 +.names 15006 20664 52677 +11 1 +.names 2413 52664 52678 +1- 1 +-1 1 +.names 52678 52679 +1 1 +.names 15015 1191 52680 +11 1 +.names 52679 52681 +0 1 +.names 52687 52688 52682 +1- 1 +-1 1 +.names 52682 52683 +1 1 +.names 52690 52634 52684 +11 1 +.names 52684 52685 +1 1 +.names 52685 52686 +0 1 +.names 52666 52686 52687 +11 1 +.names 15015 20803 52688 +11 1 +.names 15002 52689 +0 1 +.names 1783 52689 52690 +11 1 +.names 20695 52634 52691 +1- 1 +-1 1 +.names 52691 52692 +1 1 +.names 52695 52696 52693 +1- 1 +-1 1 +.names 52693 52694 +1 1 +.names 1783 15002 52695 +11 1 +.names 52692 52696 +0 1 +.names 52694 52697 +0 1 +.names 52697 52698 +1 1 +.names 52701 52702 52699 +1- 1 +-1 1 +.names 52699 52700 +1 1 +.names 52698 52701 +0 1 +.names 52683 52702 +0 1 +.names 20641 52634 52703 +1- 1 +-1 1 +.names 52703 52704 +1 1 +.names 52707 52708 52705 +1- 1 +-1 1 +.names 52705 52706 +1 1 +.names 1783 15004 52707 +11 1 +.names 52704 52708 +0 1 +.names 52711 52634 52709 +11 1 +.names 52709 52710 +1 1 +.names 1783 52632 52711 +11 1 +.names 52716 52717 52712 +1- 1 +-1 1 +.names 52712 52713 +1 1 +.names 15016 52714 +0 1 +.names 52710 52715 +0 1 +.names 52714 52715 52716 +11 1 +.names 15016 20749 52717 +11 1 +.names 52706 52720 52718 +1- 1 +-1 1 +.names 52718 52719 +1 1 +.names 52713 52720 +0 1 +.names 52726 52727 52721 +1- 1 +-1 1 +.names 52721 52722 +1 1 +.names 52728 52634 52723 +11 1 +.names 52723 52724 +1 1 +.names 52724 52725 +0 1 +.names 52666 52725 52726 +11 1 +.names 15015 20709 52727 +11 1 +.names 1783 52689 52728 +11 1 +.names 20601 52634 52729 +1- 1 +-1 1 +.names 52729 52730 +1 1 +.names 52733 52734 52731 +1- 1 +-1 1 +.names 52731 52732 +1 1 +.names 1783 15002 52733 +11 1 +.names 52730 52734 +0 1 +.names 52732 52735 +0 1 +.names 52735 52736 +1 1 +.names 52739 52740 52737 +1- 1 +-1 1 +.names 52737 52738 +1 1 +.names 52736 52739 +0 1 +.names 52722 52740 +0 1 +.names 52743 52666 52741 +11 1 +.names 52741 52742 +1 1 +.names 1783 52664 52743 +11 1 +.names 52747 52750 52744 +1- 1 +-1 1 +.names 52744 52745 +1 1 +.names 52757 52758 52746 +1- 1 +-1 1 +.names 52746 52747 +1 1 +.names 52752 52754 52748 +1- 1 +-1 1 +.names 52748 52749 +1 1 +.names 52749 52750 +0 1 +.names 52742 52751 +0 1 +.names 52674 52751 52752 +11 1 +.names 1734 52753 +0 1 +.names 15006 52753 52754 +11 1 +.names 2413 52664 52755 +1- 1 +-1 1 +.names 52755 52756 +1 1 +.names 15015 1735 52757 +11 1 +.names 52756 52758 +0 1 +.names 52764 52765 52759 +1- 1 +-1 1 +.names 52759 52760 +1 1 +.names 52766 52634 52761 +11 1 +.names 52761 52762 +1 1 +.names 52762 52763 +0 1 +.names 52626 52763 52764 +11 1 +.names 15012 20737 52765 +11 1 +.names 1783 52632 52766 +11 1 +.names 52770 52771 52767 +1- 1 +-1 1 +.names 52767 52768 +1 1 +.names 52774 52775 52769 +1- 1 +-1 1 +.names 52769 52770 +1 1 +.names 52760 52771 +0 1 +.names 20629 52634 52772 +1- 1 +-1 1 +.names 52772 52773 +1 1 +.names 1783 15004 52774 +11 1 +.names 52773 52775 +0 1 +.names 52778 52779 52776 +11 1 +.names 52776 52777 +1 1 +.names 1783 52664 52778 +11 1 +.names 15014 52779 +0 1 +.names 52783 52786 52780 +1- 1 +-1 1 +.names 52780 52781 +1 1 +.names 52792 52793 52782 +1- 1 +-1 1 +.names 52782 52783 +1 1 +.names 52788 52789 52784 +1- 1 +-1 1 +.names 52784 52785 +1 1 +.names 52785 52786 +0 1 +.names 52777 52787 +0 1 +.names 52674 52787 52788 +11 1 +.names 15006 20660 52789 +11 1 +.names 2413 52664 52790 +1- 1 +-1 1 +.names 52790 52791 +1 1 +.names 15014 1189 52792 +11 1 +.names 52791 52793 +0 1 +.names 52799 52800 52794 +1- 1 +-1 1 +.names 52794 52795 +1 1 +.names 52801 52634 52796 +11 1 +.names 52796 52797 +1 1 +.names 52797 52798 +0 1 +.names 52626 52798 52799 +11 1 +.names 15012 20773 52800 +11 1 +.names 1783 52689 52801 +11 1 +.names 20665 52634 52802 +1- 1 +-1 1 +.names 52802 52803 +1 1 +.names 52806 52807 52804 +1- 1 +-1 1 +.names 52804 52805 +1 1 +.names 1783 15002 52806 +11 1 +.names 52803 52807 +0 1 +.names 52805 52808 +0 1 +.names 52808 52809 +1 1 +.names 52812 52813 52810 +1- 1 +-1 1 +.names 52810 52811 +1 1 +.names 52809 52812 +0 1 +.names 52795 52813 +0 1 +.names 52819 52820 52814 +1- 1 +-1 1 +.names 52814 52815 +1 1 +.names 52821 52714 52816 +11 1 +.names 52816 52817 +1 1 +.names 52817 52818 +0 1 +.names 52646 52818 52819 +11 1 +.names 15007 20644 52820 +11 1 +.names 1783 52689 52821 +11 1 +.names 52825 52826 52822 +1- 1 +-1 1 +.names 52822 52823 +1 1 +.names 52829 52830 52824 +1- 1 +-1 1 +.names 52824 52825 +1 1 +.names 52815 52826 +0 1 +.names 2413 52689 52827 +1- 1 +-1 1 +.names 52827 52828 +1 1 +.names 15016 1187 52829 +11 1 +.names 52828 52830 +0 1 +.names 52833 52779 52831 +11 1 +.names 52831 52832 +1 1 +.names 1783 52664 52833 +11 1 +.names 52837 52840 52834 +1- 1 +-1 1 +.names 52834 52835 +1 1 +.names 52844 52847 52836 +1- 1 +-1 1 +.names 52836 52837 +1 1 +.names 52842 52843 52838 +1- 1 +-1 1 +.names 52838 52839 +1 1 +.names 52839 52840 +0 1 +.names 52832 52841 +0 1 +.names 52646 52841 52842 +11 1 +.names 15007 20605 52843 +11 1 +.names 1783 15003 52844 +11 1 +.names 20713 52779 52845 +1- 1 +-1 1 +.names 52845 52846 +1 1 +.names 52846 52847 +0 1 +.names 52853 52854 52848 +1- 1 +-1 1 +.names 52848 52849 +1 1 +.names 52856 52666 52850 +11 1 +.names 52850 52851 +1 1 +.names 52851 52852 +0 1 +.names 52646 52852 52853 +11 1 +.names 15007 2413 52854 +11 1 +.names 15013 52855 +0 1 +.names 1205 52855 52856 +11 1 +.names 52860 52861 52857 +1- 1 +-1 1 +.names 52857 52858 +1 1 +.names 52864 52865 52859 +1- 1 +-1 1 +.names 52859 52860 +1 1 +.names 52849 52861 +0 1 +.names 50826 52855 52862 +1- 1 +-1 1 +.names 52862 52863 +1 1 +.names 15015 1783 52864 +11 1 +.names 52863 52865 +0 1 +.names 52871 52872 52866 +1- 1 +-1 1 +.names 52866 52867 +1 1 +.names 52873 52666 52868 +11 1 +.names 52868 52869 +1 1 +.names 52869 52870 +0 1 +.names 52646 52870 52871 +11 1 +.names 15007 20606 52872 +11 1 +.names 1202 52689 52873 +11 1 +.names 52877 52878 52874 +1- 1 +-1 1 +.names 52874 52875 +1 1 +.names 52881 52882 52876 +1- 1 +-1 1 +.names 52876 52877 +1 1 +.names 52867 52878 +0 1 +.names 50812 52689 52879 +1- 1 +-1 1 +.names 52879 52880 +1 1 +.names 15015 1177 52881 +11 1 +.names 52880 52882 +0 1 +.names 52888 52889 52883 +1- 1 +-1 1 +.names 52883 52884 +1 1 +.names 52890 52626 52885 +11 1 +.names 52885 52886 +1 1 +.names 52886 52887 +0 1 +.names 52855 52887 52888 +11 1 +.names 15013 50787 52889 +11 1 +.names 1209 52674 52890 +11 1 +.names 52894 52895 52891 +1- 1 +-1 1 +.names 52891 52892 +1 1 +.names 52896 52899 52893 +1- 1 +-1 1 +.names 52893 52894 +1 1 +.names 52884 52895 +0 1 +.names 15012 1183 52896 +11 1 +.names 20632 52674 52897 +1- 1 +-1 1 +.names 52897 52898 +1 1 +.names 52898 52899 +0 1 +.names 52902 52779 52900 +11 1 +.names 52900 52901 +1 1 +.names 1206 52664 52902 +11 1 +.names 52906 52909 52903 +1- 1 +-1 1 +.names 52903 52904 +1 1 +.names 52915 52916 52905 +1- 1 +-1 1 +.names 52905 52906 +1 1 +.names 52911 52912 52907 +1- 1 +-1 1 +.names 52907 52908 +1 1 +.names 52908 52909 +0 1 +.names 52901 52910 +0 1 +.names 52674 52910 52911 +11 1 +.names 15006 20661 52912 +11 1 +.names 50875 52664 52913 +1- 1 +-1 1 +.names 52913 52914 +1 1 +.names 15014 1190 52915 +11 1 +.names 52914 52916 +0 1 +.names 52922 52923 52917 +1- 1 +-1 1 +.names 52917 52918 +1 1 +.names 52924 52634 52919 +11 1 +.names 52919 52920 +1 1 +.names 52920 52921 +0 1 +.names 52714 52921 52922 +11 1 +.names 15016 20781 52923 +11 1 +.names 1783 52689 52924 +11 1 +.names 20673 52634 52925 +1- 1 +-1 1 +.names 52925 52926 +1 1 +.names 52929 52930 52927 +1- 1 +-1 1 +.names 52927 52928 +1 1 +.names 1783 15002 52929 +11 1 +.names 52926 52930 +0 1 +.names 52928 52931 +0 1 +.names 52931 52932 +1 1 +.names 52935 52936 52933 +1- 1 +-1 1 +.names 52933 52934 +1 1 +.names 52932 52935 +0 1 +.names 52918 52936 +0 1 +.names 52942 52943 52937 +1- 1 +-1 1 +.names 52937 52938 +1 1 +.names 52944 52626 52939 +11 1 +.names 52939 52940 +1 1 +.names 52940 52941 +0 1 +.names 52646 52941 52942 +11 1 +.names 15007 20640 52943 +11 1 +.names 1783 52855 52944 +11 1 +.names 52948 52949 52945 +1- 1 +-1 1 +.names 52945 52946 +1 1 +.names 52952 52953 52947 +1- 1 +-1 1 +.names 52947 52948 +1 1 +.names 52938 52949 +0 1 +.names 2413 52855 52950 +1- 1 +-1 1 +.names 52950 52951 +1 1 +.names 15012 1185 52952 +11 1 +.names 52951 52953 +0 1 +.names 52959 52960 52954 +1- 1 +-1 1 +.names 52954 52955 +1 1 +.names 52961 52779 52956 +11 1 +.names 52956 52957 +1 1 +.names 52957 52958 +0 1 +.names 52855 52958 52959 +11 1 +.names 15013 2413 52960 +11 1 +.names 1783 52674 52961 +11 1 +.names 52965 52966 52962 +1- 1 +-1 1 +.names 52962 52963 +1 1 +.names 52969 52970 52964 +1- 1 +-1 1 +.names 52964 52965 +1 1 +.names 52955 52966 +0 1 +.names 20696 52674 52967 +1- 1 +-1 1 +.names 52967 52968 +1 1 +.names 1201 15014 52969 +11 1 +.names 52968 52970 +0 1 +.names 52976 52978 52971 +1- 1 +-1 1 +.names 52971 52972 +1 1 +.names 52979 52714 52973 +11 1 +.names 52973 52974 +1 1 +.names 52974 52975 +0 1 +.names 52674 52975 52976 +11 1 +.names 1736 52977 +0 1 +.names 15006 52977 52978 +11 1 +.names 1783 52855 52979 +11 1 +.names 52983 52984 52980 +1- 1 +-1 1 +.names 52980 52981 +1 1 +.names 52985 52988 52982 +1- 1 +-1 1 +.names 52982 52983 +1 1 +.names 52972 52984 +0 1 +.names 15016 1737 52985 +11 1 +.names 2413 52855 52986 +1- 1 +-1 1 +.names 52986 52987 +1 1 +.names 52987 52988 +0 1 +.names 52994 52995 52989 +1- 1 +-1 1 +.names 52989 52990 +1 1 +.names 52996 52626 52991 +11 1 +.names 52991 52992 +1 1 +.names 52992 52993 +0 1 +.names 52855 52993 52994 +11 1 +.names 15013 2413 52995 +11 1 +.names 1783 52634 52996 +11 1 +.names 53000 53001 52997 +1- 1 +-1 1 +.names 52997 52998 +1 1 +.names 53004 53005 52999 +1- 1 +-1 1 +.names 52999 53000 +1 1 +.names 52990 53001 +0 1 +.names 20668 52634 53002 +1- 1 +-1 1 +.names 53002 53003 +1 1 +.names 1193 15012 53004 +11 1 +.names 53003 53005 +0 1 +.names 53011 53012 53006 +1- 1 +-1 1 +.names 53006 53007 +1 1 +.names 53013 52714 53008 +11 1 +.names 53008 53009 +1 1 +.names 53009 53010 +0 1 +.names 52632 53010 53011 +11 1 +.names 15004 2413 53012 +11 1 +.names 1783 52646 53013 +11 1 +.names 53017 53018 53014 +1- 1 +-1 1 +.names 53014 53015 +1 1 +.names 53021 53022 53016 +1- 1 +-1 1 +.names 53016 53017 +1 1 +.names 53007 53018 +0 1 +.names 20633 52646 53019 +1- 1 +-1 1 +.names 53019 53020 +1 1 +.names 15016 1184 53021 +11 1 +.names 53020 53022 +0 1 +.names 53025 52626 53023 +11 1 +.names 53023 53024 +1 1 +.names 763 52664 53025 +11 1 +.names 53029 53032 53026 +1- 1 +-1 1 +.names 53026 53027 +1 1 +.names 53035 53036 53028 +1- 1 +-1 1 +.names 53028 53029 +1 1 +.names 53038 53039 53030 +1- 1 +-1 1 +.names 53030 53031 +1 1 +.names 53031 53032 +0 1 +.names 3087 52664 53033 +1- 1 +-1 1 +.names 53033 53034 +1 1 +.names 15012 1198 53035 +11 1 +.names 53034 53036 +0 1 +.names 53024 53037 +0 1 +.names 52674 53037 53038 +11 1 +.names 15006 20691 53039 +11 1 +.names 53045 53046 53040 +1- 1 +-1 1 +.names 53040 53041 +1 1 +.names 53047 52626 53042 +11 1 +.names 53042 53043 +1 1 +.names 53043 53044 +0 1 +.names 52632 53044 53045 +11 1 +.names 15004 2413 53046 +11 1 +.names 1783 52674 53047 +11 1 +.names 53051 53052 53048 +1- 1 +-1 1 +.names 53048 53049 +1 1 +.names 53055 53056 53050 +1- 1 +-1 1 +.names 53050 53051 +1 1 +.names 53041 53052 +0 1 +.names 20678 52674 53053 +1- 1 +-1 1 +.names 53053 53054 +1 1 +.names 15012 1197 53055 +11 1 +.names 53054 53056 +0 1 +.names 53062 53063 53057 +1- 1 +-1 1 +.names 53057 53058 +1 1 +.names 53064 52779 53059 +11 1 +.names 53059 53060 +1 1 +.names 53060 53061 +0 1 +.names 52855 53061 53062 +11 1 +.names 15013 2413 53063 +11 1 +.names 1783 52634 53064 +11 1 +.names 53068 53069 53065 +1- 1 +-1 1 +.names 53065 53066 +1 1 +.names 53072 53073 53067 +1- 1 +-1 1 +.names 53067 53068 +1 1 +.names 53058 53069 +0 1 +.names 20692 52634 53070 +1- 1 +-1 1 +.names 53070 53071 +1 1 +.names 15014 1199 53072 +11 1 +.names 53071 53073 +0 1 +.names 53079 53080 53074 +1- 1 +-1 1 +.names 53074 53075 +1 1 +.names 53081 52779 53076 +11 1 +.names 53076 53077 +1 1 +.names 53077 53078 +0 1 +.names 52855 53078 53079 +11 1 +.names 15013 2413 53080 +11 1 +.names 1783 52646 53081 +11 1 +.names 53085 53086 53082 +1- 1 +-1 1 +.names 53082 53083 +1 1 +.names 53089 53090 53084 +1- 1 +-1 1 +.names 53084 53085 +1 1 +.names 53075 53086 +0 1 +.names 20614 52646 53087 +1- 1 +-1 1 +.names 53087 53088 +1 1 +.names 15014 1179 53089 +11 1 +.names 53088 53090 +0 1 +.names 53096 53097 53091 +1- 1 +-1 1 +.names 53091 53092 +1 1 +.names 53098 52666 53093 +11 1 +.names 53093 53094 +1 1 +.names 53094 53095 +0 1 +.names 52689 53095 53096 +11 1 +.names 15002 2413 53097 +11 1 +.names 1783 52674 53098 +11 1 +.names 53102 53103 53099 +1- 1 +-1 1 +.names 53099 53100 +1 1 +.names 53106 53107 53101 +1- 1 +-1 1 +.names 53101 53102 +1 1 +.names 53092 53103 +0 1 +.names 20618 52674 53104 +1- 1 +-1 1 +.names 53104 53105 +1 1 +.names 15015 1181 53106 +11 1 +.names 53105 53107 +0 1 +.names 53113 53114 53108 +1- 1 +-1 1 +.names 53108 53109 +1 1 +.names 53115 52714 53110 +11 1 +.names 53110 53111 +1 1 +.names 53111 53112 +0 1 +.names 52646 53112 53113 +11 1 +.names 15007 20645 53114 +11 1 +.names 1204 52632 53115 +11 1 +.names 53119 53120 53116 +1- 1 +-1 1 +.names 53116 53117 +1 1 +.names 53123 53124 53118 +1- 1 +-1 1 +.names 53118 53119 +1 1 +.names 53109 53120 +0 1 +.names 50719 52632 53121 +1- 1 +-1 1 +.names 53121 53122 +1 1 +.names 15016 1188 53123 +11 1 +.names 53122 53124 +0 1 +.names 53130 53131 53125 +1- 1 +-1 1 +.names 53125 53126 +1 1 +.names 53132 52714 53127 +11 1 +.names 53127 53128 +1 1 +.names 53128 53129 +0 1 +.names 52646 53129 53130 +11 1 +.names 15007 20672 53131 +11 1 +.names 1207 52632 53132 +11 1 +.names 53136 53137 53133 +1- 1 +-1 1 +.names 53133 53134 +1 1 +.names 53138 53141 53135 +1- 1 +-1 1 +.names 53135 53136 +1 1 +.names 53126 53137 +0 1 +.names 1215 15004 53138 +11 1 +.names 20780 52714 53139 +1- 1 +-1 1 +.names 53139 53140 +1 1 +.names 53140 53141 +0 1 +.names 53147 53149 53142 +1- 1 +-1 1 +.names 53142 53143 +1 1 +.names 53150 52779 53144 +11 1 +.names 53144 53145 +1 1 +.names 53145 53146 +0 1 +.names 52689 53146 53147 +11 1 +.names 762 53148 +0 1 +.names 15002 53148 53149 +11 1 +.names 764 52646 53150 +11 1 +.names 53154 53155 53151 +1- 1 +-1 1 +.names 53151 53152 +1 1 +.names 53156 53159 53153 +1- 1 +-1 1 +.names 53153 53154 +1 1 +.names 53143 53155 +0 1 +.names 15014 1175 53156 +11 1 +.names 20602 52646 53157 +1- 1 +-1 1 +.names 53157 53158 +1 1 +.names 53158 53159 +0 1 +.names 53165 53166 53160 +1- 1 +-1 1 +.names 53160 53161 +1 1 +.names 53167 52666 53162 +11 1 +.names 53162 53163 +1 1 +.names 53163 53164 +0 1 +.names 52632 53164 53165 +11 1 +.names 15004 2413 53166 +11 1 +.names 1783 52674 53167 +11 1 +.names 53171 53172 53168 +1- 1 +-1 1 +.names 53168 53169 +1 1 +.names 53175 53176 53170 +1- 1 +-1 1 +.names 53170 53171 +1 1 +.names 53161 53172 +0 1 +.names 20617 52674 53173 +1- 1 +-1 1 +.names 53173 53174 +1 1 +.names 1180 15015 53175 +11 1 +.names 53174 53176 +0 1 +.names 53179 52714 53177 +11 1 +.names 53177 53178 +1 1 +.names 1783 52664 53179 +11 1 +.names 53183 53186 53180 +1- 1 +-1 1 +.names 53180 53181 +1 1 +.names 53192 53193 53182 +1- 1 +-1 1 +.names 53182 53183 +1 1 +.names 53188 53189 53184 +1- 1 +-1 1 +.names 53184 53185 +1 1 +.names 53185 53186 +0 1 +.names 53178 53187 +0 1 +.names 52674 53187 53188 +11 1 +.names 15006 20613 53189 +11 1 +.names 2413 52664 53190 +1- 1 +-1 1 +.names 53190 53191 +1 1 +.names 15016 1178 53192 +11 1 +.names 53191 53193 +0 1 +.names 53200 53202 53194 +1- 1 +-1 1 +.names 53194 53195 +1 1 +.names 15035 53196 +0 1 +.names 53204 53205 53197 +11 1 +.names 53197 53198 +1 1 +.names 53198 53199 +0 1 +.names 53196 53199 53200 +11 1 +.names 899 53201 +0 1 +.names 15035 53201 53202 +11 1 +.names 15027 53203 +0 1 +.names 998 53203 53204 +11 1 +.names 15028 53205 +0 1 +.names 53209 53210 53206 +1- 1 +-1 1 +.names 53206 53207 +1 1 +.names 53214 53215 53208 +1- 1 +-1 1 +.names 53208 53209 +1 1 +.names 53195 53210 +0 1 +.names 53213 53205 53211 +1- 1 +-1 1 +.names 53211 53212 +1 1 +.names 904 53213 +0 1 +.names 1548 15027 53214 +11 1 +.names 53212 53215 +0 1 +.names 53222 53224 53216 +1- 1 +-1 1 +.names 53216 53217 +1 1 +.names 15030 53218 +0 1 +.names 53225 53196 53219 +11 1 +.names 53219 53220 +1 1 +.names 53220 53221 +0 1 +.names 53218 53221 53222 +11 1 +.names 1111 53223 +0 1 +.names 15030 53223 53224 +11 1 +.names 1010 53203 53225 +11 1 +.names 53229 53230 53226 +1- 1 +-1 1 +.names 53226 53227 +1 1 +.names 53233 53234 53228 +1- 1 +-1 1 +.names 53228 53229 +1 1 +.names 53217 53230 +0 1 +.names 47949 53203 53231 +1- 1 +-1 1 +.names 53231 53232 +1 1 +.names 15035 1138 53233 +11 1 +.names 53232 53234 +0 1 +.names 53238 53239 53235 +11 1 +.names 53235 53236 +1 1 +.names 15026 53237 +0 1 +.names 1034 53237 53238 +11 1 +.names 15038 53239 +0 1 +.names 53243 53246 53240 +1- 1 +-1 1 +.names 53240 53241 +1 1 +.names 53254 53255 53242 +1- 1 +-1 1 +.names 53242 53243 +1 1 +.names 53249 53251 53244 +1- 1 +-1 1 +.names 53244 53245 +1 1 +.names 53245 53246 +0 1 +.names 15029 53247 +0 1 +.names 53236 53248 +0 1 +.names 53247 53248 53249 +11 1 +.names 1104 53250 +0 1 +.names 15029 53250 53251 +11 1 +.names 47887 53237 53252 +1- 1 +-1 1 +.names 53252 53253 +1 1 +.names 15038 1131 53254 +11 1 +.names 53253 53255 +0 1 +.names 53261 53263 53256 +1- 1 +-1 1 +.names 53256 53257 +1 1 +.names 53265 53205 53258 +11 1 +.names 53258 53259 +1 1 +.names 53259 53260 +0 1 +.names 53239 53260 53261 +11 1 +.names 1143 53262 +0 1 +.names 15038 53262 53263 +11 1 +.names 15025 53264 +0 1 +.names 1019 53264 53265 +11 1 +.names 53268 53205 53266 +1- 1 +-1 1 +.names 53266 53267 +1 1 +.names 1116 53268 +0 1 +.names 53271 53272 53269 +1- 1 +-1 1 +.names 53269 53270 +1 1 +.names 1551 15025 53271 +11 1 +.names 53267 53272 +0 1 +.names 53270 53273 +0 1 +.names 53273 53274 +1 1 +.names 53277 53278 53275 +1- 1 +-1 1 +.names 53275 53276 +1 1 +.names 53274 53277 +0 1 +.names 53257 53278 +0 1 +.names 53281 53205 53279 +1- 1 +-1 1 +.names 53279 53280 +1 1 +.names 1117 53281 +0 1 +.names 53284 53285 53282 +1- 1 +-1 1 +.names 53282 53283 +1 1 +.names 1555 15027 53284 +11 1 +.names 53280 53285 +0 1 +.names 53288 53205 53286 +11 1 +.names 53286 53287 +1 1 +.names 1018 53203 53288 +11 1 +.names 53293 53295 53289 +1- 1 +-1 1 +.names 53289 53290 +1 1 +.names 15039 53291 +0 1 +.names 53287 53292 +0 1 +.names 53291 53292 53293 +11 1 +.names 1144 53294 +0 1 +.names 15039 53294 53295 +11 1 +.names 53283 53298 53296 +1- 1 +-1 1 +.names 53296 53297 +1 1 +.names 53290 53298 +0 1 +.names 53304 53306 53299 +1- 1 +-1 1 +.names 53299 53300 +1 1 +.names 53307 53205 53301 +11 1 +.names 53301 53302 +1 1 +.names 53302 53303 +0 1 +.names 53239 53303 53304 +11 1 +.names 1121 53305 +0 1 +.names 15038 53305 53306 +11 1 +.names 1029 53264 53307 +11 1 +.names 53310 53205 53308 +1- 1 +-1 1 +.names 53308 53309 +1 1 +.names 1094 53310 +0 1 +.names 53313 53314 53311 +1- 1 +-1 1 +.names 53311 53312 +1 1 +.names 1559 15025 53313 +11 1 +.names 53309 53314 +0 1 +.names 53312 53315 +0 1 +.names 53315 53316 +1 1 +.names 53319 53320 53317 +1- 1 +-1 1 +.names 53317 53318 +1 1 +.names 53316 53319 +0 1 +.names 53300 53320 +0 1 +.names 53323 53239 53321 +11 1 +.names 53321 53322 +1 1 +.names 1036 53237 53323 +11 1 +.names 53327 53330 53324 +1- 1 +-1 1 +.names 53324 53325 +1 1 +.names 53337 53338 53326 +1- 1 +-1 1 +.names 53326 53327 +1 1 +.names 53332 53334 53328 +1- 1 +-1 1 +.names 53328 53329 +1 1 +.names 53329 53330 +0 1 +.names 53322 53331 +0 1 +.names 53247 53331 53332 +11 1 +.names 1101 53333 +0 1 +.names 15029 53333 53334 +11 1 +.names 48180 53237 53335 +1- 1 +-1 1 +.names 53335 53336 +1 1 +.names 15038 1128 53337 +11 1 +.names 53336 53338 +0 1 +.names 53344 53346 53339 +1- 1 +-1 1 +.names 53339 53340 +1 1 +.names 53347 53205 53341 +11 1 +.names 53341 53342 +1 1 +.names 53342 53343 +0 1 +.names 53196 53343 53344 +11 1 +.names 1122 53345 +0 1 +.names 15035 53345 53346 +11 1 +.names 1042 53203 53347 +11 1 +.names 53351 53352 53348 +1- 1 +-1 1 +.names 53348 53349 +1 1 +.names 53356 53357 53350 +1- 1 +-1 1 +.names 53350 53351 +1 1 +.names 53340 53352 +0 1 +.names 53355 53205 53353 +1- 1 +-1 1 +.names 53353 53354 +1 1 +.names 1095 53355 +0 1 +.names 1567 15027 53356 +11 1 +.names 53354 53357 +0 1 +.names 53360 53361 53358 +11 1 +.names 53358 53359 +1 1 +.names 1016 53237 53360 +11 1 +.names 15037 53361 +0 1 +.names 53365 53368 53362 +1- 1 +-1 1 +.names 53362 53363 +1 1 +.names 53375 53376 53364 +1- 1 +-1 1 +.names 53364 53365 +1 1 +.names 53370 53372 53366 +1- 1 +-1 1 +.names 53366 53367 +1 1 +.names 53367 53368 +0 1 +.names 53359 53369 +0 1 +.names 53247 53369 53370 +11 1 +.names 1118 53371 +0 1 +.names 15029 53371 53372 +11 1 +.names 48284 53237 53373 +1- 1 +-1 1 +.names 53373 53374 +1 1 +.names 15037 1145 53375 +11 1 +.names 53374 53376 +0 1 +.names 53382 53384 53377 +1- 1 +-1 1 +.names 53377 53378 +1 1 +.names 53385 53205 53379 +11 1 +.names 53379 53380 +1 1 +.names 53380 53381 +0 1 +.names 53196 53381 53382 +11 1 +.names 1125 53383 +0 1 +.names 15035 53383 53384 +11 1 +.names 1037 53264 53385 +11 1 +.names 53388 53205 53386 +1- 1 +-1 1 +.names 53386 53387 +1 1 +.names 1098 53388 +0 1 +.names 53391 53392 53389 +1- 1 +-1 1 +.names 53389 53390 +1 1 +.names 1576 15025 53391 +11 1 +.names 53387 53392 +0 1 +.names 53390 53393 +0 1 +.names 53393 53394 +1 1 +.names 53397 53398 53395 +1- 1 +-1 1 +.names 53395 53396 +1 1 +.names 53394 53397 +0 1 +.names 53378 53398 +0 1 +.names 53404 53406 53399 +1- 1 +-1 1 +.names 53399 53400 +1 1 +.names 53407 53291 53401 +11 1 +.names 53401 53402 +1 1 +.names 53402 53403 +0 1 +.names 53218 53403 53404 +11 1 +.names 1115 53405 +0 1 +.names 15030 53405 53406 +11 1 +.names 1011 53264 53407 +11 1 +.names 53411 53412 53408 +1- 1 +-1 1 +.names 53408 53409 +1 1 +.names 53415 53416 53410 +1- 1 +-1 1 +.names 53410 53411 +1 1 +.names 53400 53412 +0 1 +.names 48353 53264 53413 +1- 1 +-1 1 +.names 53413 53414 +1 1 +.names 15039 1142 53415 +11 1 +.names 53414 53416 +0 1 +.names 53419 53361 53417 +11 1 +.names 53417 53418 +1 1 +.names 1039 53237 53419 +11 1 +.names 53423 53426 53420 +1- 1 +-1 1 +.names 53420 53421 +1 1 +.names 53431 53434 53422 +1- 1 +-1 1 +.names 53422 53423 +1 1 +.names 53428 53430 53424 +1- 1 +-1 1 +.names 53424 53425 +1 1 +.names 53425 53426 +0 1 +.names 53418 53427 +0 1 +.names 53218 53427 53428 +11 1 +.names 1107 53429 +0 1 +.names 15030 53429 53430 +11 1 +.names 1587 15026 53431 +11 1 +.names 53435 53361 53432 +1- 1 +-1 1 +.names 53432 53433 +1 1 +.names 53433 53434 +0 1 +.names 1134 53435 +0 1 +.names 53441 53443 53436 +1- 1 +-1 1 +.names 53436 53437 +1 1 +.names 53445 53239 53438 +11 1 +.names 53438 53439 +1 1 +.names 53439 53440 +0 1 +.names 53218 53440 53441 +11 1 +.names 903 53442 +0 1 +.names 15030 53442 53443 +11 1 +.names 15036 53444 +0 1 +.names 1006 53444 53445 +11 1 +.names 53449 53450 53446 +1- 1 +-1 1 +.names 53446 53447 +1 1 +.names 53453 53454 53448 +1- 1 +-1 1 +.names 53448 53449 +1 1 +.names 53437 53450 +0 1 +.names 48482 53444 53451 +1- 1 +-1 1 +.names 53451 53452 +1 1 +.names 15038 898 53453 +11 1 +.names 53452 53454 +0 1 +.names 53460 53462 53455 +1- 1 +-1 1 +.names 53455 53456 +1 1 +.names 53463 53239 53457 +11 1 +.names 53457 53458 +1 1 +.names 53458 53459 +0 1 +.names 53218 53459 53460 +11 1 +.names 905 53461 +0 1 +.names 15030 53461 53462 +11 1 +.names 1008 53264 53463 +11 1 +.names 53467 53468 53464 +1- 1 +-1 1 +.names 53464 53465 +1 1 +.names 53471 53472 53466 +1- 1 +-1 1 +.names 53466 53467 +1 1 +.names 53456 53468 +0 1 +.names 48800 53264 53469 +1- 1 +-1 1 +.names 53469 53470 +1 1 +.names 15038 900 53471 +11 1 +.names 53470 53472 +0 1 +.names 53478 53479 53473 +1- 1 +-1 1 +.names 53473 53474 +1 1 +.names 53480 53196 53475 +11 1 +.names 53475 53476 +1 1 +.names 53476 53477 +0 1 +.names 53444 53477 53478 +11 1 +.names 15036 48857 53479 +11 1 +.names 1021 53247 53480 +11 1 +.names 53484 53485 53481 +1- 1 +-1 1 +.names 53481 53482 +1 1 +.names 53486 53489 53483 +1- 1 +-1 1 +.names 53483 53484 +1 1 +.names 53474 53485 +0 1 +.names 15035 1139 53486 +11 1 +.names 53490 53247 53487 +1- 1 +-1 1 +.names 53487 53488 +1 1 +.names 53488 53489 +0 1 +.names 1112 53490 +0 1 +.names 53493 53361 53491 +11 1 +.names 53491 53492 +1 1 +.names 1005 53237 53493 +11 1 +.names 53497 53500 53494 +1- 1 +-1 1 +.names 53494 53495 +1 1 +.names 53507 53508 53496 +1- 1 +-1 1 +.names 53496 53497 +1 1 +.names 53502 53504 53498 +1- 1 +-1 1 +.names 53498 53499 +1 1 +.names 53499 53500 +0 1 +.names 53492 53501 +0 1 +.names 53247 53501 53502 +11 1 +.names 1113 53503 +0 1 +.names 15029 53503 53504 +11 1 +.names 48529 53237 53505 +1- 1 +-1 1 +.names 53505 53506 +1 1 +.names 15037 1140 53507 +11 1 +.names 53506 53508 +0 1 +.names 53514 53516 53509 +1- 1 +-1 1 +.names 53509 53510 +1 1 +.names 53517 53205 53511 +11 1 +.names 53511 53512 +1 1 +.names 53512 53513 +0 1 +.names 53291 53513 53514 +11 1 +.names 1126 53515 +0 1 +.names 15039 53515 53516 +11 1 +.names 1033 53264 53517 +11 1 +.names 53520 53205 53518 +1- 1 +-1 1 +.names 53518 53519 +1 1 +.names 1099 53520 +0 1 +.names 53523 53524 53521 +1- 1 +-1 1 +.names 53521 53522 +1 1 +.names 1599 15025 53523 +11 1 +.names 53519 53524 +0 1 +.names 53522 53525 +0 1 +.names 53525 53526 +1 1 +.names 53529 53530 53527 +1- 1 +-1 1 +.names 53527 53528 +1 1 +.names 53526 53529 +0 1 +.names 53510 53530 +0 1 +.names 53536 53538 53531 +1- 1 +-1 1 +.names 53531 53532 +1 1 +.names 53539 53196 53533 +11 1 +.names 53533 53534 +1 1 +.names 53534 53535 +0 1 +.names 53218 53535 53536 +11 1 +.names 1106 53537 +0 1 +.names 15030 53537 53538 +11 1 +.names 1043 53444 53539 +11 1 +.names 53543 53544 53540 +1- 1 +-1 1 +.names 53540 53541 +1 1 +.names 53547 53548 53542 +1- 1 +-1 1 +.names 53542 53543 +1 1 +.names 53532 53544 +0 1 +.names 48627 53444 53545 +1- 1 +-1 1 +.names 53545 53546 +1 1 +.names 15035 1133 53547 +11 1 +.names 53546 53548 +0 1 +.names 53554 53555 53549 +1- 1 +-1 1 +.names 53549 53550 +1 1 +.names 53556 53361 53551 +11 1 +.names 53551 53552 +1 1 +.names 53552 53553 +0 1 +.names 53444 53553 53554 +11 1 +.names 15036 48670 53555 +11 1 +.names 1032 53247 53556 +11 1 +.names 53560 53561 53557 +1- 1 +-1 1 +.names 53557 53558 +1 1 +.names 53565 53566 53559 +1- 1 +-1 1 +.names 53559 53560 +1 1 +.names 53550 53561 +0 1 +.names 53564 53247 53562 +1- 1 +-1 1 +.names 53562 53563 +1 1 +.names 1102 53564 +0 1 +.names 1129 15037 53565 +11 1 +.names 53563 53566 +0 1 +.names 53572 53574 53567 +1- 1 +-1 1 +.names 53567 53568 +1 1 +.names 53575 53291 53569 +11 1 +.names 53569 53570 +1 1 +.names 53570 53571 +0 1 +.names 53247 53571 53572 +11 1 +.names 1093 53573 +0 1 +.names 15029 53573 53574 +11 1 +.names 1041 53444 53575 +11 1 +.names 53579 53580 53576 +1- 1 +-1 1 +.names 53576 53577 +1 1 +.names 53581 53584 53578 +1- 1 +-1 1 +.names 53578 53579 +1 1 +.names 53568 53580 +0 1 +.names 15039 1120 53581 +11 1 +.names 48705 53444 53582 +1- 1 +-1 1 +.names 53582 53583 +1 1 +.names 53583 53584 +0 1 +.names 53590 53591 53585 +1- 1 +-1 1 +.names 53585 53586 +1 1 +.names 53592 53196 53587 +11 1 +.names 53587 53588 +1 1 +.names 53588 53589 +0 1 +.names 53444 53589 53590 +11 1 +.names 15036 48761 53591 +11 1 +.names 1040 53205 53592 +11 1 +.names 53596 53597 53593 +1- 1 +-1 1 +.names 53593 53594 +1 1 +.names 53601 53602 53595 +1- 1 +-1 1 +.names 53595 53596 +1 1 +.names 53586 53597 +0 1 +.names 53600 53205 53598 +1- 1 +-1 1 +.names 53598 53599 +1 1 +.names 1092 53600 +0 1 +.names 1119 15035 53601 +11 1 +.names 53599 53602 +0 1 +.names 53608 53609 53603 +1- 1 +-1 1 +.names 53603 53604 +1 1 +.names 53610 53291 53605 +11 1 +.names 53605 53606 +1 1 +.names 53606 53607 +0 1 +.names 53203 53607 53608 +11 1 +.names 15027 48903 53609 +11 1 +.names 1001 53218 53610 +11 1 +.names 53614 53615 53611 +1- 1 +-1 1 +.names 53611 53612 +1 1 +.names 53619 53620 53613 +1- 1 +-1 1 +.names 53613 53614 +1 1 +.names 53604 53615 +0 1 +.names 53618 53218 53616 +1- 1 +-1 1 +.names 53616 53617 +1 1 +.names 1097 53618 +0 1 +.names 15039 1124 53619 +11 1 +.names 53617 53620 +0 1 +.names 53623 53196 53621 +11 1 +.names 53621 53622 +1 1 +.names 1013 53237 53623 +11 1 +.names 53627 53630 53624 +1- 1 +-1 1 +.names 53624 53625 +1 1 +.names 53633 53634 53626 +1- 1 +-1 1 +.names 53626 53627 +1 1 +.names 53636 53638 53628 +1- 1 +-1 1 +.names 53628 53629 +1 1 +.names 53629 53630 +0 1 +.names 48949 53237 53631 +1- 1 +-1 1 +.names 53631 53632 +1 1 +.names 15035 1136 53633 +11 1 +.names 53632 53634 +0 1 +.names 53622 53635 +0 1 +.names 53247 53635 53636 +11 1 +.names 1109 53637 +0 1 +.names 15029 53637 53638 +11 1 +.names 53644 53645 53639 +1- 1 +-1 1 +.names 53639 53640 +1 1 +.names 53646 53196 53641 +11 1 +.names 53641 53642 +1 1 +.names 53642 53643 +0 1 +.names 53203 53643 53644 +11 1 +.names 15027 48970 53645 +11 1 +.names 1028 53247 53646 +11 1 +.names 53650 53651 53647 +1- 1 +-1 1 +.names 53647 53648 +1 1 +.names 53655 53656 53649 +1- 1 +-1 1 +.names 53649 53650 +1 1 +.names 53640 53651 +0 1 +.names 53654 53247 53652 +1- 1 +-1 1 +.names 53652 53653 +1 1 +.names 1105 53654 +0 1 +.names 15035 1132 53655 +11 1 +.names 53653 53656 +0 1 +.names 53662 53663 53657 +1- 1 +-1 1 +.names 53657 53658 +1 1 +.names 53664 53361 53659 +11 1 +.names 53659 53660 +1 1 +.names 53660 53661 +0 1 +.names 53444 53661 53662 +11 1 +.names 15036 49103 53663 +11 1 +.names 1038 53205 53664 +11 1 +.names 53668 53669 53665 +1- 1 +-1 1 +.names 53665 53666 +1 1 +.names 53673 53674 53667 +1- 1 +-1 1 +.names 53667 53668 +1 1 +.names 53658 53669 +0 1 +.names 53672 53205 53670 +1- 1 +-1 1 +.names 53670 53671 +1 1 +.names 1108 53672 +0 1 +.names 15037 1135 53673 +11 1 +.names 53671 53674 +0 1 +.names 53680 53681 53675 +1- 1 +-1 1 +.names 53675 53676 +1 1 +.names 53682 53361 53677 +11 1 +.names 53677 53678 +1 1 +.names 53678 53679 +0 1 +.names 53444 53679 53680 +11 1 +.names 15036 49052 53681 +11 1 +.names 997 53218 53682 +11 1 +.names 53686 53687 53683 +1- 1 +-1 1 +.names 53683 53684 +1 1 +.names 53691 53692 53685 +1- 1 +-1 1 +.names 53685 53686 +1 1 +.names 53676 53687 +0 1 +.names 53690 53218 53688 +1- 1 +-1 1 +.names 53688 53689 +1 1 +.names 907 53690 +0 1 +.names 15037 902 53691 +11 1 +.names 53689 53692 +0 1 +.names 53698 53699 53693 +1- 1 +-1 1 +.names 53693 53694 +1 1 +.names 53700 53239 53695 +11 1 +.names 53695 53696 +1 1 +.names 53696 53697 +0 1 +.names 53264 53697 53698 +11 1 +.names 15025 49146 53699 +11 1 +.names 1035 53247 53700 +11 1 +.names 53704 53705 53701 +1- 1 +-1 1 +.names 53701 53702 +1 1 +.names 53709 53710 53703 +1- 1 +-1 1 +.names 53703 53704 +1 1 +.names 53694 53705 +0 1 +.names 53708 53247 53706 +1- 1 +-1 1 +.names 53706 53707 +1 1 +.names 1096 53708 +0 1 +.names 15038 1123 53709 +11 1 +.names 53707 53710 +0 1 +.names 53716 53718 53711 +1- 1 +-1 1 +.names 53711 53712 +1 1 +.names 53719 53291 53713 +11 1 +.names 53713 53714 +1 1 +.names 53714 53715 +0 1 +.names 53218 53715 53716 +11 1 +.names 906 53717 +0 1 +.names 15030 53717 53718 +11 1 +.names 1025 53203 53719 +11 1 +.names 53723 53724 53720 +1- 1 +-1 1 +.names 53720 53721 +1 1 +.names 53727 53728 53722 +1- 1 +-1 1 +.names 53722 53723 +1 1 +.names 53712 53724 +0 1 +.names 49184 53203 53725 +1- 1 +-1 1 +.names 53725 53726 +1 1 +.names 15039 901 53727 +11 1 +.names 53726 53728 +0 1 +.names 53734 53736 53729 +1- 1 +-1 1 +.names 53729 53730 +1 1 +.names 53737 53291 53731 +11 1 +.names 53731 53732 +1 1 +.names 53732 53733 +0 1 +.names 53218 53733 53734 +11 1 +.names 1114 53735 +0 1 +.names 15030 53735 53736 +11 1 +.names 1003 53203 53737 +11 1 +.names 53741 53742 53738 +1- 1 +-1 1 +.names 53738 53739 +1 1 +.names 53743 53746 53740 +1- 1 +-1 1 +.names 53740 53741 +1 1 +.names 53730 53742 +0 1 +.names 1660 15027 53743 +11 1 +.names 53747 53291 53744 +1- 1 +-1 1 +.names 53744 53745 +1 1 +.names 53745 53746 +0 1 +.names 1141 53747 +0 1 +.names 53753 53754 53748 +1- 1 +-1 1 +.names 53748 53749 +1 1 +.names 53755 53361 53750 +11 1 +.names 53750 53751 +1 1 +.names 53751 53752 +0 1 +.names 53264 53752 53753 +11 1 +.names 15025 49282 53754 +11 1 +.names 1024 53218 53755 +11 1 +.names 53759 53760 53756 +1- 1 +-1 1 +.names 53756 53757 +1 1 +.names 53761 53764 53758 +1- 1 +-1 1 +.names 53758 53759 +1 1 +.names 53749 53760 +0 1 +.names 15037 1137 53761 +11 1 +.names 53765 53218 53762 +1- 1 +-1 1 +.names 53762 53763 +1 1 +.names 53763 53764 +0 1 +.names 1110 53765 +0 1 +.names 53771 53772 53766 +1- 1 +-1 1 +.names 53766 53767 +1 1 +.names 53773 53239 53768 +11 1 +.names 53768 53769 +1 1 +.names 53769 53770 +0 1 +.names 53203 53770 53771 +11 1 +.names 15027 49332 53772 +11 1 +.names 1031 53247 53773 +11 1 +.names 53777 53778 53774 +1- 1 +-1 1 +.names 53774 53775 +1 1 +.names 53782 53783 53776 +1- 1 +-1 1 +.names 53776 53777 +1 1 +.names 53767 53778 +0 1 +.names 53781 53247 53779 +1- 1 +-1 1 +.names 53779 53780 +1 1 +.names 1103 53781 +0 1 +.names 1130 15038 53782 +11 1 +.names 53780 53783 +0 1 +.names 53786 53291 53784 +11 1 +.names 53784 53785 +1 1 +.names 1030 53237 53786 +11 1 +.names 53790 53793 53787 +1- 1 +-1 1 +.names 53787 53788 +1 1 +.names 53800 53801 53789 +1- 1 +-1 1 +.names 53789 53790 +1 1 +.names 53795 53797 53791 +1- 1 +-1 1 +.names 53791 53792 +1 1 +.names 53792 53793 +0 1 +.names 53785 53794 +0 1 +.names 53247 53794 53795 +11 1 +.names 1100 53796 +0 1 +.names 15029 53796 53797 +11 1 +.names 49380 53237 53798 +1- 1 +-1 1 +.names 53798 53799 +1 1 +.names 15039 1127 53800 +11 1 +.names 53799 53801 +0 1 +.names 53804 53805 53802 +1- 1 +-1 1 +.names 53802 53803 +1 1 +.names 15051 53804 +0 1 +.names 1738 53805 +0 1 +.names 2413 53808 53806 +1- 1 +-1 1 +.names 53806 53807 +1 1 +.names 15072 53808 +0 1 +.names 53815 53818 53809 +1- 1 +-1 1 +.names 53809 53810 +1 1 +.names 53822 53823 53811 +1- 1 +-1 1 +.names 53811 53812 +1 1 +.names 53812 53813 +0 1 +.names 53807 53814 +0 1 +.names 53813 53814 53815 +1- 1 +-1 1 +.names 53826 53828 53816 +11 1 +.names 53816 53817 +1 1 +.names 53817 53818 +0 1 +.names 53838 53839 53819 +11 1 +.names 53819 53820 +1 1 +.names 53820 53821 +0 1 +.names 2413 53821 53822 +11 1 +.names 1783 2413 53823 +11 1 +.names 15061 53840 53824 +1- 1 +-1 1 +.names 53824 53825 +1 1 +.names 53825 53803 53826 +11 1 +.names 15069 14886 53827 +1- 1 +-1 1 +.names 53827 53828 +1 1 +.names 53833 3390 53829 +1- 1 +-1 1 +.names 53829 53830 +1 1 +.names 53804 53831 +1 1 +.names 53831 53832 +0 1 +.names 15072 53832 53833 +1- 1 +-1 1 +.names 15074 53837 53834 +1- 1 +-1 1 +.names 53834 53835 +1 1 +.names 15069 53836 +1 1 +.names 53836 53837 +0 1 +.names 53830 53838 +0 1 +.names 53835 53839 +0 1 +.names 1066 53840 +0 1 +.names 2413 53808 53841 +1- 1 +-1 1 +.names 53841 53842 +1 1 +.names 53849 53851 53843 +1- 1 +-1 1 +.names 53843 53844 +1 1 +.names 15073 53845 +0 1 +.names 53861 53862 53846 +11 1 +.names 53846 53847 +1 1 +.names 53847 53848 +0 1 +.names 53845 53848 53849 +11 1 +.names 1739 53850 +0 1 +.names 15073 53850 53851 +11 1 +.names 53856 2413 53852 +1- 1 +-1 1 +.names 53852 53853 +1 1 +.names 15069 53854 +1 1 +.names 53854 53855 +0 1 +.names 15083 53855 53856 +1- 1 +-1 1 +.names 15072 53860 53857 +1- 1 +-1 1 +.names 53857 53858 +1 1 +.names 2413 53859 +1 1 +.names 53859 53860 +0 1 +.names 53853 53861 +0 1 +.names 53858 53862 +0 1 +.names 53866 53867 53863 +1- 1 +-1 1 +.names 53863 53864 +1 1 +.names 53879 53880 53865 +1- 1 +-1 1 +.names 53865 53866 +1 1 +.names 53844 53867 +0 1 +.names 15069 14886 53868 +1- 1 +-1 1 +.names 53868 53869 +1 1 +.names 2413 53870 +1 1 +.names 53870 53871 +1 1 +.names 16518 53874 53872 +1- 1 +-1 1 +.names 53872 53873 +1 1 +.names 15083 53874 +0 1 +.names 53871 53875 +0 1 +.names 53873 53876 +0 1 +.names 53875 53876 53877 +1- 1 +-1 1 +.names 53869 53878 +0 1 +.names 53877 53878 53879 +1- 1 +-1 1 +.names 53842 53880 +0 1 +.names 53889 53892 53881 +1- 1 +-1 1 +.names 53881 53882 +1 1 +.names 53897 53898 53883 +1- 1 +-1 1 +.names 53883 53884 +1 1 +.names 53884 53885 +0 1 +.names 2413 53886 +1 1 +.names 53886 53887 +1 1 +.names 53887 53888 +0 1 +.names 53885 53888 53889 +1- 1 +-1 1 +.names 53903 53905 53890 +11 1 +.names 53890 53891 +1 1 +.names 53891 53892 +0 1 +.names 15043 53893 +0 1 +.names 53912 53913 53894 +11 1 +.names 53894 53895 +1 1 +.names 53895 53896 +0 1 +.names 53893 53896 53897 +11 1 +.names 15043 2413 53898 +11 1 +.names 53845 2413 53899 +1- 1 +-1 1 +.names 53899 53900 +1 1 +.names 15061 16440 53901 +1- 1 +-1 1 +.names 53901 53902 +1 1 +.names 53900 53902 53903 +11 1 +.names 14886 53914 53904 +1- 1 +-1 1 +.names 53904 53905 +1 1 +.names 15074 53909 53906 +1- 1 +-1 1 +.names 53906 53907 +1 1 +.names 2413 53908 +1 1 +.names 53908 53909 +0 1 +.names 53919 3489 53910 +1- 1 +-1 1 +.names 53910 53911 +1 1 +.names 53911 53912 +0 1 +.names 53907 53913 +0 1 +.names 15058 53914 +0 1 +.names 53914 53915 +1 1 +.names 53915 53916 +0 1 +.names 53845 53917 +1 1 +.names 53917 53918 +0 1 +.names 53916 53918 53919 +1- 1 +-1 1 +.names 53928 53931 53920 +1- 1 +-1 1 +.names 53920 53921 +1 1 +.names 53936 53937 53922 +1- 1 +-1 1 +.names 53922 53923 +1 1 +.names 53923 53924 +0 1 +.names 2413 53925 +1 1 +.names 53925 53926 +1 1 +.names 53926 53927 +0 1 +.names 53924 53927 53928 +1- 1 +-1 1 +.names 53955 53956 53929 +11 1 +.names 53929 53930 +1 1 +.names 53930 53931 +0 1 +.names 15079 53932 +0 1 +.names 53944 53945 53933 +11 1 +.names 53933 53934 +1 1 +.names 53934 53935 +0 1 +.names 53932 53935 53936 +11 1 +.names 15079 2413 53937 +11 1 +.names 15078 53941 53938 +1- 1 +-1 1 +.names 53938 53939 +1 1 +.names 2413 53940 +1 1 +.names 53940 53941 +0 1 +.names 53963 53964 53942 +1- 1 +-1 1 +.names 53942 53943 +1 1 +.names 53943 53944 +0 1 +.names 53939 53945 +0 1 +.names 14886 53948 53946 +1- 1 +-1 1 +.names 53946 53947 +1 1 +.names 15078 53948 +0 1 +.names 53951 53952 53949 +1- 1 +-1 1 +.names 53949 53950 +1 1 +.names 1740 15052 53951 +11 1 +.names 53947 53952 +0 1 +.names 15082 1056 53953 +11 1 +.names 53953 53954 +1 1 +.names 53954 53955 +0 1 +.names 53950 53956 +0 1 +.names 15052 53957 +0 1 +.names 53957 53958 +1 1 +.names 15082 53959 +0 1 +.names 53959 53960 +1 1 +.names 53960 53961 +0 1 +.names 53958 53962 +0 1 +.names 53961 53962 53963 +1- 1 +-1 1 +.names 774 53964 +0 1 +.names 53957 53967 53965 +1- 1 +-1 1 +.names 53965 53966 +1 1 +.names 1741 53967 +0 1 +.names 14886 15069 53968 +1- 1 +-1 1 +.names 53968 53969 +1 1 +.names 15081 53973 53970 +1- 1 +-1 1 +.names 53970 53971 +1 1 +.names 2413 53972 +1 1 +.names 53972 53973 +0 1 +.names 53979 53980 53974 +1- 1 +-1 1 +.names 53974 53975 +1 1 +.names 53983 53984 53976 +11 1 +.names 53976 53977 +1 1 +.names 53977 53978 +0 1 +.names 53932 53978 53979 +11 1 +.names 15079 2413 53980 +11 1 +.names 53987 3404 53981 +1- 1 +-1 1 +.names 53981 53982 +1 1 +.names 53982 53983 +0 1 +.names 53971 53984 +0 1 +.names 53957 53985 +1 1 +.names 53985 53986 +0 1 +.names 15055 53986 53987 +1- 1 +-1 1 +.names 53994 53995 53988 +1- 1 +-1 1 +.names 53988 53989 +1 1 +.names 53966 53990 +0 1 +.names 54006 16635 53991 +1- 1 +-1 1 +.names 53991 53992 +1 1 +.names 53992 53993 +0 1 +.names 53990 53993 53994 +1- 1 +-1 1 +.names 53969 53995 +0 1 +.names 53998 54001 53996 +11 1 +.names 53996 53997 +1 1 +.names 53989 53998 +0 1 +.names 1783 53999 +1 1 +.names 53999 54000 +1 1 +.names 54000 54001 +0 1 +.names 54004 54005 54002 +1- 1 +-1 1 +.names 54002 54003 +1 1 +.names 53975 54004 +0 1 +.names 53997 54005 +0 1 +.names 15081 54006 +0 1 +.names 54015 54018 54007 +1- 1 +-1 1 +.names 54007 54008 +1 1 +.names 54023 54024 54009 +1- 1 +-1 1 +.names 54009 54010 +1 1 +.names 54010 54011 +0 1 +.names 2413 54012 +1 1 +.names 54012 54013 +1 1 +.names 54013 54014 +0 1 +.names 54011 54014 54015 +1- 1 +-1 1 +.names 54046 54041 54016 +11 1 +.names 54016 54017 +1 1 +.names 54017 54018 +0 1 +.names 15068 54019 +0 1 +.names 54035 54036 54020 +11 1 +.names 54020 54021 +1 1 +.names 54021 54022 +0 1 +.names 54019 54022 54023 +11 1 +.names 15068 14886 54024 +11 1 +.names 15072 3370 54025 +1- 1 +-1 1 +.names 54025 54026 +1 1 +.names 54031 54033 54027 +1- 1 +-1 1 +.names 54027 54028 +1 1 +.names 54034 2413 54029 +11 1 +.names 54029 54030 +1 1 +.names 54030 54031 +0 1 +.names 53874 54032 +1 1 +.names 54032 54033 +0 1 +.names 15053 54034 +0 1 +.names 54028 54035 +0 1 +.names 54026 54036 +0 1 +.names 54034 54039 54037 +1- 1 +-1 1 +.names 54037 54038 +1 1 +.names 1742 54039 +0 1 +.names 54042 53808 54040 +1- 1 +-1 1 +.names 54040 54041 +1 1 +.names 6438 54042 +0 1 +.names 53874 54045 54043 +1- 1 +-1 1 +.names 54043 54044 +1 1 +.names 1061 54045 +0 1 +.names 54044 54038 54046 +11 1 +.names 54055 54058 54047 +1- 1 +-1 1 +.names 54047 54048 +1 1 +.names 54063 54064 54049 +1- 1 +-1 1 +.names 54049 54050 +1 1 +.names 54050 54051 +0 1 +.names 2413 54052 +1 1 +.names 54052 54053 +1 1 +.names 54053 54054 +0 1 +.names 54051 54054 54055 +1- 1 +-1 1 +.names 54084 54085 54056 +11 1 +.names 54056 54057 +1 1 +.names 54057 54058 +0 1 +.names 15041 54059 +0 1 +.names 54080 54081 54060 +11 1 +.names 54060 54061 +1 1 +.names 54061 54062 +0 1 +.names 54059 54062 54063 +11 1 +.names 15041 2413 54064 +11 1 +.names 54067 54070 54065 +1- 1 +-1 1 +.names 54065 54066 +1 1 +.names 15051 1743 54067 +11 1 +.names 54086 53959 54068 +1- 1 +-1 1 +.names 54068 54069 +1 1 +.names 54069 54070 +0 1 +.names 54075 3320 54071 +1- 1 +-1 1 +.names 54071 54072 +1 1 +.names 53804 54073 +1 1 +.names 54073 54074 +0 1 +.names 15077 54074 54075 +1- 1 +-1 1 +.names 15082 54079 54076 +1- 1 +-1 1 +.names 54076 54077 +1 1 +.names 2413 54078 +1 1 +.names 54078 54079 +0 1 +.names 54072 54080 +0 1 +.names 54077 54081 +0 1 +.names 1775 15077 54082 +11 1 +.names 54082 54083 +1 1 +.names 54083 54084 +0 1 +.names 54066 54085 +0 1 +.names 1068 54086 +0 1 +.names 54095 54098 54087 +1- 1 +-1 1 +.names 54087 54088 +1 1 +.names 54102 54103 54089 +1- 1 +-1 1 +.names 54089 54090 +1 1 +.names 54090 54091 +0 1 +.names 2413 54092 +1 1 +.names 54092 54093 +1 1 +.names 54093 54094 +0 1 +.names 54091 54094 54095 +1- 1 +-1 1 +.names 54108 54110 54096 +11 1 +.names 54096 54097 +1 1 +.names 54097 54098 +0 1 +.names 54120 54121 54099 +11 1 +.names 54099 54100 +1 1 +.names 54100 54101 +0 1 +.names 53932 54101 54102 +11 1 +.names 15079 2413 54103 +11 1 +.names 53845 54123 54104 +1- 1 +-1 1 +.names 54104 54105 +1 1 +.names 15061 54124 54106 +1- 1 +-1 1 +.names 54106 54107 +1 1 +.names 54105 54107 54108 +11 1 +.names 14886 54122 54109 +1- 1 +-1 1 +.names 54109 54110 +1 1 +.names 54115 3378 54111 +1- 1 +-1 1 +.names 54111 54112 +1 1 +.names 53845 54113 +1 1 +.names 54113 54114 +0 1 +.names 15077 54114 54115 +1- 1 +-1 1 +.names 15074 54119 54116 +1- 1 +-1 1 +.names 54116 54117 +1 1 +.names 2413 54118 +1 1 +.names 54118 54119 +0 1 +.names 54117 54120 +0 1 +.names 54112 54121 +0 1 +.names 15077 54122 +0 1 +.names 1744 54123 +0 1 +.names 1074 54124 +0 1 +.names 54130 54131 54125 +1- 1 +-1 1 +.names 54125 54126 +1 1 +.names 54138 54139 54127 +11 1 +.names 54127 54128 +1 1 +.names 54128 54129 +0 1 +.names 53932 54129 54130 +11 1 +.names 15079 2413 54131 +11 1 +.names 1783 54135 54132 +1- 1 +-1 1 +.names 54132 54133 +1 1 +.names 53959 54134 +1 1 +.names 54134 54135 +0 1 +.names 54144 3414 54136 +1- 1 +-1 1 +.names 54136 54137 +1 1 +.names 54137 54138 +0 1 +.names 54133 54139 +0 1 +.names 14886 53914 54140 +1- 1 +-1 1 +.names 54140 54141 +1 1 +.names 53845 54142 +1 1 +.names 54142 54143 +0 1 +.names 15058 54143 54144 +1- 1 +-1 1 +.names 54153 54154 54145 +1- 1 +-1 1 +.names 54145 54146 +1 1 +.names 53845 54165 54147 +1- 1 +-1 1 +.names 54147 54148 +1 1 +.names 54148 54149 +0 1 +.names 53959 54166 54150 +1- 1 +-1 1 +.names 54150 54151 +1 1 +.names 54151 54152 +0 1 +.names 54149 54152 54153 +1- 1 +-1 1 +.names 54141 54154 +0 1 +.names 54157 54160 54155 +1- 1 +-1 1 +.names 54155 54156 +1 1 +.names 54126 54157 +0 1 +.names 54163 54164 54158 +11 1 +.names 54158 54159 +1 1 +.names 54159 54160 +0 1 +.names 1783 54161 +1 1 +.names 54161 54162 +1 1 +.names 54146 54163 +0 1 +.names 54162 54164 +0 1 +.names 1745 54165 +0 1 +.names 1054 54166 +0 1 +.names 54175 54178 54167 +1- 1 +-1 1 +.names 54167 54168 +1 1 +.names 54182 54183 54169 +1- 1 +-1 1 +.names 54169 54170 +1 1 +.names 54170 54171 +0 1 +.names 2413 54172 +1 1 +.names 54172 54173 +1 1 +.names 54173 54174 +0 1 +.names 54171 54174 54175 +1- 1 +-1 1 +.names 54203 54196 54176 +11 1 +.names 54176 54177 +1 1 +.names 54177 54178 +0 1 +.names 54193 54194 54179 +11 1 +.names 54179 54180 +1 1 +.names 54180 54181 +0 1 +.names 53932 54181 54182 +11 1 +.names 15079 14886 54183 +11 1 +.names 54188 3300 54184 +1- 1 +-1 1 +.names 54184 54185 +1 1 +.names 53804 54186 +1 1 +.names 54186 54187 +0 1 +.names 15077 54187 54188 +1- 1 +-1 1 +.names 15083 54192 54189 +1- 1 +-1 1 +.names 54189 54190 +1 1 +.names 2413 54191 +1 1 +.names 54191 54192 +0 1 +.names 54185 54193 +0 1 +.names 54190 54194 +0 1 +.names 14886 54122 54195 +1- 1 +-1 1 +.names 54195 54196 +1 1 +.names 53804 54199 54197 +1- 1 +-1 1 +.names 54197 54198 +1 1 +.names 1746 54199 +0 1 +.names 53874 54202 54200 +1- 1 +-1 1 +.names 54200 54201 +1 1 +.names 1069 54202 +0 1 +.names 54201 54198 54203 +11 1 +.names 54212 54215 54204 +1- 1 +-1 1 +.names 54204 54205 +1 1 +.names 54219 54220 54206 +1- 1 +-1 1 +.names 54206 54207 +1 1 +.names 54207 54208 +0 1 +.names 2413 54209 +1 1 +.names 54209 54210 +1 1 +.names 54210 54211 +0 1 +.names 54208 54211 54212 +1- 1 +-1 1 +.names 54225 54227 54213 +11 1 +.names 54213 54214 +1 1 +.names 54214 54215 +0 1 +.names 54238 54239 54216 +11 1 +.names 54216 54217 +1 1 +.names 54217 54218 +0 1 +.names 54059 54218 54219 +11 1 +.names 15041 2413 54220 +11 1 +.names 53804 54240 54221 +1- 1 +-1 1 +.names 54221 54222 +1 1 +.names 15061 16831 54223 +1- 1 +-1 1 +.names 54223 54224 +1 1 +.names 54222 54224 54225 +11 1 +.names 14886 15069 54226 +1- 1 +-1 1 +.names 54226 54227 +1 1 +.names 15055 54230 54228 +1- 1 +-1 1 +.names 54228 54229 +1 1 +.names 770 54230 +0 1 +.names 54235 54237 54231 +1- 1 +-1 1 +.names 54231 54232 +1 1 +.names 53804 2413 54233 +11 1 +.names 54233 54234 +1 1 +.names 54234 54235 +0 1 +.names 15061 54236 +1 1 +.names 54236 54237 +0 1 +.names 54232 54238 +0 1 +.names 54229 54239 +0 1 +.names 1747 54240 +0 1 +.names 54243 53804 54241 +1- 1 +-1 1 +.names 54241 54242 +1 1 +.names 1748 54243 +0 1 +.names 54252 54255 54244 +1- 1 +-1 1 +.names 54244 54245 +1 1 +.names 54259 54260 54246 +1- 1 +-1 1 +.names 54246 54247 +1 1 +.names 54247 54248 +0 1 +.names 2413 54249 +1 1 +.names 54249 54250 +1 1 +.names 54250 54251 +0 1 +.names 54248 54251 54252 +1- 1 +-1 1 +.names 54278 54279 54253 +11 1 +.names 54253 54254 +1 1 +.names 54254 54255 +0 1 +.names 54274 54275 54256 +11 1 +.names 54256 54257 +1 1 +.names 54257 54258 +0 1 +.names 54059 54258 54259 +11 1 +.names 15041 2413 54260 +11 1 +.names 54263 54264 54261 +1- 1 +-1 1 +.names 54261 54262 +1 1 +.names 15082 1071 54263 +11 1 +.names 54242 54264 +0 1 +.names 54269 3296 54265 +1- 1 +-1 1 +.names 54265 54266 +1 1 +.names 53804 54267 +1 1 +.names 54267 54268 +0 1 +.names 15077 54268 54269 +1- 1 +-1 1 +.names 15082 54273 54270 +1- 1 +-1 1 +.names 54270 54271 +1 1 +.names 2413 54272 +1 1 +.names 54272 54273 +0 1 +.names 54266 54274 +0 1 +.names 54271 54275 +0 1 +.names 1775 15077 54276 +11 1 +.names 54276 54277 +1 1 +.names 54277 54278 +0 1 +.names 54262 54279 +0 1 +.names 54288 54291 54280 +1- 1 +-1 1 +.names 54280 54281 +1 1 +.names 54295 54296 54282 +1- 1 +-1 1 +.names 54282 54283 +1 1 +.names 54283 54284 +0 1 +.names 2413 54285 +1 1 +.names 54285 54286 +1 1 +.names 54286 54287 +0 1 +.names 54284 54287 54288 +1- 1 +-1 1 +.names 54317 54318 54289 +11 1 +.names 54289 54290 +1 1 +.names 54290 54291 +0 1 +.names 54307 54308 54292 +11 1 +.names 54292 54293 +1 1 +.names 54293 54294 +0 1 +.names 53893 54294 54295 +11 1 +.names 15043 14886 54296 +11 1 +.names 54301 54302 54297 +1- 1 +-1 1 +.names 54297 54298 +1 1 +.names 53957 54299 +1 1 +.names 54299 54300 +0 1 +.names 15081 54300 54301 +1- 1 +-1 1 +.names 785 54302 +0 1 +.names 15055 54306 54303 +1- 1 +-1 1 +.names 54303 54304 +1 1 +.names 2413 54305 +1 1 +.names 54305 54306 +0 1 +.names 54298 54307 +0 1 +.names 54304 54308 +0 1 +.names 14886 15069 54309 +1- 1 +-1 1 +.names 54309 54310 +1 1 +.names 54313 54314 54311 +1- 1 +-1 1 +.names 54311 54312 +1 1 +.names 15052 1783 54313 +11 1 +.names 54310 54314 +0 1 +.names 15081 1049 54315 +11 1 +.names 54315 54316 +1 1 +.names 54316 54317 +0 1 +.names 54312 54318 +0 1 +.names 54325 54327 54319 +1- 1 +-1 1 +.names 54319 54320 +1 1 +.names 15060 54321 +0 1 +.names 54337 54338 54322 +11 1 +.names 54322 54323 +1 1 +.names 54323 54324 +0 1 +.names 54321 54324 54325 +11 1 +.names 1065 54326 +0 1 +.names 15060 54326 54327 +11 1 +.names 15072 3374 54328 +1- 1 +-1 1 +.names 54328 54329 +1 1 +.names 54334 54336 54330 +1- 1 +-1 1 +.names 54330 54331 +1 1 +.names 53957 2413 54332 +11 1 +.names 54332 54333 +1 1 +.names 54333 54334 +0 1 +.names 15069 54335 +1 1 +.names 54335 54336 +0 1 +.names 54331 54337 +0 1 +.names 54329 54338 +0 1 +.names 54342 54343 54339 +1- 1 +-1 1 +.names 54339 54340 +1 1 +.names 54354 54357 54341 +1- 1 +-1 1 +.names 54341 54342 +1 1 +.names 54320 54343 +0 1 +.names 14886 15069 54344 +1- 1 +-1 1 +.names 54344 54345 +1 1 +.names 54345 54346 +0 1 +.names 14886 53808 54347 +1- 1 +-1 1 +.names 54347 54348 +1 1 +.names 54348 54349 +0 1 +.names 54346 54349 54350 +1- 1 +-1 1 +.names 54358 53957 54351 +1- 1 +-1 1 +.names 54351 54352 +1 1 +.names 54352 54353 +0 1 +.names 54350 54353 54354 +1- 1 +-1 1 +.names 2413 54355 +1 1 +.names 54355 54356 +1 1 +.names 54356 54357 +0 1 +.names 1749 54358 +0 1 +.names 54364 54365 54359 +1- 1 +-1 1 +.names 54359 54360 +1 1 +.names 54375 54376 54361 +11 1 +.names 54361 54362 +1 1 +.names 54362 54363 +0 1 +.names 54059 54363 54364 +11 1 +.names 15041 2413 54365 +11 1 +.names 54370 2413 54366 +1- 1 +-1 1 +.names 54366 54367 +1 1 +.names 53957 54368 +1 1 +.names 54368 54369 +0 1 +.names 15058 54369 54370 +1- 1 +-1 1 +.names 15074 54374 54371 +1- 1 +-1 1 +.names 54371 54372 +1 1 +.names 2413 54373 +1 1 +.names 54373 54374 +0 1 +.names 54367 54375 +0 1 +.names 54372 54376 +0 1 +.names 15061 16645 54377 +1- 1 +-1 1 +.names 54377 54378 +1 1 +.names 14886 53914 54379 +1- 1 +-1 1 +.names 54379 54380 +1 1 +.names 54387 54388 54381 +1- 1 +-1 1 +.names 54381 54382 +1 1 +.names 54378 54383 +0 1 +.names 53957 54399 54384 +1- 1 +-1 1 +.names 54384 54385 +1 1 +.names 54385 54386 +0 1 +.names 54383 54386 54387 +1- 1 +-1 1 +.names 54380 54388 +0 1 +.names 54391 54394 54389 +1- 1 +-1 1 +.names 54389 54390 +1 1 +.names 54360 54391 +0 1 +.names 54395 54398 54392 +11 1 +.names 54392 54393 +1 1 +.names 54393 54394 +0 1 +.names 54382 54395 +0 1 +.names 1783 54396 +1 1 +.names 54396 54397 +1 1 +.names 54397 54398 +0 1 +.names 1750 54399 +0 1 +.names 54408 54411 54400 +1- 1 +-1 1 +.names 54400 54401 +1 1 +.names 54415 54416 54402 +1- 1 +-1 1 +.names 54402 54403 +1 1 +.names 54403 54404 +0 1 +.names 2413 54405 +1 1 +.names 54405 54406 +1 1 +.names 54406 54407 +0 1 +.names 54404 54407 54408 +1- 1 +-1 1 +.names 54419 54422 54409 +11 1 +.names 54409 54410 +1 1 +.names 54410 54411 +0 1 +.names 54429 54430 54412 +11 1 +.names 54412 54413 +1 1 +.names 54413 54414 +0 1 +.names 54059 54414 54415 +11 1 +.names 15041 2413 54416 +11 1 +.names 54434 1050 54417 +11 1 +.names 54417 54418 +1 1 +.names 54418 54419 +0 1 +.names 54436 54437 54420 +1- 1 +-1 1 +.names 54420 54421 +1 1 +.names 54421 54422 +0 1 +.names 15055 54426 54423 +1- 1 +-1 1 +.names 54423 54424 +1 1 +.names 2413 54425 +1 1 +.names 54425 54426 +0 1 +.names 54440 3481 54427 +1- 1 +-1 1 +.names 54427 54428 +1 1 +.names 54428 54429 +0 1 +.names 54424 54430 +0 1 +.names 14886 15069 54431 +1- 1 +-1 1 +.names 54431 54432 +1 1 +.names 54438 54433 +0 1 +.names 54433 54434 +1 1 +.names 54034 54435 +1 1 +.names 15053 1751 54436 +11 1 +.names 54432 54437 +0 1 +.names 53874 54438 +1 1 +.names 54435 54439 +0 1 +.names 54433 54439 54440 +1- 1 +-1 1 +.names 54443 53845 54441 +1- 1 +-1 1 +.names 54441 54442 +1 1 +.names 1752 54443 +0 1 +.names 54452 54455 54444 +1- 1 +-1 1 +.names 54444 54445 +1 1 +.names 54459 54460 54446 +1- 1 +-1 1 +.names 54446 54447 +1 1 +.names 54447 54448 +0 1 +.names 2413 54449 +1 1 +.names 54449 54450 +1 1 +.names 54450 54451 +0 1 +.names 54448 54451 54452 +1- 1 +-1 1 +.names 54463 54466 54453 +11 1 +.names 54453 54454 +1 1 +.names 54454 54455 +0 1 +.names 54471 54474 54456 +11 1 +.names 54456 54457 +1 1 +.names 54457 54458 +0 1 +.names 53893 54458 54459 +11 1 +.names 15043 14886 54460 +11 1 +.names 54476 54461 +0 1 +.names 54461 54462 +1 1 +.names 54462 54463 +0 1 +.names 54482 54483 54464 +1- 1 +-1 1 +.names 54464 54465 +1 1 +.names 54465 54466 +0 1 +.names 15082 54470 54467 +1- 1 +-1 1 +.names 54467 54468 +1 1 +.names 2413 54469 +1 1 +.names 54469 54470 +0 1 +.names 54468 54471 +0 1 +.names 54481 2413 54472 +1- 1 +-1 1 +.names 54472 54473 +1 1 +.names 54473 54474 +0 1 +.names 14886 53914 54475 +1- 1 +-1 1 +.names 54475 54476 +1 1 +.names 53914 54477 +1 1 +.names 54477 54478 +0 1 +.names 53845 54479 +1 1 +.names 54479 54480 +0 1 +.names 54478 54480 54481 +1- 1 +-1 1 +.names 15082 1057 54482 +11 1 +.names 54442 54483 +0 1 +.names 53957 54486 54484 +1- 1 +-1 1 +.names 54484 54485 +1 1 +.names 1753 54486 +0 1 +.names 54492 54493 54487 +1- 1 +-1 1 +.names 54487 54488 +1 1 +.names 54503 54504 54489 +11 1 +.names 54489 54490 +1 1 +.names 54490 54491 +0 1 +.names 53932 54491 54492 +11 1 +.names 15079 2413 54493 +11 1 +.names 54498 3366 54494 +1- 1 +-1 1 +.names 54494 54495 +1 1 +.names 53957 54496 +1 1 +.names 54496 54497 +0 1 +.names 15058 54497 54498 +1- 1 +-1 1 +.names 15074 54502 54499 +1- 1 +-1 1 +.names 54499 54500 +1 1 +.names 2413 54501 +1 1 +.names 54501 54502 +0 1 +.names 54495 54503 +0 1 +.names 54500 54504 +0 1 +.names 14886 53914 54505 +1- 1 +-1 1 +.names 54505 54506 +1 1 +.names 54513 54514 54507 +1- 1 +-1 1 +.names 54507 54508 +1 1 +.names 54485 54509 +0 1 +.names 15061 54525 54510 +1- 1 +-1 1 +.names 54510 54511 +1 1 +.names 54511 54512 +0 1 +.names 54509 54512 54513 +1- 1 +-1 1 +.names 54506 54514 +0 1 +.names 54517 54520 54515 +1- 1 +-1 1 +.names 54515 54516 +1 1 +.names 54488 54517 +0 1 +.names 54523 54524 54518 +11 1 +.names 54518 54519 +1 1 +.names 54519 54520 +0 1 +.names 1783 54521 +1 1 +.names 54521 54522 +1 1 +.names 54508 54523 +0 1 +.names 54522 54524 +0 1 +.names 1075 54525 +0 1 +.names 54534 54537 54526 +1- 1 +-1 1 +.names 54526 54527 +1 1 +.names 54541 54542 54528 +1- 1 +-1 1 +.names 54528 54529 +1 1 +.names 54529 54530 +0 1 +.names 2413 54531 +1 1 +.names 54531 54532 +1 1 +.names 54532 54533 +0 1 +.names 54530 54533 54534 +1- 1 +-1 1 +.names 54562 54555 54535 +11 1 +.names 54535 54536 +1 1 +.names 54536 54537 +0 1 +.names 54552 54553 54538 +11 1 +.names 54538 54539 +1 1 +.names 54539 54540 +0 1 +.names 54059 54540 54541 +11 1 +.names 15041 14886 54542 +11 1 +.names 54547 2413 54543 +1- 1 +-1 1 +.names 54543 54544 +1 1 +.names 54034 54545 +1 1 +.names 54545 54546 +0 1 +.names 15078 54546 54547 +1- 1 +-1 1 +.names 15083 54551 54548 +1- 1 +-1 1 +.names 54548 54549 +1 1 +.names 2413 54550 +1 1 +.names 54550 54551 +0 1 +.names 54544 54552 +0 1 +.names 54549 54553 +0 1 +.names 14886 53948 54554 +1- 1 +-1 1 +.names 54554 54555 +1 1 +.names 54034 54558 54556 +1- 1 +-1 1 +.names 54556 54557 +1 1 +.names 1754 54558 +0 1 +.names 53874 54561 54559 +1- 1 +-1 1 +.names 54559 54560 +1 1 +.names 1064 54561 +0 1 +.names 54560 54557 54562 +11 1 +.names 54034 54565 54563 +1- 1 +-1 1 +.names 54563 54564 +1 1 +.names 1755 54565 +0 1 +.names 54574 54577 54566 +1- 1 +-1 1 +.names 54566 54567 +1 1 +.names 54581 54582 54568 +1- 1 +-1 1 +.names 54568 54569 +1 1 +.names 54569 54570 +0 1 +.names 2413 54571 +1 1 +.names 54571 54572 +1 1 +.names 54572 54573 +0 1 +.names 54570 54573 54574 +1- 1 +-1 1 +.names 54585 54587 54575 +11 1 +.names 54575 54576 +1 1 +.names 54576 54577 +0 1 +.names 54598 54599 54578 +11 1 +.names 54578 54579 +1 1 +.names 54579 54580 +0 1 +.names 53893 54580 54581 +11 1 +.names 15043 2413 54582 +11 1 +.names 54006 54600 54583 +1- 1 +-1 1 +.names 54583 54584 +1 1 +.names 54564 54584 54585 +11 1 +.names 14886 53948 54586 +1- 1 +-1 1 +.names 54586 54587 +1 1 +.names 54592 54593 54588 +1- 1 +-1 1 +.names 54588 54589 +1 1 +.names 54034 54590 +1 1 +.names 54590 54591 +0 1 +.names 15078 54591 54592 +1- 1 +-1 1 +.names 1756 54593 +0 1 +.names 15081 54597 54594 +1- 1 +-1 1 +.names 54594 54595 +1 1 +.names 2413 54596 +1 1 +.names 54596 54597 +0 1 +.names 54589 54598 +0 1 +.names 54595 54599 +0 1 +.names 1073 54600 +0 1 +.names 54609 54612 54601 +1- 1 +-1 1 +.names 54601 54602 +1 1 +.names 54616 54617 54603 +1- 1 +-1 1 +.names 54603 54604 +1 1 +.names 54604 54605 +0 1 +.names 2413 54606 +1 1 +.names 54606 54607 +1 1 +.names 54607 54608 +0 1 +.names 54605 54608 54609 +1- 1 +-1 1 +.names 54622 54624 54610 +11 1 +.names 54610 54611 +1 1 +.names 54611 54612 +0 1 +.names 54634 54635 54613 +11 1 +.names 54613 54614 +1 1 +.names 54614 54615 +0 1 +.names 53932 54615 54616 +11 1 +.names 15079 14886 54617 +11 1 +.names 54034 54637 54618 +1- 1 +-1 1 +.names 54618 54619 +1 1 +.names 54006 54636 54620 +1- 1 +-1 1 +.names 54620 54621 +1 1 +.names 54619 54621 54622 +11 1 +.names 14886 54122 54623 +1- 1 +-1 1 +.names 54623 54624 +1 1 +.names 54629 3386 54625 +1- 1 +-1 1 +.names 54625 54626 +1 1 +.names 54034 54627 +1 1 +.names 54627 54628 +0 1 +.names 15077 54628 54629 +1- 1 +-1 1 +.names 15081 54633 54630 +1- 1 +-1 1 +.names 54630 54631 +1 1 +.names 2413 54632 +1 1 +.names 54632 54633 +0 1 +.names 54626 54634 +0 1 +.names 54631 54635 +0 1 +.names 1072 54636 +0 1 +.names 1757 54637 +0 1 +.names 54034 54640 54638 +1- 1 +-1 1 +.names 54638 54639 +1 1 +.names 1758 54640 +0 1 +.names 54646 54647 54641 +1- 1 +-1 1 +.names 54641 54642 +1 1 +.names 54657 54658 54643 +11 1 +.names 54643 54644 +1 1 +.names 54644 54645 +0 1 +.names 53932 54645 54646 +11 1 +.names 15079 2413 54647 +11 1 +.names 54652 2413 54648 +1- 1 +-1 1 +.names 54648 54649 +1 1 +.names 54034 54650 +1 1 +.names 54650 54651 +0 1 +.names 15058 54651 54652 +1- 1 +-1 1 +.names 15081 54656 54653 +1- 1 +-1 1 +.names 54653 54654 +1 1 +.names 2413 54655 +1 1 +.names 54655 54656 +0 1 +.names 54649 54657 +0 1 +.names 54654 54658 +0 1 +.names 14886 53914 54659 +1- 1 +-1 1 +.names 54659 54660 +1 1 +.names 54667 54668 54661 +1- 1 +-1 1 +.names 54661 54662 +1 1 +.names 54639 54663 +0 1 +.names 54006 16662 54664 +1- 1 +-1 1 +.names 54664 54665 +1 1 +.names 54665 54666 +0 1 +.names 54663 54666 54667 +1- 1 +-1 1 +.names 54660 54668 +0 1 +.names 54671 54674 54669 +1- 1 +-1 1 +.names 54669 54670 +1 1 +.names 54642 54671 +0 1 +.names 54677 54678 54672 +11 1 +.names 54672 54673 +1 1 +.names 54673 54674 +0 1 +.names 1783 54675 +1 1 +.names 54675 54676 +1 1 +.names 54662 54677 +0 1 +.names 54676 54678 +0 1 +.names 54687 54690 54679 +1- 1 +-1 1 +.names 54679 54680 +1 1 +.names 54694 54695 54681 +1- 1 +-1 1 +.names 54681 54682 +1 1 +.names 54682 54683 +0 1 +.names 2413 54684 +1 1 +.names 54684 54685 +1 1 +.names 54685 54686 +0 1 +.names 54683 54686 54687 +1- 1 +-1 1 +.names 54700 54702 54688 +11 1 +.names 54688 54689 +1 1 +.names 54689 54690 +0 1 +.names 54712 54713 54691 +11 1 +.names 54691 54692 +1 1 +.names 54692 54693 +0 1 +.names 53932 54693 54694 +11 1 +.names 15079 2413 54695 +11 1 +.names 15061 16647 54696 +1- 1 +-1 1 +.names 54696 54697 +1 1 +.names 53804 54714 54698 +1- 1 +-1 1 +.names 54698 54699 +1 1 +.names 54697 54699 54700 +11 1 +.names 14886 54122 54701 +1- 1 +-1 1 +.names 54701 54702 +1 1 +.names 54707 2413 54703 +1- 1 +-1 1 +.names 54703 54704 +1 1 +.names 53804 54705 +1 1 +.names 54705 54706 +0 1 +.names 15077 54706 54707 +1- 1 +-1 1 +.names 1783 54711 54708 +1- 1 +-1 1 +.names 54708 54709 +1 1 +.names 15061 54710 +1 1 +.names 54710 54711 +0 1 +.names 54704 54712 +0 1 +.names 54709 54713 +0 1 +.names 1759 54714 +0 1 +.names 54717 53804 54715 +1- 1 +-1 1 +.names 54715 54716 +1 1 +.names 1760 54717 +0 1 +.names 54726 54729 54718 +1- 1 +-1 1 +.names 54718 54719 +1 1 +.names 54733 54734 54720 +1- 1 +-1 1 +.names 54720 54721 +1 1 +.names 54721 54722 +0 1 +.names 2413 54723 +1 1 +.names 54723 54724 +1 1 +.names 54724 54725 +0 1 +.names 54722 54725 54726 +1- 1 +-1 1 +.names 54737 54740 54727 +11 1 +.names 54727 54728 +1 1 +.names 54728 54729 +0 1 +.names 54750 54751 54730 +11 1 +.names 54730 54731 +1 1 +.names 54731 54732 +0 1 +.names 53893 54732 54733 +11 1 +.names 15043 14886 54734 +11 1 +.names 54755 54735 +0 1 +.names 54735 54736 +1 1 +.names 54736 54737 +0 1 +.names 54752 54753 54738 +1- 1 +-1 1 +.names 54738 54739 +1 1 +.names 54739 54740 +0 1 +.names 54745 3312 54741 +1- 1 +-1 1 +.names 54741 54742 +1 1 +.names 53804 54743 +1 1 +.names 54743 54744 +0 1 +.names 15078 54744 54745 +1- 1 +-1 1 +.names 15074 54749 54746 +1- 1 +-1 1 +.names 54746 54747 +1 1 +.names 2413 54748 +1 1 +.names 54748 54749 +0 1 +.names 54742 54750 +0 1 +.names 54747 54751 +0 1 +.names 15074 1060 54752 +11 1 +.names 54716 54753 +0 1 +.names 14886 53948 54754 +1- 1 +-1 1 +.names 54754 54755 +1 1 +.names 54034 54758 54756 +1- 1 +-1 1 +.names 54756 54757 +1 1 +.names 1761 54758 +0 1 +.names 54764 54765 54759 +1- 1 +-1 1 +.names 54759 54760 +1 1 +.names 54775 54776 54761 +11 1 +.names 54761 54762 +1 1 +.names 54762 54763 +0 1 +.names 53893 54763 54764 +11 1 +.names 15043 2413 54765 +11 1 +.names 54770 2413 54766 +1- 1 +-1 1 +.names 54766 54767 +1 1 +.names 54034 54768 +1 1 +.names 54768 54769 +0 1 +.names 15058 54769 54770 +1- 1 +-1 1 +.names 15081 54774 54771 +1- 1 +-1 1 +.names 54771 54772 +1 1 +.names 2413 54773 +1 1 +.names 54773 54774 +0 1 +.names 54767 54775 +0 1 +.names 54772 54776 +0 1 +.names 14886 53914 54777 +1- 1 +-1 1 +.names 54777 54778 +1 1 +.names 54785 54786 54779 +1- 1 +-1 1 +.names 54779 54780 +1 1 +.names 54757 54781 +0 1 +.names 54006 16344 54782 +1- 1 +-1 1 +.names 54782 54783 +1 1 +.names 54783 54784 +0 1 +.names 54781 54784 54785 +1- 1 +-1 1 +.names 54778 54786 +0 1 +.names 54789 54792 54787 +1- 1 +-1 1 +.names 54787 54788 +1 1 +.names 54760 54789 +0 1 +.names 54795 54796 54790 +11 1 +.names 54790 54791 +1 1 +.names 54791 54792 +0 1 +.names 1783 54793 +1 1 +.names 54793 54794 +1 1 +.names 54780 54795 +0 1 +.names 54794 54796 +0 1 +.names 54805 54808 54797 +1- 1 +-1 1 +.names 54797 54798 +1 1 +.names 54812 54813 54799 +1- 1 +-1 1 +.names 54799 54800 +1 1 +.names 54800 54801 +0 1 +.names 2413 54802 +1 1 +.names 54802 54803 +1 1 +.names 54803 54804 +0 1 +.names 54801 54804 54805 +1- 1 +-1 1 +.names 54816 54819 54806 +11 1 +.names 54806 54807 +1 1 +.names 54807 54808 +0 1 +.names 54826 54827 54809 +11 1 +.names 54809 54810 +1 1 +.names 54810 54811 +0 1 +.names 53893 54811 54812 +11 1 +.names 15043 2413 54813 +11 1 +.names 15082 1070 54814 +11 1 +.names 54814 54815 +1 1 +.names 54815 54816 +0 1 +.names 54831 54832 54817 +1- 1 +-1 1 +.names 54817 54818 +1 1 +.names 54818 54819 +0 1 +.names 15055 54823 54820 +1- 1 +-1 1 +.names 54820 54821 +1 1 +.names 2413 54822 +1 1 +.names 54822 54823 +0 1 +.names 54836 3304 54824 +1- 1 +-1 1 +.names 54824 54825 +1 1 +.names 54825 54826 +0 1 +.names 54821 54827 +0 1 +.names 14886 15069 54828 +1- 1 +-1 1 +.names 54828 54829 +1 1 +.names 53845 54830 +1 1 +.names 15073 1762 54831 +11 1 +.names 54829 54832 +0 1 +.names 53959 54833 +1 1 +.names 54833 54834 +0 1 +.names 54830 54835 +0 1 +.names 54834 54835 54836 +1- 1 +-1 1 +.names 54034 54839 54837 +1- 1 +-1 1 +.names 54837 54838 +1 1 +.names 1763 54839 +0 1 +.names 54848 54851 54840 +1- 1 +-1 1 +.names 54840 54841 +1 1 +.names 54855 54856 54842 +1- 1 +-1 1 +.names 54842 54843 +1 1 +.names 54843 54844 +0 1 +.names 2413 54845 +1 1 +.names 54845 54846 +1 1 +.names 54846 54847 +0 1 +.names 54844 54847 54848 +1- 1 +-1 1 +.names 54873 54869 54849 +11 1 +.names 54849 54850 +1 1 +.names 54850 54851 +0 1 +.names 54866 54867 54852 +11 1 +.names 54852 54853 +1 1 +.names 54853 54854 +0 1 +.names 54059 54854 54855 +11 1 +.names 15041 2413 54856 +11 1 +.names 54861 3308 54857 +1- 1 +-1 1 +.names 54857 54858 +1 1 +.names 54034 54859 +1 1 +.names 54859 54860 +0 1 +.names 15078 54860 54861 +1- 1 +-1 1 +.names 15083 54865 54862 +1- 1 +-1 1 +.names 54862 54863 +1 1 +.names 2413 54864 +1 1 +.names 54864 54865 +0 1 +.names 54858 54866 +0 1 +.names 54863 54867 +0 1 +.names 14886 53948 54868 +1- 1 +-1 1 +.names 54868 54869 +1 1 +.names 53874 54872 54870 +1- 1 +-1 1 +.names 54870 54871 +1 1 +.names 1067 54872 +0 1 +.names 54871 54838 54873 +11 1 +.names 53957 54876 54874 +1- 1 +-1 1 +.names 54874 54875 +1 1 +.names 1764 54876 +0 1 +.names 54882 54883 54877 +1- 1 +-1 1 +.names 54877 54878 +1 1 +.names 54890 54891 54879 +11 1 +.names 54879 54880 +1 1 +.names 54880 54881 +0 1 +.names 53932 54881 54882 +11 1 +.names 15079 2413 54883 +11 1 +.names 15082 54887 54884 +1- 1 +-1 1 +.names 54884 54885 +1 1 +.names 2413 54886 +1 1 +.names 54886 54887 +0 1 +.names 54896 54897 54888 +1- 1 +-1 1 +.names 54888 54889 +1 1 +.names 54889 54890 +0 1 +.names 54885 54891 +0 1 +.names 14886 53914 54892 +1- 1 +-1 1 +.names 54892 54893 +1 1 +.names 53957 54894 +1 1 +.names 54894 54895 +0 1 +.names 15058 54895 54896 +1- 1 +-1 1 +.names 782 54897 +0 1 +.names 54904 54905 54898 +1- 1 +-1 1 +.names 54898 54899 +1 1 +.names 54875 54900 +0 1 +.names 53959 16692 54901 +1- 1 +-1 1 +.names 54901 54902 +1 1 +.names 54902 54903 +0 1 +.names 54900 54903 54904 +1- 1 +-1 1 +.names 54893 54905 +0 1 +.names 54908 54911 54906 +1- 1 +-1 1 +.names 54906 54907 +1 1 +.names 54878 54908 +0 1 +.names 54914 54915 54909 +11 1 +.names 54909 54910 +1 1 +.names 54910 54911 +0 1 +.names 1783 54912 +1 1 +.names 54912 54913 +1 1 +.names 54899 54914 +0 1 +.names 54913 54915 +0 1 +.names 54924 54927 54916 +1- 1 +-1 1 +.names 54916 54917 +1 1 +.names 54931 54932 54918 +1- 1 +-1 1 +.names 54918 54919 +1 1 +.names 54919 54920 +0 1 +.names 14886 15069 54921 +1- 1 +-1 1 +.names 54921 54922 +1 1 +.names 54922 54923 +0 1 +.names 54920 54923 54924 +1- 1 +-1 1 +.names 54935 54938 54925 +11 1 +.names 54925 54926 +1 1 +.names 54926 54927 +0 1 +.names 54952 54953 54928 +11 1 +.names 54928 54929 +1 1 +.names 54929 54930 +0 1 +.names 54321 54930 54931 +11 1 +.names 15060 16703 54932 +11 1 +.names 1783 15072 54933 +11 1 +.names 54933 54934 +1 1 +.names 54934 54935 +0 1 +.names 54939 54942 54936 +1- 1 +-1 1 +.names 54936 54937 +1 1 +.names 54937 54938 +0 1 +.names 15052 1765 54939 +11 1 +.names 2413 54940 +1 1 +.names 54940 54941 +1 1 +.names 54941 54942 +0 1 +.names 54947 2413 54943 +1- 1 +-1 1 +.names 54943 54944 +1 1 +.names 2413 54945 +1 1 +.names 54945 54946 +0 1 +.names 15072 54946 54947 +1- 1 +-1 1 +.names 15055 54951 54948 +1- 1 +-1 1 +.names 54948 54949 +1 1 +.names 53957 54950 +1 1 +.names 54950 54951 +0 1 +.names 54944 54952 +0 1 +.names 54949 54953 +0 1 +.names 54962 54965 54954 +1- 1 +-1 1 +.names 54954 54955 +1 1 +.names 54969 54970 54956 +1- 1 +-1 1 +.names 54956 54957 +1 1 +.names 54957 54958 +0 1 +.names 2413 54959 +1 1 +.names 54959 54960 +1 1 +.names 54960 54961 +0 1 +.names 54958 54961 54962 +1- 1 +-1 1 +.names 54989 54983 54963 +11 1 +.names 54963 54964 +1 1 +.names 54964 54965 +0 1 +.names 54980 54981 54966 +11 1 +.names 54966 54967 +1 1 +.names 54967 54968 +0 1 +.names 53932 54968 54969 +11 1 +.names 15079 2413 54970 +11 1 +.names 54975 2413 54971 +1- 1 +-1 1 +.names 54971 54972 +1 1 +.names 53845 54973 +1 1 +.names 54973 54974 +0 1 +.names 15078 54974 54975 +1- 1 +-1 1 +.names 15083 54979 54976 +1- 1 +-1 1 +.names 54976 54977 +1 1 +.names 2413 54978 +1 1 +.names 54978 54979 +0 1 +.names 54972 54980 +0 1 +.names 54977 54981 +0 1 +.names 14886 53948 54982 +1- 1 +-1 1 +.names 54982 54983 +1 1 +.names 53845 54986 54984 +1- 1 +-1 1 +.names 54984 54985 +1 1 +.names 1766 54986 +0 1 +.names 53874 16591 54987 +1- 1 +-1 1 +.names 54987 54988 +1 1 +.names 54988 54985 54989 +11 1 +.names 53804 54992 54990 +1- 1 +-1 1 +.names 54990 54991 +1 1 +.names 1767 54992 +0 1 +.names 14886 15069 54993 +1- 1 +-1 1 +.names 54993 54994 +1 1 +.names 54999 3382 54995 +1- 1 +-1 1 +.names 54995 54996 +1 1 +.names 53804 54997 +1 1 +.names 54997 54998 +0 1 +.names 15055 54998 54999 +1- 1 +-1 1 +.names 15083 55003 55000 +1- 1 +-1 1 +.names 55000 55001 +1 1 +.names 2413 55002 +1 1 +.names 55002 55003 +0 1 +.names 55009 55010 55004 +1- 1 +-1 1 +.names 55004 55005 +1 1 +.names 55011 55012 55006 +11 1 +.names 55006 55007 +1 1 +.names 55007 55008 +0 1 +.names 53932 55008 55009 +11 1 +.names 15079 14886 55010 +11 1 +.names 54996 55011 +0 1 +.names 55001 55012 +0 1 +.names 55019 55020 55013 +1- 1 +-1 1 +.names 55013 55014 +1 1 +.names 53874 55031 55015 +1- 1 +-1 1 +.names 55015 55016 +1 1 +.names 55016 55017 +0 1 +.names 54991 55018 +0 1 +.names 55017 55018 55019 +1- 1 +-1 1 +.names 54994 55020 +0 1 +.names 55023 55026 55021 +11 1 +.names 55021 55022 +1 1 +.names 55014 55023 +0 1 +.names 1783 55024 +1 1 +.names 55024 55025 +1 1 +.names 55025 55026 +0 1 +.names 55029 55030 55027 +1- 1 +-1 1 +.names 55027 55028 +1 1 +.names 55005 55029 +0 1 +.names 55022 55030 +0 1 +.names 1063 55031 +0 1 +.names 55040 55043 55032 +1- 1 +-1 1 +.names 55032 55033 +1 1 +.names 55047 55048 55034 +1- 1 +-1 1 +.names 55034 55035 +1 1 +.names 55035 55036 +0 1 +.names 2413 55037 +1 1 +.names 55037 55038 +1 1 +.names 55038 55039 +0 1 +.names 55036 55039 55040 +1- 1 +-1 1 +.names 55051 55054 55041 +11 1 +.names 55041 55042 +1 1 +.names 55042 55043 +0 1 +.names 55061 55062 55044 +11 1 +.names 55044 55045 +1 1 +.names 55045 55046 +0 1 +.names 53932 55046 55047 +11 1 +.names 15079 2413 55048 +11 1 +.names 15081 1062 55049 +11 1 +.names 55049 55050 +1 1 +.names 55050 55051 +0 1 +.names 55068 55069 55052 +1- 1 +-1 1 +.names 55052 55053 +1 1 +.names 55053 55054 +0 1 +.names 15078 55058 55055 +1- 1 +-1 1 +.names 55055 55056 +1 1 +.names 2413 55057 +1 1 +.names 55057 55058 +0 1 +.names 55067 3316 55059 +1- 1 +-1 1 +.names 55059 55060 +1 1 +.names 55060 55061 +0 1 +.names 55056 55062 +0 1 +.names 14886 53948 55063 +1- 1 +-1 1 +.names 55063 55064 +1 1 +.names 53845 55065 +1 1 +.names 55065 55066 +0 1 +.names 15081 55066 55067 +1- 1 +-1 1 +.names 15073 1768 55068 +11 1 +.names 55064 55069 +0 1 +.names 55072 55073 55070 +1- 1 +-1 1 +.names 55070 55071 +1 1 +.names 15095 55072 +0 1 +.names 53810 55073 +0 1 +.names 55076 55077 55074 +1- 1 +-1 1 +.names 55074 55075 +1 1 +.names 53241 55076 +0 1 +.names 15116 55077 +0 1 +.names 55089 55090 55078 +1- 1 +-1 1 +.names 55078 55079 +1 1 +.names 55079 55080 +0 1 +.names 55075 55081 +0 1 +.names 55080 55081 55082 +1- 1 +-1 1 +.names 55093 55095 55083 +11 1 +.names 55083 55084 +1 1 +.names 55084 55085 +0 1 +.names 55106 55107 55086 +11 1 +.names 55086 55087 +1 1 +.names 55087 55088 +0 1 +.names 2413 55088 55089 +11 1 +.names 1783 2413 55090 +11 1 +.names 15105 55108 55091 +1- 1 +-1 1 +.names 55091 55092 +1 1 +.names 55092 55071 55093 +11 1 +.names 15113 55109 55094 +1- 1 +-1 1 +.names 55094 55095 +1 1 +.names 55100 55101 55096 +1- 1 +-1 1 +.names 55096 55097 +1 1 +.names 55072 55098 +1 1 +.names 55098 55099 +0 1 +.names 15116 55099 55100 +1- 1 +-1 1 +.names 51524 55101 +0 1 +.names 15118 55105 55102 +1- 1 +-1 1 +.names 55102 55103 +1 1 +.names 15113 55104 +1 1 +.names 55104 55105 +0 1 +.names 55097 55106 +0 1 +.names 55103 55107 +0 1 +.names 52100 55108 +0 1 +.names 52668 55109 +0 1 +.names 55112 55077 55110 +1- 1 +-1 1 +.names 55110 55111 +1 1 +.names 53227 55112 +0 1 +.names 55119 55121 55113 +1- 1 +-1 1 +.names 55113 55114 +1 1 +.names 15117 55115 +0 1 +.names 55132 55133 55116 +11 1 +.names 55116 55117 +1 1 +.names 55117 55118 +0 1 +.names 55115 55118 55119 +11 1 +.names 53864 55120 +0 1 +.names 15117 55120 55121 +11 1 +.names 55126 55127 55122 +1- 1 +-1 1 +.names 55122 55123 +1 1 +.names 15113 55124 +1 1 +.names 55124 55125 +0 1 +.names 15127 55125 55126 +1- 1 +-1 1 +.names 51510 55127 +0 1 +.names 15116 55131 55128 +1- 1 +-1 1 +.names 55128 55129 +1 1 +.names 2413 55130 +1 1 +.names 55130 55131 +0 1 +.names 55123 55132 +0 1 +.names 55129 55133 +0 1 +.names 55150 55151 55134 +1- 1 +-1 1 +.names 55134 55135 +1 1 +.names 55114 55136 +0 1 +.names 15113 55139 55137 +1- 1 +-1 1 +.names 55137 55138 +1 1 +.names 52654 55139 +0 1 +.names 2413 55140 +1 1 +.names 55140 55141 +1 1 +.names 55144 55145 55142 +1- 1 +-1 1 +.names 55142 55143 +1 1 +.names 52086 55144 +0 1 +.names 15127 55145 +0 1 +.names 55141 55146 +0 1 +.names 55143 55147 +0 1 +.names 55146 55147 55148 +1- 1 +-1 1 +.names 55138 55149 +0 1 +.names 55148 55149 55150 +1- 1 +-1 1 +.names 55111 55151 +0 1 +.names 55166 55168 55152 +1- 1 +-1 1 +.names 55152 55153 +1 1 +.names 55153 55154 +0 1 +.names 2413 55155 +1 1 +.names 55155 55156 +1 1 +.names 55156 55157 +0 1 +.names 55154 55157 55158 +1- 1 +-1 1 +.names 55173 55175 55159 +11 1 +.names 55159 55160 +1 1 +.names 55160 55161 +0 1 +.names 15087 55162 +0 1 +.names 55182 55183 55163 +11 1 +.names 55163 55164 +1 1 +.names 55164 55165 +0 1 +.names 55162 55165 55166 +11 1 +.names 53207 55167 +0 1 +.names 15087 55167 55168 +11 1 +.names 55115 55192 55169 +1- 1 +-1 1 +.names 55169 55170 +1 1 +.names 15105 55193 55171 +1- 1 +-1 1 +.names 55171 55172 +1 1 +.names 55170 55172 55173 +11 1 +.names 55184 55185 55174 +1- 1 +-1 1 +.names 55174 55175 +1 1 +.names 15118 55179 55176 +1- 1 +-1 1 +.names 55176 55177 +1 1 +.names 2413 55178 +1 1 +.names 55178 55179 +0 1 +.names 55190 55191 55180 +1- 1 +-1 1 +.names 55180 55181 +1 1 +.names 55181 55182 +0 1 +.names 55177 55183 +0 1 +.names 52636 55184 +0 1 +.names 15102 55185 +0 1 +.names 55185 55186 +1 1 +.names 55186 55187 +0 1 +.names 55115 55188 +1 1 +.names 55188 55189 +0 1 +.names 55187 55189 55190 +1- 1 +-1 1 +.names 51492 55191 +0 1 +.names 53882 55192 +0 1 +.names 52068 55193 +0 1 +.names 55208 55210 55194 +1- 1 +-1 1 +.names 55194 55195 +1 1 +.names 55195 55196 +0 1 +.names 2413 55197 +1 1 +.names 55197 55198 +1 1 +.names 55198 55199 +0 1 +.names 55196 55199 55200 +1- 1 +-1 1 +.names 55229 55230 55201 +11 1 +.names 55201 55202 +1 1 +.names 55202 55203 +0 1 +.names 15123 55204 +0 1 +.names 55217 55218 55205 +11 1 +.names 55205 55206 +1 1 +.names 55206 55207 +0 1 +.names 55204 55207 55208 +11 1 +.names 53276 55209 +0 1 +.names 15123 55209 55210 +11 1 +.names 15122 55214 55211 +1- 1 +-1 1 +.names 55211 55212 +1 1 +.names 2413 55213 +1 1 +.names 55213 55214 +0 1 +.names 55237 55238 55215 +1- 1 +-1 1 +.names 55215 55216 +1 1 +.names 55216 55217 +0 1 +.names 55212 55218 +0 1 +.names 55221 55222 55219 +1- 1 +-1 1 +.names 55219 55220 +1 1 +.names 52700 55221 +0 1 +.names 15122 55222 +0 1 +.names 55225 55226 55223 +1- 1 +-1 1 +.names 55223 55224 +1 1 +.names 53921 15096 55225 +11 1 +.names 55220 55226 +0 1 +.names 15126 52132 55227 +11 1 +.names 55227 55228 +1 1 +.names 55228 55229 +0 1 +.names 55224 55230 +0 1 +.names 15096 55231 +0 1 +.names 55231 55232 +1 1 +.names 15126 55233 +0 1 +.names 55233 55234 +1 1 +.names 55234 55235 +0 1 +.names 55232 55236 +0 1 +.names 55235 55236 55237 +1- 1 +-1 1 +.names 51557 55238 +0 1 +.names 55231 55241 55239 +1- 1 +-1 1 +.names 55239 55240 +1 1 +.names 54003 55241 +0 1 +.names 55244 15113 55242 +1- 1 +-1 1 +.names 55242 55243 +1 1 +.names 52719 55244 +0 1 +.names 15125 55248 55245 +1- 1 +-1 1 +.names 55245 55246 +1 1 +.names 2413 55247 +1 1 +.names 55247 55248 +0 1 +.names 55254 55256 55249 +1- 1 +-1 1 +.names 55249 55250 +1 1 +.names 55259 55260 55251 +11 1 +.names 55251 55252 +1 1 +.names 55252 55253 +0 1 +.names 55204 55253 55254 +11 1 +.names 53297 55255 +0 1 +.names 15123 55255 55256 +11 1 +.names 55263 55264 55257 +1- 1 +-1 1 +.names 55257 55258 +1 1 +.names 55258 55259 +0 1 +.names 55246 55260 +0 1 +.names 55231 55261 +1 1 +.names 55261 55262 +0 1 +.names 15099 55262 55263 +1- 1 +-1 1 +.names 51577 55264 +0 1 +.names 55271 55272 55265 +1- 1 +-1 1 +.names 55265 55266 +1 1 +.names 55240 55267 +0 1 +.names 55281 55282 55268 +1- 1 +-1 1 +.names 55268 55269 +1 1 +.names 55269 55270 +0 1 +.names 55267 55270 55271 +1- 1 +-1 1 +.names 55243 55272 +0 1 +.names 55275 55278 55273 +11 1 +.names 55273 55274 +1 1 +.names 55266 55275 +0 1 +.names 1783 55276 +1 1 +.names 55276 55277 +1 1 +.names 55277 55278 +0 1 +.names 55250 55279 +0 1 +.names 55274 55280 +0 1 +.names 15125 55281 +0 1 +.names 52151 55282 +0 1 +.names 55297 55299 55283 +1- 1 +-1 1 +.names 55283 55284 +1 1 +.names 55284 55285 +0 1 +.names 2413 55286 +1 1 +.names 55286 55287 +1 1 +.names 55287 55288 +0 1 +.names 55285 55288 55289 +1- 1 +-1 1 +.names 55322 55317 55290 +11 1 +.names 55290 55291 +1 1 +.names 55291 55292 +0 1 +.names 15112 55293 +0 1 +.names 55311 55312 55294 +11 1 +.names 55294 55295 +1 1 +.names 55295 55296 +0 1 +.names 55293 55296 55297 +11 1 +.names 52738 55298 +0 1 +.names 15112 55298 55299 +11 1 +.names 15116 55302 55300 +1- 1 +-1 1 +.names 55300 55301 +1 1 +.names 51596 55302 +0 1 +.names 55307 55309 55303 +1- 1 +-1 1 +.names 55303 55304 +1 1 +.names 55310 2413 55305 +11 1 +.names 55305 55306 +1 1 +.names 55306 55307 +0 1 +.names 55145 55308 +1 1 +.names 55308 55309 +0 1 +.names 15097 55310 +0 1 +.names 55304 55311 +0 1 +.names 55301 55312 +0 1 +.names 55310 55315 55313 +1- 1 +-1 1 +.names 55313 55314 +1 1 +.names 54008 55315 +0 1 +.names 55318 55077 55316 +1- 1 +-1 1 +.names 55316 55317 +1 1 +.names 53318 55318 +0 1 +.names 55145 55321 55319 +1- 1 +-1 1 +.names 55319 55320 +1 1 +.names 52170 55321 +0 1 +.names 55320 55314 55322 +11 1 +.names 55337 55339 55323 +1- 1 +-1 1 +.names 55323 55324 +1 1 +.names 55324 55325 +0 1 +.names 2413 55326 +1 1 +.names 55326 55327 +1 1 +.names 55327 55328 +0 1 +.names 55325 55328 55329 +1- 1 +-1 1 +.names 55360 55361 55330 +11 1 +.names 55330 55331 +1 1 +.names 55331 55332 +0 1 +.names 15085 55333 +0 1 +.names 55356 55357 55334 +11 1 +.names 55334 55335 +1 1 +.names 55335 55336 +0 1 +.names 55333 55336 55337 +11 1 +.names 53325 55338 +0 1 +.names 15085 55338 55339 +11 1 +.names 55342 55345 55340 +1- 1 +-1 1 +.names 55340 55341 +1 1 +.names 15095 54048 55342 +11 1 +.names 55362 55233 55343 +1- 1 +-1 1 +.names 55343 55344 +1 1 +.names 55344 55345 +0 1 +.names 55350 55351 55346 +1- 1 +-1 1 +.names 55346 55347 +1 1 +.names 55072 55348 +1 1 +.names 55348 55349 +0 1 +.names 15121 55349 55350 +1- 1 +-1 1 +.names 51603 55351 +0 1 +.names 15126 55355 55352 +1- 1 +-1 1 +.names 55352 55353 +1 1 +.names 2413 55354 +1 1 +.names 55354 55355 +0 1 +.names 55347 55356 +0 1 +.names 55353 55357 +0 1 +.names 52745 15121 55358 +11 1 +.names 55358 55359 +1 1 +.names 55359 55360 +0 1 +.names 55341 55361 +0 1 +.names 52177 55362 +0 1 +.names 55376 55378 55363 +1- 1 +-1 1 +.names 55363 55364 +1 1 +.names 55364 55365 +0 1 +.names 2413 55366 +1 1 +.names 55366 55367 +1 1 +.names 55367 55368 +0 1 +.names 55365 55368 55369 +1- 1 +-1 1 +.names 55383 55385 55370 +11 1 +.names 55370 55371 +1 1 +.names 55371 55372 +0 1 +.names 55396 55397 55373 +11 1 +.names 55373 55374 +1 1 +.names 55374 55375 +0 1 +.names 55204 55375 55376 +11 1 +.names 53349 55377 +0 1 +.names 15123 55377 55378 +11 1 +.names 55115 55400 55379 +1- 1 +-1 1 +.names 55379 55380 +1 1 +.names 15105 55401 55381 +1- 1 +-1 1 +.names 55381 55382 +1 1 +.names 55380 55382 55383 +11 1 +.names 55398 55399 55384 +1- 1 +-1 1 +.names 55384 55385 +1 1 +.names 55390 55391 55386 +1- 1 +-1 1 +.names 55386 55387 +1 1 +.names 55115 55388 +1 1 +.names 55388 55389 +0 1 +.names 15121 55389 55390 +1- 1 +-1 1 +.names 51625 55391 +0 1 +.names 15118 55395 55392 +1- 1 +-1 1 +.names 55392 55393 +1 1 +.names 2413 55394 +1 1 +.names 55394 55395 +0 1 +.names 55393 55396 +0 1 +.names 55387 55397 +0 1 +.names 52768 55398 +0 1 +.names 15121 55399 +0 1 +.names 54088 55400 +0 1 +.names 52199 55401 +0 1 +.names 55407 55409 55402 +1- 1 +-1 1 +.names 55402 55403 +1 1 +.names 55416 55417 55404 +11 1 +.names 55404 55405 +1 1 +.names 55405 55406 +0 1 +.names 55204 55406 55407 +11 1 +.names 53363 55408 +0 1 +.names 15123 55408 55409 +11 1 +.names 1783 55413 55410 +1- 1 +-1 1 +.names 55410 55411 +1 1 +.names 55233 55412 +1 1 +.names 55412 55413 +0 1 +.names 55423 55424 55414 +1- 1 +-1 1 +.names 55414 55415 +1 1 +.names 55415 55416 +0 1 +.names 55411 55417 +0 1 +.names 55420 55185 55418 +1- 1 +-1 1 +.names 55418 55419 +1 1 +.names 52781 55420 +0 1 +.names 55115 55421 +1 1 +.names 55421 55422 +0 1 +.names 15102 55422 55423 +1- 1 +-1 1 +.names 51638 55424 +0 1 +.names 55433 55434 55425 +1- 1 +-1 1 +.names 55425 55426 +1 1 +.names 55115 55443 55427 +1- 1 +-1 1 +.names 55427 55428 +1 1 +.names 55428 55429 +0 1 +.names 55233 55444 55430 +1- 1 +-1 1 +.names 55430 55431 +1 1 +.names 55431 55432 +0 1 +.names 55429 55432 55433 +1- 1 +-1 1 +.names 55419 55434 +0 1 +.names 55403 55435 +0 1 +.names 55441 55442 55436 +11 1 +.names 55436 55437 +1 1 +.names 55437 55438 +0 1 +.names 1783 55439 +1 1 +.names 55439 55440 +1 1 +.names 55426 55441 +0 1 +.names 55440 55442 +0 1 +.names 54156 55443 +0 1 +.names 52212 55444 +0 1 +.names 55458 55460 55445 +1- 1 +-1 1 +.names 55445 55446 +1 1 +.names 55446 55447 +0 1 +.names 2413 55448 +1 1 +.names 55448 55449 +1 1 +.names 55449 55450 +0 1 +.names 55447 55450 55451 +1- 1 +-1 1 +.names 55482 55474 55452 +11 1 +.names 55452 55453 +1 1 +.names 55453 55454 +0 1 +.names 55471 55472 55455 +11 1 +.names 55455 55456 +1 1 +.names 55456 55457 +0 1 +.names 55204 55457 55458 +11 1 +.names 53396 55459 +0 1 +.names 15123 55459 55460 +11 1 +.names 55465 55466 55461 +1- 1 +-1 1 +.names 55461 55462 +1 1 +.names 55072 55463 +1 1 +.names 55463 55464 +0 1 +.names 15121 55464 55465 +1- 1 +-1 1 +.names 51670 55466 +0 1 +.names 15127 55470 55467 +1- 1 +-1 1 +.names 55467 55468 +1 1 +.names 2413 55469 +1 1 +.names 55469 55470 +0 1 +.names 55462 55471 +0 1 +.names 55468 55472 +0 1 +.names 55475 55399 55473 +1- 1 +-1 1 +.names 55473 55474 +1 1 +.names 52811 55475 +0 1 +.names 55072 55478 55476 +1- 1 +-1 1 +.names 55476 55477 +1 1 +.names 54168 55478 +0 1 +.names 55145 55481 55479 +1- 1 +-1 1 +.names 55479 55480 +1 1 +.names 52242 55481 +0 1 +.names 55480 55477 55482 +11 1 +.names 55496 55498 55483 +1- 1 +-1 1 +.names 55483 55484 +1 1 +.names 55484 55485 +0 1 +.names 2413 55486 +1 1 +.names 55486 55487 +1 1 +.names 55487 55488 +0 1 +.names 55485 55488 55489 +1- 1 +-1 1 +.names 55503 55505 55490 +11 1 +.names 55490 55491 +1 1 +.names 55491 55492 +0 1 +.names 55516 55517 55493 +11 1 +.names 55493 55494 +1 1 +.names 55494 55495 +0 1 +.names 55333 55495 55496 +11 1 +.names 53409 55497 +0 1 +.names 15085 55497 55498 +11 1 +.names 55072 55520 55499 +1- 1 +-1 1 +.names 55499 55500 +1 1 +.names 15105 55519 55501 +1- 1 +-1 1 +.names 55501 55502 +1 1 +.names 55500 55502 55503 +11 1 +.names 55518 15113 55504 +1- 1 +-1 1 +.names 55504 55505 +1 1 +.names 15099 55508 55506 +1- 1 +-1 1 +.names 55506 55507 +1 1 +.names 51683 55508 +0 1 +.names 55513 55515 55509 +1- 1 +-1 1 +.names 55509 55510 +1 1 +.names 55072 2413 55511 +11 1 +.names 55511 55512 +1 1 +.names 55512 55513 +0 1 +.names 15105 55514 +1 1 +.names 55514 55515 +0 1 +.names 55510 55516 +0 1 +.names 55507 55517 +0 1 +.names 52823 55518 +0 1 +.names 52255 55519 +0 1 +.names 54205 55520 +0 1 +.names 55523 55072 55521 +1- 1 +-1 1 +.names 55521 55522 +1 1 +.names 54245 55523 +0 1 +.names 55537 55539 55524 +1- 1 +-1 1 +.names 55524 55525 +1 1 +.names 55525 55526 +0 1 +.names 2413 55527 +1 1 +.names 55527 55528 +1 1 +.names 55528 55529 +0 1 +.names 55526 55529 55530 +1- 1 +-1 1 +.names 55558 55559 55531 +11 1 +.names 55531 55532 +1 1 +.names 55532 55533 +0 1 +.names 55554 55555 55534 +11 1 +.names 55534 55535 +1 1 +.names 55535 55536 +0 1 +.names 55333 55536 55537 +11 1 +.names 53421 55538 +0 1 +.names 15085 55538 55539 +11 1 +.names 55542 55543 55540 +1- 1 +-1 1 +.names 55540 55541 +1 1 +.names 15126 52267 55542 +11 1 +.names 55522 55543 +0 1 +.names 55548 55549 55544 +1- 1 +-1 1 +.names 55544 55545 +1 1 +.names 55072 55546 +1 1 +.names 55546 55547 +0 1 +.names 15121 55547 55548 +1- 1 +-1 1 +.names 51695 55549 +0 1 +.names 15126 55553 55550 +1- 1 +-1 1 +.names 55550 55551 +1 1 +.names 2413 55552 +1 1 +.names 55552 55553 +0 1 +.names 55545 55554 +0 1 +.names 55551 55555 +0 1 +.names 52835 15121 55556 +11 1 +.names 55556 55557 +1 1 +.names 55557 55558 +0 1 +.names 55541 55559 +0 1 +.names 55573 55575 55560 +1- 1 +-1 1 +.names 55560 55561 +1 1 +.names 55561 55562 +0 1 +.names 2413 55563 +1 1 +.names 55563 55564 +1 1 +.names 55564 55565 +0 1 +.names 55562 55565 55566 +1- 1 +-1 1 +.names 55597 55598 55567 +11 1 +.names 55567 55568 +1 1 +.names 55568 55569 +0 1 +.names 55586 55587 55570 +11 1 +.names 55570 55571 +1 1 +.names 55571 55572 +0 1 +.names 55162 55572 55573 +11 1 +.names 53447 55574 +0 1 +.names 15087 55574 55575 +11 1 +.names 55580 55581 55576 +1- 1 +-1 1 +.names 55576 55577 +1 1 +.names 55231 55578 +1 1 +.names 55578 55579 +0 1 +.names 15125 55579 55580 +1- 1 +-1 1 +.names 51719 55581 +0 1 +.names 15099 55585 55582 +1- 1 +-1 1 +.names 55582 55583 +1 1 +.names 2413 55584 +1 1 +.names 55584 55585 +0 1 +.names 55577 55586 +0 1 +.names 55583 55587 +0 1 +.names 55590 15113 55588 +1- 1 +-1 1 +.names 55588 55589 +1 1 +.names 52858 55590 +0 1 +.names 55593 55594 55591 +1- 1 +-1 1 +.names 55591 55592 +1 1 +.names 15096 54281 55593 +11 1 +.names 55589 55594 +0 1 +.names 15125 52290 55595 +11 1 +.names 55595 55596 +1 1 +.names 55596 55597 +0 1 +.names 55592 55598 +0 1 +.names 55605 55607 55599 +1- 1 +-1 1 +.names 55599 55600 +1 1 +.names 15104 55601 +0 1 +.names 55618 55619 55602 +11 1 +.names 55602 55603 +1 1 +.names 55603 55604 +0 1 +.names 55601 55604 55605 +11 1 +.names 52366 55606 +0 1 +.names 15104 55606 55607 +11 1 +.names 15116 55610 55608 +1- 1 +-1 1 +.names 55608 55609 +1 1 +.names 51796 55610 +0 1 +.names 55615 55617 55611 +1- 1 +-1 1 +.names 55611 55612 +1 1 +.names 55231 2413 55613 +11 1 +.names 55613 55614 +1 1 +.names 55614 55615 +0 1 +.names 15113 55616 +1 1 +.names 55616 55617 +0 1 +.names 55612 55618 +0 1 +.names 55609 55619 +0 1 +.names 55634 55637 55620 +1- 1 +-1 1 +.names 55620 55621 +1 1 +.names 55600 55622 +0 1 +.names 55625 15113 55623 +1- 1 +-1 1 +.names 55623 55624 +1 1 +.names 52934 55625 +0 1 +.names 55624 55626 +0 1 +.names 55638 55077 55627 +1- 1 +-1 1 +.names 55627 55628 +1 1 +.names 55628 55629 +0 1 +.names 55626 55629 55630 +1- 1 +-1 1 +.names 55639 55231 55631 +1- 1 +-1 1 +.names 55631 55632 +1 1 +.names 55632 55633 +0 1 +.names 55630 55633 55634 +1- 1 +-1 1 +.names 2413 55635 +1 1 +.names 55635 55636 +1 1 +.names 55636 55637 +0 1 +.names 53528 55638 +0 1 +.names 54340 55639 +0 1 +.names 55645 55647 55640 +1- 1 +-1 1 +.names 55640 55641 +1 1 +.names 55658 55659 55642 +11 1 +.names 55642 55643 +1 1 +.names 55643 55644 +0 1 +.names 55333 55644 55645 +11 1 +.names 53495 55646 +0 1 +.names 15085 55646 55647 +11 1 +.names 55652 55653 55648 +1- 1 +-1 1 +.names 55648 55649 +1 1 +.names 55231 55650 +1 1 +.names 55650 55651 +0 1 +.names 15102 55651 55652 +1- 1 +-1 1 +.names 51765 55653 +0 1 +.names 15118 55657 55654 +1- 1 +-1 1 +.names 55654 55655 +1 1 +.names 2413 55656 +1 1 +.names 55656 55657 +0 1 +.names 55649 55658 +0 1 +.names 55655 55659 +0 1 +.names 15105 55662 55660 +1- 1 +-1 1 +.names 55660 55661 +1 1 +.names 52336 55662 +0 1 +.names 55665 55185 55663 +1- 1 +-1 1 +.names 55663 55664 +1 1 +.names 52904 55665 +0 1 +.names 55672 55673 55666 +1- 1 +-1 1 +.names 55666 55667 +1 1 +.names 55661 55668 +0 1 +.names 55231 55682 55669 +1- 1 +-1 1 +.names 55669 55670 +1 1 +.names 55670 55671 +0 1 +.names 55668 55671 55672 +1- 1 +-1 1 +.names 55664 55673 +0 1 +.names 55641 55674 +0 1 +.names 55678 55681 55675 +11 1 +.names 55675 55676 +1 1 +.names 55676 55677 +0 1 +.names 55667 55678 +0 1 +.names 1783 55679 +1 1 +.names 55679 55680 +1 1 +.names 55680 55681 +0 1 +.names 54390 55682 +0 1 +.names 55696 55698 55683 +1- 1 +-1 1 +.names 55683 55684 +1 1 +.names 55684 55685 +0 1 +.names 2413 55686 +1 1 +.names 55686 55687 +1 1 +.names 55687 55688 +0 1 +.names 55685 55688 55689 +1- 1 +-1 1 +.names 55701 55704 55690 +11 1 +.names 55690 55691 +1 1 +.names 55691 55692 +0 1 +.names 55711 55712 55693 +11 1 +.names 55693 55694 +1 1 +.names 55694 55695 +0 1 +.names 55333 55695 55696 +11 1 +.names 53465 55697 +0 1 +.names 15085 55697 55698 +11 1 +.names 55717 52307 55699 +11 1 +.names 55699 55700 +1 1 +.names 55700 55701 +0 1 +.names 55719 55720 55702 +1- 1 +-1 1 +.names 55702 55703 +1 1 +.names 55703 55704 +0 1 +.names 15099 55708 55705 +1- 1 +-1 1 +.names 55705 55706 +1 1 +.names 2413 55707 +1 1 +.names 55707 55708 +0 1 +.names 55723 55724 55709 +1- 1 +-1 1 +.names 55709 55710 +1 1 +.names 55710 55711 +0 1 +.names 55706 55712 +0 1 +.names 55715 15113 55713 +1- 1 +-1 1 +.names 55713 55714 +1 1 +.names 52875 55715 +0 1 +.names 55721 55716 +0 1 +.names 55716 55717 +1 1 +.names 55310 55718 +1 1 +.names 15097 54401 55719 +11 1 +.names 55714 55720 +0 1 +.names 55145 55721 +1 1 +.names 55718 55722 +0 1 +.names 55716 55722 55723 +1- 1 +-1 1 +.names 51736 55724 +0 1 +.names 55727 55115 55725 +1- 1 +-1 1 +.names 55725 55726 +1 1 +.names 54445 55727 +0 1 +.names 55741 55743 55728 +1- 1 +-1 1 +.names 55728 55729 +1 1 +.names 55729 55730 +0 1 +.names 2413 55731 +1 1 +.names 55731 55732 +1 1 +.names 55732 55733 +0 1 +.names 55730 55733 55734 +1- 1 +-1 1 +.names 55746 55749 55735 +11 1 +.names 55735 55736 +1 1 +.names 55736 55737 +0 1 +.names 55754 55757 55738 +11 1 +.names 55738 55739 +1 1 +.names 55739 55740 +0 1 +.names 55162 55740 55741 +11 1 +.names 53482 55742 +0 1 +.names 15087 55742 55743 +11 1 +.names 55759 55744 +0 1 +.names 55744 55745 +1 1 +.names 55745 55746 +0 1 +.names 55767 55768 55747 +1- 1 +-1 1 +.names 55747 55748 +1 1 +.names 55748 55749 +0 1 +.names 15126 55753 55750 +1- 1 +-1 1 +.names 55750 55751 +1 1 +.names 2413 55752 +1 1 +.names 55752 55753 +0 1 +.names 55751 55754 +0 1 +.names 55765 55766 55755 +1- 1 +-1 1 +.names 55755 55756 +1 1 +.names 55756 55757 +0 1 +.names 55760 55185 55758 +1- 1 +-1 1 +.names 55758 55759 +1 1 +.names 52892 55760 +0 1 +.names 55185 55761 +1 1 +.names 55761 55762 +0 1 +.names 55115 55763 +1 1 +.names 55763 55764 +0 1 +.names 55762 55764 55765 +1- 1 +-1 1 +.names 51753 55766 +0 1 +.names 15126 52324 55767 +11 1 +.names 55726 55768 +0 1 +.names 55231 55771 55769 +1- 1 +-1 1 +.names 55769 55770 +1 1 +.names 54516 55771 +0 1 +.names 55777 55779 55772 +1- 1 +-1 1 +.names 55772 55773 +1 1 +.names 55790 55791 55774 +11 1 +.names 55774 55775 +1 1 +.names 55775 55776 +0 1 +.names 55204 55776 55777 +11 1 +.names 53541 55778 +0 1 +.names 15123 55778 55779 +11 1 +.names 55784 55785 55780 +1- 1 +-1 1 +.names 55780 55781 +1 1 +.names 55231 55782 +1 1 +.names 55782 55783 +0 1 +.names 15102 55783 55784 +1- 1 +-1 1 +.names 51808 55785 +0 1 +.names 15118 55789 55786 +1- 1 +-1 1 +.names 55786 55787 +1 1 +.names 2413 55788 +1 1 +.names 55788 55789 +0 1 +.names 55781 55790 +0 1 +.names 55787 55791 +0 1 +.names 55794 55185 55792 +1- 1 +-1 1 +.names 55792 55793 +1 1 +.names 52946 55794 +0 1 +.names 55801 55802 55795 +1- 1 +-1 1 +.names 55795 55796 +1 1 +.names 55770 55797 +0 1 +.names 15105 55811 55798 +1- 1 +-1 1 +.names 55798 55799 +1 1 +.names 55799 55800 +0 1 +.names 55797 55800 55801 +1- 1 +-1 1 +.names 55793 55802 +0 1 +.names 55773 55803 +0 1 +.names 55809 55810 55804 +11 1 +.names 55804 55805 +1 1 +.names 55805 55806 +0 1 +.names 1783 55807 +1 1 +.names 55807 55808 +1 1 +.names 55796 55809 +0 1 +.names 55808 55810 +0 1 +.names 52378 55811 +0 1 +.names 55825 55827 55812 +1- 1 +-1 1 +.names 55812 55813 +1 1 +.names 55813 55814 +0 1 +.names 2413 55815 +1 1 +.names 55815 55816 +1 1 +.names 55816 55817 +0 1 +.names 55814 55817 55818 +1- 1 +-1 1 +.names 55849 55841 55819 +11 1 +.names 55819 55820 +1 1 +.names 55820 55821 +0 1 +.names 55838 55839 55822 +11 1 +.names 55822 55823 +1 1 +.names 55823 55824 +0 1 +.names 55333 55824 55825 +11 1 +.names 53558 55826 +0 1 +.names 15085 55826 55827 +11 1 +.names 55832 55833 55828 +1- 1 +-1 1 +.names 55828 55829 +1 1 +.names 55310 55830 +1 1 +.names 55830 55831 +0 1 +.names 15122 55831 55832 +1- 1 +-1 1 +.names 51825 55833 +0 1 +.names 15127 55837 55834 +1- 1 +-1 1 +.names 55834 55835 +1 1 +.names 2413 55836 +1 1 +.names 55836 55837 +0 1 +.names 55829 55838 +0 1 +.names 55835 55839 +0 1 +.names 55842 55222 55840 +1- 1 +-1 1 +.names 55840 55841 +1 1 +.names 52963 55842 +0 1 +.names 55310 55845 55843 +1- 1 +-1 1 +.names 55843 55844 +1 1 +.names 54527 55845 +0 1 +.names 55145 55848 55846 +1- 1 +-1 1 +.names 55846 55847 +1 1 +.names 52395 55848 +0 1 +.names 55847 55844 55849 +11 1 +.names 55310 55852 55850 +1- 1 +-1 1 +.names 55850 55851 +1 1 +.names 54567 55852 +0 1 +.names 55866 55868 55853 +1- 1 +-1 1 +.names 55853 55854 +1 1 +.names 55854 55855 +0 1 +.names 2413 55856 +1 1 +.names 55856 55857 +1 1 +.names 55857 55858 +0 1 +.names 55855 55858 55859 +1- 1 +-1 1 +.names 55871 55873 55860 +11 1 +.names 55860 55861 +1 1 +.names 55861 55862 +0 1 +.names 55884 55885 55863 +11 1 +.names 55863 55864 +1 1 +.names 55864 55865 +0 1 +.names 55162 55865 55866 +11 1 +.names 53577 55867 +0 1 +.names 15087 55867 55868 +11 1 +.names 55281 55887 55869 +1- 1 +-1 1 +.names 55869 55870 +1 1 +.names 55851 55870 55871 +11 1 +.names 55886 55222 55872 +1- 1 +-1 1 +.names 55872 55873 +1 1 +.names 55878 55879 55874 +1- 1 +-1 1 +.names 55874 55875 +1 1 +.names 55310 55876 +1 1 +.names 55876 55877 +0 1 +.names 15122 55877 55878 +1- 1 +-1 1 +.names 51842 55879 +0 1 +.names 15125 55883 55880 +1- 1 +-1 1 +.names 55880 55881 +1 1 +.names 2413 55882 +1 1 +.names 55882 55883 +0 1 +.names 55875 55884 +0 1 +.names 55881 55885 +0 1 +.names 52981 55886 +0 1 +.names 52412 55887 +0 1 +.names 55901 55903 55888 +1- 1 +-1 1 +.names 55888 55889 +1 1 +.names 55889 55890 +0 1 +.names 2413 55891 +1 1 +.names 55891 55892 +1 1 +.names 55892 55893 +0 1 +.names 55890 55893 55894 +1- 1 +-1 1 +.names 55908 55910 55895 +11 1 +.names 55895 55896 +1 1 +.names 55896 55897 +0 1 +.names 55921 55922 55898 +11 1 +.names 55898 55899 +1 1 +.names 55899 55900 +0 1 +.names 55204 55900 55901 +11 1 +.names 53594 55902 +0 1 +.names 15123 55902 55903 +11 1 +.names 55310 55925 55904 +1- 1 +-1 1 +.names 55904 55905 +1 1 +.names 55281 55924 55906 +1- 1 +-1 1 +.names 55906 55907 +1 1 +.names 55905 55907 55908 +11 1 +.names 55923 55399 55909 +1- 1 +-1 1 +.names 55909 55910 +1 1 +.names 55915 55916 55911 +1- 1 +-1 1 +.names 55911 55912 +1 1 +.names 55310 55913 +1 1 +.names 55913 55914 +0 1 +.names 15121 55914 55915 +1- 1 +-1 1 +.names 51859 55916 +0 1 +.names 15125 55920 55917 +1- 1 +-1 1 +.names 55917 55918 +1 1 +.names 2413 55919 +1 1 +.names 55919 55920 +0 1 +.names 55912 55921 +0 1 +.names 55918 55922 +0 1 +.names 52998 55923 +0 1 +.names 52429 55924 +0 1 +.names 54602 55925 +0 1 +.names 55310 55928 55926 +1- 1 +-1 1 +.names 55926 55927 +1 1 +.names 54670 55928 +0 1 +.names 55934 55936 55929 +1- 1 +-1 1 +.names 55929 55930 +1 1 +.names 55947 55948 55931 +11 1 +.names 55931 55932 +1 1 +.names 55932 55933 +0 1 +.names 55204 55933 55934 +11 1 +.names 53612 55935 +0 1 +.names 15123 55935 55936 +11 1 +.names 55941 55942 55937 +1- 1 +-1 1 +.names 55937 55938 +1 1 +.names 55310 55939 +1 1 +.names 55939 55940 +0 1 +.names 15102 55940 55941 +1- 1 +-1 1 +.names 51876 55942 +0 1 +.names 15125 55946 55943 +1- 1 +-1 1 +.names 55943 55944 +1 1 +.names 2413 55945 +1 1 +.names 55945 55946 +0 1 +.names 55938 55947 +0 1 +.names 55944 55948 +0 1 +.names 55951 55185 55949 +1- 1 +-1 1 +.names 55949 55950 +1 1 +.names 53015 55951 +0 1 +.names 55958 55959 55952 +1- 1 +-1 1 +.names 55952 55953 +1 1 +.names 55927 55954 +0 1 +.names 55281 55968 55955 +1- 1 +-1 1 +.names 55955 55956 +1 1 +.names 55956 55957 +0 1 +.names 55954 55957 55958 +1- 1 +-1 1 +.names 55950 55959 +0 1 +.names 55930 55960 +0 1 +.names 55966 55967 55961 +11 1 +.names 55961 55962 +1 1 +.names 55962 55963 +0 1 +.names 1783 55964 +1 1 +.names 55964 55965 +1 1 +.names 55953 55966 +0 1 +.names 55965 55967 +0 1 +.names 52446 55968 +0 1 +.names 55982 55984 55969 +1- 1 +-1 1 +.names 55969 55970 +1 1 +.names 55970 55971 +0 1 +.names 2413 55972 +1 1 +.names 55972 55973 +1 1 +.names 55973 55974 +0 1 +.names 55971 55974 55975 +1- 1 +-1 1 +.names 55989 55991 55976 +11 1 +.names 55976 55977 +1 1 +.names 55977 55978 +0 1 +.names 56002 56003 55979 +11 1 +.names 55979 55980 +1 1 +.names 55980 55981 +0 1 +.names 55204 55981 55982 +11 1 +.names 53625 55983 +0 1 +.names 15123 55983 55984 +11 1 +.names 15105 56004 55985 +1- 1 +-1 1 +.names 55985 55986 +1 1 +.names 55072 56006 55987 +1- 1 +-1 1 +.names 55987 55988 +1 1 +.names 55986 55988 55989 +11 1 +.names 56005 55399 55990 +1- 1 +-1 1 +.names 55990 55991 +1 1 +.names 55996 55997 55992 +1- 1 +-1 1 +.names 55992 55993 +1 1 +.names 55072 55994 +1 1 +.names 55994 55995 +0 1 +.names 15121 55995 55996 +1- 1 +-1 1 +.names 51888 55997 +0 1 +.names 1783 56001 55998 +1- 1 +-1 1 +.names 55998 55999 +1 1 +.names 15105 56000 +1 1 +.names 56000 56001 +0 1 +.names 55993 56002 +0 1 +.names 55999 56003 +0 1 +.names 52458 56004 +0 1 +.names 53027 56005 +0 1 +.names 54680 56006 +0 1 +.names 56009 55072 56007 +1- 1 +-1 1 +.names 56007 56008 +1 1 +.names 54719 56009 +0 1 +.names 56023 56025 56010 +1- 1 +-1 1 +.names 56010 56011 +1 1 +.names 56011 56012 +0 1 +.names 2413 56013 +1 1 +.names 56013 56014 +1 1 +.names 56014 56015 +0 1 +.names 56012 56015 56016 +1- 1 +-1 1 +.names 56028 56031 56017 +11 1 +.names 56017 56018 +1 1 +.names 56018 56019 +0 1 +.names 56042 56043 56020 +11 1 +.names 56020 56021 +1 1 +.names 56021 56022 +0 1 +.names 55162 56022 56023 +11 1 +.names 53648 56024 +0 1 +.names 15087 56024 56025 +11 1 +.names 56047 56026 +0 1 +.names 56026 56027 +1 1 +.names 56027 56028 +0 1 +.names 56044 56045 56029 +1- 1 +-1 1 +.names 56029 56030 +1 1 +.names 56030 56031 +0 1 +.names 56036 56037 56032 +1- 1 +-1 1 +.names 56032 56033 +1 1 +.names 55072 56034 +1 1 +.names 56034 56035 +0 1 +.names 15122 56035 56036 +1- 1 +-1 1 +.names 51910 56037 +0 1 +.names 15118 56041 56038 +1- 1 +-1 1 +.names 56038 56039 +1 1 +.names 2413 56040 +1 1 +.names 56040 56041 +0 1 +.names 56033 56042 +0 1 +.names 56039 56043 +0 1 +.names 15118 52480 56044 +11 1 +.names 56008 56045 +0 1 +.names 56048 55222 56046 +1- 1 +-1 1 +.names 56046 56047 +1 1 +.names 53049 56048 +0 1 +.names 55310 56051 56049 +1- 1 +-1 1 +.names 56049 56050 +1 1 +.names 54788 56051 +0 1 +.names 56057 56059 56052 +1- 1 +-1 1 +.names 56052 56053 +1 1 +.names 56070 56071 56054 +11 1 +.names 56054 56055 +1 1 +.names 56055 56056 +0 1 +.names 55162 56056 56057 +11 1 +.names 53684 56058 +0 1 +.names 15087 56058 56059 +11 1 +.names 56064 56065 56060 +1- 1 +-1 1 +.names 56060 56061 +1 1 +.names 55310 56062 +1 1 +.names 56062 56063 +0 1 +.names 15102 56063 56064 +1- 1 +-1 1 +.names 51945 56065 +0 1 +.names 15125 56069 56066 +1- 1 +-1 1 +.names 56066 56067 +1 1 +.names 2413 56068 +1 1 +.names 56068 56069 +0 1 +.names 56061 56070 +0 1 +.names 56067 56071 +0 1 +.names 56074 55185 56072 +1- 1 +-1 1 +.names 56072 56073 +1 1 +.names 53083 56074 +0 1 +.names 56081 56082 56075 +1- 1 +-1 1 +.names 56075 56076 +1 1 +.names 56050 56077 +0 1 +.names 55281 56091 56078 +1- 1 +-1 1 +.names 56078 56079 +1 1 +.names 56079 56080 +0 1 +.names 56077 56080 56081 +1- 1 +-1 1 +.names 56073 56082 +0 1 +.names 56053 56083 +0 1 +.names 56089 56090 56084 +11 1 +.names 56084 56085 +1 1 +.names 56085 56086 +0 1 +.names 1783 56087 +1 1 +.names 56087 56088 +1 1 +.names 56076 56089 +0 1 +.names 56088 56090 +0 1 +.names 52514 56091 +0 1 +.names 56105 56107 56092 +1- 1 +-1 1 +.names 56092 56093 +1 1 +.names 56093 56094 +0 1 +.names 2413 56095 +1 1 +.names 56095 56096 +1 1 +.names 56096 56097 +0 1 +.names 56094 56097 56098 +1- 1 +-1 1 +.names 56110 56113 56099 +11 1 +.names 56099 56100 +1 1 +.names 56100 56101 +0 1 +.names 56120 56121 56102 +11 1 +.names 56102 56103 +1 1 +.names 56103 56104 +0 1 +.names 55162 56104 56105 +11 1 +.names 53666 56106 +0 1 +.names 15087 56106 56107 +11 1 +.names 15126 52497 56108 +11 1 +.names 56108 56109 +1 1 +.names 56109 56110 +0 1 +.names 56126 56127 56111 +1- 1 +-1 1 +.names 56111 56112 +1 1 +.names 56112 56113 +0 1 +.names 15099 56117 56114 +1- 1 +-1 1 +.names 56114 56115 +1 1 +.names 2413 56116 +1 1 +.names 56116 56117 +0 1 +.names 56131 56132 56118 +1- 1 +-1 1 +.names 56118 56119 +1 1 +.names 56119 56120 +0 1 +.names 56115 56121 +0 1 +.names 56124 15113 56122 +1- 1 +-1 1 +.names 56122 56123 +1 1 +.names 53066 56124 +0 1 +.names 55115 56125 +1 1 +.names 15117 54798 56126 +11 1 +.names 56123 56127 +0 1 +.names 55233 56128 +1 1 +.names 56128 56129 +0 1 +.names 56125 56130 +0 1 +.names 56129 56130 56131 +1- 1 +-1 1 +.names 51928 56132 +0 1 +.names 55310 56135 56133 +1- 1 +-1 1 +.names 56133 56134 +1 1 +.names 54841 56135 +0 1 +.names 56149 56151 56136 +1- 1 +-1 1 +.names 56136 56137 +1 1 +.names 56137 56138 +0 1 +.names 2413 56139 +1 1 +.names 56139 56140 +1 1 +.names 56140 56141 +0 1 +.names 56138 56141 56142 +1- 1 +-1 1 +.names 56170 56165 56143 +11 1 +.names 56143 56144 +1 1 +.names 56144 56145 +0 1 +.names 56162 56163 56146 +11 1 +.names 56146 56147 +1 1 +.names 56147 56148 +0 1 +.names 55333 56148 56149 +11 1 +.names 53702 56150 +0 1 +.names 15085 56150 56151 +11 1 +.names 56156 56157 56152 +1- 1 +-1 1 +.names 56152 56153 +1 1 +.names 55310 56154 +1 1 +.names 56154 56155 +0 1 +.names 15122 56155 56156 +1- 1 +-1 1 +.names 51962 56157 +0 1 +.names 15127 56161 56158 +1- 1 +-1 1 +.names 56158 56159 +1 1 +.names 2413 56160 +1 1 +.names 56160 56161 +0 1 +.names 56153 56162 +0 1 +.names 56159 56163 +0 1 +.names 56166 55222 56164 +1- 1 +-1 1 +.names 56164 56165 +1 1 +.names 53100 56166 +0 1 +.names 55145 56169 56167 +1- 1 +-1 1 +.names 56167 56168 +1 1 +.names 52531 56169 +0 1 +.names 56168 56134 56170 +11 1 +.names 55231 56173 56171 +1- 1 +-1 1 +.names 56171 56172 +1 1 +.names 54907 56173 +0 1 +.names 56179 56181 56174 +1- 1 +-1 1 +.names 56174 56175 +1 1 +.names 56188 56189 56176 +11 1 +.names 56176 56177 +1 1 +.names 56177 56178 +0 1 +.names 55204 56178 56179 +11 1 +.names 53721 56180 +0 1 +.names 15123 56180 56181 +11 1 +.names 15126 56185 56182 +1- 1 +-1 1 +.names 56182 56183 +1 1 +.names 2413 56184 +1 1 +.names 56184 56185 +0 1 +.names 56195 56196 56186 +1- 1 +-1 1 +.names 56186 56187 +1 1 +.names 56187 56188 +0 1 +.names 56183 56189 +0 1 +.names 56192 55185 56190 +1- 1 +-1 1 +.names 56190 56191 +1 1 +.names 53117 56192 +0 1 +.names 55231 56193 +1 1 +.names 56193 56194 +0 1 +.names 15102 56194 56195 +1- 1 +-1 1 +.names 51979 56196 +0 1 +.names 56203 56204 56197 +1- 1 +-1 1 +.names 56197 56198 +1 1 +.names 56172 56199 +0 1 +.names 55233 56213 56200 +1- 1 +-1 1 +.names 56200 56201 +1 1 +.names 56201 56202 +0 1 +.names 56199 56202 56203 +1- 1 +-1 1 +.names 56191 56204 +0 1 +.names 56175 56205 +0 1 +.names 56211 56212 56206 +11 1 +.names 56206 56207 +1 1 +.names 56207 56208 +0 1 +.names 1783 56209 +1 1 +.names 56209 56210 +1 1 +.names 56198 56211 +0 1 +.names 56210 56212 +0 1 +.names 52548 56213 +0 1 +.names 56227 56229 56214 +1- 1 +-1 1 +.names 56214 56215 +1 1 +.names 56215 56216 +0 1 +.names 56252 15113 56217 +1- 1 +-1 1 +.names 56217 56218 +1 1 +.names 56218 56219 +0 1 +.names 56216 56219 56220 +1- 1 +-1 1 +.names 56232 56235 56221 +11 1 +.names 56221 56222 +1 1 +.names 56222 56223 +0 1 +.names 56250 56251 56224 +11 1 +.names 56224 56225 +1 1 +.names 56225 56226 +0 1 +.names 55601 56226 56227 +11 1 +.names 52565 56228 +0 1 +.names 15104 56228 56229 +11 1 +.names 53739 15116 56230 +11 1 +.names 56230 56231 +1 1 +.names 56231 56232 +0 1 +.names 56236 56239 56233 +1- 1 +-1 1 +.names 56233 56234 +1 1 +.names 56234 56235 +0 1 +.names 15096 54917 56236 +11 1 +.names 2413 56237 +1 1 +.names 56237 56238 +1 1 +.names 56238 56239 +0 1 +.names 56244 56245 56240 +1- 1 +-1 1 +.names 56240 56241 +1 1 +.names 2413 56242 +1 1 +.names 56242 56243 +0 1 +.names 15116 56243 56244 +1- 1 +-1 1 +.names 51996 56245 +0 1 +.names 15099 56249 56246 +1- 1 +-1 1 +.names 56246 56247 +1 1 +.names 55231 56248 +1 1 +.names 56248 56249 +0 1 +.names 56241 56250 +0 1 +.names 56247 56251 +0 1 +.names 53134 56252 +0 1 +.names 56266 56268 56253 +1- 1 +-1 1 +.names 56253 56254 +1 1 +.names 56254 56255 +0 1 +.names 2413 56256 +1 1 +.names 56256 56257 +1 1 +.names 56257 56258 +0 1 +.names 56255 56258 56259 +1- 1 +-1 1 +.names 56290 56282 56260 +11 1 +.names 56260 56261 +1 1 +.names 56261 56262 +0 1 +.names 56279 56280 56263 +11 1 +.names 56263 56264 +1 1 +.names 56264 56265 +0 1 +.names 55204 56265 56266 +11 1 +.names 53757 56267 +0 1 +.names 15123 56267 56268 +11 1 +.names 56273 56274 56269 +1- 1 +-1 1 +.names 56269 56270 +1 1 +.names 55115 56271 +1 1 +.names 56271 56272 +0 1 +.names 15122 56272 56273 +1- 1 +-1 1 +.names 52014 56274 +0 1 +.names 15127 56278 56275 +1- 1 +-1 1 +.names 56275 56276 +1 1 +.names 2413 56277 +1 1 +.names 56277 56278 +0 1 +.names 56270 56279 +0 1 +.names 56276 56280 +0 1 +.names 56283 55222 56281 +1- 1 +-1 1 +.names 56281 56282 +1 1 +.names 53152 56283 +0 1 +.names 55115 56286 56284 +1- 1 +-1 1 +.names 56284 56285 +1 1 +.names 54955 56286 +0 1 +.names 55145 56289 56287 +1- 1 +-1 1 +.names 56287 56288 +1 1 +.names 52582 56289 +0 1 +.names 56288 56285 56290 +11 1 +.names 55072 56293 56291 +1- 1 +-1 1 +.names 56291 56292 +1 1 +.names 55028 56293 +0 1 +.names 56296 15113 56294 +1- 1 +-1 1 +.names 56294 56295 +1 1 +.names 53169 56296 +0 1 +.names 56301 56302 56297 +1- 1 +-1 1 +.names 56297 56298 +1 1 +.names 55072 56299 +1 1 +.names 56299 56300 +0 1 +.names 15099 56300 56301 +1- 1 +-1 1 +.names 52031 56302 +0 1 +.names 15127 56306 56303 +1- 1 +-1 1 +.names 56303 56304 +1 1 +.names 2413 56305 +1 1 +.names 56305 56306 +0 1 +.names 56312 56314 56307 +1- 1 +-1 1 +.names 56307 56308 +1 1 +.names 56315 56316 56309 +11 1 +.names 56309 56310 +1 1 +.names 56310 56311 +0 1 +.names 55204 56311 56312 +11 1 +.names 53775 56313 +0 1 +.names 15123 56313 56314 +11 1 +.names 56298 56315 +0 1 +.names 56304 56316 +0 1 +.names 56323 56324 56317 +1- 1 +-1 1 +.names 56317 56318 +1 1 +.names 55145 56333 56319 +1- 1 +-1 1 +.names 56319 56320 +1 1 +.names 56320 56321 +0 1 +.names 56292 56322 +0 1 +.names 56321 56322 56323 +1- 1 +-1 1 +.names 56295 56324 +0 1 +.names 56327 56330 56325 +11 1 +.names 56325 56326 +1 1 +.names 56318 56327 +0 1 +.names 1783 56328 +1 1 +.names 56328 56329 +1 1 +.names 56329 56330 +0 1 +.names 56308 56331 +0 1 +.names 56326 56332 +0 1 +.names 52599 56333 +0 1 +.names 56347 56349 56334 +1- 1 +-1 1 +.names 56334 56335 +1 1 +.names 56335 56336 +0 1 +.names 2413 56337 +1 1 +.names 56337 56338 +1 1 +.names 56338 56339 +0 1 +.names 56336 56339 56340 +1- 1 +-1 1 +.names 56352 56355 56341 +11 1 +.names 56341 56342 +1 1 +.names 56342 56343 +0 1 +.names 56362 56363 56344 +11 1 +.names 56344 56345 +1 1 +.names 56345 56346 +0 1 +.names 55204 56346 56347 +11 1 +.names 53788 56348 +0 1 +.names 15123 56348 56349 +11 1 +.names 15125 52611 56350 +11 1 +.names 56350 56351 +1 1 +.names 56351 56352 +0 1 +.names 56371 56372 56353 +1- 1 +-1 1 +.names 56353 56354 +1 1 +.names 56354 56355 +0 1 +.names 15122 56359 56356 +1- 1 +-1 1 +.names 56356 56357 +1 1 +.names 2413 56358 +1 1 +.names 56358 56359 +0 1 +.names 56369 56370 56360 +1- 1 +-1 1 +.names 56360 56361 +1 1 +.names 56361 56362 +0 1 +.names 56357 56363 +0 1 +.names 56366 55222 56364 +1- 1 +-1 1 +.names 56364 56365 +1 1 +.names 53181 56366 +0 1 +.names 55115 56367 +1 1 +.names 56367 56368 +0 1 +.names 15125 56368 56369 +1- 1 +-1 1 +.names 52043 56370 +0 1 +.names 15117 55033 56371 +11 1 +.names 56365 56372 +0 1 +.names 29977 56373 +0 1 +.names 29610 56374 +1 1 +.names 56374 56375 +0 1 +.names 56373 56375 56376 +11 1 +.names 29536 56377 +0 1 +.names 56377 56378 +1 1 +.names 56378 56379 +0 1 +.names 29977 56379 56380 +11 1 +.names 2413 56381 +1 1 +.names 56381 56382 +0 1 +.names 56373 56382 56383 +11 1 +.names 29315 56384 +0 1 +.names 56384 56385 +1 1 +.names 56385 56386 +0 1 +.names 29977 56386 56387 +11 1 +.names 11103 56388 +0 1 +.names 56388 56389 +1 1 +.names 56389 56390 +0 1 +.names 56373 56390 56391 +11 1 +.names 29474 56392 +0 1 +.names 56392 56393 +1 1 +.names 56393 56394 +0 1 +.names 29977 56394 56395 +11 1 +.names 49858 56396 +0 1 +.names 508 56397 +0 1 +.names 56397 56398 +1 1 +.names 56398 56399 +0 1 +.names 56396 56399 56400 +11 1 +.names 49532 56401 +0 1 +.names 56401 56402 +1 1 +.names 56402 56403 +0 1 +.names 49858 56403 56404 +11 1 +.names 2447 56774 +1 1 +.names 2447 56783 +1 1 +.names 2447 56785 +1 1 +.names 2447 56790 +1 1 +.names 2447 56795 +1 1 +.names 2447 56801 +1 1 +.names 2584 56808 +1 1 +.names 2447 56809 +1 1 +.names 2447 56811 +1 1 +.names 2447 56812 +1 1 +.names 2447 56815 +1 1 +.names 2447 56831 +1 1 +.names 2584 56833 +1 1 +.names 2447 56834 +1 1 +.names 2584 56849 +1 1 +.names 2447 56852 +1 1 +.names 2447 56873 +1 1 +.names 2584 56913 +1 1 +.names 2447 56918 +1 1 +.names 2447 56920 +1 1 +.names 2447 56922 +1 1 +.names 2447 56923 +1 1 +.names 2447 56924 +1 1 +.names 2447 56925 +1 1 +.names 2447 56926 +1 1 +.names 2447 56927 +1 1 +.names 2447 56930 +1 1 +.names 2447 56939 +1 1 +.names 2447 56950 +1 1 +.names 2447 56963 +1 1 +.names 2447 56966 +1 1 +.names 2447 56967 +1 1 +.names 2447 56968 +1 1 +.names 2447 56971 +1 1 +.names 2447 56973 +1 1 +.names 2447 56975 +1 1 +.names 2447 56977 +1 1 +.names 2447 56978 +1 1 +.names 2447 56979 +1 1 +.names 2447 56980 +1 1 +.names 2447 56983 +1 1 +.names 2447 56984 +1 1 +.names 2447 56985 +1 1 +.names 2447 56990 +1 1 +.names 2447 56992 +1 1 +.names 2584 56998 +1 1 +.names 2447 56999 +1 1 +.names 2584 57001 +1 1 +.names 2447 57002 +1 1 +.names 2584 57012 +1 1 +.names 2447 57013 +1 1 +.names 2447 57014 +1 1 +.names 2447 57017 +1 1 +.names 2447 57020 +1 1 +.names 2447 57022 +1 1 +.names 2447 57024 +1 1 +.names 2447 57026 +1 1 +.names 2584 57028 +1 1 +.names 2447 57030 +1 1 +.names 2447 57031 +1 1 +.names 2447 57032 +1 1 +.names 2447 57040 +1 1 +.names 2447 57043 +1 1 +.names 2447 57045 +1 1 +.names 2447 57046 +1 1 +.names 2447 57047 +1 1 +.names 2447 57048 +1 1 +.names 2447 57049 +1 1 +.names 2447 57050 +1 1 +.names 2447 57051 +1 1 +.names 2447 57052 +1 1 +.names 2447 57053 +1 1 +.names 2447 57054 +1 1 +.names 2447 57055 +1 1 +.names 2447 57056 +1 1 +.names 2447 57057 +1 1 +.names 2447 57058 +1 1 +.names 2447 57059 +1 1 +.names 2447 57060 +1 1 +.names 2447 57061 +1 1 +.names 2447 57062 +1 1 +.names 2447 57063 +1 1 +.names 2447 57064 +1 1 +.names 2447 57065 +1 1 +.names 2447 57066 +1 1 +.names 2447 57067 +1 1 +.names 2447 57070 +1 1 +.names 5666 57072 +1 1 +.names 5666 57073 +1 1 +.names 5666 57075 +1 1 +.names 5786 57076 +1 1 +.names 5786 57077 +1 1 +.names 5786 57079 +1 1 +.end diff --git a/abc70930/examples/s38417.blif b/abc70930/examples/s38417.blif new file mode 100644 index 00000000..256d554e --- /dev/null +++ b/abc70930/examples/s38417.blif @@ -0,0 +1,48956 @@ +.model s38417 +.inputs g51 g563 g1249 g1943 g2637 g3212 g3213 g3214 g3215 g3216 g3217 g3218 \ +g3219 g3220 g3221 g3222 g3223 g3224 g3225 g3226 g3227 g3228 g3229 g3230 g3231 \ +g3232 g3233 g3234 +.outputs g3993 g4088 g4090 g4200 g4321 g4323 g4450 g4590 g5388 g5437 g5472 \ +g5511 g5549 g5555 g5595 g5612 g5629 g5637 g5648 g5657 g5686 g5695 g5738 g5747 \ +g5796 g6225 g6231 g6313 g6368 g6442 g6447 g6485 g6518 g6573 g6642 g6677 g6712 \ +g6750 g6782 g6837 g6895 g6911 g6944 g6979 g7014 g7052 g7084 g7161 g7194 g7229 \ +g7264 g7302 g7334 g7357 g7390 g7425 g7487 g7519 g7909 g7956 g7961 g8007 g8012 \ +g8021 g8023 g8030 g8082 g8087 g8096 g8106 g8167 g8175 g8249 g8251 g8258 g8259 \ +g8260 g8261 g8262 g8263 g8264 g8265 g8266 g8267 g8268 g8269 g8270 g8271 g8272 \ +g8273 g8274 g8275 g16297 g16355 g16399 g16437 g16496 g24734 g25420 g25435 \ +g25442 g25489 g26104 g26135 g26149 g27380 +.wire_load_slope 0.00 +.latch g16475 g2814 0 +.latch g20571 g2817 0 +.latch g20588 g2933 0 +.latch g21951 g2950 0 +.latch g23315 g2883 0 +.latch g24423 g2888 0 +.latch g25175 g2896 0 +.latch g26019 g2892 0 +.latch g26747 g2903 0 +.latch g27237 g2900 0 +.latch g27715 g2908 0 +.latch g24424 g2912 0 +.latch g25174 g2917 0 +.latch g26020 g2924 0 +.latch g26746 g2920 0 +.latch g19061 g2984 0 +.latch g19060 g2985 0 +.latch g19062 g2930 0 +.latch gbuf1 g2929 0 +.latch g16494 g2879 0 +.latch g16476 g2934 0 +.latch g16477 g2935 0 +.latch g16478 g2938 0 +.latch g16479 g2941 0 +.latch g16480 g2944 0 +.latch g16481 g2947 0 +.latch g16482 g2953 0 +.latch g16483 g2956 0 +.latch g16484 g2959 0 +.latch g16485 g2962 0 +.latch g16486 g2963 0 +.latch g16487 g2966 0 +.latch g16488 g2969 0 +.latch g16489 g2972 0 +.latch g16490 g2975 0 +.latch g16491 g2978 0 +.latch g16492 g2981 0 +.latch g16493 g2874 0 +.latch g20572 g1506 0 +.latch g20573 g1501 0 +.latch g20574 g1496 0 +.latch g20575 g1491 0 +.latch g20576 g1486 0 +.latch g20577 g1481 0 +.latch g20578 g1476 0 +.latch g20579 g1471 0 +.latch g23313 g2877 0 +.latch g21960 g2861 0 +.latch gbuf2 g813 0 +.latch g21961 g2864 0 +.latch gbuf3 g809 0 +.latch g21962 g2867 0 +.latch gbuf4 g805 0 +.latch g21963 g2870 0 +.latch gbuf5 g801 0 +.latch g21947 g2818 0 +.latch gbuf6 g797 0 +.latch g21948 g2821 0 +.latch gbuf7 g793 0 +.latch g21949 g2824 0 +.latch gbuf8 g789 0 +.latch g21950 g2827 0 +.latch gbuf9 g785 0 +.latch g23312 g2830 0 +.latch gbuf10 g2873 0 +.latch g21952 g2833 0 +.latch gbuf11 g125 0 +.latch g21953 g2836 0 +.latch gbuf12 g121 0 +.latch g21954 g2839 0 +.latch gbuf13 g117 0 +.latch g21955 g2842 0 +.latch gbuf14 g113 0 +.latch g21956 g2845 0 +.latch gbuf15 g109 0 +.latch g21957 g2848 0 +.latch gbuf16 g105 0 +.latch g21958 g2851 0 +.latch gbuf17 g101 0 +.latch g21959 g2854 0 +.latch gbuf18 g97 0 +.latch g23316 g2858 0 +.latch gbuf19 g2857 0 +.latch g20587 g2200 0 +.latch g20585 g2195 0 +.latch g20586 g2190 0 +.latch g20584 g2185 0 +.latch g20583 g2180 0 +.latch g20582 g2175 0 +.latch g20581 g2170 0 +.latch g20580 g2165 0 +.latch g23314 g2878 0 +.latch g13475 g3129 0 +.latch gbuf20 g3117 0 +.latch gbuf21 g3109 0 +.latch g20630 g3210 0 +.latch g20631 g3211 0 +.latch g20632 g3084 0 +.latch g20609 g3085 0 +.latch g20610 g3086 0 +.latch g20611 g3087 0 +.latch g20612 g3091 0 +.latch g20613 g3092 0 +.latch g20614 g3093 0 +.latch g20615 g3094 0 +.latch g20616 g3095 0 +.latch g20617 g3096 0 +.latch g26751 g3097 0 +.latch g26752 g3098 0 +.latch g26753 g3099 0 +.latch g29163 g3100 0 +.latch g29164 g3101 0 +.latch g29165 g3102 0 +.latch g30120 g3103 0 +.latch g30121 g3104 0 +.latch g30122 g3105 0 +.latch g30941 g3106 0 +.latch g30942 g3107 0 +.latch g30943 g3108 0 +.latch g20618 g3155 0 +.latch g20619 g3158 0 +.latch g20620 g3161 0 +.latch g20621 g3164 0 +.latch g20622 g3167 0 +.latch g20623 g3170 0 +.latch g20624 g3173 0 +.latch g20625 g3176 0 +.latch g20626 g3179 0 +.latch g20627 g3182 0 +.latch g20628 g3185 0 +.latch g20629 g3088 0 +.latch g27717 g3191 0 +.latch g28316 g3194 0 +.latch g28317 g3197 0 +.latch g28318 g3198 0 +.latch g28704 g3201 0 +.latch g28705 g3204 0 +.latch g28706 g3207 0 +.latch g29463 g3188 0 +.latch g29656 g3133 0 +.latch g28698 g3132 0 +.latch g29166 g3128 0 +.latch g28697 g3127 0 +.latch g28315 g3126 0 +.latch g28696 g3125 0 +.latch g28314 g3124 0 +.latch g28313 g3123 0 +.latch g28695 g3120 0 +.latch g28694 g3114 0 +.latch g28693 g3113 0 +.latch g28312 g3112 0 +.latch g28311 g3110 0 +.latch g28310 g3111 0 +.latch g29461 g3139 0 +.latch g28701 g3136 0 +.latch g28700 g3134 0 +.latch g28699 g3135 0 +.latch g29462 g3151 0 +.latch g28703 g3142 0 +.latch g28702 g3147 0 +.latch g29657 g185 0 +.latch g13405 g138 0 +.latch gbuf22 g135 0 +.latch gbuf23 g165 0 +.latch g24259 g130 0 +.latch g24260 g131 0 +.latch g24261 g129 0 +.latch g24262 g133 0 +.latch g24263 g134 0 +.latch g24264 g132 0 +.latch g24265 g142 0 +.latch g24266 g143 0 +.latch g24267 g141 0 +.latch g24268 g145 0 +.latch g24269 g146 0 +.latch g24270 g144 0 +.latch g24271 g148 0 +.latch g24272 g149 0 +.latch g24273 g147 0 +.latch g24274 g151 0 +.latch g24275 g152 0 +.latch g24276 g150 0 +.latch g24277 g154 0 +.latch g24278 g155 0 +.latch g24279 g153 0 +.latch g24280 g157 0 +.latch g24281 g158 0 +.latch g24282 g156 0 +.latch g24283 g160 0 +.latch g24284 g161 0 +.latch g24285 g159 0 +.latch g24286 g163 0 +.latch g24287 g164 0 +.latch g24288 g162 0 +.latch g26679 g169 0 +.latch g26680 g170 0 +.latch g26681 g168 0 +.latch g26682 g172 0 +.latch g26683 g173 0 +.latch g26684 g171 0 +.latch g26685 g175 0 +.latch g26686 g176 0 +.latch g26687 g174 0 +.latch g26688 g178 0 +.latch g26689 g179 0 +.latch g26690 g177 0 +.latch g30506 g186 0 +.latch g30507 g189 0 +.latch g30508 g192 0 +.latch g30842 g231 0 +.latch g30843 g234 0 +.latch g30844 g237 0 +.latch g30836 g195 0 +.latch g30837 g198 0 +.latch g30838 g201 0 +.latch g30845 g240 0 +.latch g30846 g243 0 +.latch g30847 g246 0 +.latch g30509 g204 0 +.latch g30510 g207 0 +.latch g30511 g210 0 +.latch g30515 g249 0 +.latch g30516 g252 0 +.latch g30517 g255 0 +.latch g30512 g213 0 +.latch g30513 g216 0 +.latch g30514 g219 0 +.latch g30518 g258 0 +.latch g30519 g261 0 +.latch g30520 g264 0 +.latch g30839 g222 0 +.latch g30840 g225 0 +.latch g30841 g228 0 +.latch g30848 g267 0 +.latch g30849 g270 0 +.latch g30850 g273 0 +.latch g25983 g92 0 +.latch g26678 g88 0 +.latch g27189 g83 0 +.latch g27683 g79 0 +.latch g28206 g74 0 +.latch g28673 g70 0 +.latch g29131 g65 0 +.latch g29413 g61 0 +.latch g29627 g56 0 +.latch g29794 g52 0 +.latch g20555 g180 0 +.latch gbuf24 g182 0 +.latch gbuf25 g181 0 +.latch g13406 g276 0 +.latch gbuf26 g405 0 +.latch gbuf27 g401 0 +.latch g11496 g309 0 +.latch g28207 g354 0 +.latch g28208 g343 0 +.latch g28209 g346 0 +.latch g28210 g369 0 +.latch g28211 g358 0 +.latch g28212 g361 0 +.latch g28213 g384 0 +.latch g28214 g373 0 +.latch g28215 g376 0 +.latch g28216 g398 0 +.latch g28217 g388 0 +.latch g28218 g391 0 +.latch g29414 g408 0 +.latch g29415 g411 0 +.latch g29416 g414 0 +.latch g29631 g417 0 +.latch g29632 g420 0 +.latch g29633 g423 0 +.latch g29417 g427 0 +.latch g29418 g428 0 +.latch g29419 g426 0 +.latch g27684 g429 0 +.latch g27685 g432 0 +.latch g27686 g435 0 +.latch g27687 g438 0 +.latch g27688 g441 0 +.latch g27689 g444 0 +.latch g28674 g448 0 +.latch g28675 g449 0 +.latch g28676 g447 0 +.latch g29795 g312 0 +.latch g29796 g313 0 +.latch g29797 g314 0 +.latch g30851 g315 0 +.latch g30852 g316 0 +.latch g30853 g317 0 +.latch g30710 g318 0 +.latch g30711 g319 0 +.latch g30712 g320 0 +.latch g29628 g322 0 +.latch g29629 g323 0 +.latch g29630 g321 0 +.latch g27191 g403 0 +.latch g27192 g404 0 +.latch g27193 g402 0 +.latch g11509 g450 0 +.latch gbuf28 g451 0 +.latch g11510 g452 0 +.latch gbuf29 g453 0 +.latch g11511 g454 0 +.latch gbuf30 g279 0 +.latch g11491 g280 0 +.latch gbuf31 g281 0 +.latch g11492 g282 0 +.latch gbuf32 g283 0 +.latch g11493 g284 0 +.latch gbuf33 g285 0 +.latch g11494 g286 0 +.latch gbuf34 g287 0 +.latch g11495 g288 0 +.latch gbuf35 g289 0 +.latch g13407 g290 0 +.latch gbuf36 g291 0 +.latch g19012 g299 0 +.latch g23148 g305 0 +.latch g23149 g308 0 +.latch g23150 g297 0 +.latch g23151 g296 0 +.latch g23152 g295 0 +.latch g23153 g294 0 +.latch g19016 g304 0 +.latch g19015 g303 0 +.latch g19014 g302 0 +.latch g19013 g301 0 +.latch g25130 g300 0 +.latch g27190 g298 0 +.latch g11497 g342 0 +.latch gbuf37 g349 0 +.latch g11498 g350 0 +.latch gbuf38 g351 0 +.latch g11499 g352 0 +.latch gbuf39 g353 0 +.latch g11500 g357 0 +.latch gbuf40 g364 0 +.latch g11501 g365 0 +.latch gbuf41 g366 0 +.latch g11502 g367 0 +.latch gbuf42 g368 0 +.latch g11503 g372 0 +.latch gbuf43 g379 0 +.latch g11504 g380 0 +.latch gbuf44 g381 0 +.latch g11505 g382 0 +.latch gbuf45 g383 0 +.latch g11506 g387 0 +.latch gbuf46 g394 0 +.latch g11507 g395 0 +.latch gbuf47 g396 0 +.latch g11508 g397 0 +.latch gbuf48 g324 0 +.latch g13408 g325 0 +.latch gbuf49 g331 0 +.latch gbuf50 g337 0 +.latch g13419 g545 0 +.latch gbuf51 g551 0 +.latch gbuf52 g550 0 +.latch g23160 g554 0 +.latch g20556 g557 0 +.latch g20557 g510 0 +.latch g16467 g513 0 +.latch gbuf53 g523 0 +.latch gbuf54 g524 0 +.latch g11512 g564 0 +.latch gbuf55 g569 0 +.latch g11515 g570 0 +.latch gbuf56 g571 0 +.latch g11516 g572 0 +.latch gbuf57 g573 0 +.latch g11517 g574 0 +.latch gbuf58 g565 0 +.latch g11513 g566 0 +.latch gbuf59 g567 0 +.latch g11514 g568 0 +.latch gbuf60 g489 0 +.latch g13409 g474 0 +.latch gbuf61 g481 0 +.latch gbuf62 g485 0 +.latch g24292 g486 0 +.latch g24293 g487 0 +.latch g24294 g488 0 +.latch g25139 g455 0 +.latch g25131 g458 0 +.latch g25132 g461 0 +.latch g25136 g477 0 +.latch g25137 g478 0 +.latch g25138 g479 0 +.latch g24289 g480 0 +.latch g24290 g484 0 +.latch g24291 g464 0 +.latch g25133 g465 0 +.latch g25134 g468 0 +.latch g25135 g471 0 +.latch g16468 g528 0 +.latch gbuf63 g535 0 +.latch gbuf64 g542 0 +.latch g19021 g543 0 +.latch gbuf65 g544 0 +.latch g23159 g548 0 +.latch g19022 g549 0 +.latch gbuf66 g499 0 +.latch g19023 g558 0 +.latch gbuf67 g559 0 +.latch g28219 g576 0 +.latch g28220 g577 0 +.latch g28221 g575 0 +.latch g28222 g579 0 +.latch g28223 g580 0 +.latch g28224 g578 0 +.latch g28225 g582 0 +.latch g28226 g583 0 +.latch g28227 g581 0 +.latch g28228 g585 0 +.latch g28229 g586 0 +.latch g28230 g584 0 +.latch g25985 g587 0 +.latch g25986 g590 0 +.latch g25987 g593 0 +.latch g25988 g596 0 +.latch g25989 g599 0 +.latch g25990 g602 0 +.latch g29135 g614 0 +.latch g29136 g617 0 +.latch g29137 g620 0 +.latch g29132 g605 0 +.latch g29133 g608 0 +.latch g29134 g611 0 +.latch g27194 g490 0 +.latch g27195 g493 0 +.latch g27196 g496 0 +.latch g8284 g506 0 +.latch g24295 g507 0 +.latch g19017 g508 0 +.latch g19018 g509 0 +.latch g19019 g514 0 +.latch g19020 g515 0 +.latch g23158 g516 0 +.latch g23157 g517 0 +.latch g23156 g518 0 +.latch g23155 g519 0 +.latch g23154 g520 0 +.latch gbuf68 g525 0 +.latch g13410 g529 0 +.latch g13411 g530 0 +.latch g13412 g531 0 +.latch g13413 g532 0 +.latch g13414 g533 0 +.latch g13415 g534 0 +.latch g13416 g536 0 +.latch g13417 g537 0 +.latch g25984 g538 0 +.latch g13418 g541 0 +.latch g13420 g623 0 +.latch gbuf69 g626 0 +.latch gbuf70 g629 0 +.latch g20558 g630 0 +.latch g21943 g659 0 +.latch g23161 g640 0 +.latch g24296 g633 0 +.latch g25140 g653 0 +.latch g25991 g646 0 +.latch g26691 g660 0 +.latch g27197 g672 0 +.latch g27690 g666 0 +.latch g28231 g679 0 +.latch g28677 g686 0 +.latch g29138 g692 0 +.latch g23162 g699 0 +.latch g23163 g700 0 +.latch g23164 g698 0 +.latch g23165 g702 0 +.latch g23166 g703 0 +.latch g23167 g701 0 +.latch g23168 g705 0 +.latch g23169 g706 0 +.latch g23170 g704 0 +.latch g23171 g708 0 +.latch g23172 g709 0 +.latch g23173 g707 0 +.latch g23174 g711 0 +.latch g23175 g712 0 +.latch g23176 g710 0 +.latch g23177 g714 0 +.latch g23178 g715 0 +.latch g23179 g713 0 +.latch g23180 g717 0 +.latch g23181 g718 0 +.latch g23182 g716 0 +.latch g23183 g720 0 +.latch g23184 g721 0 +.latch g23185 g719 0 +.latch g23186 g723 0 +.latch g23187 g724 0 +.latch g23188 g722 0 +.latch g23189 g726 0 +.latch g23190 g727 0 +.latch g23191 g725 0 +.latch g23192 g729 0 +.latch g23193 g730 0 +.latch g23194 g728 0 +.latch g23195 g732 0 +.latch g23196 g733 0 +.latch g23197 g731 0 +.latch g26692 g735 0 +.latch g26693 g736 0 +.latch g26694 g734 0 +.latch g24297 g738 0 +.latch g24298 g739 0 +.latch g24299 g737 0 +.latch g13421 g826 0 +.latch gbuf71 g823 0 +.latch gbuf72 g853 0 +.latch g24300 g818 0 +.latch g24301 g819 0 +.latch g24302 g817 0 +.latch g24303 g821 0 +.latch g24304 g822 0 +.latch g24305 g820 0 +.latch g24306 g830 0 +.latch g24307 g831 0 +.latch g24308 g829 0 +.latch g24309 g833 0 +.latch g24310 g834 0 +.latch g24311 g832 0 +.latch g24312 g836 0 +.latch g24313 g837 0 +.latch g24314 g835 0 +.latch g24315 g839 0 +.latch g24316 g840 0 +.latch g24317 g838 0 +.latch g24318 g842 0 +.latch g24319 g843 0 +.latch g24320 g841 0 +.latch g24321 g845 0 +.latch g24322 g846 0 +.latch g24323 g844 0 +.latch g24324 g848 0 +.latch g24325 g849 0 +.latch g24326 g847 0 +.latch g24327 g851 0 +.latch g24328 g852 0 +.latch g24329 g850 0 +.latch g26696 g857 0 +.latch g26697 g858 0 +.latch g26698 g856 0 +.latch g26699 g860 0 +.latch g26700 g861 0 +.latch g26701 g859 0 +.latch g26702 g863 0 +.latch g26703 g864 0 +.latch g26704 g862 0 +.latch g26705 g866 0 +.latch g26706 g867 0 +.latch g26707 g865 0 +.latch g30521 g873 0 +.latch g30522 g876 0 +.latch g30523 g879 0 +.latch g30860 g918 0 +.latch g30861 g921 0 +.latch g30862 g924 0 +.latch g30854 g882 0 +.latch g30855 g885 0 +.latch g30856 g888 0 +.latch g30863 g927 0 +.latch g30864 g930 0 +.latch g30865 g933 0 +.latch g30524 g891 0 +.latch g30525 g894 0 +.latch g30526 g897 0 +.latch g30530 g936 0 +.latch g30531 g939 0 +.latch g30532 g942 0 +.latch g30527 g900 0 +.latch g30528 g903 0 +.latch g30529 g906 0 +.latch g30533 g945 0 +.latch g30534 g948 0 +.latch g30535 g951 0 +.latch g30857 g909 0 +.latch g30858 g912 0 +.latch g30859 g915 0 +.latch g30866 g954 0 +.latch g30867 g957 0 +.latch g30868 g960 0 +.latch g25992 g780 0 +.latch g26695 g776 0 +.latch g27198 g771 0 +.latch g27691 g767 0 +.latch g28232 g762 0 +.latch g28678 g758 0 +.latch g29139 g753 0 +.latch g29420 g749 0 +.latch g29634 g744 0 +.latch g29798 g740 0 +.latch g20559 g868 0 +.latch gbuf73 g870 0 +.latch gbuf74 g869 0 +.latch g13422 g963 0 +.latch gbuf75 g1092 0 +.latch gbuf76 g1088 0 +.latch g11523 g996 0 +.latch g28233 g1041 0 +.latch g28234 g1030 0 +.latch g28235 g1033 0 +.latch g28236 g1056 0 +.latch g28237 g1045 0 +.latch g28238 g1048 0 +.latch g28239 g1071 0 +.latch g28240 g1060 0 +.latch g28241 g1063 0 +.latch g28242 g1085 0 +.latch g28243 g1075 0 +.latch g28244 g1078 0 +.latch g29421 g1095 0 +.latch g29422 g1098 0 +.latch g29423 g1101 0 +.latch g29638 g1104 0 +.latch g29639 g1107 0 +.latch g29640 g1110 0 +.latch g29424 g1114 0 +.latch g29425 g1115 0 +.latch g29426 g1113 0 +.latch g27692 g1116 0 +.latch g27693 g1119 0 +.latch g27694 g1122 0 +.latch g27695 g1125 0 +.latch g27696 g1128 0 +.latch g27697 g1131 0 +.latch g28679 g1135 0 +.latch g28680 g1136 0 +.latch g28681 g1134 0 +.latch g29799 g999 0 +.latch g29800 g1000 0 +.latch g29801 g1001 0 +.latch g30869 g1002 0 +.latch g30870 g1003 0 +.latch g30871 g1004 0 +.latch g30713 g1005 0 +.latch g30714 g1006 0 +.latch g30715 g1007 0 +.latch g29635 g1009 0 +.latch g29636 g1010 0 +.latch g29637 g1008 0 +.latch g27206 g1090 0 +.latch g27207 g1091 0 +.latch g27208 g1089 0 +.latch g11536 g1137 0 +.latch gbuf77 g1138 0 +.latch g11537 g1139 0 +.latch gbuf78 g1140 0 +.latch g11538 g1141 0 +.latch gbuf79 g966 0 +.latch g11518 g967 0 +.latch gbuf80 g968 0 +.latch g11519 g969 0 +.latch gbuf81 g970 0 +.latch g11520 g971 0 +.latch gbuf82 g972 0 +.latch g11521 g973 0 +.latch gbuf83 g974 0 +.latch g11522 g975 0 +.latch gbuf84 g976 0 +.latch g13423 g977 0 +.latch gbuf85 g978 0 +.latch g19024 g986 0 +.latch g27200 g992 0 +.latch g27201 g995 0 +.latch g27202 g984 0 +.latch g27203 g983 0 +.latch g27204 g982 0 +.latch g27205 g981 0 +.latch g19028 g991 0 +.latch g19027 g990 0 +.latch g19026 g989 0 +.latch g19025 g988 0 +.latch g25141 g987 0 +.latch g27199 g985 0 +.latch g11524 g1029 0 +.latch gbuf86 g1036 0 +.latch g11525 g1037 0 +.latch gbuf87 g1038 0 +.latch g11526 g1039 0 +.latch gbuf88 g1040 0 +.latch g11527 g1044 0 +.latch gbuf89 g1051 0 +.latch g11528 g1052 0 +.latch gbuf90 g1053 0 +.latch g11529 g1054 0 +.latch gbuf91 g1055 0 +.latch g11530 g1059 0 +.latch gbuf92 g1066 0 +.latch g11531 g1067 0 +.latch gbuf93 g1068 0 +.latch g11532 g1069 0 +.latch gbuf94 g1070 0 +.latch g11533 g1074 0 +.latch gbuf95 g1081 0 +.latch g11534 g1082 0 +.latch gbuf96 g1083 0 +.latch g11535 g1084 0 +.latch gbuf97 g1011 0 +.latch g13424 g1012 0 +.latch gbuf98 g1018 0 +.latch gbuf99 g1024 0 +.latch g13435 g1231 0 +.latch gbuf100 g1237 0 +.latch gbuf101 g1236 0 +.latch g23198 g1240 0 +.latch g20560 g1243 0 +.latch g20561 g1196 0 +.latch g16469 g1199 0 +.latch gbuf102 g1209 0 +.latch gbuf103 g1210 0 +.latch g11539 g1250 0 +.latch gbuf104 g1255 0 +.latch g11542 g1256 0 +.latch gbuf105 g1257 0 +.latch g11543 g1258 0 +.latch gbuf106 g1259 0 +.latch g11544 g1260 0 +.latch gbuf107 g1251 0 +.latch g11540 g1252 0 +.latch gbuf108 g1253 0 +.latch g11541 g1254 0 +.latch gbuf109 g1176 0 +.latch g13425 g1161 0 +.latch gbuf110 g1168 0 +.latch gbuf111 g1172 0 +.latch g24333 g1173 0 +.latch g24334 g1174 0 +.latch g24335 g1175 0 +.latch g25150 g1142 0 +.latch g25142 g1145 0 +.latch g25143 g1148 0 +.latch g25147 g1164 0 +.latch g25148 g1165 0 +.latch g25149 g1166 0 +.latch g24330 g1167 0 +.latch g24331 g1171 0 +.latch g24332 g1151 0 +.latch g25144 g1152 0 +.latch g25145 g1155 0 +.latch g25146 g1158 0 +.latch g16470 g1214 0 +.latch gbuf112 g1221 0 +.latch gbuf113 g1228 0 +.latch g19033 g1229 0 +.latch gbuf114 g1230 0 +.latch g27217 g1234 0 +.latch g19034 g1235 0 +.latch gbuf115 g1186 0 +.latch g19035 g1244 0 +.latch gbuf116 g1245 0 +.latch g28245 g1262 0 +.latch g28246 g1263 0 +.latch g28247 g1261 0 +.latch g28248 g1265 0 +.latch g28249 g1266 0 +.latch g28250 g1264 0 +.latch g28251 g1268 0 +.latch g28252 g1269 0 +.latch g28253 g1267 0 +.latch g28254 g1271 0 +.latch g28255 g1272 0 +.latch g28256 g1270 0 +.latch g25994 g1273 0 +.latch g25995 g1276 0 +.latch g25996 g1279 0 +.latch g25997 g1282 0 +.latch g25998 g1285 0 +.latch g25999 g1288 0 +.latch g29143 g1300 0 +.latch g29144 g1303 0 +.latch g29145 g1306 0 +.latch g29140 g1291 0 +.latch g29141 g1294 0 +.latch g29142 g1297 0 +.latch g27209 g1177 0 +.latch g27210 g1180 0 +.latch g27211 g1183 0 +.latch g8293 g1192 0 +.latch g24336 g1193 0 +.latch g19029 g1194 0 +.latch g19030 g1195 0 +.latch g19031 g1200 0 +.latch g19032 g1201 0 +.latch g27216 g1202 0 +.latch g27215 g1203 0 +.latch g27214 g1204 0 +.latch g27213 g1205 0 +.latch g27212 g1206 0 +.latch gbuf117 g1211 0 +.latch g13426 g1215 0 +.latch g13427 g1216 0 +.latch g13428 g1217 0 +.latch g13429 g1218 0 +.latch g13430 g1219 0 +.latch g13431 g1220 0 +.latch g13432 g1222 0 +.latch g13433 g1223 0 +.latch g25993 g1224 0 +.latch g13434 g1227 0 +.latch g13436 g1309 0 +.latch gbuf118 g1312 0 +.latch gbuf119 g1315 0 +.latch g20562 g1316 0 +.latch g21944 g1345 0 +.latch g23199 g1326 0 +.latch g24337 g1319 0 +.latch g25151 g1339 0 +.latch g26000 g1332 0 +.latch g26708 g1346 0 +.latch g27218 g1358 0 +.latch g27698 g1352 0 +.latch g28257 g1365 0 +.latch g28682 g1372 0 +.latch g29146 g1378 0 +.latch g23200 g1385 0 +.latch g23201 g1386 0 +.latch g23202 g1384 0 +.latch g23203 g1388 0 +.latch g23204 g1389 0 +.latch g23205 g1387 0 +.latch g23206 g1391 0 +.latch g23207 g1392 0 +.latch g23208 g1390 0 +.latch g23209 g1394 0 +.latch g23210 g1395 0 +.latch g23211 g1393 0 +.latch g23212 g1397 0 +.latch g23213 g1398 0 +.latch g23214 g1396 0 +.latch g23215 g1400 0 +.latch g23216 g1401 0 +.latch g23217 g1399 0 +.latch g23218 g1403 0 +.latch g23219 g1404 0 +.latch g23220 g1402 0 +.latch g23221 g1406 0 +.latch g23222 g1407 0 +.latch g23223 g1405 0 +.latch g23224 g1409 0 +.latch g23225 g1410 0 +.latch g23226 g1408 0 +.latch g23227 g1412 0 +.latch g23228 g1413 0 +.latch g23229 g1411 0 +.latch g23230 g1415 0 +.latch g23231 g1416 0 +.latch g23232 g1414 0 +.latch g23233 g1418 0 +.latch g23234 g1419 0 +.latch g23235 g1417 0 +.latch g26709 g1421 0 +.latch g26710 g1422 0 +.latch g26711 g1420 0 +.latch g24338 g1424 0 +.latch g24339 g1425 0 +.latch g24340 g1423 0 +.latch g13437 g1520 0 +.latch gbuf120 g1517 0 +.latch gbuf121 g1547 0 +.latch g24341 g1512 0 +.latch g24342 g1513 0 +.latch g24343 g1511 0 +.latch g24344 g1515 0 +.latch g24345 g1516 0 +.latch g24346 g1514 0 +.latch g24347 g1524 0 +.latch g24348 g1525 0 +.latch g24349 g1523 0 +.latch g24350 g1527 0 +.latch g24351 g1528 0 +.latch g24352 g1526 0 +.latch g24353 g1530 0 +.latch g24354 g1531 0 +.latch g24355 g1529 0 +.latch g24356 g1533 0 +.latch g24357 g1534 0 +.latch g24358 g1532 0 +.latch g24359 g1536 0 +.latch g24360 g1537 0 +.latch g24361 g1535 0 +.latch g24362 g1539 0 +.latch g24363 g1540 0 +.latch g24364 g1538 0 +.latch g24365 g1542 0 +.latch g24366 g1543 0 +.latch g24367 g1541 0 +.latch g24368 g1545 0 +.latch g24369 g1546 0 +.latch g24370 g1544 0 +.latch g26713 g1551 0 +.latch g26714 g1552 0 +.latch g26715 g1550 0 +.latch g26716 g1554 0 +.latch g26717 g1555 0 +.latch g26718 g1553 0 +.latch g26719 g1557 0 +.latch g26720 g1558 0 +.latch g26721 g1556 0 +.latch g26722 g1560 0 +.latch g26723 g1561 0 +.latch g26724 g1559 0 +.latch g30536 g1567 0 +.latch g30537 g1570 0 +.latch g30538 g1573 0 +.latch g30878 g1612 0 +.latch g30879 g1615 0 +.latch g30880 g1618 0 +.latch g30872 g1576 0 +.latch g30873 g1579 0 +.latch g30874 g1582 0 +.latch g30881 g1621 0 +.latch g30882 g1624 0 +.latch g30883 g1627 0 +.latch g30539 g1585 0 +.latch g30540 g1588 0 +.latch g30541 g1591 0 +.latch g30545 g1630 0 +.latch g30546 g1633 0 +.latch g30547 g1636 0 +.latch g30542 g1594 0 +.latch g30543 g1597 0 +.latch g30544 g1600 0 +.latch g30548 g1639 0 +.latch g30549 g1642 0 +.latch g30550 g1645 0 +.latch g30875 g1603 0 +.latch g30876 g1606 0 +.latch g30877 g1609 0 +.latch g30884 g1648 0 +.latch g30885 g1651 0 +.latch g30886 g1654 0 +.latch g26001 g1466 0 +.latch g26712 g1462 0 +.latch g27219 g1457 0 +.latch g27699 g1453 0 +.latch g28258 g1448 0 +.latch g28683 g1444 0 +.latch g29147 g1439 0 +.latch g29427 g1435 0 +.latch g29641 g1430 0 +.latch g29802 g1426 0 +.latch g20563 g1562 0 +.latch gbuf122 g1564 0 +.latch gbuf123 g1563 0 +.latch g13438 g1657 0 +.latch gbuf124 g1786 0 +.latch gbuf125 g1782 0 +.latch g11550 g1690 0 +.latch g28259 g1735 0 +.latch g28260 g1724 0 +.latch g28261 g1727 0 +.latch g28262 g1750 0 +.latch g28263 g1739 0 +.latch g28264 g1742 0 +.latch g28265 g1765 0 +.latch g28266 g1754 0 +.latch g28267 g1757 0 +.latch g28268 g1779 0 +.latch g28269 g1769 0 +.latch g28270 g1772 0 +.latch g29434 g1789 0 +.latch g29435 g1792 0 +.latch g29436 g1795 0 +.latch g29645 g1798 0 +.latch g29646 g1801 0 +.latch g29647 g1804 0 +.latch g29437 g1808 0 +.latch g29438 g1809 0 +.latch g29439 g1807 0 +.latch g27700 g1810 0 +.latch g27701 g1813 0 +.latch g27702 g1816 0 +.latch g27703 g1819 0 +.latch g27704 g1822 0 +.latch g27705 g1825 0 +.latch g28684 g1829 0 +.latch g28685 g1830 0 +.latch g28686 g1828 0 +.latch g29803 g1693 0 +.latch g29804 g1694 0 +.latch g29805 g1695 0 +.latch g30887 g1696 0 +.latch g30888 g1697 0 +.latch g30889 g1698 0 +.latch g30716 g1699 0 +.latch g30717 g1700 0 +.latch g30718 g1701 0 +.latch g29642 g1703 0 +.latch g29643 g1704 0 +.latch g29644 g1702 0 +.latch g27221 g1784 0 +.latch g27222 g1785 0 +.latch g27223 g1783 0 +.latch g11563 g1831 0 +.latch gbuf126 g1832 0 +.latch g11564 g1833 0 +.latch gbuf127 g1834 0 +.latch g11565 g1835 0 +.latch gbuf128 g1660 0 +.latch g11545 g1661 0 +.latch gbuf129 g1662 0 +.latch g11546 g1663 0 +.latch gbuf130 g1664 0 +.latch g11547 g1665 0 +.latch gbuf131 g1666 0 +.latch g11548 g1667 0 +.latch gbuf132 g1668 0 +.latch g11549 g1669 0 +.latch gbuf133 g1670 0 +.latch g13439 g1671 0 +.latch gbuf134 g1672 0 +.latch g19036 g1680 0 +.latch g29428 g1686 0 +.latch g29429 g1689 0 +.latch g29430 g1678 0 +.latch g29431 g1677 0 +.latch g29432 g1676 0 +.latch g29433 g1675 0 +.latch g19040 g1685 0 +.latch g19039 g1684 0 +.latch g19038 g1683 0 +.latch g19037 g1682 0 +.latch g25152 g1681 0 +.latch g27220 g1679 0 +.latch g11551 g1723 0 +.latch gbuf135 g1730 0 +.latch g11552 g1731 0 +.latch gbuf136 g1732 0 +.latch g11553 g1733 0 +.latch gbuf137 g1734 0 +.latch g11554 g1738 0 +.latch gbuf138 g1745 0 +.latch g11555 g1746 0 +.latch gbuf139 g1747 0 +.latch g11556 g1748 0 +.latch gbuf140 g1749 0 +.latch g11557 g1753 0 +.latch gbuf141 g1760 0 +.latch g11558 g1761 0 +.latch gbuf142 g1762 0 +.latch g11559 g1763 0 +.latch gbuf143 g1764 0 +.latch g11560 g1768 0 +.latch gbuf144 g1775 0 +.latch g11561 g1776 0 +.latch gbuf145 g1777 0 +.latch g11562 g1778 0 +.latch gbuf146 g1705 0 +.latch g13440 g1706 0 +.latch gbuf147 g1712 0 +.latch gbuf148 g1718 0 +.latch g13451 g1925 0 +.latch gbuf149 g1931 0 +.latch gbuf150 g1930 0 +.latch g23236 g1934 0 +.latch g20564 g1937 0 +.latch g20565 g1890 0 +.latch g16471 g1893 0 +.latch gbuf151 g1903 0 +.latch gbuf152 g1904 0 +.latch g11566 g1944 0 +.latch gbuf153 g1949 0 +.latch g11569 g1950 0 +.latch gbuf154 g1951 0 +.latch g11570 g1952 0 +.latch gbuf155 g1953 0 +.latch g11571 g1954 0 +.latch gbuf156 g1945 0 +.latch g11567 g1946 0 +.latch gbuf157 g1947 0 +.latch g11568 g1948 0 +.latch gbuf158 g1870 0 +.latch g13441 g1855 0 +.latch gbuf159 g1862 0 +.latch gbuf160 g1866 0 +.latch g24374 g1867 0 +.latch g24375 g1868 0 +.latch g24376 g1869 0 +.latch g25161 g1836 0 +.latch g25153 g1839 0 +.latch g25154 g1842 0 +.latch g25158 g1858 0 +.latch g25159 g1859 0 +.latch g25160 g1860 0 +.latch g24371 g1861 0 +.latch g24372 g1865 0 +.latch g24373 g1845 0 +.latch g25155 g1846 0 +.latch g25156 g1849 0 +.latch g25157 g1852 0 +.latch g16472 g1908 0 +.latch gbuf161 g1915 0 +.latch gbuf162 g1922 0 +.latch g19045 g1923 0 +.latch gbuf163 g1924 0 +.latch g29445 g1928 0 +.latch g19046 g1929 0 +.latch gbuf164 g1880 0 +.latch g19047 g1938 0 +.latch gbuf165 g1939 0 +.latch g28271 g1956 0 +.latch g28272 g1957 0 +.latch g28273 g1955 0 +.latch g28274 g1959 0 +.latch g28275 g1960 0 +.latch g28276 g1958 0 +.latch g28277 g1962 0 +.latch g28278 g1963 0 +.latch g28279 g1961 0 +.latch g28280 g1965 0 +.latch g28281 g1966 0 +.latch g28282 g1964 0 +.latch g26003 g1967 0 +.latch g26004 g1970 0 +.latch g26005 g1973 0 +.latch g26006 g1976 0 +.latch g26007 g1979 0 +.latch g26008 g1982 0 +.latch g29151 g1994 0 +.latch g29152 g1997 0 +.latch g29153 g2000 0 +.latch g29148 g1985 0 +.latch g29149 g1988 0 +.latch g29150 g1991 0 +.latch g27224 g1871 0 +.latch g27225 g1874 0 +.latch g27226 g1877 0 +.latch g8302 g1886 0 +.latch g24377 g1887 0 +.latch g19041 g1888 0 +.latch g19042 g1889 0 +.latch g19043 g1894 0 +.latch g19044 g1895 0 +.latch g29444 g1896 0 +.latch g29443 g1897 0 +.latch g29442 g1898 0 +.latch g29441 g1899 0 +.latch g29440 g1900 0 +.latch gbuf166 g1905 0 +.latch g13442 g1909 0 +.latch g13443 g1910 0 +.latch g13444 g1911 0 +.latch g13445 g1912 0 +.latch g13446 g1913 0 +.latch g13447 g1914 0 +.latch g13448 g1916 0 +.latch g13449 g1917 0 +.latch g26002 g1918 0 +.latch g13450 g1921 0 +.latch g13452 g2003 0 +.latch gbuf167 g2006 0 +.latch gbuf168 g2009 0 +.latch g20566 g2010 0 +.latch g21945 g2039 0 +.latch g23237 g2020 0 +.latch g24378 g2013 0 +.latch g25162 g2033 0 +.latch g26009 g2026 0 +.latch g26725 g2040 0 +.latch g27227 g2052 0 +.latch g27706 g2046 0 +.latch g28283 g2059 0 +.latch g28687 g2066 0 +.latch g29154 g2072 0 +.latch g23238 g2079 0 +.latch g23239 g2080 0 +.latch g23240 g2078 0 +.latch g23241 g2082 0 +.latch g23242 g2083 0 +.latch g23243 g2081 0 +.latch g23244 g2085 0 +.latch g23245 g2086 0 +.latch g23246 g2084 0 +.latch g23247 g2088 0 +.latch g23248 g2089 0 +.latch g23249 g2087 0 +.latch g23250 g2091 0 +.latch g23251 g2092 0 +.latch g23252 g2090 0 +.latch g23253 g2094 0 +.latch g23254 g2095 0 +.latch g23255 g2093 0 +.latch g23256 g2097 0 +.latch g23257 g2098 0 +.latch g23258 g2096 0 +.latch g23259 g2100 0 +.latch g23260 g2101 0 +.latch g23261 g2099 0 +.latch g23262 g2103 0 +.latch g23263 g2104 0 +.latch g23264 g2102 0 +.latch g23265 g2106 0 +.latch g23266 g2107 0 +.latch g23267 g2105 0 +.latch g23268 g2109 0 +.latch g23269 g2110 0 +.latch g23270 g2108 0 +.latch g23271 g2112 0 +.latch g23272 g2113 0 +.latch g23273 g2111 0 +.latch g26726 g2115 0 +.latch g26727 g2116 0 +.latch g26728 g2114 0 +.latch g24379 g2118 0 +.latch g24380 g2119 0 +.latch g24381 g2117 0 +.latch g13453 g2214 0 +.latch gbuf169 g2211 0 +.latch gbuf170 g2241 0 +.latch g24382 g2206 0 +.latch g24383 g2207 0 +.latch g24384 g2205 0 +.latch g24385 g2209 0 +.latch g24386 g2210 0 +.latch g24387 g2208 0 +.latch g24388 g2218 0 +.latch g24389 g2219 0 +.latch g24390 g2217 0 +.latch g24391 g2221 0 +.latch g24392 g2222 0 +.latch g24393 g2220 0 +.latch g24394 g2224 0 +.latch g24395 g2225 0 +.latch g24396 g2223 0 +.latch g24397 g2227 0 +.latch g24398 g2228 0 +.latch g24399 g2226 0 +.latch g24400 g2230 0 +.latch g24401 g2231 0 +.latch g24402 g2229 0 +.latch g24403 g2233 0 +.latch g24404 g2234 0 +.latch g24405 g2232 0 +.latch g24406 g2236 0 +.latch g24407 g2237 0 +.latch g24408 g2235 0 +.latch g24409 g2239 0 +.latch g24410 g2240 0 +.latch g24411 g2238 0 +.latch g26730 g2245 0 +.latch g26731 g2246 0 +.latch g26732 g2244 0 +.latch g26733 g2248 0 +.latch g26734 g2249 0 +.latch g26735 g2247 0 +.latch g26736 g2251 0 +.latch g26737 g2252 0 +.latch g26738 g2250 0 +.latch g26739 g2254 0 +.latch g26740 g2255 0 +.latch g26741 g2253 0 +.latch g30551 g2261 0 +.latch g30552 g2264 0 +.latch g30553 g2267 0 +.latch g30896 g2306 0 +.latch g30897 g2309 0 +.latch g30898 g2312 0 +.latch g30890 g2270 0 +.latch g30891 g2273 0 +.latch g30892 g2276 0 +.latch g30899 g2315 0 +.latch g30900 g2318 0 +.latch g30901 g2321 0 +.latch g30554 g2279 0 +.latch g30555 g2282 0 +.latch g30556 g2285 0 +.latch g30560 g2324 0 +.latch g30561 g2327 0 +.latch g30562 g2330 0 +.latch g30557 g2288 0 +.latch g30558 g2291 0 +.latch g30559 g2294 0 +.latch g30563 g2333 0 +.latch g30564 g2336 0 +.latch g30565 g2339 0 +.latch g30893 g2297 0 +.latch g30894 g2300 0 +.latch g30895 g2303 0 +.latch g30902 g2342 0 +.latch g30903 g2345 0 +.latch g30904 g2348 0 +.latch g26010 g2160 0 +.latch g26729 g2156 0 +.latch g27228 g2151 0 +.latch g27707 g2147 0 +.latch g28284 g2142 0 +.latch g28688 g2138 0 +.latch g29155 g2133 0 +.latch g29446 g2129 0 +.latch g29648 g2124 0 +.latch g29806 g2120 0 +.latch g20567 g2256 0 +.latch gbuf171 g2258 0 +.latch gbuf172 g2257 0 +.latch g13454 g2351 0 +.latch gbuf173 g2480 0 +.latch gbuf174 g2476 0 +.latch g11577 g2384 0 +.latch g28285 g2429 0 +.latch g28286 g2418 0 +.latch g28287 g2421 0 +.latch g28288 g2444 0 +.latch g28289 g2433 0 +.latch g28290 g2436 0 +.latch g28291 g2459 0 +.latch g28292 g2448 0 +.latch g28293 g2451 0 +.latch g28294 g2473 0 +.latch g28295 g2463 0 +.latch g28296 g2466 0 +.latch g29447 g2483 0 +.latch g29448 g2486 0 +.latch g29449 g2489 0 +.latch g29652 g2492 0 +.latch g29653 g2495 0 +.latch g29654 g2498 0 +.latch g29450 g2502 0 +.latch g29451 g2503 0 +.latch g29452 g2501 0 +.latch g27708 g2504 0 +.latch g27709 g2507 0 +.latch g27710 g2510 0 +.latch g27711 g2513 0 +.latch g27712 g2516 0 +.latch g27713 g2519 0 +.latch g28689 g2523 0 +.latch g28690 g2524 0 +.latch g28691 g2522 0 +.latch g29807 g2387 0 +.latch g29808 g2388 0 +.latch g29809 g2389 0 +.latch g30905 g2390 0 +.latch g30906 g2391 0 +.latch g30907 g2392 0 +.latch g30719 g2393 0 +.latch g30720 g2394 0 +.latch g30721 g2395 0 +.latch g29649 g2397 0 +.latch g29650 g2398 0 +.latch g29651 g2396 0 +.latch g27230 g2478 0 +.latch g27231 g2479 0 +.latch g27232 g2477 0 +.latch g11590 g2525 0 +.latch gbuf175 g2526 0 +.latch g11591 g2527 0 +.latch gbuf176 g2528 0 +.latch g11592 g2529 0 +.latch gbuf177 g2354 0 +.latch g11572 g2355 0 +.latch gbuf178 g2356 0 +.latch g11573 g2357 0 +.latch gbuf179 g2358 0 +.latch g11574 g2359 0 +.latch gbuf180 g2360 0 +.latch g11575 g2361 0 +.latch gbuf181 g2362 0 +.latch g11576 g2363 0 +.latch gbuf182 g2364 0 +.latch g13455 g2365 0 +.latch gbuf183 g2366 0 +.latch g19048 g2374 0 +.latch g30314 g2380 0 +.latch g30315 g2383 0 +.latch g30316 g2372 0 +.latch g30317 g2371 0 +.latch g30318 g2370 0 +.latch g30319 g2369 0 +.latch g19052 g2379 0 +.latch g19051 g2378 0 +.latch g19050 g2377 0 +.latch g19049 g2376 0 +.latch g25163 g2375 0 +.latch g27229 g2373 0 +.latch g11578 g2417 0 +.latch gbuf184 g2424 0 +.latch g11579 g2425 0 +.latch gbuf185 g2426 0 +.latch g11580 g2427 0 +.latch gbuf186 g2428 0 +.latch g11581 g2432 0 +.latch gbuf187 g2439 0 +.latch g11582 g2440 0 +.latch gbuf188 g2441 0 +.latch g11583 g2442 0 +.latch gbuf189 g2443 0 +.latch g11584 g2447 0 +.latch gbuf190 g2454 0 +.latch g11585 g2455 0 +.latch gbuf191 g2456 0 +.latch g11586 g2457 0 +.latch gbuf192 g2458 0 +.latch g11587 g2462 0 +.latch gbuf193 g2469 0 +.latch g11588 g2470 0 +.latch gbuf194 g2471 0 +.latch g11589 g2472 0 +.latch gbuf195 g2399 0 +.latch g13456 g2400 0 +.latch gbuf196 g2406 0 +.latch gbuf197 g2412 0 +.latch g13467 g2619 0 +.latch gbuf198 g2625 0 +.latch gbuf199 g2624 0 +.latch g23274 g2628 0 +.latch g20568 g2631 0 +.latch g20569 g2584 0 +.latch g16473 g2587 0 +.latch gbuf200 g2597 0 +.latch gbuf201 g2598 0 +.latch g11593 g2638 0 +.latch gbuf202 g2643 0 +.latch g11596 g2644 0 +.latch gbuf203 g2645 0 +.latch g11597 g2646 0 +.latch gbuf204 g2647 0 +.latch g11598 g2648 0 +.latch gbuf205 g2639 0 +.latch g11594 g2640 0 +.latch gbuf206 g2641 0 +.latch g11595 g2642 0 +.latch gbuf207 g2564 0 +.latch g13457 g2549 0 +.latch gbuf208 g2556 0 +.latch gbuf209 g2560 0 +.latch g24415 g2561 0 +.latch g24416 g2562 0 +.latch g24417 g2563 0 +.latch g25172 g2530 0 +.latch g25164 g2533 0 +.latch g25165 g2536 0 +.latch g25169 g2552 0 +.latch g25170 g2553 0 +.latch g25171 g2554 0 +.latch g24412 g2555 0 +.latch g24413 g2559 0 +.latch g24414 g2539 0 +.latch g25166 g2540 0 +.latch g25167 g2543 0 +.latch g25168 g2546 0 +.latch g16474 g2602 0 +.latch gbuf210 g2609 0 +.latch gbuf211 g2616 0 +.latch g19057 g2617 0 +.latch gbuf212 g2618 0 +.latch g30325 g2622 0 +.latch g19058 g2623 0 +.latch gbuf213 g2574 0 +.latch g19059 g2632 0 +.latch gbuf214 g2633 0 +.latch g28297 g2650 0 +.latch g28298 g2651 0 +.latch g28299 g2649 0 +.latch g28300 g2653 0 +.latch g28301 g2654 0 +.latch g28302 g2652 0 +.latch g28303 g2656 0 +.latch g28304 g2657 0 +.latch g28305 g2655 0 +.latch g28306 g2659 0 +.latch g28307 g2660 0 +.latch g28308 g2658 0 +.latch g26012 g2661 0 +.latch g26013 g2664 0 +.latch g26014 g2667 0 +.latch g26015 g2670 0 +.latch g26016 g2673 0 +.latch g26017 g2676 0 +.latch g29159 g2688 0 +.latch g29160 g2691 0 +.latch g29161 g2694 0 +.latch g29156 g2679 0 +.latch g29157 g2682 0 +.latch g29158 g2685 0 +.latch g27233 g2565 0 +.latch g27234 g2568 0 +.latch g27235 g2571 0 +.latch g8311 g2580 0 +.latch g24418 g2581 0 +.latch g19053 g2582 0 +.latch g19054 g2583 0 +.latch g19055 g2588 0 +.latch g19056 g2589 0 +.latch g30324 g2590 0 +.latch g30323 g2591 0 +.latch g30322 g2592 0 +.latch g30321 g2593 0 +.latch g30320 g2594 0 +.latch gbuf215 g2599 0 +.latch g13458 g2603 0 +.latch g13459 g2604 0 +.latch g13460 g2605 0 +.latch g13461 g2606 0 +.latch g13462 g2607 0 +.latch g13463 g2608 0 +.latch g13464 g2610 0 +.latch g13465 g2611 0 +.latch g26011 g2612 0 +.latch g13466 g2615 0 +.latch g13468 g2697 0 +.latch gbuf216 g2700 0 +.latch gbuf217 g2703 0 +.latch g20570 g2704 0 +.latch g21946 g2733 0 +.latch g23275 g2714 0 +.latch g24419 g2707 0 +.latch g25173 g2727 0 +.latch g26018 g2720 0 +.latch g26742 g2734 0 +.latch g27236 g2746 0 +.latch g27714 g2740 0 +.latch g28309 g2753 0 +.latch g28692 g2760 0 +.latch g29162 g2766 0 +.latch g23276 g2773 0 +.latch g23277 g2774 0 +.latch g23278 g2772 0 +.latch g23279 g2776 0 +.latch g23280 g2777 0 +.latch g23281 g2775 0 +.latch g23282 g2779 0 +.latch g23283 g2780 0 +.latch g23284 g2778 0 +.latch g23285 g2782 0 +.latch g23286 g2783 0 +.latch g23287 g2781 0 +.latch g23288 g2785 0 +.latch g23289 g2786 0 +.latch g23290 g2784 0 +.latch g23291 g2788 0 +.latch g23292 g2789 0 +.latch g23293 g2787 0 +.latch g23294 g2791 0 +.latch g23295 g2792 0 +.latch g23296 g2790 0 +.latch g23297 g2794 0 +.latch g23298 g2795 0 +.latch g23299 g2793 0 +.latch g23300 g2797 0 +.latch g23301 g2798 0 +.latch g23302 g2796 0 +.latch g23303 g2800 0 +.latch g23304 g2801 0 +.latch g23305 g2799 0 +.latch g23306 g2803 0 +.latch g23307 g2804 0 +.latch g23308 g2802 0 +.latch g23309 g2806 0 +.latch g23310 g2807 0 +.latch g23311 g2805 0 +.latch g26743 g2809 0 +.latch g26744 g2810 0 +.latch g26745 g2808 0 +.latch g24420 g2812 0 +.latch g24421 g2813 0 +.latch g24422 g2811 0 +.latch g23317 g3054 0 +.latch g23318 g3079 0 +.latch g21965 g3080 0 +.latch g29453 g3043 0 +.latch g29454 g3044 0 +.latch g29455 g3045 0 +.latch g29456 g3046 0 +.latch g29457 g3047 0 +.latch g29458 g3048 0 +.latch g29459 g3049 0 +.latch g29460 g3050 0 +.latch g29655 g3051 0 +.latch g29972 g3052 0 +.latch g29973 g3053 0 +.latch g29974 g3055 0 +.latch g29975 g3056 0 +.latch g29976 g3057 0 +.latch g29977 g3058 0 +.latch g29978 g3059 0 +.latch g29979 g3060 0 +.latch g30119 g3061 0 +.latch g30908 g3062 0 +.latch g30909 g3063 0 +.latch g30910 g3064 0 +.latch g30911 g3065 0 +.latch g30912 g3066 0 +.latch g30913 g3067 0 +.latch g30914 g3068 0 +.latch g30915 g3069 0 +.latch g30940 g3070 0 +.latch g30980 g3071 0 +.latch g30981 g3072 0 +.latch g30982 g3073 0 +.latch g30983 g3074 0 +.latch g30984 g3075 0 +.latch g30985 g3076 0 +.latch g30986 g3077 0 +.latch g30987 g3078 0 +.latch g30989 g2997 0 +.latch g26748 g2993 0 +.latch g27238 g2998 0 +.latch g25177 g3006 0 +.latch g26021 g3002 0 +.latch g26750 g3013 0 +.latch g27239 g3010 0 +.latch g27716 g3024 0 +.latch g24425 g3018 0 +.latch g25176 g3028 0 +.latch g26022 g3036 0 +.latch g26749 g3032 0 +.latch g16497 g3040 0 +.latch gbuf218 g2986 0 +.latch g16495 g2987 0 +.latch g20595 g48 0 +.latch g20596 g45 0 +.latch g20597 g42 0 +.latch g20598 g39 0 +.latch g20599 g27 0 +.latch g20600 g30 0 +.latch g20601 g33 0 +.latch g20602 g36 0 +.latch g20603 g3083 0 +.latch g20604 g26 0 +.latch g21966 g2992 0 +.latch g20605 g23 0 +.latch g20606 g20 0 +.latch g20607 g17 0 +.latch g20608 g11 0 +.latch g20589 g14 0 +.latch g20590 g5 0 +.latch g20591 g8 0 +.latch g20592 g2 0 +.latch g20593 g2990 0 +.latch g21964 g2991 0 +.latch g20594 g1 0 +.names II13275 g3993 +0 1 +.names II13316 g4088 +0 1 +.names II13320 g4090 +0 1 +.names II13366 g4200 +0 1 +.names II13417 g4321 +0 1 +.names II13421 g4323 +0 1 +.names II13478 g4450 +0 1 +.names II13538 g4590 +0 1 +.names II13892 g5388 +0 1 +.names II13999 g5437 +0 1 +.names II14006 g5472 +0 1 +.names II14017 g5511 +0 1 +.names II14027 g5549 +0 1 +.names II14037 g5555 +0 1 +.names II14049 g5595 +0 1 +.names II14066 g5612 +0 1 +.names II14083 g5629 +0 1 +.names II14091 g5637 +0 1 +.names II14104 g5648 +0 1 +.names II14113 g5657 +0 1 +.names II14134 g5686 +0 1 +.names II14143 g5695 +0 1 +.names II14182 g5738 +0 1 +.names II14191 g5747 +0 1 +.names II14238 g5796 +0 1 +.names II14704 g6225 +0 1 +.names II14712 g6231 +0 1 +.names II14731 g6313 +0 1 +.names II14739 g6368 +0 1 +.names II14755 g6442 +0 1 +.names II14760 g6447 +0 1 +.names II14766 g6485 +0 1 +.names II14775 g6518 +0 1 +.names II14783 g6573 +0 1 +.names II14799 g6642 +0 1 +.names II14808 g6677 +0 1 +.names II14816 g6712 +0 1 +.names II14822 g6750 +0 1 +.names II14831 g6782 +0 1 +.names II14839 g6837 +0 1 +.names II14848 g6895 +0 1 +.names II14857 g6911 +0 1 +.names II14865 g6944 +0 1 +.names II14874 g6979 +0 1 +.names II14882 g7014 +0 1 +.names II14888 g7052 +0 1 +.names II14897 g7084 +0 1 +.names II14917 g7161 +0 1 +.names II14925 g7194 +0 1 +.names II14934 g7229 +0 1 +.names II14942 g7264 +0 1 +.names II14948 g7302 +0 1 +.names II14957 g7334 +0 1 +.names II14973 g7357 +0 1 +.names II14981 g7390 +0 1 +.names II14990 g7425 +0 1 +.names II15012 g7487 +0 1 +.names II15019 g7519 +0 1 +.names II15226 g7909 +0 1 +.names II15262 g7956 +0 1 +.names II15267 g7961 +0 1 +.names II15299 g8007 +0 1 +.names II15304 g8012 +0 1 +.names II15313 g8021 +0 1 +.names II15317 g8023 +0 1 +.names II15326 g8030 +0 1 +.names II15345 g8082 +0 1 +.names II15350 g8087 +0 1 +.names II15359 g8096 +0 1 +.names II15369 g8106 +0 1 +.names II15392 g8167 +0 1 +.names II15398 g8175 +0 1 +.names II15429 g8249 +0 1 +.names II15433 g8251 +0 1 +.names II15442 g8258 +0 1 +.names II15445 g8259 +0 1 +.names II15448 g8260 +0 1 +.names II15451 g8261 +0 1 +.names II15454 g8262 +0 1 +.names II15457 g8263 +0 1 +.names II15460 g8264 +0 1 +.names II15463 g8265 +0 1 +.names II15466 g8266 +0 1 +.names II15469 g8267 +0 1 +.names II15472 g8268 +0 1 +.names II15475 g8269 +0 1 +.names II15478 g8270 +0 1 +.names II15481 g8271 +0 1 +.names II15484 g8272 +0 1 +.names II15487 g8273 +0 1 +.names II15490 g8274 +0 1 +.names II15493 g8275 +0 1 +.names II22382 g16297 +0 1 +.names II22414 g16355 +0 1 +.names II22444 g16399 +0 1 +.names II22475 g16437 +0 1 +.names II22590 g16496 +0 1 +.names II32248 g24734 +0 1 +.names II33246 g25420 +0 1 +.names II33257 g25435 +0 1 +.names II33265 g25442 +0 1 +.names g24795 g16466 g25489 +1- 1 +-1 1 +.names II33999 g26104 +0 1 +.names II34029 g26135 +0 1 +.names II34041 g26149 +0 1 +.names II35708 g27380 +0 1 +.names II22527 g16475 +0 1 +.names II27038 g20571 +0 1 +.names II27089 g20588 +0 1 +.names II28479 g21951 +0 1 +.names II30398 g23315 +0 1 +.names II31943 g24423 +0 1 +.names II33003 g25175 +0 1 +.names II33909 g26019 +0 1 +.names II34848 g26747 +0 1 +.names II35548 g27237 +0 1 +.names II36156 g27715 +0 1 +.names II31946 g24424 +0 1 +.names II33000 g25174 +0 1 +.names II33912 g26020 +0 1 +.names II34845 g26746 +0 1 +.names II25246 g19061 +0 1 +.names II25243 g19060 +0 1 +.names II25249 g19062 +0 1 +.names g2930 gbuf1 +1 1 +.names II22584 g16494 +0 1 +.names II22530 g16476 +0 1 +.names II22533 g16477 +0 1 +.names II22536 g16478 +0 1 +.names II22539 g16479 +0 1 +.names II22542 g16480 +0 1 +.names II22545 g16481 +0 1 +.names II22548 g16482 +0 1 +.names II22551 g16483 +0 1 +.names II22554 g16484 +0 1 +.names II22557 g16485 +0 1 +.names II22560 g16486 +0 1 +.names II22563 g16487 +0 1 +.names II22566 g16488 +0 1 +.names II22569 g16489 +0 1 +.names II22572 g16490 +0 1 +.names II22575 g16491 +0 1 +.names II22578 g16492 +0 1 +.names II22581 g16493 +0 1 +.names II27041 g20572 +0 1 +.names II27044 g20573 +0 1 +.names II27047 g20574 +0 1 +.names II27050 g20575 +0 1 +.names II27053 g20576 +0 1 +.names II27056 g20577 +0 1 +.names II27059 g20578 +0 1 +.names II27062 g20579 +0 1 +.names II30392 g23313 +0 1 +.names II28506 g21960 +0 1 +.names g2861 gbuf2 +1 1 +.names II28509 g21961 +0 1 +.names g2864 gbuf3 +1 1 +.names II28512 g21962 +0 1 +.names g2867 gbuf4 +1 1 +.names II28515 g21963 +0 1 +.names g2870 gbuf5 +1 1 +.names II28467 g21947 +0 1 +.names g2818 gbuf6 +1 1 +.names II28470 g21948 +0 1 +.names g2821 gbuf7 +1 1 +.names II28473 g21949 +0 1 +.names g2824 gbuf8 +1 1 +.names II28476 g21950 +0 1 +.names g2827 gbuf9 +1 1 +.names II30389 g23312 +0 1 +.names g2830 gbuf10 +1 1 +.names II28482 g21952 +0 1 +.names g2833 gbuf11 +1 1 +.names II28485 g21953 +0 1 +.names g2836 gbuf12 +1 1 +.names II28488 g21954 +0 1 +.names g2839 gbuf13 +1 1 +.names II28491 g21955 +0 1 +.names g2842 gbuf14 +1 1 +.names II28494 g21956 +0 1 +.names g2845 gbuf15 +1 1 +.names II28497 g21957 +0 1 +.names g2848 gbuf16 +1 1 +.names II28500 g21958 +0 1 +.names g2851 gbuf17 +1 1 +.names II28503 g21959 +0 1 +.names g2854 gbuf18 +1 1 +.names II30401 g23316 +0 1 +.names g2858 gbuf19 +1 1 +.names II27086 g20587 +0 1 +.names II27080 g20585 +0 1 +.names II27083 g20586 +0 1 +.names II27077 g20584 +0 1 +.names II27074 g20583 +0 1 +.names II27071 g20582 +0 1 +.names II27068 g20581 +0 1 +.names II27065 g20580 +0 1 +.names II30395 g23314 +0 1 +.names II20709 g13475 +0 1 +.names g3129 gbuf20 +1 1 +.names g3117 gbuf21 +1 1 +.names II27215 g20630 +0 1 +.names II27218 g20631 +0 1 +.names II27221 g20632 +0 1 +.names II27152 g20609 +0 1 +.names II27155 g20610 +0 1 +.names II27158 g20611 +0 1 +.names II27161 g20612 +0 1 +.names II27164 g20613 +0 1 +.names II27167 g20614 +0 1 +.names II27170 g20615 +0 1 +.names II27173 g20616 +0 1 +.names II27176 g20617 +0 1 +.names II34860 g26751 +0 1 +.names II34863 g26752 +0 1 +.names II34866 g26753 +0 1 +.names II38232 g29163 +0 1 +.names II38235 g29164 +0 1 +.names II38238 g29165 +0 1 +.names II39625 g30120 +0 1 +.names II39628 g30121 +0 1 +.names II39631 g30122 +0 1 +.names II41047 g30941 +0 1 +.names II41050 g30942 +0 1 +.names II41053 g30943 +0 1 +.names II27179 g20618 +0 1 +.names II27182 g20619 +0 1 +.names II27185 g20620 +0 1 +.names II27188 g20621 +0 1 +.names II27191 g20622 +0 1 +.names II27194 g20623 +0 1 +.names II27197 g20624 +0 1 +.names II27200 g20625 +0 1 +.names II27203 g20626 +0 1 +.names II27206 g20627 +0 1 +.names II27209 g20628 +0 1 +.names II27212 g20629 +0 1 +.names II36162 g27717 +0 1 +.names II37197 g28316 +0 1 +.names II37200 g28317 +0 1 +.names II37203 g28318 +0 1 +.names II37659 g28704 +0 1 +.names II37662 g28705 +0 1 +.names II37665 g28706 +0 1 +.names II38770 g29463 +0 1 +.names II39086 g29656 +0 1 +.names II37641 g28698 +0 1 +.names II38241 g29166 +0 1 +.names II37638 g28697 +0 1 +.names II37194 g28315 +0 1 +.names II37635 g28696 +0 1 +.names II37191 g28314 +0 1 +.names II37188 g28313 +0 1 +.names II37632 g28695 +0 1 +.names II37629 g28694 +0 1 +.names II37626 g28693 +0 1 +.names II37185 g28312 +0 1 +.names II37182 g28311 +0 1 +.names II37179 g28310 +0 1 +.names II38764 g29461 +0 1 +.names II37650 g28701 +0 1 +.names II37647 g28700 +0 1 +.names II37644 g28699 +0 1 +.names II38767 g29462 +0 1 +.names II37656 g28703 +0 1 +.names II37653 g28702 +0 1 +.names II39089 g29657 +0 1 +.names II20514 g13405 +0 1 +.names g138 gbuf22 +1 1 +.names g135 gbuf23 +1 1 +.names II31451 g24259 +0 1 +.names II31454 g24260 +0 1 +.names II31457 g24261 +0 1 +.names II31460 g24262 +0 1 +.names II31463 g24263 +0 1 +.names II31466 g24264 +0 1 +.names II31469 g24265 +0 1 +.names II31472 g24266 +0 1 +.names II31475 g24267 +0 1 +.names II31478 g24268 +0 1 +.names II31481 g24269 +0 1 +.names II31484 g24270 +0 1 +.names II31487 g24271 +0 1 +.names II31490 g24272 +0 1 +.names II31493 g24273 +0 1 +.names II31496 g24274 +0 1 +.names II31499 g24275 +0 1 +.names II31502 g24276 +0 1 +.names II31505 g24277 +0 1 +.names II31508 g24278 +0 1 +.names II31511 g24279 +0 1 +.names II31514 g24280 +0 1 +.names II31517 g24281 +0 1 +.names II31520 g24282 +0 1 +.names II31523 g24283 +0 1 +.names II31526 g24284 +0 1 +.names II31529 g24285 +0 1 +.names II31532 g24286 +0 1 +.names II31535 g24287 +0 1 +.names II31538 g24288 +0 1 +.names II34644 g26679 +0 1 +.names II34647 g26680 +0 1 +.names II34650 g26681 +0 1 +.names II34653 g26682 +0 1 +.names II34656 g26683 +0 1 +.names II34659 g26684 +0 1 +.names II34662 g26685 +0 1 +.names II34665 g26686 +0 1 +.names II34668 g26687 +0 1 +.names II34671 g26688 +0 1 +.names II34674 g26689 +0 1 +.names II34677 g26690 +0 1 +.names II40098 g30506 +0 1 +.names II40101 g30507 +0 1 +.names II40104 g30508 +0 1 +.names II40778 g30842 +0 1 +.names II40781 g30843 +0 1 +.names II40784 g30844 +0 1 +.names II40760 g30836 +0 1 +.names II40763 g30837 +0 1 +.names II40766 g30838 +0 1 +.names II40787 g30845 +0 1 +.names II40790 g30846 +0 1 +.names II40793 g30847 +0 1 +.names II40107 g30509 +0 1 +.names II40110 g30510 +0 1 +.names II40113 g30511 +0 1 +.names II40125 g30515 +0 1 +.names II40128 g30516 +0 1 +.names II40131 g30517 +0 1 +.names II40116 g30512 +0 1 +.names II40119 g30513 +0 1 +.names II40122 g30514 +0 1 +.names II40134 g30518 +0 1 +.names II40137 g30519 +0 1 +.names II40140 g30520 +0 1 +.names II40769 g30839 +0 1 +.names II40772 g30840 +0 1 +.names II40775 g30841 +0 1 +.names II40796 g30848 +0 1 +.names II40799 g30849 +0 1 +.names II40802 g30850 +0 1 +.names II33801 g25983 +0 1 +.names II34641 g26678 +0 1 +.names II35404 g27189 +0 1 +.names II36060 g27683 +0 1 +.names II36867 g28206 +0 1 +.names II37566 g28673 +0 1 +.names II38136 g29131 +0 1 +.names II38620 g29413 +0 1 +.names II38999 g29627 +0 1 +.names II39234 g29794 +0 1 +.names II26990 g20555 +0 1 +.names g180 gbuf24 +1 1 +.names g182 gbuf25 +1 1 +.names II20517 g13406 +0 1 +.names g276 gbuf26 +1 1 +.names g405 gbuf27 +1 1 +.names II18464 g11496 +0 1 +.names II36870 g28207 +0 1 +.names II36873 g28208 +0 1 +.names II36876 g28209 +0 1 +.names II36879 g28210 +0 1 +.names II36882 g28211 +0 1 +.names II36885 g28212 +0 1 +.names II36888 g28213 +0 1 +.names II36891 g28214 +0 1 +.names II36894 g28215 +0 1 +.names II36897 g28216 +0 1 +.names II36900 g28217 +0 1 +.names II36903 g28218 +0 1 +.names II38623 g29414 +0 1 +.names II38626 g29415 +0 1 +.names II38629 g29416 +0 1 +.names II39011 g29631 +0 1 +.names II39014 g29632 +0 1 +.names II39017 g29633 +0 1 +.names II38632 g29417 +0 1 +.names II38635 g29418 +0 1 +.names II38638 g29419 +0 1 +.names II36063 g27684 +0 1 +.names II36066 g27685 +0 1 +.names II36069 g27686 +0 1 +.names II36072 g27687 +0 1 +.names II36075 g27688 +0 1 +.names II36078 g27689 +0 1 +.names II37569 g28674 +0 1 +.names II37572 g28675 +0 1 +.names II37575 g28676 +0 1 +.names II39237 g29795 +0 1 +.names II39240 g29796 +0 1 +.names II39243 g29797 +0 1 +.names II40805 g30851 +0 1 +.names II40808 g30852 +0 1 +.names II40811 g30853 +0 1 +.names II40420 g30710 +0 1 +.names II40423 g30711 +0 1 +.names II40426 g30712 +0 1 +.names II39002 g29628 +0 1 +.names II39005 g29629 +0 1 +.names II39008 g29630 +0 1 +.names II35410 g27191 +0 1 +.names II35413 g27192 +0 1 +.names II35416 g27193 +0 1 +.names II18503 g11509 +0 1 +.names g450 gbuf28 +1 1 +.names II18506 g11510 +0 1 +.names g452 gbuf29 +1 1 +.names II18509 g11511 +0 1 +.names g454 gbuf30 +1 1 +.names II18449 g11491 +0 1 +.names g280 gbuf31 +1 1 +.names II18452 g11492 +0 1 +.names g282 gbuf32 +1 1 +.names II18455 g11493 +0 1 +.names g284 gbuf33 +1 1 +.names II18458 g11494 +0 1 +.names g286 gbuf34 +1 1 +.names II18461 g11495 +0 1 +.names g288 gbuf35 +1 1 +.names II20520 g13407 +0 1 +.names g290 gbuf36 +1 1 +.names II25099 g19012 +0 1 +.names II29897 g23148 +0 1 +.names II29900 g23149 +0 1 +.names II29903 g23150 +0 1 +.names II29906 g23151 +0 1 +.names II29909 g23152 +0 1 +.names II29912 g23153 +0 1 +.names II25111 g19016 +0 1 +.names II25108 g19015 +0 1 +.names II25105 g19014 +0 1 +.names II25102 g19013 +0 1 +.names II32868 g25130 +0 1 +.names II35407 g27190 +0 1 +.names II18467 g11497 +0 1 +.names g342 gbuf37 +1 1 +.names II18470 g11498 +0 1 +.names g350 gbuf38 +1 1 +.names II18473 g11499 +0 1 +.names g352 gbuf39 +1 1 +.names II18476 g11500 +0 1 +.names g357 gbuf40 +1 1 +.names II18479 g11501 +0 1 +.names g365 gbuf41 +1 1 +.names II18482 g11502 +0 1 +.names g367 gbuf42 +1 1 +.names II18485 g11503 +0 1 +.names g372 gbuf43 +1 1 +.names II18488 g11504 +0 1 +.names g380 gbuf44 +1 1 +.names II18491 g11505 +0 1 +.names g382 gbuf45 +1 1 +.names II18494 g11506 +0 1 +.names g387 gbuf46 +1 1 +.names II18497 g11507 +0 1 +.names g395 gbuf47 +1 1 +.names II18500 g11508 +0 1 +.names g397 gbuf48 +1 1 +.names II20523 g13408 +0 1 +.names g325 gbuf49 +1 1 +.names g331 gbuf50 +1 1 +.names II20556 g13419 +0 1 +.names g545 gbuf51 +1 1 +.names g551 gbuf52 +1 1 +.names II29933 g23160 +0 1 +.names II26993 g20556 +0 1 +.names II26996 g20557 +0 1 +.names II22503 g16467 +0 1 +.names g513 gbuf53 +1 1 +.names g523 gbuf54 +1 1 +.names II18512 g11512 +0 1 +.names g564 gbuf55 +1 1 +.names II18521 g11515 +0 1 +.names g570 gbuf56 +1 1 +.names II18524 g11516 +0 1 +.names g572 gbuf57 +1 1 +.names II18527 g11517 +0 1 +.names g574 gbuf58 +1 1 +.names II18515 g11513 +0 1 +.names g566 gbuf59 +1 1 +.names II18518 g11514 +0 1 +.names g568 gbuf60 +1 1 +.names II20526 g13409 +0 1 +.names g474 gbuf61 +1 1 +.names g481 gbuf62 +1 1 +.names II31550 g24292 +0 1 +.names II31553 g24293 +0 1 +.names II31556 g24294 +0 1 +.names II32895 g25139 +0 1 +.names II32871 g25131 +0 1 +.names II32874 g25132 +0 1 +.names II32886 g25136 +0 1 +.names II32889 g25137 +0 1 +.names II32892 g25138 +0 1 +.names II31541 g24289 +0 1 +.names II31544 g24290 +0 1 +.names II31547 g24291 +0 1 +.names II32877 g25133 +0 1 +.names II32880 g25134 +0 1 +.names II32883 g25135 +0 1 +.names II22506 g16468 +0 1 +.names g528 gbuf63 +1 1 +.names g535 gbuf64 +1 1 +.names II25126 g19021 +0 1 +.names g543 gbuf65 +1 1 +.names II29930 g23159 +0 1 +.names II25129 g19022 +0 1 +.names g549 gbuf66 +1 1 +.names II25132 g19023 +0 1 +.names g558 gbuf67 +1 1 +.names II36906 g28219 +0 1 +.names II36909 g28220 +0 1 +.names II36912 g28221 +0 1 +.names II36915 g28222 +0 1 +.names II36918 g28223 +0 1 +.names II36921 g28224 +0 1 +.names II36924 g28225 +0 1 +.names II36927 g28226 +0 1 +.names II36930 g28227 +0 1 +.names II36933 g28228 +0 1 +.names II36936 g28229 +0 1 +.names II36939 g28230 +0 1 +.names II33807 g25985 +0 1 +.names II33810 g25986 +0 1 +.names II33813 g25987 +0 1 +.names II33816 g25988 +0 1 +.names II33819 g25989 +0 1 +.names II33822 g25990 +0 1 +.names II38148 g29135 +0 1 +.names II38151 g29136 +0 1 +.names II38154 g29137 +0 1 +.names II38139 g29132 +0 1 +.names II38142 g29133 +0 1 +.names II38145 g29134 +0 1 +.names II35419 g27194 +0 1 +.names II35422 g27195 +0 1 +.names II35425 g27196 +0 1 +.names II15499 g8284 +0 1 +.names II31559 g24295 +0 1 +.names II25114 g19017 +0 1 +.names II25117 g19018 +0 1 +.names II25120 g19019 +0 1 +.names II25123 g19020 +0 1 +.names II29927 g23158 +0 1 +.names II29924 g23157 +0 1 +.names II29921 g23156 +0 1 +.names II29918 g23155 +0 1 +.names II29915 g23154 +0 1 +.names g520 gbuf68 +1 1 +.names II20529 g13410 +0 1 +.names II20532 g13411 +0 1 +.names II20535 g13412 +0 1 +.names II20538 g13413 +0 1 +.names II20541 g13414 +0 1 +.names II20544 g13415 +0 1 +.names II20547 g13416 +0 1 +.names II20550 g13417 +0 1 +.names II33804 g25984 +0 1 +.names II20553 g13418 +0 1 +.names II20559 g13420 +0 1 +.names g623 gbuf69 +1 1 +.names g626 gbuf70 +1 1 +.names II26999 g20558 +0 1 +.names II28455 g21943 +0 1 +.names II29936 g23161 +0 1 +.names II31562 g24296 +0 1 +.names II32898 g25140 +0 1 +.names II33825 g25991 +0 1 +.names II34680 g26691 +0 1 +.names II35428 g27197 +0 1 +.names II36081 g27690 +0 1 +.names II36942 g28231 +0 1 +.names II37578 g28677 +0 1 +.names II38157 g29138 +0 1 +.names II29939 g23162 +0 1 +.names II29942 g23163 +0 1 +.names II29945 g23164 +0 1 +.names II29948 g23165 +0 1 +.names II29951 g23166 +0 1 +.names II29954 g23167 +0 1 +.names II29957 g23168 +0 1 +.names II29960 g23169 +0 1 +.names II29963 g23170 +0 1 +.names II29966 g23171 +0 1 +.names II29969 g23172 +0 1 +.names II29972 g23173 +0 1 +.names II29975 g23174 +0 1 +.names II29978 g23175 +0 1 +.names II29981 g23176 +0 1 +.names II29984 g23177 +0 1 +.names II29987 g23178 +0 1 +.names II29990 g23179 +0 1 +.names II29993 g23180 +0 1 +.names II29996 g23181 +0 1 +.names II29999 g23182 +0 1 +.names II30002 g23183 +0 1 +.names II30005 g23184 +0 1 +.names II30008 g23185 +0 1 +.names II30011 g23186 +0 1 +.names II30014 g23187 +0 1 +.names II30017 g23188 +0 1 +.names II30020 g23189 +0 1 +.names II30023 g23190 +0 1 +.names II30026 g23191 +0 1 +.names II30029 g23192 +0 1 +.names II30032 g23193 +0 1 +.names II30035 g23194 +0 1 +.names II30038 g23195 +0 1 +.names II30041 g23196 +0 1 +.names II30044 g23197 +0 1 +.names II34683 g26692 +0 1 +.names II34686 g26693 +0 1 +.names II34689 g26694 +0 1 +.names II31565 g24297 +0 1 +.names II31568 g24298 +0 1 +.names II31571 g24299 +0 1 +.names II20562 g13421 +0 1 +.names g826 gbuf71 +1 1 +.names g823 gbuf72 +1 1 +.names II31574 g24300 +0 1 +.names II31577 g24301 +0 1 +.names II31580 g24302 +0 1 +.names II31583 g24303 +0 1 +.names II31586 g24304 +0 1 +.names II31589 g24305 +0 1 +.names II31592 g24306 +0 1 +.names II31595 g24307 +0 1 +.names II31598 g24308 +0 1 +.names II31601 g24309 +0 1 +.names II31604 g24310 +0 1 +.names II31607 g24311 +0 1 +.names II31610 g24312 +0 1 +.names II31613 g24313 +0 1 +.names II31616 g24314 +0 1 +.names II31619 g24315 +0 1 +.names II31622 g24316 +0 1 +.names II31625 g24317 +0 1 +.names II31628 g24318 +0 1 +.names II31631 g24319 +0 1 +.names II31634 g24320 +0 1 +.names II31637 g24321 +0 1 +.names II31640 g24322 +0 1 +.names II31643 g24323 +0 1 +.names II31646 g24324 +0 1 +.names II31649 g24325 +0 1 +.names II31652 g24326 +0 1 +.names II31655 g24327 +0 1 +.names II31658 g24328 +0 1 +.names II31661 g24329 +0 1 +.names II34695 g26696 +0 1 +.names II34698 g26697 +0 1 +.names II34701 g26698 +0 1 +.names II34704 g26699 +0 1 +.names II34707 g26700 +0 1 +.names II34710 g26701 +0 1 +.names II34713 g26702 +0 1 +.names II34716 g26703 +0 1 +.names II34719 g26704 +0 1 +.names II34722 g26705 +0 1 +.names II34725 g26706 +0 1 +.names II34728 g26707 +0 1 +.names II40143 g30521 +0 1 +.names II40146 g30522 +0 1 +.names II40149 g30523 +0 1 +.names II40832 g30860 +0 1 +.names II40835 g30861 +0 1 +.names II40838 g30862 +0 1 +.names II40814 g30854 +0 1 +.names II40817 g30855 +0 1 +.names II40820 g30856 +0 1 +.names II40841 g30863 +0 1 +.names II40844 g30864 +0 1 +.names II40847 g30865 +0 1 +.names II40152 g30524 +0 1 +.names II40155 g30525 +0 1 +.names II40158 g30526 +0 1 +.names II40170 g30530 +0 1 +.names II40173 g30531 +0 1 +.names II40176 g30532 +0 1 +.names II40161 g30527 +0 1 +.names II40164 g30528 +0 1 +.names II40167 g30529 +0 1 +.names II40179 g30533 +0 1 +.names II40182 g30534 +0 1 +.names II40185 g30535 +0 1 +.names II40823 g30857 +0 1 +.names II40826 g30858 +0 1 +.names II40829 g30859 +0 1 +.names II40850 g30866 +0 1 +.names II40853 g30867 +0 1 +.names II40856 g30868 +0 1 +.names II33828 g25992 +0 1 +.names II34692 g26695 +0 1 +.names II35431 g27198 +0 1 +.names II36084 g27691 +0 1 +.names II36945 g28232 +0 1 +.names II37581 g28678 +0 1 +.names II38160 g29139 +0 1 +.names II38641 g29420 +0 1 +.names II39020 g29634 +0 1 +.names II39246 g29798 +0 1 +.names II27002 g20559 +0 1 +.names g868 gbuf73 +1 1 +.names g870 gbuf74 +1 1 +.names II20565 g13422 +0 1 +.names g963 gbuf75 +1 1 +.names g1092 gbuf76 +1 1 +.names II18545 g11523 +0 1 +.names II36948 g28233 +0 1 +.names II36951 g28234 +0 1 +.names II36954 g28235 +0 1 +.names II36957 g28236 +0 1 +.names II36960 g28237 +0 1 +.names II36963 g28238 +0 1 +.names II36966 g28239 +0 1 +.names II36969 g28240 +0 1 +.names II36972 g28241 +0 1 +.names II36975 g28242 +0 1 +.names II36978 g28243 +0 1 +.names II36981 g28244 +0 1 +.names II38644 g29421 +0 1 +.names II38647 g29422 +0 1 +.names II38650 g29423 +0 1 +.names II39032 g29638 +0 1 +.names II39035 g29639 +0 1 +.names II39038 g29640 +0 1 +.names II38653 g29424 +0 1 +.names II38656 g29425 +0 1 +.names II38659 g29426 +0 1 +.names II36087 g27692 +0 1 +.names II36090 g27693 +0 1 +.names II36093 g27694 +0 1 +.names II36096 g27695 +0 1 +.names II36099 g27696 +0 1 +.names II36102 g27697 +0 1 +.names II37584 g28679 +0 1 +.names II37587 g28680 +0 1 +.names II37590 g28681 +0 1 +.names II39249 g29799 +0 1 +.names II39252 g29800 +0 1 +.names II39255 g29801 +0 1 +.names II40859 g30869 +0 1 +.names II40862 g30870 +0 1 +.names II40865 g30871 +0 1 +.names II40429 g30713 +0 1 +.names II40432 g30714 +0 1 +.names II40435 g30715 +0 1 +.names II39023 g29635 +0 1 +.names II39026 g29636 +0 1 +.names II39029 g29637 +0 1 +.names II35455 g27206 +0 1 +.names II35458 g27207 +0 1 +.names II35461 g27208 +0 1 +.names II18584 g11536 +0 1 +.names g1137 gbuf77 +1 1 +.names II18587 g11537 +0 1 +.names g1139 gbuf78 +1 1 +.names II18590 g11538 +0 1 +.names g1141 gbuf79 +1 1 +.names II18530 g11518 +0 1 +.names g967 gbuf80 +1 1 +.names II18533 g11519 +0 1 +.names g969 gbuf81 +1 1 +.names II18536 g11520 +0 1 +.names g971 gbuf82 +1 1 +.names II18539 g11521 +0 1 +.names g973 gbuf83 +1 1 +.names II18542 g11522 +0 1 +.names g975 gbuf84 +1 1 +.names II20568 g13423 +0 1 +.names g977 gbuf85 +1 1 +.names II25135 g19024 +0 1 +.names II35437 g27200 +0 1 +.names II35440 g27201 +0 1 +.names II35443 g27202 +0 1 +.names II35446 g27203 +0 1 +.names II35449 g27204 +0 1 +.names II35452 g27205 +0 1 +.names II25147 g19028 +0 1 +.names II25144 g19027 +0 1 +.names II25141 g19026 +0 1 +.names II25138 g19025 +0 1 +.names II32901 g25141 +0 1 +.names II35434 g27199 +0 1 +.names II18548 g11524 +0 1 +.names g1029 gbuf86 +1 1 +.names II18551 g11525 +0 1 +.names g1037 gbuf87 +1 1 +.names II18554 g11526 +0 1 +.names g1039 gbuf88 +1 1 +.names II18557 g11527 +0 1 +.names g1044 gbuf89 +1 1 +.names II18560 g11528 +0 1 +.names g1052 gbuf90 +1 1 +.names II18563 g11529 +0 1 +.names g1054 gbuf91 +1 1 +.names II18566 g11530 +0 1 +.names g1059 gbuf92 +1 1 +.names II18569 g11531 +0 1 +.names g1067 gbuf93 +1 1 +.names II18572 g11532 +0 1 +.names g1069 gbuf94 +1 1 +.names II18575 g11533 +0 1 +.names g1074 gbuf95 +1 1 +.names II18578 g11534 +0 1 +.names g1082 gbuf96 +1 1 +.names II18581 g11535 +0 1 +.names g1084 gbuf97 +1 1 +.names II20571 g13424 +0 1 +.names g1012 gbuf98 +1 1 +.names g1018 gbuf99 +1 1 +.names II20604 g13435 +0 1 +.names g1231 gbuf100 +1 1 +.names g1237 gbuf101 +1 1 +.names II30047 g23198 +0 1 +.names II27005 g20560 +0 1 +.names II27008 g20561 +0 1 +.names II22509 g16469 +0 1 +.names g1199 gbuf102 +1 1 +.names g1209 gbuf103 +1 1 +.names II18593 g11539 +0 1 +.names g1250 gbuf104 +1 1 +.names II18602 g11542 +0 1 +.names g1256 gbuf105 +1 1 +.names II18605 g11543 +0 1 +.names g1258 gbuf106 +1 1 +.names II18608 g11544 +0 1 +.names g1260 gbuf107 +1 1 +.names II18596 g11540 +0 1 +.names g1252 gbuf108 +1 1 +.names II18599 g11541 +0 1 +.names g1254 gbuf109 +1 1 +.names II20574 g13425 +0 1 +.names g1161 gbuf110 +1 1 +.names g1168 gbuf111 +1 1 +.names II31673 g24333 +0 1 +.names II31676 g24334 +0 1 +.names II31679 g24335 +0 1 +.names II32928 g25150 +0 1 +.names II32904 g25142 +0 1 +.names II32907 g25143 +0 1 +.names II32919 g25147 +0 1 +.names II32922 g25148 +0 1 +.names II32925 g25149 +0 1 +.names II31664 g24330 +0 1 +.names II31667 g24331 +0 1 +.names II31670 g24332 +0 1 +.names II32910 g25144 +0 1 +.names II32913 g25145 +0 1 +.names II32916 g25146 +0 1 +.names II22512 g16470 +0 1 +.names g1214 gbuf112 +1 1 +.names g1221 gbuf113 +1 1 +.names II25162 g19033 +0 1 +.names g1229 gbuf114 +1 1 +.names II35488 g27217 +0 1 +.names II25165 g19034 +0 1 +.names g1235 gbuf115 +1 1 +.names II25168 g19035 +0 1 +.names g1244 gbuf116 +1 1 +.names II36984 g28245 +0 1 +.names II36987 g28246 +0 1 +.names II36990 g28247 +0 1 +.names II36993 g28248 +0 1 +.names II36996 g28249 +0 1 +.names II36999 g28250 +0 1 +.names II37002 g28251 +0 1 +.names II37005 g28252 +0 1 +.names II37008 g28253 +0 1 +.names II37011 g28254 +0 1 +.names II37014 g28255 +0 1 +.names II37017 g28256 +0 1 +.names II33834 g25994 +0 1 +.names II33837 g25995 +0 1 +.names II33840 g25996 +0 1 +.names II33843 g25997 +0 1 +.names II33846 g25998 +0 1 +.names II33849 g25999 +0 1 +.names II38172 g29143 +0 1 +.names II38175 g29144 +0 1 +.names II38178 g29145 +0 1 +.names II38163 g29140 +0 1 +.names II38166 g29141 +0 1 +.names II38169 g29142 +0 1 +.names II35464 g27209 +0 1 +.names II35467 g27210 +0 1 +.names II35470 g27211 +0 1 +.names II15505 g8293 +0 1 +.names II31682 g24336 +0 1 +.names II25150 g19029 +0 1 +.names II25153 g19030 +0 1 +.names II25156 g19031 +0 1 +.names II25159 g19032 +0 1 +.names II35485 g27216 +0 1 +.names II35482 g27215 +0 1 +.names II35479 g27214 +0 1 +.names II35476 g27213 +0 1 +.names II35473 g27212 +0 1 +.names g1206 gbuf117 +1 1 +.names II20577 g13426 +0 1 +.names II20580 g13427 +0 1 +.names II20583 g13428 +0 1 +.names II20586 g13429 +0 1 +.names II20589 g13430 +0 1 +.names II20592 g13431 +0 1 +.names II20595 g13432 +0 1 +.names II20598 g13433 +0 1 +.names II33831 g25993 +0 1 +.names II20601 g13434 +0 1 +.names II20607 g13436 +0 1 +.names g1309 gbuf118 +1 1 +.names g1312 gbuf119 +1 1 +.names II27011 g20562 +0 1 +.names II28458 g21944 +0 1 +.names II30050 g23199 +0 1 +.names II31685 g24337 +0 1 +.names II32931 g25151 +0 1 +.names II33852 g26000 +0 1 +.names II34731 g26708 +0 1 +.names II35491 g27218 +0 1 +.names II36105 g27698 +0 1 +.names II37020 g28257 +0 1 +.names II37593 g28682 +0 1 +.names II38181 g29146 +0 1 +.names II30053 g23200 +0 1 +.names II30056 g23201 +0 1 +.names II30059 g23202 +0 1 +.names II30062 g23203 +0 1 +.names II30065 g23204 +0 1 +.names II30068 g23205 +0 1 +.names II30071 g23206 +0 1 +.names II30074 g23207 +0 1 +.names II30077 g23208 +0 1 +.names II30080 g23209 +0 1 +.names II30083 g23210 +0 1 +.names II30086 g23211 +0 1 +.names II30089 g23212 +0 1 +.names II30092 g23213 +0 1 +.names II30095 g23214 +0 1 +.names II30098 g23215 +0 1 +.names II30101 g23216 +0 1 +.names II30104 g23217 +0 1 +.names II30107 g23218 +0 1 +.names II30110 g23219 +0 1 +.names II30113 g23220 +0 1 +.names II30116 g23221 +0 1 +.names II30119 g23222 +0 1 +.names II30122 g23223 +0 1 +.names II30125 g23224 +0 1 +.names II30128 g23225 +0 1 +.names II30131 g23226 +0 1 +.names II30134 g23227 +0 1 +.names II30137 g23228 +0 1 +.names II30140 g23229 +0 1 +.names II30143 g23230 +0 1 +.names II30146 g23231 +0 1 +.names II30149 g23232 +0 1 +.names II30152 g23233 +0 1 +.names II30155 g23234 +0 1 +.names II30158 g23235 +0 1 +.names II34734 g26709 +0 1 +.names II34737 g26710 +0 1 +.names II34740 g26711 +0 1 +.names II31688 g24338 +0 1 +.names II31691 g24339 +0 1 +.names II31694 g24340 +0 1 +.names II20610 g13437 +0 1 +.names g1520 gbuf120 +1 1 +.names g1517 gbuf121 +1 1 +.names II31697 g24341 +0 1 +.names II31700 g24342 +0 1 +.names II31703 g24343 +0 1 +.names II31706 g24344 +0 1 +.names II31709 g24345 +0 1 +.names II31712 g24346 +0 1 +.names II31715 g24347 +0 1 +.names II31718 g24348 +0 1 +.names II31721 g24349 +0 1 +.names II31724 g24350 +0 1 +.names II31727 g24351 +0 1 +.names II31730 g24352 +0 1 +.names II31733 g24353 +0 1 +.names II31736 g24354 +0 1 +.names II31739 g24355 +0 1 +.names II31742 g24356 +0 1 +.names II31745 g24357 +0 1 +.names II31748 g24358 +0 1 +.names II31751 g24359 +0 1 +.names II31754 g24360 +0 1 +.names II31757 g24361 +0 1 +.names II31760 g24362 +0 1 +.names II31763 g24363 +0 1 +.names II31766 g24364 +0 1 +.names II31769 g24365 +0 1 +.names II31772 g24366 +0 1 +.names II31775 g24367 +0 1 +.names II31778 g24368 +0 1 +.names II31781 g24369 +0 1 +.names II31784 g24370 +0 1 +.names II34746 g26713 +0 1 +.names II34749 g26714 +0 1 +.names II34752 g26715 +0 1 +.names II34755 g26716 +0 1 +.names II34758 g26717 +0 1 +.names II34761 g26718 +0 1 +.names II34764 g26719 +0 1 +.names II34767 g26720 +0 1 +.names II34770 g26721 +0 1 +.names II34773 g26722 +0 1 +.names II34776 g26723 +0 1 +.names II34779 g26724 +0 1 +.names II40188 g30536 +0 1 +.names II40191 g30537 +0 1 +.names II40194 g30538 +0 1 +.names II40886 g30878 +0 1 +.names II40889 g30879 +0 1 +.names II40892 g30880 +0 1 +.names II40868 g30872 +0 1 +.names II40871 g30873 +0 1 +.names II40874 g30874 +0 1 +.names II40895 g30881 +0 1 +.names II40898 g30882 +0 1 +.names II40901 g30883 +0 1 +.names II40197 g30539 +0 1 +.names II40200 g30540 +0 1 +.names II40203 g30541 +0 1 +.names II40215 g30545 +0 1 +.names II40218 g30546 +0 1 +.names II40221 g30547 +0 1 +.names II40206 g30542 +0 1 +.names II40209 g30543 +0 1 +.names II40212 g30544 +0 1 +.names II40224 g30548 +0 1 +.names II40227 g30549 +0 1 +.names II40230 g30550 +0 1 +.names II40877 g30875 +0 1 +.names II40880 g30876 +0 1 +.names II40883 g30877 +0 1 +.names II40904 g30884 +0 1 +.names II40907 g30885 +0 1 +.names II40910 g30886 +0 1 +.names II33855 g26001 +0 1 +.names II34743 g26712 +0 1 +.names II35494 g27219 +0 1 +.names II36108 g27699 +0 1 +.names II37023 g28258 +0 1 +.names II37596 g28683 +0 1 +.names II38184 g29147 +0 1 +.names II38662 g29427 +0 1 +.names II39041 g29641 +0 1 +.names II39258 g29802 +0 1 +.names II27014 g20563 +0 1 +.names g1562 gbuf122 +1 1 +.names g1564 gbuf123 +1 1 +.names II20613 g13438 +0 1 +.names g1657 gbuf124 +1 1 +.names g1786 gbuf125 +1 1 +.names II18626 g11550 +0 1 +.names II37026 g28259 +0 1 +.names II37029 g28260 +0 1 +.names II37032 g28261 +0 1 +.names II37035 g28262 +0 1 +.names II37038 g28263 +0 1 +.names II37041 g28264 +0 1 +.names II37044 g28265 +0 1 +.names II37047 g28266 +0 1 +.names II37050 g28267 +0 1 +.names II37053 g28268 +0 1 +.names II37056 g28269 +0 1 +.names II37059 g28270 +0 1 +.names II38683 g29434 +0 1 +.names II38686 g29435 +0 1 +.names II38689 g29436 +0 1 +.names II39053 g29645 +0 1 +.names II39056 g29646 +0 1 +.names II39059 g29647 +0 1 +.names II38692 g29437 +0 1 +.names II38695 g29438 +0 1 +.names II38698 g29439 +0 1 +.names II36111 g27700 +0 1 +.names II36114 g27701 +0 1 +.names II36117 g27702 +0 1 +.names II36120 g27703 +0 1 +.names II36123 g27704 +0 1 +.names II36126 g27705 +0 1 +.names II37599 g28684 +0 1 +.names II37602 g28685 +0 1 +.names II37605 g28686 +0 1 +.names II39261 g29803 +0 1 +.names II39264 g29804 +0 1 +.names II39267 g29805 +0 1 +.names II40913 g30887 +0 1 +.names II40916 g30888 +0 1 +.names II40919 g30889 +0 1 +.names II40438 g30716 +0 1 +.names II40441 g30717 +0 1 +.names II40444 g30718 +0 1 +.names II39044 g29642 +0 1 +.names II39047 g29643 +0 1 +.names II39050 g29644 +0 1 +.names II35500 g27221 +0 1 +.names II35503 g27222 +0 1 +.names II35506 g27223 +0 1 +.names II18665 g11563 +0 1 +.names g1831 gbuf126 +1 1 +.names II18668 g11564 +0 1 +.names g1833 gbuf127 +1 1 +.names II18671 g11565 +0 1 +.names g1835 gbuf128 +1 1 +.names II18611 g11545 +0 1 +.names g1661 gbuf129 +1 1 +.names II18614 g11546 +0 1 +.names g1663 gbuf130 +1 1 +.names II18617 g11547 +0 1 +.names g1665 gbuf131 +1 1 +.names II18620 g11548 +0 1 +.names g1667 gbuf132 +1 1 +.names II18623 g11549 +0 1 +.names g1669 gbuf133 +1 1 +.names II20616 g13439 +0 1 +.names g1671 gbuf134 +1 1 +.names II25171 g19036 +0 1 +.names II38665 g29428 +0 1 +.names II38668 g29429 +0 1 +.names II38671 g29430 +0 1 +.names II38674 g29431 +0 1 +.names II38677 g29432 +0 1 +.names II38680 g29433 +0 1 +.names II25183 g19040 +0 1 +.names II25180 g19039 +0 1 +.names II25177 g19038 +0 1 +.names II25174 g19037 +0 1 +.names II32934 g25152 +0 1 +.names II35497 g27220 +0 1 +.names II18629 g11551 +0 1 +.names g1723 gbuf135 +1 1 +.names II18632 g11552 +0 1 +.names g1731 gbuf136 +1 1 +.names II18635 g11553 +0 1 +.names g1733 gbuf137 +1 1 +.names II18638 g11554 +0 1 +.names g1738 gbuf138 +1 1 +.names II18641 g11555 +0 1 +.names g1746 gbuf139 +1 1 +.names II18644 g11556 +0 1 +.names g1748 gbuf140 +1 1 +.names II18647 g11557 +0 1 +.names g1753 gbuf141 +1 1 +.names II18650 g11558 +0 1 +.names g1761 gbuf142 +1 1 +.names II18653 g11559 +0 1 +.names g1763 gbuf143 +1 1 +.names II18656 g11560 +0 1 +.names g1768 gbuf144 +1 1 +.names II18659 g11561 +0 1 +.names g1776 gbuf145 +1 1 +.names II18662 g11562 +0 1 +.names g1778 gbuf146 +1 1 +.names II20619 g13440 +0 1 +.names g1706 gbuf147 +1 1 +.names g1712 gbuf148 +1 1 +.names II20652 g13451 +0 1 +.names g1925 gbuf149 +1 1 +.names g1931 gbuf150 +1 1 +.names II30161 g23236 +0 1 +.names II27017 g20564 +0 1 +.names II27020 g20565 +0 1 +.names II22515 g16471 +0 1 +.names g1893 gbuf151 +1 1 +.names g1903 gbuf152 +1 1 +.names II18674 g11566 +0 1 +.names g1944 gbuf153 +1 1 +.names II18683 g11569 +0 1 +.names g1950 gbuf154 +1 1 +.names II18686 g11570 +0 1 +.names g1952 gbuf155 +1 1 +.names II18689 g11571 +0 1 +.names g1954 gbuf156 +1 1 +.names II18677 g11567 +0 1 +.names g1946 gbuf157 +1 1 +.names II18680 g11568 +0 1 +.names g1948 gbuf158 +1 1 +.names II20622 g13441 +0 1 +.names g1855 gbuf159 +1 1 +.names g1862 gbuf160 +1 1 +.names II31796 g24374 +0 1 +.names II31799 g24375 +0 1 +.names II31802 g24376 +0 1 +.names II32961 g25161 +0 1 +.names II32937 g25153 +0 1 +.names II32940 g25154 +0 1 +.names II32952 g25158 +0 1 +.names II32955 g25159 +0 1 +.names II32958 g25160 +0 1 +.names II31787 g24371 +0 1 +.names II31790 g24372 +0 1 +.names II31793 g24373 +0 1 +.names II32943 g25155 +0 1 +.names II32946 g25156 +0 1 +.names II32949 g25157 +0 1 +.names II22518 g16472 +0 1 +.names g1908 gbuf161 +1 1 +.names g1915 gbuf162 +1 1 +.names II25198 g19045 +0 1 +.names g1923 gbuf163 +1 1 +.names II38716 g29445 +0 1 +.names II25201 g19046 +0 1 +.names g1929 gbuf164 +1 1 +.names II25204 g19047 +0 1 +.names g1938 gbuf165 +1 1 +.names II37062 g28271 +0 1 +.names II37065 g28272 +0 1 +.names II37068 g28273 +0 1 +.names II37071 g28274 +0 1 +.names II37074 g28275 +0 1 +.names II37077 g28276 +0 1 +.names II37080 g28277 +0 1 +.names II37083 g28278 +0 1 +.names II37086 g28279 +0 1 +.names II37089 g28280 +0 1 +.names II37092 g28281 +0 1 +.names II37095 g28282 +0 1 +.names II33861 g26003 +0 1 +.names II33864 g26004 +0 1 +.names II33867 g26005 +0 1 +.names II33870 g26006 +0 1 +.names II33873 g26007 +0 1 +.names II33876 g26008 +0 1 +.names II38196 g29151 +0 1 +.names II38199 g29152 +0 1 +.names II38202 g29153 +0 1 +.names II38187 g29148 +0 1 +.names II38190 g29149 +0 1 +.names II38193 g29150 +0 1 +.names II35509 g27224 +0 1 +.names II35512 g27225 +0 1 +.names II35515 g27226 +0 1 +.names II15511 g8302 +0 1 +.names II31805 g24377 +0 1 +.names II25186 g19041 +0 1 +.names II25189 g19042 +0 1 +.names II25192 g19043 +0 1 +.names II25195 g19044 +0 1 +.names II38713 g29444 +0 1 +.names II38710 g29443 +0 1 +.names II38707 g29442 +0 1 +.names II38704 g29441 +0 1 +.names II38701 g29440 +0 1 +.names g1900 gbuf166 +1 1 +.names II20625 g13442 +0 1 +.names II20628 g13443 +0 1 +.names II20631 g13444 +0 1 +.names II20634 g13445 +0 1 +.names II20637 g13446 +0 1 +.names II20640 g13447 +0 1 +.names II20643 g13448 +0 1 +.names II20646 g13449 +0 1 +.names II33858 g26002 +0 1 +.names II20649 g13450 +0 1 +.names II20655 g13452 +0 1 +.names g2003 gbuf167 +1 1 +.names g2006 gbuf168 +1 1 +.names II27023 g20566 +0 1 +.names II28461 g21945 +0 1 +.names II30164 g23237 +0 1 +.names II31808 g24378 +0 1 +.names II32964 g25162 +0 1 +.names II33879 g26009 +0 1 +.names II34782 g26725 +0 1 +.names II35518 g27227 +0 1 +.names II36129 g27706 +0 1 +.names II37098 g28283 +0 1 +.names II37608 g28687 +0 1 +.names II38205 g29154 +0 1 +.names II30167 g23238 +0 1 +.names II30170 g23239 +0 1 +.names II30173 g23240 +0 1 +.names II30176 g23241 +0 1 +.names II30179 g23242 +0 1 +.names II30182 g23243 +0 1 +.names II30185 g23244 +0 1 +.names II30188 g23245 +0 1 +.names II30191 g23246 +0 1 +.names II30194 g23247 +0 1 +.names II30197 g23248 +0 1 +.names II30200 g23249 +0 1 +.names II30203 g23250 +0 1 +.names II30206 g23251 +0 1 +.names II30209 g23252 +0 1 +.names II30212 g23253 +0 1 +.names II30215 g23254 +0 1 +.names II30218 g23255 +0 1 +.names II30221 g23256 +0 1 +.names II30224 g23257 +0 1 +.names II30227 g23258 +0 1 +.names II30230 g23259 +0 1 +.names II30233 g23260 +0 1 +.names II30236 g23261 +0 1 +.names II30239 g23262 +0 1 +.names II30242 g23263 +0 1 +.names II30245 g23264 +0 1 +.names II30248 g23265 +0 1 +.names II30251 g23266 +0 1 +.names II30254 g23267 +0 1 +.names II30257 g23268 +0 1 +.names II30260 g23269 +0 1 +.names II30263 g23270 +0 1 +.names II30266 g23271 +0 1 +.names II30269 g23272 +0 1 +.names II30272 g23273 +0 1 +.names II34785 g26726 +0 1 +.names II34788 g26727 +0 1 +.names II34791 g26728 +0 1 +.names II31811 g24379 +0 1 +.names II31814 g24380 +0 1 +.names II31817 g24381 +0 1 +.names II20658 g13453 +0 1 +.names g2214 gbuf169 +1 1 +.names g2211 gbuf170 +1 1 +.names II31820 g24382 +0 1 +.names II31823 g24383 +0 1 +.names II31826 g24384 +0 1 +.names II31829 g24385 +0 1 +.names II31832 g24386 +0 1 +.names II31835 g24387 +0 1 +.names II31838 g24388 +0 1 +.names II31841 g24389 +0 1 +.names II31844 g24390 +0 1 +.names II31847 g24391 +0 1 +.names II31850 g24392 +0 1 +.names II31853 g24393 +0 1 +.names II31856 g24394 +0 1 +.names II31859 g24395 +0 1 +.names II31862 g24396 +0 1 +.names II31865 g24397 +0 1 +.names II31868 g24398 +0 1 +.names II31871 g24399 +0 1 +.names II31874 g24400 +0 1 +.names II31877 g24401 +0 1 +.names II31880 g24402 +0 1 +.names II31883 g24403 +0 1 +.names II31886 g24404 +0 1 +.names II31889 g24405 +0 1 +.names II31892 g24406 +0 1 +.names II31895 g24407 +0 1 +.names II31898 g24408 +0 1 +.names II31901 g24409 +0 1 +.names II31904 g24410 +0 1 +.names II31907 g24411 +0 1 +.names II34797 g26730 +0 1 +.names II34800 g26731 +0 1 +.names II34803 g26732 +0 1 +.names II34806 g26733 +0 1 +.names II34809 g26734 +0 1 +.names II34812 g26735 +0 1 +.names II34815 g26736 +0 1 +.names II34818 g26737 +0 1 +.names II34821 g26738 +0 1 +.names II34824 g26739 +0 1 +.names II34827 g26740 +0 1 +.names II34830 g26741 +0 1 +.names II40233 g30551 +0 1 +.names II40236 g30552 +0 1 +.names II40239 g30553 +0 1 +.names II40940 g30896 +0 1 +.names II40943 g30897 +0 1 +.names II40946 g30898 +0 1 +.names II40922 g30890 +0 1 +.names II40925 g30891 +0 1 +.names II40928 g30892 +0 1 +.names II40949 g30899 +0 1 +.names II40952 g30900 +0 1 +.names II40955 g30901 +0 1 +.names II40242 g30554 +0 1 +.names II40245 g30555 +0 1 +.names II40248 g30556 +0 1 +.names II40260 g30560 +0 1 +.names II40263 g30561 +0 1 +.names II40266 g30562 +0 1 +.names II40251 g30557 +0 1 +.names II40254 g30558 +0 1 +.names II40257 g30559 +0 1 +.names II40269 g30563 +0 1 +.names II40272 g30564 +0 1 +.names II40275 g30565 +0 1 +.names II40931 g30893 +0 1 +.names II40934 g30894 +0 1 +.names II40937 g30895 +0 1 +.names II40958 g30902 +0 1 +.names II40961 g30903 +0 1 +.names II40964 g30904 +0 1 +.names II33882 g26010 +0 1 +.names II34794 g26729 +0 1 +.names II35521 g27228 +0 1 +.names II36132 g27707 +0 1 +.names II37101 g28284 +0 1 +.names II37611 g28688 +0 1 +.names II38208 g29155 +0 1 +.names II38719 g29446 +0 1 +.names II39062 g29648 +0 1 +.names II39270 g29806 +0 1 +.names II27026 g20567 +0 1 +.names g2256 gbuf171 +1 1 +.names g2258 gbuf172 +1 1 +.names II20661 g13454 +0 1 +.names g2351 gbuf173 +1 1 +.names g2480 gbuf174 +1 1 +.names II18707 g11577 +0 1 +.names II37104 g28285 +0 1 +.names II37107 g28286 +0 1 +.names II37110 g28287 +0 1 +.names II37113 g28288 +0 1 +.names II37116 g28289 +0 1 +.names II37119 g28290 +0 1 +.names II37122 g28291 +0 1 +.names II37125 g28292 +0 1 +.names II37128 g28293 +0 1 +.names II37131 g28294 +0 1 +.names II37134 g28295 +0 1 +.names II37137 g28296 +0 1 +.names II38722 g29447 +0 1 +.names II38725 g29448 +0 1 +.names II38728 g29449 +0 1 +.names II39074 g29652 +0 1 +.names II39077 g29653 +0 1 +.names II39080 g29654 +0 1 +.names II38731 g29450 +0 1 +.names II38734 g29451 +0 1 +.names II38737 g29452 +0 1 +.names II36135 g27708 +0 1 +.names II36138 g27709 +0 1 +.names II36141 g27710 +0 1 +.names II36144 g27711 +0 1 +.names II36147 g27712 +0 1 +.names II36150 g27713 +0 1 +.names II37614 g28689 +0 1 +.names II37617 g28690 +0 1 +.names II37620 g28691 +0 1 +.names II39273 g29807 +0 1 +.names II39276 g29808 +0 1 +.names II39279 g29809 +0 1 +.names II40967 g30905 +0 1 +.names II40970 g30906 +0 1 +.names II40973 g30907 +0 1 +.names II40447 g30719 +0 1 +.names II40450 g30720 +0 1 +.names II40453 g30721 +0 1 +.names II39065 g29649 +0 1 +.names II39068 g29650 +0 1 +.names II39071 g29651 +0 1 +.names II35527 g27230 +0 1 +.names II35530 g27231 +0 1 +.names II35533 g27232 +0 1 +.names II18746 g11590 +0 1 +.names g2525 gbuf175 +1 1 +.names II18749 g11591 +0 1 +.names g2527 gbuf176 +1 1 +.names II18752 g11592 +0 1 +.names g2529 gbuf177 +1 1 +.names II18692 g11572 +0 1 +.names g2355 gbuf178 +1 1 +.names II18695 g11573 +0 1 +.names g2357 gbuf179 +1 1 +.names II18698 g11574 +0 1 +.names g2359 gbuf180 +1 1 +.names II18701 g11575 +0 1 +.names g2361 gbuf181 +1 1 +.names II18704 g11576 +0 1 +.names g2363 gbuf182 +1 1 +.names II20664 g13455 +0 1 +.names g2365 gbuf183 +1 1 +.names II25207 g19048 +0 1 +.names II39785 g30314 +0 1 +.names II39788 g30315 +0 1 +.names II39791 g30316 +0 1 +.names II39794 g30317 +0 1 +.names II39797 g30318 +0 1 +.names II39800 g30319 +0 1 +.names II25219 g19052 +0 1 +.names II25216 g19051 +0 1 +.names II25213 g19050 +0 1 +.names II25210 g19049 +0 1 +.names II32967 g25163 +0 1 +.names II35524 g27229 +0 1 +.names II18710 g11578 +0 1 +.names g2417 gbuf184 +1 1 +.names II18713 g11579 +0 1 +.names g2425 gbuf185 +1 1 +.names II18716 g11580 +0 1 +.names g2427 gbuf186 +1 1 +.names II18719 g11581 +0 1 +.names g2432 gbuf187 +1 1 +.names II18722 g11582 +0 1 +.names g2440 gbuf188 +1 1 +.names II18725 g11583 +0 1 +.names g2442 gbuf189 +1 1 +.names II18728 g11584 +0 1 +.names g2447 gbuf190 +1 1 +.names II18731 g11585 +0 1 +.names g2455 gbuf191 +1 1 +.names II18734 g11586 +0 1 +.names g2457 gbuf192 +1 1 +.names II18737 g11587 +0 1 +.names g2462 gbuf193 +1 1 +.names II18740 g11588 +0 1 +.names g2470 gbuf194 +1 1 +.names II18743 g11589 +0 1 +.names g2472 gbuf195 +1 1 +.names II20667 g13456 +0 1 +.names g2400 gbuf196 +1 1 +.names g2406 gbuf197 +1 1 +.names II20700 g13467 +0 1 +.names g2619 gbuf198 +1 1 +.names g2625 gbuf199 +1 1 +.names II30275 g23274 +0 1 +.names II27029 g20568 +0 1 +.names II27032 g20569 +0 1 +.names II22521 g16473 +0 1 +.names g2587 gbuf200 +1 1 +.names g2597 gbuf201 +1 1 +.names II18755 g11593 +0 1 +.names g2638 gbuf202 +1 1 +.names II18764 g11596 +0 1 +.names g2644 gbuf203 +1 1 +.names II18767 g11597 +0 1 +.names g2646 gbuf204 +1 1 +.names II18770 g11598 +0 1 +.names g2648 gbuf205 +1 1 +.names II18758 g11594 +0 1 +.names g2640 gbuf206 +1 1 +.names II18761 g11595 +0 1 +.names g2642 gbuf207 +1 1 +.names II20670 g13457 +0 1 +.names g2549 gbuf208 +1 1 +.names g2556 gbuf209 +1 1 +.names II31919 g24415 +0 1 +.names II31922 g24416 +0 1 +.names II31925 g24417 +0 1 +.names II32994 g25172 +0 1 +.names II32970 g25164 +0 1 +.names II32973 g25165 +0 1 +.names II32985 g25169 +0 1 +.names II32988 g25170 +0 1 +.names II32991 g25171 +0 1 +.names II31910 g24412 +0 1 +.names II31913 g24413 +0 1 +.names II31916 g24414 +0 1 +.names II32976 g25166 +0 1 +.names II32979 g25167 +0 1 +.names II32982 g25168 +0 1 +.names II22524 g16474 +0 1 +.names g2602 gbuf210 +1 1 +.names g2609 gbuf211 +1 1 +.names II25234 g19057 +0 1 +.names g2617 gbuf212 +1 1 +.names II39818 g30325 +0 1 +.names II25237 g19058 +0 1 +.names g2623 gbuf213 +1 1 +.names II25240 g19059 +0 1 +.names g2632 gbuf214 +1 1 +.names II37140 g28297 +0 1 +.names II37143 g28298 +0 1 +.names II37146 g28299 +0 1 +.names II37149 g28300 +0 1 +.names II37152 g28301 +0 1 +.names II37155 g28302 +0 1 +.names II37158 g28303 +0 1 +.names II37161 g28304 +0 1 +.names II37164 g28305 +0 1 +.names II37167 g28306 +0 1 +.names II37170 g28307 +0 1 +.names II37173 g28308 +0 1 +.names II33888 g26012 +0 1 +.names II33891 g26013 +0 1 +.names II33894 g26014 +0 1 +.names II33897 g26015 +0 1 +.names II33900 g26016 +0 1 +.names II33903 g26017 +0 1 +.names II38220 g29159 +0 1 +.names II38223 g29160 +0 1 +.names II38226 g29161 +0 1 +.names II38211 g29156 +0 1 +.names II38214 g29157 +0 1 +.names II38217 g29158 +0 1 +.names II35536 g27233 +0 1 +.names II35539 g27234 +0 1 +.names II35542 g27235 +0 1 +.names II15517 g8311 +0 1 +.names II31928 g24418 +0 1 +.names II25222 g19053 +0 1 +.names II25225 g19054 +0 1 +.names II25228 g19055 +0 1 +.names II25231 g19056 +0 1 +.names II39815 g30324 +0 1 +.names II39812 g30323 +0 1 +.names II39809 g30322 +0 1 +.names II39806 g30321 +0 1 +.names II39803 g30320 +0 1 +.names g2594 gbuf215 +1 1 +.names II20673 g13458 +0 1 +.names II20676 g13459 +0 1 +.names II20679 g13460 +0 1 +.names II20682 g13461 +0 1 +.names II20685 g13462 +0 1 +.names II20688 g13463 +0 1 +.names II20691 g13464 +0 1 +.names II20694 g13465 +0 1 +.names II33885 g26011 +0 1 +.names II20697 g13466 +0 1 +.names II20703 g13468 +0 1 +.names g2697 gbuf216 +1 1 +.names g2700 gbuf217 +1 1 +.names II27035 g20570 +0 1 +.names II28464 g21946 +0 1 +.names II30278 g23275 +0 1 +.names II31931 g24419 +0 1 +.names II32997 g25173 +0 1 +.names II33906 g26018 +0 1 +.names II34833 g26742 +0 1 +.names II35545 g27236 +0 1 +.names II36153 g27714 +0 1 +.names II37176 g28309 +0 1 +.names II37623 g28692 +0 1 +.names II38229 g29162 +0 1 +.names II30281 g23276 +0 1 +.names II30284 g23277 +0 1 +.names II30287 g23278 +0 1 +.names II30290 g23279 +0 1 +.names II30293 g23280 +0 1 +.names II30296 g23281 +0 1 +.names II30299 g23282 +0 1 +.names II30302 g23283 +0 1 +.names II30305 g23284 +0 1 +.names II30308 g23285 +0 1 +.names II30311 g23286 +0 1 +.names II30314 g23287 +0 1 +.names II30317 g23288 +0 1 +.names II30320 g23289 +0 1 +.names II30323 g23290 +0 1 +.names II30326 g23291 +0 1 +.names II30329 g23292 +0 1 +.names II30332 g23293 +0 1 +.names II30335 g23294 +0 1 +.names II30338 g23295 +0 1 +.names II30341 g23296 +0 1 +.names II30344 g23297 +0 1 +.names II30347 g23298 +0 1 +.names II30350 g23299 +0 1 +.names II30353 g23300 +0 1 +.names II30356 g23301 +0 1 +.names II30359 g23302 +0 1 +.names II30362 g23303 +0 1 +.names II30365 g23304 +0 1 +.names II30368 g23305 +0 1 +.names II30371 g23306 +0 1 +.names II30374 g23307 +0 1 +.names II30377 g23308 +0 1 +.names II30380 g23309 +0 1 +.names II30383 g23310 +0 1 +.names II30386 g23311 +0 1 +.names II34836 g26743 +0 1 +.names II34839 g26744 +0 1 +.names II34842 g26745 +0 1 +.names II31934 g24420 +0 1 +.names II31937 g24421 +0 1 +.names II31940 g24422 +0 1 +.names II30404 g23317 +0 1 +.names II30407 g23318 +0 1 +.names II28521 g21965 +0 1 +.names II38740 g29453 +0 1 +.names II38743 g29454 +0 1 +.names II38746 g29455 +0 1 +.names II38749 g29456 +0 1 +.names II38752 g29457 +0 1 +.names II38755 g29458 +0 1 +.names II38758 g29459 +0 1 +.names II38761 g29460 +0 1 +.names II39083 g29655 +0 1 +.names II39454 g29972 +0 1 +.names II39457 g29973 +0 1 +.names II39460 g29974 +0 1 +.names II39463 g29975 +0 1 +.names II39466 g29976 +0 1 +.names II39469 g29977 +0 1 +.names II39472 g29978 +0 1 +.names II39475 g29979 +0 1 +.names II39622 g30119 +0 1 +.names II40976 g30908 +0 1 +.names II40979 g30909 +0 1 +.names II40982 g30910 +0 1 +.names II40985 g30911 +0 1 +.names II40988 g30912 +0 1 +.names II40991 g30913 +0 1 +.names II40994 g30914 +0 1 +.names II40997 g30915 +0 1 +.names II41044 g30940 +0 1 +.names II41114 g30980 +0 1 +.names II41117 g30981 +0 1 +.names II41120 g30982 +0 1 +.names II41123 g30983 +0 1 +.names II41126 g30984 +0 1 +.names II41129 g30985 +0 1 +.names II41132 g30986 +0 1 +.names II41135 g30987 +0 1 +.names II41141 g30989 +0 1 +.names II34851 g26748 +0 1 +.names II35551 g27238 +0 1 +.names II33009 g25177 +0 1 +.names II33915 g26021 +0 1 +.names II34857 g26750 +0 1 +.names II35554 g27239 +0 1 +.names II36159 g27716 +0 1 +.names II31949 g24425 +0 1 +.names II33006 g25176 +0 1 +.names II33918 g26022 +0 1 +.names II34854 g26749 +0 1 +.names II22593 g16497 +0 1 +.names g3040 gbuf218 +1 1 +.names II22587 g16495 +0 1 +.names II27110 g20595 +0 1 +.names II27113 g20596 +0 1 +.names II27116 g20597 +0 1 +.names II27119 g20598 +0 1 +.names II27122 g20599 +0 1 +.names II27125 g20600 +0 1 +.names II27128 g20601 +0 1 +.names II27131 g20602 +0 1 +.names II27134 g20603 +0 1 +.names II27137 g20604 +0 1 +.names II28524 g21966 +0 1 +.names II27140 g20605 +0 1 +.names II27143 g20606 +0 1 +.names II27146 g20607 +0 1 +.names II27149 g20608 +0 1 +.names II27092 g20589 +0 1 +.names II27095 g20590 +0 1 +.names II27098 g20591 +0 1 +.names II27101 g20592 +0 1 +.names II27104 g20593 +0 1 +.names II28518 g21964 +0 1 +.names II27107 g20594 +0 1 +.names g563 II13089 +0 1 +.names II13089 g562 +0 1 +.names g1249 II13092 +0 1 +.names II13092 g1248 +0 1 +.names g1943 II13095 +0 1 +.names II13095 g1942 +0 1 +.names g2637 II13098 +0 1 +.names II13098 g2636 +0 1 +.names g1 II13101 +0 1 +.names II13101 g3235 +0 1 +.names g2 II13104 +0 1 +.names II13104 g3236 +0 1 +.names g5 II13107 +0 1 +.names II13107 g3237 +0 1 +.names g8 II13110 +0 1 +.names II13110 g3238 +0 1 +.names g11 II13113 +0 1 +.names II13113 g3239 +0 1 +.names g14 II13116 +0 1 +.names II13116 g3240 +0 1 +.names g17 II13119 +0 1 +.names II13119 g3241 +0 1 +.names g20 II13122 +0 1 +.names II13122 g3242 +0 1 +.names g23 II13125 +0 1 +.names II13125 g3243 +0 1 +.names g26 II13128 +0 1 +.names II13128 g3244 +0 1 +.names g27 II13131 +0 1 +.names II13131 g3245 +0 1 +.names g30 II13134 +0 1 +.names II13134 g3246 +0 1 +.names g33 II13137 +0 1 +.names II13137 g3247 +0 1 +.names g36 II13140 +0 1 +.names II13140 g3248 +0 1 +.names g39 II13143 +0 1 +.names II13143 g3249 +0 1 +.names g42 II13146 +0 1 +.names II13146 g3250 +0 1 +.names g45 II13149 +0 1 +.names II13149 g3251 +0 1 +.names g48 II13152 +0 1 +.names II13152 g3252 +0 1 +.names g51 II13155 +0 1 +.names II13155 g3253 +0 1 +.names g165 II13158 +0 1 +.names II13158 g3254 +0 1 +.names g308 II13161 +0 1 +.names II13161 g3304 +0 1 +.names g305 g3305 +0 1 +.names g401 II13165 +0 1 +.names II13165 g3306 +0 1 +.names g309 g3337 +0 1 +.names g550 II13169 +0 1 +.names II13169 g3338 +0 1 +.names g499 g3365 +0 1 +.names g629 II13173 +0 1 +.names II13173 g3366 +0 1 +.names g630 II13176 +0 1 +.names II13176 g3398 +0 1 +.names g853 II13179 +0 1 +.names II13179 g3410 +0 1 +.names g995 II13182 +0 1 +.names II13182 g3460 +0 1 +.names g992 g3461 +0 1 +.names g1088 II13186 +0 1 +.names II13186 g3462 +0 1 +.names g996 g3493 +0 1 +.names g1236 II13190 +0 1 +.names II13190 g3494 +0 1 +.names g1186 g3521 +0 1 +.names g1315 II13194 +0 1 +.names II13194 g3522 +0 1 +.names g1316 II13197 +0 1 +.names II13197 g3554 +0 1 +.names g1547 II13200 +0 1 +.names II13200 g3566 +0 1 +.names g1689 II13203 +0 1 +.names II13203 g3616 +0 1 +.names g1686 g3617 +0 1 +.names g1782 II13207 +0 1 +.names II13207 g3618 +0 1 +.names g1690 g3649 +0 1 +.names g1930 II13211 +0 1 +.names II13211 g3650 +0 1 +.names g1880 g3677 +0 1 +.names g2009 II13215 +0 1 +.names II13215 g3678 +0 1 +.names g2010 II13218 +0 1 +.names II13218 g3710 +0 1 +.names g2241 II13221 +0 1 +.names II13221 g3722 +0 1 +.names g2383 II13224 +0 1 +.names II13224 g3772 +0 1 +.names g2380 g3773 +0 1 +.names g2476 II13228 +0 1 +.names II13228 g3774 +0 1 +.names g2384 g3805 +0 1 +.names g2624 II13232 +0 1 +.names II13232 g3806 +0 1 +.names g2574 g3833 +0 1 +.names g2703 II13236 +0 1 +.names II13236 g3834 +0 1 +.names g2704 II13239 +0 1 +.names II13239 g3866 +0 1 +.names g2879 II13242 +0 1 +.names II13242 g3878 +0 1 +.names g2950 g3897 +0 1 +.names g2987 II13246 +0 1 +.names II13246 g3900 +0 1 +.names g3080 g3919 +0 1 +.names g150 g3922 +0 1 +.names g155 g3925 +0 1 +.names g157 g3928 +0 1 +.names g171 g3931 +0 1 +.names g176 g3934 +0 1 +.names g178 g3937 +0 1 +.names g408 g3940 +0 1 +.names g455 g3941 +0 1 +.names g699 g3942 +0 1 +.names g726 g3945 +0 1 +.names g835 g3948 +0 1 +.names g840 g3951 +0 1 +.names g842 g3954 +0 1 +.names g856 g3957 +0 1 +.names g861 g3960 +0 1 +.names g863 g3963 +0 1 +.names g1526 g3966 +0 1 +.names g1531 g3969 +0 1 +.names g1533 g3972 +0 1 +.names g1552 g3975 +0 1 +.names g1554 g3978 +0 1 +.names g2217 g3981 +0 1 +.names g2222 g3984 +0 1 +.names g2224 g3987 +0 1 +.names g2245 g3990 +0 1 +.names g2848 II13275 +0 1 +.names g2848 g3994 +0 1 +.names g3064 g3995 +0 1 +.names g3073 g3996 +0 1 +.names g45 g3997 +0 1 +.names g23 g3998 +0 1 +.names g3204 g3999 +0 1 +.names g153 g4000 +0 1 +.names g158 g4003 +0 1 +.names g160 g4006 +0 1 +.names g174 g4009 +0 1 +.names g179 g4012 +0 1 +.names g411 g4015 +0 1 +.names g417 g4016 +0 1 +.names g427 g4017 +0 1 +.names g700 g4020 +0 1 +.names g702 g4023 +0 1 +.names g727 g4026 +0 1 +.names g838 g4029 +0 1 +.names g843 g4032 +0 1 +.names g845 g4035 +0 1 +.names g859 g4038 +0 1 +.names g864 g4041 +0 1 +.names g866 g4044 +0 1 +.names g1095 g4047 +0 1 +.names g1142 g4048 +0 1 +.names g1385 g4049 +0 1 +.names g1412 g4052 +0 1 +.names g1529 g4055 +0 1 +.names g1534 g4058 +0 1 +.names g1536 g4061 +0 1 +.names g1550 g4064 +0 1 +.names g1555 g4067 +0 1 +.names g1557 g4070 +0 1 +.names g2220 g4073 +0 1 +.names g2225 g4076 +0 1 +.names g2227 g4079 +0 1 +.names g2246 g4082 +0 1 +.names g2248 g4085 +0 1 +.names g2836 II13316 +0 1 +.names g2836 g4089 +0 1 +.names g2864 II13320 +0 1 +.names g2864 g4091 +0 1 +.names g3074 g4092 +0 1 +.names g33 g4093 +0 1 +.names g3207 g4094 +0 1 +.names g130 g4095 +0 1 +.names g156 g4098 +0 1 +.names g161 g4101 +0 1 +.names g163 g4104 +0 1 +.names g177 g4107 +0 1 +.names g414 g4110 +0 1 +.names g420 g4111 +0 1 +.names g428 g4112 +0 1 +.names g698 g4115 +0 1 +.names g703 g4118 +0 1 +.names g705 g4121 +0 1 +.names g725 g4124 +0 1 +.names g841 g4127 +0 1 +.names g846 g4130 +0 1 +.names g848 g4133 +0 1 +.names g862 g4136 +0 1 +.names g867 g4139 +0 1 +.names g1098 g4142 +0 1 +.names g1104 g4143 +0 1 +.names g1114 g4144 +0 1 +.names g1386 g4147 +0 1 +.names g1388 g4150 +0 1 +.names g1413 g4153 +0 1 +.names g1532 g4156 +0 1 +.names g1537 g4159 +0 1 +.names g1539 g4162 +0 1 +.names g1553 g4165 +0 1 +.names g1558 g4168 +0 1 +.names g1560 g4171 +0 1 +.names g1789 g4174 +0 1 +.names g1836 g4175 +0 1 +.names g2079 g4176 +0 1 +.names g2106 g4179 +0 1 +.names g2223 g4182 +0 1 +.names g2228 g4185 +0 1 +.names g2230 g4188 +0 1 +.names g2244 g4191 +0 1 +.names g2249 g4194 +0 1 +.names g2251 g4197 +0 1 +.names g2851 II13366 +0 1 +.names g2851 g4201 +0 1 +.names g42 g4202 +0 1 +.names g20 g4203 +0 1 +.names g3188 g4204 +0 1 +.names g131 g4205 +0 1 +.names g133 g4208 +0 1 +.names g159 g4211 +0 1 +.names g164 g4214 +0 1 +.names g354 g4217 +0 1 +.names g423 g4220 +0 1 +.names g426 g4221 +0 1 +.names g429 g4224 +0 1 +.names g701 g4225 +0 1 +.names g706 g4228 +0 1 +.names g708 g4231 +0 1 +.names g818 g4234 +0 1 +.names g844 g4237 +0 1 +.names g849 g4240 +0 1 +.names g851 g4243 +0 1 +.names g865 g4246 +0 1 +.names g1101 g4249 +0 1 +.names g1107 g4250 +0 1 +.names g1115 g4251 +0 1 +.names g1384 g4254 +0 1 +.names g1389 g4257 +0 1 +.names g1391 g4260 +0 1 +.names g1411 g4263 +0 1 +.names g1535 g4266 +0 1 +.names g1540 g4269 +0 1 +.names g1542 g4272 +0 1 +.names g1556 g4275 +0 1 +.names g1561 g4278 +0 1 +.names g1792 g4281 +0 1 +.names g1798 g4282 +0 1 +.names g1808 g4283 +0 1 +.names g2080 g4286 +0 1 +.names g2082 g4289 +0 1 +.names g2107 g4292 +0 1 +.names g2226 g4295 +0 1 +.names g2231 g4298 +0 1 +.names g2233 g4301 +0 1 +.names g2247 g4304 +0 1 +.names g2252 g4307 +0 1 +.names g2254 g4310 +0 1 +.names g2483 g4313 +0 1 +.names g2530 g4314 +0 1 +.names g2773 g4315 +0 1 +.names g2800 g4318 +0 1 +.names g2839 II13417 +0 1 +.names g2839 g4322 +0 1 +.names g2867 II13421 +0 1 +.names g2867 g4324 +0 1 +.names g36 g4325 +0 1 +.names g181 g4326 +0 1 +.names g129 g4329 +0 1 +.names g134 g4332 +0 1 +.names g162 g4335 +0 1 +.names g101 II13430 +0 1 +.names II13430 g4338 +0 1 +.names g105 II13433 +0 1 +.names II13433 g4339 +0 1 +.names g343 g4340 +0 1 +.names g369 g4343 +0 1 +.names g432 g4346 +0 1 +.names g438 g4347 +0 1 +.names g704 g4348 +0 1 +.names g709 g4351 +0 1 +.names g711 g4354 +0 1 +.names g729 g4357 +0 1 +.names g819 g4360 +0 1 +.names g821 g4363 +0 1 +.names g847 g4366 +0 1 +.names g852 g4369 +0 1 +.names g1041 g4372 +0 1 +.names g1110 g4375 +0 1 +.names g1113 g4376 +0 1 +.names g1116 g4379 +0 1 +.names g1387 g4380 +0 1 +.names g1392 g4383 +0 1 +.names g1394 g4386 +0 1 +.names g1512 g4389 +0 1 +.names g1538 g4392 +0 1 +.names g1543 g4395 +0 1 +.names g1545 g4398 +0 1 +.names g1559 g4401 +0 1 +.names g1795 g4404 +0 1 +.names g1801 g4405 +0 1 +.names g1809 g4406 +0 1 +.names g2078 g4409 +0 1 +.names g2083 g4412 +0 1 +.names g2085 g4415 +0 1 +.names g2105 g4418 +0 1 +.names g2229 g4421 +0 1 +.names g2234 g4424 +0 1 +.names g2236 g4427 +0 1 +.names g2250 g4430 +0 1 +.names g2255 g4433 +0 1 +.names g2486 g4436 +0 1 +.names g2492 g4437 +0 1 +.names g2502 g4438 +0 1 +.names g2774 g4441 +0 1 +.names g2776 g4444 +0 1 +.names g2801 g4447 +0 1 +.names g2854 II13478 +0 1 +.names g2854 g4451 +0 1 +.names g17 g4452 +0 1 +.names g132 g4453 +0 1 +.names g309 g4456 +0 1 +.names g346 g4465 +0 1 +.names g358 g4468 +0 1 +.names g384 g4471 +0 1 +.names g435 g4474 +0 1 +.names g441 g4475 +0 1 +.names g576 g4476 +0 1 +.names g587 g4479 +0 1 +.names g707 g4480 +0 1 +.names g712 g4483 +0 1 +.names g714 g4486 +0 1 +.names g730 g4489 +0 1 +.names g732 g4492 +0 1 +.names g869 g4495 +0 1 +.names g817 g4498 +0 1 +.names g822 g4501 +0 1 +.names g850 g4504 +0 1 +.names g789 II13501 +0 1 +.names II13501 g4507 +0 1 +.names g793 II13504 +0 1 +.names II13504 g4508 +0 1 +.names g1030 g4509 +0 1 +.names g1056 g4512 +0 1 +.names g1119 g4515 +0 1 +.names g1125 g4516 +0 1 +.names g1390 g4517 +0 1 +.names g1395 g4520 +0 1 +.names g1397 g4523 +0 1 +.names g1415 g4526 +0 1 +.names g1513 g4529 +0 1 +.names g1515 g4532 +0 1 +.names g1541 g4535 +0 1 +.names g1546 g4538 +0 1 +.names g1735 g4541 +0 1 +.names g1804 g4544 +0 1 +.names g1807 g4545 +0 1 +.names g1810 g4548 +0 1 +.names g2081 g4549 +0 1 +.names g2086 g4552 +0 1 +.names g2088 g4555 +0 1 +.names g2206 g4558 +0 1 +.names g2232 g4561 +0 1 +.names g2237 g4564 +0 1 +.names g2239 g4567 +0 1 +.names g2253 g4570 +0 1 +.names g2489 g4573 +0 1 +.names g2495 g4574 +0 1 +.names g2503 g4575 +0 1 +.names g2772 g4578 +0 1 +.names g2777 g4581 +0 1 +.names g2779 g4584 +0 1 +.names g2799 g4587 +0 1 +.names g2870 II13538 +0 1 +.names g2870 g4591 +0 1 +.names g361 g4592 +0 1 +.names g373 g4595 +0 1 +.names g398 g4598 +0 1 +.names g444 g4601 +0 1 +.names g525 g4602 +0 1 +.names g577 g4603 +0 1 +.names g579 g4606 +0 1 +.names g590 g4609 +0 1 +.names g596 g4610 +0 1 +.names g710 g4611 +0 1 +.names g715 g4614 +0 1 +.names g717 g4617 +0 1 +.names g728 g4620 +0 1 +.names g733 g4623 +0 1 +.names g735 g4626 +0 1 +.names g820 g4629 +0 1 +.names g996 g4632 +0 1 +.names g1033 g4641 +0 1 +.names g1045 g4644 +0 1 +.names g1071 g4647 +0 1 +.names g1122 g4650 +0 1 +.names g1128 g4651 +0 1 +.names g1262 g4652 +0 1 +.names g1273 g4655 +0 1 +.names g1393 g4656 +0 1 +.names g1398 g4659 +0 1 +.names g1400 g4662 +0 1 +.names g1416 g4665 +0 1 +.names g1418 g4668 +0 1 +.names g1563 g4671 +0 1 +.names g1511 g4674 +0 1 +.names g1516 g4677 +0 1 +.names g1544 g4680 +0 1 +.names g1476 II13575 +0 1 +.names II13575 g4683 +0 1 +.names g1481 II13578 +0 1 +.names II13578 g4684 +0 1 +.names g1724 g4685 +0 1 +.names g1750 g4688 +0 1 +.names g1813 g4691 +0 1 +.names g1819 g4692 +0 1 +.names g2084 g4693 +0 1 +.names g2089 g4696 +0 1 +.names g2091 g4699 +0 1 +.names g2109 g4702 +0 1 +.names g2207 g4705 +0 1 +.names g2209 g4708 +0 1 +.names g2235 g4711 +0 1 +.names g2240 g4714 +0 1 +.names g2429 g4717 +0 1 +.names g2498 g4720 +0 1 +.names g2501 g4721 +0 1 +.names g2504 g4724 +0 1 +.names g2775 g4725 +0 1 +.names g2780 g4728 +0 1 +.names g2782 g4731 +0 1 +.names g11 g4734 +0 1 +.names g121 II13601 +0 1 +.names II13601 g4735 +0 1 +.names g125 II13604 +0 1 +.names II13604 g4736 +0 1 +.names g376 g4737 +0 1 +.names g388 g4740 +0 1 +.names g575 g4743 +0 1 +.names g580 g4746 +0 1 +.names g582 g4749 +0 1 +.names g593 g4752 +0 1 +.names g599 g4753 +0 1 +.names g713 g4754 +0 1 +.names g718 g4757 +0 1 +.names g720 g4760 +0 1 +.names g731 g4763 +0 1 +.names g736 g4766 +0 1 +.names g1048 g4769 +0 1 +.names g1060 g4772 +0 1 +.names g1085 g4775 +0 1 +.names g1131 g4778 +0 1 +.names g1211 g4779 +0 1 +.names g1263 g4780 +0 1 +.names g1265 g4783 +0 1 +.names g1276 g4786 +0 1 +.names g1282 g4787 +0 1 +.names g1396 g4788 +0 1 +.names g1401 g4791 +0 1 +.names g1403 g4794 +0 1 +.names g1414 g4797 +0 1 +.names g1419 g4800 +0 1 +.names g1421 g4803 +0 1 +.names g1514 g4806 +0 1 +.names g1690 g4809 +0 1 +.names g1727 g4818 +0 1 +.names g1739 g4821 +0 1 +.names g1765 g4824 +0 1 +.names g1816 g4827 +0 1 +.names g1822 g4828 +0 1 +.names g1956 g4829 +0 1 +.names g1967 g4832 +0 1 +.names g2087 g4833 +0 1 +.names g2092 g4836 +0 1 +.names g2094 g4839 +0 1 +.names g2110 g4842 +0 1 +.names g2112 g4845 +0 1 +.names g2257 g4848 +0 1 +.names g2205 g4851 +0 1 +.names g2210 g4854 +0 1 +.names g2238 g4857 +0 1 +.names g2170 II13652 +0 1 +.names II13652 g4860 +0 1 +.names g2175 II13655 +0 1 +.names II13655 g4861 +0 1 +.names g2418 g4862 +0 1 +.names g2444 g4865 +0 1 +.names g2507 g4868 +0 1 +.names g2513 g4869 +0 1 +.names g2778 g4870 +0 1 +.names g2783 g4873 +0 1 +.names g2785 g4876 +0 1 +.names g2803 g4879 +0 1 +.names g391 g4882 +0 1 +.names g448 g4885 +0 1 +.names g578 g4888 +0 1 +.names g583 g4891 +0 1 +.names g585 g4894 +0 1 +.names g602 g4897 +0 1 +.names g605 g4898 +0 1 +.names g716 g4899 +0 1 +.names g721 g4902 +0 1 +.names g723 g4905 +0 1 +.names g734 g4908 +0 1 +.names g809 II13677 +0 1 +.names II13677 g4911 +0 1 +.names g813 II13680 +0 1 +.names II13680 g4912 +0 1 +.names g1063 g4913 +0 1 +.names g1075 g4916 +0 1 +.names g1261 g4919 +0 1 +.names g1266 g4922 +0 1 +.names g1268 g4925 +0 1 +.names g1279 g4928 +0 1 +.names g1285 g4929 +0 1 +.names g1399 g4930 +0 1 +.names g1404 g4933 +0 1 +.names g1406 g4936 +0 1 +.names g1417 g4939 +0 1 +.names g1422 g4942 +0 1 +.names g1742 g4945 +0 1 +.names g1754 g4948 +0 1 +.names g1779 g4951 +0 1 +.names g1825 g4954 +0 1 +.names g1905 g4955 +0 1 +.names g1957 g4956 +0 1 +.names g1959 g4959 +0 1 +.names g1970 g4962 +0 1 +.names g1976 g4963 +0 1 +.names g2090 g4964 +0 1 +.names g2095 g4967 +0 1 +.names g2097 g4970 +0 1 +.names g2108 g4973 +0 1 +.names g2113 g4976 +0 1 +.names g2115 g4979 +0 1 +.names g2208 g4982 +0 1 +.names g2384 g4985 +0 1 +.names g2421 g4994 +0 1 +.names g2433 g4997 +0 1 +.names g2459 g5000 +0 1 +.names g2510 g5003 +0 1 +.names g2516 g5004 +0 1 +.names g2650 g5005 +0 1 +.names g2661 g5008 +0 1 +.names g2781 g5009 +0 1 +.names g2786 g5012 +0 1 +.names g2788 g5015 +0 1 +.names g2804 g5018 +0 1 +.names g2806 g5021 +0 1 +.names g449 g5024 +0 1 +.names g581 g5027 +0 1 +.names g586 g5030 +0 1 +.names g608 g5033 +0 1 +.names g614 g5034 +0 1 +.names g719 g5035 +0 1 +.names g724 g5038 +0 1 +.names g1078 g5041 +0 1 +.names g1135 g5044 +0 1 +.names g1264 g5047 +0 1 +.names g1269 g5050 +0 1 +.names g1271 g5053 +0 1 +.names g1288 g5056 +0 1 +.names g1291 g5057 +0 1 +.names g1402 g5058 +0 1 +.names g1407 g5061 +0 1 +.names g1409 g5064 +0 1 +.names g1420 g5067 +0 1 +.names g1501 II13742 +0 1 +.names II13742 g5070 +0 1 +.names g1506 II13745 +0 1 +.names II13745 g5071 +0 1 +.names g1757 g5072 +0 1 +.names g1769 g5075 +0 1 +.names g1955 g5078 +0 1 +.names g1960 g5081 +0 1 +.names g1962 g5084 +0 1 +.names g1973 g5087 +0 1 +.names g1979 g5088 +0 1 +.names g2093 g5089 +0 1 +.names g2098 g5092 +0 1 +.names g2100 g5095 +0 1 +.names g2111 g5098 +0 1 +.names g2116 g5101 +0 1 +.names g2436 g5104 +0 1 +.names g2448 g5107 +0 1 +.names g2473 g5110 +0 1 +.names g2519 g5113 +0 1 +.names g2599 g5114 +0 1 +.names g2651 g5115 +0 1 +.names g2653 g5118 +0 1 +.names g2664 g5121 +0 1 +.names g2670 g5122 +0 1 +.names g2784 g5123 +0 1 +.names g2789 g5126 +0 1 +.names g2791 g5129 +0 1 +.names g2802 g5132 +0 1 +.names g2807 g5135 +0 1 +.names g2809 g5138 +0 1 +.names g109 II13775 +0 1 +.names II13775 g5141 +0 1 +.names g447 g5142 +0 1 +.names g584 g5145 +0 1 +.names g611 g5148 +0 1 +.names g617 g5149 +0 1 +.names g722 g5150 +0 1 +.names g1136 g5153 +0 1 +.names g1267 g5156 +0 1 +.names g1272 g5159 +0 1 +.names g1294 g5162 +0 1 +.names g1300 g5163 +0 1 +.names g1405 g5164 +0 1 +.names g1410 g5167 +0 1 +.names g1772 g5170 +0 1 +.names g1829 g5173 +0 1 +.names g1958 g5176 +0 1 +.names g1963 g5179 +0 1 +.names g1965 g5182 +0 1 +.names g1982 g5185 +0 1 +.names g1985 g5186 +0 1 +.names g2096 g5187 +0 1 +.names g2101 g5190 +0 1 +.names g2103 g5193 +0 1 +.names g2114 g5196 +0 1 +.names g2195 II13801 +0 1 +.names II13801 g5199 +0 1 +.names g2200 II13804 +0 1 +.names II13804 g5200 +0 1 +.names g2451 g5201 +0 1 +.names g2463 g5204 +0 1 +.names g2649 g5207 +0 1 +.names g2654 g5210 +0 1 +.names g2656 g5213 +0 1 +.names g2667 g5216 +0 1 +.names g2673 g5217 +0 1 +.names g2787 g5218 +0 1 +.names g2792 g5221 +0 1 +.names g2794 g5224 +0 1 +.names g2805 g5227 +0 1 +.names g2810 g5230 +0 1 +.names g620 g5233 +0 1 +.names g797 II13820 +0 1 +.names II13820 g5234 +0 1 +.names g1134 g5235 +0 1 +.names g1270 g5238 +0 1 +.names g1297 g5241 +0 1 +.names g1303 g5242 +0 1 +.names g1408 g5243 +0 1 +.names g1830 g5246 +0 1 +.names g1961 g5249 +0 1 +.names g1966 g5252 +0 1 +.names g1988 g5255 +0 1 +.names g1994 g5256 +0 1 +.names g2099 g5257 +0 1 +.names g2104 g5260 +0 1 +.names g2466 g5263 +0 1 +.names g2523 g5266 +0 1 +.names g2652 g5269 +0 1 +.names g2657 g5272 +0 1 +.names g2659 g5275 +0 1 +.names g2676 g5278 +0 1 +.names g2679 g5279 +0 1 +.names g2790 g5280 +0 1 +.names g2795 g5283 +0 1 +.names g2797 g5286 +0 1 +.names g2808 g5289 +0 1 +.names g2857 g5292 +0 1 +.names g738 g5293 +0 1 +.names g1306 g5296 +0 1 +.names g1486 II13849 +0 1 +.names II13849 g5297 +0 1 +.names g1828 g5298 +0 1 +.names g1964 g5301 +0 1 +.names g1991 g5304 +0 1 +.names g1997 g5305 +0 1 +.names g2102 g5306 +0 1 +.names g2524 g5309 +0 1 +.names g2655 g5312 +0 1 +.names g2660 g5315 +0 1 +.names g2682 g5318 +0 1 +.names g2688 g5319 +0 1 +.names g2793 g5320 +0 1 +.names g2798 g5323 +0 1 +.names g2873 g5326 +0 1 +.names g739 g5327 +0 1 +.names g1424 g5330 +0 1 +.names g2000 g5333 +0 1 +.names g2180 II13868 +0 1 +.names II13868 g5334 +0 1 +.names g2522 g5335 +0 1 +.names g2658 g5338 +0 1 +.names g2685 g5341 +0 1 +.names g2691 g5342 +0 1 +.names g2796 g5343 +0 1 +.names g3106 g5346 +0 1 +.names g2877 g5349 +0 1 +.names g737 g5352 +0 1 +.names g1425 g5355 +0 1 +.names g2118 g5358 +0 1 +.names g2694 g5361 +0 1 +.names g2817 g5362 +0 1 +.names g3107 g5363 +0 1 +.names g2878 g5366 +0 1 +.names g1423 g5369 +0 1 +.names g2119 g5372 +0 1 +.names g2812 g5375 +0 1 +.names g2933 g5378 +0 1 +.names g3108 g5379 +0 1 +.names g2117 g5382 +0 1 +.names g2813 g5385 +0 1 +.names g3040 II13892 +0 1 +.names g3040 g5389 +0 1 +.names g343 II13896 +0 1 +.names II13896 g5390 +0 1 +.names g2811 g5391 +0 1 +.names g3054 g5394 +0 1 +.names g346 II13901 +0 1 +.names II13901 g5395 +0 1 +.names g358 II13904 +0 1 +.names II13904 g5396 +0 1 +.names g1030 II13907 +0 1 +.names II13907 g5397 +0 1 +.names g361 II13910 +0 1 +.names II13910 g5398 +0 1 +.names g373 II13913 +0 1 +.names II13913 g5399 +0 1 +.names g1033 II13916 +0 1 +.names II13916 g5400 +0 1 +.names g1045 II13919 +0 1 +.names II13919 g5401 +0 1 +.names g1724 II13922 +0 1 +.names II13922 g5402 +0 1 +.names g376 II13925 +0 1 +.names II13925 g5403 +0 1 +.names g388 II13928 +0 1 +.names II13928 g5404 +0 1 +.names g1048 II13931 +0 1 +.names II13931 g5405 +0 1 +.names g1060 II13934 +0 1 +.names II13934 g5406 +0 1 +.names g1727 II13937 +0 1 +.names II13937 g5407 +0 1 +.names g1739 II13940 +0 1 +.names II13940 g5408 +0 1 +.names g2418 II13943 +0 1 +.names II13943 g5409 +0 1 +.names g3079 g5410 +0 1 +.names g391 II13947 +0 1 +.names II13947 g5411 +0 1 +.names g1063 II13950 +0 1 +.names II13950 g5412 +0 1 +.names g1075 II13953 +0 1 +.names II13953 g5413 +0 1 +.names g1742 II13956 +0 1 +.names II13956 g5414 +0 1 +.names g1754 II13959 +0 1 +.names II13959 g5415 +0 1 +.names g2421 II13962 +0 1 +.names II13962 g5416 +0 1 +.names g2433 II13965 +0 1 +.names II13965 g5417 +0 1 +.names g1078 II13968 +0 1 +.names II13968 g5418 +0 1 +.names g1757 II13971 +0 1 +.names II13971 g5419 +0 1 +.names g1769 II13974 +0 1 +.names II13974 g5420 +0 1 +.names g2436 II13977 +0 1 +.names II13977 g5421 +0 1 +.names g2448 II13980 +0 1 +.names II13980 g5422 +0 1 +.names g2879 g5423 +0 1 +.names g1772 II13984 +0 1 +.names II13984 g5424 +0 1 +.names g2451 II13987 +0 1 +.names II13987 g5425 +0 1 +.names g2463 II13990 +0 1 +.names II13990 g5426 +0 1 +.names g2466 II13993 +0 1 +.names II13993 g5427 +0 1 +.names g3210 g5428 +0 1 +.names g3211 g5431 +0 1 +.names g3084 g5434 +0 1 +.names g276 II13999 +0 1 +.names g276 II14002 +0 1 +.names II14002 g5438 +0 1 +.names g3085 g5469 +0 1 +.names g963 II14006 +0 1 +.names g963 II14009 +0 1 +.names II14009 g5473 +0 1 +.names g3086 g5504 +0 1 +.names g3155 g5507 +0 1 +.names g499 II14014 +0 1 +.names II14014 g5508 +0 1 +.names g1657 II14017 +0 1 +.names g1657 II14020 +0 1 +.names II14020 g5512 +0 1 +.names g3087 g5543 +0 1 +.names g3164 g5546 +0 1 +.names g101 g5547 +0 1 +.names g105 g5548 +0 1 +.names g182 II14027 +0 1 +.names g182 II14030 +0 1 +.names II14030 g5550 +0 1 +.names g514 g5551 +0 1 +.names g1186 II14034 +0 1 +.names II14034 g5552 +0 1 +.names g2351 II14037 +0 1 +.names g2351 II14040 +0 1 +.names II14040 g5556 +0 1 +.names g3091 g5587 +0 1 +.names g3158 g5590 +0 1 +.names g3173 g5591 +0 1 +.names g515 g5592 +0 1 +.names g789 g5593 +0 1 +.names g793 g5594 +0 1 +.names g870 II14049 +0 1 +.names g870 II14052 +0 1 +.names II14052 g5596 +0 1 +.names g1200 g5597 +0 1 +.names g1880 II14056 +0 1 +.names II14056 g5598 +0 1 +.names g3092 g5601 +0 1 +.names g3167 g5604 +0 1 +.names g3182 g5605 +0 1 +.names g79 g5606 +0 1 +.names g1201 g5609 +0 1 +.names g1476 g5610 +0 1 +.names g1481 g5611 +0 1 +.names g1564 II14066 +0 1 +.names g1564 II14069 +0 1 +.names II14069 g5613 +0 1 +.names g1894 g5614 +0 1 +.names g2574 II14073 +0 1 +.names II14073 g5615 +0 1 +.names g3093 g5618 +0 1 +.names g3161 g5621 +0 1 +.names g3176 g5622 +0 1 +.names g70 g5623 +0 1 +.names g121 g5626 +0 1 +.names g125 g5627 +0 1 +.names g300 g5628 +0 1 +.names g325 II14083 +0 1 +.names g767 g5631 +0 1 +.names g1895 g5634 +0 1 +.names g2170 g5635 +0 1 +.names g2175 g5636 +0 1 +.names g2258 II14091 +0 1 +.names g2258 II14094 +0 1 +.names II14094 g5638 +0 1 +.names g2588 g5639 +0 1 +.names g3170 g5640 +0 1 +.names g3185 g5641 +0 1 +.names g61 g5642 +0 1 +.names g101 g5645 +0 1 +.names g213 g5646 +0 1 +.names g301 g5647 +0 1 +.names g331 II14104 +0 1 +.names g758 g5651 +0 1 +.names g809 g5654 +0 1 +.names g813 g5655 +0 1 +.names g987 g5656 +0 1 +.names g1012 II14113 +0 1 +.names g1453 g5659 +0 1 +.names g2589 g5662 +0 1 +.names g3179 g5663 +0 1 +.names g65 g5664 +0 1 +.names g105 g5665 +0 1 +.names g216 g5666 +0 1 +.names g222 g5667 +0 1 +.names g299 g5668 +0 1 +.names g302 g5675 +0 1 +.names g506 g5679 +0 1 +.names g749 g5680 +0 1 +.names g789 g5683 +0 1 +.names g900 g5684 +0 1 +.names g988 g5685 +0 1 +.names g1018 II14134 +0 1 +.names g1444 g5689 +0 1 +.names g1501 g5692 +0 1 +.names g1506 g5693 +0 1 +.names g1681 g5694 +0 1 +.names g1706 II14143 +0 1 +.names g2147 g5697 +0 1 +.names g3088 g5700 +0 1 +.names g3231 II14149 +0 1 +.names II14149 g5701 +0 1 +.names g56 g5702 +0 1 +.names g109 g5703 +0 1 +.names g219 g5704 +0 1 +.names g225 g5705 +0 1 +.names g231 g5706 +0 1 +.names g109 g5707 +0 1 +.names g303 g5708 +0 1 +.names g305 g5712 +0 1 +.names g113 II14163 +0 1 +.names II14163 g5713 +0 1 +.names g507 g5714 +0 1 +.names g541 g5715 +0 1 +.names g753 g5716 +0 1 +.names g793 g5717 +0 1 +.names g903 g5718 +0 1 +.names g909 g5719 +0 1 +.names g986 g5720 +0 1 +.names g989 g5727 +0 1 +.names g1192 g5731 +0 1 +.names g1435 g5732 +0 1 +.names g1476 g5735 +0 1 +.names g1594 g5736 +0 1 +.names g1682 g5737 +0 1 +.names g1712 II14182 +0 1 +.names g2138 g5741 +0 1 +.names g2195 g5744 +0 1 +.names g2200 g5745 +0 1 +.names g2375 g5746 +0 1 +.names g2400 II14191 +0 1 +.names g3212 II14195 +0 1 +.names II14195 g5749 +0 1 +.names g92 g5750 +0 1 +.names g52 g5751 +0 1 +.names g113 g5752 +0 1 +.names g228 g5753 +0 1 +.names g234 g5754 +0 1 +.names g240 g5755 +0 1 +.names g304 g5756 +0 1 +.names g508 g5759 +0 1 +.names g744 g5760 +0 1 +.names g797 g5761 +0 1 +.names g906 g5762 +0 1 +.names g912 g5763 +0 1 +.names g918 g5764 +0 1 +.names g797 g5765 +0 1 +.names g990 g5766 +0 1 +.names g992 g5770 +0 1 +.names g801 II14219 +0 1 +.names II14219 g5771 +0 1 +.names g1193 g5772 +0 1 +.names g1227 g5773 +0 1 +.names g1439 g5774 +0 1 +.names g1481 g5775 +0 1 +.names g1597 g5776 +0 1 +.names g1603 g5777 +0 1 +.names g1680 g5778 +0 1 +.names g1683 g5785 +0 1 +.names g1886 g5789 +0 1 +.names g2129 g5790 +0 1 +.names g2170 g5793 +0 1 +.names g2288 g5794 +0 1 +.names g2376 g5795 +0 1 +.names g2406 II14238 +0 1 +.names g3221 II14243 +0 1 +.names II14243 g5799 +0 1 +.names g3227 II14246 +0 1 +.names II14246 g5800 +0 1 +.names g3216 II14249 +0 1 +.names II14249 g5801 +0 1 +.names g83 g5802 +0 1 +.names g117 g5803 +0 1 +.names g237 g5804 +0 1 +.names g243 g5805 +0 1 +.names g249 g5806 +0 1 +.names g509 g5808 +0 1 +.names g780 g5809 +0 1 +.names g740 g5810 +0 1 +.names g801 g5811 +0 1 +.names g915 g5812 +0 1 +.names g921 g5813 +0 1 +.names g927 g5814 +0 1 +.names g991 g5815 +0 1 +.names g1194 g5818 +0 1 +.names g1430 g5819 +0 1 +.names g1486 g5820 +0 1 +.names g1600 g5821 +0 1 +.names g1606 g5822 +0 1 +.names g1612 g5823 +0 1 +.names g1486 g5824 +0 1 +.names g1684 g5825 +0 1 +.names g1686 g5829 +0 1 +.names g1491 II14280 +0 1 +.names II14280 g5830 +0 1 +.names g1887 g5831 +0 1 +.names g1921 g5832 +0 1 +.names g2133 g5833 +0 1 +.names g2175 g5834 +0 1 +.names g2291 g5835 +0 1 +.names g2297 g5836 +0 1 +.names g2374 g5837 +0 1 +.names g2377 g5844 +0 1 +.names g2580 g5848 +0 1 +.names g3228 II14295 +0 1 +.names II14295 g5849 +0 1 +.names g3217 II14298 +0 1 +.names II14298 g5850 +0 1 +.names g74 g5851 +0 1 +.names g121 g5852 +0 1 +.names g246 g5853 +0 1 +.names g252 g5854 +0 1 +.names g258 g5855 +0 1 +.names g97 II14306 +0 1 +.names II14306 g5856 +0 1 +.names g538 g5857 +0 1 +.names g771 g5858 +0 1 +.names g805 g5859 +0 1 +.names g924 g5860 +0 1 +.names g930 g5861 +0 1 +.names g936 g5862 +0 1 +.names g1195 g5864 +0 1 +.names g1466 g5865 +0 1 +.names g1426 g5866 +0 1 +.names g1491 g5867 +0 1 +.names g1609 g5868 +0 1 +.names g1615 g5869 +0 1 +.names g1621 g5870 +0 1 +.names g1685 g5871 +0 1 +.names g1888 g5874 +0 1 +.names g2124 g5875 +0 1 +.names g2180 g5876 +0 1 +.names g2294 g5877 +0 1 +.names g2300 g5878 +0 1 +.names g2306 g5879 +0 1 +.names g2180 g5880 +0 1 +.names g2378 g5881 +0 1 +.names g2380 g5885 +0 1 +.names g2185 II14338 +0 1 +.names II14338 g5886 +0 1 +.names g2581 g5887 +0 1 +.names g2615 g5888 +0 1 +.names g3219 II14343 +0 1 +.names II14343 g5889 +0 1 +.names g88 g5890 +0 1 +.names g125 g5893 +0 1 +.names g186 g5894 +0 1 +.names g255 g5895 +0 1 +.names g261 g5896 +0 1 +.names g267 g5897 +0 1 +.names g762 g5898 +0 1 +.names g809 g5899 +0 1 +.names g933 g5900 +0 1 +.names g939 g5901 +0 1 +.names g945 g5902 +0 1 +.names g785 II14357 +0 1 +.names II14357 g5903 +0 1 +.names g1224 g5904 +0 1 +.names g1457 g5905 +0 1 +.names g1496 g5906 +0 1 +.names g1618 g5907 +0 1 +.names g1624 g5908 +0 1 +.names g1630 g5909 +0 1 +.names g1889 g5911 +0 1 +.names g2160 g5912 +0 1 +.names g2120 g5913 +0 1 +.names g2185 g5914 +0 1 +.names g2303 g5915 +0 1 +.names g2309 g5916 +0 1 +.names g2315 g5917 +0 1 +.names g2379 g5918 +0 1 +.names g2582 g5921 +0 1 +.names g3234 II14378 +0 1 +.names II14378 g5922 +0 1 +.names g3223 II14381 +0 1 +.names II14381 g5923 +0 1 +.names g3218 II14384 +0 1 +.names II14384 g5924 +0 1 +.names g189 g5925 +0 1 +.names g195 g5926 +0 1 +.names g264 g5927 +0 1 +.names g270 g5928 +0 1 +.names g776 g5929 +0 1 +.names g813 g5932 +0 1 +.names g873 g5933 +0 1 +.names g942 g5934 +0 1 +.names g948 g5935 +0 1 +.names g954 g5936 +0 1 +.names g1448 g5937 +0 1 +.names g1501 g5938 +0 1 +.names g1627 g5939 +0 1 +.names g1633 g5940 +0 1 +.names g1639 g5941 +0 1 +.names g1471 II14402 +0 1 +.names II14402 g5942 +0 1 +.names g1918 g5943 +0 1 +.names g2151 g5944 +0 1 +.names g2190 g5945 +0 1 +.names g2312 g5946 +0 1 +.names g2318 g5947 +0 1 +.names g2324 g5948 +0 1 +.names g2583 g5950 +0 1 +.names g3233 II14413 +0 1 +.names II14413 g5951 +0 1 +.names g3222 II14416 +0 1 +.names II14416 g5952 +0 1 +.names g97 g5953 +0 1 +.names g192 g5954 +0 1 +.names g198 g5955 +0 1 +.names g204 g5956 +0 1 +.names g273 g5957 +0 1 +.names g117 II14424 +0 1 +.names II14424 g5958 +0 1 +.names g876 g5959 +0 1 +.names g882 g5960 +0 1 +.names g951 g5961 +0 1 +.names g957 g5962 +0 1 +.names g1462 g5963 +0 1 +.names g1506 g5966 +0 1 +.names g1567 g5967 +0 1 +.names g1636 g5968 +0 1 +.names g1642 g5969 +0 1 +.names g1648 g5970 +0 1 +.names g2142 g5971 +0 1 +.names g2195 g5972 +0 1 +.names g2321 g5973 +0 1 +.names g2327 g5974 +0 1 +.names g2333 g5975 +0 1 +.names g2165 II14442 +0 1 +.names II14442 g5976 +0 1 +.names g2612 g5977 +0 1 +.names g3230 II14446 +0 1 +.names II14446 g5978 +0 1 +.names g3224 II14449 +0 1 +.names II14449 g5979 +0 1 +.names g201 g5980 +0 1 +.names g207 g5981 +0 1 +.names g785 g5982 +0 1 +.names g879 g5983 +0 1 +.names g885 g5984 +0 1 +.names g891 g5985 +0 1 +.names g960 g5986 +0 1 +.names g805 II14459 +0 1 +.names II14459 g5987 +0 1 +.names g1570 g5988 +0 1 +.names g1576 g5989 +0 1 +.names g1645 g5990 +0 1 +.names g1651 g5991 +0 1 +.names g2156 g5992 +0 1 +.names g2200 g5995 +0 1 +.names g2261 g5996 +0 1 +.names g2330 g5997 +0 1 +.names g2336 g5998 +0 1 +.names g2342 g5999 +0 1 +.names g3080 II14472 +0 1 +.names II14472 g6000 +0 1 +.names g3225 II14475 +0 1 +.names II14475 g6014 +0 1 +.names g3213 II14478 +0 1 +.names II14478 g6015 +0 1 +.names g210 g6016 +0 1 +.names g888 g6017 +0 1 +.names g894 g6018 +0 1 +.names g1471 g6019 +0 1 +.names g1573 g6020 +0 1 +.names g1579 g6021 +0 1 +.names g1585 g6022 +0 1 +.names g1654 g6023 +0 1 +.names g1496 II14489 +0 1 +.names II14489 g6024 +0 1 +.names g2264 g6025 +0 1 +.names g2270 g6026 +0 1 +.names g2339 g6027 +0 1 +.names g2345 g6028 +0 1 +.names g3226 II14496 +0 1 +.names II14496 g6029 +0 1 +.names g3214 II14499 +0 1 +.names II14499 g6030 +0 1 +.names g471 II14502 +0 1 +.names II14502 g6031 +0 1 +.names g897 g6032 +0 1 +.names g1582 g6033 +0 1 +.names g1588 g6034 +0 1 +.names g2165 g6035 +0 1 +.names g2267 g6036 +0 1 +.names g2273 g6037 +0 1 +.names g2279 g6038 +0 1 +.names g2348 g6039 +0 1 +.names g2190 II14513 +0 1 +.names II14513 g6040 +0 1 +.names g3215 II14516 +0 1 +.names II14516 g6041 +0 1 +.names g1158 II14519 +0 1 +.names II14519 g6042 +0 1 +.names g1591 g6043 +0 1 +.names g2276 g6044 +0 1 +.names g2282 g6045 +0 1 +.names g1852 II14525 +0 1 +.names II14525 g6046 +0 1 +.names g2285 g6047 +0 1 +.names g3142 II14529 +0 1 +.names II14529 g6048 +0 1 +.names g354 II14532 +0 1 +.names II14532 g6051 +0 1 +.names g2546 II14535 +0 1 +.names II14535 g6052 +0 1 +.names g369 II14538 +0 1 +.names II14538 g6053 +0 1 +.names g455 II14541 +0 1 +.names II14541 g6054 +0 1 +.names g1041 II14544 +0 1 +.names II14544 g6055 +0 1 +.names g384 II14547 +0 1 +.names II14547 g6056 +0 1 +.names g458 II14550 +0 1 +.names II14550 g6057 +0 1 +.names g1056 II14553 +0 1 +.names II14553 g6058 +0 1 +.names g1142 II14556 +0 1 +.names II14556 g6059 +0 1 +.names g1735 II14559 +0 1 +.names II14559 g6060 +0 1 +.names g398 II14562 +0 1 +.names II14562 g6061 +0 1 +.names g461 II14565 +0 1 +.names II14565 g6062 +0 1 +.names g1071 II14568 +0 1 +.names II14568 g6063 +0 1 +.names g1145 II14571 +0 1 +.names II14571 g6064 +0 1 +.names g1750 II14574 +0 1 +.names II14574 g6065 +0 1 +.names g1836 II14577 +0 1 +.names II14577 g6066 +0 1 +.names g2429 II14580 +0 1 +.names II14580 g6067 +0 1 +.names g499 g6068 +0 1 +.names g465 II14584 +0 1 +.names II14584 g6079 +0 1 +.names g1085 II14587 +0 1 +.names II14587 g6080 +0 1 +.names g1148 II14590 +0 1 +.names II14590 g6081 +0 1 +.names g1765 II14593 +0 1 +.names II14593 g6082 +0 1 +.names g1839 II14596 +0 1 +.names II14596 g6083 +0 1 +.names g2444 II14599 +0 1 +.names II14599 g6084 +0 1 +.names g2530 II14602 +0 1 +.names II14602 g6085 +0 1 +.names g468 II14605 +0 1 +.names II14605 g6086 +0 1 +.names g1186 g6087 +0 1 +.names g1152 II14609 +0 1 +.names II14609 g6098 +0 1 +.names g1779 II14612 +0 1 +.names II14612 g6099 +0 1 +.names g1842 II14615 +0 1 +.names II14615 g6100 +0 1 +.names g2459 II14618 +0 1 +.names II14618 g6101 +0 1 +.names g2533 II14621 +0 1 +.names II14621 g6102 +0 1 +.names g1155 II14624 +0 1 +.names II14624 g6103 +0 1 +.names g1880 g6104 +0 1 +.names g1846 II14628 +0 1 +.names II14628 g6115 +0 1 +.names g2473 II14631 +0 1 +.names II14631 g6116 +0 1 +.names g2536 II14634 +0 1 +.names II14634 g6117 +0 1 +.names g1849 II14637 +0 1 +.names II14637 g6118 +0 1 +.names g2574 g6119 +0 1 +.names g2540 II14641 +0 1 +.names II14641 g6130 +0 1 +.names g3142 II14644 +0 1 +.names II14644 g6131 +0 1 +.names g2543 II14647 +0 1 +.names II14647 g6134 +0 1 +.names g525 II14650 +0 1 +.names II14650 g6135 +0 1 +.names g672 g6136 +0 1 +.names g3220 II14654 +0 1 +.names II14654 g6139 +0 1 +.names g524 g6140 +0 1 +.names g554 g6141 +0 1 +.names g679 g6142 +0 1 +.names g1211 II14660 +0 1 +.names II14660 g6145 +0 1 +.names g1358 g6146 +0 1 +.names g3097 g6149 +0 1 +.names g3147 II14665 +0 1 +.names II14665 g6153 +0 1 +.names g3232 II14668 +0 1 +.names II14668 g6156 +0 1 +.names g686 g6157 +0 1 +.names g1210 g6161 +0 1 +.names g1240 g6162 +0 1 +.names g1365 g6163 +0 1 +.names g1905 II14675 +0 1 +.names II14675 g6166 +0 1 +.names g2052 g6167 +0 1 +.names g3098 g6170 +0 1 +.names g557 g6173 +0 1 +.names g633 g6177 +0 1 +.names g692 g6180 +0 1 +.names g291 g6183 +0 1 +.names g1372 g6184 +0 1 +.names g1904 g6188 +0 1 +.names g1934 g6189 +0 1 +.names g2059 g6190 +0 1 +.names g2599 II14688 +0 1 +.names II14688 g6193 +0 1 +.names g2746 g6194 +0 1 +.names g3099 g6197 +0 1 +.names g542 g6200 +0 1 +.names g646 g6201 +0 1 +.names g289 g6204 +0 1 +.names g1243 g6205 +0 1 +.names g1319 g6209 +0 1 +.names g1378 g6212 +0 1 +.names g978 g6215 +0 1 +.names g2066 g6216 +0 1 +.names g2598 g6220 +0 1 +.names g2628 g6221 +0 1 +.names g2753 g6222 +0 1 +.names g2818 II14704 +0 1 +.names g2818 g6226 +0 1 +.names g3100 g6227 +0 1 +.names g3229 II14709 +0 1 +.names II14709 g6230 +0 1 +.names g138 II14712 +0 1 +.names g138 II14715 +0 1 +.names II14715 g6232 +0 1 +.names g510 g6281 +0 1 +.names g640 g6284 +0 1 +.names g287 g6288 +0 1 +.names g1228 g6289 +0 1 +.names g1332 g6290 +0 1 +.names g976 g6293 +0 1 +.names g1937 g6294 +0 1 +.names g2013 g6298 +0 1 +.names g2072 g6301 +0 1 +.names g1672 g6304 +0 1 +.names g2760 g6305 +0 1 +.names g14 g6309 +0 1 +.names g3101 g6310 +0 1 +.names g135 II14731 +0 1 +.names g135 II14734 +0 1 +.names II14734 g6314 +0 1 +.names g653 g6363 +0 1 +.names g285 g6367 +0 1 +.names g826 II14739 +0 1 +.names g826 II14742 +0 1 +.names II14742 g6369 +0 1 +.names g1196 g6418 +0 1 +.names g1326 g6421 +0 1 +.names g974 g6425 +0 1 +.names g1922 g6426 +0 1 +.names g2026 g6427 +0 1 +.names g1670 g6430 +0 1 +.names g2631 g6431 +0 1 +.names g2707 g6435 +0 1 +.names g2766 g6438 +0 1 +.names g2366 g6441 +0 1 +.names g2821 II14755 +0 1 +.names g2821 g6443 +0 1 +.names g3102 g6444 +0 1 +.names g405 II14760 +0 1 +.names g405 II14763 +0 1 +.names II14763 g6448 +0 1 +.names g545 II14766 +0 1 +.names g545 II14769 +0 1 +.names II14769 g6486 +0 1 +.names g544 g6512 +0 1 +.names g660 g6513 +0 1 +.names g283 g6517 +0 1 +.names g823 II14775 +0 1 +.names g823 II14778 +0 1 +.names II14778 g6519 +0 1 +.names g1339 g6568 +0 1 +.names g972 g6572 +0 1 +.names g1520 II14783 +0 1 +.names g1520 II14786 +0 1 +.names II14786 g6574 +0 1 +.names g1890 g6623 +0 1 +.names g2020 g6626 +0 1 +.names g1668 g6630 +0 1 +.names g2616 g6631 +0 1 +.names g2720 g6632 +0 1 +.names g2364 g6635 +0 1 +.names g1491 g6636 +0 1 +.names g5 g6637 +0 1 +.names g3103 g6638 +0 1 +.names g113 g6641 +0 1 +.names g551 II14799 +0 1 +.names g551 II14802 +0 1 +.names II14802 g6643 +0 1 +.names g464 g6672 +0 1 +.names g458 g6675 +0 1 +.names g559 g6676 +0 1 +.names g623 II14808 +0 1 +.names g623 II14811 +0 1 +.names II14811 g6678 +0 1 +.names g666 g6707 +0 1 +.names g281 g6711 +0 1 +.names g1092 II14816 +0 1 +.names g1092 II14819 +0 1 +.names II14819 g6713 +0 1 +.names g1231 II14822 +0 1 +.names g1231 II14825 +0 1 +.names II14825 g6751 +0 1 +.names g1230 g6776 +0 1 +.names g1346 g6777 +0 1 +.names g970 g6781 +0 1 +.names g1517 II14831 +0 1 +.names g1517 II14834 +0 1 +.names II14834 g6783 +0 1 +.names g2033 g6832 +0 1 +.names g1666 g6836 +0 1 +.names g2214 II14839 +0 1 +.names g2214 II14842 +0 1 +.names II14842 g6838 +0 1 +.names g2584 g6887 +0 1 +.names g2714 g6890 +0 1 +.names g2362 g6894 +0 1 +.names g2824 II14848 +0 1 +.names g2824 g6896 +0 1 +.names g1486 g6897 +0 1 +.names g2993 g6898 +0 1 +.names g3006 g6901 +0 1 +.names g3104 g6905 +0 1 +.names g484 g6908 +0 1 +.names g626 II14857 +0 1 +.names g626 II14860 +0 1 +.names II14860 g6912 +0 1 +.names g279 g6942 +0 1 +.names g801 g6943 +0 1 +.names g1237 II14865 +0 1 +.names g1237 II14868 +0 1 +.names II14868 g6945 +0 1 +.names g1151 g6974 +0 1 +.names g1145 g6977 +0 1 +.names g1245 g6978 +0 1 +.names g1309 II14874 +0 1 +.names g1309 II14877 +0 1 +.names II14877 g6980 +0 1 +.names g1352 g7009 +0 1 +.names g968 g7013 +0 1 +.names g1786 II14882 +0 1 +.names g1786 II14885 +0 1 +.names II14885 g7015 +0 1 +.names g1925 II14888 +0 1 +.names g1925 II14891 +0 1 +.names II14891 g7053 +0 1 +.names g1924 g7078 +0 1 +.names g2040 g7079 +0 1 +.names g1664 g7083 +0 1 +.names g2211 II14897 +0 1 +.names g2211 II14900 +0 1 +.names II14900 g7085 +0 1 +.names g2727 g7134 +0 1 +.names g2360 g7138 +0 1 +.names g1481 g7139 +0 1 +.names g2170 g7140 +0 1 +.names g2195 g7141 +0 1 +.names g8 g7142 +0 1 +.names g2998 g7143 +0 1 +.names g3013 g7146 +0 1 +.names g3105 g7149 +0 1 +.names g3136 g7152 +0 1 +.names g480 g7153 +0 1 +.names g461 g7156 +0 1 +.names g453 g7157 +0 1 +.names g1171 g7158 +0 1 +.names g1312 II14917 +0 1 +.names g1312 II14920 +0 1 +.names II14920 g7162 +0 1 +.names g966 g7192 +0 1 +.names g1491 g7193 +0 1 +.names g1931 II14925 +0 1 +.names g1931 II14928 +0 1 +.names II14928 g7195 +0 1 +.names g1845 g7224 +0 1 +.names g1839 g7227 +0 1 +.names g1939 g7228 +0 1 +.names g2003 II14934 +0 1 +.names g2003 II14937 +0 1 +.names II14937 g7230 +0 1 +.names g2046 g7259 +0 1 +.names g1662 g7263 +0 1 +.names g2480 II14942 +0 1 +.names g2480 II14945 +0 1 +.names II14945 g7265 +0 1 +.names g2619 II14948 +0 1 +.names g2619 II14951 +0 1 +.names II14951 g7303 +0 1 +.names g2618 g7328 +0 1 +.names g2734 g7329 +0 1 +.names g2358 g7333 +0 1 +.names g2827 II14957 +0 1 +.names g2827 g7335 +0 1 +.names g1476 g7336 +0 1 +.names g2190 g7337 +0 1 +.names g3002 g7338 +0 1 +.names g3024 g7342 +0 1 +.names g3139 g7345 +0 1 +.names g97 g7346 +0 1 +.names g490 g7347 +0 1 +.names g451 g7348 +0 1 +.names g1167 g7349 +0 1 +.names g1148 g7352 +0 1 +.names g1140 g7353 +0 1 +.names g1865 g7354 +0 1 +.names g2006 II14973 +0 1 +.names g2006 II14976 +0 1 +.names II14976 g7358 +0 1 +.names g1660 g7388 +0 1 +.names g2185 g7389 +0 1 +.names g2625 II14981 +0 1 +.names g2625 II14984 +0 1 +.names II14984 g7391 +0 1 +.names g2539 g7420 +0 1 +.names g2533 g7423 +0 1 +.names g2633 g7424 +0 1 +.names g2697 II14990 +0 1 +.names g2697 II14993 +0 1 +.names II14993 g7426 +0 1 +.names g2740 g7455 +0 1 +.names g2356 g7459 +0 1 +.names g1471 g7460 +0 1 +.names g2175 g7461 +0 1 +.names g2912 g7462 +0 1 +.names g2 g7465 +0 1 +.names g3010 g7466 +0 1 +.names g3036 g7471 +0 1 +.names g493 g7475 +0 1 +.names g785 g7476 +0 1 +.names g1177 g7477 +0 1 +.names g1138 g7478 +0 1 +.names g1861 g7479 +0 1 +.names g1842 g7482 +0 1 +.names g1834 g7483 +0 1 +.names g2559 g7484 +0 1 +.names g2700 II15012 +0 1 +.names g2700 II15015 +0 1 +.names II15015 g7488 +0 1 +.names g2354 g7518 +0 1 +.names g2830 II15019 +0 1 +.names g2830 g7520 +0 1 +.names g2200 g7521 +0 1 +.names g2917 g7522 +0 1 +.names g3018 g7527 +0 1 +.names g465 g7529 +0 1 +.names g496 g7530 +0 1 +.names g1180 g7531 +0 1 +.names g1471 g7532 +0 1 +.names g1871 g7533 +0 1 +.names g1832 g7534 +0 1 +.names g2555 g7535 +0 1 +.names g2536 g7538 +0 1 +.names g2528 g7539 +0 1 +.names g1506 g7540 +0 1 +.names g2180 g7541 +0 1 +.names g2883 g7542 +0 1 +.names g2920 g7545 +0 1 +.names g2990 g7548 +0 1 +.names g3028 g7549 +0 1 +.names g3114 g7553 +0 1 +.names g117 g7554 +0 1 +.names g1152 g7555 +0 1 +.names g1183 g7556 +0 1 +.names g1874 g7557 +0 1 +.names g2165 g7558 +0 1 +.names g2565 g7559 +0 1 +.names g2526 g7560 +0 1 +.names g1501 g7561 +0 1 +.names g2888 g7562 +0 1 +.names g2896 g7566 +0 1 +.names g3032 g7570 +0 1 +.names g3120 g7573 +0 1 +.names g3128 g7574 +0 1 +.names g468 g7576 +0 1 +.names g805 g7577 +0 1 +.names g1846 g7578 +0 1 +.names g1877 g7579 +0 1 +.names g2568 g7580 +0 1 +.names g1496 g7581 +0 1 +.names g2185 g7582 +0 1 +.names g2892 g7583 +0 1 +.names g2903 g7587 +0 1 +.names g1155 g7590 +0 1 +.names g1496 g7591 +0 1 +.names g2540 g7592 +0 1 +.names g2571 g7593 +0 1 +.names g2165 g7594 +0 1 +.names g2900 g7595 +0 1 +.names g2908 g7600 +0 1 +.names g3133 g7603 +0 1 +.names g471 g7604 +0 1 +.names g1849 g7605 +0 1 +.names g2190 g7606 +0 1 +.names g2924 g7607 +0 1 +.names g312 g7610 +0 1 +.names g1158 g7613 +0 1 +.names g2543 g7614 +0 1 +.names g3123 g7615 +0 1 +.names g313 g7616 +0 1 +.names g999 g7619 +0 1 +.names g1852 g7622 +0 1 +.names g314 g7623 +0 1 +.names g315 g7626 +0 1 +.names g403 g7629 +0 1 +.names g1000 g7632 +0 1 +.names g1693 g7635 +0 1 +.names g2546 g7638 +0 1 +.names g3094 g7639 +0 1 +.names g3125 g7642 +0 1 +.names g316 g7643 +0 1 +.names g318 g7646 +0 1 +.names g404 g7649 +0 1 +.names g1001 g7652 +0 1 +.names g1002 g7655 +0 1 +.names g1090 g7658 +0 1 +.names g1694 g7661 +0 1 +.names g2387 g7664 +0 1 +.names g3095 g7667 +0 1 +.names g317 g7670 +0 1 +.names g319 g7673 +0 1 +.names g402 g7676 +0 1 +.names g1003 g7679 +0 1 +.names g1005 g7682 +0 1 +.names g1091 g7685 +0 1 +.names g1695 g7688 +0 1 +.names g1696 g7691 +0 1 +.names g1784 g7694 +0 1 +.names g2388 g7697 +0 1 +.names g3096 g7700 +0 1 +.names g320 g7703 +0 1 +.names g1004 g7706 +0 1 +.names g1006 g7709 +0 1 +.names g1089 g7712 +0 1 +.names g1697 g7715 +0 1 +.names g1699 g7718 +0 1 +.names g1785 g7721 +0 1 +.names g2389 g7724 +0 1 +.names g2390 g7727 +0 1 +.names g2478 g7730 +0 1 +.names g1007 g7733 +0 1 +.names g1698 g7736 +0 1 +.names g1700 g7739 +0 1 +.names g1783 g7742 +0 1 +.names g2391 g7745 +0 1 +.names g2393 g7748 +0 1 +.names g2479 g7751 +0 1 +.names g322 g7754 +0 1 +.names g1701 g7757 +0 1 +.names g2392 g7760 +0 1 +.names g2394 g7763 +0 1 +.names g2477 g7766 +0 1 +.names g323 g7769 +0 1 +.names g659 g7772 +0 1 +.names g1009 g7776 +0 1 +.names g2395 g7779 +0 1 +.names g321 g7782 +0 1 +.names g1010 g7785 +0 1 +.names g1345 g7788 +0 1 +.names g1703 g7792 +0 1 +.names g1008 g7796 +0 1 +.names g1704 g7799 +0 1 +.names g2039 g7802 +0 1 +.names g2397 g7806 +0 1 +.names g1702 g7809 +0 1 +.names g2398 g7812 +0 1 +.names g2733 g7815 +0 1 +.names g479 g7819 +0 1 +.names g510 g7822 +0 1 +.names g2396 g7823 +0 1 +.names g2987 g7826 +0 1 +.names g478 g7827 +0 1 +.names g1166 g7830 +0 1 +.names g1196 g7833 +0 1 +.names g2953 g7834 +0 1 +.names g3044 g7837 +0 1 +.names g477 g7838 +0 1 +.names g630 g7841 +0 1 +.names g1165 g7842 +0 1 +.names g1860 g7845 +0 1 +.names g1890 g7848 +0 1 +.names g2956 g7849 +0 1 +.names g2981 g7852 +0 1 +.names g3045 g7856 +0 1 +.names g3055 g7857 +0 1 +.names g1164 g7858 +0 1 +.names g1316 g7861 +0 1 +.names g1859 g7862 +0 1 +.names g2554 g7865 +0 1 +.names g2584 g7868 +0 1 +.names g2959 g7869 +0 1 +.names g2874 g7872 +0 1 +.names g3046 g7877 +0 1 +.names g3056 g7878 +0 1 +.names g3065 g7879 +0 1 +.names g3201 g7880 +0 1 +.names g1858 g7888 +0 1 +.names g2010 g7891 +0 1 +.names g2553 g7892 +0 1 +.names g3047 g7897 +0 1 +.names g3057 g7898 +0 1 +.names g3066 g7899 +0 1 +.names g3075 g7900 +0 1 +.names g3151 II15222 +0 1 +.names II15222 g7901 +0 1 +.names g488 g7906 +0 1 +.names g474 II15226 +0 1 +.names g474 g7910 +0 1 +.names g499 II15230 +0 1 +.names II15230 g7911 +0 1 +.names g2552 g7912 +0 1 +.names g2704 g7915 +0 1 +.names g2935 g7916 +0 1 +.names g2963 g7919 +0 1 +.names g3048 g7924 +0 1 +.names g3058 g7925 +0 1 +.names g3067 g7926 +0 1 +.names g3076 g7927 +0 1 +.names g3204 g7928 +0 1 +.names g2950 II15256 +0 1 +.names II15256 g7936 +0 1 +.names g165 g7949 +0 1 +.names g142 g7950 +0 1 +.names g487 g7953 +0 1 +.names g481 II15262 +0 1 +.names g481 g7957 +0 1 +.names g1175 g7958 +0 1 +.names g1161 II15267 +0 1 +.names g1161 g7962 +0 1 +.names g1186 II15271 +0 1 +.names II15271 g7963 +0 1 +.names g2938 g7964 +0 1 +.names g2966 g7967 +0 1 +.names g3049 g7971 +0 1 +.names g3059 g7972 +0 1 +.names g3068 g7973 +0 1 +.names g3077 g7974 +0 1 +.names g39 g7975 +0 1 +.names g3109 II15288 +0 1 +.names II15288 g7976 +0 1 +.names g3191 g7989 +0 1 +.names g143 g7990 +0 1 +.names g145 g7993 +0 1 +.names g486 g7996 +0 1 +.names g485 g7999 +0 1 +.names g853 g8000 +0 1 +.names g830 g8001 +0 1 +.names g1174 g8004 +0 1 +.names g1168 II15299 +0 1 +.names g1168 g8008 +0 1 +.names g1869 g8009 +0 1 +.names g1855 II15304 +0 1 +.names g1855 g8013 +0 1 +.names g1880 II15308 +0 1 +.names II15308 g8014 +0 1 +.names g2941 g8015 +0 1 +.names g2969 g8018 +0 1 +.names g2930 II15313 +0 1 +.names g2930 g8022 +0 1 +.names g2842 II15317 +0 1 +.names g2842 g8024 +0 1 +.names g3050 g8025 +0 1 +.names g3060 g8026 +0 1 +.names g3069 g8027 +0 1 +.names g3078 g8028 +0 1 +.names g3083 g8029 +0 1 +.names g3117 II15326 +0 1 +.names g3117 II15329 +0 1 +.names II15329 g8031 +0 1 +.names g3194 g8044 +0 1 +.names g3207 g8045 +0 1 +.names g141 g8053 +0 1 +.names g146 g8056 +0 1 +.names g148 g8059 +0 1 +.names g169 g8062 +0 1 +.names g831 g8065 +0 1 +.names g833 g8068 +0 1 +.names g1173 g8071 +0 1 +.names g1172 g8074 +0 1 +.names g1547 g8075 +0 1 +.names g1524 g8076 +0 1 +.names g1868 g8079 +0 1 +.names g1862 II15345 +0 1 +.names g1862 g8083 +0 1 +.names g2563 g8084 +0 1 +.names g2549 II15350 +0 1 +.names g2549 g8088 +0 1 +.names g2574 II15354 +0 1 +.names II15354 g8089 +0 1 +.names g2944 g8090 +0 1 +.names g2972 g8093 +0 1 +.names g2858 II15359 +0 1 +.names g2858 g8097 +0 1 +.names g3051 g8098 +0 1 +.names g3061 g8099 +0 1 +.names g3070 g8100 +0 1 +.names g2997 g8101 +0 1 +.names g27 g8102 +0 1 +.names g185 g8103 +0 1 +.names g3129 II15369 +0 1 +.names g3129 II15372 +0 1 +.names II15372 g8107 +0 1 +.names g3197 g8120 +0 1 +.names g144 g8123 +0 1 +.names g149 g8126 +0 1 +.names g151 g8129 +0 1 +.names g170 g8132 +0 1 +.names g172 g8135 +0 1 +.names g829 g8138 +0 1 +.names g834 g8141 +0 1 +.names g836 g8144 +0 1 +.names g857 g8147 +0 1 +.names g1525 g8150 +0 1 +.names g1527 g8153 +0 1 +.names g1867 g8156 +0 1 +.names g1866 g8159 +0 1 +.names g2241 g8160 +0 1 +.names g2218 g8161 +0 1 +.names g2562 g8164 +0 1 +.names g2556 II15392 +0 1 +.names g2556 g8168 +0 1 +.names g2947 g8169 +0 1 +.names g2975 g8172 +0 1 +.names g2845 II15398 +0 1 +.names g2845 g8176 +0 1 +.names g3043 g8177 +0 1 +.names g3052 g8178 +0 1 +.names g3062 g8179 +0 1 +.names g3071 g8180 +0 1 +.names g48 g8181 +0 1 +.names g3198 g8182 +0 1 +.names g3188 g8183 +0 1 +.names g147 g8191 +0 1 +.names g152 g8194 +0 1 +.names g154 g8197 +0 1 +.names g168 g8200 +0 1 +.names g173 g8203 +0 1 +.names g175 g8206 +0 1 +.names g832 g8209 +0 1 +.names g837 g8212 +0 1 +.names g839 g8215 +0 1 +.names g858 g8218 +0 1 +.names g860 g8221 +0 1 +.names g1523 g8224 +0 1 +.names g1528 g8227 +0 1 +.names g1530 g8230 +0 1 +.names g1551 g8233 +0 1 +.names g2219 g8236 +0 1 +.names g2221 g8239 +0 1 +.names g2561 g8242 +0 1 +.names g2560 g8245 +0 1 +.names g2978 g8246 +0 1 +.names g2833 II15429 +0 1 +.names g2833 g8250 +0 1 +.names g2861 II15433 +0 1 +.names g2861 g8252 +0 1 +.names g3053 g8253 +0 1 +.names g3063 g8254 +0 1 +.names g3072 g8255 +0 1 +.names g30 g8256 +0 1 +.names g3201 g8257 +0 1 +.names g3235 II15442 +0 1 +.names g3236 II15445 +0 1 +.names g3237 II15448 +0 1 +.names g3238 II15451 +0 1 +.names g3239 II15454 +0 1 +.names g3240 II15457 +0 1 +.names g3241 II15460 +0 1 +.names g3242 II15463 +0 1 +.names g3243 II15466 +0 1 +.names g3244 II15469 +0 1 +.names g3245 II15472 +0 1 +.names g3246 II15475 +0 1 +.names g3247 II15478 +0 1 +.names g3248 II15481 +0 1 +.names g3249 II15484 +0 1 +.names g3250 II15487 +0 1 +.names g3251 II15490 +0 1 +.names g3252 II15493 +0 1 +.names g3253 g8276 +0 1 +.names g3305 g8277 +0 1 +.names g3337 g8278 +0 1 +.names g7911 II15499 +0 1 +.names g3365 g8285 +0 1 +.names g3461 g8286 +0 1 +.names g3493 g8287 +0 1 +.names g7963 II15505 +0 1 +.names g3521 g8294 +0 1 +.names g3617 g8295 +0 1 +.names g3649 g8296 +0 1 +.names g8014 II15511 +0 1 +.names g3677 g8303 +0 1 +.names g3773 g8304 +0 1 +.names g3805 g8305 +0 1 +.names g8089 II15517 +0 1 +.names g3833 g8312 +0 1 +.names g3897 g8313 +0 1 +.names g3919 g8317 +0 1 +.names g3254 II15523 +0 1 +.names II15523 g8321 +0 1 +.names g6314 II15526 +0 1 +.names II15526 g8324 +0 1 +.names g3410 II15532 +0 1 +.names II15532 g8330 +0 1 +.names g6519 II15535 +0 1 +.names II15535 g8333 +0 1 +.names g6369 II15538 +0 1 +.names II15538 g8336 +0 1 +.names g3410 II15543 +0 1 +.names II15543 g8341 +0 1 +.names g6783 II15546 +0 1 +.names II15546 g8344 +0 1 +.names g6574 II15549 +0 1 +.names II15549 g8347 +0 1 +.names g3566 II15553 +0 1 +.names II15553 g8351 +0 1 +.names g6783 II15556 +0 1 +.names II15556 g8354 +0 1 +.names g7015 II15559 +0 1 +.names II15559 g8357 +0 1 +.names g5778 II15562 +0 1 +.names II15562 g8360 +0 1 +.names g6838 II15565 +0 1 +.names II15565 g8363 +0 1 +.names g3722 II15568 +0 1 +.names II15568 g8366 +0 1 +.names g7085 II15571 +0 1 +.names II15571 g8369 +0 1 +.names g6838 II15574 +0 1 +.names II15574 g8372 +0 1 +.names g7265 II15577 +0 1 +.names II15577 g8375 +0 1 +.names g5837 II15580 +0 1 +.names II15580 g8378 +0 1 +.names g3254 II15584 +0 1 +.names II15584 g8382 +0 1 +.names g3410 II15590 +0 1 +.names II15590 g8388 +0 1 +.names g6519 II15593 +0 1 +.names II15593 g8391 +0 1 +.names g3566 II15599 +0 1 +.names II15599 g8397 +0 1 +.names g6783 II15602 +0 1 +.names II15602 g8400 +0 1 +.names g6574 II15605 +0 1 +.names II15605 g8403 +0 1 +.names g3566 II15610 +0 1 +.names II15610 g8408 +0 1 +.names g7085 II15613 +0 1 +.names II15613 g8411 +0 1 +.names g6838 II15616 +0 1 +.names II15616 g8414 +0 1 +.names g3722 II15620 +0 1 +.names II15620 g8418 +0 1 +.names g7085 II15623 +0 1 +.names II15623 g8421 +0 1 +.names g7265 II15626 +0 1 +.names II15626 g8424 +0 1 +.names g5837 II15629 +0 1 +.names II15629 g8427 +0 1 +.names g3410 II15636 +0 1 +.names II15636 g8434 +0 1 +.names g3566 II15642 +0 1 +.names II15642 g8440 +0 1 +.names g6783 II15645 +0 1 +.names II15645 g8443 +0 1 +.names g3722 II15651 +0 1 +.names II15651 g8449 +0 1 +.names g7085 II15654 +0 1 +.names II15654 g8452 +0 1 +.names g6838 II15657 +0 1 +.names II15657 g8455 +0 1 +.names g3722 II15662 +0 1 +.names II15662 g8460 +0 1 +.names g3566 II15671 +0 1 +.names II15671 g8469 +0 1 +.names g3722 II15677 +0 1 +.names II15677 g8475 +0 1 +.names g7085 II15680 +0 1 +.names II15680 g8478 +0 1 +.names g3722 II15696 +0 1 +.names II15696 g8494 +0 1 +.names g6139 g8514 +0 1 +.names g6156 g8530 +0 1 +.names g6230 g8568 +0 1 +.names g6000 II15771 +0 1 +.names II15771 g8569 +0 1 +.names g6000 II15779 +0 1 +.names II15779 g8575 +0 1 +.names g6000 II15784 +0 1 +.names II15784 g8578 +0 1 +.names g6000 II15787 +0 1 +.names II15787 g8579 +0 1 +.names g6281 g8580 +0 1 +.names g6418 g8587 +0 1 +.names g6623 g8594 +0 1 +.names g3338 II15794 +0 1 +.names II15794 g8602 +0 1 +.names g6887 g8605 +0 1 +.names g3494 II15800 +0 1 +.names II15800 g8614 +0 1 +.names g8107 II15803 +0 1 +.names II15803 g8617 +0 1 +.names g5550 II15806 +0 1 +.names II15806 g8620 +0 1 +.names g3338 II15810 +0 1 +.names II15810 g8622 +0 1 +.names g3650 II15815 +0 1 +.names II15815 g8627 +0 1 +.names g5596 II15818 +0 1 +.names II15818 g8630 +0 1 +.names g3494 II15822 +0 1 +.names II15822 g8632 +0 1 +.names g3806 II15827 +0 1 +.names II15827 g8637 +0 1 +.names g8031 II15830 +0 1 +.names II15830 g8640 +0 1 +.names g3338 II15833 +0 1 +.names II15833 g8643 +0 1 +.names g3366 II15836 +0 1 +.names II15836 g8646 +0 1 +.names g5613 II15839 +0 1 +.names II15839 g8649 +0 1 +.names g3650 II15843 +0 1 +.names II15843 g8651 +0 1 +.names g3878 II15847 +0 1 +.names II15847 g8655 +0 1 +.names g5627 II15850 +0 1 +.names II15850 g8658 +0 1 +.names g3494 II15853 +0 1 +.names II15853 g8659 +0 1 +.names g3522 II15856 +0 1 +.names II15856 g8662 +0 1 +.names g5638 II15859 +0 1 +.names II15859 g8665 +0 1 +.names g3806 II15863 +0 1 +.names II15863 g8667 +0 1 +.names g3878 II15866 +0 1 +.names II15866 g8670 +0 1 +.names g7976 II15869 +0 1 +.names II15869 g8673 +0 1 +.names g5655 II15873 +0 1 +.names II15873 g8677 +0 1 +.names g3650 II15876 +0 1 +.names II15876 g8678 +0 1 +.names g3678 II15879 +0 1 +.names II15879 g8681 +0 1 +.names g3878 II15882 +0 1 +.names II15882 g8684 +0 1 +.names g5693 II15887 +0 1 +.names II15887 g8689 +0 1 +.names g3806 II15890 +0 1 +.names II15890 g8690 +0 1 +.names g3834 II15893 +0 1 +.names II15893 g8693 +0 1 +.names g3878 II15896 +0 1 +.names II15896 g8696 +0 1 +.names g5626 II15899 +0 1 +.names II15899 g8699 +0 1 +.names g6486 II15902 +0 1 +.names II15902 g8700 +0 1 +.names g5745 II15909 +0 1 +.names II15909 g8707 +0 1 +.names g3878 II15912 +0 1 +.names II15912 g8708 +0 1 +.names g3878 II15915 +0 1 +.names II15915 g8711 +0 1 +.names g6643 II15918 +0 1 +.names II15918 g8714 +0 1 +.names g5654 II15922 +0 1 +.names II15922 g8718 +0 1 +.names g6751 II15925 +0 1 +.names II15925 g8719 +0 1 +.names g5423 II15932 +0 1 +.names II15932 g8726 +0 1 +.names g3878 II15935 +0 1 +.names II15935 g8745 +0 1 +.names g3338 II15938 +0 1 +.names II15938 g8748 +0 1 +.names g6945 II15942 +0 1 +.names II15942 g8752 +0 1 +.names g5692 II15946 +0 1 +.names II15946 g8756 +0 1 +.names g7053 II15949 +0 1 +.names II15949 g8757 +0 1 +.names g3878 II15955 +0 1 +.names II15955 g8763 +0 1 +.names g3878 II15958 +0 1 +.names II15958 g8766 +0 1 +.names g6051 II15961 +0 1 +.names II15961 g8769 +0 1 +.names g7554 II15964 +0 1 +.names II15964 g8770 +0 1 +.names g3494 II15967 +0 1 +.names II15967 g8771 +0 1 +.names g7195 II15971 +0 1 +.names II15971 g8775 +0 1 +.names g5744 II15975 +0 1 +.names II15975 g8779 +0 1 +.names g7303 II15978 +0 1 +.names II15978 g8780 +0 1 +.names g3878 II15983 +0 1 +.names II15983 g8785 +0 1 +.names g3878 II15986 +0 1 +.names II15986 g8788 +0 1 +.names g6053 II15989 +0 1 +.names II15989 g8791 +0 1 +.names g6055 II15992 +0 1 +.names II15992 g8792 +0 1 +.names g7577 II15995 +0 1 +.names II15995 g8793 +0 1 +.names g3650 II15998 +0 1 +.names II15998 g8794 +0 1 +.names g7391 II16002 +0 1 +.names II16002 g8798 +0 1 +.names g3878 II16006 +0 1 +.names II16006 g8802 +0 1 +.names g3878 II16009 +0 1 +.names II16009 g8805 +0 1 +.names g5390 II16012 +0 1 +.names II16012 g8808 +0 1 +.names g6056 II16015 +0 1 +.names II16015 g8809 +0 1 +.names g6058 II16018 +0 1 +.names II16018 g8810 +0 1 +.names g6060 II16021 +0 1 +.names II16021 g8811 +0 1 +.names g7591 II16024 +0 1 +.names II16024 g8812 +0 1 +.names g3806 II16027 +0 1 +.names II16027 g8813 +0 1 +.names g3878 II16031 +0 1 +.names II16031 g8817 +0 1 +.names g5396 II16034 +0 1 +.names II16034 g8820 +0 1 +.names g6061 II16037 +0 1 +.names II16037 g8821 +0 1 +.names g4602 g8822 +0 1 +.names g6486 II16041 +0 1 +.names II16041 g8823 +0 1 +.names g5397 II16044 +0 1 +.names II16044 g8824 +0 1 +.names g6063 II16047 +0 1 +.names II16047 g8825 +0 1 +.names g6065 II16050 +0 1 +.names II16050 g8826 +0 1 +.names g6067 II16053 +0 1 +.names II16053 g8827 +0 1 +.names g7606 II16056 +0 1 +.names II16056 g8828 +0 1 +.names g3878 II16059 +0 1 +.names II16059 g8829 +0 1 +.names g3900 II16062 +0 1 +.names II16062 g8832 +0 1 +.names g7936 II16065 +0 1 +.names II16065 g8835 +0 1 +.names g5438 II16068 +0 1 +.names II16068 g8836 +0 1 +.names g5395 II16071 +0 1 +.names II16071 g8839 +0 1 +.names g5399 II16074 +0 1 +.names II16074 g8840 +0 1 +.names g6086 II16079 +0 1 +.names II16079 g8843 +0 1 +.names g5401 II16082 +0 1 +.names II16082 g8844 +0 1 +.names g6080 II16085 +0 1 +.names II16085 g8845 +0 1 +.names g4779 g8846 +0 1 +.names g6751 II16089 +0 1 +.names II16089 g8847 +0 1 +.names g5402 II16092 +0 1 +.names II16092 g8850 +0 1 +.names g6082 II16095 +0 1 +.names II16095 g8851 +0 1 +.names g6084 II16098 +0 1 +.names II16098 g8852 +0 1 +.names g3878 II16101 +0 1 +.names II16101 g8853 +0 1 +.names g6448 II16104 +0 1 +.names II16104 g8856 +0 1 +.names g5398 II16107 +0 1 +.names II16107 g8859 +0 1 +.names g5404 II16110 +0 1 +.names II16110 g8860 +0 1 +.names g7936 II16114 +0 1 +.names II16114 g8862 +0 1 +.names g5473 II16117 +0 1 +.names II16117 g8863 +0 1 +.names g5400 II16120 +0 1 +.names II16120 g8866 +0 1 +.names g5406 II16123 +0 1 +.names II16123 g8867 +0 1 +.names g6103 II16128 +0 1 +.names II16128 g8870 +0 1 +.names g5408 II16131 +0 1 +.names II16131 g8871 +0 1 +.names g6099 II16134 +0 1 +.names II16134 g8872 +0 1 +.names g4955 g8873 +0 1 +.names g7053 II16138 +0 1 +.names II16138 g8874 +0 1 +.names g5409 II16141 +0 1 +.names II16141 g8877 +0 1 +.names g6101 II16144 +0 1 +.names II16144 g8878 +0 1 +.names g3878 II16147 +0 1 +.names II16147 g8879 +0 1 +.names g3900 II16150 +0 1 +.names II16150 g8882 +0 1 +.names g3306 II16153 +0 1 +.names II16153 g8885 +0 1 +.names g5438 II16156 +0 1 +.names II16156 g8888 +0 1 +.names g5403 II16159 +0 1 +.names II16159 g8891 +0 1 +.names g6031 II16163 +0 1 +.names II16163 g8893 +0 1 +.names g6713 II16166 +0 1 +.names II16166 g8894 +0 1 +.names g5405 II16169 +0 1 +.names II16169 g8897 +0 1 +.names g5413 II16172 +0 1 +.names II16172 g8898 +0 1 +.names g7936 II16176 +0 1 +.names II16176 g8900 +0 1 +.names g5512 II16179 +0 1 +.names II16179 g8901 +0 1 +.names g5407 II16182 +0 1 +.names II16182 g8904 +0 1 +.names g5415 II16185 +0 1 +.names II16185 g8905 +0 1 +.names g6118 II16190 +0 1 +.names II16190 g8908 +0 1 +.names g5417 II16193 +0 1 +.names II16193 g8909 +0 1 +.names g6116 II16196 +0 1 +.names II16196 g8910 +0 1 +.names g5114 g8911 +0 1 +.names g7303 II16200 +0 1 +.names II16200 g8912 +0 1 +.names g3878 II16203 +0 1 +.names II16203 g8915 +0 1 +.names g6448 II16206 +0 1 +.names II16206 g8918 +0 1 +.names g5438 II16209 +0 1 +.names II16209 g8921 +0 1 +.names g5411 II16212 +0 1 +.names II16212 g8924 +0 1 +.names g3462 II16215 +0 1 +.names II16215 g8925 +0 1 +.names g5473 II16218 +0 1 +.names II16218 g8928 +0 1 +.names g5412 II16221 +0 1 +.names II16221 g8931 +0 1 +.names g6042 II16225 +0 1 +.names II16225 g8933 +0 1 +.names g7015 II16228 +0 1 +.names II16228 g8934 +0 1 +.names g5414 II16231 +0 1 +.names II16231 g8937 +0 1 +.names g5420 II16234 +0 1 +.names II16234 g8938 +0 1 +.names g7936 II16238 +0 1 +.names II16238 g8940 +0 1 +.names g5556 II16241 +0 1 +.names II16241 g8941 +0 1 +.names g5416 II16244 +0 1 +.names II16244 g8944 +0 1 +.names g5422 II16247 +0 1 +.names II16247 g8945 +0 1 +.names g6134 II16252 +0 1 +.names II16252 g8948 +0 1 +.names g3900 II16255 +0 1 +.names II16255 g8949 +0 1 +.names g3306 II16258 +0 1 +.names II16258 g8952 +0 1 +.names g6448 II16261 +0 1 +.names II16261 g8955 +0 1 +.names g6713 II16264 +0 1 +.names II16264 g8958 +0 1 +.names g5473 II16267 +0 1 +.names II16267 g8961 +0 1 +.names g5418 II16270 +0 1 +.names II16270 g8964 +0 1 +.names g3618 II16273 +0 1 +.names II16273 g8965 +0 1 +.names g5512 II16276 +0 1 +.names II16276 g8968 +0 1 +.names g5419 II16279 +0 1 +.names II16279 g8971 +0 1 +.names g6046 II16283 +0 1 +.names II16283 g8973 +0 1 +.names g7265 II16286 +0 1 +.names II16286 g8974 +0 1 +.names g5421 II16289 +0 1 +.names II16289 g8977 +0 1 +.names g5426 II16292 +0 1 +.names II16292 g8978 +0 1 +.names g3306 II16296 +0 1 +.names II16296 g8980 +0 1 +.names g6486 g8983 +0 1 +.names g3462 II16300 +0 1 +.names II16300 g8984 +0 1 +.names g6713 II16303 +0 1 +.names II16303 g8987 +0 1 +.names g7015 II16306 +0 1 +.names II16306 g8990 +0 1 +.names g5512 II16309 +0 1 +.names II16309 g8993 +0 1 +.names g5424 II16312 +0 1 +.names II16312 g8996 +0 1 +.names g3774 II16315 +0 1 +.names II16315 g8997 +0 1 +.names g5556 II16318 +0 1 +.names II16318 g9000 +0 1 +.names g5425 II16321 +0 1 +.names II16321 g9003 +0 1 +.names g6052 II16325 +0 1 +.names II16325 g9005 +0 1 +.names g3900 II16328 +0 1 +.names II16328 g9006 +0 1 +.names g3462 II16332 +0 1 +.names II16332 g9010 +0 1 +.names g3618 II16335 +0 1 +.names II16335 g9013 +0 1 +.names g7015 II16338 +0 1 +.names II16338 g9016 +0 1 +.names g7265 II16341 +0 1 +.names II16341 g9019 +0 1 +.names g5556 II16344 +0 1 +.names II16344 g9022 +0 1 +.names g5427 II16347 +0 1 +.names II16347 g9025 +0 1 +.names g5679 g9027 +0 1 +.names g3618 II16354 +0 1 +.names II16354 g9035 +0 1 +.names g3774 II16357 +0 1 +.names II16357 g9038 +0 1 +.names g7265 II16360 +0 1 +.names II16360 g9041 +0 1 +.names g3900 II16363 +0 1 +.names II16363 g9044 +0 1 +.names g5731 g9050 +0 1 +.names g3774 II16372 +0 1 +.names II16372 g9058 +0 1 +.names g5789 g9067 +0 1 +.names g5848 g9084 +0 1 +.names g3366 II16432 +0 1 +.names II16432 g9128 +0 1 +.names g3522 II16438 +0 1 +.names II16438 g9134 +0 1 +.names g3678 II16444 +0 1 +.names II16444 g9140 +0 1 +.names g3834 II16450 +0 1 +.names II16450 g9146 +0 1 +.names g7936 II16453 +0 1 +.names II16453 g9149 +0 1 +.names g5893 g9150 +0 1 +.names g7936 II16457 +0 1 +.names II16457 g9159 +0 1 +.names g6170 g9160 +0 1 +.names g5852 g9161 +0 1 +.names g5438 II16462 +0 1 +.names II16462 g9170 +0 1 +.names g6000 II16465 +0 1 +.names II16465 g9173 +0 1 +.names g5932 g9174 +0 1 +.names g7936 II16469 +0 1 +.names II16469 g9183 +0 1 +.names g7901 II16472 +0 1 +.names II16472 g9184 +0 1 +.names g5803 g9187 +0 1 +.names g6448 II16476 +0 1 +.names II16476 g9196 +0 1 +.names g5438 II16479 +0 1 +.names II16479 g9199 +0 1 +.names g6000 II16482 +0 1 +.names II16482 g9202 +0 1 +.names g5899 g9203 +0 1 +.names g5473 II16486 +0 1 +.names II16486 g9212 +0 1 +.names g6000 II16489 +0 1 +.names II16489 g9215 +0 1 +.names g5966 g9216 +0 1 +.names g7936 II16493 +0 1 +.names II16493 g9225 +0 1 +.names g5434 g9226 +0 1 +.names g5587 g9227 +0 1 +.names g7667 g9228 +0 1 +.names g7901 II16499 +0 1 +.names II16499 g9229 +0 1 +.names g5752 g9232 +0 1 +.names g3306 II16504 +0 1 +.names II16504 g9242 +0 1 +.names g6448 II16507 +0 1 +.names II16507 g9245 +0 1 +.names g5859 g9248 +0 1 +.names g6713 II16511 +0 1 +.names II16511 g9257 +0 1 +.names g5473 II16514 +0 1 +.names II16514 g9260 +0 1 +.names g6000 II16517 +0 1 +.names II16517 g9263 +0 1 +.names g5938 g9264 +0 1 +.names g5512 II16521 +0 1 +.names II16521 g9273 +0 1 +.names g6000 II16524 +0 1 +.names II16524 g9276 +0 1 +.names g5995 g9277 +0 1 +.names g6197 g9286 +0 1 +.names g6638 g9287 +0 1 +.names g5363 g9288 +0 1 +.names g5379 g9289 +0 1 +.names g7901 II16532 +0 1 +.names II16532 g9290 +0 1 +.names g5703 g9293 +0 1 +.names g3306 II16538 +0 1 +.names II16538 g9303 +0 1 +.names g5438 II16541 +0 1 +.names II16541 g9306 +0 1 +.names g6054 II16544 +0 1 +.names II16544 g9309 +0 1 +.names g5811 g9310 +0 1 +.names g3462 II16549 +0 1 +.names II16549 g9320 +0 1 +.names g6713 II16552 +0 1 +.names II16552 g9323 +0 1 +.names g5906 g9326 +0 1 +.names g7015 II16556 +0 1 +.names II16556 g9335 +0 1 +.names g5512 II16559 +0 1 +.names II16559 g9338 +0 1 +.names g6000 II16562 +0 1 +.names II16562 g9341 +0 1 +.names g5972 g9342 +0 1 +.names g5556 II16566 +0 1 +.names II16566 g9351 +0 1 +.names g6000 II16569 +0 1 +.names II16569 g9354 +0 1 +.names g7639 g9355 +0 1 +.names g5665 g9356 +0 1 +.names g6448 II16578 +0 1 +.names II16578 g9368 +0 1 +.names g5438 II16581 +0 1 +.names II16581 g9371 +0 1 +.names g5761 g9374 +0 1 +.names g3462 II16587 +0 1 +.names II16587 g9384 +0 1 +.names g5473 II16590 +0 1 +.names II16590 g9387 +0 1 +.names g6059 II16593 +0 1 +.names II16593 g9390 +0 1 +.names g5867 g9391 +0 1 +.names g3618 II16598 +0 1 +.names II16598 g9401 +0 1 +.names g7015 II16601 +0 1 +.names II16601 g9404 +0 1 +.names g5945 g9407 +0 1 +.names g7265 II16605 +0 1 +.names II16605 g9416 +0 1 +.names g5556 II16608 +0 1 +.names II16608 g9419 +0 1 +.names g6000 II16611 +0 1 +.names II16611 g9422 +0 1 +.names g5428 g9423 +0 1 +.names g5469 g9424 +0 1 +.names g5346 g9425 +0 1 +.names g5543 g9426 +0 1 +.names g5645 g9427 +0 1 +.names g3306 II16624 +0 1 +.names II16624 g9443 +0 1 +.names g6448 II16627 +0 1 +.names II16627 g9446 +0 1 +.names g6057 II16630 +0 1 +.names II16630 g9449 +0 1 +.names g6486 II16633 +0 1 +.names II16633 g9450 +0 1 +.names g5717 g9453 +0 1 +.names g6713 II16641 +0 1 +.names II16641 g9465 +0 1 +.names g5473 II16644 +0 1 +.names II16644 g9468 +0 1 +.names g5820 g9471 +0 1 +.names g3618 II16650 +0 1 +.names II16650 g9481 +0 1 +.names g5512 II16653 +0 1 +.names II16653 g9484 +0 1 +.names g6066 II16656 +0 1 +.names II16656 g9487 +0 1 +.names g5914 g9488 +0 1 +.names g3774 II16661 +0 1 +.names II16661 g9498 +0 1 +.names g7265 II16664 +0 1 +.names II16664 g9501 +0 1 +.names g6149 g9504 +0 1 +.names g6227 g9505 +0 1 +.names g6444 g9506 +0 1 +.names g5953 g9507 +0 1 +.names g3306 II16677 +0 1 +.names II16677 g9524 +0 1 +.names g5508 g9527 +0 1 +.names g6643 II16681 +0 1 +.names II16681 g9528 +0 1 +.names g6486 II16684 +0 1 +.names II16684 g9531 +0 1 +.names g5683 g9569 +0 1 +.names g3462 II16694 +0 1 +.names II16694 g9585 +0 1 +.names g6713 II16697 +0 1 +.names II16697 g9588 +0 1 +.names g6064 II16700 +0 1 +.names II16700 g9591 +0 1 +.names g6751 II16703 +0 1 +.names II16703 g9592 +0 1 +.names g5775 g9595 +0 1 +.names g7015 II16711 +0 1 +.names II16711 g9607 +0 1 +.names g5512 II16714 +0 1 +.names II16714 g9610 +0 1 +.names g5876 g9613 +0 1 +.names g3774 II16720 +0 1 +.names II16720 g9623 +0 1 +.names g5556 II16723 +0 1 +.names II16723 g9626 +0 1 +.names g6085 II16726 +0 1 +.names II16726 g9629 +0 1 +.names g6062 II16741 +0 1 +.names II16741 g9640 +0 1 +.names g3338 II16744 +0 1 +.names II16744 g9641 +0 1 +.names g6643 II16747 +0 1 +.names II16747 g9644 +0 1 +.names g5982 g9649 +0 1 +.names g3462 II16759 +0 1 +.names II16759 g9666 +0 1 +.names g5552 g9669 +0 1 +.names g6945 II16763 +0 1 +.names II16763 g9670 +0 1 +.names g6751 II16766 +0 1 +.names II16766 g9673 +0 1 +.names g5735 g9711 +0 1 +.names g3618 II16776 +0 1 +.names II16776 g9727 +0 1 +.names g7015 II16779 +0 1 +.names II16779 g9730 +0 1 +.names g6083 II16782 +0 1 +.names II16782 g9733 +0 1 +.names g7053 II16785 +0 1 +.names II16785 g9734 +0 1 +.names g5834 g9737 +0 1 +.names g7265 II16793 +0 1 +.names II16793 g9749 +0 1 +.names g5556 II16796 +0 1 +.names II16796 g9752 +0 1 +.names g5431 g9755 +0 1 +.names g5504 g9756 +0 1 +.names g5601 g9757 +0 1 +.names g5618 g9758 +0 1 +.names g3338 II16811 +0 1 +.names II16811 g9767 +0 1 +.names g6486 II16814 +0 1 +.names II16814 g9770 +0 1 +.names g6081 II16832 +0 1 +.names II16832 g9786 +0 1 +.names g3494 II16835 +0 1 +.names II16835 g9787 +0 1 +.names g6945 II16838 +0 1 +.names II16838 g9790 +0 1 +.names g6019 g9795 +0 1 +.names g3618 II16850 +0 1 +.names II16850 g9812 +0 1 +.names g5598 g9815 +0 1 +.names g7195 II16854 +0 1 +.names II16854 g9816 +0 1 +.names g7053 II16857 +0 1 +.names II16857 g9819 +0 1 +.names g5793 g9857 +0 1 +.names g3774 II16867 +0 1 +.names II16867 g9873 +0 1 +.names g7265 II16870 +0 1 +.names II16870 g9876 +0 1 +.names g6102 II16873 +0 1 +.names II16873 g9879 +0 1 +.names g7303 II16876 +0 1 +.names II16876 g9880 +0 1 +.names g6310 g9884 +0 1 +.names g6905 g9885 +0 1 +.names g7149 g9886 +0 1 +.names g6643 II16897 +0 1 +.names II16897 g9895 +0 1 +.names g6486 II16900 +0 1 +.names II16900 g9898 +0 1 +.names g3494 II16915 +0 1 +.names II16915 g9913 +0 1 +.names g6751 II16918 +0 1 +.names II16918 g9916 +0 1 +.names g6100 II16936 +0 1 +.names II16936 g9932 +0 1 +.names g3650 II16939 +0 1 +.names II16939 g9933 +0 1 +.names g7195 II16942 +0 1 +.names II16942 g9936 +0 1 +.names g6035 g9941 +0 1 +.names g3774 II16954 +0 1 +.names II16954 g9958 +0 1 +.names g5615 g9961 +0 1 +.names g7391 II16958 +0 1 +.names II16958 g9962 +0 1 +.names g7303 II16961 +0 1 +.names II16961 g9965 +0 1 +.names g3900 II16972 +0 1 +.names II16972 g10004 +0 1 +.names g5292 g10015 +0 1 +.names g7936 II16984 +0 1 +.names II16984 g10016 +0 1 +.names g6079 II16987 +0 1 +.names II16987 g10017 +0 1 +.names g3338 II16990 +0 1 +.names II16990 g10018 +0 1 +.names g6643 II16993 +0 1 +.names II16993 g10021 +0 1 +.names g6945 II17009 +0 1 +.names II17009 g10049 +0 1 +.names g6751 II17012 +0 1 +.names II17012 g10052 +0 1 +.names g3650 II17027 +0 1 +.names II17027 g10067 +0 1 +.names g7053 II17030 +0 1 +.names II17030 g10070 +0 1 +.names g6117 II17048 +0 1 +.names II17048 g10086 +0 1 +.names g3806 II17051 +0 1 +.names II17051 g10087 +0 1 +.names g7391 II17054 +0 1 +.names II17054 g10090 +0 1 +.names g3900 II17066 +0 1 +.names II17066 g10096 +0 1 +.names g7700 g10099 +0 1 +.names g3151 g3142 g3147 g7528 +000 1 +.names g7528 II17070 +0 1 +.names II17070 g10100 +0 1 +.names g3338 II17081 +0 1 +.names II17081 g10109 +0 1 +.names g5326 g10124 +0 1 +.names g7936 II17097 +0 1 +.names II17097 g10125 +0 1 +.names g6098 II17100 +0 1 +.names II17100 g10126 +0 1 +.names g3494 II17103 +0 1 +.names II17103 g10127 +0 1 +.names g6945 II17106 +0 1 +.names II17106 g10130 +0 1 +.names g7195 II17122 +0 1 +.names II17122 g10158 +0 1 +.names g7053 II17125 +0 1 +.names II17125 g10161 +0 1 +.names g3806 II17140 +0 1 +.names II17140 g10176 +0 1 +.names g7303 II17143 +0 1 +.names II17143 g10179 +0 1 +.names g3900 II17159 +0 1 +.names II17159 g10189 +0 1 +.names g3494 II17184 +0 1 +.names II17184 g10214 +0 1 +.names g5349 g10229 +0 1 +.names g7936 II17200 +0 1 +.names II17200 g10230 +0 1 +.names g6115 II17203 +0 1 +.names II17203 g10231 +0 1 +.names g3650 II17206 +0 1 +.names II17206 g10232 +0 1 +.names g7195 II17209 +0 1 +.names II17209 g10235 +0 1 +.names g7391 II17225 +0 1 +.names II17225 g10263 +0 1 +.names g7303 II17228 +0 1 +.names II17228 g10266 +0 1 +.names g3900 II17235 +0 1 +.names II17235 g10273 +0 1 +.names g3900 II17238 +0 1 +.names II17238 g10276 +0 1 +.names g3650 II17278 +0 1 +.names II17278 g10316 +0 1 +.names g5366 g10331 +0 1 +.names g7936 II17294 +0 1 +.names II17294 g10332 +0 1 +.names g6130 II17297 +0 1 +.names II17297 g10333 +0 1 +.names g3806 II17300 +0 1 +.names II17300 g10334 +0 1 +.names g7391 II17303 +0 1 +.names II17303 g10337 +0 1 +.names g3900 II17311 +0 1 +.names II17311 g10357 +0 1 +.names g3806 II17363 +0 1 +.names II17363 g10409 +0 1 +.names g3900 II17370 +0 1 +.names II17370 g10416 +0 1 +.names g3900 II17373 +0 1 +.names II17373 g10419 +0 1 +.names g7910 g10424 +0 1 +.names g7826 g10481 +0 1 +.names g3900 II17433 +0 1 +.names II17433 g10482 +0 1 +.names g7957 g10486 +0 1 +.names g7962 g10500 +0 1 +.names g3900 II17483 +0 1 +.names II17483 g10542 +0 1 +.names g3900 II17486 +0 1 +.names II17486 g10545 +0 1 +.names g7999 g10549 +0 1 +.names g8008 g10560 +0 1 +.names g8013 g10574 +0 1 +.names g3900 II17527 +0 1 +.names II17527 g10601 +0 1 +.names g8074 g10606 +0 1 +.names g8083 g10617 +0 1 +.names g8088 g10631 +0 1 +.names g3900 II17557 +0 1 +.names II17557 g10646 +0 1 +.names g8159 g10653 +0 1 +.names g8168 g10664 +0 1 +.names g8245 g10683 +0 1 +.names g4326 g10694 +0 1 +.names g4495 g10714 +0 1 +.names g6173 g10730 +0 1 +.names g4671 g10735 +0 1 +.names g6205 g10749 +0 1 +.names g4848 g10754 +0 1 +.names g6048 g10765 +0 1 +.names g6676 g10766 +0 1 +.names g6294 g10767 +0 1 +.names g6978 g10772 +0 1 +.names g6431 g10773 +0 1 +.names g2984 g2985 g7575 +00 1 +.names g7575 II17627 +0 1 +.names II17627 g10779 +0 1 +.names g7228 g10783 +0 1 +.names g6183 II17632 +0 1 +.names II17632 g10787 +0 1 +.names g7424 g10788 +0 1 +.names g6204 II17637 +0 1 +.names II17637 g10792 +0 1 +.names g6215 II17641 +0 1 +.names II17641 g10796 +0 1 +.names g6288 II17645 +0 1 +.names II17645 g10800 +0 1 +.names g6293 II17649 +0 1 +.names II17649 g10804 +0 1 +.names g6304 II17653 +0 1 +.names II17653 g10808 +0 1 +.names g5701 g10809 +0 1 +.names g6367 II17658 +0 1 +.names II17658 g10813 +0 1 +.names g6425 II17662 +0 1 +.names II17662 g10817 +0 1 +.names g6430 II17666 +0 1 +.names II17666 g10821 +0 1 +.names g6441 II17670 +0 1 +.names II17670 g10825 +0 1 +.names g8107 II17673 +0 1 +.names II17673 g10826 +0 1 +.names g5749 g10829 +0 1 +.names g6517 II17677 +0 1 +.names II17677 g10830 +0 1 +.names g6572 II17681 +0 1 +.names II17681 g10834 +0 1 +.names g6630 II17685 +0 1 +.names II17685 g10838 +0 1 +.names g6635 II17689 +0 1 +.names II17689 g10842 +0 1 +.names g8107 II17692 +0 1 +.names II17692 g10843 +0 1 +.names g5799 g10846 +0 1 +.names g5800 g10847 +0 1 +.names g5801 g10848 +0 1 +.names g6711 II17698 +0 1 +.names II17698 g10849 +0 1 +.names g6781 II17701 +0 1 +.names II17701 g10850 +0 1 +.names g6836 II17705 +0 1 +.names II17705 g10854 +0 1 +.names g6894 II17709 +0 1 +.names II17709 g10858 +0 1 +.names g8031 II17712 +0 1 +.names II17712 g10859 +0 1 +.names g8107 II17715 +0 1 +.names II17715 g10862 +0 1 +.names g6131 g10865 +0 1 +.names g5849 g10866 +0 1 +.names g5850 g10867 +0 1 +.names g6641 II17721 +0 1 +.names II17721 g10868 +0 1 +.names g6942 II17724 +0 1 +.names II17724 g10869 +0 1 +.names g7013 II17727 +0 1 +.names II17727 g10870 +0 1 +.names g7083 II17730 +0 1 +.names II17730 g10871 +0 1 +.names g7138 II17734 +0 1 +.names II17734 g10875 +0 1 +.names g6000 II17737 +0 1 +.names II17737 g10876 +0 1 +.names g8031 II17740 +0 1 +.names II17740 g10877 +0 1 +.names g8107 II17743 +0 1 +.names II17743 g10880 +0 1 +.names g8107 II17746 +0 1 +.names II17746 g10883 +0 1 +.names g5889 g10886 +0 1 +.names g7157 II17750 +0 1 +.names II17750 g10887 +0 1 +.names g6943 II17753 +0 1 +.names II17753 g10888 +0 1 +.names g7192 II17756 +0 1 +.names II17756 g10889 +0 1 +.names g7263 II17759 +0 1 +.names II17759 g10890 +0 1 +.names g7333 II17762 +0 1 +.names II17762 g10891 +0 1 +.names g7976 II17765 +0 1 +.names II17765 g10892 +0 1 +.names g8031 II17768 +0 1 +.names II17768 g10895 +0 1 +.names g8107 II17771 +0 1 +.names II17771 g10898 +0 1 +.names g8107 II17774 +0 1 +.names II17774 g10901 +0 1 +.names g5922 g10904 +0 1 +.names g5923 g10905 +0 1 +.names g5924 g10906 +0 1 +.names g7348 II17780 +0 1 +.names II17780 g10907 +0 1 +.names g7353 II17783 +0 1 +.names II17783 g10908 +0 1 +.names g7193 II17786 +0 1 +.names II17786 g10909 +0 1 +.names g7388 II17789 +0 1 +.names II17789 g10910 +0 1 +.names g7459 II17792 +0 1 +.names II17792 g10911 +0 1 +.names g7976 II17795 +0 1 +.names II17795 g10912 +0 1 +.names g8031 II17798 +0 1 +.names II17798 g10915 +0 1 +.names g8107 II17801 +0 1 +.names II17801 g10918 +0 1 +.names g8031 II17804 +0 1 +.names II17804 g10921 +0 1 +.names g8107 II17807 +0 1 +.names II17807 g10924 +0 1 +.names g6153 g10927 +0 1 +.names g5951 g10928 +0 1 +.names g5952 g10929 +0 1 +.names g5707 II17813 +0 1 +.names II17813 g10930 +0 1 +.names g7346 II17816 +0 1 +.names II17816 g10931 +0 1 +.names g6448 II17819 +0 1 +.names II17819 g10932 +0 1 +.names g7478 II17822 +0 1 +.names II17822 g10933 +0 1 +.names g7483 II17825 +0 1 +.names II17825 g10934 +0 1 +.names g7389 II17828 +0 1 +.names II17828 g10935 +0 1 +.names g7518 II17831 +0 1 +.names II17831 g10936 +0 1 +.names g7976 II17834 +0 1 +.names II17834 g10937 +0 1 +.names g8031 II17837 +0 1 +.names II17837 g10940 +0 1 +.names g8107 II17840 +0 1 +.names II17840 g10943 +0 1 +.names g8031 II17843 +0 1 +.names II17843 g10946 +0 1 +.names g8107 II17846 +0 1 +.names II17846 g10949 +0 1 +.names g8103 II17849 +0 1 +.names II17849 g10952 +0 1 +.names g5978 g10961 +0 1 +.names g5979 g10962 +0 1 +.names g6232 II17854 +0 1 +.names II17854 g10963 +0 1 +.names g6448 II17857 +0 1 +.names II17857 g10966 +0 1 +.names g5765 II17860 +0 1 +.names II17860 g10967 +0 1 +.names g7476 II17863 +0 1 +.names II17863 g10968 +0 1 +.names g6713 II17866 +0 1 +.names II17866 g10969 +0 1 +.names g7534 II17869 +0 1 +.names II17869 g10972 +0 1 +.names g7539 II17872 +0 1 +.names II17872 g10973 +0 1 +.names g7976 II17875 +0 1 +.names II17875 g10974 +0 1 +.names g8031 II17878 +0 1 +.names II17878 g10977 +0 1 +.names g7976 II17881 +0 1 +.names II17881 g10980 +0 1 +.names g8031 II17884 +0 1 +.names II17884 g10983 +0 1 +.names g6014 g10986 +0 1 +.names g6015 g10987 +0 1 +.names g6314 II17889 +0 1 +.names II17889 g10988 +0 1 +.names g6232 II17892 +0 1 +.names II17892 g10991 +0 1 +.names g6448 II17895 +0 1 +.names II17895 g10994 +0 1 +.names g6643 II17898 +0 1 +.names II17898 g10995 +0 1 +.names g6369 II17901 +0 1 +.names II17901 g10996 +0 1 +.names g6713 II17904 +0 1 +.names II17904 g10999 +0 1 +.names g5824 II17907 +0 1 +.names II17907 g11002 +0 1 +.names g7532 II17910 +0 1 +.names II17910 g11003 +0 1 +.names g7015 II17913 +0 1 +.names II17913 g11004 +0 1 +.names g7560 II17916 +0 1 +.names II17916 g11007 +0 1 +.names g7976 II17919 +0 1 +.names II17919 g11008 +0 1 +.names g8031 II17922 +0 1 +.names II17922 g11011 +0 1 +.names g7976 II17925 +0 1 +.names II17925 g11014 +0 1 +.names g8031 II17928 +0 1 +.names II17928 g11017 +0 1 +.names g6029 g11020 +0 1 +.names g6030 g11021 +0 1 +.names g3254 II17933 +0 1 +.names II17933 g11022 +0 1 +.names g6314 II17936 +0 1 +.names II17936 g11025 +0 1 +.names g6232 II17939 +0 1 +.names II17939 g11028 +0 1 +.names g5548 II17942 +0 1 +.names II17942 g11031 +0 1 +.names g5668 II17945 +0 1 +.names II17945 g11032 +0 1 +.names g6643 II17948 +0 1 +.names II17948 g11035 +0 1 +.names g6519 II17951 +0 1 +.names II17951 g11036 +0 1 +.names g6369 II17954 +0 1 +.names II17954 g11039 +0 1 +.names g6713 II17957 +0 1 +.names II17957 g11042 +0 1 +.names g6945 II17960 +0 1 +.names II17960 g11045 +0 1 +.names g6574 II17963 +0 1 +.names II17963 g11048 +0 1 +.names g7015 II17966 +0 1 +.names II17966 g11051 +0 1 +.names g5880 II17969 +0 1 +.names II17969 g11054 +0 1 +.names g7558 II17972 +0 1 +.names II17972 g11055 +0 1 +.names g7265 II17975 +0 1 +.names II17975 g11056 +0 1 +.names g2992 g2991 g7795 +00 1 +.names g7795 II17978 +0 1 +.names II17978 g11059 +0 1 +.names g7976 II17981 +0 1 +.names II17981 g11063 +0 1 +.names g7976 II17984 +0 1 +.names II17984 g11066 +0 1 +.names g8257 g11069 +0 1 +.names g6041 g11078 +0 1 +.names g3254 II17989 +0 1 +.names II17989 g11079 +0 1 +.names g6314 II17992 +0 1 +.names II17992 g11082 +0 1 +.names g6232 II17995 +0 1 +.names II17995 g11085 +0 1 +.names g5668 II17998 +0 1 +.names II17998 g11088 +0 1 +.names g6643 II18001 +0 1 +.names II18001 g11091 +0 1 +.names g3410 II18004 +0 1 +.names II18004 g11092 +0 1 +.names g6519 II18007 +0 1 +.names II18007 g11095 +0 1 +.names g6369 II18010 +0 1 +.names II18010 g11098 +0 1 +.names g5594 II18013 +0 1 +.names II18013 g11101 +0 1 +.names g5720 II18016 +0 1 +.names II18016 g11102 +0 1 +.names g6945 II18019 +0 1 +.names II18019 g11105 +0 1 +.names g6783 II18022 +0 1 +.names II18022 g11108 +0 1 +.names g6574 II18025 +0 1 +.names II18025 g11111 +0 1 +.names g7015 II18028 +0 1 +.names II18028 g11114 +0 1 +.names g7195 II18031 +0 1 +.names II18031 g11117 +0 1 +.names g6838 II18034 +0 1 +.names II18034 g11120 +0 1 +.names g7265 II18037 +0 1 +.names II18037 g11123 +0 1 +.names g7976 II18040 +0 1 +.names II18040 g11126 +0 1 +.names g7976 II18043 +0 1 +.names II18043 g11129 +0 1 +.names g3254 II18046 +0 1 +.names II18046 g11132 +0 1 +.names g6314 II18049 +0 1 +.names II18049 g11135 +0 1 +.names g6232 II18052 +0 1 +.names II18052 g11138 +0 1 +.names g5668 II18055 +0 1 +.names II18055 g11141 +0 1 +.names g6643 II18058 +0 1 +.names II18058 g11144 +0 1 +.names g3410 II18061 +0 1 +.names II18061 g11145 +0 1 +.names g6519 II18064 +0 1 +.names II18064 g11148 +0 1 +.names g6369 II18067 +0 1 +.names II18067 g11151 +0 1 +.names g5720 II18070 +0 1 +.names II18070 g11154 +0 1 +.names g6945 II18073 +0 1 +.names II18073 g11157 +0 1 +.names g3566 II18076 +0 1 +.names II18076 g11160 +0 1 +.names g6783 II18079 +0 1 +.names II18079 g11163 +0 1 +.names g6574 II18082 +0 1 +.names II18082 g11166 +0 1 +.names g5611 II18085 +0 1 +.names II18085 g11169 +0 1 +.names g5778 II18088 +0 1 +.names II18088 g11170 +0 1 +.names g7195 II18091 +0 1 +.names II18091 g11173 +0 1 +.names g7085 II18094 +0 1 +.names II18094 g11176 +0 1 +.names g6838 II18097 +0 1 +.names II18097 g11179 +0 1 +.names g7265 II18100 +0 1 +.names II18100 g11182 +0 1 +.names g7391 II18103 +0 1 +.names II18103 g11185 +0 1 +.names g3999 g11190 +0 1 +.names g3254 II18121 +0 1 +.names II18121 g11199 +0 1 +.names g6314 II18124 +0 1 +.names II18124 g11202 +0 1 +.names g6232 II18127 +0 1 +.names II18127 g11205 +0 1 +.names g5547 II18130 +0 1 +.names II18130 g11208 +0 1 +.names g6448 II18133 +0 1 +.names II18133 g11209 +0 1 +.names g5668 II18136 +0 1 +.names II18136 g11210 +0 1 +.names g6643 II18139 +0 1 +.names II18139 g11213 +0 1 +.names g3410 II18142 +0 1 +.names II18142 g11216 +0 1 +.names g6519 II18145 +0 1 +.names II18145 g11219 +0 1 +.names g6369 II18148 +0 1 +.names II18148 g11222 +0 1 +.names g5720 II18151 +0 1 +.names II18151 g11225 +0 1 +.names g6945 II18154 +0 1 +.names II18154 g11228 +0 1 +.names g3566 II18157 +0 1 +.names II18157 g11231 +0 1 +.names g6783 II18160 +0 1 +.names II18160 g11234 +0 1 +.names g6574 II18163 +0 1 +.names II18163 g11237 +0 1 +.names g5778 II18166 +0 1 +.names II18166 g11240 +0 1 +.names g7195 II18169 +0 1 +.names II18169 g11243 +0 1 +.names g3722 II18172 +0 1 +.names II18172 g11246 +0 1 +.names g7085 II18175 +0 1 +.names II18175 g11249 +0 1 +.names g6838 II18178 +0 1 +.names II18178 g11252 +0 1 +.names g5636 II18181 +0 1 +.names II18181 g11255 +0 1 +.names g5837 II18184 +0 1 +.names II18184 g11256 +0 1 +.names g7391 II18187 +0 1 +.names II18187 g11259 +0 1 +.names g6232 II18211 +0 1 +.names II18211 g11265 +0 1 +.names g3254 II18214 +0 1 +.names II18214 g11268 +0 1 +.names g6314 II18217 +0 1 +.names II18217 g11271 +0 1 +.names g6232 II18220 +0 1 +.names II18220 g11274 +0 1 +.names g6448 II18223 +0 1 +.names II18223 g11277 +0 1 +.names g5668 II18226 +0 1 +.names II18226 g11278 +0 1 +.names g3410 II18229 +0 1 +.names II18229 g11281 +0 1 +.names g6519 II18232 +0 1 +.names II18232 g11284 +0 1 +.names g6369 II18235 +0 1 +.names II18235 g11287 +0 1 +.names g5593 II18238 +0 1 +.names II18238 g11290 +0 1 +.names g6713 II18241 +0 1 +.names II18241 g11291 +0 1 +.names g5720 II18244 +0 1 +.names II18244 g11294 +0 1 +.names g6945 II18247 +0 1 +.names II18247 g11297 +0 1 +.names g3566 II18250 +0 1 +.names II18250 g11300 +0 1 +.names g6783 II18253 +0 1 +.names II18253 g11303 +0 1 +.names g6574 II18256 +0 1 +.names II18256 g11306 +0 1 +.names g5778 II18259 +0 1 +.names II18259 g11309 +0 1 +.names g7195 II18262 +0 1 +.names II18262 g11312 +0 1 +.names g3722 II18265 +0 1 +.names II18265 g11315 +0 1 +.names g7085 II18268 +0 1 +.names II18268 g11318 +0 1 +.names g6838 II18271 +0 1 +.names II18271 g11321 +0 1 +.names g5837 II18274 +0 1 +.names II18274 g11324 +0 1 +.names g7391 II18277 +0 1 +.names II18277 g11327 +0 1 +.names g4094 g11332 +0 1 +.names g6314 II18295 +0 1 +.names II18295 g11341 +0 1 +.names g6232 II18298 +0 1 +.names II18298 g11344 +0 1 +.names g3254 II18302 +0 1 +.names II18302 g11348 +0 1 +.names g6314 II18305 +0 1 +.names II18305 g11351 +0 1 +.names g6448 II18308 +0 1 +.names II18308 g11354 +0 1 +.names g5668 II18311 +0 1 +.names II18311 g11355 +0 1 +.names g6369 II18314 +0 1 +.names II18314 g11358 +0 1 +.names g3410 II18317 +0 1 +.names II18317 g11361 +0 1 +.names g6519 II18320 +0 1 +.names II18320 g11364 +0 1 +.names g6369 II18323 +0 1 +.names II18323 g11367 +0 1 +.names g6713 II18326 +0 1 +.names II18326 g11370 +0 1 +.names g5720 II18329 +0 1 +.names II18329 g11373 +0 1 +.names g3566 II18332 +0 1 +.names II18332 g11376 +0 1 +.names g6783 II18335 +0 1 +.names II18335 g11379 +0 1 +.names g6574 II18338 +0 1 +.names II18338 g11382 +0 1 +.names g5610 II18341 +0 1 +.names II18341 g11385 +0 1 +.names g7015 II18344 +0 1 +.names II18344 g11386 +0 1 +.names g5778 II18347 +0 1 +.names II18347 g11389 +0 1 +.names g7195 II18350 +0 1 +.names II18350 g11392 +0 1 +.names g3722 II18353 +0 1 +.names II18353 g11395 +0 1 +.names g7085 II18356 +0 1 +.names II18356 g11398 +0 1 +.names g6838 II18359 +0 1 +.names II18359 g11401 +0 1 +.names g5837 II18362 +0 1 +.names II18362 g11404 +0 1 +.names g7391 II18365 +0 1 +.names II18365 g11407 +0 1 +.names g3254 II18375 +0 1 +.names II18375 g11411 +0 1 +.names g6314 II18378 +0 1 +.names II18378 g11414 +0 1 +.names g6232 II18381 +0 1 +.names II18381 g11417 +0 1 +.names g3254 II18386 +0 1 +.names II18386 g11422 +0 1 +.names g6519 II18389 +0 1 +.names II18389 g11425 +0 1 +.names g6369 II18392 +0 1 +.names II18392 g11428 +0 1 +.names g3410 II18396 +0 1 +.names II18396 g11432 +0 1 +.names g6519 II18399 +0 1 +.names II18399 g11435 +0 1 +.names g6713 II18402 +0 1 +.names II18402 g11438 +0 1 +.names g5720 II18405 +0 1 +.names II18405 g11441 +0 1 +.names g6574 II18408 +0 1 +.names II18408 g11444 +0 1 +.names g3566 II18411 +0 1 +.names II18411 g11447 +0 1 +.names g6783 II18414 +0 1 +.names II18414 g11450 +0 1 +.names g6574 II18417 +0 1 +.names II18417 g11453 +0 1 +.names g7015 II18420 +0 1 +.names II18420 g11456 +0 1 +.names g5778 II18423 +0 1 +.names II18423 g11459 +0 1 +.names g3722 II18426 +0 1 +.names II18426 g11462 +0 1 +.names g7085 II18429 +0 1 +.names II18429 g11465 +0 1 +.names g6838 II18432 +0 1 +.names II18432 g11468 +0 1 +.names g5635 II18435 +0 1 +.names II18435 g11471 +0 1 +.names g7265 II18438 +0 1 +.names II18438 g11472 +0 1 +.names g5837 II18441 +0 1 +.names II18441 g11475 +0 1 +.names g7391 II18444 +0 1 +.names II18444 g11478 +0 1 +.names g4204 g11481 +0 1 +.names g8276 g11490 +0 1 +.names g10868 II18449 +0 1 +.names g10930 II18452 +0 1 +.names g11031 II18455 +0 1 +.names g11208 II18458 +0 1 +.names g10931 II18461 +0 1 +.names g8620 II18464 +0 1 +.names g8769 II18467 +0 1 +.names g8808 II18470 +0 1 +.names g8839 II18473 +0 1 +.names g8791 II18476 +0 1 +.names g8820 II18479 +0 1 +.names g8859 II18482 +0 1 +.names g8809 II18485 +0 1 +.names g8840 II18488 +0 1 +.names g8891 II18491 +0 1 +.names g8821 II18494 +0 1 +.names g8860 II18497 +0 1 +.names g8924 II18500 +0 1 +.names g8658 II18503 +0 1 +.names g8699 II18506 +0 1 +.names g8770 II18509 +0 1 +.names g9309 II18512 +0 1 +.names g8843 II18515 +0 1 +.names g8893 II18518 +0 1 +.names g9449 II18521 +0 1 +.names g9640 II18524 +0 1 +.names g10017 II18527 +0 1 +.names g10888 II18530 +0 1 +.names g10967 II18533 +0 1 +.names g11101 II18536 +0 1 +.names g11290 II18539 +0 1 +.names g10968 II18542 +0 1 +.names g8630 II18545 +0 1 +.names g8792 II18548 +0 1 +.names g8824 II18551 +0 1 +.names g8866 II18554 +0 1 +.names g8810 II18557 +0 1 +.names g8844 II18560 +0 1 +.names g8897 II18563 +0 1 +.names g8825 II18566 +0 1 +.names g8867 II18569 +0 1 +.names g8931 II18572 +0 1 +.names g8845 II18575 +0 1 +.names g8898 II18578 +0 1 +.names g8964 II18581 +0 1 +.names g8677 II18584 +0 1 +.names g8718 II18587 +0 1 +.names g8793 II18590 +0 1 +.names g9390 II18593 +0 1 +.names g8870 II18596 +0 1 +.names g8933 II18599 +0 1 +.names g9591 II18602 +0 1 +.names g9786 II18605 +0 1 +.names g10126 II18608 +0 1 +.names g10909 II18611 +0 1 +.names g11002 II18614 +0 1 +.names g11169 II18617 +0 1 +.names g11385 II18620 +0 1 +.names g11003 II18623 +0 1 +.names g8649 II18626 +0 1 +.names g8811 II18629 +0 1 +.names g8850 II18632 +0 1 +.names g8904 II18635 +0 1 +.names g8826 II18638 +0 1 +.names g8871 II18641 +0 1 +.names g8937 II18644 +0 1 +.names g8851 II18647 +0 1 +.names g8905 II18650 +0 1 +.names g8971 II18653 +0 1 +.names g8872 II18656 +0 1 +.names g8938 II18659 +0 1 +.names g8996 II18662 +0 1 +.names g8689 II18665 +0 1 +.names g8756 II18668 +0 1 +.names g8812 II18671 +0 1 +.names g9487 II18674 +0 1 +.names g8908 II18677 +0 1 +.names g8973 II18680 +0 1 +.names g9733 II18683 +0 1 +.names g9932 II18686 +0 1 +.names g10231 II18689 +0 1 +.names g10935 II18692 +0 1 +.names g11054 II18695 +0 1 +.names g11255 II18698 +0 1 +.names g11471 II18701 +0 1 +.names g11055 II18704 +0 1 +.names g8665 II18707 +0 1 +.names g8827 II18710 +0 1 +.names g8877 II18713 +0 1 +.names g8944 II18716 +0 1 +.names g8852 II18719 +0 1 +.names g8909 II18722 +0 1 +.names g8977 II18725 +0 1 +.names g8878 II18728 +0 1 +.names g8945 II18731 +0 1 +.names g9003 II18734 +0 1 +.names g8910 II18737 +0 1 +.names g8978 II18740 +0 1 +.names g9025 II18743 +0 1 +.names g8707 II18746 +0 1 +.names g8779 II18749 +0 1 +.names g8828 II18752 +0 1 +.names g9629 II18755 +0 1 +.names g8948 II18758 +0 1 +.names g9005 II18761 +0 1 +.names g9879 II18764 +0 1 +.names g10086 II18767 +0 1 +.names g10333 II18770 +0 1 +.names g10830 II18773 +0 1 +.names II18773 g11599 +0 1 +.names g9050 II18777 +0 1 +.names II18777 g11603 +0 1 +.names g10870 II18780 +0 1 +.names II18780 g11606 +0 1 +.names g9067 II18784 +0 1 +.names II18784 g11608 +0 1 +.names g10910 II18787 +0 1 +.names II18787 g11611 +0 1 +.names g9084 II18791 +0 1 +.names II18791 g11613 +0 1 +.names g10973 II18794 +0 1 +.names II18794 g11616 +0 1 +.names g10601 g11620 +0 1 +.names g10961 g11623 +0 1 +.names g10813 II18810 +0 1 +.names II18810 g11628 +0 1 +.names g10850 II18813 +0 1 +.names II18813 g11629 +0 1 +.names g9067 II18817 +0 1 +.names II18817 g11633 +0 1 +.names g10890 II18820 +0 1 +.names II18820 g11636 +0 1 +.names g9084 II18824 +0 1 +.names II18824 g11638 +0 1 +.names g10936 II18827 +0 1 +.names II18827 g11641 +0 1 +.names g10646 g11642 +0 1 +.names g10834 II18835 +0 1 +.names II18835 g11651 +0 1 +.names g10871 II18838 +0 1 +.names II18838 g11652 +0 1 +.names g9084 II18842 +0 1 +.names II18842 g11656 +0 1 +.names g10911 II18845 +0 1 +.names II18845 g11659 +0 1 +.names g10854 II18854 +0 1 +.names II18854 g11670 +0 1 +.names g10891 II18857 +0 1 +.names II18857 g11671 +0 1 +.names g10875 II18866 +0 1 +.names II18866 g11682 +0 1 +.names g10928 g11706 +0 1 +.names g10826 g11732 +0 1 +.names g10843 g11734 +0 1 +.names g10859 g11735 +0 1 +.names g10862 g11736 +0 1 +.names g10809 g11737 +0 1 +.names g10877 g11740 +0 1 +.names g10880 g11741 +0 1 +.names g10883 g11742 +0 1 +.names g8530 g11743 +0 1 +.names g10892 g11745 +0 1 +.names g10895 g11746 +0 1 +.names g10898 g11747 +0 1 +.names g10901 g11748 +0 1 +.names g7595 g7600 II17599 g10711 +111 1 +.names g10711 II18929 +0 1 +.names II18929 g11749 +0 1 +.names g8514 g11758 +0 1 +.names g10912 g11761 +0 1 +.names g10915 g11762 +0 1 +.names g10918 g11763 +0 1 +.names g10921 g11764 +0 1 +.names g10924 g11765 +0 1 +.names g10886 g11766 +0 1 +.names g9149 II18943 +0 1 +.names II18943 g11769 +0 1 +.names g10932 g11770 +0 1 +.names g10937 g11774 +0 1 +.names g10940 g11775 +0 1 +.names g10943 g11776 +0 1 +.names g10946 g11777 +0 1 +.names g10949 g11778 +0 1 +.names g10906 g11779 +0 1 +.names g10963 g11782 +0 1 +.names g10966 g11783 +0 1 +.names g9159 II18962 +0 1 +.names II18962 g11786 +0 1 +.names g10969 g11787 +0 1 +.names g8726 II18969 +0 1 +.names II18969 g11791 +0 1 +.names g10974 g11794 +0 1 +.names g10977 g11795 +0 1 +.names g10980 g11796 +0 1 +.names g10983 g11797 +0 1 +.names g10867 g11798 +0 1 +.names g10988 g11801 +0 1 +.names g10991 g11802 +0 1 +.names g10994 g11803 +0 1 +.names g10995 g11804 +0 1 +.names g10996 g11808 +0 1 +.names g10999 g11809 +0 1 +.names g9183 II18990 +0 1 +.names II18990 g11812 +0 1 +.names g11004 g11813 +0 1 +.names g11008 g11817 +0 1 +.names g11011 g11818 +0 1 +.names g11014 g11819 +0 1 +.names g11017 g11820 +0 1 +.names g10848 g11821 +0 1 +.names g11022 g11824 +0 1 +.names g11025 g11825 +0 1 +.names g11028 g11826 +0 1 +.names g11032 g11827 +0 1 +.names g11035 g11829 +0 1 +.names g11036 g11834 +0 1 +.names g11039 g11835 +0 1 +.names g11042 g11836 +0 1 +.names g11045 g11837 +0 1 +.names g11048 g11841 +0 1 +.names g11051 g11842 +0 1 +.names g9225 II19025 +0 1 +.names II19025 g11845 +0 1 +.names g11056 g11846 +0 1 +.names g8726 II19030 +0 1 +.names II19030 g11848 +0 1 +.names g11063 g11852 +0 1 +.names g11066 g11853 +0 1 +.names g11078 g11854 +0 1 +.names g11079 g11856 +0 1 +.names g11082 g11857 +0 1 +.names g11085 g11858 +0 1 +.names g11088 g11859 +0 1 +.names g11091 g11862 +0 1 +.names g11092 g11866 +0 1 +.names g11095 g11867 +0 1 +.names g11098 g11868 +0 1 +.names g11102 g11869 +0 1 +.names g11105 g11871 +0 1 +.names g11108 g11876 +0 1 +.names g11111 g11877 +0 1 +.names g11114 g11878 +0 1 +.names g11117 g11879 +0 1 +.names g11120 g11883 +0 1 +.names g11123 g11884 +0 1 +.names g11126 g11886 +0 1 +.names g11129 g11887 +0 1 +.names g11021 g11888 +0 1 +.names g11132 g11891 +0 1 +.names g11135 g11892 +0 1 +.names g11138 g11893 +0 1 +.names g11141 g11894 +0 1 +.names g11144 g11895 +0 1 +.names g11145 g11898 +0 1 +.names g11148 g11899 +0 1 +.names g11151 g11900 +0 1 +.names g11154 g11901 +0 1 +.names g11157 g11904 +0 1 +.names g11160 g11908 +0 1 +.names g11163 g11909 +0 1 +.names g11166 g11910 +0 1 +.names g11170 g11911 +0 1 +.names g11173 g11913 +0 1 +.names g11176 g11918 +0 1 +.names g11179 g11919 +0 1 +.names g11182 g11920 +0 1 +.names g11185 g11921 +0 1 +.names g8726 II19105 +0 1 +.names II19105 g11923 +0 1 +.names g10987 g11927 +0 1 +.names g11199 g11929 +0 1 +.names g11202 g11930 +0 1 +.names g11205 g11931 +0 1 +.names g11209 g11932 +0 1 +.names g11210 g11933 +0 1 +.names g11213 g11936 +0 1 +.names g9202 II19119 +0 1 +.names II19119 g11937 +0 1 +.names g11216 g11941 +0 1 +.names g11219 g11942 +0 1 +.names g11222 g11943 +0 1 +.names g11225 g11944 +0 1 +.names g11228 g11945 +0 1 +.names g11231 g11948 +0 1 +.names g11234 g11949 +0 1 +.names g11237 g11950 +0 1 +.names g11240 g11951 +0 1 +.names g11243 g11954 +0 1 +.names g11246 g11958 +0 1 +.names g11249 g11959 +0 1 +.names g11252 g11960 +0 1 +.names g11256 g11961 +0 1 +.names g11259 g11963 +0 1 +.names g11265 g11968 +0 1 +.names g11268 g11969 +0 1 +.names g11271 g11970 +0 1 +.names g11274 g11971 +0 1 +.names g11277 g11972 +0 1 +.names g11278 g11973 +0 1 +.names g10549 II19160 +0 1 +.names II19160 g11976 +0 1 +.names g11281 g11982 +0 1 +.names g11284 g11983 +0 1 +.names g11287 g11984 +0 1 +.names g11291 g11985 +0 1 +.names g11294 g11986 +0 1 +.names g11297 g11989 +0 1 +.names g9263 II19174 +0 1 +.names II19174 g11990 +0 1 +.names g11300 g11994 +0 1 +.names g11303 g11995 +0 1 +.names g11306 g11996 +0 1 +.names g11309 g11997 +0 1 +.names g11312 g11998 +0 1 +.names g11315 g12001 +0 1 +.names g11318 g12002 +0 1 +.names g11321 g12003 +0 1 +.names g11324 g12004 +0 1 +.names g11327 g12007 +0 1 +.names g8726 II19195 +0 1 +.names II19195 g12009 +0 1 +.names g10772 g12013 +0 1 +.names g10100 g12017 +0 1 +.names g11341 g12020 +0 1 +.names g11344 g12021 +0 1 +.names g11348 g12022 +0 1 +.names g11351 g12023 +0 1 +.names g11354 g12024 +0 1 +.names g11355 g12025 +0 1 +.names g10424 II19208 +0 1 +.names II19208 g12027 +0 1 +.names g10486 II19211 +0 1 +.names II19211 g12030 +0 1 +.names g11358 g12037 +0 1 +.names g11361 g12038 +0 1 +.names g11364 g12039 +0 1 +.names g11367 g12040 +0 1 +.names g11370 g12041 +0 1 +.names g11373 g12042 +0 1 +.names g10606 II19226 +0 1 +.names II19226 g12045 +0 1 +.names g11376 g12051 +0 1 +.names g11379 g12052 +0 1 +.names g11382 g12053 +0 1 +.names g11386 g12054 +0 1 +.names g11389 g12055 +0 1 +.names g11392 g12058 +0 1 +.names g9341 II19240 +0 1 +.names II19240 g12059 +0 1 +.names g11395 g12063 +0 1 +.names g11398 g12064 +0 1 +.names g11401 g12065 +0 1 +.names g11404 g12066 +0 1 +.names g11407 g12067 +0 1 +.names g10783 g12071 +0 1 +.names g11411 g12075 +0 1 +.names g11414 g12076 +0 1 +.names g11417 g12077 +0 1 +.names g11422 g12078 +0 1 +.names g11425 g12084 +0 1 +.names g11428 g12085 +0 1 +.names g11432 g12086 +0 1 +.names g11435 g12087 +0 1 +.names g11438 g12088 +0 1 +.names g11441 g12089 +0 1 +.names g10500 II19271 +0 1 +.names II19271 g12091 +0 1 +.names g10560 II19274 +0 1 +.names II19274 g12094 +0 1 +.names g11444 g12101 +0 1 +.names g11447 g12102 +0 1 +.names g11450 g12103 +0 1 +.names g11453 g12104 +0 1 +.names g11456 g12105 +0 1 +.names g11459 g12106 +0 1 +.names g10653 II19289 +0 1 +.names II19289 g12109 +0 1 +.names g11462 g12115 +0 1 +.names g11465 g12116 +0 1 +.names g11468 g12117 +0 1 +.names g11472 g12118 +0 1 +.names g11475 g12119 +0 1 +.names g11478 g12122 +0 1 +.names g9422 II19303 +0 1 +.names II19303 g12123 +0 1 +.names g8726 II19307 +0 1 +.names II19307 g12125 +0 1 +.names g10788 g12130 +0 1 +.names g8321 g12134 +0 1 +.names g8324 g12135 +0 1 +.names g10424 II19315 +0 1 +.names II19315 g12136 +0 1 +.names g10486 II19318 +0 1 +.names II19318 g12139 +0 1 +.names g10549 II19321 +0 1 +.names II19321 g12142 +0 1 +.names g8330 g12147 +0 1 +.names g8333 g12148 +0 1 +.names g8336 g12149 +0 1 +.names g8341 g12150 +0 1 +.names g8344 g12156 +0 1 +.names g8347 g12157 +0 1 +.names g8351 g12158 +0 1 +.names g8354 g12159 +0 1 +.names g8357 g12160 +0 1 +.names g8360 g12161 +0 1 +.names g10574 II19342 +0 1 +.names II19342 g12163 +0 1 +.names g10617 II19345 +0 1 +.names II19345 g12166 +0 1 +.names g8363 g12173 +0 1 +.names g8366 g12174 +0 1 +.names g8369 g12175 +0 1 +.names g8372 g12176 +0 1 +.names g8375 g12177 +0 1 +.names g8378 g12178 +0 1 +.names g10683 II19360 +0 1 +.names II19360 g12181 +0 1 +.names g8285 g12187 +0 1 +.names g8382 g12191 +0 1 +.names g8388 g12196 +0 1 +.names g8391 g12197 +0 1 +.names g10500 II19374 +0 1 +.names II19374 g12198 +0 1 +.names g10560 II19377 +0 1 +.names II19377 g12201 +0 1 +.names g10606 II19380 +0 1 +.names II19380 g12204 +0 1 +.names g8397 g12209 +0 1 +.names g8400 g12210 +0 1 +.names g8403 g12211 +0 1 +.names g8408 g12212 +0 1 +.names g8411 g12218 +0 1 +.names g8414 g12219 +0 1 +.names g8418 g12220 +0 1 +.names g8421 g12221 +0 1 +.names g8424 g12222 +0 1 +.names g8427 g12223 +0 1 +.names g10631 II19401 +0 1 +.names II19401 g12225 +0 1 +.names g10664 II19404 +0 1 +.names II19404 g12228 +0 1 +.names g8294 g12235 +0 1 +.names g10486 II19412 +0 1 +.names II19412 g12239 +0 1 +.names g10549 II19415 +0 1 +.names II19415 g12242 +0 1 +.names g8434 g12246 +0 1 +.names g8440 g12251 +0 1 +.names g8443 g12252 +0 1 +.names g10574 II19426 +0 1 +.names II19426 g12253 +0 1 +.names g10617 II19429 +0 1 +.names II19429 g12256 +0 1 +.names g10653 II19432 +0 1 +.names II19432 g12259 +0 1 +.names g8449 g12264 +0 1 +.names g8452 g12265 +0 1 +.names g8455 g12266 +0 1 +.names g8460 g12267 +0 1 +.names g8303 g12275 +0 1 +.names g10424 II19449 +0 1 +.names II19449 g12279 +0 1 +.names g10560 II19452 +0 1 +.names II19452 g12282 +0 1 +.names g10606 II19455 +0 1 +.names II19455 g12285 +0 1 +.names g8469 g12289 +0 1 +.names g8475 g12294 +0 1 +.names g8478 g12295 +0 1 +.names g10631 II19466 +0 1 +.names II19466 g12296 +0 1 +.names g10664 II19469 +0 1 +.names II19469 g12299 +0 1 +.names g10683 II19472 +0 1 +.names II19472 g12302 +0 1 +.names g8312 g12308 +0 1 +.names g10549 II19479 +0 1 +.names II19479 g12312 +0 1 +.names g10500 II19482 +0 1 +.names II19482 g12315 +0 1 +.names g10617 II19485 +0 1 +.names II19485 g12318 +0 1 +.names g10653 II19488 +0 1 +.names II19488 g12321 +0 1 +.names g8494 g12325 +0 1 +.names g10829 g12332 +0 1 +.names g10424 II19500 +0 1 +.names II19500 g12333 +0 1 +.names g10486 II19503 +0 1 +.names II19503 g12336 +0 1 +.names g10606 II19507 +0 1 +.names II19507 g12340 +0 1 +.names g10574 II19510 +0 1 +.names II19510 g12343 +0 1 +.names g10664 II19513 +0 1 +.names II19513 g12346 +0 1 +.names g10683 II19516 +0 1 +.names II19516 g12349 +0 1 +.names g8182 g8120 g8044 g7989 g8381 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g8381 g12354 +0 1 +.names g10866 g12362 +0 1 +.names g10500 II19523 +0 1 +.names II19523 g12363 +0 1 +.names g10560 II19526 +0 1 +.names II19526 g12366 +0 1 +.names g10653 II19530 +0 1 +.names II19530 g12370 +0 1 +.names g10631 II19533 +0 1 +.names II19533 g12373 +0 1 +.names g10847 g12378 +0 1 +.names g10549 II19539 +0 1 +.names II19539 g12379 +0 1 +.names g10574 II19542 +0 1 +.names II19542 g12382 +0 1 +.names g10617 II19545 +0 1 +.names II19545 g12385 +0 1 +.names g10683 II19549 +0 1 +.names II19549 g12389 +0 1 +.names g3198 g8120 g3194 g3191 g8430 +0000 1 +.names g8430 II19552 +0 1 +.names II19552 g12392 +0 1 +.names g11020 g12408 +0 1 +.names g10606 II19557 +0 1 +.names II19557 g12409 +0 1 +.names g10631 II19560 +0 1 +.names II19560 g12412 +0 1 +.names g10664 II19563 +0 1 +.names II19563 g12415 +0 1 +.names g10986 g12420 +0 1 +.names g10653 II19569 +0 1 +.names II19569 g12421 +0 1 +.names g10962 g12424 +0 1 +.names g8835 II19573 +0 1 +.names II19573 g12425 +0 1 +.names g10683 II19576 +0 1 +.names II19576 g12426 +0 1 +.names g10905 g12430 +0 1 +.names g8862 II19582 +0 1 +.names II19582 g12432 +0 1 +.names g10929 g12434 +0 1 +.names g9173 II19587 +0 1 +.names II19587 g12435 +0 1 +.names g8900 II19591 +0 1 +.names II19591 g12437 +0 1 +.names g10846 g12438 +0 1 +.names g5711 g5758 g5807 g10810 +000 1 +.names g10810 II19595 +0 1 +.names II19595 g12439 +0 1 +.names g9215 II19598 +0 1 +.names II19598 g12440 +0 1 +.names g8940 II19602 +0 1 +.names II19602 g12442 +0 1 +.names g5678 g5710 g5757 g10797 +000 1 +.names g10797 II19605 +0 1 +.names II19605 g12443 +0 1 +.names g5769 g5817 g5863 g10831 +000 1 +.names g10831 II19608 +0 1 +.names II19608 g12444 +0 1 +.names g9276 II19611 +0 1 +.names II19611 g12445 +0 1 +.names g5650 g5677 g5709 g10789 +000 1 +.names g10789 II19615 +0 1 +.names II19615 g12447 +0 1 +.names g5730 g5768 g5816 g10814 +000 1 +.names g10814 II19618 +0 1 +.names II19618 g12448 +0 1 +.names g5828 g5873 g5910 g10851 +000 1 +.names g10851 II19621 +0 1 +.names II19621 g12449 +0 1 +.names g9354 II19624 +0 1 +.names II19624 g12450 +0 1 +.names g5630 g5649 g5676 g10784 +000 1 +.names g10784 II19628 +0 1 +.names II19628 g12452 +0 1 +.names g5688 g5729 g5767 g10801 +000 1 +.names g10801 II19631 +0 1 +.names II19631 g12453 +0 1 +.names g5788 g5827 g5872 g10835 +000 1 +.names g10835 II19634 +0 1 +.names II19634 g12454 +0 1 +.names g5884 g5920 g5949 g10872 +000 1 +.names g10872 II19637 +0 1 +.names II19637 g12455 +0 1 +.names g8602 g12456 +0 1 +.names g5658 g5687 g5728 g10793 +000 1 +.names g10793 II19642 +0 1 +.names II19642 g12460 +0 1 +.names g5740 g5787 g5826 g10818 +000 1 +.names g10818 II19645 +0 1 +.names II19645 g12461 +0 1 +.names g5847 g5883 g5919 g10855 +000 1 +.names g10855 II19648 +0 1 +.names II19648 g12462 +0 1 +.names g10730 g12463 +0 1 +.names g8614 g12466 +0 1 +.names g5696 g5739 g5786 g10805 +000 1 +.names g10805 II19654 +0 1 +.names II19654 g12470 +0 1 +.names g5798 g5846 g5882 g10839 +000 1 +.names g10839 II19657 +0 1 +.names II19657 g12471 +0 1 +.names g8617 g12472 +0 1 +.names g8580 g12473 +0 1 +.names g8622 g12476 +0 1 +.names g10749 g12478 +0 1 +.names g8627 g12481 +0 1 +.names g5748 g5797 g5845 g10822 +000 1 +.names g10822 II19667 +0 1 +.names II19667 g12485 +0 1 +.names g8587 g12490 +0 1 +.names g8632 g12493 +0 1 +.names g10767 g12495 +0 1 +.names g8637 g12498 +0 1 +.names g8640 g12502 +0 1 +.names g8643 g12504 +0 1 +.names g8646 g12505 +0 1 +.names g8594 g12510 +0 1 +.names g8651 g12513 +0 1 +.names g10773 g12515 +0 1 +.names g8655 g12518 +0 1 +.names g10016 II19689 +0 1 +.names II19689 g12519 +0 1 +.names g8659 g12521 +0 1 +.names g8662 g12522 +0 1 +.names g8605 g12527 +0 1 +.names g8667 g12530 +0 1 +.names g8670 g12532 +0 1 +.names g8673 g12533 +0 1 +.names g10125 II19702 +0 1 +.names II19702 g12534 +0 1 +.names g8678 g12536 +0 1 +.names g8681 g12537 +0 1 +.names g8684 g12542 +0 1 +.names g10230 II19711 +0 1 +.names II19711 g12543 +0 1 +.names g8690 g12545 +0 1 +.names g8693 g12546 +0 1 +.names g8696 g12547 +0 1 +.names g8726 II19718 +0 1 +.names II19718 g12548 +0 1 +.names g8700 g12551 +0 1 +.names g10332 II19722 +0 1 +.names II19722 g12552 +0 1 +.names g8708 g12553 +0 1 +.names g8711 g12554 +0 1 +.names g8726 II19727 +0 1 +.names II19727 g12555 +0 1 +.names g8714 g12558 +0 1 +.names g8719 g12559 +0 1 +.names g8745 g12560 +0 1 +.names g8726 II19733 +0 1 +.names II19733 g12561 +0 1 +.names g9184 II19736 +0 1 +.names II19736 g12564 +0 1 +.names g10694 II19739 +0 1 +.names II19739 g12565 +0 1 +.names g8748 g12596 +0 1 +.names g8752 g12597 +0 1 +.names g8757 g12598 +0 1 +.names g8763 g12599 +0 1 +.names g8766 g12600 +0 1 +.names g8726 II19747 +0 1 +.names II19747 g12601 +0 1 +.names g8726 II19750 +0 1 +.names II19750 g12604 +0 1 +.names g9229 II19753 +0 1 +.names II19753 g12607 +0 1 +.names g10424 II19756 +0 1 +.names II19756 g12608 +0 1 +.names g10714 II19759 +0 1 +.names II19759 g12611 +0 1 +.names g8771 g12642 +0 1 +.names g8775 g12643 +0 1 +.names g8780 g12644 +0 1 +.names g8785 g12645 +0 1 +.names g8788 g12646 +0 1 +.names g8726 II19767 +0 1 +.names II19767 g12647 +0 1 +.names g7772 g3366 g10038 +0- 1 +-0 1 +.names g10038 II19771 +0 1 +.names II19771 g12651 +0 1 +.names g10500 II19774 +0 1 +.names II19774 g12654 +0 1 +.names g10735 II19777 +0 1 +.names II19777 g12657 +0 1 +.names g8794 g12688 +0 1 +.names g8798 g12689 +0 1 +.names g8802 g12690 +0 1 +.names g8805 g12691 +0 1 +.names g8726 II19784 +0 1 +.names II19784 g12692 +0 1 +.names g8726 II19787 +0 1 +.names II19787 g12695 +0 1 +.names g10486 II19791 +0 1 +.names II19791 g12699 +0 1 +.names g3398 g6678 g10676 +0- 1 +-0 1 +.names g10676 II19794 +0 1 +.names II19794 g12702 +0 1 +.names g7788 g3522 g10147 +0- 1 +-0 1 +.names g10147 II19797 +0 1 +.names II19797 g12705 +0 1 +.names g10574 II19800 +0 1 +.names II19800 g12708 +0 1 +.names g10754 II19803 +0 1 +.names II19803 g12711 +0 1 +.names g8813 g12742 +0 1 +.names g8817 g12743 +0 1 +.names g8726 II19808 +0 1 +.names II19808 g12744 +0 1 +.names g8823 g12748 +0 1 +.names g3398 g6912 g10649 +0- 1 +-0 1 +.names g10649 II19813 +0 1 +.names II19813 g12749 +0 1 +.names g3398 g6678 g10703 +0- 1 +-0 1 +.names g10703 II19816 +0 1 +.names II19816 g12752 +0 1 +.names g10560 II19820 +0 1 +.names II19820 g12756 +0 1 +.names g3554 g6980 g10705 +0- 1 +-0 1 +.names g10705 II19823 +0 1 +.names II19823 g12759 +0 1 +.names g7802 g3678 g10252 +0- 1 +-0 1 +.names g10252 II19826 +0 1 +.names II19826 g12762 +0 1 +.names g10631 II19829 +0 1 +.names II19829 g12765 +0 1 +.names g8829 g12768 +0 1 +.names g8726 II19833 +0 1 +.names II19833 g12769 +0 1 +.names g8726 II19836 +0 1 +.names II19836 g12772 +0 1 +.names g8832 g12775 +0 1 +.names g10766 g12776 +0 1 +.names g8836 g12782 +0 1 +.names g3398 g3366 g8533 +0- 1 +-0 1 +.names g8533 II19844 +0 1 +.names II19844 g12783 +0 1 +.names g3398 g6912 g10677 +0- 1 +-0 1 +.names g10677 II19847 +0 1 +.names II19847 g12786 +0 1 +.names g8847 g12790 +0 1 +.names g3554 g7162 g10679 +0- 1 +-0 1 +.names g10679 II19852 +0 1 +.names II19852 g12791 +0 1 +.names g3554 g6980 g10723 +0- 1 +-0 1 +.names g10723 II19855 +0 1 +.names II19855 g12794 +0 1 +.names g10617 II19859 +0 1 +.names II19859 g12798 +0 1 +.names g3710 g7230 g10725 +0- 1 +-0 1 +.names g10725 II19862 +0 1 +.names II19862 g12801 +0 1 +.names g7815 g3834 g10354 +0- 1 +-0 1 +.names g10354 II19865 +0 1 +.names II19865 g12804 +0 1 +.names g8853 g12807 +0 1 +.names g8726 II19869 +0 1 +.names II19869 g12808 +0 1 +.names g8317 II19872 +0 1 +.names II19872 g12811 +0 1 +.names g8856 g12815 +0 1 +.names g3398 g3366 g8547 +0- 1 +-0 1 +.names g8547 II19877 +0 1 +.names II19877 g12816 +0 1 +.names g8863 g12821 +0 1 +.names g3554 g3522 g8550 +0- 1 +-0 1 +.names g8550 II19883 +0 1 +.names II19883 g12822 +0 1 +.names g3554 g7162 g10706 +0- 1 +-0 1 +.names g10706 II19886 +0 1 +.names II19886 g12825 +0 1 +.names g8874 g12829 +0 1 +.names g3710 g7358 g10708 +0- 1 +-0 1 +.names g10708 II19891 +0 1 +.names II19891 g12830 +0 1 +.names g3710 g7230 g10744 +0- 1 +-0 1 +.names g10744 II19894 +0 1 +.names II19894 g12833 +0 1 +.names g10664 II19898 +0 1 +.names II19898 g12837 +0 1 +.names g3866 g7426 g10746 +0- 1 +-0 1 +.names g10746 II19901 +0 1 +.names II19901 g12840 +0 1 +.names g8879 g12843 +0 1 +.names g8726 II19905 +0 1 +.names II19905 g12844 +0 1 +.names g8882 g12847 +0 1 +.names g11059 g12848 +0 1 +.names g8885 g12850 +0 1 +.names g8888 g12851 +0 1 +.names g8894 g12853 +0 1 +.names g3554 g3522 g8560 +0- 1 +-0 1 +.names g8560 II19915 +0 1 +.names II19915 g12854 +0 1 +.names g8901 g12859 +0 1 +.names g3710 g3678 g8563 +0- 1 +-0 1 +.names g8563 II19921 +0 1 +.names II19921 g12860 +0 1 +.names g3710 g7358 g10726 +0- 1 +-0 1 +.names g10726 II19924 +0 1 +.names II19924 g12863 +0 1 +.names g8912 g12867 +0 1 +.names g3866 g7488 g10728 +0- 1 +-0 1 +.names g10728 II19929 +0 1 +.names II19929 g12868 +0 1 +.names g3866 g7426 g10763 +0- 1 +-0 1 +.names g10763 II19932 +0 1 +.names II19932 g12871 +0 1 +.names g8915 g12874 +0 1 +.names g10779 g12875 +0 1 +.names g8918 g12881 +0 1 +.names g8921 g12882 +0 1 +.names g8925 g12891 +0 1 +.names g8928 g12892 +0 1 +.names g8934 g12894 +0 1 +.names g3710 g3678 g8571 +0- 1 +-0 1 +.names g8571 II19952 +0 1 +.names II19952 g12895 +0 1 +.names g8941 g12900 +0 1 +.names g3866 g3834 g8574 +0- 1 +-0 1 +.names g8574 II19958 +0 1 +.names II19958 g12901 +0 1 +.names g3866 g7488 g10747 +0- 1 +-0 1 +.names g10747 II19961 +0 1 +.names II19961 g12904 +0 1 +.names g8949 g12907 +0 1 +.names g10904 g12909 +0 1 +.names g8952 g12914 +0 1 +.names g8955 g12915 +0 1 +.names g8958 g12921 +0 1 +.names g8961 g12922 +0 1 +.names g8965 g12931 +0 1 +.names g8968 g12932 +0 1 +.names g8974 g12934 +0 1 +.names g3866 g3834 g8577 +0- 1 +-0 1 +.names g8577 II19986 +0 1 +.names II19986 g12935 +0 1 +.names g8980 g12940 +0 1 +.names g8984 g12943 +0 1 +.names g8987 g12944 +0 1 +.names g8990 g12950 +0 1 +.names g8993 g12951 +0 1 +.names g8997 g12960 +0 1 +.names g9000 g12961 +0 1 +.names g8313 II20009 +0 1 +.names II20009 g12962 +0 1 +.names g9006 g12965 +0 1 +.names g9010 g12969 +0 1 +.names g9013 g12972 +0 1 +.names g9016 g12973 +0 1 +.names g9019 g12979 +0 1 +.names g9022 g12980 +0 1 +.names g9035 g12993 +0 1 +.names g9038 g12996 +0 1 +.names g9041 g12997 +0 1 +.names g9044 g12998 +0 1 +.names g9058 g13003 +0 1 +.names g7466 g7342 II17429 g10480 +111 1 +.names g10480 II20062 +0 1 +.names II20062 g13011 +0 1 +.names g10810 g13025 +0 1 +.names g10797 g13033 +0 1 +.names g10831 g13036 +0 1 +.names g10789 g13043 +0 1 +.names g10814 g13046 +0 1 +.names g10851 g13049 +0 1 +.names g10784 g13057 +0 1 +.names g10801 g13060 +0 1 +.names g10835 g13063 +0 1 +.names g10872 g13066 +0 1 +.names g10876 II20117 +0 1 +.names II20117 g13070 +0 1 +.names g10793 g13073 +0 1 +.names g10818 g13076 +0 1 +.names g10855 g13079 +0 1 +.names g10805 g13092 +0 1 +.names g10839 g13095 +0 1 +.names g9128 g13101 +0 1 +.names g10822 g13107 +0 1 +.names g9134 g13117 +0 1 +.names g9140 g13130 +0 1 +.names g9146 g13141 +0 1 +.names g9170 g13148 +0 1 +.names g9184 g13151 +0 1 +.names g9196 g13152 +0 1 +.names g9199 g13153 +0 1 +.names g9212 g13154 +0 1 +.names g9229 g13157 +0 1 +.names g9242 g13158 +0 1 +.names g9245 g13159 +0 1 +.names g9257 g13161 +0 1 +.names g9260 g13162 +0 1 +.names g9273 g13163 +0 1 +.names g9290 g13166 +0 1 +.names g9303 g13167 +0 1 +.names g9306 g13168 +0 1 +.names g9320 g13169 +0 1 +.names g9323 g13170 +0 1 +.names g9335 g13172 +0 1 +.names g9338 g13173 +0 1 +.names g9351 g13174 +0 1 +.names g9368 g13176 +0 1 +.names g9371 g13177 +0 1 +.names g9384 g13178 +0 1 +.names g9387 g13179 +0 1 +.names g9401 g13180 +0 1 +.names g9404 g13181 +0 1 +.names g9416 g13183 +0 1 +.names g9419 g13184 +0 1 +.names g9443 g13185 +0 1 +.names g9446 g13186 +0 1 +.names g9450 g13187 +0 1 +.names g9465 g13188 +0 1 +.names g9468 g13189 +0 1 +.names g9481 g13190 +0 1 +.names g9484 g13191 +0 1 +.names g9498 g13192 +0 1 +.names g9501 g13193 +0 1 +.names g9524 g13195 +0 1 +.names g9528 g13196 +0 1 +.names g9531 g13197 +0 1 +.names g9585 g13198 +0 1 +.names g9588 g13199 +0 1 +.names g9592 g13200 +0 1 +.names g9607 g13201 +0 1 +.names g9610 g13202 +0 1 +.names g9623 g13203 +0 1 +.names g9626 g13204 +0 1 +.names g9641 g13205 +0 1 +.names g9644 g13206 +0 1 +.names g9666 g13207 +0 1 +.names g9670 g13208 +0 1 +.names g9673 g13209 +0 1 +.names g9727 g13210 +0 1 +.names g9730 g13211 +0 1 +.names g9734 g13212 +0 1 +.names g9749 g13213 +0 1 +.names g9752 g13214 +0 1 +.names g9027 II20264 +0 1 +.names II20264 g13215 +0 1 +.names g9767 g13218 +0 1 +.names g9770 g13219 +0 1 +.names g9787 g13220 +0 1 +.names g9790 g13221 +0 1 +.names g9812 g13222 +0 1 +.names g9816 g13223 +0 1 +.names g9819 g13224 +0 1 +.names g9873 g13225 +0 1 +.names g9876 g13226 +0 1 +.names g9880 g13227 +0 1 +.names g9027 II20278 +0 1 +.names II20278 g13229 +0 1 +.names g9895 g13232 +0 1 +.names g9898 g13233 +0 1 +.names g9050 II20283 +0 1 +.names II20283 g13234 +0 1 +.names g9913 g13237 +0 1 +.names g9916 g13238 +0 1 +.names g9933 g13239 +0 1 +.names g9936 g13240 +0 1 +.names g9958 g13241 +0 1 +.names g9962 g13242 +0 1 +.names g9965 g13243 +0 1 +.names g10004 g13244 +0 1 +.names g10015 II20295 +0 1 +.names II20295 g13246 +0 1 +.names g10800 II20299 +0 1 +.names II20299 g13248 +0 1 +.names g10018 g13249 +0 1 +.names g10021 g13250 +0 1 +.names g9050 II20305 +0 1 +.names II20305 g13252 +0 1 +.names g10049 g13255 +0 1 +.names g10052 g13256 +0 1 +.names g9067 II20310 +0 1 +.names II20310 g13257 +0 1 +.names g10067 g13260 +0 1 +.names g10070 g13261 +0 1 +.names g10087 g13262 +0 1 +.names g10090 g13263 +0 1 +.names g10096 g13264 +0 1 +.names g8568 g13265 +0 1 +.names g10792 II20320 +0 1 +.names II20320 g13267 +0 1 +.names g10109 g13268 +0 1 +.names g10124 II20324 +0 1 +.names II20324 g13269 +0 1 +.names g10817 II20328 +0 1 +.names II20328 g13271 +0 1 +.names g10127 g13272 +0 1 +.names g10130 g13273 +0 1 +.names g9067 II20334 +0 1 +.names II20334 g13275 +0 1 +.names g10158 g13278 +0 1 +.names g10161 g13279 +0 1 +.names g9084 II20339 +0 1 +.names II20339 g13280 +0 1 +.names g10176 g13283 +0 1 +.names g10179 g13284 +0 1 +.names g10189 g13285 +0 1 +.names g10787 II20347 +0 1 +.names II20347 g13290 +0 1 +.names g10804 II20351 +0 1 +.names II20351 g13292 +0 1 +.names g10214 g13293 +0 1 +.names g10229 II20355 +0 1 +.names II20355 g13294 +0 1 +.names g10838 II20359 +0 1 +.names II20359 g13296 +0 1 +.names g10232 g13297 +0 1 +.names g10235 g13298 +0 1 +.names g9084 II20365 +0 1 +.names II20365 g13300 +0 1 +.names g10263 g13303 +0 1 +.names g10266 g13304 +0 1 +.names g10273 g13308 +0 1 +.names g10276 g13309 +0 1 +.names g8569 II20376 +0 1 +.names II20376 g13317 +0 1 +.names g11213 II20379 +0 1 +.names II20379 g13318 +0 1 +.names g10907 II20382 +0 1 +.names II20382 g13319 +0 1 +.names g10796 II20386 +0 1 +.names II20386 g13321 +0 1 +.names g10821 II20390 +0 1 +.names II20390 g13323 +0 1 +.names g10316 g13324 +0 1 +.names g10331 II20394 +0 1 +.names II20394 g13325 +0 1 +.names g10858 II20398 +0 1 +.names II20398 g13327 +0 1 +.names g10334 g13328 +0 1 +.names g10337 g13329 +0 1 +.names g10357 g13330 +0 1 +.names g9027 II20407 +0 1 +.names II20407 g13336 +0 1 +.names g10887 II20410 +0 1 +.names II20410 g13339 +0 1 +.names g8575 II20414 +0 1 +.names II20414 g13341 +0 1 +.names g10933 II20417 +0 1 +.names II20417 g13342 +0 1 +.names g10808 II20421 +0 1 +.names II20421 g13344 +0 1 +.names g10842 II20425 +0 1 +.names II20425 g13346 +0 1 +.names g10409 g13347 +0 1 +.names g10416 g13351 +0 1 +.names g10419 g13352 +0 1 +.names g9027 II20441 +0 1 +.names II20441 g13356 +0 1 +.names g10869 II20444 +0 1 +.names II20444 g13359 +0 1 +.names g9050 II20448 +0 1 +.names II20448 g13361 +0 1 +.names g10908 II20451 +0 1 +.names II20451 g13364 +0 1 +.names g8578 II20455 +0 1 +.names II20455 g13366 +0 1 +.names g10972 II20458 +0 1 +.names II20458 g13367 +0 1 +.names g10825 II20462 +0 1 +.names II20462 g13369 +0 1 +.names g10482 g13373 +0 1 +.names g9027 II20476 +0 1 +.names II20476 g13381 +0 1 +.names g10849 II20479 +0 1 +.names II20479 g13384 +0 1 +.names g9050 II20483 +0 1 +.names II20483 g13386 +0 1 +.names g10889 II20486 +0 1 +.names II20486 g13389 +0 1 +.names g9067 II20490 +0 1 +.names II20490 g13391 +0 1 +.names g10934 II20493 +0 1 +.names II20493 g13394 +0 1 +.names g8579 II20497 +0 1 +.names II20497 g13396 +0 1 +.names g11007 II20500 +0 1 +.names II20500 g13397 +0 1 +.names g10542 g13398 +0 1 +.names g10545 g13400 +0 1 +.names g11769 II20514 +0 1 +.names g12425 II20517 +0 1 +.names g13246 II20520 +0 1 +.names g13317 II20523 +0 1 +.names g12519 II20526 +0 1 +.names g13319 II20529 +0 1 +.names g13339 II20532 +0 1 +.names g13359 II20535 +0 1 +.names g13384 II20538 +0 1 +.names g11599 II20541 +0 1 +.names g11628 II20544 +0 1 +.names g13248 II20547 +0 1 +.names g13267 II20550 +0 1 +.names g13290 II20553 +0 1 +.names g12435 II20556 +0 1 +.names g11937 II20559 +0 1 +.names g11786 II20562 +0 1 +.names g12432 II20565 +0 1 +.names g13269 II20568 +0 1 +.names g13341 II20571 +0 1 +.names g12534 II20574 +0 1 +.names g13342 II20577 +0 1 +.names g13364 II20580 +0 1 +.names g13389 II20583 +0 1 +.names g11606 II20586 +0 1 +.names g11629 II20589 +0 1 +.names g11651 II20592 +0 1 +.names g13271 II20595 +0 1 +.names g13292 II20598 +0 1 +.names g13321 II20601 +0 1 +.names g12440 II20604 +0 1 +.names g11990 II20607 +0 1 +.names g11812 II20610 +0 1 +.names g12437 II20613 +0 1 +.names g13294 II20616 +0 1 +.names g13366 II20619 +0 1 +.names g12543 II20622 +0 1 +.names g13367 II20625 +0 1 +.names g13394 II20628 +0 1 +.names g11611 II20631 +0 1 +.names g11636 II20634 +0 1 +.names g11652 II20637 +0 1 +.names g11670 II20640 +0 1 +.names g13296 II20643 +0 1 +.names g13323 II20646 +0 1 +.names g13344 II20649 +0 1 +.names g12445 II20652 +0 1 +.names g12059 II20655 +0 1 +.names g11845 II20658 +0 1 +.names g12442 II20661 +0 1 +.names g13325 II20664 +0 1 +.names g13396 II20667 +0 1 +.names g12552 II20670 +0 1 +.names g13397 II20673 +0 1 +.names g11616 II20676 +0 1 +.names g11641 II20679 +0 1 +.names g11659 II20682 +0 1 +.names g11671 II20685 +0 1 +.names g11682 II20688 +0 1 +.names g13327 II20691 +0 1 +.names g13346 II20694 +0 1 +.names g13369 II20697 +0 1 +.names g12450 II20700 +0 1 +.names g12123 II20703 +0 1 +.names g11490 II20706 +0 1 +.names II20706 g13469 +0 1 +.names g13070 II20709 +0 1 +.names g8841 g8861 g8892 g13228 +000 1 +.names g13228 g13519 +0 1 +.names g8868 g8899 g8932 g13251 +000 1 +.names g13251 g13530 +0 1 +.names g8906 g8939 g8972 g13274 +000 1 +.names g13274 g13541 +0 1 +.names g8946 g8979 g9004 g13299 +000 1 +.names g13299 g13552 +0 1 +.names g10423 g10485 g10548 g12192 +000 1 +.names g12192 g13565 +0 1 +.names g9063 g9077 g9093 g11627 +000 1 +.names g11627 g13568 +0 1 +.names g8676 g8687 g8703 g13149 +000 1 +.names g13149 II20791 +0 1 +.names II20791 g13571 +0 1 +.names g8601 g8612 g8621 g13111 +000 1 +.names g13111 II20794 +0 1 +.names II20794 g13572 +0 1 +.names g10499 g10559 g10605 g12247 +000 1 +.names g12247 g13573 +0 1 +.names g9080 g9096 g9105 g11650 +000 1 +.names g11650 g13576 +0 1 +.names g8688 g8705 g8722 g13155 +000 1 +.names g13155 II20799 +0 1 +.names II20799 g13579 +0 1 +.names g8704 g8717 g8751 g13160 +000 1 +.names g13160 II20802 +0 1 +.names II20802 g13580 +0 1 +.names g8613 g8625 g8631 g13124 +000 1 +.names g13124 II20805 +0 1 +.names II20805 g13581 +0 1 +.names g10573 g10616 g10652 g12290 +000 1 +.names g12290 g13582 +0 1 +.names g9099 g9108 g9115 g11669 +000 1 +.names g11669 g13585 +0 1 +.names g8706 g8724 g8760 g13164 +000 1 +.names g13164 II20810 +0 1 +.names II20810 g13588 +0 1 +.names g13265 II20813 +0 1 +.names II20813 g13589 +0 1 +.names g10108 g10198 g10283 g12487 +000 1 +.names g12487 II20816 +0 1 +.names II20816 g13598 +0 1 +.names g8723 g8755 g8774 g13171 +000 1 +.names g13171 II20820 +0 1 +.names II20820 g13600 +0 1 +.names g8626 g8635 g8650 g13135 +000 1 +.names g13135 II20823 +0 1 +.names II20823 g13601 +0 1 +.names g10630 g10663 g10682 g12326 +000 1 +.names g12326 g13602 +0 1 +.names g9111 g9118 g9123 g11681 +000 1 +.names g11681 g13605 +0 1 +.names g8725 g8762 g8783 g13175 +000 1 +.names g13175 II20828 +0 1 +.names II20828 g13608 +0 1 +.names g10213 g10300 g10376 g12507 +000 1 +.names g12507 II20832 +0 1 +.names II20832 g13610 +0 1 +.names g8761 g8778 g8797 g13182 +000 1 +.names g13182 II20836 +0 1 +.names II20836 g13612 +0 1 +.names g8636 g8654 g8666 g13143 +000 1 +.names g13143 II20839 +0 1 +.names II20839 g13613 +0 1 +.names g9119 g9124 g9127 g11690 +000 1 +.names g11690 g13614 +0 1 +.names g10315 g10393 g10455 g12524 +000 1 +.names g12524 II20844 +0 1 +.names II20844 g13620 +0 1 +.names g8784 g8801 g8816 g13194 +000 1 +.names g13194 II20848 +0 1 +.names II20848 g13622 +0 1 +.names g9009 g9033 g9048 g12457 +000 1 +.names g12457 II20852 +0 1 +.names II20852 g13624 +0 1 +.names g9125 g9131 g9133 g11697 +000 1 +.names g11697 g13626 +0 1 +.names g10408 g10472 g10531 g12539 +000 1 +.names g12539 II20858 +0 1 +.names II20858 g13632 +0 1 +.names g9034 g9056 g9065 g12467 +000 1 +.names g12467 II20863 +0 1 +.names II20863 g13635 +0 1 +.names g9132 g9137 g9139 g11703 +000 1 +.names g11703 g13637 +0 1 +.names g13215 g13644 +0 1 +.names g9057 g9073 g9082 g12482 +000 1 +.names g12482 II20873 +0 1 +.names II20873 g13647 +0 1 +.names g9138 g9143 g9145 g11711 +000 1 +.names g11711 g13649 +0 1 +.names g12452 g13657 +0 1 +.names g13229 g13669 +0 1 +.names g13234 g13670 +0 1 +.names g9074 g9090 g9101 g12499 +000 1 +.names g12499 II20886 +0 1 +.names II20886 g13673 +0 1 +.names g12447 g13677 +0 1 +.names g12460 g13687 +0 1 +.names g13252 g13699 +0 1 +.names g13257 g13700 +0 1 +.names g12443 g13706 +0 1 +.names g12453 g13714 +0 1 +.names g12470 g13724 +0 1 +.names g13275 g13736 +0 1 +.names g13280 g13737 +0 1 +.names g7471 g7570 II20100 g13055 +111 1 +.names g13055 II20909 +0 1 +.names II20909 g13741 +0 1 +.names g12439 g13750 +0 1 +.names g12448 g13756 +0 1 +.names g12461 g13764 +0 1 +.names g12485 g13774 +0 1 +.names g13300 g13786 +0 1 +.names g12444 g13791 +0 1 +.names g12454 g13797 +0 1 +.names g12471 g13805 +0 1 +.names g13336 g13817 +0 1 +.names g12449 g13819 +0 1 +.names g12462 g13825 +0 1 +.names g13356 g13836 +0 1 +.names g13361 g13838 +0 1 +.names g12455 g13840 +0 1 +.names g9241 g9301 g9364 g11744 +000 1 +.names g11744 g13848 +0 1 +.names g13381 g13849 +0 1 +.names g13386 g13850 +0 1 +.names g13391 g13852 +0 1 +.names g9302 g9365 g9438 g11759 +000 1 +.names g11759 g13856 +0 1 +.names g9319 g9382 g9461 g11760 +000 1 +.names g11760 g13857 +0 1 +.names g11603 g13858 +0 1 +.names g11608 g13859 +0 1 +.names g11613 g13861 +0 1 +.names g10481 g9144 g11713 +0- 1 +-0 1 +.names g11713 II20959 +0 1 +.names II20959 g13863 +0 1 +.names g9366 g9439 g9518 g11767 +000 1 +.names g11767 g13864 +0 1 +.names g9383 g9462 g9580 g11772 +000 1 +.names g11772 g13866 +0 1 +.names g9400 g9479 g9603 g11773 +000 1 +.names g11773 g13867 +0 1 +.names g11633 g13868 +0 1 +.names g11638 g13869 +0 1 +.names g9440 g9519 g9630 g11780 +000 1 +.names g11780 g13872 +0 1 +.names g11347 g11420 g8327 g12698 +000 1 +.names g12698 g13873 +0 1 +.names g9463 g9581 g9660 g11784 +000 1 +.names g11784 g13879 +0 1 +.names g9480 g9604 g9722 g11789 +000 1 +.names g11789 g13881 +0 1 +.names g9497 g9621 g9745 g11790 +000 1 +.names g11790 g13882 +0 1 +.names g11656 g13883 +0 1 +.names g9520 g9631 g9759 g11799 +000 1 +.names g11799 g13885 +0 1 +.names g11421 g8328 g8385 g12747 +000 1 +.names g12747 g13886 +0 1 +.names g9582 g9661 g9776 g11806 +000 1 +.names g11806 g13894 +0 1 +.names g11431 g8339 g8394 g12755 +000 1 +.names g12755 g13895 +0 1 +.names g9605 g9723 g9806 g11810 +000 1 +.names g11810 g13901 +0 1 +.names g9622 g9746 g9868 g11815 +000 1 +.names g11815 g13903 +0 1 +.names g9632 g9760 g9888 g11822 +000 1 +.names g11822 g13906 +0 1 +.names g8329 g8386 g8431 g12781 +000 1 +.names g12781 g13907 +0 1 +.names g9647 g9773 g9901 g11830 +000 1 +.names g11830 g13918 +0 1 +.names g9648 g9775 g9904 g11831 +000 1 +.names g11831 g13922 +0 1 +.names g9662 g9777 g9905 g11832 +000 1 +.names g11832 g13926 +0 1 +.names g8340 g8395 g8437 g12789 +000 1 +.names g12789 g13927 +0 1 +.names g9724 g9807 g9922 g11839 +000 1 +.names g11839 g13935 +0 1 +.names g8350 g8406 g8446 g12797 +000 1 +.names g12797 g13936 +0 1 +.names g9747 g9869 g9952 g11843 +000 1 +.names g11843 g13942 +0 1 +.names g9761 g9889 g10009 g11855 +000 1 +.names g11855 g13945 +0 1 +.names g8387 g8432 g8463 g12814 +000 1 +.names g12814 g13946 +0 1 +.names g8278 g5438 g12503 +0- 1 +-0 1 +.names g12503 II21012 +0 1 +.names II21012 g13954 +0 1 +.names g9774 g9902 g10035 g11863 +000 1 +.names g11863 g13958 +0 1 +.names g9778 g9906 g10042 g11864 +000 1 +.names g11864 g13962 +0 1 +.names g8396 g8438 g8466 g12820 +000 1 +.names g12820 g13963 +0 1 +.names g9793 g9919 g10055 g11872 +000 1 +.names g11872 g13974 +0 1 +.names g9794 g9921 g10058 g11873 +000 1 +.names g11873 g13978 +0 1 +.names g9808 g9923 g10059 g11874 +000 1 +.names g11874 g13982 +0 1 +.names g8407 g8447 g8472 g12828 +000 1 +.names g12828 g13983 +0 1 +.names g9870 g9953 g10076 g11881 +000 1 +.names g11881 g13991 +0 1 +.names g8417 g8458 g8481 g12836 +000 1 +.names g12836 g13992 +0 1 +.names g9887 g10007 g10101 g11889 +000 1 +.names g11889 g13999 +0 1 +.names g9890 g10010 g10103 g11890 +000 1 +.names g11890 g14000 +0 1 +.names g8433 g8464 g8485 g12849 +000 1 +.names g12849 g14001 +0 1 +.names g8278 g6448 g12486 +0- 1 +-0 1 +.names g12486 II21037 +0 1 +.names II21037 g14008 +0 1 +.names g9903 g10036 g10112 g11896 +000 1 +.names g11896 g14011 +0 1 +.names g9907 g10043 g10118 g11897 +000 1 +.names g11897 g14015 +0 1 +.names g8439 g8467 g8488 g12852 +000 1 +.names g12852 g14016 +0 1 +.names g8287 g5473 g12520 +0- 1 +-0 1 +.names g12520 II21045 +0 1 +.names II21045 g14024 +0 1 +.names g9920 g10056 g10144 g11905 +000 1 +.names g11905 g14028 +0 1 +.names g9924 g10060 g10151 g11906 +000 1 +.names g11906 g14032 +0 1 +.names g8448 g8473 g8491 g12858 +000 1 +.names g12858 g14033 +0 1 +.names g9939 g10073 g10164 g11914 +000 1 +.names g11914 g14044 +0 1 +.names g9940 g10075 g10167 g11915 +000 1 +.names g11915 g14048 +0 1 +.names g9954 g10077 g10168 g11916 +000 1 +.names g11916 g14052 +0 1 +.names g8459 g8482 g8497 g12866 +000 1 +.names g12866 g14053 +0 1 +.names g10008 g10102 g10192 g11928 +000 1 +.names g11928 g14061 +0 1 +.names g8465 g8486 g8502 g12880 +000 1 +.names g12880 g14062 +0 1 +.names g8278 g3306 g13147 +0- 1 +-0 1 +.names g13147 II21064 +0 1 +.names II21064 g14068 +0 1 +.names g10011 g10104 g10193 g11934 +000 1 +.names g11934 g14071 +0 1 +.names g10014 g10106 g10196 g11935 +000 1 +.names g11935 g14079 +0 1 +.names g10037 g10113 g10201 g11938 +000 1 +.names g11938 g14086 +0 1 +.names g10041 g10116 g10206 g11939 +000 1 +.names g11939 g14090 +0 1 +.names g10044 g10119 g10208 g11940 +000 1 +.names g11940 g14091 +0 1 +.names g8468 g8489 g8505 g12890 +000 1 +.names g12890 g14092 +0 1 +.names g8287 g6713 g12506 +0- 1 +-0 1 +.names g12506 II21075 +0 1 +.names II21075 g14099 +0 1 +.names g10057 g10145 g10217 g11946 +000 1 +.names g11946 g14102 +0 1 +.names g10061 g10152 g10223 g11947 +000 1 +.names g11947 g14106 +0 1 +.names g8474 g8492 g8508 g12893 +000 1 +.names g12893 g14107 +0 1 +.names g8296 g5512 g12535 +0- 1 +-0 1 +.names g12535 II21083 +0 1 +.names II21083 g14115 +0 1 +.names g10074 g10165 g10249 g11955 +000 1 +.names g11955 g14119 +0 1 +.names g10078 g10169 g10256 g11956 +000 1 +.names g11956 g14123 +0 1 +.names g8483 g8498 g8511 g12899 +000 1 +.names g12899 g14124 +0 1 +.names g10093 g10182 g10269 g11964 +000 1 +.names g11964 g14135 +0 1 +.names g10094 g10184 g10272 g11965 +000 1 +.names g11965 g14139 +0 1 +.names g11749 II21096 +0 1 +.names II21096 g14144 +0 1 +.names g8484 g8500 g8515 g12912 +000 1 +.names g12912 g14148 +0 1 +.names g8487 g8503 g8518 g12913 +000 1 +.names g12913 g14153 +0 1 +.names g10105 g10194 g10279 g11974 +000 1 +.names g11974 g14158 +0 1 +.names g10107 g10197 g10282 g11975 +000 1 +.names g11975 g14165 +0 1 +.names g10114 g10202 g10288 g11979 +000 1 +.names g11979 g14171 +0 1 +.names g10115 g10204 g10291 g11980 +000 1 +.names g11980 g14175 +0 1 +.names g10117 g10207 g10294 g11981 +000 1 +.names g11981 g14176 +0 1 +.names g8490 g8506 g8521 g12920 +000 1 +.names g12920 g14177 +0 1 +.names g8287 g3462 g13150 +0- 1 +-0 1 +.names g13150 II21108 +0 1 +.names II21108 g14183 +0 1 +.names g10120 g10209 g10295 g11987 +000 1 +.names g11987 g14186 +0 1 +.names g10123 g10211 g10298 g11988 +000 1 +.names g11988 g14194 +0 1 +.names g10146 g10218 g10303 g11991 +000 1 +.names g11991 g14201 +0 1 +.names g10150 g10221 g10308 g11992 +000 1 +.names g11992 g14205 +0 1 +.names g10153 g10224 g10310 g11993 +000 1 +.names g11993 g14206 +0 1 +.names g8493 g8509 g8524 g12930 +000 1 +.names g12930 g14207 +0 1 +.names g8296 g7015 g12523 +0- 1 +-0 1 +.names g12523 II21119 +0 1 +.names II21119 g14214 +0 1 +.names g10166 g10250 g10319 g11999 +000 1 +.names g11999 g14217 +0 1 +.names g10170 g10257 g10325 g12000 +000 1 +.names g12000 g14221 +0 1 +.names g8499 g8512 g8527 g12933 +000 1 +.names g12933 g14222 +0 1 +.names g8305 g5556 g12544 +0- 1 +-0 1 +.names g12544 II21127 +0 1 +.names II21127 g14230 +0 1 +.names g10183 g10270 g10351 g12008 +000 1 +.names g12008 g14234 +0 1 +.names g8501 g8516 g8531 g12939 +000 1 +.names g12939 g14238 +0 1 +.names g10195 g10280 g10360 g12026 +000 1 +.names g12026 g14244 +0 1 +.names g10200 g10286 g10365 g12034 +000 1 +.names g12034 g14249 +0 1 +.names g10203 g10289 g10367 g12035 +000 1 +.names g12035 g14252 +0 1 +.names g10205 g10292 g10370 g12036 +000 1 +.names g12036 g14256 +0 1 +.names g11749 II21137 +0 1 +.names II21137 g14259 +0 1 +.names g8504 g8519 g8534 g12941 +000 1 +.names g12941 g14263 +0 1 +.names g8507 g8522 g8537 g12942 +000 1 +.names g12942 g14268 +0 1 +.names g10210 g10296 g10372 g12043 +000 1 +.names g12043 g14273 +0 1 +.names g10212 g10299 g10375 g12044 +000 1 +.names g12044 g14280 +0 1 +.names g10219 g10304 g10381 g12048 +000 1 +.names g12048 g14286 +0 1 +.names g10220 g10306 g10384 g12049 +000 1 +.names g12049 g14290 +0 1 +.names g10222 g10309 g10387 g12050 +000 1 +.names g12050 g14291 +0 1 +.names g8510 g8525 g8540 g12949 +000 1 +.names g12949 g14292 +0 1 +.names g8296 g3618 g13156 +0- 1 +-0 1 +.names g13156 II21149 +0 1 +.names II21149 g14298 +0 1 +.names g10225 g10311 g10388 g12056 +000 1 +.names g12056 g14301 +0 1 +.names g10228 g10313 g10391 g12057 +000 1 +.names g12057 g14309 +0 1 +.names g10251 g10320 g10396 g12060 +000 1 +.names g12060 g14316 +0 1 +.names g10255 g10323 g10401 g12061 +000 1 +.names g12061 g14320 +0 1 +.names g10258 g10326 g10403 g12062 +000 1 +.names g12062 g14321 +0 1 +.names g8513 g8528 g8543 g12959 +000 1 +.names g12959 g14322 +0 1 +.names g8305 g7265 g12538 +0- 1 +-0 1 +.names g12538 II21160 +0 1 +.names II21160 g14329 +0 1 +.names g10271 g10352 g10412 g12068 +000 1 +.names g12068 g14332 +0 1 +.names g10693 g2883 g7562 g10711 g13110 +1111 1 +.names g13110 II21165 +0 1 +.names II21165 g14337 +0 1 +.names g8517 g8532 g8546 g12967 +000 1 +.names g12967 g14342 +0 1 +.names g10281 g10361 g10422 g12079 +000 1 +.names g12079 g14347 +0 1 +.names g10287 g10366 g10433 g12081 +000 1 +.names g12081 g14352 +0 1 +.names g10290 g10368 g10435 g12082 +000 1 +.names g12082 g14355 +0 1 +.names g10293 g10371 g10438 g12083 +000 1 +.names g12083 g14359 +0 1 +.names g8520 g8535 g8548 g12968 +000 1 +.names g12968 g14360 +0 1 +.names g10297 g10373 g10439 g12090 +000 1 +.names g12090 g14366 +0 1 +.names g10302 g10379 g10444 g12098 +000 1 +.names g12098 g14371 +0 1 +.names g10305 g10382 g10446 g12099 +000 1 +.names g12099 g14374 +0 1 +.names g10307 g10385 g10449 g12100 +000 1 +.names g12100 g14378 +0 1 +.names g11749 II21178 +0 1 +.names II21178 g14381 +0 1 +.names g8523 g8538 g8551 g12970 +000 1 +.names g12970 g14385 +0 1 +.names g8526 g8541 g8554 g12971 +000 1 +.names g12971 g14390 +0 1 +.names g10312 g10389 g10451 g12107 +000 1 +.names g12107 g14395 +0 1 +.names g10314 g10392 g10454 g12108 +000 1 +.names g12108 g14402 +0 1 +.names g10321 g10397 g10460 g12112 +000 1 +.names g12112 g14408 +0 1 +.names g10322 g10399 g10463 g12113 +000 1 +.names g12113 g14412 +0 1 +.names g10324 g10402 g10466 g12114 +000 1 +.names g12114 g14413 +0 1 +.names g8529 g8544 g8557 g12978 +000 1 +.names g12978 g14414 +0 1 +.names g8305 g3774 g13165 +0- 1 +-0 1 +.names g13165 II21190 +0 1 +.names II21190 g14420 +0 1 +.names g10327 g10404 g10467 g12120 +000 1 +.names g12120 g14423 +0 1 +.names g10330 g10406 g10470 g12121 +000 1 +.names g12121 g14431 +0 1 +.names g10353 g10413 g10475 g12124 +000 1 +.names g12124 g14438 +0 1 +.names g9367 g9441 g9521 g11768 +000 1 +.names g11768 g14442 +0 1 +.names g10369 g10436 g10496 g12146 +000 1 +.names g12146 g14450 +0 1 +.names g8536 g8549 g8559 g12991 +000 1 +.names g12991 g14454 +0 1 +.names g10374 g10440 g10498 g12151 +000 1 +.names g12151 g14459 +0 1 +.names g10380 g10445 g10509 g12153 +000 1 +.names g12153 g14464 +0 1 +.names g10383 g10447 g10511 g12154 +000 1 +.names g12154 g14467 +0 1 +.names g10386 g10450 g10514 g12155 +000 1 +.names g12155 g14471 +0 1 +.names g8539 g8552 g8561 g12992 +000 1 +.names g12992 g14472 +0 1 +.names g10390 g10452 g10515 g12162 +000 1 +.names g12162 g14478 +0 1 +.names g10395 g10458 g10520 g12170 +000 1 +.names g12170 g14483 +0 1 +.names g10398 g10461 g10522 g12171 +000 1 +.names g12171 g14486 +0 1 +.names g10400 g10464 g10525 g12172 +000 1 +.names g12172 g14490 +0 1 +.names g11749 II21208 +0 1 +.names II21208 g14493 +0 1 +.names g8542 g8555 g8564 g12994 +000 1 +.names g12994 g14497 +0 1 +.names g8545 g8558 g8567 g12995 +000 1 +.names g12995 g14502 +0 1 +.names g10405 g10468 g10527 g12179 +000 1 +.names g12179 g14507 +0 1 +.names g10407 g10471 g10530 g12180 +000 1 +.names g12180 g14514 +0 1 +.names g10414 g10476 g10536 g12184 +000 1 +.names g12184 g14520 +0 1 +.names g10415 g10478 g10539 g12185 +000 1 +.names g12185 g14524 +0 1 +.names g10437 g10497 g10558 g12195 +000 1 +.names g12195 g14525 +0 1 +.names g9464 g9583 g9663 g11785 +000 1 +.names g11785 g14529 +0 1 +.names g10448 g10512 g10570 g12208 +000 1 +.names g12208 g14537 +0 1 +.names g8553 g8562 g8570 g13001 +000 1 +.names g13001 g14541 +0 1 +.names g10453 g10516 g10572 g12213 +000 1 +.names g12213 g14546 +0 1 +.names g10459 g10521 g10583 g12215 +000 1 +.names g12215 g14551 +0 1 +.names g10462 g10523 g10585 g12216 +000 1 +.names g12216 g14554 +0 1 +.names g10465 g10526 g10588 g12217 +000 1 +.names g12217 g14558 +0 1 +.names g8556 g8565 g8572 g13002 +000 1 +.names g13002 g14559 +0 1 +.names g10469 g10528 g10589 g12224 +000 1 +.names g12224 g14565 +0 1 +.names g10474 g10534 g10594 g12232 +000 1 +.names g12232 g14570 +0 1 +.names g10477 g10537 g10596 g12233 +000 1 +.names g12233 g14573 +0 1 +.names g10479 g10540 g10599 g12234 +000 1 +.names g12234 g14577 +0 1 +.names g10513 g10571 g10615 g12250 +000 1 +.names g12250 g14580 +0 1 +.names g9606 g9725 g9809 g11811 +000 1 +.names g11811 g14584 +0 1 +.names g10524 g10586 g10627 g12263 +000 1 +.names g12263 g14592 +0 1 +.names g8566 g8573 g8576 g13022 +000 1 +.names g13022 g14596 +0 1 +.names g10529 g10590 g10629 g12268 +000 1 +.names g12268 g14601 +0 1 +.names g10535 g10595 g10640 g12270 +000 1 +.names g12270 g14606 +0 1 +.names g10538 g10597 g10642 g12271 +000 1 +.names g12271 g14609 +0 1 +.names g10541 g10600 g10645 g12272 +000 1 +.names g12272 g14613 +0 1 +.names g10587 g10628 g10662 g12293 +000 1 +.names g12293 g14614 +0 1 +.names g9748 g9871 g9955 g11844 +000 1 +.names g11844 g14618 +0 1 +.names g10598 g10643 g10674 g12306 +000 1 +.names g12306 g14626 +0 1 +.names g9026 g9047 g9061 g13378 +000 1 +.names g13378 II21241 +0 1 +.names II21241 g14630 +0 1 +.names g10644 g10675 g10692 g12329 +000 1 +.names g12329 g14637 +0 1 +.names g9635 g9763 g9891 g11823 +000 1 +.names g11823 g14641 +0 1 +.names g9062 g9075 g9091 g11624 +000 1 +.names g11624 II21246 +0 1 +.names II21246 g14642 +0 1 +.names g9049 g9064 g9078 g11600 +000 1 +.names g11600 II21249 +0 1 +.names II21249 g14650 +0 1 +.names g9076 g9092 g9102 g11644 +000 1 +.names g11644 II21252 +0 1 +.names II21252 g14657 +0 1 +.names g9781 g9909 g10045 g11865 +000 1 +.names g11865 g14668 +0 1 +.names g9079 g9094 g9103 g11647 +000 1 +.names g11647 II21256 +0 1 +.names II21256 g14669 +0 1 +.names g9066 g9081 g9097 g11630 +000 1 +.names g11630 II21259 +0 1 +.names II21259 g14677 +0 1 +.names g11713 II21262 +0 1 +.names II21262 g14684 +0 1 +.names g10495 g10557 g10604 g12245 +000 1 +.names g12245 g14685 +0 1 +.names g9095 g9104 g9112 g11663 +000 1 +.names g11663 II21267 +0 1 +.names II21267 g14691 +0 1 +.names g9927 g10063 g10154 g11907 +000 1 +.names g11907 g14702 +0 1 +.names g9098 g9106 g9113 g11666 +000 1 +.names g11666 II21271 +0 1 +.names II21271 g14703 +0 1 +.names g9083 g9100 g9109 g11653 +000 1 +.names g11653 II21274 +0 1 +.names II21274 g14711 +0 1 +.names g12430 II21277 +0 1 +.names II21277 g14718 +0 1 +.names g10569 g10614 g10651 g12288 +000 1 +.names g12288 g14719 +0 1 +.names g9107 g9114 g9120 g11675 +000 1 +.names g11675 II21282 +0 1 +.names II21282 g14725 +0 1 +.names g10081 g10172 g10259 g11957 +000 1 +.names g11957 g14736 +0 1 +.names g9110 g9116 g9121 g11678 +000 1 +.names g11678 II21286 +0 1 +.names II21286 g14737 +0 1 +.names g12434 II21289 +0 1 +.names II21289 g14745 +0 1 +.names g11888 II21292 +0 1 +.names II21292 g14746 +0 1 +.names g10626 g10661 g10681 g12324 +000 1 +.names g12324 g14747 +0 1 +.names g9117 g9122 g9126 g11687 +000 1 +.names g11687 II21297 +0 1 +.names II21297 g14753 +0 1 +.names g11791 g14764 +0 1 +.names g12438 II21301 +0 1 +.names II21301 g14765 +0 1 +.names g11927 II21304 +0 1 +.names II21304 g14766 +0 1 +.names g10673 g10691 g10710 g12352 +000 1 +.names g12352 g14768 +0 1 +.names g12332 II21310 +0 1 +.names II21310 g14774 +0 1 +.names g11743 II21313 +0 1 +.names II21313 g14775 +0 1 +.names g10199 g10284 g10362 g12033 +000 1 +.names g12033 g14776 +0 1 +.names g11848 g14794 +0 1 +.names g12362 II21318 +0 1 +.names II21318 g14795 +0 1 +.names g11758 II21321 +0 1 +.names II21321 g14796 +0 1 +.names g10285 g10363 g10430 g12080 +000 1 +.names g12080 g14797 +0 1 +.names g10301 g10377 g10441 g12097 +000 1 +.names g12097 g14811 +0 1 +.names g12378 II21326 +0 1 +.names II21326 g14829 +0 1 +.names g11766 II21329 +0 1 +.names II21329 g14830 +0 1 +.names g9639 g9764 g9892 g11828 +000 1 +.names g11828 g14831 +0 1 +.names g10364 g10431 g10492 g12145 +000 1 +.names g12145 g14837 +0 1 +.names g10378 g10442 g10506 g12152 +000 1 +.names g12152 g14849 +0 1 +.names g10394 g10456 g10517 g12169 +000 1 +.names g12169 g14863 +0 1 +.names g11923 g14881 +0 1 +.names g12408 II21337 +0 1 +.names II21337 g14882 +0 1 +.names g11779 II21340 +0 1 +.names II21340 g14883 +0 1 +.names g9765 g9893 g10012 g11860 +000 1 +.names g11860 g14885 +0 1 +.names g10432 g10493 g10555 g12193 +000 1 +.names g12193 g14895 +0 1 +.names g9785 g9910 g10046 g11870 +000 1 +.names g11870 g14904 +0 1 +.names g10443 g10507 g10566 g12207 +000 1 +.names g12207 g14910 +0 1 +.names g10457 g10518 g10580 g12214 +000 1 +.names g12214 g14922 +0 1 +.names g10473 g10532 g10591 g12231 +000 1 +.names g12231 g14936 +0 1 +.names g12420 II21351 +0 1 +.names II21351 g14954 +0 1 +.names g11798 II21354 +0 1 +.names II21354 g14955 +0 1 +.names g11976 g14959 +0 1 +.names g9534 g6678 g13026 +0- 1 +-0 1 +.names g13026 II21361 +0 1 +.names II21361 g14960 +0 1 +.names g9534 g6678 g13028 +0- 1 +-0 1 +.names g13028 II21364 +0 1 +.names II21364 g14963 +0 1 +.names g9911 g10047 g10121 g11902 +000 1 +.names g11902 g14966 +0 1 +.names g10508 g10567 g10612 g12248 +000 1 +.names g12248 g14976 +0 1 +.names g9931 g10064 g10155 g11912 +000 1 +.names g11912 g14985 +0 1 +.names g10519 g10581 g10623 g12262 +000 1 +.names g12262 g14991 +0 1 +.names g10533 g10592 g10637 g12269 +000 1 +.names g12269 g15003 +0 1 +.names g12009 g15017 +0 1 +.names g12424 II21374 +0 1 +.names II21374 g15018 +0 1 +.names g11821 II21377 +0 1 +.names II21377 g15019 +0 1 +.names g13157 II21381 +0 1 +.names II21381 g15021 +0 1 +.names g9442 g9522 g9633 g11781 +000 1 +.names g11781 g15022 +0 1 +.names g12027 g15032 +0 1 +.names g12030 g15033 +0 1 +.names g10038 g6284 g12883 +00 1 +.names g12883 II21389 +0 1 +.names II21389 g15034 +0 1 +.names g9534 g6912 g13020 +0- 1 +-0 1 +.names g13020 II21392 +0 1 +.names II21392 g15037 +0 1 +.names g9534 g6678 g13034 +0- 1 +-0 1 +.names g13034 II21395 +0 1 +.names II21395 g15040 +0 1 +.names g9534 g6912 g13021 +0- 1 +-0 1 +.names g13021 II21398 +0 1 +.names II21398 g15043 +0 1 +.names g12045 g15048 +0 1 +.names g9676 g6980 g13037 +0- 1 +-0 1 +.names g13037 II21404 +0 1 +.names II21404 g15049 +0 1 +.names g9676 g6980 g13039 +0- 1 +-0 1 +.names g13039 II21407 +0 1 +.names II21407 g15052 +0 1 +.names g10065 g10156 g10226 g11952 +000 1 +.names g11952 g15055 +0 1 +.names g10582 g10624 g10659 g12291 +000 1 +.names g12291 g15065 +0 1 +.names g10085 g10173 g10260 g11962 +000 1 +.names g11962 g15074 +0 1 +.names g10593 g10638 g10670 g12305 +000 1 +.names g12305 g15080 +0 1 +.names g11854 II21415 +0 1 +.names II21415 g15092 +0 1 +.names g13166 II21420 +0 1 +.names II21420 g15095 +0 1 +.names g9523 g9634 g9762 g11800 +000 1 +.names g11800 g15096 +0 1 +.names g9534 g3366 g11661 +0- 1 +-0 1 +.names g11661 II21426 +0 1 +.names II21426 g15106 +0 1 +.names g9534 g6912 g13027 +0- 1 +-0 1 +.names g13027 II21429 +0 1 +.names II21429 g15109 +0 1 +.names g9534 g6678 g13044 +0- 1 +-0 1 +.names g13044 II21432 +0 1 +.names II21432 g15112 +0 1 +.names g9534 g3366 g11662 +0- 1 +-0 1 +.names g11662 II21435 +0 1 +.names II21435 g15115 +0 1 +.names g9584 g9664 g9779 g11807 +000 1 +.names g11807 g15118 +0 1 +.names g12091 g15128 +0 1 +.names g12094 g15129 +0 1 +.names g10147 g6421 g12923 +00 1 +.names g12923 II21443 +0 1 +.names II21443 g15130 +0 1 +.names g9676 g7162 g13029 +0- 1 +-0 1 +.names g13029 II21446 +0 1 +.names II21446 g15133 +0 1 +.names g9676 g6980 g13047 +0- 1 +-0 1 +.names g13047 II21449 +0 1 +.names II21449 g15136 +0 1 +.names g9676 g7162 g13030 +0- 1 +-0 1 +.names g13030 II21452 +0 1 +.names II21452 g15139 +0 1 +.names g12109 g15144 +0 1 +.names g9822 g7230 g13050 +0- 1 +-0 1 +.names g13050 II21458 +0 1 +.names II21458 g15145 +0 1 +.names g9822 g7230 g13052 +0- 1 +-0 1 +.names g13052 II21461 +0 1 +.names II21461 g15148 +0 1 +.names g10174 g10261 g10328 g12005 +000 1 +.names g12005 g15151 +0 1 +.names g10639 g10671 g10689 g12327 +000 1 +.names g12327 g15161 +0 1 +.names g12125 g15170 +0 1 +.names g12136 g15174 +0 1 +.names g12139 g15175 +0 1 +.names g12142 g15176 +0 1 +.names g10650 g10678 g10704 g12339 +000 1 +.names g12339 g15177 +0 1 +.names g9534 g3366 g11672 +0- 1 +-0 1 +.names g11672 II21476 +0 1 +.names II21476 g15179 +0 1 +.names g9534 g6912 g13035 +0- 1 +-0 1 +.names g13035 II21479 +0 1 +.names II21479 g15182 +0 1 +.names g9534 g6678 g13058 +0- 1 +-0 1 +.names g13058 II21482 +0 1 +.names II21482 g15185 +0 1 +.names g9665 g9780 g9908 g11833 +000 1 +.names g11833 g15188 +0 1 +.names g9676 g3522 g11673 +0- 1 +-0 1 +.names g11673 II21488 +0 1 +.names II21488 g15198 +0 1 +.names g9676 g7162 g13038 +0- 1 +-0 1 +.names g13038 II21491 +0 1 +.names II21491 g15201 +0 1 +.names g9676 g6980 g13061 +0- 1 +-0 1 +.names g13061 II21494 +0 1 +.names II21494 g15204 +0 1 +.names g9676 g3522 g11674 +0- 1 +-0 1 +.names g11674 II21497 +0 1 +.names II21497 g15207 +0 1 +.names g9726 g9810 g9925 g11840 +000 1 +.names g11840 g15210 +0 1 +.names g12163 g15220 +0 1 +.names g12166 g15221 +0 1 +.names g10252 g6626 g12952 +00 1 +.names g12952 II21505 +0 1 +.names II21505 g15222 +0 1 +.names g9822 g7358 g13040 +0- 1 +-0 1 +.names g13040 II21508 +0 1 +.names II21508 g15225 +0 1 +.names g9822 g7230 g13064 +0- 1 +-0 1 +.names g13064 II21511 +0 1 +.names II21511 g15228 +0 1 +.names g9822 g7358 g13041 +0- 1 +-0 1 +.names g13041 II21514 +0 1 +.names II21514 g15231 +0 1 +.names g12181 g15236 +0 1 +.names g9968 g7426 g13067 +0- 1 +-0 1 +.names g13067 II21520 +0 1 +.names II21520 g15237 +0 1 +.names g9968 g7426 g13069 +0- 1 +-0 1 +.names g13069 II21523 +0 1 +.names II21523 g15240 +0 1 +.names g9534 g3366 g11683 +0- 1 +-0 1 +.names g11683 II21531 +0 1 +.names II21531 g15248 +0 1 +.names g9534 g6912 g13045 +0- 1 +-0 1 +.names g13045 II21534 +0 1 +.names II21534 g15251 +0 1 +.names g9534 g6678 g13071 +0- 1 +-0 1 +.names g13071 II21537 +0 1 +.names II21537 g15254 +0 1 +.names g12198 g15260 +0 1 +.names g12201 g15261 +0 1 +.names g12204 g15262 +0 1 +.names g10680 g10707 g10724 g12369 +000 1 +.names g12369 g15263 +0 1 +.names g9676 g3522 g11684 +0- 1 +-0 1 +.names g11684 II21548 +0 1 +.names II21548 g15265 +0 1 +.names g9676 g7162 g13048 +0- 1 +-0 1 +.names g13048 II21551 +0 1 +.names II21551 g15268 +0 1 +.names g9676 g6980 g13074 +0- 1 +-0 1 +.names g13074 II21554 +0 1 +.names II21554 g15271 +0 1 +.names g9811 g9926 g10062 g11875 +000 1 +.names g11875 g15274 +0 1 +.names g9822 g3678 g11685 +0- 1 +-0 1 +.names g11685 II21560 +0 1 +.names II21560 g15284 +0 1 +.names g9822 g7358 g13051 +0- 1 +-0 1 +.names g13051 II21563 +0 1 +.names II21563 g15287 +0 1 +.names g9822 g7230 g13077 +0- 1 +-0 1 +.names g13077 II21566 +0 1 +.names II21566 g15290 +0 1 +.names g9822 g3678 g11686 +0- 1 +-0 1 +.names g11686 II21569 +0 1 +.names II21569 g15293 +0 1 +.names g9872 g9956 g10079 g11882 +000 1 +.names g11882 g15296 +0 1 +.names g12225 g15306 +0 1 +.names g12228 g15307 +0 1 +.names g10354 g6890 g12981 +00 1 +.names g12981 II21577 +0 1 +.names II21577 g15308 +0 1 +.names g9968 g7488 g13053 +0- 1 +-0 1 +.names g13053 II21580 +0 1 +.names II21580 g15311 +0 1 +.names g9968 g7426 g13080 +0- 1 +-0 1 +.names g13080 II21583 +0 1 +.names II21583 g15314 +0 1 +.names g9968 g7488 g13054 +0- 1 +-0 1 +.names g13054 II21586 +0 1 +.names II21586 g15317 +0 1 +.names g12239 g15322 +0 1 +.names g12242 g15323 +0 1 +.names g9534 g3366 g11691 +0- 1 +-0 1 +.names g11691 II21595 +0 1 +.names II21595 g15326 +0 1 +.names g9534 g6912 g13059 +0- 1 +-0 1 +.names g13059 II21598 +0 1 +.names II21598 g15329 +0 1 +.names g9534 g6678 g13087 +0- 1 +-0 1 +.names g13087 II21601 +0 1 +.names II21601 g15332 +0 1 +.names g9676 g3522 g11692 +0- 1 +-0 1 +.names g11692 II21609 +0 1 +.names II21609 g15340 +0 1 +.names g9676 g7162 g13062 +0- 1 +-0 1 +.names g13062 II21612 +0 1 +.names II21612 g15343 +0 1 +.names g9676 g6980 g13090 +0- 1 +-0 1 +.names g13090 II21615 +0 1 +.names II21615 g15346 +0 1 +.names g12253 g15352 +0 1 +.names g12256 g15353 +0 1 +.names g12259 g15354 +0 1 +.names g10709 g10727 g10745 g12388 +000 1 +.names g12388 g15355 +0 1 +.names g9822 g3678 g11693 +0- 1 +-0 1 +.names g11693 II21626 +0 1 +.names II21626 g15357 +0 1 +.names g9822 g7358 g13065 +0- 1 +-0 1 +.names g13065 II21629 +0 1 +.names II21629 g15360 +0 1 +.names g9822 g7230 g13093 +0- 1 +-0 1 +.names g13093 II21632 +0 1 +.names II21632 g15363 +0 1 +.names g9957 g10080 g10171 g11917 +000 1 +.names g11917 g15366 +0 1 +.names g9968 g3834 g11694 +0- 1 +-0 1 +.names g11694 II21638 +0 1 +.names II21638 g15376 +0 1 +.names g9968 g7488 g13068 +0- 1 +-0 1 +.names g13068 II21641 +0 1 +.names II21641 g15379 +0 1 +.names g9968 g7426 g13096 +0- 1 +-0 1 +.names g13096 II21644 +0 1 +.names II21644 g15382 +0 1 +.names g9968 g3834 g11695 +0- 1 +-0 1 +.names g11695 II21647 +0 1 +.names II21647 g15385 +0 1 +.names g12279 g15390 +0 1 +.names g9534 g3366 g11696 +0- 1 +-0 1 +.names g11696 II21655 +0 1 +.names II21655 g15393 +0 1 +.names g9534 g6912 g13072 +0- 1 +-0 1 +.names g13072 II21658 +0 1 +.names II21658 g15396 +0 1 +.names g9534 g6678 g13098 +0- 1 +-0 1 +.names g13098 II21661 +0 1 +.names II21661 g15399 +0 1 +.names g9534 g6678 g13100 +0- 1 +-0 1 +.names g13100 II21666 +0 1 +.names II21666 g15404 +0 1 +.names g12282 g15408 +0 1 +.names g12285 g15409 +0 1 +.names g9676 g3522 g11698 +0- 1 +-0 1 +.names g11698 II21674 +0 1 +.names II21674 g15412 +0 1 +.names g9676 g7162 g13075 +0- 1 +-0 1 +.names g13075 II21677 +0 1 +.names II21677 g15415 +0 1 +.names g9676 g6980 g13102 +0- 1 +-0 1 +.names g13102 II21680 +0 1 +.names II21680 g15418 +0 1 +.names g9822 g3678 g11699 +0- 1 +-0 1 +.names g11699 II21688 +0 1 +.names II21688 g15426 +0 1 +.names g9822 g7358 g13078 +0- 1 +-0 1 +.names g13078 II21691 +0 1 +.names II21691 g15429 +0 1 +.names g9822 g7230 g13105 +0- 1 +-0 1 +.names g13105 II21694 +0 1 +.names II21694 g15432 +0 1 +.names g12296 g15438 +0 1 +.names g12299 g15439 +0 1 +.names g12302 g15440 +0 1 +.names g10729 g10748 g10764 g12418 +000 1 +.names g12418 g15441 +0 1 +.names g9968 g3834 g11700 +0- 1 +-0 1 +.names g11700 II21705 +0 1 +.names II21705 g15443 +0 1 +.names g9968 g7488 g13081 +0- 1 +-0 1 +.names g13081 II21708 +0 1 +.names II21708 g15446 +0 1 +.names g9968 g7426 g13108 +0- 1 +-0 1 +.names g13108 II21711 +0 1 +.names II21711 g15449 +0 1 +.names g12312 g15458 +0 1 +.names g9534 g3366 g11701 +0- 1 +-0 1 +.names g11701 II21720 +0 1 +.names II21720 g15461 +0 1 +.names g9534 g6912 g13088 +0- 1 +-0 1 +.names g13088 II21723 +0 1 +.names II21723 g15464 +0 1 +.names g9534 g6678 g13112 +0- 1 +-0 1 +.names g13112 II21726 +0 1 +.names II21726 g15467 +0 1 +.names g9534 g6912 g13089 +0- 1 +-0 1 +.names g13089 II21730 +0 1 +.names II21730 g15471 +0 1 +.names g12315 g15474 +0 1 +.names g9676 g3522 g11702 +0- 1 +-0 1 +.names g11702 II21736 +0 1 +.names II21736 g15477 +0 1 +.names g9676 g7162 g13091 +0- 1 +-0 1 +.names g13091 II21739 +0 1 +.names II21739 g15480 +0 1 +.names g9676 g6980 g13114 +0- 1 +-0 1 +.names g13114 II21742 +0 1 +.names II21742 g15483 +0 1 +.names g9676 g6980 g13116 +0- 1 +-0 1 +.names g13116 II21747 +0 1 +.names II21747 g15488 +0 1 +.names g12318 g15492 +0 1 +.names g12321 g15493 +0 1 +.names g9822 g3678 g11704 +0- 1 +-0 1 +.names g11704 II21755 +0 1 +.names II21755 g15496 +0 1 +.names g9822 g7358 g13094 +0- 1 +-0 1 +.names g13094 II21758 +0 1 +.names II21758 g15499 +0 1 +.names g9822 g7230 g13118 +0- 1 +-0 1 +.names g13118 II21761 +0 1 +.names II21761 g15502 +0 1 +.names g9968 g3834 g11705 +0- 1 +-0 1 +.names g11705 II21769 +0 1 +.names II21769 g15510 +0 1 +.names g9968 g7488 g13097 +0- 1 +-0 1 +.names g13097 II21772 +0 1 +.names II21772 g15513 +0 1 +.names g9968 g7426 g13121 +0- 1 +-0 1 +.names g13121 II21775 +0 1 +.names II21775 g15516 +0 1 +.names g8317 g2993 g13305 +0- 1 +-0 1 +.names g13305 II21780 +0 1 +.names II21780 g15521 +0 1 +.names g12333 g15524 +0 1 +.names g12336 g15525 +0 1 +.names g9534 g3366 g11707 +0- 1 +-0 1 +.names g11707 II21787 +0 1 +.names II21787 g15528 +0 1 +.names g9534 g6912 g13099 +0- 1 +-0 1 +.names g13099 II21790 +0 1 +.names II21790 g15531 +0 1 +.names g9534 g6678 g13123 +0- 1 +-0 1 +.names g13123 II21793 +0 1 +.names II21793 g15534 +0 1 +.names g9534 g3366 g11708 +0- 1 +-0 1 +.names g11708 II21796 +0 1 +.names II21796 g15537 +0 1 +.names g12340 g15544 +0 1 +.names g9676 g3522 g11709 +0- 1 +-0 1 +.names g11709 II21803 +0 1 +.names II21803 g15547 +0 1 +.names g9676 g7162 g13103 +0- 1 +-0 1 +.names g13103 II21806 +0 1 +.names II21806 g15550 +0 1 +.names g9676 g6980 g13125 +0- 1 +-0 1 +.names g13125 II21809 +0 1 +.names II21809 g15553 +0 1 +.names g9676 g7162 g13104 +0- 1 +-0 1 +.names g13104 II21813 +0 1 +.names II21813 g15557 +0 1 +.names g12343 g15560 +0 1 +.names g9822 g3678 g11710 +0- 1 +-0 1 +.names g11710 II21819 +0 1 +.names II21819 g15563 +0 1 +.names g9822 g7358 g13106 +0- 1 +-0 1 +.names g13106 II21822 +0 1 +.names II21822 g15566 +0 1 +.names g9822 g7230 g13127 +0- 1 +-0 1 +.names g13127 II21825 +0 1 +.names II21825 g15569 +0 1 +.names g9822 g7230 g13129 +0- 1 +-0 1 +.names g13129 II21830 +0 1 +.names II21830 g15574 +0 1 +.names g12346 g15578 +0 1 +.names g12349 g15579 +0 1 +.names g9968 g3834 g11712 +0- 1 +-0 1 +.names g11712 II21838 +0 1 +.names II21838 g15582 +0 1 +.names g9968 g7488 g13109 +0- 1 +-0 1 +.names g13109 II21841 +0 1 +.names II21841 g15585 +0 1 +.names g9968 g7426 g13131 +0- 1 +-0 1 +.names g13131 II21844 +0 1 +.names II21844 g15588 +0 1 +.names g9534 g3366 g11716 +0- 1 +-0 1 +.names g11716 II21852 +0 1 +.names II21852 g15596 +0 1 +.names g9534 g6912 g13113 +0- 1 +-0 1 +.names g13113 II21855 +0 1 +.names II21855 g15599 +0 1 +.names g12363 g15602 +0 1 +.names g12366 g15603 +0 1 +.names g9676 g3522 g11717 +0- 1 +-0 1 +.names g11717 II21862 +0 1 +.names II21862 g15606 +0 1 +.names g9676 g7162 g13115 +0- 1 +-0 1 +.names g13115 II21865 +0 1 +.names II21865 g15609 +0 1 +.names g9676 g6980 g13134 +0- 1 +-0 1 +.names g13134 II21868 +0 1 +.names II21868 g15612 +0 1 +.names g9676 g3522 g11718 +0- 1 +-0 1 +.names g11718 II21871 +0 1 +.names II21871 g15615 +0 1 +.names g12370 g15622 +0 1 +.names g9822 g3678 g11719 +0- 1 +-0 1 +.names g11719 II21878 +0 1 +.names II21878 g15625 +0 1 +.names g9822 g7358 g13119 +0- 1 +-0 1 +.names g13119 II21881 +0 1 +.names II21881 g15628 +0 1 +.names g9822 g7230 g13136 +0- 1 +-0 1 +.names g13136 II21884 +0 1 +.names II21884 g15631 +0 1 +.names g9822 g7358 g13120 +0- 1 +-0 1 +.names g13120 II21888 +0 1 +.names II21888 g15635 +0 1 +.names g12373 g15638 +0 1 +.names g9968 g3834 g11720 +0- 1 +-0 1 +.names g11720 II21894 +0 1 +.names II21894 g15641 +0 1 +.names g9968 g7488 g13122 +0- 1 +-0 1 +.names g13122 II21897 +0 1 +.names II21897 g15644 +0 1 +.names g9968 g7426 g13138 +0- 1 +-0 1 +.names g13138 II21900 +0 1 +.names II21900 g15647 +0 1 +.names g9968 g7426 g13140 +0- 1 +-0 1 +.names g13140 II21905 +0 1 +.names II21905 g15652 +0 1 +.names II20131 II20132 g13082 +11 1 +.names g13082 II21908 +0 1 +.names II21908 g15655 +0 1 +.names g11706 g15659 +0 1 +.names g12379 g15665 +0 1 +.names g9534 g3366 g11721 +0- 1 +-0 1 +.names g11721 II21918 +0 1 +.names II21918 g15667 +0 1 +.names g9676 g3522 g11722 +0- 1 +-0 1 +.names g11722 II21923 +0 1 +.names II21923 g15672 +0 1 +.names g9676 g7162 g13126 +0- 1 +-0 1 +.names g13126 II21926 +0 1 +.names II21926 g15675 +0 1 +.names g12382 g15678 +0 1 +.names g12385 g15679 +0 1 +.names g9822 g3678 g11723 +0- 1 +-0 1 +.names g11723 II21933 +0 1 +.names II21933 g15682 +0 1 +.names g9822 g7358 g13128 +0- 1 +-0 1 +.names g13128 II21936 +0 1 +.names II21936 g15685 +0 1 +.names g9822 g7230 g13142 +0- 1 +-0 1 +.names g13142 II21939 +0 1 +.names II21939 g15688 +0 1 +.names g9822 g3678 g11724 +0- 1 +-0 1 +.names g11724 II21942 +0 1 +.names II21942 g15691 +0 1 +.names g12389 g15698 +0 1 +.names g9968 g3834 g11725 +0- 1 +-0 1 +.names g11725 II21949 +0 1 +.names II21949 g15701 +0 1 +.names g9968 g7488 g13132 +0- 1 +-0 1 +.names g13132 II21952 +0 1 +.names II21952 g15704 +0 1 +.names g9968 g7426 g13144 +0- 1 +-0 1 +.names g13144 II21955 +0 1 +.names II21955 g15707 +0 1 +.names g9968 g7488 g13133 +0- 1 +-0 1 +.names g13133 II21959 +0 1 +.names II21959 g15711 +0 1 +.names g10186 g8317 g13004 +11 1 +.names g13004 II21962 +0 1 +.names II21962 g15714 +0 1 +.names g13011 g15722 +0 1 +.names g12409 g15724 +0 1 +.names g9676 g3522 g11726 +0- 1 +-0 1 +.names g11726 II21974 +0 1 +.names II21974 g15726 +0 1 +.names g9822 g3678 g11727 +0- 1 +-0 1 +.names g11727 II21979 +0 1 +.names II21979 g15731 +0 1 +.names g9822 g7358 g13137 +0- 1 +-0 1 +.names g13137 II21982 +0 1 +.names II21982 g15734 +0 1 +.names g12412 g15737 +0 1 +.names g12415 g15738 +0 1 +.names g9968 g3834 g11728 +0- 1 +-0 1 +.names g11728 II21989 +0 1 +.names II21989 g15741 +0 1 +.names g9968 g7488 g13139 +0- 1 +-0 1 +.names g13139 II21992 +0 1 +.names II21992 g15744 +0 1 +.names g9968 g7426 g13146 +0- 1 +-0 1 +.names g13146 II21995 +0 1 +.names II21995 g15747 +0 1 +.names g9968 g3834 g11729 +0- 1 +-0 1 +.names g11729 II21998 +0 1 +.names II21998 g15750 +0 1 +.names g13011 g15762 +0 1 +.names g12421 g15764 +0 1 +.names g9822 g3678 g11730 +0- 1 +-0 1 +.names g11730 II22014 +0 1 +.names II22014 g15766 +0 1 +.names g9968 g3834 g11731 +0- 1 +-0 1 +.names g11731 II22019 +0 1 +.names II22019 g15771 +0 1 +.names g9968 g7488 g13145 +0- 1 +-0 1 +.names g13145 II22022 +0 1 +.names II22022 g15774 +0 1 +.names g8313 g2883 g11617 +0- 1 +-0 1 +.names g11617 II22025 +0 1 +.names II22025 g15777 +0 1 +.names g13011 g15790 +0 1 +.names g12426 g15792 +0 1 +.names g9968 g3834 g11733 +0- 1 +-0 1 +.names g11733 II22044 +0 1 +.names II22044 g15794 +0 1 +.names g12909 g15800 +0 1 +.names g13011 g15813 +0 1 +.names g13378 g15859 +0 1 +.names g12909 II22120 +0 1 +.names II22120 g15876 +0 1 +.names g11624 g15880 +0 1 +.names g11600 g15890 +0 1 +.names g11644 g15904 +0 1 +.names g11647 g15913 +0 1 +.names g11630 g15923 +0 1 +.names g11663 g15933 +0 1 +.names g11666 g15942 +0 1 +.names g11653 g15952 +0 1 +.names g11675 g15962 +0 1 +.names g11678 g15971 +0 1 +.names g11687 g15981 +0 1 +.names g2879 g10778 g12433 +0- 1 +-0 1 +.names g12433 II22163 +0 1 +.names II22163 g15989 +0 1 +.names g12548 g15991 +0 1 +.names g12555 g15994 +0 1 +.names g12561 g15997 +0 1 +.names g12601 g16001 +0 1 +.names g12604 g16002 +0 1 +.names g12608 g16005 +0 1 +.names g12647 g16007 +0 1 +.names g12651 g16011 +0 1 +.names g12654 g16012 +0 1 +.names g12692 g16013 +0 1 +.names g12695 g16014 +0 1 +.names g12699 g16023 +0 1 +.names g12702 g16024 +0 1 +.names g12705 g16025 +0 1 +.names g12708 g16026 +0 1 +.names g12744 g16027 +0 1 +.names g12749 g16034 +0 1 +.names g12752 g16035 +0 1 +.names g12756 g16039 +0 1 +.names g12759 g16040 +0 1 +.names g12762 g16041 +0 1 +.names g12765 g16042 +0 1 +.names g12769 g16043 +0 1 +.names g12772 g16044 +0 1 +.names g12783 g16054 +0 1 +.names g12786 g16055 +0 1 +.names g12791 g16056 +0 1 +.names g12794 g16057 +0 1 +.names g12798 g16061 +0 1 +.names g12801 g16062 +0 1 +.names g12804 g16063 +0 1 +.names g12808 g16064 +0 1 +.names g12811 g16065 +0 1 +.names g9766 g9894 g10013 g11861 +000 1 +.names g11861 g16075 +0 1 +.names g12816 g16088 +0 1 +.names g12822 g16090 +0 1 +.names g12825 g16091 +0 1 +.names g12830 g16092 +0 1 +.names g12833 g16093 +0 1 +.names g12837 g16097 +0 1 +.names g12840 g16098 +0 1 +.names g12844 g16099 +0 1 +.names g9912 g10048 g10122 g11903 +000 1 +.names g11903 g16113 +0 1 +.names g12854 g16126 +0 1 +.names g12860 g16128 +0 1 +.names g12863 g16129 +0 1 +.names g12868 g16130 +0 1 +.names g12871 g16131 +0 1 +.names g13057 g16142 +0 1 +.names g10434 g10494 g10556 g12194 +000 1 +.names g12194 g16154 +0 1 +.names g10066 g10157 g10227 g11953 +000 1 +.names g11953 g16164 +0 1 +.names g12895 g16177 +0 1 +.names g12901 g16179 +0 1 +.names g12904 g16180 +0 1 +.names g13043 g16189 +0 1 +.names g13073 g16201 +0 1 +.names g10510 g10568 g10613 g12249 +000 1 +.names g12249 g16213 +0 1 +.names g10175 g10262 g10329 g12006 +000 1 +.names g12006 g16223 +0 1 +.names g12935 g16236 +0 1 +.names g13033 g16243 +0 1 +.names g13060 g16254 +0 1 +.names g13092 g16266 +0 1 +.names g10584 g10625 g10660 g12292 +000 1 +.names g12292 g16278 +0 1 +.names g12962 g16287 +0 1 +.names g13025 g16293 +0 1 +.names g520 II22382 +0 1 +.names g13046 g16302 +0 1 +.names g13076 g16313 +0 1 +.names g13107 g16325 +0 1 +.names g10641 g10672 g10690 g12328 +000 1 +.names g12328 g16337 +0 1 +.names g13036 g16351 +0 1 +.names g1206 II22414 +0 1 +.names g13063 g16360 +0 1 +.names g13095 g16371 +0 1 +.names g13049 g16395 +0 1 +.names g1900 II22444 +0 1 +.names g13079 g16404 +0 1 +.names g13066 g16433 +0 1 +.names g2594 II22475 +0 1 +.names g12017 g16466 +0 1 +.names g13598 II22503 +0 1 +.names g13624 II22506 +0 1 +.names g13610 II22509 +0 1 +.names g13635 II22512 +0 1 +.names g13620 II22515 +0 1 +.names g13647 II22518 +0 1 +.names g13632 II22521 +0 1 +.names g13673 II22524 +0 1 +.names g13469 II22527 +0 1 +.names g14774 II22530 +0 1 +.names g14795 II22533 +0 1 +.names g14829 II22536 +0 1 +.names g14882 II22539 +0 1 +.names g14954 II22542 +0 1 +.names g15018 II22545 +0 1 +.names g14718 II22548 +0 1 +.names g14745 II22551 +0 1 +.names g14765 II22554 +0 1 +.names g14775 II22557 +0 1 +.names g14796 II22560 +0 1 +.names g14830 II22563 +0 1 +.names g14883 II22566 +0 1 +.names g14955 II22569 +0 1 +.names g15019 II22572 +0 1 +.names g15092 II22575 +0 1 +.names g14746 II22578 +0 1 +.names g14766 II22581 +0 1 +.names g15989 II22584 +0 1 +.names g14684 II22587 +0 1 +.names g13863 II22590 +0 1 +.names g15876 II22593 +0 1 +.names g14158 g16501 +0 1 +.names g14966 II22599 +0 1 +.names II22599 g16506 +0 1 +.names g14186 g16507 +0 1 +.names g15080 II22604 +0 1 +.names II22604 g16514 +0 1 +.names g14244 g16515 +0 1 +.names g14273 g16523 +0 1 +.names g15055 II22611 +0 1 +.names II22611 g16528 +0 1 +.names g14301 g16529 +0 1 +.names g14630 II22618 +0 1 +.names II22618 g16540 +0 1 +.names g14347 g16543 +0 1 +.names g14366 g16546 +0 1 +.names g14395 g16554 +0 1 +.names g15151 II22626 +0 1 +.names II22626 g16559 +0 1 +.names g14423 g16560 +0 1 +.names g14650 II22640 +0 1 +.names II22640 g16572 +0 1 +.names g14459 g16575 +0 1 +.names g14478 g16578 +0 1 +.names g14507 g16586 +0 1 +.names g14677 II22651 +0 1 +.names II22651 g16596 +0 1 +.names g14546 g16599 +0 1 +.names g14565 g16602 +0 1 +.names g14657 II22657 +0 1 +.names II22657 g16608 +0 1 +.names g14711 II22663 +0 1 +.names II22663 g16616 +0 1 +.names g14601 g16619 +0 1 +.names g14642 II22667 +0 1 +.names II22667 g16622 +0 1 +.names g14691 II22671 +0 1 +.names II22671 g16626 +0 1 +.names g14630 II22676 +0 1 +.names II22676 g16633 +0 1 +.names g14669 II22679 +0 1 +.names II22679 g16636 +0 1 +.names g14725 II22683 +0 1 +.names II22683 g16640 +0 1 +.names g14650 II22687 +0 1 +.names II22687 g16644 +0 1 +.names g14703 II22690 +0 1 +.names II22690 g16647 +0 1 +.names g14753 II22694 +0 1 +.names II22694 g16651 +0 1 +.names g14677 II22699 +0 1 +.names II22699 g16656 +0 1 +.names g14737 II22702 +0 1 +.names II22702 g16659 +0 1 +.names g14776 g16665 +0 1 +.names g14711 II22715 +0 1 +.names II22715 g16673 +0 1 +.names g14657 II22718 +0 1 +.names II22718 g16676 +0 1 +.names g14797 g16682 +0 1 +.names g14811 g16686 +0 1 +.names g14642 II22726 +0 1 +.names II22726 g16694 +0 1 +.names g14837 g16697 +0 1 +.names g14691 II22730 +0 1 +.names II22730 g16702 +0 1 +.names g14849 g16708 +0 1 +.names g14863 g16712 +0 1 +.names g14630 II22737 +0 1 +.names II22737 g16719 +0 1 +.names g14895 g16722 +0 1 +.names g14669 II22741 +0 1 +.names II22741 g16725 +0 1 +.names g14910 g16728 +0 1 +.names g14725 II22745 +0 1 +.names II22745 g16733 +0 1 +.names g14922 g16739 +0 1 +.names g14936 g16743 +0 1 +.names g13332 g12354 g15782 +0- 1 +-0 1 +.names g15782 g16749 +0 1 +.names g14657 II22752 +0 1 +.names II22752 g16758 +0 1 +.names g14650 II22755 +0 1 +.names II22755 g16761 +0 1 +.names g14976 g16764 +0 1 +.names g14703 II22759 +0 1 +.names II22759 g16767 +0 1 +.names g14991 g16770 +0 1 +.names g14753 II22763 +0 1 +.names II22763 g16775 +0 1 +.names g15003 g16781 +0 1 +.names g14691 II22768 +0 1 +.names II22768 g16785 +0 1 +.names g14677 II22771 +0 1 +.names II22771 g16788 +0 1 +.names g15065 g16791 +0 1 +.names g14737 II22775 +0 1 +.names II22775 g16794 +0 1 +.names g15080 g16797 +0 1 +.names g13375 g12354 g15803 +0- 1 +-0 1 +.names g15803 g16804 +0 1 +.names g13332 g12392 g15842 +0- 1 +-0 1 +.names g15842 g16809 +0 1 +.names g13572 II22783 +0 1 +.names II22783 g16813 +0 1 +.names g14725 II22786 +0 1 +.names II22786 g16814 +0 1 +.names g14711 II22789 +0 1 +.names II22789 g16817 +0 1 +.names g15161 g16820 +0 1 +.names g13354 g12392 g15855 +0- 1 +-0 1 +.names g15855 g16825 +0 1 +.names g14165 II22797 +0 1 +.names II22797 g16830 +0 1 +.names g13581 II22800 +0 1 +.names II22800 g16831 +0 1 +.names g14753 II22803 +0 1 +.names II22803 g16832 +0 1 +.names g13024 g12354 g15818 +0- 1 +-0 1 +.names g15818 g16836 +0 1 +.names g13375 g12392 g15878 +0- 1 +-0 1 +.names g15878 g16840 +0 1 +.names g14280 II22810 +0 1 +.names II22810 g16842 +0 1 +.names g13601 II22813 +0 1 +.names II22813 g16843 +0 1 +.names g13404 g12392 g15903 +0- 1 +-0 1 +.names g15903 g16846 +0 1 +.names g14402 II22820 +0 1 +.names II22820 g16848 +0 1 +.names g13613 II22823 +0 1 +.names II22823 g16849 +0 1 +.names g14514 II22828 +0 1 +.names II22828 g16852 +0 1 +.names g13571 II22836 +0 1 +.names II22836 g16858 +0 1 +.names g13580 II22842 +0 1 +.names II22842 g16862 +0 1 +.names g13579 II22845 +0 1 +.names II22845 g16863 +0 1 +.names g13589 g16867 +0 1 +.names g13600 II22852 +0 1 +.names II22852 g16877 +0 1 +.names g13588 II22855 +0 1 +.names II22855 g16878 +0 1 +.names g14885 II22860 +0 1 +.names II22860 g16881 +0 1 +.names g13589 g16884 +0 1 +.names g13589 g16895 +0 1 +.names g13612 II22866 +0 1 +.names II22866 g16905 +0 1 +.names g13608 II22869 +0 1 +.names II22869 g16906 +0 1 +.names g14966 II22875 +0 1 +.names II22875 g16910 +0 1 +.names g13589 g16913 +0 1 +.names g13589 g16924 +0 1 +.names g13622 II22881 +0 1 +.names II22881 g16934 +0 1 +.names g15055 II22893 +0 1 +.names II22893 g16940 +0 1 +.names g13589 g16943 +0 1 +.names g13589 g16954 +0 1 +.names g15151 II22912 +0 1 +.names II22912 g16971 +0 1 +.names g13589 g16974 +0 1 +.names g14685 g17029 +0 1 +.names g13519 g17057 +0 1 +.names g14719 g17063 +0 1 +.names g13530 g17092 +0 1 +.names g14747 g17098 +0 1 +.names g13541 g17130 +0 1 +.names g14768 g17136 +0 1 +.names g13552 g17157 +0 1 +.names g13741 II23253 +0 1 +.names II23253 g17189 +0 1 +.names g13741 II23274 +0 1 +.names II23274 g17200 +0 1 +.names g13568 g17203 +0 1 +.names g13741 II23287 +0 1 +.names II23287 g17207 +0 1 +.names g13576 g17208 +0 1 +.names g13741 II23292 +0 1 +.names II23292 g17212 +0 1 +.names g13585 g17214 +0 1 +.names g13605 g17217 +0 1 +.names II22283 II22284 g16132 +0- 1 +-0 1 +.names g16132 II23309 +0 1 +.names II23309 g17227 +0 1 +.names g12565 g6232 g15720 +0- 1 +-0 1 +.names g15720 II23314 +0 1 +.names II23314 g17230 +0 1 +.names II22317 II22318 g16181 +0- 1 +-0 1 +.names g16181 II23317 +0 1 +.names II23317 g17233 +0 1 +.names g12565 g6314 g15664 +0- 1 +-0 1 +.names g15664 II23323 +0 1 +.names II23323 g17237 +0 1 +.names g12565 g6232 g15758 +0- 1 +-0 1 +.names g15758 II23326 +0 1 +.names II23326 g17240 +0 1 +.names g12611 g6369 g15760 +0- 1 +-0 1 +.names g15760 II23329 +0 1 +.names II23329 g17243 +0 1 +.names g12565 g3254 g16412 +0- 1 +-0 1 +.names g16412 II23335 +0 1 +.names II23335 g17249 +0 1 +.names g12565 g6314 g15721 +0- 1 +-0 1 +.names g15721 II23338 +0 1 +.names II23338 g17252 +0 1 +.names g12565 g6232 g15784 +0- 1 +-0 1 +.names g15784 II23341 +0 1 +.names II23341 g17255 +0 1 +.names g297 g11770 g16053 +11 1 +.names g16053 g17258 +0 1 +.names g12611 g6519 g15723 +0- 1 +-0 1 +.names g15723 II23345 +0 1 +.names II23345 g17259 +0 1 +.names g12611 g6369 g15786 +0- 1 +-0 1 +.names g15786 II23348 +0 1 +.names II23348 g17262 +0 1 +.names g12657 g6574 g15788 +0- 1 +-0 1 +.names g15788 II23351 +0 1 +.names II23351 g17265 +0 1 +.names g12565 g3254 g16442 +0- 1 +-0 1 +.names g16442 II23358 +0 1 +.names II23358 g17272 +0 1 +.names g12565 g6314 g15759 +0- 1 +-0 1 +.names g15759 II23361 +0 1 +.names II23361 g17275 +0 1 +.names g12565 g6232 g15805 +0- 1 +-0 1 +.names g15805 II23364 +0 1 +.names II23364 g17278 +0 1 +.names g3304 g11783 g16081 +11 1 +.names g16081 g17281 +0 1 +.names g12611 g3410 g16446 +0- 1 +-0 1 +.names g16446 II23368 +0 1 +.names II23368 g17282 +0 1 +.names g12611 g6519 g15761 +0- 1 +-0 1 +.names g15761 II23371 +0 1 +.names II23371 g17285 +0 1 +.names g12611 g6369 g15807 +0- 1 +-0 1 +.names g15807 II23374 +0 1 +.names II23374 g17288 +0 1 +.names g12657 g6783 g15763 +0- 1 +-0 1 +.names g15763 II23377 +0 1 +.names II23377 g17291 +0 1 +.names g12657 g6574 g15809 +0- 1 +-0 1 +.names g15809 II23380 +0 1 +.names II23380 g17294 +0 1 +.names g12711 g6838 g15811 +0- 1 +-0 1 +.names g15811 II23383 +0 1 +.names II23383 g17297 +0 1 +.names g13469 II23386 +0 1 +.names II23386 g17300 +0 1 +.names g12565 g3254 g13476 +0- 1 +-0 1 +.names g13476 II23392 +0 1 +.names II23392 g17304 +0 1 +.names g12565 g6314 g15785 +0- 1 +-0 1 +.names g15785 II23395 +0 1 +.names II23395 g17307 +0 1 +.names g12565 g6232 g15820 +0- 1 +-0 1 +.names g15820 II23398 +0 1 +.names II23398 g17310 +0 1 +.names g8277 g11803 g16109 +11 1 +.names g16109 g17313 +0 1 +.names g516 g11804 g16110 +11 1 +.names g16110 g17314 +0 1 +.names g12611 g3410 g13478 +0- 1 +-0 1 +.names g13478 II23403 +0 1 +.names II23403 g17315 +0 1 +.names g12611 g6519 g15787 +0- 1 +-0 1 +.names g15787 II23406 +0 1 +.names II23406 g17318 +0 1 +.names g12611 g6369 g15822 +0- 1 +-0 1 +.names g15822 II23409 +0 1 +.names II23409 g17321 +0 1 +.names g12657 g3566 g13482 +0- 1 +-0 1 +.names g13482 II23412 +0 1 +.names II23412 g17324 +0 1 +.names g12657 g6783 g15789 +0- 1 +-0 1 +.names g15789 II23415 +0 1 +.names II23415 g17327 +0 1 +.names g12657 g6574 g15824 +0- 1 +-0 1 +.names g15824 II23418 +0 1 +.names II23418 g17330 +0 1 +.names g12711 g7085 g15791 +0- 1 +-0 1 +.names g15791 II23421 +0 1 +.names II23421 g17333 +0 1 +.names g12711 g6838 g15826 +0- 1 +-0 1 +.names g15826 II23424 +0 1 +.names II23424 g17336 +0 1 +.names g12565 g3254 g13494 +0- 1 +-0 1 +.names g13494 II23430 +0 1 +.names II23430 g17342 +0 1 +.names g12565 g6314 g15806 +0- 1 +-0 1 +.names g15806 II23433 +0 1 +.names II23433 g17345 +0 1 +.names g12565 g6232 g15832 +0- 1 +-0 1 +.names g15832 II23436 +0 1 +.names II23436 g17348 +0 1 +.names g517 g11829 g16152 +11 1 +.names g16152 g17351 +0 1 +.names g12611 g3410 g13495 +0- 1 +-0 1 +.names g13495 II23442 +0 1 +.names II23442 g17354 +0 1 +.names g12611 g6519 g15808 +0- 1 +-0 1 +.names g15808 II23445 +0 1 +.names II23445 g17357 +0 1 +.names g12611 g6369 g15834 +0- 1 +-0 1 +.names g15834 II23448 +0 1 +.names II23448 g17360 +0 1 +.names g12657 g3566 g13497 +0- 1 +-0 1 +.names g13497 II23451 +0 1 +.names II23451 g17363 +0 1 +.names g12657 g6783 g15810 +0- 1 +-0 1 +.names g15810 II23454 +0 1 +.names II23454 g17366 +0 1 +.names g12657 g6574 g15836 +0- 1 +-0 1 +.names g15836 II23457 +0 1 +.names II23457 g17369 +0 1 +.names g12711 g3722 g13501 +0- 1 +-0 1 +.names g13501 II23460 +0 1 +.names II23460 g17372 +0 1 +.names g12711 g7085 g15812 +0- 1 +-0 1 +.names g15812 II23463 +0 1 +.names II23463 g17375 +0 1 +.names g12711 g6838 g15838 +0- 1 +-0 1 +.names g15838 II23466 +0 1 +.names II23466 g17378 +0 1 +.names g12565 g3254 g13510 +0- 1 +-0 1 +.names g13510 II23472 +0 1 +.names II23472 g17384 +0 1 +.names g12565 g6314 g15821 +0- 1 +-0 1 +.names g15821 II23475 +0 1 +.names II23475 g17387 +0 1 +.names g12565 g6232 g15844 +0- 1 +-0 1 +.names g15844 II23478 +0 1 +.names II23478 g17390 +0 1 +.names g518 g11862 g16197 +11 1 +.names g16197 g17394 +0 1 +.names g12611 g3410 g13511 +0- 1 +-0 1 +.names g13511 II23487 +0 1 +.names II23487 g17399 +0 1 +.names g12611 g6519 g15823 +0- 1 +-0 1 +.names g15823 II23490 +0 1 +.names II23490 g17402 +0 1 +.names g12611 g6369 g15846 +0- 1 +-0 1 +.names g15846 II23493 +0 1 +.names II23493 g17405 +0 1 +.names g12657 g3566 g13512 +0- 1 +-0 1 +.names g13512 II23498 +0 1 +.names II23498 g17410 +0 1 +.names g12657 g6783 g15825 +0- 1 +-0 1 +.names g15825 II23501 +0 1 +.names II23501 g17413 +0 1 +.names g12657 g6574 g15848 +0- 1 +-0 1 +.names g15848 II23504 +0 1 +.names II23504 g17416 +0 1 +.names g12711 g3722 g13514 +0- 1 +-0 1 +.names g13514 II23507 +0 1 +.names II23507 g17419 +0 1 +.names g12711 g7085 g15827 +0- 1 +-0 1 +.names g15827 II23510 +0 1 +.names II23510 g17422 +0 1 +.names g12711 g6838 g15850 +0- 1 +-0 1 +.names g15850 II23513 +0 1 +.names II23513 g17425 +0 1 +.names g12565 g6232 g15856 +0- 1 +-0 1 +.names g15856 II23518 +0 1 +.names II23518 g17430 +0 1 +.names g12565 g3254 g13518 +0- 1 +-0 1 +.names g13518 II23521 +0 1 +.names II23521 g17433 +0 1 +.names g12565 g6314 g15833 +0- 1 +-0 1 +.names g15833 II23524 +0 1 +.names II23524 g17436 +0 1 +.names g12565 g6232 g15858 +0- 1 +-0 1 +.names g15858 II23527 +0 1 +.names II23527 g17439 +0 1 +.names g14885 II23530 +0 1 +.names II23530 g17442 +0 1 +.names g519 g11895 g16250 +11 1 +.names g16250 g17445 +0 1 +.names g12611 g3410 g13524 +0- 1 +-0 1 +.names g13524 II23539 +0 1 +.names II23539 g17451 +0 1 +.names g12611 g6519 g15835 +0- 1 +-0 1 +.names g15835 II23542 +0 1 +.names II23542 g17454 +0 1 +.names g12611 g6369 g15867 +0- 1 +-0 1 +.names g15867 II23545 +0 1 +.names II23545 g17457 +0 1 +.names g12657 g3566 g13525 +0- 1 +-0 1 +.names g13525 II23553 +0 1 +.names II23553 g17465 +0 1 +.names g12657 g6783 g15837 +0- 1 +-0 1 +.names g15837 II23556 +0 1 +.names II23556 g17468 +0 1 +.names g12657 g6574 g15869 +0- 1 +-0 1 +.names g15869 II23559 +0 1 +.names II23559 g17471 +0 1 +.names g12711 g3722 g13526 +0- 1 +-0 1 +.names g13526 II23564 +0 1 +.names II23564 g17476 +0 1 +.names g12711 g7085 g15839 +0- 1 +-0 1 +.names g15839 II23567 +0 1 +.names II23567 g17479 +0 1 +.names g12711 g6838 g15871 +0- 1 +-0 1 +.names g15871 II23570 +0 1 +.names II23570 g17482 +0 1 +.names g12565 g6314 g15843 +0- 1 +-0 1 +.names g15843 II23575 +0 1 +.names II23575 g17487 +0 1 +.names g12565 g6232 g15879 +0- 1 +-0 1 +.names g15879 II23578 +0 1 +.names II23578 g17490 +0 1 +.names g12565 g3254 g13528 +0- 1 +-0 1 +.names g13528 II23581 +0 1 +.names II23581 g17493 +0 1 +.names g12565 g6314 g15845 +0- 1 +-0 1 +.names g15845 II23584 +0 1 +.names II23584 g17496 +0 1 +.names g294 g11932 g16292 +11 1 +.names g16292 g17499 +0 1 +.names g14885 II23588 +0 1 +.names II23588 g17500 +0 1 +.names g14885 II23591 +0 1 +.names II23591 g17503 +0 1 +.names g12611 g6369 g15887 +0- 1 +-0 1 +.names g15887 II23599 +0 1 +.names II23599 g17511 +0 1 +.names g12611 g3410 g13529 +0- 1 +-0 1 +.names g13529 II23602 +0 1 +.names II23602 g17514 +0 1 +.names g12611 g6519 g15847 +0- 1 +-0 1 +.names g15847 II23605 +0 1 +.names II23605 g17517 +0 1 +.names g12611 g6369 g15889 +0- 1 +-0 1 +.names g15889 II23608 +0 1 +.names II23608 g17520 +0 1 +.names g14966 II23611 +0 1 +.names II23611 g17523 +0 1 +.names g12657 g3566 g13535 +0- 1 +-0 1 +.names g13535 II23619 +0 1 +.names II23619 g17531 +0 1 +.names g12657 g6783 g15849 +0- 1 +-0 1 +.names g15849 II23622 +0 1 +.names II23622 g17534 +0 1 +.names g12657 g6574 g15898 +0- 1 +-0 1 +.names g15898 II23625 +0 1 +.names II23625 g17537 +0 1 +.names g12711 g3722 g13536 +0- 1 +-0 1 +.names g13536 II23633 +0 1 +.names II23633 g17545 +0 1 +.names g12711 g7085 g15851 +0- 1 +-0 1 +.names g15851 II23636 +0 1 +.names II23636 g17548 +0 1 +.names g12711 g6838 g15900 +0- 1 +-0 1 +.names g15900 II23639 +0 1 +.names II23639 g17551 +0 1 +.names g12565 g3254 g13537 +0- 1 +-0 1 +.names g13537 II23645 +0 1 +.names II23645 g17557 +0 1 +.names g12565 g6314 g15857 +0- 1 +-0 1 +.names g15857 II23648 +0 1 +.names II23648 g17560 +0 1 +.names g12565 g3254 g13538 +0- 1 +-0 1 +.names g13538 II23651 +0 1 +.names II23651 g17563 +0 1 +.names g295 g11972 g16346 +11 1 +.names g16346 g17566 +0 1 +.names g14831 II23655 +0 1 +.names II23655 g17567 +0 1 +.names g14885 II23658 +0 1 +.names II23658 g17570 +0 1 +.names g12883 g633 g16085 +0- 1 +-0 1 +.names g16085 II23661 +0 1 +.names II23661 g17573 +0 1 +.names g12611 g6519 g15866 +0- 1 +-0 1 +.names g15866 II23667 +0 1 +.names II23667 g17579 +0 1 +.names g12611 g6369 g15912 +0- 1 +-0 1 +.names g15912 II23670 +0 1 +.names II23670 g17582 +0 1 +.names g12611 g3410 g13539 +0- 1 +-0 1 +.names g13539 II23673 +0 1 +.names II23673 g17585 +0 1 +.names g12611 g6519 g15868 +0- 1 +-0 1 +.names g15868 II23676 +0 1 +.names II23676 g17588 +0 1 +.names g14966 II23679 +0 1 +.names II23679 g17591 +0 1 +.names g14966 II23682 +0 1 +.names II23682 g17594 +0 1 +.names g12657 g6574 g15920 +0- 1 +-0 1 +.names g15920 II23689 +0 1 +.names II23689 g17601 +0 1 +.names g12657 g3566 g13540 +0- 1 +-0 1 +.names g13540 II23692 +0 1 +.names II23692 g17604 +0 1 +.names g12657 g6783 g15870 +0- 1 +-0 1 +.names g15870 II23695 +0 1 +.names II23695 g17607 +0 1 +.names g12657 g6574 g15922 +0- 1 +-0 1 +.names g15922 II23698 +0 1 +.names II23698 g17610 +0 1 +.names g15055 II23701 +0 1 +.names II23701 g17613 +0 1 +.names g12711 g3722 g13546 +0- 1 +-0 1 +.names g13546 II23709 +0 1 +.names II23709 g17621 +0 1 +.names g12711 g7085 g15872 +0- 1 +-0 1 +.names g15872 II23712 +0 1 +.names II23712 g17624 +0 1 +.names g12711 g6838 g15931 +0- 1 +-0 1 +.names g15931 II23715 +0 1 +.names II23715 g17627 +0 1 +.names g12565 g3254 g13547 +0- 1 +-0 1 +.names g13547 II23725 +0 1 +.names II23725 g17637 +0 1 +.names g13873 g17640 +0 1 +.names g14337 II23729 +0 1 +.names II23729 g17645 +0 1 +.names g296 g12024 g16384 +11 1 +.names g16384 g17648 +0 1 +.names g14831 II23733 +0 1 +.names II23733 g17649 +0 1 +.names g12611 g3410 g13548 +0- 1 +-0 1 +.names g13548 II23739 +0 1 +.names II23739 g17655 +0 1 +.names g12611 g6519 g15888 +0- 1 +-0 1 +.names g15888 II23742 +0 1 +.names II23742 g17658 +0 1 +.names g12611 g3410 g13549 +0- 1 +-0 1 +.names g13549 II23745 +0 1 +.names II23745 g17661 +0 1 +.names g14904 II23748 +0 1 +.names II23748 g17664 +0 1 +.names g14966 II23751 +0 1 +.names II23751 g17667 +0 1 +.names g12923 g1319 g16123 +0- 1 +-0 1 +.names g16123 II23754 +0 1 +.names II23754 g17670 +0 1 +.names g12657 g6783 g15897 +0- 1 +-0 1 +.names g15897 II23760 +0 1 +.names II23760 g17676 +0 1 +.names g12657 g6574 g15941 +0- 1 +-0 1 +.names g15941 II23763 +0 1 +.names II23763 g17679 +0 1 +.names g12657 g3566 g13550 +0- 1 +-0 1 +.names g13550 II23766 +0 1 +.names II23766 g17682 +0 1 +.names g12657 g6783 g15899 +0- 1 +-0 1 +.names g15899 II23769 +0 1 +.names II23769 g17685 +0 1 +.names g15055 II23772 +0 1 +.names II23772 g17688 +0 1 +.names g15055 II23775 +0 1 +.names II23775 g17691 +0 1 +.names g12711 g6838 g15949 +0- 1 +-0 1 +.names g15949 II23782 +0 1 +.names II23782 g17698 +0 1 +.names g12711 g3722 g13551 +0- 1 +-0 1 +.names g13551 II23785 +0 1 +.names II23785 g17701 +0 1 +.names g12711 g7085 g15901 +0- 1 +-0 1 +.names g15901 II23788 +0 1 +.names II23788 g17704 +0 1 +.names g12711 g6838 g15951 +0- 1 +-0 1 +.names g15951 II23791 +0 1 +.names II23791 g17707 +0 1 +.names g15151 II23794 +0 1 +.names II23794 g17710 +0 1 +.names g13310 g12354 g15853 +0- 1 +-0 1 +.names g15853 g17720 +0 1 +.names g13886 g17724 +0 1 +.names g12611 g3410 g13557 +0- 1 +-0 1 +.names g13557 II23817 +0 1 +.names II23817 g17738 +0 1 +.names g13895 g17741 +0 1 +.names g14337 II23821 +0 1 +.names II23821 g17746 +0 1 +.names g14904 II23824 +0 1 +.names II23824 g17749 +0 1 +.names g12657 g3566 g13558 +0- 1 +-0 1 +.names g13558 II23830 +0 1 +.names II23830 g17755 +0 1 +.names g12657 g6783 g15921 +0- 1 +-0 1 +.names g15921 II23833 +0 1 +.names II23833 g17758 +0 1 +.names g12657 g3566 g13559 +0- 1 +-0 1 +.names g13559 II23836 +0 1 +.names II23836 g17761 +0 1 +.names g14985 II23839 +0 1 +.names II23839 g17764 +0 1 +.names g15055 II23842 +0 1 +.names II23842 g17767 +0 1 +.names g12952 g2013 g16174 +0- 1 +-0 1 +.names g16174 II23845 +0 1 +.names II23845 g17770 +0 1 +.names g12711 g7085 g15930 +0- 1 +-0 1 +.names g15930 II23851 +0 1 +.names II23851 g17776 +0 1 +.names g12711 g6838 g15970 +0- 1 +-0 1 +.names g15970 II23854 +0 1 +.names II23854 g17779 +0 1 +.names g12711 g3722 g13560 +0- 1 +-0 1 +.names g13560 II23857 +0 1 +.names II23857 g17782 +0 1 +.names g12711 g7085 g15932 +0- 1 +-0 1 +.names g15932 II23860 +0 1 +.names II23860 g17785 +0 1 +.names g15151 II23863 +0 1 +.names II23863 g17788 +0 1 +.names g15151 II23866 +0 1 +.names II23866 g17791 +0 1 +.names g13305 g7143 g15797 +00 1 +.names g15797 II23874 +0 1 +.names II23874 g17799 +0 1 +.names g13907 g17802 +0 1 +.names g14685 II23888 +0 1 +.names II23888 g17815 +0 1 +.names g13927 g17825 +0 1 +.names g12657 g3566 g13561 +0- 1 +-0 1 +.names g13561 II23904 +0 1 +.names II23904 g17839 +0 1 +.names g13936 g17842 +0 1 +.names g14337 II23908 +0 1 +.names II23908 g17847 +0 1 +.names g14985 II23911 +0 1 +.names II23911 g17850 +0 1 +.names g12711 g3722 g13562 +0- 1 +-0 1 +.names g13562 II23917 +0 1 +.names II23917 g17856 +0 1 +.names g12711 g7085 g15950 +0- 1 +-0 1 +.names g15950 II23920 +0 1 +.names II23920 g17859 +0 1 +.names g12711 g3722 g13563 +0- 1 +-0 1 +.names g13563 II23923 +0 1 +.names II23923 g17862 +0 1 +.names g15074 II23926 +0 1 +.names II23926 g17865 +0 1 +.names g15151 II23929 +0 1 +.names II23929 g17868 +0 1 +.names g12981 g2707 g16233 +0- 1 +-0 1 +.names g16233 II23932 +0 1 +.names II23932 g17871 +0 1 +.names g13310 g12392 g15830 +0- 1 +-0 1 +.names g15830 g17878 +0 1 +.names g13946 g17882 +0 1 +.names g13954 g17892 +0 1 +.names g14165 g17893 +0 1 +.names g16154 II23954 +0 1 +.names II23954 g17903 +0 1 +.names g13963 g17914 +0 1 +.names g14719 II23976 +0 1 +.names II23976 g17927 +0 1 +.names g13983 g17937 +0 1 +.names g12711 g3722 g13564 +0- 1 +-0 1 +.names g13564 II23992 +0 1 +.names II23992 g17951 +0 1 +.names g13992 g17954 +0 1 +.names g14337 II23996 +0 1 +.names II23996 g17959 +0 1 +.names g15074 II23999 +0 1 +.names II23999 g17962 +0 1 +.names g13331 g12392 g15841 +0- 1 +-0 1 +.names g15841 g17969 +0 1 +.names g14001 g17974 +0 1 +.names g14008 g17984 +0 1 +.names g14685 g17988 +0 1 +.names g14450 g17991 +0 1 +.names g14016 g17993 +0 1 +.names g14024 g18003 +0 1 +.names g14280 g18004 +0 1 +.names g16213 II24049 +0 1 +.names II24049 g18014 +0 1 +.names g14033 g18025 +0 1 +.names g14747 II24071 +0 1 +.names II24071 g18038 +0 1 +.names g14053 g18048 +0 1 +.names g13401 g12354 g15660 +0- 1 +-0 1 +.names g15660 g18063 +0 1 +.names g13353 g12392 g15854 +0- 1 +-0 1 +.names g15854 g18070 +0 1 +.names g14062 g18074 +0 1 +.names g14068 g18084 +0 1 +.names g14355 g18089 +0 1 +.names g14092 g18091 +0 1 +.names g14099 g18101 +0 1 +.names g14719 g18105 +0 1 +.names g14537 g18108 +0 1 +.names g14107 g18110 +0 1 +.names g14115 g18120 +0 1 +.names g14402 g18121 +0 1 +.names g16278 II24144 +0 1 +.names II24144 g18131 +0 1 +.names g14124 g18142 +0 1 +.names g14768 II24166 +0 1 +.names II24166 g18155 +0 1 +.names g13082 g2912 g16439 +0- 1 +-0 1 +.names g16439 II24171 +0 1 +.names II24171 g18166 +0 1 +.names g13374 g12392 g15877 +0- 1 +-0 1 +.names g15877 g18170 +0 1 +.names g14148 g18174 +0 1 +.names g14153 g18179 +0 1 +.names g14252 g18188 +0 1 +.names g14177 g18190 +0 1 +.names g14183 g18200 +0 1 +.names g14467 g18205 +0 1 +.names g14207 g18207 +0 1 +.names g14214 g18217 +0 1 +.names g14747 g18221 +0 1 +.names g14592 g18224 +0 1 +.names g14222 g18226 +0 1 +.names g14230 g18236 +0 1 +.names g14514 g18237 +0 1 +.names g16337 II24247 +0 1 +.names II24247 g18247 +0 1 +.names g13004 g3018 g16463 +0- 1 +-0 1 +.names g16463 II24258 +0 1 +.names II24258 g18258 +0 1 +.names g13401 g12392 g15719 +0- 1 +-0 1 +.names g15719 g18261 +0 1 +.names g14238 g18265 +0 1 +.names g14171 g18275 +0 1 +.names g12886 g6678 g15992 +0- 1 +-0 1 +.names g15992 II24285 +0 1 +.names II24285 g18278 +0 1 +.names g14263 g18281 +0 1 +.names g14268 g18286 +0 1 +.names g14374 g18295 +0 1 +.names g14292 g18297 +0 1 +.names g14298 g18307 +0 1 +.names g14554 g18312 +0 1 +.names g14322 g18314 +0 1 +.names g14329 g18324 +0 1 +.names g14768 g18328 +0 1 +.names g14626 g18331 +0 1 +.names g11617 g7562 g15873 +00 1 +.names g15873 II24346 +0 1 +.names II24346 g18334 +0 1 +.names g11622 g12392 g15757 +0- 1 +-0 1 +.names g15757 g18337 +0 1 +.names g14342 g18341 +0 1 +.names g13741 g18351 +0 1 +.names g13918 g18353 +0 1 +.names g12886 g6912 g15990 +0- 1 +-0 1 +.names g15990 II24368 +0 1 +.names II24368 g18355 +0 1 +.names g14360 g18358 +0 1 +.names g14286 g18368 +0 1 +.names g12926 g6980 g15995 +0- 1 +-0 1 +.names g15995 II24394 +0 1 +.names II24394 g18371 +0 1 +.names g14385 g18374 +0 1 +.names g14390 g18379 +0 1 +.names g14486 g18388 +0 1 +.names g14414 g18390 +0 1 +.names g14420 g18400 +0 1 +.names g14609 g18405 +0 1 +.names g2814 g13082 g15959 +00 1 +.names g15959 g18407 +0 1 +.names g13286 g12354 g15718 +0- 1 +-0 1 +.names g15718 g18414 +0 1 +.names g11643 g12392 g15783 +0- 1 +-0 1 +.names g15783 g18415 +0 1 +.names g14831 g18429 +0 1 +.names g12886 g3366 g13599 +0- 1 +-0 1 +.names g13599 II24459 +0 1 +.names II24459 g18432 +0 1 +.names g14359 g18435 +0 1 +.names g14454 g18436 +0 1 +.names g13741 g18446 +0 1 +.names g13974 g18448 +0 1 +.names g12926 g7162 g15993 +0- 1 +-0 1 +.names g15993 II24481 +0 1 +.names II24481 g18450 +0 1 +.names g14472 g18453 +0 1 +.names g14408 g18463 +0 1 +.names g12955 g7230 g15999 +0- 1 +-0 1 +.names g15999 II24507 +0 1 +.names II24507 g18466 +0 1 +.names g14497 g18469 +0 1 +.names g14502 g18474 +0 1 +.names g14573 g18483 +0 1 +.names g13313 g12354 g15756 +0- 1 +-0 1 +.names g15756 g18485 +0 1 +.names g11660 g12392 g15804 +0- 1 +-0 1 +.names g15804 g18486 +0 1 +.names g13565 g18490 +0 1 +.names g14904 g18502 +0 1 +.names g12926 g3522 g13611 +0- 1 +-0 1 +.names g13611 II24560 +0 1 +.names II24560 g18505 +0 1 +.names g14471 g18508 +0 1 +.names g14541 g18509 +0 1 +.names g13741 g18519 +0 1 +.names g14044 g18521 +0 1 +.names g12955 g7358 g15996 +0- 1 +-0 1 +.names g15996 II24582 +0 1 +.names II24582 g18523 +0 1 +.names g14559 g18526 +0 1 +.names g14520 g18536 +0 1 +.names g12984 g7426 g16006 +0- 1 +-0 1 +.names g16006 II24608 +0 1 +.names II24608 g18539 +0 1 +.names g13286 g12392 g15819 +0- 1 +-0 1 +.names g15819 g18543 +0 1 +.names g16154 g18552 +0 1 +.names g13573 g18554 +0 1 +.names g14985 g18566 +0 1 +.names g12955 g3678 g13621 +0- 1 +-0 1 +.names g13621 II24662 +0 1 +.names II24662 g18569 +0 1 +.names g14558 g18572 +0 1 +.names g14596 g18573 +0 1 +.names g13741 g18583 +0 1 +.names g14135 g18585 +0 1 +.names g12984 g7488 g16000 +0- 1 +-0 1 +.names g16000 II24684 +0 1 +.names II24684 g18587 +0 1 +.names g13313 g12392 g15831 +0- 1 +-0 1 +.names g15831 g18593 +0 1 +.names g16213 g18602 +0 1 +.names g13582 g18604 +0 1 +.names g15074 g18616 +0 1 +.names g12984 g3834 g13633 +0- 1 +-0 1 +.names g13633 II24732 +0 1 +.names II24732 g18619 +0 1 +.names g14613 g18622 +0 1 +.names g16278 g18634 +0 1 +.names g13602 g18636 +0 1 +.names g16337 g18643 +0 1 +.names g12377 g12407 g16341 +0- 1 +-0 1 +.names g16341 g18646 +0 1 +.names g14776 g18656 +0 1 +.names g14797 g18670 +0 1 +.names g14811 g18679 +0 1 +.names g14885 g18691 +0 1 +.names g14837 g18692 +0 1 +.names g14849 g18699 +0 1 +.names g14863 g18708 +0 1 +.names g14895 g18720 +0 1 +.names g548 g12748 g13865 +11 1 +.names g13865 g18725 +0 1 +.names g14966 g18727 +0 1 +.names g14910 g18728 +0 1 +.names g14922 g18735 +0 1 +.names g14936 g18744 +0 1 +.names g14960 g18756 +0 1 +.names g14963 g18757 +0 1 +.names g14976 g18758 +0 1 +.names g15055 g18764 +0 1 +.names g14991 g18765 +0 1 +.names g15003 g18772 +0 1 +.names g15034 g18783 +0 1 +.names g15037 g18784 +0 1 +.names g15040 g18785 +0 1 +.names g15043 g18786 +0 1 +.names g15049 g18787 +0 1 +.names g15052 g18788 +0 1 +.names g15065 g18789 +0 1 +.names g15151 g18795 +0 1 +.names g15080 g18796 +0 1 +.names g15106 g18805 +0 1 +.names g15109 g18806 +0 1 +.names g15112 g18807 +0 1 +.names g15115 g18808 +0 1 +.names g15130 g18809 +0 1 +.names g15133 g18810 +0 1 +.names g15136 g18811 +0 1 +.names g15139 g18812 +0 1 +.names g15145 g18813 +0 1 +.names g15148 g18814 +0 1 +.names g15161 g18815 +0 1 +.names g15179 g18822 +0 1 +.names g15182 g18823 +0 1 +.names g15185 g18824 +0 1 +.names g15198 g18825 +0 1 +.names g15201 g18826 +0 1 +.names g15204 g18827 +0 1 +.names g15207 g18828 +0 1 +.names g15222 g18829 +0 1 +.names g15225 g18830 +0 1 +.names g15228 g18831 +0 1 +.names g15231 g18832 +0 1 +.names g15237 g18833 +0 1 +.names g15240 g18834 +0 1 +.names g15248 g18838 +0 1 +.names g15251 g18839 +0 1 +.names g15254 g18840 +0 1 +.names g15265 g18841 +0 1 +.names g15268 g18842 +0 1 +.names g15271 g18843 +0 1 +.names g15284 g18844 +0 1 +.names g15287 g18845 +0 1 +.names g15290 g18846 +0 1 +.names g15293 g18847 +0 1 +.names g15308 g18848 +0 1 +.names g15311 g18849 +0 1 +.names g15314 g18850 +0 1 +.names g15317 g18851 +0 1 +.names g15326 g18853 +0 1 +.names g15329 g18854 +0 1 +.names g15332 g18855 +0 1 +.names g15340 g18856 +0 1 +.names g15343 g18857 +0 1 +.names g15346 g18858 +0 1 +.names g15357 g18859 +0 1 +.names g15360 g18860 +0 1 +.names g15363 g18861 +0 1 +.names g15376 g18862 +0 1 +.names g15379 g18863 +0 1 +.names g15382 g18864 +0 1 +.names g15385 g18865 +0 1 +.names g14797 II24894 +0 1 +.names II24894 g18869 +0 1 +.names g15393 g18870 +0 1 +.names g15396 g18871 +0 1 +.names g15399 g18872 +0 1 +.names g15404 g18873 +0 1 +.names g15412 g18874 +0 1 +.names g15415 g18875 +0 1 +.names g15418 g18876 +0 1 +.names g15426 g18877 +0 1 +.names g15429 g18878 +0 1 +.names g15432 g18879 +0 1 +.names g15443 g18880 +0 1 +.names g15446 g18881 +0 1 +.names g15449 g18882 +0 1 +.names g13469 g18884 +0 1 +.names g15800 II24913 +0 1 +.names II24913 g18886 +0 1 +.names g14776 II24916 +0 1 +.names II24916 g18890 +0 1 +.names g15461 g18891 +0 1 +.names g15464 g18892 +0 1 +.names g15467 g18893 +0 1 +.names g15471 g18894 +0 1 +.names g14849 II24923 +0 1 +.names II24923 g18895 +0 1 +.names g15477 g18896 +0 1 +.names g15480 g18897 +0 1 +.names g15483 g18898 +0 1 +.names g15488 g18899 +0 1 +.names g15496 g18900 +0 1 +.names g15499 g18901 +0 1 +.names g15502 g18902 +0 1 +.names g15510 g18903 +0 1 +.names g15513 g18904 +0 1 +.names g15516 g18905 +0 1 +.names g15521 g18908 +0 1 +.names g15528 g18909 +0 1 +.names g15531 g18910 +0 1 +.names g15534 g18911 +0 1 +.names g15537 g18912 +0 1 +.names g14811 II24943 +0 1 +.names II24943 g18913 +0 1 +.names g15547 g18914 +0 1 +.names g15550 g18915 +0 1 +.names g15553 g18916 +0 1 +.names g15557 g18917 +0 1 +.names g14922 II24950 +0 1 +.names II24950 g18918 +0 1 +.names g15563 g18919 +0 1 +.names g15566 g18920 +0 1 +.names g15569 g18921 +0 1 +.names g15574 g18922 +0 1 +.names g15582 g18923 +0 1 +.names g15585 g18924 +0 1 +.names g15588 g18925 +0 1 +.names g15596 g18926 +0 1 +.names g15599 g18927 +0 1 +.names g15606 g18928 +0 1 +.names g15609 g18929 +0 1 +.names g15612 g18930 +0 1 +.names g15615 g18931 +0 1 +.names g14863 II24966 +0 1 +.names II24966 g18932 +0 1 +.names g15625 g18933 +0 1 +.names g15628 g18934 +0 1 +.names g15631 g18935 +0 1 +.names g15635 g18936 +0 1 +.names g15003 II24973 +0 1 +.names II24973 g18937 +0 1 +.names g15641 g18938 +0 1 +.names g15644 g18939 +0 1 +.names g15647 g18940 +0 1 +.names g15652 g18941 +0 1 +.names g15655 g18943 +0 1 +.names g14347 II24982 +0 1 +.names II24982 g18944 +0 1 +.names g15667 g18945 +0 1 +.names g15672 g18946 +0 1 +.names g15675 g18947 +0 1 +.names g15682 g18948 +0 1 +.names g15685 g18949 +0 1 +.names g15688 g18950 +0 1 +.names g15691 g18951 +0 1 +.names g14936 II24992 +0 1 +.names II24992 g18952 +0 1 +.names g15701 g18953 +0 1 +.names g15704 g18954 +0 1 +.names g15707 g18955 +0 1 +.names g15711 g18956 +0 1 +.names g15714 g18958 +0 1 +.names g14244 II25001 +0 1 +.names II25001 g18959 +0 1 +.names g14459 II25004 +0 1 +.names II25004 g18960 +0 1 +.names g15726 g18961 +0 1 +.names g15731 g18962 +0 1 +.names g15734 g18963 +0 1 +.names g15741 g18964 +0 1 +.names g15744 g18965 +0 1 +.names g15747 g18966 +0 1 +.names g15750 g18967 +0 1 +.names g14158 II25015 +0 1 +.names II25015 g18969 +0 1 +.names g14366 II25018 +0 1 +.names II25018 g18970 +0 1 +.names g14546 II25021 +0 1 +.names II25021 g18971 +0 1 +.names g15766 g18972 +0 1 +.names g15771 g18973 +0 1 +.names g15774 g18974 +0 1 +.names g15777 g18976 +0 1 +.names g14071 II25037 +0 1 +.names II25037 g18981 +0 1 +.names g14895 II25041 +0 1 +.names II25041 g18983 +0 1 +.names g14273 II25044 +0 1 +.names II25044 g18984 +0 1 +.names g14478 II25047 +0 1 +.names II25047 g18985 +0 1 +.names g14601 II25050 +0 1 +.names II25050 g18986 +0 1 +.names g15794 g18987 +0 1 +.names g14837 II25054 +0 1 +.names II25054 g18988 +0 1 +.names g14186 II25057 +0 1 +.names II25057 g18989 +0 1 +.names g14976 II25061 +0 1 +.names II25061 g18991 +0 1 +.names g14395 II25064 +0 1 +.names II25064 g18992 +0 1 +.names g14565 II25067 +0 1 +.names II25067 g18993 +0 1 +.names g14910 II25071 +0 1 +.names II25071 g18995 +0 1 +.names g14301 II25074 +0 1 +.names II25074 g18996 +0 1 +.names g15065 II25078 +0 1 +.names II25078 g18998 +0 1 +.names g14507 II25081 +0 1 +.names II25081 g18999 +0 1 +.names g14885 II25084 +0 1 +.names II25084 g19000 +0 1 +.names g14071 g19001 +0 1 +.names g14991 II25089 +0 1 +.names II25089 g19008 +0 1 +.names g14423 II25092 +0 1 +.names II25092 g19009 +0 1 +.names g15161 II25096 +0 1 +.names II25096 g19011 +0 1 +.names g19000 II25099 +0 1 +.names g18944 II25102 +0 1 +.names g18959 II25105 +0 1 +.names g18969 II25108 +0 1 +.names g18981 II25111 +0 1 +.names g18983 II25114 +0 1 +.names g18988 II25117 +0 1 +.names g18869 II25120 +0 1 +.names g18890 II25123 +0 1 +.names g16858 II25126 +0 1 +.names g16813 II25129 +0 1 +.names g16862 II25132 +0 1 +.names g16506 II25135 +0 1 +.names g18960 II25138 +0 1 +.names g18970 II25141 +0 1 +.names g18984 II25144 +0 1 +.names g18989 II25147 +0 1 +.names g18991 II25150 +0 1 +.names g18995 II25153 +0 1 +.names g18895 II25156 +0 1 +.names g18913 II25159 +0 1 +.names g16863 II25162 +0 1 +.names g16831 II25165 +0 1 +.names g16877 II25168 +0 1 +.names g16528 II25171 +0 1 +.names g18971 II25174 +0 1 +.names g18985 II25177 +0 1 +.names g18992 II25180 +0 1 +.names g18996 II25183 +0 1 +.names g18998 II25186 +0 1 +.names g19008 II25189 +0 1 +.names g18918 II25192 +0 1 +.names g18932 II25195 +0 1 +.names g16878 II25198 +0 1 +.names g16843 II25201 +0 1 +.names g16905 II25204 +0 1 +.names g16559 II25207 +0 1 +.names g18986 II25210 +0 1 +.names g18993 II25213 +0 1 +.names g18999 II25216 +0 1 +.names g19009 II25219 +0 1 +.names g19011 II25222 +0 1 +.names g16514 II25225 +0 1 +.names g18937 II25228 +0 1 +.names g18952 II25231 +0 1 +.names g16906 II25234 +0 1 +.names g16849 II25237 +0 1 +.names g16934 II25240 +0 1 +.names g17227 II25243 +0 1 +.names g17233 II25246 +0 1 +.names g17300 II25249 +0 1 +.names g14725 g15942 g14677 g17124 +000 1 +.names g17124 II25253 +0 1 +.names II25253 g19064 +0 1 +.names g18583 g19070 +0 1 +.names g16974 II25258 +0 1 +.names II25258 g19075 +0 1 +.names g18619 g19078 +0 1 +.names g14753 g15971 g14711 g17151 +000 1 +.names g17151 II25264 +0 1 +.names II25264 g19081 +0 1 +.names g14657 g15880 g14630 g17051 +000 1 +.names g17051 II25272 +0 1 +.names II25272 g19091 +0 1 +.names II25031 II25032 g18980 +0- 1 +-0 1 +.names g18980 g19096 +0 1 +.names g14691 g15913 g14650 g17086 +000 1 +.names g17086 II25283 +0 1 +.names II25283 g19098 +0 1 +.names g17124 II25294 +0 1 +.names II25294 g19105 +0 1 +.names g17151 II25303 +0 1 +.names II25303 g19110 +0 1 +.names g16867 II25308 +0 1 +.names II25308 g19113 +0 1 +.names g16895 II25315 +0 1 +.names II25315 g19118 +0 1 +.names g16924 II25320 +0 1 +.names II25320 g19125 +0 1 +.names g16954 II25325 +0 1 +.names II25325 g19132 +0 1 +.names g17645 II25334 +0 1 +.names II25334 g19145 +0 1 +.names g17746 II25338 +0 1 +.names II25338 g19147 +0 1 +.names g17847 II25344 +0 1 +.names II25344 g19151 +0 1 +.names g17959 II25351 +0 1 +.names II25351 g19156 +0 1 +.names g13623 g13634 g18669 +00 1 +.names g18669 II25355 +0 1 +.names II25355 g19158 +0 1 +.names g13625 g11771 g18678 +00 1 +.names g18678 II25358 +0 1 +.names II25358 g19159 +0 1 +.names g13636 g11788 g18707 +00 1 +.names g18707 II25365 +0 1 +.names II25365 g19164 +0 1 +.names g13643 g13656 g18719 +00 1 +.names g18719 II25371 +0 1 +.names II25371 g19168 +0 1 +.names g13645 g11805 g18726 +00 1 +.names g18726 II25374 +0 1 +.names II25374 g19169 +0 1 +.names g13648 g11814 g18743 +00 1 +.names g18743 II25377 +0 1 +.names II25377 g19170 +0 1 +.names g13871 g12274 g18755 +00 1 +.names g18755 II25383 +0 1 +.names II25383 g19174 +0 1 +.names g13671 g11838 g18763 +00 1 +.names g18763 II25386 +0 1 +.names II25386 g19175 +0 1 +.names g13674 g11847 g18780 +00 1 +.names g18780 II25389 +0 1 +.names II25389 g19176 +0 1 +.names g13676 g13705 g18782 +00 1 +.names g18782 II25395 +0 1 +.names II25395 g19180 +0 1 +.names g13701 g11880 g18794 +00 1 +.names g18794 II25399 +0 1 +.names II25399 g19182 +0 1 +.names g13740 g11926 g18821 +00 1 +.names g18821 II25402 +0 1 +.names II25402 g19183 +0 1 +.names g13905 g12331 g18804 +00 1 +.names g18804 II25406 +0 1 +.names II25406 g19185 +0 1 +.names g13738 g11922 g18820 +00 1 +.names g18820 II25412 +0 1 +.names II25412 g19189 +0 1 +.names g13788 g11966 g18835 +00 1 +.names g18835 II25415 +0 1 +.names II25415 g19190 +0 1 +.names g13815 g12012 g18852 +00 1 +.names g18852 II25423 +0 1 +.names II25423 g19196 +0 1 +.names g13789 g11967 g18836 +00 1 +.names g18836 II25426 +0 1 +.names II25426 g19197 +0 1 +.names g13944 g12353 g18975 +00 1 +.names g18975 II25429 +0 1 +.names II25429 g19198 +0 1 +.names g13998 g12376 g18837 +00 1 +.names g18837 II25432 +0 1 +.names II25432 g19199 +0 1 +.names g13834 g12069 g18866 +00 1 +.names g18866 II25442 +0 1 +.names II25442 g19207 +0 1 +.names g13904 g12330 g18968 +00 1 +.names g18968 II25445 +0 1 +.names II25445 g19208 +0 1 +.names g13846 g12128 g18883 +00 1 +.names g18883 II25456 +0 1 +.names II25456 g19217 +0 1 +.names g13835 g12070 g18867 +00 1 +.names g18867 II25459 +0 1 +.names II25459 g19218 +0 1 +.names g14143 g12419 g18868 +00 1 +.names g18868 II25463 +0 1 +.names II25463 g19220 +0 1 +.names g13847 g12129 g18885 +00 1 +.names g18885 II25474 +0 1 +.names II25474 g19229 +0 1 +.names g13655 g11816 g18754 +00 1 +.names g18754 II25486 +0 1 +.names II25486 g19237 +0 1 +.names g13855 g12186 g18906 +00 1 +.names g18906 II25489 +0 1 +.names II25489 g19238 +0 1 +.names g14336 g12429 g18907 +00 1 +.names g18907 II25492 +0 1 +.names II25492 g19239 +0 1 +.names g13675 g11851 g18781 +00 1 +.names g18781 II25506 +0 1 +.names II25506 g19247 +0 1 +.names II24612 II24613 g18542 +0- 1 +-0 1 +.names g18542 II25510 +0 1 +.names II25510 g19249 +0 1 +.names g16540 g19251 +0 1 +.names g13704 g11885 g18803 +00 1 +.names g18803 II25525 +0 1 +.names II25525 g19258 +0 1 +.names g13870 g12273 g18942 +00 1 +.names g18942 II25528 +0 1 +.names II25528 g19259 +0 1 +.names g16572 g19265 +0 1 +.names g13884 g12307 g18957 +00 1 +.names g18957 II25557 +0 1 +.names II25557 g19270 +0 1 +.names g7949 g14144 g17186 +00 1 +.names g17186 II25567 +0 1 +.names II25567 g19272 +0 1 +.names g16596 g19280 +0 1 +.names g16608 g19287 +0 1 +.names g8000 g14259 g17197 +00 1 +.names g17197 II25612 +0 1 +.names II25612 g19291 +0 1 +.names g16616 g19299 +0 1 +.names g16622 g19301 +0 1 +.names g15904 g15880 g15859 g17025 +000 1 +.names g17025 g19302 +0 1 +.names g16626 g19305 +0 1 +.names g8075 g14381 g17204 +00 1 +.names g17204 II25660 +0 1 +.names II25660 g19309 +0 1 +.names g16633 g19319 +0 1 +.names g16636 g19322 +0 1 +.names g15933 g15913 g15890 g17059 +000 1 +.names g17059 g19323 +0 1 +.names g16640 g19326 +0 1 +.names g8160 g14493 g17209 +00 1 +.names g17209 II25717 +0 1 +.names II25717 g19330 +0 1 +.names g13915 g13893 g17118 +0- 1 +-0 1 +.names g17118 II25728 +0 1 +.names II25728 g19335 +0 1 +.names g16644 g19346 +0 1 +.names g16647 g19349 +0 1 +.names g15962 g15942 g15923 g17094 +000 1 +.names g17094 g19350 +0 1 +.names g16651 g19353 +0 1 +.names g13957 g13915 g17139 +0- 1 +-0 1 +.names g17139 II25768 +0 1 +.names II25768 g19358 +0 1 +.names g13971 g13934 g17145 +0- 1 +-0 1 +.names g17145 II25778 +0 1 +.names II25778 g19369 +0 1 +.names g16656 g19380 +0 1 +.names g16659 g19383 +0 1 +.names g15981 g15971 g15952 g17132 +000 1 +.names g17132 g19384 +0 1 +.names g15904 g15880 g15859 g16567 +000 1 +.names g16567 g19387 +0 1 +.names g17139 g19388 +0 1 +.names g14027 g13971 g17162 +0- 1 +-0 1 +.names g17162 II25816 +0 1 +.names II25816 g19390 +0 1 +.names g14041 g13990 g17168 +0- 1 +-0 1 +.names g17168 II25826 +0 1 +.names II25826 g19401 +0 1 +.names g16673 g19412 +0 1 +.names g16676 g19415 +0 1 +.names g15933 g15913 g15890 g16591 +000 1 +.names g16591 g19417 +0 1 +.names g17162 g19418 +0 1 +.names g14118 g14041 g17177 +0- 1 +-0 1 +.names g17177 II25862 +0 1 +.names II25862 g19420 +0 1 +.names g14132 g14060 g17183 +0- 1 +-0 1 +.names g17183 II25872 +0 1 +.names II25872 g19431 +0 1 +.names g4326 g14442 g17213 +00 1 +.names g17213 g19441 +0 1 +.names g14641 g9636 g17985 +0- 1 +-0 1 +.names g17985 g19444 +0 1 +.names g16694 g19448 +0 1 +.names g16702 g19452 +0 1 +.names g15962 g15942 g15923 g16611 +000 1 +.names g16611 g19454 +0 1 +.names g17177 g19455 +0 1 +.names g14233 g14132 g17194 +0- 1 +-0 1 +.names g17194 II25904 +0 1 +.names II25904 g19457 +0 1 +.names g16719 g19467 +0 1 +.names g4495 g14529 g17216 +00 1 +.names g17216 g19468 +0 1 +.names g14668 g9782 g18102 +0- 1 +-0 1 +.names g18102 g19471 +0 1 +.names g16725 g19475 +0 1 +.names g16733 g19479 +0 1 +.names g15981 g15971 g15952 g16629 +000 1 +.names g16629 g19481 +0 1 +.names g17194 g19482 +0 1 +.names g16758 g19483 +0 1 +.names g16867 g19484 +0 1 +.names g16761 g19490 +0 1 +.names g4671 g14584 g17219 +00 1 +.names g17219 g19491 +0 1 +.names g14702 g9928 g18218 +0- 1 +-0 1 +.names g18218 g19494 +0 1 +.names g16767 g19498 +0 1 +.names g16775 g19502 +0 1 +.names g16785 g19504 +0 1 +.names g16895 g19505 +0 1 +.names g16788 g19511 +0 1 +.names g4848 g14618 g17221 +00 1 +.names g17221 g19512 +0 1 +.names g14736 g10082 g18325 +0- 1 +-0 1 +.names g18325 g19515 +0 1 +.names g16794 g19519 +0 1 +.names g16814 g19523 +0 1 +.names g16924 g19524 +0 1 +.names g16817 g19530 +0 1 +.names g16832 g19533 +0 1 +.names g16954 g19534 +0 1 +.names g14690 g12477 g16654 +00 1 +.names g16654 II25966 +0 1 +.names II25966 g19543 +0 1 +.names g14724 g12494 g16671 +00 1 +.names g16671 II25971 +0 1 +.names II25971 g19546 +0 1 +.names g14752 g12514 g16692 +00 1 +.names g16692 II25977 +0 1 +.names II25977 g19550 +0 1 +.names g14773 g12531 g16718 +00 1 +.names g16718 II25985 +0 1 +.names II25985 g19556 +0 1 +.names g15828 g13031 g16860 +00 1 +.names g16860 II25994 +0 1 +.names II25994 g19563 +0 1 +.names g15840 g13042 g16866 +00 1 +.names g16866 II26006 +0 1 +.names II26006 g19573 +0 1 +.names g16881 g19577 +0 1 +.names g16884 g19578 +0 1 +.names g15593 g12908 g16803 +00 1 +.names g16803 II26025 +0 1 +.names II26025 g19595 +0 1 +.names II22631 II22632 g16566 +0- 1 +-0 1 +.names g16566 II26028 +0 1 +.names II26028 g19596 +0 1 +.names g16910 g19607 +0 1 +.names g16913 g19608 +0 1 +.names g15658 g12938 g16824 +00 1 +.names g16824 II26051 +0 1 +.names II26051 g19622 +0 1 +.names g16940 g19640 +0 1 +.names g16943 g19641 +0 1 +.names g15717 g12966 g16835 +00 1 +.names g16835 II26078 +0 1 +.names II26078 g19652 +0 1 +.names g16085 g6363 g18085 +00 1 +.names g18085 II26085 +0 1 +.names II26085 g19657 +0 1 +.names g16971 g19680 +0 1 +.names g16974 g19681 +0 1 +.names g15754 g12989 g16844 +00 1 +.names g16844 II26112 +0 1 +.names II26112 g19689 +0 1 +.names g15755 g12990 g16845 +00 1 +.names g16845 II26115 +0 1 +.names II26115 g19690 +0 1 +.names g17503 II26123 +0 1 +.names II26123 g19696 +0 1 +.names g16123 g6568 g18201 +00 1 +.names g18201 II26134 +0 1 +.names II26134 g19705 +0 1 +.names g15781 g13000 g16851 +00 1 +.names g16851 II26154 +0 1 +.names II26154 g19725 +0 1 +.names g17594 II26171 +0 1 +.names II26171 g19740 +0 1 +.names g16174 g6832 g18308 +00 1 +.names g18308 II26182 +0 1 +.names II26182 g19749 +0 1 +.names g15801 g13009 g16853 +00 1 +.names g16853 II26195 +0 1 +.names II26195 g19762 +0 1 +.names g15802 g13010 g16854 +00 1 +.names g16854 II26198 +0 1 +.names II26198 g19763 +0 1 +.names g17691 II26220 +0 1 +.names II26220 g19783 +0 1 +.names g16233 g7134 g18401 +00 1 +.names g18401 II26231 +0 1 +.names II26231 g19792 +0 1 +.names g15817 g13023 g16857 +00 1 +.names g16857 II26237 +0 1 +.names II26237 g19798 +0 1 +.names g17791 II26266 +0 1 +.names II26266 g19825 +0 1 +.names g18886 g19830 +0 1 +.names g15829 g13032 g16861 +00 1 +.names g16861 II26276 +0 1 +.names II26276 g19838 +0 1 +.names g15797 g3006 g18977 +0- 1 +-0 1 +.names g18977 II26334 +0 1 +.names II26334 g19890 +0 1 +.names g15852 g13056 g16880 +00 1 +.names g16880 II26337 +0 1 +.names II26337 g19893 +0 1 +.names g17025 II26340 +0 1 +.names II26340 g19894 +0 1 +.names g16463 g7549 g18626 +00 1 +.names g18626 II26365 +0 1 +.names II26365 g19915 +0 1 +.names g18646 g19918 +0 1 +.names g17059 II26369 +0 1 +.names II26369 g19919 +0 1 +.names g14249 g16082 g18548 +00 1 +.names g18548 g19933 +0 1 +.names g17094 II26388 +0 1 +.names II26388 g19934 +0 1 +.names g14657 g14642 g15859 g17012 +000 1 +.names g17012 II26401 +0 1 +.names II26401 g19945 +0 1 +.names g14352 g16020 g17896 +00 1 +.names g17896 g19948 +0 1 +.names g14371 g16120 g18598 +00 1 +.names g18598 g19950 +0 1 +.names g17132 II26407 +0 1 +.names II26407 g19951 +0 1 +.names g15904 g14642 g15859 g16643 +000 1 +.names g16643 II26413 +0 1 +.names II26413 g19957 +0 1 +.names g14691 g14669 g15890 g17042 +000 1 +.names g17042 II26420 +0 1 +.names II26420 g19972 +0 1 +.names g14464 g16036 g18007 +00 1 +.names g18007 g19975 +0 1 +.names g14483 g16171 g18630 +00 1 +.names g18630 g19977 +0 1 +.names g15873 g2896 g16536 +0- 1 +-0 1 +.names g16536 II26426 +0 1 +.names II26426 g19978 +0 1 +.names g15933 g14669 g15890 g16655 +000 1 +.names g16655 II26437 +0 1 +.names II26437 g19987 +0 1 +.names g14725 g14703 g15923 g17076 +000 1 +.names g17076 II26444 +0 1 +.names II26444 g20002 +0 1 +.names g14551 g16058 g18124 +00 1 +.names g18124 g20005 +0 1 +.names g14570 g16230 g18639 +00 1 +.names g18639 g20007 +0 1 +.names g17985 II26458 +0 1 +.names II26458 g20016 +0 1 +.names g15962 g14703 g15923 g16672 +000 1 +.names g16672 II26469 +0 1 +.names II26469 g20025 +0 1 +.names g14753 g14737 g15952 g17111 +000 1 +.names g17111 II26476 +0 1 +.names II26476 g20040 +0 1 +.names g14606 g16094 g18240 +00 1 +.names g18240 g20043 +0 1 +.names g16439 g7522 g18590 +00 1 +.names g18590 II26481 +0 1 +.names II26481 g20045 +0 1 +.names g18102 II26494 +0 1 +.names II26494 g20058 +0 1 +.names g15981 g14737 g15952 g16693 +000 1 +.names g16693 II26505 +0 1 +.names II26505 g20067 +0 1 +.names g13469 g3897 g16802 +00 1 +.names g16802 II26512 +0 1 +.names II26512 g20082 +0 1 +.names II24006 II24007 g17968 +0- 1 +-0 1 +.names g17968 g20083 +0 1 +.names g18218 II26535 +0 1 +.names II26535 g20099 +0 1 +.names g5362 g13469 g16823 +00 1 +.names g16823 II26545 +0 1 +.names II26545 g20105 +0 1 +.names g18325 II26574 +0 1 +.names II26574 g20124 +0 1 +.names g15902 g2814 g18623 +00 1 +.names g18623 g20127 +0 1 +.names g16830 g20140 +0 1 +.names g11623 g15659 g17973 +1- 1 +-1 1 +.names g17973 g20163 +0 1 +.names g17645 II26612 +0 1 +.names II26612 g20164 +0 1 +.names g16842 g20178 +0 1 +.names g18691 g20193 +0 1 +.names g17746 II26642 +0 1 +.names II26642 g20198 +0 1 +.names g16848 g20212 +0 1 +.names g18727 g20223 +0 1 +.names g17847 II26664 +0 1 +.names II26664 g20228 +0 1 +.names g16852 g20242 +0 1 +.names g18764 g20250 +0 1 +.names g17959 II26679 +0 1 +.names II26679 g20255 +0 1 +.names g17230 g20269 +0 1 +.names g18795 g20273 +0 1 +.names g17237 g20278 +0 1 +.names g17240 g20279 +0 1 +.names g17243 g20281 +0 1 +.names g17249 g20286 +0 1 +.names g17252 g20287 +0 1 +.names g17255 g20288 +0 1 +.names g17259 g20289 +0 1 +.names g17262 g20290 +0 1 +.names g17265 g20292 +0 1 +.names g17720 II26714 +0 1 +.names II26714 g20295 +0 1 +.names g17272 g20296 +0 1 +.names g17275 g20297 +0 1 +.names g17278 g20298 +0 1 +.names g17282 g20302 +0 1 +.names g17285 g20303 +0 1 +.names g17288 g20304 +0 1 +.names g17291 g20305 +0 1 +.names g17294 g20306 +0 1 +.names g17297 g20308 +0 1 +.names g17304 g20311 +0 1 +.names g17307 g20312 +0 1 +.names g17310 g20313 +0 1 +.names g17315 g20315 +0 1 +.names g17318 g20316 +0 1 +.names g17321 g20317 +0 1 +.names g17324 g20321 +0 1 +.names g17327 g20322 +0 1 +.names g17330 g20323 +0 1 +.names g17333 g20324 +0 1 +.names g17336 g20325 +0 1 +.names g17342 g20327 +0 1 +.names g17345 g20328 +0 1 +.names g17348 g20329 +0 1 +.names g17354 g20330 +0 1 +.names g17357 g20331 +0 1 +.names g17360 g20332 +0 1 +.names g17363 g20334 +0 1 +.names g17366 g20335 +0 1 +.names g17369 g20336 +0 1 +.names g17372 g20340 +0 1 +.names g17375 g20341 +0 1 +.names g17378 g20342 +0 1 +.names g17384 g20344 +0 1 +.names g17387 g20345 +0 1 +.names g17390 g20346 +0 1 +.names g17399 g20347 +0 1 +.names g17402 g20348 +0 1 +.names g17405 g20349 +0 1 +.names g17410 g20350 +0 1 +.names g17413 g20351 +0 1 +.names g17416 g20352 +0 1 +.names g17419 g20354 +0 1 +.names g17422 g20355 +0 1 +.names g17425 g20356 +0 1 +.names g15998 g16003 g17222 +00 1 +.names g17222 II26777 +0 1 +.names II26777 g20360 +0 1 +.names g17430 g20361 +0 1 +.names g17433 g20362 +0 1 +.names g17436 g20363 +0 1 +.names g17439 g20364 +0 1 +.names g17442 g20365 +0 1 +.names g17451 g20366 +0 1 +.names g17454 g20367 +0 1 +.names g17457 g20368 +0 1 +.names g17465 g20369 +0 1 +.names g17468 g20370 +0 1 +.names g17471 g20371 +0 1 +.names g17476 g20372 +0 1 +.names g17479 g20373 +0 1 +.names g17482 g20374 +0 1 +.names g16004 g16009 g17224 +00 1 +.names g17224 II26796 +0 1 +.names II26796 g20377 +0 1 +.names g17487 g20378 +0 1 +.names g17490 g20379 +0 1 +.names g17493 g20380 +0 1 +.names g17496 g20381 +0 1 +.names g17500 g20382 +0 1 +.names g17503 g20383 +0 1 +.names g17511 g20384 +0 1 +.names g17514 g20385 +0 1 +.names g17517 g20386 +0 1 +.names g17520 g20387 +0 1 +.names g17523 g20388 +0 1 +.names g17531 g20389 +0 1 +.names g17534 g20390 +0 1 +.names g17537 g20391 +0 1 +.names g17545 g20392 +0 1 +.names g17548 g20393 +0 1 +.names g17551 g20394 +0 1 +.names g16008 g16015 g17225 +00 1 +.names g17225 II26816 +0 1 +.names II26816 g20395 +0 1 +.names g16010 g16017 g17226 +00 1 +.names g17226 II26819 +0 1 +.names II26819 g20396 +0 1 +.names g17557 g20397 +0 1 +.names g17560 g20398 +0 1 +.names g17563 g20399 +0 1 +.names g17567 g20400 +0 1 +.names g17570 g20401 +0 1 +.names g17573 g20402 +0 1 +.names g17579 g20403 +0 1 +.names g17582 g20404 +0 1 +.names g17585 g20405 +0 1 +.names g17588 g20406 +0 1 +.names g17591 g20407 +0 1 +.names g17594 g20408 +0 1 +.names g17601 g20409 +0 1 +.names g17604 g20410 +0 1 +.names g17607 g20411 +0 1 +.names g17610 g20412 +0 1 +.names g17613 g20413 +0 1 +.names g17621 g20414 +0 1 +.names g17624 g20415 +0 1 +.names g17627 g20416 +0 1 +.names g16016 g16029 g17228 +00 1 +.names g17228 II26843 +0 1 +.names II26843 g20418 +0 1 +.names g16019 g16032 g17229 +00 1 +.names g17229 II26846 +0 1 +.names II26846 g20419 +0 1 +.names g17637 g20420 +0 1 +.names g17649 g20421 +0 1 +.names g17655 g20422 +0 1 +.names g17658 g20423 +0 1 +.names g17661 g20424 +0 1 +.names g17664 g20425 +0 1 +.names g17667 g20426 +0 1 +.names g17670 g20427 +0 1 +.names g17676 g20428 +0 1 +.names g17679 g20429 +0 1 +.names g17682 g20430 +0 1 +.names g17685 g20431 +0 1 +.names g17688 g20432 +0 1 +.names g17691 g20433 +0 1 +.names g17698 g20434 +0 1 +.names g17701 g20435 +0 1 +.names g17704 g20436 +0 1 +.names g17707 g20437 +0 1 +.names g17710 g20438 +0 1 +.names g16028 g16045 g17234 +00 1 +.names g17234 II26868 +0 1 +.names II26868 g20439 +0 1 +.names g16030 g16047 g17235 +00 1 +.names g17235 II26871 +0 1 +.names II26871 g20440 +0 1 +.names g16033 g16051 g17236 +00 1 +.names g17236 II26874 +0 1 +.names II26874 g20441 +0 1 +.names g17738 g20442 +0 1 +.names g17749 g20443 +0 1 +.names g17755 g20444 +0 1 +.names g17758 g20445 +0 1 +.names g17761 g20446 +0 1 +.names g17764 g20447 +0 1 +.names g17767 g20448 +0 1 +.names g17770 g20449 +0 1 +.names g17776 g20450 +0 1 +.names g17779 g20451 +0 1 +.names g17782 g20452 +0 1 +.names g17785 g20453 +0 1 +.names g17788 g20454 +0 1 +.names g17791 g20455 +0 1 +.names g17799 g20456 +0 1 +.names g16046 g16066 g17246 +00 1 +.names g17246 II26892 +0 1 +.names II26892 g20457 +0 1 +.names g16050 g16070 g17247 +00 1 +.names g17247 II26895 +0 1 +.names II26895 g20458 +0 1 +.names g16052 g16072 g17248 +00 1 +.names g17248 II26898 +0 1 +.names II26898 g20459 +0 1 +.names g17839 g20461 +0 1 +.names g17850 g20462 +0 1 +.names g17856 g20463 +0 1 +.names g17859 g20464 +0 1 +.names g17862 g20465 +0 1 +.names g17865 g20466 +0 1 +.names g17868 g20467 +0 1 +.names g17871 g20468 +0 1 +.names g16067 g16100 g17269 +00 1 +.names g17269 II26910 +0 1 +.names II26910 g20469 +0 1 +.names g16071 g16104 g17270 +00 1 +.names g17270 II26913 +0 1 +.names II26913 g20470 +0 1 +.names g16073 g16106 g17271 +00 1 +.names g17271 II26916 +0 1 +.names II26916 g20471 +0 1 +.names g17951 g20476 +0 1 +.names g17962 g20477 +0 1 +.names g16103 g16135 g17302 +00 1 +.names g17302 II26923 +0 1 +.names II26923 g20478 +0 1 +.names g16105 g16137 g17303 +00 1 +.names g17303 II26926 +0 1 +.names II26926 g20479 +0 1 +.names g16136 g16183 g17340 +00 1 +.names g17340 II26931 +0 1 +.names II26931 g20484 +0 1 +.names g16138 g16185 g17341 +00 1 +.names g17341 II26934 +0 1 +.names II26934 g20485 +0 1 +.names g18166 g20490 +0 1 +.names g16184 g16238 g17383 +00 1 +.names g17383 II26940 +0 1 +.names II26940 g20491 +0 1 +.names g18258 g20496 +0 1 +.names g16239 g16288 g17429 +00 1 +.names g17429 II26947 +0 1 +.names II26947 g20498 +0 1 +.names g18278 g20500 +0 1 +.names g18334 g20501 +0 1 +.names g18355 g20504 +0 1 +.names g18371 g20505 +0 1 +.names g18351 g20507 +0 1 +.names g16884 II26960 +0 1 +.names II26960 g20513 +0 1 +.names g18432 g20516 +0 1 +.names g18450 g20517 +0 1 +.names g18466 g20518 +0 1 +.names g17051 II26966 +0 1 +.names II26966 g20519 +0 1 +.names g18446 g20526 +0 1 +.names g16913 II26972 +0 1 +.names II26972 g20531 +0 1 +.names g18505 g20534 +0 1 +.names g18523 g20535 +0 1 +.names g18539 g20536 +0 1 +.names g17086 II26980 +0 1 +.names II26980 g20539 +0 1 +.names g18519 g20545 +0 1 +.names g16943 II26985 +0 1 +.names II26985 g20550 +0 1 +.names g18569 g20553 +0 1 +.names g18587 g20554 +0 1 +.names g19145 II26990 +0 1 +.names g19159 II26993 +0 1 +.names g19169 II26996 +0 1 +.names g19543 II26999 +0 1 +.names g19147 II27002 +0 1 +.names g19164 II27005 +0 1 +.names g19175 II27008 +0 1 +.names g19546 II27011 +0 1 +.names g19151 II27014 +0 1 +.names g19170 II27017 +0 1 +.names g19182 II27020 +0 1 +.names g19550 II27023 +0 1 +.names g19156 II27026 +0 1 +.names g19176 II27029 +0 1 +.names g19189 II27032 +0 1 +.names g19556 II27035 +0 1 +.names g20082 II27038 +0 1 +.names g19237 II27041 +0 1 +.names g19247 II27044 +0 1 +.names g19258 II27047 +0 1 +.names g19183 II27050 +0 1 +.names g19190 II27053 +0 1 +.names g19196 II27056 +0 1 +.names g19207 II27059 +0 1 +.names g19217 II27062 +0 1 +.names g19270 II27065 +0 1 +.names g19197 II27068 +0 1 +.names g19218 II27071 +0 1 +.names g19238 II27074 +0 1 +.names g19259 II27077 +0 1 +.names g19198 II27080 +0 1 +.names g19208 II27083 +0 1 +.names g19229 II27086 +0 1 +.names g20105 II27089 +0 1 +.names g19174 II27092 +0 1 +.names g19185 II27095 +0 1 +.names g19199 II27098 +0 1 +.names g19220 II27101 +0 1 +.names g19239 II27104 +0 1 +.names g19249 II27107 +0 1 +.names g19622 II27110 +0 1 +.names g19689 II27113 +0 1 +.names g19762 II27116 +0 1 +.names g19563 II27119 +0 1 +.names g19595 II27122 +0 1 +.names g19652 II27125 +0 1 +.names g19725 II27128 +0 1 +.names g19798 II27131 +0 1 +.names g19573 II27134 +0 1 +.names g19596 II27137 +0 1 +.names g19690 II27140 +0 1 +.names g19763 II27143 +0 1 +.names g19838 II27146 +0 1 +.names g19893 II27149 +0 1 +.names g20360 II27152 +0 1 +.names g20395 II27155 +0 1 +.names g20439 II27158 +0 1 +.names g20377 II27161 +0 1 +.names g20418 II27164 +0 1 +.names g20457 II27167 +0 1 +.names g20396 II27170 +0 1 +.names g20440 II27173 +0 1 +.names g20469 II27176 +0 1 +.names g20419 II27179 +0 1 +.names g20458 II27182 +0 1 +.names g20478 II27185 +0 1 +.names g20441 II27188 +0 1 +.names g20470 II27191 +0 1 +.names g20484 II27194 +0 1 +.names g20459 II27197 +0 1 +.names g20479 II27200 +0 1 +.names g20491 II27203 +0 1 +.names g20471 II27206 +0 1 +.names g20485 II27209 +0 1 +.names g20498 II27212 +0 1 +.names g19158 II27215 +0 1 +.names g19168 II27218 +0 1 +.names g19180 II27221 +0 1 +.names g19358 II27225 +0 1 +.names II27225 g20634 +0 1 +.names g19390 II27228 +0 1 +.names II27228 g20637 +0 1 +.names g19401 II27232 +0 1 +.names II27232 g20641 +0 1 +.names g19420 II27235 +0 1 +.names II27235 g20644 +0 1 +.names g19335 II27240 +0 1 +.names II27240 g20649 +0 1 +.names g19335 II27243 +0 1 +.names II27243 g20652 +0 1 +.names g19335 II27246 +0 1 +.names II27246 g20655 +0 1 +.names g19390 II27250 +0 1 +.names II27250 g20659 +0 1 +.names g19420 II27253 +0 1 +.names II27253 g20662 +0 1 +.names g19431 II27257 +0 1 +.names II27257 g20666 +0 1 +.names g19457 II27260 +0 1 +.names II27260 g20669 +0 1 +.names g19358 II27264 +0 1 +.names II27264 g20673 +0 1 +.names g19358 II27267 +0 1 +.names II27267 g20676 +0 1 +.names g19335 II27270 +0 1 +.names II27270 g20679 +0 1 +.names g19369 II27275 +0 1 +.names II27275 g20684 +0 1 +.names g19369 II27278 +0 1 +.names II27278 g20687 +0 1 +.names g19369 II27281 +0 1 +.names II27281 g20690 +0 1 +.names g19420 II27285 +0 1 +.names II27285 g20694 +0 1 +.names g19457 II27288 +0 1 +.names II27288 g20697 +0 1 +.names g19335 II27293 +0 1 +.names II27293 g20704 +0 1 +.names g19390 II27297 +0 1 +.names II27297 g20708 +0 1 +.names g19390 II27300 +0 1 +.names II27300 g20711 +0 1 +.names g19369 II27303 +0 1 +.names II27303 g20714 +0 1 +.names g19401 II27308 +0 1 +.names II27308 g20719 +0 1 +.names g19401 II27311 +0 1 +.names II27311 g20722 +0 1 +.names g19401 II27314 +0 1 +.names II27314 g20725 +0 1 +.names g19457 II27318 +0 1 +.names II27318 g20729 +0 1 +.names g19335 II27321 +0 1 +.names II27321 g20732 +0 1 +.names g19358 II27324 +0 1 +.names II27324 g20735 +0 1 +.names g19369 II27328 +0 1 +.names II27328 g20739 +0 1 +.names g19420 II27332 +0 1 +.names II27332 g20743 +0 1 +.names g19420 II27335 +0 1 +.names II27335 g20746 +0 1 +.names g19401 II27338 +0 1 +.names II27338 g20749 +0 1 +.names g19431 II27343 +0 1 +.names II27343 g20754 +0 1 +.names g19431 II27346 +0 1 +.names II27346 g20757 +0 1 +.names g19431 II27349 +0 1 +.names II27349 g20760 +0 1 +.names g19358 II27352 +0 1 +.names II27352 g20763 +0 1 +.names g19335 II27355 +0 1 +.names II27355 g20766 +0 1 +.names g19369 II27358 +0 1 +.names II27358 g20769 +0 1 +.names g19390 II27361 +0 1 +.names II27361 g20772 +0 1 +.names g19401 II27365 +0 1 +.names II27365 g20776 +0 1 +.names g19457 II27369 +0 1 +.names II27369 g20780 +0 1 +.names g19457 II27372 +0 1 +.names II27372 g20783 +0 1 +.names g19431 II27375 +0 1 +.names II27375 g20786 +0 1 +.names g19358 II27379 +0 1 +.names II27379 g20790 +0 1 +.names g19390 II27382 +0 1 +.names II27382 g20793 +0 1 +.names g19369 II27385 +0 1 +.names II27385 g20796 +0 1 +.names g19401 II27388 +0 1 +.names II27388 g20799 +0 1 +.names g19420 II27391 +0 1 +.names II27391 g20802 +0 1 +.names g19431 II27395 +0 1 +.names II27395 g20806 +0 1 +.names g19390 II27399 +0 1 +.names II27399 g20810 +0 1 +.names g19420 II27402 +0 1 +.names II27402 g20813 +0 1 +.names g19401 II27405 +0 1 +.names II27405 g20816 +0 1 +.names g19431 II27408 +0 1 +.names II27408 g20819 +0 1 +.names g19457 II27411 +0 1 +.names II27411 g20822 +0 1 +.names g19420 II27416 +0 1 +.names II27416 g20827 +0 1 +.names g19457 II27419 +0 1 +.names II27419 g20830 +0 1 +.names g19431 II27422 +0 1 +.names II27422 g20833 +0 1 +.names g19457 II27426 +0 1 +.names II27426 g20837 +0 1 +.names g19441 g20842 +0 1 +.names g19468 g20850 +0 1 +.names g19491 g20858 +0 1 +.names g19512 g20866 +0 1 +.names g16607 g9636 g19865 +0- 1 +-0 1 +.names g19865 g20885 +0 1 +.names g16625 g9782 g19896 +0- 1 +-0 1 +.names g19896 g20904 +0 1 +.names g16639 g9928 g19921 +0- 1 +-0 1 +.names g19921 g20928 +0 1 +.names g16850 g13654 g20310 +00 1 +.names g20310 II27488 +0 1 +.names II27488 g20942 +0 1 +.names g13646 g16855 g20314 +00 1 +.names g20314 II27491 +0 1 +.names II27491 g20943 +0 1 +.names g16650 g10082 g19936 +0- 1 +-0 1 +.names g19936 g20956 +0 1 +.names g13672 g16859 g20333 +00 1 +.names g20333 II27516 +0 1 +.names II27516 g20971 +0 1 +.names g16856 g13703 g20343 +00 1 +.names g20343 II27531 +0 1 +.names II27531 g20984 +0 1 +.names g20083 II27534 +0 1 +.names II27534 g20985 +0 1 +.names g19957 II27537 +0 1 +.names II27537 g20986 +0 1 +.names g13702 g16864 g20353 +00 1 +.names g20353 II27549 +0 1 +.names II27549 g20998 +0 1 +.names g19987 II27565 +0 1 +.names II27565 g21012 +0 1 +.names g13739 g16879 g20375 +00 1 +.names g20375 II27577 +0 1 +.names II27577 g21024 +0 1 +.names g16865 g13787 g20376 +00 1 +.names g20376 II27585 +0 1 +.names II27585 g21030 +0 1 +.names g20025 II27593 +0 1 +.names II27593 g21036 +0 1 +.names g20513 g21050 +0 1 +.names g20067 II27614 +0 1 +.names II27614 g21057 +0 1 +.names g16907 g13833 g20417 +00 1 +.names g20417 II27621 +0 1 +.names II27621 g21064 +0 1 +.names g20519 g21066 +0 1 +.names g20531 g21069 +0 1 +.names g20539 g21076 +0 1 +.names g20550 g21079 +0 1 +.names g20507 II27646 +0 1 +.names II27646 g21087 +0 1 +.names g19064 g21090 +0 1 +.names g19075 g21093 +0 1 +.names g20526 II27658 +0 1 +.names II27658 g21099 +0 1 +.names g19081 g21102 +0 1 +.names g20507 II27667 +0 1 +.names II27667 g21108 +0 1 +.names g20545 II27672 +0 1 +.names II27672 g21113 +0 1 +.names g20526 II27684 +0 1 +.names II27684 g21125 +0 1 +.names g19070 II27689 +0 1 +.names II27689 g21130 +0 1 +.names g20545 II27705 +0 1 +.names II27705 g21144 +0 1 +.names g19070 II27727 +0 1 +.names II27727 g21164 +0 1 +.names g17186 g92 g19954 +0- 1 +-0 1 +.names g19954 II27749 +0 1 +.names II27749 g21184 +0 1 +.names g19113 g21187 +0 1 +.names g17197 g780 g19984 +0- 1 +-0 1 +.names g19984 II27766 +0 1 +.names II27766 g21199 +0 1 +.names g19118 g21202 +0 1 +.names g17204 g1466 g20022 +0- 1 +-0 1 +.names g20022 II27779 +0 1 +.names II27779 g21214 +0 1 +.names g19125 g21217 +0 1 +.names g17209 g2160 g20064 +0- 1 +-0 1 +.names g20064 II27785 +0 1 +.names II27785 g21222 +0 1 +.names g19132 g21225 +0 1 +.names g19945 g21241 +0 1 +.names g19972 g21249 +0 1 +.names g20002 g21258 +0 1 +.names g20040 g21266 +0 1 +.names g19865 II27822 +0 1 +.names II27822 g21271 +0 1 +.names g19896 II27827 +0 1 +.names II27827 g21278 +0 1 +.names g19921 II27832 +0 1 +.names II27832 g21285 +0 1 +.names g19936 II27838 +0 1 +.names II27838 g21293 +0 1 +.names g17268 g14884 g19144 +00 1 +.names g19144 II27868 +0 1 +.names II27868 g21327 +0 1 +.names g17339 g15020 g19149 +00 1 +.names g19149 II27897 +0 1 +.names II27897 g21358 +0 1 +.names g19096 II27900 +0 1 +.names II27900 g21359 +0 1 +.names g17381 g15093 g19153 +00 1 +.names g19153 II27917 +0 1 +.names II27917 g21376 +0 1 +.names g17382 g15094 g19154 +00 1 +.names g19154 II27920 +0 1 +.names II27920 g21377 +0 1 +.names g19957 II27927 +0 1 +.names II27927 g21382 +0 1 +.names g17428 g15171 g19157 +00 1 +.names g19157 II27942 +0 1 +.names II27942 g21399 +0 1 +.names g19918 g21400 +0 1 +.names g19957 II27949 +0 1 +.names II27949 g21404 +0 1 +.names g19987 II27958 +0 1 +.names II27958 g21415 +0 1 +.names g17485 g15243 g19162 +00 1 +.names g19162 II27969 +0 1 +.names II27969 g21426 +0 1 +.names g17486 g15244 g19163 +00 1 +.names g19163 II27972 +0 1 +.names II27972 g21427 +0 1 +.names g19957 II27976 +0 1 +.names II27976 g21429 +0 1 +.names g19987 II27984 +0 1 +.names II27984 g21441 +0 1 +.names g20025 II27992 +0 1 +.names II27992 g21449 +0 1 +.names g17556 g15320 g19167 +00 1 +.names g19167 II28000 +0 1 +.names II28000 g21457 +0 1 +.names g19957 II28003 +0 1 +.names II28003 g21458 +0 1 +.names g19957 g21461 +0 1 +.names g18085 g646 g20473 +0- 1 +-0 1 +.names g20473 II28009 +0 1 +.names II28009 g21473 +0 1 +.names g19987 II28013 +0 1 +.names II28013 g21477 +0 1 +.names g20025 II28019 +0 1 +.names II28019 g21483 +0 1 +.names g20067 II28027 +0 1 +.names II28027 g21491 +0 1 +.names g17635 g15388 g19172 +00 1 +.names g19172 II28031 +0 1 +.names II28031 g21495 +0 1 +.names g17636 g15389 g19173 +00 1 +.names g19173 II28034 +0 1 +.names II28034 g21496 +0 1 +.names g19957 II28038 +0 1 +.names II28038 g21498 +0 1 +.names g19987 II28043 +0 1 +.names II28043 g21505 +0 1 +.names g19987 g21508 +0 1 +.names g18201 g1332 g20481 +0- 1 +-0 1 +.names g20481 II28047 +0 1 +.names II28047 g21514 +0 1 +.names g20025 II28051 +0 1 +.names II28051 g21518 +0 1 +.names g20067 II28057 +0 1 +.names II28057 g21524 +0 1 +.names g17718 g15452 g19178 +00 1 +.names g19178 II28061 +0 1 +.names II28061 g21528 +0 1 +.names g19272 g21529 +0 1 +.names g19957 II28065 +0 1 +.names II28065 g21530 +0 1 +.names g19987 II28072 +0 1 +.names II28072 g21537 +0 1 +.names g20025 II28076 +0 1 +.names II28076 g21541 +0 1 +.names g20025 g21544 +0 1 +.names g18308 g2026 g20487 +0- 1 +-0 1 +.names g20487 II28080 +0 1 +.names II28080 g21550 +0 1 +.names g20067 II28084 +0 1 +.names II28084 g21554 +0 1 +.names g17798 g15520 g19184 +00 1 +.names g19184 II28087 +0 1 +.names II28087 g21557 +0 1 +.names g18977 g7338 g20008 +00 1 +.names g20008 II28090 +0 1 +.names II28090 g21558 +0 1 +.names g19957 II28093 +0 1 +.names II28093 g21561 +0 1 +.names g19291 g21565 +0 1 +.names g19987 II28100 +0 1 +.names II28100 g21566 +0 1 +.names g20025 II28107 +0 1 +.names II28107 g21573 +0 1 +.names g20067 II28111 +0 1 +.names II28111 g21577 +0 1 +.names g20067 g21580 +0 1 +.names g18401 g2720 g20493 +0- 1 +-0 1 +.names g20493 II28115 +0 1 +.names II28115 g21586 +0 1 +.names g19957 II28119 +0 1 +.names II28119 g21590 +0 1 +.names g19987 II28123 +0 1 +.names II28123 g21594 +0 1 +.names g19309 g21598 +0 1 +.names g20025 II28130 +0 1 +.names II28130 g21599 +0 1 +.names g20067 II28137 +0 1 +.names II28137 g21606 +0 1 +.names g19957 II28143 +0 1 +.names II28143 g21612 +0 1 +.names g19987 II28148 +0 1 +.names II28148 g21619 +0 1 +.names g20025 II28152 +0 1 +.names II28152 g21623 +0 1 +.names g19330 g21627 +0 1 +.names g20067 II28159 +0 1 +.names II28159 g21628 +0 1 +.names g19987 II28169 +0 1 +.names II28169 g21640 +0 1 +.names g20025 II28174 +0 1 +.names II28174 g21647 +0 1 +.names g20067 II28178 +0 1 +.names II28178 g21651 +0 1 +.names g18590 g2924 g19103 +0- 1 +-0 1 +.names g19103 II28184 +0 1 +.names II28184 g21655 +0 1 +.names g19091 g21661 +0 1 +.names g20025 II28201 +0 1 +.names II28201 g21671 +0 1 +.names g20067 II28206 +0 1 +.names II28206 g21678 +0 1 +.names g18626 g3036 g20537 +0- 1 +-0 1 +.names g20537 II28210 +0 1 +.names II28210 g21682 +0 1 +.names g19098 g21690 +0 1 +.names g20067 II28229 +0 1 +.names II28229 g21700 +0 1 +.names g16536 g7583 g20153 +00 1 +.names g20153 II28235 +0 1 +.names II28235 g21708 +0 1 +.names g19894 g21716 +0 1 +.names g19105 g21726 +0 1 +.names g19919 g21742 +0 1 +.names g19110 g21752 +0 1 +.names g19934 g21766 +0 1 +.names g19951 g21782 +0 1 +.names g5378 g18884 g19152 +0- 1 +-0 1 +.names g19152 II28314 +0 1 +.names II28314 g21795 +0 1 +.names g5410 g18886 g20497 +0- 1 +-0 1 +.names g20497 II28357 +0 1 +.names II28357 g21824 +0 1 +.names g20163 II28360 +0 1 +.names II28360 g21825 +0 1 +.names g19657 g21861 +0 1 +.names g19705 g21867 +0 1 +.names g19749 g21872 +0 1 +.names g19792 g21876 +0 1 +.names g19890 g21883 +0 1 +.names g19915 g21886 +0 1 +.names g19945 g21895 +0 1 +.names g19978 g21902 +0 1 +.names g19972 g21907 +0 1 +.names g19335 II28432 +0 1 +.names II28432 g21914 +0 1 +.names g19358 II28435 +0 1 +.names II28435 g21917 +0 1 +.names g20002 g21921 +0 1 +.names g20045 g21927 +0 1 +.names g19358 II28443 +0 1 +.names II28443 g21928 +0 1 +.names g19369 II28447 +0 1 +.names II28447 g21932 +0 1 +.names g19390 II28450 +0 1 +.names II28450 g21935 +0 1 +.names g20040 g21939 +0 1 +.names g20943 II28455 +0 1 +.names g20971 II28458 +0 1 +.names g20998 II28461 +0 1 +.names g21024 II28464 +0 1 +.names g20942 II28467 +0 1 +.names g20984 II28470 +0 1 +.names g21030 II28473 +0 1 +.names g21064 II28476 +0 1 +.names g21795 II28479 +0 1 +.names g21376 II28482 +0 1 +.names g21426 II28485 +0 1 +.names g21495 II28488 +0 1 +.names g21327 II28491 +0 1 +.names g21358 II28494 +0 1 +.names g21399 II28497 +0 1 +.names g21457 II28500 +0 1 +.names g21528 II28503 +0 1 +.names g21377 II28506 +0 1 +.names g21427 II28509 +0 1 +.names g21496 II28512 +0 1 +.names g21557 II28515 +0 1 +.names g20985 II28518 +0 1 +.names g21824 II28521 +0 1 +.names g21359 II28524 +0 1 +.names g20499 g13316 g21407 +00 1 +.names g21407 II28527 +0 1 +.names II28527 g21967 +0 1 +.names g20506 g13355 g21467 +00 1 +.names g21467 II28541 +0 1 +.names II28541 g21982 +0 1 +.names g20502 g13335 g21432 +00 1 +.names g21432 II28550 +0 1 +.names II28550 g21995 +0 1 +.names g21407 II28557 +0 1 +.names II28557 g22003 +0 1 +.names g20492 g13289 g21385 +00 1 +.names g21385 II28564 +0 1 +.names II28564 g22014 +0 1 +.names g13609 g19150 g21842 +00 1 +.names g21842 II28628 +0 1 +.names II28628 g22082 +0 1 +.names g13619 g19155 g21843 +00 1 +.names g21843 II28649 +0 1 +.names II28649 g22107 +0 1 +.names g13631 g19161 g21845 +00 1 +.names g21845 II28671 +0 1 +.names II28671 g22133 +0 1 +.names g13642 g19166 g21847 +00 1 +.names g21847 II28693 +0 1 +.names II28693 g22156 +0 1 +.names g19252 g8842 g21851 +00 1 +.names g21851 II28712 +0 1 +.names II28712 g22176 +0 1 +.names g21914 g22212 +0 1 +.names g21917 g22213 +0 1 +.names g21928 g22217 +0 1 +.names g20472 g16153 g21331 +00 1 +.names g21331 II28781 +0 1 +.names II28781 g22219 +0 1 +.names g21932 g22221 +0 1 +.names g21935 g22222 +0 1 +.names g16964 g19228 g21878 +00 1 +.names g21878 II28789 +0 1 +.names II28789 g22225 +0 1 +.names g13854 g19236 g21880 +00 1 +.names g21880 II28792 +0 1 +.names II28792 g22226 +0 1 +.names g20634 g22230 +0 1 +.names g20460 g16111 g21316 +00 1 +.names g21316 II28800 +0 1 +.names II28800 g22232 +0 1 +.names g20637 g22233 +0 1 +.names g20641 g22236 +0 1 +.names g20644 g22237 +0 1 +.names g20649 g22239 +0 1 +.names g20652 g22240 +0 1 +.names g20655 g22241 +0 1 +.names g20525 g16445 g21502 +00 1 +.names g21502 II28813 +0 1 +.names II28813 g22243 +0 1 +.names g20659 g22246 +0 1 +.names g20662 g22248 +0 1 +.names g20666 g22251 +0 1 +.names g20669 g22252 +0 1 +.names g13862 g19248 g21882 +00 1 +.names g21882 II28825 +0 1 +.names II28825 g22253 +0 1 +.names g20673 g22256 +0 1 +.names g20676 g22257 +0 1 +.names g20679 g22258 +0 1 +.names g20512 g16417 g21470 +00 1 +.names g21470 II28833 +0 1 +.names II28833 g22259 +0 1 +.names g20684 g22260 +0 1 +.names g20687 g22261 +0 1 +.names g20690 g22262 +0 1 +.names g20694 g22266 +0 1 +.names g20697 g22268 +0 1 +.names g20704 g22271 +0 1 +.names g20708 g22274 +0 1 +.names g20711 g22275 +0 1 +.names g20714 g22276 +0 1 +.names g20719 g22277 +0 1 +.names g20722 g22278 +0 1 +.names g20725 g22279 +0 1 +.names g20729 g22283 +0 1 +.names g20732 g22286 +0 1 +.names g20735 g22287 +0 1 +.names g20739 g22290 +0 1 +.names g20743 g22293 +0 1 +.names g20746 g22294 +0 1 +.names g20749 g22295 +0 1 +.names g20754 g22296 +0 1 +.names g20757 g22297 +0 1 +.names g20760 g22298 +0 1 +.names g19954 g5890 g21238 +00 1 +.names g21238 II28876 +0 1 +.names II28876 g22300 +0 1 +.names g20763 g22303 +0 1 +.names g20766 g22304 +0 1 +.names g20769 g22306 +0 1 +.names g20772 g22307 +0 1 +.names g20776 g22310 +0 1 +.names g20780 g22313 +0 1 +.names g20783 g22314 +0 1 +.names g20786 g22315 +0 1 +.names g20015 g19981 g21149 +00 1 +.names g21149 g22316 +0 1 +.names g20790 g22318 +0 1 +.names g19388 g17118 g21228 +00 1 +.names g21228 g22319 +0 1 +.names g19984 g5929 g21246 +00 1 +.names g21246 II28896 +0 1 +.names II28896 g22328 +0 1 +.names g20793 g22331 +0 1 +.names g20796 g22332 +0 1 +.names g20799 g22334 +0 1 +.names g20802 g22335 +0 1 +.names g20806 g22338 +0 1 +.names g20057 g20019 g21169 +00 1 +.names g21169 g22341 +0 1 +.names g20810 g22343 +0 1 +.names g19418 g17145 g21233 +00 1 +.names g21233 g22344 +0 1 +.names g20022 g5963 g21255 +00 1 +.names g21255 II28913 +0 1 +.names II28913 g22353 +0 1 +.names g20813 g22356 +0 1 +.names g20816 g22357 +0 1 +.names g20819 g22359 +0 1 +.names g20822 g22360 +0 1 +.names g20098 g20061 g21189 +00 1 +.names g21189 g22364 +0 1 +.names g20827 g22366 +0 1 +.names g19455 g17168 g21242 +00 1 +.names g21242 g22367 +0 1 +.names g20064 g5992 g21263 +00 1 +.names g21263 II28928 +0 1 +.names II28928 g22376 +0 1 +.names g20830 g22379 +0 1 +.names g20833 g22380 +0 1 +.names g20123 g20102 g21204 +00 1 +.names g21204 g22384 +0 1 +.names g20837 g22386 +0 1 +.names g19482 g17183 g21250 +00 1 +.names g21250 g22387 +0 1 +.names g17724 g18179 g19799 II28068 g21533 +1111 1 +.names g21533 g22401 +0 1 +.names g17825 g18286 g19843 II28103 g21569 +1111 1 +.names g21569 g22402 +0 1 +.names g17937 g18379 g19876 II28133 g21602 +1111 1 +.names g21602 g22403 +0 1 +.names g18048 g18474 g19907 II28162 g21631 +1111 1 +.names g21631 g22404 +0 1 +.names g20164 g6232 g21685 +0- 1 +-0 1 +.names g21685 II28949 +0 1 +.names II28949 g22405 +0 1 +.names g20986 g22408 +0 1 +.names g20164 g6314 g21659 +0- 1 +-0 1 +.names g21659 II28953 +0 1 +.names II28953 g22409 +0 1 +.names g20164 g6232 g21714 +0- 1 +-0 1 +.names g21714 II28956 +0 1 +.names II28956 g22412 +0 1 +.names g20473 g6513 g21636 +00 1 +.names g21636 II28959 +0 1 +.names II28959 g22415 +0 1 +.names g20198 g6369 g21721 +0- 1 +-0 1 +.names g21721 II28962 +0 1 +.names II28962 g22418 +0 1 +.names g21012 g22421 +0 1 +.names g20164 g3254 g20633 +0- 1 +-0 1 +.names g20633 II28966 +0 1 +.names II28966 g22422 +0 1 +.names g20164 g6314 g21686 +0- 1 +-0 1 +.names g21686 II28969 +0 1 +.names II28969 g22425 +0 1 +.names g20164 g6232 g21736 +0- 1 +-0 1 +.names g21736 II28972 +0 1 +.names II28972 g22428 +0 1 +.names g20198 g6519 g21688 +0- 1 +-0 1 +.names g21688 II28975 +0 1 +.names II28975 g22431 +0 1 +.names g20198 g6369 g21740 +0- 1 +-0 1 +.names g21740 II28978 +0 1 +.names II28978 g22434 +0 1 +.names g20481 g6777 g21667 +00 1 +.names g21667 II28981 +0 1 +.names II28981 g22437 +0 1 +.names g20228 g6574 g21747 +0- 1 +-0 1 +.names g21747 II28984 +0 1 +.names II28984 g22440 +0 1 +.names g21036 g22443 +0 1 +.names g17301 g19594 g20874 +00 1 +.names g20874 II28988 +0 1 +.names II28988 g22444 +0 1 +.names g20164 g3254 g20648 +0- 1 +-0 1 +.names g20648 II28991 +0 1 +.names II28991 g22445 +0 1 +.names g20164 g6314 g21715 +0- 1 +-0 1 +.names g21715 II28994 +0 1 +.names II28994 g22448 +0 1 +.names g20164 g6232 g21759 +0- 1 +-0 1 +.names g21759 II28997 +0 1 +.names II28997 g22451 +0 1 +.names g20198 g3410 g20658 +0- 1 +-0 1 +.names g20658 II29001 +0 1 +.names II29001 g22455 +0 1 +.names g20198 g6519 g21722 +0- 1 +-0 1 +.names g21722 II29004 +0 1 +.names II29004 g22458 +0 1 +.names g20198 g6369 g21760 +0- 1 +-0 1 +.names g21760 II29007 +0 1 +.names II29007 g22461 +0 1 +.names g20228 g6783 g21724 +0- 1 +-0 1 +.names g21724 II29010 +0 1 +.names II29010 g22464 +0 1 +.names g20228 g6574 g21764 +0- 1 +-0 1 +.names g21764 II29013 +0 1 +.names II29013 g22467 +0 1 +.names g20487 g7079 g21696 +00 1 +.names g21696 II29016 +0 1 +.names II29016 g22470 +0 1 +.names g20255 g6838 g21771 +0- 1 +-0 1 +.names g21771 II29019 +0 1 +.names II29019 g22473 +0 1 +.names g21057 g22476 +0 1 +.names g20164 g3254 g20672 +0- 1 +-0 1 +.names g20672 II29023 +0 1 +.names II29023 g22477 +0 1 +.names g20164 g6314 g21737 +0- 1 +-0 1 +.names g21737 II29026 +0 1 +.names II29026 g22480 +0 1 +.names g20198 g3410 g20683 +0- 1 +-0 1 +.names g20683 II29030 +0 1 +.names II29030 g22484 +0 1 +.names g20198 g6519 g21741 +0- 1 +-0 1 +.names g21741 II29033 +0 1 +.names II29033 g22487 +0 1 +.names g20198 g6369 g21775 +0- 1 +-0 1 +.names g21775 II29036 +0 1 +.names II29036 g22490 +0 1 +.names g20228 g3566 g20693 +0- 1 +-0 1 +.names g20693 II29040 +0 1 +.names II29040 g22494 +0 1 +.names g20228 g6783 g21748 +0- 1 +-0 1 +.names g21748 II29043 +0 1 +.names II29043 g22497 +0 1 +.names g20228 g6574 g21776 +0- 1 +-0 1 +.names g21776 II29046 +0 1 +.names II29046 g22500 +0 1 +.names g20255 g7085 g21750 +0- 1 +-0 1 +.names g21750 II29049 +0 1 +.names II29049 g22503 +0 1 +.names g20255 g6838 g21780 +0- 1 +-0 1 +.names g21780 II29052 +0 1 +.names II29052 g22506 +0 1 +.names g20493 g7329 g21732 +00 1 +.names g21732 II29055 +0 1 +.names II29055 g22509 +0 1 +.names g20164 g3254 g20703 +0- 1 +-0 1 +.names g20703 II29058 +0 1 +.names II29058 g22512 +0 1 +.names g19584 g17352 g20875 +00 1 +.names g20875 II29064 +0 1 +.names II29064 g22518 +0 1 +.names g19585 g17353 g20876 +00 1 +.names g20876 II29067 +0 1 +.names II29067 g22519 +0 1 +.names g20198 g3410 g20707 +0- 1 +-0 1 +.names g20707 II29070 +0 1 +.names II29070 g22520 +0 1 +.names g20198 g6519 g21761 +0- 1 +-0 1 +.names g21761 II29073 +0 1 +.names II29073 g22523 +0 1 +.names g20228 g3566 g20718 +0- 1 +-0 1 +.names g20718 II29077 +0 1 +.names II29077 g22527 +0 1 +.names g20228 g6783 g21765 +0- 1 +-0 1 +.names g21765 II29080 +0 1 +.names II29080 g22530 +0 1 +.names g20228 g6574 g21790 +0- 1 +-0 1 +.names g21790 II29083 +0 1 +.names II29083 g22533 +0 1 +.names g20255 g3722 g20728 +0- 1 +-0 1 +.names g20728 II29087 +0 1 +.names II29087 g22537 +0 1 +.names g20255 g7085 g21772 +0- 1 +-0 1 +.names g21772 II29090 +0 1 +.names II29090 g22540 +0 1 +.names g20255 g6838 g21791 +0- 1 +-0 1 +.names g21791 II29093 +0 1 +.names II29093 g22543 +0 1 +.names g21087 g22547 +0 1 +.names g19601 g17396 g20879 +00 1 +.names g20879 II29098 +0 1 +.names II29098 g22548 +0 1 +.names g19602 g17397 g20880 +00 1 +.names g20880 II29101 +0 1 +.names II29101 g22549 +0 1 +.names g19603 g17398 g20881 +00 1 +.names g20881 II29104 +0 1 +.names II29104 g22550 +0 1 +.names g20503 g16385 g21435 +00 1 +.names g21435 II29107 +0 1 +.names II29107 g22551 +0 1 +.names g20198 g3410 g20738 +0- 1 +-0 1 +.names g20738 II29110 +0 1 +.names II29110 g22552 +0 1 +.names g19614 g17408 g20882 +00 1 +.names g20882 II29116 +0 1 +.names II29116 g22558 +0 1 +.names g19615 g17409 g20883 +00 1 +.names g20883 II29119 +0 1 +.names II29119 g22559 +0 1 +.names g20228 g3566 g20742 +0- 1 +-0 1 +.names g20742 II29122 +0 1 +.names II29122 g22560 +0 1 +.names g20228 g6783 g21777 +0- 1 +-0 1 +.names g21777 II29125 +0 1 +.names II29125 g22563 +0 1 +.names g20255 g3722 g20753 +0- 1 +-0 1 +.names g20753 II29129 +0 1 +.names II29129 g22567 +0 1 +.names g20255 g7085 g21781 +0- 1 +-0 1 +.names g21781 II29132 +0 1 +.names II29132 g22570 +0 1 +.names g20255 g6838 g21804 +0- 1 +-0 1 +.names g21804 II29135 +0 1 +.names II29135 g22573 +0 1 +.names g19160 g10024 g20682 +00 1 +.names g20682 II29142 +0 1 +.names II29142 g22582 +0 1 +.names g19626 g17447 g20891 +00 1 +.names g20891 II29145 +0 1 +.names II29145 g22583 +0 1 +.names g19627 g17448 g20892 +00 1 +.names g20892 II29148 +0 1 +.names II29148 g22584 +0 1 +.names g19628 g17449 g20893 +00 1 +.names g20893 II29151 +0 1 +.names II29151 g22585 +0 1 +.names g19629 g17450 g20894 +00 1 +.names g20894 II29154 +0 1 +.names II29154 g22586 +0 1 +.names g21099 g22588 +0 1 +.names g19634 g17462 g20896 +00 1 +.names g20896 II29159 +0 1 +.names II29159 g22589 +0 1 +.names g19635 g17463 g20897 +00 1 +.names g20897 II29162 +0 1 +.names II29162 g22590 +0 1 +.names g19636 g17464 g20898 +00 1 +.names g20898 II29165 +0 1 +.names II29165 g22591 +0 1 +.names g20228 g3566 g20775 +0- 1 +-0 1 +.names g20775 II29168 +0 1 +.names II29168 g22592 +0 1 +.names g19647 g17474 g20899 +00 1 +.names g20899 II29174 +0 1 +.names II29174 g22598 +0 1 +.names g19648 g17475 g20900 +00 1 +.names g20900 II29177 +0 1 +.names II29177 g22599 +0 1 +.names g20255 g3722 g20779 +0- 1 +-0 1 +.names g20779 II29180 +0 1 +.names II29180 g22600 +0 1 +.names g20255 g7085 g21792 +0- 1 +-0 1 +.names g21792 II29183 +0 1 +.names II29183 g22603 +0 1 +.names g21108 g22609 +0 1 +.names g19660 g17508 g20901 +00 1 +.names g20901 II29191 +0 1 +.names II29191 g22611 +0 1 +.names g19661 g17509 g20902 +00 1 +.names g20902 II29194 +0 1 +.names II29194 g22612 +0 1 +.names g19662 g17510 g20903 +00 1 +.names g20903 II29197 +0 1 +.names II29197 g22613 +0 1 +.names g19165 g10133 g20717 +00 1 +.names g20717 II29203 +0 1 +.names II29203 g22619 +0 1 +.names g19666 g17527 g20910 +00 1 +.names g20910 II29206 +0 1 +.names II29206 g22620 +0 1 +.names g19667 g17528 g20911 +00 1 +.names g20911 II29209 +0 1 +.names II29209 g22621 +0 1 +.names g19668 g17529 g20912 +00 1 +.names g20912 II29212 +0 1 +.names II29212 g22622 +0 1 +.names g19669 g17530 g20913 +00 1 +.names g20913 II29215 +0 1 +.names II29215 g22623 +0 1 +.names g21113 g22625 +0 1 +.names g19674 g17542 g20915 +00 1 +.names g20915 II29220 +0 1 +.names II29220 g22626 +0 1 +.names g19675 g17543 g20916 +00 1 +.names g20916 II29223 +0 1 +.names II29223 g22627 +0 1 +.names g19676 g17544 g20917 +00 1 +.names g20917 II29226 +0 1 +.names II29226 g22628 +0 1 +.names g20255 g3722 g20805 +0- 1 +-0 1 +.names g20805 II29229 +0 1 +.names II29229 g22629 +0 1 +.names g19687 g17554 g20918 +00 1 +.names g20918 II29235 +0 1 +.names II29235 g22635 +0 1 +.names g19688 g17555 g20919 +00 1 +.names g20919 II29238 +0 1 +.names II29238 g22636 +0 1 +.names g19697 g17576 g20921 +00 1 +.names g20921 II29243 +0 1 +.names II29243 g22639 +0 1 +.names g19698 g17577 g20922 +00 1 +.names g20922 II29246 +0 1 +.names II29246 g22640 +0 1 +.names g19699 g17578 g20923 +00 1 +.names g20923 II29249 +0 1 +.names II29249 g22641 +0 1 +.names g19700 g15257 g20924 +00 1 +.names g20924 II29252 +0 1 +.names II29252 g22642 +0 1 +.names g21125 g22645 +0 1 +.names g19708 g17598 g20925 +00 1 +.names g20925 II29259 +0 1 +.names II29259 g22647 +0 1 +.names g19709 g17599 g20926 +00 1 +.names g20926 II29262 +0 1 +.names II29262 g22648 +0 1 +.names g19710 g17600 g20927 +00 1 +.names g20927 II29265 +0 1 +.names II29265 g22649 +0 1 +.names g19171 g10238 g20752 +00 1 +.names g20752 II29271 +0 1 +.names II29271 g22655 +0 1 +.names g19714 g17617 g20934 +00 1 +.names g20934 II29274 +0 1 +.names II29274 g22656 +0 1 +.names g19715 g17618 g20935 +00 1 +.names g20935 II29277 +0 1 +.names II29277 g22657 +0 1 +.names g19716 g17619 g20936 +00 1 +.names g20936 II29280 +0 1 +.names II29280 g22658 +0 1 +.names g19717 g17620 g20937 +00 1 +.names g20937 II29283 +0 1 +.names II29283 g22659 +0 1 +.names g21130 g22661 +0 1 +.names g19722 g17632 g20939 +00 1 +.names g20939 II29288 +0 1 +.names II29288 g22662 +0 1 +.names g19723 g17633 g20940 +00 1 +.names g20940 II29291 +0 1 +.names II29291 g22663 +0 1 +.names g19724 g17634 g20941 +00 1 +.names g20941 II29294 +0 1 +.names II29294 g22664 +0 1 +.names g19731 g17652 g20944 +00 1 +.names g20944 II29301 +0 1 +.names II29301 g22669 +0 1 +.names g19732 g17653 g20945 +00 1 +.names g20945 II29304 +0 1 +.names II29304 g22670 +0 1 +.names g19733 g17654 g20946 +00 1 +.names g20946 II29307 +0 1 +.names II29307 g22671 +0 1 +.names g19734 g15335 g20947 +00 1 +.names g20947 II29310 +0 1 +.names II29310 g22672 +0 1 +.names g19735 g15336 g20948 +00 1 +.names g20948 II29313 +0 1 +.names II29313 g22673 +0 1 +.names g19741 g17673 g20949 +00 1 +.names g20949 II29317 +0 1 +.names II29317 g22675 +0 1 +.names g19742 g17674 g20950 +00 1 +.names g20950 II29320 +0 1 +.names II29320 g22676 +0 1 +.names g19743 g17675 g20951 +00 1 +.names g20951 II29323 +0 1 +.names II29323 g22677 +0 1 +.names g19744 g15349 g20952 +00 1 +.names g20952 II29326 +0 1 +.names II29326 g22678 +0 1 +.names g21144 g22681 +0 1 +.names g19752 g17695 g20953 +00 1 +.names g20953 II29333 +0 1 +.names II29333 g22683 +0 1 +.names g19753 g17696 g20954 +00 1 +.names g20954 II29336 +0 1 +.names II29336 g22684 +0 1 +.names g19754 g17697 g20955 +00 1 +.names g20955 II29339 +0 1 +.names II29339 g22685 +0 1 +.names g19177 g10340 g20789 +00 1 +.names g20789 II29345 +0 1 +.names II29345 g22691 +0 1 +.names g19758 g17714 g20962 +00 1 +.names g20962 II29348 +0 1 +.names II29348 g22692 +0 1 +.names g19759 g17715 g20963 +00 1 +.names g20963 II29351 +0 1 +.names II29351 g22693 +0 1 +.names g19760 g17716 g20964 +00 1 +.names g20964 II29354 +0 1 +.names II29354 g22694 +0 1 +.names g19761 g17717 g20965 +00 1 +.names g20965 II29357 +0 1 +.names II29357 g22695 +0 1 +.names g19830 g13004 g21796 +00 1 +.names g21796 II29360 +0 1 +.names II29360 g22696 +0 1 +.names g19765 g17734 g20966 +00 1 +.names g20966 II29366 +0 1 +.names II29366 g22702 +0 1 +.names g19766 g17735 g20967 +00 1 +.names g20967 II29369 +0 1 +.names II29369 g22703 +0 1 +.names g19767 g17736 g20968 +00 1 +.names g20968 II29372 +0 1 +.names II29372 g22704 +0 1 +.names g19768 g15402 g20969 +00 1 +.names g20969 II29375 +0 1 +.names II29375 g22705 +0 1 +.names g19769 g15403 g20970 +00 1 +.names g20970 II29378 +0 1 +.names II29378 g22706 +0 1 +.names g19774 g17752 g20972 +00 1 +.names g20972 II29383 +0 1 +.names II29383 g22709 +0 1 +.names g19775 g17753 g20973 +00 1 +.names g20973 II29386 +0 1 +.names II29386 g22710 +0 1 +.names g19776 g17754 g20974 +00 1 +.names g20974 II29389 +0 1 +.names II29389 g22711 +0 1 +.names g19777 g15421 g20975 +00 1 +.names g20975 II29392 +0 1 +.names II29392 g22712 +0 1 +.names g19778 g15422 g20976 +00 1 +.names g20976 II29395 +0 1 +.names II29395 g22713 +0 1 +.names g19784 g17773 g20977 +00 1 +.names g20977 II29399 +0 1 +.names II29399 g22715 +0 1 +.names g19785 g17774 g20978 +00 1 +.names g20978 II29402 +0 1 +.names II29402 g22716 +0 1 +.names g19786 g17775 g20979 +00 1 +.names g20979 II29405 +0 1 +.names II29405 g22717 +0 1 +.names g19787 g15435 g20980 +00 1 +.names g20980 II29408 +0 1 +.names II29408 g22718 +0 1 +.names g21164 g22721 +0 1 +.names g19795 g17795 g20981 +00 1 +.names g20981 II29415 +0 1 +.names II29415 g22723 +0 1 +.names g19796 g17796 g20982 +00 1 +.names g20982 II29418 +0 1 +.names II29418 g22724 +0 1 +.names g19797 g17797 g20983 +00 1 +.names g20983 II29421 +0 1 +.names II29421 g22725 +0 1 +.names g19802 g17812 g20989 +00 1 +.names g20989 II29426 +0 1 +.names II29426 g22728 +0 1 +.names g19803 g17813 g20990 +00 1 +.names g20990 II29429 +0 1 +.names II29429 g22729 +0 1 +.names g19804 g17814 g20991 +00 1 +.names g20991 II29432 +0 1 +.names II29432 g22730 +0 1 +.names g19805 g15470 g20992 +00 1 +.names g20992 II29435 +0 1 +.names II29435 g22731 +0 1 +.names g19807 g17835 g20993 +00 1 +.names g20993 II29439 +0 1 +.names II29439 g22733 +0 1 +.names g19808 g17836 g20994 +00 1 +.names g20994 II29442 +0 1 +.names II29442 g22734 +0 1 +.names g19809 g17837 g20995 +00 1 +.names g20995 II29445 +0 1 +.names II29445 g22735 +0 1 +.names g19810 g15486 g20996 +00 1 +.names g20996 II29448 +0 1 +.names II29448 g22736 +0 1 +.names g19811 g15487 g20997 +00 1 +.names g20997 II29451 +0 1 +.names II29451 g22737 +0 1 +.names g19816 g17853 g20999 +00 1 +.names g20999 II29456 +0 1 +.names II29456 g22740 +0 1 +.names g19817 g17854 g21000 +00 1 +.names g21000 II29459 +0 1 +.names II29459 g22741 +0 1 +.names g19818 g17855 g21001 +00 1 +.names g21001 II29462 +0 1 +.names II29462 g22742 +0 1 +.names g19819 g15505 g21002 +00 1 +.names g21002 II29465 +0 1 +.names II29465 g22743 +0 1 +.names g19820 g15506 g21003 +00 1 +.names g21003 II29468 +0 1 +.names II29468 g22744 +0 1 +.names g19826 g17874 g21004 +00 1 +.names g21004 II29472 +0 1 +.names II29472 g22746 +0 1 +.names g19827 g17875 g21005 +00 1 +.names g21005 II29475 +0 1 +.names II29475 g22747 +0 1 +.names g19828 g17876 g21006 +00 1 +.names g21006 II29478 +0 1 +.names II29478 g22748 +0 1 +.names g19829 g15519 g21007 +00 1 +.names g21007 II29481 +0 1 +.names II29481 g22749 +0 1 +.names g20008 g3013 g21903 +0- 1 +-0 1 +.names g21903 II29484 +0 1 +.names II29484 g22750 +0 1 +.names g21184 g22753 +0 1 +.names g19839 g17900 g21009 +00 1 +.names g21009 II29490 +0 1 +.names II29490 g22756 +0 1 +.names g19840 g17901 g21010 +00 1 +.names g21010 II29493 +0 1 +.names II29493 g22757 +0 1 +.names g19841 g17902 g21011 +00 1 +.names g21011 II29496 +0 1 +.names II29496 g22758 +0 1 +.names g19846 g17924 g21015 +00 1 +.names g21015 II29500 +0 1 +.names II29500 g22760 +0 1 +.names g19847 g17925 g21016 +00 1 +.names g21016 II29503 +0 1 +.names II29503 g22761 +0 1 +.names g19848 g17926 g21017 +00 1 +.names g21017 II29506 +0 1 +.names II29506 g22762 +0 1 +.names g19849 g15556 g21018 +00 1 +.names g21018 II29509 +0 1 +.names II29509 g22763 +0 1 +.names g19851 g17947 g21019 +00 1 +.names g21019 II29513 +0 1 +.names II29513 g22765 +0 1 +.names g19852 g17948 g21020 +00 1 +.names g21020 II29516 +0 1 +.names II29516 g22766 +0 1 +.names g19853 g17949 g21021 +00 1 +.names g21021 II29519 +0 1 +.names II29519 g22767 +0 1 +.names g19854 g15572 g21022 +00 1 +.names g21022 II29522 +0 1 +.names II29522 g22768 +0 1 +.names g19855 g15573 g21023 +00 1 +.names g21023 II29525 +0 1 +.names II29525 g22769 +0 1 +.names g19860 g17965 g21025 +00 1 +.names g21025 II29530 +0 1 +.names II29530 g22772 +0 1 +.names g19861 g17966 g21026 +00 1 +.names g21026 II29533 +0 1 +.names II29533 g22773 +0 1 +.names g19862 g17967 g21027 +00 1 +.names g21027 II29536 +0 1 +.names II29536 g22774 +0 1 +.names g19863 g15591 g21028 +00 1 +.names g21028 II29539 +0 1 +.names II29539 g22775 +0 1 +.names g19864 g15592 g21029 +00 1 +.names g21029 II29542 +0 1 +.names II29542 g22776 +0 1 +.names g21796 g22777 +0 1 +.names g19869 g17989 g21031 +00 1 +.names g21031 II29547 +0 1 +.names II29547 g22785 +0 1 +.names g19870 g17990 g21032 +00 1 +.names g21032 II29550 +0 1 +.names II29550 g22786 +0 1 +.names g21199 g22787 +0 1 +.names g19872 g18011 g21033 +00 1 +.names g21033 II29556 +0 1 +.names II29556 g22790 +0 1 +.names g19873 g18012 g21034 +00 1 +.names g21034 II29559 +0 1 +.names II29559 g22791 +0 1 +.names g19874 g18013 g21035 +00 1 +.names g21035 II29562 +0 1 +.names II29562 g22792 +0 1 +.names g19879 g18035 g21039 +00 1 +.names g21039 II29566 +0 1 +.names II29566 g22794 +0 1 +.names g19880 g18036 g21040 +00 1 +.names g21040 II29569 +0 1 +.names II29569 g22795 +0 1 +.names g19881 g18037 g21041 +00 1 +.names g21041 II29572 +0 1 +.names II29572 g22796 +0 1 +.names g19882 g15634 g21042 +00 1 +.names g21042 II29575 +0 1 +.names II29575 g22797 +0 1 +.names g19884 g18058 g21043 +00 1 +.names g21043 II29579 +0 1 +.names II29579 g22799 +0 1 +.names g19885 g18059 g21044 +00 1 +.names g21044 II29582 +0 1 +.names II29582 g22800 +0 1 +.names g19886 g18060 g21045 +00 1 +.names g21045 II29585 +0 1 +.names II29585 g22801 +0 1 +.names g19887 g15650 g21046 +00 1 +.names g21046 II29588 +0 1 +.names II29588 g22802 +0 1 +.names g19888 g15651 g21047 +00 1 +.names g21047 II29591 +0 1 +.names II29591 g22803 +0 1 +.names g19317 g19356 g21894 +00 1 +.names g21894 g22805 +0 1 +.names g16567 g19957 g21615 +00 1 +.names g21615 g22806 +0 1 +.names g14256 g15177 g19871 g19842 g21720 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g21720 II29600 +0 1 +.names II29600 g22812 +0 1 +.names g19895 g18088 g21051 +00 1 +.names g21051 II29603 +0 1 +.names II29603 g22824 +0 1 +.names g20486 g13266 g21364 +00 1 +.names g21364 II29606 +0 1 +.names II29606 g22825 +0 1 +.names g19900 g18106 g21052 +00 1 +.names g21052 II29610 +0 1 +.names II29610 g22827 +0 1 +.names g19901 g18107 g21053 +00 1 +.names g21053 II29613 +0 1 +.names II29613 g22828 +0 1 +.names g21214 g22829 +0 1 +.names g19903 g18128 g21054 +00 1 +.names g21054 II29619 +0 1 +.names II29619 g22832 +0 1 +.names g19904 g18129 g21055 +00 1 +.names g21055 II29622 +0 1 +.names II29622 g22833 +0 1 +.names g19905 g18130 g21056 +00 1 +.names g21056 II29625 +0 1 +.names II29625 g22834 +0 1 +.names g19910 g18152 g21060 +00 1 +.names g21060 II29629 +0 1 +.names II29629 g22836 +0 1 +.names g19911 g18153 g21061 +00 1 +.names g21061 II29632 +0 1 +.names II29632 g22837 +0 1 +.names g19912 g18154 g21062 +00 1 +.names g21062 II29635 +0 1 +.names II29635 g22838 +0 1 +.names g19913 g15710 g21063 +00 1 +.names g21063 II29638 +0 1 +.names II29638 g22839 +0 1 +.names g19219 g15959 g20825 +0- 1 +-0 1 +.names g20825 II29641 +0 1 +.names II29641 g22840 +0 1 +.names g19285 g19316 g21889 +00 1 +.names g21889 g22843 +0 1 +.names g16591 g19987 g21643 +00 1 +.names g21643 g22847 +0 1 +.names g14378 g15263 g19902 g19875 g21746 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g21746 II29653 +0 1 +.names II29653 g22852 +0 1 +.names g19920 g18204 g21070 +00 1 +.names g21070 II29656 +0 1 +.names II29656 g22864 +0 1 +.names g19925 g18222 g21071 +00 1 +.names g21071 II29660 +0 1 +.names II29660 g22866 +0 1 +.names g19926 g18223 g21072 +00 1 +.names g21072 II29663 +0 1 +.names II29663 g22867 +0 1 +.names g21222 g22868 +0 1 +.names g19928 g18244 g21073 +00 1 +.names g21073 II29669 +0 1 +.names II29669 g22871 +0 1 +.names g19929 g18245 g21074 +00 1 +.names g21074 II29672 +0 1 +.names II29672 g22872 +0 1 +.names g19930 g18246 g21075 +00 1 +.names g21075 II29675 +0 1 +.names II29675 g22873 +0 1 +.names g19260 g19284 g21884 +00 1 +.names g21884 g22875 +0 1 +.names g16611 g20025 g21674 +00 1 +.names g21674 g22882 +0 1 +.names g14490 g15355 g19927 g19906 g21770 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g21770 II29687 +0 1 +.names II29687 g22887 +0 1 +.names g19935 g18311 g21080 +00 1 +.names g21080 II29690 +0 1 +.names II29690 g22899 +0 1 +.names g19940 g18329 g21081 +00 1 +.names g21081 II29694 +0 1 +.names II29694 g22901 +0 1 +.names g19941 g18330 g21082 +00 1 +.names g21082 II29697 +0 1 +.names II29697 g22902 +0 1 +.names g20153 g2903 g20700 +0- 1 +-0 1 +.names g20700 II29700 +0 1 +.names II29700 g22903 +0 1 +.names g19830 g15780 g21711 +00 1 +.names g21711 g22907 +0 1 +.names g16629 g20067 g21703 +00 1 +.names g21703 g22917 +0 1 +.names g14577 g15441 g19942 g19931 g21786 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g21786 II29712 +0 1 +.names II29712 g22922 +0 1 +.names g19952 g18404 g21094 +00 1 +.names g21094 II29715 +0 1 +.names II29715 g22934 +0 1 +.names g21851 II29724 +0 1 +.names II29724 g22945 +0 1 +.names g3919 g19830 g20877 +00 1 +.names g20877 II29727 +0 1 +.names II29727 g22948 +0 1 +.names g20507 g18352 g21665 +00 1 +.names g21665 g22949 +0 1 +.names g20507 g18430 g21739 +00 1 +.names g21739 g22954 +0 1 +.names g20526 g18447 g21694 +00 1 +.names g21694 g22958 +0 1 +.names g20526 g18503 g21763 +00 1 +.names g21763 g22962 +0 1 +.names g20545 g18520 g21730 +00 1 +.names g21730 g22966 +0 1 +.names g5394 g19830 g20884 +00 1 +.names g20884 II29736 +0 1 +.names II29736 g22970 +0 1 +.names g20545 g18567 g21779 +00 1 +.names g21779 g22971 +0 1 +.names g19070 g18584 g21756 +00 1 +.names g21756 g22975 +0 1 +.names g20480 g13247 g21346 +00 1 +.names g21346 II29741 +0 1 +.names II29741 g22979 +0 1 +.names g19070 g18617 g21794 +00 1 +.names g21794 g22980 +0 1 +.names g21382 g22986 +0 1 +.names g21404 g22988 +0 1 +.names g21415 g22989 +0 1 +.names g21429 g22991 +0 1 +.names g21441 g22995 +0 1 +.names g21449 g22996 +0 1 +.names g21458 g22998 +0 1 +.names g21473 g23001 +0 1 +.names g21477 g23002 +0 1 +.names g21483 g23006 +0 1 +.names g21491 g23007 +0 1 +.names g21498 g23008 +0 1 +.names g21505 g23012 +0 1 +.names g21514 g23015 +0 1 +.names g21518 g23016 +0 1 +.names g21524 g23020 +0 1 +.names g21530 g23021 +0 1 +.names g21537 g23024 +0 1 +.names g21541 g23028 +0 1 +.names g21550 g23031 +0 1 +.names g21554 g23032 +0 1 +.names g21558 g23036 +0 1 +.names g21561 g23037 +0 1 +.names g21566 g23038 +0 1 +.names g21573 g23041 +0 1 +.names g21577 g23045 +0 1 +.names g21586 g23048 +0 1 +.names g21590 g23049 +0 1 +.names g21432 II29797 +0 1 +.names II29797 g23050 +0 1 +.names g21435 II29802 +0 1 +.names II29802 g23055 +0 1 +.names g21594 g23056 +0 1 +.names g21599 g23057 +0 1 +.names g21606 g23060 +0 1 +.names g21612 g23064 +0 1 +.names g21467 II29812 +0 1 +.names II29812 g23065 +0 1 +.names g21470 II29817 +0 1 +.names II29817 g23068 +0 1 +.names g21619 g23069 +0 1 +.names g21623 g23074 +0 1 +.names g21628 g23075 +0 1 +.names g21502 II29827 +0 1 +.names II29827 g23078 +0 1 +.names g21640 g23079 +0 1 +.names g21647 g23082 +0 1 +.names g21651 g23087 +0 1 +.names g21655 g23088 +0 1 +.names g21316 II29841 +0 1 +.names II29841 g23094 +0 1 +.names g21671 g23095 +0 1 +.names g21678 g23098 +0 1 +.names g21682 g23103 +0 1 +.names g21331 II29852 +0 1 +.names II29852 g23105 +0 1 +.names g21700 g23112 +0 1 +.names g21708 g23115 +0 1 +.names g21346 II29863 +0 1 +.names II29863 g23116 +0 1 +.names g21364 II29872 +0 1 +.names II29872 g23125 +0 1 +.names g21385 II29881 +0 1 +.names II29881 g23134 +0 1 +.names g21825 g23140 +0 1 +.names g21825 g23141 +0 1 +.names g21825 g23142 +0 1 +.names g21825 g23143 +0 1 +.names g21825 g23144 +0 1 +.names g21825 g23145 +0 1 +.names g21825 g23146 +0 1 +.names g21825 g23147 +0 1 +.names g23116 II29897 +0 1 +.names g23125 II29900 +0 1 +.names g23134 II29903 +0 1 +.names g21967 II29906 +0 1 +.names g23050 II29909 +0 1 +.names g23065 II29912 +0 1 +.names g23055 II29915 +0 1 +.names g23068 II29918 +0 1 +.names g23078 II29921 +0 1 +.names g23094 II29924 +0 1 +.names g23105 II29927 +0 1 +.names g22176 II29930 +0 1 +.names g22082 II29933 +0 1 +.names g22582 II29936 +0 1 +.names g22518 II29939 +0 1 +.names g22548 II29942 +0 1 +.names g22583 II29945 +0 1 +.names g22549 II29948 +0 1 +.names g22584 II29951 +0 1 +.names g22611 II29954 +0 1 +.names g22585 II29957 +0 1 +.names g22612 II29960 +0 1 +.names g22639 II29963 +0 1 +.names g22613 II29966 +0 1 +.names g22640 II29969 +0 1 +.names g22669 II29972 +0 1 +.names g22641 II29975 +0 1 +.names g22670 II29978 +0 1 +.names g22702 II29981 +0 1 +.names g22671 II29984 +0 1 +.names g22703 II29987 +0 1 +.names g22728 II29990 +0 1 +.names g22704 II29993 +0 1 +.names g22729 II29996 +0 1 +.names g22756 II29999 +0 1 +.names g22730 II30002 +0 1 +.names g22757 II30005 +0 1 +.names g22785 II30008 +0 1 +.names g22758 II30011 +0 1 +.names g22786 II30014 +0 1 +.names g22824 II30017 +0 1 +.names g22519 II30020 +0 1 +.names g22550 II30023 +0 1 +.names g22586 II30026 +0 1 +.names g22642 II30029 +0 1 +.names g22672 II30032 +0 1 +.names g22705 II30035 +0 1 +.names g22673 II30038 +0 1 +.names g22706 II30041 +0 1 +.names g22731 II30044 +0 1 +.names g22107 II30047 +0 1 +.names g22619 II30050 +0 1 +.names g22558 II30053 +0 1 +.names g22589 II30056 +0 1 +.names g22620 II30059 +0 1 +.names g22590 II30062 +0 1 +.names g22621 II30065 +0 1 +.names g22647 II30068 +0 1 +.names g22622 II30071 +0 1 +.names g22648 II30074 +0 1 +.names g22675 II30077 +0 1 +.names g22649 II30080 +0 1 +.names g22676 II30083 +0 1 +.names g22709 II30086 +0 1 +.names g22677 II30089 +0 1 +.names g22710 II30092 +0 1 +.names g22733 II30095 +0 1 +.names g22711 II30098 +0 1 +.names g22734 II30101 +0 1 +.names g22760 II30104 +0 1 +.names g22735 II30107 +0 1 +.names g22761 II30110 +0 1 +.names g22790 II30113 +0 1 +.names g22762 II30116 +0 1 +.names g22791 II30119 +0 1 +.names g22827 II30122 +0 1 +.names g22792 II30125 +0 1 +.names g22828 II30128 +0 1 +.names g22864 II30131 +0 1 +.names g22559 II30134 +0 1 +.names g22591 II30137 +0 1 +.names g22623 II30140 +0 1 +.names g22678 II30143 +0 1 +.names g22712 II30146 +0 1 +.names g22736 II30149 +0 1 +.names g22713 II30152 +0 1 +.names g22737 II30155 +0 1 +.names g22763 II30158 +0 1 +.names g22133 II30161 +0 1 +.names g22655 II30164 +0 1 +.names g22598 II30167 +0 1 +.names g22626 II30170 +0 1 +.names g22656 II30173 +0 1 +.names g22627 II30176 +0 1 +.names g22657 II30179 +0 1 +.names g22683 II30182 +0 1 +.names g22658 II30185 +0 1 +.names g22684 II30188 +0 1 +.names g22715 II30191 +0 1 +.names g22685 II30194 +0 1 +.names g22716 II30197 +0 1 +.names g22740 II30200 +0 1 +.names g22717 II30203 +0 1 +.names g22741 II30206 +0 1 +.names g22765 II30209 +0 1 +.names g22742 II30212 +0 1 +.names g22766 II30215 +0 1 +.names g22794 II30218 +0 1 +.names g22767 II30221 +0 1 +.names g22795 II30224 +0 1 +.names g22832 II30227 +0 1 +.names g22796 II30230 +0 1 +.names g22833 II30233 +0 1 +.names g22866 II30236 +0 1 +.names g22834 II30239 +0 1 +.names g22867 II30242 +0 1 +.names g22899 II30245 +0 1 +.names g22599 II30248 +0 1 +.names g22628 II30251 +0 1 +.names g22659 II30254 +0 1 +.names g22718 II30257 +0 1 +.names g22743 II30260 +0 1 +.names g22768 II30263 +0 1 +.names g22744 II30266 +0 1 +.names g22769 II30269 +0 1 +.names g22797 II30272 +0 1 +.names g22156 II30275 +0 1 +.names g22691 II30278 +0 1 +.names g22635 II30281 +0 1 +.names g22662 II30284 +0 1 +.names g22692 II30287 +0 1 +.names g22663 II30290 +0 1 +.names g22693 II30293 +0 1 +.names g22723 II30296 +0 1 +.names g22694 II30299 +0 1 +.names g22724 II30302 +0 1 +.names g22746 II30305 +0 1 +.names g22725 II30308 +0 1 +.names g22747 II30311 +0 1 +.names g22772 II30314 +0 1 +.names g22748 II30317 +0 1 +.names g22773 II30320 +0 1 +.names g22799 II30323 +0 1 +.names g22774 II30326 +0 1 +.names g22800 II30329 +0 1 +.names g22836 II30332 +0 1 +.names g22801 II30335 +0 1 +.names g22837 II30338 +0 1 +.names g22871 II30341 +0 1 +.names g22838 II30344 +0 1 +.names g22872 II30347 +0 1 +.names g22901 II30350 +0 1 +.names g22873 II30353 +0 1 +.names g22902 II30356 +0 1 +.names g22934 II30359 +0 1 +.names g22636 II30362 +0 1 +.names g22664 II30365 +0 1 +.names g22695 II30368 +0 1 +.names g22749 II30371 +0 1 +.names g22775 II30374 +0 1 +.names g22802 II30377 +0 1 +.names g22776 II30380 +0 1 +.names g22803 II30383 +0 1 +.names g22839 II30386 +0 1 +.names g22225 II30389 +0 1 +.names g22226 II30392 +0 1 +.names g22253 II30395 +0 1 +.names g22840 II30398 +0 1 +.names g22444 II30401 +0 1 +.names g22948 II30404 +0 1 +.names g22970 II30407 +0 1 +.names g21800 g21788 g21844 g23052 +1-- 1 +-1- 1 +--1 1 +.names g23052 g23403 +0 1 +.names g21808 g21802 g21846 g23071 +1-- 1 +-1- 1 +--1 1 +.names g23071 g23410 +0 1 +.names g21815 g21810 g21849 g23084 +1-- 1 +-1- 1 +--1 1 +.names g23084 g23415 +0 1 +.names g21806 g21799 g23089 +1- 1 +-1 1 +.names g23089 g23420 +0 1 +.names g21821 g21817 g21856 g23100 +1-- 1 +-1- 1 +--1 1 +.names g23100 g23424 +0 1 +.names g21813 g21807 g23107 +1- 1 +-1 1 +.names g23107 g23429 +0 1 +.names g21819 g21814 g23120 +1- 1 +-1 1 +.names g23120 g23435 +0 1 +.names g16909 g21067 g23000 +00 1 +.names g23000 II30467 +0 1 +.names II30467 g23438 +0 1 +.names g17117 g21188 g23117 +00 1 +.names g23117 II30470 +0 1 +.names II30470 g23439 +0 1 +.names g21823 g21820 g23129 +1- 1 +-1 1 +.names g23129 g23441 +0 1 +.names g22945 g23444 +0 1 +.names g21238 g83 g22876 +0- 1 +-0 1 +.names g22876 II30476 +0 1 +.names II30476 g23448 +0 1 +.names g16939 g21077 g23014 +00 1 +.names g23014 II30480 +0 1 +.names II30480 g23452 +0 1 +.names g17144 g21203 g23126 +00 1 +.names g23126 II30483 +0 1 +.names II30483 g23453 +0 1 +.names g16968 g21086 g23022 +00 1 +.names g23022 II30486 +0 1 +.names II30486 g23454 +0 1 +.names g21246 g771 g22911 +0- 1 +-0 1 +.names g22911 II30489 +0 1 +.names II30489 g23455 +0 1 +.names g16970 g21091 g23030 +00 1 +.names g23030 II30493 +0 1 +.names II30493 g23459 +0 1 +.names g17167 g21218 g23137 +00 1 +.names g23137 II30496 +0 1 +.names II30496 g23460 +0 1 +.names g16989 g21098 g23039 +00 1 +.names g23039 II30501 +0 1 +.names II30501 g23463 +0 1 +.names g21255 g1457 g22936 +0- 1 +-0 1 +.names g22936 II30504 +0 1 +.names II30504 g23464 +0 1 +.names g16991 g21103 g23047 +00 1 +.names g23047 II30508 +0 1 +.names II30508 g23468 +0 1 +.names g17182 g21226 g21970 +00 1 +.names g21970 II30511 +0 1 +.names II30511 g23469 +0 1 +.names II28727 II28728 g22188 +0- 1 +-0 1 +.names g22188 g23470 +0 1 +.names g16999 g21112 g23058 +00 1 +.names g23058 II30516 +0 1 +.names II30516 g23472 +0 1 +.names g21263 g2151 g22942 +0- 1 +-0 1 +.names g22942 II30519 +0 1 +.names II30519 g23473 +0 1 +.names g17015 g21122 g23067 +00 1 +.names g23067 II30525 +0 1 +.names II30525 g23481 +0 1 +.names II28742 II28743 g22197 +0- 1 +-0 1 +.names g22197 g23482 +0 1 +.names g17023 g21129 g23076 +00 1 +.names g23076 II30531 +0 1 +.names II30531 g23485 +0 1 +.names g17045 g21141 g23081 +00 1 +.names g23081 II30536 +0 1 +.names II30536 g23492 +0 1 +.names II28754 II28755 g22203 +0- 1 +-0 1 +.names g22203 g23493 +0 1 +.names g17055 g21154 g23092 +00 1 +.names g23092 II30544 +0 1 +.names II30544 g23500 +0 1 +.names g17056 g21155 g23093 +00 1 +.names g23093 II30547 +0 1 +.names II30547 g23501 +0 1 +.names g17079 g21161 g23097 +00 1 +.names g23097 II30552 +0 1 +.names II30552 g23508 +0 1 +.names II28766 II28767 g22209 +0- 1 +-0 1 +.names g22209 g23509 +0 1 +.names g17090 g21174 g23110 +00 1 +.names g23110 II30560 +0 1 +.names II30560 g23516 +0 1 +.names g17091 g21175 g23111 +00 1 +.names g23111 II30563 +0 1 +.names II30563 g23517 +0 1 +.names g17114 g21181 g23114 +00 1 +.names g23114 II30568 +0 1 +.names II30568 g23524 +0 1 +.names g17128 g21194 g23123 +00 1 +.names g23123 II30575 +0 1 +.names II30575 g23531 +0 1 +.names g17129 g21195 g23124 +00 1 +.names g23124 II30578 +0 1 +.names II30578 g23532 +0 1 +.names g17155 g21209 g23132 +00 1 +.names g23132 II30586 +0 1 +.names II30586 g23542 +0 1 +.names g17156 g21210 g23133 +00 1 +.names g23133 II30589 +0 1 +.names II30589 g23543 +0 1 +.names g21284 g19549 g22025 +00 1 +.names g22025 II30594 +0 1 +.names II30594 g23546 +0 1 +.names g21290 g19553 g22027 +00 1 +.names g22027 II30598 +0 1 +.names II30598 g23548 +0 1 +.names g21291 g19554 g22028 +00 1 +.names g22028 II30601 +0 1 +.names II30601 g23549 +0 1 +.names g21292 g19555 g22029 +00 1 +.names g22029 II30607 +0 1 +.names II30607 g23553 +0 1 +.names g21298 g19557 g22030 +00 1 +.names g22030 II30611 +0 1 +.names II30611 g23555 +0 1 +.names g21299 g19558 g22031 +00 1 +.names g22031 II30614 +0 1 +.names II30614 g23556 +0 1 +.names g21300 g19559 g22032 +00 1 +.names g22032 II30617 +0 1 +.names II30617 g23557 +0 1 +.names g21301 g19560 g22033 +00 1 +.names g22033 II30623 +0 1 +.names II30623 g23561 +0 1 +.names g21302 g19561 g22034 +00 1 +.names g22034 II30626 +0 1 +.names II30626 g23562 +0 1 +.names g21303 g19562 g22035 +00 1 +.names g22035 II30632 +0 1 +.names II30632 g23566 +0 1 +.names g21304 g19564 g22037 +00 1 +.names g22037 II30636 +0 1 +.names II30636 g23568 +0 1 +.names g21305 g19565 g22038 +00 1 +.names g22038 II30639 +0 1 +.names II30639 g23569 +0 1 +.names g21306 g19566 g22039 +00 1 +.names g22039 II30642 +0 1 +.names II30642 g23570 +0 1 +.names g21307 g19567 g22040 +00 1 +.names g22040 II30648 +0 1 +.names II30648 g23574 +0 1 +.names g21308 g19568 g22041 +00 1 +.names g22041 II30651 +0 1 +.names II30651 g23575 +0 1 +.names g21309 g19569 g22042 +00 1 +.names g22042 II30654 +0 1 +.names II30654 g23576 +0 1 +.names g21310 g19570 g22043 +00 1 +.names g22043 II30660 +0 1 +.names II30660 g23580 +0 1 +.names g21311 g19571 g22044 +00 1 +.names g22044 II30663 +0 1 +.names II30663 g23581 +0 1 +.names g21312 g19572 g22045 +00 1 +.names g22045 II30669 +0 1 +.names II30669 g23585 +0 1 +.names g21313 g19574 g22047 +00 1 +.names g22047 II30673 +0 1 +.names II30673 g23587 +0 1 +.names g21314 g19575 g22048 +00 1 +.names g22048 II30676 +0 1 +.names II30676 g23588 +0 1 +.names g21315 g19576 g22049 +00 1 +.names g22049 II30679 +0 1 +.names II30679 g23589 +0 1 +.names g20878 g10024 g23136 +00 1 +.names g23136 II30686 +0 1 +.names II30686 g23594 +0 1 +.names g21319 g19586 g22054 +00 1 +.names g22054 II30689 +0 1 +.names II30689 g23595 +0 1 +.names g21320 g19587 g22055 +00 1 +.names g22055 II30692 +0 1 +.names II30692 g23596 +0 1 +.names g21321 g19588 g22056 +00 1 +.names g22056 II30695 +0 1 +.names II30695 g23597 +0 1 +.names g21322 g19589 g22057 +00 1 +.names g22057 II30701 +0 1 +.names II30701 g23601 +0 1 +.names g21323 g19590 g22058 +00 1 +.names g22058 II30704 +0 1 +.names II30704 g23602 +0 1 +.names g21324 g19591 g22059 +00 1 +.names g22059 II30707 +0 1 +.names II30707 g23603 +0 1 +.names g21325 g19592 g22060 +00 1 +.names g22060 II30713 +0 1 +.names II30713 g23607 +0 1 +.names g21326 g19593 g22061 +00 1 +.names g22061 II30716 +0 1 +.names II30716 g23608 +0 1 +.names g21328 g19597 g22063 +00 1 +.names g22063 II30722 +0 1 +.names II30722 g23612 +0 1 +.names g21329 g19598 g22064 +00 1 +.names g22064 II30725 +0 1 +.names II30725 g23613 +0 1 +.names g21330 g19599 g22065 +00 1 +.names g22065 II30728 +0 1 +.names II30728 g23614 +0 1 +.names g21334 g19604 g22066 +00 1 +.names g22066 II30735 +0 1 +.names II30735 g23619 +0 1 +.names g21335 g19605 g22067 +00 1 +.names g22067 II30738 +0 1 +.names II30738 g23620 +0 1 +.names g21336 g19606 g22068 +00 1 +.names g22068 II30741 +0 1 +.names II30741 g23621 +0 1 +.names g20895 g10133 g21969 +00 1 +.names g21969 II30748 +0 1 +.names II30748 g23626 +0 1 +.names g21337 g19616 g22073 +00 1 +.names g22073 II30751 +0 1 +.names II30751 g23627 +0 1 +.names g21338 g19617 g22074 +00 1 +.names g22074 II30754 +0 1 +.names II30754 g23628 +0 1 +.names g21339 g19618 g22075 +00 1 +.names g22075 II30757 +0 1 +.names II30757 g23629 +0 1 +.names g21340 g19619 g22076 +00 1 +.names g22076 II30763 +0 1 +.names II30763 g23633 +0 1 +.names g21341 g19620 g22077 +00 1 +.names g22077 II30766 +0 1 +.names II30766 g23634 +0 1 +.names g21342 g19621 g22078 +00 1 +.names g22078 II30769 +0 1 +.names II30769 g23635 +0 1 +.names g21343 g19623 g22079 +00 1 +.names g22079 II30776 +0 1 +.names II30776 g23640 +0 1 +.names g21344 g19624 g22080 +00 1 +.names g22080 II30779 +0 1 +.names II30779 g23641 +0 1 +.names g21345 g19625 g22081 +00 1 +.names g22081 II30782 +0 1 +.names II30782 g23642 +0 1 +.names g17012 g21891 g22454 +00 1 +.names g22454 II30786 +0 1 +.names II30786 g23644 +0 1 +.names g21349 g19630 g22087 +00 1 +.names g22087 II30797 +0 1 +.names II30797 g23661 +0 1 +.names g21350 g19631 g22088 +00 1 +.names g22088 II30800 +0 1 +.names II30800 g23662 +0 1 +.names g21351 g19632 g22089 +00 1 +.names g22089 II30803 +0 1 +.names II30803 g23663 +0 1 +.names g21352 g19637 g22090 +00 1 +.names g22090 II30810 +0 1 +.names II30810 g23668 +0 1 +.names g21353 g19638 g22091 +00 1 +.names g22091 II30813 +0 1 +.names II30813 g23669 +0 1 +.names g21354 g19639 g22092 +00 1 +.names g22092 II30816 +0 1 +.names II30816 g23670 +0 1 +.names g20914 g10238 g21972 +00 1 +.names g21972 II30823 +0 1 +.names II30823 g23675 +0 1 +.names g21355 g19649 g22097 +00 1 +.names g22097 II30826 +0 1 +.names II30826 g23676 +0 1 +.names g21356 g19650 g22098 +00 1 +.names g22098 II30829 +0 1 +.names II30829 g23677 +0 1 +.names g21357 g19651 g22099 +00 1 +.names g22099 II30832 +0 1 +.names II30832 g23678 +0 1 +.names g21360 g19653 g22100 +00 1 +.names g22100 II30838 +0 1 +.names II30838 g23682 +0 1 +.names g21361 g19654 g22101 +00 1 +.names g22101 II30841 +0 1 +.names II30841 g23683 +0 1 +.names g21362 g19655 g22102 +00 1 +.names g22102 II30844 +0 1 +.names II30844 g23684 +0 1 +.names g21363 g19656 g22103 +00 1 +.names g22103 II30847 +0 1 +.names II30847 g23685 +0 1 +.names g21367 g19663 g22104 +00 1 +.names g22104 II30854 +0 1 +.names II30854 g23690 +0 1 +.names g21368 g19664 g22105 +00 1 +.names g22105 II30857 +0 1 +.names II30857 g23691 +0 1 +.names g21369 g19665 g22106 +00 1 +.names g22106 II30860 +0 1 +.names II30860 g23692 +0 1 +.names g17042 g21899 g22493 +00 1 +.names g22493 II30864 +0 1 +.names II30864 g23694 +0 1 +.names g21370 g19670 g22112 +00 1 +.names g22112 II30875 +0 1 +.names II30875 g23711 +0 1 +.names g21371 g19671 g22113 +00 1 +.names g22113 II30878 +0 1 +.names II30878 g23712 +0 1 +.names g21372 g19672 g22114 +00 1 +.names g22114 II30881 +0 1 +.names II30881 g23713 +0 1 +.names g21373 g19677 g22115 +00 1 +.names g22115 II30888 +0 1 +.names II30888 g23718 +0 1 +.names g21374 g19678 g22116 +00 1 +.names g22116 II30891 +0 1 +.names II30891 g23719 +0 1 +.names g21375 g19679 g22117 +00 1 +.names g22117 II30894 +0 1 +.names II30894 g23720 +0 1 +.names g20938 g10340 g21974 +00 1 +.names g21974 II30901 +0 1 +.names II30901 g23725 +0 1 +.names g21378 g19692 g22122 +00 1 +.names g22122 II30905 +0 1 +.names II30905 g23727 +0 1 +.names g21379 g19693 g22123 +00 1 +.names g22123 II30908 +0 1 +.names II30908 g23728 +0 1 +.names g21380 g19694 g22124 +00 1 +.names g22124 II30911 +0 1 +.names II30911 g23729 +0 1 +.names g21381 g19695 g22125 +00 1 +.names g22125 II30914 +0 1 +.names II30914 g23730 +0 1 +.names g22806 II30917 +0 1 +.names II30917 g23731 +0 1 +.names g21389 g19701 g22126 +00 1 +.names g22126 II30922 +0 1 +.names II30922 g23736 +0 1 +.names g21390 g19702 g22127 +00 1 +.names g22127 II30925 +0 1 +.names II30925 g23737 +0 1 +.names g21391 g19703 g22128 +00 1 +.names g22128 II30928 +0 1 +.names II30928 g23738 +0 1 +.names g21392 g19704 g22129 +00 1 +.names g22129 II30931 +0 1 +.names II30931 g23739 +0 1 +.names g21393 g19711 g22130 +00 1 +.names g22130 II30938 +0 1 +.names II30938 g23744 +0 1 +.names g21394 g19712 g22131 +00 1 +.names g22131 II30941 +0 1 +.names II30941 g23745 +0 1 +.names g21395 g19713 g22132 +00 1 +.names g22132 II30944 +0 1 +.names II30944 g23746 +0 1 +.names g17076 g21911 g22536 +00 1 +.names g22536 II30948 +0 1 +.names II30948 g23748 +0 1 +.names g21396 g19718 g22138 +00 1 +.names g22138 II30959 +0 1 +.names II30959 g23765 +0 1 +.names g21397 g19719 g22139 +00 1 +.names g22139 II30962 +0 1 +.names II30962 g23766 +0 1 +.names g21398 g19720 g22140 +00 1 +.names g22140 II30965 +0 1 +.names II30965 g23767 +0 1 +.names g21401 g19727 g22141 +00 1 +.names g22141 II30973 +0 1 +.names II30973 g23773 +0 1 +.names g21402 g19728 g22142 +00 1 +.names g22142 II30976 +0 1 +.names II30976 g23774 +0 1 +.names g21403 g19729 g22143 +00 1 +.names g22143 II30979 +0 1 +.names II30979 g23775 +0 1 +.names g21636 g672 g22992 +0- 1 +-0 1 +.names g22992 II30985 +0 1 +.names II30985 g23779 +0 1 +.names g21411 g19736 g22145 +00 1 +.names g22145 II30988 +0 1 +.names II30988 g23782 +0 1 +.names g21412 g19737 g22146 +00 1 +.names g22146 II30991 +0 1 +.names II30991 g23783 +0 1 +.names g21413 g19738 g22147 +00 1 +.names g22147 II30994 +0 1 +.names II30994 g23784 +0 1 +.names g21414 g19739 g22148 +00 1 +.names g22148 II30997 +0 1 +.names II30997 g23785 +0 1 +.names g22847 II31000 +0 1 +.names II31000 g23786 +0 1 +.names g21419 g19745 g22149 +00 1 +.names g22149 II31005 +0 1 +.names II31005 g23791 +0 1 +.names g21420 g19746 g22150 +00 1 +.names g22150 II31008 +0 1 +.names II31008 g23792 +0 1 +.names g21421 g19747 g22151 +00 1 +.names g22151 II31011 +0 1 +.names II31011 g23793 +0 1 +.names g21422 g19748 g22152 +00 1 +.names g22152 II31014 +0 1 +.names II31014 g23794 +0 1 +.names g21423 g19755 g22153 +00 1 +.names g22153 II31021 +0 1 +.names II31021 g23799 +0 1 +.names g21424 g19756 g22154 +00 1 +.names g22154 II31024 +0 1 +.names II31024 g23800 +0 1 +.names g21425 g19757 g22155 +00 1 +.names g22155 II31027 +0 1 +.names II31027 g23801 +0 1 +.names g17111 g21925 g22576 +00 1 +.names g22576 II31031 +0 1 +.names II31031 g23803 +0 1 +.names g21428 g19764 g22161 +00 1 +.names g22161 II31043 +0 1 +.names II31043 g23821 +0 1 +.names g21438 g19770 g22162 +00 1 +.names g22162 II31050 +0 1 +.names II31050 g23826 +0 1 +.names g21439 g19771 g22163 +00 1 +.names g22163 II31053 +0 1 +.names II31053 g23827 +0 1 +.names g21440 g19772 g22164 +00 1 +.names g22164 II31056 +0 1 +.names II31056 g23828 +0 1 +.names g21667 g1358 g23003 +0- 1 +-0 1 +.names g23003 II31062 +0 1 +.names II31062 g23832 +0 1 +.names g21445 g19779 g22166 +00 1 +.names g22166 II31065 +0 1 +.names II31065 g23835 +0 1 +.names g21446 g19780 g22167 +00 1 +.names g22167 II31068 +0 1 +.names II31068 g23836 +0 1 +.names g21447 g19781 g22168 +00 1 +.names g22168 II31071 +0 1 +.names II31071 g23837 +0 1 +.names g21448 g19782 g22169 +00 1 +.names g22169 II31074 +0 1 +.names II31074 g23838 +0 1 +.names g22882 II31077 +0 1 +.names II31077 g23839 +0 1 +.names g21453 g19788 g22170 +00 1 +.names g22170 II31082 +0 1 +.names II31082 g23844 +0 1 +.names g21454 g19789 g22171 +00 1 +.names g22171 II31085 +0 1 +.names II31085 g23845 +0 1 +.names g21455 g19790 g22172 +00 1 +.names g22172 II31088 +0 1 +.names II31088 g23846 +0 1 +.names g21456 g19791 g22173 +00 1 +.names g22173 II31091 +0 1 +.names II31091 g23847 +0 1 +.names g22300 g23853 +0 1 +.names g21476 g19806 g22177 +00 1 +.names g22177 II31102 +0 1 +.names II31102 g23856 +0 1 +.names g21480 g19812 g22178 +00 1 +.names g22178 II31109 +0 1 +.names II31109 g23861 +0 1 +.names g21481 g19813 g22179 +00 1 +.names g22179 II31112 +0 1 +.names II31112 g23862 +0 1 +.names g21482 g19814 g22180 +00 1 +.names g22180 II31115 +0 1 +.names II31115 g23863 +0 1 +.names g21696 g2052 g23017 +0- 1 +-0 1 +.names g23017 II31121 +0 1 +.names II31121 g23867 +0 1 +.names g21487 g19821 g22182 +00 1 +.names g22182 II31124 +0 1 +.names II31124 g23870 +0 1 +.names g21488 g19822 g22183 +00 1 +.names g22183 II31127 +0 1 +.names II31127 g23871 +0 1 +.names g21489 g19823 g22184 +00 1 +.names g22184 II31130 +0 1 +.names II31130 g23872 +0 1 +.names g21490 g19824 g22185 +00 1 +.names g22185 II31133 +0 1 +.names II31133 g23873 +0 1 +.names g22917 II31136 +0 1 +.names II31136 g23874 +0 1 +.names g22777 II31141 +0 1 +.names II31141 g23879 +0 1 +.names g21903 g7466 g22935 +00 1 +.names g22935 II31144 +0 1 +.names II31144 g23882 +0 1 +.names g21135 g21118 g21106 II28609 g22062 +1111 1 +.names g22062 g23885 +0 1 +.names g22328 g23887 +0 1 +.names g21517 g19850 g22191 +00 1 +.names g22191 II31152 +0 1 +.names II31152 g23890 +0 1 +.names g21521 g19856 g22192 +00 1 +.names g22192 II31159 +0 1 +.names II31159 g23895 +0 1 +.names g21522 g19857 g22193 +00 1 +.names g22193 II31162 +0 1 +.names II31162 g23896 +0 1 +.names g21523 g19858 g22194 +00 1 +.names g22194 II31165 +0 1 +.names II31165 g23897 +0 1 +.names g21732 g2746 g23033 +0- 1 +-0 1 +.names g23033 II31171 +0 1 +.names II31171 g23901 +0 1 +.names g21117 g21105 g21096 II28594 g22046 +1111 1 +.names g22046 g23905 +0 1 +.names g22353 g23908 +0 1 +.names g21553 g19883 g22200 +00 1 +.names g22200 II31181 +0 1 +.names II31181 g23911 +0 1 +.names g21048 g18623 g21989 +0- 1 +-0 1 +.names g21989 II31188 +0 1 +.names II31188 g23916 +0 1 +.names g21104 g21095 g21084 II28582 g22036 +1111 1 +.names g22036 g23918 +0 1 +.names g21892 g18982 g22578 +00 1 +.names g22578 II31195 +0 1 +.names II31195 g23923 +0 1 +.names g22376 g23940 +0 1 +.names g21065 g21711 g22002 +0- 1 +-0 1 +.names g22002 II31205 +0 1 +.names II31205 g23943 +0 1 +.names g21900 g18990 g22615 +00 1 +.names g22615 II31213 +0 1 +.names II31213 g23955 +0 1 +.names g21912 g18997 g22651 +00 1 +.names g22651 II31226 +0 1 +.names II31226 g23984 +0 1 +.names g21083 g18407 g22026 +00 1 +.names g22026 II31232 +0 1 +.names II31232 g24000 +0 1 +.names g21639 g19949 g22218 +00 1 +.names g22218 II31235 +0 1 +.names II31235 g24001 +0 1 +.names g21926 g19010 g22687 +00 1 +.names g22687 II31244 +0 1 +.names II31244 g24014 +0 1 +.names g20700 g7595 g22953 +00 1 +.names g22953 II31250 +0 1 +.names II31250 g24030 +0 1 +.names g21666 g19971 g22231 +00 1 +.names g22231 II31253 +0 1 +.names II31253 g24033 +0 1 +.names g21670 g19976 g22234 +00 1 +.names g22234 II31257 +0 1 +.names II31257 g24035 +0 1 +.names g14256 g14175 g21123 g23023 +000 1 +.names g23023 g24047 +0 1 +.names g21687 g19983 g22242 +00 1 +.names g22242 II31266 +0 1 +.names II31266 g24051 +0 1 +.names g21695 g20001 g22247 +00 1 +.names g22247 II31270 +0 1 +.names II31270 g24053 +0 1 +.names g21699 g20006 g22249 +00 1 +.names g22249 II31274 +0 1 +.names II31274 g24055 +0 1 +.names g14378 g14290 g21142 g23040 +000 1 +.names g23040 g24060 +0 1 +.names g21723 g20021 g22263 +00 1 +.names g22263 II31282 +0 1 +.names II31282 g24064 +0 1 +.names g21731 g20039 g22267 +00 1 +.names g22267 II31286 +0 1 +.names II31286 g24066 +0 1 +.names g21735 g20044 g22269 +00 1 +.names g22269 II31290 +0 1 +.names II31290 g24068 +0 1 +.names g14490 g14412 g21162 g23059 +000 1 +.names g23059 g24073 +0 1 +.names g21749 g20063 g22280 +00 1 +.names g22280 II31298 +0 1 +.names II31298 g24077 +0 1 +.names g21757 g20081 g22284 +00 1 +.names g22284 II31302 +0 1 +.names II31302 g24079 +0 1 +.names g14577 g14524 g21182 g23077 +000 1 +.names g23077 g24084 +0 1 +.names g21773 g20104 g22299 +00 1 +.names g22299 II31310 +0 1 +.names II31310 g24088 +0 1 +.names g14442 g21149 g10694 g22339 +0-- 1 +-0- 1 +--0 1 +.names g22339 g24094 +0 1 +.names g14529 g21169 g10714 g22362 +0-- 1 +-0- 1 +--0 1 +.names g22362 g24095 +0 1 +.names g22405 g24096 +0 1 +.names g14584 g21189 g10735 g22382 +0-- 1 +-0- 1 +--0 1 +.names g22382 g24097 +0 1 +.names g22409 g24098 +0 1 +.names g22412 g24099 +0 1 +.names g22415 g24101 +0 1 +.names g22418 g24102 +0 1 +.names g14618 g21204 g10754 g22397 +0-- 1 +-0- 1 +--0 1 +.names g22397 g24103 +0 1 +.names g22422 g24104 +0 1 +.names g22425 g24105 +0 1 +.names g22428 g24106 +0 1 +.names g22431 g24107 +0 1 +.names g22434 g24108 +0 1 +.names g22437 g24110 +0 1 +.names g22440 g24111 +0 1 +.names g22445 g24112 +0 1 +.names g22448 g24113 +0 1 +.names g22451 g24114 +0 1 +.names g21211 g14442 g10694 g22381 +0-- 1 +-0- 1 +--0 1 +.names g22381 g24115 +0 1 +.names g22455 g24121 +0 1 +.names g22458 g24122 +0 1 +.names g22461 g24123 +0 1 +.names g22464 g24124 +0 1 +.names g22467 g24125 +0 1 +.names g22470 g24127 +0 1 +.names g22473 g24128 +0 1 +.names g22477 g24129 +0 1 +.names g22480 g24130 +0 1 +.names g22484 g24131 +0 1 +.names g22487 g24132 +0 1 +.names g22490 g24133 +0 1 +.names g21219 g14529 g10714 g22396 +0-- 1 +-0- 1 +--0 1 +.names g22396 g24134 +0 1 +.names g22494 g24140 +0 1 +.names g22497 g24141 +0 1 +.names g22500 g24142 +0 1 +.names g22503 g24143 +0 1 +.names g22506 g24144 +0 1 +.names g22509 g24146 +0 1 +.names g22512 g24147 +0 1 +.names g22520 g24148 +0 1 +.names g22523 g24149 +0 1 +.names g22527 g24150 +0 1 +.names g22530 g24151 +0 1 +.names g22533 g24152 +0 1 +.names g21230 g14584 g10735 g22399 +0-- 1 +-0- 1 +--0 1 +.names g22399 g24153 +0 1 +.names g22537 g24159 +0 1 +.names g22540 g24160 +0 1 +.names g22543 g24161 +0 1 +.names g22552 g24162 +0 1 +.names g22560 g24163 +0 1 +.names g22563 g24164 +0 1 +.names g22567 g24165 +0 1 +.names g22570 g24166 +0 1 +.names g22573 g24167 +0 1 +.names g21235 g14618 g10754 g22400 +0-- 1 +-0- 1 +--0 1 +.names g22400 g24168 +0 1 +.names g22592 g24175 +0 1 +.names g22600 g24176 +0 1 +.names g22603 g24177 +0 1 +.names g22629 g24180 +0 1 +.names g562 g559 g12451 g21851 g22811 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g22811 II31387 +0 1 +.names II31387 g24183 +0 1 +.names g22696 g24210 +0 1 +.names g22750 g24220 +0 1 +.names g22578 II31417 +0 1 +.names II31417 g24233 +0 1 +.names g22615 II31426 +0 1 +.names II31426 g24240 +0 1 +.names g22651 II31436 +0 1 +.names II31436 g24248 +0 1 +.names g22903 g24251 +0 1 +.names g22687 II31445 +0 1 +.names II31445 g24255 +0 1 +.names g23682 II31451 +0 1 +.names g23727 II31454 +0 1 +.names g23773 II31457 +0 1 +.names g23728 II31460 +0 1 +.names g23774 II31463 +0 1 +.names g23821 II31466 +0 1 +.names g23546 II31469 +0 1 +.names g23548 II31472 +0 1 +.names g23555 II31475 +0 1 +.names g23549 II31478 +0 1 +.names g23556 II31481 +0 1 +.names g23568 II31484 +0 1 +.names g23557 II31487 +0 1 +.names g23569 II31490 +0 1 +.names g23587 II31493 +0 1 +.names g23570 II31496 +0 1 +.names g23588 II31499 +0 1 +.names g23612 II31502 +0 1 +.names g23589 II31505 +0 1 +.names g23613 II31508 +0 1 +.names g23640 II31511 +0 1 +.names g23614 II31514 +0 1 +.names g23641 II31517 +0 1 +.names g23683 II31520 +0 1 +.names g23642 II31523 +0 1 +.names g23684 II31526 +0 1 +.names g23729 II31529 +0 1 +.names g23685 II31532 +0 1 +.names g23730 II31535 +0 1 +.names g23775 II31538 +0 1 +.names g23500 II31541 +0 1 +.names g23438 II31544 +0 1 +.names g23454 II31547 +0 1 +.names g23481 II31550 +0 1 +.names g23501 II31553 +0 1 +.names g23439 II31556 +0 1 +.names g24233 II31559 +0 1 +.names g23594 II31562 +0 1 +.names g24001 II31565 +0 1 +.names g24033 II31568 +0 1 +.names g24051 II31571 +0 1 +.names g23736 II31574 +0 1 +.names g23782 II31577 +0 1 +.names g23826 II31580 +0 1 +.names g23783 II31583 +0 1 +.names g23827 II31586 +0 1 +.names g23856 II31589 +0 1 +.names g23553 II31592 +0 1 +.names g23561 II31595 +0 1 +.names g23574 II31598 +0 1 +.names g23562 II31601 +0 1 +.names g23575 II31604 +0 1 +.names g23595 II31607 +0 1 +.names g23576 II31610 +0 1 +.names g23596 II31613 +0 1 +.names g23619 II31616 +0 1 +.names g23597 II31619 +0 1 +.names g23620 II31622 +0 1 +.names g23661 II31625 +0 1 +.names g23621 II31628 +0 1 +.names g23662 II31631 +0 1 +.names g23690 II31634 +0 1 +.names g23663 II31637 +0 1 +.names g23691 II31640 +0 1 +.names g23737 II31643 +0 1 +.names g23692 II31646 +0 1 +.names g23738 II31649 +0 1 +.names g23784 II31652 +0 1 +.names g23739 II31655 +0 1 +.names g23785 II31658 +0 1 +.names g23828 II31661 +0 1 +.names g23516 II31664 +0 1 +.names g23452 II31667 +0 1 +.names g23463 II31670 +0 1 +.names g23492 II31673 +0 1 +.names g23517 II31676 +0 1 +.names g23453 II31679 +0 1 +.names g24240 II31682 +0 1 +.names g23626 II31685 +0 1 +.names g24035 II31688 +0 1 +.names g24053 II31691 +0 1 +.names g24064 II31694 +0 1 +.names g23791 II31697 +0 1 +.names g23835 II31700 +0 1 +.names g23861 II31703 +0 1 +.names g23836 II31706 +0 1 +.names g23862 II31709 +0 1 +.names g23890 II31712 +0 1 +.names g23566 II31715 +0 1 +.names g23580 II31718 +0 1 +.names g23601 II31721 +0 1 +.names g23581 II31724 +0 1 +.names g23602 II31727 +0 1 +.names g23627 II31730 +0 1 +.names g23603 II31733 +0 1 +.names g23628 II31736 +0 1 +.names g23668 II31739 +0 1 +.names g23629 II31742 +0 1 +.names g23669 II31745 +0 1 +.names g23711 II31748 +0 1 +.names g23670 II31751 +0 1 +.names g23712 II31754 +0 1 +.names g23744 II31757 +0 1 +.names g23713 II31760 +0 1 +.names g23745 II31763 +0 1 +.names g23792 II31766 +0 1 +.names g23746 II31769 +0 1 +.names g23793 II31772 +0 1 +.names g23837 II31775 +0 1 +.names g23794 II31778 +0 1 +.names g23838 II31781 +0 1 +.names g23863 II31784 +0 1 +.names g23531 II31787 +0 1 +.names g23459 II31790 +0 1 +.names g23472 II31793 +0 1 +.names g23508 II31796 +0 1 +.names g23532 II31799 +0 1 +.names g23460 II31802 +0 1 +.names g24248 II31805 +0 1 +.names g23675 II31808 +0 1 +.names g24055 II31811 +0 1 +.names g24066 II31814 +0 1 +.names g24077 II31817 +0 1 +.names g23844 II31820 +0 1 +.names g23870 II31823 +0 1 +.names g23895 II31826 +0 1 +.names g23871 II31829 +0 1 +.names g23896 II31832 +0 1 +.names g23911 II31835 +0 1 +.names g23585 II31838 +0 1 +.names g23607 II31841 +0 1 +.names g23633 II31844 +0 1 +.names g23608 II31847 +0 1 +.names g23634 II31850 +0 1 +.names g23676 II31853 +0 1 +.names g23635 II31856 +0 1 +.names g23677 II31859 +0 1 +.names g23718 II31862 +0 1 +.names g23678 II31865 +0 1 +.names g23719 II31868 +0 1 +.names g23765 II31871 +0 1 +.names g23720 II31874 +0 1 +.names g23766 II31877 +0 1 +.names g23799 II31880 +0 1 +.names g23767 II31883 +0 1 +.names g23800 II31886 +0 1 +.names g23845 II31889 +0 1 +.names g23801 II31892 +0 1 +.names g23846 II31895 +0 1 +.names g23872 II31898 +0 1 +.names g23847 II31901 +0 1 +.names g23873 II31904 +0 1 +.names g23897 II31907 +0 1 +.names g23542 II31910 +0 1 +.names g23468 II31913 +0 1 +.names g23485 II31916 +0 1 +.names g23524 II31919 +0 1 +.names g23543 II31922 +0 1 +.names g23469 II31925 +0 1 +.names g24255 II31928 +0 1 +.names g23725 II31931 +0 1 +.names g24068 II31934 +0 1 +.names g24079 II31937 +0 1 +.names g24088 II31940 +0 1 +.names g24000 II31943 +0 1 +.names g23916 II31946 +0 1 +.names g23943 II31949 +0 1 +.names g24183 g24482 +0 1 +.names g17506 g22581 g23399 +00 1 +.names g23399 II32042 +0 1 +.names II32042 g24518 +0 1 +.names g17597 g22618 g23406 +00 1 +.names g23406 II32057 +0 1 +.names II32057 g24531 +0 1 +.names g16894 g22206 g24174 +00 1 +.names g24174 II32067 +0 1 +.names II32067 g24539 +0 1 +.names g17694 g22654 g23413 +00 1 +.names g23413 II32074 +0 1 +.names II32074 g24544 +0 1 +.names g16908 g22211 g24178 +00 1 +.names g24178 II32081 +0 1 +.names II32081 g24549 +0 1 +.names g16923 g22214 g24179 +00 1 +.names g24179 II32085 +0 1 +.names II32085 g24551 +0 1 +.names g17794 g22690 g23418 +00 1 +.names g23418 II32092 +0 1 +.names II32092 g24556 +0 1 +.names g16938 g22220 g24181 +00 1 +.names g24181 II32098 +0 1 +.names II32098 g24560 +0 1 +.names g16953 g22223 g24182 +00 1 +.names g24182 II32102 +0 1 +.names II32102 g24562 +0 1 +.names g16966 g22228 g24206 +00 1 +.names g24206 II32109 +0 1 +.names II32109 g24567 +0 1 +.names g16967 g22229 g24207 +00 1 +.names g24207 II32112 +0 1 +.names II32112 g24568 +0 1 +.names g16969 g22235 g24208 +00 1 +.names g24208 II32116 +0 1 +.names II32116 g24570 +0 1 +.names g16984 g22238 g24209 +00 1 +.names g24209 II32120 +0 1 +.names II32120 g24572 +0 1 +.names g16987 g22244 g24212 +00 1 +.names g24212 II32126 +0 1 +.names II32126 g24576 +0 1 +.names g16988 g22245 g24213 +00 1 +.names g24213 II32129 +0 1 +.names II32129 g24577 +0 1 +.names g16990 g22250 g24214 +00 1 +.names g24214 II32133 +0 1 +.names II32133 g24579 +0 1 +.names g16993 g22254 g24215 +00 1 +.names g24215 II32137 +0 1 +.names II32137 g24581 +0 1 +.names g16994 g22255 g24216 +00 1 +.names g24216 II32140 +0 1 +.names II32140 g24582 +0 1 +.names g16997 g22264 g24218 +00 1 +.names g24218 II32143 +0 1 +.names II32143 g24583 +0 1 +.names g16998 g22265 g24219 +00 1 +.names g24219 II32146 +0 1 +.names II32146 g24584 +0 1 +.names g17017 g22272 g24222 +00 1 +.names g24222 II32150 +0 1 +.names II32150 g24586 +0 1 +.names g17018 g22273 g24223 +00 1 +.names g24223 II32153 +0 1 +.names II32153 g24587 +0 1 +.names g17021 g22281 g24225 +00 1 +.names g24225 II32156 +0 1 +.names II32156 g24588 +0 1 +.names g17022 g22282 g24226 +00 1 +.names g24226 II32159 +0 1 +.names II32159 g24589 +0 1 +.names g17028 g22285 g24228 +00 1 +.names g24228 II32164 +0 1 +.names II32164 g24592 +0 1 +.names g17047 g22291 g24230 +00 1 +.names g24230 II32167 +0 1 +.names II32167 g24593 +0 1 +.names g17048 g22292 g24231 +00 1 +.names g24231 II32170 +0 1 +.names II32170 g24594 +0 1 +.names g17062 g22305 g24235 +00 1 +.names g24235 II32175 +0 1 +.names II32175 g24597 +0 1 +.names g17081 g22311 g24237 +00 1 +.names g24237 II32178 +0 1 +.names II32178 g24598 +0 1 +.names g17082 g22312 g24238 +00 1 +.names g24238 II32181 +0 1 +.names II32181 g24599 +0 1 +.names g22876 g5606 g23497 +00 1 +.names g23497 II32184 +0 1 +.names II32184 g24600 +0 1 +.names g17097 g22333 g24243 +00 1 +.names g24243 II32189 +0 1 +.names II32189 g24605 +0 1 +.names g22911 g5631 g23513 +00 1 +.names g23513 II32193 +0 1 +.names II32193 g24607 +0 1 +.names g17135 g22358 g24250 +00 1 +.names g24250 II32198 +0 1 +.names II32198 g24612 +0 1 +.names g22936 g5659 g23528 +00 1 +.names g23528 II32203 +0 1 +.names II32203 g24619 +0 1 +.names g22942 g5697 g23539 +00 1 +.names g23539 II32210 +0 1 +.names II32210 g24630 +0 1 +.names g23470 g24648 +0 1 +.names g23482 g24668 +0 1 +.names g23493 g24687 +0 1 +.names g23509 g24704 +0 1 +.names g22666 g23140 g23919 +1- 1 +-1 1 +.names g23919 II32248 +0 1 +.names g23919 II32251 +0 1 +.names II32251 g24735 +0 1 +.names g22992 g6707 g23950 +00 1 +.names g23950 II32281 +0 1 +.names II32281 g24763 +0 1 +.names g23003 g7009 g23979 +00 1 +.names g23979 II32320 +0 1 +.names II32320 g24784 +0 1 +.names g23017 g7259 g24009 +00 1 +.names g24009 II32365 +0 1 +.names II32365 g24805 +0 1 +.names g23448 g24815 +0 1 +.names g17393 g22517 g23385 +00 1 +.names g23385 II32388 +0 1 +.names II32388 g24816 +0 1 +.names g23033 g7455 g24043 +00 1 +.names g24043 II32419 +0 1 +.names II32419 g24827 +0 1 +.names g23455 g24834 +0 1 +.names g17460 g22557 g23392 +00 1 +.names g23392 II32439 +0 1 +.names II32439 g24835 +0 1 +.names g23464 g24850 +0 1 +.names g17540 g22597 g23400 +00 1 +.names g23400 II32487 +0 1 +.names II32487 g24851 +0 1 +.names g22144 g10024 g23324 +00 1 +.names g23324 II32506 +0 1 +.names II32506 g24856 +0 1 +.names g23473 g24864 +0 1 +.names g17630 g22634 g23407 +00 1 +.names g23407 II32535 +0 1 +.names II32535 g24865 +0 1 +.names g22165 g10133 g23329 +00 1 +.names g23329 II32556 +0 1 +.names II32556 g24872 +0 1 +.names g22186 g22777 g23330 +00 1 +.names g23330 II32583 +0 1 +.names II32583 g24879 +0 1 +.names g22181 g10238 g23339 +00 1 +.names g23339 II32604 +0 1 +.names II32604 g24886 +0 1 +.names g22844 g14442 g10694 g23486 +0-- 1 +-0- 1 +--0 1 +.names g23486 g24893 +0 1 +.names g22195 g10340 g23348 +00 1 +.names g23348 II32642 +0 1 +.names II32642 g24903 +0 1 +.names g10694 g14442 g22316 g23495 +0-- 1 +-0- 1 +--0 1 +.names g23495 g24912 +0 1 +.names g22879 g14529 g10714 g23502 +0-- 1 +-0- 1 +--0 1 +.names g23502 g24916 +0 1 +.names g10714 g14529 g22341 g23511 +0-- 1 +-0- 1 +--0 1 +.names g23511 g24929 +0 1 +.names g22914 g14584 g10735 g23518 +0-- 1 +-0- 1 +--0 1 +.names g23518 g24933 +0 1 +.names II30791 II30792 g23660 +0- 1 +-0 1 +.names g23660 g24939 +0 1 +.names g10735 g14584 g22364 g23526 +0-- 1 +-0- 1 +--0 1 +.names g23526 g24941 +0 1 +.names g22939 g14618 g10754 g23533 +0-- 1 +-0- 1 +--0 1 +.names g23533 g24945 +0 1 +.names g22210 g20127 g23357 +00 1 +.names g23357 II32704 +0 1 +.names II32704 g24949 +0 1 +.names II30869 II30870 g23710 +0- 1 +-0 1 +.names g23710 g24950 +0 1 +.names g10754 g14618 g22384 g23537 +0-- 1 +-0- 1 +--0 1 +.names g23537 g24952 +0 1 +.names g22227 g18407 g23358 +00 1 +.names g23358 II32716 +0 1 +.names II32716 g24956 +0 1 +.names g22216 g22907 g23359 +00 1 +.names g23359 II32719 +0 1 +.names II32719 g24957 +0 1 +.names g22809 g14442 g10694 g23478 +0-- 1 +-0- 1 +--0 1 +.names g23478 g24958 +0 1 +.names II30953 II30954 g23764 +0- 1 +-0 1 +.names g23764 g24962 +0 1 +.names g22850 g14529 g10714 g23489 +0-- 1 +-0- 1 +--0 1 +.names g23489 g24969 +0 1 +.names II31036 II31037 g23819 +0- 1 +-0 1 +.names g23819 g24973 +0 1 +.names g22885 g14584 g10735 g23505 +0-- 1 +-0- 1 +--0 1 +.names g23505 g24982 +0 1 +.names g22920 g14618 g10754 g23521 +0-- 1 +-0- 1 +--0 1 +.names g23521 g24993 +0 1 +.names g23731 g25087 +0 1 +.names g23779 g25094 +0 1 +.names g23786 g25095 +0 1 +.names g21990 g20809 g24059 +00 1 +.names g24059 II32829 +0 1 +.names II32829 g25103 +0 1 +.names g23832 g25104 +0 1 +.names g23839 g25105 +0 1 +.names g22004 g20826 g24072 +00 1 +.names g24072 II32835 +0 1 +.names II32835 g25109 +0 1 +.names g23867 g25110 +0 1 +.names g23874 g25111 +0 1 +.names g23879 g25115 +0 1 +.names g23882 g25116 +0 1 +.names g23644 II32844 +0 1 +.names II32844 g25118 +0 1 +.names g22015 g20836 g24083 +00 1 +.names g24083 II32847 +0 1 +.names II32847 g25119 +0 1 +.names g23901 g25120 +0 1 +.names g23694 II32851 +0 1 +.names II32851 g25121 +0 1 +.names g22020 g20840 g24092 +00 1 +.names g24092 II32854 +0 1 +.names II32854 g25122 +0 1 +.names g23748 II32857 +0 1 +.names II32857 g25123 +0 1 +.names g23803 II32860 +0 1 +.names II32860 g25124 +0 1 +.names g24030 g25126 +0 1 +.names g25118 II32868 +0 1 +.names g24518 II32871 +0 1 +.names g24539 II32874 +0 1 +.names g24567 II32877 +0 1 +.names g24581 II32880 +0 1 +.names g24592 II32883 +0 1 +.names g24549 II32886 +0 1 +.names g24568 II32889 +0 1 +.names g24582 II32892 +0 1 +.names g24816 II32895 +0 1 +.names g24856 II32898 +0 1 +.names g25121 II32901 +0 1 +.names g24531 II32904 +0 1 +.names g24551 II32907 +0 1 +.names g24576 II32910 +0 1 +.names g24586 II32913 +0 1 +.names g24597 II32916 +0 1 +.names g24560 II32919 +0 1 +.names g24577 II32922 +0 1 +.names g24587 II32925 +0 1 +.names g24835 II32928 +0 1 +.names g24872 II32931 +0 1 +.names g25123 II32934 +0 1 +.names g24544 II32937 +0 1 +.names g24562 II32940 +0 1 +.names g24583 II32943 +0 1 +.names g24593 II32946 +0 1 +.names g24605 II32949 +0 1 +.names g24570 II32952 +0 1 +.names g24584 II32955 +0 1 +.names g24594 II32958 +0 1 +.names g24851 II32961 +0 1 +.names g24886 II32964 +0 1 +.names g25124 II32967 +0 1 +.names g24556 II32970 +0 1 +.names g24572 II32973 +0 1 +.names g24588 II32976 +0 1 +.names g24598 II32979 +0 1 +.names g24612 II32982 +0 1 +.names g24579 II32985 +0 1 +.names g24589 II32988 +0 1 +.names g24599 II32991 +0 1 +.names g24865 II32994 +0 1 +.names g24903 II32997 +0 1 +.names g24949 II33000 +0 1 +.names g24956 II33003 +0 1 +.names g24957 II33006 +0 1 +.names g24879 II33009 +0 1 +.names g25119 II33013 +0 1 +.names II33013 g25179 +0 1 +.names g25122 II33016 +0 1 +.names II33016 g25180 +0 1 +.names g24912 g25274 +0 1 +.names g24929 g25283 +0 1 +.names g24941 g25291 +0 1 +.names g23497 g74 g24975 +0- 1 +-0 1 +.names g24975 II33128 +0 1 +.names II33128 g25296 +0 1 +.names g24952 g25301 +0 1 +.names II32587 II32588 g24880 +0- 1 +-0 1 +.names g24880 g25305 +0 1 +.names g23513 g762 g24986 +0- 1 +-0 1 +.names g24986 II33136 +0 1 +.names II33136 g25306 +0 1 +.names II32547 II32548 g24868 +0- 1 +-0 1 +.names g24868 g25313 +0 1 +.names II32625 II32626 g24897 +0- 1 +-0 1 +.names g24897 g25314 +0 1 +.names g23528 g1448 g24997 +0- 1 +-0 1 +.names g24997 II33145 +0 1 +.names II33145 g25315 +0 1 +.names II32510 II32511 g24857 +0- 1 +-0 1 +.names g24857 g25319 +0 1 +.names II32596 II32597 g24883 +0- 1 +-0 1 +.names g24883 g25322 +0 1 +.names II32660 II32661 g24920 +0- 1 +-0 1 +.names g24920 g25323 +0 1 +.names g23539 g2142 g25005 +0- 1 +-0 1 +.names g25005 II33154 +0 1 +.names II33154 g25324 +0 1 +.names g24227 g17001 g25027 +00 1 +.names g25027 II33157 +0 1 +.names II33157 g25327 +0 1 +.names II32469 II32470 g24844 +0- 1 +-0 1 +.names g24844 g25329 +0 1 +.names II32560 II32561 g24873 +0- 1 +-0 1 +.names g24873 g25330 +0 1 +.names II32634 II32635 g24900 +0- 1 +-0 1 +.names g24900 g25332 +0 1 +.names II32687 II32688 g24937 +0- 1 +-0 1 +.names g24937 g25333 +0 1 +.names II32431 II32432 g24832 +0- 1 +-0 1 +.names g24832 g25335 +0 1 +.names g24234 g17031 g25042 +00 1 +.names g25042 II33168 +0 1 +.names II33168 g25336 +0 1 +.names II32519 II32520 g24860 +0- 1 +-0 1 +.names g24860 g25338 +0 1 +.names II32608 II32609 g24887 +0- 1 +-0 1 +.names g24887 g25339 +0 1 +.names II32669 II32670 g24923 +0- 1 +-0 1 +.names g24923 g25341 +0 1 +.names II32392 II32393 g24817 +0- 1 +-0 1 +.names g24817 g25347 +0 1 +.names II32479 II32480 g24848 +0- 1 +-0 1 +.names g24848 g25349 +0 1 +.names g24242 g17065 g25056 +00 1 +.names g25056 II33182 +0 1 +.names II33182 g25350 +0 1 +.names II32568 II32569 g24875 +0- 1 +-0 1 +.names g24875 g25352 +0 1 +.names II32646 II32647 g24904 +0- 1 +-0 1 +.names g24904 g25353 +0 1 +.names g24239 g24244 g24814 +0- 1 +-0 1 +.names g24814 II33188 +0 1 +.names II33188 g25354 +0 1 +.names II32346 II32347 g24797 +0- 1 +-0 1 +.names g24797 g25355 +0 1 +.names II32444 II32445 g24837 +0- 1 +-0 1 +.names g24837 g25361 +0 1 +.names II32527 II32528 g24862 +0- 1 +-0 1 +.names g24862 g25363 +0 1 +.names g24249 g17100 g25067 +00 1 +.names g25067 II33198 +0 1 +.names II33198 g25364 +0 1 +.names II32616 II32617 g24889 +0- 1 +-0 1 +.names g24889 g25366 +0 1 +.names g13568 g24115 g24676 +11 1 +.names g24676 g25367 +0 1 +.names II32309 II32310 g24778 +0- 1 +-0 1 +.names g24778 g25368 +0 1 +.names g24245 g24252 g24833 +0- 1 +-0 1 +.names g24833 II33205 +0 1 +.names II33205 g25369 +0 1 +.names II32401 II32402 g24820 +0- 1 +-0 1 +.names g24820 g25370 +0 1 +.names II32491 II32492 g24852 +0- 1 +-0 1 +.names g24852 g25376 +0 1 +.names II32576 II32577 g24877 +0- 1 +-0 1 +.names g24877 g25378 +0 1 +.names g24893 g25379 +0 1 +.names II32285 II32286 g24766 +0- 1 +-0 1 +.names g24766 g25383 +0 1 +.names g13576 g24134 g24695 +11 1 +.names g24695 g25384 +0 1 +.names II32356 II32357 g24801 +0- 1 +-0 1 +.names g24801 g25385 +0 1 +.names g24254 g24257 g24849 +0- 1 +-0 1 +.names g24849 II33219 +0 1 +.names II33219 g25386 +0 1 +.names II32452 II32453 g24839 +0- 1 +-0 1 +.names g24839 g25387 +0 1 +.names II32539 II32540 g24866 +0- 1 +-0 1 +.names g24866 g25393 +0 1 +.names II32266 II32267 g24753 +0- 1 +-0 1 +.names g24753 g25394 +0 1 +.names g24916 g25395 +0 1 +.names II32324 II32325 g24787 +0- 1 +-0 1 +.names g24787 g25399 +0 1 +.names g13585 g24153 g24712 +11 1 +.names g24712 g25400 +0 1 +.names II32410 II32411 g24823 +0- 1 +-0 1 +.names g24823 g25401 +0 1 +.names g24258 g23319 g24863 +0- 1 +-0 1 +.names g24863 II33232 +0 1 +.names II33232 g25402 +0 1 +.names II32499 II32500 g24854 +0- 1 +-0 1 +.names g24854 g25403 +0 1 +.names II32296 II32297 g24771 +0- 1 +-0 1 +.names g24771 g25404 +0 1 +.names g24933 g25405 +0 1 +.names II32369 II32370 g24808 +0- 1 +-0 1 +.names g24808 g25409 +0 1 +.names g13605 g24168 g24723 +11 1 +.names g24723 g25410 +0 1 +.names II32461 II32462 g24842 +0- 1 +-0 1 +.names g24842 g25411 +0 1 +.names II32334 II32335 g24791 +0- 1 +-0 1 +.names g24791 g25412 +0 1 +.names g24945 g25413 +0 1 +.names II32423 II32424 g24830 +0- 1 +-0 1 +.names g24830 g25417 +0 1 +.names II32379 II32380 g24812 +0- 1 +-0 1 +.names g24812 g25419 +0 1 +.names g23639 g23144 g24890 +1- 1 +-1 1 +.names g24890 II33246 +0 1 +.names g24890 II33249 +0 1 +.names II33249 g25421 +0 1 +.names g24958 g25422 +0 1 +.names g499 g23376 g24616 +0- 1 +-0 1 +.names g24616 g25430 +0 1 +.names g24969 g25431 +0 1 +.names g23726 g23142 g24909 +1- 1 +-1 1 +.names g24909 II33257 +0 1 +.names g24909 II33260 +0 1 +.names II33260 g25436 +0 1 +.names g1186 g23387 g24627 +0- 1 +-0 1 +.names g24627 g25437 +0 1 +.names g24982 g25438 +0 1 +.names g23772 g23141 g24925 +1- 1 +-1 1 +.names g24925 II33265 +0 1 +.names g24925 II33268 +0 1 +.names II33268 g25443 +0 1 +.names g1880 g23394 g24641 +0- 1 +-0 1 +.names g24641 g25444 +0 1 +.names g24993 g25445 +0 1 +.names g2574 g23402 g24660 +0- 1 +-0 1 +.names g24660 g25449 +0 1 +.names g23950 g679 g25088 +0- 1 +-0 1 +.names g25088 II33278 +0 1 +.names II33278 g25454 +0 1 +.names g23979 g1365 g25096 +0- 1 +-0 1 +.names g25096 II33282 +0 1 +.names II33282 g25458 +0 1 +.names g23386 g10024 g24426 +00 1 +.names g24426 II33286 +0 1 +.names II33286 g25462 +0 1 +.names g24009 g2059 g25106 +0- 1 +-0 1 +.names g25106 II33289 +0 1 +.names II33289 g25463 +0 1 +.names g23644 g5438 g25008 +0- 1 +-0 1 +.names g25008 II33293 +0 1 +.names II33293 g25467 +0 1 +.names g23393 g10133 g24430 +00 1 +.names g24430 II33297 +0 1 +.names II33297 g25471 +0 1 +.names g24043 g2753 g25112 +0- 1 +-0 1 +.names g25112 II33300 +0 1 +.names II33300 g25472 +0 1 +.names g23644 g6448 g25004 +0- 1 +-0 1 +.names g25004 II33304 +0 1 +.names II33304 g25476 +0 1 +.names g23644 g5438 g25011 +0- 1 +-0 1 +.names g25011 II33307 +0 1 +.names II33307 g25479 +0 1 +.names g23694 g5473 g25014 +0- 1 +-0 1 +.names g25014 II33312 +0 1 +.names II33312 g25484 +0 1 +.names g23401 g10238 g24434 +00 1 +.names g24434 II33316 +0 1 +.names II33316 g25488 +0 1 +.names g23644 g3306 g24442 +0- 1 +-0 1 +.names g24442 II33321 +0 1 +.names II33321 g25493 +0 1 +.names g23644 g6448 g25009 +0- 1 +-0 1 +.names g25009 II33324 +0 1 +.names II33324 g25496 +0 1 +.names g23644 g5438 g25017 +0- 1 +-0 1 +.names g25017 II33327 +0 1 +.names II33327 g25499 +0 1 +.names g23923 g6486 g25019 +0- 1 +-0 1 +.names g25019 II33330 +0 1 +.names II33330 g25502 +0 1 +.names g23694 g6713 g25010 +0- 1 +-0 1 +.names g25010 II33335 +0 1 +.names II33335 g25507 +0 1 +.names g23694 g5473 g25021 +0- 1 +-0 1 +.names g25021 II33338 +0 1 +.names II33338 g25510 +0 1 +.names g23748 g5512 g25024 +0- 1 +-0 1 +.names g25024 II33343 +0 1 +.names II33343 g25515 +0 1 +.names g23408 g10340 g24438 +00 1 +.names g24438 II33347 +0 1 +.names II33347 g25519 +0 1 +.names g23644 g3306 g24443 +0- 1 +-0 1 +.names g24443 II33352 +0 1 +.names II33352 g25524 +0 1 +.names g23644 g6448 g25012 +0- 1 +-0 1 +.names g25012 II33355 +0 1 +.names II33355 g25527 +0 1 +.names g23644 g5438 g25028 +0- 1 +-0 1 +.names g25028 II33358 +0 1 +.names II33358 g25530 +0 1 +.names g23923 g6643 g25013 +0- 1 +-0 1 +.names g25013 II33361 +0 1 +.names II33361 g25533 +0 1 +.names g23923 g6486 g25029 +0- 1 +-0 1 +.names g25029 II33364 +0 1 +.names II33364 g25536 +0 1 +.names g23694 g3462 g24444 +0- 1 +-0 1 +.names g24444 II33368 +0 1 +.names II33368 g25540 +0 1 +.names g23694 g6713 g25015 +0- 1 +-0 1 +.names g25015 II33371 +0 1 +.names II33371 g25543 +0 1 +.names g23694 g5473 g25031 +0- 1 +-0 1 +.names g25031 II33374 +0 1 +.names II33374 g25546 +0 1 +.names g23955 g6751 g25033 +0- 1 +-0 1 +.names g25033 II33377 +0 1 +.names II33377 g25549 +0 1 +.names g23748 g7015 g25016 +0- 1 +-0 1 +.names g25016 II33382 +0 1 +.names II33382 g25554 +0 1 +.names g23748 g5512 g25035 +0- 1 +-0 1 +.names g25035 II33385 +0 1 +.names II33385 g25557 +0 1 +.names g23803 g5556 g25038 +0- 1 +-0 1 +.names g25038 II33390 +0 1 +.names II33390 g25562 +0 1 +.names g23644 g3306 g24447 +0- 1 +-0 1 +.names g24447 II33396 +0 1 +.names II33396 g25573 +0 1 +.names g23644 g6448 g25018 +0- 1 +-0 1 +.names g25018 II33399 +0 1 +.names II33399 g25576 +0 1 +.names g23923 g3338 g24448 +0- 1 +-0 1 +.names g24448 II33402 +0 1 +.names II33402 g25579 +0 1 +.names g23923 g6643 g25020 +0- 1 +-0 1 +.names g25020 II33405 +0 1 +.names II33405 g25582 +0 1 +.names g23923 g6486 g25040 +0- 1 +-0 1 +.names g25040 II33408 +0 1 +.names II33408 g25585 +0 1 +.names g15247 g23735 g24491 +00 1 +.names g24491 II33411 +0 1 +.names II33411 g25588 +0 1 +.names g23694 g3462 g24449 +0- 1 +-0 1 +.names g24449 II33415 +0 1 +.names II33415 g25590 +0 1 +.names g23694 g6713 g25022 +0- 1 +-0 1 +.names g25022 II33418 +0 1 +.names II33418 g25593 +0 1 +.names g23694 g5473 g25043 +0- 1 +-0 1 +.names g25043 II33421 +0 1 +.names II33421 g25596 +0 1 +.names g23955 g6945 g25023 +0- 1 +-0 1 +.names g25023 II33424 +0 1 +.names II33424 g25599 +0 1 +.names g23955 g6751 g25044 +0- 1 +-0 1 +.names g25044 II33427 +0 1 +.names II33427 g25602 +0 1 +.names g23748 g3618 g24450 +0- 1 +-0 1 +.names g24450 II33431 +0 1 +.names II33431 g25606 +0 1 +.names g23748 g7015 g25025 +0- 1 +-0 1 +.names g25025 II33434 +0 1 +.names II33434 g25609 +0 1 +.names g23748 g5512 g25046 +0- 1 +-0 1 +.names g25046 II33437 +0 1 +.names II33437 g25612 +0 1 +.names g23984 g7053 g25048 +0- 1 +-0 1 +.names g25048 II33440 +0 1 +.names II33440 g25615 +0 1 +.names g23803 g7265 g25026 +0- 1 +-0 1 +.names g25026 II33445 +0 1 +.names II33445 g25620 +0 1 +.names g23803 g5556 g25050 +0- 1 +-0 1 +.names g25050 II33448 +0 1 +.names II33448 g25623 +0 1 +.names g23545 g21119 g21227 g24478 +111 1 +.names g24478 g25630 +0 1 +.names g23644 g3306 g24451 +0- 1 +-0 1 +.names g24451 II33457 +0 1 +.names II33457 g25634 +0 1 +.names g23923 g3338 g24452 +0- 1 +-0 1 +.names g24452 II33460 +0 1 +.names II33460 g25637 +0 1 +.names g23923 g6643 g25030 +0- 1 +-0 1 +.names g25030 II33463 +0 1 +.names II33463 g25640 +0 1 +.names g23923 g6486 g25053 +0- 1 +-0 1 +.names g25053 II33466 +0 1 +.names II33466 g25643 +0 1 +.names g15324 g23777 g24498 +00 1 +.names g24498 II33469 +0 1 +.names II33469 g25646 +0 1 +.names g15325 g23778 g24499 +00 1 +.names g24499 II33472 +0 1 +.names II33472 g25647 +0 1 +.names g23694 g3462 g24453 +0- 1 +-0 1 +.names g24453 II33476 +0 1 +.names II33476 g25652 +0 1 +.names g23694 g6713 g25032 +0- 1 +-0 1 +.names g25032 II33479 +0 1 +.names II33479 g25655 +0 1 +.names g23955 g3494 g24454 +0- 1 +-0 1 +.names g24454 II33482 +0 1 +.names II33482 g25658 +0 1 +.names g23955 g6945 g25034 +0- 1 +-0 1 +.names g25034 II33485 +0 1 +.names II33485 g25661 +0 1 +.names g23955 g6751 g25054 +0- 1 +-0 1 +.names g25054 II33488 +0 1 +.names II33488 g25664 +0 1 +.names g15339 g23790 g24501 +00 1 +.names g24501 II33491 +0 1 +.names II33491 g25667 +0 1 +.names g23748 g3618 g24455 +0- 1 +-0 1 +.names g24455 II33495 +0 1 +.names II33495 g25669 +0 1 +.names g23748 g7015 g25036 +0- 1 +-0 1 +.names g25036 II33498 +0 1 +.names II33498 g25672 +0 1 +.names g23748 g5512 g25057 +0- 1 +-0 1 +.names g25057 II33501 +0 1 +.names II33501 g25675 +0 1 +.names g23984 g7195 g25037 +0- 1 +-0 1 +.names g25037 II33504 +0 1 +.names II33504 g25678 +0 1 +.names g23984 g7053 g25058 +0- 1 +-0 1 +.names g25058 II33507 +0 1 +.names II33507 g25681 +0 1 +.names g23803 g3774 g24456 +0- 1 +-0 1 +.names g24456 II33511 +0 1 +.names II33511 g25685 +0 1 +.names g23803 g7265 g25039 +0- 1 +-0 1 +.names g25039 II33514 +0 1 +.names II33514 g25688 +0 1 +.names g23803 g5556 g25060 +0- 1 +-0 1 +.names g25060 II33517 +0 1 +.names II33517 g25691 +0 1 +.names g24014 g7303 g25062 +0- 1 +-0 1 +.names g25062 II33520 +0 1 +.names II33520 g25694 +0 1 +.names g24600 g25698 +0 1 +.names g23923 g3338 g24457 +0- 1 +-0 1 +.names g24457 II33526 +0 1 +.names II33526 g25700 +0 1 +.names g23923 g6643 g25041 +0- 1 +-0 1 +.names g25041 II33529 +0 1 +.names II33529 g25703 +0 1 +.names g15391 g23824 g24507 +00 1 +.names g24507 II33532 +0 1 +.names II33532 g25706 +0 1 +.names g15392 g23825 g24508 +00 1 +.names g24508 II33535 +0 1 +.names II33535 g25707 +0 1 +.names g23694 g3462 g24458 +0- 1 +-0 1 +.names g24458 II33539 +0 1 +.names II33539 g25711 +0 1 +.names g23955 g3494 g24459 +0- 1 +-0 1 +.names g24459 II33542 +0 1 +.names II33542 g25714 +0 1 +.names g23955 g6945 g25045 +0- 1 +-0 1 +.names g25045 II33545 +0 1 +.names II33545 g25717 +0 1 +.names g23955 g6751 g25064 +0- 1 +-0 1 +.names g25064 II33548 +0 1 +.names II33548 g25720 +0 1 +.names g15410 g23830 g24510 +00 1 +.names g24510 II33551 +0 1 +.names II33551 g25723 +0 1 +.names g15411 g23831 g24511 +00 1 +.names g24511 II33554 +0 1 +.names II33554 g25724 +0 1 +.names g23748 g3618 g24460 +0- 1 +-0 1 +.names g24460 II33558 +0 1 +.names II33558 g25729 +0 1 +.names g23748 g7015 g25047 +0- 1 +-0 1 +.names g25047 II33561 +0 1 +.names II33561 g25732 +0 1 +.names g23984 g3650 g24461 +0- 1 +-0 1 +.names g24461 II33564 +0 1 +.names II33564 g25735 +0 1 +.names g23984 g7195 g25049 +0- 1 +-0 1 +.names g25049 II33567 +0 1 +.names II33567 g25738 +0 1 +.names g23984 g7053 g25065 +0- 1 +-0 1 +.names g25065 II33570 +0 1 +.names II33570 g25741 +0 1 +.names g15425 g23843 g24513 +00 1 +.names g24513 II33573 +0 1 +.names II33573 g25744 +0 1 +.names g23803 g3774 g24462 +0- 1 +-0 1 +.names g24462 II33577 +0 1 +.names II33577 g25746 +0 1 +.names g23803 g7265 g25051 +0- 1 +-0 1 +.names g25051 II33580 +0 1 +.names II33580 g25749 +0 1 +.names g23803 g5556 g25068 +0- 1 +-0 1 +.names g25068 II33583 +0 1 +.names II33583 g25752 +0 1 +.names g24014 g7391 g25052 +0- 1 +-0 1 +.names g25052 II33586 +0 1 +.names II33586 g25755 +0 1 +.names g24014 g7303 g25069 +0- 1 +-0 1 +.names g25069 II33589 +0 1 +.names II33589 g25758 +0 1 +.names g23427 g22777 g24445 +00 1 +.names g24445 II33593 +0 1 +.names II33593 g25762 +0 1 +.names g23433 g22907 g24446 +00 1 +.names g24446 II33596 +0 1 +.names II33596 g25763 +0 1 +.names g23923 g3338 g24463 +0- 1 +-0 1 +.names g24463 II33600 +0 1 +.names II33600 g25767 +0 1 +.names g15459 g23855 g24519 +00 1 +.names g24519 II33603 +0 1 +.names II33603 g25770 +0 1 +.names g24607 g25771 +0 1 +.names g23955 g3494 g24464 +0- 1 +-0 1 +.names g24464 II33608 +0 1 +.names II33608 g25773 +0 1 +.names g23955 g6945 g25055 +0- 1 +-0 1 +.names g25055 II33611 +0 1 +.names II33611 g25776 +0 1 +.names g15475 g23859 g24521 +00 1 +.names g24521 II33614 +0 1 +.names II33614 g25779 +0 1 +.names g15476 g23860 g24522 +00 1 +.names g24522 II33617 +0 1 +.names II33617 g25780 +0 1 +.names g23748 g3618 g24465 +0- 1 +-0 1 +.names g24465 II33621 +0 1 +.names II33621 g25784 +0 1 +.names g23984 g3650 g24466 +0- 1 +-0 1 +.names g24466 II33624 +0 1 +.names II33624 g25787 +0 1 +.names g23984 g7195 g25059 +0- 1 +-0 1 +.names g25059 II33627 +0 1 +.names II33627 g25790 +0 1 +.names g23984 g7053 g25071 +0- 1 +-0 1 +.names g25071 II33630 +0 1 +.names II33630 g25793 +0 1 +.names g15494 g23865 g24524 +00 1 +.names g24524 II33633 +0 1 +.names II33633 g25796 +0 1 +.names g15495 g23866 g24525 +00 1 +.names g24525 II33636 +0 1 +.names II33636 g25797 +0 1 +.names g23803 g3774 g24467 +0- 1 +-0 1 +.names g24467 II33640 +0 1 +.names II33640 g25802 +0 1 +.names g23803 g7265 g25061 +0- 1 +-0 1 +.names g25061 II33643 +0 1 +.names II33643 g25805 +0 1 +.names g24014 g3806 g24468 +0- 1 +-0 1 +.names g24468 II33646 +0 1 +.names II33646 g25808 +0 1 +.names g24014 g7391 g25063 +0- 1 +-0 1 +.names g25063 II33649 +0 1 +.names II33649 g25811 +0 1 +.names g24014 g7303 g25072 +0- 1 +-0 1 +.names g25072 II33652 +0 1 +.names II33652 g25814 +0 1 +.names g15509 g23878 g24527 +00 1 +.names g24527 II33655 +0 1 +.names II33655 g25817 +0 1 +.names g23955 g3494 g24469 +0- 1 +-0 1 +.names g24469 II33659 +0 1 +.names II33659 g25821 +0 1 +.names g15545 g23889 g24532 +00 1 +.names g24532 II33662 +0 1 +.names II33662 g25824 +0 1 +.names g24619 g25825 +0 1 +.names g23984 g3650 g24470 +0- 1 +-0 1 +.names g24470 II33667 +0 1 +.names II33667 g25827 +0 1 +.names g23984 g7195 g25066 +0- 1 +-0 1 +.names g25066 II33670 +0 1 +.names II33670 g25830 +0 1 +.names g15561 g23893 g24534 +00 1 +.names g24534 II33673 +0 1 +.names II33673 g25833 +0 1 +.names g15562 g23894 g24535 +00 1 +.names g24535 II33676 +0 1 +.names II33676 g25834 +0 1 +.names g23803 g3774 g24471 +0- 1 +-0 1 +.names g24471 II33680 +0 1 +.names II33680 g25838 +0 1 +.names g24014 g3806 g24472 +0- 1 +-0 1 +.names g24472 II33683 +0 1 +.names II33683 g25841 +0 1 +.names g24014 g7391 g25070 +0- 1 +-0 1 +.names g25070 II33686 +0 1 +.names II33686 g25844 +0 1 +.names g24014 g7303 g25074 +0- 1 +-0 1 +.names g25074 II33689 +0 1 +.names II33689 g25847 +0 1 +.names g15580 g23899 g24537 +00 1 +.names g24537 II33692 +0 1 +.names II33692 g25850 +0 1 +.names g15581 g23900 g24538 +00 1 +.names g24538 II33695 +0 1 +.names II33695 g25851 +0 1 +.names g23984 g3650 g24474 +0- 1 +-0 1 +.names g24474 II33700 +0 1 +.names II33700 g25856 +0 1 +.names g15623 g23910 g24545 +00 1 +.names g24545 II33703 +0 1 +.names II33703 g25859 +0 1 +.names g24630 g25860 +0 1 +.names g24014 g3806 g24475 +0- 1 +-0 1 +.names g24475 II33708 +0 1 +.names II33708 g25862 +0 1 +.names g24014 g7391 g25073 +0- 1 +-0 1 +.names g25073 II33711 +0 1 +.names II33711 g25865 +0 1 +.names g15639 g23914 g24547 +00 1 +.names g24547 II33714 +0 1 +.names II33714 g25868 +0 1 +.names g15640 g23915 g24548 +00 1 +.names g24548 II33717 +0 1 +.names II33717 g25869 +0 1 +.names g24014 g3806 g24477 +0- 1 +-0 1 +.names g24477 II33723 +0 1 +.names II33723 g25877 +0 1 +.names g15699 g23942 g24557 +00 1 +.names g24557 II33726 +0 1 +.names II33726 g25880 +0 1 +.names g23461 g18407 g24473 +00 1 +.names g24473 II33732 +0 1 +.names II33732 g25886 +0 1 +.names g23477 g20127 g24476 +00 1 +.names g24476 II33737 +0 1 +.names II33737 g25891 +0 1 +.names g24939 g25895 +0 1 +.names II32678 II32679 g24928 +0- 1 +-0 1 +.names g24928 g25899 +0 1 +.names g24950 g25903 +0 1 +.names II32696 II32697 g24940 +0- 1 +-0 1 +.names g24940 g25907 +0 1 +.names g24962 g25911 +0 1 +.names II32709 II32710 g24951 +0- 1 +-0 1 +.names g24951 g25915 +0 1 +.names g24973 g25919 +0 1 +.names II32725 II32726 g24963 +0- 1 +-0 1 +.names g24963 g25923 +0 1 +.names g24763 g25937 +0 1 +.names g24784 g25939 +0 1 +.names g24805 g25942 +0 1 +.names g24827 g25945 +0 1 +.names g24735 g25952 +0 1 +.names g25103 II33790 +0 1 +.names II33790 g25976 +0 1 +.names g25109 II33798 +0 1 +.names II33798 g25982 +0 1 +.names g25327 II33801 +0 1 +.names g25976 II33804 +0 1 +.names g25588 II33807 +0 1 +.names g25646 II33810 +0 1 +.names g25706 II33813 +0 1 +.names g25647 II33816 +0 1 +.names g25707 II33819 +0 1 +.names g25770 II33822 +0 1 +.names g25462 II33825 +0 1 +.names g25336 II33828 +0 1 +.names g25982 II33831 +0 1 +.names g25667 II33834 +0 1 +.names g25723 II33837 +0 1 +.names g25779 II33840 +0 1 +.names g25724 II33843 +0 1 +.names g25780 II33846 +0 1 +.names g25824 II33849 +0 1 +.names g25471 II33852 +0 1 +.names g25350 II33855 +0 1 +.names g25179 II33858 +0 1 +.names g25744 II33861 +0 1 +.names g25796 II33864 +0 1 +.names g25833 II33867 +0 1 +.names g25797 II33870 +0 1 +.names g25834 II33873 +0 1 +.names g25859 II33876 +0 1 +.names g25488 II33879 +0 1 +.names g25364 II33882 +0 1 +.names g25180 II33885 +0 1 +.names g25817 II33888 +0 1 +.names g25850 II33891 +0 1 +.names g25868 II33894 +0 1 +.names g25851 II33897 +0 1 +.names g25869 II33900 +0 1 +.names g25880 II33903 +0 1 +.names g25519 II33906 +0 1 +.names g25886 II33909 +0 1 +.names g25891 II33912 +0 1 +.names g25762 II33915 +0 1 +.names g25763 II33918 +0 1 +.names g24975 g5623 g25343 +00 1 +.names g25343 II33954 +0 1 +.names II33954 g26056 +0 1 +.names g24986 g5651 g25357 +00 1 +.names g25357 II33961 +0 1 +.names II33961 g26063 +0 1 +.names g24997 g5689 g25372 +00 1 +.names g25372 II33968 +0 1 +.names II33968 g26070 +0 1 +.names g25005 g5741 g25389 +00 1 +.names g25389 II33974 +0 1 +.names II33974 g26076 +0 1 +.names g25125 g17001 g25932 +00 1 +.names g25932 II33984 +0 1 +.names II33984 g26086 +0 1 +.names g4456 g25078 g18429 g16075 g25870 +0000 1 +.names g25870 II33990 +0 1 +.names II33990 g26092 +0 1 +.names g25127 g17031 g25935 +00 1 +.names g25935 II33995 +0 1 +.names II33995 g26102 +0 1 +.names g24759 g23146 g25490 +1- 1 +-1 1 +.names g25490 II33999 +0 1 +.names g25490 II34002 +0 1 +.names II34002 g26105 +0 1 +.names g4632 g25082 g18502 g16113 g25882 +0000 1 +.names g25882 II34009 +0 1 +.names II34009 g26114 +0 1 +.names g25129 g17065 g25938 +00 1 +.names g25938 II34012 +0 1 +.names II34012 g26118 +0 1 +.names g4809 g25091 g18566 g16164 g25887 +0000 1 +.names g25887 II34017 +0 1 +.names II34017 g26121 +0 1 +.names g24428 g17100 g25940 +00 1 +.names g25940 II34020 +0 1 +.names II34020 g26125 +0 1 +.names g4985 g25099 g18616 g16223 g25892 +0000 1 +.names g25892 II34026 +0 1 +.names II34026 g26131 +0 1 +.names g24813 g23145 g25520 +1- 1 +-1 1 +.names g25520 II34029 +0 1 +.names g25520 II34032 +0 1 +.names II34032 g26136 +0 1 +.names g24843 g23143 g25566 +1- 1 +-1 1 +.names g25566 II34041 +0 1 +.names g25566 II34044 +0 1 +.names II34044 g26150 +0 1 +.names g24745 g23547 g25204 +00 1 +.names g25204 II34051 +0 1 +.names II34051 g26159 +0 1 +.names g24746 g23550 g25206 +00 1 +.names g25206 II34056 +0 1 +.names II34056 g26164 +0 1 +.names g24747 g23551 g25207 +00 1 +.names g25207 II34059 +0 1 +.names II34059 g26165 +0 1 +.names g24749 g23554 g25209 +00 1 +.names g25209 II34063 +0 1 +.names II34063 g26167 +0 1 +.names g24750 g23558 g25211 +00 1 +.names g25211 II34068 +0 1 +.names II34068 g26172 +0 1 +.names g24751 g23559 g25212 +00 1 +.names g25212 II34071 +0 1 +.names II34071 g26173 +0 1 +.names g24752 g23560 g25213 +00 1 +.names g25213 II34074 +0 1 +.names II34074 g26174 +0 1 +.names g22806 g24517 g25954 +0- 1 +-0 1 +.names g25954 II34077 +0 1 +.names II34077 g26175 +0 1 +.names g25088 g6157 g25539 +00 1 +.names g25539 II34080 +0 1 +.names II34080 g26178 +0 1 +.names g24754 g23563 g25214 +00 1 +.names g25214 II34083 +0 1 +.names II34083 g26181 +0 1 +.names g24755 g23564 g25215 +00 1 +.names g25215 II34086 +0 1 +.names II34086 g26182 +0 1 +.names g24758 g23567 g25217 +00 1 +.names g25217 II34091 +0 1 +.names II34091 g26187 +0 1 +.names g25952 g26189 +0 1 +.names g24760 g23571 g25218 +00 1 +.names g25218 II34096 +0 1 +.names II34096 g26190 +0 1 +.names g24761 g23572 g25219 +00 1 +.names g25219 II34099 +0 1 +.names II34099 g26191 +0 1 +.names g24762 g23573 g25220 +00 1 +.names g25220 II34102 +0 1 +.names II34102 g26192 +0 1 +.names g24767 g23577 g25221 +00 1 +.names g25221 II34105 +0 1 +.names II34105 g26193 +0 1 +.names g24768 g23578 g25222 +00 1 +.names g25222 II34108 +0 1 +.names II34108 g26194 +0 1 +.names g24769 g23579 g25223 +00 1 +.names g25223 II34111 +0 1 +.names II34111 g26195 +0 1 +.names g22847 g24530 g25958 +0- 1 +-0 1 +.names g25958 II34114 +0 1 +.names II34114 g26196 +0 1 +.names g25096 g6184 g25605 +00 1 +.names g25605 II34118 +0 1 +.names II34118 g26202 +0 1 +.names g24772 g23582 g25224 +00 1 +.names g25224 II34121 +0 1 +.names II34121 g26205 +0 1 +.names g24773 g23583 g25225 +00 1 +.names g25225 II34124 +0 1 +.names II34124 g26206 +0 1 +.names g24775 g23586 g25227 +00 1 +.names g25227 II34128 +0 1 +.names II34128 g26208 +0 1 +.names g25296 g26209 +0 1 +.names g24776 g23590 g25228 +00 1 +.names g25228 II34132 +0 1 +.names II34132 g26210 +0 1 +.names g24777 g23591 g25229 +00 1 +.names g25229 II34135 +0 1 +.names II34135 g26211 +0 1 +.names g24779 g23598 g25230 +00 1 +.names g25230 II34140 +0 1 +.names II34140 g26214 +0 1 +.names g24780 g23599 g25231 +00 1 +.names g25231 II34143 +0 1 +.names II34143 g26215 +0 1 +.names g24781 g23600 g25232 +00 1 +.names g25232 II34146 +0 1 +.names II34146 g26216 +0 1 +.names g24788 g23604 g25233 +00 1 +.names g25233 II34150 +0 1 +.names II34150 g26220 +0 1 +.names g24789 g23605 g25234 +00 1 +.names g25234 II34153 +0 1 +.names II34153 g26221 +0 1 +.names g24790 g23606 g25235 +00 1 +.names g25235 II34156 +0 1 +.names II34156 g26222 +0 1 +.names g22882 g24543 g25964 +0- 1 +-0 1 +.names g25964 II34159 +0 1 +.names II34159 g26223 +0 1 +.names g25106 g6216 g25684 +00 1 +.names g25684 II34162 +0 1 +.names II34162 g26226 +0 1 +.names g24792 g23609 g25236 +00 1 +.names g25236 II34165 +0 1 +.names II34165 g26229 +0 1 +.names g24793 g23610 g25237 +00 1 +.names g25237 II34168 +0 1 +.names II34168 g26230 +0 1 +.names g24796 g23615 g25239 +00 1 +.names g25239 II34172 +0 1 +.names II34172 g26232 +0 1 +.names g25306 g26237 +0 1 +.names g24798 g23622 g25240 +00 1 +.names g25240 II34180 +0 1 +.names II34180 g26238 +0 1 +.names g24799 g23623 g25241 +00 1 +.names g25241 II34183 +0 1 +.names II34183 g26239 +0 1 +.names g24802 g23630 g25242 +00 1 +.names g25242 II34189 +0 1 +.names II34189 g26245 +0 1 +.names g24803 g23631 g25243 +00 1 +.names g25243 II34192 +0 1 +.names II34192 g26246 +0 1 +.names g24804 g23632 g25244 +00 1 +.names g25244 II34195 +0 1 +.names II34195 g26247 +0 1 +.names g24809 g23636 g25245 +00 1 +.names g25245 II34198 +0 1 +.names II34198 g26248 +0 1 +.names g24810 g23637 g25246 +00 1 +.names g25246 II34201 +0 1 +.names II34201 g26249 +0 1 +.names g24811 g23638 g25247 +00 1 +.names g25247 II34204 +0 1 +.names II34204 g26250 +0 1 +.names g22917 g24555 g25969 +0- 1 +-0 1 +.names g25969 II34207 +0 1 +.names II34207 g26251 +0 1 +.names g25112 g6305 g25761 +00 1 +.names g25761 II34210 +0 1 +.names II34210 g26254 +0 1 +.names g24818 g23664 g25248 +00 1 +.names g25248 II34220 +0 1 +.names II34220 g26264 +0 1 +.names g25315 g26275 +0 1 +.names g24821 g23671 g25249 +00 1 +.names g25249 II34230 +0 1 +.names II34230 g26276 +0 1 +.names g24822 g23672 g25250 +00 1 +.names g25250 II34233 +0 1 +.names II34233 g26277 +0 1 +.names g24824 g23679 g25251 +00 1 +.names g25251 II34238 +0 1 +.names II34238 g26280 +0 1 +.names g24825 g23680 g25252 +00 1 +.names g25252 II34241 +0 1 +.names II34241 g26281 +0 1 +.names g24826 g23681 g25253 +00 1 +.names g25253 II34244 +0 1 +.names II34244 g26282 +0 1 +.names g24492 g10024 g25185 +00 1 +.names g25185 II34254 +0 1 +.names II34254 g26294 +0 1 +.names g24838 g23714 g25255 +00 1 +.names g25255 II34266 +0 1 +.names II34266 g26308 +0 1 +.names g25324 g26313 +0 1 +.names g24840 g23721 g25256 +00 1 +.names g25256 II34274 +0 1 +.names II34274 g26314 +0 1 +.names g24841 g23722 g25257 +00 1 +.names g25257 II34277 +0 1 +.names II34277 g26315 +0 1 +.names g24502 g10133 g25189 +00 1 +.names g25189 II34296 +0 1 +.names II34296 g26341 +0 1 +.names g24853 g23768 g25259 +00 1 +.names g25259 II34306 +0 1 +.names II34306 g26349 +0 1 +.names g24878 g23852 g25265 +00 1 +.names g25265 II34313 +0 1 +.names II34313 g26354 +0 1 +.names g24516 g22777 g25191 +00 1 +.names g25191 II34316 +0 1 +.names II34316 g26355 +0 1 +.names g24965 g5438 g25928 +0- 1 +-0 1 +.names g25928 II34321 +0 1 +.names II34321 g26358 +0 1 +.names g24858 g17737 g25260 +00 1 +.names g25260 II34327 +0 1 +.names II34327 g26364 +0 1 +.names g24514 g10238 g25194 +00 1 +.names g25194 II34343 +0 1 +.names II34343 g26385 +0 1 +.names g24965 g6448 g25927 +0- 1 +-0 1 +.names g25927 II34353 +0 1 +.names II34353 g26393 +0 1 +.names g24869 g17824 g25262 +00 1 +.names g25262 II34358 +0 1 +.names II34358 g26398 +0 1 +.names g24978 g5473 g25930 +0- 1 +-0 1 +.names g25930 II34363 +0 1 +.names II34363 g26401 +0 1 +.names g24874 g17838 g25263 +00 1 +.names g25263 II34369 +0 1 +.names II34369 g26407 +0 1 +.names g24528 g10340 g25197 +00 1 +.names g25197 II34385 +0 1 +.names II34385 g26428 +0 1 +.names g24965 g3306 g25200 +0- 1 +-0 1 +.names g25200 II34388 +0 1 +.names II34388 g26429 +0 1 +.names g24881 g17912 g25266 +00 1 +.names g25266 II34392 +0 1 +.names II34392 g26433 +0 1 +.names g24978 g6713 g25929 +0- 1 +-0 1 +.names g25929 II34395 +0 1 +.names II34395 g26434 +0 1 +.names g24884 g17936 g25267 +00 1 +.names g25267 II34400 +0 1 +.names II34400 g26439 +0 1 +.names g24989 g5512 g25933 +0- 1 +-0 1 +.names g25933 II34405 +0 1 +.names II34405 g26442 +0 1 +.names g24888 g17950 g25268 +00 1 +.names g25268 II34411 +0 1 +.names II34411 g26448 +0 1 +.names g24978 g3462 g25203 +0- 1 +-0 1 +.names g25203 II34421 +0 1 +.names II34421 g26461 +0 1 +.names g24898 g18023 g25270 +00 1 +.names g25270 II34425 +0 1 +.names II34425 g26465 +0 1 +.names g24989 g7015 g25931 +0- 1 +-0 1 +.names g25931 II34428 +0 1 +.names II34428 g26466 +0 1 +.names g24901 g18047 g25271 +00 1 +.names g25271 II34433 +0 1 +.names II34433 g26471 +0 1 +.names g25000 g5556 g25936 +0- 1 +-0 1 +.names g25936 II34438 +0 1 +.names II34438 g26474 +0 1 +.names g24905 g18061 g25272 +00 1 +.names g25272 II34444 +0 1 +.names II34444 g26480 +0 1 +.names g25076 g21615 g25764 +00 1 +.names g25764 g26481 +0 1 +.names g24989 g3618 g25205 +0- 1 +-0 1 +.names g25205 II34449 +0 1 +.names II34449 g26485 +0 1 +.names g24921 g18140 g25279 +00 1 +.names g25279 II34453 +0 1 +.names II34453 g26489 +0 1 +.names g25000 g7265 g25934 +0- 1 +-0 1 +.names g25934 II34456 +0 1 +.names II34456 g26490 +0 1 +.names g24924 g18164 g25280 +00 1 +.names g25280 II34461 +0 1 +.names II34461 g26495 +0 1 +.names g24558 g20127 g25199 +00 1 +.names g25199 II34464 +0 1 +.names II34464 g26496 +0 1 +.names g25077 g21643 g25818 +00 1 +.names g25818 g26497 +0 1 +.names g25000 g3774 g25210 +0- 1 +-0 1 +.names g25210 II34469 +0 1 +.names II34469 g26501 +0 1 +.names g24938 g18256 g25288 +00 1 +.names g25288 II34473 +0 1 +.names II34473 g26505 +0 1 +.names g24575 g18407 g25201 +00 1 +.names g25201 II34476 +0 1 +.names II34476 g26506 +0 1 +.names g24566 g22907 g25202 +00 1 +.names g25202 II34479 +0 1 +.names II34479 g26507 +0 1 +.names g21211 g14442 g10694 g24590 g25312 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g25312 g26508 +0 1 +.names g25081 g21674 g25853 +00 1 +.names g25853 g26512 +0 1 +.names g21219 g14529 g10714 g24595 g25320 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g25320 g26516 +0 1 +.names g25085 g21703 g25874 +00 1 +.names g25874 g26520 +0 1 +.names g21230 g14584 g10735 g24603 g25331 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g25331 g26521 +0 1 +.names g21235 g14618 g10754 g24610 g25340 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g25340 g26525 +0 1 +.names g25454 g26533 +0 1 +.names g25458 g26538 +0 1 +.names g25463 g26539 +0 1 +.names g25467 g26540 +0 1 +.names g25472 g26542 +0 1 +.names g25476 g26543 +0 1 +.names g25479 g26544 +0 1 +.names g25484 g26546 +0 1 +.names g16018 g25086 g25450 +00 1 +.names g25450 II34505 +0 1 +.names II34505 g26548 +0 1 +.names g25421 g26549 +0 1 +.names g25493 g26550 +0 1 +.names g25496 g26551 +0 1 +.names g25499 g26552 +0 1 +.names g25502 g26554 +0 1 +.names g25507 g26555 +0 1 +.names g25510 g26556 +0 1 +.names g25515 g26558 +0 1 +.names g25524 g26561 +0 1 +.names g25527 g26562 +0 1 +.names g25530 g26563 +0 1 +.names g25533 g26564 +0 1 +.names g25536 g26565 +0 1 +.names g25540 g26566 +0 1 +.names g25543 g26567 +0 1 +.names g25546 g26568 +0 1 +.names g25549 g26570 +0 1 +.names g25554 g26571 +0 1 +.names g25557 g26572 +0 1 +.names g25562 g26574 +0 1 +.names g16048 g25102 g25451 +00 1 +.names g25451 II34535 +0 1 +.names II34535 g26576 +0 1 +.names g25436 g26577 +0 1 +.names g25573 g26578 +0 1 +.names g25576 g26579 +0 1 +.names g25579 g26580 +0 1 +.names g25582 g26581 +0 1 +.names g25585 g26582 +0 1 +.names g25590 g26584 +0 1 +.names g25593 g26585 +0 1 +.names g25596 g26586 +0 1 +.names g25599 g26587 +0 1 +.names g25602 g26588 +0 1 +.names g25606 g26589 +0 1 +.names g25609 g26590 +0 1 +.names g25612 g26591 +0 1 +.names g25615 g26593 +0 1 +.names g25620 g26594 +0 1 +.names g25623 g26595 +0 1 +.names g25443 g26597 +0 1 +.names g25634 g26598 +0 1 +.names g25637 g26599 +0 1 +.names g25640 g26600 +0 1 +.names g25643 g26601 +0 1 +.names g25652 g26602 +0 1 +.names g25655 g26603 +0 1 +.names g25658 g26604 +0 1 +.names g25661 g26605 +0 1 +.names g25664 g26606 +0 1 +.names g25669 g26608 +0 1 +.names g25672 g26609 +0 1 +.names g25675 g26610 +0 1 +.names g25678 g26611 +0 1 +.names g25681 g26612 +0 1 +.names g25685 g26613 +0 1 +.names g25688 g26614 +0 1 +.names g25691 g26615 +0 1 +.names g25694 g26617 +0 1 +.names g16101 g25117 g25452 +00 1 +.names g25452 II34579 +0 1 +.names II34579 g26618 +0 1 +.names g25700 g26619 +0 1 +.names g25703 g26620 +0 1 +.names g25711 g26621 +0 1 +.names g25714 g26622 +0 1 +.names g25717 g26623 +0 1 +.names g25720 g26624 +0 1 +.names g25729 g26625 +0 1 +.names g25732 g26626 +0 1 +.names g25735 g26627 +0 1 +.names g25738 g26628 +0 1 +.names g25741 g26629 +0 1 +.names g25746 g26631 +0 1 +.names g25749 g26632 +0 1 +.names g25752 g26633 +0 1 +.names g25755 g26634 +0 1 +.names g25758 g26635 +0 1 +.names g25767 g26636 +0 1 +.names g25773 g26637 +0 1 +.names g25776 g26638 +0 1 +.names g25784 g26639 +0 1 +.names g25787 g26640 +0 1 +.names g25790 g26641 +0 1 +.names g25793 g26642 +0 1 +.names g25802 g26643 +0 1 +.names g25805 g26644 +0 1 +.names g25808 g26645 +0 1 +.names g25811 g26646 +0 1 +.names g25814 g26647 +0 1 +.names g25821 g26648 +0 1 +.names g25827 g26649 +0 1 +.names g25830 g26650 +0 1 +.names g25838 g26651 +0 1 +.names g25841 g26652 +0 1 +.names g25844 g26653 +0 1 +.names g25847 g26654 +0 1 +.names g25856 g26656 +0 1 +.names g25862 g26657 +0 1 +.names g25865 g26658 +0 1 +.names g25877 g26662 +0 1 +.names g26086 II34641 +0 1 +.names g26159 II34644 +0 1 +.names g26164 II34647 +0 1 +.names g26172 II34650 +0 1 +.names g26165 II34653 +0 1 +.names g26173 II34656 +0 1 +.names g26190 II34659 +0 1 +.names g26174 II34662 +0 1 +.names g26191 II34665 +0 1 +.names g26210 II34668 +0 1 +.names g26192 II34671 +0 1 +.names g26211 II34674 +0 1 +.names g26232 II34677 +0 1 +.names g26294 II34680 +0 1 +.names g26364 II34683 +0 1 +.names g26398 II34686 +0 1 +.names g26433 II34689 +0 1 +.names g26102 II34692 +0 1 +.names g26167 II34695 +0 1 +.names g26181 II34698 +0 1 +.names g26193 II34701 +0 1 +.names g26182 II34704 +0 1 +.names g26194 II34707 +0 1 +.names g26214 II34710 +0 1 +.names g26195 II34713 +0 1 +.names g26215 II34716 +0 1 +.names g26238 II34719 +0 1 +.names g26216 II34722 +0 1 +.names g26239 II34725 +0 1 +.names g26264 II34728 +0 1 +.names g26341 II34731 +0 1 +.names g26407 II34734 +0 1 +.names g26439 II34737 +0 1 +.names g26465 II34740 +0 1 +.names g26118 II34743 +0 1 +.names g26187 II34746 +0 1 +.names g26205 II34749 +0 1 +.names g26220 II34752 +0 1 +.names g26206 II34755 +0 1 +.names g26221 II34758 +0 1 +.names g26245 II34761 +0 1 +.names g26222 II34764 +0 1 +.names g26246 II34767 +0 1 +.names g26276 II34770 +0 1 +.names g26247 II34773 +0 1 +.names g26277 II34776 +0 1 +.names g26308 II34779 +0 1 +.names g26385 II34782 +0 1 +.names g26448 II34785 +0 1 +.names g26471 II34788 +0 1 +.names g26489 II34791 +0 1 +.names g26125 II34794 +0 1 +.names g26208 II34797 +0 1 +.names g26229 II34800 +0 1 +.names g26248 II34803 +0 1 +.names g26230 II34806 +0 1 +.names g26249 II34809 +0 1 +.names g26280 II34812 +0 1 +.names g26250 II34815 +0 1 +.names g26281 II34818 +0 1 +.names g26314 II34821 +0 1 +.names g26282 II34824 +0 1 +.names g26315 II34827 +0 1 +.names g26349 II34830 +0 1 +.names g26428 II34833 +0 1 +.names g26480 II34836 +0 1 +.names g26495 II34839 +0 1 +.names g26505 II34842 +0 1 +.names g26496 II34845 +0 1 +.names g26506 II34848 +0 1 +.names g26354 II34851 +0 1 +.names g26507 II34854 +0 1 +.names g26355 II34857 +0 1 +.names g26548 II34860 +0 1 +.names g26576 II34863 +0 1 +.names g26618 II34866 +0 1 +.names g25963 g13320 g26217 +00 1 +.names g26217 II34872 +0 1 +.names II34872 g26757 +0 1 +.names g25968 g13340 g26240 +00 1 +.names g26240 II34879 +0 1 +.names II34879 g26762 +0 1 +.names g25977 g13385 g26295 +00 1 +.names g26295 II34901 +0 1 +.names II34901 g26782 +0 1 +.names g25972 g13360 g26265 +00 1 +.names g26265 II34909 +0 1 +.names II34909 g26788 +0 1 +.names g26240 II34916 +0 1 +.names II34916 g26793 +0 1 +.names g26217 II34921 +0 1 +.names II34921 g26796 +0 1 +.names g25321 g8869 g26534 +00 1 +.names g26534 II34946 +0 1 +.names II34946 g26819 +0 1 +.names g13755 g25269 g26541 +00 1 +.names g26541 II34957 +0 1 +.names II34957 g26828 +0 1 +.names g13790 g25277 g26545 +00 1 +.names g26545 II34961 +0 1 +.names II34961 g26830 +0 1 +.names g13796 g25278 g26547 +00 1 +.names g26547 II34964 +0 1 +.names II34964 g26831 +0 1 +.names g13816 g25282 g26553 +00 1 +.names g26553 II34967 +0 1 +.names II34967 g26832 +0 1 +.names g13818 g25286 g26557 +00 1 +.names g26557 II34971 +0 1 +.names II34971 g26834 +0 1 +.names g25953 g16212 g26168 +00 1 +.names g26168 II34974 +0 1 +.names II34974 g26835 +0 1 +.names g13824 g25287 g26559 +00 1 +.names g26559 II34977 +0 1 +.names II34977 g26836 +0 1 +.names g25343 g65 g26458 +0- 1 +-0 1 +.names g26458 II34980 +0 1 +.names II34980 g26837 +0 1 +.names g13837 g25290 g26569 +00 1 +.names g26569 II34983 +0 1 +.names II34983 g26840 +0 1 +.names g25951 g16162 g26160 +00 1 +.names g26160 II34986 +0 1 +.names II34986 g26841 +0 1 +.names g13839 g25294 g26573 +00 1 +.names g26573 II34990 +0 1 +.names II34990 g26843 +0 1 +.names g13845 g25295 g26575 +00 1 +.names g26575 II34993 +0 1 +.names II34993 g26844 +0 1 +.names g25357 g753 g26482 +0- 1 +-0 1 +.names g26482 II34997 +0 1 +.names II34997 g26846 +0 1 +.names g25981 g13481 g26336 +00 1 +.names g26336 II35000 +0 1 +.names II35000 g26849 +0 1 +.names g13851 g25300 g26592 +00 1 +.names g26592 II35003 +0 1 +.names II35003 g26850 +0 1 +.names g13853 g25304 g26596 +00 1 +.names g26596 II35007 +0 1 +.names II35007 g26852 +0 1 +.names g25978 g16451 g26304 +00 1 +.names g26304 II35011 +0 1 +.names II35011 g26854 +0 1 +.names g25372 g1439 g26498 +0- 1 +-0 1 +.names g26498 II35014 +0 1 +.names II35014 g26855 +0 1 +.names g13860 g25310 g26616 +00 1 +.names g26616 II35017 +0 1 +.names II35017 g26858 +0 1 +.names g25389 g2133 g26513 +0- 1 +-0 1 +.names g26513 II35028 +0 1 +.names II35028 g26861 +0 1 +.names g25962 g17001 g26529 +00 1 +.names g26529 II35031 +0 1 +.names II35031 g26864 +0 1 +.names g25967 g17031 g26530 +00 1 +.names g26530 II35049 +0 1 +.names II35049 g26868 +0 1 +.names g25328 g17084 g26655 +00 1 +.names g26655 II35053 +0 1 +.names II35053 g26872 +0 1 +.names g25974 g17065 g26531 +00 1 +.names g26531 II35064 +0 1 +.names II35064 g26875 +0 1 +.names g25334 g17116 g26659 +00 1 +.names g26659 II35067 +0 1 +.names II35067 g26876 +0 1 +.names g25337 g17122 g26661 +00 1 +.names g26661 II35072 +0 1 +.names II35072 g26881 +0 1 +.names g25979 g17100 g26532 +00 1 +.names g26532 II35076 +0 1 +.names II35076 g26883 +0 1 +.names g25346 g17138 g26664 +00 1 +.names g26664 II35079 +0 1 +.names II35079 g26884 +0 1 +.names g25348 g17143 g26665 +00 1 +.names g26665 II35083 +0 1 +.names II35083 g26886 +0 1 +.names g25351 g17149 g26667 +00 1 +.names g26667 II35087 +0 1 +.names II35087 g26890 +0 1 +.names g25360 g17161 g26669 +00 1 +.names g26669 II35092 +0 1 +.names II35092 g26895 +0 1 +.names g25362 g17166 g26670 +00 1 +.names g26670 II35095 +0 1 +.names II35095 g26896 +0 1 +.names g25365 g17172 g26672 +00 1 +.names g26672 II35099 +0 1 +.names II35099 g26900 +0 1 +.names g25375 g17176 g26675 +00 1 +.names g26675 II35106 +0 1 +.names II35106 g26909 +0 1 +.names g25377 g17181 g26676 +00 1 +.names g26676 II35109 +0 1 +.names II35109 g26910 +0 1 +.names g25392 g17193 g26025 +00 1 +.names g26025 II35116 +0 1 +.names II35116 g26921 +0 1 +.names g25954 g24486 g26283 +00 1 +.names g26283 g26922 +0 1 +.names g25958 g24493 g26327 +00 1 +.names g26327 g26935 +0 1 +.names g25964 g24503 g26374 +00 1 +.names g26374 g26944 +0 1 +.names g25969 g24515 g26417 +00 1 +.names g26417 g26950 +0 1 +.names g25208 g10024 g26660 +00 1 +.names g26660 II35136 +0 1 +.names II35136 g26953 +0 1 +.names g26549 g26954 +0 1 +.names g25216 g10133 g26666 +00 1 +.names g26666 II35141 +0 1 +.names II35141 g26956 +0 1 +.names g26577 g26957 +0 1 +.names g25226 g10238 g26671 +00 1 +.names g26671 II35146 +0 1 +.names II35146 g26959 +0 1 +.names g26597 g26960 +0 1 +.names g25238 g10340 g26677 +00 1 +.names g26677 II35153 +0 1 +.names II35153 g26964 +0 1 +.names g25973 g16423 g26272 +00 1 +.names g26272 II35172 +0 1 +.names II35172 g26983 +0 1 +.names g26056 g26987 +0 1 +.names g26063 g27010 +0 1 +.names g26070 g27036 +0 1 +.names g26076 g27064 +0 1 +.names g25628 g24906 g26048 +00 1 +.names g26048 II35254 +0 1 +.names II35254 g27075 +0 1 +.names g25273 g22777 g26031 +00 1 +.names g26031 II35283 +0 1 +.names II35283 g27102 +0 1 +.names g25961 g13291 g26199 +00 1 +.names g26199 II35297 +0 1 +.names II35297 g27114 +0 1 +.names g25311 g18407 g26037 +00 1 +.names g26037 II35301 +0 1 +.names II35301 g27116 +0 1 +.names g26534 II35313 +0 1 +.names II35313 g27126 +0 1 +.names g25957 g13270 g26183 +00 1 +.names g26183 II35319 +0 1 +.names II35319 g27132 +0 1 +.names g26105 g27133 +0 1 +.names g26175 g27134 +0 1 +.names g26178 g27135 +0 1 +.names g26196 g27136 +0 1 +.names g26202 g27137 +0 1 +.names g26223 g27138 +0 1 +.names g26226 g27139 +0 1 +.names g26136 g27140 +0 1 +.names g26251 g27141 +0 1 +.names g26254 g27142 +0 1 +.names g26150 g27143 +0 1 +.names g23644 g25354 g26106 +0- 1 +-0 1 +.names g26106 II35334 +0 1 +.names II35334 g27145 +0 1 +.names g26358 g27146 +0 1 +.names g26393 g27148 +0 1 +.names g23694 g25369 g26120 +0- 1 +-0 1 +.names g26120 II35341 +0 1 +.names II35341 g27150 +0 1 +.names g26401 g27151 +0 1 +.names g26429 g27153 +0 1 +.names g26265 II35347 +0 1 +.names II35347 g27154 +0 1 +.names g26434 g27155 +0 1 +.names g26272 II35351 +0 1 +.names II35351 g27156 +0 1 +.names g23748 g25386 g26130 +0- 1 +-0 1 +.names g26130 II35355 +0 1 +.names II35355 g27158 +0 1 +.names g26442 g27159 +0 1 +.names g26295 II35360 +0 1 +.names II35360 g27161 +0 1 +.names g26461 g27162 +0 1 +.names g26304 II35364 +0 1 +.names II35364 g27163 +0 1 +.names g26466 g27164 +0 1 +.names g23803 g25402 g26144 +0- 1 +-0 1 +.names g26144 II35369 +0 1 +.names II35369 g27166 +0 1 +.names g26474 g27167 +0 1 +.names g26189 II35373 +0 1 +.names II35373 g27168 +0 1 +.names g26336 II35376 +0 1 +.names II35376 g27171 +0 1 +.names g26485 g27172 +0 1 +.names g26490 g27173 +0 1 +.names g26160 II35383 +0 1 +.names II35383 g27176 +0 1 +.names g26501 g27177 +0 1 +.names g26168 II35389 +0 1 +.names II35389 g27180 +0 1 +.names g26183 II35394 +0 1 +.names II35394 g27183 +0 1 +.names g26199 II35399 +0 1 +.names II35399 g27186 +0 1 +.names g26864 II35404 +0 1 +.names g27145 II35407 +0 1 +.names g26872 II35410 +0 1 +.names g26876 II35413 +0 1 +.names g26884 II35416 +0 1 +.names g26828 II35419 +0 1 +.names g26830 II35422 +0 1 +.names g26832 II35425 +0 1 +.names g26953 II35428 +0 1 +.names g26868 II35431 +0 1 +.names g27150 II35434 +0 1 +.names g27183 II35437 +0 1 +.names g27186 II35440 +0 1 +.names g26757 II35443 +0 1 +.names g26762 II35446 +0 1 +.names g27154 II35449 +0 1 +.names g27161 II35452 +0 1 +.names g26881 II35455 +0 1 +.names g26886 II35458 +0 1 +.names g26895 II35461 +0 1 +.names g26831 II35464 +0 1 +.names g26834 II35467 +0 1 +.names g26840 II35470 +0 1 +.names g27156 II35473 +0 1 +.names g27163 II35476 +0 1 +.names g27171 II35479 +0 1 +.names g27176 II35482 +0 1 +.names g27180 II35485 +0 1 +.names g26819 II35488 +0 1 +.names g26956 II35491 +0 1 +.names g26875 II35494 +0 1 +.names g27158 II35497 +0 1 +.names g26890 II35500 +0 1 +.names g26896 II35503 +0 1 +.names g26909 II35506 +0 1 +.names g26836 II35509 +0 1 +.names g26843 II35512 +0 1 +.names g26850 II35515 +0 1 +.names g26959 II35518 +0 1 +.names g26883 II35521 +0 1 +.names g27166 II35524 +0 1 +.names g26900 II35527 +0 1 +.names g26910 II35530 +0 1 +.names g26921 II35533 +0 1 +.names g26844 II35536 +0 1 +.names g26852 II35539 +0 1 +.names g26858 II35542 +0 1 +.names g26964 II35545 +0 1 +.names g27116 II35548 +0 1 +.names g27075 II35551 +0 1 +.names g27102 II35554 +0 1 +.names g27126 g27349 +0 1 +.names g26560 g17001 g27120 +00 1 +.names g27120 II35667 +0 1 +.names II35667 g27353 +0 1 +.names g26583 g17031 g27123 +00 1 +.names g27123 II35673 +0 1 +.names II35673 g27357 +0 1 +.names g26607 g17065 g27129 +00 1 +.names g27129 II35678 +0 1 +.names II35678 g27360 +0 1 +.names g26458 g5642 g26869 +00 1 +.names g26869 II35681 +0 1 +.names II35681 g27361 +0 1 +.names g26630 g17100 g27131 +00 1 +.names g27131 II35686 +0 1 +.names II35686 g27366 +0 1 +.names g26482 g5680 g26878 +00 1 +.names g26878 II35689 +0 1 +.names II35689 g27367 +0 1 +.names g26498 g5732 g26887 +00 1 +.names g26887 II35695 +0 1 +.names II35695 g27373 +0 1 +.names g26513 g5790 g26897 +00 1 +.names g26897 II35698 +0 1 +.names II35698 g27376 +0 1 +.names g26157 g23147 g26974 +1- 1 +-1 1 +.names g26974 II35708 +0 1 +.names g26974 II35711 +0 1 +.names II35711 g27381 +0 1 +.names g27133 g27383 +0 1 +.names g27140 g27384 +0 1 +.names g27168 II35723 +0 1 +.names II35723 g27385 +0 1 +.names g27143 g27386 +0 1 +.names g25631 g26283 g25569 g26902 +0-- 1 +-0- 1 +--0 1 +.names g26902 II35727 +0 1 +.names II35727 g27387 +0 1 +.names g25699 g26283 g25569 g25631 g26892 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g26892 II35731 +0 1 +.names II35731 g27391 +0 1 +.names g25708 g26327 g25648 g26915 +0-- 1 +-0- 1 +--0 1 +.names g26915 II35737 +0 1 +.names II35737 g27397 +0 1 +.names g26320 g5438 g27118 +0- 1 +-0 1 +.names g27118 II35741 +0 1 +.names II35741 g27401 +0 1 +.names g25772 g26327 g25648 g25708 g26906 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g26906 II35744 +0 1 +.names II35744 g27404 +0 1 +.names g25781 g26374 g25725 g26928 +0-- 1 +-0- 1 +--0 1 +.names g26928 II35750 +0 1 +.names II35750 g27410 +0 1 +.names g26320 g6448 g27117 +0- 1 +-0 1 +.names g27117 II35756 +0 1 +.names II35756 g27416 +0 1 +.names g26367 g5473 g27121 +0- 1 +-0 1 +.names g27121 II35759 +0 1 +.names II35759 g27419 +0 1 +.names g25826 g26374 g25725 g25781 g26918 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g26918 II35762 +0 1 +.names II35762 g27422 +0 1 +.names g25835 g26417 g25798 g26941 +0-- 1 +-0- 1 +--0 1 +.names g26941 II35768 +0 1 +.names II35768 g27428 +0 1 +.names g26320 g3306 g26772 +0- 1 +-0 1 +.names g26772 II35772 +0 1 +.names II35772 g27432 +0 1 +.names g26367 g6713 g27119 +0- 1 +-0 1 +.names g27119 II35777 +0 1 +.names II35777 g27437 +0 1 +.names g26410 g5512 g27124 +0- 1 +-0 1 +.names g27124 II35780 +0 1 +.names II35780 g27440 +0 1 +.names g25861 g26417 g25798 g25835 g26931 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g26931 II35783 +0 1 +.names II35783 g27443 +0 1 +.names g26837 g27449 +0 1 +.names g26367 g3462 g26779 +0- 1 +-0 1 +.names g26779 II35791 +0 1 +.names II35791 g27451 +0 1 +.names g26410 g7015 g27122 +0- 1 +-0 1 +.names g27122 II35796 +0 1 +.names II35796 g27456 +0 1 +.names g26451 g5556 g27130 +0- 1 +-0 1 +.names g27130 II35799 +0 1 +.names II35799 g27459 +0 1 +.names g15105 g26213 g26803 +00 1 +.names g26803 II35803 +0 1 +.names II35803 g27463 +0 1 +.names g26846 g27465 +0 1 +.names g26410 g3618 g26785 +0- 1 +-0 1 +.names g26785 II35809 +0 1 +.names II35809 g27467 +0 1 +.names g26451 g7265 g27125 +0- 1 +-0 1 +.names g27125 II35814 +0 1 +.names II35814 g27472 +0 1 +.names g26922 II35817 +0 1 +.names II35817 g27475 +0 1 +.names g15172 g26235 g26804 +00 1 +.names g26804 II35821 +0 1 +.names II35821 g27479 +0 1 +.names g15173 g26236 g26805 +00 1 +.names g26805 II35824 +0 1 +.names II35824 g27480 +0 1 +.names g15197 g26244 g26806 +00 1 +.names g26806 II35829 +0 1 +.names II35829 g27483 +0 1 +.names g26855 g27484 +0 1 +.names g26451 g3774 g26792 +0- 1 +-0 1 +.names g26792 II35834 +0 1 +.names II35834 g27486 +0 1 +.names g25569 g26283 g26911 +0- 1 +-0 1 +.names g26911 II35837 +0 1 +.names II35837 g27489 +0 1 +.names g15245 g26261 g26807 +00 1 +.names g26807 II35841 +0 1 +.names II35841 g27493 +0 1 +.names g15246 g26262 g26808 +00 1 +.names g26808 II35844 +0 1 +.names II35844 g27494 +0 1 +.names g26042 g10024 g26776 +00 1 +.names g26776 II35849 +0 1 +.names II35849 g27497 +0 1 +.names g26935 II35852 +0 1 +.names II35852 g27498 +0 1 +.names g15258 g26270 g26809 +00 1 +.names g26809 II35856 +0 1 +.names II35856 g27502 +0 1 +.names g15259 g26271 g26810 +00 1 +.names g26810 II35859 +0 1 +.names II35859 g27503 +0 1 +.names g15283 g26279 g26811 +00 1 +.names g26811 II35863 +0 1 +.names II35863 g27505 +0 1 +.names g26861 g27506 +0 1 +.names g15321 g26291 g26812 +00 1 +.names g26812 II35868 +0 1 +.names II35868 g27508 +0 1 +.names g25648 g26327 g26925 +0- 1 +-0 1 +.names g26925 II35872 +0 1 +.names II35872 g27510 +0 1 +.names g15337 g26302 g26813 +00 1 +.names g26813 II35876 +0 1 +.names II35876 g27514 +0 1 +.names g15338 g26303 g26814 +00 1 +.names g26814 II35879 +0 1 +.names II35879 g27515 +0 1 +.names g26044 g10133 g26781 +00 1 +.names g26781 II35883 +0 1 +.names II35883 g27517 +0 1 +.names g26944 II35886 +0 1 +.names II35886 g27518 +0 1 +.names g15350 g26311 g26815 +00 1 +.names g26815 II35890 +0 1 +.names II35890 g27522 +0 1 +.names g15351 g26312 g26816 +00 1 +.names g26816 II35893 +0 1 +.names II35893 g27523 +0 1 +.names g15375 g26317 g26817 +00 1 +.names g26817 II35897 +0 1 +.names II35897 g27525 +0 1 +.names g26049 g22777 g26786 +00 1 +.names g26786 II35900 +0 1 +.names II35900 g27526 +0 1 +.names g15407 g26335 g26818 +00 1 +.names g26818 II35915 +0 1 +.names II35915 g27533 +0 1 +.names g25725 g26374 g26938 +0- 1 +-0 1 +.names g26938 II35919 +0 1 +.names II35919 g27535 +0 1 +.names g15423 g26346 g26820 +00 1 +.names g26820 II35923 +0 1 +.names II35923 g27539 +0 1 +.names g15424 g26347 g26821 +00 1 +.names g26821 II35926 +0 1 +.names II35926 g27540 +0 1 +.names g26046 g10238 g26789 +00 1 +.names g26789 II35930 +0 1 +.names II35930 g27542 +0 1 +.names g26950 II35933 +0 1 +.names II35933 g27543 +0 1 +.names g15436 g26352 g26822 +00 1 +.names g26822 II35937 +0 1 +.names II35937 g27547 +0 1 +.names g15437 g26353 g26823 +00 1 +.names g26823 II35940 +0 1 +.names II35940 g27548 +0 1 +.names g15491 g26382 g26824 +00 1 +.names g26824 II35953 +0 1 +.names II35953 g27553 +0 1 +.names g25798 g26417 g26947 +0- 1 +-0 1 +.names g26947 II35957 +0 1 +.names II35957 g27555 +0 1 +.names g15507 g26390 g26825 +00 1 +.names g26825 II35961 +0 1 +.names II35961 g27559 +0 1 +.names g15508 g26391 g26826 +00 1 +.names g26826 II35964 +0 1 +.names II35964 g27560 +0 1 +.names g26050 g10340 g26795 +00 1 +.names g26795 II35968 +0 1 +.names II35968 g27562 +0 1 +.names g15577 g26425 g26827 +00 1 +.names g26827 II35983 +0 1 +.names II35983 g27569 +0 1 +.names g26055 g18407 g26798 +00 1 +.names g26798 II36008 +0 1 +.names II36008 g27586 +0 1 +.names g27168 g27589 +0 1 +.names g23451 g26052 g27144 +00 1 +.names g27144 g27590 +0 1 +.names g23462 g26060 g27149 +00 1 +.names g27149 g27595 +0 1 +.names g23458 g26054 g27147 +00 1 +.names g27147 g27599 +0 1 +.names g23471 g26067 g27157 +00 1 +.names g27157 g27604 +0 1 +.names g23467 g26062 g27152 +00 1 +.names g27152 g27608 +0 1 +.names g23484 g26074 g27165 +00 1 +.names g27165 g27613 +0 1 +.names g23476 g26069 g27160 +00 1 +.names g27160 g27617 +0 1 +.names g23494 g26080 g27174 +00 1 +.names g27174 g27622 +0 1 +.names g1248 g1245 g26534 g27113 +1-- 1 +-1- 1 +--1 1 +.names g27113 II36032 +0 1 +.names II36032 g27632 +0 1 +.names g26960 II36042 +0 1 +.names II36042 g27662 +0 1 +.names g26957 II36046 +0 1 +.names II36046 g27667 +0 1 +.names g26954 II36052 +0 1 +.names II36052 g27674 +0 1 +.names g27353 II36060 +0 1 +.names g27463 II36063 +0 1 +.names g27479 II36066 +0 1 +.names g27493 II36069 +0 1 +.names g27480 II36072 +0 1 +.names g27494 II36075 +0 1 +.names g27508 II36078 +0 1 +.names g27497 II36081 +0 1 +.names g27357 II36084 +0 1 +.names g27483 II36087 +0 1 +.names g27502 II36090 +0 1 +.names g27514 II36093 +0 1 +.names g27503 II36096 +0 1 +.names g27515 II36099 +0 1 +.names g27533 II36102 +0 1 +.names g27517 II36105 +0 1 +.names g27360 II36108 +0 1 +.names g27505 II36111 +0 1 +.names g27522 II36114 +0 1 +.names g27539 II36117 +0 1 +.names g27523 II36120 +0 1 +.names g27540 II36123 +0 1 +.names g27553 II36126 +0 1 +.names g27542 II36129 +0 1 +.names g27366 II36132 +0 1 +.names g27525 II36135 +0 1 +.names g27547 II36138 +0 1 +.names g27559 II36141 +0 1 +.names g27548 II36144 +0 1 +.names g27560 II36147 +0 1 +.names g27569 II36150 +0 1 +.names g27562 II36153 +0 1 +.names g27586 II36156 +0 1 +.names g27526 II36159 +0 1 +.names g27385 II36162 +0 1 +.names g27632 g27748 +0 1 +.names g26869 g56 g27571 +0- 1 +-0 1 +.names g27571 II36213 +0 1 +.names II36213 g27776 +0 1 +.names g26878 g744 g27580 +0- 1 +-0 1 +.names g27580 II36217 +0 1 +.names II36217 g27780 +0 1 +.names g27662 II36221 +0 1 +.names II36221 g27784 +0 1 +.names g27589 II36224 +0 1 +.names II36224 g27785 +0 1 +.names g27175 g17001 g27594 +00 1 +.names g27594 II36227 +0 1 +.names II36227 g27786 +0 1 +.names g26887 g1430 g27583 +0- 1 +-0 1 +.names g27583 II36230 +0 1 +.names II36230 g27787 +0 1 +.names g27667 II36234 +0 1 +.names II36234 g27791 +0 1 +.names g27662 II36237 +0 1 +.names II36237 g27792 +0 1 +.names g27179 g17031 g27603 +00 1 +.names g27603 II36240 +0 1 +.names II36240 g27793 +0 1 +.names g26897 g2124 g27587 +0- 1 +-0 1 +.names g27587 II36243 +0 1 +.names II36243 g27794 +0 1 +.names g27674 II36246 +0 1 +.names II36246 g27797 +0 1 +.names g27184 g17065 g27612 +00 1 +.names g27612 II36250 +0 1 +.names II36250 g27799 +0 1 +.names g27674 II36253 +0 1 +.names II36253 g27800 +0 1 +.names g27188 g17100 g27621 +00 1 +.names g27621 II36264 +0 1 +.names II36264 g27805 +0 1 +.names g26989 g5438 g27395 +0- 1 +-0 1 +.names g27395 II36267 +0 1 +.names II36267 g27806 +0 1 +.names g26989 g6448 g27390 +0- 1 +-0 1 +.names g27390 II36280 +0 1 +.names II36280 g27817 +0 1 +.names g27012 g5473 g27408 +0- 1 +-0 1 +.names g27408 II36283 +0 1 +.names II36283 g27820 +0 1 +.names g26989 g3306 g27626 +0- 1 +-0 1 +.names g27626 II36296 +0 1 +.names II36296 g27831 +0 1 +.names g27012 g6713 g27400 +0- 1 +-0 1 +.names g27400 II36307 +0 1 +.names II36307 g27839 +0 1 +.names g27038 g5512 g27426 +0- 1 +-0 1 +.names g27426 II36311 +0 1 +.names II36311 g27843 +0 1 +.names g27012 g3462 g27627 +0- 1 +-0 1 +.names g27627 II36321 +0 1 +.names II36321 g27847 +0 1 +.names g27038 g7015 g27413 +0- 1 +-0 1 +.names g27413 II36327 +0 1 +.names II36327 g27858 +0 1 +.names g27066 g5556 g27447 +0- 1 +-0 1 +.names g27447 II36330 +0 1 +.names II36330 g27861 +0 1 +.names g27038 g3618 g27628 +0- 1 +-0 1 +.names g27628 II36337 +0 1 +.names II36337 g27872 +0 1 +.names g27066 g7265 g27431 +0- 1 +-0 1 +.names g27431 II36341 +0 1 +.names II36341 g27879 +0 1 +.names g27066 g3774 g27630 +0- 1 +-0 1 +.names g27630 II36347 +0 1 +.names II36347 g27889 +0 1 +.names g27662 II36354 +0 1 +.names II36354 g27903 +0 1 +.names g26799 g10024 g27672 +00 1 +.names g27672 II36358 +0 1 +.names II36358 g27905 +0 1 +.names g27667 II36362 +0 1 +.names II36362 g27907 +0 1 +.names g26800 g10133 g27678 +00 1 +.names g27678 II36367 +0 1 +.names II36367 g27910 +0 1 +.names g27674 II36371 +0 1 +.names II36371 g27912 +0 1 +.names g26801 g10238 g27682 +00 1 +.names g27682 II36379 +0 1 +.names II36379 g27918 +0 1 +.names g26922 g24708 g27563 +00 1 +.names g27563 II36382 +0 1 +.names II36382 g27919 +0 1 +.names g26802 g10340 g27243 +00 1 +.names g27243 II36390 +0 1 +.names II36390 g27927 +0 1 +.names g26911 g24717 g27572 +00 1 +.names g27572 II36393 +0 1 +.names II36393 g27928 +0 1 +.names g26935 g24720 g27574 +00 1 +.names g27574 II36397 +0 1 +.names II36397 g27932 +0 1 +.names g26902 g24613 g27450 +00 1 +.names g27450 II36404 +0 1 +.names II36404 g27939 +0 1 +.names g26925 g24728 g27581 +00 1 +.names g27581 II36407 +0 1 +.names II36407 g27942 +0 1 +.names g26944 g24731 g27582 +00 1 +.names g27582 II36411 +0 1 +.names II36411 g27946 +0 1 +.names g26892 g24622 g27462 +00 1 +.names g27462 II36417 +0 1 +.names II36417 g27952 +0 1 +.names g26965 g26212 g27253 +00 1 +.names g27253 II36420 +0 1 +.names II36420 g27955 +0 1 +.names g26915 g24624 g27466 +00 1 +.names g27466 II36423 +0 1 +.names II36423 g27956 +0 1 +.names g26938 g24736 g27584 +00 1 +.names g27584 II36426 +0 1 +.names II36426 g27959 +0 1 +.names g26950 g24739 g27585 +00 1 +.names g27585 II36432 +0 1 +.names II36432 g27965 +0 1 +.names g27361 g27969 +0 1 +.names g26969 g26233 g27255 +00 1 +.names g27255 II36438 +0 1 +.names II36438 g27971 +0 1 +.names g26970 g26234 g27256 +00 1 +.names g27256 II36441 +0 1 +.names II36441 g27972 +0 1 +.names g26906 g24637 g27482 +00 1 +.names g27482 II36444 +0 1 +.names II36444 g27973 +0 1 +.names g26971 g26243 g27257 +00 1 +.names g27257 II36447 +0 1 +.names II36447 g27976 +0 1 +.names g26928 g24638 g27485 +00 1 +.names g27485 II36450 +0 1 +.names II36450 g27977 +0 1 +.names g26947 g24742 g27588 +00 1 +.names g27588 II36454 +0 1 +.names II36454 g27981 +0 1 +.names g26977 g26257 g27258 +00 1 +.names g27258 II36459 +0 1 +.names II36459 g27986 +0 1 +.names g26978 g26258 g27259 +00 1 +.names g27259 II36462 +0 1 +.names II36462 g27987 +0 1 +.names g26979 g26259 g27260 +00 1 +.names g27260 II36465 +0 1 +.names II36465 g27988 +0 1 +.names g26980 g26263 g27261 +00 1 +.names g27261 II36468 +0 1 +.names II36468 g27989 +0 1 +.names g27367 g27990 +0 1 +.names g26981 g26268 g27262 +00 1 +.names g27262 II36473 +0 1 +.names II36473 g27992 +0 1 +.names g26982 g26269 g27263 +00 1 +.names g27263 II36476 +0 1 +.names II36476 g27993 +0 1 +.names g26918 g24656 g27504 +00 1 +.names g27504 II36479 +0 1 +.names II36479 g27994 +0 1 +.names g26984 g26278 g27264 +00 1 +.names g27264 II36483 +0 1 +.names II36483 g27998 +0 1 +.names g26941 g24657 g27507 +00 1 +.names g27507 II36486 +0 1 +.names II36486 g27999 +0 1 +.names g26993 g26288 g27265 +00 1 +.names g27265 II36490 +0 1 +.names II36490 g28003 +0 1 +.names g26994 g26289 g27266 +00 1 +.names g27266 II36493 +0 1 +.names II36493 g28004 +0 1 +.names g26995 g26290 g27267 +00 1 +.names g27267 II36496 +0 1 +.names II36496 g28005 +0 1 +.names g26996 g26292 g27268 +00 1 +.names g27268 II36499 +0 1 +.names II36499 g28006 +0 1 +.names g26997 g26293 g27269 +00 1 +.names g27269 II36502 +0 1 +.names II36502 g28007 +0 1 +.names g26998 g26298 g27270 +00 1 +.names g27270 II36507 +0 1 +.names II36507 g28010 +0 1 +.names g26999 g26299 g27271 +00 1 +.names g27271 II36510 +0 1 +.names II36510 g28011 +0 1 +.names g27000 g26300 g27272 +00 1 +.names g27272 II36513 +0 1 +.names II36513 g28012 +0 1 +.names g27001 g26307 g27273 +00 1 +.names g27273 II36516 +0 1 +.names II36516 g28013 +0 1 +.names g27373 g28014 +0 1 +.names g27002 g26309 g27274 +00 1 +.names g27274 II36521 +0 1 +.names II36521 g28016 +0 1 +.names g27003 g26310 g27275 +00 1 +.names g27275 II36524 +0 1 +.names II36524 g28017 +0 1 +.names g26931 g24675 g27524 +00 1 +.names g27524 II36527 +0 1 +.names II36527 g28018 +0 1 +.names g27004 g26316 g27276 +00 1 +.names g27276 II36530 +0 1 +.names II36530 g28021 +0 1 +.names g27005 g26318 g27277 +00 1 +.names g27277 II36533 +0 1 +.names II36533 g28022 +0 1 +.names g27006 g26319 g27278 +00 1 +.names g27278 II36536 +0 1 +.names II36536 g28023 +0 1 +.names g27007 g26324 g27279 +00 1 +.names g27279 II36539 +0 1 +.names II36539 g28024 +0 1 +.names g27008 g26325 g27280 +00 1 +.names g27280 II36542 +0 1 +.names II36542 g28025 +0 1 +.names g27009 g26326 g27281 +00 1 +.names g27281 II36545 +0 1 +.names II36545 g28026 +0 1 +.names g27016 g26332 g27282 +00 1 +.names g27282 II36551 +0 1 +.names II36551 g28030 +0 1 +.names g27017 g26333 g27283 +00 1 +.names g27283 II36554 +0 1 +.names II36554 g28031 +0 1 +.names g27018 g26334 g27284 +00 1 +.names g27284 II36557 +0 1 +.names II36557 g28032 +0 1 +.names g27019 g26339 g27285 +00 1 +.names g27285 II36560 +0 1 +.names II36560 g28033 +0 1 +.names g27020 g26340 g27286 +00 1 +.names g27286 II36563 +0 1 +.names II36563 g28034 +0 1 +.names g27021 g26342 g27287 +00 1 +.names g27287 II36568 +0 1 +.names II36568 g28037 +0 1 +.names g27022 g26343 g27288 +00 1 +.names g27288 II36571 +0 1 +.names II36571 g28038 +0 1 +.names g27023 g26344 g27289 +00 1 +.names g27289 II36574 +0 1 +.names II36574 g28039 +0 1 +.names g27024 g26348 g27290 +00 1 +.names g27290 II36577 +0 1 +.names II36577 g28040 +0 1 +.names g27376 g28041 +0 1 +.names g27025 g26350 g27291 +00 1 +.names g27291 II36582 +0 1 +.names II36582 g28043 +0 1 +.names g27026 g26351 g27292 +00 1 +.names g27292 II36585 +0 1 +.names II36585 g28044 +0 1 +.names g27027 g26357 g27293 +00 1 +.names g27293 II36588 +0 1 +.names II36588 g28045 +0 1 +.names g27028 g26361 g27294 +00 1 +.names g27294 II36598 +0 1 +.names II36598 g28047 +0 1 +.names g27029 g26362 g27295 +00 1 +.names g27295 II36601 +0 1 +.names II36601 g28048 +0 1 +.names g27030 g26363 g27296 +00 1 +.names g27296 II36604 +0 1 +.names II36604 g28049 +0 1 +.names g27031 g26365 g27297 +00 1 +.names g27297 II36609 +0 1 +.names II36609 g28052 +0 1 +.names g27032 g26366 g27298 +00 1 +.names g27298 II36612 +0 1 +.names II36612 g28053 +0 1 +.names g27033 g26371 g27299 +00 1 +.names g27299 II36615 +0 1 +.names II36615 g28054 +0 1 +.names g27034 g26372 g27300 +00 1 +.names g27300 II36618 +0 1 +.names II36618 g28055 +0 1 +.names g27035 g26373 g27301 +00 1 +.names g27301 II36621 +0 1 +.names II36621 g28056 +0 1 +.names g27042 g26379 g27302 +00 1 +.names g27302 II36627 +0 1 +.names II36627 g28060 +0 1 +.names g27043 g26380 g27303 +00 1 +.names g27303 II36630 +0 1 +.names II36630 g28061 +0 1 +.names g27044 g26381 g27304 +00 1 +.names g27304 II36633 +0 1 +.names II36633 g28062 +0 1 +.names g27045 g26383 g27305 +00 1 +.names g27305 II36636 +0 1 +.names II36636 g28063 +0 1 +.names g27046 g26384 g27306 +00 1 +.names g27306 II36639 +0 1 +.names II36639 g28064 +0 1 +.names g27047 g26386 g27307 +00 1 +.names g27307 II36644 +0 1 +.names II36644 g28067 +0 1 +.names g27048 g26387 g27308 +00 1 +.names g27308 II36647 +0 1 +.names II36647 g28068 +0 1 +.names g27049 g26388 g27309 +00 1 +.names g27309 II36650 +0 1 +.names II36650 g28069 +0 1 +.names g27050 g26392 g27310 +00 1 +.names g27310 II36653 +0 1 +.names II36653 g28070 +0 1 +.names g27053 g26396 g27311 +00 1 +.names g27311 II36656 +0 1 +.names II36656 g28071 +0 1 +.names g27054 g26397 g27312 +00 1 +.names g27312 II36659 +0 1 +.names II36659 g28072 +0 1 +.names g27055 g26400 g27313 +00 1 +.names g27313 II36663 +0 1 +.names II36663 g28074 +0 1 +.names g27056 g26404 g27314 +00 1 +.names g27314 II36673 +0 1 +.names II36673 g28076 +0 1 +.names g27057 g26405 g27315 +00 1 +.names g27315 II36676 +0 1 +.names II36676 g28077 +0 1 +.names g27058 g26406 g27316 +00 1 +.names g27316 II36679 +0 1 +.names II36679 g28078 +0 1 +.names g27059 g26408 g27317 +00 1 +.names g27317 II36684 +0 1 +.names II36684 g28081 +0 1 +.names g27060 g26409 g27318 +00 1 +.names g27318 II36687 +0 1 +.names II36687 g28082 +0 1 +.names g27061 g26414 g27319 +00 1 +.names g27319 II36690 +0 1 +.names II36690 g28083 +0 1 +.names g27062 g26415 g27320 +00 1 +.names g27320 II36693 +0 1 +.names II36693 g28084 +0 1 +.names g27063 g26416 g27321 +00 1 +.names g27321 II36696 +0 1 +.names II36696 g28085 +0 1 +.names g27070 g26422 g27322 +00 1 +.names g27322 II36702 +0 1 +.names II36702 g28089 +0 1 +.names g27071 g26423 g27323 +00 1 +.names g27323 II36705 +0 1 +.names II36705 g28090 +0 1 +.names g27072 g26424 g27324 +00 1 +.names g27324 II36708 +0 1 +.names II36708 g28091 +0 1 +.names g27073 g26426 g27325 +00 1 +.names g27325 II36711 +0 1 +.names II36711 g28092 +0 1 +.names g27074 g26427 g27326 +00 1 +.names g27326 II36714 +0 1 +.names II36714 g28093 +0 1 +.names g27077 g26432 g27327 +00 1 +.names g27327 II36718 +0 1 +.names II36718 g28095 +0 1 +.names g27080 g26437 g27328 +00 1 +.names g27328 II36721 +0 1 +.names II36721 g28096 +0 1 +.names g27081 g26438 g27329 +00 1 +.names g27329 II36724 +0 1 +.names II36724 g28097 +0 1 +.names g27082 g26441 g27330 +00 1 +.names g27330 II36728 +0 1 +.names II36728 g28099 +0 1 +.names g27083 g26445 g27331 +00 1 +.names g27331 II36738 +0 1 +.names II36738 g28101 +0 1 +.names g27084 g26446 g27332 +00 1 +.names g27332 II36741 +0 1 +.names II36741 g28102 +0 1 +.names g27085 g26447 g27333 +00 1 +.names g27333 II36744 +0 1 +.names II36744 g28103 +0 1 +.names g27086 g26449 g27334 +00 1 +.names g27334 II36749 +0 1 +.names II36749 g28106 +0 1 +.names g27087 g26450 g27335 +00 1 +.names g27335 II36752 +0 1 +.names II36752 g28107 +0 1 +.names g27088 g26455 g27336 +00 1 +.names g27336 II36755 +0 1 +.names II36755 g28108 +0 1 +.names g27089 g26456 g27337 +00 1 +.names g27337 II36758 +0 1 +.names II36758 g28109 +0 1 +.names g27090 g26457 g27338 +00 1 +.names g27338 II36761 +0 1 +.names II36761 g28110 +0 1 +.names g27093 g26464 g27339 +00 1 +.names g27339 II36766 +0 1 +.names II36766 g28113 +0 1 +.names g27096 g26469 g27340 +00 1 +.names g27340 II36769 +0 1 +.names II36769 g28114 +0 1 +.names g27097 g26470 g27341 +00 1 +.names g27341 II36772 +0 1 +.names II36772 g28115 +0 1 +.names g27098 g26473 g27342 +00 1 +.names g27342 II36776 +0 1 +.names II36776 g28117 +0 1 +.names g27099 g26477 g27343 +00 1 +.names g27343 II36786 +0 1 +.names II36786 g28119 +0 1 +.names g27100 g26478 g27344 +00 1 +.names g27344 II36789 +0 1 +.names II36789 g28120 +0 1 +.names g27101 g26479 g27345 +00 1 +.names g27345 II36792 +0 1 +.names II36792 g28121 +0 1 +.names g27105 g26488 g27346 +00 1 +.names g27346 II36797 +0 1 +.names II36797 g28124 +0 1 +.names g27108 g26493 g27347 +00 1 +.names g27347 II36800 +0 1 +.names II36800 g28125 +0 1 +.names g27109 g26494 g27348 +00 1 +.names g27348 II36803 +0 1 +.names II36803 g28126 +0 1 +.names II35905 II35906 g27528 +0- 1 +-0 1 +.names g27528 g28128 +0 1 +.names g27112 g26504 g27354 +00 1 +.names g27354 II36808 +0 1 +.names II36808 g28132 +0 1 +.names II35945 II35946 g27550 +0- 1 +-0 1 +.names g27550 g28133 +0 1 +.names II35975 II35976 g27566 +0- 1 +-0 1 +.names g27566 g28137 +0 1 +.names II35993 II35994 g27576 +0- 1 +-0 1 +.names g27576 g28141 +0 1 +.names g27667 g28149 +0 1 +.names g27387 g28150 +0 1 +.names g27381 g28151 +0 1 +.names g27391 g28152 +0 1 +.names g27397 g28153 +0 1 +.names g27401 g28154 +0 1 +.names g27404 g28155 +0 1 +.names g27410 g28156 +0 1 +.names g27416 g28158 +0 1 +.names g27419 g28159 +0 1 +.names g27422 g28160 +0 1 +.names g27428 g28161 +0 1 +.names g27432 g28162 +0 1 +.names g27437 g28163 +0 1 +.names g27440 g28164 +0 1 +.names g27443 g28165 +0 1 +.names g27451 g28166 +0 1 +.names g27456 g28167 +0 1 +.names g27459 g28168 +0 1 +.names g27467 g28169 +0 1 +.names g27472 g28170 +0 1 +.names g27475 g28172 +0 1 +.names g27486 g28173 +0 1 +.names g27489 g28174 +0 1 +.names g27498 g28175 +0 1 +.names g27510 g28177 +0 1 +.names g27518 g28178 +0 1 +.names g27383 II36848 +0 1 +.names II36848 g28179 +0 1 +.names g27535 g28186 +0 1 +.names g27543 g28187 +0 1 +.names g27555 g28190 +0 1 +.names g27386 II36860 +0 1 +.names II36860 g28194 +0 1 +.names g27384 II36864 +0 1 +.names II36864 g28200 +0 1 +.names g27786 II36867 +0 1 +.names g27955 II36870 +0 1 +.names g27971 II36873 +0 1 +.names g27986 II36876 +0 1 +.names g27972 II36879 +0 1 +.names g27987 II36882 +0 1 +.names g28003 II36885 +0 1 +.names g27988 II36888 +0 1 +.names g28004 II36891 +0 1 +.names g28022 II36894 +0 1 +.names g28005 II36897 +0 1 +.names g28023 II36900 +0 1 +.names g28045 II36903 +0 1 +.names g27989 II36906 +0 1 +.names g28006 II36909 +0 1 +.names g28024 II36912 +0 1 +.names g28007 II36915 +0 1 +.names g28025 II36918 +0 1 +.names g28047 II36921 +0 1 +.names g28026 II36924 +0 1 +.names g28048 II36927 +0 1 +.names g28071 II36930 +0 1 +.names g28049 II36933 +0 1 +.names g28072 II36936 +0 1 +.names g28095 II36939 +0 1 +.names g27905 II36942 +0 1 +.names g27793 II36945 +0 1 +.names g27976 II36948 +0 1 +.names g27992 II36951 +0 1 +.names g28010 II36954 +0 1 +.names g27993 II36957 +0 1 +.names g28011 II36960 +0 1 +.names g28030 II36963 +0 1 +.names g28012 II36966 +0 1 +.names g28031 II36969 +0 1 +.names g28052 II36972 +0 1 +.names g28032 II36975 +0 1 +.names g28053 II36978 +0 1 +.names g28074 II36981 +0 1 +.names g28013 II36984 +0 1 +.names g28033 II36987 +0 1 +.names g28054 II36990 +0 1 +.names g28034 II36993 +0 1 +.names g28055 II36996 +0 1 +.names g28076 II36999 +0 1 +.names g28056 II37002 +0 1 +.names g28077 II37005 +0 1 +.names g28096 II37008 +0 1 +.names g28078 II37011 +0 1 +.names g28097 II37014 +0 1 +.names g28113 II37017 +0 1 +.names g27910 II37020 +0 1 +.names g27799 II37023 +0 1 +.names g27998 II37026 +0 1 +.names g28016 II37029 +0 1 +.names g28037 II37032 +0 1 +.names g28017 II37035 +0 1 +.names g28038 II37038 +0 1 +.names g28060 II37041 +0 1 +.names g28039 II37044 +0 1 +.names g28061 II37047 +0 1 +.names g28081 II37050 +0 1 +.names g28062 II37053 +0 1 +.names g28082 II37056 +0 1 +.names g28099 II37059 +0 1 +.names g28040 II37062 +0 1 +.names g28063 II37065 +0 1 +.names g28083 II37068 +0 1 +.names g28064 II37071 +0 1 +.names g28084 II37074 +0 1 +.names g28101 II37077 +0 1 +.names g28085 II37080 +0 1 +.names g28102 II37083 +0 1 +.names g28114 II37086 +0 1 +.names g28103 II37089 +0 1 +.names g28115 II37092 +0 1 +.names g28124 II37095 +0 1 +.names g27918 II37098 +0 1 +.names g27805 II37101 +0 1 +.names g28021 II37104 +0 1 +.names g28043 II37107 +0 1 +.names g28067 II37110 +0 1 +.names g28044 II37113 +0 1 +.names g28068 II37116 +0 1 +.names g28089 II37119 +0 1 +.names g28069 II37122 +0 1 +.names g28090 II37125 +0 1 +.names g28106 II37128 +0 1 +.names g28091 II37131 +0 1 +.names g28107 II37134 +0 1 +.names g28117 II37137 +0 1 +.names g28070 II37140 +0 1 +.names g28092 II37143 +0 1 +.names g28108 II37146 +0 1 +.names g28093 II37149 +0 1 +.names g28109 II37152 +0 1 +.names g28119 II37155 +0 1 +.names g28110 II37158 +0 1 +.names g28120 II37161 +0 1 +.names g28125 II37164 +0 1 +.names g28121 II37167 +0 1 +.names g28126 II37170 +0 1 +.names g28132 II37173 +0 1 +.names g27927 II37176 +0 1 +.names g27784 II37179 +0 1 +.names g27791 II37182 +0 1 +.names g27797 II37185 +0 1 +.names g27785 II37188 +0 1 +.names g27792 II37191 +0 1 +.names g27800 II37194 +0 1 +.names g27903 II37197 +0 1 +.names g27907 II37200 +0 1 +.names g27912 II37203 +0 1 +.names g28194 II37228 +0 1 +.names II37228 g28341 +0 1 +.names g28200 II37232 +0 1 +.names II37232 g28343 +0 1 +.names g28179 II37238 +0 1 +.names II37238 g28347 +0 1 +.names g28200 II37252 +0 1 +.names II37252 g28359 +0 1 +.names g28179 II37260 +0 1 +.names II37260 g28365 +0 1 +.names g28200 II37266 +0 1 +.names II37266 g28369 +0 1 +.names g27629 g17001 g28145 +00 1 +.names g28145 II37269 +0 1 +.names II37269 g28370 +0 1 +.names g28179 II37273 +0 1 +.names II37273 g28372 +0 1 +.names g27631 g17031 g28146 +00 1 +.names g28146 II37277 +0 1 +.names II37277 g28374 +0 1 +.names g28179 II37280 +0 1 +.names II37280 g28375 +0 1 +.names g27655 g17065 g28147 +00 1 +.names g28147 II37284 +0 1 +.names II37284 g28377 +0 1 +.names g27658 g17100 g28148 +00 1 +.names g28148 II37291 +0 1 +.names II37291 g28382 +0 1 +.names g28149 II37319 +0 1 +.names II37319 g28390 +0 1 +.names g28194 II37330 +0 1 +.names II37330 g28393 +0 1 +.names g28194 II37334 +0 1 +.names II37334 g28395 +0 1 +.names g28151 g28419 +0 1 +.names g27250 g10024 g28199 +00 1 +.names g28199 II37379 +0 1 +.names II37379 g28432 +0 1 +.names g28194 II37386 +0 1 +.names II37386 g28437 +0 1 +.names g27251 g10133 g27718 +00 1 +.names g27718 II37394 +0 1 +.names II37394 g28443 +0 1 +.names g28200 II37400 +0 1 +.names II37400 g28447 +0 1 +.names g27252 g10238 g27722 +00 1 +.names g27722 II37410 +0 1 +.names II37410 g28455 +0 1 +.names g28179 II37415 +0 1 +.names II37415 g28458 +0 1 +.names g27254 g10340 g27724 +00 1 +.names g27724 II37426 +0 1 +.names II37426 g28467 +0 1 +.names g27776 g28483 +0 1 +.names g27780 g28491 +0 1 +.names g27787 g28496 +0 1 +.names g27495 g27052 g27759 +00 1 +.names g27759 II37459 +0 1 +.names II37459 g28498 +0 1 +.names g27794 g28500 +0 1 +.names g27509 g27076 g27760 +00 1 +.names g27760 II37467 +0 1 +.names II37467 g28524 +0 1 +.names g27516 g27079 g27761 +00 1 +.names g27761 II37471 +0 1 +.names II37471 g28526 +0 1 +.names g27530 g27091 g27762 +00 1 +.names g27762 II37474 +0 1 +.names II37474 g28527 +0 1 +.names g27534 g27092 g27763 +00 1 +.names g27763 II37481 +0 1 +.names II37481 g28552 +0 1 +.names g27541 g27095 g27764 +00 1 +.names g27764 II37484 +0 1 +.names II37484 g28553 +0 1 +.names g27806 g28554 +0 1 +.names g27552 g27103 g27765 +00 1 +.names g27765 II37488 +0 1 +.names II37488 g28555 +0 1 +.names g27554 g27104 g27766 +00 1 +.names g27766 II37494 +0 1 +.names II37494 g28579 +0 1 +.names g27561 g27107 g27767 +00 1 +.names g27767 II37497 +0 1 +.names II37497 g28580 +0 1 +.names g27817 g28581 +0 1 +.names g27820 g28582 +0 1 +.names g27568 g27110 g27768 +00 1 +.names g27768 II37502 +0 1 +.names II37502 g28583 +0 1 +.names g27570 g27111 g27769 +00 1 +.names g27769 II37508 +0 1 +.names II37508 g28607 +0 1 +.names g27831 g28608 +0 1 +.names g27839 g28609 +0 1 +.names g27843 g28610 +0 1 +.names g27578 g27115 g27771 +00 1 +.names g27771 II37514 +0 1 +.names II37514 g28611 +0 1 +.names II36592 II36593 g28046 +0- 1 +-0 1 +.names g28046 g28612 +0 1 +.names g27847 g28616 +0 1 +.names g27858 g28617 +0 1 +.names g27861 g28618 +0 1 +.names II36667 II36668 g28075 +0- 1 +-0 1 +.names g28075 g28619 +0 1 +.names g27872 g28623 +0 1 +.names g27879 g28624 +0 1 +.names II36732 II36733 g28100 +0- 1 +-0 1 +.names g28100 g28625 +0 1 +.names g27889 g28629 +0 1 +.names II36780 II36781 g28118 +0- 1 +-0 1 +.names g28118 g28630 +0 1 +.names g28200 g28638 +0 1 +.names g27919 g28639 +0 1 +.names g27928 g28640 +0 1 +.names g27932 g28641 +0 1 +.names g27939 g28642 +0 1 +.names g27942 g28643 +0 1 +.names g27946 g28644 +0 1 +.names g27952 g28645 +0 1 +.names g27956 g28646 +0 1 +.names g27959 g28647 +0 1 +.names g27965 g28648 +0 1 +.names g27973 g28649 +0 1 +.names g27977 g28650 +0 1 +.names g27981 g28651 +0 1 +.names g27994 g28652 +0 1 +.names g27999 g28653 +0 1 +.names g28018 g28655 +0 1 +.names g28370 II37566 +0 1 +.names g28498 II37569 +0 1 +.names g28524 II37572 +0 1 +.names g28527 II37575 +0 1 +.names g28432 II37578 +0 1 +.names g28374 II37581 +0 1 +.names g28526 II37584 +0 1 +.names g28552 II37587 +0 1 +.names g28555 II37590 +0 1 +.names g28443 II37593 +0 1 +.names g28377 II37596 +0 1 +.names g28553 II37599 +0 1 +.names g28579 II37602 +0 1 +.names g28583 II37605 +0 1 +.names g28455 II37608 +0 1 +.names g28382 II37611 +0 1 +.names g28580 II37614 +0 1 +.names g28607 II37617 +0 1 +.names g28611 II37620 +0 1 +.names g28467 II37623 +0 1 +.names g28393 II37626 +0 1 +.names g28369 II37629 +0 1 +.names g28372 II37632 +0 1 +.names g28390 II37635 +0 1 +.names g28395 II37638 +0 1 +.names g28375 II37641 +0 1 +.names g28341 II37644 +0 1 +.names g28343 II37647 +0 1 +.names g28347 II37650 +0 1 +.names g28359 II37653 +0 1 +.names g28365 II37656 +0 1 +.names g28437 II37659 +0 1 +.names g28447 II37662 +0 1 +.names g28458 II37665 +0 1 +.names g27244 g27723 g28495 +00 1 +.names g28495 g28720 +0 1 +.names g27240 g27721 g28490 +00 1 +.names g28490 g28721 +0 1 +.names g26030 g27728 g28528 +00 1 +.names g28528 g28723 +0 1 +.names g26027 g27725 g28499 +00 1 +.names g28499 g28725 +0 1 +.names g26756 g27720 g28489 +00 1 +.names g28489 g28727 +0 1 +.names g27671 g28193 g28470 +00 1 +.names g28470 g28730 +0 1 +.names g27245 g27726 g28525 +00 1 +.names g28525 g28734 +0 1 +.names g26755 g27719 g28488 +00 1 +.names g28488 g28740 +0 1 +.names g26481 g27738 g28512 +1- 1 +-1 1 +.names g28512 II37702 +0 1 +.names II37702 g28741 +0 1 +.names g28512 II37712 +0 1 +.names II37712 g28751 +0 1 +.names g26497 g27743 g28540 +1- 1 +-1 1 +.names g28540 II37716 +0 1 +.names II37716 g28755 +0 1 +.names g28540 II37725 +0 1 +.names II37725 g28764 +0 1 +.names g26512 g27751 g28567 +1- 1 +-1 1 +.names g28567 II37729 +0 1 +.names II37729 g28768 +0 1 +.names g28567 II37736 +0 1 +.names II37736 g28775 +0 1 +.names g26520 g27756 g28595 +1- 1 +-1 1 +.names g28595 II37740 +0 1 +.names II37740 g28779 +0 1 +.names g28595 II37746 +0 1 +.names II37746 g28785 +0 1 +.names g28512 II37752 +0 1 +.names II37752 g28791 +0 1 +.names g28512 II37757 +0 1 +.names II37757 g28796 +0 1 +.names g28540 II37760 +0 1 +.names II37760 g28799 +0 1 +.names g28512 II37765 +0 1 +.names II37765 g28804 +0 1 +.names g28540 II37768 +0 1 +.names II37768 g28807 +0 1 +.names g28567 II37771 +0 1 +.names II37771 g28810 +0 1 +.names g28540 II37775 +0 1 +.names II37775 g28814 +0 1 +.names g28567 II37778 +0 1 +.names II37778 g28817 +0 1 +.names g28595 II37781 +0 1 +.names II37781 g28820 +0 1 +.names g28567 II37784 +0 1 +.names II37784 g28823 +0 1 +.names g28595 II37787 +0 1 +.names II37787 g28826 +0 1 +.names g28595 II37790 +0 1 +.names II37790 g28829 +0 1 +.names g28638 II37793 +0 1 +.names II37793 g28832 +0 1 +.names g28185 g17001 g28634 +00 1 +.names g28634 II37796 +0 1 +.names II37796 g28833 +0 1 +.names g28189 g17031 g28635 +00 1 +.names g28635 II37800 +0 1 +.names II37800 g28835 +0 1 +.names g28191 g17065 g28636 +00 1 +.names g28636 II37804 +0 1 +.names II37804 g28837 +0 1 +.names g28192 g17100 g28637 +00 1 +.names g28637 II37808 +0 1 +.names II37808 g28839 +0 1 +.names g24676 g27801 g28409 +00 1 +.names g28409 g28855 +0 1 +.names g24695 g27809 g28413 +00 1 +.names g28413 g28859 +0 1 +.names g24712 g27830 g28417 +00 1 +.names g28417 g28863 +0 1 +.names g24723 g27846 g28418 +00 1 +.names g28418 g28867 +0 1 +.names g27738 g25764 g28501 +1- 1 +-1 1 +.names g28501 II37842 +0 1 +.names II37842 g28871 +0 1 +.names g28501 II37846 +0 1 +.names II37846 g28877 +0 1 +.names g27736 g10024 g28668 +00 1 +.names g28668 II37851 +0 1 +.names II37851 g28882 +0 1 +.names g27743 g25818 g28529 +1- 1 +-1 1 +.names g28529 II37854 +0 1 +.names II37854 g28883 +0 1 +.names g28501 II37858 +0 1 +.names II37858 g28889 +0 1 +.names g28529 II37863 +0 1 +.names II37863 g28894 +0 1 +.names g27742 g10133 g28321 +00 1 +.names g28321 II37868 +0 1 +.names II37868 g28899 +0 1 +.names g27751 g25853 g28556 +1- 1 +-1 1 +.names g28556 II37871 +0 1 +.names II37871 g28900 +0 1 +.names g28501 II37875 +0 1 +.names II37875 g28906 +0 1 +.names g28529 II37880 +0 1 +.names II37880 g28911 +0 1 +.names g28556 II37885 +0 1 +.names II37885 g28916 +0 1 +.names g27747 g10238 g28325 +00 1 +.names g28325 II37891 +0 1 +.names II37891 g28924 +0 1 +.names g27756 g25874 g28584 +1- 1 +-1 1 +.names g28584 II37894 +0 1 +.names II37894 g28925 +0 1 +.names g28501 II37897 +0 1 +.names II37897 g28928 +0 1 +.names g28529 II37901 +0 1 +.names II37901 g28932 +0 1 +.names g28556 II37906 +0 1 +.names II37906 g28937 +0 1 +.names g28584 II37912 +0 1 +.names II37912 g28945 +0 1 +.names g27755 g10340 g28328 +00 1 +.names g28328 II37917 +0 1 +.names II37917 g28950 +0 1 +.names g28501 II37920 +0 1 +.names II37920 g28951 +0 1 +.names g28529 II37924 +0 1 +.names II37924 g28955 +0 1 +.names g28556 II37928 +0 1 +.names II37928 g28959 +0 1 +.names g28584 II37934 +0 1 +.names II37934 g28967 +0 1 +.names g28501 II37939 +0 1 +.names II37939 g28972 +0 1 +.names g28501 II37942 +0 1 +.names II37942 g28975 +0 1 +.names g28529 II37946 +0 1 +.names II37946 g28979 +0 1 +.names g28556 II37950 +0 1 +.names II37950 g28983 +0 1 +.names g28584 II37956 +0 1 +.names II37956 g28993 +0 1 +.names g28501 II37961 +0 1 +.names II37961 g28998 +0 1 +.names g28529 II37965 +0 1 +.names II37965 g29002 +0 1 +.names g28529 II37968 +0 1 +.names II37968 g29005 +0 1 +.names g28556 II37973 +0 1 +.names II37973 g29010 +0 1 +.names g28584 II37978 +0 1 +.names II37978 g29019 +0 1 +.names g28501 II37982 +0 1 +.names II37982 g29023 +0 1 +.names g28529 II37986 +0 1 +.names II37986 g29027 +0 1 +.names g28556 II37991 +0 1 +.names II37991 g29032 +0 1 +.names g28556 II37994 +0 1 +.names II37994 g29035 +0 1 +.names g28584 II37999 +0 1 +.names II37999 g29042 +0 1 +.names g28529 II38003 +0 1 +.names II38003 g29046 +0 1 +.names g28556 II38007 +0 1 +.names II38007 g29050 +0 1 +.names g28584 II38011 +0 1 +.names II38011 g29054 +0 1 +.names g28584 II38014 +0 1 +.names II38014 g29057 +0 1 +.names g15460 g28008 g28342 +00 1 +.names g28342 II38018 +0 1 +.names II38018 g29061 +0 1 +.names g28556 II38024 +0 1 +.names II38024 g29065 +0 1 +.names g28584 II38028 +0 1 +.names II38028 g29069 +0 1 +.names g15526 g28027 g28344 +00 1 +.names g28344 II38032 +0 1 +.names II38032 g29073 +0 1 +.names g15527 g28028 g28345 +00 1 +.names g28345 II38035 +0 1 +.names II38035 g29074 +0 1 +.names g15546 g28035 g28346 +00 1 +.names g28346 II38038 +0 1 +.names II38038 g29075 +0 1 +.names g28584 II38042 +0 1 +.names II38042 g29077 +0 1 +.names g15594 g28050 g28348 +00 1 +.names g28348 II38046 +0 1 +.names II38046 g29081 +0 1 +.names g15595 g28051 g28349 +00 1 +.names g28349 II38049 +0 1 +.names II38049 g29082 +0 1 +.names g15604 g28057 g28350 +00 1 +.names g28350 II38053 +0 1 +.names II38053 g29084 +0 1 +.names g15605 g28058 g28351 +00 1 +.names g28351 II38056 +0 1 +.names II38056 g29085 +0 1 +.names g15624 g28065 g28352 +00 1 +.names g28352 II38059 +0 1 +.names II38059 g29086 +0 1 +.names g15666 g28073 g28353 +00 1 +.names g28353 II38064 +0 1 +.names II38064 g29089 +0 1 +.names g15670 g28079 g28354 +00 1 +.names g28354 II38068 +0 1 +.names II38068 g29091 +0 1 +.names g15671 g28080 g28355 +00 1 +.names g28355 II38071 +0 1 +.names II38071 g29092 +0 1 +.names g15680 g28086 g28356 +00 1 +.names g28356 II38074 +0 1 +.names II38074 g29093 +0 1 +.names g15681 g28087 g28357 +00 1 +.names g28357 II38077 +0 1 +.names II38077 g29094 +0 1 +.names g15700 g28094 g28358 +00 1 +.names g28358 II38080 +0 1 +.names II38080 g29095 +0 1 +.names g15725 g28098 g28360 +00 1 +.names g28360 II38085 +0 1 +.names II38085 g29098 +0 1 +.names g15729 g28104 g28361 +00 1 +.names g28361 II38088 +0 1 +.names II38088 g29099 +0 1 +.names g15730 g28105 g28362 +00 1 +.names g28362 II38091 +0 1 +.names II38091 g29100 +0 1 +.names g15739 g28111 g28363 +00 1 +.names g28363 II38094 +0 1 +.names II38094 g29101 +0 1 +.names g15740 g28112 g28364 +00 1 +.names g28364 II38097 +0 1 +.names II38097 g29102 +0 1 +.names g15765 g28116 g28366 +00 1 +.names g28366 II38101 +0 1 +.names II38101 g29104 +0 1 +.names g15769 g28122 g28367 +00 1 +.names g28367 II38104 +0 1 +.names II38104 g29105 +0 1 +.names g15770 g28123 g28368 +00 1 +.names g28368 II38107 +0 1 +.names II38107 g29106 +0 1 +.names g15793 g28127 g28371 +00 1 +.names g28371 II38111 +0 1 +.names II38111 g29108 +0 1 +.names g16031 g28171 g28420 +00 1 +.names g28420 II38119 +0 1 +.names II38119 g29117 +0 1 +.names g16068 g28176 g28421 +00 1 +.names g28421 II38122 +0 1 +.names II38122 g29118 +0 1 +.names g16133 g28188 g28425 +00 1 +.names g28425 II38125 +0 1 +.names II38125 g29119 +0 1 +.names g28419 II38128 +0 1 +.names II38128 g29120 +0 1 +.names g28833 II38136 +0 1 +.names g29061 II38139 +0 1 +.names g29073 II38142 +0 1 +.names g29081 II38145 +0 1 +.names g29074 II38148 +0 1 +.names g29082 II38151 +0 1 +.names g29089 II38154 +0 1 +.names g28882 II38157 +0 1 +.names g28835 II38160 +0 1 +.names g29075 II38163 +0 1 +.names g29084 II38166 +0 1 +.names g29091 II38169 +0 1 +.names g29085 II38172 +0 1 +.names g29092 II38175 +0 1 +.names g29098 II38178 +0 1 +.names g28899 II38181 +0 1 +.names g28837 II38184 +0 1 +.names g29086 II38187 +0 1 +.names g29093 II38190 +0 1 +.names g29099 II38193 +0 1 +.names g29094 II38196 +0 1 +.names g29100 II38199 +0 1 +.names g29104 II38202 +0 1 +.names g28924 II38205 +0 1 +.names g28839 II38208 +0 1 +.names g29095 II38211 +0 1 +.names g29101 II38214 +0 1 +.names g29105 II38217 +0 1 +.names g29102 II38220 +0 1 +.names g29106 II38223 +0 1 +.names g29108 II38226 +0 1 +.names g28950 II38229 +0 1 +.names g29117 II38232 +0 1 +.names g29118 II38235 +0 1 +.names g29119 II38238 +0 1 +.names g28832 II38241 +0 1 +.names g28662 g13322 g28920 +00 1 +.names g28920 II38245 +0 1 +.names II38245 g29168 +0 1 +.names g28663 g13343 g28941 +00 1 +.names g28941 II38250 +0 1 +.names II38250 g29171 +0 1 +.names g28664 g13365 g28963 +00 1 +.names g28963 II38258 +0 1 +.names II38258 g29177 +0 1 +.names g28671 g11607 g29013 +00 1 +.names g29013 II38272 +0 1 +.names II38272 g29189 +0 1 +.names g28666 g13390 g28987 +00 1 +.names g28987 II38275 +0 1 +.names II38275 g29190 +0 1 +.names g28963 II38278 +0 1 +.names II38278 g29191 +0 1 +.names g26673 g27241 g28323 g28954 +000 1 +.names g28954 g29192 +0 1 +.names g28941 II38282 +0 1 +.names II38282 g29193 +0 1 +.names g28381 g8907 g29113 +00 1 +.names g29113 II38321 +0 1 +.names II38321 g29230 +0 1 +.names g29120 II38330 +0 1 +.names II38330 g29237 +0 1 +.names g29120 II38339 +0 1 +.names II38339 g29244 +0 1 +.names g28659 g16277 g28886 +00 1 +.names g28886 II38342 +0 1 +.names II38342 g29245 +0 1 +.names g28654 g17001 g29109 +00 1 +.names g29109 II38345 +0 1 +.names II38345 g29246 +0 1 +.names g28657 g16221 g28874 +00 1 +.names g28874 II38348 +0 1 +.names II38348 g29247 +0 1 +.names g28656 g17031 g29110 +00 1 +.names g29110 II38352 +0 1 +.names II38352 g29249 +0 1 +.names g28322 g13500 g29039 +00 1 +.names g29039 II38355 +0 1 +.names II38355 g29250 +0 1 +.names g28658 g17065 g29111 +00 1 +.names g29111 II38360 +0 1 +.names II38360 g29253 +0 1 +.names g28672 g13487 g29016 +00 1 +.names g29016 II38363 +0 1 +.names II38363 g29254 +0 1 +.names g28661 g17100 g29112 +00 1 +.names g29112 II38369 +0 1 +.names II38369 g29258 +0 1 +.names g28741 g29266 +0 1 +.names g28734 II38386 +0 1 +.names II38386 g29267 +0 1 +.names g28751 g29268 +0 1 +.names g28755 g29269 +0 1 +.names g28730 II38391 +0 1 +.names II38391 g29270 +0 1 +.names g28764 g29271 +0 1 +.names g28768 g29272 +0 1 +.names g28727 II38396 +0 1 +.names II38396 g29273 +0 1 +.names g28775 g29274 +0 1 +.names g28779 g29275 +0 1 +.names g28725 II38401 +0 1 +.names II38401 g29276 +0 1 +.names g28785 g29277 +0 1 +.names g28723 II38405 +0 1 +.names II38405 g29278 +0 1 +.names g28721 II38408 +0 1 +.names II38408 g29279 +0 1 +.names g28791 g29280 +0 1 +.names g28720 II38412 +0 1 +.names II38412 g29281 +0 1 +.names g28796 g29282 +0 1 +.names g28799 g29283 +0 1 +.names g28804 g29285 +0 1 +.names g28807 g29286 +0 1 +.names g28810 g29287 +0 1 +.names g28740 II38421 +0 1 +.names II38421 g29288 +0 1 +.names g28814 g29290 +0 1 +.names g28817 g29291 +0 1 +.names g28820 g29292 +0 1 +.names g14894 g28426 g28732 +00 1 +.names g28732 II38428 +0 1 +.names II38428 g29293 +0 1 +.names g28823 g29295 +0 1 +.names g28826 g29296 +0 1 +.names g14957 g28430 g28735 +00 1 +.names g28735 II38434 +0 1 +.names II38434 g29297 +0 1 +.names g28427 g27913 g28736 +00 1 +.names g28736 II38437 +0 1 +.names II38437 g29298 +0 1 +.names g14975 g28433 g28738 +00 1 +.names g28738 II38440 +0 1 +.names II38440 g29299 +0 1 +.names g28829 g29301 +0 1 +.names g15030 g28439 g28744 +00 1 +.names g28744 II38447 +0 1 +.names II38447 g29304 +0 1 +.names g28431 g27922 g28745 +00 1 +.names g28745 II38450 +0 1 +.names II38450 g29305 +0 1 +.names g15046 g28441 g28746 +00 1 +.names g28746 II38453 +0 1 +.names II38453 g29306 +0 1 +.names g28434 g27923 g28747 +00 1 +.names g28747 II38456 +0 1 +.names II38456 g29307 +0 1 +.names g15064 g28444 g28749 +00 1 +.names g28749 II38459 +0 1 +.names II38459 g29308 +0 1 +.names g29120 II38462 +0 1 +.names II38462 g29309 +0 1 +.names g28440 g27931 g28754 +00 1 +.names g28754 II38466 +0 1 +.names II38466 g29311 +0 1 +.names g15126 g28451 g28758 +00 1 +.names g28758 II38471 +0 1 +.names II38471 g29314 +0 1 +.names g28442 g27935 g28759 +00 1 +.names g28759 II38474 +0 1 +.names II38474 g29315 +0 1 +.names g15142 g28453 g28760 +00 1 +.names g28760 II38477 +0 1 +.names II38477 g29316 +0 1 +.names g28445 g27936 g28761 +00 1 +.names g28761 II38480 +0 1 +.names II38480 g29317 +0 1 +.names g28667 g16457 g28990 +00 1 +.names g28990 II38483 +0 1 +.names II38483 g29318 +0 1 +.names g15160 g28456 g28763 +00 1 +.names g28763 II38486 +0 1 +.names II38486 g29319 +0 1 +.names g28452 g27945 g28767 +00 1 +.names g28767 II38491 +0 1 +.names II38491 g29322 +0 1 +.names g15218 g28463 g28771 +00 1 +.names g28771 II38496 +0 1 +.names II38496 g29325 +0 1 +.names g28454 g27949 g28772 +00 1 +.names g28772 II38499 +0 1 +.names II38499 g29326 +0 1 +.names g15234 g28465 g28773 +00 1 +.names g28773 II38502 +0 1 +.names II38502 g29327 +0 1 +.names g28457 g27951 g28774 +00 1 +.names g28774 II38505 +0 1 +.names II38505 g29328 +0 1 +.names g28464 g27963 g28778 +00 1 +.names g28778 II38510 +0 1 +.names II38510 g29331 +0 1 +.names g15304 g28475 g28782 +00 1 +.names g28782 II38515 +0 1 +.names II38515 g29334 +0 1 +.names g28466 g27968 g28783 +00 1 +.names g28783 II38518 +0 1 +.names II38518 g29335 +0 1 +.names g28476 g27984 g28788 +00 1 +.names g28788 II38524 +0 1 +.names II38524 g29339 +0 1 +.names g28920 II38536 +0 1 +.names II38536 g29349 +0 1 +.names g29113 II38539 +0 1 +.names II38539 g29350 +0 1 +.names g29120 g29356 +0 1 +.names g29120 g29358 +0 1 +.names g28660 g13295 g28903 +00 1 +.names g28903 II38548 +0 1 +.names II38548 g29359 +0 1 +.names g28871 g29360 +0 1 +.names g28877 g29361 +0 1 +.names g28883 g29362 +0 1 +.names g28889 g29363 +0 1 +.names g28894 g29364 +0 1 +.names g28900 g29365 +0 1 +.names g28906 g29366 +0 1 +.names g28911 g29367 +0 1 +.names g28916 g29368 +0 1 +.names g28925 g29369 +0 1 +.names g28928 g29370 +0 1 +.names g28932 g29371 +0 1 +.names g28937 g29372 +0 1 +.names g28945 g29373 +0 1 +.names g28951 g29374 +0 1 +.names g28955 g29375 +0 1 +.names g28959 g29376 +0 1 +.names g28967 g29377 +0 1 +.names g28972 g29378 +0 1 +.names g28975 g29379 +0 1 +.names g28979 g29380 +0 1 +.names g28983 g29381 +0 1 +.names g28993 g29382 +0 1 +.names g28998 g29383 +0 1 +.names g29002 g29384 +0 1 +.names g29005 g29385 +0 1 +.names g29010 g29386 +0 1 +.names g29019 g29387 +0 1 +.names g29023 g29388 +0 1 +.names g29027 g29389 +0 1 +.names g29032 g29390 +0 1 +.names g29035 g29391 +0 1 +.names g29042 g29392 +0 1 +.names g29046 g29393 +0 1 +.names g29050 g29394 +0 1 +.names g29054 g29395 +0 1 +.names g29057 g29396 +0 1 +.names g29065 g29397 +0 1 +.names g29069 g29398 +0 1 +.names g28987 II38591 +0 1 +.names II38591 g29400 +0 1 +.names g28990 II38594 +0 1 +.names II38594 g29401 +0 1 +.names g29077 g29402 +0 1 +.names g29013 II38599 +0 1 +.names II38599 g29404 +0 1 +.names g29016 II38602 +0 1 +.names II38602 g29405 +0 1 +.names g29039 II38606 +0 1 +.names II38606 g29407 +0 1 +.names g28874 II38609 +0 1 +.names II38609 g29408 +0 1 +.names g28886 II38613 +0 1 +.names II38613 g29410 +0 1 +.names g28903 II38617 +0 1 +.names II38617 g29412 +0 1 +.names g29246 II38620 +0 1 +.names g29293 II38623 +0 1 +.names g29297 II38626 +0 1 +.names g29304 II38629 +0 1 +.names g29298 II38632 +0 1 +.names g29305 II38635 +0 1 +.names g29311 II38638 +0 1 +.names g29249 II38641 +0 1 +.names g29299 II38644 +0 1 +.names g29306 II38647 +0 1 +.names g29314 II38650 +0 1 +.names g29307 II38653 +0 1 +.names g29315 II38656 +0 1 +.names g29322 II38659 +0 1 +.names g29253 II38662 +0 1 +.names g29412 II38665 +0 1 +.names g29168 II38668 +0 1 +.names g29171 II38671 +0 1 +.names g29177 II38674 +0 1 +.names g29400 II38677 +0 1 +.names g29404 II38680 +0 1 +.names g29308 II38683 +0 1 +.names g29316 II38686 +0 1 +.names g29325 II38689 +0 1 +.names g29317 II38692 +0 1 +.names g29326 II38695 +0 1 +.names g29331 II38698 +0 1 +.names g29401 II38701 +0 1 +.names g29405 II38704 +0 1 +.names g29407 II38707 +0 1 +.names g29408 II38710 +0 1 +.names g29410 II38713 +0 1 +.names g29230 II38716 +0 1 +.names g29258 II38719 +0 1 +.names g29319 II38722 +0 1 +.names g29327 II38725 +0 1 +.names g29334 II38728 +0 1 +.names g29328 II38731 +0 1 +.names g29335 II38734 +0 1 +.names g29339 II38737 +0 1 +.names g29288 II38740 +0 1 +.names g29267 II38743 +0 1 +.names g29270 II38746 +0 1 +.names g29273 II38749 +0 1 +.names g29276 II38752 +0 1 +.names g29278 II38755 +0 1 +.names g29279 II38758 +0 1 +.names g29281 II38761 +0 1 +.names g29237 II38764 +0 1 +.names g29244 II38767 +0 1 +.names g29309 II38770 +0 1 +.names g29350 g29491 +0 1 +.names g29358 II38801 +0 1 +.names II38801 g29495 +0 1 +.names g29126 g17001 g29353 +00 1 +.names g29353 II38804 +0 1 +.names II38804 g29496 +0 1 +.names g29356 II38807 +0 1 +.names II38807 g29497 +0 1 +.names g29127 g17031 g29354 +00 1 +.names g29354 II38817 +0 1 +.names II38817 g29499 +0 1 +.names g29128 g17065 g29355 +00 1 +.names g29355 II38827 +0 1 +.names II38827 g29501 +0 1 +.names g29129 g17100 g29357 +00 1 +.names g29357 II38838 +0 1 +.names II38838 g29504 +0 1 +.names g28841 g28396 g29167 +00 1 +.names g29167 II38848 +0 1 +.names II38848 g29506 +0 1 +.names g28843 g28398 g29169 +00 1 +.names g29169 II38851 +0 1 +.names II38851 g29507 +0 1 +.names g28844 g28399 g29170 +00 1 +.names g29170 II38854 +0 1 +.names II38854 g29508 +0 1 +.names g28846 g28401 g29172 +00 1 +.names g29172 II38857 +0 1 +.names II38857 g29509 +0 1 +.names g28847 g28402 g29173 +00 1 +.names g29173 II38860 +0 1 +.names II38860 g29510 +0 1 +.names g28848 g28404 g29178 +00 1 +.names g29178 II38863 +0 1 +.names II38863 g29511 +0 1 +.names g28849 g28405 g29179 +00 1 +.names g29179 II38866 +0 1 +.names II38866 g29512 +0 1 +.names g28850 g28407 g29181 +00 1 +.names g29181 II38869 +0 1 +.names II38869 g29513 +0 1 +.names g28851 g28408 g29182 +00 1 +.names g29182 II38872 +0 1 +.names II38872 g29514 +0 1 +.names g28852 g28411 g29184 +00 1 +.names g29184 II38875 +0 1 +.names II38875 g29515 +0 1 +.names g28853 g28412 g29185 +00 1 +.names g29185 II38878 +0 1 +.names II38878 g29516 +0 1 +.names g28854 g28416 g29187 +00 1 +.names g29187 II38881 +0 1 +.names II38881 g29517 +0 1 +.names g29192 II38885 +0 1 +.names II38885 g29519 +0 1 +.names g14958 g28881 g29194 +00 1 +.names g29194 II38898 +0 1 +.names II38898 g29530 +0 1 +.names g15031 g28893 g29197 +00 1 +.names g29197 II38905 +0 1 +.names II38905 g29535 +0 1 +.names g15047 g28898 g29198 +00 1 +.names g29198 II38909 +0 1 +.names II38909 g29537 +0 1 +.names g15104 g28910 g29201 +00 1 +.names g29201 II38916 +0 1 +.names II38916 g29542 +0 1 +.names g15127 g28915 g29204 +00 1 +.names g29204 II38920 +0 1 +.names II38920 g29544 +0 1 +.names g15143 g28923 g29205 +00 1 +.names g29205 II38924 +0 1 +.names II38924 g29546 +0 1 +.names g15196 g28936 g29209 +00 1 +.names g29209 II38931 +0 1 +.names II38931 g29551 +0 1 +.names g15219 g28944 g29212 +00 1 +.names g29212 II38936 +0 1 +.names II38936 g29554 +0 1 +.names g15235 g28949 g29213 +00 1 +.names g29213 II38940 +0 1 +.names II38940 g29556 +0 1 +.names g15282 g28966 g29218 +00 1 +.names g29218 II38947 +0 1 +.names II38947 g29561 +0 1 +.names g15305 g28971 g29221 +00 1 +.names g29221 II38951 +0 1 +.names II38951 g29563 +0 1 +.names g15374 g28997 g29226 +00 1 +.names g29226 II38958 +0 1 +.names II38958 g29568 +0 1 +.names g1942 g1939 g29113 g29348 +1-- 1 +-1- 1 +--1 1 +.names g29348 II38975 +0 1 +.names II38975 g29583 +0 1 +.names g29496 II38999 +0 1 +.names g29506 II39002 +0 1 +.names g29507 II39005 +0 1 +.names g29509 II39008 +0 1 +.names g29530 II39011 +0 1 +.names g29535 II39014 +0 1 +.names g29542 II39017 +0 1 +.names g29499 II39020 +0 1 +.names g29508 II39023 +0 1 +.names g29510 II39026 +0 1 +.names g29512 II39029 +0 1 +.names g29537 II39032 +0 1 +.names g29544 II39035 +0 1 +.names g29551 II39038 +0 1 +.names g29501 II39041 +0 1 +.names g29511 II39044 +0 1 +.names g29513 II39047 +0 1 +.names g29515 II39050 +0 1 +.names g29546 II39053 +0 1 +.names g29554 II39056 +0 1 +.names g29561 II39059 +0 1 +.names g29504 II39062 +0 1 +.names g29514 II39065 +0 1 +.names g29516 II39068 +0 1 +.names g29517 II39071 +0 1 +.names g29556 II39074 +0 1 +.names g29563 II39077 +0 1 +.names g29568 II39080 +0 1 +.names g29519 II39083 +0 1 +.names g29497 II39086 +0 1 +.names g29495 II39089 +0 1 +.names g28712 g29180 g29574 +00 1 +.names g29574 g29658 +0 1 +.names g28710 g29176 g29571 +00 1 +.names g29571 g29659 +0 1 +.names g28715 g29188 g29578 +00 1 +.names g29578 g29660 +0 1 +.names g28713 g29183 g29576 +00 1 +.names g29576 g29661 +0 1 +.names g28709 g29175 g29570 +00 1 +.names g29570 g29662 +0 1 +.names g29130 g29411 g29552 +00 1 +.names g29552 g29664 +0 1 +.names g28714 g29186 g29577 +00 1 +.names g29577 g29666 +0 1 +.names g28708 g29174 g29569 +00 1 +.names g29569 g29668 +0 1 +.names g29583 g29673 +0 1 +.names g29399 g17001 g29579 +00 1 +.names g29579 II39121 +0 1 +.names II39121 g29689 +0 1 +.names g13878 g29248 g29606 +00 1 +.names g29606 II39124 +0 1 +.names II39124 g29690 +0 1 +.names g13892 g29251 g29608 +00 1 +.names g29608 II39127 +0 1 +.names II39127 g29691 +0 1 +.names g29403 g17031 g29580 +00 1 +.names g29580 II39130 +0 1 +.names II39130 g29692 +0 1 +.names g13900 g29252 g29609 +00 1 +.names g29609 II39133 +0 1 +.names II39133 g29693 +0 1 +.names g13913 g29255 g29611 +00 1 +.names g29611 II39136 +0 1 +.names II39136 g29694 +0 1 +.names g13933 g29256 g29612 +00 1 +.names g29612 II39139 +0 1 +.names II39139 g29695 +0 1 +.names g29406 g17065 g29581 +00 1 +.names g29581 II39142 +0 1 +.names II39142 g29696 +0 1 +.names g13941 g29257 g29613 +00 1 +.names g29613 II39145 +0 1 +.names II39145 g29697 +0 1 +.names g13969 g29259 g29616 +00 1 +.names g29616 II39148 +0 1 +.names II39148 g29698 +0 1 +.names g13989 g29260 g29617 +00 1 +.names g29617 II39151 +0 1 +.names II39151 g29699 +0 1 +.names g29409 g17100 g29582 +00 1 +.names g29582 II39154 +0 1 +.names II39154 g29700 +0 1 +.names g13997 g29261 g29618 +00 1 +.names g29618 II39157 +0 1 +.names II39157 g29701 +0 1 +.names g14039 g29262 g29620 +00 1 +.names g29620 II39160 +0 1 +.names II39160 g29702 +0 1 +.names g14059 g29263 g29621 +00 1 +.names g29621 II39164 +0 1 +.names II39164 g29704 +0 1 +.names g14130 g29264 g29623 +00 1 +.names g29623 II39168 +0 1 +.names II39168 g29708 +0 1 +.names II38811 II38812 g29498 +0- 1 +-0 1 +.names g29498 g29716 +0 1 +.names II38821 II38822 g29500 +0- 1 +-0 1 +.names g29500 g29724 +0 1 +.names II38832 II38833 g29503 +0- 1 +-0 1 +.names g29503 g29726 +0 1 +.names II38842 II38843 g29505 +0- 1 +-0 1 +.names g29505 g29739 +0 1 +.names g29689 II39234 +0 1 +.names g29690 II39237 +0 1 +.names g29691 II39240 +0 1 +.names g29694 II39243 +0 1 +.names g29692 II39246 +0 1 +.names g29693 II39249 +0 1 +.names g29695 II39252 +0 1 +.names g29698 II39255 +0 1 +.names g29696 II39258 +0 1 +.names g29697 II39261 +0 1 +.names g29699 II39264 +0 1 +.names g29702 II39267 +0 1 +.names g29700 II39270 +0 1 +.names g29701 II39273 +0 1 +.names g29704 II39276 +0 1 +.names g29708 II39279 +0 1 +.names g29518 g29284 g29663 +00 1 +.names g29663 g29823 +0 1 +.names g29521 g29289 g29665 +00 1 +.names g29665 g29829 +0 1 +.names g29524 g29294 g29667 +00 1 +.names g29667 g29835 +0 1 +.names g29528 g29300 g29669 +00 1 +.names g29669 g29840 +0 1 +.names g29529 g29302 g29670 +00 1 +.names g29670 g29844 +0 1 +.names g28707 g28711 g29466 g29761 +000 1 +.names g29761 g29848 +0 1 +.names g29534 g29310 g29671 +00 1 +.names g29671 g29849 +0 1 +.names g29536 g29312 g29672 +00 1 +.names g29672 g29853 +0 1 +.names g29540 g29320 g29676 +00 1 +.names g29676 g29857 +0 1 +.names g29543 g29321 g29677 +00 1 +.names g29677 g29861 +0 1 +.names g29545 g29323 g29678 +00 1 +.names g29678 g29865 +0 1 +.names g29549 g29329 g29679 +00 1 +.names g29679 g29869 +0 1 +.names g29553 g29330 g29680 +00 1 +.names g29680 g29873 +0 1 +.names g29555 g29332 g29681 +00 1 +.names g29681 g29877 +0 1 +.names g29557 g29336 g29682 +00 1 +.names g29682 g29881 +0 1 +.names g29559 g29337 g29683 +00 1 +.names g29683 g29885 +0 1 +.names g29562 g29338 g29684 +00 1 +.names g29684 g29889 +0 1 +.names g29564 g29341 g29685 +00 1 +.names g29685 g29893 +0 1 +.names g29566 g29342 g29686 +00 1 +.names g29686 g29897 +0 1 +.names g29572 g29344 g29687 +00 1 +.names g29687 g29901 +0 1 +.names g29575 g29346 g29688 +00 1 +.names g29688 g29905 +0 1 +.names g29664 II39398 +0 1 +.names II39398 g29932 +0 1 +.names g29662 II39401 +0 1 +.names II39401 g29933 +0 1 +.names g29661 II39404 +0 1 +.names II39404 g29934 +0 1 +.names g29660 II39407 +0 1 +.names II39407 g29935 +0 1 +.names g29659 II39411 +0 1 +.names II39411 g29937 +0 1 +.names g29658 II39414 +0 1 +.names II39414 g29938 +0 1 +.names g29668 II39418 +0 1 +.names II39418 g29940 +0 1 +.names g29666 II39423 +0 1 +.names II39423 g29943 +0 1 +.names g29940 II39454 +0 1 +.names g29943 II39457 +0 1 +.names g29932 II39460 +0 1 +.names g29933 II39463 +0 1 +.names g29934 II39466 +0 1 +.names g29935 II39469 +0 1 +.names g29937 II39472 +0 1 +.names g29938 II39475 +0 1 +.names g24676 g29716 g29912 +00 1 +.names g29912 g30036 +0 1 +.names g24695 g29724 g29914 +00 1 +.names g29914 g30040 +0 1 +.names g24712 g29726 g29916 +00 1 +.names g29916 g30044 +0 1 +.names g24723 g29739 g29920 +00 1 +.names g29920 g30048 +0 1 +.names g29848 II39550 +0 1 +.names II39550 g30052 +0 1 +.names g16049 g29790 g29936 +00 1 +.names g29936 II39573 +0 1 +.names II39573 g30076 +0 1 +.names g16102 g29792 g29939 +00 1 +.names g29939 II39577 +0 1 +.names II39577 g30078 +0 1 +.names g16182 g29793 g29941 +00 1 +.names g29941 II39585 +0 1 +.names II39585 g30084 +0 1 +.names g30052 II39622 +0 1 +.names g30076 II39625 +0 1 +.names g30078 II39628 +0 1 +.names g30084 II39631 +0 1 +.names g29965 g13326 g30055 +00 1 +.names g30055 II39635 +0 1 +.names II39635 g30124 +0 1 +.names g29966 g13345 g30056 +00 1 +.names g30056 II39638 +0 1 +.names II39638 g30125 +0 1 +.names g29967 g13368 g30057 +00 1 +.names g30057 II39641 +0 1 +.names II39641 g30126 +0 1 +.names g29968 g13395 g30058 +00 1 +.names g30058 II39647 +0 1 +.names II39647 g30130 +0 1 +.names g29520 g29942 g30010 +00 1 +.names g30010 g30134 +0 1 +.names g29522 g29944 g30011 +00 1 +.names g30011 g30139 +0 1 +.names g29523 g29945 g30012 +00 1 +.names g30012 g30143 +0 1 +.names g29525 g29946 g30013 +00 1 +.names g30013 g30147 +0 1 +.names g29526 g29947 g30014 +00 1 +.names g30014 g30151 +0 1 +.names g29527 g29948 g30015 +00 1 +.names g30015 g30155 +0 1 +.names g29531 g29949 g30016 +00 1 +.names g30016 g30159 +0 1 +.names g29532 g29950 g30017 +00 1 +.names g30017 g30163 +0 1 +.names g29533 g29951 g30018 +00 1 +.names g30018 g30167 +0 1 +.names g29538 g29952 g30019 +00 1 +.names g30019 g30171 +0 1 +.names g29539 g29953 g30020 +00 1 +.names g30020 g30175 +0 1 +.names g29541 g29954 g30021 +00 1 +.names g30021 g30179 +0 1 +.names g29547 g29955 g30022 +00 1 +.names g30022 g30183 +0 1 +.names g29548 g29956 g30023 +00 1 +.names g30023 g30187 +0 1 +.names g29550 g29957 g30024 +00 1 +.names g30024 g30191 +0 1 +.names g29558 g29958 g30025 +00 1 +.names g30025 g30195 +0 1 +.names g29560 g29959 g30026 +00 1 +.names g30026 g30199 +0 1 +.names g29565 g29960 g30027 +00 1 +.names g30027 g30203 +0 1 +.names g29567 g29961 g30028 +00 1 +.names g30028 g30207 +0 1 +.names g29573 g29962 g30029 +00 1 +.names g30029 g30211 +0 1 +.names g29910 g8947 g30072 +00 1 +.names g30072 II39674 +0 1 +.names II39674 g30215 +0 1 +.names g24676 g29923 g30030 +00 1 +.names g30030 g30229 +0 1 +.names g24695 g29925 g30031 +00 1 +.names g30031 g30233 +0 1 +.names g24712 g29927 g30032 +00 1 +.names g30032 g30237 +0 1 +.names g24723 g29931 g30033 +00 1 +.names g30033 g30241 +0 1 +.names g30072 II39761 +0 1 +.names II39761 g30306 +0 1 +.names g29970 g11612 g30060 +00 1 +.names g30060 II39764 +0 1 +.names II39764 g30307 +0 1 +.names g29971 g13493 g30061 +00 1 +.names g30061 II39767 +0 1 +.names II39767 g30308 +0 1 +.names g29812 g11637 g30063 +00 1 +.names g30063 II39770 +0 1 +.names II39770 g30309 +0 1 +.names g29813 g13506 g30064 +00 1 +.names g30064 II39773 +0 1 +.names II39773 g30310 +0 1 +.names g29816 g13517 g30066 +00 1 +.names g30066 II39776 +0 1 +.names II39776 g30311 +0 1 +.names g29963 g16286 g30053 +00 1 +.names g30053 II39779 +0 1 +.names II39779 g30312 +0 1 +.names g29964 g16336 g30054 +00 1 +.names g30054 II39782 +0 1 +.names II39782 g30313 +0 1 +.names g30124 II39785 +0 1 +.names g30125 II39788 +0 1 +.names g30126 II39791 +0 1 +.names g30130 II39794 +0 1 +.names g30307 II39797 +0 1 +.names g30309 II39800 +0 1 +.names g30308 II39803 +0 1 +.names g30310 II39806 +0 1 +.names g30311 II39809 +0 1 +.names g30312 II39812 +0 1 +.names g30313 II39815 +0 1 +.names g30215 II39818 +0 1 +.names g16380 g30101 g30267 +00 1 +.names g30267 II39821 +0 1 +.names II39821 g30326 +0 1 +.names g16382 g30102 g30268 +00 1 +.names g30268 II39825 +0 1 +.names II39825 g30328 +0 1 +.names g16386 g30103 g30269 +00 1 +.names g30269 II39828 +0 1 +.names II39828 g30329 +0 1 +.names g16387 g30104 g30270 +00 1 +.names g30270 II39832 +0 1 +.names II39832 g30331 +0 1 +.names g16388 g30105 g30271 +00 1 +.names g30271 II39835 +0 1 +.names II39835 g30332 +0 1 +.names g16392 g30106 g30272 +00 1 +.names g30272 II39840 +0 1 +.names II39840 g30335 +0 1 +.names g16393 g30107 g30273 +00 1 +.names g30273 II39843 +0 1 +.names II39843 g30336 +0 1 +.names g16403 g30108 g30274 +00 1 +.names g30274 II39848 +0 1 +.names II39848 g30339 +0 1 +.names g16413 g30109 g30275 +00 1 +.names g30275 II39853 +0 1 +.names II39853 g30342 +0 1 +.names g16415 g30110 g30276 +00 1 +.names g30276 II39856 +0 1 +.names II39856 g30343 +0 1 +.names g16418 g30111 g30277 +00 1 +.names g30277 II39859 +0 1 +.names II39859 g30344 +0 1 +.names g16420 g30112 g30278 +00 1 +.names g30278 II39863 +0 1 +.names II39863 g30346 +0 1 +.names g16424 g30113 g30279 +00 1 +.names g30279 II39866 +0 1 +.names II39866 g30347 +0 1 +.names g16425 g30114 g30280 +00 1 +.names g30280 II39870 +0 1 +.names II39870 g30349 +0 1 +.names g16426 g30115 g30281 +00 1 +.names g30281 II39873 +0 1 +.names II39873 g30350 +0 1 +.names g16430 g30117 g30282 +00 1 +.names g30282 II39878 +0 1 +.names II39878 g30353 +0 1 +.names g16431 g30118 g30283 +00 1 +.names g30283 II39881 +0 1 +.names II39881 g30354 +0 1 +.names g16444 g29980 g30284 +00 1 +.names g30284 II39886 +0 1 +.names II39886 g30357 +0 1 +.names g16447 g29981 g30285 +00 1 +.names g30285 II39889 +0 1 +.names II39889 g30358 +0 1 +.names g16449 g29982 g30286 +00 1 +.names g30286 II39892 +0 1 +.names II39892 g30359 +0 1 +.names g16452 g29983 g30287 +00 1 +.names g30287 II39895 +0 1 +.names II39895 g30360 +0 1 +.names g16454 g29984 g30288 +00 1 +.names g30288 II39899 +0 1 +.names II39899 g30362 +0 1 +.names g16458 g29985 g30289 +00 1 +.names g30289 II39902 +0 1 +.names II39902 g30363 +0 1 +.names g16459 g29986 g30290 +00 1 +.names g30290 II39906 +0 1 +.names II39906 g30365 +0 1 +.names g16460 g29987 g30291 +00 1 +.names g30291 II39909 +0 1 +.names II39909 g30366 +0 1 +.names g13477 g29988 g30292 +00 1 +.names g30292 II39913 +0 1 +.names II39913 g30368 +0 1 +.names g13480 g29989 g30293 +00 1 +.names g30293 II39916 +0 1 +.names II39916 g30369 +0 1 +.names g13483 g29990 g30294 +00 1 +.names g30294 II39919 +0 1 +.names II39919 g30370 +0 1 +.names g13485 g29991 g30295 +00 1 +.names g30295 II39922 +0 1 +.names II39922 g30371 +0 1 +.names g13488 g29993 g30296 +00 1 +.names g30296 II39926 +0 1 +.names II39926 g30373 +0 1 +.names g13490 g29994 g30297 +00 1 +.names g30297 II39930 +0 1 +.names II39930 g30375 +0 1 +.names g13496 g29995 g30298 +00 1 +.names g30298 II39933 +0 1 +.names II39933 g30376 +0 1 +.names g13499 g29996 g30299 +00 1 +.names g30299 II39936 +0 1 +.names II39936 g30377 +0 1 +.names g13502 g30001 g30300 +00 1 +.names g30300 II39939 +0 1 +.names II39939 g30378 +0 1 +.names g13504 g30002 g30301 +00 1 +.names g30301 II39942 +0 1 +.names II39942 g30379 +0 1 +.names g13513 g30003 g30302 +00 1 +.names g30302 II39945 +0 1 +.names II39945 g30380 +0 1 +.names g13516 g30005 g30303 +00 1 +.names g30303 II39948 +0 1 +.names II39948 g30381 +0 1 +.names g13527 g30007 g30304 +00 1 +.names g30304 II39951 +0 1 +.names II39951 g30382 +0 1 +.names g30306 g30383 +0 1 +.names g16074 g30077 g30245 +00 1 +.names g30245 II39976 +0 1 +.names II39976 g30408 +0 1 +.names g2636 g2633 g30072 g30305 +1-- 1 +-1- 1 +--1 1 +.names g30305 II39982 +0 1 +.names II39982 g30412 +0 1 +.names g16107 g30079 g30246 +00 1 +.names g30246 II39985 +0 1 +.names II39985 g30435 +0 1 +.names g16112 g30080 g30247 +00 1 +.names g30247 II39991 +0 1 +.names II39991 g30439 +0 1 +.names g16139 g30081 g30248 +00 1 +.names g30248 II39997 +0 1 +.names II39997 g30443 +0 1 +.names g16158 g30082 g30249 +00 1 +.names g30249 II40002 +0 1 +.names II40002 g30446 +0 1 +.names g16163 g30083 g30250 +00 1 +.names g30250 II40008 +0 1 +.names II40008 g30450 +0 1 +.names g16198 g30085 g30251 +00 1 +.names g30251 II40016 +0 1 +.names II40016 g30456 +0 1 +.names g16217 g30086 g30252 +00 1 +.names g30252 II40021 +0 1 +.names II40021 g30459 +0 1 +.names g16222 g30087 g30253 +00 1 +.names g30253 II40027 +0 1 +.names II40027 g30463 +0 1 +.names g16242 g30088 g30254 +00 1 +.names g30254 II40032 +0 1 +.names II40032 g30466 +0 1 +.names g16263 g30089 g30255 +00 1 +.names g30255 II40039 +0 1 +.names II40039 g30471 +0 1 +.names g16282 g30090 g30256 +00 1 +.names g30256 II40044 +0 1 +.names II40044 g30474 +0 1 +.names g16290 g30091 g30257 +00 1 +.names g30257 II40051 +0 1 +.names II40051 g30479 +0 1 +.names g16291 g30092 g30258 +00 1 +.names g30258 II40054 +0 1 +.names II40054 g30480 +0 1 +.names g16301 g30093 g30259 +00 1 +.names g30259 II40059 +0 1 +.names II40059 g30483 +0 1 +.names g16322 g30094 g30260 +00 1 +.names g30260 II40066 +0 1 +.names II40066 g30488 +0 1 +.names g16342 g30095 g30261 +00 1 +.names g30261 II40071 +0 1 +.names II40071 g30491 +0 1 +.names g16343 g30096 g30262 +00 1 +.names g30262 II40075 +0 1 +.names II40075 g30493 +0 1 +.names g16344 g30097 g30263 +00 1 +.names g30263 II40078 +0 1 +.names II40078 g30494 +0 1 +.names g16348 g30098 g30264 +00 1 +.names g30264 II40083 +0 1 +.names II40083 g30497 +0 1 +.names g16349 g30099 g30265 +00 1 +.names g30265 II40086 +0 1 +.names II40086 g30498 +0 1 +.names g16359 g30100 g30266 +00 1 +.names g30266 II40091 +0 1 +.names II40091 g30501 +0 1 +.names g30491 II40098 +0 1 +.names g30326 II40101 +0 1 +.names g30342 II40104 +0 1 +.names g30343 II40107 +0 1 +.names g30357 II40110 +0 1 +.names g30368 II40113 +0 1 +.names g30408 II40116 +0 1 +.names g30435 II40119 +0 1 +.names g30443 II40122 +0 1 +.names g30466 II40125 +0 1 +.names g30479 II40128 +0 1 +.names g30493 II40131 +0 1 +.names g30480 II40134 +0 1 +.names g30494 II40137 +0 1 +.names g30328 II40140 +0 1 +.names g30329 II40143 +0 1 +.names g30344 II40146 +0 1 +.names g30358 II40149 +0 1 +.names g30359 II40152 +0 1 +.names g30369 II40155 +0 1 +.names g30376 II40158 +0 1 +.names g30439 II40161 +0 1 +.names g30446 II40164 +0 1 +.names g30456 II40167 +0 1 +.names g30483 II40170 +0 1 +.names g30497 II40173 +0 1 +.names g30331 II40176 +0 1 +.names g30498 II40179 +0 1 +.names g30332 II40182 +0 1 +.names g30346 II40185 +0 1 +.names g30347 II40188 +0 1 +.names g30360 II40191 +0 1 +.names g30370 II40194 +0 1 +.names g30371 II40197 +0 1 +.names g30377 II40200 +0 1 +.names g30380 II40203 +0 1 +.names g30450 II40206 +0 1 +.names g30459 II40209 +0 1 +.names g30471 II40212 +0 1 +.names g30501 II40215 +0 1 +.names g30335 II40218 +0 1 +.names g30349 II40221 +0 1 +.names g30336 II40224 +0 1 +.names g30350 II40227 +0 1 +.names g30362 II40230 +0 1 +.names g30363 II40233 +0 1 +.names g30373 II40236 +0 1 +.names g30378 II40239 +0 1 +.names g30379 II40242 +0 1 +.names g30381 II40245 +0 1 +.names g30382 II40248 +0 1 +.names g30463 II40251 +0 1 +.names g30474 II40254 +0 1 +.names g30488 II40257 +0 1 +.names g30339 II40260 +0 1 +.names g30353 II40263 +0 1 +.names g30365 II40266 +0 1 +.names g30354 II40269 +0 1 +.names g30366 II40272 +0 1 +.names g30375 II40275 +0 1 +.names g30004 g30131 g30403 +00 1 +.names g30403 g30567 +0 1 +.names g29999 g30129 g30402 +00 1 +.names g30402 g30568 +0 1 +.names g30009 g30138 g30406 +00 1 +.names g30406 g30569 +0 1 +.names g30006 g30132 g30404 +00 1 +.names g30404 g30570 +0 1 +.names g29998 g30128 g30401 +00 1 +.names g30401 g30571 +0 1 +.names g30116 g30123 g30399 +00 1 +.names g30399 g30572 +0 1 +.names g30008 g30133 g30405 +00 1 +.names g30405 g30573 +0 1 +.names g29997 g30127 g30400 +00 1 +.names g30400 g30574 +0 1 +.names g30412 g30575 +0 1 +.names g13953 g30216 g30455 +00 1 +.names g30455 II40288 +0 1 +.names II40288 g30578 +0 1 +.names g14007 g30217 g30468 +00 1 +.names g30468 II40291 +0 1 +.names II40291 g30579 +0 1 +.names g14023 g30218 g30470 +00 1 +.names g30470 II40294 +0 1 +.names II40294 g30580 +0 1 +.names g14067 g30219 g30482 +00 1 +.names g30482 II40297 +0 1 +.names II40297 g30581 +0 1 +.names g14098 g30220 g30485 +00 1 +.names g30485 II40300 +0 1 +.names II40300 g30582 +0 1 +.names g14114 g30221 g30487 +00 1 +.names g30487 II40303 +0 1 +.names II40303 g30583 +0 1 +.names g14182 g30222 g30500 +00 1 +.names g30500 II40307 +0 1 +.names II40307 g30585 +0 1 +.names g14213 g30223 g30503 +00 1 +.names g30503 II40310 +0 1 +.names II40310 g30586 +0 1 +.names g14229 g30224 g30505 +00 1 +.names g30505 II40313 +0 1 +.names II40313 g30587 +0 1 +.names g14297 g30225 g30338 +00 1 +.names g30338 II40317 +0 1 +.names II40317 g30591 +0 1 +.names g14328 g30226 g30341 +00 1 +.names g30341 II40320 +0 1 +.names II40320 g30592 +0 1 +.names g14419 g30227 g30356 +00 1 +.names g30356 II40326 +0 1 +.names II40326 g30600 +0 1 +.names g30578 II40420 +0 1 +.names g30579 II40423 +0 1 +.names g30581 II40426 +0 1 +.names g30580 II40429 +0 1 +.names g30582 II40432 +0 1 +.names g30585 II40435 +0 1 +.names g30583 II40438 +0 1 +.names g30586 II40441 +0 1 +.names g30591 II40444 +0 1 +.names g30587 II40447 +0 1 +.names g30592 II40450 +0 1 +.names g30600 II40453 +0 1 +.names g16381 g30478 g30668 +00 1 +.names g30668 II40456 +0 1 +.names II40456 g30722 +0 1 +.names g16383 g30481 g30669 +00 1 +.names g30669 II40459 +0 1 +.names II40459 g30723 +0 1 +.names g16389 g30484 g30670 +00 1 +.names g30670 II40462 +0 1 +.names II40462 g30724 +0 1 +.names g16391 g30486 g30671 +00 1 +.names g30671 II40465 +0 1 +.names II40465 g30725 +0 1 +.names g16401 g30489 g30672 +00 1 +.names g30672 II40468 +0 1 +.names II40468 g30726 +0 1 +.names g16402 g30490 g30673 +00 1 +.names g30673 II40471 +0 1 +.names II40471 g30727 +0 1 +.names g16414 g30492 g30674 +00 1 +.names g30674 II40475 +0 1 +.names II40475 g30729 +0 1 +.names g16416 g30495 g30675 +00 1 +.names g30675 II40478 +0 1 +.names II40478 g30730 +0 1 +.names g16419 g30496 g30676 +00 1 +.names g30676 II40481 +0 1 +.names II40481 g30731 +0 1 +.names g16421 g30499 g30677 +00 1 +.names g30677 II40484 +0 1 +.names II40484 g30732 +0 1 +.names g16427 g30502 g30678 +00 1 +.names g30678 II40487 +0 1 +.names II40487 g30733 +0 1 +.names g16429 g30504 g30679 +00 1 +.names g30679 II40490 +0 1 +.names II40490 g30734 +0 1 +.names g16443 g30327 g30680 +00 1 +.names g30680 II40495 +0 1 +.names II40495 g30737 +0 1 +.names g16448 g30330 g30681 +00 1 +.names g30681 II40498 +0 1 +.names II40498 g30738 +0 1 +.names g16450 g30333 g30682 +00 1 +.names g30682 II40501 +0 1 +.names II40501 g30739 +0 1 +.names g16453 g30334 g30683 +00 1 +.names g30683 II40504 +0 1 +.names II40504 g30740 +0 1 +.names g16455 g30337 g30684 +00 1 +.names g30684 II40507 +0 1 +.names II40507 g30741 +0 1 +.names g16461 g30340 g30686 +00 1 +.names g30686 II40510 +0 1 +.names II40510 g30742 +0 1 +.names g13479 g30345 g30687 +00 1 +.names g30687 II40515 +0 1 +.names II40515 g30745 +0 1 +.names g13484 g30348 g30688 +00 1 +.names g30688 II40518 +0 1 +.names II40518 g30746 +0 1 +.names g13486 g30351 g30689 +00 1 +.names g30689 II40521 +0 1 +.names II40521 g30747 +0 1 +.names g13489 g30352 g30690 +00 1 +.names g30690 II40524 +0 1 +.names II40524 g30748 +0 1 +.names g13491 g30355 g30691 +00 1 +.names g30691 II40527 +0 1 +.names II40527 g30749 +0 1 +.names g13498 g30361 g30692 +00 1 +.names g30692 II40531 +0 1 +.names II40531 g30751 +0 1 +.names g13503 g30364 g30693 +00 1 +.names g30693 II40534 +0 1 +.names II40534 g30752 +0 1 +.names g13505 g30367 g30694 +00 1 +.names g30694 II40537 +0 1 +.names II40537 g30753 +0 1 +.names g13515 g30374 g30695 +00 1 +.names g30695 II40542 +0 1 +.names II40542 g30756 +0 1 +.names g29992 g30000 g30372 g30685 +000 1 +.names g30685 g30765 +0 1 +.names g13914 g30387 g30699 +00 1 +.names g30699 II40555 +0 1 +.names II40555 g30767 +0 1 +.names g13952 g30388 g30700 +00 1 +.names g30700 II40565 +0 1 +.names II40565 g30769 +0 1 +.names g13970 g30389 g30701 +00 1 +.names g30701 II40568 +0 1 +.names II40568 g30770 +0 1 +.names g14006 g30390 g30702 +00 1 +.names g30702 II40578 +0 1 +.names II40578 g30772 +0 1 +.names g14022 g30391 g30703 +00 1 +.names g30703 II40581 +0 1 +.names II40581 g30773 +0 1 +.names g14040 g30392 g30704 +00 1 +.names g30704 II40584 +0 1 +.names II40584 g30774 +0 1 +.names g14097 g30393 g30705 +00 1 +.names g30705 II40594 +0 1 +.names II40594 g30776 +0 1 +.names g14113 g30394 g30706 +00 1 +.names g30706 II40597 +0 1 +.names II40597 g30777 +0 1 +.names g14131 g30395 g30707 +00 1 +.names g30707 II40600 +0 1 +.names II40600 g30778 +0 1 +.names g14212 g30396 g30708 +00 1 +.names g30708 II40611 +0 1 +.names II40611 g30781 +0 1 +.names g14228 g30397 g30709 +00 1 +.names g30709 II40614 +0 1 +.names II40614 g30782 +0 1 +.names g14327 g30398 g30566 +00 1 +.names g30566 II40618 +0 1 +.names II40618 g30784 +0 1 +.names g30571 II40634 +0 1 +.names II40634 g30792 +0 1 +.names g30570 II40637 +0 1 +.names II40637 g30793 +0 1 +.names g30569 II40640 +0 1 +.names II40640 g30794 +0 1 +.names g30568 II40643 +0 1 +.names II40643 g30795 +0 1 +.names g30567 II40647 +0 1 +.names II40647 g30797 +0 1 +.names g30574 II40651 +0 1 +.names II40651 g30799 +0 1 +.names g30573 II40654 +0 1 +.names II40654 g30800 +0 1 +.names g30572 II40658 +0 1 +.names II40658 g30802 +0 1 +.names g16108 g30407 g30635 +00 1 +.names g30635 II40661 +0 1 +.names II40661 g30803 +0 1 +.names g16140 g30409 g30636 +00 1 +.names g30636 II40664 +0 1 +.names II40664 g30804 +0 1 +.names g16141 g30410 g30637 +00 1 +.names g30637 II40667 +0 1 +.names II40667 g30805 +0 1 +.names g16159 g30411 g30638 +00 1 +.names g30638 II40670 +0 1 +.names II40670 g30806 +0 1 +.names g16186 g30436 g30639 +00 1 +.names g30639 II40673 +0 1 +.names II40673 g30807 +0 1 +.names g16187 g30437 g30640 +00 1 +.names g30640 II40676 +0 1 +.names II40676 g30808 +0 1 +.names g16188 g30438 g30641 +00 1 +.names g30641 II40679 +0 1 +.names II40679 g30809 +0 1 +.names g16199 g30440 g30642 +00 1 +.names g30642 II40682 +0 1 +.names II40682 g30810 +0 1 +.names g16200 g30441 g30643 +00 1 +.names g30643 II40685 +0 1 +.names II40685 g30811 +0 1 +.names g16218 g30442 g30644 +00 1 +.names g30644 II40688 +0 1 +.names II40688 g30812 +0 1 +.names g16240 g30444 g30645 +00 1 +.names g30645 II40691 +0 1 +.names II40691 g30813 +0 1 +.names g16241 g30445 g30646 +00 1 +.names g30646 II40694 +0 1 +.names II40694 g30814 +0 1 +.names g16251 g30447 g30647 +00 1 +.names g30647 II40697 +0 1 +.names II40697 g30815 +0 1 +.names g16252 g30448 g30648 +00 1 +.names g30648 II40700 +0 1 +.names II40700 g30816 +0 1 +.names g16253 g30449 g30649 +00 1 +.names g30649 II40703 +0 1 +.names II40703 g30817 +0 1 +.names g16264 g30451 g30650 +00 1 +.names g30650 II40706 +0 1 +.names II40706 g30818 +0 1 +.names g16265 g30452 g30651 +00 1 +.names g30651 II40709 +0 1 +.names II40709 g30819 +0 1 +.names g16283 g30453 g30652 +00 1 +.names g30652 II40712 +0 1 +.names II40712 g30820 +0 1 +.names g16289 g30454 g30653 +00 1 +.names g30653 II40715 +0 1 +.names II40715 g30821 +0 1 +.names g16299 g30457 g30654 +00 1 +.names g30654 II40718 +0 1 +.names II40718 g30822 +0 1 +.names g16300 g30458 g30655 +00 1 +.names g30655 II40721 +0 1 +.names II40721 g30823 +0 1 +.names g16310 g30460 g30656 +00 1 +.names g30656 II40724 +0 1 +.names II40724 g30824 +0 1 +.names g16311 g30461 g30657 +00 1 +.names g30657 II40727 +0 1 +.names II40727 g30825 +0 1 +.names g16312 g30462 g30658 +00 1 +.names g30658 II40730 +0 1 +.names II40730 g30826 +0 1 +.names g16323 g30464 g30659 +00 1 +.names g30659 II40733 +0 1 +.names II40733 g30827 +0 1 +.names g16324 g30465 g30660 +00 1 +.names g30660 II40736 +0 1 +.names II40736 g30828 +0 1 +.names g16345 g30467 g30661 +00 1 +.names g30661 II40739 +0 1 +.names II40739 g30829 +0 1 +.names g16347 g30469 g30662 +00 1 +.names g30662 II40742 +0 1 +.names II40742 g30830 +0 1 +.names g16357 g30472 g30663 +00 1 +.names g30663 II40745 +0 1 +.names II40745 g30831 +0 1 +.names g16358 g30473 g30664 +00 1 +.names g30664 II40748 +0 1 +.names II40748 g30832 +0 1 +.names g16368 g30475 g30665 +00 1 +.names g30665 II40751 +0 1 +.names II40751 g30833 +0 1 +.names g16369 g30476 g30666 +00 1 +.names g30666 II40754 +0 1 +.names II40754 g30834 +0 1 +.names g16370 g30477 g30667 +00 1 +.names g30667 II40757 +0 1 +.names II40757 g30835 +0 1 +.names g30722 II40760 +0 1 +.names g30729 II40763 +0 1 +.names g30737 II40766 +0 1 +.names g30803 II40769 +0 1 +.names g30804 II40772 +0 1 +.names g30807 II40775 +0 1 +.names g30805 II40778 +0 1 +.names g30808 II40781 +0 1 +.names g30813 II40784 +0 1 +.names g30809 II40787 +0 1 +.names g30814 II40790 +0 1 +.names g30821 II40793 +0 1 +.names g30829 II40796 +0 1 +.names g30723 II40799 +0 1 +.names g30730 II40802 +0 1 +.names g30767 II40805 +0 1 +.names g30769 II40808 +0 1 +.names g30772 II40811 +0 1 +.names g30731 II40814 +0 1 +.names g30738 II40817 +0 1 +.names g30745 II40820 +0 1 +.names g30806 II40823 +0 1 +.names g30810 II40826 +0 1 +.names g30815 II40829 +0 1 +.names g30811 II40832 +0 1 +.names g30816 II40835 +0 1 +.names g30822 II40838 +0 1 +.names g30817 II40841 +0 1 +.names g30823 II40844 +0 1 +.names g30830 II40847 +0 1 +.names g30724 II40850 +0 1 +.names g30732 II40853 +0 1 +.names g30739 II40856 +0 1 +.names g30770 II40859 +0 1 +.names g30773 II40862 +0 1 +.names g30776 II40865 +0 1 +.names g30740 II40868 +0 1 +.names g30746 II40871 +0 1 +.names g30751 II40874 +0 1 +.names g30812 II40877 +0 1 +.names g30818 II40880 +0 1 +.names g30824 II40883 +0 1 +.names g30819 II40886 +0 1 +.names g30825 II40889 +0 1 +.names g30831 II40892 +0 1 +.names g30826 II40895 +0 1 +.names g30832 II40898 +0 1 +.names g30725 II40901 +0 1 +.names g30733 II40904 +0 1 +.names g30741 II40907 +0 1 +.names g30747 II40910 +0 1 +.names g30774 II40913 +0 1 +.names g30777 II40916 +0 1 +.names g30781 II40919 +0 1 +.names g30748 II40922 +0 1 +.names g30752 II40925 +0 1 +.names g30756 II40928 +0 1 +.names g30820 II40931 +0 1 +.names g30827 II40934 +0 1 +.names g30833 II40937 +0 1 +.names g30828 II40940 +0 1 +.names g30834 II40943 +0 1 +.names g30726 II40946 +0 1 +.names g30835 II40949 +0 1 +.names g30727 II40952 +0 1 +.names g30734 II40955 +0 1 +.names g30742 II40958 +0 1 +.names g30749 II40961 +0 1 +.names g30753 II40964 +0 1 +.names g30778 II40967 +0 1 +.names g30782 II40970 +0 1 +.names g30784 II40973 +0 1 +.names g30799 II40976 +0 1 +.names g30800 II40979 +0 1 +.names g30802 II40982 +0 1 +.names g30792 II40985 +0 1 +.names g30793 II40988 +0 1 +.names g30794 II40991 +0 1 +.names g30795 II40994 +0 1 +.names g30797 II40997 +0 1 +.names g30765 II41024 +0 1 +.names II41024 g30928 +0 1 +.names g16069 g30696 g30796 +00 1 +.names g30796 II41035 +0 1 +.names II41035 g30937 +0 1 +.names g16134 g30697 g30798 +00 1 +.names g30798 II41038 +0 1 +.names II41038 g30938 +0 1 +.names g16237 g30698 g30801 +00 1 +.names g30801 II41041 +0 1 +.names II41041 g30939 +0 1 +.names g30928 II41044 +0 1 +.names g30937 II41047 +0 1 +.names g30938 II41050 +0 1 +.names g30939 II41053 +0 1 +.names g30922 g30948 g30958 +00 1 +.names g30958 g30962 +0 1 +.names g30920 g30947 g30957 +00 1 +.names g30957 g30963 +0 1 +.names g30925 g30951 g30961 +00 1 +.names g30961 g30964 +0 1 +.names g30923 g30949 g30959 +00 1 +.names g30959 g30965 +0 1 +.names g30919 g30946 g30956 +00 1 +.names g30956 g30966 +0 1 +.names g30916 g30944 g30954 +00 1 +.names g30954 g30967 +0 1 +.names g30924 g30950 g30960 +00 1 +.names g30960 g30968 +0 1 +.names g30918 g30945 g30955 +00 1 +.names g30955 g30969 +0 1 +.names g30917 g30921 g30953 g30970 +000 1 +.names g30970 g30971 +0 1 +.names g30965 II41090 +0 1 +.names II41090 g30972 +0 1 +.names g30964 II41093 +0 1 +.names II41093 g30973 +0 1 +.names g30963 II41096 +0 1 +.names II41096 g30974 +0 1 +.names g30962 II41099 +0 1 +.names II41099 g30975 +0 1 +.names g30969 II41102 +0 1 +.names II41102 g30976 +0 1 +.names g30968 II41105 +0 1 +.names II41105 g30977 +0 1 +.names g30967 II41108 +0 1 +.names II41108 g30978 +0 1 +.names g30966 II41111 +0 1 +.names II41111 g30979 +0 1 +.names g30976 II41114 +0 1 +.names g30977 II41117 +0 1 +.names g30978 II41120 +0 1 +.names g30979 II41123 +0 1 +.names g30972 II41126 +0 1 +.names g30973 II41129 +0 1 +.names g30974 II41132 +0 1 +.names g30975 II41135 +0 1 +.names g30971 II41138 +0 1 +.names II41138 g30988 +0 1 +.names g30988 II41141 +0 1 +.names g325 g349 g5630 +11 1 +.names g331 g351 g5649 +11 1 +.names g325 g364 g5650 +11 1 +.names g1012 g1036 g5658 +11 1 +.names g337 g353 g5676 +11 1 +.names g331 g366 g5677 +11 1 +.names g325 g379 g5678 +11 1 +.names g1018 g1038 g5687 +11 1 +.names g1012 g1051 g5688 +11 1 +.names g1706 g1730 g5696 +11 1 +.names g337 g368 g5709 +11 1 +.names g331 g381 g5710 +11 1 +.names g325 g394 g5711 +11 1 +.names g1024 g1040 g5728 +11 1 +.names g1018 g1053 g5729 +11 1 +.names g1012 g1066 g5730 +11 1 +.names g1712 g1732 g5739 +11 1 +.names g1706 g1745 g5740 +11 1 +.names g2400 g2424 g5748 +11 1 +.names g337 g383 g5757 +11 1 +.names g331 g396 g5758 +11 1 +.names g1024 g1055 g5767 +11 1 +.names g1018 g1068 g5768 +11 1 +.names g1012 g1081 g5769 +11 1 +.names g1718 g1734 g5786 +11 1 +.names g1712 g1747 g5787 +11 1 +.names g1706 g1760 g5788 +11 1 +.names g2406 g2426 g5797 +11 1 +.names g2400 g2439 g5798 +11 1 +.names g337 g324 g5807 +11 1 +.names g1024 g1070 g5816 +11 1 +.names g1018 g1083 g5817 +11 1 +.names g1718 g1749 g5826 +11 1 +.names g1712 g1762 g5827 +11 1 +.names g1706 g1775 g5828 +11 1 +.names g2412 g2428 g5845 +11 1 +.names g2406 g2441 g5846 +11 1 +.names g2400 g2454 g5847 +11 1 +.names g1024 g1011 g5863 +11 1 +.names g1718 g1764 g5872 +11 1 +.names g1712 g1777 g5873 +11 1 +.names g2412 g2443 g5882 +11 1 +.names g2406 g2456 g5883 +11 1 +.names g2400 g2469 g5884 +11 1 +.names g1718 g1705 g5910 +11 1 +.names g2412 g2458 g5919 +11 1 +.names g2406 g2471 g5920 +11 1 +.names g2412 g2399 g5949 +11 1 +.names g3254 g219 g8327 +11 1 +.names g6314 g225 g8328 +11 1 +.names g6232 g231 g8329 +11 1 +.names g6519 g903 g8339 +11 1 +.names g6369 g909 g8340 +11 1 +.names g6574 g1594 g8350 +11 1 +.names g3254 g228 g8385 +11 1 +.names g6314 g234 g8386 +11 1 +.names g6232 g240 g8387 +11 1 +.names g3410 g906 g8394 +11 1 +.names g6519 g912 g8395 +11 1 +.names g6369 g918 g8396 +11 1 +.names g6783 g1597 g8406 +11 1 +.names g6574 g1603 g8407 +11 1 +.names g6838 g2288 g8417 +11 1 +.names g3254 g237 g8431 +11 1 +.names g6314 g243 g8432 +11 1 +.names g6232 g249 g8433 +11 1 +.names g3410 g915 g8437 +11 1 +.names g6519 g921 g8438 +11 1 +.names g6369 g927 g8439 +11 1 +.names g3566 g1600 g8446 +11 1 +.names g6783 g1606 g8447 +11 1 +.names g6574 g1612 g8448 +11 1 +.names g7085 g2291 g8458 +11 1 +.names g6838 g2297 g8459 +11 1 +.names g3254 g246 g8463 +11 1 +.names g6314 g252 g8464 +11 1 +.names g6232 g258 g8465 +11 1 +.names g3410 g924 g8466 +11 1 +.names g6519 g930 g8467 +11 1 +.names g6369 g936 g8468 +11 1 +.names g3566 g1609 g8472 +11 1 +.names g6783 g1615 g8473 +11 1 +.names g6574 g1621 g8474 +11 1 +.names g3722 g2294 g8481 +11 1 +.names g7085 g2300 g8482 +11 1 +.names g6838 g2306 g8483 +11 1 +.names g6232 g186 g8484 +11 1 +.names g3254 g255 g8485 +11 1 +.names g6314 g261 g8486 +11 1 +.names g6232 g267 g8487 +11 1 +.names g3410 g933 g8488 +11 1 +.names g6519 g939 g8489 +11 1 +.names g6369 g945 g8490 +11 1 +.names g3566 g1618 g8491 +11 1 +.names g6783 g1624 g8492 +11 1 +.names g6574 g1630 g8493 +11 1 +.names g3722 g2303 g8497 +11 1 +.names g7085 g2309 g8498 +11 1 +.names g6838 g2315 g8499 +11 1 +.names g6314 g189 g8500 +11 1 +.names g6232 g195 g8501 +11 1 +.names g3254 g264 g8502 +11 1 +.names g6314 g270 g8503 +11 1 +.names g6369 g873 g8504 +11 1 +.names g3410 g942 g8505 +11 1 +.names g6519 g948 g8506 +11 1 +.names g6369 g954 g8507 +11 1 +.names g3566 g1627 g8508 +11 1 +.names g6783 g1633 g8509 +11 1 +.names g6574 g1639 g8510 +11 1 +.names g3722 g2312 g8511 +11 1 +.names g7085 g2318 g8512 +11 1 +.names g6838 g2324 g8513 +11 1 +.names g3254 g192 g8515 +11 1 +.names g6314 g198 g8516 +11 1 +.names g6232 g204 g8517 +11 1 +.names g3254 g273 g8518 +11 1 +.names g6519 g876 g8519 +11 1 +.names g6369 g882 g8520 +11 1 +.names g3410 g951 g8521 +11 1 +.names g6519 g957 g8522 +11 1 +.names g6574 g1567 g8523 +11 1 +.names g3566 g1636 g8524 +11 1 +.names g6783 g1642 g8525 +11 1 +.names g6574 g1648 g8526 +11 1 +.names g3722 g2321 g8527 +11 1 +.names g7085 g2327 g8528 +11 1 +.names g6838 g2333 g8529 +11 1 +.names g3254 g201 g8531 +11 1 +.names g6314 g207 g8532 +11 1 +.names g3410 g879 g8534 +11 1 +.names g6519 g885 g8535 +11 1 +.names g6369 g891 g8536 +11 1 +.names g3410 g960 g8537 +11 1 +.names g6783 g1570 g8538 +11 1 +.names g6574 g1576 g8539 +11 1 +.names g3566 g1645 g8540 +11 1 +.names g6783 g1651 g8541 +11 1 +.names g6838 g2261 g8542 +11 1 +.names g3722 g2330 g8543 +11 1 +.names g7085 g2336 g8544 +11 1 +.names g6838 g2342 g8545 +11 1 +.names g3254 g210 g8546 +11 1 +.names g3410 g888 g8548 +11 1 +.names g6519 g894 g8549 +11 1 +.names g3566 g1573 g8551 +11 1 +.names g6783 g1579 g8552 +11 1 +.names g6574 g1585 g8553 +11 1 +.names g3566 g1654 g8554 +11 1 +.names g7085 g2264 g8555 +11 1 +.names g6838 g2270 g8556 +11 1 +.names g3722 g2339 g8557 +11 1 +.names g7085 g2345 g8558 +11 1 +.names g3410 g897 g8559 +11 1 +.names g3566 g1582 g8561 +11 1 +.names g6783 g1588 g8562 +11 1 +.names g3722 g2267 g8564 +11 1 +.names g7085 g2273 g8565 +11 1 +.names g6838 g2279 g8566 +11 1 +.names g3722 g2348 g8567 +11 1 +.names g3566 g1591 g8570 +11 1 +.names g3722 g2276 g8572 +11 1 +.names g7085 g2282 g8573 +11 1 +.names g3722 g2285 g8576 +11 1 +.names g6643 g7153 g8601 +11 1 +.names g3338 g6908 g8612 +11 1 +.names g6945 g7349 g8613 +11 1 +.names g6486 g6672 g8621 +11 1 +.names g3494 g7158 g8625 +11 1 +.names g7195 g7479 g8626 +11 1 +.names g6751 g6974 g8631 +11 1 +.names g3650 g7354 g8635 +11 1 +.names g7391 g7535 g8636 +11 1 +.names g7053 g7224 g8650 +11 1 +.names g3806 g7484 g8654 +11 1 +.names g7303 g7420 g8666 +11 1 +.names g6643 g7838 g8676 +11 1 +.names g3338 g7827 g8687 +11 1 +.names g6945 g7858 g8688 +11 1 +.names g6486 g7819 g8703 +11 1 +.names g6643 g7996 g8704 +11 1 +.names g3494 g7842 g8705 +11 1 +.names g7195 g7888 g8706 +11 1 +.names g3338 g7953 g8717 +11 1 +.names g6751 g7830 g8722 +11 1 +.names g6945 g8071 g8723 +11 1 +.names g3650 g7862 g8724 +11 1 +.names g7391 g7912 g8725 +11 1 +.names g6486 g7906 g8751 +11 1 +.names g3494 g8004 g8755 +11 1 +.names g7053 g7845 g8760 +11 1 +.names g7195 g8156 g8761 +11 1 +.names g3806 g7892 g8762 +11 1 +.names g6751 g7958 g8774 +11 1 +.names g3650 g8079 g8778 +11 1 +.names g7303 g7865 g8783 +11 1 +.names g7391 g8242 g8784 +11 1 +.names g7053 g8009 g8797 +11 1 +.names g3806 g8164 g8801 +11 1 +.names g7303 g8084 g8816 +11 1 +.names g6486 g490 g8841 +11 1 +.names g6512 g5508 g8842 +11 1 +.names g6643 g493 g8861 +11 1 +.names g6751 g1177 g8868 +11 1 +.names g6776 g5552 g8869 +11 1 +.names g3338 g496 g8892 +11 1 +.names g6945 g1180 g8899 +11 1 +.names g7053 g1871 g8906 +11 1 +.names g7078 g5598 g8907 +11 1 +.names g3494 g1183 g8932 +11 1 +.names g7195 g1874 g8939 +11 1 +.names g7303 g2565 g8946 +11 1 +.names g7328 g5615 g8947 +11 1 +.names g3650 g1877 g8972 +11 1 +.names g7391 g2568 g8979 +11 1 +.names g3806 g2571 g9004 +11 1 +.names g6486 g565 g9009 +11 1 +.names g5438 g7610 g9026 +11 1 +.names g6643 g567 g9033 +11 1 +.names g6751 g1251 g9034 +11 1 +.names g6448 g7616 g9047 +11 1 +.names g3338 g489 g9048 +11 1 +.names g5473 g7619 g9049 +11 1 +.names g6945 g1253 g9056 +11 1 +.names g7053 g1945 g9057 +11 1 +.names g3306 g7623 g9061 +11 1 +.names g5438 g7626 g9062 +11 1 +.names g5438 g7629 g9063 +11 1 +.names g6713 g7632 g9064 +11 1 +.names g3494 g1176 g9065 +11 1 +.names g5512 g7635 g9066 +11 1 +.names g7195 g1947 g9073 +11 1 +.names g7303 g2639 g9074 +11 1 +.names g6448 g7643 g9075 +11 1 +.names g5438 g7646 g9076 +11 1 +.names g6448 g7649 g9077 +11 1 +.names g3462 g7652 g9078 +11 1 +.names g5473 g7655 g9079 +11 1 +.names g5473 g7658 g9080 +11 1 +.names g7015 g7661 g9081 +11 1 +.names g3650 g1870 g9082 +11 1 +.names g5556 g7664 g9083 +11 1 +.names g7391 g2641 g9090 +11 1 +.names g3306 g7670 g9091 +11 1 +.names g6448 g7673 g9092 +11 1 +.names g3306 g7676 g9093 +11 1 +.names g6713 g7679 g9094 +11 1 +.names g5473 g7682 g9095 +11 1 +.names g6713 g7685 g9096 +11 1 +.names g3618 g7688 g9097 +11 1 +.names g5512 g7691 g9098 +11 1 +.names g5512 g7694 g9099 +11 1 +.names g7265 g7697 g9100 +11 1 +.names g3806 g2564 g9101 +11 1 +.names g3306 g7703 g9102 +11 1 +.names g3462 g7706 g9103 +11 1 +.names g6713 g7709 g9104 +11 1 +.names g3462 g7712 g9105 +11 1 +.names g7015 g7715 g9106 +11 1 +.names g5512 g7718 g9107 +11 1 +.names g7015 g7721 g9108 +11 1 +.names g3774 g7724 g9109 +11 1 +.names g5556 g7727 g9110 +11 1 +.names g5556 g7730 g9111 +11 1 +.names g3462 g7733 g9112 +11 1 +.names g3618 g7736 g9113 +11 1 +.names g7015 g7739 g9114 +11 1 +.names g3618 g7742 g9115 +11 1 +.names g7265 g7745 g9116 +11 1 +.names g5556 g7748 g9117 +11 1 +.names g7265 g7751 g9118 +11 1 +.names g5438 g7754 g9119 +11 1 +.names g3618 g7757 g9120 +11 1 +.names g3774 g7760 g9121 +11 1 +.names g7265 g7763 g9122 +11 1 +.names g3774 g7766 g9123 +11 1 +.names g6448 g7769 g9124 +11 1 +.names g5473 g7776 g9125 +11 1 +.names g3774 g7779 g9126 +11 1 +.names g3306 g7782 g9127 +11 1 +.names g6713 g7785 g9131 +11 1 +.names g5512 g7792 g9132 +11 1 +.names g3462 g7796 g9133 +11 1 +.names g7015 g7799 g9137 +11 1 +.names g5556 g7806 g9138 +11 1 +.names g3618 g7809 g9139 +11 1 +.names g7265 g7812 g9143 +11 1 +.names g3774 g7823 g9145 +11 1 +.names g6232 g7950 g9241 +11 1 +.names g6314 g7990 g9301 +11 1 +.names g6232 g7993 g9302 +11 1 +.names g6369 g8001 g9319 +11 1 +.names g3254 g8053 g9364 +11 1 +.names g6314 g8056 g9365 +11 1 +.names g6232 g8059 g9366 +11 1 +.names g6232 g8062 g9367 +11 1 +.names g6519 g8065 g9382 +11 1 +.names g6369 g8068 g9383 +11 1 +.names g6574 g8076 g9400 +11 1 +.names g3254 g8123 g9438 +11 1 +.names g6314 g8126 g9439 +11 1 +.names g6232 g8129 g9440 +11 1 +.names g6314 g8132 g9441 +11 1 +.names g6232 g8135 g9442 +11 1 +.names g3410 g8138 g9461 +11 1 +.names g6519 g8141 g9462 +11 1 +.names g6369 g8144 g9463 +11 1 +.names g6369 g8147 g9464 +11 1 +.names g6783 g8150 g9479 +11 1 +.names g6574 g8153 g9480 +11 1 +.names g6838 g8161 g9497 +11 1 +.names g3254 g8191 g9518 +11 1 +.names g6314 g8194 g9519 +11 1 +.names g6232 g8197 g9520 +11 1 +.names g3254 g8200 g9521 +11 1 +.names g6314 g8203 g9522 +11 1 +.names g6232 g8206 g9523 +11 1 +.names g7772 g6135 g538 g9534 +111 1 +.names g3410 g8209 g9580 +11 1 +.names g6519 g8212 g9581 +11 1 +.names g6369 g8215 g9582 +11 1 +.names g6519 g8218 g9583 +11 1 +.names g6369 g8221 g9584 +11 1 +.names g3566 g8224 g9603 +11 1 +.names g6783 g8227 g9604 +11 1 +.names g6574 g8230 g9605 +11 1 +.names g6574 g8233 g9606 +11 1 +.names g7085 g8236 g9621 +11 1 +.names g6838 g8239 g9622 +11 1 +.names g3254 g3922 g9630 +11 1 +.names g6314 g3925 g9631 +11 1 +.names g6232 g3928 g9632 +11 1 +.names g3254 g3931 g9633 +11 1 +.names g6314 g3934 g9634 +11 1 +.names g6232 g3937 g9635 +11 1 +.names g5856 g4338 g4339 g5141 II16735 +1111 1 +.names g5713 g5958 g4735 g4736 II16736 +1111 1 +.names II16735 II16736 g9636 +11 1 +.names g5438 g408 g9639 +11 1 +.names g6678 g3942 g9647 +11 1 +.names g6678 g3945 g9648 +11 1 +.names g3410 g3948 g9660 +11 1 +.names g6519 g3951 g9661 +11 1 +.names g6369 g3954 g9662 +11 1 +.names g3410 g3957 g9663 +11 1 +.names g6519 g3960 g9664 +11 1 +.names g6369 g3963 g9665 +11 1 +.names g7788 g6145 g1224 g9676 +111 1 +.names g3566 g3966 g9722 +11 1 +.names g6783 g3969 g9723 +11 1 +.names g6574 g3972 g9724 +11 1 +.names g6783 g3975 g9725 +11 1 +.names g6574 g3978 g9726 +11 1 +.names g3722 g3981 g9745 +11 1 +.names g7085 g3984 g9746 +11 1 +.names g6838 g3987 g9747 +11 1 +.names g6838 g3990 g9748 +11 1 +.names g3254 g4000 g9759 +11 1 +.names g6314 g4003 g9760 +11 1 +.names g6232 g4006 g9761 +11 1 +.names g3254 g4009 g9762 +11 1 +.names g6314 g4012 g9763 +11 1 +.names g6448 g411 g9764 +11 1 +.names g5438 g417 g9765 +11 1 +.names g5438 g4017 g9766 +11 1 +.names g6912 g4020 g9773 +11 1 +.names g6678 g4023 g9774 +11 1 +.names g6912 g4026 g9775 +11 1 +.names g3410 g4029 g9776 +11 1 +.names g6519 g4032 g9777 +11 1 +.names g6369 g4035 g9778 +11 1 +.names g3410 g4038 g9779 +11 1 +.names g6519 g4041 g9780 +11 1 +.names g6369 g4044 g9781 +11 1 +.names g5903 g4507 g4508 g5234 II16826 +1111 1 +.names g5771 g5987 g4911 g4912 II16827 +1111 1 +.names II16826 II16827 g9782 +11 1 +.names g5473 g1095 g9785 +11 1 +.names g6980 g4049 g9793 +11 1 +.names g6980 g4052 g9794 +11 1 +.names g3566 g4055 g9806 +11 1 +.names g6783 g4058 g9807 +11 1 +.names g6574 g4061 g9808 +11 1 +.names g3566 g4064 g9809 +11 1 +.names g6783 g4067 g9810 +11 1 +.names g6574 g4070 g9811 +11 1 +.names g7802 g6166 g1918 g9822 +111 1 +.names g3722 g4073 g9868 +11 1 +.names g7085 g4076 g9869 +11 1 +.names g6838 g4079 g9870 +11 1 +.names g7085 g4082 g9871 +11 1 +.names g6838 g4085 g9872 +11 1 +.names g6232 g4095 g9887 +11 1 +.names g3254 g4098 g9888 +11 1 +.names g6314 g4101 g9889 +11 1 +.names g6232 g4104 g9890 +11 1 +.names g3254 g4107 g9891 +11 1 +.names g3306 g414 g9892 +11 1 +.names g6448 g420 g9893 +11 1 +.names g6448 g4112 g9894 +11 1 +.names g3366 g4115 g9901 +11 1 +.names g6912 g4118 g9902 +11 1 +.names g6678 g4121 g9903 +11 1 +.names g3366 g4124 g9904 +11 1 +.names g3410 g4127 g9905 +11 1 +.names g6519 g4130 g9906 +11 1 +.names g6369 g4133 g9907 +11 1 +.names g3410 g4136 g9908 +11 1 +.names g6519 g4139 g9909 +11 1 +.names g6713 g1098 g9910 +11 1 +.names g5473 g1104 g9911 +11 1 +.names g5473 g4144 g9912 +11 1 +.names g7162 g4147 g9919 +11 1 +.names g6980 g4150 g9920 +11 1 +.names g7162 g4153 g9921 +11 1 +.names g3566 g4156 g9922 +11 1 +.names g6783 g4159 g9923 +11 1 +.names g6574 g4162 g9924 +11 1 +.names g3566 g4165 g9925 +11 1 +.names g6783 g4168 g9926 +11 1 +.names g6574 g4171 g9927 +11 1 +.names g5942 g4683 g4684 g5297 II16930 +1111 1 +.names g5830 g6024 g5070 g5071 II16931 +1111 1 +.names II16930 II16931 g9928 +11 1 +.names g5512 g1789 g9931 +11 1 +.names g7230 g4176 g9939 +11 1 +.names g7230 g4179 g9940 +11 1 +.names g3722 g4182 g9952 +11 1 +.names g7085 g4185 g9953 +11 1 +.names g6838 g4188 g9954 +11 1 +.names g3722 g4191 g9955 +11 1 +.names g7085 g4194 g9956 +11 1 +.names g6838 g4197 g9957 +11 1 +.names g7815 g6193 g2612 g9968 +111 1 +.names g6314 g4205 g10007 +11 1 +.names g6232 g4208 g10008 +11 1 +.names g3254 g4211 g10009 +11 1 +.names g6314 g4214 g10010 +11 1 +.names g5438 g4217 g10011 +11 1 +.names g3306 g423 g10012 +11 1 +.names g3306 g4221 g10013 +11 1 +.names g5438 g429 g10014 +11 1 +.names g3398 g6912 g10024 +11 1 +.names g3366 g4225 g10035 +11 1 +.names g6912 g4228 g10036 +11 1 +.names g6678 g4231 g10037 +11 1 +.names g6369 g4234 g10041 +11 1 +.names g3410 g4237 g10042 +11 1 +.names g6519 g4240 g10043 +11 1 +.names g6369 g4243 g10044 +11 1 +.names g3410 g4246 g10045 +11 1 +.names g3462 g1101 g10046 +11 1 +.names g6713 g1107 g10047 +11 1 +.names g6713 g4251 g10048 +11 1 +.names g3522 g4254 g10055 +11 1 +.names g7162 g4257 g10056 +11 1 +.names g6980 g4260 g10057 +11 1 +.names g3522 g4263 g10058 +11 1 +.names g3566 g4266 g10059 +11 1 +.names g6783 g4269 g10060 +11 1 +.names g6574 g4272 g10061 +11 1 +.names g3566 g4275 g10062 +11 1 +.names g6783 g4278 g10063 +11 1 +.names g7015 g1792 g10064 +11 1 +.names g5512 g1798 g10065 +11 1 +.names g5512 g4283 g10066 +11 1 +.names g7358 g4286 g10073 +11 1 +.names g7230 g4289 g10074 +11 1 +.names g7358 g4292 g10075 +11 1 +.names g3722 g4295 g10076 +11 1 +.names g7085 g4298 g10077 +11 1 +.names g6838 g4301 g10078 +11 1 +.names g3722 g4304 g10079 +11 1 +.names g7085 g4307 g10080 +11 1 +.names g6838 g4310 g10081 +11 1 +.names g5976 g4860 g4861 g5334 II17042 +1111 1 +.names g5886 g6040 g5199 g5200 II17043 +1111 1 +.names II17042 II17043 g10082 +11 1 +.names g5556 g2483 g10085 +11 1 +.names g7426 g4315 g10093 +11 1 +.names g7426 g4318 g10094 +11 1 +.names g3254 g4329 g10101 +11 1 +.names g6314 g4332 g10102 +11 1 +.names g3254 g4335 g10103 +11 1 +.names g6448 g4340 g10104 +11 1 +.names g5438 g4343 g10105 +11 1 +.names g6448 g432 g10106 +11 1 +.names g5438 g438 g10107 +11 1 +.names g6486 g569 g10108 +11 1 +.names g3366 g4348 g10112 +11 1 +.names g6912 g4351 g10113 +11 1 +.names g6678 g4354 g10114 +11 1 +.names g6678 g4357 g10115 +11 1 +.names g6519 g4360 g10116 +11 1 +.names g6369 g4363 g10117 +11 1 +.names g3410 g4366 g10118 +11 1 +.names g6519 g4369 g10119 +11 1 +.names g5473 g4372 g10120 +11 1 +.names g3462 g1110 g10121 +11 1 +.names g3462 g4376 g10122 +11 1 +.names g5473 g1116 g10123 +11 1 +.names g3554 g7162 g10133 +11 1 +.names g3522 g4380 g10144 +11 1 +.names g7162 g4383 g10145 +11 1 +.names g6980 g4386 g10146 +11 1 +.names g6574 g4389 g10150 +11 1 +.names g3566 g4392 g10151 +11 1 +.names g6783 g4395 g10152 +11 1 +.names g6574 g4398 g10153 +11 1 +.names g3566 g4401 g10154 +11 1 +.names g3618 g1795 g10155 +11 1 +.names g7015 g1801 g10156 +11 1 +.names g7015 g4406 g10157 +11 1 +.names g3678 g4409 g10164 +11 1 +.names g7358 g4412 g10165 +11 1 +.names g7230 g4415 g10166 +11 1 +.names g3678 g4418 g10167 +11 1 +.names g3722 g4421 g10168 +11 1 +.names g7085 g4424 g10169 +11 1 +.names g6838 g4427 g10170 +11 1 +.names g3722 g4430 g10171 +11 1 +.names g7085 g4433 g10172 +11 1 +.names g7265 g2486 g10173 +11 1 +.names g5556 g2492 g10174 +11 1 +.names g5556 g4438 g10175 +11 1 +.names g7488 g4441 g10182 +11 1 +.names g7426 g4444 g10183 +11 1 +.names g7488 g4447 g10184 +11 1 +.names g6898 g2998 g6901 g3002 II17156 +1111 1 +.names g3013 g7466 g3024 II17156 g10186 +1111 1 +.names g3254 g4453 g10192 +11 1 +.names g3306 g4465 g10193 +11 1 +.names g6448 g4468 g10194 +11 1 +.names g5438 g4471 g10195 +11 1 +.names g3306 g435 g10196 +11 1 +.names g6448 g441 g10197 +11 1 +.names g6643 g571 g10198 +11 1 +.names g6486 g4476 g10199 +11 1 +.names g6486 g587 g10200 +11 1 +.names g3366 g4480 g10201 +11 1 +.names g6912 g4483 g10202 +11 1 +.names g6678 g4486 g10203 +11 1 +.names g6912 g4489 g10204 +11 1 +.names g6678 g4492 g10205 +11 1 +.names g3410 g4498 g10206 +11 1 +.names g6519 g4501 g10207 +11 1 +.names g3410 g4504 g10208 +11 1 +.names g6713 g4509 g10209 +11 1 +.names g5473 g4512 g10210 +11 1 +.names g6713 g1119 g10211 +11 1 +.names g5473 g1125 g10212 +11 1 +.names g6751 g1255 g10213 +11 1 +.names g3522 g4517 g10217 +11 1 +.names g7162 g4520 g10218 +11 1 +.names g6980 g4523 g10219 +11 1 +.names g6980 g4526 g10220 +11 1 +.names g6783 g4529 g10221 +11 1 +.names g6574 g4532 g10222 +11 1 +.names g3566 g4535 g10223 +11 1 +.names g6783 g4538 g10224 +11 1 +.names g5512 g4541 g10225 +11 1 +.names g3618 g1804 g10226 +11 1 +.names g3618 g4545 g10227 +11 1 +.names g5512 g1810 g10228 +11 1 +.names g3710 g7358 g10238 +11 1 +.names g3678 g4549 g10249 +11 1 +.names g7358 g4552 g10250 +11 1 +.names g7230 g4555 g10251 +11 1 +.names g6838 g4558 g10255 +11 1 +.names g3722 g4561 g10256 +11 1 +.names g7085 g4564 g10257 +11 1 +.names g6838 g4567 g10258 +11 1 +.names g3722 g4570 g10259 +11 1 +.names g3774 g2489 g10260 +11 1 +.names g7265 g2495 g10261 +11 1 +.names g7265 g4575 g10262 +11 1 +.names g3834 g4578 g10269 +11 1 +.names g7488 g4581 g10270 +11 1 +.names g7426 g4584 g10271 +11 1 +.names g3834 g4587 g10272 +11 1 +.names g3306 g4592 g10279 +11 1 +.names g6448 g4595 g10280 +11 1 +.names g5438 g4598 g10281 +11 1 +.names g3306 g444 g10282 +11 1 +.names g3338 g573 g10283 +11 1 +.names g6643 g4603 g10284 +11 1 +.names g6486 g4606 g10285 +11 1 +.names g6643 g590 g10286 +11 1 +.names g6486 g596 g10287 +11 1 +.names g3366 g4611 g10288 +11 1 +.names g6912 g4614 g10289 +11 1 +.names g6678 g4617 g10290 +11 1 +.names g3366 g4620 g10291 +11 1 +.names g6912 g4623 g10292 +11 1 +.names g6678 g4626 g10293 +11 1 +.names g3410 g4629 g10294 +11 1 +.names g3462 g4641 g10295 +11 1 +.names g6713 g4644 g10296 +11 1 +.names g5473 g4647 g10297 +11 1 +.names g3462 g1122 g10298 +11 1 +.names g6713 g1128 g10299 +11 1 +.names g6945 g1257 g10300 +11 1 +.names g6751 g4652 g10301 +11 1 +.names g6751 g1273 g10302 +11 1 +.names g3522 g4656 g10303 +11 1 +.names g7162 g4659 g10304 +11 1 +.names g6980 g4662 g10305 +11 1 +.names g7162 g4665 g10306 +11 1 +.names g6980 g4668 g10307 +11 1 +.names g3566 g4674 g10308 +11 1 +.names g6783 g4677 g10309 +11 1 +.names g3566 g4680 g10310 +11 1 +.names g7015 g4685 g10311 +11 1 +.names g5512 g4688 g10312 +11 1 +.names g7015 g1813 g10313 +11 1 +.names g5512 g1819 g10314 +11 1 +.names g7053 g1949 g10315 +11 1 +.names g3678 g4693 g10319 +11 1 +.names g7358 g4696 g10320 +11 1 +.names g7230 g4699 g10321 +11 1 +.names g7230 g4702 g10322 +11 1 +.names g7085 g4705 g10323 +11 1 +.names g6838 g4708 g10324 +11 1 +.names g3722 g4711 g10325 +11 1 +.names g7085 g4714 g10326 +11 1 +.names g5556 g4717 g10327 +11 1 +.names g3774 g2498 g10328 +11 1 +.names g3774 g4721 g10329 +11 1 +.names g5556 g2504 g10330 +11 1 +.names g3866 g7488 g10340 +11 1 +.names g3834 g4725 g10351 +11 1 +.names g7488 g4728 g10352 +11 1 +.names g7426 g4731 g10353 +11 1 +.names g3306 g4737 g10360 +11 1 +.names g6448 g4740 g10361 +11 1 +.names g3338 g4743 g10362 +11 1 +.names g6643 g4746 g10363 +11 1 +.names g6486 g4749 g10364 +11 1 +.names g3338 g593 g10365 +11 1 +.names g6643 g599 g10366 +11 1 +.names g3366 g4754 g10367 +11 1 +.names g6912 g4757 g10368 +11 1 +.names g6678 g4760 g10369 +11 1 +.names g3366 g4763 g10370 +11 1 +.names g6912 g4766 g10371 +11 1 +.names g3462 g4769 g10372 +11 1 +.names g6713 g4772 g10373 +11 1 +.names g5473 g4775 g10374 +11 1 +.names g3462 g1131 g10375 +11 1 +.names g3494 g1259 g10376 +11 1 +.names g6945 g4780 g10377 +11 1 +.names g6751 g4783 g10378 +11 1 +.names g6945 g1276 g10379 +11 1 +.names g6751 g1282 g10380 +11 1 +.names g3522 g4788 g10381 +11 1 +.names g7162 g4791 g10382 +11 1 +.names g6980 g4794 g10383 +11 1 +.names g3522 g4797 g10384 +11 1 +.names g7162 g4800 g10385 +11 1 +.names g6980 g4803 g10386 +11 1 +.names g3566 g4806 g10387 +11 1 +.names g3618 g4818 g10388 +11 1 +.names g7015 g4821 g10389 +11 1 +.names g5512 g4824 g10390 +11 1 +.names g3618 g1816 g10391 +11 1 +.names g7015 g1822 g10392 +11 1 +.names g7195 g1951 g10393 +11 1 +.names g7053 g4829 g10394 +11 1 +.names g7053 g1967 g10395 +11 1 +.names g3678 g4833 g10396 +11 1 +.names g7358 g4836 g10397 +11 1 +.names g7230 g4839 g10398 +11 1 +.names g7358 g4842 g10399 +11 1 +.names g7230 g4845 g10400 +11 1 +.names g3722 g4851 g10401 +11 1 +.names g7085 g4854 g10402 +11 1 +.names g3722 g4857 g10403 +11 1 +.names g7265 g4862 g10404 +11 1 +.names g5556 g4865 g10405 +11 1 +.names g7265 g2507 g10406 +11 1 +.names g5556 g2513 g10407 +11 1 +.names g7303 g2643 g10408 +11 1 +.names g3834 g4870 g10412 +11 1 +.names g7488 g4873 g10413 +11 1 +.names g7426 g4876 g10414 +11 1 +.names g7426 g4879 g10415 +11 1 +.names g3306 g4882 g10422 +11 1 +.names g5438 g4885 g10423 +11 1 +.names g3338 g4888 g10430 +11 1 +.names g6643 g4891 g10431 +11 1 +.names g6486 g4894 g10432 +11 1 +.names g3338 g602 g10433 +11 1 +.names g6486 g605 g10434 +11 1 +.names g3366 g4899 g10435 +11 1 +.names g6912 g4902 g10436 +11 1 +.names g6678 g4905 g10437 +11 1 +.names g3366 g4908 g10438 +11 1 +.names g3462 g4913 g10439 +11 1 +.names g6713 g4916 g10440 +11 1 +.names g3494 g4919 g10441 +11 1 +.names g6945 g4922 g10442 +11 1 +.names g6751 g4925 g10443 +11 1 +.names g3494 g1279 g10444 +11 1 +.names g6945 g1285 g10445 +11 1 +.names g3522 g4930 g10446 +11 1 +.names g7162 g4933 g10447 +11 1 +.names g6980 g4936 g10448 +11 1 +.names g3522 g4939 g10449 +11 1 +.names g7162 g4942 g10450 +11 1 +.names g3618 g4945 g10451 +11 1 +.names g7015 g4948 g10452 +11 1 +.names g5512 g4951 g10453 +11 1 +.names g3618 g1825 g10454 +11 1 +.names g3650 g1953 g10455 +11 1 +.names g7195 g4956 g10456 +11 1 +.names g7053 g4959 g10457 +11 1 +.names g7195 g1970 g10458 +11 1 +.names g7053 g1976 g10459 +11 1 +.names g3678 g4964 g10460 +11 1 +.names g7358 g4967 g10461 +11 1 +.names g7230 g4970 g10462 +11 1 +.names g3678 g4973 g10463 +11 1 +.names g7358 g4976 g10464 +11 1 +.names g7230 g4979 g10465 +11 1 +.names g3722 g4982 g10466 +11 1 +.names g3774 g4994 g10467 +11 1 +.names g7265 g4997 g10468 +11 1 +.names g5556 g5000 g10469 +11 1 +.names g3774 g2510 g10470 +11 1 +.names g7265 g2516 g10471 +11 1 +.names g7391 g2645 g10472 +11 1 +.names g7303 g5005 g10473 +11 1 +.names g7303 g2661 g10474 +11 1 +.names g3834 g5009 g10475 +11 1 +.names g7488 g5012 g10476 +11 1 +.names g7426 g5015 g10477 +11 1 +.names g7488 g5018 g10478 +11 1 +.names g7426 g5021 g10479 +11 1 +.names g6901 g7338 g7146 II17429 +111 1 +.names g6448 g5024 g10485 +11 1 +.names g3338 g5027 g10492 +11 1 +.names g6643 g5030 g10493 +11 1 +.names g6643 g608 g10494 +11 1 +.names g6486 g614 g10495 +11 1 +.names g3366 g5035 g10496 +11 1 +.names g6912 g5038 g10497 +11 1 +.names g3462 g5041 g10498 +11 1 +.names g5473 g5044 g10499 +11 1 +.names g3494 g5047 g10506 +11 1 +.names g6945 g5050 g10507 +11 1 +.names g6751 g5053 g10508 +11 1 +.names g3494 g1288 g10509 +11 1 +.names g6751 g1291 g10510 +11 1 +.names g3522 g5058 g10511 +11 1 +.names g7162 g5061 g10512 +11 1 +.names g6980 g5064 g10513 +11 1 +.names g3522 g5067 g10514 +11 1 +.names g3618 g5072 g10515 +11 1 +.names g7015 g5075 g10516 +11 1 +.names g3650 g5078 g10517 +11 1 +.names g7195 g5081 g10518 +11 1 +.names g7053 g5084 g10519 +11 1 +.names g3650 g1973 g10520 +11 1 +.names g7195 g1979 g10521 +11 1 +.names g3678 g5089 g10522 +11 1 +.names g7358 g5092 g10523 +11 1 +.names g7230 g5095 g10524 +11 1 +.names g3678 g5098 g10525 +11 1 +.names g7358 g5101 g10526 +11 1 +.names g3774 g5104 g10527 +11 1 +.names g7265 g5107 g10528 +11 1 +.names g5556 g5110 g10529 +11 1 +.names g3774 g2519 g10530 +11 1 +.names g3806 g2647 g10531 +11 1 +.names g7391 g5115 g10532 +11 1 +.names g7303 g5118 g10533 +11 1 +.names g7391 g2664 g10534 +11 1 +.names g7303 g2670 g10535 +11 1 +.names g3834 g5123 g10536 +11 1 +.names g7488 g5126 g10537 +11 1 +.names g7426 g5129 g10538 +11 1 +.names g3834 g5132 g10539 +11 1 +.names g7488 g5135 g10540 +11 1 +.names g7426 g5138 g10541 +11 1 +.names g3306 g5142 g10548 +11 1 +.names g3338 g5145 g10555 +11 1 +.names g3338 g611 g10556 +11 1 +.names g6643 g617 g10557 +11 1 +.names g3366 g5150 g10558 +11 1 +.names g6713 g5153 g10559 +11 1 +.names g3494 g5156 g10566 +11 1 +.names g6945 g5159 g10567 +11 1 +.names g6945 g1294 g10568 +11 1 +.names g6751 g1300 g10569 +11 1 +.names g3522 g5164 g10570 +11 1 +.names g7162 g5167 g10571 +11 1 +.names g3618 g5170 g10572 +11 1 +.names g5512 g5173 g10573 +11 1 +.names g3650 g5176 g10580 +11 1 +.names g7195 g5179 g10581 +11 1 +.names g7053 g5182 g10582 +11 1 +.names g3650 g1982 g10583 +11 1 +.names g7053 g1985 g10584 +11 1 +.names g3678 g5187 g10585 +11 1 +.names g7358 g5190 g10586 +11 1 +.names g7230 g5193 g10587 +11 1 +.names g3678 g5196 g10588 +11 1 +.names g3774 g5201 g10589 +11 1 +.names g7265 g5204 g10590 +11 1 +.names g3806 g5207 g10591 +11 1 +.names g7391 g5210 g10592 +11 1 +.names g7303 g5213 g10593 +11 1 +.names g3806 g2667 g10594 +11 1 +.names g7391 g2673 g10595 +11 1 +.names g3834 g5218 g10596 +11 1 +.names g7488 g5221 g10597 +11 1 +.names g7426 g5224 g10598 +11 1 +.names g3834 g5227 g10599 +11 1 +.names g7488 g5230 g10600 +11 1 +.names g3338 g620 g10604 +11 1 +.names g3462 g5235 g10605 +11 1 +.names g3494 g5238 g10612 +11 1 +.names g3494 g1297 g10613 +11 1 +.names g6945 g1303 g10614 +11 1 +.names g3522 g5243 g10615 +11 1 +.names g7015 g5246 g10616 +11 1 +.names g3650 g5249 g10623 +11 1 +.names g7195 g5252 g10624 +11 1 +.names g7195 g1988 g10625 +11 1 +.names g7053 g1994 g10626 +11 1 +.names g3678 g5257 g10627 +11 1 +.names g7358 g5260 g10628 +11 1 +.names g3774 g5263 g10629 +11 1 +.names g5556 g5266 g10630 +11 1 +.names g3806 g5269 g10637 +11 1 +.names g7391 g5272 g10638 +11 1 +.names g7303 g5275 g10639 +11 1 +.names g3806 g2676 g10640 +11 1 +.names g7303 g2679 g10641 +11 1 +.names g3834 g5280 g10642 +11 1 +.names g7488 g5283 g10643 +11 1 +.names g7426 g5286 g10644 +11 1 +.names g3834 g5289 g10645 +11 1 +.names g6678 g5293 g10650 +11 1 +.names g3494 g1306 g10651 +11 1 +.names g3618 g5298 g10652 +11 1 +.names g3650 g5301 g10659 +11 1 +.names g3650 g1991 g10660 +11 1 +.names g7195 g1997 g10661 +11 1 +.names g3678 g5306 g10662 +11 1 +.names g7265 g5309 g10663 +11 1 +.names g3806 g5312 g10670 +11 1 +.names g7391 g5315 g10671 +11 1 +.names g7391 g2682 g10672 +11 1 +.names g7303 g2688 g10673 +11 1 +.names g3834 g5320 g10674 +11 1 +.names g7488 g5323 g10675 +11 1 +.names g6912 g5327 g10678 +11 1 +.names g6980 g5330 g10680 +11 1 +.names g3650 g2000 g10681 +11 1 +.names g3774 g5335 g10682 +11 1 +.names g3806 g5338 g10689 +11 1 +.names g3806 g2685 g10690 +11 1 +.names g7391 g2691 g10691 +11 1 +.names g3834 g5343 g10692 +11 1 +.names g7462 g7522 g2924 g7545 g10693 +1111 1 +.names g3366 g5352 g10704 +11 1 +.names g7162 g5355 g10707 +11 1 +.names g7230 g5358 g10709 +11 1 +.names g3806 g2694 g10710 +11 1 +.names g7566 g7583 g7587 II17599 +111 1 +.names g3522 g5369 g10724 +11 1 +.names g7358 g5372 g10727 +11 1 +.names g7426 g5375 g10729 +11 1 +.names g3678 g5382 g10745 +11 1 +.names g7488 g5385 g10748 +11 1 +.names g3834 g5391 g10764 +11 1 +.names g6232 g213 g11347 +11 1 +.names g6314 g216 g11420 +11 1 +.names g6232 g222 g11421 +11 1 +.names g6369 g900 g11431 +11 1 +.names g5871 g8360 g11607 +11 1 +.names g5881 g8378 g11612 +11 1 +.names g5918 g8427 g11637 +11 1 +.names g554 g8622 g11771 +11 1 +.names g1240 g8632 g11788 +11 1 +.names g6173 g8643 g11805 +11 1 +.names g1934 g8651 g11814 +11 1 +.names g7869 g8655 g11816 +11 1 +.names g6205 g8659 g11838 +11 1 +.names g2628 g8667 g11847 +11 1 +.names g7849 g8670 g11851 +11 1 +.names g6294 g8678 g11880 +11 1 +.names g7834 g8684 g11885 +11 1 +.names g6431 g8690 g11922 +11 1 +.names g8169 g8696 g11926 +11 1 +.names g8090 g8708 g11966 +11 1 +.names g7967 g8711 g11967 +11 1 +.names g8015 g8745 g12012 +11 1 +.names g7964 g8763 g12069 +11 1 +.names g8018 g8766 g12070 +11 1 +.names g7916 g8785 g12128 +11 1 +.names g7872 g8788 g12129 +11 1 +.names g8093 g8805 g12186 +11 1 +.names g8172 g8829 g12273 +11 1 +.names g7900 g8832 g12274 +11 1 +.names g7919 g8853 g12307 +11 1 +.names g8246 g8879 g12330 +11 1 +.names g7927 g8882 g12331 +11 1 +.names g7852 g8915 g12353 +11 1 +.names g7974 g8949 g12376 +11 1 +.names g8028 g9006 g12419 +11 1 +.names g8101 g9044 g12429 +11 1 +.names g7822 g9128 g12477 +11 1 +.names g7833 g9134 g12494 +11 1 +.names g7848 g9140 g12514 +11 1 +.names g7868 g9146 g12531 +11 1 +.names g6149 g9290 g12650 +11 1 +.names g9507 g9427 g9356 g9293 II19937 +1111 1 +.names g9232 g9187 g9161 g9150 II19938 +1111 1 +.names II19937 II19938 g12876 +11 1 +.names g7899 g10004 g12908 +11 1 +.names g9649 g9569 g9453 g9374 II19971 +1111 1 +.names g9310 g9248 g9203 g9174 II19972 +1111 1 +.names II19971 II19972 g12916 +11 1 +.names g8179 g10096 g12938 +11 1 +.names g9795 g9711 g9595 g9471 II19996 +1111 1 +.names g9391 g9326 g9264 g9216 II19997 +1111 1 +.names II19996 II19997 g12945 +11 1 +.names g7926 g10189 g12966 +11 1 +.names g9941 g9857 g9737 g9613 II20021 +1111 1 +.names g9488 g9407 g9342 g9277 II20022 +1111 1 +.names II20021 II20022 g12974 +11 1 +.names g8254 g10273 g12989 +11 1 +.names g8180 g10276 g12990 +11 1 +.names g7973 g10357 g13000 +11 1 +.names g3995 g10416 g13009 +11 1 +.names g8255 g10419 g13010 +11 1 +.names g8027 g10482 g13023 +11 1 +.names g7879 g10542 g13031 +11 1 +.names g3996 g10545 g13032 +11 1 +.names g8100 g10601 g13042 +11 1 +.names g10186 g3018 g3028 II20100 +111 1 +.names g4092 g10646 g13056 +11 1 +.names g8313 g7542 g2888 g7566 II20131 +1111 1 +.names g2892 g2903 g7595 g2908 II20132 +1111 1 +.names g298 g11032 g13247 +11 1 +.names g5628 g11088 g13266 +11 1 +.names g985 g11102 g13270 +11 1 +.names g5647 g11141 g13289 +11 1 +.names g5656 g11154 g13291 +11 1 +.names g1679 g11170 g13295 +11 1 +.names g5675 g11210 g13316 +11 1 +.names g5685 g11225 g13320 +11 1 +.names g5694 g11240 g13322 +11 1 +.names g2373 g11256 g13326 +11 1 +.names g5708 g11278 g13335 +11 1 +.names g5727 g11294 g13340 +11 1 +.names g5737 g11309 g13343 +11 1 +.names g5746 g11324 g13345 +11 1 +.names g5756 g11355 g13355 +11 1 +.names g5766 g11373 g13360 +11 1 +.names g5785 g11389 g13365 +11 1 +.names g5795 g11404 g13368 +11 1 +.names g5815 g11441 g13385 +11 1 +.names g5825 g11459 g13390 +11 1 +.names g5844 g11475 g13395 +11 1 +.names g6016 g12191 g13477 +11 1 +.names g6017 g12196 g13479 +11 1 +.names g6018 g12197 g13480 +11 1 +.names g5864 g11603 g13481 +11 1 +.names g6020 g12209 g13483 +11 1 +.names g6021 g12210 g13484 +11 1 +.names g6022 g12211 g13485 +11 1 +.names g6023 g12212 g13486 +11 1 +.names g5874 g11608 g13487 +11 1 +.names g6025 g12218 g13488 +11 1 +.names g6026 g12219 g13489 +11 1 +.names g6027 g12220 g13490 +11 1 +.names g6028 g12221 g13491 +11 1 +.names g2371 g12222 g13492 +11 1 +.names g5887 g11613 g13493 +11 1 +.names g6032 g12246 g13496 +11 1 +.names g6033 g12251 g13498 +11 1 +.names g6034 g12252 g13499 +11 1 +.names g5911 g11633 g13500 +11 1 +.names g6036 g12264 g13502 +11 1 +.names g6037 g12265 g13503 +11 1 +.names g6038 g12266 g13504 +11 1 +.names g6039 g12267 g13505 +11 1 +.names g5921 g11638 g13506 +11 1 +.names g6043 g12289 g13513 +11 1 +.names g6044 g12294 g13515 +11 1 +.names g6045 g12295 g13516 +11 1 +.names g5950 g11656 g13517 +11 1 +.names g6047 g12325 g13527 +11 1 +.names g6141 g12456 g13609 +11 1 +.names g6162 g12466 g13619 +11 1 +.names g5428 g12472 g13623 +11 1 +.names g6173 g12476 g13625 +11 1 +.names g6189 g12481 g13631 +11 1 +.names g12776 g8617 g13634 +11 1 +.names g6205 g12493 g13636 +11 1 +.names g6221 g12498 g13642 +11 1 +.names g5431 g12502 g13643 +11 1 +.names g6281 g12504 g13645 +11 1 +.names g7772 g12505 g13646 +11 1 +.names g6294 g12513 g13648 +11 1 +.names g8093 g11791 g13654 +11 1 +.names g7540 g12518 g13655 +11 1 +.names g12776 g8640 g13656 +11 1 +.names g6418 g12521 g13671 +11 1 +.names g7788 g12522 g13672 +11 1 +.names g6431 g12530 g13674 +11 1 +.names g7561 g12532 g13675 +11 1 +.names g5434 g12533 g13676 +11 1 +.names g6623 g12536 g13701 +11 1 +.names g7802 g12537 g13702 +11 1 +.names g8018 g11848 g13703 +11 1 +.names g7581 g12542 g13704 +11 1 +.names g12776 g8673 g13705 +11 1 +.names g6887 g12545 g13738 +11 1 +.names g7815 g12546 g13739 +11 1 +.names g6636 g12547 g13740 +11 1 +.names g7347 g12551 g13755 +11 1 +.names g7967 g11923 g13787 +11 1 +.names g6897 g12553 g13788 +11 1 +.names g7140 g12554 g13789 +11 1 +.names g7475 g12558 g13790 +11 1 +.names g7477 g12559 g13796 +11 1 +.names g7139 g12560 g13815 +11 1 +.names g7530 g12596 g13816 +11 1 +.names g7531 g12597 g13818 +11 1 +.names g7533 g12598 g13824 +11 1 +.names g7919 g12009 g13833 +11 1 +.names g7336 g12599 g13834 +11 1 +.names g7461 g12600 g13835 +11 1 +.names g7556 g12642 g13837 +11 1 +.names g7557 g12643 g13839 +11 1 +.names g7559 g12644 g13845 +11 1 +.names g7460 g12645 g13846 +11 1 +.names g7521 g12646 g13847 +11 1 +.names g7579 g12688 g13851 +11 1 +.names g7580 g12689 g13853 +11 1 +.names g5349 g12690 g13854 +11 1 +.names g7541 g12691 g13855 +11 1 +.names g7593 g12742 g13860 +11 1 +.names g5366 g12743 g13862 +11 1 +.names g7582 g12768 g13870 +11 1 +.names g7898 g12775 g13871 +11 1 +.names g7610 g12782 g13878 +11 1 +.names g1234 g12790 g13880 +11 1 +.names g7594 g12807 g13884 +11 1 +.names g7616 g12815 g13892 +11 1 +.names g7619 g12821 g13900 +11 1 +.names g1928 g12829 g13902 +11 1 +.names g7337 g12843 g13904 +11 1 +.names g7925 g12847 g13905 +11 1 +.names g7623 g12850 g13913 +11 1 +.names g7626 g12851 g13914 +11 1 +.names g7632 g12853 g13933 +11 1 +.names g7635 g12859 g13941 +11 1 +.names g2622 g12867 g13943 +11 1 +.names g7141 g12874 g13944 +11 1 +.names g7643 g12881 g13952 +11 1 +.names g7646 g12882 g13953 +11 1 +.names g7652 g12891 g13969 +11 1 +.names g7655 g12892 g13970 +11 1 +.names g7661 g12894 g13989 +11 1 +.names g7664 g12900 g13997 +11 1 +.names g7972 g12907 g13998 +11 1 +.names g7670 g12914 g14006 +11 1 +.names g7673 g12915 g14007 +11 1 +.names g7679 g12921 g14022 +11 1 +.names g7682 g12922 g14023 +11 1 +.names g7688 g12931 g14039 +11 1 +.names g7691 g12932 g14040 +11 1 +.names g7697 g12934 g14059 +11 1 +.names g7703 g12940 g14067 +11 1 +.names g7706 g12943 g14097 +11 1 +.names g7709 g12944 g14098 +11 1 +.names g7715 g12950 g14113 +11 1 +.names g7718 g12951 g14114 +11 1 +.names g7724 g12960 g14130 +11 1 +.names g7727 g12961 g14131 +11 1 +.names g8026 g12965 g14143 +11 1 +.names g7733 g12969 g14182 +11 1 +.names g7736 g12972 g14212 +11 1 +.names g7739 g12973 g14213 +11 1 +.names g7745 g12979 g14228 +11 1 +.names g7748 g12980 g14229 +11 1 +.names g7757 g12993 g14297 +11 1 +.names g7760 g12996 g14327 +11 1 +.names g7763 g12997 g14328 +11 1 +.names g8099 g12998 g14336 +11 1 +.names g7779 g13003 g14419 +11 1 +.names g7841 g13101 g14690 +11 1 +.names g7861 g13117 g14724 +11 1 +.names g7891 g13130 g14752 +11 1 +.names g10779 g7901 g13245 +0- 1 +-0 1 +.names g13245 g10765 g14767 +11 1 +.names g7915 g13141 g14773 +11 1 +.names g8169 g12548 g14884 +11 1 +.names g3940 g13148 g14894 +11 1 +.names g11059 g13151 g14956 +11 1 +.names g4015 g13152 g14957 +11 1 +.names g4016 g13153 g14958 +11 1 +.names g4047 g13154 g14975 +11 1 +.names g8090 g12561 g15020 +11 1 +.names g4110 g13158 g15030 +11 1 +.names g4111 g13159 g15031 +11 1 +.names g4142 g13161 g15046 +11 1 +.names g4143 g13162 g15047 +11 1 +.names g4174 g13163 g15064 +11 1 +.names g7869 g12601 g15093 +11 1 +.names g7872 g12604 g15094 +11 1 +.names g4220 g13167 g15104 +11 1 +.names g4224 g13168 g15105 +11 1 +.names g4249 g13169 g15126 +11 1 +.names g4250 g13170 g15127 +11 1 +.names g4281 g13172 g15142 +11 1 +.names g4282 g13173 g15143 +11 1 +.names g4313 g13174 g15160 +11 1 +.names g8015 g12647 g15171 +11 1 +.names g4346 g13176 g15172 +11 1 +.names g4347 g13177 g15173 +11 1 +.names g640 g12651 g15178 +11 1 +.names g4375 g13178 g15196 +11 1 +.names g4379 g13179 g15197 +11 1 +.names g4404 g13180 g15218 +11 1 +.names g4405 g13181 g15219 +11 1 +.names g4436 g13183 g15234 +11 1 +.names g4437 g13184 g15235 +11 1 +.names g7849 g12692 g15243 +11 1 +.names g7852 g12695 g15244 +11 1 +.names g4474 g13185 g15245 +11 1 +.names g4475 g13186 g15246 +11 1 +.names g4479 g13187 g15247 +11 1 +.names g4357 g12702 g15257 +11 1 +.names g4515 g13188 g15258 +11 1 +.names g4516 g13189 g15259 +11 1 +.names g1326 g12705 g15264 +11 1 +.names g4544 g13190 g15282 +11 1 +.names g4548 g13191 g15283 +11 1 +.names g4573 g13192 g15304 +11 1 +.names g4574 g13193 g15305 +11 1 +.names g7964 g12744 g15320 +11 1 +.names g4601 g13195 g15321 +11 1 +.names g4609 g13196 g15324 +11 1 +.names g4610 g13197 g15325 +11 1 +.names g4489 g12749 g15335 +11 1 +.names g4492 g12752 g15336 +11 1 +.names g4650 g13198 g15337 +11 1 +.names g4651 g13199 g15338 +11 1 +.names g4655 g13200 g15339 +11 1 +.names g4526 g12759 g15349 +11 1 +.names g4691 g13201 g15350 +11 1 +.names g4692 g13202 g15351 +11 1 +.names g2020 g12762 g15356 +11 1 +.names g4720 g13203 g15374 +11 1 +.names g4724 g13204 g15375 +11 1 +.names g7834 g12769 g15388 +11 1 +.names g8246 g12772 g15389 +11 1 +.names g4752 g13205 g15391 +11 1 +.names g4753 g13206 g15392 +11 1 +.names g4620 g12783 g15402 +11 1 +.names g4623 g12786 g15403 +11 1 +.names g4778 g13207 g15407 +11 1 +.names g4786 g13208 g15410 +11 1 +.names g4787 g13209 g15411 +11 1 +.names g4665 g12791 g15421 +11 1 +.names g4668 g12794 g15422 +11 1 +.names g4827 g13210 g15423 +11 1 +.names g4828 g13211 g15424 +11 1 +.names g4832 g13212 g15425 +11 1 +.names g4702 g12801 g15435 +11 1 +.names g4868 g13213 g15436 +11 1 +.names g4869 g13214 g15437 +11 1 +.names g2714 g12804 g15442 +11 1 +.names g7916 g12808 g15452 +11 1 +.names g6898 g12811 g15453 +11 1 +.names g4897 g13218 g15459 +11 1 +.names g4898 g13219 g15460 +11 1 +.names g4763 g12816 g15470 +11 1 +.names g4928 g13220 g15475 +11 1 +.names g4929 g13221 g15476 +11 1 +.names g4797 g12822 g15486 +11 1 +.names g4800 g12825 g15487 +11 1 +.names g4954 g13222 g15491 +11 1 +.names g4962 g13223 g15494 +11 1 +.names g4963 g13224 g15495 +11 1 +.names g4842 g12830 g15505 +11 1 +.names g4845 g12833 g15506 +11 1 +.names g5003 g13225 g15507 +11 1 +.names g5004 g13226 g15508 +11 1 +.names g5008 g13227 g15509 +11 1 +.names g4879 g12840 g15519 +11 1 +.names g8172 g12844 g15520 +11 1 +.names g5033 g13232 g15526 +11 1 +.names g5034 g13233 g15527 +11 1 +.names g5056 g13237 g15545 +11 1 +.names g5057 g13238 g15546 +11 1 +.names g4939 g12854 g15556 +11 1 +.names g5087 g13239 g15561 +11 1 +.names g5088 g13240 g15562 +11 1 +.names g4973 g12860 g15572 +11 1 +.names g4976 g12863 g15573 +11 1 +.names g5113 g13241 g15577 +11 1 +.names g5121 g13242 g15580 +11 1 +.names g5122 g13243 g15581 +11 1 +.names g5018 g12868 g15591 +11 1 +.names g5021 g12871 g15592 +11 1 +.names g7897 g13244 g15593 +11 1 +.names g5148 g13249 g15594 +11 1 +.names g5149 g13250 g15595 +11 1 +.names g5162 g13255 g15604 +11 1 +.names g5163 g13256 g15605 +11 1 +.names g5185 g13260 g15623 +11 1 +.names g5186 g13261 g15624 +11 1 +.names g5098 g12895 g15634 +11 1 +.names g5216 g13262 g15639 +11 1 +.names g5217 g13263 g15640 +11 1 +.names g5132 g12901 g15650 +11 1 +.names g5135 g12904 g15651 +11 1 +.names g8177 g13264 g15658 +11 1 +.names g5233 g13268 g15666 +11 1 +.names g5241 g13272 g15670 +11 1 +.names g5242 g13273 g15671 +11 1 +.names g5255 g13278 g15680 +11 1 +.names g5256 g13279 g15681 +11 1 +.names g5278 g13283 g15699 +11 1 +.names g5279 g13284 g15700 +11 1 +.names g5227 g12935 g15710 +11 1 +.names g7924 g13285 g15717 +11 1 +.names g5296 g13293 g15725 +11 1 +.names g5304 g13297 g15729 +11 1 +.names g5305 g13298 g15730 +11 1 +.names g5318 g13303 g15739 +11 1 +.names g5319 g13304 g15740 +11 1 +.names g7542 g12962 g15753 +11 1 +.names g7837 g13308 g15754 +11 1 +.names g8178 g13309 g15755 +11 1 +.names g5333 g13324 g15765 +11 1 +.names g5341 g13328 g15769 +11 1 +.names g5342 g13329 g15770 +11 1 +.names g13004 g3018 g7549 II22028 +111 1 +.names g7471 g3032 II22028 g15780 +111 1 +.names g7971 g13330 g15781 +11 1 +.names g5361 g13347 g15793 +11 1 +.names g7856 g13351 g15801 +11 1 +.names g8253 g13352 g15802 +11 1 +.names g8025 g13373 g15817 +11 1 +.names g7877 g13398 g15828 +11 1 +.names g7857 g13400 g15829 +11 1 +.names g8098 g11620 g15840 +11 1 +.names g7878 g11642 g15852 +11 1 +.names g13082 g2912 g7522 II22136 +111 1 +.names g7607 g2920 II22136 g15902 +111 1 +.names g5469 g11732 g15998 +11 1 +.names g12013 g10826 g16003 +11 1 +.names g5587 g11734 g16004 +11 1 +.names g5504 g11735 g16008 +11 1 +.names g12071 g10843 g16009 +11 1 +.names g7639 g11736 g16010 +11 1 +.names g12013 g10859 g16015 +11 1 +.names g5601 g11740 g16016 +11 1 +.names g12130 g10862 g16017 +11 1 +.names g6149 g11741 g16018 +11 1 +.names g5507 g11742 g16019 +11 1 +.names g5543 g11745 g16028 +11 1 +.names g12071 g10877 g16029 +11 1 +.names g7667 g11746 g16030 +11 1 +.names g6227 g11747 g16031 +11 1 +.names g12187 g10883 g16032 +11 1 +.names g5546 g11748 g16033 +11 1 +.names g12013 g10892 g16045 +11 1 +.names g5618 g11761 g16046 +11 1 +.names g12130 g10895 g16047 +11 1 +.names g6170 g11762 g16048 +11 1 +.names g6638 g11763 g16049 +11 1 +.names g5590 g11764 g16050 +11 1 +.names g12235 g10901 g16051 +11 1 +.names g5591 g11765 g16052 +11 1 +.names g12071 g10912 g16066 +11 1 +.names g7700 g11774 g16067 +11 1 +.names g6310 g11775 g16068 +11 1 +.names g5346 g11776 g16069 +11 1 +.names g12187 g10921 g16070 +11 1 +.names g5604 g11777 g16071 +11 1 +.names g12275 g10924 g16072 +11 1 +.names g5605 g11778 g16073 +11 1 +.names g5646 g11782 g16074 +11 1 +.names g984 g11787 g16089 +11 1 +.names g12130 g10937 g16100 +11 1 +.names g6197 g11794 g16101 +11 1 +.names g6905 g11795 g16102 +11 1 +.names g5621 g11796 g16103 +11 1 +.names g12235 g10946 g16104 +11 1 +.names g5622 g11797 g16105 +11 1 +.names g12308 g10949 g16106 +11 1 +.names g5666 g11801 g16107 +11 1 +.names g5667 g11802 g16108 +11 1 +.names g5551 g13215 g16111 +11 1 +.names g5684 g11808 g16112 +11 1 +.names g3460 g11809 g16119 +11 1 +.names g1678 g11813 g16127 +11 1 +.names g6444 g11817 g16133 +11 1 +.names g5363 g11818 g16134 +11 1 +.names g12187 g10980 g16135 +11 1 +.names g5640 g11819 g16136 +11 1 +.names g12275 g10983 g16137 +11 1 +.names g5641 g11820 g16138 +11 1 +.names g5704 g11824 g16139 +11 1 +.names g5705 g11825 g16140 +11 1 +.names g5706 g11826 g16141 +11 1 +.names g5592 g13229 g16153 +11 1 +.names g5718 g11834 g16158 +11 1 +.names g5719 g11835 g16159 +11 1 +.names g8286 g11836 g16160 +11 1 +.names g1202 g11837 g16161 +11 1 +.names g5597 g13234 g16162 +11 1 +.names g5736 g11841 g16163 +11 1 +.names g3616 g11842 g16170 +11 1 +.names g2372 g11846 g16178 +11 1 +.names g7149 g11852 g16182 +11 1 +.names g12235 g11014 g16183 +11 1 +.names g5663 g11853 g16184 +11 1 +.names g12308 g11017 g16185 +11 1 +.names g5753 g11856 g16186 +11 1 +.names g5754 g11857 g16187 +11 1 +.names g5755 g11858 g16188 +11 1 +.names g5762 g11866 g16198 +11 1 +.names g5763 g11867 g16199 +11 1 +.names g5764 g11868 g16200 +11 1 +.names g1203 g11871 g16211 +11 1 +.names g5609 g13252 g16212 +11 1 +.names g5776 g11876 g16217 +11 1 +.names g5777 g11877 g16218 +11 1 +.names g8295 g11878 g16219 +11 1 +.names g1896 g11879 g16220 +11 1 +.names g5614 g13257 g16221 +11 1 +.names g5794 g11883 g16222 +11 1 +.names g3772 g11884 g16229 +11 1 +.names g5379 g11886 g16237 +11 1 +.names g12275 g11066 g16238 +11 1 +.names g5700 g11887 g16239 +11 1 +.names g5804 g11891 g16240 +11 1 +.names g5805 g11892 g16241 +11 1 +.names g5806 g11893 g16242 +11 1 +.names g5812 g11898 g16251 +11 1 +.names g5813 g11899 g16252 +11 1 +.names g5814 g11900 g16253 +11 1 +.names g1204 g11904 g16262 +11 1 +.names g5821 g11908 g16263 +11 1 +.names g5822 g11909 g16264 +11 1 +.names g5823 g11910 g16265 +11 1 +.names g1897 g11913 g16276 +11 1 +.names g5634 g13275 g16277 +11 1 +.names g5835 g11918 g16282 +11 1 +.names g5836 g11919 g16283 +11 1 +.names g8304 g11920 g16284 +11 1 +.names g2590 g11921 g16285 +11 1 +.names g5639 g13280 g16286 +11 1 +.names g12308 g11129 g16288 +11 1 +.names g5853 g11929 g16289 +11 1 +.names g5854 g11930 g16290 +11 1 +.names g5855 g11931 g16291 +11 1 +.names g520 g11936 g16298 +11 1 +.names g5860 g11941 g16299 +11 1 +.names g5861 g11942 g16300 +11 1 +.names g5862 g11943 g16301 +11 1 +.names g1205 g11945 g16309 +11 1 +.names g5868 g11948 g16310 +11 1 +.names g5869 g11949 g16311 +11 1 +.names g5870 g11950 g16312 +11 1 +.names g1898 g11954 g16321 +11 1 +.names g5877 g11958 g16322 +11 1 +.names g5878 g11959 g16323 +11 1 +.names g5879 g11960 g16324 +11 1 +.names g2591 g11963 g16335 +11 1 +.names g5662 g13300 g16336 +11 1 +.names g5894 g11968 g16342 +11 1 +.names g5895 g11969 g16343 +11 1 +.names g5896 g11970 g16344 +11 1 +.names g5897 g11971 g16345 +11 1 +.names g5900 g11982 g16347 +11 1 +.names g5901 g11983 g16348 +11 1 +.names g5902 g11984 g16349 +11 1 +.names g981 g11985 g16350 +11 1 +.names g1206 g11989 g16356 +11 1 +.names g5907 g11994 g16357 +11 1 +.names g5908 g11995 g16358 +11 1 +.names g5909 g11996 g16359 +11 1 +.names g1899 g11998 g16367 +11 1 +.names g5915 g12001 g16368 +11 1 +.names g5916 g12002 g16369 +11 1 +.names g5917 g12003 g16370 +11 1 +.names g2592 g12007 g16379 +11 1 +.names g5925 g12020 g16380 +11 1 +.names g5926 g12021 g16381 +11 1 +.names g5927 g12022 g16382 +11 1 +.names g5928 g12023 g16383 +11 1 +.names g5714 g13336 g16385 +11 1 +.names g5933 g12037 g16386 +11 1 +.names g5934 g12038 g16387 +11 1 +.names g5935 g12039 g16388 +11 1 +.names g5936 g12040 g16389 +11 1 +.names g982 g12041 g16390 +11 1 +.names g5939 g12051 g16391 +11 1 +.names g5940 g12052 g16392 +11 1 +.names g5941 g12053 g16393 +11 1 +.names g1675 g12054 g16394 +11 1 +.names g1900 g12058 g16400 +11 1 +.names g5946 g12063 g16401 +11 1 +.names g5947 g12064 g16402 +11 1 +.names g5948 g12065 g16403 +11 1 +.names g2593 g12067 g16411 +11 1 +.names g5954 g12075 g16413 +11 1 +.names g5955 g12076 g16414 +11 1 +.names g5956 g12077 g16415 +11 1 +.names g5957 g12078 g16416 +11 1 +.names g5759 g13356 g16417 +11 1 +.names g5959 g12084 g16418 +11 1 +.names g5960 g12085 g16419 +11 1 +.names g5961 g12086 g16420 +11 1 +.names g5962 g12087 g16421 +11 1 +.names g983 g12088 g16422 +11 1 +.names g5772 g13361 g16423 +11 1 +.names g5967 g12101 g16424 +11 1 +.names g5968 g12102 g16425 +11 1 +.names g5969 g12103 g16426 +11 1 +.names g5970 g12104 g16427 +11 1 +.names g1676 g12105 g16428 +11 1 +.names g5973 g12115 g16429 +11 1 +.names g5974 g12116 g16430 +11 1 +.names g5975 g12117 g16431 +11 1 +.names g2369 g12118 g16432 +11 1 +.names g2594 g12122 g16438 +11 1 +.names g5980 g12134 g16443 +11 1 +.names g5981 g12135 g16444 +11 1 +.names g5808 g13381 g16445 +11 1 +.names g5983 g12147 g16447 +11 1 +.names g5984 g12148 g16448 +11 1 +.names g5985 g12149 g16449 +11 1 +.names g5986 g12150 g16450 +11 1 +.names g5818 g13386 g16451 +11 1 +.names g5988 g12156 g16452 +11 1 +.names g5989 g12157 g16453 +11 1 +.names g5990 g12158 g16454 +11 1 +.names g5991 g12159 g16455 +11 1 +.names g1677 g12160 g16456 +11 1 +.names g5831 g13391 g16457 +11 1 +.names g5996 g12173 g16458 +11 1 +.names g5997 g12174 g16459 +11 1 +.names g5998 g12175 g16460 +11 1 +.names g5999 g12176 g16461 +11 1 +.names g2370 g12177 g16462 +11 1 +.names g14776 g14797 g16142 g16243 g16505 +1111 1 +.names g15065 g13724 g13764 g13797 g16513 +1111 1 +.names g14811 g14849 g16201 g16302 g16527 +1111 1 +.names g15161 g13774 g13805 g13825 g16535 +1111 1 +.names g14863 g14922 g16266 g16360 g16558 +1111 1 +.names g14936 g15003 g16325 g16404 g16590 +1111 1 +.names g15022 g15096 g16607 +11 1 +.names g15118 g15188 g16625 +11 1 +.names g15210 g15274 g16639 +11 1 +.names g15296 g15366 g16650 +11 1 +.names g6226 g14764 g16850 +11 1 +.names g15722 g8646 g16855 +11 1 +.names g6443 g14794 g16856 +11 1 +.names g15762 g8662 g16859 +11 1 +.names g15790 g8681 g16864 +11 1 +.names g6896 g14881 g16865 +11 1 +.names g15813 g8693 g16879 +11 1 +.names g7156 g14959 g16894 +11 1 +.names g7335 g15017 g16907 +11 1 +.names g7838 g15032 g16908 +11 1 +.names g6908 g15033 g16909 +11 1 +.names g7352 g15048 g16923 +11 1 +.names g7858 g15128 g16938 +11 1 +.names g7158 g15129 g16939 +11 1 +.names g7482 g15144 g16953 +11 1 +.names g7520 g15170 g16964 +11 1 +.names g7529 g15174 g16966 +11 1 +.names g7827 g15175 g16967 +11 1 +.names g6672 g15176 g16968 +11 1 +.names g7888 g15220 g16969 +11 1 +.names g7354 g15221 g16970 +11 1 +.names g7538 g15236 g16984 +11 1 +.names g7555 g15260 g16987 +11 1 +.names g7842 g15261 g16988 +11 1 +.names g6974 g15262 g16989 +11 1 +.names g7912 g15306 g16990 +11 1 +.names g7484 g15307 g16991 +11 1 +.names g7576 g15322 g16993 +11 1 +.names g7819 g15323 g16994 +11 1 +.names g7578 g15352 g16997 +11 1 +.names g7862 g15353 g16998 +11 1 +.names g7224 g15354 g16999 +11 1 +.names g3254 g10694 g14144 g17001 +111 1 +.names g7996 g15390 g17015 +11 1 +.names g7590 g15408 g17017 +11 1 +.names g7830 g15409 g17018 +11 1 +.names g7592 g15438 g17021 +11 1 +.names g7892 g15439 g17022 +11 1 +.names g7420 g15440 g17023 +11 1 +.names g7604 g15458 g17028 +11 1 +.names g3410 g10714 g14259 g17031 +111 1 +.names g8071 g15474 g17045 +11 1 +.names g7605 g15492 g17047 +11 1 +.names g7845 g15493 g17048 +11 1 +.names g7153 g15524 g17055 +11 1 +.names g7953 g15525 g17056 +11 1 +.names g7613 g15544 g17062 +11 1 +.names g3566 g10735 g14381 g17065 +111 1 +.names g8156 g15560 g17079 +11 1 +.names g7614 g15578 g17081 +11 1 +.names g7865 g15579 g17082 +11 1 +.names g7629 g13954 g17084 +11 1 +.names g7349 g15602 g17090 +11 1 +.names g8004 g15603 g17091 +11 1 +.names g7622 g15622 g17097 +11 1 +.names g3722 g10754 g14493 g17100 +111 1 +.names g8242 g15638 g17114 +11 1 +.names g7649 g14008 g17116 +11 1 +.names g7906 g15665 g17117 +11 1 +.names g7658 g14024 g17122 +11 1 +.names g7479 g15678 g17128 +11 1 +.names g8079 g15679 g17129 +11 1 +.names g7638 g15698 g17135 +11 1 +.names g7676 g14068 g17138 +11 1 +.names g7685 g14099 g17143 +11 1 +.names g7958 g15724 g17144 +11 1 +.names g7694 g14115 g17149 +11 1 +.names g7535 g15737 g17155 +11 1 +.names g8164 g15738 g17156 +11 1 +.names g7712 g14183 g17161 +11 1 +.names g7721 g14214 g17166 +11 1 +.names g8009 g15764 g17167 +11 1 +.names g7730 g14230 g17172 +11 1 +.names g7742 g14298 g17176 +11 1 +.names g7751 g14329 g17181 +11 1 +.names g8084 g15792 g17182 +11 1 +.names g7766 g14420 g17193 +11 1 +.names g8024 g15991 g17268 +11 1 +.names g8097 g15994 g17301 +11 1 +.names g8176 g15997 g17339 +11 1 +.names g3942 g14960 g17352 +11 1 +.names g3945 g14963 g17353 +11 1 +.names g8250 g16001 g17381 +11 1 +.names g8252 g16002 g17382 +11 1 +.names g3941 g16005 g17393 +11 1 +.names g6177 g15034 g17395 +11 1 +.names g4020 g15037 g17396 +11 1 +.names g4023 g15040 g17397 +11 1 +.names g4026 g15043 g17398 +11 1 +.names g4049 g15049 g17408 +11 1 +.names g4052 g15052 g17409 +11 1 +.names g3994 g16007 g17428 +11 1 +.names g6284 g16011 g17446 +11 1 +.names g4115 g15106 g17447 +11 1 +.names g4118 g15109 g17448 +11 1 +.names g4121 g15112 g17449 +11 1 +.names g4124 g15115 g17450 +11 1 +.names g4048 g16012 g17460 +11 1 +.names g6209 g15130 g17461 +11 1 +.names g4147 g15133 g17462 +11 1 +.names g4150 g15136 g17463 +11 1 +.names g4153 g15139 g17464 +11 1 +.names g4176 g15145 g17474 +11 1 +.names g4179 g15148 g17475 +11 1 +.names g4089 g16013 g17485 +11 1 +.names g4091 g16014 g17486 +11 1 +.names g6675 g16023 g17506 +11 1 +.names g4225 g15179 g17508 +11 1 +.names g4228 g15182 g17509 +11 1 +.names g4231 g15185 g17510 +11 1 +.names g6421 g16025 g17526 +11 1 +.names g4254 g15198 g17527 +11 1 +.names g4257 g15201 g17528 +11 1 +.names g4260 g15204 g17529 +11 1 +.names g4263 g15207 g17530 +11 1 +.names g4175 g16026 g17540 +11 1 +.names g6298 g15222 g17541 +11 1 +.names g4286 g15225 g17542 +11 1 +.names g4289 g15228 g17543 +11 1 +.names g4292 g15231 g17544 +11 1 +.names g4315 g15237 g17554 +11 1 +.names g4318 g15240 g17555 +11 1 +.names g4201 g16027 g17556 +11 1 +.names g4348 g15248 g17576 +11 1 +.names g4351 g15251 g17577 +11 1 +.names g4354 g15254 g17578 +11 1 +.names g6977 g16039 g17597 +11 1 +.names g4380 g15265 g17598 +11 1 +.names g4383 g15268 g17599 +11 1 +.names g4386 g15271 g17600 +11 1 +.names g6626 g16041 g17616 +11 1 +.names g4409 g15284 g17617 +11 1 +.names g4412 g15287 g17618 +11 1 +.names g4415 g15290 g17619 +11 1 +.names g4418 g15293 g17620 +11 1 +.names g4314 g16042 g17630 +11 1 +.names g6435 g15308 g17631 +11 1 +.names g4441 g15311 g17632 +11 1 +.names g4444 g15314 g17633 +11 1 +.names g4447 g15317 g17634 +11 1 +.names g4322 g16043 g17635 +11 1 +.names g4324 g16044 g17636 +11 1 +.names g4480 g15326 g17652 +11 1 +.names g4483 g15329 g17653 +11 1 +.names g4486 g15332 g17654 +11 1 +.names g4517 g15340 g17673 +11 1 +.names g4520 g15343 g17674 +11 1 +.names g4523 g15346 g17675 +11 1 +.names g7227 g16061 g17694 +11 1 +.names g4549 g15357 g17695 +11 1 +.names g4552 g15360 g17696 +11 1 +.names g4555 g15363 g17697 +11 1 +.names g6890 g16063 g17713 +11 1 +.names g4578 g15376 g17714 +11 1 +.names g4581 g15379 g17715 +11 1 +.names g4584 g15382 g17716 +11 1 +.names g4587 g15385 g17717 +11 1 +.names g4451 g16064 g17718 +11 1 +.names g2993 g16065 g17719 +11 1 +.names g4611 g15393 g17734 +11 1 +.names g4614 g15396 g17735 +11 1 +.names g4617 g15399 g17736 +11 1 +.names g4626 g15404 g17737 +11 1 +.names g4656 g15412 g17752 +11 1 +.names g4659 g15415 g17753 +11 1 +.names g4662 g15418 g17754 +11 1 +.names g4693 g15426 g17773 +11 1 +.names g4696 g15429 g17774 +11 1 +.names g4699 g15432 g17775 +11 1 +.names g7423 g16097 g17794 +11 1 +.names g4725 g15443 g17795 +11 1 +.names g4728 g15446 g17796 +11 1 +.names g4731 g15449 g17797 +11 1 +.names g4591 g16099 g17798 +11 1 +.names g4754 g15461 g17812 +11 1 +.names g4757 g15464 g17813 +11 1 +.names g4760 g15467 g17814 +11 1 +.names g4766 g15471 g17824 +11 1 +.names g4788 g15477 g17835 +11 1 +.names g4791 g15480 g17836 +11 1 +.names g4794 g15483 g17837 +11 1 +.names g4803 g15488 g17838 +11 1 +.names g4833 g15496 g17853 +11 1 +.names g4836 g15499 g17854 +11 1 +.names g4839 g15502 g17855 +11 1 +.names g4870 g15510 g17874 +11 1 +.names g4873 g15513 g17875 +11 1 +.names g4876 g15516 g17876 +11 1 +.names g2998 g15521 g17877 +11 1 +.names g4899 g15528 g17900 +11 1 +.names g4902 g15531 g17901 +11 1 +.names g4905 g15534 g17902 +11 1 +.names g4908 g15537 g17912 +11 1 +.names g4930 g15547 g17924 +11 1 +.names g4933 g15550 g17925 +11 1 +.names g4936 g15553 g17926 +11 1 +.names g4942 g15557 g17936 +11 1 +.names g4964 g15563 g17947 +11 1 +.names g4967 g15566 g17948 +11 1 +.names g4970 g15569 g17949 +11 1 +.names g4979 g15574 g17950 +11 1 +.names g5009 g15582 g17965 +11 1 +.names g5012 g15585 g17966 +11 1 +.names g5015 g15588 g17967 +11 1 +.names g5035 g15596 g17989 +11 1 +.names g5038 g15599 g17990 +11 1 +.names g5058 g15606 g18011 +11 1 +.names g5061 g15609 g18012 +11 1 +.names g5064 g15612 g18013 +11 1 +.names g5067 g15615 g18023 +11 1 +.names g5089 g15625 g18035 +11 1 +.names g5092 g15628 g18036 +11 1 +.names g5095 g15631 g18037 +11 1 +.names g5101 g15635 g18047 +11 1 +.names g5123 g15641 g18058 +11 1 +.names g5126 g15644 g18059 +11 1 +.names g5129 g15647 g18060 +11 1 +.names g5138 g15652 g18061 +11 1 +.names g7462 g15655 g18062 +11 1 +.names g5150 g15667 g18088 +11 1 +.names g5164 g15672 g18106 +11 1 +.names g5167 g15675 g18107 +11 1 +.names g5187 g15682 g18128 +11 1 +.names g5190 g15685 g18129 +11 1 +.names g5193 g15688 g18130 +11 1 +.names g5196 g15691 g18140 +11 1 +.names g5218 g15701 g18152 +11 1 +.names g5221 g15704 g18153 +11 1 +.names g5224 g15707 g18154 +11 1 +.names g5230 g15711 g18164 +11 1 +.names g2883 g16287 g18165 +11 1 +.names g7527 g15714 g18169 +11 1 +.names g5243 g15726 g18204 +11 1 +.names g5257 g15731 g18222 +11 1 +.names g5260 g15734 g18223 +11 1 +.names g5280 g15741 g18244 +11 1 +.names g5283 g15744 g18245 +11 1 +.names g5286 g15747 g18246 +11 1 +.names g5289 g15750 g18256 +11 1 +.names g5306 g15766 g18311 +11 1 +.names g5320 g15771 g18329 +11 1 +.names g5323 g15774 g18330 +11 1 +.names g2888 g15777 g18333 +11 1 +.names g5343 g15794 g18404 +11 1 +.names g14776 g14837 g16142 II24619 +111 1 +.names g13677 g13750 II24619 g18547 +111 1 +.names g14811 g14910 g16201 II24689 +111 1 +.names g13714 g13791 II24689 g18597 +111 1 +.names g14863 g14991 g16266 II24738 +111 1 +.names g13764 g13819 II24738 g18629 +111 1 +.names g14936 g15080 g16325 II24758 +111 1 +.names g13805 g13840 II24758 g18638 +111 1 +.names g14776 g14895 g16142 g13750 g18645 +1111 1 +.names g14895 g16142 g16243 g18647 +111 1 +.names g14811 g14976 g16201 g13791 g18648 +1111 1 +.names g14776 g14837 g13657 g16189 g18649 +1111 1 +.names g14976 g16201 g16302 g18650 +111 1 +.names g14863 g15065 g16266 g13819 g18651 +1111 1 +.names g14797 g13657 g13677 g16243 g18652 +1111 1 +.names g14811 g14910 g13687 g16254 g18653 +1111 1 +.names g15065 g16266 g16360 g18654 +111 1 +.names g14936 g15161 g16325 g13840 g18655 +1111 1 +.names g14776 g14837 g16189 g13706 g18665 +1111 1 +.names g14849 g13687 g13714 g16302 g18666 +1111 1 +.names g14863 g14991 g13724 g16313 g18667 +1111 1 +.names g15161 g16325 g16404 g18668 +111 1 +.names g14811 g14910 g16254 g13756 g18688 +1111 1 +.names g14922 g13724 g13764 g16360 g18689 +1111 1 +.names g14936 g15080 g13774 g16371 g18690 +1111 1 +.names g14863 g14991 g16313 g13797 g18717 +1111 1 +.names g15003 g13774 g13805 g16404 g18718 +1111 1 +.names g14936 g15080 g16371 g13825 g18753 +1111 1 +.names g13519 g16154 g18982 +11 1 +.names g13530 g16213 g18990 +11 1 +.names g14895 g13657 g13677 g13706 g18994 +1111 1 +.names g13541 g16278 g18997 +11 1 +.names g14976 g13687 g13714 g13756 g19007 +1111 1 +.names g13552 g16337 g19010 +11 1 +.names g18679 g14910 g13687 g16254 g19063 +1111 1 +.names g14797 g18692 g16142 g16189 g19079 +1111 1 +.names g18708 g14991 g13724 g16313 g19080 +1111 1 +.names g15904 g14642 g17215 +00 1 +.names g17215 g16540 g19087 +11 1 +.names g18656 g14797 g16189 g13706 g19088 +1111 1 +.names g14849 g18728 g16201 g16254 g19089 +1111 1 +.names g18744 g15080 g13774 g16371 g19090 +1111 1 +.names g14776 g18670 g18692 g16293 g19092 +1111 1 +.names g15933 g14669 g17218 +00 1 +.names g17218 g16572 g19093 +11 1 +.names g18679 g14849 g16254 g13756 g19094 +1111 1 +.names g14922 g18765 g16266 g16313 g19095 +1111 1 +.names g18656 g18670 g18720 II25280 +111 1 +.names g13657 g16243 II25280 g19097 +111 1 +.names g14811 g18699 g18728 g16351 g19099 +1111 1 +.names g15962 g14703 g17220 +00 1 +.names g17220 g16596 g19100 +11 1 +.names g18708 g14922 g16313 g13797 g19101 +1111 1 +.names g15003 g18796 g16325 g16371 g19102 +1111 1 +.names g18679 g18699 g18758 II25291 +111 1 +.names g13687 g16302 II25291 g19104 +111 1 +.names g14863 g18735 g18765 g16395 g19106 +1111 1 +.names g15981 g14737 g17223 +00 1 +.names g17223 g16616 g19107 +11 1 +.names g18744 g15003 g16371 g13825 g19108 +1111 1 +.names g18708 g18735 g18789 II25300 +111 1 +.names g13724 g16360 II25300 g19109 +111 1 +.names g14936 g18772 g18796 g16433 g19111 +1111 1 +.names g14657 g16633 g19112 +11 1 +.names g18744 g18772 g18815 II25311 +111 1 +.names g13774 g16404 II25311 g19116 +111 1 +.names g14691 g16644 g19117 +11 1 +.names g14725 g16656 g19124 +11 1 +.names g14753 g16673 g19131 +11 1 +.names g14642 g14657 g17159 +0- 1 +-0 1 +.names g17159 g16719 g19142 +11 1 +.names g14669 g14691 g17174 +0- 1 +-0 1 +.names g17174 g16761 g19143 +11 1 +.names g14703 g14725 g17191 +0- 1 +-0 1 +.names g17191 g16788 g19146 +11 1 +.names g14737 g14753 g17202 +0- 1 +-0 1 +.names g17202 g16817 g19148 +11 1 +.names g17189 g8602 g19150 +11 1 +.names g17200 g8614 g19155 +11 1 +.names g17207 g8627 g19161 +11 1 +.names g17212 g8637 g19166 +11 1 +.names II22706 II22707 g16662 +0- 1 +-0 1 +.names g16662 g12125 g19228 +11 1 +.names II22885 II22886 g16935 +0- 1 +-0 1 +.names g16935 g8802 g19236 +11 1 +.names g16867 g14158 g14071 g19241 +111 1 +.names g16662 g8817 g19248 +11 1 +.names g18725 g9527 g19252 +11 1 +.names g16895 g14273 g14186 g19254 +111 1 +.names g16749 g3124 g19260 +11 1 +.names g16924 g14395 g14301 g19267 +111 1 +.names g16954 g14507 g14423 g19282 +111 1 +.names g18063 g3111 g19284 +11 1 +.names g16749 g7642 g19285 +11 1 +.names g17029 g8580 g19289 +11 1 +.names g16867 g16543 g14071 g19303 +111 1 +.names g17063 g8587 g19307 +11 1 +.names g18063 g3110 g19316 +11 1 +.names g16749 g3126 g19317 +11 1 +.names g16867 g16515 g14158 g19320 +111 1 +.names g16895 g16575 g14186 g19324 +111 1 +.names g17098 g8594 g19328 +11 1 +.names g16895 g16546 g14273 g19347 +111 1 +.names g16924 g16599 g14301 g19351 +111 1 +.names g17136 g8605 g19355 +11 1 +.names g18063 g3112 g19356 +11 1 +.names g16924 g16578 g14395 g19381 +111 1 +.names g16954 g16619 g14423 g19385 +111 1 +.names g16954 g16602 g14507 g19413 +111 1 +.names g16884 g14797 g14776 g19449 +111 1 +.names g16913 g14849 g14811 g19476 +111 1 +.names g16943 g14922 g14863 g19499 +111 1 +.names g16974 g15003 g14936 g19520 +111 1 +.names g16884 g16722 g14776 g19531 +111 1 +.names g16884 g16697 g14797 g19540 +111 1 +.names g16913 g16764 g14811 g19541 +111 1 +.names g16913 g16728 g14849 g19544 +111 1 +.names g16943 g16791 g14863 g19545 +111 1 +.names g16943 g16770 g14922 g19547 +111 1 +.names g16974 g16820 g14936 g19548 +111 1 +.names g7950 g17230 g19549 +11 1 +.names g16974 g16797 g15003 g19551 +111 1 +.names g14956 g12564 g16829 +00 1 +.names g16829 g6048 g19552 +11 1 +.names g7990 g17237 g19553 +11 1 +.names g7993 g17240 g19554 +11 1 +.names g8001 g17243 g19555 +11 1 +.names g8053 g17249 g19557 +11 1 +.names g8056 g17252 g19558 +11 1 +.names g8059 g17255 g19559 +11 1 +.names g8065 g17259 g19560 +11 1 +.names g8068 g17262 g19561 +11 1 +.names g8076 g17265 g19562 +11 1 +.names g8123 g17272 g19564 +11 1 +.names g8126 g17275 g19565 +11 1 +.names g8129 g17278 g19566 +11 1 +.names g8138 g17282 g19567 +11 1 +.names g8141 g17285 g19568 +11 1 +.names g8144 g17288 g19569 +11 1 +.names g8150 g17291 g19570 +11 1 +.names g8153 g17294 g19571 +11 1 +.names g8161 g17297 g19572 +11 1 +.names g8191 g17304 g19574 +11 1 +.names g8194 g17307 g19575 +11 1 +.names g8197 g17310 g19576 +11 1 +.names g640 g18756 g19584 +11 1 +.names g692 g18757 g19585 +11 1 +.names g8209 g17315 g19586 +11 1 +.names g8212 g17318 g19587 +11 1 +.names g8215 g17321 g19588 +11 1 +.names g8224 g17324 g19589 +11 1 +.names g8227 g17327 g19590 +11 1 +.names g8230 g17330 g19591 +11 1 +.names g8236 g17333 g19592 +11 1 +.names g8239 g17336 g19593 +11 1 +.names g16935 g12555 g19594 +11 1 +.names g3922 g17342 g19597 +11 1 +.names g3925 g17345 g19598 +11 1 +.names g3928 g17348 g19599 +11 1 +.names g633 g18783 g19600 +11 1 +.names g640 g18784 g19601 +11 1 +.names g633 g18785 g19602 +11 1 +.names g692 g18786 g19603 +11 1 +.names g3948 g17354 g19604 +11 1 +.names g3951 g17357 g19605 +11 1 +.names g3954 g17360 g19606 +11 1 +.names g1326 g18787 g19614 +11 1 +.names g1378 g18788 g19615 +11 1 +.names g3966 g17363 g19616 +11 1 +.names g3969 g17366 g19617 +11 1 +.names g3972 g17369 g19618 +11 1 +.names g3981 g17372 g19619 +11 1 +.names g3984 g17375 g19620 +11 1 +.names g3987 g17378 g19621 +11 1 +.names g4000 g17384 g19623 +11 1 +.names g4003 g17387 g19624 +11 1 +.names g4006 g17390 g19625 +11 1 +.names g640 g18805 g19626 +11 1 +.names g633 g18806 g19627 +11 1 +.names g653 g18807 g19628 +11 1 +.names g692 g18808 g19629 +11 1 +.names g4029 g17399 g19630 +11 1 +.names g4032 g17402 g19631 +11 1 +.names g4035 g17405 g19632 +11 1 +.names g1319 g18809 g19633 +11 1 +.names g1326 g18810 g19634 +11 1 +.names g1319 g18811 g19635 +11 1 +.names g1378 g18812 g19636 +11 1 +.names g4055 g17410 g19637 +11 1 +.names g4058 g17413 g19638 +11 1 +.names g4061 g17416 g19639 +11 1 +.names g2020 g18813 g19647 +11 1 +.names g2072 g18814 g19648 +11 1 +.names g4073 g17419 g19649 +11 1 +.names g4076 g17422 g19650 +11 1 +.names g4079 g17425 g19651 +11 1 +.names g4095 g17430 g19653 +11 1 +.names g4098 g17433 g19654 +11 1 +.names g4101 g17436 g19655 +11 1 +.names g4104 g17439 g19656 +11 1 +.names g633 g18822 g19660 +11 1 +.names g653 g18823 g19661 +11 1 +.names g646 g18824 g19662 +11 1 +.names g4127 g17451 g19663 +11 1 +.names g4130 g17454 g19664 +11 1 +.names g4133 g17457 g19665 +11 1 +.names g1326 g18825 g19666 +11 1 +.names g1319 g18826 g19667 +11 1 +.names g1339 g18827 g19668 +11 1 +.names g1378 g18828 g19669 +11 1 +.names g4156 g17465 g19670 +11 1 +.names g4159 g17468 g19671 +11 1 +.names g4162 g17471 g19672 +11 1 +.names g2013 g18829 g19673 +11 1 +.names g2020 g18830 g19674 +11 1 +.names g2013 g18831 g19675 +11 1 +.names g2072 g18832 g19676 +11 1 +.names g4182 g17476 g19677 +11 1 +.names g4185 g17479 g19678 +11 1 +.names g4188 g17482 g19679 +11 1 +.names g2714 g18833 g19687 +11 1 +.names g2766 g18834 g19688 +11 1 +.names g15021 g12607 g16841 +00 1 +.names g16841 g10865 g19691 +11 1 +.names g4205 g17487 g19692 +11 1 +.names g4208 g17490 g19693 +11 1 +.names g4211 g17493 g19694 +11 1 +.names g4214 g17496 g19695 +11 1 +.names g653 g18838 g19697 +11 1 +.names g646 g18839 g19698 +11 1 +.names g660 g18840 g19699 +11 1 +.names g17815 g16024 g19700 +11 1 +.names g4234 g17511 g19701 +11 1 +.names g4237 g17514 g19702 +11 1 +.names g4240 g17517 g19703 +11 1 +.names g4243 g17520 g19704 +11 1 +.names g1319 g18841 g19708 +11 1 +.names g1339 g18842 g19709 +11 1 +.names g1332 g18843 g19710 +11 1 +.names g4266 g17531 g19711 +11 1 +.names g4269 g17534 g19712 +11 1 +.names g4272 g17537 g19713 +11 1 +.names g2020 g18844 g19714 +11 1 +.names g2013 g18845 g19715 +11 1 +.names g2033 g18846 g19716 +11 1 +.names g2072 g18847 g19717 +11 1 +.names g4295 g17545 g19718 +11 1 +.names g4298 g17548 g19719 +11 1 +.names g4301 g17551 g19720 +11 1 +.names g2707 g18848 g19721 +11 1 +.names g2714 g18849 g19722 +11 1 +.names g2707 g18850 g19723 +11 1 +.names g2766 g18851 g19724 +11 1 +.names g15095 g12650 g16847 +00 1 +.names g16847 g6131 g19726 +11 1 +.names g4329 g17557 g19727 +11 1 +.names g4332 g17560 g19728 +11 1 +.names g4335 g17563 g19729 +11 1 +.names g653 g17573 g19730 +11 1 +.names g646 g18853 g19731 +11 1 +.names g660 g18854 g19732 +11 1 +.names g672 g18855 g19733 +11 1 +.names g17815 g16034 g19734 +11 1 +.names g17903 g16035 g19735 +11 1 +.names g4360 g17579 g19736 +11 1 +.names g4363 g17582 g19737 +11 1 +.names g4366 g17585 g19738 +11 1 +.names g4369 g17588 g19739 +11 1 +.names g1339 g18856 g19741 +11 1 +.names g1332 g18857 g19742 +11 1 +.names g1346 g18858 g19743 +11 1 +.names g17927 g16040 g19744 +11 1 +.names g4389 g17601 g19745 +11 1 +.names g4392 g17604 g19746 +11 1 +.names g4395 g17607 g19747 +11 1 +.names g4398 g17610 g19748 +11 1 +.names g2013 g18859 g19752 +11 1 +.names g2033 g18860 g19753 +11 1 +.names g2026 g18861 g19754 +11 1 +.names g4421 g17621 g19755 +11 1 +.names g4424 g17624 g19756 +11 1 +.names g4427 g17627 g19757 +11 1 +.names g2714 g18862 g19758 +11 1 +.names g2707 g18863 g19759 +11 1 +.names g2727 g18864 g19760 +11 1 +.names g2766 g18865 g19761 +11 1 +.names g4453 g17637 g19764 +11 1 +.names g660 g18870 g19765 +11 1 +.names g672 g18871 g19766 +11 1 +.names g666 g18872 g19767 +11 1 +.names g17815 g16054 g19768 +11 1 +.names g17903 g16055 g19769 +11 1 +.names g4498 g17655 g19770 +11 1 +.names g4501 g17658 g19771 +11 1 +.names g4504 g17661 g19772 +11 1 +.names g1339 g17670 g19773 +11 1 +.names g1332 g18874 g19774 +11 1 +.names g1346 g18875 g19775 +11 1 +.names g1358 g18876 g19776 +11 1 +.names g17927 g16056 g19777 +11 1 +.names g18014 g16057 g19778 +11 1 +.names g4529 g17676 g19779 +11 1 +.names g4532 g17679 g19780 +11 1 +.names g4535 g17682 g19781 +11 1 +.names g4538 g17685 g19782 +11 1 +.names g2033 g18877 g19784 +11 1 +.names g2026 g18878 g19785 +11 1 +.names g2040 g18879 g19786 +11 1 +.names g18038 g16062 g19787 +11 1 +.names g4558 g17698 g19788 +11 1 +.names g4561 g17701 g19789 +11 1 +.names g4564 g17704 g19790 +11 1 +.names g4567 g17707 g19791 +11 1 +.names g2707 g18880 g19795 +11 1 +.names g2727 g18881 g19796 +11 1 +.names g2720 g18882 g19797 +11 1 +.names g18174 g18341 g17974 II26240 +111 1 +.names g17640 g18074 II26240 g19799 +111 1 +.names g672 g18891 g19802 +11 1 +.names g666 g18892 g19803 +11 1 +.names g679 g18893 g19804 +11 1 +.names g17903 g16088 g19805 +11 1 +.names g4629 g17738 g19806 +11 1 +.names g1346 g18896 g19807 +11 1 +.names g1358 g18897 g19808 +11 1 +.names g1352 g18898 g19809 +11 1 +.names g17927 g16090 g19810 +11 1 +.names g18014 g16091 g19811 +11 1 +.names g4674 g17755 g19812 +11 1 +.names g4677 g17758 g19813 +11 1 +.names g4680 g17761 g19814 +11 1 +.names g2033 g17770 g19815 +11 1 +.names g2026 g18900 g19816 +11 1 +.names g2040 g18901 g19817 +11 1 +.names g2052 g18902 g19818 +11 1 +.names g18038 g16092 g19819 +11 1 +.names g18131 g16093 g19820 +11 1 +.names g4705 g17776 g19821 +11 1 +.names g4708 g17779 g19822 +11 1 +.names g4711 g17782 g19823 +11 1 +.names g4714 g17785 g19824 +11 1 +.names g2727 g18903 g19826 +11 1 +.names g2720 g18904 g19827 +11 1 +.names g2734 g18905 g19828 +11 1 +.names g18155 g16098 g19829 +11 1 +.names g7143 g18908 g19836 +11 1 +.names g6901 g17799 g19837 +11 1 +.names g666 g18909 g19839 +11 1 +.names g679 g18910 g19840 +11 1 +.names g686 g18911 g19841 +11 1 +.names g18188 g18089 g17991 II26282 +111 1 +.names g14525 g13922 II26282 g19842 +111 1 +.names g18281 g18436 g18091 II26285 +111 1 +.names g17741 g18190 II26285 g19843 +111 1 +.names g1358 g18914 g19846 +11 1 +.names g1352 g18915 g19847 +11 1 +.names g1365 g18916 g19848 +11 1 +.names g18014 g16126 g19849 +11 1 +.names g4806 g17839 g19850 +11 1 +.names g2040 g18919 g19851 +11 1 +.names g2052 g18920 g19852 +11 1 +.names g2046 g18921 g19853 +11 1 +.names g18038 g16128 g19854 +11 1 +.names g18131 g16129 g19855 +11 1 +.names g4851 g17856 g19856 +11 1 +.names g4854 g17859 g19857 +11 1 +.names g4857 g17862 g19858 +11 1 +.names g2727 g17871 g19859 +11 1 +.names g2720 g18923 g19860 +11 1 +.names g2734 g18924 g19861 +11 1 +.names g2746 g18925 g19862 +11 1 +.names g18155 g16130 g19863 +11 1 +.names g18247 g16131 g19864 +11 1 +.names g14158 g14347 g16498 +00 1 +.names g16498 g16867 g19001 g19868 +111 1 +.names g679 g18926 g19869 +11 1 +.names g686 g18927 g19870 +11 1 +.names g18353 g13958 g14011 II26311 +111 1 +.names g14086 g18275 II26311 g19871 +111 1 +.names g1352 g18928 g19872 +11 1 +.names g1365 g18929 g19873 +11 1 +.names g1372 g18930 g19874 +11 1 +.names g18295 g18205 g18108 II26317 +111 1 +.names g14580 g13978 II26317 g19875 +111 1 +.names g18374 g18509 g18207 II26320 +111 1 +.names g17842 g18297 II26320 g19876 +111 1 +.names g2052 g18933 g19879 +11 1 +.names g2046 g18934 g19880 +11 1 +.names g2059 g18935 g19881 +11 1 +.names g18131 g16177 g19882 +11 1 +.names g4982 g17951 g19883 +11 1 +.names g2734 g18938 g19884 +11 1 +.names g2746 g18939 g19885 +11 1 +.names g2740 g18940 g19886 +11 1 +.names g18155 g16179 g19887 +11 1 +.names g18247 g16180 g19888 +11 1 +.names g2912 g18943 g19889 +11 1 +.names g686 g18945 g19895 +11 1 +.names g14273 g14459 g16520 +00 1 +.names g16520 g16895 g16507 g19899 +111 1 +.names g1365 g18946 g19900 +11 1 +.names g1372 g18947 g19901 +11 1 +.names g18448 g14028 g14102 II26348 +111 1 +.names g14201 g18368 II26348 g19902 +111 1 +.names g2046 g18948 g19903 +11 1 +.names g2059 g18949 g19904 +11 1 +.names g2066 g18950 g19905 +11 1 +.names g18388 g18312 g18224 II26354 +111 1 +.names g14614 g14048 II26354 g19906 +111 1 +.names g18469 g18573 g18314 II26357 +111 1 +.names g17954 g18390 II26357 g19907 +111 1 +.names g2746 g18953 g19910 +11 1 +.names g2740 g18954 g19911 +11 1 +.names g2753 g18955 g19912 +11 1 +.names g18247 g16236 g19913 +11 1 +.names g3018 g18958 g19914 +11 1 +.names g1372 g18961 g19920 +11 1 +.names g14395 g14546 g16551 +00 1 +.names g16551 g16924 g16529 g19924 +111 1 +.names g2059 g18962 g19925 +11 1 +.names g2066 g18963 g19926 +11 1 +.names g18521 g14119 g14217 II26377 +111 1 +.names g14316 g18463 II26377 g19927 +111 1 +.names g2740 g18964 g19928 +11 1 +.names g2753 g18965 g19929 +11 1 +.names g2760 g18966 g19930 +11 1 +.names g18483 g18405 g18331 II26383 +111 1 +.names g14637 g14139 II26383 g19931 +111 1 +.names g2917 g18166 g19932 +11 1 +.names g2066 g18972 g19935 +11 1 +.names g14507 g14601 g16583 +00 1 +.names g16583 g16954 g16560 g19939 +111 1 +.names g2753 g18973 g19940 +11 1 +.names g2760 g18974 g19941 +11 1 +.names g18585 g14234 g14332 II26396 +111 1 +.names g14438 g18536 II26396 g19942 +111 1 +.names g7562 g18976 g19943 +11 1 +.names g3028 g18258 g19944 +11 1 +.names g5293 g18278 g19949 +11 1 +.names g2760 g18987 g19952 +11 1 +.names g7566 g18334 g19953 +11 1 +.names II24625 II24626 g18553 +0- 1 +-0 1 +.names II24531 II24532 g18491 +0- 1 +-0 1 +.names II24453 II24454 g18431 +0- 1 +-0 1 +.names g18553 g18491 g18431 II26416 +111 1 +.names II24362 II24363 g18354 +0- 1 +-0 1 +.names II24272 II24273 g18276 +0- 1 +-0 1 +.names g18354 g18276 II26416 g19970 +111 1 +.names g5327 g18355 g19971 +11 1 +.names g5330 g18371 g19976 +11 1 +.names II24279 II24280 g18277 +0- 1 +-0 1 +.names II24187 II24188 g18189 +0- 1 +-0 1 +.names II24103 II24104 g18090 +0- 1 +-0 1 +.names g18277 g18189 g18090 II26432 +111 1 +.names II24029 II24030 g17992 +0- 1 +-0 1 +.names II23959 II23960 g17913 +0- 1 +-0 1 +.names g17992 g17913 II26432 g19982 +111 1 +.names g5352 g18432 g19983 +11 1 +.names II24695 II24696 g18603 +0- 1 +-0 1 +.names II24633 II24634 g18555 +0- 1 +-0 1 +.names II24554 II24555 g18504 +0- 1 +-0 1 +.names g18603 g18555 g18504 II26440 +111 1 +.names II24475 II24476 g18449 +0- 1 +-0 1 +.names II24381 II24382 g18369 +0- 1 +-0 1 +.names g18449 g18369 II26440 g20000 +111 1 +.names g5355 g18450 g20001 +11 1 +.names g5358 g18466 g20006 +11 1 +.names g18063 g3113 g20011 +11 1 +.names g16804 g3135 g20012 +11 1 +.names g17720 g12848 g20013 +11 1 +.names g7615 g16749 g20014 +11 1 +.names II24388 II24389 g18370 +0- 1 +-0 1 +.names II24299 II24300 g18296 +0- 1 +-0 1 +.names II24206 II24207 g18206 +0- 1 +-0 1 +.names g18370 g18296 g18206 II26464 +111 1 +.names II24124 II24125 g18109 +0- 1 +-0 1 +.names II24054 II24055 g18024 +0- 1 +-0 1 +.names g18109 g18024 II26464 g20020 +111 1 +.names g5369 g18505 g20021 +11 1 +.names II24744 II24745 g18635 +0- 1 +-0 1 +.names II24703 II24704 g18605 +0- 1 +-0 1 +.names II24656 II24657 g18568 +0- 1 +-0 1 +.names g18635 g18605 g18568 II26472 +111 1 +.names II24576 II24577 g18522 +0- 1 +-0 1 +.names II24494 II24495 g18464 +0- 1 +-0 1 +.names g18522 g18464 II26472 g20038 +111 1 +.names g5372 g18523 g20039 +11 1 +.names g5375 g18539 g20044 +11 1 +.names g16749 g3127 g20048 +11 1 +.names g17878 g3155 g20049 +11 1 +.names g18070 g3161 g20050 +11 1 +.names g18063 g3114 g20051 +11 1 +.names g16804 g3134 g20052 +11 1 +.names g17720 g12875 g20053 +11 1 +.names II24501 II24502 g18465 +0- 1 +-0 1 +.names II24408 II24409 g18389 +0- 1 +-0 1 +.names II24318 II24319 g18313 +0- 1 +-0 1 +.names g18465 g18389 g18313 II26500 +111 1 +.names II24227 II24228 g18225 +0- 1 +-0 1 +.names II24149 II24150 g18141 +0- 1 +-0 1 +.names g18225 g18141 II26500 g20062 +111 1 +.names g5382 g18569 g20063 +11 1 +.names II24764 II24765 g18644 +0- 1 +-0 1 +.names II24752 II24753 g18637 +0- 1 +-0 1 +.names II24726 II24727 g18618 +0- 1 +-0 1 +.names g18644 g18637 g18618 II26508 +111 1 +.names II24678 II24679 g18586 +0- 1 +-0 1 +.names II24595 II24596 g18537 +0- 1 +-0 1 +.names g18586 g18537 II26508 g20080 +111 1 +.names g5385 g18587 g20081 +11 1 +.names g17969 g3158 g20084 +11 1 +.names g18170 g3164 g20085 +11 1 +.names g18337 g3170 g20086 +11 1 +.names g16749 g7574 g20087 +11 1 +.names g16836 g3147 g20088 +11 1 +.names g17969 g9160 g20089 +11 1 +.names g18063 g3120 g20090 +11 1 +.names g16804 g3136 g20091 +11 1 +.names g16749 g7603 g20092 +11 1 +.names g18656 g18670 g18692 II26525 +111 1 +.names g13657 g13677 g13750 II26525 g20093 +1111 1 +.names g18656 g14837 g13657 II26528 +111 1 +.names g13677 g13706 II26528 g20094 +111 1 +.names II24602 II24603 g18538 +0- 1 +-0 1 +.names II24521 II24522 g18484 +0- 1 +-0 1 +.names II24427 II24428 g18406 +0- 1 +-0 1 +.names g18538 g18484 g18406 II26541 +111 1 +.names II24339 II24340 g18332 +0- 1 +-0 1 +.names II24252 II24253 g18257 +0- 1 +-0 1 +.names g18332 g18257 II26541 g20103 +111 1 +.names g5391 g18619 g20104 +11 1 +.names g18261 g3167 g20106 +11 1 +.names g18415 g3173 g20107 +11 1 +.names g18543 g3179 g20108 +11 1 +.names g17878 g9504 g20109 +11 1 +.names g18070 g9286 g20110 +11 1 +.names g18261 g9884 g20111 +11 1 +.names g16749 g3132 g20112 +11 1 +.names g16836 g3142 g20113 +11 1 +.names g17969 g9755 g20114 +11 1 +.names g16804 g3139 g20115 +11 1 +.names g14776 g18670 g18720 II26558 +111 1 +.names g16142 g13677 g13706 II26558 g20116 +1111 1 +.names g14776 g18720 g13657 II26561 +111 1 +.names g16189 g13706 II26561 g20117 +111 1 +.names g18679 g18699 g18728 II26564 +111 1 +.names g13687 g13714 g13791 II26564 g20118 +1111 1 +.names g18679 g14910 g13687 II26567 +111 1 +.names g13714 g13756 II26567 g20119 +111 1 +.names g18486 g3176 g20131 +11 1 +.names g18593 g3182 g20132 +11 1 +.names g18170 g9505 g20133 +11 1 +.names g18337 g9506 g20134 +11 1 +.names g18486 g9885 g20135 +11 1 +.names g17878 g9423 g20136 +11 1 +.names g18070 g9226 g20137 +11 1 +.names g18261 g9756 g20138 +11 1 +.names g16836 g3151 g20139 +11 1 +.names g14797 g14895 g16679 +00 1 +.names g16679 g16884 g16665 g20144 +111 1 +.names g14776 g18670 g16142 g16189 g20145 +1111 1 +.names g14811 g18699 g18758 II26590 +111 1 +.names g16201 g13714 g13756 II26590 g20146 +1111 1 +.names g14811 g18758 g13687 II26593 +111 1 +.names g16254 g13756 II26593 g20147 +111 1 +.names g18708 g18735 g18765 II26596 +111 1 +.names g13724 g13764 g13819 II26596 g20148 +1111 1 +.names g18708 g14991 g13724 II26599 +111 1 +.names g13764 g13797 II26599 g20149 +111 1 +.names g16809 g3185 g20156 +11 1 +.names g18415 g9287 g20157 +11 1 +.names g18543 g9886 g20158 +11 1 +.names g16809 g9288 g20159 +11 1 +.names g18170 g9424 g20160 +11 1 +.names g18337 g9426 g20161 +11 1 +.names g18486 g9757 g20162 +11 1 +.names g14797 g18692 g13657 II26615 +111 1 +.names g13677 g13750 II26615 g20177 +111 1 +.names g14849 g14976 g16705 +00 1 +.names g16705 g16913 g16686 g20182 +111 1 +.names g14811 g18699 g16201 g16254 g20183 +1111 1 +.names g14863 g18735 g18789 II26621 +111 1 +.names g16266 g13764 g13797 II26621 g20184 +1111 1 +.names g14863 g18789 g13724 II26624 +111 1 +.names g16313 g13797 II26624 g20185 +111 1 +.names g18744 g18772 g18796 II26627 +111 1 +.names g13774 g13805 g13840 II26627 g20186 +1111 1 +.names g18744 g15080 g13774 II26630 +111 1 +.names g13805 g13825 II26630 g20187 +111 1 +.names g18593 g9425 g20188 +11 1 +.names g16825 g9289 g20189 +11 1 +.names g18415 g9227 g20190 +11 1 +.names g18543 g9758 g20191 +11 1 +.names g16809 g9228 g20192 +11 1 +.names g18656 g18670 g16142 II26639 +111 1 +.names g13677 g13706 II26639 g20197 +111 1 +.names g14849 g18728 g13687 II26645 +111 1 +.names g13714 g13791 II26645 g20211 +111 1 +.names g14922 g15065 g16736 +00 1 +.names g16736 g16943 g16712 g20216 +111 1 +.names g14863 g18735 g16266 g16313 g20217 +1111 1 +.names g14936 g18772 g18815 II26651 +111 1 +.names g16325 g13805 g13825 II26651 g20218 +1111 1 +.names g14936 g18815 g13774 II26654 +111 1 +.names g16371 g13825 II26654 g20219 +111 1 +.names g18593 g9355 g20220 +11 1 +.names g16825 g10099 g20221 +11 1 +.names g18656 g18720 g13657 g16293 g20222 +1111 1 +.names g18679 g18699 g16201 II26661 +111 1 +.names g13714 g13756 II26661 g20227 +111 1 +.names g14922 g18765 g13724 II26667 +111 1 +.names g13764 g13819 II26667 g20241 +111 1 +.names g15003 g15161 g16778 +00 1 +.names g16778 g16974 g16743 g20246 +111 1 +.names g14936 g18772 g16325 g16371 g20247 +1111 1 +.names g18656 g14837 g16293 g20248 +111 1 +.names g18679 g18758 g13687 g16351 g20249 +1111 1 +.names g18708 g18735 g16266 II26676 +111 1 +.names g13764 g13797 II26676 g20254 +111 1 +.names g15003 g18796 g13774 II26682 +111 1 +.names g13805 g13840 II26682 g20268 +111 1 +.names g14797 g18692 g13657 g16243 g20270 +1111 1 +.names g18679 g14910 g16351 g20271 +111 1 +.names g18708 g18789 g13724 g16395 g20272 +1111 1 +.names g18744 g18772 g16325 II26690 +111 1 +.names g13805 g13825 II26690 g20277 +111 1 +.names g18670 g18692 g16142 II26695 +111 1 +.names g13677 g16243 II26695 g20280 +111 1 +.names g14849 g18728 g13687 g16302 g20282 +1111 1 +.names g18708 g14991 g16395 g20283 +111 1 +.names g18744 g18815 g13774 g16433 g20284 +1111 1 +.names g16846 g8103 g20285 +11 1 +.names g18699 g18728 g16201 II26708 +111 1 +.names g13714 g16302 II26708 g20291 +111 1 +.names g14922 g18765 g13724 g16360 g20293 +1111 1 +.names g18744 g15080 g16433 g20294 +111 1 +.names g18735 g18765 g16266 II26726 +111 1 +.names g13764 g16360 II26726 g20307 +111 1 +.names g15003 g18796 g13774 g16404 g20309 +1111 1 +.names g18772 g18796 g16325 II26745 +111 1 +.names g13805 g16404 II26745 g20326 +111 1 +.names g17351 g13644 g20460 +11 1 +.names g17314 g13669 g20472 +11 1 +.names g17313 g11827 g20480 +11 1 +.names g17281 g11859 g20486 +11 1 +.names g17258 g11894 g20492 +11 1 +.names g17648 g11933 g20499 +11 1 +.names g17566 g11973 g20502 +11 1 +.names g16298 g13318 g17507 +00 1 +.names g17507 g13817 g20503 +11 1 +.names g17499 g12025 g20506 +11 1 +.names g17445 g13836 g20512 +11 1 +.names g17394 g13849 g20525 +11 1 +.names g18656 g14837 g13657 g16189 g20538 +1111 1 +.names g4809 g19064 g20640 +11 1 +.names g5888 g19075 g20647 +11 1 +.names g4985 g19081 g20665 +11 1 +.names g5712 g19113 g20809 +11 1 +.names g5770 g19118 g20826 +11 1 +.names g5829 g19125 g20836 +11 1 +.names g5885 g19132 g20840 +11 1 +.names g20016 g14079 g14165 g21049 +111 1 +.names g20193 g12030 g21067 +11 1 +.names g20058 g14194 g14280 g21068 +111 1 +.names g20223 g12094 g21077 +11 1 +.names g20099 g14309 g14402 g21078 +111 1 +.names g19484 g14158 g19001 g21085 +111 1 +.names g20193 g12142 g21086 +11 1 +.names g20250 g12166 g21091 +11 1 +.names g20124 g14431 g14514 g21092 +111 1 +.names g19505 g14273 g16507 g21097 +111 1 +.names g20223 g12204 g21098 +11 1 +.names g20273 g12228 g21103 +11 1 +.names g19444 g17893 g14079 g21107 +111 1 +.names g19524 g14395 g16529 g21111 +111 1 +.names g20250 g12259 g21112 +11 1 +.names g19001 g16867 g20054 +00 1 +.names g20054 g14244 g21121 +11 1 +.names g20140 g12279 g21122 +11 1 +.names g19970 g19982 g21123 +11 1 +.names g19471 g18004 g14194 g21124 +111 1 +.names g19534 g14507 g16560 g21128 +111 1 +.names g20273 g12302 g21129 +11 1 +.names II25682 II25683 g19318 +0- 1 +-0 1 +.names II25634 II25635 g19300 +0- 1 +-0 1 +.names II25596 II25597 g19286 +0- 1 +-0 1 +.names g19318 g19300 g19286 II27695 +111 1 +.names II25561 II25562 g19271 +0- 1 +-0 1 +.names II25533 II25534 g19261 +0- 1 +-0 1 +.names g19271 g19261 II27695 g21136 +111 1 +.names g5750 g19272 g21137 +11 1 +.names g19484 g14347 g21138 +11 1 +.names g16507 g16895 g20095 +00 1 +.names g20095 g14366 g21140 +11 1 +.names g20178 g12315 g21141 +11 1 +.names g20000 g20020 g21142 +11 1 +.names g19494 g18121 g14309 g21143 +111 1 +.names II25540 II25541 g19262 +0- 1 +-0 1 +.names II25839 II25840 g19414 +0- 1 +-0 1 +.names II25801 II25802 g19386 +0- 1 +-0 1 +.names g19262 g19414 g19386 II27711 +111 1 +.names II25762 II25763 g19357 +0- 1 +-0 1 +.names II25722 II25723 g19334 +0- 1 +-0 1 +.names g19357 g19334 II27711 g21152 +111 1 +.names g20054 g16543 g16501 g21153 +111 1 +.names g20193 g12333 g21154 +11 1 +.names g20140 g12336 g21155 +11 1 +.names II25732 II25733 g19345 +0- 1 +-0 1 +.names II25691 II25692 g19321 +0- 1 +-0 1 +.names II25644 II25645 g19304 +0- 1 +-0 1 +.names g19345 g19321 g19304 II27717 +111 1 +.names II25606 II25607 g19290 +0- 1 +-0 1 +.names II25572 II25573 g19276 +0- 1 +-0 1 +.names g19290 g19276 II27717 g21156 +111 1 +.names g5809 g19291 g21157 +11 1 +.names g19505 g14459 g21158 +11 1 +.names g16529 g16924 g20120 +00 1 +.names g20120 g14478 g21160 +11 1 +.names g20212 g12343 g21161 +11 1 +.names g20038 g20062 g21162 +11 1 +.names g19515 g18237 g14431 g21163 +111 1 +.names II25579 II25580 g19277 +0- 1 +-0 1 +.names II25881 II25882 g19451 +0- 1 +-0 1 +.names II25847 II25848 g19416 +0- 1 +-0 1 +.names g19277 g19451 g19416 II27733 +111 1 +.names II25810 II25811 g19389 +0- 1 +-0 1 +.names II25772 II25773 g19368 +0- 1 +-0 1 +.names g19389 g19368 II27733 g21172 +111 1 +.names g20095 g16575 g16523 g21173 +111 1 +.names g20223 g12363 g21174 +11 1 +.names g20178 g12366 g21175 +11 1 +.names II25782 II25783 g19379 +0- 1 +-0 1 +.names II25741 II25742 g19348 +0- 1 +-0 1 +.names II25701 II25702 g19325 +0- 1 +-0 1 +.names g19379 g19348 g19325 II27739 +111 1 +.names II25654 II25655 g19308 +0- 1 +-0 1 +.names II25617 II25618 g19295 +0- 1 +-0 1 +.names g19308 g19295 II27739 g21176 +111 1 +.names g5865 g19309 g21177 +11 1 +.names g19524 g14546 g21178 +11 1 +.names g16560 g16954 g20150 +00 1 +.names g20150 g14565 g21180 +11 1 +.names g20242 g12373 g21181 +11 1 +.names g20080 g20103 g21182 +11 1 +.names g20140 g12379 g21188 +11 1 +.names II25624 II25625 g19296 +0- 1 +-0 1 +.names II25914 II25915 g19478 +0- 1 +-0 1 +.names II25889 II25890 g19453 +0- 1 +-0 1 +.names g19296 g19478 g19453 II27755 +111 1 +.names II25856 II25857 g19419 +0- 1 +-0 1 +.names II25820 II25821 g19400 +0- 1 +-0 1 +.names g19419 g19400 II27755 g21192 +111 1 +.names g20120 g16599 g16554 g21193 +111 1 +.names g20250 g12382 g21194 +11 1 +.names g20212 g12385 g21195 +11 1 +.names II25830 II25831 g19411 +0- 1 +-0 1 +.names II25791 II25792 g19382 +0- 1 +-0 1 +.names II25751 II25752 g19352 +0- 1 +-0 1 +.names g19411 g19382 g19352 II27761 +111 1 +.names II25711 II25712 g19329 +0- 1 +-0 1 +.names II25665 II25666 g19313 +0- 1 +-0 1 +.names g19329 g19313 II27761 g21196 +111 1 +.names g5912 g19330 g21197 +11 1 +.names g19534 g14601 g21198 +11 1 +.names g20178 g12409 g21203 +11 1 +.names II25672 II25673 g19314 +0- 1 +-0 1 +.names II25939 II25940 g19501 +0- 1 +-0 1 +.names II25922 II25923 g19480 +0- 1 +-0 1 +.names g19314 g19501 g19480 II27772 +111 1 +.names II25898 II25899 g19456 +0- 1 +-0 1 +.names II25866 II25867 g19430 +0- 1 +-0 1 +.names g19456 g19430 II27772 g21207 +111 1 +.names g20150 g16619 g16586 g21208 +111 1 +.names g20273 g12412 g21209 +11 1 +.names g20242 g12415 g21210 +11 1 +.names g20212 g12421 g21218 +11 1 +.names g20242 g12426 g21226 +11 1 +.names g19578 g14797 g16665 g21229 +111 1 +.names g19608 g14849 g16686 g21234 +111 1 +.names g19641 g14922 g16712 g21243 +111 1 +.names g16665 g16884 g20299 +00 1 +.names g20299 g14837 g21245 +11 1 +.names g19681 g15003 g16743 g21251 +111 1 +.names g19578 g14895 g21252 +11 1 +.names g16686 g16913 g20318 +00 1 +.names g20318 g14910 g21254 +11 1 +.names g20299 g16722 g16682 g21259 +111 1 +.names g19608 g14976 g21260 +11 1 +.names g16712 g16943 g20337 +00 1 +.names g20337 g14991 g21262 +11 1 +.names g20318 g16764 g16708 g21267 +111 1 +.names g19641 g15065 g21268 +11 1 +.names g16743 g16974 g20357 +00 1 +.names g20357 g15080 g21270 +11 1 +.names g20337 g16791 g16739 g21276 +111 1 +.names g19681 g15161 g21277 +11 1 +.names g20357 g16820 g16781 g21283 +111 1 +.names g9356 g20269 g21284 +11 1 +.names g9356 g20278 g21290 +11 1 +.names g9293 g20279 g21291 +11 1 +.names g9453 g20281 g21292 +11 1 +.names g9356 g20286 g21298 +11 1 +.names g9293 g20287 g21299 +11 1 +.names g9232 g20288 g21300 +11 1 +.names g9453 g20289 g21301 +11 1 +.names g9374 g20290 g21302 +11 1 +.names g9595 g20292 g21303 +11 1 +.names g9293 g20296 g21304 +11 1 +.names g9232 g20297 g21305 +11 1 +.names g9187 g20298 g21306 +11 1 +.names g9453 g20302 g21307 +11 1 +.names g9374 g20303 g21308 +11 1 +.names g9310 g20304 g21309 +11 1 +.names g9595 g20305 g21310 +11 1 +.names g9471 g20306 g21311 +11 1 +.names g9737 g20308 g21312 +11 1 +.names g9232 g20311 g21313 +11 1 +.names g9187 g20312 g21314 +11 1 +.names g9161 g20313 g21315 +11 1 +.names g9374 g20315 g21319 +11 1 +.names g9310 g20316 g21320 +11 1 +.names g9248 g20317 g21321 +11 1 +.names g9595 g20321 g21322 +11 1 +.names g9471 g20322 g21323 +11 1 +.names g9391 g20323 g21324 +11 1 +.names g9737 g20324 g21325 +11 1 +.names g9613 g20325 g21326 +11 1 +.names g9187 g20327 g21328 +11 1 +.names g9161 g20328 g21329 +11 1 +.names g9150 g20329 g21330 +11 1 +.names g9310 g20330 g21334 +11 1 +.names g9248 g20331 g21335 +11 1 +.names g9203 g20332 g21336 +11 1 +.names g9471 g20334 g21337 +11 1 +.names g9391 g20335 g21338 +11 1 +.names g9326 g20336 g21339 +11 1 +.names g9737 g20340 g21340 +11 1 +.names g9613 g20341 g21341 +11 1 +.names g9488 g20342 g21342 +11 1 +.names g9161 g20344 g21343 +11 1 +.names g9150 g20345 g21344 +11 1 +.names g15096 g20346 g21345 +11 1 +.names g9248 g20347 g21349 +11 1 +.names g9203 g20348 g21350 +11 1 +.names g9174 g20349 g21351 +11 1 +.names g9391 g20350 g21352 +11 1 +.names g9326 g20351 g21353 +11 1 +.names g9264 g20352 g21354 +11 1 +.names g9613 g20354 g21355 +11 1 +.names g9488 g20355 g21356 +11 1 +.names g9407 g20356 g21357 +11 1 +.names g9507 g20361 g21360 +11 1 +.names g9150 g20362 g21361 +11 1 +.names g15096 g20363 g21362 +11 1 +.names g15022 g20364 g21363 +11 1 +.names g9203 g20366 g21367 +11 1 +.names g9174 g20367 g21368 +11 1 +.names g15188 g20368 g21369 +11 1 +.names g9326 g20369 g21370 +11 1 +.names g9264 g20370 g21371 +11 1 +.names g9216 g20371 g21372 +11 1 +.names g9488 g20372 g21373 +11 1 +.names g9407 g20373 g21374 +11 1 +.names g9342 g20374 g21375 +11 1 +.names g9507 g20378 g21378 +11 1 +.names g9427 g20379 g21379 +11 1 +.names g15096 g20380 g21380 +11 1 +.names g15022 g20381 g21381 +11 1 +.names g6201 g19657 g21388 +11 1 +.names g9649 g20384 g21389 +11 1 +.names g9174 g20385 g21390 +11 1 +.names g15188 g20386 g21391 +11 1 +.names g15118 g20387 g21392 +11 1 +.names g9264 g20389 g21393 +11 1 +.names g9216 g20390 g21394 +11 1 +.names g15274 g20391 g21395 +11 1 +.names g9407 g20392 g21396 +11 1 +.names g9342 g20393 g21397 +11 1 +.names g9277 g20394 g21398 +11 1 +.names g9507 g20397 g21401 +11 1 +.names g9427 g20398 g21402 +11 1 +.names g15022 g20399 g21403 +11 1 +.names g6363 g20402 g21410 +11 1 +.names g9649 g20403 g21411 +11 1 +.names g9569 g20404 g21412 +11 1 +.names g15188 g20405 g21413 +11 1 +.names g15118 g20406 g21414 +11 1 +.names g6290 g19705 g21418 +11 1 +.names g9795 g20409 g21419 +11 1 +.names g9216 g20410 g21420 +11 1 +.names g15274 g20411 g21421 +11 1 +.names g15210 g20412 g21422 +11 1 +.names g9342 g20414 g21423 +11 1 +.names g9277 g20415 g21424 +11 1 +.names g15366 g20416 g21425 +11 1 +.names g9427 g20420 g21428 +11 1 +.names g9649 g20422 g21438 +11 1 +.names g9569 g20423 g21439 +11 1 +.names g15118 g20424 g21440 +11 1 +.names g6568 g20427 g21444 +11 1 +.names g9795 g20428 g21445 +11 1 +.names g9711 g20429 g21446 +11 1 +.names g15274 g20430 g21447 +11 1 +.names g15210 g20431 g21448 +11 1 +.names g6427 g19749 g21452 +11 1 +.names g9941 g20434 g21453 +11 1 +.names g9277 g20435 g21454 +11 1 +.names g15366 g20436 g21455 +11 1 +.names g15296 g20437 g21456 +11 1 +.names g9569 g20442 g21476 +11 1 +.names g9795 g20444 g21480 +11 1 +.names g9711 g20445 g21481 +11 1 +.names g15210 g20446 g21482 +11 1 +.names g6832 g20449 g21486 +11 1 +.names g9941 g20450 g21487 +11 1 +.names g9857 g20451 g21488 +11 1 +.names g15366 g20452 g21489 +11 1 +.names g15296 g20453 g21490 +11 1 +.names g6632 g19792 g21494 +11 1 +.names g3006 g20456 g21497 +11 1 +.names g9711 g20461 g21517 +11 1 +.names g9941 g20463 g21521 +11 1 +.names g9857 g20464 g21522 +11 1 +.names g15296 g20465 g21523 +11 1 +.names g7134 g20468 g21527 +11 1 +.names g17802 g18265 g17882 II28068 +111 1 +.names g9857 g20476 g21553 +11 1 +.names g13907 g14238 g13946 II28096 +111 1 +.names g13886 g14153 g19799 II28096 g21564 +1111 1 +.names g17914 g18358 g17993 II28103 +111 1 +.names g3002 g19890 g21589 +11 1 +.names g16498 g19484 g14071 g21593 +111 1 +.names g13963 g14360 g14016 II28126 +111 1 +.names g13927 g14268 g19843 II28126 g21597 +1111 1 +.names g18025 g18453 g18110 II28133 +111 1 +.names g7522 g20490 g21610 +11 1 +.names g7471 g19915 g21611 +11 1 +.names g16520 g19505 g14186 g21622 +111 1 +.names g14033 g14472 g14107 II28155 +111 1 +.names g13983 g14390 g19876 II28155 g21626 +1111 1 +.names g18142 g18526 g18226 II28162 +111 1 +.names g7549 g20496 g21635 +11 1 +.names g3398 g20500 g21639 +11 1 +.names g16551 g19524 g14301 g21650 +111 1 +.names g14124 g14559 g14222 II28181 +111 1 +.names g14053 g14502 g19907 II28181 g21654 +1111 1 +.names g2896 g20501 g21658 +11 1 +.names g3398 g20504 g21666 +11 1 +.names g3554 g20505 g21670 +11 1 +.names g16583 g19534 g14423 g21681 +111 1 +.names g3398 g20516 g21687 +11 1 +.names g3554 g20517 g21695 +11 1 +.names g3710 g20518 g21699 +11 1 +.names g2892 g19978 g21707 +11 1 +.names g3554 g20534 g21723 +11 1 +.names g3710 g20535 g21731 +11 1 +.names g3866 g20536 g21735 +11 1 +.names g3710 g20553 g21749 +11 1 +.names g3866 g20554 g21757 +11 1 +.names g7607 g20045 g21758 +11 1 +.names g3866 g19078 g21773 +11 1 +.names g16679 g19578 g14776 g21805 +111 1 +.names g16705 g19608 g14811 g21812 +111 1 +.names g16736 g19641 g14863 g21818 +111 1 +.names g16778 g19681 g14936 g21822 +111 1 +.names g19302 g11749 g21891 +11 1 +.names g14685 g8580 g17057 g19288 +0-- 1 +-0- 1 +--0 1 +.names g19288 g13011 g21892 +11 1 +.names g19323 g11749 g21899 +11 1 +.names g14719 g8587 g17092 g19306 +0-- 1 +-0- 1 +--0 1 +.names g19306 g13011 g21900 +11 1 +.names g5715 g20513 g21906 +11 1 +.names g19350 g11749 g21911 +11 1 +.names g14747 g8594 g17130 g19327 +0-- 1 +-0- 1 +--0 1 +.names g19327 g13011 g21912 +11 1 +.names g4456 g20519 g21913 +11 1 +.names g5773 g20531 g21920 +11 1 +.names g19384 g11749 g21925 +11 1 +.names g14768 g8605 g17157 g19354 +0-- 1 +-0- 1 +--0 1 +.names g19354 g13011 g21926 +11 1 +.names g4632 g20539 g21931 +11 1 +.names g5832 g20550 g21938 +11 1 +.names g291 g21187 g21990 +11 1 +.names g978 g21202 g22004 +11 1 +.names g1672 g21217 g22015 +11 1 +.names g2366 g21225 g22020 +11 1 +.names g3088 g16825 g19141 +0- 1 +-0 1 +.names g20108 g20132 g20156 g21133 +000 1 +.names g20086 g20107 g20131 g21116 +000 1 +.names g19141 g21133 g21116 II28582 +111 1 +.names g20050 g20085 g20106 g21104 +000 1 +.names g20012 g20049 g20084 g21095 +000 1 +.names g20011 g20048 g21084 +00 1 +.names g20159 g20189 g21167 +00 1 +.names g20135 g20158 g20188 g21147 +000 1 +.names g20111 g20134 g20157 g21134 +000 1 +.names g21167 g21147 g21134 II28594 +111 1 +.names g20089 g20110 g20133 g21117 +000 1 +.names g20052 g20088 g20109 g21105 +000 1 +.names g20013 g20051 g20087 g21096 +000 1 +.names g20192 g20221 g21183 +00 1 +.names g20162 g20191 g20220 g21168 +000 1 +.names g20138 g20161 g20190 g21148 +000 1 +.names g21183 g21168 g21148 II28609 +111 1 +.names g20114 g20137 g20160 g21135 +000 1 +.names g20091 g20113 g20136 g21118 +000 1 +.names g20053 g20090 g20112 g21106 +000 1 +.names g21564 g20986 g22187 +11 1 +.names g21597 g21012 g22196 +11 1 +.names g21271 g16881 g22201 +11 1 +.names g21626 g21036 g22202 +11 1 +.names g21895 g11976 g22206 +11 1 +.names g21278 g16910 g22207 +11 1 +.names g21654 g21057 g22208 +11 1 +.names g21661 g12027 g22211 +11 1 +.names g21907 g12045 g22214 +11 1 +.names g21285 g16940 g22215 +11 1 +.names g21690 g12091 g22220 +11 1 +.names g21921 g12109 g22223 +11 1 +.names g21293 g16971 g22224 +11 1 +.names g21716 g12136 g22228 +11 1 +.names g21661 g12139 g22229 +11 1 +.names g21726 g12163 g22235 +11 1 +.names g21939 g12181 g22238 +11 1 +.names g21742 g12198 g22244 +11 1 +.names g21690 g12201 g22245 +11 1 +.names g21752 g12225 g22250 +11 1 +.names g21716 g12239 g22254 +11 1 +.names g21661 g12242 g22255 +11 1 +.names g21766 g12253 g22264 +11 1 +.names g21726 g12256 g22265 +11 1 +.names g92 g21529 g22270 +11 1 +.names g21742 g12282 g22272 +11 1 +.names g21690 g12285 g22273 +11 1 +.names g21782 g12296 g22281 +11 1 +.names g21752 g12299 g22282 +11 1 +.names g21716 g12312 g22285 +11 1 +.names g780 g21565 g22289 +11 1 +.names g21766 g12318 g22291 +11 1 +.names g21726 g12321 g22292 +11 1 +.names g21742 g12340 g22305 +11 1 +.names g1466 g21598 g22309 +11 1 +.names g21782 g12346 g22311 +11 1 +.names g21752 g12349 g22312 +11 1 +.names g21766 g12370 g22333 +11 1 +.names g2160 g21627 g22337 +11 1 +.names g88 g21184 g22340 +11 1 +.names g21782 g12389 g22358 +11 1 +.names g776 g21199 g22363 +11 1 +.names g1462 g21214 g22383 +11 1 +.names g2156 g21222 g22398 +11 1 +.names g646 g21861 g22483 +11 1 +.names g13873 g21382 g22515 +11 1 +.names g20885 g17442 g22516 +11 1 +.names g21895 g12608 g22517 +11 1 +.names g1332 g21867 g22526 +11 1 +.names g13886 g21404 g22546 +11 1 +.names g13895 g21415 g22555 +11 1 +.names g20904 g17523 g22556 +11 1 +.names g21907 g12654 g22557 +11 1 +.names g2026 g21872 g22566 +11 1 +.names g13907 g21429 g22577 +11 1 +.names g21895 g12699 g22581 +11 1 +.names g13927 g21441 g22587 +11 1 +.names g13936 g21449 g22595 +11 1 +.names g20928 g17613 g22596 +11 1 +.names g21921 g12708 g22597 +11 1 +.names g2720 g21876 g22606 +11 1 +.names g13946 g21458 g22607 +11 1 +.names g660 g21473 g22610 +11 1 +.names g13963 g21477 g22614 +11 1 +.names g21907 g12756 g22618 +11 1 +.names g13983 g21483 g22624 +11 1 +.names g13992 g21491 g22632 +11 1 +.names g20956 g17710 g22633 +11 1 +.names g21939 g12765 g22634 +11 1 +.names g14767 g19552 g20841 +00 1 +.names g20841 g10927 g22637 +11 1 +.names g14001 g21498 g22638 +11 1 +.names g14016 g21505 g22643 +11 1 +.names g1346 g21514 g22646 +11 1 +.names g14033 g21518 g22650 +11 1 +.names g21921 g12798 g22654 +11 1 +.names g14053 g21524 g22660 +11 1 +.names g19691 g19726 g20920 +00 1 +.names g20920 g6153 g22665 +11 1 +.names g21825 g20014 g22666 +11 1 +.names g14062 g21530 g22667 +11 1 +.names g14092 g21537 g22674 +11 1 +.names g14107 g21541 g22679 +11 1 +.names g2040 g21550 g22682 +11 1 +.names g14124 g21554 g22686 +11 1 +.names g21939 g12837 g22690 +11 1 +.names g7338 g21883 g22699 +11 1 +.names g7146 g21558 g22700 +11 1 +.names g18174 g21561 g22701 +11 1 +.names g14177 g21566 g22707 +11 1 +.names g14207 g21573 g22714 +11 1 +.names g14222 g21577 g22719 +11 1 +.names g2734 g21586 g22722 +11 1 +.names g3036 g21886 g22726 +11 1 +.names g14238 g21590 g22727 +11 1 +.names g18281 g21594 g22732 +11 1 +.names g14292 g21599 g22738 +11 1 +.names g14322 g21606 g22745 +11 1 +.names g14342 g21612 g22754 +11 1 +.names g14360 g21619 g22759 +11 1 +.names g18374 g21623 g22764 +11 1 +.names g14414 g21628 g22770 +11 1 +.names g14454 g21640 g22788 +11 1 +.names g14472 g21647 g22793 +11 1 +.names g18469 g21651 g22798 +11 1 +.names g2920 g21655 g22804 +11 1 +.names g14541 g21671 g22830 +11 1 +.names g14559 g21678 g22835 +11 1 +.names g7583 g21902 g22841 +11 1 +.names g3032 g21682 g22842 +11 1 +.names g14596 g21700 g22869 +11 1 +.names g7587 g21708 g22874 +11 1 +.names g2924 g21927 g22906 +11 1 +.names g16840 g21400 g22984 +11 1 +.names g20842 g15859 g23104 +11 1 +.names g5857 g21050 g23106 +11 1 +.names g20850 g15890 g23118 +11 1 +.names g5904 g21069 g23119 +11 1 +.names g20858 g15923 g23127 +11 1 +.names g5943 g21079 g23128 +11 1 +.names g20866 g15952 g23138 +11 1 +.names g5977 g21093 g23139 +11 1 +.names g21533 g22408 g23409 +11 1 +.names g21569 g22421 g23414 +11 1 +.names g21271 g20842 g22755 +00 1 +.names g22755 g19577 g23419 +11 1 +.names g21602 g22443 g23423 +11 1 +.names g21278 g20850 g22789 +00 1 +.names g22789 g19607 g23428 +11 1 +.names g21631 g22476 g23432 +11 1 +.names g21285 g20858 g22831 +00 1 +.names g22831 g19640 g23434 +11 1 +.names g21293 g20866 g22870 +00 1 +.names g22870 g19680 g23440 +11 1 +.names g18552 g22547 g23451 +11 1 +.names g18602 g22588 g23458 +11 1 +.names g17988 g22609 g23462 +11 1 +.names g18634 g22625 g23467 +11 1 +.names g18105 g22645 g23471 +11 1 +.names g18643 g22661 g23476 +11 1 +.names g22945 g8847 g23483 +11 1 +.names g18221 g22681 g23484 +11 1 +.names g18328 g22721 g23494 +11 1 +.names g5802 g22300 g23496 +11 1 +.names g5890 g22753 g23510 +11 1 +.names g5858 g22328 g23512 +11 1 +.names g5929 g22787 g23525 +11 1 +.names g5905 g22353 g23527 +11 1 +.names g5963 g22829 g23536 +11 1 +.names g5944 g22376 g23538 +11 1 +.names g5992 g22868 g23544 +11 1 +.names g8062 g22405 g23547 +11 1 +.names g8132 g22409 g23550 +11 1 +.names g8135 g22412 g23551 +11 1 +.names g6136 g22415 g23552 +11 1 +.names g8147 g22418 g23554 +11 1 +.names g8200 g22422 g23558 +11 1 +.names g8203 g22425 g23559 +11 1 +.names g8206 g22428 g23560 +11 1 +.names g8218 g22431 g23563 +11 1 +.names g8221 g22434 g23564 +11 1 +.names g6146 g22437 g23565 +11 1 +.names g8233 g22440 g23567 +11 1 +.names g3931 g22445 g23571 +11 1 +.names g3934 g22448 g23572 +11 1 +.names g3937 g22451 g23573 +11 1 +.names g3957 g22455 g23577 +11 1 +.names g3960 g22458 g23578 +11 1 +.names g3963 g22461 g23579 +11 1 +.names g3975 g22464 g23582 +11 1 +.names g3978 g22467 g23583 +11 1 +.names g6167 g22470 g23584 +11 1 +.names g3990 g22473 g23586 +11 1 +.names g4009 g22477 g23590 +11 1 +.names g4012 g22480 g23591 +11 1 +.names g17640 g22986 g23592 +11 1 +.names g19441 g20885 g22845 +0- 1 +-0 1 +.names g22845 g20365 g23593 +11 1 +.names g4038 g22484 g23598 +11 1 +.names g4041 g22487 g23599 +11 1 +.names g4044 g22490 g23600 +11 1 +.names g4064 g22494 g23604 +11 1 +.names g4067 g22497 g23605 +11 1 +.names g4070 g22500 g23606 +11 1 +.names g4082 g22503 g23609 +11 1 +.names g4085 g22506 g23610 +11 1 +.names g6194 g22509 g23611 +11 1 +.names g4107 g22512 g23615 +11 1 +.names g17724 g22988 g23616 +11 1 +.names g16075 g20842 g21271 g22810 +000 1 +.names g22810 g20382 g23617 +11 1 +.names g20842 g20885 g22608 +0- 1 +-0 1 +.names g22608 g20383 g23618 +11 1 +.names g4136 g22520 g23622 +11 1 +.names g4139 g22523 g23623 +11 1 +.names g17741 g22989 g23624 +11 1 +.names g19468 g20904 g22880 +0- 1 +-0 1 +.names g22880 g20388 g23625 +11 1 +.names g4165 g22527 g23630 +11 1 +.names g4168 g22530 g23631 +11 1 +.names g4171 g22533 g23632 +11 1 +.names g4191 g22537 g23636 +11 1 +.names g4194 g22540 g23637 +11 1 +.names g4197 g22543 g23638 +11 1 +.names g21825 g22805 g23639 +11 1 +.names g17802 g22991 g23643 +11 1 +.names g16075 g20885 g22784 +00 1 +.names g22784 g17500 g23659 +11 1 +.names g4246 g22552 g23664 +11 1 +.names g17825 g22995 g23665 +11 1 +.names g16113 g20850 g21278 g22851 +000 1 +.names g22851 g20407 g23666 +11 1 +.names g20850 g20904 g22644 +0- 1 +-0 1 +.names g22644 g20408 g23667 +11 1 +.names g4275 g22560 g23671 +11 1 +.names g4278 g22563 g23672 +11 1 +.names g17842 g22996 g23673 +11 1 +.names g19491 g20928 g22915 +0- 1 +-0 1 +.names g22915 g20413 g23674 +11 1 +.names g4304 g22567 g23679 +11 1 +.names g4307 g22570 g23680 +11 1 +.names g4310 g22573 g23681 +11 1 +.names g17882 g22998 g23686 +11 1 +.names g16075 g21271 g22668 +0- 1 +-0 1 +.names g22668 g17570 g23687 +11 1 +.names g6513 g23001 g23689 +11 1 +.names g17914 g23002 g23693 +11 1 +.names g16113 g20904 g22826 +00 1 +.names g22826 g17591 g23709 +11 1 +.names g4401 g22592 g23714 +11 1 +.names g17937 g23006 g23715 +11 1 +.names g16164 g20858 g21285 g22886 +000 1 +.names g22886 g20432 g23716 +11 1 +.names g20858 g20928 g22680 +0- 1 +-0 1 +.names g22680 g20433 g23717 +11 1 +.names g4430 g22600 g23721 +11 1 +.names g4433 g22603 g23722 +11 1 +.names g17954 g23007 g23723 +11 1 +.names g19512 g20956 g22940 +0- 1 +-0 1 +.names g22940 g20438 g23724 +11 1 +.names g21825 g22843 g23726 +11 1 +.names g17974 g23008 g23734 +11 1 +.names g22949 g9450 g23735 +11 1 +.names g17993 g23012 g23740 +11 1 +.names g16113 g21278 g22708 +0- 1 +-0 1 +.names g22708 g17667 g23741 +11 1 +.names g6777 g23015 g23743 +11 1 +.names g18025 g23016 g23747 +11 1 +.names g16164 g20928 g22865 +00 1 +.names g22865 g17688 g23763 +11 1 +.names g4570 g22629 g23768 +11 1 +.names g18048 g23020 g23769 +11 1 +.names g16223 g20866 g21293 g22921 +000 1 +.names g22921 g20454 g23770 +11 1 +.names g20866 g20956 g22720 +0- 1 +-0 1 +.names g22720 g20455 g23771 +11 1 +.names g21825 g22875 g23772 +11 1 +.names g18074 g23021 g23776 +11 1 +.names g22949 g9528 g23777 +11 1 +.names g22954 g9531 g23778 +11 1 +.names g18091 g23024 g23789 +11 1 +.names g22958 g9592 g23790 +11 1 +.names g18110 g23028 g23795 +11 1 +.names g16164 g21285 g22739 +0- 1 +-0 1 +.names g22739 g17767 g23796 +11 1 +.names g7079 g23031 g23798 +11 1 +.names g18142 g23032 g23802 +11 1 +.names g16223 g20956 g22900 +00 1 +.names g22900 g17788 g23818 +11 1 +.names g3013 g23036 g23820 +11 1 +.names g14148 g23037 g23822 +11 1 +.names g22949 g9641 g23824 +11 1 +.names g22954 g9644 g23825 +11 1 +.names g18190 g23038 g23829 +11 1 +.names g22958 g9670 g23830 +11 1 +.names g22962 g9673 g23831 +11 1 +.names g18207 g23041 g23842 +11 1 +.names g22966 g9734 g23843 +11 1 +.names g18226 g23045 g23848 +11 1 +.names g16223 g21293 g22771 +0- 1 +-0 1 +.names g22771 g17868 g23849 +11 1 +.names g7329 g23048 g23851 +11 1 +.names g17719 g15453 g19179 +00 1 +.names g19179 g22696 g23852 +11 1 +.names g18265 g23049 g23854 +11 1 +.names g22954 g9767 g23855 +11 1 +.names g14263 g23056 g23857 +11 1 +.names g22958 g9787 g23859 +11 1 +.names g22962 g9790 g23860 +11 1 +.names g18297 g23057 g23864 +11 1 +.names g22966 g9816 g23865 +11 1 +.names g22971 g9819 g23866 +11 1 +.names g18314 g23060 g23877 +11 1 +.names g22975 g9880 g23878 +11 1 +.names g18341 g23064 g23886 +11 1 +.names g18358 g23069 g23888 +11 1 +.names g22962 g9913 g23889 +11 1 +.names g14385 g23074 g23891 +11 1 +.names g22966 g9933 g23893 +11 1 +.names g22971 g9936 g23894 +11 1 +.names g18390 g23075 g23898 +11 1 +.names g22975 g9962 g23899 +11 1 +.names g22980 g9965 g23900 +11 1 +.names g3010 g22750 g23904 +11 1 +.names g18436 g23079 g23907 +11 1 +.names g18453 g23082 g23909 +11 1 +.names g22971 g10067 g23910 +11 1 +.names g14497 g23087 g23912 +11 1 +.names g22975 g10087 g23914 +11 1 +.names g22980 g10090 g23915 +11 1 +.names g7545 g23088 g23917 +11 1 +.names g18509 g23095 g23939 +11 1 +.names g18526 g23098 g23941 +11 1 +.names g22980 g10176 g23942 +11 1 +.names g7570 g23103 g23944 +11 1 +.names g18573 g23112 g23971 +11 1 +.names g2903 g23115 g23972 +11 1 +.names g2900 g22903 g24029 +11 1 +.names g22014 g10969 g24211 +11 1 +.names g22825 g10999 g24217 +11 1 +.names g22979 g11042 g24221 +11 1 +.names g22219 g11045 g24224 +11 1 +.names g22232 g11105 g24229 +11 1 +.names g22243 g11157 g24236 +11 1 +.names g22259 g11228 g24241 +11 1 +.names g21982 g11291 g24246 +11 1 +.names g22551 g11297 g24247 +11 1 +.names g21995 g11370 g24253 +11 1 +.names g22003 g11438 g24256 +11 1 +.names g17086 g24134 g13626 g24427 +111 1 +.names g24115 g13614 g24429 +11 1 +.names g17124 g24153 g13637 g24431 +111 1 +.names g14642 g15904 g24115 g24432 +111 1 +.names g24134 g13626 g24433 +11 1 +.names g17151 g24168 g13649 g24435 +111 1 +.names g14669 g15933 g24134 g24436 +111 1 +.names g24153 g13637 g24437 +11 1 +.names g14703 g15962 g24153 g24439 +111 1 +.names g24168 g13649 g24440 +11 1 +.names g14737 g15981 g24168 g24441 +111 1 +.names g22984 g20285 g23545 +00 1 +.names g20092 g20115 g20139 g21119 +000 1 +.names g18414 g18485 g20295 g21227 +000 1 +.names g19933 g17896 g23403 g24529 +111 1 +.names g18548 g23089 g23403 g24540 +111 1 +.names g23420 g17896 g23052 g24541 +111 1 +.names g19950 g18007 g23410 g24542 +111 1 +.names g18548 g23420 g19948 g24550 +111 1 +.names g18598 g23107 g23410 g24552 +111 1 +.names g23429 g18007 g23071 g24553 +111 1 +.names g19977 g18124 g23415 g24554 +111 1 +.names g79 g23448 g24559 +11 1 +.names g18598 g23429 g19975 g24561 +111 1 +.names g18630 g23120 g23415 g24563 +111 1 +.names g23435 g18124 g23084 g24564 +111 1 +.names g20007 g18240 g23424 g24565 +111 1 +.names g767 g23455 g24569 +11 1 +.names g18630 g23435 g20005 g24571 +111 1 +.names g18639 g23129 g23424 g24573 +111 1 +.names g23441 g18240 g23100 g24574 +111 1 +.names g1453 g23464 g24578 +11 1 +.names g18639 g23441 g20043 g24580 +111 1 +.names g2147 g23473 g24585 +11 1 +.names g23486 g23478 g24590 +11 1 +.names g83 g23853 g24591 +11 1 +.names g23502 g23489 g24595 +11 1 +.names g771 g23887 g24596 +11 1 +.names g23518 g23505 g24603 +11 1 +.names g1457 g23908 g24604 +11 1 +.names g23533 g23521 g24610 +11 1 +.names g2151 g23940 g24611 +11 1 +.names g17203 g24115 g24644 +11 1 +.names g17208 g24134 g24664 +11 1 +.names g17214 g24153 g24683 +11 1 +.names g17217 g24168 g24700 +11 1 +.names g9232 g9150 g12780 g15454 +0-- 1 +-0- 1 +--0 1 +.names g15454 g24096 g24745 +11 1 +.names g15454 g24098 g24746 +11 1 +.names g9427 g24099 g24747 +11 1 +.names g672 g24101 g24748 +11 1 +.names g9310 g9174 g12819 g15540 +0-- 1 +-0- 1 +--0 1 +.names g15540 g24102 g24749 +11 1 +.names g15454 g24104 g24750 +11 1 +.names g9427 g24105 g24751 +11 1 +.names g9507 g24106 g24752 +11 1 +.names g15540 g24107 g24754 +11 1 +.names g9569 g24108 g24755 +11 1 +.names g1358 g24110 g24757 +11 1 +.names g9391 g9216 g12857 g15618 +0-- 1 +-0- 1 +--0 1 +.names g15618 g24111 g24758 +11 1 +.names g21825 g23885 g24759 +11 1 +.names g9427 g24112 g24760 +11 1 +.names g9507 g24113 g24761 +11 1 +.names g12876 g24114 g24762 +11 1 +.names g15540 g24121 g24767 +11 1 +.names g9569 g24122 g24768 +11 1 +.names g9649 g24123 g24769 +11 1 +.names g15618 g24124 g24772 +11 1 +.names g9711 g24125 g24773 +11 1 +.names g2052 g24127 g24774 +11 1 +.names g9488 g9277 g12898 g15694 +0-- 1 +-0- 1 +--0 1 +.names g15694 g24128 g24775 +11 1 +.names g9507 g24129 g24776 +11 1 +.names g12876 g24130 g24777 +11 1 +.names g9569 g24131 g24779 +11 1 +.names g9649 g24132 g24780 +11 1 +.names g12916 g24133 g24781 +11 1 +.names g15618 g24140 g24788 +11 1 +.names g9711 g24141 g24789 +11 1 +.names g9795 g24142 g24790 +11 1 +.names g15694 g24143 g24792 +11 1 +.names g9857 g24144 g24793 +11 1 +.names g2746 g24146 g24794 +11 1 +.names g22637 g22665 g24232 +00 1 +.names g12017 g24232 g24795 +11 1 +.names g12876 g24147 g24796 +11 1 +.names g9649 g24148 g24798 +11 1 +.names g12916 g24149 g24799 +11 1 +.names g9711 g24150 g24802 +11 1 +.names g9795 g24151 g24803 +11 1 +.names g12945 g24152 g24804 +11 1 +.names g15694 g24159 g24809 +11 1 +.names g9857 g24160 g24810 +11 1 +.names g9941 g24161 g24811 +11 1 +.names g21825 g23905 g24813 +11 1 +.names g12916 g24162 g24818 +11 1 +.names g9795 g24163 g24821 +11 1 +.names g12945 g24164 g24822 +11 1 +.names g9857 g24165 g24824 +11 1 +.names g9941 g24166 g24825 +11 1 +.names g12974 g24167 g24826 +11 1 +.names g20885 g22175 g24100 +0- 1 +-0 1 +.names g24100 g20401 g24831 +11 1 +.names g12945 g24175 g24838 +11 1 +.names g9941 g24176 g24840 +11 1 +.names g12974 g24177 g24841 +11 1 +.names g21825 g23918 g24843 +11 1 +.names g20904 g22190 g24109 +0- 1 +-0 1 +.names g24109 g20426 g24846 +11 1 +.names g12974 g24180 g24853 +11 1 +.names g18174 g23731 g24855 +11 1 +.names g24047 g18873 g24858 +11 1 +.names g20928 g22199 g24126 +0- 1 +-0 1 +.names g24126 g20448 g24861 +11 1 +.names g666 g23779 g24867 +11 1 +.names g24047 g18894 g24869 +11 1 +.names g18281 g23786 g24870 +11 1 +.names g24060 g18899 g24874 +11 1 +.names g20956 g22205 g24145 +0- 1 +-0 1 +.names g24145 g20467 g24876 +11 1 +.names g19830 g24210 g24878 +11 1 +.names g24047 g18912 g24881 +11 1 +.names g1352 g23832 g24882 +11 1 +.names g24060 g18917 g24884 +11 1 +.names g18374 g23839 g24885 +11 1 +.names g24073 g18922 g24888 +11 1 +.names g24060 g18931 g24898 +11 1 +.names g2046 g23867 g24899 +11 1 +.names g24073 g18936 g24901 +11 1 +.names g18469 g23874 g24902 +11 1 +.names g24084 g18941 g24905 +11 1 +.names g18886 g23879 g24906 +11 1 +.names g7466 g24220 g24907 +11 1 +.names g7342 g23882 g24908 +11 1 +.names g24073 g18951 g24921 +11 1 +.names g2740 g23901 g24922 +11 1 +.names g24084 g18956 g24924 +11 1 +.names g24084 g18967 g24938 +11 1 +.names g7595 g24251 g24964 +11 1 +.names g7600 g24030 g24974 +11 1 +.names g23444 g10880 g25086 +11 1 +.names g23444 g10915 g25102 +11 1 +.names g23444 g10974 g25117 +11 1 +.names g17051 g24115 g13614 g25128 +111 1 +.names g24183 g529 g24623 +00 1 +.names g24623 g20634 g25178 +11 1 +.names g24183 g530 g24636 +00 1 +.names g24636 g20673 g25181 +11 1 +.names g24183 g533 g24681 +00 1 +.names g24681 g20676 g25182 +11 1 +.names g24183 g534 g24694 +00 1 +.names g24694 g20735 g25184 +11 1 +.names g24094 g20842 g24633 +1- 1 +-1 1 +.names g24633 g16608 g25187 +11 1 +.names g24183 g531 g24652 +00 1 +.names g24652 g20763 g25188 +11 1 +.names g24183 g536 g24711 +00 1 +.names g24711 g20790 g25192 +11 1 +.names g24095 g20850 g24653 +1- 1 +-1 1 +.names g24653 g16626 g25193 +11 1 +.names g24097 g20858 g24672 +1- 1 +-1 1 +.names g24672 g16640 g25196 +11 1 +.names g24103 g20866 g24691 +1- 1 +-1 1 +.names g24691 g16651 g25198 +11 1 +.names g24648 g8700 g25269 +11 1 +.names g24648 g8714 g25277 +11 1 +.names g24668 g8719 g25278 +11 1 +.names g5606 g24815 g25281 +11 1 +.names g24648 g8748 g25282 +11 1 +.names g24668 g8752 g25286 +11 1 +.names g24687 g8757 g25287 +11 1 +.names g5631 g24834 g25289 +11 1 +.names g24668 g8771 g25290 +11 1 +.names g24687 g8775 g25294 +11 1 +.names g24704 g8780 g25295 +11 1 +.names g5659 g24850 g25299 +11 1 +.names g24687 g8794 g25300 +11 1 +.names g24704 g8798 g25304 +11 1 +.names g5697 g24864 g25309 +11 1 +.names g24704 g8813 g25310 +11 1 +.names g23688 g24183 g24682 +00 1 +.names g24682 g19358 g19335 g25318 +111 1 +.names g13880 g23483 g25075 +00 1 +.names g25075 g9669 g25321 +11 1 +.names g24644 g17892 g25328 +11 1 +.names g24644 g17984 g25334 +11 1 +.names g24664 g18003 g25337 +11 1 +.names g5851 g24600 g25342 +11 1 +.names g24644 g18084 g25346 +11 1 +.names g24664 g18101 g25348 +11 1 +.names g24683 g18120 g25351 +11 1 +.names g5898 g24607 g25356 +11 1 +.names g24664 g18200 g25360 +11 1 +.names g24683 g18217 g25362 +11 1 +.names g24700 g18236 g25365 +11 1 +.names g5937 g24619 g25371 +11 1 +.names g24683 g18307 g25375 +11 1 +.names g24700 g18324 g25377 +11 1 +.names g5971 g24630 g25388 +11 1 +.names g24700 g18400 g25392 +11 1 +.names g6142 g24763 g25453 +11 1 +.names g6163 g24784 g25457 +11 1 +.names g6190 g24805 g25461 +11 1 +.names g6222 g24827 g25466 +11 1 +.names g23593 g22516 g24479 +00 1 +.names g24479 g20400 g25470 +11 1 +.names g14148 g25087 g25475 +11 1 +.names g23617 g23659 g24480 +00 1 +.names g24480 g17567 g25482 +11 1 +.names g23618 g19696 g24481 +00 1 +.names g24481 g20421 g25483 +11 1 +.names g23625 g22556 g24485 +00 1 +.names g24485 g20425 g25487 +11 1 +.names g6707 g25094 g25505 +11 1 +.names g14263 g25095 g25506 +11 1 +.names g23666 g23709 g24487 +00 1 +.names g24487 g17664 g25513 +11 1 +.names g23667 g19740 g24488 +00 1 +.names g24488 g20443 g25514 +11 1 +.names g23674 g22596 g24489 +00 1 +.names g24489 g20447 g25518 +11 1 +.names g7009 g25104 g25552 +11 1 +.names g14385 g25105 g25553 +11 1 +.names g23716 g23763 g24494 +00 1 +.names g24494 g17764 g25560 +11 1 +.names g23717 g19783 g24495 +00 1 +.names g24495 g20462 g25561 +11 1 +.names g23724 g22633 g24496 +00 1 +.names g24496 g20466 g25565 +11 1 +.names g7259 g25110 g25618 +11 1 +.names g14497 g25111 g25619 +11 1 +.names g23770 g23818 g24504 +00 1 +.names g24504 g17865 g25626 +11 1 +.names g23771 g19825 g24505 +00 1 +.names g24505 g20477 g25627 +11 1 +.names g19836 g17877 g21008 +00 1 +.names g21008 g25115 g25628 +11 1 +.names g3024 g25116 g25629 +11 1 +.names g7455 g25120 g25697 +11 1 +.names g2908 g25126 g25881 +11 1 +.names g16211 g24229 g24800 +00 1 +.names g24800 g13670 g25951 +11 1 +.names g16161 g24224 g24783 +00 1 +.names g24783 g13699 g25953 +11 1 +.names g16160 g24221 g24782 +00 1 +.names g24782 g11869 g25957 +11 1 +.names g16119 g24217 g24770 +00 1 +.names g24770 g11901 g25961 +11 1 +.names g16089 g24211 g24756 +00 1 +.names g24756 g11944 g25963 +11 1 +.names g16422 g24256 g24871 +00 1 +.names g24871 g11986 g25968 +11 1 +.names g16390 g24253 g24859 +00 1 +.names g24859 g12042 g25972 +11 1 +.names g16356 g24247 g24847 +00 1 +.names g24847 g13838 g25973 +11 1 +.names g24183 g537 g24606 +00 1 +.names g24606 g21917 g25975 +11 1 +.names g16350 g24246 g24845 +00 1 +.names g24845 g12089 g25977 +11 1 +.names g16309 g24241 g24836 +00 1 +.names g24836 g13850 g25978 +11 1 +.names g24183 g532 g24663 +00 1 +.names g24663 g21928 g25980 +11 1 +.names g16262 g24236 g24819 +00 1 +.names g24819 g13858 g25981 +11 1 +.names g25422 g24912 g26023 +11 1 +.names g25301 g21102 g26024 +11 1 +.names g25431 g24929 g26026 +11 1 +.names g24482 g22319 g25418 +00 1 +.names g25418 g22271 g26027 +11 1 +.names g25438 g24941 g26028 +11 1 +.names g25445 g24952 g26029 +11 1 +.names g24482 g22319 g25429 +00 1 +.names g25429 g22304 g26030 +11 1 +.names g25379 g19415 g26032 +11 1 +.names g25395 g19452 g26033 +11 1 +.names g25405 g19479 g26034 +11 1 +.names g20842 g24429 g25523 +00 1 +.names g25523 g19483 g26035 +11 1 +.names g25413 g19502 g26036 +11 1 +.names g20850 g24433 g25589 +00 1 +.names g25589 g19504 g26038 +11 1 +.names g20858 g24437 g25668 +00 1 +.names g25668 g19523 g26039 +11 1 +.names g20866 g24440 g25745 +00 1 +.names g25745 g19533 g26040 +11 1 +.names g70 g25296 g26051 +11 1 +.names g24529 g24540 g25941 +00 1 +.names g25941 g21087 g26052 +11 1 +.names g758 g25306 g26053 +11 1 +.names g24542 g24552 g25944 +00 1 +.names g25944 g21099 g26054 +11 1 +.names g24541 g24550 g25943 +00 1 +.names g25943 g21108 g26060 +11 1 +.names g1444 g25315 g26061 +11 1 +.names g24554 g24563 g25947 +00 1 +.names g25947 g21113 g26062 +11 1 +.names g24553 g24561 g25946 +00 1 +.names g25946 g21125 g26067 +11 1 +.names g2138 g25324 g26068 +11 1 +.names g24565 g24573 g25949 +00 1 +.names g25949 g21130 g26069 +11 1 +.names g24564 g24571 g25948 +00 1 +.names g25948 g21144 g26074 +11 1 +.names g74 g25698 g26075 +11 1 +.names g24574 g24580 g25950 +00 1 +.names g25950 g21164 g26080 +11 1 +.names g762 g25771 g26082 +11 1 +.names g1448 g25825 g26085 +11 1 +.names g2142 g25860 g26091 +11 1 +.names g21825 g25630 g26157 +11 1 +.names g679 g25937 g26158 +11 1 +.names g1365 g25939 g26163 +11 1 +.names g686 g25454 g26166 +11 1 +.names g2059 g25942 g26171 +11 1 +.names g1372 g25458 g26186 +11 1 +.names g2753 g25945 g26188 +11 1 +.names g2066 g25463 g26207 +11 1 +.names g4217 g25467 g26212 +11 1 +.names g25895 g9306 g26213 +11 1 +.names g2760 g25472 g26231 +11 1 +.names g4340 g25476 g26233 +11 1 +.names g4343 g25479 g26234 +11 1 +.names g25895 g9368 g26235 +11 1 +.names g25899 g9371 g26236 +11 1 +.names g4372 g25484 g26243 +11 1 +.names g25903 g9387 g26244 +11 1 +.names g4465 g25493 g26257 +11 1 +.names g4468 g25496 g26258 +11 1 +.names g4471 g25499 g26259 +11 1 +.names g24831 g23687 g25254 +00 1 +.names g25254 g17649 g26260 +11 1 +.names g25895 g9443 g26261 +11 1 +.names g25899 g9446 g26262 +11 1 +.names g4476 g25502 g26263 +11 1 +.names g4509 g25507 g26268 +11 1 +.names g4512 g25510 g26269 +11 1 +.names g25903 g9465 g26270 +11 1 +.names g25907 g9468 g26271 +11 1 +.names g4541 g25515 g26278 +11 1 +.names g25911 g9484 g26279 +11 1 +.names g4592 g25524 g26288 +11 1 +.names g4595 g25527 g26289 +11 1 +.names g4598 g25530 g26290 +11 1 +.names g25899 g9524 g26291 +11 1 +.names g4603 g25533 g26292 +11 1 +.names g4606 g25536 g26293 +11 1 +.names g4641 g25540 g26298 +11 1 +.names g4644 g25543 g26299 +11 1 +.names g4647 g25546 g26300 +11 1 +.names g24846 g23741 g25258 +00 1 +.names g25258 g17749 g26301 +11 1 +.names g25903 g9585 g26302 +11 1 +.names g25907 g9588 g26303 +11 1 +.names g4652 g25549 g26307 +11 1 +.names g4685 g25554 g26309 +11 1 +.names g4688 g25557 g26310 +11 1 +.names g25911 g9607 g26311 +11 1 +.names g25915 g9610 g26312 +11 1 +.names g4717 g25562 g26316 +11 1 +.names g25919 g9626 g26317 +11 1 +.names g4737 g25573 g26318 +11 1 +.names g4740 g25576 g26319 +11 1 +.names g4743 g25579 g26324 +11 1 +.names g4746 g25582 g26325 +11 1 +.names g4749 g25585 g26326 +11 1 +.names g4769 g25590 g26332 +11 1 +.names g4772 g25593 g26333 +11 1 +.names g4775 g25596 g26334 +11 1 +.names g25907 g9666 g26335 +11 1 +.names g4780 g25599 g26339 +11 1 +.names g4783 g25602 g26340 +11 1 +.names g4818 g25606 g26342 +11 1 +.names g4821 g25609 g26343 +11 1 +.names g4824 g25612 g26344 +11 1 +.names g24861 g23796 g25261 +00 1 +.names g25261 g17850 g26345 +11 1 +.names g25911 g9727 g26346 +11 1 +.names g25915 g9730 g26347 +11 1 +.names g4829 g25615 g26348 +11 1 +.names g4862 g25620 g26350 +11 1 +.names g4865 g25623 g26351 +11 1 +.names g25919 g9749 g26352 +11 1 +.names g25923 g9752 g26353 +11 1 +.names g4882 g25634 g26357 +11 1 +.names g4888 g25637 g26361 +11 1 +.names g4891 g25640 g26362 +11 1 +.names g4894 g25643 g26363 +11 1 +.names g4913 g25652 g26365 +11 1 +.names g4916 g25655 g26366 +11 1 +.names g4919 g25658 g26371 +11 1 +.names g4922 g25661 g26372 +11 1 +.names g4925 g25664 g26373 +11 1 +.names g4945 g25669 g26379 +11 1 +.names g4948 g25672 g26380 +11 1 +.names g4951 g25675 g26381 +11 1 +.names g25915 g9812 g26382 +11 1 +.names g4956 g25678 g26383 +11 1 +.names g4959 g25681 g26384 +11 1 +.names g4994 g25685 g26386 +11 1 +.names g4997 g25688 g26387 +11 1 +.names g5000 g25691 g26388 +11 1 +.names g24876 g23849 g25264 +00 1 +.names g25264 g17962 g26389 +11 1 +.names g25919 g9873 g26390 +11 1 +.names g25923 g9876 g26391 +11 1 +.names g5005 g25694 g26392 +11 1 +.names g5027 g25700 g26396 +11 1 +.names g5030 g25703 g26397 +11 1 +.names g5041 g25711 g26400 +11 1 +.names g5047 g25714 g26404 +11 1 +.names g5050 g25717 g26405 +11 1 +.names g5053 g25720 g26406 +11 1 +.names g5072 g25729 g26408 +11 1 +.names g5075 g25732 g26409 +11 1 +.names g5078 g25735 g26414 +11 1 +.names g5081 g25738 g26415 +11 1 +.names g5084 g25741 g26416 +11 1 +.names g5104 g25746 g26422 +11 1 +.names g5107 g25749 g26423 +11 1 +.names g5110 g25752 g26424 +11 1 +.names g25923 g9958 g26425 +11 1 +.names g5115 g25755 g26426 +11 1 +.names g5118 g25758 g26427 +11 1 +.names g5145 g25767 g26432 +11 1 +.names g5156 g25773 g26437 +11 1 +.names g5159 g25776 g26438 +11 1 +.names g5170 g25784 g26441 +11 1 +.names g5176 g25787 g26445 +11 1 +.names g5179 g25790 g26446 +11 1 +.names g5182 g25793 g26447 +11 1 +.names g5201 g25802 g26449 +11 1 +.names g5204 g25805 g26450 +11 1 +.names g5207 g25808 g26455 +11 1 +.names g5210 g25811 g26456 +11 1 +.names g5213 g25814 g26457 +11 1 +.names g5238 g25821 g26464 +11 1 +.names g5249 g25827 g26469 +11 1 +.names g5252 g25830 g26470 +11 1 +.names g5263 g25838 g26473 +11 1 +.names g5269 g25841 g26477 +11 1 +.names g5272 g25844 g26478 +11 1 +.names g5275 g25847 g26479 +11 1 +.names g5301 g25856 g26488 +11 1 +.names g5312 g25862 g26493 +11 1 +.names g5315 g25865 g26494 +11 1 +.names g5338 g25877 g26504 +11 1 +.names g25274 g21066 g26663 +11 1 +.names g25283 g21076 g26668 +11 1 +.names g8580 g10730 g12431 +00 1 +.names g12431 g25318 g26673 +11 1 +.names g25291 g21090 g26674 +11 1 +.names g14657 g26508 g26754 +11 1 +.names g25426 g22319 g26083 +00 1 +.names g26083 g22239 g26755 +11 1 +.names g25426 g22319 g26113 +00 1 +.names g26113 g22240 g26756 +11 1 +.names g15962 g15942 g14677 g16614 +000 1 +.names g16614 g26521 g13637 g26758 +111 1 +.names g16539 g25183 g26356 +0- 1 +-0 1 +.names g26356 g19251 g26759 +11 1 +.names g6068 g24183 g25355 g26137 +000 1 +.names g26137 g22256 g26760 +11 1 +.names g6068 g24183 g25329 g26154 +000 1 +.names g26154 g22257 g26761 +11 1 +.names g14691 g26516 g26763 +11 1 +.names g15981 g15971 g14711 g16632 +000 1 +.names g16632 g26525 g13649 g26764 +111 1 +.names g16571 g25186 g26399 +0- 1 +-0 1 +.names g26399 g19265 g26765 +11 1 +.names g14725 g26521 g26766 +11 1 +.names g6068 g24183 g25319 g26087 +000 1 +.names g26087 g22287 g26767 +11 1 +.names g16595 g25190 g26440 +0- 1 +-0 1 +.names g26440 g19280 g26768 +11 1 +.names g14753 g26525 g26769 +11 1 +.names g25422 g25379 g25274 g26059 +0-- 1 +-0- 1 +--0 1 +.names g26059 g19287 g26770 +11 1 +.names g24912 g26508 g13614 g26771 +111 1 +.names g6068 g24183 g25347 g26145 +000 1 +.names g26145 g22303 g26773 +11 1 +.names g16615 g25195 g26472 +0- 1 +-0 1 +.names g26472 g19299 g26774 +11 1 +.names g6068 g24183 g25313 g26099 +000 1 +.names g26099 g22318 g26775 +11 1 +.names g25431 g25395 g25283 g26066 +0-- 1 +-0- 1 +--0 1 +.names g26066 g19305 g26777 +11 1 +.names g24929 g26516 g13626 g26778 +111 1 +.names g8278 g14657 g25422 g25379 g26119 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g26119 g16622 g26780 +11 1 +.names g25438 g25405 g25291 g26073 +0-- 1 +-0- 1 +--0 1 +.names g26073 g19326 g26783 +11 1 +.names g24941 g26521 g13637 g26784 +111 1 +.names g8287 g14691 g25431 g25395 g26129 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g26129 g16636 g26787 +11 1 +.names g25445 g25413 g25301 g26079 +0-- 1 +-0- 1 +--0 1 +.names g26079 g19353 g26790 +11 1 +.names g24952 g26525 g13649 g26791 +111 1 +.names g8296 g14725 g25438 g25405 g26143 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g26143 g16647 g26794 +11 1 +.names g8305 g14753 g25445 g25413 g26148 +0--- 1 +-0-- 1 +--0- 1 +---0 1 +.names g26148 g16659 g26797 +11 1 +.names g5623 g26209 g26829 +11 1 +.names g5651 g26237 g26833 +11 1 +.names g5689 g26275 g26842 +11 1 +.names g5664 g26056 g26845 +11 1 +.names g5741 g26313 g26851 +11 1 +.names g5716 g26063 g26853 +11 1 +.names g5774 g26070 g26860 +11 1 +.names g5833 g26076 g26866 +11 1 +.names g6157 g26533 g26955 +11 1 +.names g6184 g26538 g26958 +11 1 +.names g13907 g26175 g26961 +11 1 +.names g6180 g26178 g26962 +11 1 +.names g6216 g26539 g26963 +11 1 +.names g23066 g23051 g23320 +0- 1 +-0 1 +.names g23320 g26540 g26965 +11 1 +.names g13963 g26196 g26966 +11 1 +.names g6212 g26202 g26967 +11 1 +.names g6305 g26542 g26968 +11 1 +.names g23320 g26543 g26969 +11 1 +.names g19242 g21120 g19275 g21976 +0-- 1 +-0- 1 +--0 1 +.names g21976 g26544 g26970 +11 1 +.names g23080 g23070 g23325 +0- 1 +-0 1 +.names g23325 g26546 g26971 +11 1 +.names g14033 g26223 g26972 +11 1 +.names g6301 g26226 g26973 +11 1 +.names g23320 g26550 g26977 +11 1 +.names g21976 g26551 g26978 +11 1 +.names g22999 g22174 g23331 +0- 1 +-0 1 +.names g23331 g26552 g26979 +11 1 +.names g21980 g21975 g23360 +0- 1 +-0 1 +.names g23360 g26554 g26980 +11 1 +.names g23325 g26555 g26981 +11 1 +.names g19255 g21139 g19294 g21983 +0-- 1 +-0- 1 +--0 1 +.names g21983 g26556 g26982 +11 1 +.names g23096 g23083 g23335 +0- 1 +-0 1 +.names g23335 g26558 g26984 +11 1 +.names g14124 g26251 g26985 +11 1 +.names g6438 g26254 g26986 +11 1 +.names g21976 g26561 g26993 +11 1 +.names g23331 g26562 g26994 +11 1 +.names g21501 g21536 g21991 +0- 1 +-0 1 +.names g21991 g26563 g26995 +11 1 +.names g23360 g26564 g26996 +11 1 +.names g19450 g21244 g19503 g22050 +0-- 1 +-0- 1 +--0 1 +.names g22050 g26565 g26997 +11 1 +.names g23325 g26566 g26998 +11 1 +.names g21983 g26567 g26999 +11 1 +.names g23013 g22189 g23340 +0- 1 +-0 1 +.names g23340 g26568 g27000 +11 1 +.names g21987 g21981 g23364 +0- 1 +-0 1 +.names g23364 g26570 g27001 +11 1 +.names g23335 g26571 g27002 +11 1 +.names g19268 g21159 g19312 g21996 +0-- 1 +-0- 1 +--0 1 +.names g21996 g26572 g27003 +11 1 +.names g23113 g23099 g23344 +0- 1 +-0 1 +.names g23344 g26574 g27004 +11 1 +.names g23331 g26578 g27005 +11 1 +.names g21991 g26579 g27006 +11 1 +.names g23360 g26580 g27007 +11 1 +.names g22050 g26581 g27008 +11 1 +.names g23135 g22288 g23368 +0- 1 +-0 1 +.names g23368 g26582 g27009 +11 1 +.names g21983 g26584 g27016 +11 1 +.names g23340 g26585 g27017 +11 1 +.names g21540 g21572 g22005 +0- 1 +-0 1 +.names g22005 g26586 g27018 +11 1 +.names g23364 g26587 g27019 +11 1 +.names g19477 g21253 g19522 g22069 +0-- 1 +-0- 1 +--0 1 +.names g22069 g26588 g27020 +11 1 +.names g23335 g26589 g27021 +11 1 +.names g21996 g26590 g27022 +11 1 +.names g23029 g22198 g23349 +0- 1 +-0 1 +.names g23349 g26591 g27023 +11 1 +.names g22000 g21988 g23372 +0- 1 +-0 1 +.names g23372 g26593 g27024 +11 1 +.names g23344 g26594 g27025 +11 1 +.names g19283 g21179 g19333 g22009 +0-- 1 +-0- 1 +--0 1 +.names g22009 g26595 g27026 +11 1 +.names g21991 g26598 g27027 +11 1 +.names g22050 g26599 g27028 +11 1 +.names g23368 g26600 g27029 +11 1 +.names g21774 g21787 g22083 +0- 1 +-0 1 +.names g22083 g26601 g27030 +11 1 +.names g23340 g26602 g27031 +11 1 +.names g22005 g26603 g27032 +11 1 +.names g23364 g26604 g27033 +11 1 +.names g22069 g26605 g27034 +11 1 +.names g21968 g22308 g23377 +0- 1 +-0 1 +.names g23377 g26606 g27035 +11 1 +.names g21996 g26608 g27042 +11 1 +.names g23349 g26609 g27043 +11 1 +.names g21576 g21605 g22016 +0- 1 +-0 1 +.names g22016 g26610 g27044 +11 1 +.names g23372 g26611 g27045 +11 1 +.names g19500 g21261 g19532 g22093 +0-- 1 +-0- 1 +--0 1 +.names g22093 g26612 g27046 +11 1 +.names g23344 g26613 g27047 +11 1 +.names g22009 g26614 g27048 +11 1 +.names g23046 g22204 g23353 +0- 1 +-0 1 +.names g23353 g26615 g27049 +11 1 +.names g22013 g22001 g23381 +0- 1 +-0 1 +.names g23381 g26617 g27050 +11 1 +.names g4885 g26358 g27052 +11 1 +.names g23368 g26619 g27053 +11 1 +.names g22083 g26620 g27054 +11 1 +.names g22005 g26621 g27055 +11 1 +.names g22069 g26622 g27056 +11 1 +.names g23377 g26623 g27057 +11 1 +.names g21789 g21801 g22108 +0- 1 +-0 1 +.names g22108 g26624 g27058 +11 1 +.names g23349 g26625 g27059 +11 1 +.names g22016 g26626 g27060 +11 1 +.names g23372 g26627 g27061 +11 1 +.names g22093 g26628 g27062 +11 1 +.names g21971 g22336 g23388 +0- 1 +-0 1 +.names g23388 g26629 g27063 +11 1 +.names g22009 g26631 g27070 +11 1 +.names g23353 g26632 g27071 +11 1 +.names g21609 g21634 g22021 +0- 1 +-0 1 +.names g22021 g26633 g27072 +11 1 +.names g23381 g26634 g27073 +11 1 +.names g19521 g21269 g19542 g22118 +0-- 1 +-0- 1 +--0 1 +.names g22118 g26635 g27074 +11 1 +.names g5024 g26393 g27076 +11 1 +.names g22083 g26636 g27077 +11 1 +.names g5044 g26401 g27079 +11 1 +.names g23377 g26637 g27080 +11 1 +.names g22108 g26638 g27081 +11 1 +.names g22016 g26639 g27082 +11 1 +.names g22093 g26640 g27083 +11 1 +.names g23388 g26641 g27084 +11 1 +.names g21803 g21809 g22134 +0- 1 +-0 1 +.names g22134 g26642 g27085 +11 1 +.names g23353 g26643 g27086 +11 1 +.names g22021 g26644 g27087 +11 1 +.names g23381 g26645 g27088 +11 1 +.names g22118 g26646 g27089 +11 1 +.names g21973 g22361 g23395 +0- 1 +-0 1 +.names g23395 g26647 g27090 +11 1 +.names g5142 g26429 g27091 +11 1 +.names g5153 g26434 g27092 +11 1 +.names g22108 g26648 g27093 +11 1 +.names g5173 g26442 g27095 +11 1 +.names g23388 g26649 g27096 +11 1 +.names g22134 g26650 g27097 +11 1 +.names g22021 g26651 g27098 +11 1 +.names g22118 g26652 g27099 +11 1 +.names g23395 g26653 g27100 +11 1 +.names g21811 g21816 g22157 +0- 1 +-0 1 +.names g22157 g26654 g27101 +11 1 +.names g5235 g26461 g27103 +11 1 +.names g5246 g26466 g27104 +11 1 +.names g22134 g26656 g27105 +11 1 +.names g5266 g26474 g27107 +11 1 +.names g23395 g26657 g27108 +11 1 +.names g22157 g26658 g27109 +11 1 +.names g5298 g26485 g27110 +11 1 +.names g5309 g26490 g27111 +11 1 +.names g22157 g26662 g27112 +11 1 +.names g5335 g26501 g27115 +11 1 +.names g6068 g24183 g25305 g26110 +000 1 +.names g26110 g22213 g27178 +11 1 +.names g15904 g15880 g14630 g16570 +000 1 +.names g16570 g26508 g13614 g27181 +111 1 +.names g6068 g24183 g25335 g26151 +000 1 +.names g26151 g22217 g27182 +11 1 +.names g6068 g24183 g25368 g26126 +000 1 +.names g26126 g22230 g27185 +11 1 +.names g15933 g15913 g14650 g16594 +000 1 +.names g16594 g26516 g13626 g27187 +111 1 +.names g26096 g22319 g26905 +00 1 +.names g26905 g22241 g27240 +11 1 +.names II35124 II35125 g26934 +0- 1 +-0 1 +.names g10730 g26934 g27241 +11 1 +.names g26793 g8357 g27242 +11 1 +.names g26107 g22319 g26914 +00 1 +.names g26914 g22258 g27244 +11 1 +.names g26140 g22319 g26877 +00 1 +.names g26877 g22286 g27245 +11 1 +.names g24893 g26023 g26988 +00 1 +.names g26988 g16676 g27246 +11 1 +.names g24916 g26026 g27011 +00 1 +.names g27011 g16702 g27247 +11 1 +.names g24933 g26028 g27037 +00 1 +.names g27037 g16733 g27248 +11 1 +.names g24945 g26029 g27065 +00 1 +.names g27065 g16775 g27249 +11 1 +.names g61 g26837 g27355 +11 1 +.names g65 g26987 g27356 +11 1 +.names g749 g26846 g27358 +11 1 +.names g753 g27010 g27359 +11 1 +.names g1435 g26855 g27364 +11 1 +.names g1439 g27036 g27365 +11 1 +.names g27126 g8874 g27370 +11 1 +.names g2129 g26861 g27371 +11 1 +.names g2133 g27064 g27372 +11 1 +.names g17802 g27134 g27394 +11 1 +.names g692 g27135 g27396 +11 1 +.names g17914 g27136 g27407 +11 1 +.names g1378 g27137 g27409 +11 1 +.names g18025 g27138 g27425 +11 1 +.names g2072 g27139 g27427 +11 1 +.names g18142 g27141 g27446 +11 1 +.names g2766 g27142 g27448 +11 1 +.names g4456 g13565 g23009 g23945 +000 1 +.names g23945 g27146 g27495 +11 1 +.names g23945 g27148 g27509 +11 1 +.names g4632 g13573 g23025 g23974 +000 1 +.names g23974 g27151 g27516 +11 1 +.names g23945 g27153 g27530 +11 1 +.names g23974 g27155 g27534 +11 1 +.names g4809 g13582 g23042 g24004 +000 1 +.names g24004 g27159 g27541 +11 1 +.names g23974 g27162 g27552 +11 1 +.names g24004 g27164 g27554 +11 1 +.names g4985 g13602 g23061 g24038 +000 1 +.names g24038 g27167 g27561 +11 1 +.names g24004 g27172 g27568 +11 1 +.names g24038 g27173 g27570 +11 1 +.names g24038 g27177 g27578 +11 1 +.names g26796 g11004 g27656 +11 1 +.names g27114 g11051 g27657 +11 1 +.names g27132 g11114 g27659 +11 1 +.names g26835 g11117 g27660 +11 1 +.names g26841 g11173 g27661 +11 1 +.names g26849 g11243 g27666 +11 1 +.names g26140 g22319 g26885 +00 1 +.names g26885 g22212 g27671 +11 1 +.names g26854 g11312 g27673 +11 1 +.names g26782 g11386 g27679 +11 1 +.names g26983 g11392 g27680 +11 1 +.names g26788 g11456 g27681 +11 1 +.names g27185 g25178 g27496 +00 1 +.names g27496 g20649 g27719 +11 1 +.names g27182 g25980 g27481 +00 1 +.names g27481 g20652 g27720 +11 1 +.names g26775 g25192 g27579 +00 1 +.names g27579 g20655 g27721 +11 1 +.names g27178 g25975 g27464 +00 1 +.names g27464 g20679 g27723 +11 1 +.names g26761 g25182 g27532 +00 1 +.names g27532 g20704 g27725 +11 1 +.names g26760 g25181 g27531 +00 1 +.names g27531 g20732 g27726 +11 1 +.names g26770 g25187 g27414 +00 1 +.names g27414 g19301 g27727 +11 1 +.names g26767 g25184 g27564 +00 1 +.names g27564 g20766 g27728 +11 1 +.names g26777 g25193 g27435 +00 1 +.names g27435 g19322 g27729 +11 1 +.names g26783 g25196 g27454 +00 1 +.names g27454 g19349 g27730 +11 1 +.names g26790 g25198 g27470 +00 1 +.names g27470 g19383 g27731 +11 1 +.names g24958 g24633 g26771 g27492 +000 1 +.names g27492 g16758 g27732 +11 1 +.names g24969 g24653 g26778 g27513 +000 1 +.names g27513 g16785 g27733 +11 1 +.names g24982 g24672 g26784 g27538 +000 1 +.names g27538 g16814 g27734 +11 1 +.names g24993 g24691 g26791 g27558 +000 1 +.names g27558 g16832 g27737 +11 1 +.names g5642 g27449 g27770 +11 1 +.names g5680 g27465 g27772 +11 1 +.names g5732 g27484 g27773 +11 1 +.names g5702 g27361 g27774 +11 1 +.names g5790 g27506 g27775 +11 1 +.names g5760 g27367 g27779 +11 1 +.names g5819 g27373 g27783 +11 1 +.names g5875 g27376 g27790 +11 1 +.names g13873 g27387 g27904 +11 1 +.names g13886 g27391 g27908 +11 1 +.names g13895 g27397 g27909 +11 1 +.names g4017 g27401 g27913 +11 1 +.names g13927 g27404 g27914 +11 1 +.names g13936 g27410 g27915 +11 1 +.names g4112 g27416 g27922 +11 1 +.names g4144 g27419 g27923 +11 1 +.names g13983 g27422 g27924 +11 1 +.names g13992 g27428 g27926 +11 1 +.names g4221 g27432 g27931 +11 1 +.names g4251 g27437 g27935 +11 1 +.names g4283 g27440 g27936 +11 1 +.names g14053 g27443 g27938 +11 1 +.names g4376 g27451 g27945 +11 1 +.names g4406 g27456 g27949 +11 1 +.names g4438 g27459 g27951 +11 1 +.names g4545 g27467 g27963 +11 1 +.names g4575 g27472 g27968 +11 1 +.names g14238 g27475 g27970 +11 1 +.names g4721 g27486 g27984 +11 1 +.names g14342 g27489 g27985 +11 1 +.names g14360 g27498 g27991 +11 1 +.names g27590 g9770 g28008 +11 1 +.names g14454 g27510 g28009 +11 1 +.names g14472 g27518 g28015 +11 1 +.names g27590 g9895 g28027 +11 1 +.names g27595 g9898 g28028 +11 1 +.names g27599 g9916 g28035 +11 1 +.names g14541 g27535 g28036 +11 1 +.names g14559 g27543 g28042 +11 1 +.names g27590 g10018 g28050 +11 1 +.names g27595 g10021 g28051 +11 1 +.names g27599 g10049 g28057 +11 1 +.names g27604 g10052 g28058 +11 1 +.names g27608 g10070 g28065 +11 1 +.names g14596 g27555 g28066 +11 1 +.names g27595 g10109 g28073 +11 1 +.names g27599 g10127 g28079 +11 1 +.names g27604 g10130 g28080 +11 1 +.names g27608 g10158 g28086 +11 1 +.names g27613 g10161 g28087 +11 1 +.names g27617 g10179 g28094 +11 1 +.names g27604 g10214 g28098 +11 1 +.names g27608 g10232 g28104 +11 1 +.names g27613 g10235 g28105 +11 1 +.names g27617 g10263 g28111 +11 1 +.names g27622 g10266 g28112 +11 1 +.names g27613 g10316 g28116 +11 1 +.names g27617 g10334 g28122 +11 1 +.names g27622 g10337 g28123 +11 1 +.names g27622 g10409 g28127 +11 1 +.names g27349 g10898 g28171 +11 1 +.names g27349 g10940 g28176 +11 1 +.names g27349 g11008 g28188 +11 1 +.names g26773 g25188 g27573 +00 1 +.names g27573 g21914 g28193 +11 1 +.names g6087 g27632 g25385 g27855 +000 1 +.names g27855 g22246 g28319 +11 1 +.names g27632 g1218 g27854 +00 1 +.names g27854 g20637 g28320 +11 1 +.names g16321 g27666 g27937 +00 1 +.names g27937 g13868 g28322 +11 1 +.names II36301 II36302 g27838 +0- 1 +-0 1 +.names g8580 g27838 g28323 +11 1 +.names g27632 g1215 g27810 +00 1 +.names g27810 g20659 g28324 +11 1 +.names g6087 g27632 g25370 g27865 +000 1 +.names g27865 g22274 g28326 +11 1 +.names g6087 g27632 g25338 g27900 +000 1 +.names g27900 g22275 g28327 +11 1 +.names g27632 g1216 g27823 +00 1 +.names g27823 g20708 g28329 +11 1 +.names g27632 g1219 g27864 +00 1 +.names g27864 g20711 g28330 +11 1 +.names g6087 g27632 g25330 g27802 +000 1 +.names g27802 g22307 g28331 +11 1 +.names g6087 g27632 g25361 g27883 +000 1 +.names g27883 g22331 g28332 +11 1 +.names g27632 g1220 g27882 +00 1 +.names g27882 g20772 g28333 +11 1 +.names g27632 g1217 g27842 +00 1 +.names g27842 g20793 g28334 +11 1 +.names g6087 g27632 g25322 g27814 +000 1 +.names g27814 g22343 g28335 +11 1 +.names g27632 g1222 g27896 +00 1 +.names g27896 g20810 g28336 +11 1 +.names g26032 g27246 g28002 +00 1 +.names g28002 g19448 g28337 +11 1 +.names g26033 g27247 g28029 +00 1 +.names g28029 g19475 g28338 +11 1 +.names g26034 g27248 g28059 +00 1 +.names g28059 g19498 g28339 +11 1 +.names g26036 g27249 g28088 +00 1 +.names g28088 g19519 g28340 +11 1 +.names g56 g27969 g28373 +11 1 +.names g744 g27990 g28376 +11 1 +.names g52 g27776 g28378 +11 1 +.names g23742 g27632 g27868 +00 1 +.names g27868 g19390 g19369 g28379 +111 1 +.names g1430 g28014 g28380 +11 1 +.names g13902 g27370 g28157 +00 1 +.names g28157 g9815 g28381 +11 1 +.names g740 g27780 g28383 +11 1 +.names g2124 g28041 g28385 +11 1 +.names g1426 g27787 g28387 +11 1 +.names g2120 g27794 g28389 +11 1 +.names g7754 g27806 g28396 +11 1 +.names g7769 g27817 g28398 +11 1 +.names g7776 g27820 g28399 +11 1 +.names g7782 g27831 g28401 +11 1 +.names g7785 g27839 g28402 +11 1 +.names g7792 g27843 g28404 +11 1 +.names g7796 g27847 g28405 +11 1 +.names g7799 g27858 g28407 +11 1 +.names g7806 g27861 g28408 +11 1 +.names g7809 g27872 g28411 +11 1 +.names g7812 g27879 g28412 +11 1 +.names g7823 g27889 g28416 +11 1 +.names g17640 g28150 g28422 +11 1 +.names g17724 g28152 g28423 +11 1 +.names g17741 g28153 g28424 +11 1 +.names g28128 g9170 g28426 +11 1 +.names g26092 g28154 g28427 +11 1 +.names g17825 g28155 g28428 +11 1 +.names g17842 g28156 g28429 +11 1 +.names g28128 g9196 g28430 +11 1 +.names g26092 g28158 g28431 +11 1 +.names g28133 g9212 g28433 +11 1 +.names g26114 g28159 g28434 +11 1 +.names g17937 g28160 g28435 +11 1 +.names g17954 g28161 g28436 +11 1 +.names g17882 g27919 g28438 +11 1 +.names g28128 g9242 g28439 +11 1 +.names g26092 g28162 g28440 +11 1 +.names g28133 g9257 g28441 +11 1 +.names g26114 g28163 g28442 +11 1 +.names g28137 g9273 g28444 +11 1 +.names g26121 g28164 g28445 +11 1 +.names g18048 g28165 g28446 +11 1 +.names g17974 g27928 g28448 +11 1 +.names g17993 g27932 g28450 +11 1 +.names g28133 g9320 g28451 +11 1 +.names g26114 g28166 g28452 +11 1 +.names g28137 g9335 g28453 +11 1 +.names g26121 g28167 g28454 +11 1 +.names g28141 g9351 g28456 +11 1 +.names g26131 g28168 g28457 +11 1 +.names g18074 g27939 g28459 +11 1 +.names g18091 g27942 g28460 +11 1 +.names g18110 g27946 g28462 +11 1 +.names g28137 g9401 g28463 +11 1 +.names g26121 g28169 g28464 +11 1 +.names g28141 g9416 g28465 +11 1 +.names g26131 g28170 g28466 +11 1 +.names g18265 g28172 g28468 +11 1 +.names g18179 g27952 g28469 +11 1 +.names g18190 g27956 g28471 +11 1 +.names g18207 g27959 g28472 +11 1 +.names g18226 g27965 g28474 +11 1 +.names g28141 g9498 g28475 +11 1 +.names g26131 g28173 g28476 +11 1 +.names g18341 g28174 g28477 +11 1 +.names g18358 g28175 g28478 +11 1 +.names g18286 g27973 g28479 +11 1 +.names g18297 g27977 g28480 +11 1 +.names g18314 g27981 g28481 +11 1 +.names g18436 g28177 g28484 +11 1 +.names g18453 g28178 g28485 +11 1 +.names g18379 g27994 g28486 +11 1 +.names g18390 g27999 g28487 +11 1 +.names g18509 g28186 g28492 +11 1 +.names g18526 g28187 g28493 +11 1 +.names g18474 g28018 g28494 +11 1 +.names g18573 g28190 g28497 +11 1 +.names g16276 g27661 g27925 +00 1 +.names g27925 g13700 g28657 +11 1 +.names g16220 g27660 g27917 +00 1 +.names g27917 g13736 g28659 +11 1 +.names g16219 g27659 g27916 +00 1 +.names g27916 g11911 g28660 +11 1 +.names g16170 g27657 g27911 +00 1 +.names g27911 g11951 g28662 +11 1 +.names g16127 g27656 g27906 +00 1 +.names g27906 g11997 g28663 +11 1 +.names g16456 g27242 g27997 +00 1 +.names g27997 g12055 g28664 +11 1 +.names g6087 g27632 g25314 g27827 +000 1 +.names g27827 g22222 g28665 +11 1 +.names g16428 g27681 g27980 +00 1 +.names g27980 g12106 g28666 +11 1 +.names g16400 g27680 g27964 +00 1 +.names g27964 g13852 g28667 +11 1 +.names g6087 g27632 g25349 g27897 +000 1 +.names g27897 g22233 g28669 +11 1 +.names g27632 g1223 g27798 +00 1 +.names g27798 g21935 g28670 +11 1 +.names g16394 g27679 g27962 +00 1 +.names g27962 g12161 g28671 +11 1 +.names g16367 g27673 g27950 +00 1 +.names g27950 g13859 g28672 +11 1 +.names g8587 g10749 g12436 +00 1 +.names g12436 g28379 g28707 +11 1 +.names g27886 g22344 g28392 +00 1 +.names g28392 g22260 g28708 +11 1 +.names g27886 g22344 g28400 +00 1 +.names g28400 g22261 g28709 +11 1 +.names g27811 g22344 g28403 +00 1 +.names g28403 g22262 g28710 +11 1 +.names II37357 II37358 g28415 +0- 1 +-0 1 +.names g10749 g28415 g28711 +11 1 +.names g27824 g22344 g28406 +00 1 +.names g28406 g22276 g28712 +11 1 +.names g27748 g22344 g28410 +00 1 +.names g28410 g22290 g28713 +11 1 +.names g27869 g22344 g28394 +00 1 +.names g28394 g22306 g28714 +11 1 +.names g27748 g22344 g28414 +00 1 +.names g28414 g22332 g28715 +11 1 +.names g27727 g26780 g28449 +00 1 +.names g28449 g19319 g28716 +11 1 +.names g27729 g26787 g28461 +00 1 +.names g28461 g19346 g28717 +11 1 +.names g27730 g26794 g28473 +00 1 +.names g28473 g19380 g28718 +11 1 +.names g27731 g26797 g28482 +00 1 +.names g28482 g19412 g28719 +11 1 +.names g26035 g27732 g28523 +00 1 +.names g28523 g16694 g28722 +11 1 +.names g26038 g27733 g28551 +00 1 +.names g28551 g16725 g28724 +11 1 +.names g26039 g27734 g28578 +00 1 +.names g28578 g16767 g28726 +11 1 +.names g26040 g27737 g28606 +00 1 +.names g28606 g16794 g28729 +11 1 +.names g5751 g28483 g28834 +11 1 +.names g5810 g28491 g28836 +11 1 +.names g5866 g28496 g28838 +11 1 +.names g5913 g28500 g28840 +11 1 +.names g27478 g14630 g27834 +00 1 +.names g27834 g28554 g28841 +11 1 +.names g27834 g28581 g28843 +11 1 +.names g27501 g14650 g27850 +00 1 +.names g27850 g28582 g28844 +11 1 +.names g27834 g28608 g28846 +11 1 +.names g27850 g28609 g28847 +11 1 +.names g27521 g14677 g27875 +00 1 +.names g27875 g28610 g28848 +11 1 +.names g27850 g28616 g28849 +11 1 +.names g27875 g28617 g28850 +11 1 +.names g27546 g14711 g27892 +00 1 +.names g27892 g28618 g28851 +11 1 +.names g27875 g28623 g28852 +11 1 +.names g27892 g28624 g28853 +11 1 +.names g27892 g28629 g28854 +11 1 +.names g13946 g28639 g28880 +11 1 +.names g28612 g9199 g28881 +11 1 +.names g14001 g28640 g28892 +11 1 +.names g28612 g9245 g28893 +11 1 +.names g14016 g28641 g28897 +11 1 +.names g28619 g9260 g28898 +11 1 +.names g14062 g28642 g28909 +11 1 +.names g28612 g9303 g28910 +11 1 +.names g14092 g28643 g28914 +11 1 +.names g28619 g9323 g28915 +11 1 +.names g14107 g28644 g28919 +11 1 +.names g28625 g9338 g28923 +11 1 +.names g14153 g28645 g28931 +11 1 +.names g14177 g28646 g28935 +11 1 +.names g28619 g9384 g28936 +11 1 +.names g14207 g28647 g28940 +11 1 +.names g28625 g9404 g28944 +11 1 +.names g14222 g28648 g28948 +11 1 +.names g28630 g9419 g28949 +11 1 +.names g14268 g28649 g28958 +11 1 +.names g14292 g28650 g28962 +11 1 +.names g28625 g9481 g28966 +11 1 +.names g14322 g28651 g28970 +11 1 +.names g28630 g9501 g28971 +11 1 +.names g14390 g28652 g28986 +11 1 +.names g14414 g28653 g28996 +11 1 +.names g28630 g9623 g28997 +11 1 +.names g14502 g28655 g29022 +11 1 +.names g27869 g22344 g28397 +00 1 +.names g28397 g22221 g29130 +11 1 +.names g28319 g28324 g29031 +00 1 +.names g29031 g20684 g29174 +11 1 +.names g28669 g28320 g29009 +00 1 +.names g29009 g20687 g29175 +11 1 +.names g28335 g28336 g29097 +00 1 +.names g29097 g20690 g29176 +11 1 +.names g28665 g28670 g28982 +00 1 +.names g28982 g20714 g29180 +11 1 +.names g28327 g28330 g29064 +00 1 +.names g29064 g20739 g29183 +11 1 +.names g28326 g28329 g29063 +00 1 +.names g29063 g20769 g29186 +11 1 +.names g28331 g28333 g29083 +00 1 +.names g29083 g20796 g29188 +11 1 +.names g15022 g28741 g29196 +11 1 +.names g15096 g28751 g29200 +11 1 +.names g15118 g28755 g29203 +11 1 +.names g15188 g28764 g29208 +11 1 +.names g15210 g28768 g29211 +11 1 +.names g15274 g28775 g29217 +11 1 +.names g15296 g28779 g29220 +11 1 +.names g15366 g28785 g29225 +11 1 +.names g9293 g28791 g29229 +11 1 +.names g9356 g28796 g29232 +11 1 +.names g9374 g28799 g29233 +11 1 +.names g9427 g28804 g29234 +11 1 +.names g9453 g28807 g29235 +11 1 +.names g9471 g28810 g29236 +11 1 +.names g9569 g28814 g29238 +11 1 +.names g9595 g28817 g29239 +11 1 +.names g9613 g28820 g29240 +11 1 +.names g9711 g28823 g29241 +11 1 +.names g9737 g28826 g29242 +11 1 +.names g9857 g28829 g29243 +11 1 +.names g28855 g8836 g29248 +11 1 +.names g28855 g8856 g29251 +11 1 +.names g28859 g8863 g29252 +11 1 +.names g28855 g8885 g29255 +11 1 +.names g28859 g8894 g29256 +11 1 +.names g28863 g8901 g29257 +11 1 +.names g28859 g8925 g29259 +11 1 +.names g28863 g8934 g29260 +11 1 +.names g28867 g8941 g29261 +11 1 +.names g28863 g8965 g29262 +11 1 +.names g28867 g8974 g29263 +11 1 +.names g28867 g8997 g29264 +11 1 +.names g9161 g28512 g29001 +0- 1 +-0 1 +.names g29001 g28871 g29284 +11 1 +.names g9203 g28540 g29030 +0- 1 +-0 1 +.names g29030 g28883 g29289 +11 1 +.names g9264 g28567 g29053 +0- 1 +-0 1 +.names g29053 g28900 g29294 +11 1 +.names g9342 g28595 g29072 +0- 1 +-0 1 +.names g29072 g28925 g29300 +11 1 +.names g9187 g28512 g29026 +0- 1 +-0 1 +.names g29026 g28928 g29302 +11 1 +.names g9150 g28512 g28978 +0- 1 +-0 1 +.names g28978 g28951 g29310 +11 1 +.names g9248 g28540 g29049 +0- 1 +-0 1 +.names g29049 g28955 g29312 +11 1 +.names g9507 g28512 g29088 +0- 1 +-0 1 +.names g29088 g28972 g29320 +11 1 +.names g9174 g28540 g29008 +0- 1 +-0 1 +.names g29008 g28979 g29321 +11 1 +.names g9326 g28567 g29068 +0- 1 +-0 1 +.names g29068 g28983 g29323 +11 1 +.names g9649 g28540 g29096 +0- 1 +-0 1 +.names g29096 g29002 g29329 +11 1 +.names g9216 g28567 g29038 +0- 1 +-0 1 +.names g29038 g29010 g29330 +11 1 +.names g9407 g28595 g29080 +0- 1 +-0 1 +.names g29080 g29019 g29332 +11 1 +.names g9232 g28512 g29045 +0- 1 +-0 1 +.names g29045 g29023 g29336 +11 1 +.names g9795 g28567 g29103 +0- 1 +-0 1 +.names g29103 g29032 g29337 +11 1 +.names g9277 g28595 g29060 +0- 1 +-0 1 +.names g29060 g29042 g29338 +11 1 +.names g9310 g28540 g29062 +0- 1 +-0 1 +.names g29062 g29046 g29341 +11 1 +.names g9941 g28595 g29107 +0- 1 +-0 1 +.names g29107 g29054 g29342 +11 1 +.names g9391 g28567 g29076 +0- 1 +-0 1 +.names g29076 g29065 g29344 +11 1 +.names g9488 g28595 g29087 +0- 1 +-0 1 +.names g29087 g29077 g29346 +11 1 +.names g28332 g28334 g29090 +00 1 +.names g29090 g21932 g29411 +11 1 +.names g29190 g8375 g29464 +11 1 +.names g29191 g8424 g29465 +11 1 +.names II38379 II38380 g29265 +0- 1 +-0 1 +.names g8587 g29265 g29466 +11 1 +.names g28337 g28722 g29340 +00 1 +.names g29340 g19467 g29467 +11 1 +.names g28338 g28724 g29343 +00 1 +.names g29343 g19490 g29468 +11 1 +.names g28339 g28726 g29345 +00 1 +.names g29345 g19511 g29469 +11 1 +.names g28340 g28729 g29347 +00 1 +.names g29347 g19530 g29470 +11 1 +.names g21461 g29266 g29471 +11 1 +.names g21461 g29268 g29472 +11 1 +.names g21508 g29269 g29473 +11 1 +.names g21508 g29271 g29474 +11 1 +.names g21544 g29272 g29475 +11 1 +.names g21544 g29274 g29476 +11 1 +.names g21580 g29275 g29477 +11 1 +.names g21580 g29277 g29478 +11 1 +.names g21461 g29280 g29479 +11 1 +.names g21461 g29282 g29480 +11 1 +.names g21508 g29283 g29481 +11 1 +.names g21461 g29285 g29482 +11 1 +.names g21508 g29286 g29483 +11 1 +.names g21544 g29287 g29484 +11 1 +.names g21508 g29290 g29485 +11 1 +.names g21544 g29291 g29486 +11 1 +.names g21580 g29292 g29487 +11 1 +.names g21544 g29295 g29488 +11 1 +.names g21580 g29296 g29489 +11 1 +.names g21580 g29301 g29490 +11 1 +.names g29350 g8912 g29502 +11 1 +.names g28422 g27904 g28728 +00 1 +.names g28728 g29360 g29518 +11 1 +.names g28423 g27908 g28731 +00 1 +.names g28731 g29361 g29520 +11 1 +.names g28424 g27909 g28733 +00 1 +.names g28733 g29362 g29521 +11 1 +.names g27394 g26961 g27735 +00 1 +.names g27735 g29363 g29522 +11 1 +.names g28428 g27914 g28737 +00 1 +.names g28737 g29364 g29523 +11 1 +.names g28429 g27915 g28739 +00 1 +.names g28739 g29365 g29524 +11 1 +.names g28880 g28438 g29195 +00 1 +.names g29195 g29366 g29525 +11 1 +.names g27407 g26966 g27741 +00 1 +.names g27741 g29367 g29526 +11 1 +.names g28435 g27924 g28748 +00 1 +.names g28748 g29368 g29527 +11 1 +.names g28436 g27926 g28750 +00 1 +.names g28750 g29369 g29528 +11 1 +.names g28892 g28448 g29199 +00 1 +.names g29199 g29370 g29529 +11 1 +.names g28897 g28450 g29202 +00 1 +.names g29202 g29371 g29531 +11 1 +.names g27425 g26972 g27746 +00 1 +.names g27746 g29372 g29532 +11 1 +.names g28446 g27938 g28762 +00 1 +.names g28762 g29373 g29533 +11 1 +.names g28909 g28459 g29206 +00 1 +.names g29206 g29374 g29534 +11 1 +.names g28914 g28460 g29207 +00 1 +.names g29207 g29375 g29536 +11 1 +.names g28919 g28462 g29210 +00 1 +.names g29210 g29376 g29538 +11 1 +.names g27446 g26985 g27754 +00 1 +.names g27754 g29377 g29539 +11 1 +.names g25475 g24855 g26041 +00 1 +.names g26041 g29378 g29540 +11 1 +.names g28931 g28469 g29214 +00 1 +.names g29214 g29379 g29541 +11 1 +.names g28935 g28471 g29215 +00 1 +.names g29215 g29380 g29543 +11 1 +.names g28940 g28472 g29216 +00 1 +.names g29216 g29381 g29545 +11 1 +.names g28948 g28474 g29219 +00 1 +.names g29219 g29382 g29547 +11 1 +.names g28468 g27970 g28784 +00 1 +.names g28784 g29383 g29548 +11 1 +.names g25506 g24870 g26043 +00 1 +.names g26043 g29384 g29549 +11 1 +.names g28958 g28479 g29222 +00 1 +.names g29222 g29385 g29550 +11 1 +.names g28962 g28480 g29223 +00 1 +.names g29223 g29386 g29553 +11 1 +.names g28970 g28481 g29224 +00 1 +.names g29224 g29387 g29555 +11 1 +.names g28477 g27985 g28789 +00 1 +.names g28789 g29388 g29557 +11 1 +.names g28478 g27991 g28790 +00 1 +.names g28790 g29389 g29558 +11 1 +.names g25553 g24885 g26045 +00 1 +.names g26045 g29390 g29559 +11 1 +.names g28986 g28486 g29227 +00 1 +.names g29227 g29391 g29560 +11 1 +.names g28996 g28487 g29228 +00 1 +.names g29228 g29392 g29562 +11 1 +.names g28484 g28009 g28794 +00 1 +.names g28794 g29393 g29564 +11 1 +.names g28485 g28015 g28795 +00 1 +.names g28795 g29394 g29565 +11 1 +.names g25619 g24902 g26047 +00 1 +.names g26047 g29395 g29566 +11 1 +.names g29022 g28494 g29231 +00 1 +.names g29231 g29396 g29567 +11 1 +.names g28492 g28036 g28802 +00 1 +.names g28802 g29397 g29572 +11 1 +.names g28493 g28042 g28803 +00 1 +.names g28803 g29398 g29573 +11 1 +.names g28497 g28066 g28813 +00 1 +.names g28813 g29402 g29575 +11 1 +.names g29193 g11056 g29607 +11 1 +.names g29349 g11123 g29610 +11 1 +.names g29359 g11182 g29614 +11 1 +.names g29245 g11185 g29615 +11 1 +.names g29247 g11259 g29619 +11 1 +.names g29250 g11327 g29622 +11 1 +.names g29254 g11407 g29624 +11 1 +.names g29189 g11472 g29625 +11 1 +.names g29318 g11478 g29626 +11 1 +.names g29491 g10918 g29790 +11 1 +.names g29491 g10977 g29792 +11 1 +.names g29491 g11063 g29793 +11 1 +.names g6104 g29583 g25363 g29748 +000 1 +.names g29748 g22248 g29810 +11 1 +.names g29583 g1917 g29703 +00 1 +.names g29703 g20644 g29811 +11 1 +.names g16432 g29625 g29762 +00 1 +.names g29762 g12223 g29812 +11 1 +.names g16411 g29624 g29760 +00 1 +.names g29760 g13869 g29813 +11 1 +.names g6104 g29583 g25401 g29728 +000 1 +.names g29728 g22266 g29814 +11 1 +.names g29583 g1912 g29727 +00 1 +.names g29727 g20662 g29815 +11 1 +.names g16379 g29622 g29759 +00 1 +.names g29759 g13883 g29816 +11 1 +.names g29583 g1909 g29709 +00 1 +.names g29709 g20694 g29817 +11 1 +.names g6104 g29583 g25387 g29732 +000 1 +.names g29732 g22293 g29818 +11 1 +.names g6104 g29583 g25352 g29751 +000 1 +.names g29751 g22294 g29819 +11 1 +.names g29583 g1910 g29717 +00 1 +.names g29717 g20743 g29820 +11 1 +.names g29583 g1913 g29731 +00 1 +.names g29731 g20746 g29821 +11 1 +.names g6104 g29583 g25339 g29705 +000 1 +.names g29705 g22335 g29822 +11 1 +.names g6104 g29583 g25376 g29741 +000 1 +.names g29741 g22356 g29827 +11 1 +.names g29583 g1914 g29740 +00 1 +.names g29740 g20802 g29828 +11 1 +.names g29583 g1911 g29725 +00 1 +.names g29725 g20813 g29833 +11 1 +.names g6104 g29583 g25332 g29713 +000 1 +.names g29713 g22366 g29834 +11 1 +.names g29583 g1916 g29747 +00 1 +.names g29747 g20827 g29839 +11 1 +.names g23797 g29583 g29735 +00 1 +.names g29735 g19420 g19401 g29909 +111 1 +.names g13943 g29502 g29779 +00 1 +.names g29779 g9961 g29910 +11 1 +.names g29472 g29200 g29771 +00 1 +.names g29771 g28877 g29942 +11 1 +.names g29482 g29234 g29782 +00 1 +.names g29782 g28889 g29944 +11 1 +.names g29474 g29208 g29773 +00 1 +.names g29773 g28894 g29945 +11 1 +.names g29479 g29229 g29778 +00 1 +.names g29778 g28906 g29946 +11 1 +.names g29485 g29238 g29785 +00 1 +.names g29785 g28911 g29947 +11 1 +.names g29476 g29217 g29775 +00 1 +.names g29775 g28916 g29948 +11 1 +.names g29481 g29233 g29781 +00 1 +.names g29781 g28932 g29949 +11 1 +.names g29488 g29241 g29788 +00 1 +.names g29788 g28937 g29950 +11 1 +.names g29478 g29225 g29777 +00 1 +.names g29777 g28945 g29951 +11 1 +.names g29484 g29236 g29784 +00 1 +.names g29784 g28959 g29952 +11 1 +.names g29490 g29243 g29791 +00 1 +.names g29791 g28967 g29953 +11 1 +.names g29471 g29196 g29770 +00 1 +.names g29770 g28975 g29954 +11 1 +.names g29487 g29240 g29787 +00 1 +.names g29787 g28993 g29955 +11 1 +.names g29480 g29232 g29780 +00 1 +.names g29780 g28998 g29956 +11 1 +.names g29473 g29203 g29772 +00 1 +.names g29772 g29005 g29957 +11 1 +.names g29483 g29235 g29783 +00 1 +.names g29783 g29027 g29958 +11 1 +.names g29475 g29211 g29774 +00 1 +.names g29774 g29035 g29959 +11 1 +.names g29486 g29239 g29786 +00 1 +.names g29786 g29050 g29960 +11 1 +.names g29477 g29220 g29776 +00 1 +.names g29776 g29057 g29961 +11 1 +.names g29489 g29242 g29789 +00 1 +.names g29789 g29069 g29962 +11 1 +.names g16335 g29619 g29758 +00 1 +.names g29758 g13737 g29963 +11 1 +.names g16285 g29615 g29757 +00 1 +.names g29757 g13786 g29964 +11 1 +.names g16284 g29614 g29756 +00 1 +.names g29756 g11961 g29965 +11 1 +.names g16229 g29610 g29755 +00 1 +.names g29755 g12004 g29966 +11 1 +.names g16178 g29607 g29754 +00 1 +.names g29754 g12066 g29967 +11 1 +.names g13492 g29465 g29765 +00 1 +.names g29765 g12119 g29968 +11 1 +.names g6104 g29583 g25323 g29721 +000 1 +.names g29721 g22237 g29969 +11 1 +.names g16462 g29464 g29764 +00 1 +.names g29764 g12178 g29970 +11 1 +.names g16438 g29626 g29763 +00 1 +.names g29763 g13861 g29971 +11 1 +.names g29881 g8324 g29980 +11 1 +.names g29869 g8330 g29981 +11 1 +.names g29893 g8336 g29982 +11 1 +.names g29885 g8344 g29983 +11 1 +.names g29873 g8351 g29984 +11 1 +.names g29897 g8363 g29985 +11 1 +.names g29877 g8366 g29986 +11 1 +.names g29889 g8369 g29987 +11 1 +.names g29881 g8382 g29988 +11 1 +.names g29893 g8391 g29989 +11 1 +.names g29885 g8397 g29990 +11 1 +.names g29901 g8403 g29991 +11 1 +.names g8594 g10767 g12441 +00 1 +.names g12441 g29909 g29992 +11 1 +.names g29897 g8411 g29993 +11 1 +.names g29889 g8418 g29994 +11 1 +.names g29893 g8434 g29995 +11 1 +.names g29901 g8443 g29996 +11 1 +.names g29744 g22367 g29918 +00 1 +.names g29918 g22277 g29997 +11 1 +.names g29744 g22367 g29922 +00 1 +.names g29922 g22278 g29998 +11 1 +.names g29710 g22367 g29924 +00 1 +.names g29924 g22279 g29999 +11 1 +.names II39385 II39386 g29930 +0- 1 +-0 1 +.names g10767 g29930 g30000 +11 1 +.names g29897 g8449 g30001 +11 1 +.names g29905 g8455 g30002 +11 1 +.names g29901 g8469 g30003 +11 1 +.names g29718 g22367 g29926 +00 1 +.names g29926 g22295 g30004 +11 1 +.names g29905 g8478 g30005 +11 1 +.names g29673 g22367 g29928 +00 1 +.names g29928 g22310 g30006 +11 1 +.names g29905 g8494 g30007 +11 1 +.names g29736 g22367 g29919 +00 1 +.names g29919 g22334 g30008 +11 1 +.names g29673 g22367 g29929 +00 1 +.names g29929 g22357 g30009 +11 1 +.names g29823 g10963 g30077 +11 1 +.names g29823 g10988 g30079 +11 1 +.names g29829 g10996 g30080 +11 1 +.names g29823 g11022 g30081 +11 1 +.names g29829 g11036 g30082 +11 1 +.names g29835 g11048 g30083 +11 1 +.names g29829 g11092 g30085 +11 1 +.names g29835 g11108 g30086 +11 1 +.names g29840 g11120 g30087 +11 1 +.names g29844 g11138 g30088 +11 1 +.names g29835 g11160 g30089 +11 1 +.names g29840 g11176 g30090 +11 1 +.names g29844 g11202 g30091 +11 1 +.names g29849 g11205 g30092 +11 1 +.names g29853 g11222 g30093 +11 1 +.names g29840 g11246 g30094 +11 1 +.names g29857 g11265 g30095 +11 1 +.names g29844 g11268 g30096 +11 1 +.names g29849 g11271 g30097 +11 1 +.names g29853 g11284 g30098 +11 1 +.names g29861 g11287 g30099 +11 1 +.names g29865 g11306 g30100 +11 1 +.names g29857 g11341 g30101 +11 1 +.names g29849 g11348 g30102 +11 1 +.names g29869 g11358 g30103 +11 1 +.names g29853 g11361 g30104 +11 1 +.names g29861 g11364 g30105 +11 1 +.names g29865 g11379 g30106 +11 1 +.names g29873 g11382 g30107 +11 1 +.names g29877 g11401 g30108 +11 1 +.names g29857 g11411 g30109 +11 1 +.names g29881 g11417 g30110 +11 1 +.names g29869 g11425 g30111 +11 1 +.names g29861 g11432 g30112 +11 1 +.names g29885 g11444 g30113 +11 1 +.names g29865 g11447 g30114 +11 1 +.names g29873 g11450 g30115 +11 1 +.names g29736 g22367 g29921 +00 1 +.names g29921 g22236 g30116 +11 1 +.names g29877 g11465 g30117 +11 1 +.names g29889 g11468 g30118 +11 1 +.names g29827 g29833 g30070 +00 1 +.names g30070 g20641 g30123 +11 1 +.names g29814 g29817 g30065 +00 1 +.names g30065 g20719 g30127 +11 1 +.names g29810 g29815 g30062 +00 1 +.names g30062 g20722 g30128 +11 1 +.names g29834 g29839 g30071 +00 1 +.names g30071 g20725 g30129 +11 1 +.names g29969 g29811 g30059 +00 1 +.names g30059 g20749 g30131 +11 1 +.names g29819 g29821 g30068 +00 1 +.names g30068 g20776 g30132 +11 1 +.names g29818 g29820 g30067 +00 1 +.names g30067 g20799 g30133 +11 1 +.names g29822 g29828 g30069 +00 1 +.names g30069 g20816 g30138 +11 1 +.names g30036 g8921 g30216 +11 1 +.names g30036 g8955 g30217 +11 1 +.names g30040 g8961 g30218 +11 1 +.names g30036 g8980 g30219 +11 1 +.names g30040 g8987 g30220 +11 1 +.names g30044 g8993 g30221 +11 1 +.names g30040 g9010 g30222 +11 1 +.names g30044 g9016 g30223 +11 1 +.names g30048 g9022 g30224 +11 1 +.names g30044 g9035 g30225 +11 1 +.names g30048 g9041 g30226 +11 1 +.names g30048 g9058 g30227 +11 1 +.names g30187 g8321 g30327 +11 1 +.names g30195 g8333 g30330 +11 1 +.names g30191 g8341 g30333 +11 1 +.names g30203 g8347 g30334 +11 1 +.names g30199 g8354 g30337 +11 1 +.names g30207 g8372 g30340 +11 1 +.names g30195 g8388 g30345 +11 1 +.names g30203 g8400 g30348 +11 1 +.names g30199 g8408 g30351 +11 1 +.names g30211 g8414 g30352 +11 1 +.names g30207 g8421 g30355 +11 1 +.names g30203 g8440 g30361 +11 1 +.names g30211 g8452 g30364 +11 1 +.names g30207 g8460 g30367 +11 1 +.names II39690 II39691 g30228 +0- 1 +-0 1 +.names g8594 g30228 g30372 +11 1 +.names g30211 g8475 g30374 +11 1 +.names g30229 g8888 g30387 +11 1 +.names g30229 g8918 g30388 +11 1 +.names g30233 g8928 g30389 +11 1 +.names g30229 g8952 g30390 +11 1 +.names g30233 g8958 g30391 +11 1 +.names g30237 g8968 g30392 +11 1 +.names g30233 g8984 g30393 +11 1 +.names g30237 g8990 g30394 +11 1 +.names g30241 g9000 g30395 +11 1 +.names g30237 g9013 g30396 +11 1 +.names g30241 g9019 g30397 +11 1 +.names g30241 g9038 g30398 +11 1 +.names g30134 g10991 g30407 +11 1 +.names g30134 g11025 g30409 +11 1 +.names g30139 g11028 g30410 +11 1 +.names g30143 g11039 g30411 +11 1 +.names g30134 g11079 g30436 +11 1 +.names g30139 g11082 g30437 +11 1 +.names g30147 g11085 g30438 +11 1 +.names g30143 g11095 g30440 +11 1 +.names g30151 g11098 g30441 +11 1 +.names g30155 g11111 g30442 +11 1 +.names g30139 g11132 g30444 +11 1 +.names g30147 g11135 g30445 +11 1 +.names g30143 g11145 g30447 +11 1 +.names g30151 g11148 g30448 +11 1 +.names g30159 g11151 g30449 +11 1 +.names g30155 g11163 g30451 +11 1 +.names g30163 g11166 g30452 +11 1 +.names g30167 g11179 g30453 +11 1 +.names g30147 g11199 g30454 +11 1 +.names g30151 g11216 g30457 +11 1 +.names g30159 g11219 g30458 +11 1 +.names g30155 g11231 g30460 +11 1 +.names g30163 g11234 g30461 +11 1 +.names g30171 g11237 g30462 +11 1 +.names g30167 g11249 g30464 +11 1 +.names g30175 g11252 g30465 +11 1 +.names g30179 g11274 g30467 +11 1 +.names g30159 g11281 g30469 +11 1 +.names g30163 g11300 g30472 +11 1 +.names g30171 g11303 g30473 +11 1 +.names g30167 g11315 g30475 +11 1 +.names g30175 g11318 g30476 +11 1 +.names g30183 g11321 g30477 +11 1 +.names g30187 g11344 g30478 +11 1 +.names g30179 g11351 g30481 +11 1 +.names g30191 g11367 g30484 +11 1 +.names g30171 g11376 g30486 +11 1 +.names g30175 g11395 g30489 +11 1 +.names g30183 g11398 g30490 +11 1 +.names g30187 g11414 g30492 +11 1 +.names g30179 g11422 g30495 +11 1 +.names g30195 g11428 g30496 +11 1 +.names g30191 g11435 g30499 +11 1 +.names g30199 g11453 g30502 +11 1 +.names g30183 g11462 g30504 +11 1 +.names g30383 g10943 g30696 +11 1 +.names g30383 g11011 g30697 +11 1 +.names g30383 g11126 g30698 +11 1 +.names g6119 g30412 g25333 g30605 +000 1 +.names g30605 g22252 g30728 +11 1 +.names g6119 g30412 g25378 g30629 +000 1 +.names g30629 g22268 g30735 +11 1 +.names g30412 g2611 g30584 +00 1 +.names g30584 g20669 g30736 +11 1 +.names g6119 g30412 g25411 g30610 +000 1 +.names g30610 g22283 g30743 +11 1 +.names g30412 g2606 g30609 +00 1 +.names g30609 g20697 g30744 +11 1 +.names g30412 g2603 g30593 +00 1 +.names g30593 g20729 g30750 +11 1 +.names g6119 g30412 g25403 g30614 +000 1 +.names g30614 g22313 g30754 +11 1 +.names g6119 g30412 g25366 g30632 +000 1 +.names g30632 g22314 g30755 +11 1 +.names g30412 g2604 g30601 +00 1 +.names g30601 g20780 g30757 +11 1 +.names g30412 g2607 g30613 +00 1 +.names g30613 g20783 g30758 +11 1 +.names g6119 g30412 g25353 g30588 +000 1 +.names g30588 g22360 g30759 +11 1 +.names g6119 g30412 g25393 g30622 +000 1 +.names g30622 g22379 g30760 +11 1 +.names g30412 g2608 g30621 +00 1 +.names g30621 g20822 g30761 +11 1 +.names g30412 g2605 g30608 +00 1 +.names g30608 g20830 g30762 +11 1 +.names g6119 g30412 g25341 g30597 +000 1 +.names g30597 g22386 g30763 +11 1 +.names g30412 g2610 g30628 +00 1 +.names g30628 g20837 g30764 +11 1 +.names g23850 g30412 g30617 +00 1 +.names g30617 g19457 g19431 g30766 +111 1 +.names g30618 g22387 g30785 +00 1 +.names g30785 g22251 g30916 +11 1 +.names g8605 g10773 g12446 +00 1 +.names g12446 g30766 g30917 +11 1 +.names g30625 g22387 g30780 +00 1 +.names g30780 g22296 g30918 +11 1 +.names g30625 g22387 g30786 +00 1 +.names g30786 g22297 g30919 +11 1 +.names g30594 g22387 g30787 +00 1 +.names g30787 g22298 g30920 +11 1 +.names II40628 II40629 g30791 +0- 1 +-0 1 +.names g10773 g30791 g30921 +11 1 +.names g30602 g22387 g30788 +00 1 +.names g30788 g22315 g30922 +11 1 +.names g30575 g22387 g30789 +00 1 +.names g30789 g22338 g30923 +11 1 +.names g30618 g22387 g30783 +00 1 +.names g30783 g22359 g30924 +11 1 +.names g30575 g22387 g30790 +00 1 +.names g30790 g22380 g30925 +11 1 +.names g30760 g30762 g30935 +00 1 +.names g30935 g20666 g30944 +11 1 +.names g30743 g30750 g30931 +00 1 +.names g30931 g20754 g30945 +11 1 +.names g30735 g30744 g30930 +00 1 +.names g30930 g20757 g30946 +11 1 +.names g30763 g30764 g30936 +00 1 +.names g30936 g20760 g30947 +11 1 +.names g30728 g30736 g30929 +00 1 +.names g30929 g20786 g30948 +11 1 +.names g30755 g30758 g30933 +00 1 +.names g30933 g20806 g30949 +11 1 +.names g30754 g30757 g30932 +00 1 +.names g30932 g20819 g30950 +11 1 +.names g30759 g30761 g30934 +00 1 +.names g30934 g20833 g30951 +11 1 +.names II41065 II41066 g30952 +0- 1 +-0 1 +.names g8605 g30952 g30953 +11 1 +.names g2986 g5389 g9144 +1- 1 +-1 1 +.names g2929 g8022 g10778 +1- 1 +-1 1 +.names g7553 g11059 g12377 +1- 1 +-1 1 +.names g7573 g10779 g12407 +1- 1 +-1 1 +.names g9534 g3398 g12886 +1- 1 +-1 1 +.names g9676 g3554 g12926 +1- 1 +-1 1 +.names g9822 g3710 g12955 +1- 1 +-1 1 +.names g9968 g3866 g12984 +1- 1 +-1 1 +.names g15880 g14657 g16539 +1- 1 +-1 1 +.names g15913 g14691 g16571 +1- 1 +-1 1 +.names g15942 g14725 g16595 +1- 1 +-1 1 +.names g15971 g14753 g16615 +1- 1 +-1 1 +.names II23807 II23808 g17729 +0- 1 +-0 1 +.names II24016 II24017 g17979 +0- 1 +-0 1 +.names g17729 g17979 g19181 +1- 1 +-1 1 +.names II24437 II24438 g18419 +0- 1 +-0 1 +.names II23942 II23943 g17887 +0- 1 +-0 1 +.names g18419 g17887 g19186 +1- 1 +-1 1 +.names g18419 g17729 g19187 +1- 1 +-1 1 +.names II23894 II23895 g17830 +0- 1 +-0 1 +.names II24111 II24112 g18096 +0- 1 +-0 1 +.names g17830 g18096 g19188 +1- 1 +-1 1 +.names II23879 II23880 g17807 +0- 1 +-0 1 +.names g17807 g17887 g19191 +1- 1 +-1 1 +.names II24179 II24180 g18183 +0- 1 +-0 1 +.names II24264 II24265 g18270 +0- 1 +-0 1 +.names g18183 g18270 g19192 +1- 1 +-1 1 +.names II24538 II24539 g18492 +0- 1 +-0 1 +.names II24037 II24038 g17998 +0- 1 +-0 1 +.names g18492 g17998 g19193 +1- 1 +-1 1 +.names g18492 g17830 g19194 +1- 1 +-1 1 +.names II23982 II23983 g17942 +0- 1 +-0 1 +.names II24214 II24215 g18212 +0- 1 +-0 1 +.names g17942 g18212 g19195 +1- 1 +-1 1 +.names II24352 II24353 g18346 +0- 1 +-0 1 +.names II24444 II24445 g18424 +0- 1 +-0 1 +.names g18346 g18424 g19200 +1- 1 +-1 1 +.names g18183 g18424 g19201 +1- 1 +-1 1 +.names II23967 II23968 g17919 +0- 1 +-0 1 +.names g17919 g17998 g19202 +1- 1 +-1 1 +.names II24291 II24292 g18290 +0- 1 +-0 1 +.names II24373 II24374 g18363 +0- 1 +-0 1 +.names g18290 g18363 g19203 +1- 1 +-1 1 +.names II24640 II24641 g18556 +0- 1 +-0 1 +.names II24132 II24133 g18115 +0- 1 +-0 1 +.names g18556 g18115 g19204 +1- 1 +-1 1 +.names g18556 g17942 g19205 +1- 1 +-1 1 +.names II24077 II24078 g18053 +0- 1 +-0 1 +.names II24326 II24327 g18319 +0- 1 +-0 1 +.names g18053 g18319 g19206 +1- 1 +-1 1 +.names II24092 II24093 g18079 +0- 1 +-0 1 +.names g18079 g18346 g19209 +1- 1 +-1 1 +.names g18079 g18183 g19210 +1- 1 +-1 1 +.names II24465 II24466 g18441 +0- 1 +-0 1 +.names II24545 II24546 g18497 +0- 1 +-0 1 +.names g18441 g18497 g19211 +1- 1 +-1 1 +.names g18290 g18497 g19212 +1- 1 +-1 1 +.names II24062 II24063 g18030 +0- 1 +-0 1 +.names g18030 g18115 g19213 +1- 1 +-1 1 +.names II24400 II24401 g18383 +0- 1 +-0 1 +.names II24486 II24487 g18458 +0- 1 +-0 1 +.names g18383 g18458 g19214 +1- 1 +-1 1 +.names II24710 II24711 g18606 +0- 1 +-0 1 +.names II24235 II24236 g18231 +0- 1 +-0 1 +.names g18606 g18231 g19215 +1- 1 +-1 1 +.names g18606 g18053 g19216 +1- 1 +-1 1 +.names g18270 g18346 g19221 +1- 1 +-1 1 +.names II24195 II24196 g18195 +0- 1 +-0 1 +.names g18195 g18441 g19222 +1- 1 +-1 1 +.names g18195 g18290 g19223 +1- 1 +-1 1 +.names II24566 II24567 g18514 +0- 1 +-0 1 +.names II24647 II24648 g18561 +0- 1 +-0 1 +.names g18514 g18561 g19224 +1- 1 +-1 1 +.names g18383 g18561 g19225 +1- 1 +-1 1 +.names II24157 II24158 g18147 +0- 1 +-0 1 +.names g18147 g18231 g19226 +1- 1 +-1 1 +.names II24513 II24514 g18478 +0- 1 +-0 1 +.names II24587 II24588 g18531 +0- 1 +-0 1 +.names g18478 g18531 g19227 +1- 1 +-1 1 +.names II22999 II23000 g17024 +0- 1 +-0 1 +.names II22963 II22964 g17000 +0- 1 +-0 1 +.names II22937 II22938 g16992 +0- 1 +-0 1 +.names g17024 g17000 g16992 II25477 +1-- 1 +-1- 1 +--1 1 +.names II22918 II22919 g16985 +0- 1 +-0 1 +.names II22901 II22902 g16965 +0- 1 +-0 1 +.names g16985 g16965 II25477 g19230 +1-- 1 +-1- 1 +--1 1 +.names g18363 g18441 g19231 +1- 1 +-1 1 +.names II24307 II24308 g18302 +0- 1 +-0 1 +.names g18302 g18514 g19232 +1- 1 +-1 1 +.names g18302 g18383 g19233 +1- 1 +-1 1 +.names II24668 II24669 g18578 +0- 1 +-0 1 +.names II24717 II24718 g18611 +0- 1 +-0 1 +.names g18578 g18611 g19234 +1- 1 +-1 1 +.names g18478 g18611 g19235 +1- 1 +-1 1 +.names II23191 II23192 g17158 +0- 1 +-0 1 +.names II23153 II23154 g17137 +0- 1 +-0 1 +.names II23114 II23115 g17115 +0- 1 +-0 1 +.names g17158 g17137 g17115 II25495 +1-- 1 +-1- 1 +--1 1 +.names II23075 II23076 g17083 +0- 1 +-0 1 +.names II23035 II23036 g17050 +0- 1 +-0 1 +.names g17083 g17050 II25495 g19240 +1-- 1 +-1- 1 +--1 1 +.names g14244 g16501 g19242 +1- 1 +-1 1 +.names II23046 II23047 g17058 +0- 1 +-0 1 +.names II23009 II23010 g17030 +0- 1 +-0 1 +.names II22973 II22974 g17016 +0- 1 +-0 1 +.names g17058 g17030 g17016 II25500 +1-- 1 +-1- 1 +--1 1 +.names II22946 II22947 g16995 +0- 1 +-0 1 +.names II22925 II22926 g16986 +0- 1 +-0 1 +.names g16995 g16986 II25500 g19243 +1-- 1 +-1- 1 +--1 1 +.names g18458 g18514 g19244 +1- 1 +-1 1 +.names II24416 II24417 g18395 +0- 1 +-0 1 +.names g18395 g18578 g19245 +1- 1 +-1 1 +.names g18395 g18478 g19246 +1- 1 +-1 1 +.names g17729 g17807 g19250 +1- 1 +-1 1 +.names II23226 II23227 g17173 +0- 1 +-0 1 +.names II23199 II23200 g17160 +0- 1 +-0 1 +.names II23162 II23163 g17142 +0- 1 +-0 1 +.names g17173 g17160 g17142 II25516 +1-- 1 +-1- 1 +--1 1 +.names II23124 II23125 g17121 +0- 1 +-0 1 +.names II23083 II23084 g17085 +0- 1 +-0 1 +.names g17121 g17085 II25516 g19253 +1-- 1 +-1- 1 +--1 1 +.names g14366 g16523 g19255 +1- 1 +-1 1 +.names II23094 II23095 g17093 +0- 1 +-0 1 +.names II23056 II23057 g17064 +0- 1 +-0 1 +.names II23019 II23020 g17046 +0- 1 +-0 1 +.names g17093 g17064 g17046 II25521 +1-- 1 +-1- 1 +--1 1 +.names II22982 II22983 g17019 +0- 1 +-0 1 +.names II22953 II22954 g16996 +0- 1 +-0 1 +.names g17019 g16996 II25521 g19256 +1-- 1 +-1- 1 +--1 1 +.names g18531 g18578 g19257 +1- 1 +-1 1 +.names g17887 g17979 g19263 +1- 1 +-1 1 +.names g17830 g17919 g19264 +1- 1 +-1 1 +.names II23257 II23258 g17190 +0- 1 +-0 1 +.names II23234 II23235 g17175 +0- 1 +-0 1 +.names II23208 II23209 g17165 +0- 1 +-0 1 +.names g17190 g17175 g17165 II25549 +1-- 1 +-1- 1 +--1 1 +.names II23172 II23173 g17148 +0- 1 +-0 1 +.names II23132 II23133 g17123 +0- 1 +-0 1 +.names g17148 g17123 II25549 g19266 +1-- 1 +-1- 1 +--1 1 +.names g14478 g16554 g19268 +1- 1 +-1 1 +.names II23143 II23144 g17131 +0- 1 +-0 1 +.names II23104 II23105 g17099 +0- 1 +-0 1 +.names II23066 II23067 g17080 +0- 1 +-0 1 +.names g17131 g17099 g17080 II25554 +1-- 1 +-1- 1 +--1 1 +.names II23028 II23029 g17049 +0- 1 +-0 1 +.names II22989 II22990 g17020 +0- 1 +-0 1 +.names g17049 g17020 II25554 g19269 +1-- 1 +-1- 1 +--1 1 +.names g16867 g16515 g19001 g19275 +1-- 1 +-1- 1 +--1 1 +.names g17998 g18096 g19278 +1- 1 +-1 1 +.names g17942 g18030 g19279 +1- 1 +-1 1 +.names II23278 II23279 g17201 +0- 1 +-0 1 +.names II23265 II23266 g17192 +0- 1 +-0 1 +.names II23243 II23244 g17180 +0- 1 +-0 1 +.names g17201 g17192 g17180 II25588 +1-- 1 +-1- 1 +--1 1 +.names II23218 II23219 g17171 +0- 1 +-0 1 +.names II23180 II23181 g17150 +0- 1 +-0 1 +.names g17171 g17150 II25588 g19281 +1-- 1 +-1- 1 +--1 1 +.names g14565 g16586 g19283 +1- 1 +-1 1 +.names g16895 g16546 g16507 g19294 +1-- 1 +-1- 1 +--1 1 +.names g18115 g18212 g19297 +1- 1 +-1 1 +.names g18053 g18147 g19298 +1- 1 +-1 1 +.names g16924 g16578 g16529 g19312 +1-- 1 +-1- 1 +--1 1 +.names g18231 g18319 g19315 +1- 1 +-1 1 +.names g16954 g16602 g16560 g19333 +1-- 1 +-1- 1 +--1 1 +.names g14837 g16682 g19450 +1- 1 +-1 1 +.names g14910 g16708 g19477 +1- 1 +-1 1 +.names g14991 g16739 g19500 +1- 1 +-1 1 +.names g16884 g16697 g16665 g19503 +1-- 1 +-1- 1 +--1 1 +.names g15080 g16781 g19521 +1- 1 +-1 1 +.names g16913 g16728 g16686 g19522 +1-- 1 +-1- 1 +--1 1 +.names g16943 g16770 g16712 g19532 +1-- 1 +-1- 1 +--1 1 +.names g16974 g16797 g16743 g19542 +1-- 1 +-1- 1 +--1 1 +.names g17979 g17887 g17807 II26429 +1-- 1 +-1- 1 +--1 1 +.names g17729 g18419 II26429 g19981 +1-- 1 +-1- 1 +--1 1 +.names g18424 g18346 g18270 II26455 +1-- 1 +-1- 1 +--1 1 +.names g18183 g18079 II26455 g20015 +1-- 1 +-1- 1 +--1 1 +.names g18096 g17998 g17919 II26461 +1-- 1 +-1- 1 +--1 1 +.names g17830 g18492 II26461 g20019 +1-- 1 +-1- 1 +--1 1 +.names g18497 g18441 g18363 II26491 +1-- 1 +-1- 1 +--1 1 +.names g18290 g18195 II26491 g20057 +1-- 1 +-1- 1 +--1 1 +.names g18212 g18115 g18030 II26497 +1-- 1 +-1- 1 +--1 1 +.names g17942 g18556 II26497 g20061 +1-- 1 +-1- 1 +--1 1 +.names g18561 g18514 g18458 II26532 +1-- 1 +-1- 1 +--1 1 +.names g18383 g18302 II26532 g20098 +1-- 1 +-1- 1 +--1 1 +.names g18319 g18231 g18147 II26538 +1-- 1 +-1- 1 +--1 1 +.names g18053 g18606 II26538 g20102 +1-- 1 +-1- 1 +--1 1 +.names g18611 g18578 g18531 II26571 +1-- 1 +-1- 1 +--1 1 +.names g18478 g18395 II26571 g20123 +1-- 1 +-1- 1 +--1 1 +.names g19484 g16515 g14071 g21120 +1-- 1 +-1- 1 +--1 1 +.names g19505 g16546 g14186 g21139 +1-- 1 +-1- 1 +--1 1 +.names g19524 g16578 g14301 g21159 +1-- 1 +-1- 1 +--1 1 +.names g19534 g16602 g14423 g21179 +1-- 1 +-1- 1 +--1 1 +.names g19578 g16697 g14776 g21244 +1-- 1 +-1- 1 +--1 1 +.names g19608 g16728 g14811 g21253 +1-- 1 +-1- 1 +--1 1 +.names g19641 g16770 g14863 g21261 +1-- 1 +-1- 1 +--1 1 +.names g19681 g16797 g14936 g21269 +1-- 1 +-1- 1 +--1 1 +.names g16501 g16515 g20522 +0- 1 +-0 1 +.names g20522 g16867 g14071 g21501 +1-- 1 +-1- 1 +--1 1 +.names g20522 g19484 g19001 g21536 +1-- 1 +-1- 1 +--1 1 +.names g16523 g16546 g20542 +0- 1 +-0 1 +.names g20542 g16895 g14186 g21540 +1-- 1 +-1- 1 +--1 1 +.names g20542 g19505 g16507 g21572 +1-- 1 +-1- 1 +--1 1 +.names g16554 g16578 g19067 +0- 1 +-0 1 +.names g19067 g16924 g14301 g21576 +1-- 1 +-1- 1 +--1 1 +.names g19067 g19524 g16529 g21605 +1-- 1 +-1- 1 +--1 1 +.names g16586 g16602 g19084 +0- 1 +-0 1 +.names g19084 g16954 g14423 g21609 +1-- 1 +-1- 1 +--1 1 +.names g19084 g19534 g16560 g21634 +1-- 1 +-1- 1 +--1 1 +.names g16682 g16697 g19121 +0- 1 +-0 1 +.names g19121 g16884 g14776 g21774 +1-- 1 +-1- 1 +--1 1 +.names g19121 g19578 g16665 g21787 +1-- 1 +-1- 1 +--1 1 +.names g20197 g20177 g20145 II28305 +1-- 1 +-1- 1 +--1 1 +.names g20117 g20094 II28305 g21788 +1-- 1 +-1- 1 +--1 1 +.names g16708 g16728 g19128 +0- 1 +-0 1 +.names g19128 g16913 g14811 g21789 +1-- 1 +-1- 1 +--1 1 +.names g19092 g19088 g19079 II28318 +1-- 1 +-1- 1 +--1 1 +.names g16505 g20538 g18994 II28318 g21799 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g18665 g20270 g20248 g18647 g21800 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g19128 g19608 g16686 g21801 +1-- 1 +-1- 1 +--1 1 +.names g20227 g20211 g20183 II28323 +1-- 1 +-1- 1 +--1 1 +.names g20147 g20119 II28323 g21802 +1-- 1 +-1- 1 +--1 1 +.names g16739 g16770 g19135 +0- 1 +-0 1 +.names g19135 g16943 g14863 g21803 +1-- 1 +-1- 1 +--1 1 +.names g20116 g20093 g18547 g19097 g21806 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g19099 g19094 g19089 II28330 +1-- 1 +-1- 1 +--1 1 +.names g16527 g19063 g19007 II28330 g21807 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g18688 g20282 g20271 g18650 g21808 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g19135 g19641 g16712 g21809 +1-- 1 +-1- 1 +--1 1 +.names g20254 g20241 g20217 II28335 +1-- 1 +-1- 1 +--1 1 +.names g20185 g20149 II28335 g21810 +1-- 1 +-1- 1 +--1 1 +.names g16781 g16797 g19138 +0- 1 +-0 1 +.names g19138 g16974 g14936 g21811 +1-- 1 +-1- 1 +--1 1 +.names g20146 g20118 g18597 g19104 g21813 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g19106 g19101 g19095 II28341 +1-- 1 +-1- 1 +--1 1 +.names g16558 g19080 g16513 II28341 g21814 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g18717 g20293 g20283 g18654 g21815 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g19138 g19681 g16743 g21816 +1-- 1 +-1- 1 +--1 1 +.names g20277 g20268 g20247 II28346 +1-- 1 +-1- 1 +--1 1 +.names g20219 g20187 II28346 g21817 +1-- 1 +-1- 1 +--1 1 +.names g20184 g20148 g18629 g19109 g21819 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g19111 g19108 g19102 II28351 +1-- 1 +-1- 1 +--1 1 +.names g16590 g19090 g16535 II28351 g21820 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g18753 g20309 g20294 g18668 g21821 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g20218 g20186 g18638 g19116 g21823 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names g20280 g18652 g18649 II28365 +1-- 1 +-1- 1 +--1 1 +.names g20222 g18645 II28365 g21844 +1-- 1 +-1- 1 +--1 1 +.names g20291 g18666 g18653 II28369 +1-- 1 +-1- 1 +--1 1 +.names g20249 g18648 II28369 g21846 +1-- 1 +-1- 1 +--1 1 +.names g20307 g18689 g18667 II28374 +1-- 1 +-1- 1 +--1 1 +.names g20272 g18651 II28374 g21849 +1-- 1 +-1- 1 +--1 1 +.names g20326 g18718 g18690 II28380 +1-- 1 +-1- 1 +--1 1 +.names g20284 g18655 II28380 g21856 +1-- 1 +-1- 1 +--1 1 +.names g16075 g20842 g22175 +1- 1 +-1 1 +.names g16113 g20850 g22190 +1- 1 +-1 1 +.names g16164 g20858 g22199 +1- 1 +-1 1 +.names g16223 g20866 g22205 +1- 1 +-1 1 +.names g499 g8983 g12451 +00 1 +.names g21207 g21266 g21196 g22385 +0-- 1 +-0- 1 +--0 1 +.names g14493 g22385 g23319 +1- 1 +-1 1 +.names g23106 g21906 g23688 +1- 1 +-1 1 +.names g23119 g21920 g23742 +1- 1 +-1 1 +.names g23128 g21938 g23797 +1- 1 +-1 1 +.names g23139 g20647 g23850 +1- 1 +-1 1 +.names g19387 g22401 g24239 +1- 1 +-1 1 +.names g21152 g21241 g21136 g22317 +0-- 1 +-0- 1 +--0 1 +.names g14144 g22317 g24244 +1- 1 +-1 1 +.names g19417 g22402 g24245 +1- 1 +-1 1 +.names g21172 g21249 g21156 g22342 +0-- 1 +-0- 1 +--0 1 +.names g14259 g22342 g24252 +1- 1 +-1 1 +.names g19454 g22403 g24254 +1- 1 +-1 1 +.names g21192 g21258 g21176 g22365 +0-- 1 +-0- 1 +--0 1 +.names g14381 g22365 g24257 +1- 1 +-1 1 +.names g19481 g22404 g24258 +1- 1 +-1 1 +.names g4456 g22985 g23922 +00 1 +.names g23922 g23945 g24965 +1- 1 +-1 1 +.names g4632 g22987 g23954 +00 1 +.names g23954 g23974 g24978 +1- 1 +-1 1 +.names g4809 g22990 g23983 +00 1 +.names g23983 g24004 g24989 +1- 1 +-1 1 +.names g4985 g22997 g24013 +00 1 +.names g24013 g24038 g25000 +1- 1 +-1 1 +.names g24958 g24893 g25183 +1- 1 +-1 1 +.names g24969 g24916 g25186 +1- 1 +-1 1 +.names g24982 g24933 g25190 +1- 1 +-1 1 +.names g24993 g24945 g25195 +1- 1 +-1 1 +.names g4456 g14831 g25078 g25852 +000 1 +.names g25852 g25870 g26320 +1- 1 +-1 1 +.names g4632 g14904 g25082 g25873 +000 1 +.names g25873 g25882 g26367 +1- 1 +-1 1 +.names g4809 g14985 g25091 g25885 +000 1 +.names g25885 g25887 g26410 +1- 1 +-1 1 +.names g4985 g15074 g25099 g25890 +000 1 +.names g25890 g25892 g26451 +1- 1 +-1 1 +.names g25367 g27415 g27738 +0- 1 +-0 1 +.names g25384 g27436 g27743 +0- 1 +-0 1 +.names g25400 g27455 g27751 +0- 1 +-0 1 +.names g25410 g27471 g27756 +0- 1 +-0 1 +.names g2981 g2874 II15167 +0- 1 +-0 1 +.names g2981 II15167 II15168 +0- 1 +-0 1 +.names g2874 II15167 II15169 +0- 1 +-0 1 +.names II15168 II15169 g7855 +0- 1 +-0 1 +.names g2975 g2978 II15183 +0- 1 +-0 1 +.names g2975 II15183 II15184 +0- 1 +-0 1 +.names g2978 II15183 II15185 +0- 1 +-0 1 +.names II15184 II15185 g7875 +0- 1 +-0 1 +.names g2956 g2959 II15190 +0- 1 +-0 1 +.names g2956 II15190 II15191 +0- 1 +-0 1 +.names g2959 II15190 II15192 +0- 1 +-0 1 +.names II15191 II15192 g7876 +0- 1 +-0 1 +.names g2969 g2972 II15204 +0- 1 +-0 1 +.names g2969 II15204 II15205 +0- 1 +-0 1 +.names g2972 II15204 II15206 +0- 1 +-0 1 +.names II15205 II15206 g7895 +0- 1 +-0 1 +.names g2947 g2953 II15211 +0- 1 +-0 1 +.names g2947 II15211 II15212 +0- 1 +-0 1 +.names g2953 II15211 II15213 +0- 1 +-0 1 +.names II15212 II15213 g7896 +0- 1 +-0 1 +.names g2963 g2966 II15237 +0- 1 +-0 1 +.names g2963 II15237 II15238 +0- 1 +-0 1 +.names g2966 II15237 II15239 +0- 1 +-0 1 +.names II15238 II15239 g7922 +0- 1 +-0 1 +.names g2941 g2944 II15244 +0- 1 +-0 1 +.names g2941 II15244 II15245 +0- 1 +-0 1 +.names g2944 II15244 II15246 +0- 1 +-0 1 +.names II15245 II15246 g7923 +0- 1 +-0 1 +.names g2935 g2938 II15276 +0- 1 +-0 1 +.names g2935 II15276 II15277 +0- 1 +-0 1 +.names g2938 II15276 II15278 +0- 1 +-0 1 +.names II15277 II15278 g7970 +0- 1 +-0 1 +.names g4203 g3998 II16879 +0- 1 +-0 1 +.names g4203 II16879 II16880 +0- 1 +-0 1 +.names g3998 II16879 II16881 +0- 1 +-0 1 +.names II16880 II16881 g9883 +0- 1 +-0 1 +.names g4734 g4452 II16965 +0- 1 +-0 1 +.names g4734 II16965 II16966 +0- 1 +-0 1 +.names g4452 II16965 II16967 +0- 1 +-0 1 +.names II16966 II16967 g10003 +0- 1 +-0 1 +.names g6637 g6309 II17059 +0- 1 +-0 1 +.names g6637 II17059 II17060 +0- 1 +-0 1 +.names g6309 II17059 II17061 +0- 1 +-0 1 +.names II17060 II17061 g10095 +0- 1 +-0 1 +.names g7465 g7142 II17149 +0- 1 +-0 1 +.names g7465 II17149 II17150 +0- 1 +-0 1 +.names g7142 II17149 II17151 +0- 1 +-0 1 +.names II17150 II17151 g10185 +0- 1 +-0 1 +.names g7875 g7855 II18106 +0- 1 +-0 1 +.names g7875 II18106 II18107 +0- 1 +-0 1 +.names g7855 II18106 II18108 +0- 1 +-0 1 +.names II18107 II18108 g11188 +0- 1 +-0 1 +.names g3997 g8181 II18113 +0- 1 +-0 1 +.names g3997 II18113 II18114 +0- 1 +-0 1 +.names g8181 II18113 II18115 +0- 1 +-0 1 +.names II18114 II18115 g11189 +0- 1 +-0 1 +.names g7922 g7895 II18190 +0- 1 +-0 1 +.names g7922 II18190 II18191 +0- 1 +-0 1 +.names g7895 II18190 II18192 +0- 1 +-0 1 +.names II18191 II18192 g11262 +0- 1 +-0 1 +.names g7896 g7876 II18197 +0- 1 +-0 1 +.names g7896 II18197 II18198 +0- 1 +-0 1 +.names g7876 II18197 II18199 +0- 1 +-0 1 +.names II18198 II18199 g11263 +0- 1 +-0 1 +.names g7975 g4202 II18204 +0- 1 +-0 1 +.names g7975 II18204 II18205 +0- 1 +-0 1 +.names g4202 II18204 II18206 +0- 1 +-0 1 +.names II18205 II18206 g11264 +0- 1 +-0 1 +.names g7970 g7923 II18280 +0- 1 +-0 1 +.names g7970 II18280 II18281 +0- 1 +-0 1 +.names g7923 II18280 II18282 +0- 1 +-0 1 +.names II18281 II18282 g11330 +0- 1 +-0 1 +.names g8256 g8102 II18287 +0- 1 +-0 1 +.names g8256 II18287 II18288 +0- 1 +-0 1 +.names g8102 II18287 II18289 +0- 1 +-0 1 +.names II18288 II18289 g11331 +0- 1 +-0 1 +.names g4325 g4093 II18368 +0- 1 +-0 1 +.names g4325 II18368 II18369 +0- 1 +-0 1 +.names g4093 II18368 II18370 +0- 1 +-0 1 +.names II18369 II18370 g11410 +0- 1 +-0 1 +.names g11410 g11331 II18799 +0- 1 +-0 1 +.names g11410 II18799 II18800 +0- 1 +-0 1 +.names g11331 II18799 II18801 +0- 1 +-0 1 +.names II18800 II18801 g11621 +0- 1 +-0 1 +.names g10003 g9883 II20031 +0- 1 +-0 1 +.names g10003 II20031 II20032 +0- 1 +-0 1 +.names g9883 II20031 II20033 +0- 1 +-0 1 +.names II20032 II20033 g12988 +0- 1 +-0 1 +.names g10185 g10095 II20048 +0- 1 +-0 1 +.names g10185 II20048 II20049 +0- 1 +-0 1 +.names g10095 II20048 II20050 +0- 1 +-0 1 +.names II20049 II20050 g12999 +0- 1 +-0 1 +.names g11262 g11188 II20429 +0- 1 +-0 1 +.names g11262 II20429 II20430 +0- 1 +-0 1 +.names g11188 II20429 II20431 +0- 1 +-0 1 +.names II20430 II20431 g13348 +0- 1 +-0 1 +.names g11330 g11263 II20465 +0- 1 +-0 1 +.names g11330 II20465 II20466 +0- 1 +-0 1 +.names g11263 II20465 II20467 +0- 1 +-0 1 +.names II20466 II20467 g13370 +0- 1 +-0 1 +.names g11264 g11189 II20504 +0- 1 +-0 1 +.names g11264 II20504 II20505 +0- 1 +-0 1 +.names g11189 II20504 II20506 +0- 1 +-0 1 +.names II20505 II20506 g13399 +0- 1 +-0 1 +.names g11621 g13399 II20743 +0- 1 +-0 1 +.names g11621 II20743 II20744 +0- 1 +-0 1 +.names g13399 II20743 II20745 +0- 1 +-0 1 +.names II20744 II20745 g13507 +0- 1 +-0 1 +.names g8580 g12463 g13893 +0- 1 +-0 1 +.names g8822 g12473 g12463 g13915 +0-- 1 +-0- 1 +--0 1 +.names g8587 g12478 g13934 +0- 1 +-0 1 +.names g10730 g12473 g13957 +0- 1 +-0 1 +.names g8846 g12490 g12478 g13971 +0-- 1 +-0- 1 +--0 1 +.names g8594 g12495 g13990 +0- 1 +-0 1 +.names g10749 g12490 g14027 +0- 1 +-0 1 +.names g8873 g12510 g12495 g14041 +0-- 1 +-0- 1 +--0 1 +.names g8605 g12515 g14060 +0- 1 +-0 1 +.names g10767 g12510 g14118 +0- 1 +-0 1 +.names g8911 g12527 g12515 g14132 +0-- 1 +-0- 1 +--0 1 +.names g10773 g12527 g14233 +0- 1 +-0 1 +.names g9187 g9161 g12780 +00 1 +.names g9248 g9203 g12819 +00 1 +.names g9326 g9264 g12857 +00 1 +.names g11481 g11332 g7928 g11069 g13401 +0000 1 +.names g9407 g9342 g12898 +00 1 +.names g11481 g11332 g11190 g7880 g13286 +0000 1 +.names g8183 g11332 g11190 g7880 g13313 +0000 1 +.names g8183 g11332 g7928 g11069 g11622 +0000 1 +.names g11481 g8045 g11190 g7880 g13332 +0000 1 +.names g11481 g8045 g7928 g11069 g11643 +0000 1 +.names g11481 g11332 g7928 g7880 g13375 +0000 1 +.names g8183 g8045 g7928 g11069 g11660 +0000 1 +.names g12999 g12988 II22062 +0- 1 +-0 1 +.names g12999 II22062 II22063 +0- 1 +-0 1 +.names g12988 II22062 II22064 +0- 1 +-0 1 +.names II22063 II22064 g15814 +0- 1 +-0 1 +.names g11481 g8045 g7928 g7880 g13024 +0000 1 +.names g11481 g11332 g11190 g11069 g13310 +0000 1 +.names g8183 g11332 g11190 g11069 g13331 +0000 1 +.names g11481 g8045 g11190 g11069 g13353 +0000 1 +.names g8183 g8045 g11190 g7880 g13354 +0000 1 +.names g8183 g8045 g11190 g11069 g13374 +0000 1 +.names g8183 g11332 g7928 g7880 g13404 +0000 1 +.names g2962 g13348 II22282 +0- 1 +-0 1 +.names g2962 II22282 II22283 +0- 1 +-0 1 +.names g13348 II22282 II22284 +0- 1 +-0 1 +.names g2934 g13370 II22316 +0- 1 +-0 1 +.names g2934 II22316 II22317 +0- 1 +-0 1 +.names g13370 II22316 II22318 +0- 1 +-0 1 +.names g11737 g7152 g15978 +00 1 +.names g13507 g15978 II22630 +0- 1 +-0 1 +.names g13507 II22630 II22631 +0- 1 +-0 1 +.names g15978 II22630 II22632 +0- 1 +-0 1 +.names g11737 g7345 g15661 +00 1 +.names g13348 g15661 II22705 +0- 1 +-0 1 +.names g13348 II22705 II22706 +0- 1 +-0 1 +.names g15661 II22705 II22707 +0- 1 +-0 1 +.names g13370 g15661 II22884 +0- 1 +-0 1 +.names g13370 II22884 II22885 +0- 1 +-0 1 +.names g15661 II22884 II22886 +0- 1 +-0 1 +.names g15022 g14000 II22900 +0- 1 +-0 1 +.names g15022 II22900 II22901 +0- 1 +-0 1 +.names g14000 II22900 II22902 +0- 1 +-0 1 +.names g15096 g13945 II22917 +0- 1 +-0 1 +.names g15096 II22917 II22918 +0- 1 +-0 1 +.names g13945 II22917 II22919 +0- 1 +-0 1 +.names g15118 g14091 II22924 +0- 1 +-0 1 +.names g15118 II22924 II22925 +0- 1 +-0 1 +.names g14091 II22924 II22926 +0- 1 +-0 1 +.names g9150 g13906 II22936 +0- 1 +-0 1 +.names g9150 II22936 II22937 +0- 1 +-0 1 +.names g13906 II22936 II22938 +0- 1 +-0 1 +.names g15188 g14015 II22945 +0- 1 +-0 1 +.names g15188 II22945 II22946 +0- 1 +-0 1 +.names g14015 II22945 II22947 +0- 1 +-0 1 +.names g15210 g14206 II22952 +0- 1 +-0 1 +.names g15210 II22952 II22953 +0- 1 +-0 1 +.names g14206 II22952 II22954 +0- 1 +-0 1 +.names g9161 g13885 II22962 +0- 1 +-0 1 +.names g9161 II22962 II22963 +0- 1 +-0 1 +.names g13885 II22962 II22964 +0- 1 +-0 1 +.names g9174 g13962 II22972 +0- 1 +-0 1 +.names g9174 II22972 II22973 +0- 1 +-0 1 +.names g13962 II22972 II22974 +0- 1 +-0 1 +.names g15274 g14106 II22981 +0- 1 +-0 1 +.names g15274 II22981 II22982 +0- 1 +-0 1 +.names g14106 II22981 II22983 +0- 1 +-0 1 +.names g15296 g14321 II22988 +0- 1 +-0 1 +.names g15296 II22988 II22989 +0- 1 +-0 1 +.names g14321 II22988 II22990 +0- 1 +-0 1 +.names g9187 g13872 II22998 +0- 1 +-0 1 +.names g9187 II22998 II22999 +0- 1 +-0 1 +.names g13872 II22998 II23000 +0- 1 +-0 1 +.names g9203 g13926 II23008 +0- 1 +-0 1 +.names g9203 II23008 II23009 +0- 1 +-0 1 +.names g13926 II23008 II23010 +0- 1 +-0 1 +.names g9216 g14032 II23018 +0- 1 +-0 1 +.names g9216 II23018 II23019 +0- 1 +-0 1 +.names g14032 II23018 II23020 +0- 1 +-0 1 +.names g15366 g14221 II23027 +0- 1 +-0 1 +.names g15366 II23027 II23028 +0- 1 +-0 1 +.names g14221 II23027 II23029 +0- 1 +-0 1 +.names g9232 g13864 II23034 +0- 1 +-0 1 +.names g9232 II23034 II23035 +0- 1 +-0 1 +.names g13864 II23034 II23036 +0- 1 +-0 1 +.names g9248 g13894 II23045 +0- 1 +-0 1 +.names g9248 II23045 II23046 +0- 1 +-0 1 +.names g13894 II23045 II23047 +0- 1 +-0 1 +.names g9264 g13982 II23055 +0- 1 +-0 1 +.names g9264 II23055 II23056 +0- 1 +-0 1 +.names g13982 II23055 II23057 +0- 1 +-0 1 +.names g9277 g14123 II23065 +0- 1 +-0 1 +.names g9277 II23065 II23066 +0- 1 +-0 1 +.names g14123 II23065 II23067 +0- 1 +-0 1 +.names g9293 g13856 II23074 +0- 1 +-0 1 +.names g9293 II23074 II23075 +0- 1 +-0 1 +.names g13856 II23074 II23076 +0- 1 +-0 1 +.names g9310 g13879 II23082 +0- 1 +-0 1 +.names g9310 II23082 II23083 +0- 1 +-0 1 +.names g13879 II23082 II23084 +0- 1 +-0 1 +.names g9326 g13935 II23093 +0- 1 +-0 1 +.names g9326 II23093 II23094 +0- 1 +-0 1 +.names g13935 II23093 II23095 +0- 1 +-0 1 +.names g9342 g14052 II23103 +0- 1 +-0 1 +.names g9342 II23103 II23104 +0- 1 +-0 1 +.names g14052 II23103 II23105 +0- 1 +-0 1 +.names g9356 g13848 II23113 +0- 1 +-0 1 +.names g9356 II23113 II23114 +0- 1 +-0 1 +.names g13848 II23113 II23115 +0- 1 +-0 1 +.names g9374 g13866 II23123 +0- 1 +-0 1 +.names g9374 II23123 II23124 +0- 1 +-0 1 +.names g13866 II23123 II23125 +0- 1 +-0 1 +.names g9391 g13901 II23131 +0- 1 +-0 1 +.names g9391 II23131 II23132 +0- 1 +-0 1 +.names g13901 II23131 II23133 +0- 1 +-0 1 +.names g9407 g13991 II23142 +0- 1 +-0 1 +.names g9407 II23142 II23143 +0- 1 +-0 1 +.names g13991 II23142 II23144 +0- 1 +-0 1 +.names g9427 g14061 II23152 +0- 1 +-0 1 +.names g9427 II23152 II23153 +0- 1 +-0 1 +.names g14061 II23152 II23154 +0- 1 +-0 1 +.names g9453 g13857 II23161 +0- 1 +-0 1 +.names g9453 II23161 II23162 +0- 1 +-0 1 +.names g13857 II23161 II23163 +0- 1 +-0 1 +.names g9471 g13881 II23171 +0- 1 +-0 1 +.names g9471 II23171 II23172 +0- 1 +-0 1 +.names g13881 II23171 II23173 +0- 1 +-0 1 +.names g9488 g13942 II23179 +0- 1 +-0 1 +.names g9488 II23179 II23180 +0- 1 +-0 1 +.names g13942 II23179 II23181 +0- 1 +-0 1 +.names g9507 g13999 II23190 +0- 1 +-0 1 +.names g9507 II23190 II23191 +0- 1 +-0 1 +.names g13999 II23190 II23192 +0- 1 +-0 1 +.names g9569 g14176 II23198 +0- 1 +-0 1 +.names g9569 II23198 II23199 +0- 1 +-0 1 +.names g14176 II23198 II23200 +0- 1 +-0 1 +.names g9595 g13867 II23207 +0- 1 +-0 1 +.names g9595 II23207 II23208 +0- 1 +-0 1 +.names g13867 II23207 II23209 +0- 1 +-0 1 +.names g9613 g13903 II23217 +0- 1 +-0 1 +.names g9613 II23217 II23218 +0- 1 +-0 1 +.names g13903 II23217 II23219 +0- 1 +-0 1 +.names g9649 g14090 II23225 +0- 1 +-0 1 +.names g9649 II23225 II23226 +0- 1 +-0 1 +.names g14090 II23225 II23227 +0- 1 +-0 1 +.names g9711 g14291 II23233 +0- 1 +-0 1 +.names g9711 II23233 II23234 +0- 1 +-0 1 +.names g14291 II23233 II23235 +0- 1 +-0 1 +.names g9737 g13882 II23242 +0- 1 +-0 1 +.names g9737 II23242 II23243 +0- 1 +-0 1 +.names g13882 II23242 II23244 +0- 1 +-0 1 +.names g9795 g14205 II23256 +0- 1 +-0 1 +.names g9795 II23256 II23257 +0- 1 +-0 1 +.names g14205 II23256 II23258 +0- 1 +-0 1 +.names g9857 g14413 II23264 +0- 1 +-0 1 +.names g9857 II23264 II23265 +0- 1 +-0 1 +.names g14413 II23264 II23266 +0- 1 +-0 1 +.names g9941 g14320 II23277 +0- 1 +-0 1 +.names g9941 II23277 II23278 +0- 1 +-0 1 +.names g14320 II23277 II23279 +0- 1 +-0 1 +.names g14062 g9150 II23806 +0- 1 +-0 1 +.names g14062 II23806 II23807 +0- 1 +-0 1 +.names g9150 II23806 II23808 +0- 1 +-0 1 +.names g14001 g9187 II23878 +0- 1 +-0 1 +.names g14001 II23878 II23879 +0- 1 +-0 1 +.names g9187 II23878 II23880 +0- 1 +-0 1 +.names g14177 g9174 II23893 +0- 1 +-0 1 +.names g14177 II23893 II23894 +0- 1 +-0 1 +.names g9174 II23893 II23895 +0- 1 +-0 1 +.names g13946 g9293 II23941 +0- 1 +-0 1 +.names g13946 II23941 II23942 +0- 1 +-0 1 +.names g9293 II23941 II23943 +0- 1 +-0 1 +.names g6513 g14171 II23958 +0- 1 +-0 1 +.names g6513 II23958 II23959 +0- 1 +-0 1 +.names g14171 II23958 II23960 +0- 1 +-0 1 +.names g14092 g9248 II23966 +0- 1 +-0 1 +.names g14092 II23966 II23967 +0- 1 +-0 1 +.names g9248 II23966 II23968 +0- 1 +-0 1 +.names g14292 g9216 II23981 +0- 1 +-0 1 +.names g14292 II23981 II23982 +0- 1 +-0 1 +.names g9216 II23981 II23983 +0- 1 +-0 1 +.names g7548 g15814 II24005 +0- 1 +-0 1 +.names g7548 II24005 II24006 +0- 1 +-0 1 +.names g15814 II24005 II24007 +0- 1 +-0 1 +.names g13907 g9427 II24015 +0- 1 +-0 1 +.names g13907 II24015 II24016 +0- 1 +-0 1 +.names g9427 II24015 II24017 +0- 1 +-0 1 +.names g6201 g14086 II24028 +0- 1 +-0 1 +.names g6201 II24028 II24029 +0- 1 +-0 1 +.names g14086 II24028 II24030 +0- 1 +-0 1 +.names g14016 g9374 II24036 +0- 1 +-0 1 +.names g14016 II24036 II24037 +0- 1 +-0 1 +.names g9374 II24036 II24038 +0- 1 +-0 1 +.names g6777 g14286 II24053 +0- 1 +-0 1 +.names g6777 II24053 II24054 +0- 1 +-0 1 +.names g14286 II24053 II24055 +0- 1 +-0 1 +.names g14207 g9326 II24061 +0- 1 +-0 1 +.names g14207 II24061 II24062 +0- 1 +-0 1 +.names g9326 II24061 II24063 +0- 1 +-0 1 +.names g14414 g9277 II24076 +0- 1 +-0 1 +.names g14414 II24076 II24077 +0- 1 +-0 1 +.names g9277 II24076 II24078 +0- 1 +-0 1 +.names g13886 g15096 II24091 +0- 1 +-0 1 +.names g13886 II24091 II24092 +0- 1 +-0 1 +.names g15096 II24091 II24093 +0- 1 +-0 1 +.names g6363 g14011 II24102 +0- 1 +-0 1 +.names g6363 II24102 II24103 +0- 1 +-0 1 +.names g14011 II24102 II24104 +0- 1 +-0 1 +.names g13963 g9569 II24110 +0- 1 +-0 1 +.names g13963 II24110 II24111 +0- 1 +-0 1 +.names g9569 II24110 II24112 +0- 1 +-0 1 +.names g6290 g14201 II24123 +0- 1 +-0 1 +.names g6290 II24123 II24124 +0- 1 +-0 1 +.names g14201 II24123 II24125 +0- 1 +-0 1 +.names g14107 g9471 II24131 +0- 1 +-0 1 +.names g14107 II24131 II24132 +0- 1 +-0 1 +.names g9471 II24131 II24133 +0- 1 +-0 1 +.names g7079 g14408 II24148 +0- 1 +-0 1 +.names g7079 II24148 II24149 +0- 1 +-0 1 +.names g14408 II24148 II24150 +0- 1 +-0 1 +.names g14322 g9407 II24156 +0- 1 +-0 1 +.names g14322 II24156 II24157 +0- 1 +-0 1 +.names g9407 II24156 II24158 +0- 1 +-0 1 +.names g13873 g9161 II24178 +0- 1 +-0 1 +.names g13873 II24178 II24179 +0- 1 +-0 1 +.names g9161 II24178 II24180 +0- 1 +-0 1 +.names g6177 g13958 II24186 +0- 1 +-0 1 +.names g6177 II24186 II24187 +0- 1 +-0 1 +.names g13958 II24186 II24188 +0- 1 +-0 1 +.names g13927 g15188 II24194 +0- 1 +-0 1 +.names g13927 II24194 II24195 +0- 1 +-0 1 +.names g15188 II24194 II24196 +0- 1 +-0 1 +.names g6568 g14102 II24205 +0- 1 +-0 1 +.names g6568 II24205 II24206 +0- 1 +-0 1 +.names g14102 II24205 II24207 +0- 1 +-0 1 +.names g14033 g9711 II24213 +0- 1 +-0 1 +.names g14033 II24213 II24214 +0- 1 +-0 1 +.names g9711 II24213 II24215 +0- 1 +-0 1 +.names g6427 g14316 II24226 +0- 1 +-0 1 +.names g6427 II24226 II24227 +0- 1 +-0 1 +.names g14316 II24226 II24228 +0- 1 +-0 1 +.names g14222 g9613 II24234 +0- 1 +-0 1 +.names g14222 II24234 II24235 +0- 1 +-0 1 +.names g9613 II24234 II24236 +0- 1 +-0 1 +.names g7329 g14520 II24251 +0- 1 +-0 1 +.names g7329 II24251 II24252 +0- 1 +-0 1 +.names g14520 II24251 II24253 +0- 1 +-0 1 +.names g14342 g9232 II24263 +0- 1 +-0 1 +.names g14342 II24263 II24264 +0- 1 +-0 1 +.names g9232 II24263 II24265 +0- 1 +-0 1 +.names g6180 g13922 II24271 +0- 1 +-0 1 +.names g6180 II24271 II24272 +0- 1 +-0 1 +.names g13922 II24271 II24273 +0- 1 +-0 1 +.names g6284 g13918 II24278 +0- 1 +-0 1 +.names g6284 II24278 II24279 +0- 1 +-0 1 +.names g13918 II24278 II24280 +0- 1 +-0 1 +.names g13895 g9203 II24290 +0- 1 +-0 1 +.names g13895 II24290 II24291 +0- 1 +-0 1 +.names g9203 II24290 II24292 +0- 1 +-0 1 +.names g6209 g14028 II24298 +0- 1 +-0 1 +.names g6209 II24298 II24299 +0- 1 +-0 1 +.names g14028 II24298 II24300 +0- 1 +-0 1 +.names g13983 g15274 II24306 +0- 1 +-0 1 +.names g13983 II24306 II24307 +0- 1 +-0 1 +.names g15274 II24306 II24308 +0- 1 +-0 1 +.names g6832 g14217 II24317 +0- 1 +-0 1 +.names g6832 II24317 II24318 +0- 1 +-0 1 +.names g14217 II24317 II24319 +0- 1 +-0 1 +.names g14124 g9857 II24325 +0- 1 +-0 1 +.names g14124 II24325 II24326 +0- 1 +-0 1 +.names g9857 II24325 II24327 +0- 1 +-0 1 +.names g6632 g14438 II24338 +0- 1 +-0 1 +.names g6632 II24338 II24339 +0- 1 +-0 1 +.names g14438 II24338 II24340 +0- 1 +-0 1 +.names g14238 g9356 II24351 +0- 1 +-0 1 +.names g14238 II24351 II24352 +0- 1 +-0 1 +.names g9356 II24351 II24353 +0- 1 +-0 1 +.names g6157 g14525 II24361 +0- 1 +-0 1 +.names g6157 II24361 II24362 +0- 1 +-0 1 +.names g14525 II24361 II24363 +0- 1 +-0 1 +.names g14454 g9310 II24372 +0- 1 +-0 1 +.names g14454 II24372 II24373 +0- 1 +-0 1 +.names g9310 II24372 II24374 +0- 1 +-0 1 +.names g6212 g13978 II24380 +0- 1 +-0 1 +.names g6212 II24380 II24381 +0- 1 +-0 1 +.names g13978 II24380 II24382 +0- 1 +-0 1 +.names g6421 g13974 II24387 +0- 1 +-0 1 +.names g6421 II24387 II24388 +0- 1 +-0 1 +.names g13974 II24387 II24389 +0- 1 +-0 1 +.names g13936 g9264 II24399 +0- 1 +-0 1 +.names g13936 II24399 II24400 +0- 1 +-0 1 +.names g9264 II24399 II24401 +0- 1 +-0 1 +.names g6298 g14119 II24407 +0- 1 +-0 1 +.names g6298 II24407 II24408 +0- 1 +-0 1 +.names g14119 II24407 II24409 +0- 1 +-0 1 +.names g14053 g15366 II24415 +0- 1 +-0 1 +.names g14053 II24415 II24416 +0- 1 +-0 1 +.names g15366 II24415 II24417 +0- 1 +-0 1 +.names g7134 g14332 II24426 +0- 1 +-0 1 +.names g7134 II24426 II24427 +0- 1 +-0 1 +.names g14332 II24426 II24428 +0- 1 +-0 1 +.names g14153 g15022 II24436 +0- 1 +-0 1 +.names g14153 II24436 II24437 +0- 1 +-0 1 +.names g15022 II24436 II24438 +0- 1 +-0 1 +.names g14148 g9507 II24443 +0- 1 +-0 1 +.names g14148 II24443 II24444 +0- 1 +-0 1 +.names g9507 II24443 II24445 +0- 1 +-0 1 +.names g6142 g14450 II24452 +0- 1 +-0 1 +.names g6142 II24452 II24453 +0- 1 +-0 1 +.names g14450 II24452 II24454 +0- 1 +-0 1 +.names g14360 g9453 II24464 +0- 1 +-0 1 +.names g14360 II24464 II24465 +0- 1 +-0 1 +.names g9453 II24464 II24466 +0- 1 +-0 1 +.names g6184 g14580 II24474 +0- 1 +-0 1 +.names g6184 II24474 II24475 +0- 1 +-0 1 +.names g14580 II24474 II24476 +0- 1 +-0 1 +.names g14541 g9391 II24485 +0- 1 +-0 1 +.names g14541 II24485 II24486 +0- 1 +-0 1 +.names g9391 II24485 II24487 +0- 1 +-0 1 +.names g6301 g14048 II24493 +0- 1 +-0 1 +.names g6301 II24493 II24494 +0- 1 +-0 1 +.names g14048 II24493 II24495 +0- 1 +-0 1 +.names g6626 g14044 II24500 +0- 1 +-0 1 +.names g6626 II24500 II24501 +0- 1 +-0 1 +.names g14044 II24500 II24502 +0- 1 +-0 1 +.names g13992 g9342 II24512 +0- 1 +-0 1 +.names g13992 II24512 II24513 +0- 1 +-0 1 +.names g9342 II24512 II24514 +0- 1 +-0 1 +.names g6435 g14234 II24520 +0- 1 +-0 1 +.names g6435 II24520 II24521 +0- 1 +-0 1 +.names g14234 II24520 II24522 +0- 1 +-0 1 +.names g6707 g14355 II24530 +0- 1 +-0 1 +.names g6707 II24530 II24531 +0- 1 +-0 1 +.names g14355 II24530 II24532 +0- 1 +-0 1 +.names g14268 g15118 II24537 +0- 1 +-0 1 +.names g14268 II24537 II24538 +0- 1 +-0 1 +.names g15118 II24537 II24539 +0- 1 +-0 1 +.names g14263 g9649 II24544 +0- 1 +-0 1 +.names g14263 II24544 II24545 +0- 1 +-0 1 +.names g9649 II24544 II24546 +0- 1 +-0 1 +.names g6163 g14537 II24553 +0- 1 +-0 1 +.names g6163 II24553 II24554 +0- 1 +-0 1 +.names g14537 II24553 II24555 +0- 1 +-0 1 +.names g14472 g9595 II24565 +0- 1 +-0 1 +.names g14472 II24565 II24566 +0- 1 +-0 1 +.names g9595 II24565 II24567 +0- 1 +-0 1 +.names g6216 g14614 II24575 +0- 1 +-0 1 +.names g6216 II24575 II24576 +0- 1 +-0 1 +.names g14614 II24575 II24577 +0- 1 +-0 1 +.names g14596 g9488 II24586 +0- 1 +-0 1 +.names g14596 II24586 II24587 +0- 1 +-0 1 +.names g9488 II24586 II24588 +0- 1 +-0 1 +.names g6438 g14139 II24594 +0- 1 +-0 1 +.names g6438 II24594 II24595 +0- 1 +-0 1 +.names g14139 II24594 II24596 +0- 1 +-0 1 +.names g6890 g14135 II24601 +0- 1 +-0 1 +.names g6890 II24601 II24602 +0- 1 +-0 1 +.names g14135 II24601 II24603 +0- 1 +-0 1 +.names g15814 g15978 II24611 +0- 1 +-0 1 +.names g15814 II24611 II24612 +0- 1 +-0 1 +.names g15978 II24611 II24613 +0- 1 +-0 1 +.names g6136 g14252 II24624 +0- 1 +-0 1 +.names g6136 II24624 II24625 +0- 1 +-0 1 +.names g14252 II24624 II24626 +0- 1 +-0 1 +.names g7009 g14467 II24632 +0- 1 +-0 1 +.names g7009 II24632 II24633 +0- 1 +-0 1 +.names g14467 II24632 II24634 +0- 1 +-0 1 +.names g14390 g15210 II24639 +0- 1 +-0 1 +.names g14390 II24639 II24640 +0- 1 +-0 1 +.names g15210 II24639 II24641 +0- 1 +-0 1 +.names g14385 g9795 II24646 +0- 1 +-0 1 +.names g14385 II24646 II24647 +0- 1 +-0 1 +.names g9795 II24646 II24648 +0- 1 +-0 1 +.names g6190 g14592 II24655 +0- 1 +-0 1 +.names g6190 II24655 II24656 +0- 1 +-0 1 +.names g14592 II24655 II24657 +0- 1 +-0 1 +.names g14559 g9737 II24667 +0- 1 +-0 1 +.names g14559 II24667 II24668 +0- 1 +-0 1 +.names g9737 II24667 II24669 +0- 1 +-0 1 +.names g6305 g14637 II24677 +0- 1 +-0 1 +.names g6305 II24677 II24678 +0- 1 +-0 1 +.names g14637 II24677 II24679 +0- 1 +-0 1 +.names g6146 g14374 II24694 +0- 1 +-0 1 +.names g6146 II24694 II24695 +0- 1 +-0 1 +.names g14374 II24694 II24696 +0- 1 +-0 1 +.names g7259 g14554 II24702 +0- 1 +-0 1 +.names g7259 II24702 II24703 +0- 1 +-0 1 +.names g14554 II24702 II24704 +0- 1 +-0 1 +.names g14502 g15296 II24709 +0- 1 +-0 1 +.names g14502 II24709 II24710 +0- 1 +-0 1 +.names g15296 II24709 II24711 +0- 1 +-0 1 +.names g14497 g9941 II24716 +0- 1 +-0 1 +.names g14497 II24716 II24717 +0- 1 +-0 1 +.names g9941 II24716 II24718 +0- 1 +-0 1 +.names g6222 g14626 II24725 +0- 1 +-0 1 +.names g6222 II24725 II24726 +0- 1 +-0 1 +.names g14626 II24725 II24727 +0- 1 +-0 1 +.names g6167 g14486 II24743 +0- 1 +-0 1 +.names g6167 II24743 II24744 +0- 1 +-0 1 +.names g14486 II24743 II24745 +0- 1 +-0 1 +.names g7455 g14609 II24751 +0- 1 +-0 1 +.names g7455 II24751 II24752 +0- 1 +-0 1 +.names g14609 II24751 II24753 +0- 1 +-0 1 +.names g6194 g14573 II24763 +0- 1 +-0 1 +.names g6194 II24763 II24764 +0- 1 +-0 1 +.names g14573 II24763 II24765 +0- 1 +-0 1 +.names g8029 g13507 II25030 +0- 1 +-0 1 +.names g8029 II25030 II25031 +0- 1 +-0 1 +.names g13507 II25030 II25032 +0- 1 +-0 1 +.names g52 g18179 II25532 +0- 1 +-0 1 +.names g52 II25532 II25533 +0- 1 +-0 1 +.names g18179 II25532 II25534 +0- 1 +-0 1 +.names g92 g18174 II25539 +0- 1 +-0 1 +.names g92 II25539 II25540 +0- 1 +-0 1 +.names g18174 II25539 II25541 +0- 1 +-0 1 +.names g56 g17724 II25560 +0- 1 +-0 1 +.names g56 II25560 II25561 +0- 1 +-0 1 +.names g17724 II25560 II25562 +0- 1 +-0 1 +.names g740 g18286 II25571 +0- 1 +-0 1 +.names g740 II25571 II25572 +0- 1 +-0 1 +.names g18286 II25571 II25573 +0- 1 +-0 1 +.names g780 g18281 II25578 +0- 1 +-0 1 +.names g780 II25578 II25579 +0- 1 +-0 1 +.names g18281 II25578 II25580 +0- 1 +-0 1 +.names g61 g18074 II25595 +0- 1 +-0 1 +.names g61 II25595 II25596 +0- 1 +-0 1 +.names g18074 II25595 II25597 +0- 1 +-0 1 +.names g744 g17825 II25605 +0- 1 +-0 1 +.names g744 II25605 II25606 +0- 1 +-0 1 +.names g17825 II25605 II25607 +0- 1 +-0 1 +.names g1426 g18379 II25616 +0- 1 +-0 1 +.names g1426 II25616 II25617 +0- 1 +-0 1 +.names g18379 II25616 II25618 +0- 1 +-0 1 +.names g1466 g18374 II25623 +0- 1 +-0 1 +.names g1466 II25623 II25624 +0- 1 +-0 1 +.names g18374 II25623 II25625 +0- 1 +-0 1 +.names g65 g17640 II25633 +0- 1 +-0 1 +.names g65 II25633 II25634 +0- 1 +-0 1 +.names g17640 II25633 II25635 +0- 1 +-0 1 +.names g749 g18190 II25643 +0- 1 +-0 1 +.names g749 II25643 II25644 +0- 1 +-0 1 +.names g18190 II25643 II25645 +0- 1 +-0 1 +.names g1430 g17937 II25653 +0- 1 +-0 1 +.names g1430 II25653 II25654 +0- 1 +-0 1 +.names g17937 II25653 II25655 +0- 1 +-0 1 +.names g2120 g18474 II25664 +0- 1 +-0 1 +.names g2120 II25664 II25665 +0- 1 +-0 1 +.names g18474 II25664 II25666 +0- 1 +-0 1 +.names g2160 g18469 II25671 +0- 1 +-0 1 +.names g2160 II25671 II25672 +0- 1 +-0 1 +.names g18469 II25671 II25673 +0- 1 +-0 1 +.names g70 g17974 II25681 +0- 1 +-0 1 +.names g70 II25681 II25682 +0- 1 +-0 1 +.names g17974 II25681 II25683 +0- 1 +-0 1 +.names g753 g17741 II25690 +0- 1 +-0 1 +.names g753 II25690 II25691 +0- 1 +-0 1 +.names g17741 II25690 II25692 +0- 1 +-0 1 +.names g1435 g18297 II25700 +0- 1 +-0 1 +.names g1435 II25700 II25701 +0- 1 +-0 1 +.names g18297 II25700 II25702 +0- 1 +-0 1 +.names g2124 g18048 II25710 +0- 1 +-0 1 +.names g2124 II25710 II25711 +0- 1 +-0 1 +.names g18048 II25710 II25712 +0- 1 +-0 1 +.names g74 g18341 II25721 +0- 1 +-0 1 +.names g74 II25721 II25722 +0- 1 +-0 1 +.names g18341 II25721 II25723 +0- 1 +-0 1 +.names g758 g18091 II25731 +0- 1 +-0 1 +.names g758 II25731 II25732 +0- 1 +-0 1 +.names g18091 II25731 II25733 +0- 1 +-0 1 +.names g1439 g17842 II25740 +0- 1 +-0 1 +.names g1439 II25740 II25741 +0- 1 +-0 1 +.names g17842 II25740 II25742 +0- 1 +-0 1 +.names g2129 g18390 II25750 +0- 1 +-0 1 +.names g2129 II25750 II25751 +0- 1 +-0 1 +.names g18390 II25750 II25752 +0- 1 +-0 1 +.names g79 g17882 II25761 +0- 1 +-0 1 +.names g79 II25761 II25762 +0- 1 +-0 1 +.names g17882 II25761 II25763 +0- 1 +-0 1 +.names g762 g18436 II25771 +0- 1 +-0 1 +.names g762 II25771 II25772 +0- 1 +-0 1 +.names g18436 II25771 II25773 +0- 1 +-0 1 +.names g1444 g18207 II25781 +0- 1 +-0 1 +.names g1444 II25781 II25782 +0- 1 +-0 1 +.names g18207 II25781 II25783 +0- 1 +-0 1 +.names g2133 g17954 II25790 +0- 1 +-0 1 +.names g2133 II25790 II25791 +0- 1 +-0 1 +.names g17954 II25790 II25792 +0- 1 +-0 1 +.names g83 g18265 II25800 +0- 1 +-0 1 +.names g83 II25800 II25801 +0- 1 +-0 1 +.names g18265 II25800 II25802 +0- 1 +-0 1 +.names g767 g17993 II25809 +0- 1 +-0 1 +.names g767 II25809 II25810 +0- 1 +-0 1 +.names g17993 II25809 II25811 +0- 1 +-0 1 +.names g1448 g18509 II25819 +0- 1 +-0 1 +.names g1448 II25819 II25820 +0- 1 +-0 1 +.names g18509 II25819 II25821 +0- 1 +-0 1 +.names g2138 g18314 II25829 +0- 1 +-0 1 +.names g2138 II25829 II25830 +0- 1 +-0 1 +.names g18314 II25829 II25831 +0- 1 +-0 1 +.names g88 g17802 II25838 +0- 1 +-0 1 +.names g88 II25838 II25839 +0- 1 +-0 1 +.names g17802 II25838 II25840 +0- 1 +-0 1 +.names g771 g18358 II25846 +0- 1 +-0 1 +.names g771 II25846 II25847 +0- 1 +-0 1 +.names g18358 II25846 II25848 +0- 1 +-0 1 +.names g1453 g18110 II25855 +0- 1 +-0 1 +.names g1453 II25855 II25856 +0- 1 +-0 1 +.names g18110 II25855 II25857 +0- 1 +-0 1 +.names g2142 g18573 II25865 +0- 1 +-0 1 +.names g2142 II25865 II25866 +0- 1 +-0 1 +.names g18573 II25865 II25867 +0- 1 +-0 1 +.names g776 g17914 II25880 +0- 1 +-0 1 +.names g776 II25880 II25881 +0- 1 +-0 1 +.names g17914 II25880 II25882 +0- 1 +-0 1 +.names g1457 g18453 II25888 +0- 1 +-0 1 +.names g1457 II25888 II25889 +0- 1 +-0 1 +.names g18453 II25888 II25890 +0- 1 +-0 1 +.names g2147 g18226 II25897 +0- 1 +-0 1 +.names g2147 II25897 II25898 +0- 1 +-0 1 +.names g18226 II25897 II25899 +0- 1 +-0 1 +.names g1462 g18025 II25913 +0- 1 +-0 1 +.names g1462 II25913 II25914 +0- 1 +-0 1 +.names g18025 II25913 II25915 +0- 1 +-0 1 +.names g2151 g18526 II25921 +0- 1 +-0 1 +.names g2151 II25921 II25922 +0- 1 +-0 1 +.names g18526 II25921 II25923 +0- 1 +-0 1 +.names g2156 g18142 II25938 +0- 1 +-0 1 +.names g2156 II25938 II25939 +0- 1 +-0 1 +.names g18142 II25938 II25940 +0- 1 +-0 1 +.names g18165 g15753 g19219 +00 1 +.names g14079 g19444 II28189 +0- 1 +-0 1 +.names g14079 II28189 II28190 +0- 1 +-0 1 +.names g19444 II28189 II28191 +0- 1 +-0 1 +.names II28190 II28191 g21660 +0- 1 +-0 1 +.names g14194 g19471 II28217 +0- 1 +-0 1 +.names g14194 II28217 II28218 +0- 1 +-0 1 +.names g19471 II28217 II28219 +0- 1 +-0 1 +.names II28218 II28219 g21689 +0- 1 +-0 1 +.names g14309 g19494 II28247 +0- 1 +-0 1 +.names g14309 II28247 II28248 +0- 1 +-0 1 +.names g19494 II28247 II28249 +0- 1 +-0 1 +.names II28248 II28249 g21725 +0- 1 +-0 1 +.names g14431 g19515 II28271 +0- 1 +-0 1 +.names g14431 II28271 II28272 +0- 1 +-0 1 +.names g19515 II28271 II28273 +0- 1 +-0 1 +.names II28272 II28273 g21751 +0- 1 +-0 1 +.names g17807 g19181 g19186 g21848 +0-- 1 +-0- 1 +--0 1 +.names g17979 g19187 g19191 g21850 +0-- 1 +-0- 1 +--0 1 +.names g17919 g19188 g19193 g21855 +0-- 1 +-0- 1 +--0 1 +.names g18079 g19192 g19200 g21857 +0-- 1 +-0- 1 +--0 1 +.names g18096 g19194 g19202 g21858 +0-- 1 +-0- 1 +--0 1 +.names g18030 g19195 g19204 g21859 +0-- 1 +-0- 1 +--0 1 +.names g18270 g19201 g19209 g21860 +0-- 1 +-0- 1 +--0 1 +.names g18195 g19203 g19211 g21862 +0-- 1 +-0- 1 +--0 1 +.names g18212 g19205 g19213 g21863 +0-- 1 +-0- 1 +--0 1 +.names g18147 g19206 g19215 g21864 +0-- 1 +-0- 1 +--0 1 +.names g18424 g19210 g19221 g21865 +0-- 1 +-0- 1 +--0 1 +.names g18363 g19212 g19222 g21866 +0-- 1 +-0- 1 +--0 1 +.names g18302 g19214 g19224 g21868 +0-- 1 +-0- 1 +--0 1 +.names g18319 g19216 g19226 g21869 +0-- 1 +-0- 1 +--0 1 +.names g18497 g19223 g19231 g21870 +0-- 1 +-0- 1 +--0 1 +.names g18458 g19225 g19232 g21871 +0-- 1 +-0- 1 +--0 1 +.names g18395 g19227 g19234 g21873 +0-- 1 +-0- 1 +--0 1 +.names g18561 g19233 g19244 g21874 +0-- 1 +-0- 1 +--0 1 +.names g18531 g19235 g19245 g21875 +0-- 1 +-0- 1 +--0 1 +.names g18611 g19246 g19257 g21877 +0-- 1 +-0- 1 +--0 1 +.names g18419 g19250 g19263 g21879 +0-- 1 +-0- 1 +--0 1 +.names g18492 g19264 g19278 g21881 +0-- 1 +-0- 1 +--0 1 +.names g18556 g19279 g19297 g21885 +0-- 1 +-0- 1 +--0 1 +.names g18606 g19298 g19315 g21888 +0-- 1 +-0- 1 +--0 1 +.names g19889 g18062 g21048 +00 1 +.names g19914 g18169 g21065 +00 1 +.names g13519 g19289 g21887 +00 1 +.names g21887 g13519 II28726 +0- 1 +-0 1 +.names g21887 II28726 II28727 +0- 1 +-0 1 +.names g13519 II28726 II28728 +0- 1 +-0 1 +.names g13530 g19307 g21890 +00 1 +.names g21890 g13530 II28741 +0- 1 +-0 1 +.names g21890 II28741 II28742 +0- 1 +-0 1 +.names g13530 II28741 II28743 +0- 1 +-0 1 +.names g13541 g19328 g21893 +00 1 +.names g21893 g13541 II28753 +0- 1 +-0 1 +.names g21893 II28753 II28754 +0- 1 +-0 1 +.names g13541 II28753 II28755 +0- 1 +-0 1 +.names g13552 g19355 g21901 +00 1 +.names g21901 g13552 II28765 +0- 1 +-0 1 +.names g21901 II28765 II28766 +0- 1 +-0 1 +.names g13552 II28765 II28767 +0- 1 +-0 1 +.names g19240 g19230 g21211 +00 1 +.names g19253 g19243 g21219 +00 1 +.names g19266 g19256 g21230 +00 1 +.names g19281 g19269 g21235 +00 1 +.names g21850 g21848 g21879 g22809 +0-- 1 +-0- 1 +--0 1 +.names g21865 g21860 g21857 g22844 +0-- 1 +-0- 1 +--0 1 +.names g8278 g21660 g22846 +0- 1 +-0 1 +.names g21858 g21855 g21881 g22850 +0-- 1 +-0- 1 +--0 1 +.names g21870 g21866 g21862 g22879 +0-- 1 +-0- 1 +--0 1 +.names g8287 g21689 g22881 +0- 1 +-0 1 +.names g21863 g21859 g21885 g22885 +0-- 1 +-0- 1 +--0 1 +.names g21874 g21871 g21868 g22914 +0-- 1 +-0- 1 +--0 1 +.names g8296 g21725 g22916 +0- 1 +-0 1 +.names g21869 g21864 g21888 g22920 +0-- 1 +-0- 1 +--0 1 +.names g21877 g21875 g21873 g22939 +0-- 1 +-0- 1 +--0 1 +.names g8305 g21751 g22941 +0- 1 +-0 1 +.names g21138 g19303 g19320 g23066 +000 1 +.names g21121 g21153 g23051 +00 1 +.names g21158 g19324 g19347 g23080 +000 1 +.names g21140 g21173 g23070 +00 1 +.names g21085 g19241 g22999 +00 1 +.names g19868 g21593 g22174 +00 1 +.names g21178 g19351 g19381 g23096 +000 1 +.names g21160 g21193 g23083 +00 1 +.names g21097 g19254 g23013 +00 1 +.names g19899 g21622 g22189 +00 1 +.names g21198 g19385 g19413 g23113 +000 1 +.names g21180 g21208 g23099 +00 1 +.names g21111 g19267 g23029 +00 1 +.names g19924 g21650 g22198 +00 1 +.names g21128 g19282 g23046 +00 1 +.names g19939 g21681 g22204 +00 1 +.names g21252 g19531 g19540 g21980 +000 1 +.names g21245 g21259 g21975 +00 1 +.names g21260 g19541 g19544 g21987 +000 1 +.names g21254 g21267 g21981 +00 1 +.names g21229 g19449 g23135 +00 1 +.names g20144 g21805 g22288 +00 1 +.names g21268 g19545 g19547 g22000 +000 1 +.names g21262 g21276 g21988 +00 1 +.names g18435 g22812 g23376 +0- 1 +-0 1 +.names g21234 g19476 g21968 +00 1 +.names g20182 g21812 g22308 +00 1 +.names g21277 g19548 g19551 g22013 +000 1 +.names g21270 g21283 g22001 +00 1 +.names g18508 g22852 g23387 +0- 1 +-0 1 +.names g21243 g19499 g21971 +00 1 +.names g20216 g21818 g22336 +00 1 +.names g18572 g22887 g23394 +0- 1 +-0 1 +.names g21251 g19520 g21973 +00 1 +.names g20246 g21822 g22361 +00 1 +.names g18622 g22922 g23402 +0- 1 +-0 1 +.names g22846 g14079 II30790 +0- 1 +-0 1 +.names g22846 II30790 II30791 +0- 1 +-0 1 +.names g14079 II30790 II30792 +0- 1 +-0 1 +.names g22881 g14194 II30868 +0- 1 +-0 1 +.names g22881 II30868 II30869 +0- 1 +-0 1 +.names g14194 II30868 II30870 +0- 1 +-0 1 +.names g22916 g14309 II30952 +0- 1 +-0 1 +.names g22916 II30952 II30953 +0- 1 +-0 1 +.names g14309 II30952 II30954 +0- 1 +-0 1 +.names g22941 g14431 II31035 +0- 1 +-0 1 +.names g22941 II31035 II31036 +0- 1 +-0 1 +.names g14431 II31035 II31037 +0- 1 +-0 1 +.names g22812 g13958 g23906 +0- 1 +-0 1 +.names g22812 g13922 g23936 +0- 1 +-0 1 +.names g22812 g13918 g23937 +0- 1 +-0 1 +.names g22852 g14028 g23938 +0- 1 +-0 1 +.names g22812 g14525 g23953 +0- 1 +-0 1 +.names g22852 g13978 g23968 +0- 1 +-0 1 +.names g22852 g13974 g23969 +0- 1 +-0 1 +.names g22887 g14119 g23970 +0- 1 +-0 1 +.names g22812 g14450 g23973 +0- 1 +-0 1 +.names g22852 g14580 g23982 +0- 1 +-0 1 +.names g22887 g14048 g23997 +0- 1 +-0 1 +.names g22887 g14044 g23998 +0- 1 +-0 1 +.names g22922 g14234 g23999 +0- 1 +-0 1 +.names g22812 g14355 g24002 +0- 1 +-0 1 +.names g22852 g14537 g24003 +0- 1 +-0 1 +.names g22887 g14614 g24012 +0- 1 +-0 1 +.names g22922 g14139 g24027 +0- 1 +-0 1 +.names g22922 g14135 g24028 +0- 1 +-0 1 +.names g22812 g14252 g24034 +0- 1 +-0 1 +.names g22852 g14467 g24036 +0- 1 +-0 1 +.names g22887 g14592 g24037 +0- 1 +-0 1 +.names g22922 g14637 g24046 +0- 1 +-0 1 +.names g22812 g14171 g24052 +0- 1 +-0 1 +.names g22852 g14374 g24054 +0- 1 +-0 1 +.names g22887 g14554 g24056 +0- 1 +-0 1 +.names g22922 g14626 g24057 +0- 1 +-0 1 +.names g22812 g14086 g24058 +0- 1 +-0 1 +.names g22852 g14286 g24065 +0- 1 +-0 1 +.names g22887 g14486 g24067 +0- 1 +-0 1 +.names g22922 g14609 g24069 +0- 1 +-0 1 +.names g22812 g14011 g24070 +0- 1 +-0 1 +.names g22852 g14201 g24071 +0- 1 +-0 1 +.names g22887 g14408 g24078 +0- 1 +-0 1 +.names g22922 g14573 g24080 +0- 1 +-0 1 +.names g22852 g14102 g24081 +0- 1 +-0 1 +.names g22887 g14316 g24082 +0- 1 +-0 1 +.names g22922 g14520 g24089 +0- 1 +-0 1 +.names g22887 g14217 g24090 +0- 1 +-0 1 +.names g22922 g14438 g24091 +0- 1 +-0 1 +.names g22922 g14332 g24093 +0- 1 +-0 1 +.names g17903 g23936 II32265 +0- 1 +-0 1 +.names g17903 II32265 II32266 +0- 1 +-0 1 +.names g23936 II32265 II32267 +0- 1 +-0 1 +.names g17815 g23953 II32284 +0- 1 +-0 1 +.names g17815 II32284 II32285 +0- 1 +-0 1 +.names g23953 II32284 II32286 +0- 1 +-0 1 +.names g18014 g23968 II32295 +0- 1 +-0 1 +.names g18014 II32295 II32296 +0- 1 +-0 1 +.names g23968 II32295 II32297 +0- 1 +-0 1 +.names g17903 g23973 II32308 +0- 1 +-0 1 +.names g17903 II32308 II32309 +0- 1 +-0 1 +.names g23973 II32308 II32310 +0- 1 +-0 1 +.names g17927 g23982 II32323 +0- 1 +-0 1 +.names g17927 II32323 II32324 +0- 1 +-0 1 +.names g23982 II32323 II32325 +0- 1 +-0 1 +.names g18131 g23997 II32333 +0- 1 +-0 1 +.names g18131 II32333 II32334 +0- 1 +-0 1 +.names g23997 II32333 II32335 +0- 1 +-0 1 +.names g17815 g24002 II32345 +0- 1 +-0 1 +.names g17815 II32345 II32346 +0- 1 +-0 1 +.names g24002 II32345 II32347 +0- 1 +-0 1 +.names g18014 g24003 II32355 +0- 1 +-0 1 +.names g18014 II32355 II32356 +0- 1 +-0 1 +.names g24003 II32355 II32357 +0- 1 +-0 1 +.names g18038 g24012 II32368 +0- 1 +-0 1 +.names g18038 II32368 II32369 +0- 1 +-0 1 +.names g24012 II32368 II32370 +0- 1 +-0 1 +.names g18247 g24027 II32378 +0- 1 +-0 1 +.names g18247 II32378 II32379 +0- 1 +-0 1 +.names g24027 II32378 II32380 +0- 1 +-0 1 +.names g17903 g24034 II32391 +0- 1 +-0 1 +.names g17903 II32391 II32392 +0- 1 +-0 1 +.names g24034 II32391 II32393 +0- 1 +-0 1 +.names g17927 g24036 II32400 +0- 1 +-0 1 +.names g17927 II32400 II32401 +0- 1 +-0 1 +.names g24036 II32400 II32402 +0- 1 +-0 1 +.names g18131 g24037 II32409 +0- 1 +-0 1 +.names g18131 II32409 II32410 +0- 1 +-0 1 +.names g24037 II32409 II32411 +0- 1 +-0 1 +.names g18155 g24046 II32422 +0- 1 +-0 1 +.names g18155 II32422 II32423 +0- 1 +-0 1 +.names g24046 II32422 II32424 +0- 1 +-0 1 +.names g17815 g24052 II32430 +0- 1 +-0 1 +.names g17815 II32430 II32431 +0- 1 +-0 1 +.names g24052 II32430 II32432 +0- 1 +-0 1 +.names g18014 g24054 II32443 +0- 1 +-0 1 +.names g18014 II32443 II32444 +0- 1 +-0 1 +.names g24054 II32443 II32445 +0- 1 +-0 1 +.names g18038 g24056 II32451 +0- 1 +-0 1 +.names g18038 II32451 II32452 +0- 1 +-0 1 +.names g24056 II32451 II32453 +0- 1 +-0 1 +.names g18247 g24057 II32460 +0- 1 +-0 1 +.names g18247 II32460 II32461 +0- 1 +-0 1 +.names g24057 II32460 II32462 +0- 1 +-0 1 +.names g17903 g24058 II32468 +0- 1 +-0 1 +.names g17903 II32468 II32469 +0- 1 +-0 1 +.names g24058 II32468 II32470 +0- 1 +-0 1 +.names g17927 g24065 II32478 +0- 1 +-0 1 +.names g17927 II32478 II32479 +0- 1 +-0 1 +.names g24065 II32478 II32480 +0- 1 +-0 1 +.names g18131 g24067 II32490 +0- 1 +-0 1 +.names g18131 II32490 II32491 +0- 1 +-0 1 +.names g24067 II32490 II32492 +0- 1 +-0 1 +.names g18155 g24069 II32498 +0- 1 +-0 1 +.names g18155 II32498 II32499 +0- 1 +-0 1 +.names g24069 II32498 II32500 +0- 1 +-0 1 +.names g17815 g24070 II32509 +0- 1 +-0 1 +.names g17815 II32509 II32510 +0- 1 +-0 1 +.names g24070 II32509 II32511 +0- 1 +-0 1 +.names g18014 g24071 II32518 +0- 1 +-0 1 +.names g18014 II32518 II32519 +0- 1 +-0 1 +.names g24071 II32518 II32520 +0- 1 +-0 1 +.names g18038 g24078 II32526 +0- 1 +-0 1 +.names g18038 II32526 II32527 +0- 1 +-0 1 +.names g24078 II32526 II32528 +0- 1 +-0 1 +.names g18247 g24080 II32538 +0- 1 +-0 1 +.names g18247 II32538 II32539 +0- 1 +-0 1 +.names g24080 II32538 II32540 +0- 1 +-0 1 +.names g17903 g23906 II32546 +0- 1 +-0 1 +.names g17903 II32546 II32547 +0- 1 +-0 1 +.names g23906 II32546 II32548 +0- 1 +-0 1 +.names g17927 g24081 II32559 +0- 1 +-0 1 +.names g17927 II32559 II32560 +0- 1 +-0 1 +.names g24081 II32559 II32561 +0- 1 +-0 1 +.names g18131 g24082 II32567 +0- 1 +-0 1 +.names g18131 II32567 II32568 +0- 1 +-0 1 +.names g24082 II32567 II32569 +0- 1 +-0 1 +.names g18155 g24089 II32575 +0- 1 +-0 1 +.names g18155 II32575 II32576 +0- 1 +-0 1 +.names g24089 II32575 II32577 +0- 1 +-0 1 +.names g17815 g23937 II32586 +0- 1 +-0 1 +.names g17815 II32586 II32587 +0- 1 +-0 1 +.names g23937 II32586 II32588 +0- 1 +-0 1 +.names g18014 g23938 II32595 +0- 1 +-0 1 +.names g18014 II32595 II32596 +0- 1 +-0 1 +.names g23938 II32595 II32597 +0- 1 +-0 1 +.names g18038 g24090 II32607 +0- 1 +-0 1 +.names g18038 II32607 II32608 +0- 1 +-0 1 +.names g24090 II32607 II32609 +0- 1 +-0 1 +.names g18247 g24091 II32615 +0- 1 +-0 1 +.names g18247 II32615 II32616 +0- 1 +-0 1 +.names g24091 II32615 II32617 +0- 1 +-0 1 +.names g17927 g23969 II32624 +0- 1 +-0 1 +.names g17927 II32624 II32625 +0- 1 +-0 1 +.names g23969 II32624 II32626 +0- 1 +-0 1 +.names g18131 g23970 II32633 +0- 1 +-0 1 +.names g18131 II32633 II32634 +0- 1 +-0 1 +.names g23970 II32633 II32635 +0- 1 +-0 1 +.names g18155 g24093 II32645 +0- 1 +-0 1 +.names g18155 II32645 II32646 +0- 1 +-0 1 +.names g24093 II32645 II32647 +0- 1 +-0 1 +.names g18038 g23998 II32659 +0- 1 +-0 1 +.names g18038 II32659 II32660 +0- 1 +-0 1 +.names g23998 II32659 II32661 +0- 1 +-0 1 +.names g18247 g23999 II32668 +0- 1 +-0 1 +.names g18247 II32668 II32669 +0- 1 +-0 1 +.names g23999 II32668 II32670 +0- 1 +-0 1 +.names g23009 g18490 g4456 g23823 +000 1 +.names g23823 g14165 II32677 +0- 1 +-0 1 +.names g23823 II32677 II32678 +0- 1 +-0 1 +.names g14165 II32677 II32679 +0- 1 +-0 1 +.names g18155 g24028 II32686 +0- 1 +-0 1 +.names g18155 II32686 II32687 +0- 1 +-0 1 +.names g24028 II32686 II32688 +0- 1 +-0 1 +.names g23025 g18554 g4632 g23858 +000 1 +.names g23858 g14280 II32695 +0- 1 +-0 1 +.names g23858 II32695 II32696 +0- 1 +-0 1 +.names g14280 II32695 II32697 +0- 1 +-0 1 +.names g23042 g18604 g4809 g23892 +000 1 +.names g23892 g14402 II32708 +0- 1 +-0 1 +.names g23892 II32708 II32709 +0- 1 +-0 1 +.names g14402 II32708 II32710 +0- 1 +-0 1 +.names g23061 g18636 g4985 g23913 +000 1 +.names g23913 g14514 II32724 +0- 1 +-0 1 +.names g23913 II32724 II32725 +0- 1 +-0 1 +.names g14514 II32724 II32726 +0- 1 +-0 1 +.names g23822 g22701 g24517 +00 1 +.names g23857 g22732 g24530 +00 1 +.names g23891 g22764 g24543 +00 1 +.names g23912 g22798 g24555 +00 1 +.names g26110 g26099 II35020 +0- 1 +-0 1 +.names g26110 II35020 II35021 +0- 1 +-0 1 +.names g26099 II35020 II35022 +0- 1 +-0 1 +.names II35021 II35022 g26859 +0- 1 +-0 1 +.names g26087 g26154 II35034 +0- 1 +-0 1 +.names g26087 II35034 II35035 +0- 1 +-0 1 +.names g26154 II35034 II35036 +0- 1 +-0 1 +.names II35035 II35036 g26865 +0- 1 +-0 1 +.names g26151 g26145 II35042 +0- 1 +-0 1 +.names g26151 II35042 II35043 +0- 1 +-0 1 +.names g26145 II35042 II35044 +0- 1 +-0 1 +.names II35043 II35044 g26867 +0- 1 +-0 1 +.names g26137 g26126 II35057 +0- 1 +-0 1 +.names g26137 II35057 II35058 +0- 1 +-0 1 +.names g26126 II35057 II35059 +0- 1 +-0 1 +.names II35058 II35059 g26874 +0- 1 +-0 1 +.names g24613 g24506 g25699 +00 1 +.names g24708 g24490 g25569 +00 1 +.names g24717 g24497 g25631 +00 1 +.names g24624 g24520 g25772 +00 1 +.names g24720 g24500 g25648 +00 1 +.names g24728 g24509 g25708 +00 1 +.names g24638 g24533 g25826 +00 1 +.names g24731 g24512 g25725 +00 1 +.names g24736 g24523 g25781 +00 1 +.names g24657 g24546 g25861 +00 1 +.names g24739 g24526 g25798 +00 1 +.names g24742 g24536 g25835 +00 1 +.names g6068 g24183 g25383 g26107 +000 1 +.names g6068 g24183 g25394 g26096 +000 1 +.names g26107 g26096 II35123 +0- 1 +-0 1 +.names g26107 II35123 II35124 +0- 1 +-0 1 +.names g26096 II35123 II35125 +0- 1 +-0 1 +.names g26867 g26874 II35701 +0- 1 +-0 1 +.names g26867 II35701 II35702 +0- 1 +-0 1 +.names g26874 II35701 II35703 +0- 1 +-0 1 +.names II35702 II35703 g27379 +0- 1 +-0 1 +.names g26859 g26865 II35714 +0- 1 +-0 1 +.names g26859 II35714 II35715 +0- 1 +-0 1 +.names g26865 II35714 II35716 +0- 1 +-0 1 +.names II35715 II35716 g27382 +0- 1 +-0 1 +.names g26663 g21913 g26989 +00 1 +.names g26668 g21931 g27012 +00 1 +.names g26674 g20640 g27038 +00 1 +.names g26024 g20665 g27066 +00 1 +.names g4456 g26081 g27051 +00 1 +.names g27051 g14831 II35904 +0- 1 +-0 1 +.names g27051 II35904 II35905 +0- 1 +-0 1 +.names g14831 II35904 II35906 +0- 1 +-0 1 +.names g4632 g26084 g27078 +00 1 +.names g27078 g14904 II35944 +0- 1 +-0 1 +.names g27078 II35944 II35945 +0- 1 +-0 1 +.names g14904 II35944 II35946 +0- 1 +-0 1 +.names g4809 g26090 g27094 +00 1 +.names g27094 g14985 II35974 +0- 1 +-0 1 +.names g27094 II35974 II35975 +0- 1 +-0 1 +.names g14985 II35974 II35976 +0- 1 +-0 1 +.names g4985 g26103 g27106 +00 1 +.names g27106 g15074 II35992 +0- 1 +-0 1 +.names g27106 II35992 II35993 +0- 1 +-0 1 +.names g15074 II35992 II35994 +0- 1 +-0 1 +.names g23104 g27181 g25128 g27415 +000 1 +.names g23118 g27187 g24427 g27436 +000 1 +.names g23127 g26758 g24431 g27455 +000 1 +.names g23138 g26764 g24435 g27471 +000 1 +.names g26759 g19087 g27527 +00 1 +.names g27527 g15859 II36256 +0- 1 +-0 1 +.names g27527 II36256 II36257 +0- 1 +-0 1 +.names g15859 II36256 II36258 +0- 1 +-0 1 +.names II36257 II36258 g27801 +0- 1 +-0 1 +.names g26765 g19093 g27549 +00 1 +.names g27549 g15890 II36270 +0- 1 +-0 1 +.names g27549 II36270 II36271 +0- 1 +-0 1 +.names g15890 II36270 II36272 +0- 1 +-0 1 +.names II36271 II36272 g27809 +0- 1 +-0 1 +.names g26768 g19100 g27565 +00 1 +.names g27565 g15923 II36289 +0- 1 +-0 1 +.names g27565 II36289 II36290 +0- 1 +-0 1 +.names g15923 II36289 II36291 +0- 1 +-0 1 +.names II36290 II36291 g27830 +0- 1 +-0 1 +.names g27382 g27379 II36300 +0- 1 +-0 1 +.names g27382 II36300 II36301 +0- 1 +-0 1 +.names g27379 II36300 II36302 +0- 1 +-0 1 +.names g26774 g19107 g27575 +00 1 +.names g27575 g15952 II36314 +0- 1 +-0 1 +.names g27575 II36314 II36315 +0- 1 +-0 1 +.names g15952 II36314 II36316 +0- 1 +-0 1 +.names II36315 II36316 g27846 +0- 1 +-0 1 +.names g4456 g26873 g27529 +00 1 +.names g27529 g14885 II36591 +0- 1 +-0 1 +.names g27529 II36591 II36592 +0- 1 +-0 1 +.names g14885 II36591 II36593 +0- 1 +-0 1 +.names g4632 g26882 g27551 +00 1 +.names g27551 g14966 II36666 +0- 1 +-0 1 +.names g27551 II36666 II36667 +0- 1 +-0 1 +.names g14966 II36666 II36668 +0- 1 +-0 1 +.names g4809 g26891 g27567 +00 1 +.names g27567 g15055 II36731 +0- 1 +-0 1 +.names g27567 II36731 II36732 +0- 1 +-0 1 +.names g15055 II36731 II36733 +0- 1 +-0 1 +.names g4985 g26901 g27577 +00 1 +.names g27577 g15151 II36779 +0- 1 +-0 1 +.names g27577 II36779 II36780 +0- 1 +-0 1 +.names g15151 II36779 II36781 +0- 1 +-0 1 +.names g27827 g27814 II37295 +0- 1 +-0 1 +.names g27827 II37295 II37296 +0- 1 +-0 1 +.names g27814 II37295 II37297 +0- 1 +-0 1 +.names II37296 II37297 g28384 +0- 1 +-0 1 +.names g27802 g27900 II37303 +0- 1 +-0 1 +.names g27802 II37303 II37304 +0- 1 +-0 1 +.names g27900 II37303 II37305 +0- 1 +-0 1 +.names II37304 II37305 g28386 +0- 1 +-0 1 +.names g27897 g27883 II37311 +0- 1 +-0 1 +.names g27897 II37311 II37312 +0- 1 +-0 1 +.names g27883 II37311 II37313 +0- 1 +-0 1 +.names II37312 II37313 g28388 +0- 1 +-0 1 +.names g27865 g27855 II37322 +0- 1 +-0 1 +.names g27865 II37322 II37323 +0- 1 +-0 1 +.names g27855 II37322 II37324 +0- 1 +-0 1 +.names II37323 II37324 g28391 +0- 1 +-0 1 +.names g6087 g27632 g25399 g27824 +000 1 +.names g6087 g27632 g25404 g27811 +000 1 +.names g27824 g27811 II37356 +0- 1 +-0 1 +.names g27824 II37356 II37357 +0- 1 +-0 1 +.names g27811 II37356 II37358 +0- 1 +-0 1 +.names g28388 g28391 II37813 +0- 1 +-0 1 +.names g28388 II37813 II37814 +0- 1 +-0 1 +.names g28391 II37813 II37815 +0- 1 +-0 1 +.names II37814 II37815 g28842 +0- 1 +-0 1 +.names g28384 g28386 II37822 +0- 1 +-0 1 +.names g28384 II37822 II37823 +0- 1 +-0 1 +.names g28386 II37822 II37824 +0- 1 +-0 1 +.names II37823 II37824 g28845 +0- 1 +-0 1 +.names g28845 g28842 II38378 +0- 1 +-0 1 +.names g28845 II38378 II38379 +0- 1 +-0 1 +.names g28842 II38378 II38380 +0- 1 +-0 1 +.names g28716 g19112 g29303 +00 1 +.names g29303 g15904 II38810 +0- 1 +-0 1 +.names g29303 II38810 II38811 +0- 1 +-0 1 +.names g15904 II38810 II38812 +0- 1 +-0 1 +.names g28717 g19117 g29313 +00 1 +.names g29313 g15933 II38820 +0- 1 +-0 1 +.names g29313 II38820 II38821 +0- 1 +-0 1 +.names g15933 II38820 II38822 +0- 1 +-0 1 +.names g28718 g19124 g29324 +00 1 +.names g29324 g15962 II38831 +0- 1 +-0 1 +.names g29324 II38831 II38832 +0- 1 +-0 1 +.names g15962 II38831 II38833 +0- 1 +-0 1 +.names g28719 g19131 g29333 +00 1 +.names g29333 g15981 II38841 +0- 1 +-0 1 +.names g29333 II38841 II38842 +0- 1 +-0 1 +.names g15981 II38841 II38843 +0- 1 +-0 1 +.names g29721 g29713 II39323 +0- 1 +-0 1 +.names g29721 II39323 II39324 +0- 1 +-0 1 +.names g29713 II39323 II39325 +0- 1 +-0 1 +.names II39324 II39325 g29911 +0- 1 +-0 1 +.names g29705 g29751 II39331 +0- 1 +-0 1 +.names g29705 II39331 II39332 +0- 1 +-0 1 +.names g29751 II39331 II39333 +0- 1 +-0 1 +.names II39332 II39333 g29913 +0- 1 +-0 1 +.names g29748 g29741 II39339 +0- 1 +-0 1 +.names g29748 II39339 II39340 +0- 1 +-0 1 +.names g29741 II39339 II39341 +0- 1 +-0 1 +.names II39340 II39341 g29915 +0- 1 +-0 1 +.names g29732 g29728 II39347 +0- 1 +-0 1 +.names g29732 II39347 II39348 +0- 1 +-0 1 +.names g29728 II39347 II39349 +0- 1 +-0 1 +.names II39348 II39349 g29917 +0- 1 +-0 1 +.names g29467 g19142 g29766 +00 1 +.names g29766 g15880 II39359 +0- 1 +-0 1 +.names g29766 II39359 II39360 +0- 1 +-0 1 +.names g15880 II39359 II39361 +0- 1 +-0 1 +.names II39360 II39361 g29923 +0- 1 +-0 1 +.names g29468 g19143 g29767 +00 1 +.names g29767 g15913 II39367 +0- 1 +-0 1 +.names g29767 II39367 II39368 +0- 1 +-0 1 +.names g15913 II39367 II39369 +0- 1 +-0 1 +.names II39368 II39369 g29925 +0- 1 +-0 1 +.names g29469 g19146 g29768 +00 1 +.names g29768 g15942 II39375 +0- 1 +-0 1 +.names g29768 II39375 II39376 +0- 1 +-0 1 +.names g15942 II39375 II39377 +0- 1 +-0 1 +.names II39376 II39377 g29927 +0- 1 +-0 1 +.names g6104 g29583 g25409 g29718 +000 1 +.names g6104 g29583 g25412 g29710 +000 1 +.names g29718 g29710 II39384 +0- 1 +-0 1 +.names g29718 II39384 II39385 +0- 1 +-0 1 +.names g29710 II39384 II39386 +0- 1 +-0 1 +.names g29470 g19148 g29769 +00 1 +.names g29769 g15971 II39391 +0- 1 +-0 1 +.names g29769 II39391 II39392 +0- 1 +-0 1 +.names g15971 II39391 II39393 +0- 1 +-0 1 +.names II39392 II39393 g29931 +0- 1 +-0 1 +.names g29915 g29917 II39532 +0- 1 +-0 1 +.names g29915 II39532 II39533 +0- 1 +-0 1 +.names g29917 II39532 II39534 +0- 1 +-0 1 +.names II39533 II39534 g30034 +0- 1 +-0 1 +.names g29911 g29913 II39539 +0- 1 +-0 1 +.names g29911 II39539 II39540 +0- 1 +-0 1 +.names g29913 II39539 II39541 +0- 1 +-0 1 +.names II39540 II39541 g30035 +0- 1 +-0 1 +.names g30035 g30034 II39689 +0- 1 +-0 1 +.names g30035 II39689 II39690 +0- 1 +-0 1 +.names g30034 II39689 II39691 +0- 1 +-0 1 +.names g30605 g30597 II40558 +0- 1 +-0 1 +.names g30605 II40558 II40559 +0- 1 +-0 1 +.names g30597 II40558 II40560 +0- 1 +-0 1 +.names II40559 II40560 g30768 +0- 1 +-0 1 +.names g30588 g30632 II40571 +0- 1 +-0 1 +.names g30588 II40571 II40572 +0- 1 +-0 1 +.names g30632 II40571 II40573 +0- 1 +-0 1 +.names II40572 II40573 g30771 +0- 1 +-0 1 +.names g30629 g30622 II40587 +0- 1 +-0 1 +.names g30629 II40587 II40588 +0- 1 +-0 1 +.names g30622 II40587 II40589 +0- 1 +-0 1 +.names II40588 II40589 g30775 +0- 1 +-0 1 +.names g30614 g30610 II40603 +0- 1 +-0 1 +.names g30614 II40603 II40604 +0- 1 +-0 1 +.names g30610 II40603 II40605 +0- 1 +-0 1 +.names II40604 II40605 g30779 +0- 1 +-0 1 +.names g6119 g30412 g25417 g30602 +000 1 +.names g6119 g30412 g25419 g30594 +000 1 +.names g30602 g30594 II40627 +0- 1 +-0 1 +.names g30602 II40627 II40628 +0- 1 +-0 1 +.names g30594 II40627 II40629 +0- 1 +-0 1 +.names g30775 g30779 II41010 +0- 1 +-0 1 +.names g30775 II41010 II41011 +0- 1 +-0 1 +.names g30779 II41010 II41012 +0- 1 +-0 1 +.names II41011 II41012 g30926 +0- 1 +-0 1 +.names g30768 g30771 II41017 +0- 1 +-0 1 +.names g30768 II41017 II41018 +0- 1 +-0 1 +.names g30771 II41017 II41019 +0- 1 +-0 1 +.names II41018 II41019 g30927 +0- 1 +-0 1 +.names g30927 g30926 II41064 +0- 1 +-0 1 +.names g30927 II41064 II41065 +0- 1 +-0 1 +.names g30926 II41064 II41066 +0- 1 +-0 1 +.names g6200 g12457 g10952 g16020 +000 1 +.names g6289 g12467 g10952 g16036 +000 1 +.names g6426 g12482 g10952 g16058 +000 1 +.names g10952 g6140 g12487 g16082 +000 1 +.names g6631 g12499 g10952 g16094 +000 1 +.names g10952 g6161 g12507 g16120 +000 1 +.names g10952 g6188 g12524 g16171 +000 1 +.names g10952 g6220 g12539 g16230 +000 1 +.names g16082 g14249 g18352 +00 1 +.names g16020 g14352 g18430 +00 1 +.names g16120 g14371 g18447 +00 1 +.names g16036 g14464 g18503 +00 1 +.names g16171 g14483 g18520 +00 1 +.names g16058 g14551 g18567 +00 1 +.names g16230 g14570 g18584 +00 1 +.names g16094 g14606 g18617 +00 1 +.names g17446 g15178 g19160 +00 1 +.names g17526 g15264 g19165 +00 1 +.names g17616 g15356 g19171 +00 1 +.names g17713 g15442 g19177 +00 1 +.names g19600 g17395 g20878 +00 1 +.names g19633 g17461 g20895 +00 1 +.names g19673 g17541 g20914 +00 1 +.names g19721 g17631 g20938 +00 1 +.names g19943 g18333 g21083 +00 1 +.names g20016 g14079 g14165 g21618 +000 1 +.names g20058 g14194 g14280 g21646 +000 1 +.names g20099 g14309 g14402 g21677 +000 1 +.names g20124 g14431 g14514 g21706 +000 1 +.names g19444 g17893 g14079 g21738 +000 1 +.names g19471 g18004 g14194 g21762 +000 1 +.names g19494 g18121 g14309 g21778 +000 1 +.names g19515 g18237 g14431 g21793 +000 1 +.names g21410 g19730 g22144 +00 1 +.names g21444 g19773 g22165 +00 1 +.names g21486 g19815 g22181 +00 1 +.names g21497 g19837 g22186 +00 1 +.names g21527 g19859 g22195 +00 1 +.names g21610 g19932 g22210 +00 1 +.names g21635 g19944 g22216 +00 1 +.names g21658 g19953 g22227 +00 1 +.names g21618 g21049 g22985 +00 1 +.names g21646 g21068 g22987 +00 1 +.names g21677 g21078 g22990 +00 1 +.names g21706 g21092 g22997 +00 1 +.names g21738 g21107 g23009 +00 1 +.names g21762 g21124 g23025 +00 1 +.names g21778 g21143 g23042 +00 1 +.names g21793 g21163 g23061 +00 1 +.names g22483 g21388 g23386 +00 1 +.names g22526 g21418 g23393 +00 1 +.names g22566 g21452 g23401 +00 1 +.names g22606 g21494 g23408 +00 1 +.names g22699 g21589 g23427 +00 1 +.names g22726 g21611 g23433 +00 1 +.names g22841 g21707 g23461 +00 1 +.names g22906 g21758 g23477 +00 1 +.names g22270 g21137 g24227 +00 1 +.names g22289 g21157 g24234 +00 1 +.names g22309 g21177 g24242 +00 1 +.names g22337 g21197 g24249 +00 1 +.names g23544 g22398 g24428 +00 1 +.names g23643 g22577 g24486 +00 1 +.names g23686 g22607 g24490 +00 1 +.names g23689 g22610 g24492 +00 1 +.names g23693 g22614 g24493 +00 1 +.names g23734 g22638 g24497 +00 1 +.names g23740 g22643 g24500 +00 1 +.names g23743 g22646 g24502 +00 1 +.names g23747 g22650 g24503 +00 1 +.names g23776 g22667 g24506 +00 1 +.names g23789 g22674 g24509 +00 1 +.names g23795 g22679 g24512 +00 1 +.names g23798 g22682 g24514 +00 1 +.names g23802 g22686 g24515 +00 1 +.names g23820 g22700 g24516 +00 1 +.names g23829 g22707 g24520 +00 1 +.names g23842 g22714 g24523 +00 1 +.names g23848 g22719 g24526 +00 1 +.names g23851 g22722 g24528 +00 1 +.names g23864 g22738 g24533 +00 1 +.names g23877 g22745 g24536 +00 1 +.names g23898 g22770 g24546 +00 1 +.names g23917 g22804 g24558 +00 1 +.names g23944 g22842 g24566 +00 1 +.names g23972 g22874 g24575 +00 1 +.names g23592 g22515 g24613 +00 1 +.names g23616 g22546 g24622 +00 1 +.names g23624 g22555 g24624 +00 1 +.names g23665 g22587 g24637 +00 1 +.names g23673 g22595 g24638 +00 1 +.names g23715 g22624 g24656 +00 1 +.names g23723 g22632 g24657 +00 1 +.names g23769 g22660 g24675 +00 1 +.names g23854 g22727 g24708 +00 1 +.names g23886 g22754 g24717 +00 1 +.names g23888 g22759 g24720 +00 1 +.names g23907 g22788 g24728 +00 1 +.names g23909 g22793 g24731 +00 1 +.names g23939 g22830 g24736 +00 1 +.names g23941 g22835 g24739 +00 1 +.names g23971 g22869 g24742 +00 1 +.names g23409 g22187 g25076 +00 1 +.names g23414 g22196 g25077 +00 1 +.names g23419 g22201 g25078 +00 1 +.names g23423 g22202 g25081 +00 1 +.names g23428 g22207 g25082 +00 1 +.names g23432 g22208 g25085 +00 1 +.names g23434 g22215 g25091 +00 1 +.names g23440 g22224 g25099 +00 1 +.names g23510 g22340 g25125 +00 1 +.names g23525 g22363 g25127 +00 1 +.names g23536 g22383 g25129 +00 1 +.names g24748 g23552 g25208 +00 1 +.names g24757 g23565 g25216 +00 1 +.names g24774 g23584 g25226 +00 1 +.names g24794 g23611 g25238 +00 1 +.names g24907 g23904 g25273 +00 1 +.names g24964 g24029 g25311 +00 1 +.names g24183 g24616 g25426 +00 1 +.names g24591 g23496 g25962 +00 1 +.names g24596 g23512 g25967 +00 1 +.names g24604 g23527 g25974 +00 1 +.names g24611 g23538 g25979 +00 1 +.names g25505 g24867 g26042 +00 1 +.names g25552 g24882 g26044 +00 1 +.names g25618 g24899 g26046 +00 1 +.names g25629 g24908 g26049 +00 1 +.names g25697 g24922 g26050 +00 1 +.names g25881 g24974 g26055 +00 1 +.names g25470 g25482 g26081 +00 1 +.names g25487 g25513 g26084 +00 1 +.names g25518 g25560 g26090 +00 1 +.names g25565 g25626 g26103 +00 1 +.names g24183 g25430 g26140 +00 1 +.names g25281 g24559 g26560 +00 1 +.names g25289 g24569 g26583 +00 1 +.names g25299 g24578 g26607 +00 1 +.names g25309 g24585 g26630 +00 1 +.names g26158 g25453 g26799 +00 1 +.names g26163 g25457 g26800 +00 1 +.names g26171 g25461 g26801 +00 1 +.names g26188 g25466 g26802 +00 1 +.names g25483 g26260 g26873 +00 1 +.names g25514 g26301 g26882 +00 1 +.names g25561 g26345 g26891 +00 1 +.names g25627 g26389 g26901 +00 1 +.names g26075 g25342 g27175 +00 1 +.names g26082 g25356 g27179 +00 1 +.names g26085 g25371 g27184 +00 1 +.names g26091 g25388 g27188 +00 1 +.names g26955 g26166 g27250 +00 1 +.names g26958 g26186 g27251 +00 1 +.names g26963 g26207 g27252 +00 1 +.names g26968 g26231 g27254 +00 1 +.names g26754 g24432 g27478 +00 1 +.names g26763 g24436 g27501 +00 1 +.names g26766 g24439 g27521 +00 1 +.names g26769 g24441 g27546 +00 1 +.names g26829 g26051 g27629 +00 1 +.names g26833 g26053 g27631 +00 1 +.names g26842 g26061 g27655 +00 1 +.names g26851 g26068 g27658 +00 1 +.names g27396 g26962 g27736 +00 1 +.names g27409 g26967 g27742 +00 1 +.names g27427 g26973 g27747 +00 1 +.names g27448 g26986 g27755 +00 1 +.names g27632 g25437 g27869 +00 1 +.names g27632 g24627 g27886 +00 1 +.names g27356 g26845 g28185 +00 1 +.names g27359 g26853 g28189 +00 1 +.names g27365 g26860 g28191 +00 1 +.names g27372 g26866 g28192 +00 1 +.names g27770 g27355 g28654 +00 1 +.names g27772 g27358 g28656 +00 1 +.names g27773 g27364 g28658 +00 1 +.names g27775 g27371 g28661 +00 1 +.names g28373 g27774 g29126 +00 1 +.names g28376 g27779 g29127 +00 1 +.names g28380 g27783 g29128 +00 1 +.names g28385 g27790 g29129 +00 1 +.names g28834 g28378 g29399 +00 1 +.names g28836 g28383 g29403 +00 1 +.names g28838 g28387 g29406 +00 1 +.names g28840 g28389 g29409 +00 1 +.names g29583 g25444 g29736 +00 1 +.names g29583 g24641 g29744 +00 1 +.names g30412 g25449 g30618 +00 1 +.names g30412 g24660 g30625 +00 1 +.end diff --git a/abc70930/examples/s38584.bench b/abc70930/examples/s38584.bench new file mode 100644 index 00000000..b6135ca4 --- /dev/null +++ b/abc70930/examples/s38584.bench @@ -0,0 +1,21008 @@ +# 12 inputs +# 278 outputs +# 1452 D-type flipflops +# 7805 inverters +# 11448 gates (5516 ANDs + 2126 NANDs + 2621 ORs + 1185 NORs) + +INPUT(g35) +INPUT(g36) +INPUT(g6744) +INPUT(g6745) +INPUT(g6746) +INPUT(g6747) +INPUT(g6748) +INPUT(g6749) +INPUT(g6750) +INPUT(g6751) +INPUT(g6752) +INPUT(g6753) + +OUTPUT(g7243) +OUTPUT(g7245) +OUTPUT(g7257) +OUTPUT(g7260) +OUTPUT(g7540) +OUTPUT(g7916) +OUTPUT(g7946) +OUTPUT(g8132) +OUTPUT(g8178) +OUTPUT(g8215) +OUTPUT(g8235) +OUTPUT(g8277) +OUTPUT(g8279) +OUTPUT(g8283) +OUTPUT(g8291) +OUTPUT(g8342) +OUTPUT(g8344) +OUTPUT(g8353) +OUTPUT(g8358) +OUTPUT(g8398) +OUTPUT(g8403) +OUTPUT(g8416) +OUTPUT(g8475) +OUTPUT(g8719) +OUTPUT(g8783) +OUTPUT(g8784) +OUTPUT(g8785) +OUTPUT(g8786) +OUTPUT(g8787) +OUTPUT(g8788) +OUTPUT(g8789) +OUTPUT(g8839) +OUTPUT(g8870) +OUTPUT(g8915) +OUTPUT(g8916) +OUTPUT(g8917) +OUTPUT(g8918) +OUTPUT(g8919) +OUTPUT(g8920) +OUTPUT(g9019) +OUTPUT(g9048) +OUTPUT(g9251) +OUTPUT(g9497) +OUTPUT(g9553) +OUTPUT(g9555) +OUTPUT(g9615) +OUTPUT(g9617) +OUTPUT(g9680) +OUTPUT(g9682) +OUTPUT(g9741) +OUTPUT(g9743) +OUTPUT(g9817) +OUTPUT(g10122) +OUTPUT(g10306) +OUTPUT(g10500) +OUTPUT(g10527) +OUTPUT(g11349) +OUTPUT(g11388) +OUTPUT(g11418) +OUTPUT(g11447) +OUTPUT(g11678) +OUTPUT(g11770) +OUTPUT(g12184) +OUTPUT(g12238) +OUTPUT(g12300) +OUTPUT(g12350) +OUTPUT(g12368) +OUTPUT(g12422) +OUTPUT(g12470) +OUTPUT(g12832) +OUTPUT(g12919) +OUTPUT(g12923) +OUTPUT(g13039) +OUTPUT(g13049) +OUTPUT(g13068) +OUTPUT(g13085) +OUTPUT(g13099) +OUTPUT(g13259) +OUTPUT(g13272) +OUTPUT(g13865) +OUTPUT(g13881) +OUTPUT(g13895) +OUTPUT(g13906) +OUTPUT(g13926) +OUTPUT(g13966) +OUTPUT(g14096) +OUTPUT(g14125) +OUTPUT(g14147) +OUTPUT(g14167) +OUTPUT(g14189) +OUTPUT(g14201) +OUTPUT(g14217) +OUTPUT(g14421) +OUTPUT(g14451) +OUTPUT(g14518) +OUTPUT(g14597) +OUTPUT(g14635) +OUTPUT(g14662) +OUTPUT(g14673) +OUTPUT(g14694) +OUTPUT(g14705) +OUTPUT(g14738) +OUTPUT(g14749) +OUTPUT(g14779) +OUTPUT(g14828) +OUTPUT(g16603) +OUTPUT(g16624) +OUTPUT(g16627) +OUTPUT(g16656) +OUTPUT(g16659) +OUTPUT(g16686) +OUTPUT(g16693) +OUTPUT(g16718) +OUTPUT(g16722) +OUTPUT(g16744) +OUTPUT(g16748) +OUTPUT(g16775) +OUTPUT(g16874) +OUTPUT(g16924) +OUTPUT(g16955) +OUTPUT(g17291) +OUTPUT(g17316) +OUTPUT(g17320) +OUTPUT(g17400) +OUTPUT(g17404) +OUTPUT(g17423) +OUTPUT(g17519) +OUTPUT(g17577) +OUTPUT(g17580) +OUTPUT(g17604) +OUTPUT(g17607) +OUTPUT(g17639) +OUTPUT(g17646) +OUTPUT(g17649) +OUTPUT(g17674) +OUTPUT(g17678) +OUTPUT(g17685) +OUTPUT(g17688) +OUTPUT(g17711) +OUTPUT(g17715) +OUTPUT(g17722) +OUTPUT(g17739) +OUTPUT(g17743) +OUTPUT(g17760) +OUTPUT(g17764) +OUTPUT(g17778) +OUTPUT(g17787) +OUTPUT(g17813) +OUTPUT(g17819) +OUTPUT(g17845) +OUTPUT(g17871) +OUTPUT(g18092) +OUTPUT(g18094) +OUTPUT(g18095) +OUTPUT(g18096) +OUTPUT(g18097) +OUTPUT(g18098) +OUTPUT(g18099) +OUTPUT(g18100) +OUTPUT(g18101) +OUTPUT(g18881) +OUTPUT(g19334) +OUTPUT(g19357) +OUTPUT(g20049) +OUTPUT(g20557) +OUTPUT(g20652) +OUTPUT(g20654) +OUTPUT(g20763) +OUTPUT(g20899) +OUTPUT(g20901) +OUTPUT(g21176) +OUTPUT(g21245) +OUTPUT(g21270) +OUTPUT(g21292) +OUTPUT(g21698) +OUTPUT(g21727) +OUTPUT(g23002) +OUTPUT(g23190) +OUTPUT(g23612) +OUTPUT(g23652) +OUTPUT(g23683) +OUTPUT(g23759) +OUTPUT(g24151) +OUTPUT(g25114) +OUTPUT(g25167) +OUTPUT(g25219) +OUTPUT(g25259) +OUTPUT(g25582) +OUTPUT(g25583) +OUTPUT(g25584) +OUTPUT(g25585) +OUTPUT(g25586) +OUTPUT(g25587) +OUTPUT(g25588) +OUTPUT(g25589) +OUTPUT(g25590) +OUTPUT(g26801) +OUTPUT(g26875) +OUTPUT(g26876) +OUTPUT(g26877) +OUTPUT(g27831) +OUTPUT(g28030) +OUTPUT(g28041) +OUTPUT(g28042) +OUTPUT(g28753) +OUTPUT(g29210) +OUTPUT(g29211) +OUTPUT(g29212) +OUTPUT(g29213) +OUTPUT(g29214) +OUTPUT(g29215) +OUTPUT(g29216) +OUTPUT(g29217) +OUTPUT(g29218) +OUTPUT(g29219) +OUTPUT(g29220) +OUTPUT(g29221) +OUTPUT(g30327) +OUTPUT(g30329) +OUTPUT(g30330) +OUTPUT(g30331) +OUTPUT(g30332) +OUTPUT(g31521) +OUTPUT(g31656) +OUTPUT(g31665) +OUTPUT(g31793) +OUTPUT(g31860) +OUTPUT(g31861) +OUTPUT(g31862) +OUTPUT(g31863) +OUTPUT(g32185) +OUTPUT(g32429) +OUTPUT(g32454) +OUTPUT(g32975) +OUTPUT(g33079) +OUTPUT(g33435) +OUTPUT(g33533) +OUTPUT(g33636) +OUTPUT(g33659) +OUTPUT(g33874) +OUTPUT(g33894) +OUTPUT(g33935) +OUTPUT(g33945) +OUTPUT(g33946) +OUTPUT(g33947) +OUTPUT(g33948) +OUTPUT(g33949) +OUTPUT(g33950) +OUTPUT(g33959) +OUTPUT(g34201) +OUTPUT(g34221) +OUTPUT(g34232) +OUTPUT(g34233) +OUTPUT(g34234) +OUTPUT(g34235) +OUTPUT(g34236) +OUTPUT(g34237) +OUTPUT(g34238) +OUTPUT(g34239) +OUTPUT(g34240) +OUTPUT(g34383) +OUTPUT(g34425) +OUTPUT(g34435) +OUTPUT(g34436) +OUTPUT(g34437) +OUTPUT(g34597) +OUTPUT(g34788) +OUTPUT(g34839) +OUTPUT(g34913) +OUTPUT(g34915) +OUTPUT(g34917) +OUTPUT(g34919) +OUTPUT(g34921) +OUTPUT(g34923) +OUTPUT(g34925) +OUTPUT(g34927) +OUTPUT(g34956) +OUTPUT(g34972) + +g72 = DFF(g24166) +g73 = DFF(g24167) +g84 = DFF(g24168) +g90 = DFF(g24169) +g91 = DFF(g24170) +g92 = DFF(g24171) +g99 = DFF(g24172) +g100 = DFF(g24173) +g110 = DFF(g34848) +g112 = DFF(g34879) +g113 = DFF(g24174) +g114 = DFF(g24175) +g115 = DFF(g24176) +g116 = DFF(g24177) +g120 = DFF(g24178) +g124 = DFF(g24179) +g125 = DFF(g24180) +g126 = DFF(g24181) +g127 = DFF(g24182) +g134 = DFF(g24183) +g135 = DFF(g24184) +g44 = DFF(g24185) +g45 = DFF(g34990) +g46 = DFF(g34991) +g47 = DFF(g34992) +g48 = DFF(g34993) +g49 = DFF(g34994) +g50 = DFF(g34995) +g51 = DFF(g34996) +g52 = DFF(g34997) +g53 = DFF(g24161) +g54 = DFF(g24162) +g55 = DFF(g35002) +g56 = DFF(g24163) +g57 = DFF(g24164) +g58 = DFF(g30328) +g63 = DFF(g34847) +g71 = DFF(g34786) +g85 = DFF(g34717) +g93 = DFF(g34878) +g101 = DFF(g34787) +g111 = DFF(g34718) +g43 = DFF(g34789) +g64 = DFF(g24165) +g65 = DFF(g34785) +g70 = DFF(g18093) +g4507 = DFF(g30458) +g4459 = DFF(g34253) +g4369 = DFF(g26970) +g4473 = DFF(g34256) +g4462 = DFF(g34254) +g4581 = DFF(g26969) +g4467 = DFF(g34255) +g4474 = DFF(g10384) +g4477 = DFF(g26960) +g4480 = DFF(g31896) +g4495 = DFF(g33036) +g4498 = DFF(g33037) +g4501 = DFF(g33038) +g4504 = DFF(g33039) +g4512 = DFF(g33040) +g4521 = DFF(g26971) +g4527 = DFF(g28082) +g4515 = DFF(g26964) +g4519 = DFF(g33616) +g4520 = DFF(g6972) +g4483 = DFF(g4520) +g4486 = DFF(g26961) +g4489 = DFF(g26962) +g4492 = DFF(g26963) +g4537 = DFF(g34024) +g4423 = DFF(g4537) +g4540 = DFF(g31897) +g4543 = DFF(g33042) +g4567 = DFF(g33043) +g4546 = DFF(g33045) +g4549 = DFF(g33041) +g4552 = DFF(g33044) +g4570 = DFF(g33617) +g4571 = DFF(g6974) +g4555 = DFF(g4571) +g4558 = DFF(g26966) +g4561 = DFF(g26968) +g4564 = DFF(g26967) +g4534 = DFF(g34023) +g4420 = DFF(g26965) +g4438 = DFF(g26953) +g4449 = DFF(g26955) +g4443 = DFF(g4449) +g4446 = DFF(g26954) +g4452 = DFF(g4446) +g4434 = DFF(g26956) +g4430 = DFF(g26957) +g4427 = DFF(g26952) +g4375 = DFF(g26951) +g4414 = DFF(g26946) +g4411 = DFF(g4414) +g4408 = DFF(g26945) +g4405 = DFF(g4408) +g4401 = DFF(g26948) +g4388 = DFF(g26949) +g4382 = DFF(g26947) +g4417 = DFF(g31895) +g4392 = DFF(g26950) +g4456 = DFF(g25692) +g4455 = DFF(g26959) +g1 = DFF(g26958) +g4304 = DFF(g24281) +g4308 = DFF(g4304) +g2932 = DFF(g24282) +g4639 = DFF(g34025) +g4621 = DFF(g34460) +g4628 = DFF(g34457) +g4633 = DFF(g34458) +g4643 = DFF(g34259) +g4340 = DFF(g34459) +g4349 = DFF(g34257) +g4358 = DFF(g34258) +g66 = DFF(g24334) +g4531 = DFF(g24335) +g4311 = DFF(g34449) +g4322 = DFF(g34450) +g4332 = DFF(g34455) +g4584 = DFF(g34451) +g4593 = DFF(g34452) +g4601 = DFF(g34453) +g4608 = DFF(g34454) +g4616 = DFF(g34456) +g4366 = DFF(g26944) +g4372 = DFF(g34882) +g4836 = DFF(g34265) +g4864 = DFF(g34034) +g4871 = DFF(g34035) +g4878 = DFF(g34036) +g4843 = DFF(g34466) +g4849 = DFF(g34465) +g4854 = DFF(g34467) +g4859 = DFF(g34468) +g4917 = DFF(g34638) +g4922 = DFF(g34639) +g4907 = DFF(g34640) +g4912 = DFF(g34641) +g4927 = DFF(g34642) +g4931 = DFF(g21904) +g4932 = DFF(g21905) +g4572 = DFF(g29279) +g4578 = DFF(g29278) +g4999 = DFF(g25694) +g5002 = DFF(g4999) +g5005 = DFF(g5002) +g5008 = DFF(g5005) +g4983 = DFF(g34041) +g4991 = DFF(g34038) +g4966 = DFF(g34039) +g4975 = DFF(g34037) +g4899 = DFF(g34040) +g4894 = DFF(g28087) +g4888 = DFF(g34266) +g4939 = DFF(g28088) +g4933 = DFF(g34267) +g4950 = DFF(g28089) +g4944 = DFF(g34268) +g4961 = DFF(g28090) +g4955 = DFF(g34269) +g4646 = DFF(g34260) +g4674 = DFF(g34026) +g4681 = DFF(g34027) +g4688 = DFF(g34028) +g4653 = DFF(g34462) +g4659 = DFF(g34461) +g4664 = DFF(g34463) +g4669 = DFF(g34464) +g4727 = DFF(g34633) +g4732 = DFF(g34634) +g4717 = DFF(g34635) +g4722 = DFF(g34636) +g4737 = DFF(g34637) +g4741 = DFF(g21902) +g4742 = DFF(g21903) +g59 = DFF(g29277) +g4575 = DFF(g29276) +g4809 = DFF(g25693) +g4812 = DFF(g4809) +g4815 = DFF(g4812) +g4818 = DFF(g4815) +g4793 = DFF(g34033) +g4801 = DFF(g34030) +g4776 = DFF(g34031) +g4785 = DFF(g34029) +g4709 = DFF(g34032) +g4704 = DFF(g28083) +g4698 = DFF(g34261) +g4749 = DFF(g28084) +g4743 = DFF(g34262) +g4760 = DFF(g28085) +g4754 = DFF(g34263) +g4771 = DFF(g28086) +g4765 = DFF(g34264) +g5313 = DFF(g24336) +g5290 = DFF(g5313) +g5320 = DFF(g5290) +g5276 = DFF(g5320) +g5283 = DFF(g5276) +g5308 = DFF(g5283) +g5327 = DFF(g5308) +g5331 = DFF(g5327) +g5335 = DFF(g5331) +g5339 = DFF(g5335) +g5343 = DFF(g24337) +g5348 = DFF(g24338) +g5352 = DFF(g24339) +g5357 = DFF(g33618) +g5297 = DFF(g33619) +g5101 = DFF(g25700) +g5109 = DFF(g5101) +g5062 = DFF(g25702) +g5105 = DFF(g25701) +g5112 = DFF(g5105) +g5022 = DFF(g25703) +g5016 = DFF(g31898) +g5029 = DFF(g31902) +g5033 = DFF(g31904) +g5037 = DFF(g31899) +g5041 = DFF(g31900) +g5046 = DFF(g31901) +g5052 = DFF(g31903) +g5057 = DFF(g33046) +g5069 = DFF(g28092) +g5073 = DFF(g28091) +g5077 = DFF(g25704) +g5080 = DFF(g25695) +g5084 = DFF(g25696) +g5092 = DFF(g25697) +g5097 = DFF(g25698) +g86 = DFF(g25699) +g5164 = DFF(g30459) +g5170 = DFF(g33047) +g5176 = DFF(g33048) +g5180 = DFF(g33049) +g5188 = DFF(g33050) +g5196 = DFF(g30460) +g5224 = DFF(g30464) +g5240 = DFF(g30468) +g5256 = DFF(g30472) +g5204 = DFF(g30476) +g5200 = DFF(g30461) +g5228 = DFF(g30465) +g5244 = DFF(g30469) +g5260 = DFF(g30473) +g5212 = DFF(g30477) +g5208 = DFF(g30462) +g5232 = DFF(g30466) +g5248 = DFF(g30470) +g5264 = DFF(g30474) +g5220 = DFF(g30478) +g5216 = DFF(g30463) +g5236 = DFF(g30467) +g5252 = DFF(g30471) +g5268 = DFF(g30475) +g5272 = DFF(g30479) +g128 = DFF(g28093) +g5156 = DFF(g29285) +g5120 = DFF(g25708) +g5115 = DFF(g29280) +g5124 = DFF(g29281) +g5128 = DFF(g25705) +g5134 = DFF(g29282) +g5138 = DFF(g29283) +g5142 = DFF(g29284) +g5148 = DFF(g25706) +g5152 = DFF(g25707) +g5160 = DFF(g34643) +g5659 = DFF(g24340) +g5637 = DFF(g5659) +g5666 = DFF(g5637) +g5623 = DFF(g5666) +g5630 = DFF(g5623) +g5654 = DFF(g5630) +g5673 = DFF(g5654) +g5677 = DFF(g5673) +g5681 = DFF(g5677) +g5685 = DFF(g5681) +g5689 = DFF(g24341) +g5694 = DFF(g24342) +g5698 = DFF(g24343) +g5703 = DFF(g33620) +g5644 = DFF(g33621) +g5448 = DFF(g25714) +g5456 = DFF(g5448) +g5406 = DFF(g25716) +g5452 = DFF(g25715) +g5459 = DFF(g5452) +g5366 = DFF(g25717) +g5360 = DFF(g31905) +g5373 = DFF(g31909) +g5377 = DFF(g31911) +g5381 = DFF(g31906) +g5385 = DFF(g31907) +g5390 = DFF(g31908) +g5396 = DFF(g31910) +g5401 = DFF(g33051) +g5413 = DFF(g28095) +g5417 = DFF(g28094) +g5421 = DFF(g25718) +g5424 = DFF(g25709) +g5428 = DFF(g25710) +g5436 = DFF(g25711) +g5441 = DFF(g25712) +g5445 = DFF(g25713) +g5511 = DFF(g30480) +g5517 = DFF(g33052) +g5523 = DFF(g33053) +g5527 = DFF(g33054) +g5535 = DFF(g33055) +g5543 = DFF(g30481) +g5571 = DFF(g30485) +g5587 = DFF(g30489) +g5603 = DFF(g30493) +g5551 = DFF(g30497) +g5547 = DFF(g30482) +g5575 = DFF(g30486) +g5591 = DFF(g30490) +g5607 = DFF(g30494) +g5559 = DFF(g30498) +g5555 = DFF(g30483) +g5579 = DFF(g30487) +g5595 = DFF(g30491) +g5611 = DFF(g30495) +g5567 = DFF(g30499) +g5563 = DFF(g30484) +g5583 = DFF(g30488) +g5599 = DFF(g30492) +g5615 = DFF(g30496) +g5619 = DFF(g30500) +g4821 = DFF(g28096) +g5503 = DFF(g29291) +g5467 = DFF(g25722) +g5462 = DFF(g29286) +g5471 = DFF(g29287) +g5475 = DFF(g25719) +g5481 = DFF(g29288) +g5485 = DFF(g29289) +g5489 = DFF(g29290) +g5495 = DFF(g25720) +g5499 = DFF(g25721) +g5507 = DFF(g34644) +g6005 = DFF(g24344) +g5983 = DFF(g6005) +g6012 = DFF(g5983) +g5969 = DFF(g6012) +g5976 = DFF(g5969) +g6000 = DFF(g5976) +g6019 = DFF(g6000) +g6023 = DFF(g6019) +g6027 = DFF(g6023) +g6031 = DFF(g6027) +g6035 = DFF(g24345) +g6040 = DFF(g24346) +g6044 = DFF(g24347) +g6049 = DFF(g33622) +g5990 = DFF(g33623) +g5794 = DFF(g25728) +g5802 = DFF(g5794) +g5752 = DFF(g25730) +g5798 = DFF(g25729) +g5805 = DFF(g5798) +g5712 = DFF(g25731) +g5706 = DFF(g31912) +g5719 = DFF(g31916) +g5723 = DFF(g31918) +g5727 = DFF(g31913) +g5731 = DFF(g31914) +g5736 = DFF(g31915) +g5742 = DFF(g31917) +g5747 = DFF(g33056) +g5759 = DFF(g28098) +g5763 = DFF(g28097) +g5767 = DFF(g25732) +g5770 = DFF(g25723) +g5774 = DFF(g25724) +g5782 = DFF(g25725) +g5787 = DFF(g25726) +g5791 = DFF(g25727) +g5857 = DFF(g30501) +g5863 = DFF(g33057) +g5869 = DFF(g33058) +g5873 = DFF(g33059) +g5881 = DFF(g33060) +g5889 = DFF(g30502) +g5917 = DFF(g30506) +g5933 = DFF(g30510) +g5949 = DFF(g30514) +g5897 = DFF(g30518) +g5893 = DFF(g30503) +g5921 = DFF(g30507) +g5937 = DFF(g30511) +g5953 = DFF(g30515) +g5905 = DFF(g30519) +g5901 = DFF(g30504) +g5925 = DFF(g30508) +g5941 = DFF(g30512) +g5957 = DFF(g30516) +g5913 = DFF(g30520) +g5909 = DFF(g30505) +g5929 = DFF(g30509) +g5945 = DFF(g30513) +g5961 = DFF(g30517) +g5965 = DFF(g30521) +g4831 = DFF(g28099) +g5849 = DFF(g29297) +g5813 = DFF(g25736) +g5808 = DFF(g29292) +g5817 = DFF(g29293) +g5821 = DFF(g25733) +g5827 = DFF(g29294) +g5831 = DFF(g29295) +g5835 = DFF(g29296) +g5841 = DFF(g25734) +g5845 = DFF(g25735) +g5853 = DFF(g34645) +g6351 = DFF(g24348) +g6329 = DFF(g6351) +g6358 = DFF(g6329) +g6315 = DFF(g6358) +g6322 = DFF(g6315) +g6346 = DFF(g6322) +g6365 = DFF(g6346) +g6369 = DFF(g6365) +g6373 = DFF(g6369) +g6377 = DFF(g6373) +g6381 = DFF(g24349) +g6386 = DFF(g24350) +g6390 = DFF(g24351) +g6395 = DFF(g33624) +g6336 = DFF(g33625) +g6140 = DFF(g25742) +g6148 = DFF(g6140) +g6098 = DFF(g25744) +g6144 = DFF(g25743) +g6151 = DFF(g6144) +g6058 = DFF(g25745) +g6052 = DFF(g31919) +g6065 = DFF(g31923) +g6069 = DFF(g31925) +g6073 = DFF(g31920) +g6077 = DFF(g31921) +g6082 = DFF(g31922) +g6088 = DFF(g31924) +g6093 = DFF(g33061) +g6105 = DFF(g28101) +g6109 = DFF(g28100) +g6113 = DFF(g25746) +g6116 = DFF(g25737) +g6120 = DFF(g25738) +g6128 = DFF(g25739) +g6133 = DFF(g25740) +g6137 = DFF(g25741) +g6203 = DFF(g30522) +g6209 = DFF(g33062) +g6215 = DFF(g33063) +g6219 = DFF(g33064) +g6227 = DFF(g33065) +g6235 = DFF(g30523) +g6263 = DFF(g30527) +g6279 = DFF(g30531) +g6295 = DFF(g30535) +g6243 = DFF(g30539) +g6239 = DFF(g30524) +g6267 = DFF(g30528) +g6283 = DFF(g30532) +g6299 = DFF(g30536) +g6251 = DFF(g30540) +g6247 = DFF(g30525) +g6271 = DFF(g30529) +g6287 = DFF(g30533) +g6303 = DFF(g30537) +g6259 = DFF(g30541) +g6255 = DFF(g30526) +g6275 = DFF(g30530) +g6291 = DFF(g30534) +g6307 = DFF(g30538) +g6311 = DFF(g30542) +g4826 = DFF(g28102) +g6195 = DFF(g29303) +g6159 = DFF(g25750) +g6154 = DFF(g29298) +g6163 = DFF(g29299) +g6167 = DFF(g25747) +g6173 = DFF(g29300) +g6177 = DFF(g29301) +g6181 = DFF(g29302) +g6187 = DFF(g25748) +g6191 = DFF(g25749) +g6199 = DFF(g34646) +g6697 = DFF(g24352) +g6675 = DFF(g6697) +g6704 = DFF(g6675) +g6661 = DFF(g6704) +g6668 = DFF(g6661) +g6692 = DFF(g6668) +g6711 = DFF(g6692) +g6715 = DFF(g6711) +g6719 = DFF(g6715) +g6723 = DFF(g6719) +g6727 = DFF(g24353) +g6732 = DFF(g24354) +g6736 = DFF(g24355) +g6741 = DFF(g33626) +g6682 = DFF(g33627) +g6486 = DFF(g25756) +g6494 = DFF(g6486) +g6444 = DFF(g25758) +g6490 = DFF(g25757) +g6497 = DFF(g6490) +g6404 = DFF(g25759) +g6398 = DFF(g31926) +g6411 = DFF(g31930) +g6415 = DFF(g31932) +g6419 = DFF(g31927) +g6423 = DFF(g31928) +g6428 = DFF(g31929) +g6434 = DFF(g31931) +g6439 = DFF(g33066) +g6451 = DFF(g28104) +g6455 = DFF(g28103) +g6459 = DFF(g25760) +g6462 = DFF(g25751) +g6466 = DFF(g25752) +g6474 = DFF(g25753) +g6479 = DFF(g25754) +g6483 = DFF(g25755) +g6549 = DFF(g30543) +g6555 = DFF(g33067) +g6561 = DFF(g33068) +g6565 = DFF(g33069) +g6573 = DFF(g33070) +g6581 = DFF(g30544) +g6609 = DFF(g30548) +g6625 = DFF(g30552) +g6641 = DFF(g30556) +g6589 = DFF(g30560) +g6585 = DFF(g30545) +g6613 = DFF(g30549) +g6629 = DFF(g30553) +g6645 = DFF(g30557) +g6597 = DFF(g30561) +g6593 = DFF(g30546) +g6617 = DFF(g30550) +g6633 = DFF(g30554) +g6649 = DFF(g30558) +g6605 = DFF(g30562) +g6601 = DFF(g30547) +g6621 = DFF(g30551) +g6637 = DFF(g30555) +g6653 = DFF(g30559) +g6657 = DFF(g30563) +g5011 = DFF(g28105) +g6541 = DFF(g29309) +g6505 = DFF(g25764) +g6500 = DFF(g29304) +g6509 = DFF(g29305) +g6513 = DFF(g25761) +g6519 = DFF(g29306) +g6523 = DFF(g29307) +g6527 = DFF(g29308) +g6533 = DFF(g25762) +g6537 = DFF(g25763) +g6545 = DFF(g34647) +g3303 = DFF(g24267) +g3281 = DFF(g3303) +g3310 = DFF(g3281) +g3267 = DFF(g3310) +g3274 = DFF(g3267) +g3298 = DFF(g3274) +g3317 = DFF(g3298) +g3321 = DFF(g3317) +g3325 = DFF(g3321) +g3329 = DFF(g3325) +g3338 = DFF(g24268) +g3343 = DFF(g24269) +g3347 = DFF(g24270) +g3352 = DFF(g33609) +g3288 = DFF(g33610) +g3092 = DFF(g25648) +g3100 = DFF(g3092) +g3050 = DFF(g25650) +g3096 = DFF(g25649) +g3103 = DFF(g3096) +g3010 = DFF(g25651) +g3004 = DFF(g31873) +g3017 = DFF(g31877) +g3021 = DFF(g31879) +g3025 = DFF(g31874) +g3029 = DFF(g31875) +g3034 = DFF(g31876) +g3040 = DFF(g31878) +g3045 = DFF(g33020) +g3057 = DFF(g28062) +g3061 = DFF(g28061) +g3065 = DFF(g25652) +g3068 = DFF(g25643) +g3072 = DFF(g25644) +g3080 = DFF(g25645) +g3085 = DFF(g25646) +g3089 = DFF(g25647) +g3155 = DFF(g30393) +g3161 = DFF(g33021) +g3167 = DFF(g33022) +g3171 = DFF(g33023) +g3179 = DFF(g33024) +g3187 = DFF(g30394) +g3215 = DFF(g30398) +g3231 = DFF(g30402) +g3247 = DFF(g30406) +g3195 = DFF(g30410) +g3191 = DFF(g30395) +g3219 = DFF(g30399) +g3235 = DFF(g30403) +g3251 = DFF(g30407) +g3203 = DFF(g30411) +g3199 = DFF(g30396) +g3223 = DFF(g30400) +g3239 = DFF(g30404) +g3255 = DFF(g30408) +g3211 = DFF(g30412) +g3207 = DFF(g30397) +g3227 = DFF(g30401) +g3243 = DFF(g30405) +g3259 = DFF(g30409) +g3263 = DFF(g30413) +g3333 = DFF(g28063) +g3147 = DFF(g29262) +g3111 = DFF(g25656) +g3106 = DFF(g29257) +g3115 = DFF(g29258) +g3119 = DFF(g25653) +g3125 = DFF(g29259) +g3129 = DFF(g29260) +g3133 = DFF(g29261) +g3139 = DFF(g25654) +g3143 = DFF(g25655) +g3151 = DFF(g34625) +g3654 = DFF(g24271) +g3632 = DFF(g3654) +g3661 = DFF(g3632) +g3618 = DFF(g3661) +g3625 = DFF(g3618) +g3649 = DFF(g3625) +g3668 = DFF(g3649) +g3672 = DFF(g3668) +g3676 = DFF(g3672) +g3680 = DFF(g3676) +g3689 = DFF(g24272) +g3694 = DFF(g24273) +g3698 = DFF(g24274) +g3703 = DFF(g33611) +g3639 = DFF(g33612) +g3443 = DFF(g25662) +g3451 = DFF(g3443) +g3401 = DFF(g25664) +g3447 = DFF(g25663) +g3454 = DFF(g3447) +g3361 = DFF(g25665) +g3355 = DFF(g31880) +g3368 = DFF(g31884) +g3372 = DFF(g31886) +g3376 = DFF(g31881) +g3380 = DFF(g31882) +g3385 = DFF(g31883) +g3391 = DFF(g31885) +g3396 = DFF(g33025) +g3408 = DFF(g28065) +g3412 = DFF(g28064) +g3416 = DFF(g25666) +g3419 = DFF(g25657) +g3423 = DFF(g25658) +g3431 = DFF(g25659) +g3436 = DFF(g25660) +g3440 = DFF(g25661) +g3506 = DFF(g30414) +g3512 = DFF(g33026) +g3518 = DFF(g33027) +g3522 = DFF(g33028) +g3530 = DFF(g33029) +g3538 = DFF(g30415) +g3566 = DFF(g30419) +g3582 = DFF(g30423) +g3598 = DFF(g30427) +g3546 = DFF(g30431) +g3542 = DFF(g30416) +g3570 = DFF(g30420) +g3586 = DFF(g30424) +g3602 = DFF(g30428) +g3554 = DFF(g30432) +g3550 = DFF(g30417) +g3574 = DFF(g30421) +g3590 = DFF(g30425) +g3606 = DFF(g30429) +g3562 = DFF(g30433) +g3558 = DFF(g30418) +g3578 = DFF(g30422) +g3594 = DFF(g30426) +g3610 = DFF(g30430) +g3614 = DFF(g30434) +g3684 = DFF(g28066) +g3498 = DFF(g29268) +g3462 = DFF(g25670) +g3457 = DFF(g29263) +g3466 = DFF(g29264) +g3470 = DFF(g25667) +g3476 = DFF(g29265) +g3480 = DFF(g29266) +g3484 = DFF(g29267) +g3490 = DFF(g25668) +g3494 = DFF(g25669) +g3502 = DFF(g34626) +g4005 = DFF(g24275) +g3983 = DFF(g4005) +g4012 = DFF(g3983) +g3969 = DFF(g4012) +g3976 = DFF(g3969) +g4000 = DFF(g3976) +g4019 = DFF(g4000) +g4023 = DFF(g4019) +g4027 = DFF(g4023) +g4031 = DFF(g4027) +g4040 = DFF(g24276) +g4045 = DFF(g24277) +g4049 = DFF(g24278) +g4054 = DFF(g33613) +g3990 = DFF(g33614) +g3794 = DFF(g25676) +g3802 = DFF(g3794) +g3752 = DFF(g25678) +g3798 = DFF(g25677) +g3805 = DFF(g3798) +g3712 = DFF(g25679) +g3706 = DFF(g31887) +g3719 = DFF(g31891) +g3723 = DFF(g31893) +g3727 = DFF(g31888) +g3731 = DFF(g31889) +g3736 = DFF(g31890) +g3742 = DFF(g31892) +g3747 = DFF(g33030) +g3759 = DFF(g28068) +g3763 = DFF(g28067) +g3767 = DFF(g25680) +g3770 = DFF(g25671) +g3774 = DFF(g25672) +g3782 = DFF(g25673) +g3787 = DFF(g25674) +g3791 = DFF(g25675) +g3857 = DFF(g30435) +g3863 = DFF(g33031) +g3869 = DFF(g33032) +g3873 = DFF(g33033) +g3881 = DFF(g33034) +g3889 = DFF(g30436) +g3917 = DFF(g30440) +g3933 = DFF(g30444) +g3949 = DFF(g30448) +g3897 = DFF(g30452) +g3893 = DFF(g30437) +g3921 = DFF(g30441) +g3937 = DFF(g30445) +g3953 = DFF(g30449) +g3905 = DFF(g30453) +g3901 = DFF(g30438) +g3925 = DFF(g30442) +g3941 = DFF(g30446) +g3957 = DFF(g30450) +g3913 = DFF(g30454) +g3909 = DFF(g30439) +g3929 = DFF(g30443) +g3945 = DFF(g30447) +g3961 = DFF(g30451) +g3965 = DFF(g30455) +g4035 = DFF(g28069) +g3849 = DFF(g29274) +g3813 = DFF(g25684) +g3808 = DFF(g29269) +g3817 = DFF(g29270) +g3821 = DFF(g25681) +g3827 = DFF(g29271) +g3831 = DFF(g29272) +g3835 = DFF(g29273) +g3841 = DFF(g25682) +g3845 = DFF(g25683) +g3853 = DFF(g34627) +g4165 = DFF(g28079) +g4169 = DFF(g28080) +g4125 = DFF(g28081) +g4072 = DFF(g25691) +g4064 = DFF(g25685) +g4057 = DFF(g25686) +g4141 = DFF(g25687) +g4082 = DFF(g26938) +g4076 = DFF(g28070) +g4087 = DFF(g29275) +g4093 = DFF(g30456) +g4098 = DFF(g31894) +g4108 = DFF(g33035) +g4104 = DFF(g33615) +g4145 = DFF(g26939) +g4112 = DFF(g28071) +g4116 = DFF(g28072) +g4119 = DFF(g28073) +g4122 = DFF(g28074) +g4153 = DFF(g30457) +g4164 = DFF(g26940) +g4129 = DFF(g28075) +g4132 = DFF(g28076) +g4135 = DFF(g28077) +g4138 = DFF(g28078) +g4172 = DFF(g34733) +g4176 = DFF(g34734) +g4146 = DFF(g34628) +g4157 = DFF(g34629) +g4258 = DFF(g21893) +g4264 = DFF(g21894) +g4269 = DFF(g21895) +g4273 = DFF(g24280) +g4239 = DFF(g21892) +g4294 = DFF(g21900) +g4297 = DFF(g4294) +g4300 = DFF(g34735) +g4253 = DFF(g34630) +g4249 = DFF(g34631) +g4245 = DFF(g34632) +g4277 = DFF(g21896) +g4281 = DFF(g4277) +g4284 = DFF(g21897) +g4287 = DFF(g21898) +g4291 = DFF(g4287) +g2946 = DFF(g21899) +g4191 = DFF(g21901) +g4188 = DFF(g4191) +g4194 = DFF(g4188) +g4197 = DFF(g4194) +g4200 = DFF(g4197) +g4204 = DFF(g4200) +g4207 = DFF(g4204) +g4210 = DFF(g4207) +g4180 = DFF(g4210) +g4185 = DFF(g21891) +g4213 = DFF(g4185) +g4216 = DFF(g4213) +g4219 = DFF(g4216) +g4222 = DFF(g4219) +g4226 = DFF(g4222) +g4229 = DFF(g4226) +g4232 = DFF(g4229) +g4235 = DFF(g4232) +g4242 = DFF(g24279) +g305 = DFF(g26880) +g311 = DFF(g26881) +g336 = DFF(g26886) +g324 = DFF(g26887) +g316 = DFF(g26883) +g319 = DFF(g26882) +g329 = DFF(g26885) +g333 = DFF(g26884) +g344 = DFF(g26890) +g347 = DFF(g344) +g351 = DFF(g26891) +g355 = DFF(g26892) +g74 = DFF(g26893) +g106 = DFF(g26889) +g341 = DFF(g26888) +g637 = DFF(g24212) +g640 = DFF(g637) +g559 = DFF(g640) +g562 = DFF(g25613) +g568 = DFF(g26895) +g572 = DFF(g28045) +g586 = DFF(g29224) +g577 = DFF(g30334) +g582 = DFF(g31866) +g590 = DFF(g32978) +g595 = DFF(g33538) +g599 = DFF(g33964) +g604 = DFF(g34251) +g608 = DFF(g34438) +g613 = DFF(g34599) +g617 = DFF(g34724) +g622 = DFF(g34790) +g626 = DFF(g34849) +g632 = DFF(g34880) +g859 = DFF(g26900) +g869 = DFF(g859) +g875 = DFF(g869) +g878 = DFF(g875) +g881 = DFF(g878) +g884 = DFF(g881) +g887 = DFF(g884) +g872 = DFF(g887) +g225 = DFF(g26901) +g255 = DFF(g26902) +g232 = DFF(g26903) +g262 = DFF(g26904) +g239 = DFF(g26905) +g269 = DFF(g26906) +g246 = DFF(g26907) +g446 = DFF(g26908) +g890 = DFF(g34440) +g862 = DFF(g26909) +g896 = DFF(g26910) +g901 = DFF(g25620) +g391 = DFF(g26911) +g365 = DFF(g25595) +g358 = DFF(g365) +g370 = DFF(g25597) +g376 = DFF(g25596) +g385 = DFF(g25598) +g203 = DFF(g25599) +g854 = DFF(g32980) +g847 = DFF(g24216) +g703 = DFF(g24214) +g837 = DFF(g24215) +g843 = DFF(g25619) +g812 = DFF(g26898) +g817 = DFF(g25617) +g832 = DFF(g25618) +g822 = DFF(g26899) +g827 = DFF(g28055) +g723 = DFF(g29229) +g645 = DFF(g28046) +g681 = DFF(g28047) +g699 = DFF(g28053) +g650 = DFF(g28049) +g655 = DFF(g28050) +g718 = DFF(g28051) +g661 = DFF(g28052) +g728 = DFF(g28054) +g79 = DFF(g26896) +g691 = DFF(g28048) +g686 = DFF(g25614) +g667 = DFF(g25615) +g671 = DFF(g29225) +g676 = DFF(g29226) +g714 = DFF(g29227) +g499 = DFF(g25609) +g504 = DFF(g25610) +g513 = DFF(g25611) +g518 = DFF(g25612) +g528 = DFF(g26894) +g482 = DFF(g28044) +g490 = DFF(g29223) +g417 = DFF(g24209) +g411 = DFF(g29222) +g424 = DFF(g24202) +g475 = DFF(g24208) +g441 = DFF(g24207) +g437 = DFF(g24206) +g433 = DFF(g24205) +g429 = DFF(g24204) +g401 = DFF(g24203) +g392 = DFF(g24200) +g405 = DFF(g24201) +g182 = DFF(g25602) +g174 = DFF(g25601) +g168 = DFF(g25600) +g460 = DFF(g25605) +g452 = DFF(g25604) +g457 = DFF(g25603) +g471 = DFF(g25608) +g464 = DFF(g25607) +g468 = DFF(g25606) +g479 = DFF(g24210) +g102 = DFF(g33962) +g496 = DFF(g33963) +g732 = DFF(g25616) +g753 = DFF(g26897) +g799 = DFF(g24213) +g802 = DFF(g799) +g736 = DFF(g802) +g739 = DFF(g29228) +g744 = DFF(g30335) +g749 = DFF(g31867) +g758 = DFF(g32979) +g763 = DFF(g33539) +g767 = DFF(g33965) +g772 = DFF(g34252) +g776 = DFF(g34439) +g781 = DFF(g34600) +g785 = DFF(g34725) +g790 = DFF(g34791) +g794 = DFF(g34850) +g807 = DFF(g34881) +g554 = DFF(g34911) +g538 = DFF(g34719) +g546 = DFF(g34722) +g542 = DFF(g24211) +g534 = DFF(g34723) +g550 = DFF(g34720) +g136 = DFF(g34598) +g199 = DFF(g34721) +g278 = DFF(g25594) +g283 = DFF(g28043) +g287 = DFF(g31865) +g291 = DFF(g32977) +g294 = DFF(g33535) +g298 = DFF(g33961) +g142 = DFF(g34250) +g146 = DFF(g30333) +g164 = DFF(g31864) +g150 = DFF(g32976) +g153 = DFF(g33534) +g157 = DFF(g33960) +g160 = DFF(g34249) +g301 = DFF(g33536) +g222 = DFF(g33537) +g194 = DFF(g25592) +g191 = DFF(g194) +g209 = DFF(g25593) +g215 = DFF(g25591) +g218 = DFF(g215) +g1249 = DFF(g24247) +g1266 = DFF(g25630) +g1280 = DFF(g26919) +g1252 = DFF(g28058) +g1256 = DFF(g29235) +g1259 = DFF(g30342) +g1263 = DFF(g31870) +g1270 = DFF(g32984) +g1274 = DFF(g33542) +g1277 = DFF(g32985) +g1418 = DFF(g24254) +g1422 = DFF(g1418) +g1426 = DFF(g1422) +g1430 = DFF(g1426) +g1548 = DFF(g24260) +g1564 = DFF(g24262) +g1559 = DFF(g25638) +g1554 = DFF(g25637) +g1570 = DFF(g24258) +g1585 = DFF(g1570) +g1589 = DFF(g24261) +g1576 = DFF(g24255) +g1579 = DFF(g1576) +g1339 = DFF(g24259) +g1500 = DFF(g24256) +g1582 = DFF(g1500) +g1333 = DFF(g1582) +g1399 = DFF(g24257) +g1459 = DFF(g1399) +g1322 = DFF(g1459) +g1514 = DFF(g30344) +g1526 = DFF(g30345) +g1521 = DFF(g24252) +g1306 = DFF(g25636) +g1532 = DFF(g24253) +g1536 = DFF(g26925) +g1542 = DFF(g30346) +g1413 = DFF(g30347) +g1395 = DFF(g25634) +g1404 = DFF(g26921) +g1319 = DFF(g24248) +g1312 = DFF(g25631) +g1351 = DFF(g25632) +g1345 = DFF(g28059) +g1361 = DFF(g30343) +g1367 = DFF(g31871) +g1373 = DFF(g32986) +g1379 = DFF(g33543) +g1384 = DFF(g25633) +g1389 = DFF(g26920) +g1489 = DFF(g24249) +g1495 = DFF(g24250) +g1442 = DFF(g24251) +g1437 = DFF(g29236) +g1478 = DFF(g26924) +g1454 = DFF(g29239) +g1448 = DFF(g26922) +g1467 = DFF(g29237) +g1472 = DFF(g26923) +g1484 = DFF(g29238) +g1300 = DFF(g25635) +g1291 = DFF(g34602) +g1296 = DFF(g34729) +g1283 = DFF(g34730) +g1287 = DFF(g34731) +g1311 = DFF(g21724) +g929 = DFF(g21725) +g904 = DFF(g24231) +g921 = DFF(g25621) +g936 = DFF(g26912) +g907 = DFF(g28056) +g911 = DFF(g29230) +g914 = DFF(g30336) +g918 = DFF(g31868) +g925 = DFF(g32981) +g930 = DFF(g33540) +g933 = DFF(g32982) +g1075 = DFF(g24238) +g1079 = DFF(g1075) +g1083 = DFF(g1079) +g1087 = DFF(g1083) +g1205 = DFF(g24244) +g1221 = DFF(g24246) +g1216 = DFF(g25629) +g1211 = DFF(g25628) +g1227 = DFF(g24242) +g1242 = DFF(g1227) +g1246 = DFF(g24245) +g1233 = DFF(g24239) +g1236 = DFF(g1233) +g996 = DFF(g24243) +g1157 = DFF(g24240) +g1239 = DFF(g1157) +g990 = DFF(g1239) +g1056 = DFF(g24241) +g1116 = DFF(g1056) +g979 = DFF(g1116) +g1171 = DFF(g30338) +g1183 = DFF(g30339) +g1178 = DFF(g24236) +g962 = DFF(g25627) +g1189 = DFF(g24237) +g1193 = DFF(g26918) +g1199 = DFF(g30340) +g1070 = DFF(g30341) +g1052 = DFF(g25625) +g1061 = DFF(g26914) +g976 = DFF(g24232) +g969 = DFF(g25622) +g1008 = DFF(g25623) +g1002 = DFF(g28057) +g1018 = DFF(g30337) +g1024 = DFF(g31869) +g1030 = DFF(g32983) +g1036 = DFF(g33541) +g1041 = DFF(g25624) +g1046 = DFF(g26913) +g1146 = DFF(g24233) +g1152 = DFF(g24234) +g1099 = DFF(g24235) +g1094 = DFF(g29231) +g1135 = DFF(g26917) +g1111 = DFF(g29234) +g1105 = DFF(g26915) +g1124 = DFF(g29232) +g1129 = DFF(g26916) +g1141 = DFF(g29233) +g956 = DFF(g25626) +g947 = DFF(g34601) +g952 = DFF(g34726) +g939 = DFF(g34727) +g943 = DFF(g34728) +g967 = DFF(g21722) +g968 = DFF(g21723) +g1592 = DFF(g33544) +g1644 = DFF(g33551) +g1636 = DFF(g33545) +g1668 = DFF(g33546) +g1682 = DFF(g33971) +g1687 = DFF(g33547) +g1604 = DFF(g33972) +g1600 = DFF(g33966) +g1608 = DFF(g33967) +g1620 = DFF(g33970) +g1616 = DFF(g33969) +g1612 = DFF(g33968) +g1632 = DFF(g30348) +g1624 = DFF(g32987) +g1648 = DFF(g32988) +g1664 = DFF(g32990) +g1657 = DFF(g32989) +g1677 = DFF(g29240) +g1691 = DFF(g29241) +g1696 = DFF(g30349) +g1700 = DFF(g30350) +g1706 = DFF(g33548) +g1710 = DFF(g33549) +g1714 = DFF(g33550) +g1720 = DFF(g30351) +g1724 = DFF(g30352) +g1728 = DFF(g33552) +g1779 = DFF(g33559) +g1772 = DFF(g33553) +g1802 = DFF(g33554) +g1816 = DFF(g33978) +g1821 = DFF(g33555) +g1740 = DFF(g33979) +g1736 = DFF(g33973) +g1744 = DFF(g33974) +g1756 = DFF(g33977) +g1752 = DFF(g33976) +g1748 = DFF(g33975) +g1768 = DFF(g30353) +g1760 = DFF(g32991) +g1783 = DFF(g32992) +g1798 = DFF(g32994) +g1792 = DFF(g32993) +g1811 = DFF(g29242) +g1825 = DFF(g29243) +g1830 = DFF(g30354) +g1834 = DFF(g30355) +g1840 = DFF(g33556) +g1844 = DFF(g33557) +g1848 = DFF(g33558) +g1854 = DFF(g30356) +g1858 = DFF(g30357) +g1862 = DFF(g33560) +g1913 = DFF(g33567) +g1906 = DFF(g33561) +g1936 = DFF(g33562) +g1950 = DFF(g33985) +g1955 = DFF(g33563) +g1874 = DFF(g33986) +g1870 = DFF(g33980) +g1878 = DFF(g33981) +g1890 = DFF(g33984) +g1886 = DFF(g33983) +g1882 = DFF(g33982) +g1902 = DFF(g30358) +g1894 = DFF(g32995) +g1917 = DFF(g32996) +g1932 = DFF(g32998) +g1926 = DFF(g32997) +g1945 = DFF(g29244) +g1959 = DFF(g29245) +g1964 = DFF(g30359) +g1968 = DFF(g30360) +g1974 = DFF(g33564) +g1978 = DFF(g33565) +g1982 = DFF(g33566) +g1988 = DFF(g30361) +g1992 = DFF(g30362) +g1996 = DFF(g33568) +g2047 = DFF(g33575) +g2040 = DFF(g33569) +g2070 = DFF(g33570) +g2084 = DFF(g33992) +g2089 = DFF(g33571) +g2008 = DFF(g33993) +g2004 = DFF(g33987) +g2012 = DFF(g33988) +g2024 = DFF(g33991) +g2020 = DFF(g33990) +g2016 = DFF(g33989) +g2036 = DFF(g30363) +g2028 = DFF(g32999) +g2051 = DFF(g33000) +g2066 = DFF(g33002) +g2060 = DFF(g33001) +g2079 = DFF(g29246) +g2093 = DFF(g29247) +g2098 = DFF(g30364) +g2102 = DFF(g30365) +g2108 = DFF(g33572) +g2112 = DFF(g33573) +g2116 = DFF(g33574) +g2122 = DFF(g30366) +g2126 = DFF(g30367) +g2130 = DFF(g34603) +g2138 = DFF(g34604) +g2145 = DFF(g34605) +g2151 = DFF(g18421) +g2152 = DFF(g18422) +g2153 = DFF(g33576) +g2204 = DFF(g33583) +g2197 = DFF(g33577) +g2227 = DFF(g33578) +g2241 = DFF(g33999) +g2246 = DFF(g33579) +g2165 = DFF(g34000) +g2161 = DFF(g33994) +g2169 = DFF(g33995) +g2181 = DFF(g33998) +g2177 = DFF(g33997) +g2173 = DFF(g33996) +g2193 = DFF(g30368) +g2185 = DFF(g33003) +g2208 = DFF(g33004) +g2223 = DFF(g33006) +g2217 = DFF(g33005) +g2236 = DFF(g29248) +g2250 = DFF(g29249) +g2255 = DFF(g30369) +g2259 = DFF(g30370) +g2265 = DFF(g33580) +g2269 = DFF(g33581) +g2273 = DFF(g33582) +g2279 = DFF(g30371) +g2283 = DFF(g30372) +g2287 = DFF(g33584) +g2338 = DFF(g33591) +g2331 = DFF(g33585) +g2361 = DFF(g33586) +g2375 = DFF(g34006) +g2380 = DFF(g33587) +g2299 = DFF(g34007) +g2295 = DFF(g34001) +g2303 = DFF(g34002) +g2315 = DFF(g34005) +g2311 = DFF(g34004) +g2307 = DFF(g34003) +g2327 = DFF(g30373) +g2319 = DFF(g33007) +g2342 = DFF(g33008) +g2357 = DFF(g33010) +g2351 = DFF(g33009) +g2370 = DFF(g29250) +g2384 = DFF(g29251) +g2389 = DFF(g30374) +g2393 = DFF(g30375) +g2399 = DFF(g33588) +g2403 = DFF(g33589) +g2407 = DFF(g33590) +g2413 = DFF(g30376) +g2417 = DFF(g30377) +g2421 = DFF(g33592) +g2472 = DFF(g33599) +g2465 = DFF(g33593) +g2495 = DFF(g33594) +g2509 = DFF(g34013) +g2514 = DFF(g33595) +g2433 = DFF(g34014) +g2429 = DFF(g34008) +g2437 = DFF(g34009) +g2449 = DFF(g34012) +g2445 = DFF(g34011) +g2441 = DFF(g34010) +g2461 = DFF(g30378) +g2453 = DFF(g33011) +g2476 = DFF(g33012) +g2491 = DFF(g33014) +g2485 = DFF(g33013) +g2504 = DFF(g29252) +g2518 = DFF(g29253) +g2523 = DFF(g30379) +g2527 = DFF(g30380) +g2533 = DFF(g33596) +g2537 = DFF(g33597) +g2541 = DFF(g33598) +g2547 = DFF(g30381) +g2551 = DFF(g30382) +g2555 = DFF(g33600) +g2606 = DFF(g33607) +g2599 = DFF(g33601) +g2629 = DFF(g33602) +g2643 = DFF(g34020) +g2648 = DFF(g33603) +g2567 = DFF(g34021) +g2563 = DFF(g34015) +g2571 = DFF(g34016) +g2583 = DFF(g34019) +g2579 = DFF(g34018) +g2575 = DFF(g34017) +g2595 = DFF(g30383) +g2587 = DFF(g33015) +g2610 = DFF(g33016) +g2625 = DFF(g33018) +g2619 = DFF(g33017) +g2638 = DFF(g29254) +g2652 = DFF(g29255) +g2657 = DFF(g30384) +g2661 = DFF(g30385) +g2667 = DFF(g33604) +g2671 = DFF(g33605) +g2675 = DFF(g33606) +g2681 = DFF(g30386) +g2685 = DFF(g30387) +g2689 = DFF(g34606) +g2697 = DFF(g34607) +g2704 = DFF(g34608) +g2710 = DFF(g18527) +g2711 = DFF(g18528) +g2837 = DFF(g26935) +g2841 = DFF(g26936) +g2712 = DFF(g26937) +g2715 = DFF(g24263) +g2719 = DFF(g25639) +g2724 = DFF(g26926) +g2729 = DFF(g28060) +g2735 = DFF(g29256) +g2741 = DFF(g30388) +g2748 = DFF(g31872) +g2756 = DFF(g33019) +g2759 = DFF(g33608) +g2763 = DFF(g34022) +g2767 = DFF(g26927) +g2779 = DFF(g26928) +g2791 = DFF(g26929) +g2795 = DFF(g26930) +g2787 = DFF(g34444) +g2783 = DFF(g34442) +g2775 = DFF(g34443) +g2771 = DFF(g34441) +g2831 = DFF(g30391) +g121 = DFF(g30389) +g2799 = DFF(g26931) +g2811 = DFF(g26932) +g2823 = DFF(g26933) +g2827 = DFF(g26934) +g2819 = DFF(g34448) +g2815 = DFF(g34446) +g2807 = DFF(g34447) +g2803 = DFF(g34445) +g2834 = DFF(g30392) +g117 = DFF(g30390) +g2999 = DFF(g34805) +g2994 = DFF(g34732) +g2988 = DFF(g34624) +g2868 = DFF(g34616) +g2873 = DFF(g34615) +g2890 = DFF(g34799) +g2844 = DFF(g34609) +g2852 = DFF(g34610) +g2860 = DFF(g34611) +g2894 = DFF(g34612) +g37 = DFF(g34613) +g94 = DFF(g34614) +g2848 = DFF(g34792) +g2856 = DFF(g34793) +g2864 = DFF(g34794) +g2898 = DFF(g34795) +g2882 = DFF(g34796) +g2878 = DFF(g34797) +g2886 = DFF(g34798) +g2980 = DFF(g34800) +g2984 = DFF(g34980) +g2907 = DFF(g34617) +g2912 = DFF(g34618) +g2922 = DFF(g34619) +g2936 = DFF(g34620) +g2950 = DFF(g34621) +g2960 = DFF(g34622) +g2970 = DFF(g34623) +g2902 = DFF(g34801) +g2917 = DFF(g34802) +g2927 = DFF(g34803) +g2941 = DFF(g34806) +g2955 = DFF(g34807) +g2965 = DFF(g34808) +g2975 = DFF(g34804) +g3003 = DFF(g21726) +g5 = DFF(g12833) +g6 = DFF(g34589) +g7 = DFF(g34590) +g8 = DFF(g34591) +g9 = DFF(g34592) +g16 = DFF(g34593) +g19 = DFF(g34594) +g28 = DFF(g34595) +g31 = DFF(g34596) +g34 = DFF(g34877) +g12 = DFF(g30326) +g22 = DFF(g29209) +g25 = DFF(g15048) + +I11617 = NOT(g1) +g6754 = NOT(I11617) +I11620 = NOT(g1) +g6755 = NOT(I11620) +I11623 = NOT(g28) +g6756 = NOT(I11623) +I11626 = NOT(g31) +g6767 = NOT(I11626) +I11629 = NOT(g19) +g6772 = NOT(I11629) +I11632 = NOT(g16) +g6782 = NOT(I11632) +I11635 = NOT(g9) +g6789 = NOT(I11635) +g6799 = NOT(g199) +g6800 = NOT(g203) +g6801 = NOT(g391) +g6802 = NOT(g468) +g6803 = NOT(g496) +g6804 = NOT(g490) +g6808 = NOT(g554) +g6809 = NOT(g341) +g6810 = NOT(g723) +g6811 = NOT(g714) +g6814 = NOT(g632) +g6815 = NOT(g929) +g6816 = NOT(g933) +g6817 = NOT(g956) +g6818 = NOT(g976) +g6819 = NOT(g1046) +g6820 = NOT(g1070) +I11655 = NOT(g1246) +g6821 = NOT(I11655) +g6825 = NOT(g979) +g6826 = NOT(g218) +g6827 = NOT(g1277) +g6828 = NOT(g1300) +g6829 = NOT(g1319) +g6830 = NOT(g1389) +g6831 = NOT(g1413) +I11665 = NOT(g1589) +g6832 = NOT(I11665) +g6836 = NOT(g1322) +g6837 = NOT(g968) +g6838 = NOT(g1724) +g6839 = NOT(g1858) +g6840 = NOT(g1992) +g6841 = NOT(g2145) +g6845 = NOT(g2126) +g6846 = NOT(g2152) +g6847 = NOT(g2283) +g6848 = NOT(g2417) +g6849 = NOT(g2551) +g6850 = NOT(g2704) +g6854 = NOT(g2685) +g6855 = NOT(g2711) +I11682 = NOT(g2756) +g6856 = NOT(I11682) +I11685 = NOT(g117) +g6867 = NOT(I11685) +I11688 = NOT(g70) +g6868 = NOT(I11688) +I11691 = NOT(g36) +g6869 = NOT(I11691) +g6870 = NOT(g3089) +g6873 = NOT(g3151) +g6874 = NOT(g3143) +I11697 = NOT(g3352) +g6875 = NOT(I11697) +g6887 = NOT(g3333) +I11701 = NOT(g4164) +g6888 = NOT(I11701) +g6895 = NOT(g3288) +g6900 = NOT(g3440) +g6903 = NOT(g3502) +g6904 = NOT(g3494) +I11708 = NOT(g3703) +g6905 = NOT(I11708) +g6917 = NOT(g3684) +g6918 = NOT(g3639) +g6923 = NOT(g3791) +g6926 = NOT(g3853) +g6927 = NOT(g3845) +I11716 = NOT(g4054) +g6928 = NOT(I11716) +g6940 = NOT(g4035) +g6941 = NOT(g3990) +I11721 = NOT(g4145) +g6946 = NOT(I11721) +g6953 = NOT(g4157) +g6954 = NOT(g4138) +I11726 = NOT(g4273) +g6955 = NOT(I11726) +g6956 = NOT(g4242) +g6957 = NOT(g2932) +g6958 = NOT(g4372) +g6959 = NOT(g4420) +g6960 = NOT(g1) +I11734 = NOT(g4473) +g6961 = NOT(I11734) +I11737 = NOT(g4467) +g6971 = NOT(I11737) +I11740 = NOT(g4519) +g6972 = NOT(I11740) +I11743 = NOT(g4564) +g6973 = NOT(I11743) +I11746 = NOT(g4570) +g6974 = NOT(I11746) +g6975 = NOT(g4507) +I11750 = NOT(g4474) +g6976 = NOT(I11750) +I11753 = NOT(g4492) +g6977 = NOT(I11753) +g6978 = NOT(g4616) +g6982 = NOT(g4531) +g6983 = NOT(g4698) +g6984 = NOT(g4709) +g6985 = NOT(g4669) +g6986 = NOT(g4743) +g6987 = NOT(g4754) +g6988 = NOT(g4765) +g6989 = NOT(g4575) +g6990 = NOT(g4742) +g6991 = NOT(g4888) +g6992 = NOT(g4899) +g6993 = NOT(g4859) +g6994 = NOT(g4933) +g6995 = NOT(g4944) +g6996 = NOT(g4955) +g6997 = NOT(g4578) +g6998 = NOT(g4932) +g6999 = NOT(g86) +g7002 = NOT(g5160) +g7003 = NOT(g5152) +I11777 = NOT(g5357) +g7004 = NOT(I11777) +g7017 = NOT(g128) +g7018 = NOT(g5297) +g7023 = NOT(g5445) +g7026 = NOT(g5507) +g7027 = NOT(g5499) +I11785 = NOT(g5703) +g7028 = NOT(I11785) +g7040 = NOT(g4821) +g7041 = NOT(g5644) +g7046 = NOT(g5791) +g7049 = NOT(g5853) +g7050 = NOT(g5845) +I11793 = NOT(g6049) +g7051 = NOT(I11793) +g7063 = NOT(g4831) +g7064 = NOT(g5990) +g7069 = NOT(g6137) +g7072 = NOT(g6199) +g7073 = NOT(g6191) +I11801 = NOT(g6395) +g7074 = NOT(I11801) +g7086 = NOT(g4826) +g7087 = NOT(g6336) +g7092 = NOT(g6483) +g7095 = NOT(g6545) +g7096 = NOT(g6537) +I11809 = NOT(g6741) +g7097 = NOT(I11809) +g7109 = NOT(g5011) +g7110 = NOT(g6682) +g7115 = NOT(g12) +g7116 = NOT(g22) +I11816 = NOT(g93) +g7117 = NOT(I11816) +g7118 = NOT(g832) +I11820 = NOT(g3869) +g7121 = NOT(I11820) +g7132 = NOT(g4558) +g7134 = NOT(g5029) +g7138 = NOT(g5360) +I11835 = NOT(g101) +g7148 = NOT(I11835) +g7149 = NOT(g4564) +g7153 = NOT(g5373) +g7157 = NOT(g5706) +I11843 = NOT(g111) +g7161 = NOT(I11843) +g7162 = NOT(g4521) +g7163 = NOT(g4593) +g7166 = NOT(g4311) +g7170 = NOT(g5719) +g7174 = NOT(g6052) +g7178 = NOT(g4392) +g7183 = NOT(g4608) +g7187 = NOT(g6065) +g7191 = NOT(g6398) +g7195 = NOT(g25) +I11860 = NOT(g43) +g7196 = NOT(I11860) +g7197 = NOT(g812) +g7202 = NOT(g4639) +g7212 = NOT(g6411) +g7216 = NOT(g822) +g7219 = NOT(g4405) +g7222 = NOT(g4427) +g7224 = NOT(g4601) +g7231 = NOT(g5) +g7232 = NOT(g4411) +g7235 = NOT(g4521) +g7236 = NOT(g4608) +g7239 = NOT(g5033) +I11892 = NOT(g4408) +g7243 = NOT(I11892) +g7244 = NOT(g4408) +I11896 = NOT(g4446) +g7245 = NOT(I11896) +g7246 = NOT(g4446) +g7247 = NOT(g5377) +g7252 = NOT(g1592) +I11903 = NOT(g4414) +g7257 = NOT(I11903) +g7258 = NOT(g4414) +g7259 = NOT(g4375) +I11908 = NOT(g4449) +g7260 = NOT(I11908) +g7261 = NOT(g4449) +g7262 = NOT(g5723) +g7266 = NOT(g35) +g7267 = NOT(g1604) +g7268 = NOT(g1636) +g7275 = NOT(g1728) +g7280 = NOT(g2153) +g7285 = NOT(g4643) +g7289 = NOT(g4382) +g7293 = NOT(g4452) +g7296 = NOT(g5313) +g7297 = NOT(g6069) +g7301 = NOT(g925) +g7308 = NOT(g1668) +g7314 = NOT(g1740) +g7315 = NOT(g1772) +g7322 = NOT(g1862) +g7327 = NOT(g2165) +g7328 = NOT(g2197) +g7335 = NOT(g2287) +g7340 = NOT(g4443) +g7343 = NOT(g5290) +g7344 = NOT(g5659) +g7345 = NOT(g6415) +g7349 = NOT(g1270) +g7356 = NOT(g1802) +g7361 = NOT(g1874) +g7362 = NOT(g1906) +g7369 = NOT(g1996) +g7374 = NOT(g2227) +g7379 = NOT(g2299) +g7380 = NOT(g2331) +g7387 = NOT(g2421) +g7392 = NOT(g4438) +g7393 = NOT(g5320) +g7394 = NOT(g5637) +g7395 = NOT(g6005) +g7397 = NOT(g890) +g7400 = NOT(g911) +g7405 = NOT(g1936) +g7410 = NOT(g2008) +g7411 = NOT(g2040) +g7418 = NOT(g2361) +g7423 = NOT(g2433) +g7424 = NOT(g2465) +g7431 = NOT(g2555) +g7436 = NOT(g5276) +g7437 = NOT(g5666) +g7438 = NOT(g5983) +g7439 = NOT(g6351) +g7440 = NOT(g329) +g7441 = NOT(g862) +g7443 = NOT(g914) +g7446 = NOT(g1256) +g7451 = NOT(g2070) +g7456 = NOT(g2495) +g7461 = NOT(g2567) +g7462 = NOT(g2599) +g7470 = NOT(g5623) +g7471 = NOT(g6012) +g7472 = NOT(g6329) +g7473 = NOT(g6697) +I11980 = NOT(g66) +g7474 = NOT(I11980) +g7475 = NOT(g896) +g7479 = NOT(g1008) +g7487 = NOT(g1259) +g7490 = NOT(g2629) +g7495 = NOT(g4375) +g7496 = NOT(g5969) +g7497 = NOT(g6358) +g7498 = NOT(g6675) +I11992 = NOT(g763) +g7502 = NOT(I11992) +g7503 = NOT(g1351) +g7512 = NOT(g5283) +g7513 = NOT(g6315) +g7514 = NOT(g6704) +I12000 = NOT(g582) +g7515 = NOT(I12000) +I12003 = NOT(g767) +g7516 = NOT(I12003) +g7517 = NOT(g962) +g7518 = NOT(g1024) +g7519 = NOT(g1157) +g7521 = NOT(g5630) +g7522 = NOT(g6661) +g7523 = NOT(g305) +I12013 = NOT(g590) +g7526 = NOT(I12013) +I12016 = NOT(g772) +g7527 = NOT(I12016) +g7528 = NOT(g930) +g7532 = NOT(g1157) +g7533 = NOT(g1306) +g7534 = NOT(g1367) +g7535 = NOT(g1500) +g7536 = NOT(g5976) +g7537 = NOT(g311) +I12026 = NOT(g344) +g7540 = NOT(I12026) +g7541 = NOT(g344) +I12030 = NOT(g595) +g7542 = NOT(I12030) +I12033 = NOT(g776) +g7543 = NOT(I12033) +g7544 = NOT(g918) +g7548 = NOT(g1036) +g7553 = NOT(g1274) +g7557 = NOT(g1500) +I12041 = NOT(g2741) +g7558 = NOT(I12041) +g7563 = NOT(g6322) +g7564 = NOT(g336) +I12046 = NOT(g613) +g7565 = NOT(I12046) +I12049 = NOT(g781) +g7566 = NOT(I12049) +g7577 = NOT(g1263) +g7581 = NOT(g1379) +I12056 = NOT(g2748) +g7586 = NOT(I12056) +g7591 = NOT(g6668) +g7592 = NOT(g347) +I12061 = NOT(g562) +g7593 = NOT(I12061) +I12064 = NOT(g617) +g7594 = NOT(I12064) +I12067 = NOT(g739) +g7595 = NOT(I12067) +I12070 = NOT(g785) +g7596 = NOT(I12070) +g7597 = NOT(g952) +I12083 = NOT(g568) +g7615 = NOT(I12083) +I12086 = NOT(g622) +g7616 = NOT(I12086) +I12089 = NOT(g744) +g7617 = NOT(I12089) +I12092 = NOT(g790) +g7618 = NOT(I12092) +g7619 = NOT(g1296) +I12103 = NOT(g572) +g7623 = NOT(I12103) +I12106 = NOT(g626) +g7624 = NOT(I12106) +I12109 = NOT(g749) +g7625 = NOT(I12109) +I12112 = NOT(g794) +g7626 = NOT(I12112) +g7627 = NOT(g4311) +g7631 = NOT(g74) +I12117 = NOT(g586) +g7632 = NOT(I12117) +I12120 = NOT(g632) +g7633 = NOT(I12120) +I12123 = NOT(g758) +g7634 = NOT(I12123) +g7635 = NOT(g1002) +g7636 = NOT(g4098) +I12128 = NOT(g4253) +g7640 = NOT(I12128) +g7643 = NOT(g4322) +I12132 = NOT(g577) +g7647 = NOT(I12132) +I12135 = NOT(g807) +g7648 = NOT(I12135) +g7649 = NOT(g1345) +g7650 = NOT(g4064) +g7655 = NOT(g4332) +I12141 = NOT(g599) +g7659 = NOT(I12141) +I12144 = NOT(g554) +g7660 = NOT(I12144) +g7666 = NOT(g4076) +g7670 = NOT(g4104) +I12151 = NOT(g604) +g7674 = NOT(I12151) +g7680 = NOT(g4108) +g7686 = NOT(g4659) +I12159 = NOT(g608) +g7689 = NOT(I12159) +g7693 = NOT(g4849) +g7697 = NOT(g4087) +I12167 = NOT(g5176) +g7704 = NOT(I12167) +g7715 = NOT(g1178) +g7716 = NOT(g1199) +I12172 = NOT(g2715) +g7717 = NOT(I12172) +g7733 = NOT(g4093) +I12176 = NOT(g5523) +g7738 = NOT(I12176) +g7749 = NOT(g996) +g7750 = NOT(g1070) +g7751 = NOT(g1521) +g7752 = NOT(g1542) +I12183 = NOT(g2719) +g7753 = NOT(I12183) +g7765 = NOT(g4165) +I12189 = NOT(g5869) +g7766 = NOT(I12189) +g7778 = NOT(g1339) +g7779 = NOT(g1413) +g7780 = NOT(g2878) +g7785 = NOT(g4621) +g7788 = NOT(g4674) +I12199 = NOT(g6215) +g7791 = NOT(I12199) +g7802 = NOT(g324) +g7805 = NOT(g4366) +g7806 = NOT(g4681) +g7809 = NOT(g4864) +I12214 = NOT(g6561) +g7812 = NOT(I12214) +g7824 = NOT(g4169) +g7827 = NOT(g4688) +g7828 = NOT(g4871) +I12227 = NOT(g34) +g7831 = NOT(I12227) +g7835 = NOT(g4125) +g7840 = NOT(g4878) +g7841 = NOT(g904) +g7845 = NOT(g1146) +g7851 = NOT(g921) +g7854 = NOT(g1152) +g7858 = NOT(g947) +g7863 = NOT(g1249) +g7867 = NOT(g1489) +g7868 = NOT(g1099) +g7870 = NOT(g1193) +g7873 = NOT(g1266) +g7876 = NOT(g1495) +g7880 = NOT(g1291) +g7886 = NOT(g1442) +g7888 = NOT(g1536) +g7891 = NOT(g2994) +g7892 = NOT(g4801) +g7898 = NOT(g4991) +g7903 = NOT(g969) +g7907 = NOT(g3072) +g7908 = NOT(g4157) +g7909 = NOT(g936) +g7913 = NOT(g1052) +I12300 = NOT(g1157) +g7916 = NOT(I12300) +g7917 = NOT(g1157) +g7922 = NOT(g1312) +g7926 = NOT(g3423) +g7927 = NOT(g4064) +g7928 = NOT(g4776) +g7933 = NOT(g907) +g7936 = NOT(g1061) +g7939 = NOT(g1280) +g7943 = NOT(g1395) +I12314 = NOT(g1500) +g7946 = NOT(I12314) +g7947 = NOT(g1500) +g7952 = NOT(g3774) +g7953 = NOT(g4966) +g7957 = NOT(g1252) +g7960 = NOT(g1404) +g7963 = NOT(g4146) +g7964 = NOT(g3155) +g7970 = NOT(g4688) +g7971 = NOT(g4818) +g7972 = NOT(g1046) +g7975 = NOT(g3040) +g7980 = NOT(g3161) +g7985 = NOT(g3506) +g7991 = NOT(g4878) +g7992 = NOT(g5008) +I12333 = NOT(g45) +g7993 = NOT(I12333) +I12336 = NOT(g52) +g7994 = NOT(I12336) +g7995 = NOT(g153) +g7998 = NOT(g392) +g8002 = NOT(g1389) +g8005 = NOT(g3025) +g8009 = NOT(g3106) +g8011 = NOT(g3167) +g8016 = NOT(g3391) +g8021 = NOT(g3512) +g8026 = NOT(g3857) +I12355 = NOT(g46) +g8032 = NOT(I12355) +g8033 = NOT(g157) +g8037 = NOT(g405) +I12360 = NOT(g528) +g8038 = NOT(I12360) +g8046 = NOT(g528) +g8052 = NOT(g1211) +g8055 = NOT(g1236) +g8056 = NOT(g1246) +g8057 = NOT(g3068) +g8058 = NOT(g3115) +g8059 = NOT(g3171) +g8064 = NOT(g3376) +g8068 = NOT(g3457) +g8070 = NOT(g3518) +g8075 = NOT(g3742) +g8080 = NOT(g3863) +I12382 = NOT(g47) +g8085 = NOT(I12382) +g8087 = NOT(g1157) +g8088 = NOT(g1554) +g8091 = NOT(g1579) +g8092 = NOT(g1589) +g8093 = NOT(g1624) +g8097 = NOT(g3029) +g8102 = NOT(g3072) +g8106 = NOT(g3133) +g8107 = NOT(g3179) +g8112 = NOT(g3419) +g8113 = NOT(g3466) +g8114 = NOT(g3522) +g8119 = NOT(g3727) +g8123 = NOT(g3808) +g8125 = NOT(g3869) +g8130 = NOT(g4515) +I12411 = NOT(g4809) +g8132 = NOT(I12411) +g8133 = NOT(g4809) +I12415 = NOT(g48) +g8134 = NOT(I12415) +I12418 = NOT(g55) +g8135 = NOT(I12418) +g8136 = NOT(g269) +g8137 = NOT(g411) +g8138 = NOT(g1500) +g8139 = NOT(g1648) +g8146 = NOT(g1760) +g8150 = NOT(g2185) +g8154 = NOT(g3139) +g8155 = NOT(g3380) +g8160 = NOT(g3423) +g8164 = NOT(g3484) +g8165 = NOT(g3530) +g8170 = NOT(g3770) +g8171 = NOT(g3817) +g8172 = NOT(g3873) +I12437 = NOT(g4999) +g8178 = NOT(I12437) +g8179 = NOT(g4999) +g8180 = NOT(g262) +g8181 = NOT(g424) +g8183 = NOT(g482) +g8186 = NOT(g990) +g8187 = NOT(g1657) +g8195 = NOT(g1783) +g8201 = NOT(g1894) +g8205 = NOT(g2208) +g8211 = NOT(g2319) +I12451 = NOT(g3092) +g8215 = NOT(I12451) +g8216 = NOT(g3092) +g8217 = NOT(g3143) +g8218 = NOT(g3490) +g8219 = NOT(g3731) +g8224 = NOT(g3774) +g8228 = NOT(g3835) +g8229 = NOT(g3881) +I12463 = NOT(g4812) +g8235 = NOT(I12463) +g8236 = NOT(g4812) +g8237 = NOT(g255) +g8239 = NOT(g1056) +g8240 = NOT(g1333) +g8241 = NOT(g1792) +g8249 = NOT(g1917) +g8255 = NOT(g2028) +g8259 = NOT(g2217) +g8267 = NOT(g2342) +g8273 = NOT(g2453) +I12483 = NOT(g3096) +g8277 = NOT(I12483) +g8278 = NOT(g3096) +I12487 = NOT(g3443) +g8279 = NOT(I12487) +g8280 = NOT(g3443) +g8281 = NOT(g3494) +g8282 = NOT(g3841) +I12493 = NOT(g5002) +g8283 = NOT(I12493) +g8284 = NOT(g5002) +I12497 = NOT(g49) +g8285 = NOT(I12497) +g8286 = NOT(g53) +g8287 = NOT(g160) +g8290 = NOT(g218) +I12503 = NOT(g215) +g8291 = NOT(I12503) +g8296 = NOT(g246) +g8297 = NOT(g142) +g8300 = NOT(g1242) +g8301 = NOT(g1399) +g8302 = NOT(g1926) +g8310 = NOT(g2051) +g8316 = NOT(g2351) +g8324 = NOT(g2476) +g8330 = NOT(g2587) +g8334 = NOT(g3034) +g8340 = NOT(g3050) +g8341 = NOT(g3119) +I12519 = NOT(g3447) +g8342 = NOT(I12519) +g8343 = NOT(g3447) +I12523 = NOT(g3794) +g8344 = NOT(I12523) +g8345 = NOT(g3794) +g8346 = NOT(g3845) +g8350 = NOT(g4646) +I12530 = NOT(g4815) +g8353 = NOT(I12530) +g8354 = NOT(g4815) +I12534 = NOT(g50) +g8355 = NOT(I12534) +g8356 = NOT(g54) +I12538 = NOT(g58) +g8357 = NOT(I12538) +I12541 = NOT(g194) +g8358 = NOT(I12541) +g8362 = NOT(g194) +g8363 = NOT(g239) +g8364 = NOT(g1585) +g8365 = NOT(g2060) +g8373 = NOT(g2485) +g8381 = NOT(g2610) +g8387 = NOT(g3080) +g8388 = NOT(g3010) +g8389 = NOT(g3125) +g8390 = NOT(g3385) +g8396 = NOT(g3401) +g8397 = NOT(g3470) +I12563 = NOT(g3798) +g8398 = NOT(I12563) +g8399 = NOT(g3798) +g8400 = NOT(g4836) +I12568 = NOT(g5005) +g8403 = NOT(I12568) +g8404 = NOT(g5005) +I12572 = NOT(g51) +g8405 = NOT(I12572) +g8406 = NOT(g232) +g8407 = NOT(g1171) +I12577 = NOT(g1227) +g8411 = NOT(I12577) +I12580 = NOT(g1239) +g8416 = NOT(I12580) +g8418 = NOT(g2619) +g8426 = NOT(g3045) +g8431 = NOT(g3085) +g8438 = NOT(g3100) +g8439 = NOT(g3129) +g8440 = NOT(g3431) +g8441 = NOT(g3361) +g8442 = NOT(g3476) +g8443 = NOT(g3736) +g8449 = NOT(g3752) +g8450 = NOT(g3821) +g8451 = NOT(g4057) +g8456 = NOT(g56) +g8457 = NOT(g225) +g8458 = NOT(g294) +g8462 = NOT(g1183) +g8466 = NOT(g1514) +I12605 = NOT(g1570) +g8470 = NOT(I12605) +I12608 = NOT(g1582) +g8475 = NOT(I12608) +g8477 = NOT(g3061) +g8478 = NOT(g3103) +g8479 = NOT(g3057) +g8480 = NOT(g3147) +I12618 = NOT(g3338) +g8481 = NOT(I12618) +g8492 = NOT(g3396) +g8497 = NOT(g3436) +g8504 = NOT(g3451) +g8505 = NOT(g3480) +g8506 = NOT(g3782) +g8507 = NOT(g3712) +g8508 = NOT(g3827) +g8509 = NOT(g4141) +g8514 = NOT(g4258) +I12631 = NOT(g1242) +g8515 = NOT(I12631) +g8519 = NOT(g287) +g8522 = NOT(g298) +g8526 = NOT(g1526) +g8531 = NOT(g3288) +g8534 = NOT(g3338) +g8538 = NOT(g3412) +g8539 = NOT(g3454) +g8540 = NOT(g3408) +g8541 = NOT(g3498) +I12644 = NOT(g3689) +g8542 = NOT(I12644) +g8553 = NOT(g3747) +g8558 = NOT(g3787) +g8565 = NOT(g3802) +g8566 = NOT(g3831) +g8567 = NOT(g4082) +g8571 = NOT(g57) +I12654 = NOT(g1585) +g8572 = NOT(I12654) +g8575 = NOT(g291) +g8579 = NOT(g2771) +g8584 = NOT(g3639) +g8587 = NOT(g3689) +g8591 = NOT(g3763) +g8592 = NOT(g3805) +g8593 = NOT(g3759) +g8594 = NOT(g3849) +I12666 = NOT(g4040) +g8595 = NOT(I12666) +g8606 = NOT(g4653) +g8607 = NOT(g37) +g8608 = NOT(g278) +g8612 = NOT(g2775) +g8616 = NOT(g2803) +g8620 = NOT(g3065) +g8623 = NOT(g3990) +g8626 = NOT(g4040) +g8630 = NOT(g4843) +g8631 = NOT(g283) +g8635 = NOT(g2783) +g8639 = NOT(g2807) +g8644 = NOT(g3352) +g8647 = NOT(g3416) +g8650 = NOT(g4664) +g8651 = NOT(g758) +g8654 = NOT(g1087) +g8655 = NOT(g2787) +g8659 = NOT(g2815) +g8663 = NOT(g3343) +g8666 = NOT(g3703) +g8669 = NOT(g3767) +g8672 = NOT(g4669) +g8673 = NOT(g4737) +g8676 = NOT(g4821) +g8677 = NOT(g4854) +g8680 = NOT(g686) +g8681 = NOT(g763) +g8685 = NOT(g1430) +g8686 = NOT(g2819) +g8696 = NOT(g3347) +g8697 = NOT(g3694) +g8700 = NOT(g4054) +I12709 = NOT(g4284) +g8703 = NOT(I12709) +I12712 = NOT(g59) +g8712 = NOT(I12712) +g8713 = NOT(g4826) +g8714 = NOT(g4859) +g8715 = NOT(g4927) +g8718 = NOT(g3333) +I12719 = NOT(g365) +g8719 = NOT(I12719) +g8725 = NOT(g739) +g8733 = NOT(g3698) +g8734 = NOT(g4045) +I12735 = NOT(g4572) +g8740 = NOT(I12735) +g8741 = NOT(g4821) +g8742 = NOT(g4035) +g8743 = NOT(g550) +g8744 = NOT(g691) +g8745 = NOT(g744) +g8748 = NOT(g776) +g8756 = NOT(g4049) +I12746 = NOT(g4087) +g8757 = NOT(I12746) +I12749 = NOT(g4575) +g8763 = NOT(I12749) +g8764 = NOT(g4826) +g8765 = NOT(g3333) +g8766 = NOT(g572) +g8770 = NOT(g749) +g8774 = NOT(g781) +I12758 = NOT(g4093) +g8778 = NOT(I12758) +I12761 = NOT(g4188) +g8783 = NOT(I12761) +I12764 = NOT(g4194) +g8784 = NOT(I12764) +I12767 = NOT(g4197) +g8785 = NOT(I12767) +I12770 = NOT(g4200) +g8786 = NOT(I12770) +I12773 = NOT(g4204) +g8787 = NOT(I12773) +I12776 = NOT(g4207) +g8788 = NOT(I12776) +I12779 = NOT(g4210) +g8789 = NOT(I12779) +I12787 = NOT(g4311) +g8791 = NOT(I12787) +I12790 = NOT(g4340) +g8792 = NOT(I12790) +I12793 = NOT(g4578) +g8795 = NOT(I12793) +g8796 = NOT(g4785) +g8804 = NOT(g4035) +I12799 = NOT(g59) +g8805 = NOT(I12799) +g8807 = NOT(g79) +g8808 = NOT(g595) +I12805 = NOT(g4098) +g8812 = NOT(I12805) +I12808 = NOT(g4322) +g8818 = NOT(I12808) +I12811 = NOT(g4340) +g8821 = NOT(I12811) +g8822 = NOT(g4975) +g8830 = NOT(g767) +g8833 = NOT(g794) +g8836 = NOT(g736) +I12819 = NOT(g4277) +g8839 = NOT(I12819) +g8840 = NOT(g4277) +I12823 = NOT(g4311) +g8841 = NOT(I12823) +I12826 = NOT(g4349) +g8844 = NOT(I12826) +g8848 = NOT(g358) +g8851 = NOT(g590) +g8854 = NOT(g613) +g8858 = NOT(g671) +g8859 = NOT(g772) +I12837 = NOT(g4222) +g8870 = NOT(I12837) +g8872 = NOT(g4258) +I12855 = NOT(g4311) +g8876 = NOT(I12855) +I12858 = NOT(g4340) +g8879 = NOT(I12858) +I12861 = NOT(g4372) +g8880 = NOT(I12861) +g8883 = NOT(g4709) +g8890 = NOT(g376) +g8891 = NOT(g582) +g8895 = NOT(g599) +g8898 = NOT(g676) +g8899 = NOT(g807) +g8903 = NOT(g1075) +g8912 = NOT(g4180) +g8914 = NOT(g4264) +I12884 = NOT(g4213) +g8915 = NOT(I12884) +I12887 = NOT(g4216) +g8916 = NOT(I12887) +I12890 = NOT(g4219) +g8917 = NOT(I12890) +I12893 = NOT(g4226) +g8918 = NOT(I12893) +I12896 = NOT(g4229) +g8919 = NOT(I12896) +I12899 = NOT(g4232) +g8920 = NOT(I12899) +I12907 = NOT(g4322) +g8922 = NOT(I12907) +I12910 = NOT(g4340) +g8925 = NOT(I12910) +g8928 = NOT(g4340) +g8938 = NOT(g4899) +g8944 = NOT(g370) +g8945 = NOT(g608) +g8948 = NOT(g785) +g8951 = NOT(g554) +g8954 = NOT(g1079) +g8955 = NOT(g1418) +g8964 = NOT(g4269) +I12927 = NOT(g4332) +g8971 = NOT(I12927) +I12930 = NOT(g4349) +g8974 = NOT(I12930) +g8977 = NOT(g4349) +I12935 = NOT(g6753) +g8989 = NOT(I12935) +g8990 = NOT(g146) +g8993 = NOT(g385) +g8997 = NOT(g577) +g9000 = NOT(g632) +g9003 = NOT(g790) +g9007 = NOT(g1083) +g9011 = NOT(g1422) +g9014 = NOT(g3004) +g9018 = NOT(g4273) +I12950 = NOT(g4287) +g9019 = NOT(I12950) +g9020 = NOT(g4287) +I12954 = NOT(g4358) +g9021 = NOT(I12954) +g9024 = NOT(g4358) +g9030 = NOT(g4793) +g9036 = NOT(g5084) +g9037 = NOT(g164) +g9040 = NOT(g499) +g9044 = NOT(g604) +I12963 = NOT(g640) +g9048 = NOT(I12963) +g9049 = NOT(g640) +g9050 = NOT(g1087) +g9051 = NOT(g1426) +g9056 = NOT(g3017) +g9060 = NOT(g3355) +g9064 = NOT(g4983) +g9070 = NOT(g5428) +g9071 = NOT(g2831) +g9072 = NOT(g2994) +g9073 = NOT(g150) +g9077 = NOT(g504) +g9083 = NOT(g626) +g9086 = NOT(g847) +g9091 = NOT(g1430) +g9095 = NOT(g3368) +g9099 = NOT(g3706) +g9103 = NOT(g5774) +I12987 = NOT(g12) +g9104 = NOT(I12987) +g9152 = NOT(g2834) +I12991 = NOT(g6752) +g9153 = NOT(I12991) +I12994 = NOT(g6748) +g9154 = NOT(I12994) +I12997 = NOT(g351) +g9155 = NOT(I12997) +g9158 = NOT(g513) +g9162 = NOT(g622) +g9166 = NOT(g837) +g9174 = NOT(g1205) +g9180 = NOT(g3719) +g9184 = NOT(g6120) +I13007 = NOT(g65) +g9185 = NOT(I13007) +I13010 = NOT(g6749) +g9186 = NOT(I13010) +g9187 = NOT(g518) +g9194 = NOT(g827) +g9197 = NOT(g1221) +g9200 = NOT(g1548) +g9206 = NOT(g5164) +g9212 = NOT(g6466) +I13020 = NOT(g6750) +g9213 = NOT(I13020) +g9214 = NOT(g617) +g9220 = NOT(g843) +g9223 = NOT(g1216) +g9226 = NOT(g1564) +g9229 = NOT(g5052) +g9234 = NOT(g5170) +g9239 = NOT(g5511) +I13031 = NOT(g6747) +g9245 = NOT(I13031) +g9247 = NOT(g1559) +g9250 = NOT(g1600) +I13037 = NOT(g4304) +g9251 = NOT(I13037) +g9252 = NOT(g4304) +g9253 = NOT(g5037) +g9257 = NOT(g5115) +g9259 = NOT(g5176) +g9264 = NOT(g5396) +g9269 = NOT(g5517) +g9274 = NOT(g5857) +I13054 = NOT(g6744) +g9280 = NOT(I13054) +I13057 = NOT(g112) +g9281 = NOT(I13057) +g9282 = NOT(g723) +g9283 = NOT(g1736) +g9284 = NOT(g2161) +g9285 = NOT(g2715) +g9291 = NOT(g3021) +g9298 = NOT(g5080) +g9299 = NOT(g5124) +g9300 = NOT(g5180) +g9305 = NOT(g5381) +g9309 = NOT(g5462) +g9311 = NOT(g5523) +g9316 = NOT(g5742) +g9321 = NOT(g5863) +g9326 = NOT(g6203) +g9332 = NOT(g64) +g9333 = NOT(g417) +g9337 = NOT(g1608) +g9338 = NOT(g1870) +g9339 = NOT(g2295) +I13094 = NOT(g2724) +g9340 = NOT(I13094) +g9354 = NOT(g2719) +g9360 = NOT(g3372) +g9364 = NOT(g5041) +g9369 = NOT(g5084) +g9373 = NOT(g5142) +g9374 = NOT(g5188) +g9379 = NOT(g5424) +g9380 = NOT(g5471) +g9381 = NOT(g5527) +g9386 = NOT(g5727) +g9390 = NOT(g5808) +g9392 = NOT(g5869) +g9397 = NOT(g6088) +g9402 = NOT(g6209) +g9407 = NOT(g6549) +g9413 = NOT(g1744) +g9414 = NOT(g2004) +g9415 = NOT(g2169) +g9416 = NOT(g2429) +I13124 = NOT(g2729) +g9417 = NOT(I13124) +g9429 = NOT(g3723) +g9433 = NOT(g5148) +g9434 = NOT(g5385) +g9439 = NOT(g5428) +g9443 = NOT(g5489) +g9444 = NOT(g5535) +g9449 = NOT(g5770) +g9450 = NOT(g5817) +g9451 = NOT(g5873) +g9456 = NOT(g6073) +g9460 = NOT(g6154) +g9462 = NOT(g6215) +g9467 = NOT(g6434) +g9472 = NOT(g6555) +I13149 = NOT(g6745) +g9477 = NOT(I13149) +I13152 = NOT(g6746) +g9478 = NOT(I13152) +g9480 = NOT(g559) +g9484 = NOT(g1612) +g9488 = NOT(g1878) +g9489 = NOT(g2303) +g9490 = NOT(g2563) +g9491 = NOT(g2729) +g9492 = NOT(g2759) +g9496 = NOT(g3303) +I13166 = NOT(g5101) +g9497 = NOT(I13166) +g9498 = NOT(g5101) +g9499 = NOT(g5152) +g9500 = NOT(g5495) +g9501 = NOT(g5731) +g9506 = NOT(g5774) +g9510 = NOT(g5835) +g9511 = NOT(g5881) +g9516 = NOT(g6116) +g9517 = NOT(g6163) +g9518 = NOT(g6219) +g9523 = NOT(g6419) +g9527 = NOT(g6500) +g9529 = NOT(g6561) +g9534 = NOT(g90) +g9537 = NOT(g1748) +g9541 = NOT(g2012) +g9542 = NOT(g2173) +g9546 = NOT(g2437) +g9547 = NOT(g2735) +g9551 = NOT(g3281) +g9552 = NOT(g3654) +I13202 = NOT(g5105) +g9553 = NOT(I13202) +g9554 = NOT(g5105) +I13206 = NOT(g5448) +g9555 = NOT(I13206) +g9556 = NOT(g5448) +g9557 = NOT(g5499) +g9558 = NOT(g5841) +g9559 = NOT(g6077) +g9564 = NOT(g6120) +g9568 = NOT(g6181) +g9569 = NOT(g6227) +g9574 = NOT(g6462) +g9575 = NOT(g6509) +g9576 = NOT(g6565) +g9581 = NOT(g91) +g9582 = NOT(g703) +g9585 = NOT(g1616) +g9590 = NOT(g1882) +g9594 = NOT(g2307) +g9598 = NOT(g2571) +g9599 = NOT(g3310) +g9600 = NOT(g3632) +g9601 = NOT(g4005) +g9607 = NOT(g5046) +g9613 = NOT(g5062) +g9614 = NOT(g5128) +I13236 = NOT(g5452) +g9615 = NOT(I13236) +g9616 = NOT(g5452) +I13240 = NOT(g5794) +g9617 = NOT(I13240) +g9618 = NOT(g5794) +g9619 = NOT(g5845) +g9620 = NOT(g6187) +g9621 = NOT(g6423) +g9626 = NOT(g6466) +g9630 = NOT(g6527) +g9631 = NOT(g6573) +g9636 = NOT(g72) +I13252 = NOT(g6751) +g9637 = NOT(I13252) +g9638 = NOT(g1620) +g9639 = NOT(g1752) +g9644 = NOT(g2016) +g9648 = NOT(g2177) +g9653 = NOT(g2441) +g9657 = NOT(g2763) +g9660 = NOT(g3267) +g9661 = NOT(g3661) +g9662 = NOT(g3983) +g9669 = NOT(g5092) +g9670 = NOT(g5022) +g9671 = NOT(g5134) +g9672 = NOT(g5390) +g9678 = NOT(g5406) +g9679 = NOT(g5475) +I13276 = NOT(g5798) +g9680 = NOT(I13276) +g9681 = NOT(g5798) +I13280 = NOT(g6140) +g9682 = NOT(I13280) +g9683 = NOT(g6140) +g9684 = NOT(g6191) +g9685 = NOT(g6533) +g9686 = NOT(g73) +I13287 = NOT(g110) +g9687 = NOT(I13287) +g9688 = NOT(g113) +g9689 = NOT(g124) +g9690 = NOT(g732) +g9691 = NOT(g1706) +g9692 = NOT(g1756) +g9693 = NOT(g1886) +g9698 = NOT(g2181) +g9699 = NOT(g2311) +g9704 = NOT(g2575) +g9708 = NOT(g2741) +g9713 = NOT(g3618) +g9714 = NOT(g4012) +g9716 = NOT(g5057) +g9721 = NOT(g5097) +g9728 = NOT(g5109) +g9729 = NOT(g5138) +g9730 = NOT(g5436) +g9731 = NOT(g5366) +g9732 = NOT(g5481) +g9733 = NOT(g5736) +g9739 = NOT(g5752) +g9740 = NOT(g5821) +I13317 = NOT(g6144) +g9741 = NOT(I13317) +g9742 = NOT(g6144) +I13321 = NOT(g6486) +g9743 = NOT(I13321) +g9744 = NOT(g6486) +g9745 = NOT(g6537) +I13326 = NOT(g66) +g9746 = NOT(I13326) +I13329 = NOT(g86) +g9747 = NOT(I13329) +g9748 = NOT(g114) +g9749 = NOT(g1691) +g9751 = NOT(g1710) +g9752 = NOT(g1840) +g9753 = NOT(g1890) +g9754 = NOT(g2020) +g9759 = NOT(g2265) +g9760 = NOT(g2315) +g9761 = NOT(g2445) +g9766 = NOT(g2748) +g9771 = NOT(g3969) +I13352 = NOT(g4146) +g9772 = NOT(I13352) +g9776 = NOT(g5073) +g9777 = NOT(g5112) +g9778 = NOT(g5069) +g9779 = NOT(g5156) +I13360 = NOT(g5343) +g9780 = NOT(I13360) +g9792 = NOT(g5401) +g9797 = NOT(g5441) +g9804 = NOT(g5456) +g9805 = NOT(g5485) +g9806 = NOT(g5782) +g9807 = NOT(g5712) +g9808 = NOT(g5827) +g9809 = NOT(g6082) +g9815 = NOT(g6098) +g9816 = NOT(g6167) +I13374 = NOT(g6490) +g9817 = NOT(I13374) +g9818 = NOT(g6490) +g9819 = NOT(g92) +g9820 = NOT(g99) +g9821 = NOT(g115) +g9822 = NOT(g125) +g9824 = NOT(g1825) +g9826 = NOT(g1844) +g9827 = NOT(g1974) +g9828 = NOT(g2024) +g9829 = NOT(g2250) +g9831 = NOT(g2269) +g9832 = NOT(g2399) +g9833 = NOT(g2449) +g9834 = NOT(g2579) +g9839 = NOT(g2724) +g9842 = NOT(g3274) +g9843 = NOT(g4311) +g9848 = NOT(g4462) +g9853 = NOT(g5297) +g9856 = NOT(g5343) +g9860 = NOT(g5417) +g9861 = NOT(g5459) +g9862 = NOT(g5413) +g9863 = NOT(g5503) +I13424 = NOT(g5689) +g9864 = NOT(I13424) +g9875 = NOT(g5747) +g9880 = NOT(g5787) +g9887 = NOT(g5802) +g9888 = NOT(g5831) +g9889 = NOT(g6128) +g9890 = NOT(g6058) +g9891 = NOT(g6173) +g9892 = NOT(g6428) +g9898 = NOT(g6444) +g9899 = NOT(g6513) +g9900 = NOT(g6) +g9901 = NOT(g84) +g9902 = NOT(g100) +g9903 = NOT(g681) +g9905 = NOT(g802) +g9907 = NOT(g1959) +g9909 = NOT(g1978) +g9910 = NOT(g2108) +g9911 = NOT(g2384) +g9913 = NOT(g2403) +g9914 = NOT(g2533) +g9915 = NOT(g2583) +g9916 = NOT(g3625) +I13473 = NOT(g4157) +g9917 = NOT(I13473) +g9920 = NOT(g4322) +g9924 = NOT(g5644) +g9927 = NOT(g5689) +g9931 = NOT(g5763) +g9932 = NOT(g5805) +g9933 = NOT(g5759) +g9934 = NOT(g5849) +I13483 = NOT(g6035) +g9935 = NOT(I13483) +g9946 = NOT(g6093) +g9951 = NOT(g6133) +g9958 = NOT(g6148) +g9959 = NOT(g6177) +g9960 = NOT(g6474) +g9961 = NOT(g6404) +g9962 = NOT(g6519) +g9963 = NOT(g7) +g9964 = NOT(g126) +g9965 = NOT(g127) +g9969 = NOT(g1682) +g9970 = NOT(g1714) +g9971 = NOT(g2093) +g9973 = NOT(g2112) +g9974 = NOT(g2518) +g9976 = NOT(g2537) +g9977 = NOT(g2667) +g9978 = NOT(g2756) +g9982 = NOT(g3976) +g9983 = NOT(g4239) +g9985 = NOT(g4332) +g9989 = NOT(g5077) +g9992 = NOT(g5990) +g9995 = NOT(g6035) +g9999 = NOT(g6109) +g10000 = NOT(g6151) +g10001 = NOT(g6105) +g10002 = NOT(g6195) +I13539 = NOT(g6381) +g10003 = NOT(I13539) +g10014 = NOT(g6439) +g10019 = NOT(g6479) +g10026 = NOT(g6494) +g10027 = NOT(g6523) +g10028 = NOT(g8) +I13548 = NOT(g94) +g10029 = NOT(I13548) +g10030 = NOT(g116) +I13552 = NOT(g121) +g10031 = NOT(I13552) +g10032 = NOT(g562) +g10033 = NOT(g655) +g10035 = NOT(g1720) +g10036 = NOT(g1816) +g10037 = NOT(g1848) +g10038 = NOT(g2241) +g10039 = NOT(g2273) +g10040 = NOT(g2652) +g10042 = NOT(g2671) +g10043 = NOT(g1632) +g10044 = NOT(g5357) +g10047 = NOT(g5421) +g10050 = NOT(g6336) +g10053 = NOT(g6381) +g10057 = NOT(g6455) +g10058 = NOT(g6497) +g10059 = NOT(g6451) +g10060 = NOT(g6541) +I13581 = NOT(g6727) +g10061 = NOT(I13581) +g10072 = NOT(g9) +g10073 = NOT(g134) +g10074 = NOT(g718) +g10077 = NOT(g1724) +g10078 = NOT(g1854) +g10079 = NOT(g1950) +g10080 = NOT(g1982) +g10081 = NOT(g2279) +g10082 = NOT(g2375) +g10083 = NOT(g2407) +g10084 = NOT(g2837) +g10085 = NOT(g1768) +g10086 = NOT(g2193) +I13597 = NOT(g4417) +g10087 = NOT(I13597) +g10090 = NOT(g5348) +g10093 = NOT(g5703) +g10096 = NOT(g5767) +g10099 = NOT(g6682) +g10102 = NOT(g6727) +g10106 = NOT(g16) +I13606 = NOT(g74) +g10107 = NOT(I13606) +g10108 = NOT(g120) +g10109 = NOT(g135) +g10110 = NOT(g661) +g10111 = NOT(g1858) +g10112 = NOT(g1988) +g10113 = NOT(g2084) +g10114 = NOT(g2116) +g10115 = NOT(g2283) +g10116 = NOT(g2413) +g10117 = NOT(g2509) +g10118 = NOT(g2541) +g10119 = NOT(g2841) +g10120 = NOT(g1902) +g10121 = NOT(g2327) +I13623 = NOT(g4294) +g10122 = NOT(I13623) +g10129 = NOT(g5352) +g10130 = NOT(g5694) +g10133 = NOT(g6049) +g10136 = NOT(g6113) +g10139 = NOT(g136) +g10140 = NOT(g19) +I13634 = NOT(g79) +g10141 = NOT(I13634) +I13637 = NOT(g102) +g10142 = NOT(I13637) +g10143 = NOT(g568) +g10147 = NOT(g728) +g10150 = NOT(g1700) +g10151 = NOT(g1992) +g10152 = NOT(g2122) +g10153 = NOT(g2417) +g10154 = NOT(g2547) +g10155 = NOT(g2643) +g10156 = NOT(g2675) +g10157 = NOT(g2036) +g10158 = NOT(g2461) +g10159 = NOT(g4477) +g10165 = NOT(g5698) +g10166 = NOT(g6040) +g10169 = NOT(g6395) +g10172 = NOT(g6459) +g10175 = NOT(g28) +g10176 = NOT(g44) +g10177 = NOT(g1834) +g10178 = NOT(g2126) +g10180 = NOT(g2259) +g10181 = NOT(g2551) +g10182 = NOT(g2681) +g10183 = NOT(g2595) +g10184 = NOT(g4486) +g10190 = NOT(g6044) +g10191 = NOT(g6386) +g10194 = NOT(g6741) +g10197 = NOT(g31) +I13672 = NOT(g106) +g10198 = NOT(I13672) +g10199 = NOT(g1968) +g10200 = NOT(g2138) +g10203 = NOT(g2393) +g10204 = NOT(g2685) +g10206 = NOT(g4489) +g10212 = NOT(g6390) +g10213 = NOT(g6732) +I13684 = NOT(g128) +g10216 = NOT(I13684) +g10217 = NOT(g2102) +g10218 = NOT(g2527) +g10219 = NOT(g2697) +g10222 = NOT(g4492) +g10223 = NOT(g4561) +g10229 = NOT(g6736) +I13694 = NOT(g117) +g10230 = NOT(I13694) +g10231 = NOT(g2661) +g10232 = NOT(g4527) +I13699 = NOT(g4581) +g10233 = NOT(I13699) +g10261 = NOT(g4555) +g10262 = NOT(g586) +I13705 = NOT(g63) +g10272 = NOT(I13705) +I13708 = NOT(g136) +g10273 = NOT(I13708) +g10274 = NOT(g976) +g10275 = NOT(g4584) +g10278 = NOT(g4628) +I13715 = NOT(g71) +g10287 = NOT(I13715) +I13718 = NOT(g890) +g10288 = NOT(I13718) +g10289 = NOT(g1319) +I13723 = NOT(g3167) +g10295 = NOT(I13723) +I13726 = NOT(g4537) +g10306 = NOT(I13726) +g10308 = NOT(g4459) +g10311 = NOT(g4633) +I13740 = NOT(g85) +g10319 = NOT(I13740) +g10320 = NOT(g817) +I13744 = NOT(g3518) +g10323 = NOT(I13744) +g10334 = NOT(g4420) +g10335 = NOT(g4483) +g10337 = NOT(g5016) +I13759 = NOT(g6754) +g10347 = NOT(I13759) +I13762 = NOT(g6755) +g10348 = NOT(I13762) +g10349 = NOT(g6956) +g10350 = NOT(g6800) +g10351 = NOT(g6802) +g10352 = NOT(g6804) +g10353 = NOT(g6803) +g10354 = NOT(g6811) +g10355 = NOT(g6816) +g10356 = NOT(g6819) +g10357 = NOT(g6825) +g10358 = NOT(g6827) +g10359 = NOT(g6830) +g10360 = NOT(g6836) +g10361 = NOT(g6841) +g10362 = NOT(g6850) +I13779 = NOT(g6868) +g10363 = NOT(I13779) +g10364 = NOT(g6869) +g10365 = NOT(g6867) +g10366 = NOT(g6895) +g10367 = NOT(g6870) +g10368 = NOT(g6887) +g10369 = NOT(g6873) +g10370 = NOT(g7095) +g10371 = NOT(g6918) +g10372 = NOT(g6900) +g10373 = NOT(g6917) +g10374 = NOT(g6903) +g10375 = NOT(g6941) +g10376 = NOT(g6923) +g10377 = NOT(g6940) +g10378 = NOT(g6926) +g10379 = NOT(g6953) +g10380 = NOT(g6960) +g10381 = NOT(g6957) +g10382 = NOT(g6958) +g10383 = NOT(g6978) +I13802 = NOT(g6971) +g10384 = NOT(I13802) +I13805 = NOT(g6976) +g10385 = NOT(I13805) +g10386 = NOT(g6982) +g10387 = NOT(g6996) +g10388 = NOT(g6983) +g10389 = NOT(g6986) +g10390 = NOT(g6987) +g10391 = NOT(g6988) +g10392 = NOT(g6989) +g10393 = NOT(g6991) +g10394 = NOT(g6994) +g10395 = NOT(g6995) +g10396 = NOT(g6997) +g10397 = NOT(g7018) +g10398 = NOT(g6999) +g10399 = NOT(g7017) +g10400 = NOT(g7002) +g10401 = NOT(g7041) +g10402 = NOT(g7023) +g10403 = NOT(g7040) +g10404 = NOT(g7026) +g10405 = NOT(g7064) +g10406 = NOT(g7046) +g10407 = NOT(g7063) +g10408 = NOT(g7049) +g10409 = NOT(g7087) +g10410 = NOT(g7069) +g10411 = NOT(g7086) +g10412 = NOT(g7072) +g10413 = NOT(g7110) +g10414 = NOT(g7092) +g10415 = NOT(g7109) +g10416 = NOT(g10318) +g10417 = NOT(g7117) +g10418 = NOT(g8818) +g10419 = NOT(g8821) +g10420 = NOT(g9239) +g10427 = NOT(g10053) +g10428 = NOT(g9631) +g10429 = NOT(g7148) +I13847 = NOT(g7266) +g10430 = NOT(I13847) +I13857 = NOT(g9780) +g10473 = NOT(I13857) +g10474 = NOT(g8841) +g10475 = NOT(g8844) +g10487 = NOT(g10233) +g10489 = NOT(g9259) +g10490 = NOT(g9274) +g10497 = NOT(g10102) +g10498 = NOT(g7161) +I13872 = NOT(g7474) +g10499 = NOT(I13872) +I13875 = NOT(g1233) +g10500 = NOT(I13875) +g10502 = NOT(g8876) +g10503 = NOT(g8879) +g10504 = NOT(g8763) +g10509 = NOT(g10233) +g10518 = NOT(g9311) +g10519 = NOT(g9326) +I13889 = NOT(g7598) +g10521 = NOT(I13889) +I13892 = NOT(g1576) +g10527 = NOT(I13892) +g10530 = NOT(g8922) +g10531 = NOT(g8925) +g10532 = NOT(g10233) +g10533 = NOT(g8795) +g10540 = NOT(g9392) +g10541 = NOT(g9407) +g10542 = NOT(g7196) +I13906 = NOT(g7620) +g10544 = NOT(I13906) +g10553 = NOT(g8971) +g10554 = NOT(g8974) +g10564 = NOT(g9462) +g10570 = NOT(g9021) +g10571 = NOT(g10233) +g10572 = NOT(g10233) +g10581 = NOT(g9529) +g10582 = NOT(g7116) +g10597 = NOT(g10233) +g10606 = NOT(g10233) +g10607 = NOT(g10233) +g10608 = NOT(g9155) +g10612 = NOT(g10233) +g10613 = NOT(g10233) +g10620 = NOT(g10233) +g10621 = NOT(g7567) +I13968 = NOT(g7697) +g10627 = NOT(I13968) +g10652 = NOT(g7601) +I13979 = NOT(g7733) +g10658 = NOT(I13979) +g10664 = NOT(g8928) +I13990 = NOT(g7636) +g10678 = NOT(I13990) +I13995 = NOT(g8744) +g10685 = NOT(I13995) +g10708 = NOT(g7836) +I14006 = NOT(g9104) +g10710 = NOT(I14006) +g10725 = NOT(g7846) +I14016 = NOT(g9104) +g10727 = NOT(I14016) +g10741 = NOT(g8411) +g10761 = NOT(g8411) +g10762 = NOT(g8470) +I14033 = NOT(g8912) +g10776 = NOT(I14033) +g10794 = NOT(g8470) +g10795 = NOT(g7202) +g10804 = NOT(g9772) +I14046 = NOT(g9900) +g10805 = NOT(I14046) +I14050 = NOT(g9963) +g10812 = NOT(I14050) +g10815 = NOT(g9917) +I14054 = NOT(g10028) +g10816 = NOT(I14054) +g10830 = NOT(g10087) +I14069 = NOT(g9104) +g10851 = NOT(I14069) +g10857 = NOT(g8712) +g10872 = NOT(g7567) +I14079 = NOT(g7231) +g10877 = NOT(I14079) +g10881 = NOT(g7567) +g10882 = NOT(g7601) +g10897 = NOT(g7601) +g10960 = NOT(g9007) +g10980 = NOT(g9051) +I14119 = NOT(g7824) +g10981 = NOT(I14119) +g11011 = NOT(g10274) +g11017 = NOT(g10289) +g11026 = NOT(g8434) +g11030 = NOT(g8292) +g11031 = NOT(g8609) +g11033 = NOT(g8500) +g11034 = NOT(g7611) +g11038 = NOT(g8632) +g11042 = NOT(g8691) +g11043 = NOT(g8561) +I14158 = NOT(g8806) +g11048 = NOT(I14158) +g11110 = NOT(g8728) +g11122 = NOT(g8751) +g11128 = NOT(g7993) +g11129 = NOT(g7994) +I14192 = NOT(g10233) +g11136 = NOT(I14192) +g11143 = NOT(g8032) +g11147 = NOT(g8417) +g11164 = NOT(g8085) +I14222 = NOT(g8286) +g11165 = NOT(I14222) +g11170 = NOT(g8476) +g11181 = NOT(g8134) +I14241 = NOT(g8356) +g11182 = NOT(I14241) +g11183 = NOT(g8135) +g11192 = NOT(g8038) +I14267 = NOT(g7835) +g11202 = NOT(I14267) +I14271 = NOT(g8456) +g11204 = NOT(I14271) +g11214 = NOT(g9602) +g11215 = NOT(g8285) +g11233 = NOT(g9664) +g11234 = NOT(g8355) +I14301 = NOT(g8571) +g11235 = NOT(I14301) +g11236 = NOT(g8357) +I14305 = NOT(g8805) +g11237 = NOT(I14305) +g11249 = NOT(g8405) +g11250 = NOT(g7502) +g11268 = NOT(g7515) +g11269 = NOT(g7516) +I14326 = NOT(g8607) +g11290 = NOT(I14326) +g11291 = NOT(g7526) +g11293 = NOT(g7527) +g11294 = NOT(g7598) +g11316 = NOT(g8967) +I14346 = NOT(g10233) +g11317 = NOT(I14346) +g11324 = NOT(g7542) +g11325 = NOT(g7543) +g11336 = NOT(g7620) +g11344 = NOT(g9015) +I14365 = NOT(g3303) +g11349 = NOT(I14365) +I14381 = NOT(g8300) +g11367 = NOT(I14381) +g11371 = NOT(g7565) +g11373 = NOT(g7566) +g11383 = NOT(g9061) +I14395 = NOT(g3654) +g11388 = NOT(I14395) +I14409 = NOT(g8364) +g11398 = NOT(I14409) +g11401 = NOT(g7593) +g11402 = NOT(g7594) +g11403 = NOT(g7595) +g11404 = NOT(g7596) +g11413 = NOT(g9100) +I14424 = NOT(g4005) +g11418 = NOT(I14424) +g11425 = NOT(g7640) +g11428 = NOT(g7615) +g11429 = NOT(g7616) +g11430 = NOT(g7617) +g11431 = NOT(g7618) +I14450 = NOT(g4191) +g11447 = NOT(I14450) +I14455 = NOT(g10197) +g11450 = NOT(I14455) +g11467 = NOT(g7623) +g11468 = NOT(g7624) +g11470 = NOT(g7625) +g11471 = NOT(g7626) +g11472 = NOT(g7918) +I14475 = NOT(g10175) +g11498 = NOT(I14475) +g11509 = NOT(g7632) +g11510 = NOT(g7633) +g11512 = NOT(g7634) +g11513 = NOT(g7948) +g11519 = NOT(g8481) +I14505 = NOT(g10140) +g11547 = NOT(I14505) +g11560 = NOT(g7647) +g11562 = NOT(g7648) +g11576 = NOT(g8542) +I14537 = NOT(g10106) +g11592 = NOT(I14537) +g11608 = NOT(g7659) +g11609 = NOT(g7660) +g11615 = NOT(g6875) +g11631 = NOT(g8595) +I14550 = NOT(g10072) +g11640 = NOT(I14550) +g11652 = NOT(g7674) +g11663 = NOT(g6905) +g11677 = NOT(g7689) +I14563 = NOT(g802) +g11678 = NOT(I14563) +I14567 = NOT(g9708) +g11686 = NOT(I14567) +I14570 = NOT(g7932) +g11691 = NOT(I14570) +g11702 = NOT(g6928) +I14576 = NOT(g8791) +g11705 = NOT(I14576) +I14579 = NOT(g8792) +g11706 = NOT(I14579) +I14584 = NOT(g9766) +g11709 = NOT(I14584) +g11714 = NOT(g8107) +I14589 = NOT(g8818) +g11720 = NOT(I14589) +g11721 = NOT(g10074) +I14593 = NOT(g9978) +g11724 = NOT(I14593) +g11735 = NOT(g8534) +g11736 = NOT(g8165) +g11741 = NOT(g10033) +I14602 = NOT(g9340) +g11744 = NOT(I14602) +g11753 = NOT(g8587) +g11754 = NOT(g8229) +g11762 = NOT(g7964) +g11769 = NOT(g8626) +I14619 = NOT(g4185) +g11770 = NOT(I14619) +I14623 = NOT(g8925) +g11772 = NOT(I14623) +g11779 = NOT(g9602) +g11786 = NOT(g7549) +I14630 = NOT(g7717) +g11790 = NOT(I14630) +I14633 = NOT(g9340) +g11793 = NOT(I14633) +g11796 = NOT(g7985) +g11810 = NOT(g9664) +g11811 = NOT(g9724) +g11812 = NOT(g7567) +g11815 = NOT(g7582) +g11819 = NOT(g7717) +I14644 = NOT(g7717) +g11820 = NOT(I14644) +I14647 = NOT(g7717) +g11823 = NOT(I14647) +I14650 = NOT(g9340) +g11826 = NOT(I14650) +I14653 = NOT(g9417) +g11829 = NOT(I14653) +g11832 = NOT(g8011) +g11833 = NOT(g8026) +g11841 = NOT(g9800) +I14660 = NOT(g9746) +g11842 = NOT(I14660) +I14663 = NOT(g9747) +g11845 = NOT(I14663) +g11849 = NOT(g7601) +I14668 = NOT(g7753) +g11852 = NOT(I14668) +I14671 = NOT(g7717) +g11855 = NOT(I14671) +g11861 = NOT(g8070) +g11865 = NOT(g10124) +g11866 = NOT(g9883) +I14679 = NOT(g9332) +g11867 = NOT(I14679) +g11868 = NOT(g9185) +I14684 = NOT(g7717) +g11872 = NOT(I14684) +I14687 = NOT(g7753) +g11875 = NOT(I14687) +I14690 = NOT(g9340) +g11878 = NOT(I14690) +g11884 = NOT(g8125) +g11888 = NOT(g10160) +g11889 = NOT(g9954) +I14702 = NOT(g7717) +g11894 = NOT(I14702) +I14705 = NOT(g7717) +g11897 = NOT(I14705) +I14708 = NOT(g9417) +g11900 = NOT(I14708) +g11910 = NOT(g10185) +g11911 = NOT(g10022) +g11912 = NOT(g8989) +I14727 = NOT(g7753) +g11917 = NOT(I14727) +I14730 = NOT(g7717) +g11920 = NOT(I14730) +g11927 = NOT(g10207) +I14742 = NOT(g9534) +g11928 = NOT(I14742) +I14745 = NOT(g10029) +g11929 = NOT(I14745) +g11930 = NOT(g9281) +I14749 = NOT(g10031) +g11931 = NOT(I14749) +I14761 = NOT(g7753) +g11941 = NOT(I14761) +g11948 = NOT(g10224) +I14773 = NOT(g9581) +g11949 = NOT(I14773) +g11963 = NOT(g9153) +g11964 = NOT(g9154) +I14797 = NOT(g9636) +g11965 = NOT(I14797) +I14800 = NOT(g10107) +g11966 = NOT(I14800) +I14823 = NOT(g8056) +g11981 = NOT(I14823) +g11984 = NOT(g9186) +I14827 = NOT(g9686) +g11985 = NOT(I14827) +I14830 = NOT(g10141) +g11986 = NOT(I14830) +I14833 = NOT(g10142) +g11987 = NOT(I14833) +I14836 = NOT(g9688) +g11988 = NOT(I14836) +I14839 = NOT(g9689) +g11989 = NOT(I14839) +g11991 = NOT(g9485) +I14862 = NOT(g8092) +g12009 = NOT(I14862) +g12012 = NOT(g9213) +I14866 = NOT(g9748) +g12013 = NOT(I14866) +g12018 = NOT(g9538) +g12021 = NOT(g9543) +g12036 = NOT(g9245) +I14893 = NOT(g9819) +g12037 = NOT(I14893) +I14896 = NOT(g9820) +g12038 = NOT(I14896) +I14899 = NOT(g10198) +g12039 = NOT(I14899) +I14902 = NOT(g9821) +g12040 = NOT(I14902) +I14905 = NOT(g9822) +g12041 = NOT(I14905) +g12047 = NOT(g9591) +g12051 = NOT(g9595) +g12054 = NOT(g7690) +I14932 = NOT(g9901) +g12074 = NOT(I14932) +I14935 = NOT(g9902) +g12075 = NOT(I14935) +g12076 = NOT(g9280) +I14939 = NOT(g10216) +g12077 = NOT(I14939) +g12082 = NOT(g9645) +g12086 = NOT(g9654) +g12088 = NOT(g7701) +g12107 = NOT(g9687) +I14964 = NOT(g10230) +g12108 = NOT(I14964) +I14967 = NOT(g9964) +g12109 = NOT(I14967) +I14970 = NOT(g9965) +g12110 = NOT(I14970) +g12122 = NOT(g9705) +I14999 = NOT(g10030) +g12143 = NOT(I14999) +g12180 = NOT(g9477) +g12181 = NOT(g9478) +I15030 = NOT(g10073) +g12182 = NOT(I15030) +I15033 = NOT(g10273) +g12183 = NOT(I15033) +I15036 = NOT(g799) +g12184 = NOT(I15036) +I15070 = NOT(g10108) +g12217 = NOT(I15070) +I15073 = NOT(g10109) +g12218 = NOT(I15073) +g12233 = NOT(g10338) +I15102 = NOT(g5313) +g12238 = NOT(I15102) +g12295 = NOT(g7139) +I15144 = NOT(g5659) +g12300 = NOT(I15144) +g12321 = NOT(g9637) +I15162 = NOT(g10176) +g12322 = NOT(I15162) +g12337 = NOT(g9340) +g12345 = NOT(g7158) +I15190 = NOT(g6005) +g12350 = NOT(I15190) +I15205 = NOT(g10139) +g12367 = NOT(I15205) +I15208 = NOT(g637) +g12368 = NOT(I15208) +g12378 = NOT(g9417) +I15223 = NOT(g10119) +g12381 = NOT(I15223) +g12399 = NOT(g9920) +g12417 = NOT(g7175) +I15238 = NOT(g6351) +g12422 = NOT(I15238) +I15250 = NOT(g9152) +g12430 = NOT(I15250) +g12440 = NOT(g9985) +g12465 = NOT(g7192) +I15284 = NOT(g6697) +g12470 = NOT(I15284) +I15295 = NOT(g8515) +g12477 = NOT(I15295) +g12487 = NOT(g9340) +I15316 = NOT(g10087) +g12490 = NOT(I15316) +g12497 = NOT(g9780) +g12543 = NOT(g9417) +g12546 = NOT(g8740) +g12563 = NOT(g9864) +g12598 = NOT(g7004) +g12614 = NOT(g9935) +I15382 = NOT(g9071) +g12640 = NOT(I15382) +g12656 = NOT(g7028) +g12672 = NOT(g10003) +g12705 = NOT(g7051) +g12721 = NOT(g10061) +g12738 = NOT(g9374) +g12749 = NOT(g7074) +g12760 = NOT(g10272) +g12778 = NOT(g9856) +g12779 = NOT(g9444) +g12790 = NOT(g7097) +g12793 = NOT(g10287) +g12804 = NOT(g9927) +g12805 = NOT(g9511) +g12811 = NOT(g10319) +g12818 = NOT(g8792) +g12820 = NOT(g10233) +g12823 = NOT(g9206) +g12830 = NOT(g9995) +g12831 = NOT(g9569) +I15448 = NOT(g10877) +g12833 = NOT(I15448) +g12834 = NOT(g10349) +g12835 = NOT(g10352) +g12836 = NOT(g10351) +g12837 = NOT(g10354) +g12838 = NOT(g10353) +g12839 = NOT(g10350) +g12840 = NOT(g10356) +g12841 = NOT(g10357) +g12842 = NOT(g10355) +g12843 = NOT(g10359) +g12844 = NOT(g10360) +g12845 = NOT(g10358) +I15474 = NOT(g10364) +g12857 = NOT(I15474) +g12859 = NOT(g10366) +g12860 = NOT(g10368) +g12861 = NOT(g10367) +g12862 = NOT(g10370) +g12863 = NOT(g10371) +g12864 = NOT(g10373) +g12865 = NOT(g10372) +g12866 = NOT(g10369) +g12867 = NOT(g10375) +g12868 = NOT(g10377) +g12869 = NOT(g10376) +g12870 = NOT(g10374) +g12871 = NOT(g10378) +g12872 = NOT(g10379) +g12873 = NOT(g10380) +g12874 = NOT(g10383) +I15494 = NOT(g10385) +g12875 = NOT(I15494) +g12878 = NOT(g10386) +g12879 = NOT(g10381) +g12880 = NOT(g10387) +g12881 = NOT(g10388) +g12882 = NOT(g10389) +g12883 = NOT(g10390) +g12884 = NOT(g10392) +g12885 = NOT(g10382) +g12886 = NOT(g10393) +g12887 = NOT(g10394) +g12888 = NOT(g10395) +g12889 = NOT(g10396) +g12890 = NOT(g10397) +g12891 = NOT(g10399) +g12892 = NOT(g10398) +g12893 = NOT(g10391) +g12894 = NOT(g10401) +g12895 = NOT(g10403) +g12896 = NOT(g10402) +g12897 = NOT(g10400) +g12898 = NOT(g10405) +g12899 = NOT(g10407) +g12900 = NOT(g10406) +g12901 = NOT(g10404) +g12902 = NOT(g10409) +g12903 = NOT(g10411) +g12904 = NOT(g10410) +g12905 = NOT(g10408) +g12906 = NOT(g10413) +g12907 = NOT(g10415) +g12908 = NOT(g10414) +g12909 = NOT(g10412) +g12914 = NOT(g12235) +I15533 = NOT(g11867) +g12918 = NOT(I15533) +I15536 = NOT(g1227) +g12919 = NOT(I15536) +g12921 = NOT(g12228) +g12922 = NOT(g12297) +I15542 = NOT(g1570) +g12923 = NOT(I15542) +g12929 = NOT(g12550) +g12930 = NOT(g12347) +I15550 = NOT(g10430) +g12932 = NOT(I15550) +g12936 = NOT(g12601) +g12937 = NOT(g12419) +I15556 = NOT(g11928) +g12938 = NOT(I15556) +g12940 = NOT(g11744) +g12944 = NOT(g12659) +g12945 = NOT(g12467) +I15564 = NOT(g11949) +g12946 = NOT(I15564) +g12950 = NOT(g12708) +I15569 = NOT(g11965) +g12951 = NOT(I15569) +I15572 = NOT(g10499) +g12952 = NOT(I15572) +I15577 = NOT(g10430) +g12955 = NOT(I15577) +g12967 = NOT(g11790) +g12968 = NOT(g11793) +g12975 = NOT(g12752) +I15587 = NOT(g11985) +g12976 = NOT(I15587) +I15590 = NOT(g11988) +g12977 = NOT(I15590) +I15593 = NOT(g11989) +g12978 = NOT(I15593) +I15600 = NOT(g10430) +g12983 = NOT(I15600) +g12995 = NOT(g11820) +g12996 = NOT(g11823) +g12997 = NOT(g11826) +g12998 = NOT(g11829) +I15609 = NOT(g12013) +g13003 = NOT(I15609) +g13007 = NOT(g11852) +g13008 = NOT(g11855) +I15617 = NOT(g12037) +g13009 = NOT(I15617) +I15620 = NOT(g12038) +g13010 = NOT(I15620) +I15623 = NOT(g12040) +g13011 = NOT(I15623) +I15626 = NOT(g12041) +g13012 = NOT(I15626) +g13014 = NOT(g11872) +g13015 = NOT(g11875) +g13016 = NOT(g11878) +I15633 = NOT(g12074) +g13017 = NOT(I15633) +I15636 = NOT(g12075) +g13018 = NOT(I15636) +g13022 = NOT(g11894) +g13023 = NOT(g11897) +g13024 = NOT(g11900) +g13026 = NOT(g11018) +I15647 = NOT(g12109) +g13027 = NOT(I15647) +I15650 = NOT(g12110) +g13028 = NOT(I15650) +g13033 = NOT(g11917) +g13034 = NOT(g11920) +g13036 = NOT(g10981) +g13037 = NOT(g10981) +I15663 = NOT(g5308) +g13039 = NOT(I15663) +I15667 = NOT(g12143) +g13041 = NOT(I15667) +g13045 = NOT(g11941) +I15677 = NOT(g5654) +g13049 = NOT(I15677) +g13051 = NOT(g11964) +I15682 = NOT(g12182) +g13055 = NOT(I15682) +g13061 = NOT(g10981) +g13062 = NOT(g10981) +g13064 = NOT(g11705) +g13065 = NOT(g10476) +I15697 = NOT(g6000) +g13068 = NOT(I15697) +g13070 = NOT(g11984) +I15702 = NOT(g12217) +g13074 = NOT(I15702) +I15705 = NOT(g12218) +g13075 = NOT(I15705) +g13082 = NOT(g10981) +I15717 = NOT(g6346) +g13085 = NOT(I15717) +g13087 = NOT(g12012) +I15727 = NOT(g10981) +g13096 = NOT(I15727) +I15732 = NOT(g6692) +g13099 = NOT(I15732) +I15736 = NOT(g12322) +g13101 = NOT(I15736) +g13103 = NOT(g10905) +g13106 = NOT(g10981) +g13107 = NOT(g10476) +g13116 = NOT(g10935) +g13117 = NOT(g10981) +g13120 = NOT(g10632) +g13132 = NOT(g10632) +g13133 = NOT(g11330) +I15765 = NOT(g10823) +g13138 = NOT(I15765) +g13140 = NOT(g10632) +g13141 = NOT(g11374) +g13142 = NOT(g10632) +I15773 = NOT(g10430) +g13144 = NOT(I15773) +g13173 = NOT(g10632) +g13174 = NOT(g10741) +g13175 = NOT(g10909) +I15782 = NOT(g10430) +g13177 = NOT(I15782) +g13188 = NOT(g10909) +g13189 = NOT(g10762) +g13190 = NOT(g10939) +I15788 = NOT(g10430) +g13191 = NOT(I15788) +g13209 = NOT(g10632) +g13215 = NOT(g10909) +g13216 = NOT(g10939) +g13222 = NOT(g10590) +I15800 = NOT(g11607) +g13223 = NOT(I15800) +g13239 = NOT(g10632) +g13246 = NOT(g10939) +g13249 = NOT(g10590) +I15811 = NOT(g11128) +g13250 = NOT(I15811) +I15814 = NOT(g11129) +g13251 = NOT(I15814) +g13255 = NOT(g10632) +I15821 = NOT(g11143) +g13258 = NOT(I15821) +I15824 = NOT(g1116) +g13259 = NOT(I15824) +I15831 = NOT(g10416) +g13267 = NOT(I15831) +I15834 = NOT(g11164) +g13271 = NOT(I15834) +I15837 = NOT(g1459) +g13272 = NOT(I15837) +g13278 = NOT(g10738) +I15843 = NOT(g11181) +g13279 = NOT(I15843) +I15846 = NOT(g11183) +g13280 = NOT(I15846) +g13297 = NOT(g10831) +I15862 = NOT(g11215) +g13298 = NOT(I15862) +g13301 = NOT(g10862) +g13302 = NOT(g12321) +I15869 = NOT(g11234) +g13303 = NOT(I15869) +I15872 = NOT(g11236) +g13304 = NOT(I15872) +g13305 = NOT(g11048) +I15878 = NOT(g11249) +g13311 = NOT(I15878) +g13312 = NOT(g11048) +g13314 = NOT(g10893) +g13322 = NOT(g10918) +g13323 = NOT(g11048) +I15893 = NOT(g10430) +g13329 = NOT(I15893) +g13334 = NOT(g11048) +I15906 = NOT(g10430) +g13350 = NOT(I15906) +I15915 = NOT(g10430) +g13394 = NOT(I15915) +I15918 = NOT(g12381) +g13409 = NOT(I15918) +I15921 = NOT(g12381) +g13410 = NOT(I15921) +g13412 = NOT(g11963) +g13413 = NOT(g11737) +g13414 = NOT(g11048) +I15929 = NOT(g10430) +g13416 = NOT(I15929) +I15932 = NOT(g12381) +g13431 = NOT(I15932) +I15937 = NOT(g11676) +g13437 = NOT(I15937) +g13458 = NOT(g11048) +I15942 = NOT(g12381) +g13460 = NOT(I15942) +g13463 = NOT(g10476) +g13474 = NOT(g11048) +I15954 = NOT(g12381) +g13477 = NOT(I15954) +g13483 = NOT(g11270) +g13484 = NOT(g10981) +g13485 = NOT(g10476) +g13494 = NOT(g11912) +g13504 = NOT(g11303) +g13505 = NOT(g10981) +g13506 = NOT(g10808) +I15981 = NOT(g11290) +g13510 = NOT(I15981) +I15987 = NOT(g12381) +g13514 = NOT(I15987) +g13521 = NOT(g11357) +g13522 = NOT(g10981) +g13530 = NOT(g12641) +I16010 = NOT(g11148) +g13545 = NOT(I16010) +g13555 = NOT(g12692) +g13565 = NOT(g11006) +g13569 = NOT(g10951) +I16024 = NOT(g11171) +g13574 = NOT(I16024) +I16028 = NOT(g12381) +g13583 = NOT(I16028) +g13584 = NOT(g12735) +g13593 = NOT(g10556) +g13594 = NOT(g11012) +g13595 = NOT(g10951) +g13596 = NOT(g10971) +I16040 = NOT(g10430) +g13605 = NOT(I16040) +g13620 = NOT(g10556) +g13621 = NOT(g10573) +g13624 = NOT(g10951) +g13625 = NOT(g10971) +g13626 = NOT(g11273) +g13637 = NOT(g10556) +I16057 = NOT(g10430) +g13638 = NOT(I16057) +g13655 = NOT(g10573) +g13663 = NOT(g10971) +g13664 = NOT(g11252) +g13665 = NOT(g11306) +g13675 = NOT(g10556) +g13679 = NOT(g10573) +I16077 = NOT(g10430) +g13680 = NOT(I16077) +g13706 = NOT(g11280) +g13707 = NOT(g11360) +g13715 = NOT(g10573) +I16090 = NOT(g10430) +g13716 = NOT(I16090) +g13729 = NOT(g10951) +g13736 = NOT(g11313) +I16102 = NOT(g10430) +g13745 = NOT(I16102) +g13763 = NOT(g10971) +I16117 = NOT(g10430) +g13782 = NOT(I16117) +I16120 = NOT(g11868) +g13793 = NOT(I16120) +I16135 = NOT(g10430) +g13809 = NOT(I16135) +I16150 = NOT(g10430) +g13835 = NOT(I16150) +I16160 = NOT(g11237) +g13856 = NOT(I16160) +I16163 = NOT(g11930) +g13857 = NOT(I16163) +I16168 = NOT(g3321) +g13865 = NOT(I16168) +g13868 = NOT(g11493) +g13869 = NOT(g10831) +g13876 = NOT(g11432) +g13877 = NOT(g11350) +I16181 = NOT(g3672) +g13881 = NOT(I16181) +g13885 = NOT(g10862) +I16193 = NOT(g3281) +g13895 = NOT(I16193) +g13901 = NOT(g11480) +g13902 = NOT(g11389) +I16201 = NOT(g4023) +g13906 = NOT(I16201) +I16217 = NOT(g3632) +g13926 = NOT(I16217) +g13932 = NOT(g11534) +g13933 = NOT(g11419) +I16231 = NOT(g10520) +g13943 = NOT(I16231) +I16246 = NOT(g3983) +g13966 = NOT(I16246) +g13975 = NOT(g11048) +g13976 = NOT(g11130) +g13995 = NOT(g11261) +g13999 = NOT(g11048) +g14004 = NOT(g11149) +g14029 = NOT(g11283) +I16289 = NOT(g12107) +g14031 = NOT(I16289) +g14032 = NOT(g11048) +g14034 = NOT(g11048) +g14063 = NOT(g11048) +g14065 = NOT(g11048) +g14095 = NOT(g11326) +I16328 = NOT(g878) +g14096 = NOT(I16328) +I16345 = NOT(g881) +g14125 = NOT(I16345) +I16357 = NOT(g884) +g14147 = NOT(I16357) +g14149 = NOT(g12381) +g14150 = NOT(g12381) +g14166 = NOT(g11048) +I16371 = NOT(g887) +g14167 = NOT(I16371) +g14169 = NOT(g12381) +g14173 = NOT(g12076) +g14179 = NOT(g11048) +g14183 = NOT(g12381) +g14184 = NOT(g12381) +g14186 = NOT(g11346) +I16391 = NOT(g859) +g14189 = NOT(I16391) +g14191 = NOT(g12381) +g14192 = NOT(g11385) +g14197 = NOT(g12160) +g14198 = NOT(g12180) +I16401 = NOT(g869) +g14201 = NOT(I16401) +g14203 = NOT(g12381) +g14204 = NOT(g12155) +g14205 = NOT(g12381) +g14208 = NOT(g11563) +g14209 = NOT(g11415) +g14215 = NOT(g12198) +I16417 = NOT(g875) +g14217 = NOT(I16417) +g14219 = NOT(g12381) +g14226 = NOT(g11618) +g14231 = NOT(g12246) +g14232 = NOT(g11083) +g14237 = NOT(g11666) +g14238 = NOT(g10823) +g14251 = NOT(g12308) +I16438 = NOT(g11165) +g14252 = NOT(I16438) +g14255 = NOT(g12381) +g14262 = NOT(g10838) +g14275 = NOT(g12358) +I16452 = NOT(g11182) +g14276 = NOT(I16452) +I16455 = NOT(g11845) +g14277 = NOT(I16455) +I16460 = NOT(g10430) +g14290 = NOT(I16460) +g14297 = NOT(g10869) +I16468 = NOT(g12760) +g14307 = NOT(I16468) +I16471 = NOT(g12367) +g14308 = NOT(I16471) +I16476 = NOT(g10430) +g14314 = NOT(I16476) +I16479 = NOT(g10430) +g14315 = NOT(I16479) +g14321 = NOT(g10874) +I16486 = NOT(g11204) +g14330 = NOT(I16486) +I16489 = NOT(g12793) +g14331 = NOT(I16489) +I16492 = NOT(g12430) +g14332 = NOT(I16492) +I16498 = NOT(g10430) +g14336 = NOT(I16498) +I16502 = NOT(g10430) +g14338 = NOT(I16502) +g14342 = NOT(g12163) +g14348 = NOT(g10887) +g14357 = NOT(g12181) +I16512 = NOT(g12811) +g14358 = NOT(I16512) +I16515 = NOT(g12477) +g14359 = NOT(I16515) +I16521 = NOT(g10430) +g14363 = NOT(I16521) +I16526 = NOT(g10430) +g14366 = NOT(I16526) +g14376 = NOT(g12126) +g14377 = NOT(g12201) +I16535 = NOT(g11235) +g14383 = NOT(I16535) +I16538 = NOT(g10417) +g14384 = NOT(I16538) +I16541 = NOT(g11929) +g14385 = NOT(I16541) +I16544 = NOT(g11931) +g14386 = NOT(I16544) +I16555 = NOT(g10430) +g14398 = NOT(I16555) +g14405 = NOT(g12170) +g14406 = NOT(g12249) +I16564 = NOT(g10429) +g14412 = NOT(I16564) +I16575 = NOT(g3298) +g14421 = NOT(I16575) +I16579 = NOT(g10981) +g14423 = NOT(I16579) +g14424 = NOT(g11136) +g14431 = NOT(g12208) +g14432 = NOT(g12311) +I16590 = NOT(g11966) +g14441 = NOT(I16590) +I16593 = NOT(g10498) +g14442 = NOT(I16593) +I16596 = NOT(g12640) +g14443 = NOT(I16596) +I16606 = NOT(g3649) +g14451 = NOT(I16606) +I16610 = NOT(g10981) +g14453 = NOT(I16610) +I16613 = NOT(g10430) +g14454 = NOT(I16613) +g14503 = NOT(g12256) +g14504 = NOT(g12361) +I16626 = NOT(g11986) +g14509 = NOT(I16626) +I16629 = NOT(g11987) +g14510 = NOT(I16629) +I16639 = NOT(g4000) +g14518 = NOT(I16639) +g14535 = NOT(g12318) +I16651 = NOT(g10542) +g14536 = NOT(I16651) +g14541 = NOT(g11405) +I16660 = NOT(g10981) +g14543 = NOT(I16660) +I16663 = NOT(g10981) +g14544 = NOT(I16663) +g14545 = NOT(g12768) +g14562 = NOT(g12036) +I16676 = NOT(g10588) +g14563 = NOT(I16676) +I16679 = NOT(g12039) +g14564 = NOT(I16679) +I16688 = NOT(g10981) +g14571 = NOT(I16688) +I16698 = NOT(g12077) +g14582 = NOT(I16698) +g14584 = NOT(g11048) +I16709 = NOT(g10430) +g14591 = NOT(I16709) +I16713 = NOT(g5331) +g14597 = NOT(I16713) +I16724 = NOT(g12108) +g14609 = NOT(I16724) +I16733 = NOT(g12026) +g14616 = NOT(I16733) +g14630 = NOT(g12402) +g14631 = NOT(g12239) +I16741 = NOT(g5677) +g14635 = NOT(I16741) +I16747 = NOT(g12729) +g14639 = NOT(I16747) +I16755 = NOT(g12377) +g14645 = NOT(I16755) +I16762 = NOT(g5290) +g14662 = NOT(I16762) +g14668 = NOT(g12450) +g14669 = NOT(g12301) +I16770 = NOT(g6023) +g14673 = NOT(I16770) +I16775 = NOT(g12183) +g14676 = NOT(I16775) +I16795 = NOT(g5637) +g14694 = NOT(I16795) +g14700 = NOT(g12512) +g14701 = NOT(g12351) +I16803 = NOT(g6369) +g14705 = NOT(I16803) +g14714 = NOT(g11405) +I16821 = NOT(g5983) +g14738 = NOT(I16821) +g14744 = NOT(g12578) +g14745 = NOT(g12423) +I16829 = NOT(g6715) +g14749 = NOT(I16829) +g14753 = NOT(g11317) +I16847 = NOT(g6329) +g14779 = NOT(I16847) +g14785 = NOT(g12629) +g14786 = NOT(g12471) +I16855 = NOT(g10473) +g14790 = NOT(I16855) +I16875 = NOT(g6675) +g14828 = NOT(I16875) +g14833 = NOT(g11405) +I16898 = NOT(g10615) +g14873 = NOT(I16898) +I16917 = NOT(g10582) +g14912 = NOT(I16917) +I16969 = NOT(g13943) +g15048 = NOT(I16969) +I17008 = NOT(g12857) +g15085 = NOT(I17008) +I17094 = NOT(g14331) +g15169 = NOT(I17094) +I17098 = NOT(g14336) +g15171 = NOT(I17098) +I17101 = NOT(g14338) +g15224 = NOT(I17101) +I17104 = NOT(g12932) +g15277 = NOT(I17104) +g15344 = NOT(g14851) +I17108 = NOT(g13782) +g15345 = NOT(I17108) +I17111 = NOT(g13809) +g15348 = NOT(I17111) +I17114 = NOT(g14358) +g15371 = NOT(I17114) +I17118 = NOT(g14363) +g15373 = NOT(I17118) +I17121 = NOT(g14366) +g15426 = NOT(I17121) +g15479 = NOT(g14895) +I17125 = NOT(g13809) +g15480 = NOT(I17125) +I17128 = NOT(g13835) +g15483 = NOT(I17128) +I17131 = NOT(g14384) +g15506 = NOT(I17131) +I17136 = NOT(g14398) +g15509 = NOT(I17136) +g15562 = NOT(g14943) +I17140 = NOT(g13835) +g15563 = NOT(I17140) +I17143 = NOT(g14412) +g15566 = NOT(I17143) +g15568 = NOT(g14984) +I17148 = NOT(g14442) +g15569 = NOT(I17148) +g15571 = NOT(g13211) +I17154 = NOT(g13605) +g15573 = NOT(I17154) +I17159 = NOT(g13350) +g15579 = NOT(I17159) +g15580 = NOT(g13242) +I17166 = NOT(g14536) +g15588 = NOT(I17166) +I17173 = NOT(g13716) +g15595 = NOT(I17173) +g15614 = NOT(g14914) +I17181 = NOT(g13745) +g15615 = NOT(I17181) +I17188 = NOT(g13782) +g15634 = NOT(I17188) +g15655 = NOT(g13202) +I17198 = NOT(g13809) +g15656 = NOT(I17198) +I17207 = NOT(g13835) +g15680 = NOT(I17207) +g15705 = NOT(g13217) +I17228 = NOT(g13350) +g15714 = NOT(I17228) +g15731 = NOT(g13326) +I17249 = NOT(g13605) +g15733 = NOT(I17249) +g15739 = NOT(g13284) +g15740 = NOT(g13342) +g15746 = NOT(g13121) +g15747 = NOT(g13307) +g15750 = NOT(g13291) +g15755 = NOT(g13134) +g15756 = NOT(g13315) +I17276 = NOT(g13605) +g15758 = NOT(I17276) +g15799 = NOT(g13110) +I17302 = NOT(g14044) +g15806 = NOT(I17302) +g15811 = NOT(g13125) +I17314 = NOT(g14078) +g15816 = NOT(I17314) +I17324 = NOT(g14119) +g15824 = NOT(I17324) +g15830 = NOT(g13432) +g15831 = NOT(g13385) +g15842 = NOT(g13469) +I17355 = NOT(g14591) +g15862 = NOT(I17355) +I17374 = NOT(g13638) +g15885 = NOT(I17374) +I17392 = NOT(g13680) +g15915 = NOT(I17392) +I17395 = NOT(g12952) +g15932 = NOT(I17395) +I17401 = NOT(g13394) +g15938 = NOT(I17401) +I17416 = NOT(g13806) +g15969 = NOT(I17416) +I17420 = NOT(g13394) +g15979 = NOT(I17420) +I17425 = NOT(g13416) +g16000 = NOT(I17425) +g16030 = NOT(g13570) +I17436 = NOT(g13416) +g16031 = NOT(I17436) +I17442 = NOT(g13638) +g16053 = NOT(I17442) +g16075 = NOT(g13597) +I17456 = NOT(g13680) +g16077 = NOT(I17456) +g16096 = NOT(g13530) +g16099 = NOT(g13437) +I17471 = NOT(g13394) +g16100 = NOT(I17471) +g16123 = NOT(g13530) +g16124 = NOT(g13555) +g16127 = NOT(g13437) +I17488 = NOT(g13394) +g16129 = NOT(I17488) +I17491 = NOT(g13416) +g16136 = NOT(I17491) +g16158 = NOT(g13555) +g16159 = NOT(g13584) +g16162 = NOT(g13437) +I17507 = NOT(g13416) +g16164 = NOT(I17507) +g16171 = NOT(g13530) +g16172 = NOT(g13584) +g16180 = NOT(g13437) +g16182 = NOT(g13846) +g16186 = NOT(g13555) +g16195 = NOT(g13437) +g16197 = NOT(g13861) +g16200 = NOT(g13584) +g16206 = NOT(g13437) +g16214 = NOT(g13437) +I17557 = NOT(g14510) +g16216 = NOT(I17557) +g16223 = NOT(g13437) +I17569 = NOT(g14564) +g16228 = NOT(I17569) +g16235 = NOT(g13437) +I17590 = NOT(g14591) +g16249 = NOT(I17590) +g16280 = NOT(g13330) +I17609 = NOT(g13510) +g16284 = NOT(I17609) +I17612 = NOT(g13250) +g16285 = NOT(I17612) +I17615 = NOT(g13251) +g16286 = NOT(I17615) +g16289 = NOT(g13223) +g16290 = NOT(g13260) +I17626 = NOT(g14582) +g16300 = NOT(I17626) +g16305 = NOT(g13346) +I17633 = NOT(g13258) +g16307 = NOT(I17633) +I17636 = NOT(g14252) +g16308 = NOT(I17636) +I17639 = NOT(g13350) +g16309 = NOT(I17639) +g16310 = NOT(g13223) +g16311 = NOT(g13273) +g16320 = NOT(g14454) +I17650 = NOT(g13271) +g16322 = NOT(I17650) +I17653 = NOT(g14276) +g16323 = NOT(I17653) +g16325 = NOT(g13223) +I17658 = NOT(g13394) +g16326 = NOT(I17658) +I17661 = NOT(g13329) +g16349 = NOT(I17661) +g16423 = NOT(g14066) +I17668 = NOT(g13279) +g16428 = NOT(I17668) +I17671 = NOT(g13280) +g16429 = NOT(I17671) +I17675 = NOT(g13394) +g16431 = NOT(I17675) +I17679 = NOT(g13416) +g16449 = NOT(I17679) +g16472 = NOT(g14098) +g16473 = NOT(g13977) +g16475 = NOT(g14107) +g16482 = NOT(g13464) +I17695 = NOT(g14330) +g16487 = NOT(I17695) +I17699 = NOT(g13416) +g16489 = NOT(I17699) +I17704 = NOT(g13144) +g16508 = NOT(I17704) +g16509 = NOT(g13873) +g16510 = NOT(g14008) +g16511 = NOT(g14130) +g16512 = NOT(g14015) +g16514 = NOT(g14139) +g16515 = NOT(g13486) +g16521 = NOT(g13543) +g16522 = NOT(g13889) +g16523 = NOT(g14041) +I17723 = NOT(g13177) +g16525 = NOT(I17723) +g16526 = NOT(g13898) +g16527 = NOT(g14048) +g16528 = NOT(g14154) +g16529 = NOT(g14055) +g16530 = NOT(g14454) +I17733 = NOT(g14844) +g16533 = NOT(I17733) +I17744 = NOT(g14912) +g16540 = NOT(I17744) +I17747 = NOT(g13298) +g16577 = NOT(I17747) +I17750 = NOT(g14383) +g16578 = NOT(I17750) +g16579 = NOT(g13267) +I17754 = NOT(g13494) +g16580 = NOT(I17754) +g16582 = NOT(g13915) +g16583 = NOT(g14069) +g16584 = NOT(g13920) +g16585 = NOT(g14075) +I17763 = NOT(g13191) +g16587 = NOT(I17763) +g16588 = NOT(g13929) +g16589 = NOT(g14082) +I17772 = NOT(g14888) +g16594 = NOT(I17772) +I17780 = NOT(g13303) +g16600 = NOT(I17780) +I17783 = NOT(g13304) +g16601 = NOT(I17783) +g16602 = NOT(g14101) +I17787 = NOT(g3267) +g16603 = NOT(I17787) +g16605 = NOT(g13955) +g16606 = NOT(g14110) +g16607 = NOT(g13960) +g16608 = NOT(g14116) +g16609 = NOT(g14454) +I17801 = NOT(g14936) +g16615 = NOT(I17801) +I17808 = NOT(g13311) +g16620 = NOT(I17808) +g16622 = NOT(g14104) +g16623 = NOT(g14127) +I17814 = NOT(g3274) +g16624 = NOT(I17814) +g16626 = NOT(g14133) +I17819 = NOT(g3618) +g16627 = NOT(I17819) +g16629 = NOT(g13990) +g16630 = NOT(g14142) +g16631 = NOT(g14454) +g16632 = NOT(g14454) +I17834 = NOT(g14977) +g16640 = NOT(I17834) +I17839 = NOT(g13412) +g16643 = NOT(I17839) +I17842 = NOT(g13051) +g16644 = NOT(I17842) +g16645 = NOT(g13756) +g16651 = NOT(g14005) +g16652 = NOT(g13892) +g16654 = NOT(g14136) +g16655 = NOT(g14151) +I17852 = NOT(g3625) +g16656 = NOT(I17852) +g16658 = NOT(g14157) +I17857 = NOT(g3969) +g16659 = NOT(I17857) +g16661 = NOT(g14454) +I17873 = NOT(g15017) +g16675 = NOT(I17873) +I17876 = NOT(g13070) +g16676 = NOT(I17876) +I17879 = NOT(g14386) +g16677 = NOT(I17879) +g16680 = NOT(g13223) +g16684 = NOT(g14223) +g16685 = NOT(g14038) +I17892 = NOT(g3325) +g16686 = NOT(I17892) +g16688 = NOT(g14045) +g16689 = NOT(g13923) +g16691 = NOT(g14160) +g16692 = NOT(g14170) +I17901 = NOT(g3976) +g16693 = NOT(I17901) +g16695 = NOT(g14454) +I17916 = NOT(g13087) +g16708 = NOT(I17916) +I17919 = NOT(g14609) +g16709 = NOT(I17919) +g16712 = NOT(g13223) +g16716 = NOT(g13948) +g16717 = NOT(g13951) +I17932 = NOT(g3310) +g16718 = NOT(I17932) +g16720 = NOT(g14234) +g16721 = NOT(g14072) +I17938 = NOT(g3676) +g16722 = NOT(I17938) +g16724 = NOT(g14079) +g16725 = NOT(g13963) +g16726 = NOT(g14454) +g16727 = NOT(g14454) +I17956 = NOT(g14562) +g16738 = NOT(I17956) +g16739 = NOT(g13223) +g16740 = NOT(g13980) +g16742 = NOT(g13983) +g16743 = NOT(g13986) +I17964 = NOT(g3661) +g16744 = NOT(I17964) +g16746 = NOT(g14258) +g16747 = NOT(g14113) +I17970 = NOT(g4027) +g16748 = NOT(I17970) +g16750 = NOT(g14454) +I17976 = NOT(g13638) +g16752 = NOT(I17976) +I17989 = NOT(g14173) +g16767 = NOT(I17989) +g16768 = NOT(g13223) +g16769 = NOT(g13530) +g16771 = NOT(g14018) +g16773 = NOT(g14021) +g16774 = NOT(g14024) +I17999 = NOT(g4012) +g16775 = NOT(I17999) +I18003 = NOT(g13638) +g16777 = NOT(I18003) +I18006 = NOT(g13638) +g16782 = NOT(I18006) +I18009 = NOT(g13680) +g16795 = NOT(I18009) +g16809 = NOT(g14387) +g16812 = NOT(g13555) +g16814 = NOT(g14058) +I18028 = NOT(g13638) +g16816 = NOT(I18028) +I18031 = NOT(g13680) +g16821 = NOT(I18031) +I18034 = NOT(g13680) +g16826 = NOT(I18034) +g16853 = NOT(g13584) +I18048 = NOT(g13638) +g16856 = NOT(I18048) +I18051 = NOT(g13680) +g16861 = NOT(I18051) +I18060 = NOT(g14198) +g16872 = NOT(I18060) +I18063 = NOT(g14357) +g16873 = NOT(I18063) +I18066 = NOT(g3317) +g16874 = NOT(I18066) +I18071 = NOT(g13680) +g16877 = NOT(I18071) +I18078 = NOT(g13350) +g16886 = NOT(I18078) +I18083 = NOT(g13394) +g16897 = NOT(I18083) +I18086 = NOT(g13856) +g16920 = NOT(I18086) +I18089 = NOT(g13144) +g16923 = NOT(I18089) +I18092 = NOT(g3668) +g16924 = NOT(I18092) +I18101 = NOT(g13416) +g16931 = NOT(I18101) +I18104 = NOT(g13177) +g16954 = NOT(I18104) +I18107 = NOT(g4019) +g16955 = NOT(I18107) +g16958 = NOT(g14238) +I18114 = NOT(g14509) +g16960 = NOT(I18114) +I18117 = NOT(g13302) +g16963 = NOT(I18117) +I18120 = NOT(g13350) +g16964 = NOT(I18120) +g16966 = NOT(g14291) +I18125 = NOT(g13191) +g16967 = NOT(I18125) +g16968 = NOT(g14238) +g16969 = NOT(g14262) +I18131 = NOT(g13350) +g16971 = NOT(I18131) +I18135 = NOT(g13144) +g16987 = NOT(I18135) +I18138 = NOT(g14277) +g17010 = NOT(I18138) +g17013 = NOT(g14262) +g17014 = NOT(g14297) +I18143 = NOT(g13350) +g17015 = NOT(I18143) +g17056 = NOT(g13437) +I18148 = NOT(g13526) +g17058 = NOT(I18148) +I18151 = NOT(g13144) +g17059 = NOT(I18151) +I18154 = NOT(g13177) +g17062 = NOT(I18154) +g17085 = NOT(g14238) +g17086 = NOT(g14297) +g17087 = NOT(g14321) +I18160 = NOT(g14441) +g17088 = NOT(I18160) +g17092 = NOT(g14011) +I18165 = NOT(g13177) +g17093 = NOT(I18165) +I18168 = NOT(g13191) +g17096 = NOT(I18168) +g17120 = NOT(g14262) +g17121 = NOT(g14321) +g17122 = NOT(g14348) +g17124 = NOT(g14051) +I18177 = NOT(g13191) +g17125 = NOT(I18177) +I18180 = NOT(g13605) +g17128 = NOT(I18180) +g17135 = NOT(g14297) +g17136 = NOT(g14348) +I18191 = NOT(g14385) +g17141 = NOT(I18191) +g17144 = NOT(g14085) +g17147 = NOT(g14321) +g17154 = NOT(g14348) +I18205 = NOT(g14563) +g17155 = NOT(I18205) +g17157 = NOT(g13350) +I18214 = NOT(g12918) +g17178 = NOT(I18214) +I18221 = NOT(g13605) +g17183 = NOT(I18221) +I18224 = NOT(g13793) +g17188 = NOT(I18224) +g17189 = NOT(g14708) +I18233 = NOT(g14639) +g17197 = NOT(I18233) +I18238 = NOT(g13144) +g17200 = NOT(I18238) +g17216 = NOT(g14454) +I18245 = NOT(g14676) +g17221 = NOT(I18245) +I18248 = NOT(g12938) +g17224 = NOT(I18248) +I18252 = NOT(g13177) +g17226 = NOT(I18252) +g17242 = NOT(g14454) +I18259 = NOT(g12946) +g17247 = NOT(I18259) +I18262 = NOT(g13857) +g17248 = NOT(I18262) +I18265 = NOT(g13350) +g17249 = NOT(I18265) +I18270 = NOT(g13191) +g17271 = NOT(I18270) +I18276 = NOT(g1075) +g17291 = NOT(I18276) +I18280 = NOT(g12951) +g17296 = NOT(I18280) +g17301 = NOT(g14454) +I18285 = NOT(g13638) +g17302 = NOT(I18285) +g17308 = NOT(g14876) +I18293 = NOT(g1079) +g17316 = NOT(I18293) +I18297 = NOT(g1418) +g17320 = NOT(I18297) +I18301 = NOT(g12976) +g17324 = NOT(I18301) +I18304 = NOT(g14790) +g17325 = NOT(I18304) +I18307 = NOT(g12977) +g17326 = NOT(I18307) +I18310 = NOT(g12978) +g17327 = NOT(I18310) +I18313 = NOT(g13350) +g17328 = NOT(I18313) +g17366 = NOT(g14454) +I18320 = NOT(g13605) +g17367 = NOT(I18320) +I18323 = NOT(g13680) +g17384 = NOT(I18323) +g17389 = NOT(g14915) +g17390 = NOT(g14755) +g17392 = NOT(g14924) +I18333 = NOT(g1083) +g17400 = NOT(I18333) +I18337 = NOT(g1422) +g17404 = NOT(I18337) +I18341 = NOT(g14308) +g17408 = NOT(I18341) +I18344 = NOT(g13003) +g17409 = NOT(I18344) +g17410 = NOT(g12955) +g17411 = NOT(g14454) +I18350 = NOT(g13716) +g17413 = NOT(I18350) +g17414 = NOT(g14627) +g17415 = NOT(g14797) +g17416 = NOT(g14956) +g17417 = NOT(g14804) +g17419 = NOT(g14965) +I18360 = NOT(g1426) +g17423 = NOT(I18360) +I18364 = NOT(g13009) +g17427 = NOT(I18364) +I18367 = NOT(g13010) +g17428 = NOT(I18367) +I18370 = NOT(g14873) +g17429 = NOT(I18370) +I18373 = NOT(g13011) +g17430 = NOT(I18373) +I18376 = NOT(g14332) +g17431 = NOT(I18376) +I18379 = NOT(g13012) +g17432 = NOT(I18379) +I18382 = NOT(g13350) +g17433 = NOT(I18382) +g17465 = NOT(g12955) +g17466 = NOT(g12983) +g17467 = NOT(g14339) +g17470 = NOT(g14454) +g17471 = NOT(g14454) +g17472 = NOT(g14656) +g17473 = NOT(g14841) +I18398 = NOT(g13745) +g17475 = NOT(I18398) +g17476 = NOT(g14665) +g17477 = NOT(g14848) +g17478 = NOT(g14996) +g17479 = NOT(g14855) +g17481 = NOT(g15005) +I18408 = NOT(g13017) +g17485 = NOT(I18408) +I18411 = NOT(g13018) +g17486 = NOT(I18411) +I18414 = NOT(g14359) +g17487 = NOT(I18414) +g17489 = NOT(g12955) +g17491 = NOT(g12983) +g17494 = NOT(g14339) +g17496 = NOT(g14683) +g17497 = NOT(g14879) +g17498 = NOT(g14688) +g17499 = NOT(g14885) +I18434 = NOT(g13782) +g17501 = NOT(I18434) +g17502 = NOT(g14697) +g17503 = NOT(g14892) +g17504 = NOT(g15021) +g17505 = NOT(g14899) +g17507 = NOT(g15030) +I18443 = NOT(g13027) +g17508 = NOT(I18443) +I18446 = NOT(g13028) +g17509 = NOT(I18446) +g17512 = NOT(g12983) +g17518 = NOT(g14918) +I18460 = NOT(g5276) +g17519 = NOT(I18460) +g17521 = NOT(g14727) +g17522 = NOT(g14927) +g17523 = NOT(g14732) +g17524 = NOT(g14933) +I18469 = NOT(g13809) +g17526 = NOT(I18469) +g17527 = NOT(g14741) +g17528 = NOT(g14940) +g17529 = NOT(g15039) +g17530 = NOT(g14947) +I18476 = NOT(g14031) +g17531 = NOT(I18476) +I18479 = NOT(g13041) +g17532 = NOT(I18479) +I18482 = NOT(g13350) +g17533 = NOT(I18482) +g17573 = NOT(g12911) +g17575 = NOT(g14921) +g17576 = NOT(g14953) +I18504 = NOT(g5283) +g17577 = NOT(I18504) +g17579 = NOT(g14959) +I18509 = NOT(g5623) +g17580 = NOT(I18509) +g17582 = NOT(g14768) +g17583 = NOT(g14968) +g17584 = NOT(g14773) +g17585 = NOT(g14974) +I18518 = NOT(g13835) +g17587 = NOT(I18518) +g17588 = NOT(g14782) +g17589 = NOT(g14981) +I18523 = NOT(g14443) +g17590 = NOT(I18523) +I18526 = NOT(g13055) +g17591 = NOT(I18526) +g17599 = NOT(g14794) +g17600 = NOT(g14659) +g17602 = NOT(g14962) +g17603 = NOT(g14993) +I18555 = NOT(g5630) +g17604 = NOT(I18555) +g17606 = NOT(g14999) +I18560 = NOT(g5969) +g17607 = NOT(I18560) +g17609 = NOT(g14817) +g17610 = NOT(g15008) +g17611 = NOT(g14822) +g17612 = NOT(g15014) +I18571 = NOT(g13074) +g17614 = NOT(I18571) +I18574 = NOT(g13075) +g17615 = NOT(I18574) +g17616 = NOT(g14309) +g17637 = NOT(g12933) +g17638 = NOT(g14838) +I18600 = NOT(g5335) +g17639 = NOT(I18600) +g17641 = NOT(g14845) +g17642 = NOT(g14691) +g17644 = NOT(g15002) +g17645 = NOT(g15018) +I18609 = NOT(g5976) +g17646 = NOT(I18609) +g17648 = NOT(g15024) +I18614 = NOT(g6315) +g17649 = NOT(I18614) +g17651 = NOT(g14868) +g17652 = NOT(g15033) +g17672 = NOT(g14720) +g17673 = NOT(g14723) +I18647 = NOT(g5320) +g17674 = NOT(I18647) +g17676 = NOT(g12941) +g17677 = NOT(g14882) +I18653 = NOT(g5681) +g17678 = NOT(I18653) +g17680 = NOT(g14889) +g17681 = NOT(g14735) +g17683 = NOT(g15027) +g17684 = NOT(g15036) +I18662 = NOT(g6322) +g17685 = NOT(I18662) +g17687 = NOT(g15042) +I18667 = NOT(g6661) +g17688 = NOT(I18667) +I18674 = NOT(g13101) +g17691 = NOT(I18674) +g17707 = NOT(g14758) +g17709 = NOT(g14761) +g17710 = NOT(g14764) +I18694 = NOT(g5666) +g17711 = NOT(I18694) +g17713 = NOT(g12947) +g17714 = NOT(g14930) +I18700 = NOT(g6027) +g17715 = NOT(I18700) +g17717 = NOT(g14937) +g17718 = NOT(g14776) +g17720 = NOT(g15045) +g17721 = NOT(g12915) +I18709 = NOT(g6668) +g17722 = NOT(I18709) +g17733 = NOT(g14238) +g17735 = NOT(g14807) +g17737 = NOT(g14810) +g17738 = NOT(g14813) +I18728 = NOT(g6012) +g17739 = NOT(I18728) +g17741 = NOT(g12972) +g17742 = NOT(g14971) +I18734 = NOT(g6373) +g17743 = NOT(I18734) +g17745 = NOT(g14978) +g17746 = NOT(g14825) +g17754 = NOT(g14262) +g17756 = NOT(g14858) +g17758 = NOT(g14861) +g17759 = NOT(g14864) +I18752 = NOT(g6358) +g17760 = NOT(I18752) +g17762 = NOT(g13000) +g17763 = NOT(g15011) +I18758 = NOT(g6719) +g17764 = NOT(I18758) +g17772 = NOT(g14297) +g17774 = NOT(g14902) +g17776 = NOT(g14905) +g17777 = NOT(g14908) +I18778 = NOT(g6704) +g17778 = NOT(I18778) +I18788 = NOT(g13138) +g17782 = NOT(I18788) +I18795 = NOT(g5327) +g17787 = NOT(I18795) +g17789 = NOT(g14321) +g17791 = NOT(g14950) +g17794 = NOT(g13350) +g17811 = NOT(g12925) +I18810 = NOT(g13716) +g17812 = NOT(I18810) +I18813 = NOT(g5673) +g17813 = NOT(I18813) +g17815 = NOT(g14348) +I18822 = NOT(g13745) +g17818 = NOT(I18822) +I18825 = NOT(g6019) +g17819 = NOT(I18825) +I18829 = NOT(g13350) +g17821 = NOT(I18829) +I18832 = NOT(g13782) +g17844 = NOT(I18832) +I18835 = NOT(g6365) +g17845 = NOT(I18835) +I18839 = NOT(g13716) +g17847 = NOT(I18839) +I18842 = NOT(g13809) +g17870 = NOT(I18842) +I18845 = NOT(g6711) +g17871 = NOT(I18845) +I18849 = NOT(g14290) +g17873 = NOT(I18849) +I18852 = NOT(g13716) +g17926 = NOT(I18852) +I18855 = NOT(g13745) +g17929 = NOT(I18855) +I18858 = NOT(g13835) +g17952 = NOT(I18858) +I18861 = NOT(g14307) +g17953 = NOT(I18861) +I18865 = NOT(g14314) +g17955 = NOT(I18865) +I18868 = NOT(g14315) +g18008 = NOT(I18868) +g18061 = NOT(g14800) +I18872 = NOT(g13745) +g18062 = NOT(I18872) +I18875 = NOT(g13782) +g18065 = NOT(I18875) +g18088 = NOT(g13267) +I18879 = NOT(g13267) +g18091 = NOT(I18879) +I18882 = NOT(g16580) +g18092 = NOT(I18882) +I18885 = NOT(g16643) +g18093 = NOT(I18885) +I18888 = NOT(g16644) +g18094 = NOT(I18888) +I18891 = NOT(g16676) +g18095 = NOT(I18891) +I18894 = NOT(g16708) +g18096 = NOT(I18894) +I18897 = NOT(g16738) +g18097 = NOT(I18897) +I18900 = NOT(g16767) +g18098 = NOT(I18900) +I18903 = NOT(g16872) +g18099 = NOT(I18903) +I18906 = NOT(g16963) +g18100 = NOT(I18906) +I18909 = NOT(g16873) +g18101 = NOT(I18909) +I18912 = NOT(g15050) +g18102 = NOT(I18912) +I19012 = NOT(g15060) +g18200 = NOT(I19012) +I19235 = NOT(g15078) +g18421 = NOT(I19235) +I19238 = NOT(g15079) +g18422 = NOT(I19238) +I19345 = NOT(g15083) +g18527 = NOT(I19345) +I19348 = NOT(g15084) +g18528 = NOT(I19348) +I19384 = NOT(g15085) +g18562 = NOT(I19384) +I19484 = NOT(g15122) +g18660 = NOT(I19484) +I19487 = NOT(g15125) +g18661 = NOT(I19487) +g18827 = NOT(g16000) +g18828 = NOT(g17955) +g18829 = NOT(g15171) +g18830 = NOT(g18008) +g18831 = NOT(g15224) +g18832 = NOT(g15634) +I19661 = NOT(g17587) +g18833 = NOT(I19661) +g18874 = NOT(g15938) +g18875 = NOT(g15171) +g18876 = NOT(g15373) +g18877 = NOT(g15224) +g18878 = NOT(g15426) +g18880 = NOT(g15656) +I19671 = NOT(g15932) +g18881 = NOT(I19671) +I19674 = NOT(g15932) +g18882 = NOT(I19674) +g18883 = NOT(g15938) +g18884 = NOT(g15938) +g18885 = NOT(g15979) +g18886 = NOT(g16000) +g18887 = NOT(g15373) +g18888 = NOT(g15426) +g18889 = NOT(g15509) +g18891 = NOT(g16053) +g18892 = NOT(g15680) +g18894 = NOT(g16000) +g18895 = NOT(g16000) +g18896 = NOT(g16031) +g18897 = NOT(g15509) +g18898 = NOT(g15566) +g18903 = NOT(g15758) +g18904 = NOT(g16053) +g18905 = NOT(g16077) +g18907 = NOT(g15979) +g18908 = NOT(g16100) +g18911 = NOT(g15169) +g18916 = NOT(g16053) +g18917 = NOT(g16077) +I19704 = NOT(g17653) +g18918 = NOT(I19704) +I19707 = NOT(g17590) +g18926 = NOT(I19707) +g18929 = NOT(g16100) +g18930 = NOT(g15789) +g18931 = NOT(g16031) +g18932 = NOT(g16136) +g18938 = NOT(g16053) +g18939 = NOT(g16077) +I19719 = NOT(g17431) +g18940 = NOT(I19719) +g18944 = NOT(g15938) +g18945 = NOT(g16100) +g18946 = NOT(g16100) +g18947 = NOT(g16136) +g18948 = NOT(g15800) +g18952 = NOT(g16053) +g18953 = NOT(g16077) +g18954 = NOT(g17427) +I19734 = NOT(g17725) +g18957 = NOT(I19734) +g18975 = NOT(g15938) +g18976 = NOT(g16100) +g18977 = NOT(g16100) +g18978 = NOT(g16000) +g18979 = NOT(g16136) +g18980 = NOT(g16136) +g18983 = NOT(g16077) +g18984 = NOT(g17486) +g18988 = NOT(g15979) +g18989 = NOT(g16000) +g18990 = NOT(g16136) +g18991 = NOT(g16136) +I19756 = NOT(g17812) +g18997 = NOT(I19756) +I19759 = NOT(g17767) +g19050 = NOT(I19759) +I19762 = NOT(g15732) +g19061 = NOT(I19762) +g19067 = NOT(g15979) +g19068 = NOT(g16031) +g19071 = NOT(g15591) +I19772 = NOT(g17818) +g19074 = NOT(I19772) +I19775 = NOT(g17780) +g19127 = NOT(I19775) +I19778 = NOT(g17781) +g19128 = NOT(I19778) +g19144 = NOT(g16031) +g19146 = NOT(g15574) +I19786 = NOT(g17844) +g19147 = NOT(I19786) +I19789 = NOT(g17793) +g19200 = NOT(I19789) +g19208 = NOT(g17367) +I19796 = NOT(g17870) +g19210 = NOT(I19796) +I19799 = NOT(g17817) +g19263 = NOT(I19799) +I19802 = NOT(g15727) +g19264 = NOT(I19802) +g19273 = NOT(g16100) +g19276 = NOT(g17367) +I19813 = NOT(g17952) +g19277 = NOT(I19813) +g19330 = NOT(g17326) +I19818 = NOT(g1056) +g19334 = NOT(I19818) +g19343 = NOT(g16136) +g19345 = NOT(g17591) +g19351 = NOT(g17367) +g19352 = NOT(g15758) +I19831 = NOT(g16533) +g19353 = NOT(I19831) +g19355 = NOT(g16027) +I19837 = NOT(g1399) +g19357 = NOT(I19837) +g19360 = NOT(g16249) +I19843 = NOT(g16594) +g19361 = NOT(I19843) +g19362 = NOT(g16072) +g19364 = NOT(g15825) +g19365 = NOT(g16249) +g19366 = NOT(g15885) +I19851 = NOT(g16615) +g19367 = NOT(I19851) +g19368 = NOT(g16326) +g19369 = NOT(g15995) +g19370 = NOT(g15915) +I19857 = NOT(g16640) +g19371 = NOT(I19857) +g19373 = NOT(g16449) +g19374 = NOT(g16047) +I19863 = NOT(g16675) +g19375 = NOT(I19863) +g19376 = NOT(g17509) +g19379 = NOT(g17327) +g19385 = NOT(g16326) +g19386 = NOT(g16431) +g19387 = NOT(g16431) +g19389 = NOT(g17532) +g19394 = NOT(g16326) +g19395 = NOT(g16431) +g19396 = NOT(g16431) +g19397 = NOT(g16449) +g19398 = NOT(g16489) +g19399 = NOT(g16489) +g19407 = NOT(g16268) +g19408 = NOT(g16066) +g19409 = NOT(g16431) +g19410 = NOT(g16449) +g19411 = NOT(g16489) +g19412 = NOT(g16489) +g19414 = NOT(g16349) +g19415 = NOT(g15758) +g19416 = NOT(g15885) +g19417 = NOT(g17178) +g19421 = NOT(g16326) +g19427 = NOT(g16292) +g19428 = NOT(g16090) +g19429 = NOT(g16489) +g19431 = NOT(g16249) +g19432 = NOT(g15885) +g19433 = NOT(g15915) +g19434 = NOT(g16326) +g19435 = NOT(g16449) +g19437 = NOT(g16349) +g19438 = NOT(g16249) +g19439 = NOT(g15885) +g19440 = NOT(g15915) +g19443 = NOT(g16449) +g19445 = NOT(g15915) +I19917 = NOT(g18088) +g19446 = NOT(I19917) +g19451 = NOT(g15938) +g19452 = NOT(g16326) +g19454 = NOT(g16349) +I19927 = NOT(g17408) +g19458 = NOT(I19927) +g19468 = NOT(g15938) +g19469 = NOT(g16326) +g19470 = NOT(g16000) +g19471 = NOT(g16449) +g19472 = NOT(g16349) +g19473 = NOT(g16349) +g19476 = NOT(g16326) +g19477 = NOT(g16431) +g19478 = NOT(g16000) +g19479 = NOT(g16449) +g19480 = NOT(g16349) +g19481 = NOT(g16349) +g19482 = NOT(g16349) +g19489 = NOT(g16449) +g19490 = NOT(g16489) +g19491 = NOT(g16349) +g19492 = NOT(g16349) +g19493 = NOT(g16349) +g19494 = NOT(g16349) +g19498 = NOT(g16752) +g19499 = NOT(g16782) +g19502 = NOT(g15674) +g19503 = NOT(g16349) +g19504 = NOT(g16349) +g19505 = NOT(g16349) +g19517 = NOT(g16777) +g19518 = NOT(g16239) +g19519 = NOT(g16795) +g19520 = NOT(g16826) +g19523 = NOT(g16100) +g19524 = NOT(g15695) +g19526 = NOT(g16349) +g19527 = NOT(g16349) +g19528 = NOT(g16349) +g19529 = NOT(g16349) +g19531 = NOT(g16816) +g19532 = NOT(g16821) +g19533 = NOT(g16261) +g19537 = NOT(g15938) +g19538 = NOT(g16100) +g19539 = NOT(g16129) +g19541 = NOT(g16136) +g19542 = NOT(g16349) +g19543 = NOT(g16349) +g19544 = NOT(g16349) +g19552 = NOT(g16856) +g19553 = NOT(g16782) +g19554 = NOT(g16861) +g19558 = NOT(g15938) +g19559 = NOT(g16129) +g19565 = NOT(g16000) +g19566 = NOT(g16136) +g19567 = NOT(g16164) +g19569 = NOT(g16349) +g19570 = NOT(g16349) +g19573 = NOT(g16877) +g19574 = NOT(g16826) +g19577 = NOT(g16129) +g19579 = NOT(g16000) +g19580 = NOT(g16164) +g19586 = NOT(g16349) +I20035 = NOT(g15706) +g19592 = NOT(I20035) +g19600 = NOT(g16164) +g19602 = NOT(g16349) +g19603 = NOT(g16349) +g19606 = NOT(g17614) +g19609 = NOT(g16264) +g19612 = NOT(g16897) +g19617 = NOT(g16349) +g19618 = NOT(g16349) +g19620 = NOT(g17296) +g19626 = NOT(g17409) +g19629 = NOT(g17015) +g19630 = NOT(g16897) +g19633 = NOT(g16931) +g19634 = NOT(g16349) +g19635 = NOT(g16349) +g19636 = NOT(g16987) +g19638 = NOT(g17324) +g19644 = NOT(g17953) +g19649 = NOT(g17015) +g19650 = NOT(g16971) +g19652 = NOT(g16897) +g19653 = NOT(g16897) +g19654 = NOT(g16931) +g19657 = NOT(g16349) +g19658 = NOT(g16987) +g19659 = NOT(g17062) +g19662 = NOT(g17432) +g19666 = NOT(g17188) +g19670 = NOT(g16897) +g19672 = NOT(g16931) +g19673 = NOT(g16931) +g19675 = NOT(g16987) +g19676 = NOT(g17062) +g19677 = NOT(g17096) +g19678 = NOT(g16752) +g19679 = NOT(g16782) +g19682 = NOT(g17015) +g19683 = NOT(g16931) +g19685 = NOT(g16987) +g19686 = NOT(g17062) +g19687 = NOT(g17096) +g19688 = NOT(g16777) +g19689 = NOT(g16795) +g19690 = NOT(g16826) +g19694 = NOT(g16429) +g19695 = NOT(g17015) +g19696 = NOT(g17015) +g19697 = NOT(g16886) +g19698 = NOT(g16971) +I20116 = NOT(g15737) +g19699 = NOT(I20116) +g19709 = NOT(g16987) +g19710 = NOT(g17059) +g19711 = NOT(g17062) +g19712 = NOT(g17096) +g19713 = NOT(g16816) +g19714 = NOT(g16821) +g19718 = NOT(g17015) +g19719 = NOT(g16897) +I20130 = NOT(g15748) +g19720 = NOT(I20130) +g19730 = NOT(g17062) +g19731 = NOT(g17093) +g19732 = NOT(g17096) +g19733 = NOT(g16856) +g19734 = NOT(g16861) +g19737 = NOT(g17015) +g19738 = NOT(g15992) +g19739 = NOT(g16931) +g19741 = NOT(g16987) +g19742 = NOT(g17096) +g19743 = NOT(g17125) +g19744 = NOT(g15885) +g19745 = NOT(g16877) +g19747 = NOT(g17015) +g19748 = NOT(g17015) +g19750 = NOT(g16326) +g19751 = NOT(g16044) +g19753 = NOT(g16987) +g19754 = NOT(g17062) +g19755 = NOT(g15915) +g19757 = NOT(g17224) +g19760 = NOT(g17015) +g19761 = NOT(g17015) +g19762 = NOT(g16326) +g19763 = NOT(g16431) +g19765 = NOT(g16897) +g19766 = NOT(g16449) +g19769 = NOT(g16987) +g19770 = NOT(g17062) +g19771 = NOT(g17096) +g19772 = NOT(g17183) +g19773 = NOT(g17615) +g19776 = NOT(g17015) +g19777 = NOT(g17015) +g19779 = NOT(g16431) +g19780 = NOT(g16449) +g19781 = NOT(g16489) +g19783 = NOT(g16931) +g19785 = NOT(g16987) +g19786 = NOT(g17062) +g19787 = NOT(g17096) +g19789 = NOT(g17015) +g19790 = NOT(g16971) +g19794 = NOT(g16489) +g19798 = NOT(g17200) +g19799 = NOT(g17062) +g19800 = NOT(g17096) +I20216 = NOT(g15862) +g19801 = NOT(I20216) +g19852 = NOT(g17015) +g19860 = NOT(g17226) +g19861 = NOT(g17096) +I20233 = NOT(g17487) +g19862 = NOT(I20233) +g19865 = NOT(g15885) +g19866 = NOT(g16540) +g19869 = NOT(g16540) +g19872 = NOT(g17015) +g19878 = NOT(g17271) +g19881 = NOT(g15915) +g19882 = NOT(g16540) +g19885 = NOT(g17249) +g19902 = NOT(g17200) +g19905 = NOT(g15885) +g19908 = NOT(g16540) +g19912 = NOT(g17328) +g19915 = NOT(g16349) +g19930 = NOT(g17200) +g19931 = NOT(g17200) +g19947 = NOT(g17226) +g19950 = NOT(g15885) +g19952 = NOT(g15915) +g19954 = NOT(g16540) +g19957 = NOT(g16540) +g19960 = NOT(g17433) +g19961 = NOT(g17328) +g19963 = NOT(g16326) +g19964 = NOT(g17200) +g19979 = NOT(g17226) +g19980 = NOT(g17226) +g19996 = NOT(g17271) +g19998 = NOT(g15915) +g20004 = NOT(g17249) +g20005 = NOT(g17433) +g20006 = NOT(g17328) +g20008 = NOT(g16449) +g20009 = NOT(g16349) +g20010 = NOT(g17226) +g20025 = NOT(g17271) +g20026 = NOT(g17271) +g20028 = NOT(g15371) +g20033 = NOT(g16579) +g20035 = NOT(g16430) +g20036 = NOT(g17433) +g20037 = NOT(g17328) +g20038 = NOT(g17328) +g20040 = NOT(g17271) +g20041 = NOT(g15569) +g20046 = NOT(g16540) +I20318 = NOT(g16920) +g20049 = NOT(I20318) +I20321 = NOT(g16920) +g20050 = NOT(I20321) +g20052 = NOT(g17533) +g20053 = NOT(g17328) +g20054 = NOT(g17328) +g20057 = NOT(g16349) +g20058 = NOT(g16782) +g20059 = NOT(g17302) +g20060 = NOT(g16540) +g20064 = NOT(g17533) +g20065 = NOT(g16846) +g20066 = NOT(g17433) +g20067 = NOT(g17328) +g20070 = NOT(g16173) +g20071 = NOT(g16826) +g20072 = NOT(g17384) +g20073 = NOT(g16540) +g20078 = NOT(g16846) +g20079 = NOT(g17328) +g20080 = NOT(g17328) +g20085 = NOT(g16187) +I20355 = NOT(g17613) +g20086 = NOT(I20355) +g20087 = NOT(g17249) +g20088 = NOT(g17533) +g20089 = NOT(g17533) +g20090 = NOT(g17433) +g20091 = NOT(g17328) +g20096 = NOT(g16782) +g20097 = NOT(g17691) +I20369 = NOT(g17690) +g20100 = NOT(I20369) +g20101 = NOT(g17533) +g20102 = NOT(g17533) +g20103 = NOT(g17433) +g20104 = NOT(g17433) +g20105 = NOT(g17433) +g20106 = NOT(g17328) +g20110 = NOT(g16897) +g20113 = NOT(g16826) +I20385 = NOT(g16194) +g20114 = NOT(I20385) +I20388 = NOT(g17724) +g20127 = NOT(I20388) +g20128 = NOT(g17533) +g20129 = NOT(g17328) +g20130 = NOT(g17328) +g20132 = NOT(g16931) +I20399 = NOT(g16205) +g20136 = NOT(I20399) +g20144 = NOT(g17533) +g20145 = NOT(g17533) +g20146 = NOT(g17533) +g20147 = NOT(g17328) +g20153 = NOT(g16782) +I20412 = NOT(g16213) +g20154 = NOT(I20412) +g20157 = NOT(g16886) +g20158 = NOT(g16971) +g20159 = NOT(g17533) +g20164 = NOT(g16826) +g20166 = NOT(g16886) +g20167 = NOT(g16971) +g20168 = NOT(g17533) +I20433 = NOT(g16234) +g20175 = NOT(I20433) +g20178 = NOT(g16971) +g20179 = NOT(g17249) +g20180 = NOT(g17533) +g20182 = NOT(g16897) +I20447 = NOT(g16244) +g20189 = NOT(I20447) +g20190 = NOT(g16971) +g20191 = NOT(g17821) +g20192 = NOT(g17268) +g20194 = NOT(g16897) +g20195 = NOT(g16931) +g20197 = NOT(g16987) +g20204 = NOT(g16578) +g20207 = NOT(g17015) +g20208 = NOT(g17533) +g20209 = NOT(g17821) +g20210 = NOT(g16897) +g20211 = NOT(g16931) +g20212 = NOT(g17194) +g20213 = NOT(g17062) +I20495 = NOT(g16283) +g20219 = NOT(I20495) +g20229 = NOT(g17015) +I20499 = NOT(g16224) +g20230 = NOT(I20499) +g20231 = NOT(g17821) +g20232 = NOT(g16931) +g20233 = NOT(g17873) +g20235 = NOT(g15277) +g20237 = NOT(g17213) +g20238 = NOT(g17096) +g20239 = NOT(g17128) +g20240 = NOT(g17847) +g20242 = NOT(g16308) +g20247 = NOT(g17015) +g20265 = NOT(g17821) +g20266 = NOT(g17873) +g20267 = NOT(g17955) +g20268 = NOT(g18008) +g20269 = NOT(g15844) +g20270 = NOT(g15277) +g20272 = NOT(g17239) +g20273 = NOT(g17128) +g20274 = NOT(g17847) +g20275 = NOT(g17929) +g20277 = NOT(g16487) +I20529 = NOT(g16309) +g20283 = NOT(I20529) +g20320 = NOT(g17015) +g20321 = NOT(g17821) +g20322 = NOT(g17873) +g20323 = NOT(g17873) +g20324 = NOT(g17955) +g20325 = NOT(g15171) +g20326 = NOT(g18008) +g20327 = NOT(g15224) +g20328 = NOT(g15867) +g20329 = NOT(g15277) +I20542 = NOT(g16508) +g20330 = NOT(I20542) +g20372 = NOT(g17847) +g20373 = NOT(g17929) +g20374 = NOT(g18065) +g20379 = NOT(g17821) +g20380 = NOT(g17955) +g20381 = NOT(g17955) +g20382 = NOT(g15171) +g20383 = NOT(g15373) +g20384 = NOT(g18008) +g20385 = NOT(g18008) +g20386 = NOT(g15224) +g20387 = NOT(g15426) +g20388 = NOT(g17297) +g20389 = NOT(g15277) +I20562 = NOT(g16525) +g20391 = NOT(I20562) +g20432 = NOT(g17847) +g20433 = NOT(g17929) +g20434 = NOT(g18065) +g20435 = NOT(g15348) +I20569 = NOT(g16486) +g20436 = NOT(I20569) +g20441 = NOT(g17873) +g20442 = NOT(g15171) +g20443 = NOT(g15171) +g20444 = NOT(g15373) +g20445 = NOT(g15224) +g20446 = NOT(g15224) +g20447 = NOT(g15426) +g20448 = NOT(g15509) +g20449 = NOT(g15277) +g20450 = NOT(g15277) +g20451 = NOT(g15277) +g20452 = NOT(g17200) +I20584 = NOT(g16587) +g20453 = NOT(I20584) +g20494 = NOT(g17847) +g20495 = NOT(g17926) +g20496 = NOT(g17929) +g20497 = NOT(g18065) +g20498 = NOT(g15348) +g20499 = NOT(g15483) +g20500 = NOT(g17873) +g20501 = NOT(g17955) +g20502 = NOT(g15373) +g20503 = NOT(g15373) +g20504 = NOT(g18008) +g20505 = NOT(g15426) +g20506 = NOT(g15426) +g20507 = NOT(g15509) +g20508 = NOT(g15277) +g20509 = NOT(g15277) +g20510 = NOT(g17226) +g20511 = NOT(g17929) +g20512 = NOT(g18062) +g20513 = NOT(g18065) +g20514 = NOT(g15348) +g20515 = NOT(g15483) +I20609 = NOT(g16539) +g20516 = NOT(I20609) +g20523 = NOT(g17821) +g20524 = NOT(g17873) +g20525 = NOT(g17955) +g20526 = NOT(g15171) +g20527 = NOT(g18008) +g20528 = NOT(g15224) +g20529 = NOT(g15509) +g20530 = NOT(g15509) +g20531 = NOT(g15907) +g20532 = NOT(g15277) +g20533 = NOT(g17271) +g20534 = NOT(g17183) +g20535 = NOT(g17847) +g20536 = NOT(g18065) +g20537 = NOT(g15345) +g20538 = NOT(g15348) +g20539 = NOT(g15483) +g20540 = NOT(g16646) +g20541 = NOT(g17821) +g20542 = NOT(g17873) +g20543 = NOT(g17955) +g20544 = NOT(g15171) +g20545 = NOT(g15373) +g20546 = NOT(g18008) +g20547 = NOT(g15224) +g20548 = NOT(g15426) +g20549 = NOT(g15277) +g20550 = NOT(g15864) +g20551 = NOT(g17302) +g20552 = NOT(g17847) +g20553 = NOT(g17929) +g20554 = NOT(g15348) +g20555 = NOT(g15480) +g20556 = NOT(g15483) +I20647 = NOT(g17010) +g20557 = NOT(I20647) +I20650 = NOT(g17010) +g20558 = NOT(I20650) +g20560 = NOT(g17328) +g20561 = NOT(g17873) +g20562 = NOT(g17955) +g20563 = NOT(g15171) +g20564 = NOT(g15373) +g20565 = NOT(g18008) +g20566 = NOT(g15224) +g20567 = NOT(g15426) +g20568 = NOT(g15509) +g20569 = NOT(g15277) +g20570 = NOT(g15277) +g20571 = NOT(g15277) +g20572 = NOT(g15833) +g20573 = NOT(g17384) +g20574 = NOT(g17847) +g20575 = NOT(g17929) +g20576 = NOT(g18065) +g20577 = NOT(g15483) +g20578 = NOT(g15563) +g20579 = NOT(g17249) +g20580 = NOT(g17328) +g20582 = NOT(g17873) +g20583 = NOT(g17873) +g20584 = NOT(g17873) +g20585 = NOT(g17955) +g20586 = NOT(g15171) +g20587 = NOT(g15373) +g20588 = NOT(g18008) +g20589 = NOT(g15224) +g20590 = NOT(g15426) +g20591 = NOT(g15509) +g20592 = NOT(g15277) +g20593 = NOT(g15277) +g20594 = NOT(g15277) +g20595 = NOT(g15877) +I20690 = NOT(g15733) +g20596 = NOT(I20690) +g20597 = NOT(g17847) +g20598 = NOT(g17929) +g20599 = NOT(g18065) +g20600 = NOT(g15348) +g20601 = NOT(g17433) +g20603 = NOT(g17873) +g20604 = NOT(g17873) +g20605 = NOT(g17955) +g20606 = NOT(g17955) +g20607 = NOT(g17955) +g20608 = NOT(g15171) +g20609 = NOT(g15373) +g20610 = NOT(g18008) +g20611 = NOT(g18008) +g20612 = NOT(g18008) +g20613 = NOT(g15224) +g20614 = NOT(g15426) +g20615 = NOT(g15509) +g20616 = NOT(g15277) +g20617 = NOT(g15277) +g20618 = NOT(g15277) +g20622 = NOT(g15595) +g20623 = NOT(g17929) +g20624 = NOT(g18065) +g20625 = NOT(g15348) +g20626 = NOT(g15483) +g20627 = NOT(g17433) +g20629 = NOT(g17955) +g20630 = NOT(g17955) +g20631 = NOT(g15171) +g20632 = NOT(g15171) +g20633 = NOT(g15171) +g20634 = NOT(g15373) +g20635 = NOT(g18008) +g20636 = NOT(g18008) +g20637 = NOT(g15224) +g20638 = NOT(g15224) +g20639 = NOT(g15224) +g20640 = NOT(g15426) +g20641 = NOT(g15509) +g20642 = NOT(g15277) +g20643 = NOT(g15962) +g20648 = NOT(g15615) +g20649 = NOT(g18065) +g20650 = NOT(g15348) +g20651 = NOT(g15483) +I20744 = NOT(g17141) +g20652 = NOT(I20744) +I20747 = NOT(g17141) +g20653 = NOT(I20747) +I20750 = NOT(g16677) +g20654 = NOT(I20750) +I20753 = NOT(g16677) +g20655 = NOT(I20753) +g20656 = NOT(g17249) +g20657 = NOT(g17433) +g20659 = NOT(g17873) +g20660 = NOT(g17873) +g20661 = NOT(g15171) +g20662 = NOT(g15171) +g20663 = NOT(g15373) +g20664 = NOT(g15373) +g20665 = NOT(g15373) +g20666 = NOT(g15224) +g20667 = NOT(g15224) +g20668 = NOT(g15426) +g20669 = NOT(g15426) +g20670 = NOT(g15426) +g20671 = NOT(g15509) +g20672 = NOT(g15277) +g20673 = NOT(g15277) +g20674 = NOT(g15277) +g20679 = NOT(g15634) +g20680 = NOT(g15348) +g20681 = NOT(g15483) +I20781 = NOT(g17155) +g20695 = NOT(I20781) +g20696 = NOT(g17533) +g20697 = NOT(g17433) +g20698 = NOT(g17873) +g20699 = NOT(g17873) +g20700 = NOT(g17873) +g20701 = NOT(g17955) +g20702 = NOT(g17955) +g20703 = NOT(g15373) +g20704 = NOT(g15373) +I20793 = NOT(g17694) +g20705 = NOT(I20793) +g20706 = NOT(g18008) +g20707 = NOT(g18008) +g20708 = NOT(g15426) +g20709 = NOT(g15426) +g20710 = NOT(g15509) +g20711 = NOT(g15509) +g20712 = NOT(g15509) +g20713 = NOT(g15277) +g20714 = NOT(g15277) +g20715 = NOT(g15277) +g20716 = NOT(g15277) +g20732 = NOT(g15595) +g20737 = NOT(g15656) +g20738 = NOT(g15483) +I20816 = NOT(g17088) +g20763 = NOT(I20816) +I20819 = NOT(g17088) +g20764 = NOT(I20819) +g20765 = NOT(g17748) +g20766 = NOT(g17433) +g20767 = NOT(g17873) +g20768 = NOT(g17955) +g20769 = NOT(g17955) +g20770 = NOT(g17955) +g20771 = NOT(g15171) +g20772 = NOT(g15171) +I20830 = NOT(g17657) +g20773 = NOT(I20830) +g20774 = NOT(g18008) +g20775 = NOT(g18008) +g20776 = NOT(g18008) +g20777 = NOT(g15224) +g20778 = NOT(g15224) +g20779 = NOT(g15509) +g20780 = NOT(g15509) +I20840 = NOT(g17727) +g20781 = NOT(I20840) +g20782 = NOT(g15853) +I20846 = NOT(g16923) +g20785 = NOT(I20846) +g20852 = NOT(g15595) +g20853 = NOT(g15595) +g20869 = NOT(g15615) +g20874 = NOT(g15680) +I20861 = NOT(g16960) +g20899 = NOT(I20861) +I20864 = NOT(g16960) +g20900 = NOT(I20864) +I20867 = NOT(g16216) +g20901 = NOT(I20867) +I20870 = NOT(g16216) +g20902 = NOT(I20870) +g20903 = NOT(g17249) +g20904 = NOT(g17433) +g20909 = NOT(g17955) +g20910 = NOT(g15171) +g20911 = NOT(g15171) +g20912 = NOT(g15171) +g20913 = NOT(g15373) +g20914 = NOT(g15373) +I20882 = NOT(g17619) +g20915 = NOT(I20882) +g20916 = NOT(g18008) +g20917 = NOT(g15224) +g20918 = NOT(g15224) +g20919 = NOT(g15224) +g20920 = NOT(g15426) +g20921 = NOT(g15426) +I20891 = NOT(g17700) +g20922 = NOT(I20891) +g20923 = NOT(g15277) +I20895 = NOT(g16954) +g20924 = NOT(I20895) +g20978 = NOT(g15595) +g20993 = NOT(g15615) +g20994 = NOT(g15615) +g21010 = NOT(g15634) +I20910 = NOT(g17197) +g21036 = NOT(I20910) +I20913 = NOT(g16964) +g21037 = NOT(I20913) +g21048 = NOT(g17533) +g21049 = NOT(g17433) +g21050 = NOT(g17873) +g21051 = NOT(g15171) +g21052 = NOT(g15373) +g21053 = NOT(g15373) +g21054 = NOT(g15373) +g21055 = NOT(g15224) +g21056 = NOT(g15426) +g21057 = NOT(g15426) +g21058 = NOT(g15426) +g21059 = NOT(g15509) +g21060 = NOT(g15509) +I20929 = NOT(g17663) +g21061 = NOT(I20929) +g21068 = NOT(g15277) +g21069 = NOT(g15277) +I20937 = NOT(g16967) +g21070 = NOT(I20937) +g21123 = NOT(g15615) +g21138 = NOT(g15634) +g21139 = NOT(g15634) +g21155 = NOT(g15656) +g21156 = NOT(g17247) +g21160 = NOT(g17508) +I20951 = NOT(g17782) +g21175 = NOT(I20951) +I20954 = NOT(g16228) +g21176 = NOT(I20954) +I20957 = NOT(g16228) +g21177 = NOT(I20957) +g21178 = NOT(g17955) +g21179 = NOT(g15373) +g21180 = NOT(g18008) +g21181 = NOT(g15426) +g21182 = NOT(g15509) +g21183 = NOT(g15509) +g21184 = NOT(g15509) +g21185 = NOT(g15277) +g21189 = NOT(g15634) +g21204 = NOT(g15656) +g21205 = NOT(g15656) +g21221 = NOT(g15680) +g21222 = NOT(g17430) +g21225 = NOT(g17428) +g21228 = NOT(g17531) +I20982 = NOT(g16300) +g21245 = NOT(I20982) +I20985 = NOT(g16300) +g21246 = NOT(I20985) +g21247 = NOT(g15171) +g21248 = NOT(g15224) +g21249 = NOT(g15509) +g21252 = NOT(g15656) +g21267 = NOT(g15680) +g21268 = NOT(g15680) +g21269 = NOT(g15506) +I20999 = NOT(g16709) +g21270 = NOT(I20999) +I21002 = NOT(g16709) +g21271 = NOT(I21002) +I21006 = NOT(g15579) +g21273 = NOT(I21006) +g21274 = NOT(g15373) +g21275 = NOT(g15426) +I21013 = NOT(g15806) +g21278 = NOT(I21013) +g21279 = NOT(g15680) +g21280 = NOT(g16601) +g21281 = NOT(g16286) +I21019 = NOT(g17325) +g21282 = NOT(I21019) +g21286 = NOT(g15509) +I21029 = NOT(g15816) +g21290 = NOT(I21029) +g21291 = NOT(g16620) +I21033 = NOT(g17221) +g21292 = NOT(I21033) +I21036 = NOT(g17221) +g21293 = NOT(I21036) +g21295 = NOT(g17533) +I21042 = NOT(g15824) +g21297 = NOT(I21042) +g21299 = NOT(g16600) +I21047 = NOT(g17429) +g21300 = NOT(I21047) +g21304 = NOT(g17367) +g21305 = NOT(g15758) +g21306 = NOT(g15582) +g21308 = NOT(g17485) +I21058 = NOT(g17747) +g21326 = NOT(I21058) +g21329 = NOT(g16577) +I21067 = NOT(g15573) +g21335 = NOT(I21067) +g21336 = NOT(g17367) +g21337 = NOT(g15758) +I21074 = NOT(g17766) +g21340 = NOT(I21074) +g21343 = NOT(g16428) +g21346 = NOT(g17821) +g21349 = NOT(g15758) +g21352 = NOT(g16322) +g21355 = NOT(g17821) +g21358 = NOT(g16307) +g21362 = NOT(g17873) +I21100 = NOT(g16284) +g21366 = NOT(I21100) +g21369 = NOT(g16285) +g21370 = NOT(g16323) +g21379 = NOT(g17873) +g21380 = NOT(g17955) +g21381 = NOT(g18008) +g21383 = NOT(g17367) +I21115 = NOT(g15714) +g21387 = NOT(I21115) +g21393 = NOT(g17264) +g21395 = NOT(g17873) +g21396 = NOT(g17955) +g21397 = NOT(g15171) +g21398 = NOT(g18008) +g21399 = NOT(g15224) +g21400 = NOT(g17847) +g21406 = NOT(g17955) +g21407 = NOT(g15171) +g21408 = NOT(g15373) +g21409 = NOT(g18008) +g21410 = NOT(g15224) +g21411 = NOT(g15426) +g21412 = NOT(g15758) +g21413 = NOT(g15585) +g21414 = NOT(g17929) +g21418 = NOT(g17821) +g21421 = NOT(g15171) +g21422 = NOT(g15373) +g21423 = NOT(g15224) +g21424 = NOT(g15426) +g21425 = NOT(g15509) +g21426 = NOT(g15277) +g21427 = NOT(g17367) +g21428 = NOT(g15758) +g21430 = NOT(g15608) +g21431 = NOT(g18065) +g21434 = NOT(g17248) +I21162 = NOT(g17292) +g21451 = NOT(I21162) +g21454 = NOT(g15373) +g21455 = NOT(g15426) +g21456 = NOT(g15509) +g21457 = NOT(g17367) +g21458 = NOT(g15758) +g21460 = NOT(g15628) +g21461 = NOT(g15348) +g21463 = NOT(g15588) +g21466 = NOT(g15509) +g21467 = NOT(g15758) +I21181 = NOT(g17413) +g21468 = NOT(I21181) +g21510 = NOT(g15647) +g21511 = NOT(g15483) +I21189 = NOT(g17475) +g21514 = NOT(I21189) +g21556 = NOT(g15669) +g21560 = NOT(g17873) +g21561 = NOT(g15595) +I21199 = NOT(g17501) +g21562 = NOT(I21199) +g21604 = NOT(g15938) +g21607 = NOT(g17873) +g21608 = NOT(g17955) +g21609 = NOT(g18008) +g21610 = NOT(g15615) +I21210 = NOT(g17526) +g21611 = NOT(I21210) +g21653 = NOT(g17663) +g21654 = NOT(g17619) +g21656 = NOT(g17700) +g21657 = NOT(g17657) +g21659 = NOT(g17727) +g21660 = NOT(g17694) +I21222 = NOT(g18091) +g21661 = NOT(I21222) +g21662 = NOT(g16540) +I21226 = NOT(g16540) +g21665 = NOT(I21226) +g21666 = NOT(g16540) +I21230 = NOT(g16540) +g21669 = NOT(I21230) +g21670 = NOT(g16540) +I21234 = NOT(g16540) +g21673 = NOT(I21234) +g21674 = NOT(g16540) +I21238 = NOT(g16540) +g21677 = NOT(I21238) +g21678 = NOT(g16540) +I21242 = NOT(g16540) +g21681 = NOT(I21242) +g21682 = NOT(g16540) +I21246 = NOT(g16540) +g21685 = NOT(I21246) +g21686 = NOT(g16540) +I21250 = NOT(g16540) +g21689 = NOT(I21250) +g21690 = NOT(g16540) +I21254 = NOT(g16540) +g21693 = NOT(I21254) +g21694 = NOT(g16540) +I21258 = NOT(g16540) +g21697 = NOT(I21258) +g21698 = NOT(g18562) +I21285 = NOT(g18215) +g21722 = NOT(I21285) +I21288 = NOT(g18216) +g21723 = NOT(I21288) +I21291 = NOT(g18273) +g21724 = NOT(I21291) +I21294 = NOT(g18274) +g21725 = NOT(I21294) +I21297 = NOT(g18597) +g21726 = NOT(I21297) +I21300 = NOT(g18598) +g21727 = NOT(I21300) +I21477 = NOT(g18695) +g21902 = NOT(I21477) +I21480 = NOT(g18696) +g21903 = NOT(I21480) +I21483 = NOT(g18726) +g21904 = NOT(I21483) +I21486 = NOT(g18727) +g21905 = NOT(I21486) +g22136 = NOT(g20277) +g22137 = NOT(g21370) +g22138 = NOT(g21370) +I21722 = NOT(g19264) +g22139 = NOT(I21722) +g22144 = NOT(g18997) +g22146 = NOT(g18997) +g22147 = NOT(g18997) +g22148 = NOT(g19074) +g22150 = NOT(g21280) +I21734 = NOT(g19268) +g22151 = NOT(I21734) +g22153 = NOT(g18997) +g22154 = NOT(g19074) +g22155 = NOT(g19074) +g22156 = NOT(g19147) +I21744 = NOT(g19338) +g22159 = NOT(I21744) +g22166 = NOT(g18997) +g22167 = NOT(g19074) +g22168 = NOT(g19147) +g22169 = NOT(g19147) +g22170 = NOT(g19210) +g22171 = NOT(g18882) +I21757 = NOT(g21308) +g22173 = NOT(I21757) +g22176 = NOT(g18997) +g22177 = NOT(g19074) +g22178 = NOT(g19147) +g22179 = NOT(g19210) +g22180 = NOT(g19210) +g22181 = NOT(g19277) +I21766 = NOT(g19620) +g22182 = NOT(I21766) +I21769 = NOT(g19402) +g22189 = NOT(I21769) +g22192 = NOT(g19801) +I21776 = NOT(g21308) +g22194 = NOT(I21776) +g22197 = NOT(g19074) +g22198 = NOT(g19147) +g22199 = NOT(g19210) +g22200 = NOT(g19277) +g22201 = NOT(g19277) +I21784 = NOT(g19638) +g22202 = NOT(I21784) +I21787 = NOT(g19422) +g22207 = NOT(I21787) +I21792 = NOT(g21308) +g22210 = NOT(I21792) +g22213 = NOT(g19147) +g22214 = NOT(g19210) +g22215 = NOT(g19277) +I21802 = NOT(g21308) +g22220 = NOT(I21802) +g22223 = NOT(g19210) +g22224 = NOT(g19277) +g22227 = NOT(g19801) +I21810 = NOT(g20596) +g22228 = NOT(I21810) +I21815 = NOT(g21308) +g22300 = NOT(I21815) +g22303 = NOT(g19277) +g22305 = NOT(g19801) +g22311 = NOT(g18935) +g22317 = NOT(g19801) +I21831 = NOT(g19127) +g22319 = NOT(I21831) +g22330 = NOT(g19801) +I21838 = NOT(g19263) +g22332 = NOT(I21838) +g22338 = NOT(g19801) +g22339 = NOT(g19801) +g22341 = NOT(g19801) +g22358 = NOT(g19801) +g22359 = NOT(g19495) +I21849 = NOT(g19620) +g22360 = NOT(I21849) +g22406 = NOT(g19506) +g22407 = NOT(g19455) +g22408 = NOT(g19483) +I21860 = NOT(g19638) +g22409 = NOT(I21860) +g22449 = NOT(g19597) +g22455 = NOT(g19801) +g22456 = NOT(g19801) +g22492 = NOT(g19614) +g22493 = NOT(g19801) +g22494 = NOT(g19801) +g22495 = NOT(g19801) +g22496 = NOT(g19510) +g22497 = NOT(g19513) +g22519 = NOT(g19801) +g22520 = NOT(g19801) +g22526 = NOT(g19801) +g22527 = NOT(g19546) +g22528 = NOT(g19801) +g22529 = NOT(g19549) +I21911 = NOT(g21278) +g22541 = NOT(I21911) +g22542 = NOT(g19801) +g22543 = NOT(g19801) +g22544 = NOT(g19589) +I21918 = NOT(g21290) +g22546 = NOT(I21918) +I21922 = NOT(g21335) +g22550 = NOT(I21922) +I21930 = NOT(g21297) +g22592 = NOT(I21930) +g22593 = NOT(g19801) +I21934 = NOT(g21273) +g22594 = NOT(I21934) +I21941 = NOT(g18918) +g22626 = NOT(I21941) +g22635 = NOT(g19801) +g22646 = NOT(g19389) +I21959 = NOT(g20242) +g22647 = NOT(I21959) +g22649 = NOT(g19063) +I21969 = NOT(g21370) +g22658 = NOT(I21969) +g22660 = NOT(g19140) +g22667 = NOT(g21156) +g22682 = NOT(g19379) +I22000 = NOT(g20277) +g22683 = NOT(I22000) +I22009 = NOT(g21269) +g22698 = NOT(I22009) +g22714 = NOT(g20436) +g22716 = NOT(g19795) +g22718 = NOT(g20887) +I22024 = NOT(g19350) +g22719 = NOT(I22024) +I22028 = NOT(g20204) +g22721 = NOT(I22028) +I22031 = NOT(g21387) +g22722 = NOT(I22031) +g22756 = NOT(g20436) +g22758 = NOT(g20330) +g22759 = NOT(g19857) +g22761 = NOT(g21024) +I22046 = NOT(g19330) +g22763 = NOT(I22046) +g22830 = NOT(g20283) +g22840 = NOT(g20330) +g22841 = NOT(g20391) +g22842 = NOT(g19875) +g22844 = NOT(g21163) +g22845 = NOT(g20682) +g22847 = NOT(g20283) +g22854 = NOT(g20330) +g22855 = NOT(g20391) +g22856 = NOT(g20453) +g22857 = NOT(g20739) +g22858 = NOT(g20751) +g22860 = NOT(g20000) +g22865 = NOT(g20330) +g22866 = NOT(g20330) +g22867 = NOT(g20391) +g22868 = NOT(g20453) +g22869 = NOT(g20875) +g22870 = NOT(g20887) +I22096 = NOT(g19890) +g22881 = NOT(I22096) +g22882 = NOT(g20391) +g22883 = NOT(g20391) +g22884 = NOT(g20453) +g22896 = NOT(g21012) +g22897 = NOT(g21024) +g22898 = NOT(g20283) +g22903 = NOT(g20330) +I22111 = NOT(g19919) +g22904 = NOT(I22111) +I22114 = NOT(g19935) +g22905 = NOT(I22114) +g22906 = NOT(g20453) +g22907 = NOT(g20453) +g22919 = NOT(g21163) +g22922 = NOT(g20330) +I22124 = NOT(g21300) +g22923 = NOT(I22124) +g22926 = NOT(g20391) +I22128 = NOT(g19968) +g22927 = NOT(I22128) +I22131 = NOT(g19984) +g22928 = NOT(I22131) +g22935 = NOT(g20283) +g22936 = NOT(g20283) +I22143 = NOT(g20189) +g22957 = NOT(I22143) +g22973 = NOT(g20330) +g22974 = NOT(g20330) +g22975 = NOT(g20391) +I22149 = NOT(g21036) +g22976 = NOT(I22149) +g22979 = NOT(g20453) +I22153 = NOT(g20014) +g22980 = NOT(I22153) +g22981 = NOT(g20283) +g22985 = NOT(g20330) +g22986 = NOT(g20330) +g22987 = NOT(g20391) +g22988 = NOT(g20391) +g22989 = NOT(g20453) +g22994 = NOT(g20436) +g22995 = NOT(g20330) +g22996 = NOT(g20330) +g22997 = NOT(g20391) +g22998 = NOT(g20391) +g22999 = NOT(g20453) +g23000 = NOT(g20453) +g23001 = NOT(g19801) +I22177 = NOT(g21366) +g23002 = NOT(I22177) +I22180 = NOT(g21366) +g23003 = NOT(I22180) +g23004 = NOT(g20283) +g23005 = NOT(g20283) +g23011 = NOT(g20330) +g23012 = NOT(g20330) +g23013 = NOT(g20330) +g23014 = NOT(g20391) +g23015 = NOT(g20391) +g23016 = NOT(g20453) +g23017 = NOT(g20453) +g23018 = NOT(g19801) +g23019 = NOT(g19866) +g23020 = NOT(g19869) +g23021 = NOT(g20283) +g23022 = NOT(g20283) +g23026 = NOT(g20391) +g23027 = NOT(g20391) +g23028 = NOT(g20391) +g23029 = NOT(g20453) +g23030 = NOT(g20453) +g23031 = NOT(g19801) +I22211 = NOT(g21463) +g23032 = NOT(I22211) +g23041 = NOT(g19882) +g23046 = NOT(g20283) +g23055 = NOT(g20887) +g23057 = NOT(g20453) +g23058 = NOT(g20453) +g23059 = NOT(g20453) +g23060 = NOT(g19908) +g23061 = NOT(g20283) +g23066 = NOT(g20330) +g23082 = NOT(g21024) +g23084 = NOT(g19954) +g23085 = NOT(g19957) +g23086 = NOT(g20283) +I22240 = NOT(g20086) +g23088 = NOT(I22240) +g23111 = NOT(g20391) +g23127 = NOT(g21163) +g23128 = NOT(g20283) +g23138 = NOT(g20453) +g23152 = NOT(g20283) +I22264 = NOT(g20100) +g23154 = NOT(I22264) +g23170 = NOT(g20046) +I22275 = NOT(g20127) +g23172 = NOT(I22275) +g23182 = NOT(g21389) +g23189 = NOT(g20060) +I22286 = NOT(g19446) +g23190 = NOT(I22286) +I22289 = NOT(g19446) +g23191 = NOT(I22289) +g23192 = NOT(g20248) +g23196 = NOT(g20785) +I22302 = NOT(g19353) +g23202 = NOT(I22302) +g23203 = NOT(g20073) +g23211 = NOT(g21308) +g23214 = NOT(g20785) +g23215 = NOT(g20785) +g23216 = NOT(g20924) +I22316 = NOT(g19361) +g23219 = NOT(I22316) +g23221 = NOT(g20785) +g23222 = NOT(g20785) +g23223 = NOT(g21308) +g23226 = NOT(g20924) +g23227 = NOT(g20924) +g23228 = NOT(g21070) +I22327 = NOT(g19367) +g23230 = NOT(I22327) +g23231 = NOT(g20050) +I22331 = NOT(g19417) +g23232 = NOT(I22331) +g23233 = NOT(g21037) +g23234 = NOT(g20375) +g23235 = NOT(g20785) +g23236 = NOT(g20785) +g23237 = NOT(g20924) +g23238 = NOT(g20924) +g23239 = NOT(g21308) +g23242 = NOT(g21070) +g23243 = NOT(g21070) +I22343 = NOT(g19371) +g23244 = NOT(I22343) +g23245 = NOT(g20785) +g23246 = NOT(g20785) +g23247 = NOT(g20924) +g23248 = NOT(g20924) +g23249 = NOT(g21070) +g23250 = NOT(g21070) +I22353 = NOT(g19375) +g23252 = NOT(I22353) +g23253 = NOT(g21037) +g23256 = NOT(g20785) +g23257 = NOT(g20924) +g23258 = NOT(g20924) +g23259 = NOT(g21070) +g23260 = NOT(g21070) +I22366 = NOT(g19757) +g23263 = NOT(I22366) +g23264 = NOT(g21037) +g23267 = NOT(g20097) +g23270 = NOT(g20785) +g23271 = NOT(g20785) +g23272 = NOT(g20924) +g23273 = NOT(g21070) +g23274 = NOT(g21070) +I22380 = NOT(g21156) +g23277 = NOT(I22380) +g23278 = NOT(g20283) +g23279 = NOT(g21037) +g23282 = NOT(g20330) +g23283 = NOT(g20785) +g23284 = NOT(g20785) +g23285 = NOT(g20887) +g23289 = NOT(g20924) +g23290 = NOT(g20924) +g23291 = NOT(g21070) +I22400 = NOT(g19620) +g23299 = NOT(I22400) +g23300 = NOT(g20283) +g23301 = NOT(g21037) +g23302 = NOT(g20330) +g23303 = NOT(g20785) +g23304 = NOT(g20785) +g23305 = NOT(g20391) +g23306 = NOT(g20924) +g23307 = NOT(g20924) +g23308 = NOT(g21024) +g23312 = NOT(g21070) +g23313 = NOT(g21070) +I22419 = NOT(g19638) +g23320 = NOT(I22419) +I22422 = NOT(g19330) +g23321 = NOT(I22422) +I22425 = NOT(g19379) +g23322 = NOT(I22425) +g23323 = NOT(g20283) +g23331 = NOT(g20905) +g23332 = NOT(g20785) +g23333 = NOT(g20785) +g23334 = NOT(g20785) +g23335 = NOT(g20391) +g23336 = NOT(g20924) +g23337 = NOT(g20924) +g23338 = NOT(g20453) +g23339 = NOT(g21070) +g23340 = NOT(g21070) +g23341 = NOT(g21163) +I22444 = NOT(g19626) +g23347 = NOT(I22444) +g23350 = NOT(g20785) +g23351 = NOT(g20924) +g23352 = NOT(g20924) +g23353 = NOT(g20924) +g23354 = NOT(g20453) +g23355 = NOT(g21070) +g23356 = NOT(g21070) +I22458 = NOT(g18954) +g23359 = NOT(I22458) +I22461 = NOT(g21225) +g23360 = NOT(I22461) +I22464 = NOT(g21222) +g23361 = NOT(I22464) +I22467 = NOT(g19662) +g23362 = NOT(I22467) +I22470 = NOT(g21326) +g23363 = NOT(I22470) +g23375 = NOT(g20924) +g23376 = NOT(g21070) +g23377 = NOT(g21070) +g23378 = NOT(g21070) +g23380 = NOT(g20619) +g23382 = NOT(g20682) +I22485 = NOT(g21308) +g23384 = NOT(I22485) +I22488 = NOT(g18984) +g23385 = NOT(I22488) +g23388 = NOT(g21070) +g23390 = NOT(g21468) +g23391 = NOT(g20645) +g23393 = NOT(g20739) +I22499 = NOT(g21160) +g23394 = NOT(I22499) +I22502 = NOT(g19376) +g23395 = NOT(I22502) +g23398 = NOT(g21468) +g23399 = NOT(g21514) +g23400 = NOT(g20676) +g23402 = NOT(g20875) +I22512 = NOT(g19389) +g23403 = NOT(I22512) +g23406 = NOT(g20330) +g23408 = NOT(g21468) +g23409 = NOT(g21514) +g23410 = NOT(g21562) +g23411 = NOT(g20734) +g23413 = NOT(g21012) +I22525 = NOT(g19345) +g23414 = NOT(I22525) +g23417 = NOT(g20391) +g23418 = NOT(g21468) +g23419 = NOT(g21468) +g23420 = NOT(g21514) +g23421 = NOT(g21562) +g23422 = NOT(g21611) +g23423 = NOT(g20871) +g23425 = NOT(g20751) +I22539 = NOT(g19606) +g23426 = NOT(I22539) +I22542 = NOT(g19773) +g23427 = NOT(I22542) +g23429 = NOT(g20453) +I22547 = NOT(g20720) +g23430 = NOT(I22547) +g23431 = NOT(g21514) +g23432 = NOT(g21514) +g23433 = NOT(g21562) +g23434 = NOT(g21611) +g23435 = NOT(g18833) +I22557 = NOT(g20695) +g23440 = NOT(I22557) +g23443 = NOT(g21468) +I22561 = NOT(g20841) +g23444 = NOT(I22561) +I22564 = NOT(g20857) +g23445 = NOT(I22564) +g23446 = NOT(g21562) +g23447 = NOT(g21562) +g23448 = NOT(g21611) +g23449 = NOT(g18833) +I22571 = NOT(g20097) +g23450 = NOT(I22571) +g23452 = NOT(g21468) +I22576 = NOT(g21282) +g23453 = NOT(I22576) +g23456 = NOT(g21514) +I22580 = NOT(g20982) +g23457 = NOT(I22580) +I22583 = NOT(g20998) +g23458 = NOT(I22583) +g23459 = NOT(g21611) +g23460 = NOT(g21611) +g23461 = NOT(g18833) +I22589 = NOT(g21340) +g23462 = NOT(I22589) +g23472 = NOT(g21062) +g23473 = NOT(g20785) +g23476 = NOT(g21468) +g23477 = NOT(g21468) +g23478 = NOT(g21514) +g23479 = NOT(g21562) +I22601 = NOT(g21127) +g23480 = NOT(I22601) +I22604 = NOT(g21143) +g23481 = NOT(I22604) +g23482 = NOT(g18833) +g23483 = NOT(g18833) +g23485 = NOT(g20785) +g23486 = NOT(g20785) +g23487 = NOT(g20924) +g23488 = NOT(g21468) +g23489 = NOT(g21468) +g23490 = NOT(g21514) +g23491 = NOT(g21514) +g23492 = NOT(g21562) +g23493 = NOT(g21611) +I22619 = NOT(g21193) +g23494 = NOT(I22619) +I22622 = NOT(g21209) +g23495 = NOT(I22622) +g23496 = NOT(g20248) +g23499 = NOT(g20785) +g23500 = NOT(g20924) +g23501 = NOT(g20924) +g23502 = NOT(g21070) +g23503 = NOT(g21468) +g23504 = NOT(g21468) +g23505 = NOT(g21514) +g23506 = NOT(g21514) +g23507 = NOT(g21562) +g23508 = NOT(g21562) +g23509 = NOT(g21611) +g23510 = NOT(g18833) +I22640 = NOT(g21256) +g23511 = NOT(I22640) +g23512 = NOT(g20248) +g23515 = NOT(g20785) +g23516 = NOT(g20924) +g23517 = NOT(g21070) +g23518 = NOT(g21070) +g23519 = NOT(g21468) +g23520 = NOT(g21468) +g23521 = NOT(g21468) +g23522 = NOT(g21514) +g23523 = NOT(g21514) +g23524 = NOT(g21562) +g23525 = NOT(g21562) +g23526 = NOT(g21611) +g23527 = NOT(g21611) +g23528 = NOT(g18833) +g23529 = NOT(g20558) +g23530 = NOT(g20248) +I22665 = NOT(g21308) +g23534 = NOT(I22665) +g23537 = NOT(g20785) +g23538 = NOT(g20924) +g23539 = NOT(g21070) +g23541 = NOT(g21514) +g23542 = NOT(g21514) +g23543 = NOT(g21514) +g23544 = NOT(g21562) +g23545 = NOT(g21562) +g23546 = NOT(g21611) +g23547 = NOT(g21611) +g23548 = NOT(g18833) +g23549 = NOT(g18833) +g23550 = NOT(g20248) +I22692 = NOT(g21308) +g23555 = NOT(I22692) +g23558 = NOT(g20924) +g23559 = NOT(g21070) +g23563 = NOT(g20682) +g23565 = NOT(g21562) +g23566 = NOT(g21562) +g23567 = NOT(g21562) +g23568 = NOT(g21611) +g23569 = NOT(g21611) +g23570 = NOT(g18833) +g23571 = NOT(g18833) +g23573 = NOT(g20248) +I22725 = NOT(g21250) +g23578 = NOT(I22725) +I22729 = NOT(g21308) +g23582 = NOT(I22729) +g23585 = NOT(g21070) +g23589 = NOT(g21468) +g23605 = NOT(g20739) +g23607 = NOT(g21611) +g23608 = NOT(g21611) +g23609 = NOT(g21611) +g23610 = NOT(g18833) +g23611 = NOT(g18833) +I22745 = NOT(g19458) +g23612 = NOT(I22745) +I22748 = NOT(g19458) +g23613 = NOT(I22748) +g23614 = NOT(g20248) +I22769 = NOT(g21277) +g23620 = NOT(I22769) +g23629 = NOT(g21514) +g23645 = NOT(g20875) +g23647 = NOT(g18833) +g23648 = NOT(g18833) +g23649 = NOT(g18833) +g23650 = NOT(g20653) +g23651 = NOT(g20655) +I22785 = NOT(g18940) +g23652 = NOT(I22785) +I22788 = NOT(g18940) +g23653 = NOT(I22788) +g23654 = NOT(g20248) +g23665 = NOT(g21562) +g23681 = NOT(g21012) +I22816 = NOT(g19862) +g23683 = NOT(I22816) +I22819 = NOT(g19862) +g23684 = NOT(I22819) +g23698 = NOT(g21611) +g23714 = NOT(g20751) +g23715 = NOT(g20764) +g23732 = NOT(g18833) +g23745 = NOT(g20900) +g23746 = NOT(g20902) +g23749 = NOT(g18997) +I22886 = NOT(g18926) +g23759 = NOT(I22886) +I22889 = NOT(g18926) +g23760 = NOT(I22889) +g23764 = NOT(g21308) +g23767 = NOT(g18997) +g23768 = NOT(g18997) +g23769 = NOT(g19074) +g23776 = NOT(g21177) +I22918 = NOT(g21451) +g23777 = NOT(I22918) +g23787 = NOT(g18997) +g23788 = NOT(g18997) +g23789 = NOT(g21308) +g23792 = NOT(g19074) +g23793 = NOT(g19074) +g23794 = NOT(g19147) +g23800 = NOT(g21246) +g23812 = NOT(g18997) +g23813 = NOT(g18997) +g23814 = NOT(g19074) +g23815 = NOT(g19074) +g23816 = NOT(g21308) +g23819 = NOT(g19147) +g23820 = NOT(g19147) +g23821 = NOT(g19210) +I22989 = NOT(g21175) +g23823 = NOT(I22989) +g23824 = NOT(g21271) +g23838 = NOT(g18997) +g23839 = NOT(g18997) +g23840 = NOT(g19074) +g23841 = NOT(g19074) +g23842 = NOT(g19147) +g23843 = NOT(g19147) +g23844 = NOT(g21308) +g23847 = NOT(g19210) +g23848 = NOT(g19210) +g23849 = NOT(g19277) +g23858 = NOT(g18997) +g23859 = NOT(g19074) +g23860 = NOT(g19074) +g23861 = NOT(g19147) +g23862 = NOT(g19147) +g23863 = NOT(g19210) +g23864 = NOT(g19210) +g23865 = NOT(g21308) +g23868 = NOT(g19277) +g23869 = NOT(g19277) +g23870 = NOT(g21293) +g23874 = NOT(g18997) +g23875 = NOT(g18997) +g23876 = NOT(g19074) +g23877 = NOT(g19147) +g23878 = NOT(g19147) +g23879 = NOT(g19210) +g23880 = NOT(g19210) +g23881 = NOT(g19277) +g23882 = NOT(g19277) +g23886 = NOT(g21468) +g23887 = NOT(g18997) +g23888 = NOT(g18997) +g23889 = NOT(g20682) +g23893 = NOT(g19074) +g23894 = NOT(g19074) +g23895 = NOT(g19147) +g23896 = NOT(g19210) +g23897 = NOT(g19210) +g23898 = NOT(g19277) +g23899 = NOT(g19277) +g23902 = NOT(g21468) +g23903 = NOT(g18997) +g23904 = NOT(g18997) +g23905 = NOT(g21514) +g23906 = NOT(g19074) +g23907 = NOT(g19074) +g23908 = NOT(g20739) +g23912 = NOT(g19147) +g23913 = NOT(g19147) +g23914 = NOT(g19210) +g23915 = NOT(g19277) +g23916 = NOT(g19277) +g23922 = NOT(g18997) +g23923 = NOT(g18997) +g23924 = NOT(g18997) +g23925 = NOT(g21514) +g23926 = NOT(g19074) +g23927 = NOT(g19074) +g23928 = NOT(g21562) +g23929 = NOT(g19147) +g23930 = NOT(g19147) +g23931 = NOT(g20875) +g23935 = NOT(g19210) +g23936 = NOT(g19210) +g23937 = NOT(g19277) +g23938 = NOT(g18997) +g23939 = NOT(g19074) +g23940 = NOT(g19074) +g23941 = NOT(g19074) +g23942 = NOT(g21562) +g23943 = NOT(g19147) +g23944 = NOT(g19147) +g23945 = NOT(g21611) +g23946 = NOT(g19210) +g23947 = NOT(g19210) +g23948 = NOT(g21012) +g23952 = NOT(g19277) +g23953 = NOT(g19277) +I23099 = NOT(g20682) +g23954 = NOT(I23099) +g23961 = NOT(g19074) +g23962 = NOT(g19147) +g23963 = NOT(g19147) +g23964 = NOT(g19147) +g23965 = NOT(g21611) +g23966 = NOT(g19210) +g23967 = NOT(g19210) +g23968 = NOT(g18833) +g23969 = NOT(g19277) +g23970 = NOT(g19277) +g23971 = NOT(g20751) +g23982 = NOT(g19147) +g23983 = NOT(g19210) +g23984 = NOT(g19210) +g23985 = NOT(g19210) +g23986 = NOT(g18833) +g23987 = NOT(g19277) +g23988 = NOT(g19277) +g23992 = NOT(g19210) +g23993 = NOT(g19277) +g23994 = NOT(g19277) +g23995 = NOT(g19277) +g23999 = NOT(g21468) +g24000 = NOT(g19277) +g24003 = NOT(g21514) +I23149 = NOT(g19061) +g24005 = NOT(I23149) +g24010 = NOT(g21562) +g24013 = NOT(g21611) +g24017 = NOT(g18833) +g24019 = NOT(g19968) +g24020 = NOT(g20014) +g24021 = NOT(g20841) +g24022 = NOT(g20982) +g24023 = NOT(g21127) +g24024 = NOT(g21193) +g24025 = NOT(g21256) +g24026 = NOT(g19919) +g24027 = NOT(g20014) +g24028 = NOT(g20841) +g24029 = NOT(g20982) +g24030 = NOT(g21127) +g24031 = NOT(g21193) +g24032 = NOT(g21256) +g24033 = NOT(g19919) +g24034 = NOT(g19968) +g24035 = NOT(g20841) +g24036 = NOT(g20982) +g24037 = NOT(g21127) +g24038 = NOT(g21193) +g24039 = NOT(g21256) +g24040 = NOT(g19919) +g24041 = NOT(g19968) +g24042 = NOT(g20014) +g24043 = NOT(g20982) +g24044 = NOT(g21127) +g24045 = NOT(g21193) +g24046 = NOT(g21256) +g24047 = NOT(g19919) +g24048 = NOT(g19968) +g24049 = NOT(g20014) +g24050 = NOT(g20841) +g24051 = NOT(g21127) +g24052 = NOT(g21193) +g24053 = NOT(g21256) +g24054 = NOT(g19919) +g24055 = NOT(g19968) +g24056 = NOT(g20014) +g24057 = NOT(g20841) +g24058 = NOT(g20982) +g24059 = NOT(g21193) +g24060 = NOT(g21256) +g24061 = NOT(g19919) +g24062 = NOT(g19968) +g24063 = NOT(g20014) +g24064 = NOT(g20841) +g24065 = NOT(g20982) +g24066 = NOT(g21127) +g24067 = NOT(g21256) +g24068 = NOT(g19919) +g24069 = NOT(g19968) +g24070 = NOT(g20014) +g24071 = NOT(g20841) +g24072 = NOT(g20982) +g24073 = NOT(g21127) +g24074 = NOT(g21193) +g24075 = NOT(g19935) +g24076 = NOT(g19984) +g24077 = NOT(g20720) +g24078 = NOT(g20857) +g24079 = NOT(g20998) +g24080 = NOT(g21143) +g24081 = NOT(g21209) +g24082 = NOT(g19890) +g24083 = NOT(g19984) +g24084 = NOT(g20720) +g24085 = NOT(g20857) +g24086 = NOT(g20998) +g24087 = NOT(g21143) +g24088 = NOT(g21209) +g24089 = NOT(g19890) +g24090 = NOT(g19935) +g24091 = NOT(g20720) +g24092 = NOT(g20857) +g24093 = NOT(g20998) +g24094 = NOT(g21143) +g24095 = NOT(g21209) +g24096 = NOT(g19890) +g24097 = NOT(g19935) +g24098 = NOT(g19984) +g24099 = NOT(g20720) +g24100 = NOT(g20857) +g24101 = NOT(g20998) +g24102 = NOT(g21143) +g24103 = NOT(g21209) +g24104 = NOT(g19890) +g24105 = NOT(g19935) +g24106 = NOT(g19984) +g24107 = NOT(g20857) +g24108 = NOT(g20998) +g24109 = NOT(g21143) +g24110 = NOT(g21209) +g24111 = NOT(g19890) +g24112 = NOT(g19935) +g24113 = NOT(g19984) +g24114 = NOT(g20720) +g24115 = NOT(g20998) +g24116 = NOT(g21143) +g24117 = NOT(g21209) +g24118 = NOT(g19890) +g24119 = NOT(g19935) +g24120 = NOT(g19984) +g24121 = NOT(g20720) +g24122 = NOT(g20857) +g24123 = NOT(g21143) +g24124 = NOT(g21209) +g24125 = NOT(g19890) +g24126 = NOT(g19935) +g24127 = NOT(g19984) +g24128 = NOT(g20720) +g24129 = NOT(g20857) +g24130 = NOT(g20998) +g24131 = NOT(g21209) +g24132 = NOT(g19890) +g24133 = NOT(g19935) +g24134 = NOT(g19984) +g24135 = NOT(g20720) +g24136 = NOT(g20857) +g24137 = NOT(g20998) +g24138 = NOT(g21143) +g24146 = NOT(g19422) +g24147 = NOT(g19402) +g24149 = NOT(g19338) +g24150 = NOT(g19268) +I23300 = NOT(g21665) +g24152 = NOT(I23300) +I23303 = NOT(g21669) +g24153 = NOT(I23303) +I23306 = NOT(g21673) +g24154 = NOT(I23306) +I23309 = NOT(g21677) +g24155 = NOT(I23309) +I23312 = NOT(g21681) +g24156 = NOT(I23312) +I23315 = NOT(g21685) +g24157 = NOT(I23315) +I23318 = NOT(g21689) +g24158 = NOT(I23318) +I23321 = NOT(g21693) +g24159 = NOT(I23321) +I23324 = NOT(g21697) +g24160 = NOT(I23324) +I23327 = NOT(g22647) +g24161 = NOT(I23327) +I23330 = NOT(g22658) +g24162 = NOT(I23330) +I23333 = NOT(g22683) +g24163 = NOT(I23333) +I23336 = NOT(g22721) +g24164 = NOT(I23336) +I23339 = NOT(g23232) +g24165 = NOT(I23339) +I23342 = NOT(g23299) +g24166 = NOT(I23342) +I23345 = NOT(g23320) +g24167 = NOT(I23345) +I23348 = NOT(g23384) +g24168 = NOT(I23348) +I23351 = NOT(g23263) +g24169 = NOT(I23351) +I23354 = NOT(g23277) +g24170 = NOT(I23354) +I23357 = NOT(g23359) +g24171 = NOT(I23357) +I23360 = NOT(g23360) +g24172 = NOT(I23360) +I23363 = NOT(g23385) +g24173 = NOT(I23363) +I23366 = NOT(g23321) +g24174 = NOT(I23366) +I23369 = NOT(g23347) +g24175 = NOT(I23369) +I23372 = NOT(g23361) +g24176 = NOT(I23372) +I23375 = NOT(g23403) +g24177 = NOT(I23375) +I23378 = NOT(g23426) +g24178 = NOT(I23378) +I23381 = NOT(g23322) +g24179 = NOT(I23381) +I23384 = NOT(g23362) +g24180 = NOT(I23384) +I23387 = NOT(g23394) +g24181 = NOT(I23387) +I23390 = NOT(g23395) +g24182 = NOT(I23390) +I23393 = NOT(g23414) +g24183 = NOT(I23393) +I23396 = NOT(g23427) +g24184 = NOT(I23396) +I23399 = NOT(g23450) +g24185 = NOT(I23399) +g24356 = NOT(g22594) +g24357 = NOT(g22325) +g24358 = NOT(g22550) +g24359 = NOT(g22550) +g24360 = NOT(g22228) +g24361 = NOT(g22885) +g24364 = NOT(g22722) +g24365 = NOT(g22594) +g24366 = NOT(g22594) +g24367 = NOT(g22550) +g24368 = NOT(g22228) +g24372 = NOT(g22885) +g24373 = NOT(g22908) +g24375 = NOT(g22722) +g24376 = NOT(g22722) +g24377 = NOT(g22594) +g24379 = NOT(g22550) +g24384 = NOT(g22885) +g24385 = NOT(g22908) +g24386 = NOT(g22594) +g24388 = NOT(g22885) +g24389 = NOT(g22908) +g24394 = NOT(g22228) +g24396 = NOT(g22885) +g24397 = NOT(g22908) +g24404 = NOT(g22908) +g24405 = NOT(g22722) +g24407 = NOT(g22594) +g24417 = NOT(g22171) +g24418 = NOT(g22722) +g24419 = NOT(g22722) +g24424 = NOT(g22722) +g24425 = NOT(g22722) +g24426 = NOT(g22722) +g24428 = NOT(g22722) +g24429 = NOT(g22722) +g24431 = NOT(g22722) +g24437 = NOT(g22654) +g24438 = NOT(g22722) +g24452 = NOT(g22722) +g24463 = NOT(g23578) +I23671 = NOT(g23202) +g24466 = NOT(I23671) +g24474 = NOT(g23620) +I23680 = NOT(g23219) +g24477 = NOT(I23680) +I23684 = NOT(g23230) +g24481 = NOT(I23684) +I23688 = NOT(g23244) +g24483 = NOT(I23688) +I23694 = NOT(g23252) +g24489 = NOT(I23694) +g24490 = NOT(g22594) +g24505 = NOT(g22689) +I23711 = NOT(g23192) +g24506 = NOT(I23711) +g24509 = NOT(g22689) +g24515 = NOT(g22689) +g24516 = NOT(g22670) +g24522 = NOT(g22689) +g24524 = NOT(g22876) +g24525 = NOT(g22670) +g24526 = NOT(g22942) +g24527 = NOT(g22670) +g24533 = NOT(g22876) +g24534 = NOT(g22670) +g24535 = NOT(g22942) +g24540 = NOT(g22942) +g24548 = NOT(g22942) +g24560 = NOT(g22942) +g24568 = NOT(g22942) +g24571 = NOT(g22942) +g24579 = NOT(g23067) +g24585 = NOT(g23063) +g24586 = NOT(g23067) +g24587 = NOT(g23112) +g24603 = NOT(g23108) +g24604 = NOT(g23112) +g24605 = NOT(g23139) +g24623 = NOT(g23076) +g24625 = NOT(g23135) +g24626 = NOT(g23139) +g24636 = NOT(g23121) +g24648 = NOT(g23148) +g24655 = NOT(g23067) +g24665 = NOT(g23067) +g24667 = NOT(g23112) +g24683 = NOT(g23112) +g24685 = NOT(g23139) +g24699 = NOT(g23047) +g24711 = NOT(g23139) +g24718 = NOT(g22182) +g24732 = NOT(g23042) +g24744 = NOT(g22202) +g24756 = NOT(g22763) +g24759 = NOT(g23003) +g24770 = NOT(g22763) +g24778 = NOT(g23286) +g24789 = NOT(g23309) +g24791 = NOT(g23850) +g24795 = NOT(g23342) +g24818 = NOT(g23191) +I23998 = NOT(g22182) +g24819 = NOT(I23998) +g24825 = NOT(g23204) +I24008 = NOT(g22182) +g24836 = NOT(I24008) +g24839 = NOT(g23436) +I24022 = NOT(g22182) +g24850 = NOT(I24022) +I24038 = NOT(g22202) +g24866 = NOT(I24038) +I24041 = NOT(g22182) +g24869 = NOT(I24041) +g24891 = NOT(g23231) +I24060 = NOT(g22202) +g24893 = NOT(I24060) +I24078 = NOT(g22360) +g24911 = NOT(I24078) +I24089 = NOT(g22409) +g24920 = NOT(I24089) +g24960 = NOT(g23716) +g24963 = NOT(g22342) +I24128 = NOT(g23009) +g24964 = NOT(I24128) +g24966 = NOT(g22763) +g24971 = NOT(g23590) +g24978 = NOT(g22342) +g24979 = NOT(g22369) +g24980 = NOT(g22384) +g24981 = NOT(g22763) +g24982 = NOT(g22763) +g24985 = NOT(g23586) +g24986 = NOT(g23590) +g24987 = NOT(g23630) +g24991 = NOT(g22369) +g24992 = NOT(g22417) +g24993 = NOT(g22384) +g24994 = NOT(g22432) +g24995 = NOT(g22763) +g24996 = NOT(g22763) +g24999 = NOT(g23626) +g25000 = NOT(g23630) +g25001 = NOT(g23666) +g25006 = NOT(g22417) +g25007 = NOT(g22457) +g25008 = NOT(g22432) +g25009 = NOT(g22472) +g25011 = NOT(g22763) +g25013 = NOT(g23599) +g25015 = NOT(g23662) +g25016 = NOT(g23666) +g25017 = NOT(g23699) +g25023 = NOT(g22457) +g25024 = NOT(g22472) +g25025 = NOT(g22498) +I24191 = NOT(g22360) +g25027 = NOT(I24191) +g25032 = NOT(g23639) +g25034 = NOT(g23695) +g25035 = NOT(g23699) +g25036 = NOT(g23733) +g25039 = NOT(g22498) +g25044 = NOT(g23675) +g25046 = NOT(g23729) +g25047 = NOT(g23733) +I24215 = NOT(g22360) +g25051 = NOT(I24215) +g25055 = NOT(g23590) +g25060 = NOT(g23708) +I24228 = NOT(g22409) +g25064 = NOT(I24228) +g25070 = NOT(g23590) +g25072 = NOT(g23630) +I24237 = NOT(g23823) +g25073 = NOT(I24237) +g25080 = NOT(g23742) +g25081 = NOT(g22342) +g25082 = NOT(g22342) +g25083 = NOT(g23782) +g25090 = NOT(g23630) +g25092 = NOT(g23666) +g25097 = NOT(g22342) +g25098 = NOT(g22369) +g25099 = NOT(g22369) +g25100 = NOT(g22384) +g25101 = NOT(g22384) +g25109 = NOT(g23666) +g25111 = NOT(g23699) +I24278 = NOT(g23440) +g25114 = NOT(I24278) +I24281 = NOT(g23440) +g25115 = NOT(I24281) +g25116 = NOT(g22369) +g25117 = NOT(g22417) +g25118 = NOT(g22417) +g25119 = NOT(g22384) +g25120 = NOT(g22432) +g25121 = NOT(g22432) +g25131 = NOT(g23699) +g25133 = NOT(g23733) +g25134 = NOT(g22417) +g25135 = NOT(g22457) +g25136 = NOT(g22457) +g25137 = NOT(g22432) +g25138 = NOT(g22472) +g25139 = NOT(g22472) +g25140 = NOT(g22228) +g25153 = NOT(g23733) +g25154 = NOT(g22457) +g25155 = NOT(g22472) +g25156 = NOT(g22498) +g25157 = NOT(g22498) +g25158 = NOT(g22228) +I24331 = NOT(g22976) +g25167 = NOT(I24331) +I24334 = NOT(g22976) +g25168 = NOT(I24334) +g25169 = NOT(g22763) +g25170 = NOT(g22498) +g25171 = NOT(g22228) +g25174 = NOT(g23890) +g25180 = NOT(g23529) +g25182 = NOT(g22763) +g25183 = NOT(g22763) +g25184 = NOT(g22763) +g25185 = NOT(g22228) +g25188 = NOT(g23909) +g25193 = NOT(g22763) +g25194 = NOT(g22763) +g25195 = NOT(g22763) +g25196 = NOT(g22763) +g25197 = NOT(g23958) +g25198 = NOT(g22228) +g25202 = NOT(g23932) +g25206 = NOT(g23613) +g25208 = NOT(g22763) +g25209 = NOT(g22763) +g25210 = NOT(g23802) +g25211 = NOT(g22763) +g25212 = NOT(g22763) +g25213 = NOT(g23293) +g25214 = NOT(g22228) +g25218 = NOT(g23949) +I24393 = NOT(g23453) +g25219 = NOT(I24393) +I24396 = NOT(g23453) +g25220 = NOT(I24396) +g25221 = NOT(g23653) +I24400 = NOT(g23954) +g25222 = NOT(I24400) +g25224 = NOT(g22763) +g25225 = NOT(g23802) +g25226 = NOT(g22763) +g25227 = NOT(g22763) +g25228 = NOT(g23828) +g25230 = NOT(g23314) +g25231 = NOT(g22228) +g25232 = NOT(g22228) +g25239 = NOT(g23972) +g25240 = NOT(g23650) +g25241 = NOT(g23651) +g25242 = NOT(g23684) +g25243 = NOT(g22763) +g25244 = NOT(g23802) +g25245 = NOT(g22763) +g25246 = NOT(g23828) +g25248 = NOT(g22228) +g25249 = NOT(g22228) +I24434 = NOT(g22763) +g25250 = NOT(I24434) +I24445 = NOT(g22923) +g25259 = NOT(I24445) +I24448 = NOT(g22923) +g25260 = NOT(I24448) +g25262 = NOT(g22763) +g25263 = NOT(g22763) +g25264 = NOT(g23828) +I24455 = NOT(g22541) +g25265 = NOT(I24455) +g25266 = NOT(g22228) +g25267 = NOT(g22228) +g25272 = NOT(g23715) +g25273 = NOT(g23978) +g25274 = NOT(g22763) +g25282 = NOT(g22763) +g25283 = NOT(g22763) +I24474 = NOT(g22546) +g25284 = NOT(I24474) +g25286 = NOT(g22228) +g25287 = NOT(g22228) +g25288 = NOT(g22228) +g25289 = NOT(g22228) +g25296 = NOT(g23745) +g25297 = NOT(g23746) +g25298 = NOT(g23760) +g25299 = NOT(g22763) +g25307 = NOT(g22763) +g25308 = NOT(g22763) +g25316 = NOT(g22763) +I24497 = NOT(g22592) +g25322 = NOT(I24497) +g25324 = NOT(g22228) +g25325 = NOT(g22228) +g25326 = NOT(g22228) +g25327 = NOT(g22161) +g25340 = NOT(g22763) +g25348 = NOT(g22763) +g25356 = NOT(g22763) +g25369 = NOT(g22228) +g25370 = NOT(g22228) +g25380 = NOT(g23776) +g25388 = NOT(g22763) +g25399 = NOT(g22763) +g25409 = NOT(g22228) +g25410 = NOT(g22228) +I24558 = NOT(g23777) +g25423 = NOT(I24558) +g25424 = NOT(g23800) +g25438 = NOT(g22763) +g25451 = NOT(g22228) +g25452 = NOT(g22228) +g25465 = NOT(g23824) +g25480 = NOT(g22228) +g25481 = NOT(g22228) +g25505 = NOT(g22228) +g25506 = NOT(g22228) +g25513 = NOT(g23870) +g25517 = NOT(g22228) +g25523 = NOT(g22550) +g25524 = NOT(g22228) +g25525 = NOT(g22550) +g25528 = NOT(g22594) +g25529 = NOT(g22763) +g25533 = NOT(g22550) +g25534 = NOT(g22763) +g25535 = NOT(g22763) +g25538 = NOT(g22594) +g25541 = NOT(g22763) +g25542 = NOT(g22763) +g25544 = NOT(g22594) +g25546 = NOT(g22550) +g25547 = NOT(g22550) +g25548 = NOT(g22550) +g25549 = NOT(g22763) +g25550 = NOT(g22763) +g25552 = NOT(g22594) +g25553 = NOT(g22550) +g25554 = NOT(g22550) +g25555 = NOT(g22550) +g25556 = NOT(g22763) +g25557 = NOT(g22763) +g25558 = NOT(g22594) +g25560 = NOT(g22550) +g25561 = NOT(g22550) +g25562 = NOT(g22763) +g25563 = NOT(g22594) +g25564 = NOT(g22312) +g25566 = NOT(g22550) +I24759 = NOT(g24229) +g25620 = NOT(I24759) +I24781 = NOT(g24264) +g25640 = NOT(I24781) +I24784 = NOT(g24265) +g25641 = NOT(I24784) +I24787 = NOT(g24266) +g25642 = NOT(I24787) +I24839 = NOT(g24298) +g25692 = NOT(I24839) +g25766 = NOT(g24439) +I24920 = NOT(g25513) +g25771 = NOT(I24920) +g25773 = NOT(g24453) +g25781 = NOT(g24510) +g25783 = NOT(g25250) +g25786 = NOT(g24518) +g25790 = NOT(g25027) +g25820 = NOT(g25051) +g25830 = NOT(g24485) +g25837 = NOT(g25064) +g25838 = NOT(g25250) +g25849 = NOT(g24491) +g25869 = NOT(g25250) +g25882 = NOT(g25026) +g25886 = NOT(g24537) +g25892 = NOT(g24528) +g25893 = NOT(g24541) +g25899 = NOT(g24997) +I25005 = NOT(g24417) +g25903 = NOT(I25005) +I25028 = NOT(g24484) +g25930 = NOT(I25028) +g25994 = NOT(g24575) +I25095 = NOT(g25265) +g25997 = NOT(I25095) +I25105 = NOT(g25284) +g26026 = NOT(I25105) +g26054 = NOT(g24804) +I25115 = NOT(g25322) +g26055 = NOT(I25115) +g26081 = NOT(g24619) +g26083 = NOT(g24809) +g26093 = NOT(g24814) +I25146 = NOT(g24911) +g26105 = NOT(I25146) +I25161 = NOT(g24920) +g26131 = NOT(I25161) +I25190 = NOT(g25423) +g26187 = NOT(I25190) +g26260 = NOT(g24759) +g26284 = NOT(g24875) +g26326 = NOT(g24872) +g26337 = NOT(g24818) +g26340 = NOT(g24953) +I25327 = NOT(g24641) +g26364 = NOT(I25327) +I25351 = NOT(g24466) +g26400 = NOT(I25351) +I25356 = NOT(g24374) +g26424 = NOT(I25356) +I25359 = NOT(g24715) +g26483 = NOT(I25359) +I25366 = NOT(g24477) +g26488 = NOT(I25366) +I25369 = NOT(g24891) +g26510 = NOT(I25369) +g26518 = NOT(g25233) +I25380 = NOT(g24481) +g26519 = NOT(I25380) +g26548 = NOT(g25255) +I25391 = NOT(g24483) +g26549 = NOT(I25391) +g26575 = NOT(g25268) +I25399 = NOT(g24489) +g26576 = NOT(I25399) +g26605 = NOT(g25293) +g26607 = NOT(g25382) +g26608 = NOT(g25334) +g26614 = NOT(g25426) +g26615 = NOT(g25432) +g26631 = NOT(g25467) +g26632 = NOT(g25473) +g26634 = NOT(g25317) +g26648 = NOT(g25115) +g26653 = NOT(g25337) +g26654 = NOT(g25275) +g26655 = NOT(g25492) +g26656 = NOT(g25495) +g26672 = NOT(g25275) +g26679 = NOT(g25385) +g26680 = NOT(g25300) +g26681 = NOT(g25396) +g26682 = NOT(g25309) +g26683 = NOT(g25514) +g26693 = NOT(g25300) +g26700 = NOT(g25429) +g26701 = NOT(g25341) +g26702 = NOT(g25309) +g26709 = NOT(g25435) +g26710 = NOT(g25349) +g26718 = NOT(g25168) +g26720 = NOT(g25275) +g26724 = NOT(g25341) +g26731 = NOT(g25470) +g26732 = NOT(g25389) +g26736 = NOT(g25349) +g26743 = NOT(g25476) +g26744 = NOT(g25400) +g26754 = NOT(g25300) +g26758 = NOT(g25389) +g26765 = NOT(g25309) +g26769 = NOT(g25400) +g26776 = NOT(g25498) +g26777 = NOT(g25439) +g26784 = NOT(g25341) +g26788 = NOT(g25349) +g26792 = NOT(g25439) +I25511 = NOT(g25073) +g26801 = NOT(I25511) +I25514 = NOT(g25073) +g26802 = NOT(I25514) +g26803 = NOT(g25389) +g26804 = NOT(g25400) +g26810 = NOT(g25220) +g26811 = NOT(g25206) +g26812 = NOT(g25439) +g26814 = NOT(g25221) +g26816 = NOT(g25260) +g26817 = NOT(g25242) +I25530 = NOT(g25222) +g26818 = NOT(I25530) +I25534 = NOT(g25448) +g26820 = NOT(I25534) +g26824 = NOT(g25298) +I25541 = NOT(g25180) +g26825 = NOT(I25541) +g26827 = NOT(g24819) +g26830 = NOT(g24411) +g26831 = NOT(g24836) +g26832 = NOT(g24850) +I25552 = NOT(g25240) +g26834 = NOT(I25552) +I25555 = NOT(g25241) +g26835 = NOT(I25555) +g26836 = NOT(g24866) +g26837 = NOT(g24869) +I25562 = NOT(g25250) +g26840 = NOT(I25562) +g26841 = NOT(g24893) +I25567 = NOT(g25272) +g26843 = NOT(I25567) +I25576 = NOT(g25296) +g26850 = NOT(I25576) +I25579 = NOT(g25297) +g26851 = NOT(I25579) +I25586 = NOT(g25537) +g26856 = NOT(I25586) +I25591 = NOT(g25380) +g26859 = NOT(I25591) +I25594 = NOT(g25531) +g26860 = NOT(I25594) +I25598 = NOT(g25424) +g26862 = NOT(I25598) +g26869 = NOT(g24842) +I25606 = NOT(g25465) +g26870 = NOT(I25606) +I25677 = NOT(g25640) +g26935 = NOT(I25677) +I25680 = NOT(g25641) +g26936 = NOT(I25680) +I25683 = NOT(g25642) +g26937 = NOT(I25683) +I25689 = NOT(g25688) +g26941 = NOT(I25689) +I25692 = NOT(g25689) +g26942 = NOT(I25692) +I25695 = NOT(g25690) +g26943 = NOT(I25695) +g26973 = NOT(g26105) +g26987 = NOT(g26131) +g26990 = NOT(g26105) +g27004 = NOT(g26131) +g27009 = NOT(g25911) +g27011 = NOT(g25917) +I25743 = NOT(g25903) +g27013 = NOT(I25743) +g27014 = NOT(g25888) +g27015 = NOT(g26869) +g27017 = NOT(g25895) +I25750 = NOT(g26823) +g27018 = NOT(I25750) +g27038 = NOT(g25932) +I25779 = NOT(g26424) +g27051 = NOT(I25779) +I25786 = NOT(g26424) +g27064 = NOT(I25786) +I25790 = NOT(g26424) +g27074 = NOT(I25790) +g27084 = NOT(g26673) +g27088 = NOT(g26694) +g27089 = NOT(g26703) +g27091 = NOT(g26725) +g27092 = NOT(g26737) +g27100 = NOT(g26759) +g27101 = NOT(g26770) +g27112 = NOT(g26793) +g27142 = NOT(g26105) +g27155 = NOT(g26131) +I25869 = NOT(g25851) +g27163 = NOT(I25869) +I25882 = NOT(g25776) +g27187 = NOT(I25882) +g27237 = NOT(g26162) +g27242 = NOT(g26183) +g27245 = NOT(g26209) +g27279 = NOT(g26330) +I26004 = NOT(g26818) +g27320 = NOT(I26004) +g27349 = NOT(g26352) +I26100 = NOT(g26365) +g27402 = NOT(I26100) +g27415 = NOT(g26382) +I26130 = NOT(g26510) +g27438 = NOT(I26130) +g27492 = NOT(g26598) +I26195 = NOT(g26260) +g27527 = NOT(I26195) +g27554 = NOT(g26625) +g27565 = NOT(g26645) +g27573 = NOT(g26667) +g27576 = NOT(g26081) +g27583 = NOT(g26686) +g27585 = NOT(g25994) +g27592 = NOT(g26715) +g27597 = NOT(g26745) +I26296 = NOT(g26820) +g27662 = NOT(I26296) +I26309 = NOT(g26825) +g27675 = NOT(I26309) +g27698 = NOT(g26648) +I26334 = NOT(g26834) +g27708 = NOT(I26334) +I26337 = NOT(g26835) +g27709 = NOT(I26337) +g27730 = NOT(g26424) +I26356 = NOT(g26843) +g27736 = NOT(I26356) +g27737 = NOT(g26718) +I26378 = NOT(g26850) +g27773 = NOT(I26378) +I26381 = NOT(g26851) +g27774 = NOT(I26381) +g27830 = NOT(g26802) +I26406 = NOT(g26187) +g27831 = NOT(I26406) +I26409 = NOT(g26187) +g27832 = NOT(I26409) +I26427 = NOT(g26859) +g27880 = NOT(I26427) +I26430 = NOT(g26856) +g27881 = NOT(I26430) +g27928 = NOT(g26810) +I26448 = NOT(g26860) +g27929 = NOT(I26448) +I26451 = NOT(g26862) +g27930 = NOT(I26451) +I26466 = NOT(g26870) +g27956 = NOT(I26466) +g27961 = NOT(g26816) +I26479 = NOT(g25771) +g27967 = NOT(I26479) +g27971 = NOT(g26673) +g27975 = NOT(g26694) +g27976 = NOT(g26703) +g27977 = NOT(g26105) +g27983 = NOT(g26725) +g27984 = NOT(g26737) +g27985 = NOT(g26131) +g27989 = NOT(g26759) +g27990 = NOT(g26770) +g27991 = NOT(g25852) +I26503 = NOT(g26811) +g27993 = NOT(I26503) +g27994 = NOT(g26793) +I26508 = NOT(g26814) +g27996 = NOT(I26508) +I26512 = NOT(g26817) +g27998 = NOT(I26512) +I26516 = NOT(g26824) +g28009 = NOT(I26516) +g28032 = NOT(g26365) +g28033 = NOT(g26365) +g28034 = NOT(g26365) +g28036 = NOT(g26365) +g28037 = NOT(g26365) +g28038 = NOT(g26365) +g28039 = NOT(g26365) +g28040 = NOT(g26365) +I26578 = NOT(g26941) +g28079 = NOT(I26578) +I26581 = NOT(g26942) +g28080 = NOT(I26581) +I26584 = NOT(g26943) +g28081 = NOT(I26584) +g28119 = NOT(g27008) +g28120 = NOT(g27108) +g28121 = NOT(g27093) +g28126 = NOT(g27122) +g28127 = NOT(g27102) +I26638 = NOT(g27965) +g28137 = NOT(I26638) +I26649 = NOT(g27675) +g28142 = NOT(I26649) +I26654 = NOT(g27576) +g28147 = NOT(I26654) +I26664 = NOT(g27708) +g28155 = NOT(I26664) +I26667 = NOT(g27585) +g28156 = NOT(I26667) +I26670 = NOT(g27709) +g28157 = NOT(I26670) +I26676 = NOT(g27736) +g28161 = NOT(I26676) +I26679 = NOT(g27773) +g28162 = NOT(I26679) +I26682 = NOT(g27774) +g28163 = NOT(I26682) +I26687 = NOT(g27880) +g28166 = NOT(I26687) +I26693 = NOT(g27930) +g28173 = NOT(I26693) +I26700 = NOT(g27956) +g28181 = NOT(I26700) +I26705 = NOT(g27967) +g28184 = NOT(I26705) +I26710 = NOT(g27511) +g28187 = NOT(I26710) +g28241 = NOT(g27064) +g28250 = NOT(g27074) +I26785 = NOT(g27013) +g28262 = NOT(I26785) +I26799 = NOT(g27660) +g28274 = NOT(I26799) +g28294 = NOT(g27295) +g28307 = NOT(g27306) +g28321 = NOT(g27317) +g28325 = NOT(g27463) +g28326 = NOT(g27414) +I26880 = NOT(g27527) +g28367 = NOT(I26880) +g28370 = NOT(g27528) +g28380 = NOT(g27064) +g28399 = NOT(g27074) +I26925 = NOT(g27015) +g28431 = NOT(I26925) +I26929 = NOT(g27980) +g28436 = NOT(I26929) +g28441 = NOT(g27629) +I26936 = NOT(g27599) +g28443 = NOT(I26936) +I26952 = NOT(g27972) +g28463 = NOT(I26952) +g28479 = NOT(g27654) +I26989 = NOT(g27277) +g28508 = NOT(I26989) +g28559 = NOT(g27700) +g28575 = NOT(g27711) +g28579 = NOT(g27714) +g28590 = NOT(g27724) +g28593 = NOT(g27727) +g28598 = NOT(g27717) +g28604 = NOT(g27759) +g28606 = NOT(g27762) +g28608 = NOT(g27670) +g28615 = NOT(g27817) +g28620 = NOT(g27679) +g28633 = NOT(g27687) +g28648 = NOT(g27693) +g28656 = NOT(g27742) +g28669 = NOT(g27705) +g28675 = NOT(g27779) +g28678 = NOT(g27800) +g28693 = NOT(g27837) +g28696 = NOT(g27858) +I27192 = NOT(g27662) +g28709 = NOT(I27192) +g28711 = NOT(g27886) +g28713 = NOT(g27907) +g28726 = NOT(g27937) +I27232 = NOT(g27993) +g28752 = NOT(I27232) +I27235 = NOT(g27320) +g28753 = NOT(I27235) +I27238 = NOT(g27320) +g28754 = NOT(I27238) +I27253 = NOT(g27996) +g28779 = NOT(I27253) +I27271 = NOT(g27998) +g28819 = NOT(I27271) +I27314 = NOT(g28009) +g28917 = NOT(I27314) +g28918 = NOT(g27832) +g28954 = NOT(g27830) +I27368 = NOT(g27881) +g29013 = NOT(I27368) +g29014 = NOT(g27742) +I27385 = NOT(g27438) +g29041 = NOT(I27385) +I27388 = NOT(g27698) +g29042 = NOT(I27388) +I27391 = NOT(g27929) +g29043 = NOT(I27391) +g29044 = NOT(g27742) +g29045 = NOT(g27779) +g29056 = NOT(g27800) +I27401 = NOT(g27051) +g29067 = NOT(I27401) +g29079 = NOT(g27742) +g29080 = NOT(g27779) +g29081 = NOT(g27837) +g29092 = NOT(g27800) +g29093 = NOT(g27858) +g29115 = NOT(g27779) +g29116 = NOT(g27837) +g29117 = NOT(g27886) +g29128 = NOT(g27800) +g29129 = NOT(g27858) +g29130 = NOT(g27907) +I27449 = NOT(g27737) +g29147 = NOT(I27449) +g29149 = NOT(g27837) +g29150 = NOT(g27886) +g29151 = NOT(g27858) +g29152 = NOT(g27907) +g29153 = NOT(g27937) +g29169 = NOT(g27886) +g29170 = NOT(g27907) +g29171 = NOT(g27937) +g29172 = NOT(g27020) +g29177 = NOT(g27937) +I27481 = NOT(g27928) +g29185 = NOT(I27481) +g29190 = NOT(g27046) +I27492 = NOT(g27511) +g29194 = NOT(I27492) +I27495 = NOT(g27961) +g29195 = NOT(I27495) +g29196 = NOT(g27059) +I27543 = NOT(g28187) +g29209 = NOT(I27543) +I27546 = NOT(g29041) +g29210 = NOT(I27546) +I27549 = NOT(g28161) +g29211 = NOT(I27549) +I27552 = NOT(g28162) +g29212 = NOT(I27552) +I27555 = NOT(g28142) +g29213 = NOT(I27555) +I27558 = NOT(g28155) +g29214 = NOT(I27558) +I27561 = NOT(g28163) +g29215 = NOT(I27561) +I27564 = NOT(g28166) +g29216 = NOT(I27564) +I27567 = NOT(g28181) +g29217 = NOT(I27567) +I27570 = NOT(g28262) +g29218 = NOT(I27570) +I27573 = NOT(g28157) +g29219 = NOT(I27573) +I27576 = NOT(g28173) +g29220 = NOT(I27576) +I27579 = NOT(g28184) +g29221 = NOT(I27579) +g29310 = NOT(g28991) +g29311 = NOT(g28998) +g29312 = NOT(g28877) +I27677 = NOT(g28156) +g29317 = NOT(I27677) +g29318 = NOT(g29029) +g29333 = NOT(g28167) +g29339 = NOT(g28274) +g29342 = NOT(g28188) +g29343 = NOT(g28174) +g29348 = NOT(g28194) +I27713 = NOT(g28224) +g29353 = NOT(I27713) +I27718 = NOT(g28231) +g29358 = NOT(I27718) +g29365 = NOT(g29067) +I27730 = NOT(g28752) +g29368 = NOT(I27730) +I27735 = NOT(g28779) +g29371 = NOT(I27735) +I27738 = NOT(g28140) +g29372 = NOT(I27738) +I27742 = NOT(g28819) +g29374 = NOT(I27742) +I27749 = NOT(g28917) +g29379 = NOT(I27749) +g29385 = NOT(g28180) +I27758 = NOT(g28119) +g29474 = NOT(I27758) +I27777 = NOT(g29043) +g29491 = NOT(I27777) +I27784 = NOT(g29013) +g29498 = NOT(I27784) +g29505 = NOT(g29186) +g29507 = NOT(g28353) +g29597 = NOT(g28444) +I27927 = NOT(g28803) +g29653 = NOT(I27927) +I27941 = NOT(g28803) +g29669 = NOT(I27941) +I27954 = NOT(g28803) +g29689 = NOT(I27954) +g29697 = NOT(g28336) +g29707 = NOT(g28504) +I27970 = NOT(g28803) +g29713 = NOT(I27970) +g29725 = NOT(g28349) +g29744 = NOT(g28431) +g29745 = NOT(g28500) +I28002 = NOT(g28153) +g29755 = NOT(I28002) +I28014 = NOT(g28158) +g29765 = NOT(I28014) +g29800 = NOT(g28363) +g29811 = NOT(g28376) +g29812 = NOT(g28381) +I28062 = NOT(g29194) +g29814 = NOT(I28062) +g29846 = NOT(g28391) +g29847 = NOT(g28395) +g29862 = NOT(g28406) +g29863 = NOT(g28410) +g29878 = NOT(g28421) +g29893 = NOT(g28755) +I28128 = NOT(g28314) +g29897 = NOT(I28128) +g29905 = NOT(g28783) +g29906 = NOT(g28793) +g29911 = NOT(g28780) +g29912 = NOT(g28827) +g29913 = NOT(g28840) +g29920 = NOT(g28824) +g29921 = NOT(g28864) +g29922 = NOT(g28837) +g29923 = NOT(g28874) +g29925 = NOT(g28820) +g29927 = NOT(g28861) +g29928 = NOT(g28871) +g29929 = NOT(g28914) +I28162 = NOT(g28803) +g29930 = NOT(I28162) +g29939 = NOT(g28857) +g29941 = NOT(g28900) +g29942 = NOT(g28867) +g29944 = NOT(g28911) +I28174 = NOT(g28803) +g29945 = NOT(I28174) +g29948 = NOT(g28853) +g29950 = NOT(g28896) +g29953 = NOT(g28907) +g29955 = NOT(g28950) +I28185 = NOT(g28803) +g29956 = NOT(I28185) +g29960 = NOT(g28885) +g29961 = NOT(g28892) +g29963 = NOT(g28931) +g29965 = NOT(g28903) +g29967 = NOT(g28946) +I28199 = NOT(g28803) +g29970 = NOT(I28199) +g29976 = NOT(g29018) +g29977 = NOT(g28920) +g29978 = NOT(g28927) +g29980 = NOT(g28935) +g29981 = NOT(g28942) +g29983 = NOT(g28977) +g29993 = NOT(g29018) +g29994 = NOT(g29049) +g29995 = NOT(g28955) +g29996 = NOT(g28962) +g29997 = NOT(g29060) +g29998 = NOT(g28966) +g29999 = NOT(g28973) +I28241 = NOT(g28709) +g30012 = NOT(I28241) +g30016 = NOT(g29049) +g30017 = NOT(g29085) +g30018 = NOT(g28987) +g30019 = NOT(g29060) +g30020 = NOT(g29097) +g30021 = NOT(g28994) +g30022 = NOT(g29001) +g30036 = NOT(g29085) +g30037 = NOT(g29121) +g30038 = NOT(g29097) +g30039 = NOT(g29134) +g30040 = NOT(g29025) +g30052 = NOT(g29018) +g30053 = NOT(g29121) +g30054 = NOT(g29134) +g30055 = NOT(g29157) +g30063 = NOT(g29015) +g30065 = NOT(g29049) +g30067 = NOT(g29060) +g30068 = NOT(g29157) +I28301 = NOT(g29042) +g30072 = NOT(I28301) +g30074 = NOT(g29046) +g30076 = NOT(g29085) +g30077 = NOT(g29057) +g30079 = NOT(g29097) +g30085 = NOT(g29082) +g30087 = NOT(g29121) +g30088 = NOT(g29094) +g30090 = NOT(g29134) +g30097 = NOT(g29118) +g30100 = NOT(g29131) +g30102 = NOT(g29157) +I28336 = NOT(g29147) +g30105 = NOT(I28336) +g30113 = NOT(g29154) +I28349 = NOT(g28367) +g30116 = NOT(I28349) +g30142 = NOT(g28754) +I28390 = NOT(g29185) +g30155 = NOT(I28390) +I28419 = NOT(g29195) +g30182 = NOT(I28419) +g30184 = NOT(g28144) +I28434 = NOT(g28114) +g30195 = NOT(I28434) +g30206 = NOT(g28436) +I28458 = NOT(g28443) +g30217 = NOT(I28458) +g30218 = NOT(g28918) +I28480 = NOT(g28652) +g30237 = NOT(I28480) +g30259 = NOT(g28463) +g30292 = NOT(g28736) +I28540 = NOT(g28954) +g30295 = NOT(I28540) +g30296 = NOT(g28889) +g30297 = NOT(g28758) +g30299 = NOT(g28765) +I28548 = NOT(g28147) +g30301 = NOT(I28548) +g30302 = NOT(g28924) +g30303 = NOT(g28786) +g30305 = NOT(g28939) +g30306 = NOT(g28796) +g30309 = NOT(g28959) +g30310 = NOT(g28830) +g30312 = NOT(g28970) +g30313 = NOT(g28843) +g30318 = NOT(g28274) +I28572 = NOT(g28274) +g30321 = NOT(I28572) +g30322 = NOT(g28431) +I28576 = NOT(g28431) +g30325 = NOT(I28576) +I28579 = NOT(g29474) +g30326 = NOT(I28579) +I28582 = NOT(g30116) +g30327 = NOT(I28582) +I28585 = NOT(g30217) +g30328 = NOT(I28585) +I28588 = NOT(g29368) +g30329 = NOT(I28588) +I28591 = NOT(g29371) +g30330 = NOT(I28591) +I28594 = NOT(g29379) +g30331 = NOT(I28594) +I28597 = NOT(g29374) +g30332 = NOT(I28597) +I28832 = NOT(g30301) +g30565 = NOT(I28832) +g30567 = NOT(g29930) +g30568 = NOT(g29339) +I28838 = NOT(g29372) +g30569 = NOT(I28838) +g30572 = NOT(g29945) +g30578 = NOT(g29956) +I28851 = NOT(g29317) +g30591 = NOT(I28851) +g30593 = NOT(g29970) +I28866 = NOT(g29730) +g30606 = NOT(I28866) +I28872 = NOT(g30072) +g30610 = NOT(I28872) +I28883 = NOT(g30105) +g30729 = NOT(I28883) +I28897 = NOT(g30155) +g30917 = NOT(I28897) +I28908 = NOT(g30182) +g30928 = NOT(I28908) +I28913 = NOT(g30322) +g30931 = NOT(I28913) +g30983 = NOT(g29657) +g30989 = NOT(g29672) +g30990 = NOT(g29676) +I28925 = NOT(g29987) +g30991 = NOT(I28925) +g30996 = NOT(g29694) +g30997 = NOT(g29702) +g30998 = NOT(g29719) +g30999 = NOT(g29722) +g31000 = NOT(g29737) +g31013 = NOT(g29679) +g31138 = NOT(g29778) +I29002 = NOT(g29675) +g31189 = NOT(I29002) +I29013 = NOT(g29705) +g31213 = NOT(I29013) +g31227 = NOT(g29744) +g31239 = NOT(g29916) +g31243 = NOT(g29933) +I29139 = NOT(g29382) +g31479 = NOT(I29139) +I29149 = NOT(g29384) +g31487 = NOT(I29149) +I29182 = NOT(g30012) +g31521 = NOT(I29182) +I29185 = NOT(g30012) +g31522 = NOT(I29185) +I29199 = NOT(g30237) +g31578 = NOT(I29199) +I29204 = NOT(g29505) +g31596 = NOT(I29204) +I29207 = NOT(g30293) +g31601 = NOT(I29207) +g31608 = NOT(g29653) +I29211 = NOT(g30298) +g31609 = NOT(I29211) +I29214 = NOT(g30300) +g31616 = NOT(I29214) +g31623 = NOT(g29669) +I29218 = NOT(g30304) +g31624 = NOT(I29218) +I29221 = NOT(g30307) +g31631 = NOT(I29221) +g31638 = NOT(g29689) +I29225 = NOT(g30311) +g31639 = NOT(I29225) +I29228 = NOT(g30314) +g31646 = NOT(I29228) +g31653 = NOT(g29713) +I29233 = NOT(g30295) +g31655 = NOT(I29233) +I29236 = NOT(g29498) +g31656 = NOT(I29236) +I29239 = NOT(g29498) +g31657 = NOT(I29239) +I29242 = NOT(g29313) +g31658 = NOT(I29242) +I29245 = NOT(g29491) +g31665 = NOT(I29245) +I29248 = NOT(g29491) +g31666 = NOT(I29248) +g31667 = NOT(g30142) +I29337 = NOT(g30286) +g31771 = NOT(I29337) +I29363 = NOT(g30218) +g31791 = NOT(I29363) +I29368 = NOT(g30321) +g31794 = NOT(I29368) +I29371 = NOT(g30325) +g31795 = NOT(I29371) +g31796 = NOT(g29385) +g31797 = NOT(g29385) +g31798 = NOT(g29385) +g31799 = NOT(g29385) +g31800 = NOT(g29385) +g31801 = NOT(g29385) +g31802 = NOT(g29385) +g31803 = NOT(g29385) +g31804 = NOT(g29385) +g31805 = NOT(g29385) +g31806 = NOT(g29385) +g31807 = NOT(g29385) +g31808 = NOT(g29385) +g31809 = NOT(g29385) +g31810 = NOT(g29385) +g31811 = NOT(g29385) +g31812 = NOT(g29385) +g31813 = NOT(g29385) +g31814 = NOT(g29385) +g31815 = NOT(g29385) +g31816 = NOT(g29385) +g31817 = NOT(g29385) +g31818 = NOT(g29385) +g31819 = NOT(g29385) +g31820 = NOT(g29385) +g31821 = NOT(g29385) +g31822 = NOT(g29385) +g31823 = NOT(g29385) +g31824 = NOT(g29385) +g31825 = NOT(g29385) +g31826 = NOT(g29385) +g31827 = NOT(g29385) +g31828 = NOT(g29385) +g31829 = NOT(g29385) +g31830 = NOT(g29385) +g31831 = NOT(g29385) +g31832 = NOT(g29385) +g31833 = NOT(g29385) +g31834 = NOT(g29385) +g31835 = NOT(g29385) +g31836 = NOT(g29385) +g31837 = NOT(g29385) +g31838 = NOT(g29385) +g31839 = NOT(g29385) +g31840 = NOT(g29385) +g31841 = NOT(g29385) +g31842 = NOT(g29385) +g31843 = NOT(g29385) +g31844 = NOT(g29385) +g31845 = NOT(g29385) +g31846 = NOT(g29385) +g31847 = NOT(g29385) +g31848 = NOT(g29385) +g31849 = NOT(g29385) +g31850 = NOT(g29385) +g31851 = NOT(g29385) +g31852 = NOT(g29385) +g31853 = NOT(g29385) +g31854 = NOT(g29385) +g31855 = NOT(g29385) +g31856 = NOT(g29385) +g31857 = NOT(g29385) +g31858 = NOT(g29385) +g31859 = NOT(g29385) +I29438 = NOT(g30610) +g31860 = NOT(I29438) +I29441 = NOT(g30917) +g31861 = NOT(I29441) +I29444 = NOT(g30928) +g31862 = NOT(I29444) +I29447 = NOT(g30729) +g31863 = NOT(I29447) +g31937 = NOT(g30991) +g31945 = NOT(g31189) +I29571 = NOT(g31783) +g32015 = NOT(I29571) +I29579 = NOT(g30565) +g32021 = NOT(I29579) +I29582 = NOT(g30591) +g32024 = NOT(I29582) +I29585 = NOT(g31655) +g32027 = NOT(I29585) +g32033 = NOT(g30929) +g32038 = NOT(g30934) +g32090 = NOT(g31003) +g32099 = NOT(g31009) +g32118 = NOT(g31008) +g32137 = NOT(g31134) +g32138 = NOT(g31233) +I29717 = NOT(g30931) +g32185 = NOT(I29717) +I29720 = NOT(g30931) +g32186 = NOT(I29720) +g32192 = NOT(g31262) +g32201 = NOT(g31509) +g32318 = NOT(g31596) +g32329 = NOT(g31522) +I29891 = NOT(g31578) +g32363 = NOT(I29891) +I29894 = NOT(g31771) +g32364 = NOT(I29894) +g32377 = NOT(g30984) +I29909 = NOT(g31791) +g32381 = NOT(I29909) +g32382 = NOT(g31657) +I29913 = NOT(g30605) +g32383 = NOT(I29913) +g32384 = NOT(g31666) +g32393 = NOT(g30922) +g32394 = NOT(g30601) +I29936 = NOT(g30606) +g32404 = NOT(I29936) +I29939 = NOT(g31667) +g32407 = NOT(I29939) +g32415 = NOT(g31591) +g32421 = NOT(g31213) +g32430 = NOT(g30984) +I29961 = NOT(g30984) +g32433 = NOT(I29961) +g32434 = NOT(g31189) +I29965 = NOT(g31189) +g32437 = NOT(I29965) +g32438 = NOT(g30991) +I29969 = NOT(g30991) +g32441 = NOT(I29969) +g32442 = NOT(g31213) +I29973 = NOT(g31213) +g32445 = NOT(I29973) +g32446 = NOT(g31596) +I29977 = NOT(g31596) +g32449 = NOT(I29977) +g32450 = NOT(g31591) +I29981 = NOT(g31591) +g32453 = NOT(I29981) +g32456 = NOT(g31376) +g32457 = NOT(g30735) +g32458 = NOT(g30825) +g32459 = NOT(g31070) +g32460 = NOT(g31194) +g32461 = NOT(g30614) +g32462 = NOT(g30673) +g32463 = NOT(g31566) +g32464 = NOT(g30735) +g32465 = NOT(g30825) +g32466 = NOT(g31070) +g32467 = NOT(g31194) +g32468 = NOT(g30614) +g32469 = NOT(g30673) +g32470 = NOT(g31566) +g32471 = NOT(g31376) +g32472 = NOT(g30825) +g32473 = NOT(g31070) +g32474 = NOT(g31194) +g32475 = NOT(g30614) +g32476 = NOT(g30673) +g32477 = NOT(g31566) +g32478 = NOT(g31376) +g32479 = NOT(g30735) +g32480 = NOT(g31070) +g32481 = NOT(g31194) +g32482 = NOT(g30614) +g32483 = NOT(g30673) +g32484 = NOT(g31566) +g32485 = NOT(g31376) +g32486 = NOT(g30735) +g32487 = NOT(g30825) +g32488 = NOT(g31194) +g32489 = NOT(g30614) +g32490 = NOT(g30673) +g32491 = NOT(g31566) +g32492 = NOT(g31376) +g32493 = NOT(g30735) +g32494 = NOT(g30825) +g32495 = NOT(g31070) +g32496 = NOT(g30614) +g32497 = NOT(g30673) +g32498 = NOT(g31566) +g32499 = NOT(g31376) +g32500 = NOT(g30735) +g32501 = NOT(g30825) +g32502 = NOT(g31070) +g32503 = NOT(g31194) +g32504 = NOT(g30673) +g32505 = NOT(g31566) +g32506 = NOT(g31376) +g32507 = NOT(g30735) +g32508 = NOT(g30825) +g32509 = NOT(g31070) +g32510 = NOT(g31194) +g32511 = NOT(g30614) +g32512 = NOT(g31566) +g32513 = NOT(g31376) +g32514 = NOT(g30735) +g32515 = NOT(g30825) +g32516 = NOT(g31070) +g32517 = NOT(g31194) +g32518 = NOT(g30614) +g32519 = NOT(g30673) +g32521 = NOT(g31376) +g32522 = NOT(g30735) +g32523 = NOT(g30825) +g32524 = NOT(g31070) +g32525 = NOT(g31170) +g32526 = NOT(g30614) +g32527 = NOT(g30673) +g32528 = NOT(g31554) +g32529 = NOT(g30735) +g32530 = NOT(g30825) +g32531 = NOT(g31070) +g32532 = NOT(g31170) +g32533 = NOT(g30614) +g32534 = NOT(g30673) +g32535 = NOT(g31554) +g32536 = NOT(g31376) +g32537 = NOT(g30825) +g32538 = NOT(g31070) +g32539 = NOT(g31170) +g32540 = NOT(g30614) +g32541 = NOT(g30673) +g32542 = NOT(g31554) +g32543 = NOT(g31376) +g32544 = NOT(g30735) +g32545 = NOT(g31070) +g32546 = NOT(g31170) +g32547 = NOT(g30614) +g32548 = NOT(g30673) +g32549 = NOT(g31554) +g32550 = NOT(g31376) +g32551 = NOT(g30735) +g32552 = NOT(g30825) +g32553 = NOT(g31170) +g32554 = NOT(g30614) +g32555 = NOT(g30673) +g32556 = NOT(g31554) +g32557 = NOT(g31376) +g32558 = NOT(g30735) +g32559 = NOT(g30825) +g32560 = NOT(g31070) +g32561 = NOT(g30614) +g32562 = NOT(g30673) +g32563 = NOT(g31554) +g32564 = NOT(g31376) +g32565 = NOT(g30735) +g32566 = NOT(g30825) +g32567 = NOT(g31070) +g32568 = NOT(g31170) +g32569 = NOT(g30673) +g32570 = NOT(g31554) +g32571 = NOT(g31376) +g32572 = NOT(g30735) +g32573 = NOT(g30825) +g32574 = NOT(g31070) +g32575 = NOT(g31170) +g32576 = NOT(g30614) +g32577 = NOT(g31554) +g32578 = NOT(g31376) +g32579 = NOT(g30735) +g32580 = NOT(g30825) +g32581 = NOT(g31070) +g32582 = NOT(g31170) +g32583 = NOT(g30614) +g32584 = NOT(g30673) +g32586 = NOT(g31376) +g32587 = NOT(g30735) +g32588 = NOT(g30825) +g32589 = NOT(g31070) +g32590 = NOT(g31154) +g32591 = NOT(g30614) +g32592 = NOT(g30673) +g32593 = NOT(g31542) +g32594 = NOT(g30735) +g32595 = NOT(g30825) +g32596 = NOT(g31070) +g32597 = NOT(g31154) +g32598 = NOT(g30614) +g32599 = NOT(g30673) +g32600 = NOT(g31542) +g32601 = NOT(g31376) +g32602 = NOT(g30825) +g32603 = NOT(g31070) +g32604 = NOT(g31154) +g32605 = NOT(g30614) +g32606 = NOT(g30673) +g32607 = NOT(g31542) +g32608 = NOT(g31376) +g32609 = NOT(g30735) +g32610 = NOT(g31070) +g32611 = NOT(g31154) +g32612 = NOT(g30614) +g32613 = NOT(g30673) +g32614 = NOT(g31542) +g32615 = NOT(g31376) +g32616 = NOT(g30735) +g32617 = NOT(g30825) +g32618 = NOT(g31154) +g32619 = NOT(g30614) +g32620 = NOT(g30673) +g32621 = NOT(g31542) +g32622 = NOT(g31376) +g32623 = NOT(g30735) +g32624 = NOT(g30825) +g32625 = NOT(g31070) +g32626 = NOT(g30614) +g32627 = NOT(g30673) +g32628 = NOT(g31542) +g32629 = NOT(g31376) +g32630 = NOT(g30735) +g32631 = NOT(g30825) +g32632 = NOT(g31070) +g32633 = NOT(g31154) +g32634 = NOT(g30673) +g32635 = NOT(g31542) +g32636 = NOT(g31376) +g32637 = NOT(g30735) +g32638 = NOT(g30825) +g32639 = NOT(g31070) +g32640 = NOT(g31154) +g32641 = NOT(g30614) +g32642 = NOT(g31542) +g32643 = NOT(g31376) +g32644 = NOT(g30735) +g32645 = NOT(g30825) +g32646 = NOT(g31070) +g32647 = NOT(g31154) +g32648 = NOT(g30614) +g32649 = NOT(g30673) +g32651 = NOT(g31376) +g32652 = NOT(g30735) +g32653 = NOT(g30825) +g32654 = NOT(g31070) +g32655 = NOT(g30614) +g32656 = NOT(g30673) +g32657 = NOT(g31528) +g32658 = NOT(g31579) +g32659 = NOT(g30735) +g32660 = NOT(g30825) +g32661 = NOT(g31070) +g32662 = NOT(g30614) +g32663 = NOT(g30673) +g32664 = NOT(g31528) +g32665 = NOT(g31579) +g32666 = NOT(g31376) +g32667 = NOT(g30825) +g32668 = NOT(g31070) +g32669 = NOT(g30614) +g32670 = NOT(g30673) +g32671 = NOT(g31528) +g32672 = NOT(g31579) +g32673 = NOT(g31376) +g32674 = NOT(g30735) +g32675 = NOT(g31070) +g32676 = NOT(g30614) +g32677 = NOT(g30673) +g32678 = NOT(g31528) +g32679 = NOT(g31579) +g32680 = NOT(g31376) +g32681 = NOT(g30735) +g32682 = NOT(g30825) +g32683 = NOT(g30614) +g32684 = NOT(g30673) +g32685 = NOT(g31528) +g32686 = NOT(g31579) +g32687 = NOT(g31376) +g32688 = NOT(g30735) +g32689 = NOT(g30825) +g32690 = NOT(g31070) +g32691 = NOT(g30673) +g32692 = NOT(g31528) +g32693 = NOT(g31579) +g32694 = NOT(g31376) +g32695 = NOT(g30735) +g32696 = NOT(g30825) +g32697 = NOT(g31070) +g32698 = NOT(g30614) +g32699 = NOT(g31528) +g32700 = NOT(g31579) +g32701 = NOT(g31376) +g32702 = NOT(g30735) +g32703 = NOT(g30825) +g32704 = NOT(g31070) +g32705 = NOT(g30614) +g32706 = NOT(g30673) +g32707 = NOT(g31579) +g32708 = NOT(g31376) +g32709 = NOT(g30735) +g32710 = NOT(g30825) +g32711 = NOT(g31070) +g32712 = NOT(g30614) +g32713 = NOT(g30673) +g32714 = NOT(g31528) +g32716 = NOT(g31376) +g32717 = NOT(g30735) +g32718 = NOT(g30825) +g32719 = NOT(g31672) +g32720 = NOT(g31710) +g32721 = NOT(g31021) +g32722 = NOT(g30937) +g32723 = NOT(g31327) +g32724 = NOT(g30735) +g32725 = NOT(g30825) +g32726 = NOT(g31672) +g32727 = NOT(g31710) +g32728 = NOT(g31021) +g32729 = NOT(g30937) +g32730 = NOT(g31327) +g32731 = NOT(g31376) +g32732 = NOT(g30825) +g32733 = NOT(g31672) +g32734 = NOT(g31710) +g32735 = NOT(g31021) +g32736 = NOT(g30937) +g32737 = NOT(g31327) +g32738 = NOT(g31376) +g32739 = NOT(g30735) +g32740 = NOT(g31672) +g32741 = NOT(g31710) +g32742 = NOT(g31021) +g32743 = NOT(g30937) +g32744 = NOT(g31327) +g32745 = NOT(g31376) +g32746 = NOT(g30735) +g32747 = NOT(g30825) +g32748 = NOT(g31710) +g32749 = NOT(g31021) +g32750 = NOT(g30937) +g32751 = NOT(g31327) +g32752 = NOT(g31376) +g32753 = NOT(g30735) +g32754 = NOT(g30825) +g32755 = NOT(g31672) +g32756 = NOT(g31021) +g32757 = NOT(g30937) +g32758 = NOT(g31327) +g32759 = NOT(g31376) +g32760 = NOT(g30735) +g32761 = NOT(g30825) +g32762 = NOT(g31672) +g32763 = NOT(g31710) +g32764 = NOT(g30937) +g32765 = NOT(g31327) +g32766 = NOT(g31376) +g32767 = NOT(g30735) +g32768 = NOT(g30825) +g32769 = NOT(g31672) +g32770 = NOT(g31710) +g32771 = NOT(g31021) +g32772 = NOT(g31327) +g32773 = NOT(g31376) +g32774 = NOT(g30735) +g32775 = NOT(g30825) +g32776 = NOT(g31672) +g32777 = NOT(g31710) +g32778 = NOT(g31021) +g32779 = NOT(g30937) +g32781 = NOT(g31376) +g32782 = NOT(g30735) +g32783 = NOT(g30825) +g32784 = NOT(g31672) +g32785 = NOT(g31710) +g32786 = NOT(g31021) +g32787 = NOT(g30937) +g32788 = NOT(g31327) +g32789 = NOT(g30735) +g32790 = NOT(g30825) +g32791 = NOT(g31672) +g32792 = NOT(g31710) +g32793 = NOT(g31021) +g32794 = NOT(g30937) +g32795 = NOT(g31327) +g32796 = NOT(g31376) +g32797 = NOT(g30825) +g32798 = NOT(g31672) +g32799 = NOT(g31710) +g32800 = NOT(g31021) +g32801 = NOT(g30937) +g32802 = NOT(g31327) +g32803 = NOT(g31376) +g32804 = NOT(g30735) +g32805 = NOT(g31672) +g32806 = NOT(g31710) +g32807 = NOT(g31021) +g32808 = NOT(g30937) +g32809 = NOT(g31327) +g32810 = NOT(g31376) +g32811 = NOT(g30735) +g32812 = NOT(g30825) +g32813 = NOT(g31710) +g32814 = NOT(g31021) +g32815 = NOT(g30937) +g32816 = NOT(g31327) +g32817 = NOT(g31376) +g32818 = NOT(g30735) +g32819 = NOT(g30825) +g32820 = NOT(g31672) +g32821 = NOT(g31021) +g32822 = NOT(g30937) +g32823 = NOT(g31327) +g32824 = NOT(g31376) +g32825 = NOT(g30735) +g32826 = NOT(g30825) +g32827 = NOT(g31672) +g32828 = NOT(g31710) +g32829 = NOT(g30937) +g32830 = NOT(g31327) +g32831 = NOT(g31376) +g32832 = NOT(g30735) +g32833 = NOT(g30825) +g32834 = NOT(g31672) +g32835 = NOT(g31710) +g32836 = NOT(g31021) +g32837 = NOT(g31327) +g32838 = NOT(g31376) +g32839 = NOT(g30735) +g32840 = NOT(g30825) +g32841 = NOT(g31672) +g32842 = NOT(g31710) +g32843 = NOT(g31021) +g32844 = NOT(g30937) +g32846 = NOT(g31376) +g32847 = NOT(g30735) +g32848 = NOT(g30825) +g32849 = NOT(g31021) +g32850 = NOT(g30937) +g32851 = NOT(g31327) +g32852 = NOT(g30614) +g32853 = NOT(g30673) +g32854 = NOT(g30735) +g32855 = NOT(g30825) +g32856 = NOT(g31021) +g32857 = NOT(g30937) +g32858 = NOT(g31327) +g32859 = NOT(g30614) +g32860 = NOT(g30673) +g32861 = NOT(g31376) +g32862 = NOT(g30825) +g32863 = NOT(g31021) +g32864 = NOT(g30937) +g32865 = NOT(g31327) +g32866 = NOT(g30614) +g32867 = NOT(g30673) +g32868 = NOT(g31376) +g32869 = NOT(g30735) +g32870 = NOT(g31021) +g32871 = NOT(g30937) +g32872 = NOT(g31327) +g32873 = NOT(g30614) +g32874 = NOT(g30673) +g32875 = NOT(g31376) +g32876 = NOT(g30735) +g32877 = NOT(g30825) +g32878 = NOT(g30937) +g32879 = NOT(g31327) +g32880 = NOT(g30614) +g32881 = NOT(g30673) +g32882 = NOT(g31376) +g32883 = NOT(g30735) +g32884 = NOT(g30825) +g32885 = NOT(g31021) +g32886 = NOT(g31327) +g32887 = NOT(g30614) +g32888 = NOT(g30673) +g32889 = NOT(g31376) +g32890 = NOT(g30735) +g32891 = NOT(g30825) +g32892 = NOT(g31021) +g32893 = NOT(g30937) +g32894 = NOT(g30614) +g32895 = NOT(g30673) +g32896 = NOT(g31376) +g32897 = NOT(g30735) +g32898 = NOT(g30825) +g32899 = NOT(g31021) +g32900 = NOT(g30937) +g32901 = NOT(g31327) +g32902 = NOT(g30673) +g32903 = NOT(g31376) +g32904 = NOT(g30735) +g32905 = NOT(g30825) +g32906 = NOT(g31021) +g32907 = NOT(g30937) +g32908 = NOT(g31327) +g32909 = NOT(g30614) +g32911 = NOT(g31376) +g32912 = NOT(g30735) +g32913 = NOT(g30825) +g32914 = NOT(g31672) +g32915 = NOT(g31710) +g32916 = NOT(g31021) +g32917 = NOT(g30937) +g32918 = NOT(g31327) +g32919 = NOT(g30735) +g32920 = NOT(g30825) +g32921 = NOT(g31672) +g32922 = NOT(g31710) +g32923 = NOT(g31021) +g32924 = NOT(g30937) +g32925 = NOT(g31327) +g32926 = NOT(g31376) +g32927 = NOT(g30825) +g32928 = NOT(g31672) +g32929 = NOT(g31710) +g32930 = NOT(g31021) +g32931 = NOT(g30937) +g32932 = NOT(g31327) +g32933 = NOT(g31376) +g32934 = NOT(g30735) +g32935 = NOT(g31672) +g32936 = NOT(g31710) +g32937 = NOT(g31021) +g32938 = NOT(g30937) +g32939 = NOT(g31327) +g32940 = NOT(g31376) +g32941 = NOT(g30735) +g32942 = NOT(g30825) +g32943 = NOT(g31710) +g32944 = NOT(g31021) +g32945 = NOT(g30937) +g32946 = NOT(g31327) +g32947 = NOT(g31376) +g32948 = NOT(g30735) +g32949 = NOT(g30825) +g32950 = NOT(g31672) +g32951 = NOT(g31021) +g32952 = NOT(g30937) +g32953 = NOT(g31327) +g32954 = NOT(g31376) +g32955 = NOT(g30735) +g32956 = NOT(g30825) +g32957 = NOT(g31672) +g32958 = NOT(g31710) +g32959 = NOT(g30937) +g32960 = NOT(g31327) +g32961 = NOT(g31376) +g32962 = NOT(g30735) +g32963 = NOT(g30825) +g32964 = NOT(g31672) +g32965 = NOT(g31710) +g32966 = NOT(g31021) +g32967 = NOT(g31327) +g32968 = NOT(g31376) +g32969 = NOT(g30735) +g32970 = NOT(g30825) +g32971 = NOT(g31672) +g32972 = NOT(g31710) +g32973 = NOT(g31021) +g32974 = NOT(g30937) +I30537 = NOT(g32027) +g32975 = NOT(I30537) +g33072 = NOT(g31945) +I30641 = NOT(g32024) +g33079 = NOT(I30641) +I30644 = NOT(g32024) +g33080 = NOT(I30644) +I30686 = NOT(g32381) +g33120 = NOT(I30686) +g33127 = NOT(g31950) +g33136 = NOT(g32057) +g33142 = NOT(g32072) +I30766 = NOT(g32363) +g33228 = NOT(I30766) +g33246 = NOT(g32212) +g33250 = NOT(g32186) +g33258 = NOT(g32296) +g33326 = NOT(g32318) +I30861 = NOT(g32383) +g33335 = NOT(I30861) +g33346 = NOT(g32132) +g33354 = NOT(g32329) +g33375 = NOT(g32377) +I30901 = NOT(g32407) +g33377 = NOT(I30901) +I30904 = NOT(g32424) +g33378 = NOT(I30904) +g33382 = NOT(g32033) +g33385 = NOT(g32038) +g33388 = NOT(g32382) +g33391 = NOT(g32384) +g33413 = NOT(g31971) +g33424 = NOT(g32415) +g33426 = NOT(g32017) +g33430 = NOT(g32421) +I30959 = NOT(g32021) +g33435 = NOT(I30959) +I30962 = NOT(g32021) +g33436 = NOT(I30962) +g33442 = NOT(g31937) +I30971 = NOT(g32015) +g33443 = NOT(I30971) +g33451 = NOT(g32132) +I30980 = NOT(g32132) +g33454 = NOT(I30980) +I30983 = NOT(g32433) +g33455 = NOT(I30983) +I30986 = NOT(g32437) +g33456 = NOT(I30986) +I30989 = NOT(g32441) +g33457 = NOT(I30989) +I30992 = NOT(g32445) +g33458 = NOT(I30992) +I30995 = NOT(g32449) +g33459 = NOT(I30995) +I30998 = NOT(g32453) +g33460 = NOT(I30998) +I31361 = NOT(g33120) +g33533 = NOT(I31361) +I31459 = NOT(g33219) +g33631 = NOT(I31459) +g33635 = NOT(g33436) +I31463 = NOT(g33318) +g33636 = NOT(I31463) +I31466 = NOT(g33318) +g33637 = NOT(I31466) +I31469 = NOT(g33388) +g33638 = NOT(I31469) +I31474 = NOT(g33212) +g33641 = NOT(I31474) +I31477 = NOT(g33391) +g33645 = NOT(I31477) +I31482 = NOT(g33204) +g33648 = NOT(I31482) +I31486 = NOT(g33197) +g33653 = NOT(I31486) +g33658 = NOT(g33080) +I31491 = NOT(g33283) +g33659 = NOT(I31491) +I31494 = NOT(g33283) +g33660 = NOT(I31494) +I31497 = NOT(g33187) +g33661 = NOT(I31497) +I31500 = NOT(g33176) +g33665 = NOT(I31500) +I31504 = NOT(g33164) +g33670 = NOT(I31504) +I31515 = NOT(g33187) +g33682 = NOT(I31515) +g33686 = NOT(g33187) +I31523 = NOT(g33187) +g33688 = NOT(I31523) +I31528 = NOT(g33219) +g33691 = NOT(I31528) +g33695 = NOT(g33187) +I31535 = NOT(g33377) +g33696 = NOT(I31535) +I31539 = NOT(g33212) +g33698 = NOT(I31539) +I31545 = NOT(g33219) +g33702 = NOT(I31545) +I31550 = NOT(g33204) +g33705 = NOT(I31550) +I31555 = NOT(g33212) +g33708 = NOT(I31555) +I31561 = NOT(g33197) +g33712 = NOT(I31561) +I31564 = NOT(g33204) +g33713 = NOT(I31564) +I31569 = NOT(g33197) +g33716 = NOT(I31569) +I31581 = NOT(g33164) +g33726 = NOT(I31581) +I31586 = NOT(g33149) +g33729 = NOT(I31586) +I31597 = NOT(g33187) +g33736 = NOT(I31597) +I31604 = NOT(g33176) +g33744 = NOT(I31604) +I31607 = NOT(g33164) +g33750 = NOT(I31607) +I31610 = NOT(g33149) +g33755 = NOT(I31610) +I31616 = NOT(g33219) +g33761 = NOT(I31616) +I31619 = NOT(g33212) +g33766 = NOT(I31619) +I31622 = NOT(g33204) +g33772 = NOT(I31622) +I31625 = NOT(g33197) +g33778 = NOT(I31625) +g33797 = NOT(g33306) +g33799 = NOT(g33299) +I31642 = NOT(g33204) +g33800 = NOT(I31642) +g33804 = NOT(g33250) +I31650 = NOT(g33212) +g33806 = NOT(I31650) +I31659 = NOT(g33219) +g33813 = NOT(I31659) +I31672 = NOT(g33149) +g33827 = NOT(I31672) +I31686 = NOT(g33164) +g33839 = NOT(I31686) +I31694 = NOT(g33176) +g33845 = NOT(I31694) +I31701 = NOT(g33164) +g33850 = NOT(I31701) +I31724 = NOT(g33076) +g33874 = NOT(I31724) +I31727 = NOT(g33076) +g33875 = NOT(I31727) +g33888 = NOT(g33346) +I31748 = NOT(g33228) +g33894 = NOT(I31748) +I31751 = NOT(g33228) +g33895 = NOT(I31751) +I31770 = NOT(g33197) +g33912 = NOT(I31770) +I31776 = NOT(g33204) +g33916 = NOT(I31776) +I31779 = NOT(g33212) +g33917 = NOT(I31779) +I31782 = NOT(g33219) +g33918 = NOT(I31782) +I31786 = NOT(g33197) +g33920 = NOT(I31786) +I31791 = NOT(g33354) +g33923 = NOT(I31791) +I31796 = NOT(g33176) +g33926 = NOT(I31796) +I31800 = NOT(g33164) +g33928 = NOT(I31800) +I31803 = NOT(g33176) +g33929 = NOT(I31803) +I31807 = NOT(g33149) +g33931 = NOT(I31807) +I31810 = NOT(g33164) +g33932 = NOT(I31810) +I31814 = NOT(g33149) +g33934 = NOT(I31814) +I31817 = NOT(g33323) +g33935 = NOT(I31817) +I31820 = NOT(g33323) +g33936 = NOT(I31820) +I31823 = NOT(g33149) +g33937 = NOT(I31823) +I31829 = NOT(g33454) +g33944 = NOT(I31829) +I31878 = NOT(g33696) +g33959 = NOT(I31878) +g34042 = NOT(g33674) +g34044 = NOT(g33675) +g34047 = NOT(g33637) +g34049 = NOT(g33678) +g34052 = NOT(g33635) +g34053 = NOT(g33683) +g34058 = NOT(g33660) +g34059 = NOT(g33658) +g34060 = NOT(g33704) +g34062 = NOT(g33711) +g34068 = NOT(g33728) +g34070 = NOT(g33725) +g34094 = NOT(g33772) +I32051 = NOT(g33631) +g34118 = NOT(I32051) +I32056 = NOT(g33641) +g34121 = NOT(I32056) +I32059 = NOT(g33648) +g34122 = NOT(I32059) +I32062 = NOT(g33653) +g34123 = NOT(I32062) +g34124 = NOT(g33819) +I32067 = NOT(g33661) +g34126 = NOT(I32067) +I32071 = NOT(g33665) +g34130 = NOT(I32071) +I32074 = NOT(g33670) +g34131 = NOT(I32074) +g34132 = NOT(g33831) +I32079 = NOT(g33937) +g34134 = NOT(I32079) +I32089 = NOT(g33665) +g34142 = NOT(I32089) +I32093 = NOT(g33670) +g34144 = NOT(I32093) +I32096 = NOT(g33641) +g34145 = NOT(I32096) +g34147 = NOT(g33823) +I32103 = NOT(g33661) +g34150 = NOT(I32103) +I32106 = NOT(g33653) +g34151 = NOT(I32106) +I32109 = NOT(g33631) +g34152 = NOT(I32109) +g34156 = NOT(g33907) +I32116 = NOT(g33937) +g34159 = NOT(I32116) +I32119 = NOT(g33648) +g34160 = NOT(I32119) +g34161 = NOT(g33851) +g34181 = NOT(g33913) +g34188 = NOT(g33875) +g34192 = NOT(g33921) +I32150 = NOT(g33923) +g34195 = NOT(I32150) +g34197 = NOT(g33812) +g34200 = NOT(g33895) +I32158 = NOT(g33791) +g34201 = NOT(I32158) +I32161 = NOT(g33791) +g34202 = NOT(I32161) +g34208 = NOT(g33838) +I32170 = NOT(g33638) +g34209 = NOT(I32170) +I32173 = NOT(g33645) +g34210 = NOT(I32173) +I32192 = NOT(g33628) +g34221 = NOT(I32192) +I32195 = NOT(g33628) +g34222 = NOT(I32195) +g34229 = NOT(g33936) +I32222 = NOT(g34118) +g34241 = NOT(I32222) +I32225 = NOT(g34121) +g34242 = NOT(I32225) +I32228 = NOT(g34122) +g34243 = NOT(I32228) +I32231 = NOT(g34123) +g34244 = NOT(I32231) +I32234 = NOT(g34126) +g34245 = NOT(I32234) +I32237 = NOT(g34130) +g34246 = NOT(I32237) +I32240 = NOT(g34131) +g34247 = NOT(I32240) +I32243 = NOT(g34134) +g34248 = NOT(I32243) +g34270 = NOT(g34159) +g34271 = NOT(g34160) +g34272 = NOT(g34229) +g34275 = NOT(g34047) +g34276 = NOT(g34058) +I32274 = NOT(g34195) +g34277 = NOT(I32274) +I32284 = NOT(g34052) +g34285 = NOT(I32284) +I32297 = NOT(g34059) +g34296 = NOT(I32297) +g34299 = NOT(g34080) +I32305 = NOT(g34209) +g34302 = NOT(I32305) +I32309 = NOT(g34210) +g34304 = NOT(I32309) +g34307 = NOT(g34087) +g34308 = NOT(g34088) +g34311 = NOT(g34097) +g34312 = NOT(g34098) +g34313 = NOT(g34086) +g34315 = NOT(g34085) +g34316 = NOT(g34093) +g34317 = NOT(g34115) +g34320 = NOT(g34119) +g34323 = NOT(g34105) +g34325 = NOT(g34092) +g34326 = NOT(g34091) +g34327 = NOT(g34108) +g34328 = NOT(g34096) +g34336 = NOT(g34112) +g34339 = NOT(g34077) +g34343 = NOT(g34089) +I32352 = NOT(g34169) +g34345 = NOT(I32352) +g34346 = NOT(g34162) +g34351 = NOT(g34174) +I32364 = NOT(g34208) +g34358 = NOT(I32364) +I32388 = NOT(g34153) +g34383 = NOT(I32388) +I32391 = NOT(g34153) +g34384 = NOT(I32391) +g34387 = NOT(g34188) +g34391 = NOT(g34200) +g34392 = NOT(g34202) +g34400 = NOT(g34142) +g34408 = NOT(g34144) +g34409 = NOT(g34145) +g34418 = NOT(g34150) +g34419 = NOT(g34151) +g34420 = NOT(g34152) +g34423 = NOT(g34222) +I32446 = NOT(g34127) +g34425 = NOT(I32446) +I32449 = NOT(g34127) +g34426 = NOT(I32449) +I32452 = NOT(g34241) +g34427 = NOT(I32452) +I32455 = NOT(g34242) +g34428 = NOT(I32455) +I32458 = NOT(g34243) +g34429 = NOT(I32458) +I32461 = NOT(g34244) +g34430 = NOT(I32461) +I32464 = NOT(g34245) +g34431 = NOT(I32464) +I32467 = NOT(g34246) +g34432 = NOT(I32467) +I32470 = NOT(g34247) +g34433 = NOT(I32470) +I32473 = NOT(g34248) +g34434 = NOT(I32473) +I32476 = NOT(g34277) +g34435 = NOT(I32476) +I32479 = NOT(g34302) +g34436 = NOT(I32479) +I32482 = NOT(g34304) +g34437 = NOT(I32482) +g34471 = NOT(g34423) +I32525 = NOT(g34285) +g34472 = NOT(I32525) +g34473 = NOT(g34426) +I32535 = NOT(g34296) +g34480 = NOT(I32535) +I32547 = NOT(g34397) +g34490 = NOT(I32547) +I32550 = NOT(g34398) +g34491 = NOT(I32550) +g34501 = NOT(g34400) +g34504 = NOT(g34408) +g34505 = NOT(g34409) +g34510 = NOT(g34418) +g34511 = NOT(g34419) +g34512 = NOT(g34420) +g34521 = NOT(g34270) +g34522 = NOT(g34271) +I32591 = NOT(g34287) +g34530 = NOT(I32591) +I32594 = NOT(g34298) +g34531 = NOT(I32594) +I32601 = NOT(g34319) +g34536 = NOT(I32601) +g34539 = NOT(g34354) +I32607 = NOT(g34358) +g34540 = NOT(I32607) +g34543 = NOT(g34359) +I32613 = NOT(g34329) +g34544 = NOT(I32613) +I32617 = NOT(g34333) +g34549 = NOT(I32617) +I32621 = NOT(g34335) +g34553 = NOT(I32621) +g34559 = NOT(g34384) +I32639 = NOT(g34345) +g34569 = NOT(I32639) +g34570 = NOT(g34392) +I32645 = NOT(g34367) +g34573 = NOT(I32645) +I32648 = NOT(g34371) +g34574 = NOT(I32648) +I32651 = NOT(g34375) +g34575 = NOT(I32651) +I32654 = NOT(g34378) +g34576 = NOT(I32654) +I32659 = NOT(g34391) +g34579 = NOT(I32659) +I32665 = NOT(g34386) +g34583 = NOT(I32665) +I32671 = NOT(g34388) +g34587 = NOT(I32671) +I32675 = NOT(g34427) +g34589 = NOT(I32675) +I32678 = NOT(g34428) +g34590 = NOT(I32678) +I32681 = NOT(g34429) +g34591 = NOT(I32681) +I32684 = NOT(g34430) +g34592 = NOT(I32684) +I32687 = NOT(g34431) +g34593 = NOT(I32687) +I32690 = NOT(g34432) +g34594 = NOT(I32690) +I32693 = NOT(g34433) +g34595 = NOT(I32693) +I32696 = NOT(g34434) +g34596 = NOT(I32696) +I32699 = NOT(g34569) +g34597 = NOT(I32699) +I32752 = NOT(g34510) +g34648 = NOT(I32752) +I32763 = NOT(g34511) +g34653 = NOT(I32763) +I32766 = NOT(g34522) +g34654 = NOT(I32766) +I32770 = NOT(g34505) +g34656 = NOT(I32770) +I32775 = NOT(g34512) +g34659 = NOT(I32775) +g34660 = NOT(g34473) +I32782 = NOT(g34571) +g34664 = NOT(I32782) +I32788 = NOT(g34577) +g34668 = NOT(I32788) +I32791 = NOT(g34578) +g34669 = NOT(I32791) +I32794 = NOT(g34580) +g34670 = NOT(I32794) +I32797 = NOT(g34581) +g34671 = NOT(I32797) +I32800 = NOT(g34582) +g34672 = NOT(I32800) +I32803 = NOT(g34584) +g34673 = NOT(I32803) +I32806 = NOT(g34585) +g34674 = NOT(I32806) +I32809 = NOT(g34586) +g34675 = NOT(I32809) +I32812 = NOT(g34588) +g34676 = NOT(I32812) +I32815 = NOT(g34470) +g34677 = NOT(I32815) +I32820 = NOT(g34474) +g34680 = NOT(I32820) +I32824 = NOT(g34475) +g34682 = NOT(I32824) +I32827 = NOT(g34477) +g34683 = NOT(I32827) +I32834 = NOT(g34472) +g34688 = NOT(I32834) +I32837 = NOT(g34498) +g34689 = NOT(I32837) +I32840 = NOT(g34480) +g34690 = NOT(I32840) +I32843 = NOT(g34499) +g34691 = NOT(I32843) +I32846 = NOT(g34502) +g34692 = NOT(I32846) +g34697 = NOT(g34545) +g34698 = NOT(g34550) +I32855 = NOT(g34540) +g34699 = NOT(I32855) +g34711 = NOT(g34559) +I32868 = NOT(g34579) +g34712 = NOT(I32868) +I32871 = NOT(g34521) +g34713 = NOT(I32871) +I32874 = NOT(g34504) +g34714 = NOT(I32874) +I32878 = NOT(g34501) +g34716 = NOT(I32878) +I32881 = NOT(g34688) +g34717 = NOT(I32881) +I32884 = NOT(g34690) +g34718 = NOT(I32884) +I32904 = NOT(g34708) +g34736 = NOT(I32904) +I32909 = NOT(g34712) +g34739 = NOT(I32909) +I32921 = NOT(g34650) +g34749 = NOT(I32921) +I32929 = NOT(g34649) +g34755 = NOT(I32929) +I32935 = NOT(g34657) +g34759 = NOT(I32935) +I32938 = NOT(g34663) +g34760 = NOT(I32938) +g34766 = NOT(g34703) +I32947 = NOT(g34659) +g34767 = NOT(I32947) +I32950 = NOT(g34713) +g34768 = NOT(I32950) +I32953 = NOT(g34656) +g34769 = NOT(I32953) +I32956 = NOT(g34654) +g34770 = NOT(I32956) +I32960 = NOT(g34653) +g34772 = NOT(I32960) +I32963 = NOT(g34650) +g34773 = NOT(I32963) +I32967 = NOT(g34648) +g34775 = NOT(I32967) +I32970 = NOT(g34716) +g34776 = NOT(I32970) +I32973 = NOT(g34714) +g34777 = NOT(I32973) +I32976 = NOT(g34699) +g34778 = NOT(I32976) +I32982 = NOT(g34749) +g34784 = NOT(I32982) +I32985 = NOT(g34736) +g34785 = NOT(I32985) +I32988 = NOT(g34755) +g34786 = NOT(I32988) +I32991 = NOT(g34759) +g34787 = NOT(I32991) +I32994 = NOT(g34739) +g34788 = NOT(I32994) +I32997 = NOT(g34760) +g34789 = NOT(I32997) +I33020 = NOT(g34781) +g34810 = NOT(I33020) +I33024 = NOT(g34783) +g34812 = NOT(I33024) +I33027 = NOT(g34767) +g34813 = NOT(I33027) +I33030 = NOT(g34768) +g34816 = NOT(I33030) +I33034 = NOT(g34769) +g34820 = NOT(I33034) +I33037 = NOT(g34770) +g34823 = NOT(I33037) +I33041 = NOT(g34772) +g34827 = NOT(I33041) +I33044 = NOT(g34775) +g34830 = NOT(I33044) +I33047 = NOT(g34776) +g34833 = NOT(I33047) +I33050 = NOT(g34777) +g34836 = NOT(I33050) +I33053 = NOT(g34778) +g34839 = NOT(I33053) +I33056 = NOT(g34778) +g34840 = NOT(I33056) +g34844 = NOT(g34737) +g34845 = NOT(g34773) +I33064 = NOT(g34784) +g34846 = NOT(I33064) +I33067 = NOT(g34812) +g34847 = NOT(I33067) +I33070 = NOT(g34810) +g34848 = NOT(I33070) +I33075 = NOT(g34843) +g34851 = NOT(I33075) +g34852 = NOT(g34845) +I33079 = NOT(g34809) +g34855 = NOT(I33079) +g34864 = NOT(g34840) +I33103 = NOT(g34846) +g34877 = NOT(I33103) +I33106 = NOT(g34855) +g34878 = NOT(I33106) +I33109 = NOT(g34851) +g34879 = NOT(I33109) +g34883 = NOT(g34852) +I33119 = NOT(g34852) +g34893 = NOT(I33119) +g34910 = NOT(g34864) +I33131 = NOT(g34906) +g34913 = NOT(I33131) +I33134 = NOT(g34906) +g34914 = NOT(I33134) +I33137 = NOT(g34884) +g34915 = NOT(I33137) +I33140 = NOT(g34884) +g34916 = NOT(I33140) +I33143 = NOT(g34903) +g34917 = NOT(I33143) +I33146 = NOT(g34903) +g34918 = NOT(I33146) +I33149 = NOT(g34900) +g34919 = NOT(I33149) +I33152 = NOT(g34900) +g34920 = NOT(I33152) +I33155 = NOT(g34897) +g34921 = NOT(I33155) +I33158 = NOT(g34897) +g34922 = NOT(I33158) +I33161 = NOT(g34894) +g34923 = NOT(I33161) +I33164 = NOT(g34894) +g34924 = NOT(I33164) +I33167 = NOT(g34890) +g34925 = NOT(I33167) +I33170 = NOT(g34890) +g34926 = NOT(I33170) +I33173 = NOT(g34887) +g34927 = NOT(I33173) +I33176 = NOT(g34887) +g34928 = NOT(I33176) +I33179 = NOT(g34893) +g34929 = NOT(I33179) +I33182 = NOT(g34910) +g34930 = NOT(I33182) +g34932 = NOT(g34914) +g34933 = NOT(g34916) +g34934 = NOT(g34918) +I33189 = NOT(g34929) +g34935 = NOT(I33189) +g34938 = NOT(g34920) +g34939 = NOT(g34922) +g34940 = NOT(g34924) +g34941 = NOT(g34926) +g34942 = NOT(g34928) +I33197 = NOT(g34930) +g34943 = NOT(I33197) +g34944 = NOT(g34932) +g34945 = NOT(g34933) +g34946 = NOT(g34934) +g34947 = NOT(g34938) +g34949 = NOT(g34939) +g34950 = NOT(g34940) +g34951 = NOT(g34941) +g34952 = NOT(g34942) +I33210 = NOT(g34943) +g34954 = NOT(I33210) +I33214 = NOT(g34954) +g34956 = NOT(I33214) +I33218 = NOT(g34955) +g34960 = NOT(I33218) +I33232 = NOT(g34957) +g34972 = NOT(I33232) +I33235 = NOT(g34957) +g34973 = NOT(I33235) +g34981 = NOT(g34973) +I33246 = NOT(g34970) +g34982 = NOT(I33246) +I33249 = NOT(g34971) +g34983 = NOT(I33249) +I33252 = NOT(g34974) +g34984 = NOT(I33252) +I33255 = NOT(g34975) +g34985 = NOT(I33255) +I33258 = NOT(g34976) +g34986 = NOT(I33258) +I33261 = NOT(g34977) +g34987 = NOT(I33261) +I33264 = NOT(g34978) +g34988 = NOT(I33264) +I33267 = NOT(g34979) +g34989 = NOT(I33267) +I33270 = NOT(g34982) +g34990 = NOT(I33270) +I33273 = NOT(g34984) +g34991 = NOT(I33273) +I33276 = NOT(g34985) +g34992 = NOT(I33276) +I33279 = NOT(g34986) +g34993 = NOT(I33279) +I33282 = NOT(g34987) +g34994 = NOT(I33282) +I33285 = NOT(g34988) +g34995 = NOT(I33285) +I33288 = NOT(g34989) +g34996 = NOT(I33288) +I33291 = NOT(g34983) +g34997 = NOT(I33291) +g34998 = NOT(g34981) +I33297 = NOT(g35000) +g35001 = NOT(I33297) +I33300 = NOT(g35001) +g35002 = NOT(I33300) + +g7251 = AND(g452, g392) +g7396 = AND(g392, g441) +g7469 = AND(g4382, g4438) +g7511 = AND(g2145, g2138, g2130) +g7520 = AND(g2704, g2697, g2689) +g7685 = AND(g4382, g4375) +g7696 = AND(g2955, g2950) +g7763 = AND(g2965, g2960) +g7777 = AND(g723, g822, g817) +g7804 = AND(g2975, g2970) +g7918 = AND(g1205, g1087) +g7948 = AND(g1548, g1430) +g8234 = AND(g4515, g4521) +g8530 = AND(g2902, g2907) +g8583 = AND(g2917, g2912) +g8643 = AND(g2927, g2922) +g8690 = AND(g2941, g2936) +g8721 = AND(g385, g376, g365) +g9217 = AND(g632, g626) +g9479 = AND(g305, g324) +g9906 = AND(g996, g1157) +g9967 = AND(g1178, g1157) +g9968 = AND(g1339, g1500) +g10034 = AND(g1521, g1500) +g10290 = AND(g4358, g4349) +I13862 = AND(g7232, g7219, g7258) +g10476 = AND(g7244, g7259, I13862) +g10501 = AND(g1233, g9007) +g10528 = AND(g1576, g9051) +g10543 = AND(g8238, g437) +g10565 = AND(g8182, g424) +g10588 = AND(g7004, g5297) +I13937 = AND(g7340, g7293, g7261) +g10590 = AND(g7246, g7392, I13937) +g10616 = AND(g7998, g174) +g10619 = AND(g3080, g7907) +g10624 = AND(g8387, g3072) +g10625 = AND(g3431, g7926) +g10626 = AND(g4057, g7927) +g10632 = AND(g7475, g7441, g890) +g10654 = AND(g3085, g8434) +g10655 = AND(g8440, g3423) +g10656 = AND(g3782, g7952) +g10657 = AND(g8451, g4064) +g10665 = AND(g209, g8292) +g10674 = AND(g6841, g10200, g2130) +g10675 = AND(g3436, g8500) +g10676 = AND(g8506, g3774) +g10677 = AND(g4141, g7611) +g10683 = AND(g7289, g4438) +g10684 = AND(g7998, g411) +g10704 = AND(g2145, g10200, g2130) +g10705 = AND(g6850, g10219, g2689) +g10706 = AND(g3338, g8691) +g10707 = AND(g3787, g8561) +g10719 = AND(g6841, g2138, g2130) +g10720 = AND(g2704, g10219, g2689) +g10721 = AND(g3288, g6875, g3274, g8481) +g10724 = AND(g3689, g8728) +g10732 = AND(g6850, g2697, g2689) +g10733 = AND(g3639, g6905, g3625, g8542) +g10736 = AND(g4040, g8751) +g10756 = AND(g3990, g6928, g3976, g8595) +g10822 = AND(g4264, g8514) +g10823 = AND(g7704, g5180, g5188) +g10827 = AND(g8914, g4258) +g10828 = AND(g6888, g7640) +g10829 = AND(g7289, g4375) +g10838 = AND(g7738, g5527, g5535) +g10841 = AND(g8509, g8567) +g10856 = AND(g4269, g8967) +g10869 = AND(g7766, g5873, g5881) +g10873 = AND(g3004, g9015) +g10874 = AND(g7791, g6219, g6227) +g10878 = AND(g7858, g1135) +g10883 = AND(g3355, g9061) +g10887 = AND(g7812, g6565, g6573) +g10890 = AND(g7858, g1105) +g10896 = AND(g1205, g8654) +g10898 = AND(g3706, g9100) +g10902 = AND(g7858, g1129) +g10917 = AND(g9174, g1087) +g10921 = AND(g1548, g8685) +g10925 = AND(g7858, g956) +g10934 = AND(g9197, g7918) +g10947 = AND(g9200, g1430) +g10948 = AND(g7880, g1478) +g10966 = AND(g9226, g7948) +g10967 = AND(g7880, g1448) +g10970 = AND(g854, g9582) +g10998 = AND(g8567, g8509, g8451, g7650) +g10999 = AND(g7880, g1472) +g11003 = AND(g7880, g1300) +g11010 = AND(g4698, g8933) +g11016 = AND(g4888, g8984) +g11018 = AND(g7655, g7643, g7627) +g11019 = AND(g5092, g9036) +g11023 = AND(g9669, g5084) +g11024 = AND(g5436, g9070) +g11027 = AND(g5097, g9724) +g11028 = AND(g9730, g5428) +g11029 = AND(g5782, g9103) +g11032 = AND(g9354, g7717) +g11035 = AND(g5441, g9800) +g11036 = AND(g9806, g5774) +g11037 = AND(g6128, g9184) +g11044 = AND(g5343, g10124) +g11045 = AND(g5787, g9883) +g11046 = AND(g9889, g6120) +g11047 = AND(g6474, g9212) +g11083 = AND(g8836, g802) +g11111 = AND(g5297, g7004, g5283, g9780) +g11114 = AND(g5689, g10160) +g11115 = AND(g6133, g9954) +g11116 = AND(g9960, g6466) +g11123 = AND(g5644, g7028, g5630, g9864) +g11126 = AND(g6035, g10185) +g11127 = AND(g6479, g10022) +g11139 = AND(g5990, g7051, g5976, g9935) +g11142 = AND(g6381, g10207) +I14198 = AND(g225, g8237, g232, g8180) +g11144 = AND(g239, g8136, g246, I14198) +g11160 = AND(g6336, g7074, g6322, g10003) +g11163 = AND(g6727, g10224) +I14225 = AND(g8457, g255, g8406, g262) +g11166 = AND(g8363, g269, g8296, I14225) +g11178 = AND(g6682, g7097, g6668, g10061) +g11205 = AND(g8217, g8439) +g11223 = AND(g8281, g8505) +g11244 = AND(g8346, g8566) +g11366 = AND(g5016, g10338) +g11397 = AND(g5360, g7139) +g11427 = AND(g5706, g7158) +g11449 = AND(g6052, g7175) +g11496 = AND(g4382, g7495) +g11497 = AND(g6398, g7192) +g11546 = AND(g7289, g4375) +g11740 = AND(g8769, g703) +g11890 = AND(g7499, g9155) +g11893 = AND(g1668, g7268) +g11915 = AND(g1802, g7315) +g11916 = AND(g2227, g7328) +g11937 = AND(g1936, g7362) +g11939 = AND(g2361, g7380) +g11956 = AND(g2070, g7411) +g11960 = AND(g2495, g7424) +g11967 = AND(g311, g7802) +g11978 = AND(g2629, g7462) +g12015 = AND(g1002, g7567) +g12027 = AND(g9499, g9729) +g12043 = AND(g1345, g7601) +g12065 = AND(g9557, g9805) +g12099 = AND(g9619, g9888) +g12135 = AND(g9684, g9959) +g12179 = AND(g9745, g10027) +g12186 = AND(g1178, g7519) +g12219 = AND(g1189, g7532) +g12220 = AND(g1521, g7535) +g12259 = AND(g9480, g640) +g12284 = AND(g1532, g7557) +g12527 = AND(g8680, g667) +g12641 = AND(g10295, g3171, g3179) +g12687 = AND(g9024, g8977) +g12692 = AND(g10323, g3522, g3530) +g12730 = AND(g9024, g4349) +g12735 = AND(g7121, g3873, g3881) +g12761 = AND(g969, g7567) +g12762 = AND(g4358, g8977) +g12794 = AND(g1008, g7567) +g12795 = AND(g1312, g7601) +g12812 = AND(g518, g9158) +g12817 = AND(g1351, g7601) +g12920 = AND(g1227, g10960) +g12924 = AND(g1570, g10980) +g12931 = AND(g392, g11048) +g12939 = AND(g405, g11048) +g12953 = AND(g411, g11048) +g12979 = AND(g424, g11048) +g13019 = AND(g194, g11737) +g13020 = AND(g401, g11048) +g13025 = AND(g8431, g11026) +g13029 = AND(g8359, g11030) +g13030 = AND(g429, g11048) +g13035 = AND(g8497, g11033) +g13038 = AND(g8509, g11034) +g13042 = AND(g433, g11048) +g13046 = AND(g6870, g11270) +g13047 = AND(g8534, g11042) +g13048 = AND(g8558, g11043) +g13059 = AND(g6900, g11303) +g13060 = AND(g8587, g11110) +g13063 = AND(g8567, g10808) +g13080 = AND(g6923, g11357) +g13081 = AND(g8626, g11122) +g13156 = AND(g10816, g10812, g10805) +g13221 = AND(g6946, g11425) +g13247 = AND(g8964, g11316) +g13252 = AND(g11561, g11511, g11469, g699) +g13265 = AND(g9018, g11493) +g13277 = AND(g3195, g11432) +g13282 = AND(g3546, g11480) +g13287 = AND(g1221, g11472) +g13290 = AND(g3897, g11534) +g13294 = AND(g1564, g11513) +g13299 = AND(g437, g11048) +g13306 = AND(g441, g11048) +g13313 = AND(g475, g11048) +g13319 = AND(g4076, g8812, g10658, g8757) +g13320 = AND(g417, g11048) +g13321 = AND(g847, g11048) +g13324 = AND(g854, g11326) +g13333 = AND(g4743, g11755) +g13345 = AND(g4754, g11773) +g13349 = AND(g4933, g11780) +g13383 = AND(g4765, g11797) +g13384 = AND(g4944, g11804) +g13393 = AND(g703, g11048) +g13411 = AND(g4955, g11834) +g13415 = AND(g837, g11048) +g13436 = AND(g9721, g11811) +g13461 = AND(g2719, g11819) +g13473 = AND(g9797, g11841) +g13491 = AND(g6999, g12160) +g13492 = AND(g9856, g11865) +g13493 = AND(g9880, g11866) +g13497 = AND(g2724, g12155) +g13507 = AND(g7023, g12198) +g13508 = AND(g9927, g11888) +g13509 = AND(g9951, g11889) +g13523 = AND(g7046, g12246) +g13524 = AND(g9995, g11910) +g13525 = AND(g10019, g11911) +g13541 = AND(g7069, g12308) +g13542 = AND(g10053, g11927) +g13564 = AND(g4480, g12820) +g13566 = AND(g7092, g12358) +g13567 = AND(g10102, g11948) +g13604 = AND(g4495, g10487) +g13632 = AND(g10232, g12228) +g13633 = AND(g4567, g10509) +g13656 = AND(g278, g11144) +g13671 = AND(g4498, g10532) +g13697 = AND(g11166, g8608) +g13737 = AND(g4501, g10571) +g13738 = AND(g8880, g10572) +I16111 = AND(g8691, g11409, g11381) +g13771 = AND(g11441, g11355, g11302, I16111) +g13778 = AND(g4540, g10597) +I16129 = AND(g8728, g11443, g11411) +g13805 = AND(g11489, g11394, g11356, I16129) +g13807 = AND(g4504, g10606) +g13808 = AND(g4543, g10607) +I16143 = AND(g8751, g11491, g11445) +g13830 = AND(g11543, g11424, g11395, I16143) +g13832 = AND(g8880, g10612) +g13833 = AND(g4546, g10613) +g13853 = AND(g4549, g10620) +g13887 = AND(g5204, g12402) +g13912 = AND(g5551, g12450) +g13942 = AND(g5897, g12512) +g13974 = AND(g6243, g12578) +g13998 = AND(g6589, g12629) +g14028 = AND(g8673, g11797) +g14035 = AND(g699, g11048) +g14061 = AND(g8715, g11834) +g14097 = AND(g878, g10632) +g14126 = AND(g881, g10632) +g14148 = AND(g884, g10632) +g14168 = AND(g887, g10632) +g14180 = AND(g872, g10632) +g14185 = AND(g8686, g11744) +g14190 = AND(g859, g10632) +g14193 = AND(g7178, g10590) +g14202 = AND(g869, g10632) +g14206 = AND(g8655, g11790) +g14207 = AND(g8639, g11793) +g14210 = AND(g4392, g10590) +g14216 = AND(g7631, g10608) +g14218 = AND(g875, g10632) +g14220 = AND(g8612, g11820) +g14221 = AND(g8686, g11823) +g14222 = AND(g8655, g11826) +g14233 = AND(g8639, g11855) +g14256 = AND(g2079, g11872) +g14257 = AND(g8612, g11878) +g14261 = AND(g4507, g10738) +g14295 = AND(g1811, g11894) +g14296 = AND(g2638, g11897) +g14316 = AND(g2370, g11920) +g14438 = AND(g1087, g10726) +I16618 = AND(g10124, g12341, g12293) +g14496 = AND(g12411, g12244, g12197, I16618) +g14506 = AND(g1430, g10755) +I16646 = AND(g10160, g12413, g12343) +g14528 = AND(g12459, g12306, g12245, I16646) +g14537 = AND(g10550, g10529) +I16671 = AND(g10185, g12461, g12415) +g14555 = AND(g12521, g12356, g12307, I16671) +g14565 = AND(g11934, g11952) +g14566 = AND(g10566, g10551) +g14567 = AND(g10568, g10552) +I16695 = AND(g10207, g12523, g12463) +g14581 = AND(g12587, g12428, g12357, I16695) +g14585 = AND(g1141, g10905) +g14586 = AND(g11953, g11970) +g14587 = AND(g10584, g10567) +g14588 = AND(g11957, g11974) +g14589 = AND(g10586, g10569) +I16721 = AND(g10224, g12589, g12525) +g14608 = AND(g12638, g12476, g12429, I16721) +g14610 = AND(g1484, g10935) +g14612 = AND(g11971, g11993) +g14613 = AND(g10602, g10585) +g14614 = AND(g11975, g11997) +g14615 = AND(g10604, g10587) +g14641 = AND(g11994, g12020) +g14643 = AND(g11998, g12023) +g14644 = AND(g10610, g10605) +g14654 = AND(g7178, g10476) +g14680 = AND(g12024, g12053) +g14681 = AND(g4392, g10476) +g14708 = AND(g74, g12369) +g14719 = AND(g4392, g10830) +g14791 = AND(g1146, g10909) +g14831 = AND(g1152, g10909) +g14832 = AND(g1489, g10939) +g14874 = AND(g1099, g10909) +g14875 = AND(g1495, g10939) +g14913 = AND(g1442, g10939) +g15075 = AND(g12850, g12955) +g15076 = AND(g2130, g12955) +g15077 = AND(g2138, g12955) +g15078 = AND(g10361, g12955) +g15079 = AND(g2151, g12955) +g15080 = AND(g12855, g12983) +g15081 = AND(g2689, g12983) +g15082 = AND(g2697, g12983) +g15083 = AND(g10362, g12983) +g15084 = AND(g2710, g12983) +g15103 = AND(g4180, g14454) +g15104 = AND(g6955, g14454) +g15105 = AND(g4235, g14454) +g15107 = AND(g4258, g14454) +g15108 = AND(g4264, g14454) +g15109 = AND(g4269, g14454) +g15110 = AND(g4245, g14454) +g15111 = AND(g4281, g14454) +g15112 = AND(g4284, g14454) +g15113 = AND(g4291, g14454) +g15114 = AND(g4239, g14454) +g15115 = AND(g2946, g14454) +g15116 = AND(g4297, g14454) +g15117 = AND(g4300, g14454) +g15118 = AND(g4253, g14454) +g15119 = AND(g4249, g14454) +g15507 = AND(g10970, g13305) +g15567 = AND(g392, g13312) +g15574 = AND(g4311, g13202) +g15589 = AND(g411, g13334) +g15590 = AND(g3139, g13530) +g15611 = AND(g471, g13437) +g15612 = AND(g3143, g13530) +g15613 = AND(g3490, g13555) +g15631 = AND(g168, g13437) +g15632 = AND(g3494, g13555) +g15633 = AND(g3841, g13584) +g15650 = AND(g8362, g13413) +g15651 = AND(g429, g13414) +g15652 = AND(g174, g13437) +g15653 = AND(g3119, g13530) +g15654 = AND(g3845, g13584) +g15672 = AND(g433, g13458) +g15673 = AND(g182, g13437) +g15678 = AND(g1094, g13846) +g15679 = AND(g3470, g13555) +g15693 = AND(g269, g13474) +g15694 = AND(g457, g13437) +g15699 = AND(g1437, g13861) +g15700 = AND(g3089, g13483) +g15701 = AND(g3821, g13584) +g15703 = AND(g452, g13437) +g15704 = AND(g3440, g13504) +g15706 = AND(g13296, g13484) +g15707 = AND(g4082, g13506) +g15711 = AND(g460, g13437) +g15712 = AND(g3791, g13521) +g15716 = AND(g468, g13437) +g15722 = AND(g464, g13437) +g15738 = AND(g1111, g13260) +g15745 = AND(g686, g13223) +g15749 = AND(g1454, g13273) +g15757 = AND(g3207, g14066) +g15779 = AND(g13909, g11214) +g15783 = AND(g3215, g14098) +g15784 = AND(g3235, g13977) +g15785 = AND(g3558, g14107) +g15786 = AND(g13940, g11233) +g15793 = AND(g3219, g13873) +g15794 = AND(g3239, g14008) +g15795 = AND(g3566, g14130) +g15796 = AND(g3586, g14015) +g15797 = AND(g3909, g14139) +g15804 = AND(g3223, g13889) +g15805 = AND(g3243, g14041) +g15807 = AND(g3570, g13898) +g15808 = AND(g3590, g14048) +g15809 = AND(g3917, g14154) +g15810 = AND(g3937, g14055) +g15812 = AND(g3227, g13915) +g15813 = AND(g3247, g14069) +g15814 = AND(g3574, g13920) +g15815 = AND(g3594, g14075) +g15817 = AND(g3921, g13929) +g15818 = AND(g3941, g14082) +g15819 = AND(g3251, g14101) +g15820 = AND(g3578, g13955) +g15821 = AND(g3598, g14110) +g15822 = AND(g3925, g13960) +g15823 = AND(g3945, g14116) +g15836 = AND(g3187, g14104) +g15837 = AND(g3255, g14127) +g15838 = AND(g3602, g14133) +g15839 = AND(g3929, g13990) +g15840 = AND(g3949, g14142) +g15841 = AND(g4273, g13868) +g15847 = AND(g3191, g14005) +g15848 = AND(g3259, g13892) +g15849 = AND(g3538, g14136) +g15850 = AND(g3606, g14151) +g15851 = AND(g3953, g14157) +g15852 = AND(g13820, g13223) +g15856 = AND(g9056, g14223) +g15857 = AND(g3199, g14038) +g15858 = AND(g3542, g14045) +g15859 = AND(g3610, g13923) +g15860 = AND(g3889, g14160) +g15861 = AND(g3957, g14170) +g15863 = AND(g13762, g13223) +g15870 = AND(g3231, g13948) +g15871 = AND(g3203, g13951) +g15872 = AND(g9095, g14234) +g15873 = AND(g3550, g14072) +g15874 = AND(g3893, g14079) +g15875 = AND(g3961, g13963) +g15876 = AND(g13512, g13223) +g15880 = AND(g3211, g13980) +g15881 = AND(g3582, g13983) +g15882 = AND(g3554, g13986) +g15883 = AND(g9180, g14258) +g15884 = AND(g3901, g14113) +g15902 = AND(g441, g13975) +g15903 = AND(g13796, g13223) +g15911 = AND(g3111, g13530) +g15912 = AND(g3562, g14018) +g15913 = AND(g3933, g14021) +g15914 = AND(g3905, g14024) +g15936 = AND(g475, g13999) +g15937 = AND(g11950, g14387) +g15966 = AND(g3462, g13555) +g15967 = AND(g3913, g14058) +g15978 = AND(g246, g14032) +g15995 = AND(g13314, g1157, g10666) +g16023 = AND(g3813, g13584) +g16025 = AND(g446, g14063) +g16026 = AND(g854, g14065) +g16047 = AND(g13322, g1500, g10699) +g16098 = AND(g5148, g14238) +g16122 = AND(g9491, g14291) +g16125 = AND(g5152, g14238) +g16126 = AND(g5495, g14262) +g16128 = AND(g14333, g14166) +g16160 = AND(g5499, g14262) +g16161 = AND(g5841, g14297) +g16163 = AND(g14254, g14179) +g16176 = AND(g14596, g11779) +g16177 = AND(g5128, g14238) +g16178 = AND(g5845, g14297) +g16179 = AND(g6187, g14321) +g16184 = AND(g9285, g14183) +g16185 = AND(g3263, g14011) +g16190 = AND(g14626, g11810) +g16191 = AND(g5475, g14262) +g16192 = AND(g6191, g14321) +g16193 = AND(g6533, g14348) +I17529 = AND(g13156, g11450, g6756) +g16194 = AND(g11547, g6782, g11640, I17529) +g16199 = AND(g3614, g14051) +g16202 = AND(g86, g14197) +g16203 = AND(g5821, g14297) +g16204 = AND(g6537, g14348) +I17542 = AND(g13156, g6767, g6756) +g16205 = AND(g11547, g6782, g11640, I17542) +g16207 = AND(g9839, g14204) +g16208 = AND(g3965, g14085) +g16211 = AND(g5445, g14215) +g16212 = AND(g6167, g14321) +I17552 = AND(g13156, g11450, g11498) +g16213 = AND(g6772, g6782, g11640, I17552) +g16221 = AND(g5791, g14231) +g16222 = AND(g6513, g14348) +g16224 = AND(g14583, g14232) +g16233 = AND(g6137, g14251) +I17575 = AND(g13156, g11450, g6756) +g16234 = AND(g6772, g6782, g11640, I17575) +g16243 = AND(g6483, g14275) +I17585 = AND(g14988, g11450, g11498) +g16244 = AND(g11547, g11592, g6789, I17585) +g16245 = AND(g14278, g14708) +g16279 = AND(g4512, g14424) +I17606 = AND(g14988, g11450, g6756) +g16283 = AND(g11547, g11592, g6789, I17606) +g16303 = AND(g4527, g12921) +g16324 = AND(g13657, g182) +g16422 = AND(g8216, g13627) +g16427 = AND(g5216, g14876) +g16474 = AND(g8280, g13666) +g16483 = AND(g5224, g14915) +g16484 = AND(g5244, g14755) +g16485 = AND(g5563, g14924) +I17692 = AND(g14988, g11450, g6756) +g16486 = AND(g6772, g11592, g6789, I17692) +g16513 = AND(g8345, g13708) +g16516 = AND(g5228, g14627) +g16517 = AND(g5248, g14797) +g16518 = AND(g5571, g14956) +g16519 = AND(g5591, g14804) +g16520 = AND(g5909, g14965) +g16531 = AND(g5232, g14656) +g16532 = AND(g5252, g14841) +g16534 = AND(g5575, g14665) +g16535 = AND(g5595, g14848) +g16536 = AND(g5917, g14996) +g16537 = AND(g5937, g14855) +g16538 = AND(g6255, g15005) +I17741 = AND(g14988, g11450, g11498) +g16539 = AND(g11547, g6782, g6789, I17741) +g16590 = AND(g5236, g14683) +g16591 = AND(g5256, g14879) +g16592 = AND(g5579, g14688) +g16593 = AND(g5599, g14885) +g16595 = AND(g5921, g14697) +g16596 = AND(g5941, g14892) +g16597 = AND(g6263, g15021) +g16598 = AND(g6283, g14899) +g16599 = AND(g6601, g15030) +g16610 = AND(g5260, g14918) +g16611 = AND(g5583, g14727) +g16612 = AND(g5603, g14927) +g16613 = AND(g5925, g14732) +g16614 = AND(g5945, g14933) +g16616 = AND(g6267, g14741) +g16617 = AND(g6287, g14940) +g16618 = AND(g6609, g15039) +g16619 = AND(g6629, g14947) +g16621 = AND(g8278, g13821) +g16633 = AND(g5196, g14921) +g16634 = AND(g5264, g14953) +g16635 = AND(g5607, g14959) +g16636 = AND(g5929, g14768) +g16637 = AND(g5949, g14968) +g16638 = AND(g6271, g14773) +g16639 = AND(g6291, g14974) +g16641 = AND(g6613, g14782) +g16642 = AND(g6633, g14981) +g16653 = AND(g8343, g13850) +g16662 = AND(g4552, g14753) +g16666 = AND(g5200, g14794) +g16667 = AND(g5268, g14659) +g16668 = AND(g5543, g14962) +g16669 = AND(g5611, g14993) +g16670 = AND(g5953, g14999) +g16671 = AND(g6275, g14817) +g16672 = AND(g6295, g15008) +g16673 = AND(g6617, g14822) +g16674 = AND(g6637, g15014) +g16690 = AND(g8399, g13867) +g16699 = AND(g7134, g12933) +g16700 = AND(g5208, g14838) +g16701 = AND(g5547, g14845) +g16702 = AND(g5615, g14691) +g16703 = AND(g5889, g15002) +g16704 = AND(g5957, g15018) +g16705 = AND(g6299, g15024) +g16706 = AND(g6621, g14868) +g16707 = AND(g6641, g15033) +g16729 = AND(g5240, g14720) +g16730 = AND(g5212, g14723) +g16731 = AND(g7153, g12941) +g16732 = AND(g5555, g14882) +g16733 = AND(g5893, g14889) +g16734 = AND(g5961, g14735) +g16735 = AND(g6235, g15027) +g16736 = AND(g6303, g15036) +g16737 = AND(g6645, g15042) +g16751 = AND(g13155, g13065) +g16758 = AND(g5220, g14758) +g16759 = AND(g5587, g14761) +g16760 = AND(g5559, g14764) +g16761 = AND(g7170, g12947) +g16762 = AND(g5901, g14930) +g16763 = AND(g6239, g14937) +g16764 = AND(g6307, g14776) +g16765 = AND(g6581, g15045) +g16766 = AND(g6649, g12915) +g16801 = AND(g5120, g14238) +g16802 = AND(g5567, g14807) +g16803 = AND(g5933, g14810) +g16804 = AND(g5905, g14813) +g16805 = AND(g7187, g12972) +g16806 = AND(g6247, g14971) +g16807 = AND(g6585, g14978) +g16808 = AND(g6653, g14825) +g16840 = AND(g5467, g14262) +g16841 = AND(g5913, g14858) +g16842 = AND(g6279, g14861) +g16843 = AND(g6251, g14864) +g16844 = AND(g7212, g13000) +g16845 = AND(g6593, g15011) +g16846 = AND(g14034, g12591, g11185) +g16855 = AND(g4392, g13107) +g16868 = AND(g5813, g14297) +g16869 = AND(g6259, g14902) +g16870 = AND(g6625, g14905) +g16871 = AND(g6597, g14908) +g16884 = AND(g6159, g14321) +g16885 = AND(g6605, g14950) +g16896 = AND(g262, g13120) +g16929 = AND(g6505, g14348) +g16930 = AND(g239, g13132) +g16957 = AND(g13064, g10418) +g16965 = AND(g269, g13140) +g16986 = AND(g246, g13142) +g17057 = AND(g446, g13173) +g17091 = AND(g8659, g12940) +g17119 = AND(g5272, g14800) +g17123 = AND(g225, g13209) +g17133 = AND(g10683, g13222) +g17134 = AND(g5619, g14851) +g17138 = AND(g255, g13239) +g17139 = AND(g8635, g12967) +g17140 = AND(g8616, g12968) +g17145 = AND(g7469, g13249) +g17146 = AND(g5965, g14895) +g17149 = AND(g232, g13255) +g17150 = AND(g8579, g12995) +g17151 = AND(g8659, g12996) +g17152 = AND(g8635, g12997) +g17153 = AND(g6311, g14943) +g17156 = AND(g305, g13385) +g17176 = AND(g8616, g13008) +g17177 = AND(g6657, g14984) +g17179 = AND(g1041, g13211) +g17181 = AND(g1945, g13014) +g17182 = AND(g8579, g13016) +g17191 = AND(g1384, g13242) +g17192 = AND(g1677, g13022) +g17193 = AND(g2504, g13023) +g17199 = AND(g2236, g13034) +g17292 = AND(g1075, g13093) +g17307 = AND(g9498, g14343) +g17317 = AND(g1079, g13124) +g17321 = AND(g1418, g13105) +g17365 = AND(g7650, g13036) +g17391 = AND(g9556, g14378) +g17401 = AND(g1083, g13143) +g17405 = AND(g1422, g13137) +g17418 = AND(g9618, g14407) +g17424 = AND(g1426, g13176) +g17469 = AND(g4076, g13217) +g17480 = AND(g9683, g14433) +g17506 = AND(g9744, g14505) +g17574 = AND(g9554, g14546) +g17601 = AND(g9616, g14572) +I18568 = AND(g13156, g11450, g11498) +g17613 = AND(g11547, g11592, g11640, I18568) +g17617 = AND(g7885, g13326) +g17636 = AND(g10829, g13463) +g17643 = AND(g9681, g14599) +I18620 = AND(g13156, g11450, g11498) +g17653 = AND(g11547, g11592, g6789, I18620) +g17654 = AND(g962, g13284) +g17655 = AND(g7897, g13342) +g17671 = AND(g7685, g13485) +g17682 = AND(g9742, g14637) +I18671 = AND(g13156, g11450, g6756) +g17690 = AND(g11547, g11592, g11640, I18671) +g17692 = AND(g1124, g13307) +g17693 = AND(g1306, g13291) +g17719 = AND(g9818, g14675) +I18713 = AND(g13156, g6767, g6756) +g17724 = AND(g11547, g11592, g11640, I18713) +I18716 = AND(g13156, g11450, g6756) +g17725 = AND(g11547, g11592, g6789, I18716) +g17726 = AND(g1467, g13315) +I18740 = AND(g13156, g11450, g11498) +g17747 = AND(g6772, g11592, g11640, I18740) +g17752 = AND(g7841, g13174) +g17753 = AND(g13281, g13175) +I18762 = AND(g13156, g6767, g11498) +g17766 = AND(g6772, g11592, g11640, I18762) +I18765 = AND(g13156, g11450, g11498) +g17767 = AND(g6772, g11592, g6789, I18765) +g17768 = AND(g13325, g10741) +g17769 = AND(g1146, g13188) +g17770 = AND(g7863, g13189) +g17771 = AND(g13288, g13190) +I18782 = AND(g13156, g11450, g6756) +g17780 = AND(g6772, g11592, g11640, I18782) +I18785 = AND(g13156, g6767, g11498) +g17781 = AND(g6772, g11592, g6789, I18785) +g17783 = AND(g7851, g13110) +g17784 = AND(g1152, g13215) +g17785 = AND(g13341, g10762) +g17786 = AND(g1489, g13216) +I18803 = AND(g13156, g11450, g6756) +g17793 = AND(g6772, g11592, g6789, I18803) +g17809 = AND(g7873, g13125) +g17810 = AND(g1495, g13246) +I18819 = AND(g13156, g11450, g11498) +g17817 = AND(g11547, g6782, g11640, I18819) +g18103 = AND(g401, g17015) +g18104 = AND(g392, g17015) +g18105 = AND(g417, g17015) +g18106 = AND(g411, g17015) +g18107 = AND(g429, g17015) +g18108 = AND(g433, g17015) +g18109 = AND(g437, g17015) +g18110 = AND(g441, g17015) +g18111 = AND(g174, g17015) +g18112 = AND(g182, g17015) +g18113 = AND(g405, g17015) +g18114 = AND(g452, g17015) +g18115 = AND(g460, g17015) +g18116 = AND(g168, g17015) +g18117 = AND(g464, g17015) +g18118 = AND(g471, g17015) +g18119 = AND(g475, g17015) +g18120 = AND(g457, g17015) +g18121 = AND(g424, g17015) +g18122 = AND(g15052, g17015) +g18123 = AND(g479, g16886) +g18124 = AND(g102, g16886) +g18125 = AND(g15053, g16886) +g18126 = AND(g15054, g16971) +g18127 = AND(g499, g16971) +g18128 = AND(g504, g16971) +g18129 = AND(g518, g16971) +g18130 = AND(g528, g16971) +g18131 = AND(g482, g16971) +g18132 = AND(g513, g16971) +g18133 = AND(g15055, g17249) +g18134 = AND(g534, g17249) +g18135 = AND(g136, g17249) +g18136 = AND(g550, g17249) +g18137 = AND(g538, g17249) +g18138 = AND(g546, g17249) +g18139 = AND(g542, g17249) +g18140 = AND(g559, g17533) +g18141 = AND(g568, g17533) +g18142 = AND(g577, g17533) +g18143 = AND(g586, g17533) +g18144 = AND(g590, g17533) +g18145 = AND(g582, g17533) +g18146 = AND(g595, g17533) +g18147 = AND(g599, g17533) +g18148 = AND(g562, g17533) +g18149 = AND(g608, g17533) +g18150 = AND(g604, g17533) +g18151 = AND(g617, g17533) +g18152 = AND(g613, g17533) +g18153 = AND(g626, g17533) +g18154 = AND(g622, g17533) +g18155 = AND(g15056, g17533) +g18156 = AND(g572, g17533) +g18157 = AND(g15057, g17433) +g18158 = AND(g667, g17433) +g18159 = AND(g671, g17433) +g18160 = AND(g645, g17433) +g18161 = AND(g691, g17433) +g18162 = AND(g686, g17433) +g18163 = AND(g79, g17433) +g18164 = AND(g699, g17433) +g18165 = AND(g650, g17433) +g18166 = AND(g655, g17433) +g18167 = AND(g718, g17433) +g18168 = AND(g681, g17433) +g18169 = AND(g676, g17433) +g18170 = AND(g661, g17433) +g18171 = AND(g728, g17433) +g18172 = AND(g15058, g17328) +g18173 = AND(g736, g17328) +g18174 = AND(g739, g17328) +g18175 = AND(g744, g17328) +g18176 = AND(g732, g17328) +g18177 = AND(g749, g17328) +g18178 = AND(g758, g17328) +g18179 = AND(g763, g17328) +g18180 = AND(g767, g17328) +g18181 = AND(g772, g17328) +g18182 = AND(g776, g17328) +g18183 = AND(g781, g17328) +g18184 = AND(g785, g17328) +g18185 = AND(g790, g17328) +g18186 = AND(g753, g17328) +g18187 = AND(g794, g17328) +g18188 = AND(g807, g17328) +g18189 = AND(g812, g17821) +g18190 = AND(g822, g17821) +g18191 = AND(g827, g17821) +g18192 = AND(g817, g17821) +g18193 = AND(g837, g17821) +g18194 = AND(g843, g17821) +g18195 = AND(g847, g17821) +g18196 = AND(g703, g17821) +g18197 = AND(g854, g17821) +g18198 = AND(g15059, g17821) +g18199 = AND(g832, g17821) +g18201 = AND(g15061, g15938) +g18202 = AND(g907, g15938) +g18203 = AND(g911, g15938) +g18204 = AND(g914, g15938) +g18205 = AND(g904, g15938) +g18206 = AND(g918, g15938) +g18207 = AND(g925, g15938) +g18208 = AND(g930, g15938) +g18209 = AND(g921, g15938) +g18210 = AND(g936, g15938) +g18211 = AND(g15062, g15979) +g18212 = AND(g947, g15979) +g18213 = AND(g952, g15979) +g18214 = AND(g939, g15979) +g18215 = AND(g943, g15979) +g18216 = AND(g967, g15979) +g18217 = AND(g15063, g16100) +g18218 = AND(g1008, g16100) +g18219 = AND(g969, g16100) +g18220 = AND(g1002, g16100) +g18221 = AND(g1018, g16100) +g18222 = AND(g1024, g16100) +g18223 = AND(g1030, g16100) +g18224 = AND(g1036, g16100) +g18225 = AND(g1041, g16100) +g18226 = AND(g15064, g16129) +g18227 = AND(g1052, g16129) +g18228 = AND(g1061, g16129) +g18229 = AND(g1099, g16326) +g18230 = AND(g1111, g16326) +g18231 = AND(g1105, g16326) +g18232 = AND(g1124, g16326) +g18233 = AND(g1094, g16326) +g18234 = AND(g1129, g16326) +g18235 = AND(g1141, g16326) +g18236 = AND(g15065, g16326) +g18237 = AND(g1146, g16326) +g18238 = AND(g1152, g16326) +g18239 = AND(g1135, g16326) +g18240 = AND(g15066, g16431) +g18241 = AND(g1183, g16431) +g18242 = AND(g962, g16431) +g18243 = AND(g1189, g16431) +g18244 = AND(g1171, g16431) +g18245 = AND(g1193, g16431) +g18246 = AND(g1199, g16431) +g18247 = AND(g1178, g16431) +g18248 = AND(g15067, g16897) +g18249 = AND(g1216, g16897) +g18250 = AND(g6821, g16897) +g18251 = AND(g996, g16897) +g18252 = AND(g990, g16897) +g18253 = AND(g1211, g16897) +g18254 = AND(g1236, g16897) +g18255 = AND(g1087, g16897) +g18256 = AND(g1242, g16897) +g18257 = AND(g1205, g16897) +g18258 = AND(g1221, g16897) +g18259 = AND(g15068, g16000) +g18260 = AND(g1252, g16000) +g18261 = AND(g1256, g16000) +g18262 = AND(g1259, g16000) +g18263 = AND(g1249, g16000) +g18264 = AND(g1263, g16000) +g18265 = AND(g1270, g16000) +g18266 = AND(g1274, g16000) +g18267 = AND(g1266, g16000) +g18268 = AND(g1280, g16000) +g18269 = AND(g15069, g16031) +g18270 = AND(g1291, g16031) +g18271 = AND(g1296, g16031) +g18272 = AND(g1283, g16031) +g18273 = AND(g1287, g16031) +g18274 = AND(g1311, g16031) +g18275 = AND(g15070, g16136) +g18276 = AND(g1351, g16136) +g18277 = AND(g1312, g16136) +g18278 = AND(g1345, g16136) +g18279 = AND(g1361, g16136) +g18280 = AND(g1367, g16136) +g18281 = AND(g1373, g16136) +g18282 = AND(g1379, g16136) +g18283 = AND(g1384, g16136) +g18284 = AND(g15071, g16164) +g18285 = AND(g1395, g16164) +g18286 = AND(g1404, g16164) +g18287 = AND(g1442, g16449) +g18288 = AND(g1454, g16449) +g18289 = AND(g1448, g16449) +g18290 = AND(g1467, g16449) +g18291 = AND(g1437, g16449) +g18292 = AND(g1472, g16449) +g18293 = AND(g1484, g16449) +g18294 = AND(g15072, g16449) +g18295 = AND(g1489, g16449) +g18296 = AND(g1495, g16449) +g18297 = AND(g1478, g16449) +g18298 = AND(g15073, g16489) +g18299 = AND(g1526, g16489) +g18300 = AND(g1306, g16489) +g18301 = AND(g1532, g16489) +g18302 = AND(g1514, g16489) +g18303 = AND(g1536, g16489) +g18304 = AND(g1542, g16489) +g18305 = AND(g1521, g16489) +g18306 = AND(g15074, g16931) +g18307 = AND(g1559, g16931) +g18308 = AND(g6832, g16931) +g18309 = AND(g1339, g16931) +g18310 = AND(g1333, g16931) +g18311 = AND(g1554, g16931) +g18312 = AND(g1579, g16931) +g18313 = AND(g1430, g16931) +g18314 = AND(g1585, g16931) +g18315 = AND(g1548, g16931) +g18316 = AND(g1564, g16931) +g18317 = AND(g12846, g17873) +g18318 = AND(g1604, g17873) +g18319 = AND(g1600, g17873) +g18320 = AND(g1616, g17873) +g18321 = AND(g1620, g17873) +g18322 = AND(g1608, g17873) +g18323 = AND(g1632, g17873) +g18324 = AND(g1644, g17873) +g18325 = AND(g1624, g17873) +g18326 = AND(g1664, g17873) +g18327 = AND(g1636, g17873) +g18328 = AND(g1657, g17873) +g18329 = AND(g1612, g17873) +g18330 = AND(g1668, g17873) +g18331 = AND(g1682, g17873) +g18332 = AND(g1677, g17873) +g18333 = AND(g1691, g17873) +g18334 = AND(g1696, g17873) +g18335 = AND(g1687, g17873) +g18336 = AND(g1700, g17873) +g18337 = AND(g1706, g17873) +g18338 = AND(g1710, g17873) +g18339 = AND(g1714, g17873) +g18340 = AND(g1720, g17873) +g18341 = AND(g1648, g17873) +g18342 = AND(g1592, g17873) +g18343 = AND(g12847, g17955) +g18344 = AND(g1740, g17955) +g18345 = AND(g1736, g17955) +g18346 = AND(g1752, g17955) +g18347 = AND(g1756, g17955) +g18348 = AND(g1744, g17955) +g18349 = AND(g1768, g17955) +g18350 = AND(g1779, g17955) +g18351 = AND(g1760, g17955) +g18352 = AND(g1798, g17955) +g18353 = AND(g1772, g17955) +g18354 = AND(g1792, g17955) +g18355 = AND(g1748, g17955) +g18356 = AND(g1802, g17955) +g18357 = AND(g1816, g17955) +g18358 = AND(g1811, g17955) +g18359 = AND(g1825, g17955) +g18360 = AND(g1830, g17955) +g18361 = AND(g1821, g17955) +g18362 = AND(g1834, g17955) +g18363 = AND(g1840, g17955) +g18364 = AND(g1844, g17955) +g18365 = AND(g1848, g17955) +g18366 = AND(g1854, g17955) +g18367 = AND(g1783, g17955) +g18368 = AND(g1728, g17955) +g18369 = AND(g12848, g15171) +g18370 = AND(g1874, g15171) +g18371 = AND(g1870, g15171) +g18372 = AND(g1886, g15171) +g18373 = AND(g1890, g15171) +g18374 = AND(g1878, g15171) +g18375 = AND(g1902, g15171) +g18376 = AND(g1913, g15171) +g18377 = AND(g1894, g15171) +g18378 = AND(g1932, g15171) +g18379 = AND(g1906, g15171) +g18380 = AND(g1926, g15171) +g18381 = AND(g1882, g15171) +g18382 = AND(g1936, g15171) +g18383 = AND(g1950, g15171) +g18384 = AND(g1945, g15171) +g18385 = AND(g1959, g15171) +g18386 = AND(g1964, g15171) +g18387 = AND(g1955, g15171) +g18388 = AND(g1968, g15171) +g18389 = AND(g1974, g15171) +g18390 = AND(g1978, g15171) +g18391 = AND(g1982, g15171) +g18392 = AND(g1988, g15171) +g18393 = AND(g1917, g15171) +g18394 = AND(g1862, g15171) +g18395 = AND(g12849, g15373) +g18396 = AND(g2008, g15373) +g18397 = AND(g2004, g15373) +g18398 = AND(g2020, g15373) +g18399 = AND(g2024, g15373) +g18400 = AND(g2012, g15373) +g18401 = AND(g2036, g15373) +g18402 = AND(g2047, g15373) +g18403 = AND(g2028, g15373) +g18404 = AND(g2066, g15373) +g18405 = AND(g2040, g15373) +g18406 = AND(g2060, g15373) +g18407 = AND(g2016, g15373) +g18408 = AND(g2070, g15373) +g18409 = AND(g2084, g15373) +g18410 = AND(g2079, g15373) +g18411 = AND(g2093, g15373) +g18412 = AND(g2098, g15373) +g18413 = AND(g2089, g15373) +g18414 = AND(g2102, g15373) +g18415 = AND(g2108, g15373) +g18416 = AND(g2112, g15373) +g18417 = AND(g2116, g15373) +g18418 = AND(g2122, g15373) +g18419 = AND(g2051, g15373) +g18420 = AND(g1996, g15373) +g18423 = AND(g12851, g18008) +g18424 = AND(g2165, g18008) +g18425 = AND(g2161, g18008) +g18426 = AND(g2177, g18008) +g18427 = AND(g2181, g18008) +g18428 = AND(g2169, g18008) +g18429 = AND(g2193, g18008) +g18430 = AND(g2204, g18008) +g18431 = AND(g2185, g18008) +g18432 = AND(g2223, g18008) +g18433 = AND(g2197, g18008) +g18434 = AND(g2217, g18008) +g18435 = AND(g2173, g18008) +g18436 = AND(g2227, g18008) +g18437 = AND(g2241, g18008) +g18438 = AND(g2236, g18008) +g18439 = AND(g2250, g18008) +g18440 = AND(g2255, g18008) +g18441 = AND(g2246, g18008) +g18442 = AND(g2259, g18008) +g18443 = AND(g2265, g18008) +g18444 = AND(g2269, g18008) +g18445 = AND(g2273, g18008) +g18446 = AND(g2279, g18008) +g18447 = AND(g2208, g18008) +g18448 = AND(g2153, g18008) +g18449 = AND(g12852, g15224) +g18450 = AND(g2299, g15224) +g18451 = AND(g2295, g15224) +g18452 = AND(g2311, g15224) +g18453 = AND(g2315, g15224) +g18454 = AND(g2303, g15224) +g18455 = AND(g2327, g15224) +g18456 = AND(g2338, g15224) +g18457 = AND(g2319, g15224) +g18458 = AND(g2357, g15224) +g18459 = AND(g2331, g15224) +g18460 = AND(g2351, g15224) +g18461 = AND(g2307, g15224) +g18462 = AND(g2361, g15224) +g18463 = AND(g2375, g15224) +g18464 = AND(g2370, g15224) +g18465 = AND(g2384, g15224) +g18466 = AND(g2389, g15224) +g18467 = AND(g2380, g15224) +g18468 = AND(g2393, g15224) +g18469 = AND(g2399, g15224) +g18470 = AND(g2403, g15224) +g18471 = AND(g2407, g15224) +g18472 = AND(g2413, g15224) +g18473 = AND(g2342, g15224) +g18474 = AND(g2287, g15224) +g18475 = AND(g12853, g15426) +g18476 = AND(g2433, g15426) +g18477 = AND(g2429, g15426) +g18478 = AND(g2445, g15426) +g18479 = AND(g2449, g15426) +g18480 = AND(g2437, g15426) +g18481 = AND(g2461, g15426) +g18482 = AND(g2472, g15426) +g18483 = AND(g2453, g15426) +g18484 = AND(g2491, g15426) +g18485 = AND(g2465, g15426) +g18486 = AND(g2485, g15426) +g18487 = AND(g2441, g15426) +g18488 = AND(g2495, g15426) +g18489 = AND(g2509, g15426) +g18490 = AND(g2504, g15426) +g18491 = AND(g2518, g15426) +g18492 = AND(g2523, g15426) +g18493 = AND(g2514, g15426) +g18494 = AND(g2527, g15426) +g18495 = AND(g2533, g15426) +g18496 = AND(g2537, g15426) +g18497 = AND(g2541, g15426) +g18498 = AND(g2547, g15426) +g18499 = AND(g2476, g15426) +g18500 = AND(g2421, g15426) +g18501 = AND(g12854, g15509) +g18502 = AND(g2567, g15509) +g18503 = AND(g2563, g15509) +g18504 = AND(g2579, g15509) +g18505 = AND(g2583, g15509) +g18506 = AND(g2571, g15509) +g18507 = AND(g2595, g15509) +g18508 = AND(g2606, g15509) +g18509 = AND(g2587, g15509) +g18510 = AND(g2625, g15509) +g18511 = AND(g2599, g15509) +g18512 = AND(g2619, g15509) +g18513 = AND(g2575, g15509) +g18514 = AND(g2629, g15509) +g18515 = AND(g2643, g15509) +g18516 = AND(g2638, g15509) +g18517 = AND(g2652, g15509) +g18518 = AND(g2657, g15509) +g18519 = AND(g2648, g15509) +g18520 = AND(g2661, g15509) +g18521 = AND(g2667, g15509) +g18522 = AND(g2671, g15509) +g18523 = AND(g2675, g15509) +g18524 = AND(g2681, g15509) +g18525 = AND(g2610, g15509) +g18526 = AND(g2555, g15509) +g18529 = AND(g2712, g15277) +g18530 = AND(g2715, g15277) +g18531 = AND(g2719, g15277) +g18532 = AND(g2724, g15277) +g18533 = AND(g2729, g15277) +g18534 = AND(g2735, g15277) +g18535 = AND(g2741, g15277) +g18536 = AND(g2748, g15277) +g18537 = AND(g6856, g15277) +g18538 = AND(g2759, g15277) +g18539 = AND(g2763, g15277) +g18540 = AND(g2775, g15277) +g18541 = AND(g2767, g15277) +g18542 = AND(g2787, g15277) +g18543 = AND(g2779, g15277) +g18544 = AND(g2791, g15277) +g18545 = AND(g2783, g15277) +g18546 = AND(g2795, g15277) +g18547 = AND(g121, g15277) +g18548 = AND(g2807, g15277) +g18549 = AND(g2799, g15277) +g18550 = AND(g2819, g15277) +g18551 = AND(g2811, g15277) +g18552 = AND(g2815, g15277) +g18553 = AND(g2827, g15277) +g18554 = AND(g2831, g15277) +g18555 = AND(g2834, g15277) +g18556 = AND(g2823, g15277) +g18557 = AND(g2771, g15277) +g18558 = AND(g2803, g15277) +g18559 = AND(g12856, g15277) +g18560 = AND(g2837, g15277) +g18561 = AND(g2841, g15277) +g18563 = AND(g2890, g16349) +g18564 = AND(g2844, g16349) +g18565 = AND(g2852, g16349) +g18566 = AND(g2860, g16349) +g18567 = AND(g2894, g16349) +g18568 = AND(g37, g16349) +g18569 = AND(g94, g16349) +g18570 = AND(g2848, g16349) +g18571 = AND(g2856, g16349) +g18572 = AND(g2864, g16349) +g18573 = AND(g2898, g16349) +g18574 = AND(g2882, g16349) +g18575 = AND(g2878, g16349) +g18576 = AND(g2868, g16349) +g18577 = AND(g2988, g16349) +g18578 = AND(g2873, g16349) +g18579 = AND(g2984, g16349) +g18580 = AND(g2907, g16349) +g18581 = AND(g2912, g16349) +g18582 = AND(g2922, g16349) +g18583 = AND(g2936, g16349) +g18584 = AND(g2950, g16349) +g18585 = AND(g2960, g16349) +g18586 = AND(g2886, g16349) +g18587 = AND(g2980, g16349) +g18588 = AND(g2970, g16349) +g18589 = AND(g2902, g16349) +g18590 = AND(g2917, g16349) +g18591 = AND(g2965, g16349) +g18592 = AND(g2994, g16349) +g18593 = AND(g2999, g16349) +g18594 = AND(g12858, g16349) +g18595 = AND(g2927, g16349) +g18596 = AND(g2941, g16349) +g18597 = AND(g2975, g16349) +g18598 = AND(g3003, g16349) +g18599 = AND(g2955, g16349) +g18600 = AND(g3111, g16987) +g18601 = AND(g3106, g16987) +g18602 = AND(g3115, g16987) +g18603 = AND(g3119, g16987) +g18604 = AND(g3125, g16987) +g18605 = AND(g3129, g16987) +g18606 = AND(g3133, g16987) +g18607 = AND(g3139, g16987) +g18608 = AND(g15087, g16987) +g18609 = AND(g3147, g16987) +g18610 = AND(g15088, g17059) +g18611 = AND(g15090, g17200) +g18612 = AND(g3329, g17200) +g18613 = AND(g3338, g17200) +g18614 = AND(g3343, g17200) +g18615 = AND(g3347, g17200) +g18616 = AND(g6875, g17200) +g18617 = AND(g3462, g17062) +g18618 = AND(g3457, g17062) +g18619 = AND(g3466, g17062) +g18620 = AND(g3470, g17062) +g18621 = AND(g3476, g17062) +g18622 = AND(g3480, g17062) +g18623 = AND(g3484, g17062) +g18624 = AND(g3490, g17062) +g18625 = AND(g15092, g17062) +g18626 = AND(g3498, g17062) +g18627 = AND(g15093, g17093) +g18628 = AND(g15095, g17226) +g18629 = AND(g3680, g17226) +g18630 = AND(g3689, g17226) +g18631 = AND(g3694, g17226) +g18632 = AND(g3698, g17226) +g18633 = AND(g6905, g17226) +g18634 = AND(g3813, g17096) +g18635 = AND(g3808, g17096) +g18636 = AND(g3817, g17096) +g18637 = AND(g3821, g17096) +g18638 = AND(g3827, g17096) +g18639 = AND(g3831, g17096) +g18640 = AND(g3835, g17096) +g18641 = AND(g3841, g17096) +g18642 = AND(g15097, g17096) +g18643 = AND(g3849, g17096) +g18644 = AND(g15098, g17125) +g18645 = AND(g15100, g17271) +g18646 = AND(g4031, g17271) +g18647 = AND(g4040, g17271) +g18648 = AND(g4045, g17271) +g18649 = AND(g4049, g17271) +g18650 = AND(g6928, g17271) +g18651 = AND(g15102, g16249) +g18652 = AND(g4172, g16249) +g18653 = AND(g4176, g16249) +g18654 = AND(g4146, g16249) +g18655 = AND(g15106, g14454) +g18656 = AND(g15120, g17128) +g18657 = AND(g4308, g17128) +g18658 = AND(g15121, g17183) +g18659 = AND(g4366, g17183) +g18662 = AND(g15126, g17367) +g18663 = AND(g4311, g17367) +g18664 = AND(g4332, g17367) +g18665 = AND(g4584, g17367) +g18666 = AND(g4593, g17367) +g18667 = AND(g4601, g17367) +g18668 = AND(g4322, g17367) +g18669 = AND(g4608, g17367) +g18670 = AND(g4621, g15758) +g18671 = AND(g4628, g15758) +g18672 = AND(g15127, g15758) +g18673 = AND(g4643, g15758) +g18674 = AND(g4340, g15758) +g18675 = AND(g4349, g15758) +g18676 = AND(g4358, g15758) +g18677 = AND(g4639, g15758) +g18678 = AND(g66, g15758) +g18679 = AND(g4633, g15758) +g18680 = AND(g15128, g15885) +g18681 = AND(g4653, g15885) +g18682 = AND(g4646, g15885) +g18683 = AND(g4674, g15885) +g18684 = AND(g4681, g15885) +g18685 = AND(g4688, g15885) +g18686 = AND(g4659, g15885) +g18687 = AND(g4664, g15885) +g18688 = AND(g4704, g16752) +g18689 = AND(g15129, g16752) +g18690 = AND(g15130, g16053) +g18691 = AND(g4727, g16053) +g18692 = AND(g4732, g16053) +g18693 = AND(g4717, g16053) +g18694 = AND(g4722, g16053) +g18695 = AND(g4737, g16053) +g18696 = AND(g4741, g16053) +g18697 = AND(g4749, g16777) +g18698 = AND(g15131, g16777) +g18699 = AND(g4760, g16816) +g18700 = AND(g15132, g16816) +g18701 = AND(g4771, g16856) +g18702 = AND(g15133, g16856) +g18703 = AND(g4776, g16782) +g18704 = AND(g4793, g16782) +g18705 = AND(g4801, g16782) +g18706 = AND(g4785, g16782) +g18707 = AND(g15134, g16782) +g18708 = AND(g4818, g16782) +g18709 = AND(g59, g17302) +g18710 = AND(g15135, g17302) +g18711 = AND(g15136, g15915) +g18712 = AND(g4843, g15915) +g18713 = AND(g4836, g15915) +g18714 = AND(g4864, g15915) +g18715 = AND(g4871, g15915) +g18716 = AND(g4878, g15915) +g18717 = AND(g4849, g15915) +g18718 = AND(g4854, g15915) +g18719 = AND(g4894, g16795) +g18720 = AND(g15137, g16795) +g18721 = AND(g15138, g16077) +g18722 = AND(g4917, g16077) +g18723 = AND(g4922, g16077) +g18724 = AND(g4907, g16077) +g18725 = AND(g4912, g16077) +g18726 = AND(g4927, g16077) +g18727 = AND(g4931, g16077) +g18728 = AND(g4939, g16821) +g18729 = AND(g15139, g16821) +g18730 = AND(g4950, g16861) +g18731 = AND(g15140, g16861) +g18732 = AND(g4961, g16877) +g18733 = AND(g15141, g16877) +g18734 = AND(g4966, g16826) +g18735 = AND(g4983, g16826) +g18736 = AND(g4991, g16826) +g18737 = AND(g4975, g16826) +g18738 = AND(g15142, g16826) +g18739 = AND(g5008, g16826) +g18740 = AND(g4572, g17384) +g18741 = AND(g15143, g17384) +g18742 = AND(g5120, g17847) +g18743 = AND(g5115, g17847) +g18744 = AND(g5124, g17847) +g18745 = AND(g5128, g17847) +g18746 = AND(g5134, g17847) +g18747 = AND(g5138, g17847) +g18748 = AND(g5142, g17847) +g18749 = AND(g5148, g17847) +g18750 = AND(g15145, g17847) +g18751 = AND(g5156, g17847) +g18752 = AND(g15146, g17926) +g18753 = AND(g15148, g15595) +g18754 = AND(g5339, g15595) +g18755 = AND(g5343, g15595) +g18756 = AND(g5348, g15595) +g18757 = AND(g5352, g15595) +g18758 = AND(g7004, g15595) +g18759 = AND(g5467, g17929) +g18760 = AND(g5462, g17929) +g18761 = AND(g5471, g17929) +g18762 = AND(g5475, g17929) +g18763 = AND(g5481, g17929) +g18764 = AND(g5485, g17929) +g18765 = AND(g5489, g17929) +g18766 = AND(g5495, g17929) +g18767 = AND(g15150, g17929) +g18768 = AND(g5503, g17929) +g18769 = AND(g15151, g18062) +g18770 = AND(g15153, g15615) +g18771 = AND(g5685, g15615) +g18772 = AND(g5689, g15615) +g18773 = AND(g5694, g15615) +g18774 = AND(g5698, g15615) +g18775 = AND(g7028, g15615) +g18776 = AND(g5813, g18065) +g18777 = AND(g5808, g18065) +g18778 = AND(g5817, g18065) +g18779 = AND(g5821, g18065) +g18780 = AND(g5827, g18065) +g18781 = AND(g5831, g18065) +g18782 = AND(g5835, g18065) +g18783 = AND(g5841, g18065) +g18784 = AND(g15155, g18065) +g18785 = AND(g5849, g18065) +g18786 = AND(g15156, g15345) +g18787 = AND(g15158, g15634) +g18788 = AND(g6031, g15634) +g18789 = AND(g6035, g15634) +g18790 = AND(g6040, g15634) +g18791 = AND(g6044, g15634) +g18792 = AND(g7051, g15634) +g18793 = AND(g6159, g15348) +g18794 = AND(g6154, g15348) +g18795 = AND(g6163, g15348) +g18796 = AND(g6167, g15348) +g18797 = AND(g6173, g15348) +g18798 = AND(g6177, g15348) +g18799 = AND(g6181, g15348) +g18800 = AND(g6187, g15348) +g18801 = AND(g15160, g15348) +g18802 = AND(g6195, g15348) +g18803 = AND(g15161, g15480) +g18804 = AND(g15163, g15656) +g18805 = AND(g6377, g15656) +g18806 = AND(g6381, g15656) +g18807 = AND(g6386, g15656) +g18808 = AND(g6390, g15656) +g18809 = AND(g7074, g15656) +g18810 = AND(g6505, g15483) +g18811 = AND(g6500, g15483) +g18812 = AND(g6509, g15483) +g18813 = AND(g6513, g15483) +g18814 = AND(g6519, g15483) +g18815 = AND(g6523, g15483) +g18816 = AND(g6527, g15483) +g18817 = AND(g6533, g15483) +g18818 = AND(g15165, g15483) +g18819 = AND(g6541, g15483) +g18820 = AND(g15166, g15563) +g18821 = AND(g15168, g15680) +g18822 = AND(g6723, g15680) +g18823 = AND(g6727, g15680) +g18824 = AND(g6732, g15680) +g18825 = AND(g6736, g15680) +g18826 = AND(g7097, g15680) +g18890 = AND(g10158, g17625) +g18893 = AND(g16215, g16030) +g18906 = AND(g13568, g16264) +g18909 = AND(g16226, g13570) +g18910 = AND(g16227, g16075) +g18933 = AND(g16237, g13597) +g18934 = AND(g3133, g16096) +g18935 = AND(g4322, g15574) +g18943 = AND(g269, g16099) +g18949 = AND(g10183, g17625) +g18950 = AND(g11193, g16123) +g18951 = AND(g3484, g16124) +g18974 = AND(g174, g16127) +g18981 = AND(g11206, g16158) +g18982 = AND(g3835, g16159) +g18987 = AND(g182, g16162) +g18992 = AND(g8341, g16171) +g18993 = AND(g11224, g16172) +g19062 = AND(g446, g16180) +g19069 = AND(g8397, g16186) +g19139 = AND(g452, g16195) +g19145 = AND(g8450, g16200) +g19206 = AND(g460, g16206) +g19207 = AND(g7803, g15992) +g19266 = AND(g246, g16214) +g19275 = AND(g7823, g16044) +g19333 = AND(g464, g16223) +g19350 = AND(g15968, g13505) +g19354 = AND(g471, g16235) +g19372 = AND(g686, g16289) +g19383 = AND(g16893, g13223) +g19384 = AND(g667, g16310) +g19393 = AND(g691, g16325) +g19461 = AND(g11708, g16846) +g19462 = AND(g7850, g14182, g14177, g16646) +g19487 = AND(g499, g16680) +g19500 = AND(g504, g16712) +g19516 = AND(g7824, g16097) +g19521 = AND(g513, g16739) +g19536 = AND(g518, g16768) +g19540 = AND(g1124, g15904) +g19545 = AND(g3147, g16769) +g19556 = AND(g11932, g16809) +g19560 = AND(g15832, g1157, g10893) +g19564 = AND(g17175, g13976) +g19568 = AND(g1467, g15959) +g19571 = AND(g3498, g16812) +g19578 = AND(g16183, g11130) +g19581 = AND(g15843, g1500, g10918) +g19585 = AND(g17180, g14004) +g19588 = AND(g3849, g16853) +g19594 = AND(g11913, g17268) +g19596 = AND(g1094, g16681) +g19601 = AND(g16198, g11149) +g19610 = AND(g1141, g16069) +g19613 = AND(g1437, g16713) +g19631 = AND(g1484, g16093) +g19637 = AND(g5142, g16958) +g19651 = AND(g1111, g16119) +g19655 = AND(g2729, g16966) +g19656 = AND(g2807, g15844) +g19660 = AND(g12001, g16968) +g19661 = AND(g5489, g16969) +g19671 = AND(g1454, g16155) +g19674 = AND(g2819, g15867) +g19680 = AND(g12028, g17013) +g19681 = AND(g5835, g17014) +g19684 = AND(g2735, g17297) +g19691 = AND(g9614, g17085) +g19692 = AND(g12066, g17086) +g19693 = AND(g6181, g17087) +g19715 = AND(g9679, g17120) +g19716 = AND(g12100, g17121) +g19717 = AND(g6527, g17122) +g19735 = AND(g9740, g17135) +g19736 = AND(g12136, g17136) +g19740 = AND(g2783, g15907) +g19746 = AND(g9816, g17147) +g19749 = AND(g732, g16646) +g19752 = AND(g2771, g15864) +g19756 = AND(g9899, g17154) +g19767 = AND(g16810, g14203) +g19768 = AND(g2803, g15833) +g19784 = AND(g2775, g15877) +g19788 = AND(g9983, g17216) +g19791 = AND(g14253, g17189) +g19855 = AND(g2787, g15962) +g19911 = AND(g14707, g17748) +g19914 = AND(g2815, g15853) +g19948 = AND(g17515, g16320) +g20056 = AND(g16291, g9007, g8954, g8903) +g20069 = AND(g16312, g9051, g9011, g8955) +g20084 = AND(g11591, g16609) +g20093 = AND(g15372, g14584) +g20094 = AND(g8872, g16631) +g20095 = AND(g8873, g16632) +g20108 = AND(g15508, g11048) +g20109 = AND(g17954, g17616) +g20112 = AND(g13540, g16661) +g20131 = AND(g15170, g14309) +g20135 = AND(g16258, g16695) +g20152 = AND(g11545, g16727) +g20162 = AND(g8737, g16750) +g20165 = AND(g5156, g17733) +g20171 = AND(g16479, g10476) +g20174 = AND(g5503, g17754) +g20188 = AND(g5849, g17772) +g20193 = AND(g15578, g17264) +g20203 = AND(g6195, g17789) +g20215 = AND(g16479, g10476) +g20218 = AND(g6541, g17815) +g20375 = AND(g671, g16846) +g20559 = AND(g336, g15831) +g20581 = AND(g10801, g15571) +g20602 = AND(g10803, g15580) +g20628 = AND(g1046, g15789) +g20658 = AND(g1389, g15800) +g20682 = AND(g16238, g4646) +g20739 = AND(g16259, g4674) +g20751 = AND(g16260, g4836) +g20875 = AND(g16281, g4681) +g20887 = AND(g16282, g4864) +g20977 = AND(g10123, g17301) +g21012 = AND(g16304, g4688) +g21024 = AND(g16306, g4871) +g21066 = AND(g10043, g17625) +g21067 = AND(g10085, g17625) +g21163 = AND(g16321, g4878) +g21188 = AND(g7666, g15705) +g21251 = AND(g13969, g17470) +g21276 = AND(g10157, g17625) +g21285 = AND(g7857, g16027) +g21296 = AND(g7879, g16072) +g21298 = AND(g7697, g15825) +g21302 = AND(g956, g15731) +g21303 = AND(g10120, g17625) +g21332 = AND(g996, g15739) +g21333 = AND(g1300, g15740) +g21347 = AND(g1339, g15750) +g21348 = AND(g10121, g17625) +g21361 = AND(g7869, g16066) +g21378 = AND(g7887, g16090) +g21382 = AND(g10086, g17625) +g21394 = AND(g13335, g15799) +g21404 = AND(g16069, g13569) +g21405 = AND(g13377, g15811) +g21419 = AND(g16681, g13595) +g21420 = AND(g16093, g13596) +g21452 = AND(g16119, g13624) +g21453 = AND(g16713, g13625) +g21464 = AND(g16181, g10872) +g21465 = AND(g16155, g13663) +g21512 = AND(g16225, g10881) +g21513 = AND(g16196, g10882) +g21557 = AND(g12980, g15674) +g21558 = AND(g15904, g13729) +g21559 = AND(g16236, g10897) +g21605 = AND(g13005, g15695) +g21606 = AND(g15959, g13763) +g21699 = AND(g142, g20283) +g21700 = AND(g150, g20283) +g21701 = AND(g153, g20283) +g21702 = AND(g157, g20283) +g21703 = AND(g146, g20283) +g21704 = AND(g164, g20283) +g21705 = AND(g209, g20283) +g21706 = AND(g222, g20283) +g21707 = AND(g191, g20283) +g21708 = AND(g15049, g20283) +g21709 = AND(g283, g20283) +g21710 = AND(g287, g20283) +g21711 = AND(g291, g20283) +g21712 = AND(g294, g20283) +g21713 = AND(g298, g20283) +g21714 = AND(g278, g20283) +g21715 = AND(g160, g20283) +g21716 = AND(g301, g20283) +g21717 = AND(g15051, g21037) +g21718 = AND(g370, g21037) +g21719 = AND(g358, g21037) +g21720 = AND(g376, g21037) +g21721 = AND(g385, g21037) +g21728 = AND(g3010, g20330) +g21729 = AND(g3021, g20330) +g21730 = AND(g3025, g20330) +g21731 = AND(g3029, g20330) +g21732 = AND(g3004, g20330) +g21733 = AND(g3034, g20330) +g21734 = AND(g3040, g20330) +g21735 = AND(g3057, g20330) +g21736 = AND(g3065, g20330) +g21737 = AND(g3068, g20330) +g21738 = AND(g3072, g20330) +g21739 = AND(g3080, g20330) +g21740 = AND(g3085, g20330) +g21741 = AND(g15086, g20330) +g21742 = AND(g3050, g20330) +g21743 = AND(g3100, g20330) +g21744 = AND(g3103, g20330) +g21745 = AND(g3017, g20330) +g21746 = AND(g3045, g20330) +g21747 = AND(g3061, g20330) +g21748 = AND(g15089, g20785) +g21749 = AND(g3155, g20785) +g21750 = AND(g3161, g20785) +g21751 = AND(g3167, g20785) +g21752 = AND(g3171, g20785) +g21753 = AND(g3179, g20785) +g21754 = AND(g3195, g20785) +g21755 = AND(g3203, g20785) +g21756 = AND(g3211, g20785) +g21757 = AND(g3187, g20785) +g21758 = AND(g3191, g20785) +g21759 = AND(g3199, g20785) +g21760 = AND(g3207, g20785) +g21761 = AND(g3215, g20785) +g21762 = AND(g3219, g20785) +g21763 = AND(g3223, g20785) +g21764 = AND(g3227, g20785) +g21765 = AND(g3231, g20785) +g21766 = AND(g3235, g20785) +g21767 = AND(g3239, g20785) +g21768 = AND(g3243, g20785) +g21769 = AND(g3247, g20785) +g21770 = AND(g3251, g20785) +g21771 = AND(g3255, g20785) +g21772 = AND(g3259, g20785) +g21773 = AND(g3263, g20785) +g21774 = AND(g3361, g20391) +g21775 = AND(g3372, g20391) +g21776 = AND(g3376, g20391) +g21777 = AND(g3380, g20391) +g21778 = AND(g3355, g20391) +g21779 = AND(g3385, g20391) +g21780 = AND(g3391, g20391) +g21781 = AND(g3408, g20391) +g21782 = AND(g3416, g20391) +g21783 = AND(g3419, g20391) +g21784 = AND(g3423, g20391) +g21785 = AND(g3431, g20391) +g21786 = AND(g3436, g20391) +g21787 = AND(g15091, g20391) +g21788 = AND(g3401, g20391) +g21789 = AND(g3451, g20391) +g21790 = AND(g3454, g20391) +g21791 = AND(g3368, g20391) +g21792 = AND(g3396, g20391) +g21793 = AND(g3412, g20391) +g21794 = AND(g15094, g20924) +g21795 = AND(g3506, g20924) +g21796 = AND(g3512, g20924) +g21797 = AND(g3518, g20924) +g21798 = AND(g3522, g20924) +g21799 = AND(g3530, g20924) +g21800 = AND(g3546, g20924) +g21801 = AND(g3554, g20924) +g21802 = AND(g3562, g20924) +g21803 = AND(g3538, g20924) +g21804 = AND(g3542, g20924) +g21805 = AND(g3550, g20924) +g21806 = AND(g3558, g20924) +g21807 = AND(g3566, g20924) +g21808 = AND(g3570, g20924) +g21809 = AND(g3574, g20924) +g21810 = AND(g3578, g20924) +g21811 = AND(g3582, g20924) +g21812 = AND(g3586, g20924) +g21813 = AND(g3590, g20924) +g21814 = AND(g3594, g20924) +g21815 = AND(g3598, g20924) +g21816 = AND(g3602, g20924) +g21817 = AND(g3606, g20924) +g21818 = AND(g3610, g20924) +g21819 = AND(g3614, g20924) +g21820 = AND(g3712, g20453) +g21821 = AND(g3723, g20453) +g21822 = AND(g3727, g20453) +g21823 = AND(g3731, g20453) +g21824 = AND(g3706, g20453) +g21825 = AND(g3736, g20453) +g21826 = AND(g3742, g20453) +g21827 = AND(g3759, g20453) +g21828 = AND(g3767, g20453) +g21829 = AND(g3770, g20453) +g21830 = AND(g3774, g20453) +g21831 = AND(g3782, g20453) +g21832 = AND(g3787, g20453) +g21833 = AND(g15096, g20453) +g21834 = AND(g3752, g20453) +g21835 = AND(g3802, g20453) +g21836 = AND(g3805, g20453) +g21837 = AND(g3719, g20453) +g21838 = AND(g3747, g20453) +g21839 = AND(g3763, g20453) +g21840 = AND(g15099, g21070) +g21841 = AND(g3857, g21070) +g21842 = AND(g3863, g21070) +g21843 = AND(g3869, g21070) +g21844 = AND(g3873, g21070) +g21845 = AND(g3881, g21070) +g21846 = AND(g3897, g21070) +g21847 = AND(g3905, g21070) +g21848 = AND(g3913, g21070) +g21849 = AND(g3889, g21070) +g21850 = AND(g3893, g21070) +g21851 = AND(g3901, g21070) +g21852 = AND(g3909, g21070) +g21853 = AND(g3917, g21070) +g21854 = AND(g3921, g21070) +g21855 = AND(g3925, g21070) +g21856 = AND(g3929, g21070) +g21857 = AND(g3933, g21070) +g21858 = AND(g3937, g21070) +g21859 = AND(g3941, g21070) +g21860 = AND(g3945, g21070) +g21861 = AND(g3949, g21070) +g21862 = AND(g3953, g21070) +g21863 = AND(g3957, g21070) +g21864 = AND(g3961, g21070) +g21865 = AND(g3965, g21070) +g21866 = AND(g4072, g19801) +g21867 = AND(g4082, g19801) +g21868 = AND(g4076, g19801) +g21869 = AND(g4087, g19801) +g21870 = AND(g4093, g19801) +g21871 = AND(g4108, g19801) +g21872 = AND(g4098, g19801) +g21873 = AND(g6946, g19801) +g21874 = AND(g4112, g19801) +g21875 = AND(g4116, g19801) +g21876 = AND(g4119, g19801) +g21877 = AND(g6888, g19801) +g21878 = AND(g4129, g19801) +g21879 = AND(g4132, g19801) +g21880 = AND(g4135, g19801) +g21881 = AND(g4064, g19801) +g21882 = AND(g4057, g19801) +g21883 = AND(g4141, g19801) +g21884 = AND(g4104, g19801) +g21885 = AND(g4122, g19801) +g21886 = AND(g4153, g19801) +g21887 = AND(g15101, g19801) +g21888 = AND(g4165, g19801) +g21889 = AND(g4169, g19801) +g21890 = AND(g4125, g19801) +g21906 = AND(g5022, g21468) +g21907 = AND(g5033, g21468) +g21908 = AND(g5037, g21468) +g21909 = AND(g5041, g21468) +g21910 = AND(g5016, g21468) +g21911 = AND(g5046, g21468) +g21912 = AND(g5052, g21468) +g21913 = AND(g5069, g21468) +g21914 = AND(g5077, g21468) +g21915 = AND(g5080, g21468) +g21916 = AND(g5084, g21468) +g21917 = AND(g5092, g21468) +g21918 = AND(g5097, g21468) +g21919 = AND(g15144, g21468) +g21920 = AND(g5062, g21468) +g21921 = AND(g5109, g21468) +g21922 = AND(g5112, g21468) +g21923 = AND(g5029, g21468) +g21924 = AND(g5057, g21468) +g21925 = AND(g5073, g21468) +g21926 = AND(g15147, g18997) +g21927 = AND(g5164, g18997) +g21928 = AND(g5170, g18997) +g21929 = AND(g5176, g18997) +g21930 = AND(g5180, g18997) +g21931 = AND(g5188, g18997) +g21932 = AND(g5204, g18997) +g21933 = AND(g5212, g18997) +g21934 = AND(g5220, g18997) +g21935 = AND(g5196, g18997) +g21936 = AND(g5200, g18997) +g21937 = AND(g5208, g18997) +g21938 = AND(g5216, g18997) +g21939 = AND(g5224, g18997) +g21940 = AND(g5228, g18997) +g21941 = AND(g5232, g18997) +g21942 = AND(g5236, g18997) +g21943 = AND(g5240, g18997) +g21944 = AND(g5244, g18997) +g21945 = AND(g5248, g18997) +g21946 = AND(g5252, g18997) +g21947 = AND(g5256, g18997) +g21948 = AND(g5260, g18997) +g21949 = AND(g5264, g18997) +g21950 = AND(g5268, g18997) +g21951 = AND(g5272, g18997) +g21952 = AND(g5366, g21514) +g21953 = AND(g5377, g21514) +g21954 = AND(g5381, g21514) +g21955 = AND(g5385, g21514) +g21956 = AND(g5360, g21514) +g21957 = AND(g5390, g21514) +g21958 = AND(g5396, g21514) +g21959 = AND(g5413, g21514) +g21960 = AND(g5421, g21514) +g21961 = AND(g5424, g21514) +g21962 = AND(g5428, g21514) +g21963 = AND(g5436, g21514) +g21964 = AND(g5441, g21514) +g21965 = AND(g15149, g21514) +g21966 = AND(g5406, g21514) +g21967 = AND(g5456, g21514) +g21968 = AND(g5459, g21514) +g21969 = AND(g5373, g21514) +g21970 = AND(g5401, g21514) +g21971 = AND(g5417, g21514) +g21972 = AND(g15152, g19074) +g21973 = AND(g5511, g19074) +g21974 = AND(g5517, g19074) +g21975 = AND(g5523, g19074) +g21976 = AND(g5527, g19074) +g21977 = AND(g5535, g19074) +g21978 = AND(g5551, g19074) +g21979 = AND(g5559, g19074) +g21980 = AND(g5567, g19074) +g21981 = AND(g5543, g19074) +g21982 = AND(g5547, g19074) +g21983 = AND(g5555, g19074) +g21984 = AND(g5563, g19074) +g21985 = AND(g5571, g19074) +g21986 = AND(g5575, g19074) +g21987 = AND(g5579, g19074) +g21988 = AND(g5583, g19074) +g21989 = AND(g5587, g19074) +g21990 = AND(g5591, g19074) +g21991 = AND(g5595, g19074) +g21992 = AND(g5599, g19074) +g21993 = AND(g5603, g19074) +g21994 = AND(g5607, g19074) +g21995 = AND(g5611, g19074) +g21996 = AND(g5615, g19074) +g21997 = AND(g5619, g19074) +g21998 = AND(g5712, g21562) +g21999 = AND(g5723, g21562) +g22000 = AND(g5727, g21562) +g22001 = AND(g5731, g21562) +g22002 = AND(g5706, g21562) +g22003 = AND(g5736, g21562) +g22004 = AND(g5742, g21562) +g22005 = AND(g5759, g21562) +g22006 = AND(g5767, g21562) +g22007 = AND(g5770, g21562) +g22008 = AND(g5774, g21562) +g22009 = AND(g5782, g21562) +g22010 = AND(g5787, g21562) +g22011 = AND(g15154, g21562) +g22012 = AND(g5752, g21562) +g22013 = AND(g5802, g21562) +g22014 = AND(g5805, g21562) +g22015 = AND(g5719, g21562) +g22016 = AND(g5747, g21562) +g22017 = AND(g5763, g21562) +g22018 = AND(g15157, g19147) +g22019 = AND(g5857, g19147) +g22020 = AND(g5863, g19147) +g22021 = AND(g5869, g19147) +g22022 = AND(g5873, g19147) +g22023 = AND(g5881, g19147) +g22024 = AND(g5897, g19147) +g22025 = AND(g5905, g19147) +g22026 = AND(g5913, g19147) +g22027 = AND(g5889, g19147) +g22028 = AND(g5893, g19147) +g22029 = AND(g5901, g19147) +g22030 = AND(g5909, g19147) +g22031 = AND(g5917, g19147) +g22032 = AND(g5921, g19147) +g22033 = AND(g5925, g19147) +g22034 = AND(g5929, g19147) +g22035 = AND(g5933, g19147) +g22036 = AND(g5937, g19147) +g22037 = AND(g5941, g19147) +g22038 = AND(g5945, g19147) +g22039 = AND(g5949, g19147) +g22040 = AND(g5953, g19147) +g22041 = AND(g5957, g19147) +g22042 = AND(g5961, g19147) +g22043 = AND(g5965, g19147) +g22044 = AND(g6058, g21611) +g22045 = AND(g6069, g21611) +g22046 = AND(g6073, g21611) +g22047 = AND(g6077, g21611) +g22048 = AND(g6052, g21611) +g22049 = AND(g6082, g21611) +g22050 = AND(g6088, g21611) +g22051 = AND(g6105, g21611) +g22052 = AND(g6113, g21611) +g22053 = AND(g6116, g21611) +g22054 = AND(g6120, g21611) +g22055 = AND(g6128, g21611) +g22056 = AND(g6133, g21611) +g22057 = AND(g15159, g21611) +g22058 = AND(g6098, g21611) +g22059 = AND(g6148, g21611) +g22060 = AND(g6151, g21611) +g22061 = AND(g6065, g21611) +g22062 = AND(g6093, g21611) +g22063 = AND(g6109, g21611) +g22064 = AND(g15162, g19210) +g22065 = AND(g6203, g19210) +g22066 = AND(g6209, g19210) +g22067 = AND(g6215, g19210) +g22068 = AND(g6219, g19210) +g22069 = AND(g6227, g19210) +g22070 = AND(g6243, g19210) +g22071 = AND(g6251, g19210) +g22072 = AND(g6259, g19210) +g22073 = AND(g6235, g19210) +g22074 = AND(g6239, g19210) +g22075 = AND(g6247, g19210) +g22076 = AND(g6255, g19210) +g22077 = AND(g6263, g19210) +g22078 = AND(g6267, g19210) +g22079 = AND(g6271, g19210) +g22080 = AND(g6275, g19210) +g22081 = AND(g6279, g19210) +g22082 = AND(g6283, g19210) +g22083 = AND(g6287, g19210) +g22084 = AND(g6291, g19210) +g22085 = AND(g6295, g19210) +g22086 = AND(g6299, g19210) +g22087 = AND(g6303, g19210) +g22088 = AND(g6307, g19210) +g22089 = AND(g6311, g19210) +g22090 = AND(g6404, g18833) +g22091 = AND(g6415, g18833) +g22092 = AND(g6419, g18833) +g22093 = AND(g6423, g18833) +g22094 = AND(g6398, g18833) +g22095 = AND(g6428, g18833) +g22096 = AND(g6434, g18833) +g22097 = AND(g6451, g18833) +g22098 = AND(g6459, g18833) +g22099 = AND(g6462, g18833) +g22100 = AND(g6466, g18833) +g22101 = AND(g6474, g18833) +g22102 = AND(g6479, g18833) +g22103 = AND(g15164, g18833) +g22104 = AND(g6444, g18833) +g22105 = AND(g6494, g18833) +g22106 = AND(g6497, g18833) +g22107 = AND(g6411, g18833) +g22108 = AND(g6439, g18833) +g22109 = AND(g6455, g18833) +g22110 = AND(g15167, g19277) +g22111 = AND(g6549, g19277) +g22112 = AND(g6555, g19277) +g22113 = AND(g6561, g19277) +g22114 = AND(g6565, g19277) +g22115 = AND(g6573, g19277) +g22116 = AND(g6589, g19277) +g22117 = AND(g6597, g19277) +g22118 = AND(g6605, g19277) +g22119 = AND(g6581, g19277) +g22120 = AND(g6585, g19277) +g22121 = AND(g6593, g19277) +g22122 = AND(g6601, g19277) +g22123 = AND(g6609, g19277) +g22124 = AND(g6613, g19277) +g22125 = AND(g6617, g19277) +g22126 = AND(g6621, g19277) +g22127 = AND(g6625, g19277) +g22128 = AND(g6629, g19277) +g22129 = AND(g6633, g19277) +g22130 = AND(g6637, g19277) +g22131 = AND(g6641, g19277) +g22132 = AND(g6645, g19277) +g22133 = AND(g6649, g19277) +g22134 = AND(g6653, g19277) +g22135 = AND(g6657, g19277) +g22142 = AND(g7957, g19140) +g22143 = AND(g19568, g10971) +g22145 = AND(g14555, g18832) +g22149 = AND(g14581, g18880) +g22157 = AND(g14608, g18892) +g22158 = AND(g13698, g19609) +g22160 = AND(g8005, g19795) +g22161 = AND(g13202, g19071) +g22165 = AND(g15594, g18903) +g22172 = AND(g8064, g19857) +g22191 = AND(g8119, g19875) +g22193 = AND(g19880, g20682) +g22208 = AND(g19906, g20739) +g22209 = AND(g19907, g20751) +g22216 = AND(g13660, g20000) +g22218 = AND(g19951, g20875) +g22219 = AND(g19953, g20887) +g22298 = AND(g19997, g21012) +g22299 = AND(g19999, g21024) +g22307 = AND(g20027, g21163) +g22308 = AND(g1135, g19738) +g22309 = AND(g1478, g19751) +g22310 = AND(g19662, g20235) +g22316 = AND(g2837, g20270) +g22329 = AND(g11940, g20329) +g22340 = AND(g19605, g13522) +g22342 = AND(g9354, g9285, g21287) +g22369 = AND(g9354, g7717, g20783) +g22384 = AND(g9354, g9285, g20784) +g22417 = AND(g7753, g9285, g21186) +g22432 = AND(g9354, g7717, g21187) +g22457 = AND(g7753, g7717, g21288) +g22472 = AND(g7753, g9285, g21289) +g22489 = AND(g12954, g19386) +g22498 = AND(g7753, g7717, g21334) +g22515 = AND(g12981, g19395) +g22518 = AND(g12982, g19398) +g22525 = AND(g13006, g19411) +g22534 = AND(g8766, g21389) +g22538 = AND(g14035, g20248) +g22588 = AND(g79, g20078) +g22589 = AND(g19267, g19451) +g22590 = AND(g19274, g19452) +g22622 = AND(g19336, g19469) +g22623 = AND(g19337, g19470) +g22624 = AND(g19344, g19471) +g22632 = AND(g19356, g19476) +g22633 = AND(g19359, g19479) +g22637 = AND(g19363, g19489) +g22665 = AND(g17174, g20905) +g22670 = AND(g20114, g9104) +g22680 = AND(g19530, g7781) +g22685 = AND(g11891, g20192) +g22686 = AND(g19335, g19577) +g22689 = AND(g18918, g9104) +g22710 = AND(g19358, g19600) +g22717 = AND(g9291, g20212) +g22720 = AND(g9253, g20619) +g22752 = AND(g15792, g19612) +g22760 = AND(g9360, g20237) +g22762 = AND(g9305, g20645) +g22831 = AND(g19441, g19629) +g22834 = AND(g102, g19630) +g22835 = AND(g15803, g19633) +g22843 = AND(g9429, g20272) +g22846 = AND(g9386, g20676) +g22848 = AND(g19449, g19649) +g22849 = AND(g1227, g19653) +g22851 = AND(g496, g19654) +g22859 = AND(g9456, g20734) +g22861 = AND(g19792, g19670) +g22862 = AND(g1570, g19673) +g22863 = AND(g9547, g20388) +g22871 = AND(g9523, g20871) +g22873 = AND(g19854, g19683) +g22876 = AND(g20136, g9104) +g22899 = AND(g19486, g19695) +g22900 = AND(g17137, g19697) +g22920 = AND(g19764, g19719) +g22937 = AND(g753, g20540) +g22938 = AND(g19782, g19739) +g22939 = AND(g9708, g21062) +g22942 = AND(g9104, g20219) +g22982 = AND(g19535, g19747) +g22990 = AND(g19555, g19760) +g22991 = AND(g645, g20248) +g22992 = AND(g1227, g19765) +g23006 = AND(g19575, g19776) +g23007 = AND(g681, g20248) +g23008 = AND(g1570, g19783) +g23009 = AND(g20196, g14219) +g23023 = AND(g650, g20248) +g23025 = AND(g16021, g19798) +g23050 = AND(g655, g20248) +g23056 = AND(g16052, g19860) +g23062 = AND(g718, g20248) +g23076 = AND(g19128, g9104) +g23083 = AND(g16076, g19878) +g23103 = AND(g10143, g20765) +g23104 = AND(g661, g20248) +g23121 = AND(g19128, g9104) +g23130 = AND(g728, g20248) +g23131 = AND(g13919, g19930) +g23148 = AND(g19128, g9104) +g23151 = AND(g18994, g7162) +g23165 = AND(g13954, g19964) +g23166 = AND(g13959, g19979) +g23187 = AND(g13989, g20010) +g23188 = AND(g13994, g20025) +g23201 = AND(g14027, g20040) +g23218 = AND(g20200, g16530) +g23220 = AND(g19417, g20067) +g23229 = AND(g18994, g4521) +g23254 = AND(g20056, g20110) +g23265 = AND(g20069, g20132) +g23280 = AND(g19417, g20146) +g23292 = AND(g19879, g16726) +g23293 = AND(g9104, g19200) +g23314 = AND(g9104, g19200) +g23348 = AND(g15570, g21393) +g23349 = AND(g13662, g20182) +g23372 = AND(g16448, g20194) +g23373 = AND(g13699, g20195) +g23381 = AND(g7239, g21413) +g23386 = AND(g20034, g20207) +g23387 = AND(g16506, g20211) +g23389 = AND(g9072, g19757) +g23392 = AND(g7247, g21430) +g23396 = AND(g20051, g20229) +g23397 = AND(g11154, g20239) +g23401 = AND(g7262, g21460) +g23404 = AND(g20063, g20247) +g23407 = AND(g9295, g20273) +g23412 = AND(g7297, g21510) +g23415 = AND(g20077, g20320) +g23416 = AND(g20082, g20321) +g23424 = AND(g7345, g21556) +g23436 = AND(g676, g20375) +g23439 = AND(g13771, g20452) +g23451 = AND(g13805, g20510) +g23471 = AND(g20148, g20523) +g23474 = AND(g13830, g20533) +g23475 = AND(g19070, g8971) +g23484 = AND(g20160, g20541) +g23497 = AND(g20169, g20569) +g23498 = AND(g20234, g12998) +g23513 = AND(g19430, g13007) +g23514 = AND(g20149, g11829) +g23531 = AND(g10760, g18930) +g23532 = AND(g19400, g11852) +g23533 = AND(g19436, g13015) +g23540 = AND(g16866, g20622) +g23551 = AND(g10793, g18948) +g23553 = AND(g19413, g11875) +g23554 = AND(g20390, g13024) +g23564 = AND(g16882, g20648) +g23572 = AND(g20230, g20656) +g23577 = AND(g19444, g13033) +g23581 = AND(g20183, g11900) +g23599 = AND(g19050, g9104) +g23606 = AND(g16927, g20679) +g23618 = AND(g19388, g11917) +g23619 = AND(g19453, g13045) +g23639 = AND(g19050, g9104) +g23646 = AND(g16959, g20737) +g23657 = AND(g19401, g11941) +g23658 = AND(g14687, g20852) +g23675 = AND(g19050, g9104) +g23682 = AND(g16970, g20874) +g23690 = AND(g14726, g20978) +g23691 = AND(g14731, g20993) +g23708 = AND(g19050, g9104) +g23724 = AND(g14767, g21123) +g23725 = AND(g14772, g21138) +g23742 = AND(g19128, g9104) +g23754 = AND(g14816, g21189) +g23755 = AND(g14821, g21204) +g23774 = AND(g14867, g21252) +g23775 = AND(g14872, g21267) +g23779 = AND(g1105, g19355) +g23799 = AND(g14911, g21279) +g23801 = AND(g1448, g19362) +g23802 = AND(g9104, g19050) +g23811 = AND(g4087, g19364) +g23828 = AND(g9104, g19128) +g23836 = AND(g4129, g19495) +g23837 = AND(g21160, g10804) +g23854 = AND(g4093, g19506) +g23855 = AND(g4112, g19455) +g23856 = AND(g4116, g19483) +g23857 = AND(g19626, g7908) +g23872 = AND(g19389, g4157) +g23873 = AND(g21222, g10815) +g23884 = AND(g4119, g19510) +g23885 = AND(g4132, g19513) +g23900 = AND(g1129, g19408) +g23901 = AND(g19606, g7963) +g23917 = AND(g1472, g19428) +g23919 = AND(g4122, g19546) +g23920 = AND(g4135, g19549) +g23921 = AND(g19379, g4146) +g23957 = AND(g4138, g19589) +g23958 = AND(g9104, g19200) +g23990 = AND(g19610, g10951) +g23991 = AND(g19209, g21428) +g23996 = AND(g19596, g10951) +g23998 = AND(g19631, g10971) +g24001 = AND(g19651, g10951) +g24002 = AND(g19613, g10971) +g24004 = AND(g37, g21225) +g24008 = AND(g7909, g19502) +g24009 = AND(g19671, g10971) +g24011 = AND(g7939, g19524) +g24012 = AND(g14496, g21561) +g24014 = AND(g7933, g19063) +g24015 = AND(g19540, g10951) +g24016 = AND(g14528, g21610) +g24139 = AND(g17619, g21653) +g24140 = AND(g17663, g21654) +g24141 = AND(g17657, g21656) +g24142 = AND(g17700, g21657) +g24143 = AND(g17694, g21659) +g24144 = AND(g17727, g21660) +g24186 = AND(g18102, g22722) +g24187 = AND(g305, g22722) +g24188 = AND(g316, g22722) +g24189 = AND(g324, g22722) +g24190 = AND(g329, g22722) +g24191 = AND(g319, g22722) +g24192 = AND(g311, g22722) +g24193 = AND(g336, g22722) +g24194 = AND(g106, g22722) +g24195 = AND(g74, g22722) +g24196 = AND(g333, g22722) +g24197 = AND(g347, g22722) +g24198 = AND(g351, g22722) +g24199 = AND(g355, g22722) +g24217 = AND(g18200, g22594) +g24218 = AND(g872, g22594) +g24219 = AND(g225, g22594) +g24220 = AND(g255, g22594) +g24221 = AND(g232, g22594) +g24222 = AND(g262, g22594) +g24223 = AND(g239, g22594) +g24224 = AND(g269, g22594) +g24225 = AND(g246, g22594) +g24226 = AND(g446, g22594) +g24227 = AND(g890, g22594) +g24228 = AND(g862, g22594) +g24229 = AND(g896, g22594) +g24230 = AND(g901, g22594) +g24283 = AND(g4411, g22550) +g24284 = AND(g4375, g22550) +g24285 = AND(g4388, g22550) +g24286 = AND(g4405, g22550) +g24287 = AND(g4401, g22550) +g24288 = AND(g4417, g22550) +g24289 = AND(g4427, g22550) +g24290 = AND(g4430, g22550) +g24291 = AND(g18660, g22550) +g24292 = AND(g4443, g22550) +g24293 = AND(g4438, g22550) +g24294 = AND(g4452, g22550) +g24295 = AND(g4434, g22550) +g24296 = AND(g4382, g22550) +g24297 = AND(g4455, g22550) +g24298 = AND(g4392, g22550) +g24299 = AND(g4456, g22550) +g24300 = AND(g15123, g22228) +g24301 = AND(g6961, g22228) +g24302 = AND(g15124, g22228) +g24303 = AND(g4369, g22228) +g24304 = AND(g12875, g22228) +g24305 = AND(g4477, g22228) +g24306 = AND(g4483, g22228) +g24307 = AND(g4486, g22228) +g24308 = AND(g4489, g22228) +g24309 = AND(g4480, g22228) +g24310 = AND(g4495, g22228) +g24311 = AND(g4498, g22228) +g24312 = AND(g4501, g22228) +g24313 = AND(g4504, g22228) +g24314 = AND(g4515, g22228) +g24315 = AND(g4521, g22228) +g24316 = AND(g4527, g22228) +g24317 = AND(g4534, g22228) +g24318 = AND(g4555, g22228) +g24319 = AND(g4561, g22228) +g24320 = AND(g6973, g22228) +g24321 = AND(g4558, g22228) +g24322 = AND(g4423, g22228) +g24323 = AND(g4546, g22228) +g24324 = AND(g4540, g22228) +g24325 = AND(g4543, g22228) +g24326 = AND(g4552, g22228) +g24327 = AND(g4549, g22228) +g24328 = AND(g4567, g22228) +g24329 = AND(g4462, g22228) +g24330 = AND(g18661, g22228) +g24331 = AND(g6977, g22228) +g24332 = AND(g4459, g22228) +g24333 = AND(g4512, g22228) +g24378 = AND(g3106, g22718) +g24387 = AND(g3457, g22761) +g24392 = AND(g3115, g23067) +g24393 = AND(g3808, g22844) +g24395 = AND(g4704, g22845) +g24399 = AND(g3133, g23067) +g24400 = AND(g3466, g23112) +g24402 = AND(g4749, g22857) +g24403 = AND(g4894, g22858) +g24406 = AND(g13623, g22860) +g24408 = AND(g23989, g18946) +g24409 = AND(g3484, g23112) +g24410 = AND(g3817, g23139) +g24411 = AND(g4584, g22161) +g24415 = AND(g4760, g22869) +g24416 = AND(g4939, g22870) +g24420 = AND(g23997, g18980) +g24421 = AND(g3835, g23139) +g24422 = AND(g4771, g22896) +g24423 = AND(g4950, g22897) +g24427 = AND(g4961, g22919) +g24436 = AND(g3125, g23067) +g24450 = AND(g3129, g23067) +g24451 = AND(g3476, g23112) +g24464 = AND(g3480, g23112) +g24465 = AND(g3827, g23139) +g24467 = AND(g13761, g23047) +g24475 = AND(g3831, g23139) +g24476 = AND(g18879, g22330) +g24482 = AND(g6875, g23055) +g24484 = AND(g16288, g23208) +g24485 = AND(g10710, g22319) +g24488 = AND(g6905, g23082) +g24491 = AND(g10727, g22332) +g24495 = AND(g6928, g23127) +g24498 = AND(g14036, g23850) +g24499 = AND(g22217, g19394) +g24501 = AND(g14000, g23182) +g24502 = AND(g23428, g13223) +g24503 = AND(g22225, g19409) +g24504 = AND(g22226, g19410) +g24507 = AND(g22304, g19429) +g24523 = AND(g22318, g19468) +g24532 = AND(g22331, g19478) +g24536 = AND(g19516, g22635) +g24537 = AND(g22626, g10851) +g24541 = AND(g22626, g10851) +g24545 = AND(g3333, g23285) +g24546 = AND(g22447, g19523) +g24549 = AND(g23162, g20887) +g24550 = AND(g3684, g23308) +g24551 = AND(g17148, g23331) +g24552 = AND(g22487, g19538) +g24553 = AND(g22983, g19539) +g24554 = AND(g22490, g19541) +g24555 = AND(g23184, g21024) +g24556 = AND(g4035, g23341) +g24558 = AND(g22516, g19566) +g24559 = AND(g22993, g19567) +g24564 = AND(g23198, g21163) +g24569 = AND(g5115, g23382) +g24572 = AND(g5462, g23393) +g24573 = AND(g17198, g23716) +g24581 = AND(g5124, g23590) +g24582 = AND(g5808, g23402) +g24588 = AND(g5142, g23590) +g24589 = AND(g5471, g23630) +g24590 = AND(g6154, g23413) +g24600 = AND(g22591, g19652) +g24602 = AND(g16507, g22854) +g24606 = AND(g5489, g23630) +g24607 = AND(g5817, g23666) +g24608 = AND(g6500, g23425) +g24618 = AND(g22625, g19672) +g24622 = AND(g19856, g22866) +g24624 = AND(g16524, g22867) +g24627 = AND(g22763, g19679) +g24628 = AND(g5835, g23666) +g24629 = AND(g6163, g23699) +g24630 = AND(g23255, g14149) +g24634 = AND(g22634, g19685) +g24635 = AND(g19874, g22883) +g24637 = AND(g16586, g22884) +g24638 = AND(g22763, g19690) +g24639 = AND(g6181, g23699) +g24640 = AND(g6509, g23733) +g24642 = AND(g8290, g22898) +g24643 = AND(g22636, g19696) +g24644 = AND(g11714, g22903) +g24645 = AND(g22639, g19709) +g24646 = AND(g22640, g19711) +g24647 = AND(g19903, g22907) +g24649 = AND(g6527, g23733) +g24650 = AND(g22641, g19718) +g24651 = AND(g2741, g23472) +g24654 = AND(g11735, g22922) +g24656 = AND(g11736, g22926) +g24657 = AND(g22644, g19730) +g24658 = AND(g22645, g19732) +g24659 = AND(g5134, g23590) +g24660 = AND(g22648, g19737) +g24663 = AND(g16621, g22974) +g24664 = AND(g22652, g19741) +g24666 = AND(g11753, g22975) +g24668 = AND(g11754, g22979) +g24669 = AND(g22653, g19742) +g24670 = AND(g5138, g23590) +g24671 = AND(g5481, g23630) +g24672 = AND(g19534, g22981) +g24673 = AND(g22659, g19748) +g24674 = AND(g446, g23496) +g24675 = AND(g17568, g22342) +g24676 = AND(g2748, g23782) +g24679 = AND(g13289, g22985) +g24680 = AND(g16422, g22986) +g24681 = AND(g16653, g22988) +g24682 = AND(g22662, g19754) +g24684 = AND(g11769, g22989) +g24686 = AND(g5485, g23630) +g24687 = AND(g5827, g23666) +g24688 = AND(g22681, g22663) +g24698 = AND(g22664, g19761) +g24700 = AND(g645, g23512) +g24702 = AND(g17464, g22342) +g24703 = AND(g17592, g22369) +g24704 = AND(g17593, g22384) +g24706 = AND(g15910, g22996) +g24707 = AND(g13295, g22997) +g24708 = AND(g16474, g22998) +g24709 = AND(g16690, g23000) +g24710 = AND(g22679, g19771) +g24712 = AND(g19592, g23001) +g24713 = AND(g5831, g23666) +g24714 = AND(g6173, g23699) +g24716 = AND(g15935, g23004) +g24717 = AND(g22684, g19777) +g24719 = AND(g681, g23530) +g24721 = AND(g17488, g22369) +g24722 = AND(g17618, g22417) +g24723 = AND(g17490, g22384) +g24724 = AND(g17624, g22432) +g24725 = AND(g19587, g23012) +g24726 = AND(g15965, g23015) +g24727 = AND(g13300, g23016) +g24728 = AND(g16513, g23017) +g24729 = AND(g22719, g23018) +g24730 = AND(g6177, g23699) +g24731 = AND(g6519, g23733) +g24743 = AND(g22708, g19789) +g24745 = AND(g650, g23550) +g24747 = AND(g17510, g22417) +g24748 = AND(g17656, g22457) +g24749 = AND(g17511, g22432) +g24750 = AND(g17662, g22472) +g24754 = AND(g19604, g23027) +g24755 = AND(g16022, g23030) +g24757 = AND(g7004, g23563) +g24758 = AND(g6523, g23733) +g24761 = AND(g22751, g19852) +g24762 = AND(g655, g23573) +g24763 = AND(g17569, g22457) +g24764 = AND(g17570, g22472) +g24765 = AND(g17699, g22498) +g24769 = AND(g19619, g23058) +g24771 = AND(g7028, g23605) +g24772 = AND(g16287, g23061) +g24773 = AND(g22832, g19872) +g24774 = AND(g718, g23614) +g24775 = AND(g17594, g22498) +g24777 = AND(g11345, g23066) +g24785 = AND(g7051, g23645) +g24786 = AND(g661, g23654) +g24788 = AND(g11384, g23111) +g24790 = AND(g7074, g23681) +g24794 = AND(g11414, g23138) +g24796 = AND(g7097, g23714) +g24797 = AND(g22872, g19960) +g24803 = AND(g22901, g20005) +g24812 = AND(g19662, g22192) +g24817 = AND(g22929, g7235) +g24820 = AND(g13944, g23978) +I24003 = AND(g8097, g8334, g3045) +g24822 = AND(g3010, g23534, I24003) +g24835 = AND(g8720, g23233) +I24015 = AND(g8334, g7975, g3045) +g24843 = AND(g3010, g23211, I24015) +I24018 = AND(g8155, g8390, g3396) +g24846 = AND(g3361, g23555, I24018) +g24849 = AND(g4165, g22227) +I24027 = AND(g3029, g3034, g8426) +g24855 = AND(g3050, g23534, I24027) +I24030 = AND(g8390, g8016, g3396) +g24858 = AND(g3361, g23223, I24030) +I24033 = AND(g8219, g8443, g3747) +g24861 = AND(g3712, g23582, I24033) +g24864 = AND(g11201, g22305) +g24865 = AND(g11323, g23253) +g24872 = AND(g23088, g9104) +I24048 = AND(g3034, g3040, g8426) +g24881 = AND(g3050, g23211, I24048) +I24051 = AND(g3380, g3385, g8492) +g24884 = AND(g3401, g23555, I24051) +I24054 = AND(g8443, g8075, g3747) +g24887 = AND(g3712, g23239, I24054) +g24892 = AND(g11559, g23264) +I24064 = AND(g3385, g3391, g8492) +g24897 = AND(g3401, g23223, I24064) +I24067 = AND(g3731, g3736, g8553) +g24900 = AND(g3752, g23582, I24067) +g24903 = AND(g128, g23889) +g24904 = AND(g11761, g23279) +I24075 = AND(g3736, g3742, g8553) +g24908 = AND(g3752, g23239, I24075) +g24912 = AND(g23687, g20682) +g24913 = AND(g4821, g23908) +g24914 = AND(g8721, g23301) +g24915 = AND(g23087, g20158) +g24921 = AND(g23721, g20739) +g24922 = AND(g4831, g23931) +g24923 = AND(g23129, g20167) +g24929 = AND(g23751, g20875) +g24930 = AND(g4826, g23948) +g24931 = AND(g23153, g20178) +g24939 = AND(g23771, g21012) +g24940 = AND(g5011, g23971) +g24941 = AND(g23171, g20190) +g24945 = AND(g23183, g20197) +g24949 = AND(g23796, g20751) +g24961 = AND(g23193, g20209) +g24962 = AND(g23194, g20210) +g24967 = AND(g23197, g20213) +g24977 = AND(g23209, g20232) +g24983 = AND(g23217, g20238) +g24984 = AND(g22929, g12818) +g24997 = AND(g22929, g10419) +g24998 = AND(g17412, g23408) +g25012 = AND(g20644, g23419) +g25014 = AND(g17474, g23420) +g25026 = AND(g22929, g10503) +g25030 = AND(g23251, g20432) +g25031 = AND(g20675, g23432) +g25033 = AND(g17500, g23433) +g25040 = AND(g12738, g23443) +g25041 = AND(g23261, g20494) +g25042 = AND(g23262, g20496) +g25043 = AND(g20733, g23447) +g25045 = AND(g17525, g23448) +g25050 = AND(g13056, g22312) +g25054 = AND(g12778, g23452) +g25056 = AND(g12779, g23456) +g25057 = AND(g23275, g20511) +g25058 = AND(g23276, g20513) +g25059 = AND(g20870, g23460) +g25061 = AND(g17586, g23461) +g25063 = AND(g13078, g22325) +g25067 = AND(g4722, g22885) +g25068 = AND(g17574, g23477) +g25069 = AND(g23296, g20535) +g25071 = AND(g12804, g23478) +g25076 = AND(g12805, g23479) +g25077 = AND(g23297, g20536) +g25078 = AND(g23298, g20538) +g25079 = AND(g21011, g23483) +g25084 = AND(g4737, g22885) +g25085 = AND(g4912, g22908) +g25086 = AND(g13941, g23488) +g25087 = AND(g17307, g23489) +g25088 = AND(g17601, g23491) +g25089 = AND(g23317, g20553) +g25091 = AND(g12830, g23492) +g25093 = AND(g12831, g23493) +g25094 = AND(g23318, g20554) +g25095 = AND(g23319, g20556) +g25096 = AND(g23778, g20560) +g25102 = AND(g4727, g22885) +g25103 = AND(g4927, g22908) +g25104 = AND(g16800, g23504) +g25105 = AND(g13973, g23505) +g25106 = AND(g17391, g23506) +g25107 = AND(g17643, g23508) +g25108 = AND(g23345, g20576) +g25110 = AND(g10427, g23509) +g25112 = AND(g10428, g23510) +g25113 = AND(g23346, g20577) +g25122 = AND(g23374, g20592) +g25123 = AND(g4732, g22885) +g25124 = AND(g4917, g22908) +g25125 = AND(g20187, g23520) +g25126 = AND(g16839, g23523) +g25127 = AND(g13997, g23524) +g25128 = AND(g17418, g23525) +g25129 = AND(g17682, g23527) +g25130 = AND(g23358, g20600) +g25132 = AND(g10497, g23528) +g25142 = AND(g4717, g22885) +g25143 = AND(g4922, g22908) +g25147 = AND(g20202, g23542) +g25148 = AND(g16867, g23545) +g25149 = AND(g14030, g23546) +g25150 = AND(g17480, g23547) +g25151 = AND(g17719, g23549) +g25152 = AND(g23383, g20626) +g25159 = AND(g4907, g22908) +g25163 = AND(g20217, g23566) +g25164 = AND(g16883, g23569) +g25165 = AND(g14062, g23570) +g25166 = AND(g17506, g23571) +g25173 = AND(g12234, g23589) +g25178 = AND(g20241, g23608) +g25179 = AND(g16928, g23611) +g25181 = AND(g23405, g20696) +g25187 = AND(g12296, g23629) +g25192 = AND(g20276, g23648) +g25201 = AND(g12346, g23665) +g25207 = AND(g22513, g10621) +g25217 = AND(g12418, g23698) +g25223 = AND(g22523, g10652) +g25229 = AND(g7636, g22654) +g25238 = AND(g12466, g23732) +g25285 = AND(g22152, g13061) +I24482 = AND(g9364, g9607, g5057) +g25290 = AND(g5022, g22173, I24482) +g25323 = AND(g6888, g22359) +I24505 = AND(g9607, g9229, g5057) +g25328 = AND(g5022, g23764, I24505) +I24508 = AND(g9434, g9672, g5401) +g25331 = AND(g5366, g22194, I24508) +g25357 = AND(g23810, g23786) +g25366 = AND(g7733, g22406) +g25367 = AND(g6946, g22407) +g25368 = AND(g6946, g22408) +I24524 = AND(g5041, g5046, g9716) +g25371 = AND(g5062, g22173, I24524) +I24527 = AND(g9672, g9264, g5401) +g25374 = AND(g5366, g23789, I24527) +I24530 = AND(g9501, g9733, g5747) +g25377 = AND(g5712, g22210, I24530) +g25408 = AND(g22682, g9772) +I24546 = AND(g5046, g5052, g9716) +g25411 = AND(g5062, g23764, I24546) +I24549 = AND(g5385, g5390, g9792) +g25414 = AND(g5406, g22194, I24549) +I24552 = AND(g9733, g9316, g5747) +g25417 = AND(g5712, g23816, I24552) +I24555 = AND(g9559, g9809, g6093) +g25420 = AND(g6058, g22220, I24555) +g25448 = AND(g11202, g22680) +g25449 = AND(g6946, g22496) +g25450 = AND(g6888, g22497) +I24576 = AND(g5390, g5396, g9792) +g25453 = AND(g5406, g23789, I24576) +I24579 = AND(g5731, g5736, g9875) +g25456 = AND(g5752, g22210, I24579) +I24582 = AND(g9809, g9397, g6093) +g25459 = AND(g6058, g23844, I24582) +I24585 = AND(g9621, g9892, g6439) +g25462 = AND(g6404, g22300, I24585) +g25466 = AND(g23574, g21346) +g25479 = AND(g22646, g9917) +I24597 = AND(g5736, g5742, g9875) +g25482 = AND(g5752, g23816, I24597) +I24600 = AND(g6077, g6082, g9946) +g25485 = AND(g6098, g22220, I24600) +I24603 = AND(g9892, g9467, g6439) +g25488 = AND(g6404, g23865, I24603) +g25491 = AND(g23615, g21355) +g25502 = AND(g6946, g22527) +g25503 = AND(g6888, g22529) +I24616 = AND(g6082, g6088, g9946) +g25507 = AND(g6098, g23844, I24616) +I24619 = AND(g6423, g6428, g10014) +g25510 = AND(g6444, g22300, I24619) +I24625 = AND(g6428, g6434, g10014) +g25518 = AND(g6444, g23865, I24625) +g25522 = AND(g6888, g22544) +g25526 = AND(g23720, g21400) +g25530 = AND(g23750, g21414) +g25536 = AND(g23770, g21431) +g25543 = AND(g23795, g21461) +g25551 = AND(g23822, g21511) +g25559 = AND(g13004, g22649) +g25565 = AND(g13013, g22660) +I24674 = AND(g19919, g24019, g24020, g24021) +I24675 = AND(g24022, g24023, g24024, g24025) +g25567 = AND(I24674, I24675) +I24679 = AND(g19968, g24026, g24027, g24028) +I24680 = AND(g24029, g24030, g24031, g24032) +g25568 = AND(I24679, I24680) +I24684 = AND(g20014, g24033, g24034, g24035) +I24685 = AND(g24036, g24037, g24038, g24039) +g25569 = AND(I24684, I24685) +I24689 = AND(g20841, g24040, g24041, g24042) +I24690 = AND(g24043, g24044, g24045, g24046) +g25570 = AND(I24689, I24690) +I24694 = AND(g20982, g24047, g24048, g24049) +I24695 = AND(g24050, g24051, g24052, g24053) +g25571 = AND(I24694, I24695) +I24699 = AND(g21127, g24054, g24055, g24056) +I24700 = AND(g24057, g24058, g24059, g24060) +g25572 = AND(I24699, I24700) +I24704 = AND(g21193, g24061, g24062, g24063) +I24705 = AND(g24064, g24065, g24066, g24067) +g25573 = AND(I24704, I24705) +I24709 = AND(g21256, g24068, g24069, g24070) +I24710 = AND(g24071, g24072, g24073, g24074) +g25574 = AND(I24709, I24710) +g25578 = AND(g19402, g24146) +g25579 = AND(g19422, g24147) +g25580 = AND(g19268, g24149) +g25581 = AND(g19338, g24150) +g25765 = AND(g24989, g24973) +g25768 = AND(g2912, g24560) +g25772 = AND(g24944, g24934) +g25775 = AND(g2922, g24568) +g25780 = AND(g25532, g25527) +g25782 = AND(g2936, g24571) +g25787 = AND(g24792, g20887) +g25788 = AND(g8010, g24579) +g25801 = AND(g8097, g24585) +g25802 = AND(g8106, g24586) +g25803 = AND(g24798, g21024) +g25804 = AND(g8069, g24587) +g25814 = AND(g24760, g13323) +g25815 = AND(g8155, g24603) +g25816 = AND(g8164, g24604) +g25817 = AND(g24807, g21163) +g25818 = AND(g8124, g24605) +g25831 = AND(g3151, g24623) +g25832 = AND(g8219, g24625) +g25833 = AND(g8228, g24626) +g25848 = AND(g25539, g18977) +g25850 = AND(g3502, g24636) +g25852 = AND(g4593, g24411) +g25865 = AND(g25545, g18991) +g25866 = AND(g3853, g24648) +g25870 = AND(g24840, g16182) +g25871 = AND(g8334, g24804) +g25872 = AND(g3119, g24655) +g25873 = AND(g24854, g16197) +g25874 = AND(g11118, g24665) +g25875 = AND(g8390, g24809) +g25876 = AND(g3470, g24667) +g25879 = AND(g11135, g24683) +g25880 = AND(g8443, g24814) +g25881 = AND(g3821, g24685) +g25883 = AND(g13728, g24699) +g25884 = AND(g11153, g24711) +g25900 = AND(g24390, g19368) +g25901 = AND(g24853, g16290) +g25902 = AND(g24398, g19373) +g25904 = AND(g14001, g24791) +g25905 = AND(g24879, g16311) +g25907 = AND(g24799, g22519) +g25908 = AND(g24782, g22520) +g25909 = AND(g8745, g24875) +g25915 = AND(g24926, g9602) +g25916 = AND(g24432, g19434) +g25921 = AND(g24936, g9664) +g25922 = AND(g24959, g20065) +g25923 = AND(g24443, g19443) +g25924 = AND(g24976, g16846) +g25925 = AND(g24990, g23234) +g25926 = AND(g25005, g24839) +g25927 = AND(g25004, g20375) +g25928 = AND(g25022, g23436) +g25931 = AND(g24574, g19477) +g25938 = AND(g8997, g24953) +g25939 = AND(g24583, g19490) +g25946 = AND(g24496, g19537) +g25949 = AND(g24701, g19559) +g25951 = AND(g24500, g19565) +g25955 = AND(g24720, g19580) +g25957 = AND(g17190, g24960) +g25959 = AND(g1648, g24963) +g25961 = AND(g25199, g20682) +g25962 = AND(g9258, g24971) +g25963 = AND(g1657, g24978) +g25964 = AND(g1783, g24979) +g25965 = AND(g2208, g24980) +g25966 = AND(g9364, g24985) +g25967 = AND(g9373, g24986) +g25968 = AND(g25215, g20739) +g25969 = AND(g9310, g24987) +g25970 = AND(g1792, g24991) +g25971 = AND(g1917, g24992) +g25972 = AND(g2217, g24993) +g25973 = AND(g2342, g24994) +g25975 = AND(g9434, g24999) +g25976 = AND(g9443, g25000) +g25977 = AND(g25236, g20875) +g25978 = AND(g9391, g25001) +g25979 = AND(g24517, g19650) +g25980 = AND(g1926, g25006) +g25981 = AND(g2051, g25007) +g25982 = AND(g2351, g25008) +g25983 = AND(g2476, g25009) +g25986 = AND(g5160, g25013) +g25987 = AND(g9501, g25015) +g25988 = AND(g9510, g25016) +g25989 = AND(g25258, g21012) +g25990 = AND(g9461, g25017) +g25991 = AND(g2060, g25023) +g25992 = AND(g2485, g25024) +g25993 = AND(g2610, g25025) +g26019 = AND(g5507, g25032) +g26020 = AND(g9559, g25034) +g26021 = AND(g9568, g25035) +g26022 = AND(g25271, g20751) +g26023 = AND(g9528, g25036) +g26024 = AND(g2619, g25039) +g26048 = AND(g5853, g25044) +g26049 = AND(g9621, g25046) +g26050 = AND(g9630, g25047) +g26051 = AND(g24896, g14169) +g26077 = AND(g9607, g25233) +g26078 = AND(g5128, g25055) +g26079 = AND(g6199, g25060) +g26084 = AND(g24926, g9602) +g26085 = AND(g11906, g25070) +g26086 = AND(g9672, g25255) +g26087 = AND(g5475, g25072) +g26088 = AND(g6545, g25080) +g26090 = AND(g1624, g25081) +g26091 = AND(g1691, g25082) +g26092 = AND(g9766, g25083) +g26094 = AND(g24936, g9664) +g26095 = AND(g11923, g25090) +g26096 = AND(g9733, g25268) +g26097 = AND(g5821, g25092) +g26100 = AND(g1677, g25097) +g26101 = AND(g1760, g25098) +g26102 = AND(g1825, g25099) +g26103 = AND(g2185, g25100) +g26104 = AND(g2250, g25101) +g26119 = AND(g11944, g25109) +g26120 = AND(g9809, g25293) +g26121 = AND(g6167, g25111) +g26122 = AND(g24557, g19762) +g26123 = AND(g1696, g25382) +g26124 = AND(g1811, g25116) +g26125 = AND(g1894, g25117) +g26126 = AND(g1959, g25118) +g26127 = AND(g2236, g25119) +g26128 = AND(g2319, g25120) +g26129 = AND(g2384, g25121) +g26130 = AND(g24890, g19772) +g26145 = AND(g11962, g25131) +g26146 = AND(g9892, g25334) +g26147 = AND(g6513, g25133) +g26148 = AND(g25357, g11724, g11709, g11686) +g26153 = AND(g24565, g19780) +g26154 = AND(g1830, g25426) +g26155 = AND(g1945, g25134) +g26156 = AND(g2028, g25135) +g26157 = AND(g2093, g25136) +g26158 = AND(g2255, g25432) +g26159 = AND(g2370, g25137) +g26160 = AND(g2453, g25138) +g26161 = AND(g2518, g25139) +g26165 = AND(g11980, g25153) +g26166 = AND(g25357, g11724, g11709, g7558) +g26171 = AND(g25357, g6856, g11709, g11686) +g26176 = AND(g1964, g25467) +g26177 = AND(g2079, g25154) +g26178 = AND(g2389, g25473) +g26179 = AND(g2504, g25155) +g26180 = AND(g2587, g25156) +g26181 = AND(g2652, g25157) +g26182 = AND(g9978, g25317) +g26186 = AND(g24580, g23031) +g26190 = AND(g25357, g11724, g7586, g11686) +g26195 = AND(g25357, g6856, g11709, g7558) +g26200 = AND(g24688, g10678, g10658, g10627) +g26203 = AND(g1632, g25337) +g26204 = AND(g1720, g25275) +g26205 = AND(g2098, g25492) +g26206 = AND(g2523, g25495) +g26207 = AND(g2638, g25170) +g26213 = AND(g25357, g11724, g7586, g7558) +g26218 = AND(g25357, g6856, g7586, g11686) +g26223 = AND(g24688, g10678, g10658, g8757) +g26226 = AND(g24688, g8812, g10658, g10627) +g26229 = AND(g1724, g25275) +g26230 = AND(g1768, g25385) +g26231 = AND(g1854, g25300) +g26232 = AND(g2193, g25396) +g26233 = AND(g2279, g25309) +g26234 = AND(g2657, g25514) +g26236 = AND(g25357, g6856, g7586, g7558) +g26241 = AND(g24688, g10678, g8778, g10627) +g26244 = AND(g24688, g8812, g10658, g8757) +g26249 = AND(g1858, g25300) +g26250 = AND(g1902, g25429) +g26251 = AND(g1988, g25341) +g26252 = AND(g2283, g25309) +g26253 = AND(g2327, g25435) +g26254 = AND(g2413, g25349) +g26257 = AND(g4253, g25197) +g26258 = AND(g12875, g25231) +g26259 = AND(g24430, g25232) +g26261 = AND(g24688, g10678, g8778, g8757) +g26264 = AND(g24688, g8812, g8778, g10627) +g26270 = AND(g1700, g25275) +g26271 = AND(g1992, g25341) +g26272 = AND(g2036, g25470) +g26273 = AND(g2122, g25389) +g26274 = AND(g2130, g25210) +g26275 = AND(g2417, g25349) +g26276 = AND(g2461, g25476) +g26277 = AND(g2547, g25400) +g26279 = AND(g4249, g25213) +g26280 = AND(g13051, g25248) +g26281 = AND(g24688, g8812, g8778, g8757) +g26285 = AND(g1834, g25300) +g26286 = AND(g2126, g25389) +g26287 = AND(g2138, g25225) +g26288 = AND(g2259, g25309) +g26289 = AND(g2551, g25400) +g26290 = AND(g2595, g25498) +g26291 = AND(g2681, g25439) +g26292 = AND(g2689, g25228) +g26294 = AND(g4245, g25230) +g26295 = AND(g13070, g25266) +g26300 = AND(g1968, g25341) +g26301 = AND(g2145, g25244) +g26302 = AND(g2393, g25349) +g26303 = AND(g2685, g25439) +g26304 = AND(g2697, g25246) +g26306 = AND(g13087, g25286) +g26307 = AND(g13070, g25288) +g26308 = AND(g6961, g25289) +g26310 = AND(g2102, g25389) +g26311 = AND(g2527, g25400) +g26312 = AND(g2704, g25264) +g26313 = AND(g12645, g25326) +g26323 = AND(g10262, g25273) +g26324 = AND(g2661, g25439) +g26325 = AND(g12644, g25370) +g26336 = AND(g10307, g25480) +g26339 = AND(g225, g24836) +g26341 = AND(g24746, g20105) +g26345 = AND(g13051, g25505) +g26347 = AND(g262, g24850) +g26350 = AND(g13087, g25517) +g26351 = AND(g239, g24869) +g26356 = AND(g15581, g25523) +g26357 = AND(g22547, g25525) +g26358 = AND(g19522, g25528) +g26360 = AND(g10589, g25533) +g26362 = AND(g19557, g25538) +g26378 = AND(g19576, g25544) +g26379 = AND(g19904, g25546) +g26380 = AND(g19572, g25547) +g26381 = AND(g4456, g25548) +g26387 = AND(g24813, g20231) +g26388 = AND(g19595, g25552) +g26389 = AND(g19949, g25553) +g26390 = AND(g4423, g25554) +g26391 = AND(g19593, g25555) +g26393 = AND(g19467, g25558) +g26394 = AND(g22530, g25560) +g26395 = AND(g22547, g25561) +g26397 = AND(g19475, g25563) +g26398 = AND(g24946, g10474) +g26399 = AND(g15572, g25566) +g26423 = AND(g19488, g24356) +g26484 = AND(g24946, g8841) +g26485 = AND(g24968, g10502) +g26486 = AND(g4423, g24358) +g26487 = AND(g15702, g24359) +g26511 = AND(g19265, g24364) +g26513 = AND(g19501, g24365) +g26514 = AND(g7400, g25564) +g26516 = AND(g24968, g8876) +g26517 = AND(g15708, g24367) +g26541 = AND(g319, g24375) +g26542 = AND(g13102, g24376) +g26543 = AND(g12910, g24377) +g26544 = AND(g7446, g24357) +g26547 = AND(g13283, g25027) +g26571 = AND(g10472, g24386) +g26572 = AND(g7443, g24439) +g26602 = AND(g7487, g24453) +g26604 = AND(g13248, g25051) +g26606 = AND(g1018, g24510) +g26610 = AND(g14198, g24405) +g26611 = AND(g24935, g20580) +g26612 = AND(g901, g24407) +g26613 = AND(g1361, g24518) +g26629 = AND(g14173, g24418) +g26630 = AND(g7592, g24419) +g26633 = AND(g24964, g20616) +g26635 = AND(g25321, g20617) +g26650 = AND(g10796, g24424) +g26651 = AND(g22707, g24425) +g26652 = AND(g10799, g24426) +g26670 = AND(g13385, g24428) +g26671 = AND(g316, g24429) +g26684 = AND(g25407, g20673) +g26689 = AND(g15754, g24431) +g26711 = AND(g25446, g20713) +g26712 = AND(g24508, g24463) +g26713 = AND(g25447, g20714) +g26719 = AND(g10709, g24438) +g26749 = AND(g24494, g23578) +g26750 = AND(g24514, g24474) +g26753 = AND(g16024, g24452) +g26778 = AND(g25501, g20923) +g26779 = AND(g24497, g23620) +g26780 = AND(g4098, g24437) +g26783 = AND(g25037, g21048) +g26799 = AND(g25247, g21068) +g26808 = AND(g25521, g21185) +g26815 = AND(g4108, g24528) +g26819 = AND(g106, g24490) +g26821 = AND(g24821, g13103) +g26822 = AND(g24841, g13116) +g26823 = AND(g24401, g13106) +g26826 = AND(g24907, g15747) +g26828 = AND(g24919, g15756) +g26829 = AND(g2844, g24505) +g26833 = AND(g2852, g24509) +g26838 = AND(g2860, g24515) +g26839 = AND(g2988, g24516) +g26842 = AND(g2894, g24522) +g26844 = AND(g25261, g21418) +g26845 = AND(g24391, g21426) +g26846 = AND(g37, g24524) +g26847 = AND(g2873, g24525) +g26848 = AND(g2950, g24526) +g26849 = AND(g2994, g24527) +g26852 = AND(g24975, g24958) +g26853 = AND(g94, g24533) +g26854 = AND(g2868, g24534) +g26855 = AND(g2960, g24535) +g26857 = AND(g25062, g25049) +g26858 = AND(g2970, g24540) +g26861 = AND(g25021, g25003) +g26863 = AND(g24974, g24957) +g26864 = AND(g2907, g24548) +g26871 = AND(g25038, g25020) +g26977 = AND(g23032, g26261, g26424, g25550) +g26994 = AND(g23032, g26226, g26424, g25557) +g27020 = AND(g4601, g25852) +g27025 = AND(g26334, g7917) +g27028 = AND(g26342, g1157) +g27029 = AND(g26327, g11031) +g27030 = AND(g26343, g7947) +g27032 = AND(g7704, g5180, g5188, g26200) +g27033 = AND(g25767, g19273) +g27034 = AND(g26328, g8609) +g27035 = AND(g26348, g1500) +g27036 = AND(g26329, g11038) +g27039 = AND(g7738, g5527, g5535, g26223) +g27040 = AND(g7812, g6565, g6573, g26226) +g27041 = AND(g8519, g26330) +g27042 = AND(g25774, g19343) +g27043 = AND(g26335, g8632) +g27044 = AND(g7766, g5873, g5881, g26241) +g27045 = AND(g10295, g3171, g3179, g26244) +g27050 = AND(g25789, g22338) +g27057 = AND(g7791, g6219, g6227, g26261) +g27058 = AND(g10323, g3522, g3530, g26264) +g27073 = AND(g7121, g3873, g3881, g26281) +g27083 = AND(g25819, g22456) +g27085 = AND(g25835, g22494) +g27086 = AND(g25836, g22495) +g27087 = AND(g13872, g26284) +g27090 = AND(g25997, g16423) +g27094 = AND(g25997, g16472) +g27095 = AND(g25997, g16473) +g27096 = AND(g26026, g16475) +g27097 = AND(g25867, g22526) +g27098 = AND(g25868, g22528) +g27099 = AND(g14094, g26352) +g27103 = AND(g25997, g16509) +g27104 = AND(g25997, g16510) +g27105 = AND(g26026, g16511) +g27106 = AND(g26026, g16512) +g27107 = AND(g26055, g16514) +g27113 = AND(g25997, g16522) +g27114 = AND(g25997, g16523) +g27115 = AND(g26026, g16526) +g27116 = AND(g26026, g16527) +g27117 = AND(g26055, g16528) +g27118 = AND(g26055, g16529) +g27119 = AND(g25877, g22542) +g27120 = AND(g25878, g22543) +g27121 = AND(g136, g26326) +g27127 = AND(g25997, g16582) +g27128 = AND(g25997, g16583) +g27129 = AND(g26026, g16584) +g27130 = AND(g26026, g16585) +g27131 = AND(g26055, g16588) +g27132 = AND(g26055, g16589) +g27134 = AND(g25997, g16602) +g27136 = AND(g26026, g16605) +g27137 = AND(g26026, g16606) +g27138 = AND(g26055, g16607) +g27139 = AND(g26055, g16608) +g27140 = AND(g25885, g22593) +g27145 = AND(g14121, g26382) +g27146 = AND(g26148, g8187, g1648) +g27148 = AND(g25997, g16622) +g27149 = AND(g25997, g16623) +g27151 = AND(g26026, g16626) +g27153 = AND(g26055, g16629) +g27154 = AND(g26055, g16630) +g27158 = AND(g26609, g16645) +g27160 = AND(g14163, g26340) +g27161 = AND(g26166, g8241, g1783) +g27162 = AND(g26171, g8259, g2208) +g27177 = AND(g25997, g16651) +g27178 = AND(g25997, g16652) +g27180 = AND(g26026, g16654) +g27181 = AND(g26026, g16655) +g27183 = AND(g26055, g16658) +g27184 = AND(g26628, g13756) +g27185 = AND(g26190, g8302, g1917) +g27186 = AND(g26195, g8316, g2342) +g27201 = AND(g25997, g16685) +g27202 = AND(g25997, g13876) +g27203 = AND(g26026, g16688) +g27204 = AND(g26026, g16689) +g27206 = AND(g26055, g16691) +g27207 = AND(g26055, g16692) +g27208 = AND(g9037, g26598) +g27209 = AND(g26213, g8365, g2051) +g27210 = AND(g26218, g8373, g2476) +g27211 = AND(g25997, g16716) +g27212 = AND(g25997, g16717) +g27213 = AND(g26026, g16721) +g27214 = AND(g26026, g13901) +g27215 = AND(g26055, g16724) +g27216 = AND(g26055, g16725) +g27217 = AND(g26236, g8418, g2610) +g27218 = AND(g25997, g16740) +g27219 = AND(g26026, g16742) +g27220 = AND(g26026, g16743) +g27221 = AND(g26055, g16747) +g27222 = AND(g26055, g13932) +g27227 = AND(g26026, g16771) +g27228 = AND(g26055, g16773) +g27229 = AND(g26055, g16774) +g27230 = AND(g25906, g19558) +g27234 = AND(g26055, g16814) +g27235 = AND(g25910, g19579) +g27246 = AND(g26690, g26673) +g27247 = AND(g2759, g26745) +g27249 = AND(g25929, g19678) +g27251 = AND(g26721, g26694) +g27252 = AND(g26733, g26703) +g27254 = AND(g25935, g19688) +g27255 = AND(g25936, g19689) +g27256 = AND(g25937, g19698) +g27259 = AND(g26755, g26725) +g27260 = AND(g26766, g26737) +g27262 = AND(g25997, g17092) +g27263 = AND(g25940, g19713) +g27264 = AND(g25941, g19714) +g27265 = AND(g26785, g26759) +g27266 = AND(g26789, g26770) +g27267 = AND(g26026, g17124) +g27268 = AND(g25942, g19733) +g27269 = AND(g25943, g19734) +g27270 = AND(g26805, g26793) +g27272 = AND(g26055, g17144) +g27275 = AND(g25945, g19745) +g27276 = AND(g9750, g26607) +g27277 = AND(g26359, g14191) +g27280 = AND(g9825, g26614) +g27281 = AND(g9830, g26615) +g27284 = AND(g9908, g26631) +g27285 = AND(g9912, g26632) +g27286 = AND(g6856, g26634) +g27287 = AND(g26545, g23011) +g27288 = AND(g26515, g23013) +g27291 = AND(g11969, g26653) +g27292 = AND(g1714, g26654) +g27293 = AND(g9972, g26655) +g27294 = AND(g9975, g26656) +g27298 = AND(g26573, g23026) +g27299 = AND(g26546, g23028) +g27300 = AND(g12370, g26672) +g27301 = AND(g11992, g26679) +g27302 = AND(g1848, g26680) +g27303 = AND(g11996, g26681) +g27304 = AND(g2273, g26682) +g27305 = AND(g10041, g26683) +g27309 = AND(g26603, g23057) +g27310 = AND(g26574, g23059) +g27311 = AND(g12431, g26693) +g27312 = AND(g12019, g26700) +g27313 = AND(g1982, g26701) +g27314 = AND(g12436, g26702) +g27315 = AND(g12022, g26709) +g27316 = AND(g2407, g26710) +g27323 = AND(g26268, g23086) +g27324 = AND(g10150, g26720) +g27325 = AND(g12478, g26724) +g27326 = AND(g12048, g26731) +g27327 = AND(g2116, g26732) +g27328 = AND(g12482, g26736) +g27329 = AND(g12052, g26743) +g27330 = AND(g2541, g26744) +g27331 = AND(g10177, g26754) +g27332 = AND(g12538, g26758) +g27333 = AND(g10180, g26765) +g27334 = AND(g12539, g26769) +g27335 = AND(g12087, g26776) +g27336 = AND(g2675, g26777) +g27339 = AND(g26400, g17308) +g27340 = AND(g10199, g26784) +g27341 = AND(g10203, g26788) +g27342 = AND(g12592, g26792) +g27346 = AND(g26400, g17389) +g27347 = AND(g26400, g17390) +g27348 = AND(g26488, g17392) +g27350 = AND(g10217, g26803) +g27351 = AND(g10218, g26804) +g27357 = AND(g26400, g17414) +g27358 = AND(g26400, g17415) +g27359 = AND(g26488, g17416) +g27360 = AND(g26488, g17417) +g27361 = AND(g26519, g17419) +g27362 = AND(g26080, g20036) +g27363 = AND(g10231, g26812) +g27369 = AND(g25894, g25324) +g27370 = AND(g26400, g17472) +g27371 = AND(g26400, g17473) +g27372 = AND(g26488, g17476) +g27373 = AND(g26488, g17477) +g27374 = AND(g26519, g17478) +g27375 = AND(g26519, g17479) +g27376 = AND(g26549, g17481) +g27378 = AND(g26089, g20052) +g27384 = AND(g26400, g17496) +g27385 = AND(g26400, g17497) +g27386 = AND(g26488, g17498) +g27387 = AND(g26488, g17499) +g27388 = AND(g26519, g17502) +g27389 = AND(g26519, g17503) +g27390 = AND(g26549, g17504) +g27391 = AND(g26549, g17505) +g27392 = AND(g26576, g17507) +g27393 = AND(g26099, g20066) +g27395 = AND(g8046, g26314, g9187, g9077) +g27404 = AND(g26400, g17518) +g27406 = AND(g26488, g17521) +g27407 = AND(g26488, g17522) +g27408 = AND(g26519, g17523) +g27409 = AND(g26519, g17524) +g27410 = AND(g26549, g17527) +g27411 = AND(g26549, g17528) +g27412 = AND(g26576, g17529) +g27413 = AND(g26576, g17530) +g27414 = AND(g255, g26827) +g27416 = AND(g8046, g26314, g9187, g504) +g27421 = AND(g8038, g26314, g9187, g9077) +g27427 = AND(g26400, g17575) +g27428 = AND(g26400, g17576) +g27430 = AND(g26488, g17579) +g27432 = AND(g26519, g17582) +g27433 = AND(g26519, g17583) +g27434 = AND(g26549, g17584) +g27435 = AND(g26549, g17585) +g27436 = AND(g26576, g17588) +g27437 = AND(g26576, g17589) +g27439 = AND(g232, g26831) +g27440 = AND(g8046, g26314, g518, g504) +g27445 = AND(g8038, g26314, g9187, g504) +g27451 = AND(g26400, g17599) +g27452 = AND(g26400, g17600) +g27454 = AND(g26488, g17602) +g27455 = AND(g26488, g17603) +g27457 = AND(g26519, g17606) +g27459 = AND(g26549, g17609) +g27460 = AND(g26549, g17610) +g27461 = AND(g26576, g17611) +g27462 = AND(g26576, g17612) +g27467 = AND(g269, g26832) +g27469 = AND(g8046, g26314, g518, g9077) +g27474 = AND(g8038, g26314, g518, g504) +g27480 = AND(g26400, g17638) +g27481 = AND(g26400, g14630) +g27482 = AND(g26488, g17641) +g27483 = AND(g26488, g17642) +g27485 = AND(g26519, g17644) +g27486 = AND(g26519, g17645) +g27488 = AND(g26549, g17648) +g27490 = AND(g26576, g17651) +g27491 = AND(g26576, g17652) +g27493 = AND(g246, g26837) +g27494 = AND(g8038, g26314, g518, g9077) +g27500 = AND(g26400, g17672) +g27501 = AND(g26400, g17673) +g27502 = AND(g26488, g17677) +g27503 = AND(g26488, g14668) +g27504 = AND(g26519, g17680) +g27505 = AND(g26519, g17681) +g27507 = AND(g26549, g17683) +g27508 = AND(g26549, g17684) +g27510 = AND(g26576, g17687) +g27517 = AND(g26400, g17707) +g27518 = AND(g26488, g17709) +g27519 = AND(g26488, g17710) +g27520 = AND(g26519, g17714) +g27521 = AND(g26519, g14700) +g27522 = AND(g26549, g17717) +g27523 = AND(g26549, g17718) +g27525 = AND(g26576, g17720) +g27526 = AND(g26576, g17721) +g27534 = AND(g26488, g17735) +g27535 = AND(g26519, g17737) +g27536 = AND(g26519, g17738) +g27537 = AND(g26549, g17742) +g27538 = AND(g26549, g14744) +g27539 = AND(g26576, g17745) +g27540 = AND(g26576, g17746) +g27541 = AND(g26278, g23334) +g27545 = AND(g26519, g17756) +g27546 = AND(g26549, g17758) +g27547 = AND(g26549, g17759) +g27548 = AND(g26576, g17763) +g27549 = AND(g26576, g14785) +g27553 = AND(g26293, g23353) +g27557 = AND(g26549, g17774) +g27558 = AND(g26576, g17776) +g27559 = AND(g26576, g17777) +g27560 = AND(g26299, g20191) +g27564 = AND(g26305, g23378) +g27568 = AND(g26576, g17791) +g27588 = AND(g26690, g26673) +g27594 = AND(g26721, g26694) +g27595 = AND(g26733, g26703) +g27598 = AND(g25899, g10475) +g27599 = AND(g26337, g20033) +g27600 = AND(g26755, g26725) +g27601 = AND(g26766, g26737) +g27602 = AND(g23032, g26244, g26424, g24966) +g27612 = AND(g25887, g8844) +g27614 = AND(g26785, g26759) +g27615 = AND(g26789, g26770) +g27616 = AND(g26349, g20449) +g27617 = AND(g23032, g26264, g26424, g24982) +g27627 = AND(g13266, g25790) +g27628 = AND(g26400, g18061) +g27633 = AND(g13076, g25766) +g27634 = AND(g26805, g26793) +g27635 = AND(g23032, g26281, g26424, g24996) +g27645 = AND(g26488, g15344) +g27646 = AND(g13094, g25773) +g27648 = AND(g25882, g8974) +g27649 = AND(g10820, g25820) +g27650 = AND(g26519, g15479) +g27651 = AND(g22448, g25781) +g27653 = AND(g26549, g15562) +g27658 = AND(g22491, g25786) +g27660 = AND(g24688, g26424, g22763) +g27661 = AND(g26576, g15568) +g27664 = AND(g1024, g25911) +g27665 = AND(g26872, g23519) +g27666 = AND(g26865, g23521) +g27667 = AND(g26361, g20601) +g27668 = AND(g1367, g25917) +g27669 = AND(g26840, g13278) +g27673 = AND(g25769, g23541) +g27674 = AND(g26873, g23543) +g27676 = AND(g26377, g20627) +g27677 = AND(g13021, g25888) +g27678 = AND(g947, g25830) +g27682 = AND(g25777, g23565) +g27683 = AND(g25770, g23567) +g27684 = AND(g26386, g20657) +g27685 = AND(g13032, g25895) +g27686 = AND(g1291, g25849) +g27690 = AND(g25784, g23607) +g27691 = AND(g25778, g23609) +g27692 = AND(g26392, g20697) +g27696 = AND(g25800, g23647) +g27697 = AND(g25785, g23649) +g27699 = AND(g26396, g20766) +g27700 = AND(g22342, g25182, g26424, g26148) +g27710 = AND(g26422, g20904) +g27711 = AND(g22369, g25193, g26424, g26166) +g27714 = AND(g22384, g25195, g26424, g26171) +g27723 = AND(g26512, g21049) +g27724 = AND(g22417, g25208, g26424, g26190) +g27727 = AND(g22432, g25211, g26424, g26195) +g27759 = AND(g22457, g25224, g26424, g26213) +g27762 = AND(g22472, g25226, g26424, g26218) +g27765 = AND(g4146, g25886) +g27817 = AND(g22498, g25245, g26424, g26236) +g27820 = AND(g7670, g25932) +g27821 = AND(g7680, g25892) +g27822 = AND(g4157, g25893) +g27932 = AND(g25944, g19369) +g27957 = AND(g25947, g15995) +g27958 = AND(g25950, g22449) +g27959 = AND(g25948, g19374) +g27962 = AND(g25954, g19597) +g27963 = AND(g25952, g16047) +g27964 = AND(g25956, g22492) +g27965 = AND(g25834, g13117) +g27968 = AND(g25958, g19614) +g27981 = AND(g26751, g23924) +g27988 = AND(g26781, g23941) +g27992 = AND(g26800, g23964) +g27995 = AND(g26809, g23985) +g27997 = AND(g26813, g23995) +g27999 = AND(g23032, g26200, g26424, g25529) +g28010 = AND(g23032, g26223, g26424, g25535) +g28020 = AND(g23032, g26241, g26424, g25542) +I26530 = AND(g26365, g24096, g24097, g24098) +I26531 = AND(g24099, g24100, g24101, g24102) +g28035 = AND(g24103, I26530, I26531) +g28107 = AND(g27970, g18874) +g28108 = AND(g7975, g27237) +g28110 = AND(g27974, g18886) +g28111 = AND(g27343, g22716) +g28112 = AND(g27352, g26162) +g28113 = AND(g8016, g27242) +g28114 = AND(g25869, g27051) +g28115 = AND(g27354, g22759) +g28116 = AND(g27366, g26183) +g28117 = AND(g8075, g27245) +g28124 = AND(g27368, g22842) +g28125 = AND(g27381, g26209) +g28130 = AND(g27353, g23063) +g28133 = AND(g27367, g23108) +g28136 = AND(g27382, g23135) +g28139 = AND(g27337, g26054) +g28141 = AND(g10831, g11797, g11261, g27163) +g28143 = AND(g27344, g26083) +g28144 = AND(g4608, g27020) +g28148 = AND(g27355, g26093) +g28150 = AND(g10862, g11834, g11283, g27187) +g28151 = AND(g8426, g27295) +g28152 = AND(g26297, g27279) +g28153 = AND(g26424, g22763, g27031) +g28154 = AND(g8492, g27306) +g28158 = AND(g26424, g22763, g27037) +g28159 = AND(g8553, g27317) +g28160 = AND(g26309, g27463) +g28164 = AND(g8651, g27528) +g28165 = AND(g27018, g22455) +g28171 = AND(g27016, g19385) +g28178 = AND(g27019, g19397) +g28182 = AND(g8770, g27349) +g28183 = AND(g27024, g19421) +g28185 = AND(g27026, g19435) +g28192 = AND(g8891, g27415) +g28193 = AND(g8851, g27629) +g28197 = AND(g27647, g11344) +g28198 = AND(g26649, g27492) +g28199 = AND(g27479, g16684) +g28200 = AND(g27652, g11383) +g28201 = AND(g27499, g16720) +g28202 = AND(g27659, g11413) +g28204 = AND(g26098, g27654) +g28205 = AND(g27516, g16746) +g28210 = AND(g9229, g27554) +g28213 = AND(g27720, g23380) +g28214 = AND(g27731, g26625) +g28215 = AND(g9264, g27565) +g28217 = AND(g27733, g23391) +g28218 = AND(g27768, g26645) +g28219 = AND(g9316, g27573) +g28223 = AND(g27338, g17194) +g28224 = AND(g27163, g22763, g27064) +g28225 = AND(g27770, g23400) +g28226 = AND(g27825, g26667) +g28227 = AND(g9397, g27583) +g28228 = AND(g27126, g19636) +g28229 = AND(g27345, g17213) +g28231 = AND(g27187, g22763, g27074) +g28232 = AND(g27732, g23586) +g28233 = AND(g27827, g23411) +g28234 = AND(g27877, g26686) +g28235 = AND(g9467, g27592) +g28236 = AND(g8515, g27971) +g28237 = AND(g9492, g27597) +g28238 = AND(g27133, g19658) +g28239 = AND(g27135, g19659) +g28240 = AND(g27356, g17239) +g28242 = AND(g27769, g23626) +g28243 = AND(g27879, g23423) +g28244 = AND(g27926, g26715) +g28245 = AND(g11367, g27975) +g28246 = AND(g8572, g27976) +g28247 = AND(g27147, g19675) +g28248 = AND(g27150, g19676) +g28249 = AND(g27152, g19677) +g28251 = AND(g27826, g23662) +g28252 = AND(g27159, g19682) +g28253 = AND(g23719, g27700) +g28254 = AND(g7268, g1668, g27395) +g28255 = AND(g8515, g27983) +g28256 = AND(g11398, g27984) +g28257 = AND(g27179, g19686) +g28258 = AND(g27182, g19687) +g28260 = AND(g27703, g26518) +g28261 = AND(g27878, g23695) +g28263 = AND(g23747, g27711) +g28264 = AND(g7315, g1802, g27416) +g28265 = AND(g11367, g27989) +g28266 = AND(g23748, g27714) +g28267 = AND(g7328, g2227, g27421) +g28268 = AND(g8572, g27990) +g28269 = AND(g27205, g19712) +g28272 = AND(g27721, g26548) +g28273 = AND(g27927, g23729) +g28280 = AND(g23761, g27724) +g28281 = AND(g7362, g1936, g27440) +g28282 = AND(g23762, g27727) +g28283 = AND(g7380, g2361, g27445) +g28284 = AND(g11398, g27994) +g28285 = AND(g9657, g27717) +g28289 = AND(g27734, g26575) +g28290 = AND(g23780, g27759) +g28291 = AND(g7411, g2070, g27469) +g28292 = AND(g23781, g27762) +g28293 = AND(g7424, g2495, g27474) +g28299 = AND(g9716, g27670) +g28300 = AND(g27771, g26605) +g28301 = AND(g27224, g19750) +g28302 = AND(g23809, g27817) +g28303 = AND(g7462, g2629, g27494) +g28304 = AND(g27226, g19753) +g28311 = AND(g9792, g27679) +g28312 = AND(g27828, g26608) +g28313 = AND(g27231, g19766) +g28314 = AND(g27552, g14205) +g28315 = AND(g27232, g19769) +g28318 = AND(g27233, g19770) +g28324 = AND(g9875, g27687) +g28327 = AND(g27365, g19785) +g28330 = AND(g27238, g19786) +g28333 = AND(g27239, g19787) +g28339 = AND(g9946, g27693) +g28341 = AND(g27240, g19790) +g28343 = AND(g27380, g19799) +g28346 = AND(g27243, g19800) +g28352 = AND(g10014, g27705) +g28360 = AND(g27401, g19861) +g28415 = AND(g27250, g19963) +g28426 = AND(g27257, g20006) +g28427 = AND(g27258, g20008) +g28439 = AND(g27273, g10233) +g28440 = AND(g27274, g20059) +g28442 = AND(g27278, g20072) +g28451 = AND(g27283, g20090) +g28453 = AND(g27582, g10233) +g28454 = AND(g26976, g12233) +g28455 = AND(g27289, g20103) +g28456 = AND(g27290, g20104) +I26948 = AND(g24981, g26424, g22698) +g28458 = AND(g27187, g12730, g20887, I26948) +g28466 = AND(g27960, g17637) +g28467 = AND(g26993, g12295) +I26960 = AND(g24995, g26424, g22698) +g28471 = AND(g27187, g12762, g21024, I26960) +g28477 = AND(g27966, g17676) +g28478 = AND(g27007, g12345) +I26972 = AND(g25011, g26424, g22698) +g28484 = AND(g27187, g10290, g21163, I26972) +g28488 = AND(g27969, g17713) +g28489 = AND(g27010, g12417) +g28494 = AND(g27973, g17741) +g28495 = AND(g27012, g12465) +g28499 = AND(g27982, g17762) +g28523 = AND(g27704, g15585) +g28524 = AND(g6821, g27084) +g28528 = AND(g27187, g12730) +g28530 = AND(g27383, g20240) +g28531 = AND(g27722, g15608) +g28532 = AND(g27394, g20265) +g28535 = AND(g11981, g27088) +g28537 = AND(g6832, g27089) +g28539 = AND(g27187, g12762) +g28541 = AND(g27403, g20274) +g28542 = AND(g27405, g20275) +g28543 = AND(g27735, g15628) +g28547 = AND(g6821, g27091) +g28550 = AND(g12009, g27092) +g28553 = AND(g27187, g10290) +g28554 = AND(g27426, g20372) +g28555 = AND(g27429, g20373) +g28556 = AND(g27431, g20374) +g28557 = AND(g27772, g15647) +g28558 = AND(g7301, g27046) +g28563 = AND(g11981, g27100) +g28567 = AND(g6832, g27101) +g28569 = AND(g27453, g20433) +g28570 = AND(g27456, g20434) +g28571 = AND(g27458, g20435) +g28572 = AND(g27829, g15669) +g28573 = AND(g7349, g27059) +g28583 = AND(g12009, g27112) +g28585 = AND(g27063, g10530) +g28586 = AND(g27484, g20497) +g28587 = AND(g27487, g20498) +g28588 = AND(g27489, g20499) +g28597 = AND(g27515, g20508) +g28599 = AND(g27027, g8922) +g28601 = AND(g27506, g20514) +g28602 = AND(g27509, g20515) +g28612 = AND(g27524, g20539) +g28616 = AND(g27532, g20551) +g28617 = AND(g27533, g20552) +g28624 = AND(g22357, g27009) +g28626 = AND(g27542, g20573) +g28627 = AND(g27543, g20574) +g28630 = AND(g27544, g20575) +g28637 = AND(g22399, g27011) +g28638 = AND(g27551, g20583) +g28639 = AND(g27767, g20597) +g28642 = AND(g27555, g20598) +g28645 = AND(g27556, g20599) +g28652 = AND(g27282, g10288) +g28653 = AND(g7544, g27014) +g28654 = AND(g1030, g27108) +g28655 = AND(g27561, g20603) +g28657 = AND(g27562, g20606) +g28658 = AND(g27563, g20611) +g28660 = AND(g27824, g20623) +g28663 = AND(g27566, g20624) +g28666 = AND(g27567, g20625) +g28672 = AND(g7577, g27017) +g28673 = AND(g1373, g27122) +g28674 = AND(g27569, g20629) +g28676 = AND(g27570, g20632) +g28677 = AND(g27571, g20635) +g28679 = AND(g27572, g20638) +g28683 = AND(g27876, g20649) +g28686 = AND(g27574, g20650) +g28689 = AND(g27575, g20651) +g28692 = AND(g27578, g20661) +g28694 = AND(g27579, g20664) +g28695 = AND(g27580, g20666) +g28697 = AND(g27581, g20669) +g28703 = AND(g27925, g20680) +g28706 = AND(g27584, g20681) +g28710 = AND(g27589, g20703) +g28712 = AND(g27590, g20708) +g28714 = AND(g27591, g20711) +g28722 = AND(g27955, g20738) +g28725 = AND(g27596, g20779) +g28739 = AND(g21434, g26424, g25274, g27395) +g28761 = AND(g21434, g26424, g25299, g27416) +g28768 = AND(g21434, g26424, g25308, g27421) +g28789 = AND(g21434, g26424, g25340, g27440) +g28799 = AND(g21434, g26424, g25348, g27445) +g28812 = AND(g26972, g13037) +g28813 = AND(g4104, g27038) +g28833 = AND(g21434, g26424, g25388, g27469) +g28846 = AND(g21434, g26424, g25399, g27474) +g28880 = AND(g21434, g26424, g25438, g27494) +g28889 = AND(g17292, g25169, g26424, g27395) +g28919 = AND(g27663, g21295) +g28924 = AND(g17317, g25183, g26424, g27416) +g28939 = AND(g17321, g25184, g26424, g27421) +g28959 = AND(g17401, g25194, g26424, g27440) +g28970 = AND(g17405, g25196, g26424, g27445) +I27349 = AND(g25534, g26424, g22698) +g28982 = AND(g27163, g12687, g20682, I27349) +g28991 = AND(g14438, g25209, g26424, g27469) +g28998 = AND(g17424, g25212, g26424, g27474) +I27364 = AND(g25541, g26424, g22698) +g29008 = AND(g27163, g12730, g20739, I27364) +g29029 = AND(g14506, g25227, g26424, g27494) +I27381 = AND(g25549, g26424, g22698) +g29036 = AND(g27163, g12762, g20875, I27381) +I27409 = AND(g25556, g26424, g22698) +g29073 = AND(g27163, g10290, g21012, I27409) +I27429 = AND(g25562, g26424, g22698) +g29110 = AND(g27187, g12687, g20751, I27429) +g29178 = AND(g27163, g12687) +g29182 = AND(g27163, g12730) +g29188 = AND(g27163, g12762) +g29192 = AND(g27163, g10290) +g29199 = AND(g27187, g12687) +I27503 = AND(g19890, g24075, g24076, g28032) +I27504 = AND(g24077, g24078, g24079, g24080) +g29201 = AND(g24081, I27503, I27504) +I27508 = AND(g19935, g24082, g24083, g28033) +I27509 = AND(g24084, g24085, g24086, g24087) +g29202 = AND(g24088, I27508, I27509) +I27513 = AND(g19984, g24089, g24090, g28034) +I27514 = AND(g24091, g24092, g24093, g24094) +g29203 = AND(g24095, I27513, I27514) +I27518 = AND(g20720, g24104, g24105, g24106) +I27519 = AND(g28036, g24107, g24108, g24109) +g29204 = AND(g24110, I27518, I27519) +I27523 = AND(g20857, g24111, g24112, g24113) +I27524 = AND(g28037, g24114, g24115, g24116) +g29205 = AND(g24117, I27523, I27524) +I27528 = AND(g20998, g24118, g24119, g24120) +I27529 = AND(g28038, g24121, g24122, g24123) +g29206 = AND(g24124, I27528, I27529) +I27533 = AND(g21143, g24125, g24126, g24127) +I27534 = AND(g28039, g24128, g24129, g24130) +g29207 = AND(g24131, I27533, I27534) +I27538 = AND(g21209, g24132, g24133, g24134) +I27539 = AND(g28040, g24135, g24136, g24137) +g29208 = AND(g24138, I27538, I27539) +g29314 = AND(g29005, g22144) +g29315 = AND(g29188, g7051, g5990) +g29316 = AND(g28528, g6875, g3288) +g29320 = AND(g29068, g22147) +g29321 = AND(g29033, g22148) +g29322 = AND(g29192, g7074, g6336) +g29323 = AND(g28539, g6905, g3639) +g29324 = AND(g29078, g18883) +g29326 = AND(g29105, g22155) +g29327 = AND(g29070, g22156) +g29328 = AND(g28553, g6928, g3990) +g29329 = AND(g7995, g28353) +g29330 = AND(g29114, g18894) +g29331 = AND(g29143, g22169) +g29332 = AND(g29107, g22170) +g29334 = AND(g29148, g18908) +g29336 = AND(g4704, g28363) +g29337 = AND(g29166, g22180) +g29338 = AND(g29145, g22181) +g29344 = AND(g29168, g18932) +g29345 = AND(g4749, g28376) +g29346 = AND(g4894, g28381) +g29347 = AND(g29176, g22201) +g29349 = AND(g4760, g28391) +g29350 = AND(g4939, g28395) +g29351 = AND(g4771, g28406) +g29352 = AND(g4950, g28410) +g29354 = AND(g4961, g28421) +g29360 = AND(g27364, g28294) +g29362 = AND(g27379, g28307) +g29363 = AND(g8458, g28444) +g29364 = AND(g27400, g28321) +g29367 = AND(g8575, g28325) +g29369 = AND(g28209, g22341) +g29375 = AND(g13946, g28370) +g29376 = AND(g14002, g28504) +g29377 = AND(g28132, g19387) +g29378 = AND(g28137, g22493) +g29380 = AND(g28134, g19396) +g29381 = AND(g28135, g19399) +g29382 = AND(g26424, g22763, g28172) +g29383 = AND(g28138, g19412) +g29384 = AND(g26424, g22763, g28179) +g29475 = AND(g14033, g28500) +g29477 = AND(g14090, g28441) +g29494 = AND(g9073, g28479) +g29509 = AND(g1600, g28755) +g29510 = AND(g28856, g22342) +g29511 = AND(g1736, g28783) +g29512 = AND(g2161, g28793) +g29513 = AND(g28448, g14095) +g29514 = AND(g1608, g28780) +g29515 = AND(g28888, g22342) +g29516 = AND(g28895, g22369) +g29517 = AND(g1870, g28827) +g29518 = AND(g28906, g22384) +g29519 = AND(g2295, g28840) +g29521 = AND(g1744, g28824) +g29522 = AND(g28923, g22369) +g29523 = AND(g28930, g22417) +g29524 = AND(g2004, g28864) +g29525 = AND(g2169, g28837) +g29526 = AND(g28938, g22384) +g29527 = AND(g28945, g22432) +g29528 = AND(g2429, g28874) +g29530 = AND(g1612, g28820) +g29531 = AND(g1664, g28559) +g29532 = AND(g1878, g28861) +g29533 = AND(g28958, g22417) +g29534 = AND(g28965, g22457) +g29535 = AND(g2303, g28871) +g29536 = AND(g28969, g22432) +g29537 = AND(g28976, g22472) +g29538 = AND(g2563, g28914) +g29547 = AND(g1748, g28857) +g29548 = AND(g1798, g28575) +g29549 = AND(g2012, g28900) +g29550 = AND(g28990, g22457) +g29551 = AND(g2173, g28867) +g29552 = AND(g2223, g28579) +g29553 = AND(g2437, g28911) +g29554 = AND(g28997, g22472) +g29555 = AND(g29004, g22498) +g29563 = AND(g1616, g28853) +g29564 = AND(g1882, g28896) +g29565 = AND(g1932, g28590) +g29566 = AND(g2307, g28907) +g29567 = AND(g2357, g28593) +g29568 = AND(g2571, g28950) +g29569 = AND(g29028, g22498) +g29570 = AND(g2763, g28598) +g29571 = AND(g28452, g11762) +g29572 = AND(g1620, g28885) +g29573 = AND(g1752, g28892) +g29574 = AND(g2016, g28931) +g29575 = AND(g2066, g28604) +g29576 = AND(g2177, g28903) +g29577 = AND(g2441, g28946) +g29578 = AND(g2491, g28606) +g29579 = AND(g28457, g7964) +g29580 = AND(g28519, g14186) +g29581 = AND(g28462, g11796) +g29582 = AND(g27766, g28608) +g29584 = AND(g1706, g29018) +g29585 = AND(g1756, g28920) +g29586 = AND(g1886, g28927) +g29587 = AND(g2181, g28935) +g29588 = AND(g2311, g28942) +g29589 = AND(g2575, g28977) +g29590 = AND(g2625, g28615) +g29591 = AND(g28552, g11346) +g29592 = AND(g28469, g11832) +g29593 = AND(g28470, g7985) +g29594 = AND(g28529, g14192) +g29595 = AND(g28475, g11833) +g29596 = AND(g27823, g28620) +g29598 = AND(g28823, g22342) +g29599 = AND(g1710, g29018) +g29600 = AND(g1840, g29049) +g29601 = AND(g1890, g28955) +g29602 = AND(g2020, g28962) +g29603 = AND(g2265, g29060) +g29604 = AND(g2315, g28966) +g29605 = AND(g2445, g28973) +g29606 = AND(g28480, g8011) +g29607 = AND(g28509, g14208) +g29608 = AND(g28568, g11385) +g29609 = AND(g28482, g11861) +g29610 = AND(g28483, g8026) +g29611 = AND(g28540, g14209) +g29612 = AND(g27875, g28633) +g29613 = AND(g28208, g19763) +g29614 = AND(g28860, g22369) +g29615 = AND(g1844, g29049) +g29616 = AND(g1974, g29085) +g29617 = AND(g2024, g28987) +g29618 = AND(g28870, g22384) +g29619 = AND(g2269, g29060) +g29620 = AND(g2399, g29097) +g29621 = AND(g2449, g28994) +g29622 = AND(g2579, g29001) +g29623 = AND(g28496, g11563) +g29624 = AND(g28491, g8070) +g29625 = AND(g28514, g14226) +g29626 = AND(g28584, g11415) +g29627 = AND(g28493, g11884) +g29628 = AND(g27924, g28648) +g29629 = AND(g28211, g19779) +g29630 = AND(g28212, g19781) +g29631 = AND(g1682, g28656) +g29632 = AND(g28899, g22417) +g29633 = AND(g1978, g29085) +g29634 = AND(g2108, g29121) +g29635 = AND(g28910, g22432) +g29636 = AND(g2403, g29097) +g29637 = AND(g2533, g29134) +g29638 = AND(g2583, g29025) +g29639 = AND(g28510, g11618) +g29640 = AND(g28498, g8125) +g29641 = AND(g28520, g14237) +g29642 = AND(g27954, g28669) +g29644 = AND(g28216, g19794) +g29645 = AND(g1714, g29018) +g29646 = AND(g1816, g28675) +g29647 = AND(g28934, g22457) +g29648 = AND(g2112, g29121) +g29649 = AND(g2241, g28678) +g29650 = AND(g28949, g22472) +g29651 = AND(g2537, g29134) +g29652 = AND(g2667, g29157) +g29656 = AND(g28515, g11666) +g29661 = AND(g1687, g29015) +g29662 = AND(g1848, g29049) +g29663 = AND(g1950, g28693) +g29664 = AND(g2273, g29060) +g29665 = AND(g2375, g28696) +g29666 = AND(g28980, g22498) +g29667 = AND(g2671, g29157) +g29668 = AND(g28527, g14255) +g29683 = AND(g1821, g29046) +g29684 = AND(g1982, g29085) +g29685 = AND(g2084, g28711) +g29686 = AND(g2246, g29057) +g29687 = AND(g2407, g29097) +g29688 = AND(g2509, g28713) +g29693 = AND(g28207, g10233) +g29708 = AND(g1955, g29082) +g29709 = AND(g2116, g29121) +g29710 = AND(g2380, g29094) +g29711 = AND(g2541, g29134) +g29712 = AND(g2643, g28726) +g29718 = AND(g28512, g11136) +g29731 = AND(g2089, g29118) +g29732 = AND(g2514, g29131) +g29733 = AND(g2675, g29157) +g29736 = AND(g28522, g10233) +g29740 = AND(g2648, g29154) +g29742 = AND(g28288, g10233) +g29743 = AND(g28206, g10233) +g29746 = AND(g28279, g20037) +g29747 = AND(g28286, g23196) +g29749 = AND(g28295, g23214) +g29750 = AND(g28296, g23215) +g29751 = AND(g28297, g23216) +g29752 = AND(g28516, g10233) +g29757 = AND(g28305, g23221) +g29758 = AND(g28306, g23222) +g29759 = AND(g28308, g23226) +g29760 = AND(g28309, g23227) +g29761 = AND(g28310, g23228) +g29762 = AND(g28298, g10233) +g29766 = AND(g28316, g23235) +g29767 = AND(g28317, g23236) +g29769 = AND(g28319, g23237) +g29770 = AND(g28320, g23238) +g29771 = AND(g28322, g23242) +g29772 = AND(g28323, g23243) +g29773 = AND(g28203, g10233) +g29774 = AND(g28287, g10233) +g29782 = AND(g28328, g23245) +g29783 = AND(g28329, g23246) +g29784 = AND(g28331, g23247) +g29785 = AND(g28332, g23248) +g29787 = AND(g28334, g23249) +g29788 = AND(g28335, g23250) +g29789 = AND(g28270, g10233) +g29794 = AND(g28342, g23256) +g29795 = AND(g28344, g23257) +g29796 = AND(g28345, g23258) +g29797 = AND(g28347, g23259) +g29798 = AND(g28348, g23260) +g29799 = AND(g28271, g10233) +g29803 = AND(g28414, g26836) +g29804 = AND(g1592, g29014) +g29805 = AND(g28357, g23270) +g29806 = AND(g28358, g23271) +g29807 = AND(g28359, g23272) +g29808 = AND(g28361, g23273) +g29809 = AND(g28362, g23274) +g29810 = AND(g28259, g11317) +g29834 = AND(g28368, g23278) +g29835 = AND(g28326, g24866) +g29836 = AND(g28425, g26841) +g29837 = AND(g28369, g20144) +g29838 = AND(g1636, g29044) +g29839 = AND(g1728, g29045) +g29840 = AND(g2153, g29056) +g29841 = AND(g28371, g23283) +g29842 = AND(g28372, g23284) +g29843 = AND(g28373, g23289) +g29844 = AND(g28374, g23290) +g29845 = AND(g28375, g23291) +g29850 = AND(g28340, g24893) +g29851 = AND(g1668, g29079) +g29852 = AND(g1772, g29080) +g29853 = AND(g1862, g29081) +g29854 = AND(g2197, g29092) +g29855 = AND(g2287, g29093) +g29856 = AND(g28385, g23303) +g29857 = AND(g28386, g23304) +g29858 = AND(g28387, g23306) +g29859 = AND(g28388, g23307) +g29860 = AND(g28389, g23312) +g29861 = AND(g28390, g23313) +g29865 = AND(g1802, g29115) +g29866 = AND(g1906, g29116) +g29867 = AND(g1996, g29117) +g29868 = AND(g2227, g29128) +g29869 = AND(g2331, g29129) +g29870 = AND(g2421, g29130) +g29871 = AND(g28400, g23332) +g29872 = AND(g28401, g23333) +g29874 = AND(g28402, g23336) +g29875 = AND(g28403, g23337) +g29876 = AND(g28404, g23339) +g29877 = AND(g28405, g23340) +g29880 = AND(g1936, g29149) +g29881 = AND(g2040, g29150) +g29882 = AND(g2361, g29151) +g29883 = AND(g2465, g29152) +g29884 = AND(g2555, g29153) +g29885 = AND(g28416, g23350) +g29887 = AND(g28417, g23351) +g29888 = AND(g28418, g23352) +g29890 = AND(g28419, g23355) +g29891 = AND(g28420, g23356) +g29894 = AND(g2070, g29169) +g29895 = AND(g2495, g29170) +g29896 = AND(g2599, g29171) +g29899 = AND(g28428, g23375) +g29901 = AND(g28429, g23376) +g29902 = AND(g28430, g23377) +g29907 = AND(g2629, g29177) +g29909 = AND(g28435, g23388) +g29924 = AND(g13031, g29190) +g29926 = AND(g1604, g28736) +g29937 = AND(g13044, g29196) +g29938 = AND(g23552, g28889) +g29940 = AND(g1740, g28758) +g29943 = AND(g2165, g28765) +g29949 = AND(g23575, g28924) +g29951 = AND(g1874, g28786) +g29952 = AND(g23576, g28939) +g29954 = AND(g2299, g28796) +g29959 = AND(g28953, g12823) +g29962 = AND(g23616, g28959) +g29964 = AND(g2008, g28830) +g29966 = AND(g23617, g28970) +g29968 = AND(g2433, g28843) +g29969 = AND(g28121, g20509) +g29973 = AND(g28981, g9206) +g29974 = AND(g29173, g12914) +g29975 = AND(g28986, g10420) +g29979 = AND(g23655, g28991) +g29982 = AND(g23656, g28998) +g29984 = AND(g2567, g28877) +g29985 = AND(g28127, g20532) +g29986 = AND(g28468, g23473) +g29987 = AND(g29197, g26424, g22763) +g29988 = AND(g29187, g12235) +g29989 = AND(g29006, g10489) +g29990 = AND(g29007, g9239) +g29991 = AND(g29179, g12922) +g29992 = AND(g29012, g10490) +g30000 = AND(g23685, g29029) +g30001 = AND(g28490, g23486) +g30002 = AND(g28481, g23487) +g30003 = AND(g28149, g9021) +g30004 = AND(g28521, g25837) +g30005 = AND(g28230, g24394) +g30006 = AND(g29032, g9259) +g30007 = AND(g29141, g12929) +g30008 = AND(g29191, g12297) +g30009 = AND(g29034, g10518) +g30010 = AND(g29035, g9274) +g30011 = AND(g29183, g12930) +g30015 = AND(g29040, g10519) +g30023 = AND(g28508, g20570) +g30024 = AND(g28497, g23501) +g30025 = AND(g28492, g23502) +g30026 = AND(g28476, g25064) +g30027 = AND(g29104, g12550) +g30028 = AND(g29069, g9311) +g30029 = AND(g29164, g12936) +g30030 = AND(g29198, g12347) +g30031 = AND(g29071, g10540) +g30032 = AND(g29072, g9326) +g30033 = AND(g29189, g12937) +g30034 = AND(g29077, g10541) +g30035 = AND(g22539, g28120) +g30041 = AND(g28511, g23518) +g30042 = AND(g29142, g12601) +g30043 = AND(g29106, g9392) +g30044 = AND(g29174, g12944) +g30045 = AND(g29200, g12419) +g30046 = AND(g29108, g10564) +g30047 = AND(g29109, g9407) +g30048 = AND(g29193, g12945) +g30049 = AND(g13114, g28167) +g30050 = AND(g22545, g28126) +g30051 = AND(g28513, g20604) +g30056 = AND(g29165, g12659) +g30057 = AND(g29144, g9462) +g30058 = AND(g29180, g12950) +g30059 = AND(g28106, g12467) +g30060 = AND(g29146, g10581) +g30061 = AND(g1036, g28188) +g30062 = AND(g13129, g28174) +g30064 = AND(g28517, g20630) +g30066 = AND(g28518, g20636) +g30069 = AND(g29175, g12708) +g30070 = AND(g29167, g9529) +g30071 = AND(g29184, g12975) +g30073 = AND(g1379, g28194) +g30075 = AND(g28525, g20662) +g30078 = AND(g28526, g20667) +g30080 = AND(g28121, g20674) +g30082 = AND(g29181, g12752) +g30083 = AND(g28533, g20698) +g30084 = AND(g28534, g20700) +g30086 = AND(g28536, g20704) +g30089 = AND(g28538, g20709) +g30091 = AND(g28127, g20716) +g30094 = AND(g28544, g20767) +g30095 = AND(g28545, g20768) +g30096 = AND(g28546, g20770) +g30098 = AND(g28548, g20774) +g30099 = AND(g28549, g20776) +g30101 = AND(g28551, g20780) +g30107 = AND(g28560, g20909) +g30108 = AND(g28561, g20910) +g30109 = AND(g28562, g20912) +g30110 = AND(g28564, g20916) +g30111 = AND(g28565, g20917) +g30112 = AND(g28566, g20919) +g30118 = AND(g28574, g21050) +g30120 = AND(g28576, g21051) +g30121 = AND(g28577, g21052) +g30122 = AND(g28578, g21054) +g30124 = AND(g28580, g21055) +g30125 = AND(g28581, g21056) +g30126 = AND(g28582, g21058) +g30131 = AND(g28589, g21178) +g30133 = AND(g28591, g21179) +g30135 = AND(g28592, g21180) +g30137 = AND(g28594, g21181) +g30138 = AND(g28595, g21182) +g30139 = AND(g28596, g21184) +g30140 = AND(g28600, g23749) +g30145 = AND(g28603, g21247) +g30149 = AND(g28605, g21248) +g30151 = AND(g28607, g21249) +g30152 = AND(g28609, g23767) +g30153 = AND(g28610, g23768) +g30154 = AND(g28611, g23769) +g30158 = AND(g28613, g21274) +g30161 = AND(g28614, g21275) +g30164 = AND(g28618, g23787) +g30165 = AND(g28619, g23788) +g30166 = AND(g28621, g23792) +g30167 = AND(g28622, g23793) +g30168 = AND(g28623, g23794) +g30172 = AND(g28625, g21286) +g30173 = AND(g28118, g13082) +g30174 = AND(g28628, g23812) +g30175 = AND(g28629, g23813) +g30177 = AND(g28631, g23814) +g30178 = AND(g28632, g23815) +g30179 = AND(g28634, g23819) +g30180 = AND(g28635, g23820) +g30181 = AND(g28636, g23821) +g30185 = AND(g28640, g23838) +g30186 = AND(g28641, g23839) +g30187 = AND(g28643, g23840) +g30188 = AND(g28644, g23841) +g30190 = AND(g28646, g23842) +g30191 = AND(g28647, g23843) +g30192 = AND(g28649, g23847) +g30193 = AND(g28650, g23848) +g30194 = AND(g28651, g23849) +g30196 = AND(g28659, g23858) +g30197 = AND(g28661, g23859) +g30198 = AND(g28662, g23860) +g30199 = AND(g28664, g23861) +g30200 = AND(g28665, g23862) +g30202 = AND(g28667, g23863) +g30203 = AND(g28668, g23864) +g30204 = AND(g28670, g23868) +g30205 = AND(g28671, g23869) +g30207 = AND(g28680, g23874) +g30208 = AND(g28681, g23875) +g30209 = AND(g28682, g23876) +g30210 = AND(g28684, g23877) +g30211 = AND(g28685, g23878) +g30212 = AND(g28687, g23879) +g30213 = AND(g28688, g23880) +g30215 = AND(g28690, g23881) +g30216 = AND(g28691, g23882) +g30219 = AND(g28698, g23887) +g30220 = AND(g28699, g23888) +g30221 = AND(g28700, g23893) +g30222 = AND(g28701, g23894) +g30223 = AND(g28702, g23895) +g30224 = AND(g28704, g23896) +g30225 = AND(g28705, g23897) +g30226 = AND(g28707, g23898) +g30227 = AND(g28708, g23899) +g30228 = AND(g28715, g23903) +g30229 = AND(g28716, g23904) +g30230 = AND(g28717, g23906) +g30231 = AND(g28718, g23907) +g30232 = AND(g28719, g23912) +g30233 = AND(g28720, g23913) +g30234 = AND(g28721, g23914) +g30235 = AND(g28723, g23915) +g30236 = AND(g28724, g23916) +g30238 = AND(g28727, g23922) +g30239 = AND(g28728, g23923) +g30241 = AND(g28729, g23926) +g30242 = AND(g28730, g23927) +g30243 = AND(g28731, g23929) +g30244 = AND(g28732, g23930) +g30245 = AND(g28733, g23935) +g30246 = AND(g28734, g23936) +g30247 = AND(g28735, g23937) +g30248 = AND(g28743, g23938) +g30250 = AND(g28744, g23939) +g30251 = AND(g28745, g23940) +g30253 = AND(g28746, g23943) +g30254 = AND(g28747, g23944) +g30255 = AND(g28748, g23946) +g30256 = AND(g28749, g23947) +g30257 = AND(g28750, g23952) +g30258 = AND(g28751, g23953) +g30261 = AND(g28772, g23961) +g30263 = AND(g28773, g23962) +g30264 = AND(g28774, g23963) +g30266 = AND(g28775, g23966) +g30267 = AND(g28776, g23967) +g30268 = AND(g28777, g23969) +g30269 = AND(g28778, g23970) +g30272 = AND(g28814, g23982) +g30274 = AND(g28815, g23983) +g30275 = AND(g28816, g23984) +g30277 = AND(g28817, g23987) +g30278 = AND(g28818, g23988) +g30281 = AND(g28850, g23992) +g30283 = AND(g28851, g23993) +g30284 = AND(g28852, g23994) +g30289 = AND(g28884, g24000) +g30308 = AND(g29178, g7004, g5297) +g30315 = AND(g29182, g7028, g5644) +g30316 = AND(g29199, g7097, g6682) +g30564 = AND(g21358, g29385) +g30566 = AND(g26247, g29507) +g30576 = AND(g18898, g29800) +g30577 = AND(g26267, g29679) +g30583 = AND(g19666, g29355) +g30589 = AND(g18898, g29811) +g30590 = AND(g18911, g29812) +g30592 = AND(g30270, g18929) +g30594 = AND(g18898, g29846) +g30595 = AND(g18911, g29847) +g30596 = AND(g30279, g18947) +g30598 = AND(g18898, g29862) +g30599 = AND(g18911, g29863) +g30600 = AND(g30287, g18975) +g30604 = AND(g18911, g29878) +g30607 = AND(g30291, g18989) +g30612 = AND(g26338, g29597) +g30614 = AND(g20154, g29814) +g30670 = AND(g11330, g29359) +g30671 = AND(g29319, g22317) +g30673 = AND(g20175, g29814) +g30730 = AND(g26346, g29778) +g30731 = AND(g11374, g29361) +g30735 = AND(g29814, g22319) +g30825 = AND(g29814, g22332) +g30914 = AND(g29873, g20887) +g30915 = AND(g29886, g24778) +g30918 = AND(g8681, g29707) +g30919 = AND(g29898, g23286) +g30920 = AND(g29889, g21024) +g30921 = AND(g29900, g24789) +g30925 = AND(g29908, g23309) +g30926 = AND(g29903, g21163) +g30927 = AND(g29910, g24795) +g30930 = AND(g29915, g23342) +g30935 = AND(g8808, g29745) +g30936 = AND(g8830, g29916) +g30937 = AND(g22626, g29814) +g30982 = AND(g8895, g29933) +g31015 = AND(g29476, g22758) +g31016 = AND(g29478, g22840) +g31017 = AND(g29479, g22841) +g31018 = AND(g29480, g22855) +g31019 = AND(g29481, g22856) +g31021 = AND(g26025, g29814) +g31066 = AND(g29483, g22865) +g31067 = AND(g29484, g22868) +g31069 = AND(g29793, g14150) +g31070 = AND(g29814, g25985) +g31115 = AND(g29487, g22882) +g31118 = AND(g29490, g22906) +g31120 = AND(g1700, g29976) +g31122 = AND(g12144, g29993) +g31123 = AND(g1834, g29994) +g31124 = AND(g2259, g29997) +g31125 = AND(g29502, g22973) +g31128 = AND(g12187, g30016) +g31129 = AND(g1968, g30017) +g31130 = AND(g12191, g30019) +g31131 = AND(g2393, g30020) +g31132 = AND(g29504, g22987) +g31139 = AND(g12221, g30036) +g31140 = AND(g2102, g30037) +g31141 = AND(g12224, g30038) +g31142 = AND(g2527, g30039) +g31143 = AND(g29506, g22999) +g31145 = AND(g9970, g30052) +g31146 = AND(g12285, g30053) +g31147 = AND(g12286, g30054) +g31148 = AND(g2661, g30055) +g31149 = AND(g29508, g23021) +g31150 = AND(g1682, g30063) +g31151 = AND(g10037, g30065) +g31152 = AND(g10039, g30067) +g31153 = AND(g12336, g30068) +g31154 = AND(g19128, g29814) +g31166 = AND(g1816, g30074) +g31167 = AND(g10080, g30076) +g31168 = AND(g2241, g30077) +g31169 = AND(g10083, g30079) +g31170 = AND(g19128, g29814) +g31182 = AND(g30240, g20682) +g31183 = AND(g30249, g25174) +g31184 = AND(g1950, g30085) +g31185 = AND(g10114, g30087) +g31186 = AND(g2375, g30088) +g31187 = AND(g10118, g30090) +g31188 = AND(g20028, g29653) +g31194 = AND(g19128, g29814) +g31206 = AND(g30260, g23890) +g31207 = AND(g30252, g20739) +g31208 = AND(g30262, g25188) +g31209 = AND(g2084, g30097) +g31210 = AND(g2509, g30100) +g31211 = AND(g10156, g30102) +g31212 = AND(g20028, g29669) +g31218 = AND(g30271, g23909) +g31219 = AND(g30265, g20875) +g31220 = AND(g30273, g25202) +g31222 = AND(g2643, g30113) +g31223 = AND(g20028, g29689) +g31224 = AND(g30280, g23932) +g31225 = AND(g30276, g21012) +g31226 = AND(g30282, g25218) +g31228 = AND(g20028, g29713) +g31229 = AND(g30288, g23949) +g31230 = AND(g30285, g20751) +g31231 = AND(g30290, g25239) +g31232 = AND(g30294, g23972) +g31237 = AND(g29366, g25325) +g31238 = AND(g29583, g20053) +g31240 = AND(g14793, g30206) +g31242 = AND(g29373, g25409) +g31252 = AND(g29643, g20101) +g31261 = AND(g14754, g30259) +g31266 = AND(g30129, g27742) +g31270 = AND(g29692, g23282) +g31271 = AND(g29706, g23300) +g31272 = AND(g30117, g27742) +g31273 = AND(g30143, g27779) +g31275 = AND(g30147, g27800) +g31278 = AND(g29716, g23302) +g31280 = AND(g29717, g23305) +g31281 = AND(g30106, g27742) +g31282 = AND(g30130, g27779) +g31283 = AND(g30156, g27837) +g31285 = AND(g30134, g27800) +g31286 = AND(g30159, g27858) +g31290 = AND(g29734, g23335) +g31292 = AND(g29735, g23338) +g31296 = AND(g30119, g27779) +g31297 = AND(g30144, g27837) +g31298 = AND(g30169, g27886) +g31299 = AND(g30123, g27800) +g31300 = AND(g30148, g27858) +g31301 = AND(g30170, g27907) +g31305 = AND(g29741, g23354) +g31309 = AND(g30132, g27837) +g31310 = AND(g30157, g27886) +g31312 = AND(g30136, g27858) +g31313 = AND(g30160, g27907) +g31314 = AND(g30183, g27937) +g31321 = AND(g30146, g27886) +g31323 = AND(g30150, g27907) +g31324 = AND(g30171, g27937) +g31327 = AND(g19200, g29814) +g31374 = AND(g29748, g23390) +g31376 = AND(g24952, g29814) +g31467 = AND(g30162, g27937) +g31470 = AND(g29753, g23398) +g31471 = AND(g29754, g23399) +g31475 = AND(g29756, g23406) +g31477 = AND(g29763, g23409) +g31478 = AND(g29764, g23410) +g31480 = AND(g1644, g30296) +g31481 = AND(g29768, g23417) +g31484 = AND(g29775, g23418) +g31485 = AND(g29776, g23421) +g31486 = AND(g29777, g23422) +g31488 = AND(g1779, g30302) +g31489 = AND(g2204, g30305) +g31490 = AND(g29786, g23429) +g31492 = AND(g29790, g23431) +g31493 = AND(g29791, g23434) +g31494 = AND(g29792, g23435) +g31495 = AND(g1913, g30309) +g31496 = AND(g2338, g30312) +g31497 = AND(g20041, g29930) +g31499 = AND(g29801, g23446) +g31500 = AND(g29802, g23449) +g31501 = AND(g2047, g29310) +g31502 = AND(g2472, g29311) +g31503 = AND(g20041, g29945) +g31504 = AND(g29370, g10553) +g31505 = AND(g30195, g24379) +g31508 = AND(g29813, g23459) +g31513 = AND(g2606, g29318) +g31514 = AND(g20041, g29956) +g31516 = AND(g29848, g23476) +g31517 = AND(g29849, g23482) +g31518 = AND(g20041, g29970) +g31519 = AND(g29864, g23490) +g31520 = AND(g29879, g23507) +g31523 = AND(g7528, g29333) +g31524 = AND(g29897, g20593) +g31525 = AND(g29892, g23526) +g31526 = AND(g22521, g29342) +g31527 = AND(g7553, g29343) +g31528 = AND(g19050, g29814) +g31540 = AND(g29904, g23548) +g31541 = AND(g22536, g29348) +g31542 = AND(g19050, g29814) +g31554 = AND(g19050, g29814) +g31566 = AND(g19050, g29814) +g31579 = AND(g19128, g29814) +g31654 = AND(g29325, g13062) +g31672 = AND(g29814, g19050) +g31707 = AND(g30081, g23886) +g31710 = AND(g29814, g19128) +g31744 = AND(g30092, g23902) +g31746 = AND(g30093, g23905) +g31750 = AND(g30103, g23925) +g31752 = AND(g30104, g23928) +g31756 = AND(g30114, g23942) +g31758 = AND(g30115, g23945) +g31759 = AND(g21291, g29385) +g31763 = AND(g30127, g23965) +g31765 = AND(g30128, g23968) +g31769 = AND(g30141, g23986) +g31776 = AND(g21329, g29385) +g31777 = AND(g21343, g29385) +g31778 = AND(g21369, g29385) +g31780 = AND(g30163, g23999) +g31784 = AND(g30176, g24003) +g31786 = AND(g30189, g24010) +g31787 = AND(g21281, g29385) +g31788 = AND(g21352, g29385) +g31789 = AND(g30201, g24013) +g31790 = AND(g21299, g29385) +g31792 = AND(g30214, g24017) +g31933 = AND(g939, g30735) +g31934 = AND(g31670, g18827) +g31936 = AND(g31213, g24005) +g31940 = AND(g943, g30735) +g31941 = AND(g1283, g30825) +g31943 = AND(g4717, g30614) +g31944 = AND(g31745, g22146) +g31948 = AND(g30670, g18884) +g31949 = AND(g1287, g30825) +g31959 = AND(g4907, g30673) +g31960 = AND(g31749, g22153) +g31961 = AND(g31751, g22154) +g31962 = AND(g8033, g31013) +g31963 = AND(g30731, g18895) +g31966 = AND(g31754, g22166) +g31967 = AND(g31755, g22167) +g31968 = AND(g31757, g22168) +g31969 = AND(g31189, g22139) +g31974 = AND(g31760, g22176) +g31975 = AND(g31761, g22177) +g31976 = AND(g31762, g22178) +g31977 = AND(g31764, g22179) +g31985 = AND(g4722, g30614) +g31986 = AND(g31766, g22197) +g31987 = AND(g31767, g22198) +g31988 = AND(g31768, g22199) +g31989 = AND(g31770, g22200) +g31990 = AND(g31772, g18945) +g31991 = AND(g4912, g30673) +g31992 = AND(g31773, g22213) +g31993 = AND(g31774, g22214) +g31994 = AND(g31775, g22215) +g31995 = AND(g28274, g30569) +g31996 = AND(g31779, g18979) +g32008 = AND(g31781, g22223) +g32009 = AND(g31782, g22224) +g32010 = AND(g31785, g22303) +g32011 = AND(g8287, g31134) +g32012 = AND(g8297, g31233) +g32013 = AND(g8673, g30614) +g32014 = AND(g8715, g30673) +g32016 = AND(g8522, g31138) +g32018 = AND(g4146, g30937) +g32019 = AND(g30579, g22358) +g32020 = AND(g4157, g30937) +g32028 = AND(g30569, g29339) +g32029 = AND(g31318, g16482) +g32030 = AND(g4172, g30937) +g32031 = AND(g31372, g13464) +g32032 = AND(g31373, g16515) +g32034 = AND(g14124, g31239) +g32035 = AND(g4176, g30937) +g32036 = AND(g31469, g13486) +g32039 = AND(g31476, g20070) +g32040 = AND(g14122, g31243) +g32041 = AND(g13913, g31262) +g32042 = AND(g27244, g31070) +g32043 = AND(g31482, g16173) +g32044 = AND(g31483, g20085) +g32045 = AND(g31491, g16187) +g32046 = AND(g10925, g30735) +g32047 = AND(g27248, g31070) +g32048 = AND(g31498, g13869) +g32049 = AND(g10902, g30735) +g32050 = AND(g11003, g30825) +g32051 = AND(g31506, g10831) +g32052 = AND(g31507, g13885) +g32053 = AND(g14176, g31509) +g32054 = AND(g10890, g30735) +g32055 = AND(g10999, g30825) +g32056 = AND(g27271, g31021) +g32067 = AND(g4727, g30614) +g32068 = AND(g31515, g10862) +g32069 = AND(g10878, g30735) +g32070 = AND(g10967, g30825) +g32071 = AND(g27236, g31070) +g32082 = AND(g4917, g30673) +g32083 = AND(g947, g30735) +g32084 = AND(g10948, g30825) +g32085 = AND(g27253, g31021) +g32086 = AND(g7597, g30735) +g32087 = AND(g1291, g30825) +g32088 = AND(g27241, g31070) +g32089 = AND(g27261, g31021) +g32095 = AND(g7619, g30825) +g32096 = AND(g31601, g29893) +g32097 = AND(g25960, g31021) +g32098 = AND(g4732, g30614) +g32103 = AND(g31609, g29905) +g32104 = AND(g31616, g29906) +g32105 = AND(g4922, g30673) +g32106 = AND(g31601, g29911) +g32107 = AND(g31624, g29912) +g32108 = AND(g31631, g29913) +g32109 = AND(g31609, g29920) +g32110 = AND(g31639, g29921) +g32111 = AND(g31616, g29922) +g32112 = AND(g31646, g29923) +g32113 = AND(g31601, g29925) +g32114 = AND(g31624, g29927) +g32115 = AND(g31631, g29928) +g32116 = AND(g31658, g29929) +g32119 = AND(g31609, g29939) +g32120 = AND(g31639, g29941) +g32121 = AND(g31616, g29942) +g32122 = AND(g31646, g29944) +g32126 = AND(g31601, g29948) +g32127 = AND(g31624, g29950) +g32128 = AND(g31631, g29953) +g32129 = AND(g31658, g29955) +g32139 = AND(g31601, g29960) +g32140 = AND(g31609, g29961) +g32141 = AND(g31639, g29963) +g32142 = AND(g31616, g29965) +g32143 = AND(g31646, g29967) +g32145 = AND(g31609, g29977) +g32146 = AND(g31624, g29978) +g32147 = AND(g31616, g29980) +g32148 = AND(g31631, g29981) +g32149 = AND(g31658, g29983) +g32150 = AND(g31624, g29995) +g32151 = AND(g31639, g29996) +g32152 = AND(g31631, g29998) +g32153 = AND(g31646, g29999) +g32154 = AND(g31277, g14184) +g32156 = AND(g31639, g30018) +g32157 = AND(g31646, g30021) +g32158 = AND(g31658, g30022) +g32159 = AND(g31658, g30040) +g32160 = AND(g31001, g22995) +g32161 = AND(g3151, g31154) +g32162 = AND(g31002, g23014) +g32163 = AND(g3502, g31170) +g32164 = AND(g30733, g25171) +g32165 = AND(g31669, g27742) +g32166 = AND(g31007, g23029) +g32167 = AND(g3853, g31194) +g32168 = AND(g30597, g25185) +g32169 = AND(g31014, g23046) +g32170 = AND(g31671, g27779) +g32171 = AND(g31706, g27800) +g32172 = AND(g2767, g31608) +g32173 = AND(g160, g31134) +g32174 = AND(g31708, g27837) +g32175 = AND(g31709, g27858) +g32176 = AND(g2779, g31623) +g32177 = AND(g30608, g25214) +g32178 = AND(g31747, g27886) +g32179 = AND(g31748, g27907) +g32180 = AND(g2791, g31638) +g32181 = AND(g31020, g19912) +g32182 = AND(g31753, g27937) +g32183 = AND(g2795, g31653) +g32184 = AND(g30611, g25249) +g32187 = AND(g30672, g25287) +g32188 = AND(g27586, g31376) +g32189 = AND(g30824, g25369) +g32190 = AND(g142, g31233) +g32191 = AND(g27593, g31376) +g32193 = AND(g30732, g25410) +g32194 = AND(g30601, g28436) +g32195 = AND(g30734, g25451) +g32196 = AND(g27587, g31376) +g32197 = AND(g31144, g20088) +g32198 = AND(g4253, g31327) +g32199 = AND(g30916, g25506) +g32200 = AND(g27468, g31376) +g32203 = AND(g4249, g31327) +g32204 = AND(g4245, g31327) +g32205 = AND(g30922, g28463) +g32206 = AND(g30609, g25524) +g32207 = AND(g31221, g23323) +g32224 = AND(g4300, g31327) +g32232 = AND(g31241, g20266) +g32234 = AND(g31601, g30292) +g32241 = AND(g31244, g20323) +g32242 = AND(g31245, g20324) +g32244 = AND(g31609, g30297) +g32246 = AND(g31246, g20326) +g32248 = AND(g31616, g30299) +g32254 = AND(g31247, g20379) +g32255 = AND(g31248, g20381) +g32256 = AND(g31249, g20382) +g32258 = AND(g31624, g30303) +g32260 = AND(g31250, g20385) +g32261 = AND(g31251, g20386) +g32263 = AND(g31631, g30306) +g32265 = AND(g2799, g30567) +g32269 = AND(g31253, g20443) +g32270 = AND(g31254, g20444) +g32272 = AND(g31639, g30310) +g32273 = AND(g31255, g20446) +g32274 = AND(g31256, g20447) +g32276 = AND(g31646, g30313) +g32278 = AND(g2811, g30572) +g32281 = AND(g31257, g20500) +g32282 = AND(g31258, g20503) +g32283 = AND(g31259, g20506) +g32284 = AND(g31260, g20507) +g32286 = AND(g31658, g29312) +g32287 = AND(g2823, g30578) +g32290 = AND(g31267, g20525) +g32291 = AND(g31268, g20527) +g32292 = AND(g31269, g20530) +g32293 = AND(g2827, g30593) +g32295 = AND(g27931, g31376) +g32300 = AND(g31274, g20544) +g32301 = AND(g31276, g20547) +g32302 = AND(g31279, g23485) +g32303 = AND(g27550, g31376) +g32304 = AND(g31284, g20564) +g32305 = AND(g31287, g20567) +g32306 = AND(g31289, g23499) +g32307 = AND(g31291, g23500) +g32308 = AND(g31293, g23503) +g32309 = AND(g5160, g31528) +g32310 = AND(g27577, g31376) +g32311 = AND(g31295, g20582) +g32312 = AND(g31302, g20591) +g32313 = AND(g31303, g23515) +g32314 = AND(g31304, g23516) +g32315 = AND(g31306, g23517) +g32316 = AND(g31307, g23522) +g32317 = AND(g5507, g31542) +g32321 = AND(g27613, g31376) +g32322 = AND(g31308, g20605) +g32323 = AND(g31311, g20610) +g32324 = AND(g31315, g23537) +g32325 = AND(g31316, g23538) +g32326 = AND(g31317, g23539) +g32327 = AND(g31319, g23544) +g32328 = AND(g5853, g31554) +g32330 = AND(g31320, g20631) +g32331 = AND(g31322, g20637) +g32332 = AND(g31325, g23558) +g32333 = AND(g31326, g23559) +g32334 = AND(g31375, g23568) +g32335 = AND(g6199, g31566) +g32336 = AND(g31596, g11842) +g32337 = AND(g31465, g20663) +g32338 = AND(g31466, g20668) +g32339 = AND(g31474, g20672) +g32340 = AND(g31468, g23585) +g32341 = AND(g31472, g23610) +g32342 = AND(g6545, g31579) +g32343 = AND(g31473, g20710) +g32345 = AND(g2138, g31672) +g32348 = AND(g2145, g31672) +g32350 = AND(g2697, g31710) +g32356 = AND(g2704, g31710) +g32369 = AND(g2130, g31672) +g32376 = AND(g2689, g31710) +g32396 = AND(g4698, g30983) +g32397 = AND(g31068, g15830) +g32400 = AND(g4743, g30989) +g32401 = AND(g31116, g13432) +g32402 = AND(g4888, g30990) +g32403 = AND(g31117, g15842) +g32409 = AND(g4754, g30996) +g32410 = AND(g4933, g30997) +g32411 = AND(g31119, g13469) +g32412 = AND(g4765, g30998) +g32413 = AND(g31121, g19518) +g32414 = AND(g4944, g30999) +g32418 = AND(g31126, g16239) +g32419 = AND(g4955, g31000) +g32420 = AND(g31127, g19533) +g32425 = AND(g31668, g21604) +g32428 = AND(g31133, g16261) +g33071 = AND(g31591, g32404) +g33073 = AND(g32386, g18828) +g33074 = AND(g32387, g18830) +g33081 = AND(g32388, g18875) +g33082 = AND(g32389, g18877) +g33086 = AND(g32390, g18887) +g33087 = AND(g32391, g18888) +g33091 = AND(g32392, g18897) +g33099 = AND(g32395, g18944) +g33101 = AND(g32398, g18976) +g33102 = AND(g32399, g18978) +g33104 = AND(g26296, g32137) +g33105 = AND(g26298, g32138) +g33106 = AND(g32408, g18990) +g33110 = AND(g32404, g32415) +g33111 = AND(g24005, g32421) +g33113 = AND(g31964, g22339) +g33114 = AND(g22139, g31945) +g33121 = AND(g8748, g32212) +g33122 = AND(g8859, g32192) +g33124 = AND(g8945, g32296) +g33126 = AND(g9044, g32201) +g33186 = AND(g32037, g22830) +g33233 = AND(g32094, g23005) +g33237 = AND(g32394, g25198) +g33239 = AND(g32117, g19902) +g33241 = AND(g32173, g23128) +g33242 = AND(g32123, g19931) +g33243 = AND(g32124, g19947) +g33244 = AND(g32190, g23152) +g33245 = AND(g32125, g19961) +g33247 = AND(g32130, g19980) +g33248 = AND(g32131, g19996) +g33249 = AND(g32144, g20026) +g33252 = AND(g32155, g20064) +g33263 = AND(g32393, g25481) +g33264 = AND(g31965, g21306) +g33269 = AND(g31970, g15582) +g33304 = AND(g32427, g31971) +g33305 = AND(g31935, g17811) +g33311 = AND(g31942, g12925) +g33322 = AND(g32202, g20450) +g33327 = AND(g32208, g20561) +g33328 = AND(g32209, g20584) +g33329 = AND(g32210, g20585) +g33330 = AND(g32211, g20588) +g33331 = AND(g32216, g20607) +g33332 = AND(g32217, g20608) +g33333 = AND(g32218, g20612) +g33334 = AND(g32219, g20613) +g33338 = AND(g32220, g20633) +g33339 = AND(g32221, g20634) +g33340 = AND(g32222, g20639) +g33341 = AND(g32223, g20640) +g33342 = AND(g32226, g20660) +g33343 = AND(g32227, g20665) +g33344 = AND(g32228, g20670) +g33345 = AND(g32229, g20671) +g33349 = AND(g32233, g20699) +g33350 = AND(g32235, g20702) +g33351 = AND(g32236, g20707) +g33352 = AND(g32237, g20712) +g33353 = AND(g32240, g20732) +g33355 = AND(g32243, g20769) +g33356 = AND(g32245, g20772) +g33357 = AND(g32247, g20775) +g33358 = AND(g32249, g20778) +g33359 = AND(g32252, g20853) +g33360 = AND(g32253, g20869) +g33361 = AND(g32257, g20911) +g33362 = AND(g32259, g20914) +g33363 = AND(g32262, g20918) +g33364 = AND(g32264, g20921) +g33365 = AND(g32267, g20994) +g33366 = AND(g32268, g21010) +g33367 = AND(g32271, g21053) +g33368 = AND(g32275, g21057) +g33369 = AND(g32277, g21060) +g33370 = AND(g32279, g21139) +g33371 = AND(g32280, g21155) +g33372 = AND(g32285, g21183) +g33373 = AND(g32288, g21205) +g33374 = AND(g32289, g21221) +g33376 = AND(g32294, g21268) +g33379 = AND(g30984, g32364) +g33381 = AND(g11842, g32318) +g33392 = AND(g32344, g21362) +g33399 = AND(g32346, g21379) +g33400 = AND(g32347, g21380) +g33401 = AND(g32349, g21381) +g33402 = AND(g32351, g21395) +g33403 = AND(g32352, g21396) +g33404 = AND(g32353, g21397) +g33405 = AND(g32354, g21398) +g33406 = AND(g32355, g21399) +g33407 = AND(g32357, g21406) +g33408 = AND(g32358, g21407) +g33409 = AND(g32359, g21408) +g33410 = AND(g32360, g21409) +g33411 = AND(g32361, g21410) +g33412 = AND(g32362, g21411) +g33414 = AND(g32367, g21421) +g33415 = AND(g32368, g21422) +g33416 = AND(g32370, g21423) +g33417 = AND(g32371, g21424) +g33418 = AND(g32372, g21425) +g33420 = AND(g32373, g21454) +g33421 = AND(g32374, g21455) +g33422 = AND(g32375, g21456) +g33423 = AND(g32225, g29657) +g33425 = AND(g32380, g21466) +g33428 = AND(g32230, g29672) +g33429 = AND(g32231, g29676) +g33431 = AND(g32364, g32377) +g33433 = AND(g32238, g29694) +g33434 = AND(g32239, g29702) +g33440 = AND(g32250, g29719) +g33441 = AND(g32251, g29722) +g33446 = AND(g32385, g21607) +g33450 = AND(g32266, g29737) +I31001 = AND(g29385, g32456, g32457, g32458) +I31002 = AND(g32459, g32460, g32461, g32462) +g33461 = AND(g32463, I31001, I31002) +I31006 = AND(g31376, g31796, g32464, g32465) +I31007 = AND(g32466, g32467, g32468, g32469) +g33462 = AND(g32470, I31006, I31007) +I31011 = AND(g30735, g31797, g32471, g32472) +I31012 = AND(g32473, g32474, g32475, g32476) +g33463 = AND(g32477, I31011, I31012) +I31016 = AND(g30825, g31798, g32478, g32479) +I31017 = AND(g32480, g32481, g32482, g32483) +g33464 = AND(g32484, I31016, I31017) +I31021 = AND(g31070, g31799, g32485, g32486) +I31022 = AND(g32487, g32488, g32489, g32490) +g33465 = AND(g32491, I31021, I31022) +I31026 = AND(g31194, g31800, g32492, g32493) +I31027 = AND(g32494, g32495, g32496, g32497) +g33466 = AND(g32498, I31026, I31027) +I31031 = AND(g30614, g31801, g32499, g32500) +I31032 = AND(g32501, g32502, g32503, g32504) +g33467 = AND(g32505, I31031, I31032) +I31036 = AND(g30673, g31802, g32506, g32507) +I31037 = AND(g32508, g32509, g32510, g32511) +g33468 = AND(g32512, I31036, I31037) +I31041 = AND(g31566, g31803, g32513, g32514) +I31042 = AND(g32515, g32516, g32517, g32518) +g33469 = AND(g32519, I31041, I31042) +I31046 = AND(g29385, g32521, g32522, g32523) +I31047 = AND(g32524, g32525, g32526, g32527) +g33470 = AND(g32528, I31046, I31047) +I31051 = AND(g31376, g31804, g32529, g32530) +I31052 = AND(g32531, g32532, g32533, g32534) +g33471 = AND(g32535, I31051, I31052) +I31056 = AND(g30735, g31805, g32536, g32537) +I31057 = AND(g32538, g32539, g32540, g32541) +g33472 = AND(g32542, I31056, I31057) +I31061 = AND(g30825, g31806, g32543, g32544) +I31062 = AND(g32545, g32546, g32547, g32548) +g33473 = AND(g32549, I31061, I31062) +I31066 = AND(g31070, g31807, g32550, g32551) +I31067 = AND(g32552, g32553, g32554, g32555) +g33474 = AND(g32556, I31066, I31067) +I31071 = AND(g31170, g31808, g32557, g32558) +I31072 = AND(g32559, g32560, g32561, g32562) +g33475 = AND(g32563, I31071, I31072) +I31076 = AND(g30614, g31809, g32564, g32565) +I31077 = AND(g32566, g32567, g32568, g32569) +g33476 = AND(g32570, I31076, I31077) +I31081 = AND(g30673, g31810, g32571, g32572) +I31082 = AND(g32573, g32574, g32575, g32576) +g33477 = AND(g32577, I31081, I31082) +I31086 = AND(g31554, g31811, g32578, g32579) +I31087 = AND(g32580, g32581, g32582, g32583) +g33478 = AND(g32584, I31086, I31087) +I31091 = AND(g29385, g32586, g32587, g32588) +I31092 = AND(g32589, g32590, g32591, g32592) +g33479 = AND(g32593, I31091, I31092) +I31096 = AND(g31376, g31812, g32594, g32595) +I31097 = AND(g32596, g32597, g32598, g32599) +g33480 = AND(g32600, I31096, I31097) +I31101 = AND(g30735, g31813, g32601, g32602) +I31102 = AND(g32603, g32604, g32605, g32606) +g33481 = AND(g32607, I31101, I31102) +I31106 = AND(g30825, g31814, g32608, g32609) +I31107 = AND(g32610, g32611, g32612, g32613) +g33482 = AND(g32614, I31106, I31107) +I31111 = AND(g31070, g31815, g32615, g32616) +I31112 = AND(g32617, g32618, g32619, g32620) +g33483 = AND(g32621, I31111, I31112) +I31116 = AND(g31154, g31816, g32622, g32623) +I31117 = AND(g32624, g32625, g32626, g32627) +g33484 = AND(g32628, I31116, I31117) +I31121 = AND(g30614, g31817, g32629, g32630) +I31122 = AND(g32631, g32632, g32633, g32634) +g33485 = AND(g32635, I31121, I31122) +I31126 = AND(g30673, g31818, g32636, g32637) +I31127 = AND(g32638, g32639, g32640, g32641) +g33486 = AND(g32642, I31126, I31127) +I31131 = AND(g31542, g31819, g32643, g32644) +I31132 = AND(g32645, g32646, g32647, g32648) +g33487 = AND(g32649, I31131, I31132) +I31136 = AND(g29385, g32651, g32652, g32653) +I31137 = AND(g32654, g32655, g32656, g32657) +g33488 = AND(g32658, I31136, I31137) +I31141 = AND(g31376, g31820, g32659, g32660) +I31142 = AND(g32661, g32662, g32663, g32664) +g33489 = AND(g32665, I31141, I31142) +I31146 = AND(g30735, g31821, g32666, g32667) +I31147 = AND(g32668, g32669, g32670, g32671) +g33490 = AND(g32672, I31146, I31147) +I31151 = AND(g30825, g31822, g32673, g32674) +I31152 = AND(g32675, g32676, g32677, g32678) +g33491 = AND(g32679, I31151, I31152) +I31156 = AND(g31070, g31823, g32680, g32681) +I31157 = AND(g32682, g32683, g32684, g32685) +g33492 = AND(g32686, I31156, I31157) +I31161 = AND(g30614, g31824, g32687, g32688) +I31162 = AND(g32689, g32690, g32691, g32692) +g33493 = AND(g32693, I31161, I31162) +I31166 = AND(g30673, g31825, g32694, g32695) +I31167 = AND(g32696, g32697, g32698, g32699) +g33494 = AND(g32700, I31166, I31167) +I31171 = AND(g31528, g31826, g32701, g32702) +I31172 = AND(g32703, g32704, g32705, g32706) +g33495 = AND(g32707, I31171, I31172) +I31176 = AND(g31579, g31827, g32708, g32709) +I31177 = AND(g32710, g32711, g32712, g32713) +g33496 = AND(g32714, I31176, I31177) +I31181 = AND(g29385, g32716, g32717, g32718) +I31182 = AND(g32719, g32720, g32721, g32722) +g33497 = AND(g32723, I31181, I31182) +I31186 = AND(g31376, g31828, g32724, g32725) +I31187 = AND(g32726, g32727, g32728, g32729) +g33498 = AND(g32730, I31186, I31187) +I31191 = AND(g30735, g31829, g32731, g32732) +I31192 = AND(g32733, g32734, g32735, g32736) +g33499 = AND(g32737, I31191, I31192) +I31196 = AND(g30825, g31830, g32738, g32739) +I31197 = AND(g32740, g32741, g32742, g32743) +g33500 = AND(g32744, I31196, I31197) +I31201 = AND(g31672, g31831, g32745, g32746) +I31202 = AND(g32747, g32748, g32749, g32750) +g33501 = AND(g32751, I31201, I31202) +I31206 = AND(g31710, g31832, g32752, g32753) +I31207 = AND(g32754, g32755, g32756, g32757) +g33502 = AND(g32758, I31206, I31207) +I31211 = AND(g31021, g31833, g32759, g32760) +I31212 = AND(g32761, g32762, g32763, g32764) +g33503 = AND(g32765, I31211, I31212) +I31216 = AND(g30937, g31834, g32766, g32767) +I31217 = AND(g32768, g32769, g32770, g32771) +g33504 = AND(g32772, I31216, I31217) +I31221 = AND(g31327, g31835, g32773, g32774) +I31222 = AND(g32775, g32776, g32777, g32778) +g33505 = AND(g32779, I31221, I31222) +I31226 = AND(g29385, g32781, g32782, g32783) +I31227 = AND(g32784, g32785, g32786, g32787) +g33506 = AND(g32788, I31226, I31227) +I31231 = AND(g31376, g31836, g32789, g32790) +I31232 = AND(g32791, g32792, g32793, g32794) +g33507 = AND(g32795, I31231, I31232) +I31236 = AND(g30735, g31837, g32796, g32797) +I31237 = AND(g32798, g32799, g32800, g32801) +g33508 = AND(g32802, I31236, I31237) +I31241 = AND(g30825, g31838, g32803, g32804) +I31242 = AND(g32805, g32806, g32807, g32808) +g33509 = AND(g32809, I31241, I31242) +I31246 = AND(g31672, g31839, g32810, g32811) +I31247 = AND(g32812, g32813, g32814, g32815) +g33510 = AND(g32816, I31246, I31247) +I31251 = AND(g31710, g31840, g32817, g32818) +I31252 = AND(g32819, g32820, g32821, g32822) +g33511 = AND(g32823, I31251, I31252) +I31256 = AND(g31021, g31841, g32824, g32825) +I31257 = AND(g32826, g32827, g32828, g32829) +g33512 = AND(g32830, I31256, I31257) +I31261 = AND(g30937, g31842, g32831, g32832) +I31262 = AND(g32833, g32834, g32835, g32836) +g33513 = AND(g32837, I31261, I31262) +I31266 = AND(g31327, g31843, g32838, g32839) +I31267 = AND(g32840, g32841, g32842, g32843) +g33514 = AND(g32844, I31266, I31267) +I31271 = AND(g29385, g32846, g32847, g32848) +I31272 = AND(g32849, g32850, g32851, g32852) +g33515 = AND(g32853, I31271, I31272) +I31276 = AND(g31376, g31844, g32854, g32855) +I31277 = AND(g32856, g32857, g32858, g32859) +g33516 = AND(g32860, I31276, I31277) +I31281 = AND(g30735, g31845, g32861, g32862) +I31282 = AND(g32863, g32864, g32865, g32866) +g33517 = AND(g32867, I31281, I31282) +I31286 = AND(g30825, g31846, g32868, g32869) +I31287 = AND(g32870, g32871, g32872, g32873) +g33518 = AND(g32874, I31286, I31287) +I31291 = AND(g31021, g31847, g32875, g32876) +I31292 = AND(g32877, g32878, g32879, g32880) +g33519 = AND(g32881, I31291, I31292) +I31296 = AND(g30937, g31848, g32882, g32883) +I31297 = AND(g32884, g32885, g32886, g32887) +g33520 = AND(g32888, I31296, I31297) +I31301 = AND(g31327, g31849, g32889, g32890) +I31302 = AND(g32891, g32892, g32893, g32894) +g33521 = AND(g32895, I31301, I31302) +I31306 = AND(g30614, g31850, g32896, g32897) +I31307 = AND(g32898, g32899, g32900, g32901) +g33522 = AND(g32902, I31306, I31307) +I31311 = AND(g30673, g31851, g32903, g32904) +I31312 = AND(g32905, g32906, g32907, g32908) +g33523 = AND(g32909, I31311, I31312) +I31316 = AND(g29385, g32911, g32912, g32913) +I31317 = AND(g32914, g32915, g32916, g32917) +g33524 = AND(g32918, I31316, I31317) +I31321 = AND(g31376, g31852, g32919, g32920) +I31322 = AND(g32921, g32922, g32923, g32924) +g33525 = AND(g32925, I31321, I31322) +I31326 = AND(g30735, g31853, g32926, g32927) +I31327 = AND(g32928, g32929, g32930, g32931) +g33526 = AND(g32932, I31326, I31327) +I31331 = AND(g30825, g31854, g32933, g32934) +I31332 = AND(g32935, g32936, g32937, g32938) +g33527 = AND(g32939, I31331, I31332) +I31336 = AND(g31672, g31855, g32940, g32941) +I31337 = AND(g32942, g32943, g32944, g32945) +g33528 = AND(g32946, I31336, I31337) +I31341 = AND(g31710, g31856, g32947, g32948) +I31342 = AND(g32949, g32950, g32951, g32952) +g33529 = AND(g32953, I31341, I31342) +I31346 = AND(g31021, g31857, g32954, g32955) +I31347 = AND(g32956, g32957, g32958, g32959) +g33530 = AND(g32960, I31346, I31347) +I31351 = AND(g30937, g31858, g32961, g32962) +I31352 = AND(g32963, g32964, g32965, g32966) +g33531 = AND(g32967, I31351, I31352) +I31356 = AND(g31327, g31859, g32968, g32969) +I31357 = AND(g32970, g32971, g32972, g32973) +g33532 = AND(g32974, I31356, I31357) +g33639 = AND(g33386, g18829) +g33640 = AND(g33387, g18831) +g33646 = AND(g33389, g18876) +g33647 = AND(g33390, g18878) +g33652 = AND(g33393, g18889) +g33657 = AND(g30991, g33443) +g33674 = AND(g33164, g10710, g22319) +g33675 = AND(g33164, g10727, g22332) +g33676 = AND(g33125, g7970) +g33677 = AND(g33443, g31937) +g33678 = AND(g33149, g10710, g22319) +g33680 = AND(g33128, g4688) +g33681 = AND(g33129, g7991) +g33683 = AND(g33149, g10727, g22332) +g33684 = AND(g33139, g13565) +g33687 = AND(g33132, g4878) +g33689 = AND(g33144, g11006) +g33690 = AND(g33146, g16280) +g33693 = AND(g33145, g13594) +g33697 = AND(g33160, g13330) +g33700 = AND(g33148, g11012) +g33701 = AND(g33162, g16305) +g33704 = AND(g33176, g10710, g22319) +g33707 = AND(g33174, g13346) +g33710 = AND(g14037, g33246) +g33711 = AND(g33176, g10727, g22332) +g33715 = AND(g33135, g19416) +g33717 = AND(g14092, g33306) +g33718 = AND(g33147, g19432) +g33719 = AND(g33141, g19433) +g33720 = AND(g33161, g19439) +g33721 = AND(g33163, g19440) +g33722 = AND(g33175, g19445) +g33723 = AND(g14091, g33299) +g33724 = AND(g14145, g33258) +g33725 = AND(g22626, g10851, g33176) +g33727 = AND(g33115, g19499) +g33728 = AND(g22626, g10851, g33187) +g33730 = AND(g7202, g4621, g33127, g4633) +g33731 = AND(g33116, g19520) +I31593 = AND(g31003, g8350, g7788) +g33734 = AND(g7806, g33136, I31593) +g33735 = AND(g33118, g19553) +I31600 = AND(g31009, g8400, g7809) +g33742 = AND(g7828, g33142, I31600) +g33743 = AND(g33119, g19574) +g33758 = AND(g33133, g20269) +g33759 = AND(g33123, g22847) +g33760 = AND(g33143, g20328) +g33784 = AND(g33107, g20531) +g33785 = AND(g33100, g20550) +g33786 = AND(g33130, g20572) +g33787 = AND(g33103, g20595) +g33789 = AND(g33159, g23022) +g33790 = AND(g33108, g20643) +g33795 = AND(g33138, g20782) +g33796 = AND(g33117, g25267) +g33798 = AND(g33227, g20058) +g33801 = AND(g33437, g25327) +g33802 = AND(g33097, g14545) +g33803 = AND(g33231, g20071) +g33805 = AND(g33232, g20079) +g33807 = AND(g33112, g25452) +g33808 = AND(g33109, g22161) +g33809 = AND(g33432, g30184) +g33810 = AND(g33427, g12768) +g33811 = AND(g33439, g17573) +g33812 = AND(g23088, g33187, g9104) +g33814 = AND(g33098, g28144) +g33815 = AND(g33449, g12911) +g33816 = AND(g33234, g20096) +g33817 = AND(g33235, g20102) +g33818 = AND(g33236, g20113) +g33819 = AND(g23088, g33176, g9104) +g33820 = AND(g33075, g26830) +g33821 = AND(g33238, g20153) +g33822 = AND(g33385, g20157) +g33828 = AND(g33090, g24411) +g33829 = AND(g33240, g20164) +g33830 = AND(g33382, g20166) +g33831 = AND(g23088, g33149, g9104) +g33832 = AND(g33088, g27991) +g33833 = AND(g33093, g25852) +g33834 = AND(g33095, g29172) +g33835 = AND(g4340, g33413) +g33836 = AND(g33096, g27020) +g33837 = AND(g33251, g20233) +g33840 = AND(g33253, g20267) +g33841 = AND(g33254, g20268) +g33842 = AND(g33255, g20322) +g33843 = AND(g33256, g20325) +g33844 = AND(g33257, g20327) +g33846 = AND(g33259, g20380) +g33847 = AND(g33260, g20383) +g33848 = AND(g33261, g20384) +g33849 = AND(g33262, g20387) +g33855 = AND(g33265, g20441) +g33856 = AND(g33266, g20442) +g33857 = AND(g33267, g20445) +g33858 = AND(g33268, g20448) +g33859 = AND(g33426, g10531) +g33860 = AND(g33270, g20501) +g33861 = AND(g33271, g20502) +g33862 = AND(g33272, g20504) +g33863 = AND(g33273, g20505) +g33864 = AND(g33274, g20524) +g33865 = AND(g33275, g20526) +g33866 = AND(g33276, g20528) +g33867 = AND(g33277, g20529) +g33868 = AND(g33278, g20542) +g33869 = AND(g33279, g20543) +g33870 = AND(g33280, g20545) +g33871 = AND(g33281, g20546) +g33872 = AND(g33282, g20548) +g33873 = AND(g33291, g20549) +g33876 = AND(g33286, g20562) +g33877 = AND(g33287, g20563) +g33878 = AND(g33288, g20565) +g33879 = AND(g33289, g20566) +g33880 = AND(g33290, g20568) +g33881 = AND(g33292, g20586) +g33882 = AND(g33293, g20587) +g33883 = AND(g33294, g20589) +g33884 = AND(g33295, g20590) +g33885 = AND(g33296, g20609) +g33886 = AND(g33297, g20614) +g33887 = AND(g33298, g20615) +g33889 = AND(g33303, g20641) +g33890 = AND(g33310, g20659) +g33892 = AND(g33312, g20701) +g33893 = AND(g33313, g20706) +g33896 = AND(g33314, g20771) +g33897 = AND(g33315, g20777) +g33898 = AND(g33419, g15655) +g33899 = AND(g32132, g33335) +g33900 = AND(g33316, g20913) +g33901 = AND(g33317, g20920) +g33902 = AND(g33085, g13202) +g33903 = AND(g33447, g19146) +g33904 = AND(g33321, g21059) +g33905 = AND(g33089, g15574) +g33906 = AND(g33084, g22311) +g33907 = AND(g23088, g33219, g9104) +g33908 = AND(g33092, g18935) +g33909 = AND(g33131, g10708) +g33910 = AND(g33134, g7836) +g33911 = AND(g33137, g10725) +g33913 = AND(g23088, g33204, g9104) +g33915 = AND(g33140, g7846) +g33919 = AND(g33438, g10795) +g33921 = AND(g33187, g9104, g19200) +g33922 = AND(g33448, g7202) +g33924 = AND(g33335, g33346) +g33927 = AND(g33094, g21412) +g33941 = AND(g33380, g21560) +g33942 = AND(g33383, g21608) +g33943 = AND(g33384, g21609) +g34045 = AND(g33766, g22942) +g34050 = AND(g33772, g22942) +g34054 = AND(g33778, g22942) +g34061 = AND(g33800, g23076) +g34063 = AND(g33806, g23121) +g34065 = AND(g33813, g23148) +g34066 = AND(g33730, g19352) +g34069 = AND(g8774, g33797) +g34071 = AND(g8854, g33799) +g34072 = AND(g33839, g24872) +g34073 = AND(g8948, g33823) +g34074 = AND(g33685, g19498) +g34075 = AND(g33692, g19517) +g34076 = AND(g33694, g19519) +g34077 = AND(g22957, g9104, g33736) +g34078 = AND(g33699, g19531) +g34079 = AND(g33703, g19532) +g34080 = AND(g22957, g9104, g33750) +g34081 = AND(g33706, g19552) +g34082 = AND(g33709, g19554) +g34083 = AND(g33714, g19573) +g34084 = AND(g9214, g33851) +g34085 = AND(g33761, g9104, g18957) +g34086 = AND(g20114, g33766, g9104) +g34087 = AND(g33766, g9104, g18957) +g34088 = AND(g33736, g9104, g18957) +g34089 = AND(g22957, g9104, g33744) +g34091 = AND(g22957, g9104, g33761) +g34092 = AND(g33750, g9104, g18957) +g34093 = AND(g20114, g33755, g9104) +g34096 = AND(g22957, g9104, g33772) +g34097 = AND(g33772, g9104, g18957) +g34098 = AND(g33744, g9104, g18957) +g34102 = AND(g33912, g23599) +g34104 = AND(g33916, g23639) +g34105 = AND(g33778, g9104, g18957) +g34106 = AND(g33917, g23675) +g34108 = AND(g22957, g9104, g33766) +g34109 = AND(g33918, g23708) +g34110 = AND(g33732, g22935) +g34111 = AND(g33733, g22936) +g34112 = AND(g22957, g9104, g33778) +g34113 = AND(g33734, g19744) +g34114 = AND(g33920, g23742) +g34115 = AND(g20516, g9104, g33750) +g34116 = AND(g33933, g25140) +g34117 = AND(g33742, g19755) +g34119 = AND(g20516, g9104, g33755) +g34120 = AND(g33930, g25158) +g34133 = AND(g33845, g23958) +g34135 = AND(g33926, g23802) +g34136 = AND(g33850, g23293) +g34137 = AND(g33928, g23802) +g34138 = AND(g33929, g23828) +g34139 = AND(g33827, g23314) +g34140 = AND(g33931, g23802) +g34141 = AND(g33932, g23828) +g34143 = AND(g33934, g23828) +g34146 = AND(g33788, g20091) +g34157 = AND(g33794, g20159) +g34169 = AND(g33804, g31227) +g34171 = AND(g33925, g24360) +g34173 = AND(g33679, g24368) +g34178 = AND(g33712, g24361) +g34179 = AND(g33686, g24372) +g34180 = AND(g33716, g24373) +g34182 = AND(g33691, g24384) +g34183 = AND(g33695, g24385) +g34184 = AND(g33698, g24388) +g34185 = AND(g33702, g24389) +g34186 = AND(g33705, g24396) +g34187 = AND(g33708, g24397) +g34191 = AND(g33713, g24404) +g34196 = AND(g33682, g24485) +g34198 = AND(g33688, g24491) +g34203 = AND(g33726, g24537) +g34205 = AND(g33729, g24541) +g34211 = AND(g33891, g21349) +g34212 = AND(g33761, g22689) +g34213 = AND(g33766, g22689) +g34214 = AND(g33772, g22689) +g34215 = AND(g33778, g22670) +g34216 = AND(g33778, g22689) +g34217 = AND(g33736, g22876) +g34218 = AND(g33744, g22670) +g34219 = AND(g33736, g22942) +g34223 = AND(g33744, g22876) +g34224 = AND(g33736, g22670) +g34225 = AND(g33744, g22942) +g34226 = AND(g33914, g21467) +g34228 = AND(g33750, g22942) +g34230 = AND(g33761, g22942) +g34279 = AND(g34231, g19208) +g34281 = AND(g34043, g19276) +g34284 = AND(g34046, g19351) +g34287 = AND(g11370, g34124) +g34291 = AND(g34055, g19366) +g34295 = AND(g34057, g19370) +g34298 = AND(g8679, g34132) +g34301 = AND(g34064, g19415) +g34309 = AND(g13947, g34147) +g34310 = AND(g14003, g34162) +g34319 = AND(g9535, g34156) +g34322 = AND(g14188, g34174) +g34324 = AND(g14064, g34161) +g34329 = AND(g14511, g34181) +g34333 = AND(g9984, g34192) +g34334 = AND(g34090, g19865) +g34335 = AND(g8461, g34197) +g34337 = AND(g34095, g19881) +g34338 = AND(g34099, g19905) +g34340 = AND(g34100, g19950) +g34341 = AND(g34101, g19952) +g34342 = AND(g34103, g19998) +g34344 = AND(g34107, g20038) +g34348 = AND(g34125, g20128) +g34363 = AND(g34148, g20389) +g34364 = AND(g34048, g24366) +g34365 = AND(g34149, g20451) +g34367 = AND(g7404, g34042) +g34370 = AND(g34067, g10554) +g34371 = AND(g7450, g34044) +g34375 = AND(g13077, g34049) +g34378 = AND(g13095, g34053) +g34380 = AND(g34158, g20571) +g34381 = AND(g34166, g20594) +g34382 = AND(g34167, g20618) +g34385 = AND(g34168, g20642) +g34386 = AND(g10800, g34060) +g34388 = AND(g10802, g34062) +g34389 = AND(g34170, g20715) +g34390 = AND(g34172, g21069) +g34393 = AND(g34189, g21304) +g34394 = AND(g34190, g21305) +g34395 = AND(g34193, g21336) +g34396 = AND(g34194, g21337) +g34397 = AND(g7673, g34068) +g34398 = AND(g7684, g34070) +g34401 = AND(g34199, g21383) +g34410 = AND(g34204, g21427) +g34413 = AND(g34094, g22670) +g34414 = AND(g34206, g21457) +g34415 = AND(g34207, g21458) +g34470 = AND(g7834, g34325) +g34474 = AND(g20083, g34326) +g34475 = AND(g27450, g34327) +g34476 = AND(g34399, g18891) +g34477 = AND(g26344, g34328) +g34478 = AND(g34402, g18904) +g34479 = AND(g34403, g18905) +g34481 = AND(g34404, g18916) +g34482 = AND(g34405, g18917) +g34483 = AND(g34406, g18938) +g34484 = AND(g34407, g18939) +g34485 = AND(g34411, g18952) +g34486 = AND(g34412, g18953) +g34487 = AND(g34416, g18983) +g34488 = AND(g34417, g18988) +g34489 = AND(g34421, g19068) +g34492 = AND(g34272, g33430) +g34493 = AND(g34273, g19360) +g34495 = AND(g34274, g19365) +g34497 = AND(g34275, g33072) +g34498 = AND(g13888, g34336) +g34499 = AND(g31288, g34339) +g34500 = AND(g34276, g30568) +g34502 = AND(g26363, g34343) +g34503 = AND(g34278, g19437) +g34506 = AND(g8833, g34354) +g34507 = AND(g34280, g19454) +g34508 = AND(g34282, g19472) +g34509 = AND(g34283, g19473) +g34513 = AND(g9003, g34346) +g34514 = AND(g34286, g19480) +g34515 = AND(g34288, g19491) +g34516 = AND(g34289, g19492) +g34517 = AND(g34290, g19493) +g34518 = AND(g34292, g19503) +g34519 = AND(g34293, g19504) +g34520 = AND(g34294, g19505) +g34523 = AND(g9162, g34351) +g34524 = AND(g9083, g34359) +g34525 = AND(g34297, g19528) +g34526 = AND(g34300, g19569) +g34527 = AND(g34303, g19603) +g34528 = AND(g34305, g19617) +g34529 = AND(g34306, g19634) +g34532 = AND(g34314, g19710) +g34533 = AND(g34318, g19731) +g34534 = AND(g34321, g19743) +g34538 = AND(g34330, g20054) +g34541 = AND(g34331, g20087) +g34542 = AND(g34332, g20089) +g34554 = AND(g34347, g20495) +g34555 = AND(g34349, g20512) +g34556 = AND(g34350, g20537) +g34557 = AND(g34352, g20555) +g34558 = AND(g34353, g20578) +g34560 = AND(g34366, g17366) +g34561 = AND(g34368, g17410) +g34562 = AND(g34369, g17411) +g34563 = AND(g34372, g17465) +g34564 = AND(g34373, g17466) +g34565 = AND(g34374, g17471) +g34566 = AND(g34376, g17489) +g34567 = AND(g34377, g17491) +g34568 = AND(g34379, g17512) +g34571 = AND(g27225, g34299) +g34572 = AND(g34387, g33326) +g34577 = AND(g24577, g34307) +g34578 = AND(g24578, g34308) +g34580 = AND(g29539, g34311) +g34581 = AND(g22864, g34312) +g34582 = AND(g7764, g34313) +g34584 = AND(g24653, g34315) +g34585 = AND(g24705, g34316) +g34586 = AND(g11025, g34317) +g34588 = AND(g26082, g34323) +g34655 = AND(g34573, g18885) +g34658 = AND(g34574, g18896) +g34661 = AND(g34575, g18907) +g34662 = AND(g34576, g18931) +g34665 = AND(g34583, g19067) +g34666 = AND(g34587, g19144) +g34667 = AND(g34471, g33424) +g34678 = AND(g34490, g19431) +g34679 = AND(g14093, g34539) +g34681 = AND(g34491, g19438) +g34684 = AND(g14178, g34545) +g34685 = AND(g14164, g34550) +g34686 = AND(g34494, g19494) +g34687 = AND(g14181, g34543) +g34694 = AND(g34530, g19885) +g34696 = AND(g34531, g20004) +g34700 = AND(g34535, g20129) +g34701 = AND(g34536, g20179) +g34702 = AND(g34537, g20208) +g34706 = AND(g34496, g10570) +g34707 = AND(g34544, g20579) +g34709 = AND(g34549, g17242) +g34710 = AND(g34553, g20903) +g34715 = AND(g34570, g33375) +g34738 = AND(g34660, g33442) +g34740 = AND(g34664, g19414) +g34741 = AND(g8899, g34697) +g34742 = AND(g9000, g34698) +g34743 = AND(g8951, g34703) +g34744 = AND(g34668, g19481) +g34745 = AND(g34669, g19482) +g34746 = AND(g34670, g19526) +g34747 = AND(g34671, g19527) +g34748 = AND(g34672, g19529) +g34750 = AND(g34673, g19542) +g34751 = AND(g34674, g19543) +g34752 = AND(g34675, g19544) +g34753 = AND(g34676, g19586) +g34754 = AND(g34677, g19602) +g34756 = AND(g34680, g19618) +g34757 = AND(g34682, g19635) +g34758 = AND(g34683, g19657) +g34763 = AND(g34689, g19915) +g34764 = AND(g34691, g20009) +g34765 = AND(g34692, g20057) +g34771 = AND(g34693, g20147) +g34774 = AND(g34695, g20180) +g34782 = AND(g34711, g33888) +g34811 = AND(g14165, g34766) +g34841 = AND(g34761, g20080) +g34842 = AND(g34762, g20168) +g34857 = AND(g16540, g34813) +g34858 = AND(g16540, g34816) +g34859 = AND(g16540, g34820) +g34860 = AND(g16540, g34823) +g34861 = AND(g16540, g34827) +g34862 = AND(g16540, g34830) +g34863 = AND(g16540, g34833) +g34865 = AND(g16540, g34836) +g34866 = AND(g34819, g20106) +g34867 = AND(g34826, g20145) +g34868 = AND(g34813, g19866) +g34869 = AND(g34816, g19869) +g34870 = AND(g34820, g19882) +g34871 = AND(g34823, g19908) +g34872 = AND(g34827, g19954) +g34873 = AND(g34830, g20046) +g34874 = AND(g34833, g20060) +g34875 = AND(g34836, g20073) +g34876 = AND(g34844, g20534) +g34909 = AND(g34856, g20130) +g34948 = AND(g16540, g34935) +g34953 = AND(g34935, g19957) +g34955 = AND(g34931, g34320) +g34961 = AND(g34944, g23019) +g34962 = AND(g34945, g23020) +g34963 = AND(g34946, g23041) +g34964 = AND(g34947, g23060) +g34965 = AND(g34949, g23084) +g34966 = AND(g34950, g23170) +g34967 = AND(g34951, g23189) +g34968 = AND(g34952, g23203) +g34969 = AND(g34960, g19570) +g34999 = AND(g34998, g23085) + +g7404 = OR(g933, g939) +g7450 = OR(g1277, g1283) +g7673 = OR(g4153, g4172) +g7684 = OR(g4072, g4176) +g7764 = OR(g2999, g2932) +g7834 = OR(g2886, g2946) +g7932 = OR(g4072, g4153) +I12583 = OR(g1157, g1239, g990) +g8417 = OR(g1056, g1116, I12583) +g8461 = OR(g301, g534) +I12611 = OR(g1500, g1582, g1333) +g8476 = OR(g1399, g1459, I12611) +g8679 = OR(g222, g199) +I12782 = OR(g4188, g4194, g4197, g4200) +I12783 = OR(g4204, g4207, g4210, g4180) +g8790 = OR(I12782, I12783) +g8863 = OR(g1644, g1664) +g8904 = OR(g1779, g1798) +g8905 = OR(g2204, g2223) +I12902 = OR(g4235, g4232, g4229, g4226) +I12903 = OR(g4222, g4219, g4216, g4213) +g8921 = OR(I12902, I12903) +g8956 = OR(g1913, g1932) +g8957 = OR(g2338, g2357) +g9012 = OR(g2047, g2066) +g9013 = OR(g2472, g2491) +g9055 = OR(g2606, g2625) +g9483 = OR(g1008, g969) +g9535 = OR(g209, g538) +g9536 = OR(g1351, g1312) +g9984 = OR(g4300, g4242) +g10589 = OR(g7223, g7201) +g10800 = OR(g7517, g952) +g10802 = OR(g7533, g1296) +g11025 = OR(g2980, g7831) +g11370 = OR(g8807, g550) +g11372 = OR(g490, g482, g8038) +g11380 = OR(g8583, g8530) +g11737 = OR(g8359, g8292) +g12768 = OR(g7785, g7202) +g12832 = OR(g10347, g10348) +g12911 = OR(g10278, g12768) +g12925 = OR(g8928, g10511) +g12954 = OR(g12186, g9906) +g12981 = OR(g12219, g9967) +g12982 = OR(g12220, g9968) +g13006 = OR(g12284, g10034) +g13077 = OR(g11330, g943) +g13091 = OR(g329, g319, g10796) +g13095 = OR(g11374, g1287) +g13155 = OR(g11496, g11546) +g13211 = OR(g11294, g7567) +g13242 = OR(g11336, g7601) +g13289 = OR(g10619, g10624) +g13295 = OR(g10625, g10655) +g13296 = OR(g10626, g10657) +g13300 = OR(g10656, g10676) +g13385 = OR(g11967, g9479) +g13526 = OR(g209, g10685, g301) +g13540 = OR(g10822, g10827) +g13543 = OR(g10543, g10565) +g13570 = OR(g9223, g11130) +g13597 = OR(g9247, g11149) +g13623 = OR(g482, g12527) +g13657 = OR(g7251, g10616) +g13660 = OR(g8183, g12527) +g13662 = OR(g10896, g10917) +g13699 = OR(g10921, g10947) +g13728 = OR(g6804, g12527) +g13761 = OR(g490, g12527) +g13762 = OR(g499, g12527) +g13794 = OR(g7396, g10684) +g13820 = OR(g11184, g9187, g12527) +g13858 = OR(g209, g10685) +g13888 = OR(g2941, g11691) +g13914 = OR(g8643, g11380) +g13938 = OR(g11213, g11191) +g13941 = OR(g11019, g11023) +g13969 = OR(g11448, g8913) +g13972 = OR(g11232, g11203) +g13973 = OR(g11024, g11028) +g13997 = OR(g11029, g11036) +g14030 = OR(g11037, g11046) +g14044 = OR(g10776, g8703) +g14062 = OR(g11047, g11116) +g14078 = OR(g10776, g8703) +g14119 = OR(g10776, g8703) +g14182 = OR(g11741, g11721, g753) +g14187 = OR(g8871, g11771) +g14309 = OR(g10320, g11048) +g14387 = OR(g9086, g11048) +g14511 = OR(g10685, g546) +g14583 = OR(g10685, g542) +g14844 = OR(g10776, g8703) +g14888 = OR(g10776, g8703) +g14936 = OR(g10776, g8703) +g14977 = OR(g10776, g8703) +g15017 = OR(g10776, g8703) +g15124 = OR(g13605, g4581) +g15125 = OR(g10363, g13605) +g15582 = OR(g8977, g12925) +g15727 = OR(g13383, g13345, g13333, g11010) +g15732 = OR(g13411, g13384, g13349, g11016) +g15789 = OR(g10819, g13211) +g15792 = OR(g12920, g10501) +g15800 = OR(g10821, g13242) +g15803 = OR(g12924, g10528) +g15910 = OR(g13025, g10654) +g15935 = OR(g13029, g10665) +g15965 = OR(g13035, g10675) +g15968 = OR(g13038, g10677) +g16021 = OR(g13047, g10706) +g16022 = OR(g13048, g10707) +g16052 = OR(g13060, g10724) +g16076 = OR(g13081, g10736) +g16173 = OR(g8796, g13464) +g16187 = OR(g8822, g13486) +g16239 = OR(g7892, g13432) +g16258 = OR(g13247, g10856) +g16261 = OR(g7898, g13469) +g16430 = OR(g182, g13657) +g16448 = OR(g13287, g10934) +g16506 = OR(g13294, g10966) +g16800 = OR(g13436, g11027) +g16810 = OR(g13461, g11032) +g16811 = OR(g8690, g13914) +g16839 = OR(g13473, g11035) +g16866 = OR(g13492, g11044) +g16867 = OR(g13493, g11045) +g16876 = OR(g14028, g11773, g11755) +g16882 = OR(g13508, g11114) +g16883 = OR(g13509, g11115) +g16926 = OR(g14061, g11804, g11780) +g16927 = OR(g13524, g11126) +g16928 = OR(g13525, g11127) +g16959 = OR(g13542, g11142) +g16970 = OR(g13567, g11163) +g17264 = OR(g7118, g14309) +g17268 = OR(g9220, g14387) +I18385 = OR(g14413, g14391, g14360) +g17464 = OR(g14334, g14313, g11935, I18385) +I18417 = OR(g14444, g14414, g14392) +g17488 = OR(g14361, g14335, g11954, I18417) +I18421 = OR(g14447, g14417, g14395) +g17490 = OR(g14364, g14337, g11958, I18421) +I18449 = OR(g14512, g14445, g14415) +g17510 = OR(g14393, g14362, g11972, I18449) +I18452 = OR(g14514, g14448, g14418) +g17511 = OR(g14396, g14365, g11976, I18452) +I18492 = OR(g14538, g14513, g14446) +g17569 = OR(g14416, g14394, g11995, I18492) +I18495 = OR(g14539, g14515, g14449) +g17570 = OR(g14419, g14397, g11999, I18495) +I18543 = OR(g14568, g14540, g14516) +g17594 = OR(g14450, g14420, g12025, I18543) +g18879 = OR(g17365, g14423) +g18994 = OR(g16303, g13632) +g19267 = OR(g17752, g17768) +g19274 = OR(g17753, g14791) +g19336 = OR(g17769, g14831) +g19337 = OR(g17770, g17785) +g19344 = OR(g17771, g14832) +g19356 = OR(g17784, g14874) +g19359 = OR(g17786, g14875) +g19363 = OR(g17810, g14913) +g19441 = OR(g15507, g12931) +g19449 = OR(g15567, g12939) +g19467 = OR(g16896, g14097) +g19475 = OR(g16930, g14126) +g19486 = OR(g15589, g12979) +g19488 = OR(g16965, g14148) +g19501 = OR(g16986, g14168) +g19522 = OR(g17057, g14180) +g19525 = OR(g7696, g16811) +g19534 = OR(g15650, g13019) +g19535 = OR(g15651, g13020) +g19555 = OR(g15672, g13030) +g19557 = OR(g17123, g14190) +g19572 = OR(g17133, g14193) +g19575 = OR(g15693, g13042) +g19576 = OR(g17138, g14202) +g19587 = OR(g15700, g13046) +g19593 = OR(g17145, g14210) +g19595 = OR(g17149, g14218) +g19604 = OR(g15704, g13059) +g19605 = OR(g15707, g13063) +g19619 = OR(g15712, g13080) +g19879 = OR(g15841, g13265) +g19904 = OR(g17636, g14654) +g19949 = OR(g17671, g14681) +g20034 = OR(g15902, g13299) +g20051 = OR(g15936, g13306) +g20063 = OR(g15978, g13313) +g20077 = OR(g16025, g13320) +g20082 = OR(g16026, g13321) +g20083 = OR(g2902, g17058) +g20148 = OR(g16128, g13393) +g20160 = OR(g16163, g13415) +g20169 = OR(g16184, g13460) +g20187 = OR(g16202, g13491) +g20196 = OR(g16207, g13497) +g20202 = OR(g16211, g13507) +g20217 = OR(g16221, g13523) +g20241 = OR(g16233, g13541) +g20276 = OR(g16243, g13566) +g20522 = OR(g691, g16893) +g20905 = OR(g7216, g17264) +g21891 = OR(g19948, g15103) +g21892 = OR(g19788, g15104) +g21893 = OR(g20094, g18655) +g21894 = OR(g20112, g15107) +g21895 = OR(g20135, g15108) +g21896 = OR(g20084, g15110) +g21897 = OR(g20095, g15111) +g21898 = OR(g20152, g15112) +g21899 = OR(g20162, g15113) +g21900 = OR(g20977, g15114) +g21901 = OR(g21251, g15115) +g22152 = OR(g21188, g17469) +g22217 = OR(g21302, g17617) +g22225 = OR(g21332, g17654) +g22226 = OR(g21333, g17655) +g22304 = OR(g21347, g17693) +g22318 = OR(g21394, g17783) +g22331 = OR(g21405, g17809) +g22447 = OR(g21464, g12761) +g22487 = OR(g21512, g12794) +g22490 = OR(g21513, g12795) +g22516 = OR(g21559, g12817) +g22530 = OR(g16751, g20171) +g22531 = OR(g20773, g20922) +g22547 = OR(g16855, g20215) +g22585 = OR(g20915, g21061) +g22591 = OR(g18893, g18909) +g22625 = OR(g18910, g18933) +g22634 = OR(g18934, g15590) +g22636 = OR(g18943, g15611) +g22639 = OR(g18950, g15612) +g22640 = OR(g18951, g15613) +g22641 = OR(g18974, g15631) +g22644 = OR(g18981, g15632) +g22645 = OR(g18982, g15633) +g22648 = OR(g18987, g15652) +g22652 = OR(g18992, g15653) +g22653 = OR(g18993, g15654) +g22659 = OR(g19062, g15673) +g22662 = OR(g19069, g15679) +g22664 = OR(g19139, g15694) +g22669 = OR(g7763, g19525) +g22679 = OR(g19145, g15701) +g22684 = OR(g19206, g15703) +g22707 = OR(g20559, g17156) +g22708 = OR(g19266, g15711) +g22751 = OR(g19333, g15716) +g22832 = OR(g19354, g15722) +g22872 = OR(g19372, g19383) +g22901 = OR(g19384, g15745) +g23087 = OR(g19487, g15852) +g23129 = OR(g19500, g15863) +g23153 = OR(g19521, g15876) +I22267 = OR(g20236, g20133, g20111) +g23162 = OR(g20184, g20170, I22267) +g23171 = OR(g19536, g15903) +g23183 = OR(g19545, g15911) +I22280 = OR(g20271, g20150, g20134) +g23184 = OR(g20198, g20185, I22280) +g23193 = OR(g19556, g15937) +g23194 = OR(g19564, g19578) +g23197 = OR(g19571, g15966) +I22298 = OR(g20371, g20161, g20151) +g23198 = OR(g20214, g20199, I22298) +g23209 = OR(g19585, g19601) +g23217 = OR(g19588, g16023) +g23251 = OR(g19637, g16098) +g23255 = OR(g19655, g16122) +g23261 = OR(g19660, g16125) +g23262 = OR(g19661, g16126) +g23275 = OR(g19680, g16160) +g23276 = OR(g19681, g16161) +g23296 = OR(g19691, g16177) +g23297 = OR(g19692, g16178) +g23298 = OR(g19693, g16179) +g23317 = OR(g19715, g16191) +g23318 = OR(g19716, g16192) +g23319 = OR(g19717, g16193) +g23345 = OR(g19735, g16203) +g23346 = OR(g19736, g16204) +g23358 = OR(g19746, g16212) +g23374 = OR(g19767, g13514) +g23383 = OR(g19756, g16222) +g23405 = OR(g19791, g16245) +g23574 = OR(g20093, g20108) +g23615 = OR(g20109, g20131) +I22830 = OR(g21429, g21338, g21307) +g23687 = OR(g21384, g21363, I22830) +g23716 = OR(g9194, g20905) +g23720 = OR(g20165, g16801) +I22852 = OR(g21459, g21350, g21339) +g23721 = OR(g21401, g21385, I22852) +g23750 = OR(g20174, g16840) +I22880 = OR(g21509, g21356, g21351) +g23751 = OR(g21415, g21402, I22880) +g23770 = OR(g20188, g16868) +I22912 = OR(g21555, g21364, g21357) +g23771 = OR(g21432, g21416, I22912) +g23795 = OR(g20203, g16884) +I22958 = OR(g21603, g21386, g21365) +g23796 = OR(g21462, g21433, I22958) +g23822 = OR(g20218, g16929) +g23825 = OR(g20705, g20781) +g23989 = OR(g20581, g17179) +g23997 = OR(g20602, g17191) +I23162 = OR(g19919, g19968, g20014, g20841) +I23163 = OR(g20982, g21127, g21193, g21256) +g24151 = OR(g18088, g21661) +g24200 = OR(g22831, g18103) +g24201 = OR(g22848, g18104) +g24202 = OR(g22899, g18106) +g24203 = OR(g22982, g18107) +g24204 = OR(g22990, g18108) +g24205 = OR(g23006, g18109) +g24206 = OR(g23386, g18110) +g24207 = OR(g23396, g18119) +g24208 = OR(g23404, g18121) +g24209 = OR(g23415, g18122) +g24210 = OR(g22900, g18125) +g24211 = OR(g23572, g18138) +g24212 = OR(g23280, g18155) +g24213 = OR(g23220, g18186) +g24214 = OR(g23471, g18195) +g24215 = OR(g23484, g18196) +g24216 = OR(g23416, g18197) +g24231 = OR(g22589, g18201) +g24232 = OR(g22686, g18228) +g24233 = OR(g22590, g18236) +g24234 = OR(g22622, g18237) +g24235 = OR(g22632, g18238) +g24236 = OR(g22489, g18241) +g24237 = OR(g22515, g18242) +g24238 = OR(g23254, g18248) +g24239 = OR(g22752, g18250) +g24240 = OR(g22861, g18251) +g24241 = OR(g22920, g18252) +g24242 = OR(g22834, g18253) +g24243 = OR(g22992, g18254) +g24244 = OR(g23349, g18255) +g24245 = OR(g22849, g18256) +g24246 = OR(g23372, g18257) +g24247 = OR(g22623, g18259) +g24248 = OR(g22710, g18286) +g24249 = OR(g22624, g18294) +g24250 = OR(g22633, g18295) +g24251 = OR(g22637, g18296) +g24252 = OR(g22518, g18299) +g24253 = OR(g22525, g18300) +g24254 = OR(g23265, g18306) +g24255 = OR(g22835, g18308) +g24256 = OR(g22873, g18309) +g24257 = OR(g22938, g18310) +g24258 = OR(g22851, g18311) +g24259 = OR(g23008, g18312) +g24260 = OR(g23373, g18313) +g24261 = OR(g22862, g18314) +g24262 = OR(g23387, g18315) +g24263 = OR(g23497, g18529) +g24264 = OR(g22310, g18559) +g24265 = OR(g22316, g18560) +g24266 = OR(g22329, g18561) +g24267 = OR(g23439, g18611) +g24268 = OR(g23025, g18612) +g24269 = OR(g23131, g18613) +g24270 = OR(g23165, g18614) +g24271 = OR(g23451, g18628) +g24272 = OR(g23056, g18629) +g24273 = OR(g23166, g18630) +g24274 = OR(g23187, g18631) +g24275 = OR(g23474, g18645) +g24276 = OR(g23083, g18646) +g24277 = OR(g23188, g18647) +g24278 = OR(g23201, g18648) +g24279 = OR(g23218, g15105) +g24280 = OR(g23292, g15109) +g24281 = OR(g23397, g18656) +g24282 = OR(g23407, g18657) +g24334 = OR(g23991, g18676) +g24335 = OR(g22165, g18678) +g24336 = OR(g24012, g18753) +g24337 = OR(g23540, g18754) +g24338 = OR(g23658, g18755) +g24339 = OR(g23690, g18756) +g24340 = OR(g24016, g18770) +g24341 = OR(g23564, g18771) +g24342 = OR(g23691, g18772) +g24343 = OR(g23724, g18773) +g24344 = OR(g22145, g18787) +g24345 = OR(g23606, g18788) +g24346 = OR(g23725, g18789) +g24347 = OR(g23754, g18790) +g24348 = OR(g22149, g18804) +g24349 = OR(g23646, g18805) +g24350 = OR(g23755, g18806) +g24351 = OR(g23774, g18807) +g24352 = OR(g22157, g18821) +g24353 = OR(g23682, g18822) +g24354 = OR(g23775, g18823) +g24355 = OR(g23799, g18824) +g24363 = OR(g7831, g22138) +g24374 = OR(g19345, g24004) +g24390 = OR(g23779, g21285) +g24398 = OR(g23801, g21296) +g24401 = OR(g23811, g21298) +g24430 = OR(g23151, g8234) +g24432 = OR(g23900, g21361) +g24433 = OR(g10878, g22400) +g24443 = OR(g23917, g21378) +g24444 = OR(g10890, g22400) +g24447 = OR(g10948, g22450) +g24457 = OR(g10902, g22400) +g24460 = OR(g10967, g22450) +g24468 = OR(g10925, g22400) +g24471 = OR(g10999, g22450) +g24478 = OR(g11003, g22450) +g24496 = OR(g24008, g21557) +g24500 = OR(g24011, g21605) +g24510 = OR(g22488, g7567) +g24517 = OR(g22158, g18906) +g24518 = OR(g22517, g7601) +g24557 = OR(g22308, g19207) +I23755 = OR(g22904, g22927, g22980, g23444) +I23756 = OR(g23457, g23480, g23494, g23511) +g24561 = OR(I23755, I23756) +g24565 = OR(g22309, g19275) +g24577 = OR(g2856, g22531) +g24578 = OR(g2882, g23825) +g24580 = OR(g22340, g13096) +g24641 = OR(g22151, g22159) +g24653 = OR(g2848, g22585) +g24705 = OR(g2890, g23267) +g24715 = OR(g22189, g22207) +g24746 = OR(g22588, g19461) +g24782 = OR(g23857, g23872) +g24799 = OR(g23901, g23921) +g24813 = OR(g22685, g19594) +g24821 = OR(g21404, g23990) +g24840 = OR(g21419, g23996) +g24841 = OR(g21420, g23998) +g24842 = OR(g7804, g22669) +g24853 = OR(g21452, g24001) +g24854 = OR(g21453, g24002) +g24879 = OR(g21465, g24009) +g24896 = OR(g22863, g19684) +g24907 = OR(g21558, g24015) +g24919 = OR(g21606, g22143) +g24935 = OR(g22937, g19749) +g24946 = OR(g22360, g22409, g8130) +I24117 = OR(g23088, g23154, g23172) +g24952 = OR(g21326, g21340, I24117) +g24965 = OR(g22667, g23825) +g24968 = OR(g22360, g22409, g23389) +g25010 = OR(g23267, g2932) +g25037 = OR(g23103, g19911) +g25261 = OR(g23348, g20193) +g25539 = OR(g23531, g20628) +g25545 = OR(g23551, g20658) +g25575 = OR(g24139, g24140) +g25576 = OR(g24141, g24142) +g25577 = OR(g24143, g24144) +g25582 = OR(g21662, g24152) +g25583 = OR(g21666, g24153) +g25584 = OR(g21670, g24154) +g25585 = OR(g21674, g24155) +g25586 = OR(g21678, g24156) +g25587 = OR(g21682, g24157) +g25588 = OR(g21686, g24158) +g25589 = OR(g21690, g24159) +g25590 = OR(g21694, g24160) +g25591 = OR(g24642, g21705) +g25592 = OR(g24672, g21706) +g25593 = OR(g24716, g21707) +g25594 = OR(g24772, g21708) +g25595 = OR(g24835, g21717) +g25596 = OR(g24865, g21718) +g25597 = OR(g24892, g21719) +g25598 = OR(g24904, g21720) +g25599 = OR(g24914, g21721) +g25600 = OR(g24650, g18111) +g25601 = OR(g24660, g18112) +g25602 = OR(g24673, g18113) +g25603 = OR(g24698, g18114) +g25604 = OR(g24717, g18115) +g25605 = OR(g24743, g18116) +g25606 = OR(g24761, g18117) +g25607 = OR(g24773, g18118) +g25608 = OR(g24643, g18120) +g25609 = OR(g24915, g18126) +g25610 = OR(g24923, g18127) +g25611 = OR(g24931, g18128) +g25612 = OR(g24941, g18132) +g25613 = OR(g25181, g18140) +g25614 = OR(g24797, g18161) +g25615 = OR(g24803, g18162) +g25616 = OR(g25096, g18172) +g25617 = OR(g25466, g18189) +g25618 = OR(g25491, g18192) +g25619 = OR(g24961, g18193) +g25621 = OR(g24523, g18205) +g25622 = OR(g24546, g18217) +g25623 = OR(g24552, g18219) +g25624 = OR(g24408, g18224) +g25625 = OR(g24553, g18226) +g25626 = OR(g24499, g18235) +g25627 = OR(g24503, g18247) +g25628 = OR(g24600, g18249) +g25629 = OR(g24962, g18258) +g25630 = OR(g24532, g18263) +g25631 = OR(g24554, g18275) +g25632 = OR(g24558, g18277) +g25633 = OR(g24420, g18282) +g25634 = OR(g24559, g18284) +g25635 = OR(g24504, g18293) +g25636 = OR(g24507, g18305) +g25637 = OR(g24618, g18307) +g25638 = OR(g24977, g18316) +g25639 = OR(g25122, g18530) +g25643 = OR(g24602, g21736) +g25644 = OR(g24622, g21737) +g25645 = OR(g24679, g21738) +g25646 = OR(g24706, g21739) +g25647 = OR(g24725, g21740) +g25648 = OR(g24644, g21741) +g25649 = OR(g24654, g21742) +g25650 = OR(g24663, g21743) +g25651 = OR(g24680, g21744) +g25652 = OR(g24777, g21747) +g25653 = OR(g24664, g18602) +g25654 = OR(g24634, g18606) +g25655 = OR(g24645, g18607) +g25656 = OR(g24945, g18609) +g25657 = OR(g24624, g21782) +g25658 = OR(g24635, g21783) +g25659 = OR(g24707, g21784) +g25660 = OR(g24726, g21785) +g25661 = OR(g24754, g21786) +g25662 = OR(g24656, g21787) +g25663 = OR(g24666, g21788) +g25664 = OR(g24681, g21789) +g25665 = OR(g24708, g21790) +g25666 = OR(g24788, g21793) +g25667 = OR(g24682, g18619) +g25668 = OR(g24646, g18623) +g25669 = OR(g24657, g18624) +g25670 = OR(g24967, g18626) +g25671 = OR(g24637, g21828) +g25672 = OR(g24647, g21829) +g25673 = OR(g24727, g21830) +g25674 = OR(g24755, g21831) +g25675 = OR(g24769, g21832) +g25676 = OR(g24668, g21833) +g25677 = OR(g24684, g21834) +g25678 = OR(g24709, g21835) +g25679 = OR(g24728, g21836) +g25680 = OR(g24794, g21839) +g25681 = OR(g24710, g18636) +g25682 = OR(g24658, g18640) +g25683 = OR(g24669, g18641) +g25684 = OR(g24983, g18643) +g25685 = OR(g24476, g21866) +g25686 = OR(g24712, g21881) +g25687 = OR(g24729, g21882) +g25688 = OR(g24812, g21887) +g25689 = OR(g24849, g21888) +g25690 = OR(g24864, g21889) +g25691 = OR(g24536, g21890) +g25693 = OR(g24627, g18707) +g25694 = OR(g24638, g18738) +g25695 = OR(g24998, g21914) +g25696 = OR(g25012, g21915) +g25697 = OR(g25086, g21916) +g25698 = OR(g25104, g21917) +g25699 = OR(g25125, g21918) +g25700 = OR(g25040, g21919) +g25701 = OR(g25054, g21920) +g25702 = OR(g25068, g21921) +g25703 = OR(g25087, g21922) +g25704 = OR(g25173, g21925) +g25705 = OR(g25069, g18744) +g25706 = OR(g25030, g18748) +g25707 = OR(g25041, g18749) +g25708 = OR(g25526, g18751) +g25709 = OR(g25014, g21960) +g25710 = OR(g25031, g21961) +g25711 = OR(g25105, g21962) +g25712 = OR(g25126, g21963) +g25713 = OR(g25147, g21964) +g25714 = OR(g25056, g21965) +g25715 = OR(g25071, g21966) +g25716 = OR(g25088, g21967) +g25717 = OR(g25106, g21968) +g25718 = OR(g25187, g21971) +g25719 = OR(g25089, g18761) +g25720 = OR(g25042, g18765) +g25721 = OR(g25057, g18766) +g25722 = OR(g25530, g18768) +g25723 = OR(g25033, g22006) +g25724 = OR(g25043, g22007) +g25725 = OR(g25127, g22008) +g25726 = OR(g25148, g22009) +g25727 = OR(g25163, g22010) +g25728 = OR(g25076, g22011) +g25729 = OR(g25091, g22012) +g25730 = OR(g25107, g22013) +g25731 = OR(g25128, g22014) +g25732 = OR(g25201, g22017) +g25733 = OR(g25108, g18778) +g25734 = OR(g25058, g18782) +g25735 = OR(g25077, g18783) +g25736 = OR(g25536, g18785) +g25737 = OR(g25045, g22052) +g25738 = OR(g25059, g22053) +g25739 = OR(g25149, g22054) +g25740 = OR(g25164, g22055) +g25741 = OR(g25178, g22056) +g25742 = OR(g25093, g22057) +g25743 = OR(g25110, g22058) +g25744 = OR(g25129, g22059) +g25745 = OR(g25150, g22060) +g25746 = OR(g25217, g22063) +g25747 = OR(g25130, g18795) +g25748 = OR(g25078, g18799) +g25749 = OR(g25094, g18800) +g25750 = OR(g25543, g18802) +g25751 = OR(g25061, g22098) +g25752 = OR(g25079, g22099) +g25753 = OR(g25165, g22100) +g25754 = OR(g25179, g22101) +g25755 = OR(g25192, g22102) +g25756 = OR(g25112, g22103) +g25757 = OR(g25132, g22104) +g25758 = OR(g25151, g22105) +g25759 = OR(g25166, g22106) +g25760 = OR(g25238, g22109) +g25761 = OR(g25152, g18812) +g25762 = OR(g25095, g18816) +g25763 = OR(g25113, g18817) +g25764 = OR(g25551, g18819) +g25767 = OR(g25207, g12015) +g25774 = OR(g25223, g12043) +g25789 = OR(g25285, g14543) +g25791 = OR(g25411, g25371, g25328, g25290) +g25805 = OR(g25453, g25414, g25374, g25331) +g25819 = OR(g25323, g23836) +g25821 = OR(g25482, g25456, g25417, g25377) +g25834 = OR(g25366, g23854) +g25835 = OR(g25367, g23855) +g25836 = OR(g25368, g23856) +g25839 = OR(g25507, g25485, g25459, g25420) +g25856 = OR(g25518, g25510, g25488, g25462) +g25867 = OR(g25449, g23884) +g25868 = OR(g25450, g23885) +g25877 = OR(g25502, g23919) +g25878 = OR(g25503, g23920) +g25885 = OR(g25522, g23957) +g25894 = OR(g24817, g23229) +g25906 = OR(g25559, g24014) +g25910 = OR(g25565, g22142) +g25911 = OR(g22514, g24510) +g25917 = OR(g22524, g24518) +g25929 = OR(g24395, g22193) +g25935 = OR(g24402, g22208) +g25936 = OR(g24403, g22209) +g25937 = OR(g24406, g22216) +g25940 = OR(g24415, g22218) +g25941 = OR(g24416, g22219) +g25942 = OR(g24422, g22298) +g25943 = OR(g24423, g22299) +g25945 = OR(g24427, g22307) +g25960 = OR(g24566, g24678) +g26080 = OR(g19393, g24502) +g26082 = OR(g2898, g24561) +g26089 = OR(g24501, g22534) +g26099 = OR(g24506, g22538) +g26278 = OR(g24545, g24549) +g26293 = OR(g24550, g24555) +g26299 = OR(g24551, g22665) +g26305 = OR(g24556, g24564) +g26327 = OR(g8462, g24591) +g26328 = OR(g1183, g24591) +g26329 = OR(g8526, g24609) +g26334 = OR(g1171, g24591) +g26335 = OR(g1526, g24609) +g26342 = OR(g8407, g24591) +g26343 = OR(g1514, g24609) +g26344 = OR(g2927, g25010) +g26348 = OR(g8466, g24609) +g26349 = OR(g24630, g13409) +g26359 = OR(g24651, g22939) +g26361 = OR(g24674, g22991) +g26363 = OR(g2965, g24965) +g26365 = OR(g25504, g25141) +g26377 = OR(g24700, g23007) +g26386 = OR(g24719, g23023) +g26392 = OR(g24745, g23050) +g26396 = OR(g24762, g23062) +g26422 = OR(g24774, g23104) +g26512 = OR(g24786, g23130) +g26616 = OR(g24881, g24855, g24843, g24822) +g26636 = OR(g24897, g24884, g24858, g24846) +g26657 = OR(g24908, g24900, g24887, g24861) +g26673 = OR(g24433, g10674) +g26690 = OR(g10776, g24433) +g26694 = OR(g24444, g10704) +g26703 = OR(g24447, g10705) +g26721 = OR(g10776, g24444) +g26725 = OR(g24457, g10719) +g26733 = OR(g10776, g24447) +g26737 = OR(g24460, g10720) +g26751 = OR(g24903, g24912) +g26755 = OR(g10776, g24457) +g26759 = OR(g24468, g7511) +g26766 = OR(g10776, g24460) +g26770 = OR(g24471, g10732) +g26781 = OR(g24913, g24921) +g26785 = OR(g10776, g24468) +g26789 = OR(g10776, g24471) +g26793 = OR(g24478, g7520) +g26800 = OR(g24922, g24929) +g26805 = OR(g10776, g24478) +g26809 = OR(g24930, g24939) +g26813 = OR(g24940, g24949) +g26866 = OR(g20204, g20242, g24363) +I25612 = OR(g25567, g25568, g25569, g25570) +I25613 = OR(g25571, g25572, g25573, g25574) +g26874 = OR(I25612, I25613) +g26875 = OR(g21652, g25575) +g26876 = OR(g21655, g25576) +g26877 = OR(g21658, g25577) +g26878 = OR(g25578, g25579) +g26879 = OR(g25580, g25581) +g26880 = OR(g26610, g24186) +g26881 = OR(g26629, g24187) +g26882 = OR(g26650, g24188) +g26883 = OR(g26670, g24189) +g26884 = OR(g26511, g24190) +g26885 = OR(g26541, g24191) +g26886 = OR(g26651, g24192) +g26887 = OR(g26542, g24193) +g26888 = OR(g26671, g24194) +g26889 = OR(g26689, g24195) +g26890 = OR(g26630, g24196) +g26891 = OR(g26652, g24197) +g26892 = OR(g26719, g24198) +g26893 = OR(g26753, g24199) +g26894 = OR(g25979, g18129) +g26895 = OR(g26783, g18148) +g26896 = OR(g26341, g18171) +g26897 = OR(g26611, g18176) +g26898 = OR(g26387, g18194) +g26899 = OR(g26844, g18199) +g26900 = OR(g26819, g24217) +g26901 = OR(g26362, g24218) +g26902 = OR(g26378, g24219) +g26903 = OR(g26388, g24220) +g26904 = OR(g26393, g24221) +g26905 = OR(g26397, g24222) +g26906 = OR(g26423, g24223) +g26907 = OR(g26513, g24224) +g26908 = OR(g26358, g24225) +g26909 = OR(g26543, g24227) +g26910 = OR(g26571, g24228) +g26911 = OR(g26612, g24230) +g26912 = OR(g25946, g18209) +g26913 = OR(g25848, g18225) +g26914 = OR(g25949, g18227) +g26915 = OR(g25900, g18230) +g26916 = OR(g25916, g18232) +g26917 = OR(g26122, g18233) +g26918 = OR(g25931, g18243) +g26919 = OR(g25951, g18267) +g26920 = OR(g25865, g18283) +g26921 = OR(g25955, g18285) +g26922 = OR(g25902, g18288) +g26923 = OR(g25923, g18290) +g26924 = OR(g26153, g18291) +g26925 = OR(g25939, g18301) +g26926 = OR(g26633, g18531) +g26927 = OR(g26711, g18539) +g26928 = OR(g26713, g18541) +g26929 = OR(g26635, g18543) +g26930 = OR(g26799, g18544) +g26931 = OR(g26778, g18547) +g26932 = OR(g26684, g18549) +g26933 = OR(g26808, g18551) +g26934 = OR(g26845, g18556) +g26938 = OR(g26186, g21883) +g26939 = OR(g25907, g21884) +g26940 = OR(g25908, g21886) +g26944 = OR(g26130, g18658) +g26945 = OR(g26379, g24283) +g26946 = OR(g26389, g24284) +g26947 = OR(g26394, g24285) +g26948 = OR(g26399, g24286) +g26949 = OR(g26356, g24287) +g26950 = OR(g26357, g24288) +g26951 = OR(g26390, g24289) +g26952 = OR(g26360, g24290) +g26953 = OR(g26486, g24291) +g26954 = OR(g26380, g24292) +g26955 = OR(g26391, g24293) +g26956 = OR(g26487, g24294) +g26957 = OR(g26517, g24295) +g26958 = OR(g26395, g24297) +g26959 = OR(g26381, g24299) +g26960 = OR(g26258, g24304) +g26961 = OR(g26280, g24306) +g26962 = OR(g26295, g24307) +g26963 = OR(g26306, g24308) +g26964 = OR(g26259, g24316) +g26965 = OR(g26336, g24317) +g26966 = OR(g26345, g24318) +g26967 = OR(g26350, g24319) +g26968 = OR(g26307, g24321) +g26969 = OR(g26313, g24329) +g26970 = OR(g26308, g24332) +g26971 = OR(g26325, g24333) +g26972 = OR(g26780, g25229) +I25736 = OR(g12, g22150, g20277) +g27008 = OR(g26866, g21370, I25736) +g27016 = OR(g26821, g14585) +g27019 = OR(g26822, g14610) +g27024 = OR(g26826, g17692) +g27026 = OR(g26828, g17726) +g27031 = OR(g26213, g26190, g26166, g26148) +g27037 = OR(g26236, g26218, g26195, g26171) +g27108 = OR(g22522, g25911) +g27122 = OR(g22537, g25917) +g27126 = OR(g24378, g25787) +g27133 = OR(g25788, g24392) +g27135 = OR(g24387, g25803) +g27147 = OR(g25802, g24399) +g27150 = OR(g25804, g24400) +g27152 = OR(g24393, g25817) +g27159 = OR(g25814, g12953) +g27179 = OR(g25816, g24409) +g27182 = OR(g25818, g24410) +g27205 = OR(g25833, g24421) +g27224 = OR(g25870, g15678) +g27225 = OR(g2975, g26364) +g27226 = OR(g25872, g24436) +g27231 = OR(g25873, g15699) +g27232 = OR(g25874, g24450) +g27233 = OR(g25876, g24451) +g27236 = OR(g24620, g25974) +g27238 = OR(g25879, g24464) +g27239 = OR(g25881, g24465) +g27240 = OR(g25883, g24467) +g27241 = OR(g24584, g25984) +g27243 = OR(g25884, g24475) +g27244 = OR(g24652, g25995) +g27248 = OR(g24880, g25953) +g27250 = OR(g25901, g15738) +g27253 = OR(g24661, g26052) +g27257 = OR(g25904, g24498) +g27258 = OR(g25905, g15749) +g27261 = OR(g24544, g25996) +g27271 = OR(g24547, g26053) +g27274 = OR(g15779, g25915) +g27278 = OR(g15786, g25921) +g27283 = OR(g25922, g25924) +g27289 = OR(g25925, g25927) +g27290 = OR(g25926, g25928) +g27383 = OR(g24569, g25961) +g27394 = OR(g25957, g24573) +g27403 = OR(g25962, g24581) +g27405 = OR(g24572, g25968) +g27426 = OR(g25967, g24588) +g27429 = OR(g25969, g24589) +g27431 = OR(g24582, g25977) +g27450 = OR(g2917, g26483) +g27453 = OR(g25976, g24606) +g27456 = OR(g25978, g24607) +g27458 = OR(g24590, g25989) +g27484 = OR(g25988, g24628) +g27487 = OR(g25990, g24629) +g27489 = OR(g24608, g26022) +g27506 = OR(g26021, g24639) +g27509 = OR(g26023, g24640) +g27515 = OR(g26051, g13431) +g27524 = OR(g26050, g24649) +g27532 = OR(g16176, g26084) +g27533 = OR(g26078, g24659) +g27542 = OR(g16190, g26094) +g27543 = OR(g26085, g24670) +g27544 = OR(g26087, g24671) +g27551 = OR(g26091, g24675) +g27552 = OR(g26092, g24676) +g27555 = OR(g26095, g24686) +g27556 = OR(g26097, g24687) +g27561 = OR(g26100, g24702) +g27562 = OR(g26102, g24703) +g27563 = OR(g26104, g24704) +g27566 = OR(g26119, g24713) +g27567 = OR(g26121, g24714) +g27569 = OR(g26124, g24721) +g27570 = OR(g26126, g24722) +g27571 = OR(g26127, g24723) +g27572 = OR(g26129, g24724) +g27574 = OR(g26145, g24730) +g27575 = OR(g26147, g24731) +g27578 = OR(g26155, g24747) +g27579 = OR(g26157, g24748) +g27580 = OR(g26159, g24749) +g27581 = OR(g26161, g24750) +g27584 = OR(g26165, g24758) +g27589 = OR(g26177, g24763) +g27590 = OR(g26179, g24764) +g27591 = OR(g26181, g24765) +g27596 = OR(g26207, g24775) +g27663 = OR(g26323, g24820) +g27742 = OR(g17292, g26673) +g27779 = OR(g17317, g26694) +g27800 = OR(g17321, g26703) +g27837 = OR(g17401, g26725) +g27858 = OR(g17405, g26737) +g27886 = OR(g14438, g26759) +g27907 = OR(g17424, g26770) +g27937 = OR(g14506, g26793) +g27970 = OR(g26514, g25050) +g27972 = OR(g26131, g26105) +g27974 = OR(g26544, g25063) +g27980 = OR(g26105, g26131) +g28030 = OR(g24018, g26874) +I26522 = OR(g19890, g19935, g19984, g26365) +I26523 = OR(g20720, g20857, g20998, g21143) +g28041 = OR(g24145, g26878) +g28042 = OR(g24148, g26879) +g28043 = OR(g27323, g21714) +g28044 = OR(g27256, g18130) +g28045 = OR(g27378, g18141) +g28046 = OR(g27667, g18157) +g28047 = OR(g27676, g18160) +g28048 = OR(g27362, g18163) +g28049 = OR(g27684, g18164) +g28050 = OR(g27692, g18165) +g28051 = OR(g27699, g18166) +g28052 = OR(g27710, g18167) +g28053 = OR(g27393, g18168) +g28054 = OR(g27723, g18170) +g28055 = OR(g27560, g18190) +g28056 = OR(g27230, g18210) +g28057 = OR(g27033, g18218) +g28058 = OR(g27235, g18268) +g28059 = OR(g27042, g18276) +g28060 = OR(g27616, g18532) +g28061 = OR(g27287, g21735) +g28062 = OR(g27288, g21746) +g28063 = OR(g27541, g21773) +g28064 = OR(g27298, g21781) +g28065 = OR(g27299, g21792) +g28066 = OR(g27553, g21819) +g28067 = OR(g27309, g21827) +g28068 = OR(g27310, g21838) +g28069 = OR(g27564, g21865) +g28070 = OR(g27050, g21867) +g28071 = OR(g27085, g21873) +g28072 = OR(g27086, g21874) +g28073 = OR(g27097, g21875) +g28074 = OR(g27119, g21876) +g28075 = OR(g27083, g21877) +g28076 = OR(g27098, g21878) +g28077 = OR(g27120, g21879) +g28078 = OR(g27140, g21880) +g28082 = OR(g27369, g24315) +g28083 = OR(g27249, g18689) +g28084 = OR(g27254, g18698) +g28085 = OR(g27263, g18700) +g28086 = OR(g27268, g18702) +g28087 = OR(g27255, g18720) +g28088 = OR(g27264, g18729) +g28089 = OR(g27269, g18731) +g28090 = OR(g27275, g18733) +g28091 = OR(g27665, g21913) +g28092 = OR(g27666, g21924) +g28093 = OR(g27981, g21951) +g28094 = OR(g27673, g21959) +g28095 = OR(g27674, g21970) +g28096 = OR(g27988, g21997) +g28097 = OR(g27682, g22005) +g28098 = OR(g27683, g22016) +g28099 = OR(g27992, g22043) +g28100 = OR(g27690, g22051) +g28101 = OR(g27691, g22062) +g28102 = OR(g27995, g22089) +g28103 = OR(g27696, g22097) +g28104 = OR(g27697, g22108) +g28105 = OR(g27997, g22135) +g28118 = OR(g27821, g26815) +g28132 = OR(g27932, g27957) +g28134 = OR(g27958, g27962) +g28135 = OR(g27959, g27963) +g28138 = OR(g27964, g27968) +I26643 = OR(g27073, g27058, g27045, g27040) +I26644 = OR(g27057, g27044, g27039, g27032) +g28140 = OR(I26643, I26644) +g28172 = OR(g27469, g27440, g27416, g27395) +g28179 = OR(g27494, g27474, g27445, g27421) +g28180 = OR(g20242, g27511) +g28186 = OR(g27209, g27185, g27161, g27146) +g28188 = OR(g22535, g27108) +g28191 = OR(g27217, g27210, g27186, g27162) +g28194 = OR(g22540, g27122) +g28208 = OR(g27025, g27028) +g28209 = OR(g27223, g27141) +g28211 = OR(g27029, g27034) +g28212 = OR(g27030, g27035) +g28216 = OR(g27036, g27043) +I26741 = OR(g22881, g22905, g22928, g27402) +I26742 = OR(g23430, g23445, g23458, g23481) +g28220 = OR(g23495, I26741, I26742) +g28230 = OR(g27669, g14261) +g28279 = OR(g27087, g25909) +g28286 = OR(g27090, g15757) +g28295 = OR(g27094, g15783) +g28296 = OR(g27095, g15784) +g28297 = OR(g27096, g15785) +g28305 = OR(g27103, g15793) +g28306 = OR(g27104, g15794) +g28308 = OR(g27105, g15795) +g28309 = OR(g27106, g15796) +g28310 = OR(g27107, g15797) +g28316 = OR(g27113, g15804) +g28317 = OR(g27114, g15805) +g28319 = OR(g27115, g15807) +g28320 = OR(g27116, g15808) +g28322 = OR(g27117, g15809) +g28323 = OR(g27118, g15810) +g28328 = OR(g27127, g15812) +g28329 = OR(g27128, g15813) +g28331 = OR(g27129, g15814) +g28332 = OR(g27130, g15815) +g28334 = OR(g27131, g15817) +g28335 = OR(g27132, g15818) +g28342 = OR(g27134, g15819) +g28344 = OR(g27136, g15820) +g28345 = OR(g27137, g15821) +g28347 = OR(g27138, g15822) +g28348 = OR(g27139, g15823) +g28357 = OR(g27148, g15836) +g28358 = OR(g27149, g15837) +g28359 = OR(g27151, g15838) +g28361 = OR(g27153, g15839) +g28362 = OR(g27154, g15840) +g28368 = OR(g27158, g27184) +g28369 = OR(g27160, g25938) +g28371 = OR(g27177, g15847) +g28372 = OR(g27178, g15848) +g28373 = OR(g27180, g15849) +g28374 = OR(g27181, g15850) +g28375 = OR(g27183, g15851) +g28385 = OR(g27201, g15857) +g28386 = OR(g27202, g13277) +g28387 = OR(g27203, g15858) +g28388 = OR(g27204, g15859) +g28389 = OR(g27206, g15860) +g28390 = OR(g27207, g15861) +g28400 = OR(g27211, g15870) +g28401 = OR(g27212, g15871) +g28402 = OR(g27213, g15873) +g28403 = OR(g27214, g13282) +g28404 = OR(g27215, g15874) +g28405 = OR(g27216, g15875) +g28416 = OR(g27218, g15880) +g28417 = OR(g27219, g15881) +g28418 = OR(g27220, g15882) +g28419 = OR(g27221, g15884) +g28420 = OR(g27222, g13290) +g28428 = OR(g27227, g15912) +g28429 = OR(g27228, g15913) +g28430 = OR(g27229, g15914) +g28435 = OR(g27234, g15967) +g28490 = OR(g27262, g16185) +g28497 = OR(g27267, g16199) +g28511 = OR(g27272, g16208) +g28513 = OR(g27276, g26123) +g28517 = OR(g27280, g26154) +g28518 = OR(g27281, g26158) +g28525 = OR(g27284, g26176) +g28526 = OR(g27285, g26178) +g28527 = OR(g27286, g26182) +g28533 = OR(g27291, g26203) +g28534 = OR(g27292, g26204) +g28536 = OR(g27293, g26205) +g28538 = OR(g27294, g26206) +g28544 = OR(g27300, g26229) +g28545 = OR(g27301, g26230) +g28546 = OR(g27302, g26231) +g28548 = OR(g27303, g26232) +g28549 = OR(g27304, g26233) +g28551 = OR(g27305, g26234) +g28560 = OR(g27311, g26249) +g28561 = OR(g27312, g26250) +g28562 = OR(g27313, g26251) +g28564 = OR(g27314, g26252) +g28565 = OR(g27315, g26253) +g28566 = OR(g27316, g26254) +g28574 = OR(g27324, g26270) +g28576 = OR(g27325, g26271) +g28577 = OR(g27326, g26272) +g28578 = OR(g27327, g26273) +g28580 = OR(g27328, g26275) +g28581 = OR(g27329, g26276) +g28582 = OR(g27330, g26277) +g28589 = OR(g27331, g26285) +g28591 = OR(g27332, g26286) +g28592 = OR(g27333, g26288) +g28594 = OR(g27334, g26289) +g28595 = OR(g27335, g26290) +g28596 = OR(g27336, g26291) +g28600 = OR(g27339, g16427) +g28603 = OR(g27340, g26300) +g28605 = OR(g27341, g26302) +g28607 = OR(g27342, g26303) +g28609 = OR(g27346, g16483) +g28610 = OR(g27347, g16484) +g28611 = OR(g27348, g16485) +g28613 = OR(g27350, g26310) +g28614 = OR(g27351, g26311) +g28618 = OR(g27357, g16516) +g28619 = OR(g27358, g16517) +g28621 = OR(g27359, g16518) +g28622 = OR(g27360, g16519) +g28623 = OR(g27361, g16520) +g28625 = OR(g27363, g26324) +g28628 = OR(g27370, g16531) +g28629 = OR(g27371, g16532) +g28631 = OR(g27372, g16534) +g28632 = OR(g27373, g16535) +g28634 = OR(g27374, g16536) +g28635 = OR(g27375, g16537) +g28636 = OR(g27376, g16538) +g28640 = OR(g27384, g16590) +g28641 = OR(g27385, g16591) +g28643 = OR(g27386, g16592) +g28644 = OR(g27387, g16593) +g28646 = OR(g27388, g16595) +g28647 = OR(g27389, g16596) +g28649 = OR(g27390, g16597) +g28650 = OR(g27391, g16598) +g28651 = OR(g27392, g16599) +g28659 = OR(g27404, g16610) +g28661 = OR(g27406, g16611) +g28662 = OR(g27407, g16612) +g28664 = OR(g27408, g16613) +g28665 = OR(g27409, g16614) +g28667 = OR(g27410, g16616) +g28668 = OR(g27411, g16617) +g28670 = OR(g27412, g16618) +g28671 = OR(g27413, g16619) +g28680 = OR(g27427, g16633) +g28681 = OR(g27428, g16634) +g28682 = OR(g27430, g16635) +g28684 = OR(g27432, g16636) +g28685 = OR(g27433, g16637) +g28687 = OR(g27434, g16638) +g28688 = OR(g27435, g16639) +g28690 = OR(g27436, g16641) +g28691 = OR(g27437, g16642) +g28698 = OR(g27451, g16666) +g28699 = OR(g27452, g16667) +g28700 = OR(g27454, g16668) +g28701 = OR(g27455, g16669) +g28702 = OR(g27457, g16670) +g28704 = OR(g27459, g16671) +g28705 = OR(g27460, g16672) +g28707 = OR(g27461, g16673) +g28708 = OR(g27462, g16674) +g28715 = OR(g27480, g16700) +g28716 = OR(g27481, g13887) +g28717 = OR(g27482, g16701) +g28718 = OR(g27483, g16702) +g28719 = OR(g27485, g16703) +g28720 = OR(g27486, g16704) +g28721 = OR(g27488, g16705) +g28723 = OR(g27490, g16706) +g28724 = OR(g27491, g16707) +g28727 = OR(g27500, g16729) +g28728 = OR(g27501, g16730) +g28729 = OR(g27502, g16732) +g28730 = OR(g27503, g13912) +g28731 = OR(g27504, g16733) +g28732 = OR(g27505, g16734) +g28733 = OR(g27507, g16735) +g28734 = OR(g27508, g16736) +g28735 = OR(g27510, g16737) +g28743 = OR(g27517, g16758) +g28744 = OR(g27518, g16759) +g28745 = OR(g27519, g16760) +g28746 = OR(g27520, g16762) +g28747 = OR(g27521, g13942) +g28748 = OR(g27522, g16763) +g28749 = OR(g27523, g16764) +g28750 = OR(g27525, g16765) +g28751 = OR(g27526, g16766) +g28772 = OR(g27534, g16802) +g28773 = OR(g27535, g16803) +g28774 = OR(g27536, g16804) +g28775 = OR(g27537, g16806) +g28776 = OR(g27538, g13974) +g28777 = OR(g27539, g16807) +g28778 = OR(g27540, g16808) +g28814 = OR(g27545, g16841) +g28815 = OR(g27546, g16842) +g28816 = OR(g27547, g16843) +g28817 = OR(g27548, g16845) +g28818 = OR(g27549, g13998) +g28850 = OR(g27557, g16869) +g28851 = OR(g27558, g16870) +g28852 = OR(g27559, g16871) +g28884 = OR(g27568, g16885) +g29068 = OR(g27628, g17119) +g29078 = OR(g27633, g26572) +g29105 = OR(g27645, g17134) +g29114 = OR(g27646, g26602) +g29143 = OR(g27650, g17146) +g29148 = OR(g27651, g26606) +g29166 = OR(g27653, g17153) +g29168 = OR(g27658, g26613) +g29176 = OR(g27661, g17177) +g29197 = OR(g27187, g27163) +g29222 = OR(g28252, g18105) +g29223 = OR(g28341, g18131) +g29224 = OR(g28919, g18156) +g29225 = OR(g28451, g18158) +g29226 = OR(g28455, g18159) +g29227 = OR(g28456, g18169) +g29228 = OR(g28426, g18173) +g29229 = OR(g28532, g18191) +g29230 = OR(g28107, g18202) +g29231 = OR(g28301, g18229) +g29232 = OR(g28183, g18231) +g29233 = OR(g28171, g18234) +g29234 = OR(g28415, g18239) +g29235 = OR(g28110, g18260) +g29236 = OR(g28313, g18287) +g29237 = OR(g28185, g18289) +g29238 = OR(g28178, g18292) +g29239 = OR(g28427, g18297) +g29240 = OR(g28655, g18328) +g29241 = OR(g28638, g18332) +g29242 = OR(g28674, g18354) +g29243 = OR(g28657, g18358) +g29244 = OR(g28692, g18380) +g29245 = OR(g28676, g18384) +g29246 = OR(g28710, g18406) +g29247 = OR(g28694, g18410) +g29248 = OR(g28677, g18434) +g29249 = OR(g28658, g18438) +g29250 = OR(g28695, g18460) +g29251 = OR(g28679, g18464) +g29252 = OR(g28712, g18486) +g29253 = OR(g28697, g18490) +g29254 = OR(g28725, g18512) +g29255 = OR(g28714, g18516) +g29256 = OR(g28597, g18533) +g29257 = OR(g28228, g18600) +g29258 = OR(g28238, g18601) +g29259 = OR(g28304, g18603) +g29260 = OR(g28315, g18604) +g29261 = OR(g28247, g18605) +g29262 = OR(g28327, g18608) +g29263 = OR(g28239, g18617) +g29264 = OR(g28248, g18618) +g29265 = OR(g28318, g18620) +g29266 = OR(g28330, g18621) +g29267 = OR(g28257, g18622) +g29268 = OR(g28343, g18625) +g29269 = OR(g28249, g18634) +g29270 = OR(g28258, g18635) +g29271 = OR(g28333, g18637) +g29272 = OR(g28346, g18638) +g29273 = OR(g28269, g18639) +g29274 = OR(g28360, g18642) +g29275 = OR(g28165, g21868) +g29276 = OR(g28616, g18709) +g29277 = OR(g28440, g18710) +g29278 = OR(g28626, g18740) +g29279 = OR(g28442, g18741) +g29280 = OR(g28530, g18742) +g29281 = OR(g28541, g18743) +g29282 = OR(g28617, g18745) +g29283 = OR(g28627, g18746) +g29284 = OR(g28554, g18747) +g29285 = OR(g28639, g18750) +g29286 = OR(g28542, g18759) +g29287 = OR(g28555, g18760) +g29288 = OR(g28630, g18762) +g29289 = OR(g28642, g18763) +g29290 = OR(g28569, g18764) +g29291 = OR(g28660, g18767) +g29292 = OR(g28556, g18776) +g29293 = OR(g28570, g18777) +g29294 = OR(g28645, g18779) +g29295 = OR(g28663, g18780) +g29296 = OR(g28586, g18781) +g29297 = OR(g28683, g18784) +g29298 = OR(g28571, g18793) +g29299 = OR(g28587, g18794) +g29300 = OR(g28666, g18796) +g29301 = OR(g28686, g18797) +g29302 = OR(g28601, g18798) +g29303 = OR(g28703, g18801) +g29304 = OR(g28588, g18810) +g29305 = OR(g28602, g18811) +g29306 = OR(g28689, g18813) +g29307 = OR(g28706, g18814) +g29308 = OR(g28612, g18815) +g29309 = OR(g28722, g18818) +g29313 = OR(g28284, g27270) +g29319 = OR(g28812, g14453) +g29325 = OR(g28813, g27820) +g29366 = OR(g13738, g28439) +g29373 = OR(g13832, g28453) +g29476 = OR(g28108, g28112) +g29478 = OR(g28111, g22160) +g29479 = OR(g28113, g28116) +g29480 = OR(g28115, g22172) +g29481 = OR(g28117, g28125) +g29482 = OR(g28524, g27588) +g29483 = OR(g25801, g28130) +g29484 = OR(g28124, g22191) +g29485 = OR(g28535, g27594) +g29486 = OR(g28537, g27595) +g29487 = OR(g25815, g28133) +g29488 = OR(g28547, g27600) +g29489 = OR(g28550, g27601) +g29490 = OR(g25832, g28136) +g29495 = OR(g28563, g27614) +g29496 = OR(g28567, g27615) +g29501 = OR(g28583, g27634) +g29502 = OR(g28139, g25871) +g29504 = OR(g28143, g25875) +g29506 = OR(g28148, g25880) +g29508 = OR(g28152, g27041) +g29520 = OR(g28291, g28281, g28264, g28254) +g29529 = OR(g28303, g28293, g28283, g28267) +g29539 = OR(g2864, g28220) +g29583 = OR(g28182, g27099) +g29643 = OR(g28192, g27145) +g29692 = OR(g28197, g10873) +g29706 = OR(g28198, g27208) +g29716 = OR(g28199, g15856) +g29717 = OR(g28200, g10883) +g29730 = OR(g28150, g28141) +g29734 = OR(g28201, g15872) +g29735 = OR(g28202, g10898) +g29741 = OR(g28205, g15883) +g29748 = OR(g28210, g28214) +g29753 = OR(g28213, g22720) +g29754 = OR(g28215, g28218) +g29756 = OR(g22717, g28223) +g29763 = OR(g28217, g22762) +g29764 = OR(g28219, g28226) +g29768 = OR(g22760, g28229) +g29775 = OR(g25966, g28232) +g29776 = OR(g28225, g22846) +g29777 = OR(g28227, g28234) +g29786 = OR(g22843, g28240) +g29790 = OR(g25975, g28242) +g29791 = OR(g28233, g22859) +g29792 = OR(g28235, g28244) +g29793 = OR(g28237, g27247) +g29801 = OR(g25987, g28251) +g29802 = OR(g28243, g22871) +g29813 = OR(g26020, g28261) +g29848 = OR(g28260, g26077) +g29849 = OR(g26049, g28273) +g29864 = OR(g28272, g26086) +g29879 = OR(g28289, g26096) +g29892 = OR(g28300, g26120) +g29904 = OR(g28312, g26146) +I28147 = OR(g2946, g24561, g28220) +g29914 = OR(g22531, g22585, I28147) +g30081 = OR(g28454, g11366) +g30092 = OR(g28466, g16699) +g30093 = OR(g28467, g11397) +g30103 = OR(g28477, g16731) +g30104 = OR(g28478, g11427) +g30114 = OR(g28488, g16761) +g30115 = OR(g28489, g11449) +g30127 = OR(g28494, g16805) +g30128 = OR(g28495, g11497) +g30141 = OR(g28499, g16844) +g30163 = OR(g23381, g28523) +g30176 = OR(g23392, g28531) +g30189 = OR(g23401, g28543) +g30201 = OR(g23412, g28557) +g30214 = OR(g23424, g28572) +g30270 = OR(g28624, g27664) +g30279 = OR(g28637, g27668) +g30286 = OR(g28191, g28186) +g30287 = OR(g28653, g27677) +g30291 = OR(g28672, g27685) +g30293 = OR(g28236, g27246) +g30298 = OR(g28245, g27251) +g30300 = OR(g28246, g27252) +g30304 = OR(g28255, g27259) +g30307 = OR(g28256, g27260) +g30311 = OR(g28265, g27265) +g30314 = OR(g28268, g27266) +I28566 = OR(g29201, g29202, g29203, g28035) +I28567 = OR(g29204, g29205, g29206, g29207) +g30317 = OR(g29208, I28566, I28567) +g30333 = OR(g29834, g21699) +g30334 = OR(g29837, g18143) +g30335 = OR(g29746, g18174) +g30336 = OR(g29324, g18203) +g30337 = OR(g29334, g18220) +g30338 = OR(g29613, g18240) +g30339 = OR(g29629, g18244) +g30340 = OR(g29377, g18245) +g30341 = OR(g29380, g18246) +g30342 = OR(g29330, g18261) +g30343 = OR(g29344, g18278) +g30344 = OR(g29630, g18298) +g30345 = OR(g29644, g18302) +g30346 = OR(g29381, g18303) +g30347 = OR(g29383, g18304) +g30348 = OR(g30083, g18329) +g30349 = OR(g30051, g18333) +g30350 = OR(g30118, g18334) +g30351 = OR(g30084, g18339) +g30352 = OR(g30094, g18340) +g30353 = OR(g30095, g18355) +g30354 = OR(g30064, g18359) +g30355 = OR(g30131, g18360) +g30356 = OR(g30096, g18365) +g30357 = OR(g30107, g18366) +g30358 = OR(g30108, g18381) +g30359 = OR(g30075, g18385) +g30360 = OR(g30145, g18386) +g30361 = OR(g30109, g18391) +g30362 = OR(g30120, g18392) +g30363 = OR(g30121, g18407) +g30364 = OR(g30086, g18411) +g30365 = OR(g30158, g18412) +g30366 = OR(g30122, g18417) +g30367 = OR(g30133, g18418) +g30368 = OR(g30098, g18435) +g30369 = OR(g30066, g18439) +g30370 = OR(g30135, g18440) +g30371 = OR(g30099, g18445) +g30372 = OR(g30110, g18446) +g30373 = OR(g30111, g18461) +g30374 = OR(g30078, g18465) +g30375 = OR(g30149, g18466) +g30376 = OR(g30112, g18471) +g30377 = OR(g30124, g18472) +g30378 = OR(g30125, g18487) +g30379 = OR(g30089, g18491) +g30380 = OR(g30161, g18492) +g30381 = OR(g30126, g18497) +g30382 = OR(g30137, g18498) +g30383 = OR(g30138, g18513) +g30384 = OR(g30101, g18517) +g30385 = OR(g30172, g18518) +g30386 = OR(g30139, g18523) +g30387 = OR(g30151, g18524) +g30388 = OR(g30023, g18534) +g30389 = OR(g29969, g18554) +g30390 = OR(g29985, g18555) +g30391 = OR(g30080, g18557) +g30392 = OR(g30091, g18558) +g30393 = OR(g29986, g21748) +g30394 = OR(g29805, g21753) +g30395 = OR(g29841, g21754) +g30396 = OR(g29856, g21755) +g30397 = OR(g29747, g21756) +g30398 = OR(g29749, g21757) +g30399 = OR(g29757, g21758) +g30400 = OR(g29766, g21759) +g30401 = OR(g29782, g21760) +g30402 = OR(g29871, g21761) +g30403 = OR(g29750, g21762) +g30404 = OR(g29758, g21763) +g30405 = OR(g29767, g21764) +g30406 = OR(g29783, g21765) +g30407 = OR(g29794, g21766) +g30408 = OR(g29806, g21767) +g30409 = OR(g29842, g21768) +g30410 = OR(g29857, g21769) +g30411 = OR(g29872, g21770) +g30412 = OR(g29885, g21771) +g30413 = OR(g30001, g21772) +g30414 = OR(g30002, g21794) +g30415 = OR(g29843, g21799) +g30416 = OR(g29858, g21800) +g30417 = OR(g29874, g21801) +g30418 = OR(g29751, g21802) +g30419 = OR(g29759, g21803) +g30420 = OR(g29769, g21804) +g30421 = OR(g29784, g21805) +g30422 = OR(g29795, g21806) +g30423 = OR(g29887, g21807) +g30424 = OR(g29760, g21808) +g30425 = OR(g29770, g21809) +g30426 = OR(g29785, g21810) +g30427 = OR(g29796, g21811) +g30428 = OR(g29807, g21812) +g30429 = OR(g29844, g21813) +g30430 = OR(g29859, g21814) +g30431 = OR(g29875, g21815) +g30432 = OR(g29888, g21816) +g30433 = OR(g29899, g21817) +g30434 = OR(g30024, g21818) +g30435 = OR(g30025, g21840) +g30436 = OR(g29860, g21845) +g30437 = OR(g29876, g21846) +g30438 = OR(g29890, g21847) +g30439 = OR(g29761, g21848) +g30440 = OR(g29771, g21849) +g30441 = OR(g29787, g21850) +g30442 = OR(g29797, g21851) +g30443 = OR(g29808, g21852) +g30444 = OR(g29901, g21853) +g30445 = OR(g29772, g21854) +g30446 = OR(g29788, g21855) +g30447 = OR(g29798, g21856) +g30448 = OR(g29809, g21857) +g30449 = OR(g29845, g21858) +g30450 = OR(g29861, g21859) +g30451 = OR(g29877, g21860) +g30452 = OR(g29891, g21861) +g30453 = OR(g29902, g21862) +g30454 = OR(g29909, g21863) +g30455 = OR(g30041, g21864) +g30456 = OR(g29378, g21869) +g30457 = OR(g29369, g21885) +g30458 = OR(g30005, g24330) +g30459 = OR(g29314, g21926) +g30460 = OR(g30207, g21931) +g30461 = OR(g30219, g21932) +g30462 = OR(g30228, g21933) +g30463 = OR(g30140, g21934) +g30464 = OR(g30152, g21935) +g30465 = OR(g30164, g21936) +g30466 = OR(g30174, g21937) +g30467 = OR(g30185, g21938) +g30468 = OR(g30238, g21939) +g30469 = OR(g30153, g21940) +g30470 = OR(g30165, g21941) +g30471 = OR(g30175, g21942) +g30472 = OR(g30186, g21943) +g30473 = OR(g30196, g21944) +g30474 = OR(g30208, g21945) +g30475 = OR(g30220, g21946) +g30476 = OR(g30229, g21947) +g30477 = OR(g30239, g21948) +g30478 = OR(g30248, g21949) +g30479 = OR(g29320, g21950) +g30480 = OR(g29321, g21972) +g30481 = OR(g30221, g21977) +g30482 = OR(g30230, g21978) +g30483 = OR(g30241, g21979) +g30484 = OR(g30154, g21980) +g30485 = OR(g30166, g21981) +g30486 = OR(g30177, g21982) +g30487 = OR(g30187, g21983) +g30488 = OR(g30197, g21984) +g30489 = OR(g30250, g21985) +g30490 = OR(g30167, g21986) +g30491 = OR(g30178, g21987) +g30492 = OR(g30188, g21988) +g30493 = OR(g30198, g21989) +g30494 = OR(g30209, g21990) +g30495 = OR(g30222, g21991) +g30496 = OR(g30231, g21992) +g30497 = OR(g30242, g21993) +g30498 = OR(g30251, g21994) +g30499 = OR(g30261, g21995) +g30500 = OR(g29326, g21996) +g30501 = OR(g29327, g22018) +g30502 = OR(g30232, g22023) +g30503 = OR(g30243, g22024) +g30504 = OR(g30253, g22025) +g30505 = OR(g30168, g22026) +g30506 = OR(g30179, g22027) +g30507 = OR(g30190, g22028) +g30508 = OR(g30199, g22029) +g30509 = OR(g30210, g22030) +g30510 = OR(g30263, g22031) +g30511 = OR(g30180, g22032) +g30512 = OR(g30191, g22033) +g30513 = OR(g30200, g22034) +g30514 = OR(g30211, g22035) +g30515 = OR(g30223, g22036) +g30516 = OR(g30233, g22037) +g30517 = OR(g30244, g22038) +g30518 = OR(g30254, g22039) +g30519 = OR(g30264, g22040) +g30520 = OR(g30272, g22041) +g30521 = OR(g29331, g22042) +g30522 = OR(g29332, g22064) +g30523 = OR(g30245, g22069) +g30524 = OR(g30255, g22070) +g30525 = OR(g30266, g22071) +g30526 = OR(g30181, g22072) +g30527 = OR(g30192, g22073) +g30528 = OR(g30202, g22074) +g30529 = OR(g30212, g22075) +g30530 = OR(g30224, g22076) +g30531 = OR(g30274, g22077) +g30532 = OR(g30193, g22078) +g30533 = OR(g30203, g22079) +g30534 = OR(g30213, g22080) +g30535 = OR(g30225, g22081) +g30536 = OR(g30234, g22082) +g30537 = OR(g30246, g22083) +g30538 = OR(g30256, g22084) +g30539 = OR(g30267, g22085) +g30540 = OR(g30275, g22086) +g30541 = OR(g30281, g22087) +g30542 = OR(g29337, g22088) +g30543 = OR(g29338, g22110) +g30544 = OR(g30257, g22115) +g30545 = OR(g30268, g22116) +g30546 = OR(g30277, g22117) +g30547 = OR(g30194, g22118) +g30548 = OR(g30204, g22119) +g30549 = OR(g30215, g22120) +g30550 = OR(g30226, g22121) +g30551 = OR(g30235, g22122) +g30552 = OR(g30283, g22123) +g30553 = OR(g30205, g22124) +g30554 = OR(g30216, g22125) +g30555 = OR(g30227, g22126) +g30556 = OR(g30236, g22127) +g30557 = OR(g30247, g22128) +g30558 = OR(g30258, g22129) +g30559 = OR(g30269, g22130) +g30560 = OR(g30278, g22131) +g30561 = OR(g30284, g22132) +g30562 = OR(g30289, g22133) +g30563 = OR(g29347, g22134) +g30579 = OR(g30173, g14571) +g30597 = OR(g13564, g29693) +g30605 = OR(g29529, g29520) +g30608 = OR(g13604, g29736) +g30609 = OR(g13633, g29742) +g30611 = OR(g13671, g29743) +g30672 = OR(g13737, g29752) +g30732 = OR(g13778, g29762) +g30733 = OR(g13807, g29773) +g30734 = OR(g13808, g29774) +g30824 = OR(g13833, g29789) +g30916 = OR(g13853, g29799) +g30984 = OR(g29765, g29755) +g31001 = OR(g29360, g28151) +g31002 = OR(g29362, g28154) +g31007 = OR(g29364, g28159) +g31014 = OR(g29367, g28160) +g31020 = OR(g29375, g28164) +g31144 = OR(g29477, g28193) +g31221 = OR(g29494, g28204) +g31241 = OR(g25959, g29510) +g31244 = OR(g25963, g29515) +g31245 = OR(g25964, g29516) +g31246 = OR(g25965, g29518) +g31247 = OR(g29513, g13324) +g31248 = OR(g25970, g29522) +g31249 = OR(g25971, g29523) +g31250 = OR(g25972, g29526) +g31251 = OR(g25973, g29527) +g31253 = OR(g25980, g29533) +g31254 = OR(g25981, g29534) +g31255 = OR(g25982, g29536) +g31256 = OR(g25983, g29537) +g31257 = OR(g29531, g28253) +g31258 = OR(g25991, g29550) +g31259 = OR(g25992, g29554) +g31260 = OR(g25993, g29555) +g31267 = OR(g29548, g28263) +g31268 = OR(g29552, g28266) +g31269 = OR(g26024, g29569) +g31274 = OR(g29565, g28280) +g31276 = OR(g29567, g28282) +g31277 = OR(g29570, g28285) +g31279 = OR(g29571, g29579) +g31284 = OR(g29575, g28290) +g31287 = OR(g29578, g28292) +g31288 = OR(g2955, g29914) +g31289 = OR(g29580, g29591) +g31291 = OR(g29581, g29593) +g31293 = OR(g29582, g28299) +g31295 = OR(g26090, g29598) +g31302 = OR(g29590, g28302) +g31303 = OR(g29592, g29606) +g31304 = OR(g29594, g29608) +g31306 = OR(g29595, g29610) +g31307 = OR(g29596, g28311) +g31308 = OR(g26101, g29614) +g31311 = OR(g26103, g29618) +g31315 = OR(g29607, g29623) +g31316 = OR(g29609, g29624) +g31317 = OR(g29611, g29626) +g31319 = OR(g29612, g28324) +g31320 = OR(g26125, g29632) +g31322 = OR(g26128, g29635) +g31325 = OR(g29625, g29639) +g31326 = OR(g29627, g29640) +g31375 = OR(g29628, g28339) +g31465 = OR(g26156, g29647) +g31466 = OR(g26160, g29650) +g31468 = OR(g29641, g29656) +g31472 = OR(g29642, g28352) +g31473 = OR(g26180, g29666) +g31474 = OR(g29668, g13583) +g31591 = OR(g29358, g29353) +g31668 = OR(g29924, g28558) +g31670 = OR(g29937, g28573) +g31745 = OR(g29959, g29973) +g31749 = OR(g29974, g29988) +g31751 = OR(g29975, g29990) +g31754 = OR(g29989, g30006) +g31755 = OR(g29991, g30008) +g31757 = OR(g29992, g30010) +g31760 = OR(g30007, g30027) +g31761 = OR(g30009, g30028) +g31762 = OR(g30011, g30030) +g31764 = OR(g30015, g30032) +g31766 = OR(g30029, g30042) +g31767 = OR(g30031, g30043) +g31768 = OR(g30033, g30045) +g31770 = OR(g30034, g30047) +g31772 = OR(g30035, g28654) +g31773 = OR(g30044, g30056) +g31774 = OR(g30046, g30057) +g31775 = OR(g30048, g30059) +g31779 = OR(g30050, g28673) +g31781 = OR(g30058, g30069) +g31782 = OR(g30060, g30070) +I29351 = OR(g29328, g29323, g29316, g30316) +I29352 = OR(g29322, g29315, g30315, g30308) +g31783 = OR(I29351, I29352) +g31785 = OR(g30071, g30082) +g31793 = OR(g28031, g30317) +g31864 = OR(g31271, g21703) +g31865 = OR(g31149, g21709) +g31866 = OR(g31252, g18142) +g31867 = OR(g31238, g18175) +g31868 = OR(g30600, g18204) +g31869 = OR(g30592, g18221) +g31870 = OR(g30607, g18262) +g31871 = OR(g30596, g18279) +g31872 = OR(g31524, g18535) +g31873 = OR(g31270, g21728) +g31874 = OR(g31016, g21729) +g31875 = OR(g31066, g21730) +g31876 = OR(g31125, g21731) +g31877 = OR(g31278, g21732) +g31878 = OR(g31015, g21733) +g31879 = OR(g31475, g21745) +g31880 = OR(g31280, g21774) +g31881 = OR(g31018, g21775) +g31882 = OR(g31115, g21776) +g31883 = OR(g31132, g21777) +g31884 = OR(g31290, g21778) +g31885 = OR(g31017, g21779) +g31886 = OR(g31481, g21791) +g31887 = OR(g31292, g21820) +g31888 = OR(g31067, g21821) +g31889 = OR(g31118, g21822) +g31890 = OR(g31143, g21823) +g31891 = OR(g31305, g21824) +g31892 = OR(g31019, g21825) +g31893 = OR(g31490, g21837) +g31894 = OR(g30671, g21870) +g31895 = OR(g31505, g24296) +g31896 = OR(g31242, g24305) +g31897 = OR(g31237, g24322) +g31898 = OR(g31707, g21906) +g31899 = OR(g31470, g21907) +g31900 = OR(g31484, g21908) +g31901 = OR(g31516, g21909) +g31902 = OR(g31744, g21910) +g31903 = OR(g31374, g21911) +g31904 = OR(g31780, g21923) +g31905 = OR(g31746, g21952) +g31906 = OR(g31477, g21953) +g31907 = OR(g31492, g21954) +g31908 = OR(g31519, g21955) +g31909 = OR(g31750, g21956) +g31910 = OR(g31471, g21957) +g31911 = OR(g31784, g21969) +g31912 = OR(g31752, g21998) +g31913 = OR(g31485, g21999) +g31914 = OR(g31499, g22000) +g31915 = OR(g31520, g22001) +g31916 = OR(g31756, g22002) +g31917 = OR(g31478, g22003) +g31918 = OR(g31786, g22015) +g31919 = OR(g31758, g22044) +g31920 = OR(g31493, g22045) +g31921 = OR(g31508, g22046) +g31922 = OR(g31525, g22047) +g31923 = OR(g31763, g22048) +g31924 = OR(g31486, g22049) +g31925 = OR(g31789, g22061) +g31926 = OR(g31765, g22090) +g31927 = OR(g31500, g22091) +g31928 = OR(g31517, g22092) +g31929 = OR(g31540, g22093) +g31930 = OR(g31769, g22094) +g31931 = OR(g31494, g22095) +g31932 = OR(g31792, g22107) +g31964 = OR(g31654, g14544) +g32037 = OR(g30566, g29329) +g32094 = OR(g30612, g29363) +g32117 = OR(g24482, g30914) +g32123 = OR(g30915, g30919) +g32124 = OR(g24488, g30920) +g32125 = OR(g30918, g29376) +g32130 = OR(g30921, g30925) +g32131 = OR(g24495, g30926) +g32132 = OR(g31487, g31479) +g32144 = OR(g30927, g30930) +g32155 = OR(g30935, g29475) +g32202 = OR(g31069, g13410) +g32208 = OR(g31120, g29584) +g32209 = OR(g31122, g29599) +g32210 = OR(g31123, g29600) +g32211 = OR(g31124, g29603) +g32216 = OR(g31128, g29615) +g32217 = OR(g31129, g29616) +g32218 = OR(g31130, g29619) +g32219 = OR(g31131, g29620) +g32220 = OR(g31139, g29633) +g32221 = OR(g31140, g29634) +g32222 = OR(g31141, g29636) +g32223 = OR(g31142, g29637) +g32225 = OR(g30576, g29336) +g32226 = OR(g31145, g29645) +g32227 = OR(g31146, g29648) +g32228 = OR(g31147, g29651) +g32229 = OR(g31148, g29652) +g32230 = OR(g30589, g29345) +g32231 = OR(g30590, g29346) +g32233 = OR(g31150, g29661) +g32235 = OR(g31151, g29662) +g32236 = OR(g31152, g29664) +g32237 = OR(g31153, g29667) +g32238 = OR(g30594, g29349) +g32239 = OR(g30595, g29350) +g32240 = OR(g24757, g31182) +g32243 = OR(g31166, g29683) +g32245 = OR(g31167, g29684) +g32247 = OR(g31168, g29686) +g32249 = OR(g31169, g29687) +g32250 = OR(g30598, g29351) +g32251 = OR(g30599, g29352) +g32252 = OR(g31183, g31206) +g32253 = OR(g24771, g31207) +g32257 = OR(g31184, g29708) +g32259 = OR(g31185, g29709) +g32262 = OR(g31186, g29710) +g32264 = OR(g31187, g29711) +g32266 = OR(g30604, g29354) +g32267 = OR(g31208, g31218) +g32268 = OR(g24785, g31219) +g32271 = OR(g31209, g29731) +g32275 = OR(g31210, g29732) +g32277 = OR(g31211, g29733) +g32279 = OR(g31220, g31224) +g32280 = OR(g24790, g31225) +g32285 = OR(g31222, g29740) +g32288 = OR(g31226, g31229) +g32289 = OR(g24796, g31230) +g32294 = OR(g31231, g31232) +g32344 = OR(g29804, g31266) +g32346 = OR(g29838, g31272) +g32347 = OR(g29839, g31273) +g32349 = OR(g29840, g31275) +g32351 = OR(g29851, g31281) +g32352 = OR(g29852, g31282) +g32353 = OR(g29853, g31283) +g32354 = OR(g29854, g31285) +g32355 = OR(g29855, g31286) +g32357 = OR(g29865, g31296) +g32358 = OR(g29866, g31297) +g32359 = OR(g29867, g31298) +g32360 = OR(g29868, g31299) +g32361 = OR(g29869, g31300) +g32362 = OR(g29870, g31301) +g32367 = OR(g29880, g31309) +g32368 = OR(g29881, g31310) +g32370 = OR(g29882, g31312) +g32371 = OR(g29883, g31313) +g32372 = OR(g29884, g31314) +g32373 = OR(g29894, g31321) +g32374 = OR(g29895, g31323) +g32375 = OR(g29896, g31324) +g32380 = OR(g29907, g31467) +g32385 = OR(g31480, g29938) +g32386 = OR(g31488, g29949) +g32387 = OR(g31489, g29952) +g32388 = OR(g31495, g29962) +g32389 = OR(g31496, g29966) +g32390 = OR(g31501, g29979) +g32391 = OR(g31502, g29982) +g32392 = OR(g31513, g30000) +g32395 = OR(g31523, g30049) +g32398 = OR(g31526, g30061) +g32399 = OR(g31527, g30062) +g32408 = OR(g31541, g30073) +g32426 = OR(g26105, g26131, g30613) +g32427 = OR(g8928, g30583) +g32429 = OR(g30318, g31794) +g32454 = OR(g30322, g31795) +I29985 = OR(g29385, g31376, g30735, g30825) +I29986 = OR(g31070, g31194, g30614, g30673) +I30054 = OR(g29385, g31376, g30735, g30825) +I30055 = OR(g31070, g31170, g30614, g30673) +I30123 = OR(g29385, g31376, g30735, g30825) +I30124 = OR(g31070, g31154, g30614, g30673) +I30192 = OR(g29385, g31376, g30735, g30825) +I30193 = OR(g31070, g30614, g30673, g31528) +I30261 = OR(g29385, g31376, g30735, g30825) +I30262 = OR(g31672, g31710, g31021, g30937) +I30330 = OR(g29385, g31376, g30735, g30825) +I30331 = OR(g31672, g31710, g31021, g30937) +I30399 = OR(g29385, g31376, g30735, g30825) +I30400 = OR(g31021, g30937, g31327, g30614) +I30468 = OR(g29385, g31376, g30735, g30825) +I30469 = OR(g31672, g31710, g31021, g30937) +g32976 = OR(g32207, g21704) +g32977 = OR(g32169, g21710) +g32978 = OR(g32197, g18145) +g32979 = OR(g32181, g18177) +g32980 = OR(g32254, g18198) +g32981 = OR(g32425, g18206) +g32982 = OR(g31948, g18208) +g32983 = OR(g31990, g18222) +g32984 = OR(g31934, g18264) +g32985 = OR(g31963, g18266) +g32986 = OR(g31996, g18280) +g32987 = OR(g32311, g18323) +g32988 = OR(g32232, g18325) +g32989 = OR(g32241, g18326) +g32990 = OR(g32281, g18341) +g32991 = OR(g32322, g18349) +g32992 = OR(g32242, g18351) +g32993 = OR(g32255, g18352) +g32994 = OR(g32290, g18367) +g32995 = OR(g32330, g18375) +g32996 = OR(g32256, g18377) +g32997 = OR(g32269, g18378) +g32998 = OR(g32300, g18393) +g32999 = OR(g32337, g18401) +g33000 = OR(g32270, g18403) +g33001 = OR(g32282, g18404) +g33002 = OR(g32304, g18419) +g33003 = OR(g32323, g18429) +g33004 = OR(g32246, g18431) +g33005 = OR(g32260, g18432) +g33006 = OR(g32291, g18447) +g33007 = OR(g32331, g18455) +g33008 = OR(g32261, g18457) +g33009 = OR(g32273, g18458) +g33010 = OR(g32301, g18473) +g33011 = OR(g32338, g18481) +g33012 = OR(g32274, g18483) +g33013 = OR(g32283, g18484) +g33014 = OR(g32305, g18499) +g33015 = OR(g32343, g18507) +g33016 = OR(g32284, g18509) +g33017 = OR(g32292, g18510) +g33018 = OR(g32312, g18525) +g33019 = OR(g32339, g18536) +g33020 = OR(g32160, g21734) +g33021 = OR(g32302, g21749) +g33022 = OR(g32306, g21750) +g33023 = OR(g32313, g21751) +g33024 = OR(g32324, g21752) +g33025 = OR(g32162, g21780) +g33026 = OR(g32307, g21795) +g33027 = OR(g32314, g21796) +g33028 = OR(g32325, g21797) +g33029 = OR(g32332, g21798) +g33030 = OR(g32166, g21826) +g33031 = OR(g32315, g21841) +g33032 = OR(g32326, g21842) +g33033 = OR(g32333, g21843) +g33034 = OR(g32340, g21844) +g33035 = OR(g32019, g21872) +g33036 = OR(g32168, g24309) +g33037 = OR(g32177, g24310) +g33038 = OR(g32184, g24311) +g33039 = OR(g32187, g24312) +g33040 = OR(g32164, g24313) +g33041 = OR(g32189, g24323) +g33042 = OR(g32193, g24324) +g33043 = OR(g32195, g24325) +g33044 = OR(g32199, g24327) +g33045 = OR(g32206, g24328) +g33046 = OR(g32308, g21912) +g33047 = OR(g31944, g21927) +g33048 = OR(g31960, g21928) +g33049 = OR(g31966, g21929) +g33050 = OR(g31974, g21930) +g33051 = OR(g32316, g21958) +g33052 = OR(g31961, g21973) +g33053 = OR(g31967, g21974) +g33054 = OR(g31975, g21975) +g33055 = OR(g31986, g21976) +g33056 = OR(g32327, g22004) +g33057 = OR(g31968, g22019) +g33058 = OR(g31976, g22020) +g33059 = OR(g31987, g22021) +g33060 = OR(g31992, g22022) +g33061 = OR(g32334, g22050) +g33062 = OR(g31977, g22065) +g33063 = OR(g31988, g22066) +g33064 = OR(g31993, g22067) +g33065 = OR(g32008, g22068) +g33066 = OR(g32341, g22096) +g33067 = OR(g31989, g22111) +g33068 = OR(g31994, g22112) +g33069 = OR(g32009, g22113) +g33070 = OR(g32010, g22114) +g33076 = OR(g32336, g32446) +g33115 = OR(g32397, g32401) +g33116 = OR(g32403, g32411) +g33118 = OR(g32413, g32418) +g33119 = OR(g32420, g32428) +g33123 = OR(g31962, g30577) +I30717 = OR(g31787, g32200, g31940, g31949) +I30718 = OR(g32348, g32356, g32097, g32020) +g33149 = OR(g32204, I30717, I30718) +g33159 = OR(g32016, g30730) +I30727 = OR(g31759, g32196, g31933, g31941) +I30728 = OR(g32345, g32350, g32056, g32018) +g33164 = OR(g32203, I30727, I30728) +I30734 = OR(g31790, g32191, g32086, g32095) +I30735 = OR(g32369, g32376, g32089, g32035) +g33176 = OR(g32198, I30734, I30735) +I30740 = OR(g31776, g32188, g32083, g32087) +I30741 = OR(g32085, g32030, g32224, g32013) +g33187 = OR(g32014, I30740, I30741) +I30745 = OR(g31777, g32321, g32069, g32084) +I30746 = OR(g32047, g31985, g31991, g32309) +g33197 = OR(g32342, I30745, I30746) +I30750 = OR(g31788, g32310, g32054, g32070) +I30751 = OR(g32042, g32161, g31943, g31959) +g33204 = OR(g32317, I30750, I30751) +I30755 = OR(g30564, g32303, g32049, g32055) +I30756 = OR(g32088, g32163, g32098, g32105) +g33212 = OR(g32328, I30755, I30756) +I30760 = OR(g31778, g32295, g32046, g32050) +I30761 = OR(g32071, g32167, g32067, g32082) +g33219 = OR(g32335, I30760, I30761) +g33227 = OR(g32029, g32031) +g33231 = OR(g32032, g32036) +g33232 = OR(g32034, g30936) +g33234 = OR(g32039, g32043) +g33235 = OR(g32040, g30982) +g33236 = OR(g32044, g32045) +g33238 = OR(g32048, g32051) +g33240 = OR(g32052, g32068) +g33251 = OR(g32096, g29509) +g33253 = OR(g32103, g29511) +g33254 = OR(g32104, g29512) +g33255 = OR(g32106, g29514) +g33256 = OR(g32107, g29517) +g33257 = OR(g32108, g29519) +g33259 = OR(g32109, g29521) +g33260 = OR(g32110, g29524) +g33261 = OR(g32111, g29525) +g33262 = OR(g32112, g29528) +g33265 = OR(g32113, g29530) +g33266 = OR(g32114, g29532) +g33267 = OR(g32115, g29535) +g33268 = OR(g32116, g29538) +g33270 = OR(g32119, g29547) +g33271 = OR(g32120, g29549) +g33272 = OR(g32121, g29551) +g33273 = OR(g32122, g29553) +g33274 = OR(g32126, g29563) +g33275 = OR(g32127, g29564) +g33276 = OR(g32128, g29566) +g33277 = OR(g32129, g29568) +g33278 = OR(g32139, g29572) +g33279 = OR(g32140, g29573) +g33280 = OR(g32141, g29574) +g33281 = OR(g32142, g29576) +g33282 = OR(g32143, g29577) +g33283 = OR(g31995, g30318) +g33286 = OR(g32145, g29585) +g33287 = OR(g32146, g29586) +g33288 = OR(g32147, g29587) +g33289 = OR(g32148, g29588) +g33290 = OR(g32149, g29589) +g33291 = OR(g32154, g13477) +g33292 = OR(g32150, g29601) +g33293 = OR(g32151, g29602) +g33294 = OR(g32152, g29604) +g33295 = OR(g32153, g29605) +g33296 = OR(g32156, g29617) +g33297 = OR(g32157, g29621) +g33298 = OR(g32158, g29622) +g33303 = OR(g32159, g29638) +g33310 = OR(g29631, g32165) +g33312 = OR(g29646, g32170) +g33313 = OR(g29649, g32171) +g33314 = OR(g29663, g32174) +g33315 = OR(g29665, g32175) +g33316 = OR(g29685, g32178) +g33317 = OR(g29688, g32179) +g33318 = OR(g31969, g32434) +g33321 = OR(g29712, g32182) +g33323 = OR(g31936, g32442) +g33380 = OR(g32234, g29926) +g33383 = OR(g32244, g29940) +g33384 = OR(g32248, g29943) +g33386 = OR(g32258, g29951) +g33387 = OR(g32263, g29954) +g33389 = OR(g32272, g29964) +g33390 = OR(g32276, g29968) +g33393 = OR(g32286, g29984) +g33534 = OR(g33186, g21700) +g33535 = OR(g33233, g21711) +g33536 = OR(g33241, g21715) +g33537 = OR(g33244, g21716) +g33538 = OR(g33252, g18144) +g33539 = OR(g33245, g18178) +g33540 = OR(g33099, g18207) +g33541 = OR(g33101, g18223) +g33542 = OR(g33102, g18265) +g33543 = OR(g33106, g18281) +g33544 = OR(g33392, g18317) +g33545 = OR(g33399, g18324) +g33546 = OR(g33402, g18327) +g33547 = OR(g33349, g18331) +g33548 = OR(g33327, g18336) +g33549 = OR(g33328, g18337) +g33550 = OR(g33342, g18338) +g33551 = OR(g33446, g18342) +g33552 = OR(g33400, g18343) +g33553 = OR(g33403, g18350) +g33554 = OR(g33407, g18353) +g33555 = OR(g33355, g18357) +g33556 = OR(g33329, g18362) +g33557 = OR(g33331, g18363) +g33558 = OR(g33350, g18364) +g33559 = OR(g33073, g18368) +g33560 = OR(g33404, g18369) +g33561 = OR(g33408, g18376) +g33562 = OR(g33414, g18379) +g33563 = OR(g33361, g18383) +g33564 = OR(g33332, g18388) +g33565 = OR(g33338, g18389) +g33566 = OR(g33356, g18390) +g33567 = OR(g33081, g18394) +g33568 = OR(g33409, g18395) +g33569 = OR(g33415, g18402) +g33570 = OR(g33420, g18405) +g33571 = OR(g33367, g18409) +g33572 = OR(g33339, g18414) +g33573 = OR(g33343, g18415) +g33574 = OR(g33362, g18416) +g33575 = OR(g33086, g18420) +g33576 = OR(g33401, g18423) +g33577 = OR(g33405, g18430) +g33578 = OR(g33410, g18433) +g33579 = OR(g33357, g18437) +g33580 = OR(g33330, g18442) +g33581 = OR(g33333, g18443) +g33582 = OR(g33351, g18444) +g33583 = OR(g33074, g18448) +g33584 = OR(g33406, g18449) +g33585 = OR(g33411, g18456) +g33586 = OR(g33416, g18459) +g33587 = OR(g33363, g18463) +g33588 = OR(g33334, g18468) +g33589 = OR(g33340, g18469) +g33590 = OR(g33358, g18470) +g33591 = OR(g33082, g18474) +g33592 = OR(g33412, g18475) +g33593 = OR(g33417, g18482) +g33594 = OR(g33421, g18485) +g33595 = OR(g33368, g18489) +g33596 = OR(g33341, g18494) +g33597 = OR(g33344, g18495) +g33598 = OR(g33364, g18496) +g33599 = OR(g33087, g18500) +g33600 = OR(g33418, g18501) +g33601 = OR(g33422, g18508) +g33602 = OR(g33425, g18511) +g33603 = OR(g33372, g18515) +g33604 = OR(g33345, g18520) +g33605 = OR(g33352, g18521) +g33606 = OR(g33369, g18522) +g33607 = OR(g33091, g18526) +g33608 = OR(g33322, g18537) +g33609 = OR(g33239, g18615) +g33610 = OR(g33242, g18616) +g33611 = OR(g33243, g18632) +g33612 = OR(g33247, g18633) +g33613 = OR(g33248, g18649) +g33614 = OR(g33249, g18650) +g33615 = OR(g33113, g21871) +g33616 = OR(g33237, g24314) +g33617 = OR(g33263, g24326) +g33618 = OR(g33353, g18757) +g33619 = OR(g33359, g18758) +g33620 = OR(g33360, g18774) +g33621 = OR(g33365, g18775) +g33622 = OR(g33366, g18791) +g33623 = OR(g33370, g18792) +g33624 = OR(g33371, g18808) +g33625 = OR(g33373, g18809) +g33626 = OR(g33374, g18825) +g33627 = OR(g33376, g18826) +g33628 = OR(g33071, g32450) +g33685 = OR(g32396, g33423) +g33692 = OR(g32400, g33428) +g33694 = OR(g32402, g33429) +g33699 = OR(g32409, g33433) +g33703 = OR(g32410, g33434) +g33706 = OR(g32412, g33440) +g33709 = OR(g32414, g33441) +g33714 = OR(g32419, g33450) +g33732 = OR(g33104, g32011) +g33733 = OR(g33105, g32012) +g33788 = OR(g33122, g32041) +g33791 = OR(g33379, g32430) +g33794 = OR(g33126, g32053) +g33891 = OR(g33264, g33269) +g33914 = OR(g33305, g33311) +g33945 = OR(g32430, g33455) +g33946 = OR(g32434, g33456) +g33947 = OR(g32438, g33457) +g33948 = OR(g32442, g33458) +g33949 = OR(g32446, g33459) +g33950 = OR(g32450, g33460) +I31838 = OR(g33461, g33462, g33463, g33464) +I31839 = OR(g33465, g33466, g33467, g33468) +g33951 = OR(g33469, I31838, I31839) +I31843 = OR(g33470, g33471, g33472, g33473) +I31844 = OR(g33474, g33475, g33476, g33477) +g33952 = OR(g33478, I31843, I31844) +I31848 = OR(g33479, g33480, g33481, g33482) +I31849 = OR(g33483, g33484, g33485, g33486) +g33953 = OR(g33487, I31848, I31849) +I31853 = OR(g33488, g33489, g33490, g33491) +I31854 = OR(g33492, g33493, g33494, g33495) +g33954 = OR(g33496, I31853, I31854) +I31858 = OR(g33497, g33498, g33499, g33500) +I31859 = OR(g33501, g33502, g33503, g33504) +g33955 = OR(g33505, I31858, I31859) +I31863 = OR(g33506, g33507, g33508, g33509) +I31864 = OR(g33510, g33511, g33512, g33513) +g33956 = OR(g33514, I31863, I31864) +I31868 = OR(g33515, g33516, g33517, g33518) +I31869 = OR(g33519, g33520, g33521, g33522) +g33957 = OR(g33523, I31868, I31869) +I31873 = OR(g33524, g33525, g33526, g33527) +I31874 = OR(g33528, g33529, g33530, g33531) +g33958 = OR(g33532, I31873, I31874) +g33960 = OR(g33759, g21701) +g33961 = OR(g33789, g21712) +g33962 = OR(g33822, g18123) +g33963 = OR(g33830, g18124) +g33964 = OR(g33817, g18146) +g33965 = OR(g33805, g18179) +g33966 = OR(g33837, g18318) +g33967 = OR(g33842, g18319) +g33968 = OR(g33855, g18320) +g33969 = OR(g33864, g18321) +g33970 = OR(g33868, g18322) +g33971 = OR(g33890, g18330) +g33972 = OR(g33941, g18335) +g33973 = OR(g33840, g18344) +g33974 = OR(g33846, g18345) +g33975 = OR(g33860, g18346) +g33976 = OR(g33869, g18347) +g33977 = OR(g33876, g18348) +g33978 = OR(g33892, g18356) +g33979 = OR(g33942, g18361) +g33980 = OR(g33843, g18370) +g33981 = OR(g33856, g18371) +g33982 = OR(g33865, g18372) +g33983 = OR(g33877, g18373) +g33984 = OR(g33881, g18374) +g33985 = OR(g33896, g18382) +g33986 = OR(g33639, g18387) +g33987 = OR(g33847, g18396) +g33988 = OR(g33861, g18397) +g33989 = OR(g33870, g18398) +g33990 = OR(g33882, g18399) +g33991 = OR(g33885, g18400) +g33992 = OR(g33900, g18408) +g33993 = OR(g33646, g18413) +g33994 = OR(g33841, g18424) +g33995 = OR(g33848, g18425) +g33996 = OR(g33862, g18426) +g33997 = OR(g33871, g18427) +g33998 = OR(g33878, g18428) +g33999 = OR(g33893, g18436) +g34000 = OR(g33943, g18441) +g34001 = OR(g33844, g18450) +g34002 = OR(g33857, g18451) +g34003 = OR(g33866, g18452) +g34004 = OR(g33879, g18453) +g34005 = OR(g33883, g18454) +g34006 = OR(g33897, g18462) +g34007 = OR(g33640, g18467) +g34008 = OR(g33849, g18476) +g34009 = OR(g33863, g18477) +g34010 = OR(g33872, g18478) +g34011 = OR(g33884, g18479) +g34012 = OR(g33886, g18480) +g34013 = OR(g33901, g18488) +g34014 = OR(g33647, g18493) +g34015 = OR(g33858, g18502) +g34016 = OR(g33867, g18503) +g34017 = OR(g33880, g18504) +g34018 = OR(g33887, g18505) +g34019 = OR(g33889, g18506) +g34020 = OR(g33904, g18514) +g34021 = OR(g33652, g18519) +g34022 = OR(g33873, g18538) +g34023 = OR(g33796, g24320) +g34024 = OR(g33807, g24331) +g34025 = OR(g33927, g18672) +g34026 = OR(g33715, g18682) +g34027 = OR(g33718, g18683) +g34028 = OR(g33720, g18684) +g34029 = OR(g33798, g18703) +g34030 = OR(g33727, g18704) +g34031 = OR(g33735, g18705) +g34032 = OR(g33816, g18706) +g34033 = OR(g33821, g18708) +g34034 = OR(g33719, g18713) +g34035 = OR(g33721, g18714) +g34036 = OR(g33722, g18715) +g34037 = OR(g33803, g18734) +g34038 = OR(g33731, g18735) +g34039 = OR(g33743, g18736) +g34040 = OR(g33818, g18737) +g34041 = OR(g33829, g18739) +g34043 = OR(g33903, g33905) +g34046 = OR(g33906, g33908) +g34055 = OR(g33909, g33910) +g34057 = OR(g33911, g33915) +g34064 = OR(g33919, g33922) +g34090 = OR(g33676, g33680) +g34095 = OR(g33681, g33687) +g34099 = OR(g33684, g33689) +g34100 = OR(g33690, g33697) +g34101 = OR(g33693, g33700) +g34103 = OR(g33701, g33707) +g34107 = OR(g33710, g33121) +g34125 = OR(g33724, g33124) +g34127 = OR(g33657, g32438) +g34148 = OR(g33758, g19656) +g34149 = OR(g33760, g19674) +g34153 = OR(g33899, g33451) +g34158 = OR(g33784, g19740) +g34166 = OR(g33785, g19752) +g34167 = OR(g33786, g19768) +g34168 = OR(g33787, g19784) +g34170 = OR(g33790, g19855) +g34172 = OR(g33795, g19914) +g34189 = OR(g33801, g33808) +g34190 = OR(g33802, g33810) +g34193 = OR(g33809, g33814) +g34194 = OR(g33811, g33815) +g34199 = OR(g33820, g33828) +g34204 = OR(g33832, g33833) +g34206 = OR(g33834, g33836) +g34207 = OR(g33835, g33304) +g34231 = OR(g33898, g33902) +g34232 = OR(g33451, g33944) +g34233 = OR(g32455, g33951) +g34234 = OR(g32520, g33952) +g34235 = OR(g32585, g33953) +g34236 = OR(g32650, g33954) +g34237 = OR(g32715, g33955) +g34238 = OR(g32780, g33956) +g34239 = OR(g32845, g33957) +g34240 = OR(g32910, g33958) +g34249 = OR(g34110, g21702) +g34250 = OR(g34111, g21713) +g34251 = OR(g34157, g18147) +g34252 = OR(g34146, g18180) +g34253 = OR(g34171, g24300) +g34254 = OR(g34116, g24301) +g34255 = OR(g34120, g24302) +g34256 = OR(g34173, g24303) +g34257 = OR(g34226, g18674) +g34258 = OR(g34211, g18675) +g34259 = OR(g34066, g18679) +g34260 = OR(g34113, g18680) +g34261 = OR(g34074, g18688) +g34262 = OR(g34075, g18697) +g34263 = OR(g34078, g18699) +g34264 = OR(g34081, g18701) +g34265 = OR(g34117, g18711) +g34266 = OR(g34076, g18719) +g34267 = OR(g34079, g18728) +g34268 = OR(g34082, g18730) +g34269 = OR(g34083, g18732) +g34273 = OR(g27765, g34203) +g34274 = OR(g27822, g34205) +g34278 = OR(g26829, g34212) +g34280 = OR(g26833, g34213) +g34282 = OR(g26838, g34214) +g34283 = OR(g26839, g34215) +g34286 = OR(g26842, g34216) +g34288 = OR(g26846, g34217) +g34289 = OR(g26847, g34218) +g34290 = OR(g26848, g34219) +g34292 = OR(g26853, g34223) +g34293 = OR(g26854, g34224) +g34294 = OR(g26855, g34225) +g34297 = OR(g26858, g34228) +g34300 = OR(g26864, g34230) +g34303 = OR(g25768, g34045) +g34305 = OR(g25775, g34050) +g34306 = OR(g25782, g34054) +g34314 = OR(g25831, g34061) +g34318 = OR(g25850, g34063) +g34321 = OR(g25866, g34065) +g34330 = OR(g34069, g33717) +g34331 = OR(g27121, g34072) +g34332 = OR(g34071, g33723) +g34347 = OR(g25986, g34102) +g34349 = OR(g26019, g34104) +g34350 = OR(g26048, g34106) +g34352 = OR(g26079, g34109) +g34353 = OR(g26088, g34114) +g34366 = OR(g26257, g34133) +g34368 = OR(g26274, g34135) +g34369 = OR(g26279, g34136) +g34372 = OR(g26287, g34137) +g34373 = OR(g26292, g34138) +g34374 = OR(g26294, g34139) +g34376 = OR(g26301, g34140) +g34377 = OR(g26304, g34141) +g34379 = OR(g26312, g34143) +g34399 = OR(g34178, g25067) +g34402 = OR(g34179, g25084) +g34403 = OR(g34180, g25085) +g34404 = OR(g34182, g25102) +g34405 = OR(g34183, g25103) +g34406 = OR(g34184, g25123) +g34407 = OR(g34185, g25124) +g34411 = OR(g34186, g25142) +g34412 = OR(g34187, g25143) +g34416 = OR(g34191, g25159) +g34417 = OR(g27678, g34196) +g34421 = OR(g27686, g34198) +g34438 = OR(g34348, g18150) +g34439 = OR(g34344, g18181) +g34440 = OR(g34364, g24226) +g34441 = OR(g34381, g18540) +g34442 = OR(g34380, g18542) +g34443 = OR(g34385, g18545) +g34444 = OR(g34389, g18546) +g34445 = OR(g34382, g18548) +g34446 = OR(g34390, g18550) +g34447 = OR(g34363, g18552) +g34448 = OR(g34365, g18553) +g34449 = OR(g34279, g18662) +g34450 = OR(g34281, g18663) +g34451 = OR(g34393, g18664) +g34452 = OR(g34401, g18665) +g34453 = OR(g34410, g18666) +g34454 = OR(g34414, g18667) +g34455 = OR(g34284, g18668) +g34456 = OR(g34395, g18669) +g34457 = OR(g34394, g18670) +g34458 = OR(g34396, g18671) +g34459 = OR(g34415, g18673) +g34460 = OR(g34301, g18677) +g34461 = OR(g34291, g18681) +g34462 = OR(g34334, g18685) +g34463 = OR(g34338, g18686) +g34464 = OR(g34340, g18687) +g34465 = OR(g34295, g18712) +g34466 = OR(g34337, g18716) +g34467 = OR(g34341, g18717) +g34468 = OR(g34342, g18718) +g34494 = OR(g26849, g34413) +g34535 = OR(g34309, g34073) +g34537 = OR(g34324, g34084) +g34598 = OR(g34541, g18136) +g34599 = OR(g34542, g18149) +g34600 = OR(g34538, g18182) +g34601 = OR(g34488, g18211) +g34602 = OR(g34489, g18269) +g34603 = OR(g34561, g15075) +g34604 = OR(g34563, g15076) +g34605 = OR(g34566, g15077) +g34606 = OR(g34564, g15080) +g34607 = OR(g34567, g15081) +g34608 = OR(g34568, g15082) +g34609 = OR(g34503, g18563) +g34610 = OR(g34507, g18564) +g34611 = OR(g34508, g18565) +g34612 = OR(g34514, g18566) +g34613 = OR(g34515, g18567) +g34614 = OR(g34518, g18568) +g34615 = OR(g34516, g18576) +g34616 = OR(g34519, g18577) +g34617 = OR(g34526, g18579) +g34618 = OR(g34527, g18580) +g34619 = OR(g34528, g18581) +g34620 = OR(g34529, g18582) +g34621 = OR(g34517, g18583) +g34622 = OR(g34520, g18584) +g34623 = OR(g34525, g18585) +g34624 = OR(g34509, g18592) +g34625 = OR(g34532, g18610) +g34626 = OR(g34533, g18627) +g34627 = OR(g34534, g18644) +g34628 = OR(g34493, g18653) +g34629 = OR(g34495, g18654) +g34630 = OR(g34560, g15117) +g34631 = OR(g34562, g15118) +g34632 = OR(g34565, g15119) +g34633 = OR(g34481, g18690) +g34634 = OR(g34483, g18691) +g34635 = OR(g34485, g18692) +g34636 = OR(g34476, g18693) +g34637 = OR(g34478, g18694) +g34638 = OR(g34484, g18721) +g34639 = OR(g34486, g18722) +g34640 = OR(g34487, g18723) +g34641 = OR(g34479, g18724) +g34642 = OR(g34482, g18725) +g34643 = OR(g34554, g18752) +g34644 = OR(g34555, g18769) +g34645 = OR(g34556, g18786) +g34646 = OR(g34557, g18803) +g34647 = OR(g34558, g18820) +g34649 = OR(g33111, g34492) +g34657 = OR(g33114, g34497) +g34663 = OR(g32028, g34500) +g34693 = OR(g34513, g34310) +g34695 = OR(g34523, g34322) +g34708 = OR(g33381, g34572) +g34719 = OR(g34701, g18133) +g34720 = OR(g34694, g18134) +g34721 = OR(g34696, g18135) +g34722 = OR(g34707, g18137) +g34723 = OR(g34710, g18139) +g34724 = OR(g34702, g18152) +g34725 = OR(g34700, g18183) +g34726 = OR(g34665, g18212) +g34727 = OR(g34655, g18213) +g34728 = OR(g34661, g18214) +g34729 = OR(g34666, g18270) +g34730 = OR(g34658, g18271) +g34731 = OR(g34662, g18272) +g34732 = OR(g34686, g18593) +g34733 = OR(g34678, g18651) +g34734 = OR(g34681, g18652) +g34735 = OR(g34709, g15116) +g34761 = OR(g34679, g34506) +g34762 = OR(g34687, g34524) +g34781 = OR(g33431, g34715) +g34783 = OR(g33110, g34667) +g34790 = OR(g34774, g18151) +g34791 = OR(g34771, g18184) +g34792 = OR(g34750, g18569) +g34793 = OR(g34744, g18570) +g34794 = OR(g34746, g18571) +g34795 = OR(g34753, g18572) +g34796 = OR(g34745, g18573) +g34797 = OR(g34747, g18574) +g34798 = OR(g34754, g18575) +g34799 = OR(g34751, g18578) +g34800 = OR(g34752, g18586) +g34801 = OR(g34756, g18588) +g34802 = OR(g34757, g18589) +g34803 = OR(g34758, g18590) +g34804 = OR(g34740, g18591) +g34805 = OR(g34748, g18594) +g34806 = OR(g34763, g18595) +g34807 = OR(g34764, g18596) +g34808 = OR(g34765, g18599) +g34809 = OR(g33677, g34738) +g34819 = OR(g34741, g34684) +g34826 = OR(g34742, g34685) +g34843 = OR(g33924, g34782) +g34849 = OR(g34842, g18154) +g34850 = OR(g34841, g18185) +g34856 = OR(g34811, g34743) +g34880 = OR(g34867, g18153) +g34881 = OR(g34866, g18187) +g34882 = OR(g34876, g18659) +g34884 = OR(g34858, g21666) +g34887 = OR(g34865, g21670) +g34890 = OR(g34863, g21674) +g34894 = OR(g34862, g21678) +g34897 = OR(g34861, g21682) +g34900 = OR(g34860, g21686) +g34903 = OR(g34859, g21690) +g34906 = OR(g34857, g21694) +g34911 = OR(g34909, g18188) +g34931 = OR(g2984, g34912) +g34957 = OR(g34948, g21662) +g34970 = OR(g34868, g34961) +g34971 = OR(g34869, g34962) +g34974 = OR(g34870, g34963) +g34975 = OR(g34871, g34964) +g34976 = OR(g34872, g34965) +g34977 = OR(g34873, g34966) +g34978 = OR(g34874, g34967) +g34979 = OR(g34875, g34968) +g34980 = OR(g34969, g18587) +g35000 = OR(g34953, g34999) + +I11824 = NAND(g4593, g4601) +I11825 = NAND(g4593, I11824) +I11826 = NAND(g4601, I11824) +g7133 = NAND(I11825, I11826) +g7150 = NAND(g5016, g5062) +g7167 = NAND(g5360, g5406) +g7184 = NAND(g5706, g5752) +I11864 = NAND(g4434, g4401) +I11865 = NAND(g4434, I11864) +I11866 = NAND(g4401, I11864) +g7201 = NAND(I11865, I11866) +g7209 = NAND(g6052, g6098) +I11877 = NAND(g4388, g4430) +I11878 = NAND(g4388, I11877) +I11879 = NAND(g4430, I11877) +g7223 = NAND(I11878, I11879) +g7227 = NAND(g4584, g4593) +g7228 = NAND(g6398, g6444) +g7442 = NAND(g896, g890) +g7549 = NAND(g1018, g1030) +g7582 = NAND(g1361, g1373) +I12074 = NAND(g996, g979) +I12075 = NAND(g996, I12074) +I12076 = NAND(g979, I12074) +g7598 = NAND(I12075, I12076) +g7611 = NAND(g4057, g4064) +I12096 = NAND(g1339, g1322) +I12097 = NAND(g1339, I12096) +I12098 = NAND(g1322, I12096) +g7620 = NAND(I12097, I12098) +g7690 = NAND(g4669, g4659, g4653) +g7701 = NAND(g4859, g4849, g4843) +I12203 = NAND(g1094, g1135) +I12204 = NAND(g1094, I12203) +I12205 = NAND(g1135, I12203) +g7803 = NAND(I12204, I12205) +I12217 = NAND(g1437, g1478) +I12218 = NAND(g1437, I12217) +I12219 = NAND(g1478, I12217) +g7823 = NAND(I12218, I12219) +g7836 = NAND(g4653, g4688) +g7846 = NAND(g4843, g4878) +g7850 = NAND(g554, g807) +I12240 = NAND(g1111, g1105) +I12241 = NAND(g1111, I12240) +I12242 = NAND(g1105, I12240) +g7857 = NAND(I12241, I12242) +I12251 = NAND(g1124, g1129) +I12252 = NAND(g1124, I12251) +I12253 = NAND(g1129, I12251) +g7869 = NAND(I12252, I12253) +I12261 = NAND(g1454, g1448) +I12262 = NAND(g1454, I12261) +I12263 = NAND(g1448, I12261) +g7879 = NAND(I12262, I12263) +I12269 = NAND(g1141, g956) +I12270 = NAND(g1141, I12269) +I12271 = NAND(g956, I12269) +g7885 = NAND(I12270, I12271) +I12277 = NAND(g1467, g1472) +I12278 = NAND(g1467, I12277) +I12279 = NAND(g1472, I12277) +g7887 = NAND(I12278, I12279) +I12287 = NAND(g1484, g1300) +I12288 = NAND(g1484, I12287) +I12289 = NAND(g1300, I12287) +g7897 = NAND(I12288, I12289) +I12344 = NAND(g3106, g3111) +I12345 = NAND(g3106, I12344) +I12346 = NAND(g3111, I12344) +g8010 = NAND(I12345, I12346) +I12372 = NAND(g3457, g3462) +I12373 = NAND(g3457, I12372) +I12374 = NAND(g3462, I12372) +g8069 = NAND(I12373, I12374) +g8105 = NAND(g3068, g3072) +I12401 = NAND(g3808, g3813) +I12402 = NAND(g3808, I12401) +I12403 = NAND(g3813, I12401) +g8124 = NAND(I12402, I12403) +g8163 = NAND(g3419, g3423) +g8227 = NAND(g3770, g3774) +I12468 = NAND(g405, g392) +I12469 = NAND(g405, I12468) +I12470 = NAND(g392, I12468) +g8238 = NAND(I12469, I12470) +g8292 = NAND(g218, g215) +g8347 = NAND(g4358, g4349, g4340) +I12544 = NAND(g191, g194) +I12545 = NAND(g191, I12544) +I12546 = NAND(g194, I12544) +g8359 = NAND(I12545, I12546) +g8434 = NAND(g3080, g3072) +g8500 = NAND(g3431, g3423) +g8561 = NAND(g3782, g3774) +g8609 = NAND(g1171, g1157) +g8632 = NAND(g1514, g1500) +g8678 = NAND(g376, g358) +g8691 = NAND(g3267, g3310, g3281, g3303) +g8728 = NAND(g3618, g3661, g3632, g3654) +I12728 = NAND(g4291, g4287) +I12729 = NAND(g4291, I12728) +I12730 = NAND(g4287, I12728) +g8737 = NAND(I12729, I12730) +g8751 = NAND(g3969, g4012, g3983, g4005) +g8769 = NAND(g691, g714) +g8803 = NAND(g128, g4646) +g8806 = NAND(g358, g370, g376, g385) +g8829 = NAND(g5011, g4836) +g8847 = NAND(g4831, g4681) +I12840 = NAND(g4222, g4235) +I12841 = NAND(g4222, I12840) +I12842 = NAND(g4235, I12840) +g8871 = NAND(I12841, I12842) +I12848 = NAND(g4281, g4277) +I12849 = NAND(g4281, I12848) +I12850 = NAND(g4277, I12848) +g8873 = NAND(I12849, I12850) +g8889 = NAND(g3684, g4871) +I12876 = NAND(g4200, g4180) +I12877 = NAND(g4200, I12876) +I12878 = NAND(g4180, I12876) +g8913 = NAND(I12877, I12878) +g8967 = NAND(g4264, g4258) +g9092 = NAND(g3004, g3050) +g9177 = NAND(g3355, g3401) +g9203 = NAND(g3706, g3752) +g9246 = NAND(g847, g812) +I13043 = NAND(g5115, g5120) +I13044 = NAND(g5115, I13043) +I13045 = NAND(g5120, I13043) +g9258 = NAND(I13044, I13045) +I13065 = NAND(g4308, g4304) +I13066 = NAND(g4308, I13065) +I13067 = NAND(g4304, I13065) +g9295 = NAND(I13066, I13067) +I13077 = NAND(g5462, g5467) +I13078 = NAND(g5462, I13077) +I13079 = NAND(g5467, I13077) +g9310 = NAND(I13078, I13079) +g9334 = NAND(g827, g832) +g9372 = NAND(g5080, g5084) +I13109 = NAND(g5808, g5813) +I13110 = NAND(g5808, I13109) +I13111 = NAND(g5813, I13109) +g9391 = NAND(I13110, I13111) +g9442 = NAND(g5424, g5428) +I13139 = NAND(g6154, g6159) +I13140 = NAND(g6154, I13139) +I13141 = NAND(g6159, I13139) +g9461 = NAND(I13140, I13141) +g9485 = NAND(g1657, g1624) +g9509 = NAND(g5770, g5774) +I13182 = NAND(g6500, g6505) +I13183 = NAND(g6500, I13182) +I13184 = NAND(g6505, I13182) +g9528 = NAND(I13183, I13184) +g9538 = NAND(g1792, g1760) +g9543 = NAND(g2217, g2185) +g9567 = NAND(g6116, g6120) +g9591 = NAND(g1926, g1894) +g9595 = NAND(g2351, g2319) +g9629 = NAND(g6462, g6466) +g9645 = NAND(g2060, g2028) +g9654 = NAND(g2485, g2453) +g9663 = NAND(g128, g4646) +g9705 = NAND(g2619, g2587) +g9715 = NAND(g5011, g4836) +g9724 = NAND(g5092, g5084) +I13334 = NAND(g1687, g1691) +I13335 = NAND(g1687, I13334) +I13336 = NAND(g1691, I13334) +g9750 = NAND(I13335, I13336) +g9775 = NAND(g4831, g4681) +g9800 = NAND(g5436, g5428) +I13382 = NAND(g269, g246) +I13383 = NAND(g269, I13382) +I13384 = NAND(g246, I13382) +g9823 = NAND(I13383, I13384) +I13390 = NAND(g1821, g1825) +I13391 = NAND(g1821, I13390) +I13392 = NAND(g1825, I13390) +g9825 = NAND(I13391, I13392) +I13401 = NAND(g2246, g2250) +I13402 = NAND(g2246, I13401) +I13403 = NAND(g2250, I13401) +g9830 = NAND(I13402, I13403) +g9852 = NAND(g3684, g4871) +g9883 = NAND(g5782, g5774) +I13442 = NAND(g262, g239) +I13443 = NAND(g262, I13442) +I13444 = NAND(g239, I13442) +g9904 = NAND(I13443, I13444) +I13452 = NAND(g1955, g1959) +I13453 = NAND(g1955, I13452) +I13454 = NAND(g1959, I13452) +g9908 = NAND(I13453, I13454) +I13462 = NAND(g2380, g2384) +I13463 = NAND(g2380, I13462) +I13464 = NAND(g2384, I13462) +g9912 = NAND(I13463, I13464) +g9954 = NAND(g6128, g6120) +I13497 = NAND(g255, g232) +I13498 = NAND(g255, I13497) +I13499 = NAND(g232, I13497) +g9966 = NAND(I13498, I13499) +I13509 = NAND(g2089, g2093) +I13510 = NAND(g2089, I13509) +I13511 = NAND(g2093, I13509) +g9972 = NAND(I13510, I13511) +I13518 = NAND(g2514, g2518) +I13519 = NAND(g2514, I13518) +I13520 = NAND(g2518, I13518) +g9975 = NAND(I13519, I13520) +g10022 = NAND(g6474, g6466) +I13564 = NAND(g2648, g2652) +I13565 = NAND(g2648, I13564) +I13566 = NAND(g2652, I13564) +g10041 = NAND(I13565, I13566) +g10124 = NAND(g5276, g5320, g5290, g5313) +g10160 = NAND(g5623, g5666, g5637, g5659) +g10185 = NAND(g5969, g6012, g5983, g6005) +g10207 = NAND(g6315, g6358, g6329, g6351) +g10224 = NAND(g6661, g6704, g6675, g6697) +I13729 = NAND(g4534, g4537) +I13730 = NAND(g4534, I13729) +I13731 = NAND(g4537, I13729) +g10307 = NAND(I13730, I13731) +I13749 = NAND(g4608, g4584) +I13750 = NAND(g4608, I13749) +I13751 = NAND(g4584, I13749) +g10336 = NAND(I13750, I13751) +I13850 = NAND(g862, g7397) +I13851 = NAND(g862, I13850) +I13852 = NAND(g7397, I13850) +g10472 = NAND(I13851, I13852) +g10511 = NAND(g4628, g7202, g4621) +g10515 = NAND(g10337, g5022) +g10520 = NAND(g7195, g7115) +g10529 = NAND(g1592, g7308) +g10537 = NAND(g7138, g5366) +g10550 = NAND(g7268, g7308) +g10551 = NAND(g1728, g7356) +g10552 = NAND(g2153, g7374) +g10556 = NAND(g7971, g8133) +g10561 = NAND(g7157, g5712) +g10566 = NAND(g7315, g7356) +g10567 = NAND(g1862, g7405) +g10568 = NAND(g7328, g7374) +g10569 = NAND(g2287, g7418) +g10573 = NAND(g7992, g8179) +g10578 = NAND(g7174, g6058) +g10583 = NAND(g7475, g862) +g10584 = NAND(g7362, g7405) +g10585 = NAND(g1996, g7451) +g10586 = NAND(g7380, g7418) +g10587 = NAND(g2421, g7456) +g10598 = NAND(g7191, g6404) +g10601 = NAND(g896, g7397) +g10602 = NAND(g7411, g7451) +g10603 = NAND(g10077, g9751) +g10604 = NAND(g7424, g7456) +g10605 = NAND(g2555, g7490) +g10609 = NAND(g10111, g9826) +g10610 = NAND(g7462, g7490) +g10611 = NAND(g10115, g9831) +g10614 = NAND(g9024, g8977, g8928) +g10617 = NAND(g10151, g9909) +g10618 = NAND(g10153, g9913) +g10622 = NAND(g10178, g9973) +g10623 = NAND(g10181, g9976) +g10653 = NAND(g10204, g10042) +g10726 = NAND(g7304, g7661, g979, g1061) +g10737 = NAND(g6961, g9848) +g10738 = NAND(g6961, g10308) +g10754 = NAND(g7936, g7913, g8411) +g10755 = NAND(g7352, g7675, g1322, g1404) +g10759 = NAND(g7537, g324) +g10775 = NAND(g7960, g7943, g8470) +g10796 = NAND(g7537, g7523) +g10820 = NAND(g9985, g9920, g9843) +g10905 = NAND(g1116, g7304) +g10909 = NAND(g7304, g1116) +g10916 = NAND(g1146, g7854) +g10928 = NAND(g8181, g8137, g417) +g10929 = NAND(g1099, g7854) +g10935 = NAND(g1459, g7352) +g10939 = NAND(g7352, g1459) +g10946 = NAND(g1489, g7876) +g10951 = NAND(g7845, g7868) +g10961 = NAND(g1442, g7876) +g10971 = NAND(g7867, g7886) +g11002 = NAND(g7475, g862) +g11020 = NAND(g9187, g9040) +g11117 = NAND(g8087, g8186, g8239) +I14169 = NAND(g8389, g3119) +I14170 = NAND(g8389, I14169) +I14171 = NAND(g3119, I14169) +g11118 = NAND(I14170, I14171) +g11130 = NAND(g1221, g7918) +g11134 = NAND(g8138, g8240, g8301) +I14185 = NAND(g8442, g3470) +I14186 = NAND(g8442, I14185) +I14187 = NAND(g3470, I14185) +g11135 = NAND(I14186, I14187) +g11149 = NAND(g1564, g7948) +I14204 = NAND(g8508, g3821) +I14205 = NAND(g8508, I14204) +I14206 = NAND(g3821, I14204) +g11153 = NAND(I14205, I14206) +I14211 = NAND(g9252, g9295) +I14212 = NAND(g9252, I14211) +I14213 = NAND(g9295, I14211) +g11154 = NAND(I14212, I14213) +g11155 = NAND(g4776, g7892, g9030) +I14228 = NAND(g979, g8055) +I14229 = NAND(g979, I14228) +I14230 = NAND(g8055, I14228) +g11169 = NAND(I14229, I14230) +g11172 = NAND(g8478, g3096) +g11173 = NAND(g4966, g7898, g9064) +I14247 = NAND(g1322, g8091) +I14248 = NAND(g1322, I14247) +I14249 = NAND(g8091, I14247) +g11189 = NAND(I14248, I14249) +g11190 = NAND(g8539, g3447) +I14257 = NAND(g8154, g3133) +I14258 = NAND(g8154, I14257) +I14259 = NAND(g3133, I14257) +g11193 = NAND(I14258, I14259) +g11200 = NAND(g8592, g3798) +I14275 = NAND(g8218, g3484) +I14276 = NAND(g8218, I14275) +I14277 = NAND(g3484, I14275) +g11206 = NAND(I14276, I14277) +I14289 = NAND(g8282, g3835) +I14290 = NAND(g8282, I14289) +I14291 = NAND(g3835, I14289) +g11224 = NAND(I14290, I14291) +g11245 = NAND(g7636, g7733, g7697) +g11251 = NAND(g8438, g3092) +g11279 = NAND(g8504, g3443) +I14330 = NAND(g225, g9966) +I14331 = NAND(g225, I14330) +I14332 = NAND(g9966, I14330) +g11292 = NAND(I14331, I14332) +g11302 = NAND(g9496, g3281) +g11312 = NAND(g8565, g3794) +g11320 = NAND(g4633, g4621, g7202) +I14350 = NAND(g8890, g8848) +I14351 = NAND(g8890, I14350) +I14352 = NAND(g8848, I14350) +g11323 = NAND(I14351, I14352) +g11326 = NAND(g8993, g376, g365, g370) +g11330 = NAND(g9483, g1193) +I14368 = NAND(g8481, g3303) +I14369 = NAND(g8481, I14368) +I14370 = NAND(g3303, I14368) +g11350 = NAND(I14369, I14370) +g11355 = NAND(g9551, g3310) +g11356 = NAND(g9552, g3632) +g11374 = NAND(g9536, g1536) +g11381 = NAND(g9660, g3274) +g11382 = NAND(g8644, g6895, g8663) +I14398 = NAND(g8542, g3654) +I14399 = NAND(g8542, I14398) +I14400 = NAND(g3654, I14398) +g11389 = NAND(I14399, I14400) +g11394 = NAND(g9600, g3661) +g11395 = NAND(g9601, g3983) +g11396 = NAND(g8713, g4688) +g11405 = NAND(g2741, g2735, g6856, g2748) +g11409 = NAND(g9842, g3298) +g11410 = NAND(g6875, g6895, g8696) +g11411 = NAND(g9713, g3625) +g11412 = NAND(g8666, g6918, g8697) +I14427 = NAND(g8595, g4005) +I14428 = NAND(g8595, I14427) +I14429 = NAND(g4005, I14427) +g11419 = NAND(I14428, I14429) +g11424 = NAND(g9662, g4012) +g11426 = NAND(g8742, g4878) +g11432 = NAND(g10295, g8864) +g11441 = NAND(g9599, g3267) +g11442 = NAND(g8644, g3288, g3343) +g11443 = NAND(g9916, g3649) +g11444 = NAND(g6905, g6918, g8733) +g11445 = NAND(g9771, g3976) +g11446 = NAND(g8700, g6941, g8734) +g11479 = NAND(g6875, g3288, g3347) +g11480 = NAND(g10323, g8906) +g11489 = NAND(g9661, g3618) +g11490 = NAND(g8666, g3639, g3694) +g11491 = NAND(g9982, g4000) +g11492 = NAND(g6928, g6941, g8756) +I14480 = NAND(g10074, g655) +I14481 = NAND(g10074, I14480) +I14482 = NAND(g655, I14480) +g11511 = NAND(I14481, I14482) +g11533 = NAND(g6905, g3639, g3698) +g11534 = NAND(g7121, g8958) +g11543 = NAND(g9714, g3969) +g11544 = NAND(g8700, g3990, g4045) +I14497 = NAND(g9020, g8737) +I14498 = NAND(g9020, I14497) +I14499 = NAND(g8737, I14497) +g11545 = NAND(I14498, I14499) +I14508 = NAND(g370, g8721) +I14509 = NAND(g370, I14508) +I14510 = NAND(g8721, I14508) +g11559 = NAND(I14509, I14510) +I14516 = NAND(g10147, g661) +I14517 = NAND(g10147, I14516) +I14518 = NAND(g661, I14516) +g11561 = NAND(I14517, I14518) +g11590 = NAND(g6928, g3990, g4049) +I14530 = NAND(g8840, g8873) +I14531 = NAND(g8840, I14530) +I14532 = NAND(g8873, I14530) +g11591 = NAND(I14531, I14532) +g11639 = NAND(g8933, g4722) +g11674 = NAND(g8676, g4674) +g11675 = NAND(g8984, g4912) +g11676 = NAND(g358, g8944, g376, g385) +g11679 = NAND(g8836, g802) +g11707 = NAND(g8718, g4864) +g11708 = NAND(g10147, g10110) +I14609 = NAND(g8993, g8678) +I14610 = NAND(g8993, I14609) +I14611 = NAND(g8678, I14609) +g11761 = NAND(I14610, I14611) +g11858 = NAND(g9014, g3010) +g11881 = NAND(g9060, g3361) +g11892 = NAND(g7777, g9086) +g11903 = NAND(g9099, g3712) +I14712 = NAND(g9671, g5128) +I14713 = NAND(g9671, I14712) +I14714 = NAND(g5128, I14712) +g11906 = NAND(I14713, I14714) +g11914 = NAND(g8187, g1648) +I14733 = NAND(g9732, g5475) +I14734 = NAND(g9732, I14733) +I14735 = NAND(g5475, I14733) +g11923 = NAND(I14734, I14735) +g11933 = NAND(g837, g9334, g7197) +g11934 = NAND(g8139, g8187) +g11936 = NAND(g8241, g1783) +g11938 = NAND(g8259, g2208) +I14764 = NAND(g9808, g5821) +I14765 = NAND(g9808, I14764) +I14766 = NAND(g5821, I14764) +g11944 = NAND(I14765, I14766) +g11951 = NAND(g9166, g847, g703) +g11952 = NAND(g1624, g8187) +g11953 = NAND(g8195, g8241) +g11955 = NAND(g8302, g1917) +g11957 = NAND(g8205, g8259) +g11959 = NAND(g8316, g2342) +g11961 = NAND(g9777, g5105) +I14788 = NAND(g9891, g6167) +I14789 = NAND(g9891, I14788) +I14790 = NAND(g6167, I14788) +g11962 = NAND(I14789, I14790) +g11968 = NAND(g837, g9334, g9086) +g11969 = NAND(g7252, g1636) +g11970 = NAND(g1760, g8241) +g11971 = NAND(g8249, g8302) +g11973 = NAND(g8365, g2051) +g11974 = NAND(g2185, g8259) +g11975 = NAND(g8267, g8316) +g11977 = NAND(g8373, g2476) +g11979 = NAND(g9861, g5452) +I14816 = NAND(g9962, g6513) +I14817 = NAND(g9962, I14816) +I14818 = NAND(g6513, I14816) +g11980 = NAND(I14817, I14818) +g11990 = NAND(g9166, g703) +g11992 = NAND(g7275, g1772) +g11993 = NAND(g1894, g8302) +g11994 = NAND(g8310, g8365) +g11996 = NAND(g7280, g2197) +g11997 = NAND(g2319, g8316) +g11998 = NAND(g8324, g8373) +g12000 = NAND(g8418, g2610) +I14853 = NAND(g9433, g5142) +I14854 = NAND(g9433, I14853) +I14855 = NAND(g5142, I14853) +g12001 = NAND(I14854, I14855) +g12008 = NAND(g9932, g5798) +g12014 = NAND(g7197, g703) +g12016 = NAND(g1648, g8093) +g12019 = NAND(g7322, g1906) +g12020 = NAND(g2028, g8365) +g12022 = NAND(g7335, g2331) +g12023 = NAND(g2453, g8373) +g12024 = NAND(g8381, g8418) +I14883 = NAND(g9500, g5489) +I14884 = NAND(g9500, I14883) +I14885 = NAND(g5489, I14883) +g12028 = NAND(I14884, I14885) +g12035 = NAND(g10000, g6144) +g12042 = NAND(g9086, g703) +g12044 = NAND(g1657, g8139) +g12045 = NAND(g1783, g8146) +g12048 = NAND(g7369, g2040) +g12049 = NAND(g2208, g8150) +g12052 = NAND(g7387, g2465) +g12053 = NAND(g2587, g8418) +I14923 = NAND(g9558, g5835) +I14924 = NAND(g9558, I14923) +I14925 = NAND(g5835, I14923) +g12066 = NAND(I14924, I14925) +g12073 = NAND(g10058, g6490) +g12078 = NAND(g8187, g8093) +g12079 = NAND(g1792, g8195) +g12080 = NAND(g1917, g8201) +g12083 = NAND(g2217, g8205) +g12084 = NAND(g2342, g8211) +g12087 = NAND(g7431, g2599) +I14955 = NAND(g9620, g6181) +I14956 = NAND(g9620, I14955) +I14957 = NAND(g6181, I14955) +g12100 = NAND(I14956, I14957) +g12111 = NAND(g847, g9166) +g12112 = NAND(g8139, g1624) +g12114 = NAND(g8241, g8146) +g12115 = NAND(g1926, g8249) +g12116 = NAND(g2051, g8255) +g12118 = NAND(g8259, g8150) +g12119 = NAND(g2351, g8267) +g12120 = NAND(g2476, g8273) +g12124 = NAND(g8741, g4674) +g12125 = NAND(g9728, g5101) +I14991 = NAND(g9685, g6527) +I14992 = NAND(g9685, I14991) +I14993 = NAND(g6527, I14991) +g12136 = NAND(I14992, I14993) +I15002 = NAND(g9691, g1700) +I15003 = NAND(g9691, I15002) +I15004 = NAND(g1700, I15002) +g12144 = NAND(I15003, I15004) +g12145 = NAND(g8195, g1760) +g12147 = NAND(g8302, g8201) +g12148 = NAND(g2060, g8310) +g12149 = NAND(g8205, g2185) +g12151 = NAND(g8316, g8211) +g12152 = NAND(g2485, g8324) +g12153 = NAND(g2610, g8330) +g12155 = NAND(g7753, g7717) +g12159 = NAND(g8765, g4864) +g12169 = NAND(g9804, g5448) +g12185 = NAND(g9905, g799) +I15041 = NAND(g9752, g1834) +I15042 = NAND(g9752, I15041) +I15043 = NAND(g1834, I15041) +g12187 = NAND(I15042, I15043) +g12188 = NAND(g8249, g1894) +g12190 = NAND(g8365, g8255) +I15051 = NAND(g9759, g2259) +I15052 = NAND(g9759, I15051) +I15053 = NAND(g2259, I15051) +g12191 = NAND(I15052, I15053) +g12192 = NAND(g8267, g2319) +g12194 = NAND(g8373, g8273) +g12195 = NAND(g2619, g8381) +g12196 = NAND(g8764, g4688) +g12197 = NAND(g7296, g5290) +g12207 = NAND(g9887, g5794) +I15078 = NAND(g9827, g1968) +I15079 = NAND(g9827, I15078) +I15080 = NAND(g1968, I15078) +g12221 = NAND(I15079, I15080) +g12222 = NAND(g8310, g2028) +I15087 = NAND(g9832, g2393) +I15088 = NAND(g9832, I15087) +I15089 = NAND(g2393, I15087) +g12224 = NAND(I15088, I15089) +g12225 = NAND(g8324, g2453) +g12227 = NAND(g8418, g8330) +g12232 = NAND(g8804, g4878) +I15105 = NAND(g9780, g5313) +I15106 = NAND(g9780, I15105) +I15107 = NAND(g5313, I15105) +g12239 = NAND(I15106, I15107) +g12244 = NAND(g7343, g5320) +g12245 = NAND(g7344, g5637) +g12255 = NAND(g9958, g6140) +I15121 = NAND(g9910, g2102) +I15122 = NAND(g9910, I15121) +I15123 = NAND(g2102, I15121) +g12285 = NAND(I15122, I15123) +I15128 = NAND(g9914, g2527) +I15129 = NAND(g9914, I15128) +I15130 = NAND(g2527, I15128) +g12286 = NAND(I15129, I15130) +g12287 = NAND(g8381, g2587) +g12289 = NAND(g9978, g9766, g9708) +g12292 = NAND(g4698, g8933) +g12293 = NAND(g7436, g5283) +g12294 = NAND(g10044, g7018, g10090) +I15147 = NAND(g9864, g5659) +I15148 = NAND(g9864, I15147) +I15149 = NAND(g5659, I15147) +g12301 = NAND(I15148, I15149) +g12306 = NAND(g7394, g5666) +g12307 = NAND(g7395, g5983) +g12317 = NAND(g10026, g6486) +g12323 = NAND(g9480, g640) +I15166 = NAND(g9904, g9823) +I15167 = NAND(g9904, I15166) +I15168 = NAND(g9823, I15166) +g12332 = NAND(I15167, I15168) +I15174 = NAND(g9977, g2661) +I15175 = NAND(g9977, I15174) +I15176 = NAND(g2661, I15174) +g12336 = NAND(I15175, I15176) +g12340 = NAND(g4888, g8984) +g12341 = NAND(g7512, g5308) +g12342 = NAND(g7004, g7018, g10129) +g12343 = NAND(g7470, g5630) +g12344 = NAND(g10093, g7041, g10130) +I15193 = NAND(g9935, g6005) +I15194 = NAND(g9935, I15193) +I15195 = NAND(g6005, I15193) +g12351 = NAND(I15194, I15195) +g12356 = NAND(g7438, g6012) +g12357 = NAND(g7439, g6329) +g12369 = NAND(g9049, g637) +I15212 = NAND(g10035, g1714) +I15213 = NAND(g10035, I15212) +I15214 = NAND(g1714, I15212) +g12370 = NAND(I15213, I15214) +g12402 = NAND(g7704, g10266) +g12411 = NAND(g7393, g5276) +g12412 = NAND(g10044, g5297, g5348) +g12413 = NAND(g7521, g5654) +g12414 = NAND(g7028, g7041, g10165) +g12415 = NAND(g7496, g5976) +g12416 = NAND(g10133, g7064, g10166) +I15241 = NAND(g10003, g6351) +I15242 = NAND(g10003, I15241) +I15243 = NAND(g6351, I15241) +g12423 = NAND(I15242, I15243) +g12428 = NAND(g7472, g6358) +g12429 = NAND(g7473, g6675) +I15253 = NAND(g10078, g1848) +I15254 = NAND(g10078, I15253) +I15255 = NAND(g1848, I15253) +g12431 = NAND(I15254, I15255) +I15262 = NAND(g10081, g2273) +I15263 = NAND(g10081, I15262) +I15264 = NAND(g2273, I15262) +g12436 = NAND(I15263, I15264) +g12449 = NAND(g7004, g5297, g5352) +g12450 = NAND(g7738, g10281) +g12459 = NAND(g7437, g5623) +g12460 = NAND(g10093, g5644, g5694) +g12461 = NAND(g7536, g6000) +g12462 = NAND(g7051, g7064, g10190) +g12463 = NAND(g7513, g6322) +g12464 = NAND(g10169, g7087, g10191) +I15287 = NAND(g10061, g6697) +I15288 = NAND(g10061, I15287) +I15289 = NAND(g6697, I15287) +g12471 = NAND(I15288, I15289) +g12476 = NAND(g7498, g6704) +I15298 = NAND(g10112, g1982) +I15299 = NAND(g10112, I15298) +I15300 = NAND(g1982, I15298) +g12478 = NAND(I15299, I15300) +I15306 = NAND(g10116, g2407) +I15307 = NAND(g10116, I15306) +I15308 = NAND(g2407, I15306) +g12482 = NAND(I15307, I15308) +g12491 = NAND(g7285, g4462, g6961) +g12511 = NAND(g7028, g5644, g5698) +g12512 = NAND(g7766, g10312) +g12521 = NAND(g7471, g5969) +g12522 = NAND(g10133, g5990, g6040) +g12523 = NAND(g7563, g6346) +g12524 = NAND(g7074, g7087, g10212) +g12525 = NAND(g7522, g6668) +g12526 = NAND(g10194, g7110, g10213) +I15333 = NAND(g10152, g2116) +I15334 = NAND(g10152, I15333) +I15335 = NAND(g2116, I15333) +g12538 = NAND(I15334, I15335) +I15340 = NAND(g10154, g2541) +I15341 = NAND(g10154, I15340) +I15342 = NAND(g2541, I15340) +g12539 = NAND(I15341, I15342) +g12577 = NAND(g7051, g5990, g6044) +g12578 = NAND(g7791, g10341) +g12587 = NAND(g7497, g6315) +g12588 = NAND(g10169, g6336, g6386) +g12589 = NAND(g7591, g6692) +g12590 = NAND(g7097, g7110, g10229) +I15363 = NAND(g10182, g2675) +I15364 = NAND(g10182, I15363) +I15365 = NAND(g2675, I15363) +g12592 = NAND(I15364, I15365) +g12628 = NAND(g7074, g6336, g6390) +g12629 = NAND(g7812, g7142) +g12638 = NAND(g7514, g6661) +g12639 = NAND(g10194, g6682, g6732) +g12644 = NAND(g10233, g4531) +g12686 = NAND(g7097, g6682, g6736) +g12767 = NAND(g4467, g6961) +g12796 = NAND(g4467, g6961) +g12797 = NAND(g10275, g7655, g7643, g7627) +g12819 = NAND(g9848, g6961) +g12822 = NAND(g6978, g7236, g7224, g7163) +g12910 = NAND(g11002, g10601) +g12915 = NAND(g12806, g12632) +g12933 = NAND(g7150, g10515) +g12941 = NAND(g7167, g10537) +g12947 = NAND(g7184, g10561) +g12969 = NAND(g4388, g7178, g10476) +g12971 = NAND(g9024, g8977, g10664) +g12972 = NAND(g7209, g10578) +g12999 = NAND(g4392, g10476, g4401) +g13000 = NAND(g7228, g10598) +g13040 = NAND(g5196, g12002, g5308, g9780) +g13043 = NAND(g10521, g969) +g13050 = NAND(g5543, g12029, g5654, g9864) +g13057 = NAND(g969, g11294) +g13058 = NAND(g10544, g1312) +g13066 = NAND(g4430, g7178, g10590) +g13067 = NAND(g5240, g12059, g5331, g9780) +g13069 = NAND(g5889, g12067, g6000, g9935) +g13079 = NAND(g1312, g11336) +g13083 = NAND(g4392, g10590, g4434) +g13084 = NAND(g5587, g12093, g5677, g9864) +g13086 = NAND(g6235, g12101, g6346, g10003) +g13092 = NAND(g1061, g10761) +g13093 = NAND(g10649, g7661, g979, g1061) +g13097 = NAND(g5204, g12002, g5339, g9780) +g13098 = NAND(g5933, g12129, g6023, g9935) +g13100 = NAND(g6581, g12137, g6692, g10061) +g13102 = NAND(g7523, g10759) +g13104 = NAND(g1404, g10794) +g13105 = NAND(g10671, g7675, g1322, g1404) +g13108 = NAND(g5551, g12029, g5685, g9864) +g13109 = NAND(g6279, g12173, g6369, g10003) +g13115 = NAND(g1008, g11786, g11294) +g13118 = NAND(g5897, g12067, g6031, g9935) +g13119 = NAND(g6625, g12211, g6715, g10061) +g13121 = NAND(g11117, g8411) +g13124 = NAND(g10666, g7661, g979, g1061) +g13130 = NAND(g1351, g11815, g11336) +g13131 = NAND(g6243, g12101, g6377, g10003) +g13134 = NAND(g11134, g8470) +g13137 = NAND(g10699, g7675, g1322, g1404) +g13139 = NAND(g6589, g12137, g6723, g10061) +g13143 = NAND(g10695, g7661, g979, g1061) +g13176 = NAND(g10715, g7675, g1322, g1404) +g13210 = NAND(g7479, g10521) +g13217 = NAND(g4082, g10808) +g13240 = NAND(g1046, g10521) +g13241 = NAND(g7503, g10544) +g13248 = NAND(g9985, g12399, g9843) +g13256 = NAND(g11846, g11294, g11812) +g13257 = NAND(g1389, g10544) +g13260 = NAND(g1116, g10666) +g13264 = NAND(g11869, g11336, g11849) +g13266 = NAND(g12440, g9920, g9843) +g13273 = NAND(g1459, g10699) +g13281 = NAND(g10916, g1099) +g13283 = NAND(g12440, g12399, g9843) +g13284 = NAND(g10695, g1157) +g13288 = NAND(g10946, g1442) +g13291 = NAND(g10715, g1500) +g13307 = NAND(g1116, g10695) +g13315 = NAND(g1459, g10715) +g13330 = NAND(g4664, g11006) +g13346 = NAND(g4854, g11012) +g13432 = NAND(g4793, g10831) +g13459 = NAND(g7479, g11294, g11846) +g13462 = NAND(g12449, g12412, g12342, g12294) +g13464 = NAND(g10831, g4793, g4776) +g13469 = NAND(g4983, g10862) +g13475 = NAND(g1008, g11294, g11786) +g13476 = NAND(g7503, g11336, g11869) +g13478 = NAND(g12511, g12460, g12414, g12344) +g13479 = NAND(g12686, g12639, g12590, g12526) +g13486 = NAND(g10862, g4983, g4966) +g13495 = NAND(g1008, g11786, g7972) +g13496 = NAND(g1351, g11336, g11815) +g13498 = NAND(g12577, g12522, g12462, g12416) +g13499 = NAND(g11479, g11442, g11410, g11382) +g13511 = NAND(g182, g174, g203, g12812) +g13513 = NAND(g1351, g11815, g8002) +g13515 = NAND(g12628, g12588, g12524, g12464) +g13516 = NAND(g11533, g11490, g11444, g11412) +g13527 = NAND(g182, g168, g203, g12812) +g13528 = NAND(g11294, g7549, g1008) +g13529 = NAND(g11590, g11544, g11492, g11446) +g13544 = NAND(g7972, g10521, g7549, g1008) +g13551 = NAND(g11812, g7479, g7903, g10521) +g13554 = NAND(g11336, g7582, g1351) +g13573 = NAND(g8002, g10544, g7582, g1351) +g13580 = NAND(g11849, g7503, g7922, g10544) +g13600 = NAND(g3021, g11039) +g13627 = NAND(g11172, g8388) +g13628 = NAND(g3372, g11107) +g13634 = NAND(g11797, g11261) +g13666 = NAND(g11190, g8441) +g13667 = NAND(g3723, g11119) +g13672 = NAND(g8933, g11261) +g13676 = NAND(g11834, g11283) +g13708 = NAND(g11200, g8507) +g13709 = NAND(g11755, g11261) +g13712 = NAND(g8984, g11283) +g13727 = NAND(g174, g203, g168, g12812) +g13739 = NAND(g11773, g11261) +g13742 = NAND(g11780, g11283) +g13756 = NAND(g203, g12812) +g13764 = NAND(g11252, g3072) +g13779 = NAND(g11804, g11283) +g13795 = NAND(g11216, g401) +g13797 = NAND(g8102, g11273) +g13798 = NAND(g11280, g3423) +g13821 = NAND(g11251, g8340) +g13822 = NAND(g8160, g11306) +g13823 = NAND(g11313, g3774) +g13834 = NAND(g4754, g11773) +g13846 = NAND(g1116, g10649) +g13850 = NAND(g11279, g8396) +g13851 = NAND(g8224, g11360) +g13854 = NAND(g4765, g11797) +g13855 = NAND(g4944, g11804) +g13861 = NAND(g1459, g10671) +g13866 = NAND(g3239, g11194, g3321, g11519) +g13867 = NAND(g11312, g8449) +g13870 = NAND(g11773, g4732) +g13871 = NAND(g4955, g11834) +g13873 = NAND(g11566, g11729) +g13882 = NAND(g3590, g11207, g3672, g11576) +g13884 = NAND(g11797, g4727) +g13886 = NAND(g11804, g4922) +g13889 = NAND(g11566, g11435) +g13892 = NAND(g11653, g11473) +g13896 = NAND(g3227, g11194, g3281, g11350) +g13897 = NAND(g3211, g11217, g3329, g11519) +g13898 = NAND(g11621, g11747) +g13907 = NAND(g3941, g11225, g4023, g11631) +g13909 = NAND(g11396, g8847, g11674, g8803) +g13911 = NAND(g11834, g4917) +g13915 = NAND(g11566, g11473) +g13918 = NAND(g3259, g11217, g3267, g11350) +g13920 = NAND(g11621, g11483) +g13923 = NAND(g11692, g11527) +g13927 = NAND(g3578, g11207, g3632, g11389) +g13928 = NAND(g3562, g11238, g3680, g11576) +g13929 = NAND(g11669, g11763) +g13940 = NAND(g11426, g8889, g11707, g8829) +g13945 = NAND(g691, g11740) +g13948 = NAND(g11610, g8864) +g13951 = NAND(g10295, g11729) +g13955 = NAND(g11621, g11527) +g13958 = NAND(g3610, g11238, g3618, g11389) +g13960 = NAND(g11669, g11537) +g13963 = NAND(g11715, g11584) +g13967 = NAND(g3929, g11225, g3983, g11419) +g13968 = NAND(g3913, g11255, g4031, g11631) +g13977 = NAND(g11610, g11729) +g13980 = NAND(g10295, g11435) +g13983 = NAND(g11658, g8906) +g13986 = NAND(g10323, g11747) +g13990 = NAND(g11669, g11584) +g13993 = NAND(g3961, g11255, g3969, g11419) +g14005 = NAND(g11514, g11729) +g14008 = NAND(g11610, g11435) +g14011 = NAND(g10295, g11473) +g14014 = NAND(g3199, g11217, g3298, g11519) +g14015 = NAND(g11658, g11747) +g14018 = NAND(g10323, g11483) +g14021 = NAND(g11697, g8958) +g14024 = NAND(g7121, g11763) +g14038 = NAND(g11514, g11435) +g14041 = NAND(g11610, g11473) +g14045 = NAND(g11571, g11747) +g14048 = NAND(g11658, g11483) +g14051 = NAND(g10323, g11527) +g14054 = NAND(g3550, g11238, g3649, g11576) +g14055 = NAND(g11697, g11763) +g14058 = NAND(g7121, g11537) +g14066 = NAND(g11514, g11473) +g14069 = NAND(g11653, g8864) +g14072 = NAND(g11571, g11483) +g14075 = NAND(g11658, g11527) +g14079 = NAND(g11626, g11763) +g14082 = NAND(g11697, g11537) +g14085 = NAND(g7121, g11584) +g14088 = NAND(g3901, g11255, g4000, g11631) +g14089 = NAND(g11755, g4717) +g14098 = NAND(g11566, g8864) +g14101 = NAND(g11653, g11729) +g14104 = NAND(g11514, g8864) +g14107 = NAND(g11571, g11527) +g14110 = NAND(g11692, g8906) +g14113 = NAND(g11626, g11537) +g14116 = NAND(g11697, g11584) +g14120 = NAND(g11780, g4907) +g14123 = NAND(g10685, g10928) +g14127 = NAND(g11653, g11435) +g14130 = NAND(g11621, g8906) +g14133 = NAND(g11692, g11747) +g14136 = NAND(g11571, g8906) +g14139 = NAND(g11626, g11584) +g14142 = NAND(g11715, g8958) +g14146 = NAND(g11020, g691) +g14151 = NAND(g11692, g11483) +g14154 = NAND(g11669, g8958) +g14157 = NAND(g11715, g11763) +g14160 = NAND(g11626, g8958) +g14170 = NAND(g11715, g11537) +g14177 = NAND(g11741, g11721, g753) +g14223 = NAND(g9092, g11858) +g14234 = NAND(g9177, g11881) +g14254 = NAND(g11968, g11933, g11951) +g14258 = NAND(g9203, g11903) +g14279 = NAND(g12111, g9246) +g14317 = NAND(g5033, g11862) +g14333 = NAND(g12042, g12014, g11990, g11892) +g14343 = NAND(g11961, g9670) +g14344 = NAND(g5377, g11885) +g14378 = NAND(g11979, g9731) +g14379 = NAND(g5723, g11907) +g14407 = NAND(g12008, g9807) +g14408 = NAND(g6069, g11924) +g14422 = NAND(g3187, g11194, g3298, g8481) +g14433 = NAND(g12035, g9890) +g14434 = NAND(g6415, g11945) +g14452 = NAND(g3538, g11207, g3649, g8542) +g14489 = NAND(g12126, g5084) +g14505 = NAND(g12073, g9961) +g14517 = NAND(g3231, g11217, g3321, g8481) +g14519 = NAND(g3889, g11225, g4000, g8595) +g14520 = NAND(g9369, g12163) +g14521 = NAND(g12170, g5428) +g14542 = NAND(g3582, g11238, g3672, g8542) +g14546 = NAND(g12125, g9613) +g14547 = NAND(g9439, g12201) +g14548 = NAND(g12208, g5774) +g14569 = NAND(g3195, g11194, g3329, g8481) +g14570 = NAND(g3933, g11255, g4023, g8595) +g14572 = NAND(g12169, g9678) +g14573 = NAND(g9506, g12249) +g14574 = NAND(g12256, g6120) +g14590 = NAND(g3546, g11207, g3680, g8542) +g14596 = NAND(g12196, g9775, g12124, g9663) +g14598 = NAND(g5248, g12002, g5331, g12497) +g14599 = NAND(g12207, g9739) +g14600 = NAND(g9564, g12311) +g14601 = NAND(g12318, g6466) +g14625 = NAND(g3897, g11225, g4031, g8595) +g14626 = NAND(g12232, g9852, g12159, g9715) +g14627 = NAND(g12553, g12772) +g14636 = NAND(g5595, g12029, g5677, g12563) +g14637 = NAND(g12255, g9815) +g14638 = NAND(g9626, g12361) +g14655 = NAND(g4743, g11755) +g14656 = NAND(g12553, g12405) +g14659 = NAND(g12646, g12443) +g14663 = NAND(g5236, g12002, g5290, g12239) +g14664 = NAND(g5220, g12059, g5339, g12497) +g14665 = NAND(g12604, g12798) +g14674 = NAND(g5941, g12067, g6023, g12614) +g14675 = NAND(g12317, g9898) +I16778 = NAND(g11292, g12332) +I16779 = NAND(g11292, I16778) +I16780 = NAND(g12332, I16778) +g14677 = NAND(I16779, I16780) +g14682 = NAND(g4933, g11780) +g14683 = NAND(g12553, g12443) +g14686 = NAND(g5268, g12059, g5276, g12239) +g14688 = NAND(g12604, g12453) +g14691 = NAND(g12695, g12505) +g14695 = NAND(g5583, g12029, g5637, g12301) +g14696 = NAND(g5567, g12093, g5685, g12563) +g14697 = NAND(g12662, g12824) +g14706 = NAND(g6287, g12101, g6369, g12672) +g14720 = NAND(g12593, g10266) +g14723 = NAND(g7704, g12772) +g14727 = NAND(g12604, g12505) +g14730 = NAND(g5615, g12093, g5623, g12301) +g14732 = NAND(g12662, g12515) +g14735 = NAND(g12739, g12571) +g14739 = NAND(g5929, g12067, g5983, g12351) +g14740 = NAND(g5913, g12129, g6031, g12614) +g14741 = NAND(g12711, g10421) +g14750 = NAND(g6633, g12137, g6715, g12721) +g14755 = NAND(g12593, g12772) +g14758 = NAND(g7704, g12405) +g14761 = NAND(g12651, g10281) +g14764 = NAND(g7738, g12798) +g14768 = NAND(g12662, g12571) +g14771 = NAND(g5961, g12129, g5969, g12351) +g14773 = NAND(g12711, g12581) +g14776 = NAND(g12780, g12622) +g14780 = NAND(g6275, g12101, g6329, g12423) +g14781 = NAND(g6259, g12173, g6377, g12672) +g14782 = NAND(g12755, g10491) +g14794 = NAND(g12492, g12772) +g14797 = NAND(g12593, g12405) +g14800 = NAND(g7704, g12443) +g14803 = NAND(g5208, g12059, g5308, g12497) +g14804 = NAND(g12651, g12798) +g14807 = NAND(g7738, g12453) +g14810 = NAND(g12700, g10312) +g14813 = NAND(g7766, g12824) +g14817 = NAND(g12711, g12622) +g14820 = NAND(g6307, g12173, g6315, g12423) +g14822 = NAND(g12755, g12632) +g14825 = NAND(g12806, g12680) +g14829 = NAND(g6621, g12137, g6675, g12471) +g14830 = NAND(g6605, g12211, g6723, g12721) +g14838 = NAND(g12492, g12405) +g14841 = NAND(g12593, g12443) +g14845 = NAND(g12558, g12798) +g14848 = NAND(g12651, g12453) +g14851 = NAND(g7738, g12505) +g14854 = NAND(g5555, g12093, g5654, g12563) +g14855 = NAND(g12700, g12824) +g14858 = NAND(g7766, g12515) +g14861 = NAND(g12744, g10341) +g14864 = NAND(g7791, g10421) +g14868 = NAND(g12755, g12680) +g14871 = NAND(g6653, g12211, g6661, g12471) +g14876 = NAND(g12492, g12443) +g14879 = NAND(g12646, g10266) +g14882 = NAND(g12558, g12453) +g14885 = NAND(g12651, g12505) +g14889 = NAND(g12609, g12824) +g14892 = NAND(g12700, g12515) +g14895 = NAND(g7766, g12571) +g14898 = NAND(g5901, g12129, g6000, g12614) +g14899 = NAND(g12744, g10421) +g14902 = NAND(g7791, g12581) +g14905 = NAND(g12785, g7142) +g14908 = NAND(g7812, g10491) +g14915 = NAND(g12553, g10266) +g14918 = NAND(g12646, g12772) +g14921 = NAND(g12492, g10266) +g14924 = NAND(g12558, g12505) +g14927 = NAND(g12695, g10281) +g14930 = NAND(g12609, g12515) +g14933 = NAND(g12700, g12571) +g14937 = NAND(g12667, g10421) +g14940 = NAND(g12744, g12581) +g14943 = NAND(g7791, g12622) +g14946 = NAND(g6247, g12173, g6346, g12672) +g14947 = NAND(g12785, g10491) +g14950 = NAND(g7812, g12632) +g14953 = NAND(g12646, g12405) +g14956 = NAND(g12604, g10281) +g14959 = NAND(g12695, g12798) +g14962 = NAND(g12558, g10281) +g14965 = NAND(g12609, g12571) +g14968 = NAND(g12739, g10312) +g14971 = NAND(g12667, g12581) +g14974 = NAND(g12744, g12622) +g14978 = NAND(g12716, g10491) +g14981 = NAND(g12785, g12632) +g14984 = NAND(g7812, g12680) +g14987 = NAND(g6593, g12211, g6692, g12721) +g14993 = NAND(g12695, g12453) +g14996 = NAND(g12662, g10312) +g14999 = NAND(g12739, g12824) +g15002 = NAND(g12609, g10312) +g15005 = NAND(g12667, g12622) +g15008 = NAND(g12780, g10341) +g15011 = NAND(g12716, g12632) +g15014 = NAND(g12785, g12680) +g15018 = NAND(g12739, g12515) +g15021 = NAND(g12711, g10341) +g15024 = NAND(g12780, g10421) +g15027 = NAND(g12667, g10341) +g15030 = NAND(g12716, g12680) +g15033 = NAND(g12806, g7142) +g15036 = NAND(g12780, g12581) +g15039 = NAND(g12755, g7142) +g15042 = NAND(g12806, g10491) +g15045 = NAND(g12716, g7142) +g15572 = NAND(g12969, g7219) +g15581 = NAND(g7232, g12999) +g15591 = NAND(g4332, g4322, g13202) +g15674 = NAND(g921, g13110) +g15695 = NAND(g1266, g13125) +g15702 = NAND(g13066, g7293) +g15708 = NAND(g7340, g13083) +g15709 = NAND(g5224, g14399, g5327, g9780) +g15710 = NAND(g319, g13385) +g15713 = NAND(g5571, g14425, g5673, g9864) +g15715 = NAND(g336, g305, g13385) +g15717 = NAND(g10754, g13092) +g15719 = NAND(g5256, g14490, g5335, g9780) +g15720 = NAND(g5917, g14497, g6019, g9935) +g15721 = NAND(g7564, g311, g13385) +g15723 = NAND(g10775, g13104) +g15725 = NAND(g5603, g14522, g5681, g9864) +g15726 = NAND(g6263, g14529, g6365, g10003) +g15728 = NAND(g5200, g14399, g5313, g9780) +g15729 = NAND(g5949, g14549, g6027, g9935) +g15730 = NAND(g6609, g14556, g6711, g10061) +g15734 = NAND(g5228, g12059, g5290, g14631) +g15735 = NAND(g5547, g14425, g5659, g9864) +g15736 = NAND(g6295, g14575, g6373, g10003) +g15737 = NAND(g13240, g13115, g7903, g13210) +g15741 = NAND(g5244, g14490, g5320, g14631) +g15742 = NAND(g5575, g12093, g5637, g14669) +g15743 = NAND(g5893, g14497, g6005, g9935) +g15744 = NAND(g6641, g14602, g6719, g10061) +g15748 = NAND(g13257, g13130, g7922, g13241) +g15751 = NAND(g5591, g14522, g5666, g14669) +g15752 = NAND(g5921, g12129, g5983, g14701) +g15753 = NAND(g6239, g14529, g6351, g10003) +g15780 = NAND(g5937, g14549, g6012, g14701) +g15781 = NAND(g6267, g12173, g6329, g14745) +g15782 = NAND(g6585, g14556, g6697, g10061) +g15787 = NAND(g6283, g14575, g6358, g14745) +g15788 = NAND(g6613, g12211, g6675, g14786) +g15798 = NAND(g6629, g14602, g6704, g14786) +g15829 = NAND(g4112, g13831) +g15832 = NAND(g7903, g7479, g13256) +g15833 = NAND(g14714, g12378, g12337) +g15843 = NAND(g7922, g7503, g13264) +g15844 = NAND(g14714, g9340, g12378) +g15853 = NAND(g14714, g9417, g12337) +g15864 = NAND(g14833, g12543, g12487) +g15867 = NAND(g14714, g9417, g9340) +g15877 = NAND(g14833, g9340, g12543) +I17379 = NAND(g13336, g1129) +I17380 = NAND(g13336, I17379) +I17381 = NAND(g1129, I17379) +g15904 = NAND(I17380, I17381) +g15907 = NAND(g14833, g9417, g12487) +I17404 = NAND(g13378, g1472) +I17405 = NAND(g13378, I17404) +I17406 = NAND(g1472, I17404) +g15959 = NAND(I17405, I17406) +g15962 = NAND(g14833, g9417, g9340) +I17446 = NAND(g13336, g956) +I17447 = NAND(g13336, I17446) +I17448 = NAND(g956, I17446) +g16069 = NAND(I17447, I17448) +I17460 = NAND(g13378, g1300) +I17461 = NAND(g13378, I17460) +I17462 = NAND(g1300, I17460) +g16093 = NAND(I17461, I17462) +g16097 = NAND(g13319, g10998) +I17474 = NAND(g13336, g1105) +I17475 = NAND(g13336, I17474) +I17476 = NAND(g1105, I17474) +g16119 = NAND(I17475, I17476) +I17494 = NAND(g13378, g1448) +I17495 = NAND(g13378, I17494) +I17496 = NAND(g1448, I17494) +g16155 = NAND(I17495, I17496) +g16181 = NAND(g13475, g13495, g13057, g13459) +g16196 = NAND(g13496, g13513, g13079, g13476) +g16225 = NAND(g13544, g13528, g13043) +g16236 = NAND(g13573, g13554, g13058) +g16238 = NAND(g4698, g13883, g12054) +g16259 = NAND(g4743, g13908, g12054) +g16260 = NAND(g4888, g13910, g12088) +g16264 = NAND(g518, g9158, g13223) +g16275 = NAND(g9291, g13480) +g16278 = NAND(g8102, g8057, g13664) +g16281 = NAND(g4754, g13937, g12054) +g16282 = NAND(g4933, g13939, g12088) +g16291 = NAND(g13551, g13545) +g16296 = NAND(g9360, g13501) +g16299 = NAND(g8160, g8112, g13706) +g16304 = NAND(g4765, g13970, g12054) +g16306 = NAND(g4944, g13971, g12088) +g16312 = NAND(g13580, g13574) +g16316 = NAND(g9429, g13518) +g16319 = NAND(g8224, g8170, g13736) +g16321 = NAND(g4955, g13996, g12088) +g16507 = NAND(g13797, g13764) +g16524 = NAND(g13822, g13798) +g16586 = NAND(g13851, g13823) +g16604 = NAND(g3251, g11194, g3267, g13877) +g16625 = NAND(g3203, g13700, g3274, g11519) +g16628 = NAND(g3602, g11207, g3618, g13902) +g16657 = NAND(g3554, g13730, g3625, g11576) +g16660 = NAND(g3953, g11225, g3969, g13933) +g16663 = NAND(g13854, g13834, g14655, g12292) +I17883 = NAND(g13336, g1135) +I17884 = NAND(g13336, I17883) +I17885 = NAND(g1135, I17883) +g16681 = NAND(I17884, I17885) +g16687 = NAND(g3255, g13700, g3325, g11519) +g16694 = NAND(g3905, g13772, g3976, g11631) +g16696 = NAND(g13871, g13855, g14682, g12340) +I17923 = NAND(g13378, g1478) +I17924 = NAND(g13378, I17923) +I17925 = NAND(g1478, I17923) +g16713 = NAND(I17924, I17925) +g16719 = NAND(g3243, g13700, g3310, g11350) +g16723 = NAND(g3606, g13730, g3676, g11576) +g16728 = NAND(g13884, g13870, g14089, g11639) +g16741 = NAND(g3207, g13765, g3303, g11519) +g16745 = NAND(g3594, g13730, g3661, g11389) +g16749 = NAND(g3957, g13772, g4027, g11631) +g16757 = NAND(g13911, g13886, g14120, g11675) +g16770 = NAND(g3263, g13765, g3274, g8481) +g16772 = NAND(g3558, g13799, g3654, g11576) +g16776 = NAND(g3945, g13772, g4012, g11419) +g16813 = NAND(g3614, g13799, g3625, g8542) +g16815 = NAND(g3909, g13824, g4005, g11631) +g16854 = NAND(g3965, g13824, g3976, g8595) +g16875 = NAND(g3223, g13765, g3317, g11519) +g16893 = NAND(g10685, g13252, g703) +g16925 = NAND(g3574, g13799, g3668, g11576) +g16956 = NAND(g3925, g13824, g4019, g11631) +g17137 = NAND(g13727, g13511, g13527) +g17217 = NAND(g7239, g14194) +g17220 = NAND(g9369, g9298, g14376) +g17225 = NAND(g8612, g14367) +g17243 = NAND(g7247, g14212) +g17246 = NAND(g9439, g9379, g14405) +g17287 = NAND(g7262, g14228) +g17290 = NAND(g9506, g9449, g14431) +g17297 = NAND(g2729, g14291) +g17312 = NAND(g7297, g14248) +g17315 = NAND(g9564, g9516, g14503) +g17363 = NAND(g8635, g14367) +g17364 = NAND(g8639, g14367) +g17396 = NAND(g7345, g14272) +g17399 = NAND(g9626, g9574, g14535) +g17412 = NAND(g14520, g14489) +g17468 = NAND(g3215, g13700, g3317, g8481) +g17474 = NAND(g14547, g14521) +g17492 = NAND(g8655, g14367) +g17493 = NAND(g8659, g14367) +g17495 = NAND(g3566, g13730, g3668, g8542) +g17500 = NAND(g14573, g14548) +g17513 = NAND(g3247, g13765, g3325, g8481) +g17514 = NAND(g3917, g13772, g4019, g8595) +g17520 = NAND(g5260, g12002, g5276, g14631) +g17525 = NAND(g14600, g14574) +I18485 = NAND(g1677, g14611) +I18486 = NAND(g1677, I18485) +I18487 = NAND(g14611, I18485) +g17568 = NAND(I18486, I18487) +g17571 = NAND(g8579, g14367) +g17572 = NAND(g3598, g13799, g3676, g8542) +g17578 = NAND(g5212, g14399, g5283, g12497) +g17581 = NAND(g5607, g12029, g5623, g14669) +g17586 = NAND(g14638, g14601) +I18529 = NAND(g1811, g14640) +I18530 = NAND(g1811, I18529) +I18531 = NAND(g14640, I18529) +g17592 = NAND(I18530, I18531) +I18536 = NAND(g2236, g14642) +I18537 = NAND(g2236, I18536) +I18538 = NAND(g14642, I18536) +g17593 = NAND(I18537, I18538) +g17595 = NAND(g8616, g14367) +g17596 = NAND(g8686, g14367) +g17597 = NAND(g3191, g13700, g3303, g8481) +g17598 = NAND(g3949, g13824, g4027, g8595) +g17605 = NAND(g5559, g14425, g5630, g12563) +g17608 = NAND(g5953, g12067, g5969, g14701) +I18579 = NAND(g1945, g14678) +I18580 = NAND(g1945, I18579) +I18581 = NAND(g14678, I18579) +g17618 = NAND(I18580, I18581) +I18587 = NAND(g2370, g14679) +I18588 = NAND(g2370, I18587) +I18589 = NAND(g14679, I18587) +g17624 = NAND(I18588, I18589) +g17634 = NAND(g3219, g11217, g3281, g13877) +g17635 = NAND(g3542, g13730, g3654, g8542) +g17640 = NAND(g5264, g14399, g5335, g12497) +g17647 = NAND(g5905, g14497, g5976, g12614) +g17650 = NAND(g6299, g12101, g6315, g14745) +I18625 = NAND(g2079, g14712) +I18626 = NAND(g2079, I18625) +I18627 = NAND(g14712, I18625) +g17656 = NAND(I18626, I18627) +I18633 = NAND(g2504, g14713) +I18634 = NAND(g2504, I18633) +I18635 = NAND(g14713, I18633) +g17662 = NAND(I18634, I18635) +g17668 = NAND(g3235, g13765, g3310, g13877) +g17669 = NAND(g3570, g11238, g3632, g13902) +g17670 = NAND(g3893, g13772, g4005, g8595) +g17675 = NAND(g5252, g14399, g5320, g12239) +g17679 = NAND(g5611, g14425, g5681, g12563) +g17686 = NAND(g6251, g14529, g6322, g12672) +g17689 = NAND(g6645, g12137, g6661, g14786) +I18680 = NAND(g2638, g14752) +I18681 = NAND(g2638, I18680) +I18682 = NAND(g14752, I18680) +g17699 = NAND(I18681, I18682) +g17705 = NAND(g3586, g13799, g3661, g13902) +g17706 = NAND(g3921, g11255, g3983, g13933) +g17708 = NAND(g5216, g14490, g5313, g12497) +g17712 = NAND(g5599, g14425, g5666, g12301) +g17716 = NAND(g5957, g14497, g6027, g12614) +g17723 = NAND(g6597, g14556, g6668, g12721) +g17732 = NAND(g3937, g13824, g4012, g13933) +g17734 = NAND(g5272, g14490, g5283, g9780) +g17736 = NAND(g5563, g14522, g5659, g12563) +g17740 = NAND(g5945, g14497, g6012, g12351) +g17744 = NAND(g6303, g14529, g6373, g12672) +g17748 = NAND(g562, g14708, g12323) +g17755 = NAND(g5619, g14522, g5630, g9864) +g17757 = NAND(g5909, g14549, g6005, g12614) +g17761 = NAND(g6291, g14529, g6358, g12423) +g17765 = NAND(g6649, g14556, g6719, g12721) +g17773 = NAND(g5965, g14549, g5976, g9935) +g17775 = NAND(g6255, g14575, g6351, g12672) +g17779 = NAND(g6637, g14556, g6704, g12471) +g17788 = NAND(g5232, g14490, g5327, g12497) +g17790 = NAND(g6311, g14575, g6322, g10003) +g17792 = NAND(g6601, g14602, g6697, g12721) +g17814 = NAND(g5579, g14522, g5673, g12563) +g17816 = NAND(g6657, g14602, g6668, g10061) +g17820 = NAND(g5925, g14549, g6019, g12614) +g17846 = NAND(g6271, g14575, g6365, g12672) +g17872 = NAND(g6617, g14602, g6711, g12721) +g19265 = NAND(g15721, g15715, g13091, g15710) +g19335 = NAND(g15717, g1056) +g19358 = NAND(g15723, g1399) +g19442 = NAND(g11431, g17794) +g19450 = NAND(g11471, g17794) +g19455 = NAND(g15969, g10841, g7781) +g19466 = NAND(g11562, g17794) +g19474 = NAND(g11609, g17794) +g19483 = NAND(g15969, g10841, g10922) +g19495 = NAND(g15969, g10841, g7781) +g19506 = NAND(g4087, g15825) +g19510 = NAND(g15969, g10841, g10899) +g19513 = NAND(g15969, g10841, g10922) +g19530 = NAND(g15829, g10841) +g19546 = NAND(g15969, g10841, g10884) +g19549 = NAND(g15969, g10841, g10899) +g19589 = NAND(g15969, g10841, g10884) +g19597 = NAND(g1199, g15995) +g19611 = NAND(g1070, g1199, g15995) +g19614 = NAND(g1542, g16047) +g19632 = NAND(g1413, g1542, g16047) +I20165 = NAND(g16246, g990) +I20166 = NAND(g16246, I20165) +I20167 = NAND(g990, I20165) +g19764 = NAND(I20166, I20167) +I20187 = NAND(g16272, g1333) +I20188 = NAND(g16272, I20187) +I20189 = NAND(g1333, I20187) +g19782 = NAND(I20188, I20189) +I20203 = NAND(g16246, g11147) +I20204 = NAND(g16246, I20203) +I20205 = NAND(g11147, I20203) +g19792 = NAND(I20204, I20205) +g19795 = NAND(g13600, g16275) +I20221 = NAND(g16272, g11170) +I20222 = NAND(g16272, I20221) +I20223 = NAND(g11170, I20221) +g19854 = NAND(I20222, I20223) +g19856 = NAND(g13626, g16278, g8105) +g19857 = NAND(g13628, g16296) +g19874 = NAND(g13665, g16299, g8163) +g19875 = NAND(g13667, g16316) +g19886 = NAND(g11403, g17794) +g19903 = NAND(g13707, g16319, g8227) +g19913 = NAND(g11430, g17794) +g19916 = NAND(g3029, g16313) +g19962 = NAND(g11470, g17794) +g19965 = NAND(g3380, g16424) +g20007 = NAND(g11512, g17794) +g20011 = NAND(g3731, g16476) +g20039 = NAND(g11250, g17794) +g20055 = NAND(g11269, g17794) +g20068 = NAND(g11293, g17794) +g20076 = NAND(g13795, g16521) +g20081 = NAND(g11325, g17794) +g20092 = NAND(g11373, g17794) +g20107 = NAND(g11404, g17794) +g20111 = NAND(g17513, g14517, g17468, g14422) +g20133 = NAND(g17668, g17634, g17597, g14569) +g20134 = NAND(g17572, g14542, g17495, g14452) +g20150 = NAND(g17705, g17669, g17635, g14590) +g20151 = NAND(g17598, g14570, g17514, g14519) +g20161 = NAND(g17732, g17706, g17670, g14625) +g20163 = NAND(g16663, g13938) +g20170 = NAND(g16741, g13897, g16687, g13866) +g20172 = NAND(g16876, g8131) +g20173 = NAND(g16696, g13972) +g20181 = NAND(g13252, g16846) +g20184 = NAND(g16770, g13918, g16719, g13896) +g20185 = NAND(g16772, g13928, g16723, g13882) +g20186 = NAND(g16926, g8177) +g20198 = NAND(g16813, g13958, g16745, g13927) +g20199 = NAND(g16815, g13968, g16749, g13907) +I20460 = NAND(g17515, g14187) +I20461 = NAND(g17515, I20460) +I20462 = NAND(g14187, I20460) +g20200 = NAND(I20461, I20462) +I20467 = NAND(g16663, g16728) +I20468 = NAND(g16663, I20467) +I20469 = NAND(g16728, I20467) +g20201 = NAND(I20468, I20469) +g20214 = NAND(g16854, g13993, g16776, g13967) +I20486 = NAND(g16696, g16757) +I20487 = NAND(g16696, I20486) +I20488 = NAND(g16757, I20486) +g20216 = NAND(I20487, I20488) +g20236 = NAND(g16875, g14014, g16625, g16604) +g20248 = NAND(g17056, g14146, g14123) +g20271 = NAND(g16925, g14054, g16657, g16628) +g20371 = NAND(g16956, g14088, g16694, g16660) +g20619 = NAND(g14317, g17217) +g20644 = NAND(g14342, g17220, g9372) +g20645 = NAND(g14344, g17243) +g20675 = NAND(g14377, g17246, g9442) +g20676 = NAND(g14379, g17287) +g20733 = NAND(g14406, g17290, g9509) +g20734 = NAND(g14408, g17312) +g20783 = NAND(g14616, g17225) +g20784 = NAND(g14616, g17595) +g20838 = NAND(g5041, g17284) +g20870 = NAND(g14432, g17315, g9567) +g20871 = NAND(g14434, g17396) +g20979 = NAND(g5385, g17309) +g21011 = NAND(g14504, g17399, g9629) +g21124 = NAND(g5731, g17393) +g21186 = NAND(g14616, g17363) +g21187 = NAND(g14616, g17364) +g21190 = NAND(g6077, g17420) +g21253 = NAND(g6423, g17482) +g21272 = NAND(g11268, g17157) +g21283 = NAND(g11291, g17157) +g21287 = NAND(g14616, g17571) +g21288 = NAND(g14616, g17492) +g21289 = NAND(g14616, g17493) +g21294 = NAND(g11324, g17157) +g21301 = NAND(g11371, g17157) +g21307 = NAND(g15719, g13067, g15709, g13040) +g21330 = NAND(g11401, g17157) +g21331 = NAND(g11402, g17157) +g21334 = NAND(g14616, g17596) +g21338 = NAND(g15741, g15734, g15728, g13097) +g21339 = NAND(g15725, g13084, g15713, g13050) +g21344 = NAND(g11428, g17157) +g21345 = NAND(g11429, g17157) +g21350 = NAND(g15751, g15742, g15735, g13108) +g21351 = NAND(g15729, g13098, g15720, g13069) +g21353 = NAND(g11467, g17157) +g21354 = NAND(g11468, g17157) +g21356 = NAND(g15780, g15752, g15743, g13118) +g21357 = NAND(g15736, g13109, g15726, g13086) +g21359 = NAND(g11509, g17157) +g21360 = NAND(g11510, g17157) +g21363 = NAND(g17708, g14664, g17640, g14598) +g21364 = NAND(g15787, g15781, g15753, g13131) +g21365 = NAND(g15744, g13119, g15730, g13100) +g21377 = NAND(g11560, g17157) +g21384 = NAND(g17734, g14686, g17675, g14663) +g21385 = NAND(g17736, g14696, g17679, g14636) +g21386 = NAND(g15798, g15788, g15782, g13139) +g21388 = NAND(g11608, g17157) +g21401 = NAND(g17755, g14730, g17712, g14695) +g21402 = NAND(g17757, g14740, g17716, g14674) +g21403 = NAND(g11652, g17157) +g21415 = NAND(g17773, g14771, g17740, g14739) +g21416 = NAND(g17775, g14781, g17744, g14706) +g21417 = NAND(g11677, g17157) +g21429 = NAND(g17788, g14803, g17578, g17520) +g21432 = NAND(g17790, g14820, g17761, g14780) +g21433 = NAND(g17792, g14830, g17765, g14750) +g21459 = NAND(g17814, g14854, g17605, g17581) +g21462 = NAND(g17816, g14871, g17779, g14829) +g21509 = NAND(g17820, g14898, g17647, g17608) +g21555 = NAND(g17846, g14946, g17686, g17650) +g21603 = NAND(g17872, g14987, g17723, g17689) +g22306 = NAND(g4584, g4616, g13202, g19071) +g22312 = NAND(g907, g19063) +g22325 = NAND(g1252, g19140) +g22638 = NAND(g18957, g2886) +g22642 = NAND(g7870, g19560) +g22643 = NAND(g20136, g18954) +g22650 = NAND(g7888, g19581) +g22651 = NAND(g20114, g2873) +g22661 = NAND(g20136, g94) +I21976 = NAND(g7680, g19620) +I21977 = NAND(g7680, I21976) +I21978 = NAND(g19620, I21976) +g22663 = NAND(I21977, I21978) +g22666 = NAND(g18957, g2878) +g22668 = NAND(g20219, g2912) +I21992 = NAND(g7670, g19638) +I21993 = NAND(g7670, I21992) +I21994 = NAND(g19638, I21992) +g22681 = NAND(I21993, I21994) +g22687 = NAND(g19560, g7870) +g22688 = NAND(g20219, g2936) +g22709 = NAND(g1193, g19611) +g22711 = NAND(g19581, g7888) +g22712 = NAND(g18957, g2864) +g22713 = NAND(g20114, g2890) +g22715 = NAND(g20114, g2999) +g22753 = NAND(g1536, g19632) +g22754 = NAND(g20114, g19376) +g22755 = NAND(g20136, g18984) +g22757 = NAND(g20114, g7891) +g22833 = NAND(g1193, g19560, g10666) +g22836 = NAND(g18918, g2852) +g22837 = NAND(g20219, g2907) +g22838 = NAND(g20219, g2960) +g22839 = NAND(g20114, g2988) +g22850 = NAND(g1536, g19581, g10699) +g22852 = NAND(g18957, g2856) +g22853 = NAND(g20219, g2922) +g22864 = NAND(g7780, g21156) +g22874 = NAND(g18918, g2844) +g22875 = NAND(g20516, g2980) +g22885 = NAND(g9104, g20154) +g22902 = NAND(g18957, g2848) +g22908 = NAND(g9104, g20175) +g22921 = NAND(g20219, g2950) +g22940 = NAND(g18918, g2860) +g22941 = NAND(g20219, g2970) +g22984 = NAND(g20114, g2868) +g23010 = NAND(g20516, g2984) +g23047 = NAND(g482, g20000) +g23067 = NAND(g20887, g10721) +g23105 = NAND(g8097, g19887) +g23112 = NAND(g21024, g10733) +g23132 = NAND(g8155, g19932) +g23139 = NAND(g21163, g10756) +g23167 = NAND(g8219, g19981) +g23195 = NAND(g20136, g37) +g23210 = NAND(g18957, g2882) +g23266 = NAND(g18918, g2894) +g23281 = NAND(g18957, g2898) +g23286 = NAND(g6875, g20887) +g23309 = NAND(g6905, g21024) +g23324 = NAND(g703, g20181) +g23342 = NAND(g6928, g21163) +g23357 = NAND(g20201, g11231) +g23379 = NAND(g20216, g11248) +g23428 = NAND(g13945, g20522) +I22683 = NAND(g11893, g21434) +I22684 = NAND(g11893, I22683) +I22685 = NAND(g21434, I22683) +g23552 = NAND(I22684, I22685) +I22710 = NAND(g11915, g21434) +I22711 = NAND(g11915, I22710) +I22712 = NAND(g21434, I22710) +g23575 = NAND(I22711, I22712) +I22717 = NAND(g11916, g21434) +I22718 = NAND(g11916, I22717) +I22719 = NAND(g21434, I22717) +g23576 = NAND(I22718, I22719) +g23590 = NAND(g20682, g11111) +I22753 = NAND(g11937, g21434) +I22754 = NAND(g11937, I22753) +I22755 = NAND(g21434, I22753) +g23616 = NAND(I22754, I22755) +I22760 = NAND(g11939, g21434) +I22761 = NAND(g11939, I22760) +I22762 = NAND(g21434, I22760) +g23617 = NAND(I22761, I22762) +g23623 = NAND(g9364, g20717) +g23630 = NAND(g20739, g11123) +I22792 = NAND(g11956, g21434) +I22793 = NAND(g11956, I22792) +I22794 = NAND(g21434, I22792) +g23655 = NAND(I22793, I22794) +I22799 = NAND(g11960, g21434) +I22800 = NAND(g11960, I22799) +I22801 = NAND(g21434, I22799) +g23656 = NAND(I22800, I22801) +g23659 = NAND(g9434, g20854) +g23666 = NAND(g20875, g11139) +I22822 = NAND(g11978, g21434) +I22823 = NAND(g11978, I22822) +I22824 = NAND(g21434, I22822) +g23685 = NAND(I22823, I22824) +g23692 = NAND(g9501, g20995) +g23699 = NAND(g21012, g11160) +I22844 = NAND(g12113, g21228) +I22845 = NAND(g12113, I22844) +I22846 = NAND(g21228, I22844) +g23719 = NAND(I22845, I22846) +g23726 = NAND(g9559, g21140) +g23733 = NAND(g20751, g11178) +I22864 = NAND(g12146, g21228) +I22865 = NAND(g12146, I22864) +I22866 = NAND(g21228, I22864) +g23747 = NAND(I22865, I22866) +I22871 = NAND(g12150, g21228) +I22872 = NAND(g12150, I22871) +I22873 = NAND(g21228, I22871) +g23748 = NAND(I22872, I22873) +g23756 = NAND(g9621, g21206) +I22892 = NAND(g12189, g21228) +I22893 = NAND(g12189, I22892) +I22894 = NAND(g21228, I22892) +g23761 = NAND(I22893, I22894) +I22899 = NAND(g12193, g21228) +I22900 = NAND(g12193, I22899) +I22901 = NAND(g21228, I22899) +g23762 = NAND(I22900, I22901) +I22921 = NAND(g14677, g21284) +I22922 = NAND(g14677, I22921) +I22923 = NAND(g21284, I22921) +g23778 = NAND(I22922, I22923) +I22929 = NAND(g12223, g21228) +I22930 = NAND(g12223, I22929) +I22931 = NAND(g21228, I22929) +g23780 = NAND(I22930, I22931) +I22936 = NAND(g12226, g21228) +I22937 = NAND(g12226, I22936) +I22938 = NAND(g21228, I22936) +g23781 = NAND(I22937, I22938) +g23782 = NAND(g2741, g21062) +I22944 = NAND(g9492, g19620) +I22945 = NAND(g9492, I22944) +I22946 = NAND(g19620, I22944) +g23786 = NAND(I22945, I22946) +I22965 = NAND(g12288, g21228) +I22966 = NAND(g12288, I22965) +I22967 = NAND(g21228, I22965) +g23809 = NAND(I22966, I22967) +I22972 = NAND(g9657, g19638) +I22973 = NAND(g9657, I22972) +I22974 = NAND(g19638, I22972) +g23810 = NAND(I22973, I22974) +g23850 = NAND(g12185, g19462) +g23890 = NAND(g7004, g20682) +g23909 = NAND(g7028, g20739) +g23932 = NAND(g7051, g20875) +g23949 = NAND(g7074, g21012) +g23972 = NAND(g7097, g20751) +I23118 = NAND(g20076, g417) +I23119 = NAND(g20076, I23118) +I23120 = NAND(g417, I23118) +g23975 = NAND(I23119, I23120) +g23978 = NAND(g572, g21389, g12323) +g24362 = NAND(g21370, g22136) +I23585 = NAND(g22409, g4332) +I23586 = NAND(g22409, I23585) +I23587 = NAND(g4332, I23585) +g24369 = NAND(I23586, I23587) +I23600 = NAND(g22360, g4322) +I23601 = NAND(g22360, I23600) +I23602 = NAND(g4322, I23600) +g24380 = NAND(I23601, I23602) +g24528 = NAND(g4098, g22654) +g24544 = NAND(g22666, g22661, g22651) +g24547 = NAND(g22638, g22643, g22754) +g24566 = NAND(g22755, g22713) +g24567 = NAND(g22957, g2917) +g24570 = NAND(g22957, g2941) +g24574 = NAND(g22709, g22687) +g24576 = NAND(g22957, g2902) +g24583 = NAND(g22753, g22711) +g24584 = NAND(g22852, g22836, g22715) +g24591 = NAND(g22833, g22642) +g24601 = NAND(g22957, g2965) +g24609 = NAND(g22850, g22650) +g24620 = NAND(g22902, g22874) +g24621 = NAND(g22957, g2927) +g24652 = NAND(g22712, g22940, g22757) +g24661 = NAND(g23210, g23195, g22984) +g24662 = NAND(g22957, g2955) +g24677 = NAND(g22957, g2975) +g24678 = NAND(g22994, g23010) +I23917 = NAND(g23975, g9333) +I23918 = NAND(g23975, I23917) +I23919 = NAND(g9333, I23917) +g24760 = NAND(I23918, I23919) +g24776 = NAND(g3040, g23052) +g24787 = NAND(g3391, g23079) +I23949 = NAND(g23162, g13603) +I23950 = NAND(g23162, I23949) +I23951 = NAND(g13603, I23949) +g24792 = NAND(I23950, I23951) +g24793 = NAND(g3742, g23124) +I23961 = NAND(g23184, g13631) +I23962 = NAND(g23184, I23961) +I23963 = NAND(g13631, I23961) +g24798 = NAND(I23962, I23963) +I23969 = NAND(g22202, g490) +I23970 = NAND(g22202, I23969) +I23971 = NAND(g490, I23969) +g24802 = NAND(I23970, I23971) +g24804 = NAND(g19916, g23105) +I23978 = NAND(g23198, g13670) +I23979 = NAND(g23198, I23978) +I23980 = NAND(g13670, I23978) +g24807 = NAND(I23979, I23980) +I23985 = NAND(g22182, g482) +I23986 = NAND(g22182, I23985) +I23987 = NAND(g482, I23985) +g24808 = NAND(I23986, I23987) +g24809 = NAND(g19965, g23132) +g24814 = NAND(g20011, g23167) +g24880 = NAND(g23281, g23266, g22839) +g24890 = NAND(g13852, g22929) +g24905 = NAND(g534, g23088) +g24906 = NAND(g8743, g23088) +g24916 = NAND(g19450, g23154) +g24917 = NAND(g19913, g23172) +g24918 = NAND(g136, g23088) +g24924 = NAND(g20007, g23172) +g24925 = NAND(g20092, g23154) +g24926 = NAND(g20172, g20163, g23357, g13995) +g24932 = NAND(g19886, g23172) +g24933 = NAND(g19466, g23154) +g24934 = NAND(g21283, g23462) +g24936 = NAND(g20186, g20173, g23379, g14029) +g24942 = NAND(g20039, g23172) +g24943 = NAND(g20068, g23172) +g24944 = NAND(g21354, g23363) +g24950 = NAND(g19442, g23154) +g24951 = NAND(g199, g23088) +g24957 = NAND(g21359, g23462) +g24958 = NAND(g21330, g23462) +g24972 = NAND(g19962, g23172) +g24973 = NAND(g21272, g23462) +g24974 = NAND(g21301, g23363) +g24975 = NAND(g21388, g23363) +g24988 = NAND(g546, g23088) +g24989 = NAND(g21345, g23363) +g25002 = NAND(g19474, g23154) +g25003 = NAND(g21353, g23462) +g25018 = NAND(g20107, g23154) +g25019 = NAND(g20055, g23172) +g25020 = NAND(g21377, g23462) +g25021 = NAND(g21417, g23363) +g25038 = NAND(g21331, g23363) +g25048 = NAND(g542, g23088) +g25049 = NAND(g21344, g23462) +g25062 = NAND(g21403, g23363) +g25172 = NAND(g5052, g23560) +g25186 = NAND(g5396, g23602) +I24363 = NAND(g23687, g14320) +I24364 = NAND(g23687, I24363) +I24365 = NAND(g14320, I24363) +g25199 = NAND(I24364, I24365) +g25200 = NAND(g5742, g23642) +I24383 = NAND(g23721, g14347) +I24384 = NAND(g23721, I24383) +I24385 = NAND(g14347, I24383) +g25215 = NAND(I24384, I24385) +g25216 = NAND(g6088, g23678) +g25233 = NAND(g20838, g23623) +I24414 = NAND(g23751, g14382) +I24415 = NAND(g23751, I24414) +I24416 = NAND(g14382, I24414) +g25236 = NAND(I24415, I24416) +g25237 = NAND(g6434, g23711) +g25255 = NAND(g20979, g23659) +I24438 = NAND(g23771, g14411) +I24439 = NAND(g23771, I24438) +I24440 = NAND(g14411, I24438) +g25258 = NAND(I24439, I24440) +g25268 = NAND(g21124, g23692) +I24461 = NAND(g23796, g14437) +I24462 = NAND(g23796, I24461) +I24463 = NAND(g14437, I24461) +g25271 = NAND(I24462, I24463) +g25275 = NAND(g22342, g11991) +g25293 = NAND(g21190, g23726) +g25300 = NAND(g22369, g12018) +g25309 = NAND(g22384, g12021) +g25334 = NAND(g21253, g23756) +g25337 = NAND(g22342, g1648, g8187) +g25341 = NAND(g22417, g12047) +g25349 = NAND(g22432, g12051) +g25381 = NAND(g538, g23088) +g25382 = NAND(g12333, g22342) +g25385 = NAND(g22369, g1783, g8241) +g25389 = NAND(g22457, g12082) +g25396 = NAND(g22384, g2208, g8259) +g25400 = NAND(g22472, g12086) +g25425 = NAND(g20081, g23172) +g25426 = NAND(g12371, g22369) +g25429 = NAND(g22417, g1917, g8302) +g25432 = NAND(g12374, g22384) +g25435 = NAND(g22432, g2342, g8316) +g25439 = NAND(g22498, g12122) +g25467 = NAND(g12432, g22417) +g25470 = NAND(g22457, g2051, g8365) +g25473 = NAND(g12437, g22432) +g25476 = NAND(g22472, g2476, g8373) +g25492 = NAND(g12479, g22457) +g25495 = NAND(g12483, g22472) +g25498 = NAND(g22498, g2610, g8418) +g25514 = NAND(g12540, g22498) +g25527 = NAND(g21294, g23462) +g25531 = NAND(g22763, g2868) +g25532 = NAND(g21360, g23363) +g25537 = NAND(g22763, g2873) +g25779 = NAND(g19694, g24362) +g25888 = NAND(g914, g24439) +g25895 = NAND(g1259, g24453) +g25953 = NAND(g22756, g24570, g22688) +g25974 = NAND(g24576, g22837) +g25984 = NAND(g24567, g22668) +g25985 = NAND(g24631, g23956) +g25995 = NAND(g24621, g22853) +g25996 = NAND(g24601, g22838) +g26025 = NAND(g22405, g24631) +g26052 = NAND(g22714, g24662, g22921) +g26053 = NAND(g22875, g24677, g22941) +g26208 = NAND(g7975, g24751) +g26235 = NAND(g8016, g24766) +I25219 = NAND(g482, g24718) +I25220 = NAND(g482, I25219) +I25221 = NAND(g24718, I25219) +g26248 = NAND(I25220, I25221) +g26255 = NAND(g8075, g24779) +I25242 = NAND(g490, g24744) +I25243 = NAND(g490, I25242) +I25244 = NAND(g24744, I25242) +g26269 = NAND(I25243, I25244) +g26352 = NAND(g744, g24875, g11679) +g26382 = NAND(g577, g24953, g12323) +g26666 = NAND(g9229, g25144) +g26685 = NAND(g9264, g25160) +g26714 = NAND(g9316, g25175) +g26745 = NAND(g6856, g25317) +g26752 = NAND(g9397, g25189) +g26782 = NAND(g9467, g25203) +I25845 = NAND(g26212, g24799) +I25846 = NAND(g26212, I25845) +I25847 = NAND(g24799, I25845) +g27141 = NAND(I25846, I25847) +I25907 = NAND(g26256, g24782) +I25908 = NAND(g26256, I25907) +I25909 = NAND(g24782, I25907) +g27223 = NAND(I25908, I25909) +g27273 = NAND(g10504, g26131, g26105) +g27282 = NAND(g11192, g26269, g26248, g479) +g27295 = NAND(g24776, g26208) +g27306 = NAND(g24787, g26235) +g27317 = NAND(g24793, g26255) +I26049 = NAND(g25997, g13500) +I26050 = NAND(g25997, I26049) +I26051 = NAND(g13500, I26049) +g27365 = NAND(I26050, I26051) +g27377 = NAND(g10685, g25930) +I26070 = NAND(g26026, g13517) +I26071 = NAND(g26026, I26070) +I26072 = NAND(g13517, I26070) +g27380 = NAND(I26071, I26072) +I26093 = NAND(g26055, g13539) +I26094 = NAND(g26055, I26093) +I26095 = NAND(g13539, I26093) +g27401 = NAND(I26094, I26095) +g27463 = NAND(g287, g26330, g23204) +g27468 = NAND(g24951, g24932, g24925, g26852) +g27550 = NAND(g24943, g25772) +g27577 = NAND(g25019, g25002, g24988, g25765) +g27582 = NAND(g10857, g26131, g26105) +g27586 = NAND(g24924, g24916, g24905, g26863) +g27587 = NAND(g24917, g25018, g24918, g26857) +g27593 = NAND(g24972, g24950, g24906, g26861) +g27613 = NAND(g24942, g24933, g25048, g26871) +g27654 = NAND(g164, g26598, g23042) +g27670 = NAND(g25172, g26666) +g27679 = NAND(g25186, g26685) +g27687 = NAND(g25200, g26714) +g27693 = NAND(g25216, g26752) +g27705 = NAND(g25237, g26782) +g27738 = NAND(g21228, g25243, g26424, g26148) +I26366 = NAND(g26400, g14211) +I26367 = NAND(g26400, I26366) +I26368 = NAND(g14211, I26366) +g27767 = NAND(I26367, I26368) +g27775 = NAND(g21228, g25262, g26424, g26166) +g27796 = NAND(g21228, g25263, g26424, g26171) +I26393 = NAND(g26488, g14227) +I26394 = NAND(g26488, I26393) +I26395 = NAND(g14227, I26393) +g27824 = NAND(I26394, I26395) +g27833 = NAND(g21228, g25282, g26424, g26190) +g27854 = NAND(g21228, g25283, g26424, g26195) +I26417 = NAND(g26519, g14247) +I26418 = NAND(g26519, I26417) +I26419 = NAND(g14247, I26417) +g27876 = NAND(I26418, I26419) +g27882 = NAND(g21228, g25307, g26424, g26213) +g27903 = NAND(g21228, g25316, g26424, g26218) +I26438 = NAND(g26549, g14271) +I26439 = NAND(g26549, I26438) +I26440 = NAND(g14271, I26438) +g27925 = NAND(I26439, I26440) +g27931 = NAND(g25425, g25381, g25780) +g27933 = NAND(g21228, g25356, g26424, g26236) +I26459 = NAND(g26576, g14306) +I26460 = NAND(g26576, I26459) +I26461 = NAND(g14306, I26459) +g27955 = NAND(I26460, I26461) +g28109 = NAND(g27051, g25783) +g28131 = NAND(g27051, g25838) +g28167 = NAND(g925, g27046) +g28174 = NAND(g1270, g27059) +g28203 = NAND(g12546, g27985, g27977) +g28206 = NAND(g12546, g26105, g27985) +g28207 = NAND(g12546, g26131, g27977) +g28259 = NAND(g10504, g26987, g26973) +g28270 = NAND(g10504, g26105, g26987) +g28271 = NAND(g10533, g27004, g26990) +g28287 = NAND(g10504, g26131, g26973) +g28288 = NAND(g10533, g26105, g27004) +g28298 = NAND(g10533, g26131, g26990) +g28336 = NAND(g27064, g24756, g27163, g19644) +g28349 = NAND(g27074, g24770, g27187, g19644) +g28363 = NAND(g27064, g13593) +g28376 = NAND(g27064, g13620) +g28381 = NAND(g27074, g13621) +g28391 = NAND(g27064, g13637) +g28395 = NAND(g27074, g13655) +g28406 = NAND(g27064, g13675) +g28410 = NAND(g27074, g13679) +g28421 = NAND(g27074, g13715) +g28448 = NAND(g23975, g27377) +g28500 = NAND(g590, g27629, g12323) +g28504 = NAND(g758, g27528, g11679) +g28512 = NAND(g10857, g27155, g27142) +g28516 = NAND(g10857, g26105, g27155) +g28522 = NAND(g10857, g26131, g27142) +g28736 = NAND(g27742, g7308, g7252) +g28755 = NAND(g27742, g7268, g1592) +g28758 = NAND(g27779, g7356, g7275) +g28765 = NAND(g27800, g7374, g7280) +g28780 = NAND(g27742, g7308, g1636) +g28783 = NAND(g27779, g7315, g1728) +g28786 = NAND(g27837, g7405, g7322) +g28793 = NAND(g27800, g7328, g2153) +g28796 = NAND(g27858, g7418, g7335) +g28820 = NAND(g27742, g1668, g1592) +g28823 = NAND(g27738, g14565) +g28824 = NAND(g27779, g7356, g1772) +g28827 = NAND(g27837, g7362, g1862) +g28830 = NAND(g27886, g7451, g7369) +g28837 = NAND(g27800, g7374, g2197) +g28840 = NAND(g27858, g7380, g2287) +g28843 = NAND(g27907, g7456, g7387) +g28853 = NAND(g27742, g1636, g7252) +g28856 = NAND(g27738, g8093) +g28857 = NAND(g27779, g1802, g1728) +g28860 = NAND(g27775, g14586) +g28861 = NAND(g27837, g7405, g1906) +g28864 = NAND(g27886, g7411, g1996) +g28867 = NAND(g27800, g2227, g2153) +g28870 = NAND(g27796, g14588) +g28871 = NAND(g27858, g7418, g2331) +g28874 = NAND(g27907, g7424, g2421) +g28877 = NAND(g27937, g7490, g7431) +g28885 = NAND(g27742, g1668, g7268) +g28888 = NAND(g27738, g8139) +g28892 = NAND(g27779, g1772, g7275) +g28895 = NAND(g27775, g8146) +g28896 = NAND(g27837, g1936, g1862) +g28899 = NAND(g27833, g14612) +g28900 = NAND(g27886, g7451, g2040) +g28903 = NAND(g27800, g2197, g7280) +g28906 = NAND(g27796, g8150) +g28907 = NAND(g27858, g2361, g2287) +g28910 = NAND(g27854, g14614) +g28911 = NAND(g27907, g7456, g2465) +g28914 = NAND(g27937, g7462, g2555) +g28920 = NAND(g27779, g1802, g7315) +g28923 = NAND(g27775, g8195) +g28927 = NAND(g27837, g1906, g7322) +g28930 = NAND(g27833, g8201) +g28931 = NAND(g27886, g2070, g1996) +g28934 = NAND(g27882, g14641) +g28935 = NAND(g27800, g2227, g7328) +g28938 = NAND(g27796, g8205) +g28942 = NAND(g27858, g2331, g7335) +g28945 = NAND(g27854, g8211) +g28946 = NAND(g27907, g2495, g2421) +g28949 = NAND(g27903, g14643) +g28950 = NAND(g27937, g7490, g2599) +g28955 = NAND(g27837, g1936, g7362) +g28958 = NAND(g27833, g8249) +g28962 = NAND(g27886, g2040, g7369) +g28965 = NAND(g27882, g8255) +g28966 = NAND(g27858, g2361, g7380) +g28969 = NAND(g27854, g8267) +g28973 = NAND(g27907, g2465, g7387) +g28976 = NAND(g27903, g8273) +g28977 = NAND(g27937, g2629, g2555) +g28980 = NAND(g27933, g14680) +g28987 = NAND(g27886, g2070, g7411) +g28990 = NAND(g27882, g8310) +g28994 = NAND(g27907, g2495, g7424) +g28997 = NAND(g27903, g8324) +g29001 = NAND(g27937, g2599, g7431) +g29004 = NAND(g27933, g8330) +g29015 = NAND(g27742, g9586) +g29018 = NAND(g9586, g27742) +g29025 = NAND(g27937, g2629, g7462) +g29028 = NAND(g27933, g8381) +g29046 = NAND(g27779, g9640) +g29049 = NAND(g9640, g27779) +g29057 = NAND(g27800, g9649) +g29060 = NAND(g9649, g27800) +g29082 = NAND(g27837, g9694) +g29085 = NAND(g9694, g27837) +g29094 = NAND(g27858, g9700) +g29097 = NAND(g9700, g27858) +g29118 = NAND(g27886, g9755) +g29121 = NAND(g9755, g27886) +g29131 = NAND(g27907, g9762) +g29134 = NAND(g9762, g27907) +g29154 = NAND(g27937, g9835) +g29157 = NAND(g9835, g27937) +g29186 = NAND(g27051, g4507) +g29335 = NAND(g25540, g28131) +g29355 = NAND(g24383, g28109) +g29540 = NAND(g28336, g13464) +g29556 = NAND(g28349, g13486) +g29657 = NAND(g28363, g13634) +g29660 = NAND(g28448, g9582) +g29672 = NAND(g28376, g13672) +g29676 = NAND(g28381, g13676) +g29679 = NAND(g153, g28353, g23042) +g29694 = NAND(g28391, g13709) +g29702 = NAND(g28395, g13712) +g29719 = NAND(g28406, g13739) +g29722 = NAND(g28410, g13742) +g29737 = NAND(g28421, g13779) +g29778 = NAND(g294, g28444, g23204) +g30573 = NAND(g29355, g19666) +g30580 = NAND(g29335, g19666) +g31003 = NAND(g27163, g29497, g19644) +g31009 = NAND(g27187, g29503, g19644) +g31262 = NAND(g767, g29916, g11679) +g31509 = NAND(g599, g29933, g12323) +I29253 = NAND(g29482, g12017) +I29254 = NAND(g29482, I29253) +I29255 = NAND(g12017, I29253) +g31669 = NAND(I29254, I29255) +I29261 = NAND(g29485, g12046) +I29262 = NAND(g29485, I29261) +I29263 = NAND(g12046, I29261) +g31671 = NAND(I29262, I29263) +I29269 = NAND(g29486, g12050) +I29270 = NAND(g29486, I29269) +I29271 = NAND(g12050, I29269) +g31706 = NAND(I29270, I29271) +I29277 = NAND(g29488, g12081) +I29278 = NAND(g29488, I29277) +I29279 = NAND(g12081, I29277) +g31708 = NAND(I29278, I29279) +I29284 = NAND(g29489, g12085) +I29285 = NAND(g29489, I29284) +I29286 = NAND(g12085, I29284) +g31709 = NAND(I29285, I29286) +I29295 = NAND(g29495, g12117) +I29296 = NAND(g29495, I29295) +I29297 = NAND(g12117, I29295) +g31747 = NAND(I29296, I29297) +I29302 = NAND(g29496, g12121) +I29303 = NAND(g29496, I29302) +I29304 = NAND(g12121, I29302) +g31748 = NAND(I29303, I29304) +I29313 = NAND(g29501, g12154) +I29314 = NAND(g29501, I29313) +I29315 = NAND(g12154, I29313) +g31753 = NAND(I29314, I29315) +g31950 = NAND(g7285, g30573) +g31971 = NAND(g30573, g10511) +g31978 = NAND(g30580, g15591) +g31997 = NAND(g22306, g30580) +g32057 = NAND(g31003, g13297) +g32072 = NAND(g31009, g13301) +g33083 = NAND(g7805, g32118) +g33299 = NAND(g608, g32296, g12323) +g33306 = NAND(g776, g32212, g11679) +g33394 = NAND(g10159, g4474, g32426) +g33669 = NAND(g33378, g862) +g33679 = NAND(g33394, g10737, g10308) +g33838 = NAND(g33083, g4369) +g33925 = NAND(g33394, g4462, g4467) +g33930 = NAND(g33394, g12767, g9848) +g33933 = NAND(g33394, g12491, g12819, g12796) +g34048 = NAND(g33669, g10583, g7442) +I31972 = NAND(g33641, g33631) +I31973 = NAND(g33641, I31972) +I31974 = NAND(g33631, I31972) +g34051 = NAND(I31973, I31974) +I31983 = NAND(g33653, g33648) +I31984 = NAND(g33653, I31983) +I31985 = NAND(g33648, I31983) +g34056 = NAND(I31984, I31985) +g34162 = NAND(g785, g33823, g11679) +g34174 = NAND(g617, g33851, g12323) +I32185 = NAND(g33665, g33661) +I32186 = NAND(g33665, I32185) +I32187 = NAND(g33661, I32185) +g34220 = NAND(I32186, I32187) +I32202 = NAND(g33937, g33670) +I32203 = NAND(g33937, I32202) +I32204 = NAND(g33670, I32202) +g34227 = NAND(I32203, I32204) +I32431 = NAND(g34056, g34051) +I32432 = NAND(g34056, I32431) +I32433 = NAND(g34051, I32431) +g34422 = NAND(I32432, I32433) +I32439 = NAND(g34227, g34220) +I32440 = NAND(g34227, I32439) +I32441 = NAND(g34220, I32439) +g34424 = NAND(I32440, I32441) +I32516 = NAND(g34424, g34422) +I32517 = NAND(g34424, I32516) +I32518 = NAND(g34422, I32516) +g34469 = NAND(I32517, I32518) +g34545 = NAND(g11679, g794, g34354) +g34550 = NAND(g626, g34359, g12323) +I32756 = NAND(g34469, g25779) +I32757 = NAND(g34469, I32756) +I32758 = NAND(g25779, I32756) +g34650 = NAND(I32757, I32758) + +g7139 = NOR(g5406, g5366) +g7142 = NOR(g6573, g6565) +g7158 = NOR(g5752, g5712) +g7175 = NOR(g6098, g6058) +g7192 = NOR(g6444, g6404) +g7304 = NOR(g1183, g1171) +g7352 = NOR(g1526, g1514) +g7499 = NOR(g333, g355) +g7567 = NOR(g979, g990) +g7601 = NOR(g1322, g1333) +g7661 = NOR(g1211, g1216, g1221, g1205) +g7675 = NOR(g1554, g1559, g1564, g1548) +g7781 = NOR(g4064, g4057) +g8086 = NOR(g168, g174, g182) +g8131 = NOR(g4776, g4801, g4793) +g8177 = NOR(g4966, g4991, g4983) +g8182 = NOR(g405, g392) +g8720 = NOR(g358, g365) +g8864 = NOR(g3179, g3171) +g8906 = NOR(g3530, g3522) +g8933 = NOR(g4709, g4785) +g8958 = NOR(g3881, g3873) +g8984 = NOR(g4899, g4975) +g9015 = NOR(g3050, g3010) +g9061 = NOR(g3401, g3361) +g9100 = NOR(g3752, g3712) +g9586 = NOR(g1668, g1592) +g9602 = NOR(g4688, g4681, g4674, g4646) +g9640 = NOR(g1802, g1728) +g9649 = NOR(g2227, g2153) +g9664 = NOR(g4878, g4871, g4864, g4836) +g9694 = NOR(g1936, g1862) +g9700 = NOR(g2361, g2287) +g9755 = NOR(g2070, g1996) +g9762 = NOR(g2495, g2421) +g9835 = NOR(g2629, g2555) +g10123 = NOR(g4294, g4297) +g10179 = NOR(g2098, g1964, g1830, g1696) +g10205 = NOR(g2657, g2523, g2389, g2255) +g10266 = NOR(g5188, g5180) +g10281 = NOR(g5535, g5527) +g10312 = NOR(g5881, g5873) +g10318 = NOR(g25, g22) +g10338 = NOR(g5062, g5022) +g10341 = NOR(g6227, g6219) +g10421 = NOR(g6227, g9518) +g10488 = NOR(g4616, g7133, g10336) +g10491 = NOR(g6573, g9576) +g10510 = NOR(g7183, g4593, g4584) +g10555 = NOR(g7227, g4601, g4608) +g10615 = NOR(g1636, g7308) +g10649 = NOR(g1183, g8407) +g10666 = NOR(g8462, g1171) +g10671 = NOR(g1526, g8466) +g10695 = NOR(g8462, g8407) +g10699 = NOR(g8526, g1514) +g10709 = NOR(g7499, g351) +g10715 = NOR(g8526, g8466) +g10760 = NOR(g1046, g7479) +g10793 = NOR(g1389, g7503) +g10799 = NOR(g347, g7541) +g10801 = NOR(g1041, g7479) +g10803 = NOR(g1384, g7503) +g10808 = NOR(g8509, g7611) +g10819 = NOR(g7479, g1041) +g10821 = NOR(g7503, g1384) +g10831 = NOR(g7690, g7827) +g10862 = NOR(g7701, g7840) +g10884 = NOR(g7650, g8451) +g10893 = NOR(g1189, g7715, g7749) +g10899 = NOR(g4064, g8451) +g10918 = NOR(g1532, g7751, g7778) +g10922 = NOR(g7650, g4057) +g11006 = NOR(g7686, g7836) +g11012 = NOR(g7693, g7846) +g11039 = NOR(g9056, g9092) +g11107 = NOR(g9095, g9177) +g11119 = NOR(g9180, g9203) +g11148 = NOR(g8052, g9197, g9174, g9050) +g11171 = NOR(g8088, g9226, g9200, g9091) +g11184 = NOR(g513, g9040) +g11185 = NOR(g8038, g8183, g6804) +g11191 = NOR(g4776, g4801, g9030) +g11194 = NOR(g3288, g6875) +g11201 = NOR(g4125, g7765) +g11203 = NOR(g4966, g4991, g9064) +g11207 = NOR(g3639, g6905) +g11213 = NOR(g4776, g7892, g9030) +g11216 = NOR(g7998, g8037) +g11217 = NOR(g8531, g6875) +g11225 = NOR(g3990, g6928) +g11231 = NOR(g7928, g4801, g4793) +g11232 = NOR(g4966, g7898, g9064) +g11238 = NOR(g8584, g6905) +g11248 = NOR(g7953, g4991, g4983) +g11252 = NOR(g8620, g3057) +g11255 = NOR(g8623, g6928) +g11261 = NOR(g7928, g4801, g9030) +g11270 = NOR(g8431, g8434) +g11273 = NOR(g3061, g8620) +g11276 = NOR(g8534, g8691) +g11280 = NOR(g8647, g3408) +g11283 = NOR(g7953, g4991, g9064) +g11303 = NOR(g8497, g8500) +g11306 = NOR(g3412, g8647) +g11309 = NOR(g8587, g8728) +g11313 = NOR(g8669, g3759) +g11345 = NOR(g8477, g8479) +g11346 = NOR(g7980, g7964) +g11357 = NOR(g8558, g8561) +g11360 = NOR(g3763, g8669) +g11363 = NOR(g8626, g8751) +g11384 = NOR(g8538, g8540) +g11385 = NOR(g8021, g7985) +g11414 = NOR(g8591, g8593) +g11415 = NOR(g8080, g8026) +g11435 = NOR(g8107, g3171) +g11448 = NOR(g4191, g8790) +g11469 = NOR(g650, g9903, g645) +g11473 = NOR(g8107, g8059) +g11483 = NOR(g8165, g3522) +g11493 = NOR(g8964, g8967) +g11514 = NOR(g10295, g3161, g3155) +g11527 = NOR(g8165, g8114) +g11537 = NOR(g8229, g3873) +g11563 = NOR(g8059, g8011) +g11566 = NOR(g3161, g7964) +g11571 = NOR(g10323, g3512, g3506) +g11584 = NOR(g8229, g8172) +g11607 = NOR(g8848, g8993, g376) +g11610 = NOR(g7980, g3155) +g11618 = NOR(g8114, g8070) +g11621 = NOR(g3512, g7985) +g11626 = NOR(g7121, g3863, g3857) +g11653 = NOR(g7980, g7964) +g11658 = NOR(g8021, g3506) +g11666 = NOR(g8172, g8125) +g11669 = NOR(g3863, g8026) +g11692 = NOR(g8021, g7985) +g11697 = NOR(g8080, g3857) +g11715 = NOR(g8080, g8026) +g11729 = NOR(g3179, g8059) +g11747 = NOR(g3530, g8114) +g11755 = NOR(g4709, g8796) +g11763 = NOR(g3881, g8172) +g11771 = NOR(g8921, g4185) +g11773 = NOR(g8883, g4785) +g11780 = NOR(g4899, g8822) +g11797 = NOR(g8883, g8796) +g11804 = NOR(g8938, g4975) +g11834 = NOR(g8938, g8822) +g11846 = NOR(g7635, g7518, g7548) +g11862 = NOR(g7134, g7150) +g11869 = NOR(g7649, g7534, g7581) +g11885 = NOR(g7153, g7167) +g11891 = NOR(g812, g9166) +g11907 = NOR(g7170, g7184) +g11913 = NOR(g7197, g9166) +g11924 = NOR(g7187, g7209) +g11932 = NOR(g843, g9166) +g11935 = NOR(g9485, g7267) +g11940 = NOR(g2712, g10084) +g11945 = NOR(g7212, g7228) +g11950 = NOR(g9220, g9166) +g11954 = NOR(g9538, g7314) +g11958 = NOR(g9543, g7327) +g11972 = NOR(g9591, g7361) +g11976 = NOR(g9595, g7379) +g11995 = NOR(g9645, g7410) +g11999 = NOR(g9654, g7423) +g12002 = NOR(g5297, g7004) +g12017 = NOR(g9969, g9586) +g12025 = NOR(g9705, g7461) +g12026 = NOR(g9417, g9340) +g12029 = NOR(g5644, g7028) +g12046 = NOR(g10036, g9640) +g12050 = NOR(g10038, g9649) +g12059 = NOR(g9853, g7004) +g12067 = NOR(g5990, g7051) +g12081 = NOR(g10079, g9694) +g12085 = NOR(g10082, g9700) +g12093 = NOR(g9924, g7028) +g12101 = NOR(g6336, g7074) +g12113 = NOR(g1648, g8187) +g12117 = NOR(g10113, g9755) +g12121 = NOR(g10117, g9762) +g12123 = NOR(g6856, g2748) +g12126 = NOR(g9989, g5069) +g12129 = NOR(g9992, g7051) +g12137 = NOR(g6682, g7097) +g12146 = NOR(g1783, g8241) +g12150 = NOR(g2208, g8259) +g12154 = NOR(g10155, g9835) +g12160 = NOR(g9721, g9724) +g12163 = NOR(g5073, g9989) +g12166 = NOR(g9856, g10124) +g12170 = NOR(g10047, g5413) +g12173 = NOR(g10050, g7074) +g12189 = NOR(g1917, g8302) +g12193 = NOR(g2342, g8316) +g12198 = NOR(g9797, g9800) +g12201 = NOR(g5417, g10047) +g12204 = NOR(g9927, g10160) +g12208 = NOR(g10096, g5759) +g12211 = NOR(g10099, g7097) +g12223 = NOR(g2051, g8365) +g12226 = NOR(g2476, g8373) +g12228 = NOR(g10222, g10206, g10184, g10335) +g12234 = NOR(g9776, g9778) +g12235 = NOR(g9234, g9206) +g12246 = NOR(g9880, g9883) +g12249 = NOR(g5763, g10096) +g12252 = NOR(g9995, g10185) +g12256 = NOR(g10136, g6105) +g12288 = NOR(g2610, g8418) +g12296 = NOR(g9860, g9862) +g12297 = NOR(g9269, g9239) +g12308 = NOR(g9951, g9954) +g12311 = NOR(g6109, g10136) +g12314 = NOR(g10053, g10207) +g12318 = NOR(g10172, g6451) +g12333 = NOR(g1624, g8139) +g12346 = NOR(g9931, g9933) +g12347 = NOR(g9321, g9274) +g12358 = NOR(g10019, g10022) +g12361 = NOR(g6455, g10172) +g12364 = NOR(g10102, g10224) +g12371 = NOR(g1760, g8195) +g12374 = NOR(g2185, g8205) +g12377 = NOR(g6856, g2748, g9708) +g12405 = NOR(g9374, g5180) +g12418 = NOR(g9999, g10001) +g12419 = NOR(g9402, g9326) +g12432 = NOR(g1894, g8249) +g12435 = NOR(g9012, g8956, g8904, g8863) +g12437 = NOR(g2319, g8267) +g12443 = NOR(g9374, g9300) +g12453 = NOR(g9444, g5527) +g12466 = NOR(g10057, g10059) +g12467 = NOR(g9472, g9407) +g12479 = NOR(g2028, g8310) +g12483 = NOR(g2453, g8324) +g12486 = NOR(g9055, g9013, g8957, g8905) +g12492 = NOR(g7704, g5170, g5164) +g12505 = NOR(g9444, g9381) +g12515 = NOR(g9511, g5873) +g12540 = NOR(g2587, g8381) +g12550 = NOR(g9300, g9259) +g12553 = NOR(g5170, g9206) +g12558 = NOR(g7738, g5517, g5511) +g12571 = NOR(g9511, g9451) +g12581 = NOR(g9569, g6219) +g12591 = NOR(g504, g9040) +g12593 = NOR(g9234, g5164) +g12601 = NOR(g9381, g9311) +g12604 = NOR(g5517, g9239) +g12609 = NOR(g7766, g5863, g5857) +g12622 = NOR(g9569, g9518) +g12632 = NOR(g9631, g6565) +g12645 = NOR(g4467, g6961) +g12646 = NOR(g9234, g9206) +g12651 = NOR(g9269, g5511) +g12659 = NOR(g9451, g9392) +g12662 = NOR(g5863, g9274) +g12667 = NOR(g7791, g6209, g6203) +g12680 = NOR(g9631, g9576) +g12695 = NOR(g9269, g9239) +g12700 = NOR(g9321, g5857) +g12708 = NOR(g9518, g9462) +g12711 = NOR(g6209, g9326) +g12716 = NOR(g7812, g6555, g6549) +g12729 = NOR(g1657, g8139) +g12739 = NOR(g9321, g9274) +g12744 = NOR(g9402, g6203) +g12752 = NOR(g9576, g9529) +g12755 = NOR(g6555, g9407) +g12772 = NOR(g5188, g9300) +g12780 = NOR(g9402, g9326) +g12785 = NOR(g9472, g6549) +g12798 = NOR(g5535, g9381) +g12806 = NOR(g9472, g9407) +g12821 = NOR(g7132, g10223, g7149, g10261) +g12824 = NOR(g5881, g9451) +g12846 = NOR(g6837, g10430) +g12847 = NOR(g6838, g10430) +g12848 = NOR(g6839, g10430) +g12849 = NOR(g6840, g10430) +g12850 = NOR(g10430, g6845) +g12851 = NOR(g6846, g10430) +g12852 = NOR(g6847, g10430) +g12853 = NOR(g6848, g10430) +g12854 = NOR(g6849, g10430) +g12855 = NOR(g10430, g6854) +g12856 = NOR(g10430, g6855) +g12858 = NOR(g10365, g10430) +g12970 = NOR(g10555, g10510, g10488) +g12980 = NOR(g7909, g10741) +g13004 = NOR(g7933, g10741) +g13005 = NOR(g7939, g10762) +g13013 = NOR(g7957, g10762) +g13021 = NOR(g7544, g10741) +g13031 = NOR(g7301, g10741) +g13032 = NOR(g7577, g10762) +g13044 = NOR(g7349, g10762) +g13056 = NOR(g7400, g10741) +g13076 = NOR(g7443, g10741) +g13078 = NOR(g7446, g10762) +g13094 = NOR(g7487, g10762) +g13110 = NOR(g7841, g10741) +g13114 = NOR(g7528, g10741) +g13125 = NOR(g7863, g10762) +g13129 = NOR(g7553, g10762) +g13202 = NOR(g8347, g10511) +g13325 = NOR(g7841, g10741) +g13326 = NOR(g10929, g10905) +g13335 = NOR(g7851, g10741) +g13336 = NOR(g11330, g11011) +g13341 = NOR(g7863, g10762) +g13342 = NOR(g10961, g10935) +g13377 = NOR(g7873, g10762) +g13378 = NOR(g11374, g11017) +g13480 = NOR(g3017, g11858) +g13500 = NOR(g8480, g12641) +g13501 = NOR(g3368, g11881) +g13512 = NOR(g9077, g12527) +g13517 = NOR(g8541, g12692) +g13518 = NOR(g3719, g11903) +g13539 = NOR(g8594, g12735) +g13568 = NOR(g8046, g12527) +g13603 = NOR(g8009, g10721) +g13622 = NOR(g278, g11166) +g13631 = NOR(g8068, g10733) +g13661 = NOR(g528, g11185) +g13670 = NOR(g8123, g10756) +g13698 = NOR(g528, g12527, g11185) +g13700 = NOR(g3288, g11615) +g13730 = NOR(g3639, g11663) +g13765 = NOR(g8531, g11615) +g13772 = NOR(g3990, g11702) +g13796 = NOR(g9158, g12527) +g13799 = NOR(g8584, g11663) +g13806 = NOR(g11245, g4076) +g13824 = NOR(g8623, g11702) +g13831 = NOR(g11245, g7666) +g13852 = NOR(g11320, g8347) +g13872 = NOR(g8745, g11083) +g13883 = NOR(g4709, g4785, g11155) +g13908 = NOR(g4709, g8796, g11155) +g13910 = NOR(g4899, g4975, g11173) +g13913 = NOR(g8859, g11083) +g13919 = NOR(g3347, g11276) +g13937 = NOR(g8883, g4785, g11155) +g13939 = NOR(g4899, g8822, g11173) +g13944 = NOR(g10262, g12259) +g13946 = NOR(g8651, g11083) +g13947 = NOR(g8948, g11083) +g13954 = NOR(g8663, g11276) +g13959 = NOR(g3698, g11309) +g13970 = NOR(g8883, g8796, g11155) +g13971 = NOR(g8938, g4975, g11173) +g13989 = NOR(g8697, g11309) +g13994 = NOR(g4049, g11363) +g13996 = NOR(g8938, g8822, g11173) +g14000 = NOR(g8766, g12259) +g14001 = NOR(g739, g11083) +g14002 = NOR(g8681, g11083) +g14003 = NOR(g9003, g11083) +g14027 = NOR(g8734, g11363) +g14033 = NOR(g8808, g12259) +g14036 = NOR(g8725, g11083) +g14037 = NOR(g8748, g11083) +g14064 = NOR(g9214, g12259) +g14090 = NOR(g8851, g12259) +g14091 = NOR(g8854, g12259) +g14092 = NOR(g8774, g11083) +g14093 = NOR(g8833, g11083) +g14094 = NOR(g8770, g11083) +g14121 = NOR(g8891, g12259) +g14122 = NOR(g8895, g12259) +g14124 = NOR(g8830, g11083) +g14145 = NOR(g8945, g12259) +g14163 = NOR(g8997, g12259) +g14164 = NOR(g9000, g12259) +g14165 = NOR(g8951, g11083) +g14176 = NOR(g9044, g12259) +g14178 = NOR(g8899, g11083) +g14181 = NOR(g9083, g12259) +g14188 = NOR(g9162, g12259) +g14194 = NOR(g5029, g10515) +g14211 = NOR(g9779, g10823) +g14212 = NOR(g5373, g10537) +g14227 = NOR(g9863, g10838) +g14228 = NOR(g5719, g10561) +g14247 = NOR(g9934, g10869) +g14248 = NOR(g6065, g10578) +g14253 = NOR(g10032, g12259, g9217) +g14271 = NOR(g10002, g10874) +g14272 = NOR(g6411, g10598) +g14278 = NOR(g562, g12259, g9217) +g14291 = NOR(g9839, g12155) +g14306 = NOR(g10060, g10887) +g14313 = NOR(g12016, g9250) +g14320 = NOR(g9257, g11111) +g14334 = NOR(g12044, g9337) +g14335 = NOR(g12045, g9283) +g14337 = NOR(g12049, g9284) +g14339 = NOR(g12289, g2735) +g14347 = NOR(g9309, g11123) +g14360 = NOR(g12078, g9484) +g14361 = NOR(g12079, g9413) +g14362 = NOR(g12080, g9338) +g14364 = NOR(g12083, g9415) +g14365 = NOR(g12084, g9339) +g14367 = NOR(g9547, g12289) +g14382 = NOR(g9390, g11139) +g14391 = NOR(g12112, g9585) +g14392 = NOR(g12114, g9537) +g14393 = NOR(g12115, g9488) +g14394 = NOR(g12116, g9414) +g14395 = NOR(g12118, g9542) +g14396 = NOR(g12119, g9489) +g14397 = NOR(g12120, g9416) +g14399 = NOR(g5297, g12598) +g14411 = NOR(g9460, g11160) +g14413 = NOR(g11914, g9638) +g14414 = NOR(g12145, g9639) +g14415 = NOR(g12147, g9590) +g14416 = NOR(g12148, g9541) +g14417 = NOR(g12149, g9648) +g14418 = NOR(g12151, g9594) +g14419 = NOR(g12152, g9546) +g14420 = NOR(g12153, g9490) +g14425 = NOR(g5644, g12656) +g14437 = NOR(g9527, g11178) +g14444 = NOR(g11936, g9692) +g14445 = NOR(g12188, g9693) +g14446 = NOR(g12190, g9644) +g14447 = NOR(g11938, g9698) +g14448 = NOR(g12192, g9699) +g14449 = NOR(g12194, g9653) +g14450 = NOR(g12195, g9598) +g14490 = NOR(g9853, g12598) +g14497 = NOR(g5990, g12705) +g14512 = NOR(g11955, g9753) +g14513 = NOR(g12222, g9754) +g14514 = NOR(g11959, g9760) +g14515 = NOR(g12225, g9761) +g14516 = NOR(g12227, g9704) +g14522 = NOR(g9924, g12656) +g14529 = NOR(g6336, g12749) +g14538 = NOR(g11973, g9828) +g14539 = NOR(g11977, g9833) +g14540 = NOR(g12287, g9834) +g14549 = NOR(g9992, g12705) +g14556 = NOR(g6682, g12790) +g14568 = NOR(g12000, g9915) +g14575 = NOR(g10050, g12749) +g14602 = NOR(g10099, g12790) +g14611 = NOR(g12333, g9749) +g14640 = NOR(g12371, g9824) +g14642 = NOR(g12374, g9829) +g14678 = NOR(g12432, g9907) +g14679 = NOR(g12437, g9911) +g14687 = NOR(g5352, g12166) +g14707 = NOR(g10143, g12259) +g14712 = NOR(g12479, g9971) +g14713 = NOR(g12483, g9974) +g14726 = NOR(g10090, g12166) +g14731 = NOR(g5698, g12204) +g14751 = NOR(g10622, g10617, g10609, g10603) +g14752 = NOR(g12540, g10040) +g14754 = NOR(g12821, g2988) +g14767 = NOR(g10130, g12204) +g14772 = NOR(g6044, g12252) +g14792 = NOR(g10653, g10623, g10618, g10611) +g14793 = NOR(g2988, g12228) +g14816 = NOR(g10166, g12252) +g14821 = NOR(g6390, g12314) +g14867 = NOR(g10191, g12314) +g14872 = NOR(g6736, g12364) +g14911 = NOR(g10213, g12364) +g14914 = NOR(g12822, g12797) +g14988 = NOR(g10816, g10812, g10805) +g15049 = NOR(g13350, g6799) +g15050 = NOR(g12834, g13350) +g15051 = NOR(g6801, g13350) +g15052 = NOR(g12835, g13350) +g15053 = NOR(g12836, g13350) +g15054 = NOR(g12837, g13350) +g15055 = NOR(g6808, g13350) +g15056 = NOR(g6809, g13350) +g15057 = NOR(g6810, g13350) +g15058 = NOR(g12838, g13350) +g15059 = NOR(g12839, g13350) +g15060 = NOR(g13350, g6814) +g15061 = NOR(g6815, g13394) +g15062 = NOR(g6817, g13394) +g15063 = NOR(g6818, g13394) +g15064 = NOR(g6820, g13394) +g15065 = NOR(g13394, g12840) +g15066 = NOR(g12841, g13394) +g15067 = NOR(g12842, g13394) +g15068 = NOR(g6826, g13416) +g15069 = NOR(g6828, g13416) +g15070 = NOR(g6829, g13416) +g15071 = NOR(g6831, g13416) +g15072 = NOR(g13416, g12843) +g15073 = NOR(g12844, g13416) +g15074 = NOR(g12845, g13416) +g15086 = NOR(g13144, g12859) +g15087 = NOR(g12860, g13144) +g15088 = NOR(g13144, g6874) +g15089 = NOR(g13144, g12861) +g15090 = NOR(g13144, g12862) +g15091 = NOR(g13177, g12863) +g15092 = NOR(g12864, g13177) +g15093 = NOR(g13177, g6904) +g15094 = NOR(g13177, g12865) +g15095 = NOR(g13177, g12866) +g15096 = NOR(g13191, g12867) +g15097 = NOR(g12868, g13191) +g15098 = NOR(g13191, g6927) +g15099 = NOR(g13191, g12869) +g15100 = NOR(g13191, g12870) +g15101 = NOR(g12871, g14591) +g15102 = NOR(g14591, g6954) +g15106 = NOR(g12872, g10430) +g15120 = NOR(g12873, g13605) +g15121 = NOR(g12874, g13605) +g15122 = NOR(g6959, g13605) +g15123 = NOR(g6975, g13605) +g15126 = NOR(g12878, g13605) +g15127 = NOR(g12879, g13605) +g15128 = NOR(g13638, g12880) +g15129 = NOR(g6984, g13638) +g15130 = NOR(g13638, g6985) +g15131 = NOR(g12881, g13638) +g15132 = NOR(g12882, g13638) +g15133 = NOR(g12883, g13638) +g15134 = NOR(g13638, g12884) +g15135 = NOR(g6990, g13638) +g15136 = NOR(g13680, g12885) +g15137 = NOR(g6992, g13680) +g15138 = NOR(g13680, g6993) +g15139 = NOR(g12886, g13680) +g15140 = NOR(g12887, g13680) +g15141 = NOR(g12888, g13680) +g15142 = NOR(g13680, g12889) +g15143 = NOR(g6998, g13680) +g15144 = NOR(g13716, g12890) +g15145 = NOR(g12891, g13716) +g15146 = NOR(g13716, g7003) +g15147 = NOR(g13716, g12892) +g15148 = NOR(g13716, g12893) +g15149 = NOR(g13745, g12894) +g15150 = NOR(g12895, g13745) +g15151 = NOR(g13745, g7027) +g15152 = NOR(g13745, g12896) +g15153 = NOR(g13745, g12897) +g15154 = NOR(g13782, g12898) +g15155 = NOR(g12899, g13782) +g15156 = NOR(g13782, g7050) +g15157 = NOR(g13782, g12900) +g15158 = NOR(g13782, g12901) +g15159 = NOR(g13809, g12902) +g15160 = NOR(g12903, g13809) +g15161 = NOR(g13809, g7073) +g15162 = NOR(g13809, g12904) +g15163 = NOR(g13809, g12905) +g15164 = NOR(g13835, g12906) +g15165 = NOR(g12907, g13835) +g15166 = NOR(g13835, g7096) +g15167 = NOR(g13835, g12908) +g15168 = NOR(g13835, g12909) +g15170 = NOR(g7118, g14279) +g15372 = NOR(g817, g14279) +g15508 = NOR(g10320, g14279) +g15570 = NOR(g822, g14279) +g15578 = NOR(g7216, g14279) +g15585 = NOR(g11862, g14194) +g15594 = NOR(g10614, g13026, g7285) +g15608 = NOR(g11885, g14212) +g15628 = NOR(g11907, g14228) +g15647 = NOR(g11924, g14248) +g15669 = NOR(g11945, g14272) +g15718 = NOR(g13858, g11330) +g15724 = NOR(g13858, g11374) +g15754 = NOR(g341, g7440, g13385) +g15825 = NOR(g7666, g13217) +g15992 = NOR(g10929, g13846) +g16024 = NOR(g14216, g11890) +g16027 = NOR(g10929, g13260) +g16044 = NOR(g10961, g13861) +g16066 = NOR(g10929, g13307) +g16072 = NOR(g10961, g13273) +g16090 = NOR(g10961, g13315) +g16183 = NOR(g9223, g13545) +g16198 = NOR(g9247, g13574) +g16201 = NOR(g13462, g4704) +g16209 = NOR(g13478, g4749) +g16210 = NOR(g13479, g4894) +g16215 = NOR(g1211, g13545) +g16219 = NOR(g13498, g4760) +g16220 = NOR(g13499, g4939) +g16226 = NOR(g8052, g13545) +g16227 = NOR(g1554, g13574) +g16231 = NOR(g13515, g4771) +g16232 = NOR(g13516, g4950) +g16237 = NOR(g8088, g13574) +g16242 = NOR(g13529, g4961) +g16246 = NOR(g13551, g11169) +g16268 = NOR(g7913, g13121) +g16272 = NOR(g13580, g11189) +g16287 = NOR(g13622, g11144) +g16288 = NOR(g13794, g417) +g16292 = NOR(g7943, g13134) +g16313 = NOR(g8005, g13600) +g16424 = NOR(g8064, g13628) +g16476 = NOR(g8119, g13667) +g16479 = NOR(g14719, g12490) +g16488 = NOR(g13697, g13656) +g16581 = NOR(g13756, g8086) +g16646 = NOR(g13437, g11020, g11372) +g17148 = NOR(g827, g14279) +g17174 = NOR(g9194, g14279) +g17175 = NOR(g1216, g13545) +g17180 = NOR(g1559, g13574) +g17190 = NOR(g723, g14279) +g17194 = NOR(g11039, g13480) +g17198 = NOR(g9282, g14279) +g17213 = NOR(g11107, g13501) +g17239 = NOR(g11119, g13518) +g17284 = NOR(g9253, g14317) +g17309 = NOR(g9305, g14344) +g17393 = NOR(g9386, g14379) +g17420 = NOR(g9456, g14408) +g17482 = NOR(g9523, g14434) +g17515 = NOR(g13221, g10828) +g17619 = NOR(g10179, g12955) +g17625 = NOR(g14541, g12123) +g17657 = NOR(g14751, g12955) +g17663 = NOR(g10205, g12983) +g17694 = NOR(g12435, g12955) +g17700 = NOR(g14792, g12983) +g17727 = NOR(g12486, g12983) +g17954 = NOR(g832, g14279) +g19063 = NOR(g7909, g15674) +g19070 = NOR(g16957, g11720) +g19140 = NOR(g7939, g15695) +g19209 = NOR(g12971, g15614, g11320) +g19268 = NOR(g15979, g962) +g19338 = NOR(g16031, g1306) +g19388 = NOR(g17181, g14256) +g19400 = NOR(g17139, g14206) +g19401 = NOR(g17193, g14296) +g19402 = NOR(g15979, g13133) +g19413 = NOR(g17151, g14221) +g19422 = NOR(g16031, g13141) +g19430 = NOR(g17150, g14220) +g19436 = NOR(g17176, g14233) +g19444 = NOR(g17192, g14295) +g19453 = NOR(g17199, g14316) +g19778 = NOR(g16268, g1061) +g19793 = NOR(g16292, g1404) +g19853 = NOR(g15746, g1052) +g19873 = NOR(g15755, g1395) +g19880 = NOR(g16201, g13634) +g19887 = NOR(g3025, g16275) +g19890 = NOR(g16987, g8058) +g19906 = NOR(g16209, g13672) +g19907 = NOR(g16210, g13676) +g19919 = NOR(g16987, g11205) +g19932 = NOR(g3376, g16296) +g19935 = NOR(g17062, g8113) +g19951 = NOR(g16219, g13709) +g19953 = NOR(g16220, g13712) +g19968 = NOR(g17062, g11223) +g19981 = NOR(g3727, g16316) +g19984 = NOR(g17096, g8171) +g19997 = NOR(g16231, g13739) +g19999 = NOR(g16232, g13742) +g20000 = NOR(g13661, g16264) +g20014 = NOR(g17096, g11244) +g20027 = NOR(g16242, g13779) +g20149 = NOR(g17091, g14185) +g20183 = NOR(g17152, g14222) +g20234 = NOR(g17140, g14207) +g20390 = NOR(g17182, g14257) +g20717 = NOR(g5037, g17217) +g20720 = NOR(g17847, g9299) +g20841 = NOR(g17847, g12027) +g20854 = NOR(g5381, g17243) +g20857 = NOR(g17929, g9380) +g20982 = NOR(g17929, g12065) +g20995 = NOR(g5727, g17287) +g20998 = NOR(g18065, g9450) +g21062 = NOR(g9547, g17297) +g21127 = NOR(g18065, g12099) +g21140 = NOR(g6073, g17312) +g21143 = NOR(g15348, g9517) +g21193 = NOR(g15348, g12135) +g21206 = NOR(g6419, g17396) +g21209 = NOR(g15483, g9575) +g21250 = NOR(g9417, g9340, g17494) +g21256 = NOR(g15483, g12179) +g21277 = NOR(g9417, g9340, g17467) +g21284 = NOR(g16646, g9690) +g21389 = NOR(g10143, g17748, g12259) +g21652 = NOR(g17619, g17663) +g21655 = NOR(g17657, g17700) +g21658 = NOR(g17694, g17727) +g22190 = NOR(g2827, g18949) +g22357 = NOR(g1024, g19699) +g22399 = NOR(g1367, g19720) +g22400 = NOR(g19345, g15718) +g22405 = NOR(g18957, g20136, g20114) +g22448 = NOR(g1018, g19699) +g22450 = NOR(g19345, g15724) +g22488 = NOR(g19699, g1002) +g22491 = NOR(g1361, g19720) +g22513 = NOR(g1002, g19699) +g22514 = NOR(g19699, g1018) +g22517 = NOR(g19720, g1345) +g22521 = NOR(g1036, g19699) +g22522 = NOR(g19699, g1024) +g22523 = NOR(g1345, g19720) +g22524 = NOR(g19720, g1361) +g22535 = NOR(g19699, g1030) +g22536 = NOR(g1379, g19720) +g22537 = NOR(g19720, g1367) +g22539 = NOR(g1030, g19699) +g22540 = NOR(g19720, g1373) +g22545 = NOR(g1373, g19720) +g22654 = NOR(g7733, g19506) +g22929 = NOR(g19773, g12970) +g22983 = NOR(g979, g16268, g19853) +g22993 = NOR(g1322, g16292, g19873) +g23024 = NOR(g7936, g19407) +g23042 = NOR(g16581, g19462, g10685) +g23051 = NOR(g7960, g19427) +g23052 = NOR(g8334, g19916) +g23063 = NOR(g16313, g19887) +g23079 = NOR(g8390, g19965) +g23108 = NOR(g16424, g19932) +g23124 = NOR(g8443, g20011) +g23135 = NOR(g16476, g19981) +g23204 = NOR(g10685, g19462, g16488) +g23208 = NOR(g20035, g16324) +g23560 = NOR(g9607, g20838) +g23586 = NOR(g17284, g20717) +g23602 = NOR(g9672, g20979) +g23626 = NOR(g17309, g20854) +g23642 = NOR(g9733, g21124) +g23662 = NOR(g17393, g20995) +g23678 = NOR(g9809, g21190) +g23686 = NOR(g2767, g21066) +g23695 = NOR(g17420, g21140) +g23711 = NOR(g9892, g21253) +g23729 = NOR(g17482, g21206) +g23763 = NOR(g2795, g21276) +g23835 = NOR(g2791, g21303) +g23871 = NOR(g2811, g21348) +g23883 = NOR(g2779, g21067) +g23918 = NOR(g2799, g21382) +g23955 = NOR(g2823, g18890) +g23956 = NOR(g18957, g18918, g20136, g20114) +g24018 = NOR(I23162, I23163) +g24145 = NOR(g19402, g19422) +g24148 = NOR(g19268, g19338) +g24383 = NOR(g22409, g22360) +g24391 = NOR(g22190, g14645) +g24439 = NOR(g7400, g22312) +g24453 = NOR(g7446, g22325) +g24494 = NOR(g23513, g23532) +g24497 = NOR(g23533, g23553) +g24508 = NOR(g23577, g23618) +g24514 = NOR(g23619, g23657) +g24575 = NOR(g23498, g23514) +g24619 = NOR(g23554, g23581) +g24631 = NOR(g20516, g20436, g20219, g22957) +g24701 = NOR(g979, g23024, g19778) +g24720 = NOR(g1322, g23051, g19793) +g24751 = NOR(g3034, g23105) +g24766 = NOR(g3385, g23132) +g24779 = NOR(g3736, g23167) +g24875 = NOR(g8725, g23850, g11083) +g24953 = NOR(g10262, g23978, g12259) +g24959 = NOR(g8858, g23324) +g24976 = NOR(g671, g23324) +g24990 = NOR(g8898, g23324) +g25004 = NOR(g676, g23324) +g25005 = NOR(g6811, g23324) +g25022 = NOR(g714, g23324) +g25141 = NOR(g22228, g10334) +g25144 = NOR(g5046, g23623) +g25160 = NOR(g5390, g23659) +g25175 = NOR(g5736, g23692) +g25189 = NOR(g6082, g23726) +g25203 = NOR(g6428, g23756) +g25247 = NOR(g23763, g14645) +g25317 = NOR(g9766, g23782) +g25321 = NOR(g23835, g14645) +g25407 = NOR(g23871, g14645) +g25446 = NOR(g23686, g14645) +g25447 = NOR(g23883, g14645) +g25501 = NOR(g23918, g14645) +g25504 = NOR(g22550, g7222) +g25521 = NOR(g23955, g14645) +g25540 = NOR(g22409, g22360) +g25769 = NOR(g25453, g25414) +g25770 = NOR(g25417, g25377) +g25776 = NOR(g7166, g24380, g24369) +g25777 = NOR(g25482, g25456) +g25778 = NOR(g25459, g25420) +g25784 = NOR(g25507, g25485) +g25785 = NOR(g25488, g25462) +g25800 = NOR(g25518, g25510) +g25851 = NOR(g4311, g24380, g24369) +g25887 = NOR(g24984, g11706) +g25932 = NOR(g7680, g24528) +g25944 = NOR(g7716, g24591) +g25947 = NOR(g1199, g24591) +g25948 = NOR(g7752, g24609) +g25950 = NOR(g1070, g24591) +g25952 = NOR(g1542, g24609) +g25954 = NOR(g7750, g24591) +g25956 = NOR(g1413, g24609) +g25958 = NOR(g7779, g24609) +g26098 = NOR(g9073, g24732) +g26162 = NOR(g23052, g24751) +g26183 = NOR(g23079, g24766) +g26209 = NOR(g23124, g24779) +g26212 = NOR(g23837, g25408) +g26247 = NOR(g7995, g24732) +g26256 = NOR(g23873, g25479) +g26267 = NOR(g8033, g24732) +g26268 = NOR(g283, g24825) +g26296 = NOR(g8287, g24732) +g26297 = NOR(g8519, g24825) +g26298 = NOR(g8297, g24825) +g26309 = NOR(g8575, g24825) +g26314 = NOR(g24808, g24802) +g26330 = NOR(g8631, g24825) +g26338 = NOR(g8458, g24825) +g26346 = NOR(g8522, g24825) +g26515 = NOR(g24843, g24822) +g26545 = NOR(g24881, g24855) +g26546 = NOR(g24858, g24846) +g26573 = NOR(g24897, g24884) +g26574 = NOR(g24887, g24861) +g26598 = NOR(g8990, g13756, g24732) +g26603 = NOR(g24908, g24900) +g26609 = NOR(g146, g24732) +g26625 = NOR(g23560, g25144) +g26628 = NOR(g8990, g24732) +g26645 = NOR(g23602, g25160) +g26649 = NOR(g9037, g24732) +g26667 = NOR(g23642, g25175) +g26686 = NOR(g23678, g25189) +g26715 = NOR(g23711, g25203) +g26865 = NOR(g25328, g25290) +g26872 = NOR(g25411, g25371) +g26873 = NOR(g25374, g25331) +g26976 = NOR(g5016, g25791) +g26993 = NOR(g5360, g25805) +g27007 = NOR(g5706, g25821) +g27010 = NOR(g6052, g25839) +g27012 = NOR(g6398, g25856) +g27027 = NOR(g26398, g26484) +g27046 = NOR(g7544, g25888) +g27059 = NOR(g7577, g25895) +g27063 = NOR(g26485, g26516) +g27093 = NOR(g26712, g26749) +g27102 = NOR(g26750, g26779) +g27337 = NOR(g8334, g26616) +g27338 = NOR(g9291, g26616) +g27343 = NOR(g8005, g26616) +g27344 = NOR(g8390, g26636) +g27345 = NOR(g9360, g26636) +g27352 = NOR(g7975, g26616) +g27353 = NOR(g8097, g26616) +g27354 = NOR(g8064, g26636) +g27355 = NOR(g8443, g26657) +g27356 = NOR(g9429, g26657) +g27364 = NOR(g8426, g26616) +g27366 = NOR(g8016, g26636) +g27367 = NOR(g8155, g26636) +g27368 = NOR(g8119, g26657) +g27379 = NOR(g8492, g26636) +g27381 = NOR(g8075, g26657) +g27382 = NOR(g8219, g26657) +g27400 = NOR(g8553, g26657) +g27479 = NOR(g9056, g26616) +g27499 = NOR(g9095, g26636) +g27511 = NOR(g22137, g26866, g20277) +g27516 = NOR(g9180, g26657) +g27528 = NOR(g8770, g26352, g11083) +g27629 = NOR(g8891, g26382, g12259) +g27647 = NOR(g3004, g26616) +g27652 = NOR(g3355, g26636) +g27659 = NOR(g3706, g26657) +g27703 = NOR(g9607, g25791) +g27704 = NOR(g7239, g25791) +g27717 = NOR(g9492, g26745) +g27720 = NOR(g9253, g25791) +g27721 = NOR(g9672, g25805) +g27722 = NOR(g7247, g25805) +g27731 = NOR(g9229, g25791) +g27732 = NOR(g9364, g25791) +g27733 = NOR(g9305, g25805) +g27734 = NOR(g9733, g25821) +g27735 = NOR(g7262, g25821) +g27766 = NOR(g9716, g25791) +g27768 = NOR(g9264, g25805) +g27769 = NOR(g9434, g25805) +g27770 = NOR(g9386, g25821) +g27771 = NOR(g9809, g25839) +g27772 = NOR(g7297, g25839) +g27823 = NOR(g9792, g25805) +g27825 = NOR(g9316, g25821) +g27826 = NOR(g9501, g25821) +g27827 = NOR(g9456, g25839) +g27828 = NOR(g9892, g25856) +g27829 = NOR(g7345, g25856) +g27875 = NOR(g9875, g25821) +g27877 = NOR(g9397, g25839) +g27878 = NOR(g9559, g25839) +g27879 = NOR(g9523, g25856) +g27924 = NOR(g9946, g25839) +g27926 = NOR(g9467, g25856) +g27927 = NOR(g9621, g25856) +g27954 = NOR(g10014, g25856) +g27960 = NOR(g7134, g25791) +g27966 = NOR(g7153, g25805) +g27969 = NOR(g7170, g25821) +g27973 = NOR(g7187, g25839) +g27982 = NOR(g7212, g25856) +g28031 = NOR(g21209, I26522, I26523) +g28106 = NOR(g7812, g26994) +g28149 = NOR(g27598, g27612) +g28340 = NOR(g27439, g26339) +g28353 = NOR(g9073, g27654, g24732) +g28414 = NOR(g27467, g26347) +g28425 = NOR(g27493, g26351) +g28444 = NOR(g8575, g27463, g24825) +g28452 = NOR(g3161, g27602) +g28457 = NOR(g7980, g27602) +g28462 = NOR(g3512, g27617) +g28468 = NOR(g3155, g10295, g27602) +g28469 = NOR(g3171, g27602) +g28470 = NOR(g8021, g27617) +g28475 = NOR(g3863, g27635) +g28476 = NOR(g27627, g26547) +g28480 = NOR(g8059, g27602) +g28481 = NOR(g3506, g10323, g27617) +g28482 = NOR(g3522, g27617) +g28483 = NOR(g8080, g27635) +g28491 = NOR(g8114, g27617) +g28492 = NOR(g3857, g7121, g27635) +g28493 = NOR(g3873, g27635) +g28496 = NOR(g3179, g27602) +g28498 = NOR(g8172, g27635) +g28509 = NOR(g8107, g27602) +g28510 = NOR(g3530, g27617) +g28514 = NOR(g8165, g27617) +g28515 = NOR(g3881, g27635) +g28519 = NOR(g8011, g27602, g10295) +g28520 = NOR(g8229, g27635) +g28521 = NOR(g27649, g26604) +g28529 = NOR(g8070, g27617, g10323) +g28540 = NOR(g8125, g27635, g7121) +g28552 = NOR(g10295, g27602) +g28568 = NOR(g10323, g27617) +g28584 = NOR(g7121, g27635) +g28803 = NOR(g27730, g22763) +g28953 = NOR(g5170, g27999) +g28981 = NOR(g9234, g27999) +g28986 = NOR(g5517, g28010) +g29005 = NOR(g5164, g7704, g27999) +g29006 = NOR(g5180, g27999) +g29007 = NOR(g9269, g28010) +g29012 = NOR(g5863, g28020) +g29032 = NOR(g9300, g27999) +g29033 = NOR(g5511, g7738, g28010) +g29034 = NOR(g5527, g28010) +g29035 = NOR(g9321, g28020) +g29040 = NOR(g6209, g26977) +g29069 = NOR(g9381, g28010) +g29070 = NOR(g5857, g7766, g28020) +g29071 = NOR(g5873, g28020) +g29072 = NOR(g9402, g26977) +g29077 = NOR(g6555, g26994) +g29104 = NOR(g5188, g27999) +g29106 = NOR(g9451, g28020) +g29107 = NOR(g6203, g7791, g26977) +g29108 = NOR(g6219, g26977) +g29109 = NOR(g9472, g26994) +g29141 = NOR(g9374, g27999) +g29142 = NOR(g5535, g28010) +g29144 = NOR(g9518, g26977) +g29145 = NOR(g6549, g7812, g26994) +g29146 = NOR(g6565, g26994) +g29164 = NOR(g9444, g28010) +g29165 = NOR(g5881, g28020) +g29167 = NOR(g9576, g26994) +g29173 = NOR(g9259, g27999, g7704) +g29174 = NOR(g9511, g28020) +g29175 = NOR(g6227, g26977) +g29179 = NOR(g9311, g28010, g7738) +g29180 = NOR(g9569, g26977) +g29181 = NOR(g6573, g26994) +g29183 = NOR(g9392, g28020, g7766) +g29184 = NOR(g9631, g26994) +g29187 = NOR(g7704, g27999) +g29189 = NOR(g9462, g26977, g7791) +g29191 = NOR(g7738, g28010) +g29193 = NOR(g9529, g26994, g7812) +g29198 = NOR(g7766, g28020) +g29200 = NOR(g7791, g26977) +g29359 = NOR(g7528, g28167) +g29361 = NOR(g7553, g28174) +g29370 = NOR(g28585, g28599) +g29497 = NOR(g22763, g28241) +g29503 = NOR(g22763, g28250) +g29675 = NOR(g28380, g8236, g8354) +g29705 = NOR(g28399, g8284, g8404) +g29873 = NOR(g6875, g28458) +g29886 = NOR(g3288, g28458) +g29889 = NOR(g6905, g28471) +g29898 = NOR(g6895, g28458) +g29900 = NOR(g3639, g28471) +g29903 = NOR(g6928, g28484) +g29908 = NOR(g6918, g28471) +g29910 = NOR(g3990, g28484) +g29915 = NOR(g6941, g28484) +g29916 = NOR(g8681, g28504, g11083) +g29933 = NOR(g8808, g28500, g12259) +g30106 = NOR(g28739, g7268) +g30117 = NOR(g28739, g7252) +g30119 = NOR(g28761, g7315) +g30123 = NOR(g28768, g7328) +g30129 = NOR(g28739, g14537) +g30130 = NOR(g28761, g7275) +g30132 = NOR(g28789, g7362) +g30134 = NOR(g28768, g7280) +g30136 = NOR(g28799, g7380) +g30143 = NOR(g28761, g14566) +g30144 = NOR(g28789, g7322) +g30146 = NOR(g28833, g7411) +g30147 = NOR(g28768, g14567) +g30148 = NOR(g28799, g7335) +g30150 = NOR(g28846, g7424) +g30156 = NOR(g28789, g14587) +g30157 = NOR(g28833, g7369) +g30159 = NOR(g28799, g14589) +g30160 = NOR(g28846, g7387) +g30162 = NOR(g28880, g7462) +g30169 = NOR(g28833, g14613) +g30170 = NOR(g28846, g14615) +g30171 = NOR(g28880, g7431) +g30183 = NOR(g28880, g14644) +g30240 = NOR(g7004, g28982) +g30249 = NOR(g5297, g28982) +g30252 = NOR(g7028, g29008) +g30260 = NOR(g7018, g28982) +g30262 = NOR(g5644, g29008) +g30265 = NOR(g7051, g29036) +g30271 = NOR(g7041, g29008) +g30273 = NOR(g5990, g29036) +g30276 = NOR(g7074, g29073) +g30280 = NOR(g7064, g29036) +g30282 = NOR(g6336, g29073) +g30285 = NOR(g7097, g29110) +g30288 = NOR(g7087, g29073) +g30290 = NOR(g6682, g29110) +g30294 = NOR(g7110, g29110) +g30601 = NOR(g16279, g29718) +g30613 = NOR(g4507, g29365) +g30922 = NOR(g16662, g29810) +g30929 = NOR(g29803, g29835) +g30934 = NOR(g29836, g29850) +g31008 = NOR(g30004, g30026) +g31068 = NOR(g4801, g29540) +g31116 = NOR(g7892, g29540) +g31117 = NOR(g4991, g29556) +g31119 = NOR(g7898, g29556) +g31121 = NOR(g4776, g29540) +g31126 = NOR(g7928, g29540) +g31127 = NOR(g4966, g29556) +g31133 = NOR(g7953, g29556) +g31134 = NOR(g8033, g29679, g24732) +g31233 = NOR(g8522, g29778, g24825) +g31294 = NOR(g11326, g29660) +g31318 = NOR(g4785, g29697) +g31372 = NOR(g8796, g29697) +g31373 = NOR(g4975, g29725) +g31469 = NOR(g8822, g29725) +g31476 = NOR(g4709, g29697) +g31482 = NOR(g8883, g29697) +g31483 = NOR(g4899, g29725) +g31491 = NOR(g8938, g29725) +g31498 = NOR(g9030, g29540) +g31506 = NOR(g4793, g29540) +g31507 = NOR(g9064, g29556) +g31515 = NOR(g4983, g29556) +g31935 = NOR(g30583, g4349) +g31942 = NOR(g8977, g30583) +g31965 = NOR(g30583, g4358) +g31970 = NOR(g9024, g30583) +g32017 = NOR(g31504, g23475) +g32212 = NOR(g8859, g31262, g11083) +g32296 = NOR(g9044, g31509, g12259) +g32424 = NOR(g8721, g31294) +g32455 = NOR(g31566, I29985, I29986) +g32520 = NOR(g31554, I30054, I30055) +g32585 = NOR(g31542, I30123, I30124) +g32650 = NOR(g31579, I30192, I30193) +g32715 = NOR(g31327, I30261, I30262) +g32780 = NOR(g31327, I30330, I30331) +g32845 = NOR(g30673, I30399, I30400) +g32910 = NOR(g31327, I30468, I30469) +g33075 = NOR(g31997, g7163) +g33084 = NOR(g31978, g7655) +g33085 = NOR(g31978, g4311) +g33088 = NOR(g31997, g7224) +g33089 = NOR(g31978, g4322) +g33090 = NOR(g31997, g4593) +g33092 = NOR(g31978, g4332) +g33093 = NOR(g31997, g4601) +g33094 = NOR(g31950, g4639) +g33095 = NOR(g31997, g7236) +g33096 = NOR(g31997, g4608) +g33097 = NOR(g31950, g4628) +g33098 = NOR(g31997, g4616) +g33100 = NOR(g32172, g31188) +g33103 = NOR(g32176, g31212) +g33107 = NOR(g32180, g31223) +g33108 = NOR(g32183, g31228) +g33109 = NOR(g31997, g4584) +g33112 = NOR(g31240, g32194) +g33117 = NOR(g31261, g32205) +g33125 = NOR(g8606, g32057) +g33128 = NOR(g4653, g32057) +g33129 = NOR(g8630, g32072) +g33130 = NOR(g32265, g31497) +g33131 = NOR(g4659, g32057) +g33132 = NOR(g4843, g32072) +g33133 = NOR(g32278, g31503) +g33134 = NOR(g7686, g32057) +g33135 = NOR(g32090, g8350) +g33137 = NOR(g4849, g32072) +g33138 = NOR(g32287, g31514) +g33139 = NOR(g8650, g32057) +g33140 = NOR(g7693, g32072) +g33141 = NOR(g32099, g8400) +g33143 = NOR(g32293, g31518) +g33144 = NOR(g4664, g32057) +g33145 = NOR(g8677, g32072) +g33146 = NOR(g4669, g32057) +g33147 = NOR(g32090, g7788) +g33148 = NOR(g4854, g32072) +g33160 = NOR(g8672, g32057) +g33161 = NOR(g32090, g7806) +g33162 = NOR(g4859, g32072) +g33163 = NOR(g32099, g7809) +g33174 = NOR(g8714, g32072) +g33175 = NOR(g32099, g7828) +g33419 = NOR(g31978, g7627) +g33427 = NOR(g10278, g31950) +g33432 = NOR(g31997, g6978) +g33437 = NOR(g31997, g10275) +g33438 = NOR(g31950, g4621) +g33439 = NOR(g31950, g4633) +g33447 = NOR(g31978, g7643) +g33448 = NOR(g7785, g31950) +g33449 = NOR(g10311, g31950) +g33823 = NOR(g8774, g33306, g11083) +g33851 = NOR(g8854, g33299, g12259) +g34067 = NOR(g33859, g11772) +g34354 = NOR(g9003, g34162, g11083) +g34359 = NOR(g9162, g34174, g12259) +g34496 = NOR(g34370, g27648) +g34703 = NOR(g8899, g34545, g11083) +g34737 = NOR(g34706, g30003) +g34912 = NOR(g34883, g20277, g20242, g21370) diff --git a/abc70930/examples/s444.blif b/abc70930/examples/s444.blif new file mode 100644 index 00000000..e89e8aa1 --- /dev/null +++ b/abc70930/examples/s444.blif @@ -0,0 +1,353 @@ +.model s444 +.inputs G0 G1 G2 +.outputs G118 G167 G107 G119 G168 G108 + +.latch G11_in G11 0 +.latch G12_in G12 0 +.latch G13_in G13 0 +.latch G14_in G14 0 +.latch G15_in G15 0 +.latch G16_in G16 0 +.latch G17_in G17 0 +.latch G18_in G18 0 +.latch G19_in G19 0 +.latch G20_in G20 0 +.latch G21_in G21 0 +.latch G22_in G22 0 +.latch G23_in G23 0 +.latch G24_in G24 0 +.latch G25_in G25 0 +.latch G26_in G26 0 +.latch G27_in G27 0 +.latch G28_in G28 0 +.latch G29_in G29 0 +.latch G30_in G30 0 +.latch G31_in G31 0 + +.names G12 G13 [25] +00 1 +.names G11 [25] [26] +01 1 +.names G14 [26] [27] +10 1 +.names G0 G11 [28] +00 1 +.names [27] [28] G11_in +01 1 +.names G11 G12 [30] +11 1 +.names G12 [30] [31] +10 1 +.names G11 [30] [32] +10 1 +.names [31] [32] [33] +00 1 +.names G0 [33] [34] +00 1 +.names [27] [34] G12_in +01 1 +.names G13 [30] [36] +11 1 +.names G13 [36] [37] +10 1 +.names [30] [36] [38] +10 1 +.names [37] [38] [39] +00 1 +.names G0 [39] [40] +00 1 +.names [27] [40] G13_in +01 1 +.names G12 G13 [42] +11 1 +.names G11 [42] [43] +11 1 +.names G14 [43] [44] +11 1 +.names G14 [44] [45] +10 1 +.names [43] [44] [46] +10 1 +.names [45] [46] [47] +00 1 +.names G0 [47] [48] +00 1 +.names [27] [48] G14_in +01 1 +.names G31 [27] [50] +00 1 +.names G16 G17 [51] +00 1 +.names G15 [51] [52] +01 1 +.names [50] [52] [53] +00 1 +.names G18 [53] [54] +11 1 +.names G15 [50] [55] +10 1 +.names G15 [55] [56] +10 1 +.names [50] [55] [57] +00 1 +.names [56] [57] [58] +00 1 +.names G0 [58] [59] +00 1 +.names [54] [59] G15_in +01 1 +.names G16 [55] [61] +11 1 +.names G16 [61] [62] +10 1 +.names [55] [61] [63] +10 1 +.names [62] [63] [64] +00 1 +.names G0 [64] [65] +00 1 +.names [54] [65] G16_in +01 1 +.names G16 [50] [67] +10 1 +.names G15 [67] [68] +11 1 +.names G17 [68] [69] +11 1 +.names G17 [69] [70] +10 1 +.names [68] [69] [71] +10 1 +.names [70] [71] [72] +00 1 +.names G0 [72] [73] +00 1 +.names [54] [73] G17_in +01 1 +.names G15 G16 [75] +11 1 +.names G17 [50] [76] +10 1 +.names [75] [76] [77] +11 1 +.names G18 [77] [78] +11 1 +.names G18 [78] [79] +10 1 +.names [77] [78] [80] +10 1 +.names [79] [80] [81] +00 1 +.names G0 [81] [82] +00 1 +.names [54] [82] G18_in +01 1 +.names G20 G21 [84] +00 1 +.names G19 [84] [85] +01 1 +.names [54] [85] [86] +10 1 +.names G22 [86] [87] +11 1 +.names G19 [54] [88] +11 1 +.names G19 [88] [89] +10 1 +.names [54] [88] [90] +10 1 +.names [89] [90] [91] +00 1 +.names G0 [91] [92] +00 1 +.names [87] [92] G19_in +01 1 +.names G20 [88] [94] +11 1 +.names G20 [94] [95] +10 1 +.names [88] [94] [96] +10 1 +.names [95] [96] [97] +00 1 +.names G0 [97] [98] +00 1 +.names [87] [98] G20_in +01 1 +.names G20 [54] [100] +11 1 +.names G19 [100] [101] +11 1 +.names G21 [101] [102] +11 1 +.names G21 [102] [103] +10 1 +.names [101] [102] [104] +10 1 +.names [103] [104] [105] +00 1 +.names G0 [105] [106] +00 1 +.names [87] [106] G21_in +01 1 +.names G19 G20 [108] +11 1 +.names G21 [54] [109] +11 1 +.names [108] [109] [110] +11 1 +.names G22 [110] [111] +11 1 +.names G22 [111] [112] +10 1 +.names [110] [111] [113] +10 1 +.names [112] [113] [114] +00 1 +.names G0 [114] [115] +00 1 +.names [87] [115] G22_in +01 1 +.names G2 G23 [117] +00 1 +.names G2 G23 [118] +11 1 +.names [117] [118] [119] +00 1 +.names G0 [119] G23_in +01 1 +.names G20 G21 [121] +01 1 +.names G0 G23 [122] +01 1 +.names [121] [122] [123] +11 1 +.names G19 [123] [124] +01 1 +.names G21 G22 [126] +10 1 +.names G19 G20 [125] +10 1 +.names G23 [125] [127] +01 1 +.names [126] [127] [128] +11 1 +.names G0 G24 [129] +01 1 +.names [128] [129] [130] +01 1 +.names [124] [130] [131] +00 1 +.names G22 G23 [132] +00 1 +.names [125] [132] [133] +11 1 +.names G24 [133] [134] +10 1 +.names G19 G20 [135] +00 1 +.names G23 [135] [136] +11 1 +.names G22 G23 [137] +11 1 +.names [136] [137] [138] +00 1 +.names G0 G21 [139] +01 1 +.names [138] [139] [140] +11 1 +.names [134] [140] G25_in +01 1 +.names G19 G22 [142] +01 1 +.names G0 [142] [143] +01 1 +.names G0 [108] [144] +01 1 +.names [143] [144] [145] +00 1 +.names [129] [139] [146] +00 1 +.names [145] [146] G26_in +11 1 +.names G21 G24 [148] +00 1 +.names [125] [148] [149] +11 1 +.names G21 G22 [150] +00 1 +.names G24 [150] [151] +01 1 +.names G0 [151] [152] +00 1 +.names [149] [152] [153] +01 1 +.names G0 G22 [154] +01 1 +.names [135] [154] [155] +11 1 +.names [146] [155] [156] +10 1 +.names [131] [156] [157] +00 1 +.names G17 [157] [158] +01 1 +.names [131] [156] [159] +10 1 +.names [158] [159] G28_in +00 1 +.names [122] [126] [161] +11 1 +.names G21 G22 [162] +01 1 +.names G0 [162] [163] +01 1 +.names [161] [163] [164] +00 1 +.names G20 [164] [165] +00 1 +.names G19 [165] [166] +01 1 +.names [130] [166] [167] +00 1 +.names [131] [167] [168] +00 1 +.names G17 [168] [169] +01 1 +.names [131] [167] [170] +10 1 +.names [169] [170] G29_in +00 1 +.names G20 G21 [172] +10 1 +.names G0 G24 [173] +00 1 +.names [172] [173] [174] +11 1 +.names G19 [174] G30_in +11 1 +.names G1 G31 [176] +00 1 +.names G1 G31 [177] +11 1 +.names [176] [177] [178] +00 1 +.names G0 [178] G31_in +01 1 +.names [131] G24_in +0 1 +.names [153] G27_in +0 1 +.names G27 G118 +1 1 +.names G29 G167 +0 1 +.names G25 G107 +1 1 +.names G28 G119 +0 1 +.names G30 G168 +1 1 +.names G26 G108 +1 1 +.end diff --git a/abc70930/examples/s5378.blif b/abc70930/examples/s5378.blif new file mode 100644 index 00000000..c6f442a3 --- /dev/null +++ b/abc70930/examples/s5378.blif @@ -0,0 +1,6138 @@ +.model s5378 +.inputs n3065gat n3066gat n3067gat n3068gat n3069gat n3070gat n3071gat \ +n3072gat n3073gat n3074gat n3075gat n3076gat n3077gat n3078gat n3079gat \ +n3080gat n3081gat n3082gat n3083gat n3084gat n3085gat n3086gat n3087gat \ +n3088gat n3089gat n3090gat n3091gat n3092gat n3093gat n3094gat n3095gat \ +n3097gat n3098gat n3099gat n3100gat +.outputs n3104gat n3105gat n3106gat n3107gat n3108gat n3109gat n3110gat \ +n3111gat n3112gat n3113gat n3114gat n3115gat n3116gat n3117gat n3118gat \ +n3119gat n3120gat n3121gat n3122gat n3123gat n3124gat n3125gat n3126gat \ +n3127gat n3128gat n3129gat n3130gat n3131gat n3132gat n3133gat n3134gat \ +n3135gat n3136gat n3137gat n3138gat n3139gat n3140gat n3141gat n3142gat \ +n3143gat n3144gat n3145gat n3146gat n3147gat n3148gat n3149gat n3150gat \ +n3151gat n3152gat +.latch n2897gat n673gat 1 +.latch n2782gat n398gat 1 +.latch n2790gat n402gat 1 +.latch n2670gat n919gat 1 +.latch n2793gat n846gat 1 +.latch n748gat n2510gat 1 +.latch n2732gat n271gat 1 +.latch n2776gat n160gat 1 +.latch n2735gat n337gat 1 +.latch n2673gat n842gat 1 +.latch n2779gat n341gat 1 +.latch n43gat n2522gat 1 +.latch n1620gat n2472gat 1 +.latch n2470gat n2319gat 1 +.latch n1827gat n1821gat 1 +.latch n1816gat n2029gat 1 +.latch n2027gat n1829gat 1 +.latch n55gat n2476gat 1 +.latch n2914gat n1068gat 1 +.latch n2928gat n957gat 1 +.latch n2927gat n861gat 1 +.latch n2896gat n1294gat 1 +.latch n2922gat n1241gat 1 +.latch n2894gat n865gat 1 +.latch n2921gat n1080gat 1 +.latch n2895gat n1148gat 1 +.latch n933gat n2468gat 1 +.latch n3064gat n834gat 1 +.latch n3055gat n707gat 1 +.latch n3063gat n838gat 1 +.latch n3062gat n830gat 1 +.latch n3056gat n614gat 1 +.latch n504gat n2526gat 1 +.latch n2913gat n680gat 1 +.latch n2920gat n816gat 1 +.latch n2905gat n580gat 1 +.latch n3057gat n824gat 1 +.latch n3059gat n820gat 1 +.latch n3058gat n883gat 1 +.latch n2898gat n584gat 1 +.latch n3060gat n684gat 1 +.latch n3061gat n699gat 1 +.latch n567gat n2464gat 1 +.latch n3048gat n2399gat 1 +.latch n3049gat n2343gat 1 +.latch n3051gat n2203gat 1 +.latch n3047gat n2562gat 1 +.latch n3050gat n2207gat 1 +.latch n3040gat n2626gat 1 +.latch n3044gat n2490gat 1 +.latch n3042gat n2622gat 1 +.latch n3037gat n2630gat 1 +.latch n3041gat n2543gat 1 +.latch n1606gat n2102gat 1 +.latch n3052gat n1880gat 1 +.latch n1610gat n1763gat 1 +.latch n1858gat n2155gat 1 +.latch n2918gat n1035gat 1 +.latch n2952gat n1121gat 1 +.latch n2919gat n1072gat 1 +.latch n2910gat n1282gat 1 +.latch n2907gat n1226gat 1 +.latch n2911gat n931gat 1 +.latch n2912gat n1135gat 1 +.latch n2909gat n1045gat 1 +.latch n2908gat n1197gat 1 +.latch n2971gat n2518gat 1 +.latch n2904gat n667gat 1 +.latch n2891gat n659gat 1 +.latch n2903gat n553gat 1 +.latch n2915gat n777gat 1 +.latch n2901gat n561gat 1 +.latch n2890gat n366gat 1 +.latch n2888gat n322gat 1 +.latch n2887gat n318gat 1 +.latch n2886gat n314gat 1 +.latch n3010gat n2599gat 1 +.latch n3016gat n2588gat 1 +.latch n3054gat n2640gat 1 +.latch n2579gat n2658gat 1 +.latch n3036gat n2495gat 1 +.latch n3034gat n2390gat 1 +.latch n3031gat n2270gat 1 +.latch n3035gat n2339gat 1 +.latch n2646gat n2502gat 1 +.latch n3053gat n2634gat 1 +.latch n2613gat n2506gat 1 +.latch n1625gat n1834gat 1 +.latch n1626gat n1767gat 1 +.latch n1603gat n2084gat 1 +.latch n2541gat n2143gat 1 +.latch n2557gat n2061gat 1 +.latch n2487gat n2139gat 1 +.latch n2532gat n1899gat 1 +.latch n2628gat n1850gat 1 +.latch n2397gat n2403gat 1 +.latch n2341gat n2394gat 1 +.latch n2560gat n2440gat 1 +.latch n2205gat n2407gat 1 +.latch n2201gat n2347gat 1 +.latch n1793gat n1389gat 1 +.latch n1781gat n2021gat 1 +.latch n1516gat n1394gat 1 +.latch n1392gat n1496gat 1 +.latch n1685gat n2091gat 1 +.latch n1565gat n1332gat 1 +.latch n1330gat n1740gat 1 +.latch n1945gat n2179gat 1 +.latch n2268gat n2190gat 1 +.latch n2337gat n2135gat 1 +.latch n2388gat n2262gat 1 +.latch n1836gat n2182gat 1 +.latch n2983gat n1433gat 1 +.latch n1431gat n1316gat 1 +.latch n1314gat n1363gat 1 +.latch n1361gat n1312gat 1 +.latch n1696gat n1775gat 1 +.latch n2009gat n1871gat 1 +.latch n1773gat n2592gat 1 +.latch n1636gat n1508gat 1 +.latch n1712gat n1678gat 1 +.latch n3000gat n2309gat 1 +.latch n2307gat n2450gat 1 +.latch n2661gat n2446gat 1 +.latch n827gat n2095gat 1 +.latch n2093gat n2176gat 1 +.latch n2174gat n2169gat 1 +.latch n2163gat n2454gat 1 +.latch n1777gat n2040gat 1 +.latch n2015gat n2044gat 1 +.latch n2042gat n2037gat 1 +.latch n2017gat n2025gat 1 +.latch n2023gat n2099gat 1 +.latch n2493gat n2266gat 1 +.latch n2035gat n2033gat 1 +.latch n2031gat n2110gat 1 +.latch n2108gat n2125gat 1 +.latch n2123gat n2121gat 1 +.latch n2119gat n2117gat 1 +.latch n2632gat n1975gat 1 +.latch n2638gat n2644gat 1 +.latch n612gat n156gat 1 +.latch n705gat n152gat 1 +.latch n822gat n331gat 1 +.latch n881gat n388gat 1 +.latch n818gat n463gat 1 +.latch n682gat n327gat 1 +.latch n697gat n384gat 1 +.latch n836gat n256gat 1 +.latch n828gat n470gat 1 +.latch n832gat n148gat 1 +.latch n2590gat n2458gat 1 +.latch n2456gat n2514gat 1 +.latch n1613gat n1771gat 1 +.latch n1391gat n1336gat 1 +.latch n1927gat n1748gat 1 +.latch n1713gat n1675gat 1 +.latch n1717gat n1807gat 1 +.latch n1567gat n1340gat 1 +.latch n1564gat n1456gat 1 +.latch n1632gat n1525gat 1 +.latch n1915gat n1462gat 1 +.latch n1800gat n1596gat 1 +.latch n1593gat n1588gat 1 +.names II4654 n3104gat +0 1 +.names II4657 n3105gat +0 1 +.names II4660 n3106gat +0 1 +.names II4663 n3107gat +0 1 +.names II4666 n3108gat +0 1 +.names II4669 n3109gat +0 1 +.names II4672 n3110gat +0 1 +.names II4675 n3111gat +0 1 +.names II4678 n3112gat +0 1 +.names II4681 n3113gat +0 1 +.names II4684 n3114gat +0 1 +.names II4687 n3115gat +0 1 +.names II4690 n3116gat +0 1 +.names II4693 n3117gat +0 1 +.names II4696 n3118gat +0 1 +.names II4699 n3119gat +0 1 +.names II4702 n3120gat +0 1 +.names II4705 n3121gat +0 1 +.names II4708 n3122gat +0 1 +.names II4711 n3123gat +0 1 +.names II4714 n3124gat +0 1 +.names II4717 n3125gat +0 1 +.names II4720 n3126gat +0 1 +.names II4723 n3127gat +0 1 +.names II4726 n3128gat +0 1 +.names II4729 n3129gat +0 1 +.names II4732 n3130gat +0 1 +.names II4735 n3131gat +0 1 +.names II4738 n3132gat +0 1 +.names II4741 n3133gat +0 1 +.names II4744 n3134gat +0 1 +.names II4747 n3135gat +0 1 +.names II4750 n3136gat +0 1 +.names II4753 n3137gat +0 1 +.names II4756 n3138gat +0 1 +.names II4759 n3139gat +0 1 +.names II4762 n3140gat +0 1 +.names II4765 n3141gat +0 1 +.names II4768 n3142gat +0 1 +.names II4771 n3143gat +0 1 +.names II4774 n3144gat +0 1 +.names II4777 n3145gat +0 1 +.names II4780 n3146gat +0 1 +.names II4783 n3147gat +0 1 +.names II4786 n3148gat +0 1 +.names II4789 n3149gat +0 1 +.names II4792 n3150gat +0 1 +.names II4795 n3151gat +0 1 +.names II4798 n3152gat +0 1 +.names n648gat n442gat n2897gat +1- 1 +-1 1 +.names II50 n2782gat +0 1 +.names II65 n2790gat +0 1 +.names II81 n2670gat +0 1 +.names II100 n2793gat +0 1 +.names n749gat n750gat n751gat n752gat n748gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names II300 n2732gat +0 1 +.names II320 n2776gat +0 1 +.names II340 n2735gat +0 1 +.names II384 n2673gat +0 1 +.names II426 n2779gat +0 1 +.names n44gat n45gat n46gat n47gat n43gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1448gat n1446gat n1620gat +00 1 +.names n2472gat n2470gat +0 1 +.names n2729gat n2317gat n1827gat +00 1 +.names n1817gat n1816gat +0 1 +.names n2029gat n2027gat +0 1 +.names n56gat n57gat n58gat n59gat n55gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n768gat n655gat n2914gat +1- 1 +-1 1 +.names n963gat n868gat n2928gat +1- 1 +-1 1 +.names n962gat n959gat n2927gat +1- 1 +-1 1 +.names n647gat n441gat n2896gat +1- 1 +-1 1 +.names n967gat n792gat n2922gat +1- 1 +-1 1 +.names n443gat n439gat n2894gat +1- 1 +-1 1 +.names n966gat n790gat n2921gat +1- 1 +-1 1 +.names n444gat n440gat n2895gat +1- 1 +-1 1 +.names n934gat n935gat n936gat n937gat n933gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names II3914 n3064gat +0 1 +.names II3703 n3055gat +0 1 +.names II3891 n3063gat +0 1 +.names II3876 n3062gat +0 1 +.names II3713 n3056gat +0 1 +.names n505gat n506gat n507gat n508gat n504gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n767gat n653gat n2913gat +1- 1 +-1 1 +.names n867gat n771gat n2920gat +1- 1 +-1 1 +.names n964gat n961gat n2905gat +1- 1 +-1 1 +.names II3754 n3057gat +0 1 +.names II3801 n3059gat +0 1 +.names II3765 n3058gat +0 1 +.names n447gat n445gat n2898gat +1- 1 +-1 1 +.names II3817 n3060gat +0 1 +.names II3841 n3061gat +0 1 +.names n568gat n569gat n570gat n571gat n567gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names II3530 n3048gat +0 1 +.names II3539 n3049gat +0 1 +.names II3558 n3051gat +0 1 +.names II3520 n3047gat +0 1 +.names II3549 n3050gat +0 1 +.names II3472 n3040gat +0 1 +.names II3504 n3044gat +0 1 +.names II3491 n3042gat +0 1 +.names II3457 n3037gat +0 1 +.names II3483 n3041gat +0 1 +.names n3020gat n270gat n1606gat +00 1 +.names II3610 n3052gat +0 1 +.names n1698gat n1543gat n1610gat +00 1 +.names n1673gat n1858gat +0 1 +.names n769gat n759gat n2918gat +1- 1 +-1 1 +.names n1076gat n1075gat n2952gat +1- 1 +-1 1 +.names n766gat n760gat n2919gat +1- 1 +-1 1 +.names n645gat n644gat n2910gat +1- 1 +-1 1 +.names n646gat n641gat n2907gat +1- 1 +-1 1 +.names n761gat n651gat n2911gat +1- 1 +-1 1 +.names n762gat n652gat n2912gat +1- 1 +-1 1 +.names n765gat n643gat n2909gat +1- 1 +-1 1 +.names n763gat n642gat n2908gat +1- 1 +-1 1 +.names n1287gat n1285gat n2971gat +1- 1 +-1 1 +.names n793gat n664gat n556gat n2904gat +1-- 1 +-1- 1 +--1 1 +.names n795gat n656gat n368gat n2891gat +1-- 1 +-1- 1 +--1 1 +.names n794gat n773gat n662gat n2903gat +1-- 1 +-1- 1 +--1 1 +.names n965gat n960gat n661gat n2915gat +1-- 1 +-1- 1 +--1 1 +.names n558gat n555gat n450gat n2901gat +1-- 1 +-1- 1 +--1 1 +.names n654gat n557gat n371gat n2890gat +1-- 1 +-1- 1 +--1 1 +.names n663gat n649gat n449gat n2888gat +1-- 1 +-1- 1 +--1 1 +.names n791gat n650gat n370gat n2887gat +1-- 1 +-1- 1 +--1 1 +.names n774gat n764gat n369gat n2886gat +1-- 1 +-1- 1 +--1 1 +.names n2460gat n2423gat n3010gat +1- 1 +-1 1 +.names n2596gat n2595gat n3016gat +1- 1 +-1 1 +.names II3660 n3054gat +0 1 +.names n2580gat n2581gat n2579gat +1- 1 +-1 1 +.names II3436 n3036gat +0 1 +.names II3401 n3034gat +0 1 +.names II3387 n3031gat +0 1 +.names II3412 n3035gat +0 1 +.names n2647gat n2648gat n2646gat +1- 1 +-1 1 +.names II3635 n3053gat +0 1 +.names n2614gat n2615gat n2613gat +1- 1 +-1 1 +.names n3021gat n1628gat n1625gat +00 1 +.names n1627gat n3022gat n1626gat +00 1 +.names n1831gat n1603gat +0 1 +.names n2543gat n2541gat +0 1 +.names n2621gat n2557gat +0 1 +.names n2489gat n2487gat +0 1 +.names n2625gat n2532gat +0 1 +.names n2630gat n2628gat +0 1 +.names n2399gat n2397gat +0 1 +.names n2343gat n2341gat +0 1 +.names n2562gat n2560gat +0 1 +.names n2207gat n2205gat +0 1 +.names n2203gat n2201gat +0 1 +.names n1792gat n1735gat n1793gat +00 1 +.names n1780gat n1781gat +0 1 +.names n1551gat n1517gat n1516gat +00 1 +.names n1394gat n1392gat +0 1 +.names n1604gat n1685gat +0 1 +.names n1735gat n1552gat n1565gat +00 1 +.names n1332gat n1330gat +0 1 +.names n1690gat n1945gat +0 1 +.names n2270gat n2268gat +0 1 +.names n2339gat n2337gat +0 1 +.names n2390gat n2388gat +0 1 +.names n1695gat n1836gat +0 1 +.names n2079gat n2073gat n2983gat +1- 1 +-1 1 +.names n1433gat n1431gat +0 1 +.names n1316gat n1314gat +0 1 +.names n1363gat n1361gat +0 1 +.names n1707gat n1698gat n1696gat +00 1 +.names n2016gat n2664gat n2004gat n2009gat +000 1 +.names n1775gat n1773gat +0 1 +.names n1584gat n1718gat n1636gat +00 1 +.names II3179 n1712gat +0 1 +.names n2000gat n1999gat n3000gat +1- 1 +-1 1 +.names n2309gat n2307gat +0 1 +.names n2662gat n2661gat +0 1 +.names n204gat n827gat +0 1 +.names n2095gat n2093gat +0 1 +.names n2176gat n2174gat +0 1 +.names n1790gat n1310gat n2664gat n2168gat n2163gat +0000 1 +.names n1694gat n1777gat +0 1 +.names n2039gat n1774gat n1315gat n2015gat +000 1 +.names n2044gat n2042gat +0 1 +.names n1790gat n2016gat n2017gat +00 1 +.names n2025gat n2023gat +0 1 +.names n2495gat n2493gat +0 1 +.names n2037gat n2035gat +0 1 +.names n2033gat n2031gat +0 1 +.names n2110gat n2108gat +0 1 +.names n2125gat n2123gat +0 1 +.names n2121gat n2119gat +0 1 +.names n2634gat n2632gat +0 1 +.names n2640gat n2638gat +0 1 +.names n614gat n612gat +0 1 +.names n707gat n705gat +0 1 +.names n824gat n822gat +0 1 +.names n883gat n881gat +0 1 +.names n820gat n818gat +0 1 +.names n684gat n682gat +0 1 +.names n699gat n697gat +0 1 +.names n838gat n836gat +0 1 +.names n830gat n828gat +0 1 +.names n834gat n832gat +0 1 +.names n2592gat n2590gat +0 1 +.names n2458gat n2456gat +0 1 +.names n1544gat n1698gat n1613gat +00 1 +.names n1513gat n2442gat n1391gat +00 1 +.names n1790gat n1635gat n1927gat +00 1 +.names II2935 n1713gat +0 1 +.names II2926 n1717gat +0 1 +.names n1634gat n1735gat n1567gat +00 1 +.names n1584gat n1719gat n1790gat n1576gat n1564gat +0000 1 +.names II4145 n1632gat +0 1 +.names n1859gat n1919gat n1915gat +00 1 +.names n1635gat n1919gat n1800gat +00 1 +.names n1551gat n1310gat n1593gat +00 1 +.names n3088gat II1 +0 1 +.names II1 n2717gat +0 1 +.names n2717gat n2715gat +0 1 +.names n3087gat II5 +0 1 +.names II5 n2725gat +0 1 +.names n2725gat n2723gat +0 1 +.names n2715gat n2723gat n421gat +00 1 +.names n421gat n296gat +0 1 +.names n3093gat II11 +0 1 +.names II11 n2768gat +0 1 +.names n2768gat II14 +0 1 +.names II14 n2767gat +0 1 +.names n2767gat n373gat +0 1 +.names n3072gat II18 +0 1 +.names II18 n2671gat +0 1 +.names n2671gat n2669gat +0 1 +.names n3081gat II23 +0 1 +.names II23 n2845gat +0 1 +.names n2845gat n2844gat +0 1 +.names n3095gat II27 +0 1 +.names II27 n2668gat +0 1 +.names n2668gat II30 +0 1 +.names II30 n2667gat +0 1 +.names n2667gat n856gat +0 1 +.names n673gat II44 +0 1 +.names II44 n672gat +0 1 +.names n3069gat II47 +0 1 +.names II47 n2783gat +0 1 +.names n2783gat II50 +0 1 +.names n398gat n396gat +0 1 +.names n3070gat II62 +0 1 +.names II62 n2791gat +0 1 +.names n2791gat II65 +0 1 +.names n402gat II76 +0 1 +.names II76 n401gat +0 1 +.names n396gat n401gat n1499gat +00 1 +.names n1499gat n1645gat +0 1 +.names n2671gat II81 +0 1 +.names n919gat II92 +0 1 +.names II92 n918gat +0 1 +.names n918gat n396gat n1616gat +00 1 +.names n1616gat n1553gat +0 1 +.names n3071gat II97 +0 1 +.names II97 n2794gat +0 1 +.names n2794gat II100 +0 1 +.names n846gat II111 +0 1 +.names II111 n845gat +0 1 +.names n396gat n845gat n1614gat +00 1 +.names n1614gat n1559gat +0 1 +.names n1645gat n1553gat n1559gat n1641gat +000 1 +.names n1641gat n1643gat +0 1 +.names n1559gat n1616gat n1645gat n1642gat +000 1 +.names n1642gat n1651gat +0 1 +.names n1614gat n1645gat n1616gat n1556gat +000 1 +.names n1556gat n1562gat +0 1 +.names n1553gat n1645gat n1614gat n1557gat +000 1 +.names n1557gat n1560gat +0 1 +.names n1499gat n1559gat n1553gat n1639gat +000 1 +.names n1639gat n1640gat +0 1 +.names n1614gat n1616gat n1499gat n396gat n1605gat +0000 1 +.names n1605gat n1566gat +0 1 +.names n1616gat n1559gat n1499gat n1555gat +000 1 +.names n1555gat n1554gat +0 1 +.names n1614gat n1553gat n1499gat n1558gat +000 1 +.names n1558gat n1722gat +0 1 +.names n398gat n392gat +0 1 +.names n402gat II149 +0 1 +.names II149 n702gat +0 1 +.names n392gat n702gat n1256gat +00 1 +.names n1256gat n1319gat +0 1 +.names n919gat n720gat +0 1 +.names n846gat II171 +0 1 +.names II171 n725gat +0 1 +.names n720gat n725gat n1117gat +00 1 +.names n1117gat n1447gat +0 1 +.names n1319gat n1447gat n1618gat +00 1 +.names n1618gat n1627gat +0 1 +.names n919gat II178 +0 1 +.names II178 n721gat +0 1 +.names n725gat n721gat n1114gat +00 1 +.names n1114gat n1380gat +0 1 +.names n1319gat n1380gat n1621gat +00 1 +.names n1621gat n1628gat +0 1 +.names n402gat n701gat +0 1 +.names n392gat n701gat n1318gat +00 1 +.names n1318gat n1446gat +0 1 +.names n1447gat n1446gat n1619gat +00 1 +.names n1619gat n1705gat +0 1 +.names n1380gat n1446gat n1622gat +00 1 +.names n1622gat n1706gat +0 1 +.names n3083gat II192 +0 1 +.names II192 n2856gat +0 1 +.names n2856gat n2854gat +0 1 +.names n2854gat II196 +0 1 +.names II196 n1218gat +0 1 +.names n3085gat II199 +0 1 +.names II199 n2861gat +0 1 +.names n2861gat n2859gat +0 1 +.names n2859gat II203 +0 1 +.names II203 n1219gat +0 1 +.names n3084gat II206 +0 1 +.names II206 n2864gat +0 1 +.names n2864gat n2862gat +0 1 +.names n2862gat II210 +0 1 +.names II210 n1220gat +0 1 +.names n2861gat II214 +0 1 +.names II214 n2860gat +0 1 +.names n2860gat II217 +0 1 +.names II217 n1221gat +0 1 +.names n2864gat II220 +0 1 +.names II220 n2863gat +0 1 +.names n2863gat II223 +0 1 +.names II223 n1222gat +0 1 +.names n2856gat II227 +0 1 +.names II227 n2855gat +0 1 +.names n2855gat II230 +0 1 +.names II230 n1223gat +0 1 +.names n1214gat n1215gat n1216gat n1217gat n1213gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1213gat n640gat +0 1 +.names n640gat II237 +0 1 +.names II237 n753gat +0 1 +.names n2717gat II240 +0 1 +.names II240 n2716gat +0 1 +.names n3089gat II243 +0 1 +.names II243 n2869gat +0 1 +.names n2869gat n2867gat +0 1 +.names n2869gat II248 +0 1 +.names II248 n2868gat +0 1 +.names n745gat n638gat n2906gat +1- 1 +-1 1 +.names n2906gat II253 +0 1 +.names II253 n754gat +0 1 +.names n2725gat II256 +0 1 +.names II256 n2724gat +0 1 +.names n3086gat II259 +0 1 +.names II259 n2728gat +0 1 +.names n2728gat n2726gat +0 1 +.names n2728gat II264 +0 1 +.names II264 n2727gat +0 1 +.names n423gat n362gat n2889gat +1- 1 +-1 1 +.names n2889gat n422gat +0 1 +.names n422gat II270 +0 1 +.names II270 n755gat +0 1 +.names n2906gat n747gat +0 1 +.names n747gat II275 +0 1 +.names II275 n756gat +0 1 +.names n2889gat II278 +0 1 +.names II278 n757gat +0 1 +.names n1213gat II282 +0 1 +.names II282 n758gat +0 1 +.names n2510gat n2508gat +0 1 +.names n3065gat II297 +0 1 +.names II297 n2733gat +0 1 +.names n2733gat II300 +0 1 +.names n271gat II311 +0 1 +.names II311 n270gat +0 1 +.names n270gat II314 +0 1 +.names II314 n263gat +0 1 +.names n3067gat II317 +0 1 +.names II317 n2777gat +0 1 +.names n2777gat II320 +0 1 +.names n160gat II331 +0 1 +.names II331 n159gat +0 1 +.names n159gat II334 +0 1 +.names II334 n264gat +0 1 +.names n3066gat II337 +0 1 +.names II337 n2736gat +0 1 +.names n2736gat II340 +0 1 +.names n337gat II351 +0 1 +.names II351 n336gat +0 1 +.names n336gat II354 +0 1 +.names II354 n265gat +0 1 +.names n160gat n158gat +0 1 +.names n158gat II359 +0 1 +.names II359 n266gat +0 1 +.names n337gat n335gat +0 1 +.names n335gat II363 +0 1 +.names II363 n267gat +0 1 +.names n271gat n269gat +0 1 +.names n269gat II368 +0 1 +.names II368 n268gat +0 1 +.names n259gat n260gat n261gat n262gat n258gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n258gat n41gat +0 1 +.names n41gat II375 +0 1 +.names II375 n48gat +0 1 +.names n725gat II378 +0 1 +.names II378 n1018gat +0 1 +.names n3073gat II381 +0 1 +.names II381 n2674gat +0 1 +.names n2674gat II384 +0 1 +.names n842gat II395 +0 1 +.names II395 n841gat +0 1 +.names n841gat II398 +0 1 +.names II398 n1019gat +0 1 +.names n721gat II401 +0 1 +.names II401 n1020gat +0 1 +.names n842gat n840gat +0 1 +.names n840gat II406 +0 1 +.names II406 n1021gat +0 1 +.names n720gat II409 +0 1 +.names II409 n1022gat +0 1 +.names n846gat n724gat +0 1 +.names n724gat II414 +0 1 +.names II414 n1023gat +0 1 +.names n1014gat n1015gat n1016gat n1017gat n1013gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1013gat II420 +0 1 +.names II420 n49gat +0 1 +.names n3068gat II423 +0 1 +.names II423 n2780gat +0 1 +.names n2780gat II426 +0 1 +.names n341gat II437 +0 1 +.names II437 n340gat +0 1 +.names n340gat II440 +0 1 +.names II440 n480gat +0 1 +.names n702gat II443 +0 1 +.names II443 n481gat +0 1 +.names n398gat II446 +0 1 +.names II446 n393gat +0 1 +.names n393gat II449 +0 1 +.names II449 n482gat +0 1 +.names n701gat II453 +0 1 +.names II453 n483gat +0 1 +.names n392gat II456 +0 1 +.names II456 n484gat +0 1 +.names n341gat n339gat +0 1 +.names n339gat II461 +0 1 +.names II461 n485gat +0 1 +.names n476gat n477gat n478gat n479gat n475gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n475gat n42gat +0 1 +.names n42gat II468 +0 1 +.names II468 n50gat +0 1 +.names n1013gat n162gat +0 1 +.names n162gat II473 +0 1 +.names II473 n51gat +0 1 +.names n475gat II476 +0 1 +.names II476 n52gat +0 1 +.names n258gat II480 +0 1 +.names II480 n53gat +0 1 +.names n2522gat n2520gat +0 1 +.names n724gat n720gat n1376gat +00 1 +.names n1376gat n1448gat +0 1 +.names n1319gat n1448gat n1617gat +00 1 +.names n1617gat n1701gat +0 1 +.names n724gat n721gat n1377gat +00 1 +.names n1377gat n1379gat +0 1 +.names n1319gat n1379gat n1624gat +00 1 +.names n1624gat n1615gat +0 1 +.names n393gat n701gat n1113gat +00 1 +.names n1113gat n1500gat +0 1 +.names n1448gat n1500gat n1501gat +00 1 +.names n1501gat n1503gat +0 1 +.names n1379gat n1446gat n1623gat +00 1 +.names n1623gat n1779gat +0 1 +.names n3099gat II509 +0 1 +.names II509 n2730gat +0 1 +.names n2730gat II512 +0 1 +.names II512 n2729gat +0 1 +.names n2319gat n2317gat +0 1 +.names n1821gat n1819gat +0 1 +.names n1821gat n1823gat +0 1 +.names n1819gat n1823gat n1817gat +00 1 +.names n1829gat II572 +0 1 +.names II572 n1828gat +0 1 +.names n3100gat II576 +0 1 +.names II576 n2851gat +0 1 +.names n2851gat II579 +0 1 +.names II579 n2850gat +0 1 +.names n3091gat n3092gat n2786gat +1- 1 +-1 1 +.names n2786gat II583 +0 1 +.names II583 n2785gat +0 1 +.names n2785gat n92gat +0 1 +.names n2724gat n2715gat n529gat +00 1 +.names n529gat n637gat +0 1 +.names n2859gat n2726gat n361gat +00 1 +.names n361gat n293gat +0 1 +.names n3094gat II591 +0 1 +.names II591 n2722gat +0 1 +.names n2722gat II594 +0 1 +.names II594 n2721gat +0 1 +.names n2721gat n297gat +0 1 +.names n271gat II606 +0 1 +.names II606 n282gat +0 1 +.names n282gat II609 +0 1 +.names II609 n172gat +0 1 +.names n160gat II620 +0 1 +.names II620 n164gat +0 1 +.names n164gat II623 +0 1 +.names II623 n173gat +0 1 +.names n337gat II634 +0 1 +.names II634 n278gat +0 1 +.names n278gat II637 +0 1 +.names II637 n174gat +0 1 +.names n160gat n163gat +0 1 +.names n163gat II642 +0 1 +.names II642 n175gat +0 1 +.names n337gat n277gat +0 1 +.names n277gat II646 +0 1 +.names II646 n176gat +0 1 +.names n271gat n281gat +0 1 +.names n281gat II651 +0 1 +.names II651 n177gat +0 1 +.names n168gat n169gat n170gat n171gat n167gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n167gat n54gat +0 1 +.names n54gat II658 +0 1 +.names II658 n60gat +0 1 +.names n845gat II661 +0 1 +.names II661 n911gat +0 1 +.names n842gat II672 +0 1 +.names II672 n1025gat +0 1 +.names n1025gat II675 +0 1 +.names II675 n912gat +0 1 +.names n918gat II678 +0 1 +.names II678 n913gat +0 1 +.names n842gat n1024gat +0 1 +.names n1024gat II683 +0 1 +.names II683 n914gat +0 1 +.names n919gat n917gat +0 1 +.names n917gat II687 +0 1 +.names II687 n915gat +0 1 +.names n846gat n844gat +0 1 +.names n844gat II692 +0 1 +.names II692 n916gat +0 1 +.names n907gat n908gat n909gat n910gat n906gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n906gat II698 +0 1 +.names II698 n61gat +0 1 +.names n341gat II709 +0 1 +.names II709 n274gat +0 1 +.names n274gat II712 +0 1 +.names II712 n348gat +0 1 +.names n401gat II715 +0 1 +.names II715 n349gat +0 1 +.names n398gat II718 +0 1 +.names II718 n397gat +0 1 +.names n397gat II721 +0 1 +.names II721 n350gat +0 1 +.names n402gat n400gat +0 1 +.names n400gat II726 +0 1 +.names II726 n351gat +0 1 +.names n396gat II729 +0 1 +.names II729 n352gat +0 1 +.names n341gat n273gat +0 1 +.names n273gat II734 +0 1 +.names II734 n353gat +0 1 +.names n344gat n345gat n346gat n347gat n343gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n343gat n178gat +0 1 +.names n178gat II741 +0 1 +.names II741 n62gat +0 1 +.names n906gat n66gat +0 1 +.names n66gat II746 +0 1 +.names II746 n63gat +0 1 +.names n343gat II749 +0 1 +.names II749 n64gat +0 1 +.names n167gat II753 +0 1 +.names II753 n65gat +0 1 +.names n2476gat n2474gat +0 1 +.names n3090gat II768 +0 1 +.names II768 n2832gat +0 1 +.names n2832gat II771 +0 1 +.names II771 n2831gat +0 1 +.names n2733gat n2731gat +0 1 +.names n3074gat II776 +0 1 +.names II776 n2719gat +0 1 +.names n2719gat n2718gat +0 1 +.names n1068gat II790 +0 1 +.names II790 n1067gat +0 1 +.names n1067gat II793 +0 1 +.names II793 n949gat +0 1 +.names n3076gat II796 +0 1 +.names II796 n2839gat +0 1 +.names n2839gat n2838gat +0 1 +.names n2777gat n2775gat +0 1 +.names n957gat II812 +0 1 +.names II812 n956gat +0 1 +.names n956gat II815 +0 1 +.names II815 n950gat +0 1 +.names n3075gat II818 +0 1 +.names II818 n2712gat +0 1 +.names n2712gat n2711gat +0 1 +.names n2736gat n2734gat +0 1 +.names n861gat II834 +0 1 +.names II834 n860gat +0 1 +.names n860gat II837 +0 1 +.names II837 n951gat +0 1 +.names n957gat n955gat +0 1 +.names n955gat II842 +0 1 +.names II842 n952gat +0 1 +.names n861gat n859gat +0 1 +.names n859gat II846 +0 1 +.names II846 n953gat +0 1 +.names n1068gat n1066gat +0 1 +.names n1066gat II851 +0 1 +.names II851 n954gat +0 1 +.names n945gat n946gat n947gat n948gat n944gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n944gat n857gat +0 1 +.names n857gat II858 +0 1 +.names II858 n938gat +0 1 +.names n2794gat n2792gat +0 1 +.names n3080gat II863 +0 1 +.names II863 n2847gat +0 1 +.names n2847gat n2846gat +0 1 +.names n1294gat II877 +0 1 +.names II877 n1293gat +0 1 +.names n1293gat II880 +0 1 +.names II880 n1233gat +0 1 +.names n2674gat n2672gat +0 1 +.names n3082gat II885 +0 1 +.names II885 n2853gat +0 1 +.names n2853gat n2852gat +0 1 +.names n1241gat II899 +0 1 +.names II899 n1240gat +0 1 +.names n1240gat II902 +0 1 +.names II902 n1234gat +0 1 +.names n673gat II913 +0 1 +.names II913 n1297gat +0 1 +.names n1297gat II916 +0 1 +.names II916 n1235gat +0 1 +.names n1241gat n1239gat +0 1 +.names n1239gat II921 +0 1 +.names II921 n1236gat +0 1 +.names n673gat n1296gat +0 1 +.names n1296gat II925 +0 1 +.names II925 n1237gat +0 1 +.names n1294gat n1292gat +0 1 +.names n1292gat II930 +0 1 +.names II930 n1238gat +0 1 +.names n1229gat n1230gat n1231gat n1232gat n1228gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1228gat II936 +0 1 +.names II936 n939gat +0 1 +.names n2780gat n2778gat +0 1 +.names n3077gat II941 +0 1 +.names II941 n2837gat +0 1 +.names n2837gat n2836gat +0 1 +.names n865gat II955 +0 1 +.names II955 n864gat +0 1 +.names n864gat II958 +0 1 +.names II958 n1055gat +0 1 +.names n2791gat n2789gat +0 1 +.names n3079gat II963 +0 1 +.names II963 n2841gat +0 1 +.names n2841gat n2840gat +0 1 +.names n1080gat II977 +0 1 +.names II977 n1079gat +0 1 +.names n1079gat II980 +0 1 +.names II980 n1056gat +0 1 +.names n2783gat n2781gat +0 1 +.names n3078gat II985 +0 1 +.names II985 n2843gat +0 1 +.names n2843gat n2842gat +0 1 +.names n1148gat II999 +0 1 +.names II999 n1147gat +0 1 +.names n1147gat II1002 +0 1 +.names II1002 n1057gat +0 1 +.names n1080gat n1078gat +0 1 +.names n1078gat II1007 +0 1 +.names II1007 n1058gat +0 1 +.names n1148gat n1146gat +0 1 +.names n1146gat II1011 +0 1 +.names II1011 n1059gat +0 1 +.names n865gat n863gat +0 1 +.names n863gat II1016 +0 1 +.names II1016 n1060gat +0 1 +.names n1051gat n1052gat n1053gat n1054gat n1050gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1050gat n928gat +0 1 +.names n928gat II1023 +0 1 +.names II1023 n940gat +0 1 +.names n1228gat n858gat +0 1 +.names n858gat II1028 +0 1 +.names II1028 n941gat +0 1 +.names n1050gat II1031 +0 1 +.names II1031 n942gat +0 1 +.names n944gat II1035 +0 1 +.names II1035 n943gat +0 1 +.names n2468gat n2466gat +0 1 +.names n2722gat n2720gat +0 1 +.names n2667gat n740gat +0 1 +.names n2786gat n2784gat +0 1 +.names n2716gat n2723gat n746gat +00 1 +.names n746gat n743gat +0 1 +.names n2859gat n2727gat n360gat +00 1 +.names n360gat n294gat +0 1 +.names n2767gat n374gat +0 1 +.names n402gat n616gat +0 1 +.names n616gat II1067 +0 1 +.names II1067 n501gat +0 1 +.names n398gat n489gat +0 1 +.names n489gat II1079 +0 1 +.names II1079 n502gat +0 1 +.names n402gat II1082 +0 1 +.names II1082 n617gat +0 1 +.names n617gat II1085 +0 1 +.names II1085 n499gat +0 1 +.names n398gat II1088 +0 1 +.names II1088 n490gat +0 1 +.names n490gat II1091 +0 1 +.names II1091 n500gat +0 1 +.names n846gat n620gat +0 1 +.names n620gat II1103 +0 1 +.names II1103 n738gat +0 1 +.names n919gat n624gat +0 1 +.names n624gat II1115 +0 1 +.names II1115 n737gat +0 1 +.names n846gat II1118 +0 1 +.names II1118 n621gat +0 1 +.names n621gat II1121 +0 1 +.names II1121 n733gat +0 1 +.names n919gat II1124 +0 1 +.names II1124 n625gat +0 1 +.names n625gat II1127 +0 1 +.names II1127 n735gat +0 1 +.names n834gat II1138 +0 1 +.names II1138 n833gat +0 1 +.names n833gat II1141 +0 1 +.names II1141 n714gat +0 1 +.names n707gat II1152 +0 1 +.names II1152 n706gat +0 1 +.names n706gat II1155 +0 1 +.names II1155 n715gat +0 1 +.names n838gat II1166 +0 1 +.names II1166 n837gat +0 1 +.names n837gat II1169 +0 1 +.names II1169 n716gat +0 1 +.names n705gat II1174 +0 1 +.names II1174 n717gat +0 1 +.names n836gat II1178 +0 1 +.names II1178 n718gat +0 1 +.names n832gat II1183 +0 1 +.names II1183 n719gat +0 1 +.names n710gat n711gat n712gat n713gat n709gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n709gat n515gat +0 1 +.names n515gat II1190 +0 1 +.names II1190 n509gat +0 1 +.names n830gat II1201 +0 1 +.names II1201 n829gat +0 1 +.names n829gat II1204 +0 1 +.names II1204 n734gat +0 1 +.names n828gat II1209 +0 1 +.names II1209 n736gat +0 1 +.names n729gat n730gat n731gat n732gat n728gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n728gat II1216 +0 1 +.names II1216 n510gat +0 1 +.names n614gat II1227 +0 1 +.names II1227 n613gat +0 1 +.names n613gat II1230 +0 1 +.names II1230 n498gat +0 1 +.names n612gat II1236 +0 1 +.names II1236 n503gat +0 1 +.names n494gat n495gat n496gat n497gat n493gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n493gat n404gat +0 1 +.names n404gat II1243 +0 1 +.names II1243 n511gat +0 1 +.names n728gat n405gat +0 1 +.names n405gat II1248 +0 1 +.names II1248 n512gat +0 1 +.names n493gat II1251 +0 1 +.names II1251 n513gat +0 1 +.names n709gat II1255 +0 1 +.names II1255 n514gat +0 1 +.names n2526gat n2524gat +0 1 +.names n3029gat n2863gat n2855gat n374gat n564gat +0000 1 +.names n564gat n17gat +0 1 +.names n743gat n294gat n17gat n86gat +000 1 +.names n86gat n79gat +0 1 +.names n2784gat n79gat n78gat +00 1 +.names n78gat n219gat +0 1 +.names n740gat n3030gat II1277 II1278 +1-- 1 +-1- 1 +--1 1 +.names II1278 n563gat +0 1 +.names n563gat n289gat +0 1 +.names n289gat n2715gat n287gat +00 1 +.names n287gat n179gat +0 1 +.names n289gat n2726gat n288gat +00 1 +.names n288gat n188gat +0 1 +.names n286gat n179gat n188gat n181gat +000 1 +.names n181gat n72gat +0 1 +.names n72gat n2720gat n182gat +00 1 +.names n182gat n111gat +0 1 +.names n680gat II1302 +0 1 +.names II1302 n679gat +0 1 +.names n679gat II1305 +0 1 +.names II1305 n808gat +0 1 +.names n816gat II1319 +0 1 +.names II1319 n815gat +0 1 +.names n815gat II1322 +0 1 +.names II1322 n809gat +0 1 +.names n580gat II1336 +0 1 +.names II1336 n579gat +0 1 +.names n579gat II1339 +0 1 +.names II1339 n810gat +0 1 +.names n816gat n814gat +0 1 +.names n814gat II1344 +0 1 +.names II1344 n811gat +0 1 +.names n580gat n578gat +0 1 +.names n578gat II1348 +0 1 +.names II1348 n812gat +0 1 +.names n680gat n678gat +0 1 +.names n678gat II1353 +0 1 +.names II1353 n813gat +0 1 +.names n804gat n805gat n806gat n807gat n803gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n803gat n677gat +0 1 +.names n677gat II1360 +0 1 +.names II1360 n572gat +0 1 +.names n824gat II1371 +0 1 +.names II1371 n823gat +0 1 +.names n823gat II1374 +0 1 +.names II1374 n591gat +0 1 +.names n820gat II1385 +0 1 +.names II1385 n819gat +0 1 +.names n819gat II1388 +0 1 +.names II1388 n592gat +0 1 +.names n883gat II1399 +0 1 +.names II1399 n882gat +0 1 +.names n882gat II1402 +0 1 +.names II1402 n593gat +0 1 +.names n818gat II1407 +0 1 +.names II1407 n594gat +0 1 +.names n881gat II1411 +0 1 +.names II1411 n595gat +0 1 +.names n822gat II1416 +0 1 +.names II1416 n596gat +0 1 +.names n587gat n588gat n589gat n590gat n586gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n586gat II1422 +0 1 +.names II1422 n573gat +0 1 +.names n584gat II1436 +0 1 +.names II1436 n583gat +0 1 +.names n583gat II1439 +0 1 +.names II1439 n691gat +0 1 +.names n684gat II1450 +0 1 +.names II1450 n683gat +0 1 +.names n683gat II1453 +0 1 +.names II1453 n692gat +0 1 +.names n699gat II1464 +0 1 +.names II1464 n698gat +0 1 +.names n698gat II1467 +0 1 +.names II1467 n693gat +0 1 +.names n682gat II1472 +0 1 +.names II1472 n694gat +0 1 +.names n697gat II1476 +0 1 +.names II1476 n695gat +0 1 +.names n584gat n582gat +0 1 +.names n582gat II1481 +0 1 +.names II1481 n696gat +0 1 +.names n687gat n688gat n689gat n690gat n686gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n686gat n456gat +0 1 +.names n456gat II1488 +0 1 +.names II1488 n574gat +0 1 +.names n586gat n565gat +0 1 +.names n565gat II1493 +0 1 +.names II1493 n575gat +0 1 +.names n686gat II1496 +0 1 +.names II1496 n576gat +0 1 +.names n803gat II1500 +0 1 +.names II1500 n577gat +0 1 +.names n2464gat n2462gat +0 1 +.names n2466gat n2462gat II1515 II1516 +1-- 1 +-1- 1 +--1 1 +.names II1516 n2665gat +0 1 +.names n2665gat n2596gat +0 1 +.names n289gat n2723gat n286gat +00 1 +.names n286gat n189gat +0 1 +.names n189gat n287gat n188gat n187gat +000 1 +.names n187gat n194gat +0 1 +.names n637gat n17gat n293gat n15gat +000 1 +.names n15gat n21gat +0 1 +.names n2399gat II1538 +0 1 +.names II1538 n2398gat +0 1 +.names n2398gat n2353gat +0 1 +.names n2343gat II1550 +0 1 +.names II1550 n2342gat +0 1 +.names n2342gat n2284gat +0 1 +.names n2201gat n2354gat +0 1 +.names n2560gat n2356gat +0 1 +.names n2205gat n2214gat +0 1 +.names n2356gat n2214gat II1584 II1585 +1-- 1 +-1- 1 +--1 1 +.names II1585 n2286gat +0 1 +.names n2626gat n2624gat +0 1 +.names n2490gat II1606 +0 1 +.names II1606 n2489gat +0 1 +.names n2622gat II1617 +0 1 +.names II1617 n2621gat +0 1 +.names n2624gat n2489gat n2621gat n2534gat +000 1 +.names n2534gat n2533gat +0 1 +.names n2630gat II1630 +0 1 +.names II1630 n2629gat +0 1 +.names n2629gat n2486gat +0 1 +.names n2541gat n2429gat +0 1 +.names n2533gat n2486gat n2429gat n2430gat +000 1 +.names n2430gat n2432gat +0 1 +.names n2102gat II1655 +0 1 +.names II1655 n2101gat +0 1 +.names n2101gat n1693gat +0 1 +.names n1880gat II1667 +0 1 +.names II1667 n1879gat +0 1 +.names n2470gat n1935gat n2239gat n1934gat +000 1 +.names n1934gat n1698gat +0 1 +.names n1606gat n1543gat +0 1 +.names n1763gat II1683 +0 1 +.names II1683 n1762gat +0 1 +.names n1693gat n1692gat n2989gat +1- 1 +-1 1 +.names n2989gat n1673gat +0 1 +.names n2155gat II1698 +0 1 +.names II1698 n2154gat +0 1 +.names n2490gat n2488gat +0 1 +.names n2626gat II1703 +0 1 +.names II1703 n2625gat +0 1 +.names n2488gat n2625gat n2621gat n2531gat +000 1 +.names n2531gat n2530gat +0 1 +.names n2543gat II1708 +0 1 +.names II1708 n2542gat +0 1 +.names n2542gat n2482gat +0 1 +.names n2530gat n2482gat n2486gat n2480gat +000 1 +.names n2480gat n2426gat +0 1 +.names n2155gat n2153gat +0 1 +.names n2341gat n2355gat +0 1 +.names n2562gat II1719 +0 1 +.names II1719 n2561gat +0 1 +.names n2561gat n2443gat +0 1 +.names n2355gat n2443gat II1723 II1724 +1-- 1 +-1- 1 +--1 1 +.names II1724 n2289gat +0 1 +.names n1604gat n2214gat II1733 II1734 +1-- 1 +-1- 1 +--1 1 +.names II1734 n2148gat +0 1 +.names n2148gat n855gat +0 1 +.names n855gat n759gat +0 1 +.names n1035gat II1749 +0 1 +.names II1749 n1034gat +0 1 +.names n1034gat II1752 +0 1 +.names II1752 n1189gat +0 1 +.names n855gat n1075gat +0 1 +.names n1121gat II1766 +0 1 +.names II1766 n1120gat +0 1 +.names n1120gat II1769 +0 1 +.names II1769 n1190gat +0 1 +.names n855gat n760gat +0 1 +.names n1072gat II1783 +0 1 +.names II1783 n1071gat +0 1 +.names n1071gat II1786 +0 1 +.names II1786 n1191gat +0 1 +.names n1121gat n1119gat +0 1 +.names n1119gat II1791 +0 1 +.names II1791 n1192gat +0 1 +.names n1072gat n1070gat +0 1 +.names n1070gat II1795 +0 1 +.names II1795 n1193gat +0 1 +.names n1035gat n1033gat +0 1 +.names n1033gat II1800 +0 1 +.names II1800 n1194gat +0 1 +.names n1185gat n1186gat n1187gat n1188gat n1184gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1184gat n1183gat +0 1 +.names n1183gat II1807 +0 1 +.names II1807 n1274gat +0 1 +.names n855gat n644gat +0 1 +.names n1282gat n1280gat +0 1 +.names n855gat n641gat +0 1 +.names n1226gat II1833 +0 1 +.names II1833 n1225gat +0 1 +.names n1282gat II1837 +0 1 +.names II1837 n1281gat +0 1 +.names n1226gat n1224gat +0 1 +.names n1383gat n1327gat n2970gat +1- 1 +-1 1 +.names n2970gat II1843 +0 1 +.names II1843 n1275gat +0 1 +.names n855gat n761gat +0 1 +.names n931gat II1857 +0 1 +.names II1857 n930gat +0 1 +.names n930gat II1860 +0 1 +.names II1860 n1206gat +0 1 +.names n855gat n762gat +0 1 +.names n1135gat II1874 +0 1 +.names II1874 n1134gat +0 1 +.names n1134gat II1877 +0 1 +.names II1877 n1207gat +0 1 +.names n855gat n643gat +0 1 +.names n1045gat II1891 +0 1 +.names II1891 n1044gat +0 1 +.names n1044gat II1894 +0 1 +.names II1894 n1208gat +0 1 +.names n1135gat n1133gat +0 1 +.names n1133gat II1899 +0 1 +.names II1899 n1209gat +0 1 +.names n1045gat n1043gat +0 1 +.names n1043gat II1903 +0 1 +.names II1903 n1210gat +0 1 +.names n931gat n929gat +0 1 +.names n929gat II1908 +0 1 +.names II1908 n1211gat +0 1 +.names n1202gat n1203gat n1204gat n1205gat n1201gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1201gat n1268gat +0 1 +.names n1268gat II1915 +0 1 +.names II1915 n1276gat +0 1 +.names n2970gat n1329gat +0 1 +.names n1329gat II1920 +0 1 +.names II1920 n1277gat +0 1 +.names n1201gat II1923 +0 1 +.names II1923 n1278gat +0 1 +.names n1184gat II1927 +0 1 +.names II1927 n1279gat +0 1 +.names n1270gat n1271gat n1272gat n1273gat n1269gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1269gat n1284gat +0 1 +.names n855gat n642gat +0 1 +.names n1197gat n1195gat +0 1 +.names n1197gat II1947 +0 1 +.names II1947 n1196gat +0 1 +.names n2518gat n2516gat +0 1 +.names n2516gat II1961 +0 1 +.names II1961 n3017gat +0 1 +.names n740gat n2148gat n853gat +00 1 +.names n853gat n851gat +0 1 +.names n2148gat n1725gat +0 1 +.names n1725gat n664gat +0 1 +.names n2148gat n374gat n854gat +00 1 +.names n854gat n852gat +0 1 +.names n667gat II1981 +0 1 +.names II1981 n666gat +0 1 +.names n1725gat n368gat +0 1 +.names n659gat II1996 +0 1 +.names II1996 n658gat +0 1 +.names n658gat II1999 +0 1 +.names II1999 n784gat +0 1 +.names n1725gat n662gat +0 1 +.names n553gat II2014 +0 1 +.names II2014 n552gat +0 1 +.names n552gat II2017 +0 1 +.names II2017 n785gat +0 1 +.names n1725gat n661gat +0 1 +.names n777gat II2032 +0 1 +.names II2032 n776gat +0 1 +.names n776gat II2035 +0 1 +.names II2035 n786gat +0 1 +.names n553gat n551gat +0 1 +.names n551gat II2040 +0 1 +.names II2040 n787gat +0 1 +.names n777gat n775gat +0 1 +.names n775gat II2044 +0 1 +.names II2044 n788gat +0 1 +.names n659gat n657gat +0 1 +.names n657gat II2049 +0 1 +.names II2049 n789gat +0 1 +.names n780gat n781gat n782gat n783gat n779gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n779gat n35gat +0 1 +.names n35gat II2056 +0 1 +.names II2056 n125gat +0 1 +.names n1725gat n558gat +0 1 +.names n561gat n559gat +0 1 +.names n1725gat n371gat +0 1 +.names n366gat II2084 +0 1 +.names II2084 n365gat +0 1 +.names n561gat II2088 +0 1 +.names II2088 n560gat +0 1 +.names n366gat n364gat +0 1 +.names n874gat n132gat n2876gat +1- 1 +-1 1 +.names n2876gat II2094 +0 1 +.names II2094 n126gat +0 1 +.names n1725gat n663gat +0 1 +.names n322gat II2109 +0 1 +.names II2109 n321gat +0 1 +.names n321gat II2112 +0 1 +.names II2112 n226gat +0 1 +.names n1725gat n370gat +0 1 +.names n318gat II2127 +0 1 +.names II2127 n317gat +0 1 +.names n317gat II2130 +0 1 +.names II2130 n227gat +0 1 +.names n1725gat n369gat +0 1 +.names n314gat II2145 +0 1 +.names II2145 n313gat +0 1 +.names n313gat II2148 +0 1 +.names II2148 n228gat +0 1 +.names n318gat n316gat +0 1 +.names n316gat II2153 +0 1 +.names II2153 n229gat +0 1 +.names n314gat n312gat +0 1 +.names n312gat II2157 +0 1 +.names II2157 n230gat +0 1 +.names n322gat n320gat +0 1 +.names n320gat II2162 +0 1 +.names II2162 n231gat +0 1 +.names n222gat n223gat n224gat n225gat n221gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n221gat n34gat +0 1 +.names n34gat II2169 +0 1 +.names II2169 n127gat +0 1 +.names n2876gat n133gat +0 1 +.names n133gat II2174 +0 1 +.names II2174 n128gat +0 1 +.names n221gat II2177 +0 1 +.names II2177 n129gat +0 1 +.names n779gat II2181 +0 1 +.names II2181 n130gat +0 1 +.names n667gat n665gat +0 1 +.names n121gat n122gat n123gat n124gat n120gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n120gat n1601gat +0 1 +.names n2599gat n2597gat +0 1 +.names n3017gat n2520gat n2597gat n2594gat +000 1 +.names n2594gat n2595gat +0 1 +.names n2588gat n2586gat +0 1 +.names n2342gat II2213 +0 1 +.names II2213 n2573gat +0 1 +.names n2638gat II2225 +0 1 +.names II2225 n2574gat +0 1 +.names n2561gat II2228 +0 1 +.names II2228 n2575gat +0 1 +.names n2640gat II2232 +0 1 +.names II2232 n2639gat +0 1 +.names n2639gat II2235 +0 1 +.names II2235 n2576gat +0 1 +.names n2560gat II2238 +0 1 +.names II2238 n2577gat +0 1 +.names n2341gat II2242 +0 1 +.names II2242 n2578gat +0 1 +.names n2569gat n2570gat n2571gat n2572gat n2568gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2568gat II2248 +0 1 +.names II2248 n2582gat +0 1 +.names n2207gat II2251 +0 1 +.names II2251 n2206gat +0 1 +.names n2206gat II2254 +0 1 +.names II2254 n2414gat +0 1 +.names n2398gat II2257 +0 1 +.names II2257 n2415gat +0 1 +.names n2203gat II2260 +0 1 +.names II2260 n2202gat +0 1 +.names n2202gat II2263 +0 1 +.names II2263 n2416gat +0 1 +.names n2397gat II2268 +0 1 +.names II2268 n2417gat +0 1 +.names n2201gat II2271 +0 1 +.names II2271 n2418gat +0 1 +.names n2205gat II2275 +0 1 +.names II2275 n2419gat +0 1 +.names n2410gat n2411gat n2412gat n2413gat n2409gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2409gat II2281 +0 1 +.names II2281 n2585gat +0 1 +.names n2658gat n2656gat +0 1 +.names n2390gat II2316 +0 1 +.names II2316 n2389gat +0 1 +.names n2495gat II2319 +0 1 +.names II2319 n2494gat +0 1 +.names n2567gat n2499gat n3014gat +1- 1 +-1 1 +.names n3014gat II2324 +0 1 +.names II2324 n2649gat +0 1 +.names n2339gat II2344 +0 1 +.names II2344 n2338gat +0 1 +.names n2270gat II2349 +0 1 +.names II2349 n2269gat +0 1 +.names n299gat n207gat n2880gat +1- 1 +-1 1 +.names n2880gat II2354 +0 1 +.names II2354 n2652gat +0 1 +.names n2502gat n2500gat +0 1 +.names n2622gat n2620gat +0 1 +.names n2620gat n2612gat +0 1 +.names n2612gat II2372 +0 1 +.names II2372 n2606gat +0 1 +.names n2532gat II2376 +0 1 +.names II2376 n2607gat +0 1 +.names n2488gat n2540gat +0 1 +.names n2540gat II2380 +0 1 +.names II2380 n2608gat +0 1 +.names n2624gat n2536gat +0 1 +.names n2536gat II2385 +0 1 +.names II2385 n2609gat +0 1 +.names n2487gat II2389 +0 1 +.names II2389 n2610gat +0 1 +.names n2557gat II2394 +0 1 +.names II2394 n2611gat +0 1 +.names n2602gat n2603gat n2604gat n2605gat n2601gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2601gat II2400 +0 1 +.names II2400 n2616gat +0 1 +.names n2629gat II2403 +0 1 +.names II2403 n2550gat +0 1 +.names n2634gat II2414 +0 1 +.names II2414 n2633gat +0 1 +.names n2633gat II2417 +0 1 +.names II2417 n2551gat +0 1 +.names n2542gat II2420 +0 1 +.names II2420 n2552gat +0 1 +.names n2632gat II2425 +0 1 +.names II2425 n2553gat +0 1 +.names n2541gat II2428 +0 1 +.names II2428 n2554gat +0 1 +.names n2628gat II2433 +0 1 +.names II2433 n2555gat +0 1 +.names n2546gat n2547gat n2548gat n2549gat n2545gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2545gat II2439 +0 1 +.names II2439 n2619gat +0 1 +.names n2506gat n2504gat +0 1 +.names n2508gat n2656gat n2500gat n2504gat n2655gat +0000 1 +.names n2655gat n2660gat +0 1 +.names n2353gat n2284gat n2443gat n2293gat +000 1 +.names n2293gat n1528gat +0 1 +.names n2354gat n2214gat n2219gat +00 1 +.names n2219gat n1523gat +0 1 +.names n1528gat n1523gat n1529gat +00 1 +.names n1529gat n1592gat +0 1 +.names n3027gat n1706gat n1704gat +00 1 +.names n1704gat n2666gat +0 1 +.names n2461gat n2421gat n3013gat +1- 1 +-1 1 +.names n3013gat n2422gat +0 1 +.names n2202gat n2290gat +0 1 +.names n2214gat n2290gat n2218gat +00 1 +.names n2218gat n2081gat +0 1 +.names n2397gat n2285gat +0 1 +.names n2285gat n2356gat n2355gat n2358gat +000 1 +.names n2358gat n2359gat +0 1 +.names n2081gat n2359gat n1415gat +00 1 +.names n1415gat n1414gat +0 1 +.names n364gat n566gat +0 1 +.names n2443gat n2284gat n2285gat n2292gat +000 1 +.names n2292gat n1480gat +0 1 +.names n2081gat n1480gat n1416gat +00 1 +.names n1416gat n1301gat +0 1 +.names n312gat n1150gat +0 1 +.names n316gat n873gat +0 1 +.names n2356gat n2284gat n2285gat n2306gat +000 1 +.names n2306gat n2011gat +0 1 +.names n2081gat n2011gat n1481gat +00 1 +.names n1481gat n1478gat +0 1 +.names n559gat n875gat +0 1 +.names n2285gat n2355gat n2443gat n2357gat +000 1 +.names n2357gat n1410gat +0 1 +.names n2081gat n1410gat n1347gat +00 1 +.names n1347gat n876gat +0 1 +.names n2081gat n1528gat n1484gat +00 1 +.names n1484gat n1160gat +0 1 +.names n657gat n1084gat +0 1 +.names n320gat n983gat +0 1 +.names n2353gat n2356gat n2355gat n2363gat +000 1 +.names n2363gat n1482gat +0 1 +.names n2081gat n1482gat n1483gat +00 1 +.names n1483gat n1157gat +0 1 +.names n775gat n985gat +0 1 +.names n2353gat n2284gat n2356gat n2364gat +000 1 +.names n2364gat n1530gat +0 1 +.names n2081gat n1530gat n1308gat +00 1 +.names n1308gat n1307gat +0 1 +.names n551gat n1085gat +0 1 +.names n2353gat n2355gat n2443gat n2291gat +000 1 +.names n2291gat n1479gat +0 1 +.names n1479gat n2081gat n1349gat +00 1 +.names n1349gat n1348gat +0 1 +.names n2206gat n2217gat +0 1 +.names n2354gat n2217gat n2223gat +00 1 +.names n2223gat n1591gat +0 1 +.names n1591gat n1480gat n1438gat +00 1 +.names n1438gat n1437gat +0 1 +.names n1834gat n1832gat +0 1 +.names n1767gat n1765gat +0 1 +.names n1880gat n1878gat +0 1 +.names n1832gat n1765gat n1878gat n1831gat +000 1 +.names n1831gat n1442gat +0 1 +.names n1442gat n1444gat +0 1 +.names n1443gat n1325gat n2975gat +1- 1 +-1 1 +.names n2975gat n1378gat +0 1 +.names n1321gat n1320gat n2974gat +1- 1 +-1 1 +.names n2974gat n1322gat +0 1 +.names n1482gat n1591gat n1486gat +00 1 +.names n1486gat n1439gat +0 1 +.names n2011gat n1591gat n1426gat +00 1 +.names n1426gat n1370gat +0 1 +.names n1368gat n1258gat n2966gat +1- 1 +-1 1 +.names n2966gat n1369gat +0 1 +.names n1479gat n1591gat n1365gat +00 1 +.names n1365gat n1366gat +0 1 +.names n1373gat n1372gat n2979gat +1- 1 +-1 1 +.names n2979gat n1374gat +0 1 +.names n2290gat n2217gat n2220gat +00 1 +.names n2220gat n2162gat +0 1 +.names n2162gat n1530gat n1423gat +00 1 +.names n1423gat n1450gat +0 1 +.names n1704gat n1703gat n1608gat +00 1 +.names n1608gat n1427gat +0 1 +.names n2084gat n2082gat +0 1 +.names n1528gat n2162gat n1494gat +00 1 +.names n1494gat n1449gat +0 1 +.names n1603gat n1590gat +0 1 +.names n1250gat n1103gat n2954gat +1- 1 +-1 1 +.names n2954gat n1248gat +0 1 +.names n2162gat n1480gat n1417gat +00 1 +.names n1417gat n1418gat +0 1 +.names n1304gat n1249gat n2964gat +1- 1 +-1 1 +.names n2964gat n1306gat +0 1 +.names n2162gat n1479gat n1419gat +00 1 +.names n1419gat n1353gat +0 1 +.names n1246gat n1161gat n2958gat +1- 1 +-1 1 +.names n2958gat n1247gat +0 1 +.names n2011gat n2162gat n1422gat +00 1 +.names n1422gat n1355gat +0 1 +.names n1291gat n1245gat n2963gat +1- 1 +-1 1 +.names n2963gat n1300gat +0 1 +.names n1482gat n2162gat n1485gat +00 1 +.names n1485gat n1487gat +0 1 +.names n1163gat n1102gat n2953gat +1- 1 +-1 1 +.names n2953gat n1164gat +0 1 +.names n1591gat n1530gat n1354gat +00 1 +.names n1354gat n1356gat +0 1 +.names n1591gat n1528gat n1435gat +00 1 +.names n1435gat n1436gat +0 1 +.names n1101gat n996gat n2949gat +1- 1 +-1 1 +.names n2949gat n1106gat +0 1 +.names n2162gat n2359gat n1421gat +00 1 +.names n1421gat n1425gat +0 1 +.names n1104gat n887gat n2934gat +1- 1 +-1 1 +.names n2934gat n1105gat +0 1 +.names n1410gat n2162gat n1420gat +00 1 +.names n1420gat n1424gat +0 1 +.names n1305gat n1162gat n2959gat +1- 1 +-1 1 +.names n2959gat n1309gat +0 1 +.names n2143gat II2672 +0 1 +.names II2672 n2142gat +0 1 +.names n2142gat n1788gat +0 1 +.names n2061gat II2684 +0 1 +.names II2684 n2060gat +0 1 +.names n2060gat n1786gat +0 1 +.names n2139gat II2696 +0 1 +.names II2696 n2138gat +0 1 +.names n2138gat n1839gat +0 1 +.names n1899gat n1897gat +0 1 +.names n1897gat n1884gat +0 1 +.names n1850gat n1848gat +0 1 +.names n1848gat n1783gat +0 1 +.names n1884gat n1783gat II2720 II2721 +1-- 1 +-1- 1 +--1 1 +.names II2721 n1548gat +0 1 +.names n1548gat n1719gat +0 1 +.names n2139gat n2137gat +0 1 +.names n2137gat n1633gat +0 1 +.names n2061gat n2059gat +0 1 +.names n2059gat n1785gat +0 1 +.names n1850gat II2731 +0 1 +.names II2731 n1849gat +0 1 +.names n1849gat n1784gat +0 1 +.names n1785gat n1784gat II2735 II2736 +1-- 1 +-1- 1 +--1 1 +.names II2736 n1716gat +0 1 +.names n1716gat n1635gat +0 1 +.names n2403gat n2401gat +0 1 +.names n2401gat n1989gat +0 1 +.names n2394gat n2392gat +0 1 +.names n2392gat n1918gat +0 1 +.names n2440gat II2771 +0 1 +.names II2771 n2439gat +0 1 +.names n2439gat n1986gat +0 1 +.names n1989gat n1918gat n1986gat n1865gat +000 1 +.names n1865gat n1866gat +0 1 +.names n2407gat II2785 +0 1 +.names II2785 n2406gat +0 1 +.names n2406gat n2216gat +0 1 +.names n2347gat n2345gat +0 1 +.names n2345gat n1988gat +0 1 +.names n1866gat n2216gat n1988gat n1861gat +000 1 +.names n1861gat n1735gat +0 1 +.names n1389gat n1387gat +0 1 +.names n1609gat n1702gat n1700gat II2812 II2813 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names II2813 n1694gat +0 1 +.names n1777gat n1625gat n1626gat n1780gat +000 1 +.names n2021gat n2019gat +0 1 +.names n1884gat n1784gat II2831 II2832 +1-- 1 +-1- 1 +--1 1 +.names II2832 n1549gat +0 1 +.names n1549gat n1551gat +0 1 +.names n2347gat II2837 +0 1 +.names II2837 n2346gat +0 1 +.names n2346gat n2152gat +0 1 +.names n2407gat n2405gat +0 1 +.names n2405gat n2351gat +0 1 +.names n2403gat II2843 +0 1 +.names II2843 n2402gat +0 1 +.names n2402gat n2212gat +0 1 +.names n2394gat II2847 +0 1 +.names II2847 n2393gat +0 1 +.names n2393gat n1991gat +0 1 +.names n1986gat n2212gat n1991gat n1666gat +000 1 +.names n1666gat n1665gat +0 1 +.names n2152gat n2351gat n1665gat n1578gat +000 1 +.names n1578gat n1517gat +0 1 +.names n1496gat II2873 +0 1 +.names II2873 n1495gat +0 1 +.names n1778gat n1609gat n1702gat n1700gat n1604gat +0000 1 +.names n2091gat II2885 +0 1 +.names II2885 n2090gat +0 1 +.names n1788gat n1786gat II2889 II2890 +1-- 1 +-1- 1 +--1 1 +.names II2890 n1550gat +0 1 +.names n1550gat n1552gat +0 1 +.names n1740gat n1738gat +0 1 +.names n1740gat II2915 +0 1 +.names II2915 n1739gat +0 1 +.names n1864gat n1921gat n1798gat n1920gat +000 1 +.names n1920gat n1925gat +0 1 +.names n1738gat n1673gat n1921gat +00 1 +.names n1921gat n1917gat +0 1 +.names n2143gat n2141gat +0 1 +.names n2141gat n1787gat +0 1 +.names n1884gat n1787gat II2925 II2926 +1-- 1 +-1- 1 +--1 1 +.names n1717gat n1859gat +0 1 +.names n1739gat n1673gat n1798gat +00 1 +.names n1798gat n1922gat +0 1 +.names n1785gat n1884gat II2934 II2935 +1-- 1 +-1- 1 +--1 1 +.names n1713gat n1743gat +0 1 +.names n1858gat n1495gat n2090gat n1864gat +000 1 +.names n1864gat n1923gat +0 1 +.names n1700gat n1702gat n1690gat +00 1 +.names n2179gat II2953 +0 1 +.names II2953 n2178gat +0 1 +.names n1918gat n1986gat n2212gat n1660gat +000 1 +.names n1660gat n1661gat +0 1 +.names n2351gat n1988gat n1661gat n1576gat +000 1 +.names n1576gat n1572gat +0 1 +.names n2440gat n2438gat +0 1 +.names n2438gat n2283gat +0 1 +.names n2283gat n1991gat n2212gat n1582gat +000 1 +.names n1582gat n1520gat +0 1 +.names n1520gat n2351gat n1988gat n1577gat +000 1 +.names n1577gat n1580gat +0 1 +.names n1733gat n1581gat n2988gat +1- 1 +-1 1 +.names n2988gat n1990gat +0 1 +.names n2190gat II2978 +0 1 +.names II2978 n2189gat +0 1 +.names n2135gat II2989 +0 1 +.names II2989 n2134gat +0 1 +.names n2262gat II3000 +0 1 +.names II3000 n2261gat +0 1 +.names n2189gat n2134gat n2261gat n2129gat +000 1 +.names n2129gat n2128gat +0 1 +.names n1609gat n1778gat n1704gat n1703gat n1695gat +0000 1 +.names n2182gat II3016 +0 1 +.names II3016 n2181gat +0 1 +.names n1312gat II3056 +0 1 +.names II3056 n1311gat +0 1 +.names n1626gat n1707gat +0 1 +.names n1574gat n1573gat n2987gat +1- 1 +-1 1 +.names n2987gat n1659gat +0 1 +.names n2283gat n1991gat n1521gat +00 1 +.names n1521gat n1515gat +0 1 +.names n2212gat n2152gat n1737gat +00 1 +.names n1737gat n1736gat +0 1 +.names n2216gat n1658gat +0 1 +.names n1515gat n1736gat n1658gat n1732gat +000 1 +.names n1732gat n1724gat +0 1 +.names n1986gat n1918gat n1663gat +00 1 +.names n1663gat n1662gat +0 1 +.names n1736gat n1662gat n1658gat n1655gat +000 1 +.names n1655gat n1656gat +0 1 +.names n1991gat n1986gat n1667gat +00 1 +.names n1667gat n1670gat +0 1 +.names n1736gat n1658gat n1670gat n1570gat +000 1 +.names n1570gat n1569gat +0 1 +.names n1918gat n2283gat n1575gat +00 1 +.names n1575gat n1568gat +0 1 +.names n1568gat n1736gat n1658gat n1728gat +000 1 +.names n1728gat n1727gat +0 1 +.names n2152gat n1989gat n1801gat +00 1 +.names n1801gat n1797gat +0 1 +.names n1658gat n1515gat n1797gat n1731gat +000 1 +.names n1731gat n1730gat +0 1 +.names n1670gat n1658gat n1797gat n1571gat +000 1 +.names n1571gat n1561gat +0 1 +.names n1988gat n2212gat n1734gat +00 1 +.names n1734gat n1668gat +0 1 +.names n2216gat n1742gat +0 1 +.names n1668gat n1742gat n1670gat n1669gat +000 1 +.names n1669gat n1671gat +0 1 +.names n1662gat n1797gat n1658gat n1657gat +000 1 +.names n1657gat n1652gat +0 1 +.names n1658gat n1797gat n1568gat n1729gat +000 1 +.names n1729gat n1648gat +0 1 +.names n2992gat n2986gat n2991gat n1726gat +000 1 +.names n1726gat n1790gat +0 1 +.names n1758gat n1790gat n1929gat +00 1 +.names n1929gat n2004gat +0 1 +.names n1871gat n1869gat +0 1 +.names n2592gat II3143 +0 1 +.names II3143 n2591gat +0 1 +.names n2989gat n1584gat +0 1 +.names n1786gat n1787gat II3148 II3149 +1-- 1 +-1- 1 +--1 1 +.names II3149 n1714gat +0 1 +.names n1714gat n1718gat +0 1 +.names n1508gat II3163 +0 1 +.names II3163 n1507gat +0 1 +.names n1584gat n1590gat n1401gat +00 1 +.names n1401gat n1396gat +0 1 +.names n1394gat II3168 +0 1 +.names II3168 n1393gat +0 1 +.names n1858gat n1590gat n1476gat +00 1 +.names n1476gat n1409gat +0 1 +.names n1899gat II3174 +0 1 +.names II3174 n1898gat +0 1 +.names n1898gat n1838gat +0 1 +.names n1839gat n1784gat II3178 II3179 +1-- 1 +-1- 1 +--1 1 +.names n1678gat II3191 +0 1 +.names II3191 n1677gat +0 1 +.names n1411gat n1406gat n2981gat n1412gat +000 1 +.names n1412gat n2000gat +0 1 +.names n1412gat n2001gat +0 1 +.names n2001gat n1999gat +0 1 +.names n2586gat n2660gat n2307gat n2663gat +000 1 +.names n2663gat II3211 +0 1 +.names II3211 n3018gat +0 1 +.names n2450gat n2448gat +0 1 +.names n2660gat n2586gat n2662gat +00 1 +.names n2446gat n2444gat +0 1 +.names n2448gat n2444gat n2238gat +00 1 +.names n2238gat II3235 +0 1 +.names II3235 n3019gat +0 1 +.names n1312gat n1310gat +0 1 +.names n743gat n17gat n293gat n87gat +000 1 +.names n87gat n199gat +0 1 +.names n189gat n188gat n179gat n184gat +000 1 +.names n184gat n195gat +0 1 +.names n200gat n196gat n204gat +00 1 +.names n2169gat II3273 +0 1 +.names II3273 n2168gat +0 1 +.names n2454gat n2452gat +0 1 +.names n2452gat n1691gat +0 1 +.names n1691gat II3287 +0 1 +.names II3287 n3020gat +0 1 +.names n1691gat II3290 +0 1 +.names II3290 n3021gat +0 1 +.names n1691gat II3293 +0 1 +.names II3293 n3022gat +0 1 +.names n2452gat n1699gat +0 1 +.names n1699gat II3297 +0 1 +.names II3297 n3023gat +0 1 +.names n1699gat II3300 +0 1 +.names II3300 n3024gat +0 1 +.names n1691gat II3303 +0 1 +.names II3303 n3025gat +0 1 +.names n1699gat II3306 +0 1 +.names II3306 n3026gat +0 1 +.names n1699gat II3309 +0 1 +.names II3309 n3027gat +0 1 +.names n1699gat II3312 +0 1 +.names II3312 n3028gat +0 1 +.names n1869gat II3315 +0 1 +.names II3315 n3029gat +0 1 +.names n1869gat II3318 +0 1 +.names II3318 n3030gat +0 1 +.names n2262gat n2260gat +0 1 +.names n2189gat n2257gat +0 1 +.names n2190gat n2188gat +0 1 +.names n2258gat n2257gat n2255gat n3004gat +1-- 1 +-1- 1 +--1 1 +.names n3004gat n2187gat +0 1 +.names n2040gat II3336 +0 1 +.names II3336 n2039gat +0 1 +.names n1775gat II3339 +0 1 +.names II3339 n1774gat +0 1 +.names n1316gat II3342 +0 1 +.names II3342 n1315gat +0 1 +.names n2099gat n2097gat +0 1 +.names n2035gat n2093gat n2018gat n2664gat n2014gat +0000 1 +.names n2014gat n1855gat +0 1 +.names n2187gat n1855gat n2194gat +00 1 +.names n2194gat II3387 +0 1 +.names n2261gat II3390 +0 1 +.names II3390 n3032gat +0 1 +.names n3032gat n2256gat +0 1 +.names n2260gat II3394 +0 1 +.names II3394 n3033gat +0 1 +.names n3033gat n2251gat +0 1 +.names n2256gat n2251gat n3003gat +1- 1 +-1 1 +.names n3003gat n2184gat +0 1 +.names n2184gat n1855gat n2192gat +00 1 +.names n2192gat II3401 +0 1 +.names n2135gat n2133gat +0 1 +.names n2261gat n2189gat n2185gat +00 1 +.names n2185gat n2131gat +0 1 +.names n2132gat n2130gat n3001gat +1- 1 +-1 1 +.names n3001gat n2049gat +0 1 +.names n2049gat n1855gat n2057gat +00 1 +.names n2057gat II3412 +0 1 +.names n2189gat n2253gat +0 1 +.names n2260gat n2252gat +0 1 +.names n2253gat n2252gat n3006gat +1- 1 +-1 1 +.names n3006gat n2248gat +0 1 +.names n2266gat n2264gat +0 1 +.names n2266gat II3429 +0 1 +.names II3429 n2265gat +0 1 +.names n1855gat n3007gat n2329gat +00 1 +.names n2329gat n2492gat +0 1 +.names n2492gat II3436 +0 1 +.names n1849gat n1709gat +0 1 +.names n2141gat n1845gat +0 1 +.names n2059gat n1891gat +0 1 +.names n2137gat n1963gat +0 1 +.names n1897gat n1886gat +0 1 +.names n1963gat n1886gat n1958gat +00 1 +.names n1958gat n1968gat +0 1 +.names n1845gat n1891gat n1968gat n1895gat +000 1 +.names n1895gat n1629gat +0 1 +.names n1848gat n1631gat +0 1 +.names n1710gat n1630gat n2990gat +1- 1 +-1 1 +.names n2990gat n1711gat +0 1 +.names n1926gat n1916gat n1994gat n1924gat n2078gat +0000 1 +.names n2078gat n2200gat +0 1 +.names n2200gat n1855gat n2195gat +00 1 +.names n2195gat n2437gat +0 1 +.names n1711gat n2437gat n2556gat +00 1 +.names n2556gat II3457 +0 1 +.names n1898gat n1956gat +0 1 +.names n1956gat II3461 +0 1 +.names II3461 n3038gat +0 1 +.names n3038gat n1954gat +0 1 +.names n1886gat II3465 +0 1 +.names II3465 n3039gat +0 1 +.names n3039gat n1888gat +0 1 +.names n1954gat n1888gat n2994gat +1- 1 +-1 1 +.names n2994gat n2048gat +0 1 +.names n2048gat n2437gat n2539gat +00 1 +.names n2539gat II3472 +0 1 +.names n2142gat n1969gat +0 1 +.names n2060gat n1893gat +0 1 +.names n1894gat n1847gat n1846gat n2993gat +1-- 1 +-1- 1 +--1 1 +.names n2993gat n1892gat +0 1 +.names n2437gat n1892gat n2436gat +00 1 +.names n2436gat II3483 +0 1 +.names n2055gat n1967gat n2998gat +1- 1 +-1 1 +.names n2998gat n2056gat +0 1 +.names n2056gat n2437gat n2387gat +00 1 +.names n2387gat II3491 +0 1 +.names n1963gat II3494 +0 1 +.names II3494 n3043gat +0 1 +.names n3043gat n1960gat +0 1 +.names n2138gat n1887gat +0 1 +.names n1960gat n1959gat n1957gat n2996gat +1-- 1 +-1- 1 +--1 1 +.names n2996gat n1961gat +0 1 +.names n2437gat n1961gat n2330gat +00 1 +.names n2330gat II3504 +0 1 +.names n2988gat n1855gat n2147gat +00 1 +.names n2147gat n2199gat +0 1 +.names n2438gat II3509 +0 1 +.names II3509 n3045gat +0 1 +.names n3045gat n2332gat +0 1 +.names n2439gat II3513 +0 1 +.names II3513 n3046gat +0 1 +.names n3046gat n2259gat +0 1 +.names n2332gat n2259gat n3008gat +1- 1 +-1 1 +.names n3008gat n2328gat +0 1 +.names n2199gat n2328gat n2498gat +00 1 +.names n2498gat II3520 +0 1 +.names n2393gat n2439gat n2193gat +00 1 +.names n2193gat n2151gat +0 1 +.names n2211gat n2210gat n3005gat +1- 1 +-1 1 +.names n3005gat n2209gat +0 1 +.names n2199gat n2209gat n2396gat +00 1 +.names n2396gat II3530 +0 1 +.names n2393gat n2052gat +0 1 +.names n2053gat n2052gat n1964gat n2997gat +1-- 1 +-1- 1 +--1 1 +.names n2997gat n2058gat +0 1 +.names n2199gat n2058gat n2198gat +00 1 +.names n2198gat II3539 +0 1 +.names n2346gat n2151gat n2402gat n2215gat +000 1 +.names n2215gat n2349gat +0 1 +.names n2350gat n2282gat n3009gat +1- 1 +-1 1 +.names n3009gat n2281gat +0 1 +.names n2199gat n2281gat n2197gat +00 1 +.names n2197gat II3549 +0 1 +.names n2213gat n2150gat n2149gat n3002gat +1-- 1 +-1- 1 +--1 1 +.names n3002gat n2146gat +0 1 +.names n2199gat n2146gat n2196gat +00 1 +.names n2196gat II3558 +0 1 +.names n2125gat II3587 +0 1 +.names II3587 n2124gat +0 1 +.names n2117gat n2115gat +0 1 +.names n2124gat n2115gat n2239gat n1882gat +000 1 +.names n1882gat II3610 +0 1 +.names n1975gat II3621 +0 1 +.names II3621 n1974gat +0 1 +.names n1956gat n1955gat +0 1 +.names n2995gat n1895gat n1896gat +00 1 +.names n1896gat n1970gat +0 1 +.names n1975gat n1973gat +0 1 +.names n2999gat n2437gat n2559gat +00 1 +.names n2559gat n2558gat +0 1 +.names n2558gat II3635 +0 1 +.names n2644gat II3646 +0 1 +.names II3646 n2643gat +0 1 +.names n2438gat n2333gat +0 1 +.names n3011gat n2215gat n2352gat +00 1 +.names n2352gat n2564gat +0 1 +.names n2644gat n2642gat +0 1 +.names n3015gat n2199gat n2637gat +00 1 +.names n2637gat n2636gat +0 1 +.names n2636gat II3660 +0 1 +.names n296gat n17gat n294gat n84gat +000 1 +.names n84gat n88gat +0 1 +.names n182gat n89gat n110gat +00 1 +.names n110gat n375gat +0 1 +.names n156gat II3677 +0 1 +.names II3677 n155gat +0 1 +.names n3024gat n1615gat n1702gat +00 1 +.names n1702gat n253gat +0 1 +.names n152gat n150gat +0 1 +.names n152gat II3691 +0 1 +.names II3691 n151gat +0 1 +.names n1702gat n243gat +0 1 +.names n243gat n233gat +0 1 +.names n156gat n154gat +0 1 +.names n141gat n38gat n37gat n2874gat +1-- 1 +-1- 1 +--1 1 +.names n2874gat n800gat +0 1 +.names n1074gat n872gat n2917gat +1- 1 +-1 1 +.names n2917gat II3703 +0 1 +.names n234gat n137gat n2878gat +1- 1 +-1 1 +.names n2878gat n235gat +0 1 +.names n378gat n377gat n2892gat +1- 1 +-1 1 +.names n2892gat II3713 +0 1 +.names n182gat n78gat n212gat +00 1 +.names n212gat n372gat +0 1 +.names n331gat n329gat +0 1 +.names n388gat II3736 +0 1 +.names II3736 n387gat +0 1 +.names n1701gat n3023gat n1700gat +00 1 +.names n1700gat n334gat +0 1 +.names n388gat n386gat +0 1 +.names n331gat II3742 +0 1 +.names II3742 n330gat +0 1 +.names n1700gat n1430gat +0 1 +.names n1430gat n1490gat +0 1 +.names n250gat n249gat n248gat n2885gat +1-- 1 +-1- 1 +--1 1 +.names n2885gat n452gat +0 1 +.names n869gat n453gat n448gat n2900gat +1-- 1 +-1- 1 +--1 1 +.names n2900gat II3754 +0 1 +.names n251gat n244gat n2883gat +1- 1 +-1 1 +.names n2883gat n333gat +0 1 +.names n974gat n973gat n870gat n2929gat +1-- 1 +-1- 1 +--1 1 +.names n2929gat II3765 +0 1 +.names n463gat II3777 +0 1 +.names II3777 n462gat +0 1 +.names n327gat n325gat +0 1 +.names n246gat n245gat n2884gat +1- 1 +-1 1 +.names n2884gat n457gat +0 1 +.names n463gat n461gat +0 1 +.names n460gat n459gat n2902gat +1- 1 +-1 1 +.names n2902gat n458gat +0 1 +.names n975gat n972gat n969gat n2925gat +1-- 1 +-1- 1 +--1 1 +.names n2925gat II3801 +0 1 +.names n334gat n387gat n330gat n247gat +000 1 +.names n247gat n144gat +0 1 +.names n327gat II3808 +0 1 +.names II3808 n326gat +0 1 +.names n145gat n143gat n2879gat +1- 1 +-1 1 +.names n2879gat n878gat +0 1 +.names n971gat n970gat n968gat n2916gat +1-- 1 +-1- 1 +--1 1 +.names n2916gat II3817 +0 1 +.names n384gat n382gat +0 1 +.names n384gat II3831 +0 1 +.names II3831 n383gat +0 1 +.names n142gat n40gat n39gat n2875gat +1-- 1 +-1- 1 +--1 1 +.names n2875gat n134gat +0 1 +.names n772gat n451gat n446gat n2899gat +1-- 1 +-1- 1 +--1 1 +.names n2899gat II3841 +0 1 +.names n256gat n254gat +0 1 +.names n139gat n136gat n2877gat +1- 1 +-1 1 +.names n2877gat n252gat +0 1 +.names n470gat n468gat +0 1 +.names n470gat II3867 +0 1 +.names II3867 n469gat +0 1 +.names n391gat n390gat n2893gat +1- 1 +-1 1 +.names n2893gat n381gat +0 1 +.names n1083gat n1077gat n2926gat +1- 1 +-1 1 +.names n2926gat II3876 +0 1 +.names n151gat n253gat n155gat n140gat +000 1 +.names n140gat n241gat +0 1 +.names n256gat II3882 +0 1 +.names II3882 n255gat +0 1 +.names n242gat n240gat n2882gat +1- 1 +-1 1 +.names n2882gat n802gat +0 1 +.names n871gat n797gat n2924gat +1- 1 +-1 1 +.names n2924gat II3891 +0 1 +.names n148gat n146gat +0 1 +.names n148gat II3904 +0 1 +.names II3904 n147gat +0 1 +.names n324gat n238gat n237gat n2881gat +1-- 1 +-1- 1 +--1 1 +.names n2881gat n380gat +0 1 +.names n1082gat n796gat n2923gat +1- 1 +-1 1 +.names n2923gat II3914 +0 1 +.names n85gat n180gat n68gat +00 1 +.names n68gat n69gat +0 1 +.names n2048gat n1885gat +0 1 +.names n69gat n1885gat n2710gat +1- 1 +-1 1 +.names n2710gat II3923 +0 1 +.names II3923 n2707gat +0 1 +.names n564gat n16gat +0 1 +.names n2726gat n2860gat n357gat +00 1 +.names n357gat n295gat +0 1 +.names n186gat n82gat n12gat +00 1 +.names n12gat n11gat +0 1 +.names n1961gat n1889gat +0 1 +.names n11gat n1889gat n2704gat +1- 1 +-1 1 +.names n2704gat II3935 +0 1 +.names II3935 n2700gat +0 1 +.names n2056gat n2051gat +0 1 +.names n1599gat n2051gat n2684gat +1- 1 +-1 1 +.names n2684gat II3941 +0 1 +.names II3941 n2680gat +0 1 +.names n1831gat n1350gat +0 1 +.names n1350gat II3945 +0 1 +.names II3945 n2696gat +0 1 +.names n2696gat II3948 +0 1 +.names II3948 n2692gat +0 1 +.names n2448gat II3951 +0 1 +.names II3951 n2683gat +0 1 +.names n2683gat II3954 +0 1 +.names II3954 n2679gat +0 1 +.names n2450gat II3957 +0 1 +.names II3957 n2449gat +0 1 +.names n2449gat n1754gat +0 1 +.names n2444gat n1754gat n2830gat +1- 1 +-1 1 +.names n2830gat II3962 +0 1 +.names II3962 n2827gat +0 1 +.names n2514gat n2512gat +0 1 +.names n1625gat n1544gat +0 1 +.names n1771gat n1769gat +0 1 +.names n2512gat n1769gat n1773gat n1756gat +000 1 +.names n1756gat n1683gat +0 1 +.names n2169gat n2167gat +0 1 +.names n2108gat n2093gat n2035gat II3999 II4000 +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names II4000 n2013gat +0 1 +.names n2013gat n1791gat +0 1 +.names n1586gat n1791gat n2695gat +1- 1 +-1 1 +.names n2695gat n2691gat +0 1 +.names n1694gat n1518gat +0 1 +.names n1755gat n1518gat n2703gat +1- 1 +-1 1 +.names n2703gat n2699gat +0 1 +.names n1412gat n2159gat +0 1 +.names n2579gat n2478gat +0 1 +.names n2159gat n2478gat n2744gat +1- 1 +-1 1 +.names n2744gat II4014 +0 1 +.names II4014 n2740gat +0 1 +.names n1412gat n2158gat +0 1 +.names n2613gat n2186gat +0 1 +.names n2158gat n2186gat n2800gat +1- 1 +-1 1 +.names n2800gat II4020 +0 1 +.names II4020 n2797gat +0 1 +.names n2353gat n2284gat II4023 II4024 +1-- 1 +-1- 1 +--1 1 +.names II4024 n2288gat +0 1 +.names n2288gat n1513gat +0 1 +.names n2620gat n2625gat n2488gat n2538gat +000 1 +.names n2538gat n2537gat +0 1 +.names n2537gat n2482gat n2486gat n2483gat +000 1 +.names n2483gat n2442gat +0 1 +.names n1336gat n1334gat +0 1 +.names n1748gat II4055 +0 1 +.names II4055 n1747gat +0 1 +.names n1675gat II4067 +0 1 +.names II4067 n1674gat +0 1 +.names n1858gat n1393gat n1604gat n1402gat +000 1 +.names n1402gat n1403gat +0 1 +.names n1807gat II4081 +0 1 +.names II4081 n1806gat +0 1 +.names n1712gat n1634gat +0 1 +.names n1340gat n1338gat +0 1 +.names n1456gat II4105 +0 1 +.names II4105 n1455gat +0 1 +.names n1340gat II4108 +0 1 +.names II4108 n1339gat +0 1 +.names n1470gat n1400gat n1399gat n1398gat n2980gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2980gat n1505gat +0 1 +.names n1505gat II4117 +0 1 +.names II4117 n2758gat +0 1 +.names n2758gat n2755gat +0 1 +.names n2980gat n1546gat +0 1 +.names n1546gat II4122 +0 1 +.names II4122 n2752gat +0 1 +.names n2752gat n2748gat +0 1 +.names n2019gat n1878gat n2016gat +00 1 +.names n2016gat n2012gat +0 1 +.names n2012gat n1774gat n2008gat +00 1 +.names n2008gat n2002gat +0 1 +.names n3097gat II4129 +0 1 +.names II4129 n2858gat +0 1 +.names n2858gat n2857gat +0 1 +.names n3098gat II4135 +0 1 +.names II4135 n2766gat +0 1 +.names n2766gat II4138 +0 1 +.names II4138 n2765gat +0 1 +.names n1818gat n1935gat n2765gat n1759gat +000 1 +.names n1759gat n1684gat +0 1 +.names n1788gat n1784gat II4144 II4145 +1-- 1 +-1- 1 +--1 1 +.names n1525gat II4157 +0 1 +.names II4157 n1524gat +0 1 +.names n1991gat n2283gat n1989gat n1863gat +000 1 +.names n1863gat n1862gat +0 1 +.names n1988gat n2216gat n1862gat n1860gat +000 1 +.names n1860gat n1919gat +0 1 +.names n1462gat n1460gat +0 1 +.names n1596gat II4185 +0 1 +.names II4185 n1595gat +0 1 +.names n1858gat n1608gat n1469gat +00 1 +.names n1469gat n1454gat +0 1 +.names n1584gat n1339gat n1600gat n1519gat +000 1 +.names n1519gat n1468gat +0 1 +.names n1462gat II4194 +0 1 +.names II4194 n1461gat +0 1 +.names n1467gat n1466gat n2984gat +1- 1 +-1 1 +.names n2984gat n1477gat +0 1 +.names n1596gat n1594gat +0 1 +.names n1588gat II4212 +0 1 +.names II4212 n1587gat +0 1 +.names n1392gat n2989gat II4216 II4217 +1-- 1 +-1- 1 +--1 1 +.names II4217 n1681gat +0 1 +.names n2985gat n1602gat n1681gat n1761gat +000 1 +.names n1761gat II4222 +0 1 +.names II4222 n2751gat +0 1 +.names n2751gat n2747gat +0 1 +.names n1681gat n1602gat n2985gat n1760gat +000 1 +.names n1760gat II4227 +0 1 +.names II4227 n2743gat +0 1 +.names n2743gat n2739gat +0 1 +.names n2286gat n1978gat +0 1 +.names n2442gat n1690gat n1978gat n1721gat +000 1 +.names n1721gat II4233 +0 1 +.names II4233 n2808gat +0 1 +.names n2808gat II4236 +0 1 +.names II4236 n2804gat +0 1 +.names n520gat n519gat n518gat +00 1 +.names n518gat n517gat +0 1 +.names n374gat n2723gat n418gat +00 1 +.names n418gat n417gat +0 1 +.names n374gat n2726gat n411gat +00 1 +.names n411gat n413gat +0 1 +.names n374gat n2859gat n522gat +00 1 +.names n522gat n412gat +0 1 +.names n374gat n2715gat n516gat +00 1 +.names n516gat n406gat +0 1 +.names n517gat n410gat n354gat n355gat +000 1 +.names n355gat n407gat +0 1 +.names n526gat n531gat n530gat n525gat +000 1 +.names n525gat n290gat +0 1 +.names n2726gat n740gat n356gat +00 1 +.names n356gat n527gat +0 1 +.names n2723gat n740gat n415gat +00 1 +.names n415gat n416gat +0 1 +.names n740gat n2715gat n521gat +00 1 +.names n521gat n528gat +0 1 +.names n527gat n416gat n528gat n532gat +000 1 +.names n532gat n358gat +0 1 +.names n522gat n356gat n523gat +00 1 +.names n523gat n639gat +0 1 +.names n639gat n634gat n414gat n635gat +000 1 +.names n635gat n1111gat +0 1 +.names n411gat n415gat n414gat +00 1 +.names n414gat n524gat +0 1 +.names n634gat n523gat n524gat n630gat +000 1 +.names n630gat n1112gat +0 1 +.names n414gat n634gat n523gat n629gat +000 1 +.names n629gat n741gat +0 1 +.names n418gat n521gat n634gat +00 1 +.names n634gat n633gat +0 1 +.names n414gat n523gat n633gat n632gat +000 1 +.names n632gat n926gat +0 1 +.names n414gat n633gat n639gat n636gat +000 1 +.names n636gat n670gat +0 1 +.names n632gat n1123gat +0 1 +.names n635gat n1007gat +0 1 +.names n630gat n1006gat +0 1 +.names n1003gat n902gat n2941gat +1- 1 +-1 1 +.names n2941gat II4309 +0 1 +.names II4309 n2814gat +0 1 +.names n2814gat II4312 +0 1 +.names II4312 n2811gat +0 1 +.names n1099gat n998gat n995gat n980gat n2946gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2946gat n1002gat +0 1 +.names n1001gat n999gat n2950gat +1- 1 +-1 1 +.names n2950gat II4329 +0 1 +.names II4329 n2813gat +0 1 +.names n2813gat II4332 +0 1 +.names II4332 n2810gat +0 1 +.names n981gat n890gat n889gat n886gat n2933gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2933gat n888gat +0 1 +.names n892gat n891gat n2935gat +1- 1 +-1 1 +.names n2935gat II4349 +0 1 +.names II4349 n2818gat +0 1 +.names n2818gat II4352 +0 1 +.names II4352 n2816gat +0 1 +.names n1152gat n1092gat n997gat n993gat n2940gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2940gat n898gat +0 1 +.names n900gat n895gat n2937gat +1- 1 +-1 1 +.names n2937gat II4369 +0 1 +.names II4369 n2817gat +0 1 +.names n2817gat II4372 +0 1 +.names II4372 n2815gat +0 1 +.names n1094gat n1093gat n988gat n984gat n2947gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2947gat n1179gat +0 1 +.names n1178gat n1116gat n2956gat +1- 1 +-1 1 +.names n2956gat II4389 +0 1 +.names II4389 n2824gat +0 1 +.names n2824gat II4392 +0 1 +.names II4392 n2821gat +0 1 +.names n1091gat n1088gat n992gat n987gat n2939gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2939gat n897gat +0 1 +.names n899gat n896gat n2938gat +1- 1 +-1 1 +.names n2938gat II4409 +0 1 +.names II4409 n2823gat +0 1 +.names n2823gat II4412 +0 1 +.names II4412 n2820gat +0 1 +.names n1098gat n1090gat n986gat n885gat n2932gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2932gat n894gat +0 1 +.names n901gat n893gat n2936gat +1- 1 +-1 1 +.names n2936gat II4429 +0 1 +.names II4429 n2829gat +0 1 +.names n2829gat II4432 +0 1 +.names II4432 n2826gat +0 1 +.names n1097gat n1089gat n1087gat n991gat n2948gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n2948gat n1180gat +0 1 +.names n1177gat n1115gat n2955gat +1- 1 +-1 1 +.names n2955gat II4449 +0 1 +.names II4449 n2828gat +0 1 +.names n2828gat II4452 +0 1 +.names II4452 n2825gat +0 1 +.names n673gat n671gat +0 1 +.names n523gat n633gat n524gat n631gat +000 1 +.names n631gat n628gat +0 1 +.names n628gat n976gat +0 1 +.names n1004gat n1000gat n2951gat +1- 1 +-1 1 +.names n2951gat II4475 +0 1 +.names II4475 n2807gat +0 1 +.names n2807gat II4478 +0 1 +.names II4478 n2803gat +0 1 +.names n2389gat n2127gat +0 1 +.names n2127gat II4482 +0 1 +.names II4482 n2682gat +0 1 +.names n2682gat II4485 +0 1 +.names II4485 n2678gat +0 1 +.names n2269gat n2046gat +0 1 +.names n2046gat II4489 +0 1 +.names II4489 n2681gat +0 1 +.names n2681gat II4492 +0 1 +.names II4492 n2677gat +0 1 +.names n2338gat n1708gat +0 1 +.names n1708gat II4496 +0 1 +.names II4496 n2688gat +0 1 +.names n2688gat II4499 +0 1 +.names II4499 n2686gat +0 1 +.names n290gat n292gat n291gat +00 1 +.names n291gat n455gat +0 1 +.names n2646gat n2237gat +0 1 +.names n1029gat n2237gat n2764gat +1- 1 +-1 1 +.names n2764gat II4506 +0 1 +.names II4506 n2763gat +0 1 +.names n2971gat n1782gat +0 1 +.names n1028gat n1782gat n2762gat +1- 1 +-1 1 +.names n2762gat II4512 +0 1 +.names II4512 n2760gat +0 1 +.names n3010gat n2325gat +0 1 +.names n1031gat n2325gat n2761gat +1- 1 +-1 1 +.names n2761gat II4518 +0 1 +.names II4518 n2759gat +0 1 +.names n504gat n2245gat +0 1 +.names n1030gat n2245gat n2757gat +1- 1 +-1 1 +.names n2757gat II4524 +0 1 +.names II4524 n2754gat +0 1 +.names n567gat n2244gat +0 1 +.names n1011gat n2244gat n2756gat +1- 1 +-1 1 +.names n2756gat II4530 +0 1 +.names II4530 n2753gat +0 1 +.names n55gat n2243gat +0 1 +.names n1181gat n2243gat n2750gat +1- 1 +-1 1 +.names n2750gat II4536 +0 1 +.names II4536 n2746gat +0 1 +.names n933gat n2246gat +0 1 +.names n1010gat n2246gat n2749gat +1- 1 +-1 1 +.names n2749gat II4542 +0 1 +.names II4542 n2745gat +0 1 +.names n43gat n2384gat +0 1 +.names n1005gat n2384gat n2742gat +1- 1 +-1 1 +.names n2742gat II4548 +0 1 +.names II4548 n2738gat +0 1 +.names n748gat n2385gat +0 1 +.names n1182gat n2385gat n2741gat +1- 1 +-1 1 +.names n2741gat II4554 +0 1 +.names II4554 n2737gat +0 1 +.names n1269gat n1286gat +0 1 +.names n1286gat II4558 +0 1 +.names II4558 n2687gat +0 1 +.names n2687gat n2685gat +0 1 +.names n1224gat n1328gat +0 1 +.names n1328gat n1381gat +0 1 +.names n2184gat n1384gat +0 1 +.names n1381gat n1384gat n2694gat +1- 1 +-1 1 +.names n2694gat II4566 +0 1 +.names II4566 n2690gat +0 1 +.names n1280gat n1382gat +0 1 +.names n1382gat n1451gat +0 1 +.names n2187gat n1453gat +0 1 +.names n1451gat n1453gat n2693gat +1- 1 +-1 1 +.names n2693gat II4573 +0 1 +.names II4573 n2689gat +0 1 +.names n1133gat n927gat +0 1 +.names n927gat n925gat +0 1 +.names n2049gat n1452gat +0 1 +.names n925gat n1452gat n2702gat +1- 1 +-1 1 +.names n2702gat II4580 +0 1 +.names II4580 n2698gat +0 1 +.names n1043gat n923gat +0 1 +.names n923gat n921gat +0 1 +.names n2328gat n1890gat +0 1 +.names n921gat n1890gat n2701gat +1- 1 +-1 1 +.names n2701gat II4587 +0 1 +.names II4587 n2697gat +0 1 +.names n929gat n850gat +0 1 +.names n850gat n739gat +0 1 +.names n2058gat n1841gat +0 1 +.names n739gat n1841gat n2709gat +1- 1 +-1 1 +.names n2709gat II4594 +0 1 +.names II4594 n2706gat +0 1 +.names n1119gat n922gat +0 1 +.names n922gat n848gat +0 1 +.names n2209gat n2047gat +0 1 +.names n848gat n2047gat n2708gat +1- 1 +-1 1 +.names n2708gat II4601 +0 1 +.names II4601 n2705gat +0 1 +.names n1070gat n924gat +0 1 +.names n924gat n849gat +0 1 +.names n2146gat n2050gat +0 1 +.names n849gat n2050gat n2799gat +1- 1 +-1 1 +.names n2799gat II4608 +0 1 +.names II4608 n2796gat +0 1 +.names n1033gat n1118gat +0 1 +.names n1118gat n1032gat +0 1 +.names n2281gat n2054gat +0 1 +.names n1032gat n2054gat n2798gat +1- 1 +-1 1 +.names n2798gat II4615 +0 1 +.names II4615 n2795gat +0 1 +.names n1869gat n1757gat n1745gat +00 1 +.names n1745gat II4620 +0 1 +.names II4620 n2806gat +0 1 +.names n2806gat II4623 +0 1 +.names II4623 n2802gat +0 1 +.names n1871gat II4626 +0 1 +.names II4626 n1870gat +0 1 +.names n1870gat n1086gat +0 1 +.names n1086gat II4630 +0 1 +.names II4630 n2805gat +0 1 +.names n2805gat II4633 +0 1 +.names II4633 n2801gat +0 1 +.names n17gat n294gat n637gat n85gat +000 1 +.names n85gat n67gat +0 1 +.names n286gat n188gat n287gat n180gat +000 1 +.names n180gat n71gat +0 1 +.names n1892gat n1840gat +0 1 +.names n73gat n70gat n1840gat n2812gat +1-- 1 +-1- 1 +--1 1 +.names n2812gat II4642 +0 1 +.names II4642 n2809gat +0 1 +.names n16gat n295gat n637gat n82gat +000 1 +.names n82gat n76gat +0 1 +.names n189gat n287gat n288gat n186gat +000 1 +.names n186gat n14gat +0 1 +.names n1711gat n1842gat +0 1 +.names n77gat n13gat n1842gat n2822gat +1-- 1 +-1- 1 +--1 1 +.names n2822gat II4651 +0 1 +.names II4651 n2819gat +0 1 +.names n2819gat II4654 +0 1 +.names n2809gat II4657 +0 1 +.names n2801gat II4660 +0 1 +.names n2802gat II4663 +0 1 +.names n2795gat II4666 +0 1 +.names n2796gat II4669 +0 1 +.names n2705gat II4672 +0 1 +.names n2706gat II4675 +0 1 +.names n2697gat II4678 +0 1 +.names n2698gat II4681 +0 1 +.names n2689gat II4684 +0 1 +.names n2690gat II4687 +0 1 +.names n2685gat II4690 +0 1 +.names n2737gat II4693 +0 1 +.names n2738gat II4696 +0 1 +.names n2745gat II4699 +0 1 +.names n2746gat II4702 +0 1 +.names n2753gat II4705 +0 1 +.names n2754gat II4708 +0 1 +.names n2759gat II4711 +0 1 +.names n2760gat II4714 +0 1 +.names n2763gat II4717 +0 1 +.names n2686gat II4720 +0 1 +.names n2677gat II4723 +0 1 +.names n2678gat II4726 +0 1 +.names n2803gat II4729 +0 1 +.names n2825gat II4732 +0 1 +.names n2826gat II4735 +0 1 +.names n2820gat II4738 +0 1 +.names n2821gat II4741 +0 1 +.names n2815gat II4744 +0 1 +.names n2816gat II4747 +0 1 +.names n2810gat II4750 +0 1 +.names n2811gat II4753 +0 1 +.names n2804gat II4756 +0 1 +.names n2739gat II4759 +0 1 +.names n2747gat II4762 +0 1 +.names n2748gat II4765 +0 1 +.names n2755gat II4768 +0 1 +.names n2797gat II4771 +0 1 +.names n2740gat II4774 +0 1 +.names n2699gat II4777 +0 1 +.names n2691gat II4780 +0 1 +.names n2827gat II4783 +0 1 +.names n2679gat II4786 +0 1 +.names n2692gat II4789 +0 1 +.names n2680gat II4792 +0 1 +.names n2700gat II4795 +0 1 +.names n2707gat II4798 +0 1 +.names n373gat n2669gat n648gat +00 1 +.names n2844gat n856gat n442gat +00 1 +.names n1218gat n1219gat n1220gat n1214gat +000 1 +.names n1218gat n1221gat n1222gat n1215gat +000 1 +.names n1223gat n1219gat n1222gat n1216gat +000 1 +.names n1223gat n1221gat n1220gat n1217gat +000 1 +.names n2716gat n2867gat n745gat +00 1 +.names n2715gat n2868gat n638gat +00 1 +.names n2724gat n2726gat n423gat +00 1 +.names n2723gat n2727gat n362gat +00 1 +.names n753gat n754gat n755gat n749gat +000 1 +.names n753gat n756gat n757gat n750gat +000 1 +.names n758gat n754gat n757gat n751gat +000 1 +.names n758gat n756gat n755gat n752gat +000 1 +.names n263gat n264gat n265gat n259gat +000 1 +.names n263gat n266gat n267gat n260gat +000 1 +.names n268gat n264gat n267gat n261gat +000 1 +.names n268gat n266gat n265gat n262gat +000 1 +.names n1018gat n1019gat n1020gat n1014gat +000 1 +.names n1018gat n1021gat n1022gat n1015gat +000 1 +.names n1023gat n1019gat n1022gat n1016gat +000 1 +.names n1023gat n1021gat n1020gat n1017gat +000 1 +.names n480gat n481gat n482gat n476gat +000 1 +.names n480gat n483gat n484gat n477gat +000 1 +.names n485gat n481gat n484gat n478gat +000 1 +.names n485gat n483gat n482gat n479gat +000 1 +.names n48gat n49gat n50gat n44gat +000 1 +.names n48gat n51gat n52gat n45gat +000 1 +.names n53gat n49gat n52gat n46gat +000 1 +.names n53gat n51gat n50gat n47gat +000 1 +.names n172gat n173gat n174gat n168gat +000 1 +.names n172gat n175gat n176gat n169gat +000 1 +.names n177gat n173gat n176gat n170gat +000 1 +.names n177gat n175gat n174gat n171gat +000 1 +.names n911gat n912gat n913gat n907gat +000 1 +.names n911gat n914gat n915gat n908gat +000 1 +.names n916gat n912gat n915gat n909gat +000 1 +.names n916gat n914gat n913gat n910gat +000 1 +.names n348gat n349gat n350gat n344gat +000 1 +.names n348gat n351gat n352gat n345gat +000 1 +.names n353gat n349gat n352gat n346gat +000 1 +.names n353gat n351gat n350gat n347gat +000 1 +.names n60gat n61gat n62gat n56gat +000 1 +.names n60gat n63gat n64gat n57gat +000 1 +.names n65gat n61gat n64gat n58gat +000 1 +.names n65gat n63gat n62gat n59gat +000 1 +.names n373gat n2731gat n768gat +00 1 +.names n856gat n2718gat n655gat +00 1 +.names n856gat n2838gat n963gat +00 1 +.names n2775gat n373gat n868gat +00 1 +.names n856gat n2711gat n962gat +00 1 +.names n373gat n2734gat n959gat +00 1 +.names n949gat n950gat n951gat n945gat +000 1 +.names n949gat n952gat n953gat n946gat +000 1 +.names n954gat n950gat n953gat n947gat +000 1 +.names n954gat n952gat n951gat n948gat +000 1 +.names n2792gat n373gat n647gat +00 1 +.names n856gat n2846gat n441gat +00 1 +.names n373gat n2672gat n967gat +00 1 +.names n2852gat n856gat n792gat +00 1 +.names n1233gat n1234gat n1235gat n1229gat +000 1 +.names n1233gat n1236gat n1237gat n1230gat +000 1 +.names n1238gat n1234gat n1237gat n1231gat +000 1 +.names n1238gat n1236gat n1235gat n1232gat +000 1 +.names n2778gat n373gat n443gat +00 1 +.names n856gat n2836gat n439gat +00 1 +.names n2789gat n373gat n966gat +00 1 +.names n856gat n2840gat n790gat +00 1 +.names n373gat n2781gat n444gat +00 1 +.names n856gat n2842gat n440gat +00 1 +.names n1055gat n1056gat n1057gat n1051gat +000 1 +.names n1055gat n1058gat n1059gat n1052gat +000 1 +.names n1060gat n1056gat n1059gat n1053gat +000 1 +.names n1060gat n1058gat n1057gat n1054gat +000 1 +.names n938gat n939gat n940gat n934gat +000 1 +.names n938gat n941gat n942gat n935gat +000 1 +.names n943gat n939gat n942gat n936gat +000 1 +.names n943gat n941gat n940gat n937gat +000 1 +.names n714gat n715gat n716gat n710gat +000 1 +.names n714gat n717gat n718gat n711gat +000 1 +.names n719gat n715gat n718gat n712gat +000 1 +.names n719gat n717gat n716gat n713gat +000 1 +.names n733gat n734gat n735gat n729gat +000 1 +.names n733gat n736gat n737gat n730gat +000 1 +.names n738gat n734gat n737gat n731gat +000 1 +.names n738gat n736gat n735gat n732gat +000 1 +.names n498gat n499gat n500gat n494gat +000 1 +.names n498gat n501gat n502gat n495gat +000 1 +.names n503gat n499gat n502gat n496gat +000 1 +.names n503gat n501gat n500gat n497gat +000 1 +.names n509gat n510gat n511gat n505gat +000 1 +.names n509gat n512gat n513gat n506gat +000 1 +.names n514gat n510gat n513gat n507gat +000 1 +.names n514gat n512gat n511gat n508gat +000 1 +.names n2860gat n2855gat n2863gat II1277 +1-- 1 +-1- 1 +--1 1 +.names n219gat n2731gat n767gat +00 1 +.names n2718gat n111gat n653gat +00 1 +.names n219gat n2775gat n867gat +00 1 +.names n2838gat n111gat n771gat +00 1 +.names n111gat n2711gat n964gat +00 1 +.names n219gat n2734gat n961gat +00 1 +.names n808gat n809gat n810gat n804gat +000 1 +.names n808gat n811gat n812gat n805gat +000 1 +.names n813gat n809gat n812gat n806gat +000 1 +.names n813gat n811gat n810gat n807gat +000 1 +.names n591gat n592gat n593gat n587gat +000 1 +.names n591gat n594gat n595gat n588gat +000 1 +.names n596gat n592gat n595gat n589gat +000 1 +.names n596gat n594gat n593gat n590gat +000 1 +.names n2836gat n111gat n447gat +00 1 +.names n2778gat n219gat n445gat +00 1 +.names n691gat n692gat n693gat n687gat +000 1 +.names n691gat n694gat n695gat n688gat +000 1 +.names n696gat n692gat n695gat n689gat +000 1 +.names n696gat n694gat n693gat n690gat +000 1 +.names n572gat n573gat n574gat n568gat +000 1 +.names n572gat n575gat n576gat n569gat +000 1 +.names n577gat n573gat n576gat n570gat +000 1 +.names n577gat n575gat n574gat n571gat +000 1 +.names n2474gat n2524gat n2831gat II1515 +1-- 1 +-1- 1 +--1 1 +.names n2353gat n2284gat n2354gat II1584 +1-- 1 +-1- 1 +--1 1 +.names n1879gat n1762gat n1692gat +00 1 +.names n2354gat n2353gat n2214gat II1723 +1-- 1 +-1- 1 +--1 1 +.names n2433gat n2427gat n2428gat +00 1 +.names n2286gat n2428gat n2289gat II1733 +1-- 1 +-1- 1 +--1 1 +.names n93gat n2731gat n769gat +00 1 +.names n93gat n2775gat n1076gat +00 1 +.names n93gat n2734gat n766gat +00 1 +.names n1189gat n1190gat n1191gat n1185gat +000 1 +.names n1189gat n1192gat n1193gat n1186gat +000 1 +.names n1194gat n1190gat n1193gat n1187gat +000 1 +.names n1194gat n1192gat n1191gat n1188gat +000 1 +.names n2792gat n93gat n645gat +00 1 +.names n93gat n2669gat n646gat +00 1 +.names n1280gat n1225gat n1383gat +00 1 +.names n1281gat n1224gat n1327gat +00 1 +.names n93gat n2778gat n651gat +00 1 +.names n2789gat n93gat n652gat +00 1 +.names n2781gat n93gat n765gat +00 1 +.names n1206gat n1207gat n1208gat n1202gat +000 1 +.names n1206gat n1209gat n1210gat n1203gat +000 1 +.names n1211gat n1207gat n1210gat n1204gat +000 1 +.names n1211gat n1209gat n1208gat n1205gat +000 1 +.names n1274gat n1275gat n1276gat n1270gat +000 1 +.names n1274gat n1277gat n1278gat n1271gat +000 1 +.names n1279gat n1275gat n1278gat n1272gat +000 1 +.names n1279gat n1277gat n1276gat n1273gat +000 1 +.names n2672gat n93gat n763gat +00 1 +.names n1284gat n1195gat n1287gat +00 1 +.names n1196gat n1269gat n1285gat +00 1 +.names n2852gat n851gat n793gat +00 1 +.names n2672gat n852gat n556gat +00 1 +.names n2731gat n852gat n795gat +00 1 +.names n851gat n2718gat n656gat +00 1 +.names n852gat n2775gat n794gat +00 1 +.names n851gat n2838gat n773gat +00 1 +.names n2711gat n851gat n965gat +00 1 +.names n2734gat n852gat n960gat +00 1 +.names n784gat n785gat n786gat n780gat +000 1 +.names n784gat n787gat n788gat n781gat +000 1 +.names n789gat n785gat n788gat n782gat +000 1 +.names n789gat n787gat n786gat n783gat +000 1 +.names n852gat n2792gat n555gat +00 1 +.names n851gat n2846gat n450gat +00 1 +.names n851gat n2844gat n654gat +00 1 +.names n2669gat n852gat n557gat +00 1 +.names n559gat n365gat n874gat +00 1 +.names n560gat n364gat n132gat +00 1 +.names n2778gat n852gat n649gat +00 1 +.names n2836gat n851gat n449gat +00 1 +.names n851gat n2840gat n791gat +00 1 +.names n852gat n2789gat n650gat +00 1 +.names n2842gat n851gat n774gat +00 1 +.names n852gat n2781gat n764gat +00 1 +.names n226gat n227gat n228gat n222gat +000 1 +.names n226gat n229gat n230gat n223gat +000 1 +.names n231gat n227gat n230gat n224gat +000 1 +.names n231gat n229gat n228gat n225gat +000 1 +.names n125gat n126gat n127gat n121gat +000 1 +.names n125gat n128gat n129gat n122gat +000 1 +.names n130gat n126gat n129gat n123gat +000 1 +.names n130gat n128gat n127gat n124gat +000 1 +.names n666gat n120gat n2460gat +00 1 +.names n665gat n1601gat n2423gat +00 1 +.names n2573gat n2574gat n2575gat n2569gat +000 1 +.names n2573gat n2576gat n2577gat n2570gat +000 1 +.names n2578gat n2574gat n2577gat n2571gat +000 1 +.names n2578gat n2576gat n2575gat n2572gat +000 1 +.names n2414gat n2415gat n2416gat n2410gat +000 1 +.names n2414gat n2417gat n2418gat n2411gat +000 1 +.names n2419gat n2415gat n2418gat n2412gat +000 1 +.names n2419gat n2417gat n2416gat n2413gat +000 1 +.names n2582gat n2583gat n2580gat +00 1 +.names n2583gat n2585gat n2581gat +00 1 +.names n2493gat n2388gat n2567gat +00 1 +.names n2389gat n2494gat n2499gat +00 1 +.names n2268gat n2338gat n299gat +00 1 +.names n2337gat n2269gat n207gat +00 1 +.names n2649gat n2650gat n2647gat +00 1 +.names n2650gat n2652gat n2648gat +00 1 +.names n2606gat n2607gat n2608gat n2602gat +000 1 +.names n2606gat n2609gat n2610gat n2603gat +000 1 +.names n2611gat n2607gat n2610gat n2604gat +000 1 +.names n2611gat n2609gat n2608gat n2605gat +000 1 +.names n2550gat n2551gat n2552gat n2546gat +000 1 +.names n2550gat n2553gat n2554gat n2547gat +000 1 +.names n2555gat n2551gat n2554gat n2548gat +000 1 +.names n2555gat n2553gat n2552gat n2549gat +000 1 +.names n2616gat n2617gat n2614gat +00 1 +.names n2617gat n2619gat n2615gat +00 1 +.names n120gat n2666gat n2461gat +00 1 +.names n1601gat n1704gat n2421gat +00 1 +.names n1414gat n566gat n1153gat +00 1 +.names n1301gat n1150gat n1151gat +00 1 +.names n873gat n1478gat n982gat +00 1 +.names n875gat n876gat n877gat +00 1 +.names n1153gat n1151gat n982gat n877gat n2930gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1160gat n1084gat n1159gat +00 1 +.names n983gat n1157gat n1158gat +00 1 +.names n985gat n1307gat n1156gat +00 1 +.names n1085gat n1348gat n1155gat +00 1 +.names n1159gat n1158gat n1156gat n1155gat n2957gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1442gat n706gat n1443gat +00 1 +.names n1444gat n164gat n1325gat +00 1 +.names n1442gat n837gat n1321gat +00 1 +.names n1444gat n278gat n1320gat +00 1 +.names n1442gat n613gat n1368gat +00 1 +.names n274gat n1444gat n1258gat +00 1 +.names n833gat n1442gat n1373gat +00 1 +.names n282gat n1444gat n1372gat +00 1 +.names n1437gat n1378gat n1441gat +00 1 +.names n1322gat n1439gat n1440gat +00 1 +.names n1370gat n1369gat n1371gat +00 1 +.names n1366gat n1374gat n1367gat +00 1 +.names n1441gat n1440gat n1371gat n1367gat n2978gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1450gat n1498gat n1504gat +00 1 +.names n1607gat n1449gat n1502gat +00 1 +.names n1504gat n1502gat n2982gat +1- 1 +-1 1 +.names n1603gat n815gat n1250gat +00 1 +.names n956gat n1590gat n1103gat +00 1 +.names n1590gat n1067gat n1304gat +00 1 +.names n679gat n1603gat n1249gat +00 1 +.names n864gat n1590gat n1246gat +00 1 +.names n583gat n1603gat n1161gat +00 1 +.names n1603gat n579gat n1291gat +00 1 +.names n1590gat n860gat n1245gat +00 1 +.names n1248gat n1418gat n1352gat +00 1 +.names n1306gat n1353gat n1351gat +00 1 +.names n1247gat n1355gat n1303gat +00 1 +.names n1300gat n1487gat n1302gat +00 1 +.names n1352gat n1351gat n1303gat n1302gat n2973gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n882gat n1603gat n1163gat +00 1 +.names n1297gat n1590gat n1102gat +00 1 +.names n1590gat n1293gat n1101gat +00 1 +.names n1603gat n823gat n996gat +00 1 +.names n1079gat n1590gat n1104gat +00 1 +.names n1603gat n683gat n887gat +00 1 +.names n1147gat n1590gat n1305gat +00 1 +.names n698gat n1603gat n1162gat +00 1 +.names n1164gat n1356gat n1360gat +00 1 +.names n1436gat n1106gat n1359gat +00 1 +.names n1425gat n1105gat n1358gat +00 1 +.names n1424gat n1309gat n1357gat +00 1 +.names n1360gat n1359gat n1358gat n1357gat n2977gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1788gat n1786gat n1839gat II2720 +1-- 1 +-1- 1 +--1 1 +.names n1788gat n1884gat n1633gat II2735 +1-- 1 +-1- 1 +--1 1 +.names n1705gat n3028gat n1703gat +00 1 +.names n3026gat n1779gat n1778gat +00 1 +.names n1703gat n1704gat n1778gat II2812 +1-- 1 +-1- 1 +--1 1 +.names n1503gat n3025gat n1609gat +00 1 +.names n1839gat n1786gat n1788gat II2831 +1-- 1 +-1- 1 +--1 1 +.names n1784gat n1633gat n1884gat II2889 +1-- 1 +-1- 1 +--1 1 +.names n1784gat n1785gat n1633gat II2925 +1-- 1 +-1- 1 +--1 1 +.names n1784gat n1839gat n1788gat II2934 +1-- 1 +-1- 1 +--1 1 +.names n1673gat n1572gat n1733gat +00 1 +.names n1858gat n1580gat n1581gat +00 1 +.names n2078gat n2178gat n1990gat n2128gat n2079gat +0000 1 +.names n2078gat n1990gat n2181gat n2073gat +000 1 +.names n1719gat n1673gat n1444gat n1574gat +000 1 +.names n1444gat n1858gat n1635gat n1573gat +000 1 +.names n1659gat n1722gat n1724gat n1723gat +000 1 +.names n1656gat n1659gat n1554gat n1647gat +000 1 +.names n1569gat n1659gat n1566gat n1646gat +000 1 +.names n1723gat n1647gat n1646gat n2992gat +1-- 1 +-1- 1 +--1 1 +.names n1727gat n1659gat n1640gat n1650gat +000 1 +.names n1560gat n1659gat n1730gat n1649gat +000 1 +.names n1561gat n1562gat n1659gat n1563gat +000 1 +.names n1650gat n1649gat n1563gat n2986gat +1-- 1 +-1- 1 +--1 1 +.names n1671gat n1659gat n1654gat +00 1 +.names n1651gat n1652gat n1659gat n1653gat +000 1 +.names n1643gat n1648gat n1659gat n1644gat +000 1 +.names n1654gat n1653gat n1644gat n2991gat +1-- 1 +-1- 1 +--1 1 +.names n1839gat n1884gat n1784gat II3148 +1-- 1 +-1- 1 +--1 1 +.names n1838gat n1785gat n1788gat II3178 +1-- 1 +-1- 1 +--1 1 +.names n1869gat n672gat n2591gat n1413gat +000 1 +.names n1507gat n1396gat n1393gat n1408gat +000 1 +.names n1393gat n1409gat n1677gat n1407gat +000 1 +.names n1413gat n1408gat n1407gat n2981gat +1-- 1 +-1- 1 +--1 1 +.names n2260gat n2189gat n2258gat +00 1 +.names n2261gat n2188gat n2255gat +00 1 +.names n2133gat n2131gat n2132gat +00 1 +.names n2134gat n2185gat n2130gat +00 1 +.names n2248gat n2264gat n2250gat +00 1 +.names n2265gat n3006gat n2249gat +00 1 +.names n2250gat n2249gat n3007gat +1- 1 +-1 1 +.names n1709gat n1629gat n1710gat +00 1 +.names n1895gat n1631gat n1630gat +00 1 +.names n1968gat n1891gat n1969gat n1894gat +000 1 +.names n1958gat n1845gat n1847gat +00 1 +.names n1845gat n1893gat n1846gat +00 1 +.names n1891gat n1958gat n2055gat +00 1 +.names n1893gat n1968gat n1967gat +00 1 +.names n1956gat n1963gat n1959gat +00 1 +.names n1886gat n1887gat n1957gat +00 1 +.names n2193gat n2402gat n2211gat +00 1 +.names n2401gat n2151gat n2210gat +00 1 +.names n2393gat n2438gat n2053gat +00 1 +.names n2392gat n2439gat n1964gat +00 1 +.names n2405gat n2349gat n2350gat +00 1 +.names n2406gat n2215gat n2282gat +00 1 +.names n2402gat n2151gat n2345gat n2213gat +000 1 +.names n2401gat n2346gat n2150gat +00 1 +.names n2193gat n2346gat n2149gat +00 1 +.names n1963gat n1893gat n1962gat +00 1 +.names n1962gat n1955gat n2995gat +1- 1 +-1 1 +.names n1974gat n1970gat n1972gat +00 1 +.names n1896gat n1973gat n1971gat +00 1 +.names n1972gat n1971gat n2999gat +1- 1 +-1 1 +.names n2393gat n2401gat n2331gat +00 1 +.names n2333gat n2331gat n3011gat +1- 1 +-1 1 +.names n2643gat n2564gat n2566gat +00 1 +.names n2352gat n2642gat n2565gat +00 1 +.names n2566gat n2565gat n3015gat +1- 1 +-1 1 +.names n155gat n253gat n150gat n141gat +000 1 +.names n151gat n233gat n38gat +00 1 +.names n151gat n154gat n37gat +00 1 +.names n2775gat n110gat n1074gat +00 1 +.names n375gat n800gat n872gat +00 1 +.names n155gat n233gat n234gat +00 1 +.names n154gat n253gat n137gat +00 1 +.names n375gat n235gat n378gat +00 1 +.names n110gat n2778gat n377gat +00 1 +.names n329gat n387gat n334gat n250gat +000 1 +.names n386gat n330gat n249gat +00 1 +.names n330gat n1490gat n248gat +00 1 +.names n219gat n2792gat n869gat +00 1 +.names n372gat n452gat n453gat +00 1 +.names n111gat n2846gat n448gat +00 1 +.names n1490gat n387gat n251gat +00 1 +.names n334gat n386gat n244gat +00 1 +.names n2844gat n111gat n974gat +00 1 +.names n372gat n333gat n973gat +00 1 +.names n2669gat n219gat n870gat +00 1 +.names n330gat n325gat n334gat n246gat +000 1 +.names n386gat n334gat n245gat +00 1 +.names n462gat n2884gat n460gat +00 1 +.names n457gat n461gat n459gat +00 1 +.names n111gat n2852gat n975gat +00 1 +.names n372gat n458gat n972gat +00 1 +.names n219gat n2672gat n969gat +00 1 +.names n144gat n325gat n145gat +00 1 +.names n326gat n247gat n143gat +00 1 +.names n111gat n2840gat n971gat +00 1 +.names n372gat n878gat n970gat +00 1 +.names n2789gat n219gat n968gat +00 1 +.names n382gat n326gat n144gat n142gat +000 1 +.names n325gat n383gat n40gat +00 1 +.names n383gat n247gat n39gat +00 1 +.names n111gat n2842gat n772gat +00 1 +.names n134gat n372gat n451gat +00 1 +.names n219gat n2781gat n446gat +00 1 +.names n253gat n151gat n254gat n139gat +000 1 +.names n253gat n154gat n136gat +00 1 +.names n252gat n468gat n391gat +00 1 +.names n469gat n2877gat n390gat +00 1 +.names n381gat n375gat n1083gat +00 1 +.names n110gat n2672gat n1077gat +00 1 +.names n254gat n241gat n242gat +00 1 +.names n255gat n140gat n240gat +00 1 +.names n802gat n375gat n871gat +00 1 +.names n110gat n2734gat n797gat +00 1 +.names n255gat n146gat n241gat n324gat +000 1 +.names n147gat n254gat n238gat +00 1 +.names n140gat n147gat n237gat +00 1 +.names n375gat n380gat n1082gat +00 1 +.names n2731gat n110gat n796gat +00 1 +.names n1691gat n336gat n1599gat +00 1 +.names n2167gat n2031gat n2174gat II3999 +1-- 1 +-1- 1 +--1 1 +.names n1869gat n1683gat n1586gat +00 1 +.names n1769gat n1773gat n2512gat n1755gat +000 1 +.names n2443gat n2290gat n2214gat II4023 +1-- 1 +-1- 1 +--1 1 +.names n1472gat n1747gat n1470gat +00 1 +.names n1674gat n1403gat n1400gat +00 1 +.names n1806gat n1338gat n1584gat n1399gat +000 1 +.names n1455gat n1397gat n1398gat +00 1 +.names n1633gat n1838gat n1786gat II4144 +1-- 1 +-1- 1 +--1 1 +.names n2289gat n1468gat n1467gat +00 1 +.names n1392gat n1461gat n1396gat n1466gat +000 1 +.names n1774gat n1869gat n1684gat n1686gat +000 1 +.names n1524gat n1403gat n1533gat +00 1 +.names n1677gat n1458gat n1532gat +00 1 +.names n1507gat n1477gat n1531gat +00 1 +.names n1686gat n1533gat n1532gat n1531gat n2985gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1427gat n1595gat n1677gat II4216 +1-- 1 +-1- 1 +--1 1 +.names n1297gat n1111gat n1100gat +00 1 +.names n1112gat n882gat n994gat +00 1 +.names n721gat n741gat n989gat +00 1 +.names n926gat n566gat n880gat +00 1 +.names n1100gat n994gat n989gat n880gat n2931gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n1007gat n918gat n1012gat +00 1 +.names n625gat n1006gat n905gat +00 1 +.names n1012gat n905gat n2943gat +1- 1 +-1 1 +.names n420gat n879gat n1003gat +00 1 +.names n1009gat n419gat n902gat +00 1 +.names n1111gat n1293gat n1099gat +00 1 +.names n725gat n741gat n998gat +00 1 +.names n823gat n1112gat n995gat +00 1 +.names n875gat n926gat n980gat +00 1 +.names n621gat n1006gat n1175gat +00 1 +.names n845gat n1007gat n1174gat +00 1 +.names n1175gat n1174gat n2960gat +1- 1 +-1 1 +.names n420gat n1002gat n1001gat +00 1 +.names n419gat n1171gat n999gat +00 1 +.names n1007gat n401gat n1323gat +00 1 +.names n1006gat n617gat n1264gat +00 1 +.names n1323gat n1264gat n2969gat +1- 1 +-1 1 +.names n926gat n873gat n981gat +00 1 +.names n741gat n702gat n890gat +00 1 +.names n1111gat n1079gat n889gat +00 1 +.names n683gat n1112gat n886gat +00 1 +.names n419gat n1265gat n892gat +00 1 +.names n420gat n888gat n891gat +00 1 +.names n1006gat n490gat n904gat +00 1 +.names n1007gat n397gat n903gat +00 1 +.names n904gat n903gat n2942gat +1- 1 +-1 1 +.names n926gat n1150gat n1152gat +00 1 +.names n1147gat n1111gat n1092gat +00 1 +.names n741gat n393gat n997gat +00 1 +.names n1112gat n698gat n993gat +00 1 +.names n419gat n1008gat n900gat +00 1 +.names n420gat n898gat n895gat +00 1 +.names n1112gat n583gat n1094gat +00 1 +.names n1111gat n864gat n1093gat +00 1 +.names n340gat n741gat n988gat +00 1 +.names n926gat n983gat n984gat +00 1 +.names n613gat n1006gat n1267gat +00 1 +.names n1007gat n274gat n1257gat +00 1 +.names n1267gat n1257gat n2965gat +1- 1 +-1 1 +.names n420gat n1179gat n1178gat +00 1 +.names n419gat n1266gat n1116gat +00 1 +.names n1006gat n706gat n1375gat +00 1 +.names n164gat n1007gat n1324gat +00 1 +.names n1375gat n1324gat n2961gat +1- 1 +-1 1 +.names n1111gat n956gat n1091gat +00 1 +.names n1085gat n926gat n1088gat +00 1 +.names n815gat n1112gat n992gat +00 1 +.names n741gat n159gat n987gat +00 1 +.names n419gat n1172gat n899gat +00 1 +.names n897gat n420gat n896gat +00 1 +.names n837gat n1006gat n1262gat +00 1 +.names n1007gat n278gat n1260gat +00 1 +.names n1262gat n1260gat n2967gat +1- 1 +-1 1 +.names n336gat n741gat n1098gat +00 1 +.names n1111gat n860gat n1090gat +00 1 +.names n985gat n926gat n986gat +00 1 +.names n579gat n1112gat n885gat +00 1 +.names n419gat n1259gat n901gat +00 1 +.names n894gat n420gat n893gat +00 1 +.names n270gat n741gat n1097gat +00 1 +.names n1067gat n1111gat n1089gat +00 1 +.names n926gat n1084gat n1087gat +00 1 +.names n1112gat n679gat n991gat +00 1 +.names n1007gat n282gat n1326gat +00 1 +.names n833gat n1006gat n1261gat +00 1 +.names n1326gat n1261gat n2968gat +1- 1 +-1 1 +.names n1180gat n420gat n1177gat +00 1 +.names n1263gat n419gat n1115gat +00 1 +.names n670gat n671gat n977gat +00 1 +.names n977gat n976gat n2944gat +1- 1 +-1 1 +.names n819gat n1112gat n1096gat +00 1 +.names n1240gat n1111gat n1095gat +00 1 +.names n841gat n741gat n990gat +00 1 +.names n1601gat n926gat n979gat +00 1 +.names n1096gat n1095gat n990gat n979gat n2945gat +1--- 1 +-1-- 1 +--1- 1 +---1 1 +.names n829gat n1006gat n1176gat +00 1 +.names n1007gat n1025gat n1173gat +00 1 +.names n1176gat n1173gat n2962gat +1- 1 +-1 1 +.names n978gat n420gat n1004gat +00 1 +.names n419gat n1252gat n1000gat +00 1 +.names n978gat n455gat n1029gat +00 1 +.names n455gat n879gat n1028gat +00 1 +.names n1002gat n455gat n1031gat +00 1 +.names n455gat n888gat n1030gat +00 1 +.names n455gat n898gat n1011gat +00 1 +.names n455gat n1179gat n1181gat +00 1 +.names n897gat n455gat n1010gat +00 1 +.names n894gat n455gat n1005gat +00 1 +.names n1180gat n455gat n1182gat +00 1 +.names n67gat n2784gat n73gat +00 1 +.names n71gat n2720gat n70gat +00 1 +.names n76gat n2784gat n77gat +00 1 +.names n2720gat n14gat n13gat +00 1 +.names n1816gat n1828gat n1935gat +00 1 +.names n194gat n297gat n197gat +00 1 +.names n92gat n21gat n22gat +00 1 +.names n197gat n22gat n93gat +00 1 +.names n2850gat n3019gat n2239gat +00 1 +.names n2432gat n2154gat n2433gat +00 1 +.names n2426gat n2153gat n2427gat +00 1 +.names n2582gat n2585gat n2583gat +00 1 +.names n2649gat n2652gat n2650gat +00 1 +.names n2616gat n2619gat n2617gat +00 1 +.names n1592gat n2422gat n1598gat +00 1 +.names n1598gat n2930gat n2957gat n1154gat +000 1 +.names n1154gat n1608gat n1411gat +00 1 +.names n1609gat n1427gat n1498gat +00 1 +.names n2082gat n1609gat n1607gat +00 1 +.names n2978gat n2982gat n2973gat n2977gat n1428gat +0000 1 +.names n1673gat n1719gat n1794gat +00 1 +.names n1858gat n1635gat n1796gat +00 1 +.names n1794gat n1796gat n1792gat +00 1 +.names n1428gat n1387gat n1406gat +00 1 +.names n2850gat n3018gat n2664gat +00 1 +.names n1925gat n1635gat n1926gat +00 1 +.names n1917gat n1859gat n1916gat +00 1 +.names n1719gat n1922gat n1994gat +00 1 +.names n1743gat n1923gat n1924gat +00 1 +.names n1311gat n1773gat n1758gat +00 1 +.names n199gat n92gat n200gat +00 1 +.names n297gat n195gat n196gat +00 1 +.names n2016gat n2097gat n2018gat +00 1 +.names n88gat n2784gat n89gat +00 1 +.names n1334gat n1858gat n1604gat n1471gat +000 1 +.names n1476gat n1471gat n1469gat n1472gat +000 1 +.names n1685gat n1427gat n1600gat +00 1 +.names n1519gat n1401gat n1397gat +00 1 +.names n2002gat n2857gat n2005gat +00 1 +.names n1823gat n2005gat n1818gat +00 1 +.names n1584gat n1460gat n1510gat +00 1 +.names n1595gat n1454gat n1459gat +00 1 +.names n1510gat n1459gat n1458gat +00 1 +.names n1594gat n1587gat n2989gat n1602gat +000 1 +.names n374gat n2862gat n520gat +00 1 +.names n2854gat n374gat n519gat +00 1 +.names n417gat n413gat n412gat n406gat n410gat +0000 1 +.names n411gat n522gat n354gat +00 1 +.names n516gat n407gat n408gat +00 1 +.names n2859gat n740gat n526gat +00 1 +.names n740gat n2854gat n531gat +00 1 +.names n2862gat n740gat n530gat +00 1 +.names n290gat n358gat n359gat +00 1 +.names n408gat n359gat n420gat +00 1 +.names n672gat n670gat n801gat +00 1 +.names n2931gat n801gat n879gat +00 1 +.names n1123gat n1225gat n1255gat +00 1 +.names n1255gat n2943gat n1009gat +00 1 +.names n406gat n407gat n409gat +00 1 +.names n415gat n356gat n292gat +00 1 +.names n409gat n291gat n419gat +00 1 +.names n1281gat n1123gat n1243gat +00 1 +.names n2960gat n1243gat n1171gat +00 1 +.names n1123gat n1134gat n1244gat +00 1 +.names n1244gat n2969gat n1265gat +00 1 +.names n1123gat n1044gat n1254gat +00 1 +.names n2942gat n1254gat n1008gat +00 1 +.names n930gat n1123gat n1253gat +00 1 +.names n2965gat n1253gat n1266gat +00 1 +.names n1120gat n1123gat n1200gat +00 1 +.names n2961gat n1200gat n1172gat +00 1 +.names n1123gat n1071gat n1251gat +00 1 +.names n2967gat n1251gat n1259gat +00 1 +.names n1123gat n1034gat n1212gat +00 1 +.names n1212gat n2968gat n1263gat +00 1 +.names n2944gat n2945gat n978gat +00 1 +.names n1123gat n1284gat n1199gat +00 1 +.names n1199gat n2962gat n1252gat +00 1 +.names n1773gat n1769gat n1757gat +00 1 +.end diff --git a/abc70930/examples/s6669.blif b/abc70930/examples/s6669.blif new file mode 100644 index 00000000..dca3a58a --- /dev/null +++ b/abc70930/examples/s6669.blif @@ -0,0 +1,6413 @@ +# Benchmark "s6669" written by ABC on Sun Aug 14 10:43:19 2005 +.model s6669 +.inputs I2 I3 I4 I5 I6 I7 I8 I9 I10 I11 I12 I13 I14 I15 I16 I17 I18 I19 I20 \ + I21 I22 I23 I24 I25 I26 I27 I28 I29 I30 I31 I32 I33 I34 I35 I36 I37 I38 \ + I39 I40 I41 I42 I43 I44 I45 I46 I47 I48 I49 I50 I51 I52 I53 I54 I55 I56 \ + I57 I58 I59 I60 I61 I62 I63 I64 I65 I66 I67 I68 I69 I70 I71 I72 I73 I74 \ + I75 I76 I77 I78 I79 I80 I81 I82 I83 I84 +.outputs I829 I821 I823 I820 I824 I826 I822 I827 I819 I825 I831 I833 I830 \ + I834 I818 I832 I828 I93 I88 I96 I94 I98 I90 I91 I87 I89 I92 I97 I99 I100 \ + I95 I85 I86 I837 I839 I835 I840 I838 I851 I847 I846 I849 I842 I844 I850 \ + I836 I848 I845 I843 I841 I914 I913 I967 I966 I968 + +.latch I55 NODE1 0 +.latch I68 NODE3 0 +.latch I14 NODE5 0 +.latch I116 NODE7 0 +.latch I829 NODE9 0 +.latch I1397 NODE11 0 +.latch I1258 NODE13 0 +.latch I10 NODE15 0 +.latch I983 NODE17 0 +.latch I191 NODE19 0 +.latch I1660 NODE21 0 +.latch I1264 NODE23 0 +.latch I109 NODE25 0 +.latch I1007 NODE27 0 +.latch I821 NODE29 0 +.latch I867 NODE31 0 +.latch I1676 NODE33 0 +.latch I1073 NODE35 0 +.latch I823 NODE37 0 +.latch I1657 NODE39 0 +.latch I933 NODE41 0 +.latch I857 NODE43 0 +.latch I53 NODE45 0 +.latch I820 NODE47 0 +.latch I1375 NODE49 0 +.latch I1350 NODE51 0 +.latch I1033 NODE53 0 +.latch I101 NODE55 0 +.latch I972 NODE57 0 +.latch I63 NODE59 0 +.latch I3 NODE61 0 +.latch I976 NODE63 0 +.latch I335 NODE65 0 +.latch I1638 NODE67 0 +.latch I863 NODE69 0 +.latch I11 NODE71 0 +.latch I113 NODE73 0 +.latch I1124 NODE75 0 +.latch I1366 NODE77 0 +.latch I824 NODE79 0 +.latch I5 NODE81 0 +.latch I978 NODE83 0 +.latch I853 NODE85 0 +.latch I2 NODE87 0 +.latch I975 NODE89 0 +.latch I1549 NODE91 0 +.latch I64 NODE93 0 +.latch I1621 NODE95 0 +.latch I76 NODE97 0 +.latch I17 NODE99 0 +.latch I970 NODE101 0 +.latch I6 NODE103 0 +.latch I979 NODE105 0 +.latch I187 NODE107 0 +.latch I1252 NODE109 0 +.latch I1442 NODE111 0 +.latch I868 NODE113 0 +.latch I189 NODE115 0 +.latch I1372 NODE117 0 +.latch I959 NODE119 0 +.latch I1472 NODE121 0 +.latch I1329 NODE123 0 +.latch I186 NODE125 0 +.latch I1164 NODE127 0 +.latch I860 NODE129 0 +.latch I858 NODE131 0 +.latch I243 NODE133 0 +.latch I72 NODE135 0 +.latch I1387 NODE137 0 +.latch I984 NODE139 0 +.latch I1635 NODE141 0 +.latch I190 NODE143 0 +.latch I1449 NODE145 0 +.latch I866 NODE147 0 +.latch I246 NODE149 0 +.latch I1585 NODE151 0 +.latch I1024 NODE153 0 +.latch I856 NODE155 0 +.latch I1367 NODE157 0 +.latch I1514 NODE159 0 +.latch I248 NODE161 0 +.latch I1100 NODE163 0 +.latch I365 NODE165 0 +.latch I245 NODE167 0 +.latch I826 NODE169 0 +.latch I77 NODE171 0 +.latch I1606 NODE173 0 +.latch I960 NODE175 0 +.latch I190 NODE177 0 +.latch I69 NODE179 0 +.latch I1453 NODE181 0 +.latch I1443 NODE183 0 +.latch I1505 NODE185 0 +.latch I66 NODE187 0 +.latch I249 NODE189 0 +.latch I1519 NODE191 0 +.latch I1155 NODE193 0 +.latch I1040 NODE195 0 +.latch I822 NODE197 0 +.latch I8 NODE199 0 +.latch I1642 NODE201 0 +.latch I981 NODE203 0 +.latch I75 NODE205 0 +.latch I59 NODE207 0 +.latch I62 NODE209 0 +.latch I1368 NODE211 0 +.latch I61 NODE213 0 +.latch I4 NODE215 0 +.latch I977 NODE217 0 +.latch I58 NODE219 0 +.latch I1601 NODE221 0 +.latch I192 NODE223 0 +.latch I1576 NODE225 0 +.latch I749 NODE227 0 +.latch I827 NODE229 0 +.latch I1328 NODE231 0 +.latch I112 NODE233 0 +.latch I748 NODE235 0 +.latch I1571 NODE237 0 +.latch I819 NODE239 0 +.latch I186 NODE241 0 +.latch I67 NODE243 0 +.latch I56 NODE245 0 +.latch I188 NODE247 0 +.latch I1336 NODE249 0 +.latch I1346 NODE251 0 +.latch I9 NODE253 0 +.latch I982 NODE255 0 +.latch I1425 NODE257 0 +.latch I1342 NODE259 0 +.latch I1175 NODE261 0 +.latch I1671 NODE263 0 +.latch I974 NODE265 0 +.latch I825 NODE267 0 +.latch I1099 NODE269 0 +.latch I105 NODE271 0 +.latch I494 NODE273 0 +.latch I1199 NODE275 0 +.latch I1247 NODE277 0 +.latch I107 NODE279 0 +.latch I1675 NODE281 0 +.latch I65 NODE283 0 +.latch I1056 NODE285 0 +.latch I104 NODE287 0 +.latch I831 NODE289 0 +.latch I7 NODE291 0 +.latch I980 NODE293 0 +.latch I193 NODE295 0 +.latch I1604 NODE297 0 +.latch I193 NODE299 0 +.latch I1672 NODE301 0 +.latch I833 NODE303 0 +.latch I102 NODE305 0 +.latch I973 NODE307 0 +.latch I247 NODE309 0 +.latch I1456 NODE311 0 +.latch I1029 NODE313 0 +.latch I1290 NODE315 0 +.latch I1246 NODE317 0 +.latch I1057 NODE319 0 +.latch I108 NODE321 0 +.latch I830 NODE323 0 +.latch I1268 NODE325 0 +.latch I764 NODE327 0 +.latch I1582 NODE329 0 +.latch I1248 NODE331 0 +.latch I192 NODE333 0 +.latch I1673 NODE335 0 +.latch I834 NODE337 0 +.latch I191 NODE339 0 +.latch I1508 NODE341 0 +.latch I1306 NODE343 0 +.latch I996 NODE345 0 +.latch I188 NODE347 0 +.latch I13 NODE349 0 +.latch I115 NODE351 0 +.latch I780 NODE353 0 +.latch I15 NODE355 0 +.latch I117 NODE357 0 +.latch I1289 NODE359 0 +.latch I818 NODE361 0 +.latch I244 NODE363 0 +.latch I1615 NODE365 0 +.latch I12 NODE367 0 +.latch I114 NODE369 0 +.latch I1674 NODE371 0 +.latch I901 NODE373 0 +.latch I859 NODE375 0 +.latch I1663 NODE377 0 +.latch I1374 NODE379 0 +.latch I60 NODE381 0 +.latch I16 NODE383 0 +.latch I969 NODE385 0 +.latch I1645 NODE387 0 +.latch I1411 NODE389 0 +.latch I1539 NODE391 0 +.latch I250 NODE393 0 +.latch I1200 NODE395 0 +.latch I862 NODE397 0 +.latch I1607 NODE399 0 +.latch I1662 NODE401 0 +.latch I852 NODE403 0 +.latch I864 NODE405 0 +.latch I1288 NODE407 0 +.latch I110 NODE409 0 +.latch I861 NODE411 0 +.latch I189 NODE413 0 +.latch I854 NODE415 0 +.latch I78 NODE417 0 +.latch I57 NODE419 0 +.latch I985 NODE421 0 +.latch I54 NODE423 0 +.latch I865 NODE425 0 +.latch I1410 NODE427 0 +.latch I1154 NODE429 0 +.latch I106 NODE431 0 +.latch I1330 NODE433 0 +.latch I1379 NODE435 0 +.latch I1170 NODE437 0 +.latch I855 NODE439 0 +.latch I1471 NODE441 0 +.latch I187 NODE443 0 +.latch I71 NODE445 0 +.latch I1386 NODE447 0 +.latch I832 NODE449 0 +.latch I73 NODE451 0 +.latch I1220 NODE453 0 +.latch I429 NODE455 0 +.latch I70 NODE457 0 +.latch I1504 NODE459 0 +.latch I18 NODE461 0 +.latch I971 NODE463 0 +.latch I1302 NODE465 0 +.latch I111 NODE467 0 +.latch I988 NODE469 0 +.latch I828 NODE471 0 +.latch I1023 NODE473 0 +.latch I103 NODE475 0 +.latch I74 NODE477 0 + +.names NODE99 I116 +0 1 +.names I684 I685 I829 +00 0 +.names ZI361_563 ZI1389_563 I1397 +00 0 +.names ZI463_471 ZI1235_471 I1258 +00 0 +.names I744 I929 I983 +00 0 +.names NODE219 I191 +0 1 +.names ZI427_737 ZI1650_737 I1660 +00 0 +.names ZI236_477 ZI1245_477 I1264 +00 0 +.names NODE15 I109 +0 1 +.names ZI341_305 ZI986_305 I1007 +00 0 +.names I668 I669 I821 +00 0 +.names I654 I655 I657 I656 I867 +0000 0 +.names I1671 I511 I1676 +11 1 +.names ZI345_349 ZI1060_349 I1073 +00 0 +.names I672 I673 I823 +00 0 +.names ZI556_735 ZI1646_735 I1657 +00 0 +.names ZI339_263 ZI869_263 I933 +00 0 +.names I614 I615 I617 I616 I857 +0000 0 +.names I666 I667 I820 +00 0 +.names ZI242_549 ZI1365_549 I1375 +00 0 +.names ZI357_535 ZI1332_535 I1350 +00 0 +.names ZI439_323 ZI1017_323 I1033 +00 0 +.names NODE87 I101 +0 1 +.names I733 I918 I972 +00 0 +.names I737 I922 I976 +00 0 +.names ZI169_6 ZI135_6 I335 +00 0 +.names ZI425_723 ZI1625_723 I1638 +00 0 +.names I638 I639 I641 I640 I863 +0000 0 +.names NODE5 I113 +0 1 +.names ZI347_387 ZI1103_387 I1124 +00 0 +.names ZI241_541 ZI1345_541 I1366 +00 0 +.names I674 I675 I824 +00 0 +.names I739 I924 I978 +00 0 +.names I598 I599 I601 I600 I853 +0000 0 +.names I736 I921 I975 +00 0 +.names I1539 I511 I1549 +11 1 +.names I1615 I511 I1621 +11 1 +.names I731 I916 I970 +00 0 +.names I740 I925 I979 +00 0 +.names NODE423 I187 +0 1 +.names ZI399_465 ZI1223_465 I1252 +00 0 +.names I796 I1422 I1442 +00 0 +.names I658 I659 I661 I660 I868 +0000 0 +.names NODE245 I189 +0 1 +.names ZI407_545 ZI1354_545 I1372 +00 0 +.names ZI498_281 ZI900_281 I959 +00 0 +.names ZI542_613 ZI1455_613 I1472 +00 0 +.names I792 I1303 I1329 +00 0 +.names NODE45 I186 +0 1 +.names ZI397_409 ZI1137_409 I1164 +00 0 +.names I626 I627 I628 I629 I860 +0000 0 +.names I618 I619 I620 I621 I858 +0000 0 +.names NODE455 I243 +0 1 +.names ZI536_557 ZI1377_557 I1387 +00 0 +.names I745 I930 I984 +00 0 +.names ZI554_721 ZI1622_721 I1635 +00 0 +.names NODE419 I190 +0 1 +.names ZI413_597 ZI1433_597 I1449 +00 0 +.names I650 I651 I652 I653 I866 +0000 0 +.names NODE53 I246 +0 1 +.names I1571 I511 I1585 +11 1 +.names I785 I1004 I1024 +00 0 +.names I610 I611 I612 I613 I856 +0000 0 +.names I793 I1347 I1367 +00 0 +.names ZI479_643 ZI1496_643 I1514 +00 0 +.names NODE13 I248 +0 1 +.names I787 I1070 I1100 +00 0 +.names I203 I195 I365 +11 1 +.names NODE345 I245 +0 1 +.names I678 I679 I826 +00 0 +.names ZI487_701 ZI1597_701 I1606 +00 0 +.names I783 I902 I960 +00 0 +.names ZI477_601 ZI1441_601 I1453 +00 0 +.names ZI540_593 ZI1423_593 I1443 +00 0 +.names ZI544_635 ZI1483_635 I1505 +00 0 +.names NODE259 I249 +0 1 +.names I1505 I511 I1519 +11 1 +.names I788 I1121 I1155 +00 0 +.names ZI343_327 ZI1027_327 I1040 +00 0 +.names I670 I671 I822 +00 0 +.names ZI489_727 ZI1631_727 I1642 +00 0 +.names I742 I927 I981 +00 0 +.names ZI534_543 ZI1348_543 I1368 +00 0 +.names I738 I923 I977 +00 0 +.names ZI550_697 ZI1586_697 I1601 +00 0 +.names NODE207 I192 +0 1 +.names ZI421_683 ZI1556_683 I1576 +00 0 +.names ZI367_177 ZI366_177 I749 +00 0 +.names I680 I681 I827 +00 0 +.names ZI239_517 ZI1301_517 I1328 +00 0 +.names NODE349 I112 +0 1 +.names ZI334_175 ZI337_175 I748 +00 0 +.names ZI548_679 ZI1550_679 I1571 +00 0 +.names I664 I665 I819 +00 0 +.names NODE1 I188 +0 1 +.names ZI405_523 ZI1312_523 I1336 +00 0 +.names ZI240_533 ZI1327_533 I1346 +00 0 +.names I743 I928 I982 +00 0 +.names ZI363_583 ZI1413_583 I1425 +00 0 +.names ZI469_529 ZI1322_529 I1342 +00 0 +.names ZI349_417 ZI1158_417 I1175 +00 0 +.names ZI557_745 ZI1664_745 I1671 +00 0 +.names I735 I920 I974 +00 0 +.names I676 I677 I825 +00 0 +.names ZI504_367 ZI1069_367 I1099 +00 0 +.names NODE103 I105 +0 1 +.names ZI251_38 ZI227_38 I494 +00 0 +.names ZI508_431 ZI1171_431 I1199 +00 0 +.names I790 I1217 I1247 +00 0 +.names NODE199 I107 +0 1 +.names ZI492_749 ZI1670_749 I1675 +00 0 +.names ZI502_337 ZI1036_337 I1056 +00 0 +.names NODE81 I104 +0 1 +.names I688 I689 I831 +00 0 +.names I741 I926 I980 +00 0 +.names NODE381 I193 +0 1 +.names ZI423_699 ZI1590_699 I1604 +00 0 +.names I1651 I1666 I1672 +00 0 +.names I692 I693 I833 +00 0 +.names NODE61 I102 +0 1 +.names I734 I919 I973 +00 0 +.names NODE437 I247 +0 1 +.names ZI364_603 ZI1445_603 I1456 +00 0 +.names ZI375_319 ZI1010_319 I1029 +00 0 +.names ZI530_491 ZI1266_491 I1290 +00 0 +.names ZI235_461 ZI1216_461 I1246 +00 0 +.names I786 I1037 I1057 +00 0 +.names NODE253 I108 +0 1 +.names I686 I687 I830 +00 0 +.names ZI353_479 ZI1250_479 I1268 +00 0 +.names ZI431_185 ZI430_185 I764 +00 0 +.names ZI485_689 ZI1566_689 I1582 +00 0 +.names ZI528_463 ZI1218_463 I1248 +00 0 +.names ZI428_747 ZI1667_747 I1673 +00 0 +.names I694 I695 I834 +00 0 +.names ZI415_637 ZI1486_637 I1508 +00 0 +.names ZI355_503 ZI1292_503 I1306 +00 0 +.names ZI437_301 ZI948_301 I996 +00 0 +.names NODE383 I115 +0 1 +.names ZI493_193 ZI496_193 I780 +00 0 +.names NODE461 I117 +0 1 +.names I791 I1265 I1289 +00 0 +.names I662 I663 I818 +00 0 +.names NODE327 I244 +0 1 +.names ZI552_707 ZI1608_707 I1615 +00 0 +.names NODE355 I114 +0 1 +.names I1656 I1669 I1674 +00 0 +.names I781 I782 I901 +00 0 +.names I622 I623 I625 I624 I859 +0000 0 +.names I1657 I511 I1663 +11 1 +.names ZI471_547 ZI1361_547 I1374 +00 0 +.names I730 I915 I969 +00 0 +.names I1635 I511 I1645 +11 1 +.names ZI538_573 ZI1395_573 I1411 +00 0 +.names ZI546_657 ZI1520_657 I1539 +00 0 +.names NODE379 I250 +0 1 +.names I789 I1172 I1200 +00 0 +.names I634 I635 I637 I636 I862 +0000 0 +.names I1601 I511 I1607 +11 1 +.names ZI491_739 ZI1655_739 I1662 +00 0 +.names I594 I595 I596 I597 I852 +0000 0 +.names I642 I643 I644 I645 I864 +0000 0 +.names ZI237_489 ZI1263_489 I1288 +00 0 +.names NODE71 I110 +0 1 +.names I630 I631 I632 I633 I861 +0000 0 +.names I602 I603 I604 I605 I854 +0000 0 +.names I746 I931 I985 +00 0 +.names I646 I647 I649 I648 I865 +0000 0 +.names I795 I1394 I1410 +00 0 +.names ZI506_401 ZI1120_401 I1154 +00 0 +.names NODE291 I106 +0 1 +.names ZI532_519 ZI1304_519 I1330 +00 0 +.names ZI359_551 ZI1370_551 I1379 +00 0 +.names ZI461_415 ZI1151_415 I1170 +00 0 +.names I606 I607 I609 I608 I855 +0000 0 +.names I797 I1454 I1471 +00 0 +.names I794 I1376 I1386 +00 0 +.names I690 I691 I832 +00 0 +.names ZI351_447 ZI1203_447 I1220 +00 0 +.names I211 I219 I429 +11 1 +.names I798 I1482 I1504 +00 0 +.names I732 I917 I971 +00 0 +.names ZI238_501 ZI1287_501 I1302 +00 0 +.names NODE367 I111 +0 1 +.names ZI373_297 ZI936_297 I988 +00 0 +.names I682 I683 I828 +00 0 +.names ZI500_315 ZI1003_315 I1023 +00 0 +.names NODE215 I103 +0 1 +.names NODE313 I230 +0 1 +.names NODE353 I268 +0 1 +.names NODE409 I127 +0 1 +.names NODE407 I277 +0 1 +.names NODE447 I311 +0 1 +.names NODE95 I320 +0 1 +.names NODE133 I259 +0 1 +.names NODE181 I251 +0 1 +.names NODE41 I221 +0 1 +.names NODE289 I182 +0 1 +.names NODE275 I274 +0 1 +.names NODE117 I234 +0 1 +.names NODE317 I275 +0 1 +.names NODE457 I291 +0 1 +.names NODE319 I303 +0 1 +.names NODE63 I142 +0 1 +.names NODE155 I156 +0 1 +.names NODE185 I93 +0 1 +.names NODE267 I176 +0 1 +.names NODE301 I242 +0 1 +.names NODE329 I253 +0 1 +.names NODE69 I163 +0 1 +.names NODE361 I169 +0 1 +.names I81 ZI81_4 +0 1 +.names I81 I332 +0 1 +.names NODE115 I214 +0 1 +.names NODE477 I295 +0 1 +.names NODE25 I126 +0 1 +.names NODE211 I88 +0 1 +.names NODE261 I226 +0 1 +.names NODE17 I149 +0 1 +.names NODE445 I292 +0 1 +.names NODE67 I239 +0 1 +.names NODE221 I96 +0 1 +.names NODE391 I94 +0 1 +.names NODE467 I128 +0 1 +.names NODE209 I283 +0 1 +.names NODE153 I302 +0 1 +.names NODE343 I205 +0 1 +.names NODE59 I284 +0 1 +.names NODE55 I118 +0 1 +.names NODE109 I232 +0 1 +.names NODE425 I165 +0 1 +.names NODE357 I134 +0 1 +.names NODE169 I177 +0 1 +.names NODE217 I143 +0 1 +.names NODE393 I266 +0 1 +.names NODE403 I152 +0 1 +.names NODE187 I287 +0 1 +.names NODE151 I318 +0 1 +.names NODE157 I310 +0 1 +.names NODE149 I262 +0 1 +.names NODE269 I272 +0 1 +.names NODE431 I123 +0 1 +.names NODE247 I213 +0 1 +.names NODE89 I141 +0 1 +.names NODE385 I135 +0 1 +.names NODE265 I140 +0 1 +.names NODE141 I98 +0 1 +.names NODE119 I269 +0 1 +.names NODE27 I222 +0 1 +.names NODE107 I212 +0 1 +.names NODE293 I146 +0 1 +.names NODE435 I207 +0 1 +.names NODE287 I121 +0 1 +.names NODE101 I136 +0 1 +.names NODE47 I171 +0 1 +.names NODE229 I178 +0 1 +.names NODE205 I296 +0 1 +.names NODE333 I201 +0 1 +.names NODE405 I164 +0 1 +.names NODE57 I138 +0 1 +.names NODE299 I202 +0 1 +.names NODE129 I160 +0 1 +.names NODE279 I124 +0 1 +.names NODE281 I257 +0 1 +.names NODE21 I240 +0 1 +.names NODE23 I276 +0 1 +.names NODE375 I159 +0 1 +.names I82 I509 +0 1 +.names I82 ZI82_55 +0 1 +.names NODE83 I144 +0 1 +.names NODE395 I306 +0 1 +.names NODE173 I254 +0 1 +.names NODE325 I204 +0 1 +.names NODE167 I261 +0 1 +.names NODE193 I305 +0 1 +.names NODE305 I119 +0 1 +.names NODE371 I258 +0 1 +.names NODE125 I211 +0 1 +.names NODE135 I293 +0 1 +.names NODE35 I224 +0 1 +.names NODE159 I252 +0 1 +.names NODE347 I197 +0 1 +.names NODE213 I194 +0 1 +.names NODE427 I312 +0 1 +.names NODE463 I137 +0 1 +.names NODE389 I90 +0 1 +.names NODE131 I158 +0 1 +.names NODE323 I181 +0 1 +.names NODE111 I313 +0 1 +.names NODE363 I260 +0 1 +.names NODE7 I133 +0 1 +.names NODE453 I203 +0 1 +.names NODE29 I172 +0 1 +.names NODE443 I196 +0 1 +.names NODE183 I91 +0 1 +.names NODE257 I209 +0 1 +.names NODE201 I255 +0 1 +.names NODE139 I150 +0 1 +.names NODE73 I130 +0 1 +.names NODE307 I139 +0 1 +.names NODE113 I168 +0 1 +.names NODE123 I309 +0 1 +.names NODE429 I273 +0 1 +.names NODE33 I323 +0 1 +.names NODE433 I87 +0 1 +.names NODE283 I286 +0 1 +.names NODE65 I219 +0 1 +.names NODE251 I280 +0 1 +.names NODE195 I223 +0 1 +.names NODE225 I237 +0 1 +.names NODE339 I216 +0 1 +.names NODE145 I235 +0 1 +.names NODE75 I225 +0 1 +.names NODE189 I265 +0 1 +.names NODE49 I282 +0 1 +.names NODE165 I227 +0 1 +.names NODE223 I217 +0 1 +.names NODE417 I299 +0 1 +.names NODE191 I316 +0 1 +.names NODE321 I125 +0 1 +.names NODE469 I229 +0 1 +.names NODE163 I304 +0 1 +.names NODE277 I307 +0 1 +.names NODE441 I314 +0 1 +.names NODE411 I161 +0 1 +.names NODE137 I89 +0 1 +.names NODE271 I122 +0 1 +.names NODE121 I92 +0 1 +.names I79 I324 +0 1 +.names I79 ZI79_ +0 1 +.names NODE369 I131 +0 1 +.names NODE335 I241 +0 1 +.names NODE179 I290 +0 1 +.names NODE377 I322 +0 1 +.names NODE415 I154 +0 1 +.names NODE451 I294 +0 1 +.names NODE399 I319 +0 1 +.names NODE401 I256 +0 1 +.names NODE471 I179 +0 1 +.names NODE273 I267 +0 1 +.names NODE147 I166 +0 1 +.names NODE93 I285 +0 1 +.names NODE365 I97 +0 1 +.names NODE19 I200 +0 1 +.names NODE79 I175 +0 1 +.names NODE239 I170 +0 1 +.names NODE387 I321 +0 1 +.names NODE97 I297 +0 1 +.names NODE373 I300 +0 1 +.names NODE309 I263 +0 1 +.names NODE359 I308 +0 1 +.names NODE465 I278 +0 1 +.names NODE11 I208 +0 1 +.names NODE197 I173 +0 1 +.names NODE241 I195 +0 1 +.names I83 I328 +0 1 +.names I83 ZI83_2 +0 1 +.names NODE421 I151 +0 1 +.names NODE9 I180 +0 1 +.names NODE51 I206 +0 1 +.names NODE475 I120 +0 1 +.names NODE255 I148 +0 1 +.names NODE39 I99 +0 1 +.names NODE37 I174 +0 1 +.names NODE227 I228 +0 1 +.names NODE311 I210 +0 1 +.names NODE105 I145 +0 1 +.names NODE161 I264 +0 1 +.names NODE337 I185 +0 1 +.names NODE439 I155 +0 1 +.names NODE449 I183 +0 1 +.names NODE175 I301 +0 1 +.names NODE263 I100 +0 1 +.names NODE351 I132 +0 1 +.names NODE413 I198 +0 1 +.names NODE235 I220 +0 1 +.names NODE233 I129 +0 1 +.names NODE397 I162 +0 1 +.names NODE231 I279 +0 1 +.names I80 ZI80_1 +0 1 +.names I80 I325 +0 1 +.names NODE243 I288 +0 1 +.names NODE85 I153 +0 1 +.names NODE285 I271 +0 1 +.names NODE297 I238 +0 1 +.names NODE341 I236 +0 1 +.names NODE91 I317 +0 1 +.names NODE127 I231 +0 1 +.names NODE237 I95 +0 1 +.names NODE473 I270 +0 1 +.names NODE171 I298 +0 1 +.names NODE31 I167 +0 1 +.names NODE77 I281 +0 1 +.names NODE249 I233 +0 1 +.names NODE303 I184 +0 1 +.names NODE459 I315 +0 1 +.names NODE143 I215 +0 1 +.names NODE177 I199 +0 1 +.names NODE3 I289 +0 1 +.names I84 I330 +0 1 +.names I84 ZI84_3 +0 1 +.names NODE203 I147 +0 1 +.names NODE295 I218 +0 1 +.names NODE43 I157 +0 1 +.names NODE331 I85 +0 1 +.names NODE315 I86 +0 1 +.names I230 ZI230_43 +0 1 +.names I268 ZI268_72 +0 1 +.names I277 ZI277_90 +0 1 +.names I311 ZI311_76 +0 1 +.names I320 ZI320_94 +0 1 +.names I259 ZI259_53 +0 1 +.names I251 ZI251_37 +0 1 +.names I182 ZI182_31 +0 1 +.names I182 ZI182_112 +0 1 +.names I274 ZI274_84 +0 1 +.names I234 ZI234_51 +0 1 +.names I275 ZI275_86 +0 1 +.names I291 ZI291_142 +0 1 +.names I303 ZI303_60 +0 1 +.names I142 ZI142_19 +0 1 +.names I142 ZI142_132 +0 1 +.names I93 ZI93_158 +0 1 +.names I176 ZI176_19 +0 1 +.names I176 ZI176_116 +0 1 +.names I242 ZI242_548 +0 1 +.names I253 ZI253_41 +0 1 +.names I169 ZI169_5 +0 1 +.names I169 ZI169_102 +0 1 +.names ZI81_4 I333 +0 1 +.names I295 ZI295_150 +0 1 +.names I88 ZI88_164 +0 1 +.names I149 ZI149_33 +0 1 +.names I149 ZI149_130 +0 1 +.names I292 ZI292_144 +0 1 +.names I239 ZI239_516 +0 1 +.names I96 ZI96_164 +0 1 +.names I94 ZI94_160 +0 1 +.names I283 ZI283_142 +0 1 +.names I302 ZI302_58 +0 1 +.names I284 ZI284_144 +0 1 +.names I232 ZI232_47 +0 1 +.names I177 ZI177_102 +0 1 +.names I177 ZI177_21 +0 1 +.names I143 ZI143_118 +0 1 +.names I143 ZI143_21 +0 1 +.names I266 ZI266_68 +0 1 +.names I287 ZI287_150 +0 1 +.names I318 ZI318_90 +0 1 +.names I310 ZI310_74 +0 1 +.names I262 ZI262_60 +0 1 +.names I272 ZI272_80 +0 1 +.names I141 ZI141_130 +0 1 +.names I141 ZI141_17 +0 1 +.names I135 ZI135_5 +0 1 +.names I135 ZI135_118 +0 1 +.names I140 ZI140_128 +0 1 +.names I140 ZI140_15 +0 1 +.names I98 ZI98_168 +0 1 +.names I269 ZI269_74 +0 1 +.names I188 ZI188_138 +0 1 +.names I146 ZI146_124 +0 1 +.names I146 ZI146_27 +0 1 +.names I136 ZI136_7 +0 1 +.names I136 ZI136_120 +0 1 +.names I171 ZI171_106 +0 1 +.names I171 ZI171_9 +0 1 +.names I178 ZI178_104 +0 1 +.names I178 ZI178_23 +0 1 +.names I296 ZI296_152 +0 1 +.names I138 ZI138_124 +0 1 +.names I138 ZI138_11 +0 1 +.names I257 ZI257_49 +0 1 +.names I240 ZI240_532 +0 1 +.names I276 ZI276_88 +0 1 +.names ZI82_55 I511 +0 1 +.names I144 ZI144_120 +0 1 +.names I144 ZI144_23 +0 1 +.names I306 ZI306_66 +0 1 +.names I193 ZI193_140 +0 1 +.names I254 ZI254_43 +0 1 +.names I261 ZI261_58 +0 1 +.names I305 ZI305_64 +0 1 +.names I192 ZI192_138 +0 1 +.names I258 ZI258_51 +0 1 +.names I293 ZI293_146 +0 1 +.names I252 ZI252_39 +0 1 +.names I194 ZI194_260 +0 1 +.names I312 ZI312_78 +0 1 +.names I137 ZI137_122 +0 1 +.names I137 ZI137_9 +0 1 +.names I90 ZI90_168 +0 1 +.names I181 ZI181_110 +0 1 +.names I181 ZI181_29 +0 1 +.names I313 ZI313_80 +0 1 +.names I260 ZI260_56 +0 1 +.names I172 ZI172_108 +0 1 +.names I172 ZI172_11 +0 1 +.names I91 ZI91_170 +0 1 +.names I255 ZI255_45 +0 1 +.names I150 ZI150_132 +0 1 +.names I150 ZI150_35 +0 1 +.names I190 ZI190_134 +0 1 +.names I139 ZI139_126 +0 1 +.names I139 ZI139_13 +0 1 +.names I189 ZI189_140 +0 1 +.names I309 ZI309_72 +0 1 +.names I273 ZI273_82 +0 1 +.names I323 ZI323_100 +0 1 +.names I87 ZI87_162 +0 1 +.names I286 ZI286_148 +0 1 +.names I280 ZI280_96 +0 1 +.names I237 ZI237_488 +0 1 +.names I235 ZI235_460 +0 1 +.names I265 ZI265_66 +0 1 +.names I282 ZI282_100 +0 1 +.names I227 ZI227_37 +0 1 +.names I299 ZI299_290 +0 1 +.names I316 ZI316_86 +0 1 +.names I229 ZI229_41 +0 1 +.names I304 ZI304_62 +0 1 +.names I307 ZI307_68 +0 1 +.names I314 ZI314_82 +0 1 +.names I89 ZI89_166 +0 1 +.names I92 ZI92_172 +0 1 +.names ZI79_ I326 +0 1 +.names I241 ZI241_540 +0 1 +.names I290 ZI290_156 +0 1 +.names I322 ZI322_98 +0 1 +.names I294 ZI294_148 +0 1 +.names I319 ZI319_92 +0 1 +.names I256 ZI256_47 +0 1 +.names I179 ZI179_106 +0 1 +.names I179 ZI179_25 +0 1 +.names I267 ZI267_70 +0 1 +.names I285 ZI285_146 +0 1 +.names I97 ZI97_166 +0 1 +.names I175 ZI175_114 +0 1 +.names I175 ZI175_17 +0 1 +.names I170 ZI170_7 +0 1 +.names I170 ZI170_104 +0 1 +.names I321 ZI321_96 +0 1 +.names I297 ZI297_154 +0 1 +.names I300 ZI300_53 +0 1 +.names I263 ZI263_62 +0 1 +.names I308 ZI308_70 +0 1 +.names I278 ZI278_92 +0 1 +.names I173 ZI173_110 +0 1 +.names I173 ZI173_13 +0 1 +.names ZI83_2 I329 +0 1 +.names I151 ZI151_294 +0 1 +.names I180 ZI180_108 +0 1 +.names I180 ZI180_27 +0 1 +.names I148 ZI148_31 +0 1 +.names I148 ZI148_128 +0 1 +.names I99 ZI99_170 +0 1 +.names I174 ZI174_15 +0 1 +.names I174 ZI174_112 +0 1 +.names I228 ZI228_39 +0 1 +.names I187 ZI187_136 +0 1 +.names I145 ZI145_122 +0 1 +.names I145 ZI145_25 +0 1 +.names I186 ZI186_134 +0 1 +.names I264 ZI264_64 +0 1 +.names I185 ZI185_292 +0 1 +.names I183 ZI183_114 +0 1 +.names I183 ZI183_33 +0 1 +.names I301 ZI301_56 +0 1 +.names I100 ZI100_172 +0 1 +.names I191 ZI191_136 +0 1 +.names I279 ZI279_94 +0 1 +.names ZI80_1 I327 +0 1 +.names I288 ZI288_152 +0 1 +.names I271 ZI271_78 +0 1 +.names I238 ZI238_500 +0 1 +.names I236 ZI236_476 +0 1 +.names I317 ZI317_88 +0 1 +.names I231 ZI231_45 +0 1 +.names I95 ZI95_162 +0 1 +.names I270 ZI270_76 +0 1 +.names I298 ZI298_156 +0 1 +.names I281 ZI281_98 +0 1 +.names I233 ZI233_49 +0 1 +.names I184 ZI184_116 +0 1 +.names I184 ZI184_35 +0 1 +.names I315 ZI315_84 +0 1 +.names I289 ZI289_154 +0 1 +.names ZI84_3 I331 +0 1 +.names I147 ZI147_126 +0 1 +.names I147 ZI147_29 +0 1 +.names I85 ZI85_158 +0 1 +.names I86 ZI86_160 +0 1 +.names I442 ZI442_380 +0 1 +.names I221 I214 I442 +11 1 +.names I476 ZI476_618 +0 1 +.names I214 I226 I476 +11 1 +.names I475 ZI475_598 +0 1 +.names I226 I213 I475 +11 1 +.names I441 ZI441_378 +0 1 +.names I221 I213 I441 +11 1 +.names I334 ZI334_174 +0 1 +.names I169 I135 I334 +11 1 +.names I444 ZI444_440 +0 1 +.names I214 I222 I444 +11 1 +.names I443 ZI443_410 +0 1 +.names I213 I222 I443 +11 1 +.names I472 ZI472_560 +0 1 +.names I226 I212 I472 +11 1 +.names I438 ZI438_274 +0 1 +.names I221 I212 I438 +11 1 +.names I440 ZI440_344 +0 1 +.names I222 I212 I440 +11 1 +.names I417 ZI417_638 +0 1 +.names I207 I201 I417 +11 1 +.names I393 ZI393_374 +0 1 +.names I205 I201 I393 +11 1 +.names I418 ZI418_640 +0 1 +.names I207 I202 I418 +11 1 +.names I394 ZI394_376 +0 1 +.names I205 I202 I394 +11 1 +.names I386 ZI386_182 +0 1 +.names I201 I204 I386 +11 1 +.names I437 ZI437_300 +0 1 +.names I221 I211 I437 +11 1 +.names I471 ZI471_546 +0 1 +.names I226 I211 I471 +11 1 +.names I439 ZI439_322 +0 1 +.names I222 I211 I439 +11 1 +.names I467 ZI467_498 +0 1 +.names I213 I224 I467 +11 1 +.names I463 ZI463_470 +0 1 +.names I211 I224 I463 +11 1 +.names I468 ZI468_526 +0 1 +.names I214 I224 I468 +11 1 +.names I464 ZI464_496 +0 1 +.names I212 I224 I464 +11 1 +.names I401 ZI401_466 +0 1 +.names I207 I197 I401 +11 1 +.names I377 ZI377_370 +0 1 +.names I205 I197 I377 +11 1 +.names I370 ZI370_178 +0 1 +.names I204 I197 I370 +11 1 +.names I387 ZI387_182 +0 1 +.names I202 I203 I387 +11 1 +.names I385 I760 +0 1 +.names I201 I203 I385 +11 1 +.names I385 ZI385_268 +0 1 +.names I369 I753 +0 1 +.names I197 I203 I369 +11 1 +.names I369 ZI369_264 +0 1 +.names I398 ZI398_438 +0 1 +.names I207 I196 I398 +11 1 +.names I367 ZI367_176 +0 1 +.names I203 I196 I367 +11 1 +.names I374 ZI374_266 +0 1 +.names I205 I196 I374 +11 1 +.names I409 ZI409_574 +0 1 +.names I197 I209 I409 +11 1 +.names I426 ZI426_724 +0 1 +.names I202 I209 I426 +11 1 +.names I406 ZI406_524 +0 1 +.names I196 I209 I406 +11 1 +.names I425 ZI425_722 +0 1 +.names I201 I209 I425 +11 1 +.names I433 I768 +0 1 +.names I213 I219 I433 +11 1 +.names I433 ZI433_272 +0 1 +.names I429 I765 +0 1 +.names I431 ZI431_184 +0 1 +.names I212 I219 I431 +11 1 +.names I435 ZI435_186 +0 1 +.names I214 I219 I435 +11 1 +.names I466 ZI466_474 +0 1 +.names I214 I223 I466 +11 1 +.names I462 ZI462_444 +0 1 +.names I212 I223 I462 +11 1 +.names I461 ZI461_414 +0 1 +.names I211 I223 I461 +11 1 +.names I465 ZI465_472 +0 1 +.names I213 I223 I465 +11 1 +.names I488 ZI488_710 +0 1 +.names I226 I216 I488 +11 1 +.names I480 ZI480_662 +0 1 +.names I224 I216 I480 +11 1 +.names I456 ZI456_346 +0 1 +.names I222 I216 I456 +11 1 +.names I447 ZI447_188 +0 1 +.names I219 I216 I447 +11 1 +.names I478 ZI478_620 +0 1 +.names I223 I216 I478 +11 1 +.names I454 ZI454_278 +0 1 +.names I221 I216 I454 +11 1 +.names I474 ZI474_580 +0 1 +.names I214 I225 I474 +11 1 +.names I486 ZI486_690 +0 1 +.names I216 I225 I486 +11 1 +.names I473 ZI473_578 +0 1 +.names I213 I225 I473 +11 1 +.names I470 ZI470_530 +0 1 +.names I212 I225 I470 +11 1 +.names I469 ZI469_528 +0 1 +.names I211 I225 I469 +11 1 +.names I493 ZI493_192 +0 1 +.names I251 I227 I493 +11 1 +.names I449 ZI449_276 +0 1 +.names I219 I217 I449 +11 1 +.names I449 I775 +0 1 +.names I457 ZI457_382 +0 1 +.names I221 I217 I457 +11 1 +.names I491 ZI491_738 +0 1 +.names I226 I217 I491 +11 1 +.names I489 ZI489_726 +0 1 +.names I225 I217 I489 +11 1 +.names I481 ZI481_644 +0 1 +.names I223 I217 I481 +11 1 +.names I459 ZI459_412 +0 1 +.names I222 I217 I459 +11 1 +.names I483 ZI483_664 +0 1 +.names I224 I217 I483 +11 1 +.names I390 ZI390_270 +0 1 +.names I205 I200 I390 +11 1 +.names I383 ZI383_180 +0 1 +.names I203 I200 I383 +11 1 +.names I422 ZI422_684 +0 1 +.names I209 I200 I422 +11 1 +.names I414 ZI414_616 +0 1 +.names I207 I200 I414 +11 1 +.names I512 ZI512_194 +0 1 +.names I259 I300 I512 +11 1 +.names I420 ZI420_680 +0 1 +.names I202 I208 I420 +11 1 +.names I416 ZI416_658 +0 1 +.names I200 I208 I416 +11 1 +.names I403 ZI403_494 +0 1 +.names I197 I208 I403 +11 1 +.names I400 ZI400_492 +0 1 +.names I196 I208 I400 +11 1 +.names I419 ZI419_660 +0 1 +.names I201 I208 I419 +11 1 +.names I365 I750 +0 1 +.names I405 ZI405_522 +0 1 +.names I209 I195 I405 +11 1 +.names I366 ZI366_176 +0 1 +.names I204 I195 I366 +11 1 +.names I399 ZI399_464 +0 1 +.names I208 I195 I399 +11 1 +.names I373 ZI373_296 +0 1 +.names I205 I195 I373 +11 1 +.names I397 ZI397_408 +0 1 +.names I207 I195 I397 +11 1 +.names I396 ZI396_436 +0 1 +.names I202 I206 I396 +11 1 +.names I379 ZI379_404 +0 1 +.names I197 I206 I379 +11 1 +.names I375 ZI375_318 +0 1 +.names I195 I206 I375 +11 1 +.names I392 ZI392_342 +0 1 +.names I200 I206 I392 +11 1 +.names I395 ZI395_406 +0 1 +.names I201 I206 I395 +11 1 +.names I376 ZI376_340 +0 1 +.names I196 I206 I376 +11 1 +.names I428 ZI428_746 +0 1 +.names I202 I210 I428 +11 1 +.names I407 ZI407_544 +0 1 +.names I195 I210 I407 +11 1 +.names I408 ZI408_558 +0 1 +.names I196 I210 I408 +11 1 +.names I424 ZI424_708 +0 1 +.names I200 I210 I424 +11 1 +.names I411 ZI411_594 +0 1 +.names I197 I210 I411 +11 1 +.names I427 ZI427_736 +0 1 +.names I201 I210 I427 +11 1 +.names I402 ZI402_468 +0 1 +.names I207 I198 I402 +11 1 +.names I410 ZI410_576 +0 1 +.names I209 I198 I410 +11 1 +.names I404 ZI404_520 +0 1 +.names I208 I198 I404 +11 1 +.names I380 ZI380_434 +0 1 +.names I206 I198 I380 +11 1 +.names I371 ZI371_178 +0 1 +.names I203 I198 I371 +11 1 +.names I378 ZI378_372 +0 1 +.names I205 I198 I378 +11 1 +.names I412 ZI412_614 +0 1 +.names I210 I198 I412 +11 1 +.names I430 ZI430_184 +0 1 +.names I211 I220 I430 +11 1 +.names I450 ZI450_190 +0 1 +.names I217 I220 I450 +11 1 +.names I434 ZI434_186 +0 1 +.names I213 I220 I434 +11 1 +.names I479 ZI479_642 +0 1 +.names I224 I215 I479 +11 1 +.names I453 ZI453_302 +0 1 +.names I221 I215 I453 +11 1 +.names I445 ZI445_398 +0 1 +.names I219 I215 I445 +11 1 +.names I445 I772 +0 1 +.names I477 ZI477_600 +0 1 +.names I223 I215 I477 +11 1 +.names I446 ZI446_188 +0 1 +.names I220 I215 I446 +11 1 +.names I485 ZI485_688 +0 1 +.names I225 I215 I485 +11 1 +.names I487 ZI487_700 +0 1 +.names I226 I215 I487 +11 1 +.names I455 ZI455_324 +0 1 +.names I222 I215 I455 +11 1 +.names I413 ZI413_596 +0 1 +.names I207 I199 I413 +11 1 +.names I391 ZI391_320 +0 1 +.names I206 I199 I391 +11 1 +.names I421 ZI421_682 +0 1 +.names I209 I199 I421 +11 1 +.names I389 ZI389_298 +0 1 +.names I205 I199 I389 +11 1 +.names I382 ZI382_180 +0 1 +.names I204 I199 I382 +11 1 +.names I381 ZI381_392 +0 1 +.names I203 I199 I381 +11 1 +.names I381 I757 +0 1 +.names I415 ZI415_636 +0 1 +.names I208 I199 I415 +11 1 +.names I423 ZI423_698 +0 1 +.names I210 I199 I423 +11 1 +.names I460 ZI460_442 +0 1 +.names I222 I218 I460 +11 1 +.names I458 ZI458_384 +0 1 +.names I221 I218 I458 +11 1 +.names I492 ZI492_748 +0 1 +.names I226 I218 I492 +11 1 +.names I482 ZI482_646 +0 1 +.names I223 I218 I482 +11 1 +.names I484 ZI484_686 +0 1 +.names I224 I218 I484 +11 1 +.names I490 ZI490_728 +0 1 +.names I225 I218 I490 +11 1 +.names I451 ZI451_190 +0 1 +.names I219 I218 I451 +11 1 +.names I761 ZI761_356 +0 1 +.names I386 I387 I761 +11 1 +.names I751 ZI751_232 +0 1 +.names I367 I366 I751 +11 1 +.names I754 ZI754_352 +0 1 +.names I370 I371 I754 +11 1 +.names I766 ZI766_236 +0 1 +.names I431 I430 I766 +11 1 +.names I769 ZI769_360 +0 1 +.names I435 I434 I769 +11 1 +.names I773 ZI773_238 +0 1 +.names I447 I446 I773 +11 1 +.names I758 ZI758_234 +0 1 +.names I383 I382 I758 +11 1 +.names I776 ZI776_364 +0 1 +.names I450 I451 I776 +11 1 +.names I349 ZI349_416 +0 1 +.names ZI142_20 ZI176_20 I349 +00 0 +.names I589 ZI589_230 +0 1 +.names ZI88_165 ZI96_165 I589 +00 0 +.names I578 ZI578_216 +0 1 +.names ZI291_143 ZI283_143 I578 +00 0 +.names I579 ZI579_218 +0 1 +.names ZI292_145 ZI284_145 I579 +00 0 +.names I558 ZI558_196 +0 1 +.names ZI169_103 ZI177_103 I558 +00 0 +.names I351 ZI351_446 +0 1 +.names ZI177_22 ZI143_22 I351 +00 0 +.names I582 ZI582_216 +0 1 +.names ZI295_151 ZI287_151 I582 +00 0 +.names I548 ZI548_678 +0 1 +.names ZI277_91 ZI318_91 I548 +00 0 +.names I518 ZI518_316 +0 1 +.names ZI303_61 ZI262_61 I518 +00 0 +.names I572 ZI572_208 +0 1 +.names ZI149_131 ZI141_131 I572 +00 0 +.names I566 ZI566_204 +0 1 +.names ZI143_119 ZI135_119 I566 +00 0 +.names I532 ZI532_518 +0 1 +.names ZI310_75 ZI269_75 I532 +00 0 +.names I569 ZI569_210 +0 1 +.names ZI146_125 ZI138_125 I569 +00 0 +.names I567 ZI567_206 +0 1 +.names ZI136_121 ZI144_121 I567 +00 0 +.names I353 ZI353_478 +0 1 +.names ZI178_24 ZI144_24 I353 +00 0 +.names I500 ZI500_314 +0 1 +.names ZI230_44 ZI254_44 I500 +00 0 +.names I516 ZI516_282 +0 1 +.names ZI302_59 ZI261_59 I516 +00 0 +.names I576 ZI576_212 +0 1 +.names ZI188_139 ZI192_139 I576 +00 0 +.names I508 ZI508_430 +0 1 +.names ZI234_52 ZI258_52 I508 +00 0 +.names I339 ZI339_262 +0 1 +.names ZI171_10 ZI137_10 I339 +00 0 +.names I591 ZI591_226 +0 1 +.names ZI98_169 ZI90_169 I591 +00 0 +.names I538 ZI538_572 +0 1 +.names ZI272_81 ZI313_81 I538 +00 0 +.names I878 ZI878_354 +0 1 +.names I760 I388 I878 +11 1 +.names I871 ZI871_350 +0 1 +.names I753 I372 I871 +11 1 +.names I341 ZI341_304 +0 1 +.names ZI138_12 ZI172_12 I341 +00 0 +.names I573 ZI573_210 +0 1 +.names ZI142_133 ZI150_133 I573 +00 0 +.names I577 ZI577_214 +0 1 +.names ZI193_141 ZI189_141 I577 +00 0 +.names I530 ZI530_490 +0 1 +.names ZI268_73 ZI309_73 I530 +00 0 +.names I886 ZI886_358 +0 1 +.names I768 I436 I886 +11 1 +.names I885 ZI885_272 +0 1 +.names I765 I432 I885 +11 1 +.names I524 ZI524_402 +0 1 +.names ZI306_67 ZI265_67 I524 +00 0 +.names I557 ZI557_744 +0 1 +.names ZI323_101 ZI282_101 I557 +00 0 +.names I893 ZI893_362 +0 1 +.names I775 I452 I893 +11 1 +.names I544 ZI544_634 +0 1 +.names ZI275_87 ZI316_87 I544 +00 0 +.names I498 ZI498_280 +0 1 +.names ZI253_42 ZI229_42 I498 +00 0 +.names I526 ZI526_432 +0 1 +.names ZI266_69 ZI307_69 I526 +00 0 +.names I540 ZI540_592 +0 1 +.names ZI273_83 ZI314_83 I540 +00 0 +.names I581 ZI581_222 +0 1 +.names ZI286_149 ZI294_149 I581 +00 0 +.names I504 ZI504_366 +0 1 +.names ZI232_48 ZI256_48 I504 +00 0 +.names I560 ZI560_200 +0 1 +.names ZI171_107 ZI179_107 I560 +00 0 +.names I580 ZI580_220 +0 1 +.names ZI293_147 ZI285_147 I580 +00 0 +.names I590 ZI590_224 +0 1 +.names ZI89_167 ZI97_167 I590 +00 0 +.names I347 ZI347_386 +0 1 +.names ZI141_18 ZI175_18 I347 +00 0 +.names I337 ZI337_174 +0 1 +.names ZI136_8 ZI170_8 I337 +00 0 +.names I559 ZI559_198 +0 1 +.names ZI178_105 ZI170_105 I559 +00 0 +.names I554 ZI554_720 +0 1 +.names ZI280_97 ZI321_97 I554 +00 0 +.names I520 ZI520_338 +0 1 +.names ZI304_63 ZI263_63 I520 +00 0 +.names I528 ZI528_462 +0 1 +.names ZI267_71 ZI308_71 I528 +00 0 +.names I550 ZI550_696 +0 1 +.names ZI319_93 ZI278_93 I550 +00 0 +.names I562 ZI562_196 +0 1 +.names ZI181_111 ZI173_111 I562 +00 0 +.names I343 ZI343_326 +0 1 +.names ZI139_14 ZI173_14 I343 +00 0 +.names I870 ZI870_264 +0 1 +.names I750 I368 I870 +11 1 +.names I561 ZI561_202 +0 1 +.names ZI172_109 ZI180_109 I561 +00 0 +.names I357 ZI357_534 +0 1 +.names ZI146_28 ZI180_28 I357 +00 0 +.names I361 ZI361_562 +0 1 +.names ZI182_32 ZI148_32 I361 +00 0 +.names I571 ZI571_206 +0 1 +.names ZI140_129 ZI148_129 I571 +00 0 +.names I592 ZI592_228 +0 1 +.names ZI91_171 ZI99_171 I592 +00 0 +.names I345 ZI345_348 +0 1 +.names ZI140_16 ZI174_16 I345 +00 0 +.names I563 ZI563_198 +0 1 +.names ZI182_113 ZI174_113 I563 +00 0 +.names I496 ZI496_192 +0 1 +.names ZI252_40 ZI228_40 I496 +00 0 +.names I568 ZI568_208 +0 1 +.names ZI137_123 ZI145_123 I568 +00 0 +.names I355 ZI355_502 +0 1 +.names ZI179_26 ZI145_26 I355 +00 0 +.names I574 ZI574_212 +0 1 +.names ZI190_135 ZI186_135 I574 +00 0 +.names I522 ZI522_368 +0 1 +.names ZI305_65 ZI264_65 I522 +00 0 +.names I564 ZI564_200 +0 1 +.names ZI175_115 ZI183_115 I564 +00 0 +.names I363 ZI363_582 +0 1 +.names ZI149_34 ZI183_34 I363 +00 0 +.names I514 ZI514_194 +0 1 +.names ZI260_57 ZI301_57 I514 +00 0 +.names I593 ZI593_230 +0 1 +.names ZI92_173 ZI100_173 I593 +00 0 +.names I575 ZI575_214 +0 1 +.names ZI187_137 ZI191_137 I575 +00 0 +.names I552 ZI552_706 +0 1 +.names ZI320_95 ZI279_95 I552 +00 0 +.names I583 ZI583_218 +0 1 +.names ZI296_153 ZI288_153 I583 +00 0 +.names I536 ZI536_556 +0 1 +.names ZI312_79 ZI271_79 I536 +00 0 +.names I546 ZI546_656 +0 1 +.names ZI276_89 ZI317_89 I546 +00 0 +.names I502 ZI502_336 +0 1 +.names ZI255_46 ZI231_46 I502 +00 0 +.names I588 ZI588_228 +0 1 +.names ZI87_163 ZI95_163 I588 +00 0 +.names I534 ZI534_542 +0 1 +.names ZI311_77 ZI270_77 I534 +00 0 +.names I585 ZI585_222 +0 1 +.names ZI290_157 ZI298_157 I585 +00 0 +.names I556 ZI556_734 +0 1 +.names ZI322_99 ZI281_99 I556 +00 0 +.names I506 ZI506_400 +0 1 +.names ZI257_50 ZI233_50 I506 +00 0 +.names I565 ZI565_202 +0 1 +.names ZI176_117 ZI184_117 I565 +00 0 +.names I364 ZI364_602 +0 1 +.names ZI150_36 ZI184_36 I364 +00 0 +.names I542 ZI542_612 +0 1 +.names ZI274_85 ZI315_85 I542 +00 0 +.names I892 ZI892_276 +0 1 +.names I772 I448 I892 +11 1 +.names I877 ZI877_268 +0 1 +.names I757 I384 I877 +11 1 +.names I584 ZI584_220 +0 1 +.names ZI297_155 ZI289_155 I584 +00 0 +.names I570 ZI570_204 +0 1 +.names ZI139_127 ZI147_127 I570 +00 0 +.names I359 ZI359_550 +0 1 +.names ZI181_30 ZI147_30 I359 +00 0 +.names I586 ZI586_224 +0 1 +.names ZI93_159 ZI85_159 I586 +00 0 +.names I587 ZI587_226 +0 1 +.names ZI94_161 ZI86_161 I587 +00 0 +.names I759 ZI759_234 +0 1 +.names ZI386_183 ZI387_183 I759 +00 0 +.names I752 ZI752_232 +0 1 +.names ZI370_179 ZI371_179 I752 +00 0 +.names I767 ZI767_236 +0 1 +.names ZI435_187 ZI434_187 I767 +00 0 +.names I771 ZI771_428 +0 1 +.names ZI447_189 ZI446_189 I771 +00 0 +.names I756 ZI756_422 +0 1 +.names ZI383_181 ZI382_181 I756 +00 0 +.names I774 ZI774_238 +0 1 +.names ZI450_191 ZI451_191 I774 +00 0 +.names I995 ZI995_310 +0 1 +.names I770 I947 I946 I995 +000 0 +.names I869 ZI869_262 +0 1 +.names I336 I747 I869 +00 0 +.names I987 ZI987_306 +0 1 +.names I755 I934 I935 I987 +000 0 +.names I900 ZI900_280 +0 1 +.names I495 I779 I900 +00 0 +.names I903 ZI903_282 +0 1 +.names I513 I799 I903 +00 0 +.names I999 ZI999_312 +0 1 +.names I777 I952 I953 I999 +000 0 +.names I991 ZI991_308 +0 1 +.names I762 I941 I940 I991 +000 0 +.names I810 ZI810_250 +0 1 +.names ZI578_217 ZI582_217 I810 +00 0 +.names I943 ZI943_330 +0 1 +.names I881 I879 I880 I943 +000 0 +.names I807 ZI807_246 +0 1 +.names ZI569_211 ZI573_211 I807 +00 0 +.names I948 ZI948_300 +0 1 +.names ZI433_273 ZI885_273 I948 +00 0 +.names I800 ZI800_240 +0 1 +.names ZI558_197 ZI562_197 I800 +00 0 +.names I936 ZI936_296 +0 1 +.names ZI369_265 ZI870_265 I936 +00 0 +.names I805 ZI805_246 +0 1 +.names ZI567_207 ZI571_207 I805 +00 0 +.names I801 ZI801_242 +0 1 +.names ZI559_199 ZI563_199 I801 +00 0 +.names I806 ZI806_244 +0 1 +.names ZI572_209 ZI568_209 I806 +00 0 +.names I808 ZI808_248 +0 1 +.names ZI576_213 ZI574_213 I808 +00 0 +.names I802 ZI802_240 +0 1 +.names ZI560_201 ZI564_201 I802 +00 0 +.names I817 ZI817_256 +0 1 +.names ZI589_231 ZI593_231 I817 +00 0 +.names I937 ZI937_328 +0 1 +.names I874 I872 I873 I937 +000 0 +.names I949 ZI949_332 +0 1 +.names I889 I887 I888 I949 +000 0 +.names I809 ZI809_248 +0 1 +.names ZI577_215 ZI575_215 I809 +00 0 +.names I811 ZI811_252 +0 1 +.names ZI579_219 ZI583_219 I811 +00 0 +.names I816 ZI816_254 +0 1 +.names ZI592_229 ZI588_229 I816 +00 0 +.names I813 ZI813_252 +0 1 +.names ZI581_223 ZI585_223 I813 +00 0 +.names I803 ZI803_242 +0 1 +.names ZI561_203 ZI565_203 I803 +00 0 +.names I954 ZI954_302 +0 1 +.names ZI449_277 ZI892_277 I954 +00 0 +.names I942 ZI942_298 +0 1 +.names ZI385_269 ZI877_269 I942 +00 0 +.names I812 ZI812_250 +0 1 +.names ZI580_221 ZI584_221 I812 +00 0 +.names I804 ZI804_244 +0 1 +.names ZI566_205 ZI570_205 I804 +00 0 +.names I955 ZI955_334 +0 1 +.names I896 I895 I894 I955 +000 0 +.names I814 ZI814_254 +0 1 +.names ZI590_225 ZI586_225 I814 +00 0 +.names I815 ZI815_256 +0 1 +.names ZI591_227 ZI587_227 I815 +00 0 +.names I882 ZI882_270 +0 1 +.names ZI758_235 ZI759_235 I882 +00 0 +.names I986 ZI986_304 +0 1 +.names I338 I932 I986 +00 0 +.names I1003 ZI1003_314 +0 1 +.names I497 I958 I1003 +00 0 +.names I1005 ZI1005_316 +0 1 +.names I515 I962 I1005 +00 0 +.names I875 ZI875_266 +0 1 +.names ZI751_233 ZI752_233 I875 +00 0 +.names I890 ZI890_274 +0 1 +.names ZI766_237 ZI767_237 I890 +00 0 +.names I897 ZI897_278 +0 1 +.names ZI773_239 ZI774_239 I897 +00 0 +.names I1027 ZI1027_326 +0 1 +.names I340 I1006 I1027 +00 0 +.names I907 ZI907_286 +0 1 +.names ZI807_247 ZI805_247 I907 +00 0 +.names I1036 ZI1036_336 +0 1 +.names I499 I1022 I1036 +00 0 +.names I904 ZI904_284 +0 1 +.names ZI800_241 ZI802_241 I904 +00 0 +.names I1038 ZI1038_338 +0 1 +.names I517 I1026 I1038 +00 0 +.names I908 ZI908_260 +0 1 +.names ZI808_249 ZI809_249 I908 +00 0 +.names I910 ZI910_288 +0 1 +.names ZI811_253 ZI813_253 I910 +00 0 +.names I905 ZI905_284 +0 1 +.names ZI801_243 ZI803_243 I905 +00 0 +.names I1000 ZI1000_456 +0 1 +.names ZI453_303 ZI954_303 I1000 +00 0 +.names I992 ZI992_450 +0 1 +.names ZI389_299 ZI942_299 I992 +00 0 +.names I909 ZI909_288 +0 1 +.names ZI810_251 ZI812_251 I909 +00 0 +.names I906 ZI906_286 +0 1 +.names ZI806_245 ZI804_245 I906 +00 0 +.names I911 ZI911_258 +0 1 +.names ZI816_255 ZI814_255 I911 +00 0 +.names I912 ZI912_258 +0 1 +.names ZI817_257 ZI815_257 I912 +00 0 +.names I944 ZI944_308 +0 1 +.names ZI390_271 ZI882_271 I944 +00 0 +.names I938 ZI938_306 +0 1 +.names ZI374_267 ZI875_267 I938 +00 0 +.names I950 ZI950_310 +0 1 +.names ZI438_275 ZI890_275 I950 +00 0 +.names I956 ZI956_312 +0 1 +.names ZI454_279 ZI897_279 I956 +00 0 +.names I1060 ZI1060_348 +0 1 +.names I342 I1039 I1060 +00 0 +.names I1069 ZI1069_366 +0 1 +.names I501 I1055 I1069 +00 0 +.names I1071 ZI1071_368 +0 1 +.names I519 I1059 I1071 +00 0 +.names I1030 ZI1030_330 +0 1 +.names I1012 I993 I1011 I1030 +000 0 +.names I1028 ZI1028_328 +0 1 +.names I1009 I1008 I989 I1028 +000 0 +.names I1032 ZI1032_332 +0 1 +.names I1016 I997 I1015 I1032 +000 0 +.names I963 ZI963_292 +0 1 +.names ZI904_285 ZI905_285 I963 +00 0 +.names I965 ZI965_290 +0 1 +.names ZI910_289 ZI909_289 I965 +00 0 +.names I964 ZI964_294 +0 1 +.names ZI907_287 ZI906_287 I964 +00 0 +.names I1034 ZI1034_334 +0 1 +.names I1019 I1018 I1001 I1034 +000 0 +.names I1013 ZI1013_320 +0 1 +.names ZI991_309 ZI944_309 I1013 +00 0 +.names I1103 ZI1103_386 +0 1 +.names I344 I1072 I1103 +00 0 +.names I1120 ZI1120_400 +0 1 +.names I503 I1098 I1120 +00 0 +.names I1122 ZI1122_402 +0 1 +.names I521 I1102 I1122 +00 0 +.names I1010 ZI1010_318 +0 1 +.names ZI987_307 ZI938_307 I1010 +00 0 +.names I1017 ZI1017_322 +0 1 +.names ZI995_311 ZI950_311 I1017 +00 0 +.names I1020 ZI1020_324 +0 1 +.names ZI999_313 ZI956_313 I1020 +00 0 +.names I1063 ZI1063_356 +0 1 +.names I994 I1045 I1044 I1063 +000 0 +.names I1061 ZI1061_352 +0 1 +.names I990 I1042 I1041 I1061 +000 0 +.names I1065 ZI1065_360 +0 1 +.names I998 I1049 I1048 I1065 +000 0 +.names I1067 ZI1067_364 +0 1 +.names I1002 I1052 I1051 I1067 +000 0 +.names I1046 ZI1046_342 +0 1 +.names ZI943_331 ZI1030_331 I1046 +00 0 +.names I1158 ZI1158_416 +0 1 +.names I346 I1123 I1158 +00 0 +.names I1171 ZI1171_430 +0 1 +.names I505 I1153 I1171 +00 0 +.names I1173 ZI1173_432 +0 1 +.names I523 I1157 I1173 +00 0 +.names I1043 ZI1043_340 +0 1 +.names ZI937_329 ZI1028_329 I1043 +00 0 +.names I1050 ZI1050_344 +0 1 +.names ZI949_333 ZI1032_333 I1050 +00 0 +.names I1053 ZI1053_346 +0 1 +.names ZI955_335 ZI1034_335 I1053 +00 0 +.names I1110 ZI1110_420 +0 1 +.names I883 I1084 I1083 I1110 +000 0 +.names I1031 ZI1031_452 +0 1 +.names ZI391_321 ZI1013_321 I1031 +00 0 +.names I1106 ZI1106_418 +0 1 +.names I876 I1078 I1077 I1106 +000 0 +.names I1114 ZI1114_424 +0 1 +.names I891 I1089 I1090 I1114 +000 0 +.names I1118 ZI1118_426 +0 1 +.names I898 I1096 I1095 I1118 +000 0 +.names I1035 ZI1035_458 +0 1 +.names ZI455_325 ZI1020_325 I1035 +00 0 +.names I1085 ZI1085_376 +0 1 +.names ZI761_357 ZI1063_357 I1085 +00 0 +.names I1203 ZI1203_446 +0 1 +.names I348 I1174 I1203 +00 0 +.names I1216 ZI1216_460 +0 1 +.names I507 I1198 I1216 +00 0 +.names I1218 ZI1218_462 +0 1 +.names I525 I1202 I1218 +00 0 +.names I1079 ZI1079_372 +0 1 +.names ZI754_353 ZI1061_353 I1079 +00 0 +.names I1091 ZI1091_380 +0 1 +.names ZI769_361 ZI1065_361 I1091 +00 0 +.names I1097 ZI1097_384 +0 1 +.names ZI776_365 ZI1067_365 I1097 +00 0 +.names I1064 ZI1064_354 +0 1 +.names ZI392_343 ZI1046_343 I1064 +00 0 +.names I1245 ZI1245_476 +0 1 +.names I235 I1216 I1245 +11 1 +.names I1062 ZI1062_350 +0 1 +.names ZI376_341 ZI1043_341 I1062 +00 0 +.names I1066 ZI1066_358 +0 1 +.names ZI440_345 ZI1050_345 I1066 +00 0 +.names I1068 ZI1068_362 +0 1 +.names ZI456_347 ZI1053_347 I1068 +00 0 +.names I1250 ZI1250_478 +0 1 +.names I350 I1219 I1250 +00 0 +.names I1263 ZI1263_488 +0 1 +.names I236 I1245 I1263 +11 1 +.names I1266 ZI1266_490 +0 1 +.names I527 I1249 I1266 +00 0 +.names I1111 ZI1111_390 +0 1 +.names ZI394_377 ZI1085_377 I1111 +00 0 +.names I1108 ZI1108_390 +0 1 +.names I945 I1080 I1081 I1108 +000 0 +.names I1287 ZI1287_500 +0 1 +.names I237 I1263 I1287 +11 1 +.names I1107 ZI1107_388 +0 1 +.names ZI378_373 ZI1079_373 I1107 +00 0 +.names I1104 ZI1104_388 +0 1 +.names I939 I1074 I1075 I1104 +000 0 +.names I1115 ZI1115_394 +0 1 +.names ZI442_381 ZI1091_381 I1115 +00 0 +.names I1112 ZI1112_394 +0 1 +.names I951 I1086 I1087 I1112 +000 0 +.names I1119 ZI1119_396 +0 1 +.names ZI458_385 ZI1097_385 I1119 +00 0 +.names I1116 ZI1116_396 +0 1 +.names I957 I1093 I1092 I1116 +000 0 +.names I1082 ZI1082_374 +0 1 +.names ZI878_355 ZI1064_355 I1082 +00 0 +.names I1292 ZI1292_502 +0 1 +.names I352 I1267 I1292 +00 0 +.names I1301 ZI1301_516 +0 1 +.names I238 I1287 I1301 +11 1 +.names I1304 ZI1304_518 +0 1 +.names I529 I1291 I1304 +00 0 +.names I1076 ZI1076_370 +0 1 +.names ZI871_351 ZI1062_351 I1076 +00 0 +.names I1088 ZI1088_378 +0 1 +.names ZI886_359 ZI1066_359 I1088 +00 0 +.names I1094 ZI1094_382 +0 1 +.names ZI893_363 ZI1068_363 I1094 +00 0 +.names I1161 ZI1161_420 +0 1 +.names I1132 I1131 I1130 I1161 +000 0 +.names I1327 ZI1327_532 +0 1 +.names I239 I1301 I1327 +11 1 +.names I1159 ZI1159_418 +0 1 +.names I1127 I1126 I1125 I1159 +000 0 +.names I1165 ZI1165_424 +0 1 +.names I1141 I1140 I1139 I1165 +000 0 +.names I1167 ZI1167_426 +0 1 +.names I1146 I1144 I1145 I1167 +000 0 +.names I1133 ZI1133_406 +0 1 +.names ZI1111_391 ZI1108_391 I1133 +00 0 +.names I1332 ZI1332_534 +0 1 +.names I354 I1305 I1332 +00 0 +.names I1345 ZI1345_540 +0 1 +.names I240 I1327 I1345 +11 1 +.names I1348 ZI1348_542 +0 1 +.names I531 I1331 I1348 +00 0 +.names I1128 ZI1128_404 +0 1 +.names ZI1107_389 ZI1104_389 I1128 +00 0 +.names I1142 ZI1142_410 +0 1 +.names ZI1115_395 ZI1112_395 I1142 +00 0 +.names I1147 ZI1147_412 +0 1 +.names ZI1119_397 ZI1116_397 I1147 +00 0 +.names I1109 ZI1109_586 +0 1 +.names ZI393_375 ZI1082_375 I1109 +00 0 +.names I1206 ZI1206_626 +0 1 +.names I1134 I1180 I1206 +00 0 +.names I1365 ZI1365_548 +0 1 +.names I241 I1345 I1365 +11 1 +.names I1204 ZI1204_452 +0 1 +.names I1129 I1177 I1204 +00 0 +.names I1105 ZI1105_392 +0 1 +.names ZI377_371 ZI1076_371 I1105 +00 0 +.names I1210 ZI1210_458 +0 1 +.names I1143 I1188 I1210 +00 0 +.names I1113 ZI1113_398 +0 1 +.names ZI441_379 ZI1088_379 I1113 +00 0 +.names I1117 ZI1117_590 +0 1 +.names ZI457_383 ZI1094_383 I1117 +00 0 +.names I1212 ZI1212_632 +0 1 +.names I1148 I1191 I1212 +00 0 +.names I1181 ZI1181_436 +0 1 +.names ZI1110_421 ZI1161_421 I1181 +00 0 +.names I1370 ZI1370_550 +0 1 +.names I356 I1349 I1370 +00 0 +.names I1377 ZI1377_556 +0 1 +.names I533 I1369 I1377 +00 0 +.names I1178 ZI1178_434 +0 1 +.names ZI1106_419 ZI1159_419 I1178 +00 0 +.names I1189 ZI1189_440 +0 1 +.names ZI1114_425 ZI1165_425 I1189 +00 0 +.names I1192 ZI1192_442 +0 1 +.names ZI1118_427 ZI1167_427 I1192 +00 0 +.names I1162 ZI1162_606 +0 1 +.names ZI395_407 ZI1133_407 I1162 +00 0 +.names I1160 ZI1160_422 +0 1 +.names ZI379_405 ZI1128_405 I1160 +00 0 +.names I1255 ZI1255_504 +0 1 +.names I1047 I1229 I1228 I1255 +000 0 +.names I1163 ZI1163_448 +0 1 +.names I763 I1136 I1135 I1163 +000 0 +.names I1166 ZI1166_428 +0 1 +.names ZI443_411 ZI1142_411 I1166 +00 0 +.names I1261 ZI1261_510 +0 1 +.names I1054 I1240 I1241 I1261 +000 0 +.names I1169 ZI1169_454 +0 1 +.names I778 I1150 I1149 I1169 +000 0 +.names I1168 ZI1168_610 +0 1 +.names ZI459_413 ZI1147_413 I1168 +00 0 +.names I1389 ZI1389_562 +0 1 +.names I358 I1378 I1389 +00 0 +.names I1395 ZI1395_572 +0 1 +.names I535 I1388 I1395 +00 0 +.names I1230 ZI1230_468 +0 1 +.names ZI1031_453 ZI1204_453 I1230 +00 0 +.names I1137 ZI1137_408 +0 1 +.names ZI381_393 ZI1105_393 I1137 +00 0 +.names I1242 ZI1242_474 +0 1 +.names ZI1035_459 ZI1210_459 I1242 +00 0 +.names I1151 ZI1151_414 +0 1 +.names ZI445_399 ZI1113_399 I1151 +00 0 +.names I1207 ZI1207_624 +0 1 +.names ZI396_437 ZI1181_437 I1207 +00 0 +.names I1208 ZI1208_480 +0 1 +.names I884 I1183 I1182 I1208 +000 0 +.names I1205 ZI1205_450 +0 1 +.names ZI380_435 ZI1178_435 I1205 +00 0 +.names I1214 ZI1214_484 +0 1 +.names I899 I1194 I1193 I1214 +000 0 +.names I1211 ZI1211_456 +0 1 +.names ZI444_441 ZI1189_441 I1211 +00 0 +.names I1213 ZI1213_630 +0 1 +.names ZI460_443 ZI1192_443 I1213 +00 0 +.names I1413 ZI1413_582 +0 1 +.names I360 I1396 I1413 +00 0 +.names I1423 ZI1423_592 +0 1 +.names I537 I1412 I1423 +00 0 +.names I1184 ZI1184_438 +0 1 +.names ZI756_423 ZI1160_423 I1184 +00 0 +.names I1195 ZI1195_444 +0 1 +.names ZI771_429 ZI1166_429 I1195 +00 0 +.names I1256 ZI1256_482 +0 1 +.names ZI402_469 ZI1230_469 I1256 +00 0 +.names I1253 ZI1253_482 +0 1 +.names I1014 I1226 I1225 I1253 +000 0 +.names I1259 ZI1259_486 +0 1 +.names I1021 I1237 I1238 I1259 +000 0 +.names I1262 ZI1262_486 +0 1 +.names ZI466_475 ZI1242_475 I1262 +00 0 +.names I1445 ZI1445_602 +0 1 +.names I362 I1424 I1445 +00 0 +.names I1455 ZI1455_612 +0 1 +.names I539 I1444 I1455 +00 0 +.names I1227 ZI1227_466 +0 1 +.names ZI992_451 ZI1205_451 I1227 +00 0 +.names I1239 ZI1239_472 +0 1 +.names ZI1000_457 ZI1211_457 I1239 +00 0 +.names I1209 ZI1209_448 +0 1 +.names ZI398_439 ZI1184_439 I1209 +00 0 +.names I1295 ZI1295_504 +0 1 +.names I1274 I1272 I1273 I1295 +000 0 +.names I1215 ZI1215_454 +0 1 +.names ZI462_445 ZI1195_445 I1215 +00 0 +.names I1299 ZI1299_510 +0 1 +.names I1282 I1281 I1283 I1299 +000 0 +.names I1483 ZI1483_634 +0 1 +.names I541 I1473 I1483 +00 0 +.names I1275 ZI1275_494 +0 1 +.names ZI1256_483 ZI1253_483 I1275 +00 0 +.names I1284 ZI1284_498 +0 1 +.names ZI1259_487 ZI1262_487 I1284 +00 0 +.names I1251 ZI1251_480 +0 1 +.names I1185 I1222 I1221 I1251 +000 0 +.names I1333 ZI1333_566 +0 1 +.names I1276 I1308 I1307 I1333 +000 0 +.names I1254 ZI1254_506 +0 1 +.names ZI401_467 ZI1227_467 I1254 +00 0 +.names I1257 ZI1257_484 +0 1 +.names I1196 I1233 I1234 I1257 +000 0 +.names I1260 ZI1260_512 +0 1 +.names ZI465_473 ZI1239_473 I1260 +00 0 +.names I1339 ZI1339_570 +0 1 +.names I1285 I1317 I1318 I1339 +000 0 +.names I1520 ZI1520_656 +0 1 +.names I543 I1506 I1520 +00 0 +.names I1223 ZI1223_464 +0 1 +.names ZI1163_449 ZI1209_449 I1223 +00 0 +.names I1309 ZI1309_520 +0 1 +.names ZI1255_505 ZI1295_505 I1309 +00 0 +.names I1235 ZI1235_470 +0 1 +.names ZI1169_455 ZI1215_455 I1235 +00 0 +.names I1319 ZI1319_526 +0 1 +.names ZI1261_511 ZI1299_511 I1319 +00 0 +.names I1293 ZI1293_508 +0 1 +.names I1224 I1270 I1269 I1293 +000 0 +.names I1296 ZI1296_508 +0 1 +.names ZI403_495 ZI1275_495 I1296 +00 0 +.names I1297 ZI1297_514 +0 1 +.names I1236 I1279 I1278 I1297 +000 0 +.names I1300 ZI1300_514 +0 1 +.names ZI467_499 ZI1284_499 I1300 +00 0 +.names I1550 ZI1550_678 +0 1 +.names I545 I1540 I1550 +00 0 +.names I1271 ZI1271_492 +0 1 +.names ZI1208_481 ZI1251_481 I1271 +00 0 +.names I1280 ZI1280_496 +0 1 +.names ZI1214_485 ZI1257_485 I1280 +00 0 +.names I1337 ZI1337_552 +0 1 +.names I1315 I1314 I1313 I1337 +000 0 +.names I1334 ZI1334_564 +0 1 +.names ZI404_521 ZI1309_521 I1334 +00 0 +.names I1340 ZI1340_568 +0 1 +.names ZI468_527 ZI1319_527 I1340 +00 0 +.names I1343 ZI1343_554 +0 1 +.names I1325 I1324 I1323 I1343 +000 0 +.names I1586 ZI1586_696 +0 1 +.names I547 I1572 I1586 +00 0 +.names I1316 ZI1316_524 +0 1 +.names ZI1293_509 ZI1296_509 I1316 +00 0 +.names I1326 ZI1326_530 +0 1 +.names ZI1297_515 ZI1300_515 I1326 +00 0 +.names I1294 ZI1294_506 +0 1 +.names ZI400_493 ZI1271_493 I1294 +00 0 +.names I1298 ZI1298_512 +0 1 +.names ZI464_497 ZI1280_497 I1298 +00 0 +.names I1608 ZI1608_706 +0 1 +.names I549 I1602 I1608 +00 0 +.names I1335 ZI1335_536 +0 1 +.names I1277 I1310 I1311 I1335 +000 0 +.names I1338 ZI1338_536 +0 1 +.names ZI406_525 ZI1316_525 I1338 +00 0 +.names I1341 ZI1341_538 +0 1 +.names I1286 I1320 I1321 I1341 +000 0 +.names I1344 ZI1344_538 +0 1 +.names ZI470_531 ZI1326_531 I1344 +00 0 +.names I1622 ZI1622_720 +0 1 +.names I551 I1616 I1622 +00 0 +.names I1312 ZI1312_522 +0 1 +.names ZI1254_507 ZI1294_507 I1312 +00 0 +.names I1322 ZI1322_528 +0 1 +.names ZI1260_513 ZI1298_513 I1322 +00 0 +.names I1371 ZI1371_552 +0 1 +.names I1352 I1351 I1353 I1371 +000 0 +.names I1373 ZI1373_554 +0 1 +.names I1359 I1358 I1360 I1373 +000 0 +.names I1646 ZI1646_734 +0 1 +.names I553 I1636 I1646 +00 0 +.names I1354 ZI1354_544 +0 1 +.names ZI1335_537 ZI1338_537 I1354 +00 0 +.names I1361 ZI1361_546 +0 1 +.names ZI1341_539 ZI1344_539 I1361 +00 0 +.names I1390 ZI1390_566 +0 1 +.names I1355 I1381 I1380 I1390 +000 0 +.names I1392 ZI1392_570 +0 1 +.names I1362 I1383 I1384 I1392 +000 0 +.names I1664 ZI1664_744 +0 1 +.names I555 I1658 I1664 +00 0 +.names I1382 ZI1382_558 +0 1 +.names ZI1337_553 ZI1371_553 I1382 +00 0 +.names I1385 ZI1385_560 +0 1 +.names ZI1343_555 ZI1373_555 I1385 +00 0 +.names I1416 ZI1416_604 +0 1 +.names I1357 I1402 I1401 I1416 +000 0 +.names I1420 ZI1420_608 +0 1 +.names I1364 I1407 I1408 I1420 +000 0 +.names I1403 ZI1403_576 +0 1 +.names ZI1333_567 ZI1390_567 I1403 +00 0 +.names I1409 ZI1409_580 +0 1 +.names ZI1339_571 ZI1392_571 I1409 +00 0 +.names I1391 ZI1391_564 +0 1 +.names ZI408_559 ZI1382_559 I1391 +00 0 +.names I1393 ZI1393_568 +0 1 +.names ZI472_561 ZI1385_561 I1393 +00 0 +.names I1414 ZI1414_584 +0 1 +.names I1356 I1399 I1398 I1414 +000 0 +.names I1417 ZI1417_584 +0 1 +.names ZI410_577 ZI1403_577 I1417 +00 0 +.names I1418 ZI1418_588 +0 1 +.names I1363 I1404 I1405 I1418 +000 0 +.names I1421 ZI1421_588 +0 1 +.names ZI474_581 ZI1409_581 I1421 +00 0 +.names I1400 ZI1400_574 +0 1 +.names ZI1334_565 ZI1391_565 I1400 +00 0 +.names I1406 ZI1406_578 +0 1 +.names ZI1340_569 ZI1393_569 I1406 +00 0 +.names I1446 ZI1446_604 +0 1 +.names I1427 I1428 I1426 I1446 +000 0 +.names I1450 ZI1450_608 +0 1 +.names I1435 I1434 I1436 I1450 +000 0 +.names I1429 ZI1429_594 +0 1 +.names ZI1414_585 ZI1417_585 I1429 +00 0 +.names I1437 ZI1437_598 +0 1 +.names ZI1418_589 ZI1421_589 I1437 +00 0 +.names I1415 ZI1415_586 +0 1 +.names ZI409_575 ZI1400_575 I1415 +00 0 +.names I1474 ZI1474_626 +0 1 +.names I1430 I1458 I1457 I1474 +000 0 +.names I1419 ZI1419_590 +0 1 +.names ZI473_579 ZI1406_579 I1419 +00 0 +.names I1478 ZI1478_632 +0 1 +.names I1438 I1464 I1465 I1478 +000 0 +.names I1459 ZI1459_614 +0 1 +.names ZI1416_605 ZI1446_605 I1459 +00 0 +.names I1466 ZI1466_618 +0 1 +.names ZI1420_609 ZI1450_609 I1466 +00 0 +.names I1448 ZI1448_622 +0 1 +.names I1138 I1432 I1431 I1448 +000 0 +.names I1511 ZI1511_666 +0 1 +.names I1232 I1491 I1492 I1511 +000 0 +.names I1447 ZI1447_606 +0 1 +.names ZI411_595 ZI1429_595 I1447 +00 0 +.names I1452 ZI1452_628 +0 1 +.names I1152 I1439 I1440 I1452 +000 0 +.names I1451 ZI1451_610 +0 1 +.names ZI475_599 ZI1437_599 I1451 +00 0 +.names I1517 ZI1517_672 +0 1 +.names I1244 I1502 I1501 I1517 +000 0 +.names I1433 ZI1433_596 +0 1 +.names ZI1109_587 ZI1415_587 I1433 +00 0 +.names I1493 ZI1493_640 +0 1 +.names ZI1206_627 ZI1474_627 I1493 +00 0 +.names I1441 ZI1441_600 +0 1 +.names ZI1117_591 ZI1419_591 I1441 +00 0 +.names I1503 ZI1503_646 +0 1 +.names ZI1212_633 ZI1478_633 I1503 +00 0 +.names I1475 ZI1475_624 +0 1 +.names ZI412_615 ZI1459_615 I1475 +00 0 +.names I1476 ZI1476_648 +0 1 +.names I1186 I1460 I1461 I1476 +000 0 +.names I1480 ZI1480_652 +0 1 +.names I1197 I1467 I1468 I1480 +000 0 +.names I1479 ZI1479_630 +0 1 +.names ZI476_619 ZI1466_619 I1479 +00 0 +.names I1462 ZI1462_616 +0 1 +.names ZI1162_607 ZI1447_607 I1462 +00 0 +.names I1469 ZI1469_620 +0 1 +.names ZI1168_611 ZI1451_611 I1469 +00 0 +.names I1512 ZI1512_650 +0 1 +.names ZI418_641 ZI1493_641 I1512 +00 0 +.names I1509 ZI1509_650 +0 1 +.names I1231 I1489 I1488 I1509 +000 0 +.names I1515 ZI1515_654 +0 1 +.names I1243 I1498 I1499 I1515 +000 0 +.names I1518 ZI1518_654 +0 1 +.names ZI482_647 ZI1503_647 I1518 +00 0 +.names I1490 ZI1490_638 +0 1 +.names ZI1207_625 ZI1475_625 I1490 +00 0 +.names I1500 ZI1500_644 +0 1 +.names ZI1213_631 ZI1479_631 I1500 +00 0 +.names I1543 ZI1543_666 +0 1 +.names I1526 I1524 I1525 I1543 +000 0 +.names I1477 ZI1477_622 +0 1 +.names ZI414_617 ZI1462_617 I1477 +00 0 +.names I1481 ZI1481_628 +0 1 +.names ZI478_621 ZI1469_621 I1481 +00 0 +.names I1547 ZI1547_672 +0 1 +.names I1534 I1535 I1533 I1547 +000 0 +.names I1527 ZI1527_660 +0 1 +.names ZI1512_651 ZI1509_651 I1527 +00 0 +.names I1536 ZI1536_664 +0 1 +.names ZI1515_655 ZI1518_655 I1536 +00 0 +.names I1573 ZI1573_714 +0 1 +.names I1528 I1552 I1551 I1573 +000 0 +.names I1510 ZI1510_668 +0 1 +.names ZI417_639 ZI1490_639 I1510 +00 0 +.names I1507 ZI1507_648 +0 1 +.names I1463 I1484 I1485 I1507 +000 0 +.names I1513 ZI1513_652 +0 1 +.names I1470 I1494 I1495 I1513 +000 0 +.names I1516 ZI1516_674 +0 1 +.names ZI481_645 ZI1500_645 I1516 +00 0 +.names I1579 ZI1579_718 +0 1 +.names I1537 I1562 I1561 I1579 +000 0 +.names I1553 ZI1553_680 +0 1 +.names ZI1511_667 ZI1543_667 I1553 +00 0 +.names I1486 ZI1486_636 +0 1 +.names ZI1448_623 ZI1477_623 I1486 +00 0 +.names I1496 ZI1496_642 +0 1 +.names ZI1452_629 ZI1481_629 I1496 +00 0 +.names I1563 ZI1563_686 +0 1 +.names ZI1517_673 ZI1547_673 I1563 +00 0 +.names I1544 ZI1544_670 +0 1 +.names ZI419_661 ZI1527_661 I1544 +00 0 +.names I1541 ZI1541_670 +0 1 +.names I1487 I1522 I1521 I1541 +000 0 +.names I1545 ZI1545_676 +0 1 +.names I1497 I1531 I1530 I1545 +000 0 +.names I1548 ZI1548_676 +0 1 +.names ZI483_665 ZI1536_665 I1548 +00 0 +.names I1523 ZI1523_658 +0 1 +.names ZI1476_649 ZI1507_649 I1523 +00 0 +.names I1532 ZI1532_662 +0 1 +.names ZI1480_653 ZI1513_653 I1532 +00 0 +.names I1574 ZI1574_712 +0 1 +.names ZI420_681 ZI1553_681 I1574 +00 0 +.names I1577 ZI1577_702 +0 1 +.names I1558 I1557 I1559 I1577 +000 0 +.names I1580 ZI1580_716 +0 1 +.names ZI484_687 ZI1563_687 I1580 +00 0 +.names I1583 ZI1583_704 +0 1 +.names I1569 I1568 I1567 I1583 +000 0 +.names I1560 ZI1560_684 +0 1 +.names ZI1544_671 ZI1541_671 I1560 +00 0 +.names I1570 ZI1570_690 +0 1 +.names ZI1545_677 ZI1548_677 I1570 +00 0 +.names I1542 ZI1542_668 +0 1 +.names ZI416_659 ZI1523_659 I1542 +00 0 +.names I1546 ZI1546_674 +0 1 +.names ZI480_663 ZI1532_663 I1546 +00 0 +.names I1575 ZI1575_692 +0 1 +.names I1529 I1554 I1555 I1575 +000 0 +.names I1578 ZI1578_692 +0 1 +.names ZI422_685 ZI1560_685 I1578 +00 0 +.names I1581 ZI1581_694 +0 1 +.names I1538 I1564 I1565 I1581 +000 0 +.names I1584 ZI1584_694 +0 1 +.names ZI486_691 ZI1570_691 I1584 +00 0 +.names I1556 ZI1556_682 +0 1 +.names ZI1510_669 ZI1542_669 I1556 +00 0 +.names I1566 ZI1566_688 +0 1 +.names ZI1516_675 ZI1546_675 I1566 +00 0 +.names I1603 ZI1603_702 +0 1 +.names I1588 I1589 I1587 I1603 +000 0 +.names I1605 ZI1605_704 +0 1 +.names I1595 I1596 I1594 I1605 +000 0 +.names I1590 ZI1590_698 +0 1 +.names ZI1575_693 ZI1578_693 I1590 +00 0 +.names I1597 ZI1597_700 +0 1 +.names ZI1581_695 ZI1584_695 I1597 +00 0 +.names I1617 ZI1617_714 +0 1 +.names I1591 I1609 I1610 I1617 +000 0 +.names I1619 ZI1619_718 +0 1 +.names I1598 I1612 I1613 I1619 +000 0 +.names I1611 ZI1611_708 +0 1 +.names ZI1577_703 ZI1603_703 I1611 +00 0 +.names I1614 ZI1614_710 +0 1 +.names ZI1583_705 ZI1605_705 I1614 +00 0 +.names I1639 ZI1639_740 +0 1 +.names I1593 I1626 I1627 I1639 +000 0 +.names I1643 ZI1643_742 +0 1 +.names I1600 I1633 I1632 I1643 +000 0 +.names I1628 ZI1628_724 +0 1 +.names ZI1573_715 ZI1617_715 I1628 +00 0 +.names I1634 ZI1634_728 +0 1 +.names ZI1579_719 ZI1619_719 I1634 +00 0 +.names I1618 ZI1618_712 +0 1 +.names ZI424_709 ZI1611_709 I1618 +00 0 +.names I1620 ZI1620_716 +0 1 +.names ZI488_711 ZI1614_711 I1620 +00 0 +.names I1640 ZI1640_730 +0 1 +.names ZI426_725 ZI1628_725 I1640 +00 0 +.names I1637 ZI1637_730 +0 1 +.names I1592 I1624 I1623 I1637 +000 0 +.names I1641 ZI1641_732 +0 1 +.names I1599 I1629 I1630 I1641 +000 0 +.names I1644 ZI1644_732 +0 1 +.names ZI490_729 ZI1634_729 I1644 +00 0 +.names I1625 ZI1625_722 +0 1 +.names ZI1574_713 ZI1618_713 I1625 +00 0 +.names I1631 ZI1631_726 +0 1 +.names ZI1580_717 ZI1620_717 I1631 +00 0 +.names I1659 ZI1659_740 +0 1 +.names I1649 I1647 I1648 I1659 +000 0 +.names I1661 ZI1661_742 +0 1 +.names I1653 I1654 I1652 I1661 +000 0 +.names I1650 ZI1650_736 +0 1 +.names ZI1640_731 ZI1637_731 I1650 +00 0 +.names I1655 ZI1655_738 +0 1 +.names ZI1641_733 ZI1644_733 I1655 +00 0 +.names I1667 ZI1667_746 +0 1 +.names ZI1639_741 ZI1659_741 I1667 +00 0 +.names I1670 ZI1670_748 +0 1 +.names ZI1643_743 ZI1661_743 I1670 +00 0 +.names I142 I176 I348 +11 1 +.names I127 I332 I739 +11 1 +.names I332 I126 I738 +11 1 +.names I332 I128 I740 +11 1 +.names I332 I118 I730 +11 1 +.names I332 I134 I746 +11 1 +.names I177 I143 I350 +11 1 +.names I277 I318 I547 +11 1 +.names I303 I262 I517 +11 1 +.names I332 I123 I735 +11 1 +.names I310 I269 I531 +11 1 +.names I332 I121 I733 +11 1 +.names I332 I124 I736 +11 1 +.names I71 I509 I792 +11 1 +.names I73 I509 I794 +11 1 +.names I70 I509 I791 +11 1 +.names I74 I509 I795 +11 1 +.names I68 I509 I789 +11 1 +.names I62 I509 I781 +11 1 +.names I64 I509 I785 +11 1 +.names I76 I509 I797 +11 1 +.names I72 I509 I793 +11 1 +.names I77 I509 I798 +11 1 +.names I69 I509 I790 +11 1 +.names I66 I509 I787 +11 1 +.names I75 I509 I796 +11 1 +.names I63 I509 I783 +11 1 +.names I67 I509 I788 +11 1 +.names I65 I509 I786 +11 1 +.names I178 I144 I352 +11 1 +.names I230 I254 I499 +11 1 +.names I202 I204 I388 +11 1 +.names I302 I261 I515 +11 1 +.names I332 I119 I731 +11 1 +.names I234 I258 I507 +11 1 +.names I171 I137 I338 +11 1 +.names I272 I313 I537 +11 1 +.names I332 I133 I745 +11 1 +.names I138 I172 I340 +11 1 +.names I204 I196 I368 +11 1 +.names I332 I130 I742 +11 1 +.names I268 I309 I529 +11 1 +.names I306 I265 I523 +11 1 +.names I275 I316 I543 +11 1 +.names I332 I125 I737 +11 1 +.names I253 I229 I497 +11 1 +.names I266 I307 I525 +11 1 +.names I273 I314 I539 +11 1 +.names I332 I122 I734 +11 1 +.names I332 I131 I743 +11 1 +.names I232 I256 I503 +11 1 +.names I204 I200 I384 +11 1 +.names I141 I175 I346 +11 1 +.names I136 I170 I336 +11 1 +.names I280 I321 I553 +11 1 +.names I304 I263 I519 +11 1 +.names I267 I308 I527 +11 1 +.names I319 I278 I549 +11 1 +.names I139 I173 I342 +11 1 +.names I29 I328 I682 +11 1 +.names I30 I328 I684 +11 1 +.names I19 I328 I662 +11 1 +.names I20 I328 I664 +11 1 +.names I33 I328 I690 +11 1 +.names I32 I328 I688 +11 1 +.names I28 I328 I680 +11 1 +.names I24 I328 I672 +11 1 +.names I25 I328 I674 +11 1 +.names I31 I328 I686 +11 1 +.names I22 I328 I668 +11 1 +.names I21 I328 I666 +11 1 +.names I34 I328 I692 +11 1 +.names I35 I328 I694 +11 1 +.names I27 I328 I678 +11 1 +.names I23 I328 I670 +11 1 +.names I26 I328 I676 +11 1 +.names I146 I180 I356 +11 1 +.names I332 I120 I732 +11 1 +.names I182 I148 I360 +11 1 +.names I140 I174 I344 +11 1 +.names I252 I228 I495 +11 1 +.names I179 I145 I354 +11 1 +.names I305 I264 I521 +11 1 +.names I149 I183 I362 +11 1 +.names I260 I301 I513 +11 1 +.names I332 I132 I744 +11 1 +.names I204 I198 I372 +11 1 +.names I214 I220 I436 +11 1 +.names I216 I220 I448 +11 1 +.names I212 I220 I432 +11 1 +.names I332 I129 I741 +11 1 +.names I320 I279 I551 +11 1 +.names I5 I324 I325 I606 +111 1 +.names I15 I324 I325 I646 +111 1 +.names I7 I324 I325 I614 +111 1 +.names I12 I324 I325 I634 +111 1 +.names I17 I324 I325 I654 +111 1 +.names I10 I324 I325 I626 +111 1 +.names I8 I324 I325 I618 +111 1 +.names I13 I324 I325 I638 +111 1 +.names I4 I324 I325 I602 +111 1 +.names I14 I324 I325 I642 +111 1 +.names I6 I324 I325 I610 +111 1 +.names I11 I324 I325 I630 +111 1 +.names I2 I324 I325 I594 +111 1 +.names I18 I324 I325 I658 +111 1 +.names I16 I324 I325 I650 +111 1 +.names I9 I324 I325 I622 +111 1 +.names I3 I324 I325 I598 +111 1 +.names I312 I271 I535 +11 1 +.names I276 I317 I545 +11 1 +.names I255 I231 I501 +11 1 +.names I311 I270 I533 +11 1 +.names I322 I281 I555 +11 1 +.names I257 I233 I505 +11 1 +.names I274 I315 I541 +11 1 +.names I40 I330 I704 +11 1 +.names I46 I330 I716 +11 1 +.names I37 I330 I698 +11 1 +.names I36 I330 I696 +11 1 +.names I42 I330 I708 +11 1 +.names I38 I330 I700 +11 1 +.names I49 I330 I722 +11 1 +.names I50 I330 I724 +11 1 +.names I41 I330 I706 +11 1 +.names I44 I330 I712 +11 1 +.names I45 I330 I714 +11 1 +.names I52 I330 I728 +11 1 +.names I48 I330 I720 +11 1 +.names I51 I330 I726 +11 1 +.names I47 I330 I718 +11 1 +.names I39 I330 I702 +11 1 +.names I43 I330 I710 +11 1 +.names I181 I147 I358 +11 1 +.names I220 I218 I452 +11 1 +.names I254 ZI230_43 ZI230_44 +11 1 +.names I309 ZI268_72 ZI268_73 +11 1 +.names I318 ZI277_90 ZI277_91 +11 1 +.names I270 ZI311_76 ZI311_77 +11 1 +.names I279 ZI320_94 ZI320_95 +11 1 +.names I300 ZI259_53 ZI259_54 +11 1 +.names I227 ZI251_37 ZI251_38 +11 1 +.names I148 ZI182_31 ZI182_32 +11 1 +.names I174 ZI182_112 ZI182_113 +11 1 +.names I315 ZI274_84 ZI274_85 +11 1 +.names I258 ZI234_51 ZI234_52 +11 1 +.names I316 ZI275_86 ZI275_87 +11 1 +.names I283 ZI291_142 ZI291_143 +11 1 +.names I262 ZI303_60 ZI303_61 +11 1 +.names I176 ZI142_19 ZI142_20 +11 1 +.names I150 ZI142_132 ZI142_133 +11 1 +.names I85 ZI93_158 ZI93_159 +11 1 +.names I142 ZI176_19 ZI176_20 +11 1 +.names I184 ZI176_116 ZI176_117 +11 1 +.names I229 ZI253_41 ZI253_42 +11 1 +.names I135 ZI169_5 ZI169_6 +11 1 +.names I177 ZI169_102 ZI169_103 +11 1 +.names I287 ZI295_150 ZI295_151 +11 1 +.names I96 ZI88_164 ZI88_165 +11 1 +.names I183 ZI149_33 ZI149_34 +11 1 +.names I141 ZI149_130 ZI149_131 +11 1 +.names I284 ZI292_144 ZI292_145 +11 1 +.names I88 ZI96_164 ZI96_165 +11 1 +.names I86 ZI94_160 ZI94_161 +11 1 +.names I291 ZI283_142 ZI283_143 +11 1 +.names I261 ZI302_58 ZI302_59 +11 1 +.names I292 ZI284_144 ZI284_145 +11 1 +.names I256 ZI232_47 ZI232_48 +11 1 +.names I169 ZI177_102 ZI177_103 +11 1 +.names I143 ZI177_21 ZI177_22 +11 1 +.names I135 ZI143_118 ZI143_119 +11 1 +.names I177 ZI143_21 ZI143_22 +11 1 +.names I307 ZI266_68 ZI266_69 +11 1 +.names I295 ZI287_150 ZI287_151 +11 1 +.names I277 ZI318_90 ZI318_91 +11 1 +.names I269 ZI310_74 ZI310_75 +11 1 +.names I303 ZI262_60 ZI262_61 +11 1 +.names I313 ZI272_80 ZI272_81 +11 1 +.names I149 ZI141_130 ZI141_131 +11 1 +.names I175 ZI141_17 ZI141_18 +11 1 +.names I169 ZI135_5 ZI135_6 +11 1 +.names I143 ZI135_118 ZI135_119 +11 1 +.names I148 ZI140_128 ZI140_129 +11 1 +.names I174 ZI140_15 ZI140_16 +11 1 +.names I90 ZI98_168 ZI98_169 +11 1 +.names I310 ZI269_74 ZI269_75 +11 1 +.names I192 ZI188_138 ZI188_139 +11 1 +.names I138 ZI146_124 ZI146_125 +11 1 +.names I180 ZI146_27 ZI146_28 +11 1 +.names I170 ZI136_7 ZI136_8 +11 1 +.names I144 ZI136_120 ZI136_121 +11 1 +.names I179 ZI171_106 ZI171_107 +11 1 +.names I137 ZI171_9 ZI171_10 +11 1 +.names I170 ZI178_104 ZI178_105 +11 1 +.names I144 ZI178_23 ZI178_24 +11 1 +.names I288 ZI296_152 ZI296_153 +11 1 +.names I146 ZI138_124 ZI138_125 +11 1 +.names I172 ZI138_11 ZI138_12 +11 1 +.names I233 ZI257_49 ZI257_50 +11 1 +.names I317 ZI276_88 ZI276_89 +11 1 +.names I136 ZI144_120 ZI144_121 +11 1 +.names I178 ZI144_23 ZI144_24 +11 1 +.names I265 ZI306_66 ZI306_67 +11 1 +.names I189 ZI193_140 ZI193_141 +11 1 +.names I230 ZI254_43 ZI254_44 +11 1 +.names I302 ZI261_58 ZI261_59 +11 1 +.names I264 ZI305_64 ZI305_65 +11 1 +.names I188 ZI192_138 ZI192_139 +11 1 +.names I234 ZI258_51 ZI258_52 +11 1 +.names I285 ZI293_146 ZI293_147 +11 1 +.names I228 ZI252_39 ZI252_40 +11 1 +.names I271 ZI312_78 ZI312_79 +11 1 +.names I145 ZI137_122 ZI137_123 +11 1 +.names I171 ZI137_9 ZI137_10 +11 1 +.names I98 ZI90_168 ZI90_169 +11 1 +.names I173 ZI181_110 ZI181_111 +11 1 +.names I147 ZI181_29 ZI181_30 +11 1 +.names I272 ZI313_80 ZI313_81 +11 1 +.names I301 ZI260_56 ZI260_57 +11 1 +.names I180 ZI172_108 ZI172_109 +11 1 +.names I138 ZI172_11 ZI172_12 +11 1 +.names I99 ZI91_170 ZI91_171 +11 1 +.names I231 ZI255_45 ZI255_46 +11 1 +.names I142 ZI150_132 ZI150_133 +11 1 +.names I184 ZI150_35 ZI150_36 +11 1 +.names I186 ZI190_134 ZI190_135 +11 1 +.names I147 ZI139_126 ZI139_127 +11 1 +.names I173 ZI139_13 ZI139_14 +11 1 +.names I193 ZI189_140 ZI189_141 +11 1 +.names I268 ZI309_72 ZI309_73 +11 1 +.names I314 ZI273_82 ZI273_83 +11 1 +.names I282 ZI323_100 ZI323_101 +11 1 +.names I95 ZI87_162 ZI87_163 +11 1 +.names I294 ZI286_148 ZI286_149 +11 1 +.names I437 I433 I770 +11 1 +.names I321 ZI280_96 ZI280_97 +11 1 +.names I306 ZI265_66 ZI265_67 +11 1 +.names I323 ZI282_100 ZI282_101 +11 1 +.names I251 ZI227_37 ZI227_38 +11 1 +.names I275 ZI316_86 ZI316_87 +11 1 +.names I253 ZI229_41 ZI229_42 +11 1 +.names I263 ZI304_62 ZI304_63 +11 1 +.names I266 ZI307_68 ZI307_69 +11 1 +.names I273 ZI314_82 ZI314_83 +11 1 +.names I97 ZI89_166 ZI89_167 +11 1 +.names I100 ZI92_172 ZI92_173 +11 1 +.names I107 I325 I326 I619 +111 1 +.names I112 I325 I326 I639 +111 1 +.names I105 I325 I326 I611 +111 1 +.names I110 I325 I326 I631 +111 1 +.names I117 I325 I326 I659 +111 1 +.names I106 I325 I326 I615 +111 1 +.names I111 I325 I326 I635 +111 1 +.names I109 I325 I326 I627 +111 1 +.names I115 I325 I326 I651 +111 1 +.names I108 I325 I326 I623 +111 1 +.names I116 I325 I326 I655 +111 1 +.names I102 I325 I326 I599 +111 1 +.names I101 I325 I326 I595 +111 1 +.names I104 I325 I326 I607 +111 1 +.names I114 I325 I326 I647 +111 1 +.names I103 I325 I326 I603 +111 1 +.names I113 I325 I326 I643 +111 1 +.names I298 ZI290_156 ZI290_157 +11 1 +.names I281 ZI322_98 ZI322_99 +11 1 +.names I286 ZI294_148 ZI294_149 +11 1 +.names I278 ZI319_92 ZI319_93 +11 1 +.names I232 ZI256_47 ZI256_48 +11 1 +.names I171 ZI179_106 ZI179_107 +11 1 +.names I145 ZI179_25 ZI179_26 +11 1 +.names I308 ZI267_70 ZI267_71 +11 1 +.names I293 ZI285_146 ZI285_147 +11 1 +.names I89 ZI97_166 ZI97_167 +11 1 +.names I183 ZI175_114 ZI175_115 +11 1 +.names I141 ZI175_17 ZI175_18 +11 1 +.names I136 ZI170_7 ZI170_8 +11 1 +.names I178 ZI170_104 ZI170_105 +11 1 +.names I280 ZI321_96 ZI321_97 +11 1 +.names I289 ZI297_154 ZI297_155 +11 1 +.names I259 ZI300_53 ZI300_54 +11 1 +.names I304 ZI263_62 ZI263_63 +11 1 +.names I267 ZI308_70 ZI308_71 +11 1 +.names I319 ZI278_92 ZI278_93 +11 1 +.names I181 ZI173_110 ZI173_111 +11 1 +.names I139 ZI173_13 ZI173_14 +11 1 +.names I369 I373 I755 +11 1 +.names I110 I329 I681 +11 1 +.names I112 I329 I685 +11 1 +.names I104 I329 I669 +11 1 +.names I116 I329 I693 +11 1 +.names I113 I329 I687 +11 1 +.names I102 I329 I665 +11 1 +.names I111 I329 I683 +11 1 +.names I109 I329 I679 +11 1 +.names I103 I329 I667 +11 1 +.names I105 I329 I671 +11 1 +.names I101 I329 I663 +11 1 +.names I107 I329 I675 +11 1 +.names I108 I329 I677 +11 1 +.names I106 I329 I673 +11 1 +.names I115 I329 I691 +11 1 +.names I117 I329 I695 +11 1 +.names I114 I329 I689 +11 1 +.names I172 ZI180_108 ZI180_109 +11 1 +.names I146 ZI180_27 ZI180_28 +11 1 +.names I182 ZI148_31 ZI148_32 +11 1 +.names I140 ZI148_128 ZI148_129 +11 1 +.names I91 ZI99_170 ZI99_171 +11 1 +.names I140 ZI174_15 ZI174_16 +11 1 +.names I182 ZI174_112 ZI174_113 +11 1 +.names I252 ZI228_39 ZI228_40 +11 1 +.names I191 ZI187_136 ZI187_137 +11 1 +.names I137 ZI145_122 ZI145_123 +11 1 +.names I179 ZI145_25 ZI145_26 +11 1 +.names I190 ZI186_134 ZI186_135 +11 1 +.names I305 ZI264_64 ZI264_65 +11 1 +.names I175 ZI183_114 ZI183_115 +11 1 +.names I149 ZI183_33 ZI183_34 +11 1 +.names I260 ZI301_56 ZI301_57 +11 1 +.names I92 ZI100_172 ZI100_173 +11 1 +.names I187 ZI191_136 ZI191_137 +11 1 +.names I320 ZI279_94 ZI279_95 +11 1 +.names I142 I326 I327 I625 +111 1 +.names I118 I324 I327 I596 +111 1 +.names I122 I324 I327 I612 +111 1 +.names I127 I324 I327 I632 +111 1 +.names I324 I132 I327 I652 +111 1 +.names I151 I326 I327 I661 +111 1 +.names I140 I326 I327 I617 +111 1 +.names I145 I326 I327 I637 +111 1 +.names I126 I324 I327 I628 +111 1 +.names I124 I324 I327 I620 +111 1 +.names I139 I326 I327 I613 +111 1 +.names I144 I326 I327 I633 +111 1 +.names I138 I326 I327 I609 +111 1 +.names I148 I326 I327 I649 +111 1 +.names I150 I326 I327 I657 +111 1 +.names I324 I120 I327 I604 +111 1 +.names I130 I324 I327 I644 +111 1 +.names I149 I326 I327 I653 +111 1 +.names I136 I326 I327 I601 +111 1 +.names I146 I326 I327 I641 +111 1 +.names I123 I324 I327 I616 +111 1 +.names I128 I324 I327 I636 +111 1 +.names I137 I326 I327 I605 +111 1 +.names I147 I326 I327 I645 +111 1 +.names I134 I324 I327 I660 +111 1 +.names I133 I324 I327 I656 +111 1 +.names I135 I326 I327 I597 +111 1 +.names I143 I326 I327 I629 +111 1 +.names I121 I324 I327 I608 +111 1 +.names I324 I131 I327 I648 +111 1 +.names I119 I324 I327 I600 +111 1 +.names I324 I129 I327 I640 +111 1 +.names I125 I324 I327 I624 +111 1 +.names I141 I326 I327 I621 +111 1 +.names I296 ZI288_152 ZI288_153 +11 1 +.names I312 ZI271_78 ZI271_79 +11 1 +.names I276 ZI317_88 ZI317_89 +11 1 +.names I255 ZI231_45 ZI231_46 +11 1 +.names I87 ZI95_162 ZI95_163 +11 1 +.names I311 ZI270_76 ZI270_77 +11 1 +.names I290 ZI298_156 ZI298_157 +11 1 +.names I322 ZI281_98 ZI281_99 +11 1 +.names I257 ZI233_49 ZI233_50 +11 1 +.names I176 ZI184_116 ZI184_117 +11 1 +.names I150 ZI184_35 ZI184_36 +11 1 +.names I274 ZI315_84 ZI315_85 +11 1 +.names I449 I453 I777 +11 1 +.names I461 I445 I778 +11 1 +.names I385 I389 I762 +11 1 +.names I397 I381 I763 +11 1 +.names I297 ZI289_154 ZI289_155 +11 1 +.names I154 I331 I701 +11 1 +.names I156 I331 I705 +11 1 +.names I152 I331 I697 +11 1 +.names I157 I331 I707 +11 1 +.names I155 I331 I703 +11 1 +.names I168 I331 I729 +11 1 +.names I164 I331 I721 +11 1 +.names I163 I331 I719 +11 1 +.names I166 I331 I725 +11 1 +.names I159 I331 I711 +11 1 +.names I161 I331 I715 +11 1 +.names I167 I331 I727 +11 1 +.names I153 I331 I699 +11 1 +.names I165 I331 I723 +11 1 +.names I162 I331 I717 +11 1 +.names I160 I331 I713 +11 1 +.names I158 I331 I709 +11 1 +.names I139 ZI147_126 ZI147_127 +11 1 +.names I181 ZI147_29 ZI147_30 +11 1 +.names I93 ZI85_158 ZI85_159 +11 1 +.names I94 ZI86_160 ZI86_161 +11 1 +.names ZI386_182 I387 ZI386_183 +11 1 +.names ZI370_178 I371 ZI370_179 +11 1 +.names I394 I761 I883 +11 1 +.names I386 ZI387_182 ZI387_183 +11 1 +.names ZI367_176 I366 ZI367_177 +11 1 +.names ZI431_184 I430 ZI431_185 +11 1 +.names ZI435_186 I434 ZI435_187 +11 1 +.names ZI447_188 I446 ZI447_189 +11 1 +.names ZI383_180 I382 ZI383_181 +11 1 +.names I367 ZI366_176 ZI366_177 +11 1 +.names I374 I751 I874 +11 1 +.names I378 I754 I876 +11 1 +.names I370 ZI371_178 ZI371_179 +11 1 +.names I438 I766 I889 +11 1 +.names I431 ZI430_184 ZI430_185 +11 1 +.names ZI450_190 I451 ZI450_191 +11 1 +.names I442 I769 I891 +11 1 +.names I435 ZI434_186 ZI434_187 +11 1 +.names I454 I773 I896 +11 1 +.names I447 ZI446_188 ZI446_189 +11 1 +.names I390 I758 I881 +11 1 +.names I383 ZI382_180 ZI382_181 +11 1 +.names I450 ZI451_190 ZI451_191 +11 1 +.names I458 I776 I898 +11 1 +.names I393 I878 I945 +11 1 +.names I377 I871 I939 +11 1 +.names I441 I886 I951 +11 1 +.names ZI433_272 I885 ZI433_273 +11 1 +.names I437 I885 I947 +11 1 +.names I433 I885 I946 +11 1 +.names I457 I893 I957 +11 1 +.names I334 I337 I747 +11 1 +.names ZI334_174 I337 ZI334_175 +11 1 +.names I511 I510 I782 +11 1 +.names ZI259_54 ZI300_54 I510 +00 0 +.names I369 I870 I934 +11 1 +.names I373 I870 I935 +11 1 +.names ZI369_264 I870 ZI369_265 +11 1 +.names I493 I496 I779 +11 1 +.names ZI493_192 I496 ZI493_193 +11 1 +.names I512 I514 I799 +11 1 +.names ZI512_194 I514 ZI512_195 +11 1 +.names I449 I892 I952 +11 1 +.names I453 I892 I953 +11 1 +.names ZI449_276 I892 ZI449_277 +11 1 +.names ZI385_268 I877 ZI385_269 +11 1 +.names I389 I877 I941 +11 1 +.names I385 I877 I940 +11 1 +.names I333 I837 I917 +11 1 +.names I700 I701 I837 +00 0 +.names I333 I839 I919 +11 1 +.names I704 I705 I839 +00 0 +.names I333 I835 I915 +11 1 +.names I696 I697 I835 +00 0 +.names I333 I840 I920 +11 1 +.names I706 I707 I840 +00 0 +.names I333 I838 I918 +11 1 +.names I702 I703 I838 +00 0 +.names I333 I851 I931 +11 1 +.names I728 I729 I851 +00 0 +.names I333 I847 I927 +11 1 +.names I720 I721 I847 +00 0 +.names I333 I846 I926 +11 1 +.names I718 I719 I846 +00 0 +.names I333 I849 I929 +11 1 +.names I724 I725 I849 +00 0 +.names I333 I842 I922 +11 1 +.names I710 I711 I842 +00 0 +.names I333 I844 I924 +11 1 +.names I714 I715 I844 +00 0 +.names I333 I850 I930 +11 1 +.names I726 I727 I850 +00 0 +.names I333 I836 I916 +11 1 +.names I698 I699 I836 +00 0 +.names I333 I848 I928 +11 1 +.names I722 I723 I848 +00 0 +.names I333 I845 I925 +11 1 +.names I716 I717 I845 +00 0 +.names I333 I843 I923 +11 1 +.names I712 I713 I843 +00 0 +.names I333 I841 I921 +11 1 +.names I708 I709 I841 +00 0 +.names ZI589_230 I593 ZI589_231 +11 1 +.names ZI578_216 I582 ZI578_217 +11 1 +.names ZI579_218 I583 ZI579_219 +11 1 +.names ZI558_196 I562 ZI558_197 +11 1 +.names I578 ZI582_216 ZI582_217 +11 1 +.names ZI572_208 I568 ZI572_209 +11 1 +.names ZI566_204 I570 ZI566_205 +11 1 +.names ZI569_210 I573 ZI569_211 +11 1 +.names ZI567_206 I571 ZI567_207 +11 1 +.names ZI576_212 I574 ZI576_213 +11 1 +.names ZI591_226 I587 ZI591_227 +11 1 +.names ZI758_234 I759 ZI758_235 +11 1 +.names I758 I759 I879 +11 1 +.names I390 I759 I880 +11 1 +.names I569 ZI573_210 ZI573_211 +11 1 +.names ZI577_214 I575 ZI577_215 +11 1 +.names I433 ZI885_272 ZI885_273 +11 1 +.names ZI581_222 I585 ZI581_223 +11 1 +.names ZI560_200 I564 ZI560_201 +11 1 +.names ZI580_220 I584 ZI580_221 +11 1 +.names ZI590_224 I586 ZI590_225 +11 1 +.names I334 ZI337_174 ZI337_175 +11 1 +.names ZI559_198 I563 ZI559_199 +11 1 +.names I558 ZI562_196 ZI562_197 +11 1 +.names I369 ZI870_264 ZI870_265 +11 1 +.names ZI561_202 I565 ZI561_203 +11 1 +.names I567 ZI571_206 ZI571_207 +11 1 +.names ZI592_228 I588 ZI592_229 +11 1 +.names I559 ZI563_198 ZI563_199 +11 1 +.names I493 ZI496_192 ZI496_193 +11 1 +.names I572 ZI568_208 ZI568_209 +11 1 +.names I576 ZI574_212 ZI574_213 +11 1 +.names I560 ZI564_200 ZI564_201 +11 1 +.names I512 ZI514_194 ZI514_195 +11 1 +.names I589 ZI593_230 ZI593_231 +11 1 +.names ZI751_232 I752 ZI751_233 +11 1 +.names I751 I752 I872 +11 1 +.names I374 I752 I873 +11 1 +.names I766 I767 I887 +11 1 +.names I438 I767 I888 +11 1 +.names ZI766_236 I767 ZI766_237 +11 1 +.names I577 ZI575_214 ZI575_215 +11 1 +.names I579 ZI583_218 ZI583_219 +11 1 +.names I592 ZI588_228 ZI588_229 +11 1 +.names I581 ZI585_222 ZI585_223 +11 1 +.names I561 ZI565_202 ZI565_203 +11 1 +.names I449 ZI892_276 ZI892_277 +11 1 +.names I462 I771 I899 +11 1 +.names I398 I756 I884 +11 1 +.names I385 ZI877_268 ZI877_269 +11 1 +.names I580 ZI584_220 ZI584_221 +11 1 +.names I566 ZI570_204 ZI570_205 +11 1 +.names I454 I774 I895 +11 1 +.names ZI773_238 I774 ZI773_239 +11 1 +.names I773 I774 I894 +11 1 +.names I590 ZI586_224 ZI586_225 +11 1 +.names I591 ZI587_226 ZI587_227 +11 1 +.names I758 ZI759_234 ZI759_235 +11 1 +.names I439 I995 I1016 +11 1 +.names I339 I869 I932 +11 1 +.names ZI339_262 I869 ZI339_263 +11 1 +.names I375 I987 I1009 +11 1 +.names ZI498_280 I900 ZI498_281 +11 1 +.names I498 I900 I958 +11 1 +.names I516 I903 I962 +11 1 +.names ZI516_282 I903 ZI516_283 +11 1 +.names I751 ZI752_232 ZI752_233 +11 1 +.names I766 ZI767_236 ZI767_237 +11 1 +.names I455 I999 I1019 +11 1 +.names I391 I991 I1012 +11 1 +.names I773 ZI774_238 ZI774_239 +11 1 +.names I392 I943 I994 +11 1 +.names ZI437_300 I948 ZI437_301 +11 1 +.names I339 ZI869_262 ZI869_263 +11 1 +.names ZI373_296 I936 ZI373_297 +11 1 +.names I498 ZI900_280 ZI900_281 +11 1 +.names I516 ZI903_282 ZI903_283 +11 1 +.names I511 I784 I902 +11 1 +.names ZI512_195 ZI514_195 I784 +00 0 +.names I376 I937 I990 +11 1 +.names I440 I949 I998 +11 1 +.names ZI453_302 I954 ZI453_303 +11 1 +.names ZI389_298 I942 ZI389_299 +11 1 +.names I456 I955 I1002 +11 1 +.names ZI810_250 I812 ZI810_251 +11 1 +.names ZI390_270 I882 ZI390_271 +11 1 +.names ZI807_246 I805 ZI807_247 +11 1 +.names I437 ZI948_300 ZI948_301 +11 1 +.names I341 I986 I1006 +11 1 +.names ZI341_304 I986 ZI341_305 +11 1 +.names ZI800_240 I802 ZI800_241 +11 1 +.names I373 ZI936_296 ZI936_297 +11 1 +.names I807 ZI805_246 ZI805_247 +11 1 +.names ZI801_242 I803 ZI801_243 +11 1 +.names I500 I1003 I1022 +11 1 +.names ZI500_314 I1003 ZI500_315 +11 1 +.names ZI806_244 I804 ZI806_245 +11 1 +.names ZI808_248 I809 ZI808_249 +11 1 +.names I800 ZI802_240 ZI802_241 +11 1 +.names ZI518_316 I1005 ZI518_317 +11 1 +.names I518 I1005 I1026 +11 1 +.names ZI817_256 I815 ZI817_257 +11 1 +.names ZI374_266 I875 ZI374_267 +11 1 +.names ZI438_274 I890 ZI438_275 +11 1 +.names I808 ZI809_248 ZI809_249 +11 1 +.names ZI811_252 I813 ZI811_253 +11 1 +.names ZI816_254 I814 ZI816_255 +11 1 +.names I811 ZI813_252 ZI813_253 +11 1 +.names I801 ZI803_242 ZI803_243 +11 1 +.names I453 ZI954_302 ZI954_303 +11 1 +.names I389 ZI942_298 ZI942_299 +11 1 +.names I810 ZI812_250 ZI812_251 +11 1 +.names I806 ZI804_244 ZI804_245 +11 1 +.names ZI454_278 I897 ZI454_279 +11 1 +.names I816 ZI814_254 ZI814_255 +11 1 +.names I817 ZI815_256 ZI815_257 +11 1 +.names I390 ZI882_270 ZI882_271 +11 1 +.names I341 ZI986_304 ZI986_305 +11 1 +.names I500 ZI1003_314 ZI1003_315 +11 1 +.names I518 ZI1005_316 ZI1005_317 +11 1 +.names I511 I961 I1004 +11 1 +.names ZI516_283 ZI903_283 I961 +00 0 +.names I374 ZI875_266 ZI875_267 +11 1 +.names I438 ZI890_274 ZI890_275 +11 1 +.names I454 ZI897_278 ZI897_279 +11 1 +.names ZI343_326 I1027 ZI343_327 +11 1 +.names I343 I1027 I1039 +11 1 +.names ZI502_336 I1036 ZI502_337 +11 1 +.names I502 I1036 I1055 +11 1 +.names I520 I1038 I1059 +11 1 +.names ZI520_338 I1038 ZI520_339 +11 1 +.names ZI194_260 I908 ZI194_261 +11 1 +.names I465 I1000 I1021 +11 1 +.names I401 I992 I1014 +11 1 +.names I391 I944 I993 +11 1 +.names I991 I944 I1011 +11 1 +.names ZI991_308 I944 ZI991_309 +11 1 +.names I343 ZI1027_326 ZI1027_327 +11 1 +.names ZI907_286 I906 ZI907_287 +11 1 +.names I502 ZI1036_336 ZI1036_337 +11 1 +.names ZI904_284 I905 ZI904_285 +11 1 +.names I511 I1025 I1037 +11 1 +.names ZI518_317 ZI1005_317 I1025 +00 0 +.names I520 ZI1038_338 ZI1038_339 +11 1 +.names I987 I938 I1008 +11 1 +.names ZI987_306 I938 ZI987_307 +11 1 +.names I375 I938 I989 +11 1 +.names I439 I950 I997 +11 1 +.names I995 I950 I1015 +11 1 +.names ZI995_310 I950 ZI995_311 +11 1 +.names I194 ZI908_260 ZI908_261 +11 1 +.names ZI910_288 I909 ZI910_289 +11 1 +.names I904 ZI905_284 ZI905_285 +11 1 +.names I910 ZI909_288 ZI909_289 +11 1 +.names I907 ZI906_286 ZI906_287 +11 1 +.names I999 I956 I1018 +11 1 +.names ZI999_312 I956 ZI999_313 +11 1 +.names I455 I956 I1001 +11 1 +.names ZI911_258 I912 ZI911_259 +11 1 +.names I911 ZI912_258 ZI912_259 +11 1 +.names I991 ZI944_308 ZI944_309 +11 1 +.names ZI345_348 I1060 ZI345_349 +11 1 +.names I345 I1060 I1072 +11 1 +.names I504 I1069 I1098 +11 1 +.names ZI504_366 I1069 ZI504_367 +11 1 +.names ZI522_368 I1071 ZI522_369 +11 1 +.names I522 I1071 I1102 +11 1 +.names I987 ZI938_306 ZI938_307 +11 1 +.names I995 ZI950_310 ZI950_311 +11 1 +.names I999 ZI956_312 ZI956_313 +11 1 +.names I392 I1030 I1045 +11 1 +.names ZI943_330 I1030 ZI943_331 +11 1 +.names I943 I1030 I1044 +11 1 +.names I345 ZI1060_348 ZI1060_349 +11 1 +.names I504 ZI1069_366 ZI1069_367 +11 1 +.names I511 I1058 I1070 +11 1 +.names ZI520_339 ZI1038_339 I1058 +00 0 +.names I522 ZI1071_368 ZI1071_369 +11 1 +.names I376 I1028 I1042 +11 1 +.names ZI937_328 I1028 ZI937_329 +11 1 +.names I937 I1028 I1041 +11 1 +.names I440 I1032 I1049 +11 1 +.names I949 I1032 I1048 +11 1 +.names ZI949_332 I1032 ZI949_333 +11 1 +.names ZI185_292 I963 ZI185_293 +11 1 +.names ZI299_290 I965 ZI299_291 +11 1 +.names ZI151_294 I964 ZI151_295 +11 1 +.names I456 I1034 I1052 +11 1 +.names I955 I1034 I1051 +11 1 +.names ZI955_334 I1034 ZI955_335 +11 1 +.names I943 ZI1030_330 ZI1030_331 +11 1 +.names ZI391_320 I1013 ZI391_321 +11 1 +.names ZI347_386 I1103 ZI347_387 +11 1 +.names I347 I1103 I1123 +11 1 +.names ZI506_400 I1120 ZI506_401 +11 1 +.names I506 I1120 I1153 +11 1 +.names I524 I1122 I1157 +11 1 +.names ZI524_402 I1122 ZI524_403 +11 1 +.names ZI375_318 I1010 ZI375_319 +11 1 +.names I937 ZI1028_328 ZI1028_329 +11 1 +.names I949 ZI1032_332 ZI1032_333 +11 1 +.names ZI439_322 I1017 ZI439_323 +11 1 +.names I185 ZI963_292 ZI963_293 +11 1 +.names I299 ZI965_290 ZI965_291 +11 1 +.names I151 ZI964_294 ZI964_295 +11 1 +.names I955 ZI1034_334 ZI1034_335 +11 1 +.names ZI455_324 I1020 ZI455_325 +11 1 +.names I394 I1063 I1084 +11 1 +.names ZI761_356 I1063 ZI761_357 +11 1 +.names I761 I1063 I1083 +11 1 +.names I391 ZI1013_320 ZI1013_321 +11 1 +.names I347 ZI1103_386 ZI1103_387 +11 1 +.names I506 ZI1120_400 ZI1120_401 +11 1 +.names I511 I1101 I1121 +11 1 +.names ZI522_369 ZI1071_369 I1101 +00 0 +.names I524 ZI1122_402 ZI1122_403 +11 1 +.names I375 ZI1010_318 ZI1010_319 +11 1 +.names ZI754_352 I1061 ZI754_353 +11 1 +.names I378 I1061 I1078 +11 1 +.names I754 I1061 I1077 +11 1 +.names ZI769_360 I1065 ZI769_361 +11 1 +.names I769 I1065 I1089 +11 1 +.names I442 I1065 I1090 +11 1 +.names I439 ZI1017_322 ZI1017_323 +11 1 +.names ZI776_364 I1067 ZI776_365 +11 1 +.names I458 I1067 I1096 +11 1 +.names I776 I1067 I1095 +11 1 +.names I455 ZI1020_324 ZI1020_325 +11 1 +.names I761 ZI1063_356 ZI1063_357 +11 1 +.names ZI392_342 I1046 ZI392_343 +11 1 +.names ZI349_416 I1158 ZI349_417 +11 1 +.names I349 I1158 I1174 +11 1 +.names I508 I1171 I1198 +11 1 +.names ZI508_430 I1171 ZI508_431 +11 1 +.names ZI526_432 I1173 ZI526_433 +11 1 +.names I526 I1173 I1202 +11 1 +.names I754 ZI1061_352 ZI1061_353 +11 1 +.names ZI376_340 I1043 ZI376_341 +11 1 +.names I769 ZI1065_360 ZI1065_361 +11 1 +.names ZI440_344 I1050 ZI440_345 +11 1 +.names I776 ZI1067_364 ZI1067_365 +11 1 +.names ZI456_346 I1053 ZI456_347 +11 1 +.names I396 I1110 I1134 +11 1 +.names I392 ZI1046_342 ZI1046_343 +11 1 +.names I402 I1031 I1047 +11 1 +.names I349 ZI1158_416 ZI1158_417 +11 1 +.names I508 ZI1171_430 ZI1171_431 +11 1 +.names I526 ZI1173_432 ZI1173_433 +11 1 +.names I511 I1156 I1172 +11 1 +.names ZI524_403 ZI1122_403 I1156 +00 0 +.names I380 I1106 I1129 +11 1 +.names I376 ZI1043_340 ZI1043_341 +11 1 +.names I444 I1114 I1143 +11 1 +.names I440 ZI1050_344 ZI1050_345 +11 1 +.names I460 I1118 I1148 +11 1 +.names I456 ZI1053_346 ZI1053_347 +11 1 +.names I466 I1035 I1054 +11 1 +.names ZI394_376 I1085 ZI394_377 +11 1 +.names I351 I1203 I1219 +11 1 +.names ZI351_446 I1203 ZI351_447 +11 1 +.names ZI235_460 I1216 ZI235_461 +11 1 +.names I528 I1218 I1249 +11 1 +.names ZI528_462 I1218 ZI528_463 +11 1 +.names ZI378_372 I1079 ZI378_373 +11 1 +.names ZI442_380 I1091 ZI442_381 +11 1 +.names ZI458_384 I1097 ZI458_385 +11 1 +.names I394 ZI1085_376 ZI1085_377 +11 1 +.names ZI878_354 I1064 ZI878_355 +11 1 +.names I878 I1064 I1080 +11 1 +.names I393 I1064 I1081 +11 1 +.names I351 ZI1203_446 ZI1203_447 +11 1 +.names ZI236_476 I1245 ZI236_477 +11 1 +.names I235 ZI1216_460 ZI1216_461 +11 1 +.names I528 ZI1218_462 ZI1218_463 +11 1 +.names I511 I1201 I1217 +11 1 +.names ZI526_433 ZI1173_433 I1201 +00 0 +.names I378 ZI1079_372 ZI1079_373 +11 1 +.names I871 I1062 I1074 +11 1 +.names I377 I1062 I1075 +11 1 +.names ZI871_350 I1062 ZI871_351 +11 1 +.names I442 ZI1091_380 ZI1091_381 +11 1 +.names I886 I1066 I1086 +11 1 +.names I441 I1066 I1087 +11 1 +.names ZI886_358 I1066 ZI886_359 +11 1 +.names I458 ZI1097_384 ZI1097_385 +11 1 +.names I457 I1068 I1093 +11 1 +.names ZI893_362 I1068 ZI893_363 +11 1 +.names I893 I1068 I1092 +11 1 +.names I878 ZI1064_354 ZI1064_355 +11 1 +.names ZI353_478 I1250 ZI353_479 +11 1 +.names I353 I1250 I1267 +11 1 +.names ZI237_488 I1263 ZI237_489 +11 1 +.names I236 ZI1245_476 ZI1245_477 +11 1 +.names I530 I1266 I1291 +11 1 +.names ZI530_490 I1266 ZI530_491 +11 1 +.names I871 ZI1062_350 ZI1062_351 +11 1 +.names I886 ZI1066_358 ZI1066_359 +11 1 +.names I893 ZI1068_362 ZI1068_363 +11 1 +.names I395 I1111 I1132 +11 1 +.names I395 I1108 I1131 +11 1 +.names I1111 I1108 I1130 +11 1 +.names I353 ZI1250_478 ZI1250_479 +11 1 +.names I237 ZI1263_488 ZI1263_489 +11 1 +.names ZI238_500 I1287 ZI238_501 +11 1 +.names I530 ZI1266_490 ZI1266_491 +11 1 +.names I1248 I511 I1265 +11 1 +.names I379 I1107 I1127 +11 1 +.names I379 I1104 I1126 +11 1 +.names I1107 I1104 I1125 +11 1 +.names I443 I1115 I1141 +11 1 +.names I443 I1112 I1140 +11 1 +.names I1115 I1112 I1139 +11 1 +.names I459 I1119 I1146 +11 1 +.names I1119 I1116 I1144 +11 1 +.names I459 I1116 I1145 +11 1 +.names ZI1111_390 I1108 ZI1111_391 +11 1 +.names ZI393_374 I1082 ZI393_375 +11 1 +.names I1111 ZI1108_390 ZI1108_391 +11 1 +.names I355 I1292 I1305 +11 1 +.names ZI355_502 I1292 ZI355_503 +11 1 +.names ZI239_516 I1301 ZI239_517 +11 1 +.names I238 ZI1287_500 ZI1287_501 +11 1 +.names I532 I1304 I1331 +11 1 +.names ZI532_518 I1304 ZI532_519 +11 1 +.names ZI1107_388 I1104 ZI1107_389 +11 1 +.names I1107 ZI1104_388 ZI1104_389 +11 1 +.names ZI377_370 I1076 ZI377_371 +11 1 +.names ZI1115_394 I1112 ZI1115_395 +11 1 +.names I1115 ZI1112_394 ZI1112_395 +11 1 +.names ZI441_378 I1088 ZI441_379 +11 1 +.names ZI1119_396 I1116 ZI1119_397 +11 1 +.names ZI457_382 I1094 ZI457_383 +11 1 +.names I1119 ZI1116_396 ZI1116_397 +11 1 +.names I393 ZI1082_374 ZI1082_375 +11 1 +.names ZI1110_420 I1161 ZI1110_421 +11 1 +.names I396 I1161 I1180 +11 1 +.names I355 ZI1292_502 ZI1292_503 +11 1 +.names I239 ZI1301_516 ZI1301_517 +11 1 +.names ZI240_532 I1327 ZI240_533 +11 1 +.names I532 ZI1304_518 ZI1304_519 +11 1 +.names I1290 I511 I1303 +11 1 +.names ZI1106_418 I1159 ZI1106_419 +11 1 +.names I380 I1159 I1177 +11 1 +.names I377 ZI1076_370 ZI1076_371 +11 1 +.names I444 I1165 I1188 +11 1 +.names ZI1114_424 I1165 ZI1114_425 +11 1 +.names I441 ZI1088_378 ZI1088_379 +11 1 +.names I457 ZI1094_382 ZI1094_383 +11 1 +.names I460 I1167 I1191 +11 1 +.names ZI1118_426 I1167 ZI1118_427 +11 1 +.names ZI395_406 I1133 ZI395_407 +11 1 +.names I1110 ZI1161_420 ZI1161_421 +11 1 +.names ZI357_534 I1332 ZI357_535 +11 1 +.names I357 I1332 I1349 +11 1 +.names I240 ZI1327_532 ZI1327_533 +11 1 +.names ZI241_540 I1345 ZI241_541 +11 1 +.names ZI534_542 I1348 ZI534_543 +11 1 +.names I534 I1348 I1369 +11 1 +.names ZI379_404 I1128 ZI379_405 +11 1 +.names I1106 ZI1159_418 ZI1159_419 +11 1 +.names ZI443_410 I1142 ZI443_411 +11 1 +.names I1114 ZI1165_424 ZI1165_425 +11 1 +.names ZI459_412 I1147 ZI459_413 +11 1 +.names I1118 ZI1167_426 ZI1167_427 +11 1 +.names I413 I1109 I1138 +11 1 +.names I395 ZI1133_406 ZI1133_407 +11 1 +.names I418 I1206 I1232 +11 1 +.names I357 ZI1332_534 ZI1332_535 +11 1 +.names I241 ZI1345_540 ZI1345_541 +11 1 +.names ZI242_548 I1365 ZI242_549 +11 1 +.names I534 ZI1348_542 ZI1348_543 +11 1 +.names I1330 I511 I1347 +11 1 +.names I379 ZI1128_404 ZI1128_405 +11 1 +.names ZI1031_452 I1204 ZI1031_453 +11 1 +.names I402 I1204 I1229 +11 1 +.names I1031 I1204 I1228 +11 1 +.names I397 I1105 I1136 +11 1 +.names I381 I1105 I1135 +11 1 +.names ZI381_392 I1105 ZI381_393 +11 1 +.names I443 ZI1142_410 ZI1142_411 +11 1 +.names I1035 I1210 I1240 +11 1 +.names ZI1035_458 I1210 ZI1035_459 +11 1 +.names I466 I1210 I1241 +11 1 +.names I461 I1113 I1150 +11 1 +.names ZI445_398 I1113 ZI445_399 +11 1 +.names I445 I1113 I1149 +11 1 +.names I477 I1117 I1152 +11 1 +.names I459 ZI1147_412 ZI1147_413 +11 1 +.names I482 I1212 I1244 +11 1 +.names ZI396_436 I1181 ZI396_437 +11 1 +.names ZI359_550 I1370 ZI359_551 +11 1 +.names I359 I1370 I1378 +11 1 +.names I242 ZI1365_548 ZI1365_549 +11 1 +.names I536 I1377 I1388 +11 1 +.names ZI536_556 I1377 ZI536_557 +11 1 +.names I1031 ZI1204_452 ZI1204_453 +11 1 +.names ZI380_434 I1178 ZI380_435 +11 1 +.names I381 ZI1105_392 ZI1105_393 +11 1 +.names ZI444_440 I1189 ZI444_441 +11 1 +.names I1035 ZI1210_458 ZI1210_459 +11 1 +.names I445 ZI1113_398 ZI1113_399 +11 1 +.names ZI460_442 I1192 ZI460_443 +11 1 +.names I414 I1162 I1186 +11 1 +.names I396 ZI1181_436 ZI1181_437 +11 1 +.names I359 ZI1370_550 ZI1370_551 +11 1 +.names I536 ZI1377_556 ZI1377_557 +11 1 +.names I1368 I511 I1376 +11 1 +.names I398 I1160 I1183 +11 1 +.names ZI756_422 I1160 ZI756_423 +11 1 +.names I756 I1160 I1182 +11 1 +.names I404 I1255 I1276 +11 1 +.names I380 ZI1178_434 ZI1178_435 +11 1 +.names I399 I1163 I1185 +11 1 +.names ZI771_428 I1166 ZI771_429 +11 1 +.names I462 I1166 I1194 +11 1 +.names I771 I1166 I1193 +11 1 +.names I444 ZI1189_440 ZI1189_441 +11 1 +.names I468 I1261 I1285 +11 1 +.names I463 I1169 I1196 +11 1 +.names I478 I1168 I1197 +11 1 +.names I460 ZI1192_442 ZI1192_443 +11 1 +.names I361 I1389 I1396 +11 1 +.names ZI361_562 I1389 ZI361_563 +11 1 +.names I538 I1395 I1412 +11 1 +.names ZI538_572 I1395 ZI538_573 +11 1 +.names I756 ZI1160_422 ZI1160_423 +11 1 +.names ZI402_468 I1230 ZI402_469 +11 1 +.names ZI397_408 I1137 ZI397_409 +11 1 +.names I771 ZI1166_428 ZI1166_429 +11 1 +.names ZI466_474 I1242 ZI466_475 +11 1 +.names ZI461_414 I1151 ZI461_415 +11 1 +.names I417 I1207 I1231 +11 1 +.names I361 ZI1389_562 ZI1389_563 +11 1 +.names I538 ZI1395_572 ZI1395_573 +11 1 +.names I1387 I511 I1394 +11 1 +.names I400 I1208 I1224 +11 1 +.names I402 ZI1230_468 ZI1230_469 +11 1 +.names I401 I1205 I1226 +11 1 +.names I992 I1205 I1225 +11 1 +.names ZI992_450 I1205 ZI992_451 +11 1 +.names I397 ZI1137_408 ZI1137_409 +11 1 +.names I464 I1214 I1236 +11 1 +.names ZI1000_456 I1211 ZI1000_457 +11 1 +.names I1000 I1211 I1237 +11 1 +.names I465 I1211 I1238 +11 1 +.names I466 ZI1242_474 ZI1242_475 +11 1 +.names I461 ZI1151_414 ZI1151_415 +11 1 +.names I481 I1213 I1243 +11 1 +.names ZI363_582 I1413 ZI363_583 +11 1 +.names I363 I1413 I1424 +11 1 +.names ZI540_592 I1423 ZI540_593 +11 1 +.names I540 I1423 I1444 +11 1 +.names ZI398_438 I1184 ZI398_439 +11 1 +.names I992 ZI1205_450 ZI1205_451 +11 1 +.names ZI462_444 I1195 ZI462_445 +11 1 +.names I1000 ZI1211_456 ZI1211_457 +11 1 +.names I363 ZI1413_582 ZI1413_583 +11 1 +.names I540 ZI1423_592 ZI1423_593 +11 1 +.names I1411 I511 I1422 +11 1 +.names I398 ZI1184_438 ZI1184_439 +11 1 +.names I403 I1256 I1274 +11 1 +.names I1256 I1253 I1272 +11 1 +.names I403 I1253 I1273 +11 1 +.names I462 ZI1195_444 ZI1195_445 +11 1 +.names I467 I1259 I1282 +11 1 +.names I1259 I1262 I1281 +11 1 +.names I467 I1262 I1283 +11 1 +.names ZI364_602 I1445 ZI364_603 +11 1 +.names ZI542_612 I1455 ZI542_613 +11 1 +.names I542 I1455 I1473 +11 1 +.names ZI1256_482 I1253 ZI1256_483 +11 1 +.names I1256 ZI1253_482 ZI1253_483 +11 1 +.names ZI401_466 I1227 ZI401_467 +11 1 +.names ZI465_472 I1239 ZI465_473 +11 1 +.names ZI1259_486 I1262 ZI1259_487 +11 1 +.names I1259 ZI1262_486 ZI1262_487 +11 1 +.names I364 ZI1445_602 ZI1445_603 +11 1 +.names I1443 I511 I1454 +11 1 +.names I542 ZI1455_612 ZI1455_613 +11 1 +.names ZI1163_448 I1209 ZI1163_449 +11 1 +.names I399 I1209 I1222 +11 1 +.names I1163 I1209 I1221 +11 1 +.names I404 I1295 I1308 +11 1 +.names ZI1255_504 I1295 ZI1255_505 +11 1 +.names I1255 I1295 I1307 +11 1 +.names I401 ZI1227_466 ZI1227_467 +11 1 +.names I1169 I1215 I1233 +11 1 +.names ZI1169_454 I1215 ZI1169_455 +11 1 +.names I463 I1215 I1234 +11 1 +.names I465 ZI1239_472 ZI1239_473 +11 1 +.names ZI1261_510 I1299 ZI1261_511 +11 1 +.names I1261 I1299 I1317 +11 1 +.names I468 I1299 I1318 +11 1 +.names ZI544_634 I1483 ZI544_635 +11 1 +.names I544 I1483 I1506 +11 1 +.names I1163 ZI1209_448 ZI1209_449 +11 1 +.names ZI403_494 I1275 ZI403_495 +11 1 +.names I1255 ZI1295_504 ZI1295_505 +11 1 +.names I1169 ZI1215_454 ZI1215_455 +11 1 +.names I1261 ZI1299_510 ZI1299_511 +11 1 +.names ZI467_498 I1284 ZI467_499 +11 1 +.names I544 ZI1483_634 ZI1483_635 +11 1 +.names I1472 I511 I1482 +11 1 +.names ZI1208_480 I1251 ZI1208_481 +11 1 +.names I400 I1251 I1270 +11 1 +.names I1208 I1251 I1269 +11 1 +.names I403 ZI1275_494 ZI1275_495 +11 1 +.names I410 I1333 I1357 +11 1 +.names I405 I1254 I1277 +11 1 +.names ZI1214_484 I1257 ZI1214_485 +11 1 +.names I464 I1257 I1279 +11 1 +.names I1214 I1257 I1278 +11 1 +.names I469 I1260 I1286 +11 1 +.names I474 I1339 I1364 +11 1 +.names I467 ZI1284_498 ZI1284_499 +11 1 +.names I546 I1520 I1540 +11 1 +.names ZI546_656 I1520 ZI546_657 +11 1 +.names ZI399_464 I1223 ZI399_465 +11 1 +.names I1208 ZI1251_480 ZI1251_481 +11 1 +.names ZI404_520 I1309 ZI404_521 +11 1 +.names ZI463_470 I1235 ZI463_471 +11 1 +.names I1214 ZI1257_484 ZI1257_485 +11 1 +.names ZI468_526 I1319 ZI468_527 +11 1 +.names I546 ZI1520_656 ZI1520_657 +11 1 +.names I399 ZI1223_464 ZI1223_465 +11 1 +.names I406 I1293 I1315 +11 1 +.names I406 I1296 I1314 +11 1 +.names I1293 I1296 I1313 +11 1 +.names I404 ZI1309_520 ZI1309_521 +11 1 +.names I463 ZI1235_470 ZI1235_471 +11 1 +.names I470 I1297 I1325 +11 1 +.names I468 ZI1319_526 ZI1319_527 +11 1 +.names I470 I1300 I1324 +11 1 +.names I1297 I1300 I1323 +11 1 +.names ZI548_678 I1550 ZI548_679 +11 1 +.names I548 I1550 I1572 +11 1 +.names ZI400_492 I1271 ZI400_493 +11 1 +.names ZI1293_508 I1296 ZI1293_509 +11 1 +.names I1293 ZI1296_508 ZI1296_509 +11 1 +.names ZI1297_514 I1300 ZI1297_515 +11 1 +.names ZI464_496 I1280 ZI464_497 +11 1 +.names I1297 ZI1300_514 ZI1300_515 +11 1 +.names I548 ZI1550_678 ZI1550_679 +11 1 +.names I400 ZI1271_492 ZI1271_493 +11 1 +.names I408 I1337 I1355 +11 1 +.names I409 I1334 I1356 +11 1 +.names I464 ZI1280_496 ZI1280_497 +11 1 +.names I473 I1340 I1363 +11 1 +.names I472 I1343 I1362 +11 1 +.names I550 I1586 I1602 +11 1 +.names ZI550_696 I1586 ZI550_697 +11 1 +.names ZI406_524 I1316 ZI406_525 +11 1 +.names ZI470_530 I1326 ZI470_531 +11 1 +.names I550 ZI1586_696 ZI1586_697 +11 1 +.names I1254 I1294 I1310 +11 1 +.names I405 I1294 I1311 +11 1 +.names ZI1254_506 I1294 ZI1254_507 +11 1 +.names I406 ZI1316_524 ZI1316_525 +11 1 +.names I1260 I1298 I1320 +11 1 +.names ZI1260_512 I1298 ZI1260_513 +11 1 +.names I469 I1298 I1321 +11 1 +.names I470 ZI1326_530 ZI1326_531 +11 1 +.names ZI552_706 I1608 ZI552_707 +11 1 +.names I552 I1608 I1616 +11 1 +.names I1254 ZI1294_506 ZI1294_507 +11 1 +.names I1260 ZI1298_512 ZI1298_513 +11 1 +.names I552 ZI1608_706 ZI1608_707 +11 1 +.names I407 I1335 I1352 +11 1 +.names I1335 I1338 I1351 +11 1 +.names I407 I1338 I1353 +11 1 +.names I471 I1341 I1359 +11 1 +.names I1341 I1344 I1358 +11 1 +.names I471 I1344 I1360 +11 1 +.names I554 I1622 I1636 +11 1 +.names ZI554_720 I1622 ZI554_721 +11 1 +.names ZI1335_536 I1338 ZI1335_537 +11 1 +.names ZI405_522 I1312 ZI405_523 +11 1 +.names I1335 ZI1338_536 ZI1338_537 +11 1 +.names ZI469_528 I1322 ZI469_529 +11 1 +.names ZI1341_538 I1344 ZI1341_539 +11 1 +.names I1341 ZI1344_538 ZI1344_539 +11 1 +.names I554 ZI1622_720 ZI1622_721 +11 1 +.names I405 ZI1312_522 ZI1312_523 +11 1 +.names ZI1337_552 I1371 ZI1337_553 +11 1 +.names I408 I1371 I1381 +11 1 +.names I1337 I1371 I1380 +11 1 +.names I469 ZI1322_528 ZI1322_529 +11 1 +.names ZI1343_554 I1373 ZI1343_555 +11 1 +.names I1343 I1373 I1383 +11 1 +.names I472 I1373 I1384 +11 1 +.names ZI556_734 I1646 ZI556_735 +11 1 +.names I556 I1646 I1658 +11 1 +.names ZI407_544 I1354 ZI407_545 +11 1 +.names I1337 ZI1371_552 ZI1371_553 +11 1 +.names ZI471_546 I1361 ZI471_547 +11 1 +.names I1343 ZI1373_554 ZI1373_555 +11 1 +.names I556 ZI1646_734 ZI1646_735 +11 1 +.names I407 ZI1354_544 ZI1354_545 +11 1 +.names ZI1333_566 I1390 ZI1333_567 +11 1 +.names I410 I1390 I1402 +11 1 +.names I1333 I1390 I1401 +11 1 +.names I471 ZI1361_546 ZI1361_547 +11 1 +.names I1339 I1392 I1407 +11 1 +.names I474 I1392 I1408 +11 1 +.names ZI1339_570 I1392 ZI1339_571 +11 1 +.names ZI557_744 I1664 ZI557_745 +11 1 +.names ZI408_558 I1382 ZI408_559 +11 1 +.names I1333 ZI1390_566 ZI1390_567 +11 1 +.names ZI472_560 I1385 ZI472_561 +11 1 +.names I1339 ZI1392_570 ZI1392_571 +11 1 +.names I557 ZI1664_744 ZI1664_745 +11 1 +.names I408 ZI1382_558 ZI1382_559 +11 1 +.names I412 I1416 I1430 +11 1 +.names I472 ZI1385_560 ZI1385_561 +11 1 +.names I476 I1420 I1438 +11 1 +.names ZI410_576 I1403 ZI410_577 +11 1 +.names ZI474_580 I1409 ZI474_581 +11 1 +.names ZI1334_564 I1391 ZI1334_565 +11 1 +.names I409 I1391 I1399 +11 1 +.names I1334 I1391 I1398 +11 1 +.names I410 ZI1403_576 ZI1403_577 +11 1 +.names I1340 I1393 I1404 +11 1 +.names I473 I1393 I1405 +11 1 +.names ZI1340_568 I1393 ZI1340_569 +11 1 +.names I474 ZI1409_580 ZI1409_581 +11 1 +.names I1334 ZI1391_564 ZI1391_565 +11 1 +.names I1340 ZI1393_568 ZI1393_569 +11 1 +.names I411 I1414 I1427 +11 1 +.names I411 I1417 I1428 +11 1 +.names I1414 I1417 I1426 +11 1 +.names I475 I1418 I1435 +11 1 +.names I1418 I1421 I1434 +11 1 +.names I475 I1421 I1436 +11 1 +.names ZI1414_584 I1417 ZI1414_585 +11 1 +.names ZI409_574 I1400 ZI409_575 +11 1 +.names I1414 ZI1417_584 ZI1417_585 +11 1 +.names ZI1418_588 I1421 ZI1418_589 +11 1 +.names ZI473_578 I1406 ZI473_579 +11 1 +.names I1418 ZI1421_588 ZI1421_589 +11 1 +.names I409 ZI1400_574 ZI1400_575 +11 1 +.names I412 I1446 I1458 +11 1 +.names ZI1416_604 I1446 ZI1416_605 +11 1 +.names I1416 I1446 I1457 +11 1 +.names I473 ZI1406_578 ZI1406_579 +11 1 +.names I1420 I1450 I1464 +11 1 +.names I476 I1450 I1465 +11 1 +.names ZI1420_608 I1450 ZI1420_609 +11 1 +.names I1416 ZI1446_604 ZI1446_605 +11 1 +.names ZI411_594 I1429 ZI411_595 +11 1 +.names ZI475_598 I1437 ZI475_599 +11 1 +.names I1420 ZI1450_608 ZI1450_609 +11 1 +.names I413 I1415 I1432 +11 1 +.names I1109 I1415 I1431 +11 1 +.names ZI1109_586 I1415 ZI1109_587 +11 1 +.names I1206 I1474 I1491 +11 1 +.names I418 I1474 I1492 +11 1 +.names ZI1206_626 I1474 ZI1206_627 +11 1 +.names I411 ZI1429_594 ZI1429_595 +11 1 +.names I1117 I1419 I1439 +11 1 +.names ZI1117_590 I1419 ZI1117_591 +11 1 +.names I477 I1419 I1440 +11 1 +.names I475 ZI1437_598 ZI1437_599 +11 1 +.names I482 I1478 I1502 +11 1 +.names I1212 I1478 I1501 +11 1 +.names ZI1212_632 I1478 ZI1212_633 +11 1 +.names I1109 ZI1415_586 ZI1415_587 +11 1 +.names I1206 ZI1474_626 ZI1474_627 +11 1 +.names ZI412_614 I1459 ZI412_615 +11 1 +.names I1117 ZI1419_590 ZI1419_591 +11 1 +.names ZI476_618 I1466 ZI476_619 +11 1 +.names I1212 ZI1478_632 ZI1478_633 +11 1 +.names I415 I1448 I1463 +11 1 +.names I420 I1511 I1528 +11 1 +.names I412 ZI1459_614 ZI1459_615 +11 1 +.names I1162 I1447 I1460 +11 1 +.names ZI1162_606 I1447 ZI1162_607 +11 1 +.names I414 I1447 I1461 +11 1 +.names I479 I1452 I1470 +11 1 +.names I1168 I1451 I1467 +11 1 +.names ZI1168_610 I1451 ZI1168_611 +11 1 +.names I478 I1451 I1468 +11 1 +.names I476 ZI1466_618 ZI1466_619 +11 1 +.names I484 I1517 I1537 +11 1 +.names ZI413_596 I1433 ZI413_597 +11 1 +.names ZI418_640 I1493 ZI418_641 +11 1 +.names I1162 ZI1447_606 ZI1447_607 +11 1 +.names ZI477_600 I1441 ZI477_601 +11 1 +.names I1168 ZI1451_610 ZI1451_611 +11 1 +.names ZI482_646 I1503 ZI482_647 +11 1 +.names I413 ZI1433_596 ZI1433_597 +11 1 +.names I418 ZI1493_640 ZI1493_641 +11 1 +.names I417 I1475 I1489 +11 1 +.names I1207 I1475 I1488 +11 1 +.names ZI1207_624 I1475 ZI1207_625 +11 1 +.names I416 I1476 I1487 +11 1 +.names I477 ZI1441_600 ZI1441_601 +11 1 +.names I480 I1480 I1497 +11 1 +.names I1213 I1479 I1498 +11 1 +.names ZI1213_630 I1479 ZI1213_631 +11 1 +.names I481 I1479 I1499 +11 1 +.names I482 ZI1503_646 ZI1503_647 +11 1 +.names I1207 ZI1475_624 ZI1475_625 +11 1 +.names ZI414_616 I1462 ZI414_617 +11 1 +.names ZI478_620 I1469 ZI478_621 +11 1 +.names I1213 ZI1479_630 ZI1479_631 +11 1 +.names I419 I1512 I1526 +11 1 +.names I1512 I1509 I1524 +11 1 +.names I419 I1509 I1525 +11 1 +.names I414 ZI1462_616 ZI1462_617 +11 1 +.names I478 ZI1469_620 ZI1469_621 +11 1 +.names I483 I1515 I1534 +11 1 +.names I483 I1518 I1535 +11 1 +.names I1515 I1518 I1533 +11 1 +.names ZI1512_650 I1509 ZI1512_651 +11 1 +.names I1512 ZI1509_650 ZI1509_651 +11 1 +.names ZI417_638 I1490 ZI417_639 +11 1 +.names ZI481_644 I1500 ZI481_645 +11 1 +.names ZI1515_654 I1518 ZI1515_655 +11 1 +.names I1515 ZI1518_654 ZI1518_655 +11 1 +.names I420 I1543 I1552 +11 1 +.names ZI1511_666 I1543 ZI1511_667 +11 1 +.names I1511 I1543 I1551 +11 1 +.names I417 ZI1490_638 ZI1490_639 +11 1 +.names ZI1448_622 I1477 ZI1448_623 +11 1 +.names I1448 I1477 I1484 +11 1 +.names I415 I1477 I1485 +11 1 +.names ZI1452_628 I1481 ZI1452_629 +11 1 +.names I1452 I1481 I1494 +11 1 +.names I479 I1481 I1495 +11 1 +.names I481 ZI1500_644 ZI1500_645 +11 1 +.names I484 I1547 I1562 +11 1 +.names I1517 I1547 I1561 +11 1 +.names ZI1517_672 I1547 ZI1517_673 +11 1 +.names ZI419_660 I1527 ZI419_661 +11 1 +.names I1511 ZI1543_666 ZI1543_667 +11 1 +.names I1448 ZI1477_622 ZI1477_623 +11 1 +.names I1452 ZI1481_628 ZI1481_629 +11 1 +.names I1517 ZI1547_672 ZI1547_673 +11 1 +.names ZI483_664 I1536 ZI483_665 +11 1 +.names I419 ZI1527_660 ZI1527_661 +11 1 +.names I426 I1573 I1593 +11 1 +.names I421 I1510 I1529 +11 1 +.names ZI1476_648 I1507 ZI1476_649 +11 1 +.names I416 I1507 I1522 +11 1 +.names I1476 I1507 I1521 +11 1 +.names ZI1480_652 I1513 ZI1480_653 +11 1 +.names I480 I1513 I1531 +11 1 +.names I1480 I1513 I1530 +11 1 +.names I485 I1516 I1538 +11 1 +.names I490 I1579 I1600 +11 1 +.names I483 ZI1536_664 ZI1536_665 +11 1 +.names ZI420_680 I1553 ZI420_681 +11 1 +.names I1476 ZI1507_648 ZI1507_649 +11 1 +.names ZI415_636 I1486 ZI415_637 +11 1 +.names ZI479_642 I1496 ZI479_643 +11 1 +.names I1480 ZI1513_652 ZI1513_653 +11 1 +.names ZI484_686 I1563 ZI484_687 +11 1 +.names I422 I1544 I1558 +11 1 +.names I420 ZI1553_680 ZI1553_681 +11 1 +.names I1544 I1541 I1557 +11 1 +.names I422 I1541 I1559 +11 1 +.names I415 ZI1486_636 ZI1486_637 +11 1 +.names I479 ZI1496_642 ZI1496_643 +11 1 +.names I486 I1545 I1569 +11 1 +.names I484 ZI1563_686 ZI1563_687 +11 1 +.names I486 I1548 I1568 +11 1 +.names I1545 I1548 I1567 +11 1 +.names ZI1544_670 I1541 ZI1544_671 +11 1 +.names ZI416_658 I1523 ZI416_659 +11 1 +.names I1544 ZI1541_670 ZI1541_671 +11 1 +.names ZI480_662 I1532 ZI480_663 +11 1 +.names ZI1545_676 I1548 ZI1545_677 +11 1 +.names I1545 ZI1548_676 ZI1548_677 +11 1 +.names I425 I1574 I1592 +11 1 +.names I416 ZI1523_658 ZI1523_659 +11 1 +.names I424 I1577 I1591 +11 1 +.names I480 ZI1532_662 ZI1532_663 +11 1 +.names I489 I1580 I1599 +11 1 +.names I488 I1583 I1598 +11 1 +.names ZI422_684 I1560 ZI422_685 +11 1 +.names ZI486_690 I1570 ZI486_691 +11 1 +.names ZI1510_668 I1542 ZI1510_669 +11 1 +.names I1510 I1542 I1554 +11 1 +.names I421 I1542 I1555 +11 1 +.names I422 ZI1560_684 ZI1560_685 +11 1 +.names I1516 I1546 I1564 +11 1 +.names I485 I1546 I1565 +11 1 +.names ZI1516_674 I1546 ZI1516_675 +11 1 +.names I486 ZI1570_690 ZI1570_691 +11 1 +.names I1510 ZI1542_668 ZI1542_669 +11 1 +.names I1516 ZI1546_674 ZI1546_675 +11 1 +.names I423 I1575 I1588 +11 1 +.names I423 I1578 I1589 +11 1 +.names I1575 I1578 I1587 +11 1 +.names I487 I1581 I1595 +11 1 +.names I487 I1584 I1596 +11 1 +.names I1581 I1584 I1594 +11 1 +.names ZI421_682 I1556 ZI421_683 +11 1 +.names ZI1575_692 I1578 ZI1575_693 +11 1 +.names I1575 ZI1578_692 ZI1578_693 +11 1 +.names ZI485_688 I1566 ZI485_689 +11 1 +.names ZI1581_694 I1584 ZI1581_695 +11 1 +.names I1581 ZI1584_694 ZI1584_695 +11 1 +.names I421 ZI1556_682 ZI1556_683 +11 1 +.names ZI1577_702 I1603 ZI1577_703 +11 1 +.names I1577 I1603 I1609 +11 1 +.names I424 I1603 I1610 +11 1 +.names I485 ZI1566_688 ZI1566_689 +11 1 +.names I1583 I1605 I1612 +11 1 +.names ZI1583_704 I1605 ZI1583_705 +11 1 +.names I488 I1605 I1613 +11 1 +.names ZI423_698 I1590 ZI423_699 +11 1 +.names I1577 ZI1603_702 ZI1603_703 +11 1 +.names ZI487_700 I1597 ZI487_701 +11 1 +.names I1583 ZI1605_704 ZI1605_705 +11 1 +.names I423 ZI1590_698 ZI1590_699 +11 1 +.names ZI1573_714 I1617 ZI1573_715 +11 1 +.names I1573 I1617 I1626 +11 1 +.names I426 I1617 I1627 +11 1 +.names I487 ZI1597_700 ZI1597_701 +11 1 +.names I490 I1619 I1633 +11 1 +.names ZI1579_718 I1619 ZI1579_719 +11 1 +.names I1579 I1619 I1632 +11 1 +.names I1573 ZI1617_714 ZI1617_715 +11 1 +.names ZI424_708 I1611 ZI424_709 +11 1 +.names ZI488_710 I1614 ZI488_711 +11 1 +.names I1579 ZI1619_718 ZI1619_719 +11 1 +.names I428 I1639 I1651 +11 1 +.names I424 ZI1611_708 ZI1611_709 +11 1 +.names I488 ZI1614_710 ZI1614_711 +11 1 +.names I492 I1643 I1656 +11 1 +.names ZI426_724 I1628 ZI426_725 +11 1 +.names ZI490_728 I1634 ZI490_729 +11 1 +.names I426 ZI1628_724 ZI1628_725 +11 1 +.names ZI1574_712 I1618 ZI1574_713 +11 1 +.names I425 I1618 I1624 +11 1 +.names I1574 I1618 I1623 +11 1 +.names ZI1580_716 I1620 ZI1580_717 +11 1 +.names I1580 I1620 I1629 +11 1 +.names I489 I1620 I1630 +11 1 +.names I490 ZI1634_728 ZI1634_729 +11 1 +.names I1574 ZI1618_712 ZI1618_713 +11 1 +.names I1580 ZI1620_716 ZI1620_717 +11 1 +.names I427 I1640 I1649 +11 1 +.names I1640 I1637 I1647 +11 1 +.names I427 I1637 I1648 +11 1 +.names I491 I1641 I1653 +11 1 +.names I491 I1644 I1654 +11 1 +.names I1641 I1644 I1652 +11 1 +.names ZI1640_730 I1637 ZI1640_731 +11 1 +.names ZI425_722 I1625 ZI425_723 +11 1 +.names I1640 ZI1637_730 ZI1637_731 +11 1 +.names ZI489_726 I1631 ZI489_727 +11 1 +.names ZI1641_732 I1644 ZI1641_733 +11 1 +.names I1641 ZI1644_732 ZI1644_733 +11 1 +.names I425 ZI1625_722 ZI1625_723 +11 1 +.names ZI1639_740 I1659 ZI1639_741 +11 1 +.names I428 I1659 I1666 +11 1 +.names I489 ZI1631_726 ZI1631_727 +11 1 +.names I492 I1661 I1669 +11 1 +.names ZI1643_742 I1661 ZI1643_743 +11 1 +.names ZI427_736 I1650 ZI427_737 +11 1 +.names I1639 ZI1659_740 ZI1659_741 +11 1 +.names ZI491_738 I1655 ZI491_739 +11 1 +.names I1643 ZI1661_742 ZI1661_743 +11 1 +.names I427 ZI1650_736 ZI1650_737 +11 1 +.names I491 ZI1655_738 ZI1655_739 +11 1 +.names ZI428_746 I1667 ZI428_747 +11 1 +.names ZI492_748 I1670 ZI492_749 +11 1 +.names I428 ZI1667_746 ZI1667_747 +11 1 +.names I492 ZI1670_748 ZI1670_749 +11 1 +.names ZI194_261 ZI908_261 I914 +00 0 +.names ZI911_259 ZI912_259 I913 +00 0 +.names ZI185_293 ZI963_293 I967 +00 0 +.names ZI299_291 ZI965_291 I966 +00 0 +.names ZI151_295 ZI964_295 I968 +00 0 +.end diff --git a/abc70930/readme b/abc70930/readme new file mode 100644 index 00000000..19a7f9d8 --- /dev/null +++ b/abc70930/readme @@ -0,0 +1,26 @@ +Often the code comes directly from a Windows computer. +The following steps may be needed to compile it on UNIX: + +>> dos2unix Makefile Makefile +>> dos2unix depends.sh depends.sh +>> chmod 755 depends.sh +>> make // on Solaris, try "gmake" + +If compiling as a static library, it is necessary to uncomment +#define _LIB in "src/abc/main/main.c" + +Several things to try if it does not compile on your platform: +- Try running all code (not only Makefile and depends.sh) through dos2unix +- Try the following actions: + (a) Remove flags from the libs line (LIBS :=) in Makefile + (b) Remove "src\base\main\libSupport.c" from "src\base\main\module.make" + (c) Comment calls to Libs_Init() and Libs_End() in "src\base\main\mainInit.c" +- Try linking with gcc (rather than g++) + For this replace "LD := g++" with "LD := gcc -lm" in Makefile +- If your Linux distribution does not have "readline", you may have problems + compiling ABC with gcc. Please try installing this library from + http://tiswww.case.edu/php/chet/readline/rltop.html + + +Finally, run regression test: +abc>>> so regtest.script diff --git a/abc70930/regtest.script b/abc70930/regtest.script new file mode 100644 index 00000000..c4a23a89 --- /dev/null +++ b/abc70930/regtest.script @@ -0,0 +1,18 @@ +r examples/apex4.pla; resyn; if; cec; ps; clp; resyn; map; cec; ps +r examples/C2670.blif; st; w 1.aig; cec 1.aig +r examples/C2670.blif; st; short_names; w 1.bench; cec 1.bench +r examples/C2670.blif; st; short_names; ren -s; w 1.eqn; cec 1.eqn +r examples/C2670.blif; resyn2; if -K 8; cec; ps; u; map; cec; ps +r examples/frg2.blif; dsd; muxes; cec; ps; clp; share; resyn; map; cec; ps +r examples/frg2.blif; bdd; muxes; cec; ps; clp; st; ren -b; muxes; cec; ps +r examples/i10.blif; resyn2; fpga; cec; ps; u; map; cec; ps +r examples/i10.blif; choice; fpga; cec; ps; u; map; cec; ps +r examples/pj1.blif; st; if; cec; ps; u; map; cec; ps +r examples/s38417.blif; comb; w 1.blif; resyn; if; cec 1.blif; ps +r examples/s38417.blif; resyn; if; cec; ps; u; map; cec; ps +r examples/s38584.bench; resyn; ren -s; fx; if; cec; ps; u; map; cec; ps +r examples/s444.blif; b; esd -v; print_exdc; dsd; cec; ps +r examples/s444.blif; double; frames -F 5; w 1.blif; ffpga -K 8; cec 1.blif +r examples/s5378.blif; frames -F 5; cycle; w 1.blif; ps; ret; ps; sec 1.blif +r examples/s6669.blif; cycle; w 1.blif; ps; ret -M 3; resyn; ps; sec 1.blif +time diff --git a/abc70930/regtest_output.txt b/abc70930/regtest_output.txt new file mode 100644 index 00000000..6e0ffec3 --- /dev/null +++ b/abc70930/regtest_output.txt @@ -0,0 +1,96 @@ +UC Berkeley, ABC 1.01 (compiled Dec 25 2006 17:15:00) +abc 01> so regtest.script +abc - > r examples/apex4.pla; resyn; if; cec; ps; clp; resyn; map; cec; ps +Networks are equivalent. +examples/apex4: i/o = 9/ 19 lat = 0 nd = 1172 aig = 4365 lev = 7 +The shared BDD size is 917 nodes. BDD construction time = 0.04 sec +A simple supergate library is derived from gate library "mcnc_temp.genlib". +Loaded 20 unique 5-input supergates from "mcnc_temp.super". Time = 0.02 sec +Networks are equivalent. +examples/apex4: i/o = 9/ 19 lat = 0 nd = 1734 aig = 2576 lev = 12 +abc - > r examples/C2670.blif; st; w 1.aig; cec 1.aig +Networks are equivalent after structural hashing. +abc - > r examples/C2670.blif; st; short_names; w 1.bench; cec 1.bench +Networks are equivalent after structural hashing. +abc - > r examples/C2670.blif; st; short_names; ren -s; w 1.eqn; cec 1.eqn +Networks are equivalent. +abc - > r examples/C2670.blif; resyn2; if -K 8; cec; ps; u; map; cec; ps +Networks are equivalent. +C2670.iscas : i/o = 233/ 140 lat = 0 nd = 120 aig = 1056 lev = 4 +Networks are equivalent. +C2670.iscas : i/o = 233/ 140 lat = 0 nd = 467 aig = 651 lev = 14 +abc - > r examples/frg2.blif; dsd; muxes; cec; ps; clp; share; resyn; map; cec; ps +Networks are equivalent. +frg2 : i/o = 143/ 139 lat = 0 nd = 1648 aig = 2268 lev = 18 +The shared BDD size is 1672 nodes. BDD construction time = 0.14 sec +Networks are equivalent. +frg2 : i/o = 143/ 139 lat = 0 nd = 533 aig = 778 lev = 8 +abc - > r examples/frg2.blif; bdd; muxes; cec; ps; clp; st; ren -b; muxes; cec; ps +Networks are equivalent. +frg2 : i/o = 143/ 139 lat = 0 nd = 2868 aig = 4221 lev = 38 +The shared BDD size is 1684 nodes. BDD construction time = 0.14 sec +Networks are equivalent. +frg2 : i/o = 143/ 139 lat = 0 nd = 2331 aig = 3180 lev = 20 +abc - > r examples/i10.blif; resyn2; fpga; cec; ps; u; map; cec; ps +Networks are equivalent. +i10 : i/o = 257/ 224 lat = 0 nd = 808 aig = 2630 lev = 12 +Networks are equivalent. +i10 : i/o = 257/ 224 lat = 0 nd = 1555 aig = 1980 lev = 24 +abc - > r examples/i10.blif; choice; fpga; cec; ps; u; map; cec; ps +Currently stored 3 networks with 5801 nodes will be fraiged. +Total fraiging time = 0.39 sec +Performing FPGA mapping with choices. +Networks are equivalent. +i10 : i/o = 257/ 224 lat = 0 nd = 798 aig = 2543 lev = 12 +Performing mapping with choices. +Networks are equivalent. +i10 : i/o = 257/ 224 lat = 0 nd = 1463 aig = 1993 lev = 23 +abc - > r examples/pj1.blif; st; if; cec; ps; u; map; cec; ps +Networks are equivalent after structural hashing. +exCombCkt : i/o = 1769/1063 lat = 0 nd = 5984 aig = 23156 lev = 52 +Networks are equivalent. +exCombCkt : i/o = 1769/1063 lat = 0 nd = 11474 aig = 16032 lev = 80 +abc - > r examples/s38417.blif; comb; w 1.blif; resyn; if; cec 1.blif; ps +examples/s38417.blif (line 14): Skipping directive ".wire_load_slope". +Networks are equivalent. +s38417 : i/o = 1664/1742 lat = 0 nd = 3479 aig = 10120 lev = 9 +abc - > r examples/s38417.blif; resyn; if; cec; ps; u; map; cec; ps +examples/s38417.blif (line 14): Skipping directive ".wire_load_slope". +examples/s38417.blif (line 14): Skipping directive ".wire_load_slope". +Networks are equivalent. +s38417 : i/o = 28/ 106 lat = 1636 nd = 3479 aig = 10120 lev = 9 +examples/s38417.blif (line 14): Skipping directive ".wire_load_slope". +Networks are equivalent. +s38417 : i/o = 28/ 106 lat = 1636 nd = 7189 aig = 8689 lev = 17 +abc - > r examples/s38584.bench; resyn; ren -s; fx; if; cec; ps; u; map; cec; ps +The network was strashed and balanced before FPGA mapping. +Networks are equivalent. +examples/s38584: i/o = 12/ 278 lat = 1452 nd = 4266 aig = 12569 lev = 10 +The network was strashed and balanced before mapping. +Networks are equivalent. +examples/s38584: i/o = 12/ 278 lat = 1452 nd = 8135 aig = 10674 lev = 18 +abc - > r examples/s444.blif; b; esd -v; print_exdc; dsd; cec; ps +The shared BDD size is 181 nodes. +BDD nodes in the transition relation before reordering 557. +BDD nodes in the transition relation after reordering 456. +Reachability analysis completed in 151 iterations. +The number of minterms in the reachable state set = 8865. +BDD nodes in the unreachable states before reordering 124. +BDD nodes in the unreachable states after reordering 113. +EXDC network statistics: +exdc : i/o = 21/ 21 lat = 0 nd = 21 cube = 86 lev = 2 +Networks are equivalent. +s444 : i/o = 3/ 6 lat = 21 nd = 82 aig = 176 lev = 7 +abc - > r examples/s444.blif; double; frames -F 5; w 1.blif; ffpga -K 8; cec 1.blif +Networks are equivalent after structural hashing. +abc - > r examples/s5378.blif; frames -F 5; cycle; w 1.blif; ps; ret; ps; sec 1.blif +s5378_5_frames: i/o = 175/ 245 lat = 164 and = 6629 (exor = 115) lev = 59 +s5378_5_frames: i/o = 175/ 245 lat = 182 nd = 6957 cube = 6956 lev = 50 +Networks are equivalent after framing. +abc - > r examples/s6669.blif; cycle; w 1.blif; ps; ret -M 3; resyn; ps; sec 1.blif +s6669 : i/o = 83/ 55 lat = 239 nd = 3080 cube = 3080 lev = 93 +s6669 : i/o = 83/ 55 lat = 183 and = 1915 (exor = 371) lev = 97 +Networks are equivalent after fraiging. +abc - > time +elapse: 44.07 seconds, total: 44.07 seconds +abc 150> \ No newline at end of file diff --git a/abc70930/src/.DS_Store b/abc70930/src/.DS_Store new file mode 100644 index 00000000..75c7d84f Binary files /dev/null and b/abc70930/src/.DS_Store differ diff --git a/abc70930/src/abc.1 b/abc70930/src/abc.1 new file mode 100644 index 00000000..b34c44ad --- /dev/null +++ b/abc70930/src/abc.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 7/21/08 \" DATE +.Dt abc 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm abc, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/abc70930/src/abc.xcodeproj/project.pbxproj b/abc70930/src/abc.xcodeproj/project.pbxproj new file mode 100644 index 00000000..9f987fef --- /dev/null +++ b/abc70930/src/abc.xcodeproj/project.pbxproj @@ -0,0 +1,3251 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 2717FCAD0E3852830038296D /* unate.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E330E349282006E7CF6 /* unate.c */; }; + 274040F00E38BEDA00DC6F18 /* libreadline.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 274040EF0E38BED900DC6F18 /* libreadline.dylib */; }; + 27A92E7C0E349283006E7CF6 /* cutApi.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B700E349280006E7CF6 /* cutApi.c */; }; + 27A92E7D0E349283006E7CF6 /* cutCut.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B710E349280006E7CF6 /* cutCut.c */; }; + 27A92E7E0E349283006E7CF6 /* cutExpand.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B720E349280006E7CF6 /* cutExpand.c */; }; + 27A92E7F0E349283006E7CF6 /* cutMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B750E349280006E7CF6 /* cutMan.c */; }; + 27A92E800E349283006E7CF6 /* cutMerge.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B760E349280006E7CF6 /* cutMerge.c */; }; + 27A92E810E349283006E7CF6 /* cutNode.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B770E349280006E7CF6 /* cutNode.c */; }; + 27A92E820E349283006E7CF6 /* cutOracle.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B780E349280006E7CF6 /* cutOracle.c */; }; + 27A92E830E349283006E7CF6 /* cutPre22.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B790E349280006E7CF6 /* cutPre22.c */; }; + 27A92E840E349283006E7CF6 /* cutSeq.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B7A0E349280006E7CF6 /* cutSeq.c */; }; + 27A92E850E349283006E7CF6 /* cutTruth.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B7B0E349280006E7CF6 /* cutTruth.c */; }; + 27A92E860E349283006E7CF6 /* decAbc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B7F0E349280006E7CF6 /* decAbc.c */; }; + 27A92E870E349283006E7CF6 /* decFactor.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B800E349280006E7CF6 /* decFactor.c */; }; + 27A92E880E349283006E7CF6 /* decMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B810E349280006E7CF6 /* decMan.c */; }; + 27A92E890E349283006E7CF6 /* decPrint.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B820E349280006E7CF6 /* decPrint.c */; }; + 27A92E8A0E349283006E7CF6 /* decUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B830E349280006E7CF6 /* decUtil.c */; }; + 27A92E8B0E349283006E7CF6 /* fxu.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B860E349280006E7CF6 /* fxu.c */; }; + 27A92E8C0E349283006E7CF6 /* fxuCreate.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B880E349280006E7CF6 /* fxuCreate.c */; }; + 27A92E8D0E349283006E7CF6 /* fxuHeapD.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B890E349280006E7CF6 /* fxuHeapD.c */; }; + 27A92E8E0E349283006E7CF6 /* fxuHeapS.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B8A0E349280006E7CF6 /* fxuHeapS.c */; }; + 27A92E8F0E349283006E7CF6 /* fxuList.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B8C0E349280006E7CF6 /* fxuList.c */; }; + 27A92E900E349283006E7CF6 /* fxuMatrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B8D0E349280006E7CF6 /* fxuMatrix.c */; }; + 27A92E910E349283006E7CF6 /* fxuPair.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B8E0E349280006E7CF6 /* fxuPair.c */; }; + 27A92E920E349283006E7CF6 /* fxuPrint.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B8F0E349280006E7CF6 /* fxuPrint.c */; }; + 27A92E930E349283006E7CF6 /* fxuReduce.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B900E349280006E7CF6 /* fxuReduce.c */; }; + 27A92E940E349283006E7CF6 /* fxuSelect.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B910E349280006E7CF6 /* fxuSelect.c */; }; + 27A92E950E349283006E7CF6 /* fxuSingle.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B920E349280006E7CF6 /* fxuSingle.c */; }; + 27A92E960E349283006E7CF6 /* fxuUpdate.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B930E349280006E7CF6 /* fxuUpdate.c */; }; + 27A92E970E349283006E7CF6 /* lpk_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B970E349280006E7CF6 /* lpk_.c */; }; + 27A92E980E349283006E7CF6 /* lpkAbcDec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B980E349280006E7CF6 /* lpkAbcDec.c */; }; + 27A92E990E349283006E7CF6 /* lpkAbcDsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B990E349280006E7CF6 /* lpkAbcDsd.c */; }; + 27A92E9A0E349283006E7CF6 /* lpkAbcMux.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B9A0E349280006E7CF6 /* lpkAbcMux.c */; }; + 27A92E9B0E349283006E7CF6 /* lpkAbcUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B9B0E349280006E7CF6 /* lpkAbcUtil.c */; }; + 27A92E9C0E349283006E7CF6 /* lpkCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B9C0E349280006E7CF6 /* lpkCore.c */; }; + 27A92E9D0E349283006E7CF6 /* lpkCut.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B9D0E349280006E7CF6 /* lpkCut.c */; }; + 27A92E9E0E349283006E7CF6 /* lpkMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92B9F0E349280006E7CF6 /* lpkMan.c */; }; + 27A92E9F0E349283006E7CF6 /* lpkMap.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BA00E349280006E7CF6 /* lpkMap.c */; }; + 27A92EA00E349283006E7CF6 /* lpkMulti.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BA10E349280006E7CF6 /* lpkMulti.c */; }; + 27A92EA10E349283006E7CF6 /* lpkMux.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BA20E349280006E7CF6 /* lpkMux.c */; }; + 27A92EA20E349283006E7CF6 /* lpkSets.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BA30E349280006E7CF6 /* lpkSets.c */; }; + 27A92EA30E349283006E7CF6 /* res_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BA80E349280006E7CF6 /* res_.c */; }; + 27A92EA40E349283006E7CF6 /* resCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BA90E349280006E7CF6 /* resCore.c */; }; + 27A92EA50E349283006E7CF6 /* resDivs.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BAA0E349280006E7CF6 /* resDivs.c */; }; + 27A92EA60E349283006E7CF6 /* resFilter.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BAB0E349280006E7CF6 /* resFilter.c */; }; + 27A92EA70E349283006E7CF6 /* resSat.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BAD0E349280006E7CF6 /* resSat.c */; }; + 27A92EA80E349283006E7CF6 /* resSim.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BAE0E349280006E7CF6 /* resSim.c */; }; + 27A92EAA0E349283006E7CF6 /* resStrash.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BB00E349280006E7CF6 /* resStrash.c */; }; + 27A92EAB0E349283006E7CF6 /* resWin.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BB10E349280006E7CF6 /* resWin.c */; }; + 27A92EAC0E349283006E7CF6 /* ret_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BB40E349280006E7CF6 /* ret_.c */; }; + 27A92EAD0E349283006E7CF6 /* retArea.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BB50E349280006E7CF6 /* retArea.c */; }; + 27A92EAE0E349283006E7CF6 /* retCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BB60E349280006E7CF6 /* retCore.c */; }; + 27A92EAF0E349283006E7CF6 /* retDelay.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BB70E349280006E7CF6 /* retDelay.c */; }; + 27A92EB00E349283006E7CF6 /* retFlow.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BB80E349280006E7CF6 /* retFlow.c */; }; + 27A92EB10E349283006E7CF6 /* retIncrem.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BB90E349280006E7CF6 /* retIncrem.c */; }; + 27A92EB20E349283006E7CF6 /* retInit.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BBA0E349280006E7CF6 /* retInit.c */; }; + 27A92EB30E349283006E7CF6 /* retLvalue.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BBC0E349280006E7CF6 /* retLvalue.c */; }; + 27A92EB40E349283006E7CF6 /* rwrDec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BC00E349280006E7CF6 /* rwrDec.c */; }; + 27A92EB50E349283006E7CF6 /* rwrEva.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BC10E349280006E7CF6 /* rwrEva.c */; }; + 27A92EB60E349283006E7CF6 /* rwrExp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BC20E349280006E7CF6 /* rwrExp.c */; }; + 27A92EB70E349283006E7CF6 /* rwrLib.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BC30E349280006E7CF6 /* rwrLib.c */; }; + 27A92EB80E349283006E7CF6 /* rwrMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BC40E349280006E7CF6 /* rwrMan.c */; }; + 27A92EB90E349283006E7CF6 /* rwrPrint.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BC50E349280006E7CF6 /* rwrPrint.c */; }; + 27A92EBA0E349283006E7CF6 /* rwrTemp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BC60E349280006E7CF6 /* rwrTemp.c */; }; + 27A92EBB0E349283006E7CF6 /* rwrUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BC70E349280006E7CF6 /* rwrUtil.c */; }; + 27A92EBC0E349283006E7CF6 /* simMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BCB0E349280006E7CF6 /* simMan.c */; }; + 27A92EBD0E349283006E7CF6 /* simSat.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BCC0E349280006E7CF6 /* simSat.c */; }; + 27A92EBE0E349283006E7CF6 /* simSeq.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BCD0E349280006E7CF6 /* simSeq.c */; }; + 27A92EBF0E349283006E7CF6 /* simSupp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BCE0E349280006E7CF6 /* simSupp.c */; }; + 27A92EC00E349283006E7CF6 /* simSwitch.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BCF0E349280006E7CF6 /* simSwitch.c */; }; + 27A92EC10E349283006E7CF6 /* simSym.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BD00E349280006E7CF6 /* simSym.c */; }; + 27A92EC20E349283006E7CF6 /* simSymSat.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BD10E349280006E7CF6 /* simSymSat.c */; }; + 27A92EC30E349283006E7CF6 /* simSymSim.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BD20E349280006E7CF6 /* simSymSim.c */; }; + 27A92EC40E349283006E7CF6 /* simSymStr.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BD30E349280006E7CF6 /* simSymStr.c */; }; + 27A92EC50E349283006E7CF6 /* simUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BD40E349280006E7CF6 /* simUtils.c */; }; + 27A92EC60E349283006E7CF6 /* satInter.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BD90E349280006E7CF6 /* satInter.c */; }; + 27A92EC70E349283006E7CF6 /* satMem.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BDA0E349280006E7CF6 /* satMem.c */; }; + 27A92EC80E349283006E7CF6 /* satSolver.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BDC0E349280006E7CF6 /* satSolver.c */; }; + 27A92EC90E349283006E7CF6 /* satStore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BDE0E349280006E7CF6 /* satStore.c */; }; + 27A92ECA0E349283006E7CF6 /* satTrace.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BE00E349280006E7CF6 /* satTrace.c */; }; + 27A92ECB0E349283006E7CF6 /* satUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BE10E349280006E7CF6 /* satUtil.c */; }; + 27A92ECC0E349283006E7CF6 /* csat_apis.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BE40E349280006E7CF6 /* csat_apis.c */; }; + 27A92ECD0E349283006E7CF6 /* fraigApi.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BE90E349280006E7CF6 /* fraigApi.c */; }; + 27A92ECE0E349283006E7CF6 /* fraigCanon.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BEA0E349280006E7CF6 /* fraigCanon.c */; }; + 27A92ECF0E349283006E7CF6 /* fraigChoice.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BEB0E349280006E7CF6 /* fraigChoice.c */; }; + 27A92ED00E349283006E7CF6 /* fraigFanout.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BEC0E349280006E7CF6 /* fraigFanout.c */; }; + 27A92ED10E349283006E7CF6 /* fraigFeed.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BED0E349280006E7CF6 /* fraigFeed.c */; }; + 27A92ED20E349283006E7CF6 /* fraigMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BEF0E349280006E7CF6 /* fraigMan.c */; }; + 27A92ED30E349283006E7CF6 /* fraigMem.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BF00E349280006E7CF6 /* fraigMem.c */; }; + 27A92ED40E349283006E7CF6 /* fraigNode.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BF10E349280006E7CF6 /* fraigNode.c */; }; + 27A92ED50E349283006E7CF6 /* fraigPrime.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BF20E349280006E7CF6 /* fraigPrime.c */; }; + 27A92ED60E349283006E7CF6 /* fraigSat.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BF30E349280006E7CF6 /* fraigSat.c */; }; + 27A92ED70E349283006E7CF6 /* fraigTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BF40E349280006E7CF6 /* fraigTable.c */; }; + 27A92ED80E349283006E7CF6 /* fraigUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BF50E349280006E7CF6 /* fraigUtil.c */; }; + 27A92ED90E349283006E7CF6 /* fraigVec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BF60E349280006E7CF6 /* fraigVec.c */; }; + 27A92EDA0E349283006E7CF6 /* msatActivity.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BFB0E349280006E7CF6 /* msatActivity.c */; }; + 27A92EDB0E349283006E7CF6 /* msatClause.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BFC0E349280006E7CF6 /* msatClause.c */; }; + 27A92EDC0E349283006E7CF6 /* msatClauseVec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BFD0E349280006E7CF6 /* msatClauseVec.c */; }; + 27A92EDD0E349283006E7CF6 /* msatMem.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92BFF0E349280006E7CF6 /* msatMem.c */; }; + 27A92EDF0E349283006E7CF6 /* msatOrderJ.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C010E349280006E7CF6 /* msatOrderJ.c */; }; + 27A92EE00E349283006E7CF6 /* msatQueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C020E349280006E7CF6 /* msatQueue.c */; }; + 27A92EE10E349283006E7CF6 /* msatRead.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C030E349280006E7CF6 /* msatRead.c */; }; + 27A92EE20E349283006E7CF6 /* msatSolverApi.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C040E349280006E7CF6 /* msatSolverApi.c */; }; + 27A92EE30E349283006E7CF6 /* msatSolverCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C050E349280006E7CF6 /* msatSolverCore.c */; }; + 27A92EE40E349283006E7CF6 /* msatSolverIo.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C060E349280006E7CF6 /* msatSolverIo.c */; }; + 27A92EE50E349283006E7CF6 /* msatSolverSearch.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C070E349280006E7CF6 /* msatSolverSearch.c */; }; + 27A92EE60E349283006E7CF6 /* msatSort.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C080E349280006E7CF6 /* msatSort.c */; }; + 27A92EE70E349283006E7CF6 /* msatVec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C090E349280006E7CF6 /* msatVec.c */; }; + 27A92EE80E349283006E7CF6 /* pr.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C0B0E349280006E7CF6 /* pr.c */; }; + 27A92EE90E349283006E7CF6 /* casCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C110E349280006E7CF6 /* casCore.c */; }; + 27A92EEA0E349283006E7CF6 /* casDec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C120E349280006E7CF6 /* casDec.c */; }; + 27A92EEB0E349283006E7CF6 /* cuddAddAbs.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C180E349280006E7CF6 /* cuddAddAbs.c */; }; + 27A92EEC0E349283006E7CF6 /* cuddAddApply.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C190E349280006E7CF6 /* cuddAddApply.c */; }; + 27A92EED0E349283006E7CF6 /* cuddAddFind.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C1A0E349280006E7CF6 /* cuddAddFind.c */; }; + 27A92EEE0E349283006E7CF6 /* cuddAddInv.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C1B0E349280006E7CF6 /* cuddAddInv.c */; }; + 27A92EEF0E349283006E7CF6 /* cuddAddIte.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C1C0E349280006E7CF6 /* cuddAddIte.c */; }; + 27A92EF00E349283006E7CF6 /* cuddAddNeg.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C1D0E349280006E7CF6 /* cuddAddNeg.c */; }; + 27A92EF10E349283006E7CF6 /* cuddAddWalsh.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C1E0E349280006E7CF6 /* cuddAddWalsh.c */; }; + 27A92EF20E349283006E7CF6 /* cuddAndAbs.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C1F0E349280006E7CF6 /* cuddAndAbs.c */; }; + 27A92EF30E349283006E7CF6 /* cuddAnneal.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C200E349280006E7CF6 /* cuddAnneal.c */; }; + 27A92EF40E349283006E7CF6 /* cuddApa.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C210E349280006E7CF6 /* cuddApa.c */; }; + 27A92EF50E349283006E7CF6 /* cuddAPI.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C220E349280006E7CF6 /* cuddAPI.c */; }; + 27A92EF60E349283006E7CF6 /* cuddApprox.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C230E349280006E7CF6 /* cuddApprox.c */; }; + 27A92EF70E349283006E7CF6 /* cuddBddAbs.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C240E349280006E7CF6 /* cuddBddAbs.c */; }; + 27A92EF80E349283006E7CF6 /* cuddBddCorr.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C250E349280006E7CF6 /* cuddBddCorr.c */; }; + 27A92EF90E349283006E7CF6 /* cuddBddIte.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C260E349280006E7CF6 /* cuddBddIte.c */; }; + 27A92EFA0E349283006E7CF6 /* cuddBridge.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C270E349280006E7CF6 /* cuddBridge.c */; }; + 27A92EFB0E349283006E7CF6 /* cuddCache.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C280E349280006E7CF6 /* cuddCache.c */; }; + 27A92EFC0E349283006E7CF6 /* cuddCheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C290E349280006E7CF6 /* cuddCheck.c */; }; + 27A92EFD0E349283006E7CF6 /* cuddClip.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C2A0E349280006E7CF6 /* cuddClip.c */; }; + 27A92EFE0E349283006E7CF6 /* cuddCof.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C2B0E349280006E7CF6 /* cuddCof.c */; }; + 27A92EFF0E349283006E7CF6 /* cuddCompose.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C2C0E349280006E7CF6 /* cuddCompose.c */; }; + 27A92F000E349283006E7CF6 /* cuddDecomp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C2D0E349280006E7CF6 /* cuddDecomp.c */; }; + 27A92F010E349283006E7CF6 /* cuddEssent.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C2E0E349280006E7CF6 /* cuddEssent.c */; }; + 27A92F020E349283006E7CF6 /* cuddExact.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C2F0E349280006E7CF6 /* cuddExact.c */; }; + 27A92F030E349283006E7CF6 /* cuddExport.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C300E349280006E7CF6 /* cuddExport.c */; }; + 27A92F040E349283006E7CF6 /* cuddGenCof.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C310E349280006E7CF6 /* cuddGenCof.c */; }; + 27A92F050E349283006E7CF6 /* cuddGenetic.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C320E349280006E7CF6 /* cuddGenetic.c */; }; + 27A92F060E349283006E7CF6 /* cuddGroup.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C330E349280006E7CF6 /* cuddGroup.c */; }; + 27A92F070E349283006E7CF6 /* cuddHarwell.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C340E349280006E7CF6 /* cuddHarwell.c */; }; + 27A92F080E349283006E7CF6 /* cuddInit.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C350E349280006E7CF6 /* cuddInit.c */; }; + 27A92F090E349283006E7CF6 /* cuddInteract.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C370E349280006E7CF6 /* cuddInteract.c */; }; + 27A92F0A0E349283006E7CF6 /* cuddLCache.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C380E349280006E7CF6 /* cuddLCache.c */; }; + 27A92F0B0E349283006E7CF6 /* cuddLevelQ.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C390E349280006E7CF6 /* cuddLevelQ.c */; }; + 27A92F0C0E349283006E7CF6 /* cuddLinear.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C3A0E349280006E7CF6 /* cuddLinear.c */; }; + 27A92F0D0E349283006E7CF6 /* cuddLiteral.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C3B0E349280006E7CF6 /* cuddLiteral.c */; }; + 27A92F0E0E349283006E7CF6 /* cuddMatMult.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C3C0E349280006E7CF6 /* cuddMatMult.c */; }; + 27A92F0F0E349283006E7CF6 /* cuddPriority.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C3D0E349280006E7CF6 /* cuddPriority.c */; }; + 27A92F100E349283006E7CF6 /* cuddRead.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C3E0E349280006E7CF6 /* cuddRead.c */; }; + 27A92F110E349283006E7CF6 /* cuddRef.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C3F0E349280006E7CF6 /* cuddRef.c */; }; + 27A92F120E349283006E7CF6 /* cuddReorder.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C400E349280006E7CF6 /* cuddReorder.c */; }; + 27A92F130E349283006E7CF6 /* cuddSat.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C410E349280006E7CF6 /* cuddSat.c */; }; + 27A92F140E349283006E7CF6 /* cuddSign.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C420E349280006E7CF6 /* cuddSign.c */; }; + 27A92F150E349283006E7CF6 /* cuddSolve.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C430E349280006E7CF6 /* cuddSolve.c */; }; + 27A92F160E349283006E7CF6 /* cuddSplit.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C440E349280006E7CF6 /* cuddSplit.c */; }; + 27A92F170E349283006E7CF6 /* cuddSubsetHB.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C450E349280006E7CF6 /* cuddSubsetHB.c */; }; + 27A92F180E349283006E7CF6 /* cuddSubsetSP.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C460E349280006E7CF6 /* cuddSubsetSP.c */; }; + 27A92F190E349283006E7CF6 /* cuddSymmetry.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C470E349280006E7CF6 /* cuddSymmetry.c */; }; + 27A92F1A0E349283006E7CF6 /* cuddTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C480E349280006E7CF6 /* cuddTable.c */; }; + 27A92F1B0E349283006E7CF6 /* cuddUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C490E349280006E7CF6 /* cuddUtil.c */; }; + 27A92F1C0E349283006E7CF6 /* cuddWindow.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C4A0E349280006E7CF6 /* cuddWindow.c */; }; + 27A92F1D0E349283006E7CF6 /* cuddZddCount.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C4B0E349280006E7CF6 /* cuddZddCount.c */; }; + 27A92F1E0E349283006E7CF6 /* cuddZddFuncs.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C4C0E349280006E7CF6 /* cuddZddFuncs.c */; }; + 27A92F1F0E349283006E7CF6 /* cuddZddGroup.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C4D0E349280006E7CF6 /* cuddZddGroup.c */; }; + 27A92F200E349283006E7CF6 /* cuddZddIsop.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C4E0E349280006E7CF6 /* cuddZddIsop.c */; }; + 27A92F210E349283006E7CF6 /* cuddZddLin.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C4F0E349280006E7CF6 /* cuddZddLin.c */; }; + 27A92F220E349283006E7CF6 /* cuddZddMisc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C500E349280006E7CF6 /* cuddZddMisc.c */; }; + 27A92F230E349283006E7CF6 /* cuddZddPort.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C510E349280006E7CF6 /* cuddZddPort.c */; }; + 27A92F240E349283006E7CF6 /* cuddZddReord.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C520E349280006E7CF6 /* cuddZddReord.c */; }; + 27A92F250E349283006E7CF6 /* cuddZddSetop.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C530E349281006E7CF6 /* cuddZddSetop.c */; }; + 27A92F260E349283006E7CF6 /* cuddZddSymm.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C540E349281006E7CF6 /* cuddZddSymm.c */; }; + 27A92F270E349283006E7CF6 /* cuddZddUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C550E349281006E7CF6 /* cuddZddUtil.c */; }; + 27A92F290E349283006E7CF6 /* dsdApi.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C5B0E349281006E7CF6 /* dsdApi.c */; }; + 27A92F2A0E349283006E7CF6 /* dsdCheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C5C0E349281006E7CF6 /* dsdCheck.c */; }; + 27A92F2B0E349283006E7CF6 /* dsdLocal.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C5E0E349281006E7CF6 /* dsdLocal.c */; }; + 27A92F2C0E349283006E7CF6 /* dsdMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C5F0E349281006E7CF6 /* dsdMan.c */; }; + 27A92F2D0E349283006E7CF6 /* dsdProc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C600E349281006E7CF6 /* dsdProc.c */; }; + 27A92F2E0E349283006E7CF6 /* dsdTree.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C610E349281006E7CF6 /* dsdTree.c */; }; + 27A92F2F0E349283006E7CF6 /* epd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C640E349281006E7CF6 /* epd.c */; }; + 27A92F300E349283006E7CF6 /* mtrBasic.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C6A0E349281006E7CF6 /* mtrBasic.c */; }; + 27A92F310E349283006E7CF6 /* mtrGroup.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C6B0E349281006E7CF6 /* mtrGroup.c */; }; + 27A92F320E349283006E7CF6 /* parseCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C700E349281006E7CF6 /* parseCore.c */; }; + 27A92F330E349283006E7CF6 /* parseEqn.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C710E349281006E7CF6 /* parseEqn.c */; }; + 27A92F340E349283006E7CF6 /* parseStack.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C730E349281006E7CF6 /* parseStack.c */; }; + 27A92F350E349283006E7CF6 /* reoApi.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C770E349281006E7CF6 /* reoApi.c */; }; + 27A92F360E349283006E7CF6 /* reoCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C780E349281006E7CF6 /* reoCore.c */; }; + 27A92F370E349283006E7CF6 /* reoProfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C790E349281006E7CF6 /* reoProfile.c */; }; + 27A92F380E349283006E7CF6 /* reoSift.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C7A0E349281006E7CF6 /* reoSift.c */; }; + 27A92F390E349283006E7CF6 /* reoSwap.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C7B0E349281006E7CF6 /* reoSwap.c */; }; + 27A92F3A0E349283006E7CF6 /* reoTest.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C7C0E349281006E7CF6 /* reoTest.c */; }; + 27A92F3B0E349283006E7CF6 /* reoTransfer.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C7D0E349281006E7CF6 /* reoTransfer.c */; }; + 27A92F3C0E349283006E7CF6 /* reoUnits.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C7E0E349281006E7CF6 /* reoUnits.c */; }; + 27A92F3E0E349283006E7CF6 /* aig_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C830E349281006E7CF6 /* aig_.c */; }; + 27A92F3F0E349283006E7CF6 /* aigCheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C840E349281006E7CF6 /* aigCheck.c */; }; + 27A92F400E349283006E7CF6 /* aigDfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C850E349281006E7CF6 /* aigDfs.c */; }; + 27A92F410E349283006E7CF6 /* aigFanout.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C860E349281006E7CF6 /* aigFanout.c */; }; + 27A92F420E349283006E7CF6 /* aigMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C870E349281006E7CF6 /* aigMan.c */; }; + 27A92F430E349283006E7CF6 /* aigMem.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C880E349281006E7CF6 /* aigMem.c */; }; + 27A92F440E349283006E7CF6 /* aigMffc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C890E349281006E7CF6 /* aigMffc.c */; }; + 27A92F450E349283006E7CF6 /* aigObj.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C8A0E349281006E7CF6 /* aigObj.c */; }; + 27A92F460E349283006E7CF6 /* aigOper.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C8B0E349281006E7CF6 /* aigOper.c */; }; + 27A92F470E349283006E7CF6 /* aigOrder.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C8C0E349281006E7CF6 /* aigOrder.c */; }; + 27A92F480E349283006E7CF6 /* aigPart.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C8D0E349281006E7CF6 /* aigPart.c */; }; + 27A92F490E349283006E7CF6 /* aigRepr.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C8E0E349281006E7CF6 /* aigRepr.c */; }; + 27A92F4A0E349283006E7CF6 /* aigRet.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C8F0E349281006E7CF6 /* aigRet.c */; }; + 27A92F4B0E349283006E7CF6 /* aigScl.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C900E349281006E7CF6 /* aigScl.c */; }; + 27A92F4C0E349283006E7CF6 /* aigSeq.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C910E349281006E7CF6 /* aigSeq.c */; }; + 27A92F4D0E349283006E7CF6 /* aigShow.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C920E349281006E7CF6 /* aigShow.c */; }; + 27A92F4E0E349283006E7CF6 /* aigTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C930E349281006E7CF6 /* aigTable.c */; }; + 27A92F4F0E349283006E7CF6 /* aigTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C940E349281006E7CF6 /* aigTime.c */; }; + 27A92F500E349283006E7CF6 /* aigTiming.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C950E349281006E7CF6 /* aigTiming.c */; }; + 27A92F510E349283006E7CF6 /* aigTruth.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C960E349281006E7CF6 /* aigTruth.c */; }; + 27A92F520E349283006E7CF6 /* aigTsim.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C970E349281006E7CF6 /* aigTsim.c */; }; + 27A92F530E349283006E7CF6 /* aigUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C980E349281006E7CF6 /* aigUtil.c */; }; + 27A92F540E349283006E7CF6 /* aigWin.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C990E349281006E7CF6 /* aigWin.c */; }; + 27A92F550E349283006E7CF6 /* bar.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92C9C0E349281006E7CF6 /* bar.c */; }; + 27A92F560E349283006E7CF6 /* bdc_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CA10E349281006E7CF6 /* bdc_.c */; }; + 27A92F570E349283006E7CF6 /* bdcCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CA20E349281006E7CF6 /* bdcCore.c */; }; + 27A92F580E349283006E7CF6 /* bdcDec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CA30E349281006E7CF6 /* bdcDec.c */; }; + 27A92F590E349283006E7CF6 /* bdcTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CA50E349281006E7CF6 /* bdcTable.c */; }; + 27A92F5A0E349283006E7CF6 /* cnf_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CA90E349281006E7CF6 /* cnf_.c */; }; + 27A92F5B0E349283006E7CF6 /* cnfCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CAA0E349281006E7CF6 /* cnfCore.c */; }; + 27A92F5C0E349283006E7CF6 /* cnfCut.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CAB0E349281006E7CF6 /* cnfCut.c */; }; + 27A92F5D0E349283006E7CF6 /* cnfData.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CAC0E349281006E7CF6 /* cnfData.c */; }; + 27A92F5E0E349283006E7CF6 /* cnfMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CAD0E349281006E7CF6 /* cnfMan.c */; }; + 27A92F5F0E349283006E7CF6 /* cnfMap.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CAE0E349281006E7CF6 /* cnfMap.c */; }; + 27A92F600E349283006E7CF6 /* cnfPost.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CAF0E349281006E7CF6 /* cnfPost.c */; }; + 27A92F610E349283006E7CF6 /* cnfUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CB00E349281006E7CF6 /* cnfUtil.c */; }; + 27A92F620E349283006E7CF6 /* cnfWrite.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CB10E349281006E7CF6 /* cnfWrite.c */; }; + 27A92F630E349283006E7CF6 /* csw_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CB50E349281006E7CF6 /* csw_.c */; }; + 27A92F640E349283006E7CF6 /* cswCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CB60E349281006E7CF6 /* cswCore.c */; }; + 27A92F650E349283006E7CF6 /* cswCut.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CB70E349281006E7CF6 /* cswCut.c */; }; + 27A92F660E349283006E7CF6 /* cswMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CB90E349281006E7CF6 /* cswMan.c */; }; + 27A92F670E349283006E7CF6 /* cswTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CBA0E349281006E7CF6 /* cswTable.c */; }; + 27A92F680E349283006E7CF6 /* dar_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CBE0E349281006E7CF6 /* dar_.c */; }; + 27A92F690E349283006E7CF6 /* darBalance.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CBF0E349281006E7CF6 /* darBalance.c */; }; + 27A92F6A0E349283006E7CF6 /* darCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CC00E349281006E7CF6 /* darCore.c */; }; + 27A92F6B0E349283006E7CF6 /* darCut.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CC10E349281006E7CF6 /* darCut.c */; }; + 27A92F6C0E349283006E7CF6 /* darData.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CC20E349281006E7CF6 /* darData.c */; }; + 27A92F6D0E349283006E7CF6 /* darLib.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CC40E349281006E7CF6 /* darLib.c */; }; + 27A92F6E0E349283006E7CF6 /* darMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CC50E349281006E7CF6 /* darMan.c */; }; + 27A92F6F0E349283006E7CF6 /* darPrec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CC60E349281006E7CF6 /* darPrec.c */; }; + 27A92F700E349283006E7CF6 /* darRefact.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CC70E349281006E7CF6 /* darRefact.c */; }; + 27A92F710E349283006E7CF6 /* darResub.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CC80E349281006E7CF6 /* darResub.c */; }; + 27A92F720E349283006E7CF6 /* darScript.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CC90E349281006E7CF6 /* darScript.c */; }; + 27A92F730E349283006E7CF6 /* fra_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CD00E349281006E7CF6 /* fra_.c */; }; + 27A92F740E349283006E7CF6 /* fraBmc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CD10E349281006E7CF6 /* fraBmc.c */; }; + 27A92F750E349283006E7CF6 /* fraCec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CD20E349281006E7CF6 /* fraCec.c */; }; + 27A92F760E349283006E7CF6 /* fraClass.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CD30E349281006E7CF6 /* fraClass.c */; }; + 27A92F770E349283006E7CF6 /* fraCnf.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CD40E349281006E7CF6 /* fraCnf.c */; }; + 27A92F780E349283006E7CF6 /* fraCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CD50E349281006E7CF6 /* fraCore.c */; }; + 27A92F790E349283006E7CF6 /* fraImp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CD60E349281006E7CF6 /* fraImp.c */; }; + 27A92F7A0E349283006E7CF6 /* fraInd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CD70E349281006E7CF6 /* fraInd.c */; }; + 27A92F7B0E349283006E7CF6 /* fraLcr.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CD80E349281006E7CF6 /* fraLcr.c */; }; + 27A92F7C0E349283006E7CF6 /* fraMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CD90E349281006E7CF6 /* fraMan.c */; }; + 27A92F7D0E349283006E7CF6 /* fraPart.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CDA0E349281006E7CF6 /* fraPart.c */; }; + 27A92F7E0E349283006E7CF6 /* fraSat.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CDB0E349281006E7CF6 /* fraSat.c */; }; + 27A92F7F0E349283006E7CF6 /* fraSec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CDC0E349281006E7CF6 /* fraSec.c */; }; + 27A92F800E349283006E7CF6 /* fraSim.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CDD0E349281006E7CF6 /* fraSim.c */; }; + 27A92F820E349283006E7CF6 /* hop_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CE30E349281006E7CF6 /* hop_.c */; }; + 27A92F830E349283006E7CF6 /* hopBalance.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CE40E349281006E7CF6 /* hopBalance.c */; }; + 27A92F840E349283006E7CF6 /* hopCheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CE50E349281006E7CF6 /* hopCheck.c */; }; + 27A92F850E349283006E7CF6 /* hopDfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CE60E349281006E7CF6 /* hopDfs.c */; }; + 27A92F860E349283006E7CF6 /* hopMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CE70E349281006E7CF6 /* hopMan.c */; }; + 27A92F870E349283006E7CF6 /* hopMem.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CE80E349281006E7CF6 /* hopMem.c */; }; + 27A92F880E349283006E7CF6 /* hopObj.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CE90E349281006E7CF6 /* hopObj.c */; }; + 27A92F890E349283006E7CF6 /* hopOper.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CEA0E349281006E7CF6 /* hopOper.c */; }; + 27A92F8A0E349283006E7CF6 /* hopTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CEB0E349281006E7CF6 /* hopTable.c */; }; + 27A92F8B0E349283006E7CF6 /* hopUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CEC0E349281006E7CF6 /* hopUtil.c */; }; + 27A92F8C0E349283006E7CF6 /* ioaReadAig.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CF00E349281006E7CF6 /* ioaReadAig.c */; }; + 27A92F8D0E349283006E7CF6 /* ioaUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CF10E349281006E7CF6 /* ioaUtil.c */; }; + 27A92F8E0E349283006E7CF6 /* ioaWriteAig.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CF20E349281006E7CF6 /* ioaWriteAig.c */; }; + 27A92F8F0E349283006E7CF6 /* ivy_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CF70E349281006E7CF6 /* ivy_.c */; }; + 27A92F900E349283006E7CF6 /* ivyBalance.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CF80E349281006E7CF6 /* ivyBalance.c */; }; + 27A92F910E349283006E7CF6 /* ivyCanon.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CF90E349281006E7CF6 /* ivyCanon.c */; }; + 27A92F920E349283006E7CF6 /* ivyCheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CFA0E349281006E7CF6 /* ivyCheck.c */; }; + 27A92F930E349283006E7CF6 /* ivyCut.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CFB0E349281006E7CF6 /* ivyCut.c */; }; + 27A92F940E349283006E7CF6 /* ivyCutTrav.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CFC0E349281006E7CF6 /* ivyCutTrav.c */; }; + 27A92F950E349283006E7CF6 /* ivyDfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CFD0E349281006E7CF6 /* ivyDfs.c */; }; + 27A92F960E349283006E7CF6 /* ivyDsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CFE0E349281006E7CF6 /* ivyDsd.c */; }; + 27A92F970E349283006E7CF6 /* ivyFanout.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92CFF0E349281006E7CF6 /* ivyFanout.c */; }; + 27A92F980E349283006E7CF6 /* ivyFastMap.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D000E349281006E7CF6 /* ivyFastMap.c */; }; + 27A92F990E349283006E7CF6 /* ivyFraig.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D010E349281006E7CF6 /* ivyFraig.c */; }; + 27A92F9A0E349283006E7CF6 /* ivyHaig.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D020E349281006E7CF6 /* ivyHaig.c */; }; + 27A92F9B0E349283006E7CF6 /* ivyMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D030E349281006E7CF6 /* ivyMan.c */; }; + 27A92F9C0E349283006E7CF6 /* ivyMem.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D040E349281006E7CF6 /* ivyMem.c */; }; + 27A92F9D0E349283006E7CF6 /* ivyMulti.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D050E349281006E7CF6 /* ivyMulti.c */; }; + 27A92F9F0E349283006E7CF6 /* ivyObj.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D070E349281006E7CF6 /* ivyObj.c */; }; + 27A92FA00E349283006E7CF6 /* ivyOper.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D080E349281006E7CF6 /* ivyOper.c */; }; + 27A92FA10E349283006E7CF6 /* ivyResyn.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D090E349281006E7CF6 /* ivyResyn.c */; }; + 27A92FA20E349283006E7CF6 /* ivyRwr.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D0A0E349281006E7CF6 /* ivyRwr.c */; }; + 27A92FA40E349283006E7CF6 /* ivySeq.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D0C0E349281006E7CF6 /* ivySeq.c */; }; + 27A92FA50E349283006E7CF6 /* ivyShow.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D0D0E349281006E7CF6 /* ivyShow.c */; }; + 27A92FA60E349283006E7CF6 /* ivyTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D0E0E349281006E7CF6 /* ivyTable.c */; }; + 27A92FA70E349283006E7CF6 /* ivyUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D0F0E349281006E7CF6 /* ivyUtil.c */; }; + 27A92FA80E349283006E7CF6 /* cloud.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D120E349281006E7CF6 /* cloud.c */; }; + 27A92FA90E349283006E7CF6 /* kit_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D150E349281006E7CF6 /* kit_.c */; }; + 27A92FAA0E349283006E7CF6 /* kitAig.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D160E349281006E7CF6 /* kitAig.c */; }; + 27A92FAB0E349283006E7CF6 /* kitBdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D170E349281006E7CF6 /* kitBdd.c */; }; + 27A92FAC0E349283006E7CF6 /* kitCloud.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D180E349281006E7CF6 /* kitCloud.c */; }; + 27A92FAD0E349283006E7CF6 /* kitDsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D190E349281006E7CF6 /* kitDsd.c */; }; + 27A92FAE0E349283006E7CF6 /* kitFactor.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D1A0E349281006E7CF6 /* kitFactor.c */; }; + 27A92FAF0E349283006E7CF6 /* kitGraph.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D1B0E349281006E7CF6 /* kitGraph.c */; }; + 27A92FB00E349283006E7CF6 /* kitHop.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D1C0E349281006E7CF6 /* kitHop.c */; }; + 27A92FB10E349283006E7CF6 /* kitIsop.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D1D0E349281006E7CF6 /* kitIsop.c */; }; + 27A92FB20E349283006E7CF6 /* kitSop.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D1E0E349281006E7CF6 /* kitSop.c */; }; + 27A92FB30E349283006E7CF6 /* kitTruth.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D1F0E349281006E7CF6 /* kitTruth.c */; }; + 27A92FB40E349283006E7CF6 /* mem.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D220E349281006E7CF6 /* mem.c */; }; + 27A92FB50E349283006E7CF6 /* rwtDec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D280E349281006E7CF6 /* rwtDec.c */; }; + 27A92FB60E349283006E7CF6 /* rwtMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D290E349281006E7CF6 /* rwtMan.c */; }; + 27A92FB70E349283006E7CF6 /* rwtUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D2A0E349281006E7CF6 /* rwtUtil.c */; }; + 27A92FB80E349283006E7CF6 /* fpga.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D2D0E349281006E7CF6 /* fpga.c */; }; + 27A92FB90E349283006E7CF6 /* fpgaCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D2F0E349281006E7CF6 /* fpgaCore.c */; }; + 27A92FBA0E349283006E7CF6 /* fpgaCreate.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D300E349281006E7CF6 /* fpgaCreate.c */; }; + 27A92FBB0E349283006E7CF6 /* fpgaCut.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D310E349281006E7CF6 /* fpgaCut.c */; }; + 27A92FBC0E349283006E7CF6 /* fpgaCutUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D320E349281006E7CF6 /* fpgaCutUtils.c */; }; + 27A92FBD0E349283006E7CF6 /* fpgaFanout.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D330E349281006E7CF6 /* fpgaFanout.c */; }; + 27A92FBE0E349283006E7CF6 /* fpgaGENERIC.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D340E349281006E7CF6 /* fpgaGENERIC.c */; }; + 27A92FBF0E349283006E7CF6 /* fpgaLib.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D360E349281006E7CF6 /* fpgaLib.c */; }; + 27A92FC00E349283006E7CF6 /* fpgaMatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D370E349281006E7CF6 /* fpgaMatch.c */; }; + 27A92FC10E349283006E7CF6 /* fpgaSwitch.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D380E349281006E7CF6 /* fpgaSwitch.c */; }; + 27A92FC20E349283006E7CF6 /* fpgaTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D390E349281006E7CF6 /* fpgaTime.c */; }; + 27A92FC30E349283006E7CF6 /* fpgaTruth.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D3A0E349281006E7CF6 /* fpgaTruth.c */; }; + 27A92FC40E349283006E7CF6 /* fpgaUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D3B0E349281006E7CF6 /* fpgaUtils.c */; }; + 27A92FC50E349283006E7CF6 /* fpgaVec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D3C0E349281006E7CF6 /* fpgaVec.c */; }; + 27A92FC60E349283006E7CF6 /* if_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D400E349281006E7CF6 /* if_.c */; }; + 27A92FC70E349283006E7CF6 /* ifCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D410E349281006E7CF6 /* ifCore.c */; }; + 27A92FC80E349283006E7CF6 /* ifCut.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D420E349281006E7CF6 /* ifCut.c */; }; + 27A92FC90E349283006E7CF6 /* ifMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D430E349281006E7CF6 /* ifMan.c */; }; + 27A92FCA0E349283006E7CF6 /* ifMap.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D440E349281006E7CF6 /* ifMap.c */; }; + 27A92FCB0E349283006E7CF6 /* ifReduce.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D450E349281006E7CF6 /* ifReduce.c */; }; + 27A92FCC0E349283006E7CF6 /* ifSeq.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D460E349281006E7CF6 /* ifSeq.c */; }; + 27A92FCD0E349283006E7CF6 /* ifTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D470E349281006E7CF6 /* ifTime.c */; }; + 27A92FCE0E349283006E7CF6 /* ifTruth.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D480E349281006E7CF6 /* ifTruth.c */; }; + 27A92FCF0E349283006E7CF6 /* ifUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D490E349281006E7CF6 /* ifUtil.c */; }; + 27A92FD00E349283006E7CF6 /* mapper.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D4C0E349281006E7CF6 /* mapper.c */; }; + 27A92FD10E349283006E7CF6 /* mapperCanon.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D4E0E349281006E7CF6 /* mapperCanon.c */; }; + 27A92FD20E349283006E7CF6 /* mapperCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D4F0E349281006E7CF6 /* mapperCore.c */; }; + 27A92FD30E349283006E7CF6 /* mapperCreate.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D500E349281006E7CF6 /* mapperCreate.c */; }; + 27A92FD40E349283006E7CF6 /* mapperCut.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D510E349281006E7CF6 /* mapperCut.c */; }; + 27A92FD50E349283006E7CF6 /* mapperCutUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D520E349281006E7CF6 /* mapperCutUtils.c */; }; + 27A92FD60E349283006E7CF6 /* mapperFanout.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D530E349281006E7CF6 /* mapperFanout.c */; }; + 27A92FD70E349283006E7CF6 /* mapperGENERIC.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D540E349281006E7CF6 /* mapperGENERIC.c */; }; + 27A92FD80E349283006E7CF6 /* mapperLib.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D560E349281006E7CF6 /* mapperLib.c */; }; + 27A92FD90E349283006E7CF6 /* mapperMatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D570E349281006E7CF6 /* mapperMatch.c */; }; + 27A92FDA0E349283006E7CF6 /* mapperRefs.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D580E349281006E7CF6 /* mapperRefs.c */; }; + 27A92FDB0E349283006E7CF6 /* mapperSuper.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D590E349281006E7CF6 /* mapperSuper.c */; }; + 27A92FDC0E349283006E7CF6 /* mapperSwitch.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D5A0E349281006E7CF6 /* mapperSwitch.c */; }; + 27A92FDD0E349283006E7CF6 /* mapperTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D5B0E349281006E7CF6 /* mapperTable.c */; }; + 27A92FDE0E349283006E7CF6 /* mapperTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D5C0E349281006E7CF6 /* mapperTime.c */; }; + 27A92FDF0E349283006E7CF6 /* mapperTree.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D5D0E349281006E7CF6 /* mapperTree.c */; }; + 27A92FE00E349283006E7CF6 /* mapperTruth.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D5E0E349281006E7CF6 /* mapperTruth.c */; }; + 27A92FE10E349283006E7CF6 /* mapperUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D5F0E349281006E7CF6 /* mapperUtils.c */; }; + 27A92FE20E349283006E7CF6 /* mapperVec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D600E349281006E7CF6 /* mapperVec.c */; }; + 27A92FE30E349283006E7CF6 /* mio.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D630E349281006E7CF6 /* mio.c */; }; + 27A92FE40E349283006E7CF6 /* mioApi.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D650E349281006E7CF6 /* mioApi.c */; }; + 27A92FE50E349283006E7CF6 /* mioFunc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D660E349281006E7CF6 /* mioFunc.c */; }; + 27A92FE60E349283006E7CF6 /* mioGENERIC.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D670E349281006E7CF6 /* mioGENERIC.c */; }; + 27A92FE70E349283006E7CF6 /* mioRead.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D690E349281006E7CF6 /* mioRead.c */; }; + 27A92FE80E349283006E7CF6 /* mioUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D6A0E349281006E7CF6 /* mioUtils.c */; }; + 27A92FE90E349283006E7CF6 /* super.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D6E0E349281006E7CF6 /* super.c */; }; + 27A92FEA0E349283006E7CF6 /* superAnd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D700E349281006E7CF6 /* superAnd.c */; }; + 27A92FEB0E349283006E7CF6 /* superGate.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D710E349281006E7CF6 /* superGate.c */; }; + 27A92FEC0E349283006E7CF6 /* superGENERIC.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D720E349281006E7CF6 /* superGENERIC.c */; }; + 27A92FED0E349283006E7CF6 /* superWrite.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D740E349281006E7CF6 /* superWrite.c */; }; + 27A92FEE0E349283006E7CF6 /* abc_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D780E349282006E7CF6 /* abc_.c */; }; + 27A92FEF0E349283006E7CF6 /* abcAig.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D790E349282006E7CF6 /* abcAig.c */; }; + 27A92FF00E349283006E7CF6 /* abcBlifMv.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D7A0E349282006E7CF6 /* abcBlifMv.c */; }; + 27A92FF10E349283006E7CF6 /* abcCheck.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D7B0E349282006E7CF6 /* abcCheck.c */; }; + 27A92FF20E349283006E7CF6 /* abcDfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D7C0E349282006E7CF6 /* abcDfs.c */; }; + 27A92FF30E349283006E7CF6 /* abcFanio.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D7D0E349282006E7CF6 /* abcFanio.c */; }; + 27A92FF40E349283006E7CF6 /* abcFunc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D7E0E349282006E7CF6 /* abcFunc.c */; }; + 27A92FF50E349283006E7CF6 /* abcHie.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D7F0E349282006E7CF6 /* abcHie.c */; }; + 27A92FF60E349283006E7CF6 /* abcLatch.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D810E349282006E7CF6 /* abcLatch.c */; }; + 27A92FF70E349283006E7CF6 /* abcLib.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D820E349282006E7CF6 /* abcLib.c */; }; + 27A92FF80E349283006E7CF6 /* abcMinBase.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D830E349282006E7CF6 /* abcMinBase.c */; }; + 27A92FF90E349283006E7CF6 /* abcNames.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D840E349282006E7CF6 /* abcNames.c */; }; + 27A92FFA0E349283006E7CF6 /* abcNetlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D850E349282006E7CF6 /* abcNetlist.c */; }; + 27A92FFB0E349283006E7CF6 /* abcNtk.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D860E349282006E7CF6 /* abcNtk.c */; }; + 27A92FFC0E349283006E7CF6 /* abcObj.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D870E349282006E7CF6 /* abcObj.c */; }; + 27A92FFD0E349283006E7CF6 /* abcRefs.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D880E349282006E7CF6 /* abcRefs.c */; }; + 27A92FFE0E349283006E7CF6 /* abcShow.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D890E349282006E7CF6 /* abcShow.c */; }; + 27A92FFF0E349283006E7CF6 /* abcSop.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D8A0E349282006E7CF6 /* abcSop.c */; }; + 27A930000E349283006E7CF6 /* abcUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D8B0E349282006E7CF6 /* abcUtil.c */; }; + 27A930010E349283006E7CF6 /* abc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D8E0E349282006E7CF6 /* abc.c */; }; + 27A930020E349283006E7CF6 /* abc_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D8F0E349282006E7CF6 /* abc_.c */; }; + 27A930030E349283006E7CF6 /* abcAttach.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D900E349282006E7CF6 /* abcAttach.c */; }; + 27A930040E349283006E7CF6 /* abcAuto.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D910E349282006E7CF6 /* abcAuto.c */; }; + 27A930050E349283006E7CF6 /* abcBalance.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D920E349282006E7CF6 /* abcBalance.c */; }; + 27A930060E349283006E7CF6 /* abcBmc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D930E349282006E7CF6 /* abcBmc.c */; }; + 27A930070E349283006E7CF6 /* abcCas.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D940E349282006E7CF6 /* abcCas.c */; }; + 27A930080E349283006E7CF6 /* abcClpBdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D950E349282006E7CF6 /* abcClpBdd.c */; }; + 27A930090E349283006E7CF6 /* abcClpSop.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D960E349282006E7CF6 /* abcClpSop.c */; }; + 27A9300A0E349283006E7CF6 /* abcCut.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D970E349282006E7CF6 /* abcCut.c */; }; + 27A9300B0E349283006E7CF6 /* abcDar.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D980E349282006E7CF6 /* abcDar.c */; }; + 27A9300C0E349283006E7CF6 /* abcDebug.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D990E349282006E7CF6 /* abcDebug.c */; }; + 27A9300D0E349283006E7CF6 /* abcDress.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D9A0E349282006E7CF6 /* abcDress.c */; }; + 27A9300E0E349283006E7CF6 /* abcDsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D9B0E349282006E7CF6 /* abcDsd.c */; }; + 27A9300F0E349283006E7CF6 /* abcEspresso.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D9C0E349282006E7CF6 /* abcEspresso.c */; }; + 27A930100E349283006E7CF6 /* abcExtract.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D9D0E349282006E7CF6 /* abcExtract.c */; }; + 27A930110E349283006E7CF6 /* abcFpga.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D9E0E349282006E7CF6 /* abcFpga.c */; }; + 27A930120E349283006E7CF6 /* abcFpgaFast.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92D9F0E349282006E7CF6 /* abcFpgaFast.c */; }; + 27A930130E349283006E7CF6 /* abcFraig.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DA00E349282006E7CF6 /* abcFraig.c */; }; + 27A930140E349283006E7CF6 /* abcFxu.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DA10E349282006E7CF6 /* abcFxu.c */; }; + 27A930150E349283006E7CF6 /* abcGen.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DA20E349282006E7CF6 /* abcGen.c */; }; + 27A930160E349283006E7CF6 /* abcHaig.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DA30E349282006E7CF6 /* abcHaig.c */; }; + 27A930170E349283006E7CF6 /* abcIf.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DA40E349282006E7CF6 /* abcIf.c */; }; + 27A930180E349283006E7CF6 /* abcIvy.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DA50E349282006E7CF6 /* abcIvy.c */; }; + 27A930190E349283006E7CF6 /* abcLut.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DA60E349282006E7CF6 /* abcLut.c */; }; + 27A9301A0E349283006E7CF6 /* abcMap.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DA70E349282006E7CF6 /* abcMap.c */; }; + 27A9301B0E349283006E7CF6 /* abcMeasure.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DA80E349282006E7CF6 /* abcMeasure.c */; }; + 27A9301C0E349283006E7CF6 /* abcMini.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DA90E349282006E7CF6 /* abcMini.c */; }; + 27A9301D0E349283006E7CF6 /* abcMiter.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DAA0E349282006E7CF6 /* abcMiter.c */; }; + 27A9301E0E349283006E7CF6 /* abcMulti.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DAB0E349282006E7CF6 /* abcMulti.c */; }; + 27A9301F0E349283006E7CF6 /* abcMv.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DAC0E349282006E7CF6 /* abcMv.c */; }; + 27A930200E349283006E7CF6 /* abcNtbdd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DAD0E349282006E7CF6 /* abcNtbdd.c */; }; + 27A930210E349283006E7CF6 /* abcOdc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DAE0E349282006E7CF6 /* abcOdc.c */; }; + 27A930220E349283006E7CF6 /* abcOrder.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DAF0E349282006E7CF6 /* abcOrder.c */; }; + 27A930230E349283006E7CF6 /* abcPart.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DB00E349282006E7CF6 /* abcPart.c */; }; + 27A930250E349283006E7CF6 /* abcPrint.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DB20E349282006E7CF6 /* abcPrint.c */; }; + 27A930260E349283006E7CF6 /* abcProve.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DB30E349282006E7CF6 /* abcProve.c */; }; + 27A930270E349283006E7CF6 /* abcQbf.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DB40E349282006E7CF6 /* abcQbf.c */; }; + 27A930280E349283006E7CF6 /* abcQuant.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DB50E349282006E7CF6 /* abcQuant.c */; }; + 27A930290E349283006E7CF6 /* abcRec.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DB60E349282006E7CF6 /* abcRec.c */; }; + 27A9302A0E349283006E7CF6 /* abcReconv.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DB70E349282006E7CF6 /* abcReconv.c */; }; + 27A9302B0E349283006E7CF6 /* abcRefactor.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DB80E349282006E7CF6 /* abcRefactor.c */; }; + 27A9302C0E349283006E7CF6 /* abcRenode.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DB90E349282006E7CF6 /* abcRenode.c */; }; + 27A9302D0E349283006E7CF6 /* abcReorder.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DBA0E349282006E7CF6 /* abcReorder.c */; }; + 27A9302E0E349283006E7CF6 /* abcRestruct.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DBB0E349282006E7CF6 /* abcRestruct.c */; }; + 27A9302F0E349283006E7CF6 /* abcResub.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DBC0E349282006E7CF6 /* abcResub.c */; }; + 27A930300E349283006E7CF6 /* abcRewrite.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DBD0E349282006E7CF6 /* abcRewrite.c */; }; + 27A930310E349283006E7CF6 /* abcRr.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DBE0E349282006E7CF6 /* abcRr.c */; }; + 27A930320E349283006E7CF6 /* abcSat.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DBF0E349282006E7CF6 /* abcSat.c */; }; + 27A930330E349283006E7CF6 /* abcStrash.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DC00E349282006E7CF6 /* abcStrash.c */; }; + 27A930340E349283006E7CF6 /* abcSweep.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DC10E349282006E7CF6 /* abcSweep.c */; }; + 27A930350E349283006E7CF6 /* abcSymm.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DC20E349282006E7CF6 /* abcSymm.c */; }; + 27A930360E349283006E7CF6 /* abcTiming.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DC30E349282006E7CF6 /* abcTiming.c */; }; + 27A930370E349283006E7CF6 /* abcUnate.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DC40E349282006E7CF6 /* abcUnate.c */; }; + 27A930380E349283006E7CF6 /* abcUnreach.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DC50E349282006E7CF6 /* abcUnreach.c */; }; + 27A930390E349283006E7CF6 /* abcVerify.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DC60E349282006E7CF6 /* abcVerify.c */; }; + 27A9303A0E349283006E7CF6 /* abcXsim.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DC70E349282006E7CF6 /* abcXsim.c */; }; + 27A9303B0E349283006E7CF6 /* cmd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DCA0E349282006E7CF6 /* cmd.c */; }; + 27A9303C0E349283006E7CF6 /* cmdAlias.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DCC0E349282006E7CF6 /* cmdAlias.c */; }; + 27A9303D0E349283006E7CF6 /* cmdApi.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DCD0E349282006E7CF6 /* cmdApi.c */; }; + 27A9303E0E349283006E7CF6 /* cmdFlag.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DCE0E349282006E7CF6 /* cmdFlag.c */; }; + 27A9303F0E349283006E7CF6 /* cmdHist.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DCF0E349282006E7CF6 /* cmdHist.c */; }; + 27A930400E349283006E7CF6 /* cmdUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DD10E349282006E7CF6 /* cmdUtils.c */; }; + 27A930410E349283006E7CF6 /* io.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DD40E349282006E7CF6 /* io.c */; }; + 27A930420E349283006E7CF6 /* io_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DD60E349282006E7CF6 /* io_.c */; }; + 27A930430E349283006E7CF6 /* ioReadAiger.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DD80E349282006E7CF6 /* ioReadAiger.c */; }; + 27A930440E349283006E7CF6 /* ioReadBaf.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DD90E349282006E7CF6 /* ioReadBaf.c */; }; + 27A930450E349283006E7CF6 /* ioReadBench.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DDA0E349282006E7CF6 /* ioReadBench.c */; }; + 27A930460E349283006E7CF6 /* ioReadBlif.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DDB0E349282006E7CF6 /* ioReadBlif.c */; }; + 27A930470E349283006E7CF6 /* ioReadBlifAig.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DDC0E349282006E7CF6 /* ioReadBlifAig.c */; }; + 27A930480E349283006E7CF6 /* ioReadBlifMv.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DDD0E349282006E7CF6 /* ioReadBlifMv.c */; }; + 27A930490E349283006E7CF6 /* ioReadDsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DDE0E349282006E7CF6 /* ioReadDsd.c */; }; + 27A9304A0E349283006E7CF6 /* ioReadEdif.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DDF0E349282006E7CF6 /* ioReadEdif.c */; }; + 27A9304B0E349283006E7CF6 /* ioReadEqn.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DE00E349282006E7CF6 /* ioReadEqn.c */; }; + 27A9304C0E349283006E7CF6 /* ioReadPla.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DE10E349282006E7CF6 /* ioReadPla.c */; }; + 27A9304D0E349283006E7CF6 /* ioReadVerilog.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DE20E349282006E7CF6 /* ioReadVerilog.c */; }; + 27A9304E0E349283006E7CF6 /* ioUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DE30E349282006E7CF6 /* ioUtil.c */; }; + 27A9304F0E349283006E7CF6 /* ioWriteAiger.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DE40E349282006E7CF6 /* ioWriteAiger.c */; }; + 27A930500E349283006E7CF6 /* ioWriteBaf.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DE50E349282006E7CF6 /* ioWriteBaf.c */; }; + 27A930510E349283006E7CF6 /* ioWriteBench.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DE60E349282006E7CF6 /* ioWriteBench.c */; }; + 27A930520E349283006E7CF6 /* ioWriteBlif.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DE70E349282006E7CF6 /* ioWriteBlif.c */; }; + 27A930530E349283006E7CF6 /* ioWriteBlifMv.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DE80E349282006E7CF6 /* ioWriteBlifMv.c */; }; + 27A930540E349283006E7CF6 /* ioWriteCnf.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DE90E349282006E7CF6 /* ioWriteCnf.c */; }; + 27A930550E349283006E7CF6 /* ioWriteDot.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DEA0E349282006E7CF6 /* ioWriteDot.c */; }; + 27A930560E349283006E7CF6 /* ioWriteEqn.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DEB0E349282006E7CF6 /* ioWriteEqn.c */; }; + 27A930570E349283006E7CF6 /* ioWriteGml.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DEC0E349282006E7CF6 /* ioWriteGml.c */; }; + 27A930580E349283006E7CF6 /* ioWriteList.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DED0E349282006E7CF6 /* ioWriteList.c */; }; + 27A930590E349283006E7CF6 /* ioWritePla.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DEE0E349282006E7CF6 /* ioWritePla.c */; }; + 27A9305A0E349283006E7CF6 /* ioWriteVerilog.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DEF0E349282006E7CF6 /* ioWriteVerilog.c */; }; + 27A9305B0E349283006E7CF6 /* libSupport.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DF20E349282006E7CF6 /* libSupport.c */; }; + 27A9305C0E349283006E7CF6 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DF30E349282006E7CF6 /* main.c */; }; + 27A9305D0E349283006E7CF6 /* mainFrame.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DF50E349282006E7CF6 /* mainFrame.c */; }; + 27A9305E0E349283006E7CF6 /* mainInit.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DF60E349282006E7CF6 /* mainInit.c */; }; + 27A9305F0E349283006E7CF6 /* mainUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DF80E349282006E7CF6 /* mainUtils.c */; }; + 27A930610E349283006E7CF6 /* ver_.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DFE0E349282006E7CF6 /* ver_.c */; }; + 27A930620E349283006E7CF6 /* verCore.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92DFF0E349282006E7CF6 /* verCore.c */; }; + 27A930630E349283006E7CF6 /* verFormula.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E000E349282006E7CF6 /* verFormula.c */; }; + 27A930640E349283006E7CF6 /* verParse.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E010E349282006E7CF6 /* verParse.c */; }; + 27A930650E349283006E7CF6 /* verStream.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E020E349282006E7CF6 /* verStream.c */; }; + 27A930660E349283006E7CF6 /* verWords.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E030E349282006E7CF6 /* verWords.c */; }; + 27A930670E349283006E7CF6 /* cofactor.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E060E349282006E7CF6 /* cofactor.c */; }; + 27A930680E349283006E7CF6 /* cols.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E070E349282006E7CF6 /* cols.c */; }; + 27A930690E349283006E7CF6 /* compl.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E080E349282006E7CF6 /* compl.c */; }; + 27A9306A0E349283006E7CF6 /* contain.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E090E349282006E7CF6 /* contain.c */; }; + 27A9306B0E349283006E7CF6 /* cubehack.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E0A0E349282006E7CF6 /* cubehack.c */; }; + 27A9306C0E349283006E7CF6 /* cubestr.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E0B0E349282006E7CF6 /* cubestr.c */; }; + 27A9306D0E349283006E7CF6 /* cvrin.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E0C0E349282006E7CF6 /* cvrin.c */; }; + 27A9306E0E349283006E7CF6 /* cvrm.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E0D0E349282006E7CF6 /* cvrm.c */; }; + 27A9306F0E349283006E7CF6 /* cvrmisc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E0E0E349282006E7CF6 /* cvrmisc.c */; }; + 27A930700E349283006E7CF6 /* cvrout.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E0F0E349282006E7CF6 /* cvrout.c */; }; + 27A930710E349283006E7CF6 /* dominate.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E100E349282006E7CF6 /* dominate.c */; }; + 27A930720E349283006E7CF6 /* equiv.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E110E349282006E7CF6 /* equiv.c */; }; + 27A930730E349283006E7CF6 /* espresso.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E120E349282006E7CF6 /* espresso.c */; }; + 27A930740E349283006E7CF6 /* essen.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E140E349282006E7CF6 /* essen.c */; }; + 27A930750E349283006E7CF6 /* exact.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E150E349282006E7CF6 /* exact.c */; }; + 27A930760E349283006E7CF6 /* expand.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E160E349282006E7CF6 /* expand.c */; }; + 27A930770E349283006E7CF6 /* gasp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E170E349282006E7CF6 /* gasp.c */; }; + 27A930780E349283006E7CF6 /* gimpel.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E180E349282006E7CF6 /* gimpel.c */; }; + 27A930790E349283006E7CF6 /* globals.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E190E349282006E7CF6 /* globals.c */; }; + 27A9307A0E349283006E7CF6 /* hack.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E1A0E349282006E7CF6 /* hack.c */; }; + 27A9307B0E349283006E7CF6 /* indep.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E1B0E349282006E7CF6 /* indep.c */; }; + 27A9307C0E349283006E7CF6 /* irred.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E1C0E349282006E7CF6 /* irred.c */; }; + 27A9307E0E349283006E7CF6 /* map.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E1F0E349282006E7CF6 /* map.c */; }; + 27A9307F0E349283006E7CF6 /* matrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E200E349282006E7CF6 /* matrix.c */; }; + 27A930800E349283006E7CF6 /* mincov.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E210E349282006E7CF6 /* mincov.c */; }; + 27A930810E349283006E7CF6 /* opo.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E250E349282006E7CF6 /* opo.c */; }; + 27A930820E349283006E7CF6 /* pair.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E260E349282006E7CF6 /* pair.c */; }; + 27A930830E349283006E7CF6 /* part.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E270E349282006E7CF6 /* part.c */; }; + 27A930840E349283006E7CF6 /* primes.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E280E349282006E7CF6 /* primes.c */; }; + 27A930850E349283006E7CF6 /* reduce.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E290E349282006E7CF6 /* reduce.c */; }; + 27A930860E349283006E7CF6 /* rows.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E2A0E349282006E7CF6 /* rows.c */; }; + 27A930870E349283006E7CF6 /* set.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E2B0E349282006E7CF6 /* set.c */; }; + 27A930880E349283006E7CF6 /* setc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E2C0E349282006E7CF6 /* setc.c */; }; + 27A930890E349283006E7CF6 /* sharp.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E2D0E349282006E7CF6 /* sharp.c */; }; + 27A9308A0E349283006E7CF6 /* sminterf.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E2E0E349282006E7CF6 /* sminterf.c */; }; + 27A9308B0E349283006E7CF6 /* solution.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E2F0E349282006E7CF6 /* solution.c */; }; + 27A9308C0E349283006E7CF6 /* sparse.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E300E349282006E7CF6 /* sparse.c */; }; + 27A9308E0E349283006E7CF6 /* verify.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E350E349282006E7CF6 /* verify.c */; }; + 27A9308F0E349283006E7CF6 /* extraBddAuto.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E380E349282006E7CF6 /* extraBddAuto.c */; }; + 27A930900E349283006E7CF6 /* extraBddCas.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E390E349282006E7CF6 /* extraBddCas.c */; }; + 27A930910E349283006E7CF6 /* extraBddKmap.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E3A0E349282006E7CF6 /* extraBddKmap.c */; }; + 27A930920E349283006E7CF6 /* extraBddMisc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E3B0E349282006E7CF6 /* extraBddMisc.c */; }; + 27A930930E349283006E7CF6 /* extraBddSymm.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E3C0E349282006E7CF6 /* extraBddSymm.c */; }; + 27A930940E349283006E7CF6 /* extraBddUnate.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E3D0E349282006E7CF6 /* extraBddUnate.c */; }; + 27A930950E349283006E7CF6 /* extraUtilBitMatrix.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E3E0E349282006E7CF6 /* extraUtilBitMatrix.c */; }; + 27A930960E349283006E7CF6 /* extraUtilCanon.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E3F0E349282006E7CF6 /* extraUtilCanon.c */; }; + 27A930970E349283006E7CF6 /* extraUtilFile.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E400E349282006E7CF6 /* extraUtilFile.c */; }; + 27A930980E349283006E7CF6 /* extraUtilMemory.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E410E349282006E7CF6 /* extraUtilMemory.c */; }; + 27A930990E349283006E7CF6 /* extraUtilMisc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E420E349282006E7CF6 /* extraUtilMisc.c */; }; + 27A9309A0E349283006E7CF6 /* extraUtilProgress.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E430E349282006E7CF6 /* extraUtilProgress.c */; }; + 27A9309B0E349283006E7CF6 /* extraUtilReader.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E440E349282006E7CF6 /* extraUtilReader.c */; }; + 27A9309C0E349283006E7CF6 /* extraUtilTruth.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E450E349282006E7CF6 /* extraUtilTruth.c */; }; + 27A9309D0E349283006E7CF6 /* extraUtilUtil.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E460E349282006E7CF6 /* extraUtilUtil.c */; }; + 27A9309E0E349283006E7CF6 /* mvc.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E500E349282006E7CF6 /* mvc.c */; }; + 27A9309F0E349283006E7CF6 /* mvcApi.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E520E349282006E7CF6 /* mvcApi.c */; }; + 27A930A00E349283006E7CF6 /* mvcCompare.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E530E349282006E7CF6 /* mvcCompare.c */; }; + 27A930A10E349283006E7CF6 /* mvcContain.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E540E349282006E7CF6 /* mvcContain.c */; }; + 27A930A20E349283006E7CF6 /* mvcCover.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E550E349282006E7CF6 /* mvcCover.c */; }; + 27A930A30E349283006E7CF6 /* mvcCube.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E560E349282006E7CF6 /* mvcCube.c */; }; + 27A930A40E349283006E7CF6 /* mvcDivide.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E570E349282006E7CF6 /* mvcDivide.c */; }; + 27A930A50E349283006E7CF6 /* mvcDivisor.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E580E349282006E7CF6 /* mvcDivisor.c */; }; + 27A930A60E349283006E7CF6 /* mvcList.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E590E349282006E7CF6 /* mvcList.c */; }; + 27A930A70E349283006E7CF6 /* mvcLits.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E5A0E349282006E7CF6 /* mvcLits.c */; }; + 27A930A80E349283006E7CF6 /* mvcMan.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E5B0E349282006E7CF6 /* mvcMan.c */; }; + 27A930A90E349283006E7CF6 /* mvcOpAlg.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E5C0E349282006E7CF6 /* mvcOpAlg.c */; }; + 27A930AA0E349283006E7CF6 /* mvcOpBool.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E5D0E349283006E7CF6 /* mvcOpBool.c */; }; + 27A930AB0E349283006E7CF6 /* mvcPrint.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E5E0E349283006E7CF6 /* mvcPrint.c */; }; + 27A930AC0E349283006E7CF6 /* mvcSort.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E5F0E349283006E7CF6 /* mvcSort.c */; }; + 27A930AD0E349283006E7CF6 /* mvcUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E600E349283006E7CF6 /* mvcUtils.c */; }; + 27A930AE0E349283006E7CF6 /* nmApi.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E640E349283006E7CF6 /* nmApi.c */; }; + 27A930AF0E349283006E7CF6 /* nmTable.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E660E349283006E7CF6 /* nmTable.c */; }; + 27A930B00E349283006E7CF6 /* st.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E690E349283006E7CF6 /* st.c */; }; + 27A930B10E349283006E7CF6 /* stmm.c in Sources */ = {isa = PBXBuildFile; fileRef = 27A92E6B0E349283006E7CF6 /* stmm.c */; }; + 8DD76FB00486AB0100D96B5E /* abc.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6A0FF2C0290799A04C91782 /* abc.1 */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 8DD76FAF0486AB0100D96B5E /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 8; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 8DD76FB00486AB0100D96B5E /* abc.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 274040EF0E38BED900DC6F18 /* libreadline.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libreadline.dylib; path = /usr/lib/libreadline.dylib; sourceTree = ""; }; + 27A92B6E0E349280006E7CF6 /* abcCut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcCut.c; sourceTree = ""; }; + 27A92B6F0E349280006E7CF6 /* cut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cut.h; sourceTree = ""; }; + 27A92B700E349280006E7CF6 /* cutApi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cutApi.c; sourceTree = ""; }; + 27A92B710E349280006E7CF6 /* cutCut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cutCut.c; sourceTree = ""; }; + 27A92B720E349280006E7CF6 /* cutExpand.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cutExpand.c; sourceTree = ""; }; + 27A92B730E349280006E7CF6 /* cutInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cutInt.h; sourceTree = ""; }; + 27A92B740E349280006E7CF6 /* cutList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cutList.h; sourceTree = ""; }; + 27A92B750E349280006E7CF6 /* cutMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cutMan.c; sourceTree = ""; }; + 27A92B760E349280006E7CF6 /* cutMerge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cutMerge.c; sourceTree = ""; }; + 27A92B770E349280006E7CF6 /* cutNode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cutNode.c; sourceTree = ""; }; + 27A92B780E349280006E7CF6 /* cutOracle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cutOracle.c; sourceTree = ""; }; + 27A92B790E349280006E7CF6 /* cutPre22.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cutPre22.c; sourceTree = ""; }; + 27A92B7A0E349280006E7CF6 /* cutSeq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cutSeq.c; sourceTree = ""; }; + 27A92B7B0E349280006E7CF6 /* cutTruth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cutTruth.c; sourceTree = ""; }; + 27A92B7C0E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92B7E0E349280006E7CF6 /* dec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dec.h; sourceTree = ""; }; + 27A92B7F0E349280006E7CF6 /* decAbc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = decAbc.c; sourceTree = ""; }; + 27A92B800E349280006E7CF6 /* decFactor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = decFactor.c; sourceTree = ""; }; + 27A92B810E349280006E7CF6 /* decMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = decMan.c; sourceTree = ""; }; + 27A92B820E349280006E7CF6 /* decPrint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = decPrint.c; sourceTree = ""; }; + 27A92B830E349280006E7CF6 /* decUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = decUtil.c; sourceTree = ""; }; + 27A92B840E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92B860E349280006E7CF6 /* fxu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxu.c; sourceTree = ""; }; + 27A92B870E349280006E7CF6 /* fxu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fxu.h; sourceTree = ""; }; + 27A92B880E349280006E7CF6 /* fxuCreate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxuCreate.c; sourceTree = ""; }; + 27A92B890E349280006E7CF6 /* fxuHeapD.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxuHeapD.c; sourceTree = ""; }; + 27A92B8A0E349280006E7CF6 /* fxuHeapS.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxuHeapS.c; sourceTree = ""; }; + 27A92B8B0E349280006E7CF6 /* fxuInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fxuInt.h; sourceTree = ""; }; + 27A92B8C0E349280006E7CF6 /* fxuList.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxuList.c; sourceTree = ""; }; + 27A92B8D0E349280006E7CF6 /* fxuMatrix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxuMatrix.c; sourceTree = ""; }; + 27A92B8E0E349280006E7CF6 /* fxuPair.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxuPair.c; sourceTree = ""; }; + 27A92B8F0E349280006E7CF6 /* fxuPrint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxuPrint.c; sourceTree = ""; }; + 27A92B900E349280006E7CF6 /* fxuReduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxuReduce.c; sourceTree = ""; }; + 27A92B910E349280006E7CF6 /* fxuSelect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxuSelect.c; sourceTree = ""; }; + 27A92B920E349280006E7CF6 /* fxuSingle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxuSingle.c; sourceTree = ""; }; + 27A92B930E349280006E7CF6 /* fxuUpdate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fxuUpdate.c; sourceTree = ""; }; + 27A92B940E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92B960E349280006E7CF6 /* lpk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lpk.h; sourceTree = ""; }; + 27A92B970E349280006E7CF6 /* lpk_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpk_.c; sourceTree = ""; }; + 27A92B980E349280006E7CF6 /* lpkAbcDec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpkAbcDec.c; sourceTree = ""; }; + 27A92B990E349280006E7CF6 /* lpkAbcDsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpkAbcDsd.c; sourceTree = ""; }; + 27A92B9A0E349280006E7CF6 /* lpkAbcMux.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpkAbcMux.c; sourceTree = ""; }; + 27A92B9B0E349280006E7CF6 /* lpkAbcUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpkAbcUtil.c; sourceTree = ""; }; + 27A92B9C0E349280006E7CF6 /* lpkCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpkCore.c; sourceTree = ""; }; + 27A92B9D0E349280006E7CF6 /* lpkCut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpkCut.c; sourceTree = ""; }; + 27A92B9E0E349280006E7CF6 /* lpkInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lpkInt.h; sourceTree = ""; }; + 27A92B9F0E349280006E7CF6 /* lpkMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpkMan.c; sourceTree = ""; }; + 27A92BA00E349280006E7CF6 /* lpkMap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpkMap.c; sourceTree = ""; }; + 27A92BA10E349280006E7CF6 /* lpkMulti.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpkMulti.c; sourceTree = ""; }; + 27A92BA20E349280006E7CF6 /* lpkMux.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpkMux.c; sourceTree = ""; }; + 27A92BA30E349280006E7CF6 /* lpkSets.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpkSets.c; sourceTree = ""; }; + 27A92BA40E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92BA60E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92BA70E349280006E7CF6 /* res.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = res.h; sourceTree = ""; }; + 27A92BA80E349280006E7CF6 /* res_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = res_.c; sourceTree = ""; }; + 27A92BA90E349280006E7CF6 /* resCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resCore.c; sourceTree = ""; }; + 27A92BAA0E349280006E7CF6 /* resDivs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resDivs.c; sourceTree = ""; }; + 27A92BAB0E349280006E7CF6 /* resFilter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resFilter.c; sourceTree = ""; }; + 27A92BAC0E349280006E7CF6 /* resInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resInt.h; sourceTree = ""; }; + 27A92BAD0E349280006E7CF6 /* resSat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resSat.c; sourceTree = ""; }; + 27A92BAE0E349280006E7CF6 /* resSim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resSim.c; sourceTree = ""; }; + 27A92BAF0E349280006E7CF6 /* resSim_old.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resSim_old.c; sourceTree = ""; }; + 27A92BB00E349280006E7CF6 /* resStrash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resStrash.c; sourceTree = ""; }; + 27A92BB10E349280006E7CF6 /* resWin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resWin.c; sourceTree = ""; }; + 27A92BB30E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92BB40E349280006E7CF6 /* ret_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ret_.c; sourceTree = ""; }; + 27A92BB50E349280006E7CF6 /* retArea.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = retArea.c; sourceTree = ""; }; + 27A92BB60E349280006E7CF6 /* retCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = retCore.c; sourceTree = ""; }; + 27A92BB70E349280006E7CF6 /* retDelay.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = retDelay.c; sourceTree = ""; }; + 27A92BB80E349280006E7CF6 /* retFlow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = retFlow.c; sourceTree = ""; }; + 27A92BB90E349280006E7CF6 /* retIncrem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = retIncrem.c; sourceTree = ""; }; + 27A92BBA0E349280006E7CF6 /* retInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = retInit.c; sourceTree = ""; }; + 27A92BBB0E349280006E7CF6 /* retInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = retInt.h; sourceTree = ""; }; + 27A92BBC0E349280006E7CF6 /* retLvalue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = retLvalue.c; sourceTree = ""; }; + 27A92BBE0E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92BBF0E349280006E7CF6 /* rwr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rwr.h; sourceTree = ""; }; + 27A92BC00E349280006E7CF6 /* rwrDec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwrDec.c; sourceTree = ""; }; + 27A92BC10E349280006E7CF6 /* rwrEva.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwrEva.c; sourceTree = ""; }; + 27A92BC20E349280006E7CF6 /* rwrExp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwrExp.c; sourceTree = ""; }; + 27A92BC30E349280006E7CF6 /* rwrLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwrLib.c; sourceTree = ""; }; + 27A92BC40E349280006E7CF6 /* rwrMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwrMan.c; sourceTree = ""; }; + 27A92BC50E349280006E7CF6 /* rwrPrint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwrPrint.c; sourceTree = ""; }; + 27A92BC60E349280006E7CF6 /* rwrTemp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwrTemp.c; sourceTree = ""; }; + 27A92BC70E349280006E7CF6 /* rwrUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwrUtil.c; sourceTree = ""; }; + 27A92BC90E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92BCA0E349280006E7CF6 /* sim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sim.h; sourceTree = ""; }; + 27A92BCB0E349280006E7CF6 /* simMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simMan.c; sourceTree = ""; }; + 27A92BCC0E349280006E7CF6 /* simSat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simSat.c; sourceTree = ""; }; + 27A92BCD0E349280006E7CF6 /* simSeq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simSeq.c; sourceTree = ""; }; + 27A92BCE0E349280006E7CF6 /* simSupp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simSupp.c; sourceTree = ""; }; + 27A92BCF0E349280006E7CF6 /* simSwitch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simSwitch.c; sourceTree = ""; }; + 27A92BD00E349280006E7CF6 /* simSym.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simSym.c; sourceTree = ""; }; + 27A92BD10E349280006E7CF6 /* simSymSat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simSymSat.c; sourceTree = ""; }; + 27A92BD20E349280006E7CF6 /* simSymSim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simSymSim.c; sourceTree = ""; }; + 27A92BD30E349280006E7CF6 /* simSymStr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simSymStr.c; sourceTree = ""; }; + 27A92BD40E349280006E7CF6 /* simUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = simUtils.c; sourceTree = ""; }; + 27A92BD50E349280006E7CF6 /* generic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = generic.h; sourceTree = ""; }; + 27A92BD80E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92BD90E349280006E7CF6 /* satInter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = satInter.c; sourceTree = ""; }; + 27A92BDA0E349280006E7CF6 /* satMem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = satMem.c; sourceTree = ""; }; + 27A92BDB0E349280006E7CF6 /* satMem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = satMem.h; sourceTree = ""; }; + 27A92BDC0E349280006E7CF6 /* satSolver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = satSolver.c; sourceTree = ""; }; + 27A92BDD0E349280006E7CF6 /* satSolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = satSolver.h; sourceTree = ""; }; + 27A92BDE0E349280006E7CF6 /* satStore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = satStore.c; sourceTree = ""; }; + 27A92BDF0E349280006E7CF6 /* satStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = satStore.h; sourceTree = ""; }; + 27A92BE00E349280006E7CF6 /* satTrace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = satTrace.c; sourceTree = ""; }; + 27A92BE10E349280006E7CF6 /* satUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = satUtil.c; sourceTree = ""; }; + 27A92BE20E349280006E7CF6 /* satVec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = satVec.h; sourceTree = ""; }; + 27A92BE40E349280006E7CF6 /* csat_apis.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = csat_apis.c; sourceTree = ""; }; + 27A92BE50E349280006E7CF6 /* csat_apis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = csat_apis.h; sourceTree = ""; }; + 27A92BE60E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92BE80E349280006E7CF6 /* fraig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fraig.h; sourceTree = ""; }; + 27A92BE90E349280006E7CF6 /* fraigApi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigApi.c; sourceTree = ""; }; + 27A92BEA0E349280006E7CF6 /* fraigCanon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigCanon.c; sourceTree = ""; }; + 27A92BEB0E349280006E7CF6 /* fraigChoice.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigChoice.c; sourceTree = ""; }; + 27A92BEC0E349280006E7CF6 /* fraigFanout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigFanout.c; sourceTree = ""; }; + 27A92BED0E349280006E7CF6 /* fraigFeed.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigFeed.c; sourceTree = ""; }; + 27A92BEE0E349280006E7CF6 /* fraigInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fraigInt.h; sourceTree = ""; }; + 27A92BEF0E349280006E7CF6 /* fraigMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigMan.c; sourceTree = ""; }; + 27A92BF00E349280006E7CF6 /* fraigMem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigMem.c; sourceTree = ""; }; + 27A92BF10E349280006E7CF6 /* fraigNode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigNode.c; sourceTree = ""; }; + 27A92BF20E349280006E7CF6 /* fraigPrime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigPrime.c; sourceTree = ""; }; + 27A92BF30E349280006E7CF6 /* fraigSat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigSat.c; sourceTree = ""; }; + 27A92BF40E349280006E7CF6 /* fraigTable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigTable.c; sourceTree = ""; }; + 27A92BF50E349280006E7CF6 /* fraigUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigUtil.c; sourceTree = ""; }; + 27A92BF60E349280006E7CF6 /* fraigVec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraigVec.c; sourceTree = ""; }; + 27A92BF70E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92BF90E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92BFA0E349280006E7CF6 /* msat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = msat.h; sourceTree = ""; }; + 27A92BFB0E349280006E7CF6 /* msatActivity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatActivity.c; sourceTree = ""; }; + 27A92BFC0E349280006E7CF6 /* msatClause.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatClause.c; sourceTree = ""; }; + 27A92BFD0E349280006E7CF6 /* msatClauseVec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatClauseVec.c; sourceTree = ""; }; + 27A92BFE0E349280006E7CF6 /* msatInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = msatInt.h; sourceTree = ""; }; + 27A92BFF0E349280006E7CF6 /* msatMem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatMem.c; sourceTree = ""; }; + 27A92C000E349280006E7CF6 /* msatOrderH.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatOrderH.c; sourceTree = ""; }; + 27A92C010E349280006E7CF6 /* msatOrderJ.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatOrderJ.c; sourceTree = ""; }; + 27A92C020E349280006E7CF6 /* msatQueue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatQueue.c; sourceTree = ""; }; + 27A92C030E349280006E7CF6 /* msatRead.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatRead.c; sourceTree = ""; }; + 27A92C040E349280006E7CF6 /* msatSolverApi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatSolverApi.c; sourceTree = ""; }; + 27A92C050E349280006E7CF6 /* msatSolverCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatSolverCore.c; sourceTree = ""; }; + 27A92C060E349280006E7CF6 /* msatSolverIo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatSolverIo.c; sourceTree = ""; }; + 27A92C070E349280006E7CF6 /* msatSolverSearch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatSolverSearch.c; sourceTree = ""; }; + 27A92C080E349280006E7CF6 /* msatSort.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatSort.c; sourceTree = ""; }; + 27A92C090E349280006E7CF6 /* msatVec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msatVec.c; sourceTree = ""; }; + 27A92C0B0E349280006E7CF6 /* pr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pr.c; sourceTree = ""; }; + 27A92C0C0E349280006E7CF6 /* pr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pr.h; sourceTree = ""; }; + 27A92C0D0E349280006E7CF6 /* stats.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = stats.txt; sourceTree = ""; }; + 27A92C100E349280006E7CF6 /* cas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cas.h; sourceTree = ""; }; + 27A92C110E349280006E7CF6 /* casCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = casCore.c; sourceTree = ""; }; + 27A92C120E349280006E7CF6 /* casDec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = casDec.c; sourceTree = ""; }; + 27A92C130E349280006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92C150E349280006E7CF6 /* cuBdd.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = cuBdd.make; sourceTree = ""; }; + 27A92C160E349280006E7CF6 /* cudd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cudd.h; sourceTree = ""; }; + 27A92C170E349280006E7CF6 /* cudd.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = cudd.make; sourceTree = ""; }; + 27A92C180E349280006E7CF6 /* cuddAddAbs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddAddAbs.c; sourceTree = ""; }; + 27A92C190E349280006E7CF6 /* cuddAddApply.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddAddApply.c; sourceTree = ""; }; + 27A92C1A0E349280006E7CF6 /* cuddAddFind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddAddFind.c; sourceTree = ""; }; + 27A92C1B0E349280006E7CF6 /* cuddAddInv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddAddInv.c; sourceTree = ""; }; + 27A92C1C0E349280006E7CF6 /* cuddAddIte.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddAddIte.c; sourceTree = ""; }; + 27A92C1D0E349280006E7CF6 /* cuddAddNeg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddAddNeg.c; sourceTree = ""; }; + 27A92C1E0E349280006E7CF6 /* cuddAddWalsh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddAddWalsh.c; sourceTree = ""; }; + 27A92C1F0E349280006E7CF6 /* cuddAndAbs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddAndAbs.c; sourceTree = ""; }; + 27A92C200E349280006E7CF6 /* cuddAnneal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddAnneal.c; sourceTree = ""; }; + 27A92C210E349280006E7CF6 /* cuddApa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddApa.c; sourceTree = ""; }; + 27A92C220E349280006E7CF6 /* cuddAPI.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddAPI.c; sourceTree = ""; }; + 27A92C230E349280006E7CF6 /* cuddApprox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddApprox.c; sourceTree = ""; }; + 27A92C240E349280006E7CF6 /* cuddBddAbs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddBddAbs.c; sourceTree = ""; }; + 27A92C250E349280006E7CF6 /* cuddBddCorr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddBddCorr.c; sourceTree = ""; }; + 27A92C260E349280006E7CF6 /* cuddBddIte.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddBddIte.c; sourceTree = ""; }; + 27A92C270E349280006E7CF6 /* cuddBridge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddBridge.c; sourceTree = ""; }; + 27A92C280E349280006E7CF6 /* cuddCache.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddCache.c; sourceTree = ""; }; + 27A92C290E349280006E7CF6 /* cuddCheck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddCheck.c; sourceTree = ""; }; + 27A92C2A0E349280006E7CF6 /* cuddClip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddClip.c; sourceTree = ""; }; + 27A92C2B0E349280006E7CF6 /* cuddCof.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddCof.c; sourceTree = ""; }; + 27A92C2C0E349280006E7CF6 /* cuddCompose.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddCompose.c; sourceTree = ""; }; + 27A92C2D0E349280006E7CF6 /* cuddDecomp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddDecomp.c; sourceTree = ""; }; + 27A92C2E0E349280006E7CF6 /* cuddEssent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddEssent.c; sourceTree = ""; }; + 27A92C2F0E349280006E7CF6 /* cuddExact.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddExact.c; sourceTree = ""; }; + 27A92C300E349280006E7CF6 /* cuddExport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddExport.c; sourceTree = ""; }; + 27A92C310E349280006E7CF6 /* cuddGenCof.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddGenCof.c; sourceTree = ""; }; + 27A92C320E349280006E7CF6 /* cuddGenetic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddGenetic.c; sourceTree = ""; }; + 27A92C330E349280006E7CF6 /* cuddGroup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddGroup.c; sourceTree = ""; }; + 27A92C340E349280006E7CF6 /* cuddHarwell.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddHarwell.c; sourceTree = ""; }; + 27A92C350E349280006E7CF6 /* cuddInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddInit.c; sourceTree = ""; }; + 27A92C360E349280006E7CF6 /* cuddInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cuddInt.h; sourceTree = ""; }; + 27A92C370E349280006E7CF6 /* cuddInteract.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddInteract.c; sourceTree = ""; }; + 27A92C380E349280006E7CF6 /* cuddLCache.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddLCache.c; sourceTree = ""; }; + 27A92C390E349280006E7CF6 /* cuddLevelQ.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddLevelQ.c; sourceTree = ""; }; + 27A92C3A0E349280006E7CF6 /* cuddLinear.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddLinear.c; sourceTree = ""; }; + 27A92C3B0E349280006E7CF6 /* cuddLiteral.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddLiteral.c; sourceTree = ""; }; + 27A92C3C0E349280006E7CF6 /* cuddMatMult.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddMatMult.c; sourceTree = ""; }; + 27A92C3D0E349280006E7CF6 /* cuddPriority.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddPriority.c; sourceTree = ""; }; + 27A92C3E0E349280006E7CF6 /* cuddRead.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddRead.c; sourceTree = ""; }; + 27A92C3F0E349280006E7CF6 /* cuddRef.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddRef.c; sourceTree = ""; }; + 27A92C400E349280006E7CF6 /* cuddReorder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddReorder.c; sourceTree = ""; }; + 27A92C410E349280006E7CF6 /* cuddSat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddSat.c; sourceTree = ""; }; + 27A92C420E349280006E7CF6 /* cuddSign.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddSign.c; sourceTree = ""; }; + 27A92C430E349280006E7CF6 /* cuddSolve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddSolve.c; sourceTree = ""; }; + 27A92C440E349280006E7CF6 /* cuddSplit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddSplit.c; sourceTree = ""; }; + 27A92C450E349280006E7CF6 /* cuddSubsetHB.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddSubsetHB.c; sourceTree = ""; }; + 27A92C460E349280006E7CF6 /* cuddSubsetSP.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddSubsetSP.c; sourceTree = ""; }; + 27A92C470E349280006E7CF6 /* cuddSymmetry.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddSymmetry.c; sourceTree = ""; }; + 27A92C480E349280006E7CF6 /* cuddTable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddTable.c; sourceTree = ""; }; + 27A92C490E349280006E7CF6 /* cuddUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddUtil.c; sourceTree = ""; }; + 27A92C4A0E349280006E7CF6 /* cuddWindow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddWindow.c; sourceTree = ""; }; + 27A92C4B0E349280006E7CF6 /* cuddZddCount.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddZddCount.c; sourceTree = ""; }; + 27A92C4C0E349280006E7CF6 /* cuddZddFuncs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddZddFuncs.c; sourceTree = ""; }; + 27A92C4D0E349280006E7CF6 /* cuddZddGroup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddZddGroup.c; sourceTree = ""; }; + 27A92C4E0E349280006E7CF6 /* cuddZddIsop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddZddIsop.c; sourceTree = ""; }; + 27A92C4F0E349280006E7CF6 /* cuddZddLin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddZddLin.c; sourceTree = ""; }; + 27A92C500E349280006E7CF6 /* cuddZddMisc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddZddMisc.c; sourceTree = ""; }; + 27A92C510E349280006E7CF6 /* cuddZddPort.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddZddPort.c; sourceTree = ""; }; + 27A92C520E349280006E7CF6 /* cuddZddReord.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddZddReord.c; sourceTree = ""; }; + 27A92C530E349281006E7CF6 /* cuddZddSetop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddZddSetop.c; sourceTree = ""; }; + 27A92C540E349281006E7CF6 /* cuddZddSymm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddZddSymm.c; sourceTree = ""; }; + 27A92C550E349281006E7CF6 /* cuddZddUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cuddZddUtil.c; sourceTree = ""; }; + 27A92C560E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92C570E349281006E7CF6 /* r7x8.1.mat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = r7x8.1.mat; sourceTree = ""; }; + 27A92C580E349281006E7CF6 /* testcudd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = testcudd.c; sourceTree = ""; }; + 27A92C5A0E349281006E7CF6 /* dsd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dsd.h; sourceTree = ""; }; + 27A92C5B0E349281006E7CF6 /* dsdApi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsdApi.c; sourceTree = ""; }; + 27A92C5C0E349281006E7CF6 /* dsdCheck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsdCheck.c; sourceTree = ""; }; + 27A92C5D0E349281006E7CF6 /* dsdInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dsdInt.h; sourceTree = ""; }; + 27A92C5E0E349281006E7CF6 /* dsdLocal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsdLocal.c; sourceTree = ""; }; + 27A92C5F0E349281006E7CF6 /* dsdMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsdMan.c; sourceTree = ""; }; + 27A92C600E349281006E7CF6 /* dsdProc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsdProc.c; sourceTree = ""; }; + 27A92C610E349281006E7CF6 /* dsdTree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsdTree.c; sourceTree = ""; }; + 27A92C620E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92C640E349281006E7CF6 /* epd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = epd.c; sourceTree = ""; }; + 27A92C650E349281006E7CF6 /* epd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = epd.h; sourceTree = ""; }; + 27A92C660E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92C680E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92C690E349281006E7CF6 /* mtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mtr.h; sourceTree = ""; }; + 27A92C6A0E349281006E7CF6 /* mtrBasic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mtrBasic.c; sourceTree = ""; }; + 27A92C6B0E349281006E7CF6 /* mtrGroup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mtrGroup.c; sourceTree = ""; }; + 27A92C6C0E349281006E7CF6 /* mtrInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mtrInt.h; sourceTree = ""; }; + 27A92C6E0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92C6F0E349281006E7CF6 /* parse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parse.h; sourceTree = ""; }; + 27A92C700E349281006E7CF6 /* parseCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parseCore.c; sourceTree = ""; }; + 27A92C710E349281006E7CF6 /* parseEqn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parseEqn.c; sourceTree = ""; }; + 27A92C720E349281006E7CF6 /* parseInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parseInt.h; sourceTree = ""; }; + 27A92C730E349281006E7CF6 /* parseStack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = parseStack.c; sourceTree = ""; }; + 27A92C750E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92C760E349281006E7CF6 /* reo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reo.h; sourceTree = ""; }; + 27A92C770E349281006E7CF6 /* reoApi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reoApi.c; sourceTree = ""; }; + 27A92C780E349281006E7CF6 /* reoCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reoCore.c; sourceTree = ""; }; + 27A92C790E349281006E7CF6 /* reoProfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reoProfile.c; sourceTree = ""; }; + 27A92C7A0E349281006E7CF6 /* reoSift.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reoSift.c; sourceTree = ""; }; + 27A92C7B0E349281006E7CF6 /* reoSwap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reoSwap.c; sourceTree = ""; }; + 27A92C7C0E349281006E7CF6 /* reoTest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reoTest.c; sourceTree = ""; }; + 27A92C7D0E349281006E7CF6 /* reoTransfer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reoTransfer.c; sourceTree = ""; }; + 27A92C7E0E349281006E7CF6 /* reoUnits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reoUnits.c; sourceTree = ""; }; + 27A92C7F0E349281006E7CF6 /* generic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = generic.c; sourceTree = ""; }; + 27A92C820E349281006E7CF6 /* aig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aig.h; sourceTree = ""; }; + 27A92C830E349281006E7CF6 /* aig_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aig_.c; sourceTree = ""; }; + 27A92C840E349281006E7CF6 /* aigCheck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigCheck.c; sourceTree = ""; }; + 27A92C850E349281006E7CF6 /* aigDfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigDfs.c; sourceTree = ""; }; + 27A92C860E349281006E7CF6 /* aigFanout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigFanout.c; sourceTree = ""; }; + 27A92C870E349281006E7CF6 /* aigMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigMan.c; sourceTree = ""; }; + 27A92C880E349281006E7CF6 /* aigMem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigMem.c; sourceTree = ""; }; + 27A92C890E349281006E7CF6 /* aigMffc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigMffc.c; sourceTree = ""; }; + 27A92C8A0E349281006E7CF6 /* aigObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigObj.c; sourceTree = ""; }; + 27A92C8B0E349281006E7CF6 /* aigOper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigOper.c; sourceTree = ""; }; + 27A92C8C0E349281006E7CF6 /* aigOrder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigOrder.c; sourceTree = ""; }; + 27A92C8D0E349281006E7CF6 /* aigPart.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigPart.c; sourceTree = ""; }; + 27A92C8E0E349281006E7CF6 /* aigRepr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigRepr.c; sourceTree = ""; }; + 27A92C8F0E349281006E7CF6 /* aigRet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigRet.c; sourceTree = ""; }; + 27A92C900E349281006E7CF6 /* aigScl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigScl.c; sourceTree = ""; }; + 27A92C910E349281006E7CF6 /* aigSeq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigSeq.c; sourceTree = ""; }; + 27A92C920E349281006E7CF6 /* aigShow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigShow.c; sourceTree = ""; }; + 27A92C930E349281006E7CF6 /* aigTable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigTable.c; sourceTree = ""; }; + 27A92C940E349281006E7CF6 /* aigTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigTime.c; sourceTree = ""; }; + 27A92C950E349281006E7CF6 /* aigTiming.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigTiming.c; sourceTree = ""; }; + 27A92C960E349281006E7CF6 /* aigTruth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigTruth.c; sourceTree = ""; }; + 27A92C970E349281006E7CF6 /* aigTsim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigTsim.c; sourceTree = ""; }; + 27A92C980E349281006E7CF6 /* aigUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigUtil.c; sourceTree = ""; }; + 27A92C990E349281006E7CF6 /* aigWin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aigWin.c; sourceTree = ""; }; + 27A92C9A0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92C9C0E349281006E7CF6 /* bar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bar.c; sourceTree = ""; }; + 27A92C9D0E349281006E7CF6 /* bar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bar.h; sourceTree = ""; }; + 27A92C9E0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92CA00E349281006E7CF6 /* bdc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bdc.h; sourceTree = ""; }; + 27A92CA10E349281006E7CF6 /* bdc_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bdc_.c; sourceTree = ""; }; + 27A92CA20E349281006E7CF6 /* bdcCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bdcCore.c; sourceTree = ""; }; + 27A92CA30E349281006E7CF6 /* bdcDec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bdcDec.c; sourceTree = ""; }; + 27A92CA40E349281006E7CF6 /* bdcInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bdcInt.h; sourceTree = ""; }; + 27A92CA50E349281006E7CF6 /* bdcTable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bdcTable.c; sourceTree = ""; }; + 27A92CA60E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92CA80E349281006E7CF6 /* cnf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cnf.h; sourceTree = ""; }; + 27A92CA90E349281006E7CF6 /* cnf_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cnf_.c; sourceTree = ""; }; + 27A92CAA0E349281006E7CF6 /* cnfCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cnfCore.c; sourceTree = ""; }; + 27A92CAB0E349281006E7CF6 /* cnfCut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cnfCut.c; sourceTree = ""; }; + 27A92CAC0E349281006E7CF6 /* cnfData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cnfData.c; sourceTree = ""; }; + 27A92CAD0E349281006E7CF6 /* cnfMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cnfMan.c; sourceTree = ""; }; + 27A92CAE0E349281006E7CF6 /* cnfMap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cnfMap.c; sourceTree = ""; }; + 27A92CAF0E349281006E7CF6 /* cnfPost.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cnfPost.c; sourceTree = ""; }; + 27A92CB00E349281006E7CF6 /* cnfUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cnfUtil.c; sourceTree = ""; }; + 27A92CB10E349281006E7CF6 /* cnfWrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cnfWrite.c; sourceTree = ""; }; + 27A92CB20E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92CB40E349281006E7CF6 /* csw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = csw.h; sourceTree = ""; }; + 27A92CB50E349281006E7CF6 /* csw_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = csw_.c; sourceTree = ""; }; + 27A92CB60E349281006E7CF6 /* cswCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cswCore.c; sourceTree = ""; }; + 27A92CB70E349281006E7CF6 /* cswCut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cswCut.c; sourceTree = ""; }; + 27A92CB80E349281006E7CF6 /* cswInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cswInt.h; sourceTree = ""; }; + 27A92CB90E349281006E7CF6 /* cswMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cswMan.c; sourceTree = ""; }; + 27A92CBA0E349281006E7CF6 /* cswTable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cswTable.c; sourceTree = ""; }; + 27A92CBB0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92CBD0E349281006E7CF6 /* dar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dar.h; sourceTree = ""; }; + 27A92CBE0E349281006E7CF6 /* dar_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dar_.c; sourceTree = ""; }; + 27A92CBF0E349281006E7CF6 /* darBalance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darBalance.c; sourceTree = ""; }; + 27A92CC00E349281006E7CF6 /* darCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darCore.c; sourceTree = ""; }; + 27A92CC10E349281006E7CF6 /* darCut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darCut.c; sourceTree = ""; }; + 27A92CC20E349281006E7CF6 /* darData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darData.c; sourceTree = ""; }; + 27A92CC30E349281006E7CF6 /* darInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = darInt.h; sourceTree = ""; }; + 27A92CC40E349281006E7CF6 /* darLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darLib.c; sourceTree = ""; }; + 27A92CC50E349281006E7CF6 /* darMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darMan.c; sourceTree = ""; }; + 27A92CC60E349281006E7CF6 /* darPrec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darPrec.c; sourceTree = ""; }; + 27A92CC70E349281006E7CF6 /* darRefact.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darRefact.c; sourceTree = ""; }; + 27A92CC80E349281006E7CF6 /* darResub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darResub.c; sourceTree = ""; }; + 27A92CC90E349281006E7CF6 /* darScript.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darScript.c; sourceTree = ""; }; + 27A92CCA0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92CCC0E349281006E7CF6 /* deco.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = deco.h; sourceTree = ""; }; + 27A92CCD0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92CCF0E349281006E7CF6 /* fra.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fra.h; sourceTree = ""; }; + 27A92CD00E349281006E7CF6 /* fra_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fra_.c; sourceTree = ""; }; + 27A92CD10E349281006E7CF6 /* fraBmc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraBmc.c; sourceTree = ""; }; + 27A92CD20E349281006E7CF6 /* fraCec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraCec.c; sourceTree = ""; }; + 27A92CD30E349281006E7CF6 /* fraClass.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraClass.c; sourceTree = ""; }; + 27A92CD40E349281006E7CF6 /* fraCnf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraCnf.c; sourceTree = ""; }; + 27A92CD50E349281006E7CF6 /* fraCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraCore.c; sourceTree = ""; }; + 27A92CD60E349281006E7CF6 /* fraImp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraImp.c; sourceTree = ""; }; + 27A92CD70E349281006E7CF6 /* fraInd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraInd.c; sourceTree = ""; }; + 27A92CD80E349281006E7CF6 /* fraLcr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraLcr.c; sourceTree = ""; }; + 27A92CD90E349281006E7CF6 /* fraMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraMan.c; sourceTree = ""; }; + 27A92CDA0E349281006E7CF6 /* fraPart.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraPart.c; sourceTree = ""; }; + 27A92CDB0E349281006E7CF6 /* fraSat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraSat.c; sourceTree = ""; }; + 27A92CDC0E349281006E7CF6 /* fraSec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraSec.c; sourceTree = ""; }; + 27A92CDD0E349281006E7CF6 /* fraSim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fraSim.c; sourceTree = ""; }; + 27A92CDE0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92CE00E349281006E7CF6 /* cudd2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cudd2.c; sourceTree = ""; }; + 27A92CE10E349281006E7CF6 /* cudd2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cudd2.h; sourceTree = ""; }; + 27A92CE20E349281006E7CF6 /* hop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hop.h; sourceTree = ""; }; + 27A92CE30E349281006E7CF6 /* hop_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hop_.c; sourceTree = ""; }; + 27A92CE40E349281006E7CF6 /* hopBalance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hopBalance.c; sourceTree = ""; }; + 27A92CE50E349281006E7CF6 /* hopCheck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hopCheck.c; sourceTree = ""; }; + 27A92CE60E349281006E7CF6 /* hopDfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hopDfs.c; sourceTree = ""; }; + 27A92CE70E349281006E7CF6 /* hopMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hopMan.c; sourceTree = ""; }; + 27A92CE80E349281006E7CF6 /* hopMem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hopMem.c; sourceTree = ""; }; + 27A92CE90E349281006E7CF6 /* hopObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hopObj.c; sourceTree = ""; }; + 27A92CEA0E349281006E7CF6 /* hopOper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hopOper.c; sourceTree = ""; }; + 27A92CEB0E349281006E7CF6 /* hopTable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hopTable.c; sourceTree = ""; }; + 27A92CEC0E349281006E7CF6 /* hopUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hopUtil.c; sourceTree = ""; }; + 27A92CED0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92CEF0E349281006E7CF6 /* ioa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioa.h; sourceTree = ""; }; + 27A92CF00E349281006E7CF6 /* ioaReadAig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioaReadAig.c; sourceTree = ""; }; + 27A92CF10E349281006E7CF6 /* ioaUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioaUtil.c; sourceTree = ""; }; + 27A92CF20E349281006E7CF6 /* ioaWriteAig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioaWriteAig.c; sourceTree = ""; }; + 27A92CF30E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92CF50E349281006E7CF6 /* attr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = attr.h; sourceTree = ""; }; + 27A92CF60E349281006E7CF6 /* ivy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ivy.h; sourceTree = ""; }; + 27A92CF70E349281006E7CF6 /* ivy_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivy_.c; sourceTree = ""; }; + 27A92CF80E349281006E7CF6 /* ivyBalance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyBalance.c; sourceTree = ""; }; + 27A92CF90E349281006E7CF6 /* ivyCanon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyCanon.c; sourceTree = ""; }; + 27A92CFA0E349281006E7CF6 /* ivyCheck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyCheck.c; sourceTree = ""; }; + 27A92CFB0E349281006E7CF6 /* ivyCut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyCut.c; sourceTree = ""; }; + 27A92CFC0E349281006E7CF6 /* ivyCutTrav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyCutTrav.c; sourceTree = ""; }; + 27A92CFD0E349281006E7CF6 /* ivyDfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyDfs.c; sourceTree = ""; }; + 27A92CFE0E349281006E7CF6 /* ivyDsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyDsd.c; sourceTree = ""; }; + 27A92CFF0E349281006E7CF6 /* ivyFanout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyFanout.c; sourceTree = ""; }; + 27A92D000E349281006E7CF6 /* ivyFastMap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyFastMap.c; sourceTree = ""; }; + 27A92D010E349281006E7CF6 /* ivyFraig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyFraig.c; sourceTree = ""; }; + 27A92D020E349281006E7CF6 /* ivyHaig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyHaig.c; sourceTree = ""; }; + 27A92D030E349281006E7CF6 /* ivyMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyMan.c; sourceTree = ""; }; + 27A92D040E349281006E7CF6 /* ivyMem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyMem.c; sourceTree = ""; }; + 27A92D050E349281006E7CF6 /* ivyMulti.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyMulti.c; sourceTree = ""; }; + 27A92D060E349281006E7CF6 /* ivyMulti8.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyMulti8.c; sourceTree = ""; }; + 27A92D070E349281006E7CF6 /* ivyObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyObj.c; sourceTree = ""; }; + 27A92D080E349281006E7CF6 /* ivyOper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyOper.c; sourceTree = ""; }; + 27A92D090E349281006E7CF6 /* ivyResyn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyResyn.c; sourceTree = ""; }; + 27A92D0A0E349281006E7CF6 /* ivyRwr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyRwr.c; sourceTree = ""; }; + 27A92D0B0E349281006E7CF6 /* ivyRwrAlg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyRwrAlg.c; sourceTree = ""; }; + 27A92D0C0E349281006E7CF6 /* ivySeq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivySeq.c; sourceTree = ""; }; + 27A92D0D0E349281006E7CF6 /* ivyShow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyShow.c; sourceTree = ""; }; + 27A92D0E0E349281006E7CF6 /* ivyTable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyTable.c; sourceTree = ""; }; + 27A92D0F0E349281006E7CF6 /* ivyUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivyUtil.c; sourceTree = ""; }; + 27A92D100E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92D120E349281006E7CF6 /* cloud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cloud.c; sourceTree = ""; }; + 27A92D130E349281006E7CF6 /* cloud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cloud.h; sourceTree = ""; }; + 27A92D140E349281006E7CF6 /* kit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kit.h; sourceTree = ""; }; + 27A92D150E349281006E7CF6 /* kit_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kit_.c; sourceTree = ""; }; + 27A92D160E349281006E7CF6 /* kitAig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kitAig.c; sourceTree = ""; }; + 27A92D170E349281006E7CF6 /* kitBdd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kitBdd.c; sourceTree = ""; }; + 27A92D180E349281006E7CF6 /* kitCloud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kitCloud.c; sourceTree = ""; }; + 27A92D190E349281006E7CF6 /* kitDsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kitDsd.c; sourceTree = ""; }; + 27A92D1A0E349281006E7CF6 /* kitFactor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kitFactor.c; sourceTree = ""; }; + 27A92D1B0E349281006E7CF6 /* kitGraph.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kitGraph.c; sourceTree = ""; }; + 27A92D1C0E349281006E7CF6 /* kitHop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kitHop.c; sourceTree = ""; }; + 27A92D1D0E349281006E7CF6 /* kitIsop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kitIsop.c; sourceTree = ""; }; + 27A92D1E0E349281006E7CF6 /* kitSop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kitSop.c; sourceTree = ""; }; + 27A92D1F0E349281006E7CF6 /* kitTruth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kitTruth.c; sourceTree = ""; }; + 27A92D200E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92D220E349281006E7CF6 /* mem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mem.c; sourceTree = ""; }; + 27A92D230E349281006E7CF6 /* mem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mem.h; sourceTree = ""; }; + 27A92D240E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92D260E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92D270E349281006E7CF6 /* rwt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rwt.h; sourceTree = ""; }; + 27A92D280E349281006E7CF6 /* rwtDec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwtDec.c; sourceTree = ""; }; + 27A92D290E349281006E7CF6 /* rwtMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwtMan.c; sourceTree = ""; }; + 27A92D2A0E349281006E7CF6 /* rwtUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwtUtil.c; sourceTree = ""; }; + 27A92D2D0E349281006E7CF6 /* fpga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpga.c; sourceTree = ""; }; + 27A92D2E0E349281006E7CF6 /* fpga.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fpga.h; sourceTree = ""; }; + 27A92D2F0E349281006E7CF6 /* fpgaCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaCore.c; sourceTree = ""; }; + 27A92D300E349281006E7CF6 /* fpgaCreate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaCreate.c; sourceTree = ""; }; + 27A92D310E349281006E7CF6 /* fpgaCut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaCut.c; sourceTree = ""; }; + 27A92D320E349281006E7CF6 /* fpgaCutUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaCutUtils.c; sourceTree = ""; }; + 27A92D330E349281006E7CF6 /* fpgaFanout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaFanout.c; sourceTree = ""; }; + 27A92D340E349281006E7CF6 /* fpgaGENERIC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaGENERIC.c; sourceTree = ""; }; + 27A92D350E349281006E7CF6 /* fpgaInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fpgaInt.h; sourceTree = ""; }; + 27A92D360E349281006E7CF6 /* fpgaLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaLib.c; sourceTree = ""; }; + 27A92D370E349281006E7CF6 /* fpgaMatch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaMatch.c; sourceTree = ""; }; + 27A92D380E349281006E7CF6 /* fpgaSwitch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaSwitch.c; sourceTree = ""; }; + 27A92D390E349281006E7CF6 /* fpgaTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaTime.c; sourceTree = ""; }; + 27A92D3A0E349281006E7CF6 /* fpgaTruth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaTruth.c; sourceTree = ""; }; + 27A92D3B0E349281006E7CF6 /* fpgaUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaUtils.c; sourceTree = ""; }; + 27A92D3C0E349281006E7CF6 /* fpgaVec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fpgaVec.c; sourceTree = ""; }; + 27A92D3D0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92D3F0E349281006E7CF6 /* if.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = if.h; sourceTree = ""; }; + 27A92D400E349281006E7CF6 /* if_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = if_.c; sourceTree = ""; }; + 27A92D410E349281006E7CF6 /* ifCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifCore.c; sourceTree = ""; }; + 27A92D420E349281006E7CF6 /* ifCut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifCut.c; sourceTree = ""; }; + 27A92D430E349281006E7CF6 /* ifMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifMan.c; sourceTree = ""; }; + 27A92D440E349281006E7CF6 /* ifMap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifMap.c; sourceTree = ""; }; + 27A92D450E349281006E7CF6 /* ifReduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifReduce.c; sourceTree = ""; }; + 27A92D460E349281006E7CF6 /* ifSeq.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifSeq.c; sourceTree = ""; }; + 27A92D470E349281006E7CF6 /* ifTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifTime.c; sourceTree = ""; }; + 27A92D480E349281006E7CF6 /* ifTruth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifTruth.c; sourceTree = ""; }; + 27A92D490E349281006E7CF6 /* ifUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ifUtil.c; sourceTree = ""; }; + 27A92D4A0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92D4C0E349281006E7CF6 /* mapper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapper.c; sourceTree = ""; }; + 27A92D4D0E349281006E7CF6 /* mapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mapper.h; sourceTree = ""; }; + 27A92D4E0E349281006E7CF6 /* mapperCanon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperCanon.c; sourceTree = ""; }; + 27A92D4F0E349281006E7CF6 /* mapperCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperCore.c; sourceTree = ""; }; + 27A92D500E349281006E7CF6 /* mapperCreate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperCreate.c; sourceTree = ""; }; + 27A92D510E349281006E7CF6 /* mapperCut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperCut.c; sourceTree = ""; }; + 27A92D520E349281006E7CF6 /* mapperCutUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperCutUtils.c; sourceTree = ""; }; + 27A92D530E349281006E7CF6 /* mapperFanout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperFanout.c; sourceTree = ""; }; + 27A92D540E349281006E7CF6 /* mapperGENERIC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperGENERIC.c; sourceTree = ""; }; + 27A92D550E349281006E7CF6 /* mapperInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mapperInt.h; sourceTree = ""; }; + 27A92D560E349281006E7CF6 /* mapperLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperLib.c; sourceTree = ""; }; + 27A92D570E349281006E7CF6 /* mapperMatch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperMatch.c; sourceTree = ""; }; + 27A92D580E349281006E7CF6 /* mapperRefs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperRefs.c; sourceTree = ""; }; + 27A92D590E349281006E7CF6 /* mapperSuper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperSuper.c; sourceTree = ""; }; + 27A92D5A0E349281006E7CF6 /* mapperSwitch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperSwitch.c; sourceTree = ""; }; + 27A92D5B0E349281006E7CF6 /* mapperTable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperTable.c; sourceTree = ""; }; + 27A92D5C0E349281006E7CF6 /* mapperTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperTime.c; sourceTree = ""; }; + 27A92D5D0E349281006E7CF6 /* mapperTree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperTree.c; sourceTree = ""; }; + 27A92D5E0E349281006E7CF6 /* mapperTruth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperTruth.c; sourceTree = ""; }; + 27A92D5F0E349281006E7CF6 /* mapperUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperUtils.c; sourceTree = ""; }; + 27A92D600E349281006E7CF6 /* mapperVec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapperVec.c; sourceTree = ""; }; + 27A92D610E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92D630E349281006E7CF6 /* mio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mio.c; sourceTree = ""; }; + 27A92D640E349281006E7CF6 /* mio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mio.h; sourceTree = ""; }; + 27A92D650E349281006E7CF6 /* mioApi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mioApi.c; sourceTree = ""; }; + 27A92D660E349281006E7CF6 /* mioFunc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mioFunc.c; sourceTree = ""; }; + 27A92D670E349281006E7CF6 /* mioGENERIC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mioGENERIC.c; sourceTree = ""; }; + 27A92D680E349281006E7CF6 /* mioInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mioInt.h; sourceTree = ""; }; + 27A92D690E349281006E7CF6 /* mioRead.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mioRead.c; sourceTree = ""; }; + 27A92D6A0E349281006E7CF6 /* mioUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mioUtils.c; sourceTree = ""; }; + 27A92D6B0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92D6D0E349281006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92D6E0E349281006E7CF6 /* super.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = super.c; sourceTree = ""; }; + 27A92D6F0E349281006E7CF6 /* super.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = super.h; sourceTree = ""; }; + 27A92D700E349281006E7CF6 /* superAnd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = superAnd.c; sourceTree = ""; }; + 27A92D710E349281006E7CF6 /* superGate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = superGate.c; sourceTree = ""; }; + 27A92D720E349281006E7CF6 /* superGENERIC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = superGENERIC.c; sourceTree = ""; }; + 27A92D730E349281006E7CF6 /* superInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = superInt.h; sourceTree = ""; }; + 27A92D740E349281006E7CF6 /* superWrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = superWrite.c; sourceTree = ""; }; + 27A92D770E349282006E7CF6 /* abc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abc.h; sourceTree = ""; }; + 27A92D780E349282006E7CF6 /* abc_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abc_.c; sourceTree = ""; }; + 27A92D790E349282006E7CF6 /* abcAig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcAig.c; sourceTree = ""; }; + 27A92D7A0E349282006E7CF6 /* abcBlifMv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcBlifMv.c; sourceTree = ""; }; + 27A92D7B0E349282006E7CF6 /* abcCheck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcCheck.c; sourceTree = ""; }; + 27A92D7C0E349282006E7CF6 /* abcDfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcDfs.c; sourceTree = ""; }; + 27A92D7D0E349282006E7CF6 /* abcFanio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcFanio.c; sourceTree = ""; }; + 27A92D7E0E349282006E7CF6 /* abcFunc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcFunc.c; sourceTree = ""; }; + 27A92D7F0E349282006E7CF6 /* abcHie.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcHie.c; sourceTree = ""; }; + 27A92D800E349282006E7CF6 /* abcInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = abcInt.h; sourceTree = ""; }; + 27A92D810E349282006E7CF6 /* abcLatch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcLatch.c; sourceTree = ""; }; + 27A92D820E349282006E7CF6 /* abcLib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcLib.c; sourceTree = ""; }; + 27A92D830E349282006E7CF6 /* abcMinBase.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcMinBase.c; sourceTree = ""; }; + 27A92D840E349282006E7CF6 /* abcNames.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcNames.c; sourceTree = ""; }; + 27A92D850E349282006E7CF6 /* abcNetlist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcNetlist.c; sourceTree = ""; }; + 27A92D860E349282006E7CF6 /* abcNtk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcNtk.c; sourceTree = ""; }; + 27A92D870E349282006E7CF6 /* abcObj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcObj.c; sourceTree = ""; }; + 27A92D880E349282006E7CF6 /* abcRefs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcRefs.c; sourceTree = ""; }; + 27A92D890E349282006E7CF6 /* abcShow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcShow.c; sourceTree = ""; }; + 27A92D8A0E349282006E7CF6 /* abcSop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcSop.c; sourceTree = ""; }; + 27A92D8B0E349282006E7CF6 /* abcUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcUtil.c; sourceTree = ""; }; + 27A92D8C0E349282006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92D8E0E349282006E7CF6 /* abc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abc.c; sourceTree = ""; }; + 27A92D8F0E349282006E7CF6 /* abc_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abc_.c; sourceTree = ""; }; + 27A92D900E349282006E7CF6 /* abcAttach.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcAttach.c; sourceTree = ""; }; + 27A92D910E349282006E7CF6 /* abcAuto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcAuto.c; sourceTree = ""; }; + 27A92D920E349282006E7CF6 /* abcBalance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcBalance.c; sourceTree = ""; }; + 27A92D930E349282006E7CF6 /* abcBmc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcBmc.c; sourceTree = ""; }; + 27A92D940E349282006E7CF6 /* abcCas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcCas.c; sourceTree = ""; }; + 27A92D950E349282006E7CF6 /* abcClpBdd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcClpBdd.c; sourceTree = ""; }; + 27A92D960E349282006E7CF6 /* abcClpSop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcClpSop.c; sourceTree = ""; }; + 27A92D970E349282006E7CF6 /* abcCut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcCut.c; sourceTree = ""; }; + 27A92D980E349282006E7CF6 /* abcDar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcDar.c; sourceTree = ""; }; + 27A92D990E349282006E7CF6 /* abcDebug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcDebug.c; sourceTree = ""; }; + 27A92D9A0E349282006E7CF6 /* abcDress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcDress.c; sourceTree = ""; }; + 27A92D9B0E349282006E7CF6 /* abcDsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcDsd.c; sourceTree = ""; }; + 27A92D9C0E349282006E7CF6 /* abcEspresso.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcEspresso.c; sourceTree = ""; }; + 27A92D9D0E349282006E7CF6 /* abcExtract.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcExtract.c; sourceTree = ""; }; + 27A92D9E0E349282006E7CF6 /* abcFpga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcFpga.c; sourceTree = ""; }; + 27A92D9F0E349282006E7CF6 /* abcFpgaFast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcFpgaFast.c; sourceTree = ""; }; + 27A92DA00E349282006E7CF6 /* abcFraig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcFraig.c; sourceTree = ""; }; + 27A92DA10E349282006E7CF6 /* abcFxu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcFxu.c; sourceTree = ""; }; + 27A92DA20E349282006E7CF6 /* abcGen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcGen.c; sourceTree = ""; }; + 27A92DA30E349282006E7CF6 /* abcHaig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcHaig.c; sourceTree = ""; }; + 27A92DA40E349282006E7CF6 /* abcIf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcIf.c; sourceTree = ""; }; + 27A92DA50E349282006E7CF6 /* abcIvy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcIvy.c; sourceTree = ""; }; + 27A92DA60E349282006E7CF6 /* abcLut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcLut.c; sourceTree = ""; }; + 27A92DA70E349282006E7CF6 /* abcMap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcMap.c; sourceTree = ""; }; + 27A92DA80E349282006E7CF6 /* abcMeasure.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcMeasure.c; sourceTree = ""; }; + 27A92DA90E349282006E7CF6 /* abcMini.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcMini.c; sourceTree = ""; }; + 27A92DAA0E349282006E7CF6 /* abcMiter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcMiter.c; sourceTree = ""; }; + 27A92DAB0E349282006E7CF6 /* abcMulti.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcMulti.c; sourceTree = ""; }; + 27A92DAC0E349282006E7CF6 /* abcMv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcMv.c; sourceTree = ""; }; + 27A92DAD0E349282006E7CF6 /* abcNtbdd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcNtbdd.c; sourceTree = ""; }; + 27A92DAE0E349282006E7CF6 /* abcOdc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcOdc.c; sourceTree = ""; }; + 27A92DAF0E349282006E7CF6 /* abcOrder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcOrder.c; sourceTree = ""; }; + 27A92DB00E349282006E7CF6 /* abcPart.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcPart.c; sourceTree = ""; }; + 27A92DB10E349282006E7CF6 /* abcPlace.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcPlace.c; sourceTree = ""; }; + 27A92DB20E349282006E7CF6 /* abcPrint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcPrint.c; sourceTree = ""; }; + 27A92DB30E349282006E7CF6 /* abcProve.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcProve.c; sourceTree = ""; }; + 27A92DB40E349282006E7CF6 /* abcQbf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcQbf.c; sourceTree = ""; }; + 27A92DB50E349282006E7CF6 /* abcQuant.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcQuant.c; sourceTree = ""; }; + 27A92DB60E349282006E7CF6 /* abcRec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcRec.c; sourceTree = ""; }; + 27A92DB70E349282006E7CF6 /* abcReconv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcReconv.c; sourceTree = ""; }; + 27A92DB80E349282006E7CF6 /* abcRefactor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcRefactor.c; sourceTree = ""; }; + 27A92DB90E349282006E7CF6 /* abcRenode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcRenode.c; sourceTree = ""; }; + 27A92DBA0E349282006E7CF6 /* abcReorder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcReorder.c; sourceTree = ""; }; + 27A92DBB0E349282006E7CF6 /* abcRestruct.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcRestruct.c; sourceTree = ""; }; + 27A92DBC0E349282006E7CF6 /* abcResub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcResub.c; sourceTree = ""; }; + 27A92DBD0E349282006E7CF6 /* abcRewrite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcRewrite.c; sourceTree = ""; }; + 27A92DBE0E349282006E7CF6 /* abcRr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcRr.c; sourceTree = ""; }; + 27A92DBF0E349282006E7CF6 /* abcSat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcSat.c; sourceTree = ""; }; + 27A92DC00E349282006E7CF6 /* abcStrash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcStrash.c; sourceTree = ""; }; + 27A92DC10E349282006E7CF6 /* abcSweep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcSweep.c; sourceTree = ""; }; + 27A92DC20E349282006E7CF6 /* abcSymm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcSymm.c; sourceTree = ""; }; + 27A92DC30E349282006E7CF6 /* abcTiming.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcTiming.c; sourceTree = ""; }; + 27A92DC40E349282006E7CF6 /* abcUnate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcUnate.c; sourceTree = ""; }; + 27A92DC50E349282006E7CF6 /* abcUnreach.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcUnreach.c; sourceTree = ""; }; + 27A92DC60E349282006E7CF6 /* abcVerify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcVerify.c; sourceTree = ""; }; + 27A92DC70E349282006E7CF6 /* abcXsim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = abcXsim.c; sourceTree = ""; }; + 27A92DC80E349282006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92DCA0E349282006E7CF6 /* cmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmd.c; sourceTree = ""; }; + 27A92DCB0E349282006E7CF6 /* cmd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cmd.h; sourceTree = ""; }; + 27A92DCC0E349282006E7CF6 /* cmdAlias.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmdAlias.c; sourceTree = ""; }; + 27A92DCD0E349282006E7CF6 /* cmdApi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmdApi.c; sourceTree = ""; }; + 27A92DCE0E349282006E7CF6 /* cmdFlag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmdFlag.c; sourceTree = ""; }; + 27A92DCF0E349282006E7CF6 /* cmdHist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmdHist.c; sourceTree = ""; }; + 27A92DD00E349282006E7CF6 /* cmdInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cmdInt.h; sourceTree = ""; }; + 27A92DD10E349282006E7CF6 /* cmdUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cmdUtils.c; sourceTree = ""; }; + 27A92DD20E349282006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92DD40E349282006E7CF6 /* io.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = io.c; sourceTree = ""; }; + 27A92DD50E349282006E7CF6 /* io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = io.h; sourceTree = ""; }; + 27A92DD60E349282006E7CF6 /* io_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = io_.c; sourceTree = ""; }; + 27A92DD70E349282006E7CF6 /* ioInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ioInt.h; sourceTree = ""; }; + 27A92DD80E349282006E7CF6 /* ioReadAiger.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioReadAiger.c; sourceTree = ""; }; + 27A92DD90E349282006E7CF6 /* ioReadBaf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioReadBaf.c; sourceTree = ""; }; + 27A92DDA0E349282006E7CF6 /* ioReadBench.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioReadBench.c; sourceTree = ""; }; + 27A92DDB0E349282006E7CF6 /* ioReadBlif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioReadBlif.c; sourceTree = ""; }; + 27A92DDC0E349282006E7CF6 /* ioReadBlifAig.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioReadBlifAig.c; sourceTree = ""; }; + 27A92DDD0E349282006E7CF6 /* ioReadBlifMv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioReadBlifMv.c; sourceTree = ""; }; + 27A92DDE0E349282006E7CF6 /* ioReadDsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioReadDsd.c; sourceTree = ""; }; + 27A92DDF0E349282006E7CF6 /* ioReadEdif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioReadEdif.c; sourceTree = ""; }; + 27A92DE00E349282006E7CF6 /* ioReadEqn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioReadEqn.c; sourceTree = ""; }; + 27A92DE10E349282006E7CF6 /* ioReadPla.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioReadPla.c; sourceTree = ""; }; + 27A92DE20E349282006E7CF6 /* ioReadVerilog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioReadVerilog.c; sourceTree = ""; }; + 27A92DE30E349282006E7CF6 /* ioUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioUtil.c; sourceTree = ""; }; + 27A92DE40E349282006E7CF6 /* ioWriteAiger.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWriteAiger.c; sourceTree = ""; }; + 27A92DE50E349282006E7CF6 /* ioWriteBaf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWriteBaf.c; sourceTree = ""; }; + 27A92DE60E349282006E7CF6 /* ioWriteBench.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWriteBench.c; sourceTree = ""; }; + 27A92DE70E349282006E7CF6 /* ioWriteBlif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWriteBlif.c; sourceTree = ""; }; + 27A92DE80E349282006E7CF6 /* ioWriteBlifMv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWriteBlifMv.c; sourceTree = ""; }; + 27A92DE90E349282006E7CF6 /* ioWriteCnf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWriteCnf.c; sourceTree = ""; }; + 27A92DEA0E349282006E7CF6 /* ioWriteDot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWriteDot.c; sourceTree = ""; }; + 27A92DEB0E349282006E7CF6 /* ioWriteEqn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWriteEqn.c; sourceTree = ""; }; + 27A92DEC0E349282006E7CF6 /* ioWriteGml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWriteGml.c; sourceTree = ""; }; + 27A92DED0E349282006E7CF6 /* ioWriteList.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWriteList.c; sourceTree = ""; }; + 27A92DEE0E349282006E7CF6 /* ioWritePla.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWritePla.c; sourceTree = ""; }; + 27A92DEF0E349282006E7CF6 /* ioWriteVerilog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioWriteVerilog.c; sourceTree = ""; }; + 27A92DF00E349282006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92DF20E349282006E7CF6 /* libSupport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = libSupport.c; sourceTree = ""; }; + 27A92DF30E349282006E7CF6 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 27A92DF40E349282006E7CF6 /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = main.h; sourceTree = ""; }; + 27A92DF50E349282006E7CF6 /* mainFrame.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mainFrame.c; sourceTree = ""; }; + 27A92DF60E349282006E7CF6 /* mainInit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mainInit.c; sourceTree = ""; }; + 27A92DF70E349282006E7CF6 /* mainInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mainInt.h; sourceTree = ""; }; + 27A92DF80E349282006E7CF6 /* mainUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mainUtils.c; sourceTree = ""; }; + 27A92DF90E349282006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92DFA0E349282006E7CF6 /* temp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = temp.c; sourceTree = ""; }; + 27A92DFC0E349282006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92DFD0E349282006E7CF6 /* ver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ver.h; sourceTree = ""; }; + 27A92DFE0E349282006E7CF6 /* ver_.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ver_.c; sourceTree = ""; }; + 27A92DFF0E349282006E7CF6 /* verCore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = verCore.c; sourceTree = ""; }; + 27A92E000E349282006E7CF6 /* verFormula.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = verFormula.c; sourceTree = ""; }; + 27A92E010E349282006E7CF6 /* verParse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = verParse.c; sourceTree = ""; }; + 27A92E020E349282006E7CF6 /* verStream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = verStream.c; sourceTree = ""; }; + 27A92E030E349282006E7CF6 /* verWords.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = verWords.c; sourceTree = ""; }; + 27A92E060E349282006E7CF6 /* cofactor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cofactor.c; sourceTree = ""; }; + 27A92E070E349282006E7CF6 /* cols.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cols.c; sourceTree = ""; }; + 27A92E080E349282006E7CF6 /* compl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = compl.c; sourceTree = ""; }; + 27A92E090E349282006E7CF6 /* contain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = contain.c; sourceTree = ""; }; + 27A92E0A0E349282006E7CF6 /* cubehack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cubehack.c; sourceTree = ""; }; + 27A92E0B0E349282006E7CF6 /* cubestr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cubestr.c; sourceTree = ""; }; + 27A92E0C0E349282006E7CF6 /* cvrin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cvrin.c; sourceTree = ""; }; + 27A92E0D0E349282006E7CF6 /* cvrm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cvrm.c; sourceTree = ""; }; + 27A92E0E0E349282006E7CF6 /* cvrmisc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cvrmisc.c; sourceTree = ""; }; + 27A92E0F0E349282006E7CF6 /* cvrout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cvrout.c; sourceTree = ""; }; + 27A92E100E349282006E7CF6 /* dominate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dominate.c; sourceTree = ""; }; + 27A92E110E349282006E7CF6 /* equiv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = equiv.c; sourceTree = ""; }; + 27A92E120E349282006E7CF6 /* espresso.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = espresso.c; sourceTree = ""; }; + 27A92E130E349282006E7CF6 /* espresso.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = espresso.h; sourceTree = ""; }; + 27A92E140E349282006E7CF6 /* essen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = essen.c; sourceTree = ""; }; + 27A92E150E349282006E7CF6 /* exact.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exact.c; sourceTree = ""; }; + 27A92E160E349282006E7CF6 /* expand.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = expand.c; sourceTree = ""; }; + 27A92E170E349282006E7CF6 /* gasp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gasp.c; sourceTree = ""; }; + 27A92E180E349282006E7CF6 /* gimpel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gimpel.c; sourceTree = ""; }; + 27A92E190E349282006E7CF6 /* globals.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = globals.c; sourceTree = ""; }; + 27A92E1A0E349282006E7CF6 /* hack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hack.c; sourceTree = ""; }; + 27A92E1B0E349282006E7CF6 /* indep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = indep.c; sourceTree = ""; }; + 27A92E1C0E349282006E7CF6 /* irred.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = irred.c; sourceTree = ""; }; + 27A92E1D0E349282006E7CF6 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 27A92E1E0E349282006E7CF6 /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = main.h; sourceTree = ""; }; + 27A92E1F0E349282006E7CF6 /* map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = map.c; sourceTree = ""; }; + 27A92E200E349282006E7CF6 /* matrix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = matrix.c; sourceTree = ""; }; + 27A92E210E349282006E7CF6 /* mincov.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mincov.c; sourceTree = ""; }; + 27A92E220E349282006E7CF6 /* mincov.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mincov.h; sourceTree = ""; }; + 27A92E230E349282006E7CF6 /* mincov_int.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mincov_int.h; sourceTree = ""; }; + 27A92E240E349282006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92E250E349282006E7CF6 /* opo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = opo.c; sourceTree = ""; }; + 27A92E260E349282006E7CF6 /* pair.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pair.c; sourceTree = ""; }; + 27A92E270E349282006E7CF6 /* part.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = part.c; sourceTree = ""; }; + 27A92E280E349282006E7CF6 /* primes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = primes.c; sourceTree = ""; }; + 27A92E290E349282006E7CF6 /* reduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reduce.c; sourceTree = ""; }; + 27A92E2A0E349282006E7CF6 /* rows.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rows.c; sourceTree = ""; }; + 27A92E2B0E349282006E7CF6 /* set.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = set.c; sourceTree = ""; }; + 27A92E2C0E349282006E7CF6 /* setc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = setc.c; sourceTree = ""; }; + 27A92E2D0E349282006E7CF6 /* sharp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sharp.c; sourceTree = ""; }; + 27A92E2E0E349282006E7CF6 /* sminterf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sminterf.c; sourceTree = ""; }; + 27A92E2F0E349282006E7CF6 /* solution.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = solution.c; sourceTree = ""; }; + 27A92E300E349282006E7CF6 /* sparse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sparse.c; sourceTree = ""; }; + 27A92E310E349282006E7CF6 /* sparse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sparse.h; sourceTree = ""; }; + 27A92E320E349282006E7CF6 /* sparse_int.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sparse_int.h; sourceTree = ""; }; + 27A92E330E349282006E7CF6 /* unate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = unate.c; sourceTree = ""; }; + 27A92E340E349282006E7CF6 /* util_old.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util_old.h; sourceTree = ""; }; + 27A92E350E349282006E7CF6 /* verify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = verify.c; sourceTree = ""; }; + 27A92E370E349282006E7CF6 /* extra.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = extra.h; sourceTree = ""; }; + 27A92E380E349282006E7CF6 /* extraBddAuto.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraBddAuto.c; sourceTree = ""; }; + 27A92E390E349282006E7CF6 /* extraBddCas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraBddCas.c; sourceTree = ""; }; + 27A92E3A0E349282006E7CF6 /* extraBddKmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraBddKmap.c; sourceTree = ""; }; + 27A92E3B0E349282006E7CF6 /* extraBddMisc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraBddMisc.c; sourceTree = ""; }; + 27A92E3C0E349282006E7CF6 /* extraBddSymm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraBddSymm.c; sourceTree = ""; }; + 27A92E3D0E349282006E7CF6 /* extraBddUnate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraBddUnate.c; sourceTree = ""; }; + 27A92E3E0E349282006E7CF6 /* extraUtilBitMatrix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraUtilBitMatrix.c; sourceTree = ""; }; + 27A92E3F0E349282006E7CF6 /* extraUtilCanon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraUtilCanon.c; sourceTree = ""; }; + 27A92E400E349282006E7CF6 /* extraUtilFile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraUtilFile.c; sourceTree = ""; }; + 27A92E410E349282006E7CF6 /* extraUtilMemory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraUtilMemory.c; sourceTree = ""; }; + 27A92E420E349282006E7CF6 /* extraUtilMisc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraUtilMisc.c; sourceTree = ""; }; + 27A92E430E349282006E7CF6 /* extraUtilProgress.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraUtilProgress.c; sourceTree = ""; }; + 27A92E440E349282006E7CF6 /* extraUtilReader.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraUtilReader.c; sourceTree = ""; }; + 27A92E450E349282006E7CF6 /* extraUtilTruth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraUtilTruth.c; sourceTree = ""; }; + 27A92E460E349282006E7CF6 /* extraUtilUtil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = extraUtilUtil.c; sourceTree = ""; }; + 27A92E470E349282006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92E490E349282006E7CF6 /* hash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hash.h; sourceTree = ""; }; + 27A92E4A0E349282006E7CF6 /* hashFlt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hashFlt.h; sourceTree = ""; }; + 27A92E4B0E349282006E7CF6 /* hashInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hashInt.h; sourceTree = ""; }; + 27A92E4C0E349282006E7CF6 /* hashPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hashPtr.h; sourceTree = ""; }; + 27A92E4D0E349282006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92E4F0E349282006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92E500E349282006E7CF6 /* mvc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvc.c; sourceTree = ""; }; + 27A92E510E349282006E7CF6 /* mvc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mvc.h; sourceTree = ""; }; + 27A92E520E349282006E7CF6 /* mvcApi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcApi.c; sourceTree = ""; }; + 27A92E530E349282006E7CF6 /* mvcCompare.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcCompare.c; sourceTree = ""; }; + 27A92E540E349282006E7CF6 /* mvcContain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcContain.c; sourceTree = ""; }; + 27A92E550E349282006E7CF6 /* mvcCover.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcCover.c; sourceTree = ""; }; + 27A92E560E349282006E7CF6 /* mvcCube.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcCube.c; sourceTree = ""; }; + 27A92E570E349282006E7CF6 /* mvcDivide.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcDivide.c; sourceTree = ""; }; + 27A92E580E349282006E7CF6 /* mvcDivisor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcDivisor.c; sourceTree = ""; }; + 27A92E590E349282006E7CF6 /* mvcList.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcList.c; sourceTree = ""; }; + 27A92E5A0E349282006E7CF6 /* mvcLits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcLits.c; sourceTree = ""; }; + 27A92E5B0E349282006E7CF6 /* mvcMan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcMan.c; sourceTree = ""; }; + 27A92E5C0E349282006E7CF6 /* mvcOpAlg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcOpAlg.c; sourceTree = ""; }; + 27A92E5D0E349283006E7CF6 /* mvcOpBool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcOpBool.c; sourceTree = ""; }; + 27A92E5E0E349283006E7CF6 /* mvcPrint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcPrint.c; sourceTree = ""; }; + 27A92E5F0E349283006E7CF6 /* mvcSort.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcSort.c; sourceTree = ""; }; + 27A92E600E349283006E7CF6 /* mvcUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mvcUtils.c; sourceTree = ""; }; + 27A92E620E349283006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92E630E349283006E7CF6 /* nm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nm.h; sourceTree = ""; }; + 27A92E640E349283006E7CF6 /* nmApi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmApi.c; sourceTree = ""; }; + 27A92E650E349283006E7CF6 /* nmInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nmInt.h; sourceTree = ""; }; + 27A92E660E349283006E7CF6 /* nmTable.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nmTable.c; sourceTree = ""; }; + 27A92E680E349283006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92E690E349283006E7CF6 /* st.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = st.c; sourceTree = ""; }; + 27A92E6A0E349283006E7CF6 /* st.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = st.h; sourceTree = ""; }; + 27A92E6B0E349283006E7CF6 /* stmm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stmm.c; sourceTree = ""; }; + 27A92E6C0E349283006E7CF6 /* stmm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stmm.h; sourceTree = ""; }; + 27A92E6E0E349283006E7CF6 /* leaks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = leaks.h; sourceTree = ""; }; + 27A92E6F0E349283006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92E700E349283006E7CF6 /* stdlib_hack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stdlib_hack.h; sourceTree = ""; }; + 27A92E710E349283006E7CF6 /* util_hack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util_hack.h; sourceTree = ""; }; + 27A92E730E349283006E7CF6 /* module.make */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = module.make; sourceTree = ""; }; + 27A92E740E349283006E7CF6 /* vec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vec.h; sourceTree = ""; }; + 27A92E750E349283006E7CF6 /* vecAtt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vecAtt.h; sourceTree = ""; }; + 27A92E760E349283006E7CF6 /* vecFlt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vecFlt.h; sourceTree = ""; }; + 27A92E770E349283006E7CF6 /* vecInt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vecInt.h; sourceTree = ""; }; + 27A92E780E349283006E7CF6 /* vecPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vecPtr.h; sourceTree = ""; }; + 27A92E790E349283006E7CF6 /* vecStr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vecStr.h; sourceTree = ""; }; + 27A92E7A0E349283006E7CF6 /* vecVec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vecVec.h; sourceTree = ""; }; + 8DD76FB20486AB0100D96B5E /* abc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = abc; sourceTree = BUILT_PRODUCTS_DIR; }; + C6A0FF2C0290799A04C91782 /* abc.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = abc.1; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DD76FAD0486AB0100D96B5E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 274040F00E38BEDA00DC6F18 /* libreadline.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 08FB7794FE84155DC02AAC07 /* abc */ = { + isa = PBXGroup; + children = ( + 274040F20E38BEE600DC6F18 /* Libraries */, + 08FB7795FE84155DC02AAC07 /* Source */, + C6A0FF2B0290797F04C91782 /* Documentation */, + 1AB674ADFE9D54B511CA2CBB /* Products */, + ); + name = abc; + sourceTree = ""; + }; + 08FB7795FE84155DC02AAC07 /* Source */ = { + isa = PBXGroup; + children = ( + 27A92B6C0E349280006E7CF6 /* opt */, + 27A92BD50E349280006E7CF6 /* generic.h */, + 27A92BD60E349280006E7CF6 /* sat */, + 27A92C0E0E349280006E7CF6 /* bdd */, + 27A92C7F0E349281006E7CF6 /* generic.c */, + 27A92C800E349281006E7CF6 /* aig */, + 27A92D2B0E349281006E7CF6 /* map */, + 27A92D750E349282006E7CF6 /* base */, + 27A92E040E349282006E7CF6 /* misc */, + ); + name = Source; + sourceTree = ""; + }; + 1AB674ADFE9D54B511CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 8DD76FB20486AB0100D96B5E /* abc */, + ); + name = Products; + sourceTree = ""; + }; + 274040F20E38BEE600DC6F18 /* Libraries */ = { + isa = PBXGroup; + children = ( + 274040EF0E38BED900DC6F18 /* libreadline.dylib */, + ); + name = Libraries; + sourceTree = ""; + }; + 27A92B6C0E349280006E7CF6 /* opt */ = { + isa = PBXGroup; + children = ( + 27A92B6D0E349280006E7CF6 /* cut */, + 27A92B7D0E349280006E7CF6 /* dec */, + 27A92B850E349280006E7CF6 /* fxu */, + 27A92B950E349280006E7CF6 /* lpk */, + 27A92BA50E349280006E7CF6 /* res */, + 27A92BB20E349280006E7CF6 /* ret */, + 27A92BBD0E349280006E7CF6 /* rwr */, + 27A92BC80E349280006E7CF6 /* sim */, + ); + path = opt; + sourceTree = ""; + }; + 27A92B6D0E349280006E7CF6 /* cut */ = { + isa = PBXGroup; + children = ( + 27A92B6E0E349280006E7CF6 /* abcCut.c */, + 27A92B6F0E349280006E7CF6 /* cut.h */, + 27A92B700E349280006E7CF6 /* cutApi.c */, + 27A92B710E349280006E7CF6 /* cutCut.c */, + 27A92B720E349280006E7CF6 /* cutExpand.c */, + 27A92B730E349280006E7CF6 /* cutInt.h */, + 27A92B740E349280006E7CF6 /* cutList.h */, + 27A92B750E349280006E7CF6 /* cutMan.c */, + 27A92B760E349280006E7CF6 /* cutMerge.c */, + 27A92B770E349280006E7CF6 /* cutNode.c */, + 27A92B780E349280006E7CF6 /* cutOracle.c */, + 27A92B790E349280006E7CF6 /* cutPre22.c */, + 27A92B7A0E349280006E7CF6 /* cutSeq.c */, + 27A92B7B0E349280006E7CF6 /* cutTruth.c */, + 27A92B7C0E349280006E7CF6 /* module.make */, + ); + path = cut; + sourceTree = ""; + }; + 27A92B7D0E349280006E7CF6 /* dec */ = { + isa = PBXGroup; + children = ( + 27A92B7E0E349280006E7CF6 /* dec.h */, + 27A92B7F0E349280006E7CF6 /* decAbc.c */, + 27A92B800E349280006E7CF6 /* decFactor.c */, + 27A92B810E349280006E7CF6 /* decMan.c */, + 27A92B820E349280006E7CF6 /* decPrint.c */, + 27A92B830E349280006E7CF6 /* decUtil.c */, + 27A92B840E349280006E7CF6 /* module.make */, + ); + path = dec; + sourceTree = ""; + }; + 27A92B850E349280006E7CF6 /* fxu */ = { + isa = PBXGroup; + children = ( + 27A92B860E349280006E7CF6 /* fxu.c */, + 27A92B870E349280006E7CF6 /* fxu.h */, + 27A92B880E349280006E7CF6 /* fxuCreate.c */, + 27A92B890E349280006E7CF6 /* fxuHeapD.c */, + 27A92B8A0E349280006E7CF6 /* fxuHeapS.c */, + 27A92B8B0E349280006E7CF6 /* fxuInt.h */, + 27A92B8C0E349280006E7CF6 /* fxuList.c */, + 27A92B8D0E349280006E7CF6 /* fxuMatrix.c */, + 27A92B8E0E349280006E7CF6 /* fxuPair.c */, + 27A92B8F0E349280006E7CF6 /* fxuPrint.c */, + 27A92B900E349280006E7CF6 /* fxuReduce.c */, + 27A92B910E349280006E7CF6 /* fxuSelect.c */, + 27A92B920E349280006E7CF6 /* fxuSingle.c */, + 27A92B930E349280006E7CF6 /* fxuUpdate.c */, + 27A92B940E349280006E7CF6 /* module.make */, + ); + path = fxu; + sourceTree = ""; + }; + 27A92B950E349280006E7CF6 /* lpk */ = { + isa = PBXGroup; + children = ( + 27A92B960E349280006E7CF6 /* lpk.h */, + 27A92B970E349280006E7CF6 /* lpk_.c */, + 27A92B980E349280006E7CF6 /* lpkAbcDec.c */, + 27A92B990E349280006E7CF6 /* lpkAbcDsd.c */, + 27A92B9A0E349280006E7CF6 /* lpkAbcMux.c */, + 27A92B9B0E349280006E7CF6 /* lpkAbcUtil.c */, + 27A92B9C0E349280006E7CF6 /* lpkCore.c */, + 27A92B9D0E349280006E7CF6 /* lpkCut.c */, + 27A92B9E0E349280006E7CF6 /* lpkInt.h */, + 27A92B9F0E349280006E7CF6 /* lpkMan.c */, + 27A92BA00E349280006E7CF6 /* lpkMap.c */, + 27A92BA10E349280006E7CF6 /* lpkMulti.c */, + 27A92BA20E349280006E7CF6 /* lpkMux.c */, + 27A92BA30E349280006E7CF6 /* lpkSets.c */, + 27A92BA40E349280006E7CF6 /* module.make */, + ); + path = lpk; + sourceTree = ""; + }; + 27A92BA50E349280006E7CF6 /* res */ = { + isa = PBXGroup; + children = ( + 27A92BA60E349280006E7CF6 /* module.make */, + 27A92BA70E349280006E7CF6 /* res.h */, + 27A92BA80E349280006E7CF6 /* res_.c */, + 27A92BA90E349280006E7CF6 /* resCore.c */, + 27A92BAA0E349280006E7CF6 /* resDivs.c */, + 27A92BAB0E349280006E7CF6 /* resFilter.c */, + 27A92BAC0E349280006E7CF6 /* resInt.h */, + 27A92BAD0E349280006E7CF6 /* resSat.c */, + 27A92BAE0E349280006E7CF6 /* resSim.c */, + 27A92BAF0E349280006E7CF6 /* resSim_old.c */, + 27A92BB00E349280006E7CF6 /* resStrash.c */, + 27A92BB10E349280006E7CF6 /* resWin.c */, + ); + path = res; + sourceTree = ""; + }; + 27A92BB20E349280006E7CF6 /* ret */ = { + isa = PBXGroup; + children = ( + 27A92BB30E349280006E7CF6 /* module.make */, + 27A92BB40E349280006E7CF6 /* ret_.c */, + 27A92BB50E349280006E7CF6 /* retArea.c */, + 27A92BB60E349280006E7CF6 /* retCore.c */, + 27A92BB70E349280006E7CF6 /* retDelay.c */, + 27A92BB80E349280006E7CF6 /* retFlow.c */, + 27A92BB90E349280006E7CF6 /* retIncrem.c */, + 27A92BBA0E349280006E7CF6 /* retInit.c */, + 27A92BBB0E349280006E7CF6 /* retInt.h */, + 27A92BBC0E349280006E7CF6 /* retLvalue.c */, + ); + path = ret; + sourceTree = ""; + }; + 27A92BBD0E349280006E7CF6 /* rwr */ = { + isa = PBXGroup; + children = ( + 27A92BBE0E349280006E7CF6 /* module.make */, + 27A92BBF0E349280006E7CF6 /* rwr.h */, + 27A92BC00E349280006E7CF6 /* rwrDec.c */, + 27A92BC10E349280006E7CF6 /* rwrEva.c */, + 27A92BC20E349280006E7CF6 /* rwrExp.c */, + 27A92BC30E349280006E7CF6 /* rwrLib.c */, + 27A92BC40E349280006E7CF6 /* rwrMan.c */, + 27A92BC50E349280006E7CF6 /* rwrPrint.c */, + 27A92BC60E349280006E7CF6 /* rwrTemp.c */, + 27A92BC70E349280006E7CF6 /* rwrUtil.c */, + ); + path = rwr; + sourceTree = ""; + }; + 27A92BC80E349280006E7CF6 /* sim */ = { + isa = PBXGroup; + children = ( + 27A92BC90E349280006E7CF6 /* module.make */, + 27A92BCA0E349280006E7CF6 /* sim.h */, + 27A92BCB0E349280006E7CF6 /* simMan.c */, + 27A92BCC0E349280006E7CF6 /* simSat.c */, + 27A92BCD0E349280006E7CF6 /* simSeq.c */, + 27A92BCE0E349280006E7CF6 /* simSupp.c */, + 27A92BCF0E349280006E7CF6 /* simSwitch.c */, + 27A92BD00E349280006E7CF6 /* simSym.c */, + 27A92BD10E349280006E7CF6 /* simSymSat.c */, + 27A92BD20E349280006E7CF6 /* simSymSim.c */, + 27A92BD30E349280006E7CF6 /* simSymStr.c */, + 27A92BD40E349280006E7CF6 /* simUtils.c */, + ); + path = sim; + sourceTree = ""; + }; + 27A92BD60E349280006E7CF6 /* sat */ = { + isa = PBXGroup; + children = ( + 27A92BD70E349280006E7CF6 /* bsat */, + 27A92BE30E349280006E7CF6 /* csat */, + 27A92BE70E349280006E7CF6 /* fraig */, + 27A92BF80E349280006E7CF6 /* msat */, + 27A92C0A0E349280006E7CF6 /* proof */, + ); + path = sat; + sourceTree = ""; + }; + 27A92BD70E349280006E7CF6 /* bsat */ = { + isa = PBXGroup; + children = ( + 27A92BD80E349280006E7CF6 /* module.make */, + 27A92BD90E349280006E7CF6 /* satInter.c */, + 27A92BDA0E349280006E7CF6 /* satMem.c */, + 27A92BDB0E349280006E7CF6 /* satMem.h */, + 27A92BDC0E349280006E7CF6 /* satSolver.c */, + 27A92BDD0E349280006E7CF6 /* satSolver.h */, + 27A92BDE0E349280006E7CF6 /* satStore.c */, + 27A92BDF0E349280006E7CF6 /* satStore.h */, + 27A92BE00E349280006E7CF6 /* satTrace.c */, + 27A92BE10E349280006E7CF6 /* satUtil.c */, + 27A92BE20E349280006E7CF6 /* satVec.h */, + ); + path = bsat; + sourceTree = ""; + }; + 27A92BE30E349280006E7CF6 /* csat */ = { + isa = PBXGroup; + children = ( + 27A92BE40E349280006E7CF6 /* csat_apis.c */, + 27A92BE50E349280006E7CF6 /* csat_apis.h */, + 27A92BE60E349280006E7CF6 /* module.make */, + ); + path = csat; + sourceTree = ""; + }; + 27A92BE70E349280006E7CF6 /* fraig */ = { + isa = PBXGroup; + children = ( + 27A92BE80E349280006E7CF6 /* fraig.h */, + 27A92BE90E349280006E7CF6 /* fraigApi.c */, + 27A92BEA0E349280006E7CF6 /* fraigCanon.c */, + 27A92BEB0E349280006E7CF6 /* fraigChoice.c */, + 27A92BEC0E349280006E7CF6 /* fraigFanout.c */, + 27A92BED0E349280006E7CF6 /* fraigFeed.c */, + 27A92BEE0E349280006E7CF6 /* fraigInt.h */, + 27A92BEF0E349280006E7CF6 /* fraigMan.c */, + 27A92BF00E349280006E7CF6 /* fraigMem.c */, + 27A92BF10E349280006E7CF6 /* fraigNode.c */, + 27A92BF20E349280006E7CF6 /* fraigPrime.c */, + 27A92BF30E349280006E7CF6 /* fraigSat.c */, + 27A92BF40E349280006E7CF6 /* fraigTable.c */, + 27A92BF50E349280006E7CF6 /* fraigUtil.c */, + 27A92BF60E349280006E7CF6 /* fraigVec.c */, + 27A92BF70E349280006E7CF6 /* module.make */, + ); + path = fraig; + sourceTree = ""; + }; + 27A92BF80E349280006E7CF6 /* msat */ = { + isa = PBXGroup; + children = ( + 27A92BF90E349280006E7CF6 /* module.make */, + 27A92BFA0E349280006E7CF6 /* msat.h */, + 27A92BFB0E349280006E7CF6 /* msatActivity.c */, + 27A92BFC0E349280006E7CF6 /* msatClause.c */, + 27A92BFD0E349280006E7CF6 /* msatClauseVec.c */, + 27A92BFE0E349280006E7CF6 /* msatInt.h */, + 27A92BFF0E349280006E7CF6 /* msatMem.c */, + 27A92C000E349280006E7CF6 /* msatOrderH.c */, + 27A92C010E349280006E7CF6 /* msatOrderJ.c */, + 27A92C020E349280006E7CF6 /* msatQueue.c */, + 27A92C030E349280006E7CF6 /* msatRead.c */, + 27A92C040E349280006E7CF6 /* msatSolverApi.c */, + 27A92C050E349280006E7CF6 /* msatSolverCore.c */, + 27A92C060E349280006E7CF6 /* msatSolverIo.c */, + 27A92C070E349280006E7CF6 /* msatSolverSearch.c */, + 27A92C080E349280006E7CF6 /* msatSort.c */, + 27A92C090E349280006E7CF6 /* msatVec.c */, + ); + path = msat; + sourceTree = ""; + }; + 27A92C0A0E349280006E7CF6 /* proof */ = { + isa = PBXGroup; + children = ( + 27A92C0B0E349280006E7CF6 /* pr.c */, + 27A92C0C0E349280006E7CF6 /* pr.h */, + 27A92C0D0E349280006E7CF6 /* stats.txt */, + ); + path = proof; + sourceTree = ""; + }; + 27A92C0E0E349280006E7CF6 /* bdd */ = { + isa = PBXGroup; + children = ( + 27A92C0F0E349280006E7CF6 /* cas */, + 27A92C140E349280006E7CF6 /* cudd */, + 27A92C590E349281006E7CF6 /* dsd */, + 27A92C630E349281006E7CF6 /* epd */, + 27A92C670E349281006E7CF6 /* mtr */, + 27A92C6D0E349281006E7CF6 /* parse */, + 27A92C740E349281006E7CF6 /* reo */, + ); + path = bdd; + sourceTree = ""; + }; + 27A92C0F0E349280006E7CF6 /* cas */ = { + isa = PBXGroup; + children = ( + 27A92C100E349280006E7CF6 /* cas.h */, + 27A92C110E349280006E7CF6 /* casCore.c */, + 27A92C120E349280006E7CF6 /* casDec.c */, + 27A92C130E349280006E7CF6 /* module.make */, + ); + path = cas; + sourceTree = ""; + }; + 27A92C140E349280006E7CF6 /* cudd */ = { + isa = PBXGroup; + children = ( + 27A92C150E349280006E7CF6 /* cuBdd.make */, + 27A92C160E349280006E7CF6 /* cudd.h */, + 27A92C170E349280006E7CF6 /* cudd.make */, + 27A92C180E349280006E7CF6 /* cuddAddAbs.c */, + 27A92C190E349280006E7CF6 /* cuddAddApply.c */, + 27A92C1A0E349280006E7CF6 /* cuddAddFind.c */, + 27A92C1B0E349280006E7CF6 /* cuddAddInv.c */, + 27A92C1C0E349280006E7CF6 /* cuddAddIte.c */, + 27A92C1D0E349280006E7CF6 /* cuddAddNeg.c */, + 27A92C1E0E349280006E7CF6 /* cuddAddWalsh.c */, + 27A92C1F0E349280006E7CF6 /* cuddAndAbs.c */, + 27A92C200E349280006E7CF6 /* cuddAnneal.c */, + 27A92C210E349280006E7CF6 /* cuddApa.c */, + 27A92C220E349280006E7CF6 /* cuddAPI.c */, + 27A92C230E349280006E7CF6 /* cuddApprox.c */, + 27A92C240E349280006E7CF6 /* cuddBddAbs.c */, + 27A92C250E349280006E7CF6 /* cuddBddCorr.c */, + 27A92C260E349280006E7CF6 /* cuddBddIte.c */, + 27A92C270E349280006E7CF6 /* cuddBridge.c */, + 27A92C280E349280006E7CF6 /* cuddCache.c */, + 27A92C290E349280006E7CF6 /* cuddCheck.c */, + 27A92C2A0E349280006E7CF6 /* cuddClip.c */, + 27A92C2B0E349280006E7CF6 /* cuddCof.c */, + 27A92C2C0E349280006E7CF6 /* cuddCompose.c */, + 27A92C2D0E349280006E7CF6 /* cuddDecomp.c */, + 27A92C2E0E349280006E7CF6 /* cuddEssent.c */, + 27A92C2F0E349280006E7CF6 /* cuddExact.c */, + 27A92C300E349280006E7CF6 /* cuddExport.c */, + 27A92C310E349280006E7CF6 /* cuddGenCof.c */, + 27A92C320E349280006E7CF6 /* cuddGenetic.c */, + 27A92C330E349280006E7CF6 /* cuddGroup.c */, + 27A92C340E349280006E7CF6 /* cuddHarwell.c */, + 27A92C350E349280006E7CF6 /* cuddInit.c */, + 27A92C360E349280006E7CF6 /* cuddInt.h */, + 27A92C370E349280006E7CF6 /* cuddInteract.c */, + 27A92C380E349280006E7CF6 /* cuddLCache.c */, + 27A92C390E349280006E7CF6 /* cuddLevelQ.c */, + 27A92C3A0E349280006E7CF6 /* cuddLinear.c */, + 27A92C3B0E349280006E7CF6 /* cuddLiteral.c */, + 27A92C3C0E349280006E7CF6 /* cuddMatMult.c */, + 27A92C3D0E349280006E7CF6 /* cuddPriority.c */, + 27A92C3E0E349280006E7CF6 /* cuddRead.c */, + 27A92C3F0E349280006E7CF6 /* cuddRef.c */, + 27A92C400E349280006E7CF6 /* cuddReorder.c */, + 27A92C410E349280006E7CF6 /* cuddSat.c */, + 27A92C420E349280006E7CF6 /* cuddSign.c */, + 27A92C430E349280006E7CF6 /* cuddSolve.c */, + 27A92C440E349280006E7CF6 /* cuddSplit.c */, + 27A92C450E349280006E7CF6 /* cuddSubsetHB.c */, + 27A92C460E349280006E7CF6 /* cuddSubsetSP.c */, + 27A92C470E349280006E7CF6 /* cuddSymmetry.c */, + 27A92C480E349280006E7CF6 /* cuddTable.c */, + 27A92C490E349280006E7CF6 /* cuddUtil.c */, + 27A92C4A0E349280006E7CF6 /* cuddWindow.c */, + 27A92C4B0E349280006E7CF6 /* cuddZddCount.c */, + 27A92C4C0E349280006E7CF6 /* cuddZddFuncs.c */, + 27A92C4D0E349280006E7CF6 /* cuddZddGroup.c */, + 27A92C4E0E349280006E7CF6 /* cuddZddIsop.c */, + 27A92C4F0E349280006E7CF6 /* cuddZddLin.c */, + 27A92C500E349280006E7CF6 /* cuddZddMisc.c */, + 27A92C510E349280006E7CF6 /* cuddZddPort.c */, + 27A92C520E349280006E7CF6 /* cuddZddReord.c */, + 27A92C530E349281006E7CF6 /* cuddZddSetop.c */, + 27A92C540E349281006E7CF6 /* cuddZddSymm.c */, + 27A92C550E349281006E7CF6 /* cuddZddUtil.c */, + 27A92C560E349281006E7CF6 /* module.make */, + 27A92C570E349281006E7CF6 /* r7x8.1.mat */, + 27A92C580E349281006E7CF6 /* testcudd.c */, + ); + path = cudd; + sourceTree = ""; + }; + 27A92C590E349281006E7CF6 /* dsd */ = { + isa = PBXGroup; + children = ( + 27A92C5A0E349281006E7CF6 /* dsd.h */, + 27A92C5B0E349281006E7CF6 /* dsdApi.c */, + 27A92C5C0E349281006E7CF6 /* dsdCheck.c */, + 27A92C5D0E349281006E7CF6 /* dsdInt.h */, + 27A92C5E0E349281006E7CF6 /* dsdLocal.c */, + 27A92C5F0E349281006E7CF6 /* dsdMan.c */, + 27A92C600E349281006E7CF6 /* dsdProc.c */, + 27A92C610E349281006E7CF6 /* dsdTree.c */, + 27A92C620E349281006E7CF6 /* module.make */, + ); + path = dsd; + sourceTree = ""; + }; + 27A92C630E349281006E7CF6 /* epd */ = { + isa = PBXGroup; + children = ( + 27A92C640E349281006E7CF6 /* epd.c */, + 27A92C650E349281006E7CF6 /* epd.h */, + 27A92C660E349281006E7CF6 /* module.make */, + ); + path = epd; + sourceTree = ""; + }; + 27A92C670E349281006E7CF6 /* mtr */ = { + isa = PBXGroup; + children = ( + 27A92C680E349281006E7CF6 /* module.make */, + 27A92C690E349281006E7CF6 /* mtr.h */, + 27A92C6A0E349281006E7CF6 /* mtrBasic.c */, + 27A92C6B0E349281006E7CF6 /* mtrGroup.c */, + 27A92C6C0E349281006E7CF6 /* mtrInt.h */, + ); + path = mtr; + sourceTree = ""; + }; + 27A92C6D0E349281006E7CF6 /* parse */ = { + isa = PBXGroup; + children = ( + 27A92C6E0E349281006E7CF6 /* module.make */, + 27A92C6F0E349281006E7CF6 /* parse.h */, + 27A92C700E349281006E7CF6 /* parseCore.c */, + 27A92C710E349281006E7CF6 /* parseEqn.c */, + 27A92C720E349281006E7CF6 /* parseInt.h */, + 27A92C730E349281006E7CF6 /* parseStack.c */, + ); + path = parse; + sourceTree = ""; + }; + 27A92C740E349281006E7CF6 /* reo */ = { + isa = PBXGroup; + children = ( + 27A92C750E349281006E7CF6 /* module.make */, + 27A92C760E349281006E7CF6 /* reo.h */, + 27A92C770E349281006E7CF6 /* reoApi.c */, + 27A92C780E349281006E7CF6 /* reoCore.c */, + 27A92C790E349281006E7CF6 /* reoProfile.c */, + 27A92C7A0E349281006E7CF6 /* reoSift.c */, + 27A92C7B0E349281006E7CF6 /* reoSwap.c */, + 27A92C7C0E349281006E7CF6 /* reoTest.c */, + 27A92C7D0E349281006E7CF6 /* reoTransfer.c */, + 27A92C7E0E349281006E7CF6 /* reoUnits.c */, + ); + path = reo; + sourceTree = ""; + }; + 27A92C800E349281006E7CF6 /* aig */ = { + isa = PBXGroup; + children = ( + 27A92C810E349281006E7CF6 /* aig */, + 27A92C9B0E349281006E7CF6 /* bar */, + 27A92C9F0E349281006E7CF6 /* bdc */, + 27A92CA70E349281006E7CF6 /* cnf */, + 27A92CB30E349281006E7CF6 /* csw */, + 27A92CBC0E349281006E7CF6 /* dar */, + 27A92CCB0E349281006E7CF6 /* deco */, + 27A92CCE0E349281006E7CF6 /* fra */, + 27A92CDF0E349281006E7CF6 /* hop */, + 27A92CEE0E349281006E7CF6 /* ioa */, + 27A92CF40E349281006E7CF6 /* ivy */, + 27A92D110E349281006E7CF6 /* kit */, + 27A92D210E349281006E7CF6 /* mem */, + 27A92D250E349281006E7CF6 /* rwt */, + ); + path = aig; + sourceTree = ""; + }; + 27A92C810E349281006E7CF6 /* aig */ = { + isa = PBXGroup; + children = ( + 27A92C820E349281006E7CF6 /* aig.h */, + 27A92C830E349281006E7CF6 /* aig_.c */, + 27A92C840E349281006E7CF6 /* aigCheck.c */, + 27A92C850E349281006E7CF6 /* aigDfs.c */, + 27A92C860E349281006E7CF6 /* aigFanout.c */, + 27A92C870E349281006E7CF6 /* aigMan.c */, + 27A92C880E349281006E7CF6 /* aigMem.c */, + 27A92C890E349281006E7CF6 /* aigMffc.c */, + 27A92C8A0E349281006E7CF6 /* aigObj.c */, + 27A92C8B0E349281006E7CF6 /* aigOper.c */, + 27A92C8C0E349281006E7CF6 /* aigOrder.c */, + 27A92C8D0E349281006E7CF6 /* aigPart.c */, + 27A92C8E0E349281006E7CF6 /* aigRepr.c */, + 27A92C8F0E349281006E7CF6 /* aigRet.c */, + 27A92C900E349281006E7CF6 /* aigScl.c */, + 27A92C910E349281006E7CF6 /* aigSeq.c */, + 27A92C920E349281006E7CF6 /* aigShow.c */, + 27A92C930E349281006E7CF6 /* aigTable.c */, + 27A92C940E349281006E7CF6 /* aigTime.c */, + 27A92C950E349281006E7CF6 /* aigTiming.c */, + 27A92C960E349281006E7CF6 /* aigTruth.c */, + 27A92C970E349281006E7CF6 /* aigTsim.c */, + 27A92C980E349281006E7CF6 /* aigUtil.c */, + 27A92C990E349281006E7CF6 /* aigWin.c */, + 27A92C9A0E349281006E7CF6 /* module.make */, + ); + path = aig; + sourceTree = ""; + }; + 27A92C9B0E349281006E7CF6 /* bar */ = { + isa = PBXGroup; + children = ( + 27A92C9C0E349281006E7CF6 /* bar.c */, + 27A92C9D0E349281006E7CF6 /* bar.h */, + 27A92C9E0E349281006E7CF6 /* module.make */, + ); + path = bar; + sourceTree = ""; + }; + 27A92C9F0E349281006E7CF6 /* bdc */ = { + isa = PBXGroup; + children = ( + 27A92CA00E349281006E7CF6 /* bdc.h */, + 27A92CA10E349281006E7CF6 /* bdc_.c */, + 27A92CA20E349281006E7CF6 /* bdcCore.c */, + 27A92CA30E349281006E7CF6 /* bdcDec.c */, + 27A92CA40E349281006E7CF6 /* bdcInt.h */, + 27A92CA50E349281006E7CF6 /* bdcTable.c */, + 27A92CA60E349281006E7CF6 /* module.make */, + ); + path = bdc; + sourceTree = ""; + }; + 27A92CA70E349281006E7CF6 /* cnf */ = { + isa = PBXGroup; + children = ( + 27A92CA80E349281006E7CF6 /* cnf.h */, + 27A92CA90E349281006E7CF6 /* cnf_.c */, + 27A92CAA0E349281006E7CF6 /* cnfCore.c */, + 27A92CAB0E349281006E7CF6 /* cnfCut.c */, + 27A92CAC0E349281006E7CF6 /* cnfData.c */, + 27A92CAD0E349281006E7CF6 /* cnfMan.c */, + 27A92CAE0E349281006E7CF6 /* cnfMap.c */, + 27A92CAF0E349281006E7CF6 /* cnfPost.c */, + 27A92CB00E349281006E7CF6 /* cnfUtil.c */, + 27A92CB10E349281006E7CF6 /* cnfWrite.c */, + 27A92CB20E349281006E7CF6 /* module.make */, + ); + path = cnf; + sourceTree = ""; + }; + 27A92CB30E349281006E7CF6 /* csw */ = { + isa = PBXGroup; + children = ( + 27A92CB40E349281006E7CF6 /* csw.h */, + 27A92CB50E349281006E7CF6 /* csw_.c */, + 27A92CB60E349281006E7CF6 /* cswCore.c */, + 27A92CB70E349281006E7CF6 /* cswCut.c */, + 27A92CB80E349281006E7CF6 /* cswInt.h */, + 27A92CB90E349281006E7CF6 /* cswMan.c */, + 27A92CBA0E349281006E7CF6 /* cswTable.c */, + 27A92CBB0E349281006E7CF6 /* module.make */, + ); + path = csw; + sourceTree = ""; + }; + 27A92CBC0E349281006E7CF6 /* dar */ = { + isa = PBXGroup; + children = ( + 27A92CBD0E349281006E7CF6 /* dar.h */, + 27A92CBE0E349281006E7CF6 /* dar_.c */, + 27A92CBF0E349281006E7CF6 /* darBalance.c */, + 27A92CC00E349281006E7CF6 /* darCore.c */, + 27A92CC10E349281006E7CF6 /* darCut.c */, + 27A92CC20E349281006E7CF6 /* darData.c */, + 27A92CC30E349281006E7CF6 /* darInt.h */, + 27A92CC40E349281006E7CF6 /* darLib.c */, + 27A92CC50E349281006E7CF6 /* darMan.c */, + 27A92CC60E349281006E7CF6 /* darPrec.c */, + 27A92CC70E349281006E7CF6 /* darRefact.c */, + 27A92CC80E349281006E7CF6 /* darResub.c */, + 27A92CC90E349281006E7CF6 /* darScript.c */, + 27A92CCA0E349281006E7CF6 /* module.make */, + ); + path = dar; + sourceTree = ""; + }; + 27A92CCB0E349281006E7CF6 /* deco */ = { + isa = PBXGroup; + children = ( + 27A92CCC0E349281006E7CF6 /* deco.h */, + 27A92CCD0E349281006E7CF6 /* module.make */, + ); + path = deco; + sourceTree = ""; + }; + 27A92CCE0E349281006E7CF6 /* fra */ = { + isa = PBXGroup; + children = ( + 27A92CCF0E349281006E7CF6 /* fra.h */, + 27A92CD00E349281006E7CF6 /* fra_.c */, + 27A92CD10E349281006E7CF6 /* fraBmc.c */, + 27A92CD20E349281006E7CF6 /* fraCec.c */, + 27A92CD30E349281006E7CF6 /* fraClass.c */, + 27A92CD40E349281006E7CF6 /* fraCnf.c */, + 27A92CD50E349281006E7CF6 /* fraCore.c */, + 27A92CD60E349281006E7CF6 /* fraImp.c */, + 27A92CD70E349281006E7CF6 /* fraInd.c */, + 27A92CD80E349281006E7CF6 /* fraLcr.c */, + 27A92CD90E349281006E7CF6 /* fraMan.c */, + 27A92CDA0E349281006E7CF6 /* fraPart.c */, + 27A92CDB0E349281006E7CF6 /* fraSat.c */, + 27A92CDC0E349281006E7CF6 /* fraSec.c */, + 27A92CDD0E349281006E7CF6 /* fraSim.c */, + 27A92CDE0E349281006E7CF6 /* module.make */, + ); + path = fra; + sourceTree = ""; + }; + 27A92CDF0E349281006E7CF6 /* hop */ = { + isa = PBXGroup; + children = ( + 27A92CE00E349281006E7CF6 /* cudd2.c */, + 27A92CE10E349281006E7CF6 /* cudd2.h */, + 27A92CE20E349281006E7CF6 /* hop.h */, + 27A92CE30E349281006E7CF6 /* hop_.c */, + 27A92CE40E349281006E7CF6 /* hopBalance.c */, + 27A92CE50E349281006E7CF6 /* hopCheck.c */, + 27A92CE60E349281006E7CF6 /* hopDfs.c */, + 27A92CE70E349281006E7CF6 /* hopMan.c */, + 27A92CE80E349281006E7CF6 /* hopMem.c */, + 27A92CE90E349281006E7CF6 /* hopObj.c */, + 27A92CEA0E349281006E7CF6 /* hopOper.c */, + 27A92CEB0E349281006E7CF6 /* hopTable.c */, + 27A92CEC0E349281006E7CF6 /* hopUtil.c */, + 27A92CED0E349281006E7CF6 /* module.make */, + ); + path = hop; + sourceTree = ""; + }; + 27A92CEE0E349281006E7CF6 /* ioa */ = { + isa = PBXGroup; + children = ( + 27A92CEF0E349281006E7CF6 /* ioa.h */, + 27A92CF00E349281006E7CF6 /* ioaReadAig.c */, + 27A92CF10E349281006E7CF6 /* ioaUtil.c */, + 27A92CF20E349281006E7CF6 /* ioaWriteAig.c */, + 27A92CF30E349281006E7CF6 /* module.make */, + ); + path = ioa; + sourceTree = ""; + }; + 27A92CF40E349281006E7CF6 /* ivy */ = { + isa = PBXGroup; + children = ( + 27A92CF50E349281006E7CF6 /* attr.h */, + 27A92CF60E349281006E7CF6 /* ivy.h */, + 27A92CF70E349281006E7CF6 /* ivy_.c */, + 27A92CF80E349281006E7CF6 /* ivyBalance.c */, + 27A92CF90E349281006E7CF6 /* ivyCanon.c */, + 27A92CFA0E349281006E7CF6 /* ivyCheck.c */, + 27A92CFB0E349281006E7CF6 /* ivyCut.c */, + 27A92CFC0E349281006E7CF6 /* ivyCutTrav.c */, + 27A92CFD0E349281006E7CF6 /* ivyDfs.c */, + 27A92CFE0E349281006E7CF6 /* ivyDsd.c */, + 27A92CFF0E349281006E7CF6 /* ivyFanout.c */, + 27A92D000E349281006E7CF6 /* ivyFastMap.c */, + 27A92D010E349281006E7CF6 /* ivyFraig.c */, + 27A92D020E349281006E7CF6 /* ivyHaig.c */, + 27A92D030E349281006E7CF6 /* ivyMan.c */, + 27A92D040E349281006E7CF6 /* ivyMem.c */, + 27A92D050E349281006E7CF6 /* ivyMulti.c */, + 27A92D060E349281006E7CF6 /* ivyMulti8.c */, + 27A92D070E349281006E7CF6 /* ivyObj.c */, + 27A92D080E349281006E7CF6 /* ivyOper.c */, + 27A92D090E349281006E7CF6 /* ivyResyn.c */, + 27A92D0A0E349281006E7CF6 /* ivyRwr.c */, + 27A92D0B0E349281006E7CF6 /* ivyRwrAlg.c */, + 27A92D0C0E349281006E7CF6 /* ivySeq.c */, + 27A92D0D0E349281006E7CF6 /* ivyShow.c */, + 27A92D0E0E349281006E7CF6 /* ivyTable.c */, + 27A92D0F0E349281006E7CF6 /* ivyUtil.c */, + 27A92D100E349281006E7CF6 /* module.make */, + ); + path = ivy; + sourceTree = ""; + }; + 27A92D110E349281006E7CF6 /* kit */ = { + isa = PBXGroup; + children = ( + 27A92D120E349281006E7CF6 /* cloud.c */, + 27A92D130E349281006E7CF6 /* cloud.h */, + 27A92D140E349281006E7CF6 /* kit.h */, + 27A92D150E349281006E7CF6 /* kit_.c */, + 27A92D160E349281006E7CF6 /* kitAig.c */, + 27A92D170E349281006E7CF6 /* kitBdd.c */, + 27A92D180E349281006E7CF6 /* kitCloud.c */, + 27A92D190E349281006E7CF6 /* kitDsd.c */, + 27A92D1A0E349281006E7CF6 /* kitFactor.c */, + 27A92D1B0E349281006E7CF6 /* kitGraph.c */, + 27A92D1C0E349281006E7CF6 /* kitHop.c */, + 27A92D1D0E349281006E7CF6 /* kitIsop.c */, + 27A92D1E0E349281006E7CF6 /* kitSop.c */, + 27A92D1F0E349281006E7CF6 /* kitTruth.c */, + 27A92D200E349281006E7CF6 /* module.make */, + ); + path = kit; + sourceTree = ""; + }; + 27A92D210E349281006E7CF6 /* mem */ = { + isa = PBXGroup; + children = ( + 27A92D220E349281006E7CF6 /* mem.c */, + 27A92D230E349281006E7CF6 /* mem.h */, + 27A92D240E349281006E7CF6 /* module.make */, + ); + path = mem; + sourceTree = ""; + }; + 27A92D250E349281006E7CF6 /* rwt */ = { + isa = PBXGroup; + children = ( + 27A92D260E349281006E7CF6 /* module.make */, + 27A92D270E349281006E7CF6 /* rwt.h */, + 27A92D280E349281006E7CF6 /* rwtDec.c */, + 27A92D290E349281006E7CF6 /* rwtMan.c */, + 27A92D2A0E349281006E7CF6 /* rwtUtil.c */, + ); + path = rwt; + sourceTree = ""; + }; + 27A92D2B0E349281006E7CF6 /* map */ = { + isa = PBXGroup; + children = ( + 27A92D2C0E349281006E7CF6 /* fpga */, + 27A92D3E0E349281006E7CF6 /* if */, + 27A92D4B0E349281006E7CF6 /* mapper */, + 27A92D620E349281006E7CF6 /* mio */, + 27A92D6C0E349281006E7CF6 /* super */, + ); + path = map; + sourceTree = ""; + }; + 27A92D2C0E349281006E7CF6 /* fpga */ = { + isa = PBXGroup; + children = ( + 27A92D2D0E349281006E7CF6 /* fpga.c */, + 27A92D2E0E349281006E7CF6 /* fpga.h */, + 27A92D2F0E349281006E7CF6 /* fpgaCore.c */, + 27A92D300E349281006E7CF6 /* fpgaCreate.c */, + 27A92D310E349281006E7CF6 /* fpgaCut.c */, + 27A92D320E349281006E7CF6 /* fpgaCutUtils.c */, + 27A92D330E349281006E7CF6 /* fpgaFanout.c */, + 27A92D340E349281006E7CF6 /* fpgaGENERIC.c */, + 27A92D350E349281006E7CF6 /* fpgaInt.h */, + 27A92D360E349281006E7CF6 /* fpgaLib.c */, + 27A92D370E349281006E7CF6 /* fpgaMatch.c */, + 27A92D380E349281006E7CF6 /* fpgaSwitch.c */, + 27A92D390E349281006E7CF6 /* fpgaTime.c */, + 27A92D3A0E349281006E7CF6 /* fpgaTruth.c */, + 27A92D3B0E349281006E7CF6 /* fpgaUtils.c */, + 27A92D3C0E349281006E7CF6 /* fpgaVec.c */, + 27A92D3D0E349281006E7CF6 /* module.make */, + ); + path = fpga; + sourceTree = ""; + }; + 27A92D3E0E349281006E7CF6 /* if */ = { + isa = PBXGroup; + children = ( + 27A92D3F0E349281006E7CF6 /* if.h */, + 27A92D400E349281006E7CF6 /* if_.c */, + 27A92D410E349281006E7CF6 /* ifCore.c */, + 27A92D420E349281006E7CF6 /* ifCut.c */, + 27A92D430E349281006E7CF6 /* ifMan.c */, + 27A92D440E349281006E7CF6 /* ifMap.c */, + 27A92D450E349281006E7CF6 /* ifReduce.c */, + 27A92D460E349281006E7CF6 /* ifSeq.c */, + 27A92D470E349281006E7CF6 /* ifTime.c */, + 27A92D480E349281006E7CF6 /* ifTruth.c */, + 27A92D490E349281006E7CF6 /* ifUtil.c */, + 27A92D4A0E349281006E7CF6 /* module.make */, + ); + path = if; + sourceTree = ""; + }; + 27A92D4B0E349281006E7CF6 /* mapper */ = { + isa = PBXGroup; + children = ( + 27A92D4C0E349281006E7CF6 /* mapper.c */, + 27A92D4D0E349281006E7CF6 /* mapper.h */, + 27A92D4E0E349281006E7CF6 /* mapperCanon.c */, + 27A92D4F0E349281006E7CF6 /* mapperCore.c */, + 27A92D500E349281006E7CF6 /* mapperCreate.c */, + 27A92D510E349281006E7CF6 /* mapperCut.c */, + 27A92D520E349281006E7CF6 /* mapperCutUtils.c */, + 27A92D530E349281006E7CF6 /* mapperFanout.c */, + 27A92D540E349281006E7CF6 /* mapperGENERIC.c */, + 27A92D550E349281006E7CF6 /* mapperInt.h */, + 27A92D560E349281006E7CF6 /* mapperLib.c */, + 27A92D570E349281006E7CF6 /* mapperMatch.c */, + 27A92D580E349281006E7CF6 /* mapperRefs.c */, + 27A92D590E349281006E7CF6 /* mapperSuper.c */, + 27A92D5A0E349281006E7CF6 /* mapperSwitch.c */, + 27A92D5B0E349281006E7CF6 /* mapperTable.c */, + 27A92D5C0E349281006E7CF6 /* mapperTime.c */, + 27A92D5D0E349281006E7CF6 /* mapperTree.c */, + 27A92D5E0E349281006E7CF6 /* mapperTruth.c */, + 27A92D5F0E349281006E7CF6 /* mapperUtils.c */, + 27A92D600E349281006E7CF6 /* mapperVec.c */, + 27A92D610E349281006E7CF6 /* module.make */, + ); + path = mapper; + sourceTree = ""; + }; + 27A92D620E349281006E7CF6 /* mio */ = { + isa = PBXGroup; + children = ( + 27A92D630E349281006E7CF6 /* mio.c */, + 27A92D640E349281006E7CF6 /* mio.h */, + 27A92D650E349281006E7CF6 /* mioApi.c */, + 27A92D660E349281006E7CF6 /* mioFunc.c */, + 27A92D670E349281006E7CF6 /* mioGENERIC.c */, + 27A92D680E349281006E7CF6 /* mioInt.h */, + 27A92D690E349281006E7CF6 /* mioRead.c */, + 27A92D6A0E349281006E7CF6 /* mioUtils.c */, + 27A92D6B0E349281006E7CF6 /* module.make */, + ); + path = mio; + sourceTree = ""; + }; + 27A92D6C0E349281006E7CF6 /* super */ = { + isa = PBXGroup; + children = ( + 27A92D6D0E349281006E7CF6 /* module.make */, + 27A92D6E0E349281006E7CF6 /* super.c */, + 27A92D6F0E349281006E7CF6 /* super.h */, + 27A92D700E349281006E7CF6 /* superAnd.c */, + 27A92D710E349281006E7CF6 /* superGate.c */, + 27A92D720E349281006E7CF6 /* superGENERIC.c */, + 27A92D730E349281006E7CF6 /* superInt.h */, + 27A92D740E349281006E7CF6 /* superWrite.c */, + ); + path = super; + sourceTree = ""; + }; + 27A92D750E349282006E7CF6 /* base */ = { + isa = PBXGroup; + children = ( + 27A92D760E349282006E7CF6 /* abc */, + 27A92D8D0E349282006E7CF6 /* abci */, + 27A92DC90E349282006E7CF6 /* cmd */, + 27A92DD30E349282006E7CF6 /* io */, + 27A92DF10E349282006E7CF6 /* main */, + 27A92DFA0E349282006E7CF6 /* temp.c */, + 27A92DFB0E349282006E7CF6 /* ver */, + ); + path = base; + sourceTree = ""; + }; + 27A92D760E349282006E7CF6 /* abc */ = { + isa = PBXGroup; + children = ( + 27A92D770E349282006E7CF6 /* abc.h */, + 27A92D780E349282006E7CF6 /* abc_.c */, + 27A92D790E349282006E7CF6 /* abcAig.c */, + 27A92D7A0E349282006E7CF6 /* abcBlifMv.c */, + 27A92D7B0E349282006E7CF6 /* abcCheck.c */, + 27A92D7C0E349282006E7CF6 /* abcDfs.c */, + 27A92D7D0E349282006E7CF6 /* abcFanio.c */, + 27A92D7E0E349282006E7CF6 /* abcFunc.c */, + 27A92D7F0E349282006E7CF6 /* abcHie.c */, + 27A92D800E349282006E7CF6 /* abcInt.h */, + 27A92D810E349282006E7CF6 /* abcLatch.c */, + 27A92D820E349282006E7CF6 /* abcLib.c */, + 27A92D830E349282006E7CF6 /* abcMinBase.c */, + 27A92D840E349282006E7CF6 /* abcNames.c */, + 27A92D850E349282006E7CF6 /* abcNetlist.c */, + 27A92D860E349282006E7CF6 /* abcNtk.c */, + 27A92D870E349282006E7CF6 /* abcObj.c */, + 27A92D880E349282006E7CF6 /* abcRefs.c */, + 27A92D890E349282006E7CF6 /* abcShow.c */, + 27A92D8A0E349282006E7CF6 /* abcSop.c */, + 27A92D8B0E349282006E7CF6 /* abcUtil.c */, + 27A92D8C0E349282006E7CF6 /* module.make */, + ); + path = abc; + sourceTree = ""; + }; + 27A92D8D0E349282006E7CF6 /* abci */ = { + isa = PBXGroup; + children = ( + 27A92D8E0E349282006E7CF6 /* abc.c */, + 27A92D8F0E349282006E7CF6 /* abc_.c */, + 27A92D900E349282006E7CF6 /* abcAttach.c */, + 27A92D910E349282006E7CF6 /* abcAuto.c */, + 27A92D920E349282006E7CF6 /* abcBalance.c */, + 27A92D930E349282006E7CF6 /* abcBmc.c */, + 27A92D940E349282006E7CF6 /* abcCas.c */, + 27A92D950E349282006E7CF6 /* abcClpBdd.c */, + 27A92D960E349282006E7CF6 /* abcClpSop.c */, + 27A92D970E349282006E7CF6 /* abcCut.c */, + 27A92D980E349282006E7CF6 /* abcDar.c */, + 27A92D990E349282006E7CF6 /* abcDebug.c */, + 27A92D9A0E349282006E7CF6 /* abcDress.c */, + 27A92D9B0E349282006E7CF6 /* abcDsd.c */, + 27A92D9C0E349282006E7CF6 /* abcEspresso.c */, + 27A92D9D0E349282006E7CF6 /* abcExtract.c */, + 27A92D9E0E349282006E7CF6 /* abcFpga.c */, + 27A92D9F0E349282006E7CF6 /* abcFpgaFast.c */, + 27A92DA00E349282006E7CF6 /* abcFraig.c */, + 27A92DA10E349282006E7CF6 /* abcFxu.c */, + 27A92DA20E349282006E7CF6 /* abcGen.c */, + 27A92DA30E349282006E7CF6 /* abcHaig.c */, + 27A92DA40E349282006E7CF6 /* abcIf.c */, + 27A92DA50E349282006E7CF6 /* abcIvy.c */, + 27A92DA60E349282006E7CF6 /* abcLut.c */, + 27A92DA70E349282006E7CF6 /* abcMap.c */, + 27A92DA80E349282006E7CF6 /* abcMeasure.c */, + 27A92DA90E349282006E7CF6 /* abcMini.c */, + 27A92DAA0E349282006E7CF6 /* abcMiter.c */, + 27A92DAB0E349282006E7CF6 /* abcMulti.c */, + 27A92DAC0E349282006E7CF6 /* abcMv.c */, + 27A92DAD0E349282006E7CF6 /* abcNtbdd.c */, + 27A92DAE0E349282006E7CF6 /* abcOdc.c */, + 27A92DAF0E349282006E7CF6 /* abcOrder.c */, + 27A92DB00E349282006E7CF6 /* abcPart.c */, + 27A92DB10E349282006E7CF6 /* abcPlace.c */, + 27A92DB20E349282006E7CF6 /* abcPrint.c */, + 27A92DB30E349282006E7CF6 /* abcProve.c */, + 27A92DB40E349282006E7CF6 /* abcQbf.c */, + 27A92DB50E349282006E7CF6 /* abcQuant.c */, + 27A92DB60E349282006E7CF6 /* abcRec.c */, + 27A92DB70E349282006E7CF6 /* abcReconv.c */, + 27A92DB80E349282006E7CF6 /* abcRefactor.c */, + 27A92DB90E349282006E7CF6 /* abcRenode.c */, + 27A92DBA0E349282006E7CF6 /* abcReorder.c */, + 27A92DBB0E349282006E7CF6 /* abcRestruct.c */, + 27A92DBC0E349282006E7CF6 /* abcResub.c */, + 27A92DBD0E349282006E7CF6 /* abcRewrite.c */, + 27A92DBE0E349282006E7CF6 /* abcRr.c */, + 27A92DBF0E349282006E7CF6 /* abcSat.c */, + 27A92DC00E349282006E7CF6 /* abcStrash.c */, + 27A92DC10E349282006E7CF6 /* abcSweep.c */, + 27A92DC20E349282006E7CF6 /* abcSymm.c */, + 27A92DC30E349282006E7CF6 /* abcTiming.c */, + 27A92DC40E349282006E7CF6 /* abcUnate.c */, + 27A92DC50E349282006E7CF6 /* abcUnreach.c */, + 27A92DC60E349282006E7CF6 /* abcVerify.c */, + 27A92DC70E349282006E7CF6 /* abcXsim.c */, + 27A92DC80E349282006E7CF6 /* module.make */, + ); + path = abci; + sourceTree = ""; + }; + 27A92DC90E349282006E7CF6 /* cmd */ = { + isa = PBXGroup; + children = ( + 27A92DCA0E349282006E7CF6 /* cmd.c */, + 27A92DCB0E349282006E7CF6 /* cmd.h */, + 27A92DCC0E349282006E7CF6 /* cmdAlias.c */, + 27A92DCD0E349282006E7CF6 /* cmdApi.c */, + 27A92DCE0E349282006E7CF6 /* cmdFlag.c */, + 27A92DCF0E349282006E7CF6 /* cmdHist.c */, + 27A92DD00E349282006E7CF6 /* cmdInt.h */, + 27A92DD10E349282006E7CF6 /* cmdUtils.c */, + 27A92DD20E349282006E7CF6 /* module.make */, + ); + path = cmd; + sourceTree = ""; + }; + 27A92DD30E349282006E7CF6 /* io */ = { + isa = PBXGroup; + children = ( + 27A92DD40E349282006E7CF6 /* io.c */, + 27A92DD50E349282006E7CF6 /* io.h */, + 27A92DD60E349282006E7CF6 /* io_.c */, + 27A92DD70E349282006E7CF6 /* ioInt.h */, + 27A92DD80E349282006E7CF6 /* ioReadAiger.c */, + 27A92DD90E349282006E7CF6 /* ioReadBaf.c */, + 27A92DDA0E349282006E7CF6 /* ioReadBench.c */, + 27A92DDB0E349282006E7CF6 /* ioReadBlif.c */, + 27A92DDC0E349282006E7CF6 /* ioReadBlifAig.c */, + 27A92DDD0E349282006E7CF6 /* ioReadBlifMv.c */, + 27A92DDE0E349282006E7CF6 /* ioReadDsd.c */, + 27A92DDF0E349282006E7CF6 /* ioReadEdif.c */, + 27A92DE00E349282006E7CF6 /* ioReadEqn.c */, + 27A92DE10E349282006E7CF6 /* ioReadPla.c */, + 27A92DE20E349282006E7CF6 /* ioReadVerilog.c */, + 27A92DE30E349282006E7CF6 /* ioUtil.c */, + 27A92DE40E349282006E7CF6 /* ioWriteAiger.c */, + 27A92DE50E349282006E7CF6 /* ioWriteBaf.c */, + 27A92DE60E349282006E7CF6 /* ioWriteBench.c */, + 27A92DE70E349282006E7CF6 /* ioWriteBlif.c */, + 27A92DE80E349282006E7CF6 /* ioWriteBlifMv.c */, + 27A92DE90E349282006E7CF6 /* ioWriteCnf.c */, + 27A92DEA0E349282006E7CF6 /* ioWriteDot.c */, + 27A92DEB0E349282006E7CF6 /* ioWriteEqn.c */, + 27A92DEC0E349282006E7CF6 /* ioWriteGml.c */, + 27A92DED0E349282006E7CF6 /* ioWriteList.c */, + 27A92DEE0E349282006E7CF6 /* ioWritePla.c */, + 27A92DEF0E349282006E7CF6 /* ioWriteVerilog.c */, + 27A92DF00E349282006E7CF6 /* module.make */, + ); + path = io; + sourceTree = ""; + }; + 27A92DF10E349282006E7CF6 /* main */ = { + isa = PBXGroup; + children = ( + 27A92DF20E349282006E7CF6 /* libSupport.c */, + 27A92DF30E349282006E7CF6 /* main.c */, + 27A92DF40E349282006E7CF6 /* main.h */, + 27A92DF50E349282006E7CF6 /* mainFrame.c */, + 27A92DF60E349282006E7CF6 /* mainInit.c */, + 27A92DF70E349282006E7CF6 /* mainInt.h */, + 27A92DF80E349282006E7CF6 /* mainUtils.c */, + 27A92DF90E349282006E7CF6 /* module.make */, + ); + path = main; + sourceTree = ""; + }; + 27A92DFB0E349282006E7CF6 /* ver */ = { + isa = PBXGroup; + children = ( + 27A92DFC0E349282006E7CF6 /* module.make */, + 27A92DFD0E349282006E7CF6 /* ver.h */, + 27A92DFE0E349282006E7CF6 /* ver_.c */, + 27A92DFF0E349282006E7CF6 /* verCore.c */, + 27A92E000E349282006E7CF6 /* verFormula.c */, + 27A92E010E349282006E7CF6 /* verParse.c */, + 27A92E020E349282006E7CF6 /* verStream.c */, + 27A92E030E349282006E7CF6 /* verWords.c */, + ); + path = ver; + sourceTree = ""; + }; + 27A92E040E349282006E7CF6 /* misc */ = { + isa = PBXGroup; + children = ( + 27A92E050E349282006E7CF6 /* espresso */, + 27A92E360E349282006E7CF6 /* extra */, + 27A92E480E349282006E7CF6 /* hash */, + 27A92E4E0E349282006E7CF6 /* mvc */, + 27A92E610E349283006E7CF6 /* nm */, + 27A92E670E349283006E7CF6 /* st */, + 27A92E6D0E349283006E7CF6 /* util */, + 27A92E720E349283006E7CF6 /* vec */, + ); + path = misc; + sourceTree = ""; + }; + 27A92E050E349282006E7CF6 /* espresso */ = { + isa = PBXGroup; + children = ( + 27A92E060E349282006E7CF6 /* cofactor.c */, + 27A92E070E349282006E7CF6 /* cols.c */, + 27A92E080E349282006E7CF6 /* compl.c */, + 27A92E090E349282006E7CF6 /* contain.c */, + 27A92E0A0E349282006E7CF6 /* cubehack.c */, + 27A92E0B0E349282006E7CF6 /* cubestr.c */, + 27A92E0C0E349282006E7CF6 /* cvrin.c */, + 27A92E0D0E349282006E7CF6 /* cvrm.c */, + 27A92E0E0E349282006E7CF6 /* cvrmisc.c */, + 27A92E0F0E349282006E7CF6 /* cvrout.c */, + 27A92E100E349282006E7CF6 /* dominate.c */, + 27A92E110E349282006E7CF6 /* equiv.c */, + 27A92E120E349282006E7CF6 /* espresso.c */, + 27A92E130E349282006E7CF6 /* espresso.h */, + 27A92E140E349282006E7CF6 /* essen.c */, + 27A92E150E349282006E7CF6 /* exact.c */, + 27A92E160E349282006E7CF6 /* expand.c */, + 27A92E170E349282006E7CF6 /* gasp.c */, + 27A92E180E349282006E7CF6 /* gimpel.c */, + 27A92E190E349282006E7CF6 /* globals.c */, + 27A92E1A0E349282006E7CF6 /* hack.c */, + 27A92E1B0E349282006E7CF6 /* indep.c */, + 27A92E1C0E349282006E7CF6 /* irred.c */, + 27A92E1D0E349282006E7CF6 /* main.c */, + 27A92E1E0E349282006E7CF6 /* main.h */, + 27A92E1F0E349282006E7CF6 /* map.c */, + 27A92E200E349282006E7CF6 /* matrix.c */, + 27A92E210E349282006E7CF6 /* mincov.c */, + 27A92E220E349282006E7CF6 /* mincov.h */, + 27A92E230E349282006E7CF6 /* mincov_int.h */, + 27A92E240E349282006E7CF6 /* module.make */, + 27A92E250E349282006E7CF6 /* opo.c */, + 27A92E260E349282006E7CF6 /* pair.c */, + 27A92E270E349282006E7CF6 /* part.c */, + 27A92E280E349282006E7CF6 /* primes.c */, + 27A92E290E349282006E7CF6 /* reduce.c */, + 27A92E2A0E349282006E7CF6 /* rows.c */, + 27A92E2B0E349282006E7CF6 /* set.c */, + 27A92E2C0E349282006E7CF6 /* setc.c */, + 27A92E2D0E349282006E7CF6 /* sharp.c */, + 27A92E2E0E349282006E7CF6 /* sminterf.c */, + 27A92E2F0E349282006E7CF6 /* solution.c */, + 27A92E300E349282006E7CF6 /* sparse.c */, + 27A92E310E349282006E7CF6 /* sparse.h */, + 27A92E320E349282006E7CF6 /* sparse_int.h */, + 27A92E330E349282006E7CF6 /* unate.c */, + 27A92E340E349282006E7CF6 /* util_old.h */, + 27A92E350E349282006E7CF6 /* verify.c */, + ); + path = espresso; + sourceTree = ""; + }; + 27A92E360E349282006E7CF6 /* extra */ = { + isa = PBXGroup; + children = ( + 27A92E370E349282006E7CF6 /* extra.h */, + 27A92E380E349282006E7CF6 /* extraBddAuto.c */, + 27A92E390E349282006E7CF6 /* extraBddCas.c */, + 27A92E3A0E349282006E7CF6 /* extraBddKmap.c */, + 27A92E3B0E349282006E7CF6 /* extraBddMisc.c */, + 27A92E3C0E349282006E7CF6 /* extraBddSymm.c */, + 27A92E3D0E349282006E7CF6 /* extraBddUnate.c */, + 27A92E3E0E349282006E7CF6 /* extraUtilBitMatrix.c */, + 27A92E3F0E349282006E7CF6 /* extraUtilCanon.c */, + 27A92E400E349282006E7CF6 /* extraUtilFile.c */, + 27A92E410E349282006E7CF6 /* extraUtilMemory.c */, + 27A92E420E349282006E7CF6 /* extraUtilMisc.c */, + 27A92E430E349282006E7CF6 /* extraUtilProgress.c */, + 27A92E440E349282006E7CF6 /* extraUtilReader.c */, + 27A92E450E349282006E7CF6 /* extraUtilTruth.c */, + 27A92E460E349282006E7CF6 /* extraUtilUtil.c */, + 27A92E470E349282006E7CF6 /* module.make */, + ); + path = extra; + sourceTree = ""; + }; + 27A92E480E349282006E7CF6 /* hash */ = { + isa = PBXGroup; + children = ( + 27A92E490E349282006E7CF6 /* hash.h */, + 27A92E4A0E349282006E7CF6 /* hashFlt.h */, + 27A92E4B0E349282006E7CF6 /* hashInt.h */, + 27A92E4C0E349282006E7CF6 /* hashPtr.h */, + 27A92E4D0E349282006E7CF6 /* module.make */, + ); + path = hash; + sourceTree = ""; + }; + 27A92E4E0E349282006E7CF6 /* mvc */ = { + isa = PBXGroup; + children = ( + 27A92E4F0E349282006E7CF6 /* module.make */, + 27A92E500E349282006E7CF6 /* mvc.c */, + 27A92E510E349282006E7CF6 /* mvc.h */, + 27A92E520E349282006E7CF6 /* mvcApi.c */, + 27A92E530E349282006E7CF6 /* mvcCompare.c */, + 27A92E540E349282006E7CF6 /* mvcContain.c */, + 27A92E550E349282006E7CF6 /* mvcCover.c */, + 27A92E560E349282006E7CF6 /* mvcCube.c */, + 27A92E570E349282006E7CF6 /* mvcDivide.c */, + 27A92E580E349282006E7CF6 /* mvcDivisor.c */, + 27A92E590E349282006E7CF6 /* mvcList.c */, + 27A92E5A0E349282006E7CF6 /* mvcLits.c */, + 27A92E5B0E349282006E7CF6 /* mvcMan.c */, + 27A92E5C0E349282006E7CF6 /* mvcOpAlg.c */, + 27A92E5D0E349283006E7CF6 /* mvcOpBool.c */, + 27A92E5E0E349283006E7CF6 /* mvcPrint.c */, + 27A92E5F0E349283006E7CF6 /* mvcSort.c */, + 27A92E600E349283006E7CF6 /* mvcUtils.c */, + ); + path = mvc; + sourceTree = ""; + }; + 27A92E610E349283006E7CF6 /* nm */ = { + isa = PBXGroup; + children = ( + 27A92E620E349283006E7CF6 /* module.make */, + 27A92E630E349283006E7CF6 /* nm.h */, + 27A92E640E349283006E7CF6 /* nmApi.c */, + 27A92E650E349283006E7CF6 /* nmInt.h */, + 27A92E660E349283006E7CF6 /* nmTable.c */, + ); + path = nm; + sourceTree = ""; + }; + 27A92E670E349283006E7CF6 /* st */ = { + isa = PBXGroup; + children = ( + 27A92E680E349283006E7CF6 /* module.make */, + 27A92E690E349283006E7CF6 /* st.c */, + 27A92E6A0E349283006E7CF6 /* st.h */, + 27A92E6B0E349283006E7CF6 /* stmm.c */, + 27A92E6C0E349283006E7CF6 /* stmm.h */, + ); + path = st; + sourceTree = ""; + }; + 27A92E6D0E349283006E7CF6 /* util */ = { + isa = PBXGroup; + children = ( + 27A92E6E0E349283006E7CF6 /* leaks.h */, + 27A92E6F0E349283006E7CF6 /* module.make */, + 27A92E700E349283006E7CF6 /* stdlib_hack.h */, + 27A92E710E349283006E7CF6 /* util_hack.h */, + ); + path = util; + sourceTree = ""; + }; + 27A92E720E349283006E7CF6 /* vec */ = { + isa = PBXGroup; + children = ( + 27A92E730E349283006E7CF6 /* module.make */, + 27A92E740E349283006E7CF6 /* vec.h */, + 27A92E750E349283006E7CF6 /* vecAtt.h */, + 27A92E760E349283006E7CF6 /* vecFlt.h */, + 27A92E770E349283006E7CF6 /* vecInt.h */, + 27A92E780E349283006E7CF6 /* vecPtr.h */, + 27A92E790E349283006E7CF6 /* vecStr.h */, + 27A92E7A0E349283006E7CF6 /* vecVec.h */, + ); + path = vec; + sourceTree = ""; + }; + C6A0FF2B0290797F04C91782 /* Documentation */ = { + isa = PBXGroup; + children = ( + C6A0FF2C0290799A04C91782 /* abc.1 */, + ); + name = Documentation; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 8DD76FA90486AB0100D96B5E /* abc */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget "abc" */; + buildPhases = ( + 8DD76FAB0486AB0100D96B5E /* Sources */, + 8DD76FAD0486AB0100D96B5E /* Frameworks */, + 8DD76FAF0486AB0100D96B5E /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = abc; + productInstallPath = "$(HOME)/bin"; + productName = abc; + productReference = 8DD76FB20486AB0100D96B5E /* abc */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "abc" */; + compatibilityVersion = "Xcode 3.1"; + hasScannedForEncodings = 1; + mainGroup = 08FB7794FE84155DC02AAC07 /* abc */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DD76FA90486AB0100D96B5E /* abc */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DD76FAB0486AB0100D96B5E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 27A92E7C0E349283006E7CF6 /* cutApi.c in Sources */, + 27A92E7D0E349283006E7CF6 /* cutCut.c in Sources */, + 27A92E7E0E349283006E7CF6 /* cutExpand.c in Sources */, + 27A92E7F0E349283006E7CF6 /* cutMan.c in Sources */, + 27A92E800E349283006E7CF6 /* cutMerge.c in Sources */, + 27A92E810E349283006E7CF6 /* cutNode.c in Sources */, + 27A92E820E349283006E7CF6 /* cutOracle.c in Sources */, + 27A92E830E349283006E7CF6 /* cutPre22.c in Sources */, + 27A92E840E349283006E7CF6 /* cutSeq.c in Sources */, + 27A92E850E349283006E7CF6 /* cutTruth.c in Sources */, + 27A92E860E349283006E7CF6 /* decAbc.c in Sources */, + 27A92E870E349283006E7CF6 /* decFactor.c in Sources */, + 27A92E880E349283006E7CF6 /* decMan.c in Sources */, + 27A92E890E349283006E7CF6 /* decPrint.c in Sources */, + 27A92E8A0E349283006E7CF6 /* decUtil.c in Sources */, + 27A92E8B0E349283006E7CF6 /* fxu.c in Sources */, + 27A92E8C0E349283006E7CF6 /* fxuCreate.c in Sources */, + 27A92E8D0E349283006E7CF6 /* fxuHeapD.c in Sources */, + 27A92E8E0E349283006E7CF6 /* fxuHeapS.c in Sources */, + 27A92E8F0E349283006E7CF6 /* fxuList.c in Sources */, + 27A92E900E349283006E7CF6 /* fxuMatrix.c in Sources */, + 27A92E910E349283006E7CF6 /* fxuPair.c in Sources */, + 27A92E920E349283006E7CF6 /* fxuPrint.c in Sources */, + 27A92E930E349283006E7CF6 /* fxuReduce.c in Sources */, + 27A92E940E349283006E7CF6 /* fxuSelect.c in Sources */, + 27A92E950E349283006E7CF6 /* fxuSingle.c in Sources */, + 27A92E960E349283006E7CF6 /* fxuUpdate.c in Sources */, + 27A92E970E349283006E7CF6 /* lpk_.c in Sources */, + 27A92E980E349283006E7CF6 /* lpkAbcDec.c in Sources */, + 27A92E990E349283006E7CF6 /* lpkAbcDsd.c in Sources */, + 27A92E9A0E349283006E7CF6 /* lpkAbcMux.c in Sources */, + 27A92E9B0E349283006E7CF6 /* lpkAbcUtil.c in Sources */, + 27A92E9C0E349283006E7CF6 /* lpkCore.c in Sources */, + 27A92E9D0E349283006E7CF6 /* lpkCut.c in Sources */, + 27A92E9E0E349283006E7CF6 /* lpkMan.c in Sources */, + 27A92E9F0E349283006E7CF6 /* lpkMap.c in Sources */, + 27A92EA00E349283006E7CF6 /* lpkMulti.c in Sources */, + 27A92EA10E349283006E7CF6 /* lpkMux.c in Sources */, + 27A92EA20E349283006E7CF6 /* lpkSets.c in Sources */, + 27A92EA30E349283006E7CF6 /* res_.c in Sources */, + 27A92EA40E349283006E7CF6 /* resCore.c in Sources */, + 27A92EA50E349283006E7CF6 /* resDivs.c in Sources */, + 27A92EA60E349283006E7CF6 /* resFilter.c in Sources */, + 27A92EA70E349283006E7CF6 /* resSat.c in Sources */, + 27A92EA80E349283006E7CF6 /* resSim.c in Sources */, + 27A92EAA0E349283006E7CF6 /* resStrash.c in Sources */, + 27A92EAB0E349283006E7CF6 /* resWin.c in Sources */, + 27A92EAC0E349283006E7CF6 /* ret_.c in Sources */, + 27A92EAD0E349283006E7CF6 /* retArea.c in Sources */, + 27A92EAE0E349283006E7CF6 /* retCore.c in Sources */, + 27A92EAF0E349283006E7CF6 /* retDelay.c in Sources */, + 27A92EB00E349283006E7CF6 /* retFlow.c in Sources */, + 27A92EB10E349283006E7CF6 /* retIncrem.c in Sources */, + 27A92EB20E349283006E7CF6 /* retInit.c in Sources */, + 27A92EB30E349283006E7CF6 /* retLvalue.c in Sources */, + 27A92EB40E349283006E7CF6 /* rwrDec.c in Sources */, + 27A92EB50E349283006E7CF6 /* rwrEva.c in Sources */, + 27A92EB60E349283006E7CF6 /* rwrExp.c in Sources */, + 27A92EB70E349283006E7CF6 /* rwrLib.c in Sources */, + 27A92EB80E349283006E7CF6 /* rwrMan.c in Sources */, + 27A92EB90E349283006E7CF6 /* rwrPrint.c in Sources */, + 27A92EBA0E349283006E7CF6 /* rwrTemp.c in Sources */, + 27A92EBB0E349283006E7CF6 /* rwrUtil.c in Sources */, + 27A92EBC0E349283006E7CF6 /* simMan.c in Sources */, + 27A92EBD0E349283006E7CF6 /* simSat.c in Sources */, + 27A92EBE0E349283006E7CF6 /* simSeq.c in Sources */, + 27A92EBF0E349283006E7CF6 /* simSupp.c in Sources */, + 27A92EC00E349283006E7CF6 /* simSwitch.c in Sources */, + 27A92EC10E349283006E7CF6 /* simSym.c in Sources */, + 27A92EC20E349283006E7CF6 /* simSymSat.c in Sources */, + 27A92EC30E349283006E7CF6 /* simSymSim.c in Sources */, + 27A92EC40E349283006E7CF6 /* simSymStr.c in Sources */, + 27A92EC50E349283006E7CF6 /* simUtils.c in Sources */, + 27A92EC60E349283006E7CF6 /* satInter.c in Sources */, + 27A92EC70E349283006E7CF6 /* satMem.c in Sources */, + 27A92EC80E349283006E7CF6 /* satSolver.c in Sources */, + 27A92EC90E349283006E7CF6 /* satStore.c in Sources */, + 27A92ECA0E349283006E7CF6 /* satTrace.c in Sources */, + 27A92ECB0E349283006E7CF6 /* satUtil.c in Sources */, + 27A92ECC0E349283006E7CF6 /* csat_apis.c in Sources */, + 27A92ECD0E349283006E7CF6 /* fraigApi.c in Sources */, + 27A92ECE0E349283006E7CF6 /* fraigCanon.c in Sources */, + 27A92ECF0E349283006E7CF6 /* fraigChoice.c in Sources */, + 27A92ED00E349283006E7CF6 /* fraigFanout.c in Sources */, + 27A92ED10E349283006E7CF6 /* fraigFeed.c in Sources */, + 27A92ED20E349283006E7CF6 /* fraigMan.c in Sources */, + 27A92ED30E349283006E7CF6 /* fraigMem.c in Sources */, + 27A92ED40E349283006E7CF6 /* fraigNode.c in Sources */, + 27A92ED50E349283006E7CF6 /* fraigPrime.c in Sources */, + 27A92ED60E349283006E7CF6 /* fraigSat.c in Sources */, + 27A92ED70E349283006E7CF6 /* fraigTable.c in Sources */, + 27A92ED80E349283006E7CF6 /* fraigUtil.c in Sources */, + 27A92ED90E349283006E7CF6 /* fraigVec.c in Sources */, + 27A92EDA0E349283006E7CF6 /* msatActivity.c in Sources */, + 27A92EDB0E349283006E7CF6 /* msatClause.c in Sources */, + 27A92EDC0E349283006E7CF6 /* msatClauseVec.c in Sources */, + 27A92EDD0E349283006E7CF6 /* msatMem.c in Sources */, + 27A92EDF0E349283006E7CF6 /* msatOrderJ.c in Sources */, + 27A92EE00E349283006E7CF6 /* msatQueue.c in Sources */, + 27A92EE10E349283006E7CF6 /* msatRead.c in Sources */, + 27A92EE20E349283006E7CF6 /* msatSolverApi.c in Sources */, + 27A92EE30E349283006E7CF6 /* msatSolverCore.c in Sources */, + 27A92EE40E349283006E7CF6 /* msatSolverIo.c in Sources */, + 27A92EE50E349283006E7CF6 /* msatSolverSearch.c in Sources */, + 27A92EE60E349283006E7CF6 /* msatSort.c in Sources */, + 27A92EE70E349283006E7CF6 /* msatVec.c in Sources */, + 27A92EE80E349283006E7CF6 /* pr.c in Sources */, + 27A92EE90E349283006E7CF6 /* casCore.c in Sources */, + 27A92EEA0E349283006E7CF6 /* casDec.c in Sources */, + 27A92EEB0E349283006E7CF6 /* cuddAddAbs.c in Sources */, + 27A92EEC0E349283006E7CF6 /* cuddAddApply.c in Sources */, + 27A92EED0E349283006E7CF6 /* cuddAddFind.c in Sources */, + 27A92EEE0E349283006E7CF6 /* cuddAddInv.c in Sources */, + 27A92EEF0E349283006E7CF6 /* cuddAddIte.c in Sources */, + 27A92EF00E349283006E7CF6 /* cuddAddNeg.c in Sources */, + 27A92EF10E349283006E7CF6 /* cuddAddWalsh.c in Sources */, + 27A92EF20E349283006E7CF6 /* cuddAndAbs.c in Sources */, + 27A92EF30E349283006E7CF6 /* cuddAnneal.c in Sources */, + 27A92EF40E349283006E7CF6 /* cuddApa.c in Sources */, + 27A92EF50E349283006E7CF6 /* cuddAPI.c in Sources */, + 27A92EF60E349283006E7CF6 /* cuddApprox.c in Sources */, + 27A92EF70E349283006E7CF6 /* cuddBddAbs.c in Sources */, + 27A92EF80E349283006E7CF6 /* cuddBddCorr.c in Sources */, + 27A92EF90E349283006E7CF6 /* cuddBddIte.c in Sources */, + 27A92EFA0E349283006E7CF6 /* cuddBridge.c in Sources */, + 27A92EFB0E349283006E7CF6 /* cuddCache.c in Sources */, + 27A92EFC0E349283006E7CF6 /* cuddCheck.c in Sources */, + 27A92EFD0E349283006E7CF6 /* cuddClip.c in Sources */, + 27A92EFE0E349283006E7CF6 /* cuddCof.c in Sources */, + 27A92EFF0E349283006E7CF6 /* cuddCompose.c in Sources */, + 27A92F000E349283006E7CF6 /* cuddDecomp.c in Sources */, + 27A92F010E349283006E7CF6 /* cuddEssent.c in Sources */, + 27A92F020E349283006E7CF6 /* cuddExact.c in Sources */, + 27A92F030E349283006E7CF6 /* cuddExport.c in Sources */, + 27A92F040E349283006E7CF6 /* cuddGenCof.c in Sources */, + 27A92F050E349283006E7CF6 /* cuddGenetic.c in Sources */, + 27A92F060E349283006E7CF6 /* cuddGroup.c in Sources */, + 27A92F070E349283006E7CF6 /* cuddHarwell.c in Sources */, + 27A92F080E349283006E7CF6 /* cuddInit.c in Sources */, + 27A92F090E349283006E7CF6 /* cuddInteract.c in Sources */, + 27A92F0A0E349283006E7CF6 /* cuddLCache.c in Sources */, + 27A92F0B0E349283006E7CF6 /* cuddLevelQ.c in Sources */, + 27A92F0C0E349283006E7CF6 /* cuddLinear.c in Sources */, + 27A92F0D0E349283006E7CF6 /* cuddLiteral.c in Sources */, + 27A92F0E0E349283006E7CF6 /* cuddMatMult.c in Sources */, + 27A92F0F0E349283006E7CF6 /* cuddPriority.c in Sources */, + 27A92F100E349283006E7CF6 /* cuddRead.c in Sources */, + 27A92F110E349283006E7CF6 /* cuddRef.c in Sources */, + 27A92F120E349283006E7CF6 /* cuddReorder.c in Sources */, + 27A92F130E349283006E7CF6 /* cuddSat.c in Sources */, + 27A92F140E349283006E7CF6 /* cuddSign.c in Sources */, + 27A92F150E349283006E7CF6 /* cuddSolve.c in Sources */, + 27A92F160E349283006E7CF6 /* cuddSplit.c in Sources */, + 27A92F170E349283006E7CF6 /* cuddSubsetHB.c in Sources */, + 27A92F180E349283006E7CF6 /* cuddSubsetSP.c in Sources */, + 27A92F190E349283006E7CF6 /* cuddSymmetry.c in Sources */, + 27A92F1A0E349283006E7CF6 /* cuddTable.c in Sources */, + 27A92F1B0E349283006E7CF6 /* cuddUtil.c in Sources */, + 27A92F1C0E349283006E7CF6 /* cuddWindow.c in Sources */, + 27A92F1D0E349283006E7CF6 /* cuddZddCount.c in Sources */, + 27A92F1E0E349283006E7CF6 /* cuddZddFuncs.c in Sources */, + 27A92F1F0E349283006E7CF6 /* cuddZddGroup.c in Sources */, + 27A92F200E349283006E7CF6 /* cuddZddIsop.c in Sources */, + 27A92F210E349283006E7CF6 /* cuddZddLin.c in Sources */, + 27A92F220E349283006E7CF6 /* cuddZddMisc.c in Sources */, + 27A92F230E349283006E7CF6 /* cuddZddPort.c in Sources */, + 27A92F240E349283006E7CF6 /* cuddZddReord.c in Sources */, + 27A92F250E349283006E7CF6 /* cuddZddSetop.c in Sources */, + 27A92F260E349283006E7CF6 /* cuddZddSymm.c in Sources */, + 27A92F270E349283006E7CF6 /* cuddZddUtil.c in Sources */, + 27A92F290E349283006E7CF6 /* dsdApi.c in Sources */, + 27A92F2A0E349283006E7CF6 /* dsdCheck.c in Sources */, + 27A92F2B0E349283006E7CF6 /* dsdLocal.c in Sources */, + 27A92F2C0E349283006E7CF6 /* dsdMan.c in Sources */, + 27A92F2D0E349283006E7CF6 /* dsdProc.c in Sources */, + 27A92F2E0E349283006E7CF6 /* dsdTree.c in Sources */, + 27A92F2F0E349283006E7CF6 /* epd.c in Sources */, + 27A92F300E349283006E7CF6 /* mtrBasic.c in Sources */, + 27A92F310E349283006E7CF6 /* mtrGroup.c in Sources */, + 27A92F320E349283006E7CF6 /* parseCore.c in Sources */, + 27A92F330E349283006E7CF6 /* parseEqn.c in Sources */, + 27A92F340E349283006E7CF6 /* parseStack.c in Sources */, + 27A92F350E349283006E7CF6 /* reoApi.c in Sources */, + 27A92F360E349283006E7CF6 /* reoCore.c in Sources */, + 27A92F370E349283006E7CF6 /* reoProfile.c in Sources */, + 27A92F380E349283006E7CF6 /* reoSift.c in Sources */, + 27A92F390E349283006E7CF6 /* reoSwap.c in Sources */, + 27A92F3A0E349283006E7CF6 /* reoTest.c in Sources */, + 27A92F3B0E349283006E7CF6 /* reoTransfer.c in Sources */, + 27A92F3C0E349283006E7CF6 /* reoUnits.c in Sources */, + 27A92F3E0E349283006E7CF6 /* aig_.c in Sources */, + 27A92F3F0E349283006E7CF6 /* aigCheck.c in Sources */, + 27A92F400E349283006E7CF6 /* aigDfs.c in Sources */, + 27A92F410E349283006E7CF6 /* aigFanout.c in Sources */, + 27A92F420E349283006E7CF6 /* aigMan.c in Sources */, + 27A92F430E349283006E7CF6 /* aigMem.c in Sources */, + 27A92F440E349283006E7CF6 /* aigMffc.c in Sources */, + 27A92F450E349283006E7CF6 /* aigObj.c in Sources */, + 27A92F460E349283006E7CF6 /* aigOper.c in Sources */, + 27A92F470E349283006E7CF6 /* aigOrder.c in Sources */, + 27A92F480E349283006E7CF6 /* aigPart.c in Sources */, + 27A92F490E349283006E7CF6 /* aigRepr.c in Sources */, + 27A92F4A0E349283006E7CF6 /* aigRet.c in Sources */, + 27A92F4B0E349283006E7CF6 /* aigScl.c in Sources */, + 27A92F4C0E349283006E7CF6 /* aigSeq.c in Sources */, + 27A92F4D0E349283006E7CF6 /* aigShow.c in Sources */, + 27A92F4E0E349283006E7CF6 /* aigTable.c in Sources */, + 27A92F4F0E349283006E7CF6 /* aigTime.c in Sources */, + 27A92F500E349283006E7CF6 /* aigTiming.c in Sources */, + 27A92F510E349283006E7CF6 /* aigTruth.c in Sources */, + 27A92F520E349283006E7CF6 /* aigTsim.c in Sources */, + 27A92F530E349283006E7CF6 /* aigUtil.c in Sources */, + 27A92F540E349283006E7CF6 /* aigWin.c in Sources */, + 27A92F550E349283006E7CF6 /* bar.c in Sources */, + 27A92F560E349283006E7CF6 /* bdc_.c in Sources */, + 27A92F570E349283006E7CF6 /* bdcCore.c in Sources */, + 27A92F580E349283006E7CF6 /* bdcDec.c in Sources */, + 27A92F590E349283006E7CF6 /* bdcTable.c in Sources */, + 27A92F5A0E349283006E7CF6 /* cnf_.c in Sources */, + 27A92F5B0E349283006E7CF6 /* cnfCore.c in Sources */, + 27A92F5C0E349283006E7CF6 /* cnfCut.c in Sources */, + 27A92F5D0E349283006E7CF6 /* cnfData.c in Sources */, + 27A92F5E0E349283006E7CF6 /* cnfMan.c in Sources */, + 27A92F5F0E349283006E7CF6 /* cnfMap.c in Sources */, + 27A92F600E349283006E7CF6 /* cnfPost.c in Sources */, + 27A92F610E349283006E7CF6 /* cnfUtil.c in Sources */, + 27A92F620E349283006E7CF6 /* cnfWrite.c in Sources */, + 27A92F630E349283006E7CF6 /* csw_.c in Sources */, + 27A92F640E349283006E7CF6 /* cswCore.c in Sources */, + 27A92F650E349283006E7CF6 /* cswCut.c in Sources */, + 27A92F660E349283006E7CF6 /* cswMan.c in Sources */, + 27A92F670E349283006E7CF6 /* cswTable.c in Sources */, + 27A92F680E349283006E7CF6 /* dar_.c in Sources */, + 27A92F690E349283006E7CF6 /* darBalance.c in Sources */, + 27A92F6A0E349283006E7CF6 /* darCore.c in Sources */, + 27A92F6B0E349283006E7CF6 /* darCut.c in Sources */, + 27A92F6C0E349283006E7CF6 /* darData.c in Sources */, + 27A92F6D0E349283006E7CF6 /* darLib.c in Sources */, + 27A92F6E0E349283006E7CF6 /* darMan.c in Sources */, + 27A92F6F0E349283006E7CF6 /* darPrec.c in Sources */, + 27A92F700E349283006E7CF6 /* darRefact.c in Sources */, + 27A92F710E349283006E7CF6 /* darResub.c in Sources */, + 27A92F720E349283006E7CF6 /* darScript.c in Sources */, + 27A92F730E349283006E7CF6 /* fra_.c in Sources */, + 27A92F740E349283006E7CF6 /* fraBmc.c in Sources */, + 27A92F750E349283006E7CF6 /* fraCec.c in Sources */, + 27A92F760E349283006E7CF6 /* fraClass.c in Sources */, + 27A92F770E349283006E7CF6 /* fraCnf.c in Sources */, + 27A92F780E349283006E7CF6 /* fraCore.c in Sources */, + 27A92F790E349283006E7CF6 /* fraImp.c in Sources */, + 27A92F7A0E349283006E7CF6 /* fraInd.c in Sources */, + 27A92F7B0E349283006E7CF6 /* fraLcr.c in Sources */, + 27A92F7C0E349283006E7CF6 /* fraMan.c in Sources */, + 27A92F7D0E349283006E7CF6 /* fraPart.c in Sources */, + 27A92F7E0E349283006E7CF6 /* fraSat.c in Sources */, + 27A92F7F0E349283006E7CF6 /* fraSec.c in Sources */, + 27A92F800E349283006E7CF6 /* fraSim.c in Sources */, + 27A92F820E349283006E7CF6 /* hop_.c in Sources */, + 27A92F830E349283006E7CF6 /* hopBalance.c in Sources */, + 27A92F840E349283006E7CF6 /* hopCheck.c in Sources */, + 27A92F850E349283006E7CF6 /* hopDfs.c in Sources */, + 27A92F860E349283006E7CF6 /* hopMan.c in Sources */, + 27A92F870E349283006E7CF6 /* hopMem.c in Sources */, + 27A92F880E349283006E7CF6 /* hopObj.c in Sources */, + 27A92F890E349283006E7CF6 /* hopOper.c in Sources */, + 27A92F8A0E349283006E7CF6 /* hopTable.c in Sources */, + 27A92F8B0E349283006E7CF6 /* hopUtil.c in Sources */, + 27A92F8C0E349283006E7CF6 /* ioaReadAig.c in Sources */, + 27A92F8D0E349283006E7CF6 /* ioaUtil.c in Sources */, + 27A92F8E0E349283006E7CF6 /* ioaWriteAig.c in Sources */, + 27A92F8F0E349283006E7CF6 /* ivy_.c in Sources */, + 27A92F900E349283006E7CF6 /* ivyBalance.c in Sources */, + 27A92F910E349283006E7CF6 /* ivyCanon.c in Sources */, + 27A92F920E349283006E7CF6 /* ivyCheck.c in Sources */, + 27A92F930E349283006E7CF6 /* ivyCut.c in Sources */, + 27A92F940E349283006E7CF6 /* ivyCutTrav.c in Sources */, + 27A92F950E349283006E7CF6 /* ivyDfs.c in Sources */, + 27A92F960E349283006E7CF6 /* ivyDsd.c in Sources */, + 27A92F970E349283006E7CF6 /* ivyFanout.c in Sources */, + 27A92F980E349283006E7CF6 /* ivyFastMap.c in Sources */, + 27A92F990E349283006E7CF6 /* ivyFraig.c in Sources */, + 27A92F9A0E349283006E7CF6 /* ivyHaig.c in Sources */, + 27A92F9B0E349283006E7CF6 /* ivyMan.c in Sources */, + 27A92F9C0E349283006E7CF6 /* ivyMem.c in Sources */, + 27A92F9D0E349283006E7CF6 /* ivyMulti.c in Sources */, + 27A92F9F0E349283006E7CF6 /* ivyObj.c in Sources */, + 27A92FA00E349283006E7CF6 /* ivyOper.c in Sources */, + 27A92FA10E349283006E7CF6 /* ivyResyn.c in Sources */, + 27A92FA20E349283006E7CF6 /* ivyRwr.c in Sources */, + 27A92FA40E349283006E7CF6 /* ivySeq.c in Sources */, + 27A92FA50E349283006E7CF6 /* ivyShow.c in Sources */, + 27A92FA60E349283006E7CF6 /* ivyTable.c in Sources */, + 27A92FA70E349283006E7CF6 /* ivyUtil.c in Sources */, + 27A92FA80E349283006E7CF6 /* cloud.c in Sources */, + 27A92FA90E349283006E7CF6 /* kit_.c in Sources */, + 27A92FAA0E349283006E7CF6 /* kitAig.c in Sources */, + 27A92FAB0E349283006E7CF6 /* kitBdd.c in Sources */, + 27A92FAC0E349283006E7CF6 /* kitCloud.c in Sources */, + 27A92FAD0E349283006E7CF6 /* kitDsd.c in Sources */, + 27A92FAE0E349283006E7CF6 /* kitFactor.c in Sources */, + 27A92FAF0E349283006E7CF6 /* kitGraph.c in Sources */, + 27A92FB00E349283006E7CF6 /* kitHop.c in Sources */, + 27A92FB10E349283006E7CF6 /* kitIsop.c in Sources */, + 27A92FB20E349283006E7CF6 /* kitSop.c in Sources */, + 27A92FB30E349283006E7CF6 /* kitTruth.c in Sources */, + 27A92FB40E349283006E7CF6 /* mem.c in Sources */, + 27A92FB50E349283006E7CF6 /* rwtDec.c in Sources */, + 27A92FB60E349283006E7CF6 /* rwtMan.c in Sources */, + 27A92FB70E349283006E7CF6 /* rwtUtil.c in Sources */, + 27A92FB80E349283006E7CF6 /* fpga.c in Sources */, + 27A92FB90E349283006E7CF6 /* fpgaCore.c in Sources */, + 27A92FBA0E349283006E7CF6 /* fpgaCreate.c in Sources */, + 27A92FBB0E349283006E7CF6 /* fpgaCut.c in Sources */, + 27A92FBC0E349283006E7CF6 /* fpgaCutUtils.c in Sources */, + 27A92FBD0E349283006E7CF6 /* fpgaFanout.c in Sources */, + 27A92FBE0E349283006E7CF6 /* fpgaGENERIC.c in Sources */, + 27A92FBF0E349283006E7CF6 /* fpgaLib.c in Sources */, + 27A92FC00E349283006E7CF6 /* fpgaMatch.c in Sources */, + 27A92FC10E349283006E7CF6 /* fpgaSwitch.c in Sources */, + 27A92FC20E349283006E7CF6 /* fpgaTime.c in Sources */, + 27A92FC30E349283006E7CF6 /* fpgaTruth.c in Sources */, + 27A92FC40E349283006E7CF6 /* fpgaUtils.c in Sources */, + 27A92FC50E349283006E7CF6 /* fpgaVec.c in Sources */, + 27A92FC60E349283006E7CF6 /* if_.c in Sources */, + 27A92FC70E349283006E7CF6 /* ifCore.c in Sources */, + 27A92FC80E349283006E7CF6 /* ifCut.c in Sources */, + 27A92FC90E349283006E7CF6 /* ifMan.c in Sources */, + 27A92FCA0E349283006E7CF6 /* ifMap.c in Sources */, + 27A92FCB0E349283006E7CF6 /* ifReduce.c in Sources */, + 27A92FCC0E349283006E7CF6 /* ifSeq.c in Sources */, + 27A92FCD0E349283006E7CF6 /* ifTime.c in Sources */, + 27A92FCE0E349283006E7CF6 /* ifTruth.c in Sources */, + 27A92FCF0E349283006E7CF6 /* ifUtil.c in Sources */, + 27A92FD00E349283006E7CF6 /* mapper.c in Sources */, + 27A92FD10E349283006E7CF6 /* mapperCanon.c in Sources */, + 27A92FD20E349283006E7CF6 /* mapperCore.c in Sources */, + 27A92FD30E349283006E7CF6 /* mapperCreate.c in Sources */, + 27A92FD40E349283006E7CF6 /* mapperCut.c in Sources */, + 27A92FD50E349283006E7CF6 /* mapperCutUtils.c in Sources */, + 27A92FD60E349283006E7CF6 /* mapperFanout.c in Sources */, + 27A92FD70E349283006E7CF6 /* mapperGENERIC.c in Sources */, + 27A92FD80E349283006E7CF6 /* mapperLib.c in Sources */, + 27A92FD90E349283006E7CF6 /* mapperMatch.c in Sources */, + 27A92FDA0E349283006E7CF6 /* mapperRefs.c in Sources */, + 27A92FDB0E349283006E7CF6 /* mapperSuper.c in Sources */, + 27A92FDC0E349283006E7CF6 /* mapperSwitch.c in Sources */, + 27A92FDD0E349283006E7CF6 /* mapperTable.c in Sources */, + 27A92FDE0E349283006E7CF6 /* mapperTime.c in Sources */, + 27A92FDF0E349283006E7CF6 /* mapperTree.c in Sources */, + 27A92FE00E349283006E7CF6 /* mapperTruth.c in Sources */, + 27A92FE10E349283006E7CF6 /* mapperUtils.c in Sources */, + 27A92FE20E349283006E7CF6 /* mapperVec.c in Sources */, + 27A92FE30E349283006E7CF6 /* mio.c in Sources */, + 27A92FE40E349283006E7CF6 /* mioApi.c in Sources */, + 27A92FE50E349283006E7CF6 /* mioFunc.c in Sources */, + 27A92FE60E349283006E7CF6 /* mioGENERIC.c in Sources */, + 27A92FE70E349283006E7CF6 /* mioRead.c in Sources */, + 27A92FE80E349283006E7CF6 /* mioUtils.c in Sources */, + 27A92FE90E349283006E7CF6 /* super.c in Sources */, + 27A92FEA0E349283006E7CF6 /* superAnd.c in Sources */, + 27A92FEB0E349283006E7CF6 /* superGate.c in Sources */, + 27A92FEC0E349283006E7CF6 /* superGENERIC.c in Sources */, + 27A92FED0E349283006E7CF6 /* superWrite.c in Sources */, + 27A92FEE0E349283006E7CF6 /* abc_.c in Sources */, + 27A92FEF0E349283006E7CF6 /* abcAig.c in Sources */, + 27A92FF00E349283006E7CF6 /* abcBlifMv.c in Sources */, + 27A92FF10E349283006E7CF6 /* abcCheck.c in Sources */, + 27A92FF20E349283006E7CF6 /* abcDfs.c in Sources */, + 27A92FF30E349283006E7CF6 /* abcFanio.c in Sources */, + 27A92FF40E349283006E7CF6 /* abcFunc.c in Sources */, + 27A92FF50E349283006E7CF6 /* abcHie.c in Sources */, + 27A92FF60E349283006E7CF6 /* abcLatch.c in Sources */, + 27A92FF70E349283006E7CF6 /* abcLib.c in Sources */, + 27A92FF80E349283006E7CF6 /* abcMinBase.c in Sources */, + 27A92FF90E349283006E7CF6 /* abcNames.c in Sources */, + 27A92FFA0E349283006E7CF6 /* abcNetlist.c in Sources */, + 27A92FFB0E349283006E7CF6 /* abcNtk.c in Sources */, + 27A92FFC0E349283006E7CF6 /* abcObj.c in Sources */, + 27A92FFD0E349283006E7CF6 /* abcRefs.c in Sources */, + 27A92FFE0E349283006E7CF6 /* abcShow.c in Sources */, + 27A92FFF0E349283006E7CF6 /* abcSop.c in Sources */, + 27A930000E349283006E7CF6 /* abcUtil.c in Sources */, + 27A930010E349283006E7CF6 /* abc.c in Sources */, + 27A930020E349283006E7CF6 /* abc_.c in Sources */, + 27A930030E349283006E7CF6 /* abcAttach.c in Sources */, + 27A930040E349283006E7CF6 /* abcAuto.c in Sources */, + 27A930050E349283006E7CF6 /* abcBalance.c in Sources */, + 27A930060E349283006E7CF6 /* abcBmc.c in Sources */, + 27A930070E349283006E7CF6 /* abcCas.c in Sources */, + 27A930080E349283006E7CF6 /* abcClpBdd.c in Sources */, + 27A930090E349283006E7CF6 /* abcClpSop.c in Sources */, + 27A9300A0E349283006E7CF6 /* abcCut.c in Sources */, + 27A9300B0E349283006E7CF6 /* abcDar.c in Sources */, + 27A9300C0E349283006E7CF6 /* abcDebug.c in Sources */, + 27A9300D0E349283006E7CF6 /* abcDress.c in Sources */, + 27A9300E0E349283006E7CF6 /* abcDsd.c in Sources */, + 27A9300F0E349283006E7CF6 /* abcEspresso.c in Sources */, + 27A930100E349283006E7CF6 /* abcExtract.c in Sources */, + 27A930110E349283006E7CF6 /* abcFpga.c in Sources */, + 27A930120E349283006E7CF6 /* abcFpgaFast.c in Sources */, + 27A930130E349283006E7CF6 /* abcFraig.c in Sources */, + 27A930140E349283006E7CF6 /* abcFxu.c in Sources */, + 27A930150E349283006E7CF6 /* abcGen.c in Sources */, + 27A930160E349283006E7CF6 /* abcHaig.c in Sources */, + 27A930170E349283006E7CF6 /* abcIf.c in Sources */, + 27A930180E349283006E7CF6 /* abcIvy.c in Sources */, + 27A930190E349283006E7CF6 /* abcLut.c in Sources */, + 27A9301A0E349283006E7CF6 /* abcMap.c in Sources */, + 27A9301B0E349283006E7CF6 /* abcMeasure.c in Sources */, + 27A9301C0E349283006E7CF6 /* abcMini.c in Sources */, + 27A9301D0E349283006E7CF6 /* abcMiter.c in Sources */, + 27A9301E0E349283006E7CF6 /* abcMulti.c in Sources */, + 27A9301F0E349283006E7CF6 /* abcMv.c in Sources */, + 27A930200E349283006E7CF6 /* abcNtbdd.c in Sources */, + 27A930210E349283006E7CF6 /* abcOdc.c in Sources */, + 27A930220E349283006E7CF6 /* abcOrder.c in Sources */, + 27A930230E349283006E7CF6 /* abcPart.c in Sources */, + 27A930250E349283006E7CF6 /* abcPrint.c in Sources */, + 27A930260E349283006E7CF6 /* abcProve.c in Sources */, + 27A930270E349283006E7CF6 /* abcQbf.c in Sources */, + 27A930280E349283006E7CF6 /* abcQuant.c in Sources */, + 27A930290E349283006E7CF6 /* abcRec.c in Sources */, + 27A9302A0E349283006E7CF6 /* abcReconv.c in Sources */, + 27A9302B0E349283006E7CF6 /* abcRefactor.c in Sources */, + 27A9302C0E349283006E7CF6 /* abcRenode.c in Sources */, + 27A9302D0E349283006E7CF6 /* abcReorder.c in Sources */, + 27A9302E0E349283006E7CF6 /* abcRestruct.c in Sources */, + 27A9302F0E349283006E7CF6 /* abcResub.c in Sources */, + 27A930300E349283006E7CF6 /* abcRewrite.c in Sources */, + 27A930310E349283006E7CF6 /* abcRr.c in Sources */, + 27A930320E349283006E7CF6 /* abcSat.c in Sources */, + 27A930330E349283006E7CF6 /* abcStrash.c in Sources */, + 27A930340E349283006E7CF6 /* abcSweep.c in Sources */, + 27A930350E349283006E7CF6 /* abcSymm.c in Sources */, + 27A930360E349283006E7CF6 /* abcTiming.c in Sources */, + 27A930370E349283006E7CF6 /* abcUnate.c in Sources */, + 27A930380E349283006E7CF6 /* abcUnreach.c in Sources */, + 27A930390E349283006E7CF6 /* abcVerify.c in Sources */, + 27A9303A0E349283006E7CF6 /* abcXsim.c in Sources */, + 27A9303B0E349283006E7CF6 /* cmd.c in Sources */, + 27A9303C0E349283006E7CF6 /* cmdAlias.c in Sources */, + 27A9303D0E349283006E7CF6 /* cmdApi.c in Sources */, + 27A9303E0E349283006E7CF6 /* cmdFlag.c in Sources */, + 27A9303F0E349283006E7CF6 /* cmdHist.c in Sources */, + 27A930400E349283006E7CF6 /* cmdUtils.c in Sources */, + 27A930410E349283006E7CF6 /* io.c in Sources */, + 27A930420E349283006E7CF6 /* io_.c in Sources */, + 27A930430E349283006E7CF6 /* ioReadAiger.c in Sources */, + 27A930440E349283006E7CF6 /* ioReadBaf.c in Sources */, + 27A930450E349283006E7CF6 /* ioReadBench.c in Sources */, + 27A930460E349283006E7CF6 /* ioReadBlif.c in Sources */, + 27A930470E349283006E7CF6 /* ioReadBlifAig.c in Sources */, + 27A930480E349283006E7CF6 /* ioReadBlifMv.c in Sources */, + 27A930490E349283006E7CF6 /* ioReadDsd.c in Sources */, + 27A9304A0E349283006E7CF6 /* ioReadEdif.c in Sources */, + 27A9304B0E349283006E7CF6 /* ioReadEqn.c in Sources */, + 27A9304C0E349283006E7CF6 /* ioReadPla.c in Sources */, + 27A9304D0E349283006E7CF6 /* ioReadVerilog.c in Sources */, + 27A9304E0E349283006E7CF6 /* ioUtil.c in Sources */, + 27A9304F0E349283006E7CF6 /* ioWriteAiger.c in Sources */, + 27A930500E349283006E7CF6 /* ioWriteBaf.c in Sources */, + 27A930510E349283006E7CF6 /* ioWriteBench.c in Sources */, + 27A930520E349283006E7CF6 /* ioWriteBlif.c in Sources */, + 27A930530E349283006E7CF6 /* ioWriteBlifMv.c in Sources */, + 27A930540E349283006E7CF6 /* ioWriteCnf.c in Sources */, + 27A930550E349283006E7CF6 /* ioWriteDot.c in Sources */, + 27A930560E349283006E7CF6 /* ioWriteEqn.c in Sources */, + 27A930570E349283006E7CF6 /* ioWriteGml.c in Sources */, + 27A930580E349283006E7CF6 /* ioWriteList.c in Sources */, + 27A930590E349283006E7CF6 /* ioWritePla.c in Sources */, + 27A9305A0E349283006E7CF6 /* ioWriteVerilog.c in Sources */, + 27A9305B0E349283006E7CF6 /* libSupport.c in Sources */, + 27A9305C0E349283006E7CF6 /* main.c in Sources */, + 27A9305D0E349283006E7CF6 /* mainFrame.c in Sources */, + 27A9305E0E349283006E7CF6 /* mainInit.c in Sources */, + 27A9305F0E349283006E7CF6 /* mainUtils.c in Sources */, + 27A930610E349283006E7CF6 /* ver_.c in Sources */, + 27A930620E349283006E7CF6 /* verCore.c in Sources */, + 27A930630E349283006E7CF6 /* verFormula.c in Sources */, + 27A930640E349283006E7CF6 /* verParse.c in Sources */, + 27A930650E349283006E7CF6 /* verStream.c in Sources */, + 27A930660E349283006E7CF6 /* verWords.c in Sources */, + 27A930670E349283006E7CF6 /* cofactor.c in Sources */, + 27A930680E349283006E7CF6 /* cols.c in Sources */, + 27A930690E349283006E7CF6 /* compl.c in Sources */, + 27A9306A0E349283006E7CF6 /* contain.c in Sources */, + 27A9306B0E349283006E7CF6 /* cubehack.c in Sources */, + 27A9306C0E349283006E7CF6 /* cubestr.c in Sources */, + 27A9306D0E349283006E7CF6 /* cvrin.c in Sources */, + 27A9306E0E349283006E7CF6 /* cvrm.c in Sources */, + 27A9306F0E349283006E7CF6 /* cvrmisc.c in Sources */, + 27A930700E349283006E7CF6 /* cvrout.c in Sources */, + 27A930710E349283006E7CF6 /* dominate.c in Sources */, + 27A930720E349283006E7CF6 /* equiv.c in Sources */, + 27A930730E349283006E7CF6 /* espresso.c in Sources */, + 27A930740E349283006E7CF6 /* essen.c in Sources */, + 27A930750E349283006E7CF6 /* exact.c in Sources */, + 27A930760E349283006E7CF6 /* expand.c in Sources */, + 27A930770E349283006E7CF6 /* gasp.c in Sources */, + 27A930780E349283006E7CF6 /* gimpel.c in Sources */, + 27A930790E349283006E7CF6 /* globals.c in Sources */, + 27A9307A0E349283006E7CF6 /* hack.c in Sources */, + 27A9307B0E349283006E7CF6 /* indep.c in Sources */, + 27A9307C0E349283006E7CF6 /* irred.c in Sources */, + 27A9307E0E349283006E7CF6 /* map.c in Sources */, + 27A9307F0E349283006E7CF6 /* matrix.c in Sources */, + 27A930800E349283006E7CF6 /* mincov.c in Sources */, + 27A930810E349283006E7CF6 /* opo.c in Sources */, + 27A930820E349283006E7CF6 /* pair.c in Sources */, + 27A930830E349283006E7CF6 /* part.c in Sources */, + 27A930840E349283006E7CF6 /* primes.c in Sources */, + 27A930850E349283006E7CF6 /* reduce.c in Sources */, + 27A930860E349283006E7CF6 /* rows.c in Sources */, + 27A930870E349283006E7CF6 /* set.c in Sources */, + 27A930880E349283006E7CF6 /* setc.c in Sources */, + 27A930890E349283006E7CF6 /* sharp.c in Sources */, + 27A9308A0E349283006E7CF6 /* sminterf.c in Sources */, + 27A9308B0E349283006E7CF6 /* solution.c in Sources */, + 27A9308C0E349283006E7CF6 /* sparse.c in Sources */, + 27A9308E0E349283006E7CF6 /* verify.c in Sources */, + 27A9308F0E349283006E7CF6 /* extraBddAuto.c in Sources */, + 27A930900E349283006E7CF6 /* extraBddCas.c in Sources */, + 27A930910E349283006E7CF6 /* extraBddKmap.c in Sources */, + 27A930920E349283006E7CF6 /* extraBddMisc.c in Sources */, + 27A930930E349283006E7CF6 /* extraBddSymm.c in Sources */, + 27A930940E349283006E7CF6 /* extraBddUnate.c in Sources */, + 27A930950E349283006E7CF6 /* extraUtilBitMatrix.c in Sources */, + 27A930960E349283006E7CF6 /* extraUtilCanon.c in Sources */, + 27A930970E349283006E7CF6 /* extraUtilFile.c in Sources */, + 27A930980E349283006E7CF6 /* extraUtilMemory.c in Sources */, + 27A930990E349283006E7CF6 /* extraUtilMisc.c in Sources */, + 27A9309A0E349283006E7CF6 /* extraUtilProgress.c in Sources */, + 27A9309B0E349283006E7CF6 /* extraUtilReader.c in Sources */, + 27A9309C0E349283006E7CF6 /* extraUtilTruth.c in Sources */, + 27A9309D0E349283006E7CF6 /* extraUtilUtil.c in Sources */, + 27A9309E0E349283006E7CF6 /* mvc.c in Sources */, + 27A9309F0E349283006E7CF6 /* mvcApi.c in Sources */, + 27A930A00E349283006E7CF6 /* mvcCompare.c in Sources */, + 27A930A10E349283006E7CF6 /* mvcContain.c in Sources */, + 27A930A20E349283006E7CF6 /* mvcCover.c in Sources */, + 27A930A30E349283006E7CF6 /* mvcCube.c in Sources */, + 27A930A40E349283006E7CF6 /* mvcDivide.c in Sources */, + 27A930A50E349283006E7CF6 /* mvcDivisor.c in Sources */, + 27A930A60E349283006E7CF6 /* mvcList.c in Sources */, + 27A930A70E349283006E7CF6 /* mvcLits.c in Sources */, + 27A930A80E349283006E7CF6 /* mvcMan.c in Sources */, + 27A930A90E349283006E7CF6 /* mvcOpAlg.c in Sources */, + 27A930AA0E349283006E7CF6 /* mvcOpBool.c in Sources */, + 27A930AB0E349283006E7CF6 /* mvcPrint.c in Sources */, + 27A930AC0E349283006E7CF6 /* mvcSort.c in Sources */, + 27A930AD0E349283006E7CF6 /* mvcUtils.c in Sources */, + 27A930AE0E349283006E7CF6 /* nmApi.c in Sources */, + 27A930AF0E349283006E7CF6 /* nmTable.c in Sources */, + 27A930B00E349283006E7CF6 /* st.c in Sources */, + 27A930B10E349283006E7CF6 /* stmm.c in Sources */, + 2717FCAD0E3852830038296D /* unate.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1DEB928608733DD80010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = abc; + }; + name = Debug; + }; + 1DEB928708733DD80010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_MODEL_TUNING = G5; + INSTALL_PATH = /usr/local/bin; + PRODUCT_NAME = abc; + }; + name = Release; + }; + 1DEB928A08733DD80010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ADDITIONAL_SDKS = ""; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_C_LANGUAGE_STANDARD = "compiler-default"; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_VERSION = ""; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = macosx10.5; + }; + name = Debug; + }; + 1DEB928B08733DD80010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = macosx10.5; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget "abc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB928608733DD80010E9CD /* Debug */, + 1DEB928708733DD80010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "abc" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB928A08733DD80010E9CD /* Debug */, + 1DEB928B08733DD80010E9CD /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; +} diff --git a/abc70930/src/abc.xcodeproj/raiyan.pbxuser b/abc70930/src/abc.xcodeproj/raiyan.pbxuser new file mode 100644 index 00000000..1de27f67 --- /dev/null +++ b/abc70930/src/abc.xcodeproj/raiyan.pbxuser @@ -0,0 +1,1622 @@ +// !$*UTF8*$! +{ + 08FB7793FE84155DC02AAC07 /* Project object */ = { + activeBuildConfigurationName = Debug; + activeExecutable = 27A92B5E0E34922E006E7CF6 /* abc */; + activeTarget = 8DD76FA90486AB0100D96B5E /* abc */; + addToTargets = ( + 8DD76FA90486AB0100D96B5E /* abc */, + ); + breakpoints = ( + 274041060E38C0DB00DC6F18 /* main.c:51 */, + 274041130E38D01D00DC6F18 /* mainUtils.c:78 */, + ); + codeSenseManager = 27A92B6A0E34923D006E7CF6 /* Code sense */; + executables = ( + 27A92B5E0E34922E006E7CF6 /* abc */, + ); + perUserDictionary = { + PBXConfiguration.PBXFileTableDataSource3.PBXErrorsWarningsDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXErrorsWarningsDataSource_LocationID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 300, + 724, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXErrorsWarningsDataSource_TypeID, + PBXErrorsWarningsDataSource_MessageID, + PBXErrorsWarningsDataSource_LocationID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 22, + 300, + 722, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXExecutablesDataSource_ActiveFlagID, + PBXExecutablesDataSource_NameID, + PBXExecutablesDataSource_CommentsID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 834, + 20, + 48, + 43, + 43, + 20, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXFileDataSource_FiletypeID, + PBXFileDataSource_Filename_ColumnID, + PBXFileDataSource_Built_ColumnID, + PBXFileDataSource_ObjectSize_ColumnID, + PBXFileDataSource_Errors_ColumnID, + PBXFileDataSource_Warnings_ColumnID, + PBXFileDataSource_Target_ColumnID, + ); + }; + PBXConfiguration.PBXFileTableDataSource3.PBXSymbolsDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXSymbolsDataSource_SymbolNameID; + PBXFileTableDataSourceColumnWidthsKey = ( + 16, + 200, + 50, + 774, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXSymbolsDataSource_SymbolTypeIconID, + PBXSymbolsDataSource_SymbolNameID, + PBXSymbolsDataSource_SymbolTypeID, + PBXSymbolsDataSource_ReferenceNameID, + ); + }; + PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 794, + 60, + 20, + 48, + 43, + 43, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXFileDataSource_FiletypeID, + PBXFileDataSource_Filename_ColumnID, + PBXTargetDataSource_PrimaryAttribute, + PBXFileDataSource_Built_ColumnID, + PBXFileDataSource_ObjectSize_ColumnID, + PBXFileDataSource_Errors_ColumnID, + PBXFileDataSource_Warnings_ColumnID, + ); + }; + PBXPerProjectTemplateStateSaveDate = 238637327; + PBXWorkspaceStateSaveDate = 238637327; + }; + perUserProjectItems = { + 2717FC7F0E3843AC0038296D /* PBXTextBookmark */ = 2717FC7F0E3843AC0038296D /* PBXTextBookmark */; + 2717FC810E3843AC0038296D /* PBXTextBookmark */ = 2717FC810E3843AC0038296D /* PBXTextBookmark */; + 2717FC820E3843AC0038296D /* PBXTextBookmark */ = 2717FC820E3843AC0038296D /* PBXTextBookmark */; + 2717FC830E3843AC0038296D /* PBXTextBookmark */ = 2717FC830E3843AC0038296D /* PBXTextBookmark */; + 2717FC840E3843AC0038296D /* PBXTextBookmark */ = 2717FC840E3843AC0038296D /* PBXTextBookmark */; + 2717FC850E3843AC0038296D /* PBXTextBookmark */ = 2717FC850E3843AC0038296D /* PBXTextBookmark */; + 2717FC870E3843AC0038296D /* PBXTextBookmark */ = 2717FC870E3843AC0038296D /* PBXTextBookmark */; + 2717FC890E3843AC0038296D /* PBXTextBookmark */ = 2717FC890E3843AC0038296D /* PBXTextBookmark */; + 2717FC8B0E3843AC0038296D /* PBXTextBookmark */ = 2717FC8B0E3843AC0038296D /* PBXTextBookmark */; + 2717FC8D0E3843AC0038296D /* PBXTextBookmark */ = 2717FC8D0E3843AC0038296D /* PBXTextBookmark */; + 2717FC8E0E3843AC0038296D /* PBXTextBookmark */ = 2717FC8E0E3843AC0038296D /* PBXTextBookmark */; + 2717FC8F0E3843AC0038296D /* PBXTextBookmark */ = 2717FC8F0E3843AC0038296D /* PBXTextBookmark */; + 2717FC900E3843AC0038296D /* PBXTextBookmark */ = 2717FC900E3843AC0038296D /* PBXTextBookmark */; + 2717FC930E3843AC0038296D /* PBXTextBookmark */ = 2717FC930E3843AC0038296D /* PBXTextBookmark */; + 2717FCA20E3852600038296D /* PBXTextBookmark */ = 2717FCA20E3852600038296D /* PBXTextBookmark */; + 2717FCA30E3852600038296D /* PBXTextBookmark */ = 2717FCA30E3852600038296D /* PBXTextBookmark */; + 2717FCA90E3852600038296D /* PBXTextBookmark */ = 2717FCA90E3852600038296D /* PBXTextBookmark */; + 2717FCB70E3854530038296D /* PBXTextBookmark */ = 2717FCB70E3854530038296D /* PBXTextBookmark */; + 2717FCB80E3854530038296D /* PBXTextBookmark */ = 2717FCB80E3854530038296D /* PBXTextBookmark */; + 2717FCBD0E3854530038296D /* PBXTextBookmark */ = 2717FCBD0E3854530038296D /* PBXTextBookmark */; + 2717FCBE0E3854530038296D /* PBXTextBookmark */ = 2717FCBE0E3854530038296D /* PBXTextBookmark */; + 2717FCC00E3854530038296D /* PBXTextBookmark */ = 2717FCC00E3854530038296D /* PBXTextBookmark */; + 2717FCD10E38569B0038296D /* PBXTextBookmark */ = 2717FCD10E38569B0038296D /* PBXTextBookmark */; + 2717FCD20E38569B0038296D /* PBXTextBookmark */ = 2717FCD20E38569B0038296D /* PBXTextBookmark */; + 2717FCD30E38569B0038296D /* PBXTextBookmark */ = 2717FCD30E38569B0038296D /* PBXTextBookmark */; + 2717FCD50E38569B0038296D /* PBXTextBookmark */ = 2717FCD50E38569B0038296D /* PBXTextBookmark */; + 2717FCD70E38569B0038296D /* PBXTextBookmark */ = 2717FCD70E38569B0038296D /* PBXTextBookmark */; + 2717FCE90E3857DC0038296D /* PBXTextBookmark */ = 2717FCE90E3857DC0038296D /* PBXTextBookmark */; + 2717FCEA0E3857DC0038296D /* PBXTextBookmark */ = 2717FCEA0E3857DC0038296D /* PBXTextBookmark */; + 2717FCEB0E3857DC0038296D /* PBXTextBookmark */ = 2717FCEB0E3857DC0038296D /* PBXTextBookmark */; + 2717FCED0E3857DC0038296D /* PBXTextBookmark */ = 2717FCED0E3857DC0038296D /* PBXTextBookmark */; + 2717FCEE0E3857DC0038296D /* PBXTextBookmark */ = 2717FCEE0E3857DC0038296D /* PBXTextBookmark */; + 2717FCEF0E3857DC0038296D /* PBXTextBookmark */ = 2717FCEF0E3857DC0038296D /* PBXTextBookmark */; + 2717FD140E3861B70038296D /* PBXTextBookmark */ = 2717FD140E3861B70038296D /* PBXTextBookmark */; + 2717FD150E3861B70038296D /* PBXTextBookmark */ = 2717FD150E3861B70038296D /* PBXTextBookmark */; + 2717FD190E3861B70038296D /* PBXTextBookmark */ = 2717FD190E3861B70038296D /* PBXTextBookmark */; + 2717FD1A0E3861B70038296D /* PBXTextBookmark */ = 2717FD1A0E3861B70038296D /* PBXTextBookmark */; + 2717FD1B0E3861B70038296D /* PBXTextBookmark */ = 2717FD1B0E3861B70038296D /* PBXTextBookmark */; + 273F099E0E387A1A00BA537B /* PBXTextBookmark */ = 273F099E0E387A1A00BA537B /* PBXTextBookmark */; + 273F099F0E387A1A00BA537B /* PBXTextBookmark */ = 273F099F0E387A1A00BA537B /* PBXTextBookmark */; + 273F09A00E387A1A00BA537B /* PBXTextBookmark */ = 273F09A00E387A1A00BA537B /* PBXTextBookmark */; + 273F09A10E387A1A00BA537B /* PBXTextBookmark */ = 273F09A10E387A1A00BA537B /* PBXTextBookmark */; + 273F09A20E387A1A00BA537B /* PBXTextBookmark */ = 273F09A20E387A1A00BA537B /* PBXTextBookmark */; + 273F09A40E387A1A00BA537B /* PBXTextBookmark */ = 273F09A40E387A1A00BA537B /* PBXTextBookmark */; + 273F09A50E387A1A00BA537B /* PBXTextBookmark */ = 273F09A50E387A1A00BA537B /* PBXTextBookmark */; + 274041210E38D50900DC6F18 /* PBXTextBookmark */ = 274041210E38D50900DC6F18 /* PBXTextBookmark */; + 274041230E38D50900DC6F18 /* PBXTextBookmark */ = 274041230E38D50900DC6F18 /* PBXTextBookmark */; + 274041280E38D50900DC6F18 /* PBXTextBookmark */ = 274041280E38D50900DC6F18 /* PBXTextBookmark */; + 2740412B0E38D50900DC6F18 /* PBXTextBookmark */ = 2740412B0E38D50900DC6F18 /* PBXTextBookmark */; + 274041720E38D73B00DC6F18 /* PBXTextBookmark */ = 274041720E38D73B00DC6F18 /* PBXTextBookmark */; + 2755FD8C0E35986F0031A656 /* PBXTextBookmark */ = 2755FD8C0E35986F0031A656 /* PBXTextBookmark */; + 2755FD8D0E35986F0031A656 /* PBXTextBookmark */ = 2755FD8D0E35986F0031A656 /* PBXTextBookmark */; + 2755FD8E0E35986F0031A656 /* PBXTextBookmark */ = 2755FD8E0E35986F0031A656 /* PBXTextBookmark */; + 2755FD8F0E35986F0031A656 /* PBXTextBookmark */ = 2755FD8F0E35986F0031A656 /* PBXTextBookmark */; + 2755FD900E35986F0031A656 /* PBXTextBookmark */ = 2755FD900E35986F0031A656 /* PBXTextBookmark */; + 2755FD910E35986F0031A656 /* PBXTextBookmark */ = 2755FD910E35986F0031A656 /* PBXTextBookmark */; + 2755FD920E35986F0031A656 /* PBXTextBookmark */ = 2755FD920E35986F0031A656 /* PBXTextBookmark */; + 2755FD930E35986F0031A656 /* PBXTextBookmark */ = 2755FD930E35986F0031A656 /* PBXTextBookmark */; + 2755FD950E35986F0031A656 /* PBXTextBookmark */ = 2755FD950E35986F0031A656 /* PBXTextBookmark */; + 2755FD960E35986F0031A656 /* PBXTextBookmark */ = 2755FD960E35986F0031A656 /* PBXTextBookmark */; + 2755FD970E35986F0031A656 /* PBXTextBookmark */ = 2755FD970E35986F0031A656 /* PBXTextBookmark */; + 2755FD980E35986F0031A656 /* PBXTextBookmark */ = 2755FD980E35986F0031A656 /* PBXTextBookmark */; + 2755FD990E35986F0031A656 /* PBXTextBookmark */ = 2755FD990E35986F0031A656 /* PBXTextBookmark */; + 2755FD9A0E35986F0031A656 /* PBXTextBookmark */ = 2755FD9A0E35986F0031A656 /* PBXTextBookmark */; + 2755FD9B0E35986F0031A656 /* PBXTextBookmark */ = 2755FD9B0E35986F0031A656 /* PBXTextBookmark */; + 2755FD9C0E35986F0031A656 /* PBXTextBookmark */ = 2755FD9C0E35986F0031A656 /* PBXTextBookmark */; + 2755FD9D0E35986F0031A656 /* PBXTextBookmark */ = 2755FD9D0E35986F0031A656 /* PBXTextBookmark */; + 2755FDCC0E3821400031A656 /* PBXTextBookmark */ = 2755FDCC0E3821400031A656 /* PBXTextBookmark */; + 2755FDCD0E3821400031A656 /* PBXTextBookmark */ = 2755FDCD0E3821400031A656 /* PBXTextBookmark */; + 2755FDD00E3821400031A656 /* PBXTextBookmark */ = 2755FDD00E3821400031A656 /* PBXTextBookmark */; + 2755FDD10E3821400031A656 /* PBXTextBookmark */ = 2755FDD10E3821400031A656 /* PBXTextBookmark */; + 27A930BD0E3494E8006E7CF6 /* PBXTextBookmark */ = 27A930BD0E3494E8006E7CF6 /* PBXTextBookmark */; + 27A930BE0E3494E8006E7CF6 /* PBXTextBookmark */ = 27A930BE0E3494E8006E7CF6 /* PBXTextBookmark */; + 27A930BF0E3494E8006E7CF6 /* PBXTextBookmark */ = 27A930BF0E3494E8006E7CF6 /* PBXTextBookmark */; + 27A930C10E3494E8006E7CF6 /* PBXTextBookmark */ = 27A930C10E3494E8006E7CF6 /* PBXTextBookmark */; + 27A930C30E3494E8006E7CF6 /* PBXTextBookmark */ = 27A930C30E3494E8006E7CF6 /* PBXTextBookmark */; + 27A930C40E3494E8006E7CF6 /* PBXTextBookmark */ = 27A930C40E3494E8006E7CF6 /* PBXTextBookmark */; + 27A930C50E3494E8006E7CF6 /* PBXTextBookmark */ = 27A930C50E3494E8006E7CF6 /* PBXTextBookmark */; + 27A930C60E3494E8006E7CF6 /* PBXTextBookmark */ = 27A930C60E3494E8006E7CF6 /* PBXTextBookmark */; + 27A930C70E3494E8006E7CF6 /* PBXTextBookmark */ = 27A930C70E3494E8006E7CF6 /* PBXTextBookmark */; + 27F2A0390E3951350056453A /* PBXTextBookmark */ = 27F2A0390E3951350056453A /* PBXTextBookmark */; + 27F2A03A0E3951350056453A /* PBXTextBookmark */ = 27F2A03A0E3951350056453A /* PBXTextBookmark */; + 27F2A03B0E3951350056453A /* PBXTextBookmark */ = 27F2A03B0E3951350056453A /* PBXTextBookmark */; + 27F2A0450E39514F0056453A /* PBXTextBookmark */ = 27F2A0450E39514F0056453A /* PBXTextBookmark */; + }; + sourceControlManager = 27A92B690E34923D006E7CF6 /* Source Control */; + userBuildSettings = { + }; + }; + 2717FC7F0E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E660E349283006E7CF6 /* nmTable.c */; + name = "nmTable.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 656; + vrLoc = 5092; + }; + 2717FC810E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92CE20E349281006E7CF6 /* hop.h */; + name = "hop.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 733; + vrLoc = 459; + }; + 2717FC820E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E740E349283006E7CF6 /* vec.h */; + name = "vec.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1041; + vrLoc = 788; + }; + 2717FC830E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E6E0E349283006E7CF6 /* leaks.h */; + name = "leaks.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1112; + vrLoc = 0; + }; + 2717FC840E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C820E349281006E7CF6 /* aig.h */; + name = "aig.h: 48"; + rLen = 49; + rLoc = 1390; + rType = 0; + vrLen = 1081; + vrLoc = 901; + }; + 2717FC850E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E6A0E349283006E7CF6 /* st.h */; + name = "st.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 462; + vrLoc = 0; + }; + 2717FC870E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92CE00E349281006E7CF6 /* cudd2.c */; + name = "cudd2.c: 61"; + rLen = 40; + rLoc = 1965; + rType = 0; + vrLen = 782; + vrLoc = 1516; + }; + 2717FC890E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E660E349283006E7CF6 /* nmTable.c */; + name = "nmTable.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 656; + vrLoc = 5092; + }; + 2717FC8B0E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DFA0E349282006E7CF6 /* temp.c */; + name = "temp.c: 14"; + rLen = 0; + rLoc = 511; + rType = 0; + vrLen = 574; + vrLoc = 0; + }; + 2717FC8D0E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92CE20E349281006E7CF6 /* hop.h */; + name = "hop.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 733; + vrLoc = 459; + }; + 2717FC8E0E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E740E349283006E7CF6 /* vec.h */; + name = "vec.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1041; + vrLoc = 788; + }; + 2717FC8F0E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E6E0E349283006E7CF6 /* leaks.h */; + name = "leaks.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1112; + vrLoc = 0; + }; + 2717FC900E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92CE00E349281006E7CF6 /* cudd2.c */; + name = "cudd2.c: 21"; + rLen = 0; + rLoc = 574; + rType = 0; + vrLen = 953; + vrLoc = 410; + }; + 2717FC930E3843AC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D060E349281006E7CF6 /* ivyMulti8.c */; + name = "ivyMulti8.c: 59"; + rLen = 9; + rLoc = 2159; + rType = 0; + vrLen = 810; + vrLoc = 1486; + }; + 2717FCA20E3852600038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D060E349281006E7CF6 /* ivyMulti8.c */; + name = "ivyMulti8.c: 9"; + rLen = 0; + rLoc = 274; + rType = 0; + vrLen = 718; + vrLoc = 0; + }; + 2717FCA30E3852600038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DF50E349282006E7CF6 /* mainFrame.c */; + name = "mainFrame.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1823; + vrLoc = 1175; + }; + 2717FCA90E3852600038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DF50E349282006E7CF6 /* mainFrame.c */; + name = "mainFrame.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1823; + vrLoc = 1175; + }; + 2717FCB70E3854530038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C2D0E349280006E7CF6 /* cuddDecomp.c */; + name = "cuddDecomp.c: 1402"; + rLen = 8; + rLoc = 42831; + rType = 0; + vrLen = 818; + vrLoc = 42435; + }; + 2717FCB80E3854530038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C310E349280006E7CF6 /* cuddGenCof.c */; + name = "cuddGenCof.c: 159"; + rLen = 8; + rLoc = 5663; + rType = 0; + vrLen = 658; + vrLoc = 5348; + }; + 2717FCBD0E3854530038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C2D0E349280006E7CF6 /* cuddDecomp.c */; + name = "cuddDecomp.c: 1402"; + rLen = 8; + rLoc = 42831; + rType = 0; + vrLen = 818; + vrLoc = 42435; + }; + 2717FCBE0E3854530038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C310E349280006E7CF6 /* cuddGenCof.c */; + name = "cuddGenCof.c: 159"; + rLen = 8; + rLoc = 5663; + rType = 0; + vrLen = 658; + vrLoc = 5348; + }; + 2717FCC00E3854530038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DB10E349282006E7CF6 /* abcPlace.c */; + name = "abcPlace.c: 32"; + rLen = 27; + rLoc = 893; + rType = 0; + vrLen = 566; + vrLoc = 677; + }; + 2717FCD10E38569B0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D0B0E349281006E7CF6 /* ivyRwrAlg.c */; + name = "ivyRwrAlg.c: 83"; + rLen = 65; + rLoc = 2940; + rType = 0; + vrLen = 658; + vrLoc = 2549; + }; + 2717FCD20E38569B0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DC80E349282006E7CF6 /* module.make */; + name = "module.make: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 716; + vrLoc = 478; + }; + 2717FCD30E38569B0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DB10E349282006E7CF6 /* abcPlace.c */; + name = "abcPlace.c: 24"; + rLen = 25; + rLoc = 576; + rType = 0; + vrLen = 683; + vrLoc = 258; + }; + 2717FCD50E38569B0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D0B0E349281006E7CF6 /* ivyRwrAlg.c */; + name = "ivyRwrAlg.c: 83"; + rLen = 65; + rLoc = 2940; + rType = 0; + vrLen = 658; + vrLoc = 2549; + }; + 2717FCD70E38569B0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DC80E349282006E7CF6 /* module.make */; + name = "module.make: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 716; + vrLoc = 478; + }; + 2717FCE90E3857DC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92BAF0E349280006E7CF6 /* resSim_old.c */; + name = "resSim_old.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 636; + vrLoc = 0; + }; + 2717FCEA0E3857DC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C010E349280006E7CF6 /* msatOrderJ.c */; + name = "msatOrderJ.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 776; + vrLoc = 0; + }; + 2717FCEB0E3857DC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D970E349282006E7CF6 /* abcCut.c */; + name = "abcCut.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 774; + vrLoc = 167; + }; + 2717FCED0E3857DC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92BAF0E349280006E7CF6 /* resSim_old.c */; + name = "resSim_old.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 636; + vrLoc = 0; + }; + 2717FCEE0E3857DC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C010E349280006E7CF6 /* msatOrderJ.c */; + name = "msatOrderJ.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 776; + vrLoc = 0; + }; + 2717FCEF0E3857DC0038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D970E349282006E7CF6 /* abcCut.c */; + name = "abcCut.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 774; + vrLoc = 167; + }; + 2717FD140E3861B70038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DF70E349282006E7CF6 /* mainInt.h */; + name = "mainInt.h: 28"; + rLen = 0; + rLoc = 832; + rType = 0; + vrLen = 810; + vrLoc = 465; + }; + 2717FD150E3861B70038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C580E349281006E7CF6 /* testcudd.c */; + name = "testcudd.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 782; + vrLoc = 0; + }; + 2717FD190E3861B70038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C580E349281006E7CF6 /* testcudd.c */; + name = "testcudd.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 782; + vrLoc = 0; + }; + 2717FD1A0E3861B70038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DF80E349282006E7CF6 /* mainUtils.c */; + name = "mainUtils.c: 78"; + rLen = 11; + rLoc = 2288; + rType = 0; + vrLen = 631; + vrLoc = 1749; + }; + 2717FD1B0E3861B70038296D /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DF40E349282006E7CF6 /* main.h */; + name = "main.h: 46"; + rLen = 0; + rLoc = 1511; + rType = 0; + vrLen = 773; + vrLoc = 843; + }; + 273F099E0E387A1A00BA537B /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DD50E349282006E7CF6 /* io.h */; + name = "io.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 837; + vrLoc = 677; + }; + 273F099F0E387A1A00BA537B /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D770E349282006E7CF6 /* abc.h */; + name = "abc.h: 37"; + rLen = 0; + rLoc = 931; + rType = 0; + vrLen = 914; + vrLoc = 1605; + }; + 273F09A00E387A1A00BA537B /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DFA0E349282006E7CF6 /* temp.c */; + name = "temp.c: 14"; + rLen = 0; + rLoc = 511; + rType = 0; + vrLen = 755; + vrLoc = 0; + }; + 273F09A10E387A1A00BA537B /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DF40E349282006E7CF6 /* main.h */; + name = "main.h: 48"; + rLen = 0; + rLoc = 1512; + rType = 0; + vrLen = 654; + vrLoc = 960; + }; + 273F09A20E387A1A00BA537B /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DF30E349282006E7CF6 /* main.c */; + name = "main.c: 50"; + rLen = 0; + rLoc = 1438; + rType = 0; + vrLen = 836; + vrLoc = 280; + }; + 273F09A40E387A1A00BA537B /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DD50E349282006E7CF6 /* io.h */; + name = "io.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 837; + vrLoc = 677; + }; + 273F09A50E387A1A00BA537B /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D770E349282006E7CF6 /* abc.h */; + name = "abc.h: 37"; + rLen = 0; + rLoc = 931; + rType = 0; + vrLen = 914; + vrLoc = 1605; + }; + 274041060E38C0DB00DC6F18 /* main.c:51 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = 27A92DF30E349282006E7CF6 /* main.c */; + functionName = "main()"; + hitCount = 1; + ignoreCount = 0; + lineNumber = 51; + location = abc; + modificationTime = 238637372.018766; + state = 1; + }; + 274041130E38D01D00DC6F18 /* mainUtils.c:78 */ = { + isa = PBXFileBreakpoint; + actions = ( + ); + breakpointStyle = 0; + continueAfterActions = 0; + countType = 0; + delayBeforeContinue = 0; + fileReference = 27A92DF80E349282006E7CF6 /* mainUtils.c */; + functionName = "Abc_UtilsGetUsersInput()"; + hitCount = 0; + ignoreCount = 0; + lineNumber = 78; + location = abc; + modificationTime = 238637369.74741; + state = 1; + }; + 274041210E38D50900DC6F18 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DF60E349282006E7CF6 /* mainInit.c */; + name = "mainInit.c: 61"; + rLen = 0; + rLoc = 2034; + rType = 0; + vrLen = 315; + vrLoc = 1989; + }; + 274041230E38D50900DC6F18 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E460E349282006E7CF6 /* extraUtilUtil.c */; + name = "extraUtilUtil.c: 254"; + rLen = 0; + rLoc = 6224; + rType = 0; + vrLen = 246; + vrLoc = 6804; + }; + 274041280E38D50900DC6F18 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DF60E349282006E7CF6 /* mainInit.c */; + name = "mainInit.c: 61"; + rLen = 0; + rLoc = 2034; + rType = 0; + vrLen = 315; + vrLoc = 1989; + }; + 2740412B0E38D50900DC6F18 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E460E349282006E7CF6 /* extraUtilUtil.c */; + name = "extraUtilUtil.c: 95"; + rLen = 0; + rLoc = 2480; + rType = 0; + vrLen = 316; + vrLoc = 2351; + }; + 274041720E38D73B00DC6F18 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DF30E349282006E7CF6 /* main.c */; + name = "main.c: 213"; + rLen = 0; + rLoc = 6094; + rType = 0; + vrLen = 601; + vrLoc = 1251; + }; + 2755FD8C0E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92B6E0E349280006E7CF6 /* abcCut.c */; + name = "abcCut.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 994; + vrLoc = 0; + }; + 2755FD8D0E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92B760E349280006E7CF6 /* cutMerge.c */; + name = "cutMerge.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 909; + vrLoc = 4785; + }; + 2755FD8E0E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D4D0E349281006E7CF6 /* mapper.h */; + name = "mapper.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 2101; + vrLoc = 8968; + }; + 2755FD8F0E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D4E0E349281006E7CF6 /* mapperCanon.c */; + name = "mapperCanon.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1369; + vrLoc = 0; + }; + 2755FD900E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D4F0E349281006E7CF6 /* mapperCore.c */; + name = "mapperCore.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1213; + vrLoc = 0; + }; + 2755FD910E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D500E349281006E7CF6 /* mapperCreate.c */; + name = "mapperCreate.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1387; + vrLoc = 0; + }; + 2755FD920E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D540E349281006E7CF6 /* mapperGENERIC.c */; + name = "mapperGENERIC.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1101; + vrLoc = 347; + }; + 2755FD930E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C100E349280006E7CF6 /* cas.h */; + name = "cas.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1347; + vrLoc = 573; + }; + 2755FD950E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E330E349282006E7CF6 /* unate.c */; + name = "unate.c: 187"; + rLen = 0; + rLoc = 2901; + rType = 0; + vrLen = 918; + vrLoc = 3741; + }; + 2755FD960E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92B6E0E349280006E7CF6 /* abcCut.c */; + name = "abcCut.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 994; + vrLoc = 0; + }; + 2755FD970E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92B760E349280006E7CF6 /* cutMerge.c */; + name = "cutMerge.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 909; + vrLoc = 4785; + }; + 2755FD980E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D4D0E349281006E7CF6 /* mapper.h */; + name = "mapper.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 2101; + vrLoc = 8968; + }; + 2755FD990E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D4E0E349281006E7CF6 /* mapperCanon.c */; + name = "mapperCanon.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1369; + vrLoc = 0; + }; + 2755FD9A0E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D4F0E349281006E7CF6 /* mapperCore.c */; + name = "mapperCore.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1213; + vrLoc = 0; + }; + 2755FD9B0E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D500E349281006E7CF6 /* mapperCreate.c */; + name = "mapperCreate.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1387; + vrLoc = 0; + }; + 2755FD9C0E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92D540E349281006E7CF6 /* mapperGENERIC.c */; + name = "mapperGENERIC.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1101; + vrLoc = 347; + }; + 2755FD9D0E35986F0031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C100E349280006E7CF6 /* cas.h */; + name = "cas.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1347; + vrLoc = 573; + }; + 2755FDCC0E3821400031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C110E349280006E7CF6 /* casCore.c */; + name = "casCore.c: 82"; + rLen = 0; + rLoc = 3380; + rType = 0; + vrLen = 870; + vrLoc = 2963; + }; + 2755FDCD0E3821400031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E600E349283006E7CF6 /* mvcUtils.c */; + name = "mvcUtils.c: 283"; + rLen = 5; + rLoc = 8137; + rType = 0; + vrLen = 868; + vrLoc = 7715; + }; + 2755FDD00E3821400031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C110E349280006E7CF6 /* casCore.c */; + name = "casCore.c: 82"; + rLen = 0; + rLoc = 3380; + rType = 0; + vrLen = 870; + vrLoc = 2963; + }; + 2755FDD10E3821400031A656 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E600E349283006E7CF6 /* mvcUtils.c */; + name = "mvcUtils.c: 283"; + rLen = 5; + rLoc = 8137; + rType = 0; + vrLen = 868; + vrLoc = 7715; + }; + 27A92B5E0E34922E006E7CF6 /* abc */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 1; + configStateDict = { + "PBXLSLaunchAction-0" = { + PBXLSLaunchAction = 0; + PBXLSLaunchStartAction = 1; + PBXLSLaunchStdioStyle = 2; + PBXLSLaunchStyle = 0; + class = PBXLSRunLaunchConfig; + commandLineArgs = ( + ); + displayName = "Executable Runner"; + environment = { + }; + identifier = com.apple.Xcode.launch.runConfig; + remoteHostInfo = ""; + startActionInfo = ""; + }; + "PBXLSLaunchAction-1" = { + PBXLSLaunchAction = 1; + PBXLSLaunchStartAction = 1; + PBXLSLaunchStdioStyle = 2; + PBXLSLaunchStyle = 0; + class = PBXGDB_LaunchConfig; + commandLineArgs = ( + ); + displayName = GDB; + environment = { + }; + identifier = com.apple.Xcode.launch.GDBMI_Config; + remoteHostInfo = ""; + startActionInfo = ""; + }; + }; + customDataFormattersEnabled = 1; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + dylibVariantSuffix = ""; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = abc; + savedGlobals = { + }; + sourceDirectories = ( + ); + variableFormatDictionary = { + }; + }; + 27A92B690E34923D006E7CF6 /* Source Control */ = { + isa = PBXSourceControlManager; + fallbackIsa = XCSourceControlManager; + isSCMEnabled = 0; + scmConfiguration = { + }; + }; + 27A92B6A0E34923D006E7CF6 /* Code sense */ = { + isa = PBXCodeSenseManager; + indexTemplatePath = ""; + }; + 27A92B6E0E349280006E7CF6 /* abcCut.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 7000}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 994}"; + }; + }; + 27A92B760E349280006E7CF6 /* cutMerge.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 9198}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{4785, 909}"; + }; + }; + 27A92BAF0E349280006E7CF6 /* resSim_old.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 7224}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 636}"; + }; + }; + 27A92BD50E349280006E7CF6 /* generic.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 896}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1021}"; + }; + }; + 27A92BFE0E349280006E7CF6 /* msatInt.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 4662}}"; + sepNavSelRange = "{1826, 28}"; + sepNavVisRange = "{1111, 1650}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92C010E349280006E7CF6 /* msatOrderJ.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 6608}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 776}"; + }; + }; + 27A92C100E349280006E7CF6 /* cas.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 910}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{573, 1347}"; + }; + }; + 27A92C110E349280006E7CF6 /* casCore.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 17360}}"; + sepNavSelRange = "{3380, 0}"; + sepNavVisRange = "{2963, 870}"; + }; + }; + 27A92C2D0E349280006E7CF6 /* cuddDecomp.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 30478}}"; + sepNavSelRange = "{42831, 8}"; + sepNavVisRange = "{42435, 818}"; + }; + }; + 27A92C310E349280006E7CF6 /* cuddGenCof.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 27202}}"; + sepNavSelRange = "{5663, 8}"; + sepNavVisRange = "{5348, 658}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92C580E349281006E7CF6 /* testcudd.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 13706}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 782}"; + }; + }; + 27A92C7F0E349281006E7CF6 /* generic.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 714}}"; + sepNavSelRange = "{468, 20}"; + sepNavVisRange = "{0, 1069}"; + }; + }; + 27A92C820E349281006E7CF6 /* aig.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 8358}}"; + sepNavSelRange = "{1390, 49}"; + sepNavVisRange = "{901, 1081}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92C850E349281006E7CF6 /* aigDfs.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 10176}}"; + sepNavSelRange = "{13510, 0}"; + sepNavVisRange = "{7567, 867}"; + }; + }; + 27A92C870E349281006E7CF6 /* aigMan.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 4606}}"; + sepNavSelRange = "{1348, 43}"; + sepNavVisRange = "{525, 1532}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92CE00E349281006E7CF6 /* cudd2.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 5068}}"; + sepNavSelRange = "{1965, 40}"; + sepNavVisRange = "{1516, 764}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92CE20E349281006E7CF6 /* hop.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1302, 4872}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{3631, 3108}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92CF60E349281006E7CF6 /* ivy.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 8372}}"; + sepNavSelRange = "{1388, 49}"; + sepNavVisRange = "{2070, 1848}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92D060E349281006E7CF6 /* ivyMulti8.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 6048}}"; + sepNavSelRange = "{274, 0}"; + sepNavVisRange = "{0, 718}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92D0B0E349281006E7CF6 /* ivyRwrAlg.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 5736}}"; + sepNavSelRange = "{2940, 65}"; + sepNavVisRange = "{2571, 969}"; + }; + }; + 27A92D3C0E349281006E7CF6 /* fpgaVec.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 5582}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1405}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92D4C0E349281006E7CF6 /* mapper.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 2604}}"; + sepNavSelRange = "{1397, 14}"; + sepNavVisRange = "{1106, 889}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92D4D0E349281006E7CF6 /* mapper.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 2744}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{8968, 2101}"; + }; + }; + 27A92D4E0E349281006E7CF6 /* mapperCanon.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 3780}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1369}"; + }; + }; + 27A92D4F0E349281006E7CF6 /* mapperCore.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 3220}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1213}"; + }; + }; + 27A92D500E349281006E7CF6 /* mapperCreate.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 8316}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1387}"; + }; + }; + 27A92D540E349281006E7CF6 /* mapperGENERIC.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 658}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{347, 1101}"; + }; + }; + 27A92D770E349282006E7CF6 /* abc.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1590, 12502}}"; + sepNavSelRange = "{26732, 0}"; + sepNavVisRange = "{12385, 1622}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92D860E349282006E7CF6 /* abcNtk.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 17094}}"; + sepNavSelRange = "{4224, 0}"; + sepNavVisRange = "{3910, 628}"; + }; + }; + 27A92D870E349282006E7CF6 /* abcObj.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 13636}}"; + sepNavSelRange = "{10191, 0}"; + sepNavVisRange = "{9836, 490}"; + }; + }; + 27A92D8E0E349282006E7CF6 /* abc.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 178332}}"; + sepNavSelRange = "{290028, 0}"; + sepNavVisRange = "{290021, 526}"; + }; + }; + 27A92D920E349282006E7CF6 /* abcBalance.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 8484}}"; + sepNavSelRange = "{2298, 0}"; + sepNavVisRange = "{1940, 604}"; + }; + }; + 27A92D970E349282006E7CF6 /* abcCut.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 8750}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{167, 774}"; + }; + }; + 27A92DB10E349282006E7CF6 /* abcPlace.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 3556}}"; + sepNavSelRange = "{576, 25}"; + sepNavVisRange = "{258, 683}"; + }; + }; + 27A92DC40E349282006E7CF6 /* abcUnate.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 2170}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1336}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92DC80E349282006E7CF6 /* module.make */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 784}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{478, 716}"; + }; + }; + 27A92DCA0E349282006E7CF6 /* cmd.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 22820}}"; + sepNavSelRange = "{4544, 0}"; + sepNavVisRange = "{2742, 2018}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92DCB0E349282006E7CF6 /* cmd.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 1036}}"; + sepNavSelRange = "{2768, 0}"; + sepNavVisRange = "{928, 2086}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92DCD0E349282006E7CF6 /* cmdApi.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 1512}}"; + sepNavSelRange = "{2785, 0}"; + sepNavVisRange = "{2484, 423}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92DCE0E349282006E7CF6 /* cmdFlag.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 1386}}"; + sepNavSelRange = "{1654, 0}"; + sepNavVisRange = "{1241, 438}"; + }; + }; + 27A92DCF0E349282006E7CF6 /* cmdHist.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 784}}"; + sepNavSelRange = "{1568, 0}"; + sepNavVisRange = "{1201, 446}"; + }; + }; + 27A92DD10E349282006E7CF6 /* cmdUtils.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 9016}}"; + sepNavSelRange = "{3526, 0}"; + sepNavVisRange = "{3266, 541}"; + }; + }; + 27A92DD40E349282006E7CF6 /* io.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 26236}}"; + sepNavSelRange = "{3837, 36}"; + sepNavVisRange = "{3341, 2202}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92DD50E349282006E7CF6 /* io.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 2422}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{677, 837}"; + }; + }; + 27A92DF30E349282006E7CF6 /* main.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 4466}}"; + sepNavSelRange = "{1588, 0}"; + sepNavVisRange = "{1326, 503}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92DF40E349282006E7CF6 /* main.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 1918}}"; + sepNavSelRange = "{1512, 0}"; + sepNavVisRange = "{960, 654}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92DF50E349282006E7CF6 /* mainFrame.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 7364}}"; + sepNavSelRange = "{7049, 0}"; + sepNavVisRange = "{6906, 299}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92DF60E349282006E7CF6 /* mainInit.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 1512}}"; + sepNavSelRange = "{2034, 0}"; + sepNavVisRange = "{1989, 315}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92DF70E349282006E7CF6 /* mainInt.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 1540}}"; + sepNavSelRange = "{832, 0}"; + sepNavVisRange = "{267, 1411}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92DF80E349282006E7CF6 /* mainUtils.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 3990}}"; + sepNavSelRange = "{1783, 44}"; + sepNavVisRange = "{1569, 573}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92DFA0E349282006E7CF6 /* temp.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 1162}}"; + sepNavSelRange = "{511, 0}"; + sepNavVisRange = "{0, 755}"; + }; + }; + 27A92E130E349282006E7CF6 /* espresso.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 11130}}"; + sepNavSelRange = "{1704, 29}"; + sepNavVisRange = "{814, 1651}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92E330E349282006E7CF6 /* unate.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 6258}}"; + sepNavSelRange = "{10139, 15}"; + sepNavVisRange = "{9874, 661}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92E410E349282006E7CF6 /* extraUtilMemory.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 8946}}"; + sepNavSelRange = "{7240, 0}"; + sepNavVisRange = "{8045, 539}"; + }; + }; + 27A92E460E349282006E7CF6 /* extraUtilUtil.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 4620}}"; + sepNavSelRange = "{2934, 0}"; + sepNavVisRange = "{3757, 304}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92E600E349283006E7CF6 /* mvcUtils.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 12222}}"; + sepNavSelRange = "{8137, 5}"; + sepNavVisRange = "{7715, 868}"; + }; + }; + 27A92E660E349283006E7CF6 /* nmTable.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 4760}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{5092, 656}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92E690E349283006E7CF6 /* st.c */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 8652}}"; + sepNavSelRange = "{3367, 0}"; + sepNavVisRange = "{3486, 200}"; + }; + }; + 27A92E6A0E349283006E7CF6 /* st.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 1358}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 462}"; + }; + }; + 27A92E6E0E349283006E7CF6 /* leaks.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 434}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 1112}"; + }; + }; + 27A92E710E349283006E7CF6 /* util_hack.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {691, 1344}}"; + sepNavSelRange = "{2287, 45}"; + sepNavVisRange = "{1599, 1173}"; + sepNavWindowFrame = "{{15, 76}, {750, 697}}"; + }; + }; + 27A92E740E349283006E7CF6 /* vec.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1012, 1554}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{788, 1041}"; + }; + }; + 27A92E780E349283006E7CF6 /* vecPtr.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1219, 10864}}"; + sepNavSelRange = "{16340, 0}"; + sepNavVisRange = "{16340, 305}"; + }; + }; + 27A930B60E3492E6006E7CF6 /* abcDar.c */ = { + isa = PBXFileReference; + lastKnownFileType = sourcecode.c.c; + name = abcDar.c; + path = "/Users/raiyan/Documents/Xcode Projects/abc/base/abci/abcDar.c"; + sourceTree = ""; + }; + 27A930BD0E3494E8006E7CF6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92BD50E349280006E7CF6 /* generic.h */; + name = "generic.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1021; + vrLoc = 0; + }; + 27A930BE0E3494E8006E7CF6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A930B60E3492E6006E7CF6 /* abcDar.c */; + name = "abcDar.c: 282"; + rLen = 0; + rLoc = 10649; + rType = 0; + vrLen = 916; + vrLoc = 10295; + }; + 27A930BF0E3494E8006E7CF6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C7F0E349281006E7CF6 /* generic.c */; + name = "generic.c: 21"; + rLen = 20; + rLoc = 468; + rType = 0; + vrLen = 1014; + vrLoc = 0; + }; + 27A930C10E3494E8006E7CF6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C850E349281006E7CF6 /* aigDfs.c */; + name = "aigDfs.c: 452"; + rLen = 0; + rLoc = 13510; + rType = 0; + vrLen = 798; + vrLoc = 7567; + }; + 27A930C30E3494E8006E7CF6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92BD50E349280006E7CF6 /* generic.h */; + name = "generic.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1021; + vrLoc = 0; + }; + 27A930C40E3494E8006E7CF6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A930B60E3492E6006E7CF6 /* abcDar.c */; + name = "abcDar.c: 282"; + rLen = 0; + rLoc = 10649; + rType = 0; + vrLen = 916; + vrLoc = 10295; + }; + 27A930C50E3494E8006E7CF6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C7F0E349281006E7CF6 /* generic.c */; + name = "generic.c: 21"; + rLen = 20; + rLoc = 468; + rType = 0; + vrLen = 1014; + vrLoc = 0; + }; + 27A930C60E3494E8006E7CF6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C820E349281006E7CF6 /* aig.h */; + name = "aig.h: 69"; + rLen = 31; + rLoc = 2287; + rType = 0; + vrLen = 1509; + vrLoc = 1016; + }; + 27A930C70E3494E8006E7CF6 /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92C850E349281006E7CF6 /* aigDfs.c */; + name = "aigDfs.c: 452"; + rLen = 0; + rLoc = 13510; + rType = 0; + vrLen = 798; + vrLoc = 7567; + }; + 27F2A0390E3951350056453A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E330E349282006E7CF6 /* unate.c */; + name = "unate.c: 419"; + rLen = 15; + rLoc = 10139; + rType = 0; + vrLen = 661; + vrLoc = 9874; + }; + 27F2A03A0E3951350056453A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + comments = "warning: unused variable 'Buffer'"; + fRef = 27A92DF80E349282006E7CF6 /* mainUtils.c */; + rLen = 1; + rLoc = 66; + rType = 1; + }; + 27F2A03B0E3951350056453A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92E330E349282006E7CF6 /* unate.c */; + name = "unate.c: 419"; + rLen = 15; + rLoc = 10139; + rType = 0; + vrLen = 661; + vrLoc = 9874; + }; + 27F2A0450E39514F0056453A /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 27A92DF80E349282006E7CF6 /* mainUtils.c */; + name = "mainUtils.c: 67"; + rLen = 44; + rLoc = 1783; + rType = 0; + vrLen = 516; + vrLoc = 1569; + }; + 8DD76FA90486AB0100D96B5E /* abc */ = { + activeExec = 0; + executables = ( + 27A92B5E0E34922E006E7CF6 /* abc */, + ); + }; +} diff --git a/abc70930/src/abc.xcodeproj/raiyan.perspectivev3 b/abc70930/src/abc.xcodeproj/raiyan.perspectivev3 new file mode 100644 index 00000000..1c6b9070 --- /dev/null +++ b/abc70930/src/abc.xcodeproj/raiyan.perspectivev3 @@ -0,0 +1,1561 @@ + + + + + ActivePerspectiveName + Debug + AllowedModules + + + BundleLoadPath + + MaxInstances + n + Module + PBXSmartGroupTreeModule + Name + Groups and Files Outline View + + + BundleLoadPath + + MaxInstances + n + Module + PBXNavigatorGroup + Name + Editor + + + BundleLoadPath + + MaxInstances + n + Module + XCTaskListModule + Name + Task List + + + BundleLoadPath + + MaxInstances + n + Module + XCDetailModule + Name + File and Smart Group Detail Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXBuildResultsModule + Name + Detailed Build Results Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXProjectFindModule + Name + Project Batch Find Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCProjectFormatConflictsModule + Name + Project Format Conflicts List + + + BundleLoadPath + + MaxInstances + n + Module + PBXBookmarksModule + Name + Bookmarks Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXClassBrowserModule + Name + Class Browser + + + BundleLoadPath + + MaxInstances + n + Module + PBXCVSModule + Name + Source Code Control Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXDebugBreakpointsModule + Name + Debug Breakpoints Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCDockableInspector + Name + Inspector + + + BundleLoadPath + + MaxInstances + n + Module + PBXOpenQuicklyModule + Name + Open Quickly Tool + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugSessionModule + Name + Debugger + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugCLIModule + Name + Debug Console + + + BundleLoadPath + + MaxInstances + n + Module + XCSnapshotModule + Name + Snapshots Tool + + + BundlePath + /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources + Description + AIODescriptionKey + DockingSystemVisible + + Extension + perspectivev3 + FavBarConfig + + PBXProjectModuleGUID + 27A92B680E34923D006E7CF6 + XCBarModuleItemNames + + XCBarModuleItems + + + FirstTimeWindowDisplayed + + Identifier + com.apple.perspectives.project.defaultV3 + MajorVersion + 34 + MinorVersion + 0 + Name + All-In-One + Notifications + + OpenEditors + + PerspectiveWidths + + 1280 + 1280 + + Perspectives + + + ChosenToolbarItems + + XCToolbarPerspectiveControl + NSToolbarSeparatorItem + active-target-popup + active-buildstyle-popup + action + NSToolbarFlexibleSpaceItem + buildOrClean + build-and-goOrGo + com.apple.ide.PBXToolbarStopButton + get-info + toggle-editor + NSToolbarFlexibleSpaceItem + com.apple.pbx.toolbar.searchfield + + ControllerClassBaseName + + IconName + WindowOfProject + Identifier + perspective.project + IsVertical + + Layout + + + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + 1C08E77C0454961000C914BD + 1C37FABC05509CD000000102 + 1C37FABC05539CD112110102 + E2644B35053B69B200211256 + 1C37FABC04509CD000100104 + 1CC0EA4004350EF90044410B + 1CC0EA4004350EF90041110B + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CA23ED40692098700951B8B + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + yes + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 185 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {185, 591}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + + + GeometryConfiguration + + Frame + {{0, 0}, {202, 609}} + GroupTreeTableConfiguration + + MainColumn + 185 + + + Module + PBXSmartGroupTreeModule + Proportion + 202pt + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 27A92B630E34923D006E7CF6 + PBXProjectModuleLabel + mainUtils.c + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 27A92B640E34923D006E7CF6 + PBXProjectModuleLabel + mainUtils.c + _historyCapacity + 0 + bookmark + 27F2A0450E39514F0056453A + history + + 27A930BD0E3494E8006E7CF6 + 27A930BE0E3494E8006E7CF6 + 27A930BF0E3494E8006E7CF6 + 27A930C10E3494E8006E7CF6 + 2755FD8C0E35986F0031A656 + 2755FD8D0E35986F0031A656 + 2755FD8E0E35986F0031A656 + 2755FD8F0E35986F0031A656 + 2755FD900E35986F0031A656 + 2755FD910E35986F0031A656 + 2755FD920E35986F0031A656 + 2755FD930E35986F0031A656 + 2755FDCC0E3821400031A656 + 2755FDCD0E3821400031A656 + 2717FC7F0E3843AC0038296D + 2717FC810E3843AC0038296D + 2717FC820E3843AC0038296D + 2717FC830E3843AC0038296D + 2717FC840E3843AC0038296D + 2717FC850E3843AC0038296D + 2717FC870E3843AC0038296D + 2717FCA20E3852600038296D + 2717FCA30E3852600038296D + 2717FCB70E3854530038296D + 2717FCB80E3854530038296D + 2717FCD10E38569B0038296D + 2717FCD20E38569B0038296D + 2717FCD30E38569B0038296D + 2717FCE90E3857DC0038296D + 2717FCEA0E3857DC0038296D + 2717FCEB0E3857DC0038296D + 2717FD140E3861B70038296D + 2717FD150E3861B70038296D + 273F099E0E387A1A00BA537B + 273F099F0E387A1A00BA537B + 273F09A00E387A1A00BA537B + 273F09A10E387A1A00BA537B + 274041210E38D50900DC6F18 + 274041230E38D50900DC6F18 + 274041720E38D73B00DC6F18 + 27F2A0390E3951350056453A + 27F2A03A0E3951350056453A + + prevStack + + 27A930C30E3494E8006E7CF6 + 27A930C40E3494E8006E7CF6 + 27A930C50E3494E8006E7CF6 + 27A930C60E3494E8006E7CF6 + 27A930C70E3494E8006E7CF6 + 2755FD950E35986F0031A656 + 2755FD960E35986F0031A656 + 2755FD970E35986F0031A656 + 2755FD980E35986F0031A656 + 2755FD990E35986F0031A656 + 2755FD9A0E35986F0031A656 + 2755FD9B0E35986F0031A656 + 2755FD9C0E35986F0031A656 + 2755FD9D0E35986F0031A656 + 2755FDD00E3821400031A656 + 2755FDD10E3821400031A656 + 2717FC890E3843AC0038296D + 2717FC8B0E3843AC0038296D + 2717FC8D0E3843AC0038296D + 2717FC8E0E3843AC0038296D + 2717FC8F0E3843AC0038296D + 2717FC900E3843AC0038296D + 2717FC930E3843AC0038296D + 2717FCA90E3852600038296D + 2717FCBD0E3854530038296D + 2717FCBE0E3854530038296D + 2717FCC00E3854530038296D + 2717FCD50E38569B0038296D + 2717FCD70E38569B0038296D + 2717FCED0E3857DC0038296D + 2717FCEE0E3857DC0038296D + 2717FCEF0E3857DC0038296D + 2717FD190E3861B70038296D + 2717FD1A0E3861B70038296D + 2717FD1B0E3861B70038296D + 273F09A20E387A1A00BA537B + 273F09A40E387A1A00BA537B + 273F09A50E387A1A00BA537B + 274041280E38D50900DC6F18 + 2740412B0E38D50900DC6F18 + 27F2A03B0E3951350056453A + + + SplitCount + 1 + + StatusBarVisibility + + XCSharingToken + com.apple.Xcode.CommonNavigatorGroupSharingToken + + GeometryConfiguration + + Frame + {{0, 0}, {1073, 336}} + + Module + PBXNavigatorGroup + Proportion + 336pt + + + Proportion + 268pt + Tabs + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA23EDF0692099D00951B8B + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{10, 27}, {1073, 241}} + + Module + XCDetailModule + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA23EE00692099D00951B8B + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{10, 27}, {1073, 241}} + + Module + PBXProjectFindModule + + + ContentConfiguration + + PBXCVSModuleFilterTypeKey + 1032 + PBXProjectModuleGUID + 1CA23EE10692099D00951B8B + PBXProjectModuleLabel + SCM Results + + GeometryConfiguration + + Frame + {{10, 27}, {1073, 209}} + + Module + PBXCVSModule + + + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build + XCBuildResultsTrigger_Collapse + 1021 + XCBuildResultsTrigger_Open + 1011 + + GeometryConfiguration + + Frame + {{10, 27}, {1073, 241}} + + Module + PBXBuildResultsModule + + + + + Proportion + 1073pt + + + Name + Project + ServiceClasses + + XCModuleDock + PBXSmartGroupTreeModule + XCModuleDock + PBXNavigatorGroup + XCDockableTabModule + XCDetailModule + PBXProjectFindModule + PBXCVSModule + PBXBuildResultsModule + + TableOfContents + + 27F2A0350E3951150056453A + 1CA23ED40692098700951B8B + 27F2A0360E3951150056453A + 27A92B630E34923D006E7CF6 + 27F2A0370E3951150056453A + 1CA23EDF0692099D00951B8B + 1CA23EE00692099D00951B8B + 1CA23EE10692099D00951B8B + XCMainBuildResultsModuleGUID + + ToolbarConfiguration + xcode.toolbar.config.defaultV3 + + + ChosenToolbarItems + + XCToolbarPerspectiveControl + NSToolbarSeparatorItem + active-combo-popup + NSToolbarFlexibleSpaceItem + go-debug + build-and-go + com.apple.ide.PBXToolbarStopButton + debugger-restart-executable + debugger-pause + debugger-step-over + debugger-step-into + debugger-step-out + debugger-enable-breakpoints + NSToolbarFlexibleSpaceItem + com.apple.ide.XCBreakpointsToolbarItem + clear-log + + ControllerClassBaseName + PBXDebugSessionModule + IconName + DebugTabIcon + Identifier + perspective.debug + IsVertical + + Layout + + + BecomeActive + + ContentConfiguration + + PBXProjectModuleGUID + 1CCC7628064C1048000F2A68 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {1280, 181}} + RubberWindowFrame + 0 128 1280 650 0 0 1280 778 + + Module + PBXDebugCLIModule + Proportion + 181pt + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {625, 206}} + {{625, 0}, {655, 206}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {1280, 206}} + {{0, 206}, {1280, 217}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1CCC7629064C1048000F2A68 + PBXProjectModuleLabel + Debug + + GeometryConfiguration + + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 186}, {1280, 423}} + PBXDebugSessionStackFrameViewKey + + DebugVariablesTableConfiguration + + Name + 120 + Value + 85 + Summary + 425 + + Frame + {{625, 0}, {655, 206}} + RubberWindowFrame + 0 128 1280 650 0 0 1280 778 + + RubberWindowFrame + 0 128 1280 650 0 0 1280 778 + + Module + PBXDebugSessionModule + Proportion + 423pt + + + Name + Debug + ServiceClasses + + XCModuleDock + PBXDebugCLIModule + PBXDebugSessionModule + PBXDebugProcessAndThreadModule + PBXDebugProcessViewModule + PBXDebugThreadViewModule + PBXDebugStackFrameViewModule + PBXNavigatorGroup + + TableOfContents + + 27F2A03E0E39514F0056453A + 1CCC7628064C1048000F2A68 + 1CCC7629064C1048000F2A68 + 27F2A03F0E39514F0056453A + 27F2A0400E39514F0056453A + 27F2A0410E39514F0056453A + 27F2A0420E39514F0056453A + 27A92B630E34923D006E7CF6 + + ToolbarConfiguration + xcode.toolbar.config.debugV3 + + + PerspectivesBarVisible + + ShelfIsVisible + + SourceDescription + file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecification.xcperspec' + StatusbarIsVisible + + TimeStamp + 0.0 + ToolbarDisplayMode + 1 + ToolbarIsVisible + + ToolbarSizeMode + 1 + Type + Perspectives + UpdateMessage + + WindowJustification + 5 + WindowOrderList + + 27F2A0430E39514F0056453A + 27F2A0440E39514F0056453A + /Users/raiyan/Documents/Xcode Projects/abc/abc.xcodeproj + + WindowString + 0 128 1280 650 0 0 1280 778 + WindowToolsV3 + + + Identifier + windowTool.debugger + Layout + + + Dock + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {317, 164}} + {{317, 0}, {377, 164}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {694, 164}} + {{0, 164}, {694, 216}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1C162984064C10D400B95A72 + PBXProjectModuleLabel + Debug - GLUTExamples (Underwater) + + GeometryConfiguration + + DebugConsoleDrawerSize + {100, 120} + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 0}, {694, 380}} + RubberWindowFrame + 321 238 694 422 0 0 1440 878 + + Module + PBXDebugSessionModule + Proportion + 100% + + + Proportion + 100% + + + Name + Debugger + ServiceClasses + + PBXDebugSessionModule + + StatusbarIsVisible + 1 + TableOfContents + + 1CD10A99069EF8BA00B06720 + 1C0AD2AB069F1E9B00FABCE6 + 1C162984064C10D400B95A72 + 1C0AD2AC069F1E9B00FABCE6 + + ToolbarConfiguration + xcode.toolbar.config.debugV3 + WindowString + 321 238 694 422 0 0 1440 878 + WindowToolGUID + 1CD10A99069EF8BA00B06720 + WindowToolIsVisible + 0 + + + Identifier + windowTool.build + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528F0623707200166675 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CD052900623707200166675 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {500, 215}} + RubberWindowFrame + 192 257 500 500 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 218pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build + + GeometryConfiguration + + Frame + {{0, 222}, {500, 236}} + RubberWindowFrame + 192 257 500 500 0 0 1280 1002 + + Module + PBXBuildResultsModule + Proportion + 236pt + + + Proportion + 458pt + + + Name + Build Results + ServiceClasses + + PBXBuildResultsModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAA5065D492600B07095 + 1C78EAA6065D492600B07095 + 1CD0528F0623707200166675 + XCMainBuildResultsModuleGUID + + ToolbarConfiguration + xcode.toolbar.config.buildV3 + WindowString + 192 257 500 500 0 0 1280 1002 + + + Identifier + windowTool.find + Layout + + + Dock + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CDD528C0622207200134675 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CD0528D0623707200166675 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {781, 167}} + RubberWindowFrame + 62 385 781 470 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 781pt + + + Proportion + 50% + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528E0623707200166675 + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{8, 0}, {773, 254}} + RubberWindowFrame + 62 385 781 470 0 0 1440 878 + + Module + PBXProjectFindModule + Proportion + 50% + + + Proportion + 428pt + + + Name + Project Find + ServiceClasses + + PBXProjectFindModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C530D57069F1CE1000CFCEE + 1C530D58069F1CE1000CFCEE + 1C530D59069F1CE1000CFCEE + 1CDD528C0622207200134675 + 1C530D5A069F1CE1000CFCEE + 1CE0B1FE06471DED0097A5F4 + 1CD0528E0623707200166675 + + WindowString + 62 385 781 470 0 0 1440 878 + WindowToolGUID + 1C530D57069F1CE1000CFCEE + WindowToolIsVisible + 0 + + + Identifier + windowTool.snapshots + Layout + + + Dock + + + Module + XCSnapshotModule + Proportion + 100% + + + Proportion + 100% + + + Name + Snapshots + ServiceClasses + + XCSnapshotModule + + StatusbarIsVisible + Yes + ToolbarConfiguration + xcode.toolbar.config.snapshots + WindowString + 315 824 300 550 0 0 1440 878 + WindowToolIsVisible + Yes + + + FirstTimeWindowDisplayed + + Identifier + windowTool.debuggerConsole + IsVertical + + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAAC065D492600B07095 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {440, 359}} + RubberWindowFrame + 21 355 440 400 0 0 1280 778 + + Module + PBXDebugCLIModule + Proportion + 359pt + + + Proportion + 359pt + + + Name + Debugger Console + ServiceClasses + + PBXDebugCLIModule + + StatusbarIsVisible + + TableOfContents + + 1C530D5B069F1CE1000CFCEE + 274041750E38EF1000DC6F18 + 1C78EAAC065D492600B07095 + + ToolbarConfiguration + xcode.toolbar.config.consoleV3 + WindowString + 21 355 440 400 0 0 1280 778 + WindowToolGUID + 1C530D5B069F1CE1000CFCEE + WindowToolIsVisible + + + + Identifier + windowTool.scm + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAB2065D492600B07095 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1C78EAB3065D492600B07095 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {452, 0}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 0pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD052920623707200166675 + PBXProjectModuleLabel + SCM + + GeometryConfiguration + + ConsoleFrame + {{0, 259}, {452, 0}} + Frame + {{0, 7}, {452, 259}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + TableConfiguration + + Status + 30 + FileName + 199 + Path + 197.09500122070312 + + TableFrame + {{0, 0}, {452, 250}} + + Module + PBXCVSModule + Proportion + 262pt + + + Proportion + 266pt + + + Name + SCM + ServiceClasses + + PBXCVSModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAB4065D492600B07095 + 1C78EAB5065D492600B07095 + 1C78EAB2065D492600B07095 + 1CD052920623707200166675 + + ToolbarConfiguration + xcode.toolbar.config.scmV3 + WindowString + 743 379 452 308 0 0 1280 1002 + + + Identifier + windowTool.breakpoints + IsVertical + 0 + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CE0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + no + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 168 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 1C77FABC04509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {168, 350}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + 0 + + GeometryConfiguration + + Frame + {{0, 0}, {185, 368}} + GroupTreeTableConfiguration + + MainColumn + 168 + + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 185pt + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA1AED706398EBD00589147 + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{190, 0}, {554, 368}} + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + XCDetailModule + Proportion + 554pt + + + Proportion + 368pt + + + MajorVersion + 3 + MinorVersion + 0 + Name + Breakpoints + ServiceClasses + + PBXSmartGroupTreeModule + XCDetailModule + + StatusbarIsVisible + 1 + TableOfContents + + 1CDDB66807F98D9800BB5817 + 1CDDB66907F98D9800BB5817 + 1CE0B1FE06471DED0097A5F4 + 1CA1AED706398EBD00589147 + + ToolbarConfiguration + xcode.toolbar.config.breakpointsV3 + WindowString + 315 424 744 409 0 0 1440 878 + WindowToolGUID + 1CDDB66807F98D9800BB5817 + WindowToolIsVisible + 1 + + + Identifier + windowTool.debugAnimator + Layout + + + Dock + + + Module + PBXNavigatorGroup + Proportion + 100% + + + Proportion + 100% + + + Name + Debug Visualizer + ServiceClasses + + PBXNavigatorGroup + + StatusbarIsVisible + 1 + ToolbarConfiguration + xcode.toolbar.config.debugAnimatorV3 + WindowString + 100 100 700 500 0 0 1280 1002 + + + Identifier + windowTool.bookmarks + Layout + + + Dock + + + Module + PBXBookmarksModule + Proportion + 166pt + + + Proportion + 166pt + + + Name + Bookmarks + ServiceClasses + + PBXBookmarksModule + + StatusbarIsVisible + 0 + WindowString + 538 42 401 187 0 0 1280 1002 + + + Identifier + windowTool.projectFormatConflicts + Layout + + + Dock + + + Module + XCProjectFormatConflictsModule + Proportion + 100% + + + Proportion + 100% + + + Name + Project Format Conflicts + ServiceClasses + + XCProjectFormatConflictsModule + + StatusbarIsVisible + 0 + WindowContentMinSize + 450 300 + WindowString + 50 850 472 307 0 0 1440 877 + + + Identifier + windowTool.classBrowser + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + OptionsSetName + Hierarchy, all classes + PBXProjectModuleGUID + 1CA6456E063B45B4001379D8 + PBXProjectModuleLabel + Class Browser - NSObject + + GeometryConfiguration + + ClassesFrame + {{0, 0}, {369, 96}} + ClassesTreeTableConfiguration + + PBXClassNameColumnIdentifier + 208 + PBXClassBookColumnIdentifier + 22 + + Frame + {{0, 0}, {616, 353}} + MembersFrame + {{0, 105}, {369, 395}} + MembersTreeTableConfiguration + + PBXMemberTypeIconColumnIdentifier + 22 + PBXMemberNameColumnIdentifier + 216 + PBXMemberTypeColumnIdentifier + 94 + PBXMemberBookColumnIdentifier + 22 + + PBXModuleWindowStatusBarHidden2 + 1 + RubberWindowFrame + 597 125 616 374 0 0 1280 1002 + + Module + PBXClassBrowserModule + Proportion + 354pt + + + Proportion + 354pt + + + Name + Class Browser + ServiceClasses + + PBXClassBrowserModule + + StatusbarIsVisible + 0 + TableOfContents + + 1C78EABA065D492600B07095 + 1C78EABB065D492600B07095 + 1CA6456E063B45B4001379D8 + + ToolbarConfiguration + xcode.toolbar.config.classbrowser + WindowString + 597 125 616 374 0 0 1280 1002 + + + Identifier + windowTool.refactoring + IncludeInToolsMenu + 0 + Layout + + + Dock + + + BecomeActive + 1 + GeometryConfiguration + + Frame + {0, 0}, {500, 335} + RubberWindowFrame + {0, 0}, {500, 335} + + Module + XCRefactoringModule + Proportion + 100% + + + Proportion + 100% + + + Name + Refactoring + ServiceClasses + + XCRefactoringModule + + WindowString + 200 200 500 356 0 0 1920 1200 + + + + diff --git a/abc70930/src/aig/aig/aig.h b/abc70930/src/aig/aig/aig.h new file mode 100644 index 00000000..e85eceb9 --- /dev/null +++ b/abc70930/src/aig/aig/aig.h @@ -0,0 +1,553 @@ +/**CFile**************************************************************** + + FileName [aig.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aig.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __AIG_H__ +#define __AIG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Aig_Man_t_ Aig_Man_t; +typedef struct Aig_Obj_t_ Aig_Obj_t; +typedef struct Aig_MmFixed_t_ Aig_MmFixed_t; +typedef struct Aig_MmFlex_t_ Aig_MmFlex_t; +typedef struct Aig_MmStep_t_ Aig_MmStep_t; +typedef struct Aig_TMan_t_ Aig_TMan_t; + +// object types +typedef enum { + AIG_OBJ_NONE, // 0: non-existent object + AIG_OBJ_CONST1, // 1: constant 1 + AIG_OBJ_PI, // 2: primary input + AIG_OBJ_PO, // 3: primary output + AIG_OBJ_BUF, // 4: buffer node + AIG_OBJ_AND, // 5: AND node + AIG_OBJ_EXOR, // 6: EXOR node + AIG_OBJ_LATCH, // 7: latch + AIG_OBJ_VOID // 8: unused object +} Aig_Type_t; + +// the AIG node +struct Aig_Obj_t_ // 8 words +{ + Aig_Obj_t * pNext; // strashing table + Aig_Obj_t * pFanin0; // fanin + Aig_Obj_t * pFanin1; // fanin + unsigned int Type : 3; // object type + unsigned int fPhase : 1; // value under 000...0 pattern + unsigned int fMarkA : 1; // multipurpose mask + unsigned int fMarkB : 1; // multipurpose mask + unsigned int nRefs : 26; // reference count + unsigned Level : 24; // the level of this node + unsigned nCuts : 8; // the number of cuts + int TravId; // unique ID of last traversal involving the node + int Id; // unique ID of the node + union { // temporary store for user's data + void * pData; + int iData; + float dData; + }; +}; + +// the AIG manager +struct Aig_Man_t_ +{ + char * pName; // the design name + // AIG nodes + Vec_Ptr_t * vPis; // the array of PIs + Vec_Ptr_t * vPos; // the array of POs + Vec_Ptr_t * vObjs; // the array of all nodes (optional) + Vec_Ptr_t * vBufs; // the array of buffers + Aig_Obj_t * pConst1; // the constant 1 node + Aig_Obj_t Ghost; // the ghost node + int nRegs; // the number of registers (registers are last POs) + int nAsserts; // the number of asserts among POs (asserts are first POs) + // AIG node counters + int nObjs[AIG_OBJ_VOID];// the number of objects by type + int nCreated; // the number of created objects + int nDeleted; // the number of deleted objects + // structural hash table + Aig_Obj_t ** pTable; // structural hash table + int nTableSize; // structural hash table size + // representation of fanouts + int * pFanData; // the database to store fanout information + int nFansAlloc; // the size of fanout representation + Vec_Vec_t * vLevels; // used to update timing information + int nBufReplaces; // the number of times replacement led to a buffer + int nBufFixes; // the number of times buffers were propagated + int nBufMax; // the maximum number of buffers during computation + // topological order + unsigned * pOrderData; + int nOrderAlloc; + int iPrev; + int iNext; + int nAndTotal; + int nAndPrev; + // representatives + Aig_Obj_t ** pEquivs; // linked list of equivalent nodes (when choices are used) + Aig_Obj_t ** pReprs; // representatives of each node + int nReprsAlloc; // the number of allocated representatives + // various data members + Aig_MmFixed_t * pMemObjs; // memory manager for objects + Vec_Int_t * vLevelR; // the reverse level of the nodes + int nLevelMax; // maximum number of levels + void * pData; // the temporary data + int nTravIds; // the current traversal ID + int fCatchExor; // enables EXOR nodes + int fAddStrash; // performs additional strashing + Aig_Obj_t ** pObjCopies; // mapping of AIG nodes into FRAIG nodes + void (*pImpFunc) (void*, void*); // implication checking precedure + void * pImpData; // implication checking data + Aig_TMan_t * pManTime; // the timing manager + Vec_Ptr_t * vMapped; + Vec_Int_t * vFlopNums; + // timing statistics + int time1; + int time2; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define AIG_MIN(a,b) (((a) < (b))? (a) : (b)) +#define AIG_MAX(a,b) (((a) > (b))? (a) : (b)) +#define AIG_ABS(a) (((a) >= 0)? (a) :-(a)) +#define AIG_INFINITY (100000000) + +#ifndef PRT +#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) +#endif + +static inline int Aig_Base2Log( unsigned n ) { int r; assert( n >= 0 ); if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ); return r; } +static inline int Aig_Base10Log( unsigned n ) { int r; assert( n >= 0 ); if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ); return r; } +static inline char * Aig_UtilStrsav( char * s ) { return s ? strcpy(ALLOC(char, strlen(s)+1), s) : NULL; } +static inline int Aig_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } +static inline int Aig_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline int Aig_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } +static inline void Aig_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } +static inline void Aig_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } +static inline unsigned Aig_InfoMask( int nVar ) { return (~(unsigned)0) >> (32-nVar); } +static inline unsigned Aig_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId & 31)); } +static inline int Aig_WordCountOnes( unsigned uWord ) +{ + uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); + uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); + uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); + uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); + return (uWord & 0x0000FFFF) + (uWord>>16); +} + +static inline Aig_Obj_t * Aig_Regular( Aig_Obj_t * p ) { return (Aig_Obj_t *)((unsigned long)(p) & ~01); } +static inline Aig_Obj_t * Aig_Not( Aig_Obj_t * p ) { return (Aig_Obj_t *)((unsigned long)(p) ^ 01); } +static inline Aig_Obj_t * Aig_NotCond( Aig_Obj_t * p, int c ) { return (Aig_Obj_t *)((unsigned long)(p) ^ (c)); } +static inline int Aig_IsComplement( Aig_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } + +static inline int Aig_ManPiNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_PI]; } +static inline int Aig_ManPoNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_PO]; } +static inline int Aig_ManBufNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_BUF]; } +static inline int Aig_ManAndNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]; } +static inline int Aig_ManExorNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_EXOR]; } +static inline int Aig_ManLatchNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_LATCH]; } +static inline int Aig_ManNodeNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]+p->nObjs[AIG_OBJ_EXOR]; } +static inline int Aig_ManGetCost( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]+3*p->nObjs[AIG_OBJ_EXOR]; } +static inline int Aig_ManObjNum( Aig_Man_t * p ) { return p->nCreated - p->nDeleted; } +static inline int Aig_ManObjNumMax( Aig_Man_t * p ) { return Vec_PtrSize(p->vObjs); } +static inline int Aig_ManRegNum( Aig_Man_t * p ) { return p->nRegs; } + +static inline Aig_Obj_t * Aig_ManConst0( Aig_Man_t * p ) { return Aig_Not(p->pConst1); } +static inline Aig_Obj_t * Aig_ManConst1( Aig_Man_t * p ) { return p->pConst1; } +static inline Aig_Obj_t * Aig_ManGhost( Aig_Man_t * p ) { return &p->Ghost; } +static inline Aig_Obj_t * Aig_ManPi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPis, i); } +static inline Aig_Obj_t * Aig_ManPo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPos, i); } +static inline Aig_Obj_t * Aig_ManLo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPis, Aig_ManPiNum(p)-Aig_ManRegNum(p)+i); } +static inline Aig_Obj_t * Aig_ManLi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPos, Aig_ManPoNum(p)-Aig_ManRegNum(p)+i); } +static inline Aig_Obj_t * Aig_ManObj( Aig_Man_t * p, int i ) { return p->vObjs ? (Aig_Obj_t *)Vec_PtrEntry(p->vObjs, i) : NULL; } + +static inline Aig_Type_t Aig_ObjType( Aig_Obj_t * pObj ) { return (Aig_Type_t)pObj->Type; } +static inline int Aig_ObjIsNone( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_NONE; } +static inline int Aig_ObjIsConst1( Aig_Obj_t * pObj ) { assert(!Aig_IsComplement(pObj)); return pObj->Type == AIG_OBJ_CONST1; } +static inline int Aig_ObjIsPi( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_PI; } +static inline int Aig_ObjIsPo( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_PO; } +static inline int Aig_ObjIsBuf( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_BUF; } +static inline int Aig_ObjIsAnd( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND; } +static inline int Aig_ObjIsExor( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_EXOR; } +static inline int Aig_ObjIsLatch( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_LATCH; } +static inline int Aig_ObjIsNode( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR; } +static inline int Aig_ObjIsTerm( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_PI || pObj->Type == AIG_OBJ_PO || pObj->Type == AIG_OBJ_CONST1; } +static inline int Aig_ObjIsHash( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR || pObj->Type == AIG_OBJ_LATCH; } +static inline int Aig_ObjIsChoice( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquivs && p->pEquivs[pObj->Id] && pObj->nRefs > 0; } + +static inline int Aig_ObjIsMarkA( Aig_Obj_t * pObj ) { return pObj->fMarkA; } +static inline void Aig_ObjSetMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 1; } +static inline void Aig_ObjClearMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 0; } + +static inline void Aig_ObjSetTravId( Aig_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } +static inline void Aig_ObjSetTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } +static inline void Aig_ObjSetTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } +static inline int Aig_ObjIsTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int)(pObj->TravId == p->nTravIds); } +static inline int Aig_ObjIsTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int)(pObj->TravId == p->nTravIds - 1); } + +static inline int Aig_ObjPhase( Aig_Obj_t * pObj ) { return pObj->fPhase; } +static inline int Aig_ObjPhaseReal( Aig_Obj_t * pObj ) { return pObj? Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) : 1; } +static inline int Aig_ObjRefs( Aig_Obj_t * pObj ) { return pObj->nRefs; } +static inline void Aig_ObjRef( Aig_Obj_t * pObj ) { pObj->nRefs++; } +static inline void Aig_ObjDeref( Aig_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } +static inline void Aig_ObjClearRef( Aig_Obj_t * pObj ) { pObj->nRefs = 0; } +static inline int Aig_ObjFaninId0( Aig_Obj_t * pObj ) { return pObj->pFanin0? Aig_Regular(pObj->pFanin0)->Id : -1; } +static inline int Aig_ObjFaninId1( Aig_Obj_t * pObj ) { return pObj->pFanin1? Aig_Regular(pObj->pFanin1)->Id : -1; } +static inline int Aig_ObjFaninC0( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin0); } +static inline int Aig_ObjFaninC1( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin1); } +static inline Aig_Obj_t * Aig_ObjFanin0( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin0); } +static inline Aig_Obj_t * Aig_ObjFanin1( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin1); } +static inline Aig_Obj_t * Aig_ObjChild0( Aig_Obj_t * pObj ) { return pObj->pFanin0; } +static inline Aig_Obj_t * Aig_ObjChild1( Aig_Obj_t * pObj ) { return pObj->pFanin1; } +static inline Aig_Obj_t * Aig_ObjChild0Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Aig_ObjChild1Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj)) : NULL; } +static inline int Aig_ObjLevel( Aig_Obj_t * pObj ) { return pObj->Level; } +static inline int Aig_ObjLevelNew( Aig_Obj_t * pObj ) { return Aig_ObjFanin1(pObj)? 1 + Aig_ObjIsExor(pObj) + AIG_MAX(Aig_ObjFanin0(pObj)->Level, Aig_ObjFanin1(pObj)->Level) : Aig_ObjFanin0(pObj)->Level; } +static inline void Aig_ObjClean( Aig_Obj_t * pObj ) { memset( pObj, 0, sizeof(Aig_Obj_t) ); } +static inline Aig_Obj_t * Aig_ObjFanout0( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert(p->pFanData && pObj->Id < p->nFansAlloc); return Aig_ManObj(p, p->pFanData[5*pObj->Id] >> 1); } +static inline Aig_Obj_t * Aig_ObjEquiv( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquivs? p->pEquivs[pObj->Id] : NULL; } +static inline int Aig_ObjWhatFanin( Aig_Obj_t * pObj, Aig_Obj_t * pFanin ) +{ + if ( Aig_ObjFanin0(pObj) == pFanin ) return 0; + if ( Aig_ObjFanin1(pObj) == pFanin ) return 1; + assert(0); return -1; +} +static inline int Aig_ObjFanoutC( Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) +{ + if ( Aig_ObjFanin0(pFanout) == pObj ) return Aig_ObjFaninC0(pObj); + if ( Aig_ObjFanin1(pFanout) == pObj ) return Aig_ObjFaninC1(pObj); + assert(0); return -1; +} + +// create the ghost of the new node +static inline Aig_Obj_t * Aig_ObjCreateGhost( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) +{ + Aig_Obj_t * pGhost; + assert( Type != AIG_OBJ_AND || !Aig_ObjIsConst1(Aig_Regular(p0)) ); + assert( p1 == NULL || !Aig_ObjIsConst1(Aig_Regular(p1)) ); + assert( Type == AIG_OBJ_PI || Aig_Regular(p0) != Aig_Regular(p1) ); + pGhost = Aig_ManGhost(p); + pGhost->Type = Type; + if ( p1 == NULL || Aig_Regular(p0)->Id < Aig_Regular(p1)->Id ) + { + pGhost->pFanin0 = p0; + pGhost->pFanin1 = p1; + } + else + { + pGhost->pFanin0 = p1; + pGhost->pFanin1 = p0; + } + return pGhost; +} + +// internal memory manager +static inline Aig_Obj_t * Aig_ManFetchMemory( Aig_Man_t * p ) +{ + extern char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ); + Aig_Obj_t * pTemp; + pTemp = (Aig_Obj_t *)Aig_MmFixedEntryFetch( p->pMemObjs ); + memset( pTemp, 0, sizeof(Aig_Obj_t) ); + Vec_PtrPush( p->vObjs, pTemp ); + pTemp->Id = p->nCreated++; + return pTemp; +} +static inline void Aig_ManRecycleMemory( Aig_Man_t * p, Aig_Obj_t * pEntry ) +{ + extern void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ); + assert( pEntry->nRefs == 0 ); + pEntry->Type = AIG_OBJ_NONE; // distinquishes a dead node from a live node + Aig_MmFixedEntryRecycle( p->pMemObjs, (char *)pEntry ); + p->nDeleted++; +} + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the primary inputs +#define Aig_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPis, pObj, i ) +// iterator over the primary outputs +#define Aig_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPos, pObj, i ) +// iterator over the assertions +#define Aig_ManForEachAssert( p, pObj, i ) \ + Vec_PtrForEachEntryStart( p->vPos, pObj, i, Aig_ManPoNum(p)-p->nAsserts ) +// iterator over all objects, including those currently not used +#define Aig_ManForEachObj( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else +// iterator over all nodes +#define Aig_ManForEachNode( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsNode(pObj) ) {} else +// iterator over the nodes whose IDs are stored in the array +#define Aig_ManForEachNodeVec( p, vIds, pObj, i ) \ + for ( i = 0; i < Vec_IntSize(vIds) && ((pObj) = Aig_ManObj(p, Vec_IntEntry(vIds,i))); i++ ) +// iterator over the nodes in the topological order +#define Aig_ManForEachNodeInOrder( p, pObj ) \ + for ( assert(p->pOrderData), p->iPrev = 0, p->iNext = p->pOrderData[1]; \ + p->iNext && (((pObj) = Aig_ManObj(p, p->iNext)), 1); \ + p->iNext = p->pOrderData[2*p->iPrev+1] ) + +// these two procedures are only here for the use inside the iterator +static inline int Aig_ObjFanout0Int( Aig_Man_t * p, int ObjId ) { assert(ObjId < p->nFansAlloc); return p->pFanData[5*ObjId]; } +static inline int Aig_ObjFanoutNext( Aig_Man_t * p, int iFan ) { assert(iFan/2 < p->nFansAlloc); return p->pFanData[5*(iFan >> 1) + 3 + (iFan & 1)]; } +// iterator over the fanouts +#define Aig_ObjForEachFanout( p, pObj, pFanout, iFan, i ) \ + for ( assert(p->pFanData), i = 0; (i < (int)(pObj)->nRefs) && \ + (((iFan) = i? Aig_ObjFanoutNext(p, iFan) : Aig_ObjFanout0Int(p, pObj->Id)), 1) && \ + (((pFanout) = Aig_ManObj(p, iFan>>1)), 1); i++ ) + + +//////////////////////////////////////////////////////////////////////// +/// SEQUENTIAL ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the primary inputs +#define Aig_ManForEachPiSeq( p, pObj, i ) \ + Vec_PtrForEachEntryStop( p->vPis, pObj, i, Aig_ManPiNum(p)-Aig_ManRegNum(p) ) +// iterator over the latch outputs +#define Aig_ManForEachLoSeq( p, pObj, i ) \ + Vec_PtrForEachEntryStart( p->vPis, pObj, i, Aig_ManPiNum(p)-Aig_ManRegNum(p) ) +// iterator over the primary outputs +#define Aig_ManForEachPoSeq( p, pObj, i ) \ + Vec_PtrForEachEntryStop( p->vPos, pObj, i, Aig_ManPoNum(p)-Aig_ManRegNum(p) ) +// iterator over the latch inputs +#define Aig_ManForEachLiSeq( p, pObj, i ) \ + Vec_PtrForEachEntryStart( p->vPos, pObj, i, Aig_ManPoNum(p)-Aig_ManRegNum(p) ) +// iterator over the latch input and outputs +#define Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, k ) \ + for ( k = 0; (k < Aig_ManRegNum(p)) && (((pObjLi) = Aig_ManLi(p, k)), 1) \ + && (((pObjLo)=Aig_ManLo(p, k)), 1); k++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== aigCheck.c ========================================================*/ +extern int Aig_ManCheck( Aig_Man_t * p ); +extern void Aig_ManCheckMarkA( Aig_Man_t * p ); +extern void Aig_ManCheckPhase( Aig_Man_t * p ); +/*=== aigDfs.c ==========================================================*/ +extern Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p ); +extern Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes ); +extern Vec_Ptr_t * Aig_ManDfsChoices( Aig_Man_t * p ); +extern Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p ); +extern int Aig_ManLevelNum( Aig_Man_t * p ); +extern int Aig_ManCountLevels( Aig_Man_t * p ); +extern int Aig_DagSize( Aig_Obj_t * pObj ); +extern int Aig_SupportSize( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ); +extern Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pObj, int nVars ); +extern Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ); +extern void Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ); +extern int Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ); +/*=== aigFanout.c ==========================================================*/ +extern void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ); +extern void Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ); +extern void Aig_ManFanoutStart( Aig_Man_t * p ); +extern void Aig_ManFanoutStop( Aig_Man_t * p ); +/*=== aigMan.c ==========================================================*/ +extern Aig_Man_t * Aig_ManStart( int nNodesMax ); +extern Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p ); +extern Aig_Obj_t * Aig_ManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ); +extern Aig_Man_t * Aig_ManDup( Aig_Man_t * p, int fOrdered ); +extern Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ); +extern void Aig_ManStop( Aig_Man_t * p ); +extern int Aig_ManCleanup( Aig_Man_t * p ); +extern void Aig_ManPrintStats( Aig_Man_t * p ); +/*=== aigMem.c ==========================================================*/ +extern void Aig_ManStartMemory( Aig_Man_t * p ); +extern void Aig_ManStopMemory( Aig_Man_t * p ); +/*=== aigMffc.c ==========================================================*/ +extern int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin ); +extern int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin ); +extern int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp ); +extern int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode ); +extern int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves ); +extern int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult ); +/*=== aigObj.c ==========================================================*/ +extern Aig_Obj_t * Aig_ObjCreatePi( Aig_Man_t * p ); +extern Aig_Obj_t * Aig_ObjCreatePo( Aig_Man_t * p, Aig_Obj_t * pDriver ); +extern Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ); +extern void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ); +extern void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop ); +extern void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew ); +extern void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fNodesOnly, int fUpdateLevel ); +/*=== aigOper.c =========================================================*/ +extern Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ); +extern Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ); +extern Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); +extern Aig_Obj_t * Aig_Latch( Aig_Man_t * p, Aig_Obj_t * pObj, int fInitOne ); +extern Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); +extern Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); +extern Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ); +extern Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ); +extern Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ); +extern Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 ); +extern Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ); +extern Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ); +extern Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ); +/*=== aigOrder.c =========================================================*/ +extern void Aig_ManOrderStart( Aig_Man_t * p ); +extern void Aig_ManOrderStop( Aig_Man_t * p ); +extern void Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId ); +extern void Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId ); +extern void Aig_ObjOrderAdvance( Aig_Man_t * p ); +/*=== aigPart.c =========================================================*/ +extern Vec_Ptr_t * Aig_ManSupports( Aig_Man_t * pMan ); +extern Vec_Ptr_t * Aig_ManPartitionSmart( Aig_Man_t * p, int nPartSizeLimit, int fVerbose, Vec_Ptr_t ** pvPartSupps ); +extern Vec_Ptr_t * Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize ); +extern Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize ); +/*=== aigRepr.c =========================================================*/ +extern void Aig_ManReprStart( Aig_Man_t * p, int nIdMax ); +extern void Aig_ManReprStop( Aig_Man_t * p ); +extern void Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ); +extern void Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p, int fOrdered ); +extern Aig_Man_t * Aig_ManRehash( Aig_Man_t * p ); +extern void Aig_ManMarkValidChoices( Aig_Man_t * p ); +/*=== aigRet.c ========================================================*/ +extern Aig_Man_t * Rtm_ManRetime( Aig_Man_t * p, int fForward, int nStepsMax, int fVerbose ); +/*=== aigScl.c ==========================================================*/ +extern Aig_Man_t * Aig_ManRemap( Aig_Man_t * p, Vec_Ptr_t * vMap ); +extern int Aig_ManSeqCleanup( Aig_Man_t * p ); +extern int Aig_ManCountMergeRegs( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManReduceLaches( Aig_Man_t * p, int fVerbose ); +/*=== aigSeq.c ========================================================*/ +extern int Aig_ManSeqStrash( Aig_Man_t * p, int nLatches, int * pInits ); +/*=== aigShow.c ========================================================*/ +extern void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ); +/*=== aigTable.c ========================================================*/ +extern Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ); +extern Aig_Obj_t * Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 ); +extern void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern int Aig_TableCountEntries( Aig_Man_t * p ); +extern void Aig_TableProfile( Aig_Man_t * p ); +/*=== aigTiming.c ========================================================*/ +extern void Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern int Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease ); +extern void Aig_ManStopReverseLevels( Aig_Man_t * p ); +extern void Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ); +extern void Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ); +extern void Aig_ManVerifyLevel( Aig_Man_t * p ); +extern void Aig_ManVerifyReverseLevel( Aig_Man_t * p ); +/*=== aigTruth.c ========================================================*/ +extern unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore ); +/*=== aigTsim.c ========================================================*/ +extern Aig_Man_t * Aig_ManConstReduce( Aig_Man_t * p, int fVerbose ); +/*=== aigUtil.c =========================================================*/ +extern unsigned Aig_PrimeCudd( unsigned p ); +extern void Aig_ManIncrementTravId( Aig_Man_t * p ); +extern int Aig_ManLevels( Aig_Man_t * p ); +extern void Aig_ManResetRefs( Aig_Man_t * p ); +extern void Aig_ManCleanMarkA( Aig_Man_t * p ); +extern void Aig_ManCleanMarkB( Aig_Man_t * p ); +extern void Aig_ManCleanData( Aig_Man_t * p ); +extern void Aig_ObjCleanData_rec( Aig_Obj_t * pObj ); +extern void Aig_ObjCollectMulti( Aig_Obj_t * pFunc, Vec_Ptr_t * vSuper ); +extern int Aig_ObjIsMuxType( Aig_Obj_t * pObj ); +extern int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ); +extern Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pObj, Aig_Obj_t ** ppObjT, Aig_Obj_t ** ppObjE ); +extern Aig_Obj_t * Aig_ObjReal_rec( Aig_Obj_t * pObj ); +extern void Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); +extern void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); +extern void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ); +extern void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ); +extern void Aig_ManDump( Aig_Man_t * p ); +extern void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName ); +extern void Aig_ManDumpVerilog( Aig_Man_t * p, char * pFileName ); +/*=== aigWin.c =========================================================*/ +extern void Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ); + +/*=== aigMem.c ===========================================================*/ +// fixed-size-block memory manager +extern Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax ); +extern void Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose ); +extern char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ); +extern void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ); +extern void Aig_MmFixedRestart( Aig_MmFixed_t * p ); +extern int Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p ); +extern int Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p ); +// flexible-size-block memory manager +extern Aig_MmFlex_t * Aig_MmFlexStart(); +extern void Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose ); +extern char * Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes ); +extern void Aig_MmFlexRestart( Aig_MmFlex_t * p ); +extern int Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p ); +// hierarchical memory manager +extern Aig_MmStep_t * Aig_MmStepStart( int nSteps ); +extern void Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose ); +extern char * Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes ); +extern void Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes ); +extern int Aig_MmStepReadMemUsage( Aig_MmStep_t * p ); + +/*=== aigTime.c ===========================================================*/ +extern Aig_TMan_t * Aig_TManStart( int nPis, int nPos ); +extern void Aig_TManStop( Aig_TMan_t * p ); +extern void Aig_TManCreateBox( Aig_TMan_t * p, int * pPis, int nPis, int * pPos, int nPos, float * pPiTimes, float * pPoTimes ); +extern void Aig_TManSetPiDelay( Aig_TMan_t * p, int iPi, float Delay ); +extern void Aig_TManSetPoDelay( Aig_TMan_t * p, int iPo, float Delay ); +extern void Aig_TManSetPiArrival( Aig_TMan_t * p, int iPi, float Delay ); +extern void Aig_TManSetPoRequired( Aig_TMan_t * p, int iPo, float Delay ); +extern void Aig_TManIncrementTravId( Aig_TMan_t * p ); +extern float Aig_TManGetPiArrival( Aig_TMan_t * p, int iPi ); +extern float Aig_TManGetPoRequired( Aig_TMan_t * p, int iPo ); + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/aig/aigCheck.c b/abc70930/src/aig/aig/aigCheck.c new file mode 100644 index 00000000..8c53e635 --- /dev/null +++ b/abc70930/src/aig/aig/aigCheck.c @@ -0,0 +1,163 @@ +/**CFile**************************************************************** + + FileName [aigCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [AIG checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigCheck.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the consistency of the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCheck( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pObj2; + int i; + // check primary inputs + Aig_ManForEachPi( p, pObj, i ) + { + if ( Aig_ObjFanin0(pObj) || Aig_ObjFanin1(pObj) ) + { + printf( "Aig_ManCheck: The PI node \"%p\" has fanins.\n", pObj ); + return 0; + } + } + // check primary outputs + Aig_ManForEachPo( p, pObj, i ) + { + if ( !Aig_ObjFanin0(pObj) ) + { + printf( "Aig_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj ); + return 0; + } + if ( Aig_ObjFanin1(pObj) ) + { + printf( "Aig_ManCheck: The PO node \"%p\" has second fanin.\n", pObj ); + return 0; + } + } + // check internal nodes + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + if ( !Aig_ObjFanin0(pObj) || !Aig_ObjFanin1(pObj) ) + { + printf( "Aig_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj ); + return 0; + } + if ( Aig_ObjFanin0(pObj)->Id >= Aig_ObjFanin1(pObj)->Id ) + { + printf( "Aig_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj ); + return 0; + } + pObj2 = Aig_TableLookup( p, pObj ); + if ( pObj2 != pObj ) + { + printf( "Aig_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj ); + return 0; + } + } + // count the total number of nodes + if ( Aig_ManObjNum(p) != 1 + Aig_ManPiNum(p) + Aig_ManPoNum(p) + + Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) ) + { + printf( "Aig_ManCheck: The number of created nodes is wrong.\n" ); + printf( "C1 = %d. Pi = %d. Po = %d. Buf = %d. And = %d. Xor = %d. Lat = %d. Total = %d.\n", + 1, Aig_ManPiNum(p), Aig_ManPoNum(p), Aig_ManBufNum(p), Aig_ManAndNum(p), Aig_ManExorNum(p), Aig_ManLatchNum(p), + 1 + Aig_ManPiNum(p) + Aig_ManPoNum(p) + Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) ); + printf( "Created = %d. Deleted = %d. Existing = %d.\n", + p->nCreated, p->nDeleted, p->nCreated - p->nDeleted ); + return 0; + } + // count the number of nodes in the table + if ( Aig_TableCountEntries(p) != Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) ) + { + printf( "Aig_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); + printf( "Entries = %d. And = %d. Xor = %d. Lat = %d. Total = %d.\n", + Aig_TableCountEntries(p), Aig_ManAndNum(p), Aig_ManExorNum(p), Aig_ManLatchNum(p), + Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) ); + + return 0; + } +// if ( !Aig_ManIsAcyclic(p) ) +// return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks if the markA is reset.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCheckMarkA( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + assert( pObj->fMarkA == 0 ); +} + +/**Function************************************************************* + + Synopsis [Checks the consistency of phase assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCheckPhase( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsPi(pObj) ) + assert( (int)pObj->fPhase == 0 ); + else + assert( (int)pObj->fPhase == (Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) & Aig_ObjPhaseReal(Aig_ObjChild1(pObj))) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigDfs.c b/abc70930/src/aig/aig/aigDfs.c new file mode 100644 index 00000000..dedfeb4a --- /dev/null +++ b/abc70930/src/aig/aig/aigDfs.c @@ -0,0 +1,700 @@ +/**CFile**************************************************************** + + FileName [aigDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [DFS traversal procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigDfs.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDfs_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( pObj == NULL ) + return; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); + Aig_ManDfs_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Aig_ManDfs_rec( p, Aig_ObjFanin1(pObj), vNodes ); + assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection + Aig_ObjSetTravIdCurrent(p, pObj); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + // mark constant and PIs + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + Aig_ManForEachPi( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // if there are latches, mark them + if ( Aig_ManLatchNum(p) > 0 ) + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsLatch(pObj) ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // go through the nodes + vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ) + Aig_ManDfs_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + assert( Aig_ManLatchNum(p) == 0 ); + Aig_ManIncrementTravId( p ); + // mark constant and PIs + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + Aig_ManForEachPi( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // go through the nodes + vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); + for ( i = 0; i < nNodes; i++ ) + Aig_ManDfs_rec( p, ppNodes[i], vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDfsChoices_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( pObj == NULL ) + return; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Aig_ManDfsChoices_rec( p, Aig_ObjFanin1(pObj), vNodes ); + Aig_ManDfsChoices_rec( p, p->pEquivs[pObj->Id], vNodes ); + assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection + Aig_ObjSetTravIdCurrent(p, pObj); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfsChoices( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + assert( p->pEquivs != NULL ); + Aig_ManIncrementTravId( p ); + // mark constant and PIs + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + Aig_ManForEachPi( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // go through the nodes + vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the reverse DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDfsReverse_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + Aig_Obj_t * pFanout; + int iFanout = -1, i; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + Aig_ManDfsReverse_rec( p, pFanout, vNodes ); + assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection + Aig_ObjSetTravIdCurrent(p, pObj); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the reverse DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + // mark POs + Aig_ManForEachPo( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // if there are latches, mark them + if ( Aig_ManLatchNum(p) > 0 ) + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsLatch(pObj) ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // go through the nodes + vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ) + Aig_ManDfsReverse_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the max number of levels in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManLevelNum( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, LevelsMax; + LevelsMax = 0; + Aig_ManForEachPo( p, pObj, i ) + LevelsMax = AIG_MAX( LevelsMax, (int)Aig_ObjFanin0(pObj)->Level ); + return LevelsMax; +} + +/**Function************************************************************* + + Synopsis [Computes the max number of levels in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCountLevels( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i, LevelsMax, Level0, Level1; + // initialize the levels + Aig_ManConst1(p)->iData = 0; + Aig_ManForEachPi( p, pObj, i ) + pObj->iData = 0; + // compute levels in a DFS order + vNodes = Aig_ManDfs( p ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + Level0 = Aig_ObjFanin0(pObj)->iData; + Level1 = Aig_ObjFanin1(pObj)->iData; + pObj->iData = 1 + Aig_ObjIsExor(pObj) + AIG_MAX(Level0, Level1); + } + Vec_PtrFree( vNodes ); + // get levels of the POs + LevelsMax = 0; + Aig_ManForEachPo( p, pObj, i ) + LevelsMax = AIG_MAX( LevelsMax, Aig_ObjFanin0(pObj)->iData ); + return LevelsMax; +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ConeMark_rec( Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) + return; + Aig_ConeMark_rec( Aig_ObjFanin0(pObj) ); + Aig_ConeMark_rec( Aig_ObjFanin1(pObj) ); + assert( !Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ConeCleanAndMark_rec( Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) + return; + Aig_ConeCleanAndMark_rec( Aig_ObjFanin0(pObj) ); + Aig_ConeCleanAndMark_rec( Aig_ObjFanin1(pObj) ); + assert( !Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjSetMarkA( pObj ); + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ConeCountAndMark_rec( Aig_Obj_t * pObj ) +{ + int Counter; + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) + return 0; + Counter = 1 + Aig_ConeCountAndMark_rec( Aig_ObjFanin0(pObj) ) + + Aig_ConeCountAndMark_rec( Aig_ObjFanin1(pObj) ); + assert( !Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjSetMarkA( pObj ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) || !Aig_ObjIsMarkA(pObj) ) + return; + Aig_ConeUnmark_rec( Aig_ObjFanin0(pObj) ); + Aig_ConeUnmark_rec( Aig_ObjFanin1(pObj) ); + assert( Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjClearMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_DagSize( Aig_Obj_t * pObj ) +{ + int Counter; + Counter = Aig_ConeCountAndMark_rec( Aig_Regular(pObj) ); + Aig_ConeUnmark_rec( Aig_Regular(pObj) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_SupportSize_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int * pCounter ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsPi(pObj) ) + { + (*pCounter)++; + return; + } + assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); + Aig_SupportSize_rec( p, Aig_ObjFanin0(pObj), pCounter ); + if ( Aig_ObjFanin1(pObj) ) + Aig_SupportSize_rec( p, Aig_ObjFanin1(pObj), pCounter ); +} + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_SupportSize( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + int Counter = 0; + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsPo(pObj) ); + Aig_ManIncrementTravId( p ); + Aig_SupportSize_rec( p, pObj, &Counter ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Transfer_rec( Aig_Man_t * pDest, Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) + return; + Aig_Transfer_rec( pDest, Aig_ObjFanin0(pObj) ); + Aig_Transfer_rec( pDest, Aig_ObjFanin1(pObj) ); + pObj->pData = Aig_And( pDest, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + assert( !Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pRoot, int nVars ) +{ + Aig_Obj_t * pObj; + int i; + // solve simple cases + if ( pSour == pDest ) + return pRoot; + if ( Aig_ObjIsConst1( Aig_Regular(pRoot) ) ) + return Aig_NotCond( Aig_ManConst1(pDest), Aig_IsComplement(pRoot) ); + // set the PI mapping + Aig_ManForEachPi( pSour, pObj, i ) + { + if ( i == nVars ) + break; + pObj->pData = Aig_IthVar(pDest, i); + } + // transfer and set markings + Aig_Transfer_rec( pDest, Aig_Regular(pRoot) ); + // clear the markings + Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); + return Aig_NotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); +} + +/**Function************************************************************* + + Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Compose_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFunc, Aig_Obj_t * pVar ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsMarkA(pObj) ) + return; + if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsPi(pObj) ) + { + pObj->pData = pObj == pVar ? pFunc : pObj; + return; + } + Aig_Compose_rec( p, Aig_ObjFanin0(pObj), pFunc, pVar ); + Aig_Compose_rec( p, Aig_ObjFanin1(pObj), pFunc, pVar ); + pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + assert( !Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ) +{ + // quit if the PI variable is not defined + if ( iVar >= Aig_ManPiNum(p) ) + { + printf( "Aig_Compose(): The PI variable %d is not defined.\n", iVar ); + return NULL; + } + // recursively perform composition + Aig_Compose_rec( p, Aig_Regular(pRoot), pFunc, Aig_ManPi(p, iVar) ); + // clear the markings + Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); + return Aig_NotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); +} + +/**Function************************************************************* + + Synopsis [Computes the internal nodes of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCollectCut_rec( Aig_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ +// Aig_Obj_t * pFan0 = Aig_ObjFanin0(pNode); +// Aig_Obj_t * pFan1 = Aig_ObjFanin1(pNode); + if ( pNode->fMarkA ) + return; + pNode->fMarkA = 1; + assert( Aig_ObjIsNode(pNode) ); + Aig_ObjCollectCut_rec( Aig_ObjFanin0(pNode), vNodes ); + Aig_ObjCollectCut_rec( Aig_ObjFanin1(pNode), vNodes ); + Vec_PtrPush( vNodes, pNode ); +//printf( "added %d ", pNode->Id ); +} + +/**Function************************************************************* + + Synopsis [Computes the internal nodes of the cut.] + + Description [Does not include the leaves of the cut.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ) +{ + Aig_Obj_t * pObj; + int i; + // collect and mark the leaves + Vec_PtrClear( vNodes ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + assert( pObj->fMarkA == 0 ); + pObj->fMarkA = 1; +// printf( "%d " , pObj->Id ); + } +//printf( "\n" ); + // collect and mark the nodes + Aig_ObjCollectCut_rec( pRoot, vNodes ); + // clean the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->fMarkA = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->fMarkA = 0; +} + + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjCollectSuper_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Aig_Regular(pObj)->fMarkA ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pObj ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Aig_Not(pObj) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1) ) + { + Vec_PtrPush( vSuper, pObj ); + Aig_Regular(pObj)->fMarkA = 1; + return 0; + } + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsNode(pObj) ); + // go through the branches + RetValue1 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper ); + RetValue2 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + int RetValue, i; + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsNode(pObj) ); + // collect the nodes in the implication supergate + Vec_PtrClear( vSuper ); + RetValue = Aig_ObjCollectSuper_rec( pObj, pObj, vSuper ); + assert( Vec_PtrSize(vSuper) > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( vSuper, pObj, i ) + Aig_Regular(pObj)->fMarkA = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vSuper->nSize = 0; + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigFanout.c b/abc70930/src/aig/aig/aigFanout.c new file mode 100644 index 00000000..d0beb128 --- /dev/null +++ b/abc70930/src/aig/aig/aigFanout.c @@ -0,0 +1,189 @@ +/**CFile**************************************************************** + + FileName [aigFanout.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Fanout manipulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigFanout.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +// 0: first iFan +// 1: prev iFan0 +// 2: prev iFan1 +// 3: next iFan0 +// 4: next iFan1 + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Aig_FanoutCreate( int FanId, int Num ) { assert( Num < 2 ); return (FanId << 1) | Num; } +static inline int * Aig_FanoutObj( int * pData, int ObjId ) { return pData + 5*ObjId; } +static inline int * Aig_FanoutPrev( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 1 + (iFan & 1); } +static inline int * Aig_FanoutNext( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 3 + (iFan & 1); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create fanout for all objects in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFanoutStart( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + assert( Aig_ManBufNum(p) == 0 ); + // allocate fanout datastructure + assert( p->pFanData == NULL ); + p->nFansAlloc = 2 * Aig_ManObjNumMax(p); + if ( p->nFansAlloc < (1<<12) ) + p->nFansAlloc = (1<<12); + p->pFanData = ALLOC( int, 5 * p->nFansAlloc ); + memset( p->pFanData, 0, sizeof(int) * 5 * p->nFansAlloc ); + // add fanouts for all objects + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjChild0(pObj) ) + Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); + if ( Aig_ObjChild1(pObj) ) + Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Deletes fanout for all objects in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFanoutStop( Aig_Man_t * p ) +{ + assert( p->pFanData != NULL ); + FREE( p->pFanData ); + p->nFansAlloc = 0; +} + +/**Function************************************************************* + + Synopsis [Adds fanout (pFanout) of node (pObj).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) +{ + int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; + assert( p->pFanData ); + assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) ); + assert( pFanout->Id > 0 ); + if ( pObj->Id >= p->nFansAlloc || pFanout->Id >= p->nFansAlloc ) + { + int nFansAlloc = 2 * AIG_MAX( pObj->Id, pFanout->Id ); + p->pFanData = REALLOC( int, p->pFanData, 5 * nFansAlloc ); + memset( p->pFanData + 5 * p->nFansAlloc, 0, sizeof(int) * 5 * (nFansAlloc - p->nFansAlloc) ); + p->nFansAlloc = nFansAlloc; + } + assert( pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc ); + iFan = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) ); + pPrevC = Aig_FanoutPrev( p->pFanData, iFan ); + pNextC = Aig_FanoutNext( p->pFanData, iFan ); + pFirst = Aig_FanoutObj( p->pFanData, pObj->Id ); + if ( *pFirst == 0 ) + { + *pFirst = iFan; + *pPrevC = iFan; + *pNextC = iFan; + } + else + { + pPrev = Aig_FanoutPrev( p->pFanData, *pFirst ); + pNext = Aig_FanoutNext( p->pFanData, *pPrev ); + assert( *pNext == *pFirst ); + *pPrevC = *pPrev; + *pNextC = *pFirst; + *pPrev = iFan; + *pNext = iFan; + } +} + +/**Function************************************************************* + + Synopsis [Removes fanout (pFanout) of node (pObj).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) +{ + int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; + assert( p->pFanData && pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc ); + assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) ); + assert( pFanout->Id > 0 ); + iFan = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) ); + pPrevC = Aig_FanoutPrev( p->pFanData, iFan ); + pNextC = Aig_FanoutNext( p->pFanData, iFan ); + pPrev = Aig_FanoutPrev( p->pFanData, *pNextC ); + pNext = Aig_FanoutNext( p->pFanData, *pPrevC ); + assert( *pPrev == iFan ); + assert( *pNext == iFan ); + pFirst = Aig_FanoutObj( p->pFanData, pObj->Id ); + assert( *pFirst > 0 ); + if ( *pFirst == iFan ) + { + if ( *pNextC == iFan ) + { + *pFirst = 0; + *pPrev = 0; + *pNext = 0; + *pPrevC = 0; + *pNextC = 0; + return; + } + *pFirst = *pNextC; + } + *pPrev = *pPrevC; + *pNext = *pNextC; + *pPrevC = 0; + *pNextC = 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigMan.c b/abc70930/src/aig/aig/aigMan.c new file mode 100644 index 00000000..fed6aebd --- /dev/null +++ b/abc70930/src/aig/aig/aigMan.c @@ -0,0 +1,325 @@ +/**CFile**************************************************************** + + FileName [aigMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [AIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [The argument of this procedure is a soft limit on the + the number of nodes, or 0 if the limit is unknown.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManStart( int nNodesMax ) +{ + Aig_Man_t * p; + if ( nNodesMax <= 0 ) + nNodesMax = 10007; + // start the manager + p = ALLOC( Aig_Man_t, 1 ); + memset( p, 0, sizeof(Aig_Man_t) ); + // perform initializations + p->nTravIds = 1; + p->fCatchExor = 0; + // allocate arrays for nodes + p->vPis = Vec_PtrAlloc( 100 ); + p->vPos = Vec_PtrAlloc( 100 ); + p->vObjs = Vec_PtrAlloc( 1000 ); + p->vBufs = Vec_PtrAlloc( 100 ); + // prepare the internal memory manager + p->pMemObjs = Aig_MmFixedStart( sizeof(Aig_Obj_t), nNodesMax ); + // create the constant node + p->pConst1 = Aig_ManFetchMemory( p ); + p->pConst1->Type = AIG_OBJ_CONST1; + p->pConst1->fPhase = 1; + p->nObjs[AIG_OBJ_CONST1]++; + // start the table + p->nTableSize = Aig_PrimeCudd( nNodesMax ); + p->pTable = ALLOC( Aig_Obj_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + // create the PIs + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePi(pNew); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj->pData ) + return pObj->pData; + Aig_ManDup_rec( pNew, p, Aig_ObjFanin0(pObj) ); + if ( Aig_ObjIsBuf(pObj) ) + return pObj->pData = Aig_ObjChild0Copy(pObj); + Aig_ManDup_rec( pNew, p, Aig_ObjFanin1(pObj) ); + return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDup( Aig_Man_t * p, int fOrdered ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->nRegs = p->nRegs; + pNew->nAsserts = p->nAsserts; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePi(pNew); + // duplicate internal nodes + if ( fOrdered ) + { + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsBuf(pObj) ) + pObj->pData = Aig_ObjChild0Copy(pObj); + else if ( Aig_ObjIsNode(pObj) ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + else + { + Aig_ManForEachObj( p, pObj, i ) + if ( !Aig_ObjIsPo(pObj) ) + { + Aig_ManDup_rec( pNew, p, pObj ); + assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level ); + } + } + // add the POs + Aig_ManForEachPo( p, pObj, i ) + Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDup(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Extracts the miter composed of XOR of the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePi(pNew); + // dump the nodes + Aig_ManDup_rec( pNew, p, pNode1 ); + Aig_ManDup_rec( pNew, p, pNode2 ); + // construct the EXOR + pObj = Aig_Exor( pNew, pNode1->pData, pNode2->pData ); + pObj = Aig_NotCond( pObj, Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ); + // add the PO + Aig_ObjCreatePo( pNew, pObj ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDup(): The check has failed.\n" ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManStop( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + if ( p->vMapped ) + Vec_PtrFree( p->vMapped ); + // print time + if ( p->time1 ) { PRT( "time1", p->time1 ); } + if ( p->time2 ) { PRT( "time2", p->time2 ); } + // delete timing + if ( p->pManTime ) + Aig_TManStop( p->pManTime ); + // delete fanout + if ( p->pFanData ) + Aig_ManFanoutStop( p ); + // make sure the nodes have clean marks + Aig_ManForEachObj( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); +// Aig_TableProfile( p ); + Aig_MmFixedStop( p->pMemObjs, 0 ); + if ( p->vPis ) Vec_PtrFree( p->vPis ); + if ( p->vPos ) Vec_PtrFree( p->vPos ); + if ( p->vObjs ) Vec_PtrFree( p->vObjs ); + if ( p->vBufs ) Vec_PtrFree( p->vBufs ); + if ( p->vLevelR ) Vec_IntFree( p->vLevelR ); + if ( p->vLevels ) Vec_VecFree( p->vLevels ); + if ( p->vFlopNums) Vec_IntFree( p->vFlopNums ); + FREE( p->pName ); + FREE( p->pObjCopies ); + FREE( p->pReprs ); + FREE( p->pEquivs ); + free( p->pTable ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCleanup( Aig_Man_t * p ) +{ + Vec_Ptr_t * vObjs; + Aig_Obj_t * pNode; + int i, nNodesOld; + nNodesOld = Aig_ManNodeNum(p); + // collect roots of dangling nodes + vObjs = Vec_PtrAlloc( 100 ); + Aig_ManForEachObj( p, pNode, i ) + if ( Aig_ObjIsNode(pNode) && Aig_ObjRefs(pNode) == 0 ) + Vec_PtrPush( vObjs, pNode ); + // recursively remove dangling nodes + Vec_PtrForEachEntry( vObjs, pNode, i ) + Aig_ObjDelete_rec( p, pNode, 1 ); + Vec_PtrFree( vObjs ); + return nNodesOld - Aig_ManNodeNum(p); +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPrintStats( Aig_Man_t * p ) +{ + printf( "PI/PO/Lat = %5d/%5d/%5d ", Aig_ManPiNum(p), Aig_ManPoNum(p), Aig_ManLatchNum(p) ); + printf( "A = %7d. ", Aig_ManAndNum(p) ); + if ( Aig_ManExorNum(p) ) + printf( "X = %5d. ", Aig_ManExorNum(p) ); +// if ( Aig_ManBufNum(p) ) + printf( "B = %5d. ", Aig_ManBufNum(p) ); +// printf( "Cre = %6d. ", p->nCreated ); +// printf( "Del = %6d. ", p->nDeleted ); +// printf( "Lev = %3d. ", Aig_ManCountLevels(p) ); + printf( "Max = %7d. ", Aig_ManObjNumMax(p) ); + printf( "Lev = %3d. ", Aig_ManLevels(p) ); + if ( Aig_ManRegNum(p) ) + printf( "Lat = %5d. ", Aig_ManRegNum(p) ); + printf( "\n" ); + fflush( stdout ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigMem.c b/abc70930/src/aig/aig/aigMem.c new file mode 100644 index 00000000..dab90777 --- /dev/null +++ b/abc70930/src/aig/aig/aigMem.c @@ -0,0 +1,598 @@ +/**CFile**************************************************************** + + FileName [aigMem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Memory managers.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigMem.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Aig_MmFixed_t_ +{ + // information about individual entries + int nEntrySize; // the size of one entry + int nEntriesAlloc; // the total number of entries allocated + int nEntriesUsed; // the number of entries in use + int nEntriesMax; // the max number of entries in use + char * pEntriesFree; // the linked list of free entries + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Aig_MmFlex_t_ +{ + // information about individual entries + int nEntriesUsed; // the number of entries allocated + char * pCurrent; // the current pointer to free memory + char * pEnd; // the first entry outside the free memory + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Aig_MmStep_t_ +{ + int nMems; // the number of fixed memory managers employed + Aig_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc + int nMapSize; // the size of the memory array + Aig_MmFixed_t ** pMap; // maps the number of bytes into its memory manager +}; + +#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#define REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates memory pieces of fixed size.] + + Description [The size of the chunk is computed as the minimum of + 1024 entries and 64K. Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax ) +{ + Aig_MmFixed_t * p; + + p = ALLOC( Aig_MmFixed_t, 1 ); + memset( p, 0, sizeof(Aig_MmFixed_t) ); + + p->nEntrySize = nEntrySize; + p->nEntriesAlloc = 0; + p->nEntriesUsed = 0; + p->pEntriesFree = NULL; + + p->nChunkSize = nEntriesMax / 8; + if ( p->nChunkSize < 8 ) + p->nChunkSize = 8; + + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", + p->nEntrySize, p->nChunkSize, p->nChunks ); + printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", + p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ) +{ + char * pTemp; + int i; + + // check if there are still free entries + if ( p->nEntriesUsed == p->nEntriesAlloc ) + { // need to allocate more entries + assert( p->pEntriesFree == NULL ); + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); + p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; + // transform these entries into a linked list + pTemp = p->pEntriesFree; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pEntriesFree; + // add to the number of entries allocated + p->nEntriesAlloc += p->nChunkSize; + } + // incrememt the counter of used entries + p->nEntriesUsed++; + if ( p->nEntriesMax < p->nEntriesUsed ) + p->nEntriesMax = p->nEntriesUsed; + // return the first entry in the free entry list + pTemp = p->pEntriesFree; + p->pEntriesFree = *((char **)pTemp); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ) +{ + // decrement the counter of used entries + p->nEntriesUsed--; + // add the entry to the linked list of free entries + *((char **)pEntry) = p->pEntriesFree; + p->pEntriesFree = pEntry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmFixedRestart( Aig_MmFixed_t * p ) +{ + int i; + char * pTemp; + if ( p->nChunks == 0 ) + return; + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + p->nChunks = 1; + // transform these entries into a linked list + pTemp = p->pChunks[0]; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // set the free entry list + p->pEntriesFree = p->pChunks[0]; + // set the correct statistics + p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; + p->nMemoryUsed = 0; + p->nEntriesAlloc = p->nChunkSize; + p->nEntriesUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p ) +{ + return p->nMemoryAlloc; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p ) +{ + return p->nEntriesMax; +} + + + +/**Function************************************************************* + + Synopsis [Allocates entries of flexible size.] + + Description [Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_MmFlex_t * Aig_MmFlexStart() +{ + Aig_MmFlex_t * p; + + p = ALLOC( Aig_MmFlex_t, 1 ); + memset( p, 0, sizeof(Aig_MmFlex_t) ); + + p->nEntriesUsed = 0; + p->pCurrent = NULL; + p->pEnd = NULL; + + p->nChunkSize = (1 << 18); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", + p->nChunkSize, p->nChunks ); + printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", + p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes ) +{ + char * pTemp; + // check if there are still free entries + if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) + { // need to allocate more entries + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + if ( nBytes > p->nChunkSize ) + { + // resize the chunk size if more memory is requested than it can give + // (ideally, this should never happen) + p->nChunkSize = 2 * nBytes; + } + p->pCurrent = ALLOC( char, p->nChunkSize ); + p->pEnd = p->pCurrent + p->nChunkSize; + p->nMemoryAlloc += p->nChunkSize; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pCurrent; + } + assert( p->pCurrent + nBytes <= p->pEnd ); + // increment the counter of used entries + p->nEntriesUsed++; + // keep track of the memory used + p->nMemoryUsed += nBytes; + // return the next entry + pTemp = p->pCurrent; + p->pCurrent += nBytes; + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmFlexRestart( Aig_MmFlex_t * p ) +{ + int i; + if ( p->nChunks == 0 ) + return; + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + p->nChunks = 1; + p->nMemoryAlloc = p->nChunkSize; + // transform these entries into a linked list + p->pCurrent = p->pChunks[0]; + p->pEnd = p->pCurrent + p->nChunkSize; + p->nEntriesUsed = 0; + p->nMemoryUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p ) +{ + return p->nMemoryUsed; +} + + + + + +/**Function************************************************************* + + Synopsis [Starts the hierarchical memory manager.] + + Description [This manager can allocate entries of any size. + Iternally they are mapped into the entries with the number of bytes + equal to the power of 2. The smallest entry size is 8 bytes. The + next one is 16 bytes etc. So, if the user requests 6 bytes, he gets + 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. + The input parameters "nSteps" says how many fixed memory managers + are employed internally. Calling this procedure with nSteps equal + to 10 results in 10 hierarchically arranged internal memory managers, + which can allocate up to 4096 (1Kb) entries. Requests for larger + entries are handed over to malloc() and then free()ed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_MmStep_t * Aig_MmStepStart( int nSteps ) +{ + Aig_MmStep_t * p; + int i, k; + p = ALLOC( Aig_MmStep_t, 1 ); + memset( p, 0, sizeof(Aig_MmStep_t) ); + p->nMems = nSteps; + // start the fixed memory managers + p->pMems = ALLOC( Aig_MmFixed_t *, p->nMems ); + for ( i = 0; i < p->nMems; i++ ) + p->pMems[i] = Aig_MmFixedStart( (8<nMapSize = (4<nMems); + p->pMap = ALLOC( Aig_MmFixed_t *, p->nMapSize+1 ); + p->pMap[0] = NULL; + for ( k = 1; k <= 4; k++ ) + p->pMap[k] = p->pMems[0]; + for ( i = 0; i < p->nMems; i++ ) + for ( k = (4<pMap[k] = p->pMems[i]; +//for ( i = 1; i < 100; i ++ ) +//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose ) +{ + int i; + for ( i = 0; i < p->nMems; i++ ) + Aig_MmFixedStop( p->pMems[i], fVerbose ); +// if ( p->pLargeChunks ) +// { +// for ( i = 0; i < p->nLargeChunks; i++ ) +// free( p->pLargeChunks[i] ); +// free( p->pLargeChunks ); +// } + free( p->pMems ); + free( p->pMap ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Creates the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes ) +{ + if ( nBytes == 0 ) + return NULL; + if ( nBytes > p->nMapSize ) + { +// printf( "Allocating %d bytes.\n", nBytes ); +/* + if ( p->nLargeChunks == p->nLargeChunksAlloc ) + { + if ( p->nLargeChunksAlloc == 0 ) + p->nLargeChunksAlloc = 5; + p->nLargeChunksAlloc *= 2; + p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); + } + p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes ); + return p->pLargeChunks[ p->nLargeChunks - 1 ]; +*/ + return ALLOC( char, nBytes ); + } + return Aig_MmFixedEntryFetch( p->pMap[nBytes] ); +} + + +/**Function************************************************************* + + Synopsis [Recycles the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes ) +{ + if ( nBytes == 0 ) + return; + if ( nBytes > p->nMapSize ) + { + free( pEntry ); + return; + } + Aig_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_MmStepReadMemUsage( Aig_MmStep_t * p ) +{ + int i, nMemTotal = 0; + for ( i = 0; i < p->nMems; i++ ) + nMemTotal += p->pMems[i]->nMemoryAlloc; + return nMemTotal; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/aig/aig/aigMffc.c b/abc70930/src/aig/aig/aigMffc.c new file mode 100644 index 00000000..47ce896d --- /dev/null +++ b/abc70930/src/aig/aig/aigMffc.c @@ -0,0 +1,297 @@ +/**CFile**************************************************************** + + FileName [aigMffc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Computation of MFFCs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigMffc.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Dereferences the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin ) +{ + Aig_Obj_t * pFanin; + int Counter = 0; + if ( Aig_ObjIsPi(pNode) ) + return 0; + // consider the first fanin + pFanin = Aig_ObjFanin0(pNode); + assert( pFanin->nRefs > 0 ); + if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeDeref_rec( pFanin, LevelMin ); + // skip the buffer + if ( Aig_ObjIsBuf(pNode) ) + return Counter; + assert( Aig_ObjIsNode(pNode) ); + // consider the second fanin + pFanin = Aig_ObjFanin1(pNode); + assert( pFanin->nRefs > 0 ); + if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeDeref_rec( pFanin, LevelMin ); + return Counter + 1; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin ) +{ + Aig_Obj_t * pFanin; + int Counter = 0; + if ( Aig_ObjIsPi(pNode) ) + return 0; + // consider the first fanin + pFanin = Aig_ObjFanin0(pNode); + if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeRef_rec( pFanin, LevelMin ); + // skip the buffer + if ( Aig_ObjIsBuf(pNode) ) + return Counter; + assert( Aig_ObjIsNode(pNode) ); + // consider the second fanin + pFanin = Aig_ObjFanin1(pNode); + if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeRef_rec( pFanin, LevelMin ); + return Counter + 1; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeRefLabel_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin ) +{ + Aig_Obj_t * pFanin; + int Counter = 0; + if ( Aig_ObjIsPi(pNode) ) + return 0; + Aig_ObjSetTravIdCurrent( p, pNode ); + // consider the first fanin + pFanin = Aig_ObjFanin0(pNode); + if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin ); + if ( Aig_ObjIsBuf(pNode) ) + return Counter; + assert( Aig_ObjIsNode(pNode) ); + // consider the second fanin + pFanin = Aig_ObjFanin1(pNode); + if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin ); + return Counter + 1; +} + +/**Function************************************************************* + + Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_NodeMffsSupp_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin, Vec_Ptr_t * vSupp, int fTopmost, Aig_Obj_t * pObjSkip ) +{ + // skip visited nodes + if ( Aig_ObjIsTravIdCurrent(p, pNode) ) + return; + Aig_ObjSetTravIdCurrent(p, pNode); + // add to the new support nodes + if ( !fTopmost && pNode != pObjSkip && (Aig_ObjIsPi(pNode) || pNode->nRefs > 0 || pNode->Level <= LevelMin) ) + { + if ( vSupp ) Vec_PtrPush( vSupp, pNode ); + return; + } + assert( Aig_ObjIsNode(pNode) ); + // recur on the children + Aig_NodeMffsSupp_rec( p, Aig_ObjFanin0(pNode), LevelMin, vSupp, 0, pObjSkip ); + Aig_NodeMffsSupp_rec( p, Aig_ObjFanin1(pNode), LevelMin, vSupp, 0, pObjSkip ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of depth-limited MFFC.] + + Description [Returns the number of internal nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp ) +{ + int ConeSize1, ConeSize2; + assert( !Aig_IsComplement(pNode) ); + assert( Aig_ObjIsNode(pNode) ); + if ( vSupp ) Vec_PtrClear( vSupp ); + Aig_ManIncrementTravId( p ); + ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin ); + Aig_NodeMffsSupp_rec( p, pNode, LevelMin, vSupp, 1, NULL ); + ConeSize2 = Aig_NodeRef_rec( pNode, LevelMin ); + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 > 0 ); + return ConeSize1; +} + +/**Function************************************************************* + + Synopsis [Labels the nodes in the MFFC.] + + Description [Returns the number of internal nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode ) +{ + int ConeSize1, ConeSize2; + assert( !Aig_IsComplement(pNode) ); + assert( Aig_ObjIsNode(pNode) ); + Aig_ManIncrementTravId( p ); + ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); + ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 > 0 ); + return ConeSize1; +} + +/**Function************************************************************* + + Synopsis [Labels the nodes in the MFFC.] + + Description [Returns the number of internal nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves ) +{ + Aig_Obj_t * pObj; + int i, ConeSize1, ConeSize2; + assert( !Aig_IsComplement(pNode) ); + assert( Aig_ObjIsNode(pNode) ); + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->nRefs++; + ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); + ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->nRefs--; + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 > 0 ); + return ConeSize1; +} + +/**Function************************************************************* + + Synopsis [Expands the cut by adding the most closely related node.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult ) +{ + Aig_Obj_t * pObj, * pLeafBest; + int i, LevelMax, ConeSize1, ConeSize2, ConeCur1, ConeCur2, ConeBest; + // dereference the current cut + LevelMax = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + LevelMax = AIG_MAX( LevelMax, (int)pObj->Level ); + if ( LevelMax == 0 ) + return 0; + // dereference the cut + ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); + // try expanding each node in the boundary + ConeBest = AIG_INFINITY; + pLeafBest = NULL; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + if ( (int)pObj->Level != LevelMax ) + continue; + ConeCur1 = Aig_NodeDeref_rec( pObj, 0 ); + if ( ConeBest > ConeCur1 ) + { + ConeBest = ConeCur1; + pLeafBest = pObj; + } + ConeCur2 = Aig_NodeRef_rec( pObj, 0 ); + assert( ConeCur1 == ConeCur2 ); + } + assert( pLeafBest != NULL ); + assert( Aig_ObjIsNode(pLeafBest) ); + // deref the best leaf + ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0 ); + // collect the cut nodes + Vec_PtrClear( vResult ); + Aig_ManIncrementTravId( p ); + Aig_NodeMffsSupp_rec( p, pNode, 0, vResult, 1, pLeafBest ); + // ref the nodes + ConeCur2 = Aig_NodeRef_rec( pLeafBest, 0 ); + assert( ConeCur1 == ConeCur2 ); + // ref the original node + ConeSize2 = Aig_NodeRef_rec( pNode, 0 ); + assert( ConeSize1 == ConeSize2 ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigObj.c b/abc70930/src/aig/aig/aigObj.c new file mode 100644 index 00000000..8323249e --- /dev/null +++ b/abc70930/src/aig/aig/aigObj.c @@ -0,0 +1,416 @@ +/**CFile**************************************************************** + + FileName [aigObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Adding/removing objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigObj.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates primary input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ObjCreatePi( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + pObj = Aig_ManFetchMemory( p ); + pObj->Type = AIG_OBJ_PI; + Vec_PtrPush( p->vPis, pObj ); + p->nObjs[AIG_OBJ_PI]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates primary output with the given driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ObjCreatePo( Aig_Man_t * p, Aig_Obj_t * pDriver ) +{ + Aig_Obj_t * pObj; + pObj = Aig_ManFetchMemory( p ); + pObj->Type = AIG_OBJ_PO; + Vec_PtrPush( p->vPos, pObj ); + Aig_ObjConnect( p, pObj, pDriver, NULL ); + p->nObjs[AIG_OBJ_PO]++; + return pObj; +} + + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ) +{ + Aig_Obj_t * pObj; + assert( !Aig_IsComplement(pGhost) ); + assert( Aig_ObjIsHash(pGhost) ); + assert( pGhost == &p->Ghost ); + // get memory for the new object + pObj = Aig_ManFetchMemory( p ); + pObj->Type = pGhost->Type; + // add connections + Aig_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); + // update node counters of the manager + p->nObjs[Aig_ObjType(pObj)]++; + assert( pObj->pData == NULL ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ) +{ + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsPi(pObj) ); + // add the first fanin + pObj->pFanin0 = pFan0; + pObj->pFanin1 = pFan1; + // increment references of the fanins and add their fanouts + if ( pFan0 != NULL ) + { + assert( Aig_ObjFanin0(pObj)->Type > 0 ); + Aig_ObjRef( Aig_ObjFanin0(pObj) ); + if ( p->pFanData ) + Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); + } + if ( pFan1 != NULL ) + { + assert( Aig_ObjFanin1(pObj)->Type > 0 ); + Aig_ObjRef( Aig_ObjFanin1(pObj) ); + if ( p->pFanData ) + Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj ); + } + // set level and phase + pObj->Level = Aig_ObjLevelNew( pObj ); + pObj->fPhase = Aig_ObjPhaseReal(pFan0) & Aig_ObjPhaseReal(pFan1); + // add the node to the structural hash table + if ( Aig_ObjIsHash(pObj) ) + Aig_TableInsert( p, pObj ); + // add the node to the dynamically updated topological order +// if ( p->pOrderData && Aig_ObjIsNode(pObj) ) +// Aig_ObjOrderInsert( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Disconnects the object from the fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + // remove connections + if ( pObj->pFanin0 != NULL ) + { + if ( p->pFanData ) + Aig_ObjRemoveFanout( p, Aig_ObjFanin0(pObj), pObj ); + Aig_ObjDeref(Aig_ObjFanin0(pObj)); + } + if ( pObj->pFanin1 != NULL ) + { + if ( p->pFanData ) + Aig_ObjRemoveFanout( p, Aig_ObjFanin1(pObj), pObj ); + Aig_ObjDeref(Aig_ObjFanin1(pObj)); + } + // remove the node from the structural hash table + if ( Aig_ObjIsHash(pObj) ) + Aig_TableDelete( p, pObj ); + // add the first fanin + pObj->pFanin0 = NULL; + pObj->pFanin1 = NULL; + // remove the node from the dynamically updated topological order +// if ( p->pOrderData && Aig_ObjIsNode(pObj) ) +// Aig_ObjOrderRemove( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Deletes the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsTerm(pObj) ); + assert( Aig_ObjRefs(pObj) == 0 ); + if ( p->pFanData && Aig_ObjIsBuf(pObj) ) + Vec_PtrRemove( p->vBufs, pObj ); + p->nObjs[pObj->Type]--; + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Aig_ManRecycleMemory( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Deletes the MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsPi(pObj) ) + return; + assert( !Aig_ObjIsPo(pObj) ); + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); + Aig_ObjDisconnect( p, pObj ); + if ( fFreeTop ) + Aig_ObjDelete( p, pObj ); + if ( pFanin0 && !Aig_ObjIsNone(pFanin0) && Aig_ObjRefs(pFanin0) == 0 ) + Aig_ObjDelete_rec( p, pFanin0, 1 ); + if ( pFanin1 && !Aig_ObjIsNone(pFanin1) && Aig_ObjRefs(pFanin1) == 0 ) + Aig_ObjDelete_rec( p, pFanin1, 1 ); +} + +/**Function************************************************************* + + Synopsis [Replaces the first fanin of the node by the new fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew ) +{ + Aig_Obj_t * pFaninOld; + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsPo(pObj) ); + pFaninOld = Aig_ObjFanin0(pObj); + // decrement ref and remove fanout + if ( p->pFanData ) + Aig_ObjRemoveFanout( p, pFaninOld, pObj ); + Aig_ObjDeref( pFaninOld ); + // update the fanin + pObj->pFanin0 = pFaninNew; + // increment ref and add fanout + if ( p->pFanData ) + Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); + Aig_ObjRef( Aig_ObjFanin0(pObj) ); + // get rid of old fanin + if ( !Aig_ObjIsPi(pFaninOld) && !Aig_ObjIsConst1(pFaninOld) && Aig_ObjRefs(pFaninOld) == 0 ) + Aig_ObjDelete_rec( p, pFaninOld, 1 ); +} + +/**Function************************************************************* + + Synopsis [Replaces node with a buffer fanin by a node without them.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_NodeFixBufferFanins( Aig_Man_t * p, Aig_Obj_t * pObj, int fNodesOnly, int fUpdateLevel ) +{ + Aig_Obj_t * pFanReal0, * pFanReal1, * pResult; + p->nBufFixes++; + if ( Aig_ObjIsPo(pObj) ) + { + assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ); + pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + assert( Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) == Aig_ObjPhaseReal(pFanReal0) ); + Aig_ObjPatchFanin0( p, pObj, pFanReal0 ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) || Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) ); + // get the real fanins + pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + pFanReal1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); + // get the new node + if ( Aig_ObjIsNode(pObj) ) + pResult = Aig_Oper( p, pFanReal0, pFanReal1, Aig_ObjType(pObj) ); +// else if ( Aig_ObjIsLatch(pObj) ) +// pResult = Aig_Latch( p, pFanReal0, Aig_ObjInit(pObj) ); + else + assert( 0 ); + // replace the node with buffer by the node without buffer + Aig_ObjReplace( p, pObj, pResult, fNodesOnly, fUpdateLevel ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManPropagateBuffers( Aig_Man_t * p, int fNodesOnly, int fUpdateLevel ) +{ + Aig_Obj_t * pObj; + int nSteps; + assert( p->pFanData ); + for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ ) + { + // get the node with a buffer fanin + for ( pObj = Vec_PtrEntryLast(p->vBufs); Aig_ObjIsBuf(pObj); pObj = Aig_ObjFanout0(p, pObj) ); + // replace this node by a node without buffer + Aig_NodeFixBufferFanins( p, pObj, fNodesOnly, fUpdateLevel ); + // stop if a cycle occured + if ( nSteps > 1000000 ) + { + printf( "Error: A cycle is encountered while propagating buffers.\n" ); + break; + } + } + return nSteps; +} + +/**Function************************************************************* + + Synopsis [Replaces one object by another.] + + Description [The new object (pObjNew) should be used instead of the old + object (pObjOld). If the new object is complemented or used, the buffer + is added and the new object remains in the manager; otherwise, the new + object is deleted.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fNodesOnly, int fUpdateLevel ) +{ + Aig_Obj_t * pObjNewR = Aig_Regular(pObjNew); + // the object to be replaced cannot be complemented + assert( !Aig_IsComplement(pObjOld) ); + // the object to be replaced cannot be a terminal + assert( !Aig_ObjIsPi(pObjOld) && !Aig_ObjIsPo(pObjOld) ); + // the object to be used cannot be a buffer or a PO + assert( !Aig_ObjIsBuf(pObjNewR) && !Aig_ObjIsPo(pObjNewR) ); + // the object cannot be the same + assert( pObjOld != pObjNewR ); + // make sure object is not pointing to itself + assert( pObjOld != Aig_ObjFanin0(pObjNewR) ); + assert( pObjOld != Aig_ObjFanin1(pObjNewR) ); + // recursively delete the old node - but leave the object there + pObjNewR->nRefs++; + Aig_ObjDelete_rec( p, pObjOld, 0 ); + pObjNewR->nRefs--; + // if the new object is complemented or already used, create a buffer + p->nObjs[pObjOld->Type]--; + if ( Aig_IsComplement(pObjNew) || Aig_ObjRefs(pObjNew) > 0 || (fNodesOnly && !Aig_ObjIsNode(pObjNew)) ) + { + pObjOld->Type = AIG_OBJ_BUF; + Aig_ObjConnect( p, pObjOld, pObjNew, NULL ); + p->nBufReplaces++; + } + else + { + Aig_Obj_t * pFanin0 = pObjNew->pFanin0; + Aig_Obj_t * pFanin1 = pObjNew->pFanin1; + int LevelOld = pObjOld->Level; + pObjOld->Type = pObjNew->Type; + Aig_ObjDisconnect( p, pObjNew ); + Aig_ObjConnect( p, pObjOld, pFanin0, pFanin1 ); + // delete the new object + Aig_ObjDelete( p, pObjNew ); + // update levels + if ( p->pFanData ) + { + pObjOld->Level = LevelOld; + Aig_ManUpdateLevel( p, pObjOld ); + } + if ( fUpdateLevel ) + { + Aig_ObjClearReverseLevel( p, pObjOld ); + Aig_ManUpdateReverseLevel( p, pObjOld ); + } + } + p->nObjs[pObjOld->Type]++; + // store buffers if fanout is allocated + if ( p->pFanData && Aig_ObjIsBuf(pObjOld) ) + { + Vec_PtrPush( p->vBufs, pObjOld ); + p->nBufMax = AIG_MAX( p->nBufMax, Vec_PtrSize(p->vBufs) ); + Aig_ManPropagateBuffers( p, fNodesOnly, fUpdateLevel ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigOper.c b/abc70930/src/aig/aig/aigOper.c new file mode 100644 index 00000000..66a6dce1 --- /dev/null +++ b/abc70930/src/aig/aig/aigOper.c @@ -0,0 +1,532 @@ +/**CFile**************************************************************** + + FileName [aigOper.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [AIG operations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigOper.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// procedure to detect an EXOR gate +static inline int Aig_ObjIsExorType( Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) +{ + if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) + return 0; + p0 = Aig_Regular(p0); + p1 = Aig_Regular(p1); + if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) + return 0; + if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) + return 0; + if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Aig_ObjChild0(p0); + *ppFan1 = Aig_ObjChild1(p0); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns i-th elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ) +{ + int v; + for ( v = Aig_ManPiNum(p); v <= i; v++ ) + Aig_ObjCreatePi( p ); + assert( i < Vec_PtrSize(p->vPis) ); + return Aig_ManPi( p, i ); +} + +/**Function************************************************************* + + Synopsis [Perform one operation.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) +{ + if ( Type == AIG_OBJ_AND ) + return Aig_And( p, p0, p1 ); + if ( Type == AIG_OBJ_EXOR ) + return Aig_Exor( p, p0, p1 ); + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_CanonPair_rec( Aig_Man_t * p, Aig_Obj_t * pGhost ) +{ + Aig_Obj_t * pResult, * pLat0, * pLat1; + int fCompl0, fCompl1; + Aig_Type_t Type; + assert( Aig_ObjIsNode(pGhost) ); + // consider the case when the pair is canonical + if ( !Aig_ObjIsLatch(Aig_ObjFanin0(pGhost)) || !Aig_ObjIsLatch(Aig_ObjFanin1(pGhost)) ) + { + if ( (pResult = Aig_TableLookup( p, pGhost )) ) + return pResult; + return Aig_ObjCreate( p, pGhost ); + } + /// remember the latches + pLat0 = Aig_ObjFanin0(pGhost); + pLat1 = Aig_ObjFanin1(pGhost); + // remember type and compls + Type = Aig_ObjType(pGhost); + fCompl0 = Aig_ObjFaninC0(pGhost); + fCompl1 = Aig_ObjFaninC1(pGhost); + // call recursively + pResult = Aig_Oper( p, Aig_NotCond(Aig_ObjChild0(pLat0), fCompl0), Aig_NotCond(Aig_ObjChild0(pLat1), fCompl1), Type ); + // build latch on top of this + return Aig_Latch( p, pResult, (Type == AIG_OBJ_AND)? fCompl0 & fCompl1 : fCompl0 ^ fCompl1 ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) +{ + Aig_Obj_t * pGhost, * pResult; +// Aig_Obj_t * pFan0, * pFan1; + // check trivial cases + if ( p0 == p1 ) + return p0; + if ( p0 == Aig_Not(p1) ) + return Aig_Not(p->pConst1); + if ( Aig_Regular(p0) == p->pConst1 ) + return p0 == p->pConst1 ? p1 : Aig_Not(p->pConst1); + if ( Aig_Regular(p1) == p->pConst1 ) + return p1 == p->pConst1 ? p0 : Aig_Not(p->pConst1); + // check not so trivial cases + if ( p->fAddStrash && (Aig_ObjIsNode(Aig_Regular(p0)) || Aig_ObjIsNode(Aig_Regular(p1))) ) + { // http://fmv.jku.at/papers/BrummayerBiere-MEMICS06.pdf + Aig_Obj_t * pFanA, * pFanB, * pFanC, * pFanD; + pFanA = Aig_ObjChild0(Aig_Regular(p0)); + pFanB = Aig_ObjChild1(Aig_Regular(p0)); + pFanC = Aig_ObjChild0(Aig_Regular(p1)); + pFanD = Aig_ObjChild1(Aig_Regular(p1)); + if ( Aig_IsComplement(p0) ) + { + if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) ) + return p1; + if ( pFanB == p1 ) + return Aig_And( p, Aig_Not(pFanA), pFanB ); + if ( pFanA == p1 ) + return Aig_And( p, Aig_Not(pFanB), pFanA ); + } + else + { + if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) ) + return Aig_Not(p->pConst1); + if ( pFanA == p1 || pFanB == p1 ) + return p0; + } + if ( Aig_IsComplement(p1) ) + { + if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) ) + return p0; + if ( pFanD == p0 ) + return Aig_And( p, Aig_Not(pFanC), pFanD ); + if ( pFanC == p0 ) + return Aig_And( p, Aig_Not(pFanD), pFanC ); + } + else + { + if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) ) + return Aig_Not(p->pConst1); + if ( pFanC == p0 || pFanD == p0 ) + return p1; + } + if ( !Aig_IsComplement(p0) && !Aig_IsComplement(p1) ) + { + if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) ) + return Aig_Not(p->pConst1); + if ( pFanA == pFanC || pFanB == pFanC ) + return Aig_And( p, p0, pFanD ); + if ( pFanB == pFanC || pFanB == pFanD ) + return Aig_And( p, pFanA, p1 ); + if ( pFanA == pFanD || pFanB == pFanD ) + return Aig_And( p, p0, pFanC ); + if ( pFanA == pFanC || pFanA == pFanD ) + return Aig_And( p, pFanB, p1 ); + } + else if ( Aig_IsComplement(p0) && !Aig_IsComplement(p1) ) + { + if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) ) + return p1; + if ( pFanB == pFanC || pFanB == pFanD ) + return Aig_And( p, Aig_Not(pFanA), p1 ); + if ( pFanA == pFanC || pFanA == pFanD ) + return Aig_And( p, Aig_Not(pFanB), p1 ); + } + else if ( !Aig_IsComplement(p0) && Aig_IsComplement(p1) ) + { + if ( pFanC == Aig_Not(pFanA) || pFanC == Aig_Not(pFanB) || pFanD == Aig_Not(pFanA) || pFanD == Aig_Not(pFanB) ) + return p0; + if ( pFanD == pFanA || pFanD == pFanB ) + return Aig_And( p, Aig_Not(pFanC), p0 ); + if ( pFanC == pFanA || pFanC == pFanB ) + return Aig_And( p, Aig_Not(pFanD), p0 ); + } + else // if ( Aig_IsComplement(p0) && Aig_IsComplement(p1) ) + { + if ( pFanA == pFanD && pFanB == Aig_Not(pFanC) ) + return Aig_Not(pFanA); + if ( pFanB == pFanC && pFanA == Aig_Not(pFanD) ) + return Aig_Not(pFanB); + if ( pFanA == pFanC && pFanB == Aig_Not(pFanD) ) + return Aig_Not(pFanA); + if ( pFanB == pFanD && pFanA == Aig_Not(pFanC) ) + return Aig_Not(pFanB); + } + } + // check if it can be an EXOR gate +// if ( Aig_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) +// return Aig_Exor( p, pFan0, pFan1 ); + pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_AND ); + pResult = Aig_CanonPair_rec( p, pGhost ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Latch( Aig_Man_t * p, Aig_Obj_t * pObj, int fInitOne ) +{ + Aig_Obj_t * pGhost, * pResult; + pGhost = Aig_ObjCreateGhost( p, Aig_NotCond(pObj, fInitOne), NULL, AIG_OBJ_LATCH ); + pResult = Aig_TableLookup( p, pGhost ); + if ( pResult == NULL ) + pResult = Aig_ObjCreate( p, pGhost ); + return Aig_NotCond( pResult, fInitOne ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) +{ +/* + Aig_Obj_t * pGhost, * pResult; + // check trivial cases + if ( p0 == p1 ) + return Aig_Not(p->pConst1); + if ( p0 == Aig_Not(p1) ) + return p->pConst1; + if ( Aig_Regular(p0) == p->pConst1 ) + return Aig_NotCond( p1, p0 == p->pConst1 ); + if ( Aig_Regular(p1) == p->pConst1 ) + return Aig_NotCond( p0, p1 == p->pConst1 ); + // check the table + pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_EXOR ); + if ( pResult = Aig_TableLookup( p, pGhost ) ) + return pResult; + return Aig_ObjCreate( p, pGhost ); +*/ + return Aig_Or( p, Aig_And(p, p0, Aig_Not(p1)), Aig_And(p, Aig_Not(p0), p1) ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) +{ + return Aig_Not( Aig_And( p, Aig_Not(p0), Aig_Not(p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ) +{ +/* + Aig_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; + int Count0, Count1; + // consider trivial cases + if ( p0 == Aig_Not(p1) ) + return Aig_Exor( p, pC, p0 ); + // other cases can be added + // implement the first MUX (F = C * x1 + C' * x0) + + // check for constants here!!! + + pTempA1 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, pC, p1, AIG_OBJ_AND) ); + pTempA2 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pC), p0, AIG_OBJ_AND) ); + if ( pTempA1 && pTempA2 ) + { + pTemp = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pTempA1), Aig_Not(pTempA2), AIG_OBJ_AND) ); + if ( pTemp ) return Aig_Not(pTemp); + } + Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); + // implement the second MUX (F' = C * x1' + C' * x0') + pTempB1 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, pC, Aig_Not(p1), AIG_OBJ_AND) ); + pTempB2 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pC), Aig_Not(p0), AIG_OBJ_AND) ); + if ( pTempB1 && pTempB2 ) + { + pTemp = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pTempB1), Aig_Not(pTempB2), AIG_OBJ_AND) ); + if ( pTemp ) return pTemp; + } + Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); + // compare and decide which one to implement + if ( Count0 >= Count1 ) + { + pTempA1 = pTempA1? pTempA1 : Aig_And(p, pC, p1); + pTempA2 = pTempA2? pTempA2 : Aig_And(p, Aig_Not(pC), p0); + return Aig_Or( p, pTempA1, pTempA2 ); + } + pTempB1 = pTempB1? pTempB1 : Aig_And(p, pC, Aig_Not(p1)); + pTempB2 = pTempB2? pTempB2 : Aig_And(p, Aig_Not(pC), Aig_Not(p0)); + return Aig_Not( Aig_Or( p, pTempB1, pTempB2 ) ); +*/ + return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ) +{ + return Aig_Or( p, Aig_Or(p, Aig_And(p, pA, pB), Aig_And(p, pA, pC)), Aig_And(p, pB, pC) ); +} + +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Multi_rec( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Aig_Type_t Type ) +{ + Aig_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Aig_Multi_rec( p, ppObjs, nObjs/2, Type ); + pObj2 = Aig_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Aig_Oper( p, pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Multi( Aig_Man_t * p, Aig_Obj_t ** pArgs, int nArgs, Aig_Type_t Type ) +{ + assert( Type == AIG_OBJ_AND || Type == AIG_OBJ_EXOR ); + assert( nArgs > 0 ); + return Aig_Multi_rec( p, pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ) +{ + int i; + assert( vPairs->nSize > 0 ); + assert( vPairs->nSize % 2 == 0 ); + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Aig_Not( Aig_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) ); + vPairs->nSize = vPairs->nSize/2; + return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_OBJ_AND ) ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 ) +{ + int i; + assert( vNodes1->nSize > 0 && vNodes1->nSize > 0 ); + assert( vNodes1->nSize == vNodes2->nSize ); + for ( i = 0; i < vNodes1->nSize; i++ ) + vNodes1->pArray[i] = Aig_Not( Aig_Exor( p, vNodes1->pArray[i], vNodes2->pArray[i] ) ); + return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vNodes1->pArray, vNodes1->nSize, AIG_OBJ_AND ) ); +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ) +{ + Aig_Obj_t * pFunc; + int i; + pFunc = Aig_ManConst1( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Aig_And( p, pFunc, Aig_IthVar(p, i) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ) +{ + Aig_Obj_t * pFunc; + int i; + pFunc = Aig_ManConst0( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Aig_Or( p, pFunc, Aig_IthVar(p, i) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ) +{ + Aig_Obj_t * pFunc; + int i; + pFunc = Aig_ManConst0( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Aig_Exor( p, pFunc, Aig_IthVar(p, i) ); + return pFunc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigOrder.c b/abc70930/src/aig/aig/aigOrder.c new file mode 100644 index 00000000..62aeca6e --- /dev/null +++ b/abc70930/src/aig/aig/aigOrder.c @@ -0,0 +1,171 @@ +/**CFile**************************************************************** + + FileName [aigOrder.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Dynamically updated topological order.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigOrder.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Initializes the order datastructure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManOrderStart( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + assert( Aig_ManBufNum(p) == 0 ); + // allocate order datastructure + assert( p->pOrderData == NULL ); + p->nOrderAlloc = 2 * Aig_ManObjNumMax(p); + if ( p->nOrderAlloc < (1<<12) ) + p->nOrderAlloc = (1<<12); + p->pOrderData = ALLOC( unsigned, 2 * p->nOrderAlloc ); + memset( p->pOrderData, 0xFF, sizeof(unsigned) * 2 * p->nOrderAlloc ); + // add the constant node + p->pOrderData[0] = p->pOrderData[1] = 0; + p->iPrev = p->iNext = 0; + // add the internal nodes + Aig_ManForEachNode( p, pObj, i ) + Aig_ObjOrderInsert( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Deletes the order datastructure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManOrderStop( Aig_Man_t * p ) +{ + assert( p->pOrderData ); + FREE( p->pOrderData ); + p->nOrderAlloc = 0; + p->iPrev = p->iNext = 0; +} + +/**Function************************************************************* + + Synopsis [Inserts an entry before iNext.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId ) +{ + int iPrev; + assert( ObjId != 0 ); + assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) ); + if ( ObjId >= p->nOrderAlloc ) + { + int nOrderAlloc = 2 * ObjId; + p->pOrderData = REALLOC( unsigned, p->pOrderData, 2 * nOrderAlloc ); + memset( p->pOrderData + 2 * p->nOrderAlloc, 0xFF, sizeof(unsigned) * 2 * (nOrderAlloc - p->nOrderAlloc) ); + p->nOrderAlloc = nOrderAlloc; + } + assert( p->pOrderData[2*ObjId] == 0xFFFFFFFF ); // prev + assert( p->pOrderData[2*ObjId+1] == 0xFFFFFFFF ); // next + iPrev = p->pOrderData[2*p->iNext]; + assert( p->pOrderData[2*iPrev+1] == (unsigned)p->iNext ); + p->pOrderData[2*ObjId] = iPrev; + p->pOrderData[2*iPrev+1] = ObjId; + p->pOrderData[2*p->iNext] = ObjId; + p->pOrderData[2*ObjId+1] = p->iNext; + p->nAndTotal++; +} + +/**Function************************************************************* + + Synopsis [Removes the entry.] + + Description [If iPrev is removed, it slides backward. + If iNext is removed, it slides forward.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId ) +{ + int iPrev, iNext; + assert( ObjId != 0 ); + assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) ); + iPrev = p->pOrderData[2*ObjId]; + iNext = p->pOrderData[2*ObjId+1]; + p->pOrderData[2*ObjId] = 0xFFFFFFFF; + p->pOrderData[2*ObjId+1] = 0xFFFFFFFF; + p->pOrderData[2*iNext] = iPrev; + p->pOrderData[2*iPrev+1] = iNext; + if ( p->iPrev == ObjId ) + { + p->nAndPrev--; + p->iPrev = iPrev; + } + if ( p->iNext == ObjId ) + p->iNext = iNext; + p->nAndTotal--; +} + +/**Function************************************************************* + + Synopsis [Advances the order forward.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjOrderAdvance( Aig_Man_t * p ) +{ + assert( p->pOrderData ); + assert( p->pOrderData[2*p->iPrev+1] == (unsigned)p->iNext ); + p->iPrev = p->iNext; + p->nAndPrev++; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigPart.c b/abc70930/src/aig/aig/aigPart.c new file mode 100644 index 00000000..3acd1aeb --- /dev/null +++ b/abc70930/src/aig/aig/aigPart.c @@ -0,0 +1,990 @@ +/**CFile**************************************************************** + + FileName [aigPart.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [AIG partitioning package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigPart.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Part_Man_t_ Part_Man_t; +struct Part_Man_t_ +{ + int nChunkSize; // the size of one chunk of memory (~1 Mb) + int nStepSize; // the step size in saving memory (~64 bytes) + char * pFreeBuf; // the pointer to free memory + int nFreeSize; // the size of remaining free memory + Vec_Ptr_t * vMemory; // the memory allocated + Vec_Ptr_t * vFree; // the vector of free pieces of memory +}; + +typedef struct Part_One_t_ Part_One_t; +struct Part_One_t_ +{ + int nRefs; // the number of references + int nOuts; // the number of outputs + int nOutsAlloc; // the array size + int pOuts[0]; // the array of outputs +}; + +static inline int Part_SizeType( int nSize, int nStepSize ) { return nSize / nStepSize + ((nSize % nStepSize) > 0); } +static inline char * Part_OneNext( char * pPart ) { return *((char **)pPart); } +static inline void Part_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Part_Man_t * Part_ManStart( int nChunkSize, int nStepSize ) +{ + Part_Man_t * p; + p = ALLOC( Part_Man_t, 1 ); + memset( p, 0, sizeof(Part_Man_t) ); + p->nChunkSize = nChunkSize; + p->nStepSize = nStepSize; + p->vMemory = Vec_PtrAlloc( 1000 ); + p->vFree = Vec_PtrAlloc( 1000 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Part_ManStop( Part_Man_t * p ) +{ + void * pMemory; + int i; + Vec_PtrForEachEntry( p->vMemory, pMemory, i ) + free( pMemory ); + Vec_PtrFree( p->vMemory ); + Vec_PtrFree( p->vFree ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Fetches the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Part_ManFetch( Part_Man_t * p, int nSize ) +{ + int Type, nSizeReal; + char * pMemory; + assert( nSize > 0 ); + Type = Part_SizeType( nSize, p->nStepSize ); + Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); + if ( (pMemory = Vec_PtrEntry( p->vFree, Type )) ) + { + Vec_PtrWriteEntry( p->vFree, Type, Part_OneNext(pMemory) ); + return pMemory; + } + nSizeReal = p->nStepSize * Type; + if ( p->nFreeSize < nSizeReal ) + { + p->pFreeBuf = ALLOC( char, p->nChunkSize ); + p->nFreeSize = p->nChunkSize; + Vec_PtrPush( p->vMemory, p->pFreeBuf ); + } + assert( p->nFreeSize >= nSizeReal ); + pMemory = p->pFreeBuf; + p->pFreeBuf += nSizeReal; + p->nFreeSize -= nSizeReal; + return pMemory; +} + +/**Function************************************************************* + + Synopsis [Recycles the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Part_ManRecycle( Part_Man_t * p, char * pMemory, int nSize ) +{ + int Type; + Type = Part_SizeType( nSize, p->nStepSize ); + Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); + Part_OneSetNext( pMemory, Vec_PtrEntry(p->vFree, Type) ); + Vec_PtrWriteEntry( p->vFree, Type, pMemory ); +} + +/**Function************************************************************* + + Synopsis [Fetches the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Part_One_t * Part_ManFetchEntry( Part_Man_t * p, int nWords, int nRefs ) +{ + Part_One_t * pPart; + pPart = (Part_One_t *)Part_ManFetch( p, sizeof(Part_One_t) + sizeof(int) * nWords ); + pPart->nRefs = nRefs; + pPart->nOuts = 0; + pPart->nOutsAlloc = nWords; + return pPart; +} + +/**Function************************************************************* + + Synopsis [Recycles the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Part_ManRecycleEntry( Part_Man_t * p, Part_One_t * pEntry ) +{ + assert( pEntry->nOuts <= pEntry->nOutsAlloc ); + assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 ); + Part_ManRecycle( p, (char *)pEntry, sizeof(Part_One_t) + sizeof(int) * pEntry->nOutsAlloc ); +} + +/**Function************************************************************* + + Synopsis [Merges two entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Part_One_t * Part_ManMergeEntry( Part_Man_t * pMan, Part_One_t * p1, Part_One_t * p2, int nRefs ) +{ + Part_One_t * p = Part_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs ); + int * pBeg1 = p1->pOuts; + int * pBeg2 = p2->pOuts; + int * pBeg = p->pOuts; + int * pEnd1 = p1->pOuts + p1->nOuts; + int * pEnd2 = p2->pOuts + p2->nOuts; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( *pBeg1 == *pBeg2 ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( *pBeg1 < *pBeg2 ) + *pBeg++ = *pBeg1++; + else + *pBeg++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pBeg++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pBeg++ = *pBeg2++; + p->nOuts = pBeg - p->pOuts; + assert( p->nOuts <= p->nOutsAlloc ); + assert( p->nOuts >= p1->nOuts ); + assert( p->nOuts >= p2->nOuts ); + return p; +} + +/**Function************************************************************* + + Synopsis [Tranfers the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Part_ManTransferEntry( Part_One_t * p ) +{ + Vec_Int_t * vSupp; + int i; + vSupp = Vec_IntAlloc( p->nOuts ); + for ( i = 0; i < p->nOuts; i++ ) + Vec_IntPush( vSupp, p->pOuts[i] ); + return vSupp; +} + +/**Function************************************************************* + + Synopsis [Computes supports of the POs in the multi-output AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManSupports( Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vSupports; + Vec_Int_t * vSupp; + Part_Man_t * p; + Part_One_t * pPart0, * pPart1; + Aig_Obj_t * pObj; + int i; + // set the number of PIs/POs + Aig_ManForEachPi( pMan, pObj, i ) + pObj->pNext = (Aig_Obj_t *)(long)i; + Aig_ManForEachPo( pMan, pObj, i ) + pObj->pNext = (Aig_Obj_t *)(long)i; + // start the support computation manager + p = Part_ManStart( 1 << 20, 1 << 6 ); + // consider objects in the topological order + vSupports = Vec_PtrAlloc( Aig_ManPoNum(pMan) ); + Aig_ManCleanData(pMan); + Aig_ManForEachObj( pMan, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + { + pPart0 = Aig_ObjFanin0(pObj)->pData; + pPart1 = Aig_ObjFanin1(pObj)->pData; + pObj->pData = Part_ManMergeEntry( p, pPart0, pPart1, pObj->nRefs ); + assert( pPart0->nRefs > 0 ); + if ( --pPart0->nRefs == 0 ) + Part_ManRecycleEntry( p, pPart0 ); + assert( pPart1->nRefs > 0 ); + if ( --pPart1->nRefs == 0 ) + Part_ManRecycleEntry( p, pPart1 ); + continue; + } + if ( Aig_ObjIsPo(pObj) ) + { + pPart0 = Aig_ObjFanin0(pObj)->pData; + vSupp = Part_ManTransferEntry(pPart0); + Vec_IntPush( vSupp, (int)(long)pObj->pNext ); + Vec_PtrPush( vSupports, vSupp ); + assert( pPart0->nRefs > 0 ); + if ( --pPart0->nRefs == 0 ) + Part_ManRecycleEntry( p, pPart0 ); + continue; + } + if ( Aig_ObjIsPi(pObj) ) + { + if ( pObj->nRefs ) + { + pPart0 = Part_ManFetchEntry( p, 1, pObj->nRefs ); + pPart0->pOuts[ pPart0->nOuts++ ] = (int)(long)pObj->pNext; + pObj->pData = pPart0; + } + continue; + } + if ( Aig_ObjIsConst1(pObj) ) + { + if ( pObj->nRefs ) + pObj->pData = Part_ManFetchEntry( p, 0, pObj->nRefs ); + continue; + } + assert( 0 ); + } +//printf( "Memory usage = %d Mb.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) ); + Part_ManStop( p ); + // sort supports by size + Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); + // clear the number of PIs/POs + Aig_ManForEachPi( pMan, pObj, i ) + pObj->pNext = NULL; + Aig_ManForEachPo( pMan, pObj, i ) + pObj->pNext = NULL; +/* + Aig_ManForEachPo( pMan, pObj, i ) + printf( "%d ", Vec_IntSize( (Vec_Int_t *)Vec_VecEntry(vSupports, i) ) ); + printf( "\n" ); +*/ + return vSupports; +} + +/**Function************************************************************* + + Synopsis [Start char-bases support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Aig_ManSuppCharStart( Vec_Int_t * vOne, int nPis ) +{ + unsigned * pBuffer; + int i, Entry; + int nWords = Aig_BitWordNum(nPis); + pBuffer = ALLOC( unsigned, nWords ); + memset( pBuffer, 0, sizeof(unsigned) * nWords ); + Vec_IntForEachEntry( vOne, Entry, i ) + { + assert( Entry < nPis ); + Aig_InfoSetBit( pBuffer, Entry ); + } + return pBuffer; +} + +/**Function************************************************************* + + Synopsis [Add to char-bases support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis ) +{ + int i, Entry; + Vec_IntForEachEntry( vOne, Entry, i ) + { + assert( Entry < nPis ); + Aig_InfoSetBit( pBuffer, Entry ); + } +} + +/**Function************************************************************* + + Synopsis [Find the common variables using char-bases support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne ) +{ + int i, Entry, nCommon = 0; + Vec_IntForEachEntry( vOne, Entry, i ) + nCommon += Aig_InfoHasBit(pBuffer, Entry); + return nCommon; +} + +/**Function************************************************************* + + Synopsis [Find the best partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsBit, int nSuppSizeLimit, Vec_Int_t * vOne ) +{ + Vec_Int_t * vPartSupp;//, * vPart; + int Attract, Repulse, Value, ValueBest; + int i, nCommon, iBest; + iBest = -1; + ValueBest = 0; + Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i ) + { +// vPart = Vec_PtrEntry( vPartsAll, i ); +// if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit ) +// continue; +// nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne ); + nCommon = Aig_ManSuppCharCommon( Vec_PtrEntry(vPartSuppsBit, i), vOne ); + if ( nCommon == 0 ) + continue; + if ( nCommon == Vec_IntSize(vOne) ) + return i; + // skip partitions whose size exceeds the limit + if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit ) + continue; + Attract = 1000 * nCommon / Vec_IntSize(vOne); + if ( Vec_IntSize(vPartSupp) < 100 ) + Repulse = 1; + else + Repulse = 1+Aig_Base2Log(Vec_IntSize(vPartSupp)-100); + Value = Attract/Repulse; + if ( ValueBest < Value ) + { + ValueBest = Value; + iBest = i; + } + } + if ( ValueBest < 75 ) + return -1; + return iBest; +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPartitionPrint( Aig_Man_t * p, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll ) +{ + Vec_Int_t * vOne; + int i, nOutputs, Counter; + + Counter = 0; + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + { + nOutputs = Vec_IntSize(Vec_PtrEntry(vPartsAll, i)); + printf( "%d=(%d,%d) ", i, Vec_IntSize(vOne), nOutputs ); + Counter += nOutputs; + if ( i == Vec_PtrSize(vPartsAll) - 1 ) + break; + } + assert( Counter == Aig_ManPoNum(p) ); +// printf( "\nTotal = %d. Outputs = %d.\n", Counter, Aig_ManPoNum(p) ); +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit ) +{ + Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; + int i, iPart; + + if ( nSuppSizeLimit == 0 ) + nSuppSizeLimit = 200; + + // pack smaller partitions into larger blocks + iPart = 0; + vPart = vPartSupp = NULL; + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + { + if ( Vec_IntSize(vOne) < nSuppSizeLimit ) + { + if ( vPartSupp == NULL ) + { + assert( vPart == NULL ); + vPartSupp = Vec_IntDup(vOne); + vPart = Vec_PtrEntry(vPartsAll, i); + } + else + { + vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); + Vec_IntFree( vTemp ); + vPart = Vec_IntTwoMerge( vTemp = vPart, Vec_PtrEntry(vPartsAll, i) ); + Vec_IntFree( vTemp ); + Vec_IntFree( Vec_PtrEntry(vPartsAll, i) ); + } + if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit ) + continue; + } + else + vPart = Vec_PtrEntry(vPartsAll, i); + // add the partition + Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); + vPart = NULL; + if ( vPartSupp ) + { + Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) ); + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + vPartSupp = NULL; + } + iPart++; + } + // add the last one + if ( vPart ) + { + Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); + vPart = NULL; + + assert( vPartSupp != NULL ); + Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) ); + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + vPartSupp = NULL; + iPart++; + } + Vec_PtrShrink( vPartsAll, iPart ); + Vec_PtrShrink( vPartsAll, iPart ); +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManPartitionSmart( Aig_Man_t * p, int nSuppSizeLimit, int fVerbose, Vec_Ptr_t ** pvPartSupps ) +{ + Vec_Ptr_t * vPartSuppsBit; + Vec_Ptr_t * vSupports, * vPartsAll, * vPartsAll2, * vPartSuppsAll;//, * vPartPtr; + Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; + int i, iPart, iOut, clk; + + // compute the supports for all outputs +clk = clock(); + vSupports = Aig_ManSupports( p ); +if ( fVerbose ) +{ +PRT( "Supps", clock() - clk ); +} + // start char-based support representation + vPartSuppsBit = Vec_PtrAlloc( 1000 ); + + // create partitions +clk = clock(); + vPartsAll = Vec_PtrAlloc( 256 ); + vPartSuppsAll = Vec_PtrAlloc( 256 ); + Vec_PtrForEachEntry( vSupports, vOne, i ) + { + // get the output number + iOut = Vec_IntPop(vOne); + // find closely matching part + iPart = Aig_ManPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsBit, nSuppSizeLimit, vOne ); + if ( iPart == -1 ) + { + // create new partition + vPart = Vec_IntAlloc( 32 ); + Vec_IntPush( vPart, iOut ); + // create new partition support + vPartSupp = Vec_IntDup( vOne ); + // add this partition and its support + Vec_PtrPush( vPartsAll, vPart ); + Vec_PtrPush( vPartSuppsAll, vPartSupp ); + + Vec_PtrPush( vPartSuppsBit, Aig_ManSuppCharStart(vOne, Aig_ManPiNum(p)) ); + } + else + { + // add output to this partition + vPart = Vec_PtrEntry( vPartsAll, iPart ); + Vec_IntPush( vPart, iOut ); + // merge supports + vPartSupp = Vec_PtrEntry( vPartSuppsAll, iPart ); + vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); + Vec_IntFree( vTemp ); + // reinsert new support + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + + Aig_ManSuppCharAdd( Vec_PtrEntry(vPartSuppsBit, iPart), vOne, Aig_ManPiNum(p) ); + } + } + + // stop char-based support representation + Vec_PtrForEachEntry( vPartSuppsBit, vTemp, i ) + free( vTemp ); + Vec_PtrFree( vPartSuppsBit ); + +//printf( "\n" ); +if ( fVerbose ) +{ +PRT( "Parts", clock() - clk ); +} + +clk = clock(); + // reorder partitions in the decreasing order of support sizes + // remember partition number in each partition support + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + Vec_IntPush( vOne, i ); + // sort the supports in the decreasing order + Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 ); + // reproduce partitions + vPartsAll2 = Vec_PtrAlloc( 256 ); + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) ); + Vec_PtrFree( vPartsAll ); + vPartsAll = vPartsAll2; + + // compact small partitions +// Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); + Aig_ManPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit ); + if ( fVerbose ) +// Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); + printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) ); + +if ( fVerbose ) +{ +//PRT( "Comps", clock() - clk ); +} + + // cleanup + Vec_VecFree( (Vec_Vec_t *)vSupports ); + if ( pvPartSupps == NULL ) + Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll ); + else + *pvPartSupps = vPartSuppsAll; +/* + // converts from intergers to nodes + Vec_PtrForEachEntry( vPartsAll, vPart, iPart ) + { + vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) ); + Vec_IntForEachEntry( vPart, iOut, i ) + Vec_PtrPush( vPartPtr, Aig_ManPo(p, iOut) ); + Vec_IntFree( vPart ); + Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr ); + } +*/ + return vPartsAll; +} + +/**Function************************************************************* + + Synopsis [Perform the naive partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize ) +{ + Vec_Ptr_t * vParts; + Aig_Obj_t * pObj; + int nParts, i; + nParts = (Aig_ManPoNum(p) / nPartSize) + ((Aig_ManPoNum(p) % nPartSize) > 0); + vParts = (Vec_Ptr_t *)Vec_VecStart( nParts ); + Aig_ManForEachPo( p, pObj, i ) + Vec_IntPush( Vec_PtrEntry(vParts, i / nPartSize), i ); + return vParts; +} + + + +/**Function************************************************************* + + Synopsis [Adds internal nodes in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDupPart_rec( Aig_Man_t * pNew, Aig_Man_t * pOld, Aig_Obj_t * pObj, Vec_Int_t * vSuppMap ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(pOld, pObj) ) + return pObj->pData; + Aig_ObjSetTravIdCurrent(pOld, pObj); + if ( Aig_ObjIsPi(pObj) ) + { + assert( Vec_IntSize(vSuppMap) == Aig_ManPiNum(pNew) ); + Vec_IntPush( vSuppMap, (int)(long)pObj->pNext ); + return pObj->pData = Aig_ObjCreatePi(pNew); + } + assert( Aig_ObjIsNode(pObj) ); + Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); + Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin1(pObj), vSuppMap ); + return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Adds internal nodes in the topological order.] + + Description [Returns the array of new outputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDupPart( Aig_Man_t * pNew, Aig_Man_t * pOld, Vec_Int_t * vPart, Vec_Int_t * vSuppMap, int fInverse ) +{ + Vec_Ptr_t * vOutsTotal; + Aig_Obj_t * pObj; + int Entry, i; + // create the PIs + Aig_ManIncrementTravId( pOld ); + Aig_ManConst1(pOld)->pData = Aig_ManConst1(pNew); + Aig_ObjSetTravIdCurrent( pOld, Aig_ManConst1(pOld) ); + if ( !fInverse ) + { + Vec_IntForEachEntry( vSuppMap, Entry, i ) + { + pObj = Aig_ManPi( pOld, Entry ); + pObj->pData = Aig_ManPi( pNew, i ); + Aig_ObjSetTravIdCurrent( pOld, pObj ); + } + } + else + { + Vec_IntForEachEntry( vSuppMap, Entry, i ) + { + pObj = Aig_ManPi( pOld, i ); + pObj->pData = Aig_ManPi( pNew, Entry ); + Aig_ObjSetTravIdCurrent( pOld, pObj ); + } + vSuppMap = NULL; // should not be useful + } + // create the internal nodes + vOutsTotal = Vec_PtrAlloc( Vec_IntSize(vPart) ); + if ( !fInverse ) + { + Vec_IntForEachEntry( vPart, Entry, i ) + { + pObj = Aig_ManPo( pOld, Entry ); + Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); + Vec_PtrPush( vOutsTotal, Aig_ObjChild0Copy(pObj) ); + } + } + else + { + Aig_ManForEachObj( pOld, pObj, i ) + { + if ( Aig_ObjIsPo(pObj) ) + { + Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); + Vec_PtrPush( vOutsTotal, Aig_ObjChild0Copy(pObj) ); + } + else if ( Aig_ObjIsNode(pObj) && pObj->nRefs == 0 ) + Aig_ManDupPart_rec( pNew, pOld, pObj, vSuppMap ); + + } + } + return vOutsTotal; +} + +/**Function************************************************************* + + Synopsis [Create partitioned miter of the two AIGs.] + + Description [Assumes that each output in the second AIG cannot have + more supp vars than the same output in the first AIG.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManMiterPartitioned( Aig_Man_t * p1, Aig_Man_t * p2, int nPartSize ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pMiter; + Vec_Ptr_t * vMiters, * vNodes1, * vNodes2; + Vec_Ptr_t * vParts, * vPartSupps; + Vec_Int_t * vPart, * vPartSupp; + int i, k; + // partition the first manager + vParts = Aig_ManPartitionSmart( p1, nPartSize, 0, &vPartSupps ); + // derive miters + vMiters = Vec_PtrAlloc( Vec_PtrSize(vParts) ); + for ( i = 0; i < Vec_PtrSize(vParts); i++ ) + { + // get partitions and their support + vPart = Vec_PtrEntry( vParts, i ); + vPartSupp = Vec_PtrEntry( vPartSupps, i ); + // create the new miter + pNew = Aig_ManStart( 1000 ); +// pNew->pName = Extra_UtilStrsav( p1->pName ); + // create the PIs + for ( k = 0; k < Vec_IntSize(vPartSupp); k++ ) + Aig_ObjCreatePi( pNew ); + // copy the components + vNodes1 = Aig_ManDupPart( pNew, p1, vPart, vPartSupp, 0 ); + vNodes2 = Aig_ManDupPart( pNew, p2, vPart, vPartSupp, 0 ); + // create the miter + pMiter = Aig_MiterTwo( pNew, vNodes1, vNodes2 ); + Vec_PtrFree( vNodes1 ); + Vec_PtrFree( vNodes2 ); + // create the output + Aig_ObjCreatePo( pNew, pMiter ); + // clean up + Aig_ManCleanup( pNew ); + Vec_PtrPush( vMiters, pNew ); + } + Vec_VecFree( (Vec_Vec_t *)vParts ); + Vec_VecFree( (Vec_Vec_t *)vPartSupps ); + return vMiters; +} + +/**Function************************************************************* + + Synopsis [Performs partitioned choice computation.] + + Description [Assumes that each output in the second AIG cannot have + more supp vars than the same output in the first AIG.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize ) +{ + extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); + extern void * Abc_FrameGetGlobalFrame(); + extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax ); + + Vec_Ptr_t * vOutsTotal, * vOuts; + Aig_Man_t * pAigTotal, * pAigPart, * pAig; + Vec_Int_t * vPart, * vPartSupp; + Vec_Ptr_t * vParts; + Aig_Obj_t * pObj; + void ** ppData; + int i, k, m; + + // partition the first AIG in the array + assert( Vec_PtrSize(vAigs) > 1 ); + pAig = Vec_PtrEntry( vAigs, 0 ); + vParts = Aig_ManPartitionSmart( pAig, nPartSize, 0, NULL ); + + // start the total fraiged AIG + pAigTotal = Aig_ManStartFrom( pAig ); + Aig_ManReprStart( pAigTotal, Vec_PtrSize(vAigs) * Aig_ManObjNumMax(pAig) + 10000 ); + vOutsTotal = Vec_PtrStart( Aig_ManPoNum(pAig) ); + + // set the PI numbers + Vec_PtrForEachEntry( vAigs, pAig, i ) + Aig_ManForEachPi( pAig, pObj, k ) + pObj->pNext = (Aig_Obj_t *)(long)k; + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); + + // create the total fraiged AIG + vPartSupp = Vec_IntAlloc( 100 ); // maps part PI num into total PI num + Vec_PtrForEachEntry( vParts, vPart, i ) + { + // derive the partition AIG + pAigPart = Aig_ManStart( 5000 ); +// pAigPart->pName = Extra_UtilStrsav( pAigPart->pName ); + Vec_IntClear( vPartSupp ); + Vec_PtrForEachEntry( vAigs, pAig, k ) + { + vOuts = Aig_ManDupPart( pAigPart, pAig, vPart, vPartSupp, 0 ); + if ( k == 0 ) + { + Vec_PtrForEachEntry( vOuts, pObj, m ) + Aig_ObjCreatePo( pAigPart, pObj ); + } + Vec_PtrFree( vOuts ); + } + // derive the total AIG from the partitioned AIG + vOuts = Aig_ManDupPart( pAigTotal, pAigPart, vPart, vPartSupp, 1 ); + // add to the outputs + Vec_PtrForEachEntry( vOuts, pObj, k ) + { + assert( Vec_PtrEntry( vOutsTotal, Vec_IntEntry(vPart,k) ) == NULL ); + Vec_PtrWriteEntry( vOutsTotal, Vec_IntEntry(vPart,k), pObj ); + } + Vec_PtrFree( vOuts ); + // store contents of pData pointers + ppData = ALLOC( void *, Aig_ManObjNumMax(pAigPart) ); + Aig_ManForEachObj( pAigPart, pObj, k ) + ppData[k] = pObj->pData; + // report the process + printf( "Part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", + i+1, Vec_PtrSize(vParts), Aig_ManPiNum(pAigPart), Aig_ManPoNum(pAigPart), + Aig_ManNodeNum(pAigPart), Aig_ManLevelNum(pAigPart) ); + // compute equivalence classes (to be stored in pNew->pReprs) + pAig = Fra_FraigChoice( pAigPart, 1000 ); + Aig_ManStop( pAig ); + // reset the pData pointers + Aig_ManForEachObj( pAigPart, pObj, k ) + pObj->pData = ppData[k]; + free( ppData ); + // transfer representatives to the total AIG + if ( pAigPart->pReprs ) + Aig_ManTransferRepr( pAigTotal, pAigPart ); + Aig_ManStop( pAigPart ); + } + printf( " \r" ); + Vec_VecFree( (Vec_Vec_t *)vParts ); + Vec_IntFree( vPartSupp ); + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); + + // clear the PI numbers + Vec_PtrForEachEntry( vAigs, pAig, i ) + Aig_ManForEachPi( pAig, pObj, k ) + pObj->pNext = NULL; +/* + // collect the missing outputs (outputs whose driver is not a node) + pAig = Vec_PtrEntry( vAigs, 0 ); + Aig_ManConst1(pAig)->pData = Aig_ManConst1(pAigTotal); + Aig_ManForEachPi( pAig, pObj, i ) + pAig->pData = Aig_ManPi( pAigTotal, i ); + Aig_ManForEachPo( pAig, pObj, i ) + if ( !Aig_ObjIsNode(Aig_ObjFanin0(pObj)) ) + { + assert( Vec_PtrEntry( vOutsTotal, i ) == NULL ); + Vec_PtrWriteEntry( vOutsTotal, i, Aig_ObjChild0Copy(pObj) ); + } +*/ + // add the outputs in the same order + Vec_PtrForEachEntry( vOutsTotal, pObj, i ) + Aig_ObjCreatePo( pAigTotal, pObj ); + Vec_PtrFree( vOutsTotal ); + + // derive the result of choicing + pAig = Aig_ManRehash( pAigTotal ); + // create the equivalent nodes lists + Aig_ManMarkValidChoices( pAig ); + return pAig; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigRepr.c b/abc70930/src/aig/aig/aigRepr.c new file mode 100644 index 00000000..5ee6c9af --- /dev/null +++ b/abc70930/src/aig/aig/aigRepr.c @@ -0,0 +1,457 @@ +/**CFile**************************************************************** + + FileName [aigRepr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Handing node representatives.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigRepr.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the array of representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManReprStart( Aig_Man_t * p, int nIdMax ) +{ + assert( Aig_ManBufNum(p) == 0 ); + assert( p->pReprs == NULL ); + p->nReprsAlloc = nIdMax; + p->pReprs = ALLOC( Aig_Obj_t *, p->nReprsAlloc ); + memset( p->pReprs, 0, sizeof(Aig_Obj_t *) * p->nReprsAlloc ); +} + +/**Function************************************************************* + + Synopsis [Stop the array of representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManReprStop( Aig_Man_t * p ) +{ + assert( p->pReprs != NULL ); + FREE( p->pReprs ); + p->nReprsAlloc = 0; +} + +/**Function************************************************************* + + Synopsis [Set the representative.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) +{ + assert( p->pReprs != NULL ); + assert( !Aig_IsComplement(pNode1) ); + assert( !Aig_IsComplement(pNode2) ); + assert( pNode1->Id < p->nReprsAlloc ); + assert( pNode2->Id < p->nReprsAlloc ); + assert( pNode1->Id < pNode2->Id ); + p->pReprs[pNode2->Id] = pNode1; +} + +/**Function************************************************************* + + Synopsis [Set the representative.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Aig_ObjSetRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) +{ + assert( p->pReprs != NULL ); + assert( !Aig_IsComplement(pNode1) ); + assert( !Aig_IsComplement(pNode2) ); + assert( pNode1->Id < p->nReprsAlloc ); + assert( pNode2->Id < p->nReprsAlloc ); + if ( pNode1 == pNode2 ) + return; + if ( pNode1->Id < pNode2->Id ) + p->pReprs[pNode2->Id] = pNode1; + else + p->pReprs[pNode1->Id] = pNode2; +} + +/**Function************************************************************* + + Synopsis [Find representative.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Aig_ObjFindRepr( Aig_Man_t * p, Aig_Obj_t * pNode ) +{ + assert( p->pReprs != NULL ); + assert( !Aig_IsComplement(pNode) ); + assert( pNode->Id < p->nReprsAlloc ); +// assert( !p->pReprs[pNode->Id] || p->pReprs[pNode->Id]->Id < pNode->Id ); + return p->pReprs[pNode->Id]; +} + +/**Function************************************************************* + + Synopsis [Clears the representative.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Aig_ObjClearRepr( Aig_Man_t * p, Aig_Obj_t * pNode ) +{ + assert( p->pReprs != NULL ); + assert( !Aig_IsComplement(pNode) ); + assert( pNode->Id < p->nReprsAlloc ); + p->pReprs[pNode->Id] = NULL; +} + +/**Function************************************************************* + + Synopsis [Find representative transitively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Aig_ObjFindReprTransitive( Aig_Man_t * p, Aig_Obj_t * pNode ) +{ + Aig_Obj_t * pNext, * pRepr; + if ( (pRepr = Aig_ObjFindRepr(p, pNode)) ) + while ( (pNext = Aig_ObjFindRepr(p, pRepr)) ) + pRepr = pNext; + return pRepr; +} + +/**Function************************************************************* + + Synopsis [Returns representatives of fanin in approapriate polarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Aig_ObjRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pRepr; + if ( (pRepr = Aig_ObjFindRepr(p, pObj)) ) + return Aig_NotCond( pRepr->pData, pObj->fPhase ^ pRepr->fPhase ); + return pObj->pData; +} +static inline Aig_Obj_t * Aig_ObjChild0Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjRepr(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); } +static inline Aig_Obj_t * Aig_ObjChild1Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjRepr(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); } + +/**Function************************************************************* + + Synopsis [Duplicates AIG while substituting representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * pOld ) +{ + Aig_Obj_t * pObj, * pRepr; + int k; + assert( pNew->pReprs != NULL ); + // extend storage to fix pNew + if ( pNew->nReprsAlloc < Aig_ManObjNumMax(pNew) ) + { + int nReprsAllocNew = 2 * Aig_ManObjNumMax(pNew); + pNew->pReprs = REALLOC( Aig_Obj_t *, pNew->pReprs, nReprsAllocNew ); + memset( pNew->pReprs + pNew->nReprsAlloc, 0, sizeof(Aig_Obj_t *) * (nReprsAllocNew-pNew->nReprsAlloc) ); + pNew->nReprsAlloc = nReprsAllocNew; + } + // go through the nodes which have representatives + Aig_ManForEachObj( pOld, pObj, k ) + if ( (pRepr = Aig_ObjFindRepr(pOld, pObj)) ) + Aig_ObjSetRepr( pNew, Aig_Regular(pRepr->pData), Aig_Regular(pObj->pData) ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDupRepr_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pRepr; + if ( pObj->pData ) + return pObj->pData; + if ( (pRepr = Aig_ObjFindRepr(p, pObj)) ) + { + Aig_ManDupRepr_rec( pNew, p, pRepr ); + return pObj->pData = Aig_NotCond( pRepr->pData, pRepr->fPhase ^ pObj->fPhase ); + } + Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin0(pObj) ); + Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin1(pObj) ); + return pObj->pData = Aig_And( pNew, Aig_ObjChild0Repr(p, pObj), Aig_ObjChild1Repr(p, pObj) ); +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while substituting representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p, int fOrdered ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // start the HOP package + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->nRegs = p->nRegs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // map the const and primary inputs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePi(pNew); + // map the internal nodes + if ( fOrdered ) + { + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Repr(p, pObj), Aig_ObjChild1Repr(p, pObj) ); + } + else + { + Aig_ManForEachPo( p, pObj, i ) + Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin0(pObj) ); + } + // transfer the POs + Aig_ManForEachPo( p, pObj, i ) + Aig_ObjCreatePo( pNew, Aig_ObjChild0Repr(p, pObj) ); + // check the new manager + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupRepr: Check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Transfer representatives and return the number of critical fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManRemapRepr( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pRepr; + int i, nFanouts = 0; + Aig_ManForEachNode( p, pObj, i ) + { + pRepr = Aig_ObjFindReprTransitive( p, pObj ); + if ( pRepr == NULL ) + continue; + assert( pRepr->Id < pObj->Id ); + Aig_ObjSetRepr( p, pObj, pRepr ); + nFanouts += (pObj->nRefs > 0); + } + return nFanouts; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pNode, Aig_Obj_t * pOld ) +{ + // check the trivial cases + if ( pNode == NULL ) + return 0; +// if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode +// return 0; + if ( pNode == pOld ) + return 1; + // skip the visited node + if ( Aig_ObjIsTravIdCurrent( p, pNode ) ) + return 0; + Aig_ObjSetTravIdCurrent( p, pNode ); + // check the children + if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin0(pNode), pOld ) ) + return 1; + if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin1(pNode), pOld ) ) + return 1; + // check equivalent nodes + return Aig_ObjCheckTfi_rec( p, p->pEquivs[pNode->Id], pOld ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pNew, Aig_Obj_t * pOld ) +{ + assert( !Aig_IsComplement(pNew) ); + assert( !Aig_IsComplement(pOld) ); + Aig_ManIncrementTravId( p ); + return Aig_ObjCheckTfi_rec( p, pNew, pOld ); +} + +/**Function************************************************************* + + Synopsis [Iteratively rehashes the AIG.] + + Description [The input AIG is assumed to have representatives assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManRehash( Aig_Man_t * p ) +{ + Aig_Man_t * pTemp; + int i, nFanouts; + assert( p->pReprs != NULL ); + for ( i = 0; (nFanouts = Aig_ManRemapRepr( p )); i++ ) + { +// printf( "Iter = %3d. Fanouts = %6d. Nodes = %7d.\n", i+1, nFanouts, Aig_ManNodeNum(p) ); + p = Aig_ManDupRepr( pTemp = p, 1 ); + Aig_ManReprStart( p, Aig_ManObjNumMax(p) ); + Aig_ManTransferRepr( p, pTemp ); + Aig_ManStop( pTemp ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes that are Creates choices.] + + Description [The input AIG is assumed to have representatives assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManMarkValidChoices( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pRepr; + int i; + assert( p->pReprs != NULL ); + // create equivalent nodes in the manager + assert( p->pEquivs == NULL ); + p->pEquivs = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); + memset( p->pEquivs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); + // make the choice nodes + Aig_ManForEachNode( p, pObj, i ) + { + pRepr = Aig_ObjFindRepr( p, pObj ); + if ( pRepr == NULL ) + continue; + assert( pObj->nRefs == 0 ); + // skip constant and PI classes + if ( !Aig_ObjIsNode(pRepr) ) + { + Aig_ObjClearRepr( p, pObj ); + continue; + } + // skip choices with combinatinal loops + if ( Aig_ObjCheckTfi( p, pObj, pRepr ) ) + { + Aig_ObjClearRepr( p, pObj ); + continue; + } +//printf( "Node %d is represented by node %d.\n", pObj->Id, pRepr->Id ); + // add choice to the choice node + p->pEquivs[pObj->Id] = p->pEquivs[pRepr->Id]; + p->pEquivs[pRepr->Id] = pObj; + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigRet.c b/abc70930/src/aig/aig/aigRet.c new file mode 100644 index 00000000..d1784b1b --- /dev/null +++ b/abc70930/src/aig/aig/aigRet.c @@ -0,0 +1,969 @@ +/**CFile**************************************************************** + + FileName [aigRet.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Retiming of AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigRet.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// init values +typedef enum { + RTM_VAL_NONE, // 0: non-existent value + RTM_VAL_ZERO, // 1: initial value 0 + RTM_VAL_ONE, // 2: initial value 1 + RTM_VAL_VOID // 3: unused value +} Rtm_Init_t; + +typedef struct Rtm_Man_t_ Rtm_Man_t; +struct Rtm_Man_t_ +{ + // network representation + Vec_Ptr_t * vObjs; // retiming objects + Vec_Ptr_t * vPis; // PIs only + Vec_Ptr_t * vPos; // POs only + Aig_MmFlex_t * pMem; // the memory manager + // autonomous components after cutting off + // storage for overflow latches + unsigned * pExtra; + int nExtraCur; + int nExtraAlloc; +}; + +typedef struct Rtm_Edg_t_ Rtm_Edg_t; +struct Rtm_Edg_t_ +{ + unsigned long nLats : 12; // the number of latches + unsigned long LData : 20; // the latches themselves +}; + +typedef struct Rtm_Obj_t_ Rtm_Obj_t; +struct Rtm_Obj_t_ +{ + void * pCopy; // the copy of this object + unsigned long Type : 3; // object type + unsigned long fMark : 1; // multipurpose mark + unsigned long fAuto : 1; // this object belongs to an autonomous component + unsigned long fCompl0 : 1; // complemented attribute of the first edge + unsigned long fCompl1 : 1; // complemented attribute of the second edge + unsigned long nFanins : 8; // the number of fanins + unsigned Num : 17; // the retiming number of this node + int Id; // ID of this object + int Temp; // temporary usage + int nFanouts; // the number of fanouts + void * pFanio[0]; // fanins and their edges (followed by fanouts and pointers to their edges) +}; + +static inline Rtm_Obj_t * Rtm_ObjFanin( Rtm_Obj_t * pObj, int i ) { return (Rtm_Obj_t *)pObj->pFanio[2*i]; } +static inline Rtm_Obj_t * Rtm_ObjFanout( Rtm_Obj_t * pObj, int i ) { return (Rtm_Obj_t *)pObj->pFanio[2*(pObj->nFanins+i)]; } +static inline Rtm_Edg_t * Rtm_ObjEdge( Rtm_Obj_t * pObj, int i ) { return (Rtm_Edg_t *)(pObj->pFanio + 2*i + 1); } +static inline Rtm_Edg_t * Rtm_ObjFanoutEdge( Rtm_Obj_t * pObj, int i ) { return (Rtm_Edg_t *)pObj->pFanio[2*(pObj->nFanins+i) + 1]; } + +static inline Rtm_Init_t Rtm_InitNot( Rtm_Init_t Val ) { if ( Val == RTM_VAL_ZERO ) return RTM_VAL_ONE; if ( Val == RTM_VAL_ONE ) return RTM_VAL_ZERO; assert( 0 ); return -1; } +static inline Rtm_Init_t Rtm_InitNotCond( Rtm_Init_t Val, int c ) { return c ? Rtm_InitNot(Val) : Val; } +static inline Rtm_Init_t Rtm_InitAnd(Rtm_Init_t ValA, Rtm_Init_t ValB ) { if ( ValA == RTM_VAL_ONE && ValB == RTM_VAL_ONE ) return RTM_VAL_ONE; if ( ValA == RTM_VAL_ZERO || ValB == RTM_VAL_ZERO ) return RTM_VAL_ZERO; assert( 0 ); return -1; } + +static inline int Rtm_InitWordsNum( int nLats ) { return (nLats >> 4) + ((nLats & 15) > 0); } +static inline int Rtm_InitGetTwo( unsigned * p, int i ) { return (p[i>>4] >> ((i & 15)<<1)) & 3; } +static inline void Rtm_InitSetTwo( unsigned * p, int i, int val ) { p[i>>4] |= (val << ((i & 15)<<1)); } +static inline void Rtm_InitXorTwo( unsigned * p, int i, int val ) { p[i>>4] ^= (val << ((i & 15)<<1)); } + +static inline Rtm_Init_t Rtm_ObjGetFirst1( Rtm_Edg_t * pEdge ) { return pEdge->LData & 3; } +static inline Rtm_Init_t Rtm_ObjGetLast1( Rtm_Edg_t * pEdge ) { return (pEdge->LData >> ((pEdge->nLats-1)<<1)) & 3; } +static inline Rtm_Init_t Rtm_ObjGetOne1( Rtm_Edg_t * pEdge, int i ) { assert( i < (int)pEdge->nLats ); return (pEdge->LData >> (i << 1)) & 3; } +static inline Rtm_Init_t Rtm_ObjRemFirst1( Rtm_Edg_t * pEdge ) { int Val = pEdge->LData & 3; pEdge->LData >>= 2; assert(pEdge->nLats > 0); pEdge->nLats--; return Val; } +static inline Rtm_Init_t Rtm_ObjRemLast1( Rtm_Edg_t * pEdge ) { int Val = (pEdge->LData >> ((pEdge->nLats-1)<<1)) & 3; pEdge->LData ^= Val << ((pEdge->nLats-1)<<1); assert(pEdge->nLats > 0); pEdge->nLats--; return Val; } +static inline void Rtm_ObjAddFirst1( Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { assert( Val > 0 && Val < 4 ); pEdge->LData = (pEdge->LData << 2) | Val; pEdge->nLats++; } +static inline void Rtm_ObjAddLast1( Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { assert( Val > 0 && Val < 4 ); pEdge->LData |= Val << (pEdge->nLats<<1); pEdge->nLats++; } + +static inline Rtm_Init_t Rtm_ObjGetFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return Rtm_InitGetTwo( p->pExtra + pEdge->LData, 0 ); } +static inline Rtm_Init_t Rtm_ObjGetLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return Rtm_InitGetTwo( p->pExtra + pEdge->LData, pEdge->nLats - 1 ); } +static inline Rtm_Init_t Rtm_ObjGetOne2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, int i ) { return Rtm_InitGetTwo( p->pExtra + pEdge->LData, i ); } +static Rtm_Init_t Rtm_ObjRemFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); +static inline Rtm_Init_t Rtm_ObjRemLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Val = Rtm_ObjGetLast2( p, pEdge ); Rtm_InitXorTwo( p->pExtra + pEdge->LData, pEdge->nLats - 1, Val ); pEdge->nLats--; return Val; } +static void Rtm_ObjAddFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ); +static inline void Rtm_ObjAddLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { Rtm_InitSetTwo( p->pExtra + pEdge->LData, pEdge->nLats, Val ); pEdge->nLats++; } + +static void Rtm_ObjTransferToSmall( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); +static void Rtm_ObjTransferToBig( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); +static void Rtm_ObjTransferToBigger( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); + +static inline Rtm_Init_t Rtm_ObjGetFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return pEdge->nLats > 10? Rtm_ObjGetFirst2(p, pEdge) : Rtm_ObjGetFirst1(pEdge); } +static inline Rtm_Init_t Rtm_ObjGetLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return pEdge->nLats > 10? Rtm_ObjGetLast2(p, pEdge) : Rtm_ObjGetLast1(pEdge); } +static inline Rtm_Init_t Rtm_ObjGetOne( Rtm_Man_t * p, Rtm_Edg_t * pEdge, int i ) { return pEdge->nLats > 10? Rtm_ObjGetOne2(p, pEdge, i) : Rtm_ObjGetOne1(pEdge, i); } +static Rtm_Init_t Rtm_ObjRemFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Res = pEdge->nLats > 10 ? Rtm_ObjRemFirst2(p, pEdge) : Rtm_ObjRemFirst1(pEdge); if ( pEdge->nLats == 10 ) Rtm_ObjTransferToSmall(p, pEdge); return Res; } +static Rtm_Init_t Rtm_ObjRemLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Res = pEdge->nLats > 10 ? Rtm_ObjRemLast2(p, pEdge) : Rtm_ObjRemLast1(pEdge); if ( pEdge->nLats == 10 ) Rtm_ObjTransferToSmall(p, pEdge); return Res; } +static void Rtm_ObjAddFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { if ( pEdge->nLats == 10 ) Rtm_ObjTransferToBig(p, pEdge); else if ( (pEdge->nLats & 15) == 15 ) Rtm_ObjTransferToBigger(p, pEdge); if ( pEdge->nLats >= 10 ) Rtm_ObjAddFirst2(p, pEdge, Val); else Rtm_ObjAddFirst1(pEdge, Val); } +static void Rtm_ObjAddLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { if ( pEdge->nLats == 10 ) Rtm_ObjTransferToBig(p, pEdge); else if ( (pEdge->nLats & 15) == 15 ) Rtm_ObjTransferToBigger(p, pEdge); if ( pEdge->nLats >= 10 ) Rtm_ObjAddLast2(p, pEdge, Val); else Rtm_ObjAddLast1(pEdge, Val); } + + +// iterator over the primary inputs +#define Rtm_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPis, pObj, i ) +// iterator over the primary outputs +#define Rtm_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPos, pObj, i ) +// iterator over all objects, including those currently not used +#define Rtm_ManForEachObj( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vObjs, pObj, i ) +// iterate through the fanins +#define Rtm_ObjForEachFanin( pObj, pFanin, i ) \ + for ( i = 0; i < (int)(pObj)->nFanins && ((pFanin = Rtm_ObjFanin(pObj, i)), 1); i++ ) +// iterate through the fanouts +#define Rtm_ObjForEachFanout( pObj, pFanout, i ) \ + for ( i = 0; i < (int)(pObj)->nFanouts && ((pFanout = Rtm_ObjFanout(pObj, i)), 1); i++ ) +// iterate through the fanin edges +#define Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) \ + for ( i = 0; i < (int)(pObj)->nFanins && ((pEdge = Rtm_ObjEdge(pObj, i)), 1); i++ ) +// iterate through the fanout edges +#define Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) \ + for ( i = 0; i < (int)(pObj)->nFanouts && ((pEdge = Rtm_ObjFanoutEdge(pObj, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transfers from big to small storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjTransferToSmall( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) +{ + assert( pEdge->nLats == 10 ); + pEdge->LData = p->pExtra[pEdge->LData]; +} + +/**Function************************************************************* + + Synopsis [Transfers from small to big storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjTransferToBig( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) +{ + assert( pEdge->nLats == 10 ); + if ( p->nExtraCur + 1 > p->nExtraAlloc ) + { + int nExtraAllocNew = AIG_MAX( 2 * p->nExtraAlloc, 1024 ); + p->pExtra = REALLOC( unsigned, p->pExtra, nExtraAllocNew ); + p->nExtraAlloc = nExtraAllocNew; + } + p->pExtra[p->nExtraCur] = pEdge->LData; + pEdge->LData = p->nExtraCur++; +} + +/**Function************************************************************* + + Synopsis [Transfers to bigger storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjTransferToBigger( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) +{ + int nWords; + assert( (pEdge->nLats & 15) == 15 ); + nWords = (pEdge->nLats + 1) >> 4; + if ( p->nExtraCur + nWords + 1 > p->nExtraAlloc ) + { + int nExtraAllocNew = AIG_MAX( 2 * p->nExtraAlloc, 1024 ); + p->pExtra = REALLOC( unsigned, p->pExtra, nExtraAllocNew ); + p->nExtraAlloc = nExtraAllocNew; + } + memcpy( p->pExtra + p->nExtraCur, p->pExtra + pEdge->LData, sizeof(unsigned) * nWords ); + p->pExtra[p->nExtraCur + nWords] = 0; + pEdge->LData = p->nExtraCur; + p->nExtraCur += nWords + 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rtm_Init_t Rtm_ObjRemFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) +{ + Rtm_Init_t Val = 0, Temp; + unsigned * pB = p->pExtra + pEdge->LData, * pE = pB + Rtm_InitWordsNum( pEdge->nLats-- ) - 1; + while ( pE >= pB ) + { + Temp = *pE & 3; + *pE = (*pE >> 2) | (Val << 30); + Val = Temp; + pE--; + } + assert( Val != 0 ); + return Val; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjAddFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) +{ + unsigned * pB = p->pExtra + pEdge->LData, * pE = pB + Rtm_InitWordsNum( ++pEdge->nLats ); + Rtm_Init_t Temp; + assert( Val != 0 ); + while ( pB < pE ) + { + Temp = *pB >> 30; + *pB = (*pB << 2) | Val; + Val = Temp; + pB++; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_PrintEdge( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) +{ +// unsigned LData = pEdge->LData; + printf( "%d : ", pEdge->nLats ); +/* + if ( pEdge->nLats > 10 ) + Extra_PrintBinary( stdout, p->pExtra + pEdge->LData, 2*(pEdge->nLats+1) ); + else + Extra_PrintBinary( stdout, &LData, 2*(pEdge->nLats+1) ); +*/ + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Allocates the retiming manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rtm_Man_t * Rtm_ManAlloc( Aig_Man_t * p ) +{ + Rtm_Man_t * pRtm; + // start the manager + pRtm = ALLOC( Rtm_Man_t, 1 ); + memset( pRtm, 0, sizeof(Rtm_Man_t) ); + // perform initializations + pRtm->vObjs = Vec_PtrAlloc( Aig_ManObjNum(p) ); + pRtm->vPis = Vec_PtrAlloc( Aig_ManPiNum(p) ); + pRtm->vPos = Vec_PtrAlloc( Aig_ManPoNum(p) ); + pRtm->pMem = Aig_MmFlexStart(); + return pRtm; +} + +/**Function************************************************************* + + Synopsis [Allocates the retiming manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ManFree( Rtm_Man_t * p ) +{ + Vec_PtrFree( p->vObjs ); + Vec_PtrFree( p->vPis ); + Vec_PtrFree( p->vPos ); + Aig_MmFlexStop( p->pMem, 0 ); + FREE( p->pExtra ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Counts the maximum number of latches on an edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ManLatchMax( Rtm_Man_t * p ) +{ + Rtm_Obj_t * pObj; + Rtm_Edg_t * pEdge; + int nLatchMax = 0, i, k;//, c, Val; + Rtm_ManForEachObj( p, pObj, i ) + Rtm_ObjForEachFaninEdge( pObj, pEdge, k ) + { +/* + for ( c = 0; c < (int)pEdge->nLats; c++ ) + { + Val = Rtm_ObjGetOne( p, pEdge, c ); + assert( Val == 1 || Val == 2 ); + } +*/ + nLatchMax = AIG_MAX( nLatchMax, (int)pEdge->nLats ); + } + return nLatchMax; +} + +/**Function************************************************************* + + Synopsis [Allocates the retiming object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rtm_Obj_t * Rtm_ObjAlloc( Rtm_Man_t * pRtm, int nFanins, int nFanouts ) +{ + Rtm_Obj_t * pObj; + int Size = sizeof(Rtm_Obj_t) + sizeof(Rtm_Obj_t *) * (nFanins + nFanouts) * 2; + pObj = (Rtm_Obj_t *)Aig_MmFlexEntryFetch( pRtm->pMem, Size ); + memset( pObj, 0, sizeof(Rtm_Obj_t) ); + pObj->Type = (int)(nFanins == 1 && nFanouts == 0); // mark PO + pObj->Num = nFanins; // temporary + pObj->Temp = nFanouts; + pObj->Id = Vec_PtrSize(pRtm->vObjs); + Vec_PtrPush( pRtm->vObjs, pObj ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Allocates the retiming object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjAddFanin( Rtm_Obj_t * pObj, Rtm_Obj_t * pFanin, int fCompl ) +{ + pObj->pFanio[ 2*pObj->nFanins ] = pFanin; + pObj->pFanio[ 2*pObj->nFanins + 1 ] = NULL; + pFanin->pFanio[ 2*(pFanin->Num + pFanin->nFanouts) ] = pObj; + pFanin->pFanio[ 2*(pFanin->Num + pFanin->nFanouts) + 1 ] = pObj->pFanio + 2*pObj->nFanins + 1; + if ( pObj->nFanins == 0 ) + pObj->fCompl0 = fCompl; + else if ( pObj->nFanins == 1 ) + pObj->fCompl1 = fCompl; + else + assert( 0 ); + pObj->nFanins++; + pFanin->nFanouts++; + assert( pObj->nFanins <= pObj->Num ); + assert( pFanin->nFanouts <= pFanin->Temp ); +} + +/**Function************************************************************* + + Synopsis [Check the possibility of forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ObjCheckRetimeFwd( Rtm_Obj_t * pObj ) +{ + Rtm_Edg_t * pEdge; + int i; + Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) + if ( pEdge->nLats == 0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Check the possibility of forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ObjCheckRetimeBwd( Rtm_Obj_t * pObj ) +{ + Rtm_Edg_t * pEdge; + int i; + Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) + if ( pEdge->nLats == 0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Check the possibility of forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ObjGetDegreeFwd( Rtm_Obj_t * pObj ) +{ + Rtm_Obj_t * pFanin; + int i, Degree = 0; + Rtm_ObjForEachFanin( pObj, pFanin, i ) + Degree = AIG_MAX( Degree, (int)pFanin->Num ); + return Degree + 1; +} + +/**Function************************************************************* + + Synopsis [Check the possibility of forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ObjGetDegreeBwd( Rtm_Obj_t * pObj ) +{ + Rtm_Obj_t * pFanout; + int i, Degree = 0; + Rtm_ObjForEachFanout( pObj, pFanout, i ) + Degree = AIG_MAX( Degree, (int)pFanout->Num ); + return Degree + 1; +} + +/**Function************************************************************* + + Synopsis [Performs forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjRetimeFwd( Rtm_Man_t * pRtm, Rtm_Obj_t * pObj ) +{ + Rtm_Init_t ValTotal, ValCur; + Rtm_Edg_t * pEdge; + int i; + assert( Rtm_ObjCheckRetimeFwd(pObj) ); + // extract values and compute the result + ValTotal = RTM_VAL_ONE; + Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) + { + ValCur = Rtm_ObjRemFirst( pRtm, pEdge ); + ValCur = Rtm_InitNotCond( ValCur, i? pObj->fCompl1 : pObj->fCompl0 ); + ValTotal = Rtm_InitAnd( ValTotal, ValCur ); + } + // insert the result in the fanout values + Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) + Rtm_ObjAddLast( pRtm, pEdge, ValTotal ); +} + +/**Function************************************************************* + + Synopsis [Performs forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjRetimeBwd( Rtm_Man_t * pRtm, Rtm_Obj_t * pObj ) +{ + Rtm_Edg_t * pEdge; + int i; + assert( Rtm_ObjCheckRetimeBwd(pObj) ); + // extract values and compute the result + Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) + Rtm_ObjRemLast( pRtm, pEdge ); + // insert the result in the fanout values + Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) + Rtm_ObjAddFirst( pRtm, pEdge, RTM_VAL_VOID ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjMarkAutoFwd_rec( Rtm_Obj_t * pObj ) +{ + Rtm_Obj_t * pFanout; + int i; + if ( pObj->fAuto ) + return; + pObj->fAuto = 1; + Rtm_ObjForEachFanout( pObj, pFanout, i ) + Rtm_ObjMarkAutoFwd_rec( pFanout ); +} + +/**Function************************************************************* + + Synopsis [Marks the nodes unreachable from the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ManMarkAutoFwd( Rtm_Man_t * pRtm ) +{ + Rtm_Obj_t * pObjRtm; + int i, Counter = 0; + // mark nodes reachable from the PIs + pObjRtm = Vec_PtrEntry( pRtm->vObjs, 0 ); + Rtm_ObjMarkAutoFwd_rec( pObjRtm ); + Rtm_ManForEachPi( pRtm, pObjRtm, i ) + Rtm_ObjMarkAutoFwd_rec( pObjRtm ); + // count the number of autonomous nodes + Rtm_ManForEachObj( pRtm, pObjRtm, i ) + { + pObjRtm->fAuto = !pObjRtm->fAuto; + Counter += pObjRtm->fAuto; + } + // mark the fanins of the autonomous nodes + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjMarkAutoBwd_rec( Rtm_Obj_t * pObj ) +{ + Rtm_Obj_t * pFanin; + int i; + if ( pObj->fAuto ) + return; + pObj->fAuto = 1; + Rtm_ObjForEachFanin( pObj, pFanin, i ) + Rtm_ObjMarkAutoBwd_rec( pFanin ); +} + +/**Function************************************************************* + + Synopsis [Marks the nodes unreachable from the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ManMarkAutoBwd( Rtm_Man_t * pRtm ) +{ + Rtm_Obj_t * pObjRtm; + int i, Counter = 0; + // mark nodes reachable from the PIs + pObjRtm = Vec_PtrEntry( pRtm->vObjs, 0 ); + pObjRtm->fAuto = 1; + Rtm_ManForEachPi( pRtm, pObjRtm, i ) + pObjRtm->fAuto = 1; + Rtm_ManForEachPo( pRtm, pObjRtm, i ) + Rtm_ObjMarkAutoBwd_rec( pObjRtm ); + // count the number of autonomous nodes + Rtm_ManForEachObj( pRtm, pObjRtm, i ) + { + pObjRtm->fAuto = !pObjRtm->fAuto; + Counter += pObjRtm->fAuto; + } + // mark the fanins of the autonomous nodes + return Counter; +} + +/**Function************************************************************* + + Synopsis [Derive retiming manager from the given AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rtm_Man_t * Rtm_ManFromAig( Aig_Man_t * p ) +{ + Rtm_Man_t * pRtm; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i; + assert( Aig_ManRegNum(p) > 0 ); + assert( Aig_ManBufNum(p) == 0 ); + // allocate the manager + pRtm = Rtm_ManAlloc( p ); + // allocate objects + pObj = Aig_ManConst1(p); + pObj->pData = Rtm_ObjAlloc( pRtm, 0, pObj->nRefs ); + Aig_ManForEachPiSeq( p, pObj, i ) + { + pObj->pData = Rtm_ObjAlloc( pRtm, 0, pObj->nRefs ); + Vec_PtrPush( pRtm->vPis, pObj->pData ); + } + Aig_ManForEachPoSeq( p, pObj, i ) + { + pObj->pData = Rtm_ObjAlloc( pRtm, 1, 0 ); + Vec_PtrPush( pRtm->vPos, pObj->pData ); + } + Aig_ManForEachLoSeq( p, pObj, i ) + pObj->pData = Rtm_ObjAlloc( pRtm, 1, pObj->nRefs ); + Aig_ManForEachLiSeq( p, pObj, i ) + pObj->pData = Rtm_ObjAlloc( pRtm, 1, 1 ); + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Rtm_ObjAlloc( pRtm, 2, pObj->nRefs ); + // connect objects + Aig_ManForEachPoSeq( p, pObj, i ) + Rtm_ObjAddFanin( pObj->pData, Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + Aig_ManForEachLiSeq( p, pObj, i ) + Rtm_ObjAddFanin( pObj->pData, Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + Rtm_ObjAddFanin( pObjLo->pData, pObjLi->pData, 0 ); + Aig_ManForEachNode( p, pObj, i ) + { + Rtm_ObjAddFanin( pObj->pData, Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + Rtm_ObjAddFanin( pObj->pData, Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + } + return pRtm; +} + +/**Function************************************************************* + + Synopsis [Derive AIG manager after retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Rtm_ManToAig_rec( Aig_Man_t * pNew, Rtm_Man_t * pRtm, Rtm_Obj_t * pObjRtm, int * pLatches ) +{ + Rtm_Edg_t * pEdge; + Aig_Obj_t * pRes, * pFanin; + int k, Val; + if ( pObjRtm->pCopy ) + return pObjRtm->pCopy; + // get the inputs + pRes = Aig_ManConst1( pNew ); + Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) + { + if ( pEdge->nLats == 0 ) + pFanin = Rtm_ManToAig_rec( pNew, pRtm, Rtm_ObjFanin(pObjRtm, k), pLatches ); + else + { + Val = Rtm_ObjGetFirst( pRtm, pEdge ); + pFanin = Aig_ManPi( pNew, pLatches[2*pObjRtm->Id + k] + pEdge->nLats - 1 ); + pFanin = Aig_NotCond( pFanin, Val == RTM_VAL_ONE ); + } + pFanin = Aig_NotCond( pFanin, k ? pObjRtm->fCompl1 : pObjRtm->fCompl0 ); + pRes = Aig_And( pNew, pRes, pFanin ); + } + return pObjRtm->pCopy = pRes; +} + +/**Function************************************************************* + + Synopsis [Derive AIG manager after retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Rtm_ManToAig( Rtm_Man_t * pRtm ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObjNew; + Rtm_Obj_t * pObjRtm; + Rtm_Edg_t * pEdge; + int i, k, m, Val, nLatches, * pLatches; + // count latches and mark the first latch on each edge + pLatches = ALLOC( int, 2 * Vec_PtrSize(pRtm->vObjs) ); + nLatches = 0; + Rtm_ManForEachObj( pRtm, pObjRtm, i ) + Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) + { + pLatches[2*pObjRtm->Id + k] = Vec_PtrSize(pRtm->vPis) + nLatches; + nLatches += pEdge->nLats; + } + // create the new manager + pNew = Aig_ManStart( Vec_PtrSize(pRtm->vObjs) + nLatches ); + // create PIs/POs and latches + pObjRtm = Vec_PtrEntry( pRtm->vObjs, 0 ); + pObjRtm->pCopy = Aig_ManConst1(pNew); + Rtm_ManForEachPi( pRtm, pObjRtm, i ) + pObjRtm->pCopy = Aig_ObjCreatePi(pNew); + for ( i = 0; i < nLatches; i++ ) + Aig_ObjCreatePi(pNew); + // create internal nodes + Rtm_ManForEachObj( pRtm, pObjRtm, i ) + Rtm_ManToAig_rec( pNew, pRtm, pObjRtm, pLatches ); + // create POs + Rtm_ManForEachPo( pRtm, pObjRtm, i ) + Aig_ObjCreatePo( pNew, pObjRtm->pCopy ); + // connect latches + Rtm_ManForEachObj( pRtm, pObjRtm, i ) + Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) + { + if ( pEdge->nLats == 0 ) + continue; + pObjNew = Rtm_ObjFanin( pObjRtm, k )->pCopy; + for ( m = 0; m < (int)pEdge->nLats; m++ ) + { + Val = Rtm_ObjGetOne( pRtm, pEdge, pEdge->nLats - 1 - m ); + assert( Val == RTM_VAL_ZERO || Val == RTM_VAL_ONE || Val == RTM_VAL_VOID ); + pObjNew = Aig_NotCond( pObjNew, Val == RTM_VAL_ONE ); + Aig_ObjCreatePo( pNew, pObjNew ); + pObjNew = Aig_ManPi( pNew, pLatches[2*pObjRtm->Id + k] + m ); + pObjNew = Aig_NotCond( pObjNew, Val == RTM_VAL_ONE ); + } +// assert( Aig_Regular(pObjNew)->nRefs > 0 ); + } + free( pLatches ); + pNew->nRegs = nLatches; + // remove useless nodes + Aig_ManCleanup( pNew ); + if ( !Aig_ManCheck( pNew ) ) + printf( "Rtm_ManToAig: The network check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Performs forward retiming with the given limit on depth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Rtm_ManRetime( Aig_Man_t * p, int fForward, int nStepsMax, int fVerbose ) +{ + Vec_Ptr_t * vQueue; + Aig_Man_t * pNew; + Rtm_Man_t * pRtm; + Rtm_Obj_t * pObj, * pNext; + Aig_Obj_t * pObjAig; + int i, k, nAutos, Degree, DegreeMax = 0; + int clk; + + // create the retiming manager +clk = clock(); + pRtm = Rtm_ManFromAig( p ); + // set registers + Aig_ManForEachLoSeq( p, pObjAig, i ) + Rtm_ObjAddFirst( pRtm, Rtm_ObjEdge(pObjAig->pData, 0), fForward? RTM_VAL_ZERO : RTM_VAL_VOID ); + // detect and mark the autonomous components + if ( fForward ) + nAutos = Rtm_ManMarkAutoFwd( pRtm ); + else + nAutos = Rtm_ManMarkAutoBwd( pRtm ); + if ( fVerbose ) + { + printf( "Detected %d autonomous objects. ", nAutos ); + PRT( "Time", clock() - clk ); + } + + // set the current retiming number + Rtm_ManForEachObj( pRtm, pObj, i ) + { + assert( pObj->nFanins == pObj->Num ); + assert( pObj->nFanouts == pObj->Temp ); + pObj->Num = 0; + } + +clk = clock(); + // put the LOs on the queue + vQueue = Vec_PtrAlloc( 1000 ); + if ( fForward ) + { + Aig_ManForEachLoSeq( p, pObjAig, i ) + { + pObj = pObjAig->pData; + if ( pObj->fAuto ) + continue; + pObj->fMark = 1; + Vec_PtrPush( vQueue, pObj ); + } + } + else + { + Aig_ManForEachLiSeq( p, pObjAig, i ) + { + pObj = pObjAig->pData; + if ( pObj->fAuto ) + continue; + pObj->fMark = 1; + Vec_PtrPush( vQueue, pObj ); + } + } + // perform retiming + DegreeMax = 0; + Vec_PtrForEachEntry( vQueue, pObj, i ) + { + pObj->fMark = 0; + // retime the node + if ( fForward ) + { + Rtm_ObjRetimeFwd( pRtm, pObj ); + // check if its fanouts should be retimed + Rtm_ObjForEachFanout( pObj, pNext, k ) + { + if ( pNext->fMark ) // skip aleady scheduled + continue; + if ( pNext->Type ) // skip POs + continue; + if ( !Rtm_ObjCheckRetimeFwd( pNext ) ) // skip non-retimable + continue; + Degree = Rtm_ObjGetDegreeFwd( pNext ); + DegreeMax = AIG_MAX( DegreeMax, Degree ); + if ( Degree > nStepsMax ) // skip nodes with high degree + continue; + pNext->fMark = 1; + pNext->Num = Degree; + Vec_PtrPush( vQueue, pNext ); + } + } + else + { + Rtm_ObjRetimeBwd( pRtm, pObj ); + // check if its fanouts should be retimed + Rtm_ObjForEachFanin( pObj, pNext, k ) + { + if ( pNext->fMark ) // skip aleady scheduled + continue; + if ( pNext->nFanins == 0 ) // skip PIs + continue; + if ( !Rtm_ObjCheckRetimeBwd( pNext ) ) // skip non-retimable + continue; + Degree = Rtm_ObjGetDegreeBwd( pNext ); + DegreeMax = AIG_MAX( DegreeMax, Degree ); + if ( Degree > nStepsMax ) // skip nodes with high degree + continue; + pNext->fMark = 1; + pNext->Num = Degree; + Vec_PtrPush( vQueue, pNext ); + } + } + } + + if ( fVerbose ) + { + printf( "Performed %d %s latch moves of max depth %d and max latch count %d.\n", + Vec_PtrSize(vQueue), fForward? "fwd":"bwd", DegreeMax, Rtm_ManLatchMax(pRtm) ); + printf( "Memory usage = %d. ", pRtm->nExtraCur ); + PRT( "Time", clock() - clk ); + } + Vec_PtrFree( vQueue ); + + // get the new manager + pNew = Rtm_ManToAig( pRtm ); + pNew->pName = Aig_UtilStrsav( p->pName ); + Rtm_ManFree( pRtm ); + // group the registers +clk = clock(); + pNew = Aig_ManReduceLaches( pNew, fVerbose ); + if ( fVerbose ) + { + PRT( "Register sharing time", clock() - clk ); + } + return pNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigScl.c b/abc70930/src/aig/aig/aigScl.c new file mode 100644 index 00000000..aae088a3 --- /dev/null +++ b/abc70930/src/aig/aig/aigScl.c @@ -0,0 +1,399 @@ +/**CFile**************************************************************** + + FileName [aigScl.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Sequential cleanup.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigScl.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Remaps the manager.] + + Description [Map in the array specifies for each CI nodes the node that + should be used after remapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManRemap( Aig_Man_t * p, Vec_Ptr_t * vMap ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjMapped; + int i; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->nRegs = p->nRegs; + pNew->nAsserts = p->nAsserts; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePi(pNew); + // implement the mapping + Aig_ManForEachPi( p, pObj, i ) + { + pObjMapped = Vec_PtrEntry( vMap, i ); + pObj->pData = Aig_NotCond( Aig_Regular(pObjMapped)->pData, Aig_IsComplement(pObjMapped) ); + } + // duplicate internal nodes + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsBuf(pObj) ) + pObj->pData = Aig_ObjChild0Copy(pObj); + else if ( Aig_ObjIsNode(pObj) ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // add the POs + Aig_ManForEachPo( p, pObj, i ) + Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); + assert( Aig_ManNodeNum(p) >= Aig_ManNodeNum(pNew) ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDup(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSeqCleanup_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + // collect latch input corresponding to unmarked PI (latch output) + if ( Aig_ObjIsPi(pObj) ) + { + Vec_PtrPush( vNodes, pObj->pNext ); + return; + } + if ( Aig_ObjIsPo(pObj) ) + { + Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Aig_ManSeqCleanup_rec( p, Aig_ObjFanin1(pObj), vNodes ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManSeqCleanup( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes, * vCis, * vCos; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, nTruePis, nTruePos; + assert( Aig_ManBufNum(p) == 0 ); + + // mark the PIs + Aig_ManIncrementTravId( p ); + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + Aig_ManForEachPiSeq( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + + // prepare to collect nodes reachable from POs + vNodes = Vec_PtrAlloc( 100 ); + Aig_ManForEachPoSeq( p, pObj, i ) + Vec_PtrPush( vNodes, pObj ); + + // remember latch inputs in latch outputs + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + pObjLo->pNext = pObjLi; + // mark the nodes reachable from these nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + Aig_ManSeqCleanup_rec( p, pObj, vNodes ); + assert( Vec_PtrSize(vNodes) <= Aig_ManPoNum(p) ); + // clean latch output pointers + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + pObjLo->pNext = NULL; + + // if some latches are removed, update PIs/POs + if ( Vec_PtrSize(vNodes) < Aig_ManPoNum(p) ) + { + if ( p->vFlopNums ) + { + int nTruePos = Aig_ManPoNum(p)-Aig_ManRegNum(p); + // remember numbers of flops in the flops + Aig_ManForEachLiSeq( p, pObj, i ) + pObj->pNext = (Aig_Obj_t *)(long)Vec_IntEntry( p->vFlopNums, i - nTruePos ); + // reset the flop numbers + Vec_PtrForEachEntryStart( vNodes, pObj, i, nTruePos ) + Vec_IntWriteEntry( p->vFlopNums, i - nTruePos, (int)(long)pObj->pNext ); + Vec_IntShrink( p->vFlopNums, Vec_PtrSize(vNodes) - nTruePos ); + // clean the next pointer + Aig_ManForEachLiSeq( p, pObj, i ) + pObj->pNext = NULL; + } + // collect new CIs/COs + vCis = Vec_PtrAlloc( Aig_ManPiNum(p) ); + Aig_ManForEachPi( p, pObj, i ) + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + Vec_PtrPush( vCis, pObj ); + else + { + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); +// Aig_ManRecycleMemory( p, pObj ); + } + vCos = Vec_PtrAlloc( Aig_ManPoNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + Vec_PtrPush( vCos, pObj ); + else + { + Aig_ObjDisconnect( p, pObj ); + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); +// Aig_ManRecycleMemory( p, pObj ); + } + // remember the number of true PIs/POs + nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p); + nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p); + // set the new number of registers + p->nRegs -= Aig_ManPoNum(p) - Vec_PtrSize(vNodes); + // create new PIs/POs + assert( Vec_PtrSize(vCis) == nTruePis + p->nRegs ); + assert( Vec_PtrSize(vCos) == nTruePos + p->nRegs ); + Vec_PtrFree( p->vPis ); p->vPis = vCis; + Vec_PtrFree( p->vPos ); p->vPos = vCos; + p->nObjs[AIG_OBJ_PI] = Vec_PtrSize( p->vPis ); + p->nObjs[AIG_OBJ_PO] = Vec_PtrSize( p->vPos ); + + } + Vec_PtrFree( vNodes ); + // remove dangling nodes + return Aig_ManCleanup( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCountMergeRegs( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pFanin; + int i, Counter = 0, Const0 = 0, Const1 = 0; + Aig_ManIncrementTravId( p ); + Aig_ManForEachLiSeq( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + if ( Aig_ObjIsConst1(pFanin) ) + { + if ( Aig_ObjFaninC0(pObj) ) + Const0++; + else + Const1++; + } + if ( Aig_ObjIsTravIdCurrent(p, pFanin) ) + continue; + Aig_ObjSetTravIdCurrent(p, pFanin); + Counter++; + } + printf( "Regs = %d. Fanins = %d. Const0 = %d. Const1 = %d.\n", + Aig_ManRegNum(p), Counter, Const0, Const1 ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Checks how many latches can be reduced.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManReduceLachesCount( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pFanin; + int i, Counter = 0, Diffs = 0; + assert( Aig_ManRegNum(p) > 0 ); + Aig_ManForEachObj( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + Aig_ManForEachLiSeq( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + if ( Aig_ObjFaninC0(pObj) ) + { + if ( pFanin->fMarkB ) + Counter++; + else + pFanin->fMarkB = 1; + } + else + { + if ( pFanin->fMarkA ) + Counter++; + else + pFanin->fMarkA = 1; + } + } + // count fanins that have both attributes + Aig_ManForEachLiSeq( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + Diffs += pFanin->fMarkA && pFanin->fMarkB; + pFanin->fMarkA = pFanin->fMarkB = 0; + } +// printf( "Diffs = %d.\n", Diffs ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Reduces the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManReduceLachesOnce( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMap; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pFanin; + int * pMapping, i; + // start mapping by adding the true PIs + vMap = Vec_PtrAlloc( Aig_ManPiNum(p) ); + Aig_ManForEachPiSeq( p, pObj, i ) + Vec_PtrPush( vMap, pObj ); + // create mapping of fanin nodes into the corresponding latch outputs + pMapping = ALLOC( int, 2 * Aig_ManObjNumMax(p) ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + pFanin = Aig_ObjFanin0(pObjLi); + if ( Aig_ObjFaninC0(pObjLi) ) + { + if ( pFanin->fMarkB ) + { + Vec_PtrPush( vMap, Aig_ManLo(p, pMapping[2*pFanin->Id + 1]) ); + } + else + { + pFanin->fMarkB = 1; + pMapping[2*pFanin->Id + 1] = i; + Vec_PtrPush( vMap, pObjLo ); + } + } + else + { + if ( pFanin->fMarkA ) + { + Vec_PtrPush( vMap, Aig_ManLo(p, pMapping[2*pFanin->Id]) ); + } + else + { + pFanin->fMarkA = 1; + pMapping[2*pFanin->Id] = i; + Vec_PtrPush( vMap, pObjLo ); + } + } + } + free( pMapping ); + Aig_ManForEachLiSeq( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + pFanin->fMarkA = pFanin->fMarkB = 0; + } + return vMap; +} + +/**Function************************************************************* + + Synopsis [Reduces the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManReduceLaches( Aig_Man_t * p, int fVerbose ) +{ + Aig_Man_t * pTemp; + Vec_Ptr_t * vMap; + int nSaved, nCur; + for ( nSaved = 0; (nCur = Aig_ManReduceLachesCount(p)); nSaved += nCur ) + { + if ( fVerbose ) + { + printf( "Saved = %5d. ", nCur ); + printf( "RBeg = %5d. NBeg = %6d. ", Aig_ManRegNum(p), Aig_ManNodeNum(p) ); + } + vMap = Aig_ManReduceLachesOnce( p ); + p = Aig_ManRemap( pTemp = p, vMap ); + Aig_ManStop( pTemp ); + Vec_PtrFree( vMap ); + Aig_ManSeqCleanup( p ); + if ( fVerbose ) + { + printf( "REnd = %5d. NEnd = %6d. ", Aig_ManRegNum(p), Aig_ManNodeNum(p) ); + printf( "\n" ); + } + if ( p->nRegs == 0 ) + break; + } + return p; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigSeq.c b/abc70930/src/aig/aig/aigSeq.c new file mode 100644 index 00000000..daafeab1 --- /dev/null +++ b/abc70930/src/aig/aig/aigSeq.c @@ -0,0 +1,502 @@ +/**CFile**************************************************************** + + FileName [aigSeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Sequential strashing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigSeq.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts combinational AIG manager into a sequential one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSeqStrashConvert( Aig_Man_t * p, int nLatches, int * pInits ) +{ + Aig_Obj_t * pObjLi, * pObjLo, * pLatch; + int i; + assert( Vec_PtrSize( p->vBufs ) == 0 ); + // collect the POs to be converted into latches + for ( i = 0; i < nLatches; i++ ) + { + // get the corresponding PI/PO pair + pObjLi = Aig_ManPo( p, Aig_ManPoNum(p) - nLatches + i ); + pObjLo = Aig_ManPi( p, Aig_ManPiNum(p) - nLatches + i ); + // create latch + pLatch = Aig_Latch( p, Aig_ObjChild0(pObjLi), pInits? pInits[i] : 0 ); + // recycle the old PO object + Aig_ObjDisconnect( p, pObjLi ); + Vec_PtrWriteEntry( p->vObjs, pObjLi->Id, NULL ); + Aig_ManRecycleMemory( p, pObjLi ); + // convert the corresponding PI to be a buffer and connect it to the latch + pObjLo->Type = AIG_OBJ_BUF; + Aig_ObjConnect( p, pObjLo, pLatch, NULL ); + // save the buffer +// Vec_PtrPush( p->vBufs, pObjLo ); + } + // shrink the arrays + Vec_PtrShrink( p->vPis, Aig_ManPiNum(p) - nLatches ); + Vec_PtrShrink( p->vPos, Aig_ManPoNum(p) - nLatches ); + // update the counters of different objects + p->nObjs[AIG_OBJ_PI] -= nLatches; + p->nObjs[AIG_OBJ_PO] -= nLatches; + p->nObjs[AIG_OBJ_BUF] += nLatches; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDfsSeq_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( pObj == NULL ) + return; + if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) + return; + Aig_ObjSetTravIdCurrent( p, pObj ); + if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) + return; + Aig_ManDfsSeq_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Aig_ManDfsSeq_rec( p, Aig_ObjFanin1(pObj), vNodes ); +// if ( (Aig_ObjFanin0(pObj) == NULL || Aig_ObjIsBuf(Aig_ObjFanin0(pObj))) && +// (Aig_ObjFanin1(pObj) == NULL || Aig_ObjIsBuf(Aig_ObjFanin1(pObj))) ) + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfsSeq( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + Aig_ManDfsSeq_rec( p, Aig_ObjFanin0(pObj), vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDfsUnreach_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( pObj == NULL ) + return; + if ( Aig_ObjIsTravIdPrevious(p, pObj) || Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdPrevious( p, pObj ); // assume unknown + Aig_ManDfsUnreach_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Aig_ManDfsUnreach_rec( p, Aig_ObjFanin1(pObj), vNodes ); + if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) && + (Aig_ObjFanin1(pObj) == NULL || Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj))) ) + Vec_PtrPush( vNodes, pObj ); + else + Aig_ObjSetTravIdCurrent( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes unreachable from PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfsUnreach( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj, * pFanin; + int i, k;//, RetValue; + // collect unreachable nodes + Aig_ManIncrementTravId( p ); + Aig_ManIncrementTravId( p ); + // mark the constant and PIs + Aig_ObjSetTravIdPrevious( p, Aig_ManConst1(p) ); + Aig_ManForEachPi( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // curr marks visited nodes reachable from PIs + // prev marks visited nodes unreachable or unknown + + // collect the unreachable nodes + vNodes = Vec_PtrAlloc( 32 ); + Aig_ManForEachPo( p, pObj, i ) + Aig_ManDfsUnreach_rec( p, Aig_ObjFanin0(pObj), vNodes ); + + // refine resulting nodes + do + { + k = 0; + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + assert( Aig_ObjIsTravIdPrevious(p, pObj) ); + if ( Aig_ObjIsLatch(pObj) || Aig_ObjIsBuf(pObj) ) + { + pFanin = Aig_ObjFanin0(pObj); + assert( Aig_ObjIsTravIdPrevious(p, pFanin) || Aig_ObjIsTravIdCurrent(p, pFanin) ); + if ( Aig_ObjIsTravIdCurrent(p, pFanin) ) + { + Aig_ObjSetTravIdCurrent( p, pObj ); + continue; + } + } + else // AND gate + { + assert( Aig_ObjIsNode(pObj) ); + pFanin = Aig_ObjFanin0(pObj); + assert( Aig_ObjIsTravIdPrevious(p, pFanin) || Aig_ObjIsTravIdCurrent(p, pFanin) ); + if ( Aig_ObjIsTravIdCurrent(p, pFanin) ) + { + Aig_ObjSetTravIdCurrent( p, pObj ); + continue; + } + pFanin = Aig_ObjFanin1(pObj); + assert( Aig_ObjIsTravIdPrevious(p, pFanin) || Aig_ObjIsTravIdCurrent(p, pFanin) ); + if ( Aig_ObjIsTravIdCurrent(p, pFanin) ) + { + Aig_ObjSetTravIdCurrent( p, pObj ); + continue; + } + } + // write it back + Vec_PtrWriteEntry( vNodes, k++, pObj ); + } + Vec_PtrShrink( vNodes, k ); + } + while ( k < i ); + +// if ( Vec_PtrSize(vNodes) > 0 ) +// printf( "Found %d unreachable.\n", Vec_PtrSize(vNodes) ); + return vNodes; + +/* + // the resulting array contains all unreachable nodes except const 1 + if ( Vec_PtrSize(vNodes) == 0 ) + { + Vec_PtrFree( vNodes ); + return 0; + } + RetValue = Vec_PtrSize(vNodes); + + // mark these nodes + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + Vec_PtrFree( vNodes ); + return RetValue; +*/ +} + + +/**Function************************************************************* + + Synopsis [Removes nodes that do not fanout into POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManRemoveUnmarked( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i, RetValue; + // collect unmarked nodes + vNodes = Vec_PtrAlloc( 100 ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsTerm(pObj) ) + continue; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; +//Aig_ObjPrintVerbose( pObj, 0 ); + Aig_ObjDisconnect( p, pObj ); + Vec_PtrPush( vNodes, pObj ); + } + if ( Vec_PtrSize(vNodes) == 0 ) + { + Vec_PtrFree( vNodes ); + return 0; + } + // remove the dangling objects + RetValue = Vec_PtrSize(vNodes); + Vec_PtrForEachEntry( vNodes, pObj, i ) + Aig_ObjDelete( p, pObj ); +// printf( "Removed %d dangling.\n", Vec_PtrSize(vNodes) ); + Vec_PtrFree( vNodes ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Rehashes the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManSeqRehashOne( Aig_Man_t * p, Vec_Ptr_t * vNodes, Vec_Ptr_t * vUnreach ) +{ + Aig_Obj_t * pObj, * pObjNew, * pFanin0, * pFanin1; + int i, RetValue = 0, Counter = 0;//, Counter2 = 0; + + // mark the unreachable nodes + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( vUnreach, pObj, i ) + Aig_ObjSetTravIdCurrent(p, pObj); +/* + // count the number of unreachable object connections + // that is the number of unreachable objects connected to main objects + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + + pFanin0 = Aig_ObjFanin0(pObj); + if ( pFanin0 == NULL ) + continue; + if ( Aig_ObjIsTravIdCurrent(p, pFanin0) ) + pFanin0->fMarkA = 1; + + pFanin1 = Aig_ObjFanin1(pObj); + if ( pFanin1 == NULL ) + continue; + if ( Aig_ObjIsTravIdCurrent(p, pFanin1) ) + pFanin1->fMarkA = 1; + } + + // count the objects + Aig_ManForEachObj( p, pObj, i ) + Counter2 += pObj->fMarkA, pObj->fMarkA = 0; + printf( "Connections = %d.\n", Counter2 ); +*/ + + // go through the nodes while skipping unreachable + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // skip nodes unreachable from the PIs + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + // process the node + if ( Aig_ObjIsPo(pObj) ) + { + if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ) + continue; + pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + Aig_ObjPatchFanin0( p, pObj, pFanin0 ); + continue; + } + if ( Aig_ObjIsLatch(pObj) ) + { + if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ) + continue; + pObjNew = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + pObjNew = Aig_Latch( p, pObjNew, 0 ); + Aig_ObjReplace( p, pObj, pObjNew, 1, 0 ); + RetValue = 1; + Counter++; + continue; + } + if ( Aig_ObjIsNode(pObj) ) + { + if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) && !Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) ) + continue; + pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + pFanin1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); + pObjNew = Aig_And( p, pFanin0, pFanin1 ); + Aig_ObjReplace( p, pObj, pObjNew, 1, 0 ); + RetValue = 1; + Counter++; + continue; + } + } +// printf( "Rehashings = %d.\n", Counter++ ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [If AIG contains buffers, this procedure removes them.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManRemoveBuffers( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pObjNew, * pFanin0, * pFanin1; + int i; + if ( Aig_ManBufNum(p) == 0 ) + return; + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsPo(pObj) ) + { + if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ) + continue; + pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + Aig_ObjPatchFanin0( p, pObj, pFanin0 ); + } + else if ( Aig_ObjIsLatch(pObj) ) + { + if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ) + continue; + pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + pObjNew = Aig_Latch( p, pFanin0, 0 ); + Aig_ObjReplace( p, pObj, pObjNew, 0, 0 ); + } + else if ( Aig_ObjIsAnd(pObj) ) + { + if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) && !Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) ) + continue; + pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + pFanin1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); + pObjNew = Aig_And( p, pFanin0, pFanin1 ); + Aig_ObjReplace( p, pObj, pObjNew, 0, 0 ); + } + } + assert( Aig_ManBufNum(p) == 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManSeqStrash( Aig_Man_t * p, int nLatches, int * pInits ) +{ + Vec_Ptr_t * vNodes, * vUnreach; +// Aig_Obj_t * pObj, * pFanin; +// int i; + int Iter, RetValue = 1; + + // create latches out of the additional PI/PO pairs + Aig_ManSeqStrashConvert( p, nLatches, pInits ); + + // iteratively rehash the network + for ( Iter = 0; RetValue; Iter++ ) + { +// Aig_ManPrintStats( p ); +/* + Aig_ManForEachObj( p, pObj, i ) + { + assert( pObj->Type > 0 ); + pFanin = Aig_ObjFanin0(pObj); + assert( pFanin == NULL || pFanin->Type > 0 ); + pFanin = Aig_ObjFanin1(pObj); + assert( pFanin == NULL || pFanin->Type > 0 ); + } +*/ + // mark nodes unreachable from the PIs + vUnreach = Aig_ManDfsUnreach( p ); + if ( Iter == 0 && Vec_PtrSize(vUnreach) > 0 ) + printf( "Unreachable objects = %d.\n", Vec_PtrSize(vUnreach) ); + // collect nodes reachable from the POs + vNodes = Aig_ManDfsSeq( p ); + // remove nodes unreachable from the POs + if ( Iter == 0 ) + Aig_ManRemoveUnmarked( p ); + // continue rehashing as long as there are changes + RetValue = Aig_ManSeqRehashOne( p, vNodes, vUnreach ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vUnreach ); + } + + // perform the final cleanup + Aig_ManIncrementTravId( p ); + vNodes = Aig_ManDfsSeq( p ); + Aig_ManRemoveUnmarked( p ); + Vec_PtrFree( vNodes ); + // remove buffers if they are left +// Aig_ManRemoveBuffers( p ); + + // clean up + if ( !Aig_ManCheck( p ) ) + { + printf( "Aig_ManSeqStrash: The network check has failed.\n" ); + return 0; + } + return 1; + +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigShow.c b/abc70930/src/aig/aig/aigShow.c new file mode 100644 index 00000000..96b0e37f --- /dev/null +++ b/abc70930/src/aig/aig/aigShow.c @@ -0,0 +1,356 @@ +/**CFile**************************************************************** + + FileName [ivyShow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Visualization of HAIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_WriteDotAig( Aig_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ) +{ + FILE * pFile; + Aig_Obj_t * pNode;//, * pTemp, * pPrev; + int LevelMax, Level, i; + + if ( Aig_ManNodeNum(pMan) > 200 ) + { + fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" ); + return; + } + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // mark the nodes + if ( vBold ) + Vec_PtrForEachEntry( vBold, pNode, i ) + pNode->fMarkB = 1; + + // compute levels +// LevelMax = 1 + Aig_ManSetLevels( pMan, fHaig ); + LevelMax = 1 + Aig_ManLevels( pMan ); + Aig_ManForEachPo( pMan, pNode, i ) + pNode->Level = LevelMax; + + // write the DOT header + fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph AIG {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != 0 ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "AIG structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); +// fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Aig_ManNodeNum(pMan), LevelMax ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the COs + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the CO nodes + Aig_ManForEachPo( pMan, pNode, i ) + { +/* + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":""), + Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); +*/ + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + + fprintf( pFile, ", shape = %s", (Aig_ObjIsLatch(pNode)? "box":"invtriangle") ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate nodes of each rank + for ( Level = LevelMax - 1; Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Aig_ManForEachObj( pMan, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; +/* + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + else + fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, + Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); +*/ + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + + fprintf( pFile, ", shape = ellipse" ); + if ( vBold && pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the CI nodes + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", 0 ); + // generate constant node + if ( Aig_ObjRefs(Aig_ManConst1(pMan)) > 0 ) + { + pNode = Aig_ManConst1(pMan); + // check if the costant node is present + fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); + fprintf( pFile, ", shape = ellipse" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + // generate the CI nodes + Aig_ManForEachPi( pMan, pNode, i ) + { +/* + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":""), + Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); +*/ + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + + fprintf( pFile, ", shape = %s", (Aig_ObjIsLatch(pNode)? "box":"triangle") ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Aig_ManForEachPo( pMan, pNode, i ) + fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") ); + + // generate edges + Aig_ManForEachObj( pMan, pNode, i ) + { + if ( !Aig_ObjIsNode(pNode) && !Aig_ObjIsPo(pNode) && !Aig_ObjIsBuf(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d%s", pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d%s", Aig_ObjFaninId0(pNode), (Aig_ObjIsLatch(Aig_ObjFanin0(pNode))? "_out":"") ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Aig_ObjFaninC0(pNode)? "dotted" : "bold" ); +// if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + if ( !Aig_ObjIsNode(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d%s", Aig_ObjFaninId1(pNode), (Aig_ObjIsLatch(Aig_ObjFanin1(pNode))? "_out":"") ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Aig_ObjFaninC1(pNode)? "dotted" : "bold" ); +// if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); +/* + // generate the edges between the equivalent nodes + if ( fHaig && pNode->pEquiv && Aig_ObjRefs(pNode) > 0 ) + { + pPrev = pNode; + for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Aig_Regular(pTemp->pEquiv) ) + { + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pTemp->Id ); + fprintf( pFile, " [style = %s]", Aig_IsComplement(pTemp->pEquiv)? "dotted" : "bold" ); + fprintf( pFile, ";\n" ); + pPrev = pTemp; + } + // connect the last node with the first + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " [style = %s]", Aig_IsComplement(pPrev->pEquiv)? "dotted" : "bold" ); + fprintf( pFile, ";\n" ); + } +*/ + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark nodes + if ( vBold ) + Vec_PtrForEachEntry( vBold, pNode, i ) + pNode->fMarkB = 0; + + Aig_ManForEachPo( pMan, pNode, i ) + pNode->Level = Aig_ObjFanin0(pNode)->Level; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) +{ + extern void Abc_ShowFile( char * FileNameDot ); + static Counter = 0; + char FileNameDot[200]; + FILE * pFile; + // create the file name +// Aig_ShowGetFileName( pMan->pName, FileNameDot ); + sprintf( FileNameDot, "temp%02d.dot", Counter++ ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + // generate the file + Aig_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); + // visualize the file + Abc_ShowFile( FileNameDot ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigTable.c b/abc70930/src/aig/aig/aigTable.c new file mode 100644 index 00000000..94593d70 --- /dev/null +++ b/abc70930/src/aig/aig/aigTable.c @@ -0,0 +1,268 @@ +/**CFile**************************************************************** + + FileName [aigTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Structural hashing table.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigTable.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// hashing the node +static unsigned long Aig_Hash( Aig_Obj_t * pObj, int TableSize ) +{ + unsigned long Key = Aig_ObjIsExor(pObj) * 1699; + Key ^= Aig_ObjFanin0(pObj)->Id * 7937; + Key ^= Aig_ObjFanin1(pObj)->Id * 2971; + Key ^= Aig_ObjFaninC0(pObj) * 911; + Key ^= Aig_ObjFaninC1(pObj) * 353; + return Key % TableSize; +} + +// returns the place where this node is stored (or should be stored) +static Aig_Obj_t ** Aig_TableFind( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t ** ppEntry; + if ( Aig_ObjIsLatch(pObj) ) + { + assert( Aig_ObjChild0(pObj) && Aig_ObjChild1(pObj) == NULL ); + } + else + { + assert( Aig_ObjChild0(pObj) && Aig_ObjChild1(pObj) ); + assert( Aig_ObjFanin0(pObj)->Id < Aig_ObjFanin1(pObj)->Id ); + } + for ( ppEntry = p->pTable + Aig_Hash(pObj, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) + if ( *ppEntry == pObj ) + return ppEntry; + assert( *ppEntry == NULL ); + return ppEntry; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [Typically this procedure should not be called.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TableResize( Aig_Man_t * p ) +{ + Aig_Obj_t * pEntry, * pNext; + Aig_Obj_t ** pTableOld, ** ppPlace; + int nTableSizeOld, Counter, i, clk; +clk = clock(); + // save the old table + pTableOld = p->pTable; + nTableSizeOld = p->nTableSize; + // get the new table + p->nTableSize = Aig_PrimeCudd( 2 * Aig_ManNodeNum(p) ); + p->pTable = ALLOC( Aig_Obj_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < nTableSizeOld; i++ ) + for ( pEntry = pTableOld[i], pNext = pEntry? pEntry->pNext : NULL; + pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL ) + { + // get the place where this entry goes in the table + ppPlace = Aig_TableFind( p, pEntry ); + assert( *ppPlace == NULL ); // should not be there + // add the entry to the list + *ppPlace = pEntry; + pEntry->pNext = NULL; + Counter++; + } + assert( Counter == Aig_ManNodeNum(p) ); +// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); +// PRT( "Time", clock() - clk ); + // replace the table and the parameters + free( pTableOld ); +} + +/**Function************************************************************* + + Synopsis [Checks if node with the given attributes is in the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ) +{ + Aig_Obj_t * pEntry; + assert( !Aig_IsComplement(pGhost) ); + if ( pGhost->Type == AIG_OBJ_LATCH ) + { + assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) == NULL ); + if ( !Aig_ObjRefs(Aig_ObjFanin0(pGhost)) ) + return NULL; + } + else + { + assert( pGhost->Type == AIG_OBJ_AND ); + assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) ); + assert( Aig_ObjFanin0(pGhost)->Id < Aig_ObjFanin1(pGhost)->Id ); + if ( !Aig_ObjRefs(Aig_ObjFanin0(pGhost)) || !Aig_ObjRefs(Aig_ObjFanin1(pGhost)) ) + return NULL; + } + for ( pEntry = p->pTable[Aig_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext ) + { + if ( Aig_ObjChild0(pEntry) == Aig_ObjChild0(pGhost) && + Aig_ObjChild1(pEntry) == Aig_ObjChild1(pGhost) && + Aig_ObjType(pEntry) == Aig_ObjType(pGhost) ) + return pEntry; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Checks if node with the given attributes is in the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 ) +{ + Aig_Obj_t * pGhost; + // consider simple cases + if ( pFanin0 == pFanin1 ) + return pFanin0; + if ( pFanin0 == Aig_Not(pFanin1) ) + return Aig_ManConst0(p); + if ( Aig_Regular(pFanin0) == Aig_ManConst1(p) ) + return pFanin0 == Aig_ManConst1(p) ? pFanin1 : Aig_ManConst0(p); + if ( Aig_Regular(pFanin1) == Aig_ManConst1(p) ) + return pFanin1 == Aig_ManConst1(p) ? pFanin0 : Aig_ManConst0(p); + pGhost = Aig_ObjCreateGhost( p, pFanin0, pFanin1, AIG_OBJ_AND ); + return Aig_TableLookup( p, pGhost ); +} + +/**Function************************************************************* + + Synopsis [Adds the new node to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t ** ppPlace; + assert( !Aig_IsComplement(pObj) ); + assert( Aig_TableLookup(p, pObj) == NULL ); + if ( (pObj->Id & 0xFF) == 0 && 2 * p->nTableSize < Aig_ManNodeNum(p) ) + Aig_TableResize( p ); + ppPlace = Aig_TableFind( p, pObj ); + assert( *ppPlace == NULL ); + *ppPlace = pObj; +} + +/**Function************************************************************* + + Synopsis [Deletes the node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t ** ppPlace; + assert( !Aig_IsComplement(pObj) ); + ppPlace = Aig_TableFind( p, pObj ); + assert( *ppPlace == pObj ); // node should be in the table + // remove the node + *ppPlace = pObj->pNext; + pObj->pNext = NULL; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_TableCountEntries( Aig_Man_t * p ) +{ + Aig_Obj_t * pEntry; + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) + Counter++; + return Counter; +} + +/**Function******************************************************************** + + Synopsis [Profiles the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Aig_TableProfile( Aig_Man_t * p ) +{ + Aig_Obj_t * pEntry; + int i, Counter; + for ( i = 0; i < p->nTableSize; i++ ) + { + Counter = 0; + for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) + Counter++; + if ( Counter ) + printf( "%d ", Counter ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigTime.c b/abc70930/src/aig/aig/aigTime.c new file mode 100644 index 00000000..42f5f575 --- /dev/null +++ b/abc70930/src/aig/aig/aigTime.c @@ -0,0 +1,299 @@ +/**CFile**************************************************************** + + FileName [aigTime.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Representation of timing information.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigTime.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Aig_TBox_t_ Aig_TBox_t; +typedef struct Aig_TObj_t_ Aig_TObj_t; + +// timing manager +struct Aig_TMan_t_ +{ + Vec_Ptr_t * vBoxes; // the timing boxes + Aig_MmFlex_t * pMemObj; // memory manager for boxes + int nTravIds; // traversal ID of the manager + int nPis; // the number of PIs + int nPos; // the number of POs + Aig_TObj_t * pPis; // timing info for the PIs + Aig_TObj_t * pPos; // timing info for the POs +}; + +// timing box +struct Aig_TBox_t_ +{ + int iBox; // the unique ID of this box + int TravId; // traversal ID of this box + int nInputs; // the number of box inputs + int nOutputs; // the number of box outputs + int Inouts[0]; // the int numbers of PIs and POs +}; + +// timing object +struct Aig_TObj_t_ +{ + int iObj2Box; // mapping of the object into its box + float timeOffset; // the static timing of the node + float timeActual; // the actual timing of the node +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the network manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_TMan_t * Aig_TManStart( int nPis, int nPos ) +{ + Aig_TMan_t * p; + int i; + p = ALLOC( Aig_TMan_t, 1 ); + memset( p, 0, sizeof(Aig_TMan_t) ); + p->pMemObj = Aig_MmFlexStart(); + p->vBoxes = Vec_PtrAlloc( 100 ); + Vec_PtrPush( p->vBoxes, NULL ); + p->nPis = nPis; + p->nPos = nPos; + p->pPis = ALLOC( Aig_TObj_t, nPis ); + memset( p->pPis, 0, sizeof(Aig_TObj_t) * nPis ); + p->pPos = ALLOC( Aig_TObj_t, nPos ); + memset( p->pPos, 0, sizeof(Aig_TObj_t) * nPos ); + for ( i = 0; i < nPis; i++ ) + p->pPis[i].iObj2Box = -1; + for ( i = 0; i < nPos; i++ ) + p->pPos[i].iObj2Box = -1; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the network manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TManStop( Aig_TMan_t * p ) +{ + Vec_PtrFree( p->vBoxes ); + Aig_MmFlexStop( p->pMemObj, 0 ); + free( p->pPis ); + free( p->pPos ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Creates the new timing box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TManCreateBox( Aig_TMan_t * p, int * pPis, int nPis, int * pPos, int nPos, float * pPiTimes, float * pPoTimes ) +{ + Aig_TBox_t * pBox; + int i; + pBox = (Aig_TBox_t *)Aig_MmFlexEntryFetch( p->pMemObj, sizeof(Aig_TBox_t) + sizeof(int) * (nPis+nPos) ); + memset( pBox, 0, sizeof(Aig_TBox_t) ); + pBox->iBox = Vec_PtrSize( p->vBoxes ); + Vec_PtrPush( p->vBoxes, pBox ); + pBox->nInputs = nPis; + pBox->nOutputs = nPos; + for ( i = 0; i < nPis; i++ ) + { + assert( pPis[i] < p->nPis ); + pBox->Inouts[i] = pPis[i]; + Aig_TManSetPiArrival( p, pPis[i], pPiTimes[i] ); + p->pPis[pPis[i]].iObj2Box = pBox->iBox; + } + for ( i = 0; i < nPos; i++ ) + { + assert( pPos[i] < p->nPos ); + pBox->Inouts[nPis+i] = pPos[i]; + Aig_TManSetPoRequired( p, pPos[i], pPoTimes[i] ); + p->pPos[pPos[i]].iObj2Box = pBox->iBox; + } +} + +/**Function************************************************************* + + Synopsis [Creates the new timing box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TManSetPiDelay( Aig_TMan_t * p, int iPi, float Delay ) +{ + assert( iPi < p->nPis ); + p->pPis[iPi].timeActual = Delay; +} + +/**Function************************************************************* + + Synopsis [Creates the new timing box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TManSetPoDelay( Aig_TMan_t * p, int iPo, float Delay ) +{ + assert( iPo < p->nPos ); + p->pPos[iPo].timeActual = Delay; +} + +/**Function************************************************************* + + Synopsis [Creates the new timing box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TManSetPiArrival( Aig_TMan_t * p, int iPi, float Delay ) +{ + assert( iPi < p->nPis ); + p->pPis[iPi].timeOffset = Delay; +} + +/**Function************************************************************* + + Synopsis [Creates the new timing box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TManSetPoRequired( Aig_TMan_t * p, int iPo, float Delay ) +{ + assert( iPo < p->nPos ); + p->pPos[iPo].timeOffset = Delay; +} + +/**Function************************************************************* + + Synopsis [Increments the trav ID of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TManIncrementTravId( Aig_TMan_t * p ) +{ + p->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Returns PI arrival time.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Aig_TManGetPiArrival( Aig_TMan_t * p, int iPi ) +{ + Aig_TBox_t * pBox; + Aig_TObj_t * pObj; + float DelayMax; + int i; + assert( iPi < p->nPis ); + if ( p->pPis[iPi].iObj2Box < 0 ) + return p->pPis[iPi].timeOffset; + pBox = Vec_PtrEntry( p->vBoxes, p->pPis[iPi].iObj2Box ); + // check if box timing is updated + if ( pBox->TravId == p->nTravIds ) + return p->pPis[iPi].timeOffset; + pBox->TravId = p->nTravIds; + // update box timing + DelayMax = -1.0e+20F; + for ( i = 0; i < pBox->nOutputs; i++ ) + { + pObj = p->pPos + pBox->Inouts[pBox->nInputs+i]; + DelayMax = AIG_MAX( DelayMax, pObj->timeActual + pObj->timeOffset ); + } + for ( i = 0; i < pBox->nInputs; i++ ) + { + pObj = p->pPis + pBox->Inouts[i]; + pObj->timeActual = DelayMax + pObj->timeOffset; + } + return p->pPis[iPi].timeActual; +} + +/**Function************************************************************* + + Synopsis [Returns PO required time.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Aig_TManGetPoRequired( Aig_TMan_t * p, int iPo ) +{ + return 0.0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigTiming.c b/abc70930/src/aig/aig/aigTiming.c new file mode 100644 index 00000000..de8fdc7c --- /dev/null +++ b/abc70930/src/aig/aig/aigTiming.c @@ -0,0 +1,351 @@ +/**CFile**************************************************************** + + FileName [aigTiming.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Incremental updating of direct/reverse AIG levels.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigTiming.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the reverse level of the node.] + + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_ObjReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + assert( p->vLevelR ); + Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 ); + return Vec_IntEntry(p->vLevelR, pObj->Id); +} + +/**Function************************************************************* + + Synopsis [Sets the reverse level of the node.] + + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Aig_ObjSetReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj, int LevelR ) +{ + assert( p->vLevelR ); + Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 ); + Vec_IntWriteEntry( p->vLevelR, pObj->Id, LevelR ); +} + +/**Function************************************************************* + + Synopsis [Resets reverse level of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_ObjSetReverseLevel( p, pObj, 0 ); +} + +/**Function************************************************************* + + Synopsis [Returns required level of the node.] + + Description [Converts the reverse levels of the node into its required + level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + assert( p->vLevelR ); + return p->nLevelMax + 1 - Aig_ObjReverseLevel(p, pObj); +} + +/**Function************************************************************* + + Synopsis [Computes the reverse level of the node using its fanout levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjReverseLevelNew( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + int i, iFanout = -1, LevelCur, Level = 0; + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + { + LevelCur = Aig_ObjReverseLevel( p, pFanout ); + Level = AIG_MAX( Level, LevelCur ); + } + return Level + 1; +} + +/**Function************************************************************* + + Synopsis [Prepares for the computation of required levels.] + + Description [This procedure should be called before the required times + are used. It starts internal data structures, which records the level + from the COs of the network nodes in reverse topologogical order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + assert( p->pFanData != NULL ); + assert( p->vLevelR == NULL ); + // remember the maximum number of direct levels + p->nLevelMax = Aig_ManLevels(p) + nMaxLevelIncrease; + // start the reverse levels + p->vLevelR = Vec_IntAlloc( 0 ); + Vec_IntFill( p->vLevelR, Aig_ManObjNumMax(p), 0 ); + // compute levels in reverse topological order + vNodes = Aig_ManDfsReverse( p ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + assert( pObj->fMarkA == 0 ); + Aig_ObjSetReverseLevel( p, pObj, Aig_ObjReverseLevelNew(p, pObj) ); + } + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Cleans the data structures used to compute required levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManStopReverseLevels( Aig_Man_t * p ) +{ + assert( p->vLevelR != NULL ); + Vec_IntFree( p->vLevelR ); + p->vLevelR = NULL; + p->nLevelMax = 0; + +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ) +{ + Aig_Obj_t * pFanout, * pTemp; + int iFanout = -1, LevelOld, Lev, k, m; + assert( p->pFanData != NULL ); + assert( Aig_ObjIsNode(pObjNew) ); + // allocate level if needed + if ( p->vLevels == NULL ) + p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 ); + // check if level has changed + LevelOld = Aig_ObjLevel(pObjNew); + if ( LevelOld == Aig_ObjLevelNew(pObjNew) ) + return; + // start the data structure for level update + // we cannot fail to visit a node when using this structure because the + // nodes are stored by their _old_ levels, which are assumed to be correct + Vec_VecClear( p->vLevels ); + Vec_VecPush( p->vLevels, LevelOld, pObjNew ); + pObjNew->fMarkA = 1; + // recursively update level + Vec_VecForEachEntryStart( p->vLevels, pTemp, Lev, k, LevelOld ) + { + pTemp->fMarkA = 0; + assert( Aig_ObjLevel(pTemp) == Lev ); + pTemp->Level = Aig_ObjLevelNew(pTemp); + // if the level did not change, no need to check the fanout levels + if ( Aig_ObjLevel(pTemp) == Lev ) + continue; + // schedule fanout for level update + Aig_ObjForEachFanout( p, pTemp, pFanout, iFanout, m ) + { + if ( Aig_ObjIsNode(pFanout) && !pFanout->fMarkA ) + { + assert( Aig_ObjLevel(pFanout) >= Lev ); + Vec_VecPush( p->vLevels, Aig_ObjLevel(pFanout), pFanout ); + pFanout->fMarkA = 1; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ) +{ + Aig_Obj_t * pFanin, * pTemp; + int LevelOld, LevFanin, Lev, k; + assert( p->vLevelR != NULL ); + assert( Aig_ObjIsNode(pObjNew) ); + // allocate level if needed + if ( p->vLevels == NULL ) + p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 ); + // check if level has changed + LevelOld = Aig_ObjReverseLevel(p, pObjNew); + if ( LevelOld == Aig_ObjReverseLevelNew(p, pObjNew) ) + return; + // start the data structure for level update + // we cannot fail to visit a node when using this structure because the + // nodes are stored by their _old_ levels, which are assumed to be correct + Vec_VecClear( p->vLevels ); + Vec_VecPush( p->vLevels, LevelOld, pObjNew ); + pObjNew->fMarkA = 1; + // recursively update level + Vec_VecForEachEntryStart( p->vLevels, pTemp, Lev, k, LevelOld ) + { + pTemp->fMarkA = 0; + LevelOld = Aig_ObjReverseLevel(p, pTemp); + assert( LevelOld == Lev ); + Aig_ObjSetReverseLevel( p, pTemp, Aig_ObjReverseLevelNew(p, pTemp) ); + // if the level did not change, to need to check the fanout levels + if ( Aig_ObjReverseLevel(p, pTemp) == Lev ) + continue; + // schedule fanins for level update + pFanin = Aig_ObjFanin0(pTemp); + if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA ) + { + LevFanin = Aig_ObjReverseLevel( p, pFanin ); + assert( LevFanin >= Lev ); + Vec_VecPush( p->vLevels, LevFanin, pFanin ); + pFanin->fMarkA = 1; + } + pFanin = Aig_ObjFanin1(pTemp); + if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA ) + { + LevFanin = Aig_ObjReverseLevel( p, pFanin ); + assert( LevFanin >= Lev ); + Vec_VecPush( p->vLevels, LevFanin, pFanin ); + pFanin->fMarkA = 1; + } + } +} + +/**Function************************************************************* + + Synopsis [Verifies direct level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManVerifyLevel( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + assert( p->pFanData ); + Aig_ManForEachNode( p, pObj, i ) + if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) ) + { + printf( "Level of node %6d should be %4d instead of %4d.\n", + pObj->Id, Aig_ObjLevelNew(pObj), Aig_ObjLevel(pObj) ); + Counter++; + } + if ( Counter ) + printf( "Levels of %d nodes are incorrect.\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [Verifies reverse level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManVerifyReverseLevel( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + assert( p->vLevelR ); + Aig_ManForEachNode( p, pObj, i ) + if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) ) + { + printf( "Reverse level of node %6d should be %4d instead of %4d.\n", + pObj->Id, Aig_ObjReverseLevelNew(p, pObj), Aig_ObjReverseLevel(p, pObj) ); + Counter++; + } + if ( Counter ) + printf( "Reverse levels of %d nodes are incorrect.\n", Counter ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigTruth.c b/abc70930/src/aig/aig/aigTruth.c new file mode 100644 index 00000000..a92f9e1d --- /dev/null +++ b/abc70930/src/aig/aig/aigTruth.c @@ -0,0 +1,98 @@ +/**CFile**************************************************************** + + FileName [aigTruth.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Computes truth table for the cut.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigTruth.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Aig_ManCutTruthOne( Aig_Obj_t * pNode, unsigned * pTruth, int nWords ) +{ + unsigned * pTruth0, * pTruth1; + int i; + pTruth0 = Aig_ObjFanin0(pNode)->pData; + pTruth1 = Aig_ObjFanin1(pNode)->pData; + if ( Aig_ObjIsExor(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] ^ pTruth1[i]; + else if ( !Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & pTruth1[i]; + else if ( !Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & ~pTruth1[i]; + else if ( Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & pTruth1[i]; + else // if ( Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [The returned pointer should be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore ) +{ + Aig_Obj_t * pObj; + int i, nWords; + assert( Vec_PtrSize(vLeaves) <= Vec_PtrSize(vTruthElem) ); + assert( Vec_PtrSize(vNodes) <= Vec_PtrSize(vTruthStore) ); + assert( Vec_PtrSize(vNodes) == 0 || pRoot == Vec_PtrEntryLast(vNodes) ); + // assign elementary truth tables + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->pData = Vec_PtrEntry( vTruthElem, i ); + // compute truths for other nodes + nWords = Aig_TruthWordNum( Vec_PtrSize(vLeaves) ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pData = Aig_ManCutTruthOne( pObj, Vec_PtrEntry(vTruthStore, i), nWords ); + return pRoot->pData; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigTsim.c b/abc70930/src/aig/aig/aigTsim.c new file mode 100644 index 00000000..a8a3dda8 --- /dev/null +++ b/abc70930/src/aig/aig/aigTsim.c @@ -0,0 +1,436 @@ +/**CFile**************************************************************** + + FileName [aigTsim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Ternary simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigTsim.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define TSI_MAX_ROUNDS 1000 + +#define AIG_XVS0 1 +#define AIG_XVS1 2 +#define AIG_XVSX 3 + +static inline void Aig_ObjSetXsim( Aig_Obj_t * pObj, int Value ) { pObj->nCuts = Value; } +static inline int Aig_ObjGetXsim( Aig_Obj_t * pObj ) { return pObj->nCuts; } +static inline int Aig_XsimInv( int Value ) +{ + if ( Value == AIG_XVS0 ) + return AIG_XVS1; + if ( Value == AIG_XVS1 ) + return AIG_XVS0; + assert( Value == AIG_XVSX ); + return AIG_XVSX; +} +static inline int Aig_XsimAnd( int Value0, int Value1 ) +{ + if ( Value0 == AIG_XVS0 || Value1 == AIG_XVS0 ) + return AIG_XVS0; + if ( Value0 == AIG_XVSX || Value1 == AIG_XVSX ) + return AIG_XVSX; + assert( Value0 == AIG_XVS1 && Value1 == AIG_XVS1 ); + return AIG_XVS1; +} +static inline int Aig_XsimRand2() +{ + return (rand() & 1) ? AIG_XVS1 : AIG_XVS0; +} +static inline int Aig_XsimRand3() +{ + int RetValue; + do { + RetValue = rand() & 3; + } while ( RetValue == 0 ); + return RetValue; +} +static inline int Aig_ObjGetXsimFanin0( Aig_Obj_t * pObj ) +{ + int RetValue; + RetValue = Aig_ObjGetXsim(Aig_ObjFanin0(pObj)); + return Aig_ObjFaninC0(pObj)? Aig_XsimInv(RetValue) : RetValue; +} +static inline int Aig_ObjGetXsimFanin1( Aig_Obj_t * pObj ) +{ + int RetValue; + RetValue = Aig_ObjGetXsim(Aig_ObjFanin1(pObj)); + return Aig_ObjFaninC1(pObj)? Aig_XsimInv(RetValue) : RetValue; +} +static inline void Aig_XsimPrint( FILE * pFile, int Value ) +{ + if ( Value == AIG_XVS0 ) + { + fprintf( pFile, "0" ); + return; + } + if ( Value == AIG_XVS1 ) + { + fprintf( pFile, "1" ); + return; + } + assert( Value == AIG_XVSX ); + fprintf( pFile, "x" ); +} + +// simulation manager +typedef struct Aig_Tsi_t_ Aig_Tsi_t; +struct Aig_Tsi_t_ +{ + Aig_Man_t * pAig; // the original AIG manager + // ternary state representation + int nWords; // the number of words in the states + Vec_Ptr_t * vStates; // the collection of ternary states + Aig_MmFixed_t * pMem; // memory for ternary states + // hash table for terminary states + unsigned ** pBins; + int nBins; +}; + +static inline unsigned * Aig_TsiNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } +static inline void Aig_TsiSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Tsi_t * Aig_TsiStart( Aig_Man_t * pAig ) +{ + Aig_Tsi_t * p; + p = (Aig_Tsi_t *)malloc( sizeof(Aig_Tsi_t) ); + memset( p, 0, sizeof(Aig_Tsi_t) ); + p->pAig = pAig; + p->nWords = Aig_BitWordNum( 2*Aig_ManRegNum(pAig) ); + p->vStates = Vec_PtrAlloc( 1000 ); + p->pMem = Aig_MmFixedStart( sizeof(unsigned) * p->nWords + sizeof(unsigned *), 10000 ); + p->nBins = Aig_PrimeCudd(TSI_MAX_ROUNDS/2); + p->pBins = ALLOC( unsigned *, p->nBins ); + memset( p->pBins, 0, sizeof(unsigned *) * p->nBins ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TsiStop( Aig_Tsi_t * p ) +{ + Aig_MmFixedStop( p->pMem, 0 ); + Vec_PtrFree( p->vStates ); + free( p->pBins ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_TsiStateHash( unsigned * pState, int nWords, int nTableSize ) +{ + static int s_FPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + unsigned uHash; + int i; + uHash = 0; + for ( i = 0; i < nWords; i++ ) + uHash ^= pState[i] * s_FPrimes[i & 0x7F]; + return uHash % nTableSize; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_TsiStateLookup( Aig_Tsi_t * p, unsigned * pState, int nWords ) +{ + unsigned * pEntry; + int Hash; + Hash = Aig_TsiStateHash( pState, nWords, p->nBins ); + for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Aig_TsiNext(pEntry, nWords) ) + if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TsiStateInsert( Aig_Tsi_t * p, unsigned * pState, int nWords ) +{ + int Hash = Aig_TsiStateHash( pState, nWords, p->nBins ); + assert( !Aig_TsiStateLookup( p, pState, nWords ) ); + Aig_TsiSetNext( pState, nWords, p->pBins[Hash] ); + p->pBins[Hash] = pState; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Aig_TsiStateNew( Aig_Tsi_t * p ) +{ + unsigned * pState; + pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMem ); + memset( pState, 0, sizeof(unsigned) * p->nWords ); + Vec_PtrPush( p->vStates, pState ); + return pState; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TsiStatePrint( Aig_Tsi_t * p, unsigned * pState ) +{ + int i, Value, nZeros = 0, nOnes = 0, nDcs = 0; + for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) + { + Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); + if ( Value == 1 ) + printf( "0" ), nZeros++; + else if ( Value == 2 ) + printf( "1" ), nOnes++; + else if ( Value == 3 ) + printf( "x" ), nDcs++; + else + assert( 0 ); + } + printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs ); +} + + +/**Function************************************************************* + + Synopsis [Cycles the circuit to create a new initial state.] + + Description [Simulates the circuit with random input for the given + number of timeframes to get a better initial state.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManTernarySimulate( Aig_Man_t * p, int fVerbose ) +{ + Aig_Tsi_t * pTsi; + Vec_Ptr_t * vMap; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + unsigned * pState, * pPrev; + int i, k, f, fConstants, Value, nCounter; + // allocate the simulation manager + pTsi = Aig_TsiStart( p ); + // initialize the values + Aig_ObjSetXsim( Aig_ManConst1(p), AIG_XVS1 ); + Aig_ManForEachPiSeq( p, pObj, i ) + Aig_ObjSetXsim( pObj, AIG_XVSX ); + Aig_ManForEachLoSeq( p, pObj, i ) + Aig_ObjSetXsim( pObj, AIG_XVS0 ); + // simulate for the given number of timeframes + for ( f = 0; f < TSI_MAX_ROUNDS; f++ ) + { + // collect this state + pState = Aig_TsiStateNew( pTsi ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + Value = Aig_ObjGetXsim(pObjLo); + if ( Value & 1 ) + Aig_InfoSetBit( pState, 2 * i ); + if ( Value & 2 ) + Aig_InfoSetBit( pState, 2 * i + 1 ); + } +// Aig_TsiStatePrint( pTsi, pState ); + // check if this state exists + if ( Aig_TsiStateLookup( pTsi, pState, pTsi->nWords ) ) + break; + // insert this state + Aig_TsiStateInsert( pTsi, pState, pTsi->nWords ); + // simulate internal nodes + Aig_ManForEachNode( p, pObj, i ) + Aig_ObjSetXsim( pObj, Aig_XsimAnd(Aig_ObjGetXsimFanin0(pObj), Aig_ObjGetXsimFanin1(pObj)) ); + // transfer the latch values + Aig_ManForEachLiSeq( p, pObj, i ) + Aig_ObjSetXsim( pObj, Aig_ObjGetXsimFanin0(pObj) ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + Aig_ObjSetXsim( pObjLo, Aig_ObjGetXsim(pObjLi) ); + } + if ( f == TSI_MAX_ROUNDS ) + { + printf( "Aig_ManTernarySimulate(): Did not reach a fixed point after %d iterations (not a bug).\n", TSI_MAX_ROUNDS ); + Aig_TsiStop( pTsi ); + return NULL; + } + // OR all the states + pState = Vec_PtrEntry( pTsi->vStates, 0 ); + Vec_PtrForEachEntry( pTsi->vStates, pPrev, i ) + { + for ( k = 0; k < pTsi->nWords; k++ ) + pState[k] |= pPrev[k]; + } + // check if there are constants + fConstants = 0; + if ( 2*Aig_ManRegNum(p) == 32*pTsi->nWords ) + { + for ( i = 0; i < pTsi->nWords; i++ ) + if ( pState[i] != ~0 ) + fConstants = 1; + } + else + { + for ( i = 0; i < pTsi->nWords - 1; i++ ) + if ( pState[i] != ~0 ) + fConstants = 1; + if ( pState[i] != Aig_InfoMask( 2*Aig_ManRegNum(p) - 32*(pTsi->nWords-1) ) ) + fConstants = 1; + } + if ( fConstants == 0 ) + { + Aig_TsiStop( pTsi ); + return NULL; + } + + // start mapping by adding the true PIs + vMap = Vec_PtrAlloc( Aig_ManPiNum(p) ); + Aig_ManForEachPiSeq( p, pObj, i ) + Vec_PtrPush( vMap, pObj ); + // find constant registers + nCounter = 0; + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); + nCounter += (Value == 1 || Value == 2); + if ( Value == 1 ) + Vec_PtrPush( vMap, Aig_ManConst0(p) ); + else if ( Value == 2 ) + Vec_PtrPush( vMap, Aig_ManConst1(p) ); + else if ( Value == 3 ) + Vec_PtrPush( vMap, pObjLo ); + else + assert( 0 ); +// Aig_XsimPrint( stdout, Value ); + } +// printf( "\n" ); + Aig_TsiStop( pTsi ); + if ( fVerbose ) + printf( "Detected %d constants after %d iterations of ternary simulation.\n", nCounter, f ); + return vMap; +} + +/**Function************************************************************* + + Synopsis [Reduces the circuit using ternary simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManConstReduce( Aig_Man_t * p, int fVerbose ) +{ + Aig_Man_t * pTemp; + Vec_Ptr_t * vMap; + while ( (vMap = Aig_ManTernarySimulate( p, fVerbose )) ) + { + if ( fVerbose ) + printf( "RBeg = %5d. NBeg = %6d. ", Aig_ManRegNum(p), Aig_ManNodeNum(p) ); + p = Aig_ManRemap( pTemp = p, vMap ); + Aig_ManStop( pTemp ); + Vec_PtrFree( vMap ); + Aig_ManSeqCleanup( p ); + if ( fVerbose ) + printf( "REnd = %5d. NEnd = %6d. \n", Aig_ManRegNum(p), Aig_ManNodeNum(p) ); + } + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigUtil.c b/abc70930/src/aig/aig/aigUtil.c new file mode 100644 index 00000000..b70d11c7 --- /dev/null +++ b/abc70930/src/aig/aig/aigUtil.c @@ -0,0 +1,851 @@ +/**CFile**************************************************************** + + FileName [aigUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Various procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function******************************************************************** + + Synopsis [Returns the next prime >= p.] + + Description [Copied from CUDD, for stand-aloneness.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +unsigned int Aig_PrimeCudd( unsigned int p ) +{ + int i,pn; + + p--; + do { + p++; + if (p&1) { + pn = 1; + i = 3; + while ((unsigned) (i * i) <= p) { + if (p % i == 0) { + pn = 0; + break; + } + i += 2; + } + } else { + pn = 0; + } + } while (!pn); + return(p); + +} /* end of Cudd_Prime */ + +/**Function************************************************************* + + Synopsis [Increments the current traversal ID of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManIncrementTravId( Aig_Man_t * p ) +{ + if ( p->nTravIds >= (1<<30)-1 ) + Aig_ManCleanData( p ); + p->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManLevels( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, LevelMax = 0; + Aig_ManForEachPo( p, pObj, i ) + LevelMax = AIG_MAX( LevelMax, (int)Aig_ObjFanin0(pObj)->Level ); + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Reset reference counters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManResetRefs( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + pObj->nRefs = 0; + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjFanin0(pObj) ) + Aig_ObjFanin0(pObj)->nRefs++; + if ( Aig_ObjFanin1(pObj) ) + Aig_ObjFanin1(pObj)->nRefs++; + } +} + +/**Function************************************************************* + + Synopsis [Cleans MarkB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCleanMarkA( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + pObj->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans MarkB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCleanMarkB( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + pObj->fMarkB = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans the data pointers for the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCleanData( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Recursively cleans the data pointers in the cone of the node.] + + Description [Applicable to small AIGs only because no caching is performed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCleanData_rec( Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsPo(pObj) ); + if ( Aig_ObjIsAnd(pObj) ) + { + Aig_ObjCleanData_rec( Aig_ObjFanin0(pObj) ); + Aig_ObjCleanData_rec( Aig_ObjFanin1(pObj) ); + } + pObj->pData = NULL; +} + + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCollectMulti_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + if ( pRoot != pObj && (Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) || Aig_ObjType(pRoot) != Aig_ObjType(pObj)) ) + { + Vec_PtrPushUnique(vSuper, pObj); + return; + } + Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild0(pObj), vSuper ); + Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild1(pObj), vSuper ); +} + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCollectMulti( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper ) +{ + assert( !Aig_IsComplement(pRoot) ); + Vec_PtrClear( vSuper ); + Aig_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjIsMuxType( Aig_Obj_t * pNode ) +{ + Aig_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Aig_IsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Aig_ObjIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Aig_ObjFaninC0(pNode) || !Aig_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Aig_ObjFanin0(pNode); + pNode1 = Aig_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( !Aig_ObjIsAnd(pNode0) || !Aig_ObjIsAnd(pNode1) ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren + return (Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1))) || + (Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1))) || + (Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1))) || + (Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1))); +} + + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are inputs of the EXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) +{ + Aig_Obj_t * p0, * p1; + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) ) + return 0; + if ( Aig_ObjIsExor(pObj) ) + { + *ppFan0 = Aig_ObjChild0(pObj); + *ppFan1 = Aig_ObjChild1(pObj); + return 1; + } + assert( Aig_ObjIsAnd(pObj) ); + p0 = Aig_ObjChild0(pObj); + p1 = Aig_ObjChild1(pObj); + if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) + return 0; + p0 = Aig_Regular(p0); + p1 = Aig_Regular(p1); + if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) + return 0; + if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) + return 0; + if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Aig_ObjChild0(p0); + *ppFan1 = Aig_ObjChild1(p0); + return 1; +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pNode, Aig_Obj_t ** ppNodeT, Aig_Obj_t ** ppNodeE ) +{ + Aig_Obj_t * pNode0, * pNode1; + assert( !Aig_IsComplement(pNode) ); + assert( Aig_ObjIsMuxType(pNode) ); + // get children + pNode0 = Aig_ObjFanin0(pNode); + pNode1 = Aig_ObjFanin1(pNode); + + // find the control variable + if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Aig_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); + return Aig_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); + return Aig_ObjChild1(pNode0);//pNode1->p2; + } + } + else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Aig_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); + return Aig_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); + return Aig_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Aig_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); + return Aig_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); + return Aig_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Aig_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); + return Aig_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); + return Aig_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ObjReal_rec( Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjNew, * pObjR = Aig_Regular(pObj); + if ( !Aig_ObjIsBuf(pObjR) ) + return pObj; + pObjNew = Aig_ObjReal_rec( Aig_ObjChild0(pObjR) ); + return Aig_NotCond( pObjNew, Aig_IsComplement(pObj) ); +} + + +/**Function************************************************************* + + Synopsis [Prints Eqn formula for the AIG rooted at this node.] + + Description [The formula is in terms of PIs, which should have + their names assigned in pObj->pData fields.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) +{ + Vec_Ptr_t * vSuper; + Aig_Obj_t * pFanin; + int fCompl, i; + // store the complemented attribute + fCompl = Aig_IsComplement(pObj); + pObj = Aig_Regular(pObj); + // constant case + if ( Aig_ObjIsConst1(pObj) ) + { + fprintf( pFile, "%d", !fCompl ); + return; + } + // PI case + if ( Aig_ObjIsPi(pObj) ) + { + fprintf( pFile, "%s%s", fCompl? "!" : "", (char*)pObj->pData ); + return; + } + // AND case + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry(vLevels, Level); + Aig_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + Aig_ObjPrintEqn( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " %s ", fCompl? "+" : "*" ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; +} + +/**Function************************************************************* + + Synopsis [Prints Verilog formula for the AIG rooted at this node.] + + Description [The formula is in terms of PIs, which should have + their names assigned in pObj->pData fields.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) +{ + Vec_Ptr_t * vSuper; + Aig_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC; + int fCompl, i; + // store the complemented attribute + fCompl = Aig_IsComplement(pObj); + pObj = Aig_Regular(pObj); + // constant case + if ( Aig_ObjIsConst1(pObj) ) + { + fprintf( pFile, "1\'b%d", !fCompl ); + return; + } + // PI case + if ( Aig_ObjIsPi(pObj) ) + { + fprintf( pFile, "%s%s", fCompl? "~" : "", (char*)pObj->pData ); + return; + } + // EXOR case + if ( Aig_ObjIsExor(pObj) ) + { + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry( vLevels, Level ); + Aig_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " ^ " ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; + } + // MUX case + if ( Aig_ObjIsMuxType(pObj) ) + { + if ( Aig_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) + { + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); + fprintf( pFile, " ^ " ); + Aig_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 ); + fprintf( pFile, "%s", (Level==0? "" : ")") ); + } + else + { + pFaninC = Aig_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Aig_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 ); + fprintf( pFile, " ? " ); + Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin1, fCompl), vLevels, Level+1 ); + fprintf( pFile, " : " ); + Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); + fprintf( pFile, "%s", (Level==0? "" : ")") ); + } + return; + } + // AND case + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry(vLevels, Level); + Aig_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " %s ", fCompl? "|" : "&" ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; +} + + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ) +{ + assert( !Aig_IsComplement(pObj) ); + printf( "Node %p : ", pObj ); + if ( Aig_ObjIsConst1(pObj) ) + printf( "constant 1" ); + else if ( Aig_ObjIsPi(pObj) ) + printf( "PI" ); + else + printf( "AND( %p%s, %p%s )", + Aig_ObjFanin0(pObj), (Aig_ObjFaninC0(pObj)? "\'" : " "), + Aig_ObjFanin1(pObj), (Aig_ObjFaninC1(pObj)? "\'" : " ") ); + printf( " (refs = %3d)", Aig_ObjRefs(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + printf( "PIs: " ); + Aig_ManForEachPi( p, pObj, i ) + printf( " %p", pObj ); + printf( "\n" ); + vNodes = Aig_ManDfs( p ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Write speculative miter for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDump( Aig_Man_t * p ) +{ + static int Counter = 0; + char FileName[20]; + // dump the logic into a file + sprintf( FileName, "aigbug\\%03d.blif", ++Counter ); + Aig_ManDumpBlif( p, FileName ); + printf( "Intermediate AIG with %d nodes was written into file \"%s\".\n", Aig_ManNodeNum(p), FileName ); +} + +/**Function************************************************************* + + Synopsis [Writes the AIG into the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pConst1 = NULL; + int i, nDigits, Counter = 0; + if ( Aig_ManPoNum(p) == 0 ) + { + printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); + return; + } + // collect nodes in the DFS order + vNodes = Aig_ManDfs( p ); + // assign IDs to objects + Aig_ManConst1(p)->iData = Counter++; + Aig_ManForEachPi( p, pObj, i ) + pObj->iData = Counter++; + Aig_ManForEachPo( p, pObj, i ) + pObj->iData = Counter++; + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->iData = Counter++; + nDigits = Aig_Base10Log( Counter ); + // write the file + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# BLIF file written by procedure Aig_ManDumpBlif()\n" ); +// fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); + fprintf( pFile, ".model test\n" ); + // write PIs + fprintf( pFile, ".inputs" ); + Aig_ManForEachPiSeq( p, pObj, i ) + fprintf( pFile, " n%0*d", nDigits, pObj->iData ); + fprintf( pFile, "\n" ); + // write POs + fprintf( pFile, ".outputs" ); + Aig_ManForEachPoSeq( p, pObj, i ) + fprintf( pFile, " n%0*d", nDigits, pObj->iData ); + fprintf( pFile, "\n" ); + // write latches + if ( Aig_ManRegNum(p) ) + { + fprintf( pFile, "\n" ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + fprintf( pFile, ".latch n%0*d n%0*d 0\n", nDigits, pObjLi->iData, nDigits, pObjLo->iData ); + fprintf( pFile, "\n" ); + } + // write nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + fprintf( pFile, ".names n%0*d n%0*d n%0*d\n", + nDigits, Aig_ObjFanin0(pObj)->iData, + nDigits, Aig_ObjFanin1(pObj)->iData, + nDigits, pObj->iData ); + fprintf( pFile, "%d%d 1\n", !Aig_ObjFaninC0(pObj), !Aig_ObjFaninC1(pObj) ); + } + // write POs + Aig_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, ".names n%0*d n%0*d\n", + nDigits, Aig_ObjFanin0(pObj)->iData, + nDigits, pObj->iData ); + fprintf( pFile, "%d 1\n", !Aig_ObjFaninC0(pObj) ); + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + pConst1 = Aig_ManConst1(p); + } + if ( pConst1 ) + fprintf( pFile, ".names n%0*d\n 1\n", nDigits, pConst1->iData ); + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Writes the AIG into the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDumpVerilog( Aig_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pConst1 = NULL; + int i, nDigits, Counter = 0; + if ( Aig_ManPoNum(p) == 0 ) + { + printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); + return; + } + // collect nodes in the DFS order + vNodes = Aig_ManDfs( p ); + // assign IDs to objects + Aig_ManConst1(p)->iData = Counter++; + Aig_ManForEachPi( p, pObj, i ) + pObj->iData = Counter++; + Aig_ManForEachPo( p, pObj, i ) + pObj->iData = Counter++; + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->iData = Counter++; + nDigits = Aig_Base10Log( Counter ); + // write the file + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "// Verilog file written by procedure Aig_ManDumpVerilog()\n" ); +// fprintf( pFile, "// http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); + if ( Aig_ManRegNum(p) ) + fprintf( pFile, "module %s ( clock", p->pName? p->pName: "test" ); + else + fprintf( pFile, "module %s (", p->pName? p->pName: "test" ); + Aig_ManForEachPiSeq( p, pObj, i ) + fprintf( pFile, "%s n%0*d", ((Aig_ManRegNum(p) || i)? ",":""), nDigits, pObj->iData ); + Aig_ManForEachPoSeq( p, pObj, i ) + fprintf( pFile, ", n%0*d", nDigits, pObj->iData ); + fprintf( pFile, " );\n" ); + + // write PIs + if ( Aig_ManRegNum(p) ) + fprintf( pFile, "input clock;\n" ); + Aig_ManForEachPiSeq( p, pObj, i ) + fprintf( pFile, "input n%0*d;\n", nDigits, pObj->iData ); + // write POs + Aig_ManForEachPoSeq( p, pObj, i ) + fprintf( pFile, "output n%0*d;\n", nDigits, pObj->iData ); + // write latches + if ( Aig_ManRegNum(p) ) + { + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + fprintf( pFile, "reg n%0*d;\n", nDigits, pObjLo->iData ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + fprintf( pFile, "wire n%0*d;\n", nDigits, pObjLi->iData ); + } + // write nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + fprintf( pFile, "wire n%0*d;\n", nDigits, pObj->iData ); + // write nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + fprintf( pFile, "assign n%0*d = %sn%0*d & %sn%0*d;\n", + nDigits, pObj->iData, + !Aig_ObjFaninC0(pObj) ? " " : "~", nDigits, Aig_ObjFanin0(pObj)->iData, + !Aig_ObjFaninC1(pObj) ? " " : "~", nDigits, Aig_ObjFanin1(pObj)->iData + ); + } + // write POs + Aig_ManForEachPoSeq( p, pObj, i ) + { + fprintf( pFile, "assign n%0*d = %sn%0*d;\n", + nDigits, pObj->iData, + !Aig_ObjFaninC0(pObj) ? " " : "~", nDigits, Aig_ObjFanin0(pObj)->iData ); + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + pConst1 = Aig_ManConst1(p); + } + if ( Aig_ManRegNum(p) ) + { + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + fprintf( pFile, "assign n%0*d = %sn%0*d;\n", + nDigits, pObjLi->iData, + !Aig_ObjFaninC0(pObjLi) ? " " : "~", nDigits, Aig_ObjFanin0(pObjLi)->iData ); + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObjLi)) ) + pConst1 = Aig_ManConst1(p); + } + } + if ( pConst1 ) + fprintf( pFile, "assign n%0*d = 1\'b1;\n", nDigits, pConst1->iData ); + + // write initial state + if ( Aig_ManRegNum(p) ) + { + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + fprintf( pFile, "always @ (posedge clock) begin n%0*d <= n%0*d; end\n", + nDigits, pObjLo->iData, + nDigits, pObjLi->iData ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + fprintf( pFile, "initial begin n%0*d <= 1\'b0; end\n", + nDigits, pObjLo->iData ); + } + + fprintf( pFile, "endmodule\n\n" ); + fclose( pFile ); + Vec_PtrFree( vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aigWin.c b/abc70930/src/aig/aig/aigWin.c new file mode 100644 index 00000000..0485b243 --- /dev/null +++ b/abc70930/src/aig/aig/aigWin.c @@ -0,0 +1,184 @@ +/**CFile**************************************************************** + + FileName [aigWin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Window computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigWin.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Evaluate the cost of removing the node from the set of leaves.] + + Description [Returns the number of new leaves that will be brought in. + Returns large number if the node cannot be removed from the set of leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_NodeGetLeafCostOne( Aig_Obj_t * pNode, int nFanoutLimit ) +{ + int Cost; + // make sure the node is in the construction zone + assert( pNode->fMarkA ); + // cannot expand over the PI node + if ( Aig_ObjIsPi(pNode) ) + return 999; + // get the cost of the cone + Cost = (!Aig_ObjFanin0(pNode)->fMarkA) + (!Aig_ObjFanin1(pNode)->fMarkA); + // always accept if the number of leaves does not increase + if ( Cost < 2 ) + return Cost; + // skip nodes with many fanouts + if ( (int)pNode->nRefs > nFanoutLimit ) + return 999; + // return the number of nodes that will be on the leaves if this node is removed + return Cost; +} + +/**Function************************************************************* + + Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] + + Description [This procedure looks at the current leaves and tries to change + one leaf at a time in such a way that the cut grows as little as possible. + In evaluating the fanins, this procedure looks only at their immediate + predecessors (this is why it is called a one-level construction procedure).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManFindCut_int( Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ) +{ + Aig_Obj_t * pNode, * pFaninBest, * pNext; + int CostBest, CostCur, i; + // find the best fanin + CostBest = 100; + pFaninBest = NULL; +//printf( "Evaluating fanins of the cut:\n" ); + Vec_PtrForEachEntry( vFront, pNode, i ) + { + CostCur = Aig_NodeGetLeafCostOne( pNode, nFanoutLimit ); +//printf( " Fanin %s has cost %d.\n", Aig_ObjName(pNode), CostCur ); + if ( CostBest > CostCur || + (CostBest == CostCur && pNode->Level > pFaninBest->Level) ) + { + CostBest = CostCur; + pFaninBest = pNode; + } + if ( CostBest == 0 ) + break; + } + if ( pFaninBest == NULL ) + return 0; + assert( CostBest < 3 ); + if ( Vec_PtrSize(vFront) - 1 + CostBest > nSizeLimit ) + return 0; + assert( Aig_ObjIsNode(pFaninBest) ); + // remove the node from the array + Vec_PtrRemove( vFront, pFaninBest ); +//printf( "Removing fanin %s.\n", Aig_ObjName(pFaninBest) ); + + // add the left child to the fanins + pNext = Aig_ObjFanin0(pFaninBest); + if ( !pNext->fMarkA ) + { +//printf( "Adding fanin %s.\n", Aig_ObjName(pNext) ); + pNext->fMarkA = 1; + Vec_PtrPush( vFront, pNext ); + Vec_PtrPush( vVisited, pNext ); + } + // add the right child to the fanins + pNext = Aig_ObjFanin1(pFaninBest); + if ( !pNext->fMarkA ) + { +//printf( "Adding fanin %s.\n", Aig_ObjName(pNext) ); + pNext->fMarkA = 1; + Vec_PtrPush( vFront, pNext ); + Vec_PtrPush( vVisited, pNext ); + } + assert( Vec_PtrSize(vFront) <= nSizeLimit ); + // keep doing this + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes one sequential cut of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ) +{ + Aig_Obj_t * pNode; + int i; + + assert( !Aig_IsComplement(pRoot) ); + assert( Aig_ObjIsNode(pRoot) ); + assert( Aig_ObjChild0(pRoot) ); + assert( Aig_ObjChild1(pRoot) ); + + // start the cut + Vec_PtrClear( vFront ); + Vec_PtrPush( vFront, Aig_ObjFanin0(pRoot) ); + Vec_PtrPush( vFront, Aig_ObjFanin1(pRoot) ); + + // start the visited nodes + Vec_PtrClear( vVisited ); + Vec_PtrPush( vVisited, pRoot ); + Vec_PtrPush( vVisited, Aig_ObjFanin0(pRoot) ); + Vec_PtrPush( vVisited, Aig_ObjFanin1(pRoot) ); + + // mark these nodes + assert( !pRoot->fMarkA ); + assert( !Aig_ObjFanin0(pRoot)->fMarkA ); + assert( !Aig_ObjFanin1(pRoot)->fMarkA ); + pRoot->fMarkA = 1; + Aig_ObjFanin0(pRoot)->fMarkA = 1; + Aig_ObjFanin1(pRoot)->fMarkA = 1; + + // compute the cut + while ( Aig_ManFindCut_int( vFront, vVisited, nSizeLimit, nFanoutLimit ) ); + assert( Vec_PtrSize(vFront) <= nSizeLimit ); + + // clean the visit markings + Vec_PtrForEachEntry( vVisited, pNode, i ) + pNode->fMarkA = 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/aig_.c b/abc70930/src/aig/aig/aig_.c new file mode 100644 index 00000000..b2313d35 --- /dev/null +++ b/abc70930/src/aig/aig/aig_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [aig_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aig_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/aig/module.make b/abc70930/src/aig/aig/module.make new file mode 100644 index 00000000..c35e7121 --- /dev/null +++ b/abc70930/src/aig/aig/module.make @@ -0,0 +1,21 @@ +SRC += src/aig/aig/aigCheck.c \ + src/aig/aig/aigDfs.c \ + src/aig/aig/aigFanout.c \ + src/aig/aig/aigMan.c \ + src/aig/aig/aigMem.c \ + src/aig/aig/aigMffc.c \ + src/aig/aig/aigObj.c \ + src/aig/aig/aigOper.c \ + src/aig/aig/aigOrder.c \ + src/aig/aig/aigPart.c \ + src/aig/aig/aigRepr.c \ + src/aig/aig/aigRet.c \ + src/aig/aig/aigScl.c \ + src/aig/aig/aigSeq.c \ + src/aig/aig/aigTable.c \ + src/aig/aig/aigTime.c \ + src/aig/aig/aigTiming.c \ + src/aig/aig/aigTruth.c \ + src/aig/aig/aigTsim.c \ + src/aig/aig/aigUtil.c \ + src/aig/aig/aigWin.c \ No newline at end of file diff --git a/abc70930/src/aig/bar/bar.c b/abc70930/src/aig/bar/bar.c new file mode 100644 index 00000000..8c215b48 --- /dev/null +++ b/abc70930/src/aig/bar/bar.c @@ -0,0 +1,177 @@ +/**CFile**************************************************************** + + FileName [bar.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Progress bar.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bar.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include "bar.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Bar_Progress_t_ +{ + int nItemsNext; // the number of items for the next update of the progress bar + int nItemsTotal; // the total number of items + int posTotal; // the total number of positions + int posCur; // the current position + FILE * pFile; // the output stream +}; + +static void Bar_ProgressShow( Bar_Progress_t * p, char * pString ); +static void Bar_ProgressClean( Bar_Progress_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the progress bar.] + + Description [The first parameter is the output stream (pFile), where + the progress is printed. The current printing position should be the + first one on the given line. The second parameters is the total + number of items that correspond to 100% position of the progress bar.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bar_Progress_t * Bar_ProgressStart( FILE * pFile, int nItemsTotal ) +{ + Bar_Progress_t * p; +// extern int Abc_FrameShowProgress( void * p ); +// extern void * Abc_FrameGetGlobalFrame(); +// if ( !Abc_FrameShowProgress(Abc_FrameGetGlobalFrame()) ) return NULL; + p = (Bar_Progress_t *) malloc(sizeof(Bar_Progress_t)); + memset( p, 0, sizeof(Bar_Progress_t) ); + p->pFile = pFile; + p->nItemsTotal = nItemsTotal; + p->posTotal = 78; + p->posCur = 1; + p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); + Bar_ProgressShow( p, NULL ); + return p; +} + +/**Function************************************************************* + + Synopsis [Updates the progress bar.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bar_ProgressUpdate_int( Bar_Progress_t * p, int nItemsCur, char * pString ) +{ + if ( p == NULL ) return; + if ( nItemsCur < p->nItemsNext ) + return; + if ( nItemsCur >= p->nItemsTotal ) + { + p->posCur = 78; + p->nItemsNext = 0x7FFFFFFF; + } + else + { + p->posCur += 7; + p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); + } + Bar_ProgressShow( p, pString ); +} + + +/**Function************************************************************* + + Synopsis [Stops the progress bar.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bar_ProgressStop( Bar_Progress_t * p ) +{ + if ( p == NULL ) return; + Bar_ProgressClean( p ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Prints the progress bar of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bar_ProgressShow( Bar_Progress_t * p, char * pString ) +{ + int i; + if ( p == NULL ) return; + if ( pString ) + fprintf( p->pFile, "%s ", pString ); + for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ ) + fprintf( p->pFile, "-" ); + if ( i == p->posCur ) + fprintf( p->pFile, ">" ); + for ( i++ ; i <= p->posTotal; i++ ) + fprintf( p->pFile, " " ); + fprintf( p->pFile, "\r" ); + fflush( stdout ); +} + +/**Function************************************************************* + + Synopsis [Cleans the progress bar before quitting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bar_ProgressClean( Bar_Progress_t * p ) +{ + int i; + if ( p == NULL ) return; + for ( i = 0; i <= p->posTotal; i++ ) + fprintf( p->pFile, " " ); + fprintf( p->pFile, "\r" ); + fflush( stdout ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/bar/bar.h b/abc70930/src/aig/bar/bar.h new file mode 100644 index 00000000..814fbe6f --- /dev/null +++ b/abc70930/src/aig/bar/bar.h @@ -0,0 +1,74 @@ +/**CFile**************************************************************** + + FileName [bar.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Progress bar.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: bar.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __BAR_H__ +#define __BAR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define BAR_PROGRESS_USE 1 + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Bar_Progress_t_ Bar_Progress_t; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== bar.c ==========================================================*/ +extern Bar_Progress_t * Bar_ProgressStart( FILE * pFile, int nItemsTotal ); +extern void Bar_ProgressStop( Bar_Progress_t * p ); +extern void Bar_ProgressUpdate_int( Bar_Progress_t * p, int nItemsCur, char * pString ); + +static inline void Bar_ProgressUpdate( Bar_Progress_t * p, int nItemsCur, char * pString ) { + if ( BAR_PROGRESS_USE && p && (nItemsCur < *((int*)p)) ) return; Bar_ProgressUpdate_int(p, nItemsCur, pString); } + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/bar/module.make b/abc70930/src/aig/bar/module.make new file mode 100644 index 00000000..26161ba1 --- /dev/null +++ b/abc70930/src/aig/bar/module.make @@ -0,0 +1 @@ +SRC += src/aig/bar/bar.c diff --git a/abc70930/src/aig/bdc/bdc.h b/abc70930/src/aig/bdc/bdc.h new file mode 100644 index 00000000..71875edb --- /dev/null +++ b/abc70930/src/aig/bdc/bdc.h @@ -0,0 +1,73 @@ +/**CFile**************************************************************** + + FileName [bdc.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Truth-table-based bi-decomposition engine.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 30, 2007.] + + Revision [$Id: bdc.h,v 1.00 2007/01/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __BDC_H__ +#define __BDC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Bdc_Man_t_ Bdc_Man_t; +typedef struct Bdc_Par_t_ Bdc_Par_t; +struct Bdc_Par_t_ +{ + // general parameters + int nVarsMax; // the maximum support + int fVerbose; // enable basic stats + int fVeryVerbose; // enable detailed stats +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== bdcCore.c ==========================================================*/ +extern Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ); +extern void Bdc_ManFree( Bdc_Man_t * p ); +extern int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesLimit ); + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/bdc/bdcCore.c b/abc70930/src/aig/bdc/bdcCore.c new file mode 100644 index 00000000..157927b1 --- /dev/null +++ b/abc70930/src/aig/bdc/bdcCore.c @@ -0,0 +1,189 @@ +/**CFile**************************************************************** + + FileName [bdcCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Truth-table-based bi-decomposition engine.] + + Synopsis [The gateway to bi-decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 30, 2007.] + + Revision [$Id: bdcCore.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bdcInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocate resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ) +{ + Bdc_Man_t * p; + unsigned * pData; + int i, k, nBits; + p = ALLOC( Bdc_Man_t, 1 ); + memset( p, 0, sizeof(Bdc_Man_t) ); + assert( pPars->nVarsMax > 3 && pPars->nVarsMax < 16 ); + p->pPars = pPars; + p->nWords = Kit_TruthWordNum( pPars->nVarsMax ); + p->nDivsLimit = 200; + p->nNodesLimit = 0; // will be set later + // memory + p->vMemory = Vec_IntStart( 1 << 16 ); + // internal nodes + p->nNodesAlloc = 512; + p->pNodes = ALLOC( Bdc_Fun_t, p->nNodesAlloc ); + // set up hash table + p->nTableSize = (1 << p->pPars->nVarsMax); + p->pTable = ALLOC( Bdc_Fun_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Bdc_Fun_t *) * p->nTableSize ); + p->vSpots = Vec_IntAlloc( 256 ); + // truth tables + p->vTruths = Vec_PtrAllocSimInfo( pPars->nVarsMax + 5, p->nWords ); + // set elementary truth tables + nBits = (1 << pPars->nVarsMax); + Kit_TruthFill( Vec_PtrEntry(p->vTruths, 0), p->nVars ); + for ( k = 0; k < pPars->nVarsMax; k++ ) + { + pData = Vec_PtrEntry( p->vTruths, k+1 ); + Kit_TruthClear( pData, p->nVars ); + for ( i = 0; i < nBits; i++ ) + if ( i & (1 << k) ) + pData[i>>5] |= (1 << (i&31)); + } + p->puTemp1 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 1 ); + p->puTemp2 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 2 ); + p->puTemp3 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 3 ); + p->puTemp4 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 4 ); + // start the internal ISFs + p->pIsfOL = &p->IsfOL; Bdc_IsfStart( p, p->pIsfOL ); + p->pIsfOR = &p->IsfOR; Bdc_IsfStart( p, p->pIsfOR ); + p->pIsfAL = &p->IsfAL; Bdc_IsfStart( p, p->pIsfAL ); + p->pIsfAR = &p->IsfAR; Bdc_IsfStart( p, p->pIsfAR ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocate resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_ManFree( Bdc_Man_t * p ) +{ + Vec_IntFree( p->vMemory ); + Vec_IntFree( p->vSpots ); + Vec_PtrFree( p->vTruths ); + free( p->pNodes ); + free( p->pTable ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Clears the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_ManPrepare( Bdc_Man_t * p, Vec_Ptr_t * vDivs ) +{ + unsigned * puTruth; + Bdc_Fun_t * pNode; + int i; + Bdc_TableClear( p ); + Vec_IntClear( p->vMemory ); + // add constant 1 and elementary vars + p->nNodes = p->nNodesNew = 0; + for ( i = 0; i <= p->pPars->nVarsMax; i++ ) + { + pNode = Bdc_FunNew( p ); + pNode->Type = BDC_TYPE_PI; + pNode->puFunc = Vec_PtrEntry( p->vTruths, i ); + pNode->uSupp = i? (1 << (i-1)) : 0; + Bdc_TableAdd( p, pNode ); + } + // add the divisors + Vec_PtrForEachEntry( vDivs, puTruth, i ) + { + pNode = Bdc_FunNew( p ); + pNode->Type = BDC_TYPE_PI; + pNode->puFunc = puTruth; + pNode->uSupp = Kit_TruthSupport( puTruth, p->nVars ); + Bdc_TableAdd( p, pNode ); + if ( i == p->nDivsLimit ) + break; + } +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesMax ) +{ + Bdc_Isf_t Isf, * pIsf = &Isf; + // set current manager parameters + p->nVars = nVars; + p->nWords = Kit_TruthWordNum( nVars ); + Bdc_ManPrepare( p, vDivs ); + p->nNodesLimit = (p->nNodes + nNodesMax < p->nNodesAlloc)? p->nNodes + nNodesMax : p->nNodesAlloc; + // copy the function + Bdc_IsfStart( p, pIsf ); + Bdc_IsfClean( pIsf ); + pIsf->uSupp = Kit_TruthSupport( puFunc, p->nVars ) | Kit_TruthSupport( puCare, p->nVars ); + Kit_TruthAnd( pIsf->puOn, puCare, puFunc, p->nVars ); + Kit_TruthSharp( pIsf->puOff, puCare, puFunc, p->nVars ); + // call decomposition + Bdc_SuppMinimize( p, pIsf ); + p->pRoot = Bdc_ManDecompose_rec( p, pIsf ); + if ( p->pRoot == NULL ) + return -1; + return p->nNodesNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/bdc/bdcDec.c b/abc70930/src/aig/bdc/bdcDec.c new file mode 100644 index 00000000..747fcb14 --- /dev/null +++ b/abc70930/src/aig/bdc/bdcDec.c @@ -0,0 +1,461 @@ +/**CFile**************************************************************** + + FileName [bdcDec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Truth-table-based bi-decomposition engine.] + + Synopsis [Decomposition procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 30, 2007.] + + Revision [$Id: bdcDec.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bdcInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ); +static int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, unsigned * puTruth, Bdc_Type_t Type ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs one step of bi-decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) +{ + Bdc_Fun_t * pFunc; + Bdc_Isf_t IsfL, * pIsfL = &IsfL; + Bdc_Isf_t IsfB, * pIsfR = &IsfB; + // check computed results + if ( pFunc = Bdc_TableLookup( p, pIsf ) ) + return pFunc; + // decide on the decomposition type + pFunc = Bdc_FunNew( p ); + if ( pFunc == NULL ) + return NULL; + pFunc->Type = Bdc_DecomposeStep( p, pIsf, pIsfL, pIsfR ); + // decompose the left branch + pFunc->pFan0 = Bdc_ManDecompose_rec( p, pIsfL ); + if ( pFunc->pFan0 == NULL ) + return NULL; + // decompose the right branch + if ( Bdc_DecomposeUpdateRight( p, pIsf, pIsfL, pIsfR, pFunc->pFan0->puFunc, pFunc->Type ) ) + { + p->nNodes--; + return pFunc->pFan0; + } + pFunc->pFan1 = Bdc_ManDecompose_rec( p, pIsfL ); + if ( pFunc->pFan1 == NULL ) + return NULL; + // compute the function of node + pFunc->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); + if ( pFunc->Type == BDC_TYPE_AND ) + Kit_TruthAnd( pFunc->puFunc, pFunc->pFan0->puFunc, pFunc->pFan1->puFunc, p->nVars ); + else if ( pFunc->Type == BDC_TYPE_OR ) + Kit_TruthOr( pFunc->puFunc, pFunc->pFan0->puFunc, pFunc->pFan1->puFunc, p->nVars ); + else + assert( 0 ); + // verify correctness + assert( Bdc_TableCheckContainment(p, pIsf, pFunc->puFunc) ); + // convert from OR to AND + if ( pFunc->Type == BDC_TYPE_OR ) + { + pFunc->Type = BDC_TYPE_AND; + pFunc->pFan0 = Bdc_Not(pFunc->pFan0); + pFunc->pFan1 = Bdc_Not(pFunc->pFan1); + Kit_TruthNot( pFunc->puFunc, pFunc->puFunc, p->nVars ); + pFunc = Bdc_Not(pFunc); + } + Bdc_TableAdd( p, Bdc_Regular(pFunc) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Updates the ISF of the right after the left was decompoosed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, unsigned * puTruth, Bdc_Type_t Type ) +{ + if ( Type == BDC_TYPE_OR ) + { +// Right.Q = bdd_appex( Q, CompSpecLeftF, bddop_diff, setRightRes ); +// Right.R = bdd_exist( R, setRightRes ); + +// if ( pR->Q ) Cudd_RecursiveDeref( dd, pR->Q ); +// if ( pR->R ) Cudd_RecursiveDeref( dd, pR->R ); +// pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Cudd_Not(CompSpecF), pL->V ); Cudd_Ref( pR->Q ); +// pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( pR->R ); + +// assert( pR->R != b0 ); +// return (int)( pR->Q == b0 ); + + Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars ); + Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp ); + Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uSupp ); + assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) ); + return Kit_TruthIsConst0(pIsfR->puOn, p->nVars); + } + else if ( Type == BDC_TYPE_AND ) + { +// Right.R = bdd_appex( R, CompSpecLeftF, bddop_and, setRightRes ); +// Right.Q = bdd_exist( Q, setRightRes ); + +// if ( pR->Q ) Cudd_RecursiveDeref( dd, pR->Q ); +// if ( pR->R ) Cudd_RecursiveDeref( dd, pR->R ); +// pR->R = Cudd_bddAndAbstract( dd, pF->R, CompSpecF, pL->V ); Cudd_Ref( pR->R ); +// pR->Q = Cudd_bddExistAbstract( dd, pF->Q, pL->V ); Cudd_Ref( pR->Q ); + +// assert( pR->Q != b0 ); +// return (int)( pR->R == b0 ); + + Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars ); + Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp ); + Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uSupp ); + assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) ); + return Kit_TruthIsConst0(pIsfR->puOn, p->nVars); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks existence of OR-bidecomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Bdc_DecomposeGetCost( Bdc_Man_t * p, int nLeftVars, int nRightVars ) +{ + assert( nLeftVars > 0 ); + assert( nRightVars > 0 ); + // compute the decomposition coefficient + if ( nLeftVars >= nRightVars ) + return BDC_SCALE * (p->nVars * nRightVars + nLeftVars); + else // if ( nLeftVars < nRightVars ) + return BDC_SCALE * (p->nVars * nLeftVars + nRightVars); +} + +/**Function************************************************************* + + Synopsis [Checks existence of weak OR-bidecomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_DecomposeFindInitialVarSet( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) +{ + char pVars[16]; + int v, nVars, Beg, End; + + assert( pIsfL->uSupp == 0 ); + assert( pIsfR->uSupp == 0 ); + + // fill in the variables + nVars = 0; + for ( v = 0; v < p->nVars; v++ ) + if ( pIsf->uSupp & (1 << v) ) + pVars[nVars++] = v; + + // try variable pairs + for ( Beg = 0; Beg < nVars; Beg++ ) + { + Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, pVars[Beg] ); + for ( End = nVars - 1; End > Beg; End-- ) + { + Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pVars[End] ); + if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp1, p->puTemp2, p->nVars) ) + { + pIsfL->uSupp = (1 << Beg); + pIsfR->uSupp = (1 << End); + pIsfL->Var = Beg; + pIsfR->Var = End; + return 1; + } + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks existence of weak OR-bidecomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_DecomposeWeakOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) +{ + int v, VarCost, VarBest, Cost, VarCostBest = 0; + + for ( v = 0; v < p->nVars; v++ ) + { + Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, v ); +// if ( (Q & !bdd_exist( R, VarSetXa )) != bddfalse ) +// Exist = Cudd_bddExistAbstract( dd, pF->R, Var ); Cudd_Ref( Exist ); +// if ( Cudd_bddIteConstant( dd, pF->Q, Cudd_Not(Exist), b0 ) != b0 ) + if ( !Kit_TruthIsImply( pIsf->puOn, p->puTemp1, p->nVars ) ) + { + // measure the cost of this variable +// VarCost = bdd_satcountset( bdd_forall( Q, VarSetXa ), VarCube ); + +// Univ = Cudd_bddUnivAbstract( dd, pF->Q, Var ); Cudd_Ref( Univ ); +// VarCost = Kit_TruthCountOnes( Univ, p->nVars ); +// Cudd_RecursiveDeref( dd, Univ ); + + Kit_TruthForallNew( p->puTemp2, pIsf->puOn, p->nVars, v ); + VarCost = Kit_TruthCountOnes( p->puTemp2, p->nVars ); + if ( VarCost == 0 ) + VarCost = 1; + if ( VarCostBest < VarCost ) + { + VarCostBest = VarCost; + VarBest = v; + } + } + } + + // derive the components for weak-bi-decomposition if the variable is found + if ( VarCostBest ) + { +// funQLeftRes = Q & bdd_exist( R, setRightORweak ); + +// Temp = Cudd_bddExistAbstract( dd, pF->R, VarBest ); Cudd_Ref( Temp ); +// pL->Q = Cudd_bddAnd( dd, pF->Q, Temp ); Cudd_Ref( pL->Q ); +// Cudd_RecursiveDeref( dd, Temp ); + + Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, VarBest ); + Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars ); + +// pL->R = pF->R; Cudd_Ref( pL->R ); +// pL->V = VarBest; Cudd_Ref( pL->V ); + Kit_TruthCopy( pIsfL->puOff, pIsf->puOff, p->nVars ); + pIsfL->Var = VarBest; + +// assert( pL->Q != b0 ); +// assert( pL->R != b0 ); +// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 ); + + // express cost in percents of the covered boolean space + Cost = VarCostBest * BDC_SCALE / (1<nVars); + if ( Cost == 0 ) + Cost = 1; + return Cost; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks existence of OR-bidecomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_DecomposeOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) +{ + unsigned uSuppRem; + int v, nLeftVars = 1, nRightVars = 1; + // clean the var sets + Bdc_IsfClean( pIsfL ); + Bdc_IsfClean( pIsfR ); + // find initial variable sets + if ( !Bdc_DecomposeFindInitialVarSet( p, pIsf, pIsfL, pIsfR ) ) + return Bdc_DecomposeWeakOr( p, pIsf, pIsfL, pIsfR ); + // prequantify the variables in the offset + Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, pIsfL->Var ); + Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pIsfR->Var ); + // go through the remaining variables + uSuppRem = pIsf->uSupp & ~pIsfL->uSupp & ~pIsfR->uSupp; + assert( Kit_WordCountOnes(uSuppRem) > 0 ); + for ( v = 0; v < p->nVars; v++ ) + { + if ( (uSuppRem & (1 << v)) == 0 ) + continue; + // prequantify this variable + Kit_TruthExistNew( p->puTemp3, p->puTemp1, p->nVars, v ); + Kit_TruthExistNew( p->puTemp4, p->puTemp2, p->nVars, v ); + if ( nLeftVars < nRightVars ) + { +// if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse ) +// if ( VerifyORCondition( dd, pF->Q, pF->R, pL->V, pR->V, VarNew ) ) + if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) ) + { +// pL->V &= VarNew; + pIsfL->uSupp |= (1 << v); + nLeftVars++; + } +// else if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse ) + else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) ) + { +// pR->V &= VarNew; + pIsfR->uSupp |= (1 << v); + nRightVars++; + } + } + else + { +// if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse ) + if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) ) + { +// pR->V &= VarNew; + pIsfR->uSupp |= (1 << v); + nRightVars++; + } +// else if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse ) + else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) ) + { +// pL->V &= VarNew; + pIsfL->uSupp |= (1 << v); + nLeftVars++; + } + } + } + + // derive the functions Q and R for the left branch +// pL->Q = bdd_appex( pF->Q, bdd_exist( pF->R, pL->V ), bddop_and, pR->V ); +// pL->R = bdd_exist( pF->R, pR->V ); + +// Temp = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( Temp ); +// pL->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pR->V ); Cudd_Ref( pL->Q ); +// Cudd_RecursiveDeref( dd, Temp ); +// pL->R = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( pL->R ); + + Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars ); + Kit_TruthExistSet( pIsfL->puOn, pIsfL->puOn, p->nVars, pIsfR->uSupp ); + Kit_TruthCopy( pIsfL->puOff, p->puTemp2, p->nVars ); + + // derive the functions Q and R for the right branch +// Temp = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( Temp ); +// pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pL->V ); Cudd_Ref( pR->Q ); +// Cudd_RecursiveDeref( dd, Temp ); +// pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( pR->R ); + +/* + Kit_TruthAnd( pIsfR->puOn, pIsf->puOn, p->puTemp2, p->nVars ); + Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp ); + Kit_TruthCopy( pIsfR->puOff, p->puTemp1, p->nVars ); +*/ + +// assert( pL->Q != b0 ); +// assert( pL->R != b0 ); +// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 ); + assert( !Kit_TruthIsConst0(pIsfL->puOn, p->nVars) ); + assert( !Kit_TruthIsConst0(pIsfL->puOff, p->nVars) ); + assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) ); + + return Bdc_DecomposeGetCost( p, nLeftVars, nRightVars ); +} + +/**Function************************************************************* + + Synopsis [Performs one step of bi-decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) +{ + int CostOr, CostAnd, CostOrL, CostOrR, CostAndL, CostAndR; + + Bdc_IsfClean( p->pIsfOL ); + Bdc_IsfClean( p->pIsfOR ); + Bdc_IsfClean( p->pIsfAL ); + Bdc_IsfClean( p->pIsfAR ); + + // perform OR decomposition + CostOr = Bdc_DecomposeOr( p, pIsf, p->pIsfOL, p->pIsfOR ); + + // perform AND decomposition + Bdc_IsfNot( pIsf ); + CostAnd = Bdc_DecomposeOr( p, pIsf, p->pIsfAL, p->pIsfAR ); + Bdc_IsfNot( pIsf ); + Bdc_IsfNot( p->pIsfAL ); + Bdc_IsfNot( p->pIsfAR ); + + // check the hash table + Bdc_SuppMinimize( p, p->pIsfOL ); + CostOrL = (Bdc_TableLookup(p, p->pIsfOL) != NULL); + Bdc_SuppMinimize( p, p->pIsfOR ); + CostOrR = (Bdc_TableLookup(p, p->pIsfOR) != NULL); + Bdc_SuppMinimize( p, p->pIsfAL ); + CostAndL = (Bdc_TableLookup(p, p->pIsfAL) != NULL); + Bdc_SuppMinimize( p, p->pIsfAR ); + CostAndR = (Bdc_TableLookup(p, p->pIsfAR) != NULL); + + // check if there is any reuse for the components + if ( CostOrL + CostOrR < CostAndL + CostAndR ) + { + Bdc_IsfCopy( pIsfL, p->pIsfOL ); + Bdc_IsfCopy( pIsfR, p->pIsfOR ); + return BDC_TYPE_OR; + } + if ( CostOrL + CostOrR > CostAndL + CostAndR ) + { + Bdc_IsfCopy( pIsfL, p->pIsfAL ); + Bdc_IsfCopy( pIsfR, p->pIsfAR ); + return BDC_TYPE_AND; + } + + // compare the two-component costs + if ( CostOr < CostAnd ) + { + Bdc_IsfCopy( pIsfL, p->pIsfOL ); + Bdc_IsfCopy( pIsfR, p->pIsfOR ); + return BDC_TYPE_OR; + } + return BDC_TYPE_AND; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/bdc/bdcInt.h b/abc70930/src/aig/bdc/bdcInt.h new file mode 100644 index 00000000..9649f870 --- /dev/null +++ b/abc70930/src/aig/bdc/bdcInt.h @@ -0,0 +1,150 @@ +/**CFile**************************************************************** + + FileName [bdcInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Truth-table-based bi-decomposition engine.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __BDC_INT_H__ +#define __BDC_INT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "kit.h" +#include "bdc.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define BDC_SCALE 100 // value used to compute the cost + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// network types +typedef enum { + BDC_TYPE_NONE = 0, // 0: unknown + BDC_TYPE_CONST1, // 1: constant 1 + BDC_TYPE_PI, // 2: primary input + BDC_TYPE_AND, // 4: AND-gate + BDC_TYPE_OR, // 5: OR-gate (temporary) + BDC_TYPE_XOR, // 6: XOR-gate + BDC_TYPE_MUX, // 7: MUX-gate + BDC_TYPE_OTHER // 8: unused +} Bdc_Type_t; + +typedef struct Bdc_Fun_t_ Bdc_Fun_t; +struct Bdc_Fun_t_ +{ + int Type; // Const1, PI, AND, XOR, MUX + Bdc_Fun_t * pFan0; // fanin of the given node + Bdc_Fun_t * pFan1; // fanin of the given node + Bdc_Fun_t * pFan2; // fanin of the given node + unsigned uSupp; // bit mask of current support + unsigned * puFunc; // the function of the node + Bdc_Fun_t * pNext; // next function with same support + void * pCopy; // the copy field +}; + +typedef struct Bdc_Isf_t_ Bdc_Isf_t; +struct Bdc_Isf_t_ +{ + int Var; // the first variable assigned + unsigned uSupp; // the current support + unsigned * puOn; // on-set + unsigned * puOff; // off-set +}; + +struct Bdc_Man_t_ +{ + // external parameters + Bdc_Par_t * pPars; // parameter set + int nVars; // the number of variables + int nWords; // the number of words + int nNodesLimit; // the limit on the number of new nodes + int nDivsLimit; // the limit on the number of divisors + // internal nodes + Bdc_Fun_t * pNodes; // storage for decomposition nodes + int nNodes; // the number of nodes used + int nNodesNew; // the number of nodes used + int nNodesAlloc; // the number of nodes allocated + Bdc_Fun_t * pRoot; // the root node + // resub candidates + Bdc_Fun_t ** pTable; // hash table of candidates + int nTableSize; // hash table size (1 << nVarsMax) + Vec_Int_t * vSpots; // the occupied spots in the table + // elementary truth tables + Vec_Ptr_t * vTruths; // for const 1 and elementary variables + unsigned * puTemp1; // temporary truth table + unsigned * puTemp2; // temporary truth table + unsigned * puTemp3; // temporary truth table + unsigned * puTemp4; // temporary truth table + // temporary ISFs + Bdc_Isf_t * pIsfOL, IsfOL; + Bdc_Isf_t * pIsfOR, IsfOR; + Bdc_Isf_t * pIsfAL, IsfAL; + Bdc_Isf_t * pIsfAR, IsfAR; + // internal memory manager + Vec_Int_t * vMemory; // memory for internal truth tables +}; + +// working with complemented attributes of objects +static inline int Bdc_IsComplement( Bdc_Fun_t * p ) { return (int)((unsigned long)p & (unsigned long)01); } +static inline Bdc_Fun_t * Bdc_Regular( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((unsigned long)p & ~(unsigned long)01); } +static inline Bdc_Fun_t * Bdc_Not( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((unsigned long)p ^ (unsigned long)01); } +static inline Bdc_Fun_t * Bdc_NotCond( Bdc_Fun_t * p, int c ) { return (Bdc_Fun_t *)((unsigned long)p ^ (unsigned long)(c!=0)); } + +static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p ) { Bdc_Fun_t * pRes; if ( p->nNodes == p->nNodesLimit ) return NULL; pRes = p->pNodes + p->nNodes++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); p->nNodesNew++; return pRes; } +static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); } +static inline void Bdc_IsfClean( Bdc_Isf_t * p ) { p->uSupp = 0; p->Var = 0; } +static inline void Bdc_IsfCopy( Bdc_Isf_t * p, Bdc_Isf_t * q ) { Bdc_Isf_t T = *p; *p = *q; *q = T; } +static inline void Bdc_IsfNot( Bdc_Isf_t * p ) { unsigned * puT = p->puOn; p->puOn = p->puOff; p->puOff = puT; } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== bdcDec.c ==========================================================*/ +extern Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf ); +/*=== bdcTable.c ==========================================================*/ +extern Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf ); +extern void Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc ); +extern void Bdc_TableClear( Bdc_Man_t * p ); +extern void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ); +extern int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/bdc/bdcTable.c b/abc70930/src/aig/bdc/bdcTable.c new file mode 100644 index 00000000..d86a938d --- /dev/null +++ b/abc70930/src/aig/bdc/bdcTable.c @@ -0,0 +1,140 @@ +/**CFile**************************************************************** + + FileName [bdcTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Truth-table-based bi-decomposition engine.] + + Synopsis [Hash table for intermediate nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 30, 2007.] + + Revision [$Id: bdcTable.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bdcInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Minimizes the support of the ISF.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) +{ + int v; + // go through the support variables + for ( v = 0; v < p->nVars; v++ ) + { + if ( (pIsf->uSupp & (1 << v)) == 0 ) + continue; + Kit_TruthExistNew( p->puTemp1, pIsf->puOn, p->nVars, v ); + Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, v ); + if ( !Kit_TruthIsDisjoint( p->puTemp1, p->puTemp2, p->nVars ) ) + continue; + // remove the variable + Kit_TruthCopy( pIsf->puOn, p->puTemp1, p->nVars ); + Kit_TruthCopy( pIsf->puOff, p->puTemp2, p->nVars ); + pIsf->uSupp &= ~(1 << v); + } +} + +/**Function************************************************************* + + Synopsis [Checks containment of the function in the ISF.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth ) +{ + return Kit_TruthIsImply( pIsf->puOn, puTruth, p->nVars ) && + Kit_TruthIsDisjoint( pIsf->puOff, puTruth, p->nVars ); +} + +/**Function************************************************************* + + Synopsis [Adds the new entry to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) +{ + Bdc_Fun_t * pFunc; + for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext ) + if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) ) + return pFunc; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Adds the new entry to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc ) +{ + if ( p->pTable[pFunc->uSupp] == NULL ) + Vec_IntPush( p->vSpots, pFunc->uSupp ); + pFunc->pNext = p->pTable[pFunc->uSupp]; + p->pTable[pFunc->uSupp] = pFunc; +} + +/**Function************************************************************* + + Synopsis [Adds the new entry to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bdc_TableClear( Bdc_Man_t * p ) +{ + int Spot, i; + Vec_IntForEachEntry( p->vSpots, Spot, i ) + p->pTable[Spot] = NULL; + Vec_IntClear( p->vSpots ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/bdc/bdc_.c b/abc70930/src/aig/bdc/bdc_.c new file mode 100644 index 00000000..9d0a9462 --- /dev/null +++ b/abc70930/src/aig/bdc/bdc_.c @@ -0,0 +1,49 @@ +/**CFile**************************************************************** + + FileName [bdc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Truth-table-based bi-decomposition engine.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 30, 2007.] + + Revision [$Id: bdc_.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "bdcInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/bdc/module.make b/abc70930/src/aig/bdc/module.make new file mode 100644 index 00000000..8697c998 --- /dev/null +++ b/abc70930/src/aig/bdc/module.make @@ -0,0 +1,4 @@ +SRC += src/aig/bdc/bdcCore.c \ + src/aig/bdc/bdcDec.c \ + src/aig/bdc/bdcTable.c + diff --git a/abc70930/src/aig/cnf/cnf.h b/abc70930/src/aig/cnf/cnf.h new file mode 100644 index 00000000..5c7a594e --- /dev/null +++ b/abc70930/src/aig/cnf/cnf.h @@ -0,0 +1,162 @@ +/**CFile**************************************************************** + + FileName [cnf.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: cnf.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CNF_H__ +#define __CNF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "vec.h" +#include "aig.h" +#include "darInt.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cnf_Man_t_ Cnf_Man_t; +typedef struct Cnf_Dat_t_ Cnf_Dat_t; +typedef struct Cnf_Cut_t_ Cnf_Cut_t; + +// the CNF asserting outputs of AIG to be 1 +struct Cnf_Dat_t_ +{ + Aig_Man_t * pMan; // the AIG manager, for which CNF is computed + int nVars; // the number of variables + int nLiterals; // the number of CNF literals + int nClauses; // the number of CNF clauses + int ** pClauses; // the CNF clauses + int * pVarNums; // the number of CNF variable for each node ID (-1 if unused) +}; + +// the cut used to represent node in the AIG +struct Cnf_Cut_t_ +{ + char nFanins; // the number of leaves + char Cost; // the cost of this cut + short nWords; // the number of words in truth table + Vec_Int_t * vIsop[2]; // neg/pos ISOPs + int pFanins[0]; // the fanins (followed by the truth table) +}; + +// the CNF computation manager +struct Cnf_Man_t_ +{ + Aig_Man_t * pManAig; // the underlying AIG manager + char * pSopSizes; // sizes of SOPs for 4-variable functions + char ** pSops; // the SOPs for 4-variable functions + int aArea; // the area of the mapping + Aig_MmFlex_t * pMemCuts; // memory manager for cuts + int nMergeLimit; // the limit on the size of merged cut + unsigned * pTruths[4]; // temporary truth tables + Vec_Int_t * vMemory; // memory for intermediate ISOP representation + int timeCuts; + int timeMap; + int timeSave; +}; + + +static inline Dar_Cut_t * Dar_ObjBestCut( Aig_Obj_t * pObj ) { Dar_Cut_t * pCut; int i; Dar_ObjForEachCut( pObj, pCut, i ) if ( pCut->fBest ) return pCut; return NULL; } + +static inline int Cnf_CutSopCost( Cnf_Man_t * p, Dar_Cut_t * pCut ) { return p->pSopSizes[pCut->uTruth] + p->pSopSizes[0xFFFF & ~pCut->uTruth]; } + +static inline int Cnf_CutLeaveNum( Cnf_Cut_t * pCut ) { return pCut->nFanins; } +static inline int * Cnf_CutLeaves( Cnf_Cut_t * pCut ) { return pCut->pFanins; } +static inline unsigned * Cnf_CutTruth( Cnf_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nFanins); } + +static inline Cnf_Cut_t * Cnf_ObjBestCut( Aig_Obj_t * pObj ) { return pObj->pData; } +static inline void Cnf_ObjSetBestCut( Aig_Obj_t * pObj, Cnf_Cut_t * pCut ) { pObj->pData = pCut; } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over leaves of the cut +#define Cnf_CutForEachLeaf( p, pCut, pLeaf, i ) \ + for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cnfCore.c ========================================================*/ +extern Cnf_Dat_t * Cnf_Derive( Aig_Man_t * pAig, int nOutputs ); +extern Cnf_Man_t * Cnf_ManRead(); +extern void Cnf_ClearMemory(); +/*=== cnfCut.c ========================================================*/ +extern Cnf_Cut_t * Cnf_CutCreate( Cnf_Man_t * p, Aig_Obj_t * pObj ); +extern void Cnf_CutPrint( Cnf_Cut_t * pCut ); +extern void Cnf_CutFree( Cnf_Cut_t * pCut ); +extern void Cnf_CutUpdateRefs( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, Cnf_Cut_t * pCutRes ); +extern Cnf_Cut_t * Cnf_CutCompose( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int iFan ); +/*=== cnfData.c ========================================================*/ +extern void Cnf_ReadMsops( char ** ppSopSizes, char *** ppSops ); +/*=== cnfMan.c ========================================================*/ +extern Cnf_Man_t * Cnf_ManStart(); +extern void Cnf_ManStop( Cnf_Man_t * p ); +extern Vec_Int_t * Cnf_DataCollectPiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ); +extern void Cnf_DataFree( Cnf_Dat_t * p ); +extern void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable ); +void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p ); +/*=== cnfMap.c ========================================================*/ +extern void Cnf_DeriveMapping( Cnf_Man_t * p ); +extern int Cnf_ManMapForCnf( Cnf_Man_t * p ); +/*=== cnfPost.c ========================================================*/ +extern void Cnf_ManTransferCuts( Cnf_Man_t * p ); +extern void Cnf_ManFreeCuts( Cnf_Man_t * p ); +extern void Cnf_ManPostprocess( Cnf_Man_t * p ); +/*=== cnfUtil.c ========================================================*/ +extern Vec_Ptr_t * Aig_ManScanMapping( Cnf_Man_t * p, int fCollect ); +extern Vec_Ptr_t * Cnf_ManScanMapping( Cnf_Man_t * p, int fCollect, int fPreorder ); +/*=== cnfWrite.c ========================================================*/ +extern void Cnf_SopConvertToVector( char * pSop, int nCubes, Vec_Int_t * vCover ); +extern Cnf_Dat_t * Cnf_ManWriteCnf( Cnf_Man_t * p, Vec_Ptr_t * vMapped, int nOutputs ); +extern Cnf_Dat_t * Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/cnf/cnfCore.c b/abc70930/src/aig/cnf/cnfCore.c new file mode 100644 index 00000000..06731451 --- /dev/null +++ b/abc70930/src/aig/cnf/cnfCore.c @@ -0,0 +1,185 @@ +/**CFile**************************************************************** + + FileName [cnfCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG-to-CNF conversion.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: cnfCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cnf.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Cnf_Man_t * s_pManCnf = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts AIG into the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Dat_t * Cnf_Derive( Aig_Man_t * pAig, int nOutputs ) +{ + Cnf_Man_t * p; + Cnf_Dat_t * pCnf; + Vec_Ptr_t * vMapped; + Aig_MmFixed_t * pMemCuts; + int clk; + // allocate the CNF manager + if ( s_pManCnf == NULL ) + s_pManCnf = Cnf_ManStart(); + // connect the managers + p = s_pManCnf; + p->pManAig = pAig; + + // generate cuts for all nodes, assign cost, and find best cuts +clk = clock(); + pMemCuts = Dar_ManComputeCuts( pAig, 10 ); +p->timeCuts = clock() - clk; + + // find the mapping +clk = clock(); + Cnf_DeriveMapping( p ); +p->timeMap = clock() - clk; +// Aig_ManScanMapping( p, 1 ); + + // convert it into CNF +clk = clock(); + Cnf_ManTransferCuts( p ); + vMapped = Cnf_ManScanMapping( p, 1, 1 ); + pCnf = Cnf_ManWriteCnf( p, vMapped, nOutputs ); + Vec_PtrFree( vMapped ); + Aig_MmFixedStop( pMemCuts, 0 ); +p->timeSave = clock() - clk; + + // reset reference counters + Aig_ManResetRefs( pAig ); +//PRT( "Cuts ", p->timeCuts ); +//PRT( "Map ", p->timeMap ); +//PRT( "Saving ", p->timeSave ); + return pCnf; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Man_t * Cnf_ManRead() +{ + return s_pManCnf; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_ClearMemory() +{ + if ( s_pManCnf == NULL ) + return; + Cnf_ManStop( s_pManCnf ); + s_pManCnf = NULL; +} + + +#if 0 + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Dat_t * Cnf_Derive_old( Aig_Man_t * pAig ) +{ +/* + // iteratively improve area flow + for ( i = 0; i < nIters; i++ ) + { +clk = clock(); + Cnf_ManScanMapping( p, 0 ); + Cnf_ManMapForCnf( p ); +PRT( "iter ", clock() - clk ); + } +*/ + // write the file + vMapped = Aig_ManScanMapping( p, 1 ); + Vec_PtrFree( vMapped ); + +clk = clock(); + Cnf_ManTransferCuts( p ); + + Cnf_ManPostprocess( p ); + Cnf_ManScanMapping( p, 0 ); +/* + Cnf_ManPostprocess( p ); + Cnf_ManScanMapping( p, 0 ); + Cnf_ManPostprocess( p ); + Cnf_ManScanMapping( p, 0 ); +*/ +PRT( "Ext ", clock() - clk ); + +/* + vMapped = Cnf_ManScanMapping( p, 1 ); + pCnf = Cnf_ManWriteCnf( p, vMapped ); + Vec_PtrFree( vMapped ); + + // clean up + Cnf_ManFreeCuts( p ); + Dar_ManCutsFree( pAig ); + return pCnf; +*/ + Aig_MmFixedStop( pMemCuts, 0 ); + return NULL; +} + +#endif + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/cnf/cnfCut.c b/abc70930/src/aig/cnf/cnfCut.c new file mode 100644 index 00000000..17ab0c78 --- /dev/null +++ b/abc70930/src/aig/cnf/cnfCut.c @@ -0,0 +1,371 @@ +/**CFile**************************************************************** + + FileName [cnfCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG-to-CNF conversion.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: cnfCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cnf.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates cut of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Cut_t * Cnf_CutAlloc( Cnf_Man_t * p, int nLeaves ) +{ + Cnf_Cut_t * pCut; + int nSize = sizeof(Cnf_Cut_t) + sizeof(int) * nLeaves + sizeof(unsigned) * Aig_TruthWordNum(nLeaves); + pCut = (Cnf_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCuts, nSize ); + pCut->nFanins = nLeaves; + pCut->nWords = Aig_TruthWordNum(nLeaves); + pCut->vIsop[0] = pCut->vIsop[1] = NULL; + return pCut; +} + +/**Function************************************************************* + + Synopsis [Deallocates cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CutFree( Cnf_Cut_t * pCut ) +{ + if ( pCut->vIsop[0] ) + Vec_IntFree( pCut->vIsop[0] ); + if ( pCut->vIsop[1] ) + Vec_IntFree( pCut->vIsop[1] ); +} + +/**Function************************************************************* + + Synopsis [Creates cut for the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Cut_t * Cnf_CutCreate( Cnf_Man_t * p, Aig_Obj_t * pObj ) +{ + Dar_Cut_t * pCutBest; + Cnf_Cut_t * pCut; + unsigned * pTruth; + assert( Aig_ObjIsNode(pObj) ); + pCutBest = Dar_ObjBestCut( pObj ); + assert( pCutBest != NULL ); + assert( pCutBest->nLeaves <= 4 ); + pCut = Cnf_CutAlloc( p, pCutBest->nLeaves ); + memcpy( pCut->pFanins, pCutBest->pLeaves, sizeof(int) * pCutBest->nLeaves ); + pTruth = Cnf_CutTruth(pCut); + *pTruth = (pCutBest->uTruth << 16) | pCutBest->uTruth; + pCut->Cost = Cnf_CutSopCost( p, pCutBest ); + return pCut; +} + +/**Function************************************************************* + + Synopsis [Deallocates cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CutPrint( Cnf_Cut_t * pCut ) +{ + int i; + printf( "{" ); + for ( i = 0; i < pCut->nFanins; i++ ) + printf( "%d ", pCut->pFanins[i] ); + printf( " } " ); +} + +/**Function************************************************************* + + Synopsis [Allocates cut of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CutDeref( Cnf_Man_t * p, Cnf_Cut_t * pCut ) +{ + Aig_Obj_t * pObj; + int i; + Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i ) + { + assert( pObj->nRefs > 0 ); + pObj->nRefs--; + } +} + +/**Function************************************************************* + + Synopsis [Allocates cut of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CutRef( Cnf_Man_t * p, Cnf_Cut_t * pCut ) +{ + Aig_Obj_t * pObj; + int i; + Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i ) + { + pObj->nRefs++; + } +} + +/**Function************************************************************* + + Synopsis [Allocates cut of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CutUpdateRefs( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, Cnf_Cut_t * pCutRes ) +{ + Cnf_CutDeref( p, pCut ); + Cnf_CutDeref( p, pCutFan ); + Cnf_CutRef( p, pCutRes ); +} + +/**Function************************************************************* + + Synopsis [Merges two arrays of integers.] + + Description [Returns the number of items.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cnf_CutMergeLeaves( Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int * pFanins ) +{ + int i, k, nFanins = 0; + for ( i = k = 0; i < pCut->nFanins && k < pCutFan->nFanins; ) + { + if ( pCut->pFanins[i] == pCutFan->pFanins[k] ) + pFanins[nFanins++] = pCut->pFanins[i], i++, k++; + else if ( pCut->pFanins[i] < pCutFan->pFanins[k] ) + pFanins[nFanins++] = pCut->pFanins[i], i++; + else + pFanins[nFanins++] = pCutFan->pFanins[k], k++; + } + for ( ; i < pCut->nFanins; i++ ) + pFanins[nFanins++] = pCut->pFanins[i]; + for ( ; k < pCutFan->nFanins; k++ ) + pFanins[nFanins++] = pCutFan->pFanins[k]; + return nFanins; +} + +/**Function************************************************************* + + Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Cnf_TruthPhase( Cnf_Cut_t * pCut, Cnf_Cut_t * pCut1 ) +{ + unsigned uPhase = 0; + int i, k; + for ( i = k = 0; i < pCut->nFanins; i++ ) + { + if ( k == pCut1->nFanins ) + break; + if ( pCut->pFanins[i] < pCut1->pFanins[k] ) + continue; + assert( pCut->pFanins[i] == pCut1->pFanins[k] ); + uPhase |= (1 << i); + k++; + } + return uPhase; +} + +/**Function************************************************************* + + Synopsis [Removes the fanin variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CutRemoveIthVar( Cnf_Cut_t * pCut, int iVar, int iFan ) +{ + int i; + assert( pCut->pFanins[iVar] == iFan ); + pCut->nFanins--; + for ( i = iVar; i < pCut->nFanins; i++ ) + pCut->pFanins[i] = pCut->pFanins[i+1]; +} + +/**Function************************************************************* + + Synopsis [Inserts the fanin variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CutInsertIthVar( Cnf_Cut_t * pCut, int iVar, int iFan ) +{ + int i; + for ( i = pCut->nFanins; i > iVar; i-- ) + pCut->pFanins[i] = pCut->pFanins[i-1]; + pCut->pFanins[iVar] = iFan; + pCut->nFanins++; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [Returns NULL of the cuts cannot be merged.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Cut_t * Cnf_CutCompose( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int iFan ) +{ + Cnf_Cut_t * pCutRes; + static int pFanins[32]; + unsigned * pTruth, * pTruthFan, * pTruthRes; + unsigned * pTop = p->pTruths[0], * pFan = p->pTruths[2], * pTemp = p->pTruths[3]; + unsigned uPhase, uPhaseFan; + int i, iVar, nFanins, RetValue; + + // make sure the second cut is the fanin of the first + for ( iVar = 0; iVar < pCut->nFanins; iVar++ ) + if ( pCut->pFanins[iVar] == iFan ) + break; + assert( iVar < pCut->nFanins ); + // remove this variable + Cnf_CutRemoveIthVar( pCut, iVar, iFan ); + // merge leaves of the cuts + nFanins = Cnf_CutMergeLeaves( pCut, pCutFan, pFanins ); + if ( nFanins+1 > p->nMergeLimit ) + { + Cnf_CutInsertIthVar( pCut, iVar, iFan ); + return NULL; + } + // create new cut + pCutRes = Cnf_CutAlloc( p, nFanins ); + memcpy( pCutRes->pFanins, pFanins, sizeof(int) * nFanins ); + assert( pCutRes->nFanins <= pCut->nFanins + pCutFan->nFanins ); + + // derive its truth table + // get the truth tables in the composition space + pTruth = Cnf_CutTruth(pCut); + pTruthFan = Cnf_CutTruth(pCutFan); + pTruthRes = Cnf_CutTruth(pCutRes); + for ( i = 0; i < 2*pCutRes->nWords; i++ ) + pTop[i] = pTruth[i % pCut->nWords]; + for ( i = 0; i < pCutRes->nWords; i++ ) + pFan[i] = pTruthFan[i % pCutFan->nWords]; + // move the variable to the end + uPhase = Kit_BitMask( pCutRes->nFanins+1 ) & ~(1 << iVar); + Kit_TruthShrink( pTemp, pTop, pCutRes->nFanins, pCutRes->nFanins+1, uPhase, 1 ); + // compute the phases + uPhase = Cnf_TruthPhase( pCutRes, pCut ) | (1 << pCutRes->nFanins); + uPhaseFan = Cnf_TruthPhase( pCutRes, pCutFan ); + // permute truth-tables to the common support + Kit_TruthStretch( pTemp, pTop, pCut->nFanins+1, pCutRes->nFanins+1, uPhase, 1 ); + Kit_TruthStretch( pTemp, pFan, pCutFan->nFanins, pCutRes->nFanins, uPhaseFan, 1 ); + // perform Boolean operation + Kit_TruthMux( pTruthRes, pTop, pTop+pCutRes->nWords, pFan, pCutRes->nFanins ); + // return the cut to its original condition + Cnf_CutInsertIthVar( pCut, iVar, iFan ); + // consider the simple case + if ( pCutRes->nFanins < 5 ) + { + pCutRes->Cost = p->pSopSizes[0xFFFF & *pTruthRes] + p->pSopSizes[0xFFFF & ~*pTruthRes]; + return pCutRes; + } + + // derive ISOP for positive phase + RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 ); + pCutRes->vIsop[1] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory ); + // derive ISOP for negative phase + Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins ); + RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 ); + pCutRes->vIsop[0] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory ); + Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins ); + + // compute the cut cost + if ( pCutRes->vIsop[0] == NULL || pCutRes->vIsop[1] == NULL ) + pCutRes->Cost = 127; + else if ( Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]) > 127 ) + pCutRes->Cost = 127; + else + pCutRes->Cost = Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]); + return pCutRes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/cnf/cnfData.c b/abc70930/src/aig/cnf/cnfData.c new file mode 100644 index 00000000..7b8be51e --- /dev/null +++ b/abc70930/src/aig/cnf/cnfData.c @@ -0,0 +1,4784 @@ +/**CFile**************************************************************** + + FileName [cnfData.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG-to-CNF conversion.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: cnfData.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cnf.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static char s_Data3[81] = "!#&()*+,-.0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz|"; + +static char * s_Data4[] = { +"! B a . 8 .B 8a K !K T Ta j 8j Tj s ( + (B +a (. +8 .B( +8a (K +K T( +T j( ", +"+j Tj( s+ E !E H Ha E. 8E H. H8 EK EK! HT HTa jE 8jE Hj sH d +d Hd g d. 8d ", +"Hd. g8 dK +dK Td gT dj +jd Hjd gs 2 !2 2B a2 5 58 5B 5a 2K 2K! T2 Ta2 5j 58", +"j 5T s5 ; +; ;B a; 5; > 5;B >a ;K +;K T; +T; ;j >j 5T; s> E2 !E2 H2 Ha2 5E ", +"58E H5 H58 EK2 !E2K HT2 TaH2 5jE 8j5E H5T sH5 d; +d; H; g; 5d >d H5d g> dK;", +" dK+; H;T gT; 5dj >jd H;j gs> N !N NB aN N. 8N .BN 8aN Q Q! QT Qa Qj Q8 QTj", +" sQ (N +N (BN +aN N.( +8N (BN. 8a+N Q( +Q QT( +QT Qj( +Q8 TjQ( s+Q W W! HW ", +"Wa W. W8 HW. H8W WQ Q!W Z Za Wj W8Q Zj sZ Wd +W HWd gW Wd. +W8 WdH. gW8 Qd ", +"+WQ Zd gZ Wjd +Wj Zdj gZs m m! mB am 5m 8m 5mB 5am Qm Q!m Tm Qam p p8 pT sp", +" m; +m m;B +ma 5m; >m m;5B >ma Q; +Qm Q;T +Tm p; p> pT; sp> Wm W!m Hm Hma 5", +"W 5W8 H5W H8m WQm WmQ! Zm Zam pW pW8 Zp sZp v v+ vH gv v5 v> vH5 gv> vQ v+Q", +" Zv gZv pv pv> Zpv y # & #B a& #. 8& .B# 8a& #K &K T# T& j# &j Tj# s& #( +&", +" #B( +a& #(. +8& #(.B 8a+& #(K +&K T#( +T& j#( +j& j#T( s+& #E &E H# H& #E.", +" 8&E H#. H8& EK# &EK HT# H&T j#E &jE Hj# sH& d# d& Hd# g& d#. 8d& d#H. g8& ", +"dK# d&K Td# gT& dj# d&j H#dj gs& #2 &2 2B# a&2 5# 5& 5B# 5a& 2K# &2K T#2 T&", +"2 5j# 5&j 5T# s5& ;# ;& ;#B a;& 5;# >& ;#5B >&a ;#K ;&K T;# T;& ;j# >&j 5#T", +"; s>& #E2 &E2 H#2 H&2 5#E 5&E H5# H5& #E2K EK&2 T#H2 H2T& j#5E 5E&j H#5T H5", +"s& d;# d&; H;# g;& 5d# >&d H#5d g>& ;#dK dK;& H#T; T;g& 5#dj d&>j H#;j >&gs", +" #N &N #BN a&N N.# 8&N #BN. aN8& Q# Q& QT# Qa& Qj# Q8& TjQ# sQ& #(N +&N #(N", +"B a&+N #(N. 8&+N .BN#( +8a&N Q#( +Q& T#Q( Q&+T j#Q( Q&+j QTj#( +Qs& W# W& H", +"W# H&W W#. W8& W#H. W8H& WQ# W&Q Z# Z& Wj# W&j Zj# sZ& Wd# +W& WdH# gW& d#W", +". 8dW& HWd#. W8g& Qd# Qd& Zd# gZ& W#dj W&+j djZ# Z&gs m# m& m#B am& 5m# 5&m", +" m#5B am5& Qm# Q&m Tm# Tm& p# p& pT# sp& m;# +m& ;#mB m&a; m;5# >m& 5m;#B a", +"m>& Q;# Q;& Q#T; T;Q& p;# p>& T;p# p&s> Wm# W&m Hm# Hm& 5W# 5W& H#5W 5WH& Q", +"mW# WQm& Zm# Z&m pW# p&W Zp# Zp& v# v& vH# gv& v5# v>& H5v# v&g> vQ# v&Q Zv", +"# Zv& pv# pv& Z#pv y& C !C D Da C. 8C D. D8 CK CK! DT DTa jC 8jC Dj sD C( +", +"C D( +D C(. +8C D(. +D8 CK( +CK DT( +DT jC( +jC Dj( s+D CE !CE HD HDa CE. 8", +"CE HD. H8D EKC !CEK HDT DTHa jCE jC8E HjD sHD dC +dC Dd gD dC. 8dC Dd. gD8 ", +"dKC dK+C DdT gDT djC +Cdj Ddj gsD C2 !C2 D2 Da2 5C 58C 5D 5D8 2KC !C2K DT2 ", +"T2Da 5jC 8j5C 5DT s5D ;C +;C D; +D; 5;C >C 5D; >D ;CK ;C+K D;T D;+T ;jC >jC", +" D;j s>D CE2 CE!2 HD2 H2Da 5CE 8C5E H5D 5DH8 CE2K !E2CK H2DT HDTa2 jC5E 58j", +"CE 5DHj H5sD d;C d;+C H;D gD; 5dC >Cd 5Dd g>D ;CdK +d;CK TdD; D;gT 5Cdj dj>", +"C Dd5T >Dgs CN !CN DN DaN N.C 8CN DN. D8N QC Q!C QD QDa QjC Q8C QDj sQD C(N", +" +CN D(N +DN C(N. 8C+N N.D( +ND8 QC( +QC QD( +QD jCQ( +CQ8 Q(Dj +QsD WC W!C", +" WD WDa WC. W8C WD. WD8 WQC WCQ! ZD ZDa WjC WCQ8 ZDj sZD WdC +WC WDd gWD dC", +"W. +CW8 W.Dd WDg8 QdC +CQd ZDd gZD WCdj +CWj DdZj gDsZ mC mC! Dm Dma 5mC 8m", +"C 5Dm D8m QmC mCQ! QDm DmQa pC p8C pD spD m;C +mC Dm; +Dm m;5C >mC 5mD; >Dm", +" Q;C +CQ; QD; QD+m p;C p>C pD; p>D WmC mCW! HmD DmWa 5WC 5CW8 5WD WD5a QmWC", +" Q!WmC ZDm DmZa pWC W8pC ZpD pDsZ vC v+C vD gvD v5C v>C vD5 v>D vQC +QvC Zv", +"D vDgZ pvC >Cpv pvD yD b b& bD c b. b8 bD. c8 bK bK& bT cT bj b8j bTj sc b(", +" b+ bD( c+ b(. b+8 D(b. c+8 bK( b+K bT( c+T bj( b+j b(Dj sc+ bE b&E bH cH b", +"E. b8E bH. cH8 bKE &EbK bHT cHT bjE bE&j bHj scH bd b+d bHd gc bd. b8d b.Dd", +" gc8 bdK bKd& bTd gcT bdj +jbd Hjbd gsc b2 b&2 bD2 c2 b5 b58 b5D c5 bK2 &2b", +"K bT2 c2T b5j 5&bj b5T sc5 b; b+; b;D c; b5; >b 5Db; c> b;K bK;& bT; c;T b;", +"j >bj 5Tb; c>s bE2 &Eb2 bH2 c2H b5E bE5& bH5 c5H EKb2 bK&E2 HTb2 HTc2 5jbE ", +"&jEb5 H5bT sHc5 bd; d&b; bH; gc; b5d >bd H5bd c>g dKb; d&;bK H;bT gTc; 5dbj", +" bd>j H;bj gsc> bN b&N bDN cN bN. b8N DNb. c8N bQ bQ& bQD cQ bQj bQ8 QDbj s", +"cQ b(N b+N D(bN c+N N.b( +8bN bD(N. +8cN bQ( b+Q b(QD cQ+ Qjb( +Qb8 bQDj( s", +"+cQ bW bW& bHW cW bW. bW8 b.WD cW8 bWQ W&bQ Zb Zc bWj W8bQ Zbj Zcs bWd b+W ", +"WDbd gcW Wdb. +Wb8 bHWd. g8cW bQd +WbQ Zbd Zcg Wjbd +Wbj bdZj gsZc bm bm& b", +"mD cm b5m b8m 5Dbm c5m bQm Q&bm bTm cQm pb pb8 pbD cp bm; b+m Dmb; cm+ 5mb;", +" >bm b5Dm; c>m bQ; +Qbm QDb; cQ; pb; p>b bTp; cp> bWm W&bm bHm cWm b5W 5Wb8", +" H5bW c5W WQbm bWQm& Zbm Zcm pbW bWp& Zpb cpZ vb vb+ vbH cv vb5 v>b bHv5 cv", +"> vbQ b+vQ Zvb cvZ pvb v>pb pvZb yc 0 !0 0B a0 1 18 1B 1a 0K !K0 T0 Ta0 1j ", +"18j 1T s1 0( +0 0B( +a0 1( 1+ 1(B 1+a 0(K +0K T0( +T0 1j( 1+j 1T( s1+ E0 !E", +"0 H0 Ha0 1E 18E 1H 1H8 EK0 !0EK HT0 TaH0 1jE 8j1E 1HT s1H d0 +d0 Hd0 g0 1d ", +"1+d 1Hd g1 dK0 dK+0 Td0 gT0 1dj +j1d 1Td gs1 02 !02 2B0 a02 15 158 15B 1a5 ", +"2K0 !02K T02 T2a0 15j 581j 1T5 s15 ;0 +;0 ;0B a;0 1; >1 1;B >1a ;0K ;0+K T;", +"0 +0T; 1;j >j1 1T; s>1 E02 E0!2 H02 a0H2 15E 581E 1H5 H51a E02K !E20K T0H2 ", +"HTa02 5j1E 158jE H51T 1Hs5 d;0 d;+0 H;0 g;0 1d5 >1d 1H; g>1 ;0dK +d;0K H0T;", +" T;g0 dj1; 1d>j H;1T s>g1 0N !0N 0BN a0N 1N 18N 1NB 1aN Q0 Q!0 QT0 Qa0 1Q 1", +"Q8 1QT s1Q 0(N +0N 0(NB a0+N 1(N 1+N (B1N +a1N Q0( +Q0 T0Q( +0Qa 1Q( 1+Q QT", +"1( 1+sQ W0 W!0 HW0 Wa0 1W 1W8 1HW 1Wa WQ0 W0Q! Z0 Za0 1WQ W81Q Z1 sZ1 Wd0 +", +"W0 WdH0 gW0 1Wd 1+W HW1d g1W Qd0 +0Qd Zd0 gZ0 1Qd +W1Q Z1d gZ1 m0 m0! m0B a", +"m0 1m 1m8 1mB 1am Qm0 m0Q! Tm0 Q0am p1 p18 p1T sp1 m;0 +m0 ;0mB +0am 1m; >m", +"1 m;1B 1a>m Q;0 +0Q; Q0T; +0Tm p1; p>1 1Tp; s1p> Wm0 m0W! Hm0 H0am 1W5 W81m", +" 1Hm H81m QmW0 Q!Wm0 Zm0 amZ0 p1W 1Wp8 Zp1 Z1sp v0 v+0 vH0 gv0 v1 v>1 v1H g", +"v1 vQ0 +Qv0 Zv0 g0Zv pv1 v1p> Zv1 y1 9 9& 9B 9a 91 : 91B :a 9K 9&K 9T 9Ta 9", +"j :j 9T1 s: 9( 9+ 9(B 9+a 91( :+ 1B9( :+a 9(K 9+K 9T( 9+T 9j( :+j 9(1T s:+ ", +"9E 9&E 9H 9Ha 91E :E 9H1 :H 9EK &E9K 9HT H&9T 9jE :jE 9Hj s:H 9d 9+d 9Hd g9", +" 9d1 :d 1H9d g: 9dK 9Kd& 9Td g9T 9dj :dj 1T9d g:s 92 9&2 92B 9a2 95 :5 95B ", +":5a 92K &29K 9T2 92T& 95j :5j 95T s:5 9; 9+; 9;B 9a; 95; :> 1B9; :>a 9;K 9K", +";& 9T; +T9; 9;j :>j 1T9; s:> 9E2 &E92 9H2 92H& 95E :5E 9H5 :H5 EK92 9&E2K H", +"T92 9HT&2 5j9E 5j:E H59T s5:H 9d; d&9; 9H; g9; 95d :>d 1H9; g:> dK9; d&;9K ", +"H;9T 9Tg; 5d9j >j:d H;9j s:g> 9N 9&N 9NB 9aN 91N :N 1B9N :aN 9Q 9Q& 9QT 9Qa", +" 9Q1 :Q 1Q9T s:Q 9(N 9+N (B9N +a9N 1(9N :+N 91(NB +a:N 9Q( 9+Q QT9( +Q9T 9(", +"1Q :Q+ 9Q1T( s+:Q 9W 9W& 9HW 9Wa 9W1 :W 1H9W :HW 9WQ W&9Q Z9 Z9a 9Wj :WQ Z9", +"1 Z: 9Wd 9+W HW9d g9W 1W9d :W+ 9H1Wd g:W 9Qd +W9Q Z9d gZ9 1Q9d :Qd 9dZ1 Z:g", +" 9m 9m& 9mB 9am 95m :m 1B9m :ma 9Qm Q&9m 9Tm Qa9m p9 :p p9T :ps 9m; 9+m m;9", +"B +m9a 1m9; :>m 95;mB :a>m 9Q; +Q9m Q;9T +T9m p9; :p> 9Tp; s>:p 9Wm W&9m 9H", +"m Hm9a 95W :W5 1H9m :Hm WQ9m 9WQm& Z9m 9aZm p9W :pW Zp9 Z:p v9 v9+ v9H gv9 ", +"v91 :v 9Hv1 :vg v9Q 9+vQ Zv9 Zvg9 pv9 :vp pvZ9 y: C0 !C0 D0 Da0 1C 18C 1D 1", +"D8 CK0 !0CK DT0 TaD0 1jC 8j1C 1DT s1D C0( +C0 D0( +D0 1C( 1+C 1D( 1+D 0(CK ", +"CK+0 T0D( DT+0 jC1( 1C+j 1(Dj 1+sD CE0 CE!0 HD0 DaH0 1CE 8C1E 1HD H81D C0EK", +" !E0CK DTH0 HDTa0 jC1E 18jCE Hj1D 1HsD dC0 dC+0 Dd0 gD0 1dC 1C8d 1Dd g1D CK", +"d0 +dC0K D0Td DTg0 1Cdj djC1+ Dd1T s1gD C02 C0!2 D02 D2a0 15C 581C 1D5 5D1a", +" C02K C02!K T2D0 DTa02 5j1C 158jC 5D1T 1Ds5 ;C0 ;C+0 D;0 +0D; 1;C >C1 1D; >", +"D1 CK;0 +;C0K D0T; a;0DT 1C;j 1j>C D;1T s1>D E0C2 C02!E D0H2 HDa02 5C1E 158", +"CE H51D 1H5D8 C02EK EK0!C2 HDT02 DTaH02 15jCE 58j1CE 1H5Dj s1H5D ;Cd0 +d;C0", +" H0D; D;g0 1C5d 1d>C H;1D >Dg1 dK;C0 dK;+C0 H;DT0 gDT;0 djC1; >j1dC 1H;Dj g", +"s>1D C0N C0!N D0N a0DN 1CN 8C1N 1DN 1ND8 QC0 !CQ0 QD0 DaQ0 1QC 1CQ8 1QD 1Qs", +"D 0(CN C0+N 0(DN D0+N C(1N +C1N D(1N 1N+D C0Q( QC+0 D0Q( +0QD QC1( 1C+Q 1(Q", +"D +Q1D WC0 !CW0 WD0 DaW0 1WC 1CW8 1WD WD1a QCW0 Q!WC0 ZD0 DaZ0 1CWj 1WQ8C Z", +"1D sDZ1 dCW0 WC+0 W0Dd WDg0 Wd1C 1C+W WD1d 1WgD dCQ0 +WQC0 DdZ0 ZDg0 1CQd 1", +"+WQC 1DZd gDZ1 mC0 !Cm0 Dm0 D0am 1mC 1C8m 1Dm D81m mCQ0 Q!mC0 Q0Dm am0QD p1", +"C 18pC pD1 s1pD ;Cm0 mC+0 m;D0 +0Dm m;1C 1m>C Dm1; 1D>m ;CQ0 +QmC0 Q0D; +QD", +"m0 1;pC p1>C 1Dp; p1>D mCW0 W!mC0 H0Dm am0WD 1C5W 1W58C Hm1D 1HmD8 WQmC0 Wm", +"CQ!0 DmZ0 ZDam0 1WpC p1W8C pDZ1 Zp1sD vC0 +Cv0 vD0 g0vD v1C >Cv1 v1D vDg1 Q", +"Cv0 v+QC0 Z0vD ZvDg0 pCv1 pv>1C v1pD y1D b9 b9& 9D c9 b1 :b b1D :c b9K 9&bK", +" bT9 c9T b1j :bj b1T s:c b9( b+9 9D( c9+ b1( :b+ b(1D :c+ 9(bK bK9+ b(9T 9+", +"cT b(9j b+:j b(1T s+:c b9E 9&bE bH9 c9H b1E :bE b1H :cH 9EbK b9&EK 9HbT 9Hc", +"T bE9j bj:E 9Hbj :Hsc bd9 9+bd 9Dd gc9 b1d :db 1Hbd g:c bK9d d&Kb9 9Tbd c9g", +"T 9dbj bd:j 1Tbd s:gc b92 9&b2 9D2 c29 b15 :b5 95D :c5 92bK b9&2K b29T 9Tc2", +" 95bj b5:j 95bT c5s: b;9 9+b; 9D; c;9 b1; :>b 1Db; c>: bK9; ;&Kb9 9Tb; 9Tc;", +" 9;bj :b>j 1Tb; s:c> 9Eb2 b9&E2 b29H 9Hc2 bE95 b5:E 9Hb5 c5:H b9E2K 9&EbK2 ", +"bH9T2 c29HT b15jE :b5jE b1H5T :cHs5 9db; d&;b9 9Hb; c;g9 95bd >b:d 1Hb; c>g", +": bd9;K bd9;&K bH;9T c;9gT b1d;j :>bdj b1HT; g:sc> b9N 9&bN 9DN c9N b1N :bN", +" bN1D :cN bQ9 b9Q& 9QD cQ9 b1Q :Qb 1QbT :cQ 9(bN bN9+ D(9N 9+cN 1(bN b+:N b", +"1D(N cN:+ b(9Q 9+bQ 9(QD 9+cQ b(1Q b+:Q b1QD( :+cQ bW9 b9W& 9WD cW9 b1W :Wb", +" 1HbW :cW 9WbQ bW9Q& Zb9 Zc9 9Wbj bW:Q Zb1 Z:c 9Wbd 9+bW WD9d cWg9 1Wbd b+:", +"W b1HWd :Wgc 9Qbd b+W9Q bdZ9 g9Zc 1Qbd bQ:d b1Zd Zcg: bm9 b9m& 9Dm cm9 b1m ", +":mb 1Dbm :cm 9Qbm bQ9m& 9Tbm 9Qcm pb9 :pb p9D cp: 9mb; 9+bm Dm9; 9+cm 1mb; ", +">b:m b1mD; :mc> 9Qb; b+Q9m QD9; 9Qc; b1p; pb:> 9Dp; c>:p 9Wbm bW9m& 9Hbm 9H", +"cm 95bW b5:W 1Hbm c5:W bW9Qm 9WQbm& bmZ9 cmZ9 b1pW pb:W pbZ9 cpZ: vb9 b+v9 ", +"v9D cv9 vb1 :vb b1vD :vc bQv9 vb9+Q vbZ9 Z9cv vbp9 pb:v vbZ1 y:c L !L LB aL", +" L. 8L .BL 8aL M M! TM aM Mj 8M TMj sM (L +L (BL +aL (L. +8L (L.B 8a+L M( +", +"M TM( +TM Mj( +M8 MjT( s+M EL !EL HL HaL EL. 8EL HL. H8L ME ME! HM HMa MjE ", +"8ME HMj sHM dL +dL HdL gL dL. 8dL dLH. g8L dM +Md HMd gM dMj 8dM dMHj gsM L", +"2 !L2 2BL aL2 5L 58L 5BL 5aL M2 M2! TM2 aM2 5M 5M8 5TM s5M ;L +;L ;LB a;L 5", +";L >L ;L5B >La M; +M; T;M aM; 5M; >M T;5M >Ms EL2 EL!2 HL2 aLH2 5EL 8E5L H5", +"L HL5a ME2 !EM2 HM2 H2aM 5ME 5E8M H5M H5sM d;L d;+L H;L g;L 5dL >Ld HL5d g>", +"L dM; +dM; HM; gM; 5dM >Md 5dHM >Mg LN !LN NBL aLN N.L 8LN LBN. aN8L QM Q!M", +" QTM QaM QMj Q8M TMQj sQM (LN +LN (LNB aL+N (LN. 8L+N (BLN. +8aLN QM( +QM T", +"MQ( Qa+M MjQ( Q8+M QTMj( +QsM WL W!L HWL WaL WL. W8L WLH. HLW8 WM WM! ZM Za", +"M WMj W8M ZMj sZM WdL +WL WdHL gWL dLW. +LW8 HWdL. W8gL WMd +WM ZdM gZM dMW", +"j W8+M dMZj sZgM mL mL! mLB amL 5mL 8mL mL5B 5Lam Mm Mm! TmM aMm pM p8M pTM", +" spM m;L +mL ;LmB +Lam m;5L >mL 5m;LB am>L Q;M +Mm MmT; Tm+M pM; >Mp T;pM s", +"p>M WmL mLW! HmL HLam 5WL 5LW8 HL5W HL8m WMm W!Mm ZMm aMZm pWM W8pM ZpM sMZ", +"p vL v+L vHL gvL v5L v>L H5vL >Lgv vM vM+ ZvM gvM pvM >Mv vMZp yM #L &L #BL", +" a&L #L. 8&L #L.B a&8L M# M& TM# T&M Mj# 8M& MjT# sM& #(L +&L #(LB a&+L (L#", +". 8&+L #L.(B +8a&L M#( +M& M#T( T&+M j#M( M&+j TMj#( +Ms& #EL &EL H#L H&L E", +"L#. &E8L #LH. 8&HL M#E M&E HM# HM& j#ME 8EM& MjH# HMs& d#L d&L d#HL g&L #Ld", +". 8Ld& Hd#L. 8&gL dM# dM& H#dM gM& Mjd# d&8M dMjH# sMg& #L2 &L2 #L2B &2aL 5", +"#L 5&L #B5L a&5L M#2 M&2 M#T2 T2M& 5M# 5M& TM5# 5Ms& ;#L ;&L #B;L aL;& ;#5L", +" >&L 5;#LB a&>L M;# M;& T#M; M;T& 5#M; >M& M;#5T sM>& EL#2 EL&2 #LH2 &LH2 #", +"E5L &E5L 5#HL HL5& #EM2 &EM2 M#H2 H2M& M#5E 5EM& H#5M 5MH& ;#dL dL;& ;#HL ;", +"&gL d#5L d&>L H5d#L g&>L d#M; M;d& H#M; M;g& 5#dM dM>& H5Md# >&gM #LN &LN #", +"LNB &LaN #LN. &L8N #LN.B 8a&LN QM# Q&M TMQ# aMQ& MjQ# 8MQ& QTMj# Q&sM (L#N ", +"&L+N #LN(B +a&LN #LN(. +8&LN N.#(BL 8a&+LN M#Q( Q&+M QTM#( +QTM& QMj#( +Q8M", +"& TMjQ#( s+QM& W#L W&L W#HL HLW& #LW. 8&WL HW#L. H8W&L WM# WM& ZM# Z&M MjW#", +" 8MW& MjZ# sMZ& d#WL +LW& HWd#L W&gL Wd#L. d&LW8 Wd#HL. gW8&L W#dM W&+M dMZ", +"# Z&gM dMjW# dM&W8 ZdMj# Z&Mgs m#L m&L #BmL aLm& m#5L 5Lm& 5m#LB am&5L Mm# ", +"Mm& T#Mm MmT& pM# p&M TMp# sMp& ;#mL +Lm& m;#LB am&+L 5m;#L m&>L m;#5BL >ma", +"&L Q#M; M;Q& Mm#T; aMm;& M;p# p&>M pTM;# >Mps& m#WL WLm& m#HL HLm& W#5L 5LW", +"& H5W#L H5&WL W#Mm MmW& MmZ# MmZ& WMp# WMp& pMZ# ZMp& v#L v&L H#vL gLv& 5#v", +"L >Lv& vH5#L gv>&L vM# vM& Z#vM vMZ& p#vM vMp& ZpvM# y&M U U! UD Ua U. U8 U", +"D. U8D UM U!M V Va Uj U8M Vj Vs U( U+ UD( U+D U(. U+8 D(U. +DU8 UM( U+M V( ", +"V+ Uj( U+j Vj( Vs+ UE U!E UH UHa UE. U8E UH. UH8 UME MEU! VH VHa UjE UE8M V", +"Hj VsH Ud U+d UHd gU Ud. U8d U.Dd gU8 UdM +MUd Vd gV Udj +jUd Vdj gVs U2 U!", +"2 UD2 Ua2 U5 U58 U5D U5a UM2 M2U! V2 V2a U5M 5MU8 V5 Vs5 U; U+; U;D Ua; U5;", +" >U 5DU; >UD U;M +MU; V; V+; U;j >MU V5; V> UE2 !EU2 UH2 HaU2 U5E 58UE UH5 ", +"H5U8 MEU2 U!ME2 V2H HaV2 UE5M U58ME V5H sHV5 Ud; +dU; UH; gU; U5d >Ud H5Ud ", +"g>U dMU; dM;U+ Vd; gV; 5dUj Ud>M V5d V>g UN U!N UDN UaN UN. U8N DNU. UND8 U", +"Q UQ! VQ VQa UQj UQ8 VQj VsQ U(N U+N D(UN UN+D N.U( +8UN UD(N. U+D8N UQ( U+", +"Q VQ( V+Q QjU( +QU8 QjV( sQV+ UW UW! UHW UWa UW. UW8 U.WD H8UW UWQ Q!UW VZ ", +"VZa UWj W8UQ VZj sZV UWd U+W WDUd gUW WdU. +WU8 UHWd. UWg8 UQd +WUQ VZd gVZ", +" WjUd +WUj ZjVd sZgV Um Um! UmD Uam U5m U8m 5DUm 5aUm UQm Q!Um Vm Vma pU pU", +"8 Vp Vps Um; U+m DmU; +DUm 5mU; >Um U5Dm; Ua>m UQ; +QUm Vm; V+m pU; p>U Vp;", +" V>p UWm W!Um UHm HmUa U5W 5WU8 H5UW H8Um WMUm Mm!UW VZm ZaVm pUW UWp8 VpZ ", +"sZVp vU vU+ vUH gvU vU5 v>U UHv5 v>gU vUQ U+vM Vv Vvg pvU v>pU Vvp yV bU U&", +" bUD cU bU. b8U UDb. cU8 bM bM& Vb Vc bMj b8M Vbj scV bU( b+U UDb( cU+ U(b.", +" U+b8 bUD(. U+c8 bM( b+M Vb( Vc+ b(Uj U+bj bjV( V+sc bUE U&E bHU cUH UEb. b", +"EU8 b.UH UHc8 bME bEM& VbH VcH bEUj bE8M bHVj sHVc bdU Ud& UHbd gcU b.Ud U8", +"bd bHUd. cUg8 bdM +Mbd Vdb gVc Udbj 8dbM bdVj scgV bU2 U&2 UDb2 c2U b5U U5&", +" bU5D c5U bM2 b2M& V2b Vc2 b5M 5Mb8 V5b c5V b;U U;& bUD; c;U U5b; >bU b5UD;", +" c>U bM; +Mb; V;b c;V U;bj >Mb b5V; V>c UEb2 &EU2 b2UH UHc2 bEU5 UE5& UHb5 ", +"UHc5 MEb2 M&Eb2 bHV2 cHV2 bE5M b5M8E bHV5 cHV5 Udb; d&U; UHb; c;gU U5bd bd>", +"U bH5Ud gUc> dMb; dM&b; bHV; c;gV 5dbM bd>M b5Vd c>gV bUN U&N UDbN cUN UNb.", +" bNU8 bUDN. U8cN bQU UQ& VbQ cQV UQbj UQb8 bQVj VscQ U(bN bNU+ bUD(N U+cN b", +"U(N. b+U8N UD(bN. cU+8N b(UQ U+bQ bQV( V+cQ bQUj( b+QU8 VbQj( cQVs+ bWU UW&", +" UHbW cWU b.UW UWb8 bHUW. UWc8 bWM WMU& ZbV ZcV UWbj W8bM VbZj VZsc UWbd U+", +"bW bHUWd cWgU bWUd. b+WU8 UHWbd. cWUg8 UQbd +WbM VdZb ZcgV bWMdj d&jUW ZbVd", +"j gVZsc bmU Um& bUDm cmU U5bm U8bm b5UDm U5cm bMm Q&Um Vmb cmV pbU pU& Vpb ", +"cpV Umb; U+bm bmUD; U+cm b5Um; bm>U U5Dbm; >Ucm UQb; +Mbm bQV; V+cm bMp; pb", +">M V;pb V>cp UWbm W&Um UHbm UHcm U5bW 5WU& bH5UW U5cW WMbm Mm&bW VmZb VZcm ", +"bWpU UWp& ZbVp VpZc vbU vU& bHvU cvU b5vU >bvU vbUH5 vUc> vbM b+vM Vvb cvV ", +"vbpU vb>M pbVv yVc k k! kB ak 1k 8k 1kB 1ak kM kM! Tk Tka l l8 lT ls k( +k ", +"k(B +ka 1k( 1+k k(1B +k1a kM( +kM Tk( +Tk l( l+ lT( ls+ kE kE! Hk Hka 1kE 8", +"kE 1Hk H8k kME M!kE HkT akHM lE l8E lH lsH dk +kd Hkd gk 1dk 8dk Hk1d g1k d", +"kM dk+M Tdk gkT ld l+d lHd gl k2 k2! k2B ak2 5k 5k8 5kB 5ak kM2 M!k2 Tk2 T2", +"ak l5 l58 l5T ls5 k; +k; k;B ak; 1;k >k 1Bk; >ka k;M k;+M Tk; T;+k l; l> l;", +"T l>s kE2 !Ek2 Hk2 H2ak 5kE 5E8k H5k 5aHk MEk2 kME!2 H2Tk ak2HM l5E 58lE lH", +"5 sHl5 dk; +dk; Hk; gk; 5dk >kd Hk1; >kg k;dM dkM+; TkH; Tkg; ld5 l>d lH; g", +"l> kN kN! kNB akN 1kN 8kN kN1B 1Nak Qk Qk! QkT Qak lQ lQ8 lQT lsQ k(N +kN (", +"BkN +Nak k(1N 1N+k 1k(NB akN1+ Qk( +Qk Q(Tk Qa+k lQ( l+Q QTl( s+lQ Wk Wk! H", +"kW Wak 1Wk W8k Hk1W W8Hk WkQ Q!Wk Zk Zka lW lW8 lZ lZs Wkd +Wk HWdk gkW Wk1", +"d +k1W 1HWdk 1Wgk Qdk Wk+Q Zkd gZk lWd l+W lZd glZ km km! kmB akm 1mk 8km 1", +"Bkm ak1m Qkm Q!km Tkm akTm lp lp8 lpT lsp km; +km m;kB ak+m km1; >km km;1B ", +"ak>m Qk; Qk+m TkQ; Tk+m l;p l>p pTl; spl> Wkm W!km Hkm akHm 5Wk W85k Hk1m W", +"a5k kmWM km!WM Zkm akZm lWp pWl8 lZp splZ vk vk+ vkH gvk v1k >kv 1Hvk gv>k ", +"vkQ +Qvk Zvk Zvgk lv lv> lvZ yl 9k k& 9kB 9ak 91k :k 1B9k :ak 9M 9M& 9Tk 9a", +"M l9 l: l9T ls: 9k( 9+k k(9B +k9a 1k9( :+k 91k(B +k:a 9M( 9+M 9(Tk +T9M l9(", +" l:+ 9Tl( s:l+ 9kE k&E 9Hk Hk& 1k9E :kE 91Hk :Hk 9ME 9EM& 9HM HM9a l9E l:E ", +"lH9 l:H 9dk dk& Hk9d g9k 91dk :dk 9H1dk g:k 9dM +M9d HM9d g9M ld9 l:d 9Hld ", +"gl: 9k2 k&2 k29B 92ak 95k :5k 9B5k 5a:k 9M2 92M& 92Tk 92aM l95 l:5 95lT l5s", +": 9;k k;& 9Bk; ak9; 5k9; >k: k;B95 :a>k 9M; +M9; Tk9; aM9; l;9 l>: 9Tl; s:l", +"> kE92 &Ek2 92Hk H2k& 9E5k 5k:E Hk95 H5:k ME92 k&EM2 92HM 9HM&2 95lE :5lE 9", +"Hl5 l5:H dk9; k;d& Hk9; 9;gk 5k9d :d>k 9H5dk >kg: dM9; dk&M; HM9; 9Mg; 95ld", +" :>ld 9Hl; g:l> 9kN k&N kN9B 9Nak 1k9N :kN 91kNB ak:N 9Qk Qk& Qk9T Qa9M l9Q", +" l:Q 9QlT :Qls k(9N 9N+k 9k(NB akN9+ 91k(N +k:N 1k(9NB :+akN 9(Qk +Q9M 9QTk", +"( 9+QTk 9Ql( :Ql+ l9QT( :Q+ls 9Wk Wk& Hk9W Wk9a 91Wk :Wk 9H1Wk Hk:W 9WM W&9", +"M Z9k Zk& lW9 l:W lZ9 Z:l Wk9d +k9W 9HWdk 9Wgk 9W1dk +W:k 1HW9dk :Wgk WM9d ", +"+W9M 9dZk Z9gk 9Wld :Wl+ Z9ld Z:gl 9mk km& 9Bkm ak9m 5k9m :mk kmB95 ak:m 9M", +"m kmQ& Tk9m aM9m p9l :pl lTp9 ls:p km9; +k9m km;9B akm9+ km;95 :m>k 95;kmB ", +":>akm Qk9; +M9m 9Q;Tk ak;9Q p9l; :pl> l;p9T l>ps: Wk9m kmW& Hk9m kmH& 5k9W ", +"5W:k 9H5Wk Hk:m WM9m km&WM 9MZm kmZ& p9lW lW:p p9lZ lZ:p v9k vk& 9Hvk v9gk ", +"95vk :vk v91Hk gk:v v9M 9+vM v9Zk v9gM lv9 lv: Z9lv yl: Uk U!k Dk Uak 1U 1U", +"8 1UD 1Ua UkM kMU! Vk Vak lU lU8 Vl lsV Uk( U+k Dk( +Dk 1U( 1U+ 1(Dk U+1D k", +"MU( Uk+M Vk( V+k lU( l+U Vl( l+V UkE kEU! UHk HkUa 1UE 1EU8 1UH UH1a kMUE U", +"!kME VHk HkVa lUE U8lE lHV VslH Udk +kUd Ddk gUk 1Ud U+1d UH1d g1U UkdM dkM", +"U+ Vdk gVk ldU U+ld ldV glV Uk2 k2U! Dk2 U2ak 1U5 5kU8 5Dk U51a kMU2 U!kM2 ", +"V2k akV2 lU5 U5l8 Vl5 V5ls U;k +kU; Dk; D;+k 1U; >kU U;1D >kD UkM; k;MU+ V;", +"k +kV; l;U l>U l;V V>l kEU2 U!kE2 U2Hk ak2UH 1EU5 1U58E U51H 1UH5a UkME2 kM", +"EU!2 HkV2 V2Hak U5lE lU58E V5lH lsVH5 dkU; dk;U+ HkU; U;gk U51d 1U>d UH1; g", +"U>k dkMU; U+dk;M HkV; V;gk U5ld >Uld V5ld V>gl UkN kNU! DkN UNak 1UN 1NU8 1", +"NDk 1NUa UQk U!Qk VQk QaVk lUQ UQl8 VlQ lQVs k(UN UN+k k(DN +NDk U(1N 1NU+ ", +"1UD(N 1U+DN U(Qk +kUQ QkV( +QVk UQl( U+lQ VQl( lQV+ UWk U!Wk WDk WkUa 1UW U", +"81W UH1W UW1a WkUQ UWQk! ZkV VaZk lWU UWl8 lZV VlsZ WkUd +kUW DdWk UWgk UW1", +"d U+1W 1UHWd 1UgW QkUd U+WQk VdZk ZkgV UWld U+lW VZld lZgV Umk U!km Dkm akU", +"m 1Um U81m Um1D Ua1m QkUm km!UQ Vmk akVm pUl l8pU Vpl lsVp kmU; +kUm kmD; D", +"k+m Um1; 1U>m 1UmD; Dk>m QkU; U+Qkm QkV; +kVm pUl; pUl> l;Vp Vpl> WkUm km!U", +"W HkUm akmUH U51W 1UW8m UH1m 1UH8m UWQkm UWQkm! VmZk ZkVam pUlW lWpU8 lZVp ", +"VplsZ vUk U+vk vDk vUgk v1U vU>k 1UvD v1gU UQvk vU+Qk Vvk gkVv lvU vUl> lvV", +" ylV t t& tD tc t1 t: t1D t:c tM tM& Vt tcV lt lt: ltV u t( t+ tD( tc+ t1( ", +"t:+ 1Dt( :ct+ tM( t+M Vt( t+V lt( lt+ l(Vt u+ tE t&E tH tcH t1E t:E tH1 t:H", +" tME M&tE tHV VctH ltE lEt: ltH uH td t+d tHd gt td1 t:d 1Htd gt: tdM +Mtd ", +"tdV gtV ltd t:ld tHld ug t2 t&2 tD2 tc2 t5 t:5 t5D tc5 tM2 M&t2 Vt2 V2tc lt", +"5 t5l: t5V u5 t; t+; t;D tc; t5; t> 1Dt; t>c t;M +Mt; t;V Vtc; lt; t>l Vlt;", +" u> tE2 &Et2 tH2 c2tH t5E :5tE tH5 :Ht5 MEt2 tM&E2 V2tH tcVH2 lEt5 t:5lE t5", +"lH uH5 td; d&t; tH; gt; t5d t>d 1Ht; gt> dMt; t+dM; Vdt; t;gV t5ld ldt> tHl", +"; ug> tN t&N tDN tcN t1N t:N 1DtN tN:c tQ tQ& tQV tcQ ltQ t:Q VltQ uQ t(N t", +"+N D(tN c+tN 1(tN :+tN t1D(N t:c+N tQ( t+Q VQt( cQt+ l(tQ tQl+ tQVl( u+Q tW", +" tW& tHW tcW tW1 t:W 1HtW :ctW tWQ WMt& tZ tZc ltW t:lW tZl uZ tWd t+W WDtd", +" gtW 1Wtd :Wt+ tH1Wd tWg: tQd +WtQ tZd gtZ tWld t+lW ldtZ uZg tm tm& tmD tc", +"m t5m t:m 1Dtm :ctm tQm Q&tm tmV cQtm tp tp: tpV up tm; t+m Dmt; cmt+ 1mt; ", +"t>m t5Dm; tmc> tQ; +Qtm Vmt; cQt; tp; tp> t;Vp up> tWm W&tm tHm cWtm t5W :W", +"t5 1Htm :Htm WMtm tWQm& tZm tmZc tpW tW:p tZp uZp tv tv+ tvH gtv tv1 tv: v1", +"tH :vgt tvQ vMt+ tZv cvtZ lvt t>lv tZlv yu ) !) )B a) ). 8) .B) 8a) )K !K) ", +"T) Ta) j) 8j) Tj) s) * +* *B a* *. 8* *B. 8*a *K +*K T* +T* *j +j* T*j s* E", +") !E) H) Ha) E). 8E) H). H8) EK) !)EK HT) TaH) jE) jE8) Hj) sH) d* +d* H* g", +"* d*. 8d* H*. g8* dK* dK+* H*T gT* dj* dj8* H*j gs* )2 !)2 2B) a)2 5) 58) 5", +"B) 5a) 2K) !)2K T)2 T2a) 5j) 8j5) 5T) s5) ;* +;* *B; a;* 5* >* 5*B >*a ;*K ", +";*+K T;* a;T* 5*j >*j 5T* s>* E)2 E)!2 H)2 a)H2 5E) 8E5) H5) H)5a E)2K !)2E", +"K T)H2 HTa)2 jE5) 58jE) H)5T H5s) d;* d;+* H;* g;* 5d* >*d H5* g>* ;*dK +d;", +"*K T;H* T;g* dj5* dj>* 5TH* s*g> )N !)N )BN a)N N.) 8)N )BN. aN8) Q) Q!) QT", +") Qa) Qj) Q8) TjQ) sQ) *N +*N *BN a*N *N. 8*N .B*N aN8* Q* +Q* Q*T Qa* Q*j ", +"Q8* QT*j s*Q W) W!) HW) Wa) W). W8) W)H. H)W8 WQ) W)Q! Z) Za) Wj) W)Q8 Zj) ", +"sZ) W* +W* H*W gW* W*. W8* H.W* W8g* W*Q W*+Q Z* gZ* W*j W*+j Z*j sZ* m) m)", +"! m)B am) 5m) 8m) m)5B 5)am Qm) m)Q! Tm) Q)am p) p8) pT) sp) m* +m* m*B am*", +" 5*m >m* 5m*B am>* Q;* Q*+m Tm* T*+m p* p>* p*T sp* Wm) m)W! Hm) H)am 5W) 5", +")W8 H)5W H)8m QmW) Q!Wm) Zm) amZ) pW) W8p) Zp) s)Zp v* v+* vH* gv* v5* v>* ", +"H5v* >*gv vQ* +Qv* Zv* Z*gv pv* v>p* Zp* y* , ,& ,B ,a ,. ,8 ,.B ,8a ,K ,&K", +" ,T ,Ta ,j ,8j ,Tj s, ,* - *B, -a ,*. -8 ,.*B -8a ,*K -K ,T* -T ,j* -j T*,j", +" s- ,E ,&E ,H ,Ha ,E. ,8E ,H. ,H8 ,EK &E,K ,HT H&,T ,jE ,E&j ,Hj s,H ,d -d ", +",Hd g- ,d. -8d ,.H* g-8 ,dK -dK ,Td g-T ,dj -jd H*,j s-g ,2 ,&2 ,2B ,a2 ,5 ", +",58 ,5B ,5a ,2K &2,K ,T2 ,2T& ,5j 5&,j ,5T s,5 ,; -; ,;B -a; ,5; -> *B,5 ->", +"a ,;K -;K ,T; -T; ,;j ->j 5T,; s-> ,E2 &E,2 ,H2 ,2H& ,5E ,E5& ,H5 H5,8 EK,2", +" ,&E2K HT,2 ,HT&2 5j,E &jE,5 H5,T ,Hs5 ,d; -d; ,H; g-; ,5d ->d H5,d g-> dK,", +"; dK-; H;,T g;-T 5d,j -d>j H;,j g>s- ,N ,&N ,NB ,aN ,N. ,8N .B,N 8a,N ,Q ,Q", +"& ,QT ,Qa ,Qj ,Q8 QT,j s,Q ,*N -N ,N*B -aN *N,. -8N *B,N. 8a-N ,Q* -Q Q*,T ", +"-QT Q*,j -Q8 ,QT*j s-Q ,W ,W& ,HW ,Wa ,W. ,W8 HW,. H8,W ,WQ W&,Q Z, Z&, ,Wj", +" W8,Q Z,j sZ, ,Wd -W H*,W g-W ,.W* -W8 ,HWd. g8-W ,Qd -WQ Z*, Z- W*,j -Wj ,", +"dZj Z-s ,m ,m& ,mB ,am ,5m ,8m 5m,B 5a,m ,Qm Q&,m ,Tm Qa,m p, p&, p,T sp, ,", +"m; -m *B,m -ma 5*,m ->m m*B,5 -a>m ,Q; -Qm Q;,T -Tm p*, -p ,Tp* -ps ,Wm W&,", +"m ,Hm Hm,a ,5W 5W,8 H5,W H8,m WQ,m ,WQm& Z,m ,aZm p,W ,Wp& Zp, Zps, v, -v v", +",H -vg v,5 -v> ,Hv5 g>-v v,Q -vQ Zv, Z-v pv, -pv pvZ, y- C) !C) D) Da) C). ", +"8C) D). D8) CK) !)CK DT) TaD) jC) jC8) Dj) sD) *C +*C D* +D* *C. 8*C D*. D8", +"* *CK *C+K D*T D*+T *jC +C*j D*j s*D CE) CE!) HD) DaH) E)C. CE8) D)H. H)D8 ", +"C)EK CE)!K DTH) HDTa) CEj) 8jCE) H)Dj HDs) d*C d*+C H*D gD* *Cd. d*8C H.D* ", +"D8g* *CdK +d*CK TdD* D*gT dC*j dj*+C D*Hj gDs* C)2 C)!2 D)2 D2a) 5C) 8C5) 5", +"D) 5)D8 C)2K !)2CK T2D) DTa)2 jC5) 58jC) 5)Dj 5Ds) ;*C ;*+C D;* a;D* 5*C >*", +"C 5D* >D* *C;K +;*CK T;D* a;*DT 5C*j *j>C D*5T >Ds* E)C2 CE)!2 D)H2 HDa)2 C", +"E5) 58CE) H)5D H5D8) CE)2K EKC!)2 HDT)2 DTaH)2 5jCE) 8jC5E) H5DT) sH5D) ;*d", +"C +d;*C D;H* D;g* d*5C d*>C 5DH* gD>* dK;*C dK;+*C H;DT* gDT;* dj*5C >*djC ", +"H5*Dj >D*gs C)N C)!N D)N a)DN C)N. C)8N N.D) 8)DN QC) !CQ) QD) DaQ) jCQ) 8C", +"Q) Q)Dj QDs) *CN *C+N D*N +ND* N.*C *C8N *ND. DN8* Q*C +CQ* QD* Q*+D QC*j Q", +"C8* DjQ* QDs* WC) !CW) WD) DaW) C)W. 8CW) D)W. W)D8 QCW) Q!WC) ZD) DaZ) jCW", +") W8QC) DjZ) ZDs) W*C +CW* WD* WDg* *CW. WC8* W.D* D8W* WCQ* +WQ*C Z*D gDZ*", +" WC*j +Wj*C D*Zj sDZ* mC) !Cm) Dm) D)am mC5) mC8) 5)Dm D)8m mCQ) Q!mC) Q)Dm", +" am)QD pC) 8Cp) pD) s)pD m*C +Cm* Dm* D*+m 5Cm* m*>C Dm5* Dm>* QCm* m*C+Q D", +"mQ* am*QD p*C >Cp* pD* pDs* mCW) W!mC) H)Dm am)WD WC5) 5W8C) 5)WD H8mD) WQm", +"C) WmCQ!) DmZ) ZDam) WCp) pW8C) Z)pD ZpDs) v*C +*vC vD* g*vD 5*vC v*>C 5Dv*", +" >*vD Q*vC v+Q*C vDZ* ZvDg* v*pC pv>*C pDZ* y*D ,b ,b& ,D c, ,b. ,8b ,D. c8", +", ,bK bK,& ,DT cT, ,jb b8,j ,Dj sc, b* -b ,D* c- b*. -b8 ,.D* c-8 b*K -bK b", +"T* c-T b*j -jb D*,j s-c ,bE b&,E ,Hb cH, bE,. ,Eb8 ,.bH ,Hc8 bK,E ,b&EK bH,", +"T ,HcT ,Ebj &jE,b bH,j cHs, ,db -bd ,Dd gc- ,.bd b8-d ,.Dd g8c- ,Kbd bd-K b", +"T,d -Tgc bd,j bd-j H*bj gcs- ,b2 b&,2 ,D2 c2, ,5b b5,8 ,5D c5, bK,2 ,b&2K ,", +"2bT ,Tc2 b5,j ,5b&j b5,T c5s, ,;b -b; ,D; c-; b5* ->b 5D,; c>- ,Kb; b;-K bT", +",; -Tc; b;,j >b-j 5Tb* c>s- bE,2 ,b&E2 ,2bH ,Hc2 ,Eb5 ,5b8E bH,5 ,Hc5 ,bE2K", +" bK&,E2 ,HbT2 c2H,T ,5bjE ,5b&jE ,H5bT s,Hc5 bd,; bd-; bH,; c;g- b5,d -d>b ", +"H5b* g-c> ,db;K -bd;K ,H;bT c-Tg; ,5dbj ->bdj ,H;bj s-gc> ,bN b&,N ,DN c,N ", +"bN,. ,Nb8 DN,. ,8cN ,Qb ,bQ& ,QD cQ, bQ,j bQ,8 QD,j cQs, b*N -bN ,ND* c-N *", +"Nb. b8-N ,D*N. -8cN bQ* -Qb QDb* c-Q Q*bj bQ-j ,QD*j cQs- ,Wb ,bW& ,WD cW, ", +",.bW bW,8 ,.WD ,Wc8 bW,Q ,WbQ& Zb, Zc, bW,j ,W8bQ ,DZj s,Zc bW* -Wb H*bW c-", +"W b.W* bW-8 ,WDd. c8-W bQ,d bW-Q Zb* Z-c W*bj bW-j b*Zj Zcs- ,mb ,bm& ,Dm c", +"m, b5,m b8,m 5D,m ,5cm bQ,m ,Qbm& bT,m ,Qcm pb, ,8pb pD, cp, bm* -mb Dm,; c", +"-m 5*bm >b-m ,5Dm* ->cm bQ,; bQ-m QD,; -Qcm pb* -pb ,Dp* cp- bW,m ,Wbm& bH,", +"m ,Hcm b5,W ,5Wb8 5W,D ,5cW ,WbQm bWQ,m& ,DZm cmZ, ,Wpb pbW,8 pbZ, Z,cp vb*", +" -vb vD, cv- ,5vb vb-> ,5vD -vc> ,Qvb vb-Q vbZ* cvZ- vbp* pb-v pbZ* yc- 0) ", +"!0) )B0 a0) 1) 18) 1)B 1a) 0)K 0)!K T0) a0T) 1j) 8j1) 1T) s1) *0 +*0 *B0 a*", +"0 1* 1+* 1*B 1a* *0K *0+K T*0 +0T* 1*j +j1* 1T* s*1 E0) E0!) H0) a0H) 1E) 8", +"E1) 1H) 1)H8 0)EK !E)0K T0H) HTa0) jE1) 18jE) 1)Hj 1Hs) d*0 d*+0 H*0 g*0 1d", +"* 8d1* 1H* g1* *0dK +d*0K H0T* T*g0 dj1* dj*1+ H*1T s*g1 0)2 0)!2 0)2B 0)a2", +" 15) 581) 5B1) 1)5a 0)2K 0)2!K 0)T2 Ta0)2 5j1) 158j) 1)5T 15s) ;*0 ;*+0 ;0*", +"B ;*a0 1;* >*1 *B1; 1a>* *0;K +;*0K ;*T0 a;*T0 ;j1* 1*>j 5T1* s1>* 0)E2 0)2", +"!E 0)H2 Ha0)2 5E1) 158E) 1)H5 1H58) 0)2EK EK0!)2 HT0)2 Ta0H)2 15jE) 58j1E) ", +"1H5T) s1H5) ;*d0 +d;*0 ;*H0 ;*g0 5d1* 1d>* H51* >*g1 dK;*0 dK;+*0 H;T*0 gT;", +"*0 dj*1; >*1dj 1H;T* s*1g> 0)N 0)!N 0)NB 0)aN 1)N 8)1N )B1N a)1N Q0) !0Q) T", +"0Q) a0Q) 1Q) 1)Q8 QT1) 1Qs) *0N *0+N 0B*N *0aN 1*N 1N8* 1N*B 1Na* Q*0 +0Q* ", +"Q0T* Q0a* 1Q* +Q1* Q*1T 1Qs* W0) !0W) W0H) a0W) 1W) 1)W8 HW1) 1)Wa Q0W) Q!W", +"0) Z0) a0Z) 1)Wj 1WQ8) Z1) s)Z1 W*0 +0W* H0W* W*g0 1W* +W1* H*1W 1Wg* W0Q* ", +"+WQ*0 Z*0 g0Z* W*1Q 1+WQ* Z1* Z1s* m0) !0m) )Bm0 m0a) 1m) 1)8m m)1B 1)am m0", +"Q) Q!m0) m0T) am0Q) p1) 18p) 1Tp) p1s) m*0 +0m* m0*B a0m* 1m* 1m>* *B1m am1", +"* Q0m* m*0+Q T0m* am*Q0 p*1 p1>* 1Tp* s1p* m0W) W!m0) m0H) am0H) 1)5W 1W58)", +" 1)Hm 1Hm8) WQm0) Wm0Q!) m0Z) Zam0) 1Wp) p1W8) p1Z) Zp1s) v*0 +*v0 H*v0 v*g", +"0 v1* >*v1 1Hv* g*v1 Q*v0 v+Q*0 v*Z0 Zv*g0 v1p* pv>1* p*Z1 y*1 ,9 ,9& ,9B ,", +"a9 ,1 :, ,1B :a, ,9K 9&,K ,T9 9T,a ,1j :j, ,1T s:, 9* -9 9*B -9a ,1* :- *B,", +"1 :-a 9*K -9K 9T* -T9 9*j :-j 1T9* s-: ,9E 9&,E ,H9 9H,a ,1E :,E ,1H :H, 9E", +",K ,9&EK 9H,T ,H9T& ,E9j ,j:E 9H,j :Hs, ,d9 -9d 9H* g-9 ,1d :-d 1H,d g:- ,K", +"9d 9d-K 9T,d -Tg9 9d,j -j:d 1T,d s-g: ,92 9&,2 92,B ,29a ,15 :5, ,B95 ,5:a ", +"92,K ,9&2K ,29T ,T9&2 95,j ,5:j 95,T :5s, ,;9 -9; *B9; 9a-; ,1; :-> *B95 :a", +"-> ,K9; 9;-K 9T,; 9T-; 9;,j -j:> 1T,; :-s> 9E,2 ,9&E2 ,29H ,H9&2 ,E95 ,5:E ", +"9H,5 ,H:5 ,9E2K 9&E,2K ,H9T2 9HT,a2 ,15jE :5j,E ,1H5T s,H:5 9d,; 9d-; 9H,; ", +"-9g; 95,d ->:d 1H,; :-g> ,d9;K -9d;K ,H;9T -T9g; ,1d;j :->dj ,1HT; g:s-> ,9", +"N 9&,N 9N,B ,N9a ,1N :,N 1N,B ,a:N ,Q9 ,9Q& 9Q,T 9Q,a ,1Q :Q, 1Q,T :Qs, 9*N", +" -9N 9N*B 9a-N ,N1* :-N ,1*NB -a:N 9Q* -Q9 Q*9T 9Q-T 1Q9* :-Q ,1QT* :Qs- ,W", +"9 ,9W& 9H,W 9W,a ,1W :W, 1H,W ,H:W 9W,Q ,W9Q& Z9, ,aZ9 9W,j ,W:Q Z1, Z:, 9W", +"* -W9 H*9W -Wg9 1W,d :-W ,1HW* :Wg- 9Q,d 9W-Q Z9* Z-9 1Q,d -W:Q ,1Z* Z:- ,m", +"9 ,9m& ,B9m 9a,m ,1m :m, ,B1m ,a:m 9Q,m ,Q9m& 9T,m ,Qa9m p9, :p, ,1pT s,:p ", +"9m* -m9 *B9m 9a-m 1m,; :-m ,1m*B :a-m 9Q,; 9Q-m Tm9* 9T-m p9* -p: 9Tp* :ps-", +" 9W,m ,W9m& 9H,m ,Hm9a 95,W ,5:W 1H,m ,H:m ,W9Qm 9WQ,m& ,mZ9 Z9a,m ,1pW p,:", +"W p9Z, Z,:p v9* -v9 ,Hv9 g9-v v1, :v- ,1vH -vg: ,Qv9 v9-Q v9Z* Z9-v v9p* -p", +":v p9Z* y:- C0) C0!) D0) a0D) 1C) 8C1) 1D) 1)D8 0)CK C0)!K T0D) DTa0) jC1) ", +"18jC) 1)Dj 1Ds) *C0 *C+0 D*0 +0D* 1*C 1C8* 1D* +D1* CK*0 +*C0K D0T* a*0DT 1", +"C*j *jC1+ D*1T 1Ds* E0C) C0)!E D0H) HDa0) CE1) 18CE) HD1) 1HD8) C0)EK EK)!C", +"0 HDT0) DTaH0) 1jCE) 8jC1E) 1HDT) s1HD) *Cd0 +d*C0 H0D* D*g0 d*1C 1+d*C H*1", +"D 1Dg* dK*C0 dK*+C0 H*DT0 gDT*0 dj*1C 1+d*jC 1H*Dj s*1gD 0)C2 C02!) 0)D2 Da", +"0)2 5C1) 158C) 1)5D 1D58) C02)K 2K!C0) DT0)2 Ta0D)2 15jC) 58j1C) 1D5T) s15D", +") *C;0 +;*C0 ;*D0 a;*D0 1C5* 1*>C 5D1* 1D>* ;*C0K ;*C+0K D;T*0 D;Ta*0 ;jC1*", +" >*1jC 1D;T* >D*s1 C02E) !E)C02 HD0)2 Da0H)2 15CE) 58C1E) 1H5D) H5D1a) EKC0", +")2 0)C2EK! DT0H)2 0)T2HDa 5jC1E) 5C1)8jE H5D1T) 1H5sD) d;*C0 d;*+C0 H;D*0 g", +"D;*0 1d5*C >*1dC 1H;D* >D*g1 ;*CdK0 dK+*;C0 D;TH*0 D;Tg*0 1d5*jC dj*>C1 H;j", +"1D* gs1>D* 0)CN C0N!) 0)DN Da0)N C)1N 18C)N D)1N 1D8)N C0Q) Q!C0) D0Q) QDa0", +") QC1) 1Q8C) 1)QD s1QD) C0*N +*C0N *0DN a*0DN *C1N 1+*CN 1ND* 1+D*N *CQ0 +Q", +"*C0 Q0D* +QD*0 1CQ* 1+Q*C QD1* s*1QD C0W) W!C0) D0W) WDa0) WC1) 1W8C) 1)WD ", +"1WD8) WQC0) WC0Q!) D0Z) ZDa0) 1WQC) W8C1Q) 1DZ) Z1Ds) *CW0 +W*C0 W0D* gWD*0", +" 1CW* 1+W*C WD1* g1DW* W*QC0 W*C+Q0 D*Z0 Z*Dg0 1W*QC *jC1+W 1DZ* Z1*gD C0m)", +" mC0!) m0D) am0D) mC1) 1m8C) 1)Dm 1Dm8) QmC0) mC0Q!) QDm0) QD0am) 1Cp) p18C", +") 1Dp) pD1s) *Cm0 m*C+0 D0m* am*D0 1Cm* >m1*C Dm1* >Dm1* m*CQ0 +QCm*0 QD;*0", +" am0QD* 1*pC p>1*C 1Dp* p>D1* WmC0) mC0W!) HmD0) WD0am) 1W5C) W8C1m) 1HmD) ", +"am)1WD QmCW0) QCW0m)! ZDm0) am0ZD) p1WC) 1W8pC) Zp1D) sZ1pD) *Cv0 v+*C0 D*v", +"0 gvD*0 1*vC v>1*C 1Dv* gv1D* vQ*C0 +Q*vC0 ZvD*0 gvDZ*0 pv1*C v>1p*C Zp*1D ", +"1Dy* ,b9 b9,& ,D9 c9, ,1b :b, ,1D :c, b9,K ,b9&K 9D,T ,Tc9 b1,j ,j:b b1,T :", +"cs, b*9 -b9 9D* c-9 b1* :-b 1Db* :c- bK9* b9-K 9Tb* c9-T 9*bj :b-j 1Tb* :cs", +"- b9,E ,b9&E 9H,D ,Hc9 ,Eb1 ,b:E b1,H cH:, ,b9EK b9&,EK ,H9bT c9H,T ,1bjE :", +"bj,E ,1HbT s,H:c 9db* bd-9 9Hb* c-g9 b1,d -b:d 1Hb* :cg- ,db9K -b9dK ,Dd9T ", +"c-9gT ,1dbj :-bdj ,1DTd g:sc- b9,2 ,b9&2 ,29D ,9c2 b1,5 ,5:b 95,D :,c5 ,b92", +"K b9&,2K ,D9T2 c29,T ,1b5j :b5,j ,1D5T s,5:c 9;b* b;-9 9D,; -9c; b1,; >b:- ", +"1D,; :-c> ,;b9K -b9;K ,D;9T c-9T; ,1;bj :->bj ,1DT; s-:c> ,b9E2 b9&,E2 ,H9b", +"2 c29,H ,1b5E :b5,E ,1Hb5 :cH,5 b9E,2K b9,&EK2 bH9,T2 ,H9c2T b15,jE ,5b:jE ", +"b1H,5T :cHs,5 ,db9; -b9d; ,H;9D c-9g; ,1db5 :->bd ,1Hb; g:c-> bd9,;K bd9-;K", +" 9H;bT* -T9gc; b1d,;j ->b:dj b1H,T; s-cg:> b9,N ,b9&N ,N9D ,9cN ,Nb1 ,b:N ,", +"N1D cN:, ,b9Q ,Qb9& 9Q,D ,Qc9 b1,Q ,Q:b 1Q,D :,cQ bN9* b9-N 9ND* -9cN bN1* ", +"-b:N ,1D*N cN:- 9Qb* bQ-9 QD9* c9-Q 1Qb* :b-Q ,1QD* c-:Q ,b9W ,Wb9& 9W,D ,W", +"c9 b1,W ,W:b 1W,D :,cW ,Wb9Q bW9,Q& ,DZ9 c9Z, ,1WbQ :Wb,Q ,1Zb :cZ, 9Wb* bW", +"-9 WD9* c9-W 1Wb* :b-W ,1WDd c-:W ,Qdb9 -Wb9Q b*Z9 c-Z9 ,1Qbd :-WbQ b1Z* :c", +"Z- ,b9m ,mb9& 9D,m ,mc9 b1,m ,m:b 1D,m :,cm ,Qb9m bQ9,m& ,QD9m cQ9,m ,1pb :", +"bp, ,1pD p,:c 9mb* bm-9 Dm9* c9-m 1mb* :b-m ,1Dm* c-:m ,Q;b9 -Qb9m ,QD9; c-", +"Q9m b1p* pb:- 9Dp* :c-p ,Wb9m bW9,m& ,Hm9D cW9,m ,1Wb5 :Wb,5 ,1Hbm :cW,5 bW", +"9,Qm WQ9m,b& Zb9,m Zc9,m pb9,W :pb,W Zpb,1 cpZ:, b*v9 -bv9 ,Dv9 v9c- ,1vb v", +"b:- ,1vD :c-v vb9,Q -vb9Q Zvb9* cvZ-9 pvb,1 :v-pb Zpb9* :cy- )L !)L )BL a)L", +" )L. 8)L )L.B a)8L M) M)! TM) aM) Mj) 8M) MjT) sM) *L +*L *BL a*L *L. 8*L .", +"B*L 8La* M* +M* T*M aM* M*j 8M* TM*j s*M E)L E)!L H)L a)HL )LE. E)8L )LH. 8", +")HL ME) !EM) HM) H)aM jEM) ME8) MjH) HMs) d*L d*+L H*L g*L *Ld. d*8L *LH. 8", +"*gL dM* +dM* HM* gM* M*dj dM8* M*Hj s*gM )L2 )L!2 )L2B )La2 5)L 8)5L )B5L a", +")5L M)2 !)M2 M)T2 M2a) 5M) 5)8M TM5) 5Ms) ;*L ;*+L ;L*B ;*aL 5*L >*L 5L*B a", +"*>L M;* +;M* M;T* M;a* 5M* >M* T*5M s*>M )LE2 !)2EL )LH2 Ha)L2 E)5L 58E)L 5", +")HL H58)L E)M2 ME)!2 M)H2 aM)H2 ME5) 5M8E) H)5M sH5M) ;*dL +d;*L ;*HL ;*gL ", +"d*5L d*>L HL5* g*>L d;M* dM;+* M;H* M;g* dM5* dM>* 5MH* >*gM )LN )L!N )LNB ", +")LaN )LN. )L8N .BL)N 8a)LN QM) M)Q! TMQ) Q)aM MjQ) Q)8M QTMj) QMs) *LN *L+N", +" NB*L *LaN N.*L *L8N *BLN. a*L8N Q*M Q*+M QTM* aMQ* QM*j 8MQ* M*jQT Q*sM W)", +"L !)WL W)HL a)WL )LW. 8)WL HW)L. H8W)L WM) M)W! ZM) aMZ) MjW) W)8M MjZ) ZMs", +") W*L +LW* HLW* W*gL *LW. WL8* H*WL. gW8*L WM* W*+M Z*M Z*gM M*Wj 8MW* M*Zj", +" sMZ* m)L !)mL )BmL m)aL m)5L m)8L 5m)LB am)5L Mm) M!m) T)Mm a)Mm pM) 8Mp) ", +"TMp) pMs) m*L +Lm* mL*B aLm* 5Lm* m*>L m*L5B >ma*L Mm* M*+m MmT* Mma* p*M p", +"*>M T*pM sMp* m)WL W!m)L m)HL am)HL W)5L 5W8)L H5W)L H8m)L W)Mm Mm)W! MmZ) ", +"aMmZ) WMp) pW8M) pMZ) ZpMs) v*L +*vL H*vL v*gL 5*vL v*>L vH5*L gv>*L vM* +M", +"v* vMZ* g*vM vMp* >*vM ZMp* y*M ,L ,&L ,LB ,aL ,L. ,8L .B,L 8a,L ,M ,M& ,TM", +" ,aM ,Mj ,8M TM,j s,M ,*L -L ,L*B -aL *L,. -8L *B,L. 8a-L ,M* -M T*,M -TM M", +"*,j -M8 M*j,T s-M ,EL &E,L ,HL ,LH& EL,. 8E,L HL,. ,LH8 ,ME ,EM& ,HM HM,a M", +"j,E ,E8M HM,j ,HsM ,dL -dL ,LH* g-L dL,. 8d-L ,HdL. -8gL ,dM -Md HM,d g-M d", +"M,j 8d-M ,HMdj gMs- ,L2 &L,2 2B,L aL,2 ,5L ,L5& 5B,L ,L5a ,M2 ,2M& TM,2 ,2a", +"M ,5M 5M,8 5T,M ,5sM ,;L -;L ;L,B a;-L ,L5* ->L ,5;LB -a>L ,M; -M; T;,M T;-", +"M 5M,; >M- ,5TM; >Ms- EL,2 ,&EL2 HL,2 ,HaL2 5E,L ,58EL ,LH5 ,H58L ME,2 M&E,", +"2 ,2HM ,HM&2 ,E5M ,5M8E H5,M s,H5M d;,L d;-L ,LH; -;gL ,L5d -d>L ,H5dL >Lg-", +" dM,; dM-; HM,; g;-M 5d,M -d>M ,H5dM g->M ,LN &L,N NB,L aL,N N.,L 8L,N ,LN.", +"B ,8aLN ,QM Q&,M QT,M Qa,M QM,j Q8,M ,QTMj ,QsM *L,N -LN *B,LN aL-N ,*LN. 8", +"L-N ,LN*B. -8aLN Q*,M -QM ,QTM* Qa-M M*j,Q Q8-M ,QTM*j sQ-M ,WL ,LW& HW,L ,", +"LWa WL,. ,LW8 ,HWL. ,H8WL ,WM W&,M Z,M ,aZM WM,j W8,M ,MZj sMZ, ,LW* -WL ,H", +"WdL gL-W ,WdL. W8-L H*L,W. -W8gL WM,d -WM ,dZM Z-M ,WMdj W8-M Z*M,j -MsZ ,m", +"L ,Lm& mL,B ,Lam 5m,L ,L8m ,5mLB ,5amL ,Mm M&,m Tm,M aM,m p,M ,8pM ,TpM sMp", +", ,Lm* -mL m*L,B am-L m*L,5 >L-m ,5Lm*B ->amL Q;,M -Mm Mm*,T Tm-M ,Mp* -pM ", +"p*T,M -Msp Wm,L m&L,W ,LHm ,HmaL ,L5W ,5W8L ,H5WL ,H8mL WM,m Mm&,W ,MZm Z&M", +",m ,WpM p&W,M ZMp, Zp&,M v,L -vL ,HvL gL-v ,5vL >L-v v,H5L -vg>L vM, -vM vM", +"Z, gM-v vMp, >M-v Zp*,M y-M U) U!) UD) Ua) U). U8) D)U. U)D8 UM) M)U! V) Va", +") Uj) U)8M Vj) Vs) U* U+* U*D Ua* U*. U8* U.D* D8U* U*M +MU* V* V+* U*j +jU", +"* V*j s*V UE) !EU) UH) HaU) E)U. 8EU) H)U. U)H8 MEU) U!ME) VH) HaV) jEU) U8", +"ME) HjV) VHs) Ud* +dU* UH* gU* d*U. 8dU* U.H* U8g* dMU* dM*U+ Vd* gV* djU* ", +"U+jd* H*Vj s*gV U)2 !)U2 D)U2 a)U2 U5) 58U) U)5D U)5a M)U2 U!M)2 V2) a)V2 U", +")5M U58M) V5) s)V5 U;* +;U* D;U* a;U* U5* >U* 5DU* Ua>* M;U* M;*U+ V;* a;V*", +" 5MU* U*>M V5* V>* E)U2 U!E)2 H)U2 UHa)2 5EU) U58E) U)H5 UH58) UME)2 ME)U!2", +" H)V2 V2Ha) U5ME) 5MEU8) H5V) VsH5) d;U* U+d;* H;U* U;g* 5dU* Ud>* H5U* >*g", +"U dM;U* U+dM;* H;V* g;V* U5dM* >MUd* H5V* V*g> U)N !)UN D)UN a)UN N.U) 8)UN", +" UD)N. U8D)N UQ) U)Q! VQ) QaV) QjU) U)Q8 QjV) VQs) U*N +*UN UND* UNa* *NU. ", +"UN8* U*DN. U8*DN UQ* +QU* V*Q +QV* Q*Uj Q8U* Q*Vj sQV* UW) W!U) U)WD U)Wa W", +")U. U)W8 UHW). UH8W) U)WM UWQ!) VZ) VaZ) U)Wj UW8Q) VjZ) s)VZ UW* +WU* H*UW", +" UWg* U.W* W8U* UH*W. gUW8* WMU* U+WQ* Z*V Z*gV W*Uj U+W*j ZjV* VZs* Um) m)", +"U! U)Dm U)am 5mU) U)8m U5Dm) U5am) U)Mm Mm)U! Vm) amV) pU) U8p) Vp) s)Vp Um", +"* +mU* DmU* amU* 5*Um Um>* U5*Dm >DmU* Q;U* Mm*U+ Vm* +mV* pU* >Up* Vp* s*V", +"p WmU) UWm!) U)Hm UHma) U)5W U5W8) UH5W) UH8m) Mm)UW UW)Mm! Z)Vm VZam) UWp)", +" pUW8) Z)Vp VpZs) vU* U+v* UHv* g*vU U5v* >*vU vUH5* gvU>* UQv* vU+Q* Vv* V", +"*gv vUp* >MvU* Z*Vp yV* ,U ,U& ,UD cU, ,U. ,U8 UD,. ,Uc8 ,UM U&,M V, Vc, ,U", +"j b8,M V,j s,V ,U* -U U*,D c-U ,.U* -U8 ,UD*. c8-U bM* -UM V*b V- U*,j -Uj ", +",jV* V-s ,UE ,EU& ,UH ,UcH UE,. ,EU8 ,.UH UH,8 ,EbM M&E,U V,H cHV, ,EUj ,U8", +"ME ,HVj sHV, ,Ud -Ud UH,d g-U ,.Ud U8-d ,UHd. g8-U bd,M bd-M Vd, V-g Ud,j U", +"d-j ,dVj s-gV ,U2 ,2U& UD,2 ,Uc2 ,U5 U5,8 U5,D ,Uc5 ,2bM M&2,U V,2 c2V, b5,", +"M ,U58M V5, V5s, ,U; -U; U;,D -Uc; U5,; ->U ,U5D; -Uc> bM,; bM-; V;, V-; U;", +",j -U>M ,5V; V-> UE,2 ,U&E2 ,2UH c2U,H ,EU5 ,U58E UH,5 c5U,H ,UME2 ,UEM&2 ,", +"HV2 VcH,2 ,U5ME M&E,U5 ,HV5 s,VH5 Ud,; Ud-; UH,; g;-U U5,d -d>U ,UH5d ->gU ", +",UdM; -UdM; ,HV; V;g- ,U5dM >M-bd ,5Vd g-V> ,UN ,NU& UD,N ,UcN UN,. ,NU8 ,U", +"DN. cU8,N ,UQ U&,Q V,Q V,cQ UQ,j UQ,8 ,QVj sQV, ,NU* -UN ,UD*N cN-U ,U*N. U", +"8-N U*N,D. c-U8N UQb* -UQ ,QV* V-Q ,UQ*j UQ-j V*bQj -QVs ,UW U&,W UH,W ,UcW", +" ,.UW UW,8 ,UHW. cWU,8 bW,M ,UWQ& Z,V VcZ, UW,j ,UWQ8 ZjV, VZs, UW,d -UW ,U", +"HW* -UcW ,UWd. UW-8 ,U.WD* c-WU8 UQ,d bW-M VdZ, Z-V ,UWdj UW-j Zb*Vj sZV- ,", +"Um U&,m Um,D ,Ucm U5,m U8,m ,U5Dm c5U,m bM,m Mm&,U Vm, V,cm pU, ,Up& Vp, s,", +"Vp Um,; -Um ,UmD; -Ucm ,U5m* >U-m U5*,Dm c>-Um UQ,; bM-m ,QV; V-m ,Up* -pU ", +"V*pb V-p UW,m ,UWm& UH,m cWU,m U5,W ,U5W8 ,UH5W c5W,U ,UWMm ,UWMm& VmZ, ZcV", +",m ,UpW pU&,W Z,Vp cpZV, vU, -vU ,UvD gU-v ,Uv5 v>-U vU,H5 cv->U ,UvM vb-M ", +"Vv, V-v vUp, pv-U V,pv yV- k) k)! k)B ak) 1k) 8k) k)1B 1)ak kM) M!k) Tk) T)", +"ak l) l8) lT) ls) k* +k* k*B ak* 1*k 8k* 1k*B ak1* k*M k*+M Tk* T*+k l* l+*", +" l*T ls* kE) !Ek) Hk) H)ak kE1) kE8) 1)Hk H)8k MEk) kME!) H)Tk ak)HM lE) 8E", +"l) lH) sHl) dk* +dk* Hk* gk* dk1* dk8* Hk1* 1*gk k*dM dkM+* TkH* Tkg* ld* 8", +"dl* lH* gl* k)2 !)k2 2Bk) k2a) 5k) 5)8k k)5B 5)ak M)k2 kM)!2 k)T2 ak)T2 l5)", +" 58l) 5Tl) s5l) k;* +;k* *Bk; k;a* 5k* >k* *B5k ak>* M;k* k;M+* k;T* ak;T* ", +"l;* l>* 5Tl* s>l* E)k2 kE)!2 k)H2 ak)H2 kE5) 5k8E) H)5k H5k8) kME)2 ME)k2! ", +"HkT)2 Hk)aM2 5El) l58E) H5l) lsH5) d;k* dk;+* k;H* k;g* dk5* dk>* 5kH* >*gk", +" dkM;* +kdM;* Hk;T* gkT;* 5dl* >*ld H5l* g>l* k)N !)kN )BkN k)aN k)1N kN8) ", +"1k)NB ak)1N Qk) k)Q! Q)Tk Q)ak lQ) Q8l) QTl) sQl) k*N +Nk* kN*B aNk* 1Nk* k", +"N8* k*N1B ak*1N Qk* Q*+k TkQ* akQ* l*Q +Ql* Q*lT lQs* Wk) k)W! H)Wk W)ak 1)", +"Wk W)8k 1HWk) 1Wak) W)Qk WkQ!) Zk) akZ) lW) W8l) lZ) l)sZ Wk* W*+k WkH* Wkg", +"* Wk1* 8kW* 1H*Wk g1Wk* QkW* +WkQ* Zk* Z*gk lW* +Wl* lZ* l*gZ km) k!m) m)kB", +" a)km 1)km 8)km km)1B akm1) Q)km km)Q! T)km akmQ) lp) p8l) pTl) l)sp km* k*", +"+m *Bkm kma* km1* km>* km*1B >kam* kmQ* km*+Q kmT* akmQ* l*p p>l* lTp* spl*", +" W)km km)W! H)km akmH) 5)Wk 5Wk8) 1Hmk) H8km) km)WM Wk)Mm! kmZ) Zkam) pWl) ", +"lWp8) l)Zp lZps) vk* +kv* Hkv* g*vk 1*vk >*vk v1Hk* >kgv* Qkv* vk+Q* vkZ* Z", +"vkg* lv* v>l* Zpl* yl* ,k ,k& ,kB ,ak ,1k :k, 1k,B ,a:k ,kM k&,M ,Tk 9a,M l", +", l:, l,T ls, ,k* -k *B,k -ka 1*,k :-k k*B,1 :a-k 9M* -kM Tk9* -Tk l*9 l- ,", +"Tl* l-s ,kE ,Ek& ,Hk Hk,a 1k,E ,k:E 1H,k ,H:k ,E9M k&E,M 9H,M ,HkT& l,E :,l", +"E lH, s,lH ,dk -kd Hk,d g-k 1d,k -k:d ,1Hdk :-gk 9d,M 9d-M HM9* -Tgk ld, l-", +"d ,Hld gl- ,k2 ,2k& k2,B ,2ak ,5k ,5:k ,B5k 5a,k ,29M k&2,M ,2Tk ,Tk&2 l,5 ", +":5l, ,5lT l5s, ,k; -k; ,Bk; ak-; 1;,k >k- ,1;kB -a>k 9M,; 9M-; Tk,; Tk-; l;", +", l-> ,Tl; s-l> kE,2 k&E,2 ,2Hk ,Hk&2 ,E5k :5k,E H5,k :H5,k ,kME2 ,kEM&2 ,H", +"kT2 ak2,HM ,5lE l:5,E ,Hl5 ls,H5 dk,; dk-; Hk,; g;-k 5d,k -d>k ,1Hk; g->k ,", +"dkM; -kdM; ,HkT; -Tkg; ,5ld ->ld ,Hl; g-l> ,kN ,Nk& kN,B ,Nak 1k,N ,k:N ,1k", +"NB :ak,N ,Qk Q&,k Qk,T Qa,k l,Q :Ql, ,QlT lQs, ,Nk* -kN k*N,B ak-N k*N,1 :N", +"-k ,1Nk*B :-akN Qk9* -Qk ,QkT* Qa-k ,Ql* l-Q l*9QT -Qls ,Wk W&,k Hk,W Wa,k ", +"1W,k ,W:k ,1HWk :HW,k 9W,M ,WkQ& Zk, ,aZk lW, :Wl, lZ, l,Z: Wk,d -Wk ,HkW* ", +"-Wgk ,1Wdk -k:W 1H*,Wk g:-Wk WM9* 9W-M ,dZk Z-k ,Wld l-W Z9l* l-Z ,km k&,m ", +",Bkm ak,m 1m,k ,k:m ,1mkB :ma,k 9M,m km&,Q Tk,m akm,Q l,p l,:p lTp, spl, km", +",; -km km*,B ak-m km*,1 -k:m kmB,1; :-mak Qk,; 9M-m km*,T Tk-m p9l* l-p l;,", +"pT ls-p Wk,m km&,W Hk,m akm,H 5W,k :W5,k ,1Hkm :Hm,k ,WkMm ,WkMm& ,kZm Zk&,", +"m p,lW :pl,W Zpl, lZ,:p vk, -vk ,Hvk gk-v ,1vk >k-v v1,Hk :v-gk ,Qvk v9-M v", +"kZ, Zk-v lv, l-v Zvl, yl- Uk) k)U! Dk) U)ak 1U) 1)U8 1)Dk 1)Ua kMU) U!kM) V", +"k) akV) lU) U8l) Vl) l)Vs U*k +kU* Dk* D*+k 1U* U+1* U*1D Ua1* UkM* k*MU+ V", +"*k +kV* l*U U+l* l*V Vls* kEU) U!kE) U)Hk ak)UH UE1) 1U8E) 1)UH 1UH8) UkME)", +" kMEU!) HkV) VHak) UEl) lU8E) VHl) lsVH) dkU* dk*U+ HkU* U*gk Ud1* 1U+d* UH", +"1* 1Ug* dkMU* U+dk*M HkV* V*gk Udl* l+Ud* Vdl* l*gV k)U2 U!k)2 k)D2 ak)U2 1", +")U5 1U58) 5)Dk 1Ua5) UkM)2 kM)U!2 k)V2 V2ak) U5l) lU58) l)V5 lsV5) k;U* k;*", +"U+ k;D* ak;U* U51* 1U>* Dk5* Dk>* k;MU* U+kM;* k;V* V+k;* U5l* >Ul* V5l* l*", +"V> UkE)2 kE)U!2 UHk)2 UH)ak2 1U5E) 5kEU8) 1UH5) ak)UH5 kMEU)2 !)k2UME V2Hk)", +" ak)V2H lU5E) U58lE) Vl5H) Vs5lH) dk;U* U+dk;* UH;k* gUk;* 1Ud5* >kUd* 1UH5", +"* >kgU* UdkM;* dkU;+M* Vdk;* gVk;* ldU5* l>Ud* lH;V* V>lg* k)UN U!k)N k)DN ", +"ak)UN U)1N 1U8)N 1UD)N 1Ua)N U)Qk UQk!) QkV) VQak) UQl) lUQ8) VQl) lsVQ) UN", +"k* k*NU+ DNk* ak*UN 1NU* 1U+*N 1U*DN 1Ua*N QkU* U+Qk* QkV* V+Qk* UQl* l+UQ*", +" lQV* s*VlQ U)Wk UWk!) W)Dk UWak) 1)UW 1UW8) 1UHW) 1UWa) UWQk) Wk)UQ! VkZ) ", +"ZkVa) UWl) lWU8) l)VZ lZVs) WkU* U+Wk* DkW* gUWk* UW1* 1U+W* 1UHW* g1UW* UW", +"*Qk +WkUQ* V*Zk gVZk* UWl* l+WU* VlZ* glZV* U)km km)U! D)km akmU) 1)Um 1Um8", +") 1UmD) 1Uam) km)UQ UQ)km! kmV) Vmak) l)pU pUl8) l)Vp Vpls) kmU* km*U+ kmD*", +" akmU* Um1* >kUm* km*1D >kDm* km*UQ U+Qkm* kmV* V+mk* pUl* l>pU* l*Vp V>lp*", +" km)UW UW)km! UHmk) ak)UHm 1UW5) km)UW8 1UHm) ak)U5W UWQkm) W)QkUm! ZkVm) V", +"maZk) lWpU) pU8lW) VplZ) lZsVp) U*vk vU+k* Dkv* gvUk* 1Uv* >kvU* v1UH* >kvD", +"* vUQk* U+Qvk* vkV* Vvgk* vUl* lv>U* l*Vv l*yV t, t&, tD, tc, t1, t:, ,1tD ", +"t,:c tM, ,Mt& Vt, V,tc lt, t:l, l,V u, t* t- t*D t-c t*1 t-: 1Dt* :ct- t*M ", +"t-M t*V V-t lt* l-t Vlt* u- t,E ,&tE tH, cHt, ,1tE :,tE ,1tH t,:H ,MtE tM&,", +"E V,tH tcV,H t,lE t:,lE tHl, uH, td* t-d tH* gt- ,1td :-td 1Ht* t-g: ,dtM -", +"Mtd Vdt* V-gt tdl* ldt- tHl* ug- t,2 ,&t2 ,Dt2 c2t, t5, :5t, ,5tD t,c5 ,Mt2", +" tM&,2 t,V2 tcV,2 t5l, t:5l, V5l, u5, t;* t-; ,Dt; c-t; t5* t>- 5Dt* c>t- ,", +"Mt; -Mt; V;t* t;V- t5l* t>l- V5t* u-> ,Et2 t&,E2 ,Ht2 tcH,2 ,5tE t:5,E ,Ht5", +" t:H,5 tM,E2 M&Et,2 tHV,2 Vc,tH2 t5,lE l:,t5E tH5l, ,Hu5 ,dt; -dt; ,Ht; t;g", +"- ,5td ->td H5t* g-t> tdM,; t-dM; tH;V* V-gt; t5dl* l-t>d tH5l* g-u> t,N ,&", +"tN ,DtN c,tN ,1tN :,tN t1D,N t:c,N tQ, ,Qt& V,tQ t,cQ tQl, t,:Q lQV, uQ, t*", +"N t-N D*tN tNc- 1*tN tN:- t*1DN t-:cN tQ* t-Q V*tQ tQV- tQl* tQl- tQ*Vl u-Q", +" tW, ,Wt& ,HtW t,cW ,1tW t,:W tH1,W t:H,W ,WtQ tWQ,& tZ, Z,tc tWl, t:Wl, l,", +"tZ uZ, tW* t-W H*tW tWg- 1Wt* :-tW tH*1W t-Wg: ,Qtd -WtQ tZ* tZ- tWl* lWt- ", +"l*tZ uZ- tm, ,mt& ,Dtm t,cm ,1tm t,:m t5D,m t:mc, ,Qtm tQm,& V,tm tcQ,m tp,", +" p,t: l,Vp up, tm* t-m Dmt* c-tm 1mt* :-tm t5*Dm t-mc> ,Qt; -Qtm Vmt* tmV- ", +"tp* tp- t*Vp up- ,Wtm tWm,& ,Htm tcW,m ,5tW t:W,5 tH5,W t:H,m tWQ,m Mm&tW, ", +"Z,tm tZc,m p,tW tp:,W Z,tp Zpu, tv* tv- vDt* t-cv v1t* t-:v tv1,H gtv:- vMt", +"* tQ-v t*Vv Z-tv l*tv tvl- l,Vv yu- F !F FB aF F. 8F .BF 8aF FK !KF TF TaF ", +"jF 8jF TjF sF (F +F (BF +aF (F. +8F (F.B 8a+F (FK +FK T(F +TF j(F +jF j(TF ", +"s+F G G! GH Ga G. G8 GH. G8H GK GK! GT GTa Gj G8j GTj sG Gd +G GHd gG Gd. +", +"G8 HdG. gG8 GdK +GK GTd gGT Gjd +Gj TdGj gsG F2 !F2 2BF aF2 5F 58F 5BF 5aF ", +"2KF !F2K TF2 T2aF 5jF 8j5F 5TF s5F ;F +;F ;FB a;F 5;F >F ;F5B >Fa ;FK ;F+K ", +"T;F +FT; ;jF >jF 5FT; s>F G2 G2! GH2 Ga2 G5 G58 G5H G5a G2K 2KG! GT2 TaG2 G", +"5j 58Gj G5T sG5 G; +G; G;H gG; G5d >G H5G; g>G G;K GK+; GT; GTg; G;j >Gj H;", +"Gj s>G FN !FN NBF aFN N.F 8FN FBN. aN8F QF Q!F QTF QaF QjF Q8F TjQF sQF (FN", +" +FN (FNB aF+N (FN. 8F+N .BN(F +8aFN Q(F +QF T(QF +FQa j(QF +FQ8 QTj(F +QsF", +" GW W!G GHW GaW GW. G8W HWG. W8Ga GQ GQ! ZG ZGa GQj GQ8 ZGj sZG GWd +GW HWG", +"d gGW WdG. G8+W GHWd. G8gW GQd +GQ ZGd gZG QdGj GQ+j GjZd sGgZ mF mF! mFB a", +"mF 5mF 8mF mF5B 5Fam QmF mFQ! TmF QFam pF p8F pTF spF m;F +mF ;FmB +Fam m;5", +"F >mF 5m;FB am>F Q;F +FQ; QFT; +FTm p;F p>F T;pF >Fsp Gm Gm! GmH Gam G5W G8", +"m H5Gm H8Gm GQm Q!Gm ZGm GaZm pG pG8 ZpG spG vG v+G vGH gvG vG5 v>G G5vH >G", +"gv vGQ +GvQ ZvG gGZv pvG p>G pGZv yG #F &F #BF a&F #F. 8&F #F.B a&8F #FK &F", +"K T#F T&F j#F &jF j#TF s&F #(F +&F #(FB a&+F (F#. 8&+F #BF(. +8a&F (F#K &F+", +"K #(TF +FT& #(jF +F&j Tj#(F +&sF G# G& GH# Ga& G#. G8& H#G. H8G& G#K G&K GT", +"# GT& Gj# G&j G#Hj sG& Gd# +G& HdG# gG& d#G. 8dG& GHd#. G8g& dKG# GKd& G#Td", +" GTg& G#dj G&+j dj#GT g&sG #F2 &F2 #F2B &2aF 5#F 5&F #B5F a&5F #F2K 2K&F #F", +"T2 &FT2 j#5F 5F&j T#5F 5&sF ;#F ;&F #B;F aF;& ;#5F >&F 5;#FB a&>F #F;K &F;K", +" ;#TF TF;& j#;F &j>F ;j#TF s&>F G#2 G&2 H#G2 G2H& G5# G5& G#H5 H5G& 2KG# &2", +"GK T#G2 G2T& 5jG# 5&Gj G#5T G5s& G;# G;& G#H; G;g& G#5d >G& G5Hd# gG>& ;#GK", +" GK;& G#T; T;G& G#;j G&>j G5Td# >&sG #FN &FN #FNB &FaN #FN. &F8N #FN.B 8a&F", +"N Q#F Q&F T#QF QFT& j#QF QF&j QTj#F Q&sF (F#N &F+N #FN(B +a&FN #FN(. +8&FN ", +"#BFN.( 8a&+FN #(QF +FQ& QT#(F +QT&F Qj#(F &jF+Q Tj#Q(F s+Q&F GW# G&W HWG# W", +"aG& W#G. W8G& GHW#. G8HW& GQ# GQ& ZG# Z&G G#Wj W&Gj GjZ# Z&sG WdG# G&+W GHW", +"d# G&gW GWd#. +GW8& HWdG#. gGW8& G#Qd G&+Q GdZ# gGZ& dj#GQ d&jGQ ZGdj# Z&Gg", +"s m#F m&F #BmF aFm& m#5F 5Fm& 5m#FB am&5F m#QF QFm& m#TF TFm& p#F p&F T#pF ", +"sFp& ;#mF +Fm& m;#FB am&+F 5m;#F m&>F m;#5BF >ma&F ;#QF QF;& Q;T#F +Tm&F ;#", +"pF >Fp& pT;#F p>&sF Gm# Gm& G#Hm HmG& G#5W 5WG& G5HW# G5aW& QmG# Q&Gm GmZ# ", +"GmZ& pG# pG& Z#pG pGZ& vG# v&G GHv# gGv& G5v# >Gv& vGH5# gv>G& GQv# GQv& vG", +"Z# ZGv& vGp# v&pG ZpvG# y&G I I! DI aI I. 8I DI. D8I IK IK! TI TIa Ij 8Ij D", +"jI sI I( +I DI( +DI I(. +I8 I(D. D8+I I(K +IK TI( +TI Ij( +Ij D(Ij sI+ GI G", +"I! J Ja GI. G8I J. J8 GIK IKG! JT JTa GjI 8IGj Jj sJ Id +GI Jd gJ Id. 8Id J", +"d. gJ8 IdK GK+I JTd gJT Idj Gj+I Jjd sJg I2 I2! DI2 aI2 5I 5I8 5DI 5aI I2K ", +"2KI! TI2 I2Ta 5Ij 58Ij 5TI sI5 I; +I; D;I aI; 5I; >I D;5I >DI I;K +KI; TI; ", +"T;+I I;j >Ij T;5I s>I GI2 I2G! J2 Ja2 G5I 5IG8 J5 J58 I2GK GI2!K JT2 TaJ2 5", +"IGj G58Ij J5T sJ5 G;I G;+I J; gJ; 5Id >GI J5d J> GKI; IdK+; J;T gTJ; I;Gj G", +"j>I J;j J>s IN IN! DIN aIN IN. 8IN IND. DN8I QI QI! QDI QaI QIj Q8I DjQI sI", +"Q I(N +IN I(DN +NaI N.I( +N8I DI(N. +D8IN QI( +QI Q(TI QD+I Q(Ij Q8+I Ij(QD", +" +QsI WI WI! JW JWa WI. W8I JW. J8W GQI Q!WI ZJ ZJa WIj Q8WI ZJj sJZ WId +W", +"I JWd gJW W.Id W8+I WdJ. gWJ8 QId GQ+I ZJd gZJ IdWj WI+j ZdJj gZsJ Im Im! D", +"mI aIm 5Im 8Im Dm5I 8IDm QIm Q!Im TIm aITm pI pI8 pDI spI Im; +Im ImD; Dm+I", +" 5mI; >Im Im;5D Dm>I QI; QI+m D;QI TI+m pI; p>I D;pI p>sI GmI W!Im Jm Jma 5", +"WI W85I J5W J8m QIGm Im!GQ ZJm ZaJm pGI G8pI Jp Jps vI vI+ Jv Jvg vI5 v>I J", +"v5 J>v vIQ +QvI JvZ gZJv pvI v>pI Jpv yJ bI I& bDI cI bI. b8I DIb. c8I bKI ", +"I&K bTI cTI bjI I&j TIbj scI bI( b+I DIb( c+I I(b. +Ib8 bDI(. +Ic8 I(bK bK+", +"I b(TI +TcI b(Ij +Ibj Ij(bT c+sI bG bG& Jb cJ bG. bG8 Jb. cJ8 bGK bKG& JbT ", +"cJT bGj G8bj Jjb sJc bGd b+G Jbd gJc b.Id +Gb8 bdJ. J8gc bKId bK+G bTJd gTc", +"J Gjbd +Gbj bdJj gcsJ bI2 I&2 DIb2 c2I b5I 5I& bD5I c5I I2bK &2IK b2TI TIc2", +" 5Ibj Ij5& 5IbT c5sI b;I I;& bDI; c;I 5Ib; >bI b5DI; c>I bKI; IK;& TIb; TIc", +"; I;bj bj>I I;jbT sIc> bG2 b2G& Jb2 cJ2 bG5 G5b8 J5b cJ5 G2bK I&2GK bTJ2 JT", +"c2 G5bj I&jG5 b5Jj c5sJ bG; +Gb; J;b cJ; G5bd >bG b5J; J>c bKG; I;&GK bTJ; ", +"cTJ; G;bj bG>j b;Jj c>sJ bIN I&N DIbN cIN INb. bN8I bDIN. 8IcN bQI QI& QIbT", +" cQI QIbj QIb8 bQDIj cQsI I(bN bN+I bDI(N +IcN bI(N. I&N+8 DI(bN. c+8IN b(Q", +"I +IbQ bQDI( +QcI Ij(bQ I&j+Q bQDIj( sI+cQ bGW WI& JbW cJW b.WI G8bW bWJ. J", +"8cW bGQ G&bQ ZJb ZcJ GQbj GQb8 JjZb ZcsJ WIbd +GbW bWJd cWgJ Id.bW b+GW8 Jb", +"Wd. cJWg8 GQbd +GbQ JbZd gJZc IdjbW IdjW& ZJbdj sJZgc bmI Im& bDIm cmI 5Ibm", +" 8Ibm b5DIm 5Icm QIbm ImQ& TIbm QIcm pbI pI& bTpI cpI Imb; +Ibm Im;bD +Icm ", +"Im;b5 bm>I b5DIm; >Icm QIb; I;Q& bQ;TI QIc; b;pI >bpI pbDI; pIc> bGm G&bm J", +"mb cJm G5bW G8bm b5Jm J5cW GQbm Im&GQ JmZb cmZJ pbG bGp& Jpb cpJ vbG vI& Jv", +"b cvJ bGv5 >bvI vbJ5 J>cv bGvQ QIv& ZbJv JvZc vbpG vIp& pbJv yJc 0F !0F 0BF", +" a0F 1F 18F 1FB 1aF 0FK 0F!K T0F a0TF 1jF 8j1F 1TF s1F 0(F +0F 0(FB a0+F 1(", +"F 1+F (B1F +a1F (F0K 0F+K 0(TF T0+F j(1F 1F+j T(1F 1+sF G0 G0! GH0 Ga0 1G 1", +"G8 1GH 1Ga G0K !KG0 GT0 TaG0 1Gj 18Gj 1GT sG1 Gd0 +G0 HdG0 gG0 1Gd 1+G GH1d", +" g1G dKG0 GK+0 G0Td GTg0 Gj1d +j1G GT1d sGg1 0F2 0F!2 0F2B 0Fa2 15F 581F 5B", +"1F 1F5a 0F2K 2K0!F 0FT2 Ta0F2 5j1F 158jF 1F5T 15sF ;0F ;0+F 0B;F ;0aF 1;F >", +"F1 ;F1B 1a>F 0F;K +;0FK ;0TF a;0TF 1F;j 1j>F 1FT; s1>F G02 !0G2 H0G2 a0G2 1", +"G5 15G8 G51H G51a 2KG0 G02!K T0G2 GTa02 15Gj 1G58j G51T 1Gs5 G;0 +0G; G0H; ", +"G;g0 1G; >G1 G;1H >Gg1 ;0GK +G;0K G0T; gGT;0 Gj1; 1G>j GT1; s1>G 0FN 0F!N 0", +"FNB 0FaN 1FN 8F1N NB1F aF1N Q0F !0QF T0QF a0QF 1QF 1FQ8 QT1F 1QsF (F0N 0F+N", +" 0B(FN +a0FN (F1N +F1N 1(FNB 1+aFN 0(QF Q0+F QT0(F +QT0F Q(1F 1F+Q 1QT(F s1", +"+QF GW0 G0W! HWG0 G0Wa 1GW G81W GH1W Ga1W GQ0 G0Q! ZG0 GaZ0 1GQ G81Q Z1G Z1", +"sG WdG0 GW+0 GHWd0 GWg0 GW1d +G1W 1GHWd 1GgW G0Qd +0GQ GdZ0 ZGg0 GQ1d +G1Q ", +"1GZd gGZ1 m0F !0mF 0BmF m0aF 1mF 1F8m mF1B 1Fam m0QF Q!m0F m0TF am0QF p1F 1", +"8pF 1TpF p1sF ;0mF m0+F m;0FB am0+F m;1F 1m>F 1m;FB >m1aF ;0QF +Qm0F Q;T0F ", +"+Tm0F 1;pF p1>F p1T;F p>1sF Gm0 m0G! G0Hm G0am 1Gm G81m Gm1H Ga1m QmG0 GQm!", +"0 GmZ0 ZGam0 pG1 1Gp8 pGZ1 s1pG vG0 +Gv0 GHv0 vGg0 v1G >Gv1 1GvH gGv1 GQv0 ", +"v+GQ0 vGZ0 ZvGg0 v1pG p1>G ZGv1 y1G 9F 9&F 9FB 9aF 91F :F 1B9F :aF 9FK &F9K", +" 9TF 9FT& 9jF :jF 9F1T s:F 9(F 9+F (B9F +a9F 1(9F :+F 91(FB +a:F (F9K +F9K ", +"T(9F 9F+T j(9F +j:F 9T1(F :+sF 9G 9G& 9GH 9Ga 9G1 :G 1G9H :GH 9GK 9KG& 9GT ", +"GT9a 9Gj :Gj 1G9T s:G 9Gd 9+G GH9d g9G 1G9d :G+ 9G1Hd g:G Gd9K 9K+G GT9d 9G", +"gT Gj9d +G:j 9GT1d sGg: 9F2 &F92 2B9F aF92 95F :5F 5B9F 5a:F 2K9F 9&F2K TF9", +"2 9TaF2 5j9F 5j:F 9F5T :5sF 9;F 9F;& ;F9B 9Fa; 9F1; :>F 95;FB :a>F ;F9K ;&F", +"9K 9FT; 9+T;F 9F;j :j>F 95T;F >Fs: 9G2 92G& GH92 92Ga 9G5 :G5 G59H G5:H G29", +"K 9G&2K 92GT 9GT&2 G59j G5:j G59T s5:G 9G; +G9; G;9H 9Gg; 1G9; :>G 9G5H; :G", +"g> 9KG; 9+G;K GT9; g9GT; G;9j >j:G 9G5Td :>sG 9FN &F9N NB9F aF9N 1F9N :FN 9", +"1FNB aF:N 9QF 9FQ& QT9F 9FQa 9F1Q :QF 9Q1TF sF:Q (F9N +F9N 9(FNB 9+aFN 91(F", +"N +F:N 1(F9NB :+aFN Q(9F 9F+Q 9QT(F 9+QTF 9Q1(F +Q:F 1Q(9TF :Q+sF 9GW G&9W ", +"GH9W Ga9W 1G9W :GW 9G1HW Ga:W 9GQ G&9Q Z9G 9GZ& 1G9Q :GQ 9GZ1 Z:G GW9d +G9W", +" 9GHWd 9GgW 9G1Wd +G:W 1GH9Wd gG:W GQ9d +G9Q 9GZd gGZ9 9GQ1d +G:Q Z91Gd :Gg", +"Z 9mF 9Fm& mF9B 9Fam 9F1m :mF 95mFB am:F Qm9F m&F9Q 9FTm 9QamF p9F :pF 9TpF", +" sF:p m;9F 9F+m 9m;FB 9+maF 95;mF >F:m 1mF9;B :>amF 9FQ; 9+QmF 9Q;TF 9+TmF ", +"9;pF >F:p p9T;F :ps>F 9Gm G&9m Gm9H Ga9m 1G9m :Gm 9G5Hm Ga:m GQ9m 9GQm& 9GZ", +"m Z9Gam p9G :pG pGZ9 sG:p v9G 9+vG 9GvH gGv9 9Gv1 :vG v91GH :Ggv 9GvQ v9+GQ", +" ZGv9 Zv9gG v9pG pv:G Zp9vG y:G I0 I0! DI0 aI0 1I 1I8 1DI 1aI I0K !KI0 TI0 ", +"T0aI 1Ij 18Ij 1TI sI1 I0( +I0 I0D( +0aI 1I( 1+I DI1( +D1I 0(IK I0+K I0T( +0", +"TI 1(Ij +j1I 1(TI 1+sI GI0 I0G! J0 Ja0 1GI G81I J1 J18 I0GK GI0!K JT0 TaJ0 ", +"Gj1I 1G8Ij J1T sJ1 Id0 +0Id Jd0 gJ0 1Id +G1I J1d gJ1 I0dK Id0+K TdJ0 JTg0 I", +"j1d Idj1+ 1TJd g1sJ I02 !0I2 I2D0 I2a0 1I5 158I 5D1I 5a1I 2KI0 I02!K I2T0 T", +"Ia02 15Ij 1I58j 5T1I 1Is5 I;0 +0I; D0I; a0I; 1I; >I1 D;1I 1D>I ;0IK I;0+K T", +"0I; +TI;0 Ij1; 1I>j TI1; s1>I I0G2 GI0!2 J02 a0J2 G51I 1G58I J15 1aJ5 GI02K", +" I02GK! T0J2 JTa02 1G5Ij G581Ij 1TJ5 s1J5 G0I; Id0+; J;0 g0J; G;1I 1G>I J1;", +" J>1 Id0;K +G0I;K T;J0 gJT;0 Idj1; >I1Gj 1TJ; J1s> I0N !0IN I0DN I0aN 1IN 1", +"N8I DI1N 1NaI QI0 I0Q! Q0TI Q0aI 1QI Q81I QD1I 1QsI 0(IN I0+N DI0(N +DI0N I", +"(1N 1N+I 1DI(N 1+DIN I0Q( +0QI QDI0( +QDI0 1(QI +Q1I 1QDI( sI1+Q WI0 I0W! J", +"W0 WaJ0 1WI W81I J1W 1WJ8 G0QI GQI!0 ZJ0 JaZ0 GQ1I 1GQ8I ZJ1 Z1sJ W0Id +0WI", +" WdJ0 JWg0 WI1d +W1I 1WJd gWJ1 Q0Id +GQI0 JdZ0 g0ZJ QI1d 1+GQI ZdJ1 ZJg1 Im", +"0 I!m0 D0Im a0Im 1Im 8I1m Dm1I aI1m Q0Im Im0Q! T0Im QaIm0 pI1 1Ip8 1DpI s1p", +"I m;I0 +0Im Im;D0 +DmI0 Im1; 1I>m 1DmI; >Dm1I Q0I; +QIm0 QD;I0 +TIm0 1Ip; p", +"1>I pD1I; p>D1I G0Im Im0W! Jm0 amJ0 Gm1I 1Gm8I J1m 1aJm Im0GQ GQ0Im! Z0Jm Z", +"Jam0 1GpI pG81I Jp1 J1sp vI0 +Iv0 Jv0 g0Jv v1I >Iv1 Jv1 g1Jv QIv0 vI+Q0 Z0J", +"v JvZg0 v1pI pvI>1 Z1Jv yJ1 9I 9I& 9DI c9I b1I :I 1D9I :cI 9IK 9KI& 9TI 9Tc", +"I 9Ij :Ij 1T9I s:I 9I( 9+I DI9( 9+cI b(1I :I+ b1DI( c+:I I(9K 9K+I 9(TI +T9", +"I 9(Ij +I:j b1TI( s+:I bG9 G&9I J9 cJ9 b1G :Gb J91 :J bK9G I&K9G J9T cTJ9 9", +"Gbj bG:j J9j :Js 9Id 9+bG J9d gJ9 1Gbd :Id b1Jd :Jg 9KId b+G9K 9TJd gTJ9 Id", +"9j Id:j 9dJj sJg: 9I2 92I& DI92 9Ic2 95I :I5 5D9I c5:I I29K I&29K 92TI c29T", +"I 5I9j 5I:j 5T9I s5:I 9I; +I9; D;9I 9Ic; 1Ib; :>I b1;DI :Ic> 9KI; I;&9K TI9", +"; c;9TI I;9j >j:I I;j9D :>sI b29G I&29G J92 c2J9 9Gb5 bG:5 J95 :J5 bG92K 9G", +"2I&K 9TJ2 cJ9T2 b1G5j :Gb5j 95Jj J5s: 9Gb; I;&9G J9; J9c; 1Gb; >b:G b1J; :J", +"> bG;9K I;K9+G 9TJ; cJ;9T Idj95 :>Gbj 9;Jj s:J> 9IN 9NI& DI9N 9IcN bN1I :IN", +" b1DIN cN:I 9QI Q&9I QD9I 9QcI 1Q9I :QI b1QTI :QsI I(9N 9N+I 9DI(N c9+IN b1", +"I(N +I:N 1D(9IN :c+IN 9(QI +Q9I 9QDI( cQ9+I b1QI( +Q:I Ij(9QD :cQ+I 9WI W&9", +"I J9W J9cW 1GbW :WI b1JW :JW 9GbQ bGQ9& ZJ9 cJZ9 1GbQ bG:Q J9Z1 Z:J WI9d +W", +"9I 9WJd gWJ9 b1GWd +W:I J91Wd :WgJ QI9d b+G9Q ZdJ9 ZJg9 Idj9W QI:d ZJ91d gZ", +":J 9Im I&9m Dm9I 9Icm 1Ibm :Im b1mDI cm:I QI9m Im&9Q TI9m cQ9Im p9I :pI 9Dp", +"I sI:p Im9; +I9m 9DmI; cm9+I b1mI; >I:m 1Dm9I; c>:Im QI9; I;&9Q 9QDI; cQ;9I", +" 9Ip; p>:I p9DI; cp:>I 9Gbm Im&9G J9m J9cm 1Gbm bG:m b1Jm :Jm bGQ9m 9GQIm& ", +"JmZ9 ZJ9cm b1pG pb:G Jp9 :Jp v9I 9+vI Jv9 g9Jv b1vI :vI vbJ1 :Jv 9QvI v9I+Q", +" Z9Jv cvZJ9 v9pI pv:I pvJ9 yJ: FL !FL LBF aFL FL. 8FL FL.B aF8L MF MF! TMF ", +"aMF MjF 8MF MjTF sMF (FL +FL (FLB aF+L FL(. 8F+L (BLF. +8aFL M(F +MF M(TF +", +"FaM j(MF +F8M TMj(F +MsF GL GL! GHL GaL GL. G8L HLG. GLH8 GM GM! GTM GaM GM", +"j G8M HMGj sGM GdL +GL HdGL gGL dLG. +LG8 GHdL. G8gL GMd +GM TdGM gMG dMGj ", +"G8+M dMjGT sGgM FL2 FL!2 FL2B FLa2 5FL 8F5L LB5F aF5L MF2 !FM2 MFT2 M2aF 5M", +"F 5F8M TM5F 5MsF ;FL ;F+L LB;F ;FaL ;F5L >FL 5;FLB aF>L M;F +FM; TFM; aFM; ", +"5FM; >MF M;F5T sM>F GL2 !LG2 HLG2 aLG2 G5L 58GL GLH5 GL5a GM2 M2G! G2HM G2a", +"M G5M 5MG8 H5GM G5sM G;L +LG; GLH; G;gL GL5d >GL G5HdL gG>L GM; G;+M HMG; G", +"Mg; 5dGM >MG G5TdM sG>M FLN FL!N FLNB FLaN FLN. FL8N .BLFN 8aFLN QMF MFQ! T", +"MQF QFaM MjQF QF8M QTMjF QMsF FL(N FL+N (BLFN +aFLN N.(FL +8FLN (BFN.L 8aF+", +"LN M(QF QM+F QTM(F aMF+Q QMj(F +Q8MF TMjQ(F s+QMF GWL GLW! HWGL GLWa WLG. G", +"LW8 GHWL. G8HWL GQM Q!GM ZGM GaZM WMGj W8GM GMZj ZGsM WdGL GW+L GHWdL GWgL ", +"GWdL. +GW8L HWdGL. gGW8L QdGM GQ+M GMZd ZGgM dMjGQ +GQ8M ZGdMj gZsGM mFL !F", +"mL LBmF mFaL mF5L mF8L 5mFLB amF5L MmF M!mF TFMm aFMm pMF 8MpF TMpF pMsF ;F", +"mL mF+L m;FLB amF+L 5m;FL mF>L m;F5BL >maFL QFM; +FMm MmFT; aMm+F M;pF pM>F", +" pTM;F >MpsF GmL mLG! GLHm GLam GL5W GL8m G5HWL G5aWL GMm G!Mm GMZm aMGm pG", +"M G8pM ZMpG sMpG vGL +GvL GHvL vGgL G5vL vG>L vGH5L gv>GL vMG +GvM ZGvM gGv", +"M vMpG pG>M ZpvGM yGM #FL &FL #FLB &FaL FL#. &F8L #L.FB 8a&FL M#F M&F M#TF ", +"TFM& j#MF 8FM& TMj#F M&sF (F#L &F+L (BL#F +a&FL #L.(F +8&FL (BF#L. 8a&+FL #", +"(MF +FM& TM#(F aMF+& Mj#(F M&F+j Mj#T(F s+M&F G#L G&L H#GL GLH& #LG. 8&GL G", +"H#L. G8H&L GM# GM& G#HM HMG& MjG# 8MG& GTMj# GMs& d#GL +LG& GHd#L G&gL Gd#L", +". d&LG8 Hd#GL. gG8&L G#dM G&+M dM#GT GMg& dMjG# dM&G8 GTMdj# gsGM& FL#2 FL&", +"2 #L2FB a&FL2 #F5L &F5L 5B#FL 5a&FL #FM2 &FM2 TM#F2 aMF&2 M#5F 5FM& 5TM#F s", +"5M&F #F;L &F;L ;#FLB a;&FL 5;#FL &F>L ;#F5BL >&aFL ;#MF MF;& M;#TF aM;&F M;", +"#5F M&>F 5T#M;F >Ms&F #LG2 &LG2 GH#L2 Ga&L2 5#GL GL5& G5H#L G5a&L M#G2 G2M&", +" GTM#2 GT&M2 G#5M 5MG& G5TM# sG5M& ;#GL GL;& G;H#L gG;&L G5d#L G&>L H5#G;L ", +"g>G&L G#M; M;G& GT;M# gMG;& G5Md# GM>& dM#G5T >MgG& FL#N FL&N #LNFB a&FLN #", +"LNF. 8&FLN .BL#FN a&F8LN M#QF QFM& QTM#F aMFQ& QMj#F M&FQ8 TMjQ#F sQM&F #LN", +"(F +&FLN #FN(BL a&F+LN #(FN.L 8&F+LN (FLBN.# 8a+&FLN QM#(F M&F+Q TM#Q(F +QT", +"M&F Mj#Q(F +Q8M&F #(TFQMj M&Fs+Q W#GL GLW& GHW#L GaW&L GW#L. G8W&L HW#GL. H", +"8WG&L G#WM WMG& GMZ# GMZ& GQMj# GQ8M& ZGMj# Z&GsM GWd#L d&LGW HWdG#L gGW&L ", +"Wd#GL. G8Wd&L WdG#HL. G8Wg&L dM#GQ dM&GQ ZGdM# Z&GgM GQMdj# GQ8dM& dMjZG# g", +"sGZ&M #FmL &FmL m#FLB am&FL 5m#FL m&F5L m#F5BL 5aFm&L m#MF MFm& Mm#TF aMm&F", +" M#pF M&pF pTM#F p&MsF m;#FL m&F+L ;#FmLB m&Fa;L m;#5FL >m&FL LBmF5;# am&>F", +"L Mm#;F Mm&+F Tm#M;F aMFQ;& pM;#F >Mp&F M;#pTF p&F>Ms m#GL GLm& GmH#L Gam&L", +" G5W#L G5&WL H5#GmL amLG5& G#Mm MmG& ZGMm# Z&GMm GMp# GMp& ZpGM# Zp&GM G#vL", +" G&vL vGH#L gvG&L vG5#L v>G&L G5Hv#L v&Gg>L GMv# GMv& ZvGM# Zv&GM pvGM# >Mv", +"G& pGMZv# GMy& UI U!I UDI UaI UI. U8I DIU. 8IUa IM IM! VI VaI UjI 8IM VIj s", +"IV UI( U+I DIU( +IUa I(U. +IU8 UDI(. U+D8I IM( +IM VI( V+I U(Ij +IUj IjV( V", +"+sI UG UG! JU JUa UG. UG8 JU. J8U UGM U!GM VJ VJa UGj G8Uj JjV sJV UGd U+G ", +"JUd gJU U.Id +GU8 UdJ. J8gU IdM +MUG VJd gVJ GjUd +GUj VdJj sJgV UI2 I2U! D", +"IU2 U2aI U5I 5IU8 UD5I 5IUa IM2 I!M2 V2I aIV2 5IM 8I5M V5I V5sI U;I +IU; UD", +"I; aIU; 5IU; >UI U5DI; Ua>I IM; I;+M V;I +IV; I;Uj >MI 5IV; V>I UG2 G2U! JU", +"2 UaJ2 UG5 G5U8 J5U U5J8 U2GM IM2G! VJ2 JaV2 G5Uj UG58M J5V VsJ5 UG; +GU; J", +";U J;gU G5Ud >UG U5J; J>U GMU; IdM+; J;V J;gV G;Uj UG>M V5J; J>V UIN INU! D", +"IUN UNaI INU. UN8I UDIN. U8IDN UQI Q!IM VQI QaVI QIUj QIU8 QIVj VQsI I(UN U", +"N+I UDI(N U+DIN UI(N. U+8IN DI(UN. +DIU8N U(QI +IUQ QIV( +QVI IM(Qj U+Q8I V", +"QIj( sIV+Q UGW U!WI JUW UWJa U.WI G8UW UWJ. UWJ8 UGQ Q!UG ZJV ZaVJ GQUj GQU", +"8 VZJj VZsJ WIUd +GUW UWJd JUgW Id.UW U+GW8 JUWd. gJUW8 GQUd +GUQ VdZJ ZJgV", +" IdMWj IdMW8 ZJVdj gVZsJ UmI U!Im UDIm aIUm 5IUm 8IUm U5DIm U5aIm IMm I!Mm ", +"VmI aIVm pUI U8pI VpI sIVp ImU; +IUm Im;UD U+maI Im;U5 Um>I U5DIm; >DmUI QI", +"U; IM+m QIV; +IVm U;pI pI>M pIV; pIV> UGm U!Gm JmU UaJm G5UW G8Um U5Jm U8Jm", +" GQUm IMmW! JmV JaVm pUG UGp8 JpV VpsJ vUG U+vI JvU gUJv UGv5 >UvI vUJ5 vUJ", +"> vIM +IvM VvJ JvgV vUpG vI>M VvJp yJV bUI U&I UDbI cUI UIb. 8IU& bUDI. U8c", +"I bMI IM& VbI VcI IMbj 8IbM bjVI VcsI UIb( +IU& bUDI( U+cI bUI(. b+U8I UDIb", +"(. cU+8I b(IM +IbM bIV( cIV+ IM(bj IM&+j VbIj( sIVc+ bGU UG& JbU cJU b.UG U", +"Gb8 bUJ. cUJ8 bGM GMU& VJb cJV UGbj G8bM VbJj VJsc UGbd U+bG bdJU cJgU Id.b", +"U b+GU8 JbUd. cJUg8 GMbd +GbM JbVd cJgV IdMbj IdMb8 JjVbd gVJsc UIb2 U2I& b", +"UDI2 UIc2 bU5I 5IU& b5UDI U5cI b2IM I2M& bIV2 cIV2 5IbM IM5& b5VI cIV5 bUI;", +" I;U& b;UDI U;cI b5UI; U&>I U5Db;I cU>I IMb; M;I& b;VI cIV; IM;b5 bM>I V5bI", +"; >IVc b2UG U2G& bUJ2 JUc2 UGb5 G5U& b5JU cUJ5 b2GM IM&G2 JbV2 V2cJ G5bM IM", +"&G5 JbV5 VJc5 UGb; G;U& b;JU cUJ; bG5Ud bG>U J5bUd >UcJ GMb; IdM;& JbV; VJc", +"; IdMb5 bG>M J5Vbd cJV> UIbN UNI& bUDIN UIcN bUIN. I&NU8 UDIbN. cU8IN QIbM ", +"QIU& bQVI VQcI bQUIj IM&Q8 VbQIj sIVcQ bUI(N I&NU+ UDIb(N cU+IN UI(bN. U+8I", +"&N UDbIN.( U+8cIN IM(bQ IM&+Q VbQI( cQV+I bQUIj( U+QI&j Ij(VbQ cQVsI+ UGbW ", +"G&UW bWJU JUcW bGUW. bG8UW JbUW. cJUW8 UGbQ GQU& VJZb VZcJ bGQUj IM&W8 ZJVb", +"j sJZVc bGUWd b+GUW JbUWd cJUgW bWUId. U+GbW8 bWUJd. gJUcW8 IdMbW IdMW& ZJV", +"bd gVZcJ bWMIdj bW8IdM JjVZbd sJZgVc bUIm ImU& bmUDI UmcI b5UIm Im&U5 U5Dbm", +"I c5UIm IMbm MmI& bmVI cIVm bMpI U&pI VbpI pIVc Im;bU Im&U+ UmDb;I cmU+I b5", +"UIm; >ImU& Imb;U5D c>UIm IMmb; IMmb+ VmbI; cQ;VI pbUI; >MbpI VpbI; cpV>I UG", +"bm GmU& bmJU cUJm bG5UW bG8Um J5bUW cJ5UW GMbm IMmG& JbVm VJcm bGpU UGp& pb", +"VJ cJVp bGvU UGv& JbvU vUcJ vbUG5 v>bUG JvbU5 cvJ>U bGvM IMv& vbVJ cJVv pvb", +"UG >MvbG JpVvb cJyV kF kF! kFB akF 1kF 8kF kF1B 1Fak kMF M!kF TkF TFak lF l", +"8F lTF lsF k(F +kF (BkF +Fak k(1F 1F+k 1k(FB akF1+ M(kF kM+F k(TF +FTk l(F ", +"l+F T(lF sFl+ Gk Gk! GkH Gak 1Gk G8k Gk1H Gk1a GkM kMG! GTk TkGa lG lG8 lGH", +" lsG Gkd +Gk GHdk gkG Gk1d +k1G 1GHdk 1Ggk dkGM Gk+M TdGk GTgk lGd l+G GTld", +" glG kF2 !Fk2 2BkF k2aF 5kF 5F8k kF5B 5Fak MFk2 kMF!2 kFT2 akFT2 l5F 58lF 5", +"TlF sFl5 k;F +Fk; ;FkB aFk; 1Fk; >kF k;F1B ak>F kFM; k;M+F TFk; ak;TF l;F l", +">F T;lF >Fls Gk2 k2G! G2Hk G2ak G5k 5kG8 H5Gk 5aGk kMG2 GkM!2 G2Tk GTka2 lG", +"5 G5l8 G5lH l5sG Gk; G;+k HkG; Gkg; Gk1; >kG 1G;Hk >Ggk k;GM +GkM; TkG; gkG", +"T; lG; l>G GTl; g>lG kFN !FkN NBkF kFaN kF1N kN8F 1kFNB akF1N QkF kFQ! QFTk", +" QFak lQF Q8lF QTlF sFlQ (FkN kF+N k(FNB akF+N 1k(FN 1+kFN k(F1NB 1+FakN k(", +"QF +FQk QkT(F +QkTF Q(lF +QlF lQT(F ls+QF GkW W!Gk GHWk WaGk Gk1W W8Gk 1GHW", +"k 1GaWk GQk Q!Gk ZkG GaZk lGW GQl8 lZG sZlG GWdk Gk+W GkHWd GkgW 1GWdk 1+GW", +"k GkH1Wd g1GWk QdGk GQ+k GkZd gGZk GQld +GlW ZGld lGgZ kmF k!mF mFkB aFkm 1", +"Fkm 8Fkm kmF1B akm1F QFkm kmFQ! TFkm akmQF lpF p8lF pTlF sFlp m;kF +Fkm km;", +"FB akm+F km;1F km>F 1mFk;B >kamF QFk; +QkmF Qk;TF ak;QF p;lF >Flp l;pTF l>p", +"sF Gkm G!km HkGm akGm Gk1m 8kGm 1GmHk akm1G QkGm GQkm! GkZm ZkGam lGp l8pG ", +"ZplG splG vkG +Gvk GkvH gGvk 1Gvk >Gvk v1GHk >kgvG GQvk vk+GQ ZGvk ZvkgG lv", +"G p>lG ZvlG ylG 9kF k&F kF9B 9Fak 1k9F :kF 91kFB ak:F 9MF 9FM& 9FTk 9FaM l9", +"F l:F 9TlF sFl: k(9F 9F+k 9k(FB akF9+ 91k(F +k:F 1k(9FB :+akF M(9F 9F+M 9Tk", +"(F 9+TkF 9(lF :+lF l9T(F ls:+F 9Gk Gk& Gk9H Gk9a 91Gk :Gk 9G1Hk Ga:k 9GM G&", +"9M GT9M Ga9M lG9 l:G 9GlH s:lG Gk9d +k9G 9GHdk 9Ggk 9G1dk +G:k 1GH9dk :Ggk ", +"GM9d +G9M 9GTdk 9GgM 9Gld :Gl+ lG9Td lGg: kF92 &Fk2 9kF2B akF92 9F5k 5k:F 9", +"5kFB :5akF MF92 k&FM2 9TkF2 9aMF2 95lF :5lF l95TF ls:5F 9Fk; kF;& k;F9B ak;", +"9F k;F95 :k>F 95Fk;B :>akF 9FM; k;&MF 9T;kF aM;9F 9;lF >Fl: l;9TF l>s:F 92G", +"k G2k& 9GHk2 9Gak2 Gk95 G5:k 9G5Hk :GH5k 92GM 9GM&2 9GTk2 9GaM2 9Gl5 l5:G l", +"G9H5 lsG:5 Gk9; k;G& 9G;Hk g9Gk; 9G5dk :G>k G5k9H; g:>Gk GM9; k;&GM 9GTk; g", +"9MG; 9Gl; :>lG lG;9H l>Gg: kF9N &FkN 9kFNB akF9N 91kFN kF:N 1kF9NB :akFN 9F", +"Qk QFk& 9QTkF 9QakF 9QlF lF:Q l9QTF :QFls 9k(FN k&F+N k(F9NB 9+FakN 1k(9FN ", +":+kFN 1k9(NBF akF:+N 9Qk(F 9+QkF Qk(9TF akF9+Q l9Q(F :Q+lF 9QTl(F ls+:QF Gk", +"9W WkG& 9GHWk 9GaWk 9G1Wk Gk:W 1GH9Wk :GHWk GQ9M QkG& 9GZk GkZ& 9GlW :GlW Z", +"9lG lGZ: 9GWdk dk&GW GkH9Wd g9GWk 1GW9dk :G+Wk 91GkHWd g:GWk 9GQdk dk&GQ Z9", +"Gdk Zk&gG lG9Qd :GQl+ lZ9Gd glZ:G 9Fkm kFm& kmF9B akm9F kmF95 km:F 95FkmB :", +"makF 9FMm km&QF 9TmkF aMm9F lFp9 lF:p p9lTF :plsF km;9F km&+F 9mFk;B akF9+m", +" 95;kmF :>mkF km1;9FB >ka:mF 9Q;kF k;&QF kmF9T; akF9Q; l;p9F l>p:F p9Tl;F :", +"psl>F Gk9m kmG& 9GmHk akm9G 9G5Wk Gk:m G5k9Hm :GmHk GM9m km&GQ Z9Gkm Zk&Gm ", +"p9lG lG:p Zp9lG :pGlZ 9Gvk Gkv& v9GHk gv9Gk v91Gk vk:G 9G5vkH :vGgk 9GvM v9", +"M+G Zv9Gk ZvkG& v9lG lG:v lvZ9G l:yG Ik Ik! DkI aIk 1UI 8Ik Dk1I Ua1I IkM I", +"!kM VIk aIVk lI lI8 lIV lsI Ik( +Ik D(Ik Dk+I 1(Ik U+1I Ik(1D 1U+aI kMI( Ik", +"+M IkV( +IVk lI( l+I VIl( sIl+ UGk U!Gk Jk Jka 1UG U81G J1U J8k IkGM IkMG! ", +"JkV VaJk lGU UGl8 lJ lJs Idk +kUG Jkd gJk UG1d U+1G 1UJd J1gU dkIM Idk+M Vd", +"Jk JkgV lId U+lG lJd glJ Ik2 I!k2 I2Dk I2ak 5Ik 8I5k Dk5I aI5k kMI2 IkM!2 I", +"kV2 V2aIk lI5 5Il8 V5lI l5sI Ik; I;+k IkD; Ika; U;1I >kI Ik;1D Dk>I k;IM Ik", +";+M IkV; V+Ik; lI; l>I V;lI lIV> U2Gk Ik2G! Jk2 akJ2 U51G 1UG58 J5k 5aJk Ik", +"MG2 Gk2IM! V2Jk JkVa2 UGl5 lGU58 lJ5 J5ls GkU; Idk+; Jk; J;gk UG1; 1U>G 1UJ", +"; J>k IdkM; +GkIM; V;Jk gVJk; UGl; >UlG lJ; J>l IkN I!kN DNIk aNIk 1NIk IN8", +"k IkN1D 1UaIN QIk Q!Ik QIVk aIQk lIQ Q8lI VQlI lQsI k(IN +NIk Ik(DN +DkIN I", +"k(1N 1U+IN 1D(IkN akN1+I Q(Ik QI+k VQIk( V+QIk QIl( +QlI VlQI( lsI+Q WIk W!", +"Ik JkW WaJk UG1W 8IWk 1UJW W8Jk GkUQ UGQk! ZJk ZaJk lWI W8lI lJZ lZsJ IdWk ", +"WI+k WkJd gWJk Idk1W IdkW8 J1UWd gJ1UW IdQk Idk+Q ZdJk ZJgk WIld +WlI ZJld ", +"gZlJ Ikm I!km IkDm Ikam Um1I Ik8m Ikm1D akm1I ImQk IkmQ! IkVm VmaIk lIp l8p", +"I lIVp splI kmI; Ik+m IkmD; akm+I Ikm1; Ik>m 1DmIk; >kDIm IkQ; Ikm+Q VmIk; ", +"V+mIk pIl; p>lI VplI; V>lpI GkUm IkmW! Jkm akJm UG1m IkmG8 1UJm 8kJm IkmGQ ", +"Ik!GMm JmZk ZJkam pUlG lGpU8 Jpl lsJp vIk +Ivk Jvk gkJv 1UvI vI>k v1Jk >kJv", +" QIvk vIk+Q ZkJv VvJgk lvI v>lI lvJ ylJ tI tI& tDI tcI t1I t:I 1DtI :Itc tI", +"M IMt& VtI tIVc ltI l:I VtlI uI tI( t+I DIt( c+tI 1It( :It+ t1DI( t:c+I IMt", +"( +ItM VIt( tIV+ tIl( t+lI ltVI( u+I tG tG& tJ tJc tG1 t:G tJ1 :Jt tGM GMt&", +" tJV VJtc ltG t:lG lJt uJ tGd t+G tJd gtJ 1Gtd :Gt+ J1td :Jgt GMtd +GtM VJt", +"d tJgV tGld t+lG ldtJ uJg tI2 I&t2 DIt2 c2tI t5I :It5 5DtI tIc5 IMt2 IM&t2 ", +"tIV2 tcVI2 t5lI l5:I tIV5 u5I t;I +It; D;tI tIc; 1It; t>I t5DI; >Itc IMt; t", +"+IM; tIV; tc;VI t;lI lIt> t5VI; u>I tG2 G&t2 tJ2 c2tJ tG5 :Gt5 tJ5 t5:J GMt", +"2 tGM&2 V2tJ tJVc2 t5lG t:Gl5 t5lJ uJ5 tG; +Gt; tJ; t;gJ 1Gt; t>G J1t; t>J ", +"GMt; t+GM; VJt; tJ;gV tGl; lGt> l;tJ uJ> tIN I&tN DItN cItN 1ItN tN:I t1DIN", +" t:cIN tQI QIt& VQtI tIcQ tQlI :QlI tQVlI uQI I(tN +ItN tDI(N tc+IN t1I(N t", +":+IN 1DIt(N :cIt+N QIt( +QtI tQVI( tcQ+I tQIl( t:Q+I Vl(tQI +QuI tGW G&tW t", +"JW cJtW 1GtW :GtW J1tW tW:J tGQ GQt& tZJ ZctJ tGlW :GtQ lJtZ uZJ WItd +GtW ", +"JWtd tWgJ tG1Wd t:G+W tJ1Wd gtJ:W GQtd +GtQ ZJtd gZtJ tGQld t:G+Q lJZtd gZu", +"J tmI Imt& DmtI tIcm 1Itm :Itm t5DIm t:mcI QItm tQIm& tIVm tcQIm tpI lI:p p", +"IVt upI Imt; +Itm tmDI; tcm+I t5Im; >Itm 1Dmt;I t>cIm QIt; t+QIm tQ;VI tcQI", +"; pIt; pIt> tpVI; p>uI tGm Gmt& tJm cJtm 1Gtm :Gtm J1tm tm:J GQtm tGQm& ZJt", +"m tJmZc tpG tG:p tpJ uJp tvG vIt+ tvJ tJcv v1tG tG:v t5Jv :Jtv vItQ tv+GQ t", +"JVv cvVtJ lGtv lI:v Jptv yuJ e e! eB ae e. 8e e.B 8ea eK eK! Te Tea ej 8ej ", +"Tej se e* +e *Be +ea e*. +e8 e.*B ae8* e*K +eK Te* +Te ej* +ej ejT* se+ Ge ", +"Ge! He Gae Ge. G8e He. H8e GeK eKG! GTe TeGa Gje 8eGj Hej sGe f f+ fH gf f.", +" f8 fH. gf8 fK f+K fT gfT fj f8j fTj sf e2 e2! e2B ae2 5e 5e8 5eB 5ae e2K 2", +"Ke! Te2 T2ae 5ej 58ej 5Te se5 e; +e; e;B ae; 5e; >e *B5e >ea e;K +Ke; Te; T", +";+e e;j >ej Te5* >es Ge2 e2G! He2 G2ae G5e 5eG8 H5e 5aHe e2GK Ge2!K G2Te ae", +"2GT 5eGj G58ej 5THe G5se f; f+; fH; gf; f5 f> f5H f>g f;K +;fK fT; g;fT f5j", +" f>j f5T sf> eN eN! eNB aeN eN. 8eN .BeN aN8e Qe Qe! QeT Qae Qej Q8e QTej s", +"eQ e*N +eN eN*B +Nae *Ne. +N8e *BeN. aeN8* Qe* +Qe TeQ* Qa+e ejQ* Q8+e ej*Q", +"T +Qse We We! HeW Wae We. W8e H.We W8He GQe Q!We Ze Zea Wej Q8We Zej sZe fW", +" f+W fHW gfW fW. f8W HWf. gWf8 fQ fQ+ Zf Zfg fQj fQ8 Zfj sfZ em em! emB aem", +" 5em 8em 5Bem ae8m Qem Q!em Tem aeTm pe pe8 peT spe em; +em *Bem ae+m em5* ", +">em em;5B ae>m Qe; Qe+m TeQ; Te+m pe; >ep Tep* sp>e Gme W!em Hem aeGm 5We W", +"85e 5WHe Wa5e QeGm em!GQ Zem aeZm pGe G8pe Zpe Zpse fv fv+ fvH gfv fv5 f>v ", +"vHf5 gvf> fvQ v+fQ Zfv gvZf fp fp> fpZ yf ,e e& ,eB ,ae ,e. ,8e e.,B 8e,a ,", +"eK e&K ,Te Te& ,je e&j Te,j se& ,e* -e ,e*B -ae e*,. -8e *Be,. 8e-a e*,K -e", +"K ,eT* -Te ,e*j -je ej*,T s-e ,G ,G& ,GH ,Ga ,G. ,G8 ,.He G8,H ,GK ,KG& ,GT", +" GT,a ,Gj G8,j GT,j sG, f, f- fH, gf- f,. f-8 ,Hf. f8g- f,K f-K fT, f-T fj,", +" f-j ,Hfj sf- ,e2 e&2 e2,B ,2ae ,5e 5e& ,B5e 5e,a e2,K &2eK ,2Te T2e& 5e,j ", +"ej5& 5e,T ,5se ,;e -e; ,Be; ae-; 5e,; >e- e;B,5 -a>e ,Ke; e;-K Te,; Te-; e;", +",j -j>e e;j,T >es- ,G2 ,2G& ,2He ,2Ga ,G5 G5,8 G5,H G5,a G2,K e&2GK ,2GT ,G", +"T&2 G5,j e&jG5 G5,T ,Gs5 f;, f-; ,Hf; g;f- f5, f>- ,Hf5 g-f> ,;fK fK-; ,Tf;", +" f;-T ,5fj ->fj ,5fT f>s- ,eN e&N eN,B ,Nae eN,. ,N8e ,eN.B aeN,8 ,Qe Qe& Q", +"e,T Qe,a Qe,j Qe,8 ,QTej ,Qse e*,N -eN *Be,N ae-N ,e*N. 8e-N ,eN*B. -8aeN ,", +"eQ* -Qe ,QTe* Qa-e ej*,Q Q8-e ,QTej* -Qse ,GW We& He,W Ga,W ,.We G8,W ,GHW.", +" ,G8Wa ,GQ G&,Q Ze, Ze& GQ,j GQ,8 ,GZj Zes, fW, f-W ,HfW -Wgf ,Wf. -Wf8 fHW", +",. f-Wg8 fQ, f-Q Zf, Z-f ,Wfj -Wfj fjZ, Z-sf ,me em& ,Bem ae,m 5e,m 8e,m em", +"B,5 aem,5 Qe,m emQ& Te,m emT& pe, pe& ,Tpe pes, em,; -me em;,B ae-m em;,5 -", +"m>e ,5em*B >e-am Qe,; Qe-m ,Q;Te Te-m ,;pe -pe peT,; se-p ,Gm G&,m Gm,H Ga,", +"m G5,W G8,m ,G5Hm em&H5 GQ,m em&GQ ,GZm emZ& pG, ,Gp& pGZ, pGs, fv, -vf fHv", +", gf-v v,f5 -vf> fvH,5 f>g-v v,fQ fQ-v fvZ, -vZf fp, fp- Z,fp yf- Ie Ie! De", +" Dea Ie. 8Ie De. D8e IeK I!eK DeT aITe Ije Ij8e Dej sIe I* +Ie De* +De I*. ", +"8I* D.I* D8+e I*K +KI* TI* De+T I*j I*+j I*Dj sI* GIe IeG! Je Jae IeG. GI8e", +" Je. J8e IeGK GIe!K JTe TeJa GIej IjeG8 Jje sJe fI f+I Jf gJf fI. f8I Jf. J", +"f8 fIK +IfK JfT fTgJ fjI +Ifj Jfj sfJ Ie2 I!e2 De2 I2ae 5Ie 8I5e 5De D85e e", +"2IK Ie2!K I2Te ae2TI Ij5e Ije58 De5T 5Dse I;e I;+e De; D;+e 5I* >eI De5* >e", +"D IKe; I;e+K TeD; ae;TI Ij5* I*>j TI5* sI>e IeG2 GIe!2 Je2 aeJ2 GI5e G58Ie ", +"J5e 5aJe GIe2K Ie2GK! TeJ2 JTae2 IjeG5 G58Ije 5TJe J5se fI; +If; Jf; J;gf f", +"5I f>I Jf5 J>f I;fK f+I;K fTJ; JfTg; 5Ifj >Ifj f5Jj J>sf IeN I!eN DeN DNae ", +"eNI. IN8e eND. DN8e QIe IeQ! QDe DeQa IjQe 8IQe DjQe QDse I*N +NI* DNI* +ND", +"e *NI. IN8* I*ND. +De8N QI* QI+e DeQ* QD+e IjQ* 8IQ* I*jQD QIs* WIe IeW! JW", +"e WaJe IeW. 8IWe WeJ. W8Je QIWe GQIe! ZJe JaZe IjWe GQ8Ie JjZe ZJse fWI +Wf", +"I JfW gWJf WIf. W8fI fWJ. JWf8 fQI +QfI ZfJ gJZf WIfj Q8fI JjZf ZfsJ Ime I!", +"em Dem aeDm Im5e Im8e Dm5e 8eDm ImQe ImeQ! DmQe aemQD pIe 8Ipe pDe pDse Im*", +" Im+e ImD* De+m Im5* Im>e Im*5D De>m ImQ* Im*+Q DeQ; ae;QD pI* pI>e Dep* pD", +">e ImWe ImeW! Jme aeJm WI5e G8mIe 5WJe 8eJm ImeGQ GQIem! JmZe ZJaem WIpe pG", +"8Ie Jpe seJp fvI f+vI Jvf gfJv vIf5 vIf> fvJ5 f>Jv vIfQ fv+QI JvZf ZfJgv fp", +"I pIf> Jpf yJf h h& hD hc h. h8 hD. hc8 hK h&K hT hcT hj h8j hTj hs h* h- h", +"D* hc- h*. h-8 D*h. c-h8 h*K h-K hT* h-T hj* h-j D*hj hs- hG hG& hJ hJc hG.", +" h8G hJ. hJ8 hGK G&hK hJT cJhT hjG G8hj hJj hsJ hf hf- hJf i hf. hf8 h.Jf i", +"8 hfK hKf- hfT iT hfj f-hj Jfhj is h2 h&2 hD2 hc2 h5 h58 h5D hc5 h2K &2hK h", +"T2 c2hT h5j 5&hj h5T hs5 h; h-; h;D hc; h5; h> 5Dh; h>c h;K -;hK hT; c;hT h", +";j h>j 5Th; hs> hG2 G&h2 hJ2 h2cJ h5G G5h8 hJ5 cJh5 G2hK hG&2K JTh2 cJTh2 G", +"5hj h5G&j J5hT h5sJ hf; f-h; hJ; i; hf5 h>f Jfh5 i> f;hK f-;hK J;hT iT; f5h", +"j hjf> J;hj is> hN h&N hDN hcN hN. h8N DNh. c8hN hQ hQ& hQD hcQ hQj hQ8 QDh", +"j hsQ h*N h-N D*hN hNc- *Nh. -8hN hD*N. c-8hN hQ* h-Q QDh* c-hQ Q*hj -Qh8 h", +"QD*j hQs- hW hW& hJW hcW hW. hW8 JWh. cWh8 hWQ GQh& hZ hZc hWj GQh8 hZj hZs", +" hfW h-W JfhW iW fWh. f8hW JfWh. iW8 hfQ f-hQ hZf iZ fQhj fQh8 hjZf iZs hm ", +"hm& hmD hcm h5m h8m 5Dhm c5hm hQm Q&hm hTm cQhm hp hp8 hpD hps hm; h-m Dmh;", +" c-hm 5*hm h>m h5Dm* hmc> hQ; -Qhm QDh; cQh; hp; hp- pDh; cph> hWm Gmh& hJm", +" cJhm h5W G8hm J5hW c5hW GQhm hWQm& hZm hmZc hpG pGh8 hZp cphZ hv hv- hvJ i", +"v hv5 hv> h5Jv iv> hvQ hQ-v hZv iZv hpf fph> Jphv yi e0 e0! e0B ae0 1e 1e8 ", +"1eB 1ae e0K !Ke0 Te0 T0ae 1ej 18ej 1Te se1 e*0 +e0 e0*B +0ae 1e* 1+e *B1e +", +"e1a *0eK e0+K e*T0 +0Te ej1* +j1e Te1* 1+se Ge0 e0G! He0 G0ae 1Ge G81e 1He ", +"Ga1e e0GK Ge0!K G0Te ae0GT Gj1e 1G8ej GT1e 1Gse f0 f+0 fH0 gf0 f1 f1+ f1H g", +"f1 f0K +0fK fT0 g0fT f1j 1+fj f1T sf1 e02 !0e2 2Be0 e2a0 1e5 158e 1B5e 5a1e", +" 2Ke0 e02!K e0T2 ae0T2 15ej 1e58j 5T1e 1es5 e;0 +0e; ;0eB a0e; 1e; >e1 1Be;", +" 1a>e ;0eK e;0+K T0e; ae;T0 ej1; 1e>j Te1; s1>e e0G2 Ge0!2 e0H2 ae0G2 G51e ", +"1G58e H51e 1Ga5e Ge02K e02GK! GTe02 GT0ae2 1G5ej G581ej 1GT5e se1G5 f;0 +;f", +"0 H;f0 f;g0 f15 f>1 1Hf5 g1f> ;0fK f+;0K T;f0 fT;g0 1;fj >jf1 1Tf5 f1s> e0N", +" !0eN 0BeN e0aN 1eN 1N8e eN1B 1Nae Qe0 e0Q! Q0Te Q0ae 1Qe Q81e Qe1T 1Qse *0", +"eN e0+N *Be0N ae0+N e*1N 1N+e 1e*NB 1+eaN e*Q0 +0Qe QeT*0 +QeT0 Qe1* +Q1e 1", +"QeT* se1+Q We0 e0W! H0We W0ae 1We W81e He1W Wa1e G0Qe GQe!0 Ze0 aeZ0 GQ1e 1", +"GQ8e Z1e Z1se fW0 +Wf0 HWf0 fWg0 f1W 1+fW 1HfW gWf1 fQ0 +Qf0 Zf0 g0Zf f1Q 1", +"+fQ Zf1 g1Zf em0 e!m0 m0eB a0em 1em 8e1m 1Bem ae1m Q0em em0Q! T0em aemQ0 pe", +"1 1ep8 1Tpe s1pe e0m* +0em em;0B aem+0 em1; 1e>m 1em*B >e1am Q0e; +Qem0 Qe;", +"T0 ae;Q0 1ep* p1>e pe1T; >eps1 G0em em0W! H0em aemG0 Gm1e 1Gm8e He1m aem1G ", +"em0GQ GQ0em! emZ0 Zeam0 1Gpe pG81e peZ1 Zpes1 fv0 v+f0 vHf0 g0fv fv1 v>f1 f", +"Hv1 fvg1 vQf0 fv+Q0 Z0fv Zfgv0 fp1 p>f1 Z1fp yf1 9e 9e& 9eB 9ae ,1e :e ,B1e", +" :ea 9eK 9Ke& 9Te Te9a 9ej :ej 1T9e s:e 9e* -9e *B9e 9a-e 1e9* :-e ,1e*B -a", +":e e*9K 9e-K Te9* 9T-e ej9* -j:e ,1Te* :-se ,G9 G&9e 9He 9G,a ,1G :Ge 1G,H ", +":He ,K9G e&K9G 9G,T ,GT9a 9G,j ,G:j 1G,T :Gse f9 f-9 f9H gf9 f91 :f ,1fH :f", +"g f9K fK-9 f9T fTg9 f9j :fj ,1fT sf: 9e2 92e& e29B 92ae 95e :e5 9B5e 5a:e e", +"29K e&29K 92Te 9Te&2 5e9j 5e:j 5T9e s5:e 9e; 9e-; 9Be; ae9; 1e,; >e: ,1;eB ", +":a>e 9Ke; -9e;K Te9; -T9e; e;9j >j:e e;j9T s:>e ,29G e&29G 92He ,Ga92 9G,5 ", +",G:5 H59e H5:e ,G92K 9G2e&K ,GT92 ae29GT ,1G5j :G5,j ,1G5T :Hes5 f9; -9f; 9", +"Hf; g;f9 f95 :f> 9Hf5 f>g: 9;fK f-9;K 9Tf; f-T9; 95fj fj:> 95fT s:f> 9eN 9N", +"e& eN9B 9Nae ,N1e :eN ,1eNB ae:N 9Qe Q&9e Qe9T Qa9e 1Q9e :Qe ,1QTe :Qse e*9", +"N 9e-N 9e*NB -9aeN ,1e*N -e:N 1eN9*B :-aeN Qe9* 9Q-e 9QeT* -Q9Te ,1Qe* -Q:e", +" 1Qe9T* s-:Qe 9We W&9e He9W Wa9e 1G,W :We ,1GHW He:W 9G,Q ,GQ9& Z9e 9aZe 1G", +",Q ,G:Q ,1Ze Z:e f9W -Wf9 9HfW gWf9 ,1fW :fW f91HW :Wgf f9Q -Qf9 Zf9 g9Zf ,", +"1fQ :fQ f9Z1 Z:f 9em e&9m 9Bem ae9m 1e,m :em ,1meB ae:m Qe9m em&9Q Te9m aem", +"9Q p9e :pe 9Tpe se:p em9; 9e-m 9em*B -m9ae ,1me; :m>e emB,1; :-mae Qe9; -Q9", +"em 9QeT; -Tm9e 9ep* >e:p p9eT; -ps:e 9G,m em&9G He9m aem9G 1G,m ,G:m ,1GHm ", +"He:m ,GQ9m 9GQem& 9eZm Z9eam ,1pG pG:e p9Ze Ze:p fv9 f9-v fHv9 fvg9 v9f1 :f", +"v fv91H gf:v v9fQ -vf9Q fvZ9 Zf9-v fp9 :fp Z9fp y:f Ie0 I!e0 De0 D0ae 1Ie 8", +"I1e 1De D81e e0IK Ie0!K D0Te ae0TI Ij1e Ije18 De1T 1Dse I*0 +0I* D0I* +0De ", +"1I* +I1e De1* +D1e *0IK I*0+K T0I* +DeT0 Ij1* I*j1+ TI1* 1Is* IeG0 GIe!0 Je", +"0 aeJ0 GI1e 1G8Ie J1e 1aJe GIe0K Ie0GK! TeJ0 JTae0 Ije1G 1G8Ije 1TJe J1se f", +"I0 +If0 Jf0 g0Jf f1I 1+fI Jf1 Jfg1 I0fK f+I0K J0fT JfTg0 1Ifj f1+Ij f1Jj J1", +"sf e0I2 Ie0!2 e0D2 ae0I2 5I1e 1I58e 5D1e 1De5a Ie02K e02IK! DeT02 TI0ae2 Ij", +"e15 5I81ej 1De5T sI15e I0e; I;e+0 D0e; ae;D0 5I1* 1I>e De1; 1D>e I;e0K +I0e", +";K De;T0 ae0TI; I;j1e >I1ej e;j1D sI*>1 GIe02 Ie0G2! e0J2 Jae02 1G5Ie G581I", +"e 1eJ5 J158e Ie0G2K !0I2GeK JTe02 ae0JT2 1G5Ije 8eGj1I5 J15Te sJ15e I;f0 f+", +"I;0 f;J0 Jf;g0 1If5 >If1 f1J5 J1f> fI;0K I;0f+K JfT;0 fT;gJ0 f15Ij f>1Ij Jf", +"15T J>sf1 e0IN Ie0!N e0DN ae0DN Ie1N 1I8eN 1NDe 1DeaN IeQ0 QIe!0 Q0De QDea0", +" QI1e 1QI8e QD1e sI1Qe *0IN I*0+N I*0DN +De0N 1NI* 1+IeN 1De*N 1+DeN Q0I* +", +"QIe0 QDe*0 +QDe0 QI1* 1+QI* 1QDI* sI*1Q IeW0 WIe!0 WeJ0 JWae0 WI1e 1WI8e 1W", +"Je J1W8e GQIe0 QI0We! JeZ0 ZJae0 1GQIe W8I1Qe J1Ze sJZ1e WIf0 f+WI0 fWJ0 Jf", +"Wg0 1WfI f1+WI JWf1 Jf1gW QIf0 fQ+I0 Z0Jf ZfJg0 1QfI f1Q+I JfZ1 Zf1sJ I0em ", +"Ime!0 D0em aemD0 Im1e 1Im8e De1m aem1D ImeQ0 QI0em! QDem0 ae0TIm 1Ipe pI81e", +" 1Dpe pDes1 I0m* Im*+0 Im*D0 am*I0 Im1* >I1em Im*1D >eD1m Im*Q0 Im0+Qe Im*T", +"0 ae0QD; 1Ip* >ep1I pDe1; sI*p1 ImeG0 WI0em! emJ0 Jmae0 1GmIe W8I1em 1eJm J", +"1m8e GQIem0 ImQeW!0 ZJem0 JmaZe0 pG1Ie 1WIpe8 peJ1 Jps1e f0vI fv+I0 J0fv Jv", +"gf0 vIf1 f>v1I fvJ1 J>fv1 fvQI0 vI+fQ0 ZfJv0 JvgZf0 pIf1 fp>1I J1fp Jfy1 h9", +" h9& h9D hc9 h1 h: h1D h:c h9K 9&hK hT9 c9hT h1j h:j h1T hs: h9* h-9 9Dh* h", +"9c- h1* h:- 1Dh* :ch- 9*hK -9hK 9Th* h9-T 9*hj :-hj 1Th* s-h: h9G 9Gh& hJ9 ", +"J9hc h1G h:G hJ1 :Jh 9GhK h9G&K J9hT cJ9hT 9Ghj :Ghj J9hj :Jhs hf9 f9h- Jf9", +" i9 hf1 :fh Jfh1 i: hKf9 f-9hK f9hT i9T f9hj hj:f f9Jj is: h92 9&h2 9Dh2 c2", +"h9 h15 h:5 95hD :ch5 92hK h9&2K 9Th2 hc9T2 95hj :5hj 95hT s:h5 h;9 -9h; 9Dh", +"; h9c; h1; h>: 1Dh; c>h: 9;hK h-9;K 9Th; hc;9T 9;hj :>hj 1Th; s:h> 9Gh2 h9G", +"&2 h2J9 cJ9h2 9Gh5 :Gh5 J9h5 h5:J h9G2K 9G&h2K J9Th2 hcTJ92 h1G5j h:G5j J95", +"hT hsJ:5 f9h; f-9h; J9h; i9; f9h5 :fh> J1h; i:> f9;hK h-;f9K Jf9T; 9Ti; f95", +"hj h>:fj Jf95T s:i> h9N 9&hN 9DhN c9hN h1N h:N 1DhN hN:c hQ9 9Qh& 9QhT h9cQ", +" h1Q h:Q 1QhT s:hQ 9*hN -9hN h9D*N c-9hN 1*hN hN:- h1D*N h:c-N 9Qh* h9-Q hQ", +"9D* c-Qh9 1Qh* :-hQ h1QD* h:Qs- hW9 9Wh& J9hW h9cW h1W h:W J1hW hW:J 9GhQ h", +"W9Q& hZ9 Z9hc 9Whj :GhQ hZ1 hZ: f9hW h9-W JWf9 i9W f1hW hW:f Jf91W i:W f9hQ", +" f-Qh9 Z9hf iZ9 f1hQ hQ:f h1Zf iZ: hm9 9mh& 9Dhm h9cm h1m h:m 1Dhm :chm 9Qh", +"m hQ9m& 9Thm hcQ9m hp9 hp: p9hT h:cp 9mh; h9-m hm9D; c-mh9 1mh; :-hm h1mD; ", +"h:mc> 9Qh; h-Q9m hQ;9D cQ;h9 p9h; h:-p hp9D; cp-h: 9Ghm hW9m& J9hm cJmh9 95", +"hW :Ghm J1hm hm:J hW9Qm 9GQhm& Z9hm hZc9m p9hW hW:p h1Jp Z:hp hv9 v9h- J9hv", +" iv9 hv1 hv: h1Jv i:v v9hQ hv-9Q Z9hv Zvi9 h1fp :fhp Zvh1 yi: eL eL! eLB ae", +"L eL. 8eL .BeL 8Lae Me Me! TeM aMe Mej 8Me TMej seM e*L +eL eL*B +Lae *Le. ", +"+L8e *BeL. aeL8* Me* +Me MeT* Te+M ejM* 8M+e Me*Tj +Mse GeL eLG! HeL GLae e", +"LG. GL8e eLH. HL8e GMe G!Me HMe aMHe MeGj 8eGM MeHj GMse fL f+L fHL gfL fL.", +" f8L HLf. gLf8 fM fM+ fTM gfM fMj f8M HMfj sfM eL2 !Le2 2BeL e2aL 5eL 5L8e ", +"eL5B 5Lae Me2 M!e2 T2Me M2ae 5Me 8M5e Te5M 5Mse e;L +Le; ;LeB aLe; 5Le; >eL", +" e;L5B ae>L Me; M;+e MeT; Mea; Me5* >Me Me;5T se>M eLG2 GeL!2 eLH2 aeLG2 GL", +"5e G58eL HL5e G5aeL G2Me Me2G! H2Me aMeG2 5eGM G5M8e 5MHe se5GM f;L +;fL H;", +"fL f;gL f5L f>L H5fL >Lgf fM; +Mf; HMf; g;fM f5M f>M H5fM >Msf eLN !LeN NBe", +"L eLaN N.eL eN8L eLN.B aeL8N QeM Q!Me QTMe aMQe QMej 8MQe MejQT QesM *LeN e", +"L+N *BeLN aeL+N e*LN. +e8LN eLN*B. 8eLa*N MeQ* Qe+M Me*QT aMe+Q Me*Qj +Qe8M", +" QeTM*j se+QM WeL eLW! HLWe WLae eLW. WL8e HeWL. H8eWL WMe W!Me ZeM aMZe Me", +"Wj 8MWe MeZj sMZe fWL +WfL HWfL fWgL WLf. W8fL fHWL. f8WgL fQM +WfM ZfM gMZ", +"f WMfj W8fM ZMfj fMsZ emL e!mL mLeB aLem 5Lem 8Lem emL5B aem5L Mem M!em MeT", +"m Meam peM 8Mpe TepM sMpe eLm* +Lem em;LB aem+L em;5L em>L 5eLm*B >eamL MeQ", +"; Me+m MemT; aMe+m Mep* pe>M peTM; >Mesp GLem emLW! HLem aemGL 5LWe G8meL H", +"5eWL H8emL MeGm MemW! MeZm ZeaMm GMpe pG8Me ZMpe ZpesM fvL v+fL vHfL gLfv v", +"5fL >Lfv fvH5L f>gvL fvM f+vM fMZv fvgM fpM >Mfp fMZp yfM ,eL e&L eL,B ,Lae", +" eL,. ,L8e ,eL.B aeL,8 ,Me Me& Te,M ae,M Me,j 8e,M Mej,T ,Mse e*,L -eL *Be,", +"L ae-L ,e*L. 8e-L ,eL*B. -8aeL ,eM* -Me Me*,T Te-M Me*,j 8M-e ,TMej* -Mse ,", +"GL ,LG& ,LHe ,LGa GL,. ,LG8 ,GHL. ,G8HL ,GM G&,M GT,M Ga,M GM,j G8,M ,GTMj ", +",GsM f,L f-L ,HfL gLf- ,Lf. -8fL fH,L. f-8gL fM, f-M ,HfM f-gM ,Mfj -Mf8 fT", +"M,j fMs- eL,2 &Le2 ,eL2B aeL,2 ,L5e 5Le& ,5eLB ,5aeL ,2Me M2e& Me2,T aMe,2 ", +"5e,M Me5& ,5TMe se5,M ,Le; e;-L e;L,B ae;-L e;L,5 -e>L ,5Le;B >e-aL Me,; Me", +"-; Me;,T -TMe; Me;,5 -M>e ,5TMe; s->Me GL,2 e&LG2 ,GHL2 ,GaL2 ,LG5 ,G58L ,G", +"5HL ,G5aL ,2GM Me&G2 ,GTM2 Me&H2 G5,M Me&G5 ,G5HM sG,5M ,;fL -;fL fH;,L f-;", +"gL ,5fL >Lf- f5H,L f>g-L ,Mf; f;-M fTM,; f-TM; ,5fM f->M f5T,M f>Ms- eL,N &", +"LeN ,eLNB aeL,N ,eLN. e&L8N eLN,.B ,8LaeN Qe,M MeQ& ,QTMe aMe,Q Mej,Q Me&Q8", +" ,QTMej seM,Q ,e*LN eL-N ,eL*BN -aeLN e*L,N. -8eLN NB*L,e. aeL-8N Me*,Q Qe-", +"M ,QTMe* -QTMe ,QMej* -Q8Me QMej,T* s-QMe ,LWe WLe& ,GHWL ,GaWL ,GWL. ,G8WL", +" HeL,W. aeL,W8 GQ,M MeW& ,GZM MeZ& ,GQMj Me&W8 ZeM,j Ze&sM ,WfL fL-W fHW,L ", +"f-WgL fW,L. f-W8L ,HWfL. gf8-WL ,WfM -WfM fMZ, fMZ- fQM,j f-Q8M ZfM,j sfZ-M", +" ,Lem eLm& emL,B aem,L emL,5 em&5L ,5LemB aeL,8m Me,m emM& Mem,T aMe,m ,Mpe", +" Mep& peT,M pe&sM em;,L em-L ,mLe;B -maeL ,5em*L >e-mL 5m*B,eL -ma>eL Mem,;", +" Me-m ,TmMe; -TmMe peM,; pe-M Me;p,T -psMe ,LGm em&GL ,GmHL em&HL ,G5WL ,G8", +"mL emL,H5 aeL,5W GM,m MemG& ZeM,m Ze&Mm ,GpM pG&,M Zpe,M ZpeM& fLv, fL-v fv", +"H,L -vgfL fv5,L f>-vL v,Hf5L -vgf>L v,fM fM-v Zfv,M -vMZf p,fM fM-p fpZ,M f", +"-yM Ue Ue! UeD Uae Ue. U8e U.De D8Ue UeM U!Me Ve Vea Uej 8MUe Vej seV Ue* U", +"+e DeU* +DUe U.I* +eU8 I*.UD U+eD8 IM* +MUe Ve* V+e I*Uj +eUj I*Vj V+se UGe", +" GeU! JUe UaJe GeU. G8Ue UeJ. U8Je GMUe IM!Ge VJe JaVe GjUe UG8Me VeJj VJse", +" fU fU+ JfU gfU fU. fU8 J.fU fUJ8 fUM U+fM Vf Vfg fUj U+fj Vfj sfV Ue2 e2U!", +" U2De U2ae U5e 5eU8 5DUe 5aUe U2Me IM2e! Ve2 aeV2 5MUe U5e8M V5e V5se Ue; +", +"eU; DeU; aeU; 5IU* >eU U5eD; Ua>e MeU; IM;+e Ve; +eV; IM5* Ue>M 5IV* V>e Ge", +"U2 UGe!2 UeJ2 JUae2 G5Ue UG58e U5Je J5U8e IM2Ge UG2Me! JeV2 VJae2 UG5Me G5M", +"U8e VeJ5 seVJ5 fU; U+f; fUJ; g;fU fU5 f>U fUJ5 gUf> U;fM fU+M; Vf; V;gf U5f", +"M fU>M Vf5 Vf> UeN eNU! UNDe UNae eNU. UN8e UeDN. U8eDN UQe Q!Ue VeQ QaVe Q", +"eUj Q8Ue QeVj sQVe UNI* UN+e I*NUD U+eDN I*NU. U+e8N DeNU*. aeNU8* QIU* +QU", +"e QIV* +QVe IM*Qj IM*Q8 VeQ*j sI*VQ UWe U!We UWJe WaUe U.We W8Ue JUWe. J8UW", +"e GQUe UGQe! ZeV ZaVe WeUj UGQ8e ZjVe VZse fUW U+fW JWfU gWfU UWf. UWf8 JfU", +"W. Jf8UW fUQ U+fQ VfZ ZfgV UWfj UQf8 fjVZ sZVf Uem U!em DeUm aeUm 5eUm 8eUm", +" U5eDm aemU5 QeUm IMme! Vem aeVm pUe U8pe Vpe seVp ImU* +eUm Im*UD aemU+ Im", +"*U5 Ue>m 5DeUm* >eUDm QeU; IMm+e QeV; +eVm Uep* pU>e pIV* >eVp GmUe UGme! U", +"eJm JmUae 5WUe UG8em J5UWe J8mUe IMmWe Im!WMe VeJm ZeVam UGpe pUG8e ZeVp Jp", +"Vse fvU f+vU fUJv fvgU vUf5 v>fU JvfU5 J>fvU vUfQ fvU+Q Vfv gfVv fpU p>fU f", +"pV yVf hU hU& hUD hcU hU. h8U UDh. cUh8 hM hM& Vh Vhc hMj h8M Vhj hsV hU* h", +"-U U*hD -Uhc U*h. -Uh8 hUD*. c-Uh8 hM* h-M Vh* V-h U*hj -Uhj V*hj V-hs hUG ", +"UGh& hJU hUcJ UGh. UGh8 JUh. hUJ8 hMG GMh& VhJ cJVh UGhj G8hM JjVh VhsJ hfU", +" f-U fUhJ iU h.fU fUh8 JfUh. iU8 hfM f-hM Vfh iV fUhj f8hM hjVf iVs hU2 U&h", +"2 UDh2 c2hU h5U U5h8 U5hD hUc5 hM2 M&h2 Vh2 h2Vc h5M 5Mh8 Vh5 c5Vh h;U -Uh;", +" U;hD hUc; U5h; h>U h5UD; >Uhc hM; -Mh; Vh; h;V- U;hj h>M V5h; h>V UGh2 hUG", +"&2 JUh2 cJUh2 UGh5 h5UG8 hUJ5 cJ5hU GMh2 hMG&2 h2VJ VhJc2 G5hM h5MG8 J5Vh V", +"h5sJ fUh; f;-U hUJ; iU; fUh5 fUh> Jf5hU i>U fMh; f-UM; h;Vf iV; f5hM hf>M h", +"5Vf iV> hUN U&hN UDhN cUhN UNh. U8hN hUDN. hcU8N hQU UQh& VhQ cQVh UQhj UQh", +"8 VQhj VshQ U*hN hN-U hUD*N c-UhN hU*N. -U8hN U*DhN. hc8-UN UQh* -UhQ V*hQ ", +"hQV- hQU*j -UQh8 VhQ*j V-hsQ hWU UWh& JUhW hUcW UWh. UWh8 hJUW. hJ8UW hWM W", +"Mh& hZV VhZc UWhj W8hM VZhj sZVh fUhW -UhW JfUhW iUW fUWh. f-UW8 hJWfU. UWi", +"8 fUhQ -UfQ VfhZ iZV fUQhj f-UWj VfZhj sZiV hmU Umh& UmhD hUcm U5hm U8hm h5", +"UDm hc5Um hMm Mmh& Vhm cmVh hpU pUh8 hpV Vphs Umh; -Uhm hmUD; c-mhU h5Um* >", +"Uhm U5*hmD h>cUm UQh; -Mhm Vmh; hmV- pUh; >Mhp h;Vp V-hp UGhm hWUm& hUJm cJ", +"mhU U5hW h5WU8 hJ5UW c5WhU GMhm hWMm& JmVh VhmZc pUhW hpUG8 VphZ cpJVh hvU ", +"fU-v vUhJ ivU vUh5 vUh> hvJU5 v>iU hvM hM-v hvV iVv hMfp >Mhv Vfhp yiV ke k", +"e! keB ake 1ek 8ke 1Bke ak1e keM M!ke Tke akTe le le8 leT lse ke* +ke *Bke ", +"ak+e ke1* +k1e ke*1B ake1+ Mek* ke+M keT* Tk+e le* l+e Tel* sel+ Gke G!ke H", +"ke akHe Gk1e 8eGk Hk1e 8kHe keGM keMG! TkHe akeGT lGe G8le lHe sGle fk fk+ ", +"fkH gfk f1k f8k 1Hfk f1gk fkM +kfM fTk fTgk lf lf+ lfH glf ke2 k!e2 e2kB k2", +"ae 5ke 8k5e 5Bke ak5e k2Me keM!2 T2ke akeT2 le5 5el8 5Tle l5se ke; k;+e kBe", +"; kea; ke1; >ke ke;1B ak>e Mek; ke;+M keT; akeT; le; l>e Tel; >els G2ke ke2", +"G! H2ke akeG2 5eGk G5k8e 5kHe akeG5 keMG2 Gk2Me! GTke2 ak2HMe G5le lG58e H5", +"le lsG5e fk; +kf; Hkf; g;fk f5k f>k H5fk gf>k k;fM fk+M; Tkf; fTkg; lf5 lf>", +" f5lH l>sf keN k!eN eNkB aNke 1Nke kN8e keN1B ake1N Qke Q!ke TkQe akQe leQ ", +"Q8le QelT lQse e*kN +Nke ke*NB ake+N ke*1N 1+ekN 1eNk*B akN1+e keQ* Qk+e Qk", +"eT* ake+Q Qel* +Qle leQT* lse+Q Wke W!ke WkHe akWe Wk1e 8kWe 1HeWk ake1W Qk", +"We GQke! Zke akZe lWe W8le lZe sZle fkW +Wfk HkfW gWfk 1Wfk W8fk f1HWk f8kg", +"W fQk +Qfk Zfk gkZf lfW fQl+ lfZ Zfgl kem k!em kBem keam ke1m ke8m kem1B ak", +"e1m kmQe kemQ! keTm akeTm lep l8pe lTpe sple emk; ke+m kem*B ake+m kem1; ke", +">m keB1m* >keam keQ; kem+Q kemT; akeQ; pel; p>le lepT; l>esp keGm kemW! keH", +"m akeGm Wk5e kemG8 kem1H ake5W kemGQ ke!GMm keZm Zkeam pGle lGp8e Zple lZes", +"p fvk f+vk fHvk fvgk v1fk fv>k fv1Hk f>kgv vkfQ fvk+Q fvZk Zfkgv lfp l>fp Z", +"flv ylf ,ke ke& ,Bke ak9e 1e,k :ek keB,1 ak:e 9Me Mek& Tk9e aM9e le9 l:e ,T", +"le s:le ke9* -ke ke*,B ak-e ke*,1 -k:e ,1ek*B :-ake Me9* 9M-e ,Tke* Tk-e 9e", +"l* l-e le9T* les- ,Gk G&,k Gk,H Ga,k 1G,k ,G:k ,1GHk Hk:e 9G,M ke&GM GT,k a", +"Me9G lG, :Gle ,GlH sGl, f9k f-k ,Hfk f-gk ,1fk :fk f91Hk gk:f f9M -kfM ,Tfk", +" f9gM lf9 lf: f9lH sfl- ,2ke k2e& ke2,B ake,2 5k9e 5k:e ,5keB :e5ak 92Me ke", +"&M2 ,Tke2 aMe92 ,5le l5:e le95T lse:5 ke,; ke-; ke;,B -kae; ke;,1 :e>k keB,", +"1; >k-ae Me9; -kMe; ke;,T -Tke; ,;le >el- le;,T l>es- ,2Gk ke&G2 ,GkH2 ke&H", +"2 G5,k :G5,k ,G5Hk :He5k ,GkM2 ke2GM& ,GTk2 ak2,GT ,Gl5 l:G,5 lG,H5 :Hel5 ,", +"kf; f;-k f9Hk; f-kg; ,5fk >k:f f95Hk f>kg: 9Mf; f-kM; f9Tk; f-Tk; f9l; l>:f", +" lf9H5 glf:> ,Nke kNe& keN,B ake,N keN,1 ke:N ,1NkeB :eakN Qk9e keQ& ,QkTe ", +"ake,Q ,Qle :Qle le9QT :Qels ke*,N ke-N 9eNk*B -kaeN ,1ek*N :-keN ke1*,NB -k", +"a:eN ,Qke* Qk-e Qke9T* -QkTe le9Q* -Qle 9Qel*T l-sQe Gk,W keW& ,GkHW ake,W ", +",1GWk Wk:e 1He,Wk :HeWk GQ,k ke&GQ ,GZk keZ& ,GlW :Wle Z9le leZ: ,Wfk -Wfk ", +"f9HWk f-kgW f91Wk fk:W ,1HfkW :fgWk ,Qfk -Qfk f9Zk f-Zk f9lW lW:f l,Zf Z:lf", +" ke,m emk& kem,B ake,m kem,1 ke:m keB,1m :emak Me9m kemQ& kem,T aMe9m p9le ", +"le:p lep,T :pels kem,; ke-m keB9m* -kmae ,1mke; :-mke ke,m1;B :ea-km ke;,Q ", +"-Qkem ,Tmke; -Tkem lep,; le-p leTp9* l-pse Gk,m kemG& kem,H akm,G ,1Gkm :Gm", +",k ,1Hkem :Hekm Mem9G ,GQkm& Z9ekm Zkem& pGl, :pGle lZep9 Z:elp v9fk fk-v f", +"v9Hk -vkgf fv95k fk:v f1Hvk, :fvgk v9fM -vkfQ Zf9vk Z-kfv l,fp :flv fp9lZ l", +"fy: Uek U!ke Dke akUe 1Ue U81e Ue1D Ua1e keIM IkMe! Vek akVe lIe U8le leV s", +"Ile Ik* +kUe IkD* Dk+e Ue1* U+1e Ik*1D ak*1I k*IM Ik*+M IkV* +kVe lI* U+le ", +"Vel* sIl* GkUe Ik!Ge Jke akJe UG1e 1UG8e 1UJe 8kJe IkMGe UGkMe! VeJk JkVae ", +"UGle lGU8e lJe lesJ fUk U+fk Jfk Jfgk f1U 1Uf8 f1Jk f1gU IkfM fU+kM Vfk gkV", +"f lfU fUl+ lfJ Vfgl U2ke Ik2e! D2ke akeU2 U51e 1Ue58 Dk5e akeU5 IkMe2 ke2IM", +"! keV2 Veka2 U5le lI58e V5le seVl5 keU; Ik;+e keD; akeU; Ue1; 1U>e Ik*5D Dk", +">e Ik;Me +IkMe; keV; V+ek; Uel; lI>e Vel; leV> Ik2Ge UG2ke! keJ2 Jkae2 1UG5", +"e G5kU8e 5kJe J5k8e UGkMe2 IkGMe2! JkVe2 VeaJk2 lGU5e UG5le8 J5le lJs5e U;f", +"k fU+k; fkJ; Jfkg; 1Uf5 fU>k f5Jk Jf>k fUkM; Ik;fM+ V;fk Vfgk; fUl; lIf> l;", +"Vf J>lf UNke IkNe! DNke akeUN 1NUe 1Ue8N 1UeDN 1UaeN QkUe UQek! QkVe VeQak ", +"UQle lIQ8e lQVe seVlQ INk* Ik*+N Ik*DN ak*IN Ik*1N Ik*8N IkN1D* akN1I* IkQ*", +" Ik*+Q VeQk* V+eQk QIl* l+IQe lI*VQ sI*lQ WkUe UWek! WkJe JkWae UW1e 1UW8e ", +"J1UWe J8kWe UGQke Ik!WMe JkZe ZJkae UWle lWI8e ZJle lJZse UWfk fU+Wk JWfk J", +"fkgW 1UfW f1U+W Jf1UW Jf8Wk UQfk fUQ+k ZkVf VfZgk fUlW lfU+W ZflJ glJZf keU", +"m Ikme! keDm akeUm Ue1m Ikm8e kem1D aem1U IkmQe Ik!Mem keVm Vemak pUle lIp8", +"e leVp Vpels kmI* Ikm+e IkmD* akmI* Ikm1* >kIem 1Dekm* >kDem IkmQ* U+Qkem V", +"emk; V+ekm pIl* l>Ipe Vpel; V>elp IkmWe Im!Wke keJm Jkmae 1UGem UG8kem J1mU", +"e J8kem UGQkem ImQkWe! ZJkem ZkaVem lGpUe lG8pUe leJp Jplse vUfk fvU+k fvJk", +" Jvkgf v1fU f>Uv1 Jv1fU J>kfv fvUQk fQ+vIk fkVv Vfvgk lIfp fpUl> Jplf lfyJ ", +"ht ht& htD htc ht1 h:t t1hD t:hc htM tMh& Vht tcVh lh lh: lhV uh ht* t-h hD", +"t* hct- t*h1 t-h: t*1hD h:tc- t*hM hMt- t*Vh Vht- lh* l-h l*Vh uh- htG h&tG", +" tJh hctJ tGh1 tGh: h1tJ tJh: tGhM tGMh& VhtJ tJVhc lhG lGh: lJh uJh tf tf-", +" tfJ it tf1 tf: J1tf it: tfM fMt- tfV iVt lfh tfl- lJtf ui ht2 t&h2 tDh2 h2", +"tc ht5 t:h5 hDt5 tch5 tMh2 htM&2 h2Vt Vhtc2 lh5 h5l: t5Vh uh5 ht; h;t- hDt;", +" tch; t5h; h>t t5*hD htc> t;hM t-hM; t;Vh V-ht; lh; h>l l;Vh uh> h2tG tG&h2", +" h2tJ tJhc2 tGh5 t:Gh5 h5tJ tJ5h: tGMh2 hM&tG2 tJVh2 VhctJ2 h5lG lh:G5 h5lJ", +" hJu5 tf; f-t; h;tJ it; tf5 tf> Jft5 it> fMt; tf-M; t;Vf t;iV l;tf h>lf hJl", +"; ui> htN t&hN tDhN hNtc t1hN hNt: ht1DN h:tcN htQ h&tQ tQVh tchQ lhQ hQl: ", +"VlhQ uhQ hNt* hNt- t*DhN t-hcN t*1hN h:t-N h1Dt*N t-ch:N t*hQ hQt- tQ*Vh V-", +"htQ hQl* hQl- lhVQ* h-uQ htW h&tW hWtJ tchW tWh1 t:hW tJh1W h:WtJ tGhQ tGQh", +"& hZt htZc lhW lWh: hZl uZh tfW hWt- JftW itW f1tW tW:f tfJ1W t:iW tfQ f-tQ", +" tZf iZt lWtf h-lW hZlf uiZ htm h&tm hDtm tchm t5hm t:hm ht5Dm h:mtc tQhm h", +"tQm& tmVh Vhmtc hpl h:tp Vplh uph tmh; hmt- tm*hD t-mhc t5*hm hmt> tmDh1; h", +">tcm tQh; t-Qhm Vhmt; V-mht l;hp hpl- lh;Vp hpu- tGhm tGmh& hmtJ tJmhc t5hW", +" h:Wt5 tJ5hW :Jmht tGQhm tG&hMm hmtZ hZtcm lGhp lhW:p tZhp hZup hvt t-hv tJ", +"hv itv h1tv tvh> hvtJ1 tvi: hQtv hvt-Q tZhv tZiv lvh hvl- hZlv uiy 3 !3 3B ", +"a3 3. 83 .B3 8a3 3K !K3 T3 Ta3 j3 8j3 Tj3 s3 3( +3 3B( +a3 3(. +83 3(.B 8a+", +"3 3(K +3K T3( +T3 j3( +j3 j3T( s+3 E3 !E3 H3 Ha3 E3. 8E3 H3. H83 EK3 !3EK H", +"T3 TaH3 jE3 jE83 Hj3 sH3 d3 +d3 Hd3 g3 d3. 8d3 d3H. g83 dK3 dK+3 Td3 gT3 dj", +"3 +3dj H3dj gs3 4 4! 4B 4a 45 48 45B 48a 4K 4K! 4T 4Ta 4j 48j 4T5 s4 4; 4+ ", +"4;B 4+a 45; >4 5;4B >4a 4;K 4+K 4T; 4+T 4j; >j4 T;4j s>4 4E 4E! 4H 4Ha 45E ", +"48E 4H5 4H8 4EK EK4! 4HT HT4a 4jE 8j4E 4Hj s4H 4d 4+d 4Hd g4 4d5 >4d H54d g", +">4 4dK +d4K 4Td g4T 4dj 4d>j H;4j gs4 3N !3N 3BN a3N N.3 83N 3BN. aN83 Q3 Q", +"!3 QT3 Qa3 Qj3 Q83 TjQ3 sQ3 3(N +3N 3(NB a3+N 3(N. 83+N 3(N.B +8a3N Q3( +Q3", +" T3Q( +3Qa j3Q( +3Q8 QTj3( +Qs3 W3 W!3 HW3 Wa3 W3. W83 W3H. H3W8 WQ3 W3Q! Z", +"3 Za3 Wj3 W3Q8 Zj3 sZ3 Wd3 +W3 WdH3 gW3 d3W. +3W8 HWd3. W8g3 Qd3 +3Qd Zd3 g", +"Z3 W3dj +3Wj djZ3 g3sZ 4m 4m! 4mB 4am 45m 48m 5m4B 8m4a 4Q 4Q! 4QT 4Qa p4 p", +"48 p4T sp4 4m; 4+m m;4B +m4a 5m4; >m4 45m;B 4a>m 4Q; 4+Q Q;4T +Q4T p4; p>4 ", +"4Tp; p>s4 4W 4W! 4HW 4Wa 4W5 4W8 H54W H84W 4WQ Q!4W Z4 Z4a p4W 4Wp8 Zp4 sZ4", +" v4 v4+ v4H gv4 v45 v>4 4Hv5 v>g4 v4Q 4+vQ Zv4 gZ4 pv4 p4v> pvZ4 y4 #3 &3 #", +"B3 a&3 #3. 8&3 #3.B a&83 #3K &3K T#3 T&3 j#3 &j3 j#T3 s&3 #3( +&3 #3(B a&+3", +" 3(#. 8&+3 .B3#( +8a&3 3(#K &3+K #3T( +3T& #3j( +3&j Tj#3( +&s3 #E3 &E3 H#3", +" H&3 E3#. &E83 #3H. 8&H3 #3EK EK&3 T#H3 H3T& #Ej3 jE&3 j#H3 H&s3 d#3 d&3 d#", +"H3 g&3 #3d. 83d& Hd#3. 8&g3 #3dK &3dK d#T3 T&g3 j#d3 d3&j dj#H3 s&g3 4# 4& ", +"4#B 4a& 45# 48& 5B4# 5a4& 4#K 4&K 4T# 4T& 4j# 4&j 4#5T s4& 4;# 4+& ;#4B a;4", +"& 5;4# >&4 45;#B 4a>& ;#4K 4K;& 4#T; +T4& 4#;j 4&>j ;j#4T >&s4 4#E 4&E 4H# ", +"4H& 5#4E 4E5& 4#H5 H54& EK4# &E4K HT4# H&4T j#4E 4E&j 4#Hj 4Hs& 4d# 4d& 4#H", +"; g4& 4#5d 4d>& 4H5d# >&g4 dK4# 4Kd& 4#Td 4Tg& 4#dj d&4j 4Hjd# g&s4 #3N &3N", +" #3NB &3aN #3N. &38N 3BN#. 8a&3N Q#3 Q&3 T#Q3 Q3T& j#Q3 Q3&j QTj#3 Q&s3 3(#", +"N &3+N 3(N#B +a&3N 3(N#. +8&3N 3B(N.# 8a&+3N #3Q( +3Q& QT#3( +QT&3 Qj#3( &j", +"3+Q Tj#Q3( s+Q&3 W#3 W&3 W#H3 H3W& #3W. 8&W3 HW#3. H8W&3 Q#W3 W3Q& Z#3 Z&3 ", +"j#W3 W3&j j#Z3 s3Z& d#W3 +3W& HWd#3 W&g3 Wd#3. d&3W8 Wd#H3. gW8&3 d#Q3 Q3d&", +" d#Z3 g3Z& dj#W3 d&jW3 Zdj#3 Z&3gs 4m# 4&m m#4B am4& 5m4# 8m4& 45m#B am&48 ", +"4Q# 4Q& 4#Tm Qa4& p4# p&4 4Tp# p&s4 m;4# +m4& 4m;#B am&4+ 45m;# 4&>m 5m;4#B", +" >m4a& 4#Q; +Q4& 4QT;# 4+QT& 4;p# p4>& p4T;# p>4s& 4W# 4W& 4#Hm Hm4& 4#5W 5", +"W4& 4H5W# 4H8W& WQ4# W&4Q Z4# Z4& 4Wp# 4Wp& p4Z# Z&s4 v4# v&4 4Hv# v&g4 45v", +"# v4>& v4H5# gv>4& 4Qv# 4Qv& v4Z# Z&g4 v4p# p4v& Zpv4# y&4 C3 !C3 D3 Da3 C3", +". 8C3 D3. D83 CK3 !3CK DT3 TaD3 jC3 jC83 Dj3 sD3 C3( +C3 D3( +D3 3(C. 8C+3 ", +"3(D. +3D8 3(CK CK+3 T3D( DT+3 C3j( jC+3 j3D( +Ds3 CE3 CE!3 HD3 DaH3 E3C. CE", +"83 D3H. H3D8 C3EK EKC!3 DTH3 HDTa3 CEj3 8jCE3 H3Dj HDs3 dC3 dC+3 Dd3 gD3 C3", +"d. dC83 d3D. D8g3 CKd3 +dC3K D3Td DTg3 jCd3 djC+3 D3dj sDg3 4C 4C! 4D 4Da 4", +"5C 48C 4D5 4D8 4CK CK4! 4DT DT4a 4jC 8j4C 4Dj s4D 4;C 4+C 4D; 4+D 5;4C >C4 ", +"45D; >D4 ;C4K +C4K D;4T +D4T 4C;j 4j>C D;4j >Ds4 4CE !C4E 4HD HD4a 5C4E 8C4", +"E H54D H84D EK4C 4CE!K HD4T 4HDTa jC4E 48jCE Hj4D 4HsD 4dC +d4C 4Dd g4D 4C5", +"d 4d>C 5D4d >Dg4 dK4C 4+dCK Dd4T 4DgT 4Cdj >j4dC Dd4j gDs4 C3N C3!N D3N a3D", +"N C3N. C38N N.D3 83DN QC3 !CQ3 QD3 DaQ3 jCQ3 8CQ3 Q3Dj QDs3 3(CN C3+N 3(DN ", +"D3+N C3N(. +8C3N D3(N. +D83N C3Q( QC+3 D3Q( +3QD QjC3( +Q8C3 QDj3( s+QD3 WC", +"3 !CW3 WD3 DaW3 C3W. 8CW3 D3W. W3D8 QCW3 Q!WC3 ZD3 DaZ3 jCW3 W8QC3 DjZ3 ZDs", +"3 dCW3 WC+3 W3Dd WDg3 WdC3. +W8C3 WDd3. gWD83 dCQ3 +WQC3 DdZ3 ZDg3 djCW3 +W", +"jC3 ZDdj3 gZsD3 4mC mC4! 4Dm Dm4a 5m4C 4C8m 45Dm Dm48 4QC 4CQ! 4QD QD4a p4C", +" 48pC pD4 pDs4 m;4C 4C+m 4mD; +m4D 45m;C 4m>C 4D5m; 4D>m 4CQ; 4C+Q Q;4D +Q4", +"D 4;pC p4>C 4Dp; p4>D 4WC W!4C 4WD WD4a 4C5W 4CW8 5W4D WD48 WQ4C 4WQ!C Z4D ", +"4DZa 4WpC p4W8C pDZ4 sDZ4 v4C 4+vC vD4 vDg4 45vC v4>C 4Dv5 v4>D 4QvC v4+QC ", +"vDZ4 gDZ4 v4pC pv>4C p4vD y4D b3 b&3 bD3 c3 b3. b83 D3b. c83 bK3 &3bK bT3 c", +"T3 bj3 b3&j b3Dj sc3 b3( b+3 D3b( c+3 3(b. +8b3 bD3(. +8c3 3(bK +3bK T3b( +", +"Tc3 j3b( b3+j bTj3( c+s3 bE3 &Eb3 bH3 cH3 E3b. 8Eb3 H3b. H8c3 EKb3 bK&E3 HT", +"b3 HTc3 jEb3 &jEb3 b3Hj cHs3 bd3 b3d& b3Dd gc3 d3b. b38d bHd3. c8g3 dKb3 d&", +"3bK b3Td cTg3 b3dj d&jb3 bHjd3 g3sc 4b 4b& 4bD c4 4b5 4b8 b54D c45 4bK bK4&", +" 4bT c4T 4bj b84j b54T sc4 4b; 4b+ b;4D c4+ 45b; >b4 4b5D; c>4 4Kb; 4Kb+ b;", +"4T 4+cT b;4j 4b>j 4bT;j s4c> 4bE b&4E 4bH c4H 4Eb5 4Eb8 b54H 4Hc5 bK4E 4b&E", +"K bH4T 4HcT 4Ebj 4b8jE bH4j sHc4 4bd b+4d bH4d gc4 b54d 4b>d 4bH5d g4c> 4Kb", +"d 4b+dK bT4d gTc4 bd4j >b4dj 4bHdj scg4 b3N &3bN D3bN c3N N.b3 83bN bD3N. 8", +"3cN bQ3 b3Q& b3QD cQ3 Qjb3 b3Q8 bQDj3 s3cQ 3(bN +3bN bD3(N +3cN b3(N. b+83N", +" D3(bN. c+83N Q3b( b3+Q bQD3( +Qc3 bQj3( b+Q83 QD3bj( cQ+s3 bW3 b3W& b3WD c", +"W3 W3b. b3W8 bHW3. W8c3 WQb3 bWQ&3 Zb3 Zc3 b3Wj bW8Q3 bjZ3 s3Zc Wdb3 b3+W b", +"HWd3 g3cW bWd3. b+W83 WD3bd. cW8g3 b3Qd b+WQ3 bdZ3 g3Zc bWjd3 b+Wj3 Zbdj3 Z", +"cgs3 4bm bm4& bm4D c4m 45bm bm48 4b5Dm 48cm 4bQ bQ4& bQ4D c4Q pb4 4bp& 4bpD", +" cp4 4mb; bm4+ 4bDm; 4+cm 4b5m; 4b>m b5m4D; >mc4 b;4Q b+4Q 4bQD; 4+cQ 4bp; ", +"p4>b pb4D; p>c4 4bW bW4& bH4W c4W b54W bW48 4bH5W 4Wc5 bW4Q 4bWQ& Z4b Zc4 4", +"bpW pb4W8 pbZ4 s4Zc vb4 4bv& 4bvD cv4 4bv5 v4>b vb4H5 v>c4 4bvQ vb4+Q vbZ4 ", +"g4Zc p4vb pvb>4 Zpbv4 yc4 6 6! 6B 6a 61 68 61B 68a 6K 6!K 6T 6Ta 6j 68j 6T1", +" s6 6( 6+ 6(B 6+a 61( 6+1 1(6B 1+6a 6(K 6+K 6T( 6+T 6j( 6+j 6(1T s6+ 6E 6!E", +" 6H 6Ha 61E 68E 6H1 6H8 6EK EK6! 6HT HT6a 6jE 8j6E 6Hj s6H 6d 6+d 6Hd g6 6d", +"1 68d 1H6d g61 6dK +d6K 6Td g6T 6dj +j6d 1T6d gs6 46 6!4 46B 4a6 7 78 7B 7a", +" 46K 4K6! 4T6 6T4a 7j 78j 7T 7s 6; 4+6 6;B 6a; 7; 7> 7B; 7>a 6;K 4K6+ 6T; 6", +"+4T 7;j 7>j 7T; 7s> 46E 4E6! 4H6 6H4a 7E 78E 7H 7H8 6E4K 6!4EK 6H4T 4H6Ta 7", +"jE 8j7E 7HT 7sH 4d6 6+4d 6H; g46 7d 7>d 7Hd g7 4K6d 4+6dK 6T4d 4Tg6 7dj >j7", +"d 7Td g7s 6N 6!N 6NB 6aN 61N 68N 1N6B 6N1a 6Q 6Q! 6QT 6Qa 6Q1 6Q8 1Q6T s6Q ", +"6(N 6+N (B6N +a6N 1(6N 6N1+ 61(NB 6+1aN 6Q( 6+Q QT6( +Q6T 6(1Q 1+6Q 6Q1T( 6", +"+sQ 6W 6W! 6HW 6Wa 6W1 6W8 1H6W 1W6a 6WQ Q!6W Z6 Z6a 6Wj W86Q Z61 sZ6 6Wd 6", +"+W HW6d g6W 1W6d 1+6W 6H1Wd 6Wg1 6Qd +W6Q Z6d gZ6 1Q6d +W6j 6dZ1 sZg6 6m 6m", +"! 6mB 6am 7m 78m 7Bm 7am 4Q6 Q!6m 6Tm 6Q4a 7p 7p8 7pT 7sp 6m; 6+m m;6B +m6a", +" 7m; 7>m m;7B >m7a 6Q; 6+4Q Q;6T +T6m 7p; 7p> pT7; 7ps> 4W6 6!4W 6Hm 6W4a 7", +"W 7W8 7HW 7Wa 6W4Q 4WQ6! Z46 4aZ6 7pW pW78 7Z 7Zs v6 v6+ v6H gv6 7v 7v> 7vH", +" g7v v6Q 6+vQ Zv6 Zvg6 7vp pv7> 7Zv y7 69 6& 69B 6a9 691 :6 916B :6a 69K 6&", +"K 6T9 6T& 6j9 :6j 9T6j s:6 69( 6+9 9(6B 9+6a 916( :6+ 691(B 6+:a 9(6K 6K9+ ", +"6(9T 9+6T 6(9j 6+:j 6T91( :6s+ 69E 6&E 6H9 6H& 916E :6E 691H :H6 9E6K &E6K ", +"9H6T H&6T 6E9j 6j:E 9H6j :Hs6 6d9 6d& 9H6d g69 691d :d6 6H91d g:6 6K9d 6Kd&", +" 9T6d 6Tg9 9d6j 6d:j 6Hj9d s:g6 49 49& 49B 49a 79 7: 7B9 7:a 49K 4K6& 49T 6", +"T4& 79j 7:j 7T9 7s: 49; 49+ 4B9; 9+4a 79; 7:> 9;7B :>7a 4K9; 4K9+ 9T6; 9+4T", +" 9;7j >j7: 9T7; 7:s> 49E 4E6& 49H 6H4& 79E 7:E 7H9 7:H 9E4K 49&EK 9H4T 49HT", +"& 9j7E :j7E 9H7T 7Hs: 49d 6d4& 9H4d g49 7d9 7:d 9H7d g7: 4K9d 49+dK 9T4d 49", +"gT 9d7j 7j:d 9T7d 7sg: 69N 6&N 9N6B 6N9a 916N :6N 691NB 6a:N 6Q9 6Q& 9Q6T 9", +"Q6a 9Q6j :Q6 6Q91T :Qs6 9(6N 6N9+ 69(NB 6+9aN 691(N 6+:N 91(6NB :6+aN 6(9Q ", +"9+6Q 6Q9T( 6+Q9T 6Q91( 6+:Q 9Q16T( :Q6s+ 6W9 6W& 9H6W 9W6a 691W :W6 6H91W 6", +"H:W 9W6Q W&6Q Z69 Z6& 9W6j 6W:Q 6jZ9 Z:6 9W6d 9+6W 6H9Wd 6Wg9 6W91d 6+:W 9H", +"16Wd :Wg6 9Q6d Qd6& 6dZ9 Z6g9 6Wj9d 6Q:d Z691d g6Z: 49m 6m& 4B9m 9a6m 79m 7", +":m 9m7B :m7a 49Q 6Q4& 9Q4T 9Q4a 7p9 :p7 p97T :p7s 9m6; 9+6m 49m;B 49+am 9m7", +"; :m7> 7B9m; 7:>am 9Q6; 9+4Q 49QT; 49+Qa 7;p9 7>:p 7p9T; 7p>s: 49W 6W4& 9H4", +"W 9W4a 7W9 7:W 9H7W :H7W 9W4Q 49WQ& Z49 49Z& p97W 7W:p 7Z9 7Z: v69 v6& 49vH", +" v6g9 7v9 :v7 v97H :vg7 49vQ 6Qv& v6Z9 Z4g9 p97v :p7v Z97v y7: 6C 6!C 6D 6D", +"a 61C 68C 6D1 6D8 6CK CK6! 6DT DT6a 6jC 8j6C 6Dj s6D 6C( 6+C 6D( 6+D 1C6( 6", +"C1+ 6(1D 1+6D CK6( +C6K DT6( +D6T jC6( 6C+j 6(Dj 6+sD 6CE !C6E 6HD HD6a 1C6", +"E 8C6E 1H6D H86D EK6C 6!CEK HD6T 6HDTa jC6E 68jCE Hj6D 6HsD 6dC +d6C 6Dd g6", +"D 6C1d 6C8d 1D6d 6Dg1 dK6C 6+dCK Dd6T 6DgT 6Cdj 6+jdC Dd6j gDs6 46C 4C6! 4D", +"6 6D4a 7C 78C 7D 7D8 6C4K 6!4CK 6D4T 4DT6a 7jC 8j7C 7DT 7sD 6;C 4C6+ 6D; 6+", +"4D 7;C 7>C 7D; 7>D ;C6K 4+6CK D;6T 4+D6T ;j7C 7j>C D;7T 7Ds> 6C4E 6!4CE 6H4", +"D 4H6Da 7CE 8C7E 7HD H87D 46CEK 4CE6!K 4H6DT 6HD4Ta jC7E 78jCE Hj7D sH7D 4C", +"6d 4+6dC 6D4d 4Dg6 7dC >C7d 7Dd g7D 4d6CK 6+C4dK 4Dd6T g46DT dj7C 7>djC Dd7", +"T 7Dgs 6CN !C6N 6DN Da6N 1C6N 8C6N 6N1D 6ND8 6QC 6CQ! 6QD QD6a 6C1Q 6CQ8 1Q", +"6D 6QsD C(6N +C6N D(6N 6N+D 61C(N 6+1CN 6D1(N 6+D1N QC6( 6C+Q 6(QD +Q6D 6Q1", +"C( 6+Q1C 6QD1( s6+QD 6WC W!6C 6WD WD6a 6C1W 6CW8 1W6D WD68 WQ6C 6WQ!C Z6D 6", +"DZa 6CWj 6W8QC 6DZ1 sDZ6 Wd6C 6C+W WD6d 6WgD 6W1dC 6+W1C 6WD1d g61WD 6CQd 6", +"+WQC 6DZd gDZ6 6WjdC 6+WjC Z61Dd gZ6sD 6mC mC6! 6Dm Dm6a 7mC 8m7C 7Dm D87m ", +"4C6Q 4Q6!C 6Q4D 4QD6a 7pC p87C 7pD 7Dsp m;6C 6C+m Dm6; +D6m m;7C 7m>C Dm7; ", +">m7D 6CQ; 4+Q6C QD6; 4+Q6D p;7C >C7p 7;pD p>7D 4C6W 4W6!C 6W4D 4WD6a 7WC W8", +"7C 7WD WD7a 4WQ6C 6WC4Q! 4DZ6 Z46Da pW7C 7pW8C 7ZD 7DsZ v6C 6+vC v6D vDg6 7", +"vC >C7v 7vD 7Dgv 6QvC v6+QC vDZ6 Zv6gD 7Cpv 7p>vC 7DZv y7D b6 b6& b6D c6 b6", +"1 :b6 6Db1 :c6 b6K bK6& b6T c6T b6j b6:j 6Dbj sc6 b6( b6+ b(6D c6+ 61b( b6:", +"+ b61D( :+c6 6(bK bK6+ b(6T 6+cT b(6j 6+bj b6T1( s+c6 b6E bE6& b6H c6H 61bE", +" b6:E 6Hb1 c6:H 6EbK b6&EK 6HbT 6HcT bE6j :b6jE 6Hbj sHc6 b6d 6+bd 6Hbd gc6", +" 6db1 b6:d b6H1d :cg6 bK6d b6+dK 6Tbd gTc6 6dbj :db6j b6Hdj scg6 4b6 b64& 4", +"9D c46 7b 7:b 7bD 7c 4Kb6 4b6&K b64T 49cT 7bj :b7j 7bT 7cs b6; b64+ 6Db; c6", +"; 7b; 7>b b;7D 7c> bK6; 4b+6K 6Tb; 6Tc; b;7j >j7b bT7; c>7s 4Eb6 4b6&E b64H", +" 49cH 7bE 7E:b 7bH 7cH 4b6EK b6E4&K 4bH6T c46HT bj7E 7:bjE bH7T 7Hsc b64d 4", +"b+6d 6Hb; c4g6 7bd :d7b bH7d g7c 4bd6K d&Kb6; 4bT6d c6;gT bd7j 7:dbj bT7d g", +"s7c b6N bN6& bN6D c6N 61bN b6:N b61DN cN:6 b6Q 6&bQ 6QbT c6Q 6Qb1 b6:Q b6Q1", +"D c6:Q 6(bN bN6+ b6D(N 6+cN b61(N :b6+N 6D(b1N :c6+N b(6Q 6+bQ b6QD( 6+cQ b", +"6Q1( :Qb6+ b6(1QD :cQ6+ b6W 6&bW 6HbW c6W 6Wb1 b6:W b6H1W c6:W 6WbQ b6WQ& Z", +"b6 Zc6 6Wbj :Wb6Q b6Z1 s6Zc 6Wbd 6+bW b6HWd cWg6 b6W1d :Wb6+ 6WDb1d g:c6W 6", +"Qbd b6+Qd b6Zd g6Zc b6Wdj :Qdb6 Zb61d Zc6g: b6m 6&bm 6Dbm c6m 7bm :m7b bm7D", +" 7cm b64Q 4bQ6& 6Tbm 49cQ 7pb 7b:p pb7D 7cp 6mb; 6+bm 49Dm; 6+cm bm7; >m7b ", +"7bDm; cm7> 6Qb; 4b+6Q 49QD; 6Qc; 7;pb p>7b 7pbD; 7pc> b64W 4bW6& 6Hbm 49cW ", +"7bW :W7b bH7W 7cW 4bW6Q b6W4Q& 4bZ6 c4Z6 pb7W 7pb:W 7Zb 7Zc vb6 b6v& 49vD c", +"v6 7vb 7b:v vb7H 7cv b6vQ vb6+Q vbZ6 Z6cv pv7b :vb7p Zv7b y7c 3L !3L 3BL a3", +"L 3L. 83L 3L.B a38L M3 M3! TM3 aM3 Mj3 8M3 MjT3 sM3 3(L +3L 3(LB a3+L (L3. ", +"83+L 3L.(B +8a3L M3( +M3 M3T( +3aM j3M( +38M TMj3( +Ms3 E3L E3!L H3L a3HL 3", +"LE. E38L 3LH. 83HL ME3 !EM3 HM3 H3aM jEM3 ME83 MjH3 HMs3 d3L d3+L d3HL g3L ", +"3Ld. d38L Hd3L. 83gL dM3 +3dM H3dM gM3 Mjd3 83dM dMjH3 sMg3 4L 4L! 4LB 4aL ", +"45L 48L 5B4L 4L5a 4M 4M! 4TM 4aM 4M5 48M 5T4M s4M 4;L 4+L ;L4B 4La; 5;4L >L", +"4 45;LB 4a>L 4M; 4+M T;4M +T4M M;4j >M4 4T5M; s4>M 4EL !E4L 4HL Ha4L 5E4L 8", +"E4L 4LH5 4LH8 4ME ME4! 4HM HM4a 4E5M 4E8M H54M 4HsM 4dL +d4L 4LH; g4L 4L5d ", +"4d>L 4H5dL >Lg4 4dM +M4d HM4d g4M 5d4M 4d>M 4HM5d g4>M 3LN 3L!N 3LNB 3LaN 3", +"LN. 3L8N 3L.NB 8a3LN QM3 M3Q! TMQ3 Q3aM MjQ3 Q38M QTMj3 QMs3 (L3N 3L+N 3(NL", +"B +a3LN 3L.(N +83LN .BL3(N 8a3+LN M3Q( QM+3 QTM3( aM3+Q QMj3( +Q8M3 TMjQ3( ", +"s+QM3 W3L !3WL W3HL a3WL 3LW. 83WL HW3L. H8W3L WM3 M3W! ZM3 aMZ3 MjW3 W38M ", +"MjZ3 ZMs3 d3WL W3+L HWd3L W3gL Wd3L. +W83L Wd3HL. gW83L W3dM +3WM dMZ3 ZMg3", +" dMjW3 +WM83 ZdMj3 gZsM3 4mL mL4! mL4B 4Lam 5m4L 4L8m 45mLB amL48 4QM Q!4M ", +"Tm4M Qa4M p4M 48pM 4TpM p4sM m;4L 4L+m 4m;LB amL4+ 45m;L 4m>L 5m;4LB >m4aL ", +"Q;4M +Q4M 4QTM; aMm4+ 4Mp; p4>M p4TM; >Mps4 4WL W!4L 4LHm 4LWa 4L5W 4LW8 4H", +"5WL 4H8WL 4WM 4!WM Z4M 4aZM 4WpM W84M p4ZM sMZ4 v4L 4+vL 4HvL v4gL 45vL v4>", +"L v4H5L gv>4L vM4 4+vM vMZ4 Z4gM p4vM v4>M Zpv4M y4M #3L &3L #3LB &3aL 3L#.", +" &38L 3L.#B 8a&3L M#3 M&3 M#T3 T3M& j#M3 83M& TMj#3 M&s3 3(#L &3+L (BL#3 +a", +"&3L 3L.#( +8&3L 3B(#L. 8a&+3L #3M( +3M& TM#3( aM3+& Mj#3( M&3+j Mj#T3( s+M&", +"3 E3#L E3&L #3HL &3HL 3L.#E 8&E3L H#3L. H8&3L #EM3 &EM3 M#H3 H3M& Mj#E3 M&E", +"83 HMj#3 sHM&3 #3dL &3dL Hd#3L &3gL d#3L. d&38L d#3HL. g8&3L M#d3 d3M& dM#H", +"3 M&g3 dMj#3 dM&83 HM#dj3 gsM&3 4#L 4&L #B4L a&4L 5#4L 4L5& 45#LB 48a&L 4M#", +" 4M& TM4# T&4M 4#5M 5M4& 4T5M# 4Ms& ;#4L 4L;& 4;#LB a;&4L 45;#L 4&>L 5;#4LB", +" >&4aL 4#M; +M4& M;#4T aM;4& M;#4j 4M>& 4T5M;# >Ms4& #E4L &E4L H#4L 4LH& 45", +"#EL 48&EL 4H5#L 4H8&L M#4E 4EM& 4#HM HM4& 4M5#E 48M&E 4HM5# s4HM& d#4L 4Ld&", +" 4Hd#L 4&gL 4d5#L >&4dL H5#4dL g>4&L 4#dM dM4& 4HMd# 4Mg& 4dM5# >M4d& dM#4H", +"j >Mg4& 3L#N 3L&N #LN3B a&3LN 3L.#N 8&3LN #L.3BN a&38LN M#Q3 Q3M& QTM#3 aM3", +"Q& QMj#3 M&3Q8 TMjQ#3 sQM&3 3(N#L +&3LN 3B(#LN a&3+LN #L.3(N 8&3+LN 3LNB#(.", +" 3L+N8a& QM#3( M&3+Q TM#Q3( +QTM&3 Mj#Q3( +Q8M&3 TMQj#3( M&3s+Q #3WL &3WL H", +"W#3L H&W3L W#3L. W8&3L W#3HL. W83H&L M#W3 W3M& M#Z3 M&Z3 WMj#3 W8M&3 ZMj#3 ", +"Z&Ms3 Wd#3L d&3WL Wd#H3L gW&3L d#3WL. W83d&L W3HLd#. W8&g3L dM#W3 dM&W3 ZdM", +"#3 Z&Mg3 WM#dj3 dM3W&j dMjZ#3 gsMZ&3 m#4L 4Lm& 4m#LB am&4L 45m#L m&L48 5m#4", +"LB 48am&L 4#Mm Q&4M Mm#4T aMm4& 4Mp# 4Mp& p4TM# p&4sM 4m;#L m&L4+ m;#4LB 4+", +"am&L 5m;4#L >m4&L mL4B5;# am&>L4 Mm#4; Mm&4+ 4QTM;# 4+TMm& p4M;# >Mp4& M;#p", +"4T p&4>Ms W#4L 4LW& 4HW#L 4H&WL 4W5#L 4W8&L H5#4WL m&L4H8 4#WM WM4& 4MZ# 4M", +"Z& p4WM# p&4WM Zp4M# Zp&4M 4#vL 4&vL v4H#L gv4&L v45#L v>4&L 4H5v#L v>&g4L ", +"4Mv# 4Mv& Zv4M# Zv&4M pv4M# >Mv4& pvMZ4# 4My& U3 U!3 UD3 Ua3 U3. U83 D3U. U", +"3D8 UM3 M3U! V3 Va3 Uj3 U38M Vj3 Vs3 U3( U+3 D3U( U3+D 3(U. +8U3 UD3(. U+D8", +"3 M3U( U3+M V3( V+3 j3U( U3+j j3V( s3V+ UE3 !EU3 UH3 HaU3 E3U. 8EU3 H3U. U3", +"H8 MEU3 U!ME3 VH3 HaV3 jEU3 U8ME3 HjV3 VHs3 Ud3 +dU3 U3Dd gU3 d3U. U38d UHd", +"3. U8g3 U3dM dM3U+ Vd3 gV3 U3dj U+jd3 djV3 g3Vs 4U 4U! 4UD 4Ua 4U5 4U8 U54D", +" U54a 4UM U!4M V4 V4a 4Uj U84M V45 s4V 4U; 4U+ U;4D U+4D 45U; >U4 4U5D; 4U>", +"D U;4M U+4M V4; V4+ U;4j 4U>M 4jV; V>4 4UE U!4E 4UH UH4a 4EU5 4EU8 U54H UH4", +"8 UM4E 4UM!E V4H 4HVa 4EUj 4U8ME 4HV5 sHV4 4Ud U+4d UH4d g4U U54d 4U>d 4UH5", +"d >Ug4 Ud4M 4U+dM V4d gV4 Ud4j >M4Ud 4dV5 g4V> U3N !3UN D3UN a3UN N.U3 83UN", +" UD3N. U8D3N UQ3 U3Q! VQ3 QaV3 QjU3 U3Q8 QjV3 VQs3 3(UN +3UN UD3(N U+D3N U3", +"(N. U+83N D3(UN. +D3U8N Q3U( U3+Q Q3V( +QV3 UQj3( U+Q83 VQj3( Vs+Q3 UW3 W!U", +"3 U3WD U3Wa W3U. U3W8 UHW3. UH8W3 U3WM UWQ!3 VZ3 VaZ3 U3Wj UW8Q3 VjZ3 s3VZ ", +"WdU3 U3+W UHWd3 UWg3 UWd3. U+W83 WD3Ud. gUW83 U3Qd U+WQ3 Z3Vd g3VZ UWjd3 U+", +"Wj3 VZdj3 gVZs3 4Um 4!Um Um4D Um4a 45Um Um48 4U5Dm 4U8Dm 4UQ Q!4U V4Q 4QVa ", +"pU4 4Up8 Vp4 s4Vp 4mU; Um4+ 4UDm; 4U+Dm 4U5m; 4U>m U5m4D; >Dm4U U;4Q U+4Q 4", +"QV; 4+Vm 4Up; p4>U p4V; p>V4 4UW 4!UW UH4W UW4a U54W UW48 4UH5W 4UHW8 UW4Q ", +"4UWQ! Z4V ZaV4 4UpW pU4W8 Z4Vp VZs4 vU4 4Uv+ 4UvD vUg4 4Uv5 v4>U vU4H5 gvU>", +"4 4UvM vU4+Q Vv4 g4Vv p4vU >Mv4U pvV4 yV4 bU3 U&3 UDb3 cU3 U3b. b3U8 bUD3. ", +"U8c3 bM3 b3M& Vb3 Vc3 b3Uj b38M bjV3 s3Vc U3b( b3U+ bUD3( U+c3 bU3(. b+U83 ", +"UD3b(. cU+83 M3b( b3+M b3V( c3V+ bMj3( b+M83 Vbj3( Vs+c3 UEb3 &EU3 b3UH UHc", +"3 bUE3. b8UE3 bHU3. cUH83 MEb3 M&Eb3 bHV3 VHc3 bMjE3 b8ME3 VbHj3 VsHc3 b3Ud", +" U3d& bHUd3 cUg3 bdU3. b8dU3 UH3bd. gcU83 b3dM dM&b3 bdV3 g3Vc bdMj3 d&jU3 ", +"Vdbj3 gVsc3 4bU 4U& bU4D c4U b54U b84U 4bU5D 4Uc5 4bM bM4& V4b c4V b54M b84", +"M 4bV5 Vsc4 b;4U b+4U 4bUD; 4Uc; 4bU5; 4b>U b5U4D; >Uc4 b;4M b+4M 4bV; V4c;", +" 4bM;j 4b>M V4b;j c4V> bU4E 4EU& bH4U 4UcH 4bU5E 4b8UE 4bHU5 c4UH5 4EbM 4bM", +"&E 4bVH cHV4 4bM5E 4b8ME V4bH5 c4VsH bd4U Ud4& 4bHUd c4gU 4bdU5 >b4Ud bH54U", +"d c>g4U bd4M dM&4b 4bVd c4gV 4bdUj >Mb4d V4db5 V>gc4 U3bN &3UN bUD3N U3cN b", +"U3N. b8U3N UD3bN. cU83N b3UQ U3Q& bQV3 VQc3 bQUj3 bQ8U3 VbQj3 cQVs3 bU3(N b", +"+U3N UD3b(N cU+3N U3(bN. U+3b8N D3UNb(. U+8c3N bQU3( b+QU3 VbQ3( cQV+3 UQ3b", +"j( &j3U+Q bQjV3( Vs+cQ3 b3UW U3W& bHUW3 UWc3 bWU3. bW8U3 UH3bW. cWU83 b3WM ", +"bWM&3 VbZ3 Z3Vc bWMj3 bW8M3 ZbVj3 ZcVs3 bWUd3 b+WU3 UHWbd3 cWUg3 UW3bd. d&3", +"UW8 W.DdbU3 gU8cW3 bWMd3 b+WM3 ZbVd3 gVZc3 dM3bWj dM3bW8 VdjZb3 ZcsgV3 bm4U", +" Um4& 4bUDm 4Ucm 4bU5m 4b8Um b5U4Dm c4U8m bQ4U UQ4& 4bVm V4cQ 4bpU 4Up& pbV", +"4 c4Vp 4bUm; 4b+Um bmU4D; c4U+m b5m4U; >b4Um 5mD;4bU c>4Um 4bQU; 4b+UQ V4bQ", +"; c4V+Q pb4U; >Mbp4 Vp4b; cpV>4 bW4U UW4& 4bHUW 4UcW 4bWU5 4bWU8 bH54UW c4W", +"U5 bW4M 4bWM& V4Zb VZc4 pb4UW pU&4W ZpbV4 cpZV4 4bvU 4Uv& vb4UH vUc4 vb4U5 ", +"v>b4U 4bHvU5 cv>4U 4bvM vbM4+ vbV4 c4Vv pvb4U >Mv4b Vvp4b c4yV 6k 6!k 6kB 6", +"ak 61k 68k 1k6B 8k6a 6M 6M! 6Tk 6aM l6 l68 l6T ls6 6k( 6+k k(6B +k6a 1k6( +", +"k68 61k(B 6+1ak 6M( 6+M 6(Tk +T6M l6( l+6 6Tl( s6l+ 6kE kE6! 6Hk Hk6a 1k6E ", +"6E8k 61Hk Hk68 6ME ME6! 6HM HM6a l6E 68lE lH6 s6lH 6dk +k6d Hk6d g6k 61dk 8", +"k6d 6H1dk 68gk 6dM +M6d HM6d g6M ld6 6+ld 6Hld gl6 4k 4k! 4kB 4ak 7k 78k 7B", +"k 7ak 4kM 6!4M 4Tk 6a4M 7l 7l8 7lT 7sl 4k; 4+k 4Bk; +k4a 7k; >k7 k;7B 7a>k ", +"6M; 6+4M Tk6; +T4k l;7 l>7 7Tl; 7sl> 4kE kE4! 4Hk Hk4a 7kE 8k7E 7Hk H87k 4E", +"6M 4kM!E 6H4M 4HkaM 7lE 78lE lH7 lH7s 4dk +k4d Hk4d g4k 7dk 7d>k Hk7d g7k 6", +"d4M 4+kdM HM6; 4Tgk ld7 7>ld 7Hld gl7 6kN kN6! kN6B 6Nak 1k6N 6N8k 61kNB ak", +"N68 6Qk Q!6M Qk6T Qa6M l6Q 6Ql8 6QlT lQs6 k(6N 6N+k 6k(NB akN6+ 61k(N 6+1kN", +" 1k(6NB 6+1akN 6(Qk +Q6M 6QTk( 6+QTk 6Ql( 6+lQ l6QT( ls6+Q 6Wk 6!Wk Hk6W Wk", +"6a 61Wk Wk68 6H1Wk 6H8Wk 6WM 6!WM Z6k 6aZk lW6 6Wl8 lZ6 s6lZ Wk6d +k6W 6HWd", +"k 6Wgk 6W1dk 6+W8k 1HW6dk g61Wk WM6d +W6M 6dZk Z6gk 6Wld 6+lW Z6ld g6lZ 4km", +" 6!km 4Bkm ak6m 7km 8k7m km7B ak7m 4Qk Q!4k Qk4T Qa4k 7lp l87p lp7T 7lsp km", +"6; +k6m km;4B akm4+ km7; 7k>m 7Bkm; 7>akm Qk6; +Q4k 4QkT; ak;4Q 7pl; 7pl> 7", +"lpT; l>p7s 4Wk 4!Wk Hk4W Wa4k 7Wk W87k Hk7W Wa7k 6W4M 4WkQ! Z4k 4aZk lW7 l8", +"7W 7Zl lZ7s v6k 4+vk 4Hvk v6gk 7vk >k7v vk7H gk7v v6M 6+vM v6Zk Z4gk lv7 7v", +"l> 7Zlv yl7 69k 6&k 9k6B ak6& 916k :6k 691kB 6a:k 6M9 6M& 9T6M 9a6M l69 l:6", +" 6Tl9 s6l: 9k6( +k6& 69k(B 6+9ak 691k( 6+:k 91k6(B :6+ak 6(9M 9+6M 6T9k( 6+", +"T9M 69l( :6l+ l69T( ls:6+ 9k6E 6Ek& 69Hk Hk6& 691kE 6k:E 6H91k 6H:k 6E9M 6E", +"M& 9H6M HM6& 69lE :6lE 6Hl9 l6:H 69dk dk6& 6H9dk 6&gk 6d91k 6d:k 9H16dk :6g", +"k 9d6M dM6& 6HM9d 6Mg9 6dl9 l6:d lH69d g6l: 49k 4k& 9k4B 9a4k 79k 7:k 9k7B ", +":a7k 49M 6M4& 9T4k 9a4M 7l9 l:7 l97T l:7s 9;4k 9+4k k;B49 ak;49 9;7k 7:>k 7", +"B9k; 7:>ak 9M6; 9+4M 49Tk; aM;49 79l; 7:l> 7l9T; l>7s: 9k4E 4Ek& 9H4k Hk4& ", +"9k7E :k7E 9H7k 7k:H 4E9M 49M&E 9H4M 49HaM 79lE lE7: l97H 7:lH 9d4k dk4& 49H", +"dk 49gk 9d7k 7k:d 7H9dk 7:gk 9d4M dk&4M 49HdM 49gM l97d 7:ld 7Tdl9 l:g7 9k6", +"N 6Nk& 69kNB akN6& 691kN 6k:N 91k6NB :6akN 9Q6M Qk6& 6Q9Tk 6Qa9M 6Ql9 l6:Q ", +"l69QT :Q6ls 69k(N k&N6+ 9k(6NB 6+9akN 91k6(N :6+kN 916k(BN akN:6+ 6Q9k( 6+Q", +"9M 9QT6M( 9+Q6aM l69Q( :Q6l+ 6Q9lT( ls6:Q+ 69Wk Wk6& 6H9Wk 6H&Wk 6W91k 6W:k", +" 9H16Wk :H6Wk 9W6M WM6& 6MZ9 6MZ& 6Wl9 l6:W l6Z9 Z6l: 6W9dk dk&6W 9HW6dk g6", +"9Wk 9W16dk :W6+k 691HWkd g:6Wk 6WM9d dk&6Q Z69dk Z6&gk lW69d :Qdl6 lZ69d gl", +"Z:6 9m4k km4& kmB49 akm49 9m7k 7k:m 7B9km 7:akm 9Q4k Qk4& 49QTk aMm49 p97l ", +"7l:p 7lp9T 7sl:p km;49 km&4+ 49mk;B 49+akm 79km; 7:>km km;7B9 :>m7ak 49Qk; ", +"k;&4Q 9Q;4Tk 49+aMm 7lp9; l>p7: l;p7T9 7spl>: 9W4k Wk4& 49HWk km&4H 9W7k 7k", +":W 7H9Wk 7:HWk 9W4M Mm&6W 49Zk 4kZ& l97W 7:lW Z97l l:7Z 49vk 4kv& v69Hk gv6", +"k& 79vk vk7: 7v9Hk :vkg7 49vM 6Mv& Zv69M Zv6k& v97l l:7v lvZ79 l:y7 6U 6U! ", +"6UD 6Ua 6U1 6U8 1U6D 1U6a 6UM U!6M V6 V6a l6U 6Ul8 Vl6 s6V 6U( 6U+ 6(Dk U+6", +"D 6(1U 1U6+ 6U1D( 6U+1D UM6( U+6M V6( V6+ 6Ul( 6Ul+ l(V6 V6l+ 6UE U!6E 6UH ", +"UH6a 6E1U 6EU8 1U6H UH68 UM6E 6UM!E V6H 6HVa 6UlE l6U8E V6lH sHV6 6Ud U+6d ", +"UH6d g6U 1U6d U86d 6UH1d 6Ug1 Ud6M 6U+dM V6d gV6 6Uld l+6Ud V6ld s6gV 4U6 6", +"!4U 4Dk 6U4a 7U 7U8 7UD 7Ua 6U4M 4U6M! V46 4aV6 7lU l87U 7V 7Vs 6U; 6U4+ U;", +"6D Ua6; 7U; 7>U U;7D 7D>k U;6M 4U+6M V6; 4+V6 7Ul; 7Ul> 7V; 7V> 4E6U 4U6!E ", +"6U4H 4UH6a 7UE U87E 7UH UH7a 4U6ME 6UE4M! 4HV6 V46Ha lE7U 7lU8E 7VH Vs7H 6U", +"4d 4U+6d UH6; 4Ug6 7Ud >U7d UH7d g7U 4Ud6M 6U+4dM 4dV6 V4g6 7Uld l>7Ud 7Vd ", +"g7V 6UN U!6N 6NDk 6NUa 6N1U 6NU8 6U1DN 6U8DN 6UQ Q!6U V6Q 6QVa 6UlQ UQ68 lQ", +"V6 sQV6 U(6N 6NU+ 6UD(N 6U+DN 6U1(N 6U+1N 1U(6DN 6UN1+D 6(UQ U+6Q 6QV( 6+VQ", +" l6UQ( l+6UQ Vl6Q( l+V6Q 6UW 6!UW UH6W UW6a 1U6W UW68 6UH1W 6UHW8 UW6Q 6UWQ", +"! Z6V ZaV6 6UlW lW6U8 VlZ6 VZs6 UW6d U+6W 6UHWd 6UgW 6UW1d 6U+1W 1UW6Dd g6U", +"1W UQ6d 6U+WM VdZ6 Z6gV lW6Ud l+W6U Z6Vld gV6lZ 6Um 6!Um Um6D Ua6m 7Um U87m", +" Um7D Ua7m 6U4Q 4UQ6! V6m 6aVm 7pU 78pU 7Vp Vp7s Um6; U+6m 4Dkm; 4+Dkm Um7;", +" >m7U 7UDm; 7>UDm UQ6; 4U+6Q 6QV; 6+Vm 7;pU p>7U V;7p 7pV> 6U4W 4UW6! UH6m ", +"4UW6a 7UW UW78 UH7W UW7a 4UW6Q Mm!6UW V4Z6 Z4V6a 7UlW 7pUW8 7ZV sZ7V v6U 6U", +"v+ 4Dvk v6gU 7vU v>7U vU7H gU7v 6UvM v6U+Q Vv6 g6Vv 7Ulv 7vUl> 7Vv y7V t6 t", +"6& t6D tc6 t61 t:6 6Dt1 c6t: t6M 6Mt& Vt6 c6V lt6 l6t: V6lt u6 t6( t+6 6Dt(", +" c6t+ 61t( :6t+ t61D( t:c6+ 6Mt( 6+tM t(V6 V6t+ t6l( l6t+ ltV6( u6+ t6E 6&t", +"E tH6 c6tH 61tE :6tE 6Ht1 t6:H 6MtE t6M&E V6tH cHV6 t6lE t:6lE l6tH u6H td6", +" 6+td 6Htd gt6 6dt1 t6:d tH61d t:g6 6dtM t+6dM V6td c6gV l6td t:dl6 tdVl6 u", +"g6 t4 t4& t4D tc4 7t 7t: 7tD 7ct t4M 4Mt& t4V Vtc4 7tl l:7t 7Vt u7 t4; t4+ ", +"4Dt; c4t+ 7t; t>7 7Dt; 7ct> 4Mt; 4+tM V4t; V4t+ l;7t 7tl> t;7V u7> t4E 4&tE", +" t4H c4tH 7tE tE7: 7tH tH7c 4MtE t4M&E V4tH tc4VH lE7t 7tl:E lH7t u7H t4d 4", +"+td 4Htd gt4 7td 7:td 7Htd g7t 4dtM t4+dM V4td t4gV ld7t 7tdl> td7V ug7 t6N", +" 6&tN 6DtN tNc6 61tN :6tN t61DN t:c6N tQ6 6Qt& V6tQ c6tQ l6tQ t6:Q tQVl6 u6", +"Q 6(tN 6+tN t6D(N tc6+N t61(N t:6+N 6D1t(N :c6t+N 6Qt( 6+tQ tQV6( tcQ6+ tQ6", +"l( t:Q6+ Vl6tQ( 6+uQ tW6 6Wt& 6HtW c6tW 6Wt1 t6:W tH61W t:H6W 6WtQ tW6Q& tZ", +"6 Z6tc l6tW t:Wl6 Z6lt uZ6 6Wtd 6+tW tH6Wd tWg6 tW61d t:W6+ 6WDtd1 gt:6W 6Q", +"td t+W6Q Z6td g6tZ tQdl6 t:Q6d tZl6d gZu6 t4m 4&tm 4Dtm c4tm 7tm 7:tm 7Dtm ", +"tm7c t4Q 4Qt& V4tQ c4tQ tp7 :p7t 7Vtp up7 6mt; 4+tm t4Dm; tc4+m 7mt; 7>tm 7", +"tDm; t>7cm 4Qt; 4+tQ t4VQ; tc4+Q 7pt; 7pt> tp7V; 7pu> t4W 4Wt& 4HtW c4tW 7t", +"W 7:tW 7HtW tW7c 4WtQ t4WQ& tZ4 t4Zc lW7t 7tW:p tZ7 uZ7 tv4 v6t+ v6tH g4tv ", +"tv7 7t:v tH7v tvg7 v6tQ tv4+Q t4Vv g4tZ 7tlv lvt7: 7Ztv yu7 < = =B5 =a> =K =+K =T =T+ =j =j> =T5 s= 4=", +"d =H5 g=> =dK +d=K =HT g=T =jd =d>j =Hj s=g =m 5m=B >m=a =Q =Q+ =QT =Qa p= p=> ", +"p=T s=p 4W< 4!W< H= vH=5 v>g= =Qv v+=Q Z= Z=g p=v v>p= Z=p y= ,<", +" <& ,= ,5=B ->=a =,K -=K =T, =T- =j, =j- ,5=T s=- ,4E ,E4& ,4H 4H,a ,E5< ,E", +"48 4H,5 4H,8 4E,K <&E4K 4H,T ,4HT& ,E4j <&j4E 4H,j ,4sH =d, -=d =H, g=- ,5=", +"d =d-> ,H=5 ->g= ,d=K -d=K ,H=T g-=T ,d=j =d-j ,H=j s-g= ,=-m =B5,m =a->m =Q, =Q- ,Q=T -Q=T p=, ", +"-p= p,=T -ps= ,4W 4&,W 4H,W 4W,a 4W,5 4W,8 ,4H5W -= =Hv,5 g=-v> v,=Q =Q-v Z=, Z", +"-= v=p, p=-v Z,p= y-= =C =D5 =D> =CK +C=K =DT +D=T ", +"=jC >C=j =Dj s=D C H5=D g>=D d", +"K=C =+dCK Dd=T gD=T dj=C =j>dC Hj=D gs=D C 5D=m >m=D =QC +Q=C =QD +Q=D p=C >Cp= p=D sp=D ", +"4CW< Cv= =5vD v>=D vQ=C =Qv+C Z=D =DgZ =C", +"pv p=v>C Zp=D y=D b< b<& ,D< c< b<. b8< ,.D< c<8 b ,5=D c=> =bK -b=K =bT c=T =", +"bj -j=b ,D=j s=c ,E4b <&E4b 4b,H ,4cH bE5< ,48bE H5b< H5c< ,4bEK 4bE<&K ,4H", +"bT c4H,T ,4jbE <&E4bj ,4Hbj c5b bH=5 c>g= bd=K", +" =b-dK bH=T gc=T bd=j =b>dj bH=j gsc= bm=b =b5Dm >=cm =bQ -Q=b ,Q=D c=Q p=b =b-p pb=", +"D cp= 4b,W =b =bvH5 v>c= vb=Q -v=bQ Z=b Z=c", +" pv=b -pv=b Zp=b yc= 6< 6!< 6= 7=B =a7 =6K 6+=K =T6 6+=T =j7 7>=j =T7 s=7 6", +"<4E 6!4=7d =H7 g7= 6d=K =6+dK 6H=T g6=T 7d=j 7>=d", +"j 7H=T s=g7 6m7= =m7B =m7a =Q6 6", +"+=Q 6Q=T 6Q=a p=7 7>p= 7p=T p=7s W<6m 7= =H7v", +" 7vg= v6=Q =Qv6+ Z=6 g6Z= p=7v 7p>v= 7Z= y7= ? ?& ?B ?a ?1 ?: ?B1 ?:a ?K ?&", +"K ?T ?Ta ?j ?:j ?T1 s? ?* ?- ?B* ?-a ?1* ?:- 1*?B :-?a ?*K ?-K ?T* ?-T ?j* ", +"?-j 1T?* s?- ?E ?&E ?H ?Ha ?1E ?:E ?H1 ?:H ?EK &E?K ?HT H&?T ?jE :j?E ?Hj s", +"?H ?d ?-d ?Hd g? ?d1 ?:d 1H?d g?: ?dK -d?K ?Td g?T ?dj :d?j 1T?d g?s ?4 ?4&", +" ?B4 ?a4 7? ?:7 7?B ?a7 ?4K 4&?K ?T4 4T?a ?j7 7:?j ?T7 s?7 ?= ?-= ?=B =a? ?", +"=7 A =B7? Aa ?=K =K?- =T? ?-=T =j? Aj ?T=j As ?4E 4&?E ?H4 4H?a 7?E ?E7: ?H", +"7 7:?H 4E?K ?4&EK 4H?T ?H4T& 7j?E ?:7jE 7H?T ?H7s ?=d -=?d =H? g?= ?d7 Ad 7", +"?=H Ag =K?d ?-=dK ?H=T =Tg? ?d=j Ajd ?H=j Ags ?N ?&N ?BN ?aN ?1N ?:N 1N?B :", +"a?N ?Q ?Q& ?QT ?Qa ?Q1 ?:Q 1Q?T s?Q ?*N ?-N *B?N -a?N 1*?N ?N:- ?B1*N ?:-aN", +" ?Q* ?-Q Q*?T -Q?T 1Q?* :-?Q ?Q1T* ?Qs- ?W ?W& ?HW ?Wa ?W1 ?:W 1H?W :H?W ?W", +"Q W&?Q ?Z ?Za ?Wj :W?Q ?Z1 s?Z ?Wd ?-W H*?W g?W 1W?d :-?W ?H1W* ?Wg: ?Qd -W", +"?Q ?Zd g?Z 1Q?d :Q?d Z1?d Z:g? ?m ?m& ?mB ?am ?m7 ?:m 7B?m 7a?m ?Q4 4Q?& ?T", +"m 4Q?a ?p ?p: ?pT s?p ?=m ?-m =B?m ?m=a 7=?m Am ?=7mB Aam =Q? ?-=Q ?Q=T ?Q=", +"a ?p= Ap =T?p Aps ?W4 4W?& ?Hm 4W?a ?W7 7:?W 7H?W 7W?a 4W?Q ?W4Q& ?Z4 Z4?a ", +"?pW ?W:p ?Zp 7Zs? ?v ?v- ?vH g?v ?v7 Av ?H7v Agv ?vQ ?Q-v ?Zv Z-?v ?pv Apv ", +"7Z?v yA 6C7= =D7 7>=D 6C=K =6+CK 6D=T =D6+T 7j=C 7>=jC 7D=T =D7s 46=dC 7H=D =Dg7 =6dCK 6+d", +"=CK =H6DT g=6DT 7=djC =j>7dC 7Dd=T g7s=D =mC =m7D 7>D=m 6Q=C =Q6+C 6Q=D =QD6+ =C7p 7p>=C 7p=D p=D7s =C =D7v 7vDg= =Qv6C v6+=QC Z6=D ", +"Z=g6D 7vp=C p=>7vC =D7Z =Dy7 ?b ?b& ?D ?c ?b1 ?:b ?D1 ?c: ?bK bK?& ?DT ?cT ", +"?jb :b?j ?Dj s?c ?b* ?-b ?D* ?c- b1?* ?b:- 1D?* :c?- b*?K -b?K bT?* c-?T b*", +"?j ?b-j D*?j ?cs- ?bE b&?E ?Hb ?cH b1?E :b?E b1?H :c?H bK?E ?b&EK bH?T cH?T", +" bj?E ?:bjE bH?j ?Hsc ?db -b?d ?Dd g?c b1?d ?b:d 1D?d ?cg: bd?K ?-bdK bT?d ", +"?Tgc bd?j ?:dbj Dd?j gs?c ?4b 4b?& ?D4 ?c4 7?b 7b?: ?D7 7c? 4b?K ?4b&K 4b?T", +" c4?T 7b?j ?:7bj 7b?T 7cs? =b? ?-=b =D? c=? =b7 Ab 7?=D Ac ?b=K ?-=bK ?D=T ", +"=T?c ?j=b Ajb ?D=j Asc 4b?E ?4b&E 4b?H c4?H ?E7b ?:7bE 7b?H ?H7c ?4bEK 4b&?", +"EK ?H4bT ?c4HT ?j7bE 7:b?jE ?H7bT s?7cH ?d=b ?-=bd ?H=b c=g? 7b?d Abd 7b=H ", +"Agc ?=dbK =b-?dK ?Dd=T c=?gT ?d7bj bdAj ?Hj=b gsAc ?bN b&?N ?DN ?cN b1?N :b", +"?N 1D?N ?N:c ?Qb bQ?& ?QD ?cQ b1?Q ?b:Q 1Q?D ?Qsc b*?N -b?N D*?N ?Nc- ?b1*N", +" ?:-bN ?D1*N ?c:-N bQ?* ?b-Q QD?* c-?Q ?Qb1* ?:Q-b ?QD1* ?cQs- ?Wb bW?& ?WD", +" ?cW b1?W ?b:W 1W?D :c?W bW?Q ?WbQ& ?Zb ?Zc bW?j ?:WbQ Zb?j ?cZ: bW?d ?b-W ", +"WD?d ?Wgc ?Wb1d ?:W-b ?WD1d ?cWg: bQ?d ?-WbQ Zb?d ?cZ- ?Wjbd ?:Qbd ?Zb1d g?", +"Zsc ?mb bm?& ?Dm ?cm 7b?m ?b:m 7D?m ?m7c 4b?Q ?Q4b& 4Q?D c4?Q ?pb pb?: ?pD ", +"?pc ?m=b ?b-m ?m=D ?mc= =m7b Abm ?D7=m Acm ?Q=b ?-Q=b ?Q=D =Q?c =b?p Apb =D", +"?p Apc 4b?W ?W4b& 4W?D c4?W 7b?W ?:W7b 7W?D ?W7c ?W4bQ 4bW?Q& Z4?D ?mZc pb?", +"W ?p:bW ?D7Z 7c?Z ?vb vb?- ?vD ?vc =b7v Avb ?D7v Acv vb?Q ?v-bQ =b?Z cv?Z p", +"b?v pvAb =b7Z yAc =L 5B=L >L=a =M =M+ =TM =aM =M5 >M= 5T", +"=M s=M L H5=L >Lg= =Md +M=d =HM g=M 5", +"d=M =d>M H5=M >Mg= L =B5mL =a>mL =QM +Q=M Tm=M Qa=M p=M >Mp= pT=M sp=M 4LW", +"< Lv= =Hv5L g=v>L =Mv =+vM Z=M =MgZ pv=M ", +"v>=M Zp=M y=M ,L-= =B5,L =a->L =M, =M- ,T=M -T=M ,5=M ->=M =T5,M =Ms- 4E,L ", +"<&E4L ,L4H ,4HaL ,45EL ,48EL ,4H5L ,4H8L ,E4M =dL =H5,L g=->L ,d=M =d-M ,H=M g-=M", +" =M5,d >M-=d =HM,5 g=Ms- =mL ,5m=BL ->m=aL ,Q=M -Q=M =QT,M =Q-aM p,=M =M-p p=T,M -ps=M ,", +"L4W =L v,5=HL -v>g=L v,=M =M-", +"v Z,=M =MZ- p=v,M -pv=M Z=p,M =My- U< U U5=D >U=D =U", +"M U+=M V= V=+ =Uj =U>M V=5 s=V 4EU< 4UU ", +"UH=5 g>=U Ud=M =U+dM V=H V=g Ud=j >M=Ud V5=H gVs= Um=U =U5Dm =U>Dm =UQ U+=Q V=", +"Q V+=Q p=U p>=U V=p Vps= U<4W 4UW=U =UvH5", +" g=Uv> vU=Q =Uv+Q Z=V gVZ= pv=U p=Uv> VpZ= yV= ,U< U<& U<,D c=U =bU5D =Uc> =bM -U=M V=b c=V ,U", +"=j =b>M V5=b V-s= ,E4U ,4U&E 4U,H c4U,H ,4U5E ,4U8E ,4UH5 c5Ud =bHU5", +" c=g>U bd=M =bM-d Vd=b gVc= =bM5d >M=bd V=bH5 c=Vgs ,NU< UN<& ,UDUm ,U5=Dm c=>Um ,U=Q -U=Q Vm=b =QV- pb=U =U-p =bV", +"p V=cp 4U,W = =U5vD, cv=>U v", +"b=M -vU=Q =bVv V-Z= p=bvU -pUv= Vv,p= c=yV k= 7B=k =", +"a>k =kM 6+=M =Tk 6a=M l= l=> l=T l=s 4Ek 7H=k >kg= 6d=M =k+dM 6H=M g6=M l=d >=ld l=H gl= m=k 7=mkB >k=am =Qk +Q=k Qk", +"=T Qa=k l=p p=l> lp=T lsp= W<4k =k 7v=", +"Hk g=k7v v6=M =Qkv+ Z=k =kgZ lv= v>l= l=Z yl= ?k ?k& ?Bk ?ak ?1k ?:k 1k?B :", +"a?k ?M ?M& ?Tk ?aM l? l?: l?T s?l ?k* ?-k k*?B -k?a 1*?k -k?: ?B1k* ?:-ak ?", +"M* ?-M Tk?* -T?M l?* l-? ?Tl* s?l- ?kE k&?E ?Hk Hk?a 1k?E :k?E 1H?k ?k:H ?M", +"E M&?E ?HM HM?a l?E lE?: l?H lHs? ?dk -k?d Hk?d g?k 1d?k ?k:d ?H1dk ?:gk ?d", +"M -M?d HM?d g?M l?d ?:ld ?Hld gl? ?4k 4k?& 4k?B 4a?k 7?k ?k7: ?k7B ?k7a ?M4", +" 4M?& 4T?M 4a?M l?7 7l?: 7l?T l?7s =k? =k- ?B=k ?a=k 7?=k Ak ?=7kB Aak =M? ", +"?-=M ?T=k ?a=M l=? Al =Tl? Als 4k?E ?4k&E 4H?k ?H4ak 7k?E ?:7kE ?k7H ?:H7k ", +"4M?E ?M4&E 4H?M ?HM4a lE7? l?7:E 7l?H l?H7s ?d=k =d-k ?H=k =kg? ?k7d Adk ?H", +"7=k Agk ?d=M ?-M=d ?H=M =Mg? ?=ld Ald =Hl? Alg ?kN k&?N kN?B ak?N 1k?N :k?N", +" ?B1kN ?:akN ?Qk Qk?& Qk?T Qa?M l?Q ?Ql: lQ?T ?Qls k*?N ?N-k ?Bk*N ?-akN ?1", +"k*N ?:-kN k*N?B1 :-k?aN Qk?* -Q?M ?QTk* ?-QTk ?Ql* ?Ql- l?QT* l-?sQ ?Wk Wk?", +"& Hk?W Wa?k 1W?k ?k:W ?H1Wk ?:HWk ?WM WM?& ?Zk Zk?a l?W ?:lW ?Zl l?Z: Wk?d ", +"-k?W ?HWdk ?Wgk ?W1dk ?:W-k 1H*?Wk g?:Wk WM?d -W?M Zk?d gk?Z ?Wld ?-lW ld?Z", +" ?Zgl ?mk km?& km?B ak?m 7k?m ?k:m ?m7kB ?:mak ?Mm Mm?& Tk?m aM?m ?pl l?:p ", +"lp?T ls?p ?m=k -k?m ?=mkB ?-mak ?=7km Akm 7=B?mk akAm ?Q=k -Q=k ?Tm=k ?-Tkm", +" ?pl= Alp l=?pT lsAp 4W?k ?W4k& Hk?m ?Hmak ?k7W ?:W7k ?H7Wk ?:Hkm 4W?M ?WM4", +"& Z4?M ?Z4ak lW?p l?W:p l?7Z s?Z7l ?vk =k-v vk?H gk?v vk7? Avk ?v7Hk gvAk ?", +"vM ?M-v =k?Z =kZ- lv? Alv ?Zlv yAl 6U< 6!U< Dk 7U=D =D>k 6U=M =U6+M V=6 V6=a l=U =Ul> l=V 7V", +"s= U=d 7U=H =Ug7 =U6dM", +" 6U+=Md V6=H =kgV ld=U l=>Ud =H7V V=gl 6NU< U=m =U7Dm 7Ua=m 6U=Q =UQ6+ V6=Q V=6+Q 7p=U l=p>U Vpl= V=pl> = 7vU=H g7Uv= =Uv6Q =U+v6M =", +"kVv Vv6g= =Ulv lv=>U Z=7V l=yV ?t ?t& ?tD ?ct ?t1 ?t: t1?D t:?c ?tM tM?& V?", +" V?c l?t ?tl: V?l u? ?t* t-? t*?D t-?c ?1t* ?:t- ?t1D* ?t:c- t*?M ?Mt- V?* ", +"V?- ?tl* l?t- l*V? u?- ?tE t&?E ?tH tc?H t1?E ?Et: ?1tH t:?H tM?E ?tM&E V?H", +" Vc?H lE?t ?t:lE lHV? u?H ?td ?dt- tH?d g?t ?1td t:?d ?tH1d ?tg: td?M ?td-M", +" V?d g?V ?tld l-?td ldV? u?g ?t4 ?&t4 t4?D t4?c 7t? ?:7t ?D7t 7t?c t4?M ?t4", +"M& V?4 c4V? l?7t ?t:7l 7V? u?7 t= t=- t=D t=c t=7 At =D7t Atc t=M =Mt- t=V ", +"V?c= l=t Alt 7Vt= Au ?Et4 ?t4&E t4?H ?tHc4 ?E7t ?t:7E ?H7t 7tH?c ?t4ME t4&?", +"ME V4?H V?c4H 7tl?E l?:7tE ?H7V ?Hu7 t=d -=td t=H gt= ?d7t Atd =H7t Agt td=", +"M t=-dM =HV? V=g? ldt= ltAd =Hlt Aug ?tN t&?N tD?N ?Ntc t1?N ?Nt: ?t1DN ?t:", +"cN ?tQ ?&tQ V?Q tc?Q ?Qlt t:?Q Vl?Q u?Q ?Nt* ?Nt- ?tD*N ?ct-N ?t1*N ?t:-N t", +"*1?DN t-:?cN t*?Q ?Qt- V*?Q ?QV- ?tQl* t-Ql? V?lQ* ?-uQ ?tW ?&tW tH?W tc?W ", +"?1tW t:?W ?tH1W ?cWt: tW?Q ?tWQ& ?ZV ?ctZ ?tlW l?Wt: l?tZ u?Z tW?d ?Wt- ?tH", +"W* ?Wgt ?tW1d t-W?: ?H1tW* g?t:W tQ?d t-W?Q ?dtZ ?Zgt l?Wtd l-W?t V?dlZ g?u", +"Z ?tm ?&tm tm?D tc?m ?m7t t:?m ?tm7D ?cm7t t4?Q ?tQ4& V?m cmV? ?pt ?t:p ?pV", +" u?p t=m ?mt- tm=D tmc= 7=tm Atm t=7Dm tcAm t=Q =Qt- =QV? ?mV- tp= Apt V=?p", +" Aup t4?W ?tW4& tH?m ?cWt4 ?W7t 7tW?: 7tH?W 7cW?t ?tW4Q ?W&t4Q ?mtZ V?mZc ?", +"Wtp ?pt:W tZ?p ?Zup ?vt t-?v =Htv ?vgt 7t?v Atv ?vt7H gtAv =Qtv ?vt-Q ?vV Z", +"-t= tp?v lvAt tZl= Auy 3F !3F 3BF a3F 3F. 83F 3F.B a38F 3FK 3F!K T3F a3TF j", +"3F j38F j3TF s3F 3(F +3F 3(FB a3+F (F3. 83+F 3F.(B +8a3F (F3K 3F+K 3(TF T3+", +"F 3(jF j3+F Tj3(F +3sF G3 G3! GH3 Ga3 G3. G83 H3G. G3H8 G3K !KG3 GT3 TaG3 G", +"j3 8jG3 G3Hj sG3 Gd3 +G3 HdG3 gG3 d3G. +3G8 GHd3. G8g3 dKG3 GK+3 G3Td GTg3 ", +"G3dj +3Gj dj3GT g3sG 4F 4F! 4FB 4aF 45F 48F 5B4F 4F5a 4FK !K4F 4TF Ta4F 4jF", +" 8j4F 4F5T s4F 4;F 4+F ;F4B 4Fa; 5;4F >F4 45;FB 4a>F ;F4K +F4K 4FT; 4F+T 4F", +";j 4j>F ;jF4T >Fs4 4G 4G! 4GH 4Ga 4G5 4G8 G54H G54a 4GK GK4! 4GT GT4a 4Gj G", +"84j G54T s4G 4Gd 4+G G;4H g4G G54d >G4 4GH5d >Gg4 4KG; 4K+G GT4d 4GgT G;4j ", +"4G>j 4GT5d sGg4 3FN 3F!N 3FNB 3FaN 3FN. 3F8N 3F.NB 8a3FN Q3F !3QF T3QF a3QF", +" j3QF 83QF QTj3F Q3sF (F3N 3F+N 3FN(B +a3FN 3F.(N +83FN N.(3BF 8a3+FN 3(QF ", +"Q3+F QT3(F +QT3F Qj3(F +Q83F Tj3Q(F s+Q3F GW3 G3W! HWG3 G3Wa W3G. G3W8 GHW3", +". G8HW3 GQ3 G3Q! ZG3 GaZ3 G3Wj G3Q8 GjZ3 ZGs3 WdG3 GW+3 GHWd3 GWg3 GWd3. +G", +"W83 HWdG3. gGW83 G3Qd +3GQ GdZ3 ZGg3 dj3GQ +GQ83 ZGdj3 gZsG3 4mF mF4! mF4B ", +"4Fam 5m4F 4F8m 45mFB amF48 4QF 4FQ! 4FTm 4FQa p4F 48pF 4TpF p4sF m;4F 4F+m ", +"4m;FB amF4+ 45m;F 4m>F 5m;4FB >m4aF 4FQ; 4F+Q 4QT;F 4+QTF 4;pF p4>F p4T;F p", +">4sF 4GW 4!Gm Gm4H Ga4W G54W G84W 4GH5W 4G8Hm 4GQ Q!4G Z4G 4GZa pG4 4Gp8 pG", +"Z4 Z4sG v4G 4+vG 4GvH v4gG 4Gv5 v4>G v4GH5 gv>4G 4GvQ +G4Q v4ZG gGZ4 v4pG p", +"4>G Zpv4G y4G #3F &3F #3FB &3aF 3F#. &38F 3F.#B 8a&3F 3F#K 3F&K #3TF &3TF #", +"3jF j3&F Tj#3F &3sF 3(#F &3+F 3BF#( +a&3F 3F.#( +8&3F #(F.B3 8a&+3F 3FK#( +", +"&3FK T#3(F +T&3F j#3(F &j3+F j#3T(F s+&3F G#3 G&3 H#G3 G3H& #3G. 8&G3 GH#3.", +" G8H&3 #3GK &3GK T#G3 G3T& j#G3 G3&j GTj#3 G&s3 d#G3 +3G& GHd#3 G&g3 Gd#3. ", +"d&3G8 Hd#G3. gG8&3 Gd#3K d&3GK GTd#3 gGT&3 dj#G3 d&jG3 GT#dj3 gsG&3 4#F 4&F", +" #B4F a&4F 5#4F 4F5& 45#FB 48a&F #F4K &F4K T#4F 4FT& j#4F 4F&j 4T5#F 4&sF ;", +"#4F 4F;& 4;#FB a;&4F 45;#F 4&>F 5;#4FB >&4aF 4;#FK ;&F4K 4T;#F 4+T&F ;j#4F ", +">&4jF 4T#;jF s>4&F 4G# 4G& GH4# Ga4& 4#G5 G54& 4GH5# 4G8H& G#4K 4KG& 4#GT G", +"T4& 4#Gj G&4j 4GT5# 4Gs& 4#G; +G4& 4GHd# 4Gg& 4G5d# 4G>& G5H4d# g>4G& 4Gd#K", +" 4+G&K 4GTd# g4GT& 4Gjd# >G4&j dj#4GT gs4G& 3F#N 3F&N 3FN#B a&3FN 3F.#N 8&3", +"FN .B3#FN a&38FN #3QF &3QF QT#3F Qa&3F Qj#3F &j3QF Tj#Q3F sQ&3F 3FN#( +&3FN", +" #BF3(N a&3+FN #3FN.( 8&3+FN 3F#N.B( 3F&N+8a Q#3(F +Q&3F T#3Q(F Q&3+TF j#3Q", +"(F +Q3&jF 3(jFQT# +Q&s3F W#G3 G3W& GHW#3 GaW&3 GW#3. G8W&3 HW#G3. H8WG&3 Q#", +"G3 G3Q& G#Z3 G&Z3 GQj#3 GQ8&3 ZGj#3 Z&Gs3 GWd#3 d&3GW HWdG#3 gGW&3 Wd#G3. G", +"8Wd&3 W#H3Gd. G8Wg&3 GQd#3 +GQ&3 ZGd#3 Z&Gg3 GQ#dj3 d&3GQ8 dj#ZG3 gsGZ&3 m#", +"4F 4Fm& 4m#FB am&4F 45m#F m&F48 5m#4FB 48am&F Q#4F 4FQ& 4QT#F 4Qa&F 4#pF 4&", +"pF p4T#F p&4sF 4m;#F m&F4+ m;#4FB 4+am&F 5m;4#F >m4&F 5B4Fm;# am&>F4 4Q;#F ", +"4+Q&F Q;#4TF a;F4Q& p4;#F p>4&F 4T;p#F s>4p&F 4#Gm Gm4& 4GHW# 4GaW& 4G5W# 4", +"G8W& G5H4W# G5a4W& 4#GQ GQ4& 4GZ# 4GZ& 4Gp# 4Gp& Zp4G# Zp&4G 4Gv# 4Gv& v4GH", +"# gv4G& v4G5# v>4G& 4GHv5# v>Gg4& v4GQ# v&4GQ Zv4G# Zv&4G pv4G# pv&4G pvGZ4", +"# 4Gy& I3 I3! DI3 aI3 I3. 8I3 I3D. D38I I3K !KI3 TI3 T3aI Ij3 83Ij D3Ij sI3", +" I3( +I3 I3D( +3aI 3(I. +38I DI3(. +D8I3 3(IK I3+K I3T( +3TI j3I( +3Ij Ij3D", +"( +Is3 GI3 I3G! J3 Ja3 I3G. G38I J3. J83 I3GK GI3!K JT3 TaJ3 G3Ij Ij3G8 Jj3", +" sJ3 Id3 +3Id Jd3 gJ3 d3I. 83Id d3J. g3J8 I3dK Id3+K TdJ3 JTg3 I3dj Idj+3 d", +"jJ3 g3sJ 4I 4I! 4DI 4aI 4I5 48I 5D4I 5a4I 4IK IK4! 4TI TI4a 4Ij 8I4j 5T4I s", +"4I 4I; 4+I D;4I +D4I 45I; >I4 4D5I; 4D>I 4KI; 4K+I T;4I +T4I I;4j 4I>j I;j4", +"D >Is4 4GI GI4! J4 J4a G54I G84I J45 J48 GI4K 4GI!K J4T 4TJa Gj4I 4G8Ij J4j", +" sJ4 4Id +G4I J4d gJ4 5I4d 4G>I 4dJ5 J>4 4KId 4+GIK 4TJ; gTJ4 Id4j >I4Gj 4d", +"Jj g4sJ I3N !3IN I3DN I3aN N.I3 IN83 DI3N. D8I3N QI3 I3Q! Q3TI Q3aI Q3Ij Q3", +"8I Ij3QD QIs3 3(IN I3+N DI3(N +DI3N I3(N. +I83N I3(DN. D83+IN I3Q( +3QI QDI", +"3( +QDI3 Ij3Q( +QI83 QD3Ij( sI+Q3 WI3 I3W! JW3 WaJ3 I3W. W38I W3J. W8J3 G3Q", +"I GQI!3 ZJ3 JaZ3 W3Ij GQ8I3 Z3Jj s3ZJ W3Id +3WI WdJ3 JWg3 Id3W. +WI83 JWd3.", +" gJW83 Q3Id +GQI3 JdZ3 g3ZJ IdjW3 +WIj3 ZJdj3 sJZg3 4Im 4!Im Dm4I am4I 45Im", +" 8m4I 4D5Im 4D8Im 4QI Q!4I QD4I Qa4I pI4 48pI 4DpI pIs4 4mI; +m4I Im;4D 4+D", +"Im Im;45 4I>m 4D5Im; >Dm4I Q;4I +Q4I 4QDI; 4+QTI 4Ip; p4>I pD4I; p>D4I 4WI ", +"4!WI J4W 4WJa 5W4I W84I 4WJ5 4WJ8 GQ4I 4GQI! ZJ4 ZaJ4 4GpI pG48I Jp4 s4Jp v", +"I4 4+vI Jv4 g4Jv 4Iv5 v4>I v4J5 v>J4 4QvI vI4+Q Z4Jv ZJg4 p4vI pvI>4 pvJ4 y", +"J4 bI3 I&3 DIb3 cI3 I3b. b38I bDI3. 8Ic3 I3bK &3IK b3TI TIc3 b3Ij I3&j Ij3b", +"T cIs3 I3b( b3+I bDI3( +Ic3 bI3(. I&3+8 DI3b(. c+8I3 bKI3( I&3+K bTI3( c+TI", +"3 Ij3b( I&j+3 bT3Ij( sI+c3 bG3 b3G& Jb3 cJ3 G3b. b3G8 b3J. c3J8 G3bK I&3GK ", +"bTJ3 JTc3 b3Gj I&jG3 bjJ3 s3cJ b3Id b3+G bdJ3 g3cJ Id3b. b+G83 Jbd3. cJ8g3 ", +"Id3bK b+G3K JbTd3 cJTg3 Idjb3 Idj&3 Jjbd3 sJgc3 4bI 4I& bD4I c4I b54I b84I ", +"4b5DI 48cI bK4I 4KI& bT4I 4TcI bj4I I&4j 4bT5I c4sI b;4I b+4I 4bDI; 4+cI 4b", +"5I; 4b>I b5D4I; >Ic4 I;K4b I;&4K 4bTI; c4+TI I;j4b >I4bj 4bTI;j c>s4I 4bG b", +"G4& J4b cJ4 b54G bG48 4bJ5 J4c5 4KbG 4bG&K 4bJT cTJ4 bG4j I&j4G 4bJj cJs4 b", +"G4d b+4G 4bJ; cJg4 4bG5d 4b>G J4b5d c4J> 4bGdK 4b+GK J4bTd cJ4gT Idj4b >bG4", +"j J4jbd J>sc4 I3bN &3IN bDI3N I3cN bI3N. I&38N DI3bN. c8I3N b3QI Q3I& bQDI3", +" QIc3 Ij3bQ I&jQ3 bQDIj3 sIQc3 bI3(N I&3+N DI3b(N c+I3N I3(bN. +I3b8N 3(INb", +"D. +I8c3N bQI3( b+QI3 QI3bT( cQ+I3 bQ3Ij( Ij3b+Q Qjb3TI( cQ+sI3 b3WI W3I& b", +"WJ3 JWc3 bGW3. bG8W3 JbW3. cJW83 b3GQ bGQ&3 JbZ3 Z3cJ bGQj3 I&jW3 ZJbj3 sJZ", +"c3 Id3bW b+GW3 JbWd3 cJWg3 bW3Id. Id3bW8 bWdJ3. gJ8cW3 bGQd3 b+GQ3 ZJbd3 Zc", +"Jg3 Id3bWj Id3bQ8 JjdZb3 ZcgsJ3 bm4I Im4& 4bDIm 4Icm 4b5Im Im&48 b5D4Im c45", +"Im bQ4I QI4& 4bQTI 4QcI 4bpI 4Ip& pb4TI pIc4 Im;4b Im&4+ 4bDIm; c4+Im 4b5Im", +"; >I4bm Imb;4D5 c>4Im 4bQI; I;&4Q bQ;4TI c4Q+I pb4I; p>b4I 4bTpI; cp>4I bG4", +"W WI4& 4bJm J4cW 4bG5W 4bGW8 J4b5W cJ45W bG4Q 4bGQ& J4Zb cJZ4 4bpG pbG48 pb", +"J4 c4Jp 4bvI 4Iv& vbJ4 c4Jv vb4G5 v>b4G Jv4b5 cvJ>4 vb4GQ vI&4Q ZJ4vb cvZJ4", +" pvb4G pvI4& Jpv4b cJy4 6F 6!F 6FB 6aF 61F 68F 1F6B 6F1a 6FK !K6F 6TF Ta6F ", +"6jF 8j6F 6F1T s6F 6(F 6+F (B6F +a6F 1(6F 6F1+ 61(FB 6+1aF (F6K +F6K T(6F 6F", +"+T j(6F 6F+j 6T1(F 6+sF 6G 6G! 6GH 6Ga 6G1 6G8 1G6H 1G6a 6GK GK6! 6GT GT6a ", +"6Gj G86j 1G6T s6G 6Gd 6+G GH6d g6G 1G6d 1+6G 6G1Hd 6Gg1 Gd6K 6K+G GT6d 6GgT", +" Gj6d +G6j 6GT1d sGg6 46F 4F6! 6F4B 4F6a 7F 78F 7BF 7aF 6F4K 6!4FK 4F6T 4T6", +"aF 7jF 8j7F 7TF 7sF 6;F 4F6+ ;F6B 6Fa; 7;F 7>F ;F7B >F7a ;F6K 4+6FK 6FT; 4+", +"T6F ;j7F 7j>F T;7F >F7s 4G6 6!4G 6G4H 6G4a 7G 7G8 7GH 7Ga 4K6G 4G6!K 6G4T 4", +"GT6a 7Gj G87j 7GT 7sG 6G; 6+4G G;6H 4Gg6 7Gd 7>G G;7H g7G 6KG; 4+G6K GT6; g", +"46GT G;7j >j7G GT7d sGg7 6FN !F6N NB6F aF6N 1F6N 8F6N 61FNB 68aFN 6QF 6FQ! ", +"QT6F 6FQa 6F1Q 6FQ8 6Q1TF 6QsF (F6N +F6N 6(FNB 6+aFN 61(FN 6+1FN 1(F6NB 1+F", +"6aN Q(6F 6F+Q 6QT(F 6+QTF 6Q1(F 6+Q1F 1Q(6TF s6+QF 6GW W!6G GH6W Ga6W 1G6W ", +"G86W 6G1HW 6G8Wa 6GQ Q!6G Z6G 6GZa 1G6Q GQ68 6GZ1 Z6sG GW6d +G6W 6GHWd 6GgW", +" 6G1Wd 6+G1W 1GH6Wd g61GW GQ6d +G6Q 6GZd gGZ6 6GQ1d 6+G1Q Z61Gd gZ6sG 6mF m", +"F6! mF6B 6Fam 7mF 8m7F mF7B am7F 4F6Q 4Q6!F 6FTm 4Qa6F 7pF p87F pT7F sF7p m", +";6F 6F+m 6m;FB 6+maF m;7F 7m>F 7Bm;F 7>amF 6FQ; 4+Q6F 6Q;TF 6+TmF p;7F >F7p", +" 7pT;F 7p>sF 6Gm 6!Gm Gm6H Ga6m 7GW G87W Gm7H Ga7W 6G4Q 4GQ6! 4GZ6 Z46Ga 7p", +"G 78pG 7ZG sG7Z v6G 6+vG 6GvH gGv6 7vG v>7G vG7H 7Ggv 6GvQ v6+GQ ZGv6 Zv6gG", +" pv7G p>7G 7GZv y7G 69F 6&F 9F6B 6F9a 916F :6F 691FB 6a:F 9F6K &F6K 6F9T 6F", +"T& 6F9j 6j:F 6T91F :6sF 9(6F 6F9+ 69(FB 6+9aF 691(F 6+:F 91(6FB :6+aF 69(FK", +" 6+9FK 6T9(F 6+T9F 6j9(F :6+jF 9T(6jF s:6+F 6G9 6G& 9G6H 9G6a 691G :G6 6G91", +"H 6G:H 6K9G 6KG& 9G6T GT6& 9G6j 6G:j 6GT9j :Gs6 9G6d 9+6G 6G9Hd 6Gg9 6G91d ", +"6+:G 9G16Hd :Gg6 6G9dK 6+G9K 6GT9d g69GT 6Gj9d :G6+j 9GT6dj g:s6G 49F 4F6& ", +"9F4B 4F9a 79F 7:F 9F7B :a7F 9F4K 49&FK 4F9T 49TaF 9j7F :j7F 9T7F sF7: 4F9; ", +"4F9+ 49;FB 49+aF 9;7F >F7: 7B9;F 7:>aF 49;FK 49+FK 49T;F 49+TF 79;jF 7:>jF ", +"7T9;F 7s:>F 49G 6G4& 9G4H 9G4a 7G9 7:G 9G7H :G7H 4K9G 49G&K 9G4T 49GT& 9G7j", +" 7j:G 9G7T 7:sG 9G4d 9+4G 49GH; 49gG 9G7d :>7G 7G9H; 7Gg: 49GdK 49+GK 49GTd", +" g49GT 7G9dj 7:G>j 7GT9d 7sGg: 9F6N &F6N 69FNB 6a9FN 691FN 6F:N 91F6NB :6aF", +"N 6F9Q 6FQ& 6Q9TF 6Qa9F 6Q91F 6Q:F 9Q16TF :Q6sF 69(FN 6+9FN 9(F6NB 9+F6aN 9", +"1(6FN :6+FN 916N(BF 6+a:FN 6Q9(F 6+Q9F 9Q(6TF 6+F9Qa 9Q(6jF :Q6+F QT1(69F s", +"6+:QF 9G6W G&6W 6G9HW 6Ga9W 6G91W 6G:W 9G16HW :G6Wa 9G6Q GQ6& 6GZ9 6GZ& 6GQ", +"9j 6G:Q Z691G :GZ6 6G9Wd 6+G9W 9GH6Wd g69GW 9G16Wd :G6+W 691HGWd g:6GW 6GQ9", +"d 6+G9Q Z69Gd Z6&gG 9GQ6dj :GQ6+ 6GjZ9d Z:g6G 4F9m 6Fm& 49mFB 49amF 9m7F 7F", +":m 7B9mF 7:amF 4F9Q 49Q&F 49QTF 49QaF 7Fp9 7F:p 7p9TF 7sp:F 49m;F 49+mF 9mF", +"6;B amF49+ 79m;F 7:>mF 9m;7BF :>m7aF 49Q;F 49+QF 4QF9T; a;F49Q 7p9;F 7p>:F ", +"p9;7TF :p>7sF 9G4W Gm6& 49GHm 49GWa 9G7W :G7W 7G9Hm 7:GHm 9G4Q 49GQ& 49ZG Z", +"49Ga p97G 7G:p Z97G 7GZ: 49vG 6Gv& v69GH gv69G v97G 7G:v 7v9GH :vGg7 v69GQ ", +"v6&GQ Zv69G Zv6G& 7pGv9 :vG7p 7Zv9G 7:yG 6I 6I! 6DI 6aI 6I1 68I 1D6I 1a6I 6", +"IK IK6! 6TI TI6a 6Ij 8I6j 1T6I s6I 6I( 6+I DI6( +D6I 6(1I 1+6I 6D1I( 6+D1I ", +"I(6K 6K+I 6(TI +T6I 6(Ij +I6j 6DjI( 6+sI 6GI GI6! J6 J6a 1G6I G86I J61 J68 ", +"GI6K 6GI!K J6T 6TJa Gj6I 6G8Ij J6j sJ6 6Id +G6I J6d gJ6 1I6d 8I6d 6dJ1 J6g1", +" 6KId 6+GIK 6TJd gTJ6 Id6j Idj6+ 6dJj g6sJ 4I6 6!4I 6D4I 6a4I 7I 7I8 7DI 7a", +"I 4K6I 4I6!K 6T4I 4TI6a 7Ij 8I7j 7TI 7sI 6I; 6+4I D;6I aI6; 7I; 7>I D;7I >D", +"7I 6KI; 4+I6K TI6; 4+T6I I;7j >j7I TI7; 7>sI 6G4I 4G6I! J46 4aJ6 7GI G87I 7", +"J 7J8 4G6IK 6GK4I! 4TJ6 J46Ta Gj7I 7G8Ij 7JT 7Js 6I4d 4+G6I J6; J4g6 7Id >G", +"7I 7Jd g7J 4Id6K I;K6+G 6TJ; gJ46T Id7j 7>GIj J;7T sJg7 6IN IN6! DI6N 6NaI ", +"6N1I 6N8I 6D1IN 6D8IN 6QI Q!6I QD6I Qa6I 1Q6I Q86I 6QD1I 6QsI I(6N 6N+I 6DI", +"(N 6+DIN 6I1(N 6+I1N 1D(6IN 6+N1aI 6(QI +Q6I 6QDI( 6+QTI 6QI1( 6+Q1I Ij(6QD", +" s6I+Q 6WI 6!WI J6W 6WJa 1W6I W86I 6WJ1 6WJ8 GQ6I 6GQI! ZJ6 ZaJ6 WI6j 6GQ8I", +" J6Z1 ZJs6 WI6d +W6I 6WJd gWJ6 6WI1d 6+W1I J61Wd gJ61W QI6d 6+GQI ZdJ6 ZJg6", +" Idj6W 6+WIj ZJ61d sJ6gZ 6Im 6!Im Dm6I aI6m 7Im 8I7m Dm7I aI7m 6Q4I 4QI6! T", +"I6m 4Qa6I 7pI 78pI pD7I 7psI Im6; +I6m 6DmI; 6+DIm Im7; >m7I 7DIm; 7>DIm QI", +"6; 4+Q6I 6QDI; 6+TIm 7;pI p>7I 7pDI; 7sIp> 6W4I 4WI6! J6m 6aJm 7WI W87I 7JW", +" J87W 4GQ6I Im!6GQ J4Z6 ZJ46a pG7I 7pG8I 7ZJ sJ7Z v6I 6+vI Jv6 g6Jv 7vI v>7", +"I 7Jv 7vJ> 6QvI v6I+Q Z6Jv Jv6gZ pv7I 7vIp> 7vJp yJ7 b6I 6I& 9D6I c6I 6Ib1 ", +":I6 b61DI c6:I bK6I 6KI& 6IbT 6TcI 6Ibj 6I:j b6T1I :Is6 b(6I 6Ib+ b6DI( 6+c", +"I b61I( 6+:I 6DIb1( :c6+I b6I(K b6+IK b6TI( c6+TI b6jI( :I6+j Ij(b6T s:I6+ ", +"b6G 6&bG J6b cJ6 6Gb1 b6:G b6J1 :J6 bK6G b6G&K b6JT cTJ6 6Gbj :Gb6j b6Jj s6", +":J 6Gbd 6+bG b6Jd cJg6 b6G1d 6I:d J6b1d g6:J b6GdK b6+GK J6bTd cJ6gT Idjb6 ", +":Id6j J6jbd sJ6g: 49I 6I4& 9D4I 49cI 7bI 7:I 9D7I 7cI 4K9I 49I&K 9T4I c46TI", +" bj7I 7j:I bT7I sI7c 6Ib; 9+4I 49DI; 6Ic; b;7I :>7I 7bDI; 7Ic> 49I;K I;&6K ", +"49TI; c6;TI 7bI;j 7:I>j 7bTI; 7sIc> b64G 4bG6& J49 J4c6 7bG :G7b 7Jb 7J: 4b", +"G6K I&K49G 49JT cJ46T bG7j 7:Gbj J97T sJ7c 6Gb; I;&6G 49J; J4g9 bG7d :I7d J", +"97d :Jg7 49IdK IdK49+ J49Td cJ6T; 7bGdj 7:Idj 7JbTd g7Js: bN6I 6NI& b6DIN 6", +"IcN b61IN 6I:N 6DIb1N :c6IN 6IbQ QI6& b6QTI 6QcI b6Q1I 6Q:I 6QIb1T :cQ6I b6", +"I(N b6+IN 9D(6IN c6+IN 6I(b1N :I6+N b(6D1IN c6+:IN b6QI( b6+QI bQ(6TI c6Q+I", +" Ij(b6Q :QI6+ b(6Q1TI sI+c6Q 6GbW WI6& b6JW J6cW b6G1W 6W:I J6b1W J6:W 6GbQ", +" b6GQ& J6Zb cJZ6 b6G1Q :GQb6 ZJ6b1 Z6:J b6GWd b6+WI J6bWd cJ6gW 6WIb1d :WI6", +"+ b6WJ1d :Jg6W b6GQd b6+GQ ZJ6bd Zc6gJ b6WIdj :QI6d ZbdJ6j Z:Jg6 6Ibm Im6& ", +"49DIm 6Icm bm7I :m7I 7bDIm cm7I 9Q4I Im&6Q 49QTI c4Q6I pb7I 7I:p 7pbTI 7Icp", +" 49Im; Im&6+ 9Dm6I; c6m+I 7bIm; 7:I>m 9Dm7I; 7c>Im 49QI; I;&6Q 6QIbT; c6QI;", +" 7pbI; :pI7> 7D;p9I 7cp>I 6Gbm Im&6G 49Jm J6cm bG7W :W7I J97W 7W:J 4bG6Q b6", +"G4Q& J4Z9 Zc4J6 pb7G :pG7b 7bJp Z:7J 49vI 6Iv& vbJ6 c6Jv vb7G 7I:v 7bJv :v7", +"J vb6GQ v6IQ& Jv6Zb cv6ZJ 7vbpG :vI7p Jp97v 7Jy: 3FL 3F!L 3FLB 3FaL FL3. 3F", +"8L 3L.FB 8a3FL M3F !3MF M3TF M3aF j3MF M38F TMj3F M3sF (F3L 3F+L 3FL(B +a3F", +"L 3L.(F +83FL (BL3F. 8a3+FL 3(MF M3+F TM3(F aM3+F Mj3(F +M83F Mj3T(F s+M3F ", +"G3L !3GL H3GL a3GL 3LG. 83GL GH3L. G8H3L GM3 M3G! G3HM G3aM MjG3 G38M GTMj3", +" GMs3 d3GL G3+L GHd3L G3gL Gd3L. +G83L Hd3GL. gG83L G3dM +3GM dM3GT GMg3 dM", +"jG3 +GM83 GTMdj3 gsGM3 4FL !F4L LB4F aF4L 5F4L 8F4L 45FLB 48aFL 4MF MF4! TM", +"4F 4FaM 4F5M 4F8M 4T5MF 4MsF ;F4L +F4L 4;FLB a;F4L 45;FL 4F>L 5;F4LB >F4aL ", +"4FM; 4F+M M;F4T aM;4F M;F4j 4M>F 4T5M;F >Ms4F 4GL GL4! GH4L 4LGa 4LG5 4LG8 ", +"4GH5L 4G8HL 4GM 4!GM GT4M Ga4M G54M G84M 4GT5M 4GsM 4LG; 4L+G 4GHdL 4GgL 4G", +"5dL 4G>L G5H4dL g>4GL GM4d +G4M 4GTdM 4GgM 4GM5d 4G>M G5T4dM >Mg4G FL3N 3FN", +"!L 3FNLB a3FLN 3L.FN 83FLN .BL3FN a3F8LN M3QF Q!M3F QTM3F aM3QF QMj3F Q8M3F", +" TMjQ3F sQM3F 3FN(L +3FLN (BL3FN a3F+LN N.(3FL 83F+LN (FLBN.3 3L+N8aF QM3(F", +" +QM3F TM3Q(F +Q3aMF Mj3Q(F Q83+MF 3(MFQTj +QMs3F W3GL W!G3L GHW3L GaW3L GW", +"3L. G8W3L HW3GL. W83GaL G3WM GQM!3 GMZ3 ZGaM3 GQMj3 GQ8M3 ZGMj3 sZGM3 GWd3L", +" +GW3L HWdG3L gGW3L Wd3GL. G83+WL W3HLGd. G8Wg3L dM3GQ +GQM3 ZGdM3 gZGM3 GQ", +"Mdj3 dM3GQ8 dMjZG3 sZGgM3 mF4L 4mF!L 4mFLB amF4L 45mFL 48mFL 5mF4LB 48FamL ", +"4FMm MmF4! MmF4T aMm4F 4MpF p48MF p4TMF sp4MF 4m;FL 4+mFL m;F4LB 4+FamL 5m;", +"4FL >m4FL mL4B5;F amF>L4 MmF4; 4+QMF 4QTM;F aMF4+Q p4M;F >Mp4F M;Fp4T sp4>M", +"F 4LGm 4GW!L 4GHWL 4GaWL 4G5WL 4G8WL G5H4WL amL4G8 GQ4M 4GQM! 4GZM Z4GaM 4G", +"pM pG48M Zp4GM sZ4GM 4GvL v4+GL v4GHL gv4GL v4G5L v>4GL 4GHv5L g4Lv>G 4GvM ", +"vM4+G Zv4GM gZ4GM pv4GM >Mv4G pvGZ4M 4GyM 3F#L 3F&L 3FL#B a&3FL 3L.#F 8&3FL", +" #L.3BF a&38FL #3MF &3MF TM#3F aM3&F Mj#3F M&38F Mj#T3F sM&3F 3FL#( +&3FL #", +"3(LBF a&3+FL #(F3L. 8&3+FL (FLB#3. 3F+L8a& M#3(F M&3+F M#3T(F +T3M&F j#3M(F", +" +M3&jF 3(MFTj# M&3s+F #3GL &3GL GH#3L Ga&3L G#3L. G8&3L H#3GL. H83G&L M#G3", +" G3M& GTM#3 GT&M3 GMj#3 G8M&3 HM#Gj3 sGM&3 Gd#3L d&3GL Hd#G3L gG&3L d#3GL. ", +"G83d&L H#G3dL. G8&g3L dM#G3 dM&G3 GT#dM3 gMG&3 GM#dj3 dM3G&j dMGjH#3 sG&gM3", +" #F4L &F4L 4#FLB 4a&FL 45#FL 48&FL 5B#4FL 5aF4&L M#4F 4FM& 4TM#F 4T&MF 4M5#", +"F 48M&F 5T#4MF s4M&F 4;#FL ;&F4L ;#F4LB 4aF;&L 5;#4FL >&4FL 5#4L;FB 4a&>FL ", +"M;#4F M;&4F 4T#M;F a;F4M& 4M#;jF >M4&F 5FM;4T# s4&>MF G#4L 4LG& 4GH#L 4Ga&L", +" 4G5#L 4G8&L G5#4HL 4GLH5& 4#GM GM4& 4GTM# 4GTM& 4GM5# 4G8M& 4G#H5M s4GM& 4", +"Gd#L 4+G&L G;#4HL g4G&L G5#4dL >G4&L HL5d4G# >G&g4L 4GMd# dM&4G dM#4GT g4MG", +"& dM#4Gj >MG4& 5#dM4GT >M&s4G 3FN#L &3FLN #LN3BF &3FaLN #LN3F. &3F8LN 3LNB#", +"F. 3F&N8aL QM#3F M&3QF TM#Q3F Qa3M&F Mj#Q3F Q83M&F TMQj#3F M&3sQF #(L3FN &3", +"F+LN (FLB#3N 3L+Na&F 3F#LN.( 3L+N8&F (BN.3F#L 8a+F3L&N M#3Q(F +Q3M&F 3(MFQT", +"# Q3aM+&F 3(MFQj# j3+FQ&M TjQ#3(MF M&s3+QF GW#3L G&W3L HW#G3L Wa3G&L W#3GL.", +" W83G&L W3HLG#. HLW&G83 GQM#3 GQ&M3 ZGM#3 Z&GM3 WM#Gj3 M&3GQ8 GMjZ#3 sGMZ&3", +" Wd#G3L G&3+WL W3HLGd# G&Wg3L W3GLd#. GW+38&L 3LH.WdG# GWg38&L GQ#dM3 dM3GQ", +"& dM#ZG3 gMGZ&3 Q#G3dMj W38M+G& dMZjG#3 sGgZM&3 4m#FL m&F4L m#F4LB 4aFm&L 5", +"m#4FL 48Fm&L mL4B5#F am5&4FL Mm#4F Mm&4F 4T#MmF aMF4Q& p4M#F p&4MF 4TMp#F s", +"4Mp&F m;#4FL 4+Fm&L mL4B;#F a;4&mFL 5#4Lm;F m&F>L4 LB;F5m4# am>&4FL 4Q#M;F ", +"M;F4Q& Q#M;4TF MmT&4+F M;#p4F p&4>MF M;p#4TF >&s4pMF 4GW#L 4G&WL Gm#4HL amL", +"4G& G5#4WL m&L4G8 W#4LG5H HL5&4GW 4GQM# Mm&4G Z4GM# Z4&GM pG4M# pG&4M pGMZ4", +"# Z4MpG& v4G#L v&4GL 4GHv#L v&Gg4L 4G5v#L >G4v&L 45v#GHL >&g4vGL vM4G# vM&4", +"G vMGZ4# Z4GvM& vM4pG# >M4pG& ZGvMp4# y&4GM UI3 I3U! DIU3 U3aI I3U. U38I UD", +"I3. U8ID3 IM3 I!M3 VI3 aIV3 U3Ij 83IM IjV3 VIs3 I3U( U3+I UDI3( U+DI3 UI3(.", +" U+8I3 DI3U(. +DIU83 M3I( +3IM I3V( +IV3 IM3j( U+jI3 VIj3( sIV+3 UG3 G3U! J", +"U3 UaJ3 G3U. U3G8 U3J. U8J3 U3GM IM3G! VJ3 VaJ3 U3Gj UG8M3 VjJ3 s3VJ U3Id U", +"3+G UdJ3 JUg3 Id3U. U+G83 JUd3. gJU83 I3dM IdM+3 J3Vd g3VJ IdMj3 IdM83 JjVd", +"3 gVJs3 4UI U!4I UD4I Ua4I U54I U84I 4U5DI 4U8aI 4IM 4!IM V4I 4aVI Uj4I 8I4", +"M 4IV5 V4sI U;4I U+4I 4UDI; 4U+aI 4U5I; 4U>I U5D4I; >I4Ua I;4M +I4M 4IV; 4+", +"VI IM;4j 4I>M V45I; >IV4 4UG 4!UG J4U 4UJa U54G UG48 4UJ5 4UJ8 UG4M 4UGM! J", +"4V JaV4 UG4j 4UG8M V4J5 VJs4 UG4d U+4G 4UJ; J4gU 4UG5d 4U>G J4U5d >UJ4 Id4M", +" IdM4+ V4J; J4gV IdM4j >MG4U J4V5d J4V> I3UN U!I3N UDI3N UaI3N UI3N. U8I3N ", +"DI3UN. 8I3UaN U3QI IM3Q! QIV3 VQaI3 IM3Qj UQ8I3 VQIj3 sIVQ3 UI3(N U+I3N DI3", +"U(N +I3UaN I3(UN. +I3U8N D3UNI(. +3UND8I IM3Q( U+QI3 VQI3( V+QI3 UQ3Ij( Ij3", +"U+Q Ij3VQ( V+QsI3 U3WI UGW!3 UWJ3 JUWa3 UGW3. UG8W3 JUW3. J8UW3 U3GQ UGQ!3 ", +"Z3VJ ZJVa3 UGQj3 UGQ83 ZJVj3 sJZV3 Id3UW U+GW3 JUWd3 gJUW3 UW3Id. Id3UW8 UW", +"dJ3. gUWJ83 IdMW3 U+GQ3 ZJVd3 gVZJ3 Id3UWj Id3UQ8 VZdJj3 sJZgV3 Um4I Im!4U ", +"4UDIm 4UaIm 4U5Im 4U8Im U5D4Im U8m4aI UQ4I IMm4! 4QVI V4QaI 4UpI pU48I pIV4", +" Vps4I Im;4U 4U+Im 4UDIm; U+m4aI 4U5Im; >I4Um ImU;4D5 4Ua>Im IMm4; IMm4+ V4", +"QI; V4+QI pU4I; >MIp4 Vp4I; V>p4I UG4W 4UGW! 4UJm J4UWa 4UG5W 4UGW8 J4U5W J", +"48UW UG4Q 4UGQ! VZJ4 ZJ4Va 4UpG pUG48 J4Vp JpVs4 4UvI vU4+G vUJ4 Jvg4U vU4G", +"5 v>U4G Jv4U5 J>v4U 4IvM vIM4+ J4Vv VvJg4 pvU4G >Mv4I JpVv4 J4yV UIb3 U3I& ", +"bUDI3 UIc3 bUI3. I&3U8 UDIb3. cU8I3 b3IM I3M& bIV3 VIc3 IM3bj IM&83 VbIj3 s", +"IVc3 bUI3( I&3U+ UDIb3( cU+I3 UI3b(. U+8I&3 3(U.bDI U+8cI3 IM3b( IM&+3 VbI3", +"( Vc+I3 bM3Ij( IM3b+j Ij3Vb( Vc+sI3 b3UG U3G& bUJ3 JUc3 bGU3. bG8U3 JbU3. c", +"JU83 b3GM IM&G3 VbJ3 c3VJ bGMj3 bG8M3 JjVb3 sJVc3 Id3bU b+GU3 JbUd3 cJUg3 U", +"G3bd. I&3U8d bdUJ3. gcUJ83 IdMb3 IdM&3 VJbd3 gVJc3 IM3bdj Id3b8M VdbJj3 sJc", +"gV3 bU4I U&4I 4bUDI 4UcI 4bU5I 4b8UI b5U4DI c4U5I bM4I IM4& 4bVI cIV4 4bM5I", +" IM&48 V4b5I c4VsI 4bUI; I;&4U b;U4DI c4U+I b5U4I; >I4U& 45b;UDI c>4UI IM;4", +"b IM;4& V4bI; c4V+I 4bMI;j >Mb4I I;jV4b V>c4I bG4U UG4& 4bJU cUJ4 4bGU5 4bG", +"U8 J4bU5 cJ4U5 bG4M IM&4G JbV4 VJc4 4bGUj 4bG8M J4Vb5 sJ4Vc 4bGUd 4b+UG J4b", +"Ud cJ4gU bG54Ud >bG4U 4bdJ5U J>c4U IdM4b IdM4& J4Vbd gV4cJ 4bMIdj >Mb4G J4b", +"V5d J>Vc4 bUI3N I&3UN UDIb3N cUI3N UI3bN. U83I&N D3UNbI. U8Ic3N IM3bQ IM&Q3", +" VbQI3 cQVI3 bQUIj3 IM3bQ8 Ij3VbQ cQVsI3 UI3b(N U+3I&N D3UNbI( U+Ic3N 3(U.b", +"IN b3U+8IN UDb.3(IN UIc3+8N bQ3IM( IM3b+Q bQIV3( V+IcQ3 Qjb3IM( b3+Q8IM IjV", +"3bQ( s+cQVI3 bGUW3 UG&W3 JbUW3 cJUW3 UG3bW. I&3UW8 bWUJ3. J8UcW3 bGQU3 IM&W", +"3 ZJVb3 ZcJV3 IM3bWj IM3bW8 JjVZb3 ZcVsJ3 bWUId3 Id3UW& bWUJd3 gJUcW3 Wdb3U", +"G. b3+GUW8 W3J.bdU gWJ8cU3 Id3bWM Id3UQ& VJdZb3 ZcJgV3 IdWjbM3 +WUjI&3 djJ3", +"ZbV g3sJZcV 4bUIm Im&4U bmU4DI c4UIm b5U4Im 4U8Im& 45bmUDI 4U8cmI IMm4b IMm", +"4& V4bQI c4VQI pb4IM pU&4I Vp4bI cpV4I 4bUIm; 4U+Im& Imb;4UD 4U+cmI Imb;4U5", +" Im&>U4 bU4I5mD; c4U>Im 4bQIM; 4b+IMm 4bQV;I c4IV+m IM;pb4 >I4pU& pbIV4; V>", +"4cpI 4bGUW 4UGW& J4bUW cJ4UW bG54UW bG84UW 4bWJ5U c4UJ8m 4bGUQ IM&4W ZJ4Vb ", +"Zc4VJ pbG4U pUG4& JpV4b cpJV4 vb4UG vU&4G Jv4bU cvJ4U 4bGvU5 >I4vU& vb4J5U ", +"J>4cvU vbM4G vIM4& VvJ4b cvVJ4 pb4vIM >I4vbM Vv4Jpb yJVc4 6kF kF6! kF6B 6Fa", +"k 1k6F 6F8k 61kFB akF68 6MF MF6! 6FTk 6FaM l6F 68lF 6TlF sFl6 k(6F 6F+k 6k(", +"FB akF6+ 61k(F 6+1kF 1k(6FB 6+1akF M(6F 6F+M 6Tk(F 6+TkF 6(lF 6+lF l6T(F ls", +"6+F 6Gk 6!Gk Gk6H Gk6a 61Gk Gk68 6G1Hk 6G8Hk 6GM 6!GM GT6M Ga6M lG6 6Gl8 6G", +"lH s6lG Gk6d +k6G 6GHdk 6Ggk 6G1dk 6+G8k 1GH6dk g61Gk GM6d +G6M 6GTdk 6GgM ", +"6Gld 6+lG lG6Td g6lG 4kF kF4! kF4B 4Fak 7kF 8k7F kF7B ak7F 4F6M 4kM!F 4FTk ", +"4TkaF 7lF 78lF lF7T sF7l 4Fk; 4F+k k;F4B ak;4F k;7F 7k>F 7Bk;F 7>akF 6FM; 4", +"+kMF 4Tk;F aM;6F 7;lF >F7l 7lT;F l>7sF 4Gk 4!Gk Gk4H Ga4k 7Gk G87k Gk7H Ga7", +"k 6G4M 4GkM! GT4k 4GTak lG7 l87G 7GlH lG7s Gk4d +G4k 4GkH; 4Ggk Gk7d 7G>k 7", +"GHdk 7Ggk GM6; 4+G6M 4GTdk g4kGT 7Gld 7>lG 7GTld lGg7 kF6N 6!kFN 6kFNB akF6", +"N 61kFN 68kFN 1kF6NB 68FakN 6FQk 6Qk!F 6QTkF 6QakF 6QlF l6Q8F l6QTF ls6QF 6", +"k(FN 6+kFN k(F6NB 6+FakN 1k(6FN +kF68N 1k6(NBF 6F1+akN 6Qk(F 6+QkF Qk(6TF a", +"kF6+Q l6Q(F l+6QF 6QTl(F s6Ql+F Gk6W 6GWk! 6GHWk 6GaWk 6G1Wk 6G8Wk 1GH6Wk G", +"8k6Wa GQ6M 6GQM! 6GZk Z6Gak 6GlW lG6W8 Z6lG lZs6G 6GWdk 6+GWk GkH6Wd g6GWk ", +"1GW6dk +Gk6W8 61GkHWd 6G8gkW 6GQdk 6+GWM Z6Gdk gZ6Gk lG6Qd l+G6W lZ6Gd glZ6", +"G 4Fkm kmF6! kmF4B akm4F km7F 78kmF 7BkmF 7akmF 4FQk 4Qk!F 4QkTF aMm6F lF7p", +" 7lp8F 7lpTF 7slpF km;4F 4+kmF 6mFk;B akF6+m 7km;F 7>mkF km;7BF >km7aF 4Qk;", +"F 4+QkF kmF6T; akF4+Q 7lp;F l>p7F l;p7TF 7spl>F Gk4W 4GkW! 4GkHm akm4G Gk7W", +" 7GW8k 7GHWk 7GaWk GQ4k 4GQk! 4GZk Z4kGa 7plG 7pGl8 lG7Z 7sGlZ 4Gvk v6+Gk v", +"6GHk gv6Gk vk7G 7>Gvk 7vGHk g7vGk 6GvM v6M+G Zv6Gk Z4kgG lG7v l>G7v lvZ7G l", +"Gy7 9k6F 6Fk& 69kFB akF6& 691kF 6k:F 91k6FB :6akF 6F9M 6FM& 6T9kF 6T&kF 69l", +"F :6lF l69TF ls:6F 69k(F k&F6+ 9k(6FB 6+9akF 91k6(F :6+kF 916k(BF akF:6+ 6M", +"9(F 6+M9F 9T(6MF k&F6+T l69(F l:6+F 6T9l(F s:6l+F 69Gk Gk6& 6G9Hk 6Gak& 6G9", +"1k 6G:k 9G16Hk :G6Hk 9G6M GM6& 6GT9M 6GTk& 6Gl9 l6:G lG69H lsG:6 6G9dk dk&6", +"G 9GH6dk g69Gk 9G16dk :G6+k 691HGkd g:6Gk 6GM9d dM&6G 9GT6dM g6M9G lG69d l:", +"G6+ 6GTld9 gl:6G 9k4F 4Fk& 49kFB 49akF 9k7F :k7F 7B9kF 7:akF 4F9M 49M&F 49T", +"kF 49aMF lF79 lF7: 7l9TF 7sl:F k;F49 k;&4F 49Fk;B akF49+ 79k;F 7:>kF k;F7B9", +" :>F7ak 49M;F M;&6F k;F49T aMF49+ 7l9;F l>7:F l;97TF 7s:l>F 9G4k Gk4& 49GHk", +" 49Gak 9G7k 7k:G 7G9Hk 7:GHk 9G4M 49GM& 49GHM 49GaM l97G 7:lG 7GTl9 7sGl: 4", +"9Gdk dk&4G 9G;4Hk g49Gk 7G9dk 7:G>k 9G;7Hk g7:Gk 49GdM M;&6G 9GT4dk g49GM l", +"G79d l>G7: 7G9lH; gl7:G 69kFN k&F6N 9kF6NB 6aFk&N 91k6FN :6kFN 916kNBF akF:", +"6N 6Q9kF 6Q&kF 9QT6MF akF6Q& l69QF :Q6lF 6Q9lTF ls6:QF 9k(6FN 6+Fk&N 9k6(NB", +"F ak6&+FN 916k(FN 6+k:FN NB1F9k6( ak:F6+N 9Q(6MF k&F6+Q QT6F9M( 6F+Q9aM 6Q9", +"l(F l+6:QF 69l(QTF l6:Qs+F 6G9Wk 6G&Wk 9GH6Wk Gak6W& 9G16Wk :G6Wk 691HGkW 6", +"Ga:Wk 6GQ9M 6GQk& Z69Gk Z6&Gk lG69W :GQl6 lZ69G Z:l6G 9GW6dk +Gk6W& 69HkGWd", +" 6G&gkW 691WGkd 6+G:Wk GH1d69Wk g6G:Wk 9GQ6dM 6GQdk& 6GMZ9d Z6Gg9M 6GQld9 :", +"G6l+W lG6Z9d Z:6glG kmF49 km&4F 49FkmB akF6m& 79kmF 7:kmF kmF7B9 :mk7aF 49Q", +"kF Mm&6F kmF49T akF49Q 7lp9F :pl7F p9l7TF :pl7sF 49mk;F kmF49+ km6;9FB ak6m", +";&F km;79F :mk7>F km7B9;F ak:m7>F k;F49Q k;F4Q& Tk9;4QF aM9m4+F l;97pF :p7l", +">F l97Tp;F >F7s:pl 49GWk km&4G 9Gm4Hk 49Gakm 7G9Wk 7:GWk 9Gm7Hk 7Gk:Hm 49GW", +"M Mm&6G Z49Gk Z4kG& 7pGl9 :pG7l 7Zl9G 7Z:lG v69Gk v6&Gk 49GvkH g4Gvk& 7v9Gk", +" :vG7k v9G7Hk g7G:vk v6M9G v6MG& Z4Gv9M Z4Gg9M lv79G lv:7G 7Z9lvG yl7:G 6UI", +" 6!Ik Dk6I Ua6I 1U6I U86I 6U1DI 6U8aI 6IM 6!IM V6I 6aVI lI6 68lI V6lI s6lI ", +"6(Ik U+6I Ik(6D 6U+aI Ik(61 6U+1I 6D1Ik( 1U+6aI 6(IM +I6M 6IV( 6+VI 6Il( 6+", +"lI Vl6I( lsI6+ 6UG 6!UG J6U 6UJa 1U6G UG68 6UJ1 6UJ8 UG6M 6UGM! J6V JaV6 6U", +"lG lG6U8 lJ6 s6lJ UG6d U+6G 6UJd J6gU Idk61 Idk68 J61Ud gJ61U Id6M IdM6+ Vd", +"J6 J6gV 6Ild l+G6U J6ld g6lJ 4Ik 4!Ik Dk4I aI4k 7UI U87I Dk7I Ua7I 6I4M 4Ik", +"M! 4IV6 V46aI lI7 l87I 7VI lI7s U;6I +I4k Ik;4D ak;4I U;7I 7I>k 7UDI; 7>UaI", +" IM6; IM;6+ 6IV; V4+6I 7Il; 7>lI V;7I 7IV> 6U4G 4UG6! J4k 4aJk 7UG UG78 7JU", +" J87U 4UG6M Ik!4GM V4J6 J4V6a 7UlG 7UGl8 7Jl sJ7V UG6; Idk4+ 4dJk J4gk UG7d", +" >U7G Jk7d >k7J Idk4M 4+kIdM V6J; gV4J6 7Ild l>G7U ld7J 7Jgl 6NIk IkN6! IkN", +"6D 6UaIN IkN61 6U8IN 6D1IkN akN68I UQ6I 6UQI! 6QVI V6QaI 6QlI lI6Q8 Vl6QI l", +"sI6Q Ik(6N 6U+IN 6D(IkN akN6+I 1U(6IN 6UN1+I 6(1UDIN 6NU+1aI 6UQI( 6U+QI V6", +"QI( V6+QI lI6Q( l+I6Q V6QlI( sIQV6+ UG6W 6UGW! 6UJW J6WUa 6UG1W 6UGW8 J61UW", +" J68UW UG6Q 6UGQ! J6Zk ZJ6Va 6WlI lWI68 Z6lJ lJZs6 Idk6W 6U+WI J6WUd gJ6UW ", +"1UW6Id 6W8Idk 6UWJ1d J6Wg1U Idk6Q 6U+GQ ZJ6Vd gV6ZJ lWI6d l+W6I lJZ6d glJZ6", +" Um6I Ikm6! Ikm4D akm4I Um7I 7U8Im 7UDIm 7UaIm QI4k IMm6! 6IVm V6maI 7plI 7", +"pU8I 7IVp 7sIVp Ikm6; Ikm4+ 6DmIk; 4+DIkm 7UIm; 7>UIm Ikm7D; >Im7Ua Ik;4Q I", +"Mm6+ V6mI; V6+Im 7pUI; l>I7p 7VpI; 7V>pI UG6m 4WIk! 4WJk J4kWa UG7W 7UGW8 J", +"k7W 7JUW8 IMm6G Ik!4GQ J4Zk ZJ4ak 7WlI 7pUG8 Jp7V Jpl7s 4Ivk v6U+G v6Jk Jv6", +"gU vU7G 7vU>G 7UJv J>k7v 6IvM v6I+M J6Vv Vv6gJ lI7v lvI7> 7Jlv 7Jyl t6I 6It", +"& 6DtI tIc6 6It1 t6:I t61DI t:c6I 6ItM IM6& tIV6 cIV6 t6lI l6:I ltV6I u6I 6", +"It( 6+tI t6DI( tc6+I t61I( t:6+I 6D1tI( :c6t+I t6IM( t+6IM Vt6I( t+V6I lt6I", +"( lt+6I Vt6lI( 6+uI tG6 6Gt& tJ6 c6tJ 6Gt1 t6:G t6J1 J6t: 6GtM tG6M& VtJ6 V", +"Jc6 l6tG t:Gl6 J6lt uJ6 6Gtd 6+tG J6td g6tJ tG61d t:G6+ tJ61d gtJ:6 tG6dM t", +"+G6M tdVJ6 gV6tJ ltG6d t+Gl6 lJt6d gJu6 t4I 4It& 4DtI tIc4 7tI 7It: tD7I 7I", +"tc 4ItM t4IM& tIV4 tc4VI lI7t 7:lI Vt7I u7I 4It; 4+tI t4DI; tc4+I 7It; 7It>", +" 7tDI; t>7cI t4IM; t4+IM t4VI; t4V+I 7tlI; l>I7t 7VtI; 7>uI t4G 4Gt& tJ4 cJ", +"t4 7tG 7:tG 7Jt tJ7c 4GtM t4GM& VJt4 tJ4Vc lG7t 7tGl: tJ7V uJ7 4Gtd 4+tG J4", +"td g4tJ 7Gtd 7>tG td7J 7Jgt t4GdM t4+GM tJ4Vd gt4VJ 7tGld t>G7l lJ;7t g7uJ ", +"6ItN t6I&N t6DIN tc6IN t61IN t:6IN 6D1tIN :I6tcN 6QtI tQ6I& tQV6I tcQ6I tQ6", +"lI t:Q6I Vl6tQI 6QuI t6I(N t+6IN 6DIt(N c6It+N 6I1t(N :I6t+N 61t(DIN t6:Ic+", +"N tQ6I( t+Q6I V6ItQ( t+Ic6Q lI6tQ( t+6:QI l6tQVI( u6+QI 6GtW tG6W& J6tW tcW", +"J6 tG61W t:G6W tJ61W :Jt6W 6GtQ tGQ6& Z6tJ Zc6tJ tGQl6 t:G6Q lJZt6 ZJu6 tG6", +"Wd t+G6W tJ6Wd gtJ6W 6WItd1 t+6:WI J61tWd :J6gtW tGQ6d t+G6Q tZJ6d gtZJ6 tW", +"6lId t+6:GQ tZ6lJd ug6ZJ 4Itm t4Im& t4DIm tc4Im 7Itm t:m7I 7tDIm 7ctIm 4QtI", +" t4QI& t4VQI tc4QI 7Itp :pI7t tp7VI 7puI t4Im; t4+Im 6Dmt;I t+Ic6m 7tIm; t>", +"7Im 7DItm; 7cIt>m t4QI; t4+QI tQIV6; t4IcQ; tp7I; tp>7I 7VItp; u7Ip> 4GtW t", +"4GW& J4tW tJ4cW 7GtW 7tG:W tW7J 7Jt:W 4GtQ t4GQ& ZJt4 tZ4cJ 7ptG tpG7: 7JtZ", +" 7ZuJ v6tG tv4+G t4Jv cv6tJ tG7v :vI7t 7Jtv g7tJv tv4GQ t4+GQ Vv6tJ cvVJ6 l", +"vt7G :vI7l lvJ7t yJu7 e= 5e=B =a>e =eK +e=K =Te +T=e =je =j>e 5T=e s=e 4G", +"< 4!G< 4He Ga4e G5< G84e H54e H84e 4KG< 4G= f5=H f>g= f=K f+=K =Tf gf=T =jf =jf> f5=T sf= m =B5em >e=am", +" =Qe +Q=e Qe=T Qa=e p=e >ep= pe=T sep= 4We 4!We Hf= =H", +"fv5 g=fv> =Qf =+fQ Z=f Zfg= fp= p=f> fpZ= yf= ,e =B5,e >e-=a ,e=K -e=K ,T=e =e-T ,j=e =", +"e-j =T5,e -=se ,4G 4&,G 4G,H 4G,a 4G,5 4G,8 ,4GH5 ,4GH8 ,K4G ,4G&K 4G,T ,4G", +"T& 4G,j <&j4G ,4GHj ,4sG f=, f-= fH=, f-g= =,f5 ->f= =Hf,5 g=f-> f,=K =Kf- ", +"=,fT f-=T =,fj f-=j =Hjf, f-s= e-=m emB=5, =a->em ,Q=e =e-Q =QT,e =Q-Te =ep, pe-= p=T,e -ps=e 4G,", +"W We4& ,4GHm -v= fv5=H, f>-g=v =,fQ f-=Q f=Z,", +" f-Z= p,f= f-p= fpZ=, f-y= I< I 5D=I =D>e =IK +I=K", +" =TI +T=I =Ij >I=j 5T=I s=I G<4I I J=5 J>= f", +"I=K =If+K J=T =TgJ fj=I f>=Ij J=j s=J Im=I =D5Im >eD=m =QI +Q=I QD=I Qa=I p", +"=I p>=I pD=I sp=I WI4e I=I v=J5 v>J= fQ=I =Qf+", +"I Z=J gZJ= =Ifp fp>=I Jp= yJ= h< h<& hD< hc< h<. h8< D= h5=D c=h> h=K =Kh- h=", +"T hc=T h=j =jh> h5=T hs= h4G 4Gh& hJ4 cJh4 4Gh5 4Gh8 J4h5 J4h8 4GhK h4G&K J", +"4hT cJ4hT 4Ghj h48Gj J4hj h4sJ h=f f-h= J=h i= f=h5 f>h= h5J= i>= =Khf h=f-", +"K hJ=T i=T hf=j h=jf> hJ=j is= h=hm h=5Dm c=h>m h=Q h-=Q hQ=D hc=Q hp= h=-p =", +"Dhp s=hp h4W 4Wh& J4hW c4hW 4Wh5 4Wh8 J5h= J=hv5 v>i= =Qhv h=Q-v hZ= iZ= h", +"=fp fp-h= Z=hp yi= 6e 6e! 6eB 6ae 6e1 68e 6B1e 1a6e 6eK eK6! 6Te Te6a 6ej 8", +"e6j 1T6e s6e 6e* 6+e *B6e +e6a 1e6* 1+6e 6e1*B 6+e1a e*6K 6K+e Te6* +T6e ej", +"6* +e6j 6Te1* 6+se 6G< 6!G< 6He Ga6e 1G< G86e 1H6e Ga1< 6KG< 6Ge7 =B7e 7a>e 6e=K =6+eK 6T=e =T6+e ", +"7e=j >j7e 7e=T >e7s 6G4e 4G6 7fH g7f =Kf6 f=6+", +"K f6=T g=f6T 7fj fj7> 7fT sf7 6eN eN6! eN6B 6Nae 6N1e 6N8e 6e1NB 68eaN 6Qe ", +"Q!6e Qe6T Qa6e 1Q6e Q86e 6Qe1T 6Qse e*6N 6N+e 6e*NB 6+eaN 6e1*N 6+e1N 1eN6*", +"B aeN68* Qe6* +Q6e 6QeT* 6+QTe 6Qe1* 6+Q1e 1Qe6T* s6e+Q 6We 6!We He6W Wa6e ", +"1W6e W86e 6He1W 6H8We GQ6e 6GQm7e 7=emB 7ae>m 6Q=e =Q6+e =Q6Te =Qa6e 7ep= 7p>e 7p", +"e=T 7sep= 6W4e 4We6! He6m aem6G 7We W87e He7W Wa7e 4GQ6e 7v fv7H gf7v f6=Q =Qf6+ fvZ6 Z", +"f6g= 7fp 7pf> 7Zf y7f ?e ?e& ?Be ?ae ?1e ?:e 1e?B :e?a ?eK e&?K ?Te Te?a ?j", +"e :e?j 1T?e s?e ?e* ?-e *B?e -a?e 1e?* :e?- ?B1e* ?:-ae e*?K -e?K Te?* ?e-T", +" ej?* ?e-j ?T1e* ?-se ?G ?G& ?GH ?Ga ?G1 ?:G 1G?H :G?H ?GK G&?K ?GT GT?a ?G", +"j :G?j 1G?T s?G ?f ?f- ?fH g?f ?f1 :f? f1?H :fg? ?fK ?Kf- ?fT ?Tgf ?fj ?j:f", +" f1?T s?f ?4e 4e?& 4e?B 4a?e 7?e 7:e ?B7e 7e?a 4e?K ?4e&K 4T?e ?T4ae 7e?j 7", +"j:e 7e?T 7?se ?=e =e?- ?B=e =e?a 7e?= Ae ?=7eB Aae ?e=K ?-=eK =e?T ?-T=e =e", +"?j Aje ?T7=e Ase ?G4 4G?& 4G?H 4G?a ?G7 7:?G 7G?H 7G?a 4G?K ?G4&K 4G?T ?GT4", +"a 7G?j ?:G7j 7G?T ?G7s ?f= f-?= =H?f ?fg= 7f? Af ?H7f Agf =K?f ?f-=K =T?f ?", +"fTg= =j?f Afj ?T7f Asf ?eN e&?N eN?B ae?N 1e?N ?N:e ?B1eN ?:aeN ?Qe Qe?& Qe", +"?T Qa?e 1Q?e :e?Q ?Q1Te ?Qse e*?N -e?N ?Be*N ?-aeN ?1e*N ?:-eN 1e*?BN :-e?a", +"N Qe?* ?e-Q ?QTe* ?-QTe ?Q1e* ?:Q-e 1Qe?T* s?-Qe ?GW G&?W He?W Ga?W 1G?W :G", +"?W ?G1HW ?:GWa ?GQ GQ?& ?ZG Ze?a 1G?Q :G?Q Z1?G sG?Z ?fW f-?W fH?W ?Wgf f1?", +"W ?W:f ?f1HW g?:fW ?fQ f-?Q ?Zf ?fZ- f1?Q ?Q:f ?jZf ?Zsf ?me em?& em?B ae?m", +" 7e?m :e?m ?m7eB ?:mae 4Q?e ?Q4e& Te?m ?Qa4e ?pe 7e:p pe?T se?p =e?m ?e-m ?", +"=emB ?-mae ?=7em Aem 7=e?mB aeAm =e?Q ?-Q=e ?Tm=e ?-Tem pe?= Ape ?p=Te spAe", +" ?Gm Gm?& Gm?H Ga?m 7G?W :G?m ?G7Hm ?:GHm 4G?Q ?GQ4& Z4?G ?Z4Ga ?pG ?G:p ?G", +"7Z sG?p ?vf -v?f fv?H gf?v 7f?v Afv ?v7fH gfAv =Q?f ?fQ-v ?fZ= g?Zfv ?pf Ap", +"f 7f?Z yAf 6I< 6!I< 6De De6a 1I< 8I6e 1D6e D86e 6KI< I=I 7D=I 7D>e 6I=K =I6+K 6T=I =TI6+ 7I=j 7>I=j 7T=I =I7s 4G6I< 4G6I 7Jf J>7f =If6K f6+=IK J6=T J=g6T fj7I 7", +"f>Ij =T7J 7Jsf 6NI< II=m 7De=m 7>Dem 6", +"Q=I =QI6+ =QD6I =Qa6I 7p=I p=I7> p=D7I s=I7p I 7vJ= J>=7v =Qf6I =Q+v6I Z6J= Z=Jg6 7Ifp 7fp>I Z=7", +"J 7Jyf h? h?& h?D ?ch h?1 h:? ?Dh1 ?ch: h?K ?Kh& h?T hT?c h?j ?:hj ?Dhj hs?", +" h?* h?- h*?D h-?c ?1h* ?:h- ?D1h* h:?c- ?Kh* ?Kh- h*?T ?-hT h*?j ?-hj ?Djh", +"* h?s- h?G h&?G ?J ?Jc ?Gh1 ?Gh: ?J1 ?J: ?KhG ?G&hK ?JT cJ?T ?Ghj ?:Ghj ?Jj", +" s?J ?fh h-?f ?Jf i? h1?f ?fh: J1?f i?: ?Khf ?fh-K hT?f i?T hj?f ?fjh: Jf?j", +" i?s h?4 ?4h& ?Dh4 h4?c 7h 7h: 7hD 7hc ?Kh4 h?4&K ?Th4 ?ch4T 7hj 7:hj 7hT h", +"s7 h=? ?-h= h?=D ?ch= 7h= Ah =D7h Ahc =Kh? h=?-K h?=T c=?hT =j7h Ahj =T7h A", +"hs ?Gh4 ?G4h& ?J4 c4?J 7hG 7Gh: ?J7 7c?J ?G4hK h4&?GK J4?T ?Jc4T 7Ghj 7h:Gj", +" hT7J 7Jhs ?fh= h=?f- ?J= i?= 7hf Ahf 7f?J Ai h=?fK ?f-h=K =T?J =Ti? hj7f h", +"fAj =j?J Ais h?N ?&hN hN?D hN?c ?1hN hN?: ?D1hN h:?cN h?Q h&?Q ?QhT hQ?c ?Q", +"h1 ?:hQ ?QDh1 hQs? ?*hN hN?- ?D*hN ?ch-N h?1*N h:?-N h1*?DN ?c-h:N h*?Q ?-h", +"Q ?QDh* ?cQh- h?Q1* h:Q?- ?Q*h1T hs?-Q h?W h&?W ?JW hW?c ?Wh1 ?:hW J1?W ?W:", +"J ?GhQ ?GQh& hZ? ?chZ ?Whj h:W?Q h1?Z s?hZ hW?f ?-hW Jf?W i?W ?fh1W h:W?f ?", +"Jf1W ?:iW hQ?f ?fQh- ?fhZ i?Z ?fQh1 :fQh? hZ?f1 s?iZ h?m h&?m ?Dhm hm?c 7hm", +" ?:hm 7Dhm hm7c ?Qh4 h?Q4& ?Thm ?cQh4 hp? h:?p hT?p s?hp ?=hm ?-hm ?Dmh= c=", +"?hm 7=hm Ahm 7h=Dm hcAm h?=Q h=Q?- h=Q?D c=Qh? h=?p Aph hp?=D hpAs ?Ghm ?Gm", +"h& ?Jm cJ?m 7hW 7:hW hW7J hW7c ?GQh4 ?G&h4Q h4?Z hZ?c4 hW?p hp?:G hZ7 7Zhs ", +"hv? h?-v ?Jv i?v hv7 Ahv 7Jhv Aiv hQ?v hv?-Q ?Zhv ?Ziv ?phv hpAf 7Zhv Aiy <", +"eL L =B5", +"eL >e=aL =Me +M=e Te=M aM=e 5M=e =M>e =T5Me se=M 4LG< 4GLf= =Hf5L g=f>L =Mf =+fM fT=M gf=M f5=M =Mf> =HMf5 =Msf eLe=mL em", +"L=B5 =am>eL Qe=M =Q+Me =QTMe =QaMe pe=M p=>Me p=TMe s=pMe 4LWe 4We!L 4HeWL ", +"4WaeL 4We5L 4W8eL v=L fv5=HL f>vg=L fv=M =Qf+M =MZf g=MZf =M", +"fp fp>=M fpZ=M =Myf e-=L ,5e=BL =a->eL ,M=e =e-M =TM,e =T-Me =M5,e >M-=e ,5T=Me s=-Me ,L", +"4G ,4G&L ,4GHL ,4GaL ,4G5L ,4G8L ,4LH5e <&LG5a 4G,M -=L f5,=HL f>-g=L =,fM f-", +"=M =HMf, g=Mf- =Mf,5 f>M-= =H,f5M sf=-M ,eL 5m=L,eB >m=a-eL =QM,e =Q-Me Mem=T, =Te-Mm", +" p=M,e -p=Me peT=M, s=M-pe ,4GWL L =,f5vHL >Lg=-vf =Qf,M -vMf= Z=f,M Z-=fM fp=,M fp-=M ", +"Z=Mfp, yf-=M Ue =U5De >eU=D =IM +I=M V=I V+=I Ue=j =I>M V5=I >eV= UG4e 4UG J5=U =UJ> fU=M =Uf+M J=V gVJ= fU=j f>U=M =jVf Vfs", +"= UNI< IeU=m U5e=D", +"m >Im=Ua UQ=I =UQ+I Ve=Q V=+QI pU=I p=U>e =IVp V>ep= UW4e 4UWe! UUv= J=vU5 J>=vU fU=Q =Uf+Q VfZ= J=VgZ =Ufp fpU>= V", +"=Jp J=yV hU< U h=U5D c=h>U h=M h-=M V=h h=V- h5=M >Mh= =jVh V=hs 4UhG h4UG& ", +"hUJ4 cJ4hU h4UG5 h48UG J5Uh= J=hU5 =Ui> hf=M h=Mf- h=Vf iV= h=Mf5 h", +">Mf= J=Vh5 s=iV U=Um h5U=Dm h>Uc=m hQ=U h=Q-U =QVh c=VhQ =Uhp -pUh= V=hp cp=V", +"h 4UhW h4WU& J=U hvUJ=5 iv>=U =Mhv h", +"vM-= V=hZ Z=iV fpUh= fp-=U Jp=Vh yVi= 6ek 6!ke 6Bke ak6e e 7=ekB 7ae>k 6M=e =k+Me Tk=e =Tk+e l=e >el= le=T", +" les= G<4k 4Gkk7f fk7H gk7f f6=M =kf+M fT=", +"k g=kfT lf7 l>7f =Hlf g7lf 6Nke k=em =km7eB 7am>ke Qk=e =Qk+e =QkTe =Qake lep= l>ep= l=pTe l=s", +"pe Wk4e k7v 7fvHk g7fvk fQ=k =Qf+", +"k =kZf Z=kgf 7flv lfp7> 7Zlf lfy7 ?ke ke?& ke?B ak?e 1e?k ?k:e ?B1ke ?:ake ", +"?Me Me?& Tk?e aM?e l?e ?:le ?Tle les? ke?* ?e-k ?Bke* ?-ake ?1ke* ?:-ke ke*", +"?B1 :-k?ae Me?* ?e-M ?Tke* ?-Tke ?el* ?-le l?Te* l-?se ?Gk Gk?& Gk?H Ga?k 1", +"G?k ?k:G ?G1Hk ?:GHk ?GM GM?& GT?M Ga?M l?G ?:lG ?GlH lGs? ?fk fk?- fk?H gk", +"?f ?1fk fk?: ?f1Hk g?:fk ?fM f-?M fT?M gM?f lf? ?fl- lH?f lfg? 4k?e ke4& ?B", +"4ke ?a4ke ?k7e 7k:e 7?keB ?a7ke 4M?e ?M4e& ?T4ke ?aM4e 7?le 7:le ?T7le 7sel", +"? ?k=e =e-k ?=ekB =a?ke ?=7ke Ake 7ek?=B akAe =e?M ?-M=e =T?ke ?aM=e ?=le A", +"le l=?Te lsAe 4G?k ?G4k& ?G4Hk ?Ga4k ?k7G ?:G7k ?G7Hk ?G7ak 4G?M ?GM4& ?GT4", +"k ?Ga4M 7l?G l?G7: l?G7H s?G7l =k?f f-=k ?f=Hk g=k?f fk7? Afk 7f?Hk gfAk =M", +"?f ?fM-= ?fT=k g?Mf= ?fl= Alf lf?=H glAf ke?N ke&?N ?BkeN ?akeN ?1keN ?:ekN", +" keN?B1 :ek?aN Qk?e ?Qke& ?QTke ?Qake ?Qle ?:Qle l?QTe s?lQe ?ke*N ?-keN ke", +"*?BN -ke?aN ke*?1N :ek?-N ke?B1*N ak:e?-N ?Qke* ?-Qke Qke?T* ?Qe-Tk l?Qe* l", +"-?Qe leQ?T* s?Ql-e Gk?W ?GWk& ?GHWk ?GaWk ?G1Wk ?:GWk 1He?Wk ?Hk:We GQ?M ?G", +"Qk& Zk?G ?ZGak ?GlW l?G:W lG?Z s?ZlG fk?W ?-Wfk ?fHWk g?fWk ?f1Wk :f?Wk f1H", +"?Wk :fWg?k fQ?M ?fQ-k ?MZf g?Zfk lW?f lf?:W ?Zlf gl?Zf ke?m ?mke& ?mkeB ?am", +"ke ?m7ke ?:mke 7ek?mB ?ak:em Me?m ?Mme& ?Tmke ?aMem le?p :pel? ?plTe s?ple ", +"?=ekm ?-mke =ke?mB ?ae-km 7=e?mk keAm =B?m7ek Akmae ?Mm=e ?-Mem ?Qe=Tk ?Qe=", +"ak l=?pe leAp ?pTl=e Apels Gk?m ?Gmk& ?GmHk ?Gakm ?G7Wk ?:Gkm ?Hk7We ?Gk7Wa", +" GM?m ?GMm& ?Z4Gk ?GaMm lG?p ?pGl: ?Zl7G s?plG fk?v -vk?f ?vfHk g?vfk ?v7fk", +" fvAk 7fH?vk Avkgf fv?M ?vMf- ?Zf=k g?vfM ?plf lfAp lv?Zf ylAf 6Ue 6!Ue Ue6", +"D Ua6e 1U6e U86e 6Ue1D 6U8De Ue6M Ik 7Ue=D 7>UD", +"e 6I=M =Ik+M V6=I V=6+I l=I =Il> =I7V >e7V 4UG6e I =U7J >kJ= =Uf6M =U+f6M =kVf J=Vg6 =Ulf lf7>U l=J 7Vsf 6", +"NUe 6Ue!N 6UeDN 6UaeN 6Ue1N 6U8eN IkN1D< akN1I< UQ6e 6UQe! 6QVe V6eQa QIl< ", +"lIUem 7Dm=Ik >Dm7U", +"e QI=k =QI+k V=6QI =QaIk lIp= l=Ip> V=plI V>e7p I J=k7v J>=vk =Uf6Q =U+f6Q ZJ=k J=kgZ =Ilv fpU7", +"> Jpl= l=yJ h?t h&?t ?Dht ht?c ?th1 ?th: ?t1hD ?t:hc h?M h&?M V?h Vh?c lh? ", +"l?h: lhV? u?h t*h? h?t- ?tDh* ?cht- ?t1h* ?t:h- h?1t*D ?cth:- h*?M ?-hM V*h", +"? h?V- h?l* h?l- V?lh* h?u- ?tG ?&tG ?Jt tJ?c ?1tG t:?G J1?t ?t:J ?GhM ?tGM", +"& ?JV cJV? h?lG lh?:G ?Jl u?J tf? t-?f tf?J i?t f1?t ?t:f ?Jtf1 ?ti: hM?f ?", +"fMt- V?f i?V ?flh lf?h: ?Jlf ui? ht4 h&t4 hDt4 tch4 7ht 7th: 7Dht ht7c ?Mh4", +" h?M4& h4V? V?hc4 7hl l:7h 7Vh u7h t=h t-h= ht=D htc= 7ht= Aht t=7hD htAc h", +"?=M h=Mt- h=V? c=Vh? l=h Alh V=7h Auh t4?G ?tG4& h4tJ tJ4?c ?G7t 7tGh: tJ7h", +" ?J7t: ?tG4M ?G&h4M J4V? ?JVc4 lG7h 7hl:G 7V?J ?Ju7 tf= f-t= t=J it= tf7 At", +"f 7Jtf Ait =Mtf tf=-M V?J= t=iV tfl= lfAh ?Jl= Aiu hN?t ?t&hN ?tDhN ?chtN ?", +"t1hN ?t:hN ht1?DN ?cth:N ?thQ ?tQh& hQV? V?hcQ hQl? lh?:Q V?lhQ h?uQ ?t*hN ", +"t-?hN h?Dt*N t-h?cN h?1t*N t-?h:N hDt*?1N hN?ct-: ?tQh* t-Qh? V?hQ* V?-hQ l", +"h?Q* l-h?Q lhQV?* uh-?Q ?thW ?tGW& ?WtJ ?cWtJ ?tG1W h:W?t ?Jt1W ?J:tW ?WhM ", +"?tGQ& tZ?J hZ?tc h?lW lhW?: lJ?Z hZu? ?Wtf t-W?f ?JtfW ?tiW tf?1W tf:?W tf1", +"?JW i?t:W ?Qtf tfQ?- tf?Z ?ZiV lhW?f lhW?- V?flZ i?uZ ?thm ?tmh& ?tmhD ?cmh", +"t hm7t h:m7t 7htDm 7hctm ?Mhm ?Mmh& hmV? V?mhc 7htp hpl?: 7Vhp hpu? hmt= t-", +"mh= t=hDm t=chm t=7hm htAm 7hDt=m Atmhc ht=Q t=Qh- V?mh= c=Qht hpl= hpAl l=", +"hVp upAh t4hW ?tGm& ?mtJ ?Jmtc hW7t 7hWt: ?J7tW ?J:tm ?tG4Q ?G&t4Q h4tZ V?m", +"cJ lW7h lhW7: tp?J hZu7 tf?v hv?t- tv?J ?vit 7htv hvAt hv7tJ itAv =Qtf hv?-", +"M t=hZ ?viV hvl= lvAh hZl= yAui O !O OB aO O. 8O .BO 8aO OK !KO TO TaO jO j", +"O8 jOT sO (O +O (BO +aO (O. +8O (O.B 8a+O (OK +OK T(O +TO jO( +jO T(jO s+O ", +"EO !EO HO HaO EO. 8EO HO. H8O EKO !OEK HTO TaHO jOE 8EjO HjO sHO dO +dO HdO", +" gO dO. 8dO dOH. g8O dKO dK+O TdO gTO djO jO8d jOTd gsO O2 !O2 2BO aO2 5O 5", +"8O 5BO 5aO 2KO !O2K TO2 T2aO jO5 58jO 5TO s5O ;O +;O ;OB a;O 5;O >O ;O5B >O", +"a ;OK ;O+K T;O +OT; ;jO >jO jOT; s>O EO2 EO!2 HO2 aOH2 5EO 8E5O H5O HO5a EO", +"2K !EO2K TOH2 HTaO2 5EjO jO58E jOH5 H5sO d;O d;+O H;O g;O 5dO >Od HO5d g>O ", +";OdK +d;OK HOT; T;gO jO5d dj>O jOH; >Ogs P P! PB aP P. 8P P.B 8Pa QP Q!P TP", +" QaP Pj Q8P TPj sP P( +P P(B +Pa P(. +P8 .BP( +8aP QP( +QP TP( +TP Pj( +Pj ", +"T(Pj sP+ WP W!P HP HPa WP. W8P HP. H8P WQP WPQ! ZP ZaP WjP 8PWj ZPj sZP dP ", +"+WP HPd gP dP. 8dP H.dP gP8 QdP Qd+P ZdP gZP dPj Wj+P dPZj gsP mP mP! mPB a", +"mP 5P 5P8 5PB 5aP QmP mPQ! TmP amTP pP p8P pTP spP ;P +mP ;PB a;P 5P; >P 5B", +";P >Pa Q;P Q;+P T;P Tm+P p;P >Pp T;pP >Ps WmP mPW! HmP amHP 5WP W85P H5P 5a", +"HP QmWP Q!WmP ZmP amZP pWP W8pP ZpP ZpsP vP v+P vHP gvP v5P >Pv H5vP >Pg vQ", +"P +QvP ZvP ZvgP pvP pv>P ZPpv yP #O &O #BO a&O #O. 8&O #O.B a&8O #OK &OK T#", +"O T&O jO# &jO T#jO s&O #(O +&O #(OB a&+O (O#. 8&+O (BO#. +8a&O (O#K &O+K #(", +"TO +OT& #(jO +&jO jOT#( +&sO #EO &EO H#O H&O EO#. &E8O #OH. 8&HO #OEK EK&O ", +"T#HO HOT& #EjO &EjO H#jO H&sO d#O d&O d#HO g&O #Od. 8Od& Hd#O. 8&gO #OdK &O", +"dK d#TO T&gO d#jO jOd& dj#HO gOs& #O2 &O2 #O2B &2aO 5#O 5&O #B5O a&5O #O2K ", +"2K&O #OT2 &OT2 5#jO jO5& T#5O 5&sO ;#O ;&O #B;O aO;& ;#5O >&O 5;#OB a&>O #O", +";K &O;K ;#TO TO;& ;#jO &j>O ;j#TO s&>O EO#2 EO&2 #OH2 &OH2 #E5O &E5O 5#HO H", +"O5& #O2EK &EO2K HT#O2 H&TO2 jO5#E &jE5O H5T#O sH5&O ;#dO dO;& ;#HO ;&gO d#5", +"O d&>O H5d#O g&>O dK;#O d&;OK H;T#O gT;&O dj#5O >&djO H;j#O gs>&O P# P& P#B", +" aP& P#. 8P& .BP# 8aP& QP# Q&P TP# TP& Pj# P&j T#Pj sP& P#( +P& #BP( +aP& #", +"(P. +8P& P#(.B aP&+8 P#Q( Q&+P P#T( T&+P j#P( P&+j Pj#T( +Ps& WP# W&P HP# H", +"P& P#W. 8PW& P#H. 8PH& QPW# WQP& ZP# Z&P W#Pj P&Wj PjZ# Z&sP dP# dP& H#dP g", +"P& P#d. d&8P dP#H. 8Pg& Q#dP dPQ& dPZ# Z&gP d#Pj P&dj dPjZ# g&sP mP# m&P P#", +"mB m&aP 5P# 5P& P#5B aP5& mPQ# QmP& mPT# m&TP pP# p&P TPp# p&sP ;P# ;P& PB;", +"# ;&aP 5#;P >P& ;P#5B aP>& Q#;P ;PQ& T#;P ;PT& ;Pp# p&>P pT;P# >&sP mPW# Wm", +"P& mPH# m&HP WP5# W&5P H#5P 5PH& WQmP# m&PWQ mPZ# m&ZP WPp# W&pP pPZ# ZPp& ", +"vP# v&P HPv# v&gP 5Pv# v&>P vH5P# >&gP QPv# Q&vP vPZ# ZPv& vPp# pPv& ZpvP# ", +"y&P CO !CO DO DaO CO. 8CO DO. D8O CKO !OCK DTO TaDO jOC 8CjO DjO sDO C(O +C", +"O D(O +DO (OC. 8C+O (OD. +OD8 (OCK CK+O T(DO DT+O C(jO +CjO D(jO +DsO CEO C", +"E!O HDO DaHO EOC. CE8O DOH. HOD8 COEK !EOCK DTHO HDTaO CEjO jO8CE HDjO HDsO", +" dCO dC+O DdO gDO COd. dC8O dOD. D8gO CKdO +dCOK DOTd DTgO dCjO djC+O jODd ", +"gOsD CO2 CO!2 DO2 D2aO 5CO 8C5O 5DO 5OD8 CO2K !C2OK T2DO DTaO2 5CjO jO58C j", +"O5D 5DsO ;CO ;C+O D;O +OD; ;C5O >CO 5OD; >DO CK;O +;COK DOT; a;ODT ;CjO jO>", +"C jOD; sD>O EOC2 !EOC2 DOH2 HDaO2 CE5O 58CEO HO5D H5D8O EKCO2 EK2!CO HDTO2 ", +"DTaHO2 jO5CE 58CjOE H5DjO sH5DO ;CdO +d;CO HOD; D;gO dC5O dC>O 5ODd gD>O dK", +";CO dK;+CO H;DTO gDT;O djC5O >jdCO H;jDO >DOgs PC PC! DP DPa PC. 8PC DP. D8", +"P QPC PCQ! QDP DPQa PjC QC8P DPj sPD PC( +PC DP( +DP C(P. +C8P P(D. D8+P PC", +"Q( QP+C Q(DP QD+P jCP( +CPj D(Pj +DsP WPC PCW! HPD DPWa PCW. WC8P H.DP D8HP", +" QPWC Q!WPC ZDP DPZa WCPj PjCW8 DPZj ZDsP dPC +CdP DdP gPD PCd. 8CdP D.dP D", +"8gP QCdP dPC+Q DdZP ZDgP dCPj dPj+C dPDj gDsP mPC P!mC DmP amDP 5PC 5C8P 5D", +"P D85P mPQC Q!mPC TmDP amPQD pPC 8PpC pDP pDsP ;PC +C;P D;P Dm+P 5C;P >PC D", +";5P >PD QC;P ;PC+Q DPQ; a;PQD ;PpC pP>C D;pP pD>P mPWC W!mPC DmHP amPWD WP5", +"C 5W8PC 5DHP H5PD8 WQmPC WmPQ!C DmZP ZDamP WPpC pW8PC ZPpD sPDZp vPC +PvC v", +"DP vDgP 5PvC vP>C 5DvP vD>P QPvC v+QPC ZPvD ZvDgP vPpC >PpvC pPvD yDP bO b&", +"O bDO cO bO. b8O DOb. c8O bKO &ObK bTO cTO bjO jOb8 jObT scO b(O b+O D(bO c", +"+O (Ob. +8bO bD(O. +8cO (ObK +ObK T(bO +TcO b(jO jOb+ bTj(O c+sO bEO &EbO b", +"HO cHO EOb. 8EbO HOb. H8cO EKbO bK&EO HTbO HTcO bEjO &jEbO jObH cHsO bdO bO", +"d& bODd gcO dOb. bO8d bHdO. c8gO dKbO d&ObK bOTd cTgO jObd d&jbO bHjdO gOsc", +" bO2 &Ob2 DOb2 c2O b5O bO5& bO5D c5O 2KbO bK&O2 TOb2 TOc2 jOb5 &jOb5 bO5T s", +"Oc5 b;O bO;& bOD; c;O 5;bO >bO b5D;O c>O ;ObK ;&ObK bOT; T;cO jOb; bj>O b5T", +";O >Osc EOb2 b&EO2 HOb2 HOc2 5EbO b58EO bOH5 H5cO bKEO2 &EObK2 bHTO2 c2HTO ", +"b5jEO b5E&jO bH5jO c5HsO d;bO d&;bO bOH; gOc; bO5d bd>O bH5dO >Ogc bd;OK bd", +"O;&K bH;TO c;TgO b5djO >bdjO bH;jO c>gsO bP bP& bPD cP bP. b8P b.DP cP8 bQP", +" Q&bP bTP cQP bPj Q8bP DPbj scP bP( b+P b(DP cP+ P(b. +Pb8 bPD(. +Pc8 QPb( ", +"+QbP b(TP +QcP b(Pj +Pbj bTPj( s+cP bWP W&bP bHP cWP WPb. W8bP b.HP H8cP WQ", +"bP bWQP& ZbP ZcP WjbP P&jbW bPZj sPZc bdP +WbP HPbd gcP b.dP 8dbP bHPd. g8c", +"P QdbP dP&bQ bdZP gPZc dPbj dP&bj ZbdPj scgP bmP m&bP DmbP cmP b5P 5Pb8 5Db", +"P c5P QmbP m&PbQ TmbP TmcP pbP b8pP bTpP cpP b;P +mbP D;bP c;P 5Pb; >Pb b5P", +"D; c>P Q;bP ;P&bQ T;bP Q;cP b;pP pb>P pbD;P >Pcp WmbP m&PbW HmbP HmcP 5WbP ", +"b5W8P H5bP H5cP bWQmP bWQm&P bmZP ZmcP bWpP pbW8P ZPpb cPZp vbP b+vP bHvP c", +"vP b5vP vb>P vbH5P >Pcv bQvP vb+QP ZPvb cPZv pPvb >Pbpv ZpbvP ycP 0O !0O 0B", +"O a0O 1O 18O 1OB 1aO 0OK 0O!K T0O a0TO jO1 18jO 1TO s1O 0(O +0O 0(OB a0+O 1", +"(O 1+O (B1O +a1O (O0K 0O+K 0(TO T0+O 1(jO jO1+ T(1O 1+sO E0O E0!O H0O a0HO ", +"1EO 8E1O 1HO 1OH8 0OEK !EO0K T0HO HTa0O 1EjO jO18E jO1H 1HsO d0O d0+O d0HO ", +"g0O 1dO 1O8d Hd1O g1O 0OdK +d0OK d0TO T0gO jO1d djO1+ 1OTd gOs1 0O2 0O!2 0O", +"2B 0Oa2 15O 581O 5B1O 1O5a 0O2K 2K0!O 0OT2 Ta0O2 15jO jO158 1O5T 15sO ;0O ;", +"0+O 0B;O ;0aO 1;O >O1 ;O1B 1a>O 0O;K +;0OK ;0TO a;0TO jO1; jO>1 1OT; s1>O 0", +"OE2 !EO02 0OH2 Ha0O2 5E1O 158EO 1OH5 1H58O EK0O2 2K0!EO HT0O2 Ta0HO2 jO15E ", +"158jOE 1H5jO s1H5O ;0dO +d;0O ;0HO ;0gO 1O5d 1d>O 1OH; >Og1 dK;0O dK;+0O H;", +"T0O gT;0O djO1; >j1dO 1H;jO gs>1O P0 P0! P0B aP0 1P 1P8 1PB 1aP QP0 P0Q! TP", +"0 Q0aP 1QP Q81P 1TP sP1 P0( +P0 0BP( +0aP 1P( 1+P P(1B +P1a P0Q( QP+0 P0T( ", +"+0TP 1(Pj +Q1P 1(TP 1+sP WP0 P0W! HP0 H0aP 1WP W81P 1HP H81P QPW0 Q!WP0 ZP0", +" aPZ0 Wj1P 1WQ8P Z1P Z1sP dP0 +0dP H0dP gP0 1dP +W1P HP1d g1P Q0dP dP0+Q dP", +"Z0 ZPg0 Qd1P dPj1+ 1dZP sPg1 mP0 P!m0 P0mB mPa0 1mP 8m1P 1B5P 5a1P mPQ0 Q!m", +"P0 mPT0 amPQ0 p1P 1Pp8 1TpP p1sP ;P0 +0;P PB;0 a0;P 1;P >P1 1B;P 1a>P Q0;P ", +";P0+Q T0;P a;PQ0 1;pP p1>P T;1P s1>P mPW0 W!mP0 mPH0 amPH0 5W1P 1W58P H51P ", +"1Hm8P WQmP0 WmPQ!0 mPZ0 ZamP0 1WpP p1W8P p1ZP sP1Zp vP0 +Pv0 HPv0 vPg0 v1P ", +"v1>P 1HvP g1>P QPv0 v+QP0 vPZ0 ZvPg0 pPv1 >Ppv1 ZPv1 y1P 9O 9&O 9OB 9aO 91O", +" :O 1B9O :aO 9OK &O9K 9TO 9OT& 9jO :jO jO9T s:O 9(O 9+O (B9O +a9O 1(9O :+O ", +"91(OB +a:O (O9K +O9K T(9O 9O+T 9(jO +j:O 9T1(O :+sO 9EO &E9O 9HO 9OH& 1E9O ", +":EO 9O1H :HO EK9O 9&EOK HT9O 9HTaO 9EjO jO:E jO9H sO:H 9dO 9Od& Hd9O g9O 9O", +"1d :dO 9H1dO g:O dK9O d&O9K 9OTd 9TgO jO9d dj:O 9HjdO gOs: 9O2 &O92 2B9O aO", +"92 95O :5O 5B9O 5a:O 2K9O 9&O2K TO92 9TaO2 jO95 jO:5 9O5T :5sO 9;O 9O;& ;O9", +"B 9Oa; 9O1; :>O 95;OB :a>O ;O9K ;&O9K 9OT; 9+T;O jO9; :j>O 95T;O >Os: EO92 ", +"9&EO2 HO92 9HaO2 5E9O 5E:O 9OH5 H5:O 9EO2K &EO92K 9HTO2 H&O9T2 95jEO :5jEO ", +"9H5jO :H5sO d;9O d&;9O 9OH; 9;gO 9O5d >O:d 9H5dO >Og: 9d;OK 9dO;&K 9H;TO g9", +"T;O 95djO :>djO 9H;jO g:s>O 9P 9P& 9PB 9aP 9P1 :P 1B9P :Pa 9QP Q&9P 9TP Qa9", +"P 9Pj :QP 1T9P s:P 9P( 9+P P(9B +P9a 9(1P :P+ 9P1(B +P:a QP9( +Q9P 9(TP +T9", +"P 9(Pj +Q:P 9TP1( s+:P 9WP W&9P 9HP HP9a 1W9P :WP 1H9P :HP WQ9P 9WQP& Z9P 9", +"aZP Wj9P Wj:P 9PZ1 Z:P 9dP +W9P HP9d g9P 1d9P :dP 9HP1d g:P Qd9P dP&9Q 9dZP", +" Z9gP dP9j Qd:P Z91dP gPZ: 9mP m&9P mP9B am9P 95P :mP 9B5P 5a:P Qm9P m&P9Q ", +"Tm9P 9QamP p9P :pP 9TpP sP:p 9;P +m9P 9B;P a;9P 1;9P >P: 95P;B :a>P Q;9P ;P", +"&9Q T;9P a;P9Q 9;pP >P:p p9T;P s:>P Wm9P m&P9W Hm9P 9HmaP 5W9P 5W:P H59P H5", +":P 9WQmP 9WQm&P 9mZP Z9amP 9WpP pW:P ZPp9 :PZp v9P 9+vP 9HvP v9gP 95vP :vP ", +"v91HP >Pg: 9QvP v9+QP ZPv9 Zv9gP pPv9 pv:P Zp9vP y:P C0O C0!O D0O a0DO 1CO ", +"8C1O 1DO 1OD8 0OCK C0O!K T0DO DTa0O 1CjO jO18C jO1D 1DsO 0(CO C0+O 0(DO D0+", +"O C(1O +C1O D(1O 1O+D C0O(K +C0OK DT0(O +DT0O jO1C( 1+jCO 1DT(O s1+DO E0CO ", +"C0O!E D0HO HDa0O CE1O 18CEO HD1O 1HD8O C0OEK EK0!CO HDT0O DTaH0O jO1CE 18Cj", +"OE 1HDjO s1HDO C0dO +dC0O d0DO D0gO dC1O 1+dCO 1ODd 1DgO dKC0O dKC+0O DdT0O", +" gDT0O djC1O 1+CdjO 1DdjO gs1DO 0OC2 C02!O 0OD2 Da0O2 5C1O 158CO 1O5D 1D58O", +" C02OK 2K0!CO DT0O2 Ta0DO2 jO15C 158jOC 1D5jO s15DO C0;O +;C0O ;0DO a;0DO ;", +"C1O 1C>O 1OD; 1D>O ;C0OK ;C0+OK D;T0O D;0+TO ;jC1O >j1CO 1D;jO >DOs1 C02EO ", +"!EOC02 HD0O2 Da0HO2 15CEO 58C1EO 1H5DO H5D1aO EK2C0O E02K!CO DT0HO2 DTH0aO2", +" 15CjOE 5E1O8jC H5D1TO 1H5sDO d;C0O d;C+0O H;D0O gD;0O 1d5CO >C1dO 1H;DO >D", +"Og1 ;C0dKO C0;O+dK Td0D;O D;Tg0O 1dC;jO djC>O1 djO1D; gs1>DO PC0 !CP0 DP0 D", +"0aP 1PC 1C8P 1DP D81P PCQ0 Q!PC0 Q0DP aP0QD 1CPj PjC18 QD1P 1DsP C0P( PC+0 ", +"P0D( +0DP PC1( 1C+P 1(DP +D1P QPC0( +QPC0 QDP0( +QDP0 PjC1( 1+QPC 1QDP( sP1", +"+D PCW0 W!PC0 H0DP aP0WD WP1C 1W8PC HP1D 1HPD8 WQPC0 WPCQ!0 DPZ0 ZDaP0 PjC1", +"W 1W8PjC 1DZP sP1ZD PCd0 dPC+0 D0dP DPg0 1CdP 1+WPC Dd1P 1DgP dPCQ0 +QCdP0 ", +"ZDdP0 gZDP0 dPj1C dPC1+Q Z1DdP gZ1DP PCm0 mPC!0 mPD0 amPD0 1C5P 1m8PC 5D1P ", +"1Dm8P QmPC0 mPCQ!0 QDmP0 QDmaP0 1PpC p18PC 1DpP sP1pD PC;0 ;PC+0 D0;P a;PD0", +" 1C;P 1P>C D;1P 1D>P ;PCQ0 +QC;P0 QD;P0 aP0QD; p1;PC >Pp1C pD1;P >Ps1D WmPC", +"0 mPCW!0 HmDP0 HmDaP0 1W5PC 5W81PC 1HmDP H8m1DP QmPWC0 QCW0mP! ZDmP0 amPZD0", +" p1WPC 1W8pPC Zp1DP Zp1sPD PCv0 v+PC0 DPv0 gvDP0 1PvC >Pv1C 1DvP >Pg1D vQPC", +"0 +QPvC0 ZvDP0 vDPgZ0 pv1PC pv1>PC Zv1DP 1DyP b9O 9&bO 9DO c9O b1O :bO bO1D", +" :cO 9ObK b9&OK bO9T 9TcO jOb1 bj:O jO9D sO:c 9(bO bO9+ D(9O 9+cO 1(bO b+:O", +" b1D(O c+:O b9(OK b+9OK bT9(O c9+TO b1j(O :b+jO b1T(O :c+sO 9EbO b9&EO bO9H", +" 9HcO 1EbO bE:O bO1H cH:O b9EOK 9&EbKO bH9TO c9HTO b1jEO :bjEO b1HjO :cHsO ", +"bO9d d&Ob9 9ODd c9gO bO1d bd:O b1HdO gO:c bd9OK 9+ObdK bTd9O gc9TO b1djO :d", +"bjO b1TdO g:scO 9Ob2 b9&O2 DO92 9Oc2 bO95 b5:O 9O5D :Oc5 b9O2K 9&ObK2 bT9O2", +" c29TO b15jO :b5jO b1T5O :c5sO bO9; ;&Ob9 9OD; 9;cO bO1; :b>O b1;DO >O:c b;", +"9OK 9+Ob;K bT;9O c;9TO b1;jO :>bjO b1T;O c>s:O b9EO2 9&EbO2 bH9O2 c29HO b15", +"EO :b5EO b1H5O :cH5O 9EObK2 EOb29&K 9HObT2 9HTc2O 95EbjO b5j:EO bHO95T s:Hc", +"5O bd9;O bd9;&O bH;9O c;9gO b1d5O :>bdO b1H;O g:c>O 9dOb;K d&b;9OK bHO9T; g", +"9Tc;O djOb1; >bj:dO djO95D c>sg:O bP9 b9P& 9DP cP9 b1P :Pb 1DbP :cP 9QbP bQ", +"9P& 9TbP 9QcP 9Pbj bQ:P 1TbP :csP b(9P 9+bP 9(DP 9+cP b(1P b+:P b1PD( :+cP ", +"bQ9P( b+Q9P bTP9( cQ9+P b1QP( :Qb+P b1TP( :cQ+P 9WbP bW9P& 9HbP 9HcP 1WbP b", +"W:P 1HbP cW:P bW9QP 9WQbP& bPZ9 cPZ9 b1WPj :WbPj b1ZP :PZc 9dbP dP&b9 Dd9P ", +"cPg9 1dbP bd:P b1HdP :cgP bQd9P 9+QbdP Zb9dP Zcg9P dPjb1 :QdbP Zb1dP g:PZc ", +"9mbP m&Pb9 Dm9P 9mcP 95bP b5:P 5D9P c5:P bQ9mP bQ9m&P bTm9P cQ9mP b1pP pb:P", +" 9DpP :Pcp 9;bP ;P&b9 D;9P 9;cP 1;bP >b:P b1;DP :c>P bQ;9P 9+Qb;P bT;9P cQ;", +"9P pb9;P :p>bP p9D;P cp:>P bW9mP bW9m&P bHm9P cW9mP b1W5P :Wb5P b1H5P :cW5P", +" 9WQbmP QmP&bW9 Zb9mP Zc9mP pb9WP :pbWP Zpb9P cpZ:P bPv9 vb9+P 9DvP v9cP b1", +"vP vb:P vb1HP :Pcv vb9QP b+Qv9P Zvb9P cvZ9P pvb9P :vbpP Zvb1P :cyP R R! RB ", +"Ra R. R8 R.B R8a RM RM! RT RTa Rj R8M RTj sR R( R+ R(B R+a R(. R+8 .BR( +8R", +"a RM( R+M RT( R+T Rj( R+j TjR( sR+ RE RE! RH RHa RE. R8E RH. RH8 RME MER! R", +"HT HMRa RjE RE8M RHj sRH Rd R+d RHd gR Rd. R8d HdR. gR8 RdM +MRd RTd gRT Rd", +"j +jRd HjRd gsR R2 R2! R2B Ra2 R5 R58 R5B R5a RM2 M2R! RT2 R2aM R5M 5MR8 R5", +"T sR5 R; R+; R;B Ra; R5; >R 5;RB >Ra R;M +MR; RT; +TR; R;j >MR 5TR; s>R RE2", +" !ER2 RH2 HaR2 R5E 58RE RH5 H5R8 MER2 RME!2 R2HM aM2RH RE5M R58ME H5RT RHs5", +" Rd; +dR; RH; gR; R5d >Rd H5Rd g>R dMR; dM;R+ HMR; RTg; 5dRj Rd>M H;Rj gR>M", +" RP RP! RPB RaP RP. R8P P.RB 8PRa S S! ST Sa Sj S8 STj Ss RP( R+P P(RB +PRa", +" P(R. +PR8 RP(.B R+8aP S( S+ ST( S+T Sj( S+8 TjS( Ss+ RW RW! RHW RWa RW. RW", +"8 R.HP H8RW SW S!W SZ SZa SWj S8W SZj SsZ RWd R+W HPRd gRW R.dP +WR8 dP.RH ", +"RWg8 Sd S+W SZd gS Sdj S8d ZdSj gSs Rm Rm! RmB Ram R5m R8m RB5P 5aRm Sm S!m", +" STm Sam Sp Sp8 SpT Ssp Rm; R+m RB;P +mRa 5PR; >PR ;PBR5 Ra>P S; S+m S;T Sa", +"; Sp; S> pTS; S>s RWm W!Rm RHm HmRa R5W 5WR8 H5RW H8Rm SWm W!Sm SZm ZaSm Sp", +"W pWS8 SZp SZsp vR vR+ vRH gvR vR5 v>R RHv5 gR>P Sv Sv+ SvZ gSv Svp S>v ZpS", +"v yS R# R& R#B Ra& R#. R8& .BR# 8aR& RM# R&M RT# RT& Rj# R&j TjR# sR& R#( R", +"+& #BR( +aR& #(R. +8R& R#(.B R+8a& M#R( +MR& T#R( +TR& j#R( +jR& RTj#( R+s&", +" R#E R&E RH# RH& #ER. 8&RE H#R. H8R& M#RE REM& R#HM HMR& j#RE RE&j R#Hj RHs", +"& Rd# Rd& HdR# gR& d#R. 8dR& RHd#. R8g& R#dM dMR& R#Td RTg& R#dj d&Rj RHjd#", +" g&sR R#2 R&2 2BR# a&R2 R5# R5& 5BR# 5aR& M#R2 R2M& T#R2 R2T& R#5M 5MR& R#5", +"T R5s& R;# R;& ;#RB a;R& 5;R# >R& R5;#B Ra>& R#M; M;R& R#T; T;R& R#;j R&>M ", +"R5T;# >&sR #ER2 &ER2 H#R2 R2H& 5#RE RE5& R#H5 H5R& RM#E2 M&ER2 RHT#2 RH&T2 ", +"R5M#E R5&ME RH5T# sRH5& d;R# d&R; R#H; R;g& R#5d Rd>& RH5d# >&gR dM;R# dM&R", +"; RH;T# gRT;& R5dM# >MRd& RH;j# >MgR& RP# R&P P#RB aPR& P#R. 8PR& RP#.B aP&", +"R8 S# S& ST# Sa& Sj# S8& TjS# Ss& P#R( +PR& RP#(B aP&R+ RP#(. R+8P& P#(R.B ", +"R+8aP& S#( S+& T#S( +TS& j#S( +jS& STj#( s+S& RW# RW& R#HP HPR& W#R. W8R& R", +"HW#. RH8W& SW# S&W SZ# SZ& WjS# W8S& ZjS# S&sZ R#dP +WR& dP#RH RWg& dP#R. d", +"P&R8 RH#dP. gRW8& Sd# Sd& ZdS# gS& djS# 8dS& SZdj# S&gs Rm# Rm& m#RB amR& R", +"#5P 5PR& R5m#B R5am& Sm# S&m TmS# TmS& Sp# Sp& pTS# S&sp R#;P +mR& ;P#RB a;", +"PR& ;P#R5 Rm>& R5#;PB >PRa& S;# S;& T;S# T;S& p;S# S>& SpT;# S&s> WmR# W&Rm", +" R#Hm HmR& R#5W 5WR& RH5W# RH5W& WmS# W&Sm ZmS# SmZ& pWS# SWp& S#Zp ZpS& vR", +"# vR& RHv# v&gR R5v# >Rv& vRH5# >PgR& Sv# Sv& S#Zv S&gv S#pv pvS& SZpv# yS&", +" RU RU! RD RDa RU. R8U RD. RD8 RUM U!RM VR VRa RjU U8Rj VRj sRV RU( R+U RD(", +" R+D U(R. U+R8 D(R. +DR8 UMR( RU+M VR( V+R R(Uj U+Rj RjV( V+sR RUE U!RE RHU", +" UHRa UER. REU8 R.UH UHR8 UMRE RUM!E VRH RHVa REUj R8UME RHVj VRsH RdU U+Rd", +" RDd gRU R.Ud U8Rd R.Dd RDg8 RUdM R+UdM VdR gVR UdRj R+jUd RdVj sRgV RU2 U!", +"R2 RD2 R2Ua R5U U5R8 R5D U5Ra UMR2 RUM!2 V2R RaV2 U5Rj R5U8M V5R V5sR R;U U", +"+R; RD; UaR; U5R; >RU 5DR; >RD RUM; R+UM; V;R R+V; U;Rj Rj>U R5V; V>R UER2 ", +"RUE!2 R2UH RHUa2 REU5 R5U8E UHR5 RH5U8 RUME2 U!MRE2 RHV2 V2RHa R5UME U58RjE", +" RHV5 VsHR5 UdR; R+Ud; UHR; RDg; U5Rd Rd>U 5DRd >RgU dM;RU R+UdM; RHV; V;gR", +" R5dUj >MRUd R5Vd gRV> UP UP! RDP UaP UP. U8P R.DP D8UP SU S!U SV SVa SUj S", +"8U SVj SsV UP( U+P R(DP +DUP P(U. +PU8 RDP(. R+D8P SU( S+U SV( SV+ UjS( U+S", +"8 VjS( VsS+ RWU R!UW RWD UWRa R.UW UWR8 R.WD H8UP SUW UWS! SZV VZSa UWSj UW", +"S8 SjVZ SVsZ UdP U+RW HPUd gUP U.dP 8dUP RWDd. U8gP SdU U+Sd SVd gSV UdSj U", +"8Sd SjVd SsgV RmU R!Um RDm UaRm U5P U8Rm 5DRm 5aUP SUm UmS! SVm VmSa SpU pU", +"S8 VpS VpSs U;P U+Rm DmR; +DRm 5PU; >PU R5D;P RD>P S;U U+S; SV; V+S; pUS; S", +">U S;Vp S>V UWRm RWUm! UHRm RHmUa U5RW R5WU8 H5UP RH8Um UWSm S!UWm VmSZ SZV", +"am SWpU SpUW8 SZVp SZpVs vRU R+vU vRD vRgU R5vU vU>P R5vD gU>P SvU vUS+ VvS", +" VvgS pUSv vUS> VpSv yVS Rb Rb& RbD cR Rb. Rb8 bDR. cR8 RbM bMR& VRb cRV Rb", +"j b8Rj RbVj scR Rb( Rb+ bDR( cR+ b(R. b+R8 RbD(. R+c8 R(bM bMR+ RbV( V+cR R", +"(bj b+Rj VRbj( s+cR RbE REU& RbH cRH bER. REb8 R.bH RHc8 REbM M&ERb RbVH VR", +"cH REbj Rb8ME bHRj sHcR Rbd b+Rd bHRd gcR R.bd b8Rd RbHd. g8cR bMRd dM&Rb R", +"bVd cRgV bdRj d&jRb VdRbj scgR Rb2 R2U& bDR2 cR2 Rb5 b5R8 b5RD cR5 R2bM M&2", +"Rb RbV2 V2cR b5Rj Rb58M RbV5 c5sR Rb; b+R; b;RD cR; b5R; >Rb Rb5D; c>R bMR;", +" M;&Rb RbV; V;cR b;Rj Rb>M V5Rb; sRc> bER2 Rb&E2 R2bH RHc2 REb5 Rb58E bHR5 ", +"RHc5 RbME2 RbEM&2 V2RbH cRVH2 Rb5ME M&ERb5 V5RbH cR5sH bdR; Rb+d; bHR; c;gR", +" b5Rd Rb>d RbH5d gRc> RbdM; RbdM;& VdRb; gVcR; Rb5dM >MbRd V5dRb V>gcR RbP ", +"UP& bPRD cRP R.bP bPR8 RbDP. R8cP Sb Sb& SVb Sc Sbj Sb8 VbSj Scs R(bP bPR+ ", +"RbDP( R+cP RbP(. Rb+8P bP(RD. cR+8P Sb( Sb+ VbS( Sc+ bjS( b+S8 SVbj( S+sc R", +"bW bWR& bHRW cRW R.bW bWR8 RbHW. RWc8 SbW bWS& SZb ScZ bWSj bWS8 SjZb ZcSs ", +"bWRd b+RW RbHdP cRgP RbWd. dP&U8 dP.RbH cRWg8 Sbd b+Sd ZbSd gSc bdSj b8Sd S", +"Zbdj gsSc Rbm bmR& bmRD cRm b5Rm b8Rm Rb5Dm R5cm Sbm bmS& VmSb Scm Spb pbS8", +" SbVp Scp bmR; b+Rm RbmD; R+cm Rb5;P Rb>P b5PRD; cR>P Sb; b+S; V;Sb Sc; pbS", +"; S>b SpbV; Sc> bWRm RbWm& bHRm RHcm b5RW Rb5W8 RbH5W R5cW bWSm SbWm& SmZb ", +"cmSZ SWpb SpbW8 ZpSb SZcp vRb Rbv& RbvD cvR Rbv5 >Rvb vRbH5 v>cR Svb vbS+ S", +"bVv Scv pvSb v>Sb VvpSb ycS Rk Rk! RkB Rak R1 R18 R1B R1a RkM kMR! RTk TkRa", +" lR lR8 lRT lsR Rk( R+k k(RB +kRa R1( R1+ 1(RB 1+Ra kMR( Rk+M R(Tk +kRT lR(", +" l+R RTl( sRl+ RkE kER! RHk HkRa R1E RE8k R1H 1HR8 kMRE RkM!E HkRT RHTak lR", +"E R8lE lHR sRlH Rdk +kRd HkRd gRk R1d 1+Rd 1HRd gR1 RkdM dkMR+ TkRd RTgk ld", +"R R+ld RHld glR Rk2 k2R! k2RB R2ak R15 5kR8 RB5k 1aR5 kMR2 RkM!2 R2Tk ak2RT", +" lR5 R5l8 R5lT l5sR R;k +kR; RBk; akR; R1; >kR RB1; R1>a RkM; k;MR+ TkR; ak", +";RT l;R l>R RTl; sRl> kER2 RkE!2 R2Hk ak2RH RE5k R158E 1HR5 R1H5a RkME2 kME", +"R2! RHTk2 RHTak2 R5lE lR58E RHl5 lsRH5 dkR; dk;R+ HkR; R;gk 1dR5 R1>d 1HR; ", +"gR>k dkMR; R+dk;M RH;Tk gRTk; R5ld >Rld RHl; gRl> kP kP! kPB akP R1P 8kP RB", +"1P 1PRa Sk S!k STk Sak Sl Sl8 SlT Ssl kP( +kP P(kB ak+P R(1P 1PR+ kP(1B akP", +"1+ Sk( S+k TkS( +TSk Sl( l+S STl( l+Ss RWk R!Wk HkP WkRa R1W 1WR8 1HRW 1WRa", +" SWk WkS! SZk ZkSa lWS S8lW lZS lZSs dkP +kRW dkHP gkP 1WRd 1+RW dkP1H R1gP", +" Sdk +WSk ZkSd gSk ldS S+lW SZld glS Rmk R!km RBkm akRm R1m 1mR8 RB1m 1aRm ", +"Skm kmS! TkSm akSm Slp lpS8 lTSp Slsp k;P +kRm kB;P k;aP 1mR; >kP k;P1B ak>", +"P S;k +kS; TkS; akS; l;S S>l lTS; Ssl> WkRm km!RW HkRm akmRH 1WR5 R1W8m 1HR", +"m akPH5 WkSm S!Wkm SmZk SZakm SplW SlpW8 SplZ SZpls vRk R+vk RHvk vRgk vR1 ", +"vR>k R1vH gk>P Svk vkS+ ZkSv gkSv lvS S>lv lZSv ylS R9 R9& R9B R9a R91 :R 9", +"1RB :Ra R9M 9MR& R9T 9TRa lR9 l:R R9lT s:R R9( R9+ 9(RB 9+Ra 91R( :R+ R91(B", +" R+:a R(9M 9MR+ R(9T 9+RT R9l( :Rl+ lR9T( s+:R R9E REk& R9H 9HRa 91RE :RE 9", +"HR1 :RH RE9M k&ERM 9HRT R9HT& R9lE lE:R R9lH :RlH R9d 9+Rd 9HRd gR9 9dR1 :R", +"d R9H1d g:R 9MRd dk&RM 9TRd R9gM R9ld :Rld lHR9d gRl: R92 R2k& 92RB R29a R9", +"5 :R5 RB95 R5:a R29M k&2RM R29T R9T&2 R9l5 l5:R 95RT s5:R R9; 9+R; RB9; 9aR", +"; 95R; :>R R95;B :a>R 9MR; k;&RM 9TR; aM;R9 R9l; :Rl> l;R9T :>sR 9ER2 k&ER2", +" R29H R9H&2 RE95 R5:E 9HR5 RH:5 R9ME2 R9EM&2 R9HT2 aM2R9H lR95E :R5lE lHR95", +" :RHl5 9dR; dk&R; 9HR; R9g; 95Rd >R:d R9H1; :>gR R9dM; R9dM;& R9HT; gR9T; l", +"dR95 l>:Rd lH;R9 g:Rl> R9P kP& RB9P 9PRa 9PR1 :RP kPB91 Ra:P S9 S9& S9T S9a", +" Sl9 S: lTS9 S:s R(9P 9PR+ kP(9B akP9+ kP(91 R+:P 9P(R1B :R+aP S9( S9+ 9TS(", +" 9+Sa l(S9 S:+ Sl9T( S+s: R9W 9WR& 9HRW 9WRa 9WR1 :RW R9H1W RH:W S9W 9WS& S", +"Z9 Z9Sa S9lW S:W S9lZ S:Z 9WRd 9+RW dkP9H R9gP dkP91 R+:W 9HPR1d :RgP S9d 9", +"+Sd Z9Sd gS9 S9ld S:d SZ9ld gS: R9m 9mR& RB9m 9aRm 95Rm :Rm R95mB Ra:m S9m ", +"9mS& 9TSm 9aSm Sp9 S:p STp9 :pSs 9mR; 9+Rm k;P9B ak;9P k;P95 :R>P k;B95P :>", +"Ram S9; 9+S; 9TS; 9aS; S9l; S:> Sp9T; s:S> 9WRm km&RW 9HRm km&RH 95RW R5:W ", +"R9H1m RH:m 9WSm S9Wm& SmZ9 SZ9am SWp9 :WSp ZpS9 SZ:p vR9 R9v& R9vH vRg9 R9v", +"1 :vR vR91H gR:v Sv9 v9S+ ZvS9 g9Sv S9lv S:v Sv9lZ y:S RUk U!Rk RDk DkRa R1", +"U 1UR8 R1D 1URa UkRM RUkM! VRk RaVk lRU R8lU VlR VlsR UkR( RU+k R(Dk +kRD R", +"(1U 1UR+ R(1D 1+RD RUkM( R+UkM RkV( R+Vk RUl( R+lU VRl( lRV+ UkRE RUk!E HkR", +"D RHUak RE1U R1U8E 1URH R1HU8 RUkME U!kRME RHVk VRHak RUlE lRU8E VRlH lsVRH", +" RUdk R+Udk DkRd RDgk 1URd R1+Ud 1DRd R1gU dkMRU R+UdkM RdVk VRgk RdlU l+RU", +"d lRVd VlgR UkR2 RUk!2 R2Dk ak2RD 1UR5 R1U58 1DR5 R1D5a RUkM2 U!kRM2 RkV2 V", +"2Rak R5lU lRU58 lRV5 lsVR5 RUk; R+Uk; DkR; ak;RD 1UR; R1>U 1DR; R1>D k;MRU ", +"R+Uk;M R;Vk V+Rk; R;lU lR>U lRV; >RVl RUkE2 U!kRE2 RHUk2 RHUak2 R1U5E 1U5R8", +"E R1HU5 1UHR5a UkMRE2 !ER2UkM V2RHk ak2VRH lRU5E R5Ul8E VlRH5 Vs5lHR dk;RU ", +"R+Udk; RH;Dk gRUk; R1dU5 >kRUd R1HU; >kgRD RdUk;M dkR;U+M VdRk; gVRk; ldRU5", +" l>RUd lH;VR V>lgR UPk U!kP DkP akUP 1UP U81P 1PRD Ua1P SUk U!Sk SVk VaSk S", +"lU lUS8 SlV SVls U(kP +kUP D(kP Dk+P 1(UP U+1P R1DP( R1+DP UkS( U+Sk VkS( S", +"kV+ SUl( lUS+ l(SV SVl+ WkUP kP!UW HkUP akPUH 1URW R1WU8 1WRD R1WUa UWSk S!", +"UWk ZkSV SZVak SUlW SlUW8 SVlZ SlVsZ dkUP dkPU+ dkDP UPgk Ud1P dkPU8 dkP1D ", +"1UgP UdSk S+UWk SkVd SVgk lUSd S8dlU SVld SlgV kmUP km!UP DkRm akmRD 1URm R", +"1mU8 1DRm akPU5 UmSk S!Ukm SkVm SVakm pUSl SlpU8 SlVp SlVsp k;UP k;PU+ k;DP", +" ak;UP U;1P 1U>P k;P1D Dk>P U;Sk S+Ukm SkV; SV+km lUS; >USl SVl; SlV> RWUkm", +" RWUkm! RHmDk RWDakm R1WU5 1UWR8m R1HUm 1UHR8m SUWkm km!SUW SZVkm ZkVSam Sl", +"pUW lWpS8U SlVZp VplSsZ UPvk vRU+k RDvk gvRDk R1vU >kvUP R1vD >kgUP SUvk Sv", +"U+k vkSV VvgSk vUSl lv>SU SlVv SlyV tR tR& tRD tcR tR1 t:R R1tD :cR tRM R&t", +"M VtR VtcR ltR :Rlt lRVt uR tR( t+R RDt( cRt+ R1t( :Rt+ tR1D( :+cR RMt( R+t", +"M VRt( tRV+ tRl( lRt+ ltVR( uR+ tRE R&tE tHR cRtH R1tE tE:R R1tH :RtH RMtE ", +"tRM&E VRtH tcVRH tRlE t:RlE lRtH uRH tdR R+td RHtd gtR R1td :Rtd tHR1d t:gR", +" RdtM t+RdM tRVd VtgR lRtd t:dlR tdVlR ugR tR2 R&t2 RDt2 c2tR t5R :Rt5 R5tD", +" cRt5 RMt2 tRM&2 tRV2 tcVR2 lRt5 t:Rl5 tRV5 uR5 t;R R+t; RDt; cRt; R1t; t>R", +" t5RD; :Rc> R;tM t+RM; tRV; tc;VR lRt; >Rlt t5VR; u>R REt2 tR&E2 RHt2 tcRH2", +" R5tE t:R5E RHt5 t:HR5 tRME2 M&EtR2 tHVR2 cRVtH2 t5RlE lt5:RE tH5lR RHu5 Rd", +"t; t+Rd; RHt; t;gR R5td >Rtd tH5Rd gRt> tdRM; dM&t;R tH;VR gtVR; t5dlR t>lR", +"d tH;lR g>uR tP tP& tPD tcP tP1 t:P 1DtP :ctP St St& StV Sct Stl S:t SVlt u", +"S tP( t+P DPt( cPt+ 1Pt( :Pt+ tP1D( t:Pc+ St( St+ S(Vt tcS+ l(St l+St SlVt(", +" uS+ tWR RWt& tHP cRtW R1tW :RtW 1HtP :HtP StW tWS& tZS tZSc lWSt tWS: lZSt", +" uZS tdP R+tW HPtd gtP 1dtP :dtP tHP1d t:gP Std t+Sd SdtZ gtS ldSt t:Sd Std", +"lZ ugS tmR Rmt& RDtm cRtm t5P :Rtm 5DtP cR:m Stm tmS& tmSV tmSc tpS tpS: Vp", +"St upS t;P R+tm D;tP c;tP 1;tP t>P t5PD; tc>P St; t+S; t;SV S;tc l;St S>t S", +"t;Vp u>S RWtm tWRm& RHtm tcWRm R5tW t:WR5 H5tP t:HRm SWtm StWm& tmSZ ScZtm ", +"tWSp S:ptW SZtp SZup tvR vRt+ vRtH gRtv vRt5 >Ptv tvR1H >Pgt tvS S+tv StVv ", +"tvgS Stlv tvS: lvVSt yuS )O !)O )BO a)O )O. 8)O )O.B a)8O )OK )O!K T)O a)TO", +" jO) 8)jO T)jO s)O *O +*O *BO a*O *O. 8*O .B*O 8Oa* *OK *O+K T*O +OT* *jO j", +"O8* jOT* s*O E)O E)!O H)O a)HO )OE. E)8O )OH. 8)HO )OEK !E)OK T)HO HTa)O E)", +"jO jO8E) H)jO H)sO d*O d*+O H*O g*O *Od. d*8O *OH. 8*gO *OdK +d*OK HOT* T*g", +"O d*jO dj*+O jOH* gOs* )O2 )O!2 )O2B )Oa2 5)O 8)5O )B5O a)5O )O2K !)2OK )OT", +"2 Ta)O2 5)jO jO58) T)5O 5)sO ;*O ;*+O ;O*B ;*aO 5*O >*O 5O*B a*>O *O;K +;*O", +"K ;*TO a;*TO jO5* *j>O 5OT* >Os* )OE2 !)2EO )OH2 Ha)O2 E)5O 58E)O 5)HO H58)", +"O EK)O2 !)OEK2 HT)O2 Ta)HO2 jO5E) 58EjO) H5T)O sH5)O ;*dO +d;*O ;*HO ;*gO d", +"*5O d*>O HO5* g*>O dK;*O dK;+*O H;T*O gT;*O dj*5O >*djO H5*jO s*Og> P) P)! ", +"P)B aP) P). 8P) .BP) 8)aP QP) P)Q! TP) Q)aP Pj) Q)8P T)Pj sP) P* +P* P*B aP", +"* P*. 8P* P.*B aP8* Q*P Q*+P TP* T*+P P*j 8PQ* PjT* sP* WP) P)W! HP) H)aP P", +")W. W)8P P)H. H)8P QPW) Q!WP) ZP) aPZ) W)Pj Pj)W8 PjZ) ZPs) W*P W*+P HP* gP", +"* W.P* 8PW* H.P* 8Pg* dPQ* +WQP* Z*P Z*gP P*Wj dPj8* P*Zj s*gP mP) P!m) P)m", +"B mPa) 5P) 5)8P P)5B 5)aP mPQ) Q!mP) mPT) amPQ) pP) 8Pp) TPp) pPs) m*P m*+P", +" *B;P m*aP 5P* >P* *B5P aP>* ;PQ* m*P+Q m*TP am*TP p*P p*>P TPp* s*>P mPW) ", +"W!mP) mPH) amPH) WP5) 5W8P) H)5P H5P8) WQmP) WmPQ!) mPZ) ZamP) WPp) pW8P) p", +"PZ) sP)Zp vP* +Pv* HPv* vPg* 5Pv* vP>* 5PH* >*gP Q*vP v+QP* vPZ* ZvPg* vPp*", +" >Ppv* ZPp* y*P ,O ,&O ,OB ,aO ,O. ,8O .B,O 8a,O ,OK &O,K ,TO ,OT& ,jO ,O&j", +" jO,T s,O ,*O -O ,O*B -aO *O,. -8O *B,O. 8a-O *O,K -OK ,OT* -TO ,O*j -jO *j", +"O,T s-O ,EO &E,O ,HO ,OH& EO,. 8E,O HO,. ,OH8 EK,O ,&EOK HT,O ,HTaO jO,E &j", +"E,O ,OHj ,HsO ,dO -dO ,OH* g-O dO,. 8d-O ,HdO. -8gO dK,O dK-O ,OTd gO-T ,Od", +"j dj-O ,HjdO gOs- ,O2 &O,2 2B,O aO,2 ,5O ,O5& 5B,O ,O5a 2K,O ,&O2K TO,2 ,Ta", +"O2 jO,5 &jO,5 ,O5T ,5sO ,;O -;O ;O,B a;-O ,O5* ->O ,5;OB -a>O ;O,K ;O-K ,OT", +"; T;-O ,O;j >O-j ,5T;O >Os- EO,2 ,&EO2 HO,2 ,HaO2 5E,O ,58EO ,OH5 ,H58O ,EO", +"2K &EO,2K ,HTO2 H&O,T2 ,5jEO ,5E&jO ,H5jO s,H5O d;,O d;-O ,OH; -;gO ,O5d -d", +">O ,H5dO >Og- ,d;OK -d;OK ,H;TO -T;gO ,5djO ->djO ,H;jO s-g>O ,P ,P& ,PB ,a", +"P ,P. ,8P P.,B 8P,a ,QP Q&,P ,TP Qa,P ,Pj Q8,P TP,j sP, ,P* -P *B,P -Pa ,.P", +"* -P8 P*.,B 8P-a Q*,P -QP T*,P -TP P*,j -Pj P*j,T s-P ,WP W&,P ,HP HP,a WP,", +". W8,P ,.HP H8,P WQ,P ,WQP& Z,P ,aZP Wj,P P&j,W ,PZj Z,sP ,dP -WP HP,d g-P ", +",.dP W8-P ,HPd. g8-P Qd,P Qd-P ,dZP Z-P dP,j Wj-P Z*P,j gPs- ,mP m&,P mP,B ", +"am,P ,5P 5P,8 ,B5P 5a,P Qm,P m&P,Q Tm,P ,QamP p,P ,8pP ,TpP p,sP ,;P -mP ,B", +";P am-P 5P,; >P- ,5P*B -a>P Q;,P Q;-P T;,P Tm-P ,;pP -pP p*T,P >Ps- Wm,P m&", +"P,W Hm,P ,HmaP 5W,P ,5W8P H5,P ,H58P ,WQmP ,WQm&P ,mZP Z&m,P ,WpP p&W,P ZPp", +", sP,Zp v,P -vP ,HvP gP-v ,5vP >P-v v,H5P g->P ,QvP vQ-P ZPv, -PZv pPv, pv-", +"P Zp*,P y-P C)O C)!O D)O a)DO )OC. C)8O )OD. 8)DO )OCK !CO)K T)DO DTa)O C)j", +"O jO8C) D)jO D)sO *CO *C+O D*O +OD* CO*. *C8O *OD. DO8* CK*O +*COK DOT* a*O", +"DT *CjO *jC+O jOD* D*sO E)CO CE)!O D)HO HDa)O C).EO 8CE)O HD)O. H8D)O CE)OK", +" EK)!CO HDT)O DTaH)O jOCE) 8CEjO) HjD)O sHD)O *CdO +d*CO HOD* D*gO d*CO. 8d", +"*CO H*DO. gD8*O dK*CO dK*+CO H*DTO gDT*O dj*CO 8dC*jO H*jDO s*DgO )OC2 !)2C", +"O )OD2 Da)O2 C)5O 58C)O D)5O 5D8)O 2KC)O CKO!)2 DT)O2 Ta)DO2 jO5C) 58CjO) 5", +"DT)O s5D)O *C;O +;*CO ;*DO a;*DO *C5O *C>O 5OD* D*>O ;*COK ;*C+OK D;T*O D;T", +"a*O ;jC*O >*jCO 5D*jO >D*sO CE)O2 !O2CE) HD)O2 Da)HO2 5CE)O 8CE5)O H5D)O 5D", +")H8O C)OEK2 C)!OEK2 DT)HO2 DTH)aO2 5CEjO) 5)jO8CE 5D)HjO H5Ds)O d;*CO d;*+C", +"O H;D*O gD;*O 5d*CO >*dCO H5*DO >D*gO ;*CdKO dK+*;CO D;TH*O D;Tg*O 5dC*jO d", +"j*>CO djO5D* gs*>DO PC) !CP) DP) D)aP C)P. PC8) P)D. D)8P PCQ) Q!PC) Q)DP a", +"P)QD jCP) PjC8) D)Pj DPs) P*C +CP* DP* D*+P *CP. 8CP* D.P* 8PD* QCP* P*C+Q ", +"DPQ* aP*QD PC*j P*j+C P*Dj DPs* PCW) W!PC) H)DP aP)WD WPC). W8PC) HPD). H8P", +"D) WQPC) WPCQ!) DPZ) ZDaP) PjCW) W8CPj) ZDPj) sPDZ) WCP* dPC+* DPH* DPg* dP", +"C*. W8*PC HP*D. gPD8* dPCQ* +WQP*C DPZ* Z*DgP dPj*C dPCQ8* Z*DPj sP*gD PCm)", +" mPC!) mPD) amPD) PC5) 5P8C) 5)DP 5DP8) QmPC) mPCQ!) QDmP) QDmaP) PCp) p8PC", +") DPp) sPDp) mCP* m*P+C m*DP am*DP 5CP* P*>C DP5* DP>* m*PQC +QmP*C QD;P* Q", +"D;aP* P*pC >Pp*C DPp* sP*pD WmPC) mPCW!) HmDP) HmDaP) 5WPC) W8C5P) H5PD) aP", +")5WD QmPWC) W)Q!mPC ZDmP) amPZD) pWPC) W8PpC) ZpDP) ZpDsP) P*vC v+P*C DPv* ", +"gvDP* v5P*C >Pv*C vD5P* >PgD* vQP*C P*Cv+Q ZvDP* gvDZ*P pvP*C pv*>PC Zp*DP ", +"DPy* ,bO b&,O ,DO c,O bO,. ,Ob8 DO,. ,8cO bK,O ,b&OK ,ObT ,TcO ,Obj &jO,b ,", +"ODj c,sO b*O -bO ,OD* c-O *Ob. b8-O ,D*O. -8cO *ObK bK-O bOT* cO-T jOb* bj-", +"O ,Dj*O sOc- bE,O ,b&EO ,ObH ,HcO ,bEO. ,8bEO ,HbO. cH8,O ,bEOK bK&,EO ,HbT", +"O cHT,O ,jbEO b8E,jO ,HjbO s,HcO ,Obd bd-O ,ODd gOc- ,dbO. -b8dO ,DdO. c-8g", +"O ,dbOK -bdOK ,DdTO c-TgO ,djbO -jbdO ,DdjO s-gcO bO,2 ,b&O2 DO,2 ,Oc2 ,Ob5", +" ,5b8O ,O5D ,5cO ,bO2K bK&,O2 ,DTO2 c2T,O ,5bjO ,5b&jO ,5DjO s,5cO ,Ob; b;-", +"O ,OD; -;cO bO5* -b>O ,5D;O >Oc- ,;bOK -b;OK ,D;TO c-T;O ,;jbO ->bjO ,D;jO ", +"s-c>O ,bEO2 b&E,O2 ,HbO2 c2H,O ,5bEO b5E,8O ,H5bO c5H,O bKE,O2 EO,2bK& bHO,", +"T2 ,HTc2O b5E,jO 5jbE,8O ,HOb5T c5Hs,O ,db;O -bd;O ,H;bO c-;gO ,5dbO ->bdO ", +",5DdO c>g-O bdO,;K bd;-OK ,HObT; -T;gcO djOb5* >bd-jO djO,5D c>gs-O ,Pb ,bP", +"& ,DP cP, ,.bP b8,P ,.DP ,8cP bQ,P ,QbP& bT,P ,QcP bP,j P&j,b DP,j cPs, bP*", +" -Pb DPb* c-P b.P* b8-P ,DP*. c8-P Q*bP bQ-P TPb* -QcP P*bj bP-j P*j,D c-sP", +" bW,P ,WbP& bH,P ,HcP ,WbP. ,W8bP ,HPb. cW8,P ,WbQP bWQ,P& ,DZP cPZ, ,WjbP ", +"bW8,Pj ZbP,j sP,Zc bd,P bW-P HPb* c-gP ,dPb. -Wb8P ,DdP. c-W8P ,QdbP -WbQP ", +"bPZ* cPZ- dPjb* -WjbP Zb*Pj s-PZc bm,P m&P,b Dm,P ,mcP b5,P ,5Pb8 5D,P ,5cP", +" ,QbmP ,Qbm&P ,QDmP cQm,P ,Ppb pb8,P ,DpP p,cP b;,P bm-P D;,P -mcP 5Pb* >b-", +"P ,5D;P c->P ,Q;bP -Qb;P ,QD;P c-Q;P bPp* pb-P pb*DP cP-p ,WbmP ,Wbm&P ,Hmb", +"P cWm,P ,5WbP b5W,8P ,H5bP c5W,P bWQ,mP QmP&,Wb Zbm,P ZcP,m pbW,P ,W8pbP Zp", +"b,P cpZ,P ,Pvb vb-P ,DvP cP-v vb5,P -v>bP vD,5P cv->P vbQ,P -vbQP Zvb,P cvZ", +"-P pvb,P -pvbP ZpbP* c-yP 0)O 0)!O 0)OB 0)aO 1)O 8)1O )B1O a)1O )O0K !K0)O ", +"0)TO Ta0)O 1)jO jO18) T)1O 1)sO *0O *0+O 0B*O *0aO 1*O 1O8* 1O*B 1Oa* 0O*K ", +"+*0OK *0TO a*0TO jO1* *jO1+ 1OT* 1*sO 0)EO !E)0O 0)HO Ha0)O E)1O 18E)O H)1O", +" 1H8)O EK0)O !0OEK) HT0)O Ta0H)O jO1E) 18EjO) 1HT)O s1H)O *0dO +d*0O *0HO *", +"0gO d*1O 1+d*O 1OH* 1*gO dK*0O dK*+0O H*T0O gT*0O dj*1O 1+d*jO 1H*jO s*1gO ", +")O02 0)2!O 0)2OB a0)O2 5)1O 158)O 15)OB 1a5)O 0)2OK !)O2K0 T0)O2 a0)TO2 jO1", +"5) 158jO) 1T5)O s15)O *0;O +;*0O *B;0O a;*0O 1O5* 1*>O 1;*OB >*1aO ;*0OK ;*", +"0+OK T;*0O T;0a*O ;jO1* >*1jO 1T;*O s*1>O 0)2EO !EO0)2 H0)O2 a0)HO2 15E)O 5", +"8E1)O 1H5)O H5)1aO E)O2K0 0)EO2K! T0)HO2 0)HOTa2 15EjO) 5)jO18E H5)1TO 1H5s", +")O d;*0O d;*+0O H;*0O g;*0O 1d5*O >*1dO 1H;*O g>1*O ;*0dKO dK+*;0O T;0H*O T", +";*g0O 1d5*jO dj*>O1 ;jO1H* g>1s*O P0) !0P) )BP0 P0a) 1P) 1)8P P)1B 1)aP P0Q", +") Q!P0) P0T) aP0Q) 1)Pj Pj)18 1)TP 1Ps) P*0 +0P* P0*B a0P* 1P* +P1* *B1P aP", +"1* Q0P* P*0+Q T0P* aP*Q0 Q*1P P*j1+ TP1* 1Ps* P0W) W!P0) P0H) aP0H) WP1) 1W", +"8P) 1)HP 1HP8) WQP0) WP0Q!) P0Z) ZaP0) Pj)1W 1W8Pj) 1PZ) sP1Z) W0P* dP0+* H", +"0P* P*g0 W*1P 1+WP* HP1* 1Pg* dP0Q* +WQP*0 P*Z0 Z*Pg0 dPj1* 1+WP*j 1PZ* sP*", +"g1 P0m) mP0!) mP0)B amP0) 1)5P 1m8P) 1mP)B 1amP) QmP0) mP0Q!) TmP0) Tm0aP) ", +"1Pp) p18P) p1TP) sP1p) m0P* m*P+0 m*P0B am*P0 5P1* 1P>* 1m*PB >P1a* m*PQ0 +", +"QmP*0 Tm*P0 am0TP* 1Pp* >Pp1* p*1TP sP*p1 WmP0) mP0W!) HmP0) Hm0aP) 1W5P) 5", +"W81P) 1HmP) am)1HP QmPW0) P!m0WQ) ZmP0) amPZ0) p1WP) 1W8pP) Zp1P) Zp1sP) P*", +"v0 v+P*0 vHP*0 gvP*0 1Pv* >Pv1* v1HP* >Pg1* vQP*0 P*0v+Q ZvP*0 gvPZ*0 pv1P*", +" pv1>P* Zp*1P 1Py* ,9O 9&,O 9O,B ,O9a ,1O :,O 1O,B ,a:O 9O,K ,9&OK ,O9T ,T9", +"aO ,O9j ,j:O ,O1T :,sO 9*O -9O 9O*B 9a-O ,O1* :-O ,1*OB -a:O *O9K 9O-K 9OT*", +" 9T-O jO9* :O-j ,1T*O sO:- 9E,O ,9&EO ,O9H ,H9aO 1E,O ,E:O ,O1H ,H:O ,9EOK ", +"9&E,OK ,H9TO 9HT,aO ,1jEO :j,EO ,1HjO s,H:O ,O9d 9d-O 9OH* -9gO ,O1d -d:O ,", +"1HdO gO:- ,d9OK -9dOK ,Td9O -T9gO ,1djO :-djO ,1TdO g:s-O 9O,2 ,9&O2 ,9O2B ", +",a9O2 ,O95 ,5:O ,15OB :5a,O ,9O2K 9&O,2K ,T9O2 9TO,a2 ,15jO :5j,O ,1T5O s,5", +":O ,O9; 9;-O ,;9OB -9a;O ,O1; >O:- ,1;OB :->aO ,;9OK -9;OK ,T;9O -T9;O ,1;j", +"O :->jO ,1T;O s-:>O ,9EO2 9&E,O2 ,H9O2 9HO,a2 ,15EO :5,EO ,1H5O :H5,O 9EO,2", +"K EO,29&K 9HO,T2 HO,29Ta 95E,jO ,5j:EO ,HO95T :H5s,O ,d9;O -9d;O ,H;9O g-9;", +"O ,1d5O :->dO ,1H;O g:->O 9dO,;K 9d;-OK ,HO9T; g9;-TO djO,1; ->j:dO ;jO,1H ", +"s->g:O ,P9 ,9P& ,B9P 9a,P ,1P :P, ,B1P ,a:P 9Q,P ,Q9P& 9T,P ,Qa9P 9P,j ,Q:P", +" 1T,P :Ps, 9P* -P9 *B9P 9a-P 1P9* :-P ,1P*B :a-P Q*9P 9Q-P TP9* 9T-P P*9j -", +"Q:P P*j9T :-sP 9W,P ,W9P& 9H,P ,HP9a 1W,P ,W:P 1H,P ,H:P ,W9QP 9WQ,P& ,PZ9 ", +"Z9a,P ,1WPj :WQ,P ,1ZP :PZ, 9d,P 9W-P HP9* -Pg9 1d,P -W:P ,1HdP :-gP ,Qd9P ", +"-W9QP 9PZ* -PZ9 dPj,1 :-WPj Z9*1P :PZ- 9m,P m&P,9 ,m9PB ,am9P 95,P ,5:P ,1m", +"PB :ma,P ,Q9mP ,Q9m&P ,Tm9P 9Tm,aP ,1pP p,:P p9T,P sP,:p 9;,P 9m-P ,;P9B -m", +"9aP 1;,P :->P ,1;PB :-maP ,Q;9P -Q9;P ,T;9P -Tm9P 9Pp* :P-p p9*TP -ps:P ,W9", +"mP ,W9m&P ,Hm9P 9Hm,aP ,1W5P :W5,P ,1H5P :Hm,P 9WQ,mP QmP&,W9 Z9m,P ,amZ9P ", +"p9W,P :pW,P Zp9,P Z:p,P ,Pv9 v9-P v9H,P -vg9P ,1vP :P-v v1,HP :v-gP v9Q,P -", +"v9QP Zv9,P Z-v9P pv9,P :v-pP Zp9P* :-yP 0)CO C0)!O 0)DO Da0)O C)1O 18C)O D)", +"1O 1D8)O C0)OK !K)C0O DT0)O Ta0D)O jO1C) 18CjO) 1DT)O s1D)O C0*O +*C0O *0DO", +" a*0DO *C1O 1+*CO 1OD* 1+D*O *C0OK *C0+OK D*T0O D*0+TO *jC1O 1+C*jO 1D*jO s", +"*1DO C0)EO !E)C0O HD0)O Da0H)O 1CE)O 8CE1)O 1HD)O H8)1DO EK)C0O 0)EOCK! DT0", +"H)O 0)HODTa 1CEjO) C)8O1jE Hj)1DO 1HDs)O d*C0O d*C+0O H*D0O gD*0O 1d*CO 8dC", +"1*O 1H*DO g1D*O *C0dKO C0dO+*K Td0D*O D*Tg0O 1dC*jO dj1*+CO djO1D* g1Ds*O C", +"02)O !)2C0O D0)O2 a0)DO2 15C)O 58C1)O 1D5)O 5D)1aO CKO0)2 0)C2!KO T0)DO2 0)", +"TODa2 15CjO) 5)jO18C 5D)1TO 1D5s)O ;*C0O ;*C+0O D;*0O D;0a*O 1;*CO >*1CO 1D", +";*O >D*1O *C0;OK C0;O+*K T;0D*O a;D*T0O 1;C*jO *jC>O1 ;jO1D* s*1>DO CEO0)2 ", +"0)C2!EO D0)HO2 0)HODa2 5CE1)O 5E1O8C) H5)1DO 5OD81H) 0)C2EKO C)!OE02K 0)HOD", +"T2 DaHO0)T2 5)jO1CE 5j1EC)8O H)Dj15O 15s)HDO ;*Cd0O C0;O+d* D;0H*O D;*g0O 5", +"dC1*O 1d*>CO 1HO5D* g1*>DO C0;OdK* dK+*C0;O T;H*D0O D*g0T;O dj1;*CO dj>*1CO", +" jOH;1D* >Dgs1*O C0P) PC0!) P0D) aP0D) PC1) 1P8C) 1)DP 1DP8) QPC0) PC0Q!) Q", +"DP0) QD0aP) PjC1) Q8C1P) 1QDP) sP1D) *CP0 P*C+0 D0P* aP*D0 1CP* 1+P*C DP1* ", +"aP*1D P*CQ0 +QCP*0 QD*P0 aP0QD* P*j1C P*C1+Q P*j1D sP*1D WPC0) PC0W!) HPD0)", +" WD0aP) 1WPC) W8C1P) 1HPD) aP)1WD QPCW0) QCW0P)! ZDP0) aP0ZD) 1WCPj) QC8P1W", +") Z1DP) Z1DsP) dPC*0 +WCP*0 HP*D0 gPD*0 1W*PC P*C1+W 1HPD* g1PD* QdCP*0 QCd", +"P+*0 Z*DP0 gPDZ*0 dPC1Q* WC*j1+P Z1*DP sPDZ1* mPC0) PC0m)! DmP0) Dm0aP) 1mP", +"C) 8mC1P) 1DmP) am)1DP mPCQ0) P!m0QC) Tm0DP) amDPQ0) p1PC) 1P8pC) pD1P) pD1", +"sP) m*PC0 +mCP*0 Dm*P0 am0DP* 1m*PC >P1*C 1DmP* >PD1* Q;CP*0 QCm*+P0 ;P0QD*", +" m*DP+Q0 p*1PC p*1>PC pD*1P sP1pD* mPCW0) P!m0WC) Dm0HP) amHPD0) 5WC1P) W)8", +"P1mC 1H)5DP H)8m1DP QCW0mP) !Cm)QPW0 DmPZ0) amZPD0) 1WPpC) 18pCWP) pDPZ1) s", +"1pDZP) vP*C0 P*Cv+0 vDP*0 gP*vD0 v1P*C v1*>PC v1DP* >D*g1P P*CvQ0 P*vC+Q0 v", +"DPZ*0 gDZ*vP0 v1Pp*C >*v1pPC Z1PpD* y*1DP b9,O ,b9&O ,O9D ,9cO ,Ob1 ,b:O ,O", +"1D c,:O ,b9OK b9&,OK ,D9TO c9T,O ,1bjO :bj,O ,1DjO s,O:c bO9* b9-O 9OD* -9c", +"O bO1* -b:O ,1D*O :Oc- b*9OK -b9OK bT*9O c-9TO b1*jO :-bjO b1T*O s-:cO ,b9E", +"O b9&,EO ,H9bO c9H,O ,1bEO :b,EO ,1HbO :cH,O b9E,OK b9,&EKO bH9,TO ,H9cTO b", +"1E,jO ,jb:EO ,1ObHj :cHs,O ,db9O -b9dO ,Dd9O c-9gO ,1dbO :-bdO ,1DdO g:c-O ", +"9dOb*K bd9-OK ,DO9Td -T9gcO djOb1* -jb:dO djO,1D s-cg:O ,b9O2 b9&,O2 ,D9O2 ", +"c29,O ,1b5O :b5,O ,1D5O :c5,O b9O,2K bO,29&K 9DO,T2 ,T9c2O b15,jO ,5b:jO ,1", +"Ob5T :c5s,O ,;b9O -b9;O ,D;9O c-9;O ,1;bO :->bO ,1D;O c>:-O 9;Ob*K b;9-OK ,", +"DO9T; -T9c;O ;jOb1* -jb:>O ;jO,1D c>:s-O b9E,O2 EO,2b9& 9HO,D2 ,H9c2O b1E,5", +"O ,5b:EO ,1ObH5 c5,:HO EO,2b9K 9&,KEOb2 HO,2bT9 ,9c2HTO 5E9O,jb ,b:EjO5 ,O1", +"Hb5T sHc5:,O bd9,;O bd9-;O ,HO9D; g-9c;O ,1Ob5d ->b:dO ,1ObH; c>-g:O ,Obd9;", +"K b9-OdK; ,OH;bT9 gTc;-9O ,O1db;j >j:d-bO 1H,;bTO >Og:s-c ,b9P ,P9b& 9D,P ,", +"Pc9 b1,P ,P:b 1D,P :,cP ,Qb9P bQ9,P& ,QD9P cQ9,P ,1QbP :Qb,P ,1QDP sP,:c 9P", +"b* bP-9 DP9* c9-P 1Pb* :b-P ,1DP* c-:P bQ*9P -Qb9P bTP9* c-Q9P P*jb1 :-QbP ", +"P*j9D s-P:c ,Wb9P bW9,P& ,HP9D cW9,P ,1WbP :Wb,P ,1HbP :cW,P bW9,QP WQP&,b9", +" Zb9,P Zc9,P b1W,Pj ,Wj:Pb Zb1,P Z:c,P ,dPb9 -Wb9P ,Dd9P c-W9P ,1dbP :-WbP ", +",1DdP g:Pc- 9QdbP* bQd-P9 Zb*9P Z-c9P b1WP*j :Wb-Pj Zb1P* Z:-cP ,mb9P bm9,P", +"& ,Dm9P cm9,P ,1mbP :mb,P ,1D5P :cm,P bQ9,mP QmP&,b9 9Dm,TP ,TmcP9 pb9,P :p", +"b,P p9D,P cp:,P ,;Pb9 -mb9P ,D;9P c-m9P ,1;bP :-mbP ,1D;P c>P:- 9Q;bP* bQ;-", +"P9 9QD,;P cm9-TP pb*9P -p:bP p9DP* cp-:P bW9,mP WmbP,9& 9Hm,DP ,HmcP9 b1W,5", +"P ,5W:Pb b1H,5P :H,c5P QmbP,W9 ,bP&WQ9m ,DmZ9P cm9Z,P ,1WpbP pbW:P, Z9PpD, ", +"Z:Pcp, vb9,P -vb9P v9D,P cv-9P vb1,P :v-bP v1D,P :vc-P bQ*v9P vb9-QP Z9PvD,", +" Z-9cvP pbPv1, -pb:vP ZbPp9* y:c-P R) R)! R)B Ra) R). R8) .BR) 8aR) RM) M)R", +"! RT) R)aM Rj) R)8M TjR) sR) R* R+* R*B Ra* R*. R8* R.*B 8*Ra R*M +MR* RT* ", +"+TR* R*j +jR* T*Rj sR* RE) !ER) RH) HaR) E)R. 8ER) H)R. R)H8 MER) RME!) R)H", +"M aM)RH jER) R8ME) R)Hj RHs) Rd* +dR* RH* gR* d*R. 8dR* R.H* R8g* dMR* dM*R", +"+ HMR* RTg* djR* R+jd* H*Rj s*gR R)2 !)R2 2BR) a)R2 R5) 58R) 5BR) R)5a M)R2", +" RM)!2 T)R2 aM)R2 R)5M R58M) R)5T R5s) R;* +;R* *BR; a;R* R5* >R* *BR5 Ra>*", +" M;R* M;*R+ T;R* aM;R* 5MR* R*>M 5TR* >Rs* E)R2 RE)!2 H)R2 RHa)2 5ER) R58E)", +" R)H5 RH58) RME)2 ME)R2! RHT)2 RH)aM2 R5ME) 5MER8) RH5T) sRH5) d;R* R+d;* H", +";R* R;g* 5dR* Rd>* H5R* >*gR dM;R* R+dM;* RH;T* gRT;* R5dM* >MRd* RH5T* >Mg", +"R* RP) P)R! P)RB R)aP P)R. R)8P RP).B aP)R8 S) S!) ST) Sa) Sj) S8) TjS) Ss)", +" R*P +PR* RP*B aPR* R.P* 8PR* P*.RB aP*R8 S* S+* S*T Sa* S*j S8* T*Sj Ss* R", +"W) W!R) R)HP R)Wa W)R. R)W8 RHW). RH8W) SW) W!S) SZ) ZaS) WjS) W8S) ZjS) s)", +"SZ RW* +WR* HPR* RWg* R.W* W8R* RH*W. gRW8* Sd* +WS* SZ* gS* W*Sj W8S* SjZ*", +" s*gS Rm) m)R! m)RB R)am R)5P R)8m R5m)B R5am) Sm) m)S! TmS) amS) Sp) p8S) ", +"pTS) s)Sp Rm* +mR* *BRm amR* 5PR* Rm>* R5*mB >PRa* S;* +mS* TmS* amS* Sp* S", +">* STp* s*S> WmR) RWm!) R)Hm RHma) R)5W R5W8) RH5W) RH8m) WmS) S!Wm) ZmS) S", +"Zam) pWS) SpW8) S)Zp SZps) vR* R+v* RHv* g*vR R5v* >*vR vRH5* >PgR* Sv* v+S", +"* ZvS* S*gv pvS* v>S* ZpS* yS* ,R ,R& ,RB ,Ra ,R. ,R8 RB,. R8,a ,RM R&,M ,R", +"T RT,a ,Rj R8,M RT,j sR, ,R* -R *B,R -Ra ,.R* -R8 ,R*.B R8-a R*,M -RM R*,T ", +"-RT R*,j -Rj ,RT*j s-R ,RE ,ER& ,RH RH,a RE,. ,ER8 ,.RH RH,8 RM,E M&E,R RH,", +"T ,RHT& ,ERj ,R8ME RH,j ,RsH ,Rd -Rd RH,d g-R ,.Rd R8-d ,RHd. g8-R Rd,M Rd-", +"M RT,d -RgM Rd,j Rd-j ,RHdj gRs- ,R2 ,2R& RB,2 ,2Ra ,R5 R5,8 RB,5 R5,a RM,2", +" M&2,R ,2RT ,RT&2 R5,M ,R58M R5,T ,Rs5 ,R; -R; RB,; Ra-; R5,; ->R ,R5*B -a>", +"R R;,M R;-M RT,; RT-; R;,j -R>M ,R5T; ->sR RE,2 ,R&E2 ,2RH ,RH&2 ,ER5 ,R58E", +" RH,5 ,RH5a ,RME2 ,REM&2 ,RHT2 aM2,RH ,R5ME M&E,R5 ,RH5T sR,H5 Rd,; Rd-; RH", +",; g;-R R5,d -d>R ,RH5d ->gR ,RdM; -RdM; ,RHT; -RTg; ,R5dM >M-Rd ,RH;j s-Rg", +"> ,RP R&,P RB,P Ra,P RP,. R8,P ,RP.B ,R8aP S, S&, S,T Sa, S,j S8, ,TSj Ss, ", +"R*,P -RP P*B,R Ra-P P*.,R R8-P ,R.P*B -R8aP S*, S- ,TS* S-T ,jS* S-8 S*T,j ", +"S-s ,RW R&,W RH,W RW,a ,.RW RW,8 ,RHW. ,RHW8 S,W ,WS& SZ, Z&S, ,WSj ,WS8 Sj", +"Z, s,SZ RW,d -RW ,RHW* -RgP ,RWd. RW-8 dP.,RH -RWg8 Sd, S-W Z*S, gS- ,dSj -", +"WS8 SZ*,j s-gS ,Rm R&,m RB,m Ra,m R5,m R8,m ,R5mB ,R5am S,m ,mS& ,TSm ,aSm ", +"Sp, p&S, STp, s,Sp Rm,; -Rm ,Rm*B Ra-m ,R5m* -R>P m*B,R5 >P-Ra S;, S-m ,TS;", +" -TS; p*S, S-p Sp*,T s-S> RW,m ,RWm& RH,m ,RHam R5,W ,R5W8 ,RH5W ,RH8m ,WSm", +" S&W,m SmZ, SZ&,m SWp, Sp&,W ZpS, Ss,Zp vR, -vR ,RvH gR-v ,Rv5 v>-R vR,H5 -", +"vRg> Sv, S-v ZvS, SvZ- pvS, Sv-p Sv,Zp y-S RU) U!R) RD) R)Ua U)R. R)U8 D)R.", +" R)D8 UMR) RUM!) VR) RaV) R)Uj R8UM) RjV) VRs) R*U U+R* RD* UaR* R.U* U8R* ", +"R.D* D8R* RUM* R+UM* V*R R+V* U*Rj R+jU* R*Vj V*sR UER) RUE!) R)UH RHUa) RU", +"E). R8UE) RHU). RH8U) RUME) U!MRE) RHV) VRHa) RjUE) U8ERj) VRHj) VsHR) UdR*", +" R+Ud* UHR* RDg* RdU*. R8dU* RH*U. gRU8* dM*RU R+UdM* RHV* V*gR RdjU* U8dR*", +"j VdR*j s*VgR U)R2 RU)!2 D)R2 RDa)2 R)U5 R5U8) R)5D R5D8) RUM)2 U!MR)2 R)V2", +" V2Ra) R5UM) U58Rj) R5V) Vs5R) U;R* R+U;* D;R* R+D;* U5R* R*>U 5DR* RD>* M;", +"*RU R+UM;* R;V* V+R;* R5*Uj >MRU* R5V* >RV* RUE)2 U!ER)2 RHU)2 UH)Ra2 R5UE)", +" U5ER8) RH5U) RH)U5a UMER)2 !ER)UM2 V2RH) RHaV2) U5ERj) REU85M) V5RH) sRHV5", +") RdU;* U+dR;* RH;U* gRU;* R5dU* >RUd* RH5U* g>RU* RdUM;* dMR;U+* VdR;* gVR", +";* U5dR*j Rdj>U* V5dR* V>gR* UP) P)U! R)DP U)aP P)U. U)8P RDP). RD8P) SU) U", +"!S) SV) VaS) UjS) U8S) VjS) s)SV UP* +PU* DPR* aPU* U.P* 8PU* RD*P. aP*U8 S", +"*U U+S* SV* V+S* U*Sj U8S* SjV* s*SV R)UW RWU!) R)WD RWDa) RWU). RW8U) RWD)", +". RWD8) UWS) S!UW) S)VZ SZVa) SUWj) S8UW) SZVj) SsZV) UWR* R+WU* HPU* UPg* ", +"RW*U. RW8U* RWD*. gUP8* UWS* S+UW* Z*SV S*gV SdU*j S8dU* SZ*Vj Ss*gV R)Um R", +"mU!) R)Dm RDma) U)5P R8mU) R5Dm) RD8m) UmS) S!Um) S)Vm SVam) S)pU SpU8) S)V", +"p SspV) UmR* R+mU* DmR* am*RD 5PU* UP>* R5Dm* >PUD* UmS* S+Um* VmS* SV+m* p", +"US* >US* S*Vp S*V> RWUm) UW)Rm! RHmU) am)RWD R5WU) R5)UW8 R5WD) aP)UH5 SUWm", +") UWmS!) SZVm) VZmSa) SpUW) pUWS8) SZpV) VpZSs) R*vU vRU+* RDv* gvRU* vRU5*", +" >PUv* vRD5* >PgU* vUS* SvU+* S*Vv VvgS* Sp*vU S>vU* VvpS* SVy* ,Rb R&,U ,R", +"D cR, ,.Rb Rb,8 ,.RD ,Rc8 Rb,M ,RbM& V,R V,cR Rb,j ,R8bM ,RVj cRs, Rb* -Rb ", +"R*,D c-R R.b* Rb-8 ,RD*. c8-R bMR* Rb-M ,RV* V-R b*Rj Rb-j V*R,j sRV- ,ERb ", +",Rb&E Rb,H ,RcH ,RbE. ,R8bE ,RHb. cRH,8 ,RbME ,RbM&E ,RVH cRV,H ,RjbE ,Rb&j", +"E V,RHj s,VRH Rb,d Rb-d RD,d c-gR ,Rdb. -Rb8d ,RDd. c-Rg8 ,RdbM -RbdM ,RVd ", +"gRV- ,Rdbj -Rjbd Vd,Rj V-gsR ,2Rb ,Rb&2 ,2RD ,Rc2 Rb,5 ,R5b8 R5,D ,Rc5 ,RbM", +"2 ,RbM&2 ,RV2 cRV,2 ,R5bM Rb5,8M ,RV5 s,VR5 Rb,; Rb-; RD,; -Rc; b5R* >R-U ,", +"R5D; ->cR ,R;bM -RbM; ,RV; V;-R ,R;bj >M-Rb V5*,R -RV> ,RbE2 R&E,U2 ,RHb2 c", +"RH,2 ,R5bE ,REU5& ,RHb5 cR5,H RbE,M2 bER2,M& V,RH2 V,HcR2 ,REb5M ,ER5b8M V5", +",RH s,HcR5 ,Rdb; -Rbd; ,RHb; c-Rg; ,R5bd ->Rbd ,R5Dd c>Rg- Rbd,M; Rbd-M; Vd", +",R; V-gR; Rb5,dM -Rb>Md V5d,R V->gR ,UP U&,P RD,P ,RcP ,.UP U8,P ,RDP. cR8,", +"P Sb, ,US& SV, Sc, ,USj ,US8 SjV, s,Sc bPR* -UP ,RDP* -RcP ,UP*. U8-P P*.,R", +"D c-R8P Sb* S-b V*Sb Sc- b*Sj -US8 SV*,j s-Sc Rb,W ,RWU& RW,D ,RcW ,RWb. ,R", +"Wb8 ,RWD. cRW,8 ,USW SbW,& ZbS, S,Zc SbW,j Sb8,W SZb,j Ss,Zc bWR* Rb-W ,RWD", +"d -RcW ,UdP. -RWb8 dP.,RD c-RW8 ,USd -USd ZbS* Z-Sc Sbd,j S-bW8 SZb*j gScs-", +" Rb,m ,RmU& RD,m ,Rcm U5,P ,R8bm ,R5Dm cR5,m ,USm Sbm,& VmS, cmS, pbS, Spb,", +"8 S,Vp S,cp bmR* Rb-m ,RDm* -Rcm ,U5;P -U>P R5D,;P c>R-m ,US; -US; V;S, S;V", +"- pbS* Sb-p Vp*Sb cpS- ,RWbm RW&,Um ,RHbm cRW,m ,R5bW Rb5,W8 ,R5WD cR5,W Sb", +"W,m ,UWS&m SZb,m ScZ,m Spb,W S8WpU, Vp,SZ ScpZ, ,Rvb vR-U ,RvD cR-v vRb,5 -", +"vR>b vRD,5 cvR-> vbS* Sb-v S,Vv cvS- Svbp* -pUSv Vv,Sp Scy- Rk) k)R! k)RB R", +")ak R1) R)8k 1)RB R)1a kMR) RkM!) R)Tk ak)RT lR) R8l) RTl) l)sR R*k +kR* Rk", +"*B akR* R1* 1+R* *BR1 1aR* RkM* k*MR+ TkR* ak*RT l*R R+l* RTl* sRl* kER) Rk", +"E!) R)Hk ak)RH 1ER) R18E) R)1H R1H8) RkME) kMER)! RHTk) RHTak) REl) lR8E) R", +"Hl) lsRH) dkR* dk*R+ HkR* R*gk 1dR* R1+d* 1HR* R1g* dkMR* R+dk*M RH*Tk gRTk", +"* Rdl* l+Rd* RHl* gRl* k)R2 Rk)!2 Rk)2B ak)R2 R)5k R158) R15)B R1a5) RkM)2 ", +"kM)R2! RTk)2 RT)ak2 R5l) lR58) lR5T) lsR5) k;R* k;*R+ k;*RB ak;R* 1;R* R1>*", +" R1;*B >kRa* k;MR* R+kM;* RT;k* RT;ak* R5l* >Rl* l;RT* l>sR* RkE)2 kE)R2! R", +"Hk)2 RH)ak2 R15E) 5kER8) R1H5) ak)RH5 kMER)2 !ER)kM2 Hk)RT2 akHMR)2 lR5E) R", +"58lE) lHR5) sR5lH) dk;R* R+dk;* RH;k* gRk;* R1d5* >kRd* R1H5* >kgR* RdkM;* ", +"dkR;+M* Hk;RT* RT;gk* ldR5* l>Rd* lH;R* gl>R* kP) k!P) P)kB a)kP R)1P 8)kP ", +"kP)1B akP1) Sk) k)S! TkS) akS) Sl) l)S8 STl) l)Ss kP* k*+P *BkP kPa* 1PR* k", +"P8* kP*1B akP1* S*k +kS* TkS* akS* l*S S+l* lTS* l*Ss R)Wk kP)W! H)kP akPH)", +" R)1W R1W8) R1HW) R1Wa) WkS) S!Wk) S)Zk SZak) SWl) Sl8W) l)SZ SslZ) WkR* dk", +"P+* kPH* kPg* 1WR* dkP8* kP*1H gR1W* WkS* S+Wk* ZkS* S*gk Sdl* S8dl* SZl* l", +"*gS R)km km)R! km)RB akmR) R)1m R1m8) R1m)B akP5) kmS) S!km) STkm) Sakm) l)", +"Sp Slp8) SlpT) Sslp) kmR* km*R+ km*RB akmR* 1mR* kP>* kP*5B >kPa* kmS* S+km", +"* S;Tk* Sa;k* Spl* l*S> Sp*lT Ss*l> km)RW RW)km! RHmk) ak)RHm R1W5) km)RW8 ", +"R1Hm) ak)R5W SWkm) km)S!W SZkm) ZkmSa) SlpW) lWpS8) SZpl) lZpSs) R*vk vR+k*", +" vRHk* gvRk* R1v* >kvR* vR1H* >kgP* vkS* Sv+k* SZ*vk gSvk* l*Sv lv>S* lvZS*", +" l*yS ,R9 R&,k RB,k R9,a ,R1 :R, RB,1 ,R:a R9,M ,R9M& R9,T ,RT9a l,R :Rl, ,", +"RlT sRl, R9* -R9 *BR9 R9-a R*,1 :-R ,R1*B :a-R 9MR* R9-M 9TR* R9-T ,Rl* l-R", +" l*R,T sRl- ,ER9 k&E,R R9,H ,RH9a ,ER1 ,R:E R1,H ,R:H ,R9ME ,R9M&E ,RH9T R9", +"H,aM ,RlE :R,lE ,RlH :RHl, R9,d R9-d 9HR* -Rg9 R1,d -R:d ,R1H* :-gR ,Rd9M -", +"R9dM ,RT9d -RTg9 ,Rld -Rld lH*,R gRl- ,2R9 k&2,R ,R92B ,Ra92 R9,5 ,R:5 ,R15", +"B :R5,a ,R9M2 ,R9M&2 ,RT92 ak2,RT ,Rl5 :R5l, l,R5T ls,R5 R9,; R9-; ,R;9B -R", +"9a; R1,; ->:R ,R1;B :-R>a ,R;9M -R9M; ,RT9; -RT9; ,Rl; -Rl> l;,RT s-Rl> ,R9", +"E2 ,REk&2 ,RH92 ak2,RH ,R15E :R5,E ,R1H5 :RH,5 R9E,M2 k&,MRE2 ,R29HM ,2RH9a", +"M l,R5E l,5:RE lH,R5 s,5:RH ,Rd9; -R9d; ,RH9; g-R9; ,R15d :-R>d ,R1H; g:R->", +" R9d,M; R9d-M; R9H,T; -R;g9M ld,R5 l->Rd lH;,R gl->R ,kP k&,P ,BkP ak,P R1,", +"P ,R:P ,R1PB :Ra,P S9, ,kS& ,TS9 ,aS9 l,S S:, lTS, l,Ss 9PR* -kP kP*,B ak-P", +" kP*,1 -R:P k*B,1P :-RaP S9* S-9 9TS* -TS9 S9l* l-S S9*lT s-S: R9,W kP&,W H", +"k,P akP,H R1,W ,R:W ,R1HP :RH,W ,WS9 S9W,& Z9S, SZ9,a S,lW :WS, SZl, S,Z: 9", +"WR* R9-W dkP,H -kgP dkP,1 -R:W ,1HdkP g:R-W ,dS9 -WS9 Z9S* g9S- Sdl, lWS- l", +"Z*S9 gSl- R9,m km&,R ,Rm9B akm,R R1,m ,R:m ,R1mB :Rm,a ,kSm S9m,& S9T,m S9a", +",m Spl, S,:p Sp9,T Ss,:p 9mR* R9-m k;P,B -Rm9a k;P,1 -R:m k;B,1P :-Ram ,kS;", +" -kS; S9;,T S-9Tm S;l, S>l- Sp9T* l-pSs ,RW9m ,RWkm& ,RH9m ,RHakm ,R15W :RW", +",5 ,R1Hm :RH,m S9W,m km&S,W SZ9,m SamZk, Sp9,W S:p,W lZ,Sp S:Zp, ,Rv9 vR-k ", +"vR9,H -vRg9 ,Rv1 :R-v vR1,H :vRg- v9S* S9-v Sv9Z* gS-v9 l,Sv S-lv lv,SZ l-y", +"S UkR) RUk!) R)Dk ak)RD R)1U R1U8) R)1D R1D8) RUkM) U!kRM) RkV) VRak) RUl) ", +"lRU8) VRl) lsVR) RUk* R+Uk* DkR* ak*RD 1UR* R1+U* 1DR* R1+D* k*MRU R+Uk*M R", +"*Vk V+Rk* R*lU l+RU* lRV* s*VlR RUkE) U!kRE) RHUk) RHUak) R1UE) 1UER8) R1HU", +") R1)UH8 UkMRE) !ER)UkM VRHk) ak)VRH lRUE) R8UlE) VlRH) Vs)lHR dk*RU R+Udk*", +" RH*Dk gRUk* R1dU* 1UdR8* R1HU* gR1U* RdUk*M dkR*U+M VdRk* gVRk* ldRU* R8dl", +"*U lH*VR glVR* RUk)2 U!kR)2 RDk)2 RD)ak2 R1U5) 1U5R8) R1D5) ak)R5D UkMR)2 !", +")k2RUM V2Rk) ak)V2R lRU5) R5Ul8) VlR5) V5Rls) k;*RU R+Uk;* RD;k* RD;ak* R1;", +"U* >kRU* R1D5* >kDR* R;Uk*M k;R*U+M V;Rk* ak;V*R l;RU* l>RU* l;VR* V>lR* Uk", +"ER)2 !ER)Uk2 Hk)RD2 R)UHak2 1UER5) RE1U58) R1)UH5 R)1HU5a E)R2UkM U!RME)k2 ", +"RHkV2) akV2RH) R5UlE) RUlE58) V5RlH) lRV5sH) RdUk;* dkR;U+* Hk;RD* RD;gk* 1", +"UdR5* R1d>U* 1UHR5* >D*gR1 dkR;U*M U+R*k;dM RH;V*k gRkV;* R5dl*U >RUld* lHR", +"V5* glRV>* U)kP kP)U! D)kP akPU) 1)UP 1UP8) R1DP) 1UaP) UkS) S!Uk) VkS) SVa", +"k) SUl) SlU8) l)SV SlVs) kPU* kP*U+ kPD* akPU* UP1* kP*U8 kP*1D aP*1U U*Sk ", +"S+Uk* SkV* SV+k* lUS* S8*lU SVl* Ss*Vl kP)UW UW)kP! RWDk) ak)RWD R1WU) kP)U", +"W8 R1WD) aP)1UH SUWk) UWkS!) SZVk) ZkVSa) SlUW) lWUS8) SlVZ) lZVSs) dkPU* U", +"+WkP* dkPD* gUPk* R1WU* 1U+RW* R1WD* g1UP* SdkU* U+WS*k SZ*Vk gSVk* lW*SU S", +"+UlW* lZ*SV glSV* km)UP Um)kP! RDmk) ak)RDm R1mU) km)U8P R1Dm) ak)U5P SUkm)", +" km)S!U SVkm) VmkSa) SlpU) pUlS8) SlVp) VplSs) km*UP U+mkP* km*RD R+Dkm* kP", +"*U5 >kPU* kP*5D >kDP* S;Uk* km*S+U SV;k* S+kVm* Sp*lU S>lU* Vp*Sl S>Vl* RWU", +"km) k!m)RWU km)RWD akRmUH) kP)U5W R)1WU8m kP)UH5 1HRmU8) km)SUW WmS)U!k Zkm", +"SV) akVmSZ) lWUSp) SplWU8) lZSVp) SlVpsZ) vRUk* kP*vU+ vRDk* gR*vDk vR1U* >", +"P*v1U vR1D* >D*vR1 SvUk* vU+S*k VvSk* gSkVv* lvSU* S>Ulv* lvVS* ylVS* tR, ,", +"Rt& ,RtD t,cR ,Rt1 t,:R R1,D :,cR ,RtM tRM,& tRV, tcV,R tRl, t:Rl, lRV, uR,", +" t*R t-R RDt* cRt- R1t* :Rt- t*R1D c-:R R*tM tR-M tRV* -RVt lRt* -Rlt t*VlR", +" u-R ,RtE tR&,E ,RtH tcR,H tR1,E t:R,E tHR,1 t:H,R tRM,E M&EtR, tHV,R cRVtH", +", ltR,E lt,:RE ltH,R ,RuH ,Rtd -Rtd RHt* gRt- tdR,1 t:d-R tH*R1 g:Rt- tdR,M", +" t-RdM tH*VR V-gtR ltd,R l-tRd tH*lR g-uR ,Rt2 tR&,2 tRD,2 tcR,2 ,Rt5 t:R,5", +" t5R,D tc5,R tRM,2 M&2tR, VtR,2 Vt,cR2 t5Rl, lt5:R, t5V,R ,Ru5 ,Rt; -Rt; t;", +"R,D tc;-R R5t* -Rt> t5*RD c>Rt- t;R,M t-RM; t;V,R V-tR; t5*lR l-t>R t5VR* -", +">uR tR,E2 ,R&tE2 tHR,2 cR,tH2 t5R,E :R,t5E tH5,R tH,cR5 ,RMtE2 M&tE,R2 V,Rt", +"H2 V2tc,RH l,Rt5E lRt5:,E tHRV5, uRH,5 tdR,; t-Rd; tH;,R gt-R; t5d,R t>-Rd ", +"tH5R* gt>-R ,Rdt;M -Rdt;M tHRV;, gtRV-; t5Rld, t>Rl-d tHRl;, u->gR tP, ,Pt&", +" ,DtP t,cP ,1tP t,:P tP1,D t:Pc, St, t&S, VtS, S,tc l,St S,t: SVl, uS, tP* ", +"t-P DPt* c-tP 1Pt* :-tP tP*1D t-P:c St* S-t t*SV StV- l*St Stl- St*Vl u-S ,", +"RtW tWR,& ,HtP tcW,R tWR,1 t:W,R tHP,1 t:H,P S,tW StW,& S,tZ ScZt, Stl,W S:", +"t,W lZ,St SZu, ,dtP -RtW HPt* gPt- tW*R1 t-W:R tHP1* gtP:- tWS* Sdt- S*tZ S", +"-gt Stdl* l-StW tZ*Sl gSu- ,Rtm tmR,& tmR,D tcm,R ,5tP t:m,R t5P,D tc5,P tm", +"S, Stm,& SV,tm Sct,m S,tp S:pt, Vp,St Spu, ,;tP -Rtm tm*RD t-mcR 5Pt* >Pt- ", +"t5PD* t>Pc- tmS* S;t- St;V* V-mSt S*tp tpS- tp*SV S-up tWR,m ,RWtm& tHm,R t", +"H,cRm t5W,R t5,:RW tH5,P tH,:Rm StW,m tWmS&, tZS,m tZmSc, tpS,W tpWS:, tZpS", +", uZ,Sp vRt* tP-v tvR,H cvRt- tvR,1 :vRt- tH5P* :vRc- S*tv tvS- Vv,St V-vSt", +" lvtS* l-vSt Vv,Sl y-uS X X! XB aX X. 8X X.B 8Xa XK XK! TX TXa Xj 8Xj TXj s", +"X X( +X X(B +Xa X(. +X8 .BX( +8aX X(K +XK TX( +TX Xj( +Xj T(Xj sX+ GX GX! H", +"X GaX GX. G8X HX. H8X GXK XKG! GTX TXGa GjX 8XGj HXj sGX dX +GX HXd gX dX. ", +"8dX H.dX gX8 dXK GK+X TdX gXT dXj Gj+X dXHj gsX X2 X2! X2B aX2 5X 5X8 5XB 5", +"aX X2K 2KX! TX2 T2aX 5Xj 58Xj 5TX sX5 X; +X; X;B aX; 5X; >X 5BX; >Xa X;K +K", +"X; TX; T;+X X;j >Xj T;5X >Xs GX2 X2G! HX2 G2aX G5X 5XG8 H5X 5aHX X2GK GX2!K", +" G2TX aX2GT 5XGj G58Xj 5THX G5sX G;X G;+X HX; gX; 5dX >XG 5dHX >Xg GKX; dXK", +"+; TXG; TXg; dj5X Gj>X Td5X gs>X XP XP! XPB aXP XP. 8XP P.XB aX8P QX QX! QX", +"T QaX QXj Q8X XjTP sXQ XP( +XP P(XB aX+P P(X. 8X+P XP(.B aXP+8 QX( +QX Q(TX", +" Qa+X Q(Xj Q8+X Xj(TP +QsX Y Y! YH Ya Y. Y8 YH. Y8H YQ YQ! YZ YZa Yj Y8Q YZ", +"j sY Yd Y+ YHd gY Yd. Y+8 HdY. gY8 YQd Y+Q YZd gYZ Yjd Y+j ZdYj sYg Xm Xm! ", +"XmB aXm 5Xm 8Xm 5BXm aX5P QXm Q!Xm TXm aXTm pX pX8 pXT spX Xm; +Xm XB;P aX+", +"m X;5P >Xm Xm;5B aX>P QX; QX+m TXQ; TX+m pX; >Xp TXp; sp>X Ym Ym! YHm Yam Y", +"5 Y58 Y5H Y5a YQm Q!Ym YZm ZaYm Yp Yp8 YpZ sYp Yv Yv+ YvH gYv Yv5 Y> vHY5 Y", +">g YvQ v+YQ YZv YZgv Ypv Y>p ZpYv yY X# X& X#B aX& X#. 8X& .BX# 8aX& X#K X&", +"K TX# TX& Xj# X&j T#Xj sX& X#( +X& #BX( +aX& #(X. +8X& X#(.B aX&+8 #(XK +KX", +"& X#T( T&+X j#X( X&+j Xj#T( +Xs& GX# G&X HX# HX& X#G. 8XG& X#H. 8XH& X#GK G", +"KX& G#TX TXG& G#Xj X&Gj H#Xj G&sX dX# dX& H#dX gX& X#d. d&8X dX#H. 8Xg& X#d", +"K dKX& T#dX TXg& d#Xj X&dj dXjH# g&sX X#2 X&2 2BX# X2a& 5X# 5X& X#5B aX5& 2", +"KX# &2XK X#T2 T2X& 5#Xj Xj5& 5#TX 5Xs& X;# X;& ;#XB X&a; 5#X; >X& X;#5B aX>", +"& ;#XK XK;& T#X; X;T& X#;j X&>j X;jT# >&sX X#G2 G2X& X#H2 H2X& G#5X 5XG& H#", +"5X 5XH& GX#2K X&2GK GTX#2 GT&X2 Xj#G5 X&jG5 G5TX# sX5G& G#X; X;G& H#X; X;g&", +" 5#dX G&>X H5Xd# >&gX dX#;K dX&;K GT;X# gXT;& dXj5# >XG&j X;jH# >Xgs& XP# X", +"&P P#XB X&aP P#X. X&8P XP#.B aXP8& QX# QX& Q#TX TXQ& Q#Xj 8XQ& Xj#TP QXs& P", +"#X( X&+P XP#(B aXP+& XP#(. X&P+8 P#(X.B +X8aP& X#Q( Q&+X QXT#( +QXT& Xj#Q( ", +"X&j+Q TX#Pj( sX+Q& Y# Y& YH# Ya& Y#. Y8& H#Y. H8Y& YQ# Y&Q YZ# YZ& Yj# Y&j ", +"ZjY# sY& Yd# Y+& HdY# gY& d#Y. 8dY& YHd#. g8Y& QdY# +QY& ZdY# Y&gZ djY# +jY", +"& YZdj# Y&gs Xm# Xm& m#XB X&am 5#Xm Xm5& Xm#5B aXm5& Q#Xm XmQ& T#Xm XmT& pX", +"# pX& TXp# p&sX X#;P X&+m Xm;#B aXm;& Xm;5# Xm>& 5X#;PB >Xam& Q#X; X;Q& QX;", +"T# aX;Q& X;p# p&>X pXT;# >Xps& Ym# Y&m HmY# HmY& Y5# Y5& H5Y# H5Y& QmY# Q&Y", +"m ZmY# YmZ& Yp# Yp& Y#Zp Y&sp Yv# Yv& vHY# Y&gv v5Y# Y>& YvH5# Y&g> vQY# YQ", +"v& Y#Zv ZvY& Y#pv pvY& YZvp# yY& IX IX! DX DXa IX. 8IX DX. D8X IXK I!XK DXT", +" aITX IjX Ij8X DXj sIX IX( +IX DX( +DX X(I. 8I+X X(D. D8+X X(IK IX+K D(TX D", +"X+T I(Xj Ij+X D(Xj +DsX GIX IXG! JX JaX IXG. GI8X JX. J8X IXGK GIX!K JTX TX", +"Ja GIXj IjXG8 JjX sJX IdX Id+X JdX gJX I.dX Id8X dXJ. J8gX IXdK IdX+K TdJX ", +"JTgX dXIj Idj+X dXJj gXsJ IX2 I!X2 DX2 I2aX 5IX 8I5X 5DX D85X X2IK IX2!K I2", +"TX aX2TI Ij5X IjX58 DX5T 5DsX I;X I;+X DX; D;+X I;5X >XI D;5X >XD IKX; I;X+", +"K TXD; aX;TI X;Ij Ij>X X;Dj sI>X IXG2 GIX!2 JX2 aXJ2 GI5X G58IX J5X 5aJX GI", +"X2K IX2GK! TXJ2 JTaX2 IjXG5 G58IjX 5TJX J5sX dXI; IdX+; J;X J;gX Id5X Id>X ", +"5dJX J>X IdX;K +GIX;K TXJ; gJTX; Idj5X >IjdX X;Jj >XsJ IP IP! DXP aIP IP. 8", +"IP D.IP 8IDP QIX Q!IP QDX DXQa IPj 8IQX DjQX sIP IP( +IP D(IP DX+P P(I. 8I+", +"P IP(D. +DX8P Q(IP QI+X Q(DX QD+X I(Pj IP+j IPjD( +IsP YI YI! YJ YJa YI. Y8", +"I YJ. YJ8 YQI QIY! YZJ ZJYa YjI Q8YI YJj sYJ YId Y+I YJd gYJ IdY. +IY8 JdY.", +" Y8gJ QIYd +QYI YdZJ YZgJ IdYj +IYj YdJj sJgY ImX I!Xm DXm aXDm 5IP 8I5P DX", +"5P 8XDm ImQX ImXQ! DmQX aXmQD pIX 8IpX pDX pDsX I;P Im+X I;DP DX+m I;5P >PI", +" I;P5D DX>P I;QX I;P+Q DXQ; aX;QD I;pX pI>X DXp; sI>P YIm ImY! YJm JmYa Y5I", +" 5IY8 YJ5 J5Y8 QIYm YQIm! JmYZ YZJam YpI pIY8 JpY JpsY YvI vIY+ JvY JvgY vI", +"Y5 Y>I Y5Jv Y>J YQvI Yv+QI YZJv gYZJv pIYv pIY> JvYp yJY bX bX& bXD cX bX. ", +"b8X b.DX cX8 bXK bKX& bTX cXT bXj 8Xbj DXbj scX bX( b+X b(DX cX+ X(b. +Xb8 ", +"bXD(. +Xc8 X(bK bK+X b(TX +TcX b(Xj +Xbj bTXj( s+cX bGX G&bX JbX cJX GXb. G", +"8bX bXJ. J8cX GXbK I&KGX bTJX JTcX GjbX I&jGX bXJj cJsX bdX +GbX bdJX gcX b", +".dX 8dbX JbdX. g8cX bKdX dX&bK TdbX gTcX dXbj IdjX& JjbdX scgX bX2 b2X& b2D", +"X cX2 b5X 5Xb8 5DbX c5X X2bK I&2XK b2TX TXc2 5Xbj I&j5X 5TbX c5sX bX; +Xb; ", +"DXb; cX; 5Xb; >Xb b5XD; c>X bKX; I;&XK TXb; TXc; X;bj bX>j X;jbT sc>X GXb2 ", +"I&2GX bXJ2 JXc2 G5bX bG58X b5JX J5cX bGX2K bG2X&K JbTX2 cJTX2 bG5Xj bG5X&j ", +"J5bTX sJc5X G;bX I;&dX bXJ; c;gX 5dbX bG>X J5bdX gc>X bG;XK IdKX;& J;bTX cJ", +";TX dXjb5 >XbGj J;jbX J>scX bXP IP& DXbP cXP b.IP 8IbP IP.bD 8IcP bQX Q&bX ", +"QDbX cQX QXbj Q8bX IPjbT cQsX b(IP +IbP IP(bD +IcP IP(b. IP&+8 DX(bP. cX+8P", +" b(QX +QbX bQXD( +QcX IPjb( IP&+j Ij(bTP sIPc+ Yb Yb& YJb Yc Yb. Yb8 JbY. Y", +"c8 YbQ bQY& YZb YcZ Ybj bQY8 ZbYj sYc Ybd Yb+ JbYd Ycg bdY. b+Y8 YJbd. Y8gc", +" bQYd b+YQ YdZb ZcgY bdYj b+Yj YZbdj gsYc bXm XmI& DXbm cXm 5IbP 8Xbm b5XDm", +" 5IcP QXbm Im&QX TXbm QXcm pbX b8pX bTpX cpX I;bP +Xbm I;PbD +Xcm I;Pb5 bX>", +"P 5DXb;P cX>P QXb; I;PQ& I;PbT QXc; bXp; pb>X pbXD; >Xcp Ybm bmY& JmYb Ycm ", +"Yb5 b5Y8 J5Yb Yc5 bQYm YbQm& YmZb cmYZ Ypb pbY8 YbJp Ycp Yvb vbY+ YbJv Ycv ", +"vbY5 Y>b YJ5vb Yc> YQvb Yvb+Q ZvYb YZcv pvYb p>Yb JpYvb yYc X0 X0! X0B aX0 ", +"1X 1X8 1XB 1aX X0K !KX0 TX0 T0aX 1Xj 18Xj 1TX sX1 X0( +X0 0BX( +0aX 1X( 1+X", +" X(1B +X1a 0(XK X0+K X0T( +0TX 1(Xj +j1X 1(TX 1+sX GX0 X0G! HX0 G0aX 1GX G8", +"1X 1HX Ga1X X0GK GX0!K G0TX aX0GT Gj1X 1G8Xj GT1X 1GsX dX0 +0dX H0dX gX0 1d", +"X +G1X HX1d g1X X0dK dX0+K T0dX TXg0 dj1X dXj1+ Td1X sXg1 X02 !0X2 2BX0 X2a", +"0 1X5 158X 1B5X 5a1X 2KX0 X02!K X0T2 aX0T2 15Xj 1X58j 5T1X 1Xs5 X;0 +0X; ;0", +"XB a0X; 1X; >X1 1BX; 1a>X ;0XK X;0+K T0X; aX;T0 Xj1; 1X>j TX1; s1>X X0G2 GX", +"0!2 X0H2 aX0G2 G51X 1G58X H51X 1Ga5X GX02K X02GK! GTX02 GT0aX2 1G5Xj G581Xj", +" 1GT5X sX1G5 G0X; dX0+; H0X; X;g0 G;1X 1G>X HX1; g1>X dX0;K +G0X;K GT;X0 gX", +"T;0 dXj1; >X1Gj X;j1H >Xgs1 XP0 X!P0 P0XB XPa0 1XP 8X1P XP1B aX1P QX0 X0Q! ", +"Q0TX Q0aX 1QX Q81X QX1T 1QsX P0X( XP+0 XP0(B aXP+0 XP1( +X1P 1XP(B 1+XaP X0", +"Q( +0QX QXT0( +QXT0 1(QX +Q1X 1QXT( sX1+Q Y0 Y0! YH0 Ya0 Y1 Y18 Y1H Y1a YQ0", +" Q!Y0 YZ0 ZaY0 Y1Q 1QY8 YZ1 sY1 Yd0 Y+0 HdY0 gY0 Y1d Y1+ 1HYd gY1 QdY0 +QY0", +" ZdY0 g0YZ 1QYd 1+Yj YdZ1 g1sY Xm0 X!m0 m0XB a0Xm 1Xm 8X1m 1BXm aX1m Q0Xm X", +"m0Q! T0Xm aXmQ0 pX1 1Xp8 1TpX s1pX X0;P +0Xm Xm;0B aXm+0 Xm1; 1X>P 1Xm;B >X", +"1am Q0X; +QXm0 QX;T0 aX;Q0 1Xp; p1>X pX1T; >Xps1 Ym0 m0Y! HmY0 amY0 Y15 1mY", +"8 1HY5 1aY5 QmY0 YQm!0 ZmY0 YZam0 Yp1 p1Y8 ZpY1 Y1sp Yv0 v+Y0 vHY0 g0Yv Yv1", +" Y>1 YHv1 g1Y> vQY0 Yv+Q0 Y0Zv gYZv0 pvY1 p>Y1 ZvY1 yY1 9X 9X& 9XB 9aX 9X1 ", +":X 1B9X :Xa 9XK 9KX& 9TX TX9a 9Xj :Xj 1T9X s:X 9X( 9+X X(9B +X9a 9(1X :X+ 9", +"X1(B +X:a X(9K 9K+X 9(TX +T9X 9(Xj +X:j 9TX1( s+:X 9GX G&9X 9HX Ga9X 1G9X :", +"GX 1H9X :HX GX9K X&K9G GT9X 9GTaX Gj9X Gj:X HX9j :GsX 9dX +G9X HX9d g9X 1d9", +"X :dX 9HX1d g:X 9KdX dX&9K Td9X 9TgX dX9j dX:j dXj9H s:gX 9X2 92X& X29B 92a", +"X 95X :X5 9B5X 5a:X X29K X&29K 92TX 9TX&2 5X9j 5X:j 5T9X s5:X 9X; +X9; 9BX;", +" aX9; 1X9; >X: 95X;B :a>X 9KX; X;&9K TX9; aX;9T X;9j >j:X X;j9T s:>X GX92 X", +"&29G 92HX 9GaX2 G59X G5:X H59X H5:X 9GX2K 9G2X&K 9GTX2 aX29GT 9G5Xj :G5Xj 9", +"G5TX :HXs5 G;9X dX&9; HX9; 9Xg; 5d9X :G>X 9H5dX >Xg: 9G;XK d&K9X; 9GTX; g9X", +"T; dXj95 :>GXj X;j9H g:Xs> 9XP X&9P XP9B aX9P 1X9P :XP 9X1PB aX:P 9QX Q&9X ", +"QX9T Qa9X 1Q9X :QX 9QX1T :QsX XP9( +X9P 9XP(B 9+XaP 9X1P( +X:P 1X(9PB :X+aP", +" 9(QX +Q9X 9QXT( 9+QTX 9QX1( +Q:X Xj(9TP :QXs+ Y9 Y9& Y9H Y9a Y91 Y: 9HY1 Y", +":H Y9Q 9QY& YZ9 Z9Ya Y9j Y:Q Z9Y1 sY: Y9d Y9+ 9HYd gY9 9dY1 Y:+ Y91Hd Y:g 9", +"QYd 9+YQ YdZ9 YZg9 9dYj :QY+ YZ91d gYZ: 9Xm X&9m 9BXm aX9m 1X9m :Xm 95XmB a", +"X:m QX9m Xm&9Q TX9m aXm9Q p9X :pX 9TpX sX:p Xm9; +X9m 9Xm;B aXm9+ 95X;P :X>", +"P X;B95P :Xm>a QX9; X;&9Q 9QXT; aX;9Q 9Xp; >X:p p9XT; :pXs> Y9m 9mY& 9HYm 9", +"aYm Y95 Y:5 9HY5 :HY5 9QYm Y9Qm& YmZ9 YZ9am Yp9 Y:p ZpY9 YpZ: Yv9 v9Y+ YHv9", +" Yvg9 v9Y1 Y:v Yv91H gY:v YQv9 Yv9+Q ZvY9 gY9Zv pvY9 Yp:v Yp9Zv yY: IX0 I!X", +"0 DX0 D0aX 1IX 8I1X 1DX D81X X0IK IX0!K D0TX aX0TI Ij1X IjX18 DX1T 1DsX X0I", +"( IX+0 X0D( +0DX IX1( +I1X 1(DX +D1X IX0(K +IX0K DXT0( +DXT0 IjX1( 1+IXj 1D", +"XT( sI1+X IXG0 GIX!0 JX0 aXJ0 GI1X 1G8IX J1X 1aJX GIX0K IX0GK! TXJ0 JTaX0 I", +"jX1G 1G8IjX 1TJX J1sX I0dX IdX+0 dXJ0 JXg0 Id1X 1+GIX 1dJX J1gX IdX0K +I0dX", +"K JTdX0 gJTX0 Idj1X 1+IdXj J1TdX sJg1X X0I2 IX0!2 X0D2 aX0I2 5I1X 1I58X 5D1", +"X 1DX5a IX02K X02IK! DXT02 TI0aX2 IjX15 5I81Xj 1DX5T sI15X I0X; I;X+0 D0X; ", +"aX;D0 I;1X 1I>X DX1; 1D>X I;X0K +I0X;K DX;T0 aX0TI; I;j1X >I1Xj X;j1D >Xs1D", +" GIX02 IX0G2! X0J2 JaX02 1G5IX G581IX 1XJ5 J158X IX0G2K I!X2G0K JTX02 aX0JT", +"2 1G5IjX Ij1XG58 J15TX sJ15X IdX;0 +GIX;0 X;J0 gJX;0 1G;IX >I1dX 1XJ; J1>X ", +"dX0I;K Id+X;0K J;TX0 gXTJ;0 1IdX;j Idj>X1 J1;TX J>s1X IP0 I!P0 D0IP a0IP 1I", +"P 8I1P DX1P aI1P Q0IP IP0Q! Q0DX QDXa0 QI1X IPj18 QD1X 1IsP P0I( +0IP IP0D(", +" +DXP0 1(IP +I1P 1DXP( 1+DIP IP0Q( +QIX0 QDX0( +QDX0 IPj1( IPj1+ 1QDX( sIP1", +"+ YI0 I0Y! YJ0 JaY0 Y1I 1IY8 YJ1 J1Y8 QIY0 YQI!0 Y0ZJ YZJa0 1QYI Y1Q8I ZJY1", +" Y1sJ IdY0 +IY0 JdY0 g0YJ 1IYd 1+YI YdJ1 YJg1 YQId0 Y+QI0 YZJd0 gYZJ0 Y1QId", +" Y1+QI YZ1Jd gY1sJ I0Xm ImX!0 D0Xm aXmD0 5I1P 1Im8X DX1m aXm1D ImXQ0 QI0Xm!", +" QDXm0 aX0TIm 1IpX pI81X 1DpX sIPp1 I0;P I;P+0 I;PD0 a;PI0 I;1P 1I>P I;P1D ", +">XD1m I;PQ0 Im0+QX I;PT0 aX0QD; pI1X; >Xp1I pDX1; sIP>1 ImY0 YIm!0 Y0Jm YJa", +"m0 1IY5 Y158I J1Y5 YJ15a YQIm0 Im0YQ! YZJm0 ZJmYa0 pIY1 Yp18I Y1Jp JpsY1 Y0", +"vI Yv+I0 Y0Jv gYJv0 vIY1 >IY1 Y1Jv Y1J> YvQI0 vIQY+0 YZvJ0 JvZgY0 Yv1pI Y>p", +"1I JpYv1 YJy1 bX9 I&9X 9DX cX9 b1X :IX 1DbX :cX bK9X I&K9X 9TbX 9TcX 9Xbj b", +"X:j 1TbX :csX b(9X 9+bX 9(DX 9+cX b(1X b+:X b1XD( :+cX bX9(K b+X9K bTX9( cX", +"9+T b1Xj( :I+Xj b1TX( :cXs+ 9GbX bG9X& J9X J9cX 1GbX bG:X b1JX :JX bG9XK bG", +"9X&K 9TJX cJ9TX b1GXj :GbXj 9XJj sX:J 9dbX dX&9I 9dJX cXg9 1dbX bd:X J91dX ", +"gX:J bdX9K IdK9+X J9TdX gJ9TX Idj9X :IdXj J9jdX g:XsJ b29X I&29X 92DX 9Xc2 ", +"95bX b5:X 5D9X c5:X bX92K 9I2X&K bTX92 cX9T2 b1X5j :I5Xj b1T5X :cXs5 9Xb; I", +";&9X DX9; 9Xc; 1Xb; :I>X b1XD; :c>X bX;9K I;K9+X bTX9; cX;9T I;j9X :>IXj X;", +"j9D c>Xs: bG9X2 bG9X&2 9XJ2 cJ9X2 b1G5X :Gb5X 95JX J5:X 9G2bXK bK9GX&2 J9TX", +"2 J9TcX2 9G5bXj bG5:Xj J95TX :Js5X bG;9X 9+GbX; 9XJ; cJ;9X b1GX; :>GbX J95d", +"X >X:J IdK9X; X;G&9IK J9;TX cXTJ9; b1GX;j >Ij:dX J9;Xj :J>sX 9IP I&9P DX9P ", +"9IcP 1IbP :IP b1XDP cX:P 9QbX IP&9Q QD9X 9QcX 1QbX bQ:X IPj9D :IsP 9(IP +I9", +"P 9DXP( cX9+P b1XP( +I:P b1DIP( :cX+P bQX9( b+Q9X 9QDX( cQX9+ IPj9( :QI+X I", +"P(b1T sIP:+ Yb9 9IY& YJ9 Yc9 Yb1 Y:b J9Y1 Y:J bQY9 Yb9Q& ZJY9 Y9Zc b1Yj :QY", +"b ZbY1 Z:Yc bdY9 b+Y9 YdJ9 g9Yc b1Yd :IY+ YJ91d gY:J Yb9Qd Yb+9Q YZb9d gY9Z", +"c Yb1Qd Y:b+Q YZb1d sY:gJ 9Xbm Im&9X DX9m 9Xcm 1Xbm bX:m b1XDm cX:m bQX9m 9", +"QIXm& bTX9m cQX9m b1pX pb:X 9DpX :Xcp I;9P I;P9+ I;P9D cXm9+ I;Pb1 :I>P 95D", +"I;P c>X:m I;P9Q 9+QI;P I;P9T cQX9; pbX9; :pI>X p9DX; cpX:> bmY9 Yb9m& JmY9 ", +"cmY9 b1Y5 :IY5 J9Y5 Y5:J Yb9Qm Im&Y9Q YZb9m YcZ9m pbY9 Yb:p Y9Jp cpY: vbY9 ", +"Yvb9+ Y9Jv Y9cv vbY1 Yb:v Jv9Y1 :JY> Yvb9Q Y9QvI& Jv9YZ YcvZ9 Ypbv9 :vIYp J", +"p9Yv Y:yJ RX RX! RXB RaX RX. R8X X.RB 8XRa XM XM! RTX aXM RjX 8XM TXRj sRX ", +"RX( R+X X(RB +XRa X(R. +XR8 RX(.B R+8aX XM( +XM R(TX +XRT R(Xj +XRj XM(Tj R", +"+sX RG RG! RGH RGa RG. RG8 R.HX G8RH RGM R!GM RGT GTRa RGj G8Rj GTRj sRG RG", +"d R+G HXRd gRG R.dX +GR8 dX.RH RGg8 dXM +MRG GTRd gXM GjRd +GRj dXMHj sRgX ", +"RX2 X2R! X2RB R2aX R5X 5XR8 RB5X 5XRa XM2 M!X2 R2TX X2aM 5XM 8X5M 5XRT R5sX", +" R;X +XR; RBX; aXR; 5XR; >XR X;BR5 Ra>X XM; X;+M TXR; XMa; X;Rj >XM XM;5T s", +"R>X RG2 G2R! R2HX R2Ga RG5 G5R8 G5RH G5Ra R2GM XM2G! R2GT aXMG2 G5Rj RG58M ", +"G5RT RGs5 RG; +GR; G;RH RGg; G5Rd >RG RG5H; gR>X GMR; dXM+; GTR; XMg; G;Rj ", +"RG>M dXMH5 gX>M RXP XPR! XPRB RXaP XPR. RX8P RXP.B aXPR8 SX S!X STX SaX SXj", +" S8X TXSj SsX XPR( RX+P RXP(B aXPR+ RXP(. R+8XP XP(R.B R+8aXP SX( S+X TXS( ", +"+TSX XjS( +XS8 STXj( S+sX YR YR! YRH YaR YR. Y8R RHY. RHY8 SY SY! SZY SYa S", +"Yj SY8 YjSZ sYS YRd Y+R RHYd gYR RdY. R+Y8 YRHd. Y8gR SYd SY+ YZSd gSY YjSd", +" Y+S8 SZYdj sYgS RmX R!Xm RBXm aXRm 5XRm 8XRm XmBR5 aXmR5 SXm XmS! TXSm aXS", +"m SpX pXS8 STpX sXSp XmR; +XRm Xm;RB aXmR+ Xm;R5 Rm>X R5X;PB >XRam S;X +XS;", +" TXS; aXS; pXS; S>X SpTX; >XSs YRm RmY! RHYm RaYm Y5R R5Y8 RHY5 R5Ya SYm Ym", +"S! SmYZ SmYa YpS S8Yp SZYp YpSs YvR vRY+ YHvR YvgR vRY5 Y>R YvRH5 gRY> SvY ", +"YvS+ YZSv SvgY YpSv S>Y SZpYv yYS RX# R&X X#RB aXR& X#R. 8XR& RX#.B aX&R8 X", +"M# XM& R#TX TXR& R#Xj X&Rj XM#Tj R&sX X#R( +XR& RX#(B aX&R+ RX#(. R+8X& X#(", +"R.B R+8aX& M#X( X&+M XM#T( aXM+& XM#j( XM&+j RT#Xj( sX+R& RG# RG& R#HX GaR&", +" G#R. G8R& RGH#. RG8H& R#GM GMR& R#GT GTR& R#Gj G&Rj RGTj# RGs& R#dX +GR& d", +"X#RH RGg& dX#R. dX&R8 RH#dX. gRG8& d#XM XMd& dXMH# XMg& dXMj# dXM&j dX#RHj ", +"gsRG& X#R2 R2X& RX#2B aX&R2 R#5X 5XR& R5X#B R5aX& M#X2 X2M& XM#T2 aXM&2 5#X", +"M XM5& R5TX# sX5R& R#X; X;R& X;#RB aX;R& X;#R5 R&>X R5#X;B >XRa& X#M; M;X& ", +"XM;T# aXM;& XM;5# XM>& X;#R5T >XsR& G#R2 R2G& RGH#2 RGa&2 R#G5 G5R& RG5H# R", +"G5H& XM#G2 XM&G2 RGT#2 XM&H2 RG5M# XM&G5 RG5T# sRG5& R#G; G;R& RG;H# gRG;& ", +"RG5d# RG>& dX#RH5 >XgR& dXM;# dXM;& XM;H# gXM;& dXM5# >XMG& dX#R5T >XgM& XP", +"R# RXP& RXP#B aXPR& RXP#. X&PR8 XP#R.B R8aX&P SX# S&X TXS# TXS& XjS# 8XS& S", +"TXj# S&sX RXP#( X&PR+ XP#R(B R+aX&P XP#R(. R+8X&P .BR(XP# aXR&+P8 X#S( +XS&", +" STX#( S+TX& SXj#( S+8X& Xj#ST( Ss+X& YR# Y&R RHY# RHY& R#Y. R8Y& YRH#. Y8R", +"H& SY# SY& S#YZ YZS& S#Yj Y8S& SZYj# S&sY RdY# R+Y& YRHd# Y&gR YRd#. Y+R8& ", +"RHdY#. gYR8& YdS# Y+S& SZYd# S&gY SYdj# SY+&j YZjSd# gSsY& R#Xm XmR& Xm#RB ", +"aXmR& Xm#R5 Xm&R5 R5#XmB R5aXm& XmS# XmS& STXm# SaXm& S#pX pXS& SpTX# Sp&sX", +" Xm;R# Xm&R+ Rm#X;B RamX;& R5X;P# >XRm& 5#XmR;B aXm>R& X;S# X;S& S;TX# Sa;X", +"& SpX;# S&>X pXTS;# S>sX& RmY# RmY& YRHm# YaRm& R5Y# R5Y& Y5RH# Y5aR& YmS# ", +"SmY& SZYm# SZ&Ym S#Yp S&Yp SZpY# Yp&Ss Y#vR vRY& YvRH# gYvR& YvR5# >RY& vRH", +"Y5# Y>gR& S#Yv YvS& YZvS# Sv&gY SvpY# S&Y> YpZSv# SYy& [ [! [D [a [. [8 [D.", +" [8D [M [!M V[ V[a [j [8M V[j [s [( [+ [D( [+D [(. [+8 D([. +D[8 [M( [+M V[", +"( V[+ [j( [+j V([j [s+ [G [!G [J [Ja [G. [8G [J. J8[ [GM GM[! VJ[ [aVJ [jG ", +"G8[j Jj[ [sJ [d [+G [Jd g[ [d. [8d J.[d g[8 [dM +G[M V[d g[V [dj +G[j [dJj ", +"g[s [2 [!2 [D2 [a2 [5 [58 [5D [5a [M2 M2[! V[2 V2[a [5M 5M[8 V[5 [s5 [; [+;", +" [;D [a; [5; [> 5D[; [>D [;M +M[; V[; [+V; [;j [>M [5V; V>[ [G2 G2[! [J2 J2", +"[a [5G G5[8 J5[ [5J8 GM[2 [!GM2 V2[J VJ[a2 G5[j [5G8M V[J5 J5[s [d; +G[; J;", +"[ g[; [5d [>G [5J; g[> GM[; [+GM; V[J; V;g[ G;[j [d>M [5Vd V>g[ [P [!P [DP ", +"[aP [P. [8P DP[. D8[P S[ S[! SV[ S[a S[j S[8 [jSV [sS [P( [+P DP[( +D[P P([", +". +P[8 [DP(. [+D8P S[( S[+ S(V[ V[S+ S([j [+S8 SV[j( S+[s [Y [Y! YJ[ Ya[ [Y", +". Y8[ Y.[J [JY8 S[Y S![Y ] ]a Yj[ Y8S[ ]j ]s [Yd Y+[ [dYJ g[Y Y.[d [+Y8 YJ[", +"d. Y8g[ S[d Y+S[ ]d ]g [dYj [+Yj ]jd ]gs [m [m! [mD [am [5m [8m 5D[m 5a[m S", +"[m S![m V[m [aVm [p [p8 [pV [ps [m; [+m Dm[; +D[m 5P[; [>m [5D;P [a>P S[; [", +"+S; V[S; [+Vm [p; S>[ V;[p [pV> [Ym Ym[! Jm[ [aJm Y5[ [5Y8 [JY5 [5Ya [mSY S", +"[Ym! ]m ]am [pY Y8[p ]p ]ps [v [v+ [vJ g[v [v5 Y>[ J5[v Y>g[ [vS S+[v ]v ]g", +"v [pv [pY> ]pv ]y [b [& [bD [c [b. [8b bD[. [c8 [bM [&M V[b [cV [jb [&j Vb[", +"j [sc [b( [+b bD[( [c+ b([. b+[8 [bD(. c+[8 bM[( b+[M [bV( V+[c bj[( b+[j V", +"[bj( [+sc [bG [&G [Jb [cJ bG[. bG[8 [bJ. J8[c bG[M GM[& JbV[ VJ[c bG[j G&[j", +" Jb[j [csJ [db [d& Jb[d g[c bd[. b8[d [Jbd. [8gc bd[M dM[& Vb[d [cgV bd[j d", +"&[j Jj[bd gs[c [b2 [&2 bD[2 [c2 [5b [5& b5[D [c5 bM[2 M&[2 [bV2 V2[c b5[j 5", +"M[& Vb[5 c5[s [;b [;& b;[D [c; b5[; [>b [5bD; [>c bM[; M;[& Vb[; V[c; b;[j ", +"[&>M V[5b; c>[s bG[2 G&[2 [bJ2 c2[J bG[5 G5[& Jb[5 J5[c [bGM2 [&GM2 VJ[b2 [", +"cJV2 [5bGM [5&GM J5V[b [sJc5 bG[; G;[& Jb[; c;g[ b5[d >b[d J5[bd c>g[ [dbM;", +" [d&M; J;V[b g[Vc; [5dbM [>bGM J;[bj J>V[c [bP [&P bP[D [cP bP[. b8[P [bDP.", +" [8cP S[b S[& V[Sb Sc[ [jSb [8Sb SV[bj [sSc bP[( b+[P [bDP( [+cP [bP(. [+b8", +"P bPD[(. [c+8P [bS( [+Sb SV[b( S+[c S[bj( S[+b8 V[jSb( [scS+ Yb[ Y&[ [JYb Y", +"c[ [bY. [8Yb YJ[b. Y8[c SYb YbS& ]b ]c YjSb YbS8 ]jb ]sc [dYb [+Yb YJ[bd Yc", +"g[ Yb[d. Yb+[8 [JdYb. g[Yc8 YbSd YbS+ ]bd ]gc S[dbj S[8bd bd]j gs]c [mb [m&", +" bm[D [cm b5[m b8[m [5bDm [5cm [mSb [mS& Vb[m cmS[ [pb [p& pbV[ cp[ bm[; b+", +"[m [mbD; [+cm [5b;P [&>P b5P[;D >P[c [;Sb [;S& SV;[b S;[c [;pb Sb[> [pVb; [", +">Sc [mYb [mY& Jb[m Jm[c [5Yb [5Y& YJ5[b Y5[c SmYb S[&Ym ]bm ]cm SbYp Y&[p ]", +"pb ]pc [vb [v& vb[J cv[ [5vb Yb[> [vJb5 [>Yc Sb[v S&[v ]vb ]cv pb[v SbY> pv", +"]b ]yc kX kX! kXB akX R1X 8kX RB1X 1XRa kXM M!kX TkX akTX lX lX8 lXT lsX kX", +"( +kX X(kB ak+X R(1X 1XR+ kX(1B akX1+ k(XM kX+M T(kX Tk+X lX( l+X TXl( sXl+", +" RGk R!Gk HkX GkRa R1G 1GR8 1GRH 1GRa kXGM kXMG! GkRT akXGT lGR RGl8 lHX sR", +"lG dkX +kRG dkHX gkX 1GRd 1+RG dkX1H R1gX kXdM dkX+M dkTX TkgX ldX R+lG HXl", +"d glX kX2 X!k2 X2kB k2aX 5kX 8k5X 5BkX ak5X k2XM kXM!2 T2kX akXT2 lX5 5Xl8 ", +"5TlX l5sX kX; k;+X kBX; kXa; 1XR; >kX kX;1B ak>X XMk; kX;+M kXT; akXT; lX; ", +"l>X TXl; >Xls R2Gk kX2G! H2kX akXG2 1GR5 R1G58 5kHX akXG5 kXMG2 Gk2XM! RGTk", +"2 ak2RGT RGl5 lGR58 H5lX lsGR5 GkR; dkX+; kXH; kXg; 1GR; R1>G dkXH5 gk>X dk", +"XM; +GkXM; dkXT; gkXT; RGl; lG>X HXl; >Xgl kXP X!kP XPkB kXaP kX1P kX8P kXP", +"1B akX1P SkX kXS! TkSX akSX lXS S8lX STlX lXSs XPk( kX+P kXP(B akX+P kXP1( ", +"R1+XP 1X(kPB 1+XakP kXS( +kSX STkX( S+TkX SXl( S+lX SlTX( Ssl+X Yk Yk! YkH ", +"Yak Y1R Y8k R1YH R1Ya SYk S!Yk YZk YkSa lY lY8 lYZ lYs Ykd Y+k HkYd gYk R1Y", +"d R1Y+ Y1RHd Y1gR YkSd YkS+ YdZk SYgk lYd lY+ YZld glY kXm X!km kBXm kXam 1", +"XRm kX8m kXm1B akX1m kXSm kXmS! kXTm SakXm lXp l8pX lTpX splX Xmk; kX+m kXm", +";B akX+m kXm1; kX>P kXB1;P >kXam kXS; S+kXm S;TkX Sa;kX S;lX lXS> lXpT; l>X", +"Ss Ykm kmY! HkYm akYm Y5k 5kY8 H5Yk 5aYk SmYk SYkm! YmZk SYakm lYp lpY8 lZY", +"p lsYp Yvk vkY+ YHvk Yvgk vRY1 Y>k Yv1RH >kgY YkSv SY+vk ZvYk gYkSv lYv lY>", +" YZlv ylY R9X kX& RB9X 9XRa 9XR1 :RX kXB91 Ra:X 9XM XMk& 9XRT aX9M lX9 l:X ", +"9TlX s:lX R(9X 9XR+ kX(9B akX9+ kX(91 R+:X 9X(R1B :R+aX 9(XM +X9M R9TX( aXM", +"9+ 9Xl( :Xl+ lX9T( lsX:+ R9G 9GR& 9GRH 9GRa 9GR1 :RG R9G1H RG:H 9MRG kX&GM ", +"9GRT aXM9G R9lG :RlG 9HlX :RsG 9GRd 9+RG dkX9H R9gX dkX91 R+:G 9HXR1d :RgX ", +"dX9M dkXM& dkX9T 9XgM 9dlX :dlX lHX9d lXg: R29X k2X& kX29B akX92 9XR5 R5:X ", +"R95XB :R5aX 92XM kX&M2 R9TX2 aXM92 95lX l5:X lX95T lsX:5 9XR; X;k& kX;9B ak", +"X9; kX;95 :R>X k;B95X :>RaX XM9; kX;M& kX;9T aXM9; 9Xl; l:>X lX;9T l>Xs: R2", +"9G kX&G2 R9GH2 kX&H2 9GR5 RG:5 R9GH5 :RGH5 R9GM2 kX2GM& R9GT2 aX29GM lGR95 ", +":RGl5 lHX95 :RGs5 9GR; dkX;& kX;9H gR9G; dkX95 >R:G 9G5RH; g:R>X dXM9; kX;d", +"M& XM;9H g9XM; lG;R9 l>G:R lHX9; glX:> kX9P X&kP kXP9B akX9P kXP91 kX:P 9X1", +"kPB :RaXP S9X 9XS& 9TSX 9aSX S9lX S:X Sl9TX sXS: kXP9( kX&+P 9X(kPB 9+XakP ", +"9X1kP( :R+XP kX9P1(B akX:P+ 9XS( 9+SX S9TX( S9+TX Sl9X( :XS+ lXTS9( S:s+X Y", +"9R Yk& R9YH R9Ya R9Y1 Y:R Y9R1H :RYa SY9 Y9S& YZS9 Y9Sa lY9 lY: Y9lZ S:sY R", +"9Yd R9Y+ Y9RHd Y9gR Y9R1d :RY+ R9HY1d gRY: Y9Sd Y9S+ SZ9Yd SYg9 Y9ld l+Y: l", +"YZ9d Y:gl 9XRm Xmk& kXm9B akX9m kXm95 Rm:X kXB95P :RmaX 9XSm S9Xm& S9TXm S9", +"aXm p9lX lX:p Sp9TX :pXSs kXm9; kXm9+ kXB9;P kX&a;P 95Xk;P :>RXm 1;9PkXB :X", +"a>kP 9XS; S9+Xm S9;TX S9aX; Sp9X; >XS: S9TlX; S:>sX R9Ym kmY& Y9RHm Y9aRm R", +"9Y5 :RY5 Y95RH Y:RH5 SmY9 SY9m& SZ9Ym SY9am S9Yp YpS: Yp9lZ lYs:p vRY9 vkY&", +" Yv9RH gY9vR Yv9R1 >kY: Y9HvR1 :vRgY YvS9 Sv9Y+ Sv9YZ gS9Yv Y9lv Y:lv lYvZ9", +" lYy: [k [!k [Dk [ak [1 [18 [1D [1a [kM kM[! V[k Vk[a [l [l8 [lV [sl [k( [+", +"k Dk[( +D[k [1( [1+ 1D[( 1+[a kM[( +k[M [kV( Vk[+ [l( [l+ l(V[ l+[s [Gk Gk[", +"! Jk[ [aJk [1G 1G[8 J1[ [1J8 Gk[M [!GkM V[Jk JkV[a [lG [8lG lJ[ lJ[s [dk +G", +"[k [dJk g[k [1d 1+[d [dJ1 g[1 dk[M [+GkM Vk[d V[gk [ld [+lG V[ld gl[ [k2 k2", +"[! Dk[2 ak[2 [15 5k[8 1D[5 1a[5 kM[2 [!kM2 [kV2 V[ak2 [l5 l5[8 V5[l [5ls [;", +"k +k[; Dk[; ak[; [1; [>1 1D[; [a>k k;[M [+kM; Vk[; V[+k; [l; [>l V[l; l>[s ", +"Gk[2 [!Gk2 [kJ2 Jk[a2 1G[5 [1G58 [1J5 J1[5a [GkM2 GkM[!2 JkV[2 V[aJk2 [5lG ", +"[lG58 J5[l [slJ5 Gk[; [+Gk; [;Jk [;gk 1G[; [d>k [1J; >kg[ [dkM; +Gk[;M Jk;V", +"[ g[Vk; [5ld lG[> J;[l [>gl [kP kP[! Dk[P ak[P [1P 1P[8 1D[P 1a[P S[k [!Sk ", +"SkV[ Sk[a [lS S8[l SV[l [lSs kP[( +k[P [DkP( [+DkP 1P[( 1+[P [1DP( [1+DP [k", +"S( Sk[+ SV[k( SV+[k l(S[ S[l+ SlV[( [slS+ Yk[ [!Yk YJk JkYa Y1[ [1Y8 J1Yk J", +"8Yk YkS[ S[Yk! ]k ]ak lY[ Y8[l ]l ]ls [dYk [+Yk YdJk YJgk [dY1 [1Y+ YJ1[d Y", +"1g[ Sk[d S[+Yk ]dk ]gk S[ld Y+[l ]ld ]lg [mk km[! Dk[m ak[m [1m 1m[8 1D[m 1", +"a[m Sk[m S[km! Vk[m S[akm [pl lp[8 [lVp ls[p km[; +k[m [mDk; [+mDk 1m[; [1>", +"P [1mD; [>1Dm Sk[; S[+km SV;[k S[ak; l;[p l>[p [plV; V>[Sl [mYk Yk[m! JmYk ", +"YJkam [1Y5 Y1[8m J5Yk YJ58k S[Ykm YkmS[! ]km ak]m [plY [plY8 ]lp ls]p [vk [", +"+vk YkJv gk[v [v1 >k[v J1[v g1[v vkS[ [vS+k ]vk gv]k lv[ [>lY ]lv ]yl [t [t", +"& [tD [ct [t1 [: tD[1 [:c [tM tM[& V[t V[tc [lt [:l V[lt u[ [t( t+[ [Dt( t+", +"[c t([1 [:+ [t1D( [+:c [Mt( tM[+ t(V[ V[t+ l([t l+[: [lVt( u[+ tG[ [&tG tJ[", +" [ctJ [1tG [:G [tJ1 :J[ [GtM tG[M& V[tJ tJV[c tG[l lG[: [ltJ uJ[ td[ [+tG [", +"Jtd g[t [1td [:d td[J1 g[: tM[d t+[GM V[td V[gt td[l ld[: lJ[td ug[ [t2 t2[", +"& [Dt2 c2[t t5[ [:5 tD[5 t5[c [Mt2 [tM&2 V2[t [cVt2 t5[l [5l: V[t5 u[5 t;[ ", +"[+t; tD[; t;[c [1t; t>[ t5[D; c>[: tM[; t+[M; V[t; [c;Vt t;[l l>[: [l;Vt u[", +"> [Gt2 tG[&2 t2[J tJ[c2 [5tG [5:G [Jt5 J5[: tG[M2 [&MtG2 tJV[2 [cVtJ2 tG5[l", +" [:lG5 lJ[t5 J5u[ [dt; t+[G; [Jt; t;g[ [5td tG[> tJ5[d t>g[ tG;[M tGM[;& tJ", +";V[ g[tV; [ldt5 [:dl> lJ;[t g[u> tP[ [&tP [DtP tP[c [1tP [:P tP[1D :P[c St[", +" [tS& V[St [cSt [lSt S:[ SlV[t u[S [Pt( [+tP tP[D( tcP[+ tP[1( [+:P [1DtP( ", +"[:c+P S([t t+S[ StV[( St+[c Stl[( S+[: [lVSt( S[u+ tY tY& tYJ tYc tY1 tY: Y", +"1tJ :JtY tYS S&tY ]t ]tc lYt tYS: ]lt ]u tYd tY+ YJtd gtY Y1td t+Y: tYJ1d Y", +":g[ SdtY S+tY ]td ]gt ldtY l+tY lt]d ]ug tm[ [&tm tD[m tm[c [1tm [:m t5[Dm ", +":m[c tmS[ S[&tm V[tm [cmSt tp[ [p: V[tp up[ [mt; [+tm tm[D; [cmt+ t5[;P >P[", +": tmD[1; [:mc> t;S[ St+[m St;V[ Sc;[t t;[p [pt> tp[V; S>u[ tYm Y&tm YJtm tm", +"Yc tY5 t5Y: YJt5 t5Yc tmSY tYSm& ]tm tc]m tpY Y:tp ]pt ]up tYv t+[v tJ[v tv", +"g[ t5[v tY> [v1tJ Yct> St[v [v&St ]tv gt]v tYlv tYS> lv]t ]yu Xe Xe! XeB aX", +"e Xe. 8Xe e.XB aX8e XeK X!eK TXe aXTe Xje Xj8e XjTe sXe X* +Xe X*B aX* X*. ", +"8X* X.*B aX8* X*K +KX* TX* TX+e X*j X*+j XjT* sX* GXe XeG! HXe aXHe XeG. GX", +"8e XeH. 8XHe XeGK GXe!K TXHe aXeGT GXej XjeG8 XjHe HXse fX f+X fHX gfX fX. ", +"f8X HXf. f8gX fXK +XfK fTX fTgX fjX +Xfj HXfj sfX Xe2 X!e2 e2XB X2ae 5Xe 8X", +"5e Xe5B aX5e e2XK Xe2!K XeT2 aXeT2 Xj5e Xje58 TX5e 5Xse X;e X;+e *BX; X;ae ", +"5X* >Xe *B5X aX>e XKe; X;e+K X;Te aX;Te Xj5* X*>j TX5* sX>e XeG2 GXe!2 XeH2", +" aXeG2 GX5e G58Xe 5XHe G5aXe GXe2K Xe2GK! GTXe2 GTXae2 XjeG5 G58Xje G5TXe s", +"X5He fX; +Xf; HXf; fXg; f5X f>X H5fX gf>X X;fK f+X;K TXf; fTXg; 5Xfj fj>X 5", +"TfX >Xsf eP eP! ePB aeP eP. 8eP P.eB ae8P QXe Q!eP TeP aXQe ePj 8XQe ejTP s", +"eP X*P +eP *BeP ae+P X.P* 8e+P X*P.B aX*8P QX* QX+e TXQ* Te+P XjQ* 8XQ* X*j", +"TP +esP Ye Ye! YHe Yae Ye. Y8e HeY. H8Ye YQe QeY! YZe ZeYa Yje Q8Ye ZeYj sY", +"e Yf Yf+ YfH gYf Yf. Yf8 fHY. Y8gf YfQ fQY+ ZfY ZfgY Yfj fQY8 YjZf sYf Xme ", +"X!em XBem Xmae 5eP 8e5P 5BeP ae5P XmQe XmeQ! XmTe aXmQe pXe 8Xpe TXpe pXse ", +"Xm* Xm+e *BXm Xma* Xm5* >eP Xm*5B ae>P XmQ* Xm*+Q XmT* aXmQ* pX* pX>e TXp* ", +"se>P Yem emY! HeYm aeYm Y5e 5eY8 H5Ye 5aYe QeYm YQem! YmZe YZaem Ype peY8 Z", +"eYp seYp Yfv fvY+ YHfv Yfgv Yf5 Y>f YHf5 f>gY fQYv Yfv+Q YvZf gYZfv fpY fpY", +"> ZfYp yYf ,X ,X& ,XB ,aX ,X. ,8X X.,B 8X,a ,XK ,KX& ,TX TX,a ,Xj 8X,j TX,j", +" sX, ,X* -X *B,X -Xa ,.X* -X8 X*.,B 8X-a ,KX* -XK T*,X -TX X*,j -Xj X*j,T s", +"-X ,GX G&,X ,HX Ga,X GX,. G8,X ,.HX H8,X GX,K X&K,G GT,X ,GTaX Gj,X X&j,G H", +"X,j ,GsX fX, f-X ,HfX g-X ,Xf. -Xf8 fHX,. g8-X ,XfK fK-X ,TfX -TgX ,Xfj -Xf", +"j fTX,j gXs- ,X2 ,2X& X2,B ,2aX ,5X 5X,8 ,B5X 5a,X X2,K X&2,K ,2TX ,TX&2 5X", +",j X&j,5 5T,X ,5sX ,X; -X; ,BX; aX-; 5X,; >X- ,5X*B -a>X ,KX; X;-K TX,; TX-", +"; X;,j -j>X X;j,T >Xs- GX,2 X&2,G ,2HX ,GaX2 G5,X ,G58X H5,X ,G5aX ,GX2K ,G", +"2X&K ,GTX2 aX2,GT ,G5Xj ,G5X&j ,G5TX sX,G5 ,Xf; f;-X HX,; g;-X ,5fX f->X f5", +"H,X g->X fX;,K f-X;K fTX,; f-TX; f5X,j f>-Xj f5T,X s-Xf> ,XP eP& ,BeP aX,P ", +",.eP 8X,P eP.,B aeP,8 ,QX Q&,X QX,T Qa,X QX,j Q8,X ePj,T ,QsX X*,P -XP X*P,", +"B aX-P X*P,. 8X-P ,X.P*B -X8aP Q*,X -QX ,QXT* Qa-X X*j,Q Q8-X ,TXP*j -QsX Y", +", Y&e Y,H Ya, Y,. Y8, ,HY. ,HY8 Y,Q ,QY& YZ, ZeY& Yj, ,QY8 Z,Yj sY, Yf, Y- ", +"fHY, Y-g f,Y. Y-8 YfH,. Y8g- fQY, Y-Q Y,Zf Y-Z fjY, Y-j YZ,fj sY- ,Xm X&,m ", +",BXm aX,m 5X,m 8X,m ,5XmB aXm,5 QX,m Xm&,Q TX,m aXm,Q pX, ,8pX ,TpX pXs, Xm", +",; -Xm Xm*,B aX-m Xm*,5 -X>P X;B,5P >X-am QX,; QX-m Xm*,T TX-m ,Xp* -pX pX*", +",T sX-p Y,m ,mY& ,HYm ,aYm Y5, ,5Y8 ,HY5 ,5Ya ,QYm Y&Q,m YmZ, YZ&,m Yp, peY", +"& ZpY, s,Yp Yv, Y-v YHv, -vgY f5Y, Y-> Yf5,H g-Y> YQv, -QYv ZvY, YZ-v Y,fp ", +"Y-p fpZY, yY- IXe I!Xe DXe aXDe XeI. IX8e XeD. 8XDe XeIK IXe!K TXDe aXeTI I", +"Xej IjX8e XjDe DXse I*X I*+X DX* DX+e I.X* I*8X D.X* 8XD* IKX* I*X+K TXD* a", +"X*TI X*Ij I*j+X X*Dj DXs* IXGe GIXe! JXe aXJe GIXe. G8IXe XeJ. 8XJe GIXeK I", +"XeGK! TXJe JTaXe IjXGe G8IXje XjJe JXse fIX +IfX JfX JfgX IXf. 8IfX fXJ. JX", +"f8 IXfK f+IXK JXfT JfTgX IjfX f8IXj JXfj JfsX XeI2 IXe!2 XeD2 aXeI2 IX5e 5I", +"8Xe DX5e 5DX8e IXe2K Xe2IK! DXTe2 DXTae2 IjX5e 5I8Xje 5DXTe sI5Xe X;I* I;X+", +"e X;De aX;De I*5X I*>X DX5* DX>e I;XeK +IXe;K DX;Te DX;+Te I;jX* >IjX* X;jD", +"e sI*>X GIXe2 IXeG2! XeJ2 JaXe2 G5IXe 5IXG8e 5XJe J58Xe IXeG2K I!X2GeK JTXe", +"2 aXeJT2 G5IXje 8eGj5IX J5TXe sJ5Xe I;fX f+IX; fXJ; JfXg; 5IfX fI>X JXf5 Jf", +">X fIX;K I;Xf+K JfTX; fTXgJ; f5IXj f>IXj Jf5TX J>sfX IPe I!eP DeP aeDP I.eP", +" IP8e D.eP 8eDP IPQe IPeQ! DXQe aePQD ePIj IPj8e ePDj DesP IP* IP+e IPD* De", +"+P I.P* IP8* IP*D. aP*8I IPQ* IP*+Q DXQ* aX*QD P*Ij IP*+j IP*Dj IPs* YIe Ie", +"Y! YJe JaYe IeY. 8IYe JeY. YeJ8 QIYe YQIe! ZeYJ YZJae IjYe Y8QIe YeJj YJse ", +"YfI f+YI YJf YJgf fIY. YIf8 Y.Jf JfY8 YIfQ Yf+QI YJZf gYZJf YIfj Yf8QI JfYj", +" YJsf emIP ImXe! XmDe aXmDe IP5e 5IP8e De5P aeP5D ImXQe QIXem! QDXem QDXaem", +" IPpe pI8eP DXpe sIPpe XmI* Im*+X XmD* aXmD* IP5* IP>e IP*5D De>P Im*QX +QI", +"Xm* Im*TX +QDXm* IPp* >XpI* DXp* sIP>e ImYe YIem! YeJm YJaem 5IYe Y58Ie YeJ", +"5 YJ58e YQIem ImeYQ! YZJem ZJeYam YIpe Yp8Ie peYJ JpsYe vIYf Yfv+I YfJv gYJ", +"fv YIf5 >IYf JfY5 YJf> YfvQI fvQY+I YZvJf ZfJgYv pIYf fpY>I YJfp YJyf hX hX", +"& hDX hcX hX. h8X DXh. cXh8 hXK X&hK hTX cXhT hjX 8Xhj DXhj hsX hX* h-X DXh", +"* c-X X*h. -Xh8 hDX*. c8-X X*hK hK-X TXh* -TcX X*hj -Xhj hTX*j sXh- hGX G&h", +"X hJX cXhJ GXh. G8hX JXh. hXJ8 GXhK hGX&K JThX cJThX GjhX h8GXj hXJj sXhJ h", +"fX -Xhf hXJf iX fXh. hXf8 JfXh. i8X fXhK f-XhK hXfT iTX hXfj f-jhX JfjhX is", +"X hX2 X&h2 DXh2 h2cX h5X 5Xh8 5DhX cXh5 X2hK hX&2K TXh2 cXTh2 5Xhj h58Xj 5T", +"hX sXh5 h;X -Xh; DXh; cXh; 5Xh; h>X h5DX; hc>X X;hK -X;hK TXh; c-XT; X;hj h", +"j>X h5TX; >Xhs GXh2 hGX&2 JXh2 cJXh2 G5hX h5G8X hXJ5 cJ5hX hGX2K X&2hGK hJT", +"X2 hJTcX2 h5GXj X&jh5G hJ5TX hsJ5X fXh; f-Xh; hXJ; iX; hXf5 hf>X Jf5hX i>X ", +"hfX;K hf;-XK hJ;TX TXi; hf5Xj h>fXj J;jhX >Xis hP hP& hPD hcP hP. h8P DPh. ", +"cPh8 hQX QXh& hTP cQhP hPj Q8hP DPhj hsP hP* h-P DPh* c-hP P*h. -Ph8 hPD*. ", +"c-X8P QXh* -QhP TPh* -QcX P*hj -Phj hTP*j hPs- hY hY& hYJ Ych hY. hY8 h.YJ ", +"h8Yc hYQ Y&hQ hZY YchZ hYj Y8hQ YZhj hsY hYf Y-h YJhf iY h.Yf h8Y- hYJf. iY", +"8 YfhQ hQY- ZfhY iZY Yfhj hjY- hYjZf isY hmX Xmh& DXhm cXhm h5P 5Ph8 5DhP c", +"5hP QXhm hQXm& TXhm cQXhm hpX pXh8 pDhP hPcp h;P -Xhm D;hP c;hP 5Ph; h>P h5", +"PD; hc>P QXh; -QXhm T;hP c-QXm pXh; >Xhp hpDX; >Phs hYm Y&hm YJhm hmYc hY5 ", +"Y5h8 YJh5 h5Yc YQhm hYQm& YZhm hZYcm hpY h8Yp hYJp sYhp hvY Y-hv JvhY iYv Y", +"fh5 h>Y hY5Jv iY> YvhQ hvY-Q YZhv YZiv hYfp Y-hp JpfhY yiY Xe0 X!e0 e0XB Xe", +"a0 1Xe 8X1e Xe1B aX1e e0XK Xe0!K XeT0 aXeT0 Xj1e Xje18 TX1e 1Xse X*0 +0X* X", +"0*B a0X* 1X* +X1e *B1X aX1* *0XK X*0+K T0X* aX*T0 Xj1* X*j1+ TX1* 1Xs* XeG0", +" GXe!0 XeH0 aXeG0 GX1e 1G8Xe HX1e 1GaXe GXe0K Xe0GK! GTXe0 GTXae0 Xje1G 1G8", +"Xje 1GTXe sX1He fX0 +Xf0 HXf0 fXg0 f1X 1+fX 1HfX f1gX X0fK f+X0K TXf0 fTXg0", +" 1Xfj f1+Xj 1TfX f1sX e0X2 Xe0!2 Xe02B aXe02 5X1e 1X58e 1X5eB 1aX5e Xe02K e", +"02XK! TXe02 TX0ae2 Xje15 5X81ej 1TX5e sX15e X0e; X;e+0 X;e0B aX;e0 5X1* 1X>", +"e 1X;*B >X1ae X;e0K +X0e;K TX;e0 aX0Te; X;j1e >X1ej 1TX5* sX*>1 GXe02 Xe0G2", +"! HXe02 HX0ae2 1G5Xe G581Xe 1HX5e H5X1ae Xe0G2K 2Ke!GX0 TX0He2 aXHeT02 1G5X", +"je 8eGj1X5 H5X1Te 1HXse5 X;f0 f+X;0 fHX;0 gfX;0 1Xf5 f1>X f1H5X f>g1X fX;0K", +" X;0f+K fTX;0 gX;fT0 f15Xj f>1Xj f1T5X sf>1X eP0 P!e0 P0eB a0eP 1eP 8e1P 1B", +"eP ae1P Q0eP eP0Q! T0eP aePQ0 QX1e ePj18 Te1P 1esP X0P* +0eP X*P0B aX*P0 X*", +"1P +e1P 1X*PB aX*1P Q0X* +QXe0 QX*T0 aX*Q0 QX1* ePj1+ 1QXT* sX*1Q Ye0 e0Y! ", +"HeY0 aeY0 Y1e 1eY8 1HYe 1aYe QeY0 YQe!0 Y0Ze YZae0 1QYe Y1Q8e ZeY1 Y1se Yf0", +" f+Y0 fHY0 g0Yf Yf1 f1Y+ YHf1 Yfg1 Y0fQ Yf+Q0 Y0Zf gYZf0 f1Yj Yf1+Q Y1Zf Y1", +"sf X0em Xme!0 Xme0B aXme0 5e1P 1Xm8e 1XmeB aXm1e XmeQ0 QX0em! TXme0 aX0Tem ", +"1Xpe pX18e pX1Te sePp1 X0m* Xm*+0 Xm*0B aXm*0 Xm1* 1e>P Xm*1B >eP1a Xm*Q0 X", +"m0+Qe Xm*T0 aX0Qe; 1Xp* >Xp1e pX*1T sX*p1 emY0 Yem!0 YHem0 Yaem0 1eY5 Y158e", +" Y1H5e Y1a5e YQem0 em0YQ! YZem0 ZemYa0 peY1 Yp18e YZ1pe sYp1e Y0fv Yfv+0 Yf", +"vH0 gYfv0 fvY1 Y1f> Yf1vH gY1f> YfvQ0 fvQY+0 YZvf0 ZfvgY0 Y1fp fpY>1 fpZY1 ", +"Yfy1 ,X9 X&9e ,B9X 9a,X ,1X :Xe ,B1X ,a:X ,K9X X&K9e 9T,X ,TX9a 9X,j ,X:j 1", +"T,X :Xse 9X* -X9 *B9X 9a-X 1X9* :-X ,1X*B :a-X 9KX* 9X-K TX9* 9T-X X*9j -j:", +"X X*j9T :-sX 9G,X ,G9X& 9H,X ,Ga9X 1G,X ,G:X 1H,X ,H:X ,G9XK ,G9X&K ,GT9X 9", +"GT,aX ,1GXj :GX,j ,1GTX sX,:G f9X -Xf9 9HfX f9gX ,1fX :fX f91HX gX:f 9XfK f", +"-9XK 9TfX f-T9X 9Xfj fj:X f9T1X sX:f ,29X X&29e ,X92B ,aX92 95,X ,5:X ,1X5B", +" :X5,a ,X92K 9X2e&K ,TX92 aX29Te ,1X5j :X5,j ,1T5X sX,:5 9X,; 9X-; ,X;9B -X", +"9a; 1X,; :->X ,1X;B :-X>a ,X;9K -X9;K ,TX9; -TX9; X;j,1 :-X>j ,1TX; s-X:> ,", +"G9X2 ,G9X&2 ,HX92 aX29He ,1G5X :G5,X ,1H5X :HX,5 9G2,XK X&9eG2K ,G29TX ,2GT", +"9aX 9G5,Xj ,G5:Xj 9G5,TX sX5:He 9Xf; f-9X; f9HX; gf9X; 95fX >X:f f95HX g:Xf", +"> f9X;K -X;f9K f9TX; f9;-TX f95Xj :f>Xj f95TX sf:>X 9eP e&9P 9BeP ae9P 1X,P", +" :eP ,1XPB ae:P 9Q,X eP&9Q Te9P aeP9Q 1Q,X ,Q:X ePj9T :esP X*9P 9X-P 9X*PB ", +"-X9aP ,1XP* -X:P X*B,1P :-XaP QX9* 9Q-X 9QXT* -QX9T X*j9Q -Q:X 9TXP*j s-X:Q", +" Y9e 9eY& ,HY9 ,aY9 Y1, Y:e ,1YH :HY, ,QY9 Y9Qe& Z9Y, YZ9,a ,1Yj :QY, Z1Y, ", +"seY: Yf9 Y-9 YHf9 g9Y- f9Y1 Y:f Yf91H gY:f fQY9 -QY9 Y9Zf Y9Z- f9Yj Yj:f Zf", +"9Y1 Y:sf 9X,m Xm&9e ,Xm9B aXm9e 1X,m ,X:m ,1XmB :Xm,a ,QX9m 9QXem& ,TX9m 9Q", +"a,Xm ,1pX pX:e p9X,T :pXse Xm9* 9X-m Xm*9B -Xm9a Xm*,1 :e>P XmB,1; :-Xam Xm", +"*9Q -QX9m Xm*9T -TX9m 9Xp* :X-p p9XT* -pXs: ,mY9 Y9em& Y9H,m Y9a,m ,1Y5 :eY", +"5 Y95,H Y:H,5 Y9Q,m em&Y9Q YZ9,m Y9mZe& p9Y, Y,:p Yp9Ze sY:pe fvY9 Y9-v Yf9", +"vH gY9-v f9Y5 :fY> Yf9H5 Y:gf> Yf9vQ Y-v9Q Zf9Yv Y-Zv9 Y9fp fpY: fp9YZ Y:yf", +" XeI0 IXe!0 XeD0 aXeD0 IX1e 1I8Xe DX1e 1DX8e IXe0K Xe0IK! DXTe0 DXTae0 IjX1", +"e 1I8Xje 1DXTe sI1Xe I0X* I*X+0 D0X* aX*D0 I*1X 1+IX* DX1* aX*1D I*X0K +I0X", +"*K DX*T0 aX0TI* I*j1X 1+IX*j X*j1D sI*1X GIXe0 IXeG0! XeJ0 JaXe0 1GIXe G8I1", +"Xe 1XJe J18Xe IXeG0K I!XKGe0 JTXe0 aXeJT0 1GIXje 8eGj1IX J1TXe sJ1Xe IXf0 f", +"+IX0 fXJ0 JfXg0 1IfX f1+IX JXf1 Jf1gX fIX0K +IXf0K JfTX0 fTXgJ0 f1IXj 1+Ifj", +"X Jf1TX sfJ1X IXe02 Xe0I2! DXe02 DX0ae2 1I5Xe 5I81Xe 1DX5e 5DX1ae Xe0I2K I!", +"X2e0K TX0De2 aXDeT02 1I5Xje 8X5e1Ij 5DX1Te 1DXse5 I;Xe0 +IXe;0 DX;e0 aX0De;", +" 1I;X* >I1X* 1DX5* >XD1e X;0I*K +KI;X*0 I;0TX* X;De+T0 1I;X*j I*j>X1 1DXe;j", +" >I1sX* IXeG02 I!X2Ge0 JXe02 aXeJ02 G5I1Xe 8X5e1GI J15Xe 1aXJ5e IXG0e2K IXG", +"02Ke! TXeJ02 aXJeT02 Ij1XG5e GX8e15Ij 1TXJ5e J15sXe fIX;0 I;Xf+0 JfX;0 gfXJ", +";0 f15IX f>1IX Jf15X J>f1X I;Xf0K I;fX+0K fTXJ;0 X;g0JfT I;jf1X f1I>Xj J1Xf", +"5T sf1J>X I0eP IPe!0 D0eP aePD0 IP1e 1IP8e De1P aeP1D IPeQ0 QI0eP! QDXe0 aX", +"0QDe IPj1e Q8I1eP ePj1D sIP1e I0P* IP*+0 IP*D0 aP*I0 IP1* IP*1+ IP*1D aP*1I", +" IP*Q0 IP0+Qe IP*T0 aX0QD* IP*1Q 1+QIP* IP*1T sIP1* IeY0 YIe!0 JeY0 YJae0 1", +"IYe Y18Ie YeJ1 YJ18e YQIe0 QIeY0! YZJe0 ZJeYa0 Y1QIe 1QIY8e YZ1Je sYJ1e fIY", +"0 Yf+I0 Y0Jf gYJf0 YIf1 Yf1+I JfY1 gY1Jf YfQI0 fQIY+0 YJfZ0 ZfJgY0 Yf1QI Y1", +"IfQ8 Zf1YJ sYfJ1 ImXe0 em0IP! DXme0 aX0Dem 1ImeP 8Im1eP 1DXem 1DXaem QIXem0", +" ImQXe0! Im0TeP aXQeIm0 pI1eP 1IPpe8 pDX1e sX1pDe Im*X0 Im0+eP Xm*D0 aX0Im*", +" Im*1X >eP1I Xm*1D >eD1P Im0QX* Im+XQe0 Im0TX* XmD*+Q0 pI*1X >I1pX* pDX1* >", +"I1seP YIem0 ImeY0! YJem0 JmeYa0 Y15Ie 1ImY8e YJ15e Y1eJ8m ImeYQ0 QmY0Ie! Ze", +"mYJ0 aeJmYZ0 Yp1Ie pI8Y1e JpY1e sY1Jpe YfvI0 fvIY+0 YJfv0 JvfgY0 Yf1vI Y>f1", +"I Jv1Yf Y>Jf1 fQIYv0 YQvIf+0 JvYZf0 gJZfYv0 fpY1I Y>1fpI JpfY1 yJYf1 h9X 9X", +"h& 9DhX h9cX h1X h:X 1DhX :Xhc 9XhK h9X&K 9ThX cX9hT 9Xhj :Xhj 1ThX sXh: 9X", +"h* h9-X DX9* c9-X 1Xh* :Xh- h1DX* c-:X h9X*K -X9hK hT9X* c-X9T h1X*j h:-Xj ", +"h1TX* s-Xh: 9GhX h9GX& hXJ9 cJ9hX 1GhX hG:X hXJ1 :XhJ h9GXK X&Kh9G J9ThX hJ", +"9cXT h1GXj h:GXj J9jhX hsJ:X hXf9 f-9hX JXf9 i9X hXf1 :Xhf Jf91X i:X f9XhK ", +"hf9-XK Jf9TX 9TiX f9jhX :fhXj Jf9Xj s:iX 9Xh2 h9X&2 h9DX2 cX9h2 95hX :Xh5 h", +"15DX h:c5X h9X2K X&2h9K hT9X2 hT9cX2 h15Xj h:5Xj h1T5X hs:5X 9Xh; -X9h; h;9", +"DX c-X9; 1Xh; >Xh: h1;DX c>Xh: h;9XK h;9-XK hT;9X cX9hT; h1;Xj h>:Xj h1TX; ", +"hs>:X h9GX2 X&2h9G J9Xh2 hJ9cX2 h1G5X h:G5X J95hX :Jh5X 9GXh2K X&h29GK hTXJ", +"92 h9cXJT2 9G5hjX h5G:Xj J9Xh5T :J5hsX f9Xh; hf9-X; Jf9X; 9Xi; f95hX h>:fX ", +"Jf95X >Xi: h;Xf9K h9-Xf;K J9XhT; i9;TX f9Xh;j :fXh>j J9Xf5T is:>X hP9 9Ph& ", +"9DhP h9cP h1P h:P 1DhP :chP 9QhP hQ9X& 9ThP cQXh9 9Phj :QhP 1ThP s:hP 9Ph* ", +"h9-P hP9D* c-X9P 1Ph* :-hP h1PD* h:Pc- hQ9X* -QXh9 hTP9* c-Q9X h1QX* h:Q-X ", +"h1TP* hsP:- hY9 h9Y& Y9hJ Y9hc hY1 Y:h YJh1 hY:J Y9hQ hY9Q& Y9hZ hZYc9 Y9hj", +" hQY: YZh1 Y:hZ Y9hf Y9h- JfY9 iY9 Yfh1 hY:f hY1Jf iY: hYf9Q Y-h9Q Zf9hY YZ", +"i9 hY1fQ Y:hfQ hZ1Yf sYi: 9Xhm hm9X& hm9DX cXmh9 95hP :Xhm h1mDX h:mcX hQ9X", +"m Xm&hQ9 hTm9X cX9hTm p9hP hP:p hp9DX cpXh: 9;hP -Xmh9 h;P9D c-X9m 1;hP >Ph", +": h1;DP h>P:c hQ;9X -Q9h;P hT;9P cQ9-Xm hp9X; -pXh: p9DX* cp-:X Y9hm hY9m& ", +"hYJ9m Ych9m Y9h5 h5Y: hY1J5 Y:Jh5 hY9Qm hQ9Y&m hZY9m Yc9hZm h1Yp Y:hp Jp9hY", +" hZ:Yp Y9hv hvY-9 Jv9hY Yvi9 Yvh1 Y:hv hv1YJ Y:iv hvY9Q Y-9hvQ hZvY9 iZYv9 ", +"fp9hY hv:Yp JpfY9 yYi: Re Re! ReB Rae Re. R8e e.RB 8eRa ReM R!Me RTe TeRa R", +"ej 8MRe TeRj sRe Re* R+e *BRe +eRa R.X* +eR8 X*.RB aX*R8 XM* +MRe TXR* +TRe", +" X*Rj +eRj XM*Tj R+se RGe GeR! RHe GaRe GeR. G8Re R.He H8Re GMRe XM!Ge GTRe", +" aXMHe GjRe RG8Me HeRj RGse fR fR+ fRH gfR fR. fR8 RHf. f8gR fRM R+fM fRT f", +"RgM fRj R+fj RHfj sfR Re2 e2R! e2RB R2ae R5e 5eR8 RB5e 5aRe R2Me XM2e! R2Te", +" aXMe2 5MRe R5e8M 5TRe R5se Re; +eR; RBe; aeR; 5XR* >eR R5e*B Ra>e MeR; XM;", +"+e TeR; aXMe; XM5* Re>M XM*5T sR>e GeR2 RGe!2 R2He RGae2 G5Re RG58e H5Re RG", +"5ae XM2Ge RG2Me! RGTe2 aX2HMe RG5Me G5MR8e RG5Te sRG5e fR; R+f; RHf; g;fR f", +"R5 f>R RHf5 gRf> R;fM fR+M; RTf; fRTg; R5fM fR>M R5fT sRf> ReP R!eP RBeP aP", +"Re R.eP 8PRe eP.RB aePR8 Se Se! SeT Sae Sej S8e TeSj Sse ePR* +PRe X*PRB aX", +"*RP X*PR. R+e8P Re.P*B R8eaP* Se* S+e TXS* +TSe X*Sj +eS8 SeT*j S+se YRe Re", +"Y! RHYe RaYe ReY. R8Ye YRHe. Y8RHe SYe YeS! SZe YaSe YjSe Y8Se SjZe seSZ Yf", +"R fRY+ YHfR YfgR Y.fR fRY8 YfRH. gYfR8 Sf Sf+ SfZ gSf Sfj Sf8 fjSZ sfS Rem ", +"R!em RBem aeRm 5eRm 8eRm R5emB aemR5 Sem emS! TeSm aeSm Spe peS8 STpe seSp ", +"XmR* +eRm Xm*RB aXmR* Xm*R5 Re>P XmBR5* >eRam Se; +eS; TeS; aeS; pXS* S>e S", +"peT; >eSs ReYm YRem! HeRm YaRem R5Ye Y5R8e Y5RHe Y5aRe YeSm SYem! SmZe SZea", +"m SeYp SpeY8 ZpSe SseYp fvR f+vR fHvR fvgR fRY5 fRY> Yf5RH f>RgY Sfv fvS+ Z", +"fSv gfSv Sfp Sf> SZfp yfS ,RX Re& RB,X Ra,X ,.Re R8,X ,RX.B ,R8aX ,XM X&,M ", +"RT,X TeR& Re,j 8X,M ,RTXj ,RsX R*,X -RX X*B,R Ra-X X*.,R R8-X ,R.X*B -R8aX ", +"X*,M -XM XM*,T RT-X XM*,j Re-j ,RTX*j -RsX ,RG R&,G RG,H RG,a ,.RG RG,8 ,RG", +"H. ,RGH8 RG,M XM&,G RG,T aXM,G RG,j e&jRG ,RGHj ,RsG fR, f-R ,RfH f-gR ,Rf.", +" -Rf8 fRH,. f-Rg8 ,RfM -RfM ,RfT -RfT ,Rfj -Rfj fRT,j f-sR ,2Re R2e& ,RX2B ", +",RaX2 R5,X 5eR& ,R5XB ,R5aX ,2XM XM&,2 ,RTX2 aXM,2 5X,M XM&,5 ,R5TX sX,R5 R", +"e,; Re-; ,R;XB -RaX; ,R5X; -R>X X;B,R5 >X-Ra XM,; XM-; XM;,T -RTX; XM;,5 -X", +">M ,RTX;j s-R>X ,2RG ,RG&2 ,RGH2 ,RGa2 RG,5 ,RG5& ,RGH5 ,RG5a ,RGM2 X&2,GM ", +",RGT2 aX2,GM ,RG5M ,G5XM& ,RG5T sRG,5 ,Rf; f;-R fRH,; f-Rg; ,Rf5 ->fR fR5,H", +" f>Rg- fRM,; f-RM; fRT,; f-RT; fR5,M f>R-M fR5,T sfR-> Re,P ePR& ePB,R aeP,", +"R eP.,R eP&R8 ,R.ePB ,R8aeP Se, Se& ,TSe ,aSe ,XSj ,8Se SeT,j Ses, X*P,R Re", +"-P ,RXP*B -RaeP ,RXP*. -R8eP ePR*,.B aeP-R8 ,XS* S-X SeT,* -TSe Se*,j -XS8 ", +"X*jS,T sXS- Y,R ,RY& ,RYH ,RYa ,RY. ,RY8 Y,RH. Y8,RH SY, Y&Se YZS, YaS, YjS", +", Y8S, SZe,j SYs, fRY, Y-R YfR,H gRY- YfR,. -RY8 fRHY,. Y-gR8 Sf, Sf- S,Zf ", +"Y-gS fjS, S8Y- SfZ,j S-sY Re,m emR& ,RmXB aXm,R ,R5Xm em&R5 XmB,R5 ,R5aXm ,", +"XSm emS& SeT,m Sae,m pXS, peS& Spe,T Ssep& Xm*,R Re-m XmB,R; -RmaX ,R5Xm* >", +"X-Rm Xm,;R5B >Xa-Rm ,XS; -XS; Se;,T S-TXm Spe,; >XS- S;TpX, -pXSs ,RYm Y&R,", +"m Y,RHm Ya,Rm ,RY5 Y5&,R Y5,RH Y5a,R SmY, SY&,m SZe,m SZem& S,Yp Yp&Se Yp,S", +"Z sY,Sp vRY, fR-v Yv,RH -vRgY Yf5,R -RY> Y5HvR, Y->gR YvS, SvY- Sv,Zf gSf-v", +" S,fp Y-S> SfpZ, Sfy- [e [!e [De [ae [e. [8e De[. D8[e [Me Me[! V[e [aVe [j", +"e 8M[e [jVe [se [* [+e [*D [a* [*. [8* D*[. D8[* [*M +M[* V[* [+Ve [*j +e[j", +" [jV* [s* [Ge Ge[! [Je Je[a Ge[. G8[e [eJ. Je[8 GM[e [!GMe [JVe VJ[ae Gj[e ", +"[8GMe Je[j [Jse [f [f+ [fJ g[f [f. [f8 J.[f J8[f [fM [+fM Vf[ Vfg[ [fj [+fj", +" Jj[f sf[ [e2 e2[! De[2 ae[2 [5e 5e[8 5D[e 5a[e Me[2 [!Me2 [eV2 V[ae2 5M[e ", +"[58Me [5Ve [5se [;e +e[; De[; ae[; [5* [>e 5D[* [a>e Me[; [+Me; [;Ve V[+e; ", +"5M[* [*>M [5V* >e[s Ge[2 [!Ge2 [eJ2 [Jae2 G5[e [5G8e Je[5 J5[8e [GMe2 Me2[!", +"G VJ[e2 [JaVe2 [5GMe G5M[8e J5V[e [sJ5e [f; f+[; J;[f [;gf [f5 [>f J5[f f>g", +"[ [;fM [f+M; V;[f Vfg[; [5fM >M[f V[f5 [>sf [eP eP[! De[P ae[P eP[. 8e[P [D", +"eP. [8DeP S[e [!Se SVe VeSa [jSe [8Se SjVe SVse [*P +e[P DP[* aP[* P*[. 8P[", +"* [*DP. [8*DP S[* [+Se V[S* V+Se [jS* [8S* SVe*j s*S[ [Ye Ye[! Ye[J Ye[a [e", +"Y. Ye[8 YJ[e. YJ8[e [YSe S[Ye! ]e ]ae Ye[j S[8Ye ]je ]se [fY Y+[f YJ[f [fgY", +" Y.[f Y8[f YJf[. g[Yf8 Sf[ S+[f ]f ]gf Yj[f S8[f ]fj ]sf [me em[! De[m ae[m", +" 5e[m 8e[m [5Dem [5aem [mSe S[em! VmSe SVeam [pe [8pe SeVp se[p [m* +e[m Dm", +"[* am[* 5P[* [m>e [5*Dm [>Dem [mS* S[+em VeS; SV+em [p* >e[p V*[p SV>e Ye[m", +" [Yem! Je[m Ya[em Ye[5 Y5[8e YJ5[e Y5[ae S[Yem [YmSe! ]em ae]m [Ype [pY8e ]", +"pe sp]e [vf [+fv [fJv gf[v Y5[f f>[v [vJf5 [>fgY [vSf [vfS+ ]fv gf]v fp[ [>", +"Sf ]pf ]yf [h [h& [hD [ch [h. h8[ [Dh. h8[c hM[ [&hM Vh[ [cVh hj[ [8hM V[hj", +" hs[ [h* [- hD[* [-c h.[* [-8 [hD*. [8c- [*hM [-M [hV* V-[ [*hj [-j Vh[*j [", +"s- [hG hG[& hJ[ hJ[c [Gh. hG[8 h.[J [Jh8 [GhM [hGM& V[hJ VhJ[c hG[j h8[GM [", +"Jhj hJ[s [fh [-f hJ[f i[ h.[f h8[f [fJh. i[8 hM[f fM[- [fVh iV[ hj[f fj[- V", +"f[hj i[s [h2 h2[& [Dh2 h2[c h5[ [5h8 hD[5 h5[c [Mh2 [h&M2 h2V[ Vh[c2 [5hM h", +"5[8M V[h5 h5[s h;[ [-; hD[; h;[c [5h; h>[ h5[D; c>[- [;hM [;-M V[h; V;[- [;", +"hj >M[- Vh5[; [sh> [Gh2 [hG&2 h2[J [cJh2 hG[5 h5[G8 [Jh5 [c5hJ [hGM2 [&GhM2", +" VhJ[2 [cJVh2 h5[GM h5G[&j Vh5[J hs[J5 h;[f [;f- [Jh; i[; h5[f f>[- [f5hJ i", +"[> [fhM; [-fM; Vf[h; V[i; [f5hM [-jf> Vf5[h V>i[ hP[ [&hP [DhP hP[c [Ph. [8", +"hP [hDP. [ch8P Sh Sh& ShV Shc Shj Sh8 SVhj hsS [*hP [-P [hDP* cP[- [h*P. [8", +"-P [*DhP. [-c8P Sh* Sh- S*Vh V-Sh S*hj h8S- ShV*j S-hs hY[ [hY& [JhY [chY h", +".[Y [hY8 hYJ[. hY8[c ShY S&hY ]h ]hc SYhj SYh8 ]hj ]hs [fhY Y-[ hYJ[f i[Y h", +"Y[f. Y8[- [fJhY. Y8i[ Shf Y-Sh ]hf ]i hjSf h8Sf hf]j ]is hm[ [&hm hD[m hm[c", +" [5hm [8hm h5[Dm [c5hm Shm S&hm SVhm hmSc hp[ h8[p VpSh Schp [mh; [-m hm[D;", +" cm[- h5[m* >P[- h5D[m* [-mc> Sh; hmS- SVh; h;Sc h;[p h>S [p*Vh Sch> [Yhm h", +"Y[m& [Jhm [cmhY [hY5 hY5[8 hY5[J Yc5[h SYhm ShYm& ]hm hc]m hY[p [p&hY ]ph h", +"p]s hv[ [-v hJ[v i[v h5[v [-Y> hv[J5 Y>i[ hvS S-hv ]hv ]iv Sfhp Sfh> hp]f ]", +"yi Rek R!ke RBke akRe R1e 1eR8 RB1e 1aRe XMke kXMe! TkRe akXTe lXe R8le RTl", +"e sRle kX* +kRe *BkX kXa* 1XR* 1+Re kX*1B akX1* XMk* kX*+M kXT* akXT* lX* R", +"+le TXl* sXl* GkRe kX!Ge HkRe akXHe 1GRe R1G8e 1HRe R1Gae kXMGe RGkMe! RGTk", +"e RGTake RGle lGR8e RHle lsGRe fRk R+fk RHfk fRgk fR1 R1f8 R1fH fRg1 kXfM f", +"R+kM RTfk fRTgk lfR fRl+ fRlH lXsf R2ke kX2e! kX2eB akXe2 1eR5 R1e58 R1e5B ", +"akX5e kXMe2 XM2ke! RTek2 ak2RTe R5le lX58e lX5Te lsX5e keR; kX;+e kX;*B akX", +"e; 1eR; R1>e kX*5B >kXae kX;Me +kXMe; kX;Te kX;aMe Rel; lX>e lX;Te l>Xse kX", +"2Ge RG2ke! RHek2 ak2RHe R1G5e G5kR8e R1H5e RG5ake RGkMe2 M!kXGe2 kX2HMe akR", +"eGT2 lGR5e RG5le8 lHX5e sX5lHe R;fk fR+k; fRHk; gfRk; R1f5 fR>k fR1H5 f>Rg1", +" fRkM; kX;fM+ fRTk; fT;gkX fRl; >Xlf lfRH5 glf>X keP k!eP kBeP keaP 1PRe ke", +"8P keP1B ake1P Sek keS! TkSe akSe leS S8le lTSe leSs X*kP ke+P kX*PB akXP* ", +"kX*1P kX*8P kXB1P* R1+aeP kXS* +kSe SeTk* S+eTk Sel* S+le lX*ST Ssel+ Yke k", +"eY! HkYe akYe R1Ye 8kYe Y1RHe Y1aRe YkSe SYke! ZkSe SZeak lYe Y8le SZle les", +"Y Yfk fkY+ YHfk Yfgk fRY1 f8Yk Yf1RH gY1fR Sfk fkS+ YkZf gkSf lYf l+Sf ZflY", +" gSlf keRm kXme! kXmeB akXem 1eRm kXm8e keP5B ake5P keSm Sekm! SeTkm Saekm ", +"Sple Spel8 SpelT Sselp Xmk* kXm+e kXm*B akXm* kXm1* ke>P kXB1m* >keaP keS; ", +"S+ekm Se;Tk Saek; Sel; leS> Se;lT S>els keYm Ykem! YkHem Yakem 5kYe Y5k8e Y", +"5kHe Y5ake SYkem YkmSe! SZekm SamZke leYp lYp8e lYZpe lYspe fvYk Yfkv+ Yfkv", +"H gYkfv f5Yk Yf>k Yf5Hk Y>kgf fkSv Sfv+k ZfkSv gSfvk Sflv S>lf lYfZp lYyf ,", +"kX 9eR& RB9e 9aRe R1,X :Re ,R1XB Ra:e 9X,M kX&,M 9TRe akX,T lX, :Rle ,TlX s", +"Xl, 9XR* -kX kX*,B ak-X kX*,1 -R:X k*B,1X :-RaX XM9* 9X-M kX*,T Tk-X ,Xl* l", +"-X lX*,T lXs- R9,G kX&,G 9HRe akX,G R1,G ,R:G ,R1HX RH:e ,RG9M ,GkXM& ,RG9T", +" ,GTakX ,RlG :RGle ,HlX sX,lG fR9 -Rf9 R9fH fRg9 ,Rf1 :fR fR91H gR:f R9fM f", +"-R9M R9fT f-R9T fRl, lX:f lfR,H g-lX ,2kX kX&,2 ,kX2B akX,2 95Re R5:e ,5kXB", +" :Re5a ,kXM2 kX2Me& ,TkX2 ak2,TX ,5lX :Rel5 lX,5T sX,l5 9eR; kX-; kX;,B -kX", +"a; kX;,1 :R>e kXB,1; :>Rae kX;,M -kXM; kX;,T -TkX; ,Xl; >Xl- lX;,T l-Xs> ,R", +"G92 ke2RG& ,HkX2 ak2,RG ,R1G5 :RG,5 ,H5kX :RH5e kX2,GM XMk&,G2 kX2,GT aX9M,", +"G2 lG,R5 :R5lG, lHX,5 sX5lG, R9f; f-R9; fR9H; fR9g; R9f5 :Rf> fR9H5 :fRg> f", +"R9M; f9;-XM fR9T; fR;-Tk lfR,5 lf:>X fR95T gl->X 9PRe ePk& keP,B akX,P keP,", +"1 Re:P kXB,1P :ReaP S9e 9eS& 9TSe 9aSe S9le S:e S9elT seS: kX*,P kX-P kXB9P", +"* -kXaP ,1XkP* :-ReP X*9PR1B :Xa-kP 9XS* -kSe S9eT* S-9TX S9el* lXS- S9TlX*", +" l-SsX Yk, ,kY& ,HYk ,aYk ,RY1 :RY, Y1,RH Y:R,H Y9Se SY9e& Z9Se SZ9ae lY, l", +"eY: YZl, l,sY fRY9 Y-k Yf9RH gkY- Yf9R1 Yk:f Y9HfR1 Y:gfR Sf9 S9Y- S9Zf g9S", +"f l,Sf lY- lYfZ9 sYl- 9eRm kXme& kXm,B akX,m kXm,1 Re:m kXB,1m :Ream 9eSm S", +"9em& S9eTm S9aem p9Se Se:p Sp9Te S:esp kXm,; kX-m kXB,;P -kXam ,R1Xm* :-RXm", +" Xm9*R1B :Ra>eP 9eS; S-9Xm S9eT; S9ae; Sp9X* >eS: S9Tle; -pXls ,kYm Yk&,m Y", +"k,Hm Yak,m ,5Yk Y:R,5 Y5k,H Y5a,k SY9,m SemYk& SZ9em S9mYa, l,Yp lY:pe lY,Z", +"p lYsp, vRf9 Yk-v Yvk,H Y-kgv Yf9R5 >kY- Y9HfR5 :vRgf fvS9 Sf-v9 Sf9Zv gSfv", +"9 S9fp Y-lv fp9SZ lYy- [ke ke[! Dk[e ak[e [1e 1e[8 1D[e 1a[e ke[M [!kMe [kV", +"e V[ake [le [8le V[le le[s [*k +k[* Dk[* ak[* [1* 1+[* 1D[* 1a[* k*[M [+kMe", +" Vk[* V[+ke [l* [+le V[l* l*[s Gk[e [!Gke [kJe Jk[ae 1G[e [1G8e Je[1 J1[8e ", +"[GkMe keM[!G JkV[e V[aJke [Gle [lG8e [Jle [slJe [fk [+fk Jk[f gk[f [f1 [1f8", +" J1[f g1[f [kfM [f+kM fkV[ Vfg[k lf[ l+[f [lVf g[lf ke[2 [!ke2 [Dke2 [ake2 ", +"1e[5 [158e [15De [1a5e [kMe2 keM[!2 V[ke2 [akVe2 [5le [l58e [lV5e [sl5e ke[", +"; [+ke; [;Dke [a;ke 1e[; [1>e [1;De [>1De [;kMe ke;[+M V[;ke Vek[a; [5l* >e", +"[l [l;Ve V>[le [Gke2 ke2[!G Jk[e2 [aeJk2 [1G5e G5k[8e J1[5e J1e[5a keM[G2 k", +"e[!GM2 V[eJk2 akVe[J2 [lG5e [5Gle8 lJ[5e lJ5[se [;fk [f+k; [fJk; g[fk; [1f5", +" >k[f [f1J5 J>k[f [fkM; [+kfM; Vf[k; g[kVf; l;[f [>lf Vf5[l J>l[f ke[P keP[", +"! keDP [akeP 1e[P [18eP [1DeP [1aeP [kSe S[ke! SkVe SVeak S[le S[8le SVle [", +"slSe kP[* [+keP [*DkP [a*kP 1P[* [1+eP [1*DP [1aP* Sk[* S[+ke SVek* SV+ke S", +"[l* [l+Se [l*SV [s*Sl [kYe Yk[e! YeJk YJkae Ye[1 Y1[8e YJ1[e YJ8ke S[Yke Yk", +"[Se! ]ke ak]e [Yle lY[8e ]le ls]e Yk[f Yfk[+ JfYk gYk[f Y1[f [f1Y+ [f1YJ g[", +"1Yf fkS[ Sf[+k ]fk gf]k [lSf lYf[+ ]lf gl]f ke[m [mke! [mDke [amke 1e[m [1m", +"8e [1mDe [1aem S[kem [mkSe! SVekm SakVem le[p [pl8e [plVe [psle km[* [+mke ", +"[m*Dk [amk* 1m[* [>1em [1mD* >kDeP S[;ke S+k[m* SVek; S+kVem l*[p [p*l> [p*", +"Vl V>eSl Yk[em [meYk! YJkem YaeJkm Y1[5e Y1e[8m YJ5ke Y1e[5a Yk[Sem ke[mSY!", +" ke]m ]akem [plYe lY8[pe le]p ]lpse fk[v [vf+k [vJfk g[vfk f1[v [v1f> [v1Jf", +" J>kYf [vfSk Sf+[vk fv]k ]gfvk [plf fp[l> lf]p yl]f ht[ [&ht hD[t ht[c h1[ ", +"[:h hD[1 [ch: [thM ht[M& V[ht Vh[tc lh[ lh[: [lVh u[h t*[ [-t tD[* [ct- [1t", +"* [:- t*[1D :c[- tM[* [t-M V[t* V[t- t*[l l-[ lhV[* u[- [htG tG[h& [Jht tJ[", +"hc hG[1 [h:G [Jh1 hJ[: tG[hM [h&tGM tJV[h Vh[tJc [hlG [:lhG hJ[l hJu[ tf[ [", +"-tf [ftJ i[t h1[f :f[ [f1tJ i[: [tfM [-tfM V[tf V[it [ltf [:lf lJh[f ui[ h2", +"[t ht[&2 ht[D2 [cht2 [ht5 h5[: t5[hD [:hc5 ht[M2 hM&[t2 Vh[t2 [ctVh2 h5[l [", +":lh5 lhV[5 h5u[ [ht; t;[- t;[hD [-tc; [1h; [:h> t5[D* [:-c> t;[hM [-tM; Vh;", +"[t V-[t; h;[l [>l- lh;V[ h>u[ tG[h2 [h&tG2 tJ[h2 [chtJ2 tG5[h [:hG5 tJ5[h :", +"J[h5 [h2tGM hG[&tM2 Vh[tJ2 h2tJ[cV lh[G5 lhG[:5 lJh[5 uh5[J t;[f [-tf; tJ;[", +"f t;i[ t5[f [>tf tf5[J t>i[ tf[M; tfM[-; tfV[; iV[t; lh;[f l-[f> Vf5[t i[u>", +" htP h&tP hDtP tchP tPh1 hP[: htP1D [:hcP Sht S&ht VhSt htSc Shl Sh: SlVh u", +"hS t*hP hPt- tP*hD [-tcP tP*h1 :P[- tPD[1* [:-cP S*ht St[- St*Vh V-[St l*Sh", +" Shl- ShlV* Shu- tYh Y&ht tJhY htYc h1tY hY[: hY1tJ tY:hJ tYSh ShtY& ]ht ht", +"]c lYh Y:Sh ]lh ]uh tYf tY- YJtf itY Y1tf Y:tf tYfJ1 tYi: Sft tYS- ]tf ]it ", +"Shlf tYl- lf]h ui] tmhP tm[h& tm[hD [cmht t5hP hm[: t5PhD [:mhc hmSt Shtm& ", +"VhmSt Shctm tpSh S:hp hplSV hpu[ t;hP tm[- tm[D* [-mtc t5[m* ht>P t5Dh;P [:", +"-cm h;St [-mSt Sh;Vt V-[tm l;Sh S:h> [p*Vt h>uS hmtY tYhm& tJmhY tYchm h5tY", +" [:mhY tY5hJ [:mhJ ShtYm tYmSh& ht]m ]htcm hplY [p:hY hp]l ]puh tYhv Y-tv h", +"v[tJ tYiv h1[v tYh> [v1hJ tYi> tvSh [-vSt hv]t ]tiv hvlY h>lY lv]h ]yui n n", +"! nB an n. 8n n.B 8na nK n!K Tn Tna nj 8nj Tnj sn n( +n n(B +na n(. +n8 .Bn", +"( +8an n(K +nK Tn( +Tn nj( +nj T(nj sn+ nE n!E Hn Hna nE. 8nE Hn. H8n nEK E", +"Kn! HnT HTan njE 8Enj Hnj snH dn +nd Hnd gn dn. 8dn H.dn gn8 dnK +Kdn Tdn g", +"nT dnj dn+j dnHj gsn 4n 4n! 4nB 4an 5n 48n 5nB 5an 4nK n!4K 4Tn Tn4a 4jn 8n", +"4j 5Tn s4n ;n 4+n ;nB a;n 5n; >n 5B;n >na ;nK 4K+n T;n +n4T ;nj >nj T;5n >n", +"s 4nE n!4E 4Hn Hn4a 5nE 4E8n H5n Hn48 nE4K 4nE!K Hn4T 4HTan 4Enj njE48 Hn4j", +" 4Hsn 4dn +n4d H;n g4n 5dn >nd 5dHn >ng 4Kdn dnK4+ T;Hn 4Tgn dn4j dn>j Td5n", +" gs>n Pn n!P PnB aPn Pn. 8Pn n.PB aP8n Qn Qn! QnT Qan Qnj Q8n PjTn sPn Pn( ", +"+Pn n(PB aP+n n(P. 8P+n Pn(.B aPn+8 Qn( +Qn Q(Tn Qa+n Q(nj Q8+n Pj(Tn +Qsn ", +"Wn Wn! HPn Wan Wn. W8n H.Wn W8Hn WnQ Q!Wn Zn Zna Wnj Q8Wn Znj sZn Wnd +Wn d", +"PHn gPn W.dn W8+n dP.Hn W8gn Qdn Wn+Q Znd gZn dnWj Wn+j dnZj gnsZ o o! oB o", +"a o5 o8 o5B o8a oQ o!Q oT oTa op op8 opT os o; o+ o;B o+a o5; o> 5;oB o>a o", +"Q; o+Q oT; o+T op; o>p pTo; os> oW o!W oH oHa o5W o8W oH5 oH8 oWQ Q!oW oZ o", +"Za opW pWo8 oZp osZ ov ov+ ovH go ov5 o>v vHo5 go> ovQ v+oQ oZv goZ opv pvo", +"> opZv yo n# &n n#B an& n#. 8n& .Bn# 8a&n n#K &nK Tn# T&n nj# &nj T#nj sn& ", +"n#( +n& #Bn( +a&n #(n. +8&n n#(.B an&+8 #(nK +K&n n#T( T&+n j#n( &n+j nj#T(", +" +ns& n#E &nE Hn# H&n #En. 8E&n n#H. 8nH& EKn# nK&E H#Tn T&Hn j#nE &Enj H#n", +"j H&sn dn# d&n H#dn gn& n#d. d&8n dn#H. 8ng& n#dK dK&n T#dn T&gn d#nj &ndj ", +"dnjH# g&sn 4n# 4&n n#4B an4& 5n# 5&n n#5B an5& n#4K 4K&n 4#Tn Tn4& 4#nj &n4", +"j 5#Tn 4&sn ;n# ;&n nB;# ;&an 5#;n >n& ;n#5B an>& n#;K ;K&n T#;n ;&Tn ;#nj ", +"&n>j ;njT# >&sn n#4E 4E&n 4#Hn Hn4& n#5E 5E&n H#5n 5&Hn 4n#EK &nE4K 4HTn# 4", +"H&Tn nj#4E &nj4E 4Hjn# snH4& 4#dn dn4& H#;n 4&gn 5#dn d&>n H5nd# >&gn dn#4K", +" d&n4K 4Tdn# g4T&n dnj4# >nd&j ;njH# >ngs& Pn# P&n n#PB P&an n#P. P&8n Pn#.", +"B aP&8n Qn# Q&n Q#Tn T&Qn Q#nj 8nQ& Pj#Tn Q&sn n#P( P&+n Pn#(B aP&+n Pn#(. ", +"P&n+8 n#(P.B +P8an& n#Q( Q&+n QnT#( +QnT& Pj#n( P&j+n TP#nj( sP+&n Wn# W&n ", +"H#Wn W&Hn n#W. 8nW& HPn#. H8P&n W#Qn Q&Wn Zn# Z&n W#nj &nWj njZ# Z&sn W#dn ", +"W&+n dP#Hn W&gn dP#n. dP&8n HP#dn. gP8&n Q#dn d&Qn dnZ# Z&gn dPjn# dP&nj Zn", +"dj# Z&ngs o# o& o#B oa& o5# o8& 5Bo# 5ao& oQ# o&Q oT# oT& op# op& pTo# os& ", +"o;# o+& ;#oB a;o& 5;o# o>& o5;#B >&oa Q;o# +Qo& T;o# +To& p;o# p>o& opT;# o", +"&s> oW# o&W oH# oH& 5Wo# 5Wo& H5o# H5o& WQo# W&oQ oZ# oZ& pWo# oWp& Z#op Z&", +"os ov# ov& vHo# go& v5o# v>o& ovH5# o&g> vQo# oQv& Z#ov Z&go o#pv pvo& oZpv", +"# yo& nC n!C Dn Dna nC. 8nC Dn. D8n nCK CKn! DnT DTan njC 8Cnj Dnj snD nC( ", +"+nC Dn( +Dn C(n. +C8n n(D. D8+n CKn( nC+K D(Tn Dn+T jCn( +Cnj D(nj +Dsn nCE", +" !CnE HnD HDan CEn. nC8E H.Dn D8Hn EKnC n!CEK HDTn HnDTa jCnE njC8E DnHj Hn", +"sD dnC +Cdn Ddn gnD nCd. 8Cdn D.dn D8gn nCdK dnC+K TdDn DngT dCnj dnj+C dnD", +"j gDsn 4nC n!4C 4Dn Dn4a 5nC 4C8n 5Dn D85n nC4K 4nC!K Dn4T 4DTan 4Cnj njC48", +" Dn4j 4Dsn ;nC 4C+n D;n +n4D 5C;n >nC D;5n >nD nC;K ;nC+K T;Dn a;nDT ;Cnj n", +"j>C ;nDj >Dsn nC4E 4nC!E Hn4D 4HDan nC5E 48nCE 5DHn 4H8Dn 4nCEK n!C4EK 4HDT", +"n HnD4Ta njC4E 48CnjE 4HjDn snH4D 4Cdn dnC4+ D;Hn 4Dgn 5Cdn dn>C Dd5n >Dgn ", +"dnC4K 4+CdnK 4DdTn g4DTn dnj4C >ndjC dnj4D >ngsD PnC PCn! DPn aPDn nCP. Pn8", +"C PnD. 8PDn QnC n!QC QDn DnQa QCnj QC8n DjQn QDsn nCP( Pn+C PnD( DP+n PnC(.", +" +P8nC DPn(. +DP8n nCQ( +CQn Q(Dn QD+n PjCn( +Qn8C QDnj( sP+Dn WnC n!WC WDn", +" DnWa nCW. WC8n W.Dn D8Wn WCQn WnQ!C ZnD DnZa WCnj W8nQC DnZj sDZn WCdn +CW", +"n DdWn WDgn dPCn. +Wn8C WDnd. gPD8n QCdn +WnQC DdZn gDZn dPjnC +WnjC ZnDdj ", +"gZnsD oC o!C oD oDa o5C o8C oD5 oD8 oQC Q!oC oDQ QDoa opC p8oC opD osD o;C ", +"o+C oD; o+D 5;oC o>C 5Do; o>D Q;oC +QoC QDo; +QoD p;oC >Cop o;pD oDs> oWC W", +"!oC oHD WDoa 5WoC W8oC H5oD H8oD WQoC o!WQC oZD ZDoa pWoC opW8C oDZp oDsZ o", +"vC v+oC ovD goD v5oC >Cov o5vD oDg> vQoC ov+QC oDZv oDgZ oCpv o>pvC pvoD yo", +"D bn bn& bnD cn bn. b8n b.Dn cn8 bnK bK&n bTn cnT bnj 8nbj Dnbj scn bn( b+n", +" b(Dn cn+ n(b. +nb8 bnD(. +nc8 n(bK bK+n b(Tn +Tcn b(nj +nbj bTnj( s+cn bnE", +" bE&n bHn cnH nEb. bE8n b.Hn H8cn nEbK &nEbK HnbT HncT bEnj &njbE Hnbj sHcn", +" bdn +nbd Hnbd gcn b.dn 8dbn bHnd. g8cn bKdn d&nbK Tdbn gTcn dnbj d&nbj dnj", +"bH gnsc 4bn bn4& bn4D c4n b5n bn48 5Dbn c5n 4Kbn &nK4b bn4T 4Tcn bn4j &nj4b", +" 5Tbn c4sn b;n bn4+ D;bn c;n 5nb; >nb b5nD; c>n bK;n ;&nbK T;bn T;cn ;nbj b", +"n>j ;njbT sc>n 4Ebn &nE4b bn4H 4Hcn bE5n 4b8nE H5bn H5cn 4bnEK 4bE&nK 4bHTn", +" c4HTn 4bjnE &nE4bj 4bHnj c5nsH bn4d d&n4b H;bn c4gn 5dbn bd>n bH5dn gc>n 4", +"bdnK d&Kb;n 4bTdn c;ngT dnj4b >nbdj ;njbH c>ngs bPn P&bn DPbn cPn Pnb. 8Pbn", +" bPDn. 8Pcn bQn Q&bn QDbn cQn Qnbj Q8bn bQnDj cQsn Pnb( +Pbn bPDn( +Pcn bPn", +"(. b+P8n DP(bn. cP+8n b(Qn +Qbn bQnD( +Qcn bQnj( b+Q8n Pj(bTn cQns+ bWn W&b", +"n HPbn cWn b.Wn W8bn bHPn. W8cn WnbQ bWnQ& Zbn Zcn Wnbj &njbW bnZj snZc Wnb", +"d +Wbn bHPdn cWgn bWnd. b+W8n dP.bHn cWng8 Qdbn d&nbQ bdZn gnZc dPjbn b+Wnj", +" Zbndj Zcngs ob ob& obD oc ob5 ob8 b5oD oc5 obQ bQo& obT ocQ opb pbo8 pboD ", +"osc ob; ob+ b;oD oc+ b5o; o>b ob5D; oc> bQo; b+oQ bTo; o+cQ o;pb p>ob opbD;", +" c>os obW bWo& obH ocH b5oW bWo8 bHo5 oHc5 bWoQ obWQ& oZb ocZ oWpb opbW8 op", +"Zb Zcos ovb vbo+ vboH goc o5vb v>ob ovbH5 c>go oQvb ovb+Q ovZb Zcgo pvob o>", +"bpv oZbpv yoc 6n 6!n 6nB 6an 1n 68n 1nB 1an 6nK n!6K 6Tn Tn6a 6jn 8n6j 1Tn ", +"s6n 6n( 6+n n(6B +n6a 1n( 1+n n(1B +n1a n(6K 6K+n 6(Tn +n6T 6(nj +n6j 1(Tn ", +"6+sn 6nE n!6E 6Hn Hn6a 1nE 6E8n 1Hn H81n nE6K 6!nEK Hn6T 6HTan 6Enj njE68 H", +"n6j 6Hsn 6dn +n6d Hn6d g6n 1dn +n1d Hn1d g1n 6Kdn dnK6+ Tn6d 6Tgn dn6j dnj6", +"+ Td1n s6gn 46n 4n6! 6n4B 46an 7n 78n 7Bn 7an 6n4K 6!4nK 46Tn 4T6an 7nj 8n7", +"j 7Tn 7sn 6;n +n6; 6B;n an6; 7;n >n7 ;n7B 7a>n 6K;n ;nK6+ Tn6; a;n6T ;n7j 7", +"n>j T;7n >n7s 6n4E 6!4nE 46Hn 4H6an 7nE 8n7E 7Hn H87n 46nEK 4nE6!K 4H6Tn 6H", +"T4an nj7E 78njE Hn7T 7Hsn dn6; 4+6dn Hn6; 6;gn 7dn 7d>n H;7n g7n dnK6; 4+6d", +"nK 4Td6n g46Tn dn7j 7>dnj Td7n gn7s 6P 6P! 6PB 6aP 6P1 68P 6B1P 1a6P 6QP Q!", +"6P 6TP Qa6P 6Pj Q86P 1T6P s6P 6P( 6+P P(6B +P6a 6(1P 1+6P 6P1(B 6+P1a 6(Qn ", +"+Q6P 6(TP +T6P 6(Pj +Q1n 6TP1( 6+sP 6WP 6!Wn 6HP HP6a 1Wn W86P 1H6P H86P Wn", +"6Q 6WQn! Z6P 6aZn Wn6j 6W8Qn Z1n Z6sP 6dP +W6P HP6d g6P 1d6P +W1n 6HP1d 68g", +"P Qd6P 6+WQn 6dZn Z6gP Qd1n dPj6+ 1dZn s6gP o6 o!6 o6B oa6 7o 7o8 7oB 7oa o", +"6Q 6Qo! oT6 6Qoa 7op o87p 7oT os7 o6; o+6 6;oB 6+oa 7o; o>7 o;7B 7ao> 6Qo; ", +"6+oQ 6To; 6+oT 7;op 7po> 7;oT o>7s o6W 6Wo! oH6 6Hoa 7oW o87W 7oH oH7a 6WoQ", +" o!6WQ oZ6 oaZ6 op7W 7opW8 7Zo os7Z ov6 v6o+ v6oH go6 7vo o>7v ov7H go7 oQv", +"6 ov6+Q ovZ6 g6oZ op7v 7p>ov oZ7v yo7 9n 6&n 9nB 9an 9n1 :n 1B9n :na 9nK 6K", +"&n 9Tn T&9n 9nj :nj 1T9n s:n 9n( 9+n n(9B +n9a 9(1n :n+ 9n1(B +n:a n(9K 9K+", +"n 9(Tn +T9n 9(nj +n:j 9Tn1( s+:n 9nE 6E&n 9Hn H&9n 9E1n :nE 1H9n :Hn nE9K &", +"nE6K Hn9T 6H&Tn 9Enj nj:E Hn9j :Hsn 9dn +n9d Hn9d g9n 1d9n :dn 9Hn1d g:n 9K", +"dn d&n6K Td9n 9Tgn dn9j dn:j dnj9H gns: 49n 9n4& 4B9n 9n4a 79n 7:n 9n7B :n7", +"a 4K9n &nK49 9n4T 49Tan 9n7j 7j:n 9T7n 7:sn 9;n 9n4+ 9B;n a;9n 9;7n >n: 7B9", +";n :a>n 9K;n ;&n6K T;9n a;n9T ;n9j >j:n 7T9;n s:>n 4E9n &nE49 9n4H 49Han 9n", +"7E 7E:n 9H7n :n7H 49nEK 49E&nK 49HTn 9Hn4T& 79njE 7:njE 7H9Tn 7:Hsn 9n4d d&", +"n49 H;9n 49gn 9d7n :d>n 7H9dn >ng: 49dnK d&K9;n 49Tdn g49Tn 7d9nj 7:dnj 7Td", +"9n g:n7s 6P9 6P& 6B9P 9a6P 1P9n :P6 6P19B 6a:P 9Qn Q&6P 9T6P Qa9n 9P6j :Qn ", +"6TP9j :Qsn 6(9P 9+6P 6P9(B 6+P9a 6P19( 6+:P 1P(9nB :P6+a 9(Qn +Q9n 6TP9( 6+", +"T9P 6Pj9( +Q:n Pj(9Tn :Qns+ 9Wn W&6P 9H6P HP6& 1W9n :Wn 6HP91 6H:P Wn9Q 6W&", +"Qn Z9n 6PZ& Wn9j Wn:Q 9nZ1 Z:n 9d6P +W9n 6HP9d 6Pg9 6dP91 6d:P 1HP9dn :Wgn ", +"Qd9n dP&6Q 9dZn Z9gn dPj9n Qd:n Z9n1d gnZ: o9 o9& o9B o9a 7o9 o: 7Bo9 o:a o", +"9Q 6Qo& o9T 6To& op9 o:p o97T os: o9; o9+ 9;oB 9+oa 7;o9 o:> 7o9;B oa:> 9Qo", +"; 9+oQ 9To; 9+oT o;p9 o>:p 7oT9; s:o> o9W 6Wo& o9H 6Ho& o97W o:W o97H o:H 9", +"WoQ o9WQ& oZ9 o9Z& oWp9 op:W Z97o Z:o ov9 v6o& v9oH go9 o97v :vo 7oHv9 go: ", +"oQv9 ov9+Q ovZ9 g9oZ pvo9 op:v oZ97v yo: 6nC n!6C 6Dn Dn6a 1nC 6C8n 1Dn D81", +"n nC6K 6!nCK Dn6T 6DTan 6Cnj njC68 Dn6j 6Dsn nC6( 6C+n 6(Dn +n6D nC1( 1C+n ", +"1(Dn +D1n 6nC(K 6+nCK 6DTn( 6+DTn njC6( 6+jnC 6Djn( sn+6D nC6E 6!nCE Hn6D 6", +"HDan nC1E 68nCE Hn1D 6H8Dn 6nCEK n!C6EK 6HDTn HnD6Ta njC6E 68CnjE 6HjDn snH", +"6D 6Cdn dnC6+ Dn6d 6Dgn 1Cdn 68dnC Dd1n 1Dgn dnC6K 6+CdnK 6DdTn g6DTn dnj6C", +" dnC6+j dnj6D gs6Dn 6n4C 6!4nC 46Dn 4D6an 7nC 8n7C 7Dn D87n 46nCK 4nC6!K 4D", +"T6n 6DT4an nj7C 78njC Dn7T 7Dsn 6C;n ;nC6+ Dn6; a;n6D ;n7C 7n>C D;7n 7D>n ;", +"nC6K 6+C;nK 6D;Tn +Dn6T; ;nj7C 7>jnC 7DT;n 7s>Dn 46nCE 4nC6!E 4H6Dn 6HD4an ", +"nC7E 78nCE Hn7D 7HD8n 6nC4EK 4n6!EKC 6HD4Tn 46anHDT 7njCE njC78E 7HDTn 7sHD", +"n dnC6; 4+6dnC 4Dd6n g46Dn dn7C 7>dnC Dd7n 7Dgn 6dC;nK dn6;+CK Ddn6T; 6D;gn", +"T 7dnjC >nj7dC 7DdTn g7sDn 6PC PC6! 6DP DP6a 6C1P 6C8P 1D6P D86P 6CQn 6QP!C", +" QD6P 6QDaP 6CPj 6Q8PC QD1n 6DsP PC6( 6C+P 6(DP +D6P 6P1C( 6+P1C 6DP1( 6+D1", +"P 6QPC( 6+QPC 6QDP( 6+QDP 6PjC( 6+PjC 6DPj( s6P+D 6CWn 6WP!C HP6D 6HPDa 1CW", +"n 6W8PC WD1n 6H8DP 6WQPC WnC6Q! 6DZn Z6DaP 6WjPC PjC6W8 1DZn Z1nsD 6CdP 6+W", +"PC Dd6P 6DgP 6dP1C 68dPC 6Dd1P g6P1D 6QdPC dPC6+Q Z6DdP gZ6DP dPj6C dPC6+j ", +"Z1nDd Z1ngD o6C 6!oC oD6 6Doa 7oC 7Co8 7oD oD7a 6QoC o!6QC 6QoD oD6Qa 7Cop ", +"7op8C op7D 7Dos 6;oC 6+oC 6Do; 6+oD o;7C >C7o 7;oD 7Do> o6Q;C o+6QC oD6Q; o", +"+D6Q 7op;C 7p>oC 7oDp; os7>D 6WoC o!6WC 6HoD oH6Da oW7C 7oW8C oH7D 7oHD8 o6", +"WQC 6WQo!C oDZ6 oZ6Da 7opWC op87WC 7DoZ osZ7D oCv6 ov6+C v6oD oDg6 7Cov 7vo", +">C ov7D 7Dgo ov6QC v6Qo+C Zv6oD goZ6D 7vopC o>p7vC 7vDoZ 7oyD b6n 6&bn 9Dn ", +"c6n b1n :nb 1Dbn :cn bK9n &nKb6 6Tbn 6Tcn 6jbn bn:j 1Tbn :csn b(9n 6+bn 9(D", +"n 6+cn b(1n b+:n b1nD( :+cn b6n(K b6+nK b6Tn( c6+Tn b6jn( :nb+j b1Tn( :cns+", +" bE9n &nEb6 6Hbn 6Hcn bE1n bn:E 1Hbn cn:H b6nEK b6E&nK b6HTn c6HTn b6jnE :n", +"bjE b6Hnj :cnsH 6dbn d&nb6 Dd9n c6gn 1dbn bd:n b1Hdn :cgn b6dnK dnKb6+ b6Td", +"n gc6Tn dnjb6 :dnbj dnj9D g:nsc bn49 4b6&n 9n4D 49cn 7bn :n7b bn7D 7cn 4b6n", +"K 4b6&nK 4bT9n c46Tn bn7j 7:bnj bT7n sn7c 6;bn ;&nb6 D;9n 6;cn b;7n 7b>n 7b", +"D;n >n7c b6;nK ;nKb6+ b6T;n c6;Tn 7b;nj 7>bnj 7bT;n c>n7s 4b6nE 4b6&nE 4bH9", +"n c46Hn bn7E 7:bnE bH7n cn7H bnE49K 4Eb6&nK bHn49T 49HcnT 7bnjE :nj7bE 7bHT", +"n 7csHn 4bd9n b6d;&n 49Ddn c6;gn bd7n 7:dbn 7bHdn gn7c dnKb6; dn4&b6K bTn49", +"d c4Tg9n 7bdnj 7bj:dn 7bTdn g7csn b6P 6&bP 6DbP c6P 6Pb1 b6:P b6P1D c6:P 6Q", +"bP b6QP& 6TbP 6QcP 6Pbj bQ:n b6T1P c6sP b(6P 6+bP b6PD( 6+cP b6P1( :Pb6+ b6", +"(1DP :cP6+ b6QP( b6+Qn b6TP( c6Q+P b6Pj( :Qnb+ Pj(b6T :cQ+n 6WbP b6WP& 6HbP", +" 6HcP 1Wbn bW:n b6H1P cW:n b6WQn 6W&bQn b6Zn c6Zn b6WPj :WnbQ b1Zn :cZn 6db", +"P dP&b6 b6HdP c6gP b6d1P :Wnb+ 6HPb1d g:Pc6 b6QdP b6QdP& Zb6dP Zc6gP dPjb6 ", +":Qdbn Zb1dn Z:ngc ob6 b6o& o9D oc6 7ob o:b ob7D 7co b6oQ ob6Q& b6oT o9cQ op", +"7b ob:p ob7T os7c b6o; b6o+ 9Do; o9c; 7;ob 7bo> 7obD; c>o: ob6Q; ob+6Q obT6", +"; oc6+Q 7obp; o:p>b 7obT; os:c> b6oW ob6W& b6oH o9cW ob7W ob:W ob7H 7Hoc ob", +"6WQ b6Wo&Q obZ6 Z6oc 7obpW o:pbW 7boZ oc7Z vbo9 ovb6+ v9oD g6oc ov7b ob:v 7", +"vboH 7cgo ovb6Q obQv6& oZbv6 cv6oZ 7vbop :vopb 7Zbov 7cyo Rn Rn! RnB Ran Rn", +". R8n n.RB 8nRa Mn Mn! RTn aMn Rjn 8Mn TnRj sRn Rn( R+n n(RB +nRa n(R. +nR8", +" Rn(.B R+8an Mn( +Mn R(Tn +nRT R(nj +nRj Mn(Tj R+sn RnE n!RE RHn HnRa nER. ", +"RE8n R.Hn HnR8 MnE MEn! HMn aMHn REnj 8EMn HnRj RHsn Rdn +nRd HnRd gRn R.dn", +" 8nRd dn.RH R8gn dMn dM+n TnRd gMn dnRj dM8n dMnHj sRgn R4 R4! R4B R4a R45 ", +"R48 RB5n 48Ra R4M 4!Mn R4T 4TRa R4j 48Rj 4TR5 sR4 R4; R4+ RB;n 4+Ra 5nR; >n", +"R ;nBR5 R4>a M;n 4MR+ 4TR; 4+RT 4jR; >Mn M;n5T sR>n R4E 4!RE R4H 4HRa RE5n ", +"RE48 4HR5 4HR8 RE4M MnE4! 4HRT aMn4H RE4j R48ME 4HRj R4sH R4d 4+Rd 4HRd gR4", +" 4dR5 R4>d R4H5d gR>n 4MRd dMn4+ 4TRd R4gM 4dRj dM>n dMnH5 gM>n RPn n!RP Pn", +"RB RPan PnR. RP8n RPn.B aPnR8 Sn S!n STn San Snj S8n TnSj Ssn PnR( RP+n RPn", +"(B aPnR+ RPn(. R+8Pn Pn(R.B R+8aPn Sn( S+n TnS( +TSn njS( +nS8 STnj( S+sn R", +"Wn R!Wn HnRW WnRa R.Wn WnR8 RHWn. RH8Wn SWn WnS! SZn ZnSa WnSj W8Sn SjZn sn", +"SZ WnRd +nRW RHWdn RWgn dP.Rn R+W8n RHWdn. gRW8n Sdn +WSn ZnSd gSn dnSj 8dS", +"n SZdnj gnSs oR o!R oRB oaR oR5 o8R R5oB R5oa So So! SoT Soa Sop So8 oTSp o", +"sS oR; o+R R;oB R+oa R5o; o>R oR5;B >Roa So; So+ oTS; o+Sa opS; S>o SpTo; o", +"sS> oRW RWo! oHR RHoa R5oW RWo8 RHo5 RHo8 SoW o!SW oZS SaoZ SWop SWo8 SpoZ ", +"oZSs ovR vRo+ vRoH goR o5vR vRo> ovRH5 gRo> Svo ovS+ oZSv goS opSv o>Sv SZp", +"ov yoS Rn# R&n n#RB anR& n#R. 8nR& Rn#.B an&R8 Mn# M&n R#Tn TnR& R#nj M&8n ", +"Mn#Tj R&sn n#R( +nR& Rn#(B an&R+ Rn#(. R+8&n n#(R.B R+8an& n#M( M&+n Mn#T( ", +"aMn+& Mn#j( M&n+j RT#nj( sn+R& n#RE RE&n R#Hn HnR& Rn#E. &nER8 RHn#. RH8&n ", +"n#ME ME&n H#Mn M&Hn Mn#jE M&n8E RHjn# snHR& R#dn dnR& dn#RH R&gn dn#R. d&nR", +"8 RH#dn. gR8&n d#Mn M&dn dMnH# M&gn dMnj# dM&8n dM#Hnj gsR&n R4# R4& 4#RB 4", +"aR& R#5n 48R& R45#B R48a& R#4M 4MR& R#4T 4TR& R#4j 4&Rj R4T5# R4s& R#;n 4+R", +"& ;n#RB a;nR& ;n#R5 R4>& R5#;nB >nRa& M#;n ;&Mn M;nT# aM;&n M;n5# M&>n M;#5", +"Tn >Mns& 4#RE RE4& R#4H 4HR& R45#E R48&E R4H5# R4H5& Mn#4E M&n4E R4HT# M&n4", +"H R4j#E M&n5E R4Hj# sR4H& R#4d 4dR& R4Hd# R4g& R4d5# >nRd& dn#RH5 >ngR& dMn", +"4# dM&R4 M;nH# gR4T& dMn5# >Mnd& dM#H5n >Mg&n PnR# RP&n RPn#B aP&Rn RPn#. P", +"&nR8 Pn#R.B R8aP&n Sn# S&n TnS# T&Sn njS# 8nS& STnj# S&sn RPn#( P&nR+ Pn#R(", +"B R+aP&n Pn#R(. R+8P&n .BR(Pn# aP8nR+& n#S( +nS& STn#( S+T&n Snj#( S+8&n nj", +"#ST( Ss+&n R#Wn WnR& RHWn# RH&Wn RWn#. RW8&n Hn#RW. H8nRW& WnS# W&Sn S#Zn Z", +"nS& SWnj# S8W&n SZnj# SZ&sn dP#Rn dP&Rn RHWdn# gRW&n RW#dn. RW8d&n dPHnR#. ", +"RW8gn& dnS# d&Sn SZdn# S&gn Sdnj# S8d&n ZnjSd# gSs&n oR# o&R R#oB Rao& R5o#", +" R5o& oR5#B o8Ra& So# So& S#oT oTS& S#op opS& SpTo# S&os R;o# R+o& oR;#B o+", +"Ra& oR5;# >Ro& R5;o#B o>Ra& o;S# o+S& S;To# Sa;o& Sp;o# S&o> opTS;# os>S& R", +"Wo# RWo& RHo# RHo& oR5W# o8RW& oHR5# oH8R& oWS# SWo& S#oZ S&oZ SpWo# Sp&oW ", +"SZpo# osZS& o#vR vRo& ovRH# o&gR ovR5# o>vR& vR5oH# go>R& S#ov ovS& SvoZ# S", +"&go Svop# Sv&o> oZpSv# Soy& Un Un! RDn Uan Un. U8n R.Dn D8Un UnM U!Mn Vn Vn", +"a Unj 8MUn Vnj snV Un( U+n R(Dn +DUn n(U. +nU8 RDn(. R+D8n U(Mn +MUn Vn( V+", +"n U(nj +nUj njV( V+sn UnE n!UE UHn HnUa nEU. UE8n U.Hn H8Un UEMn MnEU! VnH ", +"HnVa UEnj U8nME HnVj sHVn Udn +nUd HnUd gUn U.dn 8dUn RDdn. U8gn dMUn dMnU+", +" Vdn gVn dnUj dMnU8 dnVj sngV R4U 4!Un R4D 4URa U5n 4UR8 4DR5 4DR8 Un4M Mn!", +"4U V4R R4Va 4URj R48Uj V5n V4sR U;n 4UR+ 4DR; 4+RD 5nU; >nU R4D5; R4>D M;Un", +" M;nU+ V;n R4V+ ;nUj Un>M 5nV; V>n RE4U R4U!E 4URH R4HUa UE5n R48UE H5Un R4", +"HU8 MnE4U 4UEMn! R4VH V4RHa R4jUE MnE4U8 H5Vn snV4H 4URd R4+Ud 4DRd R4gU 5d", +"Un Ud>n R4D5d gU>n dMn4U 4U+dMn R4Vd V4gR dMnU5 >MnUd 5dVn >ngV UPn n!UP DP", +"Un aPUn PnU. 8PUn RDPn. RD8Pn SUn UnS! SVn VnSa UnSj U8Sn SjVn snSV PnU( +P", +"Un RDPn( R+DPn UPn(. U+P8n DP(Un. +DPU8n UnS( U+Sn S(Vn VnS+ SUnj( S+U8n SV", +"nj( SV+sn UWn U!Wn HPUn WaUn U.Wn W8Un RWDn. RWD8n UWSn S!UWn ZnV ZaVn WnUj", +" S8UWn ZjVn VZsn WnUd +WUn RWDdn UWgn UWnd. U+W8n dP.UHn gUP8n UdSn S+UWn V", +"dZn SVgn SdUnj S8dUn SVdnj gVnSs oU oU! oUD oUa oU5 oU8 R5oD RDo8 SoU S!oU ", +"oV oVa opU oUS8 oVp oVs oU; oU+ RDo; R+oD U5o; o>U oU5D; >RoD oUS; oUS+ oV;", +" oV+ o;pU oUS> V;op oV> oUW UWo! oUH UHoa U5oW UWo8 UHo5 UHo8 SWoU oUWS! oV", +"Z VZoa oWpU opUW8 VpoZ sZoV ovU vUo+ vRoD goU o5vU v>oU ovUH5 gUo> oUSv Svo", +"U+ oVv goV pvoU o>USv opVv yoV Rbn U&n bnRD cRn R.bn bnR8 RbDn. R8cn bMn M&", +"bn Vnb cnV bnRj 8Mbn bnVj cRsn R(bn bnR+ RbDn( R+cn Rbn(. Rb+8n bn(RD. cR+8", +"n b(Mn +Mbn bnV( V+cn Rbjn( &njU+ Vnbj( snVc+ REbn UE&n bnRH RHcn RbnE. Rb8", +"nE RbHn. cRH8n bEMn M&nbE bHVn cHVn RbjnE &njUE VnbHj snVcH bnRd d&Un RbHdn", +" cRgn Rbdn. d&nU8 dn.RbH gcR8n dMbn dM&bn bdVn cngV dMnbj dMnb8 Vdnbj gVnsc", +" R4b 4bR& 4bRD cR4 4bR5 4bR8 R4b5D R4c5 4MRb M&n4b R4Vb V4cR 4bRj M&nb5 b5V", +"n cRs4 4bR; 4bR+ R4bD; R4c; R4b5; R4>b b5nRD; cR>n M;bn M;&bn b;Vn V;cn M;n", +"b5 bM>n V5nb; cnV> RE4b R4b&E 4bRH R4cH R4b5E R4b8E R4bH5 cR4H5 R4bME M&ER4", +"b V4RbH cR4VH R4bjE M&Eb5n V5nbH cR4sH 4bRd d&n4U R4bH; cRg4 R4b5d >nbRd 4b", +"HR5d c>Rg4 dMn4b R4bdM& V4dRb gV4cR dMnb5 >Mbdn V5dbn V>ngc UPbn P&Un RbDPn", +" UPcn RbPn. Rb8Pn bPnRD. cR8Pn Sbn bnS& VnSb Scn bnSj b8Sn SVbnj snSc RbPn(", +" Rb+Pn bPnRD( cR+Pn UP(bn. U+Pb8n R(bPDn. U+Pcn8 bnS( b+Sn SVbn( cnS+ Sbnj(", +" Sb+8n VnjSb( Scs+n bnRW W&Un RbHWn RWcn RbWn. RbW8n Rb.WDn cRW8n bWSn SbW&", +"n ZnSb ZnSc SbWnj Sb8Wn SZbnj ZcnSs RbWdn dP&Un bWnRDd cRWgn dn.RbW b+nRW8 ", +"R.bHWnd cW8gUn bdSn Sb+Wn SZbdn gnSc Sbdnj Sb8dn SbjVdn gScsn obR oU& RboD ", +"ocR Rbo5 Rbo8 obR5D oUc5 Sob obS& oVb Sco opSb obS8 obVp osSc Rbo; Rbo+ obR", +"D; oUc; obR5; >Rob Rb5oD; cRo> obS; obS+ V;ob S+oc Spbo; Sbo> oVpb; ocS> Rb", +"oW UWo& RboH oUcW obR5W ob8RW obHR5 ocRH5 SWob oU&SW SboZ ZcoV SpboW Sb8oW ", +"oVZpb oVsZc vRob vUo& ovbRH gRoc ovbR5 o>bvR ob5vRD cvRo> ovSb Svbo+ obVv S", +"cgo Svbop S>bov oVvpb Scyo q q! qB qa q1 q8 q1B q8a qM q!M qT qTa lq q8l qT", +"l sq q( q+ q(B q+a q1( q+1 1(qB 1+qa qM( q+M qT( q+T lq( l+q l(qT sq+ qE q!", +"E qH qHa q1E q8E qH1 qH8 qME MEq! qHT HMqa lqE lEq8 lHq sqH qd q+d qHd gq q", +"d1 q8d 1Hqd gq1 qdM +Mqd qTd gqT ldq q+ld qHld glq q4 q!4 q4B qa4 7q 7q8 7q", +"B 7qa q4M 4Mq! qT4 4Tqa 7lq q87l 7qT sq7 q; q+4 q;B qa; 7q; q> 7Bq; q>a q;M", +" 4+qM qT; 4+qT l;q q>l qTl; sq> q4E 4Eq! qH4 4Hqa 7qE 7Eq8 7qH qH7a 4MqE q!", +"4ME 4HqT qH4aM lE7q 7lq8E 7qlH 7Hsq qd4 4+qd qH; gq4 7qd q>d qH7d gq7 4dqM ", +"q+4dM 4Tqd qTg4 7qld ldq> qHl; sqg7 qP q!P qPB qaP q1P q8P 1PqB 1aqP Sq Sq!", +" SqT Sqa Slq Sq8 qTSl sqS qP( q+P P(qB +Pqa 1Pq( 1+qP q1P(B q+1aP Sq( Sq+ S", +"(qT q+Sa l(Sq Sql+ SlqT( S+sq qW qW! qHW qWa qW1 qW8 1HqW 1Wqa SqW S!qW Zq ", +"Zqa lWq qWS8 Zql sqZ qWd q+W HPqd gqW 1Wqd 1+qW qH1dP qWg1 Sqd q+Sd Zqd gqZ", +" Sqld q+lW ldZq sqgS oq oq! oqB oqa 7oq oq8 7Boq oq7a Soq S!oq oqT oqSa r r", +"8 rT rs oq; oq+ oBq; q+oa q;7o q>o 7oq;B oaq> Sq; oqS+ qTS; q+oT r; r> r;T ", +"rs> oqW o!qW oqH qHoa 7qW qWo8 oq7H qHo8 qWSo SqWo! Zqo oaZq rW rW8 rZ rZs ", +"vq vq+ vqH goq vq7 vq> 7Hvq vqg7 vqS S+vq Zqv Zqgo rv rv> rZv yr q9 q& q9B ", +"qa9 q91 :q 91qB :qa q9M q&M qT9 qT& lq9 :ql l9qT sq: q9( q+9 9(qB 9+qa 91q(", +" :q+ q91(B :+qa 9Mq( 9+qM 9Tq( 9+qT q9l( l+:q qTl9( q+s: q9E q&E qH9 qH& 91", +"qE :qE 9Hq1 :qH 9MqE M&qE 9HqT HMq& q9lE lE:q l9qH lH:q qd9 qd& 9Hqd gq9 9d", +"q1 :qd qH91d gq: 9dqM dMq& 9Tqd qTg9 l9qd ld:q lHq9d g:sq q49 q&4 49qB 49qa", +" 7q9 :q7 q97B 7a:q 49qM 4Mq& 49qT 4Tq& l97q 7l:q 79qT :q7s q;9 q;& 9;qB 9aq", +"; 79q; q>: 7q9;B qa:> 9Mq; M;q& 9Tq; T;q& l9q; :ql> 7qT9; s:q> 49qE 4&qE 49", +"qH 4Hq& q97E 7E:q 79qH 7H:q q49ME q&4ME qH49T qH&4T 7lq9E :ql7E 7qHl9 :qH7s", +" 49qd 4dq& 9Hq; q;g9 79qd 7d:q 7qH9d g:q> qd49M qd&4M qH;9T gq49T 7qdl9 q>l", +":d 7qT9d glq7: q9P q&P 9PqB 9aqP 9Pq1 :qP q91PB qa:P Sq9 Sq& qTS9 qTS& lqS9", +" S:q Slq9T S:sq 9Pq( 9+qP q9P(B q+9aP q91P( q+:P 9P1q(B :q+aP q9S( q+S9 Sq9", +"T( Sq+9T Slq9( S+:q qTlS9( sq:S+ qW9 qW& 9HqW 9Wqa 9Wq1 :qW qH91W qH:W qWS9", +" qWS& Zq9 Zq& l9qW lW:q lqZ9 Zq: 9Wqd 9+qW qH9dP qWg9 qW19d q+:W 9HPqd1 gP:", +"q qdS9 qdS& qdZ9 g9Zq Sqdl9 Sd:q Zql9d S:gq oq9 oq& q9oB qao9 o97q o:q 7oq9", +"B oa:q So9 oqS& oTS9 o9Sa r9 r: r9T rs: q;o9 q+o9 oq9;B oq+9a 7oq9; q>o: o9", +";7qB o:q>a o9S; o9S+ Sq;9T Sqa9; r;9 r:> 9Tr; s:r> qWo9 qWo& qHo9 qHo& 79qW", +" 7W:q 7oHq9 oq:H SWo9 Sq&oW S9oZ oqZ& r9W r:W rZ9 rZ: vq9 vq& qHv9 g9vq v97", +"q :vq vq79H :vgq S9vq S&vq Z9vq Sog9 rv9 r:v Zvr9 yr: qU q!U qD qDa q1U q8U", +" qD1 qD8 qUM U!qM Vq Vqa lqU lUq8 Vql sqV qU( q+U qD( q+D 1Uq( 1Uq+ 1Dq( 1+", +"qD UMq( U+qM Vq( Vq+ qUl( lUq+ l(Vq l+Vq qUE U!qE qHU UHqa 1UqE U8qE 1UqH U", +"Hq8 UMqE q!UME VqH VHqa qUlE q8lUE lHVq qHVs qdU U+qd qDd gqU 1Uqd U8qd 1Dq", +"d qDg1 UdqM q+UdM Vqd gqV lUqd l+qUd ldVq gVsq q4U 4Uq! qD4 4Uqa 7qU q87U 7", +"qD qD7a 4UqM q!4UM Vq4 qaV4 lq7U 7lqU8 7Vq 7Vsq q;U 4Uq+ qD; 4+qD q;7U q>U ", +"q;7D q>D U;qM q+4UM Vq; q+V4 lUq; lq>U l;Vq V>q 4UqE q!4UE 4UqH qH4Ua qU7E ", +"7qU8E qH7U 7qHU8 q4UME 4UMq!E qHV4 Vq4Ha 7lqUE q8l7UE 7HVq sq7VH 4Uqd q+4Ud", +" 4Dqd qDg4 qd7U >Uqd qD7d gUq> qd4UM 4U+qdM qHV; g4Vq 7qdlU q>lUd 7dVq 7Vgq", +" qUP UPq! qDP UaqP 1UqP U8qP 1DqP D8qP SqU q!SU VqS SaVq lUSq SUq8 SlVq VqS", +"s UPq( U+qP DPq( +DqP q1UP( q+1UP qD1P( q+D1P qUS( SUq+ S(Vq S+Vq SlqU( Sq+", +"lU SlVq( Vq+Ss qWU UWq! qWD UWqa 1UqW UWq8 1WqD WDq8 SUqW SqUW! ZqV qaVZ lU", +"qW Sq8UW lZVq sZVq UWqd U+qW WDqd qWgU qW1Ud q+W1U qWD1d gq1UW SUqd Sq+UW S", +"dVq gVZq SqdlU Sq8Ud VqdlZ glqSV oqU q!oU oqD qDoa 7oU o87U oq7D oU7a oUSq ", +"SqUo! oVq oaVq rU rU8 rV rVs q;oU q+oU q;oD q+oD 7;oU 7Uo> 7oUD; oDq> SUq; ", +"Sq+oU S;Vq o+Vq r;U r>U rV; rV> qWoU oqUW! qHoU oqHUa oU7W 7oUW8 oU7H 7oUH8", +" SqUoW oUWSq! oVZq oVZqa rUW UWr8 rZV sZrV vqU q+vU vqD gUvq 7Uvq vUq> 7Dvq", +" 7ogU vUSq vqSU+ Vvq oVgq rvU v>rU rVv yrV tq tq& tqD cq tq1 :qt t1qD cq: t", +"qM tMq& Vqt cqV ltq lt:q ltVq uq tq( tq+ t(qD cq+ q1t( t+:q tq1D( q+:c qMt(", +" tMq+ t(Vq t+Vq l(tq tql+ Vqlt( uq+ tqE tEq& tqH cqH q1tE tE:q t1qH tH:q qM", +"tE tqM&E tHVq qHVc lEtq :qltE tqlH uqH tqd q+td qHtd gqt t1qd td:q tqH1d g:", +"cq tMqd tq+dM tdVq gVcq tqld :qdlt Vqdlt uqg tq4 q&t4 qDt4 cq4 7tq :q7t 7Dt", +"q 7cq q4tM tq4M& t4Vq c4Vq 7ltq 7tl:q Vq7t uq7 tq; q+t4 qDt; cq; 7qt; t>q t", +"q;7D cq> tMq; tq+4M t;Vq c;Vq tql; ltq> Vq;7t uq> q4tE tq4&E qHt4 qHc4 tE7q", +" 7tq:E 7qtH 7Hcq tq4ME q&Mt4E tqHV4 cqV4H 7tlqE :ql7tE 7tHVq 7quH qdt4 tq+4", +"d qHt; g4cq 7qtd tdq> 7tHqd t>gq tqd4M t4Mqd& Vqdt4 cq;gV 7tdlq t>qld 7Vdtq", +" gqu7 tqP q&tP qDtP cqP q1tP tP:q tq1DP :Pcq Stq S&tq VqSt Scq Sqlt :qSt Sl", +"Vtq uqS qPt( q+tP tqDP( q+cP tq1P( tq+:P qD1tP( cq:+P S(tq tqS+ StqV( S+cq ", +"Stlq( St+:q VqlSt( Squ+ tqW q&tW qHtW cqW t1qW tW:q tqH1W :Wcq tWSq Sq&tW t", +"Zq Zqc tqlW :qWSt ltZq uZq qWtd q+tW tqHdP gPcq tqW1d :qWt+ tW1qDd cqWg: Sd", +"tq St+qW tdZq Scgq Stdlq S:dtq tZqld gquZ ot ot& otD otc ot7 ot: 7Dot ot7c ", +"otS S&ot oVt otSc rt rt: rVt ur ot; ot+ oDt; t+oc 7ot; t>o ot7D; oct> S;ot ", +"S+ot t;oV S;cq rt; rt> t;rV ur> otW o&tW otH tHoc 7otW tWo: 7otH tHo: tWSo ", +"otSW& tZo octZ rtW t:rW rZt urZ tvo t+vq tHvq got 7tvq ot:v otH7v t>go Stvq", +" ot+Sv Zqtv tZgo rtv tvr: tZrv ury n= 5n=B =a>n =nK", +" +n=K =Tn +T=n =jn =j>n 5T=n s=n n H5=n >ng= dn=K =+dnK Hn=T gn=T dn=j >n=dj Hn=j gns=

= o5=B =ao> =Qo o+=Q =To o+=T p=o p=o> op=T s=o oW< Wo= =5oH o>g= ov=Q ov=+Q Z=o Z=go ovp= o>pv= p=oZ yo= ,n ,n& ,nB ,an ,", +"n. ,8n n.,B 8n,a ,nK ,K&n ,Tn T&,n ,nj 8n,j Tn,j sn, ,n* -n *B,n -na ,.n* -", +"n8 n*.,B 8n-a ,Kn* -nK T*,n -Tn n*,j -nj n*j,T s-n ,nE ,E&n ,Hn H&,n nE,. ,", +"E8n ,.Hn H8,n nE,K <&EnK Hn,T ,HnT& ,Enj <&jnE Hn,j ,Hsn ,dn -nd Hn,d g-n ,", +".dn 8d-n ,Hnd. g8-n ,Kdn dn-K Td,n -Tgn dn,j dn-j dnj,H gns- ,4n 4&,n 4B,n ", +"4a,n ,5n 48,n ,B5n 5a,n 4n,K <&K4n 4T,n ,4Tan 4j,n <&j5n 5T,n ,4sn =n, -=n ", +",n=B -n=a ,5=n >n- =B5,n -a>n ,n=K =K-n ,T=n -n=T ,n=j -n=j =T5,n >ns- 4n,E", +" <&E4n 4H,n ,4Han ,E5n ,48nE H5,n ,4H8n ,4nEK ,4E&nK ,4HTn 4H&,Tn ,4jnE n =H5,n g->n =dn,K -=dnK =HT,n ", +"g=-Tn =jd,n >n-dj =Hj,n s-ng= ,P< o=5,B ->oa o,=Q o-Q o,=T o-T o,p= o-p p=o,T os- o,W ,Wo& oH, ,Hoa ,", +"5oW ,Wo8 ,Ho5 ,Ho8 ,WoQ o&W,Q oZ, oaZ, oWp, op&,W opZ, s,oZ ov, o-v o,=H go", +"- o5v, -vo> ov,H5 g-o> oQv, -Qov ovZ, Z-o pvo, op-v oZ,p= yo- C 5D=n =D>n nC=K =+nCK Dn=T =D+Tn nj=C >n=jC Dn=j sn=D 4n=dC =H5Dn g=>Dn =d", +"nCK dnC=+K =HDTn g=DTn =jdnC =jd>nC =HjDn s=gDn Co= =5oD =Do", +"> oQ=C o=+QC oD=Q o+D=Q =Cop o>p=C op=D =Dos Wv=C ovD=5 go>=D ov=QC =Qvo+C =DoZ goZ=D p=ovC p=vo>C p=D", +"oZ =Dyo ,nb <&bn ,Dn cn =b5Dn >nc= bn=K =b-nK bT=n cn=T bn=j >n-bj =bT5n snc", +"= ,4bnE ,4b&nE ,4Hbn c4H,n ,5nbE <&Eb5n ,H5bn c5n-bd =bH5n c", +"=g>n =bdnK -nd=bK =bHTn c=gTn =bjdn >nd=bj =bHnj s=cgn b

=bo5D", +" c>o- ob=Q -Qob ob=T =Qoc op=b ob-p p=boD ocs= ,Wob obW<& ,Hob oHc< ob5,W o", +"b8,W obH,5 ocH,5 obW,Q bWb ovD,5 cv=o> ovb=Q o-vbQ =boZ ocZ- p=bov o-pvb Z=bop o", +"cy- 6n =n7B =n7a 6n=K =6+nK 6T=n =T6+n 7n=j 7>=nj =n7T 7=sn 46", +"=dn =n7H 7=gn =6dnK d", +"nK=6+ =H6Tn g=6Tn 7=dnj >n=7dj 7Td=n g7s=n 6P< 6!

=B7o 7o=a o6=Q o=6+Q =6o", +"T o+T=6 7op= 7o=p> 7o=T 7os= 6Wo< o!6W< 6Ho< oH6a< oW7< 7oW8< 7 7o=H 7og= ov=6Q =Qvo+6 o=Z6 goZ=6 7o=pv o>p7v= 7oZ= 7oy= ?n ?&n ?Bn ?an ", +"?1n ?:n 1n?B :n?a ?nK &n?K ?Tn T&?n ?jn :n?j 1T?n s?n ?n* ?-n n*?B -n?a 1n?", +"* :-n ?B1n* :a-n n*?K ?K-n Tn?* -n?T n*?j -n?j ?T1n* ?-sn ?nE &n?E ?Hn H&?n", +" 1n?E ?E:n 1H?n :n?H nE?K ?&nEK Hn?T ?HTan nj?E ?:njE Hn?j ?Hsn ?dn -n?d Hn", +"?d g?n 1d?n :n?d ?H1dn ?:gn dn?K ?-dnK Td?n ?Tgn dn?j ?:dnj ?Hjdn gns? ?4n ", +"4&?n 4n?B 4a?n 7?n :n7? ?n7B ?n7a 4n?K ?4&nK 4T?n ?T4an 7n?j ?:7nj ?n7T 7?s", +"n ?=n -n?= ?B=n =n?a =n7? An ?=7nB Aan ?n=K ?-=nK =n?T ?-T=n =n?j Ajn ?T7=n", +" Asn 4n?E ?4&nE 4H?n ?H4an 7n?E ?:7nE ?n7H ?:H7n ?4nEK &nE?4K ?H4Tn 4H&?Tn ", +"?j7nE 7:n?jE ?H7Tn s?7Hn =n?d ?-=dn =n?H ?=gn ?n7d Adn ?H7=n Agn ?=dnK -=n?", +"dK ?Td=n g?=Tn ?d7nj dnAj ?Hj=n gsAn ?P ?P& ?PB ?aP ?P1 ?:P 1P?B :P?a ?QP Q", +"&?P ?TP Qa?P ?Pj :Q?P 1T?P s?P ?P* ?-P P*?B -P?a 1P?* :-?P ?P1*B ?:P-a Qn?*", +" -Q?P TP?* -T?P P*?j -Q:n ?TP1* ?-sP ?WP W&?P ?HP HP?a 1W?P :W?P 1H?P :H?P ", +"Wn?Q ?WQP& ?ZP Z&?P Wn?j ?:WQn Z1?P sP?Z ?dP -W?P HP?d g?P 1d?P :d?P ?HP1d ", +"?:gP Qd?P ?-WQn Zn?d gP?Z dP?j ?:QdP ?Z1dP gPs? o? o?& o?B o?a o?7 o:? 7Bo?", +" ?ao: o?Q o&?Q o?T oT?a ?po o:?p 7o?T s?o o?= o-? =Bo? =ao? 7o?= Ao 7o=?B A", +"oa =Qo? ?Qo- =To? ?To- p=o? Aop o?Tp= Aos o?W o&?W o?H oH?a 7o?W ?Wo: 7o?H ", +"?Ho: oW?Q o?WQ& ?Zo ?aoZ op?W o:?pW o?7Z os?Z ?vo o-?v =Ho? go? o?7v Aov o?", +"H7v Aog ov?Q o-?vQ o?Z= ?Zgo op?v opAv ?Zo7v yAo =nC =n7D 7", +">D=n =6nCK 6+n=CK =D6Tn 6+D=Tn 7=njC >nj7=C =D7Tn s=7Dn 6n=7dC 7Dd=n g7=Dn ", +"dnC=6K dn=C6+K 6Dd=Tn g6D=Tn =jn7dC >j7d=nC 7Hn=Dj s=Dg7n 6C

C 7o=D o>D", +"7= o=6QC =Q6o+C =QDo6 o+6=QD 7o=pC p=7o>C p=D7o s=o7D o6W=7vC 7vDo= go7=D =Q6ovC =6o+vQ", +"C Z=o6D Z=6goD p=o7vC >C7vp=o 7Z=oD yo7=D ?bn bn?& ?Dn ?cn b1?n ?b:n 1D?n :", +"n?c bn?K ?b&nK bT?n cn?T bn?j ?:bnj Dn?j sn?c bn?* ?b-n Dn?* cn?- 1nb* :b-n", +" ?D1n* c-:n ?bn*K ?-bnK ?DTn* ?-Tcn ?jbn* ?-jbn ?Djn* s-n?c bn?E ?b&nE bH?n", +" cn?H ?b1nE ?:bnE ?Hb1n ?:Hcn ?bnEK &nE?bK ?HbTn ?cHTn ?jbnE :nb?jE ?Hjbn s", +"?cHn bd?n ?-bdn Dd?n gn?c ?d1bn ?:dbn ?Dd1n g:n?c ?dbnK -nb?dK ?DdTn g?cTn ", +"?djbn ?db-nj ?Ddnj g?scn 4b?n ?4b&n 4D?n ?4cn ?n7b ?:7bn ?n7D cn7? ?4bnK &n", +"K?4b ?D4Tn ?c4Tn ?j7bn 7:b?jn ?D7Tn s?7cn ?b=n ?-=bn =n?D cn?= =n7b Abn ?D7", +"=n Acn ?=nbK =bn?-K =bT?n c=?Tn =b7nj bnAj ?Dj=n scAn ?4bnE &nE?4b ?H4bn ?c", +"4Hn 7?bnE 7bn?:E ?H7bn 7c?Hn 4bn?EK &n?E4bK 4bH?Tn c4H?Tn 7bn?jE 7j?E:nb ?H", +"n7bT 7cHs?n ?=dbn =b-?dn ?Dd=n c=?gn ?d7bn bdAn ?D7dn gcAn =bn?dK =d-n?bK ?", +"Hn=bT g?Tc=n ?dn=bj Adnbj ?Hn=bj Agnsc ?Pb bP?& ?DP ?cP b1?P ?b:P 1D?P :c?P", +" bQ?P ?QbP& bT?P cQ?P bP?j ?:QbP DP?j sP?c bP?* ?b-P DP?* c-?P ?Pb1* ?:P-b ", +"?DP1* ?cP:- ?QbP* ?-QbP ?QDP* ?cQ-P ?Pjb* ?-Pbj ?DP*j s?Pc- bW?P ?WbP& bH?P", +" cW?P ?Wb1P ?:WbP ?HPb1 ?cW:P ?WbQn bWn?Q& Zb?P ?PZc ?WjbP ?Wb:Qn ?Zb1P s?Z", +"cP bd?P ?-WbP Dd?P gP?c ?dPb1 ?:dbP ?Dd1P g?P:c ?QdbP ?Wb-Qn ?ZbdP g?ZcP ?d", +"Pbj ?Wb-Pj ?DdPj g?scP o?b ?bo& o?D oc? 7bo? ob?: 7o?D ?co: ob?Q o?bQ& ob?T", +" ?Qoc ob?p o:?pb op?D ocs? =bo? ob?- =Do? ?co- 7o=b Aob o?D7= Aoc o?=bQ o-?", +"bQ o?D=Q oc?=Q p=bo? opAb ?pDo= osAc ob?W o?bW& ob?H ?Hoc ?W7ob o:?bW o?H7b", +" o:H?c o?bWQ obW?Q& ?DoZ oc?Z ?pobW ?pbo:W ?Zo7b s?oZc ob?v o-?vb ov?D ocg?", +" 7vbo? ovAb ?vD7o goAc ?vobQ ?vbo-Q ?Zo=b go?Zc ?pvob Aopvb ?pvoD yoAc R< R", +" R5=B >R=a =RM R+=M =RT R+=T =Rj =R>M R", +"5=T s=R 4R RH=5 g>=R Rd=M =R+dM", +" RH=T gR=T Rd=j >M=Rd RH=j gs=R R

o=5RB o>=Ra S= S=+ S=T S=a S=p S>= Sp=T s=S RWo< o!RW< RHo< o", +"HRa< 5WR< o8RW< oHR5< oH8R< oWS< S=R =RvH5 g=Ro> S=v v=S+ S=Z gS= p=Sv v>S= SZp= y=S ,", +"R< R<& RB,n Ra,n ,.R< R8,n ,R<.B ,R8a< ,Mn =R =R5,B >n-Ra ,R=M -R=M ,R=T -R=T ,R=j -R=j =RT,5 =Rs- ,ER4 ,R4&E ", +"R4,H ,R4H& ,R45E ,R48E ,R4H5 ,R4H8 ,R4ME n-Rd =RH,5 g=R-> =Rd,M =R-dM =RH,T g=", +"R-T =Rj,d >M-dn =RH,j s=Rg- R<,P o,5=RB o->Ra ", +"S=, S-o S,=T =TS- S,p= o-S> S=p,T S-s= ,RoW o&R,W ,RoH oH&,R o,R5W o8,RW oH", +",R5 oH8,R SWo, S<&oW S,oZ oZ&S< Sp<,W SpR =R5oH, go->R ovS, Svo- S,Z= S-go Sv,p= o-pSv S=Zp, S-yo Rn R5=D >R=D Un=M =RU+M V=R V+=R Rj=U >M=Un V5=R >nV= R4UnU=d =RHU5 g=R>U =RUdM d", +"Mn=U+ Vd=R =RgV =RjUd >nd=Uj V=RH5 V>ng= U

=RDo5 o>U=D S=U S+", +"=U S=V =aoV Sp=U =US> VpS= oVs= UWo< oUWUv= =Rv5D goU>= =USv S=vU+ oVZ= V=go p=USv S>=vU oVvp= S=yV ,Un bn =Rb5D =Rc> Rb=M =R-bM Vn=b =RV- Rb=j >M-bn V=R,5 >nV- ,R4bE <&ER", +"4b ,R4bH cR4,H ,U5nE <&ERb5 ,UH5n cR5H< n-Ud =RbH5 c=Rg> =RbdM =bd", +"-Mn V=R,H c=VgR =Rbdj >Md=Rb =RbHj c=Rgs bPR< ", +"oU ob5=RD oc->R S=b =bS- =boV Sc= Sp=b =bS> oV,p= Scs= ,UoW oU&,W ,UoH ocR,", +"H oU,5W oU8,W oUH,5 cR5W< Sb ob5=RH cv=>R =bSv o-USv SZ=b Z=Sc S=bpv o-", +"pvU oVvp, Scy= q< q!< q= =B7q =aq> q=M q+=M q=T q+=T l=q q", +">l= 7q=T sq= 4=qd 7q=H g=q> qd=M ", +"q=+dM qH=T =Tgq ldq= q>l=d lHq= l=gq q

7o=qB q>o=a S=q S+q= Sq=T Sq=a r= r>= r=T rs= oq= vq7=H vq>g= vqS= vq=S+ Zq= S=gq rv= v>r= rZ= ", +"yr= ?q ?q& ?qB ?qa ?q1 :q? q1?B ?a:q ?qM q&?M ?qT qT?a l?q l?:q qTl? s?q ?q", +"* -q ?Bq* -qa ?1q* -q: ?q1*B qa:- q*?M -qM q*?T -qT ?ql* l-q ?qTl* sq- ?qE ", +"?Eq& ?qH qH?a q1?E ?E:q ?1qH ?H:q qM?E ?qM&E qH?T ?qHT& lE?q :ql?E ?qlH ?Hs", +"q ?qd -qd qH?d g?q ?1qd ?d:q ?qH1d g:-q qd?M qd-M qT?d gM-q ?qld ld-q l?Hqd", +" gql- ?q4 ?4q& q4?B ?4qa ?q7 7?:q 7B?q 7q?a q4?M ?q4M& ?4qT ?qT4a 7l?q ?q7l", +": 7q?T ?q7s q=? -q= =B?q =a-q 7?q= Aq ?q7=B Aqa ?q=M =M-q ?q=T =T-q l?q= Al", +"q l=?qT Aqs q4?E ?q4&E ?4qH ?qH4a ?E7q ?q7:E 7q?H :qH7? ?q4ME q&4?ME ?qH4T ", +"?H4qT& ?q7lE l?7:qE l?H7q s?q7H ?dq= qd-= ?q=H g=-q 7q?d Aqd q=H7? Aqg ?qd=", +"M -q=dM q=H?T -qTg= l=?qd ldAq l=H?q glAq ?qP q&?P qP?B qa?P q1?P ?P:q ?q1P", +"B ?qa:P S? S?& S?T S?a S?l S?: ?TSl s?S q*?P -qP ?qP*B qa-P ?q1P* :P-q q*1?", +"PB -q:aP S?* S?- S*?T ?TS- l*S? S?l- S?lT* S-s? ?qW q&?W qH?W qW?a ?1qW ?W:", +"q ?qH1W :qH?W S?W S&?W S?Z ?aZq lWS? ?WS: l?Zq ?Zsq qW?d -qW ?qHW* gP-q ?qW", +"1d :W-q ?H1qW* -qWg: S?d ?WS- ?dZq g?S ldS? lW-q S?Zld s?gS o?q o&?q ?Boq o", +"q?a 7o?q o?:q ?q7oB o:?qa S?o S&o? ?TSo ?aSo r? r?: r?T r?s q=o? o-q o?q=B ", +"oa-q ?q7o= Aoq q=7o?B oqAa S?= o-S? =TS? =aS? r?= Ar =Tr? Ars oq?W ?qWo& oq", +"?H o?Hqa 7q?W o:?qW o?H7q o:H?q ?WSo S?oW& o?Zq S?Zoa r?W ?:rW r?Z s?rZ ?vq", +" -qv ?Hvq ?vgq ?q7v Aqv ?vq7H goAq S?v S-?v S=?Z S?go r?v Arv ?Zrv Ary qU< ", +"U 7q=D =Dq> qU=M q=U+M V=q =aVq lq=U q>l=U Vql= V=sq q4U=Ud q=H7U q>Dg= q=UdM q+U", +"=Md =HVq V=gq l=qUd l=Uq>d V=qlH V>qg= Uo=U q=D7o q>Do= Sq=U S=qU+ VqS= oV+q= r=U =Ur> rV= s=rV oqUW< qW=U vqD7= vq>=D vq=SU S=Uvq+ V=Zq Vv", +"qg= =Urv rv>=U Z=rV y=rV ?qt q&?t ?qD cq? ?1tq ?t:q ?1qD :q?c tq?M ?qtM& V?", +"q V?cq ?qlt ?t:lq l?Vq u?q tq* -qt qDt* cq- t1q* :qt- ?qD1* :c-q tMq* -Mtq ", +"t*Vq V-q tql* lt-q V?lq* uq- ?Etq ?qt&E tq?H ?Hcq ?qt1E ?t:qE ?qHt1 cq?:H ?", +"qtME tq&?ME ?HVq cq?VH l?qtE l?t:qE V?lqH ?quH tq?d td-q qHt* cqg? ?qdt1 -q", +"t:d ?qD1d cq-g: ?qdtM -qtdM ?dVq V?gq l?dtq l-qtd V?dlq g?uq t4?q ?qt4& ?4q", +"D c4?q ?q7t ?q7t: 7q?D ?q7c ?qt4M tq4?M& V4?q cq?V4 ?q7lt :ql7t? ?q7V ?qu7 ", +"t=q -qt= ?q=D cq= q=7t Aqt q=D7t Aqc tq=M -qt=M Vqt= V=cq ltq= ltAq V=q7t A", +"uq ?qt4E t4&?qE ?qHt4 cq?4H ?q7tE :q?7tE 7tH?q 7cq?H tq4?ME M&?Etq4 V?q4H V", +"?4cqH l?q7tE lE7t:q? 7V?qH u?q7H tdq= -qt=d tq=H t=gq 7tdq= tqAd t=H7q gqAt", +" t=qdM t=d-qM V?dq= cq=gV l=tqd Aqdlt V?d7q uqAg ?tP ?&tP tP?D ?Pcq ?1tP t:", +"?P ?qD1P cq?:P S?t S&?t S?V S?c l?St ?tS: SlV? u?S t*?P ?Pt- ?qDP* cP-q ?tP", +"1* -qt:P ?D1tP* cq-:P S*?t St-q S*V? cqS- St*l? l-qSt S?Vl* S?u- tq?W ?qWt&", +" tH?P ?Wcq ?qWt1 :qW?t ?qW1D cqW?: ?WSt S?tW& tZS? Sc?Z l?WSt S?:tW S?Zlt S", +"?uZ td?P tW-q ?qWDd ?tgP ?td1P -qWt: ?H1tdP cq-:W ?dSt -qWSt ?dSV S?gt S?dl", +"t -qWlt V?dSl g?uS ot? o&?t ?Dot ?cot o?7t ?to: ot?7D ot:?c otS? ot?S& oV? ", +"ocS? r?t ?tr: r?V ur? t=o ot- =Dot oct= 7ot= Aot t=o7D otAc S=t t=S- oVt= t", +"=Sc rt= Art t=rV Aru ?Wot ot?W& ?Hot otc?H ot?7W ot:?W otH7? ot:?H ot?SW S?", +"Wot& oV?Z oV?Zc ?trW r?t:W ?ZrV r?uZ ot?v o-tv =Hot t=go ?vq7t tvAo otH7= g", +"oAt tvS? ot-Sv tZS= ?vSc ?vrt rtAv ?vrV yAur Xn n!X XnB aXn Xn. 8Xn n.XB aX", +"8n XnK XKn! TXn aXTn Xjn Xj8n XjTn sXn Xn( +Xn n(XB aX+n n(X. 8X+n Xn(.B aX", +"n+8 n(XK Xn+K XnT( TX+n X(nj Xj+n XjnT( +Xsn Gn Gn! GnH Gan Gn. G8n G.Hn H8", +"Gn GnK n!GK GTn TnGa Gnj 8nGj HnGj sGn Gnd +Gn dXHn gXn G.dn G8+n dX.Hn G8g", +"n GKdn GK+n TdGn GTgn dnGj Gn+j dXjHn sGgn 4X 4X! 4XB 4aX 4X5 48X 4B5X 5a4X", +" 4XK XK4! 4TX TX4a 4Xj 8X4j 5T4X s4X 4X; 4+X 4BX; +X4a X;5n >X4 X;B5n 4a>X ", +"4KX; 4K+X T;4X +T4X X;4j 4X>j X;j4T s4>X 4GX 4!Gn 4HX Ga4X G5n G84X H54X H8", +"4X 4KGn 4GX!K GT4X 4GTaX Gn4j 4G8Xj HX4j 4GsX 4dX +G4X HX4d g4X 5d4X >nG 4H", +"X5d g4>X 4KdX 4+GXK Td4X 4TgX dX4j Gn>j dXj4H s4gX XPn XPn! PnXB XPan PnX. ", +"XP8n XPn.B aXP8n QXn n!QX TXQn aXQn XjQn 8XQn XjnTP QXsn PnX( XP+n XPn(B aX", +"P+n XPn(. +X8Pn Pn(X.B +X8aPn XnQ( QX+n QXnT( +QXTn XjnQ( +QX8n QXTnj( sX+Q", +"n Yn Yn! YHn Yan Yn. Y8n HnY. H8Yn YQn QnY! YZn ZnYa Yjn Q8Yn ZnYj sYn Ydn ", +"Y+n HnYd gYn dnY. +nY8 YHdn. Y8gn QdYn +QYn YdZn YZgn dnYj +nYj YZdnj gnsY ", +"oX o!X oXB oaX o5X o8X 5XoB 5aoX oQX QXo! oTX QaoX opX pXo8 pXoT osX oX; o+", +"X X;oB +Xoa 5Xo; o>X o5X;B oa>X QXo; +QoX TXo; +ToX o;pX op>X opTX; >Xos oY", +" oY! oYH Yao Y5o Y8o oHY5 oHY8 oYQ YQo! oZY YaoZ Ypo opY8 oZYp sYo Yvo Y+o ", +"oHYv goY ovY5 Y>o YvoH5 Y>go YQov YQo+ YvoZ oZgY opYv o>Yp YZvop yoY Xn# X&", +"n n#XB X&an n#X. X&8n Xn#.B aXn8& n#XK XK&n XnT# X&Tn X#nj &nXj XjnT# X&sn ", +"n#X( X&+n Xn#(B aXn+& Xn#(. X&n+8 n#(X.B +X8an& Xn#(K X&n+K TXn#( +TX&n Xjn", +"#( X&j+n TX#nj( sX+&n Gn# G&n G#Hn H&Gn n#G. 8nG& GnH#. G8nH& n#GK GK&n G#T", +"n T&Gn G#nj &nGj GTnj# G&sn G#dn G&+n dX#Hn G&gn dX#n. dX&8n HX#dn. gX8&n d", +"X#nK dX&nK GTnd# gXT&n dXjn# dX&nj dX#Hnj gsX&n 4X# 4X& X#4B aX4& 4#5X 5X4&", +" 4X5#B 48Xa& X#4K 4KX& 4#TX TX4& 4#Xj X&4j 4TX5# 4Xs& 4#X; +X4& X;#4B aX;4&", +" X;#5n 4X>& 5X#;nB >X4a& X;#4K X;&4K 4TX;# X;&4T X;j4# >X4&j X;#5Tn >Xs4& 4", +"#Gn G&4X 4#HX HX4& G#5n 5&Gn 4HX5# 4H8X& 4GX#K 4G&XK 4GTX# 4GTX& 4GjX# X&j4", +"G 4HXj# s4GX& 4#dX dX4& 4HXd# 4Xg& 4dX5# G&>n dX#H5n >Xg4& 4dX#K dX&4K 4TdX", +"# g4XT& dXj4# >nG&j dX#4Hj >nsG& PnX# XP&n XPn#B aXP&n XPn#. X&P8n Pn#X.B 8", +"XaP&n XnQ# X&Qn QXnT# QaX&n XjnQ# X&jQn QXTnj# sXQ&n XPn#( X&P+n Pn#X(B +Xa", +"P&n Pn#X(. +X8P&n .BX(Pn# aX+P8n& QXn#( +QX&n TX#Qn( QX&+Tn QX#nj( +QX&nj Q", +"#TnXj( +QXsn& Yn# Y&n HnY# H&Yn n#Y. 8nY& YHn#. Y8H&n QnY# Q&Yn Y#Zn ZnY& n", +"jY# &nYj YZnj# Y&sn dnY# +nY& YHdn# Y&gn Ydn#. Y+8&n dn#YH. gY8&n YQdn# Y+Q", +"&n YZdn# gYZ&n Yjdn# Y+j&n ZndYj# sYg&n oX# o&X X#oB aXo& 5Xo# 5Xo& o5X#B o", +"8aX& QXo# QXo& TXo# TXo& o#pX pXo& opTX# o&sX X;o# +Xo& oX;#B o+aX& o5X;# o", +"&>X X;#o5B o>aX& oQX;# o+QX& oTX;# o+TX& opX;# o>pX& pX;oT# os>X& oY# Y&o Y", +"#oH oHY& o5Y# o8Y& Y5oH# Y5ao& oQY# YQo& Y#oZ Y&oZ Y#op opY& YpoZ# Y&os Y#o", +"v ovY& YvoH# Y&go Yvo5# Y&o> ovHY5# goY>& YvoQ# Yv&oQ YZvo# goZY& Ypov# Yp&", +"o> oZvYp# Y&yo In In! DXn aIn In. 8In D.In 8IDn InK IKn! TIn aITn Inj Ij8n ", +"InDj sIn In( +In D(In DX+n n(I. 8I+n In(D. +DX8n n(IK +KIn T(In TI+n I(nj I", +"n+j InjD( +Isn GnI G!In Jn Jna G.In 8IGn Jn. J8n GKIn InKG! JnT TnJa InGj I", +"njG8 Jnj sJn Idn Gn+I Jnd gJn I.dn Id8n dnJ. J8gn dKIn Idn+K TdJn gTJn dnIj", +" Idn+j dnJj gnsJ 4IX 4!In 4DX DX4a 5In 8I4X 5D4X D84X 4KIn InK4! DX4T 4DXTa", +" In4j Inj48 DX4j 4DsX I;n +I4X D;4X +D4X I;5n >nI I;n5D 4D>X IK;n I;n+K I;T", +"n a;nTI ;nIj In>j I;n5T sI>n Gn4I In!4G J4X 4aJn 5IGn 4G8In J5n 48Jn InK4G ", +"4GKIn! 4TJn J4TaX Inj4G 4G8Inj 4XJj J4sX Id4X Idn4+ J;n J4gX Id5n Gn>I 5dJn", +" J>n Idn4K IdK4+X T;Jn gJ4TX Idn4j >nGIj ;nJj >nsJ IPn n!IP IPDn IPan PnI. ", +"IP8n IPnD. D8XPn QIn Q!In DXQn aIQn IjQn 8IQn IPjDn QIsn PnI( IP+n IPnD( +D", +"XPn IPn(. +IP8n DP(In. D8P+In Q(In QI+n QDXn( +QDIn IPjn( IPj+n IP(Dnj sIP+", +"n YIn InY! YJn JnYa InY. 8IYn Y.Jn JnY8 QIYn YQIn! ZJn ZaJn InYj Y8QIn JnYj", +" YJsn IdYn +IYn YdJn YJgn IdnY. Y+8In YJdn. gYJ8n IdQn Y+QIn ZdJn ZJgn YjId", +"n Y+jIn YJjdn sJngY oI oI! oDI oaI oI5 o8I 5DoI 5aoI oIQ QIo! oTI QaoI opI ", +"pIo8 pDoI osI oI; o+I DXo; +DoI 5Io; o>I oD5I; oD>X QIo; +QoI TIo; +ToI o;p", +"I p>oI opDI; sIo> oYI YIo! oJ oJa oIY5 oIY8 oJ5 oJ8 YQoI oYQI! oJZ oaZJ oIY", +"p Y8opI oJp oJs ovI oIY+ oJv goJ o5vI oIY> J5ov oJ> oQvI Y+oQI JvoZ gZoJ pv", +"oI o>IYp opJv yoJ bXn I&n DXbn cXn b.In 8Ibn In.bD 8Icn bKIn IK&n TIbn TIcn", +" Inbj &nIj InjbT cXsn b(In +Ibn In(bD +Icn In(b. I&n+8 DX(bn. cX+8n In(bK I", +"&n+K bTXn( cX+Tn Injb( I&n+j Ij(bTn sInc+ bGn G&bn Jnb cJn b.Gn G8bn bnJ. J", +"8cn bKGn I&nGK bTJn cTJn Gnbj I&nGj bnJj cJsn Gnbd +Gbn bdJn cJgn Idnb. Idn", +"b8 Jnbd. cJng8 IdnbK Idn&K JnbTd cJngT Idnbj Idn&j Jnjbd sJngc 4bX bX4& bX4", +"D c4X b54X b84X 4bX5D 48cX 4KbX I&n4K bT4X 4TcX bX4j I&n4j 4bT5X c4sX b;4X ", +"b+4X I;nbD 4+cX I;nb5 4b>X 5DXb;n c4>X I;nbK I;&nK I;nbT c4X+T I;nbj >Xb4j ", +"4bTX;j c>Xs4 bG4X I&n4G 4bJn J4cX G5bn I&nG5 b5Jn J5cn 4bGXK InK4G& J4bTX c", +"J4TX 4bGXj 4bGX&j J4jbX sJ4cX bd4X Idn4& b;Jn c4gX Idnb5 bG>n J5nbd cJ>n 4b", +"dXK IdK;&n J;nbT cJ;Tn dXj4b >nbGj J;nbj J>nsc IPbn P&In IPnbD IPcn IPnb. I", +"P&8n bPDIn. cX8Pn QIbn I&Qn bQXDn QIcn IPjbn IP&nj bTPInj sIPcn IPnb( IP&+n", +" bPDIn( cX+Pn bP(In. +IPb8n IPbnD(. +IPcn8 bQXn( I&n+Q IP(bTn cQX+n IP(bnj ", +"b+QInj InbjQD( sI+cQn Ybn bnY& JnYb Ycn bnY. b8Yn YJbn. cnY8 bQYn YbQ&n ZnY", +"b ZnYc bnYj Yb8Qn YZbnj snYc bdYn b+Yn YJbdn gnYc Ybdn. Yb+8n JndYb. Ycg8n ", +"YbQdn Yb+Qn YZbdn ZcngY Ybjdn Yb+nj YbdJnj sYcgn obI oI& bXoD ocI b5oI b8oI", +" ob5DX o8cX bQoI QIo& bToI oTcX pboI pIo& opbDX sIoc bXo; b+oI obDI; o+cX o", +"b5I; ob>X b5XoD; >Xoc obQI; ob+QI obTI; oc+QI opbI; o>bpI ob;pDX osc>X Ybo ", +"obY& oJb Yco obY5 obY8 J5ob Y5oc YQob YboQ& YboZ ZcoJ opYb Ypbo8 obJp osYc ", +"ovYb obY+ obJv Ycgo Yvbo5 Ybo> oJvb5 ocY> YvboQ Ybo+Q oJZvb ocZgY Ypbov Y>b", +"op oJpvb Ycyo 6X 6X! 6XB 6aX 6X1 68X 6B1X 1a6X 6XK XK6! 6TX TX6a 6Xj 8X6j 1", +"T6X s6X 6X( 6+X X(6B +X6a 6(1X 1+6X 6X1(B 6+X1a X(6K 6K+X 6(TX +T6X 6(Xj +X", +"6j 6TX1( 6+sX 6GX 6!Gn 6HX Ga6X 1Gn G86X 1H6X Ga1n 6KGn 6GX!K GT6X 6GTaX Gn", +"6j 6G8Xj GT1n 6GsX 6dX +G6X HX6d g6X 1d6X +G1n 6HX1d 68gX 6KdX 6+GXK Td6X 6", +"TgX dX6j dXj6+ dXj6H s6gX 4X6 6!4X 4B6X 6a4X 7X 7X8 7XB 7aX 4K6X 4X6!K 6T4X", +" 4TX6a 7Xj 8X7j 7TX 7sX 6X; 6+4X 6BX; aX6; 7X; >X7 X;7B 7a>X 6KX; 4+X6K TX6", +"; aX;6T X;7j >j7X TX7; >X7s 6G4X 4G6n! 6H4X 4Ga6X 7GX G87X 7HX Ga7X 4G6XK 6", +"GK4X! 4GT6X 6GT4aX Gn7j 7G8Xj GT7X 7GsX 6d4X 4+G6X HX6; 4Xg6 7dX 7G>X HX7d ", +"g7X 4dX6K X;K6+G 4Td6X g4X6T dX7j 7>GXj Td7X gX7s 6XP XP6! XP6B aX6P 1X6P 8", +"X6P 6X1PB 68XaP 6QX Q!6X QX6T Qa6X 1Q6X Q86X 6QX1T 6QsX XP6( +X6P 6XP(B 6+X", +"aP 6X1P( 6+X1P 1X(6PB 1+X6aP 6(QX +Q6X 6QXT( 6+QTX 6QX1( 6+Q1X Xj(6TP s6X+Q", +" Y6 Y6! Y6H Y6a Y61 Y68 6HY1 6HY8 Y6Q 6QY! YZ6 Z6Ya Y6j 6QY8 Z6Y1 sY6 Y6d Y", +"6+ 6HYd gY6 6dY1 6+Y1 Y61Hd Y6g1 6QYd 6+YQ YdZ6 YZg6 6dYj 6+Yj YZ61d g6sY o", +"6X 6Xo! 6XoB 6aoX 7oX o87X oX7B oa7X 6QoX o!6QX 6ToX oT6aX 7pX 78pX oT7X 7o", +"sX 6Xo; 6+oX o6X;B o+6aX oX7; 7o>X 7oX;B 7oa>X QX6; o+6QX oT6X; o+T6X 7;pX ", +"7p>X 7oTX; os7>X Y6o o!Y6 oHY6 oaY6 7Y 7Y8 7YH 7Ya o6YQ Y6oQ! Y6oZ YZ6oa 7Y", +"p Y87p 7ZY sY7 Yv6 o+Y6 YHv6 Yvg6 7Yv Y>7 7HYv g7Y YQv6 Yv6+Q ZvY6 gY6oZ 7v", +"Yp 7pY> YZ7v y7Y 6X9 6X& 6B9X 9a6X 1X9n :X6 6X19B 6a:X 6K9X 6KX& 9T6X TX6& ", +"9X6j 6X:j 6TX9j :Xs6 6(9X 9+6X 6X9(B 6+X9a 6X19( 6+:X 1X(9nB :X6+a 6X9(K 6+", +"X9K 6TX9( 6+T9X 6Xj9( :X6+j Xj(9Tn s:X6+ 9Gn G&6X 9H6X Ga9n 1G9n :Gn 6HX91 ", +"6H:X 9KGn 6G&XK GT9n 6GTX& Gn9j Gn:j 6HX9j :Gsn 9d6X +G9n 6HX9d 6Xg9 6dX91 ", +"6d:X 1HX9dn :Ggn 6dX9K dX&6K 6Td9X g6X9T dXj9n :Gn+j 9GTdnj g:Xs6 49X 6X4& ", +"4B9X 9a4X 7X9 7:X 9X7B :X7a 4K9X 49X&K 9T4X 49TaX 9X7j 7j:X 9T7X 7:sX 9X6; ", +"9+4X 49X;B aX;49 9X7; 7:>X 7X9;B 7:X>a 49X;K X;&6K 49TX; X;&6T 7X9;j 7:X>j ", +"7TX9; 7sX:> 9G4X 49GX& 9H4X 49GaX 9G7X :G7X 9H7X :H7X 49GXK X&K49G 49GTX 6G", +"T4X& 7G9Xj 7:GXj 7GT9X 7sG:X 9d4X dX&49 49HdX 49gX 9d7X :G>n 7HX9d 7:gX 49d", +"XK dXK49+ 49TdX g49TX 7dX9j 7:dXj 7Td9X g7Xs: 9X6P X&6P 6XP9B 6aX9P 6X19P 6", +"X:P 9X16PB :X6aP 9Q6X QX6& 6QX9T 6Qa9X 6QX9j 6Q:X 9TX6Pj :QXs6 6XP9( 6+X9P ", +"9X(6PB 9+X6aP 9X16P( :X6+P 6(9X1PB 6+X:Pa 6QX9( 6+Q9X 6Q(9TX 9+Q6TX Xj(9Qn ", +":QX6+ 6(QX9T1 sX+:Qn Y69 Y6& 6HY9 6HY& 9nY1 Y:6 Y691H :HY6 6QY9 6QY& Z6Y9 Z", +"6Y& 6jY9 :QY6 YZ69j s6Y: 6dY9 6+Y9 Y69Hd Y6g9 Y691d :dY6 9HnY1d g6Y: Y69Qd ", +"Y6+9Q YZ69d gY6Z9 Y6j9d Y:6+Q Y9dZ1n sY:g6 o9X 6Xo& 9XoB 9aoX o97X o:X 7o9X", +"B oa:X 9QoX o9QX& 9ToX o9TaX p97X 7X:p 7oT9X sXo: 9Xo; 9+oX o9X;B o9+aX 7o9", +"X; >Xo: o9;7XB o:>aX o9QX; o9+QX o9TX; o9+TX 7pX9; o:p>X 7T;p9X os:>X Y9o o", +"9Y& oHY9 o9Ya 7Y9 Y:o 7HY9 Yao: YQo9 Y6&oQ Y9oZ oZ9Ya Y97p Ypo: Y97Z Y:7Z o", +"vY9 o9Y+ Yv69H Y9go Y97v :v7Y 7Yv9H Y:go Yv69Q Yv6Q& oZ9Yv go9YZ Yp97v Y:op", +"v 7ZYv9 Y:yo 6IX 6!In 6DX DX6a 1In 8I6X 1D6X D86X 6KIn InK6! DX6T 6DXTa In6", +"j Inj68 DX6j 6DsX 6(In +I6X 6(DX +D6X 1(In +I1n 6DX1( 6+D1X In(6K 6+IXK 6DX", +"T( 6+DTX Inj6( Inj6+ 6DXj( sIn6+ Gn6I In!6G J6X 6aJn Gn1I 6G8In J1n 68Jn In", +"K6G 6GKIn! 6TJn J6TaX Inj6G 6G8Inj 6XJj J6sX Id6X Idn6+ 6dJn J6gX Id1n Idn6", +"8 1dJn J1gn Idn6K IdK6+X J6TdX gJ6TX Idn6j 6+GInj J6jdX sJ6gX 6I4X In!46 6D", +"4X 4DX6a 7IX 8I7X 7DX D87X InK46 6IK4X! 4DX6T 6TI4aX In7j 7I8Xj DX7T 7DsX I", +";6X I;n6+ DX6; aX;6D I;7X 7I>X DX7; 7D>X I;n6K I;K6+X I;n6T 6+D4TX 7IX;j 7>", +"IXj 7DXT; 7sI>X 4G6In 4G6In! 4XJ6 J46aX Gn7I 7G8In 7JX J87X 4G6InK 6!4GInK ", +"J46TX 4TXJ6a 7GIXj Inj7G8 Jn7T sX7J Idn6; 6+GI;n 6XJ; gJ46X Id7X 7>GIn J;7X", +" >X7J IdK6X; Id4X6+K J6;TX J4Tg6X 7IdXj >Ij7dX 7JTdX J>n7s 6IP 6!IP DX6P aI", +"6P 1I6P 8I6P 6DX1P 6D8IP QI6X 6QIn! QD6X 6QDaX QI1n IPj68 IPj6D 6IsP 6(IP +", +"I6P 6DXP( 6+DIP 6IP1( 6+I1P IP(1Dn 1+D6IP 6QIX( 6+QIP 6QDX( 6+QDX IPj6( IPj", +"6+ IP(6Dj sIP6+ Y6I 6IY! YJ6 J6Ya 6IY1 68YI J6Y1 J6Y8 6QYI Y6QI! ZJY6 YZ6Ja", +" 6IYj Y68QI J6Yj YJs6 6IYd 6+YI YdJ6 YJg6 Y61Id Y6+1I YJ61d gY6J1 Y6QId Y6+", +"QI YZ6Jd gY6ZJ Y6jId Y6+Ij YJ6dj sY6gJ oI6 6Io! 6DoI 6aoI 7oI o87I oD7I oa7", +"I 6QoI oIQ6! 6ToI oTI6a op7I 7oIp8 oT7I 7osI 6Io; 6+oI oD6I; o+D6I 7;oI 7Io", +"> 7oDI; o>D7I oIQ6; o+I6Q oTI6; o+T6I 7oIp; o>I7p 7oTI; osI7> oIY6 Y6oI! oJ", +"6 oaJ6 7YI 7IY8 7Jo Y87J Y6oQI oIQY6! Z6oJ oJZ6a 7IYp 7Yp8I oJ7Z 7JsY v6oI ", +"Yv6+I Y6Jv g6oJ 7IYv 7IY> 7voJ 7Jgo Yv6QI Y6Qo+I oJZv6 goJZ6 7vIYp Y>7pI oJ", +"p7v 7Jyo b6X 6&bX 6DbX c6X 6Xb1 :In b6X1D c6:X bK6X I&n6K 6TbX 6TcX 6Xbj In", +":j Inj9D :Isn b(6X 6+bX b6XD( 6+cX b6X1( +I:n b6(1DX :cX6+ b6X(K b6+XK b6TX", +"( c6X+T Inj9( :In+j In(b1T sIn:+ 6GbX I&n6G J9n J6cX 1Gbn bG:n b1Jn :Jn b6G", +"XK I&K9Gn 9TJn cJ6TX Inj9G :Gnbj 9nJj sn:J 6dbX Idn6& 9dJn c6gX Idnb1 Id:n ", +"J9n1d gn:J Idn9K IdK6X& J9nTd c6XgT Idn9j :Idnj J9ndj :Jngs b64X I&n49 9D4X", +" 49cX 7bX :I7X bX7D 7cX 4bX6K I&K49X 4bT6X c4X6T bX7j 7:IXj bT7X sX7c 6Xb; ", +"I;&6X I;n9D 6Xc; bX7; 7b>X 7bXD; >X7c I;n9K I;K6X& I;n9T c6XT; 7bX;j 7>bXj ", +"7bTX; 7cXs> 4bG6X 49GI&n 49Jn cJ46X bG7X 7:GbX J97X 7X:J InK49G 4KbG6X& J49", +"TX c4TJ9n 7bGXj 7bj:Gn 7JbTX 7Js:X Idn49 49+Idn 9;Jn cJ6X; bd7X 7:IdX 7JbdX", +" >n:J IdK49X dX4&b6K J9;Tn c4Tg6X 7bdXj >Ij:Gn 7bTdX J>ns: 6IbP IP6& b6XDP ", +"6IcP b6X1P 6I:P 6DXb1P :cX6P 6QbX IP&6Q b6QDX 6QcX IPjb6 QI:n b6TIPj sIP:n ", +"b6XP( IP&6+ IP(9Dn c6X+P IP(b1n :IP6+ b(6X1DP :I+c6P b6QX( b6+QX IP(b6T c6Q", +"+X IP(b6j :QI+n 6XbjQD( sI+:Qn Yb6 b6Y& J6Yb Yc6 b6Y1 :IY6 YJ6b1 Y6:J b6YQ ", +"Yb6Q& ZbY6 Y6Zc b6Yj Y:b6Q YZb6j s6Yc b6Yd b6Y+ YJ6bd g6Yc Yb61d Y:b6+ YbdJ", +"1n Y:Jg6 Yb6Qd Yb6+Q YZb6d Yc6gZ Yb6dj Yb6+j YbdZ1n sYcg6 o9I 6Io& 9DoI o9c", +"X ob7I o:I 7obDX 7Ioc 9QoI o9IQ& 9ToI oc6QI pb7X op:I 7obTI sIo: 9Io; 9+oI ", +"o9DI; oc6+I 7obI; :Io> 7D;o9I o:Ic> o9IQ; o9+QI o9TI; c6QX; 7pbX; o:Ip> 7b;", +"oTI os:>I obY6 Ybo6& oJ9 Y6oc 7Yb Ybo: Yb7J Yc7 Ybo6Q Y6QoI& Z9oJ oJ9Zc Yb7", +"p o:IYp Yb7Z Yc7Z vbY6 Yvb6+ o9Jv g9oJ Yb7v 7>Yb oJ97v Ycg7 Yvb6Q YbQo9+ oJ", +"9Zv oJ9gZ 7Ybpv :vIop oJpv9 Ycy7 RXn n!RX XnRB RXan XnR. RX8n RXn.B aXnR8 X", +"Mn n!XM XMTn XMan MnXj XM8n XMnTj XMsn XnR( RX+n RXn(B aXnR+ RXn(. R+8Xn Xn", +"(R.B R+8aXn X(Mn XM+n XMnT( aXM+n XMnj( R+jXn RTXnj( sX+Mn RGn R!Gn GnRH Gn", +"Ra R.Gn GnR8 RGHn. RG8Hn GMn G!Mn GnRT aMGn GnRj 8MGn RGTnj RGsn GnRd +nRG ", +"RGHdn RGgn dX.Rn R+G8n RGHdn. gRG8n dMGn GM+n dXMHn GMgn dXMnj dXM8n RGTdnj", +" gsRGn R4X 4!RX RB4X 4XRa 4XR5 4XR8 R45XB R48aX 4XM 4!XM 4XRT aX4M 4XRj 8X4", +"M R4T5X R4sX 4XR; 4XR+ X;BR4 aX;R4 R45X; R4>X R45X;B >XR4a X;4M +X4M XM;4T ", +"aXM4+ XM;4j 4X>M R4TX;j >XsR4 R4G 4!RG 4GRH 4GRa 4GR5 4GR8 R4GH5 R4GH8 4MRG", +" R4GM! 4GRT aXM4G 4GRj R4G8M R4GHj R4sG 4GRd 4+RG R4GH; R4gX R4G5d R4>G 4HX", +"R5d >XgR4 dX4M dXM4+ dXM4H 4XgM dXM4j GM>n R4HdXj >Xg4M XPRn RXPn! RXPnB aX", +"PRn RXPn. R8XPn XPnR.B R8XaPn SXn n!SX TXSn aXSn XjSn 8XSn STXnj SXsn RXPn(", +" R+XPn XPnR(B R+XaPn XPnR(. +XPR8n .BR(XPn aX+PR8n XnS( +XSn STXn( S+TXn SX", +"nj( S+8Xn XjnST( Ss+Xn YRn RnY! RHYn RaYn RnY. R8Yn YRHn. Y8RHn SYn YnS! Zn", +"SY SnYa SnYj SnY8 SZYnj SYsn RdYn R+Yn YRHdn YRgn YRdn. Y+R8n dn.YRH gYR8n ", +"YdSn SnY+ SZYdn SYgn SYdnj SY+8n YZnSdj gSsYn oRX RXo! RXoB RaoX R5oX R8oX ", +"oR5XB o8RaX SoX o!SX SXoT SXoa pXSo SXo8 SpToX sXSo R;oX R+oX oRX;B o+RaX o", +"R5X; oR>X X;BoR5 o>RaX oXS; SXo+ S;ToX Sa;oX SpXo; So>X opTS;X os>SX oYR YR", +"o! YRoH YRoa oRY5 YRo8 Y5oRH Y5aoR SoY S!oY SYoZ YaSo SoYp Y8So SZpoY SosY ", +"vRoY YRo+ YvoRH oYgR YvoR5 >RoY ovRY5H goY>R YvSo Y+So YZvSo SogY SvoYp SoY", +"> YpoSvZ SoyY XnR# RX&n RXn#B aXnR& RXn#. X&nR8 Xn#R.B R8aX&n X#Mn MnX& XMn", +"T# aXM&n XMnj# XM&8n RTXnj# sX&Mn RXn#( X&nR+ Xn#R(B R+aX&n Xn#R(. R+8X&n .", +"BR(Xn# aXR&+n8 XMn#( XM&+n TX#Mn( +TXM&n Mn#Xj( +XM&nj XMTnj#( XM&sn+ R#Gn ", +"GnR& RGHn# RGa&n RGn#. RG8&n Gn#RH. G8nRH& G#Mn M&Gn RGTn# aMnG& RGjn# M&nG", +"8 XM#Hnj sRG&n dX#Rn dX&Rn RGHdn# gRG&n RG#dn. RG8d&n dXHnR#. RG8gn& dXMn# ", +"dXM&n dX#HMn gXM&n dM#Gnj XM&dnj dXHjMn# sX&gMn R#4X 4XR& R4X#B R4aX& R45X#", +" R48X& 4X#R5B 4aXR5& 4#XM XM4& R4TX# aXM4& R4jX# XM&48 XM#5Tn sR4X& X;#R4 X", +";&R4 R4#X;B R4aX;& R45X;# >XR4& 5#X;R4B R4a>X& XM;4# XM;4& XM#T;n XM&a;n XM", +"#;nj >XM4& X;Rj4T# sX&>Mn R#4G 4GR& R4GH# R4GH& R4G5# R4G5& R4#H5X 4G8RH& R", +"4GM# XM&4G R4GT# XM&4H R4Gj# M&nG5 XM#4Hj sR4G& R4Gd# dX&R4 dX#R4H gR4G& dn", +"#RG5 >nGR& H#5nRG; >X&gR4 dXM4# dXM4& dX#R4T g4XM& dX#R4j >MG&n dX4MH5# sX&", +"gR4 RXPn# X&PRn XPnR#B RaXP&n XPnR#. R8XP&n .BP#RXn aXR&8Pn XnS# X&Sn STXn#", +" SaX&n SXnj# S8X&n XjnST# SsX&n XPnR#( R+XP&n XPRn#B( aXR&+Pn #(P.RXn 8X+PR", +"&n XnR(.BP# anR&8X+P SXn#( S+X&n TXnS#( +TXS&n XjnS#( X&jS+n XjSnT#( S+Xsn&", +" RnY# R&Yn YRHn# YaR&n YRn#. Y8R&n RHnY#. RH8Y&n YnS# SnY& SZYn# SZ&Yn SYnj", +"# SY8&n YjnSZ# sYS&n YRdn# Y+R&n dn#YRH gYR&n dn#YR. d&nY8R dnY#RH. gR8Y&n ", +"SYdn# SY+&n YZnSd# gSY&n YjnSd# S+nY&j dnYjSZ# sY&gSn RXo# R&oX oRX#B oaRX&", +" oR5X# o8RX& R5Xo#B R5ao&X oXS# SXo& oTXS# oT&SX SpXo# Sp&oX oTXSp# osSX& o", +"RX;# o+RX& X;#oRB aX;o&R X;#oR5 o>RX& X;o#R5B oaR>X& S;Xo# S;&oX oTXS;# S+X", +"oT& opXS;# S>oX& X;S#opT S>Xos& oRY# YRo& oYRH# YaoR& Y5oR# Y5&oR oHRY5# Y5", +"RoH& S#oY Y&So oZYS# oZ&SY YpoS# Yp&So oZSYp# sYoS& YvoR# Yv&oR oHRYv# goYR", +"& ovRY5# Y>oR& YRoHv5# Y>Rgo& SvoY# Sv&oY oZYSv# goSY& YpoSv# S>Yo& SZYpov#", +" yoYS& [n [!n [Dn [an [n. [8n Dn[. D8[n [Mn Mn[! V[n [aVn [jn 8M[n [jVn [sn", +" [n( [+n Dn[( +D[n n([. +n[8 [Dn(. [+D8n Mn[( +M[n [nV( [+Vn nj[( +n[j V[nj", +"( [+sn [Gn Gn[! Jn[ [aJn Gn[. G8[n [nJ. [8Jn GM[n [!GMn JnV JaVn Gn[j [8GMn", +" VnJj Jn[s [dn +G[n [dJn g[n dn[. 8d[n Jn[d. [8gn dM[n [+GMn VdJn JngV dn[j", +" [+jGn JnVdj gn[s [4 [4! [4D [4a [45 [48 4D[5 4D[8 [4M 4M[! V[4 [aV4 [4j 48", +"[j [4V5 [s4 [4; [4+ 4D[; 4+[a 5n[; [>4 [45D; [a>n 4M[; 4+[M [4V; [4V+ 4j[; ", +"[4>M V[4;j >n[s [4G 4G[! J4[ [aJ4 4G[5 4G[8 [4J5 [4J8 4G[M [4GM! V[J4 J4V[a", +" 4G[j [48GM V5Jn J4[s [4d 4+[d [4J; g[4 4d[5 [d>n J4[5d >ng[ 4d[M [4+GM V;J", +"n V[g4 4d[j [>4GM J4[dj g4[s [Pn n![P DP[n aP[n Pn[. 8P[n [DPn. [8DPn S[n [", +"!Sn VnS[ Sn[a Sn[j Sn[8 SV[nj S[sn Pn[( +P[n [DPn( [+DPn [Pn(. [+8Pn DPn[(.", +" +DP[8n [nS( Sn[+ SV[n( SV+[n S[nj( S[+8n VnjS[( [sS+n [Yn Yn[! [YJn Yn[a [", +"nY. Yn[8 YJ[n. YJ8[n Sn[Y S[Yn! ]n ]an Yn[j S[8Yn ]jn ]sn Yn[d Yn[+ YJ[dn [", +"Ygn [Ydn. Y+[8n [YdJn. g[Y8n Sn[d S[+Yn ]dn ]gn S[dnj S[8dn dn]j gs]n o[ o[", +"! o[D o[a o[5 o[8 [5oD [5oa o[S S!o[ oV[ Sao[ [po S8o[ [poV os[ o[; o[+ [;o", +"D [+oD o5[; [>o o[5D; oD[> S;o[ S+o[ V;o[ V[o+ [;op o[S> oVp[; [>oV o[Y o![", +"Y oJ[ Yao[ Y5o[ Y8o[ J5o[ J8o[ SYo[ o[YS! ]o ]oa o[Yp [poY8 ]op ]os [vo Y+o", +"[ [voJ go[ [5ov o[Y> oJ[v5 [>go o[Sv [voS+ ]ov ]og op[v [pvo> op]v ]yo [bn ", +"[&n bn[D [cn bn[. b8[n [bDn. [8cn bM[n M&[n [bVn V[cn bn[j &n[j V[bnj sn[c ", +"bn[( b+[n [bDn( [+cn [bn(. [+b8n bnD[(. [c+8n [bMn( [+bMn V[bn( [cV+n [jbn(", +" [+jbn [jbVn( [sc+n bG[n G&[n [bJn Jn[c [bGn. [8bGn Jn[b. [cJ8n GMbn [&GMn ", +"JbVn VJcn [jbGn [&jGn JnVbj [sJcn bd[n d&[n Jn[bd gn[c [dbn. [8dbn [dbJn. g", +"[c8n [dbMn [d&Mn JnVbd gVn[c [djbn [d&nj Jnb[dj g[scn [4b [4& 4b[D [c4 4b[5", +" 4b[8 [4b5D [4c5 4b[M 4M[& Vb[4 V[c4 4b[j 4&[j V[4b5 s4[c 4b[; 4b[+ [4bD; [", +"4c; [4b5; [&>n b5n[;D >n[c [4bM; [4+bM V[4b; [c4V+ [4jb; [>4bM V4b[;j V>[c4", +" 4b[G 4G[& Jb[4 J4[c [4bG5 [48bG J4[b5 [c4J5 [4bGM [4&GM J4V[b [c4VJ [4jbG ", +"[4&Gj J4[bj [s4cJ 4b[d 4d[& J4[bd g4[c [4db5 [>4bG J4b[5d J>n[c [4dbM [4dM&", +" J;Vbn g[4Vc [4dbj >MbGn J4b[dj J>Vcn bP[n P&[n [bDPn [Pcn [bPn. [8bPn bPD[", +"n. [c8Pn [bSn Sn[& SV[bn cnS[ S[bnj S[8bn V[nSbj [scSn [bPn( [+bPn bPD[n( [", +"c+Pn bPn[(. b+P[8n bD[(Pn. [+8cPn S[bn( S[+bn V[nSb( Sc[+n [jnSb( Sbn[+j nj", +"V(S[b Sc+[sn [bYn Yn[& YJ[bn [Ycn Yb[n. Yb8[n Jn[Yb. Yc[8n SnYb S[&Yn ]bn ]", +"cn SYbnj SYb8n bn]j sc]n Yb[dn Yb+[n Jn[Ybd g[Ycn [dnYb. Ybn[8d dnJ.Yb[ Yc8", +"g[n S[dbn S[d&n bd]n gc]n Sbn[dj SbnY+j ]jnbd ]cngs o[b o[& [boD oc[ [5ob [", +"5o& o[b5D c5o[ Sbo[ S&o[ V[ob o[Sc ob[p o&[p oVp[b [poc [;ob [+ob o[bD; c;o", +"[ o[b5; ob[> [5boD; [>oc S[;ob o[+Sb oV[b; oV+[c [pob; [p&o> [pboV; oV>[c Y", +"bo[ Y&o[ [Job o[Yc Ybo[5 o[8Yb oJ[b5 oJ8[c YbSo o[&SY ]ob ]oc [poYb [p&oY o", +"p]b os]c ob[v o&[v oJ[vb ocg[ [vob5 [v&o> [vboJ5 oJ>[c [voSb [v&So ov]b go]", +"c [pvob [pvo& ]opvb yo]c qX q!X qXB qaX q1X q8X 1XqB 1aqX qXM XMq! qTX TXqa", +" lXq q8lX qTlX sqX qX( q+X X(qB +Xqa 1Xq( 1+qX q1X(B q+1aX XMq( +XqM TXq( +", +"TqX qXl( q+lX lXqT( q+sX qG qG! qGH qGa qG1 qG8 1GqH 1Gqa qGM GMq! qGT GTqa", +" lGq q8lG qGlH sqG qGd q+G HXqd gqG 1Gqd 1+qG qG1Hd qGg1 GMqd +GqM GTqd qGg", +"M qGld q+lG lGqTd lGgq q4X 4Xq! 4XqB 4aqX 7qX q87X qX7B qa7X 4XqM q!4XM 4Tq", +"X qT4aX lX7 l87X 7TlX lX7s q;X 4+qX X;qB aXq; q;7X q>X 7qX;B qa>X XMq; q+4X", +"M TXq; q+T4X 7Xl; lXq> 7qTX; >Xsq qG4 4Gq! 4GqH 4Gqa 7qG q87G qG7H qG7a 4Gq", +"M qG4M! 4GqT qGT4a 7qlG 7qGl8 7HlX 7qsG qG; 4+qG G;qH qGg4 qG7d q>G 7qGH; >", +"Xgq GMq; q+G4M GTq; gq4GT 7dlX lGq> 7qGTd lXg7 qXP XPq! XPqB aXqP 1XqP 8XqP", +" q1XPB q8aXP SqX q!SX SXqT SXqa SqlX SXq8 SlqTX SqsX XPq( +XqP qXP(B q+aXP ", +"q1XP( q+1XP 1XPq(B 1+XqaP qXS( SXq+ SqTX( Sq+TX SlqX( Sq+lX lXTSq( sqS+X Yq", +" Yq! YqH Yqa Yq1 Yq8 qHY1 qHY8 YqS S!Yq ZqY SaYq lYq S8Yq ZqlY sqY Yqd Yq+ ", +"YHqd gqY qdY1 q+Y1 Yq1Hd g1Yq SdYq S+Yq qdYZ gYZq ldYq l+Yq lYZqd gqlY oqX ", +"oXq! qXoB oXqa oq7X oXq8 7oqXB 7oaqX SXoq SqXo! oXqT SqaoX rX r8X rTX rsX o", +"Xq; oXq+ oqX;B oq+aX 7oqX; oq>X oq;7XB q>oaX SXq; Sq+oX Sq;TX SqaX; r;X r>X", +" TXr; >Xrs Yqo o!Yq oHYq oqYa 7Yq Y87q 7HYq Ya7q SoYq YqoS! oZYq YqaoZ rY r", +"Y8 rZY rsY vqY Y+vq qHYv gYvq vq7Y Y>q vq7YH Y>gq YqSv vqYS+ YZvq goqSY rYv", +" rY> YZrv yrY q9X q&X 9XqB 9aqX 9Xq1 :qX q91XB qa:X 9XqM XMq& 9TqX TXq& q9l", +"X lX:q lXq9T sX:q 9Xq( 9+qX q9X(B q+9aX q91X( q+:X 9X1q(B :q+aX q9XM( q+9XM", +" qT9X( q+T9X lXq9( :ql+X qT9lX( sq:+X qG9 qG& 9GqH 9Gqa 9Gq1 :qG qG91H qG:H", +" 9GqM GMq& 9GqT GTq& l9qG lG:q lGq9H sG:q 9Gqd 9+qG qG9Hd qGg9 qG91d q+:G 9", +"HXqd1 gX:q qG9dM q+G9M qGT9d gq9GT lGq9d :qGl+ lG9qTd glq:G 49qX 4Xq& q49XB", +" qa49X q97X 7X:q 7q9XB 7qa:X 9X4M q&4XM qT49X qT&4X l97X 7:lX 7qT9X 7sX:q 9", +"Xq; X;q& q;9XB qa;9X 7q9X; >X:q q;97XB q>:aX q;9XM q;&XM qT;9X qT;X& lX79; ", +"q>l:X 7T9lX; sq>:X 49qG 4Gq& qG49H qGa49 79qG 7G:q 7qG9H :qG7H qG49M qG&4M ", +"qGT49 qGT4& 7qGl9 :qG7l 7qG9T sqG7: 9Gq; G;q& qG;9H gq49G 7qG9d :Gq> 7G9qH;", +" q>Gg: qG;9M qG;M& qGT9; g49XM 7dXl9 q>Gl: 7G9qTd q>Gs: 9XqP X&qP q9XPB qa9", +"XP q91XP qX:P 9X1qPB :qaXP q9SX SXq& Sq9TX Sqa9X Slq9X :XSq lXqS9T sq:SX q9", +"XP( q+9XP 9XPq(B 9+XqaP 9X1qP( :q+XP 91q(XPB q+a:XP Sq9X( Sq+9X qTXS9( S9Xq", +"+T lXqS9( S:q+X l9qTSX( S:+sqX Yq9 Yq& qHY9 qHY& q9Y1 Y:q Yq91H Ya:q S9Yq S", +"&Yq Y9Zq Y&Zq lqY9 YqS: lYZq9 Y:sq qdY9 q+Y9 Yq9Hd g9Yq Yq91d Y+:q qH9Y1d Y", +":gq SqdY9 Yq+S9 ZqY9d gqZY9 lYq9d lY:q+ Zq9lYd glY:q q9oX oXq& oq9XB oqa9X ", +"7oq9X oq:X oq97XB o:qaX SXo9 Sq&oX oqT9X S9aoX r9X r:X 9TrX s:rX oq9X; oq+9", +"X q;Xo9B o9Xqa; oq97X; o:q>X 7Boq9X; q>ao:X Sq;9X Sq;X& S9XqT; S9Xo+T 9Xr; ", +">Xr: r;X9T r>Xs: oqY9 oqY& Y9oqH Yqao9 Y97q Yqo: 7Yq9H o:HYq Y9So Yq&So oZ9", +"Yq Zq&oY rY9 rY: YZr9 sYr: Y9vq Y&vq vqY9H vq&gY vq7Y9 vqY: 7Y9vqH go:Yq vq", +"YS9 vq&SY ZqvY9 vq&YZ Yvr9 Y:rv rZYv9 rYy: [q [q! [qD [qa [q1 [q8 qD[1 qD[8", +" [qM [Mq! Vq[ [aVq [lq q8[l [lVq sq[ [q( [q+ [(qD q+[a [(q1 q+[1 [q1D( [q+1", +"D [(qM [Mq+ V([q [qV+ l([q [ql+ Vql[( [+sq [qG [!qG Jq Jqa qG[1 qG[8 Jq1 Jq", +"8 [MqG [qGM! JqV qaVJ [qlG [lqG8 Jql sqJ [qd q+[d Jqd gqJ qd[1 q8[d qdJ1 g1", +"Jq [Mqd [q+GM VdJq gVJq [qld [l+qG ldJq sqg[ [q4 q![4 qD[4 qa[4 7[ 7[8 7[D ", +"7[a q4[M [q4M! [qV4 Vq[4a 7[l [87l 7V[ 7[s [q; q+[4 qD[; qa[; 7[; 7[> [;7D ", +"7D[> [Mq; [q+4M [qV; Vq+[4 l;7[ l>7[ V;7[ V>7[ qG[4 [q4G! Jq4 qaJ4 7[G [87G", +" 7Jq 7aJq [q4GM qGM[4! J4Vq JqV4a lG7[ 7[lG8 Jq7V 7Jsq qG[; [q+4G Jq; g4Jq ", +"7[d 7G[> 7dJq g7[ [qd4M [4Mq+G J;Vq Jq;gV ld7[ [>l7G l;Jq 7Vg[ [qP [Pq! [Pq", +"D [Pqa [Pq1 [Pq8 [q1DP [q8DP Sq[ S![q S[Vq [qSa Sq[l [qS8 SlV[q Sq[s qP[( [", +"Pq+ [qDP( [q+DP [q1P( [q+1P qDP[1( [1Pq+D S([q [qS+ Sq[V( Vq+S[ Sq[l( [l+Sq", +" [lSVq( sq[S+ Yq[ [!Yq JqY YaJq [qY1 [qY8 Y1Jq Y8Jq S[Yq Sq[Y! ]q ]qa [lYq ", +"Yq8[l ]lq ]qs [dYq [qY+ qdYJ gYJq Y1[qd Yq+[1 JqY1d Jq8gY [qSd Yq+S[ ]qd ]q", +"g lYq[d lY+[q ld]q gl]q o[q o![q [qoD [qoa 7[o o87[ 7Do[ 7ao[ Sqo[ Sq[o! Vq", +"o[ oVq[a r[ r[8 rV[ r[s [;oq [qo+ o[qD; o[+qD [;7o o[q> 7[oD; [>o7D [qS; o[", +"+Sq oVq[; oV+[q r[; r[> V[r; V>r[ o[Yq Yqo[! oJq oaJq 7[Y Y87[ oJ7[ Ya7[ Sq", +"[oY o[SYq! ]oq oq]a r[Y Y8r[ ]r ]rs vq[ [+vq Jqv oJgq 7[v 7[Y> vq7J 7[go Sq", +"[v vq[S+ ]qv go]q r[v Y>r[ ]rv ]yr tq[ [q& qD[t cq[ [1tq [:q tq[1D [:cq tM[", +"q [Mq& V[tq [cVq tq[l [l:q Vql[t uq[ t([q [qt+ tq[D( [+cq tq[1( [+:q [1Dtq(", +" cq[:+ tq[M( tq+[M Vq[t( cqV[+ [lqt( [:lq+ [ltVq( [qu+ tqG [&qG Jqt cqJ t1q", +"G tG:q J1tq :Jq tMqG tqGM& VqtJ cJVq tqlG [:lqG ltJq uJq [qtd q+tG tdJq cqg", +"[ tqG1d [q:d Jqt1d :Jgq tqGdM tq+GM JqVtd cqJgV [ldtq [:dlq Jqltd gquJ t4[ ", +"[&t4 tD[4 t4[c 7[t 7[: [t7D 7[c tM[4 t4[M& V[t4 cqV[4 [l7t l:7[ V[7t u7[ [q", +"t; [4t+ tq;[D [qc; t;7[ 7[t> 7[tD; [>7c tq;[M t4[+M Vq;[t cq;V[ [l;7t [>l7t", +" 7V[t; 7[u> [4tG tqG4& t4Jq c4Jq tG7[ 7G[: tJ7[ :J7[ tqG4M t4MqG& JqVt4 cqJ", +"V4 7tG[l 7[:lG Jql7t 7Juq [4td tq+4G t;Jq t4g[ td7[ tGq> Jq;7t 7[gt tqGM; t", +"4M[d& Jq;Vt cqJV; 7[dlt [:d7l Jqlt; g7u[ [qtP [Pq& tq[DP [qcP tq[1P [q:P [q", +"1tPD cq[:P tqS[ [qS& Sq[Vt Sq[c Sq[lt Sq[: VqlSt[ Squ[ tq[P( tq+[P [qDtP( c", +"q[+P [q1tP( [:q+P t1qD[P( [:+cqP Sq[t( St+[q Vq[St( Scq[+ [lqSt( S:[q+ SlVq", +"[t( uS+[q tYq Y&tq JqtY Ycq Y1tq Yq[: JqtY1 cqY: YqSt Yq&St ]qt ]qc ltYq lY", +"t:q lt]q ]uq tdYq t+Yq JqtYd tYgq tYq1d [:dYq tY1Jqd g[:Yq StdYq tY+Sq tq]d", +" gq]t lYtqd [:dSq ]lqtd ]qug ot[ [qo& [toD o[cq ot7[ o:[ ot7[D oc7[ o[St ot", +"[S& V[ot oVt[c r[t r[: V[rt ur[ t;o[ t+o[ ot[D; otc[+ ot7[; [>ot 7[Dot; cq>", +"o[ ot[S; ot+S[ oVt[; oVt[+ t;r[ t>r[ rV[t; r[u> tYo Y&ot oJt otYc tY7 7[Y: ", +"7JtY 7[Yc SotY tYoS& ]ot ot]c rtY tYr: ]rt ur] vqtY Y+ot oJtv tYgo 7[tv 7Yt", +"> oJt7v tYg7 vq[St ot+SY tv]o go]t tYrv tYr> rt]v ]yur w w! wB wa w. w8 w.B", +" w8a wK w!K wT wTa wj w8j wTj sw w* w+ w*B w+a w*. w+8 *Bw. 8*wa w*K w+K wT", +"* w+T wj* w+j T*wj sw+ wG w!G wH wHa wG. w8G wH. wH8 wGK GKw! wHT GTwa wjG ", +"G8wj wHj swG fw fw+ fwH gw fw. fw8 f.wH gw8 fwK fKw+ fwT gwT fwj w+fj wHfj ", +"gws w4 w!4 w4B wa4 w5 w58 w5B w5a w4K 4Kw! wT4 4Twa w5j 48wj w5T sw4 w= w=+", +" w=B =aw w=5 w> =Bw5 w>a w=K =Kw+ =Tw w+=T =jw w>j w5=T sw> w4G 4Gw! wH4 4G", +"wa w5G 4Gw8 wH5 4Hw8 4GwK w!4GK 4GwT wH4Ta 4Gwj w5G8j 4Hwj wHs4 fw= w+f= =H", +"w gw= fw5 w>f wHf5 gw> =Kfw fw=+K fw=T =Tgw fw=j fjw> wH=j s=gw wP w!P wPB ", +"waP wP. w8P P.wB 8Pwa wQ wQ! wQT wQa wQj wQ8 TPwj swQ wP* w+P P*wB +Pwa P*w", +". +Pw8 wP*.B w+a8P wQ* w+Q Q*wT +QwT Q*wj +Qw8 wQT*j w+sP Yw Yw! YwH Ywa Yw", +". Yw8 Y.wH wHY8 YwQ Y!wQ Zw Zwa Ywj wQY8 Zwj sYw Yfw Yw+ wHYf gwY Y.fw fwY8", +" YfwH. Y8gw fwQ w+fQ Zwf gwZ fwYj w+Yj fjZw sYgw ow ow! owB owa ow5 ow8 oBw", +"5 w5oa owQ o!wQ owT wQoa pw pw8 pwT swo ow= ow+ =Bow ow=a w5o= w>o ow=5B oa", +"w> =Qw w+=Q ow=T w+oT pw= pw> =Tpw pws= Ywo o!Yw owH owYa Yw5 owY8 wHY5 wHo", +"8 wQoY YwoQ! Zwo oaZw pwY Y8pw Zwp osZw x x+ xH xg x5 x> xH5 xg> xQ x+Q xZ ", +"xZg xp xp> xZp yx w, w& w,B wa& w,. w8& ,.wB ,8wa w,K w&K wT, wT& wj, w&j ,", +"Twj sw& w*, -w *Bw, -wa ,*w. -w8 w*,.B -8wa ,*wK -wK ,Tw* -wT ,jw* -wj wT*,", +"j sw- wG, w&G wH, wH& ,Gw. ,Gw8 ,Hw. ,Hw8 ,GwK G&wK ,GwT GTw& ,Gwj G&wj ,Hw", +"j wHs, fw, -wf f,wH gw- w,f. f8-w fwH,. w8g- w,fK fK-w f,wT fT-w f,wj fj-w ", +"fwT,j s-gw w4, w&4 ,4wB ,4wa w5, w5& ,5wB ,5wa ,4wK 4&wK ,4wT 4Tw& ,4wj 4&w", +"j ,5wT w5s, w=, -w= w,=B =a-w =,w5 w>- w=5,B wa-> w,=K =K-w =,wT =T-w =,wj ", +"=j-w =Tw,5 s-w> ,4wG 4Gw& ,4wH 4Hw& ,Gw5 G5w& ,Hw5 H5w& w4G,K w&4GK wH4,T w", +"H&4T w5G,j w5&Gj wH5,T sw4,G =,fw f=-w =,wH -wg= f,w5 -wf> =Hw,5 g-w> fw=,K", +" -wf=K =Hw,T -wTg= fw5,j w>f-j =Hw,j gws-> wP, w&P ,PwB ,awP ,Pw. ,8wP wP,.", +"B w8a,P wQ, wQ& ,QwT ,Qwa ,Qwj ,Qw8 wQT,j wQs, ,Pw* -wP wP*,B wa-P wP*,. w8", +"-P P*.w,B -w8aP ,Qw* -wQ wQT,* wQ-T wQ*,j wQ-j P*jwT, sP-w Yw, Yw& wHY, wHY", +"& w,Y. w8Y& YwH,. Yw8,H wQY, wQY& Zw, Zw& wjY, w&Yj wjZ, s,Zw fwY, Y-w Yfw,", +"H Y-gw Yfw,. Y8-w fwHY,. gwY-8 f,wQ fQ-w fwZ, Z-w Yfjw, Yj-w Zwf,j Y-sw ow,", +" ow& w,oB wao& w5o, w5o& ow5,B ow8,a wQo, wQo& wTo, wTo& pw, pw& wTp, s,pw ", +"w=o, o-w ow=,B oa-w ow=,5 w>o- w=5o,B o-w>a =,wQ =Q-w owT=, oT-w w=p, -pw p", +"w=,T o-sw Y,o owY& oHY, oaY, o,Y5 o8Y, Yw5,H Yw5,a YQo, Yw&oQ Y,oZ owZ& Y,p", +"w Y&pw Z,pw Y,os x, x- x,H xg- x,5 x-> ,Hx5 g-x> x,Q x-Q xZ, xZ- xp, xp- Zp", +"x, yx- wI w!I wD wDa wI. w8I wD. wD8 wIK IKw! wDT TIwa wjI 8Iwj wDj swD wI*", +" w+I wD* w+D I*w. +Iw8 D*w. +Dw8 I*wK +IwK D*wT +DwT I*wj +Iwj D*wj w+sI wG", +"I GIw! Jw Jwa GIw. G8wI Jw. Jw8 GIwK w!GIK JwT JTwa GjwI w8GIj Jwj swJ fwI ", +"fIw+ Jwf gwJ wIf. fIw8 J.fw J8gw wIfK fw+IK fTJw wTgJ fIwj fw8Ij fwJj sJgw ", +"w4I 4Iw! wD4 4Dwa w5I 48wI w5D 4Dw8 4IwK w!4IK 4DwT wD4Ta 4Iwj w58Ij 4Dwj w", +"5sI =Iw w+=I =Dw w+=D w5=I w>I w5=D w>D wI=K =Iw+K wD=T =Dw+T wj=I >Iwj wD=", +"j =Dsw 4GwI w!4GI Jw4 waJ4 G5wI w5G8I Jw5 w5J8 w4GIK 4GIw!K wTJ4 Jw4Ta w5GI", +"j 4G8wjI w5Jj s4Jw fw=I =Ifw+ J=w J=gw fIw5 >Ifw fwJ5 J>w =IfwK fw+=IK =TJw", +" J=gwT =Ijfw w>fIj =jJw J>sw wIP IPw! wDP DPwa IPw. 8IwP DPw. D8wP wQI QIw!", +" wQD QDwa QIwj Q8wI QDwj wQsI IPw* +IwP DPw* +DwP IP*w. w+8IP wDP*. w+D8P Q", +"Iw* +QwI QDw* +QwD wQI*j w+Q8I wQD*j sw+QD YwI w!YI JwY YaJw wIY. YIw8 Y.Jw", +" Y8Jw YIwQ YwQI! ZwJ waZJ YIwj Yw8QI YjJw sJZw YIfw YIw+ YfJw JwgY YfwI. Yf", +"8wI YJfw. Jw8gY fIwQ Yw+QI JwZf gZJw YfjwI Yw+Ij JwjZf gwZsJ owI w!oI owD w", +"Doa w5oI w8oI w5oD wDo8 wQoI owQI! wQoD owDQa pwI w8pI pwD sIpw =Io o+=I ow", +"=D oa=I =5oI =Io> owD=5 oDw> oI=Q ow+QI oT=I ow+QD =Ipw pIw> =Dpw =Ios oIYw", +" YwoI! oJw oaJw YIw5 Yw58I Y5Jw o8Jw YwoQI oIQYw! oJZw oJZwa pIYw pwY8I Jpw", +" oJsw xI x+I xJ xJg x5I x>I xJ5 xJ> xQI +QxI xZJ gZxJ xpI p>xI xJp yxJ hw h", +"w& hwD cw hw. hw8 h.wD cw8 hwK hKw& hwT cwT hwj w8hj wDhj hsw hw* -wh h*wD ", +"cw- w*h. h8-w hwD*. w8c- w*hK hK-w h*wT hT-w h*wj hj-w hwT*j s-cw hwG hGw& ", +"Jwh cwJ wGh. hGw8 h.Jw h8Jw wGhK hwG&K hTJw wTcJ hGwj hw8Gj hjJw sJcw hfw h", +"f-w hfJw iw h.fw fwh8 Jwhf. iw8 hKfw -whfK fwhT iwT fwhj -wjhf Jwjhf isw hw", +"4 w&h4 wDh4 cw4 hw5 w5h8 wDh5 cw5 w4hK hw4&K wTh4 wTc4 w5hj hw5&j w5hT h4sw", +" h=w -wh= hw=D cw= w=h5 h>w h=w5D cw> =Khw h=-wK hw=T =Tcw hw=j hjw> h=Tw5 ", +"swh> w4hG hw4G& h4Jw c4Jw hGw5 hw5G8 h5Jw c5Jw hw4GK w&Gh4K Jwh4T cwJ4T hw5", +"Gj h4Gw&j Jw5hT cw5sJ fwh= h=f-w Jwh= iw= fwh5 hfw> J=hw5 iw> h=fwK -wfh=K ", +"J=hwT =Tiw h=jfw h>wfj J=jhw swi> hwP w&hP wDhP cwP wPh. w8hP hwDP. w8cP hw", +"Q w&hQ wQhT cwQ wQhj wQh8 hwQDj hQsw wPh* hP-w hwDP* cP-w hwP*. -wh8P wD*hP", +". cw-8P h*wQ hQ-w hwQD* cQ-w hwQ*j -wQh8 hQ*wDj cwQs- hYw Y&hw JwhY Ycw h.Y", +"w Ywh8 hYJw. Y8cw YwhQ hYwQ& hZw Zwc Ywhj hY8wQ hjZw swhZ Yfhw -whY hYJfw i", +"Yw hYfw. hY8-w JwfhY. Ywi8 fwhQ -wQhY hfZw iZw hYjfw Y-jhw hZwfj sYiw oh oh", +"& ohD ohc oh5 oh8 oDh5 h5oc ohQ o&hQ ohT hQoc hpo h8pw hTpw hso oh= oh- =Do", +"h c=oh o=h5 h>o oh=5D och> =Qoh hQo- =Toh =Qcw h=pw o-hp ohTp= ohs= ohY Y&o", +"h oJh ohYc Ywh5 Y8oh h5oJ h8oJ oYhQ ohYQ& hZo ochZ hYpw oh8Yp Zwhp oJhs xh ", +"xh- xJh ix xh5 xh> hJx5 ix> xhQ h-xQ xZh ixZ xph hpx- hZxp ixy w6 w!6 w6B w", +"a6 w1 w18 w1B w1a w6K 6!wK wT6 6Twa w1j 68wj w1T sw6 w6* w+6 6*wB 6+wa w1* ", +"w1+ 1*wB 1+wa 6*wK 6+wK 6Tw* 6+wT 6*wj 6+wj 1Tw* w1s* w6G 6Gw! wH6 6Gwa w1G", +" 6Gw8 w1H 6Hw8 6GwK w!6GK 6GwT wH6Ta 6Gwj w1G8j 6Hwj w1sG fw6 w+f6 wHf6 gw6", +" fw1 w1f8 wHf1 gw1 w6fK fw6+K wTf6 wTg6 w1fj fw1+j w1fT g6sw w46 6!w4 46wB ", +"4aw6 7w 7w8 7wB 7wa 46wK w!46K 4Tw6 wT46a 7wj 78wj 7wT sw7 w=6 =6w+ w6=B =6", +"wa 7w= w>7 =B7w =a7w w6=K w=6+K =6wT =Tw6+ =j7w wj7> =T7w 7sw> 4Gw6 w!46G 4", +"Hw6 wH46a 7wG w87G 7wH wH7a w46GK 4G6w!K wH46T 4GTwa6 wj7G 7wG8j wH7T sG7w ", +"w=f6 fw=6+ =6wH w=g6 7fw w>7f =H7w g7w fw=6K w=+f6K =Hw6T gw=6T fj7w w>7fj ", +"fw7T swg7 w6P 6Pw! 6PwB 6awP w1P 68wP 1PwB 1awP wQ6 6Qw! 6QwT 6Qwa w1Q 6Qw8", +" 1QwT w1sP 6Pw* 6+wP w6P*B w+6aP 1Pw* 1+wP w1P*B w1+aP 6Qw* 6+wQ wQ6T* w+Q6", +"T 1Qw* 1+wQ w1QT* sw6+Q Yw6 w!Y6 wHY6 waY6 Yw1 w1Y8 wHY1 w1Ya wQY6 Yw6Q! Zw", +"6 waZ6 w1Yj Yw1Q8 Zw1 s6Zw Yf6 f6Y+ YHf6 Yfg6 fwY1 f6Y8 Yf61H Ywg1 fQY6 Yf6", +"+Q Y6Zf g6Zw f6Yj Yf6+j fwZ1 g1Zw ow6 w!o6 w6oB o6wa 7wo o87w 7Bow ow7a o6w", +"Q ow6Q! o6wT owT6a pw7 w87p 7Tpw 7spw =6ow o6w+ ow=6B ow+6a ow7= o>7w 7o=wB", +" w>o7a =6wQ ow+6Q owT=6 ow+6T p=7w 7pw> pw7=T pw>7s owY6 Ywo6! o6wH Ywao6 7", +"Yw Y87w 7HYw Ya7w Ywo6Q owQY6! owZ6 Zwo6a pw7Y pw7Y8 7Zw 7Zsw x6 x6+ x6H xg", +"6 x7 x7> x7H xg7 x6Q 6+xQ xZ6 gZx6 xp7 7px> xZ7 yx7 ?w ?w& ?wB ?wa ?w1 :w ?", +"Bw1 :wa ?wK ?Kw& ?wT wT?a ?wj :wj w1?T s?w ?w* -w? w*?B ?a-w ?*w1 :w- ?w1*B", +" wa:- w*?K ?K-w ?*wT ?T-w ?*wj ?j-w ?wT1* s-:w ?wG w&?G ?wH wH?a w1?G :wG w", +"1?H :wH wG?K ?wG&K wH?T ?wHT& wj?G wj:G wH?j sG:w ?fw -w?f fw?H g?w f1?w :f", +"w ?wHf1 gw: ?Kfw ?f-wK fw?T ?Tgw fw?j fj:w ?fTw1 s?gw ?w4 ?4w& w4?B ?4wa 7w", +"? :w7 7B?w ?a7w w4?K ?w4&K ?4wT ?wT4a ?j7w wj7: ?T7w 7s:w ?w= ?=-w =B?w ?w=", +"a ?=7w Aw ?w=7B Awa =K?w ?w=-K ?w=T -wT?= ?w=j Awj 7wT?= Asw w4?G ?w4G& ?4w", +"H ?wH4a ?G7w 7G:w ?H7w 7H:w ?w4GK w&4?GK ?wH4T ?G4wT& ?wj7G :w7Gj 7wH?T :wH", +"7s fw?= ?w=f- ?w=H ?wg= 7w?f Afw 7wH?f Agw ?w=fK -w=?fK ?fTw= g?w=T ?fj7w f", +"wAj 7fT?w gwAs ?wP w&?P wP?B wa?P w1?P :wP ?w1PB wa:P ?wQ w&?Q wQ?T wQ?a w1", +"?Q :wQ ?wQ1T sP:w wP?* ?P-w ?wP*B ?-Pwa ?w1P* :P-w w1*?PB :w-aP ?*wQ ?Q-w ?", +"wQT* -wQ?T ?wQ1* :Q-w ?Q*w1T :wQs- ?Y ?Y& ?YH ?Ya ?Y1 ?Y: Y1?H ?HY: ?YQ Y&?", +"Q ?ZY ?aZw ?Yj ?QY: ?jZw s?Y ?Yf ?Y- Yf?H g?Y Y1?f :f?Y ?Yf1H Y:g? Yf?Q ?QY", +"- ?fZw ?Zgw Yf?j ?jY- ?ZYf1 sYg? o?w o&?w ?Bow ow?a o?7w :wo 7wo?B oa:w ow?", +"Q ?wQo& ow?T o?Twa ?pw :wp ?Tpw ?psw ow?= -wo? ?w=oB o-?wa ?w=7o Aow o?=7wB", +" owAa ?w=Q o-?wQ o?Tw= o-T?w ?wp= Apw ?pw=T swAo ?Yo Y&o? oY?H Yao? ?Y7 :w7", +"Y ?H7Y ?a7Y oY?Q ?YoQ& o?Zw ?ZoYa ?pY Y:?p 7Z?Y ?psY x? x?- x?H x?g x?7 Ax ", +"?Hx7 Axg x?Q ?-xQ x?Z g?xZ x?p Axp ?Zxp Axy w6I 6Iw! wD6 6Dwa w1I 68wI w1D ", +"6Dw8 6IwK w!6IK 6DwT wD6Ta 6Iwj w18Ij 6Dwj w1sI 6Iw* 6+wI 6Dw* 6+wD 1Iw* 1+", +"wI 1Dw* 1+wD w6I*K w+6IK wD6T* w+D6T w1I*j w1+Ij w1DT* sw6+D 6GwI w!6GI Jw6", +" waJ6 1GwI w1G8I Jw1 w1J8 w6GIK 6GIw!K wTJ6 Jw6Ta w1GIj 6G8wjI w1Jj s6Jw w6", +"fI fw6+I fwJ6 g6Jw fIw1 fw1+I fwJ1 g1Jw fw6IK w+If6K Jwf6T gwJ6T fw1Ij f6Iw", +"+j Jw1fT gwsJ6 4Iw6 w!46I 4Dw6 wD46a 7wI w87I 7wD wD7a w46IK 4I6w!K wD46T 4", +"TIwa6 wj7I 7w8Ij wD7T sI7w w6=I =Iw6+ =6wD =Dw6+ =I7w 7Iw> =D7w 7Dw> =Iw6K ", +"w+6=IK =Dw6T =D6w+T 7w=Ij w>7Ij 7wD=T w>D7s w46GI 4G6w!I w4J6 Jw64a wG7I 7w", +"G8I 7Jw 7aJw 4G6wIK 6!w4GIK Jw64T wT4J6a 7wGIj w8G7Ij 7TJw 7Jsw =Ifw6 fw6=I", +"+ w=J6 J=gw6 fw7I w>7fI 7wJ= 7Jgw fw6=IK =6w+fIK J=w6T gw6J=T 7fwIj 7fIw>j ", +"J=j7w J>w7s 6IwP w!6IP 6DwP wD6aP 1IwP w18IP 1DwP w1D8P 6QwI wQ6I! 6QwD wQD", +"6a 1QwI w1Q8I 1QwD sw6QD IP6* w+6IP wD6P* w+D6P w1IP* w1+IP w1DP* w1+DP wQ6", +"I* w+Q6I wQD6* w+Q6D w1QI* w1+QI w1QD* sIP6* w6YI Yw6I! Y6Jw YJ6wa YIw1 Yw1", +"8I Y1Jw Jw1Y8 Yw6QI wQIY6! Z6Jw ZwJ6a Yw1QI Y6IwQ8 Z1Jw sYwJ6 YIf6 Yf6+I Jf", +"Y6 gY6Jw Yf61I Yf68I Jw1Yf gw1YJ Yf6QI Y6Iw+Q Zf6Jw gwZJ6 Yf6Ij Y6IfQ8 Zw1J", +"f gwZJ1 w6oI ow6I! o6wD owD6a ow7I 7oIw8 ow7D 7wDo8 ow6QI wQ6oI! owD6Q oD6w", +"Qa 7Ipw pw78I 7Dpw osI7w =6oI ow+6I owD=6 ow+6D 7o=I w>o7I 7wDo= w>D7o =Qw6", +"I o+6=QI oTI=6 o+6=TI pw7=I pw>7I pwD7= osI7= Ywo6I owIY6! J6ow oJw6a 7IYw ", +"7Yw8I 7woJ oJ87w owQY6I o!Yw6QI oJZw6 Zw6oJa pw7YI 7Y8pwI Zw7J oJs7w x6I 6+", +"xI xJ6 gJx6 x7I 7>xI xJ7 g7xJ 6QxI x6+QI ZJx6 xZJg6 7pxI xp7>I 7ZxJ x7yJ h?", +"w w&h? ?wD cw? hw1 :wh w1?D :wc ?Khw ?w&hK ?whT ?Tcw ?whj hj:w w1hT :whs h*", +"?w h?-w ?*wD -w?c h*w1 -wh: ?wD1* :c-w ?w*hK -w?hK ?wDT* cw?-T ?wjh* :wh-j ", +"?wD*j :wcs- ?Ghw ?wGh& ?Jw cw?J hGw1 :Ghw h1Jw :Jw ?wGhK hw&?GK ?TJw cw?JT ", +"?wjhG :whGj ?jJw ?Jsw hw?f ?fh-w Jw?f i?w fwh1 hf:w Jw1?f i:w ?fhwK -wh?fK ", +"?fTJw ?wiT ?fjhw :fwhj ?Jjfw s?iw ?wh4 ?w4h& ?4wD c4?w 7hw :w7h ?D7w 7cw ?w", +"4hK h4&?wK ?wD4T cw?4T hj7w :w7hj hT7w 7hsw ?wh= ?w=h- ?w=D ?wc= 7wh= Ahw 7", +"wDh= Acw ?w=hK -w?h=K h=T?w cw=?T h=j7w hwAj 7hTw= hsAw ?w4hG hw4?G& J4?w c", +"w?J4 7Ghw :w7hG 7w?J :w7J hw4?GK hGw&?4K ?Jw4T ?J4cwT 7hwGj 7hG:wj ?J7wT hs", +"7Jw ?w=hf ?f-h=w ?wJ= ?wi= hf7w hfAw ?J7fw Aiw ?fwh=K =K?f-wh ?J=wT i?w=T 7", +"hfwj Ahjfw J=j?w isAw h?P h&?P ?DhP hP?c ?Ph1 hP:w ?wD1P :Pcw ?whQ ?wQh& ?T", +"hP ?Qcw ?Phj hQ:w ?wQ1D hPs? h*?P ?-hP ?wDP* cw?-P h?P1* :wh-P ?D*h1P :wc-P", +" ?wQh* -wQh? ?wQD* cwQ?- ?Pjh* :wQh- ?Q*w1D :wc-Q ?Yh Y&h? ?JY ?Yc h1?Y hY:", +"w Y1?J Y:?J hQ?Y ?YhQ& ?YhZ Yc?Z hj?Y :wQhY h1Zw ?JsY ?fhY h?Y- YJ?f i?Y hY", +"1?f ?Y:hf ?JYf1 ?Yi: ?fQhY ?Y-hQ hZ?Yf ?ZiY ?Yjhf :wQhf hZwf1 s?iY oh? o&h?", +" ?Doh ?coh 7ho oh: 7Doh oh7c hQo? oh?Q& hTo? ohc?Q oh?p :whp ?Dpw ohs? o?h=", +" h?o- oh?=D ohc?- 7oh= Aoh 7ho=D ohAc oh?=Q oh-?Q ohT?= oh-?T hpo?= hpAo oh", +"T7= hsAo oh?Y oh?Y& ?Jo oc?J 7hY 7hY: 7J?Y 7hYc oh?YQ ?YQoh& oJ?Z hZo?c ?Yh", +"p :wphY 7YhZ Yc?p x?h h?x- x?J ix? x7h Axh ?Jx7 Aix h?xQ x?h-Q hZx? x?iZ hp", +"x? xpAh hZx7 yAix wR w!R wRB waR wR. w8R R.wB R8wa wM wM! wTR waM wMj w8M R", +"Twj swR wR* w+R R*wB R+wa R*w. R+w8 wR*.B w+R8a wM* w+M RTw* R+wT R*wj R+wj", +" wTR*j w+sR wRG RGw! wHR RGwa RGw. RGw8 RHw. RHw8 wMG GMw! wHM GawM RGwj G8", +"wM RHwj wHsR fwR w+fR wHfR gwR wRf. w8fR fwRH. w8gR fwM w+fM wHfM gwM wMfj ", +"w8fM fwTRj gRsw wR4 R4w! R4wB R4wa w5R R4w8 R5wB R5wa wM4 4Mw! R4wT 4awM w5", +"M 48wM R5wT w5sR =Rw w+=R wR=B wa=R w5=R w>R =Rw5B >Rwa =Mw w+=M wT=R wa=M ", +"w5=M w>M =RTw5 >Msw R4wG w!R4G R4wH wHR4a RGw5 w5RG8 RHw5 wH5R8 4GwM wM4G! ", +"4HwM wHM4a G5wM w5MG8 H5wM swR4G =Rf =+fR fR=H =Rgw f5=R =Rf> =RfH5 gRw> fw", +"=M =Rf+M fR=T =Mgw fR=j fw>M =RfHj >Mgw wRP RPw! RPwB RawP RPw. R8wP wRP.B ", +"w8RaP Sw Sw! SwT Swa Swj Sw8 STwj swS R*wP R+wP wRP*B w+RaP wRP*. w+R8P P*.", +"wRB aP*w8R Sw* Sw+ wTS* w+Sa wjS* w+S8 SwT*j s*Sw YwR w!YR YRwH YRwa wRY. Y", +"Rw8 YwRH. Yw8RH SwY S!Yw ZwS SaZw YjSw YwS8 wjSZ SsZw fRYw YRw+ YfwRH YwgR ", +"YfwR. Yf8wR fRHYw. gwYR8 Sfw YwS+ ZwSf gwS fjSw fwS8 SfZwj swgS owR w!oR wR", +"oB oRwa oRw5 oRw8 owR5B ow8Ra Swo S!ow oTSw owSa pwS S8pw wTSp Sspw ow=R oR", +"w+ ow=RB ow+Ra ow=R5 >Row =R5owB w>oRa S=w owS+ =TSw =aSw pwS= S>w pw=ST S>", +"sw YRow YwoR! oRwH YwaoR YRw5 Yw5R8 Yw5RH Yw5Ra YwSo SwoY! oZSw SwaoZ YpSw ", +"pwYS8 SZpw sYoSw xR xR+ xRH xgR xR5 x>R RHx5 g>xR xS xS+ xZS xgS xpS x>S SZ", +"xp yxS wR, w&R ,RwB ,Rwa ,Rw. ,Rw8 wR,.B w8R,a wM, wM& ,RwT ,awM ,Rwj ,8wM ", +"wTR,j wMs, ,Rw* -wR wR*,B wa-R wR*,. w8-R ,R*w.B -wR8a ,Mw* -wM wTR,* wT-R ", +"wM*,j w8-M ,RTwj* sR-w ,RwG RGw& ,RwH RHw& wRG,. w8R,G wHR,. wH8,R ,GwM GMw", +"& ,HwM HMw& wMG,j w8M,G wHM,j swR,G wRf, fR-w fwR,H gR-w fwR,. -wfR8 wH,fR.", +" gw-R8 f,wM fM-w fwT,R gM-w fwM,j -wMf8 fR,wHj gws-R ,Rw4 R4w& wR4,B waR,4 ", +",Rw5 R5w& w5R,B w5a,R ,4wM 4Mw& wTR,4 wT&R4 ,5wM 5Mw& w5T,R swR,4 wR=, =R-w", +" =Rw,B -w=Ra =Rw,5 -Rw> w5,=RB w>-Ra =,wM =M-w =RTw, -wT=R =Rjw, >M-w =R,w5", +"T w>Ms- R4,G w&R4G wHR,4 wH&R4 w5R,G w5&RG wH5,R wH5R& wM4,G wM&4G wHM,4 wH", +"M4& w5M,G w5MG& wH5,M wH5M& =,fR f-=R =Rf,H g=R-w =Rf,5 w>f-R =R,wH5 gw>-R ", +"=Rf,M -wMf= =Rf,T gwM-= =Rf,j w>Mf- =R,f5T w>Mg- ,RwP R&wP wRP,B waR,P wRP,", +". w8R,P ,RPw.B ,R8waP Sw, Sw& wTS, wTS& wjS, w8S& SwT,j s,Sw wRP,* wR-P P*B", +"wR, -wRaP P*.wR, -wR8P ,RwBP*. w8R-Pa w*S, S-w SwT,* Sa-w Sw*,j S8-w wT*S,j", +" S-sw wRY, YRw& YwR,H Ywa,R YwR,. Yw8,R wHRY,. Y8RwH& YwS, YwS& S,Zw S&Zw S", +"Y,wj Sw8Y& ZwS,j sYwS& Yfw,R -RYw fwRY,H gwY-R fwRY,. Y-wR8 ,Hw.YfR Y-Rgw8 ", +"fwS, SwY- SfZw, S-gw Sfw,j Sf-w8 ZwjSf, gwSs- wRo, oRw& owR,B owa,R owR,5 o", +"w8,R w5Ro,B oaRw5& owS, owS& Swo,T Swao& S,pw S&pw pwS,T os,Sw ow=,R -Row =", +"R,owB o-wRa =R5ow, o-w>R =Bow,R5 w>Ro-a w=S, Swo- S=w,T o-TSw pw=S, pwS- S=", +"Tpw, os-Sw YRo, Yw&oR Y,oRH Yao,R Yw5,R Yw5R& Y5RoH, Y5Roa, Y,So Sw&oY oZ,S", +"w Zw&So pwYS, pw&SY ZwpS, os,SY x,R x-R ,RxH g-xR ,Rx5 ->xR x,RH5 xg->R xS,", +" x-S SZx, gSx- Spx, S-xp xZpS, y-xS [w [w! [wD [wa [w. [w8 w.[D [8wD [wM [!", +"wM Vw Vwa [wj [8wM Vwj swV [w* [w+ [*wD wD[+ w.[* w8[+ [wD*. [w+D8 [*wM wM[", +"+ Vw* Vw+ [*wj wj[+ wjV* s*Vw [wG wG[! Jw[ wa[J w.[G wG[8 J.[w [wJ8 [GwM [w", +"GM! VwJ waVJ wG[j [w8GM JjVw sJVw [fw w+[f [fJw g[w f.[w [wf8 Jw[f. w8g[ [w", +"fM [fw+M Vfw gwV [wfj [f8wM fjVw swg[ [w4 w![4 wD[4 wa[4 [w5 w8[4 [5wD wa[5", +" wM[4 [w4M! Vw4 waV4 wM[5 [w58M Vw5 s4Vw [= [=+ [=D [=a [=5 [>w [5=D =D[> [", +"=M [+=M Vw= =aVw [=j >M[= =jVw s=[ wG[4 [w4G! [wJ4 Jw[4a wG[5 [w5G8 [wJ5 Jw", +"5[8 [w4GM wMG[4! J4Vw VwJ4a [w5GM [4Gw8M J5Vw Vw5sJ [=f [+f= J=[ g[= f5[= f", +">[= J5[= [>gw =M[f [=f+M VwJ= V=g[ =j[f [>f=M Jj[= s=g[ [wP wP[! wP[D wP[a ", +"[Pw. wP[8 [wDP. [w8DP Sw[ S![w VwS SaVw wjS[ [wS8 wjSV SsVw wP[* wP[+ [wDP*", +" [w+DP [wP*. [w+8P [*PwD. [+PwD8 [wS* [wS+ S*Vw S+Vw S[*wj Sw+[8 VwS*j Vw+S", +"s Yw[ [!Yw [JYw [wYa Y.[w [wY8 Yw[J. Jw8[Y YwS[ Yw[S! ]w ]wa [wYj Sw8[Y ]wj", +" ]sw Yw[f [wY+ YJf[w Ywg[ Yw[f. [f8Yw [fYJw. g[wY8 [fSw Sw+[f ]fw ]gw [fjSw", +" Sf8[w fw]j gw]s o[w o![w [woD [woa w5o[ [wo8 o[w5D o[8wD o[Sw Swo[! oVw oa", +"Vw pw[ w8[p Vwp oVsw [=o o+[= =Do[ =ao[ [5o= o[w> [=o5D [>o=D S=[ S+[= VwS=", +" S[=a [p= [>S= pwV= VwS> Ywo[ Yw[o! Jwo[ oJ[wa [wY5 o[8Yw oJ[w5 oJ8[w Yw[So", +" o[YSw! ]ow ow]a Yw[p pw[Y8 ]pw sw]o x[ x[+ xJ[ xg[ x[5 x[> J5x[ g[x> x[S S", +"[x+ ]x ]xg xp[ S>x[ ]xp ]yx hw[ [w& wD[h cw[ h.[w [wh8 hw[D. w8[c hwM w&hM ", +"Vwh cwV [whj w8hM hjVw Vwhs [*hw [-w hw[D* [-cw hw[*. w8[- wD*[h. cw[-8 h*w", +"M hM-w V*hw V-w hwM*j [w-j Vwh*j V-sw hG[w wG[& [Jhw [cJw hw[G. hw8[G Jw[h.", +" cwJ[8 hGwM hwMG& VhJw cJVw hwMGj hw8GM VwJhj cwVsJ hw[f [f-w Jw[hf i[w [fh", +"w. [-fw8 [fhJw. [wi8 fwhM [-fwM hfVw iVw [fjhw [-jfw Vfwhj swiV h4[ w&[4 hD", +"[4 h4[c [wh5 [4h8 hw5[D [wc5 [4hM hwM4& h4Vw c4Vw [4hj hw58M h5Vw h4[s [=h ", +"[-= [h=D c=[ h5[= w>[- [=h5D [>cw hw=M =M[- h=Vw Vwc= hj[= =j[- Vw=h5 Vwh> ", +"hG[4 h4[G& [Jh4 cwJ[4 hw5[G h4[G8 Jw5[h cw5[J hwM4G h4GwM& VwJh4 cwVJ4 hw5G", +"M h4Gw8M Vw5hJ cwVJ5 [fh= f-[= hJ[= i[= [=hf5 [-=f> J=[h5 [>iw [=hfM [-=fM ", +"J=Vhw Vwi= [=jhf [-=fj J=[hj s=i[ [whP wP[& hw[DP [wcP hw[P. hw8[P hPD[w. c", +"w[8P Shw S&hw VwSh Scw hjSw h8Sw VwhSj Shsw hw[P* [w-P hPD[w* cw[-P hP*[w. ", +"[-w8P h*wD[P. [-8cwP S*hw Sw[- VwhS* cwS- Shw*j [-jSw Sh*Vwj V-wSs [hYw [wY", +"& hYJ[w Yw[c hY[w. hY8[w Jw[hY. Ycw[8 SwhY Sw&hY ]hw ]cw hYjSw Sh8Yw hw]j h", +"s]w hY[fw Yw[- Jw[hYf Ywi[ [fwhY. Y-[w8 h.Jw[fY i[Yw8 hfSw Shf-w hf]w ]iw S", +"hfwj [-jYw ]hfwj iw]s oh[ [ho& [hoD o[cw h5o[ h8o[ oh[5D ohc[5 Sho S&oh oVh", +" ohSc pwSh Soh8 oVhp oVhs [=oh o-[ oh[=D [-oc oh[=5 [>oh [=5ohD cw>o[ Sh= o", +"hS- V=Sh cwS= S=hp S=h> oVhp= Shs= o[hY oh[Y& hJo[ oJh[c oh[Y5 oh8[Y oJh[5 ", +"oJh[8 SohY ShoY& ]oh oh]c pw[hY oh8SY hp]o hs]o x[h x[- hJx[ ix[ h5x[ h>x[ ", +"xJ[h5 x[i> xhS Shx- ]xh ]ix hpx[ h>xS xp]h ix]y wq wq! wqB wqa wq1 wq8 q1wB", +" q8wa wqM q!wM wqT qTwa lw lw8 lwT lws wq* wq+ wBq* q+wa q*w1 q+w1 wq1*B wq", +"+1a q*wM q+wM q*wT q+wT lw* lw+ wTl* l+sw wqG w!qG wqH qGwa qGw1 qGw8 qHw1 ", +"qHw8 qGwM wqGM! qGwT wqHaM lwG w8lG lwH lGsw fq fq+ fqH gqf fq1 fq8 qHf1 g1", +"fq fqM q+fM fqT gMfq lfq l+fq lHfq glw wq4 w4q! q4wB w4qa 7wq w87q 7Bwq wq7", +"a q4wM wq4M! w4qT wqT4a lw7 w87l 7Tlw 7slw q=w w+q= =Bwq wq=a q=7w w>q 7wq=", +"B waq> wq=M q=w+M wq=T q=Tw+ lw= lw> =Tlw swl= w4qG wq4G! w4qH wqH4a wq7G 7", +"qGw8 wq7H 7wHq8 wq4GM qG4wM! wqH4T wT4qGa lG7w lw7G8 lH7w lws7G fq= q+f= =H", +"fq g=fq 7fq fq> 7Hfq 7fgq =Mfq fq=+M =Tfq fqTg= 7flw w>lf =Hlw g7lw wqP wPq", +"! qPwB wPqa q1wP wPq8 wq1PB wq8aP Swq S!wq wTSq wqSa lwS S8lw wTSl Sslw wPq", +"* wPq+ wqP*B wq+aP wq1P* wq+1P q*Pw1B w1Pqa* wqS* wqS+ Sq*wT Sw+qT l*Sw l+S", +"w lwST* lwsS+ Yqw q!Yw wHYq wqYa wqY1 wqY8 Yw1qH Yq8wH YqSw SwqY! Zqw waZq ", +"lYw Y8lw lwZ sYlw fqY Y+fq qHYf gYfq Y1fq Y8fq fqY1H fq8gY Sfq S+fq Zqf Sfg", +"q Sflw S8fq Zqlf gwlY oqw o!wq oBwq wqoa oq7w wqo8 7woqB 7waoq oqSw Swoq! w", +"qoT Swaoq rw rw8 rwT rsw owq= wqo+ q=owB q=aow 7o=wq oqw> q=o7wB w>qoa q=Sw", +" Sw+q= q=TSw S=awq rw= rw> =Trw swr> oqYw Yqow! wqoH Yqaow 7wYq Yq87w 7wHYq", +" 7Yawq SwoYq YqoSw! oqZw Zqwoa rYw Ywr8 rZw sYrw xq xq+ xqH xqg xq7 xq> 7qx", +"H gqx7 xqS Sqx+ xZq gqxZ xr xr> xrZ yxr ?qw wq& ?Bwq wq?a w1?q :wq ?qw1B wa", +":q ?wM w&?M wq?T wa?M lw? lw: ?Tlw s?lw q*?w -qw ?qw*B wa-q ?qw1* -q:w w1*?", +"qB :wq-a ?*wM ?M-w ?qTw* wq-T ?wl* l-w lw?T* swl- ?qG qGw& wq?H qG?a ?1qG ?", +"G:q ?qG1H wq:H wM?G ?qGM& wH?M ?qGT& ?qlG lG:w ?wlH lH:w fq? fq- ?Hfq fqg? ", +"f1?q :fq fq?1H :fgq ?Mfq fM-q ?Tfq ?wgM ?flw :flw fqTl? lwg? ?4wq w4q& ?qw4", +"B ?qaw4 ?q7w :q7w ?q7wB :wq7a ?4wM ?wM4& ?qTw4 ?wa4M l?7w l:7w 7wTl? lws7? ", +"?wq= q=-w ?w=qB -qw=a ?q7w= Aqw q=?7wB wqAa ?w=M -qw=M q=T?w -qTw= ?wl= Alw", +" lw=?T lwAs ?4qG ?qG4& ?qG4H ?qG4a 7q?G :wq7G 7wH?q :wH7q ?qG4M ?G4wM& ?qG4", +"T ?G4waM lw?7G lw:7G lwH7? :wH7l q=?f f-q= fq?=H fq-g= ?q7f Aqf 7fq?H gqAf ", +"fq?=M fq-=M fqT?= fq-=T lf?7w lfAq fqT7? glAw wq?P wPq& ?qwPB ?qawP ?qw1P w", +"q:P wq1?PB :wqaP S?w S&?w ?TSw ?aSw S?lw S:w lw?ST S?sw ?qwP* wq-P wq*?PB -", +"qwaP wq1?P* :wq-P ?Bwq1P* -qa:wP S*?w Sw-q S?wT* -qTSw lw?S* S-lw S?Tlw* l-", +"wSs ?Yq Y&?q ?HYq ?aYq Y1?q Yq:w ?Yq1H :wHYq S?Y S&?Y Zq?Y ?aSY lY? ?YS: ?Z", +"lY s?lY fq?Y Y-q fq?YH ?Ygq fq?Y1 fqY: ?Y1fqH g?Y:q S?f S-?Y Sf?Z S?gw S?lf", +" ?Yl- lY?Zf g?lY oq?w wqo& o?qwB o?awq ?q7ow oq:w o?q7wB :woqa o?Sw Sw&o? o", +"?TSw S?aow r?w r:w ?wrT s?rw ?w=oq oq-w q=wo?B o-qwa o?q7w= oqAw =B7wo?q Ao", +"awq ?wS= o-qSw S?=wT o-qwT ?wr= Arw r=T?w rsAw o?Yq Yq&o? o?HYq ?Yaoq ?q7Y ", +":woYq ?Y7qH :woqH So?Y S?Yo& S?ZoY S?Yoa r?Y ?Yr: ?ZrY s?rY x?q xq- ?qxH g?", +"xq ?qx7 Axq x?q7H xqAg x?S S?x- S?xZ g?xS xr? Axr r?xZ yxAr [qw [!wq wqD wa", +"[q [w1 w8[q wD[1 wa[1 wM[q [qwM! Vwq waVq lw[ w8[l lwV Vwsq [q* w+[q [*qD q", +"+wD [*w1 [1w+ [q*1D [q8D* [Mq* [q+wM [qV* wqV+ [ql* [wl+ l*Vw l+Vw qG[w [qw", +"G! Jqw waJq wG[1 [q8wG [wJ1 wqJ8 [qwGM wMG[q! VwJq JqVwa [wlG lw[G8 lwJ Jqs", +"w fq[ [+fq Jqf Jqgw [qf1 [qf8 J1fq J8fq [qfM fq[+M fqV Vfgq [lfq fq8[l Jqlf", +" g[lw [4wq [qw4! w4qD [qaw4 7[w w87[ [w7D [w7a [qw4M [4Mwq! wqV4 Vwq4a 7[lw", +" lw7[8 7Vw 7Vsw [=q [+q= [q=D [q=a 7[= w>7[ =D7[ =a7[ [q=M [=q+M Vq[= Vw=q+", +" l=[ [>lw Vwl= 7[s= [qw4G [4Gwq! wqJ4 Jqw4a [w7G 7[wG8 7wJq Jq87w [4GwqM [!", +"wq4GM JqVw4 Vw4Jqa lw7[G 7[Glw8 7Jlw lwJ7s [=fq fq[=+ Jq= J=gq 7[f [>7f Jq7", +"f 7[gw fq[=M [=+fqM V=Jq Jq=gV 7[lf fq>[l Jql= g[l= wP[q [qwP! wPqD [qawP w", +"P[1 [q8wP [w1DP [w1aP [qSw Sq[w! VqSw VwqSa [lSw Sw8[l SlVw lwVSs [Pq* [q+w", +"P [q*DP [qaP* [q*1P [q8P* w1PqD* w1P[a* [qS* Sw+[q VwqS* Vw+Sq lw[S* lw+S[ ", +"lwVS* Vw+Sl [qYw Yw[q! JwYq JqYwa [wY1 Yq8[w JqYw1 Jq8Yw Sq[Yw Yq[Sw! ]qw w", +"q]a Yw[l lYw[8 ]lw lw]s [fYq fq[Y+ YJfq JqfgY fq[Y1 fq8[Y JqfY1 JqfY8 Sq[f ", +"Sfq[+ ]qf gq]f lYf[q fq8S[ lf]q gl]w [qow o[qw! wqoD o[awq o[7w o[87w 7wDo[", +" 7[aow Sq[ow o[qSw! oqVw oVwqa r[w [wr8 rVw swrV q=o[ [=oq+ [=oqD [=aoq 7o[", +"= [>o7w 7[=oD w>qoD Sq[= S=[q+ oVwq= oVwq+ r[= [>rw Vwr= s=r[ Yw[oq o[wYq! ", +"oqJw oJqwa Yw7[ 7[Yw8 oJq7w oJqw8 YqoSw[ Sqo[Yw! oq]w ]oqwa Ywr[ r[Yw8 ]rw ", +"rs]w xq[ [qx+ xJq gqxJ x7[ 7[x> 7Jxq g7x[ Sqx[ xq[S+ ]xq xq]g xr[ r[x> ]xr ", +"yx]r z z& zD zc z1 z: z1D z:c zM zM& zV zVc zl zl: zlV uz z* z- z*D zc- z*1", +" z:- 1Dz* :cz- z*M z-M zV* zV- zl* zl- l*zV uz- zG zG& zJ zJc z1G z:G zJ1 z", +"J: zGM GMz& zJV cJzV zlG l:zG zlJ uzJ zf zf- zJf iz zf1 z:f Jfz1 iz: zfM f-", +"zM zVf izV zlf lfz: lfzJ uzi z4 z4& z4D zc4 z7 z7: z7D z7c z4M 4Mz& zV4 c4z", +"V zl7 l:z7 z7V uz7 z= z-= z=D zc= z7= Az =Dz7 Azc z=M =Mz- zV= c=zV zl= Azl", +" l=zV Azu z4G 4Gz& zJ4 cJz4 z7G 7:zG zJ7 7Jz: 4GzM z4GM& J4zV zJVc4 lGz7 zl", +"7:G 7Jzl zJu7 zf= f-z= zJ= iz= z7f Azf 7Jzf Azi =Mzf zf-=M J=zV zVi= lfz7 z", +"lAf l=zJ uzAi zP zP& zDP zcP z1P z:P 1DzP :czP zS zS& zVS zcS zlS z:S SlzV ", +"uzS z*P z-P DPz* c-zP 1Pz* :-zP z*1DP z:c-P zS* z-S SVz* Scz- l*zS l-zS zlV", +"S* z-uS zY zY& zJY zYc zY1 zY: YJz1 Y:zJ zYS SYz& ]z ]zc zlY lYz: ]zl uz] z", +"Yf zY- YJzf izY Yfz1 Y:zf zJYf1 zYi: zfS Sfz- ]zf ]zi lYzf lYz- zl]f ]zui z", +"o zo& zoD zoc zo7 zo: 7ozD 7czo zoS Soz& zoV Sczo zr zr: zrV uzr zo= zo- =D", +"zo ocz- 7oz= Azo zo7=D zoAc z=S S-zo S=zV Scz= zr= Azr rVz= uzAr zoY Y&zo z", +"oJ Yczo z7Y Y:zo 7Jzo Ycz7 SozY zoYS& ]zo zo]c zrY rYz: ]zr ]zur zx zx- zxJ", +" izx zx7 Azx xJz7 izAx zxS x-zS ]zx iz]x zxr zxAr zx]r | ", +NULL +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Prepares the data for MSOPs of 4-variable functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_ReadMsops( char ** ppSopSizes, char *** ppSops ) +{ + unsigned uMasks[4][2] = { + { 0x5555, 0xAAAA }, + { 0x3333, 0xCCCC }, + { 0x0F0F, 0xF0F0 }, + { 0x00FF, 0xFF00 } + }; + char Map[256], * pPrev, * pMemory; + char * pSopSizes, ** pSops; + int i, k, b, Size; + + // map chars into their numbers + for ( i = 0; i < 256; i++ ) + Map[i] = -1; + for ( i = 0; i < 81; i++ ) + Map[s_Data3[i]] = i; + + // count the number of strings + for ( Size = 0; s_Data4[Size] && Size < 100000; Size++ ); + assert( Size < 100000 ); + + // allocate memory + pMemory = ALLOC( char, Size * 75 ); + // copy the array into memory + for ( i = 0; i < Size; i++ ) + for ( k = 0; k < 75; k++ ) + if ( s_Data4[i][k] == ' ' ) + pMemory[i*75+k] = -1; + else + pMemory[i*75+k] = Map[s_Data4[i][k]]; + + // set pointers and compute SOP sizes + pSopSizes = ALLOC( char, 65536 ); + pSops = ALLOC( char *, 65536 ); + pSopSizes[0] = 0; + pSops[0] = NULL; + pPrev = pMemory; + for ( k = 0, i = 1; i < 65536; k++ ) + if ( pMemory[k] == -1 ) + { + pSopSizes[i] = pMemory + k - pPrev; + pSops[i++] = pPrev; + pPrev = pMemory + k + 1; + } + *ppSopSizes = pSopSizes; + *ppSops = pSops; + + // verify the results - derive truth table from SOP + for ( i = 1; i < 65536; i++ ) + { + int uTruth = 0, uCube, Lit; + for ( k = 0; k < pSopSizes[i]; k++ ) + { + uCube = 0xFFFF; + Lit = pSops[i][k]; + for ( b = 3; b >= 0; b-- ) + { + if ( Lit % 3 == 0 ) + uCube &= uMasks[b][0]; + else if ( Lit % 3 == 1 ) + uCube &= uMasks[b][1]; + Lit = Lit / 3; + } + uTruth |= uCube; + } + assert( uTruth == i ); + } +} + +#if 0 + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManDeriveCnfTest() +{ + int i, k, Lit; + printf( "\n" ); + for ( i = 80; i >= 0; i-- ) + { + Lit = i; + for ( k = 0; k < 4; k++ ) + { + if ( Lit % 3 == 0 ) + printf( "%c", 'A' + k ); + else if ( Lit % 3 == 1 ) + printf( "%c", 'a' + k ); + Lit = Lit / 3; + } + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManDeriveCnfTest2() +{ + char s_Data3[81] = "!#&()*+,-.0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz|"; + + unsigned uMasks[4][2] = { + { 0x5555, 0xAAAA }, + { 0x3333, 0xCCCC }, + { 0x0F0F, 0xF0F0 }, + { 0x00FF, 0xFF00 } + }; + char Buffer[100], * pCur; + FILE * pFile; + int CountCur, Counter = 0, nLines = 0; + int pLines[1<<16] = {0}; + int pNums[1<<16] = {0}; + unsigned uTruth, uTruth2, uCube, cCube; + char * pSops[1<<16] = {0}; + char Sop[10]; + char Cube[4]; + int i, k; + + pFile = fopen( "cands2.txt", "r" ); + while ( fgets( Buffer, 100, pFile ) ) + { + if ( Buffer[0] == '0' ) + Extra_ReadHexadecimal( &uTruth2, Buffer+2, 4 ); + else + uTruth2 = 0xFFFFFF; + + // skip all chars till a-d or A-D + if ( Buffer[0] == '0' ) + for ( pCur = Buffer; *pCur != '\n'; pCur++ ) + { +// if ( *pCur >= 'a' && *pCur <= 'd' || *pCur >= 'A' && *pCur <= 'D' ) + if ( *pCur == ':' ) + { + pCur++; + break; + } + } + else + pCur = Buffer; + + + uTruth = 0; + CountCur = 0; + uCube = 0xFFFF; + for ( i = 0; i < 4; i++ ) + Cube[i] = 2; + + for ( ; *pCur; pCur++ ) + { + if ( *pCur == '+' || *pCur == '\n' ) + { + uTruth |= uCube; + uCube = 0xFFFF; + + // get the cube + cCube = 0; + for ( i = 0; i < 4; i++ ) + cCube = 3 * cCube + Cube[i]; + for ( i = 0; i < 4; i++ ) + Cube[i] = 2; + + assert( cCube >= 0 && cCube < 81 ); + Sop[CountCur] = cCube; + CountCur++; + if ( *pCur == '\n' ) + { + Sop[CountCur] = 0; + break; + } + } + else if ( *pCur >= 'a' && *pCur <= 'd' ) + { + uCube &= uMasks[*pCur-'a'][1]; + Cube[*pCur-'a'] = 1; + } + else if ( *pCur >= 'A' && *pCur <= 'D' ) + { + uCube &= uMasks[*pCur-'A'][0]; + Cube[*pCur-'A'] = 0; + } + } + assert( *pCur == '\n' ); + assert( uTruth2 == 0xFFFFFF || uTruth2 == uTruth ); + + Counter += CountCur; + pNums[uTruth] = CountCur; + pSops[uTruth] = ALLOC( char, CountCur ); + memcpy( pSops[uTruth], Sop, CountCur ); + pLines[nLines++] = Counter; + } + fclose( pFile ); + + printf( "Lines = %d. Counter = %d.\n", nLines, Counter ); + +/* + // write the number of cubes + for ( i = 0; i < 65536; i++ ) + printf( "%d,%d ", pNums[i], pNums[i] + pNums[0xffff & ~i] ); + printf( "\n" ); +*/ + + // write the number of cubes + Counter = 0; + for ( i = 1; i < 65536; i++ ) + { + CountCur = pNums[i]; + assert( CountCur > 0 ); + for ( k = 0; k <= CountCur; k++ ) + { + if ( k < CountCur ) + { + assert( pSops[i][k] >= 0 && pSops[i][k] < 81 ); + printf( "%c", s_Data3[pSops[i][k]] ); + } + else + printf( " " ); + if ( ++Counter == 75 ) + { + printf( "\",\n\"" ); + Counter = 0; + } + } + } + printf( "\n" ); + + return 1; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/cnf/cnfMan.c b/abc70930/src/aig/cnf/cnfMan.c new file mode 100644 index 00000000..1edc012a --- /dev/null +++ b/abc70930/src/aig/cnf/cnfMan.c @@ -0,0 +1,202 @@ +/**CFile**************************************************************** + + FileName [cnfMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG-to-CNF conversion.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: cnfMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cnf.h" +#include "satSolver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Cnf_Lit2Var( int Lit ) { return (Lit & 1)? -(Lit >> 1)-1 : (Lit >> 1)+1; } +static inline int Cnf_Lit2Var2( int Lit ) { return (Lit & 1)? -(Lit >> 1) : (Lit >> 1); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Man_t * Cnf_ManStart() +{ + Cnf_Man_t * p; + int i; + // allocate the manager + p = ALLOC( Cnf_Man_t, 1 ); + memset( p, 0, sizeof(Cnf_Man_t) ); + // derive internal data structures + Cnf_ReadMsops( &p->pSopSizes, &p->pSops ); + // allocate memory manager for cuts + p->pMemCuts = Aig_MmFlexStart(); + p->nMergeLimit = 10; + // allocate temporary truth tables + p->pTruths[0] = ALLOC( unsigned, 4 * Aig_TruthWordNum(p->nMergeLimit) ); + for ( i = 1; i < 4; i++ ) + p->pTruths[i] = p->pTruths[i-1] + Aig_TruthWordNum(p->nMergeLimit); + p->vMemory = Vec_IntAlloc( 1 << 18 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_ManStop( Cnf_Man_t * p ) +{ + Vec_IntFree( p->vMemory ); + free( p->pTruths[0] ); + Aig_MmFlexStop( p->pMemCuts, 0 ); + free( p->pSopSizes ); + free( p->pSops[1] ); + free( p->pSops ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of CI IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cnf_DataCollectPiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ) +{ + Vec_Int_t * vCiIds; + Aig_Obj_t * pObj; + int i; + vCiIds = Vec_IntAlloc( Aig_ManPiNum(p) ); + Aig_ManForEachPi( p, pObj, i ) + Vec_IntPush( vCiIds, pCnf->pVarNums[pObj->Id] ); + return vCiIds; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_DataFree( Cnf_Dat_t * p ) +{ + if ( p == NULL ) + return; + free( p->pClauses[0] ); + free( p->pClauses ); + free( p->pVarNums ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Writes CNF into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable ) +{ + FILE * pFile; + int * pLit, * pStop, i; + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" ); + return; + } + fprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" ); + fprintf( pFile, "p %d %d\n", p->nVars, p->nClauses ); + for ( i = 0; i < p->nClauses; i++ ) + { + for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ ) + fprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) ); + fprintf( pFile, "0\n" ); + } + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes CNF into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p ) +{ + sat_solver * pSat; + int i, status; + pSat = sat_solver_new(); + sat_solver_setnvars( pSat, p->nVars ); + for ( i = 0; i < p->nClauses; i++ ) + { + if ( !sat_solver_addclause( pSat, p->pClauses[i], p->pClauses[i+1] ) ) + { + sat_solver_delete( pSat ); + return NULL; + } + } + status = sat_solver_simplify(pSat); + if ( status == 0 ) + { + sat_solver_delete( pSat ); + return NULL; + } + return pSat; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/cnf/cnfMap.c b/abc70930/src/aig/cnf/cnfMap.c new file mode 100644 index 00000000..d966df15 --- /dev/null +++ b/abc70930/src/aig/cnf/cnfMap.c @@ -0,0 +1,356 @@ +/**CFile**************************************************************** + + FileName [cnfMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG-to-CNF conversion.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: cnfMap.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cnf.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes area flow of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CutAssignAreaFlow( Cnf_Man_t * p, Dar_Cut_t * pCut, int * pAreaFlows ) +{ + Aig_Obj_t * pLeaf; + int i; + pCut->Value = 0; + pCut->uSign = 100 * Cnf_CutSopCost( p, pCut ); + Dar_CutForEachLeaf( p->pManAig, pCut, pLeaf, i ) + { + pCut->Value += pLeaf->nRefs; + if ( !Aig_ObjIsNode(pLeaf) ) + continue; + assert( pLeaf->nRefs > 0 ); + pCut->uSign += pAreaFlows[pLeaf->Id] / (pLeaf->nRefs? pLeaf->nRefs : 1); + } +} + +/**Function************************************************************* + + Synopsis [Computes area flow of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_CutSuperAreaFlow( Vec_Ptr_t * vSuper, int * pAreaFlows ) +{ + Aig_Obj_t * pLeaf; + int i, nAreaFlow; + nAreaFlow = 100 * (Vec_PtrSize(vSuper) + 1); + Vec_PtrForEachEntry( vSuper, pLeaf, i ) + { + pLeaf = Aig_Regular(pLeaf); + if ( !Aig_ObjIsNode(pLeaf) ) + continue; + assert( pLeaf->nRefs > 0 ); + nAreaFlow += pAreaFlows[pLeaf->Id] / (pLeaf->nRefs? pLeaf->nRefs : 1); + } + return nAreaFlow; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_DeriveMapping( Cnf_Man_t * p ) +{ + Vec_Ptr_t * vSuper; + Aig_Obj_t * pObj; + Dar_Cut_t * pCut, * pCutBest; + int i, k, AreaFlow, * pAreaFlows; + // allocate area flows + pAreaFlows = ALLOC( int, Aig_ManObjNumMax(p->pManAig) ); + memset( pAreaFlows, 0, sizeof(int) * Aig_ManObjNumMax(p->pManAig) ); + // visit the nodes in the topological order and update their best cuts + vSuper = Vec_PtrAlloc( 100 ); + Aig_ManForEachNode( p->pManAig, pObj, i ) + { + // go through the cuts + pCutBest = NULL; + Dar_ObjForEachCut( pObj, pCut, k ) + { + pCut->fBest = 0; + if ( k == 0 ) + continue; + Cnf_CutAssignAreaFlow( p, pCut, pAreaFlows ); + if ( pCutBest == NULL || pCutBest->uSign > pCut->uSign || + (pCutBest->uSign == pCut->uSign && pCutBest->Value < pCut->Value) ) + pCutBest = pCut; + } + // check the big cut +// Aig_ObjCollectSuper( pObj, vSuper ); + // get the area flow of this cut +// AreaFlow = Cnf_CutSuperAreaFlow( vSuper, pAreaFlows ); + AreaFlow = AIG_INFINITY; + if ( AreaFlow >= (int)pCutBest->uSign ) + { + pAreaFlows[pObj->Id] = pCutBest->uSign; + pCutBest->fBest = 1; + } + else + { + pAreaFlows[pObj->Id] = AreaFlow; + pObj->fMarkB = 1; // mark the special node + } + } + Vec_PtrFree( vSuper ); + free( pAreaFlows ); + +/* + // compute the area of mapping + AreaFlow = 0; + Aig_ManForEachPo( p->pManAig, pObj, i ) + AreaFlow += Dar_ObjBestCut(Aig_ObjFanin0(pObj))->uSign / 100 / Aig_ObjFanin0(pObj)->nRefs; + printf( "Area of the network = %d.\n", AreaFlow ); +*/ +} + + + +#if 0 + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CutDeref( Aig_Man_t * p, Dar_Cut_t * pCut ) +{ + Aig_Obj_t * pLeaf; + int i; + Dar_CutForEachLeaf( p, pCut, pLeaf, i ) + { + assert( pLeaf->nRefs > 0 ); + if ( --pLeaf->nRefs > 0 || !Aig_ObjIsAnd(pLeaf) ) + continue; + Aig_CutDeref( p, Aig_ObjBestCut(pLeaf) ); + } +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_CutRef( Aig_Man_t * p, Dar_Cut_t * pCut ) +{ + Aig_Obj_t * pLeaf; + int i, Area = pCut->Value; + Dar_CutForEachLeaf( p, pCut, pLeaf, i ) + { + assert( pLeaf->nRefs >= 0 ); + if ( pLeaf->nRefs++ > 0 || !Aig_ObjIsAnd(pLeaf) ) + continue; + Area += Aig_CutRef( p, Aig_ObjBestCut(pLeaf) ); + } + return Area; +} + +/**Function************************************************************* + + Synopsis [Computes exact area of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_CutArea( Aig_Man_t * p, Dar_Cut_t * pCut ) +{ + int Area; + Area = Aig_CutRef( p, pCut ); + Aig_CutDeref( p, pCut ); + return Area; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the second cut is better.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cnf_CutCompare( Dar_Cut_t * pC0, Dar_Cut_t * pC1 ) +{ + if ( pC0->Area < pC1->Area - 0.0001 ) + return -1; + if ( pC0->Area > pC1->Area + 0.0001 ) // smaller area flow is better + return 1; +// if ( pC0->NoRefs < pC1->NoRefs ) +// return -1; +// if ( pC0->NoRefs > pC1->NoRefs ) // fewer non-referenced fanins is better +// return 1; +// if ( pC0->FanRefs / pC0->nLeaves > pC1->FanRefs / pC1->nLeaves ) +// return -1; +// if ( pC0->FanRefs / pC0->nLeaves < pC1->FanRefs / pC1->nLeaves ) +// return 1; // larger average fanin ref-counter is better +// return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns the cut with the smallest area flow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dar_Cut_t * Cnf_ObjFindBestCut( Aig_Obj_t * pObj ) +{ + Dar_Cut_t * pCut, * pCutBest; + int i; + pCutBest = NULL; + Dar_ObjForEachCut( pObj, pCut, i ) + if ( pCutBest == NULL || Cnf_CutCompare(pCutBest, pCut) == 1 ) + pCutBest = pCut; + return pCutBest; +} + +/**Function************************************************************* + + Synopsis [Computes area flow of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_CutAssignArea( Cnf_Man_t * p, Dar_Cut_t * pCut ) +{ + Aig_Obj_t * pLeaf; + int i; + pCut->Area = (float)pCut->Cost; + pCut->NoRefs = 0; + pCut->FanRefs = 0; + Dar_CutForEachLeaf( p->pManAig, pCut, pLeaf, i ) + { + if ( !Aig_ObjIsNode(pLeaf) ) + continue; + if ( pLeaf->nRefs == 0 ) + { + pCut->Area += Aig_ObjBestCut(pLeaf)->Cost; + pCut->NoRefs++; + } + else + { + if ( pCut->FanRefs + pLeaf->nRefs > 15 ) + pCut->FanRefs = 15; + else + pCut->FanRefs += pLeaf->nRefs; + } + } +} + +/**Function************************************************************* + + Synopsis [Performs one round of "area recovery" using exact local area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_ManMapForCnf( Cnf_Man_t * p ) +{ + Aig_Obj_t * pObj; + Dar_Cut_t * pCut, * pCutBest; + int i, k; + // visit the nodes in the topological order and update their best cuts + Aig_ManForEachNode( p->pManAig, pObj, i ) + { + // find the old best cut + pCutBest = Aig_ObjBestCut(pObj); + Dar_ObjClearBestCut(pCutBest); + // if the node is used, dereference its cut + if ( pObj->nRefs ) + Aig_CutDeref( p->pManAig, pCutBest ); + + // evaluate the cuts of this node + Dar_ObjForEachCut( pObj, pCut, k ) +// Cnf_CutAssignAreaFlow( p, pCut ); + pCut->Area = (float)Cnf_CutArea( p->pManAig, pCut ); + + // find the new best cut + pCutBest = Cnf_ObjFindBestCut(pObj); + Dar_ObjSetBestCut( pCutBest ); + // if the node is used, reference its cut + if ( pObj->nRefs ) + Aig_CutRef( p->pManAig, pCutBest ); + } + return 1; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/cnf/cnfPost.c b/abc70930/src/aig/cnf/cnfPost.c new file mode 100644 index 00000000..988275b2 --- /dev/null +++ b/abc70930/src/aig/cnf/cnfPost.c @@ -0,0 +1,233 @@ +/**CFile**************************************************************** + + FileName [cnfPost.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG-to-CNF conversion.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: cnfPost.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cnf.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_ManPostprocess_old( Cnf_Man_t * p ) +{ +// extern int Aig_ManLargeCutEval( Aig_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCutR, Dar_Cut_t * pCutL, int Leaf ); + int nNew, Gain, nGain = 0, nVars = 0; + + Aig_Obj_t * pObj, * pFan; + Dar_Cut_t * pCutBest, * pCut; + int i, k;//, a, b, Counter; + Aig_ManForEachObj( p->pManAig, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + if ( pObj->nRefs == 0 ) + continue; +// pCutBest = Aig_ObjBestCut(pObj); + pCutBest = NULL; + + Dar_CutForEachLeaf( p->pManAig, pCutBest, pFan, k ) + { + if ( !Aig_ObjIsNode(pFan) ) + continue; + assert( pFan->nRefs != 0 ); + if ( pFan->nRefs != 1 ) + continue; +// pCut = Aig_ObjBestCut(pFan); + pCut = NULL; +/* + // find how many common variable they have + Counter = 0; + for ( a = 0; a < (int)pCut->nLeaves; a++ ) + { + for ( b = 0; b < (int)pCutBest->nLeaves; b++ ) + if ( pCut->pLeaves[a] == pCutBest->pLeaves[b] ) + break; + if ( b == (int)pCutBest->nLeaves ) + continue; + Counter++; + } + printf( "%d ", Counter ); +*/ + // find the new truth table after collapsing these two cuts + + +// nNew = Aig_ManLargeCutEval( p->pManAig, pObj, pCutBest, pCut, pFan->Id ); + nNew = 0; + + +// printf( "%d+%d=%d:%d(%d) ", pCutBest->Cost, pCut->Cost, +// pCutBest->Cost+pCut->Cost, nNew, pCutBest->Cost+pCut->Cost-nNew ); + + Gain = pCutBest->Value + pCut->Value - nNew; + if ( Gain > 0 ) + { + nGain += Gain; + nVars++; + } + } + } + printf( "Total gain = %d. Vars = %d.\n", nGain, nVars ); +} + +/**Function************************************************************* + + Synopsis [Transfers cuts of the mapped nodes into internal representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_ManTransferCuts( Cnf_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_MmFlexRestart( p->pMemCuts ); + Aig_ManForEachObj( p->pManAig, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) && pObj->nRefs > 0 ) + pObj->pData = Cnf_CutCreate( p, pObj ); + else + pObj->pData = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Transfers cuts of the mapped nodes into internal representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_ManFreeCuts( Cnf_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p->pManAig, pObj, i ) + if ( pObj->pData ) + { + Cnf_CutFree( pObj->pData ); + pObj->pData = NULL; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_ManPostprocess( Cnf_Man_t * p ) +{ + Cnf_Cut_t * pCut, * pCutFan, * pCutRes; + Aig_Obj_t * pObj, * pFan; + int Order[16], Costs[16]; + int i, k, fChanges; + Aig_ManForEachNode( p->pManAig, pObj, i ) + { + if ( pObj->nRefs == 0 ) + continue; + pCut = Cnf_ObjBestCut(pObj); + + // sort fanins according to their size + Cnf_CutForEachLeaf( p->pManAig, pCut, pFan, k ) + { + Order[k] = k; + Costs[k] = Aig_ObjIsNode(pFan)? Cnf_ObjBestCut(pFan)->Cost : 0; + } + // sort the cuts by Weight + do { + int Temp; + fChanges = 0; + for ( k = 0; k < pCut->nFanins - 1; k++ ) + { + if ( Costs[Order[k]] <= Costs[Order[k+1]] ) + continue; + Temp = Order[k]; + Order[k] = Order[k+1]; + Order[k+1] = Temp; + fChanges = 1; + } + } while ( fChanges ); + + +// Cnf_CutForEachLeaf( p->pManAig, pCut, pFan, k ) + for ( k = 0; (k < (int)(pCut)->nFanins) && ((pFan) = Aig_ManObj(p->pManAig, (pCut)->pFanins[Order[k]])); k++ ) + { + if ( !Aig_ObjIsNode(pFan) ) + continue; + assert( pFan->nRefs != 0 ); + if ( pFan->nRefs != 1 ) + continue; + pCutFan = Cnf_ObjBestCut(pFan); + // try composing these two cuts +// Cnf_CutPrint( pCut ); + pCutRes = Cnf_CutCompose( p, pCut, pCutFan, pFan->Id ); +// Cnf_CutPrint( pCut ); +// printf( "\n" ); + // check if the cost if reduced + if ( pCutRes == NULL || pCutRes->Cost == 127 || pCutRes->Cost > pCut->Cost + pCutFan->Cost ) + { + if ( pCutRes ) + Cnf_CutFree( pCutRes ); + continue; + } + // update the cut + Cnf_ObjSetBestCut( pObj, pCutRes ); + Cnf_ObjSetBestCut( pFan, NULL ); + Cnf_CutUpdateRefs( p, pCut, pCutFan, pCutRes ); + assert( pFan->nRefs == 0 ); + Cnf_CutFree( pCut ); + Cnf_CutFree( pCutFan ); + break; + } + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/cnf/cnfUtil.c b/abc70930/src/aig/cnf/cnfUtil.c new file mode 100644 index 00000000..cd47cb58 --- /dev/null +++ b/abc70930/src/aig/cnf/cnfUtil.c @@ -0,0 +1,188 @@ +/**CFile**************************************************************** + + FileName [cnfUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG-to-CNF conversion.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: cnfUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cnf.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes area, references, and nodes used in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManScanMapping_rec( Cnf_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vMapped ) +{ + Aig_Obj_t * pLeaf; + Dar_Cut_t * pCutBest; + int aArea, i; + if ( pObj->nRefs++ || Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) + return 0; + assert( Aig_ObjIsAnd(pObj) ); + // collect the node first to derive pre-order + if ( vMapped ) + Vec_PtrPush( vMapped, pObj ); + // visit the transitive fanin of the selected cut + if ( pObj->fMarkB ) + { + Vec_Ptr_t * vSuper = Vec_PtrAlloc( 100 ); + Aig_ObjCollectSuper( pObj, vSuper ); + aArea = Vec_PtrSize(vSuper) + 1; + Vec_PtrForEachEntry( vSuper, pLeaf, i ) + aArea += Aig_ManScanMapping_rec( p, Aig_Regular(pLeaf), vMapped ); + Vec_PtrFree( vSuper ); + //////////////////////////// + pObj->fMarkB = 1; + } + else + { + pCutBest = Dar_ObjBestCut( pObj ); + aArea = Cnf_CutSopCost( p, pCutBest ); + Dar_CutForEachLeaf( p->pManAig, pCutBest, pLeaf, i ) + aArea += Aig_ManScanMapping_rec( p, pLeaf, vMapped ); + } + return aArea; +} + +/**Function************************************************************* + + Synopsis [Computes area, references, and nodes used in the mapping.] + + Description [Collects the nodes in reverse topological order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManScanMapping( Cnf_Man_t * p, int fCollect ) +{ + Vec_Ptr_t * vMapped = NULL; + Aig_Obj_t * pObj; + int i; + // clean all references + Aig_ManForEachObj( p->pManAig, pObj, i ) + pObj->nRefs = 0; + // allocate the array + if ( fCollect ) + vMapped = Vec_PtrAlloc( 1000 ); + // collect nodes reachable from POs in the DFS order through the best cuts + p->aArea = 0; + Aig_ManForEachPo( p->pManAig, pObj, i ) + p->aArea += Aig_ManScanMapping_rec( p, Aig_ObjFanin0(pObj), vMapped ); +// printf( "Variables = %6d. Clauses = %8d.\n", vMapped? Vec_PtrSize(vMapped) + Aig_ManPiNum(p->pManAig) + 1 : 0, p->aArea + 2 ); + return vMapped; +} + +/**Function************************************************************* + + Synopsis [Computes area, references, and nodes used in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_ManScanMapping_rec( Cnf_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vMapped, int fPreorder ) +{ + Aig_Obj_t * pLeaf; + Cnf_Cut_t * pCutBest; + int aArea, i; + if ( pObj->nRefs++ || Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) + return 0; + assert( Aig_ObjIsAnd(pObj) ); + assert( pObj->pData != NULL ); + // add the node to the mapping + if ( vMapped && fPreorder ) + Vec_PtrPush( vMapped, pObj ); + // visit the transitive fanin of the selected cut + if ( pObj->fMarkB ) + { + Vec_Ptr_t * vSuper = Vec_PtrAlloc( 100 ); + Aig_ObjCollectSuper( pObj, vSuper ); + aArea = Vec_PtrSize(vSuper) + 1; + Vec_PtrForEachEntry( vSuper, pLeaf, i ) + aArea += Cnf_ManScanMapping_rec( p, Aig_Regular(pLeaf), vMapped, fPreorder ); + Vec_PtrFree( vSuper ); + //////////////////////////// + pObj->fMarkB = 1; + } + else + { + pCutBest = pObj->pData; + assert( pCutBest->Cost < 127 ); + aArea = pCutBest->Cost; + Cnf_CutForEachLeaf( p->pManAig, pCutBest, pLeaf, i ) + aArea += Cnf_ManScanMapping_rec( p, pLeaf, vMapped, fPreorder ); + } + // add the node to the mapping + if ( vMapped && !fPreorder ) + Vec_PtrPush( vMapped, pObj ); + return aArea; +} + +/**Function************************************************************* + + Synopsis [Computes area, references, and nodes used in the mapping.] + + Description [Collects the nodes in reverse topological order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Cnf_ManScanMapping( Cnf_Man_t * p, int fCollect, int fPreorder ) +{ + Vec_Ptr_t * vMapped = NULL; + Aig_Obj_t * pObj; + int i; + // clean all references + Aig_ManForEachObj( p->pManAig, pObj, i ) + pObj->nRefs = 0; + // allocate the array + if ( fCollect ) + vMapped = Vec_PtrAlloc( 1000 ); + // collect nodes reachable from POs in the DFS order through the best cuts + p->aArea = 0; + Aig_ManForEachPo( p->pManAig, pObj, i ) + p->aArea += Cnf_ManScanMapping_rec( p, Aig_ObjFanin0(pObj), vMapped, fPreorder ); +// printf( "Variables = %6d. Clauses = %8d.\n", vMapped? Vec_PtrSize(vMapped) + Aig_ManPiNum(p->pManAig) + 1 : 0, p->aArea + 2 ); + return vMapped; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/cnf/cnfWrite.c b/abc70930/src/aig/cnf/cnfWrite.c new file mode 100644 index 00000000..45a3efad --- /dev/null +++ b/abc70930/src/aig/cnf/cnfWrite.c @@ -0,0 +1,443 @@ +/**CFile**************************************************************** + + FileName [cnfWrite.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG-to-CNF conversion.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: cnfWrite.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cnf.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the cover into the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cnf_SopConvertToVector( char * pSop, int nCubes, Vec_Int_t * vCover ) +{ + int Lits[4], Cube, iCube, i, b; + Vec_IntClear( vCover ); + for ( i = 0; i < nCubes; i++ ) + { + Cube = pSop[i]; + for ( b = 0; b < 4; b++ ) + { + if ( Cube % 3 == 0 ) + Lits[b] = 1; + else if ( Cube % 3 == 1 ) + Lits[b] = 2; + else + Lits[b] = 0; + Cube = Cube / 3; + } + iCube = 0; + for ( b = 0; b < 4; b++ ) + iCube = (iCube << 2) | Lits[b]; + Vec_IntPush( vCover, iCube ); + } +} + +/**Function************************************************************* + + Synopsis [Returns the number of literals in the SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_SopCountLiterals( char * pSop, int nCubes ) +{ + int nLits = 0, Cube, i, b; + for ( i = 0; i < nCubes; i++ ) + { + Cube = pSop[i]; + for ( b = 0; b < 4; b++ ) + { + if ( Cube % 3 != 2 ) + nLits++; + Cube = Cube / 3; + } + } + return nLits; +} + +/**Function************************************************************* + + Synopsis [Returns the number of literals in the SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_IsopCountLiterals( Vec_Int_t * vIsop, int nVars ) +{ + int nLits = 0, Cube, i, b; + Vec_IntForEachEntry( vIsop, Cube, i ) + { + for ( b = 0; b < nVars; b++ ) + { + if ( (Cube & 3) == 1 || (Cube & 3) == 2 ) + nLits++; + Cube >>= 2; + } + } + return nLits; +} + +/**Function************************************************************* + + Synopsis [Writes the cube and returns the number of literals in it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cnf_IsopWriteCube( int Cube, int nVars, int * pVars, int * pLiterals ) +{ + int nLits = nVars, b; + for ( b = 0; b < nVars; b++ ) + { + if ( (Cube & 3) == 1 ) // value 0 --> write positive literal + *pLiterals++ = 2 * pVars[b]; + else if ( (Cube & 3) == 2 ) // value 1 --> write negative literal + *pLiterals++ = 2 * pVars[b] + 1; + else + nLits--; + Cube >>= 2; + } + return nLits; +} + +/**Function************************************************************* + + Synopsis [Derives CNF for the mapping.] + + Description [The last argument shows the number of last outputs + of the manager, which will not be converted into clauses but the + new variables for which will be introduced.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Dat_t * Cnf_ManWriteCnf( Cnf_Man_t * p, Vec_Ptr_t * vMapped, int nOutputs ) +{ + Aig_Obj_t * pObj; + Cnf_Dat_t * pCnf; + Cnf_Cut_t * pCut; + Vec_Int_t * vCover, * vSopTemp; + int OutVar, PoVar, pVars[32], * pLits, ** pClas; + unsigned uTruth; + int i, k, nLiterals, nClauses, Cube, Number; + + // count the number of literals and clauses + nLiterals = 1 + Aig_ManPoNum( p->pManAig ) + 3 * nOutputs; + nClauses = 1 + Aig_ManPoNum( p->pManAig ) + nOutputs; + Vec_PtrForEachEntry( vMapped, pObj, i ) + { + assert( Aig_ObjIsNode(pObj) ); + pCut = Cnf_ObjBestCut( pObj ); + + // positive polarity of the cut + if ( pCut->nFanins < 5 ) + { + uTruth = 0xFFFF & *Cnf_CutTruth(pCut); + nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth]; + assert( p->pSopSizes[uTruth] >= 0 ); + nClauses += p->pSopSizes[uTruth]; + } + else + { + nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[1], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[1]); + nClauses += Vec_IntSize(pCut->vIsop[1]); + } + // negative polarity of the cut + if ( pCut->nFanins < 5 ) + { + uTruth = 0xFFFF & ~*Cnf_CutTruth(pCut); + nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth]; + assert( p->pSopSizes[uTruth] >= 0 ); + nClauses += p->pSopSizes[uTruth]; + } + else + { + nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[0], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[0]); + nClauses += Vec_IntSize(pCut->vIsop[0]); + } +//printf( "%d ", nClauses-(1 + Aig_ManPoNum( p->pManAig )) ); + } +//printf( "\n" ); + + // allocate CNF + pCnf = ALLOC( Cnf_Dat_t, 1 ); + memset( pCnf, 0, sizeof(Cnf_Dat_t) ); + pCnf->nLiterals = nLiterals; + pCnf->nClauses = nClauses; + pCnf->pClauses = ALLOC( int *, nClauses + 1 ); + pCnf->pClauses[0] = ALLOC( int, nLiterals ); + pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; + + // create room for variable numbers + pCnf->pVarNums = ALLOC( int, Aig_ManObjNumMax(p->pManAig) ); + memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p->pManAig) ); + // assign variables to the last (nOutputs) POs + Number = 1; + if ( nOutputs ) + { + assert( nOutputs == Aig_ManRegNum(p->pManAig) ); + Aig_ManForEachLiSeq( p->pManAig, pObj, i ) + pCnf->pVarNums[pObj->Id] = Number++; + } + // assign variables to the internal nodes + Vec_PtrForEachEntry( vMapped, pObj, i ) + pCnf->pVarNums[pObj->Id] = Number++; + // assign variables to the PIs and constant node + Aig_ManForEachPi( p->pManAig, pObj, i ) + pCnf->pVarNums[pObj->Id] = Number++; + pCnf->pVarNums[Aig_ManConst1(p->pManAig)->Id] = Number++; + pCnf->nVars = Number; + + // assign the clauses + vSopTemp = Vec_IntAlloc( 1 << 16 ); + pLits = pCnf->pClauses[0]; + pClas = pCnf->pClauses; + Vec_PtrForEachEntry( vMapped, pObj, i ) + { + pCut = Cnf_ObjBestCut( pObj ); + + // save variables of this cut + OutVar = pCnf->pVarNums[ pObj->Id ]; + for ( k = 0; k < (int)pCut->nFanins; k++ ) + { + pVars[k] = pCnf->pVarNums[ pCut->pFanins[k] ]; + assert( pVars[k] <= Aig_ManObjNumMax(p->pManAig) ); + } + + // positive polarity of the cut + if ( pCut->nFanins < 5 ) + { + uTruth = 0xFFFF & *Cnf_CutTruth(pCut); + Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vSopTemp ); + vCover = vSopTemp; + } + else + vCover = pCut->vIsop[1]; + Vec_IntForEachEntry( vCover, Cube, k ) + { + *pClas++ = pLits; + *pLits++ = 2 * OutVar; + pLits += Cnf_IsopWriteCube( Cube, pCut->nFanins, pVars, pLits ); + } + + // negative polarity of the cut + if ( pCut->nFanins < 5 ) + { + uTruth = 0xFFFF & ~*Cnf_CutTruth(pCut); + Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vSopTemp ); + vCover = vSopTemp; + } + else + vCover = pCut->vIsop[0]; + Vec_IntForEachEntry( vCover, Cube, k ) + { + *pClas++ = pLits; + *pLits++ = 2 * OutVar + 1; + pLits += Cnf_IsopWriteCube( Cube, pCut->nFanins, pVars, pLits ); + } + } + Vec_IntFree( vSopTemp ); + + // write the constant literal + OutVar = pCnf->pVarNums[ Aig_ManConst1(p->pManAig)->Id ]; + assert( OutVar <= Aig_ManObjNumMax(p->pManAig) ); + *pClas++ = pLits; + *pLits++ = 2 * OutVar; + + // write the output literals + Aig_ManForEachPo( p->pManAig, pObj, i ) + { + OutVar = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ]; + if ( i < Aig_ManPoNum(p->pManAig) - nOutputs ) + { + *pClas++ = pLits; + *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); + } + else + { + PoVar = pCnf->pVarNums[ pObj->Id ]; + // first clause + *pClas++ = pLits; + *pLits++ = 2 * PoVar; + *pLits++ = 2 * OutVar + !Aig_ObjFaninC0(pObj); + // second clause + *pClas++ = pLits; + *pLits++ = 2 * PoVar + 1; + *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); + } + } + + // verify that the correct number of literals and clauses was written + assert( pLits - pCnf->pClauses[0] == nLiterals ); + assert( pClas - pCnf->pClauses == nClauses ); + return pCnf; +} + + +/**Function************************************************************* + + Synopsis [Derives a simple CNF for the AIG.] + + Description [The last argument shows the number of last outputs + of the manager, which will not be converted into clauses but the + new variables for which will be introduced.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Dat_t * Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs ) +{ + Aig_Obj_t * pObj; + Cnf_Dat_t * pCnf; + int OutVar, PoVar, pVars[32], * pLits, ** pClas; + int i, nLiterals, nClauses, Number; + + // count the number of literals and clauses + nLiterals = 1 + 7 * Aig_ManNodeNum(p) + Aig_ManPoNum( p ) + 3 * nOutputs; + nClauses = 1 + 3 * Aig_ManNodeNum(p) + Aig_ManPoNum( p ) + nOutputs; + + // allocate CNF + pCnf = ALLOC( Cnf_Dat_t, 1 ); + memset( pCnf, 0, sizeof(Cnf_Dat_t) ); + pCnf->nLiterals = nLiterals; + pCnf->nClauses = nClauses; + pCnf->pClauses = ALLOC( int *, nClauses + 1 ); + pCnf->pClauses[0] = ALLOC( int, nLiterals ); + pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; + + // create room for variable numbers + pCnf->pVarNums = ALLOC( int, Aig_ManObjNumMax(p) ); + memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p) ); + // assign variables to the last (nOutputs) POs + Number = 1; + if ( nOutputs ) + { + assert( nOutputs == Aig_ManRegNum(p) ); + Aig_ManForEachLiSeq( p, pObj, i ) + pCnf->pVarNums[pObj->Id] = Number++; + } + // assign variables to the internal nodes + Aig_ManForEachNode( p, pObj, i ) + pCnf->pVarNums[pObj->Id] = Number++; + // assign variables to the PIs and constant node + Aig_ManForEachPi( p, pObj, i ) + pCnf->pVarNums[pObj->Id] = Number++; + pCnf->pVarNums[Aig_ManConst1(p)->Id] = Number++; + pCnf->nVars = Number; +/* + // print CNF numbers + printf( "SAT numbers of each node:\n" ); + Aig_ManForEachObj( p, pObj, i ) + printf( "%d=%d ", pObj->Id, pCnf->pVarNums[pObj->Id] ); + printf( "\n" ); +*/ + // assign the clauses + pLits = pCnf->pClauses[0]; + pClas = pCnf->pClauses; + Aig_ManForEachNode( p, pObj, i ) + { + OutVar = pCnf->pVarNums[ pObj->Id ]; + pVars[0] = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ]; + pVars[1] = pCnf->pVarNums[ Aig_ObjFanin1(pObj)->Id ]; + + // positive phase + *pClas++ = pLits; + *pLits++ = 2 * OutVar; + *pLits++ = 2 * pVars[0] + !Aig_ObjFaninC0(pObj); + *pLits++ = 2 * pVars[1] + !Aig_ObjFaninC1(pObj); + // negative phase + *pClas++ = pLits; + *pLits++ = 2 * OutVar + 1; + *pLits++ = 2 * pVars[0] + Aig_ObjFaninC0(pObj); + *pClas++ = pLits; + *pLits++ = 2 * OutVar + 1; + *pLits++ = 2 * pVars[1] + Aig_ObjFaninC1(pObj); + } + + // write the constant literal + OutVar = pCnf->pVarNums[ Aig_ManConst1(p)->Id ]; + assert( OutVar <= Aig_ManObjNumMax(p) ); + *pClas++ = pLits; + *pLits++ = 2 * OutVar; + + // write the output literals + Aig_ManForEachPo( p, pObj, i ) + { + OutVar = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ]; + if ( i < Aig_ManPoNum(p) - nOutputs ) + { + *pClas++ = pLits; + *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); + } + else + { + PoVar = pCnf->pVarNums[ pObj->Id ]; + // first clause + *pClas++ = pLits; + *pLits++ = 2 * PoVar; + *pLits++ = 2 * OutVar + !Aig_ObjFaninC0(pObj); + // second clause + *pClas++ = pLits; + *pLits++ = 2 * PoVar + 1; + *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); + } + } + + // verify that the correct number of literals and clauses was written + assert( pLits - pCnf->pClauses[0] == nLiterals ); + assert( pClas - pCnf->pClauses == nClauses ); + return pCnf; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/cnf/cnf_.c b/abc70930/src/aig/cnf/cnf_.c new file mode 100644 index 00000000..7c9ca499 --- /dev/null +++ b/abc70930/src/aig/cnf/cnf_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [cnf_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG-to-CNF conversion.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: cnf_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cnf.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/cnf/module.make b/abc70930/src/aig/cnf/module.make new file mode 100644 index 00000000..dbcaeba4 --- /dev/null +++ b/abc70930/src/aig/cnf/module.make @@ -0,0 +1,8 @@ +SRC += src/aig/cnf/cnfCore.c \ + src/aig/cnf/cnfCut.c \ + src/aig/cnf/cnfData.c \ + src/aig/cnf/cnfMan.c \ + src/aig/cnf/cnfMap.c \ + src/aig/cnf/cnfPost.c \ + src/aig/cnf/cnfUtil.c \ + src/aig/cnf/cnfWrite.c diff --git a/abc70930/src/aig/csw/csw.h b/abc70930/src/aig/csw/csw.h new file mode 100644 index 00000000..1443f4d9 --- /dev/null +++ b/abc70930/src/aig/csw/csw.h @@ -0,0 +1,65 @@ +/**CFile**************************************************************** + + FileName [csw.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Cut sweeping.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - July 11, 2007.] + + Revision [$Id: csw.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CSW_H__ +#define __CSW_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cnfCore.c ========================================================*/ +extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/csw/cswCore.c b/abc70930/src/aig/csw/cswCore.c new file mode 100644 index 00000000..20893058 --- /dev/null +++ b/abc70930/src/aig/csw/cswCore.c @@ -0,0 +1,94 @@ +/**CFile**************************************************************** + + FileName [cswCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Cut sweeping.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - July 11, 2007.] + + Revision [$Id: cswCore.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cswInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose ) +{ + Csw_Man_t * p; + Aig_Man_t * pRes; + Aig_Obj_t * pObj, * pObjNew, * pObjRes; + int i, clk; +clk = clock(); + // start the manager + p = Csw_ManStart( pAig, nCutsMax, nLeafMax, fVerbose ); + // set elementary cuts at the PIs + Aig_ManForEachPi( p->pManRes, pObj, i ) + { + Csw_ObjPrepareCuts( p, pObj, 1 ); + Csw_ObjAddRefs( p, pObj, Aig_ManPi(p->pManAig,i)->nRefs ); + } + // process the nodes + Aig_ManForEachNode( pAig, pObj, i ) + { + // create the new node + pObjNew = Aig_And( p->pManRes, Csw_ObjChild0Equiv(p, pObj), Csw_ObjChild1Equiv(p, pObj) ); + // check if this node can be represented using another node +// pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 ); +// pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) ); + // try recursively if resubsitution is used + do { + pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 ); + pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) ); + pObjNew = pObjRes; + } while ( Csw_ObjCuts(p, Aig_Regular(pObjNew)) == NULL && !Aig_ObjIsConst1(Aig_Regular(pObjNew)) ); + // save the resulting node + Csw_ObjSetEquiv( p, pObj, pObjRes ); + // add to the reference counter + Csw_ObjAddRefs( p, Aig_Regular(pObjRes), pObj->nRefs ); + } + // add the POs + Aig_ManForEachPo( pAig, pObj, i ) + Aig_ObjCreatePo( p->pManRes, Csw_ObjChild0Equiv(p, pObj) ); + // remove dangling nodes + Aig_ManCleanup( p->pManRes ); + // return the resulting manager +p->timeTotal = clock() - clk; +p->timeOther = p->timeTotal - p->timeCuts - p->timeHash; + pRes = p->pManRes; + Csw_ManStop( p ); + return pRes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/csw/cswCut.c b/abc70930/src/aig/csw/cswCut.c new file mode 100644 index 00000000..b3b7152b --- /dev/null +++ b/abc70930/src/aig/csw/cswCut.c @@ -0,0 +1,602 @@ +/**CFile**************************************************************** + + FileName [cswCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Cut sweeping.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - July 11, 2007.] + + Revision [$Id: cswCut.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cswInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Compute the cost of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Csw_CutFindCost( Csw_Man_t * p, Csw_Cut_t * pCut ) +{ + Aig_Obj_t * pLeaf; + int i, Cost = 0; + assert( pCut->nFanins > 0 ); + Csw_CutForEachLeaf( p->pManRes, pCut, pLeaf, i ) + { +// Cost += pLeaf->nRefs; + Cost += Csw_ObjRefs( p, pLeaf ); +// printf( "%d ", pLeaf->nRefs ); + } +//printf( "\n" ); + return Cost * 100 / pCut->nFanins; +} + +/**Function************************************************************* + + Synopsis [Compute the cost of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Csw_CutFindCost2( Csw_Man_t * p, Csw_Cut_t * pCut ) +{ + Aig_Obj_t * pLeaf; + float Cost = 0.0; + int i; + assert( pCut->nFanins > 0 ); + Csw_CutForEachLeaf( p->pManRes, pCut, pLeaf, i ) + Cost += (float)1.0/pLeaf->nRefs; + return 1/Cost; +} + +/**Function************************************************************* + + Synopsis [Returns the next free cut to use.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Csw_Cut_t * Csw_CutFindFree( Csw_Man_t * p, Aig_Obj_t * pObj ) +{ + Csw_Cut_t * pCut, * pCutMax; + int i; + pCutMax = NULL; + Csw_ObjForEachCut( p, pObj, pCut, i ) + { + if ( pCut->nFanins == 0 ) + return pCut; + if ( pCutMax == NULL || pCutMax->Cost < pCut->Cost ) + pCutMax = pCut; + } + assert( pCutMax != NULL ); + pCutMax->nFanins = 0; + return pCutMax; +} + +/**Function************************************************************* + + Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Cut_TruthPhase( Csw_Cut_t * pCut, Csw_Cut_t * pCut1 ) +{ + unsigned uPhase = 0; + int i, k; + for ( i = k = 0; i < pCut->nFanins; i++ ) + { + if ( k == pCut1->nFanins ) + break; + if ( pCut->pFanins[i] < pCut1->pFanins[k] ) + continue; + assert( pCut->pFanins[i] == pCut1->pFanins[k] ); + uPhase |= (1 << i); + k++; + } + return uPhase; +} + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Csw_CutComputeTruth( Csw_Man_t * p, Csw_Cut_t * pCut, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, int fCompl0, int fCompl1 ) +{ + // permute the first table + if ( fCompl0 ) + Kit_TruthNot( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax ); + else + Kit_TruthCopy( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax ); + Kit_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut0), 0 ); + // permute the second table + if ( fCompl1 ) + Kit_TruthNot( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax ); + else + Kit_TruthCopy( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax ); + Kit_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut1), 0 ); + // produce the resulting table + Kit_TruthAnd( Csw_CutTruth(pCut), p->puTemp[2], p->puTemp[3], p->nLeafMax ); +// assert( pCut->nFanins >= Kit_TruthSupportSize( Csw_CutTruth(pCut), p->nLeafMax ) ); + return Csw_CutTruth(pCut); +} + +/**Function************************************************************* + + Synopsis [Performs support minimization for the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Csw_CutSupportMinimize( Csw_Man_t * p, Csw_Cut_t * pCut ) +{ + unsigned * pTruth; + int uSupp, nFansNew, i, k; + // get truth table + pTruth = Csw_CutTruth( pCut ); + // get support + uSupp = Kit_TruthSupport( pTruth, p->nLeafMax ); + // get the new support size + nFansNew = Kit_WordCountOnes( uSupp ); + // check if there are redundant variables + if ( nFansNew == pCut->nFanins ) + return nFansNew; + assert( nFansNew < pCut->nFanins ); + // minimize support + Kit_TruthShrink( p->puTemp[0], pTruth, nFansNew, p->nLeafMax, uSupp, 1 ); + for ( i = k = 0; i < pCut->nFanins; i++ ) + if ( uSupp & (1 << i) ) + pCut->pFanins[k++] = pCut->pFanins[i]; + assert( k == nFansNew ); + pCut->nFanins = nFansNew; +// assert( nFansNew == Kit_TruthSupportSize( pTruth, p->nLeafMax ) ); +//Extra_PrintBinary( stdout, pTruth, (1<nLeafMax) ); printf( "\n" ); + return nFansNew; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Csw_CutCheckDominance( Csw_Cut_t * pDom, Csw_Cut_t * pCut ) +{ + int i, k; + for ( i = 0; i < (int)pDom->nFanins; i++ ) + { + for ( k = 0; k < (int)pCut->nFanins; k++ ) + if ( pDom->pFanins[i] == pCut->pFanins[k] ) + break; + if ( k == (int)pCut->nFanins ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut is contained.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Csw_CutFilter( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCut ) +{ + Csw_Cut_t * pTemp; + int i; + // go through the cuts of the node + Csw_ObjForEachCut( p, pObj, pTemp, i ) + { + if ( pTemp->nFanins < 2 ) + continue; + if ( pTemp == pCut ) + continue; + if ( pTemp->nFanins > pCut->nFanins ) + { + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) + continue; + // check containment seriously + if ( Csw_CutCheckDominance( pCut, pTemp ) ) + { + // remove contained cut + pTemp->nFanins = 0; + } + } + else + { + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) + continue; + // check containment seriously + if ( Csw_CutCheckDominance( pTemp, pCut ) ) + { + // remove the given + pCut->nFanins = 0; + return 1; + } + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Csw_CutMergeOrdered( Csw_Man_t * p, Csw_Cut_t * pC0, Csw_Cut_t * pC1, Csw_Cut_t * pC ) +{ + int i, k, c; + assert( pC0->nFanins >= pC1->nFanins ); + // the case of the largest cut sizes + if ( pC0->nFanins == p->nLeafMax && pC1->nFanins == p->nLeafMax ) + { + for ( i = 0; i < pC0->nFanins; i++ ) + if ( pC0->pFanins[i] != pC1->pFanins[i] ) + return 0; + for ( i = 0; i < pC0->nFanins; i++ ) + pC->pFanins[i] = pC0->pFanins[i]; + pC->nFanins = pC0->nFanins; + return 1; + } + // the case when one of the cuts is the largest + if ( pC0->nFanins == p->nLeafMax ) + { + for ( i = 0; i < pC1->nFanins; i++ ) + { + for ( k = pC0->nFanins - 1; k >= 0; k-- ) + if ( pC0->pFanins[k] == pC1->pFanins[i] ) + break; + if ( k == -1 ) // did not find + return 0; + } + for ( i = 0; i < pC0->nFanins; i++ ) + pC->pFanins[i] = pC0->pFanins[i]; + pC->nFanins = pC0->nFanins; + return 1; + } + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < p->nLeafMax; c++ ) + { + if ( k == pC1->nFanins ) + { + if ( i == pC0->nFanins ) + { + pC->nFanins = c; + return 1; + } + pC->pFanins[c] = pC0->pFanins[i++]; + continue; + } + if ( i == pC0->nFanins ) + { + if ( k == pC1->nFanins ) + { + pC->nFanins = c; + return 1; + } + pC->pFanins[c] = pC1->pFanins[k++]; + continue; + } + if ( pC0->pFanins[i] < pC1->pFanins[k] ) + { + pC->pFanins[c] = pC0->pFanins[i++]; + continue; + } + if ( pC0->pFanins[i] > pC1->pFanins[k] ) + { + pC->pFanins[c] = pC1->pFanins[k++]; + continue; + } + pC->pFanins[c] = pC0->pFanins[i++]; + k++; + } + if ( i < pC0->nFanins || k < pC1->nFanins ) + return 0; + pC->nFanins = c; + return 1; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Csw_CutMerge( Csw_Man_t * p, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, Csw_Cut_t * pCut ) +{ + assert( p->nLeafMax > 0 ); + // merge the nodes + if ( pCut0->nFanins < pCut1->nFanins ) + { + if ( !Csw_CutMergeOrdered( p, pCut1, pCut0, pCut ) ) + return 0; + } + else + { + if ( !Csw_CutMergeOrdered( p, pCut0, pCut1, pCut ) ) + return 0; + } + pCut->uSign = pCut0->uSign | pCut1->uSign; + return 1; +} + +/**Function************************************************************* + + Synopsis [Consider cut with more than 2 fanins having 2 true variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Csw_ObjTwoVarCut( Csw_Man_t * p, Csw_Cut_t * pCut ) +{ + Aig_Obj_t * pRes, * pIn0, * pIn1; + int nVars, uTruth, fCompl = 0; + assert( pCut->nFanins > 2 ); + // minimize support of this cut + nVars = Csw_CutSupportMinimize( p, pCut ); + assert( nVars == 2 ); + // get the fanins + pIn0 = Aig_ManObj( p->pManRes, pCut->pFanins[0] ); + pIn1 = Aig_ManObj( p->pManRes, pCut->pFanins[1] ); + // derive the truth table + uTruth = 0xF & *Csw_CutTruth(pCut); + if ( uTruth == 14 || uTruth == 13 || uTruth == 11 || uTruth == 7 ) + { + uTruth = 0xF & ~uTruth; + fCompl = 1; + } + // compute the result + pRes = NULL; + if ( uTruth == 1 ) // 0001 // 1110 14 + pRes = Aig_And( p->pManRes, Aig_Not(pIn0), Aig_Not(pIn1) ); + if ( uTruth == 2 ) // 0010 // 1101 13 + pRes = Aig_And( p->pManRes, pIn0 , Aig_Not(pIn1) ); + if ( uTruth == 4 ) // 0100 // 1011 11 + pRes = Aig_And( p->pManRes, Aig_Not(pIn0), pIn1 ); + if ( uTruth == 8 ) // 1000 // 0111 7 + pRes = Aig_And( p->pManRes, pIn0 , pIn1 ); + if ( pRes ) + pRes = Aig_NotCond( pRes, fCompl ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Csw_Cut_t * Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ) +{ + Csw_Cut_t * pCutSet, * pCut; + int i; + // create the cutset of the node + pCutSet = (Csw_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts ); + Csw_ObjSetCuts( p, pObj, pCutSet ); + Csw_ObjForEachCut( p, pObj, pCut, i ) + { + pCut->nFanins = 0; + pCut->iNode = pObj->Id; + pCut->nCutSize = p->nCutSize; + pCut->nLeafMax = p->nLeafMax; + } + // add unit cut if needed + if ( fTriv ) + { + pCut = pCutSet; + pCut->Cost = 0; + pCut->iNode = pObj->Id; + pCut->nFanins = 1; + pCut->pFanins[0] = pObj->Id; + pCut->uSign = Aig_ObjCutSign( pObj->Id ); + memset( Csw_CutTruth(pCut), 0xAA, sizeof(unsigned) * p->nTruthWords ); + } + return pCutSet; +} + +/**Function************************************************************* + + Synopsis [Derives cuts for one node and sweeps this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ) +{ + int fUseResub = 1; + Csw_Cut_t * pCut0, * pCut1, * pCut, * pCutSet; + Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj); + Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj); + Aig_Obj_t * pObjNew; + unsigned * pTruth; + int i, k, nVars, nFanins, iVar, clk; + + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) ) + return pObj; + if ( Csw_ObjCuts(p, pObj) ) + return pObj; + // the node is not processed yet + assert( Csw_ObjCuts(p, pObj) == NULL ); + assert( Aig_ObjIsNode(pObj) ); + + // set up the first cut + pCutSet = Csw_ObjPrepareCuts( p, pObj, fTriv ); + + // compute pair-wise cut combinations while checking table + Csw_ObjForEachCut( p, pFanin0, pCut0, i ) + if ( pCut0->nFanins > 0 ) + Csw_ObjForEachCut( p, pFanin1, pCut1, k ) + if ( pCut1->nFanins > 0 ) + { + // make sure K-feasible cut exists + if ( Kit_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->nLeafMax ) + continue; + // get the next cut of this node + pCut = Csw_CutFindFree( p, pObj ); +clk = clock(); + // assemble the new cut + if ( !Csw_CutMerge( p, pCut0, pCut1, pCut ) ) + { + assert( pCut->nFanins == 0 ); + continue; + } + // check containment + if ( Csw_CutFilter( p, pObj, pCut ) ) + { + assert( pCut->nFanins == 0 ); + continue; + } + // create its truth table + pTruth = Csw_CutComputeTruth( p, pCut, pCut0, pCut1, Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); + // support minimize the truth table + nFanins = pCut->nFanins; +// nVars = Csw_CutSupportMinimize( p, pCut ); // leads to quality degradation + nVars = Kit_TruthSupportSize( pTruth, p->nLeafMax ); +p->timeCuts += clock() - clk; + + // check for trivial truth tables + if ( nVars == 0 ) + { + p->nNodesTriv0++; + return Aig_NotCond( Aig_ManConst1(p->pManRes), !(pTruth[0] & 1) ); + } + if ( nVars == 1 ) + { + p->nNodesTriv1++; + iVar = Kit_WordFindFirstBit( Kit_TruthSupport(pTruth, p->nLeafMax) ); + assert( iVar < pCut->nFanins ); + return Aig_NotCond( Aig_ManObj(p->pManRes, pCut->pFanins[iVar]), (pTruth[0] & 1) ); + } + if ( nVars == 2 && nFanins > 2 && fUseResub ) + { + if ( pObjNew = Csw_ObjTwoVarCut( p, pCut ) ) + { + p->nNodesTriv2++; + return pObjNew; + } + } + + // check if an equivalent node with the same cut exists +clk = clock(); + pObjNew = pCut->nFanins > 2 ? Csw_TableCutLookup( p, pCut ) : NULL; +p->timeHash += clock() - clk; + if ( pObjNew ) + { + p->nNodesCuts++; + return pObjNew; + } + + // assign the cost + pCut->Cost = Csw_CutFindCost( p, pCut ); + assert( pCut->nFanins > 0 ); + assert( pCut->Cost > 0 ); + } + p->nNodesTried++; + + // load the resulting cuts into the table +clk = clock(); + Csw_ObjForEachCut( p, pObj, pCut, i ) + { + if ( pCut->nFanins > 2 ) + { + assert( pCut->Cost > 0 ); + Csw_TableCutInsert( p, pCut ); + } + } +p->timeHash += clock() - clk; + + // return the node if could not replace it + return pObj; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/csw/cswInt.h b/abc70930/src/aig/csw/cswInt.h new file mode 100644 index 00000000..37efe9b4 --- /dev/null +++ b/abc70930/src/aig/csw/cswInt.h @@ -0,0 +1,157 @@ +/**CFile**************************************************************** + + FileName [cswInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Cut sweeping.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - July 11, 2007.] + + Revision [$Id: cswInt.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CSW_INT_H__ +#define __CSW_INT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "aig.h" +#include "dar.h" +#include "kit.h" +#include "csw.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Csw_Man_t_ Csw_Man_t; +typedef struct Csw_Cut_t_ Csw_Cut_t; + +// the cut used to represent node in the AIG +struct Csw_Cut_t_ +{ + Csw_Cut_t * pNext; // the next cut in the table + int Cost; // the cost of the cut +// float Cost; // the cost of the cut + unsigned uSign; // cut signature + int iNode; // the node, for which it is the cut + short nCutSize; // the number of bytes in the cut + char nLeafMax; // the maximum number of fanins + char nFanins; // the current number of fanins + int pFanins[0]; // the fanins (followed by the truth table) +}; + +// the CNF computation manager +struct Csw_Man_t_ +{ + // AIG manager + Aig_Man_t * pManAig; // the input AIG manager + Aig_Man_t * pManRes; // the output AIG manager + Aig_Obj_t ** pEquiv; // the equivalent nodes in the resulting manager + Csw_Cut_t ** pCuts; // the cuts for each node in the output manager + int * pnRefs; // the number of references of each new node + // hash table for cuts + Csw_Cut_t ** pTable; // the table composed of cuts + int nTableSize; // the size of hash table + // parameters + int nCutsMax; // the max number of cuts at the node + int nLeafMax; // the max number of leaves of a cut + int fVerbose; // enables verbose output + // internal variables + int nCutSize; // the number of bytes needed to store one cut + int nTruthWords; // the number of truth table words + Aig_MmFixed_t * pMemCuts; // memory manager for cuts + unsigned * puTemp[4]; // used for the truth table computation + // statistics + int nNodesTriv0; // the number of trivial nodes + int nNodesTriv1; // the number of trivial nodes + int nNodesTriv2; // the number of trivial nodes + int nNodesCuts; // the number of rewritten nodes + int nNodesTried; // the number of nodes tried + int timeCuts; // time to compute the cut and its truth table + int timeHash; // time for hashing cuts + int timeOther; // other time + int timeTotal; // total time +}; + +static inline int Csw_CutLeaveNum( Csw_Cut_t * pCut ) { return pCut->nFanins; } +static inline int * Csw_CutLeaves( Csw_Cut_t * pCut ) { return pCut->pFanins; } +static inline unsigned * Csw_CutTruth( Csw_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nLeafMax); } +static inline Csw_Cut_t * Csw_CutNext( Csw_Cut_t * pCut ) { return (Csw_Cut_t *)(((char *)pCut) + pCut->nCutSize); } + +static inline int Csw_ObjRefs( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pnRefs[pObj->Id]; } +static inline void Csw_ObjAddRefs( Csw_Man_t * p, Aig_Obj_t * pObj, int nRefs ) { p->pnRefs[pObj->Id] += nRefs; } + +static inline Csw_Cut_t * Csw_ObjCuts( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; } +static inline void Csw_ObjSetCuts( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCuts ) { p->pCuts[pObj->Id] = pCuts; } + +static inline Aig_Obj_t * Csw_ObjEquiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquiv[pObj->Id]; } +static inline void Csw_ObjSetEquiv( Csw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pEquiv ) { p->pEquiv[pObj->Id] = pEquiv; } + +static inline Aig_Obj_t * Csw_ObjChild0Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Csw_ObjChild1Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)) : NULL; } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over cuts of the node +#define Csw_ObjForEachCut( p, pObj, pCut, i ) \ + for ( i = 0, pCut = Csw_ObjCuts(p, pObj); i < p->nCutsMax; i++, pCut = Csw_CutNext(pCut) ) +// iterator over leaves of the cut +#define Csw_CutForEachLeaf( p, pCut, pLeaf, i ) \ + for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cnfCut.c ========================================================*/ +extern Csw_Cut_t * Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ); +extern Aig_Obj_t * Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ); +/*=== cnfMan.c ========================================================*/ +extern Csw_Man_t * Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose ); +extern void Csw_ManStop( Csw_Man_t * p ); +/*=== cnfTable.c ========================================================*/ +extern int Csw_TableCountCuts( Csw_Man_t * p ); +extern void Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut ); +extern Aig_Obj_t * Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/csw/cswMan.c b/abc70930/src/aig/csw/cswMan.c new file mode 100644 index 00000000..c3061dee --- /dev/null +++ b/abc70930/src/aig/csw/cswMan.c @@ -0,0 +1,125 @@ +/**CFile**************************************************************** + + FileName [cswMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Cut sweeping.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - July 11, 2007.] + + Revision [$Id: cswMan.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cswInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the cut sweeping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Csw_Man_t * Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose ) +{ + Csw_Man_t * p; + Aig_Obj_t * pObj; + int i; + assert( nCutsMax >= 2 ); + assert( nLeafMax <= 16 ); + // allocate the fraiging manager + p = ALLOC( Csw_Man_t, 1 ); + memset( p, 0, sizeof(Csw_Man_t) ); + p->nCutsMax = nCutsMax; + p->nLeafMax = nLeafMax; + p->fVerbose = fVerbose; + p->pManAig = pMan; + // create the new manager + p->pManRes = Aig_ManStartFrom( pMan ); + assert( Aig_ManPiNum(p->pManAig) == Aig_ManPiNum(p->pManRes) ); + // allocate room for cuts and equivalent nodes + p->pnRefs = ALLOC( int, Aig_ManObjNumMax(pMan) ); + p->pEquiv = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pMan) ); + p->pCuts = ALLOC( Csw_Cut_t *, Aig_ManObjNumMax(pMan) ); + memset( p->pCuts, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pMan) ); + memset( p->pnRefs, 0, sizeof(int) * Aig_ManObjNumMax(pMan) ); + // allocate memory manager + p->nTruthWords = Aig_TruthWordNum(nLeafMax); + p->nCutSize = sizeof(Csw_Cut_t) + sizeof(int) * nLeafMax + sizeof(unsigned) * p->nTruthWords; + p->pMemCuts = Aig_MmFixedStart( p->nCutSize * p->nCutsMax, 512 ); + // allocate hash table for cuts + p->nTableSize = Aig_PrimeCudd( Aig_ManNodeNum(pMan) * p->nCutsMax / 2 ); + p->pTable = ALLOC( Csw_Cut_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); + // set the pointers to the available fraig nodes + Csw_ObjSetEquiv( p, Aig_ManConst1(p->pManAig), Aig_ManConst1(p->pManRes) ); + Aig_ManForEachPi( p->pManAig, pObj, i ) + Csw_ObjSetEquiv( p, pObj, Aig_ManPi(p->pManRes, i) ); + // room for temporary truth tables + p->puTemp[0] = ALLOC( unsigned, 4 * p->nTruthWords ); + p->puTemp[1] = p->puTemp[0] + p->nTruthWords; + p->puTemp[2] = p->puTemp[1] + p->nTruthWords; + p->puTemp[3] = p->puTemp[2] + p->nTruthWords; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Csw_ManStop( Csw_Man_t * p ) +{ + if ( p->fVerbose ) + { + int nNodesBeg = Aig_ManNodeNum(p->pManAig); + int nNodesEnd = Aig_ManNodeNum(p->pManRes); + printf( "Beg = %7d. End = %7d. (%6.2f %%) Try = %7d. Cuts = %8d.\n", + nNodesBeg, nNodesEnd, 100.0*(nNodesBeg-nNodesEnd)/nNodesBeg, + p->nNodesTried, Csw_TableCountCuts( p ) ); + printf( "Triv0 = %6d. Triv1 = %6d. Triv2 = %6d. Cut-replace = %6d.\n", + p->nNodesTriv0, p->nNodesTriv1, p->nNodesTriv2, p->nNodesCuts ); + PRTP( "Cuts ", p->timeCuts, p->timeTotal ); + PRTP( "Hashing ", p->timeHash, p->timeTotal ); + PRTP( "Other ", p->timeOther, p->timeTotal ); + PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + } + free( p->puTemp[0] ); + Aig_MmFixedStop( p->pMemCuts, 0 ); + free( p->pnRefs ); + free( p->pEquiv ); + free( p->pCuts ); + free( p->pTable ); + free( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/csw/cswTable.c b/abc70930/src/aig/csw/cswTable.c new file mode 100644 index 00000000..87e36ae1 --- /dev/null +++ b/abc70930/src/aig/csw/cswTable.c @@ -0,0 +1,161 @@ +/**CFile**************************************************************** + + FileName [cswTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Cut sweeping.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - July 11, 2007.] + + Revision [$Id: cswTable.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cswInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes hash value of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Csw_CutHash( Csw_Cut_t * pCut ) +{ + static int s_FPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + unsigned uHash; + int i; + assert( pCut->nFanins <= 16 ); + uHash = 0; + for ( i = 0; i < pCut->nFanins; i++ ) + uHash ^= pCut->pFanins[i] * s_FPrimes[i]; + return uHash; +} + +/**Function************************************************************* + + Synopsis [Returns the total number of cuts in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Csw_TableCountCuts( Csw_Man_t * p ) +{ + Csw_Cut_t * pEnt; + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + for ( pEnt = p->pTable[i]; pEnt; pEnt = pEnt->pNext ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Adds the cut to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut ) +{ + int iEntry = Csw_CutHash(pCut) % p->nTableSize; + pCut->pNext = p->pTable[iEntry]; + p->pTable[iEntry] = pCut; +} + +/**Function************************************************************* + + Synopsis [Returns an equivalent node if it exists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut ) +{ + Aig_Obj_t * pRes = NULL; + Csw_Cut_t * pEnt; + unsigned * pTruthNew, * pTruthOld; + int iEntry = Csw_CutHash(pCut) % p->nTableSize; + for ( pEnt = p->pTable[iEntry]; pEnt; pEnt = pEnt->pNext ) + { + if ( pEnt->nFanins != pCut->nFanins ) + continue; + if ( pEnt->uSign != pCut->uSign ) + continue; + if ( memcmp( pEnt->pFanins, pCut->pFanins, sizeof(int) * pCut->nFanins ) ) + continue; + pTruthOld = Csw_CutTruth(pEnt); + pTruthNew = Csw_CutTruth(pCut); + if ( (pTruthOld[0] & 1) == (pTruthNew[0] & 1) ) + { + if ( Kit_TruthIsEqual( pTruthOld, pTruthNew, pCut->nFanins ) ) + { + pRes = Aig_ManObj( p->pManRes, pEnt->iNode ); + assert( pRes->fPhase == Aig_ManObj( p->pManRes, pCut->iNode )->fPhase ); + break; + } + } + else + { + if ( Kit_TruthIsOpposite( pTruthOld, pTruthNew, pCut->nFanins ) ) + { + pRes = Aig_Not( Aig_ManObj( p->pManRes, pEnt->iNode ) ); + assert( Aig_Regular(pRes)->fPhase != Aig_ManObj( p->pManRes, pCut->iNode )->fPhase ); + break; + } + } + } + return pRes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/csw/csw_.c b/abc70930/src/aig/csw/csw_.c new file mode 100644 index 00000000..1c59f152 --- /dev/null +++ b/abc70930/src/aig/csw/csw_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [csw_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Cut sweeping.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - July 11, 2007.] + + Revision [$Id: csw_.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cswInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/csw/module.make b/abc70930/src/aig/csw/module.make new file mode 100644 index 00000000..8fdb7bef --- /dev/null +++ b/abc70930/src/aig/csw/module.make @@ -0,0 +1,4 @@ +SRC += src/aig/csw/cswCore.c \ + src/aig/csw/cswCut.c \ + src/aig/csw/cswMan.c \ + src/aig/csw/cswTable.c diff --git a/abc70930/src/aig/dar/dar.h b/abc70930/src/aig/dar/dar.h new file mode 100644 index 00000000..2a4fcaf3 --- /dev/null +++ b/abc70930/src/aig/dar/dar.h @@ -0,0 +1,106 @@ +/**CFile**************************************************************** + + FileName [dar.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: dar.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __DAR_H__ +#define __DAR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Dar_RwrPar_t_ Dar_RwrPar_t; +typedef struct Dar_RefPar_t_ Dar_RefPar_t; + +struct Dar_RwrPar_t_ +{ + int nCutsMax; // the maximum number of cuts to try + int nSubgMax; // the maximum number of subgraphs to try + int fFanout; // support fanout representation + int fUpdateLevel; // update level + int fUseZeros; // performs zero-cost replacement + int fVerbose; // enables verbose output + int fVeryVerbose; // enables very verbose output +}; + +struct Dar_RefPar_t_ +{ + int nMffcMin; // the min MFFC size for which refactoring is used + int nLeafMax; // the max number of leaves of a cut + int nCutsMax; // the max number of cuts to consider + int fExtend; // extends the cut below MFFC + int fUpdateLevel; // updates the level after each move + int fUseZeros; // perform zero-cost replacements + int fVerbose; // verbosity level + int fVeryVerbose; // enables very verbose output +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== darLib.c ========================================================*/ +extern void Dar_LibStart(); +extern void Dar_LibStop(); +/*=== darBalance.c ========================================================*/ +extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel ); +/*=== darCore.c ========================================================*/ +extern void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars ); +extern int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ); +extern Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax ); +/*=== darRefact.c ========================================================*/ +extern void Dar_ManDefaultRefParams( Dar_RefPar_t * pPars ); +extern int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars ); +/*=== darScript.c ========================================================*/ +extern Aig_Man_t * Dar_ManRewriteDefault( Aig_Man_t * pAig ); +extern Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose ); +extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ); +extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ); +extern Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/dar/darBalance.c b/abc70930/src/aig/dar/darBalance.c new file mode 100644 index 00000000..cc1eb668 --- /dev/null +++ b/abc70930/src/aig/dar/darBalance.c @@ -0,0 +1,398 @@ +/**CFile**************************************************************** + + FileName [darBalance.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [Algebraic AIG balancing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: darBalance.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "darInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Aig_Obj_t * Dar_Balance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); +static Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); +static int Dar_BalanceFindLeft( Vec_Ptr_t * vSuper ); +static void Dar_BalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); +static void Dar_BalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj ); +static Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs algebraic balancing of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pDriver, * pObjNew; + Vec_Vec_t * vStore; + int i; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Aig_UtilStrsav( p->pName ); + pNew->nRegs = p->nRegs; + pNew->nAsserts = p->nAsserts; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // map the PI nodes + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreatePi(pNew); + // balance the AIG + vStore = Vec_VecAlloc( 50 ); + Aig_ManForEachPo( p, pObj, i ) + { + pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel ); + pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) ); + Aig_ObjCreatePo( pNew, pObjNew ); + } + Vec_VecFree( vStore ); + // remove dangling nodes + if ( (i = Aig_ManCleanup( pNew )) ) + printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); + // check the resulting AIG + if ( !Aig_ManCheck(pNew) ) + printf( "Dar_ManBalance(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns the new node constructed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Dar_Balance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) +{ + Aig_Obj_t * pObjNew; + Vec_Ptr_t * vSuper; + int i; + assert( !Aig_IsComplement(pObjOld) ); + assert( !Aig_ObjIsBuf(pObjOld) ); + // return if the result is known + if ( pObjOld->pData ) + return pObjOld->pData; + assert( Aig_ObjIsNode(pObjOld) ); + // get the implication supergate + vSuper = Dar_BalanceCone( pObjOld, vStore, Level ); + // check if supergate contains two nodes in the opposite polarity + if ( vSuper->nSize == 0 ) + return pObjOld->pData = Aig_ManConst0(pNew); + if ( Vec_PtrSize(vSuper) < 2 ) + printf( "BUG!\n" ); + // for each old node, derive the new well-balanced node + for ( i = 0; i < Vec_PtrSize(vSuper); i++ ) + { + pObjNew = Dar_Balance_rec( pNew, Aig_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); + vSuper->pArray[i] = Aig_NotCond( pObjNew, Aig_IsComplement(vSuper->pArray[i]) ); + } + // build the supergate + pObjNew = Dar_BalanceBuildSuper( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel ); + // make sure the balanced node is not assigned +// assert( pObjOld->Level >= Aig_Regular(pObjNew)->Level ); + assert( pObjOld->pData == NULL ); + return pObjOld->pData = pObjNew; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_BalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Aig_Regular(pObj)->fMarkB ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pObj ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Aig_Not(pObj) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1) ) + { + Vec_PtrPush( vSuper, pObj ); + Aig_Regular(pObj)->fMarkB = 1; + return 0; + } + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsNode(pObj) ); + // go through the branches + RetValue1 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper ); + RetValue2 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) +{ + Vec_Ptr_t * vNodes; + int RetValue, i; + assert( !Aig_IsComplement(pObj) ); + // extend the storage + if ( Vec_VecSize( vStore ) <= Level ) + Vec_VecPush( vStore, Level, 0 ); + // get the temporary array of nodes + vNodes = Vec_VecEntry( vStore, Level ); + Vec_PtrClear( vNodes ); + // collect the nodes in the implication supergate + RetValue = Dar_BalanceCone_rec( pObj, pObj, vNodes ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + Aig_Regular(pObj)->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeCompareLevelsDecrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) +{ + int Diff = Aig_ObjLevel(Aig_Regular(*pp1)) - Aig_ObjLevel(Aig_Regular(*pp2)); + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Builds implication supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel ) +{ + Aig_Obj_t * pObj1, * pObj2; + int LeftBound; + assert( vSuper->nSize > 1 ); + // sort the new nodes by level in the decreasing order + Vec_PtrSort( vSuper, Aig_NodeCompareLevelsDecrease ); + // balance the nodes + while ( vSuper->nSize > 1 ) + { + // find the left bound on the node to be paired + LeftBound = (!fUpdateLevel)? 0 : Dar_BalanceFindLeft( vSuper ); + // find the node that can be shared (if no such node, randomize choice) + Dar_BalancePermute( p, vSuper, LeftBound, Type == AIG_OBJ_EXOR ); + // pull out the last two nodes + pObj1 = Vec_PtrPop(vSuper); + pObj2 = Vec_PtrPop(vSuper); + Dar_BalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type) ); + } + return Vec_PtrEntry(vSuper, 0); +} + +/**Function************************************************************* + + Synopsis [Finds the left bound on the next candidate to be paired.] + + Description [The nodes in the array are in the decreasing order of levels. + The last node in the array has the smallest level. By default it would be paired + with the next node on the left. However, it may be possible to pair it with some + other node on the left, in such a way that the new node is shared. This procedure + finds the index of the left-most node, which can be paired with the last node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_BalanceFindLeft( Vec_Ptr_t * vSuper ) +{ + Aig_Obj_t * pObjRight, * pObjLeft; + int Current; + // if two or less nodes, pair with the first + if ( Vec_PtrSize(vSuper) < 3 ) + return 0; + // set the pointer to the one before the last + Current = Vec_PtrSize(vSuper) - 2; + pObjRight = Vec_PtrEntry( vSuper, Current ); + // go through the nodes to the left of this one + for ( Current--; Current >= 0; Current-- ) + { + // get the next node on the left + pObjLeft = Vec_PtrEntry( vSuper, Current ); + // if the level of this node is different, quit the loop + if ( Aig_ObjLevel(Aig_Regular(pObjLeft)) != Aig_ObjLevel(Aig_Regular(pObjRight)) ) + break; + } + Current++; + // get the node, for which the equality holds + pObjLeft = Vec_PtrEntry( vSuper, Current ); + assert( Aig_ObjLevel(Aig_Regular(pObjLeft)) == Aig_ObjLevel(Aig_Regular(pObjRight)) ); + return Current; +} + +/**Function************************************************************* + + Synopsis [Moves closer to the end the node that is best for sharing.] + + Description [If there is no node with sharing, randomly chooses one of + the legal nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_BalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) +{ + Aig_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; + int RightBound, i; + // get the right bound + RightBound = Vec_PtrSize(vSuper) - 2; + assert( LeftBound <= RightBound ); + if ( LeftBound == RightBound ) + return; + // get the two last nodes + pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); + pObj2 = Vec_PtrEntry( vSuper, RightBound ); + if ( Aig_Regular(pObj1) == p->pConst1 || Aig_Regular(pObj2) == p->pConst1 ) + return; + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + pObj3 = Vec_PtrEntry( vSuper, i ); + if ( Aig_Regular(pObj3) == p->pConst1 ) + { + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + pGhost = Aig_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_OBJ_EXOR : AIG_OBJ_AND ); + if ( Aig_TableLookup( p, pGhost ) ) + { + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + } +/* + // we did not find the node to share, randomize choice + { + int Choice = rand() % (RightBound - LeftBound + 1); + pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_BalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObj1, * pObj2; + int i; + if ( Vec_PtrPushUnique(vStore, pObj) ) + return; + // find the p of the node + for ( i = vStore->nSize-1; i > 0; i-- ) + { + pObj1 = vStore->pArray[i ]; + pObj2 = vStore->pArray[i-1]; + if ( Aig_ObjLevel(Aig_Regular(pObj1)) <= Aig_ObjLevel(Aig_Regular(pObj2)) ) + break; + vStore->pArray[i ] = pObj2; + vStore->pArray[i-1] = pObj1; + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/dar/darCore.c b/abc70930/src/aig/dar/darCore.c new file mode 100644 index 00000000..f4041dd1 --- /dev/null +++ b/abc70930/src/aig/dar/darCore.c @@ -0,0 +1,244 @@ +/**CFile**************************************************************** + + FileName [darCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [Core of the rewriting package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: darCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "darInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the structure with default assignment of parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars ) +{ + memset( pPars, 0, sizeof(Dar_RwrPar_t) ); + pPars->nCutsMax = 8; // 8 + pPars->nSubgMax = 5; // 5 is a "magic number" + pPars->fFanout = 1; + pPars->fUpdateLevel = 0; + pPars->fUseZeros = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) +{ + Dar_Man_t * p; +// Bar_Progress_t * pProgress; + Dar_Cut_t * pCut; + Aig_Obj_t * pObj, * pObjNew; + int i, k, nNodesOld, nNodeBefore, nNodeAfter, Required; + int clk = 0, clkStart; + // prepare the library + Dar_LibPrepare( pPars->nSubgMax ); + // create rewriting manager + p = Dar_ManStart( pAig, pPars ); + // remove dangling nodes + Aig_ManCleanup( pAig ); + // if updating levels is requested, start fanout and timing + if ( p->pPars->fFanout ) + Aig_ManFanoutStart( pAig ); + if ( p->pPars->fUpdateLevel ) + Aig_ManStartReverseLevels( pAig, 0 ); + // set elementary cuts for the PIs + Dar_ManCutsStart( p ); + // resynthesize each node once + clkStart = clock(); + p->nNodesInit = Aig_ManNodeNum(pAig); + nNodesOld = Vec_PtrSize( pAig->vObjs ); + +// pProgress = Bar_ProgressStart( stdout, nNodesOld ); + Aig_ManForEachObj( pAig, pObj, i ) +// pProgress = Bar_ProgressStart( stdout, 100 ); +// Aig_ManOrderStart( pAig ); +// Aig_ManForEachNodeInOrder( pAig, pObj ) + { +// Bar_ProgressUpdate( pProgress, 100*pAig->nAndPrev/pAig->nAndTotal, NULL ); + +// Bar_ProgressUpdate( pProgress, i, NULL ); + if ( !Aig_ObjIsNode(pObj) ) + continue; + if ( i > nNodesOld ) + break; + + // consider freeing the cuts +// if ( (i & 0xFFF) == 0 && Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) > 100 ) +// Dar_ManCutsStart( p ); + + // compute cuts for the node + p->nNodesTried++; +clk = clock(); + Dar_ObjComputeCuts_rec( p, pObj ); +p->timeCuts += clock() - clk; + + // check if there is a trivial cut + Dar_ObjForEachCut( pObj, pCut, k ) + if ( pCut->nLeaves == 0 || (pCut->nLeaves == 1 && pCut->pLeaves[0] != pObj->Id && Aig_ManObj(p->pAig, pCut->pLeaves[0])) ) + break; + if ( k < (int)pObj->nCuts ) + { + assert( pCut->nLeaves < 2 ); + if ( pCut->nLeaves == 0 ) // replace by constant + { + assert( pCut->uTruth == 0 || pCut->uTruth == 0xFFFF ); + pObjNew = Aig_NotCond( Aig_ManConst1(p->pAig), pCut->uTruth==0 ); + } + else + { + assert( pCut->uTruth == 0xAAAA || pCut->uTruth == 0x5555 ); + pObjNew = Aig_NotCond( Aig_ManObj(p->pAig, pCut->pLeaves[0]), pCut->uTruth==0x5555 ); + } + // remove the old cuts + Dar_ObjSetCuts( pObj, NULL ); + // replace the node + Aig_ObjReplace( pAig, pObj, pObjNew, 1, p->pPars->fUpdateLevel ); + continue; + } + + // evaluate the cuts + p->GainBest = -1; + Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : AIG_INFINITY; + Dar_ObjForEachCut( pObj, pCut, k ) + Dar_LibEval( p, pObj, pCut, Required ); + // check the best gain + if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) + { +// Aig_ObjOrderAdvance( pAig ); + continue; + } + // remove the old cuts + Dar_ObjSetCuts( pObj, NULL ); + // if we end up here, a rewriting step is accepted + nNodeBefore = Aig_ManNodeNum( pAig ); + pObjNew = Dar_LibBuildBest( p ); // pObjNew can be complemented! + pObjNew = Aig_NotCond( pObjNew, Aig_ObjPhaseReal(pObjNew) ^ pObj->fPhase ); + assert( (int)Aig_Regular(pObjNew)->Level <= Required ); + // replace the node + Aig_ObjReplace( pAig, pObj, pObjNew, 1, p->pPars->fUpdateLevel ); + // compare the gains + nNodeAfter = Aig_ManNodeNum( pAig ); + assert( p->GainBest <= nNodeBefore - nNodeAfter ); + // count gains of this class + p->ClassGains[p->ClassBest] += nNodeBefore - nNodeAfter; + } +// Aig_ManOrderStop( pAig ); + +p->timeTotal = clock() - clkStart; +p->timeOther = p->timeTotal - p->timeCuts - p->timeEval; + +// Bar_ProgressStop( pProgress ); + p->nCutMemUsed = Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20); + Dar_ManCutsFree( p ); + // put the nodes into the DFS order and reassign their IDs +// Aig_NtkReassignIds( p ); + // fix the levels +// Aig_ManVerifyLevel( pAig ); + if ( p->pPars->fFanout ) + Aig_ManFanoutStop( pAig ); + if ( p->pPars->fUpdateLevel ) + { +// Aig_ManVerifyReverseLevel( pAig ); + Aig_ManStopReverseLevels( pAig ); + } + // stop the rewriting manager + Dar_ManStop( p ); + Aig_ManCheckPhase( pAig ); + // check + if ( !Aig_ManCheck( pAig ) ) + { + printf( "Aig_ManRewrite: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax ) +{ + Dar_Man_t * p; + Dar_RwrPar_t Pars, * pPars = &Pars; + Aig_Obj_t * pObj; + Aig_MmFixed_t * pMemCuts; + int i, nNodes; + // remove dangling nodes + if ( (nNodes = Aig_ManCleanup( pAig )) ) + { +// printf( "Removing %d nodes.\n", nNodes ); + } + // create default parameters + Dar_ManDefaultRwrParams( pPars ); + pPars->nCutsMax = nCutsMax; + // create rewriting manager + p = Dar_ManStart( pAig, pPars ); + // set elementary cuts for the PIs + Dar_ManCutsStart( p ); + // compute cuts for each nodes in the topological order + Aig_ManForEachNode( pAig, pObj, i ) + Dar_ObjComputeCuts( p, pObj ); + // free the cuts + pMemCuts = p->pMemCuts; + p->pMemCuts = NULL; +// Dar_ManCutsFree( p ); + // stop the rewriting manager + Dar_ManStop( p ); + return pMemCuts; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/dar/darCut.c b/abc70930/src/aig/dar/darCut.c new file mode 100644 index 00000000..08bd77a9 --- /dev/null +++ b/abc70930/src/aig/dar/darCut.c @@ -0,0 +1,698 @@ +/**CFile**************************************************************** + + FileName [darCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [Computation of 4-input cuts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: darCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "darInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the number of 1s in the machine word.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dar_WordCountOnes( unsigned uWord ) +{ + uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); + uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); + uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); + uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); + return (uWord & 0x0000FFFF) + (uWord>>16); +} + +/**Function************************************************************* + + Synopsis [Compute the cost of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dar_CutFindValue( Dar_Man_t * p, Dar_Cut_t * pCut ) +{ + Aig_Obj_t * pLeaf; + int i, Value, nOnes; + assert( pCut->fUsed ); + Value = 0; + nOnes = 0; + Dar_CutForEachLeaf( p->pAig, pCut, pLeaf, i ) + { + if ( pLeaf == NULL ) + return 0; + assert( pLeaf != NULL ); + Value += pLeaf->nRefs; + nOnes += (pLeaf->nRefs == 1); + } + if ( pCut->nLeaves < 2 ) + return 1001; +// Value = Value * 100 / pCut->nLeaves; + if ( Value > 1000 ) + Value = 1000; + if ( nOnes > 3 ) + Value = 5 - nOnes; + return Value; +} + +/**Function************************************************************* + + Synopsis [Returns the next free cut to use.] + + Description [Uses the cut with the smallest value.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dar_Cut_t * Dar_CutFindFree( Dar_Man_t * p, Aig_Obj_t * pObj ) +{ + Dar_Cut_t * pCut, * pCutMax; + int i; + pCutMax = NULL; + Dar_ObjForEachCutAll( pObj, pCut, i ) + { + if ( pCut->fUsed == 0 ) + return pCut; + if ( pCut->nLeaves < 3 ) + continue; + if ( pCutMax == NULL || pCutMax->Value > pCut->Value ) + pCutMax = pCut; + } + if ( pCutMax == NULL ) + { + Dar_ObjForEachCutAll( pObj, pCut, i ) + { + if ( pCut->nLeaves < 2 ) + continue; + if ( pCutMax == NULL || pCutMax->Value > pCut->Value ) + pCutMax = pCut; + } + } + if ( pCutMax == NULL ) + { + Dar_ObjForEachCutAll( pObj, pCut, i ) + { + if ( pCutMax == NULL || pCutMax->Value > pCut->Value ) + pCutMax = pCut; + } + } + assert( pCutMax != NULL ); + pCutMax->fUsed = 0; + return pCutMax; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dar_CutCheckDominance( Dar_Cut_t * pDom, Dar_Cut_t * pCut ) +{ + int i, k; + assert( pDom->fUsed && pCut->fUsed ); + for ( i = 0; i < (int)pDom->nLeaves; i++ ) + { + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) + break; + if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut is contained.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dar_CutFilter( Aig_Obj_t * pObj, Dar_Cut_t * pCut ) +{ + Dar_Cut_t * pTemp; + int i; + assert( pCut->fUsed ); + // go through the cuts of the node + Dar_ObjForEachCut( pObj, pTemp, i ) + { + if ( pTemp == pCut ) + continue; + if ( pTemp->nLeaves > pCut->nLeaves ) + { + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) + continue; + // check containment seriously + if ( Dar_CutCheckDominance( pCut, pTemp ) ) + { + // remove contained cut + pTemp->fUsed = 0; + } + } + else + { + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) + continue; + // check containment seriously + if ( Dar_CutCheckDominance( pTemp, pCut ) ) + { + // remove the given cut + pCut->fUsed = 0; + return 1; + } + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dar_CutMergeOrdered( Dar_Cut_t * pC, Dar_Cut_t * pC0, Dar_Cut_t * pC1 ) +{ + int i, k, c; + assert( pC0->nLeaves >= pC1->nLeaves ); + + // the case of the largest cut sizes + if ( pC0->nLeaves == 4 && pC1->nLeaves == 4 ) + { + if ( pC0->uSign != pC1->uSign ) + return 0; + for ( i = 0; i < (int)pC0->nLeaves; i++ ) + if ( pC0->pLeaves[i] != pC1->pLeaves[i] ) + return 0; + for ( i = 0; i < (int)pC0->nLeaves; i++ ) + pC->pLeaves[i] = pC0->pLeaves[i]; + pC->nLeaves = pC0->nLeaves; + return 1; + } + + // the case when one of the cuts is the largest + if ( pC0->nLeaves == 4 ) + { + if ( (pC0->uSign & pC1->uSign) != pC1->uSign ) + return 0; + for ( i = 0; i < (int)pC1->nLeaves; i++ ) + { + for ( k = (int)pC0->nLeaves - 1; k >= 0; k-- ) + if ( pC0->pLeaves[k] == pC1->pLeaves[i] ) + break; + if ( k == -1 ) // did not find + return 0; + } + for ( i = 0; i < (int)pC0->nLeaves; i++ ) + pC->pLeaves[i] = pC0->pLeaves[i]; + pC->nLeaves = pC0->nLeaves; + return 1; + } + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < 4; c++ ) + { + if ( k == (int)pC1->nLeaves ) + { + if ( i == (int)pC0->nLeaves ) + { + pC->nLeaves = c; + return 1; + } + pC->pLeaves[c] = pC0->pLeaves[i++]; + continue; + } + if ( i == (int)pC0->nLeaves ) + { + if ( k == (int)pC1->nLeaves ) + { + pC->nLeaves = c; + return 1; + } + pC->pLeaves[c] = pC1->pLeaves[k++]; + continue; + } + if ( pC0->pLeaves[i] < pC1->pLeaves[k] ) + { + pC->pLeaves[c] = pC0->pLeaves[i++]; + continue; + } + if ( pC0->pLeaves[i] > pC1->pLeaves[k] ) + { + pC->pLeaves[c] = pC1->pLeaves[k++]; + continue; + } + pC->pLeaves[c] = pC0->pLeaves[i++]; + k++; + } + if ( i < (int)pC0->nLeaves || k < (int)pC1->nLeaves ) + return 0; + pC->nLeaves = c; + return 1; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dar_CutMerge( Dar_Cut_t * pCut, Dar_Cut_t * pCut0, Dar_Cut_t * pCut1 ) +{ + assert( !pCut->fUsed ); + // merge the nodes + if ( pCut0->nLeaves <= pCut1->nLeaves ) + { + if ( !Dar_CutMergeOrdered( pCut, pCut1, pCut0 ) ) + return 0; + } + else + { + if ( !Dar_CutMergeOrdered( pCut, pCut0, pCut1 ) ) + return 0; + } + pCut->uSign = pCut0->uSign | pCut1->uSign; + pCut->fUsed = 1; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dar_CutTruthPhase( Dar_Cut_t * pCut, Dar_Cut_t * pCut1 ) +{ + unsigned uPhase = 0; + int i, k; + for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) + { + if ( k == (int)pCut1->nLeaves ) + break; + if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) + continue; + assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); + uPhase |= (1 << i); + k++; + } + return uPhase; +} + +/**Function************************************************************* + + Synopsis [Swaps two advancent variables of the truth table.] + + Description [Swaps variable iVar and iVar+1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dar_CutTruthSwapAdjacentVars( unsigned uTruth, int iVar ) +{ + assert( iVar >= 0 && iVar <= 2 ); + if ( iVar == 0 ) + return (uTruth & 0x99999999) | ((uTruth & 0x22222222) << 1) | ((uTruth & 0x44444444) >> 1); + if ( iVar == 1 ) + return (uTruth & 0xC3C3C3C3) | ((uTruth & 0x0C0C0C0C) << 2) | ((uTruth & 0x30303030) >> 2); + if ( iVar == 2 ) + return (uTruth & 0xF00FF00F) | ((uTruth & 0x00F000F0) << 4) | ((uTruth & 0x0F000F00) >> 4); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Expands the truth table according to the phase.] + + Description [The input and output truth tables are in pIn/pOut. The current number + of variables is nVars. The total number of variables in nVarsAll. The last argument + (Phase) contains shows where the variables should go.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dar_CutTruthStretch( unsigned uTruth, int nVars, unsigned Phase ) +{ + int i, k, Var = nVars - 1; + for ( i = 3; i >= 0; i-- ) + if ( Phase & (1 << i) ) + { + for ( k = Var; k < i; k++ ) + uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, k ); + Var--; + } + assert( Var == -1 ); + return uTruth; +} + +/**Function************************************************************* + + Synopsis [Shrinks the truth table according to the phase.] + + Description [The input and output truth tables are in pIn/pOut. The current number + of variables is nVars. The total number of variables in nVarsAll. The last argument + (Phase) contains shows what variables should remain.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dar_CutTruthShrink( unsigned uTruth, int nVars, unsigned Phase ) +{ + int i, k, Var = 0; + for ( i = 0; i < 4; i++ ) + if ( Phase & (1 << i) ) + { + for ( k = i-1; k >= Var; k-- ) + uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, k ); + Var++; + } + return uTruth; +} + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dar_CutTruth( Dar_Cut_t * pCut, Dar_Cut_t * pCut0, Dar_Cut_t * pCut1, int fCompl0, int fCompl1 ) +{ + unsigned uTruth0 = fCompl0 ? ~pCut0->uTruth : pCut0->uTruth; + unsigned uTruth1 = fCompl1 ? ~pCut1->uTruth : pCut1->uTruth; + uTruth0 = Dar_CutTruthStretch( uTruth0, pCut0->nLeaves, Dar_CutTruthPhase(pCut, pCut0) ); + uTruth1 = Dar_CutTruthStretch( uTruth1, pCut1->nLeaves, Dar_CutTruthPhase(pCut, pCut1) ); + return uTruth0 & uTruth1; +} + +/**Function************************************************************* + + Synopsis [Minimize support of the cut.] + + Description [Returns 1 if the node's support has changed] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dar_CutSuppMinimize( Dar_Cut_t * pCut ) +{ + unsigned uMasks[4][2] = { + { 0x5555, 0xAAAA }, + { 0x3333, 0xCCCC }, + { 0x0F0F, 0xF0F0 }, + { 0x00FF, 0xFF00 } + }; + unsigned uPhase = 0, uTruth = 0xFFFF & pCut->uTruth; + int i, k, nLeaves; + assert( pCut->fUsed ); + // compute the truth support of the cut's function + nLeaves = pCut->nLeaves; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + if ( (uTruth & uMasks[i][0]) == ((uTruth & uMasks[i][1]) >> (1 << i)) ) + nLeaves--; + else + uPhase |= (1 << i); + if ( nLeaves == (int)pCut->nLeaves ) + return 0; + // shrink the truth table + uTruth = Dar_CutTruthShrink( uTruth, pCut->nLeaves, uPhase ); + pCut->uTruth = 0xFFFF & uTruth; + // update leaves and signature + pCut->uSign = 0; + for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) + { + if ( !(uPhase & (1 << i)) ) + continue; + pCut->pLeaves[k++] = pCut->pLeaves[i]; + pCut->uSign |= Aig_ObjCutSign( pCut->pLeaves[i] ); + } + assert( k == nLeaves ); + pCut->nLeaves = nLeaves; + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_ManCutsFree( Dar_Man_t * p ) +{ + if ( p->pMemCuts == NULL ) + return; + Aig_MmFixedStop( p->pMemCuts, 0 ); + p->pMemCuts = NULL; +// Aig_ManCleanData( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dar_Cut_t * Dar_ObjPrepareCuts( Dar_Man_t * p, Aig_Obj_t * pObj ) +{ + Dar_Cut_t * pCutSet, * pCut; + int i; + assert( Dar_ObjCuts(pObj) == NULL ); + pObj->nCuts = p->pPars->nCutsMax; + // create the cutset of the node + pCutSet = (Dar_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts ); + Dar_ObjSetCuts( pObj, pCutSet ); + Dar_ObjForEachCut( pObj, pCut, i ) + pCut->fUsed = 0; + // add unit cut if needed + pCut = pCutSet; + pCut->fUsed = 1; + if ( Aig_ObjIsConst1(pObj) ) + { + pCut->nLeaves = 0; + pCut->uSign = 0; + pCut->uTruth = 0xFFFF; + } + else + { + pCut->nLeaves = 1; + pCut->pLeaves[0] = pObj->Id; + pCut->uSign = Aig_ObjCutSign( pObj->Id ); + pCut->uTruth = 0xAAAA; + } + pCut->Value = Dar_CutFindValue( p, pCut ); + return pCutSet; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_ManCutsStart( Dar_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( p->pAig ); + Aig_MmFixedRestart( p->pMemCuts ); + Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) ); + Aig_ManForEachPi( p->pAig, pObj, i ) + Dar_ObjPrepareCuts( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dar_Cut_t * Dar_ObjComputeCuts( Dar_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + Aig_Obj_t * pFanin1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); + Aig_Obj_t * pFaninR0 = Aig_Regular(pFanin0); + Aig_Obj_t * pFaninR1 = Aig_Regular(pFanin1); + Dar_Cut_t * pCutSet, * pCut0, * pCut1, * pCut; + int i, k, RetValue; + + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsNode(pObj) ); + assert( Dar_ObjCuts(pObj) == NULL ); + assert( Dar_ObjCuts(pFaninR0) != NULL ); + assert( Dar_ObjCuts(pFaninR1) != NULL ); + + // set up the first cut + pCutSet = Dar_ObjPrepareCuts( p, pObj ); + // make sure fanins cuts are computed + Dar_ObjForEachCut( pFaninR0, pCut0, i ) + Dar_ObjForEachCut( pFaninR1, pCut1, k ) + { + p->nCutsAll++; + // make sure K-feasible cut exists + if ( Dar_WordCountOnes(pCut0->uSign | pCut1->uSign) > 4 ) + continue; + // get the next cut of this node + pCut = Dar_CutFindFree( p, pObj ); + // create the new cut + if ( !Dar_CutMerge( pCut, pCut0, pCut1 ) ) + { + assert( !pCut->fUsed ); + continue; + } + p->nCutsTried++; + // check dominance + if ( Dar_CutFilter( pObj, pCut ) ) + { + assert( !pCut->fUsed ); + continue; + } + // compute truth table + pCut->uTruth = 0xFFFF & Dar_CutTruth( pCut, pCut0, pCut1, Aig_IsComplement(pFanin0), Aig_IsComplement(pFanin1) ); + + // minimize support of the cut + if ( Dar_CutSuppMinimize( pCut ) ) + { + RetValue = Dar_CutFilter( pObj, pCut ); + assert( !RetValue ); + } + + // assign the value of the cut + pCut->Value = Dar_CutFindValue( p, pCut ); + // if the cut contains removed node, do not use it + if ( pCut->Value == 0 ) + { + p->nCutsSkipped++; + pCut->fUsed = 0; + } + else if ( pCut->nLeaves < 2 ) + return pCutSet; + } + // count the number of nontrivial cuts cuts + Dar_ObjForEachCut( pObj, pCut, i ) + p->nCutsUsed += pCut->fUsed; + // discount trivial cut + p->nCutsUsed--; + return pCutSet; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dar_Cut_t * Dar_ObjComputeCuts_rec( Dar_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( Dar_ObjCuts(pObj) ) + return Dar_ObjCuts(pObj); + if ( Aig_ObjIsBuf(pObj) ) + return Dar_ObjComputeCuts_rec( p, Aig_ObjFanin0(pObj) ); + Dar_ObjComputeCuts_rec( p, Aig_ObjFanin0(pObj) ); + Dar_ObjComputeCuts_rec( p, Aig_ObjFanin1(pObj) ); + return Dar_ObjComputeCuts( p, pObj ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/dar/darData.c b/abc70930/src/aig/dar/darData.c new file mode 100644 index 00000000..cb403b8a --- /dev/null +++ b/abc70930/src/aig/dar/darData.c @@ -0,0 +1,11287 @@ +/**CFile**************************************************************** + + FileName [dar_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [Storage for AIG subgraph data.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: dar_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "darInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +const int s_nDataSize1 = 2*43906; +unsigned int s_Data1[2*43906] = { + 4, 6, 5, 7, 9, 11, 5, 6, 4, 7, 15, 17, + 2, 8, 4, 21, 3, 10, 5, 25, 7, 25, 9, 25, + 2, 10, 7, 33, 9, 33, 2, 14, 5, 39, 6, 39, + 17, 39, 3, 16, 7, 47, 33, 47, 2, 16, 4, 53, + 7, 53, 3, 14, 5, 59, 17, 59, 53, 59, 3, 11, + 7, 67, 4, 68, 5, 66, 6, 73, 33, 67, 7, 76, + 5, 77, 9, 77, 9, 66, 33, 85, 3, 9, 4, 88, + 7, 91, 88, 93, 6, 88, 21, 89, 11, 89, 21, 100, + 25, 101, 11, 88, 7, 107, 33, 107, 2, 11, 5, 113, + 7, 112, 30, 113, 25, 113, 5, 120, 7, 121, 9, 120, + 9, 113, 25, 128, 21, 129, 9, 112, 2, 9, 6, 137, + 5, 138, 11, 136, 3, 17, 7, 144, 113, 145, 15, 144, + 113, 151, 3, 15, 6, 155, 4, 156, 17, 154, 113, 161, + 2, 17, 7, 165, 5, 166, 155, 165, 15, 164, 2, 15, + 6, 174, 17, 174, 3, 13, 113, 181, 135, 181, 143, 181, + 2, 12, 9, 189, 181, 189, 9, 192, 2, 13, 85, 197, + 107, 197, 3, 12, 7, 203, 11, 203, 33, 203, 197, 203, + 9, 211, 3, 19, 7, 215, 33, 215, 173, 215, 179, 215, + 2, 18, 215, 225, 2, 19, 151, 229, 161, 229, 3, 18, + 113, 235, 229, 235, 2, 4, 25, 241, 9, 241, 15, 241, + 11, 241, 6, 240, 7, 240, 59, 253, 7, 241, 9, 257, + 6, 241, 253, 261, 3, 5, 251, 265, 6, 266, 241, 269, + 253, 265, 7, 272, 7, 273, 241, 277, 53, 265, 7, 280, + 248, 265, 9, 285, 11, 265, 241, 288, 9, 291, 17, 265, + 9, 265, 257, 265, 25, 299, 251, 298, 7, 264, 3, 305, + 5, 305, 128, 305, 101, 305, 299, 305, 241, 305, 7, 317, + 265, 319, 9, 305, 113, 322, 113, 305, 9, 326, 6, 264, + 241, 331, 17, 331, 53, 331, 253, 331, 7, 265, 59, 341, + 241, 343, 331, 341, 241, 346, 241, 347, 15, 341, 113, 353, + 241, 340, 7, 357, 265, 357, 59, 357, 331, 357, 256, 265, + 7, 367, 59, 367, 331, 367, 6, 265, 5, 375, 242, 375, + 316, 375, 25, 375, 241, 382, 305, 375, 241, 386, 241, 387, + 11, 375, 241, 375, 265, 394, 7, 397, 25, 394, 305, 394, + 251, 395, 257, 375, 241, 374, 260, 265, 241, 265, 251, 413, + 331, 413, 261, 413, 375, 413, 257, 413, 19, 413, 12, 413, + 11, 413, 9, 428, 9, 413, 11, 433, 11, 432, 15, 413, + 11, 412, 9, 441, 7, 413, 241, 445, 265, 445, 375, 445, + 409, 445, 411, 445, 6, 412, 241, 457, 445, 457, 241, 460, + 6, 413, 357, 465, 367, 465, 7, 412, 265, 471, 59, 471, + 331, 471, 465, 471, 241, 479, 2, 6, 353, 483, 322, 483, + 30, 483, 25, 483, 9, 490, 305, 483, 9, 494, 19, 483, + 413, 483, 12, 483, 244, 483, 241, 483, 9, 506, 9, 483, + 305, 510, 25, 510, 11, 510, 241, 510, 257, 510, 247, 483, + 11, 483, 2, 524, 4, 527, 5, 524, 3, 531, 9, 524, + 258, 483, 151, 483, 257, 483, 9, 540, 155, 483, 17, 545, + 235, 483, 181, 483, 161, 483, 4, 482, 2, 555, 5, 482, + 2, 559, 6, 559, 17, 559, 5, 483, 2, 567, 6, 566, + 241, 567, 483, 573, 9, 573, 9, 567, 4, 483, 6, 581, + 3, 582, 3, 7, 289, 587, 510, 587, 11, 591, 11, 590, + 516, 587, 413, 587, 483, 598, 498, 587, 500, 587, 19, 587, + 483, 606, 502, 587, 12, 587, 483, 612, 534, 587, 524, 587, + 9, 618, 288, 587, 305, 623, 25, 623, 11, 587, 265, 629, + 331, 631, 510, 628, 9, 628, 483, 636, 483, 628, 9, 640, + 265, 628, 305, 645, 25, 645, 375, 628, 265, 587, 11, 653, + 33, 655, 11, 652, 25, 659, 305, 659, 295, 587, 241, 587, + 9, 587, 4, 668, 2, 671, 3, 668, 5, 675, 524, 668, + 483, 668, 11, 681, 11, 680, 11, 668, 483, 686, 392, 587, + 165, 587, 375, 587, 17, 695, 11, 695, 11, 694, 113, 587, + 567, 587, 305, 705, 25, 705, 555, 704, 5, 586, 3, 713, + 7, 713, 623, 713, 645, 713, 659, 713, 128, 713, 394, 713, + 101, 713, 299, 713, 705, 713, 510, 713, 483, 713, 9, 736, + 9, 713, 113, 740, 483, 740, 241, 713, 375, 746, 375, 713, + 241, 750, 113, 713, 9, 754, 4, 586, 7, 759, 589, 759, + 33, 759, 5, 587, 7, 767, 2, 768, 47, 767, 483, 773, + 759, 767, 483, 777, 17, 767, 113, 781, 483, 781, 483, 766, + 47, 787, 759, 787, 17, 787, 566, 587, 47, 795, 759, 795, + 17, 795, 4, 587, 3, 803, 6, 805, 7, 802, 494, 803, + 490, 803, 736, 803, 25, 803, 483, 816, 305, 803, 483, 820, + 713, 803, 483, 824, 483, 803, 305, 828, 25, 828, 713, 828, + 555, 829, 483, 802, 580, 587, 483, 587, 413, 842, 19, 842, + 12, 842, 11, 843, 9, 851, 9, 842, 11, 855, 11, 854, + 11, 842, 9, 860, 5, 843, 803, 865, 9, 865, 839, 865, + 841, 865, 4, 842, 483, 875, 865, 875, 483, 878, 4, 843, + 787, 883, 795, 883, 5, 842, 587, 889, 47, 889, 759, 889, + 17, 889, 883, 889, 483, 899, 3, 4, 559, 903, 19, 903, + 12, 903, 842, 903, 587, 903, 483, 912, 165, 912, 9, 903, + 11, 918, 483, 903, 241, 923, 555, 923, 587, 922, 11, 922, + 15, 903, 11, 903, 9, 934, 483, 934, 524, 903, 692, 903, + 767, 903, 375, 945, 165, 903, 7, 949, 587, 948, 6, 902, + 3, 955, 7, 902, 787, 959, 795, 959, 889, 959, 767, 959, + 483, 967, 33, 959, 7, 903, 956, 973, 88, 973, 4, 973, + 3, 973, 955, 980, 9, 980, 3, 972, 4, 972, 955, 973, + 3, 990, 375, 973, 9, 973, 3, 996, 6, 903, 4, 1001, + 3, 1001, 3, 1000, 4, 1000, 2, 5, 955, 1011, 914, 1011, + 918, 1011, 11, 1017, 11, 1016, 912, 1011, 483, 1022, 920, 1011, + 906, 1011, 19, 1011, 903, 1030, 842, 1011, 903, 1034, 908, 1011, + 910, 1011, 12, 1011, 903, 1042, 922, 1011, 587, 1046, 928, 1011, + 936, 1011, 934, 1011, 9, 1054, 15, 1011, 11, 1011, 918, 1060, + 9, 1060, 903, 1064, 903, 1060, 9, 1068, 483, 1011, 912, 1072, + 903, 1072, 587, 1076, 587, 1072, 903, 1080, 155, 1072, 587, 1011, + 922, 1086, 483, 1086, 903, 1090, 903, 1086, 483, 1094, 11, 1087, + 9, 1099, 9, 1086, 11, 1103, 17, 1011, 9, 1011, 934, 1108, + 903, 1108, 11, 1113, 11, 1112, 11, 1108, 903, 1118, 587, 1108, + 11, 1123, 668, 1011, 11, 1127, 544, 1011, 155, 1011, 483, 1132, + 67, 1011, 375, 1137, 7, 1010, 2, 1141, 959, 1141, 85, 1141, + 107, 1141, 203, 1141, 67, 1141, 9, 1153, 215, 1141, 47, 1141, + 759, 1141, 6, 1010, 2, 1163, 5, 1163, 17, 1163, 7, 1011, + 2, 1171, 5, 1171, 2, 1170, 5, 1170, 1163, 1171, 5, 1180, + 2, 1181, 483, 1171, 903, 1170, 375, 1189, 972, 1011, 375, 1193, + 6, 1011, 2, 1197, 5, 1197, 2, 1196, 5, 1196, 1141, 1197, + 2, 1206, 5, 1207, 903, 1196, 1000, 1011, 903, 1011, 19, 1216, + 842, 1216, 12, 1216, 11, 1217, 9, 1225, 587, 1216, 483, 1228, + 11, 1216, 9, 1232, 9, 1216, 11, 1237, 11, 1236, 15, 1216, + 483, 1216, 587, 1244, 7, 1217, 59, 1249, 331, 1249, 1213, 1249, + 1215, 1249, 6, 1216, 1249, 1259, 6, 1217, 1189, 1263, 1193, 1263, + 7, 1216, 375, 1269, 1263, 1269, 3, 6, 413, 1275, 1216, 1275, + 241, 1275, 9, 1281, 11, 1283, 11, 1280, 9, 1287, 17, 1275, + 3, 1290, 5, 1293, 4, 1290, 2, 1297, 903, 1291, 1011, 1275, + 11, 1275, 241, 1304, 9, 1307, 248, 1275, 9, 1311, 973, 1275, + 9, 1315, 341, 1275, 803, 1319, 9, 1319, 5, 1274, 3, 1325, + 17, 1325, 357, 1325, 367, 1325, 471, 1325, 341, 1325, 241, 1337, + 1249, 1325, 253, 1325, 53, 1325, 5, 1275, 6, 1347, 2, 1348, + 918, 1347, 903, 1347, 9, 1354, 9, 1347, 903, 1358, 4, 1275, + 6, 1362, 265, 1363, 2, 7, 393, 1369, 334, 1369, 1325, 1369, + 1363, 1374, 17, 1374, 62, 1369, 331, 1369, 17, 1382, 59, 1369, + 17, 1386, 1328, 1369, 1304, 1369, 9, 1393, 17, 1369, 331, 1396, + 241, 1397, 59, 1396, 1325, 1396, 11, 1369, 1275, 1406, 9, 1409, + 265, 1369, 241, 1412, 11, 1413, 15, 1369, 5, 1418, 3, 1421, + 2, 1418, 4, 1425, 1011, 1419, 107, 1369, 67, 1369, 803, 1433, + 9, 1433, 1359, 1369, 203, 1369, 215, 1369, 85, 1369, 5, 1368, + 2, 1447, 7, 1447, 47, 1447, 85, 1447, 107, 1447, 203, 1447, + 67, 1447, 9, 1461, 215, 1447, 759, 1447, 959, 1447, 4, 1368, + 2, 1471, 7, 1471, 265, 1471, 7, 1476, 331, 1471, 59, 1471, + 1325, 1471, 5, 1369, 7, 1486, 803, 1487, 1275, 1486, 803, 1493, + 9, 1493, 1346, 1369, 803, 1499, 9, 1499, 4, 1369, 7, 1505, + 3, 1506, 1060, 1505, 11, 1505, 1011, 1512, 1011, 1505, 7, 1517, + 11, 1517, 11, 1516, 1347, 1505, 1275, 1504, 1362, 1369, 1275, 1369, + 413, 1531, 19, 1531, 12, 1531, 1216, 1531, 1011, 1531, 903, 1540, + 9, 1531, 11, 1545, 11, 1544, 11, 1531, 9, 1550, 903, 1531, + 1011, 1554, 11, 1530, 9, 1559, 5, 1531, 959, 1563, 47, 1563, + 759, 1563, 17, 1563, 1527, 1563, 1529, 1563, 4, 1530, 1563, 1577, + 4, 1531, 1493, 1581, 1499, 1581, 5, 1530, 803, 1587, 9, 1587, + 1581, 1587, 1, 974, 1, 975, 1, 982, 1, 983, 0, 204, + 0, 195, 0, 881, 0, 463, 0, 212, 0, 900, 0, 480, + 0, 194, 0, 880, 0, 462, 0, 213, 0, 901, 0, 481, + 0, 205, 0, 216, 0, 217, 1, 446, 0, 448, 0, 415, + 0, 421, 1, 92, 0, 92, 1, 94, 1645, 1647, 1, 93, + 88, 1650, 1645, 1653, 0, 93, 1, 95, 1657, 1659, 0, 108, + 0, 109, 1, 360, 0, 368, 0, 358, 0, 414, 1, 447, + 1637, 1675, 0, 449, 1635, 1679, 0, 191, 0, 877, 0, 473, + 1, 473, 0, 459, 1, 459, 0, 891, 0, 207, 0, 458, + 0, 876, 0, 190, 1, 458, 0, 472, 0, 890, 0, 206, + 1, 472, 1, 977, 1, 976, 0, 399, 0, 398, 0, 397, + 7, 1722, 0, 275, 0, 269, 241, 1728, 0, 270, 1, 279, + 0, 321, 0, 274, 0, 271, 1, 278, 0, 320, 1, 277, + 241, 1746, 0, 319, 265, 1750, 1, 276, 0, 318, 1, 926, + 0, 1518, 0, 950, 0, 1519, 0, 951, 1, 998, 1, 999, + 0, 575, 0, 1478, 0, 282, 0, 1479, 0, 283, 0, 369, + 0, 359, 1667, 1785, 0, 420, 1, 422, 1, 927, 1, 1421, + 5, 1794, 1419, 1797, 3, 1794, 1799, 1801, 0, 527, 2, 1804, + 525, 1807, 4, 1804, 1809, 1811, 1, 671, 4, 1814, 669, 1817, + 2, 1814, 1819, 1821, 0, 1293, 3, 1824, 1291, 1827, 5, 1824, + 1829, 1831, 1, 1425, 2, 1834, 1419, 1837, 4, 1834, 1839, 1841, + 0, 531, 5, 1844, 525, 1847, 3, 1844, 1849, 1851, 1, 675, + 3, 1854, 669, 1857, 5, 1854, 1859, 1861, 0, 1297, 4, 1864, + 1291, 1867, 2, 1864, 1869, 1871, 1, 1422, 0, 528, 1, 672, + 0, 1294, 1, 1426, 0, 532, 1, 676, 0, 1298, 1, 123, + 0, 79, 1, 993, 0, 124, 1, 80, 0, 1210, 0, 1184, + 0, 125, 1891, 1905, 1, 81, 1893, 1909, 1, 122, 1897, 1913, + 0, 78, 1899, 1917, 0, 1208, 0, 1182, 1, 992, 1, 361, + 1671, 1927, 0, 574, 1, 984, 1, 985, 1, 114, 9, 1937, + 0, 68, 1, 980, 955, 1942, 9, 1942, 0, 568, 9, 1949, + 1, 924, 1, 925, 0, 306, 375, 1957, 0, 308, 1413, 1961, + 0, 26, 1, 306, 1, 308, 1, 714, 0, 1142, 0, 1448, + 0, 1450, 1, 1450, 1413, 1979, 0, 1474, 0, 54, 0, 56, + 1, 1472, 0, 1326, 0, 60, 1, 60, 0, 1166, 0, 40, + 1, 956, 973, 2001, 973, 2000, 0, 556, 1, 22, 0, 1475, + 1, 1165, 1168, 2012, 1169, 2013, 2015, 2017, 1168, 2013, 1169, 2012, + 2021, 2023, 1, 1167, 2, 2027, 1197, 2029, 1997, 2031, 0, 57, + 1, 957, 0, 1451, 1980, 2039, 1979, 2039, 1413, 2042, 1413, 2039, + 1979, 2046, 1, 1449, 5, 2051, 1451, 2053, 1975, 2055, 1, 1451, + 1977, 2059, 1413, 2061, 0, 307, 1967, 2065, 375, 2067, 0, 309, + 1969, 2071, 1413, 2073, 0, 41, 1, 307, 1958, 2079, 1957, 2079, + 375, 2082, 375, 2079, 1957, 2086, 1, 309, 1962, 2091, 1961, 2091, + 1413, 2094, 1413, 2091, 1961, 2098, 1, 41, 2, 2103, 43, 2105, + 1999, 2107, 1, 1143, 5, 2111, 1171, 2113, 1973, 2115, 1, 561, + 564, 2118, 565, 2119, 2121, 2123, 564, 2119, 565, 2118, 2127, 2129, + 0, 91, 7, 2132, 0, 569, 1, 981, 9, 2139, 955, 2139, + 0, 69, 9, 2145, 1, 115, 0, 432, 0, 500, 0, 1245, + 0, 1237, 0, 501, 0, 433, 1, 1415, 1, 348, 1, 388, + 1, 826, 1, 126, 1, 1376, 1, 380, 1, 814, 1, 118, + 1, 302, 1, 710, 1, 102, 1, 402, 1, 834, 1, 130, + 1, 404, 1, 836, 1, 132, 1, 314, 1, 732, 1, 104, + 0, 1236, 0, 1244, 1, 1414, 0, 202, 1, 888, 1, 202, + 1603, 2215, 0, 106, 1, 106, 1663, 2221, 1, 794, 0, 366, + 0, 84, 1, 786, 1, 84, 1941, 2233, 1, 390, 1, 994, + 1, 450, 1, 105, 1, 733, 1, 405, 1, 315, 1, 837, + 1, 133, 1, 407, 1, 451, 1, 391, 1, 1383, 0, 905, + 1, 905, 0, 1477, 1, 1477, 1775, 2269, 6, 2269, 7, 2269, + 6, 2268, 2275, 2277, 1983, 2269, 7, 2268, 2273, 2283, 0, 281, + 1, 281, 1777, 2289, 6, 2289, 7, 2289, 6, 2288, 2295, 2297, + 1987, 2289, 7, 2288, 2293, 2303, 1, 1387, 1, 406, 2227, 2309, + 1, 995, 0, 461, 1, 461, 1621, 2317, 1699, 2317, 0, 1261, + 1, 1261, 0, 879, 0, 193, 1, 879, 1619, 2331, 1701, 2331, + 1, 193, 1617, 2337, 1703, 2337, 0, 1579, 0, 211, 9, 2344, + 1, 1579, 1, 211, 1623, 2351, 1711, 2351, 0, 479, 241, 2356, + 0, 899, 483, 2360, 0, 227, 1, 479, 1627, 2367, 1707, 2367, + 1, 899, 1625, 2373, 1709, 2373, 1, 227, 0, 1273, 0, 1593, + 0, 239, 1, 1273, 1, 1593, 1, 239, 0, 478, 2367, 2393, + 1, 478, 2359, 2397, 1615, 2397, 2357, 2397, 1687, 2397, 0, 1272, + 2387, 2407, 1, 1272, 2381, 2411, 0, 898, 2373, 2415, 0, 210, + 2351, 2419, 1, 898, 2363, 2423, 1613, 2423, 2361, 2423, 1695, 2423, + 1, 210, 2347, 2433, 1611, 2433, 2345, 2433, 1697, 2433, 0, 1592, + 2389, 2443, 0, 192, 9, 2446, 2337, 2449, 2337, 2447, 1, 1592, + 2383, 2455, 1, 192, 1605, 2459, 2329, 2459, 1683, 2459, 0, 460, + 241, 2466, 2317, 2469, 2317, 2467, 0, 878, 483, 2474, 2331, 2477, + 2331, 2475, 0, 238, 2391, 2483, 1, 460, 1609, 2487, 2315, 2487, + 1691, 2487, 1, 878, 1607, 2495, 2327, 2495, 1685, 2495, 1, 238, + 2385, 2503, 0, 1260, 2325, 2507, 0, 1578, 2349, 2511, 0, 226, + 2379, 2515, 1, 1260, 2323, 2519, 1, 1578, 2343, 2523, 1, 226, + 2365, 2527, 1, 349, 1, 127, 1, 827, 1, 389, 1, 119, + 1, 815, 1, 381, 1, 1377, 1, 131, 1, 835, 1, 303, + 1, 403, 1, 711, 1, 103, 1, 1366, 1, 694, 1, 702, + 9, 2563, 0, 572, 1, 572, 1931, 2569, 0, 1516, 1, 1516, + 1761, 2575, 7, 2575, 6, 2574, 2579, 2581, 6, 2575, 7, 2574, + 2585, 2587, 0, 944, 0, 948, 1, 578, 587, 2595, 1, 948, + 1763, 2599, 7, 2599, 6, 2598, 2603, 2605, 6, 2599, 7, 2598, + 2609, 2611, 1, 1186, 1, 996, 3, 2616, 1, 544, 1, 465, + 471, 2622, 1687, 2625, 1, 197, 203, 2628, 1697, 2631, 1, 883, + 889, 2634, 1695, 2637, 1, 181, 189, 2640, 1683, 2643, 0, 445, + 1693, 2647, 1713, 2647, 265, 2646, 1675, 2653, 2257, 2647, 375, 2647, + 457, 2647, 1, 445, 264, 2662, 241, 2662, 1679, 2667, 375, 2662, + 457, 2662, 1691, 2673, 1, 865, 875, 2676, 1685, 2679, 0, 215, + 7, 2682, 1, 215, 1633, 2687, 1, 1563, 0, 457, 241, 2692, + 2317, 2695, 1, 457, 241, 2698, 445, 2699, 445, 2698, 1691, 2705, + 0, 875, 483, 2708, 2331, 2711, 1, 875, 865, 2714, 1685, 2717, + 0, 189, 9, 2720, 2337, 2723, 1, 189, 181, 2726, 1683, 2729, + 0, 203, 7, 2732, 2215, 2735, 11, 2732, 2351, 2739, 0, 471, + 7, 2742, 1689, 2745, 265, 2742, 2367, 2749, 0, 889, 587, 2752, + 2373, 2755, 1, 203, 1629, 2759, 197, 2758, 1697, 2763, 1, 471, + 265, 2766, 2647, 2769, 465, 2766, 1687, 2773, 1, 889, 883, 2776, + 1695, 2779, 0, 107, 7, 2782, 2221, 2785, 1, 107, 1665, 2789, + 1, 795, 0, 367, 2255, 2795, 375, 2795, 7, 2794, 1, 367, + 265, 2802, 1783, 2805, 0, 85, 7, 2808, 2233, 2811, 0, 357, + 7, 2814, 1927, 2817, 1, 85, 2145, 2821, 1, 357, 265, 2824, + 1785, 2827, 1, 787, 0, 573, 483, 2832, 2569, 2835, 1, 579, + 1, 573, 1773, 2841, 1, 997, 1, 545, 1, 1187, 903, 2849, + 1, 1367, 0, 949, 7, 2854, 2599, 2857, 0, 945, 483, 2861, + 1, 949, 1767, 2865, 0, 1517, 7, 2868, 2575, 2871, 1, 1517, + 1765, 2875, 1, 703, 1, 695, 1, 332, 1, 266, 1731, 2885, + 1733, 2885, 1, 1012, 1, 30, 113, 2892, 0, 316, 265, 2896, + 375, 2897, 0, 272, 7, 2902, 1735, 2903, 1, 736, 803, 2908, + 1, 316, 1737, 2913, 375, 2912, 1, 272, 1727, 2919, 241, 2918, + 0, 1374, 2545, 2925, 1, 1374, 1363, 2928, 1, 1382, 0, 904, + 483, 2934, 2265, 2937, 1, 904, 0, 1476, 7, 2942, 2269, 2945, + 1, 1476, 1779, 2949, 2011, 2949, 0, 280, 7, 2954, 2289, 2957, + 1, 280, 1781, 2961, 2035, 2961, 1, 1386, 1, 99, 1, 991, + 0, 1181, 2, 2972, 0, 347, 2165, 2977, 1, 347, 1, 263, + 273, 2983, 272, 2982, 2985, 2987, 272, 2983, 273, 2982, 2991, 2993, + 0, 77, 0, 1207, 5, 2998, 1, 77, 5, 3002, 1917, 3005, + 9, 3003, 0, 121, 7, 3010, 1913, 3013, 9, 3011, 0, 387, + 2259, 3019, 1, 121, 9, 3023, 1, 825, 483, 3027, 1, 387, + 241, 3030, 241, 3031, 1, 98, 0, 1206, 2, 3038, 0, 386, + 2237, 3043, 3033, 3043, 1, 386, 241, 3048, 1, 824, 483, 3052, + 1, 990, 3, 3056, 0, 120, 3023, 3061, 9, 3063, 0, 1180, + 5, 3066, 1, 120, 3016, 3071, 5, 3070, 1897, 3075, 3013, 3075, + 3011, 3071, 9, 3080, 9, 3070, 9, 3071, 3011, 3086, 0, 76, + 3008, 3091, 7, 3090, 1899, 3095, 3005, 3095, 3003, 3091, 9, 3100, + 9, 3091, 3003, 3104, 0, 346, 2531, 3109, 1, 76, 2997, 3113, + 9, 3115, 1, 776, 1, 346, 241, 3120, 2977, 3123, 1, 21, + 2, 3127, 1275, 3129, 9, 3131, 4, 3126, 3133, 3135, 2, 3126, + 668, 3139, 3135, 3141, 587, 3139, 9, 3144, 3135, 3147, 9, 3139, + 587, 3150, 3135, 3153, 100, 3126, 129, 3126, 129, 3127, 100, 3127, + 89, 3127, 11, 3164, 11, 3127, 89, 3169, 89, 3168, 89, 3126, + 0, 25, 2243, 3177, 2547, 3177, 2539, 3177, 2533, 3177, 3024, 3177, + 3, 3177, 1369, 3189, 11, 3191, 5, 3176, 3193, 3195, 3, 3176, + 524, 3199, 3195, 3201, 483, 3199, 11, 3204, 3195, 3207, 11, 3199, + 483, 3210, 3195, 3213, 3023, 3177, 9, 3216, 101, 3177, 128, 3177, + 113, 3177, 9, 3224, 9, 3177, 3023, 3228, 113, 3228, 1, 33, + 5, 3234, 6, 3237, 2997, 3235, 9, 3241, 3177, 3235, 67, 3235, + 9, 3247, 67, 3234, 3239, 3251, 1, 25, 128, 3254, 101, 3254, + 113, 3255, 9, 3254, 113, 3262, 113, 3254, 9, 3266, 9, 3267, + 0, 33, 2759, 3273, 2789, 3273, 2821, 3273, 9, 3273, 67, 3272, + 9, 3283, 1, 251, 298, 3286, 395, 3286, 395, 3287, 298, 3287, + 257, 3287, 265, 3297, 265, 3296, 265, 3287, 257, 3302, 265, 3286, + 0, 305, 2249, 3309, 2553, 3309, 2543, 3309, 2537, 3309, 3034, 3309, + 3031, 3309, 241, 3320, 3235, 3309, 299, 3309, 394, 3309, 375, 3309, + 241, 3330, 241, 3309, 3031, 3334, 375, 3334, 241, 3308, 375, 3341, + 1, 331, 2647, 3345, 413, 3345, 241, 3344, 1369, 3344, 341, 3344, + 0, 253, 7, 3356, 265, 3356, 3345, 3357, 1, 555, 923, 3364, + 923, 3365, 704, 3364, 829, 3364, 829, 3365, 704, 3365, 0, 713, + 2245, 3379, 2549, 3379, 2541, 3379, 2535, 3379, 3028, 3379, 3027, 3379, + 483, 3390, 3235, 3379, 705, 3379, 828, 3379, 803, 3379, 483, 3400, + 483, 3379, 3027, 3404, 803, 3404, 1, 759, 3, 3410, 6, 3413, + 3273, 3411, 767, 3410, 3415, 3419, 0, 559, 0, 251, 413, 3424, + 413, 3425, 257, 3425, 413, 3431, 412, 3430, 3433, 3435, 412, 3431, + 413, 3430, 3439, 3441, 1, 305, 3, 3445, 375, 3447, 3, 3444, + 394, 3444, 299, 3444, 241, 3444, 375, 3456, 375, 3444, 241, 3460, + 1, 253, 265, 3464, 0, 555, 4, 3469, 15, 3471, 483, 3473, + 2, 3468, 3475, 3477, 4, 3468, 524, 3481, 3477, 3483, 11, 3481, + 483, 3486, 3477, 3489, 483, 3481, 11, 3492, 3477, 3495, 1, 713, + 5, 3499, 17, 3501, 587, 3503, 3, 3498, 3505, 3507, 5, 3498, + 668, 3511, 3507, 3513, 9, 3511, 587, 3516, 3507, 3519, 587, 3511, + 9, 3522, 3507, 3525, 828, 3498, 705, 3498, 483, 3498, 803, 3532, + 803, 3498, 483, 3536, 1, 559, 903, 3540, 1, 955, 980, 3544, + 3, 3544, 973, 3549, 973, 3548, 973, 3545, 2139, 3555, 1011, 3544, + 973, 3544, 3, 3560, 0, 1141, 2, 3564, 9, 3565, 3411, 3565, + 0, 1447, 9, 3573, 3411, 3573, 1, 1471, 4, 3579, 11, 3581, + 1369, 3583, 2, 3578, 3585, 3587, 4, 3578, 1418, 3591, 3587, 3593, + 15, 3591, 1369, 3596, 3587, 3599, 1369, 3591, 15, 3602, 3587, 3605, + 265, 3578, 2011, 3609, 0, 1325, 5, 3613, 9, 3615, 1275, 3617, + 3, 3612, 3619, 3621, 5, 3612, 1290, 3625, 3621, 3627, 17, 3625, + 1275, 3630, 3621, 3633, 1275, 3625, 17, 3636, 3621, 3639, 1, 53, + 265, 3642, 2035, 3645, 0, 59, 5, 3648, 1, 1141, 3177, 3653, + 3379, 3653, 3309, 3653, 0, 1163, 5, 3660, 1, 959, 3565, 3665, + 3273, 3665, 3573, 3665, 1, 1447, 3177, 3673, 3309, 3673, 3379, 3673, + 0, 1471, 7, 3680, 2269, 3683, 3345, 3681, 1, 1325, 1369, 3688, + 3357, 3689, 3681, 3689, 0, 39, 5, 3696, 1, 47, 3565, 3701, + 3573, 3701, 3273, 3701, 0, 53, 2, 3709, 587, 3711, 17, 3713, + 7, 3708, 2289, 3717, 4, 3708, 3715, 3721, 2, 3708, 1290, 3725, + 3721, 3727, 1275, 3725, 17, 3730, 3721, 3733, 17, 3725, 1275, 3736, + 3721, 3739, 3345, 3709, 3689, 3709, 1, 59, 3, 3747, 483, 3749, + 15, 3751, 5, 3746, 3753, 3755, 3, 3746, 1418, 3759, 3755, 3761, + 1369, 3759, 15, 3764, 3755, 3767, 15, 3759, 1369, 3770, 3755, 3773, + 1369, 3746, 3681, 3747, 3357, 3747, 3709, 3747, 1, 330, 1369, 3785, + 471, 3785, 367, 3785, 357, 3785, 341, 3785, 241, 3795, 0, 1162, + 17, 3799, 0, 758, 767, 3803, 0, 32, 2215, 3807, 2221, 3807, + 2233, 3807, 3249, 3807, 3246, 3807, 9, 3817, 3235, 3807, 67, 3820, + 9, 3823, 67, 3807, 3235, 3826, 9, 3829, 1, 758, 3807, 3833, + 1, 32, 3104, 3837, 3284, 3837, 3091, 3837, 9, 3842, 3283, 3837, + 9, 3846, 3273, 3837, 67, 3851, 9, 3853, 9, 3837, 3283, 3856, + 3091, 3856, 0, 1470, 3785, 3863, 0, 24, 2203, 3867, 3259, 3867, + 2191, 3867, 3257, 3867, 2179, 3867, 2895, 3867, 2171, 3867, 3265, 3867, + 3269, 3867, 3085, 3867, 3071, 3867, 9, 3889, 3267, 3867, 9, 3893, + 2893, 3867, 113, 3897, 3263, 3867, 113, 3901, 3255, 3867, 101, 3905, + 128, 3905, 113, 3905, 9, 3910, 9, 3905, 113, 3914, 3837, 3867, + 128, 3867, 101, 3867, 9, 3867, 113, 3924, 113, 3867, 9, 3928, + 1, 24, 3220, 3933, 3222, 3933, 3232, 3933, 3226, 3933, 3224, 3933, + 9, 3942, 3228, 3933, 113, 3946, 3177, 3933, 101, 3950, 128, 3950, + 113, 3950, 9, 3956, 9, 3950, 113, 3960, 128, 3933, 3177, 3964, + 101, 3933, 3177, 3968, 9, 3933, 3224, 3972, 3177, 3972, 113, 3976, + 113, 3972, 3177, 3980, 113, 3933, 3228, 3984, 3177, 3984, 9, 3988, + 9, 3984, 3177, 3992, 0, 712, 2201, 3997, 3531, 3997, 2189, 3997, + 3529, 3997, 2177, 3997, 2911, 3997, 2169, 3997, 3535, 3997, 3539, 3997, + 3055, 3997, 3053, 3997, 483, 4019, 3537, 3997, 483, 4023, 2909, 3997, + 803, 4027, 3533, 3997, 803, 4031, 3499, 3997, 705, 4035, 828, 4035, + 803, 4035, 483, 4040, 483, 4035, 803, 4044, 3837, 3997, 828, 3997, + 705, 3997, 483, 3997, 803, 4054, 803, 3997, 483, 4058, 0, 52, + 3785, 4063, 0, 304, 2199, 4067, 3455, 4067, 2187, 4067, 3453, 4067, + 2175, 4067, 2917, 4067, 2167, 4067, 3459, 4067, 3463, 4067, 3051, 4067, + 3049, 4067, 241, 4089, 3461, 4067, 241, 4093, 2913, 4067, 375, 4097, + 3457, 4067, 375, 4101, 3445, 4067, 299, 4105, 394, 4105, 375, 4105, + 241, 4110, 241, 4105, 375, 4114, 3837, 4067, 394, 4067, 299, 4067, + 241, 4067, 375, 4124, 375, 4067, 241, 4128, 0, 38, 17, 4133, + 0, 252, 265, 4137, 3785, 4137, 0, 558, 17, 4143, 1, 712, + 3396, 4147, 3398, 4147, 3408, 4147, 3402, 4147, 3400, 4147, 483, 4156, + 3404, 4147, 803, 4160, 3379, 4147, 705, 4164, 828, 4164, 803, 4164, + 483, 4170, 483, 4164, 803, 4174, 9, 4147, 828, 4147, 3379, 4180, + 705, 4147, 3379, 4184, 483, 4147, 3400, 4188, 3379, 4188, 803, 4192, + 803, 4188, 3379, 4196, 803, 4147, 3404, 4200, 3379, 4200, 483, 4204, + 483, 4200, 3379, 4208, 1, 304, 3326, 4213, 3328, 4213, 3338, 4213, + 3332, 4213, 3330, 4213, 241, 4222, 3334, 4213, 375, 4226, 3309, 4213, + 299, 4230, 394, 4230, 375, 4230, 241, 4236, 241, 4230, 375, 4240, + 9, 4213, 394, 4213, 3309, 4246, 299, 4213, 3309, 4250, 241, 4213, + 3330, 4254, 3309, 4254, 375, 4258, 375, 4254, 3309, 4262, 375, 4213, + 3334, 4266, 3309, 4266, 241, 4270, 241, 4266, 3309, 4274, 0, 1446, + 3833, 4279, 0, 1140, 3833, 4283, 1, 1446, 3867, 4287, 3997, 4287, + 4067, 4287, 1, 46, 4279, 4295, 3807, 4295, 4283, 4295, 1, 1140, + 3867, 4303, 4067, 4303, 3997, 4303, 1, 58, 1369, 4311, 4063, 4311, + 3863, 4311, 4137, 4311, 1, 958, 3807, 4321, 4279, 4321, 4283, 4321, + 1, 1324, 1369, 4329, 3863, 4329, 4063, 4329, 4137, 4329, 1, 214, + 1631, 4339, 2685, 4339, 0, 214, 1, 1562, 1, 444, 449, 4349, + 7, 4349, 265, 4353, 2647, 4355, 2658, 4349, 251, 4349, 2647, 4349, + 375, 4362, 375, 4349, 2647, 4366, 0, 444, 2701, 4371, 1689, 4371, + 1705, 4371, 447, 4371, 2665, 4371, 2241, 4371, 3785, 4371, 2671, 4371, + 265, 4371, 331, 4371, 2663, 4371, 375, 4393, 375, 4371, 1, 510, + 257, 4399, 1, 1058, 0, 1396, 0, 1406, 0, 628, 375, 4409, + 1, 652, 1, 288, 1, 267, 1741, 4417, 1, 1013, 1, 1375, + 1, 333, 2903, 4425, 3361, 4425, 0, 1375, 2931, 4431, 2173, 4431, + 1, 273, 2905, 4437, 1739, 4437, 6, 4436, 7, 4437, 4443, 4445, + 6, 4437, 3359, 4437, 7, 4436, 4449, 4453, 0, 273, 2883, 4457, + 2913, 4457, 3351, 4457, 3457, 4457, 2923, 4457, 1749, 4457, 1743, 4457, + 1, 31, 3224, 4473, 3177, 4473, 113, 4476, 113, 4473, 3177, 4480, + 1, 737, 3400, 4485, 3379, 4485, 803, 4488, 803, 4485, 3379, 4492, + 1, 317, 2903, 4497, 3361, 4497, 2900, 4497, 7, 4497, 265, 4505, + 2897, 4507, 1753, 4497, 1745, 4497, 3330, 4497, 2897, 4497, 375, 4516, + 3309, 4497, 375, 4520, 375, 4497, 2897, 4524, 3309, 4524, 0, 317, + 7, 4530, 2913, 4531, 375, 4535, 375, 4531, 1, 507, 1, 245, + 0, 1397, 1, 913, 0, 1407, 1, 653, 11, 4551, 1, 289, + 1, 629, 713, 4557, 25, 4557, 305, 4557, 0, 629, 375, 4565, + 0, 340, 3785, 4569, 4311, 4569, 4329, 4569, 4555, 4569, 0, 766, + 1413, 4579, 922, 4579, 903, 4579, 483, 4584, 483, 4579, 903, 4588, + 0, 66, 75, 4593, 7, 4593, 3113, 4593, 9, 4599, 3251, 4593, + 9, 4603, 375, 4593, 483, 4593, 9, 4593, 1, 340, 331, 4613, + 1, 766, 483, 4616, 2591, 4617, 483, 4621, 1, 66, 5, 4624, + 6, 4627, 3248, 4625, 1941, 4625, 9, 4633, 36, 4625, 3247, 4625, + 9, 4638, 9, 4624, 1941, 4643, 3807, 4643, 33, 4625, 9, 4648, + 9, 4625, 3247, 4652, 33, 4652, 3807, 4625, 9, 4659, 0, 1170, + 2615, 4663, 903, 4665, 0, 112, 3972, 4669, 3270, 4669, 3086, 4669, + 1938, 4669, 1937, 4669, 9, 4678, 2564, 4669, 3071, 4669, 9, 4684, + 3267, 4669, 9, 4688, 2563, 4669, 9, 4692, 9, 4669, 3267, 4696, + 3933, 4696, 1937, 4696, 3071, 4696, 2563, 4696, 3933, 4669, 9, 4708, + 1, 1170, 1413, 4713, 922, 4713, 483, 4713, 903, 4718, 903, 4713, + 483, 4722, 1, 112, 2, 4727, 7, 4729, 3261, 4727, 9, 4733, + 25, 4727, 903, 4727, 587, 4727, 9, 4727, 0, 972, 3059, 4745, + 1925, 4745, 3563, 4745, 3553, 4745, 3549, 4745, 3547, 4745, 2005, 4745, + 2001, 4745, 1595, 4745, 1945, 4745, 1599, 4745, 2239, 4745, 1717, 4745, + 2619, 4745, 1769, 4745, 1947, 4745, 1933, 4745, 1943, 4745, 955, 4781, + 9, 4781, 0, 802, 807, 4787, 375, 4787, 7, 4787, 805, 4793, + 265, 4793, 483, 4787, 0, 144, 483, 4801, 1, 972, 3551, 4805, + 2003, 4805, 375, 4805, 955, 4805, 9, 4805, 1011, 4805, 1, 802, + 713, 4819, 483, 4819, 1, 144, 0, 256, 2309, 4827, 4437, 4827, + 264, 4826, 299, 4833, 264, 4827, 367, 4837, 265, 4826, 2309, 4841, + 4805, 4827, 4613, 4827, 375, 4827, 510, 4827, 483, 4827, 9, 4852, + 9, 4827, 483, 4856, 0, 1504, 1, 256, 2798, 4863, 7, 4863, + 265, 4867, 264, 4862, 264, 4863, 2795, 4863, 375, 4874, 265, 4862, + 4873, 4879, 305, 4863, 713, 4863, 25, 4863, 375, 4863, 2795, 4888, + 265, 4863, 4871, 4893, 1, 164, 0, 374, 241, 4899, 0, 1346, + 9, 4903, 0, 154, 0, 1412, 2853, 4909, 2163, 4909, 0, 1418, + 1, 1346, 1, 154, 483, 4919, 1, 1412, 241, 4922, 1, 1290, + 4915, 4927, 1, 1280, 1, 246, 0, 566, 2596, 4935, 586, 4934, + 705, 4939, 586, 4935, 795, 4943, 2595, 4935, 587, 4946, 587, 4935, + 2595, 4950, 0, 1086, 375, 4955, 0, 922, 1759, 4959, 2265, 4959, + 3367, 4959, 4421, 4959, 1953, 4959, 1, 566, 5, 4971, 6, 4973, + 1950, 4971, 1949, 4971, 9, 4978, 586, 4970, 586, 4971, 587, 4970, + 4985, 4987, 4827, 4971, 9, 4971, 1949, 4992, 4745, 4971, 4569, 4971, + 587, 4971, 4983, 5001, 1, 1086, 9, 5005, 1, 922, 3369, 5009, + 555, 5009, 257, 5009, 1, 932, 0, 88, 3171, 5019, 10, 5018, + 101, 5023, 101, 5019, 10, 5019, 107, 5029, 0, 934, 375, 5033, + 0, 1108, 587, 5037, 1, 1362, 265, 5041, 1, 88, 93, 5045, + 1643, 5047, 93, 5044, 1645, 5051, 1645, 5045, 2135, 5045, 973, 5044, + 4745, 5059, 3163, 5045, 3173, 5045, 3167, 5045, 7, 5044, 10, 5044, + 10, 5045, 11, 5044, 3807, 5075, 5073, 5075, 33, 5045, 21, 5045, + 973, 5045, 4805, 5085, 3807, 5045, 4279, 5045, 4283, 5045, 4745, 5045, + 11, 5045, 5071, 5097, 1, 1304, 1, 1108, 973, 5103, 972, 5102, + 5105, 5107, 972, 5103, 973, 5102, 5111, 5113, 257, 5103, 0, 260, + 0, 580, 0, 136, 0, 668, 1, 260, 4139, 5127, 4138, 5127, + 264, 5126, 5131, 5133, 264, 5127, 4137, 5137, 265, 5126, 4137, 5141, + 5137, 5142, 5129, 5141, 5138, 5141, 5137, 5141, 4137, 5150, 265, 5127, + 4137, 5154, 5133, 5157, 5133, 5155, 4137, 5161, 4137, 5127, 265, 5165, + 5137, 5167, 265, 5164, 5133, 5171, 1, 580, 1, 136, 5019, 5177, + 1, 524, 5125, 5181, 1, 296, 5019, 5185, 0, 1413, 2559, 5189, + 2209, 5189, 4925, 5189, 0, 1419, 5181, 5197, 1, 295, 973, 5201, + 972, 5201, 49, 5201, 48, 5201, 972, 5200, 5203, 5211, 973, 5200, + 5205, 5215, 48, 5200, 5207, 5219, 49, 5200, 5209, 5223, 1, 1413, + 1417, 5227, 1, 1291, 5125, 5231, 5197, 5231, 0, 1087, 375, 5237, + 0, 923, 1793, 5241, 2941, 5241, 5012, 5241, 3543, 5241, 3559, 5241, + 2891, 5241, 5017, 5241, 1955, 5241, 555, 5241, 5009, 5258, 5009, 5241, + 555, 5262, 1, 1087, 5037, 5267, 1, 923, 555, 5270, 4959, 5273, + 241, 5270, 4959, 5277, 4959, 5271, 555, 5281, 1, 933, 4959, 5285, + 0, 935, 375, 5289, 0, 1109, 5005, 5293, 1, 935, 0, 669, + 4927, 5299, 1, 525, 4915, 5303, 5299, 5303, 1, 669, 1, 297, + 0, 341, 483, 5313, 3747, 5313, 3689, 5313, 3345, 5313, 4415, 5313, + 0, 257, 2255, 5325, 4888, 5325, 4881, 5325, 3467, 5325, 2919, 5325, + 4871, 5325, 4893, 5336, 4894, 5325, 7, 5324, 4863, 5343, 4872, 5325, + 4879, 5347, 4869, 5325, 4893, 5325, 4871, 5352, 5343, 5353, 3, 5325, + 5, 5358, 4862, 5360, 4863, 5361, 5363, 5365, 5343, 5364, 4862, 5361, + 4863, 5360, 5371, 5373, 5344, 5361, 5343, 5361, 4863, 5378, 5, 5325, + 3, 5382, 4862, 5384, 4863, 5385, 5387, 5389, 5343, 5388, 4862, 5385, + 4863, 5384, 5395, 5397, 5344, 5385, 5343, 5385, 4863, 5402, 264, 5325, + 4863, 5406, 4879, 5409, 5344, 5407, 5343, 5407, 4863, 5414, 4863, 5407, + 4871, 5419, 5343, 5418, 7, 5325, 265, 5425, 4863, 5427, 266, 5325, + 375, 5325, 4863, 5432, 510, 5325, 483, 5325, 9, 5438, 9, 5325, + 483, 5442, 251, 5325, 265, 5446, 265, 5447, 4892, 5325, 265, 5325, + 257, 5454, 1, 5457, 7, 5455, 5459, 5461, 0, 5461, 5457, 5465, + 251, 5454, 4863, 5454, 4863, 5325, 3, 5472, 5, 5474, 5, 5472, + 3, 5478, 375, 5472, 7, 5473, 5361, 5485, 5385, 5485, 5477, 5485, + 5481, 5485, 5407, 5485, 264, 5472, 4879, 5497, 5485, 5497, 264, 5473, + 4893, 5503, 265, 5472, 265, 5324, 4417, 5509, 251, 5509, 1, 341, + 5325, 5515, 331, 5514, 1, 257, 445, 5521, 265, 5522, 449, 5521, + 448, 5521, 414, 5521, 415, 5521, 421, 5521, 420, 5521, 253, 5521, + 265, 5538, 340, 5521, 341, 5521, 272, 5520, 241, 5546, 273, 5521, + 5549, 5551, 272, 5521, 273, 5520, 412, 5521, 251, 5559, 241, 5520, + 265, 5562, 5551, 5565, 272, 5563, 5557, 5569, 500, 5521, 432, 5521, + 501, 5521, 413, 5520, 5525, 5579, 5529, 5579, 5533, 5579, 5535, 5579, + 5555, 5579, 5541, 5579, 251, 5579, 5559, 5592, 5560, 5579, 5559, 5579, + 251, 5598, 5577, 5579, 433, 5521, 5579, 5605, 264, 5520, 5543, 5609, + 367, 5609, 264, 5521, 299, 5615, 412, 5520, 5527, 5619, 5531, 5619, + 5537, 5619, 5551, 5619, 5573, 5619, 5575, 5619, 413, 5521, 375, 5632, + 5619, 5635, 251, 5632, 5619, 5639, 5619, 5633, 251, 5643, 483, 5632, + 5619, 5647, 9, 5632, 5619, 5651, 7, 5521, 265, 5654, 5609, 5657, + 265, 5655, 5615, 5661, 2227, 5521, 375, 5665, 4841, 5521, 375, 5669, + 375, 5520, 2227, 5673, 4841, 5673, 4827, 5673, 375, 5521, 413, 5680, + 5619, 5683, 413, 5681, 5559, 5687, 483, 5521, 413, 5690, 5619, 5693, + 413, 5691, 5559, 5697, 9, 5521, 413, 5700, 5619, 5703, 413, 5701, + 5559, 5707, 251, 5521, 413, 5710, 5619, 5713, 413, 5711, 5559, 5717, + 265, 5521, 445, 5720, 5579, 5723, 253, 5720, 5579, 5727, 7, 5720, + 5609, 5731, 4827, 5521, 3, 5735, 5, 5736, 5, 5735, 3, 5740, + 375, 5735, 7, 5734, 5739, 5747, 5743, 5747, 264, 5735, 5747, 5753, + 265, 5735, 265, 5520, 2647, 5759, 5545, 5759, 1783, 5759, 241, 5758, + 5551, 5767, 0, 1171, 4714, 5771, 4716, 5771, 4720, 5771, 4724, 5771, + 2850, 5771, 1413, 5771, 4713, 5782, 922, 5771, 4713, 5786, 4718, 5771, + 903, 5790, 2849, 5771, 903, 5794, 483, 5771, 4722, 5798, 903, 5798, + 4713, 5802, 4713, 5798, 903, 5806, 4722, 5771, 483, 5810, 903, 5771, + 4718, 5814, 2849, 5814, 483, 5814, 4713, 5820, 4713, 5814, 483, 5824, + 4713, 5771, 1413, 5828, 922, 5828, 483, 5828, 903, 5834, 903, 5828, + 483, 5838, 0, 973, 1895, 5843, 2037, 5843, 1597, 5843, 1601, 5843, + 2142, 5843, 2313, 5843, 4810, 5843, 1715, 5843, 1771, 5843, 1935, 5843, + 2140, 5843, 2139, 5843, 955, 5866, 9, 5866, 375, 5843, 4805, 5872, + 483, 5843, 9, 5843, 2139, 5878, 955, 5843, 2139, 5882, 1011, 5843, + 4805, 5843, 375, 5888, 1, 1171, 3, 5892, 4663, 5895, 903, 5897, + 483, 5892, 4663, 5901, 903, 5903, 4663, 5893, 1413, 5907, 922, 5907, + 483, 5907, 903, 5912, 903, 5907, 483, 5916, 1, 973, 956, 5920, + 4745, 5923, 88, 5920, 4745, 5927, 5, 5920, 4745, 5931, 1011, 5933, + 3, 5920, 955, 5936, 4745, 5939, 9, 5936, 4745, 5943, 4745, 5937, + 955, 5947, 9, 5947, 375, 5920, 4745, 5953, 955, 5920, 3, 5956, + 4745, 5959, 5325, 5921, 9, 5920, 3, 5964, 4745, 5967, 4745, 5921, + 375, 5971, 0, 767, 903, 5974, 4617, 5977, 483, 5979, 4617, 5975, + 1413, 5983, 922, 5983, 903, 5983, 483, 5988, 483, 5983, 903, 5992, + 0, 567, 4989, 5997, 4983, 5997, 5001, 6000, 5002, 5997, 4984, 5997, + 4987, 6007, 5001, 5997, 4983, 6010, 3, 5997, 7, 6014, 4970, 6016, + 4971, 6017, 6019, 6021, 4970, 6017, 4971, 6016, 6025, 6027, 7, 5997, + 3, 6030, 4970, 6032, 4971, 6033, 6035, 6037, 4970, 6033, 4971, 6032, + 6041, 6043, 3, 5996, 7, 6047, 2, 5996, 4992, 6051, 6015, 6051, + 7, 6055, 4971, 6057, 9, 6051, 4971, 6060, 4971, 6051, 9, 6064, + 586, 5997, 4971, 6068, 4987, 6071, 4971, 6069, 4983, 6075, 2, 5997, + 6048, 6079, 4971, 6081, 7, 6079, 6047, 6084, 4971, 6087, 4971, 6085, + 6047, 6091, 6047, 6079, 7, 6094, 4971, 6097, 4992, 5997, 587, 6101, + 2839, 5997, 587, 6105, 9, 5997, 4971, 6108, 587, 6111, 4971, 5997, + 2, 6115, 7, 6117, 4975, 6117, 586, 6114, 4987, 6123, 5, 6114, + 6, 6127, 6117, 6129, 6119, 6127, 586, 6115, 5001, 6135, 9, 6114, + 587, 6139, 587, 6115, 9, 6143, 0, 67, 4636, 6147, 37, 6147, + 3008, 6147, 4656, 6147, 4650, 6147, 7, 6146, 4643, 6159, 2233, 6159, + 4625, 6159, 9, 6165, 5, 6147, 6, 6169, 36, 6147, 4625, 6172, + 3807, 6173, 4648, 6147, 9, 6178, 3003, 6147, 9, 6182, 33, 6146, + 6151, 6187, 3856, 6187, 3837, 6187, 9, 6192, 9, 6187, 3837, 6196, + 33, 6147, 4652, 6200, 3807, 6201, 9, 6205, 9, 6200, 4625, 6208, + 3807, 6209, 4625, 6200, 9, 6214, 4652, 6147, 33, 6218, 9, 6147, + 4648, 6222, 3003, 6222, 33, 6222, 4625, 6228, 3807, 6229, 33, 6223, + 3837, 6235, 4625, 6222, 33, 6238, 4625, 6147, 75, 6243, 4629, 6243, + 7, 6243, 4627, 6249, 6171, 6243, 375, 6243, 36, 6242, 33, 6242, + 9, 6258, 9, 6242, 33, 6262, 0, 89, 5079, 6267, 5071, 6267, + 5097, 6270, 5098, 6267, 5072, 6267, 5075, 6277, 5097, 6267, 5071, 6280, + 107, 6267, 5, 6267, 7, 6286, 5044, 6288, 5045, 6289, 6291, 6293, + 5044, 6289, 5045, 6288, 6297, 6299, 7, 6267, 5, 6302, 5044, 6304, + 5045, 6305, 6307, 6309, 5044, 6305, 5045, 6304, 6313, 6315, 5, 6266, + 7, 6318, 5045, 6321, 7, 6319, 7, 6266, 5, 6326, 5045, 6329, + 5075, 6327, 2221, 6327, 5045, 6327, 4, 6266, 6287, 6339, 7, 6341, + 5045, 6343, 10, 6266, 5075, 6347, 2221, 6347, 5045, 6347, 10, 6267, + 5097, 6355, 5045, 6354, 5075, 6359, 5045, 6355, 5071, 6363, 1274, 6267, + 4, 6267, 6324, 6369, 5045, 6371, 7, 6369, 6319, 6374, 5045, 6377, + 5044, 6374, 5045, 6375, 6319, 6383, 6381, 6383, 5044, 6375, 5045, 6374, + 6389, 6391, 6319, 6369, 7, 6394, 5045, 6397, 6, 6267, 3, 6400, + 3, 6267, 6, 6404, 21, 6267, 11, 6409, 5045, 6411, 5045, 6267, + 10, 6414, 5075, 6417, 10, 6415, 5097, 6421, 5311, 6267, 11, 6266, + 2969, 6427, 5082, 6427, 5045, 6427, 21, 6432, 21, 6427, 5045, 6436, + 1, 767, 4580, 6441, 4582, 6441, 4586, 6441, 4590, 6441, 2862, 6441, + 1413, 6441, 4579, 6452, 922, 6441, 4579, 6456, 4584, 6441, 483, 6460, + 2861, 6441, 483, 6464, 759, 6440, 903, 6441, 4588, 6470, 483, 6470, + 4579, 6474, 4579, 6470, 483, 6478, 4588, 6441, 903, 6482, 483, 6441, + 4584, 6486, 2861, 6486, 903, 6486, 4579, 6492, 4579, 6486, 903, 6496, + 4579, 6441, 1413, 6500, 922, 6500, 903, 6500, 483, 6506, 483, 6500, + 903, 6510, 1, 567, 5, 6514, 6, 6517, 4935, 6517, 2137, 6515, + 9, 6523, 14, 6515, 2, 6515, 563, 6529, 4935, 6531, 6519, 6529, + 4935, 6535, 7, 6529, 6520, 6539, 4935, 6539, 6517, 6542, 6517, 6539, + 4935, 6546, 1197, 6529, 4935, 6551, 6, 6515, 5, 6554, 5, 6515, + 6, 6558, 5325, 6515, 903, 6515, 9, 6514, 4950, 6567, 587, 6567, + 4935, 6570, 4935, 6567, 587, 6574, 241, 6515, 4950, 6515, 9, 6581, + 587, 6515, 9, 6585, 4935, 6587, 4935, 6584, 9, 6591, 4935, 6515, + 2, 6594, 7, 6597, 5, 6595, 6539, 6601, 6599, 6601, 6, 6601, + 6597, 6607, 9, 6595, 587, 6611, 587, 6594, 9, 6615, 5843, 6515, + 5313, 6515, 587, 6514, 1, 67, 4594, 6625, 4606, 6625, 3280, 6625, + 75, 6625, 4593, 6632, 2146, 6625, 2145, 6625, 9, 6638, 7, 6625, + 73, 6643, 4593, 6645, 375, 6625, 4593, 6648, 33, 6624, 4593, 6653, + 9, 6655, 9, 6625, 3273, 6658, 2145, 6658, 4593, 6625, 75, 6664, + 375, 6664, 36, 6665, 33, 6665, 9, 6672, 9, 6665, 33, 6676, + 3273, 6625, 9, 6680, 1, 89, 1657, 6685, 25, 6685, 3565, 6685, + 3573, 6685, 3273, 6685, 21, 6684, 483, 6685, 5843, 6685, 11, 6684, + 0, 1487, 10, 6705, 7, 6705, 5, 6708, 5, 6705, 7, 6712, + 0, 1347, 0, 113, 2149, 6719, 9, 6721, 4736, 6719, 9, 6725, + 3023, 6719, 9, 6729, 4740, 6719, 9, 6733, 2879, 6719, 9, 6737, + 587, 6719, 4727, 6740, 9, 6743, 25, 6719, 4727, 6746, 9, 6749, + 4727, 6719, 5, 6753, 6, 6755, 4731, 6755, 2, 6752, 7, 6761, + 6755, 6763, 6757, 6761, 25, 6752, 9, 6769, 587, 6752, 9, 6773, + 9, 6753, 25, 6777, 587, 6777, 3255, 6719, 9, 6783, 0, 137, + 1, 113, 31, 6788, 2, 6788, 7, 6793, 4669, 6793, 4697, 6789, + 14, 6788, 6, 6789, 6, 6788, 5, 6804, 11, 6788, 5, 6808, + 5, 6788, 6, 6813, 6, 6812, 4696, 6813, 9, 6813, 4669, 6820, + 4669, 6813, 9, 6824, 7, 6788, 6815, 6829, 15, 6788, 6803, 6833, + 8, 6788, 8, 6789, 4669, 6839, 1368, 6789, 5, 6789, 35, 6845, + 4669, 6847, 6795, 6845, 4669, 6851, 6, 6845, 6796, 6855, 4669, 6855, + 6793, 6858, 6793, 6855, 4669, 6862, 1171, 6845, 4669, 6867, 17, 6845, + 4669, 6871, 7, 6789, 6811, 6875, 6807, 6875, 6817, 6875, 6801, 6875, + 2, 6874, 2, 6789, 7, 6886, 30, 6788, 3867, 6891, 25, 6788, + 4696, 6895, 3867, 6895, 9, 6899, 9, 6894, 3867, 6903, 4669, 6895, + 9, 6906, 9, 6895, 4669, 6910, 587, 6788, 4696, 6915, 9, 6915, + 4669, 6918, 4669, 6915, 9, 6922, 25, 6789, 4473, 6927, 6791, 6927, + 3972, 6927, 3933, 6927, 9, 6934, 9, 6927, 3933, 6938, 4696, 6789, + 6837, 6943, 25, 6943, 587, 6943, 9, 6789, 6837, 6951, 4669, 6953, + 587, 6951, 4669, 6957, 25, 6951, 4669, 6961, 4669, 6950, 25, 6965, + 6837, 6965, 587, 6965, 4669, 6789, 5, 6972, 6, 6975, 2, 6973, + 6855, 6979, 6977, 6979, 7, 6979, 6975, 6985, 25, 6973, 9, 6989, + 587, 6973, 9, 6993, 9, 6972, 6837, 6997, 25, 6997, 587, 6997, + 9, 6973, 6839, 7005, 9, 6788, 6799, 7009, 6840, 7009, 6839, 7009, + 4669, 7014, 4669, 7009, 6839, 7018, 25, 7008, 3867, 7023, 25, 7009, + 3933, 7027, 1, 137, 6267, 7031, 0, 375, 413, 7034, 413, 7035, + 241, 7034, 3307, 7041, 2885, 7041, 0, 261, 0, 803, 16, 7049, + 7, 7049, 4, 7052, 4, 7049, 7, 7056, 0, 581, 0, 145, + 1, 375, 317, 7064, 265, 7065, 256, 7068, 256, 7069, 4901, 7065, + 4, 7065, 2, 7077, 265, 7077, 2, 7076, 4899, 7083, 2, 7065, + 265, 7087, 4, 7086, 4899, 7091, 2, 7064, 265, 7064, 3, 7064, + 7084, 7099, 7092, 7099, 7083, 7099, 4899, 7104, 7091, 7099, 4899, 7108, + 7075, 7099, 4899, 7099, 7083, 7114, 7091, 7114, 240, 7064, 240, 7065, + 265, 7123, 7, 7125, 7114, 7123, 7099, 7123, 4899, 7130, 4899, 7123, + 7099, 7134, 413, 7065, 7, 7138, 3, 7065, 7079, 7143, 4899, 7145, + 7081, 7143, 4899, 7149, 5, 7065, 7089, 7153, 4899, 7155, 445, 7065, + 4349, 7159, 7121, 7159, 367, 7065, 4863, 7165, 973, 7065, 4805, 7169, + 316, 7064, 4067, 7173, 973, 7064, 4745, 7177, 445, 7064, 4371, 7181, + 257, 7064, 4841, 7185, 2227, 7185, 4827, 7185, 7071, 7185, 305, 7064, + 4067, 7195, 241, 7197, 241, 7194, 4067, 7201, 587, 7064, 257, 7065, + 4863, 7207, 7073, 7207, 628, 7065, 587, 7065, 11, 7214, 11, 7065, + 587, 7218, 241, 7219, 305, 7065, 4497, 7225, 7067, 7225, 4254, 7225, + 4213, 7225, 241, 7232, 241, 7225, 4213, 7236, 4900, 7065, 7121, 7241, + 7095, 7241, 7097, 7241, 241, 7065, 7095, 7249, 4899, 7251, 7097, 7249, + 4899, 7255, 6, 7249, 7121, 7249, 4899, 7261, 4899, 7248, 7121, 7265, + 7095, 7265, 7097, 7265, 4899, 7065, 241, 7272, 7121, 7275, 7095, 7275, + 7097, 7275, 241, 7273, 7123, 7283, 241, 7064, 4371, 7287, 7141, 7287, + 7127, 7287, 7075, 7287, 7134, 7287, 7123, 7287, 4899, 7298, 4899, 7287, + 7123, 7302, 305, 7286, 4067, 7307, 305, 7287, 4213, 7311, 1, 261, + 413, 7315, 3357, 7315, 264, 7319, 265, 7318, 7321, 7323, 264, 7318, + 265, 7319, 7327, 7329, 1, 803, 737, 7332, 4799, 7333, 1274, 7332, + 6, 7333, 2, 7341, 2, 7340, 4787, 7345, 2, 7333, 6, 7348, + 4787, 7351, 2, 7332, 6, 7332, 3, 7356, 587, 7332, 3, 7360, + 3, 7332, 7346, 7365, 7352, 7365, 7345, 7365, 4787, 7370, 7351, 7365, + 4787, 7374, 6, 7365, 6, 7364, 7337, 7365, 4787, 7365, 7345, 7384, + 7351, 7384, 7, 7332, 7379, 7391, 1275, 7332, 7341, 7395, 482, 7332, + 482, 7333, 7384, 7401, 7365, 7401, 4787, 7404, 4787, 7401, 7365, 7408, + 3, 7333, 7343, 7413, 4787, 7415, 7, 7333, 7363, 7419, 7359, 7419, + 7381, 7419, 7339, 7419, 736, 7332, 3997, 7429, 713, 7332, 3997, 7433, + 483, 7435, 483, 7432, 3997, 7439, 11, 7333, 483, 7443, 713, 7333, + 4485, 7447, 7335, 7447, 4188, 7447, 4147, 7447, 483, 7454, 483, 7447, + 4147, 7458, 4798, 7333, 7399, 7463, 7355, 7463, 483, 7333, 7355, 7469, + 4787, 7471, 7399, 7469, 4787, 7475, 4787, 7468, 7399, 7479, 7355, 7479, + 4787, 7333, 483, 7484, 7399, 7487, 7355, 7487, 483, 7485, 7401, 7493, + 483, 7332, 7337, 7497, 7408, 7497, 7401, 7497, 4787, 7502, 4787, 7497, + 7401, 7506, 713, 7496, 3997, 7511, 713, 7497, 4147, 7515, 1, 145, + 586, 7519, 7, 7519, 3, 7522, 3, 7519, 7, 7526, 1, 155, + 483, 7530, 0, 175, 482, 7535, 6, 7535, 2, 7538, 2, 7535, + 6, 7542, 1, 1505, 1011, 7546, 6, 7549, 7, 7549, 6, 7548, + 7553, 7555, 7, 7548, 7551, 7559, 1, 1363, 8, 7563, 6, 7563, + 4, 7566, 4, 7563, 6, 7570, 1374, 7563, 4423, 7575, 1374, 7562, + 4431, 7579, 265, 7562, 5189, 7583, 1, 165, 903, 7586, 6, 7589, + 7, 7589, 6, 7588, 7593, 7595, 7, 7588, 7591, 7599, 1, 175, + 44, 7602, 45, 7603, 7605, 7607, 44, 7603, 45, 7602, 7611, 7613, + 0, 299, 3289, 7617, 2181, 7617, 3307, 7617, 2885, 7617, 1, 299, + 4371, 7627, 2801, 7627, 1669, 7627, 5461, 7627, 3295, 7627, 305, 7626, + 4067, 7639, 251, 7627, 305, 7627, 4213, 7645, 0, 705, 3371, 7649, + 2183, 7649, 0, 101, 3157, 7655, 2185, 7655, 3175, 7655, 6697, 7655, + 3037, 7655, 6685, 7655, 21, 7667, 1, 705, 3377, 7671, 713, 7670, + 3997, 7675, 555, 7671, 713, 7671, 4147, 7681, 1, 101, 3163, 7685, + 25, 7684, 3867, 7689, 21, 7685, 25, 7685, 3933, 7695, 0, 129, + 2253, 7699, 21, 7699, 1, 129, 21, 7704, 0, 395, 2247, 7709, + 4417, 7709, 265, 7709, 7, 7715, 251, 7709, 0, 829, 2251, 7721, + 555, 7721, 1, 395, 2647, 7727, 1719, 7727, 251, 7726, 1, 829, + 555, 7734, 0, 298, 265, 7739, 7, 7741, 7627, 7743, 2551, 7739, + 7642, 7739, 4417, 7739, 7627, 7739, 251, 7752, 251, 7739, 7627, 7756, + 1, 298, 2647, 7761, 1783, 7761, 251, 7760, 7617, 7767, 7617, 7761, + 251, 7771, 0, 704, 2555, 7775, 7678, 7775, 7671, 7775, 555, 7780, + 555, 7775, 7671, 7784, 0, 100, 2557, 7789, 7692, 7789, 2969, 7789, + 5082, 7789, 5045, 7789, 21, 7798, 7685, 7789, 21, 7802, 21, 7789, + 7685, 7806, 5045, 7806, 1, 704, 555, 7812, 7649, 7815, 7649, 7813, + 555, 7819, 1, 100, 21, 7822, 7655, 7825, 7655, 7823, 21, 7829, + 0, 128, 3159, 7833, 2197, 7833, 7707, 7833, 7705, 7833, 21, 7841, + 1, 128, 3161, 7845, 7702, 7845, 25, 7844, 3867, 7851, 21, 7845, + 7699, 7854, 7699, 7845, 21, 7858, 25, 7845, 3933, 7863, 0, 394, + 3291, 7867, 2193, 7867, 7733, 7867, 2885, 7867, 3307, 7867, 7727, 7867, + 251, 7879, 0, 828, 3373, 7883, 2195, 7883, 7737, 7883, 7735, 7883, + 555, 7891, 1, 394, 4371, 7895, 3293, 7895, 7718, 7895, 1721, 7895, + 1725, 7895, 7717, 7895, 305, 7894, 4067, 7909, 251, 7895, 7709, 7912, + 7709, 7895, 251, 7916, 305, 7895, 4213, 7921, 1, 828, 3375, 7925, + 7724, 7925, 713, 7924, 3997, 7931, 555, 7925, 7721, 7934, 7721, 7925, + 555, 7938, 713, 7925, 4147, 7943, 0, 8, 6, 7947, 3, 7948, + 1274, 7947, 113, 7947, 3, 7947, 0, 7957, 6, 7956, 0, 7956, + 9, 7963, 11, 7957, 587, 7947, 1, 10, 5081, 7971, 5026, 7971, + 7, 7971, 2, 7976, 1368, 7971, 5097, 7971, 931, 7971, 1417, 7971, + 939, 7971, 941, 7971, 272, 7971, 1476, 7971, 280, 7971, 949, 7971, + 1517, 7971, 4696, 7971, 149, 7971, 631, 7971, 970, 7971, 50, 7971, + 764, 7971, 357, 7971, 367, 7971, 471, 7971, 1249, 7971, 5019, 7971, + 101, 8022, 128, 7971, 101, 7971, 5019, 8028, 4669, 7971, 9, 8032, + 759, 7971, 33, 8036, 1471, 7971, 265, 8040, 959, 7971, 33, 8044, + 253, 7971, 265, 8048, 113, 7971, 9, 8052, 375, 7971, 88, 7971, + 89, 7971, 2, 7971, 1, 8063, 7, 8062, 1, 8062, 11, 8069, + 9, 8063, 3, 7971, 9, 8074, 33, 7971, 959, 8078, 47, 8078, + 759, 8078, 25, 7971, 305, 7971, 713, 7971, 2, 7970, 8059, 8093, + 8077, 8093, 8075, 8093, 9, 8099, 3867, 8093, 3997, 8093, 4067, 8093, + 3, 7970, 4696, 8109, 8061, 8109, 8072, 8109, 8063, 8109, 9, 8116, + 4669, 8109, 9, 8120, 9, 8109, 4669, 8124, 8063, 8124, 47, 7971, + 33, 8130, 53, 7971, 265, 8134, 265, 7971, 253, 8138, 1471, 8138, + 53, 8138, 587, 7971, 483, 7971, 9, 7971, 4669, 8150, 113, 8150, + 3, 8150, 8093, 8157, 3, 8151, 8063, 8161, 0, 10, 203, 8165, + 107, 8165, 5019, 8169, 85, 8165, 2215, 8165, 2221, 8165, 2233, 8165, + 5075, 8165, 4643, 8165, 5045, 8165, 25, 8185, 4551, 8165, 922, 8165, + 1413, 8165, 273, 8165, 281, 8165, 1477, 8165, 1516, 8165, 948, 8165, + 4625, 8165, 9, 8205, 759, 8165, 959, 8165, 67, 8165, 9, 8213, + 1505, 8165, 1011, 8216, 88, 8165, 33, 8221, 89, 8165, 5019, 8225, + 3, 8165, 33, 8229, 9, 8231, 8063, 8229, 9, 8228, 33, 8237, + 2, 8165, 9, 8241, 33, 8165, 1141, 8165, 1447, 8165, 2, 8164, + 2215, 8251, 2221, 8251, 5075, 8251, 2233, 8251, 4643, 8251, 8229, 8251, + 4625, 8251, 9, 8265, 4295, 8251, 3833, 8251, 4321, 8251, 5045, 8251, + 3, 8164, 8241, 8277, 8093, 8277, 3837, 8277, 4287, 8277, 4303, 8277, + 128, 8277, 101, 8277, 113, 8277, 9, 8292, 9, 8277, 113, 8296, + 47, 8165, 165, 8165, 903, 8302, 265, 8165, 587, 8165, 1011, 8165, + 1505, 8310, 1369, 8165, 483, 8165, 903, 8316, 903, 8165, 483, 8320, + 165, 8320, 9, 8165, 3, 8326, 33, 8329, 3, 8327, 113, 8333, + 0, 240, 4266, 8337, 4888, 8337, 4892, 8337, 4213, 8337, 375, 8344, + 4863, 8337, 375, 8348, 265, 8348, 261, 8337, 3335, 8337, 375, 8357, + 347, 8337, 386, 8337, 331, 8337, 305, 8337, 375, 8366, 340, 8337, + 331, 8371, 375, 8337, 4213, 8374, 4863, 8374, 305, 8374, 1325, 8337, + 59, 8337, 7, 8337, 265, 8387, 4213, 8389, 4863, 8389, 305, 8389, + 265, 8386, 331, 8397, 7, 8336, 5141, 8401, 5137, 8402, 5137, 8401, + 5141, 8406, 5150, 8401, 5154, 8401, 5133, 8413, 5161, 8401, 5127, 8401, + 265, 8419, 5137, 8421, 265, 8418, 5133, 8425, 265, 8401, 5127, 8429, + 5141, 8431, 5127, 8428, 5133, 8435, 3785, 8401, 4329, 8401, 4311, 8401, + 483, 8337, 9, 8337, 1275, 8337, 15, 8337, 265, 8337, 4863, 8452, + 257, 8452, 1, 8457, 6, 8452, 1, 8461, 241, 8462, 241, 8461, + 1, 8466, 7, 8452, 331, 8471, 7, 8453, 7895, 8475, 7287, 8475, + 8465, 8475, 8469, 8475, 7627, 8475, 8459, 8475, 0, 8475, 8457, 8489, + 375, 8475, 1, 264, 3293, 8495, 7718, 8495, 3295, 8495, 3305, 8495, + 3301, 8495, 5512, 8495, 5451, 8495, 7756, 8495, 7091, 8495, 4899, 8512, + 7083, 8495, 4899, 8516, 7092, 8495, 7084, 8495, 4696, 8495, 7075, 8495, + 7123, 8495, 4899, 8528, 7134, 8495, 445, 8495, 4349, 8535, 8386, 8495, + 331, 8539, 471, 8495, 367, 8495, 357, 8495, 631, 8495, 1249, 8495, + 628, 8495, 8387, 8495, 8401, 8495, 4137, 8495, 3863, 8495, 4063, 8495, + 8475, 8495, 4371, 8495, 4549, 8495, 4545, 8495, 407, 8495, 1417, 8495, + 665, 8495, 338, 8495, 1480, 8495, 336, 8495, 4745, 8495, 4669, 8495, + 9, 8586, 4899, 8495, 7091, 8590, 7083, 8590, 7123, 8590, 4569, 8495, + 7709, 8495, 251, 8600, 341, 8495, 4863, 8605, 241, 8605, 253, 8495, + 331, 8610, 251, 8495, 7709, 8614, 5509, 8614, 7739, 8614, 256, 8495, + 375, 8623, 7739, 8495, 251, 8626, 5509, 8495, 251, 8630, 257, 8495, + 305, 8635, 53, 8495, 331, 8638, 1471, 8495, 331, 8642, 6, 8495, + 4349, 8647, 4497, 8647, 413, 8647, 4213, 8647, 8109, 8647, 4147, 8647, + 3933, 8647, 445, 8647, 316, 8647, 4713, 8647, 4863, 8647, 8337, 8647, + 305, 8647, 241, 8672, 241, 8647, 305, 8676, 587, 8647, 8387, 8647, + 7, 8495, 3785, 8685, 4329, 8685, 4311, 8685, 8337, 8684, 331, 8693, + 331, 8685, 8337, 8697, 15, 8685, 241, 8684, 375, 8703, 331, 8495, + 253, 8706, 1471, 8706, 53, 8706, 305, 8495, 6, 8494, 8539, 8717, + 8693, 8717, 4371, 8717, 8623, 8717, 8703, 8717, 8685, 8717, 8337, 8729, + 241, 8729, 471, 8717, 367, 8717, 357, 8717, 1369, 8717, 341, 8717, + 241, 8743, 4569, 8717, 4137, 8717, 4063, 8717, 3863, 8717, 8401, 8717, + 7, 8494, 8389, 8757, 8555, 8757, 8374, 8757, 8670, 8757, 8635, 8757, + 8676, 8757, 8647, 8757, 8337, 8770, 241, 8770, 8337, 8757, 8647, 8776, + 375, 8776, 9, 8757, 375, 8757, 8337, 8784, 241, 8757, 1, 8789, + 8647, 8791, 8647, 8788, 587, 8495, 11, 8796, 11, 8495, 587, 8800, + 9, 8495, 4669, 8804, 1369, 8495, 17, 8495, 241, 8495, 1, 8813, + 7, 8815, 8717, 8817, 7, 8814, 8647, 8821, 7, 8812, 8717, 8825, + 375, 8825, 7, 8813, 1, 8830, 8647, 8833, 8647, 8831, 331, 8831, + 6, 8813, 8337, 8495, 7, 8842, 8717, 8845, 331, 8845, 483, 8843, + 9, 8843, 7, 8843, 8647, 8855, 375, 8855, 0, 264, 3299, 8861, + 5431, 8861, 5469, 8861, 5449, 8861, 4888, 8861, 4863, 8861, 375, 8872, + 629, 8861, 394, 8861, 299, 8861, 659, 8861, 623, 8861, 645, 8861, + 101, 8861, 705, 8861, 128, 8861, 828, 8861, 3345, 8861, 3445, 8861, + 375, 8899, 2981, 8861, 3049, 8861, 7195, 8861, 3461, 8861, 4613, 8861, + 331, 8910, 4614, 8861, 375, 8861, 4863, 8916, 241, 8916, 803, 8861, + 483, 8922, 113, 8861, 9, 8926, 256, 8861, 331, 8931, 5455, 8861, + 251, 8935, 7, 8861, 331, 8939, 241, 8941, 241, 8938, 331, 8945, + 331, 8861, 4613, 8948, 7, 8860, 3837, 8953, 8093, 8953, 394, 8953, + 299, 8953, 375, 8953, 241, 8962, 4303, 8953, 4287, 8953, 241, 8953, + 375, 8970, 483, 8861, 803, 8974, 9, 8861, 113, 8978, 17, 8861, + 241, 8861, 375, 8984, 7, 8984, 331, 8989, 7, 8985, 375, 8993, + 1, 240, 3342, 8997, 2900, 8997, 8672, 8997, 8743, 8997, 3795, 8997, + 8770, 8997, 8729, 8997, 2658, 8997, 7159, 8997, 2703, 8997, 2660, 8997, + 413, 8997, 8757, 8997, 8647, 9022, 8684, 8997, 8717, 9027, 8605, 8997, + 457, 8997, 2647, 9032, 8647, 8997, 305, 9036, 8757, 9036, 8916, 8997, + 257, 8997, 2647, 8997, 375, 9046, 457, 9046, 3341, 8997, 375, 9052, + 2897, 8997, 375, 9056, 305, 8997, 8647, 9060, 340, 8997, 8717, 9065, + 3785, 9065, 8495, 9065, 375, 8997, 3341, 9072, 2897, 9072, 2647, 9072, + 8861, 9072, 7, 8997, 413, 9082, 0, 9085, 1, 9083, 264, 9088, + 264, 9089, 8495, 9082, 8717, 9095, 8495, 9083, 8757, 9099, 305, 9099, + 265, 9083, 2897, 9105, 3341, 9105, 2647, 9105, 9087, 9105, 1, 9105, + 9085, 9115, 9093, 9105, 8861, 9105, 265, 9082, 8717, 9123, 3785, 9123, + 9091, 9123, 8495, 9123, 483, 8997, 9, 8997, 265, 8997, 7, 9136, + 8717, 9139, 3785, 9139, 8495, 9139, 7, 9137, 8647, 9147, 8495, 8997, + 7, 9150, 8717, 9153, 7, 9151, 8647, 9157, 8861, 8997, 375, 9160, + 0, 482, 6, 9165, 4, 9167, 803, 9165, 5, 9165, 587, 9173, + 9, 9173, 5, 9164, 17, 9179, 19, 9165, 12, 9165, 9, 9165, + 11, 9186, 11, 9165, 9, 9190, 1, 586, 4795, 9195, 807, 9195, + 4787, 9198, 4788, 9195, 4790, 9195, 8374, 9195, 8389, 9195, 4797, 9195, + 8086, 9195, 8090, 9195, 8251, 9195, 4283, 9195, 4279, 9195, 3807, 9195, + 1491, 9195, 631, 9195, 1160, 9195, 1466, 9195, 764, 9195, 357, 9195, + 367, 9195, 471, 9195, 1249, 9195, 8800, 9195, 8647, 9195, 4787, 9195, + 807, 9246, 375, 9246, 33, 9195, 759, 9252, 1141, 9195, 759, 9256, + 803, 9195, 375, 9195, 4787, 9262, 8337, 9262, 8165, 9195, 265, 9269, + 566, 9195, 567, 9195, 7971, 9195, 25, 9276, 713, 9276, 8495, 9195, + 11, 9282, 4, 9195, 483, 9287, 5, 9195, 17, 9291, 483, 9290, + 759, 9195, 1141, 9296, 1447, 9296, 33, 9296, 713, 9195, 7971, 9304, + 25, 9195, 7971, 9308, 8337, 9195, 375, 9312, 4, 9194, 9273, 9317, + 9295, 9317, 9291, 9317, 483, 9323, 4279, 9317, 3807, 9317, 4283, 9317, + 8251, 9317, 5, 9194, 9275, 9335, 9288, 9335, 9287, 9335, 483, 9340, + 8647, 9335, 9, 9335, 483, 9335, 9287, 9348, 1447, 9195, 759, 9352, + 11, 9195, 8495, 9357, 8495, 9356, 9, 9195, 1011, 9195, 483, 9195, + 5, 9366, 9317, 9369, 5, 9367, 9287, 9373, 0, 586, 7, 9377, + 4, 9378, 16, 9377, 8800, 9377, 273, 9377, 1477, 9377, 281, 9377, + 948, 9377, 1516, 9377, 750, 9377, 386, 9377, 347, 9377, 510, 9377, + 767, 9377, 375, 9377, 305, 9406, 713, 9406, 165, 9377, 903, 9412, + 8495, 9377, 11, 9416, 566, 9377, 759, 9421, 5, 9377, 759, 9425, + 483, 9427, 483, 9424, 759, 9431, 4, 9377, 0, 9435, 7, 9434, + 0, 9434, 587, 9441, 713, 9435, 713, 9377, 375, 9446, 305, 9377, + 375, 9450, 4, 9376, 767, 9455, 5, 9376, 3837, 9459, 8093, 9459, + 828, 9459, 705, 9459, 803, 9459, 483, 9468, 4287, 9459, 4303, 9459, + 483, 9459, 803, 9476, 1505, 9377, 1011, 9480, 11, 9377, 8495, 9484, + 903, 9377, 165, 9488, 9, 9377, 483, 9492, 1011, 9377, 1505, 9496, + 483, 9377, 9, 9500, 5, 9500, 759, 9505, 5, 9501, 803, 9509, + 1, 482, 6, 9513, 5, 9514, 14, 9513, 5, 9513, 1, 9521, + 6, 9520, 1, 9520, 483, 9527, 11, 9513, 0, 902, 524, 9533, + 1291, 9533, 767, 9533, 7, 9533, 3, 9541, 305, 9533, 375, 9544, + 386, 9533, 347, 9533, 375, 9533, 305, 9552, 483, 9533, 11, 9556, + 11, 9533, 483, 9560, 1, 1010, 5038, 9565, 5037, 9565, 587, 9568, + 668, 9565, 1419, 9565, 8982, 9565, 7, 9564, 3867, 9579, 8277, 9579, + 9459, 9579, 8953, 9579, 4067, 9579, 3997, 9579, 375, 9565, 483, 9565, + 9, 9565, 587, 9596, 587, 9565, 5037, 9600, 9, 9600, 17, 9565, + 8861, 9606, 8861, 9565, 7, 9611, 17, 9610, 0, 1010, 9535, 9617, + 9537, 9617, 9559, 9617, 9563, 9617, 5, 9617, 6, 9627, 7, 9627, + 5006, 9617, 5005, 9617, 9, 9634, 9362, 9617, 1290, 9617, 9533, 9641, + 525, 9617, 9533, 9645, 8804, 9617, 8150, 9617, 922, 9617, 1413, 9617, + 7971, 9617, 9, 9656, 6, 9617, 11, 9661, 9195, 9617, 9, 9664, + 6, 9616, 17, 9669, 7, 9616, 9195, 9673, 9317, 9673, 4321, 9673, + 3833, 9673, 4295, 9673, 5045, 9673, 19, 9617, 12, 9617, 11, 9617, + 9, 9690, 483, 9617, 903, 9694, 1275, 9617, 17, 9698, 9533, 9701, + 9, 9617, 5005, 9704, 9195, 9704, 7971, 9704, 8495, 9704, 11, 9704, + 17, 9617, 1275, 9716, 9533, 9719, 903, 9617, 483, 9722, 8495, 9617, + 9, 9726, 1, 902, 9573, 9731, 9575, 9731, 9599, 9731, 9605, 9731, + 1418, 9731, 9565, 9741, 669, 9731, 9565, 9745, 8386, 9731, 7, 9731, + 8337, 9750, 7, 9730, 9673, 9755, 8251, 9755, 4283, 9755, 3807, 9755, + 4279, 9755, 483, 9731, 15, 9731, 1369, 9768, 9565, 9771, 1369, 9731, + 15, 9774, 9565, 9777, 1011, 9731, 8337, 9731, 7, 9782, 9617, 9731, + 6, 9786, 7, 9786, 6, 9787, 9791, 9793, 7, 9787, 9789, 9797, + 0, 1274, 5, 9801, 1, 1368, 4904, 9805, 4903, 9805, 9, 9808, + 9484, 9805, 1517, 9805, 1476, 9805, 272, 9805, 280, 9805, 949, 9805, + 1197, 9805, 1471, 9805, 265, 9826, 253, 9805, 265, 9830, 53, 9805, + 265, 9834, 5, 9804, 3867, 9839, 8277, 9839, 8953, 9839, 9459, 9839, + 3997, 9839, 4067, 9839, 11, 9805, 9377, 9852, 9, 9805, 4903, 9856, + 265, 9805, 1471, 9860, 253, 9860, 53, 9860, 9377, 9805, 11, 9868, + 5, 9869, 0, 1368, 5075, 9875, 2221, 9875, 4643, 9875, 2233, 9875, + 2215, 9875, 4339, 9875, 7, 9875, 5, 9888, 4, 9889, 10, 9875, + 8714, 9875, 8800, 9875, 4625, 9875, 9, 9901, 47, 9875, 305, 9875, + 8495, 9906, 959, 9875, 5045, 9875, 4551, 9875, 1325, 9875, 59, 9875, + 331, 9875, 5, 9875, 0, 9923, 7, 9922, 0, 9922, 1369, 9929, + 9287, 9923, 4, 9875, 1011, 9935, 8495, 9875, 10, 9938, 10, 9939, + 305, 9938, 11, 9938, 9943, 9947, 11, 9939, 9941, 9951, 4, 9874, + 8495, 9955, 8717, 9955, 4329, 9955, 4311, 9955, 3785, 9955, 5, 9874, + 9195, 9967, 9755, 9967, 9317, 9967, 3833, 9967, 4295, 9967, 4321, 9967, + 5045, 9967, 759, 9875, 11, 9875, 8495, 9984, 17, 9875, 903, 9875, + 265, 9875, 15, 9875, 9195, 9875, 241, 9997, 1, 1274, 6,10001, + 4,10002, 4,10003, 8,10001, 5123,10001, 5,10011, 4,10010, +10013,10015, 4,10011, 5,10010,10019,10021, 341,10001, 4663,10001, + 903,10027, 1471,10001, 253,10001, 53,10001, 4,10001, 1,10037, + 6,10036, 1,10036, 1275,10043, 5,10001, 9935,10047, 8337,10001, + 9,10051, 5,10000, 8685,10055, 1369,10055, 8401,10055, 3863,10055, + 4137,10055, 4063,10055, 4569,10055, 9955,10055, 241,10001, 17,10001, + 1369,10001, 5,10077, 0, 14, 6,10081, 2,10082, 482,10081, + 2,10081, 0,10089, 6,10088, 0,10088, 15,10095, 2,10080, + 17,10099, 1369,10081, 17,10081, 1, 16, 7,10107, 3,10108, + 586,10107, 8306,10107, 1447,10107, 1141,10107, 9875,10107, 241,10121, + 265,10120, 9992,10107, 545,10107, 695,10107, 1382,10107, 1374,10107, + 1386,10107, 59,10107, 1369,10138, 154,10107, 483,10143, 1325,10107, + 1369,10146, 331,10107, 1369,10150, 3,10107, 1,10155, 7,10154, + 1,10154, 17,10161, 8241,10155, 15,10154, 483,10167, 3,10106, + 9673,10171, 8251,10171, 3807,10171, 4279,10171, 4283,10171, 9967,10171, + 33,10107, 1369,10107, 331,10186, 1325,10186, 59,10186, 1011,10107, + 265,10107, 8165,10196, 9875,10196, 1275,10107, 15,10107, 3,10204, + 483,10207, 3,10205, 1369,10211, 8165,10107, 265,10214, 0, 16, + 4,10219, 3,10220, 3,10221, 7,10219, 2,10226,10225,10229, + 2,10227,10223,10233, 1368,10219,10225,10237, 902,10219,10233,10241, + 59,10219, 1325,10219, 331,10219, 3,10219, 4,10250,10233,10253, + 2,10219, 7,10256,10225,10259, 903,10257, 8495,10219, 587,10265, +10001,10219, 903,10269, 2,10218, 8495,10273, 8717,10273,10055,10273, + 4311,10273, 4329,10273, 3785,10273, 265,10219, 1275,10219, 1, 14, + 8982,10291, 8861,10291, 17,10294, 4745,10291, 1011,10299, 53,10291, + 253,10291, 1471,10291, 2,10291, 3,10291, 483,10311,10257,10311, + 59,10291, 17,10316, 62,10291, 1325,10291, 17,10322, 331,10291, + 17,10326, 1328,10291, 334,10291, 393,10291, 1359,10291, 1031,10291, + 499,10291, 8337,10291, 483,10343, 9875,10291, 1011,10347, 3,10290, + 8685,10351, 1369,10351, 8401,10351, 9955,10351, 4063,10351, 4137,10351, + 3863,10351, 4569,10351,10273,10351, 241,10291, 1369,10291, 17,10291, + 8861,10374, 59,10374, 1325,10374, 331,10374, 1, 11, 340,10385, + 341,10385, 264,10385, 375,10391, 1010,10385, 264,10384, 341,10397, +10387,10397, 5,10385, 6,10402, 2,10402, 2,10403, 7,10385, + 265,10410,10397,10413, 265,10411,10391,10417, 5,10384, 29,10421, + 341,10421, 6,10421, 25,10427, 8262,10385, 9,10431, 8279,10385, + 9,10435, 88,10384, 3807,10439, 6347,10439, 6327,10439, 8251,10439, + 9875,10439, 8165,10439, 8229,10385, 8251,10452, 9,10455, 9,10453, + 8251,10459, 8241,10385, 33,10385, 6685,10465, 9,10465, 6267,10385, + 101,10471, 8240,10385, 8296,10475, 8277,10475, 9,10478, 9,10475, + 8277,10482, 8228,10385, 6719,10385, 9,10489, 265,10384,10389,10493, + 5313,10493, 8251,10385, 8229,10498, 9,10501, 483,10384, 5197,10505, + 5125,10505, 1275,10384, 1369,10385, 6685,10513, 9,10513, 1011,10385, + 265,10385, 7,10520,10397,10523, 2,10384,10423,10527,10428,10527, +10427,10527, 25,10532,10425,10527, 340,10527,10397,10539,10399,10527, +10392,10527, 375,10527,10391,10546, 7,10527, 265,10550,10397,10553, + 265,10551,10391,10557,10391,10527, 375,10560,10463,10527, 9,10565, +10487,10527, 9,10569,10519,10527, 6,10573, 7,10572,10575,10577, + 7,10573, 6,10572,10581,10583, 25,10527,10427,10586, 8165,10527, + 903,10527, 265,10527, 7,10594,10397,10597, 9,10527, 3,10384, +10482,10603, 5,10602, 6,10607, 5,10603, 6,10611,10475,10613, +10458,10603,10395,10603, 6,10619, 7,10618,10621,10623, 7,10619, + 6,10618,10627,10629,10407,10603, 6,10633, 7,10632,10635,10637, + 7,10633, 6,10632,10641,10643, 8326,10603,10453,10603, 9,10648, +10475,10603, 9,10652, 9875,10603, 9,10657,10521,10603, 375,10661, + 9,10602, 8251,10665, 3807,10665, 9875,10665, 8165,10665, 8165,10603, + 9,10674, 9,10675, 3807,10603, 9,10681, 9,10603,10475,10684, +10453,10684, 8165,10684, 8251,10603, 9,10693, 2,10385,10613,10697, + 8165,10699,10646,10697, 8327,10697,10690,10697,10676,10697, 5,10696, +10603,10711, 6,10713, 7,10712,10715,10717, 7,10713, 6,10712, +10721,10723, 8326,10697,10603,10726, 8251,10727,10674,10697, 9,10732, + 8165,10696,10613,10737,10705,10737, 8296,10737,10684,10737, 8277,10737, + 9,10746,10603,10737, 9,10750, 9,10737,10603,10754, 8277,10754, + 265,10697, 8165,10697,10684,10762, 8251,10763, 9,10767, 9,10762, +10603,10770, 8251,10771,10603,10762, 9,10776,10684,10697, 8165,10780, + 8165,10781, 9,10697,10674,10786, 8165,10786,10603,10790, 8251,10791, + 8165,10787,10603,10797, 8277,10797,10603,10786, 8165,10802, 8165,10803, +10603,10697, 8326,10808, 8165,10808, 9,10812, 8165,10809, 9,10817, + 9,10808, 8165,10820, 8165,10821, 67,10697,10427,10827, 3,10385, + 8225,10831, 8242,10831,10427,10831,10409,10831, 6,10839, 7,10838, +10841,10843, 7,10839, 6,10838,10847,10849, 7,10831,10421,10853, + 375,10831,10590,10831, 9,10859, 8165,10830,10527,10863, 9,10865, + 8165,10831,10527,10868, 9,10871, 9,10831, 8241,10874,10527,10831, + 8326,10879, 8165,10878, 9,10883, 8165,10879, 9,10886, 9,10879, + 8165,10890, 8165,10891, 8241,10831, 9,10896, 89,10384, 88,10385, + 8225,10903, 8165,10385, 264,10907, 1368,10906,10909,10911, 7,10906, + 2,10915, 2,10914,10909,10919, 265,10915, 5,10907, 3,10924, +10919,10927,10911,10927, 3,10925,10917,10933, 1369,10925, 1369,10906, + 265,10907,10939,10941, 2,10907,10937,10945, 8229,10945, 9,10949, +10831,10945, 9,10953, 3,10907, 5,10957, 6,10959,10786,10957, + 5,10956,10919,10965,10911,10965,10697,10957, 9,10970, 9,10957, +10697,10974, 2,10906,10961,10979,10613,10979, 8296,10979,10974,10979, +10684,10979, 7,10978,10927,10991,10965,10991,10909,10991, 8277,10979, + 9,10998,10957,10979, 9,11002,10603,10979, 9,11006, 9,10979, +10603,11010, 8277,11010,10957,11010, 3,10906,10923,11019,10945,11019, + 9,11023,10527,11019, 9,11027, 9,10384, 1369,11031, 33,11031, + 3,11030, 8251,11037, 3807,11037, 9875,11037, 8165,11037, 3,11031, + 8241,11047, 1, 9, 69,11051, 6625,11053, 981,11050, 980,11050, + 4745,11059, 7966,11050, 7967,11050, 4,11050, 7,11067, 1275,11067, + 7954,11051, 7967,11051,11063,11075, 120,11050, 3867,11079, 112,11050, +11073,11083, 66,11050, 8251,11087, 1941,11087, 6159,11087, 3807,11087, + 9875,11087, 8165,11087, 121,11050, 7966,11051,11065,11103, 7957,11051, + 11,11106, 1141,11051, 1447,11051, 67,11051, 7,11114,11087,11117, + 113,11051,11083,11121, 7947,11123, 7947,11120,11083,11127, 89,11051, + 8495,11131, 25,11050, 113,11134, 3867,11137, 3867,11135, 113,11141, + 567,11050, 4950,11145, 587,11145, 4935,11148, 4935,11145, 587,11152, + 973,11050, 3,11156, 4745,11159, 587,11051, 566,11162, 566,11163, + 567,11163,11165,11169, 567,11162,11167,11173, 1011,11051, 1369,11051, + 6625,11179, 7956,11051, 7955,11051, 33,11051, 6625,11187, 25,11051, +11101,11191, 3984,11191, 3023,11191, 3933,11191, 113,11198, 113,11191, + 3933,11202, 973,11051, 2139,11207,11057,11207, 567,11051, 4971,11213, + 587,11215, 257,11051, 483,11219, 483,11050, 257,11223, 1011,11050, + 973,11227, 972,11226,11229,11231, 972,11227, 973,11226,11235,11237, + 257,11227, 265,11050, 5019,11243, 903,11051, 7,11246, 2,11050, +11187,11251,11073,11251,11127,11251,11207,11251,11113,11251,11111,11251, +11075,11251,11179,11251,11121,11251, 7947,11269, 25,11251, 5019,11251, + 3,11050,11068,11276,11069,11277,11279,11281,11068,11277,11069,11276, +11285,11287,11185,11277, 973,11276, 4745,11293,11103,11277,11109,11277, +11249,11277, 10,11276, 10,11277, 11,11276, 8251,11307, 3807,11307, + 9875,11307,11305,11307, 8165,11307, 33,11277, 7971,11319, 8165,11277, + 25,11323, 7947,11277, 973,11277, 4805,11329, 3807,11277, 8251,11277, + 4279,11277, 4283,11277, 9673,11277, 9967,11277, 9875,11277, 4745,11277, + 11,11277,11303,11349, 7971,11349, 2,11051,11315,11355,11303,11355, +11349,11358,11350,11355,11304,11355,11307,11365,11349,11355,11303,11368, + 5,11355, 7,11372,11276,11374,11277,11375,11377,11379,11276,11375, +11277,11374,11383,11385, 7,11355, 5,11388,11276,11390,11277,11391, +11393,11395,11276,11391,11277,11390,11399,11401, 5,11354, 7,11404, +11277,11407, 7,11405, 7,11354,11087,11413, 5,11412,11277,11417, +11307,11413,11277,11413, 4,11354,11373,11425, 7,11427,11277,11429, + 10,11354,11087,11433,11307,11433,11277,11433, 10,11355,11349,11441, +11277,11440,11307,11445,11277,11441,11303,11449, 4,11355,11410,11453, +11277,11455, 7,11453,11405,11458,11277,11461,11276,11458,11277,11459, +11405,11467,11465,11467,11276,11459,11277,11458,11473,11475,11405,11453, + 7,11478,11277,11481, 1,11452, 1,11355, 4,11486, 67,11355, + 1275,11355, 9,11493,11485,11495,11489,11495, 7947,11355, 11,11501, +11277,11503,11277,11355, 10,11506,11307,11509, 10,11507,11349,11513, + 11,11354,11326,11517,11277,11517, 7947,11520, 7947,11517,11277,11524, + 3,11051, 8213,11529, 8052,11529, 7971,11529, 113,11534, 113,11529, + 7971,11538, 8241,11529, 7947,11528, 483,11529, 112,11051,11326,11549, +11277,11549, 7947,11552, 7947,11549,11277,11556, 67,11050,11187,11561, +11053,11561,11179,11561, 66,11051, 113,11050,11556,11571,11185,11571, +11549,11571, 7947,11576, 25,11570, 3867,11581, 7947,11571,11549,11584, + 25,11571, 3933,11589, 7947,11051, 113,11592,11083,11595,11251,11595, + 113,11593,11549,11601, 3,11593,11549,11605,11517,11605, 3,11592, + 11,11051, 8116,11613, 8099,11613,11272,11613,11561,11613,11491,11613, +11251,11613, 25,11624, 8074,11613, 8093,11629, 25,11613,11251,11632, + 8109,11613, 8063,11636, 8063,11613, 8109,11640, 7957,11612,11277,11645, + 6625,11613, 113,11613, 2,11613,11183,11653,11545,11653,11611,11653, +11529,11653, 7947,11661, 3,11613, 7971,11664, 8093,11667, 7971,11665, + 8109,11671, 2,11612,11605,11675,11326,11675,11277,11675, 7947,11680, + 7947,11675,11277,11684, 7971,11613, 3,11688, 8093,11691, 3,11689, + 8063,11695, 11,11050,11355,11699, 113,11701, 1369,11699,11251,11705, + 33,11699,11251,11709, 3,11698, 8251,11713, 3807,11713,11433,11713, +11413,11713, 9875,11713, 8165,11713, 3,11699, 8241,11727, 0, 11, + 8095,11731, 8112,11731, 6688,11731, 6285,11731, 203,11730, 2351,11741, + 8159,11731, 8162,11731, 8128,11731, 8114,11731, 8097,11731, 8118,11731, + 8100,11731, 5,11730, 1369,11759, 8116,11731, 9,11762, 8099,11731, + 9,11766, 181,11731, 98,11731, 5019,11773, 8058,11731, 8093,11777, + 8156,11731, 8093,11781, 8076,11731, 8093,11785, 30,11731, 8124,11731, + 8063,11790, 8072,11731, 8109,11794, 8063,11731, 8161,11798, 8124,11798, + 8109,11798, 9,11804, 9,11798, 8109,11808, 25,11731, 6685,11812, + 9,11812, 89,11731, 5019,11819, 21,11821, 21,11818, 5019,11825, + 2759,11731, 2789,11731, 2821,11731, 6658,11731, 6685,11731, 25,11836, + 4413,11731, 113,11731, 9,11842, 128,11731, 659,11731, 623,11731, + 645,11731, 705,11731, 299,11731, 828,11731, 394,11731, 241,11731, + 375,11862, 483,11731, 803,11866, 8074,11731, 8093,11871, 9,11873, + 9,11870, 8093,11877, 101,11731, 21,11731, 89,11882, 5019,11885, + 89,11883, 5045,11889, 8061,11731, 8109,11892, 803,11731, 483,11896, + 375,11731, 241,11900, 587,11901, 6625,11731, 9,11906, 6789,11731, + 2,11911, 6855,11913, 1369,11730, 587,11730, 375,11919, 8109,11731, + 8061,11922, 8072,11922, 8063,11922, 9,11928, 9,11922, 8063,11932, + 145,11731, 903,11730, 375,11939, 265,11731, 8161,11731, 8063,11944, + 2,11730, 8124,11949, 8804,11949, 3972,11949, 8150,11949, 8495,11949, + 9,11958, 7971,11949, 9,11962, 3933,11949, 9,11966, 9,11949, + 8109,11970, 8495,11970, 3933,11970, 7971,11970, 8109,11949, 9,11980, + 3,11730, 483,11985, 2,11731, 8075,11989, 9,11991, 3,11731, + 8151,11994, 5,11995, 6,11999, 0,11998, 0,11995, 5,12004, + 8150,11994, 8093,12009, 7971,11994, 8093,12013, 9,12015, 9,12012, + 8093,12019, 1369,11995, 11,12023,12003,12025,12007,12025, 7971,11995, + 8161,12031,11997,12031, 8124,12031, 8109,12031, 9,12038, 9,12031, + 8109,12042, 9,11994, 7971,12046, 8093,12049, 7971,12047, 8109,12053, + 89,11730, 5082,12057, 2969,12057, 5045,12057, 21,12062, 21,12057, + 5045,12066, 88,11731, 7971,12070, 8093,12073, 7971,12071, 8109,12077, + 8150,11731, 3,12080, 8093,12083, 3,12081, 8063,12087, 7971,11731, + 1368,12091, 264,12090,12093,12095, 5,12090, 3,12099, 3,12098, +12093,12103, 1369,12099, 7,12091, 2,12108,12103,12111,12095,12111, + 2,12109,12101,12117, 265,12109, 265,12090, 1369,12091,12123,12125, + 88,12090, 8093,12129, 88,12091, 8061,12133, 2,12091,12001,12137, + 7,12136,12103,12141,12095,12141, 9,12137, 3,12091, 8061,12149, + 8072,12149,12121,12149, 8063,12149, 9,12156, 9,12149, 8063,12160, + 2,12090,12107,12165,12149,12165, 9,12169, 3,12090, 5,12173, + 6,12175,12137,12177,12146,12173, 5,12172,12111,12183,12141,12183, +12093,12183, 8093,12173, 9,12191,12137,12173, 9,12194, 9,12172, + 8093,12199, 9,12173,12137,12202, 9,12090, 3,12206, 8093,12209, + 3,12207, 8063,12213, 9,11731, 8116,12216, 8099,12216, 8074,12216, + 8093,12223, 25,12216, 8109,12216, 8063,12228, 8063,12216, 8109,12232, + 6625,12216, 113,12216, 3,12216, 7971,12240, 8093,12243, 7971,12241, + 8109,12247, 7971,12216, 3,12250, 8093,12253, 3,12251, 8063,12257, + 0, 9, 192,12261, 2329,12263, 211,12261, 2419,12267, 211,12260, + 2433,12271, 192,12260, 2337,12275, 189,12260, 2337,12279, 4,12261, + 7,12282, 413,12260, 413,12261, 1216,12260, 1216,12261, 1086,12261, + 9617,12295, 137,12261, 587,12261, 1011,12300, 9617,12303, 1011,12301, + 9565,12307, 1011,12261, 9617,12311, 587,12313, 587,12310, 9617,12317, + 1011,12260, 5267,12321, 9600,12321, 9565,12321, 587,12326, 587,12321, + 9565,12330, 587,12260, 5231,12335, 5181,12335,10505,12335, 1275,12261, + 2,12260,10001,12345, 5,12347, 4,12346,12349,12351, 4,12347, + 5,12346,12355,12357, 3,12260,11243,12361,11251,12361, 5177,12361, + 5185,12361, 2,12261, 3,12261,11355,12373, 1, 265, 471,12376, + 2647,12379, 357,12376, 1785,12383, 586,12377, 375,12387, 586,12376, + 413,12377, 3,12377, 7,12394, 375,12397, 7,12395, 331,12401, + 483,12395, 15,12405, 5,12377, 17,12409, 587,12411, 3,12376, + 669,12415, 1418,12415,12413,12415, 1369,12415, 15,12422, 15,12415, + 1369,12426, 5,12376,12417,12431, 1419,12431,12415,12435, 668,12431, +12415,12439,12419,12431,12407,12431,12429,12431, 9,12431, 587,12448, +12415,12451,12425,12431, 587,12431, 9,12456,12415,12459, 6719,12377, + 9,12463, 7867,12377, 251,12467, 3357,12377, 3681,12377, 3709,12377, + 2647,12377, 5843,12377, 4407,12377,11917,12377, 305,12377, 713,12377, + 25,12377, 4405,12377, 7041,12377, 251,12493, 1471,12376, 2011,12497, + 53,12376, 2035,12501, 257,12377, 253,12376, 5325,12507, 251,12376, + 7867,12511, 7617,12511, 7041,12511, 7617,12377, 251,12519, 1363,12376, + 5189,12523, 483,12377, 9,12377, 8938,12377, 375,12531, 5313,12377, + 7035,12377, 7091,12537, 7083,12537, 7123,12537, 241,12537, 11,12376, + 5313,12547, 587,12376,12387,12551,11731,12551, 9,12376, 5019,12557, +12361,12557, 1369,12376, 11,12377, 587,12377,12391,12567, 7,12376, + 2,12571, 4,12572,12537,12575, 4,12571, 2,12578,12537,12581, +12545,12571, 240,12571,12537,12587, 8948,12571, 331,12571, 8861,12592, + 8861,12571, 331,12596, 4827,12571, 6,12377, 257,12603, 265,12605, + 241,12603, 1,12609,12607,12611, 7,12377, 3,12614, 375,12617, + 8861,12614, 375,12621, 375,12615, 8861,12625, 241,12614, 375,12629, + 257,12376, 2647,12633, 1783,12633, 256,12377, 375,12639, 8861,12377, + 261,12643, 260,12643, 256,12643, 6,12643, 241,12650, 7,12643, + 241,12654, 331,12655, 6,12642,12645,12661, 7,12642,12647,12665, +12653,12665, 375,12665, 241,12643, 6,12672,12665,12675, 7,12672, + 6,12673,12679,12681,12655,12681, 7,12673,12675,12687, 241,12377, + 7,12691, 331,12693, 7,12690, 375,12697, 8997,12691, 7,12701, + 241,12376, 4457,12705, 374,12705, 5189,12705, 265,12705, 6,12712, + 8386,12705, 6,12705, 265,12718, 7,12705, 8337,12722, 8337,12705, + 7,12726, 8861,12705, 6,12731, 7,12731, 6,12730,12735,12737, + 7,12730,12733,12741, 1, 241, 448,12745, 4349,12747, 445,12744, + 1679,12751, 457,12744, 4371,12755, 8461,12744, 8475,12759, 277,12744, + 4457,12763, 923,12744, 4959,12767, 8388,12744, 8389,12744, 4,12745, + 11,12775, 1369,12777, 2,12745, 1275,12781, 9,12783, 2,12744, + 1419,12787, 668,12787,12779,12787, 587,12787, 9,12794, 9,12787, + 587,12798, 4,12744,12789,12803, 669,12803,12787,12807, 1418,12803, +12787,12811,12791,12803,12785,12803,12801,12803, 15,12803, 1369,12820, +12787,12823,12797,12803, 1369,12803, 15,12828,12787,12831, 445,12745, + 265,12834, 4349,12837, 923,12745, 5009,12841, 8374,12745, 346,12745, + 2981,12847, 386,12745, 387,12745, 3049,12853, 347,12745, 8389,12745, +12771,12859, 1412,12745, 5227,12863, 346,12744, 2977,12867,12857,12867, + 386,12744, 4067,12873,12853,12873, 1412,12744, 5189,12879, 374,12744, +12845,12883, 387,12744, 3043,12887,12851,12887, 347,12744,12847,12893, + 272,12745, 4453,12897, 4437,12897, 1755,12897, 8388,12745, 8495,12905, +12773,12905, 8387,12745, 265,12911, 8861,12913, 265,12910, 8495,12917, + 253,12745, 59,12744, 1325,12744, 341,12745, 375,12745,12883,12929, + 8337,12931, 8337,12928,12883,12935, 4371,12745, 457,12939, 375,12939, + 4531,12745, 375,12945, 8366,12745, 375,12949, 305,12744, 4457,12953, + 375,12952, 4067,12957, 4067,12953, 375,12961, 331,12744, 4457,12965, +12927,12965, 8386,12745, 8495,12971, 331,12971, 1325,12971, 59,12971, + 265,12971, 8375,12745, 8495,12983, 305,12745,12887,12987, 4266,12987, + 3031,12987, 4213,12987, 375,12994, 8337,12986, 375,12999, 375,12987, + 4213,13002, 5325,12745, 7,13007, 5361,13009, 5385,13009, 5407,13009, + 1275,12744, 15,12744, 8475,12745, 375,13021, 8461,13021, 6,12744, + 8429,13027, 8428,13027, 4139,13027, 4138,13027, 3,13026, 5,13036, + 5,13026, 3,13040, 264,13026,13031,13045,13035,13045, 264,13027, + 8401,13051, 4137,13051, 265,13026, 8401,13057,13051,13058,13029,13057, +13052,13057, 4137,13057,13051,13066,13033,13057,13054,13057,13051,13057, + 8401,13074, 4137,13074, 4137,13027, 265,13081,13051,13083, 265,13080, +13045,13087, 341,13027, 265,13027, 8401,13092,13045,13095, 4137,13092, +13045,13099,13045,13093, 8401,13103, 4137,13103, 8401,13027, 265,13109, +13051,13111, 265,13108,13045,13115, 7,12744, 8605,13119, 8374,13119, + 8916,13119, 8389,13119, 412,13119, 241,13119, 265,13130, 264,13118, + 264,13119, 8452,13119, 8647,13119, 265,13118,13137,13143, 8861,13119, + 375,13146, 8337,13119, 375,13150, 265,13150, 305,13119, 713,13119, + 25,13119, 375,13119, 8861,13162, 8337,13162, 265,13119, 241,13168, +13135,13169, 8337,13168, 6,12745,12965,13177,13145,13177,13139,13177, + 8453,13177,13119,13185,12923,13177,12925,13177,13135,13177,13169,13192, +13172,13177,13136,13177,13143,13199,13175,13177,13155,13177,13169,13177, +13135,13206, 3,13177, 5,13210,13118,13212,13119,13213,13215,13217, +13118,13213,13119,13212,13221,13223, 5,13177, 3,13226,13118,13228, +13119,13229,13231,13233,13118,13229,13119,13228,13237,13239, 264,13177, +13119,13242,13143,13245,13119,13243,13135,13249, 413,13177, 8452,13177, + 8861,13255, 305,13177, 8337,13177, 265,13260, 8861,13263, 265,13261, + 8495,13267, 265,13177, 8337,13270, 8861,13273, 8861,13271, 8337,13277, +13119,13177, 264,13280,13143,13283, 264,13281,13169,13287, 265,13280, +13287,13291, 265,13281,13283,13295, 8387,13177, 264,13299, 265,13298, +13301,13303, 264,13298, 265,13299,13307,13309, 265,13176, 8842,13313, + 8495,13313, 8337,13316, 8337,13313, 8495,13320, 7,12745,13039,13325, +13043,13325,13045,13325, 241,13324, 0,13333, 8717,13325, 8495,13325, + 8337,13339, 305,13339, 4311,13325, 4329,13325, 3785,13325,10351,13325, +10055,13325, 8337,13324, 8495,13355, 331,13355, 1325,13355, 59,13355, + 265,13355, 59,13325, 8337,13367, 1325,13325, 8337,13371, 331,13325, + 8337,13375, 8861,13375, 265,13325,13051,13381,13335,13381, 5325,13381, + 1,13381,13333,13389, 8861,13381, 8337,13381,13027,13325, 264,13396, + 264,13397, 265,13396,13401,13403, 265,13397,13399,13407, 265,13324, + 8717,13411, 3785,13411,13045,13411, 8495,13411, 374,12745, 8842,13421, + 8495,13421, 8337,13424, 8337,13421, 8495,13428, 340,12745, 8717,13433, +13045,13433, 3785,13433, 8495,13433, 375,12744, 4371,13443,13428,13443, +12983,13443, 8475,13443,13421,13443, 8337,13452, 305,13442, 4067,13457, + 8337,13443,13421,13460, 305,13443, 4213,13465, 8452,12745, 8647,13469, + 7,13469, 8495,13473, 8337,12745, 375,13476,12883,13479, 375,13477, + 305,13483,13421,13483, 305,13476, 375,13489, 6,13477, 8453,13493, + 8452,13492,13495,13497, 8452,13493, 8453,13492,13501,13503, 7,13477, +13213,13507,13229,13507, 375,13507,13243,13507, 265,13507,13177,13517, + 6,13476, 3,13521, 5,13522,13507,13525, 5,13521, 3,13528, +13507,13531,13517,13521, 264,13521,13507,13537, 7,13476, 8495,13541, + 331,13541, 1325,13541, 59,13541, 265,13541, 265,13476, 8647,13553, + 7,13553, 8495,13557, 265,13477,13177,13561,13521,13561, 7,13561, + 265,12745, 445,13568, 4349,13571, 445,13569, 4371,13575, 8770,13569, + 8729,13569,13027,13569, 375,13583, 8684,13569, 8717,13587, 331,13569, +13177,13591, 8757,13569, 8647,13594, 8647,13569, 8757,13598, 8387,13568, + 8495,13603, 6,13569, 7,13569, 8647,13609, 8495,13608, 8717,13613, + 8495,13609, 8757,13617, 6,13568, 8842,13621, 8495,13621, 8337,13624, +13609,13621, 8337,13621, 8495,13630, 7,13568, 8717,13635, 3785,13635, +13045,13635, 8495,13635,13607,13635, 8337,13568, 8647,13647, 7,13647, + 8495,13651, 8495,13569, 6,13654, 7,13654, 8717,13659, 6,13655, +13659,13663, 7,13655,13657,13667, 8647,13667, 265,12744,13258,13673, +12845,13673,13091,13673,12935,13673,12927,13673,12929,13673, 8337,13685, +13479,13673,12911,13673,13260,13673,12859,13673, 4457,13673, 5189,13673, +13177,13673, 305,13700, 8337,13700, 305,13673,13177,13706, 8386,13673, + 7,13673, 8337,13712, 8861,13673, 6,13717, 7,13717, 6,13716, +13721,13723, 7,13716,13719,13727, 8337,13673,13177,13730, 7,13730, + 1, 587, 264,13737, 375,13739, 16,13737, 264,13736, 341,13745, + 7,13737, 4,13748, 4,13749, 3,13736, 717,13755, 341,13755, + 6,13755, 713,13761, 17,13755, 566,13736, 1108,13737, 9565,13769, +11731,13737, 265,13772,11942,13737, 3565,13737, 3573,13737, 3273,13737, + 375,13736, 113,13736, 4696,13787, 9,13787, 4669,13790, 4669,13787, + 9,13794, 1011,13737, 9565,13799, 9,13801, 9,13798, 9565,13805, + 241,13737, 9,13737, 1011,13810, 9565,13813, 1011,13811, 9617,13817, + 113,13737, 4727,13821, 9,13823, 7049,13737, 807,13827, 375,13827, + 265,13736,11731,13833, 1487,13737, 1011,13736, 5293,13839, 9704,13839, + 9617,13839, 9,13844, 9,13839, 9617,13848, 265,13737,11731,13852, + 4,13736,13757,13857,13762,13857,13761,13857, 713,13862,13759,13857, + 340,13857,13745,13869,13747,13857,13740,13857, 375,13857,13739,13876, + 7,13857, 265,13880,13745,13883, 265,13881,13739,13887,13739,13857, + 375,13890, 713,13857,13761,13894, 265,13857, 7,13898,13745,13901, + 483,13857, 5,13736,13853,13907, 375,13909, 483,13906, 4,13737, + 7,13914, 767,13915,13761,13919, 5,13737, 3,13923, 1,13924, + 1,13923, 3,13928, 17,13923, 587,13933,13927,13935,13931,13935, + 567,13736, 483,13736, 5,13942, 1, 483, 9174,13946, 9175,13946, + 2,13947, 7,13952, 2,13946, 7,13957, 6,13946, 9170,13947, + 9175,13947,13949,13965, 824,13946, 3997,13969, 802,13946,13963,13973, + 766,13946, 825,13946, 9174,13947,13951,13981, 803,13947,13973,13985, + 9165,13987, 9165,13984,13973,13991, 713,13946, 803,13994, 3997,13997, + 3997,13995, 803,14001, 1171,13946, 4663,14005, 903,14007, 155,13946, + 9172,13947, 9171,13947, 713,13947,13979,14017, 4200,14017, 3027,14017, + 4147,14017, 803,14024, 803,14017, 4147,14028, 1171,13947, 4722,14033, + 903,14033, 4713,14036, 4713,14033, 903,14040, 257,13947, 9,14045, + 9,13946, 257,14049, 903,13946, 257,14053, 11,13946, 5197,14057, + 5125,14057,12335,14057, 4,13946, 2,14065, 7,14067,14013,14069, + 5,13946,13958,14072,13959,14073,14075,14077,13958,14073,13959,14072, +14081,14083, 586,14072, 586,14073, 587,14072,14089,14091, 4827,14073, + 9,14073, 4569,14073, 4745,14073, 587,14073,14087,14103, 4,13947, +14093,14107,14087,14107,14103,14110,14104,14107,14088,14107,14091,14117, +14103,14107,14087,14120, 3,14107, 7,14124,14072,14126,14073,14127, +14129,14131,14072,14127,14073,14126,14135,14137, 7,14107, 3,14140, +14072,14142,14073,14143,14145,14147,14072,14143,14073,14142,14151,14153, + 3,14106, 7,14157, 2,14106,14125,14161, 7,14163,14073,14165, + 586,14107,14073,14168,14091,14171,14073,14169,14087,14175, 2,14107, +14158,14179,14073,14181, 7,14179,14157,14184,14073,14187,14073,14185, +14157,14191,14157,14179, 7,14194,14073,14197,14073,14107, 586,14200, +14091,14203, 586,14201,14103,14207, 5,13947,14069,14211, 9165,14213, + 6,14211, 9165,14210,14069,14219, 17,14211, 802,13947, 9165,14225, + 803,13946,14226,14229,14015,14229,14225,14229, 9165,14234, 713,14228, + 3997,14239, 9165,14229,14225,14242, 713,14229, 4147,14247, 9165,13947, + 803,14250,13973,14253, 803,14251,14225,14257, 4,14251, 2,14261, + 7,14263, 5,14250,14265,14267,14069,14267, 587,13947, 9340,14273, + 9323,14273, 9290,14273, 9317,14279, 9335,14273, 9287,14282, 9287,14273, + 9335,14286, 5,14273, 9195,14290, 9317,14293, 9195,14291, 9335,14297, + 9195,14273, 5,14300, 9317,14303, 5,14301, 9287,14307, 587,13946, + 5,14310, 0, 265, 446,14315, 4371,14317, 445,14314, 1675,14321, + 8725,14315, 8766,14315, 471,14314, 2367,14329, 8827,14315, 8836,14315, + 319,14314, 4497,14337, 1302,14315, 667,14315, 8794,14315, 8768,14315, + 8727,14315, 8774,14315, 8732,14315, 1011,14315, 1275,14354, 3,14315, + 1369,14359, 11,14361, 5,14315, 9,14365, 1275,14367, 3,14314, + 1291,14371, 524,14371,14369,14371, 483,14371, 11,14378, 11,14371, + 483,14382, 5,14314, 525,14387,14371,14389,14373,14387,14375,14387, + 1290,14387,14371,14397,14363,14387,14385,14387,14381,14387, 17,14387, + 1275,14406,14371,14409, 1275,14387, 17,14412,14371,14415, 8770,14315, + 241,14418, 8729,14315, 241,14422, 445,14315, 241,14426, 4371,14429, + 1303,14315, 666,14315, 8784,14315, 4266,14315, 8622,14315, 8717,14441, + 8824,14315, 8717,14445, 8702,14315, 8717,14449, 256,14314, 7185,14453, + 2309,14453, 5673,14453, 5521,14453, 375,14461, 4213,14315, 375,14464, + 316,14315, 4533,14469, 1757,14469, 8697,14315, 629,14315, 407,14315, + 5325,14479, 3121,14315, 3031,14315, 5519,14315, 3355,14315, 510,14315, + 8788,14315, 8647,14492, 8676,14315, 8757,14496, 8647,14315, 8831,14500, + 8788,14500, 8757,14500, 241,14506, 241,14500, 8757,14510, 331,14315, + 1325,14315, 59,14315, 5521,14315, 375,14521, 375,14315, 4213,14524, + 8757,14524, 53,14525, 1471,14525, 253,14525, 253,14314, 4425,14537, + 4497,14537, 483,14315, 9,14542, 9,14315, 483,14546, 8684,14315, + 8717,14551, 241,14553, 241,14550, 8717,14557, 331,14551, 251,14315, + 257,14563, 8495,14565, 8635,14315, 8757,14568, 5515,14315, 331,14573, + 8757,14315, 8635,14576, 8676,14576, 8647,14576, 241,14582, 375,14576, + 241,14576, 8647,14588, 1369,14314, 2853,14593, 15,14315, 1275,14315, + 1011,14598, 587,14315, 241,14602, 8831,14315, 8647,14606, 6,14314, +14341,14611,14343,14611,14601,14611,14357,14611, 8495,14611, 241,14611, + 7,14314,14433,14625,14435,14625,14605,14625, 8495,14625, 3785,14625, +10055,14625,10351,14625, 4329,14625, 4311,14625, 4555,14625,14073,14625, + 4971,14625, 8717,14625, 7,14315, 8813,14652,14623,14653, 8495,14657, + 4,14653, 2,14660,14620,14663, 8495,14663,14611,14666,14611,14663, + 8495,14670, 2,14653, 4,14674,14620,14677, 8495,14677,14611,14680, +14611,14677, 8495,14684, 240,14653,14620,14689, 8495,14689,14611,14692, +14611,14689, 8495,14696, 8812,14652, 8717,14701, 8495,14652, 8717,14705, + 241,14707, 241,14704, 8717,14711, 331,14705, 15,14653, 483,14717, + 1275,14653, 9,14721, 8495,14653, 8831,14725,14655,14725, 8788,14725, + 8757,14725, 241,14732, 241,14725, 8757,14736, 375,14653, 8647,14653, + 241,14652, 8647,14745, 8495,14744, 8717,14749, 8495,14745, 8757,14753, + 257,14314, 8614,14757, 4417,14757, 8495,14757, 251,14762, 251,14757, + 8495,14766, 256,14315, 8647,14771, 7207,14771, 5432,14771, 5325,14771, + 375,14778, 8495,14770, 8717,14783, 375,14771, 5325,14786, 8495,14771, + 8757,14791, 8812,14315, 6,14794, 7,14794, 8717,14799, 6,14795, +14799,14803, 7,14795,14797,14807, 8647,14807, 8495,14315, 261,14812, + 260,14812, 256,14812, 8717,14819, 256,14813, 8635,14823, 6,14813, +14815,14827, 7,14813,14817,14831, 8635,14831, 8676,14831, 8647,14831, + 241,14838, 375,14831, 241,14831, 8647,14844, 6,14812, 241,14848, +14831,14851, 7,14812, 8717,14855, 241,14857, 241,14854, 8717,14861, + 331,14855, 241,14812, 6,14866,14831,14869, 7,14866, 8717,14873, + 6,14867,14873,14877,14855,14877, 7,14867,14869,14883, 8647,14883, + 241,14315, 445,14888, 4371,14891, 445,14889, 4349,14895, 8770,14888, + 8729,14888, 587,14888,14625,14903, 8684,14888, 8717,14907, 8757,14888, + 8647,14910, 8387,14889, 8495,14915, 8647,14888, 8757,14918, 6,14889, + 8842,14923, 8495,14923, 8337,14926, 8337,14923, 8495,14930, 7,14889, + 8717,14935, 3785,14935, 8495,14935, 6,14888,14935,14943, 7,14888, + 8647,14947, 8495,14946, 8717,14951,14923,14947, 8495,14947, 8757,14957, + 8495,14888, 6,14960, 7,14960, 8717,14965, 6,14961,14965,14969, + 7,14961,14963,14973, 8647,14973, 8337,14889, 8647,14979, 7,14979, + 8495,14983,12745,14315, 375,14987, 241,14314, 9099,14991, 9036,14991, + 8647,14991, 8997,14996, 5521,14991, 375,15001, 375,14991, 9082,14991, + 8495,15007, 7,14991, 8495,15011, 8997,15013, 8997,15010, 8495,15017, + 8997,14991, 8647,15020, 7,15020, 8495,15025, 0, 241, 460,15029, + 2315,15031, 479,15029, 2393,15035, 479,15028, 2397,15039, 460,15028, + 2317,15043, 457,15028, 2317,15047, 269,15028, 2885,15051, 464,15029, + 16,15029, 413,15029, 6,15058, 4,15029, 7,15062, 7,15063, + 15,15063, 483,15069, 2,15029, 587,15073, 17,15075, 2,15028, + 525,15079, 1290,15079,15071,15079, 1275,15079, 17,15086, 17,15079, + 1275,15090, 4,15028, 1291,15095,15079,15097,15081,15095,15083,15095, + 524,15095,15079,15105,15077,15095,15093,15095,15089,15095, 11,15095, + 483,15114,15079,15117, 483,15095, 11,15120,15079,15123, 9072,15029, + 305,15127, 9105,15029, 305,15131, 9083,15029, 413,15135, 412,15134, +15137,15139, 412,15135, 413,15134,15143,15145, 3445,15029, 375,15149, +12526,15029,12528,15029, 251,15029, 375,15029, 305,15159, 8997,15161, + 8997,15158, 305,15165,12614,15029, 375,15169, 7065,15029, 265,15173, + 7259,15175, 305,15028, 9105,15179, 9072,15179, 375,15179, 8997,15184, + 8997,15179, 375,15188, 9082,15029, 375,15193, 265,15193, 5521,15029, + 375,15199, 265,15199, 483,15029,12377,15204, 9,15029,12377,15208, + 17,15029,13737,15029, 375,15215, 6,15028, 3,15219, 5,15220, +15193,15223, 5,15219, 3,15226,15193,15229,15197,15219,15057,15219, + 3,15235, 2,15234,15237,15239, 2,15235, 3,15234,15243,15245, +15065,15219, 3,15249, 2,15248,15251,15253, 2,15249, 3,15248, +15257,15259, 264,15219,15193,15263, 8997,15219, 7,15028, 4437,15269, +15213,15269, 3,15273, 2,15272,15275,15277, 2,15273, 3,15272, +15281,15283,12571,15269, 4805,15269, 4613,15269,14073,15269, 375,15269, + 510,15269, 4971,15269, 483,15269, 9,15300, 9,15269, 483,15304, + 6,15029, 9020,15309, 9021,15309,12393,15309,12392,15309, 8337,15309, + 265,15318, 8452,15308, 241,15322, 8453,15309,15325,15327, 8452,15309, + 8453,15308, 412,15309, 8997,15335, 241,15308, 265,15338,15327,15341, + 8452,15339,15333,15345,15067,15309, 3,15349, 2,15348,15351,15353, + 2,15349, 3,15348,15357,15359, 413,15308,15313,15363,15315,15363, +15331,15363,15321,15363, 8997,15363,15335,15372,15336,15363,15335,15363, + 8997,15378, 412,15308,15311,15383,15317,15383,15327,15383, 413,15309, +12377,15390,15383,15393, 8997,15390,15383,15397,15383,15391, 8997,15401, +12377,15309, 413,15404,15383,15407, 413,15405,15335,15411, 8997,15309, + 413,15414,15383,15417, 413,15415,15335,15421, 265,15309, 8337,15424, +15363,15427, 265,15308, 241,15430,15327,15433, 7,15029,15223,15437, + 8997,15439,15229,15437, 8997,15443,15263,15437, 8997,15447, 4,15436, +15219,15451, 3,15453, 2,15452,15455,15457, 2,15453, 3,15452, +15461,15463, 264,15436, 264,15437,12377,15436, 375,15471, 8997,15436, +15223,15475,15229,15475, 375,15475,15263,15475, 265,15475,15219,15485, + 59,15437, 1325,15437, 331,15437, 1275,15437, 9,15495, 15,15437, + 483,15499, 265,15437,15266,15503,15219,15503, 8997,15506,15467,15503, + 8997,15503,15219,15512, 305,15503, 265,15436,15469,15519, 331,15519, + 375,15028, 3307,15525, 2885,15525,12511,15525,12377,15525, 251,15533, + 340,15029, 331,15537, 9136,15029, 7,15541, 8997,15029, 375,15544, + 305,15547, 305,15545, 375,15551, 6,15545, 3,15555, 5,15556, + 5,15555, 3,15560, 264,15555, 7,15545, 8495,15567, 331,15567, + 1325,15567, 59,15567, 265,15567, 7,15544,15559,15579,15563,15579, +15223,15579,15229,15579, 375,15579,15263,15579,15565,15579, 265,15579, +15219,15595,15555,15595, 265,15544,15555,15601, 7,15601, 265,15545, + 8647,15607, 7,15607, 8495,15611, 265,15029, 7,15615, 375,15617, + 7,15614, 331,15621, 8997,15614, 7,15625,12377,15029,13421,15629, +13313,15629,13621,15629,14923,15629,12721,15629,12715,15629,12709,15629, + 375,15629,12705,15645, 7,15629, 331,15649, 483,15628, 9,15628, + 7,15628, 375,15657, 265,15028, 9036,15661, 9099,15661, 241,15661, + 6,15667,15629,15669, 8647,15661, 8997,15672, 5521,15661, 375,15677, + 9082,15661, 8495,15681, 375,15661, 7,15661, 8495,15687, 8997,15689, + 8997,15686, 8495,15693, 8997,15661, 8647,15696, 7,15696, 8495,15701, + 0, 587, 9319,15705, 9336,15705, 889,15704, 2373,15711, 9371,15705, + 9374,15705, 9350,15705, 9338,15705, 9321,15705, 9342,15705, 9324,15705, + 578,15705, 3,15705, 6,15730, 7,15705, 567,15735, 9195,15737, + 4,15735, 9366,15741, 483,15741, 9195,15744, 9195,15741, 483,15748, + 7,15704, 9340,15705, 483,15754, 9323,15705, 483,15758, 579,15705, + 9272,15705, 9317,15765, 9368,15705, 9317,15769, 9294,15705, 9317,15773, + 566,15704,15729,15777, 9348,15705, 9287,15780, 9288,15705, 9335,15784, + 9287,15705, 9373,15788, 9348,15788, 9335,15788, 483,15794, 483,15788, + 9335,15798, 567,15705, 9,15802,15777,15805,15777,15803, 9,15809, +12377,15705, 11,15813, 9,15705, 567,15816,15777,15819, 567,15817, + 9290,15705, 9317,15825, 483,15827, 483,15824, 9317,15831, 9275,15705, + 9335,15834, 375,15705, 11,15839, 11,15704, 375,15843, 9335,15705, + 9275,15846, 9288,15846, 9287,15846, 483,15852, 483,15846, 9287,15856, + 9,15704, 5231,15861, 5181,15861,10505,15861,14057,15861, 1011,15704, + 375,15871, 9373,15705, 9287,15874, 4,15704, 9262,15879, 375,15879, + 9195,15882, 7,15879, 265,15887, 9195,15889, 9195,15879, 375,15892, + 483,15879, 5,15704, 5,15705, 9367,15900, 9366,15900, 9317,15905, + 9195,15900, 9317,15909, 483,15911, 483,15908, 9317,15915, 9195,15901, + 9373,15919,15903,15919, 9348,15919, 9335,15919, 483,15926, 483,15919, + 9335,15930, 483,15900, 9195,15934, 9317,15937, 9195,15935, 9335,15941, + 567,15704,15763,15945, 9,15945, 566,15705,15823,15951,15948,15951, +15945,15951, 9,15956, 9195,15950, 9317,15961, 9195,15951, 9335,15965, + 9,15951,15945,15968, 9366,15705, 5,15972, 9317,15975, 5,15973, + 9287,15979, 9195,15705, 566,15982, 9317,15985, 566,15983, 9275,15989, + 5,15983, 9275,15993, 9288,15993, 9287,15993, 483,15998, 483,15993, + 9287,16002, 5,15982, 9317,16007, 483,16009, 483,16006, 9317,16013, + 483,15982, 5,16016, 9317,16019, 5,16017, 9287,16023, 483,15705, + 9340,16026, 9323,16026, 9290,16026, 9317,16033, 9335,16026, 9287,16036, + 9287,16026, 9335,16040, 5,16026, 9195,16044, 9317,16047, 9195,16045, + 9335,16051, 9195,16026, 5,16054, 9317,16057, 5,16055, 9287,16061, + 0, 483, 878,16065, 2327,16067, 899,16065, 2415,16071, 899,16064, + 2423,16075, 878,16064, 2331,16079, 875,16064, 2331,16083, 573,16064, + 2569,16087, 2,16064, 15,16091, 413,16064, 413,16065, 573,16065, + 2567,16099, 1216,16064, 1216,16065, 904,16065, 2263,16107, 6515,16065, + 5,16111, 6539,16113, 903,16064, 4421,16117, 5285,16117, 2265,16117, + 4,16064, 5,16064, 4,16065, 2,16129, 7,16131, 0,16130, + 0,16129, 2,16136, 15,16129, 483,16141,16135,16143,16139,16143, + 9513,16065, 5,16149,16133,16151, 4,16148, 2,16155, 7,16157, +16151,16159, 1, 1011, 996,16162, 14,16162, 5,16163, 6,16169, + 9617,16171, 2,16162, 9617,16175,16171,16176,16172,16175,16171,16175, + 9617,16182, 7,16175,16169,16187, 9617,16189, 5,16162,16186,16193, +16175,16193, 7,16196, 7,16197,16187,16193, 6,16192,16195,16205, +16199,16205, 7,16192,16203,16211,16175,16211, 3,16211,16162,16217, + 3,16193, 7,16221,16162,16222,16162,16221, 7,16226, 7,16227, +16205,16231, 6,16193,16201,16235,16214,16235,16175,16235,16211,16240, +16211,16235,16175,16244,16225,16235,16229,16235,16219,16235, 7,16193, +16175,16254,16205,16257,16205,16255,16175,16261, 9704,16163, 587,16265, + 5293,16163, 587,16269, 997,16162, 972,16162,16235,16275, 9,16275, +14652,16163, 973,16163,16273,16283,16278,16283, 9,16283,16275,16288, +16275,16283, 9,16292, 955,16162, 5241,16297, 1505,16162, 6,16301, + 7,16300,16303,16305, 7,16301, 6,16300,16309,16311, 67,16162, +16235,16315, 9,16163, 9617,16318, 587,16321, 587,16319, 9617,16325, + 15,16162, 257,16163, 9,16331, 9,16162, 973,16335,16275,16337, + 973,16334, 257,16335, 587,16162, 5293,16345, 9704,16345, 9617,16345, + 9,16350, 9,16345, 9617,16354, 6,16162, 5,16358, 7,16162, +16221,16362,16235,16365,16235,16363, 8647,16363, 903,16362,16235,16373, + 6,16163,16329,16377, 7,16163,16167,16381,16205,16381,16361,16381, + 8717,16381,14315,16380, 4311,16381, 4329,16381, 3785,16381,10351,16381, +10055,16381, 973,16162, 9,16402, 972,16163,16341,16407,16165,16407, +16405,16407,16403,16407, 9,16415, 9617,16163, 1368,16418, 14,16418, + 2,16418, 7,16425,16423,16427, 7,16424, 5,16418, 6,16433, +16431,16435,16421,16435, 6,16432,16427,16441, 2,16419,16435,16445, +16171,16445, 7,16445,16433,16451, 9,16418, 587,16455, 587,16419, + 9,16459, 6,16418, 5,16462,16427,16465, 7,16418, 2,16468, +16435,16471,14315,16163, 7,16474, 17,16475, 903,16162, 3,16480, + 6,16483, 6,16482, 5241,16481, 1274,16480, 15,16480, 1275,16480, + 6,16480, 3,16496, 5,16496, 7,16480,16485,16503,16235,16503, + 6,16481,16495,16509,16493,16509, 7,16481,16499,16515,16501,16515, +16487,16515,16205,16515,16361,16515,16491,16515,16167,16515, 1, 903, + 9542,16530, 9543,16530, 1274,16530, 3,16530, 9541,16539, 6,16538, + 7,16538, 5,16545,16530,16547, 5,16539, 7,16551,16530,16552, +16530,16551, 7,16556, 7,16557,16543,16561, 6,16539, 9533,16565, +16545,16565,16555,16565,16559,16565,16549,16565, 7,16539,16543,16577, + 4,16530,16576,16581,16543,16583,16539,16581, 7,16586,16543,16589, + 7,16587,16565,16593,16545,16581,16565,16596,16565,16581,16545,16600, +16568,16581,16579,16581, 7,16581,16539,16608,16543,16611,16539,16609, +16545,16615, 1170,16530,16565,16619, 9541,16531,16535,16623, 559,16530, + 5241,16627, 767,16530,16565,16631, 165,16530, 6,16635, 7,16634, +16637,16639, 7,16635, 6,16634,16643,16645, 9540,16531,16543,16649, +16533,16649,16539,16649,16537,16649, 1275,16530,16623,16659, 9533,16659, + 257,16531, 483,16665, 483,16530, 257,16669, 15,16530, 5241,16673, + 6,16530, 3,16676,16649,16679, 7,16530,16541,16683,16566,16683, +16551,16682,16565,16689,16565,16683, 9533,16692, 375,16683, 1011,16682, +16565,16699, 9533,16683,16565,16702,15269,16683, 4827,16683, 6,16531, +16662,16711,16659,16711, 9533,16714, 9533,16711,16659,16718, 7,16531, +16539,16723, 9533,16725,16537,16723, 9533,16729, 1007,16723,16543,16723, + 9533,16735,16679,16723, 9533,16739, 331,16723, 1325,16723, 59,16723, + 9533,16722,16543,16749,16539,16749,16679,16749,16537,16749, 9533,16531, + 1275,16759,16711,16761, 7,16759,16565,16765, 7,16758,16539,16769, +16543,16769,16679,16769,16537,16769,15029,16531, 7,16779, 1011,16530, + 5,16782, 6,16785, 6,16784, 5241,16783, 14,16782, 1275,16782, + 15,16782, 6,16782, 5,16798, 3,16798, 7,16782,16787,16805, +16565,16805, 6,16783,16797,16811,16795,16811, 7,16783,16801,16817, +16803,16817,16789,16817,16543,16817,16679,16817,16793,16817,16537,16817, + 1, 1369, 1010,16833, 16,16833, 2,16833, 5,16838, 5,16839, +16837,16843, 7,16833, 4,16846,16843,16849, 4,16847,16841,16853, +16835,16853, 2,16832, 11,16859,15900,16833, 331,16832, 59,16832, + 6717,16833, 9,16869, 1325,16832, 265,16832, 4,16833, 7,16876, +16843,16879, 2,16877, 1,16882, 1,16877, 2,16886, 11,16877, + 1369,16891,16885,16893,16889,16893, 5,16833, 2,16898,16853,16901, +15705,16898, 1275,16898, 9,16907, 1346,16833, 9,16911,15705,16833, + 11,16915, 5,16914, 1275,16833, 5,16921, 17,16923, 5,16920, + 9,16927, 1275,16832, 6717,16931, 9,16933, 1, 1275, 5814,16937, + 902,16937, 902,16936, 3,16937, 7,16944, 413,16937, 1216,16937, + 6787,16937, 5,16953, 4,16952,16955,16957, 4,16953, 5,16952, +16961,16963, 1505,16937, 5771,16937, 903,16968, 1011,16937, 903,16972, + 903,16936,16941,16977, 241,16936, 17,16936, 5299,16983, 4915,16983, + 11,16936, 903,16937, 5771,16990,16943,16991, 1011,16990,15208,16937, + 9,16937,15029,17000,15029,16937, 9,17004, 4,16936, 265,17009, + 5,16936, 4,16937, 1011,17015, 1369,16936, 6717,17019, 9,17021, + 1, 17, 4,17025, 6,17026, 113,17025, 1275,17024, 5299,17033, + 4915,17033, 241,17025, 2,17024, 3,17024,11731,17025, 265,17045, + 1, 15, 5886,17049, 5,17048, 483,17053, 413,17049, 1216,17049, + 165,17049, 5843,17049, 1011,17062,14315,17049, 17,17067, 903,17049, + 1011,17070, 1011,17048, 241,17048, 903,17048, 5241,17079, 1011,17049, + 5843,17082, 903,17082,15204,17049, 483,17049,15029,17090,15029,17049, + 483,17094, 3,17048, 483,17099, 2,17049, 3,17049, 5,17105, + 1,17106, 1,17105, 5,17110, 483,17105, 15,17115,17109,17117, +17113,17117, 1369,17105, 0, 1011, 2,17125, 7,17127, 9565,17129, + 5,17124, 9565,17133,17129,17134,17130,17133,17129,17133, 9565,17140, + 6,17133,17127,17145, 9565,17147, 9600,17125, 9,17151, 5267,17125, + 9,17155,16722,17125,10385,17125, 9,17161, 587,17125, 9565,17164, + 9,17167, 9,17165, 9565,17171, 1275,17125, 903,17175, 9,17125, + 375,17125, 587,17181, 9,17124, 5267,17185, 9600,17185, 9565,17185, + 587,17190, 587,17185, 9565,17194, 587,17124, 375,17199,13737,17125, + 9,17203, 6,17124,17176,17207,17175,17207, 903,17210, 903,17207, +17175,17214, 7,17124,10001,17219, 903,17221, 6,17125, 3,17224, +17219,17227, 903,17229, 7,17125, 88,17233, 89,17233, 265,17233, + 264,17232,17239,17241, 264,17233, 3,17233, 9,17246, 3,17232, +17237,17251, 9,17251, 2,17232,17235,17257,17249,17257,17247,17257, + 9,17263, 265,17232,17245,17267, 2,17233,17254,17271, 9,17271, +17251,17274,17251,17271, 9,17278,16531,17232, 9,17233, 3,17284, +17257,17287, 3,17285,17271,17291, 903,17233, 9565,17125, 1368,17297, + 14,17297, 2,17296, 7,17303, 2,17297, 7,17306, 7,17307, +17301,17311, 5,17297,17305,17315,17129,17315, 6,17314,17311,17321, + 6,17315,17309,17325,17303,17325,17299,17325, 587,17296, 9,17333, + 9,17297, 587,17337, 6,17297, 5,17340,17311,17343, 7,17297, + 2,17346,17325,17349,12377,17125, 9,17353,16531,17125, 6,17357, + 7,17357, 6,17356,17361,17363, 7,17356,17359,17367, 0, 903, + 767,17370, 4617,17373, 483,17375, 15,17371, 1011,17379, 767,17371, + 4588,17383, 483,17383, 4579,17386, 4579,17383, 483,17390, 375,17371, + 11,17395, 483,17370, 2265,17399, 4421,17399, 5285,17399, 11,17370, + 375,17407, 6,17370,17380,17411,17379,17411, 1011,17414, 1011,17411, +17379,17418, 7,17370, 3549,17423, 2001,17423, 8495,17423,10291,17423, + 1011,17431,14073,17423,11277,17423, 4971,17423, 5045,17423, 6,17371, + 5,17442,17423,17445, 1011,17447, 7,17371, 1011,17451, 0, 1369, + 2789,17455, 2821,17455, 2759,17455, 2687,17455, 6658,17455, 2,17455, + 6,17466, 6625,17455, 9,17470,12551,17455, 1347,17455,13808,17455, + 6685,17455,13833,17455, 4413,17455,17025,17455, 265,17487, 241,17486, +17038,17455, 903,17455, 9,17455, 6625,17496, 17,17454,12377,17501, + 11,17454,12377,17505, 803,17455, 15,17454, 5303,17511, 4927,17511, +17033,17511,16983,17511, 265,17454, 2853,17521,17082,17455, 11,17455, +12377,17526,12564,17455, 241,17455,13737,17532,17025,17532, 1011,17455, +17049,17538,12377,17455, 10,17543, 10,17542, 305,17543, 11,17543, +17547,17551, 11,17542,17545,17555,17049,17455, 1011,17558, 4,17454, + 5,17455,13737,17455, 241,17566, 0, 1275, 3,17570, 9,17573, + 4,17570, 5,17570, 9856,17579, 9805,17579, 9,17582, 9,17579, + 9805,17586, 5,17571, 3,17591, 0,17592, 0,17591, 3,17596, + 9,17591, 1275,17601,17595,17603,17599,17603, 17,17591, 9805,17609, + 1369,17590, 17,17613, 1486,17571, 17,17617, 1369,17571,17577,17621, + 9,17623, 5,17621, 9,17627, 5,17620, 17,17631, 0, 17, + 4,17634, 587,17637, 155,17635, 1011,17635, 1369,17634,12377,17645, +16990,17635, 587,17635,12377,17650,12566,17635, 903,17635,16937,17656, +12377,17635, 587,17660,16937,17635, 903,17664, 3,17634, 483,17669, + 2,17635, 4,17673, 0,17674, 0,17673, 4,17678, 587,17673, + 17,17683,17677,17685,17681,17685, 3,17635, 1369,17691, 0, 15, + 5,17695, 7,17696, 1369,17694, 5303,17701, 4927,17701,16983,17701, +17033,17701, 3,17694, 3,17695,10104,17712,10105,17713,17715,17717, +10104,17713,10105,17712,17721,17723, 1, 13, 113,17727, 0, 12, +17727,17731, 9,17732, 2,17735, 2,17734, 137,17732, 136,17732, + 2,17733,17741,17745, 3,17733,17739,17749,17743,17749, 2,17732, + 9,17754,17749,17757,17749,17755, 3,17732,17737,17763,17745,17763, + 0, 13, 1, 12, 1369,17771, 33,17771, 3,17770, 8251,17777, + 3807,17777, 9875,17777, 8165,17777, 3,17771, 8241,17787,17769,17771, + 9,17791, 2,17792, 2,17793, 137,17791, 136,17791, 2,17791, + 9,17802, 3,17791,17797,17807, 2,17790,17807,17811,17799,17811, + 3,17790,17805,17817,17795,17817,17803,17817,17801,17817, 1, 413, + 4,17826, 2,17826, 5,17826, 6,17833, 6,17832, 3,17826, + 6,17839, 6,17838, 2653,17827, 1637,17827,14537,17827,14321,17827, + 260,17826, 2903,17827, 1639,17827, 1641,17827, 3361,17827, 331,17826, +17521,17827, 4909,17827,14593,17827, 261,17826, 257,17826, 14,17826, + 1274,17826, 2159,17827, 2161,17827, 251,17827, 2647,17827, 331,17885, + 15,17826, 1275,17826,14652,17827, 6,17827,17829,17895,17831,17895, + 8997,17895,17863,17895,17871,17895,17889,17895,17891,17895, 7,17827, +17833,17911,17839,17911, 8495,17911, 413,17910, 0,17919,17837,17911, +17843,17911, 265,17911,17921,17927, 1,17927,17919,17931, 2647,17927, + 8717,17911, 3785,17911,17853,17911,17875,17911,17877,17911,14315,17910, + 261,17911, 7,17826,17835,17951,17841,17951, 8647,17951, 251,17951, + 6,17826, 5,17960,17911,17963, 3,17960,17911,17967,15029,17827, + 265,17971,17895,17973, 7,17971,14315,17827, 6,17978, 7,17978, + 6,17979,17983,17985, 7,17979,17981,17989, 0, 412, 9036,17993, + 9099,17993,17829,17993,17895,17998,17831,17993,17895,18002,17896,17993, +17898,17993,17913,17993,17915,17993, 446,17993, 4371,18015, 4379,17993, +17900,17993,17917,17993, 4360,17993, 3429,17993,17882,17993, 7039,17993, +17958,17993,17949,17993, 241,17993, 445,18036, 4371,18039, 445,18037, + 4349,18043,16097,17993,12289,17993, 8647,17993, 8997,18050, 4349,17993, + 251,18054,17951,17993, 251,18058, 251,17993, 4349,18062,17827,18062, +17951,18062,17895,17993,17829,18070,17831,18070, 8997,18070, 5521,17993, + 375,18079, 445,17993, 241,18082, 4371,18085, 3,18083, 2,18082, +18089,18091, 2,18083, 3,18082,18095,18097, 465,17993, 5,18101, + 4,18100,18103,18105, 4,18101, 5,18100,18109,18111, 9082,17993, + 8495,18115,17910,17993,17833,18119,17839,18119, 8495,18119, 375,17993, + 7,17993, 8495,18129, 8997,18131,17827,18129,17829,18135,17831,18135, + 8997,18135, 8997,18128, 8495,18143,17827,18128,17833,18147,17839,18147, + 8495,18147, 8997,17993, 8647,18154,17895,18154, 7,18154, 8495,18161, +17827,17993, 241,18164, 6,18167, 6,18166, 265,18165,17895,18173, + 261,18164, 375,18165, 260,18164, 251,18164, 6,18165,18177,18185, + 7,18165,18171,18189,18181,18189, 6,18164,18173,18195, 241,18194, +18189,18199,18189,18195, 7,18164,17833,18205,17839,18205,18169,18205, +18185,18205, 8495,18205, 1, 843, 0, 842,18217,18219, 483,18220, + 4,18223, 4,18222, 581,18220, 580,18220, 4,18221,18229,18233, + 5,18221,18227,18237,18231,18237, 4,18220, 483,18242,18237,18245, +18237,18243, 5,18220,18225,18251,18233,18251, 0, 413,15309,18257, + 265,18258,15363,18261,15424,18257,15363,18265,13375,18257,13381,18257, + 4888,18257,13162,18257, 251,18256, 375,18256, 265,18257,15309,18281, +15383,18283,15309,18280,15363,18287, 331,18257, 2663,18257, 251,18293, + 9,18256, 483,18256, 375,18257, 4863,18300,13119,18300, 4863,18257, + 375,18306,13119,18257, 375,18310, 6,18257, 264,18314, 7,18257, + 264,18318, 264,18319, 265,18319,18321,18325, 265,18318,18323,18329, + 8647,18319, 375,18319, 331,18319, 7,18256, 1689,18339, 1705,18339, + 2701,18339,18317,18339, 8717,18339,12755,18339, 7627,18339, 7895,18339, + 3785,18339,13443,18339, 7287,18339, 265,18339, 331,18339, 8495,18339, + 375,18339,12745,18339, 457,18371, 375,18371, 6,18256,18291,18377, +12745,18257,17895,18381, 8647,18381, 7,18381, 8495,18387, 1, 412, + 1679,18391, 448,18391, 4349,18395, 4351,18391, 4390,18391,18300,18391, + 4457,18391,18277,18391, 1673,18391,18279,18391, 1789,18391,18364,18391, +18335,18391, 3427,18391, 7037,18391, 265,18391, 445,18422, 4349,18425, + 445,18423, 4371,18429,16095,18391,12287,18391, 5189,18391,18299,18391, +18297,18391, 2153,18391, 2151,18391, 4371,18391, 331,18446,18339,18391, + 331,18450, 331,18391, 4371,18454,18339,18454, 445,18391, 265,18460, + 4349,18463, 5,18461, 4,18460,18467,18469, 4,18461, 5,18460, +18473,18475, 465,18391, 3,18479, 2,18478,18481,18483, 2,18479, + 3,18478,18487,18489, 8386,18391,18318,18391, 375,18391,18257,18496, + 7,18391, 265,18501,18257,18503, 8337,18500,18257,18500, 8337,18391, + 7,18510, 8861,18391, 6,18515, 7,18515, 6,18514,18519,18521, + 7,18514,18517,18525,18257,18391, 265,18528, 241,18529, 6,18532, + 6,18533, 375,18528, 261,18529, 260,18529, 251,18529, 6,18529, + 241,18546,18531,18547, 7,18529, 8495,18553,18537,18553, 6,18528, +18553,18559,18541,18559, 7,18528,18549,18565,18535,18565,18547,18565, +18543,18565, 0, 843, 1, 842, 5,18576,18575,18577, 483,18581, + 4,18582, 4,18583, 581,18581, 580,18581, 4,18581, 483,18592, + 5,18581,18587,18597, 4,18580,18597,18601,18589,18601, 5,18580, +18595,18607,18585,18607,18593,18607,18591,18607, 1, 1217,16117,18617, +12291,18617,16103,18617, 4959,18617,17399,18617, 2205,18617, 2207,18617, + 1269,18617, 5,18633, 4,18632,18635,18637, 4,18633, 5,18632, +18641,18643, 1259,18617, 2,18647, 3,18646,18649,18651, 3,18647, + 2,18646,18655,18657, 7,18617, 0, 1216, 9,18662,18617,18665, + 483,18662,18617,18669,18660,18663, 7,18663,18617,18674,18617,18663, + 6,18679, 7,18679, 6,18678,18683,18685, 7,18678,18681,18689, + 1, 1531, 4904,18693,17609,18693,17586,18693, 4903,18693, 9,18700, +17579,18693, 9,18704, 9,18693, 4903,18708,17579,18708, 5,18692, + 0, 1530,18693,18717, 4,18719, 5,18719, 4,18718,18723,18725, + 5,18718,18721,18729, 1, 19, 1369,18733, 3,18733, 3,18732, + 9875,18739, 0, 18,18733,18743, 2,18745, 3,18745, 2,18744, +18749,18751, 3,18744,18747,18755, 0, 1217,12293,18759,16105,18759, + 1269,18759, 2,18765, 3,18764,18767,18769, 3,18765, 2,18764, +18773,18775, 1259,18759, 5,18779, 4,18778,18781,18783, 4,18779, + 5,18778,18787,18789, 375,18759, 7,18759, 1, 1216, 4,18796, +18759,18799, 3,18796, 6,18803, 6,18802, 5,18796, 6,18809, + 6,18808, 2,18796,18759,18815, 5241,18797, 14,18796, 1274,18796, + 2157,18797, 2155,18797,18795,18797,18799,18829,18815,18829, 15,18796, + 1275,18796, 6,18796, 3,18838, 5,18838, 7,18796,18805,18845, +18811,18845,18794,18797,18803,18851,18809,18851, 6,18797,18800,18857, +18816,18857,18799,18857,18759,18862,18815,18857,18759,18866,18835,18857, +18837,18857,18759,18857,18799,18874,18815,18874, 7,18797,18841,18881, +18843,18881,18803,18881,18759,18887,18809,18881,18759,18891,18807,18881, +18813,18881,18821,18881,18823,18881,18759,18880,18803,18903,18809,18903, +18759,18797, 6,18909, 7,18909, 6,18908,18913,18915, 7,18908, +18803,18919,18809,18919,18911,18919, 0, 1531, 1, 1530, 6717,18929, + 9,18931,18927,18929, 4,18935, 5,18935, 4,18934,18939,18941, + 5,18934,18937,18945, 0, 19, 1, 18,18949,18951, 2,18953, + 3,18953, 2,18952,18957,18959, 3,18952,18955,18963, 0, 2, +11303,18967,11349,18968, 5071,18967, 5097,18972,11350,18967, 5098,18967, +11304,18967,11307,18981, 5072,18967, 5075,18985,11315,18967, 5079,18967, +13961,18967, 581,18993, 4,18992,18995,18997, 5,18992, 580,18993, +19001,19003, 5,18993, 4,18993, 483,19008,19001,19011, 483,18993, + 4,19014,19001,19017, 4,19015,19007,19021, 1181,18966, 1206,18966, + 3451,18967, 375,19029, 1967,18967, 375,19033, 567,18966, 4992,19037, + 9,19037, 4971,19040, 4971,19037, 9,19044, 1141,18966, 555,18966, + 981,18967,16129,18966,16143,19055, 9523,18967, 483,19059, 9525,19061, + 1007,18967, 1297,18966, 524,18966, 0,19069, 4,19070, 4,19069, + 0,19074, 97,18967,11067,18967, 1275,19080, 7947,19083, 1205,18967, + 571,18967,11070,18967, 7947,19091,10043,18967, 1275,19094,10041,19097, +10044,18967,10041,19101, 1206,18967, 3001,19105, 1901,19105, 30,18967, + 8165,19111, 8150,18967, 33,19115, 1181,18967, 3663,19119, 1997,19119, + 3069,19119, 1923,19119, 9769,18967, 3972,18967, 8124,18967, 9357,18967, + 9346,18967, 8782,18967, 4244,18967, 4178,18967, 9768,18967, 8804,18967, + 8245,18967, 8249,18967, 8247,18967, 6950,18967,12299,18967, 4652,18967, +10684,18967,14096,18967, 4992,18967, 203,18967,11731,19167,17771,18967, + 113,19171,14223,18967, 85,18967,11731,19177,11031,18967, 113,19181, + 107,18967,11731,19185,11699,18967, 113,19189, 8701,18967, 9293,18967, + 3933,18967, 9,19196, 8109,18967, 9,19200, 4213,18967, 9,19204, + 4147,18967, 9,19208, 8757,18967, 9,19212, 9335,18967, 9,19216, +10202,18967, 7947,19221,17637,19221, 578,18967, 4935,19227,11349,18967, +11303,19230, 5097,18967, 5071,19234, 8647,18967, 11,19239,10603,18967, + 375,19243,10427,19243,10609,19243, 7,19243,10607,19251, 9,19242, + 4625,18967, 375,19257, 75,19257, 4629,19257, 7,19257, 4627,19265, + 9,19256,11277,18967, 10,19270,11307,19273, 10,19271,11349,19277, + 483,19271, 5045,18967, 10,19282, 5075,19285, 10,19283, 5097,19289, + 483,19283, 6789,18967, 9,19294, 288,18967, 525,18967,19073,19301, +19077,19301, 1811,19301, 1877,19301, 5,19301,17563,19301, 4861,19301, + 1290,18967, 5,19317, 3721,19317, 1985,19317,17563,19317, 4861,19317, + 296,18967, 8861,19329, 12,18967, 8165,19333, 18,18967, 25,18967, + 9,19338, 8165,19341, 8165,19339, 9,19345, 7971,18967, 9,19348, + 33,19351, 33,19349, 9,19355, 47,18967,11731,19359,10107,18967, + 1275,19362, 7947,19365,17637,19365, 113,19363, 59,18967,17635,19373, +10291,18967, 165,19377, 375,18967, 510,18967, 11,18967, 8165,19385, + 9,19387, 265,19384, 9,19384, 8165,19393, 9,18967, 567,19397, + 4971,19399, 6,19397, 25,19396, 8165,19405, 7971,19396, 33,19409, + 3933,19396, 8109,19396, 4213,19396, 4147,19396, 9335,19396, 8757,19396, + 8495,19396, 6789,19396, 4625,19396,10603,19396, 4971,19396,14073,19396, + 567,19396, 4935,19437, 11,19397, 8109,19441, 3933,19441, 8495,19441, + 7971,19441, 265,19396, 8861,19451, 11,19396, 8165,19455, 483,19396, + 17,18967, 1275,19460, 4861,19463,17563,19463, 3721,19463, 1985,19463, + 15,19460, 15,18967, 9731,19474, 1011,19475, 483,19475, 17,19474, + 6515,18967, 483,19485, 6527,19487, 6557,19487, 6561,19487,14210,18967, + 17,19495, 4971,18967, 9,19498,14073,18967, 9,19502, 5921,18967, + 375,19507,10046,18967, 16,18966, 0,19513, 4,19514,19317,19517, +19463,19517, 4,19513, 0,19522,19317,19525,19463,19525, 8495,19513, +10351,19513, 4311,19513, 4329,19513, 8717,19513,10055,19513, 3785,19513, + 14,18966, 6,19545, 2,19546, 2,19545, 6,19550, 482,19545, + 17,19545, 10,18966,17777,19559, 2215,19559,11307,19559, 5075,19559, +11713,19559, 2221,19559,11087,19559,10439,19559,10665,19559, 4643,19559, +11037,19559, 2233,19559, 9195,19559,11277,19559, 5045,19559,19455,19559, +19333,19559,19393,19559,19385,19559, 9,19597, 9317,19559, 9755,19559, + 4321,19559,10171,19559, 4295,19559, 3833,19559,10603,19559, 9,19613, + 4625,19559, 9,19617, 8,18967, 11,19621, 14,18967, 9731,19625, + 17,19625, 11,18966, 8124,19631, 3972,19631, 8804,19631, 8150,19631, + 7971,19631, 9,19640, 3933,19631, 9,19644, 8109,19631, 9,19648, + 8495,19631, 9,19652, 9,19631, 8109,19656, 3933,19656, 8495,19656, + 7971,19656, 9,18966,10001,19667, 5,19669, 4,19668,19671,19673, + 4,19669, 5,19668,19677,19679, 16,18967, 7,19683, 10,18967, +11277,19686,11307,19689, 5045,19686, 5075,19693,11349,19687, 5097,19687, + 9195,19687,19656,19687,19441,19687,19631,19687, 9,19706,11277,19687, +11303,19711, 5045,19687, 5071,19715, 9,19687,19631,19718, 19,18967, + 13,18967,19631,19725,10385,18967, 101,19729, 128,19729, 9,19729, + 113,19734, 483,19729,10081,19739,11759,19739,10405,19739, 113,19729, + 9,19746, 67,18967,11613,19751,12216,19751, 9,19751,11731,19756, +11731,19751, 9,19760, 566,18967, 253,19765, 1471,19765, 53,19765, + 256,18967, 629,18967, 1413,18967, 1471,19777, 1346,18967, 340,18967, + 8165,19783, 567,18967, 4935,19787, 9,19789, 9,19786, 4935,19793, + 305,18967, 959,18967,11731,19799, 759,18967,11731,19803, 331,18967, +17635,19807, 1325,18967,17635,19811,10001,18967,10003,19815, 4,19817, + 4,19816,10007,19815, 580,19815,10006,19815, 483,19815, 4,19828, + 4,19829, 581,19815, 4,19815,10003,19836, 483,19836, 5,19815, +19819,19843,19833,19843, 4,19814,19835,19849,19823,19849,19843,19849, + 5,19814,19839,19857,19821,19857,19825,19857,19827,19857,19841,19857, +19831,19857,19837,19857, 9731,18967, 15,19872, 8495,18967, 483,19877, + 9,19876, 9195,18967, 113,19883,11731,19883, 241,18967, 7,19888, + 483,18967, 9,19892, 17,19893, 903,19897, 5,19892, 253,19901, + 1471,19901, 53,19901, 5,19893, 1505,19909, 903,18967, 7,19913, + 1275,18967,10043,19916,10041,19919,11067,19916, 7947,19923,17637,19917, +10107,19927, 0,19916, 4,19931, 0,19932,19917,19935, 7,19932, +19937,19939, 7,19931, 4,19942, 16,19931, 6,19916, 4,19949, + 6,19950,19917,19953, 1,19950,19955,19957, 1,19949, 4,19960, + 8,19916, 4,19965, 1,19966, 1,19965, 4,19970,10107,19916, + 7947,19975,17637,19975, 7947,19917,11067,19981,10107,19981, 9,19917, + 2009,19987, 3135,19987,19969,19987,19973,19987, 5231,19987,19957,19987, +19963,19987, 0,19987, 5175,19987,14065,19987, 17,19916,19525,20009, +19517,20009, 3721,20009, 1985,20009, 1,20009,19987,20019,20003,20009, + 4861,20009,17563,20009, 5,19916, 4,19917, 5,19917, 265,18967, +17635,20035, 5771,20035, 9,20035, 11,20034, 11,20035, 9,20034, + 8861,20047, 483,20035, 7,20034, 8165,20053, 7,20035, 8495,20057, + 587,18967, 7,20061, 4,20063, 4,20062, 16,20061, 17,20061, + 4,20060,20071,20073, 5,20060,20067,20077,20069,20077, 4,20061, + 7,20082,20077,20085, 5,20061,20065,20089,13947,18967, 5,20092, + 17,20095, 5,20093, 9,20099, 4,18966, 8770,20103, 8729,20103, + 8697,20103, 8784,20103, 4266,20103, 9262,20103, 2,20103, 7,20117, + 8684,20103, 8717,20121, 331,20121, 8647,20103, 8757,20126, 8757,20103, + 8647,20130, 375,20130, 4213,20103, 375,20136, 9750,20103,19687,20103, + 347,20103, 386,20103, 340,20103, 331,20149, 375,20103, 8757,20152, + 4213,20152, 9195,20152, 305,20152, 9,20103,10291,20103, 483,20165, + 59,20103, 15,20103, 9195,20103, 375,20172, 331,20103,10001,20103, + 9,20179, 305,20103, 375,20182, 7,20103, 8495,20186, 8717,20189, + 331,20189, 8495,20187, 8757,20195, 9731,20186, 265,20187, 8757,20201, + 4213,20201, 9195,20201, 305,20201, 265,20186, 331,20211, 8647,20187, + 1325,20103, 7,20102, 8495,20219,10351,20219, 4311,20219, 4329,20219, + 3785,20219,10055,20219, 8717,20219, 483,20103, 1275,20103, 265,20103, + 7,20239, 8495,20241, 375,20241, 7,20238, 331,20247, 9731,20103, + 7,20250, 8495,20103, 7,20254, 8717,20257, 331,20257, 483,20255, + 9,20255, 7,20255, 8647,20267, 375,20267, 5,18966, 9535,20273, + 9537,20273, 2,20273, 6,20278, 9559,20273, 482,20273, 9563,20273, + 9362,20273, 922,20273, 1413,20273, 19,20273, 12,20273, 8150,20273, + 8804,20273,19385,20273, 1290,20273, 9533,20305, 525,20273, 9533,20309, + 7971,20273, 9,20312, 11,20273, 9,20316, 17,20273, 1275,20320, + 9533,20323, 9,20273, 9195,20326, 11,20326, 7971,20326, 8495,20326, + 9195,20273, 9,20336, 6,20273, 5,20341, 2,20340, 5,20340, +18967,20347, 11,20341, 7,20273, 5,20353, 6,20272, 17,20357, + 7,20272, 9195,20361,11277,20361, 5045,20361, 9755,20361, 4295,20361, +10171,20361, 4321,20361, 3833,20361, 9317,20361, 483,20273, 903,20380, + 1275,20273, 17,20384, 9533,20387, 903,20273, 483,20390, 8495,20273, + 9,20394, 9731,20273, 6,20398, 7,20398, 6,20399,20403,20405, + 7,20399,20401,20409, 6,18966,19836,20413,19857,20415,19854,20413, +19871,20413,19815,20413, 4,20423,19843,20425, 4,20422,19857,20429, +19477,20413,19145,20413,19875,20413,19843,20413,19849,20438,19849,20413, +19843,20442,19718,20413,19473,20413,19483,20413,19725,20413, 19,20413, + 12,20413,19337,20413,19687,20413, 9,20460,19475,20413, 9731,20465, + 17,20465, 9,20413,19687,20470, 11,20470, 11,20413, 9,20476, + 8495,20413, 5,20413, 9,20483, 4,20413,19815,20487,19849,20489, +19815,20486,19857,20493, 5,20412, 17,20497, 7,18966,10439,20501, +11087,20501,10665,20501, 4643,20501,11307,20501, 5075,20501,17777,20501, + 2215,20501,18739,20501, 4339,20501,11713,20501, 2221,20501,11037,20501, + 2233,20501,19626,20501,19129,20501, 0,20501, 4,20534,19301,20537, +19317,20537,19463,20537,20009,20537,10036,20501,19843,20547, 8800,20501, + 8714,20501, 5045,20501,11277,20501, 4551,20501,19628,20501,19455,20501, +19393,20501,19723,20501,19333,20501, 305,20501, 8495,20570, 959,20501, +19625,20501, 9731,20576, 17,20576,10603,20501, 9,20583, 4625,20501, + 9,20587,19385,20501, 9,20591, 759,20501, 47,20501,10107,20501, + 241,20599, 265,20598,10196,20501, 11,20501, 8495,20606, 17,20501, +19625,20610, 59,20501,10291,20501, 1011,20617, 15,20501, 1325,20501, + 8495,20501, 10,20624, 10,20625, 305,20624, 11,20624,20629,20633, + 11,20625,20627,20637, 9731,20501,19625,20640, 4,20501, 7,20645, + 483,20647,18967,20649, 0,20644,19301,20653,19317,20653,19463,20653, +20009,20653,20651,20653, 7,20644,19916,20665,20653,20667, 1275,20665, +18967,20670,20653,20673,18967,20665, 1275,20676,20653,20679,10001,20644, +19843,20683, 1011,20645,10047,20645, 5,20501, 9287,20691, 331,20501, + 4,20500, 8495,20697, 4311,20697,10351,20697, 3785,20697, 4329,20697, + 8717,20697,10055,20697, 5,20500, 9195,20713,11277,20713, 5045,20713, + 4321,20713, 9755,20713, 4295,20713,10171,20713, 9317,20713, 3833,20713, + 903,20501, 265,20501,10107,20734, 9195,20501, 241,20739,10001,20501, + 4,20742,19843,20745, 5,20742,18967,20748, 4,20743,20751,20753, +19511,20753,19857,20753, 5,20743, 7,18967, 8810,20762, 8811,20762, + 2,20763, 1,20768,20483,20763, 8495,20773, 8800,20763,20273,20763, + 8495,20763, 11,20780, 8810,20763,20767,20785,10081,20763, 1011,20789, + 1010,20788,20791,20793, 1010,20789, 1011,20788,20797,20799, 566,20763, + 11,20763, 9731,20805, 8495,20805, 8495,20804, 265,20763,20482,20763, + 17,20815, 567,20763, 9195,20819, 9,20763, 8811,20763,20765,20825, + 241,20762, 265,20762, 8165,20831, 1011,20763, 375,20763, 4,20762, +20815,20839, 5,20762,11276,20842, 5044,20842,11277,20842,11276,20843, +20849,20851, 5045,20842, 5044,20843,20855,20857,20773,20843,20470,20843, +20103,20843,20413,20843, 9,20866, 9195,20843,11277,20843,20845,20873, + 5045,20843,20847,20877, 9,20843,20413,20880, 4,20763,20480,20885, + 7,20884,20843,20889, 9366,20885, 1,20885, 3,20894,20842,20896, +20843,20897,20899,20901,20889,20900,20842,20897,20843,20896,20907,20909, +20890,20897,20889,20897,20843,20914, 3,20885, 1,20918,20842,20920, +20843,20921,20923,20925,20889,20924,20842,20921,20843,20920,20931,20933, +20890,20921,20889,20921,20843,20938, 9195,20885, 483,20942,20866,20885, + 8495,20885,20413,20948, 483,20885, 9195,20952,20413,20885, 8495,20956, +20843,20956,20843,20885, 1,20962, 3,20964, 3,20962, 1,20968, + 7,20963,20897,20973,20921,20973,20967,20973,20971,20973,20413,20962, + 5,20763, 7,20985, 17,20985,20413,20989,20413,20984,20839,20993, + 17,20993, 483,20984,20839,20985, 1,21001, 3,21002, 3,21001, + 1,21006, 7,21000,21005,21011,21009,21011,20413,21001,20413,20763, + 5,21019,20885,21021, 9,21021, 5,21018,20839,21027, 17,21027, + 483,20763, 5,21032, 5,18967, 0,21037, 3,21038, 9357,21037, +20742,21037,20761,21045,20187,21037, 8495,21049,20501,21037,10001,21036, +20753,21055,20763,21037, 8495,21059,13947,21036, 17,21063, 256,21037, +20186,21037,20885,21037, 7,21071,20897,21073,20921,21073, 9,21037, + 1275,21079, 9533,21081,21041,21081, 17,21037, 9195,21087, 7971,21087, + 8495,21087, 483,21036, 253,21095, 1471,21095, 53,21095, 1275,21036, + 6,21036,20640,21105,20610,21105,21069,21105, 9731,21105,20501,21112, +20501,21105, 9731,21116, 17,21116, 17,21105,20501,21122, 7,21036, +11276,21126, 5044,21126,11277,21126,11276,21127,21133,21135, 5045,21126, + 5044,21127,21139,21141, 1,21127, 3,21144,18967,21147, 3,21127, + 1,21150,18967,21153,18967,21127,20470,21127,21049,21127,20413,21127, + 9,21162,20103,21127, 9195,21127,11277,21127,21129,21171, 5045,21127, +21131,21175, 9,21127,20413,21178, 6,21037,21149,21183,21155,21183, +20254,21183,19243,21183,19257,21183,18967,21183, 1,21183, 3,21196, +21126,21198,21127,21199,21201,21203,21126,21199,21127,21198,21207,21209, + 3,21183, 1,21212,21126,21214,21127,21215,21217,21219,21126,21215, +21127,21214,21223,21225, 8495,21183,20103,21228,19687,21183,20843,21183, +21166,21183, 11,21183,20501,21239,20103,21183, 8495,21242,21127,21242, +21127,21183,20103,21248,20763,21183, 9731,21253, 17,21253, 7,21037, +19625,21259, 15,21259,20413,21263,20103,21258,21105,21267, 241,21258, +21105,21259,20103,21273,20103,21037, 7,21277,21199,21279,21215,21279, +11277,21279, 5045,21279,21183,21279, 6,21276, 1,21291, 3,21292, +21279,21295, 3,21291, 1,21298,21279,21301, 7,21276,21105,21305, + 241,21037, 483,21309, 7,21308, 4,18967,21183,21315, 0,21314, +20309,21319, 524,21319,20273,21323,20305,21319, 1291,21319,20273,21329, +21081,21319,20323,21319,20387,21319, 11,21319, 483,21338,20273,21341, + 483,21319, 11,21344,20273,21347, 165,21315,17635,21315, 1011,21352, +17642,21315,20413,21315, 6,21359, 9,21315,20352,21315,11277,21365, + 5045,21365,20985,21315, 11,21315,10075,21315, 483,21315, 1347,21315, + 6,21314, 1,21381, 3,21382,21365,21385, 3,21381, 1,21388, +21365,21391,20273,21381, 11,21381, 7,21314, 6,21315, 17,21401, + 7,21315,21384,21404,21390,21404,21385,21405,20273,21411,21407,21411, +21391,21405,20273,21417,21409,21417,21385,21404,21384,21405,21423,21425, +21391,21404,21390,21405,21429,21431,11276,21404, 5044,21404,11276,21405, +11277,21404,21439,21441, 5044,21405, 5045,21404,21445,21447, 0,21405, + 4,21450, 4,21405, 0,21454, 8495,21405, 5045,21405,20273,21461, +21437,21461,11277,21405,20273,21467,21435,21467, 9,21405,20273,21404, +21385,21475,21391,21475,11277,21475, 5045,21475, 265,21405, 483,21405, +18967,21487,21453,21489,21457,21489,21381,21405,20273,21315, 6,21497, + 1,21499, 3,21500, 3,21499, 1,21504, 7,21496,21503,21509, +21507,21509,21385,21509,21391,21509,11277,21509, 5045,21509, 1011,21315, +17635,21522, 6,18967, 2,21526, 11,21529,20103,21527,20690,21527, + 9,21535,21259,21527, 9,21539, 17,21527, 4,21526, 11,21545, + 5,21526,20640,21549,21259,21549,20610,21549, 9731,21549,20501,21556, +20501,21549, 9731,21560, 17,21560, 17,21549,20501,21566, 4,21527, + 15,21571, 5,21527, 482,21575, 2,21575, 6,21578, 6,21575, + 2,21582, 9,21575,20501,21587,20501,21574, 9,21591,20501,21527, + 5,21595, 17,21597, 5,21594, 9,21601, 1, 3,19718,21604, +19719,21604,19402,21605,20962,21604,20973,21613,21248,21604,21272,21604, +21494,21604,20963,21604,21249,21604,21001,21604,21011,21627,21273,21604, +21495,21604,21178,21604,20880,21604,21179,21604,20881,21604,21049,21604, +20773,21604,21361,21604,15753,21605, 803,21649,14387,21605, 375,21653, + 9663,21604, 9177,21604,20351,21604,20485,21604,21360,21604, 990,21604, + 4745,21667,19685,21605,21087,21671,21156,21605,21087,21675,21317,21605, +21291,21604,21279,21681,21499,21604,21509,21685, 996,21604, 4745,21689, +21472,21604,21473,21604, 761,21605, 3419,21697, 6469,21697, 3119,21697, +21048,21604,20772,21604, 973,21604, 955,21708, 4745,21711, 9,21708, + 4745,21715, 4745,21709, 955,21719, 9,21719, 2077,21605, 7,21725, + 14,21724,21727,21729, 6,21725, 15,21724,21733,21735,20350,21604, +20484,21604, 9662,21604, 9176,21604,21380,21604,21104,21604,21126,21604, +21183,21751, 9,21751,20842,21604,20885,21757, 9,21757, 305,21604, +18967,21763, 375,21765, 955,21604, 973,21769, 4805,21771, 973,21768, + 4745,21775,17423,21769, 4745,21769, 713,21604,21404,21604,21381,21785, + 9,21785,20884,21604,21316,21605,21182,21604,20501,21795,21793,21795, +21405,21604,21381,21800, 9,21800,20885,21604,20843,21806,20890,21807, +20889,21807,20843,21812,20973,21807,21073,21807,20413,21807,20843,21807, +21757,21823,20889,21822,21183,21604,21127,21828,21279,21829,21679,21829, +20103,21829,21127,21829,21751,21839,21105,21604,21381,21604,21365,21845, +21405,21844,20413,21845,21475,21845,21405,21845,21785,21855,20273,21855, +21509,21845,20843,21604,20885,21862, 9,21862,21127,21604,21183,21868, +18967,21869,21183,21873, 9,21868, 1199,21605,13923,21604,13935,21881, + 9437,21605, 587,21885, 9439,21887, 1177,21605, 1421,21604, 668,21604, + 1,21895, 5,21896, 5,21895, 1,21900, 117,21605,11759,21605, + 1369,21906, 7971,21909,11760,21605, 7971,21913, 809,21605, 989,21605, + 9929,21605, 1369,21920, 9927,21923, 9930,21605, 9927,21927,19596,21605, + 9,21931,19556,21605,20170,21605,19707,21605, 9,21939,20956,21605, +21791,21943,21242,21605,21795,21947,20773,21605,21707,21951,21049,21605, +21705,21955,21373,21605,20464,21605,19557,21605,20499,21605,20359,21605, + 9181,21605, 9671,21605, 4145,21605, 3801,21605, 4135,21605,10101,21605, +20577,21605,19656,21605,19441,21605,19332,21605,19392,21605,19454,21605, +21059,21605,19440,21605,19657,21605, 4134,21605,10100,21605,20498,21605, +20358,21605,20142,21605, 9,22007,20576,21605,20864,21605, 9,22013, +21116,21605,21166,21605,21183,22019, 9,22019,21560,21605, 9180,21605, + 9670,21605, 3800,21605, 4144,21605,21026,21605,20839,22035,20814,21605, +20839,22039,20992,21605,20839,22043,21359,21605,21845,22047,21647,22047, +21053,21605,21795,22053,20779,21605, 8087,21605, 8091,21605, 8089,21605, +20303,21605, 9,22065,20465,21605,10786,21605,11131,21605, 4696,21605, +11970,21605,19722,21605,19333,21605,19393,21605,19455,21605,20351,21605, +21739,22087,20485,21605,21741,22091, 9663,21605,21743,22095, 9177,21605, +21745,22099,20350,21605,21661,22103,20484,21605,21663,22107, 9662,21605, +21657,22111, 9176,21605,21659,22115,10099,21605, 17,22119, 17,22118, + 4133,21605, 17,22125, 17,22124, 8251,21605, 9,22131, 3807,21605, + 9,22135, 13,21604,18967,22139, 19,21604,20501,22143, 9875,22143, + 12,21604, 8251,22149, 3807,22149,19559,22149,20501,22149, 9875,22149, + 8165,22149, 18,21604, 3799,21605, 17,22165, 17,22164, 4143,21605, + 17,22171, 17,22170, 4283,21605, 9,22177, 4279,21605, 9,22181, + 9669,21605, 17,22185, 17,22184, 9179,21605, 17,22191, 17,22190, + 9673,21605, 9,22197, 9967,21605, 9,22201,19624,21605,20501,22205, + 17,22205,19686,21605,22149,22211,19441,22211,19656,22211,21607,22211, +19631,22211, 9,22220, 9,22211,19631,22224,19559,21605,19385,22228, + 9,22231, 9,22229,19545,21605, 17,22236, 17,22237,10102,21605, + 7971,22243,17053,22243, 629,21605,21117,21605,21561,21605,20867,21605, +20885,22255,21167,21605,21183,22259,21548,21605, 17,22263,20501,22263, +21104,21605,21069,22269,21267,22269,21305,22269,21259,22269,20103,22277, + 17,22269,20501,22269,20838,21605,20985,22285,20842,21605,21865,22289, +21809,22289,21613,22289,21637,22289,21867,22289,20773,22289,20956,22289, +21863,22289,20885,22305, 9,22305,20885,22289,20413,22310,20413,22289, +20885,22314,21126,21605,21871,22319,21831,22319,21617,22319,21635,22319, +21877,22319,21049,22319,21242,22319,21869,22319,21183,22335, 9,22335, +21183,22319,20103,22340,20103,22319,21183,22344,21020,21605,20885,22349, +21278,21605,21183,22353,21052,21605,21829,22357,21127,22357,21358,21605, +21747,22363,21665,22363,21532,21605,20497,21605, 17,22371, 17,22370, +20361,21605, 9,22377,20713,21605, 9,22381,20357,21605, 17,22385, + 17,22384,21048,21605,21643,22391,20772,21605,21645,22395,21509,21605, +21381,22399,21499,22399, 9,22399,21475,21605,21381,22407, 9,22407, +21365,21605,21381,22413, 9,22413,11971,21605, 4697,21605, 8387,21605, + 9,22423,11949,21605, 11,22426, 5,22428, 6,22426, 5,22432, + 5,22426, 6,22436, 6,22437, 7,22426,22441,22443, 7,22427, +22435,22447,22439,22447,22431,22447, 14,22426,22447,22455, 6,22427, + 15,22426,22459,22461, 9,22426, 9,22427, 4669,21605, 11,22468, + 5,22470, 6,22468, 5,22474, 5,22468, 6,22478, 6,22479, + 7,22468,22483,22485, 7,22469,22477,22489,22481,22489,22473,22489, + 14,22468,22489,22497, 6,22469, 15,22468,22501,22503, 9,22468, + 9,22469,12345,21605, 5,22510, 4,22510, 12,22510, 13,22511, +22517,22519, 12,22511, 13,22510,22523,22525, 4,22511,22513,22529, + 5,22511,22515,22533, 5123,21605, 5,22536, 4,22536, 12,22536, + 13,22537,22543,22545, 12,22537, 13,22536,22549,22551, 4,22537, +22539,22555, 5,22537,22541,22559,10697,21605, 9,22562,19385,21605, +19559,22566, 9,22569, 9,22567,19559,22573,19397,21605, 6,22576, + 11,22577, 11,22576,19475,21605,20413,22584, 1406,21605, 1396,21605, + 525,21605, 903,22593, 934,21605, 9,22597, 1290,21605, 903,22601, + 669,21605,21899,22605,21903,22605, 1861,22605, 1887,22605, 4,22605, +17013,22605, 4917,22605,19687,21605,22139,22621,21609,22621, 9,22621, +20103,22620, 9,22629,19625,21605,20501,22632,19384,21605,21087,22637, +20326,22637, 9,22636,20273,22637, 9,22644, 9,22637,20273,22648, +19396,21605, 5,22652, 10,22652,19441,22657, 10,22653,19455,22661, + 11,22652,22661,22665, 11,22653,22657,22669,19474,21605,20413,22673, + 1418,21605, 4,22677, 3755,22677, 1995,22677,17013,22677, 4917,22677, + 12,21605,22139,22689,18967,22688, 18,21605,22143,22695,21252,21605, +21279,21605,21183,22701,21291,22701, 9,22701,20483,21605,20763,22708, +20187,21605,21036,22712,21069,22715,21036,22713,21049,22719,21037,22713, +21037,22712, 9,22713,20353,21605, 5,22729,21315,22729, 33,21605, + 8150,22735,17727,22735, 9,22735, 7971,22740, 7971,22735, 9,22744, +17025,22735, 8165,21605, 30,22751, 181,22751, 9,22751, 25,22756, + 25,22751, 9,22760, 145,22751, 53,21605,17049,22767,10219,21605, + 903,22771, 155,22771,10081,21605, 1369,22776, 7971,22779,17053,22779, + 257,21605, 9,22785, 1171,21605, 4722,22789, 4713,22789, 903,22792, +21315,22789, 903,22789, 4713,22798, 628,21605, 9,22803, 11,21605, + 766,22807, 767,22807,20984,22807,20762,22806,22813,22815,20985,22807, +20762,22807,22140,22807,19718,22807,19725,22807, 586,22806,22809,22829, + 5,22807,20763,22832,22815,22835,20763,22833,22821,22839, 587,22832, +22829,22843, 587,22833, 586,22807,22847,22849, 5515,22807,17043,22807, + 4825,22807,17727,22807, 8150,22807,22139,22807,18967,22862,19396,22806, +19397,22806,19396,22807,22869,22871,19397,22807,22867,22875,22653,22875, +20763,22807, 5,22880,22815,22883,19687,22807, 9,22886, 7971,22807, + 9,22890,19461,22807, 9,22807,19687,22896, 7971,22896,18967,22896, +18967,22807,22139,22904, 9,22904,20103,22905, 9,22911, 1369,22806, + 903,22806, 9,22917, 587,22807, 5,22920,22829,22923,18967,22806, +20326,22927,21087,22927, 9,22926,20273,22927, 9,22934, 9,22927, +20273,22938, 9,22806,18967,22942,20763,22806,22819,22947, 587,22806, +22811,22951, 9,22951, 17,21605,19722,22956,19723,22957,22959,22961, +19723,22956,19722,22957,22965,22967,19396,22956,19396,22957,19397,22956, +22973,22975,19545,22956,20497,22956,20357,22956, 4133,22956,10099,22956, + 3799,22956, 4143,22956, 9179,22956, 9669,22956,19475,22957,21315,22957, +19397,22957,22971,23001, 1369,22956, 1275,22956, 903,23007, 587,22957, + 903,22957, 15,21605,20103,23014,18967,23015,20501,23019, 1369,23014, + 4917,23023,17013,23023, 3755,23023, 1995,23023,18967,23014,20413,23033, + 9,21605,19631,23036,19384,23036,19384,23037,22567,23043,19385,23036, +10697,23036, 4669,23036,11949,23036, 11,23037,23047,23055,22567,23055, +18967,23055,18967,23036, 10,23062, 10,23063, 11,23062,23067,23069, + 11,23063,23065,23073, 11,23036,18967,23076, 7049,21605, 587,23081, + 7051,23083, 7055,23083, 7059,23083,17219,21605, 903,23091, 4663,21605, + 903,23095, 4745,21605, 955,23099, 9,23099, 4569,21605,17423,21605, + 955,23107, 9,23107,14625,21605, 5997,21605, 7,23114, 5,23114, + 6,23119,23117,23121, 6,23118, 6,23114, 5,23126, 7,23115, +23129,23131,23125,23131, 14,23114,23131,23137, 6,23115, 15,23114, +23141,23143,20482,21605,20762,23146,20773,23149,20762,23147,20815,23153, +20839,23147,21399,23147,19683,23147,20763,23147,20843,23163,23149,23163, +20763,23146,20839,23169,23153,23169,20186,21605,21036,23174,21049,23177, +21036,23175,21069,23181, 331,23175, 59,23175, 1325,23175, 265,23175, +20644,21605,20352,21605, 9660,21605, 8386,21605, 59,23199, 331,23199, + 1325,23199, 265,23199,21243,21605,21829,23209,20957,21605,21807,23213, +21272,21605,21631,23217,20962,21605, 9,23221,21248,21605,21625,23225, +21549,21605,20501,23228,21105,21605,20501,23232,20843,21605,21758,23237, +21623,23237,21760,23237,21641,23237,20885,23237,21757,23246,20889,23247, +21757,23237,20885,23252, 9,23252,20103,23236, 9,23259, 9,23237, +21757,23262,20885,23236, 9,23267,21127,21605,21752,23271,21625,23271, +21754,23271,21639,23271,18967,23270,21087,23281,21183,23271,21751,23284, +21751,23271,21183,23288, 9,23288,20103,23270,21183,23295, 9,23295, + 9,23271,21751,23300,21405,21605,21633,23305,21394,23305,21786,23305, +21381,23305,20273,23312,21785,23312,20326,23305,21087,23305,21695,23305, +21037,23305,21036,23304,23325,23327,21036,23305,21037,23304,23331,23333, +21788,23305,21785,23305,21381,23338, 9,23338, 9,23305,20273,23344, +21785,23344,20273,23305,21381,23350, 9,23350,21259,21605,21843,23357, +20885,21605,20763,23360, 5,23363,18967,23362, 6,23360,18967,23368, +18967,23360, 6,23372, 6,23373, 7,23360,23377,23379, 7,23361, +23365,23383, 4,23383,23363,23387,23371,23383,23375,23383,23367,23383, +21526,23360,23383,23397, 6,23361,21527,23360,23401,23403, 9,23361, +20843,23407,21791,23361,20413,23411,20413,23360,21791,23415,20843,23360, + 9,23419,21183,21605,21315,23422,21795,23425,21795,23423,20103,23429, +20103,23422,21795,23433,20763,23422,21249,21605,21617,23439,21001,21605, + 9,23443,21273,21605,21619,23447,21371,21605, 9,23451,21253,21605, + 8,21604,22363,23457,22053,23457,21983,23457,23039,23457,21985,23457, +22077,23457,22075,23457,22465,23457,22507,23457,23053,23457,23051,23457, +20501,23457,23037,23457,19631,23483,11949,23483, 4669,23483,18967,23457, + 10,21604,22870,23493,22869,23493,22867,23493,23041,23493,22583,23493, +21995,23493,22665,23493,21991,23493,19441,23493,22626,23493,21997,23493, +19656,23493,22908,23493,22902,23493,22419,23493,22421,23493,11970,23493, + 4696,23493,21987,23493,23069,23493,21989,23493,23079,23493,22643,23493, +22933,23493,22945,23493,22693,23493,22904,23493, 9,23546,22896,23493, +18967,23550,22621,23493, 9,23554,19396,23493,22807,23558, 8647,23493, +22637,23493, 9,23565,23077,23493,18967,23569,22689,23493,18967,23573, +22927,23493, 9,23577,22943,23493,18967,23581,22807,23493,19396,23584, +19396,23585,18967,23584, 9,23590, 9,23584,18967,23594,18967,23585, + 9,23598, 9,23585,18967,23602,19631,23493, 9,23606,18967,23493, +22896,23610,22807,23610, 9,23614, 9,23610,22807,23618, 9,23493, +11949,23622, 4669,23622,22621,23622,19631,23622,22904,23622,22807,23622, +18967,23634,18967,23622,22807,23638, 4669,23493, 9,23642,11949,23493, + 9,23646, 16,21604,22979,23651,21935,23651,22239,23651,22389,23651, +22375,23651,22001,23651,21999,23651,22005,23651,22003,23651,22123,23651, +22129,23651,22983,23651,22981,23651,22987,23651,22985,23651,22989,23651, +22995,23651,22993,23651,22991,23651,22169,23651,22029,23651,22027,23651, +22175,23651,22031,23651,22189,23651,22195,23651,22033,23651, 7,23651, + 3,23706, 3,23651, 7,23710, 586,23651,22957,23651,19545,23717, +20357,23717,20497,23717,10099,23717, 4133,23717, 3799,23717, 9669,23717, + 9179,23717, 4143,23717,19559,23651,20713,23651,20361,23651, 9967,23651, + 9673,23651, 4283,23651, 3807,23651, 8251,23651, 4279,23651, 14,21604, +23175,23755,23199,23755, 5,23755, 1,23760,22677,23763,23023,23763, + 1,23755, 5,23768,22677,23771,23023,23771,16381,23755,14625,23755, + 4569,23755,13325,23755, 8685,23755,19513,23755, 1369,23755, 17,23755, +20219,23755, 4063,23755,10273,23755,20697,23755, 4137,23755, 8401,23755, + 9955,23755, 3863,23755,19631,21605, 11,23808, 5,23810, 6,23808, + 5,23814, 5,23808, 6,23818, 6,23819, 7,23808,23823,23825, + 7,23809,23817,23829,23821,23829,23813,23829, 14,23808,23829,23837, + 6,23809, 15,23808,23841,23843, 9,23808,23457,23847, 9,23809, +19667,21605, 5,23852, 4,23852, 12,23852, 13,23853,23859,23861, + 12,23853, 13,23852,23865,23867, 4,23853,23855,23871, 5,23853, +23857,23875, 8,21605,23646,23879,23642,23879,23606,23879,23851,23879, +22467,23879,22509,23879,19384,23879,19631,23879,23493,23894,23493,23879, +11949,23898, 4669,23898,19631,23898,11949,23879,23493,23906, 4669,23879, +23493,23910,18967,23879, 11,23914, 11,23915,23493,23919, 11,23879, +18967,23922, 14,21605,18967,23926,20501,23929, 17,23929,18967,23927, +20413,23935, 16,21605,22241,23939,22387,23939,22373,23939,22121,23939, +22127,23939,22167,23939,22173,23939,22187,23939,22193,23939,19545,23939, +10099,23939, 4133,23939, 3799,23939, 4143,23939, 9669,23939, 9179,23939, +20357,23939,20497,23939,19625,23939,21549,23939,21105,23939, 11,21604, +23053,23983,23051,23983,23039,23983,21985,23983,22085,23983, 5,23982, + 6,23995,21983,23983,22077,23983,22075,23983,22081,23983,22083,23983, +22572,23983,23847,23983,22465,23983,22507,23983,22211,23983, 9,24017, +19396,23983,22567,23983, 9,24022, 8165,23983, 9,24027,23037,23983, +11949,24031, 4669,24031,19631,24031,19559,23983, 9,24039, 8251,23983, + 9,24043, 3807,23983, 9,24047, 9875,23983, 9,24051,20501,23983, + 9,24055, 9,23982, 8251,24059, 3807,24059,22211,24059,19559,24059, +20501,24059, 9875,24059, 8165,24059, 9,23983,22567,24074,18967,24074, +18967,23983,21183,24081,23997,24081, 375,24081, 7,24081,23995,24089, + 9,24080, 9,21604,22869,24095,23894,24095,21997,24095,21365,24095, +21475,24095,21509,24095,21405,24094,22047,24095,22357,24095,23919,24095, +21995,24095,22583,24095,23906,24095,23910,24095,21127,24094,22319,24125, +20843,24094,22289,24129,22419,24095,22421,24095,21279,24095, 973,24094, + 4745,24139,19559,24095,20361,24095,20713,24095, 9673,24095, 9967,24095, + 4283,24095, 4279,24095, 8251,24095, 3807,24095, 33,24095, 7971,24161, + 8165,24095, 25,24165, 9875,24095,20501,24095, 4745,24095,17423,24095, +21405,24095,20273,24177,21785,24177,19631,24095,23879,24182, 4669,24095, +23879,24186,11949,24095,23879,24190, 973,24095, 4805,24195,19687,24095, +23493,24199,23879,24095,19631,24202,11949,24202, 4669,24202,20413,24095, + 11,24094, 8251,24213, 3807,24213,22211,24213,19559,24213,20501,24213, + 9875,24213, 8165,24213,21127,24095,21751,24229,20843,24095,21757,24233, + 11,24095,19687,24237,23610,24237,23493,24237,18967,24242, 7971,24237, +18967,24237,23493,24248,18967,24095, 10,24252,24213,24255, 10,24253, +24237,24259, 483,24253, 10,21605,23893,24265,24020,24265,22581,24265, +22669,24265,19455,24265,23917,24265,19333,24265,23073,24265,19393,24265, +23060,24265,24092,24265,23925,24265,24078,24265,23651,24265, 9755,24265, + 9317,24265, 4321,24265, 3833,24265,10171,24265, 4295,24265,22149,24265, +18967,24307,24213,24265,18967,24311,24059,24265,18967,24315,21183,24265, +19396,24265,23983,24320,19559,24321, 922,24265, 1413,24265,19683,24265, +24074,24265,18967,24332,23055,24265,18967,24336,24080,24265, 9,24340, +20839,24265,21399,24265,19385,24265,23879,24349, 9,24349,23983,24265, +19396,24355,19396,24354,18967,24355, 9,24360, 9,24355,18967,24364, +18967,24354, 9,24368, 9,24354,18967,24372,18967,24264,19441,24377, +24213,24377,24059,24377,22149,24377,19656,24377,19631,24377, 9,24388, +23983,24377, 9,24393, 9,24377,19631,24396, 903,24265, 483,24400, + 483,24265, 903,24404,18967,24265,23055,24408,24074,24408,19559,24409, + 9,24415, 9,24408,23983,24418,19559,24419,23983,24408, 9,24424, + 9,24265,24080,24428,18967,24428,19559,24433,23983,24432,23983,24428, +18967,24438,18967,24429,19631,24443, 17,21604,21963,24447,23958,24447, +23972,24447,23974,24447,23960,24447,23962,24447,21979,24447,21977,24447, +21967,24447,21965,24447,23964,24447,23966,24447,23968,24447,23970,24447, +21971,24447,21969,24447,21975,24447,21973,24447,22807,24447,19545,24447, +23939,24486,20357,24447,23939,24490,20497,24447,23939,24494, 9669,24447, +23939,24498, 9179,24447,23939,24502, 3799,24447,23939,24506, 4143,24447, +23939,24510,10099,24447,23939,24514, 4133,24447,23939,24518,23939,24447, +19545,24522,20357,24522,20497,24522,10099,24522, 4133,24522, 3799,24522, + 9669,24522, 9179,24522, 4143,24522, 15,24446, 15,21604,23357,24545, +22713,24545,22423,24545, 8337,24545,20103,24545, 17,24544, 483,24545, + 19,21605,22163,24561,18967,24560, 13,21605,24080,24567,22149,24567, +23983,24567,18967,24572,18967,24567,23983,24576, 113,21605,10385,24581, +23879,24583, 9,24583,11731,21605, 67,24589,23879,24591, 9,24591, + 137,21605,12261,21605, 587,24599,10107,24601,11067,24601,12285,24601, + 1346,21605, 1505,24609, 256,21605, 8495,24613,10107,24613, 1486,21605, + 803,24619, 1504,21605,20029,24623,21103,24623,19781,24623, 973,21605, + 2845,24631, 4812,24631, 955,24631, 4805,24636, 2971,24631, 4814,24631, + 9,24631, 4805,24644, 4805,24631, 955,24648, 9,24648, 341,21605, + 803,24655,17049,24655,20884,21605,21820,24661,21807,24661,20413,24664, +20413,24661,21807,24668,21182,21605,21195,24673,21836,24673,21829,24673, +20103,24678,20103,24673,21829,24682,20984,21605,20839,24687,20413,24689, +20413,24686,20839,24693,21258,21605,23755,24697,21749,24697,21574,21605, + 9,24703,21404,21605,24109,24707,21803,24707,21849,24707,21621,24707, +21693,24707,21805,24707,21801,24707,21381,24721, 9,24721, 1141,21605, +17025,24727, 1447,21605,17025,24731, 253,21605,17049,24735, 1471,21605, +17049,24739,21018,21605, 5,24742,20839,24745, 5,24743,20885,24749, +21276,21605, 7,24753,20413,21605, 6,24756, 4,24759,18967,24760, +18967,24759, 4,24764, 4,24765,21314,24759,21570,24756,21571,24757, +24773,24775, 6,24757,21314,24778,21314,24779,20885,24757,24661,24785, +21571,24756,21570,24757,24789,24791,21315,24757,24783,24795,21381,24757, +20885,24756,21791,24801,19475,24756,20984,24756,20839,24807,21315,24756, +21747,24811,24781,24811,23457,24811, 5,24756,20762,24819,20762,24818, +24763,24819,24767,24819,20839,24819,21399,24819,24771,24819,19683,24819, +20763,24819,20843,24837,24823,24837,20763,24818,24821,24843,20839,24843, + 5,24757,24769,24849,20885,24849,24661,24849,20763,24756, 5,24856, +20839,24859, 5,24857,20885,24863,20103,21605,21183,24867,21127,24869, +24673,24869, 15,24866,21183,24866,21795,24877, 15,24867,19687,24866, + 9,24883,19625,24866,20843,24866, 9,24889,21549,24866,21127,24866, +21183,24895, 9,24895,21105,24866,20763,24866, 5,24903,21527,24866, + 9,24867,19687,24909,20843,24909,21127,24909, 6,24866,21036,24917, + 5,24917,18967,24920,18967,24917, 5,24924,21036,24916, 5,24916, +18967,24930,24881,24917,18967,24916, 5,24936, 7,24866,23755,24941, + 1325,24941, 331,24941, 59,24941, 265,24941, 7,24867,23929,24953, +22205,24953,24919,24953,24923,24953,24927,24953,24929,24953,24933,24953, +24939,24953,24905,24953, 4,24953,24903,24973,22269,24953,22263,24953, + 375,24953,21037,24953,24917,24983, 6,24867, 5,24986,24941,24989, +24901,24987,24893,24987,24887,24987,21037,24866,24987,24999, 7,24999, +20273,21605,21258,25004,21259,25005,25007,25009,21183,25005,21259,25004, +21258,25005,25015,25017, 375,25005, 6,25004, 7,25004, 7,25005, +25023,25027,21315,25027, 6,25005,25025,25033,20501,21605, 7,25036, + 4,25039, 4,25038,20885,25037, 7,25037,18967,25047, 5,25049, + 5,25048, 5,25047,18967,25054, 5,25046,21036,25047,21037,25037, +22269,25063,21105,25063, 16,25036, 10,25037, 803,25037, 903,25037, + 9,25037, 17,25036,19625,25036,21105,25036,21549,25036,21037,25036, +21829,25087,25059,25087,21127,25087,24095,25087,25071,25087, 11,25037, + 4,25036, 7,25100,25051,25101, 5,25036,25041,25107,18967,25106, +25099,25111, 5,25037,25103,25115,25043,25115,25087,25115, 7,25114, +25087,25123,25069,25115, 4,25037,25111,25129,25057,25129,25053,25129, +25061,25129,25079,25129, 9165,21605, 9168,25140, 9169,25141,25143,25145, + 9169,25140, 9168,25141,25149,25151, 8337,21605, 15,25155, 6,25155, + 5,25158, 7,25155, 375,25163, 6,25154,25157,25167, 7,25154, +25161,25171,23755,25171, 59,25171, 331,25171, 1325,25171, 265,25171, + 9617,21605, 9630,25184, 9631,25185,25187,25189, 9629,25185, 9631,25184, + 9630,25185,25195,25197, 375,25185, 6,25185, 7,25185, 6,25184, +25205,25207, 7,25184,25203,25211, 9875,21605, 7,25214, 4,25216, + 4,25217, 9893,25215, 16,25214, 803,25215, 9,25215, 17,25214, + 903,25215, 4,25215,25231,25235, 5,25215,25219,25239,25225,25239, + 4,25214, 7,25244,25239,25247, 5,25214,25221,25251, 843,21605, + 9,25255, 413,21605, 7,25259, 375,25259, 1530,21605, 9,25265, + 1216,21605, 7,25269,21497,21605, 7,25273,21277,21605, 7,25276, +21183,25279, 7,25277,21105,25283,21019,21605, 5,25286,20885,25289, + 5,25287,20839,25293, 265,21605, 7,25297, 7971,25299, 587,21605, + 11,25302, 9,25305, 9,25303, 11,25309, 5,25303,20501,25313, + 9875,25313, 903,21605, 9,25319, 11,25321, 11,25318, 9,25325, + 7,25319, 1141,25329, 33,25329, 1447,25329, 1011,25318, 7,25337, + 1275,21605, 9,25341, 1369,25343, 17,25340, 903,25347, 5,25340, + 1505,25351, 5,25341, 253,25355, 53,25355, 1471,25355, 1369,25340, + 9,25363, 1011,21605, 7,25367, 959,25369, 47,25369, 759,25369, + 903,25366, 7,25377, 1369,21605, 9929,25380, 9927,25383,11759,25380, + 7971,25387,17053,25381,10081,25391, 7,25380, 4,25394, 5,25395, + 7,25398,25381,25401, 0,25398,25403,25405, 4,25395, 0,25395, + 5,25410, 1,25380, 5,25415, 1,25416,25381,25419, 6,25416, +25421,25423, 6,25415, 5,25426, 14,25415, 10,25380, 5,25433, + 0,25434, 0,25433, 5,25438, 16,25380,10081,25380, 7971,25445, +17053,25445, 7971,25381,11759,25451,10081,25451, 17,25380, 11,25380, + 11,25381, 1965,25461, 3195,25461,25437,25461,25441,25461, 5197,25461, +25405,25461,25413,25461, 1,25461, 4579,25461,15899,25461, 15,25380, +23763,25483,23771,25483, 3755,25483, 1995,25483, 0,25483,25461,25493, +25477,25483, 4917,25483,17013,25483, 4,25380, 7,25502,20029,25503, +19781,25503,21103,25503, 5,25380,25409,25513, 803,25513, 4,25381, +20033,25519,25457,25519, 5,25381,25397,25525,25505,25525,25443,25525, +10219,25525, 959,25525, 47,25525, 759,25525, 1275,25380, 9,25541, + 241,21605, 9,25545, 483,25545, 7,25544, 8495,25551,10107,25551, +17571,21605, 7,25557, 4,25558, 4,25559, 16,25557, 17,25557, + 4,25556,25567,25569, 5,25556,25561,25573,25565,25573, 4,25557, + 7,25578,25573,25581, 5,25557,25563,25585,17371,21605,16711,25589, + 7,25589,14315,21605, 5,25594, 6,25596, 6,25597, 14,25594, + 15,25594, 6,25594, 5,25606, 7,25594,25601,25611, 6,25595, +25605,25615, 7,25595,25609,25619,25599,25619,25603,25619,15705,21605, + 767,25627, 483,25629, 4,25627, 483,25633,21527,21605,20103,25636, + 5,25637, 17,25641, 5,25636, 9,25645,21315,21605,21183,25648, +21795,25651,21183,25649,24673,25655,21747,25649,20413,25659,23457,25649, +20413,25663,20413,25648,23457,25667,21747,25667,21037,21605,21829,25673, +20501,25675,21127,25673,20501,25679,21105,25673, 11,25673,20501,25685, + 15,25673,20501,25672,24095,25691,21829,25691,21127,25691,20187,25672, +24095,25673,20501,25701, 6,25673, 7,25673, 6,25672,25707,25709, +20103,25709, 7,25672,21749,25715,23755,25715,25705,25715,20103,25672, + 7,25723,20763,21605,20482,25726,20839,25729,20483,25726,21183,25726, + 4,25727,23147,25737,24819,25737, 5,25727,23383,25743,20956,25743, +20773,25743,24953,25743,20885,25743,20413,25752,20413,25743,20885,25756, + 4,25726,21605,25761, 7,25763,25743,25765,24849,25761,20413,25761, + 5,25726,20839,25773,20413,25775,20413,25772,20839,25779,20413,25726, + 5,25782,20839,25785, 5,25783,20885,25789, 5,21604,25275,25793, +25003,25793,25725,25793,24755,25793,21049,25793,21242,25793,20773,25793, +20956,25793,25699,25793,22725,25793,22391,25793,24682,25793,23209,25793, +25712,25793,25733,25793,22711,25793,22395,25793,24668,25793,23213,25793, +25770,25793,25083,25793,23235,25793,22017,25793,25085,25793,23231,25793, +22025,25793,25087,25793,25691,25793,22357,25793,22047,25793,23455,25793, +15567,25793,12971,25793,13355,25793,13541,25793,22869,25793,22635,25793, +23021,25793,23894,25793,23919,25793,21997,25793,21995,25793,22583,25793, +23906,25793,23910,25793,22419,25793,22421,25793,23034,25793,19656,25793, +19441,25793,11970,25793, 4696,25793,22674,25793,22069,25793,25081,25793, +22011,25793, 9357,25793,25205,25793,25027,25793, 9356,25793,25171,25793, +24941,25793,23199,25793,23175,25793,20606,25793,25593,25793,19396,25793, +11131,25793,21059,25793,23018,25793,20501,25933,20057,25793,22633,25793, +20501,25939,21405,25793, 357,25793, 367,25793, 471,25793, 1249,25793, + 628,25793, 4569,25793,14625,25793, 4545,25793,13325,25793, 8337,25961, + 4549,25793,23229,25793,20501,25967,23233,25793,20501,25971,25706,25793, +20186,25793, 8386,25793, 9083,25793, 9484,25793, 9984,25793,20187,25793, + 8387,25793,19513,25793, 8401,25793,20219,25793, 4137,25793,10273,25793, + 4063,25793, 3863,25793,20697,25793, 9955,25793,20353,25793,25709,25793, +20103,26010,25715,25793,24673,25793,20103,26016,24697,25793,21183,25793, +20103,26022,21259,25793, 4745,25793,17423,25793, 9082,25793,22673,25793, +20413,26034,23033,25793,20413,26038,25551,25793,24613,25793,22249,25793, +20326,25793,21087,25793, 9704,25793,23879,25793,19631,26054,11949,26054, + 4669,26054,11949,25793,23879,26062, 9,26062, 4669,25793,23879,26068, + 9,26068,20805,25793,23015,25793,18967,26076,20501,26079,18967,26077, +20413,26083,19631,25793,23879,26086, 9,26086, 9377,25793, 11,26092, + 341,25793, 241,26097, 8165,25793, 256,25793, 257,25793, 11,25793, + 9195,26106,20501,26106, 587,26106, 9377,26106, 9875,26106,20763,26106, +20804,25793,10219,25793, 587,26123, 53,25793,20501,25793, 10,26128, + 10,26129, 11,26128,26133,26135, 11,26129,26131,26139,20413,25793, +20885,26142,24661,26142,25761,26142,22673,26142,23033,26142,20762,25793, +25761,25793,20413,26156,24661,25793,20413,26160,20885,25793,20413,26164, + 17,25793,20762,26168,20762,26169,20763,26169,26171,26175,20763,26168, +26173,26179, 9,25793,11949,26182, 4669,26182,19631,26182,18967,26182, +20273,26182, 9617,26182,20763,25793, 11,26196,25707,25793, 9875,25793, + 10,26202, 10,26203, 11,26202,26207,26209, 11,26203,26205,26213, + 253,25793, 6,25793,25273,26219,24753,26219,24999,26219,24953,26219, +25005,26219,25723,26219,25707,26219,25185,26219,25163,26219,25589,26219, +24081,26219, 4713,26219,16363,26219, 9195,26219, 4863,26219,13119,26219, + 8757,26219, 4213,26219,23493,26219, 8109,26219, 3933,26219, 4147,26219, + 9335,26219,20103,26219, 8337,26219,20273,26219, 8997,26219,25673,26219, + 241,26219,18967,26219, 11,26279, 11,26219, 587,26219, 8387,26219, +14653,26219,20187,26219, 7,25793, 8717,26293, 3785,26293,25673,26292, +23755,26293,10351,26293, 4311,26293, 4329,26293,10055,26293,20103,26292, + 8337,26292, 8997,26292, 15,26293,18967,26317,18967,26292, 241,26292, + 9195,25793, 11,26324, 1471,25793, 6,25792,23175,26331,25977,26331, +24941,26331,26311,26331,26299,26331,25975,26331,25715,26331,24697,26331, +26315,26331,23199,26331,25171,26331,25979,26331,26033,26331,26313,26331, +16381,26331,26323,26331,26103,26331,13325,26331, 8685,26331,26155,26331, +26321,26331,26293,26331,20103,26375,25673,26375, 8997,26375, 8337,26375, + 241,26375,18967,26375, 17,26331, 1369,26331, 4569,26331,19513,26331, + 4063,26331,10273,26331, 3863,26331,20697,26331, 9955,26331, 4137,26331, +20219,26331, 8401,26331,14625,26331, 7,25792,25987,26415,26266,26415, +26201,26415,26274,26415,26272,26415,25989,26415,25981,26415,26268,26415, +21604,26415,18967,26433,26219,26435, 8997,26415,26219,26438,26105,26415, +26276,26415, 8647,26415,19396,26415,26197,26415,26278,26415,26219,26415, +20103,26454,25673,26454, 8997,26454, 8337,26454, 241,26454,18967,26454, + 8337,26415,26219,26468,20103,26415,26219,26472, 9,26415,18967,26476, + 241,26415, 1,26481,26219,26483,26219,26480,25673,26415,26219,26488, +18967,26415, 9,26492,26219,26492, 587,25793, 11,26498, 1369,25793, +25673,25793,20501,26505, 6,26504, 7,26504,26331,26511, 6,26505, +26511,26515, 7,26505,26509,26519,26219,26519,18967,25793, 9,26524, +23015,26524,20501,26529, 483,26525, 6,26524, 7,26524,26331,26537, + 7,26525,26219,26541, 6,26525, 241,25793, 1,26547, 7,26549, +26331,26551, 7,26548,26219,26555, 7,26547, 1,26558,26219,26561, +26219,26559, 7,26546,26331,26567,20273,25793, 9,26570,14315,25793, + 8997,25793, 7,26576,26331,26579, 7,26577,26219,26583, 9617,25793, + 9,26586, 8337,25793, 7,26590,26331,26593, 483,26591, 9,26591, + 7,26591,26219,26601,20103,25793,21183,26604,24673,26604,25709,26604, + 7,26604,26331,26613, 483,26605, 9,26605, 7,26605,26219,26621, + 4,21604,21955,26625,24877,26625,23433,26625,21947,26625,21951,26625, +24801,26625,23415,26625,21943,26625,22282,26625,22251,26625,22266,26625, +22253,26625,24811,26625,25667,26625,22363,26625,22053,26625,21116,26625, +21560,26625,25735,26625,23437,26625,22699,26625,21253,26625,23930,26625, +22206,26625,24805,26625,23937,26625,22587,26625,23039,26625,23053,26625, +23051,26625,21961,26625,21981,26625,20465,26625,20576,26625,21985,26625, +21983,26625,22077,26625,22075,26625, 9573,26625, 9575,26625,23847,26625, +22465,26625,22507,26625, 3,26625, 7,26712, 9605,26625, 586,26625, + 9599,26625,19474,26625,20413,26723,20186,26625,20805,26625,22423,26625, +22713,26625,22205,26625,20501,26734,19625,26625,20501,26738,19687,26625, +23929,26625,20501,26744,23934,26625,20413,26749,22585,26625,20413,26753, + 8386,26625,23927,26625,18967,26759,20501,26761,18967,26758,20413,26765, +23037,26625,19631,26769,11949,26769, 4669,26769, 1418,26625, 9565,26777, + 669,26625, 9565,26781,22263,26625,20501,26784,22269,26625,20501,26788, +21549,26625,20501,26792,20843,26625,21105,26625,20501,26798,21127,26625, +23423,26625,20103,26805,23357,26625, 7971,26625, 1170,26625,25203,26813, +20501,26625,22269,26816,22263,26816,21105,26816,21549,26816,22205,26816, +23929,26816,19625,26816,20762,26625,26219,26833,23361,26625,20413,26837, + 11,26625, 1,26841,18967,26841, 15,26625,18967,26846,20413,26849, +18967,26847,20501,26853, 1369,26846, 9565,26857, 7,26625, 4,26861, + 3,26860, 4,26860,21605,26867,20103,26860, 8337,26860,18967,26860, +26219,26875, 1011,26860,25203,26879, 6,26625,21604,26882,20763,26883, + 6,26624,24811,26889,22053,26889,22363,26889,25667,26889,20501,26889, +25649,26889,20413,26901,18967,26889, 7,26624,24265,26907,19559,26907, + 9673,26907, 8251,26907, 3807,26907, 4283,26907,20361,26907, 4279,26907, +20713,26907, 9967,26907, 483,26625, 1369,26625, 15,26930, 9565,26933, +25649,26625,20413,26937,18967,26625, 15,26940,20413,26943,23927,26940, +20413,26947, 6,26940,21604,26950, 7,26940,26219,26955, 7,26941, +26953,26959,26885,26959,26331,26959,23755,26959, 6,26941, 1011,26625, + 7,26971,25207,26973,23197,26973, 7,26970,25203,26979,20103,26625, + 7,26982, 8337,26625, 7,26986, 9565,26625, 9617,26625, 6,26992, + 7,26992, 6,26993,26997,26999, 7,26993,26995,27003,20273,26625, + 6,27006, 7,27006, 6,27007,27011,27013, 7,27007,27009,27017, + 7,21604,25987,27021,26266,27021,22732,27021,22733,27021,25087,27021, +25691,27021,22357,27021,22047,27021,26027,27021,25989,27021,26268,27021, +20819,27021,20152,27021, 8374,27021, 8389,27021,20201,27021,20952,27021, + 1,27021, 4,27056, 4,27057, 3,27021, 4,27062, 902,27021, +19559,27021,20361,27021, 9673,27021,20713,27021, 9967,27021, 4283,27021, + 4279,27021, 8251,27021, 3807,27021,26100,27021,26106,27021,26128,27021, +26202,27021, 8647,27021,20326,27021,25239,27021,25115,27021, 8800,27021, +21087,27021, 357,27021, 367,27021, 471,27021, 1249,27021, 8086,27021, +19687,27021, 9704,27021,25742,27021,20885,27021, 483,27122, 1141,27021, + 375,27021,20103,27128, 8337,27128,25673,27021,20501,27135,26219,27021, +20103,27138, 8337,27138, 11,27139, 17,27139, 1447,27021,21127,27021, +20843,27021, 8165,27021,25793,27154, 265,27155, 33,27021, 567,27021, +22729,27021,21315,27164, 11,27021,25793,27169, 8495,27169,25793,27168, + 8495,27168,18967,27169,21037,27169,21497,27021,21277,27021,21276,27021, +21496,27021,20273,27021, 9,27190,21315,27190,20103,27021,26219,27196, + 375,27196,21037,27196,21314,27021,22729,27205,20273,27205,21036,27021, +25129,27211,20103,27211,21183,27021, 9,27021,20273,27218, 9617,27218, +21315,27021,22729,27224,20273,27224,21037,27021,20103,27230,25743,27021, + 25,27021, 7971,27236, 7971,27021, 25,27240, 9617,27021, 9,27244, + 8337,27021,26219,27248, 375,27248, 4,27021,25037,27255,25215,27255, + 3,27254, 1,27254,25727,27255, 483,27255,20691,27255, 9923,27255, +18967,27255,20103,27273,18967,27254,22729,27277,20273,27277, 5,27021, +27061,27283, 1,27283,25727,27282,18967,27283,22729,27291,20273,27291, + 17,27283,18967,27297,18967,27282,25129,27301,20103,27301,25793,27021, + 8165,27306, 11,27306,20501,27306, 9875,27306, 9731,27021, 8495,27021, + 11,27318, 4,27020, 1,27323,27283,27324,27286,27323,27289,27323, +27121,27323,24265,27323,27225,27323,27290,27323,27211,27323,27301,27323, +27283,27323, 1,27344,25727,27345,18967,27344,18967,27345,19559,27323, +18967,27323,27283,27356, 4283,27323, 9673,27323, 8251,27323, 3807,27323, +20361,27323, 9967,27323,20713,27323, 4279,27323, 5,27020,27059,27377, +27263,27377,27235,27377,27264,27377, 8647,27377,19396,27377,27231,27377, +27272,27377,27205,27377,27277,27377,27255,27377, 1,27399,25727,27398, +18967,27398,18967,27399,26219,27377, 9,27377,18967,27410,25727,27377, +27255,27414,18967,27377, 9,27418,27255,27418, 1011,27021,25727,27021, + 5,27426,27323,27429, 5,27427,27255,27433,18967,27021, 7,27437, +21605,27439, 4,27441, 4,27440, 4,27439,21605,27446, 4,27438, + 16,27437, 113,27437,11731,27437, 17,27437, 4,27436,22729,27461, +21605,27460,27459,27465,27377,27461,20273,27461, 5,27436,25129,27473, +27443,27473,27323,27473,20103,27473, 5,27437,25101,27483,23193,27483, + 7,27483,21605,27489,27461,27491,27449,27483,27445,27483,27461,27483, +27255,27483,21315,27483, 4,27437, 7,27504,27473,27505,27283,27505, +21037,27505, 483,27021,20885,27514,20501,27021, 241,27519,25793,27518, + 9875,27021, 241,27525,25793,27524,20413,27021, 6,21604,24811,27533, +25667,27533,22363,27533,22053,27533, 1,27533, 5,27542,22605,27545, +22677,27545,23023,27545,25483,27545,20644,27533,21359,27533,25793,27557, +12345,27533, 5,27561, 4,27560,27563,27565, 4,27561, 5,27560, +27569,27571, 5123,27533, 5,27575, 4,27574,27577,27579, 4,27575, + 5,27574,27583,27585,19667,27533, 5,27589, 4,27588,27591,27593, + 4,27589, 5,27588,27597,27599, 341,27533,21052,27533,25793,27605, +25649,27533,20413,27609,25673,27533,21183,27613,26861,27533, 9,27617, +26293,27533, 9,27621,17219,27533, 903,27625, 4663,27533, 903,27629, +23195,27533,21315,27633,10219,27533, 903,27637, 53,27533,25025,27533, +21315,27643,20103,27533, 9,27647,21314,27533,24795,27651,26142,27651, +20413,27651,25793,27656,25793,27651,20413,27660,21036,27533,25129,27665, +21259,27533,26625,27669, 17,27533,21315,27673,21037,27533,25793,27677, +20501,27679,20501,27676,25793,27683, 8337,27533, 9,27687, 1471,27533, + 5,27533, 6,27693, 587,27695,21605,27697, 1,27692,22605,27701, +22677,27701,23023,27701,25483,27701,27699,27701, 6,27692,25380,27713, +27701,27715, 1369,27713,21605,27718,27701,27721,21605,27713, 1369,27724, +27701,27727, 9,27693,18967,27692,25129,27733, 9935,27693,20645,27693, + 4,27533,20501,27740,26524,27741,20501,27745,25793,27741,18967,27748, +20501,27751,18967,27749,20413,27755,18967,27741,25793,27758,20501,27761, +20501,27759,25793,27765,18967,27740,26142,27769,20413,27769,25793,27772, +25793,27769,20413,27776,26940,27533,26969,27781, 253,27533, 4,27532, +24811,27787,22053,27787,22363,27787,25667,27787,20501,27787,25649,27787, +20413,27799,18967,27787, 5,27532,24941,27805,23175,27805,25715,27805, +24697,27805,25171,27805,23199,27805,26959,27805,16381,27805,13325,27805, + 8685,27805,26293,27805, 17,27805, 1369,27805, 4569,27805,19513,27805, + 4063,27805,10273,27805, 4137,27805,20219,27805, 8401,27805, 3863,27805, +14625,27805,20697,27805, 9955,27805, 241,27533,18967,27533,20486,27857, +20487,27857,20413,27857, 4,27862, 4,27863, 580,27857, 483,27857, + 4,27870, 4,27871, 581,27857, 4,27856,27861,27879,26142,27879, +27877,27879,20413,27879,25793,27886,25793,27879,20413,27890, 5,27856, +25129,27895,27859,27895,27865,27895,27869,27895,27873,27895, 5,27857, +25101,27907,27555,27907,23193,27907,27743,27907,27886,27907,27867,27907, +27875,27907,20413,27907,27879,27922,27879,27907,20413,27926, 4,27857, +20413,27930,27895,27933, 483,27930,27895,27937,27895,27931,20413,27941, + 1369,27533, 5,27945,20501,27533,21037,27949, 4,27948,27907,27953, + 5,27948,18967,27956,21037,27948,25793,27961, 4,27949,27959,27965, +27665,27965,27733,27965,27895,27965, 5,27949,27961,27975, 7,21605, + 1,27979, 2,27981, 5,27983, 5,27982, 1010,27981, 5,27981, + 2,27990, 3,27978, 9,27995, 4311,27979,10351,27979, 4329,27979, + 3785,27979,10055,27979, 8717,27979,26283,27979,26388,27979,23790,27979, +27828,27979,22143,27979,22149,27979,24213,27979,24059,27979, 331,27979, + 8337,28027,20103,28027,21036,27978,21049,28033,21242,28033,21183,28033, +20103,28038,20103,28033,21183,28042,26331,27979,20103,28047, 8337,28047, + 17,28046,21277,27978,21183,28055,27693,27979,18967,28059,25793,27979, +21127,28063,20843,28063,19687,28063, 8337,28063,20103,28063, 7971,28063, + 241,28063, 8495,27979, 241,28079, 8337,27978,26331,28083,27805,28083, + 1325,28083, 331,28083, 59,28083,23755,28083,25793,28083, 265,28083, +21037,27979,27665,28101,28033,28101, 11,28101,21315,27979, 1325,27979, + 8337,28111,20103,28111, 59,27979, 8337,28117,20103,28117,10291,27979, + 483,28123,20273,27978,27533,28127,21315,28129,20103,27978,26331,28133, +27805,28133,23755,28133, 331,28133, 1325,28133, 59,28133,25793,28133, + 265,28133,21105,27979, 11,27979,20103,28153, 8337,28153, 17,27979, +26331,28158, 8337,28159,20103,28159,27805,28158,23755,28158,27731,27979, +27692,27979, 9,28173,23755,27979,20103,28177, 8337,28177, 17,28176, +23983,27979, 9,28185, 15,27979, 3,28189,20273,28189, 9617,28189, +27805,27979,20103,28197, 8337,28197, 17,28196, 241,27978,25793,28205, + 8495,28205,10107,28205, 265,27979,20103,28213, 8337,28213, 4,27978, +27985,28219,21105,28219,21549,28219,19625,28219,28173,28219,18967,28229, + 5,27978,19397,28233,28060,28233,18966,28232,18966,28233, 9,28241, +27323,28233,23651,28233,26907,28233, 9755,28233, 9317,28233, 4321,28233, + 3833,28233,10171,28233, 4295,28233,28101,28233,21183,28233, 1413,28233, + 922,28233,27856,28233,28059,28233,18967,28272,19396,28233,28239,28277, +19683,28233,18967,28232,28235,28283,28242,28283,28241,28283, 9,28288, + 9,28283,28241,28292,27533,28233,18967,28296, 9,28233,18967,28300, +28239,28303,18967,28301,28241,28307,21399,28233,20839,28233, 483,28233, + 903,28314, 903,28233, 483,28318,18967,28233,28059,28322,28239,28323, + 9,28327,27533,28322, 9,28322,28239,28333, 4,27979,27987,28337, +27993,28337,28270,28337,28330,28337,28298,28337,27989,28337, 586,28337, + 3,28337, 7,28352, 7,28337, 3,28356,27856,28337,28233,28360, +21575,28337,28296,28337,18967,28366,27533,28337,28322,28370,18967,28370, +28233,28374,28233,28370,18967,28378,28322,28337,27533,28382,18967,28337, +28296,28386,27533,28386,28233,28390,28233,28386,27533,28394,28233,28337, +27856,28398,27533,28398,18967,28402,18967,28398,27533,28406, 5,27979, +27255,28411, 9287,28411,20885,28411,27533,28410,28219,28419,18967,28421, + 9,28419, 241,28411, 483,28427,28219,28411,27856,28431,27533,28431, +18967,28434,18967,28431,27533,28438,18967,28410,28219,28443, 17,28443, +21036,27979,21069,28449,21267,28449,21305,28449,28219,28449,21259,28449, +20103,28459, 17,28449,21037,27978,26331,28465,21749,28465,27805,28465, +23755,28465,28449,28465,25793,28465,10001,27979, 9,28479,27533,27979, +21496,28483,21277,28483,20885,28483,27931,28483, 9,28483, 9731,28483, +21037,28482,21037,28483,21315,28483,20273,28500,21036,28482,28499,28505, +21036,28483,28497,28509,20273,28483,21315,28512, 4,28483, 5,28483, +28386,28519,28337,28519,18967,28522,18967,28519,28337,28526, 17,28519, + 4,28482,28519,28533, 5,28482,28517,28537,28219,28537,18967,28541, + 9,28537, 1275,27979,20031,28547,20885,28547, 5,28547,18967,27979, +20103,28555, 5,28555,28337,28559, 9,28559, 5,28554,28219,28565, + 17,28565,21527,27979,18967,27978,28519,28573, 7,28573, 4,28576, + 4,28577,28553,28573,21605,28573, 5,28584,28581,28587, 5,28585, +28579,28591, 16,28573,28591,28595, 11,28573,20273,28573, 567,28573, + 5,28572, 4,28573, 7,28606,28591,28609,28483,28607,28547,28607, + 483,28607, 5,28573,21605,28618,28581,28621,20762,21605,20803,28625, + 7,28625, 4,28628,25743,28631, 4,28629,24687,28635,25773,28635, +21035,28625, 16,28625,25743,28643,20999,28625,20985,28625, 483,28649, + 11,28625,20273,28625, 567,28625, 4,28624,20985,28659, 5,28624, +20956,28663,20773,28663,20885,28663,20413,28668,20413,28663,20885,28672, +20482,28625,20839,28677, 4,28625, 7,28680,25743,28683,20843,28681, + 483,28681, 5,28625,21605,28690,28635,28693,20839,28691,20413,28697, +20413,28690,20839,28701,20413,28625, 5,28705,20885,28707, 5,28704, +20839,28711, 5,21605,21183,28715,18967,28716,24673,28719,21194,28715, +24673,28723,28573,28714,28581,28727,20620,28714,20621,28714, 9994,28714, + 9995,28714, 1,28715, 1,28714,26781,28741, 668,28741,26625,28745, +26777,28741, 1419,28741,26625,28751,26857,28741,26933,28741, 2,28741, + 9,28741, 587,28760,26625,28763, 587,28741, 9,28766,26625,28769, +21018,28714,20839,28773,19396,28715,22579,28777,21611,28777,19683,28715, +20413,28783,23490,28715,20413,28787,21526,28714,26816,28791,24953,28791, + 17,28791,20501,28791,26625,28798,26625,28791,20501,28802,20762,28714, +20773,28807,20956,28807,20885,28807,20413,28812,20413,28807,20885,28816, +27787,28715,18967,28821,20501,28823,18967,28820,20413,28827,27802,28715, +20413,28831,21019,28714,20885,28835,27856,28715,20413,28839,27931,28715, +20413,28843,26904,28715,20413,28847,26861,28715,18967,28851,20823,28715, +20645,28715, 9935,28715,21362,28715,21376,28715,27533,28715,18967,28865, +20501,28867,18967,28864,20413,28871, 9994,28715,28737,28875,20822,28715, +28807,28879,20763,28715,28835,28883,28816,28883,20866,28883,21021,28883, +20413,28883,28807,28892,20843,28892,28807,28883,20413,28898, 9,28899, +20843,28883,20413,28904, 9,28882,28807,28909, 803,28715, 11,28913, +27979,28715,18967,28917,20621,28715,28731,28921,20413,28714,21399,28925, +20839,28925,25737,28925,19683,28925,20763,28925,20843,28935,28807,28935, +20763,28924,20839,28941,25737,28715,20413,28945,20839,28715,20413,28949, +20620,28715,28733,28953,21399,28715,20413,28957, 483,28715,21315,28960, +26860,28715,28337,28715, 11,28967,23457,28715,18967,28970,20413,28973, +18967,28971,20501,28977, 9,28715,21315,28980,20763,28981,20763,28980, +28807,28987, 17,28715,11949,28991, 4669,28991,19631,28991,18967,28991, +20273,28991, 9617,28991, 9995,28715,28735,29005, 1275,28714, 1505,29009, +26889,28715,18967,29012,20413,29015,18967,29013,20501,29019, 1369,28714, + 803,29023, 587,28715, 1505,28715, 6,28714,26940,29031,20413,29033, +28965,29031,18967,29037,18967,29030,26816,29041,24953,29041, 17,29041, +20501,29041,26625,29048,26625,29041,20501,29052,26625,29031,18967,29056, +20413,29059,18967,29057,20501,29063,18967,29031,20413,29067,26625,29069, +26625,29066,20413,29073, 7,28714,19397,29077, 0,29077, 2,29080, +28991,29083, 2,29077, 0,29087, 0,29086,28991,29091,28999,29077, + 1,29076,29091,29097,29083,29097,29081,29097, 2,29103, 1,29077, +29089,29107, 2,29107,28852,29077, 0,29076, 2,29115,29107,29116, +29110,29115,29107,29115, 2,29122,18966,29076,18966,29077,29097,29129, +28991,29129, 9,29129,27323,29077,23651,29077,26907,29077, 9755,29077, + 9317,29077, 4321,29077, 3833,29077,10171,29077, 4295,29077,21183,29077, + 1413,29077, 922,29077,26940,29077,28851,29077,18967,29162,19396,29077, +29127,29167,19683,29077,18967,29076,29079,29173,29134,29173,29129,29173, + 9,29178, 9,29173,29129,29182,26625,29077,18967,29186,21399,29077, + 9,29077,18967,29192,29127,29195,18967,29193,29129,29199,20839,29077, + 483,29077, 903,29204, 903,29077, 483,29208,18967,29077,29115,29213, +28851,29212,29127,29213, 9,29219,26625,29212, 9,29212,29127,29225, + 6,28715,29083,29229,29097,29230,29091,29229,29097,29234,29098,29229, +29100,29229,29105,29229,29109,29229,29119,29229,29121,29229,29125,29229, +29111,29229,29115,29253,24907,29229,25639,29229,22369,29229,28600,29229, +28557,29229,28654,29229,22057,29229,29178,29229,29160,29229,19706,29229, +10737,29229,10475,29229,10979,29229,19597,29229,12137,29229,29219,29229, +29215,29229,29130,29229,29222,29229,29129,29229,29173,29294,29097,29294, +29188,29229,29097,29229,29091,29302,29083,29302,29129,29302, 1,29229, + 5,29310, 5,29229, 1,29314,29173,29229,29129,29318,19687,29229, +19631,29322,26940,29229,29077,29326,10697,29229, 8165,29331,19631,29229, +19687,29334,21575,29229,20273,29229,28573,29340,28625,29340,29186,29229, +18967,29346,19384,29229,19559,29351,28625,29229,20273,29354,28573,29229, +20273,29358, 11,29229,18967,29362,19559,29365,18967,29363,19631,29369, + 587,29229,21605,29373,29313,29375,29317,29375,26625,29229,29212,29380, +18967,29380,29077,29384,29077,29380,18967,29388,29212,29229,29127,29393, +29115,29393,26625,29392,18967,29229,29186,29400,29077,29401,29173,29405, +29097,29405,26625,29400,29077,29410, 11,29401,19687,29415, 11,29400, +19559,29419,29077,29400,29127,29423,26625,29422,29115,29423,29077,29229, +26940,29430,26625,29430,18967,29434,18967,29430,29127,29439,26625,29438, +29115,29439,18967,29431,29129,29447, 7,28715,28791,29451,29041,29451, +19625,29451,21549,29451,21105,29451,26625,29450,29031,29463,18967,29465, + 1275,29451, 903,29469,29031,29451,26940,29473,26625,29473,18967,29476, +18967,29473,26625,29480,20763,28714,28635,29485,28855,29485,20839,29485, +20413,29491,20413,29484,20839,29495, 9,29485,20762,28715,28941,29501, +29495,29501,28773,29501,20815,29501,20993,29501,21027,29501,28985,29501, +29498,29501,29485,29501,20413,29519, 9,29518,20985,29501,20413,29525, + 9,29501,29485,29528,21527,28714,29229,29533, 9,29533,26940,28715, +20413,29539, 9731,28715, 7,29543,26625,28715,20762,29547, 6,29547, + 7,29547,29400,29553,29229,29553,18967,29556,18967,29552,18967,29553, +29229,29562, 6,29546,29553,29567, 7,29546,29551,29571,29031,29571, +18967,29575,18967,29546,20413,29579,18967,29547,20501,29583, 6,29582, + 7,29582, 6,29583,29589,29591, 7,29583,29587,29595, 903,28715, + 7,29599,18967,28715,21183,29602,24673,29605,21183,29603,21795,29609, +23457,29602,20413,29613,27787,29602,20413,29617,27533,29602,20413,29621, +20413,29603,27787,29625,26889,29625,26625,29625,27533,29625,23457,29625, +26889,29602,20413,29637,26625,29602,20413,29641,21315,28715,21183,29645, +24673,29645,25709,29645, 7,29645, 483,29644, 9,29644,18967,28714, +27965,29659,27948,29659,26816,29659,26898,29659,27796,29659,24953,29659, +20119,29659,25129,29659,29653,29659,26887,29659,23480,29659,25099,29659, +21605,29659, 6,29684,29645,29687,29451,29659,28625,29691,28573,29691, +20187,29659,28625,29659,19683,29659,20839,29659,21399,29659,28573,29659, +27787,29659,20501,29708,20501,29659,27787,29712,26889,29712,26625,29712, +27533,29712,23457,29712,27533,29659,20501,29724, 17,29659, 6,29658, +26816,29731,24953,29731,29451,29731, 17,29731,20501,29731,26625,29740, +26625,29731,20501,29744, 7,29658,29697,29749,20103,29749,20186,29659, +29731,29755, 6,29659,29752,29759,24941,29759,23175,29759,29645,29759, +28133,29759,21605,29758,29645,29771,20103,29759,29749,29774,29077,29759, +29749,29759,20103,29780, 11,29759,20763,29759,26625,29787, 7,29659, +29731,29791,20103,29793,20103,29790,29731,29797,23457,29659,20501,29800, +26889,29659,20501,29804,20103,29659, 7,29809,29759,29811, 7,29808, +29731,29815,26625,29659,20501,29818, 6,29819, 7,29819, 6,29818, +29825,29827, 7,29818,29823,29831,21036,21605,27965,29835,27951,29835, +27948,29835,26816,29835,27796,29835,26898,29835,27216,29835,28151,29835, +28101,29835,26887,29835,21194,29835,24673,29857,24675,29835,21069,29835, +21267,29835,21305,29835,24953,29835,20119,29835,22723,29835,25129,29835, +25063,29835,23480,29835,21796,29835,21795,29835,20501,29882,25099,29835, +18967,29835,21183,29889,21795,29891,21183,29888,24673,29895,21259,29835, +20103,29899,21183,29835,27021,29902,18967,29902,24673,29907,20187,29835, +21127,29911,28573,29835,28625,29835,19683,29835,20839,29835,21399,29835, +27787,29835,20501,29924,27533,29835,20501,29928,27021,29835,21183,29932, +20501,29835,27787,29936,26889,29936,26625,29936,27533,29936,23457,29936, +21795,29936, 17,29835, 6,29834,26816,29953,21069,29953,21267,29953, +24953,29953,21305,29953,25063,29953,21259,29953,20103,29967, 17,29953, +20501,29953,26625,29972,26625,29953,20501,29976, 7,29834,21242,29981, +29911,29981,21049,29981,21183,29981,20103,29988,20103,29981,21183,29992, +20186,29835,29953,29997,21105,29997, 6,29835,28133,30003,21279,30003, +21166,30003,29992,30003,23175,30003,24941,30003,20103,30003,21127,30016, +29981,30016,21127,30003,20103,30022,29981,30003,20103,30026, 11,30003, +20763,30003,26625,30033, 7,29835,21105,30037,20103,30039,29953,30037, +20103,30043,20103,30036,29953,30047,21105,30047,23457,29835,20501,30052, +26889,29835,20501,30056,26625,29835,20501,30060, 6,30061, 7,30061, + 6,30060,30067,30069, 7,30060,30065,30073,20103,29835, 7,30077, +30003,30079,21183,30079, 7,30076,29953,30085,21105,30085, 4,21605, +26371,30091,26450,30091,26539,30091,26542,30091,27439,30090,27483,30101, +17048,30091,26496,30091,26452,30091,26373,30091,26466,30091,26386,30091, + 586,30091, 803,30117, 586,30090, 767,30121, 1,30091, 15,30124, + 2,30124, 7,30124,26219,30131, 7,30125,23755,30135,26331,30135, +27805,30135,25793,30135, 1,30090,26454,30145,26375,30145,26415,30145, +26219,30150,26219,30145,26415,30154,26292,30145,26331,30159,25793,30145, + 7,30162,26331,30165, 7,30163,26219,30169, 7,30145,25793,30173, +26415,30175,25793,30172,26331,30179, 3,30090, 767,30183,26454,30091, +18967,30186,26375,30091,18967,30190,28159,30091, 8684,30091, 8647,30091, +26154,30091,26331,30201,26534,30091,26541,30205,26536,30091,26331,30209, +26320,30091,26331,30213,19384,30091,20501,30217,19474,30091,20611,30091, + 9989,30091,20762,30090,20985,30227,27436,30091,20501,30231,27507,30231, +27451,30231,27453,30231,26492,30091,26219,30240,26278,30091,26415,30244, +26219,30091,26541,30248,26492,30248,26415,30248,18967,30254,18967,30248, +26415,30258,27021,30091,18967,30263,20413,30265,18967,30262,20501,30269, +21527,30091, 9,30273,21258,30091,21575,30091,20501,30279,20985,30091, +20501,30090,27907,30285,27483,30285, 340,30091, 9,30091, 483,30091, +26292,30091,26331,30297,18967,30299,18967,30296,26331,30303,20413,30091, +20763,30307,25793,30309,26197,30091,26415,30312, 375,30091,24095,30091, +18967,30319,20413,30321,18967,30318,20501,30325,24252,30091,20501,30329, + 15,30091, 1,30332,18967,30332, 11,30091,18967,30339,20413,30341, +18967,30338,20501,30345, 1369,30339, 9565,30349,28741,30349,30129,30349, +27979,30339,19631,30357,11949,30357, 4669,30357,26415,30091, 1,30365, +26219,30367,26197,30364,26278,30364,26219,30364,18967,30374,18967,30364, +26219,30378,18967,30365,26219,30383, 1369,30090,20029,30387,19781,30387, +21103,30387,26541,30091,26219,30394, 6,30090,23646,30399,23642,30399, +23606,30399,24349,30399,26086,30399,26062,30399,26068,30399,24583,30399, +24591,30399,19384,30399,24265,30419,25793,30399,19631,30422,11949,30422, + 4669,30422,11949,30399,23493,30430,25793,30430, 4669,30399,23493,30436, +25793,30436,19631,30399,23493,30442,25793,30442, 11,30399,18967,30448, +24265,30451,18967,30399, 11,30454,24265,30457, 11,30455,23493,30461, +25793,30461,23493,30399,11949,30466, 4669,30466,19631,30466, 7,30090, +21549,30475,21105,30475,19625,30475, 6,30091,26524,30483,26545,30485, +26524,30482,26541,30489, 7,30091,26525,30492,30455,30493,25793,30497, + 2,30493, 0,30500,30422,30503,25793,30503,30399,30506,30399,30503, +25793,30510, 0,30493, 2,30514,30422,30517,25793,30517,30399,30520, +30399,30517,25793,30524, 1,30492,26219,30529,18966,30493,30422,30533, +25793,30533,30399,30536,30399,30533,25793,30540, 8495,30492,21183,30493, + 8495,30493,26524,30492,26331,30551,21037,30492,25793,30492,26331,30557, +18967,30559,18967,30556,26331,30563, 265,30492, 265,30493,25793,30493, +26541,30571,30495,30571,26492,30571,26415,30571,18967,30578,18967,30571, +26415,30582,18967,30492,26219,30587,25793,30586,26331,30591,25793,30587, +26415,30595,20763,30090,26142,30599,24849,30599,25793,30599,20413,30604, +20413,30599,25793,30608,20762,30091,26219,30613,20885,30613,25793,30612, +26331,30619,25793,30613,26415,30623,26524,30091,20501,30627, 6,30626, +26541,30631, 7,30626,26331,30635, 6,30627,26537,30639,30635,30639, + 7,30627,30631,30645,26219,30645, 8495,30091, 7,30650,25793,30091, + 1,30655, 7,30656,26219,30659, 7,30657,26331,30663,20762,30654, +26331,30667,20762,30655,26197,30671,26219,30671, 6,30655, 7,30655, +26197,30679,26278,30679, 1,30678,26219,30685,26219,30679,18967,30688, +18967,30678,26219,30693,18967,30679,26219,30696, 6,30654,30679,30701, + 7,30654,26331,30705,18967,30707,30677,30705,18967,30704,26331,30713, +18967,30654,20501,30717, 6,30716, 7,30716,26331,30723, 6,30717, +30723,30727, 7,30717,30721,30731,26219,30731,18967,30655,20413,30737, + 7,30736,26219,30741, 7,30737,26331,30745, 265,30091, 0,30748, + 6,30751,21605,30752,21605,30751, 6,30756, 6,30757, 7,30748, +30755,30763,30759,30763, 7,30749,30761,30769,18967,30091,26454,30772, +26375,30772,26292,30772,26331,30779, 11,30772,20501,30783, 15,30772, +27021,30772,20501,30789,20501,30773,25793,30793,27021,30793,24095,30793, +26415,30772,26219,30800,20187,30773,25793,30805,26219,30772,26415,30808, +24095,30772,20501,30813, 6,30773,26604,30817,29645,30817,25793,30817, +20103,30822,20103,30817,25793,30826, 7,30773,26331,30831,27805,30831, +23755,30831,25793,30831, 6,30772,30831,30841, 7,30772,26219,30845, +25793,30844,26331,30849,30817,30845,25793,30845,26415,30855,25793,30772, +20501,30859, 6,30858, 7,30858,26331,30865, 6,30859,30865,30869, + 7,30859,30863,30873,26219,30873,20103,30773,26219,30879, 7,30879, +25793,30883,21037,30091, 6,30887, 7,30887, 6,30886,30891,30893, + 7,30886,30889,30897,18967,30090,27530,30901,26142,30901,26009,30901, +26270,30901,28571,30901,26454,30901,26375,30901,24210,30901,27459,30901, +26219,30901,20273,30920,26415,30920,20413,30901,25793,30926,27021,30926, +24095,30926,27021,30901,20413,30934,20985,30901,24095,30901,20413,30940, +20352,30901,25793,30945,26292,30901,26331,30949, 7,30901,25793,30953, +20273,30955,26415,30955,20273,30952,25793,30961,25793,30952,26331,30965, +26415,30901,26219,30968,20273,30901,26219,30972, 7,30972,25793,30977, +25793,30901,20413,30980, 7,30981,26219,30985, 7,30980,26331,30989, +21314,21605,27530,30993,26142,30993,26270,30993,26009,30993,26454,30993, +26375,30993,28571,30993,24795,30993,24799,30993,24210,30993,21850,30993, +21845,30993,20413,31016,27459,30993,18967,30993, 6,31023,29645,31025, +26219,30993,20273,31028,26415,31028,27021,30993,20413,31034,20413,30993, +25793,31038,27021,31038,24095,31038,21845,31038,20985,30993,24095,30993, +20413,31050,26292,30993,26331,31055,20352,30993,25793,31059, 7,30993, +25793,31063,20273,31065,26415,31065,25793,31062,26331,31071,20273,31062, +25793,31075,26415,30993,26219,31078,25793,30993,20413,31082, 7,31083, +26219,31087, 7,31082,26331,31091,20273,30993,26219,31094, 7,31094, +25793,31099, 6,21605,27347,31103,27401,31103,27378,31103,27327,31103, +27380,31103,27329,31103,27263,31103,27377,31116,27285,31103,27059,31103, +27377,31122,27194,31103,27203,31103,27215,31103,27208,31103,27228,31103, +27233,31103,27188,31103,27187,31103,27184,31103,27183,31103,27294,31103, +27275,31103,27305,31103,27280,31103,27481,31103,27470,31103,27341,31103, +27394,31103,27122,31103,27390,31103,27337,31103,26796,31103,26802,31103, +30939,31103,30229,31103,30616,31103,31049,31103,28681,31103,20843,31180, +28686,31103,22287,31103,28661,31103,28649,31103,27502,31103,27513,31103, +25030,31103,24983,31103,30283,31103,25683,31103,21058,31103,29835,31205, +21195,31103,29835,31209,25629,31103,13894,31103,13919,31103,27498,31103, +27509,31103,27930,31103,27895,31223,27857,31103, 4,31226,27895,31229, + 4,31227,27907,31233,27479,31103,27468,31103,27500,31103,27511,31103, +26941,31103, 9457,31103,30118,31103,30185,31103,30123,31103,30105,31103, +26742,31103, 9444,31103, 9435,31103, 713,31260,30751,31102,30763,31265, +30221,31103,19397,31102,28777,31271, 3119,31103, 3027,31103, 3805,31103, + 4820,31103, 6469,31103, 3419,31103,27422,31103,27359,31103,27392,31103, +27339,31103,27343,31103,27396,31103,27404,31103,27351,31103,27352,31103, +27407,31103, 9539,31103,24554,31103,29659,31102,29645,31311,17294,31103, +26843,31103,30335,31103,26845,31103,25689,31103,30337,31103,30787,31103, +24552,31103,25157,31103,24881,31103,28387,31103,28386,31102,31335,31337, +28387,31102,28386,31103,31341,31343,27287,31103,27323,31347,30127,31103, +30117,31103, 803,31352, 3,31103, 0,31356,27277,31103,20273,31360, +27377,31360,27461,31103,20273,31366,27483,31366,27377,31366,27205,31103, +20273,31374,27377,31374,27218,31103,27316,31103,27398,31103,18967,31384, +27345,31103,18967,31388, 413,31103,30292,31103,26986,31103,26982,31103, + 9287,31103,27224,31103,20273,31402,27323,31403,21276,31103,29835,31409, +21496,31103,27021,31412,27021,31413,21277,31103,27021,31418,27021,31419, +21183,31419, 6441,31103, 759,31427, 4403,31103,17075,31103,16329,31103, + 4919,31103,17099,31103, 9362,31103, 5309,31103, 4547,31103,27291,31103, +20273,31446,27323,31447,26810,31103,26990,31103, 777,31103, 824,31103, + 244,31103, 4933,31103, 5297,31103,17077,31103,13019,31103,12705,31103, +13673,31103,18391,31103,18617,31103,14597,31103,27210,31103,27323,31481, +27472,31103,27323,31485,27300,31103,27323,31489,26317,31103,26476,31103, + 9134,31103, 1216,31103,19687,31103,26625,31500,19397,31103,29659,31505, +29835,31505,22655,31505,23622,31103,27410,31103,22139,31103,22163,31103, +24543,31103,24557,31103, 305,31103,21036,31102,26816,31527,25063,31527, +31245,31527,21069,31527,21267,31527,21305,31527,24953,31527,21259,31527, +20103,31543, 17,31527,20501,31527,26625,31548,26625,31527,20501,31552, +26415,31103, 9,31556,26940,31103,29645,31103,29659,31563,27418,31103, +27255,31566,27272,31103,27377,31570,27255,31103,27483,31574,27418,31574, +27377,31574,18967,31580,18967,31574,27377,31584, 8446,31103, 155,31103, +17049,31103, 1369,31593, 8861,31103,26625,31103,21127,31598,20843,31598, +19687,31598, 8337,31598,20103,31598, 7971,31598, 9565,31598,18967,31598, + 9731,31103,27021,31616,30613,31103,20885,31620, 9617,31102,26973,31625, + 8337,31103,24545,31628,26625,31628, 9,31628, 4819,31103, 713,31636, +13857,31103, 713,31640, 4543,31103,21372,31103,21315,31103,27190,31648, +27483,31648,25027,31648,27021,31649,20273,31657,27377,31657,27021,31648, +20273,31662,27323,31663,20273,31648,27021,31668,27021,31669, 11,31648, +21037,31103,29835,31677,20103,31679,20763,31676,29835,31683,20103,31676, +29835,31687, 713,31103,13857,31690, 9435,31690, 4819,31690, 803,31690, + 25,31103, 7971,31103,26625,31702,20884,31103,29659,31707,29835,31707, +20984,31103,28659,31713,28625,31713,30227,31713,22285,31713,17233,31103, + 903,31722,30091,31103, 9,31726,20162,31103,20171,31103,25027,31103, +21315,31734,27190,31103,21315,31738,21127,31103,26625,31742,20843,31103, +26625,31746,28681,31746, 9565,31103,26625,31752, 8997,31103, 9,31756, + 766,31103, 9455,31761,30121,31761, 3803,31761, 759,31761, 9,31103, +27021,31770,30091,31770, 9195,31770, 241,31770,26415,31770, 8997,31770, +27377,31770,23493,31770, 8337,31770,20103,31770, 1011,31103, 903,31792, + 241,31103, 9,31796,27297,31103,27282,31103,27323,31803,18967,31805, +18967,31802,27323,31809, 17,31803,20103,31103,24545,31814,26625,31814, +21037,31814,29835,31821, 9,31814,21037,31815,25793,31827,20273,31103, +27224,31830,27291,31830,27205,31830,27277,31830,27461,31830,21315,31830, +27021,31842,27021,31843,27021,31830,21315,31848,27231,31103,27377,31852, + 803,31103,30117,31856, 713,31856,20885,31103,27021,31862,30613,31862, +23493,31103, 9,31868,24545,31103,20103,31872, 8337,31872, 17,31873, + 11,31103,28715,31881,19631,31883,11949,31883, 4669,31883,21315,31880, + 8451,31103,27377,31103,27059,31894,27263,31894,27205,31894,27231,31894, +27461,31894,27272,31894,27277,31894,27255,31894,18967,31910, 9,31894, +18967,31894,27255,31916, 903,31103,17233,31920, 1011,31920, 257,31103, +27483,31103,21315,31928,27461,31928,27255,31928, 4,31102,23646,31937, +23642,31937,23606,31937,24349,31937,26086,31937,26062,31937,26068,31937, +24583,31937,24591,31937,19384,31937,24265,31957,25793,31937,19631,31960, +11949,31960, 4669,31960,11949,31937,23493,31968,25793,31968, 4669,31937, +23493,31974,25793,31974,19631,31937,23493,31980,25793,31980, 11,31937, +18967,31986,24265,31989,18967,31937, 11,31992,24265,31995, 11,31993, +23493,31999,25793,31999,23493,31937,11949,32004, 4669,32004,19631,32004, + 5,31102,26940,32013,20413,32015,18967,32012,26816,32019,24953,32019, +31245,32019, 17,32019,20501,32019,26625,32028,26625,32019,20501,32032, +26625,32013,18967,32036,20413,32039,18967,32037,20501,32043,18967,32013, +20413,32047,26625,32049,26625,32046,20413,32053, 4,31103,27857,32057, +27879,32059,27857,32056,27895,32063,20763,32056,29835,32067,29659,32067, +28715,32057,29083,32073,29091,32073,19631,32073,11949,32073, 4669,32073, +29129,32073,18967,32073,29077,32087,18967,32056,23147,32091,24819,32091, +28925,32091,28715,32091,20413,32099, 5,31103,27437,32102,19397,32103, +21605,32103,20762,32108,20762,32109, 586,32108, 586,32109,31993,32103, +25793,32119, 2,32103,21605,32123, 0,32122,31960,32127,25793,32127, +31937,32130,31937,32127,25793,32134,32073,32127, 0,32103,21605,32141, + 2,32140,31960,32145,25793,32145,31937,32148,31937,32145,25793,32152, +32073,32145, 586,32140, 586,32141,21605,32102,18966,32102,18966,32103, +21605,32167, 7,32169, 9,32167,31960,32167,25793,32167,31937,32176, +31937,32167,25793,32180,32073,32167, 1,32103,32125,32187,31937,32189, + 3,32103,32143,32193,31937,32195,28573,32103,28625,32103,20843,32201, + 9195,32103,20501,32103,21183,32103,27436,32102,27323,32211, 9377,32103, + 713,32215, 9875,32103,19396,32103,32165,32221, 9,32103,18967,32224, +32165,32227,18967,32225,32167,32231,20763,32102,22285,32235,28659,32235, +28625,32235,32111,32235,30227,32235,30772,32103,20501,32247,27021,32102, +27323,32251,18967,32253,18967,32250,27323,32257, 17,32251, 1369,32103, + 903,32103, 9,32265, 587,32102, 9455,32269,32159,32269,32115,32269, + 3803,32269,30121,32269, 759,32269,25673,32103,20501,32283,20763,32103, +32113,32287,27021,32287,30613,32287, 587,32103,32161,32295,32117,32295, +30117,32295, 713,32295,27021,32103,27483,32305,32105,32305,27418,32305, +27377,32305,18967,32312,18967,32305,27377,32316,31992,32103,32163,32321, +18967,32103,32163,32325,31937,32327,32165,32325, 9,32331, 9,32324, +32165,32335,30091,32324,20501,32339,31937,32324,32163,32343,31937,32103, +18967,32346,32163,32349,30091,32103, 9,32353,18967,32352,20501,32357, +18967,32353,20413,32361,18967,32102,24953,32365,32171,32365,32107,32365, +32172,32365,32167,32365, 9,32374, 9,32365,32167,32378,27021,32364, +27323,32383,27021,32365,27377,32387,21037,31102,26604,32391,31561,32391, +31615,32391,29645,32391,25793,32391,20103,32400,20103,32391,25793,32404, +21314,31103,23147,32409,24819,32409,28925,32409,28715,32409,20413,32417, +21036,31103,25673,32421,20501,32423,25087,32421,25691,32421,22357,32421, +24953,32421,21049,32421,21242,32421,21183,32421,20103,32438,27021,32420, +27323,32443,20103,32421,21183,32446,27021,32421,27377,32451,27436,31103, + 5,32454,27323,32457, 5,32455,27255,32461, 9195,31103, 9,32464, +27021,31103,21496,32468,21277,32468,20885,32468, 9,32468, 9731,32468, +21037,32468,21315,32468,20273,32482,27323,32483,21037,32469,21315,32469, +27205,32491,21036,32468,27323,32495,32489,32495,21036,32469,27231,32501, +32481,32501,20273,32468,21315,32506, 4,32469, 5,32469,27231,32513, +27272,32513,27255,32513,18967,32518,18967,32513,27255,32522, 9,32513, + 4,32468,32513,32529, 5,32468,27323,32533,18967,32535,32511,32533, +18967,32532,27323,32541, 17,32533,18967,32468, 5,32546,27323,32549, + 5,32547,27255,32553, 587,31103,30091,32557, 803,32559, 5,32556, + 9455,32563, 3803,32563,30121,32563, 759,32563, 5,32557, 9435,32573, + 803,32573,18967,31103,32391,32579,26625,32581,27398,32578,27345,32578, +21605,32578, 7,32589, 4,32591, 4,32590, 4,32589, 7,32596, + 16,32589,27282,32578,27323,32603,26625,32578,32391,32607,27377,32578, +27255,32610,20483,32579,25793,32615,27255,32578,27377,32618,21183,32579, +26625,32623, 4,32579,26142,32627,24849,32627,21605,32627, 7,32633, +25793,32627,20413,32636,20413,32627,25793,32640, 5,32579,32593,32645, + 4,32578,24819,32649,23147,32649,28925,32649,28715,32649,20413,32657, + 5,32578,24953,32661,32595,32661,32599,32661,32635,32661,32601,32661, +27021,32660,27323,32673,27021,32661,27377,32677,27021,32578, 5,32680, +27323,32683, 5,32681,27255,32687,20763,31103,18967,32691, 5,32692, + 5,32693,21037,32690,29835,32699,29659,32691,29835,32691,21036,32691, +21037,32691,25793,32709,30091,32691,20885,32713, 4,32691,32697,32717, + 5,32691,18967,32720,28681,32721, 4,32690,32723,32727,32695,32727, +29659,32727,29835,32727,32707,32727, 5,32690,28625,32739,22285,32739, +28659,32739,30227,32739,32709,32739,18967,31102, 5,32750,26816,32753, +24953,32753,31245,32753, 17,32753,26625,32753,20501,32762,20501,32753, +26625,32766, 5,32751, 9,32771,30091,32771,20501,32775,21526,21605, + 5,32778,26816,32781,24953,32781, 17,32781,26625,32781,20501,32788, +20501,32781,26625,32792, 5,32779, 9,32797,30091,32797,20501,32801, +18967,21605,20355,32804,20354,32804,26415,32805,26219,32810,26454,32805, +26375,32805,21127,32805,21183,32818,21248,32805,21273,32805,20986,32805, +20987,32805,28109,32804,28108,32805,32831,32833,31676,32805,31527,32837, +28109,32805,28108,32804,32841,32843,20352,32805, 4,32847,22729,32849, +22731,32847,32809,32847,20486,32805,26292,32805,26331,32859,19622,32804, +19623,32805,32863,32865,19623,32804,19622,32805,32869,32871, 386,32805, + 347,32805,21396,32804,21397,32805,32879,32881,21546,32804,21547,32805, +32885,32887,21397,32804,21396,32805,32891,32893,21547,32804,21546,32805, +32897,32899,20477,32805,27673,32805,20476,32805,27672,32805,21127,32804, +21087,32911,29031,32804,31881,32805,21543,32805,21087,32805,21127,32921, +31880,32805,21542,32805,26219,32805,26415,32928,27283,32805,31103,32933, +20353,32805,32807,32937,20487,32805,21403,32804,21402,32805,32943,32945, +21573,32804,21572,32805,32949,32951,21403,32805,21402,32804,32955,32957, +21573,32805,21572,32804,32961,32963,20985,32804,32829,32967,21401,32804, +32056,32805,29450,32805,29041,32975,28791,32975,29731,32975,29659,32975, +20984,32805,21400,32805,32971,32987,32103,32805, 7,32990,32365,32993, +32057,32805,29451,32805,32915,32999,20984,32804,32827,33003,20985,32805, +31103,33007, 7,33006,33003,33011,21400,32804,21401,32805,33015,33017, +21183,32805,21127,33020,20413,32805, 4,33025, 4,33024, 11,33024, +27533,32805, 17,33032,20273,32805, 7,33037, 7,33036, 15,33037, +25793,32805, 7,33045,26219,33047, 7,33044,26331,33051,21527,32805, + 17,33054,31103,32805, 4,33059,21037,33059,32421,33063,21037,33058, +31527,33067, 4,33058, 11,33058,21037,32805,31103,33075,32391,33077, +31103,33074,31527,33081,28715,32805,29031,33085, 7,33085,29759,33089, +21527,33085,29229,33093, 7,33084,29041,33097,29731,33097,29659,33097, +28791,33097, 15,33085, 580,32805, 1170,32805, 256,32805, 629,32805, + 1413,32805, 922,32805, 581,32805, 1171,32805, 767,32805,31103,33125, + 375,32805, 305,33128, 510,32805, 18,32804, 12,32804,23493,33137, + 1291,32805, 525,32805, 13,32805,22807,33145,33137,33145, 19,32805, +33135,33151, 18,32805, 13,32804, 12,32805,33157,33159, 19,32804, +33155,33163, 16,32805,32421,33167,25743,33167,32365,33167,32661,33167, +27533,33167,21037,33167,31103,33179, 10,32805,19333,33183,33137,33183, +31648,33183,19455,33183,24237,33183,22896,33183,19393,33183,19385,33183, + 9,33199,22807,33183, 9,33202,20413,33183, 9,33183,22807,33208, +21315,33183,31103,33212,31103,33183,21315,33216, 14,32804,32847,33221, +33041,33221,24953,33221,32975,33221,33097,33221,26816,33221,33167,33221, +33111,33221, 17,33221,20501,33221,26625,33240,26625,33221,20501,33244, + 10,32804,22149,33249,19441,33249,24213,33249,24059,33249,19656,33249, + 9,33249,19631,33260,19631,33249, 9,33264,23983,33249, 9,33269, + 524,32805, 1290,32805, 11,32804,21087,33277,20326,33277,33183,33277, + 9,33283, 9,33276,23493,33287,33183,33287,23493,33277, 9,33293, +20273,33277, 9,33296, 9,33277,20273,33300, 9,32804, 11,33304, +23493,33307,33183,33307, 11,33305,24265,33313,33249,33313, 15,32804, +32937,33319,32999,33319,26142,33319,33123,33319,20413,33319,25793,33328, +20273,33319,25793,33319,20413,33334, 11,32805,24567,33339,33157,33339, +24428,33339,20413,33338,31103,33338,33260,33339,33249,33339, 9,33352, +24265,33339, 9,33356, 9,33339,24265,33360,33249,33360, 483,33338, + 9,32805,30090,33368,30090,33369,30091,33368,33373,33375, 483,33368, + 11,33369,20273,33381,30091,33369,33371,33385,20501,33385, 17,32805, +19474,33390,19475,33391,33393,33395,21314,33390,19474,33391,19475,33390, +33401,33403,21314,33391,21315,33390,33407,33409,27533,33390,21527,33390, +33319,33391, 1275,33390,21315,33391,33399,33421, 305,32805, 375,33424, + 1011,32805, 7,33428,33221,33431, 15,33429, 7,33429, 241,32805, + 7,33438, 483,32805, 4,33442, 903,33442, 9,33442, 4,33443, + 11,33442, 903,32805, 9,33455, 483,33454, 1275,32805, 17,33460, + 7,32805,20985,33464,33003,33467,20985,33465,32985,33471,25672,33465, +30772,33465,25673,33465,30773,33465,21036,33465,30090,33465,20273,33464, +33221,33487,25793,33464,26331,33491,28715,33464,29731,33495,29659,33495, +28791,33495,29041,33495,33221,33495,18967,33465, 5,33506,30091,33506, + 5,33507,33485,33513, 17,33507,21605,33465, 4,33518,33513,33521, +21037,33518, 4,33519,33509,33527,33483,33527, 11,33519,25793,33465, +26415,33535, 1011,33464,33221,33539, 241,33464, 8495,33465,32103,33465, +20273,33547,32165,33547,21037,33465,21604,33553,21605,33552,33555,33557, +21605,33553,21604,33552,33561,33563,28715,33465,20273,33567,29533,33567, +30091,33465,18967,33572,33221,33465,20273,33577,23927,33465,20273,33581, +29031,33465,20273,33585,32013,33465,20273,33589, 15,33465,29835,33465, +29659,33465,29077,33597,32102,33465, 4,33465,24687,33603,25773,33603, +21605,33602,33513,33609,31830,33603,32645,33603,29485,33603,22729,33603, +31103,33603,20273,33620,20273,33603,31103,33624, 5,33465,18967,33628, +33527,33631,31103,33628,20103,33629,31103,33637, 5,33464,33519,33641, + 7,33641,21605,33645,33603,33647,33620,33641,33547,33641,33557,33641, +33475,33641,33525,33641,33481,33641,31648,33641,20413,33641,33603,33641, +31103,33666,21315,33641,31103,33670,31103,33641,33603,33674,21315,33674, + 4,33464,33507,33681,25743,33681,33601,33681,32365,33681,32661,33681, +33635,33681,33575,33681,33477,33681,33511,33681,33479,33681,32421,33681, +33221,33681,27533,33681,33629,33681,31103,33709,21037,33681,31103,33713, +31103,33465, 5,33716,33681,33719, 5,33717,33603,33723, 6,32804, +33624,33727,33713,33727,33085,33727,29229,33733,33179,33727,21036,33727, +33681,33739,33167,33739,28714,33727,33567,33745,18967,33727, 5,33749, +33603,33751, 5,33748,33681,33755,33167,33755,20273,33727,33603,33760, +33603,33727,20273,33764,29451,33727, 17,33727, 5,33726,26816,33773, +33681,33773,24953,33773,33487,33773,33041,33773,33495,33773,33097,33773, +32847,33773,32975,33773,33167,33773,33111,33773,33539,33773,33431,33773, + 17,33773,33465,33773,20273,33803,26625,33773,20501,33806,20501,33773, +26625,33810, 5,33727,33603,33815,18967,33814,33681,33819,33167,33819, + 9,33815,33465,33815,20273,33827,30091,33815,20501,33831,33465,33727, +18967,33834, 4,33837, 4,33836,21315,33834,21314,33834, 4,33835, +33843,33847, 5,33835,33841,33851,33845,33851, 4,33834,18967,33856, +33851,33859,33851,33857, 5,33834,33839,33865,33847,33865, 5,32805, +27953,33871,27743,33871,27555,33871, 2,33870, 0,33870, 3,33870, + 1,33870,33609,33871,33521,33871,30285,33871,33485,33871,32717,33871, +25101,33871,33027,33871,33061,33871,23193,33871,33593,33871,33451,33871, +20413,33871,20885,33871,33603,33871,27533,33913,23015,33871,20501,33917, +27741,33871,20501,33921, 9,33871,30492,33871, 6,33871,33879,33929, +33881,33929,20273,33929, 7,33871,33883,33937,33885,33937,25793,33937, +32805,33936, 4,33945,21605,33937,33947,33949, 5,33949,33945,33953, +33603,33949,30091,33936,21527,33937,27533,33937,21315,33963, 7,33870, +31648,33967,20413,33967,31103,33967,21315,33972,21315,33967,31103,33976, +21315,33871,21605,33981,33929,33983,30091,33871,20501,33987, 6,33986, + 7,33986, 6,33987,33993,33995, 7,33987,33991,33999, 4,32804, +27530,34003,26142,34003,26270,34003,26009,34003,33879,34003,33929,34012, +33881,34003,33929,34016,33930,34003,33932,34003,33939,34003,33941,34003, +33506,34003,33681,34029,33683,34003,33934,34003,33943,34003,26454,34003, +26375,34003,33769,34003,32937,34003,32999,34003,33664,34003,32941,34003, +33908,34003,32997,34003,28571,34003,33970,34003,33961,34003,18967,34003, +33465,34062,33681,34065,33465,34063,33641,34069,33206,34003,33123,34003, +33121,34003,24210,34003,33413,34003,33415,34003,32903,34003,32909,34003, +33771,34003,32917,34003,32927,34003,33275,34003,33143,34003,27459,34003, +33419,34003,33463,34003,33035,34003,33057,34003,33517,34003,26219,34003, +20273,34110,26415,34110,24265,34003,28233,34003,29077,34003,33183,34003, +20413,34122,33641,34003,20413,34126,33967,34003,20413,34130,33391,34003, +27533,34135,20413,34003,25793,34138,27021,34138,33641,34138,33871,34138, +33967,34138,33183,34138,24095,34138,27021,34003,20413,34154,33929,34003, +33879,34158,33881,34158,20273,34158,20985,34003,31103,34167, 11,34003, +21605,34171,33465,34003,18967,34174,33681,34177,24095,34003,20413,34180, +26292,34003,26331,34185,20352,34003,25793,34189,33936,34003,33883,34193, +33885,34193,25793,34193, 7,34003,25793,34201,20273,34203,26415,34203, +33871,34201,33879,34209,33881,34209,20273,34209,25793,34200,26331,34217, +20273,34200,25793,34221,33871,34200,33883,34225,33885,34225,25793,34225, +26415,34003,26219,34232,20273,34003,26219,34236,33929,34236, 7,34236, +25793,34243,25793,34003,20413,34246, 7,34247,26219,34251, 7,34246, +26331,34255,33871,34003,18967,34258, 6,34261, 6,34260,21605,34259, +33929,34267,21527,34258,31103,34259,21526,34258,20413,34258, 6,34259, +34271,34279, 7,34259,34265,34283,34275,34283, 6,34258,34267,34289, +18967,34288,34283,34293,34283,34289, 7,34258,33883,34299,33885,34299, +34263,34299,34279,34299,25793,34299, 4,32805, 2,34311, 7,34313, +27669,34311,23357,34311,32468,34311,28483,34311,27978,34311,31746,34311, +31742,34311,31500,34311,20413,34310,23014,34311,31103,34310,21605,34311, + 7,34338, 7,34339,33773,34343,33221,34343, 15,34338,27021,34311, +31103,34350,28411,34311,33629,34311,20413,34357, 483,34310,31103,34311, +27021,34362,20843,34362,21127,34362,19687,34362,19687,34311,31103,34372, +20843,34311,31103,34376,21127,34311,31103,34380, 15,34311,21605,34384, + 375,34311,33727,34311, 9,34391, 7,34311,21605,34394,25793,34395, + 265,34395,31103,34395, 7,34310,33755,34405,33819,34405,33773,34405, +33739,34405,25743,34405,32661,34405,32421,34405,32365,34405,33221,34405, +27533,34405,21037,34405,33727,34427,31103,34427,21037,34311,33929,34433, +26219,34433, 7,34433,25793,34439,28715,34311,20413,34443, 5,32804, +27965,34447,27948,34447,26816,34447,27796,34447,26898,34447,20353,34447, +29451,34447,32847,34447,33487,34447,33041,34447,32975,34447,33495,34447, +33097,34447,34343,34447,34315,34447,33527,34447,33518,34447,33641,34481, +33643,34447,24953,34447,20119,34447,33706,34447,34362,34447,32727,34447, +25129,34447,34333,34447,33029,34447,34337,34447,33071,34447,32691,34447, +34424,34447,34403,34447,32067,34447,31707,34447,26887,34447,32857,34447, +32973,34447,21605,34447,33465,34522,33641,34525,33465,34523,33681,34529, +33176,34447,33111,34447,33109,34447,31505,34447,23480,34447,33347,34447, +33349,34447,32905,34447,32907,34447,32919,34447,32925,34447,33273,34447, +33141,34447,25099,34447,33539,34447,34361,34447,33445,34447,33431,34447, +33367,34447,33453,34447,33031,34447,33073,34447,33533,34447,20187,34447, +19683,34447,20839,34447,21399,34447,33167,34447,27533,34586,33681,34447, +27533,34590,34405,34447,27533,34594,28625,34447,28573,34447,33339,34447, +20413,34603, 1171,34447,27787,34447,20501,34608,27533,34447,20501,34612, +33681,34612,34405,34612,33167,34612,20501,34447,27787,34622,26889,34622, +26625,34622,27533,34622,23457,34622,34395,34447, 17,34447,33465,34447, +29077,34639,20273,34639,21605,34638,33641,34645,28233,34639,24265,34639, + 11,34639, 6,34446,26816,34655,34405,34655,33041,34655,33097,34655, +34343,34655,33681,34655,32847,34655,33487,34655,32975,34655,33495,34655, +24953,34655,33167,34655,33111,34655,33539,34655,33431,34655, 17,34655, +33465,34655,20273,34689,20501,34655,26625,34692,26625,34655,20501,34696, + 7,34446,34635,34701,34579,34701,34311,34701,20103,34701,20186,34447, +34655,34711,34394,34447,34655,34715,31103,34447,34311,34718, 6,34447, +34706,34723,34395,34723,33039,34723,33089,34723,34397,34723,34341,34723, +20273,34723,34708,34723,23175,34723,24941,34723,34325,34723,28133,34723, +33437,34723,20103,34723,34701,34750,34701,34723,34311,34754,20103,34754, + 11,34723,34311,34723,34701,34762,20763,34723,26625,34767, 7,34447, +21605,34771,34311,34773,34655,34771,34311,34777,20103,34777,20103,34770, +34655,34783,34311,34770,34655,34787,23457,34447,20501,34790,26889,34447, +20501,34794,20103,34447, 7,34799,34723,34801, 7,34798,34655,34805, +26625,34447,20501,34808, 6,34809, 7,34809, 6,34808,34815,34817, + 7,34808,34813,34821,34311,34447,21605,34824,18967,34825, 6,34828, + 6,34829,31103,34824,21527,34825,21526,34825,20413,34825, 6,34825, +18967,34842,34827,34843, 7,34825,34723,34849,25793,34849,34833,34849, + 6,34824,34849,34857,34837,34857, 7,34824,34655,34863,34845,34863, +34831,34863,34843,34863,34839,34863, 6,32805,34236,34875,34120,34875, +34433,34875,20962,34875,21001,34875,34118,34875,34355,34875,25648,34875, +21314,34874,34891,34893,25649,34875,33087,34875,21314,34875,34116,34875, +23017,34875,34335,34875,21937,34875,34170,34875,34173,34875,21959,34875, +21315,34874,34897,34917,34385,34875,34387,34875,24875,34875,33332,34875, +33435,34875,33043,34875,33107,34875,34349,34875,21605,34875,21315,34936, +34893,34939,21315,34937,34901,34943,20273,34875,34003,34946,33319,34946, +20885,34875,20843,34952,21315,34875,21605,34956,34893,34959,19475,34875, +26625,34963,24265,34875,34003,34966,29077,34875,34003,34970,28233,34875, +34003,34974,20843,34875,20885,34978, 11,34875,34003,34982,33319,34875, +20273,34986,34003,34875,29077,34990,20273,34990,28233,34990,24265,34990, + 11,34990,30993,34875,30901,34875,20984,34875,20839,35007, 5,34875, +20763,35011,20843,35013,20763,35010,20839,35017,20763,34875, 5,35020, +20839,35023, 5,35021,20885,35027, 7,32804,34736,35031,34459,35031, +34461,35031,29691,35031,29340,35031,28714,35031,33603,35043,21605,35031, + 5,35047,33681,35049,34405,35049,33167,35049, 5,35046,33603,35057, +34607,35031,34637,35031,33924,35031,34447,35031, 11,35031,32103,35031, +29835,35031,29659,35031,20273,35031,34723,35076,29229,35076,35011,35031, +34723,35031,20273,35084, 567,35031,29229,35031,20273,35090, 9,35031, +33871,35094,33871,35031, 9,35098, 4,35030, 5,35030,35083,35105, +34875,35105,35010,35031,35103,35111, 4,35031,35108,35115, 7,35114, +35049,35119,35105,35115,34875,35122,34875,35115,35105,35126, 483,35115, + 5,35031,21605,35132,33603,35135,35103,35133,34875,35139,34875,35132, +35103,35143,34875,35031,18967,35147, 4,35148, 4,35149,21315,35147, +21314,35147, 4,35147,18967,35158, 5,35147,35115,35163,35153,35163, + 4,35146,35163,35169,35155,35169, 5,35146,35103,35175,35161,35175, +35151,35175,35159,35175,35157,35175, 0, 4,14087,35187,14103,35188, + 4983,35187, 5001,35192,14104,35187, 5002,35187,14088,35187,14091,35201, + 4984,35187, 4987,35205,14093,35187, 4989,35187,28758,35187,29229,35213, +28741,35187, 2,35216,29229,35219,20501,35186,19463,35223,19317,35223, +19301,35223,20009,35223, 53,35186,19463,35233,20009,35233,19317,35233, +19053,35187, 989,35241, 1201,35187,18967,35245, 1203,35247,17673,35186, +17685,35251,21405,35186,21489,35255,19513,35186,19463,35259,20009,35259, +19317,35259,10157,35187, 17,35267,10159,35269,20343,35187,18967,35273, +20345,35275, 1179,35187, 527,35186,19301,35281,19916,35186, 4,35285, + 7,35286, 7,35285, 4,35290, 16,35285,19069,35186,19301,35297, + 1290,35186, 0,35301, 2,35302, 2,35301, 0,35306,18966,35301, +21530,35187,20501,35313, 1489,35187,16859,35187, 11,35318, 9875,35321, +21529,35187, 11,35324,20501,35327, 147,35187,16860,35187, 9875,35333, + 987,35187, 8069,35187, 11,35338, 8067,35341, 8070,35187, 8067,35345, +27519,35187,27525,35187,26322,35187,26566,35187,26102,35187,26276,35187, +26105,35187,33464,35187,29600,35187,32295,35187,31856,35187,25636,35187, +29229,35371, 9,35371,28555,35187,29229,35377, 9,35377,19301,35187, +20501,35383, 527,35383,19069,35383, 4266,35187, 8056,35187, 8147,35187, +20739,35187, 9997,35187, 8784,35187, 8622,35187, 8824,35187, 8702,35187, + 8697,35187, 8676,35187, 8635,35187,20828,35187,19772,35187,19890,35187, +19774,35187,19894,35187,19382,35187,19458,35187,32557,35187, 803,35429, +19463,35187,20501,35433, 53,35433,19513,35433,20009,35187, 53,35441, +20501,35441,19513,35441,19317,35187,20501,35449, 53,35449,19513,35449, +19914,35187,21066,35187,20575,35187,21312,35187,21270,35187, 694,35187, + 9377,35467,16920,35187, 9,35471,17621,35187, 9,35475, 4213,35187, + 375,35478, 8757,35187, 375,35482, 9530,35187, 9875,35487,16091,35487, +20501,35487,19751,35187, 53,35495, 253,35495, 117,35495, 71,35495, + 1471,35495, 1397,35187, 9592,35187,16514,35187,19380,35187,13836,35187, +20595,35187, 9911,35187, 9983,35187, 9905,35187,17566,35187,16816,35187, +17910,35187,18880,35187,14103,35187,14087,35532, 5001,35187, 4983,35536, +20597,35187,26219,35187, 241,35542, 587,35543, 8647,35187, 241,35548, + 587,35549,14073,35187, 586,35554,14091,35557, 586,35555,14103,35561, + 4971,35187, 586,35564, 4987,35567, 586,35565, 5001,35571, 1291,35187, +35305,35575,35309,35575, 1871,35575, 1889,35575, 3,35575,19667,35575, +12345,35575, 5123,35575,19067,35575,35311,35575,18967,35575, 1297,35597, +35301,35597,19917,35187,35289,35603,35293,35603,19939,35603,19945,35603, + 6,35603,19947,35603,35295,35603, 17,35603,19931,35619,35285,35619, + 1108,35187, 11,35625,22806,35187, 9,35629, 524,35187, 3,35633, + 3477,35633, 2007,35633,19051,35633,19667,35633,12345,35633, 5123,35633, +18967,35633, 555,35649, 713,35187, 1325,35187,17455,35655,10001,35187, + 1505,35659, 9513,35187, 11,35662, 9875,35665,16091,35665,20501,35665, +19396,35187, 483,35672,17455,35187,13737,35676, 803,35187,31103,35680, +31103,35187, 803,35684, 113,35187, 375,35187, 587,35691, 9195,35693, + 4213,35690, 7971,35690, 8757,35690, 587,35690, 9377,35703, 9565,35690, +18967,35690,19892,35187, 9,35710, 510,35187,18967,35714, 587,35187, + 375,35718, 9377,35721, 9377,35719, 375,35725, 483,35187,19396,35728, + 587,35729, 11,35728, 5123,35735,12345,35735, 3477,35735, 2007,35735, +19667,35735,19051,35735,18967,35735, 555,35749,18967,35728, 9,35752, + 9,35728,18967,35756, 1275,35187,16833,35760, 9,35763, 903,35761, + 9,35761,21575,35187,18967,35771,21577,35773,21581,35773,21585,35773, + 6685,35187, 7519,35187, 17,35783, 7521,35785, 7525,35785, 7529,35785, +21258,35187, 241,35792,16722,35187,32103,35187, 9,35799,10310,35187, + 8684,35187, 241,35804, 331,35805,26292,35187, 241,35810, 482,35186, + 2,35815, 0,35816,35633,35819,35735,35819, 0,35815, 2,35824, +35633,35827,35735,35827,35749,35815,35649,35815,18966,35815,35735,35837, +35633,35837, 1368,35186,25793,35843, 8495,35843,23755,35843,10055,35843, + 4329,35843, 4311,35843,26331,35843,27805,35843, 3785,35843, 8717,35843, +10351,35843, 586,35186,31761,35867,32563,35867,32269,35867, 7,35867, + 4,35874, 4,35867, 7,35878, 16,35867, 767,35867,31103,35885, + 482,35187, 587,35889, 1274,35187, 587,35186, 9262,35895, 375,35895, + 9195,35898, 7,35895, 265,35903, 9195,35905, 9195,35895, 375,35908, + 483,35895, 483,35186, 1369,35186,19463,35917,19301,35917,20009,35917, +19317,35917, 1368,35187, 7,35927, 586,35187,14073,35930,14091,35933, + 4971,35930, 4987,35937,31856,35931,32295,35931, 7971,35931,14073,35931, +14087,35947, 4971,35931, 4983,35951,31103,35931, 803,35954, 803,35931, +31103,35958, 483,35931, 1531,35187,13737,35187, 1487,35966,17455,35966, +16833,35187, 1196,35972, 1196,35973, 1197,35972,35977,35979, 1197,35973, +35975,35983, 1275,35972, 9,35987, 767,35187,31103,35991, 1487,35187, +13737,35994,16937,35187, 17,35999, 9377,36001,17573,36001,16947,36001, + 1347,35187,18967,36009, 555,36011, 251,36011, 1365,36011, 1351,36011, + 21,36011,20762,35187, 241,36022, 256,35187,25793,36026,25793,36027, + 8495,36026, 8495,36027,18967,36026,21037,36026, 972,35187, 9377,36041, + 629,35187,18967,36044, 340,35187, 9377,36049,27978,35187,28353,36053, +30003,36053,29759,36053,34723,36053,21183,36053, 2,36053,28337,36065, +28189,36065,28191,36053, 959,36053, 759,36053, 47,36053, 66,35187, + 89,35187, 7,36080, 973,35187,35895,36085,21527,35187,21605,36088, +29229,36091, 9,36091, 145,35187, 165,35187, 305,35187, 25,35187, +27533,35187, 1505,36105, 331,35187,17455,36109, 59,35187,17455,36113, +29599,35187, 7,36116,26546,35187, 7,36120, 8812,35187, 7,36124, +10291,35187, 3,36129, 3,36128, 9565,35187, 375,36134, 8495,35187, + 256,36138, 7,36139, 375,36143, 7,36138, 241,36146, 331,36147, + 241,36138, 7,36152, 7971,35187, 375,36156,25793,35187, 256,36160, + 7,36160, 241,36164, 241,36160, 7,36168,32805,35187, 7,36172, +19888,35187, 7,36176,18967,35187, 256,36180, 629,36180, 510,36180, + 375,36180, 483,36180, 9,36190, 9,36180, 483,36194, 7,36180, + 241,36198, 7,36181,25793,36203, 8495,36203, 241,36180, 7,36208, + 241,35187,26292,36212,26219,36212, 8684,36212, 8647,36212,20762,36212, +21258,36212, 7,36212,25793,36226,25793,36227, 8495,36226, 8495,36227, +18967,36226,21037,36226,25793,36212, 7,36240, 8495,36212, 7,36244, +18967,36212, 7,36248,21037,36212, 7,36252, 9,35187,19892,36256, + 1011,36256, 11,36261,18967,36256, 483,36264, 483,36256,18967,36268, + 903,35187, 7,36272, 9377,36275,19913,35187, 6,36279, 7,36279, + 6,36278,36283,36285, 7,36278,36281,36289, 15,35187,25381,36293, + 483,36293, 2,36293,28189,36299, 1011,35187,16710,36303,16711,36303, +16710,36302,36307,36309, 0,36303, 6,36312,16711,36302,36305,36317, + 9,36302, 11,36321, 1275,36302,36315,36325, 11,36303, 9,36329, + 6,36302, 3,36332, 6,36303, 0,36336,36325,36339, 7,36303, +25793,36343, 8495,36343,21605,35187,21037,36348,21105,36348,21527,36348, +29229,36355, 9,36355,21549,36348,19625,36348,21526,36348, 5,36364, + 922,36349, 918,36349, 1505,36349, 1419,36349, 668,36349, 483,36349, + 903,36378, 587,36349, 9,36382, 9,36349, 903,36386, 11,36387, + 587,36386, 15,36348, 11,36348, 9,36397, 6,36348,21036,36400, + 5,36400,18967,36404,18967,36400, 5,36408, 7,36348,30003,36413, +29759,36413,34723,36413,21183,36413, 959,36413, 47,36413, 759,36413, + 6,36349,36353,36429,36361,36429,36351,36429,36363,36429, 7,36349, +36403,36439,31527,36439,22269,36439,28791,36439,22263,36439,32781,36439, +36367,36439,21105,36439,21549,36439,29953,36439,29731,36439,34655,36439, +33773,36439,29835,36439,29659,36439,34447,36439,32753,36439,32019,36439, +29041,36439,23929,36439,22205,36439,19625,36439,33221,36439,36407,36439, +36411,36439,18967,36348, 5,36490, 6,36493,36413,36495, 6,36492, +36439,36499,36439,36493, 14,36490,36439,36505, 6,36491,36395,36509, + 6,36490, 5,36512,36439,36515, 903,36349, 7,36519, 9,36518, + 483,36518, 265,35187,17455,36527, 5843,36527, 483,36527, 587,36527, + 9,36527, 7,36526, 9377,36539, 7,36527, 11,35187, 8069,36544, + 8067,36547,16859,36544, 9875,36551,21529,36544,20501,36555,16091,36545, + 9513,36559, 7,36544, 2,36563, 7,36564,36545,36567, 1,36564, +36569,36571, 1,36563, 2,36574, 0,36544, 2,36579, 0,36580, +36545,36583, 6,36580,36585,36587, 6,36579, 2,36590, 482,36579, + 1368,36544, 2,36597, 1,36598, 1,36597, 2,36602,18966,36544, + 2,36607, 6,36608, 6,36607, 2,36612, 482,36607, 9513,36544, +20501,36619, 9875,36619,16091,36619,20501,36545,21529,36627, 9513,36627, + 9875,36545,16859,36633, 9513,36633, 1369,36545, 1989,36639, 3587,36639, +36601,36639,36605,36639, 5303,36639,36571,36639,36577,36639, 0,36639, + 4897,36639,17041,36639,18967,36545,20281,36661,20345,36661,36611,36661, +36615,36661,36587,36661,36593,36661, 7,36661,20285,36661,36595,36661, +36617,36661, 483,36661,20273,36683,36579,36683,36607,36683,21605,36544, + 9,36691, 483,36544,35819,36695,35827,36695, 3477,36695, 2007,36695, + 1,36695,36639,36705,36655,36695,19051,36695,19667,36695, 5123,36695, +12345,36695,35837,36695,18967,36695, 555,36721,35815,36721, 3,36544, + 3,36545, 375,36729,21308,35187, 7,36732,16481,35187, 7,36736, +21037,35187, 256,36740, 7,36740, 241,36744, 241,36740, 7,36748, +16531,35187, 7,36752, 1011,36753, 7,36757,18797,35187, 7,36760, +17827,35187, 7,36764,16783,35187, 7,36768, 2,35186,27138,36773, +28047,36773,26454,36773, 8770,36773,26375,36773, 8729,36773, 8697,36773, + 8784,36773,28197,36773, 4266,36773, 9262,36773,28111,36773,27128,36773, +28027,36773,28117,36773,28177,36773,31872,36773,28063,36773,31598,36773, +24545,36773,31103,36812, 8684,36773, 8717,36817, 331,36817,26292,36773, +26331,36823, 8647,36773, 8757,36826,26219,36773,27021,36830,26415,36830, +26415,36773,26219,36836, 8757,36773, 8647,36840, 375,36840, 4213,36773, + 375,36846,28153,36773,26860,36773,28213,36773,35931,36773,28159,36773, +31770,36773, 347,36773, 386,36773, 9750,36773,27978,36773,26331,36869, +27805,36869, 1325,36869, 331,36869, 59,36869,23755,36869,25793,36869, + 265,36869, 340,36773, 331,36887,31103,36773,24545,36890,26625,36890, + 9,36890, 375,36773, 8757,36898, 4213,36898, 9195,36898,27021,36898, + 305,36898, 483,36773, 9195,36773, 375,36912,10001,36773, 9,36917, + 1325,36773, 1275,36773, 331,36773,27533,36773, 9,36927, 305,36773, + 375,36930,10291,36773, 483,36935,27021,36773,26219,36938, 375,36938, + 7,36773,25793,36944,26331,36947, 8495,36944, 8717,36951, 331,36951, +25793,36945,26415,36957,27021,36957, 8495,36945, 8757,36963,26625,36944, + 9731,36944,21605,36945,24545,36971,26625,36971, 9,36971, 265,36945, + 8757,36979, 4213,36979,27021,36979, 9195,36979, 305,36979,21605,36944, +26331,36991,27805,36991,23755,36991, 59,36991, 331,36991, 1325,36991, +25793,36991, 265,36991, 265,36944, 331,37009, 8647,36945,26219,36945, + 59,36773, 7,36772,25793,37019, 8495,37019,23755,37019,10055,37019, + 4329,37019, 4311,37019, 3785,37019,27805,37019,10351,37019, 8717,37019, +26331,37019, 9,36773,31103,37042, 15,36773,31103,37047, 9731,36773, + 7,37050,21605,36773, 15,37055,31103,37057, 6,37055, 5,37060, + 7,37055,26219,37065, 375,37065, 6,37054,37057,37071, 7,37054, +26331,37075,37063,37075,27805,37075,23755,37075, 59,37075, 331,37075, + 1325,37075,25793,37075, 265,37075, 265,36773, 7,37095, 8495,37097, + 375,37097, 7,37094, 331,37103,26625,36773,31103,37106, 7,37106, + 8495,36773, 7,37112, 8717,37115, 331,37115, 9,37113, 483,37113, + 7,37113, 8647,37125, 375,37125,25793,36773, 7,37130,26331,37133, + 483,37131, 9,37131, 7,37131,26219,37141, 3,35186,20305,37145, + 9641,37145,20309,37145, 9645,37145, 4,37145, 7,37154,35603,37157, + 9719,37145, 16,37145,35603,37163,35619,37145,21081,37145,20323,37145, +20387,37145, 9701,37145,35719,37145, 524,37145,20273,37179, 9617,37179, + 1291,37145, 9617,37185,20273,37185, 305,37145, 375,37190, 386,37145, + 347,37145, 767,37145,31103,37199, 483,37145, 11,37202, 9617,37205, +20273,37205, 375,37145, 305,37210, 7,37145, 3,37215,18967,37217, +35187,37219, 4,37214,35603,37223,37221,37223, 3,37214,35187,37229, + 11,37145, 483,37232, 9617,37235,20273,37235, 6,35186,19975,37241, + 0,37241, 2,37244,35575,37247,35633,37247,35735,37247,36695,37247, +18966,37241,35735,37257,35633,37257,35575,37257,36695,37257,35749,37241, +35649,37241,36721,37241,35597,37241,19365,37241,19221,37241,19917,37241, +10107,37279, 587,37241, 3,37241, 2,37241, 6,37287, 17,37289, +35187,37291, 0,37286,35575,37295,35633,37295,35735,37295,36695,37295, +37293,37295, 6,37286,36544,37307,37295,37309, 11,37307,35187,37312, +37295,37315,35187,37307, 11,37318,37295,37321, 7,35186, 4,37325, + 3,37326, 3,37327,35927,37331, 902,37325,25525,37325, 1325,37325, +10001,37325, 903,37341, 1275,37325, 59,37325,25793,37325, 587,37349, + 8495,37325, 587,37353, 2,37325, 7,37356,37331,37359, 903,37357, +10311,37357, 3,37325, 4,37366,27533,37325, 903,37371, 331,37325, + 2,37324,25793,37377, 8495,37377,23755,37377, 4329,37377,10055,37377, +27805,37377, 3785,37377, 4311,37377,26331,37377, 8717,37377,10351,37377, +21605,37325, 903,37401, 155,37401, 265,37325, 7,35187, 5045,37408, + 805,37409, 9195,37413, 4,37408,37279,37417,19916,37417,37241,37421, + 1275,37417,18967,37424,37241,37427,18967,37417, 1275,37430,37241,37433, +26546,37408,32805,37408,29599,37408, 652,37409, 9195,37443, 8812,37408, +19888,37408,19913,37408,21308,37408,16481,37408,37285,37409,16783,37408, +17827,37408,18797,37408,26498,37409, 8796,37409, 8495,37408, 241,37468, + 331,37469,25793,37408, 241,37474,25793,37409, 241,37479, 587,37478, + 8495,37409, 241,37485, 587,37484,21037,37408, 241,37490, 88,37409, +37411,37495,16531,37408, 587,37409, 265,37500, 9195,37503,26625,37501, +25793,37501, 8495,37501,25793,37500, 8495,37500, 9731,37501, 265,37409, + 587,37518, 9195,37521, 4213,37519, 7971,37519, 8757,37519, 587,37519, + 9377,37531, 9565,37519, 89,37409, 5069,37537, 9195,37537,27021,37537, + 483,37409, 1275,37409, 9,37547,26503,37409, 8809,37409,18967,37408, + 241,37554, 241,37408,25793,37558,25793,37559, 8495,37558, 8495,37559, +18967,37558,21037,37558, 903,37408, 9377,37573,21605,37408,30003,37577, +29759,37577,34723,37577,21183,37577,37495,37577, 959,37577, 47,37577, + 759,37577, 265,37408, 9377,37595, 903,37409,31103,37598,31920,37409, +31103,37409, 903,37604, 375,37409, 2,37408,37331,37611,37495,37611, + 3,37408,14072,37616, 4970,37616,14072,37617,14073,37616,37623,37625, + 4971,37616, 4970,37617,37629,37631, 7,37617, 4,37635, 1,37616, +37537,37639, 9,37639,36773,37617,37537,37617, 7971,37617,14073,37617, +37619,37651, 4971,37617,37621,37655, 483,37617, 9,37617, 2,37409, +37369,37663,37329,37663,37637,37663, 7,37662,37617,37671,37335,37663, + 9362,37663,27218,37663,37642,37663,37639,37663, 9,37682,28189,37663, + 1,37663, 5,37688,37616,37690,37617,37691,37693,37695,37671,37694, +37616,37691,37617,37690,37701,37703,37672,37691,37671,37691,37617,37708, + 5,37663, 1,37712,37616,37714,37617,37715,37717,37719,37671,37718, +37616,37715,37617,37714,37725,37727,37672,37715,37671,37715,37617,37732, +28337,37663,37660,37663,27021,37663, 9,37740, 9195,37663, 9,37744, + 9,37663,37639,37748,27021,37748, 9195,37748,37617,37748,37241,37663, +37617,37663, 1,37760, 5,37762, 5,37760, 1,37766, 7,37761, +37691,37771,37715,37771,37765,37771,37769,37771, 9,37760, 3,37409, +37577,37783, 9,37785, 16,37783, 4,37783, 7,37790, 7,37783, + 4,37794,18967,37783,35187,37799,37789,37801,37793,37801,37797,37801, + 9,37782,37577,37809,37611,37809,37611,37783, 1,37815, 5,37816, + 5,37815, 1,37820, 7,37814,37819,37825,37823,37825, 9,37815, + 9,37409, 3,37832,37577,37835,37611,37835, 3,37833,37663,37841, + 3,35187,10104,37844,10105,37844, 0,37845, 5,37850, 4,37844, +36773,37855,10104,37845,37849,37859,10105,37845,37847,37863,36945,37845, +37855,37867,10291,37844,36944,37845, 265,37873,37663,37845, 7,37877, +37691,37879,37715,37879, 1369,37845, 11,37885, 9617,37887,37853,37887, +20273,37887, 11,37844, 6,37844, 7,37844,14072,37898, 4970,37898, +14073,37898,14072,37899,37905,37907, 4971,37898, 4970,37899,37911,37913, +35187,37899,36773,37899, 7971,37899,14073,37899,37901,37923, 4971,37899, +37903,37927, 483,37899, 6,37845,37856,37933,37855,37933,36773,37936, + 1,37933, 5,37940,37898,37942,37899,37943,37945,37947,37898,37943, +37899,37942,37951,37953, 5,37933, 1,37956,37898,37958,37899,37959, +37961,37963,37898,37959,37899,37958,37967,37969,36773,37933,37855,37972, +37899,37933, 7,37845, 265,37979,36773,37981,35187,37978, 2,37985, + 4,37979,37987,37989, 3,37989,37985,37993,37663,37989,36773,37978, + 265,37999,37897,37979,36773,37845, 4,38005,37933,38007, 7,38005, +37943,38011,37959,38011,14073,38011, 4971,38011, 6,38004, 1,38021, + 5,38022,38011,38025, 5,38021, 1,38028,38011,38031,38007,38021, + 7,38004, 265,38037,18967,37845, 4,38041,37933,38043, 256,38041, + 7,38041, 241,38048, 241,38041, 7,38052, 2,35187,29229,38057, +28741,38059,28741,38056,29229,38063, 0,38057, 0,38056,28714,38069, +37185,38069, 1290,38069,37145,38075,37179,38069, 525,38069,37145,38081, +37887,38069,37205,38069,37235,38069, 5,38069,21605,38090,21605,38069, + 5,38094, 1275,38069, 17,38098,37145,38101, 17,38069, 1275,38104, +37145,38107, 1505,38057,17455,38057, 903,38112,17494,38057, 483,38057, +37214,38057,14073,38121, 4971,38121,37783,38057, 587,38057,10373,38057, + 9,38057, 155,38057, 6,38056, 1,38137, 5,38138,38121,38141, + 5,38137, 1,38144,38121,38147,37145,38137, 587,38137, 7,38056, +37331,38155, 6,38057, 5,38158,18966,38159, 0,38159, 2,38164, + 2,38159, 0,38168, 1369,38159, 17,38159,35187,38175,38163,38177, +38167,38177,38171,38177, 7,38057,38141,38185,37145,38187,38147,38185, +37145,38191,34447,38185,28715,38185,38069,38197,38071,38185,29659,38185, +29835,38185,38093,38185,38097,38185, 4971,38185,37145,38211,14073,38185, +37145,38215,37145,38184,38141,38219,38147,38219,14073,38219, 4971,38219, +21605,38185, 903,38229,37145,38057, 4,38232, 6,38233, 1,38237, + 5,38238, 5,38237, 1,38242,38235,38237, 7,38233, 265,38249, + 7,38232,38241,38253,38245,38253,38141,38253,38147,38253,14073,38253, + 4971,38253, 903,38057,17455,38266, 6,35187, 4,38271, 1,38272, + 0,38270, 17,38277,37844,38278,37845,38279,38281,38283,37845,38278, +37844,38279,38287,38289, 1369,38271, 2,38270, 587,38295, 3,38270, + 2,38271, 1275,38301, 1, 5,35962,38304,35963,38304,37760,38304, +37771,38311,37976,38304,38002,38304,37761,38304,37977,38304,37815,38304, +37825,38323,38003,38304,37930,38304,37658,38304,37931,38304,37659,38304, + 77,38304, 3095,38337, 1917,38337, 120,38304, 3013,38343, 1897,38343, + 79,38305, 3113,38349, 125,38305, 3023,38353,35929,38305,37885,38357, +37916,38305,37885,38361,38021,38304,38011,38365,38237,38304,38253,38369, + 4597,38305, 6625,38373, 113,38304, 4696,38377, 9,38377, 4669,38380, + 4669,38377, 9,38384,37896,38304,37898,38304,37933,38391, 483,38391, +37616,38304,37663,38397, 483,38397, 59,38304,23023,38403,25483,38403, +22677,38403,27533,38304,23023,38411,22677,38411,22605,38411,25483,38411, +37663,38304,37617,38420,37672,38421,37671,38421,37617,38426,37771,38421, +37879,38421,37617,38421,38397,38435,37671,38434,37933,38304,37899,38440, +38011,38441,37899,38441,38391,38447,37897,38304,38137,38304,38121,38453, +38219,38453,38185,38453,37145,38459,38253,38453,37617,38304,37663,38464, + 483,38464,37899,38304,37933,38470, 483,38470, 979,38305,21605,38477, + 987,38479,21879,38305, 1205,38483,29229,38304,29375,38487,17105,38304, +17117,38491,23755,38304,23023,38495,22677,38495,25483,38495,26863,38305, +21605,38503,26865,38505,10091,38305, 15,38509,10093,38511, 1009,38305, + 675,38304,22605,38517, 1418,38304, 1,38521, 3,38522, 3,38521, + 1,38526,21604,38521,21895,38304,22605,38533,25380,38304, 5,38537, + 6,38538, 6,38537, 5,38542, 14,38537, 1365,38305,17573,38305, + 9,38550,10001,38553,27996,38305,27533,38557, 1203,38305,17574,38305, +10001,38563, 177,38305,27995,38305, 9,38568,27533,38571, 7963,38305, + 9,38574, 7961,38577, 7964,38305, 7961,38581, 120,38305, 77,38305, +37758,38305,37972,38305,37457,38305,37867,38305,35912,38305,35733,38305, +35732,38305,35913,38305,22605,38305,27533,38605, 675,38605,21895,38605, +36856,38305, 483,38613,37644,38305, 483,38617,37918,38305,37933,38621, + 483,38621,37177,38305, 483,38627, 4798,38305,15896,38305,23023,38305, + 59,38635,27533,38635,23755,38635,22677,38305,27533,38643, 59,38643, +23755,38643,25483,38305, 59,38651,27533,38651,23755,38651,25368,38305, +30290,38305,27127,38305,30762,38305,30566,38305, 843,38304,35187,38669, + 1531,38304, 842,38304, 1530,38304,35930,38305,38675,38679,38307,38679, + 9492,38305,10001,38685,13755,38685,27533,38685,24597,38305, 59,38693, + 331,38693, 97,38693, 141,38693, 1325,38693, 629,38305,37896,38305, +37610,38305,37783,38709,37616,38305,38467,38713,38423,38713,38311,38713, +38331,38713,38469,38713,38465,38713,37663,38725, 483,38725,37898,38305, +38473,38731,38443,38731,38315,38731,38329,38731,38475,38731,38471,38731, +37933,38743, 483,38743,37866,38305,37456,38305,17508,38305, 9257,38305, +27149,38305, 9353,38305, 9253,38305,38253,38305,38137,38763,38237,38763, + 483,38763,38219,38305,38137,38771, 483,38771,38121,38305,38137,38777, + 483,38777,15897,38305, 4799,38305,27161,38305,20187,38305, 483,38789, + 8387,38305, 483,38793, 9541,38305,15879,38305, 483,38798, 4787,38305, + 483,38802,16125,38305, 3,38806, 2,38806, 842,38806, 843,38807, +38813,38815, 842,38807, 843,38806,38819,38821, 2,38807,38809,38825, + 3,38807,38811,38829, 5121,38305, 3,38832, 2,38832, 842,38832, + 843,38833,38839,38841, 842,38833, 843,38832,38845,38847, 2,38833, +38835,38851, 3,38833,38837,38855,35729,38305, 587,38859, 587,38858, +19384,38305, 483,38865, 669,38305, 1011,38869, 1086,38305, 483,38873, + 1418,38305, 1011,38877,25381,38305,38541,38881,38545,38881,25423,38881, +25429,38881, 7,38881,25431,38881,38547,38881, 15,38881,25415,38897, +38537,38897, 1419,38305,38525,38903,38529,38903, 1801,38903, 1875,38903, + 2,38903,23983,38903,10603,38903, 4625,38903,21893,38903,38531,38903, +21605,38903, 1421,38925,38521,38925, 1108,38305, 9565,38931, 246,38305, + 483,38935, 294,38305, 8495,38939,35931,38305,38669,38943,38309,38943, + 483,38943,36773,38942, 483,38951,19396,38305,35718,38305,37885,38957, +37202,38957,37145,38957, 483,38962, 483,38957,37145,38966, 668,38305, + 2,38971, 3507,38971, 1971,38971,21783,38971,23983,38971,10603,38971, + 4625,38971,21605,38971, 713,38987,20060,38305, 483,38991, 713,38305, +16833,38995,38011,38305,37933,38999,38021,38999, 483,38999,37285,38305, +37409,39006,36945,38305,37845,39011,37845,39010, 483,39011,37215,38305, + 3,39019,38057,39019, 9377,38305, 9,39024,10001,39027,13755,39027, +27533,39027, 1471,38305,16937,39035, 9875,38305, 1011,39039, 1347,39039, + 555,38305,20763,38305, 566,39046, 566,39047, 567,39046,39051,39053, + 567,39047,39049,39057, 257,38305, 483,39061, 973,38305, 4816,39065, + 4805,39065, 1011,39068,38057,39065, 1011,39065, 4805,39074, 628,38305, + 483,39079, 1406,38305, 587,38305,23584,39085,24355,39085,37782,39085, +37408,39084,39091,39093,37783,39085,37408,39085,38670,39085, 3,39085, +37409,39102,39093,39105,37409,39103,39099,39109,38669,39085,35187,39112, +35728,39084,23493,39085,22807,39118,22807,39085,23493,39122,35729,39084, +35728,39085,39127,39129,35729,39085,39117,39133,37409,39085, 3,39136, +39093,39139, 483,39085,35187,39142,35187,39085,38669,39146, 483,39146, +36773,39147, 483,39153, 1011,39084, 483,39157, 9,39084, 4625,39161, +10603,39161, 3507,39161, 1971,39161,23983,39161,21783,39161,21605,39161, + 713,39175,18967,39084, 483,39179,35187,39084,37202,39183,37885,39183, +37145,39183, 483,39188, 483,39183,37145,39192,37409,39084,39097,39197, + 11,39084, 483,39201, 1369,38305,35964,39204,35965,39205,39207,39209, +35965,39204,35964,39205,39213,39215,35761,39205,38057,39205, 15,39204, + 1011,39223, 11,39205, 1011,39205, 11,39204, 1275,38305, 483,38305, +35895,39234, 4787,39234,15879,39234,21405,38305, 1011,39243, 483,39243, + 7535,38305, 15,39249, 7537,39251, 7541,39251, 7545,39251,28337,38305, +21605,39259,28351,39261,28355,39261,28359,39261, 6147,38305, 483,39269, +15269,38305, 483,39273,17423,38305, 1011,39277, 483,39277, 4827,38305, + 483,39283, 4745,38305, 1011,39287, 483,39287,17232,38305,30492,38305, +25793,39295, 265,39294, 4569,38305, 483,39301,14625,38305, 483,39305, + 7063,38305, 483,39309,37284,38305,37356,38305,17233,38305,30493,38305, + 483,39319,37973,38305,37759,38305,38002,38305,38327,39327,37760,38305, + 483,39331,37976,38305,38321,39335,37617,38305,38398,39339,38319,39339, +38400,39339,38335,39339,37663,39339,38397,39348,37671,39349,38397,39339, +37663,39354, 483,39354,36773,39338, 483,39361, 483,39339,38397,39364, +37663,39338, 483,39369,37899,38305,38392,39373,38321,39373,38394,39373, +38333,39373,35187,39372,37885,39383,37933,39373,38391,39386,38391,39373, +37933,39390, 483,39390,36773,39372,37933,39397, 483,39397, 483,39373, +38391,39402,38185,38305,38150,39407,38137,39407,37145,39410,37202,39407, +37885,39407, 483,39407,37145,39418,37145,39407,38137,39422, 483,39422, +37979,38305,38451,39429,37663,38305,37409,39432, 3,39435, 7,39433, +39437,39439, 2,39439,39435,39443, 483,39433,37617,39447,37241,39432, +37617,39432, 483,39453,37933,38305,36773,39456,37977,38305,38315,39461, +37815,38305, 483,39465,38003,38305,38317,39469,38127,38305, 483,39473, + 482,38304, 5,39477, 6,39478, 6,39477, 5,39482, 14,39477, + 586,38304,39122,39489,39128,39489,39127,39489,38863,39489,38601,39489, +38948,39489,38603,39489,39150,39489,39144,39489,38783,39489,38785,39489, + 3,39489, 1,39512,38971,39515,39161,39515, 1,39489, 3,39520, +38971,39523,39161,39523,39175,39489,38987,39489,21604,39489,39161,39533, +38971,39533,39146,39489, 483,39538,39142,39489,35187,39542,38943,39489, + 483,39546,35728,39489,39085,39550,22807,39489,39085,39554,26219,39489, + 8647,39489,19396,39489,39085,39489,22807,39564,35728,39564,35187,39564, + 483,39570, 483,39564,35187,39574,35895,39489, 9,39489,18967,39580, +18967,39489, 9,39584,35187,39489,39142,39588,39085,39588, 483,39592, + 483,39588,39085,39596, 483,39489,38943,39600,39146,39600,39085,39600, +35187,39606,35187,39600,39085,39610, 4787,39489,15879,39489, 1368,38304, + 3867,39619, 8277,39619, 3997,39619, 4067,39619, 9459,39619, 8953,39619, + 1274,38304,27979,39633,14625,39633, 4569,39633,16381,39633,13325,39633, +26293,39633, 8685,39633,35843,39633, 1369,39633,19513,39633, 3863,39633, +37019,39633, 9955,39633,37377,39633, 8401,39633,10273,39633,20697,39633, + 4137,39633,20219,39633, 4063,39633,35895,38305, 483,39674,35915,38305, + 3,39678, 2,39678, 842,39678, 843,39679,39685,39687, 842,39679, + 843,39678,39691,39693, 2,39679,39681,39697, 3,39679,39683,39701, + 482,38305,39616,39705,39614,39705,39578,39705,35718,39705,35895,39705, +39489,39714,39489,39705,15879,39718, 4787,39718,35895,39718,15879,39705, +39489,39726, 4787,39705,39489,39730,35187,39705, 587,39734, 587,39735, +39489,39739, 587,39705,35187,39742, 1368,38305, 587,38304,39241,39749, +39239,39749,39237,39749,38599,39749,38597,39749,38633,39749,38631,39749, +39677,39749,38801,39749,38805,39749,38679,39749, 483,39771,39235,39749, +15879,39775, 4787,39775,35895,39775, 483,39748,38679,39783, 483,38304, +38121,39787,38219,39787,38253,39787,37899,39786,38731,39795,37617,39786, +38713,39799,38011,39787,38185,39787,37145,39805,14625,39787, 4569,39787, +19396,39787,35931,39787,39489,39815,15269,39787, 4827,39787, 587,39786, +38679,39823,37899,39787,38391,39827,37617,39787,38397,39831,17423,39787, + 4745,39787, 9,39787,18967,39838,18967,39787, 9,39842, 587,39787, +39588,39847,39489,39847,35187,39850,35187,39847,39489,39854,35187,39787, + 586,39858,39823,39861, 586,39859,39847,39865, 586,38305,39713,39869, +38861,39869,39737,39869,39745,39869,38675,39869,35187,39879,39823,39869, +35187,39883,39783,39869,35187,39887, 1108,39869, 295,39869,35927,39869, +37611,39869,38155,39869,35719,39869,39705,39901,39749,39869,22807,39905, +35728,39905,35187,39905, 483,39910, 483,39905,35187,39914,35187,39868, +39823,39919,39783,39919,38675,39919,39749,39919, 483,39927, 1011,39869, + 9,39930, 9,39869, 1011,39934, 1369,38304, 1275,39938, 1275,38304, +39429,39943,23023,39943,22605,39943,25483,39943,22677,39943, 1369,39942, + 803,38305,17455,39956,13737,39957,39705,39961, 1505,38305,21605,39965, + 713,39967, 305,39967, 1489,39967, 1509,39967, 25,39967,15705,38305, + 767,39979,39705,39981,17455,38305, 15,39985, 9513,39987,16859,39987, +17469,39987, 803,39984, 154,38305, 165,39997, 374,38305, 11,40001, + 66,38305, 340,38305,30091,40006,27978,38305,39633,40011,23755,40011, +27805,40011,26331,40011,25793,40011, 8495,40011, 511,38305, 11,40025, + 935,38305, 483,40029, 1109,38305, 11,40033, 295,38305, 256,38305, + 375,40039, 9805,40039,20762,38305, 1141,40045, 1447,40045, 33,40045, + 88,38305,11251,40053, 5177,40053, 136,38305,36727,40059,37895,40059, +36079,40059, 144,38305, 113,40067, 341,38305, 113,40071,16937,40071, +27979,38305,38411,40077, 483,40077,39943,40077, 9565,40077, 113,38305, + 4727,40087, 9,40089,37662,38305,37241,40093,37932,38305,36773,40097, +37782,38305,37978,38305,39633,40103,38389,40103, 305,38305,16833,40109, + 25,38305,16833,40113,20501,38305, 1011,40117, 1347,40117, 253,38305, +16937,40123, 53,38305,16937,40127, 251,38305, 21,38305,38004,38305, + 7,40135,37241,38305, 6,40138, 2,40141,35187,40142,35187,40141, + 2,40146, 2,40147,38056,40141,37663,40138, 3,40138,40145,40157, +40149,40157,40153,40157, 3,40139,40151,40165,40093,40165,36773,38305, +37933,40171,37899,40173,37933,40170,35931,40170, 483,40179,37617,40170, + 483,40183,37899,40170,37933,40187, 483,40187,37409,40170, 3,40193, + 483,40171,35931,40197,37617,40197,37899,40197, 6,40170,37844,40205, + 3,40205,35187,40208,35187,40205, 3,40212, 7,40171,40207,40217, +40211,40217,40215,40217,40195,40217, 2,40217,40193,40227,37845,40217, +40205,40231,37845,40170, 7,40235,37325,38305, 7,40238, 2,40241, + 2,40240, 7,40239,35187,40247, 3,40249, 3,40248, 3,40247, +35187,40254, 3,40246,37844,40247, 1368,40238, 586,40239, 1369,40238, +37845,40238,40259,40269,40265,40269, 587,40239, 2,40238, 7,40276, +40251,40277, 3,40238,40243,40283,35187,40282,40275,40287, 3,40239, +40279,40291,40245,40291,40269,40291, 7,40290,40269,40299,40263,40291, + 2,40239,40287,40305,40257,40305,40253,40305,40261,40305,40267,40305, +10219,38305, 7,40316, 2,40318, 2,40319, 1368,40316, 1369,40316, + 2,40317,40327,40329, 3,40317,40321,40333,40325,40333, 2,40316, + 7,40338,40333,40341, 3,40316,40323,40345, 413,38305, 7,40349, + 375,40349, 1217,38305, 483,40355, 1216,38305, 7,40359, 412,38305, + 483,40363,36348,38305, 2,40366,36429,40369,38233,38305, 7,40373, +25296,38305, 7,40377, 265,38305,27978,40381,30492,40380, 17,40380, + 8495,40387, 6,40380, 11,40391, 7,40380,30091,40394, 7,40381, +27021,40399, 9195,40399,40391,40399,40001,40399,21605,40398, 6,40381, +40395,40411,40007,40411, 17,40411,21605,40381, 7,40418, 17,40419, + 241,40380, 483,40425,21605,40380, 7,40429,30091,40380, 7,40432, + 11,38305,18967,40436, 483,40439, 587,40436, 483,40443, 1369,40436, + 483,40437, 587,40449, 3,40436, 3,40437, 9875,40455,20501,40455, + 1011,38305, 483,40461, 587,40463, 587,40460, 483,40467, 9,40460, + 9565,40471, 7,40461, 959,40475, 759,40475, 47,40475, 903,40460, + 7,40483, 15,38305, 1369,40486, 1011,40489, 241,40486, 483,40493, + 3,40486, 165,40497, 3,40487, 253,40501, 1471,40501, 53,40501, +21605,38305,27533,40509, 15,40509,31103,40513, 1275,40509, 7,40508, +23755,40519,39633,40519,27805,40519,26331,40519,25793,40519, 8495,40519, + 7,40509,26219,40533, 305,40533, 25,40533, 713,40533, 265,40509, +31103,40543, 265,40508, 7,40547,25367,38305, 6,40551, 7,40551, + 6,40550,40555,40557, 7,40550,40553,40561, 17,38305,19917,40565, + 587,40565, 265,40564, 8495,40571, 265,40565, 8861,40575, 3,40564, + 113,40579, 3,40565,10109,40583,10108,40583,10108,40582,40585,40589, +10109,40582,40587,40593, 1141,40583, 1447,40583, 33,40583, 903,38305, + 7,40603, 1141,40605, 1447,40605, 33,40605, 1011,40602, 7,40613, +18967,38305, 1108,40617, 1072,40617, 165,40617, 1291,40617, 524,40617, + 9,40617, 1011,40628, 11,40616, 483,40633, 11,40617, 483,40636, + 483,40617, 11,40641, 1011,40640, 587,40641, 11,40640, 9,40616, + 587,40616, 483,40653, 7,40616, 1141,40657, 1447,40657, 33,40657, + 1011,40617,21183,40665, 7,40665, 483,40664, 9,40664, 241,38305, + 483,40675, 15,40674, 483,40679, 9,40675, 7,40674, 375,40685, + 9805,40685, 7,40675, 265,40691, 59,40691, 331,40691, 1325,40691, + 265,40674, 483,40701, 9,38305, 7963,40704, 7961,40707,27995,40704, +27533,40711,17573,40704,10001,40715,13755,40705, 9377,40719, 1,40704, + 3,40723, 1,40724,40705,40727, 7,40724,40729,40731, 7,40723, + 3,40734, 586,40723, 6,40704, 3,40741, 6,40742,40705,40745, + 0,40742,40747,40749, 0,40741, 3,40752,21604,40704, 3,40757, + 7,40758, 7,40757, 3,40762, 586,40757, 1274,40704, 3,40769, + 0,40770, 0,40769, 3,40774, 9377,40704,27533,40779,10001,40779, +13755,40779,10001,40705,17573,40787, 9377,40787,27533,40705,27995,40793, + 9377,40793,21605,40705,26715,40799,26865,40799,40761,40799,40765,40799, +40731,40799,40737,40799, 6,40799,26719,40799,40739,40799,40767,40799, + 587,40799,26625,40821,40723,40821,40757,40821, 1275,40705, 1991,40829, + 3621,40829,40773,40829,40777,40829, 5299,40829,40749,40829,40755,40829, + 1,40829, 4907,40829,17711,40829, 1011,40704, 9565,40851, 587,40704, +39515,40855,39523,40855, 3507,40855, 1971,40855, 0,40855,40829,40865, +40845,40855,21783,40855,23983,40855, 4625,40855,10603,40855,39533,40855, +21605,40855, 713,40881,39489,40881,18967,40704, 1011,40705,18967,40889, + 9617,40889, 2,40704,36727,40895,37895,40895,36079,40895, 3,40704, +11251,40903, 5177,40903, 2,40705,36729,40909, 3,40705,11355,40913, +30748,38305, 7,40916,17125,38305, 7,40920,30091,38305, 340,40924, + 7,40924,25793,40929, 265,40928, 1011,40925, 7,40935, 265,40925, + 7,40939, 265,40924, 7,40942,14315,38305,31103,40947, 375,40947, + 7,40947, 8495,40953,37845,38305,37897,40957, 1275,40957,36945,40956, + 6,40957, 7,40957, 6,40956,40967,40969,36773,40969, 7,40956, +38389,40975,39633,40975,40965,40975,36773,40956, 7,40983,37409,38305, +37285,40986, 113,40987, 2,40987,39313,40993,40157,40993, 3,40987, +39439,40999,40217,40999, 2,40986,38305,41005, 7,41007,40999,41009, +40165,41005,37241,41005, 3,40986, 3,38304,40375,41019,40237,41019, +40985,41019,40137,41019,40963,41019,39015,41019,38749,41019,40098,41019, +39323,41019,40972,41019,40989,41019,39009,41019,38751,41019,40094,41019, +39325,41019,41014,41019,15567,41019,12971,41019,13355,41019,13541,41019, +21049,41019,21242,41019,39127,41019,39714,41019,39739,41019,38603,41019, +38601,41019,38863,41019,39726,41019,39730,41019,20956,41019,20773,41019, +38783,41019,38785,41019,11970,41019,19441,41019,19656,41019, 4696,41019, + 5,41019, 6,41097,27169,41019,27168,41019,33465,41019,40011,41019, +30492,41019,40519,41019,39295,41019,30493,41019,40929,41019, 357,41019, + 367,41019, 471,41019, 1249,41019, 628,41019,20057,41019, 4569,41019, +14625,41019, 4545,41019,36203,41019,36343,41019,40953,41019,21183,41019, +20103,41142,13325,41019, 8337,41147, 4549,41019, 9357,41019, 9356,41019, +40966,41019,36026,41019,37558,41019,36226,41019,36944,41019, 8386,41019, +20186,41019, 9083,41019, 9484,41019,36027,41019,37559,41019,36227,41019, +36945,41019, 8387,41019,20187,41019,19513,41019,35843,41019,20219,41019, + 8401,41019,37019,41019,20697,41019, 4137,41019, 9955,41019, 3863,41019, + 4063,41019,37377,41019,10273,41019,21405,41019,20606,41019, 9984,41019, +37215,41019,40969,41019,36773,41218,40975,41019,40097,41019,36773,41224, +40103,41019,37979,41019,19396,41019,11131,41019,21059,41019, 9082,41019, +28205,41019,25551,41019,24613,41019,20326,41019,21087,41019,39705,41019, +35895,41250,15879,41250, 4787,41250,11949,41019, 9,41258, 4669,41019, + 9,41262,15879,41019,39705,41266, 4787,41019,39705,41270,20805,41019, +37501,41019,19631,41019, 9,41278,35895,41019,39705,41282, 9704,41019, +40387,41019,38939,41019,40033,41019,40571,41019,20804,41019, 341,41019, + 241,41299,27979,41019, 241,41303, 9377,41019, 11,41306, 256,41019, +35187,41310, 257,41019,35187,41315,20763,41019, 11,41318, 4745,41019, +17423,41019, 587,41019, 11,41326,37409,41326,37500,41019, 9875,41019, + 10,41334, 10,41335, 11,41334,41339,41341, 11,41335,41337,41345, + 1471,41019,37325,41019, 587,41351,37241,41019,40093,41354,41005,41354, +37408,41019, 241,41360,41005,41019,37241,41364,40093,41019,37241,41368, +20885,41019,20413,41372, 1369,41019,37409,41377,37409,41019, 241,41381, + 587,41380,40967,41019, 9195,41019, 11,41388,20413,41019,20885,41392, +10219,41019, 587,41397,20501,41019, 10,41400, 10,41401, 11,41400, +41405,41407, 11,41401,41403,41411, 253,41019, 6,41019,40373,41417, +40135,41417,40235,41417,40983,41417,40967,41417,27021,41417,40533,41417, +30091,41417, 4713,41417,16363,41417, 4863,41417,13119,41417,26415,41417, + 8757,41417,23493,41417,27377,41417, 4213,41417, 9195,41417,39489,41417, + 9335,41417, 4147,41417, 3933,41417, 8109,41417,36212,41417,36773,41417, +20103,41417, 8337,41417,37145,41417, 8997,41417,40957,41417, 241,41417, +35187,41478,18967,41417, 11,41483,35187,41417, 241,41486, 587,41487, + 587,41417, 8387,41417,20187,41417,14653,41417,36945,41417, 7,41019, +30091,41502,26331,41503, 8717,41503,23755,41503,27805,41503, 3785,41503, +40957,41502,36212,41502,39633,41503,10055,41503, 4329,41503, 4311,41503, +10351,41503,36773,41502,20103,41502, 8337,41502, 8997,41502, 1275,41503, + 15,41503,18967,41541,35187,41502, 241,41544, 241,41502,35187,41548, +27021,41019, 11,41552, 53,41019, 6,41018,41165,41559,41531,41559, +41517,41559,41157,41559,40975,41559,40103,41559,41537,41559,41169,41559, +41167,41559,41239,41559,41533,41559,41535,41559,40011,41559,27979,41559, +40519,41559,41549,41559,41311,41559,16381,41559,13325,41559,26293,41559, + 8685,41559,41361,41559,41545,41559,41503,41559,36773,41607,40957,41607, + 8997,41607,20103,41607, 8337,41607, 241,41607,35187,41607, 1369,41559, + 4569,41559,35843,41559,19513,41559, 3863,41559, 9955,41559, 4063,41559, +37377,41559,10273,41559,20697,41559, 4137,41559,37019,41559,20219,41559, + 8401,41559,14625,41559, 7,41018,41181,41653,41466,41653,41387,41653, +41476,41653,41474,41653,41185,41653,41183,41653,41171,41653,41468,41653, +41470,41653, 8997,41653,41417,41674,41315,41653,41478,41653,26219,41653, + 8647,41653,41381,41653,41486,41653,19396,41653,41417,41653,36773,41692, +40957,41692, 8997,41692,20103,41692, 8337,41692, 241,41692,35187,41692, +20103,41653,41417,41708, 8337,41653,41417,41712,36773,41653,41417,41716, + 483,41653, 9,41653,18967,41722, 241,41653, 1,41727,41417,41729, +41417,41726,18967,41653, 9,41734,40957,41653,41417,41738,35187,41653, +41417,41742, 11,41019,27021,41746, 587,41746, 9195,41746,20501,41746, + 9377,41746, 9875,41746,20763,41746, 9,41019, 4669,41762,11949,41762, +19631,41762,18967,41762,20273,41762, 9617,41762, 17,41019,20762,41776, +20762,41777,20763,41776,41781,41783,20763,41777,41779,41787,40957,41019, + 6,41790, 7,41790,41559,41795, 6,41791,41795,41799, 7,41791, +41793,41803,41417,41803, 9617,41019, 9,41808,36212,41019, 7,41812, +35187,41019, 256,41816, 7,41816, 241,41820,41559,41821, 7,41817, +41417,41827, 241,41816, 7,41830, 241,41019, 1,41835, 7,41837, +41559,41839, 7,41836,41417,41843,37408,41834, 7,41835, 1,41848, +41417,41851,41417,41849, 7,41834,41559,41857,35187,41856,35187,41834, + 7,41862,18967,41019, 483,41867, 9,41866,30091,41019, 7,41872, +14315,41019, 8997,41019, 7,41878,41559,41881, 7,41879,41417,41885, +20273,41019, 9,41888, 8337,41019, 7,41892,41559,41895, 9,41893, + 483,41893, 7,41893,41417,41903,20103,41019,21183,41906, 7,41906, +41559,41911, 9,41907, 483,41907, 7,41907,41417,41919,36773,41019, +40097,41922,40969,41922, 7,41922,41559,41929, 9,41923, 483,41923, + 7,41923,41417,41937, 2,38304,38595,41941,40177,41941,39459,41941, +38591,41941,38593,41941,40155,41941,39451,41941,38589,41941,39237,41941, +39241,41941,39239,41941,38599,41941,38597,41941,38633,41941,38631,41941, +26777,41941, 9741,41941,26781,41941, 9745,41941,39677,41941,38801,41941, +38805,41941, 5,41941, 6,41986,38881,41989, 9771,41941, 14,41941, +38881,41995,38897,41941,30349,41941,26857,41941,26933,41941, 9777,41941, +40077,41941,31598,41941,35931,41941,37519,41941,35690,41941,40651,41941, +38955,41941,40887,41941,39235,41941,35895,42025,15879,42025, 4787,42025, + 8982,41941, 668,41941,26625,42035, 9731,42035, 1419,41941, 9731,42041, +26625,42041,40471,41941,38931,41941,40037,41941,40851,41941,37617,41941, +37899,41941,39457,41941,36773,42059,39429,41941,27021,41941, 375,41941, +35187,42066,31103,41941,26625,42070, 9195,41941, 483,41941,39433,41941, +37241,42079, 587,41941, 1,42083,35187,42083, 9,42082, 9731,42089, +26625,42089, 6,41941, 2,42095,21605,42097,38305,42099, 5,42094, +38881,42103,42101,42103, 2,42094,38305,42109, 7,41940, 9459,42113, + 8953,42113, 3997,42113, 4067,42113, 8277,42113, 3867,42113, 9,41941, + 587,42126, 9731,42129,26625,42129, 17,41941, 8861,42134,26625,41941, +31103,42138, 8861,41941, 7,42143, 17,42142,35187,41941, 375,42148, + 9731,41941, 7,38304,39023,42155,41231,42155,25445,42155, 1,42155, + 2,42162, 3,42162,38903,42167,38971,42167,39161,42167,40855,42167, +18967,42167, 2,42163, 3,42163, 5,42155, 2,42182, 3,42182, + 2,42183,42187,42189, 3,42183,42185,42193,21604,42155,18967,42197, +39161,42197,38971,42197,38903,42197,40855,42197,39175,42155,38987,42155, +40881,42155,38925,42155,22779,42155,22243,42155,28063,42155,41303,42155, +31598,42155,25299,42155, 357,42155, 367,42155, 471,42155, 1249,42155, +35690,42155,37519,42155, 272,42155, 1476,42155, 280,42155, 949,42155, + 1517,42155,40387,42155,40571,42155,40033,42155,38939,42155,21087,42155, +20326,42155, 9704,42155, 9304,42155,35931,42155,40998,42155, 253,42155, + 265,42270, 375,42155,35187,42274,31103,42155,26625,42278,25381,42155, +10081,42283,41417,42155, 1369,42287,26625,42155,31103,42290, 9617,42155, + 9,42294, 53,42155, 265,42298,20273,42155, 9,42302,37899,42155, +37617,42155, 1471,42155, 265,42310, 587,42155,35187,42315,38233,42155, +38004,42155,36773,42155,37845,42322,38056,42155,39019,42327,37145,42327, +37844,42155,40305,42333,37933,42155, 483,42155,37845,42155,36773,42340, +40999,42155, 305,42155,21605,42347, 713,42155, 9195,42350,21605,42351, + 9195,42155, 713,42356, 2,42155, 1,42360, 8229,42361,40987,42361, +35187,42361,36773,42369,35187,42360,39019,42373,37145,42373, 3,42155, +42179,42379, 1,42379, 7,42379, 15,42385,38305,42387, 1,42378, +38903,42391,38971,42391,39161,42391,40855,42391,18967,42391,42389,42391, + 7,42378,40704,42405,42391,42407, 9,42405,38305,42410,42391,42413, +38305,42405, 9,42416,42391,42419,40987,42378, 1369,42379,35187,42378, +40305,42427, 25,42155,21605,42431, 2,42154, 1,42435,42379,42436, +42382,42435,42423,42435,42269,42435,42333,42435,42427,42435,42379,42435, + 1,42450,40987,42451,35187,42451, 3997,42435, 4067,42435, 9459,42435, + 8953,42435, 8277,42435, 3867,42435, 3,42154,42165,42471,42363,42471, +42345,42471,42366,42471,26219,42471, 8647,42471,42341,42471,42368,42471, +19396,42471,42361,42471, 1,42491,40987,42490,35187,42490,41417,42471, + 483,42471,18967,42471, 9,42502, 9,42471,18967,42506,40987,42471, +42361,42510,35187,42471,42361,42514,32805,42155, 265,42155, 253,42520, + 1471,42520, 53,42520,40987,42155, 3,42528,42435,42531, 3,42529, +42361,42535,35187,42155, 7,42539,38305,42541, 2,42543, 2,42542, + 2,42541,38305,42548, 2,42540, 1368,42539, 375,42538, 1369,42539, + 2,42538,39019,42561,38305,42560,42559,42565,37145,42561, 3,42538, +40305,42571,42545,42571,42435,42571, 3,42539,40277,42579,39315,42579, + 7,42579,38305,42585,42561,42587,42551,42579,42547,42579,42561,42579, +42361,42579, 2,42539, 7,42598,42571,42599,37845,42599, 9,42155, +20273,42606, 9617,42606, 6,38304,40509,42613,31103,42615,21604,42613, +40471,42613,40851,42613,40037,42613,38931,42613, 8982,42613,27979,42613, + 483,42631,41941,42631,40957,42613,37933,42637,41503,42613, 483,42641, + 8861,42613, 17,42644,17423,42613, 1011,42649, 4745,42613, 1011,42653, + 9875,42613, 1011,42657, 1471,42613,36773,42613, 483,42663,37844,42613, +40305,42667,37979,42613,41941,42671, 1369,42613,38057,42675, 331,42613, + 17,42678, 1325,42613, 17,42682, 334,42613, 1328,42613, 8337,42613, + 483,42691,20103,42613, 483,42695, 53,42613, 393,42613, 1359,42613, + 3,42613, 483,42705,35187,42704,40305,42709,10257,42705,37357,42705, + 2,42613, 62,42613, 59,42613, 17,42720,20501,42613, 1011,42725, + 253,42613, 3,42612,40975,42731,40103,42731,27979,42731,40519,42731, +40011,42731,16381,42731,13325,42731,26293,42731, 8685,42731,41503,42731, + 1369,42731, 4569,42731,35843,42731,19513,42731, 3863,42731, 9955,42731, +20697,42731, 4137,42731,37019,42731, 8401,42731,20219,42731, 4063,42731, +14625,42731,37377,42731,10273,42731,18967,42613, 165,42783, 241,42613, +35187,42613, 3,42788,40305,42791, 3,42789,40277,42795,39315,42795, + 17,42613, 8861,42800, 331,42800, 1325,42800, 59,42800, 7,38305, +25004,42810,25005,42810,25184,42810,25185,42810, 264,42811, 5,42811, + 0,42822, 3,42822, 1,42810, 4,42829,25004,42811,42815,42833, +25184,42811,42819,42837,25005,42811,42813,42841,25185,42811,42817,42845, +41493,42811,41622,42811,25367,42810,30748,42810,39650,42811,42752,42811, +38673,42811,38675,42811,39823,42811,39783,42811,27533,42811,26625,42869, + 331,42811,35187,42873,41559,42811, 1369,42876, 767,42811,18967,42881, +41019,42811,37899,42885,37617,42885,35931,42885,27021,42885,30091,42885, + 9195,42885,25793,42811,30091,42899,27021,42899,37845,42811,42667,42905, + 59,42811,35187,42909, 1325,42811,35187,42913,37897,42811,17125,42810, +30091,42810,25793,42921,41019,42921, 265,42920, 1369,42811,30091,42929, +41559,42928,20103,42929, 8337,42929,36773,42929,42731,42928,39633,42928, +42707,42811,42704,42811, 483,42947,39633,42811, 1369,42950,39749,42811, + 483,42955, 1275,42811, 265,42810,40411,42961,30091,42960,21605,42810, +26331,42967,25793,42967,23755,42967,27805,42967,39633,42967,42731,42967, +41559,42967,41019,42967, 8495,42967,42731,42811, 1369,42986, 241,42810, + 375,42991, 9805,42991,18967,42810, 1141,42997, 33,42997, 1447,42997, + 265,42811,35187,43005, 9377,43005, 9533,43005,37145,43005,21605,42811, +34311,43015,42619,43015,26625,43015,24545,43015, 9731,43015, 2,42810, + 3,42810, 0,43028,43005,43031, 295,43029, 1108,43029,35927,43029, +38155,43029,37611,43029, 9,43029, 1011,43044, 1011,43029, 9,43048, + 2,42811,42831,43053, 5,43053,42829,43057,36256,43053, 9,43053, +35187,43062,35187,43053, 9,43066, 3,42811, 5,43070,22807,43071, +37663,43071,42613,43070, 483,43079, 241,43071, 9,43083,37845,42810, +41559,43087,38389,43087,42731,43087,39633,43087,41019,43087,42613,42811, +32805,43099,37845,43098,37845,43099,37844,43098,43105,43107,37844,43099, +43103,43111, 3,43099, 1369,43115, 3,43098, 483,43119, 15,42811, +20273,43123, 9617,43123,35187,42810, 7,43129, 2,43130, 2,43131, +38305,43129, 3,43136,43135,43139, 3,43137,43133,43143, 1368,43129, +43143,43147, 59,43129, 1325,43129, 331,43129, 265,43129, 2,43129, + 7,43158,43143,43161, 3,43129,38305,43164,43135,43167,37408,38305, + 7,43171, 2,43172,40999,43175, 2,43173,40101,43179,41017,43179, + 1368,43171,40999,43185, 59,43171, 1325,43171, 331,43171, 265,43171, + 2,43170,37783,43197, 2,43171, 7,43200,40999,43203,37617,43201, + 3,43171,38305,43208,43179,43211, 3,38305,43129,43214,43135,43217, + 1,43214, 1011,43221,42041,43221, 1418,43221,41941,43227,42035,43221, + 669,43221,41941,43233,42089,43221,42129,43221, 1369,43221, 15,43240, +41941,43243, 15,43221, 1369,43246,41941,43249,11989,43215, 9,43253, +13737,43215, 9,43257,37357,43215,10257,43215,38118,43215,38132,43215, +37544,43215,37409,43215, 483,43270, 113,43215, 587,43275,37345,43215, +37241,43214,40993,43281,40993,43215,37241,43285, 9,43215,38057,43288, + 483,43215,38057,43292,37409,43292,10289,43215, 15,43214, 165,43301, + 11,43214, 9,43214,11251,43307, 5177,43307, 17,43214, 113,43313, + 11,43215, 165,43215, 7,43214, 0,43321, 4,43322, 4,43321, + 0,43326,35186,43321, 295,43321, 1108,43321,35927,43321,38155,43321, +37611,43321, 9,43321, 1011,43342, 1011,43321, 9,43346, 7,43215, +21604,43351, 1,43351, 3,43354, 3,43351, 1,43358, 15,43351, +38305,43363,43353,43365,43357,43365,43361,43365, 1011,43363,37409,43214, +43179,43375,41941,43215,37408,43379, 7,43379,35187,43382,35187,43379, + 6,43386, 7,43386, 6,43387,43391,43393, 7,43387,43389,43397, + 1011,43215,37408,43401, 7,43401,35187,43404,35187,43401, 7,43408, +38057,43215,40097,43413,40969,43413, 7,43413, 9,43412, 483,43412, +35187,43214,40305,43425,40275,43425,38305,43425, 6,43430,43413,43433, + 6,43425,38305,43436,43413,43439,41941,43425, 6,43443, 7,43443, + 6,43442,43447,43449, 7,43442,43445,43453, 1011,43425, 7,43457, +37844,38305,42336,43461,42917,43461,42905,43461,39013,43461,40305,43461, +40275,43461,37933,43461,42155,43474,42155,43461,37933,43478, 6,43460, +41941,43461, 6,43485, 7,43485, 6,43484,43489,43491, 7,43484, +43487,43495, 1011,43461, 7,43499, 2,38305,41603,43503,41686,43503, +41825,43503,41828,43503,42541,43502,42579,43513,16936,43503,36400,43503, +36439,43519,36348,43503, 6,43523,36413,43525, 6,43522,36439,43529, +36439,43523,41744,43503,41688,43503,41605,43503,41706,43503,41620,43503, + 1,43503, 1275,43544, 4,43544, 7,43544,41417,43551, 7,43545, +39633,43555,41559,43555,42731,43555,41019,43555, 1,43502,41692,43565, +41607,43565,41653,43565,41417,43570,41417,43565,41653,43574,41502,43565, +41559,43579,41019,43565, 7,43582,41559,43585, 7,43583,41417,43589, + 7,43565,41019,43593,41653,43595,41019,43592,41559,43599, 5,43502, +21605,43603,42810,43604,42811,43605,43607,43609,42811,43604,42810,43605, +43613,43615,41692,43503,35187,43618,41607,43503,35187,43622,41360,43503, +41559,43627,41820,43503,41559,43631,41544,43503,41559,43635,35760,43503, + 8315,43503,37408,43502,37783,43643,42538,43503,42601,43647,42553,43647, +42555,43647,41742,43503,41417,43654,41486,43503,41653,43658,41417,43503, +41827,43662,41742,43662,41653,43662,35187,43668,35187,43662,41653,43672, +37783,43503,37325,43502,42795,43679,42579,43679,41502,43503,41559,43685, +35187,43687,35187,43684,41559,43691,37241,43503,37409,43695,41019,43697, +41381,43503,41653,43700, 1275,43503, 1,43704,35187,43704, 9,43705, + 9731,43711,43221,43711,43549,43711,26625,43711, 587,43503,42811,43721, +35895,43723,15879,43723, 4787,43723,41653,43503, 1,43731,41417,43733, +41381,43730,41486,43730,41417,43730,35187,43740,35187,43730,41417,43744, + 9,43502,36727,43749,36079,43749,37895,43749,41827,43503,41417,43756, + 6,43502,39616,43761,39614,43761,39578,43761,39901,43761,41282,43761, +41266,43761,41270,43761,39961,43761,39981,43761,35718,43761,39869,43781, +41019,43761,35895,43784,15879,43784, 4787,43784,15879,43761,39489,43792, +41019,43792, 4787,43761,39489,43798,41019,43798,35895,43761,39489,43804, +41019,43804, 587,43761,35187,43810,39869,43813,35187,43761, 587,43816, +39869,43819, 587,43817,39489,43823,41019,43823,39489,43761,15879,43828, + 4787,43828,35895,43828, 7,43502, 6,43503,36348,43838,36439,43841, +36348,43839,36429,43845, 7,43503,41817,43848,43817,43849,41019,43853, + 4,43849, 0,43856,43784,43859,41019,43859,43761,43862,43761,43859, +41019,43866, 0,43849, 4,43870,43784,43873,41019,43873,43761,43876, +43761,43873,41019,43880, 1,43848,41417,43885,35186,43849,43784,43889, +41019,43889,43761,43892,43761,43889,41019,43896,41816,43848,41559,43901, +41019,43848,41559,43905,35187,43907,35187,43904,41559,43911,41019,43849, +41827,43915,43851,43915,41742,43915,41653,43915,35187,43922,35187,43915, +41653,43926,35187,43848,41417,43931,41019,43930,41559,43935,41019,43931, +41653,43939,37409,43502,41354,43943,40165,43943,41019,43943,37241,43948, +37241,43943,41019,43952,37408,43503,41417,43957,37663,43957,41019,43956, +41559,43963,41019,43957,41653,43967,41816,43503, 6,43970, 7,43970, +41559,43975, 6,43971,43975,43979, 7,43971,43973,43983,41417,43983, +41019,43503, 1,43989, 7,43990,41417,43993, 7,43991,41559,43997, +37408,43988,41559,44001,37408,43989,41381,44005, 7,43989,41381,44009, +41486,44009, 1,44008,41417,44015,41417,44009,35187,44018,35187,44009, +41417,44022, 7,43988,41559,44027,35187,44029,35187,44026,41559,44033, +35187,43988, 6,44036, 7,44036,41559,44041, 6,44037,44041,44045, + 7,44037,44039,44049,41417,44049,21605,43503, 7,44055, 265,44057, +35187,43503,41692,44060,41607,44060,41502,44060,41559,44067, 1275,44060, +41653,44060,41417,44072,36945,44061,41019,44077,41417,44060,41653,44080, + 6,44061,41922,44085,43413,44085,41019,44085,36773,44090,36773,44085, +41019,44094, 7,44061,41559,44099,42731,44099,39633,44099,41019,44099, + 6,44060,44099,44109, 7,44060,41417,44113,41019,44112,41559,44117, +44085,44113,41019,44113,41653,44123,41019,44060, 6,44126, 7,44126, +41559,44131, 6,44127,44131,44135, 7,44127,44129,44139,41417,44139, +36773,44061,41417,44145, 7,44145,41019,44149,35187,43502,41217,44153, +41472,44153,29229,44153,41099,44153,36429,44153,42559,44153,41417,44153, +37145,44166,37783,44153,37214,44153,41019,44173, 7,44153,41019,44177, +37145,44179,37145,44176,41019,44183,37145,44153,41417,44186, 7,44186, +41019,44191,38056,38305,41472,44195,41217,44195,41099,44195,29229,44195, +36429,44195,42559,44195,35187,44195, 6,44209,43413,44211,41417,44195, +37145,44214,37783,44195,37214,44195,41019,44221, 7,44195,41019,44225, +37145,44227,37145,44224,41019,44231,37145,44195,41417,44234, 7,44234, +41019,44239, 6,38305,42453,44243,42493,44243,42472,44243,42439,44243, +42474,44243,42441,44243,42363,44243,42471,44256,42381,44243,42165,44243, +42471,44262,42325,44243,42330,44243,42343,44243,42321,44243,42319,44243, +42371,44243,42376,44243,42568,44243,42447,44243,42484,44243,42054,44243, +42056,44243,44171,44243,43645,44243,43960,44243,44219,44243,43201,44243, +37617,44298,43206,44243,38711,44243,43199,44243,42605,44243,40231,44243, +43677,44243,40959,44243,10586,44243,10827,44243,42594,44243,42603,44243, +42577,44243,42596,44243, 6664,44243, 6243,44243, 9780,44242, 566,44242, + 566,44243, 567,44242,44337,44339,43517,44243, 9781,44242,42012,44243, +36303,44242,36303,44243,26970,44242,26971,44242,43639,44243, 4593,44243, + 6625,44358, 3113,44243, 3023,44243, 4736,44243, 6653,44243,42518,44243, + 3251,44243,42516,44243,42486,44243,42449,44243,42496,44243,42456,44243, +19257,44243,19243,44243,43425,44242,43413,44389,40511,44243,17452,44243, +42085,44243,43707,44243,42087,44243,40961,44243,43709,44243,44071,44243, +36099,44243,36098,44242,44409,44411,36099,44242,36098,44243,44415,44417, +43605,44243,43222,44242,43223,44243,44423,44425,43222,44243,43223,44242, +44429,44431,42199,44243,24081,44243,42181,44243,42383,44243,42435,44441, +42401,44243,42177,44243,43547,44243, 5,44242,42283,44451,25380,44451, +42155,44455, 1369,44451,21605,44458,42155,44461,21605,44451, 1369,44464, +42155,44467,42373,44243,37145,44470,42561,44243,37145,44474,42579,44474, +42327,44243,37145,44480,27514,44243,42490,44243,35187,44486,42451,44243, +35187,44490, 413,44243,32805,44243,42155,44496,28547,44243,42064,44243, +42138,44243,40517,44243,40543,44243,30294,44243,38004,44243,43461,44513, +38232,44243,42155,44517,38005,44243,42155,44521,30749,44243, 9780,44243, +44345,44527,26970,44243,44355,44531, 6625,44243, 4593,44534, 33,44535, + 9781,44243,44333,44541,25005,44243,26971,44243,44353,44547,25185,44243, +25589,44243,42074,44243,42152,44243,10831,44243, 77,44243, 120,44243, + 506,44243,38041,44243, 5101,44243,16989,44243,10511,44243, 4931,44243, + 5267,44243,16981,44243,13017,44243,12705,44243,13673,44243,18391,44243, +18617,44243,14599,44243, 9366,44243,36302,44243,18217,44243,42332,44243, +42435,44599,42570,44243,42435,44603,42426,44243,42435,44607,41539,44243, +41720,44243, 9132,44243, 1216,44243,36302,44242, 3,44618,44351,44621, +30748,44243,30748,44242,44525,44627,30749,44242,44625,44631,16931,44243, +35931,44243,41941,44636,39600,44243,42500,44243,18929,44243,38669,44243, +38677,44243,17019,44243,39941,44243,39955,44243,27021,44243, 483,44656, +41941,44656,37844,44242,44351,44663,41653,44243, 483,44666,43413,44243, +43425,44671,42514,44243,42361,44674,42368,44243,42471,44678,42361,44243, +42579,44682,42514,44682,42471,44682,35187,44688,35187,44682,42471,44692, +20234,44243, 8444,44243, 567,44243,44335,44701,16937,44243, 11,44705, + 1369,44705,26625,44243,41941,44710,41941,44243,37899,44714,37617,44714, +35931,44714,27021,44714,26625,44714, 9195,44714, 9731,44714,43957,44243, +37663,44730,20103,44243, 483,44734, 8337,44243, 483,44738, 9533,44243, + 4727,44243, 25,44744,10527,44243, 25,44748, 4541,44243,38128,44243, +38057,44243,42155,44757,37145,44759,37145,44756,42155,44763, 587,44756, +37845,44243,43461,44769,36773,44771,36773,44768,43461,44775, 25,44243, +10527,44778, 4727,44778, 113,44778, 9195,44243,41941,44786, 483,44786, +37782,44243,43197,44793,43643,44793,38709,44793,17451,44243, 1011,44800, +35688,44243,36910,44243,36923,44243,37899,44243,41941,44810,37617,44243, +41941,44814,43201,44814, 9731,44243,41941,44820, 8997,44243, 483,44824, + 66,44243, 33,44829, 483,44243,27021,44832,30091,44832, 241,44832, + 9195,44832,41653,44832, 8997,44832,42471,44832,39489,44832,20103,44832, + 8337,44832,36773,44832, 903,44243, 1011,44856,18967,44243, 567,44861, + 566,44860,44863,44865, 566,44861, 567,44860,44869,44871, 241,44243, + 483,44874,42425,44243,42378,44243,42435,44881,35187,44883,35187,44880, +42435,44887, 1369,44881,36773,44243,37845,44892,43461,44895, 483,44892, +37845,44893,41019,44901,37145,44243,42327,44904,42373,44904,42561,44904, +38057,44904,42155,44913,42341,44243,42471,44916,30091,44243, 483,44920, + 113,44243, 25,44924,35187,44924,17125,44243,37663,44243,43957,44932, +39489,44243, 483,44936,39943,44243, 1369,44941, 587,44243,43215,44945, +35895,44947,15879,44947, 4787,44947,38057,44944, 8449,44243,20237,44243, + 265,44242,40399,44961, 11,44961,42471,44243,42165,44966,42363,44966, +42341,44966,42368,44966,42361,44966,35187,44976, 483,44966,35187,44966, +42361,44982,20834,44243, 1011,44243,17451,44988,35187,44988, 903,44988, +20763,44988,20763,44243, 1011,44998, 257,44243,42579,44243,42561,45004, +42361,45004, 2,44242,39616,45011,39614,45011,39578,45011,39901,45011, +41282,45011,41266,45011,41270,45011,39961,45011,39981,45011,35718,45011, +39869,45031,41019,45011,35895,45034,15879,45034, 4787,45034,15879,45011, +39489,45042,41019,45042, 4787,45011,39489,45048,41019,45048,35895,45011, +39489,45054,41019,45054, 587,45011,35187,45060,39869,45063,35187,45011, + 587,45066,39869,45069, 587,45067,39489,45073,41019,45073,39489,45011, +15879,45078, 4787,45078,35895,45078, 3,44242,36302,45087,44349,45089, +35187,45086,44351,45093, 2,44243, 14,45097, 5,45097, 6,45100, + 6,45097, 5,45104,21605,45097,38305,45109,45099,45111,45103,45111, +45107,45111,43215,45097,43325,45119,43329,45119,35895,45119,15879,45119, + 4787,45119,43331,45119,35187,45119,43321,45133,35187,45096,39313,45137, +40157,45137,43281,45137,43215,45137,37241,45145, 3,44243,42539,45148, +38305,45149,37408,45152,37408,45153,45067,45149,41019,45159, 4,45149, + 0,45163,38305,45163, 0,45162,45034,45169,41019,45169,45011,45172, +45011,45169,41019,45176,45119,45169, 0,45149,38305,45183, 4,45182, +45034,45187,41019,45187,45011,45190,45011,45187,41019,45194,45119,45187, + 0,45148,38305,45148, 1,45148,45176,45205,45194,45205,45169,45205, +45011,45210,45187,45205,45011,45214,45159,45205,45011,45205,45169,45220, +45187,45220,35186,45148,35186,45149,38305,45229, 7,45231,45220,45229, +45205,45229,45011,45236,45034,45229,41019,45229,45011,45242,45011,45229, +45205,45246,41019,45246,45119,45229, 1,45149,45165,45255,45011,45257, +45167,45255,45011,45261, 5,45149,45185,45265,45011,45267,43171,45149, +37617,45271,42538,45148,42435,45275,37409,45148,38709,45279,43197,45279, +45155,45279,43643,45279,42155,45148,42435,45289,35187,45291,35187,45288, +42435,45295, 1369,45289, 1011,45149, 483,45301, 11,45148, 33,45305, +37409,45149,45157,45309,43957,45309, 11,45149, 25,45315,35187,45315, +42155,45149,42579,45321,45151,45321,42514,45321,42471,45321,35187,45328, +35187,45321,42471,45332,45066,45149,45201,45337,45203,45337,35187,45149, +45201,45343,45011,45345,45203,45343,45011,45349,45011,45342,45201,45353, +45203,45353,45011,45149,35187,45358,45201,45361,45203,45361,35187,45148, +40217,45367,45233,45367,42155,45366,42435,45373,42155,45367,42471,45377, +37845,44242,41922,45381,43413,45381,44595,45381,44993,45381,41019,45381, +36773,45390,36773,45381,41019,45394,38056,44243,39313,45399,40157,45399, +43281,45399,43215,45399,37241,45407,37844,44243,40217,45411,42155,45410, +42435,45415,42155,45411,42471,45419,42538,44243, 3,45422,42435,45425, + 3,45423,42361,45429,42155,44243,32805,45432,37845,45432,37845,45433, +37844,45432,42435,45441,45439,45441,37844,45433,42341,45447,45437,45447, + 3,45433,42341,45453,42368,45453,42361,45453,35187,45458,35187,45453, +42361,45462, 483,45453, 3,45432,42435,45469,35187,45471,35187,45468, +42435,45475, 1369,45469,35187,45432, 3,45480,42435,45483, 3,45481, +42361,45487, 11,44243, 8861,45491, 3,45490, 33,45495, 3,45491, + 113,45499, 331,45491, 1325,45491, 59,45491,35187,44243,42490,45508, +42451,45508,38305,45508, 7,45515, 2,45517, 2,45516, 2,45515, + 7,45522, 1368,45515, 1011,45508,45381,45529,42378,45508,42435,45533, +42471,45508,42361,45536,37285,45509,41019,45541,42361,45508,42471,45544, + 113,45508, 2,45509,41354,45551,40165,45551,38305,45551, 7,45557, +41019,45551,37241,45560,37241,45551,41019,45564, 3,45509,45519,45569, + 2,45508,40157,45573,39313,45573,43281,45573,43215,45573,37241,45581, + 3,45508,40217,45585,45521,45585,45525,45585,45559,45585,45527,45585, +42155,45584,42435,45597,42155,45585,42471,45601,42155,45508, 3,45604, +42435,45607, 3,45605,42361,45611,37409,44243,43503,45615,37663,45617, + 3,45615,43201,45621, 3,45614,38709,45625,43197,45625,43643,45625, +35187,44242, 3,45632,44351,45635,35187,38305,37214,45639, 2,45641, +39019,45643,39021,45641,37286,45639,35890,45638,35891,45639,45651,45653, +35891,45638,35890,45639,45657,45659,38152,45638,38153,45639,45663,45665, +38296,45638,38297,45639,45669,45671,38153,45638,38152,45639,45675,45677, +38297,45638,38296,45639,45681,45683,37283,45639,42675,45639,37282,45639, +42674,45639,37899,45638,37885,45695,38293,45639,37885,45639,37899,45701, +44945,45639,38292,45639,44944,45639,37287,45639,38173,45638,38172,45639, +45713,45715,38303,45638,38302,45639,45719,45721,38173,45639,38172,45638, +45725,45727,38303,45639,38302,45638,45731,45733,45096,45639,45149,45639, + 7,45738,45367,45741,45097,45639,37241,45639, 2,45747, 2,45746, + 587,45746,42613,45639, 1369,45754,38271,45639, 1369,45758,44243,45639, + 2,45763, 2,45762, 587,45762, 136,45639, 137,45639, 1530,45638, + 842,45638, 669,45639, 1419,45639, 843,45639,39085,45783,45777,45783, + 1531,45639,45775,45789, 1530,45639, 843,45638, 842,45639,45795,45797, + 1531,45638,45793,45801, 1368,45639,45411,45805,40999,45805,45367,45805, +45585,45805,42613,45805,37845,45805,44243,45817, 586,45639,39847,45821, +39142,45821,39085,45821, 483,45826,37241,45821, 483,45821,39085,45832, + 586,45638,38675,45837,39823,45837,39783,45837,39749,45837, 483,45845, + 1418,45639, 668,45639, 587,45638,37885,45853,37202,45853,37145,45853, + 483,45858, 483,45853,37145,45862, 587,45639,37241,45866,44243,45866, + 9,45866, 483,45639, 587,45875,37145,45877, 1369,45639,35760,45880, +35761,45881,45883,45885,35760,45881,35761,45880,45889,45891,42613,45880, +38271,45880, 15,45880, 9,45639, 2,45900, 2,45901, 587,45900, + 265,45639, 375,45909, 15,45639, 1369,45912, 7,45639,40956,45917, +44060,45917,40957,45917,44061,45917,43502,45917,37844,45917,35187,45917, + 3,45930,43503,45930, 3,45931,45927,45937, 1369,45931,38305,45917, + 2,45942,45937,45945,37845,45942, 2,45943,45933,45951,45929,45951, + 587,45943,45149,45917,37145,45959,45227,45959,37845,45917,38305,45964, +43503,45917,35187,45968, 375,45917,45148,45917, 2,45917,40101,45977, +41017,45977,38305,45976,45937,45983,44904,45977,45569,45977,43375,45977, +39019,45977,44243,45977,37145,45994,37145,45977,44243,45998, 3,45917, +35187,46002,45951,46005,44243,46002, 3,45916,45943,46011, 7,46011, +38305,46015,45977,46017,45994,46011,45959,46011,45967,46011,45919,46011, +45949,46011,45925,46011,37241,46011,45977,46011,44243,46034,44243,46011, +45977,46038, 2,45916,45931,46043,40999,46043,45975,46043,45367,46043, +45585,46043,46009,46043,45971,46043,45921,46043,45935,46043,45923,46043, +45411,46043,42613,46043,46003,46043,44243,46069,37845,46043,44243,46073, +44243,45917, 3,46076,46043,46079, 3,46077,45977,46083, 6,45638, +45998,46087,46073,46087,45817,46087,37844,46087,46043,46095,45805,46095, +35187,46087, 3,46101,45977,46103, 3,46100,46043,46107,45805,46107, +37145,46087,45977,46112,45977,46087,37145,46116, 3,46087,35187,46120, +46043,46123,45805,46123,45917,46121,37145,46129,45917,46087,35187,46132, + 2,46135, 2,46134,38057,46132,38056,46132, 2,46133,46141,46145, + 3,46133,46139,46149,46143,46149, 2,46132,35187,46154,46149,46157, +46149,46155, 3,46132,46137,46163,46145,46163, 3,45639, 5,46169, + 6,46171, 4,46168, 0,46168, 5,46168, 1,46168,45983,46169, +45945,46169,43679,46169,45927,46169,40277,46169,45749,46169,45765,46169, +39315,46169,45905,46169,37241,46169,45977,46169,42613,46203,43848,46169, + 256,46169, 6,46169,46175,46211,46177,46211,37145,46211, 7,46169, +46179,46219,46181,46219,41019,46219,45639,46218, 2,46227,38305,46219, +46229,46231, 3,46231,46227,46235,45977,46231,43503,46218, 241,46218, +38271,46219, 7,46168,37241,46247,38057,46169,38305,46251,46211,46253, +43503,46169, 6,46256, 7,46256, 6,46257,46261,46263, 7,46257, +46259,46267, 241,46169, 7,46270, 2,45638,41472,46275,41217,46275, +46175,46275,46211,46280,46177,46275,46211,46284,46212,46275,46214,46275, +46221,46275,46223,46275,46173,46275,45930,46275,46043,46299,46045,46275, +46216,46275,46225,46275,41099,46275,46032,46275,45711,46275,46200,46275, +45745,46275,46248,46275,46245,46275,35187,46275,45917,46322,46043,46325, +45917,46323,46011,46329,45830,46275,29229,46275,45773,46275,36429,46275, +45895,46275,45897,46275,45687,46275,45693,46275,45705,46275,45707,46275, +45849,46275,45779,46275,42559,46275,45899,46275,45915,46275,45757,46275, +45761,46275,45941,46275,41417,46275,37145,46368,45821,46275,37241,46372, +46011,46275,37241,46376,46247,46275,37241,46380,45881,46275,42613,46385, +37241,46275,46011,46388,46169,46388,46247,46388,45821,46388,46211,46275, +46175,46398,46177,46398,37145,46398,37783,46275,44243,46407,45917,46275, +35187,46410,46043,46413,37214,46275,41019,46417,46218,46275,46179,46421, +46181,46421,41019,46421, 7,46275,41019,46429,37145,46431,46169,46429, +46175,46435,46177,46435,37145,46435,37145,46428,41019,46443,46169,46428, +46179,46447,46181,46447,41019,46447,37145,46275,41417,46454,46211,46454, + 7,46454,41019,46461,46169,46275,35187,46464, 6,46467, 6,46466, +38305,46465,46211,46473,38271,46464,44243,46465,38270,46464,37241,46464, + 6,46465,46477,46485, 7,46465,46471,46489,46481,46489, 6,46464, +46473,46495,35187,46494,46489,46499,46489,46495, 7,46464,46179,46505, +46181,46505,46469,46505,46485,46505,41019,46505, 2,45639,42671,46517, +39429,46517,44814,46517,44810,46517,44636,46517,37241,46516,40077,46517, +44243,46516,46003,46517,37241,46535, 9,46516,44243,46517,37617,46540, +37899,46540,35931,46540,35931,46517,44243,46548,37617,46517,44243,46552, +37899,46517,44243,46556, 7,46517,44243,46561, 7,46516,46107,46565, +46123,46565,46095,46565,40999,46565,45585,46565,45411,46565,45367,46565, +42613,46565,37845,46565,46087,46583,44243,46583,37845,46517,46211,46589, +41417,46589, 7,46589,41019,46595, 3,45638,45951,46599,45942,46599, +46011,46603,46013,46599,46066,46599,46540,46599,40305,46599,46529,46599, +45751,46599,46533,46599,45767,46599,46580,46599,46563,46599,45649,46599, +45737,46599,38305,46599,45917,46630,46011,46633,45917,46631,46043,46637, +45814,46599,45771,46599,45869,46599,45871,46599,45689,46599,45691,46599, +45699,46599,45709,46599,45851,46599,45781,46599,40275,46599,46539,46599, +45903,46599,45873,46599,45907,46599,45753,46599,45769,46599,45957,46599, +45805,46599,42613,46676,46043,46599,42613,46680,46565,46599,42613,46684, +45867,46599,37241,46689,42613,46599,46043,46692,46565,46692,45805,46692, +45917,46599,38305,46700,46011,46703,46560,46599,44243,46599,46517,46708, + 7,46599,38305,46713,46517,46715,46517,46712,41941,46599, 6,46721, + 7,46721, 6,46720,46725,46727, 7,46720,46723,46731, 1011,46599, + 7,46735,46517,46599,38305,46738,35187,46739, 6,46742, 6,46743, +44243,46738,38271,46739,38270,46739,37241,46739, 6,46739,35187,46756, +46741,46757, 7,46739,41019,46763,46747,46763, 6,46738,46763,46769, +46751,46769, 7,46738,46759,46775,46745,46775,46757,46775,46753,46775, + 6,45639, 7,45638,43214,46787,45977,46789,38305,46787, 3,46793, +46043,46795,46565,46795,45805,46795, 3,46792,45977,46803, 59,46787, + 1325,46787, 331,46787, 265,46787, 2,46787, 7,46814,46795,46817, + 3,46787,38305,46820,45977,46823,46785,46787,35187,46827, 2,46828, + 2,46829,38057,46827,38056,46827, 2,46827,35187,46838, 3,46827, +46833,46843, 2,46826,46843,46847,46835,46847, 3,46826,46841,46853, +46831,46853,46839,46853,46837,46853, 0, 6,13135,46863,13169,46864, + 4871,46863, 4893,46868,13172,46863, 4894,46863,13136,46863,13143,46877, + 4872,46863, 4879,46881,13145,46863, 4881,46863,37417,46863,38056,46888, +38057,46889,46891,46893,38057,46888,38056,46889,46897,46899,17176,46863, +17380,46863,16950,46863,17058,46863,16948,46863,17056,46863,16974,46863, +17072,46863,16996,46863,17086,46863, 3348,46863,18291,46863, 7316,46863, + 8455,46863, 8343,46863, 8353,46863,13139,46863,13175,46863,13155,46863, +13517,46863,15197,46863,15485,46863,15512,46863,15595,46863,15203,46863, + 5757,46863, 5453,46863, 5471,46863, 5455,46863, 4863,46959, 5507,46863, +12569,46863,12387,46863,12551,46966,12552,46863,16995,46863,16941,46863, +16977,46974,16978,46863,17017,46862,17016,46862,19836,46863,19857,46985, +19815,46863, 4,46988,19857,46991, 4,46989,19843,46995,27930,46863, +27895,46999,27857,46863, 4,47002,27895,47005, 4,47003,27907,47009, +36303,46862,36325,47013,27128,46863, 9136,46863,27266,46863,27163,46863, +34310,46863,34447,47025,46516,46863,46599,47029,33454,46863,33368,46863, +28027,46863,28111,46863,28117,46863,26928,46863,24253,46863,30569,46863, +30316,46863,28213,46863,26525,46863, 9137,46863, 273,46863, 1477,46863, + 281,46863,17011,46863, 5043,46863,15503,46863, 8997,47066,24558,46863, +26575,46863,41877,46863, 120,46863, 77,46863,16977,46863,16941,47080, + 9262,46863,14813,46863,26605,46863,41923,46863, 8843,46863,37131,46863, +41907,46863,26591,46863,41893,46863,37113,46863,20255,46863, 9288,46863, + 8697,46863, 9275,46863, 8784,46863,19877,46863,41867,46863,20043,46863, +21376,46863,21485,46863,19787,46863,19391,46863,19299,46863,19271,46863, +19283,46863,17010,46863, 5042,46863,36518,46863,40664,46863,17017,46863, +46983,47143, 1516,46863, 948,46863,17016,46863,46981,47151,16972,46863, + 903,47154,17070,46863, 1011,47158,17175,46863, 903,47162,17379,46863, + 1011,47166, 4213,46863, 375,47170, 8757,46863, 375,47174, 4266,46863, +16865,46863,16873,46863,16867,46863,12642,46863, 8896,46863,14740,46863, + 8355,46863, 264,47193, 265,47192,47195,47197, 264,47192, 265,47193, +47201,47203,14515,46863,14517,46863,14519,46863,20201,46863,36979,46863, +20152,46863,36898,46863,20239,46863,37095,46863,21522,46863,38266,46863, +17082,46863, 903,47228,16990,46863,16943,47233, 1011,47232,35780,46863, +29644,46863,43412,46863,15628,46863, 9044,46863, 264,47247, 265,47246, +47249,47251, 264,47246, 265,47247,47255,47257,12484,46863,12486,46863, +12488,46863,12551,46863,12387,47266,12547,46863,12633,46863,12507,46863, +12497,46863,12501,46863,13381,46863,13169,46863,13135,47282, 4893,46863, + 4871,47286,12563,46863,27255,46863, 483,47292, 9287,46863, 483,47296, +13119,46863, 264,47300,13143,47303, 264,47301,13169,47307, 4863,46863, + 264,47310, 4879,47313, 264,47311, 4893,47317, 7315,46863, 413,47320, + 264,47320, 264,47321, 265,47320,47327,47329, 265,47321,47325,47333, +14653,46863, 375,47336,16875,46863,12504,46863,19478,46863,35766,46863, +20044,46863,36534,46863,12566,46863,12391,47353,33338,46863,34447,47357, +45866,46863,46599,47361,25545,46863,40675,46863, 1413,46863, 922,46863, + 1281,46863, 247,46863,36303,46863,38299,47377,37897,47377,36335,47377, +35893,47377,20035,46863, 11,47387, 11,47386,36527,46863, 587,47392, +24545,46863, 483,47396,35761,46863, 903,47400,19475,46863, 1011,47404, + 1086,46863, 934,46863, 1216,46863,17049,47412,16937,47412, 9766,46863, + 5519,46863, 8389,46863, 8861,46863, 3345,47424,12377,47424, 8337,46863, + 375,47430, 8374,46863, 8365,46863,20169,46863,36921,46863, 8453,46863, + 4863,47443,13119,47443, 9072,46863, 9105,46863, 305,46863,12377,47452, + 9731,46863, 483,47456, 8997,46863,15503,47460, 265,47460, 265,47461, + 257,47460, 264,47469, 265,47468,47471,47473, 264,47468, 265,47469, +47477,47479, 375,47460,15029,46863,12377,47484, 375,46863,27021,47488, +30091,47488, 9195,47488, 8757,47488, 4213,47488,14653,47488,20103,47488, +36773,47488, 8337,47488, 8997,47488, 241,47488, 6578,46863, 394,46863, + 828,46863, 128,46863, 299,46863, 705,46863, 101,46863,28715,46863, +21315,47526, 165,46863, 903,47530,43215,46863,38057,47534, 1505,46863, + 1011,47538,30091,46863, 375,47542, 113,46863, 25,47546, 9,47546, + 803,46863, 483,47552, 518,46863, 504,46863, 508,46863, 645,46863, + 623,46863, 659,46863, 510,46863, 241,47568, 506,46863, 9,47572, + 244,46863, 483,47576, 265,46863, 8997,47580, 5041,47580,17009,47580, + 8861,47581, 241,46863, 265,47591, 6515,47590, 375,47590, 510,47590, + 483,47590, 9,47600, 9,47590, 483,47604, 1011,46863,16990,47608, +17070,47608,17379,47608,40617,47608,16937,47608, 903,47618, 1505,47608, +17049,47608, 903,47624,21315,47608,19475,47608, 587,47608, 903,47608, +16937,47634,17049,47634, 903,46863,16937,47641,16977,47643,17082,47640, +16972,47640,17175,47640,32805,47640,36349,47640,17049,47640, 1011,47656, + 165,47640,16937,47640,16943,47663, 1011,47662,38057,47640,35761,47640, + 483,47640, 11,47640, 1011,47640,17049,47676,16937,47676,10527,47640, + 4727,47640, 6515,47640, 6564,46863, 6685,46863,35187,47690, 11,47691, + 6515,46863, 241,47696, 903,47696, 587,47697,10761,46863,10592,46863, + 4738,46863,13857,46863, 483,47710,10527,46863, 903,47714, 9,47714, + 3345,46863, 413,47720, 8861,47720, 1369,47721, 341,47721, 3747,46863, + 1369,47731, 3689,46863, 1369,47735,17000,46863,17090,46863, 2691,46863, + 2777,46863, 2793,46863, 2831,46863, 6486,46863, 4415,46863,10493,46863, +13941,46863,10901,46863, 4727,46863, 903,47760, 9,47760, 4819,46863, + 483,47766, 6703,46863, 6623,46863, 5759,46863, 7823,46863, 7813,46863, + 7761,46863, 7705,46863, 7735,46863, 7727,46863,13904,46863,10600,46863, + 4742,46863, 4822,46863, 2875,46863, 2865,46863, 2961,46863, 2949,46863, + 2919,46863, 3645,46863, 3609,46863, 3467,46863,17102,46863,17104,46863, + 1369,47815, 5041,46863, 265,47819, 265,47818, 4919,46863, 483,47824, +17100,46863,17009,46863, 265,47831, 265,47830,17099,46863, 483,47836, + 4920,46863, 6441,46863, 483,47842,17123,46863, 3353,46863, 3691,46863, +10154,46863, 3777,46863, 2847,46863, 2881,46863, 2933,46863, 2929,46863, + 2967,46863, 5271,46863, 4923,46863, 3355,46863, 3031,46863, 3121,46863, +20819,46863,37537,46863,20952,46863,37748,46863,20885,46863, 483,47884, +37663,46863, 9,47888,11529,46863, 1010,46862,23717,47895,24522,47895, +24447,47895,23939,47900,23939,47895,24447,47904,22956,47895,23651,47909, +21605,47895, 17,47913,23939,47915, 17,47912,23651,47919, 17,47895, +21605,47923,24447,47925,21605,47922,23651,47929, 264,46862,47135,47933, +47823,47933,47835,47933,47137,47933,47587,47933,47585,47933,47465,47933, +47583,47933,47019,47933,47581,47933,17009,47953, 5041,47953, 8997,47953, + 265,46862,47063,47961,47065,47961,47055,47961, 8997,47961, 5041,47961, +17009,47961, 8495,47961, 241,47961, 241,46862, 240,46863, 265,47981, + 1,47982, 0,47982, 5521,47983, 5520,47982,47989,47991, 5520,47983, + 5521,47982,47995,47997, 0,47983,47985,48001, 1,47983,47987,48005, + 264,46863,15193,48009,15475,48009,15579,48009,13119,48008,13143,48017, + 4863,48008, 4879,48021,47972,48009,47970,48009,47821,48009,47833,48009, +13507,48009,47968,48009,47467,48009, 53,48009, 1471,48009, 8997,48009, +47961,48042, 253,48009,17009,48009,47961,48048, 5041,48009,47961,48052, +15437,48009, 8997,48057,20501,48009,47961,48009,17009,48062, 5041,48062, + 8997,48062,20219,48009,37019,48009,19513,48009,35843,48009,20697,48009, +37377,48009,13119,48009,13135,48083, 4863,48009, 4871,48087,18967,48009, + 483,48091, 1369,48009, 9875,48009, 8401,48009, 9955,48009,10273,48009, + 4137,48009, 3863,48009, 4063,48009, 241,48009, 413,46863, 3345,48112, + 7315,48112,17049,48112,16937,48112,12377,46863, 8861,48122,15029,48122, + 305,48122, 713,48122, 25,48122, 587,48123,12387,48135, 11,48123, + 257,48123, 253,48123, 1471,48123, 53,48123, 1369,48123, 257,48122, + 587,48122,12391,48153, 257,46863, 9136,48156, 9137,48156, 264,48157, +48159,48163,17827,48156,48163,48167, 413,48156, 1,48170, 264,48156, + 8997,48175, 241,48175, 1,48179, 265,48157, 8997,48183,48175,48184, + 4425,48183,48161,48183,48176,48183,48175,48183, 8997,48194, 5579,48183, +17873,48183, 1791,48183,48173,48183,48181,48183, 265,48156, 8997,48208, +48163,48211,48163,48209, 8997,48215, 8997,48156, 265,48218,48163,48221, + 265,48219,48175,48225,12377,48156,36925,46863,20177,46863, 8383,46863, + 8385,46863, 88,46863, 11,48239,37409,48239, 566,46863,27021,48245, + 9195,48245,20501,48245, 9377,48245, 9875,48245, 587,48245,20763,48245, + 653,46863, 11,48261, 289,46863, 587,48265,36349,46863, 903,48268, +40617,46863, 1011,48272, 66,46863, 33,48277,20217,46863,37017,46863, +37845,46863,38057,46863, 903,48286,43215,48286, 155,48286,21315,46863, + 483,48294, 1011,48294,28715,48294, 1347,48294, 1347,46863,21315,48304, + 155,46863,38057,48308,21378,46863,38134,46863,20103,46863, 375,48316, +36773,46863, 375,48320, 713,46863,12377,48324, 25,46863, 113,48328, +12377,48328,26625,46863, 483,48334,10107,46863,38056,48338,38056,48339, +38057,48338,48343,48345,38057,48339,48341,48349, 3,48339, 3,48338, + 9195,46863, 375,48356,27021,46863, 375,48360, 19,46863, 59,48365, +32805,46863, 4,48368,34447,48371, 903,48368, 9,48368, 4,48369, +33871,48379, 11,48368,34447,48383,45639,46863, 2,48386,46599,48389, + 2,48387,46169,48393, 587,48386,46599,48397,36256,46863,35187,46863, + 6685,48402, 9,48402, 483,46863,27255,48408,26625,48408,24545,48408, + 9287,48408,21315,48408, 903,48408, 9731,48408,13857,48408, 803,48408, + 244,48408,17049,48408, 6441,48408, 4819,48408,17099,48408, 4919,48408, + 9,48408, 241,48440, 241,48408, 9,48444,20885,48408, 5,48408, +27021,48451, 9195,48451,20501,48451, 9377,48451, 9875,48451, 587,48451, +20763,48451, 9,46863,32805,48466,10527,48466, 113,48466, 506,48466, +16937,48466, 4727,48466, 483,48466, 241,48480, 241,48466, 483,48484, +37663,48466, 265,48467, 11,48491, 3,48466, 11,48495,37409,48495, +35187,48466,19917,46863,18967,48503, 5,48504, 5,48505,21036,48503, +21037,48503, 4,48503,48509,48515, 5,48503,18967,48518, 4,48502, +48521,48523,48507,48523,48511,48523, 5,48502,48513,48531, 587,46863, +12377,48535,12551,48537,45639,48535,46275,48541,12377,48534,12391,48545, +36527,48534,45639,48534,46599,48551, 265,48535,17827,48555, 1011,48534, + 11,46863,32805,48561,34003,48563,20035,48560,32805,48560,34447,48569, + 903,48560, 1275,48561, 9,48575, 3,48560, 33,48579, 3,48561, + 113,48583,16937,46863, 1216,48586, 413,48586,21036,48586,21037,48586, +21036,48587,48595,48597,21037,48587,48593,48601, 903,48587,16941,48605, + 1011,48586, 903,48608, 903,48586,16943,48613, 1011,48612, 9,48586, +17049,46863, 1216,48620, 413,48620, 903,48620, 1011,48626, 1011,48620, + 903,48630, 483,48620, 2,48620, 3,48620, 1369,48639, 2,48621, + 3,48621, 483,48645, 2,46862, 6,48649, 4,48651, 5,48649, + 9,48655,21604,48657,21604,48656,21605,48657,48661,48663,21605,48656, +48659,48667, 5,48648,23717,48671,24522,48671,24447,48671,23939,48676, +23939,48671,24447,48680,22956,48671,23651,48685, 17,48671,21605,48689, +24447,48691,21605,48688,23651,48695,21605,48671, 17,48699,23939,48701, + 17,48698,23651,48705, 19,48649, 12,48649, 9,48649, 11,48712, + 11,48649, 9,48716,21605,48649,48652,48720,48653,48721,48723,48725, +48653,48720,48652,48721,48729,48731, 3,46862, 5,48735, 4,46862, +19975,48739,19365,48739,19221,48739,19917,48739,10107,48747, 587,48739, + 5,46862,25451,48753,42283,48753,19739,48753, 0,48753, 3,48761, +25380,48753, 7971,48765,42155,48765, 164,48753,48353,48771,20763,48753, + 1011,48775, 1010,48774,48777,48779, 1010,48775, 1011,48774,48783,48785, + 2,48753, 17,48788,48353,48791, 2,48752,23717,48795,24522,48795, +23939,48795,24447,48800,24447,48795,23939,48804,22956,48795,23651,48809, +21605,48795, 17,48813,23939,48815, 17,48812,23651,48819, 17,48795, +21605,48823,24447,48825,21605,48822,23651,48829, 1369,48753,21605,48832, + 7971,48835,42155,48835,21605,48753, 1369,48840,42155,48843, 7971,48843, + 17,48753,37844,48848,48762,48848,48763,48849,48853,48855,37844,48849, +48763,48848,48762,48849,48861,48863,37845,48848,48859,48867,37845,48849, +48851,48871, 2,48849,48355,48875,47853,48875, 2,48848,48353,48881, + 5,46863, 374,48884, 374,48885, 375,48884,48889,48891,19381,48885, +19380,48884,48895,48897,19381,48884,19380,48885,48901,48903,20812,48884, +20813,48884,20812,48885,48909,48911, 1197,48885,21604,48915,21604,48914, +21605,48915,48919,48921,21605,48914,48917,48925, 375,48885,48887,48929, +20813,48885,48907,48933,20501,48885, 1011,48937,27021,48885, 483,48941, + 9195,48885, 483,48945, 9377,48885, 483,48949, 9875,48885, 1011,48953, + 587,48885, 483,48957, 1369,48885, 1011,48961,38057,48961,20763,48885, + 483,48967, 903,48885, 375,48971, 483,48884,27021,48975, 9195,48975, +20501,48975, 9377,48975, 9875,48975, 587,48975,20763,48975,18967,48885, + 483,48991, 165,48991, 2,48884,48961,48997, 3,48884,13118,49000, + 4862,49000,13118,49001,13119,49000,49007,49009, 4863,49000, 4862,49001, +49013,49015,15193,49001,15475,49001,15579,49001,13507,49001,20501,49001, + 253,49001,15437,49001, 8997,49031,20219,49001,37019,49001,19513,49001, +35843,49001,20697,49001,37377,49001,13119,49001,49003,49047, 4863,49001, +49005,49051, 241,49001, 9875,49001, 53,49001, 1471,49001, 8401,49001, + 9955,49001,10273,49001, 4137,49001, 3863,49001, 4063,49001, 1369,49001, +18967,49001, 483,49077, 2,48885, 1,49081, 7,49082,49000,49084, +49001,49085,49087,49089,49000,49085,49001,49084,49093,49095, 7,49081, + 1,49098,49000,49100,49001,49101,49103,49105,49000,49101,49001,49100, +49109,49111, 1,49080, 7,49115, 7,49080,49001,49119, 0,49080, +49083,49123, 7,49125,49001,49127, 0,49081,49116,49131,49001,49133, + 7,49131,49115,49136,49001,49139,49001,49137,49115,49143,49115,49131, + 7,49146,49001,49149,49001,49081, 3,48885,37357,49155, 165,49155, +10257,49155, 483,49155,35187,48885, 375,49165, 9,48885, 1,49168, + 3,49171,46863,49172,46863,49171, 3,49176, 3,49177,37845,49169, +37845,49168,37844,49168,49183,49187,37844,49169,49185,49191, 2,49168, +49175,49195,49179,49195, 2,49169,49181,49201, 3,46863,49171,49204, +49195,49207, 6,49205, 11,49211, 0,49205, 0,49204,40704,49217, +38305,49217, 9,49220, 9,49217,38305,49224, 6,49204,40705,49229, +49217,49231,49219,49229,18967,49229, 4,49236, 5,49236, 5,49237, + 4,49237,46863,49244,49241,49247,46863,49237, 4,49250,49241,49253, + 4,49251,49243,49257,49227,49229, 17,49229,49223,49229,37325,49205, + 903,49267,10107,49204,48875,49271,10219,49205, 903,49275,17049,49204, + 1369,49279, 11,49205, 25,49283, 9,49283, 17,49205, 903,49289, +21315,49289,37409,49205, 9,49295, 1011,49205, 375,49299, 9,49204, + 11,49303,37409,49303, 11,49204, 33,49309,35187,49205, 1505,49313, + 4,49204,49289,49317, 5,49204,13118,49320, 4862,49320,13118,49321, +13119,49320,49327,49329, 4863,49320, 4862,49321,49333,49335,15193,49321, +15475,49321,15579,49321,13507,49321,20501,49321, 253,49321,15437,49321, + 8997,49351,37019,49321,20219,49321,35843,49321,19513,49321,37377,49321, +20697,49321,13119,49321,49323,49367, 4863,49321,49325,49371, 241,49321, + 9875,49321, 1471,49321, 53,49321, 8401,49321,10273,49321, 9955,49321, + 4137,49321, 4063,49321, 3863,49321, 1369,49321,18967,49321, 483,49397, + 4,49205, 1,49401, 7,49402,49320,49404,49321,49405,49407,49409, +49320,49405,49321,49404,49413,49415, 7,49401, 1,49418,49320,49420, +49321,49421,49423,49425,49320,49421,49321,49420,49429,49431, 1,49400, + 7,49435, 7,49400,49321,49439, 0,49400,49403,49443, 7,49445, +49321,49447, 0,49401,49436,49451,49321,49453, 7,49451,49435,49456, +49321,49459,49321,49457,49435,49463,49435,49451, 7,49466,49321,49469, +49321,49401, 5,49205,20645,49475, 1505,49475, 9935,49475,18967,49205, + 7,49483, 4,49484, 4,49485, 16,49483, 17,49483, 4,49482, +49493,49495, 5,49482,49487,49499,49491,49499, 4,49483, 7,49504, +49499,49507, 5,49483,49489,49511, 2,46863, 6,49515, 17,49517, +35187,49519, 0,49515,38305,49523, 15,49525, 0,49514,36545,49529, +49521,49529, 15,49529, 6,49514,49531,49537,36544,49537,49529,49541, +49527,49537, 11,49537,35187,49546,49529,49549,35187,49537, 11,49552, +49529,49555,45639,49514,46599,49559,45639,49515,46275,49563,17125,49515, + 16,49567, 16,49566, 17,49567,49571,49573, 17,49566,49569,49577, +17049,49514, 4,49514, 7,49583, 1,49585, 265,49583, 1,49588, + 0,49588,49587,49589,49586,49588,49595,49597,49587,49588,49586,49589, +49601,49603, 0,49589,49591,49607, 1,49589,49593,49611, 4,49515, + 1011,49615, 1,49617, 0,49617, 1,49616,49621,49623, 0,49616, +49619,49627, 4,46863,27857,49630,27895,49633,19815,49630,19857,49637, +49237,49631,49239,49641,49237,49630,49241,49645,32805,49630,34447,49649, +32805,49631,34003,49653,27857,49631,27879,49657,19815,49631,19849,49661, + 2,49630, 7,49665, 1,49667, 265,49665, 1,49670, 0,49670, +49669,49671,49668,49670,49677,49679,49669,49670,49668,49671,49683,49685, + 0,49671,49673,49689, 1,49671,49675,49693, 2,49631, 903,49697, + 1,49699, 0,49699, 1,49698,49703,49705, 0,49698,49701,49709, + 1, 7, 377,49713,48110,49712,48111,49712,49152,49712,49472,49712, +49153,49712,49473,49712,49374,49712,49054,49712,49375,49712,49055,49712, + 704,49712, 100,49712,26502,49712,41376,49712, 8808,49712,47622,49713, +47660,49713,47146,49713,47148,49713,49059,49713,49379,49713,49158,49713, +49478,49713,49061,49713,49381,49713,48998,49713,49318,49713,47224,49713, +47226,49713,48041,49713,48039,49713,47058,49713,47060,49713,47220,49713, +47222,49713,48047,49713,47056,49713,47442,49713,49349,49713,49029,49713, +49121,49713,49441,49713,47628,49713,47668,49713,48962,49713,49290,49713, +22798,49713,39074,49713,31498,49713,44616,49713,31392,49713,44494,49713, +47540,49713,47532,49713,31794,49713,44858,49713,48298,49713,48288,49713, +31924,49713,44994,49713, 8652,49713, 8535,49713,13252,49713,43989,49712, +41417,49843,30655,49712,26219,49847,26503,49712,41377,49712, 8809,49712, +26547,49712,26219,49857,41835,49712,41417,49861, 273,49712,12897,49865, + 8813,49712, 8647,49869, 376,49713, 705,49712, 101,49712, 803,49712, + 483,49879,30091,49712,26219,49883, 113,49712, 9,49887,43503,49712, +41417,49891,43215,49712, 483,49895,43214,49712, 112,49712, 802,49712, +49320,49712,49401,49905, 241,49905,49000,49712,49081,49911, 241,49911, +49081,49712,49001,49916,49001,49917,49911,49921,49401,49712,49321,49924, +49321,49925,49905,49929,49001,49712,49081,49932, 241,49932,49321,49712, +49401,49938, 241,49938, 414,49713,18391,49945, 420,49713,18391,49949, + 449,49713,18391,49953, 8808,49713,49855,49957, 8453,49713,46863,49960, +20239,49713,46863,49964,37095,49713,46863,49968,47976,49713,47593,49713, +26502,49713,49851,49977,31921,49713,47592,49713, 8495,49983, 828,49713, +49903,49987, 128,49713,49901,49991, 705,49713,49737,49995, 101,49713, +49739,49999,47977,49713, 8495,50003,47488,49713,48122,49713,48480,49713, +48440,49713,47568,49713, 1344,49713, 1482,49713, 64,49713, 1484,49713, + 336,49713, 1480,49713, 254,49713, 1342,49713, 338,49713, 1123,49713, + 931,49713, 665,49713, 1417,49713, 1429,49713, 1301,49713, 1127,49713, + 941,49713, 523,49713, 1283,49713, 939,49713, 1103,49713, 171,49713, + 1525,49713, 407,49713, 1517,49713, 949,49713, 280,49713, 1476,49713, + 272,49713, 1017,49713, 1077,49713, 1047,49713, 1113,49713, 1245,49713, + 1237,49713, 501,49713, 433,49713, 929,49713, 591,49713, 915,49713, + 681,49713, 1555,49713, 911,49713, 1545,49713, 855,49713,41376,49713, +49853,50107, 4900,49713,14622,49713,48113,49713, 8997,50115, 1382,49713, + 695,49713,48286,49713, 903,50122,48294,49713, 1011,50126,26503,49713, +49741,50131,47530,49713, 903,50134,47538,49713, 1011,50138,49289,49713, +49317,50142, 903,50142,48961,49713,48997,50148, 1011,50148,21522,49713, +46863,50154,38266,49713,46863,50158, 394,49713, 299,49713,31792,49713, + 903,50166,44856,49713, 1011,50170,22789,49713, 903,50174,39065,49713, + 1011,50178, 1386,49713, 545,49713,41377,49713,49743,50187, 413,49712, + 8647,50191,18062,50191,17993,50191, 251,50196, 251,50191,17993,50200, +46863,50191, 412,49712,48008,49713,50207,50209,49717,50209, 341,50209, +40381,49713, 17,50217, 913,49713, 483,50221, 289,49713, 8809,49713, +49745,50227,49000,49713,49935,50231,49919,50231,49721,50231,49731,50231, +49937,50231,49933,50231,49081,50243, 241,50243,49320,49713,49941,50249, +49927,50249,49723,50249,49729,50249,49943,50249,49939,50249,49401,50261, + 241,50261, 1374,49713, 8672,49713,12534,49713,12921,49713, 264,50273, + 265,50272,50275,50277, 264,50272, 265,50273,50281,50283, 8605,49713, +26097,49713,41299,49713,26277,49713,41479,49713,26104,49713,41314,49713, + 1477,49713,46863,50300, 281,49713,46863,50304, 1516,49713,46863,50308, + 948,49713,46863,50312,44988,49713, 903,50316,31920,49713, 1011,50320, +43293,49713,49895,50325,15156,49713, 264,50329, 265,50328,50331,50333, + 264,50328, 265,50329,50337,50339, 8916,49713,14623,49713, 8495,50345, + 4901,49713, 8495,50349,14611,49713, 241,50352, 4899,49713, 241,50356, +15219,49713, 412,50360, 413,50361,50363,50365, 412,50361, 413,50360, +50369,50371, 5119,49713, 412,50374, 413,50375,50377,50379, 412,50375, + 413,50374,50383,50385,13177,49713, 413,50388, 264,50388, 264,50389, + 265,50388,50395,50397, 265,50389,50393,50401, 5313,49713,12377,50404, +47591,49713, 265,50409, 8861,50411, 265,50408, 8495,50415,47641,49713, +43292,49713,49899,50421,15158,49713,39228,49713,23012,49713,40676,49713, +25546,49713, 500,49713,18391,50435, 432,49713,18391,50439, 1244,49713, +18617,50443, 1236,49713,18617,50447, 1109,49713, 903,50451, 1412,49713, + 305,50455,44832,49713,31770,49713,25545,49713, 9,50462,40675,49713, + 483,50466, 935,49713, 483,50471, 1087,49713, 9,50475, 1413,49713, + 295,49713, 1290,49713, 903,50483, 1304,49713, 9,50487,48009,49713, +50191,50491,49719,50491, 241,50491,22957,49713, 903,50498,39205,49713, + 1011,50502,47608,49713, 1505,50506,21315,50506,47640,49713, 165,50512, +38057,50512, 510,49713,46863,50518, 922,49713, 1108,49713, 1280,49713, + 9,50527, 246,49713, 483,50531, 412,49713,47460,50535, 483,50535, + 9,50535, 8997,50535,46863,50542,46863,50535, 8997,50546, 1216,49713, +44243,50550,31103,50550, 483,50550,18617,50557, 9,50550,18617,50561, + 8677,49713, 305,49713, 241,50567,16163,50567, 8647,50566, 8495,49713, + 257,50574, 1141,49713,16531,50579, 253,49713, 59,50582, 1325,50582, + 331,50582, 265,50582, 8634,49713, 8611,49713,41349,49713,26127,49713, + 273,49713,12705,50601,13673,50601,18391,50601, 2923,50601,46863,50600, + 331,49713, 53,50612, 1471,50612, 253,50612, 1369,50612, 8861,49713, + 241,50623, 375,50625, 375,50622, 251,49713, 413,50631,17993,50633, + 413,50630,18391,50637,15029,50630, 264,50641, 265,50640,50643,50645, + 264,50640, 265,50641,50649,50651,39204,49713, 257,49713, 265,50657, +26625,50657,25793,50657,41019,50657, 8495,50657, 9731,50657,25793,50656, +41019,50656, 8495,50656, 265,50656, 4863,50677,12377,49713,46863,50680, + 5313,50680, 341,49713, 241,50687, 298,49713, 4863,50691, 704,49713, +49875,50695, 9195,50695, 100,49713,49877,50701, 395,49713, 829,49713, +49879,50707, 9195,50707, 129,49713,49887,50713, 89,49713,48884,50716, +48884,50717,48885,50717,50719,50723,48885,50716,50721,50727, 11,50716, + 567,49713,42155,50733,41941,50733, 7971,50733, 9565,50733, 587,50733, + 9377,50743, 587,50732, 9195,50747,38057,49713,47640,50750,46863,50750, + 903,50754, 903,50750,46863,50758,21315,49713,47608,50762,46863,50762, + 1011,50766, 1011,50762,46863,50770, 628,49713, 1396,49713, 241,50777, + 288,49713, 7971,50781, 265,49713,23584,50785,39564,50785,24355,50785, +39905,50785, 5520,50785, 256,50784,50795,50797, 5521,50785, 256,50785, +50204,50785, 10,50784, 1,50785, 257,50808,50797,50811, 257,50809, +50803,50815, 10,50785,50191,50785,46863,50820,47590,50784,23493,50785, +22807,50826,39489,50785,39085,50830,22807,50785,23493,50834,39085,50785, +39489,50838, 1087,50785, 935,50785,47591,50784, 8495,50847,47590,50785, +50847,50851, 4213,50785, 8757,50785,26415,50785,41653,50785,27377,50785, + 9335,50785,42471,50785, 8109,50785, 4147,50785, 3933,50785, 53,50784, + 1471,50784, 253,50784,47591,50785,50825,50881, 257,50785, 1,50884, +50797,50887,50797,50885, 4827,50885, 305,50785, 8861,50895, 8495,50785, + 331,50899,46863,50785,50191,50902, 241,50902, 241,50785,46863,50908, + 8337,50909,46863,50913, 1369,50784, 305,50917, 11,50785,50807,50921, + 8165,50921, 1369,50921, 241,50784,47460,50929, 483,50929, 9,50929, + 8997,50929,46863,50936,46863,50929, 8997,50940, 257,50784,50801,50945, +50803,50945, 4863,50945, 11,50784,50819,50953, 7971,50953, 1011,49713, +31920,50958,48294,50958,44856,50958,47538,50958,48961,50958,39065,50958, +21315,50958,46863,50972,31103,50958, 903,50976, 1505,50958,46863,50980, +44243,50958, 903,50984,39205,50958, 9,50958, 903,50958,31103,50992, +44243,50992,46863,50958,21315,50998, 1505,50998, 903,49713,44988,51004, +48286,51004,31792,51004,47530,51004,49289,51004,22789,51004,38057,51004, +46863,51018,44243,51004, 1011,51022, 165,51004,46863,51026,31103,51004, + 1011,51030,22957,51004, 483,51004, 1011,51004,44243,51038,31103,51038, +46863,51004,38057,51044, 165,51044, 241,49713,47961,51050, 4899,51050, +14611,51050, 375,51050,12377,51051, 375,51061, 8997,51051, 375,51065, + 265,51065,46863,51069, 1275,51050, 9,51073, 15,51050, 483,51077, + 265,51050,47460,51081, 483,51081, 9,51081, 8997,51081,46863,51088, +46863,51081, 8997,51092, 8647,49713, 413,51096, 305,51097, 11,51097, + 1369,51097, 341,51097, 305,51096,41417,49713, 11,51111, 1369,51111, +26219,49713, 11,51117, 1369,51117,32102,49713,27021,51123,45148,49713, + 11,51127, 1369,51127,31857,49713,44925,49713,32294,49713,45314,49713, +17565,49713,32103,49713, 241,51143, 587,51142,45149,49713, 11,51148, +49317,49713,49289,51152,48997,49713,48961,51156,49001,49713,49912,51161, +49725,51161,49914,51161,49735,51161,49081,51161,49911,51170,49911,51161, +49081,51174, 241,51174, 241,51161,49911,51180,49321,49713,49906,51185, +49727,51185,49908,51185,49733,51185,49401,51185,49905,51194,49905,51185, +49401,51198, 241,51198, 241,51185,49905,51204,49475,49713, 1505,51208, +49155,49713, 165,51212, 240,49712,51059,51217,50163,51217,50165,51217, +51051,51217, 375,51225, 264,49712,49715,51229,50838,51229,50834,51229, +50850,51229,50847,51229,50945,51229,49983,51229,50415,51229,50677,51229, +50691,51229,50496,51229,50003,51229,50906,51229,50910,51229,50345,51229, +50349,51229, 8374,51229, 8389,51229,50705,51229,20152,51229,36898,51229, +20201,51229,36979,51229,50902,51229, 241,51276,50908,51229,46863,51280, +50491,51229, 241,51284,47590,51229,50785,51288,22807,51229,50785,51292, +39085,51229,50785,51296,26219,51229,41417,51229,14524,51229,35690,51229, +50733,51229,37519,51229,50781,51229,50953,51229,50455,51229,50917,51229, +19396,51229, 8647,51229,20103,51229, 375,51324,36773,51229, 375,51328, + 8337,51229, 375,51332,50785,51229,39085,51336,22807,51336,47590,51336, +46863,51336, 241,51344, 241,51336,46863,51348,47488,51229,47961,51229, + 9,51229,18967,51356, 483,51229,35187,51229, 375,51362,18967,51229, + 9,51366,46863,51229,50908,51370,50785,51370, 241,51374, 241,51370, +50785,51378, 375,51370, 241,51229,50491,51384,50902,51384,50785,51384, +46863,51390,46863,51384,50785,51394, 375,51229, 8337,51398,20103,51398, +36773,51398,14315,51398,35187,51398,46863,51398,14315,51229, 375,51412, + 4899,51229,14611,51229, 1010,49712, 3867,51421, 8277,51421, 4067,51421, + 3997,51421, 8953,51421, 9459,51421, 902,49712,50321,51435,51031,51435, +24265,51435,28233,51435,29077,51435,51005,51435,31103,51447,19559,51435, + 4283,51435, 9673,51435, 4279,51435, 3807,51435,20361,51435,20713,51435, + 9967,51435, 8251,51435,47961,49713, 241,51468,47979,49713, 412,51472, + 413,51473,51475,51477, 412,51473, 413,51472,51481,51483, 240,49713, + 340,51487,51398,51487,51418,51487,51416,51487,51354,51487,47974,51487, +47589,51487, 8590,51487,12537,51487,14620,51487, 375,51487,51229,51508, + 7,51487, 265,51512, 265,51513,51229,51517,47580,51487, 8861,51521, +47961,51487,51229,51524, 8495,51524,51229,51487, 375,51530,14611,51530, + 4899,51530,47961,51530, 8495,51487, 4899,51540,47961,51540,14611,51540, +14611,51487,51229,51548, 8495,51548, 4899,51487,51229,51554, 8495,51554, +46863,51487, 265,51560, 8861,51563, 265,51561, 8495,51567,51229,51567, + 265,51487, 7,51572,15309,51573,15308,51572,51577,51579,15308,51573, +15309,51572,51583,51585,46863,51572, 8861,51589, 902,49713,31103,51593, +43053,51593,46863,51593, 1010,49713, 1505,51601, 918,51601, 9,51601, + 903,51606, 903,51601, 9,51610, 265,49712,49873,51615,50165,51615, +51059,51615,51057,51615,51055,51615,51053,51615,49975,51615,49973,51615, +50113,51615,50111,51615,50163,51615,51471,51615,50355,51615,50359,51615, +50209,51615, 241,51645, 8948,51615,50225,51615,50479,51615, 331,51615, + 8861,51654, 8861,51615, 331,51658, 4827,51615,15269,51615,51051,51615, + 375,51667,14611,51667, 4899,51667,47961,51667, 241,51614,50209,51677, + 241,49712,18300,51681, 8605,51681, 8916,51681,50945,51681,49321,51680, +50249,51691,49001,51680,50231,51695,50705,51681, 8374,51681,51508,51681, +50691,51681,47443,51681, 8389,51681,50677,51681,51517,51681, 8861,51681, + 375,51714,26219,51681,41417,51681, 305,51681,48009,51681,51229,51725, + 8647,51681, 8452,51681,46863,51731, 713,51681, 25,51681,18257,51681, + 375,51738, 8337,51681, 375,51742, 265,51742,46863,51747, 375,51681, +18257,51750, 8861,51750, 8337,51750,51487,51750,51487,51681, 375,51760, + 265,51680,50209,51765,49321,51681,49905,51769,49001,51681,49911,51773, + 265,51681,51370,51777,51229,51777,46863,51780,46863,51777,51229,51784, + 8337,51776,46863,51789,46863,51681, 264,51792,51765,51795, 264,51793, +51777,51799, 264,49713,51489,51803,51515,51803,51575,51803,51521,51803, +50411,51803,50659,51803,51563,51803, 8471,51803, 8397,51803, 8371,51803, +20149,51803,36887,51803,20211,51803,37009,51803,20247,51803,37103,51803, +51589,51803,50207,51803,46863,51839,51765,51803,46863,51843,51677,51803, +46863,51847,36773,51803,46863,51851,20103,51803,46863,51855, 8337,51803, +46863,51859, 4613,51803,12571,51803,36539,51803,37595,51803,36049,51803, +47581,51803,51487,51873,51615,51803,39085,51877,22807,51877,47590,51877, +46863,51877, 241,51884, 241,51877,46863,51888,46863,51802,51765,51893, +51677,51893,50207,51893,51615,51893, 241,51901, 341,51893, 1369,51803, + 341,51803,51487,51909, 8337,51909,20103,51909,36773,51909,35187,51909, +14315,51909,46863,51909,12377,51803, 375,51925, 1011,49712,26219,51929, +41417,51929, 8647,51929, 903,49712,49981,51937,51594,51937, 375,51937, +31103,51937,51593,51944,51593,51937,31103,51948,15269,51937, 4827,51937, + 1217,49713, 483,51957, 9,51957, 413,49713, 8647,51962,13177,51962, + 251,51962,18391,51969, 375,51962,18391,51973,44243,51962,31103,51962, +18391,51963, 251,51981, 483,51962,18391,51985, 9,51962,18391,51989, + 375,49713, 5,51992,51615,51995, 413,51993,17993,51999, 413,51992, +18391,52003, 241,51993,51487,52007,46863,51992, 241,51992,51217,52013, +51615,52013, 8861,51992,12377,51993,51487,52021,15029,51992,14315,49713, + 341,52027,51487,52029,15029,49713, 266,52032, 267,52032, 264,52033, +52035,52039, 465,52032,52039,52043, 413,52032, 6,52046, 264,52032, + 251,52051, 241,52051, 6,52055, 265,52033, 251,52059,52051,52060, + 8841,52059,52037,52059,52052,52059,52051,52059, 251,52070,15363,52059, +15055,52059,15061,52059,52049,52059,52057,52059, 265,52032, 251,52084, +52039,52087,52039,52085, 251,52091, 251,52032, 265,52094,52039,52097, + 265,52095,52051,52101, 375,52032, 8639,49713, 8643,49713,26217,49713, +41415,49713, 164,49713,51593,52115, 903,52115, 1504,49713,51601,52121, + 144,49713, 113,52125, 802,49713,49880,52129,49879,52129, 483,52132, + 9366,52129, 9195,52129, 483,52138, 483,52129,49879,52142, 9195,52142, +31103,52129, 112,49713,49888,52151,49887,52151, 9,52154, 9,52151, +49887,52158,44243,52151, 1486,49713, 803,52165,43214,49713,49896,52169, +49895,52169, 483,52172, 483,52169,49895,52176, 1073,49713, 903,52181, + 525,49713, 903,52185, 669,49713, 483,52189, 566,49713,51929,52193, +51615,52193,10107,52193,21036,49713, 17,52201, 88,49713,37611,52205, +36083,52205,38155,52205,35927,52205, 1346,49713, 1505,52215, 154,49713, + 483,52219,26329,49713,41557,49713, 165,49713,49155,52226,47640,52226, +46863,52226, 903,52232, 903,52226,46863,52236,43215,52226, 1505,49713, +49475,52242,47608,52242,46863,52242, 1011,52248, 1011,52242,46863,52252, +28715,52242, 803,49713,49903,52259, 483,52261, 483,52258,49903,52265, + 113,49713,49901,52269, 9,52271, 9,52268,49901,52275,28715,49713, + 1505,52278,43215,49713,49899,52283, 483,52285, 483,52282,49899,52289, + 165,52282,29028,49713,43318,49713,25793,49713, 257,52298, 713,49713, + 241,52303,16163,52303,41019,49713, 257,52308, 25,49713, 241,52313, +16163,52313, 1447,49713,16531,52319, 33,49713,16531,52323, 1471,49713, + 59,52326, 1325,52326, 331,52326, 265,52326, 53,49713, 1325,52336, + 59,52336, 331,52336, 265,52336, 1325,49713, 53,52346, 1471,52346, + 253,52346, 1369,52346, 59,49713, 1471,52356, 53,52356, 253,52356, + 1369,52356,48466,49713, 483,52366,48408,49713, 9,52370, 843,49713, + 9,52375, 1530,49713, 9,52379,40436,49713, 113,52383, 587,49713, +28714,52387,36212,52387,30091,52387, 567,52386, 9195,52395, 11,52386, +32103,52386,35187,52387, 241,52402, 241,52387,35187,52406, 4,52386, + 9366,52411, 9195,52411, 483,52414, 483,52411, 9195,52418,31103,52411, + 5,52387,21605,52424, 9195,52425,27021,52425,21605,52387, 11,52433, + 5,52432, 11,49713,32805,52439,19888,52439,19913,52439, 265,52439, +51803,52447,43503,52439, 1275,52438, 9,52453, 89,52438, 587,52438, + 265,52438,51229,52461, 7971,52461,45149,52438,18967,52439, 241,52468, + 241,52439,18967,52472, 2,52438, 9,52477,44243,52477, 3,52439, + 7971,52483,42155,52483, 2,52439,52205,52489,38305,52439, 265,52493, +38305,52438, 113,52497, 1369,49713, 331,52500, 59,52500,40674,52501, +38305,52501, 265,52509, 241,52508, 241,52501,38305,52514, 1325,52500, + 265,52500,51229,52521, 305,52521, 17,52500, 241,52527,38305,52500, +35187,52501, 265,52501, 331,52535,51803,52535, 4,52500,51601,52541, + 5,52500, 803,52545, 5,52501, 959,52549, 47,52549, 759,52549, + 4,52501, 1275,52500, 9,52559, 17,49713, 1275,52562, 903,52565, + 1369,52562, 241,52569, 2,52562, 903,52573,51593,52573, 3,52562, + 113,52579, 3,52563, 1141,52583, 1447,52583, 33,52583, 2,52563, + 265,52591,51803,52591,38305,49713, 1369,52596, 3,52596, 3,52597, + 8165,52603,20501,52603, 9875,52603, 11,52603, 11,52596, 113,52613, + 15,49713, 1010,52617, 1010,52616, 1011,52616,52619,52623, 1011,52617, +52621,52627, 241,52616, 483,52631, 3,52616, 483,52635, 3,52617, + 1369,52639, 1275,49713, 17,52642, 903,52645, 11,52642, 9,52649, + 241,52642, 9,52653, 9,52643, 1369,52657, 11,52657, 5,52642, + 1505,52663, 5,52643, 53,52667, 1471,52667, 253,52667, 1369,52642, + 9,52675,18967,49713, 241,52679, 9,52681, 5,52678, 17,52685, + 5,52679, 9,52689, 483,49713, 803,52693,52129,52695,43215,52693, +52169,52699, 1216,52693,18759,52703, 413,52693,17993,52707, 803,52692, +49903,52711,48466,52692,43215,52692,49899,52717,40675,52692, 1216,52692, +18617,52723, 413,52692,18391,52727,44243,52692,38305,52693,46169,52733, + 9,52692,46863,52736, 903,52692, 5,52692,10107,52743,51929,52743, +51615,52743, 5,52693,46863,52692, 9,52752, 9,49713, 113,52757, +52151,52759, 4,52756, 7,52763, 2,52765, 2,52764, 2,52763, + 7,52770, 1368,52763, 1216,52757,18759,52777, 413,52757,17993,52781, + 113,52756,49901,52785,48408,52756,25545,52756, 1216,52756,18617,52793, + 413,52756,18391,52797,31103,52756, 483,52756,46863,52802, 1011,52756, + 3,52756,52769,52809,52773,52809,37611,52809,38155,52809,35927,52809, +52489,52809,52775,52809, 3,52757,52767,52825,52151,52825,37663,52825, +52477,52825,31103,52825,46863,52756, 483,52836,31103,49713, 1216,52840, + 413,52840,21036,52840,21037,52840,21037,52841,52847,52851, 903,52841, +51593,52855, 1011,52840, 903,52858,21036,52841,52849,52863, 903,52840, +51435,52867, 1011,52866, 9,52840, 5,52840,27021,52875,44243,49713, + 1216,52878, 413,52878, 903,52878, 1011,52884, 1011,52878, 903,52888, + 483,52878, 3,52878, 11,52895, 1369,52895, 3,52879, 483,52901, +49205,49713, 5,52905,48885,49713, 113,52909, 3,52909, 3,49712, +20819,52915,50945,52915,51508,52915,37537,52915,36898,52915,20152,52915, + 8374,52915,50695,52915,50701,52915,50707,52915,50713,52915,50691,52915, +50705,52915,37748,52915,20952,52915,52395,52915,52457,52915,52142,52915, +52158,52915, 8389,52915,50677,52915,51517,52915,50747,52915,50731,52915, +52418,52915,52478,52915,36979,52915,20201,52915,26219,52915,26106,52915, +52129,52915, 483,52976,52411,52915, 483,52980,51123,52915,32103,52915, +52875,52915,31770,52915,42885,52915,20885,52915, 483,52994,40399,52915, +44714,52915, 357,52915, 367,52915, 471,52915, 1249,52915, 8800,52915, + 8647,52915,47488,52915, 8086,52915,19687,52915,19559,52915,20361,52915, + 9673,52915,20713,52915, 9967,52915, 4283,52915, 4279,52915, 3807,52915, + 8251,52915,41746,52915,41417,52915,44832,52915, 9704,52915,20326,52915, +21087,52915,52906,52915,48245,52915,48975,52915,48451,52915,52151,52915, + 9,53058,52477,52915, 9,53062,51487,52915, 375,53066,50785,52915, + 8165,52915, 265,53073, 1447,52915,38305,53077,21127,52915,20843,52915, +52425,52915,37663,52915, 9,53086, 1141,52915,38305,53091, 566,52915, + 567,52915,46863,53097,44243,52915,41941,53100, 483,53100, 375,52915, +51487,53106,20103,53106, 8337,53106,36773,53106,46863,53106,41941,52915, +44243,53118, 33,52915,38305,53123, 9617,52915, 9,53126, 8337,52915, + 375,53130,48884,52915, 1011,52915,48885,52915, 483,53139,52907,52915, + 25,52915, 7971,53144,41019,52915, 11,53148, 305,52915, 8495,52915, + 11,53154,20103,52915, 375,53158,20273,52915, 9,53162, 4,52915, +28411,53167,31103,53167,48408,53167,52905,53167, 483,53167,46863,53176, +20691,53167, 9923,53167,46863,53167, 483,53184, 5,52915,52905,53188, + 17,53189,18967,53193,46863,53188, 483,53188,25793,52915, 11,53200, + 713,52915, 7971,52915, 25,53206,36773,52915, 375,53210, 4,52914, +53191,53215,53051,53215,24265,53215,28233,53215,29077,53215,53135,53215, +53197,53215,53189,53215,52905,53231,46863,53231,19559,53215, 9673,53215, + 4283,53215,20361,53215, 9967,53215,20713,53215, 8251,53215, 4279,53215, + 3807,53215, 5,52914,53143,53255,53174,53255,50785,53255,53139,53255, +53184,53255,50733,53255,19396,53255,53167,53255,52905,53270,46863,53270, + 8647,53255,41417,53255,26219,53255, 9,53255,18967,53282, 483,53255, +18967,53255, 9,53288,52905,53255,53167,53292,46863,53255,53167,53296, + 11,52915,25793,53301,25793,53300, 8495,53301, 8495,53300,18967,53301, +41019,53301,41019,53300,21037,53301, 9,52915,52151,53318,37663,53318, +52477,53318,31103,53318,20273,53318, 9617,53318,52905,52915, 5,53332, +53215,53335, 5,53333,53167,53339, 9875,52915,35187,53343, 241,53343, +46863,52915, 375,53348, 5,53348,53215,53353, 5,53349,53167,53357, + 483,52915,52129,53360,20885,53360,52411,53360,44243,53360, 5,53361, + 5,53360,18967,52915,11731,53375, 113,53375,31103,52915, 9,53380, +20501,52915,35187,53385, 241,53385, 2,49712,52711,53391,52785,53391, +51059,53391,50165,53391,49995,53391,49999,53391,49987,53391,49991,53391, +50163,53391,52013,53391,52265,53391,52275,53391,17609,53391, 4904,53391, +17586,53391,52259,53391, 483,53423, 272,53391, 1476,53391, 280,53391, + 949,53391, 1517,53391,52269,53391, 9,53437, 9484,53391,51803,53391, +51051,53391, 375,53445, 4903,53391, 9,53448,17579,53391, 9,53452, +42991,53391,40039,53391,40685,53391, 1197,53391, 265,53391, 253,53464, + 1471,53464, 53,53464, 53,53391, 265,53472, 253,53391, 265,53476, + 5,53391, 1471,53391, 265,53482, 5,53390, 8953,53487, 9459,53487, + 4067,53487, 3997,53487, 8277,53487, 3867,53487, 11,53391, 9377,53500, + 9,53391, 4903,53504,17579,53504, 9377,53391, 11,53510, 5,53511, + 5,49712,48765,53517,48835,53517,48843,53517,25445,53517,22779,53517, +22243,53517, 7,53517, 2,53531,28063,53517,25299,53517,31598,53517, +53152,53517,50733,53517,35690,53517,37519,53517,50781,53517,52461,53517, +50953,53517, 272,53517, 1476,53517, 280,53517, 949,53517, 1517,53517, + 357,53517, 367,53517, 471,53517, 1249,53517, 9304,53517,53204,53517, +53144,53517,35931,53517,52912,53517,20326,53517,21087,53517,20273,53517, + 9,53586,50785,53517, 1369,53591,53391,53591,25381,53517,48753,53597, +10081,53597, 9704,53517, 53,53517, 265,53604,37899,53517,37617,53517, +52483,53517, 9617,53517, 9,53614, 253,53517, 265,53618,31103,53517, +26625,53622, 375,53517,35187,53626,26625,53517,31103,53630, 1471,53517, + 265,53634, 265,53517, 253,53638, 1471,53638, 53,53638,49204,53517, +49205,53517,52913,53517, 713,53517, 9195,53652,52915,53652,21605,53653, + 305,53517,52915,53660,21605,53661, 2,53517, 8229,53667,52909,53667, +46863,53667, 3,53517,52909,53674,53391,53675, 1369,53675,46863,53674, +52915,53517, 305,53684, 713,53684, 25,53684, 25,53517,52915,53692, +21605,53693, 9195,53517, 713,53698, 2,53516,53677,53703,53581,53703, +53647,53703,53683,53703,53675,53703,52909,53713,46863,53713, 4067,53703, + 3997,53703, 8953,53703, 9459,53703, 8277,53703, 3867,53703, 3,53516, +53651,53731,53670,53731,50785,53731,50733,53731,53649,53731,53672,53731, +19396,53731,53667,53731,52909,53746,46863,53746, 8647,53731,26219,53731, +41417,53731, 483,53731,18967,53731, 9,53760, 9,53731,18967,53764, +52909,53731,53667,53768,46863,53731,53667,53772, 587,53517,35187,53777, + 483,53517,52909,53517, 3,53782,53703,53785, 3,53783,53667,53789, +46863,53517, 3,53792,53703,53795, 3,53793,53667,53799, 9,53517, +20273,53802, 9617,53802,35187,53517, 375,53808, 4,49712,48747,53813, +37279,53813,19981,53813,24601,53813, 7,53813,21605,53823,53071,53813, +52743,53813,52193,53813,50225,53813, 8306,53813, 545,53813, 695,53813, + 1382,53813, 1374,53813, 1386,53813,51906,53813,53442,53813,53199,53813, +53373,53813,53095,53813,51803,53813, 1369,53856,53391,53856, 9992,53813, +20734,53813,19916,53813,48739,53867,37241,53867, 7947,53867,28205,53813, +24613,53813,25551,53813,53189,53813, 483,53881, 33,53813, 9875,53813, + 265,53886, 241,53887,20501,53813, 265,53892, 241,53893, 1141,53813, + 154,53813, 483,53901, 1447,53813, 331,53813, 1369,53906, 265,53813, + 8165,53910, 9875,53910,20501,53910, 1011,53813, 59,53813, 1369,53920, + 3,53813, 8241,53925, 15,53924, 483,53929,53391,53813,51803,53932, + 1325,53813, 1369,53936, 3,53812,24265,53941,28233,53941,29077,53941, + 9673,53941,19559,53941, 4283,53941,20361,53941, 8251,53941, 3807,53941, + 9967,53941,20713,53941, 4279,53941, 1369,53813, 331,53966, 1325,53966, + 59,53966,51803,53966,18967,53813, 1275,53976,48739,53979,37241,53979, + 7947,53979, 113,53977, 1275,53813,18967,53988,48739,53991, 7947,53991, +37241,53991, 8165,53813, 265,53998,46863,53813,38056,54002,38056,54003, +38057,54002,54007,54009,38057,54003,54005,54013, 15,53813, 3,54017, + 1369,54019, 3,54016, 483,54023, 5,49713, 375,54026,51615,54029, + 1368,54027, 7,54027, 2,54034, 2,54035,32805,54027,31103,54041, +20035,54027, 375,54045, 341,54027,18967,54049,12377,54027, 375,54053, +52915,54027,31103,54057,27021,54027,31103,54061,30091,54027,31103,54065, +31103,54026,27021,54069,52915,54069,18967,54027,47608,54075,46863,54075, + 1011,54078, 1011,54075,46863,54082,53924,54027,53825,54087, 483,54087, +51929,54027, 483,54093,51615,54027, 375,54097, 483,54097, 1369,54026, + 803,54103, 483,54026,53813,54107,10107,54107,51929,54107,51615,54107, + 1275,54026, 1505,54117,18967,54026, 17,54121, 1369,54027,51601,54125, + 2,54026,54078,54129,54075,54129,46863,54132,52541,54129, 1505,54129, + 918,54129,52121,54129,54125,54129, 903,54129, 9,54146, 9,54129, + 903,54150,46863,54129,54075,54154, 3,54026,54033,54159,54037,54159, +53966,54159,12571,54159, 4613,54159,51615,54159, 8337,54159,46863,54173, +52591,54159,53932,54159,53391,54159,53813,54180,53813,54159, 1369,54184, +53391,54184,36773,54159,46863,54191,20103,54159,46863,54195, 1369,54159, +53813,54198, 2,54027, 0,54202,54159,54205,46863,54207, 7,54202, +54159,54211, 265,54203, 9,54215,54159,54203, 9,54219,46863,54219, + 3,54027,48286,54225,54039,54225,54150,54225,52573,54225,52115,54225, +38057,54225,46863,54236,53813,54224,53825,54241, 483,54241, 9,54225, +54129,54246, 483,54225,53813,54251,54154,54225,46863,54225,38057,54256, +54129,54256,54129,54225, 9,54262,46863,54262,10107,54027, 483,54269, +53813,54027, 483,54273, 3,54273, 1369,54277,53391,54277, 3,54272, +53825,54283, 483,54283, 17,54027,20273,54289, 9617,54289, 3,49713, +16722,54295,16530,54294,54297,54299,16723,54295,16531,54294,54303,54305, +16530,54295, 1,54295,35187,54311, 17,54313, 7,54295,16531,54316, +54299,54319,16531,54317,54309,54323, 15,54317,38305,54327, 1,54294, +40705,54331,54329,54331, 17,54331, 7,54294,54333,54339,40704,54339, +54331,54343,49713,54339, 4,54346, 4,54339,49713,54350,54315,54339, + 9,54339,38305,54356,54331,54359,38305,54339, 9,54362,54331,54365, +52489,54295, 9,54369,36527,54295, 375,54373, 341,54295,12377,54295, + 9,54379,16531,54295, 7,54382,54299,54385,37611,54295, 9,54389, + 8321,54295,35927,54295, 9,54395,38155,54295, 9,54399,43503,54295, +44243,54403, 113,54295,38305,54406,40086,54295, 8241,54295,44243,54294, + 11,54415, 1369,54415, 1486,54295,35187,54295,47640,54423,46863,54423, + 903,54426, 903,54423,46863,54430,53480,54295,11731,54295,51615,54295, + 241,54295, 17,54294, 113,54443,38305,54294, 9,54294,37611,54449, +38155,54449,35927,54449,52489,54449, 15,54294, 483,54459, 11,54295, +44243,54463,38305,54295, 113,54466,38057,54295, 7,54471, 375,54471, + 4,54294,54426,54477,54423,54477,46863,54480,52573,54477,54377,54477, +52115,54477,43053,54477,46863,54477,54423,54492, 5,54294,54473,54497, + 6,54497,54471,54501,53966,54497,12571,54497, 4613,54497,51615,54497, + 8337,54497,46863,54513,52591,54497,53932,54497,53813,54497, 1369,54520, +53391,54520,53391,54497,53813,54526,20103,54497,46863,54531,36773,54497, +46863,54535, 1369,54497,53813,54538, 4,54295, 0,54542,54497,54545, +46863,54547, 5,54295,48294,54551,21315,54551,46863,54554,53391,54550, + 1369,54550,46863,54551,21315,54562,53391,54295, 5,54567,53813,54569, + 5,54566, 1369,54295, 9893,54575,52129,54575,54353,54575,54349,54575, +20885,54575,52411,54575,44243,54575, 5,54574, 5,54575,53813,54593, + 2,49713,53227,54597,53262,54597,53355,54597,53358,54597,53298,54597, +53264,54597,53229,54597,53274,54597,53234,54597,49168,54597, 1,54597, + 7,54597, 567,54621,52915,54623, 4,54621,54575,54627,53360,54627, +52915,54627, 483,54632, 483,54627,52915,54636, 9,54621, 1,54596, +36544,54643,35187,54643, 11,54646, 11,54643,35187,54650, 7,54596, +36545,54655,54643,54657,54645,54655,21605,54655,54653,54655,54649,54655, + 15,54655,53270,54597,46863,54670,53231,54597,46863,54674,49169,54597, +54097,54597,53134,54597,53215,54683,53352,54597,53215,54687,53196,54597, +53215,54691, 8311,54597,48884,54596,54617,54697,53731,54597,53881,54597, +54283,54597,54241,54597,54087,54597,36256,54597,53296,54597,53167,54712, +53184,54597,53255,54716,53167,54597,53357,54720,53296,54720,53255,54720, +46863,54726,46863,54720,53255,54730,48885,54597, 9,54734,54697,54737, +54697,54735, 9,54741,35187,54597, 9,54744, 9,54597,48885,54748, +54697,54751,48885,54749,35187,54748, 11,54749,52915,54759,53188,54597, +53215,54763,46863,54765,46863,54762,53215,54769,53813,54763,53139,54597, +53255,54774,44243,54597, 11,54779,54225,54597,53813,54783,51229,54597, + 265,54597,54027,54789,47961,54791,14611,54791, 4899,54791, 375,54791, + 17,54596, 903,54801,51593,54801,54477,54801,54225,54801, 11,54596, +53318,54811,52825,54811,52915,54811, 9,54816, 9,54811,52915,54820, +44243,54811,53255,54597,53139,54826,53184,54826,53167,54826,46863,54832, +46863,54826,53167,54836,53357,54597,53167,54840, 4,54596,51418,54845, +51416,54845,51398,54845,51354,54845,51909,54845, 340,54845,51803,54857, +51873,54845,47974,54845,47589,54845, 8590,54845,14620,54845,12537,54845, +52021,54845,52029,54845,53106,54845, 375,54845,51229,54878,52915,54878, + 0,54845, 6,54885, 7,54845, 265,54888,51803,54891, 265,54889, +51229,54895,52915,54895,47580,54845,51803,54901, 8861,54901, 8495,54845, +47961,54906, 4899,54906,14611,54906,52915,54845, 375,54914,14611,54845, +51229,54918, 8495,54918, 4899,54845,51229,54924, 8495,54924,47961,54845, +51229,54930, 8495,54930, 265,54845, 7,54936,51803,54939,54887,54937, +54886,54936,54943,54945,54887,54936,54886,54937,54949,54951,46863,54936, + 8861,54955,51803,54955,46863,54845, 265,54960,51803,54963, 8861,54963, + 265,54961,51229,54969, 8495,54969,51229,54845, 375,54974,14611,54974, + 4899,54974,47961,54974, 5,54596, 1505,54985, 918,54985,52541,54985, +52121,54985,54125,54985, 903,54985, 9,54996, 9,54985, 903,55000, + 5,54597,54889,55005,52915,55007,53349,55004, 6,55005,54914,55013, +52915,55013,54845,55016,54845,55013,52915,55020, 53,55005, 1471,55005, + 253,55005,52557,55005,53348,55004,53215,55033, 241,55005, 9,55037, +52915,55004,53215,55041,46863,55043,46863,55040,53215,55047,53813,55041, + 17,55005,35187,55053,52915,55005,53357,55057,55011,55057,53296,55057, +53255,55057,46863,55064,46863,55057,53255,55068,46863,55004,52915,55072, +53215,55075,52915,55073,53255,55079,48885,54596,54679,55083, 9,55083, +48884,54597,54755,55089,55086,55089,55083,55089, 9,55094,52915,55088, +53215,55099,52915,55089,53255,55103, 9,55089,55083,55106,53348,54597, + 5,55110,53215,55113, 5,55111,53167,55117,52915,54597,48884,55120, +53215,55123,48884,55121,53139,55127, 5,55121,53139,55131,53184,55131, +53167,55131,46863,55136,46863,55131,53167,55140, 5,55120,53215,55145, +46863,55147,46863,55144,53215,55151,53813,55145,46863,55120, 5,55156, +53215,55159, 5,55157,53167,55163,21605,54597,54027,55167,31103,55169, +46863,54597,53270,55172,53231,55172,53188,55172,53215,55179,53255,55172, +53167,55182,53167,55172,53255,55186, 5,55172,52915,55190,53215,55193, +52915,55191,53255,55197,52915,55172, 5,55200,53215,55203, 5,55201, +53167,55207, 4,49713,51398,55211, 375,55211,51229,55214,53709,55211, +53740,55211,51909,55211,53797,55211,53800,55211, 340,55211,51803,55229, +54339,55210,54575,55233,53774,55211,53742,55211,53711,55211,53750,55211, +53716,55211,54663,55211,53533,55211, 1368,55211,52205,55251,54449,55251, +52809,55251,54295,55251, 9,55259, 7,55211, 265,55263,51229,55265, + 89,55263,52915,55269, 265,55262,51803,55273, 2,55262,52205,55277, +52809,55277,54449,55277,54295,55277, 9,55285, 2,55263,52825,55289, +53318,55289, 9,55289,52915,55294,52915,55289, 9,55298,53746,55211, +46863,55302,53713,55211,46863,55306,31796,55211,25037,55211,25215,55211, +42338,55211,42076,55211,43053,55211,42959,55211,54575,55211,54339,55325, +54786,55211,51360,55211,53780,55211,52751,55211, 8148,55211, 9594,55211, +54377,55211,54439,55211,53758,55211,54700,55211,54826,55211,53286,55211, +53646,55211,53703,55353,53794,55211,53703,55357,53682,55211,53703,55361, +53371,55211, 842,55211, 9377,55367,54591,55211,54421,55211,54561,55211, +53681,55211,53255,55211,54597,55378, 483,55378,53679,55211,54573,55211, +55131,55211,54559,55211,54435,55211,19892,55211,53772,55211,53667,55396, +53672,55211,53731,55400,53667,55211,53799,55404,53772,55404,53731,55404, +46863,55410,46863,55404,53731,55414, 935,55211,20733,55211, 9991,55211, +41941,55211, 483,55424, 9565,55211, 483,55428, 1487,55211,54597,55211, +51229,55434, 53,55435, 1471,55435, 253,55435,53731,55434,53255,55434, +47546,55211, 66,55211, 1369,55451, 241,55211,31103,55454,18967,55211, + 483,55458, 483,55211,42155,55462,41941,55462,51229,55462,53517,55462, + 7971,55462, 9565,55462,53731,55462,53255,55462, 587,55462, 9377,55481, +18967,55462, 587,55463, 9195,55487,52915,55487,53674,55211,53703,55493, +46863,55495, 1369,55493,46863,55492,53703,55501,53391,55493,53649,55211, +53731,55506,31103,55211, 241,55510, 587,55511, 113,55211,46863,55516, +17455,55211,54551,55211, 1369,55523,53391,55523,51229,55211, 375,55528, +54597,55528, 483,55528, 1011,55211, 8165,55537, 9875,55537,20501,55537, + 11,55537, 265,55211, 7,55546,51803,55549,54295,55547,47961,55553, +14611,55553, 4899,55553, 375,55553, 1369,55210,54985,55563,51601,55563, +54129,55563, 587,55210, 9366,55571,54575,55571,53360,55571, 9195,55571, + 483,55578,52915,55571, 483,55582, 483,55571, 9195,55586,52915,55586, +31103,55571,53731,55211,53649,55594,53672,55594,53667,55594,46863,55600, + 483,55594,54597,55594,46863,55594,53667,55608, 587,55211, 9377,55613, + 483,55615, 483,55612, 9377,55619,21605,55211,21526,55622, 6,55623, +21527,55622,55627,55629, 7,55622, 7,55623,55625,55635, 6,55622, +18967,55638,55635,55641,18967,55622, 6,55645,55633,55647, 6,55644, +55635,55651, 1347,55211, 1369,55655,53799,55211,53667,55658, 2,55210, +51418,55663,51416,55663,51398,55663,51354,55663,51909,55663, 340,55663, +51803,55675,51873,55663,47974,55663,47589,55663, 8590,55663,14620,55663, +12537,55663,52021,55663,52029,55663,53106,55663, 375,55663,51229,55696, +52915,55696, 0,55663, 6,55703, 7,55663, 265,55706,51803,55709, + 265,55707,51229,55713,52915,55713,47580,55663,51803,55719, 8861,55719, + 8495,55663,47961,55724, 4899,55724,14611,55724,52915,55663, 375,55732, +14611,55663,51229,55736, 8495,55736, 4899,55663,51229,55742, 8495,55742, +47961,55663,51229,55748, 8495,55748, 265,55663, 7,55754,51803,55757, +55705,55755,55704,55754,55761,55763,55705,55754,55704,55755,55767,55769, +46863,55754, 8861,55773,51803,55773,46863,55663, 265,55778,51803,55781, + 8861,55781, 265,55779,51229,55787, 8495,55787,51229,55663, 375,55792, +14611,55792, 4899,55792,47961,55792, 3,55210,54801,55803,52573,55803, +52115,55803,43053,55803,46863,55803, 2,55211, 7,55814,52205,55817, +52809,55817,54449,55817,54295,55817, 9,55825,54295,55815,54501,55829, + 7,55829,54497,55833, 375,55829, 3,55211,55707,55839,52915,55841, +55706,55839,53793,55838,55779,55839, 6,55839,55732,55851,52915,55851, +55663,55854,55663,55851,52915,55858, 0,55851,55829,55851, 0,55850, +55663,55867, 0,55839, 6,55870,55663,55873, 0,55838,49713,55838, +55845,55879, 1,55838,55868,55883,55874,55883,55867,55883,55663,55888, +55873,55883,55663,55892,55849,55883,55663,55883,55867,55898,55873,55898, +46862,55839,55898,55905,55883,55905,55663,55908,55663,55905,55883,55912, + 1,55839,55863,55917,55663,55919, 7,55839,55663,55922,55879,55925, +55879,55923,55663,55929,52591,55839,53792,55838,53703,55935,43027,55839, +43837,55839,39747,55839,53517,55838,53703,55945,46863,55947, 1369,55945, +46863,55944,53703,55953,53391,55945, 1369,55839,18967,55959, 11,55838, + 1369,55963,18967,55839,46863,55967, 11,55839,46863,55971,53517,55839, +53799,55975,55847,55975,53772,55975,53731,55975,46863,55982,46863,55975, +53731,55986,55778,55839,55877,55991,46863,55839,55877,55995,55663,55997, +55663,55994,55877,56001,55663,55839, 7,56004,55879,56007,46863,56004, +55877,56011,46863,55838,53517,56014,53703,56017,53517,56015,53731,56021, +49204,55211,53517,56024,53703,56027,53517,56025,53731,56031,53792,55211, + 3,56034,53703,56037, 3,56035,53667,56041, 7971,55211, 483,56044, +42155,55211, 483,56048,53517,55211, 483,56052,49204,56052,53703,56057, +49204,56053,53649,56061, 3,56053,53649,56065,53672,56065,53667,56065, +46863,56070, 483,56065,54597,56065,46863,56065,53667,56078, 3,56052, +53703,56083,46863,56085, 1369,56083,46863,56082,53703,56091,53391,56083, +46863,56052, 3,56096,53703,56099, 3,56097,53667,56103, 11,55211, + 3,56106, 1369,56109, 3,56107, 483,56113,46863,55211,53746,56116, +53713,56116,53674,56116,53703,56123,53731,56116,53667,56126,53667,56116, +53731,56130, 113,56116, 3,56116,53517,56136,53703,56139,53517,56137, +53731,56143,53517,56116, 3,56146,53703,56149, 3,56147,53667,56153, +46863,49713,47982,56156,47983,56157,56159,56161,47983,56156,47982,56157, +56165,56167,49588,56156,49589,56157,56171,56173,49670,56156,49671,56157, +56177,56179,49589,56156,49588,56157,56183,56185,49671,56156,49670,56157, +56189,56191, 8453,56156, 273,56156,21522,56156,38266,56156, 1516,56156, + 948,56156,20239,56156,37095,56156, 1477,56156, 281,56156,49617,56156, +49616,56157,56215,56217,49699,56156,49698,56157,56221,56223,49617,56157, +49616,56156,56227,56229,49699,56157,49698,56156,56233,56235, 1216,56156, + 412,56156,12377,56156, 375,56156, 510,56156,38057,56156, 903,56248, + 165,56156, 903,56252,21315,56156, 1011,56256, 1505,56156, 1011,56260, + 413,56157,50785,56265,56241,56265, 1217,56157,56239,56271, 1216,56157, + 413,56156, 412,56157,56277,56279, 1217,56156,56275,56283, 264,56157, +51777,56287,50908,56287,50785,56287, 241,56292, 241,56287,50785,56296, + 375,56287, 264,56156,50207,56303,51765,56303,51677,56303,51615,56303, + 241,56311, 341,56303, 1011,56156, 1505,56316,21315,56316, 903,56156, + 165,56322,38057,56322, 483,56156, 9,56328, 9,56156, 483,56332, + 5,56157, 4,56156,56337,56339,46863,56340, 2,56343, 2,56342, +49515,56340,49514,56340, 2,56341,56349,56353, 3,56341,56347,56357, +56351,56357, 2,56340,46863,56362,56357,56365,56357,56363, 3,56340, +56345,56371,56353,56371, 3,56157, 375,56377, 2,56156,56337,56381, + 1,56383, 0,56382,56385,56387, 0,56383, 1,56382,56391,56393, +56377,56381,46863,56396, 4,56399, 4,56398,49631,56396,49630,56396, + 4,56397,56405,56409, 5,56397,56403,56413,56407,56413, 4,56396, +46863,56418,56413,56421,56413,56419, 5,56396,56401,56427,56409,56427, + 2,56157, 3,56156,56337,56435, 7,56437, 6,56436,56439,56441, + 6,56437, 7,56436,56445,56447,56433,56435,46863,56451, 4,56452, + 4,56453,49631,56451,49630,56451, 4,56451,46863,56462, 5,56451, +56457,56467, 4,56450,56467,56471,56459,56471, 5,56450,56465,56477, +56455,56477,56463,56477,56461,56477, 4,56157,56435,56487, 1,56489, + 0,56488,56491,56493, 0,56489, 1,56488,56497,56499,56381,56487, + 7,56503, 6,56502,56505,56507, 6,56503, 7,56502,56511,56513, + 5,56156,56487,56517,46863,56519, 2,56520, 2,56521,49515,56519, +49514,56519, 2,56519,46863,56530, 3,56519,56525,56535, 2,56518, +56535,56539,56527,56539, 3,56518,56533,56545,56523,56545,56531,56545, +56529,56545, 1, 2,11709,56555,11632,56555,11035,56555,10468,56555, +17775,56555,11788,56555,12226,56555,11816,56555,11770,56555,44558,56555, +42181,56555,44243,56576,44438,56555,10856,56555, 3447,56555, 375,56584, + 3448,56555,11705,56555,11033,56555,10516,56555,17773,56555,18735,56555, +10427,56555,10831,56600,10836,56555,10855,56555,16623,56555,16711,56555, + 9533,56610,16718,56555, 3555,56555, 5882,56555, 9261,56555, 483,56621, + 3699,56555, 15,56625, 6,56624,56627,56629, 14,56625, 7,56624, +56633,56635, 1999,56555, 15,56639, 6,56638,56641,56643, 14,56639, + 7,56638,56647,56649,29450,56555,29731,56653,29659,56653,28791,56653, +29041,56653,38067,56555, 5,56663,38185,56665,42155,56554,44243,56669, +42471,56670,44966,56669,42471,56669,44243,56676, 1471,56554,36639,56681, +15390,56555,15383,56685,28715,56555,21527,56689,29229,56691, 7,56689, +29759,56695, 7,56688,28791,56699,29041,56699,29731,56699,29659,56699, + 1005,56555,16877,56554,16893,56711, 9925,56555, 1369,56715, 9927,56717, +35336,56555, 989,56721,35278,56555, 1177,56725, 987,56555,35187,56728, + 989,56731,36563,56554,36639,56735, 671,56554,36597,56554,36639,56741, + 1418,56554, 1,56745, 4,56746, 4,56745, 1,56750, 147,56555, +35187,56754, 53,56757,17637,56555, 587,56760,10107,56763,35316,56555, + 1471,56767,35330,56555, 53,56771,17638,56555,10107,56775, 1489,56555, +35187,56778, 1471,56781, 1179,56555,35187,56784, 1177,56787,37229,56555, +35187,56790,37223,56793, 9441,56555, 587,56796, 9439,56799,37230,56555, +37223,56803, 9442,56555, 9439,56807,45432,56555,42435,56811, 30,56555, +11731,56814,45433,56555,56669,56819,43099,56555,52259,56555, 483,56825, +44742,56555,44904,56555,52613,56555,52383,56555,52497,56555,39231,56555, +40447,56555,39083,56555,38797,56555,39019,56555,39301,56555,39429,56555, +39305,56555, 386,56555, 347,56555,54492,56555,45508,56555,56116,56555, +55812,56555,40987,56555,52909,56555,51598,56555,50419,56555,56332,56555, +52836,56555,52366,56555,36639,56555, 1471,56881,36563,56881,36597,56881, + 181,56555,11731,56888,50579,56555,52319,56555,52323,56555,54436,56555, +54406,56555,52532,56555,52514,56555,55520,56555,44930,56555,39317,56555, +51141,56555,40123,56555,39228,56555,40676,56555,47366,56555,40682,56555, +52599,56555,50655,56555,52531,56555,36538,56555,36048,56555,37594,56555, +42918,56555,40922,56555,39292,56555,11111,56555,11113,56555,11187,56555, +17508,56555,17180,56555, 3280,56555, 3574,56555, 3568,56555,12216,56555, + 25,56958,11613,56555, 25,56962,48406,56555,48400,56555,48500,56555, +43292,56555,47534,56555,17494,56555,39065,56555,48961,56555,49162,56555, +17496,56555,11179,56555,47892,56555,11546,56555,11207,56555, 5878,56555, +52446,56555,35506,56555,39035,56555,40087,56555, 9,57003,10513,56555, + 9,57006,36102,56555, 253,57011, 53,57011, 117,57011, 1471,57011, + 7968,56555,53813,57021,10107,57021,11067,57021,37282,56555,53813,57029, +37417,57029,10107,57029,35652,56555, 253,57037, 1471,57037, 809,57037, + 53,57037,38293,56555,53813,57047,37417,57047,38275,57047,10107,57047, + 1397,56555,35187,57056,52439,56555, 265,57060,40127,56555,43318,56555, +48750,56555,53813,57069,10107,57069,36100,56555, 253,57075, 53,57075, + 1471,57075, 9404,56555, 483,57083, 8053,56555, 9,57087,10465,56555, + 9,57090,11936,56555,10119,56555,10185,56555,53885,56555,10117,56555, +45490,56555, 33,57105, 8212,56555, 9,57109,11812,56555, 9,57112, +53899,56555, 6719,56555, 11,57119, 5,57120, 6,57119, 5,57124, + 5,57119, 6,57128, 6,57129, 7,57119,57133,57135, 15,57119, + 6,57118,57139,57141, 14,57119, 7,57118,57131,57147,57127,57147, +57123,57147,57145,57147, 6787,56555, 5,57157, 4,57157, 12,57157, + 13,57156,57163,57165, 13,57157, 12,57156,57169,57171, 5,57156, +57161,57175, 4,57156,57159,57179,10831,56555, 375,57182,44243,57182, +10427,57182, 9,57183,11529,56555,46863,57192, 483,57192,17640,56555, +39226,56555,48572,56555,47410,56555,40568,56555,47374,56555,47674,56555, +17656,56555,47676,56555,47634,56555,48112,56555,47412,56555, 5814,56555, + 918,56555,36256,56555,46863,57226,48466,56555,49713,57230,35187,57230, + 11,57231,47608,56555, 903,57238,52756,56555,46863,57242,48620,56555, + 247,56555,46863,57248, 1419,56555,56749,57253,56753,57253,25519,57253, + 1841,57253, 1883,57253,22679,57253, 5,57253,22677,57267,14065,57253, + 5175,57253,40565,56555, 587,57274, 922,56555,51593,56555,46863,57280, +47640,56555, 11,57285, 1011,57284, 11,57284,35718,56555, 9439,57293, +37223,57293, 9381,57293,37157,57293,35877,57293,35881,57293, 9383,57293, +37163,57293,35883,57293, 17,57293,37145,57313, 9377,57313,35867,57313, +51051,56555, 375,57321,50959,56555, 9,57325,39205,56555, 10,57329, + 10,57328, 11,57329,57333,57335, 1011,57328, 11,57328,57331,57341, +48402,56555, 9,57344,48560,56555, 903,57348,36544,56555, 6,57353, +36661,57355,36675,57353, 8067,57353, 7979,57353, 7981,57353,39747,57353, +43837,57353,43027,57353, 1369,57353, 7971,57373, 934,56555,46863,57376, + 668,56555, 5,57381,22605,57383,22615,57381, 3135,57381, 2009,57381, +14065,57381, 5175,57381,53905,56555,55432,56555,10303,56555,42661,56555, + 25,56555,11613,57404,12216,57404, 9,57404,11731,57410,35187,57404, + 253,57415, 53,57415, 117,57415, 1471,57415,11731,57404, 9,57424, + 8165,56555, 67,57428, 9,57431, 7947,56555, 587,57434,53813,57437, +10107,57437,11067,57437,17049,56555,46863,57444, 165,56555,43215,57448, + 113,56555,54295,57452, 767,56555, 483,57457, 9377,57459, 9377,57456, + 483,57463, 803,56555,17455,57466, 375,56555,10831,57470, 3447,57470, + 305,57470,17125,57470, 510,56555, 11,56555, 33,57483,44243,57485, +44243,57482, 33,57489,39205,57482,47640,57482,46863,57482, 903,57496, +35187,57482,43027,57501,43837,57501, 8067,57501, 7979,57501,39747,57501, + 7981,57501, 1369,57501, 7971,57515, 903,57482,46863,57518, 9,56555, +10465,57522,11812,57522,10513,57522, 25,57522,11731,57530,56156,57522, +40675,57522, 3565,57522, 3573,57522, 3273,57522,11731,57522, 25,57544, +48402,57522,17455,57522, 5843,57522, 11,57523,46863,57555,49713,57522, +46863,57558, 903,57522,35187,57522,46863,57564,46863,57522,49713,57568, +35187,57568, 11,57569, 587,57522, 5175,57577,14065,57577, 3135,57577, + 2009,57577, 483,57522,55839,56555, 483,57589, 5771,56555, 903,57592, + 6705,56555, 1369,57597, 6707,57599, 6711,57599, 6715,57599, 3697,56555, + 16,57607, 16,57606, 17,57607,57611,57613, 17,57606,57609,57617, + 3709,56555, 8075,56555, 9,57623, 3273,56555, 9,57626, 3423,56555, + 16,57631, 16,57630, 17,57631,57635,57637, 17,57630,57633,57641, + 3661,56555, 16,57645, 16,57644, 17,57645,57649,57651, 17,57644, +57647,57655, 3681,56555, 3357,56555,53675,56555, 9,57663,42379,56555, + 9,57667, 3573,56555, 9,57670, 3565,56555, 9,57674,52878,56555, +15436,56555, 375,57681,54550,56555,17232,56555,38305,57686, 4935,56555, + 6,57691, 5,57692, 7,57691, 5,57691, 6,57698, 6,57699, +57697,57703, 6,57690, 15,57691,57707,57709, 7,57690,57695,57713, +57701,57713, 14,57691,57713,57719,55803,56555,46863,57722,16127,56555, + 6,57727, 5,57728, 7,57727, 5,57727, 6,57734, 6,57735, +57733,57739, 6,57726, 15,57727,57743,57745, 7,57726,57731,57749, +57737,57749, 14,57727,57749,57755,54477,56555,46863,57758,49155,56555, + 483,57762, 5843,56555, 955,57766, 9,57766, 5313,56555, 9802,56555, +48736,56555, 9434,56555, 483,57779,15309,56555, 413,57782,15383,57785, + 413,57783,15335,57789, 8,56554, 4,57793, 1,57794,57381,57797, +57577,57797, 1,57793, 4,57802,57381,57805,57577,57805, 10,56554, + 7,57811, 2,57812,57353,57815,57501,57815, 2,57811, 7,57820, +57353,57823,57501,57823,57515,57811,57373,57811, 1368,57811,57501,57833, +57353,57833, 3867,57811, 8277,57811, 3997,57811, 4067,57811, 9459,57811, + 8953,57811,57483,57811, 9,57811, 14,56555,38881,57855, 11,56554, +44778,57859,44243,57859, 25,57862,47640,57859, 25,57859,44243,57868, +48466,57859, 903,57859,46863,57874,46863,57859, 903,57878, 9,57878, + 9,57859,46863,57884, 9,56554,40903,57889,40053,57889,43307,57889, + 5019,57889,12361,57889, 16,56555,19625,57901,21105,57901,21549,57901, +17591,57901, 17,56554,36639,57911, 10,56555,57859,57915,11731,56555, + 30,57918, 181,57918,54295,57918, 9,57918, 25,57926, 145,57918, + 25,57918, 9,57932, 67,56555, 9,57937, 8165,57939, 8165,57936, + 9,57943,17635,56555, 155,57946, 903,57946, 145,56555,11731,57952, +17695,56555, 1369,57957, 7971,57959,53517,57959,17053,57959,17699,57959, +42155,57959, 155,56555,17635,57970,10305,56555,42699,56555,10307,56555, + 566,56555,53813,57981,10107,57981, 256,56555,42810,56555,17125,57988, + 1170,56555, 629,56555, 1413,56555,37408,56555,25793,57999,41019,57999, + 8495,57999, 265,57998, 1346,56555,48884,56555,27021,58011,52915,58011, + 9195,58011,20763,58011, 340,56555, 331,58021,35187,58020,38270,56555, + 766,56555,25519,58029, 802,56555, 9366,58033, 9195,58033, 483,58036, + 483,58033, 9195,58040,31103,58033,42729,56555, 257,56555,44243,58048, + 1487,56555,55211,58052,44243,56555,10831,58056,42181,58056,42155,58057, +42471,58063,42155,58056,42435,58067, 9533,58056,37145,58056, 11,58057, + 25,58075,35187,58056,17125,58056, 11,58056, 33,58083,49713,58056, + 257,58056,55211,56555,46863,58090,17455,58090, 1487,58090, 1197,56555, + 4,58099, 5,58098,58101,58103, 5,58099, 4,58098,58107,58109, + 1505,56555,45002,56555,42155,56555,42435,58117,44243,58119,44243,58116, +42435,58123, 305,56555, 375,58126,35187,58126, 253,58131, 1471,58131, + 53,58131, 713,56555,35187,58138, 253,58141, 1471,58141, 809,58141, + 53,58141,37241,56555, 587,58150,53813,58153,37417,58153,10107,58153, + 955,56555, 5843,58160,48739,56555, 587,58164,53813,58167,10107,58167, +40461,56555, 9,58173,52501,56555,35187,58176, 241,58176, 9801,56555, + 17,58182, 4,58183,58185,58187, 5,58183,57901,58191, 4,58182, + 7,58194,58191,58197, 5,58182,48735,56555, 17,58202, 4,58203, +58205,58207, 5,58203,57901,58211, 4,58202, 7,58214,58211,58217, + 5,58202, 9533,56555,16711,58222,44243,58222,37145,56555,44243,58228, + 8861,56555, 5,58233, 6,58235, 6,58234, 14,58233, 15,58233, + 6,58233, 5,58244, 7,58233,58237,58249, 6,58232,58243,58253, + 7,58232,58239,58257,58247,58257,58241,58257, 9377,56555, 767,58264, + 483,58267, 4,58264, 483,58271, 1217,56555, 483,58275, 413,56555, +15309,58278,15383,58281,15309,58279,15363,58285,46863,58278, 412,56555, + 483,58291, 1216,56555,46863,58294,56156,56555, 9,58298, 1011,56555, +39205,58302,47640,58302,46863,58302, 903,58308, 7,58302, 903,58302, +46863,58314,43215,58302, 7,58319,38305,56555,17232,58322, 7,58322, +17125,58326,17125,58322, 7,58330,49713,56555,48466,58334, 9,58334, +46863,58338,44243,58334,46863,58334, 9,58344, 241,56555,52501,58348, + 7,58348, 7,58349, 265,58355, 265,58348, 483,58359, 483,56555, +40675,58362,43215,58362,49155,58362,11529,58362, 903,58362, 9,58362, + 5,58362,53813,58377,10107,58377, 5,58363,55211,58383,40675,56555, + 7,58387, 9,58386, 483,58386,46863,58386,35187,56555,37229,58396, +37223,58399, 1177,58397, 1179,58403, 989,58397, 987,58407, 1179,58396, + 1177,58411, 987,58396, 989,58415, 1489,58396, 1471,58419, 147,58396, + 53,58423, 117,58397, 25,58427, 809,58397, 713,58431, 2,58396, + 7,58435, 2,58436,58397,58439, 5,58436,58441,58443, 5,58435, + 7,58446, 10,58435, 4,58396, 7,58453, 4,58454,58397,58457, + 3,58454,58459,58461, 3,58453, 7,58464, 586,58453, 1368,58396, + 7,58471, 5,58472, 5,58471, 7,58476, 10,58471, 16,58396, + 7,58483, 3,58484, 3,58483, 7,58488, 586,58483,44243,58396, +52501,58396, 340,58396,48466,58396, 1397,58396, 25,58396, 1471,58505, + 253,58505, 53,58505, 117,58505, 713,58396, 53,58515, 253,58515, + 1471,58515, 809,58515, 53,58397, 147,58525, 305,58525, 713,58525, + 25,58525, 1471,58397, 1489,58535, 305,58535, 25,58535, 713,58535, + 305,58396, 253,58545, 1471,58545, 53,58545, 253,58397, 305,58553, + 25,58553, 713,58553, 9,58396,46863,58560, 1369,58397, 9891,58565, + 9927,58565,58475,58565,58479,58565,58443,58565,58449,58565, 4,58565, + 9895,58565,19687,58565,20843,58565,21127,58565,58451,58565,58481,58565, + 11,58565, 9875,58593,58435,58593,58471,58593, 17,58397,10111,58601, +10159,58601,58487,58601,58491,58601,36729,58601,58461,58601,58467,58601, + 2,58601,10113,58601,58469,58601,58493,58601, 587,58601,10107,58625, +58453,58625,58483,58625,46863,58396, 9,58632, 11,58396,57815,58637, +57823,58637, 8067,58637, 7979,58637, 3,58637,58601,58647,58617,58637, + 7981,58637,39747,58637,43027,58637,43837,58637,57833,58637, 1369,58637, + 7971,58663,57811,58663, 587,58396,35877,58669,35881,58669, 9439,58669, + 9381,58669, 5,58669,58565,58679,58579,58669,37223,58669,37157,58669, + 9383,58669,37163,58669,35883,58669, 17,58669, 9377,58695,37145,58695, +35867,58695, 6,58396, 7,58396,25793,58705,41019,58705, 8495,58705, + 265,58704, 6,58397,36661,58715,58705,58715,57999,58715, 7,58397, +58703,58723,58027,58723, 265,58396, 6,58728, 7,58728, 6,58729, +58733,58735, 7,58729,58731,58739, 903,56555,17455,58742,17635,58742, +47608,58742, 5771,58742,48560,58742, 11,58743,46863,58755, 9,58742, + 483,58742,46863,58742, 11,58763, 1011,58762, 11,58762, 11,58742, +46863,58770, 7,58743, 8165,58775, 1011,58742,46863,58778,46863,56555, +21036,58782,21036,58783,21037,58782,58787,58789,21037,58783,58785,58793, +54477,58782,55211,58782,55803,58782,52756,58782,51593,58782,40675,58782, +43215,58782,36256,58782,11529,58782, 934,58782, 247,58782, 1216,58782, + 413,58782,17049,58782, 11,58783, 903,58825, 9,58825, 9,58782, +49713,58830,35187,58830, 11,58831, 1011,58782, 903,58838,35187,58782, + 9,58842, 903,58782, 11,58847, 1011,58846, 11,58846, 11,58782, + 903,58854, 5,58782,27021,58859,52915,58859, 9195,58859,20763,58859, +49713,58782, 9,58868, 1275,56555, 17,58872, 4,58872, 7,58876, + 5,58872, 4,58873,58875,58883, 5,58873,58879,58887,57901,58887, + 265,56555,37408,58892,52439,58892, 7,58892, 331,58899,35187,58898, + 7,58893, 375,58905, 241,58892, 483,58909,38305,58893, 375,58913, +35187,58892, 6,58916, 7,58916, 6,58917,58921,58923, 7,58917, +58919,58927, 587,56555, 9441,58930, 9439,58933,17637,58930,10107,58937, +37417,58931,37241,58941,11067,58931, 7947,58945, 7,58930, 4,58949, + 7,58950,58931,58953, 0,58950,58955,58957, 0,58949, 4,58960, +35186,58949, 1,58930, 4,58967, 1,58968,58931,58971, 6,58968, +58973,58975, 6,58967, 4,58978, 8,58967, 16,58930, 4,58985, + 0,58986, 0,58985, 4,58990,35186,58985,22807,58931,37241,58930, +10107,58999,53813,58999,37417,58999, 7947,58930,53813,59007,10107,59007, +11067,59007,10107,58931,17637,59015,48739,59015,37241,59015, 7947,59015, +48739,58930,53813,59025,10107,59025,53813,58931,48739,59031,37241,59031, + 7947,59031,40565,58930, 17,58931, 1985,59041, 3721,59041,58989,59041, +58993,59041, 5299,59041,58957,59041,58963,59041, 1,59041,35233,59041, +35917,59041, 4861,59041,17563,59041,58965,59041,58995,59041,35187,59041, + 53,59071,58949,59071,58985,59071,35187,58930,35881,59079,35877,59079, +37223,59079,37157,59079, 6,59079, 9439,59079, 9381,59079,37163,59079, + 9383,59079,35883,59079, 17,59079,37145,59101, 9377,59101,35867,59101, + 9,58930,57797,59109,57805,59109, 3135,59109, 2009,59109, 0,59109, +59041,59119,59057,59109, 5175,59109,14065,59109, 4,58930, 9366,59129, + 9195,59129, 483,59132, 483,59129, 9195,59136,31103,59129, 5,58930, +25519,59143, 5,58931,25503,59147,24623,59147,30387,59147,58565,59147, +22605,59147,36526,56555, 6,59158, 7,59158, 6,59159,59163,59165, + 7,59159,59161,59169,40920,56555, 7,59172,43400,56555, 7,59177, +16065,56555, 5,59181, 7,59182, 7,59183,56555,59186, 6,59182, +59189,59191, 6,59183,56555,59183, 7,59196,59191,59199, 7,59197, +59195,59203,15029,56555, 5,59206, 6,59209, 6,59208, 14,59206, + 15,59206, 6,59206, 5,59218, 7,59206,59211,59223, 375,59223, + 6,59207,59217,59229, 7,59207,59221,59233,59213,59233, 59,59233, +59215,59233, 331,59233, 1325,59233, 265,59233,43215,56555, 9,59249, + 483,59248,46863,59248, 165,59248, 1011,59248, 7,59259,17125,56555, + 4,59262, 7,59265, 1011,59266, 1011,59265, 7,59270, 7,59271, + 1170,59265, 5,59263,57993,59279,58313,59279,17129,59279,42811,59263, +42811,59262,44243,59262,42810,59262,59287,59293,42810,59263,59289,59297, + 375,59262, 6,59262,59269,59303,59273,59303,59277,59303, 7,59262, +38305,59310, 6,59263,59275,59315,59311,59315, 7,59263,59303,59321, +38305,59262, 7,59324,54295,56555,11731,59328, 113,59328, 5,59328, + 5,59329,57901,59337,17455,56555, 7,59341, 4,59342, 4,59343, + 16,59341, 17,59341,55211,59340, 803,59340, 903,59340, 9,59340, + 4,59340,59351,59361, 5,59340,59345,59365,59349,59365, 4,59341, + 7,59370,59365,59373, 5,59341,59347,59377, 4,56554,26454,59381, +26375,59381, 8672,59381, 8743,59381,41692,59381,41607,59381, 8770,59381, + 8729,59381, 3795,59381,47953,59381,48062,59381,47961,59381,48009,59404, +48009,59381,47961,59408,26219,59381,26415,59412,41417,59381,41653,59416, +44832,59381,31770,59381, 8757,59381, 8647,59424,41653,59381,41417,59428, +26415,59381,26219,59432, 8647,59381, 305,59436, 8757,59436, 8605,59381, +47580,59381,47933,59445, 8684,59381, 8717,59449, 8916,59381,44243,59381, + 483,59454,41502,59381,41559,59459, 340,59381, 8717,59463, 3785,59463, + 8495,59463, 375,59381, 8861,59470,46863,59470,47488,59381,26292,59381, +26331,59479, 9,59381,31103,59482, 305,59381, 8647,59486, 7,59381, + 1,59491, 264,59492, 264,59493,25793,59491,26415,59499,41019,59491, +41653,59503, 8495,59491, 305,59507, 8757,59507, 8495,59490, 8717,59513, +41019,59490,41559,59517, 265,59491,59497,59521, 8861,59521,46863,59521, +25793,59490,26331,59529, 265,59490, 8717,59533,59495,59533, 3785,59533, + 8495,59533,31103,59381, 9,59542, 483,59381,44243,59546,46863,59381, + 265,59551,48009,59553, 265,59550,47933,59557, 375,59550,41019,59381, + 7,59563,41417,59565, 7,59562,41559,59569, 265,59381,46863,59573, +47961,59575,46863,59572,47933,59579, 7,59573, 8647,59583, 7,59572, + 8717,59587, 3785,59587, 8495,59587,25793,59381, 7,59595,26219,59597, + 7,59594,26331,59601, 8495,59381, 7,59604, 8717,59607, 7,59605, + 8647,59611, 8861,59381, 375,59614, 5,56554,26777,59619, 9741,59619, + 9745,59619,26781,59619,30349,59619,26857,59619,26933,59619, 2,59619, + 7,59634,57353,59637,57501,59637,58637,59637, 6,59635, 9777,59619, + 1368,59619,57501,59649,57353,59649,58637,59649,57515,59619,57373,59619, +58663,59619, 9771,59619,40077,59619,31598,59619,55462,59619,50733,59619, +37519,59619,35690,59619, 8982,59619,55211,59619, 483,59678, 668,59619, + 9731,59683,26625,59683, 1419,59619, 9731,59689,26625,59689, 17,59619, + 8861,59694, 9,59619, 587,59698, 9731,59701,26625,59701, 375,59619, +35187,59706, 6,59619, 7,59619, 5,59713, 2,59712,57353,59717, +57501,59717,58637,59717, 5,59712,58396,59725,59717,59727,35187,59725, +56555,59730,59717,59733,56555,59725,35187,59736,59717,59739, 7,59618, + 3867,59743, 8277,59743, 3997,59743, 4067,59743, 9459,59743, 8953,59743, +31103,59619,26625,59756, 483,59619,55211,59760, 587,59619, 9,59764, + 9731,59767,26625,59767,35187,59619, 375,59772,26625,59619,31103,59776, + 8861,59619, 7,59781, 17,59780, 6,56554,36633,59787,36627,59787, + 1,59787, 4,59792,57253,59795,57381,59795,57577,59795,59109,59795, + 5,59792,38304,59787,39987,59787,36544,59787, 9875,59811,20501,59811, + 11,59787,35187,59816,20501,59819, 9875,59819, 5,59787, 1,59824, + 4,59787, 6,59829, 1369,59831,56555,59833, 1,59828,57253,59837, +57381,59837,57577,59837,59109,59837,59835,59837, 6,59828,58930,59849, +59837,59851, 587,59849,56555,59854,59837,59857,56555,59849, 587,59860, +59837,59863,35187,59787, 11,59866,20501,59869, 9875,59869, 7,56554, + 4904,59875,17586,59875,17609,59875,40685,59875,40039,59875,42991,59875, + 9484,59875, 272,59875, 1476,59875, 280,59875, 949,59875, 1517,59875, + 1197,59875, 4903,59875, 9,59902,17579,59875, 9,59906, 11,59875, + 9377,59910, 9,59875, 4903,59914,17579,59914, 253,59875, 265,59920, + 53,59875, 265,59924, 1471,59875, 265,59928, 5,59874, 3867,59933, + 8277,59933, 4067,59933, 3997,59933, 8953,59933, 9459,59933, 265,59875, + 253,59946, 1471,59946, 53,59946, 9377,59875, 11,59954, 5,59955, + 7,56555,59826,59960,59827,59961,59963,59965,59827,59960,59826,59961, +59969,59971,59804,59960,59805,59961,59975,59977,59805,59960,59804,59961, +59981,59983,21036,59960,14072,59960,14073,59960,14072,59961,59991,59993, +59183,59960,59191,59997,59183,59961,59185,60001, 4970,59960, 4971,59960, + 4970,59961,60007,60009,16169,59961, 9617,60013,39786,59961,59807,59961, +59806,59961,28715,59960,28791,60023,29731,60023,29659,60023,29041,60023, +21036,59961,21037,59960,60033,60035,38304,59961,59787,60038, 483,60038, +38304,59960,60019,60045,59787,60045, 483,60045,18967,59961, 5,60053, + 5,60052, 2,59961, 0,60059,56555,60061, 5,60063,59961,60065, + 7,60064,60067,60069,59960,60065, 6,60064,60073,60075, 1,59961, + 3,60079, 5,60081,56555,60082,56555,60081, 5,60086, 5,60087, + 1011,60079,56555,60093, 5,60079, 1,59960,21036,60099, 3,60099, +56555,60103, 5,60105, 5,60104, 5,60103,56555,60110, 5,60099, +18967,60114,18967,60099, 5,60118, 5,60119, 2,59960,59811,60125, +36545,60125,59787,60129,59819,60125,59869,60125, 15,60125,29659,59961, +29077,60139,39787,59961,60045,60143,32103,59961,41746,59961,26106,59961, + 8800,59961,36526,59960,40920,59960, 1163,59961,41019,59961, 11,60160, +35187,60161,59619,59961, 4971,59961,60005,60169,14073,59961,59989,60173, + 4555,59961, 559,59961, 39,59961, 8495,59961,35187,60183, 11,60182, +15029,59960, 375,60189,17125,59960,38305,60192, 11,59961,41019,60196, +25793,60196, 8495,60196, 265,59961, 3447,60205,10831,60205, 305,60205, +17125,60205,11731,60205, 567,59961,46863,60217, 15,59961, 3651,60221, + 1993,60221, 4903,60221,17579,60221, 241,59960,38305,59960,60017,60233, +60021,60233,60041,60233,60043,60233,60039,60233,59787,60243, 483,60243, +17125,60232, 1011,59960,59279,60251,21037,59961,59987,60255, 11,60255, +28715,59961,29533,60261,20273,60261, 9617,60261,35187,59960,25793,60269, +41019,60269, 8495,60269,58715,60269, 265,60268, 265,59960, 331,60281, +35187,60280,38305,59961,37845,60287,37844,60286,60289,60291,37844,60287, +37845,60286,60295,60297,60048,60287,59787,60287,60045,60302,60050,60287, +60045,60287,59787,60308, 483,60308, 483,60287,60045,60314, 1011,59961, +25793,59961,35187,60321, 11,60320, 4,59960,60091,60327,60107,60327, +60033,60327,60101,60327,59337,60327,58191,60327,58211,60327,60057,60327, +60117,60327,60121,60327,21549,60327,21105,60327,19625,60327,58887,60327, +17591,60327, 5,59960, 1,60359, 3,60361,60205,60363,60255,60359, + 4,59961,60085,60369,60089,60369,60113,60369,60109,60369,57685,60369, +59335,60369,58201,60369,58221,60369,57775,60369,57777,60369,60095,60369, +60055,60369,60123,60369,31103,60369,21575,60369,58881,60369,58009,60369, +17579,60369, 4903,60369,48408,60369,46863,60369, 483,60410, 483,60369, +46863,60414, 5,59961,18967,60418,60327,60421, 1368,60419, 2,60419, + 7,60426, 7,60419, 2,60430,59787,59961,38304,60435,60287,60437, +38304,60434,60233,60441, 483,59961,38304,60445,60287,60447,38304,60444, +60233,60451, 5,56555,60081,60454,60369,60457,60103,60454,60369,60461, + 1,60455, 3,60464, 1,60454,59491,60469,59490,60469,59381,60469, + 7,60474, 7,60475, 5,60469,59961,60481, 6,60468,60473,60485, +60477,60485, 7,60468,60471,60491,59381,60491, 6,60469,59381,60497, +60491,60498,60479,60497,60494,60497,60491,60497,59381,60506, 7,60469, +59381,60510,60485,60513,60485,60511,59381,60517, 2,60454,60261,60521, +60483,60521,53813,60455, 483,60527,52915,60455,46863,60531,59875,60455, + 9801,60454,60369,60537,48735,60454,60369,60541,10107,60455, 483,60545, + 9195,60455,46863,60549,54295,60454,60369,60553, 587,60455,17455,60557, +11731,60557, 9,60455, 8861,60563, 17,60455, 587,60567,26625,60569, + 9731,60569,60467,60569, 483,60454,53813,60577,10107,60577,20763,60455, +46863,60583,46863,60454,27021,60587,52915,60587, 9195,60587,20763,60587, + 1275,60454,60369,60597, 587,60454,25519,60601,27021,60455,46863,60605, + 6,60454,38881,60609,59381,60455,30091,60455,31103,60615, 4,56555, + 2,60619, 0,60621,56555,60623, 5,60625, 7,60621,60627,60629, + 1,60618,59689,60633, 1418,60633,59619,60637,59683,60633, 669,60633, +59619,60643,60569,60633,59701,60633,59767,60633, 15,60633, 1369,60652, +59619,60655, 1369,60633, 15,60658,59619,60661, 842,60619, 9377,60665, +59787,60619, 9377,60618, 483,60671, 587,60619, 483,60674, 9377,60677, + 9377,60675, 483,60681,21527,60619, 9,60685,31103,60619, 587,60689, + 587,60618, 9366,60693, 9195,60693, 483,60696, 483,60693, 9195,60700, +31103,60693, 483,60619, 587,60706, 9377,60709, 9377,60707, 587,60707, + 9195,60715, 7,60618,59337,60719,58191,60719,58211,60719,21105,60719, +21549,60719,19625,60719,58887,60719,17591,60719, 6,60619, 1,60737, + 4,60738, 4,60737, 1,60742, 1369,60737,56555,60747,60741,60749, +60745,60749, 7,60619, 2,60755,21183,60755, 9377,60755,59619,60619, +38305,60619, 3,60764, 2,60764,56555,60765, 6,60770,60769,60773, + 6,60765,56555,60776,60769,60779, 1011,60619,46862,60782,46862,60783, +46863,60783,60785,60789,46863,60782,60787,60793, 6,56555,36303,60797, +36302,60796,60799,60801,36303,60796,36302,60797,60805,60807,40946,60796, +40946,60797,60765,60796,60769,60815, 2,60797, 0,60818,40947,60796, +60813,60823,40947,60797,60811,60827,60765,60797,60767,60831,59381,60797, + 17,60797,35187,60837,20501,60839,60125,60839,60821,60839, 9875,60839, +35187,60796,58723,60849, 5,60796,38881,60853, 0, 3, 8169,60857, + 8028,60857, 8173,60857, 8214,60857, 8167,60857, 8154,60857, 8026,60857, + 8054,60857,17728,60857,60210,60857,60283,60857,58128,60857,58023,60857, +57476,60857,56854,60857,56856,60857,58901,60857,58906,60857,58122,60857, +58066,60857,56810,60857,56822,60857,16743,60857,16696,60857, 4810,60857, +16745,60857,16729,60857,16714,60857, 6648,60857, 2079,60857, 375,60916, + 2086,60857,16733,60857,16565,60857,16683,60924,16692,60857,16735,60857, +16739,60857,51942,60857,44534,60857,42383,60857,44243,60938,44440,60857, +16747,60857, 75,60857, 6625,60946, 6632,60857, 6645,60857,60079,60857, + 5,60955,60327,60957, 5,60954,60369,60961,60096,60857,60369,60965, + 1325,60856,40829,60969, 1173,60857,17591,60856,17603,60975,10039,60857, + 1275,60979,10041,60981,38560,60857, 1205,60985, 1203,60857,38305,60988, + 1205,60991,38514,60857, 1007,60995,40741,60856,40829,60999, 531,60856, + 1290,60856, 0,61005, 5,61006, 5,61005, 0,61010,40769,60856, +40829,61015,38548,60857, 1325,61019, 177,60857,38305,61022, 59,61025, +17053,60857, 483,61028,10081,61031, 1009,60857,38305,61034, 1007,61037, + 1365,60857,38305,61040, 1325,61043,38566,60857, 59,61047,17054,60857, +10081,61051,42109,60857,38305,61054,42103,61057, 9527,60857, 483,61060, + 9525,61063,42110,60857,42103,61067, 9528,60857, 9525,61071, 386,60857, +56555,61074, 8150,60857, 113,61078, 347,60857,56555,61082,58905,60857, + 375,61086,45432,60857,56555,61090,43099,60857,56555,61094,40829,60857, + 1325,61099,40741,61099,40769,61099,60535,60857, 9,61107,57916,60857, + 9,61111,57851,60857, 9,61115,17727,60857, 113,61118,57060,60857, + 8309,60857,60230,60857,57986,60857,57998,60857,60268,60857,58352,60857, +58704,60857,13820,60857,13772,60857,57994,60857,58056,60857,42155,61144, +36101,60857, 375,61149,37407,60857,47392,60857,36532,60857,36536,60857, +57284,60857,58760,60857,58762,60857,58846,60857,58372,60857,57278,60857, +57996,60857,57470,60857, 305,61174,60205,60857, 305,61178,58374,60857, +58830,60857,57586,60857,57480,60857,57230,60857,57568,60857,40684,60857, +36542,60857, 375,61197,42990,60857,40038,60857,37498,60857,36754,60857, +35796,60857, 8225,60857, 8242,60857, 128,60857, 7971,61214, 101,60857, + 7971,61218,37362,60857,48122,60857,12526,60857, 6698,60857,47690,60857, +38704,60857,11943,60857, 9,61235,12343,60857, 5,61239, 4,61238, +61241,61243, 4,61239, 5,61238,61247,61249,40132,60857, 331,61253, + 59,61253, 97,61253, 1325,61253, 8148,60857,48753,61263,10081,61263, +11759,61263,39044,60857, 331,61271, 1325,61271, 571,61271, 59,61271, +42338,60857,48753,61281,44451,61281,10081,61281,42959,60857,48753,61289, +44451,61289,42825,61289,10081,61289, 629,60857,56555,61298,38305,61298, + 289,60857, 587,61305,10287,60857,17660,60857,10262,60857,40130,60857, + 331,61315, 59,61315, 1325,61315,53780,60857,48753,61323,10081,61323, +60668,60857, 9,61329, 8213,60857, 9,61332,11813,60857, 9,61337, +17030,60857, 8211,60857, 8301,60857, 8209,60857,38110,60857, 8052,60857, + 9,61350,10464,60857, 9,61355,10527,60857, 9,61359, 4727,60857, + 9,61363,11989,60857, 11,61367, 5,61368, 6,61367, 5,61372, + 5,61367, 6,61376, 6,61377, 7,61367,61381,61383, 15,61367, + 6,61366,61387,61389, 14,61367, 7,61366,61379,61395,61375,61395, +61371,61395,61393,61395,12371,60857, 5,61405, 4,61405, 12,61405, + 13,61404,61411,61413, 13,61405, 12,61404,61417,61419, 5,61404, +61409,61423, 4,61404,61407,61427, 6625,60857,44243,61430, 375,61430, + 75,61430, 9,61431, 6685,60857, 483,61440,46863,61440,17060,60857, +35768,60857,50524,60857,52806,60857,50480,60857,36296,60857,50990,60857, + 510,60857,56555,61460,47608,60857,36293,60857, 483,61466, 295,60857, +49713,61470, 1291,60857,61009,61475,61013,61475,20033,61475, 1831,61475, + 1881,61475,19319,61475, 4,61475,19317,61489,15899,61475, 4579,61475, +48561,60857, 9,61497, 922,60857,56555,61500,51937,60857, 375,61504, +57915,60857,57859,61508, 9,61511,39234,60857,60853,61515,60609,61515, + 9525,61515,42103,61515, 9517,61515,41989,61515,39485,61515,39481,61515, +57855,61515, 9519,61515,41995,61515,39487,61515, 15,61515, 9513,61541, +41941,61541,39477,61541,50958,60857, 9,61548,35761,60857, 9,61552, +35719,60857, 375,61557,57482,60857,57852,61561,57811,61561, 9,61564, + 9,61561,57811,61568,57522,60857, 483,61572,46863,61572, 1072,60857, + 1108,60857,49713,61580, 524,60857, 4,61585,19301,61587,19311,61585, + 3195,61585, 1965,61585,15899,61585, 4579,61585,40704,60857, 7,61601, +40799,61603,40813,61601, 7961,61601, 7951,61601, 7953,61601,35893,61601, +37897,61601,38299,61601, 1275,61601, 7947,61621,52756,60857, 1011,61624, +10245,60857,37339,60857, 33,60857,10385,61632, 9,61635, 7971,60857, + 101,61638, 128,61638, 9,61638, 113,61644, 483,61638,48753,61649, +10081,61649,11759,61649, 113,61638, 9,61656, 21,60857,38305,61660, + 331,61663, 59,61663, 97,61663, 1325,61663,47640,60857,56555,61672, +17635,60857,12377,61676,11731,60857,13737,61680, 567,60857,46863,61685, +55211,60857,44243,60857, 6625,61690,42383,61690,58116,61690,42155,61690, +56555,61698,56555,61690,42155,61702, 1505,60857,38057,61706, 288,60857, +46863,61711,48466,60857,56555,61714, 11,60857, 340,61719, 341,61719, + 264,61718,61721,61725, 7,61719, 265,61728,61725,61731, 265,61729, + 264,61719,61735,61737,56555,61719,57859,61741, 9,61743, 483,61718, + 4579,61747,15899,61747, 3195,61747, 1965,61747, 265,61719, 7,61756, +61725,61759,56555,61718,57852,61763,57811,61763, 9,61766, 9,61763, +57811,61770, 265,61718,61723,61775,46863,61775, 9,60857, 8213,61780, + 8052,61780, 7971,61780, 113,61786,36527,61780,58782,61780,58362,61780, + 8241,61780, 113,61780, 7971,61798,35761,61780,50958,61780, 483,61780, +56555,61806, 1011,61780,49713,61810,38305,61780,38299,61815,37897,61815, + 7961,61815, 7951,61815,35893,61815, 7953,61815, 1275,61815, 7947,61829, +49713,61780, 1011,61832,56555,61780,46863,61836, 483,61836,46863,61780, +56555,61842, 7563,60857, 1275,61847, 7565,61849, 7569,61849, 7573,61849, + 7065,60857,35187,61857,10089,60857, 16,61861, 16,61860, 17,61861, +61865,61867, 17,61860,61863,61871,10257,60857, 903,61874, 8241,60857, + 9,61878, 3255,60857, 9,61883,48789,60857, 16,61887, 16,61886, + 17,61887,61891,61893, 17,61886,61889,61897,37357,60857, 903,61900, + 3499,60857, 9,61905, 3445,60857, 9,61909,38184,60857, 375,61913, +16722,60857,16543,61917,16679,61917,16537,61917,35187,61916,13922,60857, +13753,61927, 4805,60857, 375,61930,16683,60857,16565,61934, 375,61934, + 6515,60857, 9,61941,59824,60857,60369,61945, 9,61945, 9520,60857, + 9,61951,16711,60857,16659,61954, 8,60856, 3,61959, 6,61960, +61601,61963,61815,61963, 6,61959, 3,61968,61601,61971,61815,61971, +61829,61959,61621,61959, 1274,61959,61815,61981,61601,61981, 16,60856, + 10,60856, 5,61989, 0,61990,61585,61993,61747,61993, 0,61989, + 5,61998,61585,62001,61747,62001,57811,61989,59933,61989,59743,61989, + 8093,61989, 3837,61989,39619,61989,51421,61989,53703,61989,42435,61989, + 4287,61989, 4303,61989,53487,61989,42113,61989, 9839,61989, 9579,61989, + 9,61989, 113,62036, 128,61989, 101,61989, 113,61989, 9,62044, +57859,60857,57915,62048, 9,62051, 9,62049,57915,62055, 11,60856, + 483,62059, 9,60856,57889,62063, 5185,62063,11243,62063,12557,62063, +11251,62063, 5177,62063, 16,60857,57293,62077,35603,62077,58669,62077, +59079,62077,55005,62077, 17,60856,61685,62089, 483,62089, 15,60856, +40829,62095, 10,60857,21183,62099, 759,62099, 47,62099, 959,62099, + 203,62099, 107,62099, 85,62099, 67,62099, 9,62115, 113,60857, + 8150,62118,17727,62118,13737,62118, 9,62118, 7971,62126,17025,62118, + 7971,62118, 9,62132,10385,60857, 9,62137, 33,62139, 33,62136, + 9,62143, 165,60857,17049,62146,17025,60857, 1275,62151, 7947,62153, +48739,62153,17637,62153,17029,62153,37241,62153, 113,62150,17049,60857, + 165,62166,10247,60857,37347,60857,10249,60857,16659,60857,16711,62176, +37408,60857,56555,62180,16531,62180, 340,60857,51803,62187, 331,62187, + 1325,62187, 59,62187,52439,60857,56555,62196,52563,60857, 265,62201, + 1413,60857,56555,62204, 256,60857,56555,62208,38305,62208, 566,60857, +61987,62215, 9377,62215,37325,62215,10219,62215, 959,62215, 47,62215, + 759,62215, 587,62215,20763,62215,42810,60857,43073,62235,42827,62235, +58703,62235,60849,62235,58027,62235,42821,62235, 1325,62235, 59,62235, + 331,62235, 265,62235,42613,62235,56555,62257, 241,62234, 580,60857, +20033,62263,59143,62263,60601,62263,58029,62263,55210,60857,31103,62273, +37375,60857, 1347,60857,37409,60857, 375,62280, 375,60857,58905,62284, +16683,62284, 4805,62284,58126,62284, 6625,62284, 2079,62284,51937,62284, + 305,62284,56555,62300,56555,62284, 305,62304,37409,62284, 803,60857, +37608,60857, 305,60857,60205,62314,57470,62314, 375,62314,56555,62320, +56555,62314, 375,62324,58116,60857,44243,62328,58126,60857, 375,62332, +42155,60857,58056,62336,44243,62336,56555,62340, 483,62336,48753,62345, +44451,62345,10081,62345,56555,62336,44243,62352,53517,60857, 483,62356, +48753,62359,10081,62359, 251,60857,38305,62364, 331,62367, 1325,62367, + 59,62367, 555,60857,38305,62374, 331,62377, 1325,62377, 571,62377, + 59,62377,60612,60857, 7,62387,36273,60857, 7,62391,59787,60857, +60619,62394, 9,62397, 5,62394,60369,62401, 9,62401, 5,62395, +60327,62407,60719,62407,57901,62407, 17,62407,59381,60857,60455,62416, + 7,62419, 9513,60857, 5,62423, 17,62425, 5,62422, 9,62429, +58362,60857, 903,62432, 9,62432,58348,60857, 7,62438,58782,60857, + 903,62442, 9,62442,58396,60857, 7,62448,58742,60857, 9,62453, + 483,62452,46863,62452,60763,60857, 7,62461, 903,60857,58782,62464, +58362,62464,37357,62464,10257,62464, 483,62464,56555,62474,46863,62464, +56555,62478,56555,62464, 9,62483,46863,62482, 483,62482,38057,62464, + 7,62491, 265,60857,46863,62495, 11,62497, 11,62494,46863,62501, + 7,62494,51803,62505, 331,62505, 1325,62505, 59,62505, 7,62495, + 375,62515,35187,60857,59960,62518,16722,62518, 7,62518,56555,62524, +16531,62524,56555,62518, 7,62530,16531,62518, 7,62534,46863,60857, +36527,62538,58742,62538,57522,62538,12377,62538, 6685,62538, 1011,62538, + 903,62538,56555,62552, 9,62538,56555,62556,56555,62538, 903,62560, + 9,62560,36527,60857, 7,62567, 331,62569, 9,62566,46863,62566, + 483,62566, 7,62566, 375,62579,38305,60857,42109,62582,42103,62585, + 1205,62583, 1203,62589, 1007,62583, 1009,62593, 1203,62582, 1205,62597, + 1009,62582, 1007,62601, 177,62582, 59,62605, 1365,62582, 1325,62609, + 571,62583, 555,62613, 97,62583, 21,62617, 5,62582, 6,62621, + 5,62622,62583,62625, 2,62622,62627,62629, 2,62621, 6,62632, + 482,62621, 3,62582, 6,62639, 3,62640,62583,62643, 4,62640, +62645,62647, 4,62639, 6,62650, 8,62639, 14,62582, 6,62657, + 2,62658, 2,62657, 6,62662, 482,62657, 1274,62582, 6,62669, + 4,62670, 4,62669, 6,62674, 8,62669, 256,62582, 629,62582, + 555,62582, 59,62685, 331,62685, 1325,62685, 571,62685, 21,62582, + 1325,62695, 331,62695, 59,62695, 97,62695, 1325,62583, 1365,62705, + 251,62705, 21,62705, 555,62705, 59,62583, 177,62715, 251,62715, + 555,62715, 21,62715, 251,62582, 331,62725, 59,62725, 1325,62725, + 331,62583, 251,62733, 555,62733, 21,62733, 15,62583,10085,62741, +10093,62741,62661,62741,62665,62741,40909,62741,62629,62741,62635,62741, + 3,62741,10087,62741,62637,62741,62667,62741, 483,62741,10081,62765, +62621,62765,62657,62765, 1275,62583,10005,62773,10041,62773,62673,62773, +62677,62773,62647,62773,62653,62773, 5,62773,10009,62773,23879,62773, +31937,62773,30399,62773,62655,62773,62679,62773, 9,62773,10001,62801, +62639,62801,62669,62801, 483,62582,39485,62809,39481,62809, 9525,62809, + 9517,62809, 4,62809,62773,62819,62787,62809,42103,62809,41989,62809, + 9519,62809,41995,62809,57855,62809,60853,62809,60609,62809,39487,62809, + 15,62809, 9513,62841,41941,62841,39477,62841, 9,62582,61971,62849, +61963,62849, 7961,62849, 7951,62849, 2,62849,62741,62859,62757,62849, + 7953,62849,35893,62849,38299,62849,37897,62849,61981,62849, 1275,62849, + 7947,62875,61959,62875, 6,62582, 7,62582,58703,62883,58027,62883, +60849,62883, 59,62883, 1325,62883, 331,62883, 265,62883,42613,62883, +56555,62899, 241,62882, 7,62583,58715,62905,58056,62905,40799,62905, + 375,62905,56555,62905,44243,62914,44243,62905,56555,62918, 265,62583, + 375,62923,62881,62923, 241,62582, 6,62928, 7,62928, 6,62929, +62933,62935, 7,62929,62931,62939, 1011,60857,52756,62942,46863,62942, + 483,62942, 9,62942,49713,62950,49713,62942, 9,62954, 7,62943, +10107,62959,53813,62959,49713,60857,22807,62965, 1108,62964, 295,62964, + 9,62964, 1011,62972, 1011,62964, 9,62976, 4,62964,31103,62981, + 241,60857,59960,62984,42810,62984, 7,62984,56555,62990,38305,62990, +56555,62984, 7,62996,38305,62984, 6,63000, 7,63000, 6,63001, +63005,63007, 7,63001,63003,63011, 483,60857, 9527,63014, 9525,63017, +17053,63014,10081,63021,11759,63015, 7971,63025,44451,63015,42155,63029, + 0,63014, 5,63033, 0,63034,63015,63037, 7,63034,63039,63041, + 7,63033, 5,63044, 10,63033, 6,63014, 5,63051, 6,63052, +63015,63055, 1,63052,63057,63059, 1,63051, 5,63062,38304,63051, + 14,63014, 5,63069, 1,63070, 1,63069, 5,63074,38304,63069, +36527,63014,58742,63014,57522,63014,12377,63014, 6685,63014, 7971,63014, +48753,63091,10081,63091,11759,63091,42155,63014,10081,63099,48753,63099, +44451,63099,10081,63015,17053,63107,53517,63107,42155,63107, 7971,63107, +53517,63014,48753,63117,10081,63117,48753,63015,53517,63123, 7971,63123, +42155,63123,36293,63014, 17,63015, 11,63015, 9,63014,56555,63136, + 15,63015, 1995,63141, 3755,63141,63073,63141,63077,63141, 5303,63141, +63059,63141,63065,63141, 0,63141,38403,63141,39943,63141, 4917,63141, +17013,63141,63067,63141,63079,63141,38305,63141, 59,63171,63051,63171, +63069,63171, 903,63014,56555,63178, 1011,63014, 11,63014,61993,63185, +62001,63185, 3195,63185, 1965,63185, 1,63185,63141,63195,63157,63185, + 4579,63185,15899,63185,38305,63014,39481,63205,39485,63205,42103,63205, +41989,63205, 7,63205, 9525,63205, 9517,63205,41995,63205, 9519,63205, +57855,63205,60609,63205,60853,63205,39487,63205, 15,63205,41941,63233, + 9513,63233,39477,63233, 4,63014,20033,63241,59143,63241,60601,63241, +58029,63241,63133,63241, 5,63014,61987,63253, 9377,63253,37325,63253, +10219,63253, 959,63253, 47,63253, 759,63253, 587,63253,20763,63253, + 4,63015, 7,63272,63253,63275,20029,63273,59147,63273,21103,63273, +19781,63273,19301,63273,62773,63273, 5,63015, 803,63291,56555,63014, + 903,63294, 9,63294,40674,60857, 6,63300, 7,63300, 6,63301, +63305,63307, 7,63301,63303,63311,38266,60857, 7,63315,36752,60857, + 7,63318,16937,60857, 580,63322, 483,63322, 4,63327, 4,63326, +49631,63322,49630,63322, 581,63322, 4,63322, 483,63338,46863,63338, + 5,63322,63329,63345, 4,63323,63333,63349,63337,63349, 5,63323, +63335,63355,63325,63355,63331,63355,63341,63355,63343,63355,46863,63322, + 4,63366,63355,63369, 4,63367,63345,63373,38057,60857, 5,63376, + 6,63379, 6,63378, 14,63376, 15,63376, 1505,63376, 6,63376, + 5,63390, 7,63376,63381,63395, 375,63395, 6,63377,63387,63401, + 7,63377,63393,63405,63383,63405,38161,63405, 59,63405,63385,63405, + 331,63405, 1325,63405, 265,63405, 903,63376, 7,63423,16531,60857, + 1275,63427,16711,63429,37408,63426, 7,63426,16543,63435,16679,63435, +16537,63435,35187,63434, 7,63427,16565,63445,35187,63426, 7,63448, +12377,60857, 9,63453,46863,63452, 483,63452,17635,63452,13737,60857, + 113,63462,11731,63462, 5,63462,13753,63469, 5,63463,13751,63473, +13917,63473,13743,63473,60619,60857,59787,63480, 9,63483,60455,60857, +59381,63486, 7,63489, 5,60856,45491,63493,42800,63493,59694,63493, +10374,63493,60563,63493, 9606,63493,42134,63493, 629,63493, 705,63493, + 101,63493, 299,63493, 828,63493, 128,63493, 394,63493,48122,63493, + 803,63493, 483,63524,42613,63493, 17,63528,51992,63493, 375,63493, + 241,63534,49713,63534,10291,63493, 17,63540, 256,63493, 113,63493, + 9,63546, 17,63493,42613,63550,10291,63550,59619,63550, 9565,63550, +41941,63550, 9,63493, 113,63562, 7,63493,21605,63567, 241,63566, + 7,63492,59933,63573,59743,63573,57811,63573, 8093,63573, 3837,63573, +53703,63573, 4287,63573,42435,63573, 4303,63573,53487,63573, 9839,63573, +42113,63573, 9579,63573,39619,63573,51421,63573,31103,63493,46863,63493, +12377,63606, 483,63493, 803,63610,49713,63493, 375,63614,56555,63493, + 5,63619, 6,63621, 6,63620, 14,63619, 15,63619, 6,63618, +63629,63631, 7,63618,63625,63635,63627,63635, 7,63619,63623,63641, + 6,63619, 5,63644,63635,63647, 241,63493, 375,63650, 7,63650, +59619,63493, 7,63657, 17,63656,12377,63493,46863,63662, 9565,63493, + 7,63667, 17,63666,41941,63493, 7,63673, 17,63672, 4,60856, +20305,63679, 9641,63679, 9645,63679,20309,63679,21081,63679,20323,63679, +20387,63679, 3,63679, 6,63694,61601,63697,61815,63697,62849,63697, + 6,63695, 9701,63679, 1274,63679,61815,63709,61601,63709,62849,63709, +61829,63679,61621,63679,62875,63679, 9719,63679,43005,63679,58056,63679, + 386,63679, 347,63679, 767,63679,31103,63733, 524,63679, 9617,63737, +20273,63737, 1291,63679, 9617,63743,20273,63743, 305,63679, 375,63748, + 375,63679, 305,63752,44243,63679,56555,63756, 11,63679, 483,63760, + 9617,63763,20273,63763, 7,63679,38305,63769,56555,63771, 6,63679, + 4,63775, 3,63774,61601,63779,61815,63779,62849,63779, 4,63774, +62582,63787,63779,63789,38305,63787,60857,63792,63779,63795,60857,63787, +38305,63798,63779,63801, 7,63678,63253,63805,62215,63805, 483,63679, + 11,63810, 9617,63813,20273,63813,56555,63679,44243,63818, 7,60856, +40787,63823,40793,63823, 0,63823, 5,63828,61475,63831,61585,63831, +61747,63831,63185,63831,36001,63823,26106,63823,32103,63823,41746,63823, +43005,63823, 8800,63823,59910,63823,36539,63823,37595,63823,36049,63823, +63253,63823,62215,63823,61305,63823,48975,63823,48245,63823,48451,63823, +60707,63823, 386,63823, 347,63823, 510,63823,60755,63823, 9852,63823, +53500,63823,36041,63823,37573,63823,36275,63823, 375,63823, 305,63892, + 273,63823, 281,63823, 1477,63823, 1516,63823, 948,63823,40704,63823, +10001,63907,27533,63907, 8495,63823, 11,63912,48885,63823, 483,63917, +41019,63823, 11,63920, 567,63823,63493,63925, 165,63823, 903,63928, + 11,63823,25793,63932,41019,63932, 8495,63932,59875,63932, 9805,63932, +53391,63932,60618,63823, 483,63947, 9,63823, 483,63950,38305,63950, +27533,63955,10001,63955, 1505,63823, 1011,63960, 305,63823, 375,63964, + 4,63823,63610,63969,63291,63969,63493,63969, 483,63974, 483,63969, +63493,63978,56555,63968, 483,63983, 5,63823, 7,63987, 1275,63989, +60857,63991, 0,63986,61475,63995,61585,63995,61747,63995,63185,63995, +63993,63995, 7,63986,63014,64007,63995,64009, 483,64007,60857,64012, +63995,64015,60857,64007, 483,64018,63995,64021, 4,63822,63253,64025, +62215,64025, 5,63822,59743,64031,59933,64031,57811,64031, 8093,64031, + 3837,64031,42435,64031, 4303,64031,53703,64031, 4287,64031,42113,64031, + 9579,64031,53487,64031, 9839,64031,51421,64031,39619,64031,25793,63823, + 11,64062, 903,63823, 165,64066,38305,63823, 9,64070,27533,64073, +10001,64073, 1011,63823, 1505,64078,56555,63823, 4,64082, 483,64085, + 483,63823, 9,64088,59875,63823, 11,64092, 5,64093, 9805,63823, + 11,64098, 5,64099,53391,63823, 11,64104, 5,64105, 6,60856, +60454,64111,60369,64113, 5,64111,56555,64116,60369,64119,56555,64111, + 17,64122, 4,64122, 7,64126, 5,64122,60369,64131, 5,64123, +60327,64135,60719,64135,64129,64135,57901,64135, 4,64123,64125,64145, + 7,60857,16539,64149,16683,64151, 264,64149, 264,64148, 3,64149, +16530,64158,16530,64159, 1,64158,58396,64148,58348,64148,36527,64148, + 375,64171,40674,64148,36752,64148, 331,64149, 1325,64149, 59,64149, +38057,64148, 375,64185,16531,64148,64161,64189,16543,64189,16679,64189, +16537,64189,35187,64188, 17,64149, 241,64201,38305,64149,42383,64205, + 6625,64205,58116,64205,42155,64205,56555,64212,56555,64205,42155,64216, +16531,64149,64163,64221,16659,64221,48885,64149,56555,64227, 15,64149, + 483,64231,38305,64231,27533,64235,64165,64235,10001,64235,35187,64148, +56555,64242,16531,64242, 265,64148,64155,64249,51803,64249, 331,64249, + 1325,64249, 59,64249, 241,64148,56555,64260,38305,64260,38305,64148, +58703,64267,58027,64267,60849,64267, 59,64267, 1325,64267, 331,64267, + 265,64267,42613,64267,56555,64283, 241,64266, 265,64149,64157,64289, +41941,64289,51229,64289, 4213,64289, 8757,64289, 9565,64289,59619,64289, + 305,64289, 713,64289, 25,64289, 8165,64289, 9617,64289,20273,64289, + 4,64148,57293,64317,35603,64317,58669,64317,59079,64317,55005,64317, + 5,64148, 3,64329, 1,64331,64205,64333,21183,64329, 759,64329, + 47,64329, 959,64329, 4,64149,43053,64345,54985,64345,54129,64345, +51601,64345,58782,64345,46863,64345,56555,64356,56555,64345,46863,64360, + 5,64149, 803,64365, 1275,64149, 9,64369,56555,64148,25793,64373, + 8495,64373,41019,64373,35187,64372, 241,64372,59960,60857,25793,64385, +41019,64385, 8495,64385, 241,64384,35187,64384, 5,60857,60079,64396, +60369,64399, 0,64396,63743,64403, 1290,64403,63679,64407,63737,64403, + 525,64403,63679,64413,63763,64403,63813,64403, 17,64403, 1275,64420, +63679,64423, 1275,64403, 17,64426,63679,64429, 3,64396, 6,64433, + 759,64397, 483,64437,64025,64397, 483,64441,63823,64397, 483,64445, + 9377,64397, 483,64449, 9513,64396, 9,64453, 959,64397, 483,64457, +37325,64397, 483,64461, 47,64397, 483,64465,10219,64397, 483,64469, +59787,64396,60369,64473, 9,64473,13737,64396,13753,64479,49713,64397, +61987,64397, 483,64485, 9,64397,42613,64489,59619,64489,10291,64489, + 9565,64489,41941,64489, 17,64397, 113,64501,63805,64397, 483,64505, +20763,64397, 483,64509, 483,64396,64025,64513,63823,64513,61987,64513, +63805,64513, 9377,64513,37325,64513,10219,64513, 959,64513, 47,64513, + 759,64513, 587,64513,20763,64513, 587,64397, 483,64539, 7,64396, +21183,64543, 759,64543, 47,64543, 959,64543, 6,64397,56555,64553, + 4,64554, 5,64554, 5,64555,64557,64561, 4,64555,64559,64565, + 7,64397, 0,64569, 5,64570, 5,64569, 0,64574,21105,64569, +21549,64569,19625,64569, 1275,64569,60857,64585,64573,64587,64577,64587, +63679,64397,63705,64593,64435,64593,31103,64593, 375,64593, 7,64593, +64433,64603, 903,64397, 375,64607, 7,64607,35187,64397,60796,64612, +60797,64612,31103,64613,60797,64613,64615,64621, 375,64613,60796,64613, +64617,64627,56555,64397,59787,64631, 9,64633,56555,64396,59914,64637, +60221,64637,59875,64637, 9,64642,60369,64637, 9,64637,59875,64648, +60454,60857,59914,64653,60221,64653,59875,64653, 9,64658,60369,64653, + 9,64653,59875,64664, 4,60857, 8743,64669, 8605,64669, 8672,64669, + 8647,64669, 305,64676, 3795,64669,10025,64669,27603,64669,31524,64669, +31690,64669,31700,64669,63569,64669,46862,64669, 0,64669, 2,64696, + 6,64696, 6,64697,63604,64669,24655,64669,63534,64669, 8916,64669, +62092,64669,63133,64669,48408,64669, 713,64669,31103,64718, 305,64669, + 8647,64722,31103,64722, 25,64669,31103,64728, 340,64669, 8717,64733, + 3785,64733, 8495,64733, 483,64669,62089,64740,46863,64740, 375,64669, +63493,64746, 8861,64746,62089,64669, 483,64752, 15,64669, 483,64757, +20273,64759, 9617,64759,64403,64759,64699,64759,31103,64669, 305,64768, + 713,64768, 25,64768,63493,64768,49713,64769, 483,64668,20033,64781, +59143,64781,58029,64781,60601,64781,49713,64668,31103,64791,46863,64669, + 483,64794, 6,64668,64795,64799, 2,64801, 3,64800,64803,64805, + 3,64801, 2,64800,64809,64811, 7,64668,57293,64815,64695,64815, + 2,64819, 3,64818,64821,64823, 3,64819, 2,64818,64827,64829, +64701,64815, 2,64833, 3,64832,64835,64837, 3,64833, 2,64832, +64841,64843,35603,64815,59079,64815,58669,64815,55005,64815, 6,64669, + 0,64854,64815,64857, 2,64859, 3,64858,64861,64863, 3,64859, + 2,64858,64867,64869, 7,64669,60857,64873, 264,64874, 264,64875, + 1,64873, 264,64880, 264,64881,64703,64873, 2,64887, 3,64886, +64889,64891, 3,64887, 2,64886,64895,64897,25793,64873,41019,64873, + 8495,64873, 305,64905,59875,64873,53391,64873, 9805,64873,38305,64873, + 483,64915, 265,64872, 8717,64919,64883,64919,64877,64919, 3785,64919, + 8495,64919, 265,64873,64885,64931,64879,64931,63493,64931, 8861,64931, +46863,64931, 8861,64669, 375,64942,63493,64669,31103,64946, 375,64946, + 265,64669, 7,64952, 8717,64955, 3785,64955, 8495,64955, 7,64953, + 8647,64963,56555,64669,59381,64967, 7,64969,56555,64668,31103,64973, + 375,64973,59712,64973, 7,64973, 265,64981,59619,64980,59619,64973, + 7,64986,60618,60857,31103,64991, 375,64991,59712,64991, 7,64991, + 265,64999,59619,64998,59619,64991, 7,65004, 6,60857, 264,65009, +64746,65011, 375,65011,64669,65014,64931,65011,64669,65011, 375,65020, + 264,65008,64733,65025, 341,65025,64669,65029,64955,65025,64919,65025, + 3,65008, 341,65037,64669,65039,63907,65037,40705,65037,63823,65045, +64235,65037,63955,65037,64073,65037, 17,65037,64953,65009, 375,65057, + 4,65009, 1274,65061, 3,65061, 6,65064, 6,65061, 3,65068, +56555,65008,60796,60857,56555,60857, 386,65076,45432,65076, 347,65076, +43099,65076,60418,65077,60327,65087,59961,65077, 5,65091,60369,65093, + 5,65090,60327,65097, 18,65076, 12,65076, 1291,65076,48561,65076, + 525,65076,49630,65076, 580,65076, 1170,65076,37408,65076, 256,65076, +52439,65076, 629,65076, 1413,65076,47640,65076, 922,65076,49631,65076, + 581,65076, 1171,65076,44243,65076,42155,65136, 375,65076, 305,65140, +48466,65076, 510,65076, 13,65077,65103,65149, 19,65077,65101,65153, + 13,65076, 18,65077, 19,65076,65159,65161, 12,65077,65157,65165, +57915,65165, 14,65077,57901,65171,60719,65171,60327,65171,65115,65171, + 17,65171, 10,65077, 9,65183, 16,65076,65171,65187, 10,65076, +65165,65191,48560,65076, 524,65076, 1290,65076, 11,65076,65149,65201, +57852,65201,65184,65201,65183,65201, 9,65208,57811,65201, 9,65212, + 9,65201,65183,65216,57811,65216,46863,65200, 483,65200, 9,65076, + 483,65226,46863,65226, 17,65076, 1275,65232, 11,65077,65191,65237, + 9,65239,57915,65237, 9,65243, 9,65236,65191,65247,57915,65247, + 9,65077, 11,65253,65183,65255,57811,65255, 11,65252,65191,65261, +57915,65261, 15,65077,65233,65267,65135,65267, 305,65076, 375,65272, +42155,65076,44243,65276, 1011,65076, 7,65281, 7,65280,65171,65285, + 15,65281, 241,65076, 7,65290, 483,65076, 4,65295, 4,65294, + 903,65294, 9,65294, 11,65294, 903,65076, 9,65307,46863,65306, + 483,65306,35187,65076, 7,65314, 1275,65076, 17,65318,46863,65076, + 4,65323, 4,65322, 903,65322, 9,65322, 11,65322, 7,65077, + 9,65335, 11,65335, 567,65335, 4,65335, 483,65343, 5,65335, + 5,65334,65343,65349, 4,65334,65347,65353, 6,65076,65350,65357, +65355,65357,65289,65357,65349,65357,65343,65364,65343,65357,65349,65368, + 11,65357,65346,65357,65353,65375, 5,65357,65335,65379,65349,65381, +65335,65378,65353,65385,65335,65357, 4,65389, 5,65389,65343,65393, + 4,65388,65393,65397, 5,65388,65391,65401,65353,65401, 5,65077, +60629,65407,59960,65406,59960,65407,38185,65407,57993,65407,65115,65407, +65113,65407,65111,65407,59961,65406,65413,65425,60327,65425,65197,65407, +65195,65407,65105,65407,60251,65407,58313,65407,65299,65407,65327,65407, +65285,65407,65225,65407,65223,65407,65305,65407,65333,65407,56555,65407, + 7,65454, 7,65455,59961,65407,60359,65461,65411,65461, 11,65461, + 1171,65407,65335,65469,65335,65407,65187,65407,57901,65407,60327,65407, +60719,65407, 17,65407,65335,65483,59875,65483,64385,65407,64373,65407, + 6,65407,65459,65493,60755,65493,65283,65493, 11,65493, 7,65407, +56555,65502, 7,65406,65461,65507,65493,65507, 6,65406,65505,65513, +65457,65513,60719,65513,65413,65513,60327,65513,57901,65513,65187,65513, +65115,65513,65285,65513,65503,65513, 17,65513, 4,65076, 2,65537, + 7,65539,65407,65541,65510,65537,65533,65537,65507,65537,65493,65548, +31103,65537,65493,65537,65507,65554, 483,65536,65407,65559,46863,65536, +65407,65563, 375,65537, 15,65537,65357,65569, 7,65536,65513,65573, +65171,65573,65407,65573,59712,65537,65502,65537,65513,65583, 7,65537, +65493,65587,65407,65587,65507,65591, 265,65587,59619,65586,65407,65586, +65513,65599,59619,65537, 7,65602,65407,65537, 6,65607, 7,65607, +65493,65611, 6,65606,65611,65615, 7,65606,65609,65619,65513,65619, + 4,65077,65135,65625,65133,65625,65131,65625,65372,65625,65199,65625, +65109,65625,65107,65625,65235,65625,65321,65625, 11,65625,65357,65644, +65233,65625,65357,65625, 11,65650,65075,65625,65073,65625, 7,65625, +60455,65625, 7,65661, 5,65076, 2,65664,65625,65667, 1,65664, + 3,65664, 0,65664,65625,65675,59914,65665,60221,65665,65336,65665, +65297,65665,65325,65665,59875,65665, 9,65688,65659,65665,65667,65693, +65675,65693,60369,65665, 9,65665,65335,65700,59875,65700,65335,65665, + 9,65706,65658,65665,65671,65711,65673,65711, 6,65665,65668,65717, +65676,65717,65667,65717,65625,65722,65675,65717,65625,65726,65625,65717, +65667,65730,65675,65730, 7,65665,65671,65737,65625,65739,65673,65737, +65625,65743,65625,65736,65671,65747,65673,65747,65625,65665, 6,65753, + 7,65753, 6,65752,65757,65759, 7,65752,65671,65763,65673,65763, +65755,65763, 6,65077,60619,65771, 9,65773, 17,65771,65625,65777, +65537,65771, 9,65781, 5,65771,60369,65785, 9,65785, 5,65770, +65573,65791,60327,65791,60719,65791,57901,65791,65187,65791,65115,65791, +65285,65791, 17,65791, 7,65076,25793,65809,41019,65809, 8495,65809, + 1011,65808,65513,65817,65791,65817,65407,65817,65171,65817, 241,65808, +35187,65808, 15,65809,65665,65831,65407,65809, 11,65835, 4,65808, +65791,65839,65513,65839,65171,65839,65407,65839, 4,65809,65785,65849, +65665,65849,65771,65809, 4,65855, 5,65855, 4,65854,65859,65861, + 5,65854,65857,65865, 1, 4,49284,65869,49311,65869,48330,65869, +48279,65869,47548,65869,47076,65869,47078,65869,48581,65869,48584,65869, +54254,65869,54260,65869,54266,65869,54222,65869, 8672,65869, 8743,65869, + 3795,65869, 8605,65869, 8647,65869, 305,65904,27021,65868,31103,65909, +27377,65910,31894,65909,27377,65909,31103,65916, 21,65868,57577,65921, +59109,65921,19987,65921,57381,65921,59787,65868,57577,65931,57381,65931, +57253,65931,59109,65931,15390,65869,15383,65941,44768,65869,44663,65945, +48284,65869,37897,65949,44243,65869,37845,65953,45411,65955,37845,65952, +44663,65959,37845,65869,44243,65963,45381,65965,44243,65962,44663,65969, +46863,65962,37897,65973, 1175,65869,56555,65977, 1177,65979,49215,65869, + 9,65983,49229,65985,56709,65869, 1009,65989,54641,65869,54643,65993, +60737,65868,60749,65997,11355,65868,11495,66001,57793,65868,57577,66005, +57381,66005,59109,66005,59715,65869,56555,66013,59717,66015, 7959,65869, + 9,66019, 7961,66021,49534,65869,49537,66025,19086,65869, 1203,66029, +49529,65869, 15,66032,49537,66035,19064,65869, 1009,66039,54668,65869, +54643,66043, 1205,65869,18967,66046, 1203,66049,19949,65868,19987,66053, + 1425,65868,57253,66057, 668,65868, 1,66061, 2,66062, 2,66061, + 1,66066,56554,66061,58930,65868, 4,66073, 6,66074, 6,66073, + 4,66078, 8,66073,19965,65868,19987,66085,56745,65868,57253,66089, +60136,65869,59787,66093, 571,65869,18967,66096, 555,66099,16091,65869, + 15,66102, 9513,66105,19078,65869, 21,66109,54655,65869, 15,66112, +54643,66115, 1007,65869,18967,66118, 1009,66121,60125,65869, 15,66124, +59787,66127,19088,65869, 555,66131,16092,65869, 9513,66135, 97,65869, +18967,66138, 21,66141,20347,65869,18967,66144,20345,66147,10095,65869, + 15,66150,10093,66153,20348,65869,20345,66157,10096,65869,10093,66161, +32468,65869,27323,66165,33442,65869,48368,65869,32469,65869,65909,66173, +28483,65869,28479,65869,63604,65869,31690,65869,31700,65869,31524,65869, +31596,65869,32464,65869,53380,65869,25037,65869,24655,65869,25457,65869, +23005,65869,27603,65869,22591,65869,23105,65869,23357,65869,23113,65869, + 120,65869,46863,66212, 77,65869,46863,66216,54154,65869,54225,66220, +56328,65869,58298,65869,58868,65869,52752,65869,52370,65869,58344,65869, +57253,65869,59787,66237, 1425,66237,56745,66237,19987,65869, 21,66245, +19949,66245,19965,66245,25215,65869,48583,65869, 113,66254,25459,65869, +31920,65869,32263,65869,23099,65869,23107,65869,24631,65869,22915,65869, +22589,65869,65294,65869,65322,65869,63534,65869,54256,65869,54129,66280, +25305,65869,32295,65869,31796,65869,62092,65869,63133,65869,22785,65869, +22803,65869,22951,65869,24735,65869,23012,65869,25546,65869,47364,65869, +25548,65869,62442,65869,63294,65869,62432,65869,62560,65869,57577,65869, + 21,66319,59787,66319,57793,66319,57381,65869,59787,66327, 21,66327, +57793,66327,59109,65869, 21,66335,59787,66335,57793,66335,48578,65869, + 33,66343,48276,65869, 33,66347,49308,65869, 33,66351,59340,65869, +63135,65869,61464,65869,61580,65869,61578,65869,62946,65869,62950,65869, +62550,65869,61810,65869,63182,65869,62948,65869,57660,65869,57766,65869, +62060,65869,57772,65869,22767,65869,19810,65869, 251,66387, 555,66387, + 1365,66387, 21,66387, 9994,65869, 9513,66397,16859,66397,59787,66397, +20620,65869,59787,66405,21529,66405, 9513,66405,19372,65869, 251,66413, + 21,66413, 177,66413, 555,66413,20823,65869,59787,66423,21529,66423, +20771,66423, 9513,66423,57971,65869, 21,66433, 251,66433, 177,66433, + 159,66433, 555,66433,25303,65869, 11,66445,24739,65869,29028,65869, +57658,65869,57620,65869,48328,65869, 113,66456,19806,65869, 251,66461, + 555,66461, 21,66461, 8916,65869,54262,65869,46863,66470,54219,65869, +46863,66474,32556,65869, 759,66479, 7061,65869, 3,66483, 2,66483, + 842,66483, 843,66482,66489,66491, 843,66483, 842,66482,66495,66497, + 3,66482,66487,66501, 2,66482,66485,66505,47546,65869, 25,66508, +49283,65869, 25,66512,47600,65869,48444,65869,47572,65869,62146,65869, +17476,65869,23010,65869,63184,65869,61584,65869,48558,65869,47408,65869, +25460,65869,61474,65869,47372,65869,61746,65869,47632,65869,17538,65869, +47634,65869,47676,65869,48112,65869,47412,65869, 5886,65869,48095,65869, + 1072,65869,60857,66560,48408,65869,49713,66564, 241,66564, 587,66565, + 903,66564,48420,65869,61780,65869, 1011,66576,47640,65869, 1011,66580, + 483,66580,47590,65869, 483,66586,47672,65869,47368,65869, 1413,65869, +46863,66594,52692,65869,46863,66598,47370,65869, 922,65869,46863,66604, +49075,65869,49395,65869,48586,65869,10025,65869, 1281,65869,46863,66616, + 1291,65869,60857,66620, 669,65869,66065,66625,66069,66625,40909,66625, + 1821,66625, 1879,66625,38973,66625, 3,66625,38971,66639,57911,66625, +17041,66625, 4897,66625,56739,66625,66071,66625,56555,66625, 671,66653, +66061,66653,25381,65869, 11,66659, 11,66658,58931,65869,66077,66665, +66081,66665,58715,66665,58975,66665,58981,66665,59089,66665, 7,66665, +59079,66679,23879,66665,30399,66665,31937,66665,58983,66665,66083,66665, + 9,66665,58967,66693,66073,66693,58782,65869,49713,66698,60857,66698, + 11,66699, 1108,65869,60857,66706,62089,65869, 483,66710, 4802,65869, + 5314,65869,17670,65869,17693,65869,62059,65869, 483,66722,47608,65869, +60857,66726, 903,66726, 11,66727, 587,66726,19474,65869,10093,66737, +20345,66737,10085,66737,20281,66737,19549,66737,19553,66737,10087,66737, +20285,66737,19555,66737, 483,66737,20273,66757,10081,66757,19545,66757, +61718,65869, 483,66764,22957,65869, 903,66768, 587,66768,62538,65869, +56555,66774, 1011,66774, 288,65869, 9,66781,19916,65869, 7,66785, +35603,66787,35613,66785,10041,66785,10005,66785,10009,66785,23879,66785, +30399,66785,31937,66785, 9,66785,10001,66805,63014,65869,56555,66808, + 11,66809, 587,66809, 1011,66808, 11,66808,48534,65869, 1011,66820, + 1418,65869, 3,66825,38903,66827,38913,66825, 3587,66825, 1989,66825, +56681,66825,57911,66825,17041,66825, 4897,66825,56555,66825, 1471,66845, + 1086,65869,46863,66848, 524,65869,60857,66852, 1304,65869, 9,66857, + 1530,65869, 9,66861, 9195,65869,31103,66864,10031,65869,27641,65869, + 713,65869,31103,66872, 1447,65869,13737,66877, 9875,65869, 15,66880, + 9513,66883,16859,66883,59787,66883, 803,66881, 1325,65869,18967,66892, + 251,66895, 555,66895, 1365,66895, 21,66895,16937,65869,46863,66904, + 1505,65869,28715,66908, 5438,65869,49162,65869, 113,65869,48583,66916, +48328,66916, 25,66916,46863,66922,46863,66916, 25,66926, 375,65869, +63493,66930, 8861,66930,58334,65869,46863,66936,58362,65869,60857,66940, + 506,65869,46863,66944, 587,65869, 759,66949,31103,66951,31103,66948, + 759,66955,22957,66948,47608,66948,46863,66948, 1011,66962, 1011,66948, +46863,66966, 1369,65869, 15,66970, 4897,66973,17041,66973, 3587,66973, + 1989,66973,57911,66973,56681,66973,56555,66973, 1471,66987, 1275,66970, + 9,66991, 1275,65869,18967,66994,31937,66997,30399,66997,10041,66997, +10005,66997,23879,66997,10009,66997, 9,66997,10001,67011, 11,66994, + 9,67015, 9,66995, 11,67019, 1369,67019, 1369,66994, 9,67025, + 483,65869,32805,67028,56156,67028,65076,67028,25545,67028,62089,67028, +62942,67028,62059,67028,47590,67028,47640,67028,17669,67028, 5313,67028, + 4801,67028, 587,67029,46863,67055,61718,67028,49713,67028,46863,67060, + 1011,67028,60857,67064, 903,67028,46863,67068,46863,67028,49713,67072, + 587,67073, 241,67072, 903,67072,60857,67028,56555,67082, 587,67083, + 11,67083, 1011,67082, 11,67082, 11,67028,60857,67094, 5325,67028, +56555,67028,60857,67100, 241,67028,46863,67104, 4593,67028,11985,67028, + 5843,67028,49155,67028, 5876,65869,49155,65869, 483,67118, 6267,65869, + 9,67123, 6367,67125, 6403,67125, 6407,67125,60419,65869,56555,67133, +60425,67135,60429,67135,60433,67135, 5325,65869, 483,67142,55005,65869, + 9,67147, 5843,65869,56555,67150, 1011,67150, 483,67150,12023,65869, +11986,65869, 4608,65869,11985,65869, 483,67164, 3681,65869,56555,67168, + 3709,65869,56555,67172, 3357,65869,56555,67176,52840,65869, 4593,65869, + 483,67182,54202,65869,54159,67187,46863,67189, 4801,65869, 483,67192, +54129,65869,54256,67196,46863,67196,54225,67200,54225,67196,46863,67204, +17669,65869, 483,67208, 5313,65869,56555,67212, 483,67212,15309,65869, + 413,67218,15383,67221, 413,67219,15335,67225,54225,65869,54154,67228, +46863,67228,54129,67232,54129,67228,46863,67236, 1274,65868, 6,67241, + 4,67242,66785,67245,66997,67245, 4,67241, 6,67250,66785,67253, +66997,67253,67011,67241,66805,67241, 8,67241,66997,67263,66785,67263, + 1368,65868, 1,67269, 2,67270,66825,67273,66973,67273, 2,67269, + 1,67278,66825,67281,66973,67281,66987,67269,66845,67269,56554,67269, +66973,67291,66825,67291, 586,65868,24265,67297,28233,67297,29077,67297, +19559,67297, 8251,67297,20361,67297, 9673,67297,20713,67297, 4283,67297, + 9967,67297, 4279,67297, 3807,67297, 482,65869, 903,67323, 1,67325, + 0,67325, 1,67324,67329,67331, 0,67324,67327,67335, 587,65868, +31690,67339,31103,67339, 713,67342, 713,67339,31103,67346,48408,67339, +46863,67339, 483,67352, 483,67339,46863,67356, 483,65868,57577,67361, +57253,67361,19987,67361,59109,67361,57381,67361, 1369,65868, 1275,65868, +47953,67375,48062,67375,47961,67375,48009,67380,48009,67375,47961,67384, +47580,67375,47933,67389,46863,67375, 265,67393,48009,67395, 265,67392, +47933,67399, 265,67375,46863,67403,47961,67405,46863,67402,47933,67409, + 1368,65869,48009,67413,49321,67413,49001,67413, 265,67413,46863,67421, + 586,65869,58056,67425,58601,67425,40799,67425,44243,67425,56555,67432, +35927,67425,38155,67425,37611,67425, 375,67425, 510,67425, 9,67425, + 483,67446,56555,67425,44243,67450, 483,67425, 9,67454, 843,65869, + 9,67459,15705,65869, 9,67463,10001,67465,13755,67465,15733,67465, +27533,67465,17455,65869,56555,67474, 1347,67474, 1011,67474, 767,65869, +56555,67483, 1471,67485, 253,67485, 809,67485, 771,67485, 53,67485, + 1347,65869,17455,67496, 567,65869, 9,67501,10033,65869,27691,65869, +10035,65869,27978,65869,26331,67511,23755,67511,27805,67511, 256,65869, +25793,67519,59875,67519,41019,67519, 8495,67519,53391,67519, 9805,67519, + 972,65869,25793,67533,41019,67533, 8495,67533,20762,65869,58715,67541, + 375,67541, 154,65869,40909,67547,49204,65869, 11,67550, 33,67553, + 11,67551, 25,67557, 1369,67551,37409,67551, 340,65869,25793,67565, +41019,67565, 8717,67565, 8495,67565, 3785,67565,49514,65869, 66,65869, + 33,67579,46863,67581,46863,67578, 33,67585, 112,65869,44243,67589, +27785,65869, 257,65869,67373,67595,31103,67594,31103,65869,27021,67601, +27377,67603,27021,67600,27323,67607, 25,67600, 713,67600, 305,67600, +63493,67600, 8861,67600, 9195,67600,52915,67600, 1369,67601, 587,67601, + 713,67627, 903,67600, 241,67600, 587,67600, 759,67635,49713,67600, + 257,67600, 165,65869,60857,67642,31926,65869,27021,65869,27323,67649, +31103,67651,31103,67648,27323,67655,52915,65869,31103,67658, 305,65869, + 8647,67662,31103,67662, 25,65869,49283,67668,47546,67668,31103,67668, + 113,67668,46863,67676,46863,67668, 113,67680,20501,65869, 15,67684, +59787,67687,21529,67687, 9513,67687, 803,67685, 1141,65869,13737,67697, + 33,65869,13737,67701, 331,65869,18967,67704, 251,67707, 21,67707, + 555,67707, 59,65869,18967,67714, 251,67717, 21,67717, 177,67717, + 555,67717, 8861,65869,60796,67727,60797,67727,60796,67726,67731,67733, +31103,67726,60797,67726,67729,67739, 375,67726,63493,65869,60796,67745, +60797,67745,31103,67744,60797,67744,67747,67753,60796,67744,67749,67757, + 375,67744, 413,65869,15309,67762,15383,67765,15309,67763,15363,67769, +46863,67762,32805,65869, 9,67775, 483,67774,46863,67774, 1216,65869, +46863,67782,65076,65869, 9,67787, 483,67786,46863,67786,56156,65869, + 483,67794,56555,67794,56555,65869,56156,67800,63014,67800,62538,67800, + 3357,67800,17455,67800, 5313,67800, 5843,67800, 3681,67800, 3709,67800, +46863,67800,49713,67820,60857,67820, 11,67821,49713,67800,46863,67828, + 483,67800,60857,67832, 11,67801,46863,67837,60857,67800, 9,67841, + 483,67840,46863,67840,15029,67800, 7,67849, 903,65869,31103,67852, +22957,67852,47608,67852,48408,67852,46863,67852, 1011,67862, 483,67862, + 483,67852,46863,67868, 7,67852,25793,67873,41019,67873, 8495,67873, + 1011,67852,46863,67880,28715,67852, 7,67885,21605,65869, 15,67889, +31103,67891, 7,67888,26331,67895,23755,67895,27805,67895, 7,67889, +26219,67903,49713,65869,58782,67906,48408,67906, 483,67906,46863,67912, +31103,67906,56555,67906,46863,67918, 3,67907,31103,67923,46863,67906, + 483,67926,56555,67926, 241,65869,31103,67932,48408,67932,46863,67932, + 483,67938, 483,67932,46863,67942, 7,67932,25793,67947,59875,67947, +41019,67947, 8495,67947,53391,67947, 9805,67947,56555,67933, 7,67961, + 9,65869,25545,67964,62942,67964,60857,67964, 1011,67970, 1011,67964, +60857,67974,25545,65869, 7,67979, 483,67978, 9,67978,46863,67978, +46863,65869,37844,67988,37896,67989,37844,67989, 6,67994,37845,67988, +67993,67999,67997,67999,67995,67999,37897,67999,54262,67988,54219,67988, + 120,67988, 77,67988, 6,67989,37844,68017,37844,68016,67999,68021, +32805,67988,37845,67989,68019,68027,67991,68027,37899,68027,37897,67989, +67991,68035,54129,67988,54225,68038,52692,67988,58334,67988,65076,67988, +54225,67988,54129,68048,25545,67988, 66,67988, 33,68055,62942,67988, + 25,67988, 113,68060, 113,67988, 25,68064, 506,67988, 1086,67988, + 1281,67988, 1216,67988, 413,67988, 922,67988, 1413,67988,16937,67988, + 587,67989, 483,68085, 483,67988,49713,68088, 241,68088, 587,68089, + 903,68088, 241,67988, 483,68098, 903,67988, 1011,68102, 483,68102, + 1275,67989,56555,67988,49713,68110,60857,68110, 11,68111,60857,67988, +56555,68118, 1011,68118, 1011,67988,60857,68124, 903,68124, 11,68125, + 587,68124, 587,67988, 1011,68134, 2,67988, 3,67988, 11,68140, + 33,68143, 11,68141, 25,68147, 1369,68141,37409,68141, 2,67989, + 3,67989, 483,68157,49713,67988,56555,68160, 483,68160, 11,67988, + 3,68166, 33,68169, 3,68167, 113,68173, 15,65869,10095,68176, +10093,68179,54643,68177,54655,68183,49537,68177,49529,68187,54655,68176, +54643,68191,49529,68176,49537,68195,16091,68176, 9513,68199,60125,68176, +59787,68203,16859,68177, 9875,68207,21529,68177,20501,68211, 1,68176, + 2,68215, 1,68216,68177,68219, 7,68216,68221,68223, 7,68215, + 2,68226, 1368,68215, 6,68176, 2,68233, 6,68234,68177,68237, + 0,68234,68239,68241, 0,68233, 2,68244,18966,68233,56554,68176, + 2,68251, 7,68252, 7,68251, 2,68256, 1368,68251, 482,68176, + 2,68263, 0,68264, 0,68263, 2,68268,18966,68263,20501,68176, + 9513,68275,59787,68275,21529,68275, 9875,68176,59787,68283, 9513,68283, +16859,68283,59787,68177,60125,68291, 9875,68291,20501,68291, 9513,68177, +16091,68299,20501,68299, 9875,68299, 483,68177, 2007,68307, 3477,68307, +68267,68307,68271,68307, 5197,68307,68241,68307,68247,68307, 1,68307, +19051,68307,19667,68307, 5123,68307,12345,68307,68249,68307,68273,68307, +18967,68307, 555,68337,68233,68337,68263,68337,56555,68177,59637,68345, +59717,68345,68255,68345,68259,68345,68223,68345,68229,68345, 6,68345, +59649,68345,39747,68345,43837,68345,43027,68345,68231,68345,68261,68345, + 1369,68345,59619,68373,68215,68373,68251,68373,18967,68176,19553,68381, +19549,68381,20345,68381,20281,68381, 7,68381,68345,68391,68359,68381, +10093,68381,10085,68381,20285,68381,10087,68381,19555,68381, 483,68381, +20273,68407,10081,68407,19545,68407, 1369,68176,67281,68415,67273,68415, + 3587,68415, 1989,68415, 0,68415,68307,68425,68323,68415,56681,68415, +57911,68415, 4897,68415,17041,68415,67291,68415,56555,68415, 1471,68441, +67269,68441, 3,68176,40909,68447, 3,68177,40895,68451,40059,68451, +43749,68451,38903,68451,18967,65869,20347,68460,20345,68463, 1203,68461, + 1205,68467, 1009,68461, 1007,68471, 1205,68460, 1203,68475, 1007,68460, + 1009,68479, 97,68460, 21,68483, 571,68460, 555,68487, 177,68461, + 59,68491, 1365,68461, 1325,68495, 2,68460, 6,68499, 2,68500, +68461,68503, 5,68500,68505,68507, 5,68499, 6,68510, 14,68499, + 4,68460, 6,68517, 4,68518,68461,68521, 3,68518,68523,68525, + 3,68517, 6,68528, 1274,68517, 482,68460, 6,68535, 5,68536, + 5,68535, 6,68540, 14,68535, 8,68460, 6,68547, 3,68548, + 3,68547, 6,68552, 1274,68547, 256,68461, 629,68461, 1325,68460, + 21,68563, 251,68563, 555,68563, 1365,68563, 59,68460, 555,68573, + 251,68573, 21,68573, 177,68573, 555,68461, 571,68583, 331,68583, + 59,68583, 1325,68583, 21,68461, 97,68593, 331,68593, 1325,68593, + 59,68593, 331,68460, 251,68603, 555,68603, 21,68603, 251,68461, + 331,68611, 59,68611, 1325,68611, 9,68461, 7951,68619, 7961,68619, +68551,68619,68555,68619,68451,68619,68525,68619,68531,68619, 2,68619, + 7953,68619,35893,68619,38299,68619,37897,68619,68533,68619,68557,68619, + 1275,68619, 7947,68649,68517,68649,68547,68649, 483,68461, 9517,68657, + 9525,68657,68539,68657,68543,68657,20033,68657,68507,68657,68513,68657, + 4,68657, 9519,68657,57855,68657,60853,68657,60609,68657,68515,68657, +68545,68657, 15,68657, 9513,68687,68499,68687,68535,68687, 1275,68460, +67245,68695,67253,68695,10041,68695,10005,68695, 5,68695,68657,68705, +68673,68695,10009,68695,23879,68695,31937,68695,30399,68695,67263,68695, + 9,68695,10001,68721,67241,68721, 15,68460,19549,68727,19553,68727, +10093,68727,10085,68727, 3,68727,68619,68737,68635,68727,20345,68727, +20281,68727,10087,68727,20285,68727,19555,68727, 483,68727,10081,68753, +20273,68753,19545,68753, 7,68460,58715,68761, 375,68761, 7,68461, +58703,68767,58027,68767,60849,68767,68345,68767,35603,68767, 59,68767, + 1325,68767, 331,68767, 265,68767, 241,68766, 241,68461, 6,68789, + 7,68789, 6,68788,68793,68795, 7,68788,68791,68799, 265,68460, + 375,68803, 1011,65869,59960,68807,61780,68806,63014,68806,62538,68806, +17455,68806,47640,68806, 5843,68806,48534,68806, 483,68806,60857,68824, + 9,68806,60857,68828,46863,68806,60857,68832, 903,68832, 11,68833, + 587,68832, 587,68806,46863,68842, 11,68807,46863,68847, 7,68807, +56555,68850,63823,68851, 9377,68851, 903,68806,46863,68858,56555,68807, + 6,68863, 7,68863, 6,68862,68867,68869, 7,68862,68865,68873, +60857,68806, 7,68877, 483,68876,46863,68876, 9,68876,62942,65869, + 7,68887,46863,68886, 9,68886, 483,68886,60857,65869,58782,68896, +58362,68896,47608,68896, 1108,68896, 1072,68896, 165,68896, 524,68896, + 1291,68896, 11,68897, 483,68915, 9,68896, 1011,68918, 587,68897, + 483,68923,46863,68896,56555,68926, 1011,68926, 483,68896,56555,68932, + 587,68933, 11,68933, 1011,68932, 11,68932, 11,68896, 483,68944, + 7,68897, 1141,68949, 1447,68949, 33,68949,56555,68896, 9,68957, +46863,68956, 483,68956, 1011,68896, 7,68965, 9,68964, 483,68964, +46863,68964, 265,65869,16710,68974,44242,68974,16711,68974,16710,68975, +68981,68983,45086,68975,44242,68975, 3,68988,44243,68974,68987,68993, +68991,68993,60797,68975,60796,68974,68999,69001,60796,68975,60797,68974, +69005,69007, 3,68975,44242,69011,44242,69010,68993,69015, 6,69010, + 1274,68975,44243,68975,69013,69023,45087,68975,68979,69027,16711,68975, +68977,69031, 1275,68975, 4899,69035,14611,69035,47961,69035, 11,68974, + 9,69043,46863,68974,69019,69047,69021,69047, 9,68975, 11,69053, + 6,68974, 0,69056,69035,69059, 7,68974,25793,69063,41019,69063, + 8717,69063, 8495,69063, 3785,69063, 6,68975, 3,69074,69047,69077, + 7,68975, 8647,69081,21605,68975, 375,69085,18967,68974, 375,69089, + 11,65869,39085,69093,49204,69092, 33,69097, 803,69093,63014,69092, +25381,69092, 265,69092, 9,69107,60857,69092, 483,69110, 483,69092, +60857,69114, 1275,69092, 9,69119, 2,69092,44243,69123, 3,69092, + 33,69127,46863,69129,46863,69126, 33,69133, 3,69093,49283,69137, +47546,69137, 113,69137,46863,69142,46863,69137, 113,69146,46863,69092, + 3,69150, 33,69153, 3,69151, 113,69157,20034,65869, 375,69161, +48560,65869, 3,69164, 33,69167, 3,69165, 113,69171,59206,65869, + 7,69175,29598,65869, 7,69179,60455,65869, 256,69183, 375,69183, + 7,69183, 241,69188, 241,69183, 7,69192,15029,65869,56555,69196, + 7,69199,28715,65869, 256,69203, 1505,69202, 7,69203, 241,69208, + 241,69203, 7,69212, 903,69202, 7,69217,54027,65869, 375,69221, + 2,69220,54159,69225,46863,69227, 2,69221,54256,69231,46863,69231, +54225,69234,54225,69231,46863,69238,17635,65869, 7,69243, 2,69244, + 2,69245, 1368,69243, 1369,69243, 2,69242,69253,69255, 3,69242, +69247,69259,69251,69259, 2,69243, 7,69264,69259,69267, 3,69243, +69249,69271, 2,65868,41692,69275,41607,69275, 8672,69275, 8743,69275, +26454,69275,26375,69275, 8770,69275, 8729,69275, 3795,69275,47953,69275, +48062,69275,47961,69275,48009,69298,48009,69275,47961,69302,41417,69275, +41653,69306,26219,69275,26415,69310,31770,69275,44832,69275, 8757,69275, + 8647,69318,26415,69275,26219,69322,41653,69275,41417,69326, 8647,69275, + 305,69330, 8757,69330, 8605,69275,47580,69275,47933,69339, 8684,69275, + 8717,69343, 8916,69275,31103,69275, 9,69348,26292,69275,26331,69353, + 340,69275, 8717,69357, 3785,69357, 8495,69357, 375,69275, 8861,69364, +46863,69364,47488,69275,41502,69275,41559,69373, 483,69275,44243,69376, + 305,69275, 8647,69380, 7,69275, 1,69385, 264,69386, 264,69387, +41019,69385,41653,69393,25793,69385,26415,69397, 8495,69385, 305,69401, + 8757,69401, 8495,69384, 8717,69407,25793,69384,26331,69411, 265,69385, +69391,69415, 8861,69415,46863,69415,41019,69384,41559,69423, 265,69384, + 8717,69427,69389,69427, 3785,69427, 8495,69427,44243,69275, 483,69436, + 9,69275,31103,69440,46863,69275, 265,69445,48009,69447, 265,69444, +47933,69451, 375,69444,25793,69275, 7,69457,26219,69459, 7,69456, +26331,69463, 265,69275,46863,69467,47961,69469,46863,69466,47933,69473, + 7,69467, 8647,69477, 7,69466, 8717,69481, 3785,69481, 8495,69481, +41019,69275, 7,69489,41417,69491, 7,69488,41559,69495, 8495,69275, + 7,69498, 8717,69501, 7,69499, 8647,69505, 8861,69275, 375,69508, + 3,65868,21116,69513,21253,69513,21560,69513,20465,69513,20576,69513, +59683,69513,42035,69513, 9573,69513,59689,69513, 9575,69513,42041,69513, +43711,69513,42089,69513,42129,69513, 1,69513, 6,69543,68974,69544, +68975,69545,69547,69549,68974,69545,68975,69544,69553,69555, 4,69513, + 6,69558,66665,69561,66785,69561,66997,69561,68695,69561, 9599,69513, + 8,69513,66997,69573,66785,69573,66665,69573,68695,69573,67011,69513, +66805,69513,68721,69513,66693,69513,60569,69513,59701,69513,59767,69513, + 9605,69513,32468,69513,28483,69513,19625,69513,20501,69602,43015,69513, +44714,69513,19474,69513,20413,69611,20805,69513,20186,69513,21549,69513, +20501,69618,21105,69513,20501,69622, 1418,69513,59619,69627, 9565,69627, +41941,69627, 669,69513, 9565,69635,59619,69635,41941,69635,37501,69513, +31103,69513,27021,69644, 8386,69513,50657,69513,36944,69513,48408,69513, + 1369,69513, 15,69656, 9565,69659,41941,69659,59619,69659, 483,69513, +46863,69666,20501,69513,21105,69670,21549,69670,19625,69670, 6,69513, + 3,69679,56555,69681,65869,69683, 4,69678,66665,69687,66785,69687, +66997,69687,68695,69687,69685,69687, 3,69678,68460,69699,69687,69701, +18967,69699,65869,69704,69687,69707,65869,69699,18967,69710,69687,69713, + 7,69513,20103,69716, 8337,69716,36773,69716,27021,69513,31103,69724, + 7,69512,24265,69729,28233,69729,29077,69729,20361,69729, 9673,69729, + 4279,69729, 9967,69729,19559,69729, 4283,69729,20713,69729, 3807,69729, + 8251,69729,44243,69513,41941,69754,46863,69513, 483,69758, 15,69513, +18967,69763,20501,69765,18967,69762,20413,69769, 1369,69762, 9565,69773, +41941,69773,59619,69773, 8337,69513, 7,69780,18967,69513, 15,69784, +20413,69787, 1011,69513,44242,69790,44242,69791,44243,69790,69795,69797, +44243,69791,69793,69801,28715,69513, 7,69805,36773,69513, 7,69808, +41941,69513,44243,69812,20103,69513, 7,69816,20273,69513, 6,69820, + 7,69820, 6,69821,69825,69827, 7,69821,69823,69831, 9617,69513, + 6,69834, 7,69834, 6,69835,69839,69841, 7,69835,69837,69845, + 6,65868, 1,69849, 3,69850, 4,69849, 3,69855,67988,69856, +67989,69857,69859,69861,67988,69857,67989,69856,69865,69867,21604,69849, + 3,69849, 1,69872, 7,65868,59007,69877,58999,69877,59025,69877, +19981,69877,48747,69877,37279,69877,57047,69877,57029,69877,58153,69877, + 1,69877, 2,69896,66625,69899,66825,69899,66973,69899,68415,69899, +58167,69877,56554,69877,66973,69911,66825,69911,66625,69911,68415,69911, +66987,69877,66845,69877,68441,69877,66653,69877,24601,69877,57437,69877, +57021,69877,57069,69877,54107,69877,52743,69877,52193,69877,20734,69877, +25551,69877,24613,69877,28205,69877,20501,69877, 265,69950, 241,69951, + 1141,69877,56555,69957,60577,69877,62959,69877,58377,69877,57981,69877, +19916,69877, 7947,69969,48739,69969,37241,69969,58931,69877,48739,69977, + 7947,69977,37241,69977, 8306,69877, 33,69877,56555,69987, 1447,69877, +56555,69991, 9875,69877, 241,69995, 265,69994, 9992,69877, 545,69877, + 695,69877, 1382,69877, 1374,69877, 1386,69877, 154,69877, 483,70013, +60455,69877, 483,70017, 1369,69877, 331,70020, 1325,70020, 59,70020, + 1325,69877, 1369,70028, 1275,69877,18967,70032,48739,70035,37241,70035, + 7947,70035, 59,69877, 1369,70042, 2,69877, 7,70047, 9,70049, +65869,70051, 1,70046,66625,70055,66825,70055,66973,70055,68415,70055, +70053,70055, 7,70046,68176,70067,70055,70069, 15,70067,65869,70072, +70055,70075,65869,70067, 15,70078,70055,70081, 3,69877, 8241,70085, + 15,70084, 483,70089, 331,69877, 1369,70092, 3,69876,24265,70097, +28233,70097,29077,70097,19559,70097,20713,70097, 4283,70097,20361,70097, + 9673,70097, 4279,70097, 9967,70097, 8251,70097, 3807,70097,18967,69877, + 1275,70122,48739,70125,37241,70125, 7947,70125, 113,70123, 1011,69877, + 265,69877,20501,70136, 8165,70136, 9875,70136,46863,69877,38056,70144, +38056,70145,38057,70144,70149,70151,38057,70145,70147,70155, 15,69877, + 3,70159, 1369,70161, 3,70158, 483,70165,54027,69877, 483,70169, + 8165,69877, 265,70172, 7,65869,69874,70176,69875,70177,70179,70181, +69875,70176,69874,70177,70185,70187,69852,70176,69853,70177,70191,70193, +69853,70176,69852,70177,70197,70199,11276,70176,11277,70176,11276,70177, +70205,70207, 5044,70176, 5045,70176, 5044,70177,70213,70215,40583,70177, +40583,70176,40582,70176,70219,70223,40582,70177,70221,70227,24094,70177, +69871,70177,69870,70177,21604,70177,69849,70236, 9,70236,21604,70176, +70233,70243,69849,70243, 9,70243, 4,70177, 0,70250, 1,70177, + 264,70254, 264,70255,24095,70177,70243,70261,45149,70177,26498,70177, +41326,70177, 8796,70177,27533,70177, 9,70273,25793,70177,27021,70277, + 587,70276, 241,70277, 5045,70177,70211,70285,11277,70177,70203,70289, + 4551,70177,10001,70177, 9,70295, 8495,70177, 305,70299, 587,70298, + 241,70299, 88,70177, 1369,70307, 587,70177,25793,70310,41019,70310, + 8495,70310, 1369,70177,20103,70319,36773,70319, 8337,70319, 265,70177, +70259,70327,63493,70327, 8861,70327,46863,70327, 89,70177,46863,70337, + 483,70177,18967,70341,37241,70343,48739,70343,70253,70343, 7947,70343, + 1275,70177,44243,70353,21605,70176,70231,70357,70235,70357,70239,70357, +70241,70357,70237,70357,69849,70367, 9,70367,26331,70357,23755,70357, +27805,70357, 241,70176,25793,70379,59875,70379,41019,70379, 8495,70379, + 9805,70379,53391,70379, 903,70176,25793,70393, 8495,70393,41019,70393, +18967,70176,58715,70401, 375,70401, 265,70176,70257,70407,25793,70407, +41019,70407, 8717,70407, 8495,70407, 3785,70407,21605,70177,70246,70421, +69849,70421,70243,70424,70248,70421,70243,70421,69849,70430, 9,70430, +24545,70421, 9,70421,70243,70438, 903,70421, 241,70177,51487,70445, + 375,70177, 1369,70449,41019,70177, 587,70452, 241,70453, 2,70176, +48009,70459, 265,70459,46863,70463,49321,70459,49001,70459, 3,70176, +58056,70471,58601,70471,40799,70471,44243,70471,56555,70478,35927,70471, + 375,70471, 510,70471, 483,70471, 9,70488,38155,70471,37611,70471, +56555,70471,44243,70496, 9,70471, 483,70500, 2,70177,44243,70505, +48466,70505,47640,70505,46863,70505, 9,70512, 903,70512, 903,70505, +46863,70518, 9,70505,46863,70522,49155,70505, 3,70177, 1369,70529, + 9,70531,37663,70529, 9,70528, 1369,70537,18967,70529,44243,70541, +69849,70177,21604,70545,70421,70547,21604,70544,70357,70551, 9,70177, +21604,70555,70421,70557,21604,70554,70357,70561, 3,70554, 1369,70565, + 3,70555, 483,70569, 3,65869,60078,70572,60079,70572,13748,70573, +13736,70572,70579,70581,13736,70573,13737,70572,13749,70573,70587,70589, + 1,70573, 5,70592, 1,70572,69385,70597,69384,70597,69275,70597, + 7,70602, 7,70603,59961,70597, 6,70596,70601,70611,70605,70611, + 7,70596,70599,70617,69275,70617, 6,70597,69275,70623,70617,70624, +70607,70623,70620,70623,70617,70623,69275,70632,56555,70623, 7,70597, +69275,70638,70611,70641,70611,70639,69275,70645,48560,70572, 33,70649, +60230,70573,57986,70573,58352,70573, 8309,70573,13737,70573, 7,70660, +70581,70663,59960,70573,70575,70667,70611,70667, 241,70666, 256,70573, +56555,70674, 11,70573,48583,70679,48328,70679, 25,70679,46863,70684, +46863,70679, 25,70688,59961,70573,70577,70693, 483,70573, 15,70697, +41941,70699, 9565,70699,70595,70699,59619,70699, 1369,70573,46863,70709, +37409,70573,46863,70713,46863,70572, 11,70716, 33,70719, 1369,70717, + 11,70717, 25,70725,37409,70717, 15,70572,40909,70731, 11,70572, + 33,70735,46863,70737,46863,70734, 33,70741, 6,70572, 1,70744, +70667,70747, 5,70744, 7,70572,70609,70753,58056,70753,70636,70753, +70623,70753,56555,70760,40799,70753,58601,70753,44243,70753,56555,70768, +35927,70753, 375,70753, 510,70753, 483,70753, 9,70778,38155,70753, +37611,70753, 9,70753, 483,70786,56555,70753,70623,70790,44243,70790, + 6,70573,70731,70797,56555,70797, 7,70573,13737,70802,70581,70805, +13737,70803,70585,70809,70611,70803,56555,70813,70747,70803,56555,70817, +70751,70803,42613,70803,56555,70823,54497,70803,54159,70803,51803,70803, +58348,70802,10291,70803,56555,70835, 59,70803, 1325,70803, 331,70803, + 1275,70803, 9,70845,56555,70802,70611,70849,70747,70849, 241,70848, + 241,70802,56555,70856, 15,70803, 483,70861,69275,70573,58348,70573, + 7,70866,38057,70573, 7,70871,43503,70573,44243,70875,56555,70573, + 256,70878, 7,70878,70611,70883,70747,70883, 241,70882, 7,70879, +70623,70891, 241,70878, 7,70894, 241,70573,44242,70899,44242,70898, +44243,70899,70903,70905,59960,70898,44243,70898,70901,70911, 7,70898, +56555,70914,56555,70898, 7,70918, 2,65869, 1,70922,69635,70925, + 668,70925,69513,70929,69627,70925, 1419,70925,69513,70935,70699,70925, +69659,70925,69773,70925, 587,70925, 9,70944,69513,70947, 9,70925, + 587,70950,69513,70953,54027,70922,54159,70957,46863,70959,54027,70923, +54154,70963,46863,70963,54129,70966,54129,70963,46863,70970,44243,70923, + 11,70975,46863,70922, 11,70922,44243,70981, 6,70922, 0,70985, + 5,70986, 5,70985, 0,70991, 0,70990, 1,70984,70995,70997, +70989,70997,70987,70997, 5,71003, 1,70985,70993,71007, 5,71007, + 0,70984, 5,71013,71007,71014,71010,71013,71007,71013, 5,71020, + 903,70985, 1,71025, 0,71025, 1,71024,71029,71031, 0,71024, +71027,71035, 7,70922,48009,71039, 265,71039,46863,71043,49321,71039, +49001,71039, 7,70923,70989,71051,70997,71052,70995,71051,70997,71056, +70998,71051,71000,71051,71005,71051,71009,71051,71017,71051,71019,71051, +71023,71051,71011,71051,71013,71075,14219,71051,14013,71051,14267,71051, +16151,71051,70997,71051,70995,71086,70989,71086,56554,71051, 1,71051, + 2,71094, 2,71051, 1,71098,14211,71051, 9165,71103, 9,71051, +65869,71107,71093,71109,71097,71109,71101,71109,70985,71051,69513,70923, + 903,70923,46862,71120,46862,71121,46863,71121,71123,71127,46863,71120, +71125,71131, 6,65869, 1,71134,70803,71137,56555,71139, 4,71134, +69977,71143,58930,71143,69877,71147,69969,71143,19917,71143,69877,71153, +70343,71143,70035,71143,70125,71143, 587,71143,56555,71162,69877,71165, +56555,71143, 587,71168,69877,71171, 2,71134, 903,71175, 1,71177, + 0,71177, 1,71176,71181,71183, 0,71176,71179,71187, 2,71135, + 265,71191, 0,71192, 1,71192, 0,71193,71197,71199, 1,71193, +71195,71203, 3,71135, 8,71207, 4,71207, 6,71210, 6,71207, + 4,71214,56555,71207,65869,71219,71209,71221,71213,71221,71217,71221, + 0, 5,59619,71229,59961,71230,60166,71229, 1207,71228,19105,71237, + 1180,71228,19119,71241,60158,71228,60180,71228,60178,71228,60318,71228, +60167,71229, 1197,71228,59875,71255,53391,71255, 9805,71255,60159,71228, +60181,71228,60179,71228,38158,71229,44195,71269, 1196,71228,60319,71228, +28739,71229, 2,71277,29229,71279, 59,71228,60221,71283,63823,71228, +61747,71287,61585,71287,61475,71287,63185,71287, 39,71228,56555,71297, + 15,71299, 6,71298,71301,71303, 14,71299, 7,71298,71307,71309, + 1163,71228,19119,71313, 25,71228,61747,71317,63185,71317,25461,71317, +61585,71317,70985,71228,71086,71327,70997,71327,71051,71330,71051,71327, +70997,71334,38057,71229, 6,71338,44195,71341,60973,71229, 1179,71345, +49213,71229,49217,71349,54619,71229, 11,71353,54655,71355, 1003,71229, +60857,71359, 1007,71361,11995,71228,12025,71365,64569,71228,64587,71369, +61989,71228,61747,71373,63185,71373,61585,71373, 8065,71229, 11,71381, + 8067,71383,63777,71229,60857,71387,63779,71389,21918,71229, 987,71393, +54336,71229,54339,71397, 989,71229,21605,71400, 987,71403,21890,71229, + 1179,71407,49262,71229,49217,71411,54331,71229, 17,71414,54339,71417, +25395,71228,25461,71421, 1293,71228,61475,71425,25433,71228,25461,71429, +61005,71228,61475,71433,63014,71228, 5,71437, 7,71438, 7,71437, + 5,71442, 10,71437, 524,71228, 0,71449, 3,71450, 3,71449, + 0,71454,60856,71449,21904,71229, 25,71461, 809,71229,21605,71464, + 713,71467,13755,71229, 17,71470, 9377,71473,65054,71229,63823,71477, + 117,71229,21605,71480, 25,71483,21916,71229, 713,71487,13764,71229, + 9377,71491,65037,71229, 17,71494,63823,71497, 1177,71229,21605,71500, + 1179,71503,49229,71229, 17,71506,49217,71509,26867,71229,21605,71512, +26865,71515,10161,71229, 17,71518,10159,71521,26868,71229,26865,71525, +10162,71229,10159,71529, 1180,71229, 2975,71533, 1903,71533,19025,71533, +33464,71229,34655,71541,34447,71541,33221,71541,33773,71541, 1207,71229, +19027,71551, 3567,71551, 1973,71551, 3041,71551, 1921,71551,19049,71551, + 9824,71229,71273,71565,53462,71229,71273,71569,59900,71229,71273,71573, +60319,71229,71251,71577,60159,71229,71245,71581,60178,71229,71267,71585, +59901,71229,71255,71589,60158,71229,71263,71593,60180,71229,71265,71597, +25461,71229, 25,71601,25395,71601,25433,71601,61475,71229,63823,71609, + 1293,71609,61005,71609,65808,71229,65513,71617,65791,71617,65407,71617, +65171,71617,60835,71229,60318,71229,71275,71629, 9617,71629,19797,71229, + 375,71635,20735,71229,47386,71229,20040,71229,20050,71229,61747,71229, +63823,71647, 25,71647,61989,71647,63185,71229, 25,71655,63823,71655, +61989,71655,61585,71229,63823,71663, 25,71663,61989,71663,20056,71229, + 375,71671, 9825,71229,71255,71675,53463,71229,71255,71679,57562,71229, +58846,71229,58372,71229,58758,71229,58762,71229,57224,71229,57284,71229, +57278,71229,58760,71229,20686,71229,24738,71229, 305,71703, 713,71703, + 1489,71703, 25,71703,10074,71229, 9377,71713,17573,71713,63823,71713, +22766,71229, 305,71721, 25,71721, 147,71721, 713,71721,27672,71229, +63823,71731,27995,71731, 9377,71731,62147,71229, 25,71739, 305,71739, + 147,71739, 169,71739, 713,71739,31881,71229,63823,71751,27995,71751, +31359,71751, 9377,71751,60221,71229, 59,71761, 653,71229, 11,71765, + 9993,71229,17542,71229, 9936,71229,24734,71229, 305,71775, 713,71775, + 25,71775,60834,71229,21350,71229,16129,71229, 3,71787, 2,71787, + 842,71787, 843,71786,71793,71795, 843,71787, 842,71786,71799,71801, + 3,71786,71791,71805, 2,71786,71789,71809,16966,71229,19480,71229, +50522,71229,52740,71229,57380,71229,59108,71229,50478,71229,57252,71229, +19986,71229,51036,71229,57576,71229,58112,71229,58362,71229, 903,71836, +47640,71229,56555,71840,60179,71229,71249,71845,60181,71229,71247,71849, +63015,71229,71441,71853,71445,71853,62905,71853,63041,71853,63047,71853, +63215,71853, 6,71853,63205,71867,19687,71853,21127,71853,20843,71853, +63049,71853,71447,71853, 11,71853,63033,71881,71437,71881,19917,71229, + 9,71886, 525,71229,71453,71891,71457,71891,36729,71891, 1851,71891, + 1885,71891,35635,71891, 2,71891,35633,71905,62095,71891,17711,71891, + 4907,71891,61003,71891,71459,71891,60857,71891, 531,71919,71449,71919, + 1413,71229, 331,71925,49713,71924, 1419,71229,56555,71930,58782,71229, + 903,71934, 296,71229, 8861,71939, 1106,71229,18967,71943, 9617,71943, +24095,71229,46863,71949,57522,71229, 11,71953, 903,71952, 587,71952, +51004,71229, 483,71960,22956,71229,70471,71965,70753,71965,10159,71965, +26865,71965,10111,71965,26715,71965,23709,71965,23713,71965,67425,71965, +10113,71965,26719,71965,23715,71965, 587,71965,10107,71991,26625,71991, +23651,71991,19475,71229, 483,71998, 918,71229,56555,72002, 922,71229, +56555,72006,49713,72006, 668,71229,56555,72012, 1290,71229, 2,72017, +35575,72019,35585,72017, 3621,72017, 1991,72017,60969,72017,62095,72017, +17711,72017, 4907,72017,60857,72017, 1325,72037,58930,71229, 9,72040, +52692,71229, 903,72044,25380,71229, 6,72049,38881,72051,38891,72049, + 9927,72049, 9891,72049, 9895,72049,19687,72049,21127,72049,20843,72049, + 11,72049, 9875,72069, 1447,71229,15705,72073, 9917,71229,20615,71229, + 759,71229,17455,72081, 9195,71229, 1487,72085, 1471,71229,21605,72088, + 305,72091, 713,72091, 1489,72091, 25,72091, 9805,71229, 1197,72101, + 1275,72101, 9,72105, 1197,72100,71273,72109,10001,71229, 17,72112, + 9377,72115,17573,72115,63823,72115,17455,71229,12377,72122,59961,71229, +59619,72126, 1011,72126, 9617,72131, 1011,72127, 9565,72135,59619,72135, + 89,71229,17455,72141,60797,71229,59381,72144, 165,71229,21315,72148, + 587,71229,66971,72153,17455,72153,57522,72152, 9,72152,56555,72160, +56555,72152, 9,72164,60857,72153, 9,72169, 1369,71229,39085,72173, +21605,72172,20843,72177,21127,72177, 9927,72177, 9891,72177,19687,72177, + 9895,72177, 11,72177, 9875,72191, 1275,71229, 17,72194, 4907,72197, +17711,72197, 3621,72197, 1991,72197,62095,72197,60969,72197,60857,72197, + 1325,72211, 483,71229,20035,72214,58742,72214,19475,72214,51004,72214, +56555,72214, 903,72224, 903,72214,56555,72228,49713,72228,49713,72214, + 903,72234,55839,71229,46863,72239,65061,71229,60857,72243,65063,72245, +65067,72245,65071,72245, 7065,71229,18967,72253, 6789,71229, 11,72257, + 6843,72259, 6885,72259, 6889,72259,11277,71229,46863,72267, 9935,71229, + 1011,72270,20645,71229, 1011,72274, 3445,71229, 375,72279, 5045,71229, +46863,72283,17104,71229,48643,72287,12614,71229, 375,72291,69872,71229, +68155,72295,71116,71229,71013,72299,70985,71229,71013,72303,71051,72305, +71051,72302,71013,72309,71051,71229,70985,72313,70997,72315,70985,72312, +71013,72319, 482,71228,23717,72323,24522,72323,24447,72323,23939,72328, +23939,72323,24447,72332,22956,72323,23651,72337,21605,72323, 17,72341, +23939,72343, 17,72340,23651,72347, 17,72323,21605,72351,24447,72353, +21605,72350,23651,72357, 1368,71228, 7,72361, 5,72362,72049,72365, +72177,72365, 5,72361, 7,72370,72049,72373,72177,72373,72191,72361, +72069,72361, 10,72361,72177,72383,72049,72383,27021,72361,24095,72361, + 9195,72361,52915,72361,23651,72361,51435,72361,21605,72361, 9,72401, +67297,72361,70097,72361,69729,72361,11277,72361, 5045,72361,10171,72361, +53941,72361, 9755,72361,26907,72361, 4321,72361,27323,72361, 3833,72361, + 9317,72361, 4295,72361,53215,72361, 1274,71228, 3,72435, 0,72436, +72017,72439,72197,72439, 0,72435, 3,72444,72017,72447,72197,72447, +72211,72435,72037,72435,60856,72435,72197,72457,72017,72457, 586,71228, +39619,72463,51421,72463,57811,72463,59933,72463,59743,72463, 8093,72463, + 3837,72463,42435,72463, 4287,72463,53703,72463, 4303,72463,42113,72463, + 9839,72463,53487,72463, 9579,72463, 483,72463, 803,72494, 828,72463, + 705,72463, 803,72463, 483,72502, 482,71229,66737,72507,36661,72507, +62741,72507,68727,72507,68381,72507, 1274,71229, 587,71228,61747,72521, +25461,72521,61475,72521,63185,72521,61585,72521, 483,71228,56555,72533, + 6,72535, 5,72536, 7,72535, 5,72535, 6,72542, 6,72543, +72541,72547, 6,72534, 15,72535,72551,72553, 7,72534,72545,72557, +72539,72557, 14,72535,72557,72563, 1368,71229,55839,72567,51803,72567, +54159,72567,54497,72567, 265,72567, 1275,71228,59914,72579,60221,72579, +18708,72579, 9856,72579,53504,72579, 9805,72579, 9,72590,53391,72579, + 9,72594,59875,72579, 9,72598,18693,72579, 9,72602,60369,72579, + 9,72579,18693,72608, 9805,72608,59875,72608,53391,72608, 586,71229, + 33,72619, 1447,72619, 1141,72619, 889,72619, 795,72619, 787,72619, + 767,72619, 483,72633, 1505,71229,16937,72636,56555,72636, 581,71229, +60857,72643, 1325,72645, 331,72645, 571,72645, 585,72645, 59,72645, +16937,71229, 1505,72656,13947,71229, 2,72661,14217,72663, 11,72661, + 9875,72667,16091,72667,13955,72667,20501,72667, 9919,71229,20623,71229, + 9921,71229, 1196,71229,72103,72683,71256,72683,71258,72683,71260,72683, +71255,72683,59875,72692,53391,72692, 9805,72692,59875,72683,71255,72700, + 9805,72683,71255,72704,53391,72683,71255,72708, 154,71229,64148,71229, + 1325,72715, 59,72715, 331,72715, 265,72715,52501,71229, 265,72725, + 297,71229,18967,72729, 1107,71229,59960,71229,21105,72735,65513,72735, +65791,72735,65407,72735,21549,72735,19625,72735,65171,72735,59619,72735, + 15,72735, 88,71229,70177,72755,70176,72754,72757,72759,70176,72755, +70177,72754,72763,72765, 1141,72755, 1447,72755, 33,72755, 11,72755, +37409,72755, 972,71229, 59,72779, 1325,72779, 331,72779,27978,71229, +60796,71229,59381,72789,31102,71229,62905,72793,68761,72793,70401,72793, +67541,72793, 164,71229,36729,72803,68447,72803,70731,72803,67547,72803, +54596,71229,44243,72813,20695,71229, 155,71229,20763,71229, 375,72820, + 1197,71229,71273,72825,59875,72827, 9805,72827,53391,72827,53391,72824, +71273,72835, 9805,72824,71273,72839,59875,72824,71273,72843, 375,71229, +20763,72846,20836,71229, 1141,71229,15705,72853, 33,71229,15705,72857, +27021,71229, 1487,72861, 959,71229,17455,72865,52915,71229, 1487,72869, + 47,71229,17455,72873,59875,71229, 1197,72877,72683,72879, 1275,72877, + 9,72883, 1197,72876,71273,72887, 253,71229,21605,72890, 305,72893, + 25,72893, 713,72893,53391,71229, 1197,72901,72683,72903, 1275,72901, + 9,72907, 1197,72900,71273,72911, 53,71229,21605,72914, 305,72917, + 25,72917, 147,72917, 713,72917,27533,71229, 17,72926,63823,72929, +27995,72929, 9377,72929,30749,71229, 7,72937,26970,71229, 7,72941, +70864,71229, 7,72945,69849,71229, 3,72948,68155,72951, 3,72949, +67577,72955,68139,72955,70979,72955,69275,71229,70573,72962, 7,72965, +69513,71229, 1011,72968, 7,72971, 9780,71229, 7,72975,59381,71229, + 2,72979,72789,72981,60797,72978, 6,72978,56555,72986,72981,72989, +26625,71229, 1011,72992, 7,72995, 9731,71229, 1011,72998, 7,73001, +69790,71229, 7,73005, 13,71229,32805,71229, 7,73010,33221,73013, +34655,73013,33773,73013,34447,73013, 15,73011,34875,73023, 7,73011, +34723,73027, 19,71229, 59,73031, 18,71229,65076,71229, 7,73037, +65493,73039, 7,73036,65171,73043,65791,73043,65513,73043,65407,73043, + 15,73037,65357,73053, 12,71229,68974,71229, 375,73059,71119,71229, + 7,73063, 1011,71229,52387,73067,20762,73067,59961,73066, 9617,73073, +20645,73066, 9935,73066, 17,73066,18967,73081, 9617,73081, 6,73066, + 7,73067,18967,73088,26625,73066, 7,73093,18967,73067, 7,73096, + 17,73097, 9731,73066, 7,73103,69513,73066, 7,73107,21315,73066, + 7,73111, 15,71229,18967,73115, 17,73117, 3,73114, 3,73115, +72567,73123, 17,73114, 265,71229, 9,73128, 8861,73131,60857,73129, + 9,73135,65869,73128, 375,73139, 11,71229,60857,73143, 9,73145, + 1275,73143, 9,73149, 9,73142,60857,71229, 7,73154, 59,73157, + 1325,73157, 331,73157, 265,73157, 7,73155, 375,73167, 265,73155, + 375,73171,12377,73154, 7,73175,18967,71229, 7,73179,25793,73181, +41019,73181, 8495,73181,46863,71229,20035,73188,58742,73188, 903,73188, +56555,73194,56555,73188, 903,73198,20035,71229,21183,73203, 7,73203, + 331,73207, 483,73202,46863,73202, 9,73202, 7,73202, 375,73217, +49713,71229,39085,73221, 136,73220, 1197,73220, 137,73220, 922,73220, + 1413,73220, 1011,73220, 6,73234, 483,73220, 903,73238, 903,73220, + 483,73242, 2,73220, 9,73246,44243,73247, 3,73220, 5,73253, + 6,73255, 9,73253, 2,73221,73257,73261,73229,73261,73258,73261, +29229,73261,72683,73261,73237,73261,73087,73261, 9,73261,73253,73276, +73253,73261, 9,73280, 3,73221,73225,73285,73249,73285,73227,73285, +73247,73285, 9,73293, 9,73220, 2,73296,73285,73299, 2,73297, +73253,73303, 17,71229,10161,73306,10159,73309,54339,73307,54331,73313, +49217,73307,49229,73317,54331,73306,54339,73321,49229,73306,49217,73325, +65037,73306,63823,73329,13755,73306, 9377,73333,27995,73307,27533,73337, +17573,73307,10001,73341, 7,73306, 3,73345, 7,73346,73307,73349, + 1,73346,73351,73353, 1,73345, 3,73356,21604,73345, 0,73306, + 3,73363, 0,73364,73307,73367, 6,73364,73369,73371, 6,73363, + 3,73374, 1274,73363, 586,73306, 3,73381, 1,73382, 1,73381, + 3,73386,21604,73381,60856,73306, 3,73393, 6,73394, 6,73393, + 3,73398, 1274,73393,10001,73306,63823,73405, 9377,73405,17573,73405, +27533,73306, 9377,73413,63823,73413,27995,73413, 9377,73307,13755,73421, +27533,73421,10001,73421,63823,73307,65037,73429,10001,73429,27533,73429, +60857,73307,63697,73437,63779,73437,73397,73437,73401,73437,73371,73437, +73377,73437, 7,73437,63709,73437,35893,73437,37897,73437,38299,73437, +73379,73437,73403,73437, 1275,73437,63679,73465,73363,73465,73393,73465, + 587,73307, 1971,73473, 3507,73473,73385,73473,73389,73473, 5231,73473, +73353,73473,73359,73473, 0,73473,21783,73473,23983,73473, 4625,73473, +10603,73473,73361,73473,73391,73473,21605,73473, 713,73503,73345,73503, +73381,73503, 1011,73306,18967,73511, 9617,73511, 1275,73306,72439,73517, +72447,73517, 3621,73517, 1991,73517, 1,73517,73473,73527,73489,73517, +60969,73517,62095,73517, 4907,73517,17711,73517,72457,73517,60857,73517, + 1325,73543,72435,73543,21605,73306,23713,73549,23709,73549,26865,73549, +26715,73549, 6,73549,73437,73559,73451,73549,10159,73549,10111,73549, +26719,73549,10113,73549,67425,73549,70753,73549,70471,73549,23715,73549, + 587,73549,26625,73581,10107,73581,23651,73581, 1011,73307, 9565,73589, + 2,73306,36729,73593,68447,73593,67547,73593,70731,73593, 2,73307, +36727,73603,68451,73603,37895,73603,36079,73603,35575,73603, 15,73306, +21605,71229,26867,73616,26865,73619, 1179,73617, 1177,73623, 987,73617, + 989,73627, 1177,73616, 1179,73631, 989,73616, 987,73635, 809,73616, + 713,73639, 117,73616, 25,73643, 1489,73617, 1471,73647, 147,73617, + 53,73651,26219,73617, 5,73616, 7,73657, 5,73658,73617,73661, + 2,73658,73663,73665, 2,73657, 7,73668, 1368,73657, 3,73616, + 7,73675, 3,73676,73617,73679, 4,73676,73681,73683, 4,73675, + 7,73686, 16,73675, 10,73616, 7,73693, 2,73694, 2,73693, + 7,73698, 1368,73693, 586,73616, 7,73705, 4,73706, 4,73705, + 7,73710, 16,73705,44243,73617,48466,73617, 340,73617, 1397,73617, + 53,73616, 713,73725, 305,73725, 25,73725, 147,73725, 1471,73616, + 25,73735, 305,73735, 713,73735, 1489,73735, 25,73617, 117,73745, + 253,73745, 1471,73745, 53,73745, 713,73617, 809,73755, 253,73755, + 53,73755, 1471,73755, 253,73616, 305,73765, 25,73765, 713,73765, + 305,73617, 253,73773, 1471,73773, 53,73773, 9,73617,46863,73780, + 587,73617, 9381,73785, 9439,73785,73709,73785,73713,73785,25519,73785, +73683,73785,73689,73785, 5,73785, 9383,73785,62077,73785,64317,73785, +64815,73785,73691,73785,73715,73785, 17,73785, 9377,73815,73675,73815, +73705,73815, 11,73617, 7979,73823, 8067,73823,73697,73823,73701,73823, +73603,73823,73665,73823,73671,73823, 3,73823, 7981,73823,39747,73823, +43027,73823,43837,73823,73673,73823,73703,73823, 1369,73823, 7971,73853, +73657,73853,73693,73853, 17,73616,23709,73861,23713,73861,10159,73861, +10111,73861, 2,73861,73823,73871,73839,73861,26865,73861,26715,73861, +10113,73861,26719,73861,67425,73861,70471,73861,70753,73861,23715,73861, + 587,73861,10107,73893,26625,73893,23651,73893, 1369,73616,72365,73901, +72373,73901, 9927,73901, 9891,73901, 4,73901,73785,73911,73801,73901, + 9895,73901,19687,73901,20843,73901,21127,73901,72383,73901, 11,73901, + 9875,73927,72361,73927,46863,73617, 9,73932, 6,73616,62905,73937, +68761,73937,70401,73937,67541,73937, 7,73616, 6,73617,62883,73949, +68767,73949,64267,73949,62235,73949,38881,73949,73437,73949,73947,73949, +72787,73949, 7,73617,25793,73967,41019,73967, 8495,73967,73937,73967, +72793,73967, 265,73966, 265,73617, 6,73981, 7,73981, 6,73980, +73985,73987, 7,73980,73983,73991, 903,71229,64148,73995,57522,73994, +58782,73994,58362,73994,52501,73995,52692,73994,46863,73994,56555,74008, + 9,73994,56555,74012, 483,73994,56555,74016,49713,74016,49713,73994, + 483,74022, 15,73995, 483,74027, 7,73994, 59,74031, 1325,74031, + 331,74031, 7,73995,60857,74038,59875,74039, 375,74039, 9805,74039, +53391,74039,60857,73995, 6,74051, 7,74051, 6,74050,74055,74057, + 7,74050,74053,74061,56555,73994, 7,74065,46863,74064, 483,74064, + 9,74064,58742,71229, 7,74075, 9,74074,46863,74074, 483,74074, +56555,71229,43502,74085,21036,74085, 6,74089, 6,74088,43503,74085, + 6,74095, 6,74094,21037,74085,59634,74085,59635,74085, 6,74105, + 6,74104,21104,74085,59645,74085,43838,74085,21548,74085,21526,74085, + 5,74118,59644,74085,19624,74085,18967,74085, 5,74126, 6,74128, + 6,74129, 6,74126, 5,74134, 6,74127, 14,74126,38305,74085, + 2,74142,59619,74085, 2,74146, 5,74085,59961,74151, 6,74151, +21526,74150, 6,74150,18967,74158,18967,74150, 6,74162, 6,74163, + 2,74085,59619,74168,38305,74168, 14,74085,18967,74174,21527,74085, +74155,74179, 9,74179,19625,74085,21549,74085,43839,74085,21105,74085, +47640,74084, 922,74084, 918,74084, 1505,74084, 668,74084, 1419,74084, + 483,74084, 903,74204, 11,74085, 9,74209, 15,74085,74139,74213, +46863,74084, 903,74216, 9,74084, 11,74221, 903,74220, 587,74220, + 587,74084, 9,74228, 6,74084,74191,74233,74189,74233,74187,74233, +74113,74233,74087,74233,74101,74233,74103,74233,74171,74233,74169,74233, +59619,74251,74149,74233,72981,74233,74185,74233,74145,74233,74173,74233, +74213,74233,59381,74233, 7,74084,74093,74269,74099,74269,74123,74269, +74109,74269,74159,74269,74089,74269,74095,74269,74105,74269,74151,74269, +74111,74269,74115,74269,74117,74269,74157,74269,74121,74269,21105,74269, +21549,74269,65513,74269,65791,74269,65407,74269,74125,74269,19625,74269, +65171,74269,74175,74269,74131,74269,74129,74269,74137,74269,74177,74269, +74161,74269,74165,74269,74163,74269,74141,74269,59619,74269, 15,74269, + 6,74085,21036,74336,74269,74339,43503,74336,74269,74343,59635,74336, +74269,74347, 5,74336,74269,74351,18967,74350,74269,74355,18967,74336, + 5,74358,74269,74361, 7,74085,74091,74365,74097,74365,74107,74365, +74155,74365,21183,74365,65493,74365,74133,74365,74167,74365, 9,74365, + 959,74365, 47,74365, 759,74365, 903,74084, 7,74391, 483,74390, + 9,74390,46863,74390, 9,71229,20035,74400,58742,74400,58930,74400, +19917,74400, 903,74400,56555,74410, 265,74400, 8861,74415, 587,74400, +56555,74418,56555,74400, 11,74423, 903,74422, 587,74422, 265,74401, + 8495,74431, 11,74431, 3,74400,70177,74437,70176,74436,74439,74441, +70176,74437,70177,74436,74445,74447, 1141,74437, 1447,74437, 33,74437, + 11,74437,37409,74437, 3,74401, 113,74461, 11,74400,21522,71229, + 7,74467,63452,71229, 7,74471,13673,71229, 7,74475,17049,71229, + 3,74478,48643,74481, 2,74479, 3,74479,48637,74487,49581,74487, +47813,74487,21315,71229, 165,74494, 1011,74494, 7,74499,16163,71229, + 2,74503,72683,74505,73087,74505,16171,74505, 375,74503,64669,71229, + 7,74515, 265,74517,12377,71229, 256,74521,17455,74520, 7,74520, + 375,74527, 7,74521, 241,74530, 331,74531,60857,74520, 7,74537, + 241,74521, 7,74540,10385,71229, 375,74545,70899,71229, 7,74549, +18391,71229, 7,74553,18617,71229, 7,74557,12705,71229, 7,74561, +70573,71229,69275,74564, 7,74567, 3,71228,74332,74571,72750,74571, +71253,74571,72985,74571,72147,74571,71783,74571,71577,74571,67600,74571, +45491,74571,42800,74571,59710,74571,74365,74593,74269,74571,59619,74596, +72735,74571,59619,74600,59694,74571,60563,74571, 629,74571, 101,74571, + 705,74571, 299,74571, 128,74571, 828,74571, 394,74571,48122,74571, +70327,74571,66930,74571, 9606,74571,10374,74571, 113,74571, 9,74632, +74465,74571,73153,74571,73031,74571,73057,74571,73131,74571,71939,74571, +72733,74571,74415,74571,72145,74571,59381,74653,42134,74571,10291,74571, + 17,74658,51992,74571, 375,74571, 241,74664,65869,74664,49713,74664, +60796,74571,74213,74673, 256,74571, 803,74571, 483,74678, 483,74571, + 803,74682,31103,74571,65869,74686, 6,74571,59619,74690,74365,74693, +56555,74690,74213,74697, 7,74571, 241,74700, 7,74570,57811,74705, +59933,74705,59743,74705, 9839,74705, 9579,74705,39619,74705,51421,74705, + 4287,74705, 4303,74705, 8093,74705, 3837,74705,53487,74705,42113,74705, +42435,74705,53703,74705,42613,74571, 17,74736,46863,74571,12377,74740, + 9,74571, 113,74744,49713,74571, 375,74748, 17,74571,42613,74752, +59619,74752,10291,74752, 9565,74752,41941,74752, 9565,74571, 7,74765, + 17,74764,65869,74571,60796,74771,60797,74771,31103,74770,60797,74770, +74773,74779,60796,74770,74775,74783, 375,74770, 241,74571, 375,74788, + 7,74788,56555,74571, 5,74795,74269,74797,72735,74797, 6,74797, +74365,74803, 6,74796,74269,74807,72735,74807, 14,74795,72735,74813, +74269,74813, 15,74795, 6,74795, 5,74820,74269,74823,72735,74823, + 7,74795,74803,74829, 6,74794,74213,74833,74819,74833, 7,74794, +74807,74839,74823,74839,71229,74838,74807,74845,74823,74845,74797,74845, +74813,74845,74813,74839,12377,74571,46863,74856,41941,74571, 7,74861, + 17,74860,59619,74571,74269,74866,72735,74866, 6,74866,74365,74873, + 6,74867,74269,74877,72735,74877, 7,74867, 17,74866, 2,71228, +71233,74887,56555,74887,72129,74887,72127,74887,59619,74895,71235,74887, +72790,74887,71627,74887,74153,74887,74155,74887,74365,74906,74372,74887, +74158,74887,74269,74913,74279,74887,74350,74887,74269,74919,74353,74887, +74266,74887,74150,74887, 6,74927,74365,74929, 6,74926,74269,74933, +74269,74927,74287,74887,74336,74887, 5,74940,74269,74943,60261,74887, +71629,74887,63737,74887,37179,74887, 9535,74887,63743,74887, 9537,74887, +37185,74887,74264,74887,74174,74887,74269,74965,74315,74887,73073,74887, +37887,74887,37205,74887,37235,74887,74085,74887, 5,74978, 6,74981, +74365,74983, 6,74980,74269,74987,74269,74981, 6,74978, 5,74992, +74269,74995, 6,74979,74213,74999, 14,74978,74269,75003, 5,74887, +74336,75006,74269,75009,74085,75006, 6,75013,74365,75015, 6,75012, +74269,75019,74269,75013,74085,75007,74233,75025, 6,75006,72735,75029, +74085,75028,74269,75033,74269,75029,74085,75029,74233,75039, 7,75006, +71853,75043,72049,75043,72177,75043,73901,75043, 6,75007,74365,75053, + 7,75007,72131,74887,72753,74887,74335,74887, 9563,74887,74382,74887, + 10,74887,72177,75069,72049,75069,71853,75069,73901,75069, 14,74887, +74085,75079,74233,75081,74085,75078,74269,75085,72735,75079,74269,75079, +72191,74887,72069,74887,73927,74887,71881,74887,64759,74887,63763,74887, +63813,74887, 9559,74887,74213,74887,74233,75108,74365,74887,74155,75112, + 9,75112,43123,74887,42606,74887,53318,74887, 9362,74887,27218,74887, +28189,74887,74233,74887,59381,75130,74213,75130,72789,74887,59381,75136, +64289,74887,26182,74887,28991,74887, 8804,74887,54289,74887,53802,74887, + 8150,74887, 1290,74887,63679,75155, 9533,75155,37145,75155, 525,74887, + 9533,75163,63679,75163,37145,75163, 922,74887, 1413,74887,73615,74887, +73127,74887,73009,74887,73035,74887,73081,74887,71943,74887,72729,74887, +73511,74887,41762,74887, 7971,74887, 9,75192,53517,74887, 9,75196, + 483,74887, 903,75200, 9195,74887, 9,75204, 1275,74887, 17,75208, + 9533,75211,37145,75211,63679,75211,27021,74887, 9,75218, 7,74887, + 2,75223,60857,75225,71229,75227, 5,75222,71853,75231,72049,75231, +72177,75231,73901,75231,75229,75231, 2,75222,73616,75243,75231,75245, +21605,75243,71229,75248,75231,75251,71229,75243,21605,75254,75231,75257, + 6,74887,74150,75260,74269,75263,74085,75260, 5,75266,74269,75269, +56555,75261,71229,75272,74085,75261,74155,75277, 9,75277, 5,75260, +72735,75283,74085,75282,74269,75287,74269,75283,74085,75283,74233,75293, +75275,75283, 11,75261,21604,75299,21604,75298,21605,75299,75303,75305, +21605,75298,75301,75309,52915,74887, 9,75312, 6,74886,23717,75317, +24522,75317,24447,75317,23939,75322,23939,75317,24447,75326,22956,75317, +23651,75331, 17,75317,21605,75335,24447,75337,21605,75334,23651,75341, +21605,75317, 17,75345,23939,75347, 17,75344,23651,75351, 7,74886, +27021,75355,24095,75355, 9195,75355,52915,75355,21605,75355, 9,75365, +67297,75355,26907,75355, 9755,75355, 9317,75355, 3833,75355,23651,75355, +51435,75355,27323,75355, 4321,75355,69729,75355,53215,75355, 4295,75355, +70097,75355,53941,75355,10171,75355, 5045,75355,11277,75355,42155,74887, + 9,75402, 19,74887, 12,74887, 11,74887, 9,75410, 9,74887, +74365,75414,42155,75414,27021,75414,52915,75414, 9195,75414,25793,75414, +53517,75414, 7971,75414, 8495,75414,41019,75414, 11,75414, 17,74887, + 1275,75438, 9533,75441,37145,75441,63679,75441, 8495,74887, 9,75448, + 903,74887, 483,75452,21605,74887,26219,75457,42810,75456,75056,75456, +75057,75457,75463,75465,75053,75457,42810,75457,75057,75456,75056,75457, +75473,75475,42811,75456,75471,75479,42811,75457,75461,75483,44243,75457, + 375,75457, 6,75457, 7,75457,25793,75493, 6,75456,75493,75497, + 7,75456,75491,75501,41019,74887, 9,75504,59381,74887,72789,75508, +74233,75508,25793,74887, 9,75514,26625,74887, 6,75518, 7,75518, + 6,75519,75523,75525, 7,75519,75521,75529, 9731,74887, 6,75532, + 7,75532, 6,75533,75537,75539, 7,75533,75535,75543,69513,74887, + 6,75546, 7,75546, 6,75547,75551,75553, 7,75547,75549,75557, + 7,71228,73276,75561,27306,75561,73261,75561, 9,75566,24095,75561, +52603,75561,53910,75561,55537,75561,20053,75561,20831,75561,19783,75561, +64289,75561,27021,75561,25793,75586, 265,75587, 959,75561,60857,75593, +58775,75561, 5045,75561,11277,75561, 4551,75561,70136,75561,10196,75561, + 273,75561, 1477,75561, 281,75561, 948,75561, 1516,75561, 922,75561, + 1413,75561,52915,75561, 265,75623, 47,75561,60857,75627,25793,75561, +27021,75630, 9195,75561, 265,75635, 759,75561,60857,75639, 89,75561, + 5019,75643,60857,75643, 1505,75561, 1011,75648, 587,75561,60857,75653, +70573,75653, 1369,75561,43503,75659, 483,75561, 903,75662, 165,75561, + 903,75666, 1141,75561,18967,75671, 1447,75561,18967,75675, 2,75561, +61780,75679, 9,75679,60857,75682,54295,75679,70085,75679,53925,75679, +10155,75679,11529,75679,60857,75679, 9,75696, 3,75561,73221,75701, + 9,75703, 8063,75701,53667,75701,42361,75701, 33,75561,18967,75713, + 2,75560,27021,75717,24095,75717, 9195,75717,52915,75717,21605,75717, + 9,75727,67297,75717,23651,75717,51435,75717,27323,75717, 4321,75717, + 9755,75717,26907,75717, 9317,75717, 3833,75717,69729,75717,53941,75717, +10171,75717,70097,75717,53215,75717, 4295,75717, 5045,75717,11277,75717, + 3,75560,57811,75765,59933,75765,59743,75765,39619,75765,51421,75765, + 4287,75765, 4303,75765, 9839,75765, 9579,75765, 8093,75765, 3837,75765, +42113,75765,53487,75765,42435,75765,53703,75765, 265,75561,53813,75796, +69877,75796,10107,75796, 1011,75561, 1505,75804,54597,75805,21605,75561, + 9,75811, 145,75811, 903,75561, 165,75816, 483,75816,54295,75817, + 9,75561,73261,75824,69877,75561, 265,75828,10107,75561, 265,75832, +53813,75561, 265,75836, 6,71228,63091,75841,63099,75841,63117,75841, +25451,75841,53597,75841,42283,75841,61289,75841,61281,75841,62345,75841, + 0,75841, 3,75860,71891,75863,72017,75863,72197,75863,73517,75863, + 3,75861,62359,75841,60856,75841,72197,75877,72017,75877,71891,75877, +73517,75877,72211,75841,72037,75841,73543,75841,71919,75841,19739,75841, +61649,75841,61263,75841,61323,75841,20763,75841, 1011,75903, 1010,75902, +75905,75907, 1010,75903, 1011,75902,75911,75913,25380,75841, 7971,75917, +53517,75917,42155,75917,63015,75841,53517,75925, 7971,75925,42155,75925, + 1369,75841,21605,75932,53517,75935,42155,75935, 7971,75935, 3,75841, + 6,75943, 11,75945,71229,75947, 0,75942,71891,75951,72017,75951, +72197,75951,73517,75951,75949,75951, 6,75942,73306,75963,75951,75965, + 17,75963,71229,75968,75951,75971,71229,75963, 17,75974,75951,75977, + 2,75841,60857,75981, 16,75983, 16,75982, 17,75983,75987,75989, + 17,75982,75985,75993, 2,75840,23717,75997,24522,75997,23939,75997, +24447,76002,24447,75997,23939,76006,22956,75997,23651,76011,21605,75997, + 17,76015,23939,76017, 17,76014,23651,76021, 17,75997,21605,76025, +24447,76027,21605,76024,23651,76031,21605,75841, 1369,76034,53517,76037, +42155,76037, 7971,76037, 17,75841,37844,76044,75872,76044,75873,76045, +76049,76051,37844,76045,75873,76044,75872,76045,76057,76059,37845,76044, +76055,76063,37845,76045,76047,76067, 7,71229,74797,76071,74829,76073, + 264,76071, 5,76071, 3,76078, 3,76079, 5,76070,75925,76085, +63014,76085,75841,76089,75917,76085,25381,76085,75841,76095,75935,76085, +76037,76085, 483,76085,60857,76102,75841,76105,60857,76085, 483,76108, +75841,76111,32805,76070,34655,76115,33773,76115,34447,76115,33221,76115, +32805,76071,34003,76125,33319,76125,34447,76071,35031,76131,65407,76071, +65335,76135,65076,76070,65513,76139,65791,76139,65407,76139,65171,76139, +65076,76071,65625,76149,65267,76149,20035,76070, 375,76155,74794,76071, +59381,76159,74819,76159,74571,76071,56555,76165,59619,76167,56555,76164, +59381,76171,12377,76070, 375,76175,49204,76071, 1369,76071, 241,76181, +56555,76071,74571,76184,59381,76187,59381,76185,74571,76191,49205,76071, +65869,76195, 1275,76071, 903,76199,60857,76070, 59,76203, 1325,76203, + 331,76203, 265,76203, 903,76070, 59,76213, 1325,76213, 331,76213, +56555,76070,74877,76221,74866,76221,65513,76221,65791,76221,65407,76221, +74807,76221,74823,76221,74797,76221,21105,76221,75029,76221,75283,76221, +21549,76221,19625,76221,65171,76221,75079,76221,74813,76221,59619,76221, +74571,76254,74571,76221,59619,76258, 15,76221,74887,76263,21605,76070, +73949,76267, 265,76071,63823,76271,63679,76271,72619,76271, 9377,76271, + 9533,76271,37145,76271, 2,76070,76077,76285,76081,76285,55839,76285, +54159,76285,54497,76285,51803,76285,73123,76285,76179,76285,65869,76301, + 265,76285, 3,76070,76196,76307,67988,76307, 33,76307, 1447,76307, + 1141,76307,76271,76307,76195,76307,65869,76320, 9,76307,46863,76307, +65869,76326,65869,76307,76195,76330,46863,76330, 2,76071,76310,76337, +76328,76337,76334,76337,76083,76337, 10,76337, 5,76337, 7,76348, + 7,76337, 5,76352,55803,76337,54225,76337,54477,76337,51593,76337, +67988,76337,76307,76364,64345,76337,76324,76337,73121,76337,72713,76337, +76326,76337,65869,76376, 9,76337,76307,76380,60857,76337,71229,76385, +76347,76387,76351,76387,76355,76387, 903,76337,46863,76337,76330,76396, +65869,76396,76307,76400,76307,76396,65869,76404,76330,76337,46863,76408, +65869,76337,76326,76412,46863,76412,76307,76416,76307,76412,46863,76420, +76307,76337,67988,76424, 9,76424,46863,76424,65869,76430,65869,76424, +46863,76434, 3,76071, 5,76438,76285,76441, 113,76439,46863,76438, +76285,76447,65869,76449,76285,76439,67988,76453, 9,76453,46863,76453, +65869,76458,65869,76453,46863,76462, 15,76071,74485,76467,73261,76467, +46863,76071, 3,76472,76285,76475,65869,76477, 3,76473,76412,76481, +65869,76481,76337,76484,76337,76481,65869,76488,65869,76070, 375,76493, +70176,71229, 375,76497, 3,71229,70554,76500, 5,76501, 1,76505, +71229,76507, 2,76509,59961,76505,74887,76513, 6,76505,76511,76517, +73261,76517, 0,76500,75163,76523, 524,76523,74887,76527,75155,76523, + 1291,76523,74887,76533,75211,76523,75441,76523, 483,76523, 11,76540, +74887,76543, 11,76523, 483,76546,74887,76549, 33,76501, 9,76553, + 8147,76501,42315,76501,53777,76501,70555,76500,70176,76500, 9,76565, +43848,76501,70177,76501,76563,76571,76566,76571, 9,76571,76565,76576, +76565,76571, 9,76580, 1141,76501, 9,76585, 1447,76501, 9,76589, +69849,76500,68155,76593,17049,76500,48643,76597, 1369,76501, 803,76601, + 15,76500,76337,76605,37409,76501, 9,76609, 9,76500,70177,76613, +76565,76615,70177,76612, 1141,76613, 1447,76613, 33,76613, 11,76613, +37409,76613, 11,76501, 9,76631, 6,76500, 7,76500, 33,76637, + 1447,76637, 1141,76637,76271,76637, 6,76501,60856,76647, 0,76647, + 3,76650, 3,76647, 0,76654, 11,76647,71229,76659,76649,76661, +76653,76661,76657,76661, 7,76501,43503,76668,70177,76500, 9,76672, +70176,76501,76619,76677,76503,76677,76675,76677,76673,76677, 9,76685, +43503,76501, 7,76688, 17,76689, 1011,76501, 375,76695, 7,76695, +18967,76501, 4,76700, 5,76700,76071,76705, 6,76704, 6,76705, +76070,76701,76709,76713,76705,76713, 14,76700,76713,76719,71229,76701, + 7,76723,76711,76725, 7,76722,76709,76729,76705,76729,76719,76729, + 15,76723,76071,76701,76703,76739, 15,76700,76739,76743, 6,76700, + 5,76746,76729,76749,76713,76749, 7,76700,76707,76755,76711,76755, + 6,76701,76743,76761,76737,76761, 7,76701,76749,76767,76709,76767, +71229,76766,76749,76773,76709,76773,76705,76773,76719,76773,76719,76767, +65869,76500,68155,76785,68109,76785, 256,76785, 7,76785, 241,76792, + 241,76785, 7,76796,70572,71229,68155,76801,68109,76801, 256,76801, + 7,76801, 241,76808, 241,76801, 7,76812, 2,71229, 0,76817, + 4,76818, 0,76816, 2,76823, 5,76816,62284,76817,62186,76817, +64248,76817,62504,76817,64205,76817,61690,76817,52501,76817,70021,76817, +17496,76817,11179,76817,10187,76817,53967,76817,17455,76817, 9,76852, +16065,76817, 16,76857, 16,76856, 17,76857,76861,76863, 17,76856, +76859,76867,70802,76817, 340,76817,60857,76872,64148,76817, 265,76876, + 9,76817,17455,76880, 375,76817,60857,76884, 587,76817, 17,76889, +37145,76891, 9533,76891,76523,76891,76821,76891,63679,76891,44243,76817, +60857,76902,49713,76903, 17,76816,36729,76909,68447,76909,67547,76909, +70731,76909,49713,76816,44243,76919,54295,76817, 9,76923, 6,76816, +66737,76927,36661,76927,62741,76927,68381,76927,68727,76927, 7,76816, +54497,76939,55839,76939,54159,76939,51803,76939,73123,76939, 265,76939, + 7,76817,62494,76952,70573,76952, 265,76952,60857,76958,60857,76952, + 265,76962, 265,76953,60857,76967,62494,76817, 7,76970,43215,76817, + 9,76975, 265,76817,64148,76978, 483,76979, 7,76978,60857,76984, +60857,76978, 7,76988,60857,76817,42810,76993,42810,76992,42811,76993, +76997,76999, 375,76992, 340,76992,42811,76992,76995,77007,44243,76992, + 6,76992, 7,76992, 265,77014, 6,76993,77015,77019, 7,76993, +77013,77023, 265,76993, 7,77027, 265,76992, 7,77030,65869,76817, +69275,77035, 7,77037,70573,76817, 6,77041, 7,77041, 6,77040, +77045,77047, 7,77040,77043,77051,65869,76816,69716,77055, 7,77055, +69513,77058,69513,77055, 7,77062,70922,71229,69716,77067, 7,77067, +69513,77070,69513,77067, 7,77074, 6,71229,74890,77079,59619,77081, +38056,77078, 5,77084,76825,77079,76827,77089,55814,77078,55815,77079, +77093,77095,55815,77078,55814,77079,77099,77101, 1346,77078, 1346,77079, + 1347,77078,77107,77109,17126,77079,17125,77079, 2,77114,17127,77079, + 9565,77119,74169,77079,59619,77123,60621,77079,59619,77127,38056,77079, +38057,77078,44195,77133,58303,77079, 1010,77079, 1010,77078,77119,77141, +35187,77079, 2,77144, 0,77079, 4,77149, 2,77151,71229,77152, +71229,77151, 2,77156, 2,77157,76816,77151, 1011,77149,71229,77165, + 5,77079, 1,77168, 5,77078,38056,77173,77133,77175, 2,77172, +58302,77079,77141,77181, 9565,77181,59619,77181,20501,77079, 1011,77189, + 1010,77188,77191,77193, 1010,77189, 1011,77188,77197,77199, 567,77079, +21604,77203,21604,77202,21605,77203,77207,77209,21605,77202,77205,77213, + 1347,77079,77105,77217,74887,77079,56555,77220,59619,77223,56555,77221, +59381,77227, 9875,77079, 1011,77231, 1010,77230,77233,77235, 1010,77231, + 1011,77230,77239,77241,56555,77079,74887,77244,59619,77247,59619,77245, +74887,77251, 1011,77244, 9565,77255,77141,77255,59619,77255, 1011,77245, + 9617,77263,77139,77263,74887,77263, 587,77079,21605,77271,42155,77273, +53517,77273,76085,77273,77171,77273, 7971,77273, 1011,77078,77113,77285, +77117,77285,74505,77285,77131,77285,77137,77285,77147,77285,73261,77285, +38057,77079,77179,77301,77087,77301,41941,77301,76827,77301, 9565,77301, +59619,77301,77141,77301,56555,77078,72981,77317,75508,77317,74887,77317, +59381,77322,59381,77317,74887,77326,21605,77078,62905,77331,68761,77331, +67541,77331,70401,77331,73967,77331, 1011,77079,56555,77343,59381,77345, +56555,77342,59619,77349,77141,77349, 9565,77349, 2,77078,66737,77357, + 5,77356,77301,77361,62741,77357,36661,77357,68727,77357,68381,77357, + 3,77078,77161,77373, 2,77079,17125,77376,77285,77379,35187,77376, +77285,77383, 3,77079,77155,77387,77159,77387,77163,77387,77167,77387, + 11,77079,37844,77397,37844,77396,37845,77397,77401,77403,37845,77396, +77399,77407,65869,71229, 1530,77410, 842,77410,48535,77410, 669,77410, + 1419,77410,49514,77410, 136,77410,49515,77410, 137,77410, 843,77411, +77415,77431, 1531,77411,77413,77435, 843,77410, 1530,77411, 1531,77410, +77441,77443, 842,77411,77439,77447, 1418,77410,48534,77410, 668,77410, + 587,77410,46863,77456, 9,77456, 1369,77410, 15,77462, 9,77410, + 2,77467, 2,77466, 587,77466, 265,77410, 375,77475, 15,77410, + 1369,77478,46863,77410, 2,77483, 2,77482, 587,77482, 7,77411, + 59,77491, 1325,77491, 331,77491, 265,77491, 6,77410,77491,77501, + 2,77503, 3,77503, 2,77502,77507,77509, 3,77502,77505,77513, + 3,77411,67577,77517,77425,77517,77423,77517,68139,77517,70979,77517, +77455,77517,77453,77517,77421,77517,77471,77517,77487,77517,77461,77517, +77459,77517,77473,77517,77489,77517, 7,77517, 1011,77517, 7,77549, + 2,77410, 9,77552,77517,77555,46863,77552,77517,77559,69716,77553, +77546,77553, 7,77553,69513,77566,77517,77566,69513,77553, 7,77572, +77517,77553, 6,77577, 7,77577, 6,77576,77581,77583, 7,77576, +77579,77587, 2,77411,76517,77591,29229,77591,72789,77591,77429,77591, +77427,77591,72683,77591,74233,77591,77317,77591,77451,77591,77419,77591, +77417,77591,77285,77591,73087,77591,77465,77591,77481,77591, 7,77591, +70573,77591, 7,77625, 3,77410, 4,77628,77591,77631, 1,77628, + 5,77628, 0,77628,77591,77639, 5,77629, 6,77643,77591,77645, +68155,77629,77469,77629,77485,77629,68109,77629,77623,77629,77631,77657, +77639,77657, 256,77629,77622,77629,77635,77665,77637,77665, 6,77629, +77632,77671,77640,77671,77631,77671,77591,77676,77639,77671,77591,77680, +77591,77671,77631,77684,77639,77684, 7,77629,77635,77691,77591,77693, +77637,77691,77591,77697, 241,77690,77591,77690,77635,77703,77637,77703, + 241,77629, 7,77708,77591,77629, 6,77713, 7,77713, 6,77712, +77717,77719, 7,77712,77635,77723,77637,77723,77715,77723, 6,77411, + 7,77410, 375,77733,77731,77733, 2,77737, 3,77737, 2,77736, +77741,77743, 3,77736,77739,77747, 1, 6,18363,77751, 4389,77751, +18362,77751, 4388,77751,70572,77750,70667,77761,70849,77761,70803,77761, +56555,77767,70883,77761, 272,77751, 8997,77773, 4425,77773, 8452,77751, + 251,77779, 8841,77779, 8453,77751, 273,77751, 4139,77751, 8429,77751, + 4138,77751, 8428,77751,70879,77751,70797,77797,18257,77751, 465,77801, + 445,77751,17827,77805, 4371,77751, 265,77808,18339,77751, 265,77812, +64953,77751, 375,77817,14888,77751, 375,77821,13569,77751, 375,77825, + 4137,77751, 265,77828, 8401,77751, 265,77832, 413,77750,77835,77837, +77831,77837,77795,77837,77793,77837,77815,77837,77811,77837,77757,77837, +77759,77837, 241,77837, 1217,77750, 412,77750, 8401,77859, 4137,77859, +18339,77859, 4371,77859,77791,77859,77789,77859,77753,77859,77755,77859, + 1216,77750,40461,77751, 9,77879,59573,77751, 375,77883,69467,77751, + 375,77887, 7047,77751, 412,77891, 413,77890,77893,77895, 413,77891, + 412,77890,77899,77901,12615,77751, 375,77905,45880,77751,46275,77909, +33390,77751,34003,77913,77462,77751,77591,77917,65232,77751,65625,77921, + 923,77751,16481,77925,16783,77925,18797,77925,25367,77751, 9,77933, +68975,77751, 375,77937,62984,77751, 9,77941, 1412,77751,17827,77945, + 412,77751,77837,77949, 1216,77751, 9137,77751, 375,77955, 253,77751, + 9136,77959, 9137,77959,17826,77959, 1,77959, 413,77966,17827,77959, + 413,77959, 1,77972, 265,77958, 8997,77977, 4425,77977,77963,77977, +77965,77977,77969,77977,77975,77977, 265,77959, 8997,77990, 8997,77959, + 265,77994, 265,77995,12377,77959, 8337,77751, 266,78003, 267,78003, + 464,78003, 6,78003, 413,78010, 465,78003, 413,78003, 6,78016, + 265,78002, 251,78021, 8841,78021,78007,78021,78009,78021,78013,78021, +78019,78021, 265,78003, 251,78034, 251,78003, 265,78038, 265,78039, + 375,78003,38057,77751, 265,77751,18339,78048,77837,78051, 4371,78048, +77837,78055, 253,78048, 8997,78059, 4425,78059, 8337,78048, 251,78065, + 8841,78065,77837,78049, 8401,78071, 4137,78071,18339,78071, 4371,78071, + 4137,78048,77837,78081, 8401,78048,77837,78085, 241,78049, 8401,78089, + 4137,78089, 1369,78048,17827,78095, 241,78048, 1011,77751,56555,78101, +60369,78103, 241,77751, 413,78107,14315,78106, 375,78111,57522,78107, +67028,78107, 265,78107,60857,78106, 9,78121,56555,78107, 9,78124, +65869,78107, 483,78128, 483,78107,65869,78132, 9,78107,56555,78136, + 265,78106, 8685,77751, 375,78143, 264,77750,78066,78147,78060,78147, +78091,78147,78093,78147,18339,78147, 4371,78147,17911,78147,13433,78147, +13411,78147,13635,78147,77978,78147,78022,78147,77999,78147,78043,78147, +77774,78147,77780,78147,64733,78147,64955,78147,78021,78147, 251,78184, +77977,78147, 8997,78188,78065,78147, 251,78192,78059,78147, 8997,78196, +77779,78147, 251,78200,77773,78147, 8997,78204, 9139,78147, 9123,78147, + 9065,78147,14935,78147,64919,78147,59463,78147,69357,78147,59533,78147, +69427,78147,59587,78147,69481,78147,78088,78147, 8401,78231, 4137,78231, + 8997,78147,78059,78236,77977,78236,77773,78236, 251,78147,78065,78244, +78021,78244,77779,78244,27979,78147,26293,78147,41503,78147, 8685,78147, +78141,78147,77949,78147,78099,78147,78049,78147, 8337,78267, 251,78269, + 253,78267, 8997,78273, 241,78266, 8401,78277, 4137,78277, 241,78267, + 1369,78147, 241,78147, 6,78287,78065,78289,78021,78289,77779,78289, + 1,78287,78059,78297,77977,78297,77773,78297,78049,78286, 8401,78305, + 4137,78305,16381,78147,19513,78147,35843,78147,13325,78147,70407,78147, +69063,78147,67565,78147, 341,78147,64669,78325, 8997,78325,59381,78325, +69275,78325,65869,78325, 241,78325, 471,78147, 367,78147, 357,78147, + 8401,78147, 4137,78147,37019,78147, 4063,78147,20219,78147, 3863,78147, +20697,78147,37377,78147, 9955,78147,10273,78147,14625,78147, 4569,78147, + 265,77750,77785,78369, 251,78371,77787,78369, 8997,78375, 253,78369, + 8997,78379, 8337,78369, 251,78383, 241,78368, 8401,78387, 4137,78387, +77791,78387,77789,78387, 241,78369, 241,77750, 8428,78399,78147,78401, + 4138,78399,78147,78405, 4137,78399, 265,78409, 265,78408,78147,78413, + 8401,78399, 265,78417, 265,78416,78147,78421, 265,78398, 8401,78425, + 4137,78425,77791,78425,77789,78425, 265,78399, 8401,78434,78147,78437, + 4137,78434,78147,78441,78147,78435, 8401,78445, 4137,78445, 240,77751, + 265,78451, 1010,77751,28337,78455, 264,77751,78426,78459,78428,78459, +78419,78459,78411,78459,78388,78459,78390,78459,77860,78459,77862,78459, +77864,78459,77866,78459,18339,78459,77859,78480, 4371,78459,77859,78484, +78381,78459,78385,78459,13381,78459,77961,78459,78005,78459,77993,78459, +78037,78459,77997,78459,78041,78459,78015,78459,77971,78459,77807,78459, +77803,78459,64746,78459,78382,78459, 251,78517,78378,78459, 8997,78521, +78035,78459, 251,78525,77991,78459, 8997,78529, 9072,78459, 9105,78459, +59470,78459,69364,78459,59521,78459,69415,78459,64931,78459, 413,78459, +77859,78459, 8401,78548, 4137,78548,18339,78548, 4371,78548,78425,78459, + 8401,78558, 4137,78558,78387,78459, 8401,78564, 4137,78564, 8401,78459, +78425,78570,78387,78570,77859,78570, 4137,78459,78425,78578,78387,78578, +77859,78578, 8337,78459,78369,78586, 251,78589, 253,78459,78369,78592, + 8997,78595,78396,78459,78119,78459,78369,78459, 8337,78602, 251,78605, + 253,78602, 8997,78609, 241,78603, 8401,78613, 4137,78613, 241,78602, +69275,78459, 375,78620,59381,78459, 375,78624, 8997,78459, 375,78628, +64669,78459, 375,78632,70327,78459,65869,78459, 375,78638,66930,78459, + 375,78459,64669,78644, 8997,78644,59381,78644,69275,78644,65869,78644, + 241,78644, 241,78459,78369,78658, 375,78658, 394,78459, 299,78459, + 1217,77751, 413,77751,77859,78671,78369,78671, 375,78671,14315,77751, + 241,78678, 375,78681, 375,78679, 341,77751,12377,78687, 257,77751, + 375,78691,70572,77751,70693,78695,70800,78695,70797,78695,56555,78700, +56555,78695,70797,78704, 1346,77751, 9,78709, 1061,77751, 9,78713, + 525,77751, 9,78717,64396,77751, 9,78721,38056,77751,29229,78725, + 9,78725, 137,77751,56555,78731, 5,78733, 4,78732,78735,78737, + 4,78733, 5,78732,78741,78743,20103,77751, 375,78747, 1471,77751, +12377,78751,36773,77751, 375,78755, 53,77751,12377,78759,45639,77751, + 1369,78762,46275,78765,32805,77751, 17,78768,34003,78771,77410,77751, + 1369,78774,77591,78777,65076,77751, 17,78780,65625,78783, 1275,77751, + 5,78786, 9,78789, 5,78787, 17,78793,35187,77751, 1196,78797, + 6,78797, 1011,78800, 137,78797, 136,78797, 1197,78797, 1413,78797, + 922,78797, 1011,78797, 6,78814, 903,78797, 483,78818, 483,78797, + 903,78822, 2,78796,78805,78827,29229,78827,78799,78827,78817,78827, +78803,78827, 9,78827, 3,78796,78807,78841,78809,78841, 2,78797, +78841,78847, 9,78849, 9,78846,78841,78853, 3,78797, 5,78857, + 6,78859,78827,78861,78838,78857, 9,78857,78827,78866,78827,78857, + 9,78870, 9,78797, 2,78875,78857,78877, 3,78875, 2,78874, +78841,78883, 3,78874, 17,77751,65076,78889,65407,78891,32805,78889, +34447,78895,20035,78889,58742,78889,65076,78888,65625,78903,32805,78888, +34003,78907, 903,78889,56555,78910,56555,78889, 903,78914,65869,78889, + 2,78919, 3,78919, 2,78918, 3,78918,18967,77751, 295,78929, + 1108,78929, 1011,78929, 9,78934, 9,78929, 1011,78938, 483,78929, +18967,78943, 5,78944, 5,78945,21036,78943,21037,78943, 4,78943, +78949,78955, 5,78943,18967,78958, 4,78942,78961,78963,78947,78963, +78951,78963, 5,78942,78953,78971, 1369,77751,12376,78974,12376,78975, +12377,78974,78979,78981,77410,78975,77517,78985,45639,78975,46599,78989, +12377,78975,78977,78993,36527,78975,68806,78975,77410,78974,77591,79001, +45639,78974,46275,79005, 1011,78975,65869,79008,65869,78975, 1011,79012, + 265,78974,17827,79017,56555,78975, 4,79021, 5,79021, 4,79020, + 5,79020,60857,77751, 241,79030, 9,79033, 5,79030, 9,79037, + 5,79031, 17,79041,70177,77751,38056,79045,38056,79044,38057,79045, +79049,79051,38057,79044,79047,79055, 375,79045,27979,77751, 375,79061, + 2,77750,68283,79065,68275,79065,36633,79065,36627,79065,39987,79065, +66423,79065,66883,79065,66405,79065,66397,79065,67687,79065,78047,79065, + 9,79087,36544,79065, 9875,79091,20501,79091,68177,79065, 9875,79097, +20501,79097,64396,79065, 9,79103, 5,79065,60857,79106, 9,79109, +35187,79065, 11,79112,20501,79115, 9875,79115, 11,79065,35187,79120, + 9875,79123,20501,79123,60857,79065, 5,79129, 17,79131, 5,79128, + 9,79135, 3,77750,40779,79139,63907,79139,73421,79139,73429,79139, +64235,79139,67465,79139,63955,79139,39027,79139,38685,79139,64073,79139, + 6,79139, 4,79161,78728,79139,78838,79139,78827,79139, 9,79168, +78725,79139, 9,79172, 9934,79139,20644,79139, 4663,79139, 903,79181, +17219,79139, 903,79185,12345,79139, 5,79189, 4,79188,79191,79193, + 4,79189, 5,79188,79197,79199, 5123,79139, 5,79203, 4,79202, +79205,79207, 4,79203, 5,79202,79211,79213,19667,79139, 5,79217, + 4,79216,79219,79221, 4,79217, 5,79216,79225,79227,73306,79139, + 9377,79231,63823,79231,40705,79139, 9377,79237,63823,79237,21036,79139, +70177,79139, 9,79245, 341,79139,64669,79249,65869,79249, 253,79139, +65869,79255, 8337,79139, 9,79259, 241,79139, 1471,79139,65869,79265, +37325,79139, 903,79269,20103,79139, 9,79273,10219,79139, 903,79277, + 4,79139,20501,79280, 9875,79280, 5,79139, 6,79287,78827,79289, +78725,79289,18967,79286, 9935,79287,20645,79287,36773,79139, 9,79301, + 53,79139,65869,79305, 5,79138,27979,79309, 8685,79309,41503,79309, +26293,79309, 1369,79309,16381,79309,13325,79309,35843,79309,19513,79309, + 8401,79309, 4137,79309,14625,79309, 4569,79309,37019,79309, 4063,79309, + 3863,79309,37377,79309,20219,79309,10273,79309, 9955,79309,20697,79309, + 9,79139,78725,79352,78827,79352,35187,79139, 1505,79359, 17,79139, +71229,79362, 9377,79365,63823,79365,21315,79363,71229,79139, 17,79372, +63823,79375, 9377,79375,18967,79139,20413,79381, 4,79383, 4,79382, +20487,79381,20486,79381,79161,79381, 4,79393, 4,79392,79163,79381, + 580,79381,49630,79381,79162,79381,46863,79381, 4,79406, 4,79407, + 483,79381, 4,79412, 4,79413,49631,79381, 581,79381, 4,79381, +20413,79422,79161,79422,46863,79422, 483,79422, 5,79381,79385,79433, +79179,79433,79283,79433,79395,79433,79411,79433,79417,79433,20413,79433, + 4,79380,79389,79449,79446,79449,79421,79449,79419,79449,79399,79449, +79433,79449,20413,79460,20413,79449,79433,79464, 5,79380,79425,79469, +79387,79469,79391,79469,79427,79469,79397,79469,79401,79469,79403,79469, +79405,79469,79429,79469,79409,79469,79431,79469,79415,79469,79423,79469, +20413,79495, 1369,79139, 5,79499,27979,79139,65869,79503, 9,79503, +20501,79139, 4,79508,79433,79511, 5,79508,18967,79514,21037,79508, + 4,79509,79517,79521,79243,79521,79295,79521,79469,79521, 5,79509, +79519,79531, 9875,79139, 4,79534, 5,79534, 4,79535, 5,79535, + 4,77750, 3,79545, 5,77750,10256,79549,37356,79549, 4745,79549, + 1011,79555,17423,79549, 1011,79559,63550,79549,64489,79549,63493,79549, + 17,79566,70803,79549,56555,79571,74752,79549, 8982,79549,74571,79549, + 17,79578, 8861,79549, 17,79582,37844,79549,27979,79549, 483,79589, + 253,79549,56555,79593, 8337,79549, 483,79597, 241,79549, 1325,79549, + 17,79602, 331,79549, 17,79606, 1328,79549, 334,79549, 53,79549, +56555,79615,20501,79549, 1011,79619,36773,79549, 483,79623, 9875,79549, + 1011,79627, 1359,79549, 393,79549, 2,79549,37325,79634,10219,79634, + 3,79549, 483,79641,35187,79640,10257,79641,37357,79641, 62,79549, + 59,79549, 17,79652,20103,79549, 483,79657, 1471,79549,56555,79661, + 3,79548,27979,79665, 8685,79665,26293,79665,41503,79665, 1369,79665, +16381,79665,13325,79665,19513,79665,35843,79665, 8401,79665, 4137,79665, +14625,79665, 4569,79665,20219,79665, 3863,79665, 4063,79665,20697,79665, +37019,79665, 9955,79665,10273,79665,37377,79665,18967,79549, 165,79709, + 1369,79549,38057,79713,35187,79549, 3,79717, 3,79716, 17,79549, +63493,79722,74571,79722, 8861,79722, 1325,79722, 331,79722, 59,79722, +37325,79549, 2,79736, 3,79736, 2,79737, 3,79737,10219,79549, + 2,79746, 3,79746, 2,79747, 3,79747, 5,77751, 1196,79756, + 1196,79757, 1197,79756,79761,79763,21604,79757, 6,79757, 587,79769, +21605,79771, 1,79757, 3,79774, 3,79775,18967,79775, 483,79781, + 1,79756,25381,79785,63014,79785,79773,79785,60857,79785, 483,79792, + 483,79785,60857,79796, 6,79756,79787,79801,63015,79801,79785,79805, +25380,79801,79785,79809,79789,79801,79783,79801,79799,79801, 1369,79801, +21605,79818,79785,79821,79795,79801,21605,79801, 1369,79826,79785,79829, + 1216,79757, 413,79757, 1197,79757,79759,79837,79546,79757, 903,79757, +20735,79757, 9993,79757, 1275,79756, 9,79849,60857,79756, 9,79853, +56555,79757, 1505,79856,21605,79757,21376,79757, 483,79757,21315,79864, +58112,79757,21315,79757, 483,79870, 1505,79757,56555,79874, 2,79756, +79767,79879, 7,79881, 6,79880,79883,79885, 6,79881, 7,79880, +79889,79891,79777,79879, 7,79895, 6,79894,79897,79899, 6,79895, + 7,79894,79903,79905,28337,79879, 3,79756,79861,79911, 7,79913, + 6,79912,79915,79917, 6,79913, 7,79912,79921,79923, 2,79757, +79779,79927, 7,79929, 6,79928,79931,79933, 6,79929, 7,79928, +79937,79939, 3,79757, 1,79942,79879,79945, 7,79947, 6,79946, +79949,79951, 6,79947, 7,79946,79955,79957,79545,79942,79545,79757, + 2,79963, 3,79963, 2,79962, 3,79962, 9,79757,63493,79973, +74571,79973, 8861,79973, 1325,79973, 331,79973, 59,79973, 3,77751, +79112,79987, 9,79989,78847,79987, 9,79993, 1216,79987,12371,79987, + 5,79999, 4,79998,80001,80003, 4,79999, 5,79998,80007,80009, + 413,79987, 375,79987,60454,79987,60369,80017, 566,79987,35187,79987, +79065,80022, 9,80025,79106,79987, 1011,79987,37407,79987,10287,79987, +65869,79987, 165,80036,38132,79987, 9,79987,38057,80042,67642,79987, +38057,79987, 9,80048, 165,79987,65869,80052, 5,79986, 4,79987, + 5,79987,79065,80060,56555,80060,60369,80065, 483,80060,79065,79987, +35187,80070, 9,80073, 4,80071, 5,80071, 4,80070, 5,80070, +56555,79987,49630,80084,46863,80084, 4,80089, 4,80088, 581,80084, + 580,80084,49631,80084, 4,80084,46863,80100, 483,80100, 5,80084, +60369,80107,80091,80107, 4,80085,80095,80113,80099,80113, 5,80085, +60327,80119,60719,80119,80097,80119,80087,80119,57901,80119,80093,80119, +80103,80119,80105,80119, 483,80084, 4,80136,80119,80139, 4,80137, +80107,80143, 483,79987, 5,80146, 2,77751,79538,80151,79541,80153, +79514,80151,79521,80157,79024,80151,79027,80161,78958,80151,78963,80165, +79021,80151, 5,80168,79027,80171, 5,80169,79023,80175,78943,80151, + 5,80178,78963,80181, 5,80179,78955,80185, 1,80151, 7,80189, + 4,80191, 4,80190, 16,80189, 4,80189, 7,80198,28714,80151, + 17,80203,79286,80151,79541,80207,79521,80207,35187,80150,79289,80213, +29229,80213,79352,80213, 9,80213,79139,80220,79139,80213, 9,80224, + 9,80151, 4,80150, 265,80231, 5,80150,80193,80235,28337,80235, + 4,80151, 1011,80241, 5,80151,80195,80245,80201,80245,79534,80245, +79543,80251,79508,80245,79531,80255,79021,80244,79027,80259,78943,80244, +78963,80263,79021,80245,79029,80267,78943,80245,78971,80271,80197,80245, +28219,80245,30475,80245,23939,80245,79139,80244,79541,80283,79521,80283, +21605,80244, 17,80289,79139,80151,35187,80293, 9,80295, 4,80293, + 5,80293,79537,80301,79511,80301,79177,80301,79179,80301,79285,80301, +79283,80301, 4,80292,80301,80315, 5,80292,79541,80319,79521,80319, +80299,80319,21605,80151, 5,80326, 17,80329, 5,80327, 9,80333, + 4,77751,79750,80337,79753,80339,79740,80337,79743,80343,78922,80337, +78925,80347,78880,80337,78883,80351,78919,80337, 3,80354,78925,80357, + 3,80355,78921,80361,78875,80337, 3,80364,78883,80367, 3,80365, +78877,80371, 6,80337, 1369,80375,56555,80377, 1,80337,60857,80381, + 1275,80383, 1,80336,58931,80387,19916,80387,80379,80387,18967,80387, + 1275,80394, 1275,80387,18967,80398, 6,80336,19917,80403,80387,80405, +80389,80403,80391,80403,58930,80403,80387,80413,80385,80403,80401,80403, + 587,80403,56555,80420,80387,80423,80397,80403,56555,80403, 587,80428, +80387,80431,43214,80337,79640,80337,79753,80437,79743,80437, 2,80336, + 265,80443, 2,80337, 903,80447, 3,80337,67988,80450,67988,80451, +67989,80450,80455,80457,79746,80451,79755,80461,79736,80451,79745,80465, +78919,80450,78925,80469,78875,80450,78883,80473,78919,80451,78927,80477, +78875,80451,78887,80481,67989,80451,80453,80485,79549,80450,79753,80489, +79743,80489,38305,80450,79549,80337, 2,80497, 3,80497,79749,80501, +79739,80501,79551,80501,79553,80501,79639,80501,79637,80501, 2,80496, +80501,80515, 3,80496,79753,80519,79743,80519,80499,80519,38305,80337, + 3,80526, 3,80527, 0, 7, 1517,80532, 2575,80535, 949,80532, + 2599,80539, 1476,80532, 2269,80543, 280,80532, 2289,80547, 272,80532, + 4437,80551, 121,80532,38343,80555, 3075,80555, 1913,80555, 76,80532, + 3005,80563, 1899,80563,38337,80563, 123,80533, 3061,80571, 81,80533, + 2997,80575, 367,80532, 7627,80579, 357,80532, 1927,80583, 397,80532, + 7895,80587, 1516,80532, 948,80532, 107,80532, 2221,80595, 203,80532, + 2215,80599, 215,80532, 4339,80603, 91,80532, 5045,80607, 1477,80532, + 281,80532, 273,80532, 317,80532,14469,80617, 67,80532,11087,80621, + 4643,80621, 2233,80621, 4625,80621, 9,80629, 53,80532, 2289,80633, + 1471,80532, 2269,80637,80012,80533,77949,80641,79834,80533,77949,80645, +79996,80533,78669,80649,79832,80533,78669,80653,78546,80533,77949,80657, +78108,80533,78141,80661,77949,80661,77855,80533,77949,80667, 416,80533, +17993,80671, 418,80533,17993,80675, 447,80533,17993,80679, 295,80532, + 294,80532, 76,80533,38587,80687,26285,80533,26390,80533,26106,80533, + 121,80533,38585,80697,26502,80533,32269,80533,31761,80533,32563,80533, +31921,80533,31591,80533,78287,80533,78141,80713,78099,80713,77949,80713, +23788,80533,27830,80533,27947,80533,41746,80533,26216,80533,41414,80533, +26126,80533,41348,80533,26328,80533,41556,80533,29029,80533,43319,80533, + 203,80533, 2211,80745,60857,80745, 85,80533, 4593,80751, 2229,80751, +60857,80751,80229,80533,39823,80533,23013,80533,39229,80533,39783,80533, +38673,80533,38675,80533, 107,80533, 5019,80773, 2219,80773,60857,80773, +80228,80533,40956,80533,45411,80783,37899,80783,41493,80533, 1517,80533, + 2573,80791,80591,80791, 949,80533, 2593,80797,80593,80797, 280,80533, + 2287,80803,80613,80803, 1476,80533, 2267,80809,80611,80809, 272,80533, + 4457,80815,80615,80815, 8673,80533, 8681,80533, 8800,80533, 8742,80533, +41622,80533, 8740,80533, 8610,80533, 8642,80533, 8638,80533,39650,80533, +42752,80533, 8717,80533, 413,80843, 1369,80842, 341,80842, 3785,80533, + 413,80851, 1369,80850, 341,80850, 413,80532, 8717,80859, 3785,80859, +13443,80859, 7627,80859, 7287,80859, 7895,80859,12755,80859, 1689,80859, + 2701,80859, 1705,80859,77859,80859,78459,80880,78548,80859,78048,80859, +77837,80887,78071,80859,18454,80859,78147,80859,78459,80859,77859,80896, + 265,80859,77751,80900,77837,80903,77751,80901,77859,80907,18391,80859, + 331,80910, 331,80859,18391,80914, 8495,80859,77751,80859, 265,80920, +77837,80923,12745,80859, 375,80927, 457,80927, 375,80859,13977,80533, +80021,80533,13767,80533, 4347,80533, 2213,80533, 2225,80533, 2231,80533, +10079,80533,79501,80533,18715,80533,18579,80533,14313,80533,80149,80533, +13945,80533, 4987,80533,14091,80533, 4619,80533,80069,80533,13913,80533, + 4555,80533,16635,80533,16301,80533, 2575,80533, 2599,80533, 2289,80533, + 2269,80533, 4437,80533, 7549,80533, 7589,80533,13785,80533,80015,80533, +23755,80533, 1369,80996,39633,80533, 1369,81000,78284,80533, 7205,80533, + 2561,80533, 2261,80533, 4423,80533, 2307,80533,79318,80533,10058,80533, +79674,80533,26331,80533, 1369,81022,41559,80533, 1369,81026, 4329,80533, + 1369,81030, 4311,80533, 1369,81034,10354,80533, 3786,80533, 4330,80533, +27805,80533, 1369,81044,42731,80533, 1369,81048,10055,80533, 1369,81052, +10351,80533, 1369,81056, 4312,80533,78645,80533,78324,80533,78458,80533, + 375,81067, 3794,80533,78147,80533, 413,81073, 1369,81072, 341,81072, + 215,80533, 4345,81081,60857,81081,79309,80533, 1369,81086,79665,80533, + 1369,81090, 1477,80533,80543,81095, 281,80533,80547,81099, 1516,80533, +80535,81103, 948,80533,80539,81107,13443,80533,16669,80533,43293,80533, +26104,80533,41314,80533,26277,80533,41479,80533,13027,80533, 264,81124, + 264,81125, 413,81125, 265,81124,81129,81133, 265,81125,81127,81137, + 5127,80533, 264,81140, 264,81141, 413,81141, 265,81140,81145,81149, + 265,81141,81143,81153,15309,80533, 412,81157, 413,81156,81159,81161, + 413,81157, 412,81156,81165,81167,32294,80533,45314,80533,31857,80533, +44925,80533,14053,80533,22897,80533,39143,80533,78107,80533, 413,81184, +78141,81187,77949,81187, 413,81185,77859,81193, 1276,80533,17993,81197, + 438,80533,17993,81201, 1278,80533,18759,81205, 1242,80533,18759,81209, +22806,80533, 903,81213, 9,81213,39084,80533, 483,81219,39204,80533, +41941,81223,22956,80533,26625,81227, 1109,80533,35187,81231, 294,80533, +80683,81235,35187,81235, 1413,80533, 1471,81241, 295,80533,80685,81245, +39749,80533, 483,81249,24095,80533,35187,81253, 11,81252,39787,80533, + 241,81259, 903,81259, 587,81258,24236,80533,39846,80533,78459,80533, + 413,81270,77949,81273, 413,81271,77859,81277,39232,80533,46169,81281, + 510,80533, 11,81285, 1108,80533, 11,81289, 1216,80533,79987,81292, +78669,81295,79757,81292,78669,81299, 1275,81292,18759,81303, 15,81292, +18759,81307, 8808,80533,41376,80533, 7195,80533, 1141,80533,14315,81317, + 959,80533,17125,81321, 253,80533,25793,81324,41019,81324, 8495,81324, + 317,80533,15661,81333,14991,81333,17993,81333, 2899,81333, 273,80533, +80551,81343, 8634,80533, 8677,80533, 331,80533, 413,81351,18391,81353, + 413,81350,17993,81357, 8861,81351,63493,81351,74571,81351,15029,81351, + 8495,80533, 586,81368, 586,81369, 587,81368,81373,81375, 11,81368, + 253,81368, 1471,81368, 53,81368, 587,81369,81371,81387, 305,81369, + 713,81369, 25,81369, 1369,81368, 257,81369, 257,81368,14011,80533, + 257,80533,25793,81404,41019,81404, 8495,81404, 973,80533,20103,81413, + 8337,81413,36773,81413, 341,80533,30091,81421, 8717,81420,20103,81421, +36773,81421, 8337,81421, 3785,81420,78147,81420, 89,80533,10831,81437, +10903,81437, 5019,81437,60857,81437,17125,81437, 567,80533,63493,81449, +74571,81449, 8861,81449, 652,80533,60857,81457, 288,80533, 8861,81461, + 265,80533,78670,81465,77859,81467, 413,81465,77751,81471,77837,81473, +77751,81470,77859,81477,73154,81465,62059,81465,78107,81465,15029,81465, + 4593,81465,11985,81465,78459,81465,80057,81465,79911,81465, 8861,81465, +63493,81465,74571,81465,72152,81465,61718,81465,77751,81465, 413,81508, +77859,81511, 413,81509,77949,81515, 17,81464,35187,81519, 11,81465, +60857,81522, 587,81465,71229,81526,71229,81465,60857,81530, 11,81531, + 587,81530,60857,81465, 10,81539, 10,81538, 305,81539, 11,81539, +81543,81547,71229,81538, 11,81538,81541,81553, 587,81464,60857,81557, + 11,81464, 8861,81561, 1011,80533,50785,81565, 9,81564, 11,81569, + 11,81565, 9,81573,71229,81565,77387,81577, 903,80533,50959,81581, +45149,80533,35187,81585, 11,81584,32103,80533,27021,81591, 241,81591, + 903,81591, 587,81590, 7333,80533, 483,81601, 6789,80533, 9,81605, + 903,81605,14073,80533, 241,81611, 903,81611, 587,81610,11277,80533, +35187,81619, 11,81618,42707,80533, 3445,80533, 375,81627,10313,80533, +79643,80533, 2621,80533,14229,80533,11571,80533, 5045,80533,35187,81641, + 11,81640, 4971,80533, 241,81647, 903,81647, 587,81646, 7009,80533, + 7497,80533, 7287,80533, 7845,80533, 7925,80533, 7895,80533, 7685,80533, + 7671,80533, 7627,80533,14102,80533,11348,80533, 5096,80533, 5000,80533, + 7533,80533, 4617,80533, 483,81683,13907,80533, 483,81687, 7563,80533, + 264,81691, 264,81690, 265,81691,81695,81697, 265,81690,81693,81701, + 7531,80533, 483,81705,79634,80533,80501,81709,79719,81709,79640,80533, + 483,81715,42716,80533,42795,81719,42704,80533, 483,81723,10308,80533, +36131,81727,10310,80533, 483,81731, 5227,80533, 5009,80533, 3461,80533, + 2981,80533, 3049,80533,80061,80533, 483,81745, 240,80532,77859,81749, +78459,81750,78089,81749,78147,81755,78305,81749,78231,81749,78277,81749, +78445,81749,78564,81749,78613,81749,78558,81749,78548,81749,78071,81749, +78387,81749,78459,81776,78425,81749,78459,81780,78434,81749,78147,81785, +13103,81749, 5161,81749,13074,81749, 5150,81749,13057,81749,13051,81796, + 5141,81749, 5137,81800,13051,81749,13057,81804, 5137,81749, 5141,81808, +13092,81749,13045,81813, 5154,81749, 5133,81817,78048,81749,77837,81821, +78459,81749,78387,81824,78425,81824,77859,81824,25793,81749,41019,81749, + 8495,81749,78147,81749,48009,81749,49321,81749,49001,81749,78399,81749, + 265,81847,78459,81849, 265,81846,78147,81853, 265,81749,13027,81856, +13045,81859, 5127,81856, 5133,81863,13027,81857,13057,81867, 5127,81857, + 5141,81871,78399,81856,78147,81875,77751,81856,77837,81879,77751,81857, +78387,81883,78425,81883,77859,81883,77751,81749, 265,81890,77837,81893, +23755,81749,39633,81749, 3785,81749, 8717,81749,79309,81749,79665,81749, +10055,81749,10351,81749,27805,81749,42731,81749,26331,81749, 4329,81749, +41559,81749, 4311,81749, 5127,81749, 265,81925, 5137,81927, 265,81924, + 5133,81931,13027,81749, 265,81935,13051,81937, 265,81934,13045,81941, + 1010,80532,27021,81945,24095,81945,52915,81945, 9195,81945,81565,81945, + 9,81955,81569,81945,23651,81945,67297,81945,81289,81945,21605,81945, + 9,81967,51435,81945, 4321,81945, 9755,81945,11277,81945, 5045,81945, + 4295,81945, 3833,81945,69729,81945,26907,81945,70097,81945,27323,81945, +53941,81945,53215,81945,10171,81945, 9317,81945, 264,80532,51421,82001, +39619,82001,57811,82001,59743,82001,59933,82001, 8093,82001, 3837,82001, +53703,82001, 4303,82001,42435,82001, 4287,82001,53487,82001, 9579,82001, +42113,82001, 9839,82001, 241,82001, 375,82032, 394,82001, 299,82001, + 375,82001, 241,82040,78399,80533, 264,82044, 264,82045, 413,82045, + 265,82044,82049,82053, 265,82045,82047,82057, 240,80533,78397,82061, +78459,82063,78099,82061,78147,82066,78264,82061,78283,82061,78260,82061, +78262,82061,78661,82061,78599,82061,78619,82061,78601,82061,78675,82061, +77837,82061,77949,82088,78673,82061,77950,82061,78118,82061,78459,82097, +78670,82061,77859,82101,77949,82061,78147,82104,77837,82104,78141,82061, +78147,82110, 413,82061,77751,82115,77837,82117,77751,82114,77859,82121, +78147,82061,78099,82124,78141,82124,77949,82124,78107,82061, 265,82132, +78459,82135, 265,82133,78147,82139,77751,82061, 413,82142,77859,82145, + 413,82143,77949,82149, 265,82061,78107,82152,78459,82155,78107,82153, +78141,82159, 902,80533,37663,82163,37599,82163, 265,80532,25793,82169, +41019,82169,39787,82169,23755,82169,39633,82169, 8495,82169,78147,82169, + 8717,82169, 3785,82169,79309,82169,79665,82169,27805,82169,42731,82169, +10055,82169,10351,82169,26331,82169,41559,82169, 4329,82169, 4311,82169, + 4555,82169,14073,82169, 4971,82169,21605,82169,65869,82215,38305,82169, +56555,82219, 483,82219, 241,80532, 4437,82225, 7,82225, 265,82229, +39787,82225,51615,82225, 4613,82225,12571,82225,14073,82225, 4971,82225, + 375,82225, 510,82225,51937,82225,16683,82225, 4805,82225, 9,82225, + 483,82254, 483,82225, 9,82258,38305,82225, 483,82263, 1010,80533, +55211,82267,64345,82267,36256,82267,35187,82267, 9,82274, 9,82267, +35187,82278, 1011,80532,10001,82283, 903,82285,27533,82283, 903,82289, +79139,82283, 903,82293,82267,82283, 9,82296,82278,82283,81231,82283, +21605,82283, 903,82305, 9,82283,82267,82308, 903,80532, 3549,82313, + 2001,82313,21769,82313,10291,82313, 1011,82321,42613,82313, 1011,82325, +79549,82313, 1011,82329,24095,82313,25793,82313, 8495,82313, 5045,82313, +11277,82313,39787,82313,14073,82313, 4971,82313,21605,82313, 955,82349, + 9,82349,65869,82349,38305,82313, 1011,82357, 483,82357,41019,82313, + 264,80533, 53,82365, 1471,82365, 253,82365,72567,82365,76285,82365, +76939,82365,77751,82364, 375,82379, 471,82365, 367,82365, 357,82365, + 341,82365, 241,82389, 241,82365, 9,82393, 483,82393, 413,80533, +78106,82398,78107,82399,82401,82403,78459,82403,78106,82399,78107,82398, +82409,82411,78141,82411,77949,82411,79987,82398,77949,82419,79757,82398, +77949,82423,78459,82398,77949,82427, 331,82398,17993,82431, 261,82398, +17993,82435,77949,82399,78459,82439,17993,82399, 331,82443, 1275,82398, +17993,82447, 15,82398,17993,82451, 375,80533, 53,82455, 1471,82455, + 253,82455, 1369,82455, 11,82455, 261,80533, 413,82467,18391,82469, + 413,82466,17993,82473,15029,82467, 264,82477, 265,82476,82479,82481, + 264,82476, 265,82477,82485,82487,16531,80533, 483,82491,12745,80533, + 264,82495,13129,82495, 413,82495,13119,82501,15503,82495,50535,82495, +50929,82495,51081,82495,82231,82495,13171,82495,13133,82495, 264,82494, + 265,82495,82519,82521, 265,82494,82497,82525, 375,82495, 257,82495, + 264,82531, 265,82530,82533,82535, 264,82530, 265,82531,82539,82541, + 566,80533, 53,82545, 253,82545, 1471,82545, 88,80533, 1369,82553, + 1346,80533,55211,82557,28714,80533,28337,82561,60618,80533,60757,82565, + 3,82565,60755,82569, 154,80533,37663,82573,43214,80533,43053,82577, + 483,82577,43502,80533,80531,82583,46169,82583, 67,80533,11529,82589, +11569,82589, 4610,82589,61780,82589, 9,82589, 4593,82598,60857,82598, +60857,82589, 9,82604, 4593,82589, 9,82608,37845,80533,38305,82612, +45411,82615,37899,82615,79926,80533,79987,82621, 4,82623, 5,82622, +82625,82627, 5,82623, 4,82622,82631,82633,80058,80533,79757,82637, + 2,82639, 3,82638,82641,82643, 3,82639, 2,82638,82647,82649, +80244,80533, 17,82653, 1447,80533,14315,82657, 33,80533,14315,82661, + 759,80533,17125,82665, 47,80533,17125,82669, 1471,80533,41019,82672, +25793,82672, 8495,82672, 53,80533,25793,82680,41019,82680, 8495,82680, +25793,80533, 586,82688, 586,82689, 11,82688, 1369,82688, 587,82688, +82693,82699, 253,82688, 53,82688, 1471,82688, 587,82689,82691,82709, + 25,82689, 713,82689, 305,82689, 257,82688, 257,82689, 1325,80533, +74571,82723,63493,82723, 8861,82723,15029,82723,41019,80533, 586,82732, + 586,82733, 587,82732,82737,82739, 11,82732, 253,82732, 1471,82732, + 53,82732, 713,82733, 25,82733, 305,82733, 587,82733,82735,82757, + 257,82732, 1369,82732, 257,82733, 59,80533,63493,82767,74571,82767, + 8861,82767,15029,82767,79139,80533,80244,82777,80245,82777,80293,82777, + 4,82782,80319,82785, 4,82783,80301,82789,80298,82777,80319,82793, +21036,82777,21037,82777, 1216,82777, 413,82777,80245,82776,82779,82805, + 1011,82777, 903,82808,21037,82776,82797,82813,80244,82776,82781,82817, +21036,82776,82799,82821,65869,82777, 9,82777, 903,82777, 1011,82828, + 4,82777,80293,82833,80315,82835,80293,82832,80319,82839,79549,80533, +80450,82843,80451,82843,80497,82843, 2,82848,80519,82851, 2,82849, +80501,82855,80498,82843,80519,82859, 1216,82843, 413,82843,80451,82842, +82845,82867, 903,82843, 1011,82870,80450,82842,82847,82875,56555,82843, + 483,82843, 1011,82843, 903,82882, 2,82842,80501,82887,79719,82887, + 3,82842,80337,82892, 483,82893, 3,82843,82867,82899, 1369,82899, + 2,82843,82875,82905,82895,82905,80497,82905,80515,82911,80497,82904, +80519,82915,80519,82905,80437,82905,80489,82905,79587,82905,79721,82905, +79645,82905,80337,82842, 3,82930,82905,82933, 3,82931,82887,82937, +27533,80533, 1216,82941, 413,82941,21036,82941,21037,82941, 1011,82941, + 903,82950,21037,82940,82947,82955,21036,82940,82949,82959, 9,82941, +65869,82941, 903,82941, 1011,82966,42613,80533, 1216,82971, 413,82971, + 903,82971, 1011,82976, 483,82971,56555,82971, 1011,82971, 903,82984, + 2,82971,42667,82989,42791,82989,42709,82989, 3,82971, 1369,82997, + 2,82970,42795,83001, 3,82970, 483,83005,10001,80533, 1216,83009, + 413,83009,21036,83009,21037,83009,21036,83008,83017,83019, 1011,83009, + 903,83022,21037,83008,83015,83027,65869,83009, 9,83009, 903,83009, + 1011,83034,10291,80533, 1216,83039, 413,83039, 903,83039, 1011,83044, +56555,83039, 483,83039, 1011,83039, 903,83052, 2,83039,37871,83057, +36133,83057,35803,83057, 3,83039, 1369,83065, 2,83038,36131,83069, + 3,83038, 483,83073, 1369,80533,26331,83076,25793,83076,23755,83076, +27805,83076,40381,83077,41559,83076, 8717,83076,21036,83077,39633,83076, +78147,83076,79309,83076,10055,83076,42731,83076, 3785,83076,79665,83076, + 4329,83076,10351,83076, 4311,83076,38305,83076,41941,83115,41019,83076, + 8495,83076,38305,83077,41019,83123, 5,83077,18967,83126,18967,83077, + 11,83131, 5,83130, 17,80533,25367,83137,62984,83137,60857,83137, + 265,83143, 241,83142, 241,83137,60857,83148,21605,83136,26625,83153, + 265,83136,35187,83157,21605,83137,25793,83161,35187,83137, 265,83165, + 587,80533,62984,83169,62518,83169,68807,83169,36526,83169,17125,83169, + 265,83169,35187,83180,35187,83169,60857,83184, 265,83184,32103,83168, +38305,83168, 483,83193,39787,83168,14073,83168, 4971,83168, 265,83168, +60857,83203, 241,83169,60857,83206,60857,83169, 241,83210,35187,83210, + 11,80533,25793,83216,41019,83216, 8495,83216, 265,83217, 8495,83225, +45149,83216,21605,83216, 903,83231, 9,83231,24095,83216,11277,83216, + 5045,83216, 265,83216, 8861,83243, 3,83217, 375,83247,38305,80533, +76424,83251,54262,83251,54219,83251,76453,83251,42185,83251,42193,83260, +42194,83251,42191,83251,42193,83251,42185,83268,80450,83251,37844,83251, +37845,83251,44663,83277,38707,83277,43483,83277,37897,83277,80451,83251, +80450,83250,83287,83289, 120,83251, 77,83251,32805,83251,54225,83251, +54129,83298,76337,83251,76307,83302,76307,83251,76337,83306,54129,83251, +54225,83310, 113,83251, 25,83314, 506,83251, 1216,83251, 413,83251, + 1413,83251,37845,83250,45411,83327,83275,83327,37899,83327,37897,83250, +83275,83335,65076,83251,37844,83250, 6,83340,83277,83343,83277,83341, +80451,83250,83273,83349, 66,83251, 33,83353, 25,83251, 113,83356, + 1281,83251, 1086,83251, 922,83251, 483,83251, 241,83366, 587,83367, + 903,83366, 241,83251, 483,83374, 903,83251, 1011,83378, 483,83378, + 1369,83250,41941,83385, 587,83250, 483,83389, 587,83251, 1011,83392, + 1011,83251, 903,83396, 11,83397, 587,83396, 1275,83250,46169,83405, +60857,83251,56555,83408,56555,83251, 11,83413,60857,83412, 2,83250, +80531,83419,46169,83419, 3,83250,43053,83425, 483,83425, 2,83251, +80435,83431,80495,83431,43461,83431,80529,83431,46599,83431,43425,83431, + 3,83251,43837,83445,43027,83445, 11,83445, 25,83451,39747,83445, + 11,83444, 33,83457, 1369,83445, 11,83251, 3,83463, 113,83465, + 3,83462, 33,83469, 15,80533, 1216,83473,18617,83475, 413,83473, +18391,83479,25545,83473,62942,83473, 1216,83472,18759,83487, 413,83472, +17993,83491,60857,83473, 1011,83494,18967,83473, 17,83499, 1011,83473, +60857,83502, 3,83472,37663,83507, 3,83473,37611,83511,38155,83511, +35927,83511,21605,80533,27065,83519,27261,83519,21036,83519,21037,83519, +27067,83519,27255,83519,73221,83519,55211,83519,36256,83519,51593,83519, +55803,83519,64345,83519,54477,83519, 1216,83519, 413,83519,21037,83518, +83525,83551,21036,83518,83527,83555, 247,83519, 934,83519, 9,83519, +35187,83562, 11,83563, 1011,83519, 903,83568, 17,83518,26625,83573, + 11,83518, 903,83577, 9,83577, 11,83519, 903,83582, 903,83519, +27021,83587, 1011,83586, 11,83587, 11,83586,35187,83519, 9,83596, +65869,83519, 5,83518,28337,83603, 5,83519,27021,83607,52915,83607, + 9195,83607,20501,83607, 9875,83607,30475,83607,28219,83607,23939,83607, + 1275,80533,43214,83624,43214,83625,43215,83624,83629,83631, 1216,83625, +18617,83635, 413,83625,18391,83639,43215,83625,83627,83643,40675,83625, +73994,83625, 1216,83624,18759,83651, 413,83624,17993,83655,71229,83625, + 903,83658, 903,83625,71229,83662,38305,83624,46169,83667, 5,83624, +55211,83671, 5,83625,53813,83675,10107,83675,69877,83675, 483,80533, + 241,83683, 9,83685, 9,83682, 11,83689, 17,83683, 903,83693, + 11,83683, 9,83697, 5,83682, 53,83701, 253,83701, 1471,83701, + 5,83683, 1505,83709, 9,80533,80151,83712, 1011,83713,82267,83717, + 241,83713, 483,83721, 483,83712, 11,83725, 1011,83712,81945,83729, + 11,83729, 3,83712, 1369,83735, 3,83713, 483,83739,17025,80533, + 5,83742, 2,83745, 17,83746, 17,83745, 2,83750, 2,83751, + 164,83745,38057,83743,38057,83742,38056,83742,83759,83763,38056,83743, +83761,83767, 3,83742,83749,83771,83753,83771,83757,83771, 3,83743, +83755,83779,13737,80533, 375,83783,80151,80533, 9,83786,35187,83787, + 9,83791, 5,83787, 9,83795, 5,83786, 17,83799,79987,80533, + 413,83802,77949,83805, 413,83803,77859,83809, 1216,83802,78669,83813, + 1216,83803,77857,83817, 4,83803,79549,83821, 2,83823, 3,83822, +83825,83827, 3,83823, 2,83822,83831,83833, 4,83802,79757,83837, + 2,83839, 3,83838,83841,83843, 3,83839, 2,83838,83847,83849, +79757,80533, 413,83852,77949,83855, 413,83853,77859,83859, 1216,83852, +78669,83863, 1216,83853,77857,83867, 2,83853,79139,83871, 4,83873, + 5,83872,83875,83877, 5,83873, 4,83872,83881,83883, 2,83852, +79987,83887, 4,83889, 5,83888,83891,83893, 5,83889, 4,83888, +83897,83899, 3,80532,79231,83903,79237,83903,79365,83903,79375,83903, +73413,83903,73405,83903,40793,83903,40787,83903,71751,83903,36001,83903, +71731,83903,72115,83903,72929,83903,71713,83903, 7,83903, 4,83933, +83519,83935,32103,83903,26106,83903,41746,83903,43005,83903, 8800,83903, +64513,83903,63253,83903,62215,83903,59910,83903,41019,83903, 11,83956, +60755,83903,60707,83903, 9852,83903,48975,83903,48245,83903,48451,83903, +76271,83903,82267,83903, 9,83974,82278,83903,83157,83903,81231,83903, +81235,83903,81519,83903, 386,83903, 347,83903, 510,83903, 273,83903, + 281,83903, 1477,83903, 1516,83903, 948,83903, 165,83903, 903,84004, +40704,83903,79139,84009,27533,84009,10001,84009,73307,83903,79139,84017, +27533,84017,10001,84017,53500,83903,37595,83903,36049,83903,36539,83903, +68851,83903,36041,83903,37573,83903,36275,83903, 1505,83903, 1011,84040, +25793,83903, 11,84044,64397,83903, 483,84049, 8495,83903, 11,84052, +60618,83903, 483,84057, 375,83903, 305,84060, 903,83903, 165,84064, + 1011,83903, 1505,84068, 305,83903, 375,84072, 4,83903,56555,84076, + 483,84079, 5,83902,57811,84083,59743,84083,59933,84083, 9579,84083, + 9839,84083,51421,84083,39619,84083, 4303,84083, 4287,84083, 8093,84083, + 3837,84083,42113,84083,53487,84083,53703,84083,42435,84083,48885,83903, + 483,84115, 11,83903,25793,84118,41019,84118, 8495,84118,59875,84118, + 9805,84118,53391,84118, 9,83903,82267,84132, 483,84132,38305,84132, +79139,84139,10001,84139,27533,84139,38305,83903, 9,84146,79139,84149, +27533,84149,10001,84149, 9805,83903, 11,84156, 5,84157, 483,83903, + 9,84162,56555,83903, 4,84166, 483,84169,53391,83903, 11,84172, + 5,84173,59875,83903, 11,84178, 5,84179, 2,80532,11087,84185, +11307,84185,11713,84185,10439,84185, 2221,84185,10665,84185,11037,84185, + 2233,84185,17777,84185, 2215,84185,18739,84185, 4339,84185,79091,84185, +79097,84185, 5075,84185, 4643,84185,79115,84185,79123,84185,59811,84185, +36619,84185,68291,84185,68299,84185,24213,84185,24059,84185,22149,84185, +22143,84185,72667,84185,60839,84185,35665,84185,59819,84185,59869,84185, +35487,84185, 7,84185, 4,84251,27306,84185,24095,84185,53910,84185, +55537,84185,79280,84185,80301,84263,83607,84185,40455,84185,25313,84185, + 8714,84185,32103,84185,26106,84185, 8800,84185,41746,84185,81569,84185, +48009,84185,49001,84185,49321,84185, 4551,84185,81531,84185,81289,84185, +81245,84185,83729,84185,10196,84185,70136,84185,10603,84185, 9,84305, + 4625,84185, 9,84309,81565,84185, 9,84313,23983,84185, 9,84317, +76501,84185,68176,84185,79065,84323,59787,84323, 9513,84323,36545,84185, +79065,84331,59787,84331, 9513,84331, 759,84185,35187,84339,10107,84185, + 265,84342, 241,84343,69877,84185, 265,84348, 241,84349, 305,84185, + 8495,84354, 959,84185,35187,84359,28714,84185,77079,84185, 1011,84365, + 1010,84364,84367,84369, 1010,84365, 1011,84364,84373,84375, 47,84185, +35187,84379,48245,84185,48975,84185,48451,84185,11277,84185, 5045,84185, +52603,84185, 8495,84185, 10,84394, 10,84395, 305,84394, 11,84394, +84399,84403, 11,84395,84397,84407, 331,84185,71229,84411,79549,84185, + 1011,84415, 265,84185,53813,84418,71229,84419,10107,84418,69877,84418, +79757,84419, 903,84185,55211,84431,10291,84185, 1011,84435,25793,84185, + 10,84438, 10,84439,27021,84438, 11,84438,84443,84447, 11,84439, +84441,84451,42613,84185, 1011,84455, 1325,84185,71229,84459, 5,84185, +27255,84463, 9287,84463,53167,84463,21605,84462, 4,84185,79139,84472, +80301,84475,49475,84473,73066,84473,28715,84473, 1011,84473,71229,84484, +71229,84473, 1011,84488,27693,84473,10047,84473,79287,84473,41019,84185, + 10,84498, 10,84499, 11,84498,84503,84505, 11,84499,84501,84509, + 59,84185,71229,84513, 4,84184, 8495,84517,41019,84517,25793,84517, +49001,84517,49321,84517,48009,84517, 265,84517,78147,84517,23755,84517, +39633,84517, 3785,84517, 8717,84517,41559,84517, 4311,84517,79665,84517, +10351,84517,26331,84517,42731,84517, 4329,84517,79309,84517,27805,84517, +10055,84517, 5,84184,27021,84563,24095,84563, 9195,84563,52915,84563, +21605,84563, 9,84573,23651,84563, 9755,84563,51435,84563,67297,84563, + 4321,84563,69729,84563,26907,84563, 9317,84563,53215,84563,27323,84563, +53941,84563, 3833,84563,10171,84563,70097,84563, 4295,84563, 5045,84563, +11277,84563,53813,84185, 265,84610, 241,84611,48885,84185, 1011,84617, + 11,84185,25793,84620, 8495,84620,41019,84620, 17,84185,30091,84629, +65869,84185, 15,84632,79065,84635,59787,84635, 9513,84635, 803,84633, +38305,84185, 1011,84645, 1347,84645, 15,84185,28714,84650,28714,84651, +65869,84650,79065,84657, 9513,84657,59787,84657,28715,84650,84655,84665, +28715,84651,84653,84669, 9195,84185, 241,84673,35187,84673,21605,84185, +27255,84679, 7,84678, 4,84682, 4,84683,84253,84679, 16,84678, +55211,84679, 803,84679, 9,84679, 17,84678, 903,84679,65869,84679, + 4,84679,84699,84705, 5,84679,84685,84709,84691,84709,27021,84709, + 4,84678, 7,84716,84709,84719, 5,84678,84687,84723,52915,84185, +35187,84727, 241,84727,27021,84185,35187,84733, 241,84733,25793,84732, +79139,84185,80245,84740, 4,84740,80301,84745, 5,84740,80151,84748, + 4,84741,80319,84753,84751,84753,80207,84753,80283,84753, 5,84741, +84743,84763, 5,80532,80759,84767, 7,84767, 2,84770, 3,84770, +83251,84775, 2,84771,84776,84779,84775,84779,83251,84782,83251,84779, +84775,84786, 3,84771,84773,84791,83251,84793,27306,84767,24095,84767, +52603,84767,53910,84767,55537,84767,84438,84767,84394,84767,84498,84767, +81539,84767,25793,84767,27021,84814,84185,84814,64289,84767,84060,84767, +81569,84767,83729,84767,81245,84767,81289,84767,70136,84767,10196,84767, + 273,84767, 1477,84767, 281,84767, 948,84767, 1516,84767,81565,84767, + 9,84847, 1505,84767, 1011,84850, 5045,84767,11277,84767, 4551,84767, + 922,84767, 1413,84767,20831,84767,19783,84767,20053,84767,58775,84767, + 9195,84767, 265,84873, 47,84767,60857,84877, 165,84767, 903,84880, +41019,84767,84185,84884,27021,84767,25793,84888, 265,84889, 8495,84767, +84185,84894, 959,84767,60857,84899, 89,84767, 5019,84903,60857,84903, + 375,84767,83903,84908, 759,84767,60857,84913, 265,84767,53813,84916, +69877,84916,10107,84916, 1011,84767, 1505,84924,54597,84925, 903,84767, + 165,84930, 483,84930,54295,84931, 1447,84767,18967,84939, 1141,84767, +18967,84943, 2,84767,61780,84947, 9,84947,60857,84950,54295,84947, +70085,84947,11529,84947,10155,84947,53925,84947,60857,84947, 9,84964, + 3,84767, 8063,84969,42361,84969,53667,84969,84185,84767,41019,84976, + 8495,84976,25793,84976,83903,84767, 375,84984, 33,84767,18967,84989, + 2,84766,27021,84993,24095,84993, 9195,84993,52915,84993,21605,84993, + 9,85003,67297,84993, 9755,84993,51435,84993,23651,84993, 4321,84993, +26907,84993,69729,84993,10171,84993,53941,84993,70097,84993,53215,84993, + 9317,84993, 4295,84993,27323,84993, 3833,84993, 5045,84993,11277,84993, + 3,84766,57811,85041,59743,85041,59933,85041,51421,85041,39619,85041, + 4303,85041, 4287,85041, 9579,85041, 9839,85041, 8093,85041, 3837,85041, +53487,85041,42113,85041,53703,85041,42435,85041,52915,84767, 265,85073, + 587,84767,60857,85077,70573,85077, 1369,84767,43503,85083, 483,84767, + 903,85086,21605,84767, 9,85091, 145,85091,10107,84767, 265,85096, + 9,84767,53813,84767, 265,85102,69877,84767, 265,85106, 4,80532, +83715,85111,80781,85111,83789,85111, 7,85111, 2,85118,83511,85121, + 2,85119,82163,85125,83507,85125,82573,85125, 1368,85111,83511,85133, +25525,85111,84498,85111,84438,85111,84709,85111,79634,85111,80501,85145, +84394,85111,64513,85111,63253,85111,62215,85111,81539,85111,64397,85111, + 483,85159,83787,85111, 9,85163,43214,85111, 8495,85111,84185,85168, + 587,85169, 331,85111,60857,85175,79139,85111, 903,85179, 265,85111, +60857,85183,79987,85183,10001,85111, 903,85189,41019,85111,84185,85192, + 587,85193,27533,85111, 903,85199, 59,85111,60857,85203, 3,85111, + 4,85206,85125,85209,38305,85206, 2,85111, 7,85214,83511,85217, +79549,85214,80501,85221,49155,85215,62464,85215,43215,85215, 903,85215, +60857,85230,60857,85215, 903,85234,42705,85215,10311,85215,79641,85215, +84185,85111,25793,85244,41019,85244, 8495,85244,25793,85111,84185,85252, + 587,85253, 1325,85111,60857,85259, 2,85110, 8495,85263,25793,85263, +41019,85263,49321,85263,49001,85263,48009,85263, 265,85263,78147,85263, +39633,85263,23755,85263, 3785,85263, 8717,85263,26331,85263, 4329,85263, +79309,85263,10055,85263,41559,85263,27805,85263, 4311,85263,79665,85263, +42731,85263,10351,85263,49205,85111, 903,85309,21605,85111, 903,85313, + 155,85313, 1275,85111,43215,85319,77751,85111,38305,85111, 7,85324, + 2,85326, 2,85327, 1368,85324, 1369,85324, 2,85325,85335,85337, + 3,85325,85329,85341,85333,85341,84185,85341, 2,85324, 7,85348, +85341,85351, 3,85324,85331,85355,79549,85111,80451,85358, 2,85358, +80501,85363, 3,85358,80337,85366, 2,85359,80519,85371,85369,85371, +80437,85371,80489,85371, 3,85359,85361,85381, 5,80533,83932,85385, +83933,85385,64148,85385,64149,85385, 0,85385,56555,85395, 1369,85397, + 7,85385,83903,85400,60857,85400, 265,85401,83903,85407, 1275,85401, +60857,85411, 0,85384,63015,85415,25380,85415,85413,85415,21605,85415, + 1369,85422, 1369,85415,21605,85426, 7,85384,85417,85431,25381,85431, +85415,85435,63014,85431,85415,85439,85419,85431,85399,85431,85429,85431, +85425,85431, 483,85431,60857,85450,85415,85453,60857,85431, 483,85456, +85415,85459,54440,85385,83903,85385, 7,85464,27425,85385,53137,85385, + 9365,85385, 803,85385,60857,85474,62310,85385,85206,85385,85125,85481, + 241,85385, 483,85485,54295,85484,54295,85385, 241,85490, 483,85384, + 53,85495, 253,85495, 1471,85495, 1275,85384,55211,85503,21605,85384, +28337,85507, 1369,85385, 1011,85511,60857,85385, 7,85514, 803,85514, + 2,85384,85389,85521,85393,85521,55211,85521,64345,85521,84132,85521, +36256,85521,83903,85521, 9,85534, 9,85521,83903,85538,35187,85538, +35187,85521, 9,85544, 3,85384,85467,85549,85387,85549,85403,85549, +85401,85549,83903,85557,85391,85549,85517,85549,85405,85549, 53,85549, + 1471,85549, 253,85549,76285,85549,76939,85549,72567,85549, 241,85549, + 483,85579, 9,85579, 2,85385, 3,85385, 165,85587, 1108,85587, + 1072,85587,76337,85587, 1011,85587, 483,85596, 9,85596,85111,85586, +85125,85603, 9,85587, 1011,85606, 483,85587, 1011,85610,80151,85384, + 17,85615,85111,85385, 1368,85618, 7,85618, 2,85623, 2,85622, + 1369,85618, 2,85619,85629,85631, 3,85619,85627,85635,85121,85635, +85217,85635,85621,85635,85133,85635, 2,85618, 7,85646,85635,85649, + 3,85618,85625,85653,85125,85653,55211,85385, 265,85659, 17,85385, + 3,80533,73221,85665, 9,85667,78796,85665, 9,85671, 8139,85665, +53639,85665,42521,85665,85322,85665, 9,85681,55004,85665,85111,85665, +77751,85686, 9,85689,42613,85664, 483,85693,10291,85664, 483,85697, +79549,85664, 483,85701,85585,85665, 9,85705, 9,85664, 1369,85709, + 15,85664,37663,85713,85125,85713,38305,85664,43053,85719, 483,85719, + 17,85665, 903,85725,35187,85665,77751,85728, 9,85731, 4,85664, +85125,85735,37663,85735, 5,85664,76939,85741, 1471,85741, 53,85741, + 253,85741,76285,85741,72567,85741, 241,85741, 9,85755, 483,85755, + 5,85665, 1505,85761, 922,85761, 918,85761,54597,85760, 903,85761, + 9,85770, 483,85770, 483,85761, 903,85776, 9,85761, 903,85780, +77751,85760, 9,85785,79756,85665, 9,85789,84185,85665, 16,85792, + 7,85792, 4,85797, 4,85796, 17,85792, 4,85793,85803,85805, + 483,85805, 5,85793,85801,85811,85797,85811,85795,85811, 4,85792, + 7,85818,85811,85821, 5,85792,85799,85825,54597,85665, 11,85829, + 5,85828, 1369,85665, 9,85835,18967,85665, 4,85839, 483,85841, +77751,85665,35187,85844, 9,85847, 9,85845,85111,85851,85111,85844, + 9,85855, 5,85845, 17,85859, 5,85844, 9,85863,77751,85664, + 375,85867,79986,80533, 375,85871, 2,80533,80080,85875,80079,85877, +80298,85875,80319,85881,80293,85875, 4,85884,80319,85887, 4,85885, +80301,85891,11727,85875,11047,85875,17787,85875,18737,85875,78670,85875, +77859,85903,10874,85875,77952,85875,77857,85909, 7,85874,83903,85913, +85167,85875,85355,85875,85213,85875, 1216,85875,77751,85923,77877,85925, +77751,85922,77857,85929,62310,85875,64483,85875,68896,85875,62464,85875, +61780,85875,61688,85875,85159,85875,10831,85875, 9,85946, 413,85875, +77751,85951,77837,85953,77751,85950,77859,85957,74571,85875,17178,85875, +50959,85875,43400,85875,11177,85875,84077,85875,85913,85971,40675,85875, +55546,85875,54440,85875,69196,85875,17125,85875, 9,85982,15029,85875, +65869,85986,52169,85875,49155,85875,40453,85875,43305,85875,40005,85875, +84767,85875,77751,86001, 9,86003,73994,85875,42613,85874,42795,86009, +10291,85874,36131,86013,70135,85875,53919,85875,10195,85875,79842,85875, +79757,85875, 903,86024,63493,85875, 8861,85875,80058,85875,80079,86033, +54422,85875,11529,85875,54447,85875,52601,85875, 145,85875,35187,86044, +36096,85875,79601,85875,79549,85874,80501,86053,79719,86053,64396,85875, +85111,86059, 1011,85875,43215,86062, 241,85875,54295,86066,65869,85875, +60857,86070,15029,86070, 9,85875,10831,86076,60857,86076,17125,86076, +84076,85875, 483,86085, 803,85875,60857,86088, 903,85875,53813,86093, +60857,86092,10107,86093,69877,86093,79757,86092,71229,86092, 265,85875, +55211,86106,10371,85875,42787,85875,55211,85875,60857,86114, 265,86114, +38305,85874,46169,86121,80531,86121,72818,85875, 11,85875,43215,86128, +43316,85875,35187,85875,54295,86134, 145,86134,71229,85875, 903,86140, + 155,86140,43215,85875, 10,86147, 10,86146,85111,86147, 1011,86146, +84767,86147, 11,86147,86151,86159, 11,86146,86149,86163, 155,85875, +71229,86166, 5,85874,55211,86171,64345,86171,84132,86171,36256,86171, +83903,86171, 9,86180, 9,86171,83903,86184,35187,86184,35187,86171, + 9,86190, 4,85875,80070,86195,80077,86197,80293,86195,80315,86201, +80293,86194,80319,86205, 483,86195,83903,86209,80533,86194, 3,86213, + 7,86195,86215,86217, 2,86217,86213,86221,79987,86194,80079,86225, +83903,86194, 483,86229,77751,86195,79545,86233, 3,86235, 2,86234, +86237,86239, 2,86235, 3,86234,86243,86245,77751,86194,79549,86249, + 3,86251, 2,86250,86253,86255, 2,86251, 3,86250,86259,86261, + 5,85875,85914,86265,85913,86265,83903,86268,49713,86265,49712,86264, +86273,86275,49712,86265,49713,86264,86279,86281,53813,86265,64317,86265, +64815,86265,62077,86265,10107,86265,69877,86265, 17,86265,83903,86297, +35187,86297,60857,86264,85111,86303,65869,86265, 9,86307, 587,86265, +60857,86311,83903,86265,85913,86314,79757,85874,79987,86319, 4,86321, + 5,86320,86323,86325, 5,86321, 4,86320,86329,86331,80336,85875, +79549,86335, 3,86337, 2,86336,86339,86341, 2,86337, 3,86336, +86345,86347,83903,85875, 16,86351, 7,86351,86265,86355, 4,86354, + 4,86355, 17,86351, 4,86351, 7,86364, 5,86351,86361,86369, + 4,86350,86363,86373, 483,86373, 5,86350,86359,86379,86367,86379, +86355,86379,86353,86379,54295,85875, 241,86388,35187,86388,60857,85875, + 7,86395, 4,86396, 4,86397,86265,86397, 16,86395, 17,86395, + 803,86394,55211,86394, 903,86394,65869,86394, 9,86394, 4,86394, +86407,86419, 5,86394,86399,86423,86405,86423,85111,86423, 4,86395, + 7,86430,86423,86433, 5,86395,86401,86437,77751,85875, 413,86440, +77859,86443, 413,86441,77949,86447, 1216,86440,77857,86451, 1216,86441, +78669,86455, 4,86441,79757,86459, 3,86461, 2,86460,86463,86465, + 2,86461, 3,86460,86469,86471, 4,86440,79549,86475, 3,86477, + 2,86476,86479,86481, 2,86477, 3,86476,86485,86487,79987,85875, +80244,86491,80245,86491,80151,86491, 5,86496, 5,86497, 4,86491, +80083,86503,80029,86503,80063,86503,86501,86503, 5,86491,80151,86512, + 4,86490,80079,86517,86513,86517,86493,86517,86515,86517,86499,86517, + 5,86490,86495,86529,86503,86529,77751,85874,86529,86535,86503,86536, +86532,86535,86521,86535,86512,86535,86517,86545,86503,86535,86529,86548, +86491,86535, 5,86552,86517,86555, 5,86553,86503,86559,85663,86535, +85100,86535, 9,86535,84767,86566,84767,86535, 9,86570, 5,86535, +86491,86574,86517,86577,86491,86575,86529,86581,80150,80533,80315,86585, +80301,86586,80298,86585,80319,86591,80301,86585,80315,86594,80316,86585, +80325,86585,80293,86585, 4,86602,80319,86605, 4,86603,80301,86609, +85663,86585,85100,86585, 9,86585,84767,86616,84767,86585, 9,86620, + 4,86585,80293,86625,80315,86627,80293,86624,80319,86631, 4,80533, +79968,86635,79967,86637,80498,86635,80519,86641,80497,86635, 2,86644, +80519,86647, 2,86645,80501,86651,78670,86635,77859,86655,77952,86635, +77857,86659, 0,86635,21605,86663, 587,86665, 7,86635, 483,86669, +18967,86671, 0,86634,19917,86675,58930,86675,86673,86675,56555,86675, + 587,86682, 587,86675,56555,86686, 7,86634,58931,86691,86675,86693, +86677,86691,86679,86691,19916,86691,86675,86701,86265,86691,86667,86691, +86689,86691,86685,86691, 1275,86691,18967,86712,86675,86715,18967,86691, + 1275,86718,86675,86721,29023,86635,25513,86635,24619,86635,84363,86635, +84723,86635,84471,86635, 1216,86635,77751,86737,77877,86739,77751,86736, +77857,86743,63610,86635,63291,86635,84321,86635,86028,86635,86030,86635, +85960,86635,86437,86635,76631,86635,76601,86635,74682,86635, 8974,86635, + 413,86635,77751,86769,77837,86771,77751,86768,77859,86775,63493,86635, + 483,86778,85875,86778,29598,86635,25545,86635,59206,86635,15029,86635, +56555,86790,62942,86635,80030,86635,79987,86635, 1011,86798,74571,86635, +85875,86802, 483,86802, 8861,86635,85875,86808, 483,86808,79926,86635, +79967,86815,85875,86635, 8861,86818,63493,86818,74571,86818,79263,86635, +76816,86635,77387,86829,76500,86635,84185,86833, 11,86833, 903,86635, +28715,86838,56555,86635,15029,86842, 483,86635,63493,86846,74571,86846, + 8861,86846, 1011,86635,79987,86854,60857,86854,10073,86635,27855,86635, +62278,86635, 587,86635,28715,86866,29026,86635,60857,86635, 1011,86872, + 1347,86872,28715,86635, 11,86879,84185,86879, 903,86878, 587,86878, + 1347,86635,60857,86888, 2,86634, 4,86893, 7,86895, 3,86634, +85125,86899,37663,86899, 2,86635,79962,86905,79965,86907,80497,86905, +80515,86911,80497,86904,80519,86915,79757,86904,79967,86919,71229,86904, +77387,86923,77751,86905,79065,86927, 5,86929, 4,86928,86931,86933, + 4,86929, 5,86928,86937,86939,77751,86904,79139,86943, 5,86945, + 4,86944,86947,86949, 4,86945, 5,86944,86953,86955, 3,86635, +85217,86959,85121,86959,86897,86959,86217,86959,85133,86959, 6,86959, + 6,86958, 7,86958,86971,86975, 7,86959,86973,86979,60755,86959, +35927,86959,38155,86959,37611,86959,71229,86958,84185,86991, 11,86991, +79987,86634,79757,86997, 2,86999, 3,86998,87001,87003, 3,86999, + 2,86998,87007,87009,80150,86635,79139,87013, 5,87015, 4,87014, +87017,87019, 4,87015, 5,87014,87023,87025,84767,86635, 1368,87029, + 7,87029, 2,87032, 2,87033, 1369,87029, 2,87029, 7,87040, + 3,87029,87037,87045, 2,87028,87039,87049, 3,87028,87035,87053, +87043,87053,87031,87053,71229,86635, 7,87061, 2,87062, 2,87063, + 1368,87061, 1369,87061, 2,87060,77387,87073,87071,87073, 3,87060, +87065,87079,87069,87079,84185,87079, 11,87079, 2,87061,77373,87089, +76635,87089, 7,87088,87079,87095,72519,87089, 3,87061,87067,87101, +85875,87101,77751,86635, 413,87106,77859,87109, 413,87107,77949,87113, + 1216,87106,77857,87117, 1216,87107,78669,87121, 2,87107,79987,87125, + 5,87127, 4,87126,87129,87131, 4,87127, 5,87126,87135,87137, + 2,87106,79139,87141, 5,87143, 4,87142,87145,87147, 4,87143, + 5,87142,87151,87153,79757,86635,80450,87157,80451,87157,80337,87157, + 3,87162, 3,87163, 2,87157,79971,87169,79841,87169,79961,87169, +87167,87169, 3,87157,80337,87178, 2,87156,79967,87183,87179,87183, +87159,87183,87181,87183,87165,87183, 3,87156,87161,87195,87169,87195, +77751,86634,87195,87201,87169,87202,87198,87201,87187,87201,87178,87201, +87183,87211,87169,87201,87195,87214,87157,87201, 3,87218,87183,87221, + 3,87219,87169,87225, 3,87201,87157,87228,87183,87231,87157,87229, +87195,87235,80336,80533,80515,87239,80501,87240,80498,87239,80519,87245, +80501,87239,80515,87248,80516,87239,80525,87239,80497,87239, 2,87256, +80519,87259, 2,87257,80501,87263, 2,87239,80497,87267,80515,87269, +80497,87266,80519,87273,77751,80533,79962,87277, 2,87279,79971,87281, + 2,87278,79967,87285,80070,87277, 4,87289,80083,87291, 4,87288, +80079,87295,79968,87277,79967,87299,80080,87277,80079,87303,80498,87277, +80519,87307,80298,87277,80319,87311,80497,87277, 2,87314,80519,87317, + 2,87315,80501,87321,80293,87277, 4,87324,80319,87327, 4,87325, +80301,87331,81857,87277,78453,87277,80233,87277,80445,87277, 8453,87277, + 273,87277,84484,87277,85230,87277,84531,87277,85277,87277,21522,87277, + 1516,87277,38266,87277, 948,87277,20239,87277, 1477,87277,37095,87277, + 281,87277,84473,87277, 1011,87370,85215,87277, 903,87374,80242,87277, +80448,87277,80447,87277, 903,87382,80241,87277, 1011,87386,38057,87277, + 903,87390, 165,87277, 903,87394,21315,87277, 1011,87398, 1505,87277, + 1011,87402, 1216,87276, 412,87276, 413,87277,87409,87411, 1217,87277, +87407,87415, 413,87276, 1216,87277, 1217,87276,87421,87423, 412,87277, +87419,87427,12377,87277, 375,87277,57522,87277,67028,87277,67800,87277, + 510,87277, 240,87277, 265,87443,77750,87445,77751,87444,87447,87449, +77751,87445,77750,87444,87453,87455, 264,87277,84517,87459,85263,87459, +81749,87459, 341,87459, 264,87276, 375,87469, 241,87277,81464,87472, +81465,87473,87475,87477,81464,87473,81465,87472,87481,87483, 1011,87277, +84473,87486,80241,87486, 1505,87486,21315,87486, 903,87277,85215,87496, +80447,87496, 165,87496,38057,87496, 483,87277,65869,87506, 9,87506, + 9,87277,56555,87512, 483,87512,56555,87277, 9,87518,65869,87518, +65869,87277, 483,87524,56555,87524, 5,87277,84185,87531, 1011,87533, + 2,87531,80532,87536, 3,87531,85215,87541, 3,87530,87539,87545, +85263,87545,84517,87545,81749,87545, 2,87530,87533,87555, 4,87276, +87531,87559, 2,87561, 3,87561, 2,87560,87565,87567, 3,87560, +87563,87571, 3,87277,85111,87575, 903,87577,87559,87575, 0,87581, + 1,87580,87583,87585, 1,87581, 0,87580,87589,87591, 4,87575, +80532,87594, 5,87575,84473,87599, 5,87574,87597,87603,84517,87603, +85263,87603,81749,87603, 4,87574,87577,87613, 2,87276,85663,87617, +85100,87617, 9,87617,84767,87622,84767,87617, 9,87626,87575,87617, + 4,87631, 5,87631, 4,87630,87635,87637, 5,87630,87633,87641, + 2,87277,79962,87645,79965,87647,80497,87645,80515,87651,80497,87644, +80519,87655,79962,87644,79967,87659,87559,87645, 7,87663, 6,87662, +87665,87667, 6,87663, 7,87662,87671,87673, 4,87645, 1011,87677, +77751,87679,77750,87678,87681,87683,77750,87679,77751,87678,87687,87689, + 4,87644, 265,87693,77750,87695,77751,87694,87697,87699,77751,87695, +77750,87694,87703,87705, 3,87276, 375,87709,87645,87709, 4,87713, + 5,87713, 4,87712,87717,87719, 5,87712,87715,87723, 4,87277, +80070,87727,80077,87729,80293,87727,80315,87733,80293,87726,80319,87737, +80070,87726,80079,87741, 2,87727, 903,87745,77751,87747,77750,87746, +87749,87751,77750,87747,77751,87746,87755,87757, 2,87726, 265,87761, +77750,87763,77751,87762,87765,87767,77751,87763,77750,87762,87771,87773, + 5,87276,87575,87777, 7,87779, 6,87778,87781,87783, 6,87779, + 7,87778,87787,87789,87645,87777, 0,87793, 1,87792,87795,87797, + 1,87793, 0,87792,87801,87803,87727,87777, 2,87807, 3,87807, + 2,87806,87811,87813, 3,87806,87809,87817 +}; + +const int s_nDataSize2 = 24772; +unsigned int s_Data2[24772] = { + 3, 9, 5, 6, 119, 796, 636, 113, 449, 235, 239, 105, + 789, 96, 439, 624, 630, 230, 111, 110, 787, 786, 628, 627, + 116, 115, 436, 435, 227, 226, 93, 92, 792, 791, 100, 99, + 443, 442, 633, 632, 128, 183, 234, 178, 233, 85, 762, 203, + 32, 742, 356, 169, 152, 12, 672, 741, 127, 168, 671, 740, + 50, 352, 149, 64, 414, 197, 276, 751, 722, 396, 275, 434, + 721, 785, 274, 795, 720, 448, 273, 719, 474, 758, 718, 392, + 269, 748, 715, 400, 118, 794, 635, 81, 76, 750, 747, 597, + 595, 91, 433, 225, 74, 745, 680, 565, 268, 476, 271, 761, + 350, 678, 345, 567, 757, 471, 470, 563, 469, 561, 551, 461, + 465, 706, 650, 714, 261, 332, 641, 708, 676, 542, 260, 458, + 755, 314, 325, 658, 288, 349, 760, 654, 656, 564, 562, 644, + 552, 642, 550, 259, 252, 254, 322, 311, 329, 109, 784, 626, + 43, 395, 182, 55, 399, 186, 104, 447, 238, 41, 389, 173, + 175, 193, 485, 580, 579, 734, 25, 733, 528, 548, 310, 546, + 344, 526, 308, 560, 342, 525, 556, 558, 523, 524, 522, 520, + 307, 622, 623, 431, 618, 620, 429, 617, 305, 615, 519, 518, + 516, 778, 304, 250, 302, 776, 216, 218, 774, 215, 301, 300, + 514, 771, 513, 541, 298, 512, 297, 535, 321, 508, 510, 319, + 538, 539, 533, 507, 509, 296, 146, 705, 531, 537, 317, 557, + 341, 143, 697, 555, 544, 339, 613, 426, 217, 773, 619, 428, + 221, 780, 611, 610, 424, 609, 769, 423, 422, 768, 213, 625, + 783, 670, 732, 782, 578, 577, 731, 484, 387, 668, 669, 171, + 172, 375, 191, 575, 729, 482, 446, 667, 237, 574, 728, 481, + 398, 666, 185, 573, 727, 480, 394, 665, 181, 572, 695, 694, + 140, 738, 372, 246, 690, 689, 136, 244, 369, 767, 212, 766, + 702, 701, 367, 257, 700, 315, 726, 382, 59, 407, 190, 52, + 366, 157, 65, 417, 201, 63, 413, 194, 686, 692, 243, 248, + 699, 256, 150, 354, 365, 364, 353, 156, 685, 348, 242, 661, + 192, 409, 376, 378, 411, 164, 569, 717, 473, 391, 660, 177, + 189, 406, 374, 371, 405, 162, 200, 416, 363, 362, 415, 155, + 313, 324, 361, 360, 331, 312, 328, 381, 316, 330, 359, 323, + 4596,24359,41366,41344, 4857,37718, 4594,24357, 4846,37706, 4678,26650, + 4592,24355, 4844,37704, 4591,24354, 4843,37703, 8816,41900,22056,15422, + 7473, 8464,42932, 8814,41898, 6804,20483,12853, 8462,42930, 8809,42808, +21978,15306, 7385, 8456,42895, 8807,41327,21965,15246,15293, 7372, 8454, +42893, 3212,20457,36983, 3516, 6187, 6184,20453,29352,10563,10421, 2593, +20452, 6183, 5637, 2589, 6182, 2645, 2619, 2283,26212,20199, 2269,12513, + 2614, 2661,18113, 2288, 4777,35226, 4775, 4774, 4773,42536, 2198,32674, +32753, 8833, 8780,40027,43084,39938,43445, 8548, 8831,24157,26148,31156, +29057, 8503, 8771, 8777,24156,26147,36425,33823,40025,43073,43081,39936, +43443,22500,18803, 8829, 8770,40023,43072,39934,43438, 8546, 8827,24155, +26146,31154,29044, 8501, 8765,24153,26140,36424,33800,33820,40022,43066, +39933,43435,22498,18801,43065,40020,43434,39931,18800,22493, 8764, 8499, +26128,24151,33799,36411, 8826, 8544,26120,24146,29025,31141, 8762, 8824, +43063,40019,43432,39929, 2287, 2286,21235,26865,13688,26627,13207,20826, + 2106, 2073, 4667, 4378, 1966, 4054,13206,20825, 2159, 2168,18699,39853, +10355,39675, 2167,39852,13205,18520, 2158,39674,20824,20823,42653,42280, +18519,10116,21390,13926, 2032,42279, 1932,42652, 2166, 2157,42651, 5184, +42278, 5035, 2070,21389,20822, 4377,13925,13204, 5034, 5183,13924,21388, + 5033, 5182,39673,42650,39851,42277, 4221, 5142,18518,21387,18698,20821, + 4220, 4982,10115,13923,10354,13203,39850,42276,39672,42649,20820,18697, +42648,39671,42275,39849,18517,21386, 4376, 5032,13202,10353,13922,10114, + 4375, 5181,20819,18696,21385,18516, 4981, 5141,42274,39848,42647,39670, + 5031, 5180,42646, 5140,42273, 4980, 4219,21384,20818, 4374,13921,13201, + 5135, 5174,39653,42257,39831,42630, 5172, 5133,24141,26112,31138,29023, + 5026, 4969, 4975,24140,26111,36408,33796,39651,42249,42254,39829,42628, +21363,18686, 5139, 5179,39669,42272,39847,42645, 5178, 5138,18515,20817, +18695,21383, 5030, 4979,10113,13200,10352,13920,39668,42271,39846,42644, +21382,18694, 5170,24183, 5169,36516, 5168,39992, 5167,22753, 5166,21404, + 5165,39867, 5164,21361, 4045,26846, 4044,21215, 5162,39827, 5191,21359, + 5190,39825, 5189, 5160, 5159, 4043, 5157, 5024, 1891,42248, 1847,42621, + 4193, 4341,18472,20750, 1681,21357,10093,13145,13869, 2660, 7371, 2659, + 2658,13144,20749, 1846, 1890,39824,18682,39649,10344, 1872,39823,18507, +13143, 1889,39648,20748,20747,42620,42247,10107,18506,21356,13868, 1871, +42246, 1843,42619, 2205,26240,26211, 2200,24249,24232, 2478, 2517,36625, +34562,31491,29570, 2507, 2558,34076,37229,29433,31635, 8704, 8600,35491, +38460,30352,32396,28999, 8171, 8335,38314,35364,32268,30297,30134, 8698, + 8591,35488,38453,30345,32384,32389, 8166, 8333,38305,35357,32255,30292, + 2285, 7325, 1898,14098, 1896, 1895, 1894,39359,24288,41706,41800,20017, +37217,39357,36575,18022,26236,20013,24246,39355,39925,18013,18779,20001, +22482,39395,20196,39397,20208,40017,39923,20064,42324,12370,42658,19065, +18776,41387,41382, 9904,21392,10687,10412,41365,41360,18055,18053,39685, +20893,39857,18775,43056,43431,42334,18524,42660,22479,40016,39922,14502, +15946,39376,39374,20062,20060,21649,22478,39380,39378,12368,18702,43055, +43430,18057,39680, 9906,39855,39991,21351,22752,39816,39990,39815,22751, +21350,39639,39814,33754,42230,28989,42602,18468,18677,24118,26056,31087, +28988,10090,10312,10318,24117,26055,36340,33753,39637,20700,20705,39812, +18675,42228,42600,42219,42225,18464,42598,21348,39635,39810,13101,13106, +13844,26054,24116,33752,36339,20699,21346,26053,24115,28987,31086,42218, +42595,36338,39633,31085,39808,39667,39845,39666,39844,39665,39843,18693, +18692,10351,10350,18514,39842,13199,13198,10112,39664,20816,20815,10111, +18513,42270,42643,13919,21381,13918,42269,21380,42642,39806,21403,21344, +39866,39805,39865,21343,21402,39804,21342,21175,26830,39802,21173,26826, +21340,39346,24061,39338,32626,39333, 9843,39332,39331, 9814,39328,15936, +39183,11746,19744,25614,39182,39181,39180,19836,42268,11903,42641,17932, +17931,40961,40960, 9771,21379, 9770, 9769,40959,40958,17930,17929,39663, +20814,39841,17928,40957,40956,42267,18512,42640,19835,39179,39178,11902, +11901,39177,39176,19834,19833,19832,19831,39175,39174,11900,18691,40955, +40954,17927,39662, 9768,39840,39173,19830,11899,17926,40953,13197, 9767, +40952,20813, 9766,17925,40951,11898,19829,39172,11897,42266,19828,19827, +42639,11896,40950,21378,13917,39171,39170,39169,39168,14088, 3310, 3309, +35263, 2276,26305, 5245, 6267, 5248, 5445,10636,10624, 5401, 7751, 5390, + 5674, 2548, 5410, 3350, 3931, 3971, 3960, 6123,28071,22800, 8025,27598, +16338, 7478,22061,15427, 3847, 3840, 3822, 5835,26825,21172, 7148,26571, +13617, 6808,20693,13100, 3469, 3729, 3618, 6021,27993,22666, 7965,27534, +16152,16158, 7368,21963,15285,15291, 3513, 3757, 3655, 6026,28010,22688, + 7970,27539,16193, 7376,21969,15297, 3722, 3611,27986,22657,22659,16147, + 3608, 3610,25575,25569,25573,25568, 2720, 2722,23945,23941,23943,23940, + 3606,26233,26200, 2718,24244,24224, 3603,22654,16143, 2716,22466,15931, + 8720, 2547, 2499, 2498,35234, 8719,35524, 7050,35233, 6181,20028, 5622, +20027, 5610, 7023,23939,24648,23938,24484, 5952, 7920,22462,25567,27390, +15928,25566,27757, 5620, 7027,36388,33781,31116,29009, 5970, 7936,33795, +36407,29022,31137, 5612, 7025,24121,24653,24129,24494, 5960, 7922,26081, +27412,26074,27796, 5601, 7014, 6501, 5946,27753,22458, 7917,27387,15926, + 4317, 7284,21850,15156, 5825, 5940, 5824, 5794, 7123, 6732, 6038,28015, +22709, 7982,27551,16225, 7395,21983,15311, 8718, 5673, 7049, 8717,35523, +23937,21560,14272,15352,40871,22739,16272,23936,22733,16263,14776,40870, +21558,14265,23935,21474,14087,15148,40869,22445,15906,23934,41714,40868, +34075,23933,34079,40867,41730,23932,41537,31827,37396,23931,41448, 4494, +23930,41503,23929,26451,38349,32305,23928,24323,23927,40866,31785,37351, +23925,40858, 4472,23924,40862,23923,40853,38197,23920,23919,38475,23914, +23913,38152,23908,40840,28843,38481,23905,23904,23903,23902,23901,23900, +23899,23898,23897,23896,40839,40838,23895,23894,40837,40836,23893,40835, +23892,23891,40834,40833,23890,40832,23889,23888,40831,40830,23887,40829, +23886,23885,40828,40827,23884,23882,40823,40826,40822,23879,23878,40819, +40818,23877,23876,23922,23875,23874,32490,32499,23873,23872,32793,23871, +17197,23870,23869,29043,33819,24320,40817,29655,38507,24317,24309,28839, +33590,23867,23868,23865,40816,25558,25555,23866,40815,23860,23864,21472, +14085,40814,22439,15900,25548,23863,40812,23859,23856,40811,40805,40808, +23858,33581,33583,23854,23881,33580,33592,23853,23852,19635,33579,40804, +23848,23844,33560,33558,35258,40795,23843,33557,33556,35255,25392,23842, +33555,33554,23841,24131,24133,23789,17857,23787,18134,25390,26230,23785, +25387,26229,26199,23783,23782,23781,23780,23779,23778,24120,24128,23777, +17845,23775,27731,25366,18759,23762,23761,23760,23759,23758,23757,23851, +23847,40801,40803,23850,33457,33578,35260,23849,33572,23756,33456,23755, +25328,18750,10402,24219,24218,24217,24239,41600,41620,24216,24215,24238, +29171,33958,24221,24241,24214,24237,24213,24236,24223,24243,24231,24248, +24235,24212,41619,41599,24580,24740,24486,24650,24479,24643,24493,24652, +24536,24696,24535,24695,24534,24694,24533,24693,24640,40701,30096,38438, +24638,24477,35149,24692,24532,24054,24053,24052,24051,24050,23803,17878, +23801,25476,23799,23798,23797,33549, 3281, 2981,35267, 2427, 2429, 2425, + 2424, 2495, 7047, 7649, 2423,21521,14156, 2422,35247,23754,40705,23741, +40684,40700,23725, 4338,40674,23724,40673, 7842, 7748, 7750, 7746, 7745, + 7744, 7761, 7758, 7769, 7651, 7653, 7648, 7647, 7646, 7645,21520,14155, + 6300,21670,14601, 7644,35246, 8354,35392, 7811, 7809, 7813,37284,31745, + 7771,36483,31210, 7788, 7802,36473,31194, 4186, 4465, 4184,13064, 4181, + 4180, 4236, 4246,23721,39799,39630,23720,18459,23719,10083,18671,39628, +33435,13819,10309,39797,28701,21329,36039,30815,42588,42206,25299,25298, +13062,42586,20667,20672,42197,42203,23718,21332,13824,33434,42590,28700, +42208,30814,36038,25297,20676,13069,39022,22404,15866,17830,43413,13837, + 9689,43025,21338, 9687,17828,40683,11384,19518,39000,11387,42593,21639, +19521,42214,14460,40699,20689,13087,24049,24531,24691, 4190,23717,22449, +15912,25296,20692,13099,23753,22427,15895,25337,20666,13060,23716,22403, +15865,25288,20665,13059,13584, 4199, 4197,23711,19508,11363,25282,20745, +13140, 9063, 9396, 9184, 9168, 9338,38785,32799, 9254,23359,17393, 9336, +38782,32791, 9247,23353,17357, 9344,38793,32809, 9282,23387,17431, 9456, +38858,32878, 9094,23244,17141,23710,21540,14212,15278,40657,22649,16130, + 2758,21538,14208, 3347, 5771, 1853, 5082, 1788, 4966,42481,42234, 1708, +26963,42233,26591,42480, 1852, 3346, 3345,42479,37847, 1851,37846, 1835, +13635,42478,42232,37845,26590, 1785,10346, 1834,35043, 1833,37844,13634, + 6891,27206, 6890,42477, 6889,37843, 5951, 5949,22464,27759, 5930, 5929, +22774,28067, 5928, 5927,20495,26455, 5926, 5925,26249,26192, 5924,26307, + 5934, 5932,27724,22402, 5923, 6119, 5922, 7262,27717, 5920, 6917, 6277, + 5918, 5917, 5916, 5915, 5914, 5954, 6118, 6927,27234, 6888,42759,27205, +29027,43024,42739, 8746,29048, 8768,43069, 6886, 6887,27204,42738,28699, +43023, 8745, 8742,43021, 8741,43020, 8740,43019, 8784,43196, 8739,43018, + 8767,43068, 8523, 8744, 4957,42196, 5672,42195, 4956,42194,24230,42193, +33939,33938,24127,42192,33769,35199,24492,42191,35198,33768,24688,20662, +24528,20661,24048,41181, 4990, 4842,42304,37700, 5671, 5670,42303,37699, + 2546, 2545,37881,42519, 5669, 5668,37880,42518, 2544, 5667, 5666, 4137, + 5106, 5104, 5072, 5070, 5074, 5076, 5068, 5067, 5066, 5065, 5064, 5063, + 5100, 5096, 5095, 5094, 5084, 5062, 4634, 5061,42190,28698,42457,26562, + 4635, 5091,42302,26982,42517,26626, 4666, 5090,37879, 4989,13687,42301, +42516,37878,26981, 4665,10365, 4136,35060, 5089,42515, 4988,26625,42300, +42514,26624,26980, 4664,42299, 4135,26979, 5088, 4134, 4987, 4663,42298, +42513, 2163,37877,13686, 2162,42512, 2150,26623,37876,10364,35059,13685, + 2161,42297, 2142,37875, 2140,42511, 2149,42296, 5087, 4986, 1917,26978, +42295,26622,42510, 2148, 4848, 4862, 4827, 4826, 4841,37698, 4882,13463, +42509,42294,37697,26621, 4840,10189, 4881,34876, 4839,37696, 4880,13462, +37874,13684, 5086,37695, 4985,13461,42293,42508,37694,26977, 4838,10188, + 4879,34875,23729,34834,40698,40656,23709,34880,40655,41381,24211,34827, +41560,41559, 4874,34826, 4876,34861, 4892,34905, 4878,37693,13460, 4898, +37778,13508, 8353,35391, 8390,35436, 8581, 8534, 8602,38462, 8683,38525, +15448, 8641,38478, 8579,15277,38435,15138,33431,16652,33730,33429,34560, +29423,29381,40645,41866,33391,26227,33910,40643,18131,33513,11326,11531, +33511,28664,40769,33510,40787,33508,28642,40785,33751,18774,41232,27772, +33679,28943,12118,40634,40633,33677,28941,40629,40632,40628,33675,28936, +41598,41618,33605,33597,33360,33359,33358,33357,33787,39161,39321,39320, +36288,34527,26330,41849,18165,34522,26325,33349,34055,41845,18161,34536, +39160,38969,23693,41793,39327,39626,32091,42030,33307,32090, 4703,33453, +28723,25230,25229,33306,28623,26436,26446,33608,33305,40807,35522,19640, +33304,40825,35232,19645,33303,34053,33301,34044,34048,33298,41691,33296, +41683,41686,33295,33536,33540,33535,33292,33287,33282,33286,33935,33933, +33279,40631,33711,41180,33709,41173,35230,19918,33708,41172,35520,19917, +33707,41171,33577,28797,33278,28611,33892,29148,33886,29144,33277,28610, +33276,28609,33275,28608,33274,28607,33291,28620,33273,28606,43071,33822, +43437,35917,33272,28605,36118,33548,30917,35916,33484,35981,35979,30906, +28760,30775,33546,36116,33383,36083,28645,33367,28749,33482,33271,35915, +36081,30729,33270,28604,39412,30728,39470,35914,33309,33311,39410,39456, +18196,25216,28625,35913,39468,39505,20324,25215,30734,41748,35944,41830, +23695,23697,28638,39458,33331,39507,25232,25234,30736,33269,41797,41832, +18192,23675,35964,35966,41701,41752,20319,23674,35912,30727,41697,28603, +41792,33268,33267,28602,36620,34558,31487,35911,33425,33427,36622,28601, +37113,31476,28689,35910,31489,33266,34471,37010,34556,30813,36021,36023, +29384,34420,37214,28675,33409,33411,31478,37012,30791,33265,29426,35909, +37115,34422,36005,36007,34066,30726,34473,29386,35908,30725,34068,37210, +29428,33264,39067,39069,23701,30724,23703,35907,23673,39065,33386,25214, +23672,39063,28670,25213,36000,30777,40776,40768,25250,25252,33263,40764, +28600,40762,33262,28599,43013,30723,43400,35906,23671,21636,22383,25212, +14454,15824,15837,33740,28975,43052,33261,43429,36320,33739,28974,43051, +31074,43428,36319,24075,31084,21648,28986,22477,26012,36329,14493,33749, +15945,43398,43011,22377,15823,14439,21634,26052,24114,33366,33365,28644, +33480,28747,36111,33529,30902,36079,33473,33260,33259,33972,33258,33553, +33285,28618,41597,41617,33284,33970,33294,33539,33528,28778,11448,40591, +40590,33526,33525,33524,33523,39058,39057,23835,30901,23815,36110,33479, +25517,28746,25494,40753,40752,33538,28787,40610,40608,33522,33780,40589, +42861,23670,33778,35362,33256,35344,33254,33463,34043,29414,41685,41783, +34041,29411,26400,26365,34040,41682,34039,34052,29420,34038,29410,34037, +29409,34065,34064,29425,34036,29408,39406,31565,39466,37204,34456,39450, +18188,26395,37101,39499,20313,26360,41742,41824,24283,24274,29519,34552, +31485,41780,36616,41681,34035,29407,36615,34551,31484,37203,34455,29376, +37100,31472,34411,37003,34047,29418,41695,41790,34046,34050,34034,34073, +34032,33930,33941,29158,33932,29155,33929,29153,33798,41083,18043,35223, +35283,35285,35154,35225,35169,30109,40588,40587,35146,30088,22376,15822, +35144,30086,22374,15820,35142,30084,22372,15818,39529,39623,35148,35209, +39159,35167,39318,35262,30208,40586,40585,35254,30204,41614,41595,35257, +30206,40794,40799,35162,40709,18758,34825,35269,35266,10793,10619,35245, +10783,10561,35251,35243,35242,33724,33728,33722,33721,33968,34685,29738, +40704,40703,34727,29780,41380,41359,34710,29763,20739,40561,13138,40560, +34684,29737,20657,40559,13052,40558,33851,27196, 9902,42736,26993,36435, +42547,42321,12366,27711,36437,43010,33439,42468, 9680,42735, 9685,36043, +11382,33445,11374,42216,36041,43009,33849,37911, 9900,42734,35066,36431, +37907,33847,12364,27710,36433,43008,35081,12602,37746,35083,35007,31772, +37338,35022,35015,35047,35005,35004,35003,35002,35001,35000,10302,35071, +10368,35013,35012,35011,34999,10301,13577,37817,34998,42180,10300,28558, +17770,37820,19393,34996,13579,42450,37818,26546,35045,35058,42292,10363, +26976,10362,37873,13683,35057,13682,42507,37872,26620,35056,37692,10361, +13459,34874,37871,37691,35055,13681,10187,37870,34873,35054,37869,10360, +13680,35053,37868,33660,25733, 9805,40999,26975,36216,42506,42291,11876, +25732,36215,40998,33659,42505, 9804,40997, 9803,36214,11875,33658,11874, +42290,36213,40996,33657,37867, 9802,40995,35052,36212,37866,33656,11873, +25731,36211,40994,33655,37690, 9801,40993,34872,36210,37689,33654,11872, +25730,36209,40992,33496,34824,18484,18433,34860,34891,18526,34871,42289, +10186,26974,10185,37688,13458,34870,13457,42504,37687,26619,34869,37686, +10184,13456,34868,37685,34922,37771,10204,13501,34915,37764,35355,41246, +40557,24074,35361,40556,41290,23645,35390,35394,35388,35387,35423,35431, +35421,35420,35419,34424,34430,29390,34410,29375,34409,29374,34408,29373, +43003,34454,43397,37099,34419,34418,29383,34554,25244,41863,17813,34550, +27709, 2281,26243,26215, 2280, 2279,26242,26806,26214,26542,23643,17768, + 9617,19682,25590, 9615,11631,25602,17766,11650,19701,23641,24043,17975, + 9857,19915,25886, 9855,12116,25884,17973,12114,19913,24041,24525,18827, +24685,10438,18963,10587,18825,10436,24523,10585,24683,18961, 2443, 2442, +18824,26805,10435,26541, 2441,21154,13576, 9256,38787,32802, 9246,38781, +32790, 9253,38784,32798, 6490, 6682,39661,39839, 6676, 6675, 6674, 6673, + 6672,39158, 6697,23640, 6775, 6783,36532,31231, 6580, 6579,18960,26804, +10584,26540, 6578,21153,13575, 6857,38536,32501, 6867,38538,32503, 6855, +38534,32498, 6822,20490,12860, 7477,22060,15426, 6814,20485,12855, 7472, +22055,15421, 8988,38813,32831, 8677,38488, 8239,38346, 6280,21655, 6279, +21654, 6320,23639,23638,23637,23636,40555,23635, 6274, 6315,38953, 8751, + 8823, 6245,23632,23631,14039,20651,37335,31769,15808,34822,24166,24163, +37375,31808,23727,25314,39344,39342,23630,14031,25171,15799, 6241,42999, + 8753,42998, 6240,42997, 6239,42996, 6238, 7605, 7603,21633,24145,14431, +24150,23743,21632,14430, 7577, 7576,21645,23768,14481,23764, 6237, 6236, +21631,42614,14429,42241, 6235,21630,14428,24073,24072,24071,24070,41264, +24069,24066,24065,37331,31766,24064,26009,24063,21647,14491, 8775,43079, + 8774,43078, 8737,42995, 7643,21669,14595,23622,21711,14828, 7827, 7826, +21710,23621,14827,23620, 7824,21709,14826, 6347, 6349, 6351,38519,32485, + 6362,38530,32492, 6364,38532,32494, 6358,38528,32489,18365,24583,18606, +18598,18597,18596,42444,37811,24657,24497,24634,24469,35138,24040,24039, +24522,24682,24681,24521,24578,24738,39405,39465,41680,20283,41779,18147, +18187,41741,20312,39449,41823,39498,24520,24680,24679,24519,24038,24037, +39157,39156,40949,19826,40948,17924,23619,23846,24202,35241,41126,33720, +25977,35386,41125,33719,25976,33718,41124,24482,24646,23834,23814,19058, +10678,43037,36075,43422,30854,19057,10677,42994,35892,43396,30674,15796, +22352,24144,24149,23613,23612,19134,10762,42990,37248,43394,31694,18444, +10075,18466,10092,18432,10073,18431,10072,18552,10124,18550,10122,23611, +23610,24036,24035,24518,24678,24677,24517,18454,10080,23609,23608,22370, +22368,15817,18448,25149,25148,18744,18741,10391,20660,23752,23751,22426, +22425,15894,18430,25336,25335,18757,18756,10405,20648,24161,24159,22349, +22348,15794,18522,26155,26150,18733,18732,10388,20880,35161,40708,34821, +25334,18505,10106,18494,10104,23607,23606,19397,19395,11212,18488,25147, +25146,17776,17773, 9620,20742,18381,38855,18383,23136,18385,38407,17765, +38850,17764,23121,17763,38405,17762,43195,17839,43034,17985,42989,17984, +42731,28965,42744,31065,17998,28977,19979,31082,42988,19997,43054,18379, +37275,17761,42173,28551,26945,42439,42170,28550,26539,30673,42436,42437, +19380,26536,26537,17760,42307,28549,30672,19379,42537,17759,42176,28548, +26948,37814,17758,34994,19378,30671,42446,19377,37812,17757,42746,28547, +30670,19376,43059,18265,10019,18264,10018,42987,20311,43393,18186,18921, +18906,18919,18915,18807,18731,38831,18730,23104,18729,38403,18869,18878, +18890,18823, 1666, 1701, 1613,22346,27707, 5904,15787,15792,27365, 7899, +15124,15129,21836, 7255, 1669, 1704, 1616,22339,27700, 5897,15785,27358, + 7892,15122,21829, 7248, 1664, 1699, 1611,22772,28065, 6116,16309,27593, + 8020,15404,22040, 7459, 1663, 1698, 1610,21183,26835, 5820,13632,26587, + 7143,13137,20738, 6799, 1829, 1839,37855,42487, 1838, 1828,42486,37854, + 2028, 2063, 1963,40545,40543, 2030, 2065, 1965, 2026, 2061, 1961, 2025, + 2060, 1960, 2154, 2146,37897,42535, 2153, 2145,37896,42534, 1827, 1837, +37853,42485, 1662, 1697,21182,26834, 1622, 4117, 7502, 7272, 7274,27373, +27378,27730,27742,17756,17854, 7245,27355,27697,18094, 7287,27392,27763, + 6313, 7244,27354,27696, 6266, 7243,27353,27695, 6311, 7242,28038,27694, + 7421, 7241,27352,27693, 6335, 7267, 7266, 7265, 7494,23605,23604,25145, +25144,23603,25143, 7324, 7323, 7322, 7321, 7320,20812,13196, 7319, 7318, +21377,13916, 7317, 4373, 7238,26225,26196, 8973,23120,16979, 8991,23130, +16996, 7361, 7359,33574,27527,28795,27980,30929,36127,23669,25203,23595, +25135,23750,25342, 8946,23103,16963,18369,38399,17755,38397,18727,38395, +39660, 8200,39838, 8199, 8198, 8197, 8196,39155, 8195, 8452,38335,42884, + 8140, 8431,38284,42842, 8238, 8459,38345,42916,17754,17853,18767,18068, + 4795, 4925,37367,42056, 4484, 4737,42533,37895, 4794, 4924,37366,42055, + 4483, 4736,37894,42532, 5148, 4829,39792,26808, 5188, 4825,39864,26903, +39989,27146, 4804,37381, 4788,37328, 4856,37595, 4824,37717, 5146, 4855, +39788,26801, 6299,27264,27094, 4457, 7316, 4456,27091,27262, 6297, 4299, + 4454,27752,27386, 7280, 4453,27978,27525, 7357, 4452,28047,27577, 7432, + 4451,27140,27285, 6329, 4450,27692,27351, 7237,13569, 4475,27089,27259, + 6295, 6696,21031,13404,34709,29762, 4560,34755,29808, 4581,34683,29736, + 4540,33871,35166,33467,24062,23862,25554,23594,25134,23714,23713,25286, + 4462, 4464, 4447, 4446, 4445, 4444, 4443, 4442, 4441, 4490, 4488, 4440, + 4439,34673,29726, 4521,33234, 4460, 4438, 4471, 4714, 4116, 4473, 4716, + 4119, 4497, 4755, 4167, 4493, 4495, 4753, 4165, 4466, 4711, 4111, 6367, +21723,14912, 6860,21744,15033, 9259,23362,17407,23593, 6328,21692,14780, + 6339,21695,14794, 6324,21690,14774, 4486, 4739, 4149, 4482, 4735, 4147, +14023, 4480, 4733, 4145, 4479, 4732, 4144, 4793, 4923,37365,42054, 4807, +37432, 4864,37753, 4806, 4936,37431,42088, 7907,23592,42849,23591,42851, +23590,42847, 8458,42915, 4918, 4916, 4911, 4910, 4909, 4933, 4932, 4931, + 4908, 4907, 4914,33979,42019,18138,33978,33765,42018,18021,35195,35194, +42017,18787,33764, 4922, 4792,42053,37364, 4747,26177, 4701,26259, 4705, + 4704, 4700, 4699, 4698, 4724, 4726, 4741, 4152, 4707, 4109, 4697, 4101, + 4696, 4100, 4695, 4099, 4694, 4098, 4693, 4097, 4745, 4156, 4749, 4162, + 4751,25133,24475,35152,24229,33977,24126,33763,24491,35193,34428,29388, +37024,34477,31481,37194,37023,31480,42016,37193,42435,34476,18270,10027, +26730,20331,26939,18213,20344,12777,42015,18212,42434,20330,18798,10416, +26729,20025,26938,18796,21497,14105,42014,18038,42433,21501,18025, 9892, +26728,21500,26937,18037,20021,12308,42013,18795,42432,20024, 4927,42065, + 4906,42012, 4935,42087, 4159, 4161, 4096, 4095, 5108,35087, 5099,35070, + 5057,34992, 4094, 5661, 4092, 5336,14586,14141,11159,11144, 4091, 5658, + 4090, 5522,14874,14302,14990,14331, 5862, 8892,17350,17552, 4089, 4088, + 4087, 5339, 4103, 5225,14403,14016, 5549,35329,26162,10521,41333,26658, +38425,42315,42540,15112,26160,38424,41335,33653,25729, 9800,40991,26618, +36208,42288,42503,11871,25728,36207,40990, 4791, 4921,37363,42052, 4478, + 4731,21062,26749, 4143, 4142,37893,42531, 4053, 4052,21234,26864, 4790, + 4920,37362,42051, 4477, 4730,21061,26748, 2152, 2144,37892,42530, 2059, + 2024,21233,26863, 4141, 4051, 1959, 4140,35970,21026,19466,37325,19470, +37594,35973,20647,36795,37324,20288,21025,20446,20646,37216,37593,36757, +37592,20286,20645,20426,21024,37208,37323,36392,41275,36391,41274,36390, +41273,36562,26297,36140,27688,36146,27687,37256,36530,36566,21023,20236, +37322,20194,37591,36542,20644,36570,37273,38249,36136,30938,42243,33227, +42616,33585,35886,30656,42245,33587,42618,33226,35885,30655,43077,28533, +43442,33225,36062,30839,43032,28725,43420,33455,35884,30654,42323,28532, +42657,33224,35963,40621,35883,30653,28530,41592,37231,31646,37228,31634, +37227,31633,37226,31632,37225,31631,36387,31115,36386,31114,36385,31113, +36384,31112,36134,40810,36142,40821,36071,40723,42984,38423,38141,32157, +38140,32156,38139,32155,38149,27088,38109,42750,38108,42749,38107,42748, +38187,27117,38186,27116,38100,42743,38088,27686,38247,38185,27115,38191, +27124,38214,27132,38159,27072,38158,32171,38157,32170,38156,32169,38228, +27110,38222,32183,38091,32101,38138,27063,36315,41193,31056,36314,41192, +31055,36313,41191,31054,36317,41195,31058,36312,31053,36311,31052,36310, +31051,36488,36486,36503,36501,37279,38775,37277,23368,37238,21750,37281, +21729,38738,38749,38748,38747,38746,38867,37264,27685,37262,31730,42983, +29628,43392,34603,37271,21705,37267,27297,37266,21703,37261,21701,36206, +40989,40988,36205,36204,40987,11870,25727,37684,13455,36203,40986,11869, +25726,37865,13677,36202,40985,11868,36078,42982,36077,40791,11447,37590, +37321,37589,37320,37588,37319,37587,37318,37601,37727,37586,37585,38474, +27258,38427,42992,38441,43041,42981,38422,38491,38421,40661,15111,25290, +37828,13590,37018,41853,37017,41852,37016,41851,37014,41847,37022,41855, +36427,41329,37904,42542,20055,26153,42839,38280,36037,40659,42464,37830, +19498,25285,42838,38279,36429,41331,27347,21820,20057,26158,42837,38278, +37832,42467,37810,42431,37809,42430,37825,31965,37834,31981,37808,31952, +37807,31951,37806,31950,37805,31949,37804,31948,37917,37915,37803,37802, +37901,37900,37801,42429,37800,42428,37799,42427,37910,42544,37909,32040, +37903,32034,37891,42529,37361,42050,21232,26862,21060,26747,37890,42528, +42049,37360,21231,26861,26746,21059,37889,42527,21230,26860,37888,42526, +21229,26859,36250,41019,31021,36249,41018,31020,36248,41017,31019,40536, +36252,41021,31023,36246,41015,37359,42048,19815,25716,41014,36245,36244, +41013,42047,37358,19814,25715,41012,36243,36242,41011,37887,42525,19813, +25714,41010,36241,36240,41009,42524,37886,19812,25713,41008,36239,36238, +41007,25712,19811,19810,25711,41006,36237,38303,27404,38277,32219,32089, +31946,38295,32233,38293,32229,38301,32251,38313,32267,38312,32266,38311, +32265,38310,32264,38316,32270,38322,27497,38321,32275,38320,32274,38319, +32273,38348,32304,37330,37597,39790,37599,37315,37576,39863,37575,39988, +37574,37314,37380,21016,21068,20643,20887,37573,37716,37379,37715,39787, +37714,37313,37312,37393,37311,31761,37371,31804,37429,31832,37334,37333, +31768,37340,31774,37317,31763,37373,31806,37310,31760,37309,31759,37308, +31758,37307,31757,37306,31756,37305,31755,37342,31782,37304,31754,37395, +31826,37357,42046,21058,26745,37356,42045,21057,26744,37384,21073,20905, +37725,37383,42080,21072,26757,36539,31236,42240,33909,42613,33908,36552, +36554,41277,27230,41843,41861,41231,32116,41230,41229,41228,40619,41868, +26318,41870,26320,40616,41138,41136,41859,41151,41140,40535,21494,14101, +23589,22490,15957,40534,22327,15761,11105,12188,25952,21433,14012,41188, +42876,41187,42788,41186,41198,41197,41185,41184,41183,41190,22326,15760, +25107,21432,14011,40532,21476,14091,25705,22469,15935,40531,22471,15939, +25961,21478,14093,40530,40528,40529,40526,40524,40522,40521,40546,40520, +40525,40519,40517,40518,40515,40513,40511,40510,40516,40509,40544,40508, +40527,40507,41533,40506,41451,40505,41499,40504,26449,40503,25565,42936, +22325,41892,27294,40502,40500,40501,40498,40497,22354,40496,27209,40495, +40494,40493,40492,40491,40490,40489,40488,40487,40486,40485,40484,40483, +40482,40481,40480,40479,40478,40477,40476,40475,40474,40473,40472,40471, +40470,40844,40873,40842,40469,40468,40467,40731,40727,40726,41525,41516, +41491,41482,41440,41413,41439,41412,41515,41524,41481,41490,43735,22324, +15759,16624,28157,21431,14010,43733,32591,21430,14009,28150,22323,15758, +43855,22322,43755,43758,43761,43764,43754,43757,43760,43763,43720,43719, +43718,43717,43716,43715,40425,40428,21429,14008,23586,22321,15757,40421, +40427,40420,40539,21428,14007,25691,22320,15756,40538,40419,41106,41105, +41104,41103,41102,41101,41100,41099,41098,41097,41096,41095,41094,41093, +41092,41091,41624,41622,41170,41169,41155,41150,41149,25938,40466,41386, +41364,41377,41358,41385,41363,41376,41357,41362,41384,41356,41375,40682, +40681,40697,40696,40680,40695,42655,42309,42637,42264,42636,42263,42635, +42262,42612,42239,41840,41839,40760,40781,40751,40750,40749,40748,40747, +40746,40745,40744,40743,19610,11499,40767,40742,19609,11498,40922,40921, +40920,40919,19824,11893,40806,19637,40824,19642,43451,43494,43383,43382, +43381,43426,43425,43403,43406,43493,42869,43492,41082,43497,25564,43543, +26448,43380,27232,43418,27208,41130,41128,41123,41122,41121,19910,41120, +19909,41119,21668,14585,25832,19949,12173,41118,21519,14140,25831,19948, +12172,40717,21471,14084,25676,22424,15893,40716,21470,14083,23749,22423, +15892,40715,21469,14082,25333,20638,13037,40714,40713,21468,21467,14081, +18429,25332,25331,18755,18754,10404,20637,43096,43094,43089,43552,43379, +43378,43391,43377,43405,43402,43376,43412,43411,43410,43050,27771,43049, +27770,43154,43150,43147,43146,42787,42875,42786,42791,42879,42790,42878, +42785,42874,42784,42873,42783,42872,42797,42800,42887,42799,42886,42804, +42889,42806,42891,42796,42883,42795,42882,42794,42881,42756,42863,42773, +42771,42766,42151,26932,42150,26931,42149,42148,42147,43496,43152,43542, +43214,43417,43030,42146,42578,43375,42972,42145,26304,42144, 8714,42143, + 4292,42142,41168,42213,26958,42212,26957,42211,42592,19520,28500,11386, +33192,42172,26944,42175,26947,41865,40982,40981,36199,25725,40980,33652, +36198,41589,38420,41594,26258,28531,41575,30651,28499,28529,30616,41573, +28498,26256,41591,41588,26253,29448,41570,31341,29251,41587,37002,26222, +41569,34280,36861,41579,41583,42426,42003,42441,42021,42422,42001,42421, +42000,42420,41999,42419,41998,42418,41997,42549,42554,42417,42416,42415, +42414,42413,42461,42460,42466,42035,42463,42033,42157,42424,42141,42412, +40979,40978,25668,42855,26110,42918,25092,42853,42871,42934,22317,42082, +25091,41996,26252,41995,41994,42037,43149,43093,42770,43091,42768,42068, +26182,43088,42765,42067,41993,41992,41991,41990,41989,41988,41090,42493, +42031,42411,42455,41986,42410,42058,35228,41985,33976,41984,33762,41983, +35192,41982,42064,26720,26751,42079,26756,41556,41555,41554,41553,41552, +41551,41550,41549,41548,41547,28954,36303,29445,28595,30719,28949,31037, +31036,28948,29138,29146,42040,18503,28890,11603,42085,18546,29136,12591, +28992,34983,33191,33607,28497,28496,28495,30615,28494,30614,28598,30722, +28597,30721,28493,40722,28492,43040,28938,33362,33190,28940,28933,33521, +28882,33189,28885,28491,33576,28490,28489,34058,28488,43036,30613,28487, +33738,43048,30612,28486,33188,33589,30951,30611,36138,35850,37007,33187, +34415,37109,35849,34465,37206,33186,33354,35968,35848,34061,36115,33185, +33364,35978,35847,33545,36598,33184,33281,35919,35846,33986,37009,33183, +34417,37112,35845,34470,37005,33182,34413,37103,35844,34460,36002,33181, +33988,36600,35843,33389,36004,33180,34063,37213,35842,33408,35921,33179, +33533,36113,35841,33289,29190,34982,29185,31274,29184,33907,37001,33984, +34407,37098,36596,34453,37212,33407,18346,19496,28643,33544,28617,28614, +28485,28484,28483,28673,28481,28479,29406,31544,29413,33178,34458,29378, +33352,37000,34029,34406,37097,37202,34452,29424,33406,34469,29382,29417, +29281,29422,29317,29405,29250,28838,28836,37849,42483,28814,30940,28478, +28477,37842,42476,28476,30606,28475,28474,38452,43058,28473,30605,28472, +28471,42453,37823,28739,28734,38419,42971,29679,43208,29678,43207,31729, +29627,33177,43206,31728,29626,29677,29650,43205,38505,28776,28775,42970, +36999,33520,34405,37096,36109,34451,35977,33543,17815,19590,28786,28783, +28774,28772,28771,30898,28770,28769,42474,37840,29623,12817,34588,34600, +31712,31658,37250,37234,37236,37269,29630,29589,34609,34590,33919,33906, +33913,33905,42969,31273,29183,33904,31235,36538,33925,31246,36556,36588, +29160,33943,37105,34462,18195,20323,37111,34468,18199,20327,37192,34475, +34981,37798,37021,34427,37199,34486,34447,37041,37036,34442,37198,34485, +34446,37040,37035,34441,37197,34484,34445,37039,37034,34440,37196,34483, +34444,37038,37033,34439,29372,42968,31543,29404,33981,31196,30367,30203, +30366,41981,18427,30356,14108,42029,18442,30336,14049,43491,18868,41980, +32456,32455,30380,30282,32249,32248,37303,10546,37572,14501,20624,30273, +35009,30290,34980,30280,30107,30279,30106,42967,38418,34593,34595,19025, +34597,19027,34592,19023,35427,30962,17897,28470,17732,38480,19333,35429, +19649,30604,38482,28844,35458,30603,17731,29656,18373,38508,20466,35444, +19332,31721,38493,28469,35460,31660,18367,29663,18375,38516,20472,35448, +20459,31725,38495,29587,28963,35440,31716,18371,30078,18726,38490,21427, +35454,20463,32088,38502,29646,29661,38512,29659,38510,34979,37797,17730, +19331,34977,37793,37795,35338,30602,17729,30097,18746,38439,21463,35336, +19330,32099,38437,28468,29180,29178,35416,31261,18112,29162,38477,20192, +35434,31268,18127,29166,38486,20217,35328,31264,18119,29164,38417,20198, +35327,31092,18019,30124,18785,38416,21482,35326,20004,32123,38415,28995, +34436,37030,18144,20280,34399,36995,29581,31652,29460,31502,31466,29366, +29003,31106,30139,30601,32132,28467,30142,30600,32143,28466,31130,29012, +34426,37020,17728,19329,34393,36989,28465,30597,29451,31497,31451,29356, +29455,29447,31340,30077,32087,31494,29249,30178,30202,30177,30299,30201, +30200,34404,36998,18725,21426,34279,36860,29360,30138,38134,36982,29363, +30425,38670,36988,29362,36987,29359,36981,29848,31780,31779,37302,10167, +37571,13097,20623,29838,31753,31752,37378,10150,37713,13026,20886,29854, +29837,29836,29887,36236,41005,31801,32030,31800,32029,41004,36235,37355, +42044,31799,32028,31798,32027,29877,29972,42043,37354,31797,32026,31796, +32025,29876,29971,37885,42523,31795,32024,31794,32023,29875,29970,42522, +37884,31793,32022,31792,32021,29874,29969,29873,29968,31791,32020,31790, +32019,29872,29967,37442,31835,31838,29892,20945,13294,37758,10198,37441, +42091,31834,32051,31837,32054,29891,29979,29963,29965,29961,29949,29948, +29947,29946,29945,29976,29975,29974,29956,31972,31971,41977,33975,31945, +33761,31944,31943,35191,29944,31942,31941,42063,42090,32050,32053,29978, +37353,42042,31017,31016,31015,31014,28924,28923,37883,42521,31013,31012, +31011,31010,28922,28921,36234,41003,31009,31008,28920,31007,31006,28919, +36573,36559,30749,41750,39927,27061,36085,28663,39519,26343,39521,26345, +39517,38971,39061,30955,30953,28834,28832,26597, 9597,20771, 9596,30942, +28812,13649,13159,36568,29087,20211,36550,30974,39555,30976,31207,31202, +39566,31213,39568,31215,32332,32324,14975,14864,32331,30971, 9587,30784, +30885,11334,11536,31035,28947,31034,28946,31033,28945,31032,30680,30682, +31027,43145,27971,38105,36361,38104,36360,38103,36359,38102,36358,30596, +30904,30595,30731,30594,30858,30593,30922,30592,31569,30591,31279,41602, +28464,40779,28463,40729,28462,30788,30920,30787,30919,30589,32108,30587, +30851,40741,31218,31282,31217,33158,31244,33923,33157,31281,31243,33922, +31223,31649,31222,33156,34481,31229,33155,31648,34480,31228,31103,41708, +30586,41705,30751,34057,30585,34060,30837,33551,31227,34479,33921,31242, +30584,33388,31238,33912,30583,33405,34467,30582,30581,34464,31590,33351, +33917,31240,31277,33471,30580,33542,30579,35822,28461,24137,33154,24135, +30578,35821,28460,20315,33153,18190,30577,35820,28459,20322,33152,18194, +40766,40775,28458,28669,33151,33385,31272,30897,33903,31234,31271,34450, +33902,31233,31270,36595,29182,20310,33983,18185,30576,35819,28457,20059, +33150,18701,40773,28667,42406,40772,30889,33149,30856,33148,31111,42577, +31110,31109,12307,41976,20622,30843,33147,31877,31865,31864,31875,38137, +37570,31904,31542,30896,31541,34449,31540,37201,29403,20309,34026,18184, +31630,42576,31629,31628,12776,41975,20621,31903,43374,33146,31108,31627, +33356,33519,31045,33145,43156,38484,28456,28455,38443,43045,28454,28453, +31152,30572,38414,42966,29040,29047,43204,38501,29676,29645,30895,36108, +28768,23808,33518,23827,31710,42921,31727,29625,36586,36582,36581,36580, +36579,36584,40740,29152,33928,31288,36607,29197,20336,33993,18262,31287, +36606,29196,20335,33992,18261,31286,36605,29195,23570,33991,23569,31284, +36603,29194,20334,33990,18260,37259,22029,43144,27970,32398,33816,32358, +33967,32372,33144,32371,32472,32357,32356,32355,32375,32377,32470,33143, +32469,32454,31940,32488,14328,32491,14344,32497,14301,32500,14308,39361, +26101,32247,10545,39782,26792,32246,31751,14500,13025,32238,39552,32227, +32323,32235,32231,32312,42580,32225,14040,42025,20652,32253,32263,42575, +32262,32261,14104,41974,20620,32260,32259,32300,32243,41593,28452,30571, +31099,41604,28451,30570,28450,30569,28449,41607,29090,41606,29089,30841, +28727,31733,29666,31732,29665,31225,31499,31220,31266,30568,31496,30567, +31263,30566,32131,30565,31105,30564,31091,30563,32122,30562,28448,42539, +28447,37827,28446,32197,32191,32196,32190,31097,31096,31095,38514,20470, +31258,31251,33142,31249,33223,31256,31255,31254,30650,30561,41572,26255, +41586,29175,31260,32084,31062,28962,32185,25060,43143,27969,32154,32153, +32152,32151,21506,32150,21505,37792,38136,43087,27905,42764,27245,41135, +25798,38184,32179,32181,32177,32114,32083,31493,32129,32128,32127,41585, +29248,31771,10157,39784,26794,31750,10149,39862,26902,39987,27145,31749, +31778,13024,13096,31777,10166,39781,26791,33466,43424,35165,40725,33880, +43390,32468,43373,32475,32374,33139,32354,31789,32018,31005,31004,31788, +32017,31787,32016,31830,13286,31829,32048,32045,25059,31976,25310,31939, +26251,31947,31983,31938,31937,32043,12475,31936,14107,31974,14074,31959, +35141,31935,33974,31934,33760,31933,35190,31932,13023,32258,14103,31931, +13022,31930,13021,32223,14038,32221,32257,32014,32013,31992,11595,31990, +31988,31986,31985,31963,31929,37791,29943,21499,34974,18036,29942,34973, +31928,18794,37790,20023,31927,37789,29941,20329,34972,18211,31926,31970, +32047,31003,32903,32767,32894,32750,32590,32608,16656,32623,12282,11039, +32630,32627,16680,32582,16581,32576,32615,32614,32573,32572,32570,32568, +32651,32665,32650,33138,32656,33896,33137,32664,32655,33895,32654,33894, +34023,32564,32563,33517,32562,41669,32828,32827,17502,17501,32745,32744, +16798,16797,32825,17495,32917,17319,32824,32850,17318,32849,32783,17544, +32797,17565,32561,32560,32658,32646,32926,32914,32913,32559,32558,32690, +32795,17563,17381,32684,32777,17541,17317,32672,17200,32670,17194,32669, +32741,16962,32740,32739,32738,32789,32923,32737,32736,32766,32755,10229, +10284,10239,10165,10237,10159,10228,10148,10227,10147,10226,10283, 9863, + 9748,40145,10048,40165,10050,40167,32291,31050,30365,28953,30176,28952, +28951,30343,30129,32290,32168,30364,30175,30174,30363,30199,30379, 9665, +21011,36541,36756,35972,36365,20445, 9752, 9582, 9750, 9581, 9627, 9634, + 9580, 9579, 9578,11036, 9648,11282, 9577,11035, 9667,34545,34581,35202, +33772, 9889, 9885, 9884, 9883,17877,17837,17713,17879,18133,17856,17712, +18096,17858,18098,18135,17711, 9949, 9955, 9953, 9952, 9951,18129,18093, +10037, 9640,23566,23565, 9646,23564,20220,33136,41616, 9694, 9697,23563, +19433,33135,40607,23562,24496,33134,35221,24699,33133,24539,33132,24046, +41177,10234,10296,10225,10282, 9726,21010, 9717, 9716, 9715, 9714, 9713, +11524, 9728,17865,24209,33927,10733,10730,23561,19623,33131,40798,23560, +24148,33130,33815,10024,21009,23559,20317,33129,41789,23694,20321,33330, +41796,40707,35160,25330,18753,34859,10070,18483,13378,34808,10099,18426, +13436,34909,10126,18555,13494,10794,10495,10784,10441,10782,10434,10796, +10498,10799,10512,10801,10515,10281,10224,10280,10223,10290,10231,35069, +34971,10279,26303,10278,10277,24228,33937,24125,24490,33767,35197,24673, +13015,24513,13014,24030,41167,10777,10431,10306,10236,34976,10768,10408, +10359,10183,10358,10182, 9797, 9796, 9795, 9799, 9794, 9793,10191,10196, +10146,10145,34402,34382,34392,34391,34390,34389,17710,18023,26235,26237, +26202,26204,18125,18089,18105,18118,17709,18100,18018,17708,18784,18778, +17707,18012,18092,26221,26195,18091,18724,18111,37836,42470,21174,26829, +37838,42472,21177,26832,37857,42495, 9576, 9575,21216,26848,11031,11030, +36545,41564,20204,26213, 9574,11029,36549,41567,20210,26218,41566,26217, +10511,10644,10497,10634,10420,10555,10514,10653,10508,10637,10403,34807, +14078,18425,36535,41546,20191,26194,10473,10618,10430,10580,10480,10623, +10491,10625,30183,10532,40102,10560,10582,10554,10579,32289,32272,10562, +10590,10628,10770,10617,10776,10620,10632,10550,10549,10548,10655,10630, +10616, 9860, 9852, 9851, 9854,10530,20618, 5566,20617, 9573,20885, 9712, +20616, 4291, 4290, 4289, 4288, 4287, 4286, 4356, 4355, 4354,41343,41339, +40665, 6669, 6709,20614,13010, 6821,20611,13007, 7470,22053,15419, 6720, +21548,14238,30101,35158,15891,22422,29753,34700,13136,20737, 4549, 4518, +29770,34717, 4565,29796,34743, 4572,29734,34681, 4535,41611,18173,41613, +33786,35208,34535,18103, 4285,42625,32907,32906,32195,32189,32188,32194, + 4993,42313, 4949,42140,42312,20607,20879,42139,10304,20606,13058,42138, +10729,20605,16109,42137,42448,42178,10276,42491,42136,42490, 4948,42489, +10286,42409, 4954,42443,36593,42135, 4284,42134,10029,42133, 9940,20935, + 9939,23558,12616,42351,23557,20934,33126,42350, 9183, 4283,10121,18549, + 4282,40459, 4281, 4280,20604,42634,13003,42261, 4279,20603,13002, 5137, + 4978,20602,42260,13001,42633,42632,42259,20601,20600,13000,12999,18690, +10349,20599,20598,12998,18689, 4278,20597,12997,18511,10110,20596,20595, +12996,18510,40918,20594,12995,17923, 9765,40917,20593,40916,17922,40692, +40691,40690,40689, 4320, 4322,40418,40417, 4306,40416,42585,42574, 4973, +42252, 4972,42405,42201,20670,42404,42200,10316,20703,13104,42223,10315, +42403,10097,18481,20592,20591,18478,12994,13134,20735,18415,18413,20734, +10063, 4277,20590,12993, 4335,20733,13133,35135,30076,22307,15748, 4399, + 4401, 4276, 4275, 4274, 4273, 4272, 4271,29721,34668, 4515, 4304,40712, +21466,14080,23748,22421,15890,40415,40514,41545,41544, 6668, 8194,33785, +35207,34534,40424,21425,14006,23588,22306,15747,40423,40414,40413,21439, +14026,23556,22334,15779, 4372, 4369, 4368, 4367,35151,30093,22413,15879, +35150, 4709,42027,20654,31957,13047, 4743, 4692,42062,20878,31969,13057, +32452,16107,32464,32480,32369,18743,24473,20658,26549,18117,24227,20589, +26528,18017,24124,20588,26527,18783,24489,20587,26526,40412,10275,20877, +12992,42311,41973,20586,31925,12991,30092,30275,29355,29432,30137,30296, +29002,29008, 4318,17706,23555,20691,26570,40411,25557, 6570, 4334,29718, +34665,12990,20585, 8185, 4333,34541,40410,21144,13573,23554,21321,13811, + 4337, 4332, 4331,17775,23649,20740,26589,18110,24208,20732,26586, 4339, +17705,23553,20744,26593,10094,18475,20584,20583,18473,12989,13156,20767, +18411,18408,20766,10060, 4269,20582,12988, 4346,20765,13155,23552,23551, +20958,20950,18569,13299,10132,18561,20957,23550,18568,23549,10131,18560, +23548,20949,23547,13298,10128,18557,20955,20947,18566,13296,23546,20967, +13309, 4426, 4425,20966,23545,13308,23544, 4422,20964,13306,18123,20907, +18736,26927,18735,20656,18116,20581,18016,20580,18782,20579,18072,27682, +18077,20932,18075,26926,18074,20930,18070,20923, 7374,21967,15295, 6806, +20578,12987, 7475,22058,15424, 7355,21955,15281, 6829,20897,13255, 7482, +22065,15432,17704,26941,39072,22305,15746,25553,21424,14005, 4345, 4344, +20764,39836,13154,39658, 4330, 4329,20731,26878,13132,26640, 5176, 5028, +20763,39657,13153,39835, 4328, 4672,20730,26639,13131,26877,39834,39656, +20762,20761,13152,13151,26876,26638,20729,20728,13130,13129, 4343,21375, +13913, 4327,21249,13704,39129,20760,13150,25661,20727,13128, 4364,20803, +13187, 4385,20846,13227, 4366,17904,26925,17903,20775,18109,20759, 4352, + 4363,17703,20773, 7224,21817,15106, 7278,21845,15151, 6793,20758,13149, + 7453,22033,15389, 4419, 4418,18063,20916,18723,20909, 4414, 4413,17702, +20911, 7222,21815,15104, 7399,21987,15317, 7350,21950,15275, 4312, 4362, +17701,20681, 7220,21813,15100,23543, 7430,22016,15356, 7436,22020,15361, + 7409,22000,15333, 7391,21981,15309, 9607, 9609,20868,26645,26883, 9571, +21254, 9570, 9569, 9568,20862,26642,26881, 9605,21252, 9603, 9711, 9710, +20845,26634,26872, 9709,21244, 9708,32149,17742,27675,18764,26633,17850, +27739, 7293,27674,27803, 7219, 7264,27723,27722, 7263,17700,27691, 7218, +27690,27673, 7233, 4397, 4384, 4387, 4383,10544,26524,14097,37564,10164, +26523,13611,37563,37712,26522,26665,37562, 4854,37711, 4819,37561,10169, +26582,13623,37610,37603,26564, 4833,37657,23542,26552,23747,26521,10144, +26664,13559,37710,24179,26684, 4622,26520, 4642,26575, 4621, 4680,26519, +26657, 4620, 4010, 4619, 4009, 4618, 4008, 4617, 4007, 4616, 4006, 4615, + 4005, 4614, 4004, 4613, 4003, 4612, 4002, 4651, 4042, 4650, 4041, 4649, + 4040,17699,42365, 4999,42364,42338,26673,42337,26672,17698,26694,10370, +26693, 9943,26689, 9942,26688, 4611,26518, 4610,42500, 4609,37862, 4608, +26517,42499,26516,37861,26515, 4984,42285,42284,26514,10357,26513, 4837, +37681,37680,26512,10181,26511,40976,36197,36196,40975, 9792,26510, 4627, + 4019, 4677, 4066, 4629, 4023, 4679,26656, 9567,17697,26655,26157,26889, +26152, 9850,17972,26509,25868,26789,25867, 5989, 4001, 5982, 4017, 9724, + 9832, 9821, 4068, 4021, 4025, 4000, 3999, 3998, 3997, 3996, 3995, 3994, + 3993, 3992,18079,18763,17849,17696, 5676, 3991, 5978, 4076, 9819, 4640, + 4639,26788,26573,26828,26827, 4655, 4607,26604,26847,26850,26787, 4653, + 4606,26845,26508,26844,26786, 4072, 4071, 4070, 9601, 9599,13239,13706, + 9566, 9565,13247,13710, 9707, 9706,13224,13694,32148,17740,27672,18762, +26869,17848,27738,17695,27802,26341,38967,25052,26190,25051,26188,25050, +12633,25049,12628,25048,26338,25047,12682,25046,26280,25045,12771,26095, +26329,25111,12672,25228,25044,25043,25042,25041,25040,25039,25038,25037, +25270,25269,25980,25979,25036,25035,25034,25033,25032,25295,25294,25293, +25292,26167,26172,26166,26171,26165,26170,26164,26169,25309,25308,25307, +26176,26181,26175,26180,26174,26179,25031,25030,25029,25028,25027,25026, +25025,25024,25023,25022,25021,25020,25019,25018,25017,25016,25015,25014, +25013,25012,25011,25010,25009,25008,25238,25236,25264,25266,25543,25542, +25537,25539,26316,26327,26091,25226,26059,26061,26058,32176,38181,25804, +25806,25802,25801,26108,20020,26093,20015,25242,19468,26336,20349,26335, +20348,26334,20347,26332,20343,26323,20340,25391,25370,29835,25369,34970, +26099,31094,32126,31253,35415,38473,36287,38148,36286,36285,25935,27057, +25934,26098,25933,26374,25963,27671,27340,25960,25932,27255,27085,25931, +25959,27050,26097,25967,26186,26184,33117,33965,33116,28439,29173,33964, +29435,34082,33115,28438,33114,34081,26377,26419,25260,33911,33531,28780, +28785,33537,33915,25007,25006,25005,33469,33960,29416,34045,33300,28622, +33283,28616,29170,33957,33350,34056,26369,26402,25004,26005,25003,25341, +29168,33955,34022,33954,26394,26357,28189,22298,28165,28167,33113,33899, +33112,28437,29150,33898,28123,33901,33516,28767,28122,28121,25552,40394, +25551,25550,28436,28435,28641,29402,29401,34021,26373,34969,26372,25248, +19474,11313,19927,25892,12124,28434,28433,25826,25825,26224,25828,26930, +26924,25830,25824,26967,41117,19947,12165,25389,26063,26083,27025,21441, +27190,21629,27108,27071,27244,32175,38180,27074,27070,27069,27076,27059, +21496,27027,27670,27047,34611,35085,27135,27056,34968,27055,38179,35414, +38472,38147,38146,27084,27254,27083,27253,27052,27222,31101,36363,26296, +26288,26271,26287,26283,20247,26285,26264,26290,26273,26294,26277,26293, +26276,26292,26275,25344,28055,28057,27828,27726,27784,27403,27783,27402, +27715,29840,27669,29881,29192,42830,42130,43047,27769,42402,37788,43086, +42763,41134,27668,42752,41279,41836,28023,27667,27737,29834,27736,27904, +27496,27903,27495,38178,32174,28432,28862,29400,29399,29247,27982,27966, +27515,38471,32426,38145,32163,36284,31043,27984,36120,40793,28431,28430, +29046,29039,27762,35413,38470,27243,27242,27068,28429,28880,29398,27126, +27270,27100,26923,27010,27012,26951,26961,26969,26954,26922,26921,26920, +26919,26918,42210,42129,30264,27000,42552,37919,29189,28991,30289,26917, +42459,37899,26956,42401,37787,43142,26916,41838,27054,26915,26914,27261, +27093,27122,27137,27139,27143,26929,27252,27082,26987,26986,26985,26984, +26965,27045,42306,26262,26269,26268,25864,25862,19907,12099,25861,21133, +13558,26232,25284,21158,13589,36233,41002,41001,36232,25459,25467,25466, +25439,25438,25437,25463,25462,25478,25436,25435,25434,25433,25432,25431, +25430,25429,25448,26797,26913,25450,25428,26630,26868,25427,25455,19572, +11451,19575,25453,11454,25425,19564,11435,25422,25421,34547,36611,29498, +31483,40783,36087,27782,27902,27499,27501,27494,27493,27401,27721,27720, +27719,27519,27514,27513,27512,26737,26742,26739,26717,26716,26715,26714, +26713,26735,26734,26733,36534,41543,26558,22395,26507,22420,26675,22296, +26506,20726,26578,20695,26505,20577,20876,26654,30266,30082,29431,29354, +30295,30136,29007,29001,26504,26785,26503,26784,26502,26783,26501,26782, +26653,20576,26803,26818,26810,26781,26780,26779,26778,26777,26905,26776, +26775,26774,26773,26772,26814,27666,26771,27735,27975,27749,28027,28044, +28037,26796,26770,26831,21179,21176,13621,13619,26843,21132,13557,26822, +26821,26820,25684,19793,25679,19791,25660,19781,25659,26261,25658,32147, +25657,26231,25656,25655,25654,27734,25653,25682,27665,27767,25704,27766, +27664,25703,25707,25652,27718,20178,20182,19439,11301,19435,11297,19999, +12305,20245,12674,20249,12676,20253,12680,20252,12679,20251,12678,26247, +21597,21596,21595,21594,30157,35219,33813,29037,29457,34543,40385,40384, +40383,40625,19655,20477,20475,42960,43367,42673,42571,42959,43366,19653, +28426,33105,28425,33104,19651,28424,33103,41111,41110,41108,31886,28423, +28422,28421,28420,19639,11546,19644,11548,19622,19115,41179,41153,19536, +11398,21323,21148,37369,37702,31765,21152,21314,21131,37377,37709,31776, +21130,32245,21129,21313,21128,21312,21127,21311,21126,21401,21305,37295, +37560,31748,21304,21374,13912,20757,20756,13148,21373,21241,13693,20725, +20724,13127,21240,21372,13911,21371,19612,11504,28419,40382,40381,19823, +11892,39128,20755,39127,19822,19780,11781,25651,20723,25650,19779,19821, +11891,19820,19819,11890,11889,19818,41089,41088,19437,11299,19540,11402, +19531,11393,20034,12310,20037,12329,15739,22295,20036,12328,20290,12758, +20300,12769,20299,12768,20298,12767,32458,40797,41132,40630,41662,41707, +41690,41785,41661,41774,41660,41773,41700,41699,41795,41684,41688,41659, +41727,41811,41725,41657,28418,28417,20229,12982,20228,20575,20225,12655, +20222,12653,28416,26302,42400,37786,22294,15738,22293,15737,22292,15736, +22291,15735,22290,15734,22289,15733,22288,15732,22287,15731,34719,29772, +35227,30162,29728,34675,35140,30081,34689,29742,35134,30075,29774,34721, +35133,30074,35253,30198,35132,30073,28931,33671,35130,30071,22286,35177, +22285,22284,22353,22283,31910,29115,29113,31879,28415,28414,22438,15899, +22282,15730,22746,21563,37294,37559,31747,21562,22748,16285,22750,16288, +22415,15884,22281,15729,22280,15728,22392,15849,22463,15930,34658,29711, +35157,30100,29710,34657,35156,30099,22419,15889,31863,29036,29035,22651, +16133,22653,16140,22658,16151,19922,19920,19906,40380,19905,19904,41087, +41116,19968,12203,19966,12201,19946,12164,19945,12163,38940,25109,21310, +21125,20232,12661,20234,12663,20240,12667,20239,12666,20238,12665,20242, +12669,20305,12687,20304,12686,20303,12685,20307,12689,20176,12631,20175, +12630,20180,12635,32140,31127,32139,31126,32138,31125,32137,31124,20351, +20346,31463,31462,31456,31448,31447,31446,31445,31862,32146,31924,41972, +21504,21503,21578,21577,21576,21575,27661,21437,21457,21455,32173,21534, +21532,21530,27660,41713,41802,42860,42754,41724,41810,21525,14160,21523, +14158,21518,14134,21517,14133,21542,14214,22955,23406,23405,23404,23403, +22986,21686,14735,21651,14505,41289,41281,42958,43365,40371,40370,43076, +43441,21638,14457,21657,14512,21674,14605,21672,14603,21667,14579,21666, +14578,19579,11459,19601,11477,25419,25417,19561,35438,30308,41723,41809, +27202,27033,21034,27713,21008,27733,25368,21007,27659,21075,22411,15877, +34878,29879,41558,41577,40612,40614,41693,41787,22278,15727,34907,29889, +26560,26816,22277,15726,26551,26812,22394,15852,22364,15806,34804,29833, +26500,26769,22363,15805,21481,20207,22481,20203,20213,20206,20202,26499, +26768,20201,20270,12650,20269,41342,41338,41337,41341,40664,40663,41562, +41581,20573,12980,29751,34698,34655,29708,34696,29749,34653,29706,41610, +20570,20569,34533,35206,33784,20568,18102,20567,12979,42624,42623,23537, +23536,20566,12978,20565,12977,41086,41085,36592,12658,20564,41808,41374, +41353,41373,41352,41372,41351,41371,40369,40368,40367,40366,40365,40364, +42597,42570,42569,42627,20664,13056,20563,12976,20800,13184,20754,20753, +13147,20799,20842,13223,20722,20721,13126,20841,20798,13183,20797,20650, +13049,20562,12975,20561,12974,20560,12973,20559,12972,41979,31961,42023, +42061,41971,31968,41970,32451,41969,40363,20875,13250,31923,42060,26496, +26767,21448,14037,20720,13125,20719,13124,25860,25859,20718,20717,25966, +25556,20796,13182,20927,13282,20929,13284,20809,13192,20795,13181,20866, +13243,20840,13222,20852,13232,20839,13221,21150,21156,21136,21124,21123, +21122,21121,21120,21278,27658,21119,25367,27732,21118,28025,21138,21117, +13556,21116,13555,21115,13554,21114,13553,21263,21262,21261,25415,25413, +12352,14223,12821,14281,12823,14284,11140,14523,11132,16013,16393,16380, +14985,14869,16399,16386,15015,14892,11966,11104,10996,14459,11321,11539, +11466,10995,11332,11472,11534,10994,11346,16643,10993,16653,11530,11520, +11433,12281,12285,11348,11345,40140,39228,11990,14113,11989,15240,11988, +21492,20011,21491,20010,21490,20009,21489,20008,21488,20007,21512,20042, +34803,29832,23535,23699,24207,21511,20041,33102,11672,22276,35218,11555, +11551,41176,11366,35137,40362,33101,40361,40523,41542,21487,21370,35188, +33950,13910,33100,40360,40499,41541,21486,20006,35187,33949,11888,43364, +33099,43363,12766,42568,18668,12657,36591,33098,32353,11080,12046,12039, +12010,12036,12014,11189,11191,37683,42287,11099,11101,37864,42502,11089, +11091,11066,11068,11117,36201,40984,12614,42348,27657,22275,42347,37744, +12613,12600,42346,37743,12538,12537,33097,13266,23526,27656,22272,12536, +12510,15773,14398,15722,33962,15721,26417,15720,26663,40355,15797,15719, +15718,33946,33830,33433,15717,15716,15715,26691,16233,33096,33095,15713, +33094,37344,33868,37388,33875,20474,32309,33833,33437,33837,17996,33093, +33092,15709,15706,15921,40354,33812,23525,20040,15834,32487,32496,32776, +40353,40352,33091,33811,33810,33809,37293,33808,33807,33806,33805,32299, +32474,32388,33090,32352,17684,23524,27756,22461,27655,22255,17843,23772, +17841,23746,27728,22418,26585,20716,15700,15099,15888,26495,26494,20558, +27029,21447,27036,21462,16104,14669,17900,16103,12971,40351,31922,32450, +25572,19660,17683,23523,26493,20557,16102,15274,26492,20556,12088,12087, +12086,41166,23522,12131,12085,42128,12084,40627,35975,37785,42399,12082, +12113,12079,12078,12077,12076,42498,37860,12075,12074,42283,37679,12073, +12072,40974,36195,12071,12123,41772,41771,41770,41769,41782,36891,41799, +36967,41768,36859,41807,12968,41806,36986,41805,36985,41767,36858,41766, +12517,12514,37751,12606,37749,12604,11378,42546,37906,11431,11430,11429, +11446,11450,11428,11427,11426,21537,12242,20215,20189,20274,21113,20200, +20268,20272,22254,20265,20555,20264,20794,20263,20262,21369,20261,20260, +22253,20257,20715,20267,24168,23521,41348,40350,24206,41540,22356,21036, +22362,21005,21070,22252,21510,21004,21146,22251,21140,22330,21435,21317, +13366,18487,13365,15909,18447,15816,21112,22361,15804,18405,15803,13364, +14077,13363,13435,13809,13572,15699,13492,18554,15698,36471,36498,36547, +15137,14053,16177,14484,40139,39954,15239,14112,15238,14111,15697,15887, +15864,40711,21465,20752,15098,20937,15326,36469,20468,15273,14182,20554, +15272,16100,14326,14299,15021,14896,15013,14890,14961,14960,14959,14958, +14853,14768,14231,14499,14426,14030,14767,14665,14705,14195,14692,14187, +14663,14180,14730,14577,14729,14132,14728,12159,14727,14726,43440,43362, +18059,34607,17682,34605,18720,34602,34903,14772,14786,14269,15355,14267, +14784,16269,15351,16265,14868,14852,14851,14850,14849,14957,14889,25722, +33651,14576,14575,14574,26973,14573,35051,14572,26612,14571,34867,14570, +14569,14096,13552,23520,14062,23519,39795,23518,21316,22250,39531,20793, +14004,39655,14003,21368,14002,39833,14001,14000,13999,39126,19817,40119, +40138,14280,14283,14228,20553,21485,20792,21484,14237,33758,33757,39753, +14240,39752,33089,14247,34800,14246,33088,21111,21451,14222,14207,26584, +15097,16099,14131,25721,33650,14130,14129,14128,26972,14127,35050,14126, +26611,14125,34866,14124,14123,14052,12157,12155,12153,12182,12152,12151, +12150,26971,12149,35049,12148,26610,12147,34865,33649,25720,13454,12146, +16900,17343,16912,17380,16619,16568,23517,16689,16566,24234,16564,22248, +16724,24188,16723,33085,16729,33890,33084,24187,23516,33889,16728,33888, +34012,16559,23826,33515,41648,16558,17067,17181,16557,26220,18087,16720, +16810,16773,16772,20552,17681,16771,16556,18719,16956,16955,17537,17300, +17536,17299,17535,17534,17297,17295,17293,17292,17291,17290,17533,17388, +17377,12965,12964,13095,12963,41609,18172,34532,35205,33783,15477,15532, +17101,12962,32905,32193,32187,16767,12961,13055,41347,13067,12960,18502, +12959,12958,18545,12957,17199,14073,18441,14048,32032,31967,31921,21110, +21446,14036,18404,14035,17680,23511,18740,24471,13163,13660,26601,20777, +18115,24226,18015,24123,18781,24488,12956,13551,26652,20874,40347,13054, +13588,26487,20551,40346,40512,41539,33756,35186,33948,13180,19648,25562, +20465,26438,30161,30303,21450,27031,29353,29430,30135,30294,29000,29006, +21461,27035,36984,41804,12955,13550,37747,42357,12954,13549,40345,25560, +26486,13123,33952,13122,13121,25965,25559,15460,15514,17055,17772,23647, +17679,23510,18108,24205,18121,17678,18738,18114,18014,18780,12953,26651, +18061,18085,17677,18083,18718,18081,15279,16126,15095,15694,17676,17906, +18107,15149,15902,13263,15344,16259,15353,16267,15187,15955,15289,16156, +15127,15790,15093,15692,13548,13610,13596,23508,22329,23745,22417,15809, +34823,15691,34863,22242,24181,15690,15886,20714,13547,40796,35139,33827, +33803,15828,15687,41794,13546,42222,13545,13544,13587,16239,34799,16238, +33082,13543,13578,42408,37794,37816,42445,13657,42127,13656,13655,13654, +42398,37782,13764,42369,17675,42368,13763,42367,13761,17674,13760,15683, +13728,13727,13542,13541,13540,42497,13539,37859,13538,42282,13537,13536, +37678,13535,40973,36194,13534,15680,14206,14568,14122,13667,13586,20550, +13585,11809,11819,11779,11817,12121,11775,11797, 9551,34857,33081,33079, + 1870,10340, 1763,21210, 1607,32011, 1803,35041,30536,30534,19291,31901, +17673,29870,28404,28402, 1820,37989, 1577,29932, 1748,18661, 1887,13864, +35765,35763,10964,37629, 9549,34854,33077,33074, 1867,10337, 1760,21207, + 1604,32008, 1800,35038,30532,30529,19289,31898,17671,29867,28400,28397, + 1817,37986, 1574,29929, 1745,18658, 1884,13861,35761,35758,10962,37626, + 9546,33071,33068,33066,19054,18717,14385,19286,38275,38056,30331,33064, +30526,30524,19282,30522,17667,28391,28388,28386,32215,35749,35477,35586, +10674,17664,21625,22234,35746,35744,10957,35742, 9542,33055,33053,33050, +19051,18714,14382,19279,38272,38053,30328,33047,30516,30513,19277,30510, +17661,28384,28382,28379,32212,35739,35474,35583,10671,17657,21622,22231, +35737,35734,10955,35731,17797,34167,33045,33043,36731,34323,33345,31399, +18340,31381,19447,34342,35958,30508,19267,31584,17649,29534,33325,28371, +17808,36906,20409,29311,35939,29295,34185,36925,35717,35715,19461,36750, +17796,34166,33029,33027,36730,34322,33344,31398,18339,31380,19446,34341, +35957,30500,19259,31583,17641,29533,33324,28368,17807,36905,20408,29310, +35938,29294,34184,36924,35713,35711,19460,36749,43358,33025,33022,33020, + 7205,40213, 6413,24632, 7559,39912, 6227,33018,42727,30498,27180,30496, +24775,28366,40212,28363, 7556,35709, 6226,43355, 7202,27333, 6412,42724, +35706,35704,39911,35702,43361,33015,33058,33061, 7208,40209, 6409,24630, + 7562,39908, 6223,33013,42730,30519,27183,30493,24778,28361,40216,28394, + 7555,35699, 6230,43354, 7201,27332, 6416,42723,35755,35752,39915,35697, +17638,10331,34848,35032,30491, 1811,33011, 1568, 9531, 1739,19256, 1878, +35695,32002,21053,21201,18613,18652,33008,29923,17635, 1861,10944, 1754, +35692, 1598,28359, 1794,37620,37980,19253,13855,17632,34202,33647,33633, +36770,34359,33005,31436,18359,31419,19250,34375,35689,30992,19768,31615, +17920,29549,33004,28918,17631,36945,20439,29346,35688,29330,34219,36962, +36230,36193,19249,36789,17630,33377,33646,33632,36229,33003,30991,17919, +30769,19248,35687,19767,28655,28917,35994,36192,17889,10746,35613,35557, +30927, 8803,33565, 5749, 9746, 8073,19628, 8560,36125,32295,22558,21685, +18903,19091,33570,30376,17895, 8844,11544, 6969,36132, 6014,28802, 8448, +38196,38333,19633,14689,17888,10745,35612,35556,30926, 8802,33564, 5748, + 9745, 8072,19627, 8559,36124,32294,22557,21684,18902,19090,33569,30375, +17894, 8843,11543, 6968,36131, 6013,28801, 8447,38195,38332,19632,14688, +17887,17628,35611,35555,30925,30488,33563,33001, 9744, 9528,19626,19246, +36123,35685,22556,21683,18901,19089,33568,32999,17893,17626,11542,10941, +36130,35683,28800,28356,38194,38331,19631,19244,39563,10143,34967,34798, +30660,42077,33233,26992,33856,42320,31186,31181,39684,31861,24419,21003, +26998,18587,42331,29831,29068,29085,36449,39689,35890,24423,28540,39559, +37950,37553,42072,13360,33862,18638,33197,33201,35065,37723,32038,34797, +31175,18619,33846,21002,30630,37949,31192,19345,29074,17746,28509,34966, +36467,18586,29079,21066,29936,37552,38021,34889,35855,35859,36462,21109, +33210,18637,33451,33444,35020,37608,31979,34796,30643,18604,33205,21001, +30835,37948,30639,19516,28522,17835,28711,34965,35868,18585,28517,21046, +29911,37551,37970,34832,36049,36060,35864,21108,18010,35175,33221,33215, +31081,18584,33736,21859,37947,37550,29904,35353,36327,30648,19351,32120, +17752,30423,33747,28527,31920,38450,34964,34795,36337,18946,28984,21000, +35874,35879,19988,38641,17823,18358,28697,29563,30809,31435,33401,34358, +38685,38468,31614,31418,36017,36769,11343,12750, 9663,10013,33421,34218, +32162,32425,36788,36944,36033,36961,28685,29329,30799,31601,19492,20438, +17822,18357,28696,29562,30808,31434,33400,34357,38467,38684,31613,31417, +36016,36768,11342,12749, 9662,10012,33420,34217,32424,32161,36787,36943, +36032,36960,28684,29328,30798,31600,19491,20437,17821,18356,33685,33684, +30807,31433,33399,34356,36258,36257,31612,31416,36015,36767,19976,19975, +17962,17961,33419,34216,31042,31041,36786,36942,36031,36959,28683,29327, +36265,36264,19490,20436,10003,34321,34165,34340,17795,32160,11309,35238, +35956,35937,28636,34183,31582,38466,20424,31397,18329,29293,29532,35383, +30747,36729,33323,33343, 9657,38683,19459,30427,36748,36904,12740,36923, +10002,34320,34164,34339,17794,32423,11308,35382,35955,35936,28635,34182, +31581,38682,20423,31396,18328,29292,29531,35237,30746,36728,33322,33342, + 9656,38465,19458,30305,36747,36903,12739,36922,33683,34319,34163,34338, +17793,31040,19974,33715,35954,35935,33682,34181,31580,36256,31048,31395, +28956,29291,29530,33714,36263,36727,33321,33341,17960,36255,19457,28928, +36746,36902,36262,36921,43340,17624,32997,32995, 7188,40208, 6408,32993, + 7542,39907, 6222,24772,42710,35681,27167,19242,24766,17621,40196,32990, + 7554,27177, 6210,43353, 7200,35678, 6396,42722,35675,35673,39895,19240, +34525,23507,32987, 7309,32975, 7308,24977,23337,17054,17288,23183,40340, +24975,23336,17053,17287,23182,40338,40336,23181,17052,24973,23335,17286, +38810,32821,40605,39392,25222,38772,40603,39389,25224,32726,38771,32725, +40601,40599,23180,39383,17051,39386,25220,25218,23334,24199,17285,24192, +25279,25281,38770,38769,38961,32820,32724,32723,38959,38809,40652,40654, +38955,38957,41224,17050,25995,23333,41226,23179,25993,17284,23681,23679, +32973,39048,40641,13960,23505,13952,23503,13969,23500,23498,39722,23496, +39746,23493,39745,40067,31682,40070,31685,40072,31687,40066,31681,40065, +31680,40055,31673,39721, 9923,39744, 9934,39743, 9933,16510,32971, 2826, +28343, 2824,40334,40332,40331,40329,40327,40325,40323,40321, 6294,22565, +16042, 6271,22626,16092, 4266,22625,16091,10919,19223, 6624,10911,24964, + 7087,19217,24960, 5724, 2709, 3037, 3181, 4265,22622,16089, 4298,22620, +16087, 7349,21949,15271, 7347,21947,15269, 7345,21945,15267, 3206, 5752, +10899,17800,34171,33121,33125,36735,34327,33348,31403,18344,31385,19450, +34346,35961,30552,19305,31588,17694,29538,33328,28443,17811,36910,20413, +29315,35942,29299,34189,36929,35807,35803,19464,36754,17799,34170,33120, +33124,36734,34326,33347,31402,18343,31384,19449,34345,35960,30551,19304, +31587,17693,29537,33327,28442,17810,36909,20412,29314,35941,29298,34188, +36928,35806,35802,19463,36753,18636,34169,33119,33123,36733,34325,34794, +31401,18342,31383,20999,34344,37946,30550,19303,31586,17692,29536,34963, +28441,18583,36908,20411,29313,37549,29297,34187,36927,35805,35801,21107, +36752,34520,23692,17727,34206,33644,33630,36773,34362,33170,31439,18362, +31423,19328,34379,35834,30989,19765,31619,17917,29553,33166,28915,17723, +36949,20442,29350,35830,29333,34222,36965,36227,36190,19324,36793,17726, +34205,33423,33403,37945,34793,33169,31860,18635,31422,19327,34378,35833, +30811,19494,31618,17825,29552,33165,28687,17722,36948,21106,29349,35829, +29830,34962,37548,36019,36035,19323,36792,17725,34204,34961,34792,36772, +34361,33168,31438,18361,31421,19326,34377,35832,31859,21105,31617,18634, +29551,33164,29829,17721,36947,20441,29348,35828,29332,34221,36964,37944, +37547,19322,36791,17719,33381,33643,33629,36226,33162,30988,17916,30773, +19320,35826,19764,28659,28914,35998,36189,17718,33380,33494,33506,37943, +34791,33161,31858,18633,30772,19319,33379,35825,30915,19588,30771,17875, +28658,33160,28758,17717,35997,21104,28657,35824,29828,34960,37546,36106, +36096,19318,35996,34201,17619,33398,33418,34790,37942,31857,32969,31415, +18632,34374,19209,30806,35662,31611,19489,29548,17820,28682,32964,36941, +17615,29345,21103,29827,35647,37538,34959,36030,36014,36785,19204,38965, +38827,38964,38402,38963,38394,30483,30481,30479,30197,30173,30172,37558, +37533,33232,26991,33855,42319,26997,31853,42071,34785,30663,10141,42330, +20996,31185,37937,30659,42076,28539,39558,29067,34954,39683,18580,28536, +13358,39562,37532,24418,29823,36448,39688,35889,24422,37708,37640,36827, +41765,29940,37091,37531,38132,37530,29954,29939,29952,29938,18047,17687, +18179,17690,37648,36442,36300,26727,26710,26725,26709,36053,36296,36454, + 8812, 5812, 8435, 8792, 4905,43814,43311,43002,43286,42582,42845,42928, +42841,17738,17994,17736,17882,37784,37852,36298,36308,42834,26708,42866, +42924,42836,41896, 4061, 5984, 5996, 3392, 6655, 3665, 5991, 2355,11822, +11824,12297,12293,41271,41244, 9823, 9825,28555,30678,23629,25170,28972, +31072,24113,26051,28716,30818,23740,25326,28544,30669,23602,25142, 9678, + 9673,12176,11804, 6292,22567,16044,14145,14590, 2539, 5657,14143,14588, +14164,14610, 2549, 5675, 1621, 5475, 1922, 5500, 3097, 5374, 5384, 3103, + 1927, 5218, 5216, 1912, 5230, 1907, 5228, 1909, 1924, 5240, 1920, 5242, + 5251, 1915,16600,16633,10970,11111,10966,11285,11116,12195,12208,11050, +24332,28819,28826,30947,37995,11048,37653,24461,38605,24787,38432,11046, +28807,30934,11044,43887,43853,43884,43850,43879,43845,43876,43842,14147, +14592,11113,12199,17610,19104,17607,19103,35640,28333, 8578, 8135, 4818, + 4785, 8230, 8669, 8667, 8228, 8584, 8161, 8176, 8596, 8576, 8133, 6923, + 6164,36294, 8790,36293, 6921, 6162, 6901, 6157, 4816, 4783, 8178, 8598, + 6925, 6166, 8586, 8163, 6903, 6159,24751,12788,39418,38649,38634,36069, +38630,37529,39997,39585,40148,40037,40013,40113,39995,39678,40109,39587, +39677,39544,39583,40111,39582,38677,35816,35815,38676,38692,38648,32845, +30554,32330,30665,31742,31199,32322,32317,10868,10865,28325,28322,28318, +28315,18253,11572,11569,37502,37165,35655,35652,35793,36302,36292,18631, +34162,32968,32963,36726,34318,34789,31394,18338,31379,20998,34337,37941, +30485,19208,31579,17614,29529,34958,28341,18582,36901,20407,29309,37537, +29290,34180,36920,35646,35661,21102,36745,18630,18355,32967,32962,31856, +31432,34788,34355,34200,34373,31610,31414,37940,36766,19207,19203,17613, +17618,34957,34215,29547,29344,36784,36940,37536,36958,29826,29326,35645, +35660,21101,20435,18629,17873,32966,32961,31855,30913,34787,33504,33376, +33375,30768,30767,37939,36104,19206,19202,17612,17617,34956,33492,28654, +28653,35993,35992,37535,36094,29825,28756,35644,35659,21100,19586,35799, + 9353, 9466, 9351, 8511, 8467, 9356, 9355,38382,28878,28873,28860,28855, +36282,36277,35797,18255,27821, 2597,18244,18243, 2456, 2596,18258,20185, +18251,18250,18248, 2639,37181,37178,37131,37164,37190,37163,37162,37161, + 2628, 2484,37160,37130,37159,37189,37158,37107,35671,28353,30196,28348, +30171,28352,28351,30211,28330,32980,32985,32978,32983,28346,28350,28329, +32887,32733,36647,36641,39425,39436,39434,17467,17466,17465,11252,11231, +11249,11228,28577,30701,28571,30695,17464,36512,36527,32681,33885, 2803, +29143, 2801,33883, 2815,29141, 2814,17283,36510,23099, 8940,16953, 8939, +24190,24197,17374,36514,23332, 9222,17282, 9221,24186,24195,16899,36509, +17342,36508,16716,36507,23331, 9220,17281, 9219,23513,23515,16898,35774, +16770,35773,35812,32912, 9413, 9412,38826,38825,32843,32842,36520,32749, +36525,32722,36524,32765, 9315, 9314,38768,38767,32721,32720,36523,32902, +36522,32643,11922,11919,17550,32854,17500,32826,17196,32891,17326,32918, +14566,13036,13033,13045, 9827,20640,20632, 5980,21627, 6232,20630, 4294, +28502,30618, 3072, 3390, 3308, 3501, 3294, 3479, 3296, 3485, 3291, 3474, +24393,42188,24390,42185,10400,38621,10397,38618,38600,37957,38597,37954, + 3369, 3053, 2347, 2474, 2341, 2468, 3497, 3306, 3387, 3070, 3372, 3056, + 3462, 3288, 3460, 3286, 3367, 3051, 6898, 5577, 6896, 5575, 6912, 5608, + 3262,38172,27114, 3033,38221,27106, 3031, 2490,38144,27081, 2488, 9523, +38143,27080, 9895, 3361, 3413, 3411, 2340, 2338,19193,20045, 3436,16188, + 7760,16186,16190,16166, 7755,27548, 7979,27546, 7977,27554, 7985,27371, + 7905,27369, 7903,10218,34894,29094,29104,23572,40849,33705,33700, 5477, + 3365, 5504, 2343, 5409, 3495, 5442, 3385, 5436, 3375, 5376, 3454, 5430, + 3363, 5327, 2345, 5283, 2367,32622,30556,30756,31026,32607,30558,30783, +30872,30884, 6085, 1558, 5512, 1532, 5502, 1551, 6098, 1541,16642,32605, +32620,16677,16631,16675,14167,14613,10974,10972, 5387, 3106,12007,12006, +19884,19883,27888,27479,25821,25820,22532,21907,15995,15226,13355,13354, +20992,20991,27887,27478,16175,22682, 3640,22681, 3639,28006, 3745,36150, +14722,16168,31028,14779,14262, 5486, 3092,14788,14271, 5514, 2300,14739, +14218, 5444, 3337, 3130, 5407,14202,14718, 3108, 5389,14190,14695, 3105, + 5386,14188,14693,14733,14211, 5433, 3328, 3090, 5367,14184,14674, 2302, + 5285,14115,14519, 2320, 5325,14137,14582,10976,10978, 2315, 5308,14118, +14556,12287,16679,12187,12185,12167,12213,12211,12145,12210,12220,12171, +12005,19882,25918,25819,19938,12144,13353,20990,25795,12218,12143,11787, +16647,11802,11800,11791,11789,12169,12012,11287,12142,12004,11785,11783, +32625,32624,16645,11772,16644,11535,11333,11771,11770,11769,11768,37781, +39432,42704,17745,19044,28513,30325,30629,32526,33196,35580,33861,33845, +31191,31174,35858,38269,11123,14378, 9612,10668,33200,35471,29073,29078, +36461,36466,35854,38050,28508,30067,30634,32209,19344,21619,17744,37488, +28512,29885,30628,32037,33195,35064,33860,33844,31190,37929,35857,37722, +11122,29816, 9611,31846,33199,34888,29072,34947,36460,36465,35853,38020, +28507,29935,30633,31908,19343,34770,42124,18618,28511,29884,30627,39579, +33194,35063,33859,39542,31189,31173,41965,37721,26764,13467,24372,10194, +39541,34887,29071,29077,36459,41964,35852,38019,28506,42123,30632,31907, +39578,21065,35579,33450,33204,33209,10667, 9684,21618,19515,32208,30827, +35470,33443,30642,30638,32525,30834,30066,28710,28516,28521,38268,36059, +30324,28721,19043,17834,14377,11391,35867,35863,38049,36048,35019,33449, +33203,33208,31845, 9683,34769,19514,31883,30826,34831,33442,37928,30637, +31978,30833,29910,28709,34946,28520,37607,36058,29852,28720,37487,17833, +29815,11390,35866,35862,37969,36047,35018,33448,39540,33207,10162,24371, +21045,39577,31882,30825,34830,39539,30641,30636,39576,30832,42122,28708, +28515,28519,37606,41963,29851,28719,18603,42121,13429,26763,41962,35861, +37968,36046,18009,35174,33220,33214,31080,10542,33735,21858, 9872,32383, +19996,35352,36326,30647,19350,32119,17751,30422,33746,28526,18003,38449, +12303,30287,36336,18945,28983,15177,35873,35878,19987,38640,18008,35578, +33219,33213,31079,10666,33734,21857, 9871,32382,19995,35469,36325,30646, +19349,32524,17750,30421,33745,28525,18002,38448,12302,30323,36335,19042, +28982,15176,35872,35877,19986,38639,18007,35173,33218,39538,31078,10541, +39575,21856,24379,32381,39537,35351,36324,30645,19348,39574,17749,42120, +33744,28524,41961,38447,26910,30286,42119,18944,28981,15175,35871,41960, +19985,38638,18006,35172,33217,33212,31077,31844,33733,34768, 9870,32380, +19994,35350,36323,37927,19347,32118,17748,30420,33743,34945,18001,38446, +12301,30285,36334,37486,28980,29814,35870,35876,19984,38637,35881,43188, +19019,43115,19000,43043,18937,42904,19125,40860,41464,40864,41531,40856, +41497,27449,27858,26485,26484,18893,35399,18905,18871,36637, 8640,43490, + 8638, 8636, 8632,43488, 8630,27913, 6309,27643, 6199,27650, 6201,27648, +27317,15071,21781,27319,36291,30114,30113,18035,18034,18843,27630, 6194, +27198,26411,27628,27627,27626,17953,18752,18873,18877, 6850,14325,14323, +13562,27200,27195,26544,26498,35410,18842,18840, 7945, 4605,36290,29959, +29958,18839,26754,26753,18838,30779,28661,28542,28311,32951,38593,37485, +26198,38808,32719,26208,26206,26210,28413,12590,18544,11602,18501,10103, +18493,11601,18500, 7875, 7873,27185,26532,26483,27409,27411,26491,27792, +26530,26719,26489,26712,12815,27808,26482,27790,27795,27794,26070,27380, +30341,10472,28732,29134,29567,29569,30349,30351,29019,29021,27745,26481, +26480,25346,25339,25355,38807,32718,26068,26073,25349,25351,25348, 2714, +26479,25856,26478,25855,26477,25854,26067,26078,32125,19191,26065,26076, +26476,26475,26072,26080,26131,26136,32145,10040,37484,37483, 4063, 5977, +22224,15675,18722,38647,38592,36537,38591,26410,26474,26473,26416,26683, +27293,27228,26245,26662,35635,28328,28327,43141, 8634, 3698, 3417,43138, + 8621, 3713, 3441, 4213, 6544, 4218, 6524,40309,21826,15119,24933,20136, +12548,31819,24935,29131,37427,37426,37408,38126,37407,24931,24929,17280, +35772,17341,35771, 8954, 8953, 8972, 8971,32782,38780,32780, 9335,38778, + 9333,35811,32911,35810,32910,35809,32909, 9436, 9435, 9450, 9449, 8407, + 8256,38629, 8415, 8264, 8255, 8406, 8263, 8414,35185,30123,35217,30156, +35214,30153,35789,40137,14174,32950,32949,32948,32953,35923,39167,35925, +38697,30195,42782,38646,27407,27788,27787, 8189,35791,12362,12359,11671, +11668, 8208,38343, 8206,38341, 8147,38291, 8145,38289, 8143,38287,10851, +27142,10850,27121,10849,27044, 6334, 1523,11177,11175,15347,23665,25199, +23667,25201,41325,41317,41322,41314,12358,23576,40851,37545,38125,37544, +37543,37541,41764,40304,28309,28308,28307,43105,18991,28306,28304,28884, +35642,42567,41159, 9349,33613, 2854,28895, 2849,33611, 2852,28893, 2847, +13527,26472,11550,36307, 9348,13526,18492,33879,41480,33867,41510,41496, +41445,41530,41535,43810,43282,43307,37913,41501,41463,13758,43028,41495, +43007,41529,12582,18534,26682,12589,18543,33877,41478,33870,41514, 4208, + 6553, 4263,22580,16060,11642,19693, 6603,11623,25597, 7060,19674,25585, + 5684, 2676, 3005, 3140, 4055, 5988, 4207, 6550,20547, 5987,19189,20546, + 9831,13525,20545, 9723,40302,40300,40298,38633,31123,25354,25357,40313, +40315,40312,40311,19187, 2935, 2932, 2975, 2972, 2931, 2389, 2392, 2388, +38391,12812,38367,38390,38360,10845,23489, 9521,23488,23541,23486,10861, +35182,30120,10858,12326,35220,30158,12323, 3320, 3318, 3083, 2317,41305, +27826,27824,27810,30339,28303,30476,21529,28302,30475,21527,28301,30474, +35418,30472,24979,41370,28299,40542,28298,40374,28297,41301,28504,41303, +28296,40378,28295,40389, 9517,22223, 9515,22222,28294,30471,15673,28293, +30470,26087,23485,26085,23484,26089,23634,26143,23482,28291,30468,35840, +25163,24068,33717,30467,33713,31149,36306,36274,36305,33668,36280,36279, +33666,41175,33726,30753, 8805, 9754,35271,35600,11567,11566, 8646,35602, +11561, 8644,40541,43812,40373,43309,40377,40376,43284,40388, 5853,40387, +35409,30466, 8193,35407,30465, 8192,35381,30464, 8184,35379,30463,35570, +30461,43352,28290,30460,27624,28289,30459,28287,30457,39372,30625,39369, +30622,38899,31715,39351,30456,39349,30978,39353,31089,29622,31709,38885, +31720,38884,30455, 8191,38882,30961,39786,30454,31739,35838,35795, 9519, +24942,24946,10856,10860,36345,36353,36344,36355,36343,36351,27406,35181, +30119,35281,30226, 8360, 8356, 8330, 8358,39348,32112,36349,36348,36347, +35184,30122,28764,41298,25054,40688,35240,30453, 8794,35249,30966,28852, +35594,28858,28857,35592,35385,30452, 4903,35397,30969,11554,35412,30451, +24989,41350,37156,36374,38124,38073,32589,11073,42118,18242,16618,38061, +11079,42117,17959,36254,33491,33503,36103,33681,30912,17872,30766,19973, +36261,19585,31039,28755,35991,36093,33703,33698,37155,38123,36373,18241, +37154, 9818,20884,14498,26409,27227,26106,41758,37129,18218,12026,42159, +18240,12035,42116,35785,38881,32098,33691,33693,33689,22218,12043,13218, +10294,10292,12028,30542,30450,30538,30449,31151,30448,31161,30447,31163, +31165,10883,22217, 5329,42155,42974, 8736,42153, 4951,41300,31460,30446, +31458,30544,31450,30445,30548,30444,30546,30443,30850,30442,31129,30441, +31171,30440,31177,31167,35657,35781, 5119, 5121,43484,18837,42822,32959, +28339,32957,28337,10890,10889,35180,30118,10888,35116,30009,32955,28335, +32956,28336,10886,32142,30439,32107,30438,33826,29060,33828,29062,30848, +31159,32105,31158,18239,12112,42115,40294,22797,16335,11611,19666,23481, +11704,19724,23480,11710,19727,23478,11634,19685,23477,11722,19733,23476, +40292,21574,14298,14322,21593,40290,11726,19737,23475,11202,19384,23474, +11677,19713,23473,11674,11673,19710,23534,11205,19387,23472,11208,19390, +23471,11353,19502,23470,11011,19312,23469,11649,19700,23468,12449,20095, +23467,11007,19309,23466,11630,19681,23465,12445,20092,23464,16116,10909, +19216, 6507,10843,19185, 7796, 5508, 1553, 6102, 1544,11201,19383, 7799, +10841,19183, 6769,10917,10916,19222, 6757, 1919, 5507, 5506, 2337,11200, +19382, 7798, 3099, 5379, 5378, 3456,11204,19386, 7743, 3078, 5354,14173, +14650,11010,19311, 6602,10930,19231, 7795,10927,10929,19230, 7724,10926, +19228, 7741, 5302, 2336,11207,19389, 7616,10838,19181,41258,11641,19692, +41257,10836,19179,41256,16649,22930,25272,11033,19314,25535,11323,19482, +25545,11004,19307,25874,11315,19476,25895,12442,20090,25866,11468,19595, +25469,11456,19577,25457,32610,32609,16651,22932,25274,30785,30886,11537, +11335,11325,19484,25547,25471,19597,11470,16682,12289,16681,25058,22939, +16691,12141,11331,16598,30781,11329,11767,11766,11320,19480,25541,12003, +12140,11319,19479,41255,17819,18627,28695,29901,30805,31851,33397,34784, +34199,34372,31609,31413,36013,37935,11341,13776, 9661,10272,33417,34953, +29546,29343,36783,36939,36029,37525,28681,29821,30797,31919,19488,21087, +17818,18651,28694,29922,30804,31892,33396,34847,34198,34371,31608,31412, +36012,37979,11340,13854, 9660,10330,33416,35031,29545,29342,36782,36938, +36028,37619,28680,29861,30796,32001,19487,21199,35953,18354,28693,29561, +30803,31431,33395,34354,34197,34370,35934,31411,36011,36765,28634,12748, +30745,10011,33415,34214,33340,29341,36781,36937,36027,36957,28679,29325, +30795,31599,33320,20434,35951,18353,28692,29560,30802,31430,33394,34353, +34196,34369,35932,31410,36010,36764,28632,12747,30743,10010,33414,34213, +33338,29340,36780,36936,36026,36956,28678,29324,30794,31598,33318,20433, +18163,34524,18170,34539,38973,41703,29442,14761,14765,14758,14451,13068, +10317,20704,13105,42224,24299,30412,43809,43281,43306,38235,27349, 7889, +14291,14320,14307,14275,27292,32314,26432, 8142,38286, 8205,38340,32311, +26426,27542, 7973,24301,30414,29621,31708,38245, 2898,34620, 3233,38243, + 2890,34618, 3225,38241, 2909,34616, 3245, 2476, 2353,29613,31699,38239, + 2333,34614, 2311,38232, 2959,32947, 2997,38230, 2957,33238, 2995,32946, + 2920, 3256,38218,33236, 2918, 3254,38216,32945, 2913, 3249,38211,33141, + 2911, 3247,38209, 3284, 3458,28841,30957,38225, 2952,33595, 2990,32944, + 2906, 3242,38205,33111, 2889, 3224,38171,26471,33619, 2904, 3240,38203, +33617, 2902, 3238,38201,33615, 2900, 3236,38199, 9347,33603, 2896, 3231, +38189,33601, 2888, 3223,38170,33599, 2908, 3244,38207,40288, 5473,19177, + 6077,19175, 6083,40286, 5510,20671,42202,28668,40774,28870,35518,28876, +28875,35516, 3026, 2497,12321,35396,30968,43080, 8776,42253, 4974, 9563, +35780, 9562,35779, 9561,35778, 9560,35777,35621,35776,43187,43525,33087, +28410, 8381,40344, 6063,40349, 5471, 8656, 8665,35769,35619,43193,43529, +24924,24922,19170, 6052,40280, 5460,19169, 6094,40279, 5498,40284, 6048, +40278, 5456,35768, 9554,35767, 9553,42816,42903,33083,28406, 8214, 8219, +42821,42908,35276,30221,10834,40283, 5465,19173, 6057,40282, 5484,19172, + 6072, 4604,35480, 8688,38151, 7004,35486, 8696,38161, 7021,35484, 8694, +38154, 7019,11715,11706,15672,11667,11713,11702,15669,11664,11699,11717, +11708, 5397, 3116,14777,14260, 5481, 3113, 5447, 3389,14741,14220, 5446, + 3339, 5412, 3500, 3132, 5411,14204,14721, 7329,21927,15249, 5494, 2352, + 5372, 3448, 3101, 5382,14186,14691, 2327, 5344,14162,14608, 3077, 5353, +14172,14646,11648,19699, 6601,35482, 8692,38166, 7017, 5392, 3473, 3110, + 5391,14192,14699,23463,43692,43694,24920,38951,22867,16482,33249,28118, +16479,28586,28115,22864,30710,35901,40584,16114,11661,23661,38948,22861, +16476,43690,33246,28112,16473,43689,28583,28109,22858,30707,35898,40581, +25195,23462,43789,43767,24919,23461,43688,43686,24918,16464,28568,30692, +28588,33251,30712,24853,35903,24812,28590,33253,30714,24855,35905,24814, +28576,30700,28575,30699,28574,30698,28594,30718,28593,30717,28592,30716, +23460,26117,23459,26125,25062,24917,25064,24916,23615,26119,23618,26127, +24915,25159,24914,25161,23458,25068,23457,25070,25378,24913,25384,24912, +23580,24911,23578,24910,25380,25086,25386,25084,23456,23455,43698,43696, +43702,43700,24909,24908,23454,28127,23453,28131,28125,24907,28129,24906, +23452,25073,23451,25076,27214,24905,27040,24904,23584,24903,23582,24902, +27216,25090,27042,25088, 9897,23617,27212,23825,27038,23807,25508,25507, +25485,25484,38076,32635,24060,43752,24059,43747,43751,25989,43746,25988, +16663,38064,23708,23707,28163,28162,28160,28159,25277,25276,33688,11488, +11501,33695,11465,19593,41254,23833,23813,24901,25514,24900,25491,25516, +25493,23824,23806,25376,25506,25382,25483,25505,25482,23840,23819,25258, +25524,25255,25501,25521,25498,16662,40650,40648,12139,16661,17475,16660, +17494,16708,32634,16655,11765,16654,16668,16665,17463,25268,22928,16640, +16658,12002,16657,41253,22927,16639,27274,27104, 8615, 2949, 8724, 2967, +24899,24898, 5711, 3168,27087,27257,39591,39593,39778,39780,24897,24896, +25305,41442,41415,24895,24981,41405,41436,24894,40670,21283,13733,25304, +20144,12556,40669,23178,17049,25303,23330,17279,40668,22082,15459,25302, +21736,14943,40667,22103,15510,25301,21714,14841,31816,38978,12457,20101, +23723,12456,20100,23722,12455,20099,25853,25930,41147,41165,24893,25153, +25151,41527,41493,41518,41484,24892,24891,24985,24983,41512,41476,41523, +41489,24890,24889,29127,37418,38081,38944,38942,25926,25928,41143,41145, +41161,41163,24888,24887,25157,24316,25155,24308,26445,24886,26435,24885, +31153,30573, 8606,27241, 8708,27067,24884,11397,24883,19535, 5633,40721, + 8611,27268, 8716,27098,24882,13815,24881,21327,27278,27119,15862, 8485, +22401, 8532,24880,24879,27266,27096,13813, 5014,21325, 5150,24878,24877, +24305,25080,24314,25078,24876,26430,24875,26443,38381,12808,38372, 9614, +33240,28553,30852,30588,23810,25510,23829,25487,24874,25489,24873,25512, +28730,32109,30590, 8604,27239, 8706,27065,25072,11400,25075,19538,23818, +25523,23839,25500,25257,25497,25254,25520,25114,41379,26145,23677,25211, +24077,36418,36416,36452,21509,20039,35274,30219,12320,35212,30151,33801, +29031,33802,29032,12319,12317,12316,12325,33814,29038,29030,31148,29029, +31147,33804,29034,31169,31146,33818,29042,23805,25504,23823,25481,26115, +25480,26123,25503,25094,40694,30575,35818,25066,41355,14455,13070,10319, +20706,13107,42226,34316,10000,34335,34160,17805,17791,20405,11306,35931, +35950,34178,28631,31377,31577,31392,20421,29288,18326,29307,29527,36724, +30742,33337,33317,18336, 9654,19444,19455,36899,36743,36918,12737,34315, + 9999,34334,34159,17804,17790,20404,11305,35930,35949,34177,28630,31376, +31576,31391,20420,29287,18325,29306,29526,36723,30741,33336,33316,18335, + 9653,19443,19454,36898,36742,36917,12736,34314, 9998,34333,34158,34388, +36806,31455,29578,35929,35948,34387,28629,31375,31575,31644,20419,29577, +18324,29305,29525,36980,30740,33335,33315,29358,31643,36979,34229,36897, +36741,36916,12735,34530,23691,34519,23690,34518,23689,37417,37349,37500, +37481,37567,37337,37555,33628,33624,33374,33373, 9760, 9764,19763,19759, +31002,30998,33638,33642,30765,30764,30983,30987,28913,28909,28652,28651, +36225,36221,28904,28900,17915,17911,11887,11883,35990,35989,36188,36184, +34783,33502,33372,33371,10271, 9735,21086,19584,31918,30877,34952,33490, +30763,30762,31850,30911,29820,28754,28650,28649,37934,36102,29900,28792, +18626,17871,13775,11515,35988,35987,37524,36092,34846,33501,33370,33369, +10329, 9734,21198,19583,32000,30876,35030,33489,30761,30760,31891,30910, +29860,28753,28648,28647,37978,36101,29921,28791,18650,17870,13853,11514, +35986,35985,37618,36091,33500,33499,38464,38679, 9733, 9732,19582,19581, +30875,30874,33488,33487,30759,30758,30909,30908,28752,28751,32408,32159, +36100,36099,28790,28789,17869,17868,11513,11512,35984,35983,36090,36089, +20673,42204,28671,40777,43082, 8778,35236,31145,42255, 4976,12467,15666, +12584,18536,15665,18529,11600,18499,43684,43683,43682,43681,41521,41506, +41487,41472,28106,28105,41520,41486,41505,41471,28104,28103,12588,18542, +35566,30397,17734,29615,31701,29620,31707,11594,11580,11593,11592,13438, +40317,40319, 2675,11660,19708,41252, 6693,40409,12569,20157,40408,40672, +12563,20151,40276,40403,40406,12618,42353,20165,42669,40402,40405,40550, +40548,12621,42356,20168,42672,40274,40272,40554,40552,35279,30224,34631, +29684,40270,43213,40268,43541,40400,40397,24303,34628,29681,40399,43210, +40396,43538,32283,11690, 3331,32281,11697,11696,11695,11694,19722, 2733, +11692,19720, 2731, 6695, 6692,34708,29761,20865,13242,11180,11183,11179, +11182, 2831,15192,39417,31625,18280,19041,29473,30322,31309,32523,34248, +35577,34246,34106,31307,31515,36671,38267,12696,14376, 9964,10665,34104, +35468,29216,29471,36826,36669,36824,38048,29214,30065,31513,32207,20360, +21617,18318,37584,29511,29813,31361,31913,34295,34944,34300,34148,31356, +37965,36713,37480,12727,29846, 9992,31873,34152,34767,29271,34991,36876, +36717,36881,37926,29266,29895,31557,31843,20395,34820,42168,18576,29518, +29812,31369,39620,34308,34943,34307,39550,31368,31564,42011,37479,26800, +13352,24374,10138,39549,34766,29279,29517,36889,42010,36888,37925,29278, +42167,31563,31842,39619,20989,18315,18575,34990,34819,31355,31912,34299, +34942,34294,34151,31360,31556,36716,37478,21142,21022,18640,18594,34147, +34765,29265,29510,36880,36712,36875,37924,29270,29894,37964,37583,20398, +20988,39536,10155,34989,34818,31354,41959,34298,26909,34293,42114,31359, +31555,39573,31872,24378,21021,26908,18593,42113,29845,29264,29509,36879, +39572,36874,24377,29269,39535,37963,37582,41958,13391,39547,10137,34941, +34764,31365,42007,34304,26936,34303,42164,31364,31560,39617,31841,24384, +20987,26935,18574,42163,29811,29275,29514,36885,39616,36884,24383,29274, +39546,37923,37477,42006,13351,38766,32717,41738,39446,26352,38806,41818, +39493,26389,32819,38805,32818,38804,32817,41744,39452,26362,38765,41826, +39501,26397,32716,38764,32715,41740,41820,23329,39495,17278,39448,26391, +26354,23177,24271,17048,24282,41746,41828,23176,39503,17047,39454,26399, +26364,23328,24276,17277,24285,24278,26367,18312,19039,29506,30320,31351, +32521,34285,35575,34290,34140,31346,31552,36705,38265,12724,14374, 9989, +10663,34144,35466,29261,29502,36866,36709,36871,38046,29256,30063,31548, +32205,20392,21615,18311,37476,29505,29843,31350,31955,34284,34987,34289, +34139,31345,37922,36704,37580,12723,29810, 9988,31840,34143,34816,29260, +34940,36865,36708,36870,37961,29255,29907,31547,31870,20391,34763,42112, +18591,29504,29842,31349,39571,34283,34986,34288,39534,31344,31551,41957, +37579,26762,13389,24370,10153,39533,34815,29259,29501,36864,41956,36869, +37960,29254,42111,31546,31869,39570,21019,18310,18590,34939,34762,31348, +31954,34282,34985,34287,34138,31343,31550,36703,37578,21080,20986,18621, +18573,34142,34814,29258,29500,36863,36707,36868,37959,29253,29906,37921, +37475,20390,21018,39491,41816,18351,18625,29558,29899,31428,31849,34351, +34782,34367,34194,31408,31606,36762,37933,12745,13774,10008,10270,34211, +34951,29338,29543,36934,36778,36954,37523,29322,29819,31596,31917,20431, +21085,18350,18649,29557,29920,31427,31890,34350,34845,34366,34193,31407, +31605,36761,37977,12744,13852,10007,10328,34210,35029,29337,29542,36933, +36777,36953,37617,29321,29859,31595,31999,20430,21197,39509,41834,39497, +41822,39416,39422,36636,26312,40618,12761, 9997,34313,34157,34332,17789, +17803,11304,20403,35947,35928,28628,34176,31574,31374,20418,31390,18323, +29286,29524,29304,30739,36722,33314,33334, 9652,18334,19453,19442,36740, +36896,12734,36915, 9996,34312,34156,34331,17788,17802,11303,20402,35946, +35927,28627,34175,31573,31373,20417,31389,18322,29285,29523,29303,30738, +36721,33313,33333, 9651,18333,19452,19441,36739,36895,12733,36914,26314, +40623,12765,40108,39363,34244,18711,34242,34102, 9962,32204,20358,35465, +31511,10662,34100,21614,31305,38045,31303,20356,29212,18278,29210,35574, +36667,19038,29469,14373,18276,38264,12694,30319,36822,36665,36820,22228, +34292,18709,34297,34146, 9991,32202,20394,35463,31554,10660,34150,21612, +31353,38043,31358,20397,29263,18314,29268,35572,36711,19036,29508,14371, +18317,38262,12726,30317,36873,36715,36878,22226,26350,24269,27187,27023, +34349,33623,34365,34192,10006, 9763,20429,19758,31594,30997,34209,33641, +31406,31604,31426,30986,29320,28908,29336,29541,36760,36220,29556,28899, +18349,17910,12743,11882,36932,36776,36952,36183,34348,33627,34364,34191, +10005, 9759,20428,19762,31593,31001,34208,33637,31405,31603,31425,30982, +29319,28912,29335,29540,36759,36224,29555,28903,18348,17914,12742,11886, +36931,36775,36951,36187,34330,18612,34311,34174, 9995,31998,20416,35028, +31572,10327,34155,21196,31388,37616,31372,20401,29302,18332,29284,34844, +36738,18648,29522,13851,18321,37976,12732,29919,36913,36720,36894,21052, +34329,18579,34310,34173, 9994,31916,20415,34950,31571,10269,34154,21084, +31387,37522,31371,20400,29301,18331,29283,34781,36737,18624,29521,13773, +18320,37932,12731,29898,36912,36719,36893,20995,39415,36635,36645,36634, +18150,32346,18876,18918,24312,24295,43680,43679,43678,43677,26441,26422, +24311,28102,24294,28101,28100,26440,28099,26421,29619,31706,35564,30395, +24748,12785,38909,17715,34572,32943,34565,32942,33109,32941,33107,32940, +33462,32939,33464,33255,33791,32938,33839,32937,26996,33854,42329,33231, + 4860,26990, 4869,42075, 4812,31180, 4889,42318,30662,30658,42070,31184, +42110,29066,28535,28538, 4851,41955, 4868,29084, 4811,42109, 4886,26761, +41954,35888,26760,36447,33841,33229, 6909, 6154,33836,33460,36639,34574, +33128,35369,32936,35343,32935,35345,33257, 4929, 4853, 4801, 8174, 8594, +26661,35341,33835,20883, 4403,27646,33832,36456,29081,34567,33172,36633, +33793,33174,35371,33176,20032, 6170,31135, 7934,31122,21877,36400,15196, +38669,38458,32136,32394,36405, 8854,12314, 8759,21876, 7933,32393,31121, +38668,12313,36399,36404,32135, 8758,15195, 8853,38457,31134,20031, 7031, +27226,35360,33777, 6907, 6152,27545, 7976,27376, 7910,25374, 5783,40720, + 5590,40719,27247, 8608,27078, 8710,11395,25577,19533,25579,25372,34570, +33459,36372,38122,40107,18793,26105,38657, 5299, 6951, 5277, 6942, 5207, +35783,36420,35787,36422,35213,30152,35211,30150,35122,30023, 8388, 8378, + 8328,24307, 8365,36415,36414,35216,30155,26359,24273, 8422, 8428, 5279, + 6944, 5209,32415,39946, 7623, 5315,32412,39943, 7620, 5312,18875,32509, +16150, 2984,35426,30960,32517,16139,30869,11425,25477,25461,30880,11462, +30866,11422,39427,30599,35836,36440,36444,10217,34885,14438,42333,10393, +20892,14503,42335,10413,20894,10266,34883,20882, 5976,26660, 7452,40393, +22765,40392,42558,17686,24994,24996,38675,37474,26104,38673,37292,41297, +41296, 5257,41295,42384,35378,31144, 7315,41309,22694,41308,42557,18046, +26133,26138,42926,17689,25000,24998,26707,26706,11659,19707,23731,16164, +22675, 3628,22673, 3626,27999, 3736,16172,22678, 3635,22677, 3634,28001, + 3741,36160,14714,11656,36158,14704,11128,11130,11151,11166,11150,11165, +18238,11137,11136,11156,11171,11139,11158,11173,43676,43675,40426,40422, +23861,43674,43673,25549,11054,28809,30936,11052,11058,24334,28821,28828, +30949,37997,11056,37655,19527,24456,19529,24467,17847,28737,30847,28736, +30846,17852,24463,38607,24789,38434,22436,24452,22433,24449,18761,32104, +30104,18766, 9511,24629,23450,22216,19145,21808, 9502,24823, 9509,24627, + 9506,24624,23447,22213,10827,22210,19142,10825,27623,21805, 9499,24821, +12241,24413,11978,11977,24351,37674,12240,38014,12239,24346,11976,11975, +24408,38009,12238,37669,36177,23963,36172,23958,34838,10321,34735,29788, +34724,29777,29106,29096,34761,10289,12275,18486,39272,17971,34802,10265, +12256,24403,12237,12236,24341,37664,12254,38004,12252,24339,12235,12234, +24401,38002,12250,37662,36165,23951,36167,23953,34650,29703,34652,29705, +25917,25916,25915,25914,25913,25912,12270,24399,12269,12268,24337,37660, +12267,38000,36163,23949,34648,29701,39271,39270,39269,39268,39614, 9840, +39611, 9837,39311,39313,15815,18446,15664,18407,25958,25957,39326,39325, +15938,18403,11852,24415,11851,11850,24353,37676,11849,38016,11848,24410, +11847,11846,24348,37671,11845,38011,36179,23965,36174,23960,23948,36162, +34737,29790,34726,29779,23955,36169,25637,25636,25635,25634,39114,39113, +39112,39111,39110,39109,25665,25663,12587,18541,11879,18498,14047,18440, +25702,25701,39166,39165,14090,18402,39108,17936,11844,24405,11843,11842, +24343,37666,11841,38006,34806,10216,34670,29723,34760,10233,11867,24398, +11866,11865,24336,37659,11864,37999,34647,29700,10477, 2940,32467,16149, +32466,16148,22209,30149,27815,22206,30146,27818,21516,30358,29052,42781, + 5262,29055, 5650,32406,39962, 7642, 5292,32403,39959, 7639, 5289,30355, +31454,31143,27276,27113,15961, 8496,22495, 8542,26122,26114, 9817, 9816, +40359,40358,40357,38632,36068,38628,36066,25364, 5587,25362, 5585,27744, +35164,27741,32167,30182,43039, 8749,28286,30437,28285,30436,28557,30676, +23626,25167,28284,30435,15392,38911,22203,15663,28480,30608,28283,30434, +13472,38888,38891, 9556, 9558,32073,17462,28408,30540,28282,30433,28281, +30432,28546,30667,23599,25139,28280,30431,32743,17461,17460,16952,32742, +32889,17532,32841,17492,32823,28445,30560,26002,23327,17046,17276,23175, +41237,32840,32328,32320,26000,23174,17275,17045,23326,41235,16461,22851, +41251,16456,22848,41249,14757,14744,14494,14440,28961,31061,24084,26022, + 9874, 9881,41268,41241,15171,24103,26041,24102,26040,24101,26039,24100, +26038,24099,26037,41261,24098,26036,24096,26034,24095,26033,24094,26032, +28970,31070,24093,26031,17457,14547, 9868, 9879, 9866, 9877,28967,31067, +24111,26049,15173,41263,24108,26046,39341,22202,15662,28964,31064,24106, +26044,28960,31060,24082,26020, 9865, 9876,32852,17456,17548,32851,17455, +32816,32785,32916,17531,17044, 9586, 9584,32333,32325, 9591, 9589, 9595, + 9593,28279,30430,12843,38913,22201,15661,28482,30610,40679,23173,17043, +25319,23325,17274,40677,23324,17273,25317,23172,17042,32839,32327,32319, +13094,11464,19592,25465,14477,13090,14461,13088,11377,11369,28713,30829, +23737,25323,13425,39016,38994,39015,38993,39014,38992,39013,38991,39012, +38990, 9676, 9671,17454,28706,30823,28704,30821,11381,11373,13427,25313, +22200,15660,11379,11371,11376,11368,28703,30820,28278,30429,36332,17990, +14546,14542,14497,14496,22199,15659,17992,36342,13093,13092,22198,15658, +36055, 2866, 2829, 3638, 3744, 3499, 3633, 3740, 3484,11658, 3631, 3738, + 3477,11670,11655, 5719, 3176, 5341, 4133, 4211, 6542, 5449, 3341, 6652, + 3662, 3115, 5396,14196,14706, 3112, 5394,14194,14701,42953, 8732,11657, +19706, 7754, 3118, 5400, 5399, 3481,11676,19712, 7757,11654,19704, 7752, + 5403, 3483, 3120, 5402,14198,14713,27282,27129,15657, 8469,22197, 8525, +25605,25607, 5438, 3330, 5347, 2330, 4205, 6539, 4204, 6536, 4216, 6535, +18237,30015, 5335,42108, 5656,42107, 5334, 4130, 4202, 6534, 9809, 9807, +12024,12022,26008,26705,31206,13483,12498,43672,43671,41432,41401,28098, +41431,41400,28097,12417,12474,37392,41411,10446,37390,41407,43005,41462, +12490,13482,12473,13478,12472, 4325,13891,13909,41113,11025,11027,11024, +41934,41909,41932,41907,41930,41905,43557,43224,41928,41903,25633,26470, +39107,22052,15418,25818,26704,10264,10263,10262,10261, 9791, 9790, 2808, +12838,12830, 2417, 2470, 2512,26469,25852,26468,26467,26466,26465,12840, +41950,41925,41947,41922,41942,41917,41939,41914,15417,22051, 7469,12848, +12847,12835,26703,26702,26701,26700,26699,25611,31367,29516,42166, 4823, +42009, 4867,26799, 4810, 4873,34306,36887,42106,26907,41953,31562,29277, +34302,26934,42162, 4821,42005, 4866,31559, 4809, 4871,31363,29273,42105, +29513,41952,26759,36883,13383,12952,13474,12951,13042,12950,13020,12949, +14487,15161,13350,13349,20985,20984,27892,27483,13348,20983,25782,13347, +20982,25206,12948,12947,20544, 4262,12946,12945,26464,14072,26566,26463, +14046,26580,26462,18439, 4603,14071,13524,14070,18453,18438,17861, 4657, +26461,17863,13626,18471,14057, 4633,13523,14045,22196,21308,39164,39106, +39324,34716,29769,10260,10259,10258,10257,10256,10255,13793,13786,13790, +13783,10254,10253,10252,10251,42104, 9370,42103, 4943,42102, 8891,42101, + 4942,42100, 5521,42099, 4941,42098, 4940,42097, 5861,42096, 5548,42095, + 4939,42094, 4938,42093, 5224,39607, 6179,39604, 6176,39600, 5011,39597, + 5008,32103,30103,11072,11078,12111,13800,13797,39315,12034,12944,13018, +26606,13076,13075,13600,32387,18401,26557,32345,32365,14060,26556,14059, +26555,34072,34074,35363,33779,32386,32385,32344,32363,14015,13566,18400, +18399,32343,32360,41729,41726,14014,13565,32342,31867,18491,10102,13908, +18497,32463,16138,39646,39105,39267,39266,39104, 8395,38401, 6355,41721, + 2806,14942,14940,15509, 2419, 2472, 2515,15507,38567,30014,30070, 6192, +21609,14364,18236,30013, 5520, 4129,14974,15523,13346,13345,13381,13344, +13040,13343,14489,15163,24034,23979,13415,25700,25956,25911,18771,18770, +14056,10057,10087,17950,18452,18437,18457,10079,14044,17955,25910,25632, +25631,30112,25667,14089,14069,15937,24022,15654,15908,17948,18398,18397, +32341,15653,30111,12274,11878,12266,12265,12264,12263,11863,11862,11861, +11860,11840,11839,11838,11837,11836,11835,11834,11833,11974,11973,12233, +12232,11832,11831,11830,11829,12231,12230,11972,11971,12229,12228,12248, +12246,12260,12258,12227,12226,32071,25909,12471,23983,23975,13362,39031, +39034,23974,23973,24018,13370,24017,25987,23323,17041,17272,23171,41218, +41216,23170,17040,25985,23322,17271,16688,16705,41214,41212,41210,43228, +43561,41208,41207,43742,19608,11484,16702,22946,41206,41222,23193,17068, +25991,23345,17302,41220,32632,32631,32629,32628,24058,43750,43745,25983, +24057,43749,43744,25982,16694,16693,16711,11413,41203,43739,19605,11481, +16698,22943,41202,11444,12020,11198,11196, 2533, 5649,11154,11169,19364, +19373,23443,23442,25123,25132,17605,17604, 9495, 9494,11149,11164,19361, +19370,23441,23439,25120,25129,17603,17601, 9493, 9491,11276,19424,25193, +11263,28096,22842,19411,28093,16450,25186,22839,16447,14152,14598,14154, +14600,40573,43670,43669,40565,11273,19421,25190,11260,28090,22836,19408, +28087,16444,25183,22833,16441,40575,40567,11622,11639,19673,19690,23659, +23654,25584,25596,17786,17781, 9645, 9639,40577,40569,11148,11163,19360, +19369,23657,23652,25119,25128,17784,17779, 9643, 9637,11628,11646,19679, +19697,23437,23436,25589,25601,17599,17598, 9489, 9488,25173,21913,15232, +25175,22538,16001,12943,12942,20543,20542,27895,27486,11632,11651,19683, +19702,23644,23642,25591,25603,17769,17767, 9618, 9616,11621,11638,19672, +19689,23435,23433,25583,25595,17597,17595, 9487, 9485,24843,24802,27885, +27476,24840,24799,27882,27473,11280,11267,19428,19415,24847,24806,11243, +11222,11278,11265,19426,19413,24845,24804,11247,11226,11246,11225,11245, +11224, 9633, 9626, 9631, 9624, 9630, 9623, 9629,22193,22192, 9622,11609, +19664, 6702,11613,19668, 6646,11653,10814,19162, 2877,11724,19735, 6704, +11720,19731, 6648,12357,10807,19156, 2750,35666,14645,35664,14654,14724, +11679,19715, 6691,35668,14649,10928,10937,12356,22619, 3566,27955, 3703, +22617, 3564,27953, 3701, 3642, 3747, 3503, 3652, 3754, 3510, 3650, 3752, + 3508,12361,10908,19215, 2747,10907,19214, 2708,10905,19212, 2706,12355, +22624, 3568,27957, 3705, 3648, 3750, 3506,10913,19219, 2711,36153,14644, + 3409, 2351,16161,22670, 3623,22669, 3622,27996, 3733, 3621, 3732, 3472, +36155,14698, 5721, 3178,11637,11620,19688,19671,25594,25582, 6644, 2752, + 7104, 3068, 5757, 3211,22609, 3556,27948, 3691, 3647, 3749, 3505,11625, +19676, 2678,14720,14712,14697,12350,20053, 6708,10920,10912,19224,19218, +24965,24961, 6625, 2710, 7088, 3038, 5725, 3182,14643,11645,11627,19696, +19678,25600,25588, 6598, 2670, 7057, 3002, 5681, 3137,11643,11624,19694, +19675,25598,25586, 6604, 2677, 7061, 3006, 5685, 3141, 6665,11636,11619, +19687,19670,25593,25581, 6597, 2669, 7056, 3001, 5680, 3136, 7420, 8000, + 6079,22010,27569, 1609,15345,28036, 1696,16260,22730, 1661, 5493, 1546, + 6090, 1536,14782,14264, 5488, 3076,11352,19501, 6767,11351,19500, 6759, + 7423, 8002, 6081,22012,27571, 1593,15349,28040, 1694,16262,22732, 1659, +11360,11358, 4196, 6563, 4559, 2510, 5632, 6430, 6983, 5538, 5417, 3315, + 2532, 5648, 6454, 6991, 5552, 7418, 7998, 6076,22006,27567, 1615,15341, +28034, 1703,16258,22728, 1668, 7429, 8005, 6096,22015,27574, 1945,15354, +28043, 2010,16268,22736, 2045,11018, 7431, 8007, 6100,22017,27576, 1943, +15357,28046, 2008,16271,22738, 2043, 7354, 7956, 6008,21954,27522, 3450, +15280,27974, 3718,16127,22646, 3599,11022, 7356, 7958, 6010,21956,27524, + 3452,15282,27977, 3720,16129,22648, 3601, 3219, 5763, 3215, 5759, 3217, + 5761,12345, 7373,21966,15294,12347, 7375, 7969, 6025,21968,27538, 3512, +15296,28009, 3756,16192,22687, 3654, 6020, 3468, 7964, 3728,27533,27992, + 7367, 3617,21962,22665,15290,16157,11605,11607, 6022, 3470, 7966, 3730, +27535,27994, 7369, 3619,21964,22667,15292,16159, 7212, 7880, 5884,21812, +27338, 1956,15096,27654, 2021,15695,22246, 2056,15652, 7176, 7863, 5878, +21771,27307, 1958,15057,27622, 2023,15651,22191, 2058, 5882, 1979, 7878, + 2086,27336,27652, 7210, 2119,21810,22244,15094,15693,15650, 5877, 1981, + 7862, 2088,27306,27621, 7175, 2121,21770,22190,15056,15649, 5903, 1972, + 7898, 2079,27364,27706, 7254, 2112,21835,22345,15128,15791, 5905, 1970, + 7900, 2077,27366,27708, 7256, 2110,21837,22347,15130,15793, 7277, 7914, + 5937,21844,27383, 1947,15150,27748, 2012,15903,22442, 2047, 7279, 7916, + 5939,21846,27385, 1942,15152,27751, 2007,15905,22444, 2042,11579,15682, +15954,15648, 7174, 7861, 5876,21769,27305, 1951,15055,27620, 2016,15647, +22189, 2051, 7225, 7887, 5893,21818,27346, 1941,15107,27681, 2006,15745, +22304, 2041, 5965, 1995, 7927, 2103,27417,27801, 7292, 2136,21871,22489, +15188,15956, 5967, 1997, 7929, 2105,27419,27805, 7295, 2138,21873,22492, +15190,15959,15725,15646, 5875, 1974, 7860, 2081,27304,27619, 7173, 2114, +21768,22188,15054,15645, 5898, 1969, 7893, 2076,27359,27701, 7249, 2109, +21830,22340,15123,15786, 5963, 1993, 7925, 2101,27415,27799, 7290, 2134, +21869,22487,15186,15953, 5975, 2335, 1930, 5492, 3095, 5371, 1929, 5238, + 4396, 6018, 3466, 7962, 3726,27531,27990, 7365, 3615,21960,22663,15288, +16155,15644, 5874, 1989, 7859, 2097,27303,27618, 7172, 2130,21767,22187, +15053,15643, 5896, 1991, 7891, 2099,27357,27699, 7247, 2132,21828,22338, +15121,15784, 5901, 1987, 7896, 2095,27362,27704, 7252, 2128,21833,22343, +15126,15789,40964,40969,11764,11763,12001,12000,19881,19880,27891,27482, +25817,25816,22535,21910,15998,15229,11762,11761,19755,19754,27894,27485, +25630,25629,22537,21912,16000,15231,40905,40903, 9789, 9788,40901,40899, +40897,40896,40966,40971,40909,40907,40895,40894, 6556, 2584,10923,19227, + 7632, 5986, 2350, 6894, 5573, 5343, 2349, 6532, 2574, 6531, 2573,11135, + 5333, 2323, 6530, 2572, 6538, 2576, 6558, 2586, 6548, 2579, 6523, 2567, + 6552, 2581,42955,43330,42965,43372,42963,43370,43386,42977,43388,42979, +43328,42952,27399,27780,18424,10069,27918,27458,27867,27441,27850,27237, +18451,10078,26723,26534,25881,26460,25851,25613,25872,25850,25533,33674, +28935,33476,28743,34646,29699,15642,22186,10387,20541,25975,33672,28932, +25970,25973,25724, 6489, 6488,22185,16713,32639,32637,35179,30117,23822, +35131,30072,15714,22269,15641,22184,15819,22373,15848,22391,12098,15640, +22183,22249,16565,32569,32571, 9719,33478,28745,23832,25719,25969,25718, +34680,29733,14043,18436,14466,14392,25879,25878,39323,17980,39257,17970, +39317,17978,26434,29669,40064,43549,26428,39091,17935,39163,17943,39090, +17934,39625,18600,34033,34028,34031,32368,15883,33670,28930,41658,41677, +41679,39052,40789,10443,20697,10475,20687, 6684, 6686,10479,20540, 6681, + 6680,18396,10056,14100,18395,32340,15639,21550,16438,32542,32541,22717, +16437,32540,32539,15638,22182,35542,14642, 7787, 7786,10643,19009,10642, +24512,19008,24672,12068,19901,24016, 6774, 6773,15637,22181,34007,34006, +41647,41646,27847,27438,26554, 9787, 9786, 9785, 9784,43226,43559,43555, +43222,25849,25610,26004,26007,15109,14390,26698,25609,10775,34837,15977, +15208,22514,21889,27846,27437,15976,15207,27398,27397,21864,21863,22513, +21888,27779,27778,15181,15180,27845,27436,22476,22475,15944,15943,24033, +24032,23978,23977,27844,27435,22564,22563,16041,16040,27843,27434,21895, +21894,15214,15213,27842,27433,22520,22519,15983,15982,15206,21887,15205, +27865,21886,27456,27841,27432,21015,21014,13387,13386,27840,27431,20628, +20627,13030,13029,15204,21885,25773,12104,12103,11744,11743,12094,12096, +10779,34810, 9700,23972,23971,27861,27452,20981,20980,13342,13341,11739, +11738, 7942, 7940,10724,10721,23970,23969,23982,24015,23968,23967,24014, +23981,24013,24025,24027,24012,12070,27864,27455,22512,22511,15975,15974, +27863,27454,20636,20634,13035,13032,24511,24671,19132,19131,10760,10759, +10732,10735,24516,24676,19106,19108,10731,10734,24510,24670,19113,19112, +10741,10740,24509,24669,19062,19061,10684,10683,10781,34759,15212,21893, +25753, 7947,10429,10571,18816,18957,24508,24668,10426,10568,24505,18813, +18954,24665,27870,27461,21901,21898,15220,15217,27873,27464,22526,22523, +15989,15986,10439,10588,18828,18964,24526,24686,10437,10586,24524,18826, +18962,24684,11737,11736,11945,11944,10596,10595,11735,11734, 9849, 9848, +12067,12066,14142,14587, 9783, 9782,12065,12063,19900,19898,25848,25846, +24011,24009,17969,17967, 9847, 9845,27876,27467,20539,20538,12941,12940, +15223,21904,25776,12061,12060,14139,14584,12117,12115,19916,19914,25887, +25885,24044,24042,17976,17974, 9858, 9856,11432,19557,25411,28147,22914, +16602,41080,11934,19847,25742,28084,22830,16436,12222,12284,16672,12217, +12215,41025,43668,11931,19844,25739,28081,22827,16433,11412,41027,11312, +19473,25900,25247,19933,12130,41029,11109,19341,25898,25106,19931,12128, +12154,19940,25920,28156,22923,16635,12183,19958,25945,25943,19956,12181, +12158,19944,25924,25951,19964,12197,11798,19788,25675,25673,19786,11796, +11776,19772,25641,25639,19770,11774,24992,20537,12939,12938,20536,25208, +12059,11760,19753,25628,25627,19752,11759,11818,19804,25696,25688,19797, +11808,11820,19806,25698,25690,19799,11810,40597,40758,40595,40594,11733, +11449,11453,19574,25452,28145,22912,16597,12058,11816,19802,25694,25686, +19795,11806,40639,41075,40637,11758,16629,11108,12193,11999,19879,25908, +25815,19937,12138,12206,12205,12038,11757,19751,25785,25626,19870,11960, +12937,20535,25784,25002,20534,12936,12057,43728,43725,32603,11411,19550, +25402,28149,22917,16605,23999,25793,23996,25790,11938,19851,24003,11913, +11936,19849,24001,11917,11916,11915,12045,12042,13120,15165,12156,19942, +25922,25823,19886,12009,12122,19926,25891,25643,19774,11778,12125,19928, +25893,25625,19750,11756,11815,32602,30882,43667,40537,12120,19924,25889, +25693,19801,11814,11107,12033,12192,19962,25949,28154,22921,16628,12191, +19961,25948,12190,19960,25947,25839,19892,12032,12296,19991,26015,12292, +27396,21862,19981,27777,15179,26011,22474,15942,15399,12056,12846,12547, +17076,15466,12055,15522,39256,39255,39254,39253,39252,39251,39263,39265, +39250,39249,39248,39247,41047,41046,41059,41061,41051,41045,41043,41042, +41041,41040,41039,41038,41037,41036,41035,25752,22562,16039,25751,22518, +15981,25750,21013,13385,25749,20626,13028,13044,20642,25772,11943,12102, +11742,12092,41054,41053,41056,12137,41034,14685,12136,11996,25761,20979, +13340,11732,12162,25907,17091,15471,15526,39246,19972,12273,12354,17039, +15458,15506,25771,22510,15973,24007,19896,12053,12090,24029,19903,12089, +24006,19895,12052,24005,19894,12051,15407,12851,41065,41064,41063,41070, +41068,41049,12119,41032,25779,22529,15992,11924,12041,41078,41073,11731, +11311,19472,25246,28144,22911,16596,12050,25764,20533,12935,12049,12100, +19908,25863,12189,12110,11106,19340,25105,28153,22920,16627,12109,19912, +25883,12262,11859,17316,14861,11730,14973,14817,11729,12834,12408,39101, +39103,39089,39088,39087,39086,39093,39095,39085,39084,39125,39121,39124, +39120,40887,40886,40885,40884,40883,40882,40927,40893,40881,40880,40879, +11755,40878,14710,14683,11754,11753,25624,25623,14807,12832,39083,20489, +12859,39082,20052,12349,39081,21547,14236,39080,39079,43776,43805,39078, +40447,43732,17270,14840,14939,17396,14901,15027,12225,12244,40915,40914, +40913, 9781, 9780,11077,40876,40925,40891,40889,40936,40934,39151,39147, +39150,39146,11813,11812,40932,40930,40938,14394,11970,12224,40944,40943, +40942,11828,11827,40940,11826,40911,40947,39308,39307,39140,39139,11752, +19749,25622,25621,19748,11751,14389,39077,39076, 9722, 9721,12135,19936, +25814,25906,19878,11995,12934,13377,12967,13339,39117,39116,39149,39145, +39154,39153, 9830, 9829,13375,12933,13338,12970,40737,40739,40734,17453, +16185,16111,14676,12161,12134,12133,19935,25905,25813,19877,11994,12179, +11794,11750,11749,16595,11439,11438,19567,25441,15755,17269,15754,15753, +25531,25446,25408,19555,11420,25620,26459,25475,25474,25473,19599,11474, +25445,25444,19570,11442,25406,19553,11418,25399,19547,11408,16959,17482, +13265,13337,15636,39056,22178,15634,28773,30900,39099,39097,39119,39123, +39075,39074, 9703, 9705,17452,28766,30894,28763,30892,28762,30891,12175, +19951,25937,25837,19890,12018,40756,16626,11529,39135,39137,14641,11793, +19784,25671,11748,19747,25619,12932,20532,25424,12048,11528,11522,11747, +19746,25618,11780,19776,25645,12178,19954,25941,11436,19565,25426,11993, +11992,19876,19875,27860,27451,25812,25811,22516,21891,15979,15210,25844, +30888,11476,30863,11415,25810,12017,12016,19889,19888,27839,27430,25836, +25835,22509,21884,15972,15203,25834,25940,19953,25939,19544,25396,25395, +25617,19745,25616,19562,25420,25418,25647,19778,25649,19560,25416,25414, +25670,19783,25669,19543,25394,25393,34715,29768, 1823, 1805,12576,24366, + 1065, 1012,24432,38030,12599,37738,35076,34899,38032,37740,24173,22266, +24434,21419,27315,26681,20922,13278,20920,13276,29112,20926,13281, 1859, + 1842, 1150, 1140, 9932,39742, 9931,39741,24819,39740,34742,29795,13907, +18540, 1482, 1476,12573,24363,12596,37734, 1062, 1009,24428,38026,12611, +42344,12595,37733,35078,34901,38034,37742,24175,22274,24436,21423, 9930, +39739, 9929,39738, 9926,39729, 9925,39728,24831,39727,29130,37421,29129, +37420,29099,29109, 1469,36495,37425,37424,37423,12586,18539,12624,42360, +20171,42676, 1479, 1473,12626,20173,42362, 1481,42678, 1475, 8054, 9922, +39720,29125,37415,38037, 1149, 1139, 1152, 1142,12620,20167,42355, 1145, +42671, 1135,35453,39526,38500,38702,24594,22314,41882,29647,27291,27290, +27617,27314,27289,12795,30387,38366,30408,38358,38363,38365, 2930,38357, + 2387,37255,29642,37254,29641,37253,29640,19022,43201,30416,38370,27663, +37246,36144,37245,38299,40063,31679,40062,31678,31738,31737,31705,35446, +31723,24604,15633,41888,29654, 8044,31735,38376, 2386,35443,31719,35442, +31718,32516,16284,32479,16283,35456,39528,38504,38704,24596,22316,41884, +29649,24601,29658,41890,15385,37241,37244, 1421,40058,31676,40057,31675, +38385,12811,24756,12793,29602,30390,38389,38388,29600,29596,29618,31704, +34636, 1433,29689, 1438,43219,43551,24599,29653,41887,15383,24598,29652, +41886,15382, 1285, 1418, 8050,38379,12806,24754,12791,24750,12787,38378, +38384,12810,38375,38387, 1306, 1294, 1303, 1291,29617,31703,29612,31698, +34634, 1429,29687, 1436,43217,43548,34630, 1300,29683, 1288,43212,43540, +30964, 3798, 3778, 3800, 3780,35425,30959,32462,16137,32461,16136,36652, +34579,34586,36650,34577,34584,34085,29464,31470,29585,31656,31506,29370, +29462,31468,29583,31654,31504,29368,36644,21875, 7932,32392, 5254,31444, +20450,38667,12312,36398,36403,31443,31624,36800, 8757,12755, 8518,15194, + 8852,38456, 8493,31120,31133,36972,36799,36971,12754,32134,20030,31623, + 6169,20449, 7030, 8702, 8337,38763, 9313,41293, 8934,36480, 8701,43062, + 8761,18031, 8593, 8173,38803,36371,36370,36369,18030,18029,18028,27225, +41287,29017,38339, 8204,38308, 8169,34386,32391,34385,34228,31132, 7931, +33774, 8517,31642, 8756,34227, 5253,36397,31641,38666,35366,35201,38455, +33771,29576,36805, 6168,29575, 8492,36402, 8851,29015, 7029,36978,36804, +36977,30301, 8061,41292, 7297,38121,38120,36368,18792,38119,36491,38118, +38117,38116,31119,31118,41283,18027,41285,18033,27911,27641,42858,42857, +26103,35204, 5619,36383, 5616,36380,24771, 7553,40207, 6407,31301,24617, +34240,40205,34238,34098,31299,39906,36663, 7199,39905, 6221,43351, 7551, +34096, 6406,29208,43349,36818,36661,36816,42721,29206,27330,42720, 7197, +27172, 6220,24769, 7550,40204, 6404,31297,24616,34236,40203,34234,34094, +31295,39903,36659, 7196,39901, 6218,43348, 7549,34092, 6402,29204,43347, +36814,36657,36812,42718,29202,27329,42716, 7195,27170, 6216,34504,30404, +34501,30401,18155,41645, 6885, 6148,41642, 7307,41673,41778,22311,41672, +22818,41641,22547,41640,22332,41639,26348,26380,22545,41668,18159,41675, +38227, 2955,34005, 2993, 2916,38213,34004, 3252, 2894,38183,34025, 3229, + 2887,38169,34020, 3222, 2627, 2643,38824, 9409,41720, 9218,36476, 2626, +41719, 2595, 2647, 2634,23169,18235,22102,18234,18217,21766,22081,18233, +37188,18232,18231,18230,18216,21765,21923,18229,18215,36632,14274,35340, +34569,20455, 2653,31640,31453,36976,12760,36803, 2617, 8060, 8540, 8244, +38393, 6849,41718, 6440, 2625,36148, 8149,38297,41717, 3792,18228,18227, + 6920, 6161,18226,18225,18224,18223,21921,18222,18221,41757,26415,41756, +26414,20448, 2591,31622,31442,36970,12753,36798, 2464,18210,26408,26407, +41754,34549,35325,41666, 7314,41665,41776,22693,41664, 6432,42556,18178, +26697,26356,26393,34087,38762, 9312,41711, 8933,36479, 2483,41710, 2455, +38802,37153,37152,37151,18209,18208,21763,18207,29565,21760,37224, 2557, +18220,37221, 2554,36643,20333,36602,39439,31285,36604,39484,24264,40237, +40132,40235,40130,39442,31290,36609,41735,39478,24258,40093,40186,40088, +40181,18143,34398,34435,37029,20279,36994,18145,34400,34437,37031,20281, +36996,39483,24263,39482,24262,39486,24266,40091,40184,40086,40179,40083, +40176,40081,40174,40241,40136,40239,40134,34758,10627,34757,10559,39303, +39305,34812,10557,37291,38086,37290,38094,37289,38080,38614,37288,38662, +37287,38664,37301,38656,37473,38655,30133,20531,10622,20530,10525,18394, +10055,18422,10067,18393,10054,26458,26696,10410,13522,15751,22319,25877, +34645,29698,34644,29697,34660,29713,38660,37435,37440,34753,29806,34751, +29804,34672,29725,34643,29696,34642,29695,34656,29709,34662,29715,34730, +29783,34732,29785,34677,29730,34641,29694,34640,29693,34667,29720,34666, +29719,37327,38096,20808,13191,18392,18391,10053,20807,20851,13231,18390, +18389,10052,20850,20857,13235,18421,18419,10066,20855,18410,10062,18477, +10096,20791,13179,18409,18412,10061,20790,14025,18388,13571,18387,20836, +13215,18414,18417,10064,20835,13521,18416,34836,10553,34691,29744,13625, +18470,13520,18480,39295,39298,12931,20529,20572,10615,12981,20574,12930, +20528,12929,20527,12928,20526,32453,16108,27288,18450,10077, 5631,37822, + 5630,42452,42565,18490,10101,13290,20941,13178,20789,13214,20834,34706, +29759,34699,29752,13177,18474,20788,20787,18476,10095,13213,18479,20833, +20832,18482,10098,13176,18538,13175,18496,32478,16282,32460,16135,13212, +20831,13174,20786,13220,20838,13190,20806,13230,20849,32339,15631,32362, +15847,32337,15629,39186,39188,15802,22360,25843,39259,39261,15628,22173, +25858,39245,39244,12083,12081,10274,39719,40156,40256,40155,40255,24386, +15813,24636,13407,30271,30269, 6595, 6594,34679,29732,14042,18435, 6251, + 6249,13292,20943,34704,29757,34702,29755,34701,29754,13119,13118,18533, +32482,16287,10342,39718,40154,40254,40153,40253,24396,13488,24439,13440, +30194,30193,34714,29767,38659,37400,37405, 8700,30362,30361,30170,30169, +37413,34739,29792,39737,10247,30192,30191,34741,29794,13117,37729,13629, +42340,24441,13487,24438,13490,39736,10215,39748,10210,39731,10209,39726, +10220,39735,10208,39725,10245,39733,10222,39717,10213,20954,10594,10379, +39764,10378,39763,39762,10528,40246,40143,40245,40142,40220,40105,40219, +40104,18564,10135,20952,13301,18563,18571,10134,20960,10373,39756,18559, +10130,20948,13297,18558,18567,10129,20956,10205,34916,34923,37772,13502, +37765,10203,34914,34921,37770,13500,37763,39761,10377,40172,40079,40170, +40077,40152,40252,40151,40251,39766,10523,40161,40261,40160,40260,40233, +40128,40231,40126,34851, 9960,34232,34090,10334, 1864,21204, 1757,32005, + 1601,35035, 1797,31293,31509,31895,20354,29864,18274,29200,29467,37983, + 1814,29926, 1571,18655, 1742,13858, 1881,36810,36655,37623,12692,34934, +34778,34003, 7306,34002,29395,34001,34498,34011,34508,34000,34497,40229, +34492,41761,34931,34775,41968,34018,34514,40243,34516,42397, 1037,41633, + 1031,41632, 1048,42392, 1022,41635, 1050,42394, 1024,41760,41631, 1046, +42390, 1020,41629, 2954,41628, 2992,41627, 2915,41626, 3251,41650, 2892, +41652, 3227,41656, 2886,41654, 3221,34263, 9979,34254,34121, 9970, 936, +20366, 931,31521, 926,34112, 921,31315,31530,31324,20375,29222,18286, +29231,29479,36686, 916,29488, 911,18294, 906,12712, 901,36842,36677, +36833,12703,34381,31639,34224, 2650,34226, 2616,31621, 2599, 2652,36975, +34384,36802,29572,36797,29574,36969, 2482, 6384,37645,37150,37149,39645, +37635,37644,37632,37148,37147,37146,37145,37144,27910, 2624, 8314, 6262, +41716,37187,38260,37297,37347,42609,32086,38078,37639,34016, 7313,34015, +29397,34014,34512,37090, 2481, 2480, 2630, 2637, 2505, 6421,37518,37128, +37399,37127,37495,37126,37469,37124,37468,37513,37142,37123,37511,37462, +37299,37756,37434,37122,37141,37121,37140,39431,36631,37412,37404,37498, +37494,37472,10043,37461,37460,37467,10039,37458,37457,37647,37138,37137, +37120,37510,37517,37520,37174,37505,37439,29444,37119,37136,37135,37172, +37170,37118,37117, 2641, 2632,39414,26406,26405,27640,42564, 2623,37566, +37286,31638,12764,12757,41733, 2622, 2621,37527,37402,37492,10045,37455, +37454,37465,37185,37508,37437,37184,37183,26413,27645,42561,20297, 2612, +20295, 2610,35114, 2608,35112, 2606,12763,37557,39421,18930,22264,27005, +21417,13951,24817,38564,38257,38562,37452,38560,30007,38068,32735,32711, +38761,32710, 9311,38760, 9310,38072,32709,38071,32901,38070,32764,17268, +23321,24825, 9217,24780, 9216,17267,38060,16897,38059,17340,38058,17530, +38066,27635,27312, 7608,38801,32708,27786,32093,30095,22171,15627,38645, +30126,38644,38643, 5247, 5530,32815,38800,32814, 9381,38799, 9380,38075, +32813,27684,30333,18707,35295,27162,27153,35405,22170,39882,38555,24446, +22351,39919,38609,24465,35332,27193,35291,27160,27150,35403,42950, 8731, +42949, 8730,42948, 8729,42947, 8728,35377,32076,40005, 8482,40002, 8479, +35541,14640,35540,14639,14313,27249,27251,17038,23168,24827, 9024,24782, + 9023,17037,38063,27021,16563,38690,23265,21508,37451,38084,32336,32515, +15626,32520,15625,32511,15677,32508,15624,32529,16280,38571, 5200,32335, +15623,35539,14638,14662,14637,35552,14666, 8626, 8629,14668,14708,18932, +22271,27007,21421,13942,24829,30360,42780,35108,30005, 5647,35143,30085, + 5665,22165,18820, 5605, 5604,35347,32111,32506,15929, 6955, 5331,40061, +43546,42762,18769, 6937, 5272, 6936, 5271, 6935, 5270, 6933, 5268, 5629, +22268, 6939, 5274,22180,22164, 6946, 5281,25809,32240,18748, 8323, 8156, + 8316, 8158, 8320, 8153, 5580,35374,32097,35335,32096,35334,32095,32513, +15882,32367,15881,38759, 9309,43061, 8932,36478, 8059,38798,38115,38114, +38113,18791,18790,18789,30347,37642,37515,37450,38130,37755,38112,38111, +27909,27639,37569,38128, 3646,22685,16184, 6338, 1522,12640,12645,15371, + 6342, 1510,12642,12647,15373, 6782, 6781,14798,21699, 6344,14796,21697, + 6341, 7801, 1555, 7440,12375, 7443, 8012, 6107,22026,27582, 1592,15367, +28052, 1693,16277,22744, 1658, 1489, 7435,12373, 7437, 8010, 6105,22021, +27580, 1940,15362,28050, 2005,16275,22742, 2040, 7442,22025,15366, 7439, +22023,15364, 7426, 1562,12340,12333,12338,12331, 5804, 3214,12342,12335, + 6027, 3514, 7971, 3758,27540,28011, 7377, 3656,21970,22689,15298,16194, +15505,12533,15504,14938,16379,14982,16012,12532, 6752, 1497, 6749, 1494, +41395,41428,41393,41426,41397,41430, 7673, 2785,12396, 3807, 8862,12509, +12436,12393, 5370, 3094,12439,12401, 5365, 3088,14737,14216, 5440, 3335, + 3128, 5405,14200,14716, 3087, 5364,14181,14664, 7871,12398, 4411, 4409, +12435,20087, 6593, 3074, 5351,14171,14636,12448,20094, 6591,12546,15118, +21825, 7236,12545,20135, 6451,12407,12544,12406,12388,12506, 3804, 8859, +12522,12505, 7664, 2776, 7671, 2783, 7717, 2884,41403,41434, 6017, 3465, + 7961, 3725,27530,27989, 7364, 3614,21959,22662,15287,16154,15051,21757, + 7169,12568,20156, 6382,14937,21735, 6848,41461,41460,12427,20084, 2755, +31205,31204,16392,12489,12488,12426, 4417,13481, 2225, 7635, 2415,15621, + 7167, 7858, 5873,21755,27302, 2239,15049,27613, 2245,15620,22163, 2261, + 7304, 7938, 5973,21879,27421, 2241,15198,27830, 2247,15967,22504, 2264, + 7251, 7895, 5900,21832,27361, 2237,15125,27703, 2243,15788,22342, 2257, +16032,12416,20081, 7526,31201,12415,12414,15686,15952, 2667,15619, 7166, + 7857, 5872,21754,27301, 1949,15048,27612, 2014,15618,22162, 2049,12423, + 7223, 7885, 5891,21816,27344, 1939,15105,27679, 2004,15743,22302, 2039, +12404, 7351, 7953, 6005,21951,27517, 3446,15276,27968, 3715,16106,22638, + 3587, 2256,21296,12567,13748,20155, 2235, 2255,21295,12566,13747,20154, + 2234,12560,20148, 6450,41459,15243, 3788,41450,15617,41420,41458,12425, +20083, 2209,31821,12497,12496,15117,21824, 7235,12562,20150, 6449, 2227, + 2223,12487,20114, 4245,12485,20112, 4243,12875,20501, 4242,14245,41418, +41456,12559,20147, 2220, 6016, 3464, 7960, 3724,27529,27988, 7363, 3613, +21958,22661,15286,16153,12500,12432, 7405, 7990, 6044,21993,27559, 1591, +15324,28021, 1692,16231,22715, 1657,15316,41467, 2217,12430, 7400, 7988, + 6042,21988,27557, 1938,15318,28019, 2003,16229,22713, 2038, 7404,21992, +15323, 7402,21990,15321, 1457,21287,12552,13738,20140, 1453,41444,15320, +41469, 1463,15615,15612,16030,12413,20080, 1444,12412,20079, 1443,31824, +31818,12565,20153, 2233,12484,32070,12483,12482,13480,13746,21294, 2254, +12481,20111, 4241,12480,20110, 4240,12492,20116, 6512,12479,20109, 6380, + 2268,22161,15610,15609,22160, 2259,15966,22503, 2263,12420,12419,15685, +22239, 2251,12495,12558,20146, 2219,12554,20142, 1460,15103, 2216,41454, +12422,41409,41438,15245, 3790,41453,11020,40855,30973,11578,11577,11591, +11575,11589, 4564,11583,11582, 2666,11586,11585,12828,12826, 5829, 3832, +12874,12870,20498, 3812,12869,20497, 3811, 3831, 5828, 3830, 5827, 3834, + 5831,12877,12879,12873, 7468,22050,15416, 2531, 5823, 3818, 3836, 3843, +12884,20506, 3875, 3905, 5843, 3898, 5839, 3900, 5841,12888, 7474,22057, +15423,12890, 7476, 8024, 6122,22059,27597, 3926,15425,28070, 3966,16337, +22799, 3955, 6117, 1968, 8021, 2075,27594,28066, 7460, 2108,22041,22773, +15405,16310, 7454, 8017, 6112,22034,27590, 1937,15390,28062, 2002,16302, +22767, 2037, 6115, 1983, 8019, 2091,27592,28064, 7456, 2124,22037,22769, +15401,16306, 7450, 8015, 6110,22032,27588, 1954,15388,28060, 2019,16293, +22756, 2054, 6109, 1977, 8014, 2084,27587,28059, 7449, 2117,22031,22755, +15387,16292,12895, 7488, 8031, 6129,22071,27604, 1590,15438,28077, 1691, +16344,22806, 1656, 3810, 3826, 3829,12893, 7483, 8029, 6127,22066,27602, + 1936,15433,28075, 2001,16342,22804, 2036, 7487,22070,15437, 7485,22068, +15435, 5838, 3897, 3886, 3910, 3915, 3877, 3891, 3902, 3874, 3889, 3896, + 3873, 3888, 3895, 3879, 3893, 3904, 6124, 3932, 8026, 3972,27599,28072, + 7479, 3961,22062,22801,15428,16339, 3884, 3908, 3913, 3809, 3825, 3828, +12865,43305,43632,43303,43630,43300,43627,43299,43626,14287,43298,43625, +43296,43623,14936,21734, 6847,22080,14935,22079,19102,22101,19101,14934, +43294,14933,43621,14932,14931,15462,15475,15457,15456,14956,14950, 6852, + 6846, 6845,15485,14333,14993,14992,14981,15007,15006,15005,15022,15014, +15010,15009,15004,15025,14351,15024,15483,15020,14349,15012, 5524, 1639, +14997,14337,14991,14332,14980,14979,14978,14995,14335,14984, 5519, 1906, +14339,15000,14999,43316,43637,15003,15479,14306,43314,43635,15041,14354, +15040,15493,15044,14356,15043,15495, 6866,14914,21725, 6369,14916,21727, + 6371,12858,20488, 6820,12872,20500, 3817, 3953,22796,16334,12883,20505, + 3872, 3952,22795,16333, 3951,22794,16332, 3865,22785,16323,19032,19100, +38551,19030,19099,38548,30001,29999, 6915, 4625, 4602,35104,29997,15608, +22159,15607,22158,15821,22375, 3127, 3334,35145,30087, 3314, 3325,15606, +27585, 4632,15846,22390,40060,43545, 2385, 2530, 2543,40009,43415, 2964, +38234,30168,30190,40054,43537,30277,23167,19097,40033,43462,38797,32707, + 2929,30189,40458,23320,17266,25101,23166,17036,40446,23349,17310,25097, +23198,17075,38926,38925,38924,38923,39028,39026,38922,38921,38920,38919, +39041,39043,40452,40462,40454,40445,40444,40442,40449,32588,32587,32586, +40456,23339,17294,25099,23187,17062,32922,32788,16896,17339,32594,40441, +16617,25096,16879,23055,40439,16911,23063,40438,40437,23400,17527,16871, +23049,40436,40435,22906,16587,40434,22905,16586,16585,22904,40433,40432, +22903,16584,16868,23046,40465,16590,22909,40464,16609,16607,16594,43731, +43730,40431,40430,39039,39038,39037,39036,16616,38937,38936,39243,39241, +38935,38934,39292,39288,17173,16615,16752,16614,16613,16612,16744,16611, +16789,39239,39238,16852,17211,32900,32763,16623,16621,11076,11075,39237, +39236,39278,39277,39276,39275,11952,19862,25769,25748,19855,11942,32899, +32762,17499,17451,17325,25842,21445,14034,17484,16791,25870,23275,17187, +25841,23273,17185,25876,23263,17165,11948,19858,25763,13414,13413,39216, +39215,39197,39196,39291,39287,12478,12477,13373,13336,13335,13368,12031, +12030,39235,39234,12108,12107,39284,39283,11941,11940,19854,19853,27900, +27491,25747,25746,22542,21917,16005,15236,39233,39232,39203,39201,27879, +27470,27855,27446,27838,27429,25904,25903,25745,25955,25902,18666,42563, +25759,25755,25998,27775,25808,27637,27015,27615,41158,41157,27836,27427, +27049,27611,39207,39211,11951,11950,19861,19860,27835,27426,25768,25767, +22508,21883,15971,15202,25766,11956,11954,19866,19864,27875,27466,25778, +25775,22528,21903,15991,15222,39221,39219,39224,39223,39290,39286,39231, +39230,39281,39280,14930,14929,14847,14954,14316,21588, 3816,14319,21591, + 3882,14318,21590, 2882,14948,14946,14294,21570, 893,14296,21572, 964, + 8262, 8413, 8261, 8412, 8253, 8404, 3081, 5860, 3167, 5859, 3175, 8260, + 8411, 1395, 1411, 1414,21584,14311,14347,21606, 1403,14305,21581, 1409, +14342,21602, 3815, 8259, 8410, 8258, 8409, 8252, 8403, 1406, 1393, 1111, + 1117,14703,14648,14660, 8187, 8350, 3080, 2322, 5710, 3166, 5718, 3174, +11162,11147,19368,19359,25127,25118, 6642, 2749, 7102, 3062, 5755, 3209, +11161,11146,19367,19358,25126,25117, 6623, 2705, 7086, 3036, 5723, 3180, +14635,11168,11153,19372,19363,25131,25122, 6590, 2665, 7054, 2999, 5678, + 3134,11160,11145,19366,19357,25125,25116, 6600, 2674, 7059, 3004, 5683, + 3139,14894,16401,15605,15603,14362,15842,14927,16368,43326,42946,43324, +42944,43321,42941,42939,43319,43255,43588,43263,43596,43262,43595,14473, +21643, 6260,30231,32200,38696,30229,38545,30262,30167,38588,30018,30166, +30012, 3276, 3434,43569,43236,43566,43233,16329,22791, 6234,16050,22573, + 6247, 7829, 7736, 7585, 7869, 7600, 6756, 7794, 7740, 6576,14475, 6583, + 7597, 4175,14479, 4170,15601,22157, 6792,15140,15600,22156, 7261,14360, + 2881, 2805, 5527, 2986, 2945, 2937, 2928, 2927, 2384, 2977,38654,30261, + 8287, 8126, 8281, 8116, 830, 8286, 8125, 8285, 8124, 824, 827, 8303, + 8131, 8302, 8123, 8307, 8101, 8300, 8301, 8120, 8121, 8299, 8119, 8297, + 8118, 8295, 8104, 8292, 8129, 8306, 8103, 8308, 8106,30038,30035,38259, +30315, 8425, 8427,32057,14884,13417,15599,22155, 6511,15656,22195, 7821, + 6331, 6427,15712, 6424, 7414,15705,22257, 6844, 5887, 5799,16243,14926, +21733, 6841,15598,15965, 6473,22154,15597,15868,15596,15840,22386, 6843, +14445, 5911, 5635,14453,14444,14448,15830,15844,22388, 6840, 5913, 5628, +15833,15827,15826,14839, 7575,15595, 2872, 2741,14925,21732, 6839,15594, +22153, 2833,15593,22152, 2835,15592,22151, 2438,15591,22150, 2432, 2664, +15875,22409, 2445, 2717,15589,22148, 7839,16355,16374,15782,22336, 7823, +16357,22809, 7240,16207,22702, 7765,14756,14227,14755,14226,14754,14225, +16218,16217,43513,43174,43510,43171,16224, 6719,21546,14235,16216,22706, + 6725,14763,14230,16220,15588,22147, 7390,15933,22467, 7388,43505,43166, +43502,43163,16209,22704, 7767,15811,22366, 7394,16146,22656, 7387,16145, + 3605,22655,16144,15587,22146, 7231,15855,16035,15854,16034, 2839,15860, +22399, 2838,15859,22398, 7229,15586,22145, 7501,30128,38653,30132,38652, +38681,38651,30131,13334,16069,22590,16078, 6270,22599, 6269,16181,12927, +27932, 6914, 6960, 5414, 8057, 5957, 6506, 6505,18941,18940,10538,10537, +16179,13333,16170,13332,16388,15017, 7588, 6306, 5236, 5811, 5851, 5869, + 6740, 7127, 5798, 6468, 6996, 5564,14405,14018,14404,14017,15770, 6466, + 6994, 5562,14450,14447,15769,15768,15767,16373,22815, 7228,14407,14020, +15772,16122,22643, 7227,14409,14022,14443, 5547, 5223,32069,27917,16038, +22561,16037, 6291,22560, 6288,27915,15874,22408, 4435,15801,22359, 4459, + 6574,22144,15585, 6562,22358,15800, 6582,22406,15872,16011, 5655, 4128, +15584,22143, 4437, 5660, 4093,14634,14633,14632,14631,43483,18998,16048, +22571, 6258,43478,43131,43475,43128, 6707,21367,13906,16183,22684, 4239, +14678, 6689,21336,13835,14680,16124,13331, 5770, 5919,14672,14671, 5768, + 5868, 5766, 5907, 6561, 4189,15911,22448, 6838, 5943, 5627, 6442, 6987, + 5542,15703, 5594, 5416, 5598, 6075, 7011, 7997,28033,27566, 6496, 7417, +22727,22005,16257,15340,15583, 5600, 5867, 7013, 7854,27610,27300, 6498, + 7163,22142,21753,15582,15047, 5945, 5645, 6724, 7116, 5787, 5602, 5947, + 7015, 7918,27754,27388, 6502, 7285,22459,21851,15927,15157, 5597, 5962, + 7010, 7924,27798,27414, 6495, 7289,22486,21868,15951,15185,15455,16352, +15503,16351,16350,15513,22106, 7835,14844,21717, 7820,14886,21720, 7819, +15410,22044, 7818,14825,21708, 7817,14824,21707, 7816,16199,22692, 7815, +14883,14823,43587,43254,43586,43253, 7825, 2663,16362,22811, 1398,16367, +16366,43289,43616,43594,43261, 2414,16372,22814, 1155,16371,22813, 2421, +16359,43280,43613,43252,43585,14838,16365,16364,43278,43611,43275,43608, +43273,43606,43291,43618,15447,38524, 8682,15449,38526, 8684,43271,43604, +43270,43603,43598,43265,43259,43592,16370,43269,43602,43017,43408,15858, + 3596,22642,16121,15857,22397, 2837,14234,21545, 6718, 5782,14743,21688, + 6318,16198,16215,16304,16214,16197,16213,16206,22701, 7764,16205,22700, + 7763, 6717,21544,14233,16291,16212, 5810,43103,43458,40124,14170,40123, +14169,30188,30187,38695,30186,38694,30185,32066,32060,14630,14629,14628, + 3343, 7680,39970,32449, 5425, 7677,39967,32446, 5422, 8440, 8451, 3712, + 3440, 3696, 3415, 3589, 3585, 3711, 3439,14244,43101,43456, 6671,21079, +13519,15581,16237,43099,43454,43111,18997, 3710, 3438,43109,18995,43123, +43470,43120,43467,16101,22636, 3583,15932, 3604,16312,16142,14805, 5765, + 5233,43113,43460,16120, 3595,16119,22641, 3594,16118,22640, 3593,14803, +16047,22570, 3522,16046,22569, 3521, 6706,20785,13173, 6447,21556,14255, + 6445,22725,16252, 6333, 6444,14418,14028,14442,15337, 5596, 6067, 7009, + 7995,28031,27564, 6494, 7412,22724,22003,16251,15336, 6435,21554,14253, + 6438,22722,16249, 6434, 7416,14753,14387, 5540, 6065, 6985, 7993,28029, +27562, 6437, 7410,22721,22001,16248,15334,15301,21973, 7380, 6030, 5803, + 6029, 5775, 6743, 7129, 5801, 6731, 7122, 5793, 6727, 7118, 5789,14760, + 6032, 5777,14746, 7386,21979,15307, 5781, 5452, 6034, 5779, 6723, 7115, + 5786, 5795, 6039, 7124, 7983,28016,27552, 6733, 7396,22710,21984,16226, +15312,14752,14748, 5791, 6037, 7120, 7981,28014,27550, 6729, 7392,22708, +21982,16222,15310,43027,14465,21641, 6257,16327,22789, 6256,32237,15002, +14464,14463, 6589, 6484,21453,14051,16246,14469,14468,15689,15950, 6254, +15580, 5571, 5866, 7001, 7853,27609,27299, 6481, 7162,22141,21752,15579, +15046,14751,14471, 5569, 5889, 6999, 7883,27677,27342, 6479, 7221,22300, +21814,15741,15101,16326,22788, 3938,43577,43244,43574,43241, 6819,21366, +13905, 6818,20784,13172,16331,22793, 4238, 5813, 3987, 6796,21319,13807, + 5817, 4015, 5809, 4012, 6805,20713,13116, 6807, 7147, 5834,20783,26609, + 3845,13171,26853, 3838,13666,21222, 3820, 6790, 7138, 5808,20805,26616, + 1953,13189,26857, 2018,13674,21227, 2053, 5807, 1976, 7137, 2083,26636, +26874, 6789, 2116,20848,21247,13229,13701, 5821, 1967, 7144, 2074,26629, +26867, 6800, 2107,20830,21239,13211,13692, 6794, 7140, 5815,20782,26608, + 1935,13170,26852, 2000,13665,21221, 2035, 5819, 1985, 7142, 2093,26647, +26885, 6798, 2126,20870,21256,13245,13708,16325,22787, 3937, 3940, 3946, + 3921, 3959, 3970, 3930, 3950, 3964, 3924, 3936, 3944, 3919, 3949, 3963, + 3923, 3957, 3968, 3928, 6835, 7154, 5848,20903,26670, 1589,13261,26895, + 1690,13717,21268, 1655, 3935, 3943, 3918, 6830, 7152, 5846,20898,26668, + 1934,13256,26893, 1999,13715,21266, 2034, 6834,20902,13260, 6832,20900, +13258,16315,22777, 3856, 3855, 3861, 3850, 5836, 3848, 7149, 3841,26628, +26866, 6809, 3823,20829,21238,13210,13691, 3934, 3942, 3917,14837,21713, + 6353,22100,14836,14835,14846, 6851,21738,14952, 6837,21731,14924,15502, +15501,15516,15528,15540,14882,15536, 5864, 1638,16378, 5858, 4127, 5857, + 1905, 6854,21740,14967,14881,15534,14878,14906,15544,15546, 6862,21746, +15035, 6864,21748,15037,14867,14908,14897,14891,14888,14899,14875,14880, +16098,16095,22634,22631, 3578, 3575,22629, 3573,27960, 3708,22608, 3555, +27947, 3688,22606, 3553,27945, 3686,40118,14110,30165,38687,30164,32068, + 3274, 3432, 3268, 3426,27965,27963,14626, 5349,27940,35536,14625,35538, +14627,35535,14624,35534,14623, 6664, 6663, 4303,21444,14033, 6560,21443, +14032, 5738, 3196, 2528, 2527, 5644, 7042, 8345, 8183, 2526, 3323, 3317, + 5640, 7038, 6931, 5266, 5641, 7039, 2524, 3313, 7732,39979,32435, 5362, + 7729,39976,32432, 5359,22612, 3559,27951, 3694,22611, 3558,27950, 3693, + 7630,39953,32422, 5322, 7627,39950,32419, 5319,35533,14622,35532,14621, +35531,14620,35545,14653,35530,14619,35544,14652,10716,10713,10708,10705, +35527,14616,35529,14618,10710,10707,10593,10592, 2702, 2690,18867,18855, +10470,10458, 5741, 3199, 7099, 3049,24735,24575, 5733, 3191, 3272, 3430, + 5735, 3193, 5734, 3192, 7096, 3046,24732,24572, 5731, 3189, 7094, 3044, +24730,24570, 5728, 3186, 7091, 3041,24727,24567, 5715, 3172, 7083, 3029, +24724,24564, 3270, 3428, 2700, 2688,18865,18853,10468,10456,43482,18834, + 5709, 3165, 5704, 3161, 5626, 4113, 5855, 4085, 5662, 3986, 5701, 3158, + 5693, 3150, 7077, 3022, 7069, 3014,24716,24556,24708,24548, 6620, 2699, + 6612, 2687,18985,18864,18977,18852,10613,10467,10605,10455, 5697, 3154, + 5689, 3146, 7073, 3018,22604, 7065, 3010,24712,24552, 3551,24704,24544, + 6616, 2694, 6608, 2682,27943,18981,18859,18973,18847, 3684,10609,10462, +10601,10450,22603, 3550,27942, 3683, 2696, 2684,18861,18849,10464,10452, + 5698, 3155, 5690, 3147, 7074, 3019, 7066, 3011,24713,24553,24705,24545, + 6617, 2695, 6609, 2683,18982,18860,18974,18848,10610,10463,10602,10451, +28004, 3126, 3060, 3379, 3125, 3123, 3122, 3333, 3066, 3383, 3065, 3382, +10507,18914,10506, 2875,18913, 2874, 3304, 3493, 3302, 3491, 3301, 3490, + 2746, 2745,18889,18888,10490,10489, 2744, 2743,18887,18886,10488,10487, +14522, 5654, 2538,15766,15765,14397, 8138, 8310, 5559, 5546, 5545, 5222, + 5707, 5221, 5717, 5544, 5220,16422,16417,16419,43666,43661,43664,43659, +43656,43654,43652,43650,43643,43648,43641,43646, 1721, 7573, 1718, 7570, + 7711, 2859, 7706, 2844,16494, 7690, 2800, 7688, 2798, 7687, 2797, 7709, + 2857, 7704, 2842,16484, 7694, 2813,16502, 7685, 2795, 7714, 2864, 7684, + 2794,16491,16490, 7693, 2812, 7683, 2793,16534,16541,16532,16539,16547, +16552,16489,16551,32547,16545,32549,16550,16549,32544,16488,32584,32596, +16580,22899,28140,32583,38724,43714,22901,28142,38722,43712,16582,32581, +16671,16593,16569,16412,16411,16410, 7682, 2792, 7692, 2811,16524,16526, +16408,16407,16430,16406,16509,16506, 3645,22871,16497,16427,16426,22823, + 4558,16425,22822, 4556,16592,16500,16511,16465,16469,16467, 7701, 2822, + 7699, 2820, 7697, 2818,16504,16951,23098, 8930,32714,16751,16750, 4324, +16746,32898,32761, 9180,23289,17210, 6722,23032,16851,17209,23288, 9179, +17215,23293, 9187,16839,16989, 6471,23037,16857,16836,16987,16831,16984, +43775,43804, 4361, 9178,17191,23279, 9156,17164,23262, 9137,17189,23277, + 9154,16785,17184,23272, 9152,17183,23271, 9151,17163,23261, 9136,16793, +17260,23314, 9210,17259,23313, 9209,17258,17257,17256,17540,17520,16895, +16894,17384,16916,17373,17084,23204, 9040,17546, 4126, 8890, 8929,23097, +16950,16949,23096, 8928,16948,23095, 8927,16947,43871,43830,43869,43828, +17472, 6376,22977,16757,16765,22969, 7161,17449,16799,17459,32713,16749, +16748,17470,17447, 8952, 8951,16830,23015, 7448,16850,23031, 6788,32760, +17208,23287, 9177, 8970, 8969,16809,22996, 4555,16808,22995, 6317,16849, +23030, 7159,16829,23014, 6374,16848,23029, 7446,16828,23013, 6786,17207, +23286, 9176,16782,16847,23028, 7215,16827,23012, 6419,16779,17480,32732, +32754,32731,16784,17182,16768, 9189,43807,43778, 4268,17176,17161,43867, +43826,17160,43865,43824, 9208,23312,17030,17255,23160, 9017, 9207,23311, +17029,17254,23159, 9016, 9226,23343,17066,17298,23191, 9030,17028,17253, + 9206,23310,17252, 9205,23309,17251,17027,23158, 9015,17250,23308, 9204, +17026,23157, 9014,17249,23307, 9203,17248,23306, 9202,17025,23156, 9013, +17247,16867,17519,16893,16892,16891,16890,16902,16865,23045, 6470,16873, +16870,23048, 6378, 6190,23395,17522,16864,23044, 4525,16883,23059, 4509, +16914,23065, 4508, 9201,23305,17246, 9249,23355,17360,17420,23377, 9272, +17138,23241, 9091, 5871, 7856, 7524, 7165, 8042, 6140,16927,17143,23076, +23246, 7522, 9096,28180,28208, 8040, 9120, 6138, 8876,17436,23391, 9286, +17592,28242, 9307,23430,28276, 8912, 7520, 8038, 6136,17136,23239, 9089, +17430,23386, 9281,17586,28237, 9302,23425,28271, 8907, 7518, 8036, 6134, + 9269,23374,16924,17140,17417,23073,23243, 7516, 9093,28177,28205, 8034, + 9117, 6132, 8873,17372,16889, 9229,23348,17074,17309,23197, 9034,17073, +23196, 9033,16881,23057, 4517,16670,16574,22893,28134,32575,38716,43706, +22895,28136,38718,43708,16576,32577,32601,16573,22892,28133,16625,22919, +28152,16946,23094, 8925,16945,23093, 8924,38796,32704,17444,17443,17498, +17477,17504,17488,17490,17442,17441,16795, 3581,22981,16775,16774,22980, + 4507, 3580,23011,16826, 8943,23102,17179,16957,23268, 9147,32748,32893, + 3864,22994,16807,16806,22993, 4539, 2179,23010,16825,17509,16846,23027, + 2193, 2184,23020,16838,16855,23035, 2197, 2182,23018,16834,16811,22998, + 4506,16813,23000, 4524,16982,16819,43800,43771, 9166, 1673, 9200,23304, +17024,17245,23155, 9012, 9228,23347,17072,17308,23195, 9032, 9224,23341, +17064,17296,23189, 9028,32759,32897,17214,23292, 9186,17206,23285, 9175, + 3948,23026,16845, 3644,23025,16844,43803,43774, 9174, 2192,17159,23260, + 9135, 9134,23259,17158,17440,17514,17512,16860,23040, 2191,17000,23134, + 8995,16998,23132, 8993, 3591,23024,16843,17222,16994, 9192,23296,17218, + 9194,23298,17220,17507,16992,23127, 8987,16862,23042, 1328,23154,17244, +17023,17474,17243,17022,17497,17021,17486,17439,17496,17057,17093,17020, +17019,17117,17352,17371,17370,17376,17369,17390,17379,17392,17109, 8894, + 1637,17338, 8889, 1904,17356,17103,17438,17401,17126,17403,17128,17409, +23364, 9261,17411,23366, 9263, 8923,23092,16944, 8922,23091,16943, 9133, + 2862, 9144, 2791, 9142, 2810, 838,22973,16764,16761,22976, 840, 9131, + 2790,16736,16734,17324, 8978,16842,23023, 3814, 9107,23257,17154,17107, +23220, 9070, 9076,23226,17115, 8968, 8967,23119,16978,16803,22990, 3881, +16802,22989, 2880,32747,16805,22992, 1327,16816,23003, 1334, 9165, 8962, + 8961, 1344, 9163, 8966,23118,16977, 8964,23116,16975,17217,23295, 9191, + 9011,23153,17018,17017,23152, 9010,17120,23229, 9079,17082,23202, 9038, + 9062,23213,17099,32758,32757, 8984, 8982, 8977, 8976, 2171, 2170, 2178, +23009,16824,43802,43773, 9173, 2190, 9199,23303,17016,17242,23151, 9009, + 9198,23302,17015,17241,23150, 9008, 9196,23300,17239,23148,17238,17237, +17236,17235,17234,17233,17232,17231,17518,17517,17172,17337,17336,17335, +17334,17345,17205,32896,17333,32921,28257, 9056,43837, 9245, 9395,28250, + 9329,43796, 9392,28197, 9326,43902,28224, 9053,43895, 9242,43834, 9049, +28254, 9238, 9388,43793, 9322,28247, 9385,43899, 9319,28194,43892, 9046, +28221, 9235, 9232,23352,17089,17323,23207, 9043,17321,17320,32773,32680, +32679,32772,32685,32778,32683,32775,32792,32688,38823,32771,17516,17539, +17543,17204,23284, 9172,17013,23147,17012, 9006,23146, 9005,17011,17010, +23145,23144, 9004, 9003,17009,17007,23143,23141, 9002, 9000,17081,17080, +23201,23200, 9037, 9036,38830, 9416,32848, 9415,32847,38829, 9215,23319, +17035,17265,23165, 9022, 9213,23317,17033,17263,23163, 9020,17203,23283, + 9171,16878,23054, 2188,17529,23402, 1325,17526,23399, 9170,16876,23052, + 1324,17525,23398, 2187, 1177, 1188, 1160, 1185, 1167, 1170,32806,32697, + 1220, 1215, 1246, 1202, 1250, 1232,32811,32702,17134,23237, 9087,17427, +17583,23383,23422,28234,28268, 9278, 1184, 9299, 1187, 8904, 1176,16926, +23075, 1159,17142,28179, 1166,23245,28207, 1169, 9095, 9119, 8875, 9275, +23380,17423, 9277,23382,17426,17148,16931,23251,23080,28212,28184, 9101, + 1236, 9124, 1240, 8880, 1226,32808,32699,38792,38755,43819,43784, 9280, + 1245, 9301, 1249, 8906, 1231,23385,23083,28236,28187, 9343, 1254, 9363, + 1256, 8883, 1210,38860,38757,43860,43786, 9458, 1260, 9471, 1262, 8911, + 1219,17429,16934,28215,28270, 9127, 1208, 9376, 1258,32880,32701,43821, +43907, 9306, 1214, 9480, 1264,28241,28275, 9365, 1222, 9378, 1242,43862, +43909, 9473, 1228, 9482, 1252,17153,17585,23256,23424, 9106, 1197,32810, +32931,38794,38872, 9285, 1201,23390,23429, 9345, 1204,38864,38874, 9462, + 1206,17435,17591,32884,32933,17434,17590,23389,23428,28240,28274, 9284, + 1200, 9305, 1213, 8910, 1218,17433,17589,23388,23427,28239,28273, 9283, + 1199, 9304, 1212, 8909, 1217,17147,16930,23250,23079, 9100, 1235,28211, +28183, 9123, 1239, 8879, 1225,16933,23082, 1244,17152,28186, 1248,23255, +28214, 1230, 9105, 9126, 8882,17145,23248, 9098,17151,23254,17150, 9104, +23253, 9103,38863, 9461,32883, 9460,32882,38862, 1316, 1319, 1337, 1313, + 1340, 1322,17098,23212,17097, 9061,23211, 9060,38834, 9427,32857, 9426, +32856,38833,17367,17366,17365,17364,17363,16908,32794,32925,17425,17582, + 9448, 9447, 1380,17560,23409, 1373,38849, 9446,32872, 9444,32870,38847, +38841, 9434,32864, 9432,32862,38839,38837, 9430,32860, 9429,32859,38836, +32691,32796,17106,17105,23219,23218, 9069, 9068,38844, 9439,32867, 9438, +32866,38843, 1370, 1378, 1348, 1375, 1356, 1362,16910,23062, 2186, 1385, +23412,17568, 9252,23358,17387, 1382, 1390, 1353, 1387, 1359, 1365,32693, +32800,17114,23225,17113, 9075,23224, 9074,38853, 9453,32875, 9452,32874, +38852,17332,17331,17330,17329,16888,32787,32920,17432,17588,17358,17556, +17351,17553,17389,17570,17378,17562,17382,17564,17394,17572,17362,17558, + 9442, 9441, 9424, 9423, 1368, 1108,13330,13329,13400,13397,17078,17315, +17071,17307,15133,13770,13518,14434,15468,14972,15521,14863,13769,14436, +15135,13517,13768,14811,15395,13516,13767,14420,15116,13515,15518,14860, +15465,14965,13805,14816,15398,13568,17124,17405,17070,17314,15369,14792, +14790,15359,14821,15430,15491,14910,14770,15314,12926,13328,15520,14971, +13327,12925,13326,12924,13325,12923,15542,15031,13469,13253,14815,15397, +15464,14859,17349,16906,17347,16904,14873,16397,14871,16395,14532,13324, +14527,13323,14525,13393,14530,12922,14535,12984,14537,12921,14517,12920, +16382,14987,16384,14989,16022,13322,16017,13321,16015,13395,16020,12919, +16025,12986,16027,12918,16008,12917,15775,15777,14402,14400,17398,14510, +14903,14858,14508,14424,14819,16961,17305,14412,14855,13876,13883,13881, +13873,14422,14414,14416,14809,13946,13944,13878,13889,13887,15029,14923, +13451,14963,13840,13900,13831,13803,13842,13981,13779,13829,13959,13950, +13971,13964,13962,13967,16068,22589,16077, 4261,22598, 4260,16066,22587, +16075, 4259,22596, 4257,15256,21934,15263, 7336,21941, 7343,15254,21932, +15261, 7334,21939, 7341,12916,20525, 4255,13079,20683, 4314,12915,20524, + 4254,12914,20523, 4253,13081,20685, 4316,13320,20978, 4434,13419,21040, + 4468,13319,20977, 4433,13318,20976, 4432,13317,20975, 4431,12913,20522, + 4252,12912,20521, 4251,12911,20520, 4250, 4301,22781,16319,15412,22046, + 7464,12910,20519, 6816,12909,20518, 6634,12908,20517, 6661,12907,20516, + 6459,12906,20515, 6453,12905,20514, 6802,13316,20974, 6632,13315,20973, + 6637,13314,20972, 6628,13313,20971, 6457,16321,22783, 4249,16308,22771, + 4248,16203,22698, 6715,15914,22451, 6492,15305,21977, 7384,15303,21975, + 7382,15155,21849, 7283,15414,22048, 7466,13006,20610, 6813,15403,22039, + 7458,13009,20613, 6659,16201,22696, 6713,13403,21030, 6639, 8092, 8571, + 8574, 8095,38612,37449,38626,37448,38624,37446,38541,37444,14814,17313, +17312,12904,12903,12902,12901,13083,13012, 7107, 5350,42779,42777, 4169, + 4393,14834,14922, 4390, 4349, 4424, 4270, 4347,18969,43135,27930,27928, +27921, 4601, 4600, 4598,27511,27509,27504, 7785, 6772, 6679, 6487, 6688, + 8090, 8569,30259,35323,30254,35317,30252,35315, 8089, 8568,18967,43133, +30251,35314,30244,35307,30257,35321,30249,35312,15087,21797, 4505, 4504, + 4512, 4579, 4577, 4514,29692,34639,29691,34638,29707,34654,29717,34664, +29799,34746,29801,34748,29740,34687,13958, 6932, 5267, 6930, 5265, 4503, + 4502, 4501, 4520, 4519, 4551, 8363, 2934, 2926, 2974, 2970, 8370, 2925, + 2383, 2391, 2382, 8368, 8347,30250,35313, 8343, 7722, 7720,19096,19094, +10709,10706, 4500,22238,15684, 4499,22236,15681,13514,21078, 7566,12900, +20513, 6779,12899,20512, 6826,12898,20511, 6737,17122,23231, 9081, 9066, +23216,17102,17111,23222, 9072, 9026,23185,17056,17095,23209, 9058,12897, +20510, 7806,15550,22120, 7851, 7507,22090,15478,15533,22114, 7845,15538, +22116, 7847, 7499,22084,15461,15530,22111, 7841,15711,22261, 6742,15708, +22259, 7774, 7581,22380,15829,15836,22382, 7583,15923,22457, 7564, 7593, +22241,15688,15442,22075, 7492,15489,22096, 7513,15481,22092, 7509, 7837, +22108,15515,17005,23139, 8998, 8997,23138,17004,15500,22099, 7832, 7497, +22078,15454,15453,22077, 7496, 7831,22098,15499,15473,22087, 7504, 4529, +22140,15578,13822,15577, 4527,22139,15576,13817,15575,15724,13513,15574, +22138, 4179,15573,13583,14251,15710,15572,22137, 7776,14257,15571,16242, +15707,15570,22136, 6745,16254,15569,15832,15835,15702,15922,15568,22135, + 6500,15567,15925, 4188, 4538,22455,15920, 4537,22454,15919, 7591,22453, +15918,15917,13613,15916, 7595,22134,15566,14065,15565,17228,14833, 4173, +13188,20804, 4365,13228,20847, 4386,17227,13237,20859, 4389,13169,20781, + 4360,14099,13827, 4534,13603,21164, 7590,14068,14024,13570,13209,20828, + 4382,13512,13412,13411,17003,17226,15452,14832,15498,14921,17328,16887, +14866,16391,14521,13410,16377,14977,16010,13409,14396,13941,13885,13074, +20679, 4310,13073,20678, 4309, 4308,22776,16314,15300,21972, 7379,13072, + 4531,15564,22133, 6475,15870,15563,15825,13599,13511,15764, 6771, 6670, + 6678, 6486, 7784,13448,13897, 3266, 3424,42761,42776, 6929, 5264, 2924, + 2381,18833,43481, 8713, 2380, 2379, 2962,19078,42868,18806,43450, 2923, + 1016, 1058,35100,29992, 1044,35096,29988,15561,22131,35097,29989, 1040, + 2404, 1034, 1042, 1054, 1028, 5115, 5117,16064,22585,16073, 4297,22594, + 4296,27926, 4624, 6948, 5294,15252,21930,15259, 7332,21937, 7339,27507, + 8352,14813,14857,14970,14969,42775,13447,13896,13446,13895, 7110, 5369, + 2980, 8377, 7739, 7738,19111,19110,10739,10738,18987,43158, 2942, 8712, + 4563,13639,21187, 4554,13904, 4195, 4381,15070,21780, 4533,13903,14067, +13957,16938,16937,42132,42573,17002,17225,15451,14920,15497,14831,14919, +15409,22043, 7462,13305,20963, 6811,13304,20962, 6657,16196,22691, 6711, +13303,13986,13985,13984,17224,14918,14830,42689,42380,42688,42379, 4429, +13311,20969, 4428,13977,16936,13307,20965, 4423,13509,37779, 4899,13507, +37777, 4897,13983,42687,42378,42373,42682,13988,42377,42686,42691,42382, + 9078,23228,17119, 7511,22094,15487,15440,22073, 7490,13115,20712, 6824, +42802, 8376, 8375, 7849,22118,15548,13826,13445,13894,13114,13628, 2232, +21214,13743,13651,21291, 2250, 6477,21167,15144,13606,21841, 7270,13956, +21399, 2214, 2231,21355,13867,15143,21840, 7269, 6483,21334,13833,13955, + 4574,13113,13949, 4571, 4570,13731,21281, 4553,13168,13737,21286, 2230, +13742,21290, 2249,13954,21398, 2213,13948,21396, 2229,13112,20711, 6735, +13940,15265,21943,15066,21776,15085,21795,30243,35306,15560,22130, 4548, +29765,34712,29750,34697, 2378, 5130, 5127,43480,18832, 2377,35094,29986, + 2376,35090,29982,15558,22128,35091,29983, 2403,15077,21787,30235,35299, +30246,35309, 8342,13111,20710, 6777,13110,20709, 7804, 4550,13208,20827, + 4380,18680,42605, 4379,13646,18934,42986, 8312, 1778,42238,42611,13167, +20780, 4359, 7035, 5307,42741, 1710, 1626, 8327, 8326, 2375, 8340, 8325, + 7615, 7612,19074,19071,10696,10693, 4562,13166, 8224, 8659,19004,43178, +15330,21997, 8664, 8226, 2922, 2374, 8223, 8658, 5467, 955, 6059, 953, + 5464, 959, 6056, 957, 8661, 8663, 8218, 8221,14243,14242,16236,16235, +32298,32297, 8076, 6069,42820,42819, 8383,10641,19007,10640, 6755,19006, + 6754,15343,22008, 7135, 5491,42828, 2373, 8387, 8386, 7793, 7792,19130, +19129,10758,10757,19123,42907,43185,43523,42818,42906, 8672, 8675, 1503, + 6071, 5483, 1507,32302, 7134, 5490, 8080, 6089,19017,43192,43191,43528, +43190,43527,42827,42913, 8385, 7791, 7790,19128,19127,10756,10755,10651, +19016,10648, 6766,19013, 6763, 8233, 8236,42911,42825, 5497, 1549, 6093, + 1539, 5496, 1548, 6092, 1538,15069,21779,15332,21999,15083,21793,15090, +21800,15088,21798,15674,22221,15557,22127,15556,22126,15559,22129,15555, +22125,15078,21788,15080,21790,15076,21786,15554,22124,15562,22132,15553, +22123,15552,22122,15074,21784,15073,21783,15184,21867,15949,22485,15948, +22484,15988,15219,22525,21900,27872,27463,15985,15216,27869,22522,21897, +27460,27857,27448,27849,27440,25615,27633,27608,21778,15068,27834,27425, +27765,27606,15970,15201,22507,21882,27833,27424,15969,15200,27899,27898, +22541,22540,22506,21881,27490,27489,16004,16003,27832,27423,21916,21915, +15235,15234,27897,27488 +}; + + +const int s_nDataSize3 = 24772; +unsigned int s_Data3[24772] = { +//Output priorities (total = 24772): +10, 9, 12, 6, 11, 14, 4, 1, 7, 5, 2, 3, 13, 8, 0, +0, 1, 2, 219, 218, 76, 217, 216, 77, 1, 0, 74, 78, 79, 75, +70, 71, 72, 68, 73, 69, 310, 299, 296, 331, 297, 332, 114, 26, 298, +340, 330, 336, 338, 339, 62, 112, 328, 334, 329, 335, 113, 337, 327, 333, +115, 60, 27, 61, 63, 273, 215, 36, 213, 31, 35, 39, 319, 312, 320, +323, 324, 343, 157, 345, 28, 178, 32, 59, 269, 58, 309, 305, 275, 271, +308, 304, 34, 117, 181, 129, 154, 211, 30, 38, 177, 193, 55, 130, 268, +33, 303, 174, 29, 37, 119, 212, 143, 188, 66, 270, 141, 183, 194, 179, +126, 261, 190, 267, 344, 346, 272, 189, 173, 274, 51, 322, 321, 342, 315, +214, 311, 14, 57, 223, 348, 125, 176, 192, 317, 280, 314, 165, 160, 175, +326, 127, 17, 247, 172, 262, 5, 231, 99, 138, 124, 54, 301, 325, 167, +15, 43, 205, 47, 122, 147, 292, 295, 83, 106, 86, 87, 220, 131, 347, +293, 150, 209, 233, 67, 116, 148, 156, 171, 180, 191, 256, 195, 341, 128, +277, 291, 281, 289, 294, 313, 102, 46, 103, 207, 229, 236, 240, 224, 227, +249, 170, 49, 251, 258, 318, 133, 197, 278, 2, 56, 252, 265, 254, 20, +142, 151, 316, 164, 121, 162, 41, 107, 139, 203, 288, 302, 48, 52, 110, +53, 64, 4, 16, 284, 135, 307, 3, 40, 155, 202, 23, 93, 22, 92, +290, 65, 210, 50, 98, 208, 94, 123, 137, 187, 225, 7, 10, 120, 109, +263, 287, 186, 108, 152, 264, 90, 253, 96, 97, 136, 200, 118, 140, 300, +306, 185, 6, 11, 89, 259, 85, 101, 132, 196, 24, 45, 260, 244, 91, +18, 104, 232, 19, 44, 105, 184, 21, 84, 226, 250, 283, 279, 286, 158, +248, 257, 255, 80, 169, 13, 100, 81, 168, 199, 238, 9, 12, 82, 182, +201, 266, 146, 204, 230, 239, 241, 159, 221, 285, 134, 88, 242, 246, 8, +144, 222, 149, 161, 228, 237, 276, 95, 206, 282, 163, 198, 243, 235, 245, +42, 166, 25, 111, 145, 153, 234, 13, 0, 1, 8, 3, 11, 7, 9, +2, 12, 4, 6, 5, 10, 0, 61, 62, 0, 2, 3, 5, 6, 8, +15, 17, 1, 4, 7, 9, 10, 11, 12, 13, 14, 16, 18, 19, 20, +21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, +36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, +51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 63, 64, 65, 66, 67, +68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 4, 5, +2, 0, 1, 3, 7, 10, 8, 11, 6, 9, 97, 100, 22, 123, 124, +125, 98, 101, 40, 39, 66, 72, 75, 69, 68, 74, 21, 41, 67, 73, +77, 30, 71, 23, 106, 36, 54, 55, 63, 96, 32, 99, 58, 59, 65, +38, 107, 27, 17, 56, 57, 64, 70, 76, 29, 15, 31, 122, 102, 25, +48, 49, 50, 51, 52, 53, 26, 28, 103, 37, 127, 104, 120, 121, 24, +33, 46, 47, 62, 112, 113, 116, 105, 20, 13, 126, 128, 35, 34, 19, +42, 43, 44, 45, 60, 61, 18, 79, 84, 91, 16, 14, 82, 89, 94, +85, 119, 83, 88, 95, 118, 78, 90, 81, 86, 93, 12, 80, 87, 92, +108, 109, 110, 111, 114, 115, 117, 148, 542, 149, 147, 303, 531, 555, 573, +574, 532, 556, 150, 153, 155, 578, 304, 560, 536, 151, 154, 157, 534, 558, +576, 533, 538, 557, 575, 547, 551, 570, 305, 568, 306, 540, 541, 544, 546, +550, 553, 562, 564, 565, 571, 552, 554, 572, 535, 559, 577, 537, 561, 569, +539, 543, 545, 548, 549, 563, 566, 567, 308, 307, 152, 156, 158, 382, 144, +128, 145, 438, 446, 450, 458, 462, 470, 474, 482, 492, 500, 504, 510, 516, +522, 530, 204, 394, 528, 381, 397, 480, 498, 396, 400, 436, 444, 448, 456, +460, 468, 472, 490, 502, 508, 514, 520, 286, 388, 393, 294, 403, 273, 384, +385, 387, 391, 399, 408, 313, 317, 347, 354, 414, 419, 426, 25, 88, 127, +130, 198, 275, 336, 483, 126, 281, 283, 341, 432, 299, 325, 390, 402, 415, +416, 417, 418, 427, 428, 116, 124, 134, 142, 221, 229, 298, 479, 486, 497, +527, 24, 87, 227, 311, 315, 329, 353, 506, 512, 518, 30, 34, 41, 196, +300, 484, 48, 104, 186, 191, 264, 335, 343, 363, 234, 276, 441, 443, 453, +455, 465, 467, 477, 495, 525, 222, 269, 476, 494, 524, 395, 89, 140, 413, +420, 425, 481, 499, 505, 511, 517, 529, 200, 257, 327, 398, 401, 440, 445, +452, 457, 464, 469, 32, 36, 42, 47, 345, 365, 435, 442, 447, 454, 459, +466, 471, 478, 489, 496, 501, 507, 513, 519, 526, 202, 323, 146, 170, 177, +179, 248, 255, 368, 380, 206, 122, 132, 258, 279, 288, 296, 349, 375, 434, +46, 114, 165, 180, 201, 219, 243, 250, 297, 405, 429, 33, 38, 43, 172, +203, 208, 346, 392, 404, 410, 485, 488, 183, 216, 261, 348, 386, 430, 20, +26, 65, 100, 131, 162, 167, 174, 182, 188, 189, 194, 210, 218, 240, 252, +260, 266, 272, 284, 360, 372, 383, 423, 12, 17, 57, 92, 99, 129, 213, +215, 230, 231, 278, 291, 293, 339, 389, 406, 411, 422, 15, 60, 62, 97, +117, 119, 135, 199, 224, 225, 236, 245, 267, 302, 321, 326, 377, 407, 102, +137, 175, 274, 431, 412, 421, 424, 173, 238, 246, 251, 253, 262, 270, 282, +366, 370, 378, 437, 439, 449, 451, 461, 463, 473, 475, 491, 493, 503, 509, +515, 521, 523, 0, 1, 81, 82, 106, 160, 168, 184, 185, 192, 193, 263, +271, 277, 322, 358, 22, 28, 31, 40, 67, 98, 103, 105, 138, 254, 316, +319, 355, 328, 10, 14, 49, 52, 59, 70, 73, 90, 112, 133, 220, 228, +232, 233, 301, 309, 314, 331, 333, 337, 344, 351, 35, 37, 44, 163, 342, +409, 433, 487, 259, 27, 29, 39, 50, 161, 164, 176, 178, 181, 187, 190, +197, 205, 239, 241, 242, 324, 332, 359, 361, 362, 371, 373, 374, 6, 7, +45, 55, 56, 75, 77, 79, 80, 108, 109, 159, 166, 169, 171, 195, 217, +237, 247, 249, 256, 265, 268, 280, 334, 340, 350, 357, 367, 369, 379, 2, +3, 9, 18, 19, 21, 23, 53, 63, 64, 66, 68, 72, 76, 83, 84, +93, 95, 96, 101, 107, 111, 120, 121, 123, 125, 139, 141, 143, 212, 244, +290, 295, 310, 312, 318, 320, 330, 338, 352, 356, 4, 5, 8, 11, 13, +51, 54, 58, 61, 69, 71, 74, 78, 85, 86, 94, 110, 113, 115, 136, +207, 209, 211, 214, 223, 226, 235, 285, 287, 289, 292, 364, 376, 16, 91, +118, 0, 3, 19, 149, 96, 20, 150, 5, 1, 6, 4, 2, 147, 93, +91, 145, 148, 95, 146, 85, 55, 66, 76, 59, 73, 81, 51, 61, 64, +54, 58, 92, 94, 63, 173, 62, 86, 65, 75, 60, 74, 82, 56, 52, +53, 57, 171, 167, 160, 159, 170, 72, 141, 162, 172, 28, 68, 29, 140, +168, 27, 70, 126, 139, 69, 163, 89, 137, 166, 71, 169, 129, 142, 164, +116, 135, 143, 90, 67, 113, 121, 165, 161, 131, 123, 125, 133, 30, 7, +138, 10, 117, 119, 11, 120, 127, 134, 130, 132, 115, 124, 114, 136, 9, +118, 33, 77, 157, 158, 8, 12, 88, 155, 156, 34, 78, 99, 97, 128, +36, 44, 87, 35, 43, 15, 13, 17, 122, 21, 23, 25, 144, 37, 45, +47, 103, 32, 42, 80, 39, 49, 83, 108, 40, 50, 84, 38, 46, 48, +31, 41, 79, 18, 98, 22, 24, 26, 14, 16, 105, 107, 100, 152, 111, +109, 104, 101, 110, 112, 106, 153, 102, 151, 154, 0, 1, 3, 4, 2, +12, 13, 10, 11, 14, 9, 6, 5, 7, 8, 21, 24, 23, 22, 20, +19, 15, 16, 17, 18, 0, 1, 3, 2, 108, 109, 139, 153, 122, 96, +178, 97, 126, 95, 101, 100, 94, 174, 140, 172, 175, 173, 5, 36, 154, +88, 83, 80, 35, 161, 151, 19, 11, 6, 147, 143, 34, 176, 123, 37, +169, 170, 171, 163, 164, 165, 166, 167, 168, 155, 156, 157, 158, 159, 160, +82, 162, 177, 152, 81, 111, 7, 12, 20, 128, 4, 93, 21, 64, 13, +148, 60, 62, 118, 10, 18, 33, 144, 30, 48, 135, 149, 86, 114, 99, +124, 129, 130, 131, 61, 63, 65, 8, 14, 16, 22, 24, 26, 28, 73, +75, 77, 90, 56, 72, 74, 76, 78, 51, 53, 55, 57, 59, 67, 69, +71, 79, 89, 91, 50, 52, 54, 58, 66, 68, 70, 92, 107, 39, 41, +43, 45, 47, 110, 103, 105, 120, 145, 127, 38, 40, 42, 44, 46, 137, +102, 104, 106, 31, 32, 49, 9, 15, 17, 23, 29, 87, 25, 27, 150, +141, 142, 84, 85, 146, 98, 116, 119, 133, 115, 121, 136, 132, 125, 117, +112, 113, 138, 134, 2, 0, 1, 3, 8, 6, 7, 4, 5, 9, 10, +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +15, 16, 2, 1, 4, 8, 7, 9, 6, 0, 5, 3, 10, 109, 107, +108, 97, 105, 28, 30, 21, 81, 26, 32, 106, 20, 24, 35, 22, 34, +96, 104, 62, 27, 111, 11, 18, 23, 36, 83, 37, 12, 95, 17, 46, +56, 25, 40, 42, 87, 89, 14, 16, 13, 29, 103, 82, 110, 15, 19, +31, 33, 102, 38, 66, 67, 68, 69, 70, 71, 72, 85, 41, 115, 117, +91, 93, 94, 99, 101, 43, 73, 86, 88, 114, 116, 50, 52, 74, 76, +77, 78, 79, 39, 113, 44, 45, 47, 48, 49, 51, 53, 54, 55, 57, +58, 59, 60, 61, 63, 64, 65, 75, 80, 84, 90, 92, 98, 100, 112, +0, 1, 20, 17, 18, 12, 19, 16, 21, 15, 23, 14, 22, 13, 0, +6, 5, 11, 3, 9, 2, 8, 1, 7, 4, 10, 3, 4, 11, 14, +17, 32, 0, 1, 2, 5, 6, 7, 8, 9, 10, 12, 13, 15, 16, +18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, +34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 2, 3, 0, 1, +15, 13, 17, 21, 77, 76, 33, 30, 34, 110, 105, 114, 118, 31, 32, +35, 101, 100, 16, 131, 12, 14, 130, 135, 132, 112, 120, 116, 111, 115, +119, 79, 117, 113, 121, 20, 133, 80, 134, 78, 81, 44, 109, 49, 47, +124, 46, 28, 48, 126, 26, 87, 89, 90, 88, 6, 5, 7, 9, 11, +19, 36, 38, 40, 42, 86, 91, 18, 4, 10, 39, 8, 37, 41, 43, +45, 60, 127, 27, 61, 106, 129, 59, 108, 128, 53, 54, 57, 58, 62, +50, 29, 56, 63, 52, 55, 107, 122, 123, 125, 51, 64, 65, 66, 67, +68, 69, 70, 71, 72, 73, 74, 75, 82, 83, 84, 85, 92, 93, 94, +95, 96, 97, 98, 99, 102, 103, 104, 23, 25, 24, 22, 175, 174, 176, +162, 158, 165, 124, 166, 15, 155, 126, 160, 120, 121, 122, 123, 125, 127, +128, 129, 153, 157, 171, 152, 163, 170, 96, 97, 108, 0, 3, 6, 9, +12, 66, 69, 72, 75, 78, 81, 130, 131, 150, 151, 156, 159, 161, 168, +169, 173, 177, 154, 164, 167, 172, 1, 2, 4, 5, 7, 8, 10, 11, +13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, +29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, +44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, +59, 60, 61, 62, 63, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, +79, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, +95, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, +113, 114, 115, 116, 117, 118, 119, 132, 133, 134, 135, 136, 137, 138, 139, +140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 178, 179, 0, 1, 2, +8, 6, 7, 3, 5, 4, 0, 1305, 1308, 540, 545, 558, 563, 564, 569, +570, 575, 576, 581, 582, 587, 588, 593, 594, 599, 600, 605, 606, 611, 612, +617, 618, 623, 624, 629, 630, 635, 636, 641, 642, 647, 648, 653, 654, 657, +662, 663, 668, 669, 672, 677, 678, 681, 684, 687, 690, 0, 1, 2, 3, +4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, +19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, +34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, +49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, +64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, +79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, +94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, +109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, +124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, +139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, +154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, +169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, +184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, +199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, +214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, +229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, +244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, +259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, +274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, +289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, +304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, +319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, +334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, +349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, +364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, +379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, +394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, +409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, +424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, +439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, +454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, +469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, +484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, +499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, +514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, +529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 541, 542, 543, 544, +546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 559, 560, 561, +562, 565, 566, 567, 568, 571, 572, 573, 574, 577, 578, 579, 580, 583, 584, +585, 586, 589, 590, 591, 592, 595, 596, 597, 598, 601, 602, 603, 604, 607, +608, 609, 610, 613, 614, 615, 616, 619, 620, 621, 622, 625, 626, 627, 628, +631, 632, 633, 634, 637, 638, 639, 640, 643, 644, 645, 646, 649, 650, 651, +652, 655, 656, 658, 659, 660, 661, 664, 665, 666, 667, 670, 671, 673, 674, +675, 676, 679, 680, 682, 683, 685, 686, 688, 689, 691, 692, 693, 694, 695, +696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, +711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, +726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, +741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, +756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, +771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, +786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, +801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, +816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, +831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, +846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, +861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, +876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, +891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, +906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, +921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, +936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, +951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, +966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, +981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, +996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, +1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, +1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, +1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, +1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, +1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, +1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, +1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, +1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, +1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, +1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, +1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, +1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, +1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, +1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, +1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, +1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, +1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, +1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, +1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, +1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1306, 1307, 1309, 1310, 158, 161, +164, 167, 170, 173, 74, 77, 86, 89, 0, 3, 12, 15, 24, 27, 36, +39, 48, 51, 60, 63, 110, 113, 122, 125, 134, 137, 146, 149, 76, 88, +156, 160, 162, 165, 169, 171, 2, 132, 175, 26, 38, 50, 62, 72, 83, +84, 95, 108, 120, 78, 90, 96, 104, 174, 14, 144, 176, 9, 21, 33, +45, 57, 69, 79, 81, 91, 93, 98, 106, 119, 131, 143, 155, 59, 71, +157, 159, 163, 166, 168, 172, 99, 101, 103, 105, 11, 35, 47, 73, 75, +80, 82, 85, 87, 92, 94, 97, 100, 102, 107, 117, 129, 141, 8, 20, +23, 32, 44, 56, 68, 114, 126, 138, 150, 153, 179, 186, 191, 198, 180, +192, 1, 4, 5, 6, 7, 10, 13, 16, 17, 18, 19, 22, 25, 28, +29, 30, 31, 34, 37, 40, 41, 42, 43, 46, 49, 52, 53, 54, 55, +58, 61, 64, 65, 66, 67, 70, 109, 111, 112, 115, 116, 118, 121, 123, +124, 127, 128, 130, 133, 135, 136, 139, 140, 142, 145, 147, 148, 151, 152, +154, 213, 214, 215, 216, 177, 189, 184, 196, 221, 222, 223, 224, 178, 181, +182, 183, 185, 187, 188, 190, 193, 194, 195, 197, 199, 200, 201, 202, 203, +204, 205, 206, 207, 208, 209, 210, 211, 212, 217, 218, 219, 220, 2, 4, +6, 8, 10, 12, 32, 34, 36, 46, 48, 52, 54, 56, 58, 60, 62, +64, 86, 87, 88, 105, 106, 107, 108, 109, 112, 113, 115, 117, 121, 1, +3, 5, 7, 9, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, +25, 26, 27, 28, 29, 30, 31, 33, 35, 37, 38, 39, 40, 41, 42, +43, 44, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 66, 67, +68, 71, 73, 75, 76, 78, 79, 80, 82, 83, 84, 92, 93, 94, 96, +97, 98, 99, 100, 101, 102, 103, 104, 110, 111, 114, 116, 118, 119, 120, +122, 124, 126, 127, 129, 131, 141, 143, 145, 146, 148, 150, 152, 153, 156, +166, 167, 170, 173, 174, 176, 180, 182, 184, 186, 0, 22, 24, 50, 69, +70, 72, 74, 77, 81, 85, 89, 90, 91, 95, 123, 125, 128, 130, 132, +133, 134, 135, 136, 137, 138, 139, 140, 142, 144, 147, 149, 151, 154, 155, +157, 158, 159, 160, 161, 162, 163, 164, 165, 168, 169, 171, 172, 175, 177, +178, 179, 181, 183, 185, 122, 85, 89, 92, 106, 118, 136, 148, 156, 164, +27, 35, 37, 38, 52, 57, 62, 67, 71, 83, 55, 65, 68, 121, 26, +53, 63, 66, 80, 82, 105, 114, 119, 123, 137, 143, 14, 25, 30, 31, +100, 28, 117, 108, 134, 3, 12, 34, 36, 39, 40, 45, 46, 51, 59, +60, 61, 73, 74, 75, 76, 77, 78, 84, 86, 87, 88, 90, 91, 93, +94, 95, 110, 112, 115, 116, 120, 127, 128, 130, 132, 141, 142, 152, 175, +58, 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 16, +17, 18, 19, 20, 21, 22, 23, 24, 29, 32, 33, 41, 42, 43, 44, +47, 48, 49, 50, 54, 56, 64, 69, 70, 72, 79, 81, 96, 97, 98, +99, 101, 102, 103, 104, 107, 109, 111, 113, 124, 125, 126, 129, 131, 133, +135, 138, 139, 140, 144, 145, 146, 147, 149, 150, 151, 153, 154, 155, 157, +158, 159, 160, 161, 162, 163, 165, 166, 167, 168, 169, 170, 171, 172, 173, +174, 176, 177, 23, 29, 5, 24, 25, 26, 27, 28, 30, 31, 0, 1, +2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, +18, 19, 20, 21, 22, 32, 83, 84, 96, 99, 100, 16, 85, 98, 18, +26, 27, 37, 40, 49, 52, 17, 51, 55, 57, 97, 8, 3, 19, 9, +50, 56, 58, 10, 53, 72, 82, 87, 89, 91, 14, 118, 129, 12, 81, +86, 88, 90, 130, 11, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31, +32, 33, 34, 35, 36, 43, 67, 68, 69, 93, 95, 41, 45, 47, 4, +5, 6, 13, 38, 117, 128, 71, 0, 1, 2, 15, 39, 92, 94, 65, +70, 122, 123, 127, 7, 42, 44, 46, 48, 54, 59, 60, 61, 62, 63, +64, 66, 105, 106, 109, 110, 111, 112, 113, 114, 121, 124, 126, 73, 74, +75, 76, 77, 78, 79, 80, 101, 102, 103, 104, 107, 108, 115, 116, 119, +120, 125, 18, 24, 5, 7, 9, 13, 0, 1, 2, 3, 4, 6, 8, +10, 11, 12, 14, 15, 16, 17, 19, 20, 21, 22, 23, 25, 26, 27, +28, 29, 30, 38, 37, 3, 2, 39, 4, 40, 5, 109, 110, 111, 99, +107, 97, 105, 140, 141, 142, 0, 98, 106, 1, 100, 108, 34, 35, 36, +10, 11, 42, 46, 50, 54, 58, 62, 66, 70, 13, 17, 21, 30, 6, +88, 90, 96, 102, 113, 115, 121, 123, 125, 135, 137, 139, 9, 14, 18, +22, 33, 44, 48, 52, 56, 60, 64, 68, 72, 116, 126, 130, 43, 47, +51, 55, 59, 63, 67, 71, 85, 91, 93, 103, 80, 82, 83, 73, 75, +76, 119, 129, 133, 12, 16, 20, 31, 7, 41, 45, 49, 53, 57, 61, +65, 69, 117, 127, 131, 87, 89, 95, 101, 112, 114, 120, 122, 124, 134, +136, 138, 86, 92, 94, 104, 118, 128, 132, 79, 81, 84, 74, 77, 78, +8, 15, 19, 23, 32, 24, 25, 28, 26, 27, 29, 0, 1, 2, 3, +4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, +19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, +34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, +49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, +64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, +79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, +94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, +109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, +124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, +139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, +154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 34, 5, 6, 7, +8, 9, 10, 11, 12, 33, 47, 2, 4, 19, 20, 21, 36, 37, 38, +40, 41, 0, 1, 3, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, +26, 27, 28, 29, 30, 31, 32, 35, 39, 42, 43, 44, 45, 46, 48, +49, 50, 144, 145, 0, 141, 142, 143, 155, 154, 139, 140, 146, 147, 150, +151, 76, 82, 83, 84, 85, 86, 87, 158, 131, 77, 132, 159, 23, 24, +25, 26, 27, 28, 32, 33, 73, 79, 91, 95, 1, 3, 5, 12, 13, +14, 15, 16, 17, 18, 19, 20, 21, 22, 29, 30, 31, 34, 102, 104, +106, 108, 112, 113, 114, 115, 116, 117, 118, 119, 138, 37, 39, 41, 43, +48, 50, 52, 54, 2, 4, 6, 7, 8, 9, 10, 11, 36, 38, 40, +42, 44, 45, 46, 47, 56, 57, 58, 59, 60, 62, 64, 66, 68, 70, +72, 74, 75, 78, 80, 81, 88, 89, 90, 92, 93, 94, 96, 97, 98, +100, 103, 105, 107, 109, 137, 160, 161, 162, 35, 49, 51, 53, 55, 61, +63, 65, 67, 69, 71, 99, 101, 110, 111, 120, 121, 122, 123, 124, 125, +126, 127, 128, 129, 130, 133, 134, 135, 136, 148, 149, 152, 153, 156, 157, +4, 11, 5, 6, 7, 8, 10, 9, 12, 17, 18, 19, 21, 2, 3, +0, 1, 13, 14, 15, 16, 20, 28, 32, 34, 38, 40, 22, 23, 24, +25, 26, 27, 29, 30, 31, 33, 35, 36, 37, 39, 41, 73, 69, 95, +11, 72, 14, 12, 13, 93, 71, 74, 94, 87, 81, 86, 79, 60, 96, +98, 88, 59, 82, 97, 44, 46, 54, 68, 92, 100, 45, 53, 67, 43, +91, 99, 80, 89, 77, 1, 3, 9, 5, 6, 7, 8, 70, 28, 83, +22, 34, 42, 49, 51, 57, 17, 23, 29, 37, 63, 19, 25, 31, 39, +48, 50, 52, 56, 58, 62, 64, 66, 84, 76, 90, 78, 75, 85, 4, +0, 2, 10, 20, 26, 32, 36, 40, 15, 61, 16, 18, 24, 30, 35, +38, 47, 55, 65, 21, 27, 33, 41, 0, 1, 2, 3, 4, 5, 6, +7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, +22, 23, 24, 25, 26, 40, 42, 3, 1, 51, 5, 49, 48, 22, 24, +4, 2, 52, 50, 76, 78, 80, 94, 96, 98, 23, 47, 26, 27, 63, +64, 65, 70, 71, 21, 77, 79, 81, 17, 20, 33, 37, 41, 43, 57, +55, 56, 58, 59, 60, 61, 62, 18, 19, 25, 32, 36, 95, 97, 99, +0, 38, 39, 54, 67, 69, 73, 75, 85, 87, 91, 93, 53, 66, 84, +86, 90, 89, 6, 7, 11, 12, 13, 82, 83, 68, 72, 74, 92, 8, +9, 10, 14, 15, 16, 28, 29, 30, 31, 34, 35, 44, 45, 46, 88, +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, +30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, +45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, +60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, +75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, +90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, +105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, +120, 121, 122, 123, 124, 125, 0, 1, 2, 3, 4, 5, 6, 7, 8, +9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, +24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, +39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, +69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, +84, 85, 86, 87, 88, 89, 90, 91, 92, 0, 1, 2, 3, 4, 5, +6, 7, 8, 1, 3, 43, 0, 2, 4, 5, 6, 7, 8, 9, 10, +11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, +26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, +41, 42, 44, 45, 46, 89, 90, 0, 1, 2, 3, 4, 5, 6, 7, +8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, +23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, +38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, +53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, +68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, +83, 84, 85, 86, 87, 88, 91, 92, 93, 94, 95, 96, 97, 98, 99, +100, 101, 102, 103, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, +11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, +26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, +9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, +24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, +39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, +69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 186, 189, 174, +185, 179, 180, 177, 181, 188, 191, 60, 63, 175, 183, 176, 184, 64, 61, +62, 65, 178, 182, 187, 190, 130, 142, 154, 166, 104, 110, 116, 13, 24, +36, 78, 122, 136, 148, 160, 172, 7, 18, 30, 84, 102, 108, 114, 105, +111, 117, 120, 123, 74, 86, 98, 107, 113, 119, 125, 1, 9, 20, 32, +44, 45, 55, 75, 99, 103, 109, 115, 0, 6, 19, 31, 42, 43, 54, +72, 73, 85, 96, 97, 137, 149, 161, 173, 2, 46, 47, 56, 76, 77, +100, 101, 127, 133, 139, 145, 151, 157, 163, 169, 8, 21, 33, 87, 106, +112, 118, 121, 124, 128, 129, 140, 141, 152, 153, 3, 4, 15, 26, 38, +48, 49, 50, 51, 57, 58, 66, 67, 68, 69, 80, 90, 91, 92, 93, +126, 131, 134, 138, 143, 146, 150, 155, 158, 162, 167, 170, 10, 11, 22, +23, 34, 35, 88, 89, 135, 147, 159, 171, 5, 12, 14, 16, 17, 25, +27, 28, 29, 37, 39, 40, 41, 52, 53, 59, 70, 71, 79, 81, 82, +83, 94, 95, 132, 144, 156, 164, 165, 168, 756, 759, 761, 104, 105, 640, +647, 700, 107, 757, 760, 102, 222, 224, 310, 420, 431, 441, 460, 468, 491, +494, 501, 558, 571, 654, 666, 683, 722, 7, 10, 31, 34, 60, 65, 162, +165, 178, 434, 467, 477, 480, 550, 569, 657, 671, 682, 718, 751, 13, 37, +54, 175, 181, 262, 265, 313, 385, 465, 551, 563, 641, 645, 701, 719, 253, +316, 333, 339, 364, 365, 369, 371, 436, 439, 461, 496, 499, 505, 514, 520, +522, 577, 585, 588, 598, 601, 608, 617, 622, 685, 727, 733, 223, 240, 191, +709, 92, 115, 144, 199, 248, 252, 290, 307, 338, 372, 382, 410, 475, 508, +513, 515, 527, 547, 566, 567, 572, 580, 587, 590, 595, 604, 606, 615, 619, +688, 716, 725, 730, 735, 739, 747, 11, 16, 22, 23, 35, 40, 46, 47, +52, 53, 59, 64, 88, 89, 94, 103, 118, 121, 124, 138, 143, 149, 163, +164, 179, 184, 190, 202, 205, 208, 225, 244, 245, 250, 259, 268, 280, 281, +284, 285, 291, 322, 328, 332, 340, 373, 379, 388, 400, 401, 404, 405, 411, +421, 426, 428, 429, 437, 442, 450, 455, 457, 469, 478, 481, 488, 497, 502, +529, 530, 536, 537, 540, 553, 564, 570, 625, 626, 630, 635, 637, 643, 655, +656, 668, 670, 678, 681, 691, 692, 699, 703, 704, 724, 738, 749, 750, 753, +560, 574, 723, 85, 331, 470, 101, 217, 633, 642, 697, 742, 745, 754, 19, +43, 48, 187, 324, 97, 218, 296, 416, 130, 137, 166, 226, 241, 271, 279, +319, 327, 391, 399, 440, 482, 142, 283, 325, 403, 443, 453, 485, 758, 0, +24, 67, 298, 336, 346, 464, 489, 504, 507, 510, 516, 518, 521, 523, 524, +535, 552, 559, 573, 576, 579, 582, 583, 591, 592, 594, 599, 602, 603, 607, +611, 614, 616, 620, 623, 632, 644, 649, 651, 661, 663, 667, 669, 684, 687, +696, 708, 720, 726, 729, 732, 736, 1, 2, 3, 4, 5, 6, 8, 9, +12, 14, 15, 17, 18, 20, 21, 25, 26, 27, 28, 29, 30, 32, 33, +36, 38, 39, 41, 42, 44, 45, 49, 50, 51, 55, 56, 57, 58, 61, +62, 63, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, +80, 81, 82, 83, 84, 86, 87, 90, 91, 93, 95, 96, 98, 99, 100, +106, 108, 109, 110, 111, 112, 113, 114, 116, 117, 119, 120, 122, 123, 125, +126, 127, 128, 129, 131, 132, 133, 134, 135, 136, 139, 140, 141, 145, 146, +147, 148, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 167, +168, 169, 170, 171, 172, 173, 174, 176, 177, 180, 182, 183, 185, 186, 188, +189, 192, 193, 194, 195, 196, 197, 198, 200, 201, 203, 204, 206, 207, 209, +210, 211, 212, 213, 214, 215, 216, 219, 220, 221, 227, 228, 229, 230, 231, +232, 233, 234, 235, 236, 237, 238, 239, 242, 243, 246, 247, 249, 251, 254, +255, 256, 257, 258, 260, 261, 263, 264, 266, 267, 269, 270, 272, 273, 274, +275, 276, 277, 278, 282, 286, 287, 288, 289, 292, 293, 294, 295, 297, 299, +300, 301, 302, 303, 304, 305, 306, 308, 309, 311, 312, 314, 315, 317, 318, +320, 321, 323, 326, 329, 330, 334, 335, 337, 341, 342, 343, 344, 345, 347, +348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, +363, 366, 367, 368, 370, 374, 375, 376, 377, 378, 380, 381, 383, 384, 386, +387, 389, 390, 392, 393, 394, 395, 396, 397, 398, 402, 406, 407, 408, 409, +412, 413, 414, 415, 417, 418, 419, 422, 423, 424, 425, 427, 430, 432, 433, +435, 438, 444, 445, 446, 447, 448, 449, 451, 452, 454, 456, 458, 459, 462, +463, 466, 471, 472, 473, 474, 476, 479, 483, 484, 486, 487, 490, 492, 493, +495, 498, 500, 503, 506, 509, 511, 512, 517, 519, 525, 526, 528, 531, 532, +533, 534, 538, 539, 541, 542, 543, 544, 545, 546, 548, 549, 554, 555, 556, +557, 561, 562, 565, 568, 575, 578, 581, 584, 586, 589, 593, 596, 597, 600, +605, 609, 610, 612, 613, 618, 621, 624, 627, 628, 629, 631, 634, 636, 638, +639, 646, 648, 650, 652, 653, 658, 659, 660, 662, 664, 665, 672, 673, 674, +675, 676, 677, 679, 680, 686, 689, 690, 693, 694, 695, 698, 702, 705, 706, +707, 710, 711, 712, 713, 714, 715, 717, 721, 728, 731, 734, 737, 740, 741, +743, 744, 746, 748, 752, 755, 325, 326, 324, 15, 258, 103, 123, 3, 9, +124, 331, 14, 259, 16, 2, 8, 337, 102, 335, 340, 4, 10, 17, 120, +246, 247, 276, 333, 334, 33, 72, 128, 338, 5, 11, 76, 105, 127, 0, +13, 74, 73, 122, 1, 75, 7, 300, 336, 364, 6, 12, 228, 235, 263, +265, 270, 280, 291, 106, 297, 77, 135, 162, 169, 192, 199, 201, 214, 216, +225, 260, 262, 104, 306, 316, 339, 170, 200, 223, 341, 137, 160, 190, 203, +215, 218, 141, 150, 157, 171, 180, 187, 312, 313, 317, 39, 125, 143, 148, +158, 173, 178, 188, 308, 318, 107, 322, 362, 35, 91, 97, 109, 299, 230, +272, 293, 244, 256, 289, 323, 367, 38, 121, 302, 303, 311, 327, 245, 257, +261, 290, 305, 234, 264, 279, 34, 36, 79, 85, 115, 126, 298, 307, 309, +319, 328, 57, 63, 69, 198, 229, 271, 292, 82, 88, 90, 96, 108, 118, +304, 320, 329, 37, 41, 80, 86, 116, 301, 332, 139, 159, 164, 168, 189, +194, 205, 213, 217, 220, 222, 40, 136, 145, 167, 177, 197, 202, 212, 227, +18, 27, 48, 363, 237, 267, 282, 196, 240, 241, 252, 253, 285, 286, 142, +147, 152, 155, 156, 172, 175, 182, 185, 186, 310, 321, 330, 346, 347, 348, +355, 138, 163, 165, 193, 195, 204, 210, 219, 226, 131, 132, 208, 250, 251, +278, 314, 315, 357, 365, 140, 146, 179, 206, 211, 20, 29, 50, 161, 166, +191, 221, 224, 269, 368, 26, 44, 47, 58, 64, 70, 81, 87, 117, 144, +151, 153, 174, 181, 183, 93, 99, 111, 232, 274, 295, 59, 65, 71, 133, +134, 149, 154, 176, 184, 209, 350, 361, 239, 242, 254, 284, 287, 268, 56, +62, 68, 78, 84, 94, 100, 112, 114, 92, 98, 110, 238, 283, 55, 61, +67, 349, 236, 243, 255, 266, 281, 288, 19, 24, 28, 42, 45, 49, 129, +130, 207, 248, 249, 277, 354, 359, 360, 233, 275, 296, 352, 353, 22, 31, +52, 54, 60, 66, 83, 89, 95, 101, 113, 119, 342, 345, 366, 231, 273, +294, 25, 43, 46, 23, 32, 53, 343, 351, 358, 21, 30, 51, 344, 356, +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, +30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, +45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, +60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, +75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, +90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, +105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, +120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, +135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, +150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, +165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, +180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, +195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, +210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, +225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, +240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, +255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, +270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, +285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, +300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, +315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, +330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, +345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, +360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, +375, 376, 377, 19, 29, 33, 45, 86, 88, 90, 92, 18, 27, 31, 47, +82, 103, 37, 41, 55, 87, 11, 35, 39, 43, 49, 51, 53, 57, 61, +63, 89, 91, 105, 109, 114, 20, 9, 13, 107, 28, 30, 32, 34, 46, +48, 78, 84, 133, 135, 93, 112, 134, 136, 36, 40, 62, 66, 80, 38, +42, 44, 50, 52, 54, 56, 58, 64, 127, 131, 137, 1, 15, 16, 21, +22, 102, 111, 113, 128, 132, 138, 23, 25, 59, 68, 70, 94, 69, 3, +4, 6, 7, 10, 104, 106, 108, 110, 121, 123, 67, 24, 26, 60, 122, +124, 72, 76, 81, 96, 85, 74, 98, 129, 83, 125, 0, 2, 5, 8, +12, 14, 17, 71, 73, 75, 77, 79, 95, 97, 99, 100, 126, 65, 130, +101, 118, 116, 120, 115, 117, 119, 219, 220, 221, 127, 131, 135, 139, 228, +229, 230, 231, 232, 233, 234, 235, 222, 223, 224, 225, 226, 227, 236, 237, +238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, +253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 275, +276, 277, 278, 9, 13, 17, 21, 25, 29, 36, 40, 44, 48, 49, 56, +60, 64, 68, 72, 76, 80, 84, 171, 176, 180, 184, 0, 1, 2, 3, +4, 5, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20, 22, +23, 24, 26, 27, 28, 30, 31, 32, 33, 34, 35, 37, 38, 39, 41, +42, 43, 45, 46, 47, 50, 51, 52, 53, 54, 55, 57, 58, 59, 61, +62, 63, 65, 66, 67, 69, 70, 71, 73, 74, 75, 77, 78, 79, 81, +82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, +98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, +113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 128, +129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 143, 144, 145, 146, +147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, +162, 163, 164, 165, 166, 167, 168, 169, 170, 172, 173, 174, 175, 177, 178, +179, 181, 182, 183, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, +196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, +211, 212, 213, 214, 215, 216, 217, 218, 267, 268, 269, 270, 271, 272, 273, +274, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 1, 2, +3, 4, 0, 8, 12, 11, 102, 127, 6, 5, 101, 7, 128, 4, 3, +10, 1, 2, 0, 9, 92, 90, 97, 114, 94, 95, 99, 112, 111, 123, +116, 118, 120, 121, 125, 98, 89, 91, 96, 93, 100, 113, 24, 34, 16, +36, 14, 22, 13, 21, 33, 18, 26, 30, 115, 117, 124, 119, 122, 126, +17, 25, 29, 104, 19, 27, 31, 106, 28, 20, 32, 15, 23, 35, 54, +56, 110, 51, 72, 88, 38, 40, 49, 58, 60, 64, 66, 74, 81, 105, +107, 37, 39, 50, 52, 57, 59, 63, 65, 71, 73, 82, 87, 42, 43, +45, 48, 61, 67, 70, 76, 77, 79, 83, 86, 53, 55, 41, 44, 46, +47, 62, 68, 69, 75, 78, 80, 84, 85, 109, 103, 108, 7, 8, 6, +9, 17, 10, 28, 26, 24, 50, 68, 4, 34, 5, 0, 23, 46, 2, +18, 33, 1, 85, 19, 58, 62, 70, 29, 31, 35, 3, 25, 27, 47, +48, 49, 51, 11, 90, 30, 32, 36, 40, 41, 42, 43, 44, 45, 12, +13, 14, 15, 16, 20, 21, 22, 37, 38, 39, 52, 53, 54, 55, 56, +57, 59, 60, 61, 63, 64, 65, 66, 67, 69, 71, 72, 73, 74, 75, +76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 88, 125, +101, 103, 124, 127, 134, 135, 25, 29, 37, 45, 165, 177, 163, 180, 138, +142, 113, 24, 28, 36, 40, 41, 44, 48, 49, 58, 59, 60, 61, 66, +67, 68, 69, 70, 71, 72, 73, 89, 92, 93, 145, 148, 149, 94, 105, +109, 151, 154, 161, 173, 96, 99, 100, 102, 104, 107, 108, 111, 114, 115, +116, 118, 119, 120, 122, 123, 126, 132, 133, 136, 137, 140, 141, 155, 156, +159, 160, 164, 169, 171, 172, 175, 176, 179, 181, 182, 183, 0, 1, 2, +3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, +18, 19, 20, 21, 22, 23, 26, 27, 30, 31, 32, 33, 34, 35, 38, +39, 42, 43, 46, 47, 50, 51, 52, 53, 54, 55, 56, 57, 62, 63, +64, 65, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, +87, 90, 91, 95, 97, 98, 106, 110, 112, 117, 121, 128, 129, 130, 131, +139, 143, 144, 146, 147, 150, 152, 153, 157, 158, 162, 166, 167, 168, 170, +174, 178, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, +13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, +28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 0, 1, 2, 3, +4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, +19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, +34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, +49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, +64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, +79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, +94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, +109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, +124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, +139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, +154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, +169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, +184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, +199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, +214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, +229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, +244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, +259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, +274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, +289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, +304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, +319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, +334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, +349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, +364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, +379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, +394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, +409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, +424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, +439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, +454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, +469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, +484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, +499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, +514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, +529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, +544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, +559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, +574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, +589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, +604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, +619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, +634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, +649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, +664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, +679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, +694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, +709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, +724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, +739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, +754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, +769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, +784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, +799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, +814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, +829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, +844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, +859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, +874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, +889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, +904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, +919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, +934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, +949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, +964, 965, 966, 967, 968, 969, 970, 971, 306, 146, 158, 174, 216, 233, 27, +29, 121, 123, 125, 127, 144, 150, 152, 173, 188, 218, 295, 299, 307, 0, +1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 30, 31, 32, +33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, +48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, +63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, +78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, +93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, +108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 122, 124, +126, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, +142, 143, 145, 147, 148, 149, 151, 153, 154, 155, 156, 157, 159, 160, 161, +162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 175, 176, 177, 178, +179, 180, 181, 182, 183, 184, 185, 186, 187, 189, 190, 191, 192, 193, 194, +195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, +210, 211, 212, 213, 214, 215, 217, 219, 220, 221, 222, 223, 224, 225, 226, +227, 228, 229, 230, 231, 232, 234, 235, 236, 237, 238, 239, 240, 241, 242, +243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, +258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, +273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, +288, 289, 290, 291, 292, 293, 294, 296, 297, 298, 300, 301, 302, 303, 304, +305, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, +322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, +337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, +352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, +367, 368, 369, 370, 371, 372, 373, 374, 76, 106, 77, 107, 125, 115, 126, +60, 61, 71, 59, 96, 99, 110, 89, 70, 58, 25, 27, 33, 35, 86, +87, 72, 75, 79, 94, 112, 95, 100, 73, 74, 78, 101, 102, 105, 109, +88, 26, 32, 34, 103, 104, 108, 24, 97, 98, 113, 114, 44, 64, 69, +36, 38, 41, 43, 47, 54, 57, 63, 66, 111, 37, 39, 40, 42, 45, +46, 55, 56, 62, 65, 67, 68, 90, 92, 5, 11, 9, 84, 8, 4, +10, 2, 48, 50, 52, 81, 82, 0, 6, 12, 14, 85, 80, 83, 49, +51, 53, 91, 93, 118, 121, 124, 3, 17, 18, 21, 22, 29, 30, 1, +7, 13, 15, 116, 119, 122, 129, 16, 19, 20, 23, 28, 31, 117, 120, +123, 127, 128, 130, 3, 4, 5, 6, 25, 26, 27, 28, 29, 33, 41, +54, 61, 62, 99, 101, 105, 106, 107, 108, 133, 134, 0, 7, 30, 83, +86, 87, 88, 90, 91, 92, 93, 135, 136, 137, 1, 2, 31, 32, 34, +100, 102, 103, 104, 119, 132, 138, 139, 140, 16, 21, 22, 23, 24, 44, +51, 64, 65, 66, 67, 69, 71, 72, 73, 74, 75, 76, 8, 9, 10, +11, 12, 13, 14, 15, 35, 36, 42, 43, 46, 48, 49, 50, 52, 60, +63, 77, 78, 79, 80, 81, 82, 85, 89, 94, 95, 96, 97, 98, 109, +110, 111, 112, 113, 114, 115, 120, 121, 17, 18, 19, 20, 37, 38, 39, +40, 45, 47, 53, 55, 56, 57, 58, 59, 68, 70, 84, 116, 117, 118, +122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 141, 142, 143, 144, 145, +146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, +161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, +176, 177, 178, 179, 180, 181, 182, 49, 18, 16, 17, 42, 45, 15, 8, +46, 39, 6, 48, 7, 9, 10, 41, 44, 5, 40, 43, 30, 47, 51, +52, 25, 19, 20, 21, 22, 23, 24, 3, 4, 29, 31, 32, 33, 34, +35, 36, 37, 38, 71, 73, 11, 12, 13, 14, 50, 70, 0, 1, 2, +26, 27, 28, 60, 62, 69, 61, 63, 64, 65, 72, 75, 76, 54, 55, +56, 57, 58, 59, 66, 68, 81, 82, 83, 84, 86, 74, 53, 67, 77, +78, 79, 80, 85, 87, 88, 0, 1, 2, 3, 4, 5, 6, 7, 8, +9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, +24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, +39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, +69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, +84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, +99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, +114, 115, 116, 117, 118, 119, 120, 121, 122, 0, 1, 2, 3, 4, 5, +6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, +21, 100, 31, 35, 41, 33, 30, 34, 40, 82, 81, 103, 47, 32, 15, +99, 46, 9, 21, 8, 69, 65, 67, 14, 62, 57, 58, 60, 80, 56, +20, 11, 97, 10, 85, 86, 1, 22, 26, 36, 16, 17, 78, 79, 105, +108, 5, 24, 28, 38, 44, 45, 59, 61, 63, 70, 109, 111, 0, 4, +25, 29, 39, 50, 51, 54, 55, 71, 72, 73, 74, 75, 76, 77, 95, +96, 101, 102, 104, 110, 98, 18, 19, 83, 84, 89, 23, 27, 37, 42, +43, 48, 113, 2, 3, 6, 7, 12, 13, 49, 52, 53, 87, 88, 90, +91, 92, 93, 94, 106, 107, 112, 64, 66, 68, 5, 4, 0, 39, 48, +17, 8, 6, 7, 77, 78, 75, 76, 79, 80, 16, 15, 73, 56, 55, +74, 40, 41, 42, 60, 9, 10, 11, 12, 13, 14, 59, 43, 62, 1, +2, 3, 44, 61, 58, 68, 22, 23, 28, 35, 36, 45, 46, 47, 57, +67, 69, 70, 71, 19, 18, 20, 21, 24, 25, 26, 27, 29, 30, 31, +32, 33, 34, 37, 38, 49, 50, 51, 52, 53, 54, 63, 64, 65, 66, +72, 81, 82, 83, 84, 34, 44, 71, 32, 43, 30, 35, 72, 33, 11, +10, 39, 37, 13, 38, 42, 36, 12, 41, 31, 8, 9, 40, 50, 69, +55, 20, 24, 28, 135, 1, 5, 15, 136, 70, 46, 51, 114, 115, 45, +3, 7, 17, 113, 116, 54, 128, 129, 134, 138, 0, 4, 14, 26, 19, +23, 27, 48, 62, 63, 68, 123, 124, 125, 126, 131, 132, 29, 49, 59, +60, 66, 127, 130, 133, 86, 110, 119, 57, 58, 65, 83, 87, 103, 111, +122, 18, 22, 82, 102, 61, 64, 67, 21, 25, 52, 2, 6, 16, 75, +76, 85, 90, 95, 99, 100, 109, 120, 56, 73, 74, 77, 78, 79, 80, +81, 84, 88, 89, 91, 92, 93, 94, 96, 97, 98, 101, 104, 105, 106, +107, 108, 112, 117, 118, 121, 137, 47, 53, 4, 5, 0, 1, 2, 3, +7, 8, 6, 9, 10, 20, 25, 27, 18, 19, 21, 23, 24, 26, 28, +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +15, 16, 17, 22, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, +40, 41, 76, 96, 112, 109, 110, 94, 95, 49, 73, 56, 61, 65, 68, +102, 30, 37, 38, 40, 41, 44, 45, 47, 48, 55, 57, 59, 60, 79, +82, 88, 89, 90, 91, 92, 98, 100, 105, 108, 111, 0, 1, 2, 3, +4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, +19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, +35, 36, 39, 42, 43, 46, 50, 51, 52, 53, 54, 58, 62, 63, 64, +66, 67, 69, 70, 71, 72, 74, 75, 77, 78, 80, 81, 83, 84, 85, +86, 87, 93, 97, 99, 101, 103, 104, 106, 107, 113, 91, 42, 46, 77, +26, 8, 78, 41, 43, 44, 47, 68, 5, 30, 45, 89, 90, 48, 49, +50, 51, 25, 76, 93, 14, 70, 88, 4, 23, 24, 29, 59, 63, 75, +79, 92, 97, 0, 1, 2, 6, 7, 15, 16, 17, 20, 21, 27, 31, +32, 33, 34, 35, 36, 62, 64, 67, 72, 61, 66, 71, 86, 94, 12, +74, 55, 58, 60, 81, 83, 3, 9, 10, 11, 13, 18, 19, 22, 28, +37, 38, 39, 40, 53, 56, 65, 69, 73, 82, 84, 85, 52, 54, 57, +80, 87, 95, 96, 1, 8, 10, 13, 12, 6, 2, 0, 11, 9, 5, +25, 7, 19, 43, 44, 45, 32, 33, 34, 50, 51, 52, 26, 22, 23, +3, 4, 28, 15, 36, 37, 49, 30, 31, 29, 14, 20, 21, 24, 27, +17, 39, 46, 16, 35, 53, 38, 40, 41, 42, 18, 47, 48, 0, 1, +2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, +17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, +32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, +47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, +62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, +77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, +92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, +107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, +122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 49, 310, 312, +314, 269, 271, 273, 275, 277, 279, 281, 297, 299, 0, 1, 2, 3, 4, +5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, +20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, +35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50, +51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, +66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, +81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, +96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, +111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, +126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, +141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, +156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, +171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, +186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, +201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, +216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, +231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, +246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, +261, 262, 263, 264, 265, 266, 267, 268, 270, 272, 274, 276, 278, 280, 282, +283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 298, +300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 311, 313, 315, 316, 317, +318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, +333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, +348, 349, 350, 351, 352, 353, 354, 355, 179, 200, 161, 175, 243, 100, 104, +196, 198, 223, 227, 176, 203, 212, 215, 162, 163, 247, 160, 174, 216, 218, +158, 172, 96, 157, 166, 170, 197, 199, 217, 219, 159, 173, 178, 201, 99, +101, 103, 105, 177, 202, 213, 214, 98, 102, 92, 108, 112, 116, 120, 124, +128, 132, 184, 192, 208, 180, 188, 204, 239, 249, 221, 225, 154, 165, 169, +51, 53, 55, 57, 59, 63, 67, 71, 75, 79, 83, 87, 95, 119, 123, +127, 131, 138, 142, 146, 150, 183, 191, 207, 236, 241, 245, 250, 61, 65, +69, 73, 77, 81, 85, 89, 93, 109, 113, 117, 140, 144, 148, 152, 8, +9, 14, 15, 20, 21, 50, 52, 54, 56, 91, 107, 111, 115, 121, 125, +129, 133, 134, 135, 136, 137, 141, 145, 149, 153, 155, 164, 168, 181, 187, +189, 195, 205, 211, 58, 62, 66, 70, 74, 78, 82, 86, 118, 122, 126, +130, 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 16, 17, +18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, +35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, +60, 64, 68, 72, 76, 80, 84, 88, 139, 143, 147, 151, 186, 194, 210, +222, 226, 238, 242, 246, 248, 94, 97, 156, 167, 171, 228, 230, 90, 106, +110, 114, 220, 224, 237, 240, 244, 251, 182, 185, 190, 193, 206, 209, 229, +231, 232, 233, 234, 235, 24, 51, 54, 111, 25, 52, 55, 112, 13, 31, +34, 37, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, +14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 26, 27, 28, 29, 30, +32, 33, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, +49, 50, 53, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, +68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, +83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, +98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 113, 114, +115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, +130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 0, +1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +16, 17, 8, 16, 18, 7, 26, 30, 34, 104, 14, 15, 17, 19, 22, +48, 68, 73, 75, 79, 11, 1, 6, 20, 28, 32, 36, 38, 40, 44, +98, 102, 103, 105, 106, 115, 2, 13, 21, 23, 49, 53, 54, 55, 56, +57, 58, 60, 61, 64, 66, 67, 69, 76, 83, 85, 95, 100, 10, 0, +3, 4, 5, 9, 12, 24, 25, 27, 29, 31, 33, 35, 37, 39, 41, +42, 43, 45, 46, 47, 50, 51, 52, 59, 62, 63, 65, 70, 71, 72, +74, 77, 78, 80, 81, 82, 84, 86, 87, 88, 89, 90, 91, 92, 93, +94, 96, 97, 99, 101, 107, 108, 109, 110, 111, 112, 113, 114, 116, 117, +118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 121, 120, 103, 101, 102, +86, 111, 124, 27, 44, 100, 10, 13, 82, 92, 98, 78, 88, 94, 42, +40, 9, 11, 12, 14, 80, 84, 90, 96, 45, 119, 122, 46, 48, 50, +52, 104, 106, 109, 110, 1, 4, 18, 25, 29, 32, 19, 34, 22, 5, +8, 38, 107, 39, 16, 17, 21, 26, 30, 33, 43, 87, 125, 41, 83, +93, 99, 2, 24, 28, 31, 35, 53, 55, 81, 91, 97, 105, 0, 3, +7, 6, 15, 20, 23, 36, 37, 47, 49, 51, 54, 56, 57, 58, 59, +60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, +75, 76, 77, 79, 85, 89, 95, 108, 112, 113, 114, 115, 116, 117, 118, +123, 161, 57, 60, 95, 169, 165, 171, 0, 160, 40, 168, 164, 39, 58, +59, 96, 1, 2, 50, 55, 64, 75, 85, 92, 97, 71, 77, 81, 87, +6, 16, 30, 44, 181, 170, 49, 56, 63, 76, 86, 91, 98, 174, 180, +5, 15, 29, 43, 72, 78, 82, 88, 113, 126, 194, 195, 198, 158, 159, +162, 163, 114, 125, 144, 145, 166, 167, 192, 193, 156, 47, 48, 51, 52, +53, 54, 61, 62, 65, 66, 83, 84, 89, 90, 93, 94, 99, 100, 101, +102, 103, 104, 130, 131, 132, 133, 134, 135, 152, 175, 176, 177, 67, 69, +73, 79, 105, 3, 4, 7, 8, 13, 14, 17, 18, 19, 20, 25, 26, +27, 28, 31, 32, 33, 34, 37, 38, 41, 42, 45, 46, 68, 70, 74, +80, 106, 117, 118, 142, 143, 178, 179, 138, 9, 140, 147, 148, 107, 109, +111, 139, 141, 146, 149, 182, 183, 184, 185, 190, 191, 115, 119, 121, 123, +137, 155, 157, 187, 189, 197, 10, 11, 12, 21, 22, 23, 24, 35, 36, +108, 110, 112, 116, 120, 122, 124, 127, 128, 129, 136, 150, 151, 153, 154, +173, 186, 188, 196, 172, 37, 36, 33, 32, 35, 34, 4, 2, 6, 0, +44, 45, 47, 46, 42, 43, 39, 41, 40, 38, 5, 7, 3, 1, 51, +17, 11, 15, 19, 9, 13, 10, 14, 18, 16, 23, 24, 27, 28, 31, +8, 12, 20, 22, 21, 25, 26, 29, 30, 49, 48, 50, 179, 176, 165, +178, 171, 175, 174, 177, 162, 168, 190, 188, 202, 200, 33, 75, 93, 51, +81, 87, 173, 164, 157, 114, 3, 6, 156, 15, 21, 27, 170, 167, 123, +63, 69, 39, 45, 57, 199, 211, 172, 208, 205, 214, 181, 184, 203, 196, +169, 198, 201, 160, 161, 137, 163, 125, 209, 119, 183, 215, 166, 207, 204, +213, 197, 191, 206, 210, 182, 212, 187, 185, 53, 83, 89, 192, 186, 193, +136, 180, 194, 130, 142, 154, 155, 148, 149, 131, 143, 116, 32, 74, 92, +122, 101, 107, 110, 113, 98, 104, 71, 65, 41, 47, 59, 2, 11, 14, +20, 26, 195, 189, 147, 150, 151, 145, 133, 127, 139, 126, 138, 132, 144, +117, 159, 52, 82, 88, 158, 120, 96, 102, 108, 99, 105, 111, 30, 72, +90, 8, 5, 9, 0, 124, 97, 103, 109, 12, 18, 24, 48, 78, 84, +66, 60, 70, 62, 35, 77, 95, 68, 42, 50, 80, 86, 17, 23, 29, +36, 54, 38, 44, 56, 152, 153, 64, 40, 58, 46, 128, 140, 129, 134, +135, 141, 146, 106, 100, 112, 121, 7, 4, 115, 118, 34, 61, 76, 94, +16, 22, 28, 37, 43, 55, 49, 79, 85, 67, 1, 13, 19, 25, 31, +73, 91, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, +12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, +27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, +42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, +57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, +72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, +87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, +102, 103, 104, 105, 106, 107, 108, 109, 110, 2, 5, 8, 11, 14, 17, +20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, +65, 68, 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, +19, 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, +42, 43, 45, 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, +64, 66, 67, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, +53, 52, 72, 71, 73, 70, 97, 98, 96, 99, 68, 80, 82, 74, 77, +78, 5, 22, 25, 41, 49, 1, 9, 17, 95, 103, 102, 104, 75, 76, +79, 66, 69, 93, 67, 94, 81, 83, 84, 85, 86, 87, 88, 89, 90, +91, 106, 107, 92, 100, 101, 105, 32, 34, 38, 12, 15, 54, 58, 62, +39, 14, 36, 57, 61, 65, 31, 35, 47, 29, 45, 42, 28, 44, 30, +46, 18, 16, 55, 59, 63, 40, 21, 26, 50, 3, 7, 11, 19, 0, +4, 8, 33, 37, 20, 23, 24, 27, 43, 48, 51, 2, 6, 10, 13, +56, 60, 64, 0, 2, 1, 11, 5, 6, 12, 3, 4, 9, 10, 14, +7, 8, 13, 21, 36, 18, 23, 24, 25, 26, 27, 28, 29, 30, 31, +32, 33, 34, 35, 37, 15, 16, 22, 17, 19, 20, 0, 1, 0, 1, +2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 48, 5, 34, 63, +4, 62, 50, 47, 49, 33, 35, 36, 29, 3, 6, 61, 64, 54, 58, +45, 32, 51, 56, 60, 70, 57, 40, 46, 11, 55, 59, 44, 53, 65, +72, 14, 15, 17, 20, 22, 27, 66, 68, 69, 71, 26, 19, 67, 1, +9, 12, 7, 25, 24, 28, 30, 31, 10, 8, 16, 18, 21, 23, 52, +0, 2, 41, 42, 43, 13, 37, 38, 39, 107, 15, 97, 100, 101, 105, +99, 33, 81, 79, 80, 34, 92, 95, 86, 48, 118, 41, 43, 119, 35, +36, 37, 75, 102, 103, 104, 23, 24, 25, 26, 31, 4, 17, 19, 21, +22, 27, 38, 39, 52, 56, 58, 64, 70, 72, 82, 47, 87, 51, 55, +57, 77, 78, 98, 116, 117, 28, 29, 30, 32, 40, 42, 5, 7, 9, +93, 96, 1, 2, 3, 6, 8, 10, 12, 54, 59, 65, 66, 68, 69, +71, 73, 74, 76, 83, 84, 89, 90, 106, 109, 111, 112, 114, 44, 45, +46, 49, 50, 11, 53, 16, 18, 20, 0, 13, 14, 60, 61, 62, 63, +67, 85, 88, 91, 94, 108, 110, 113, 115, 13, 4, 46, 47, 2, 6, +37, 38, 43, 51, 54, 55, 58, 67, 69, 0, 1, 3, 5, 7, 8, +9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, +25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 39, 40, 41, +42, 44, 45, 48, 49, 50, 52, 53, 56, 57, 59, 60, 61, 62, 63, +64, 65, 66, 68, 70, 71, 72, 73, 74, 75, 7, 4, 6, 5, 2, +3, 9, 8, 0, 1, 23, 22, 24, 25, 14, 26, 30, 34, 10, 11, +12, 13, 15, 16, 17, 18, 19, 20, 21, 27, 28, 29, 31, 32, 33, +35, 36, 37, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, +25, 26, 27, 28, 29, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, +25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, +40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, +55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, +70, 71, 72, 73, 0, 1, 2, 3, 4, 4, 0, 1, 2, 3, 5, +6, 7, 8, 0, 1, 2, 3, 4, 5, 323, 139, 149, 165, 207, 234, +320, 296, 300, 20, 44, 45, 52, 138, 147, 189, 191, 192, 193, 210, 213, +215, 217, 226, 232, 236, 238, 293, 322, 325, 74, 122, 306, 150, 264, 4, +5, 197, 201, 117, 172, 188, 195, 203, 222, 244, 245, 265, 271, 291, 292, +332, 2, 18, 19, 22, 34, 46, 57, 82, 84, 85, 88, 89, 120, 130, +133, 134, 136, 137, 140, 142, 143, 145, 146, 148, 153, 159, 160, 161, 162, +166, 169, 173, 184, 185, 209, 211, 219, 228, 229, 231, 237, 240, 242, 243, +246, 247, 248, 251, 253, 254, 257, 286, 294, 298, 324, 335, 33, 98, 118, +200, 204, 303, 305, 327, 100, 196, 205, 275, 123, 126, 282, 0, 1, 3, +6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 21, 23, 24, +25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 37, 38, 39, 40, 41, +42, 43, 47, 48, 49, 50, 51, 53, 54, 55, 56, 58, 59, 60, 61, +62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 75, 76, 77, +78, 79, 80, 81, 83, 86, 87, 90, 91, 92, 93, 94, 95, 96, 97, +99, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, +115, 116, 119, 121, 124, 125, 127, 128, 129, 131, 132, 135, 141, 144, 151, +152, 154, 155, 156, 157, 158, 163, 164, 167, 168, 170, 171, 174, 175, 176, +177, 178, 179, 180, 181, 182, 183, 186, 187, 190, 194, 198, 199, 202, 206, +208, 212, 214, 216, 218, 220, 221, 223, 224, 225, 227, 230, 233, 235, 239, +241, 249, 250, 252, 255, 256, 258, 259, 260, 261, 262, 263, 266, 267, 268, +269, 270, 272, 273, 274, 276, 277, 278, 279, 280, 281, 283, 284, 285, 287, +288, 289, 290, 295, 297, 299, 301, 302, 304, 307, 308, 309, 310, 311, 312, +313, 314, 315, 316, 317, 318, 319, 321, 326, 328, 329, 330, 331, 333, 334, +336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, +351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, 1, +2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, +17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, +32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, +47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, +62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, +77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, +92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, +107, 108, 109, 4, 5, 18, 20, 0, 1, 2, 3, 6, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 22, 23, 24, 25, 26, +0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, +25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, +40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, +55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, +70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, +85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, +100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, +115, 116, 117, 118, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, +11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, +26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, +41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, +56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, +71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, +86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, +101, 102, 103, 104, 105, 106, 107, 38, 40, 39, 65, 63, 66, 26, 28, +11, 20, 24, 32, 108, 8, 47, 45, 48, 49, 105, 109, 139, 75, 124, +18, 22, 30, 34, 111, 102, 114, 118, 77, 123, 133, 1, 5, 17, 46, +69, 73, 81, 29, 78, 101, 37, 50, 64, 9, 51, 55, 61, 76, 68, +72, 84, 2, 6, 14, 19, 23, 35, 67, 71, 79, 83, 107, 113, 115, +117, 137, 147, 36, 10, 27, 53, 57, 59, 135, 13, 103, 104, 126, 3, +7, 15, 41, 44, 54, 58, 60, 70, 74, 80, 82, 0, 4, 12, 16, +21, 25, 31, 33, 42, 43, 52, 56, 62, 85, 88, 91, 94, 106, 110, +112, 116, 119, 120, 121, 122, 125, 127, 128, 129, 130, 131, 132, 134, 136, +138, 140, 141, 142, 143, 144, 145, 146, 148, 89, 86, 87, 90, 92, 93, +95, 96, 97, 98, 99, 100, 0, 1, 2, 3, 4, 5, 6, 7, 8, +9, 10, 11, 12, 1, 2, 4, 32, 36, 38, 3, 34, 28, 31, 35, +37, 6, 12, 14, 19, 20, 22, 33, 39, 43, 53, 54, 55, 56, 57, +61, 67, 69, 70, 71, 30, 0, 5, 7, 8, 9, 10, 11, 13, 15, +16, 17, 18, 21, 23, 24, 25, 26, 27, 29, 40, 41, 42, 44, 45, +46, 47, 48, 49, 50, 51, 52, 58, 59, 60, 62, 63, 64, 65, 66, +68, 72, 16, 28, 34, 38, 42, 2, 14, 15, 18, 19, 26, 29, 30, +31, 32, 33, 40, 43, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, +11, 12, 13, 17, 20, 21, 22, 23, 24, 25, 27, 35, 36, 37, 39, +41, 2, 0, 7, 1, 86, 5, 74, 21, 89, 85, 88, 3, 4, 6, +51, 23, 111, 70, 56, 90, 98, 27, 78, 53, 68, 80, 87, 116, 12, +25, 109, 114, 103, 108, 110, 9, 57, 62, 65, 91, 96, 99, 69, 71, +72, 73, 81, 49, 50, 52, 93, 101, 36, 55, 64, 125, 19, 20, 22, +106, 41, 8, 11, 13, 29, 34, 37, 54, 102, 107, 118, 123, 126, 14, +15, 16, 18, 82, 83, 84, 92, 97, 100, 104, 112, 17, 32, 121, 94, +24, 113, 76, 77, 79, 10, 61, 95, 26, 28, 30, 31, 35, 38, 39, +40, 46, 58, 59, 60, 63, 66, 67, 75, 105, 115, 117, 119, 120, 124, +127, 128, 33, 42, 43, 44, 45, 47, 48, 122, 0, 1, 2, 3, 4, +5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, +20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 2, 0, 1, 3, 4, +5, 6, 7, 8, 82, 11, 26, 19, 75, 6, 9, 47, 54, 66, 73, +80, 87, 0, 3, 4, 5, 18, 23, 24, 25, 44, 53, 62, 63, 65, +67, 68, 69, 70, 72, 76, 77, 86, 88, 89, 90, 91, 92, 93, 22, +10, 15, 21, 49, 58, 50, 59, 83, 1, 2, 7, 8, 12, 13, 14, +16, 17, 20, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, +39, 40, 41, 42, 43, 45, 46, 48, 51, 52, 55, 56, 57, 60, 61, +64, 71, 74, 78, 79, 81, 84, 85, 0, 1, 0, 1, 34, 2, 12, +13, 32, 37, 76, 3, 10, 11, 19, 20, 21, 22, 23, 27, 28, 29, +30, 35, 53, 55, 78, 4, 16, 17, 5, 6, 7, 8, 9, 14, 15, +18, 24, 25, 26, 31, 33, 36, 38, 39, 40, 41, 42, 43, 44, 45, +46, 47, 48, 49, 50, 51, 52, 54, 56, 57, 58, 59, 60, 61, 62, +63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 79, +80, 81, 82, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, +12, 13, 14, 15, 5, 30, 31, 0, 1, 2, 3, 4, 6, 7, 8, +9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, +24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 59, 0, 1, +2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, +17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, +32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, +48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 62, 63, +64, 65, 36, 61, 20, 1, 19, 126, 127, 60, 56, 33, 34, 35, 21, +22, 52, 59, 67, 71, 72, 63, 65, 66, 32, 45, 57, 84, 91, 114, +125, 64, 0, 2, 3, 68, 70, 73, 26, 46, 53, 54, 55, 58, 115, +131, 74, 12, 96, 97, 99, 41, 42, 44, 49, 50, 75, 80, 83, 85, +103, 106, 107, 108, 109, 110, 111, 112, 113, 116, 117, 118, 119, 120, 124, +13, 62, 76, 77, 78, 86, 128, 129, 94, 23, 24, 25, 27, 28, 29, +30, 31, 37, 38, 39, 40, 43, 47, 48, 51, 4, 5, 6, 7, 8, +9, 10, 11, 14, 15, 16, 17, 18, 69, 79, 81, 82, 87, 88, 89, +90, 92, 93, 95, 98, 100, 101, 102, 104, 105, 121, 122, 123, 130, 132, +3, 2, 10, 11, 1, 4, 6, 8, 5, 7, 9, 0, 31, 30, 15, +43, 49, 53, 57, 45, 12, 13, 16, 18, 32, 34, 36, 14, 33, 35, +37, 21, 23, 17, 19, 20, 22, 24, 25, 26, 27, 28, 29, 42, 48, +52, 56, 38, 41, 44, 46, 50, 54, 39, 40, 47, 51, 55, 35, 36, +3, 5, 7, 9, 11, 2, 17, 30, 34, 14, 20, 23, 4, 6, 13, +16, 18, 19, 22, 24, 25, 31, 32, 33, 8, 10, 12, 15, 21, 0, +1, 26, 27, 28, 29, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, +25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, +40, 41, 42, 43, 44, 45, 46, 47, 5, 4, 6, 21, 0, 3, 18, +16, 15, 17, 9, 12, 20, 7, 14, 19, 8, 10, 11, 13, 1, 2, +167, 168, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, +13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, +28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, +43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, +58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, +73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, +88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, +103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, +118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, +133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, +148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, +163, 164, 165, 166, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, +2, 3, 7, 6, 8, 9, 16, 2, 18, 19, 28, 27, 24, 25, 26, +17, 3, 20, 22, 21, 23, 13, 0, 4, 14, 1, 5, 12, 10, 11, +15, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 12, 13, +14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, +9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, +24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, +39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, +69, 70, 71, 72, 73, 18, 22, 28, 35, 53, 54, 57, 59, 0, 1, +2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, +17, 19, 20, 21, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, +36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, +51, 52, 55, 56, 58, 9, 13, 4, 6, 11, 15, 8, 12, 5, 7, +10, 14, 2, 3, 0, 1, 0, 3, 4, 7, 1, 2, 5, 6, 8, +9, 10, 0, 1, 2, 65, 64, 66, 52, 46, 49, 53, 59, 44, 48, +45, 57, 34, 25, 26, 27, 36, 56, 24, 43, 47, 0, 1, 2, 3, +4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, +19, 20, 21, 22, 23, 28, 29, 30, 31, 32, 33, 35, 37, 38, 39, +40, 41, 42, 50, 51, 54, 55, 58, 60, 61, 62, 63, 0, 1, 2, +3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, +18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, +33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, +48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, +63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, +78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, +93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, +108, 109, 110, 111, 112, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, +25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, +40, 41, 42, 43, 44, 45, 46, 47, 48, 0, 1, 2, 3, 4, 5, +6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, +21, 22, 23, 24, 25, 26, 0, 1, 2, 3, 4, 5, 6, 7, 8, +9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, +24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, +39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, +69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, +84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, +99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, +114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, +144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, +159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, +174, 175, 84, 86, 5, 16, 18, 21, 81, 82, 3, 6, 10, 12, 14, +22, 24, 26, 29, 39, 41, 42, 54, 56, 58, 60, 62, 75, 0, 1, +2, 4, 7, 8, 9, 11, 13, 15, 17, 19, 20, 23, 25, 27, 28, +30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 46, 47, +48, 49, 50, 51, 52, 53, 55, 57, 59, 61, 63, 64, 65, 66, 67, +68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 83, 85, 0, +2, 4, 6, 14, 16, 18, 20, 8, 31, 10, 11, 24, 25, 28, 29, +32, 33, 36, 38, 40, 41, 44, 45, 9, 30, 1, 3, 5, 7, 12, +13, 15, 17, 19, 21, 22, 23, 26, 27, 34, 35, 37, 39, 42, 43, +46, 47, 27, 28, 35, 36, 45, 46, 13, 14, 59, 60, 0, 1, 2, +3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, +20, 21, 22, 23, 24, 25, 26, 29, 30, 31, 32, 33, 34, 37, 38, +39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 52, 53, 54, 55, +56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, +73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, +88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, +103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, +118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, +133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, +148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, +163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, +178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, +193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, +208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, +223, 224, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, +13, 14, 15, 16, 17, 0, 4, 1, 2, 3, 7, 5, 9, 6, 8, +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, +30, 31, 32, 33, 34, 35, 36, 37, 8, 11, 9, 10, 0, 1, 4, +5, 2, 3, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +10, 11, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, +12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, +27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, +42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, +57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, +72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, +87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, +102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, +117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, +132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, +147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, +162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, +177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, +192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, +207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, +222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, +237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, +252, 253, 254, 255, 256, 257, 0, 1, 2, 3, 4, 5, 6, 7, 8, +9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, +35, 1, 2, 20, 29, 32, 33, 34, 0, 3, 4, 5, 6, 7, 8, +9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, +25, 26, 27, 28, 30, 31, 36, 37, 38, 39, 40, 41, 42, 43, 44, +45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 1, 2, 3, 4, 5, +6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, +21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, +36, 37, 38, 39, 40, 0, 1, 0, 1, 2, 3, 4, 5, 0, 1, +2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, +17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, +32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, +47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, +62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, +77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, +92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, +107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, +122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, +137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, +152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, +167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, +182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, +197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, +212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, +227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, +242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, +257, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, +14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, +29, 0, 1, 4, 27, 19, 21, 5, 18, 6, 8, 10, 11, 12, 14, +15, 16, 17, 20, 0, 1, 2, 3, 7, 9, 13, 22, 23, 24, 25, +26, 28, 29, 30, 31, 32, 33, 34, 35, 0, 1, 2, 3, 4, 0, +1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +16, 17, 18, 19, 112, 110, 113, 111, 29, 37, 18, 93, 96, 97, 99, +98, 92, 100, 104, 105, 108, 101, 61, 62, 69, 77, 86, 70, 78, 85, +68, 76, 87, 60, 54, 55, 59, 30, 38, 73, 81, 90, 94, 19, 14, +16, 71, 79, 84, 50, 51, 57, 0, 2, 4, 6, 8, 10, 12, 20, +26, 34, 44, 64, 72, 80, 91, 40, 63, 13, 5, 7, 9, 11, 15, +1, 3, 39, 21, 48, 49, 56, 95, 74, 82, 89, 31, 25, 33, 45, +65, 43, 103, 106, 107, 109, 17, 52, 53, 58, 28, 36, 41, 23, 27, +35, 47, 42, 66, 22, 24, 32, 46, 67, 75, 83, 88, 102, 6, 7, +0, 1, 3, 5, 2, 4, 50, 48, 52, 54, 56, 2, 6, 14, 18, +22, 26, 30, 34, 49, 53, 55, 57, 58, 59, 60, 0, 1, 3, 4, +5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 19, 20, 21, 23, +24, 25, 27, 28, 29, 31, 32, 33, 35, 36, 37, 38, 39, 40, 41, +42, 43, 44, 45, 46, 47, 51, 23, 24, 25, 26, 16, 18, 20, 22, +15, 17, 19, 21, 6, 8, 10, 12, 14, 0, 2, 1, 3, 4, 5, +11, 7, 9, 13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, +11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, +26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, +41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, +56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, +71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, +86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, +101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, +116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, +131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 1, 0, +2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, +2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, +17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, +32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, +47, 48, 49, 50, 51, 52, 53, 54, 55, 0, 1, 2, 3, 4, 5, +6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 112, 114, 19, 61, 70, +18, 111, 3, 5, 6, 66, 82, 109, 110, 113, 58, 102, 104, 31, 35, +36, 37, 38, 71, 77, 86, 93, 95, 96, 108, 47, 25, 45, 46, 53, +55, 75, 40, 41, 42, 52, 60, 83, 84, 24, 26, 11, 12, 22, 23, +28, 30, 57, 63, 65, 69, 81, 90, 106, 32, 33, 34, 49, 50, 51, +72, 73, 78, 79, 87, 88, 94, 4, 7, 8, 9, 10, 20, 21, 29, +39, 43, 44, 48, 54, 56, 59, 62, 64, 67, 68, 74, 76, 80, 89, +91, 92, 100, 101, 115, 116, 16, 99, 13, 14, 15, 17, 27, 85, 97, +98, 103, 105, 107, 117, 7, 10, 19, 0, 1, 2, 3, 4, 5, 6, +8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 0, 1, 2, 3, 4, +5, 7, 17, 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, +13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 0, 1, 0, 7, 11, +5, 6, 10, 3, 4, 1, 2, 8, 9, 12, 0, 1, 2, 3, 4, +0, 1, 2, 3, 4, 1, 3, 0, 2, 4, 5, 6, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, +5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, +20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, +35, 36, 0, 1, 75, 78, 76, 15, 79, 77, 8, 85, 14, 0, 4, +10, 81, 83, 84, 87, 12, 80, 82, 11, 9, 2, 6, 86, 36, 38, +37, 13, 1, 5, 3, 7, 49, 22, 24, 28, 32, 50, 58, 63, 66, +71, 23, 25, 29, 33, 47, 48, 51, 52, 53, 54, 46, 17, 19, 16, +20, 21, 26, 27, 30, 31, 34, 35, 39, 40, 41, 42, 43, 44, 45, +55, 56, 57, 59, 60, 61, 62, 64, 65, 67, 68, 69, 70, 72, 73, +74, 18, 11, 22, 1, 3, 5, 7, 9, 10, 13, 15, 16, 18, 20, +26, 28, 0, 2, 4, 6, 8, 12, 14, 17, 19, 21, 23, 24, 25, +27, 29, 47, 45, 43, 48, 42, 44, 49, 46, 33, 11, 27, 31, 37, +38, 63, 17, 18, 21, 23, 25, 29, 32, 35, 77, 83, 97, 0, 5, +9, 15, 16, 19, 39, 41, 53, 69, 20, 22, 24, 26, 28, 30, 34, +36, 76, 82, 96, 102, 103, 1, 3, 7, 13, 40, 51, 57, 61, 67, +71, 73, 75, 81, 87, 95, 101, 106, 107, 70, 2, 4, 6, 8, 10, +12, 14, 50, 52, 54, 55, 56, 58, 59, 60, 62, 64, 65, 66, 68, +72, 74, 78, 79, 80, 84, 85, 86, 88, 89, 90, 91, 92, 93, 94, +98, 99, 100, 104, 105, 108, 109, 0, 1, 46, 43, 47, 42, 3, 44, +5, 20, 4, 18, 24, 26, 30, 38, 34, 36, 7, 9, 22, 2, 45, +21, 40, 19, 35, 37, 39, 32, 12, 14, 28, 10, 16, 41, 25, 27, +31, 6, 8, 23, 33, 11, 17, 13, 15, 29, 52, 50, 53, 48, 49, +51, 0, 1, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, +6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, +21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, +36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, +51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, +66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, +81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, +96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, +111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, +126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, +141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, +156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, +171, 172, 173, 174, 175, 176, 177, 178, 179, 0, 1, 2, 3, 4, 5, +6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, +21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, +36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, +51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, +66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, +81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, +96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, +111, 112, 113, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, +12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, +27, 28, 29, 30, 31, 32, 33, 34, 35, 5, 15, 19, 27, 31, 35, +39, 43, 96, 104, 120, 121, 131, 0, 1, 2, 10, 12, 24, 25, 46, +47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 76, 77, 78, 79, 80, +81, 82, 83, 84, 85, 86, 87, 88, 90, 91, 93, 95, 97, 99, 101, +103, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, +119, 122, 123, 124, 125, 126, 127, 128, 129, 130, 132, 133, 134, 135, 136, +137, 138, 140, 144, 148, 152, 156, 160, 164, 3, 4, 6, 7, 8, 9, +11, 13, 14, 16, 17, 18, 20, 21, 22, 23, 26, 28, 29, 30, 32, +33, 34, 36, 37, 38, 40, 41, 42, 44, 45, 57, 58, 59, 60, 61, +62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 89, +92, 94, 98, 100, 102, 139, 141, 142, 143, 145, 146, 147, 149, 150, 151, +153, 154, 155, 157, 158, 159, 161, 162, 163, 165, 166, 36, 57, 60, 65, +68, 114, 135, 156, 161, 162, 165, 170, 176, 179, 182, 183, 188, 191, 194, +197, 198, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, +13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, +28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43, +44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 58, 59, +61, 62, 63, 64, 66, 67, 69, 70, 71, 72, 73, 74, 75, 76, 77, +78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, +93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, +108, 109, 110, 111, 112, 113, 115, 116, 117, 118, 119, 120, 121, 122, 123, +124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 136, 137, 138, 139, +140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, +155, 157, 158, 159, 160, 163, 164, 166, 167, 168, 169, 171, 172, 173, 174, +175, 177, 178, 180, 181, 184, 185, 186, 187, 189, 190, 192, 193, 195, 196, +199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, +214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, +229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, +244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, +259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, +274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, +289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, +304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, +319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, +334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, +349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, +364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, +379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, +394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, +409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, +424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, +439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, +454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, +469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, +484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, +499, 500, 501, 502, 503, 504, 505, 506, 0, 1, 2, 3, 4, 5, 6, +7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, +25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, +40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, +55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, +70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, +85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, +100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, +115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, +130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, +145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, +160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, +175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, +190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, +205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, +220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, +235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, +250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, +265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, +280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, +295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, +310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, +325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, +340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, +355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, +370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, +385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, +400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, +415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, +430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, +445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, +460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, +475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, +490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, +505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, +520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, +535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, +550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, +565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, +580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, +595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, +610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, +625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, +640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, +655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +15, 16, 17, 18, 19, 20, 21, 0, 1, 2, 3, 4, 5, 6, 7, +8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, +23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, +38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, +53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, +68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, +83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, +98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, +113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, +128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, +143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, +158, 159, 160, 161, 162, 163, 164, 165, 166, 0, 1, 2, 3, 4, 5, +6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2, 3, 4, 5, +0, 3, 5, 10, 16, 18, 94, 4, 6, 7, 8, 17, 37, 44, 48, +51, 56, 66, 69, 75, 79, 82, 84, 88, 98, 99, 102, 1, 2, 9, +11, 12, 13, 14, 15, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, +29, 30, 31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 45, +46, 47, 49, 50, 52, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, +64, 65, 67, 68, 70, 71, 72, 73, 74, 76, 77, 78, 80, 81, 83, +85, 86, 87, 89, 90, 91, 92, 93, 95, 96, 97, 100, 101, 103, 104, +105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, +120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, +135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, +150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, +165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, +180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, +81, 18, 24, 33, 69, 83, 19, 25, 35, 71, 0, 1, 2, 3, 4, +5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, +22, 23, 26, 27, 28, 29, 30, 31, 32, 34, 36, 37, 38, 39, 40, +41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, +56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 72, +73, 74, 75, 76, 77, 78, 79, 80, 82, 84, 85, 86, 87, 88, 89, +90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, +105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, +120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, +135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, +150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, +165, 166, 167, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, +12, 13, 14, 15, 16, 17, 4, 5, 6, 31, 32, 39, 40, 41, 0, +1, 2, 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, +19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 35, +36, 37, 38, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, +69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, +84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, +99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, +114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, +129, 130, 131, 132, 133, 134, 135, 136, 0, 1, 3, 22, 23, 26, 34, +0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +16, 17, 18, 19, 20, 21, 24, 25, 27, 28, 29, 30, 31, 32, 33, +35, 36, 37, 38, 39, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0, +1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, +16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, +31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, +46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, +61, 62, 63, 64, 65, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, +10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, +25, 26, 27, 28, 29, 30, 31, 32, 33, 51, 0, 1, 2, 3, 4, +5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, +20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, +35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, +50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, +66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 0, 1, 2, +3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, +18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, +13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, +28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 1, +2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, +17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, +32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, +47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, +62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, +77, 74, 75, 92, 93, 116, 143, 144, 149, 14, 15, 34, 35, 36, 37, +68, 69, 98, 99, 104, 105, 110, 111, 154, 155, 156, 157, 166, 167, 168, +169, 178, 179, 180, 181, 4, 5, 6, 7, 22, 23, 24, 25, 46, 47, +50, 51, 56, 57, 60, 61, 80, 82, 85, 87, 121, 122, 123, 124, 133, +134, 135, 136, 190, 191, 194, 197, 202, 203, 206, 207, 212, 213, 216, 217, +0, 1, 2, 3, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, +21, 26, 27, 28, 29, 30, 31, 32, 33, 38, 39, 40, 41, 42, 43, +44, 45, 48, 49, 52, 53, 54, 55, 58, 59, 62, 63, 64, 65, 66, +67, 70, 71, 72, 73, 76, 77, 78, 79, 81, 83, 84, 86, 88, 89, +90, 91, 94, 95, 96, 97, 100, 101, 102, 103, 106, 107, 108, 109, 112, +113, 114, 115, 117, 118, 119, 120, 125, 126, 127, 128, 129, 130, 131, 132, +137, 138, 139, 140, 141, 142, 145, 146, 147, 148, 150, 151, 152, 153, 158, +159, 160, 161, 162, 163, 164, 165, 170, 171, 172, 173, 174, 175, 176, 177, +182, 183, 184, 185, 186, 187, 188, 189, 192, 193, 195, 196, 198, 199, 200, +201, 204, 205, 208, 209, 210, 211, 214, 215, 218, 219, 220, 221, 0, 1, +2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, +17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, +32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 0, 1, 2, +3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, +18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, +33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, +48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, +63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, +78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, +93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, +108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, +123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, +138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, +153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, +168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, +183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, +198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, +213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, +228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, +243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, +258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, +273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, +288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, +303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, +318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, +333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, +348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, +363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, +15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, +30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, +45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 0, 1, 2, 3, +4, 5, 6, 7, 0, 1, 14, 15, 16, 17, 2, 3, 4, 5, 8, +9, 10, 11, 12, 13, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, +28, 29, 30, 31, 32, 33, 11, 2, 5, 10, 8, 4, 9, 1, 7, +3, 0, 6, 42, 45, 36, 39, 12, 16, 18, 22, 38, 41, 44, 47, +37, 40, 43, 46, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, +11, 13, 14, 15, 17, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, +30, 31, 32, 33, 34, 35, 0, 1, 2, 3, 4, 5, 6, 7, 8, +9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, +24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, +39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, +54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, +69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, +84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, +99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, +114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, +129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, +144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, +159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, +174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, +189, 190, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, +13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, +28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, +43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, +58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, +73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, +88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, +103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 4, 5, +6, 8, 1, 3, 0, 2, 7, 9, 0, 1, 2, 3, 4, 5, 6, +7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, +22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, +37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, +52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, +67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, +82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, +97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, +112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, +127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, +142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, +157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, +172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, +187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, +202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, +217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, +232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, +247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, +262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, +277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, +292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, +307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, +322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, +337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, +352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, +367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, +382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, +397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, +412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, +427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, +442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, +457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, +472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, +487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, +502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, +517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, +532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, +547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, +562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, +577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, +592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, +607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, +622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, +637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, +652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, +667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, +682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, +697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, +712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, +727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, +742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, +757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, +772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, +787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, +802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, +817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, +832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, +847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, +862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, +877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, +892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, +907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, +922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, +937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, +952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, +967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, +982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, +997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, +1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, +1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, +1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, +1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, +1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, +1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, +1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, +1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131, +1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, +1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, +1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, +1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, +1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, +1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, +1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, +1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, +1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, +1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, +1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, +1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, +1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, +1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, +1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, +1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, +1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, +1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, +1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, +1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, +1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, +1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, +1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, +1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, +1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, +1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, +1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, +1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, +1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, +1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, +1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, +1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, +1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, +1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, +1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, +1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, +1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, +1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, +1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, +1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, +1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, +1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, +1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, +1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, +1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, +1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, +1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, +1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, +1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, +1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, +1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, +1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, +1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, +1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, +1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, +1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, +1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, +1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, +2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, +2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, +2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, +2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, +2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, +2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, +2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, +2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, +2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, +2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, +2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, +2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, +2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, +2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, +2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, +2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, +2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, +2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, +2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, +2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, +2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, +2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, +2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, +2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, +2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, +2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, +2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, +2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418, 2419, 2420, 2421, +2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, +2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, +2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, +2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, +2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, +2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, +2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, +2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, +2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, +2557, 2558, 2559, 2560, 2561, 2562, 2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, +2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, +2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, +2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, +2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, +2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, +2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, +2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, +2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, +2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, +2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, +2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, +2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, +2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, +2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, +2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, +2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, +2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, +2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, +2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, +2857, 2858, 2859, 2860, 2861, 2862, 2863, 9, 11, 6, 7, 8, 10, 4, 5, +0, 1, 2, 3, 0, 2, 10, 3, 6, 1, 9, 11, 4, 8, 7, +5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, +14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, +29, 30, 31, 32, 33, 34, 35, 68, 116, 22, 10, 97, 117, 52, 110, +7, 19, 111, 115, 6, 18, 0, 74, 88, 12, 48, 108, 99, 109, 38, +104, 4, 16, 24, 96, 15, 3, 50, 84, 71, 85, 36, 102, 103, 119, +54, 86, 100, 30, 25, 105, 113, 69, 53, 63, 98, 87, 93, 89, 95, +9, 21, 62, 114, 5, 17, 26, 55, 2, 14, 65, 8, 20, 64, 92, +42, 106, 11, 23, 46, 66, 34, 101, 107, 56, 35, 47, 57, 67, 76, +118, 75, 83, 82, 94, 37, 77, 29, 51, 1, 13, 27, 49, 58, 112, +39, 59, 28, 70, 44, 73, 80, 81, 32, 72, 31, 43, 33, 40, 41, +45, 60, 61, 78, 79, 90, 91 +}; + + +/**Function************************************************************* + + Synopsis [Reads library from array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Dar_LibReadNodes() +{ + Vec_Int_t * vResult; + int i; + vResult = Vec_IntAlloc( s_nDataSize1 ); + for ( i = 0; i < s_nDataSize1; i++ ) + Vec_IntPush( vResult, s_Data1[i] ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Reads library from array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Dar_LibReadOuts() +{ + Vec_Int_t * vResult; + int i; + vResult = Vec_IntAlloc( s_nDataSize2 ); + for ( i = 0; i < s_nDataSize2; i++ ) + Vec_IntPush( vResult, s_Data2[i] ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Reads library from array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Dar_LibReadPrios() +{ + Vec_Int_t * vResult; + int i; + vResult = Vec_IntAlloc( s_nDataSize3 ); + for ( i = 0; i < s_nDataSize3; i++ ) + Vec_IntPush( vResult, s_Data3[i] ); + return vResult; +} + +#if 0 + +#include "abc.h" + +/**Function************************************************************* + + Synopsis [Generate arrays.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_NtkGenerateArrays( Abc_Ntk_t * pNtk ) +{ + extern int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ); + + Abc_Obj_t * pObj; + int i, Count = 0; + assert( Abc_NtkPiNum(pNtk) == 4 ); + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_ObjFanoutNum(Abc_AigConst1(pNtk)) == 0 ); +/* + { + unsigned char * pBuffer; + int Pos, uLit, uLit0, uLit1, Size, Digit; + + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = (void *)Count++; + + Pos = 0; + pBuffer = ALLOC( char, 200000 ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + pObj->pCopy = (void *)Count++; + uLit = ((int)pObj->pCopy << 1); + uLit0 = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj); + uLit1 = (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj); + assert( uLit0 < uLit1 ); + Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); + Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); + } + // write the buffer + Size = 0; + for ( i = 0; i < Pos; i++ ) + { + if ( i % 36 == 0 ) + printf( "\n" ); + + Digit = pBuffer[i] & 0xF; + if ( Digit < 10 ) + printf( "%d", Digit ); + else + printf( "%c", Digit - 10 + 'A' ); + + + Digit = pBuffer[i]; + Digit >>= 4; + if ( Digit < 10 ) + printf( "%d", Digit ); + else + printf( "%c", Digit - 10 + 'A' ); + + } + printf( "\n" ); + printf( "Size = %d.\n", Pos ); + } +*/ + + + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = (void *)Count++; + Abc_AigForEachAnd( pNtk, pObj, i ) + { +// if ( (Count - 4) % 6 == 0 ) +// printf( "\n" ); +// printf( "%5d,", (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj) ); +// printf( "%5d,", (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj) ); + pObj->pCopy = (void *)Count++; + } +// printf( "\n" ); +// printf( "Nodes = %d.\n", Count-4 ); + + + + Abc_NtkForEachPo( pNtk, pObj, i ) + { + if ( i % 12 == 0 ) + printf( "\n" ); + printf( "%5d,", (int)Abc_ObjFanin0(pObj)->pCopy ); + } + printf( "\n" ); + printf( "Outputs = %d.\n", Abc_NtkPoNum(pNtk) ); + + +/* + { + unsigned char * pBuffer; + Vec_Int_t * vOuts; + int Pos, Prev, Out; + + vOuts = Vec_IntAlloc( 25000 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Vec_IntPush( vOuts, Abc_ObjFaninId0(pObj) ); + Vec_IntSort( vOuts, 0 ); + + Pos = 0; + pBuffer = ALLOC( char, 50000 ); + Prev = 0; + Vec_IntForEachEntry( vOuts, Out, i ) + { + assert( Prev < Out ); + Pos = Io_WriteAigerEncode( pBuffer, Pos, Out - Prev ); + Prev = Out; + } + Vec_IntFree( vOuts ); + + // write the buffer + for ( i = 0; i < Pos; i++ ) + { + if ( i % 32 == 0 ) + printf( "\n" ); + printf( "%d,", pBuffer[i] ); + } + printf( "\n" ); + printf( "Size = %d.\n", Pos ); + } +*/ + +} + +#endif + + + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/dar/darInt.h b/abc70930/src/aig/dar/darInt.h new file mode 100644 index 00000000..4da793f5 --- /dev/null +++ b/abc70930/src/aig/dar/darInt.h @@ -0,0 +1,165 @@ +/**CFile**************************************************************** + + FileName [darInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: darInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __DAR_INT_H__ +#define __DAR_INT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +//#include "bar.h" +#include "vec.h" +#include "aig.h" +#include "dar.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Dar_Man_t_ Dar_Man_t; +typedef struct Dar_Cut_t_ Dar_Cut_t; + +// the AIG 4-cut +struct Dar_Cut_t_ // 6 words +{ + unsigned uSign; // cut signature + unsigned uTruth : 16; // the truth table of the cut function + unsigned Value : 11; // the value of the cut + unsigned fBest : 1; // marks the best cut + unsigned fUsed : 1; // marks the cut currently in use + unsigned nLeaves : 3; // the number of leaves + int pLeaves[4]; // the array of leaves +}; + +// the AIG manager +struct Dar_Man_t_ +{ + // input data + Dar_RwrPar_t * pPars; // rewriting parameters + Aig_Man_t * pAig; // AIG manager + // various data members + Aig_MmFixed_t * pMemCuts; // memory manager for cuts + void * pManCnf; // CNF managers + // current rewriting step + Vec_Ptr_t * vLeavesBest; // the best set of leaves + int OutBest; // the best output (in the library) + int OutNumBest; // the best number of the output + int GainBest; // the best gain + int LevelBest; // the level of node with the best gain + int ClassBest; // the equivalence class of the best replacement + // function statistics + int nTotalSubgs; // the total number of subgraphs tried + int ClassTimes[222];// the runtimes for each class + int ClassGains[222];// the gains for each class + int ClassSubgs[222];// the graphs for each class + int nCutMemUsed; // memory used for cuts + // rewriting statistics + int nNodesInit; // the original number of nodes + int nNodesTried; // the number of nodes attempted + int nCutsAll; // all cut pairs + int nCutsTried; // computed cuts + int nCutsUsed; // used cuts + int nCutsBad; // bad cuts due to absent fanin + int nCutsGood; // good cuts + int nCutsSkipped; // skipped bad cuts + // timing statistics + int timeCuts; + int timeEval; + int timeOther; + int timeTotal; + int time1; + int time2; +}; + +static inline Dar_Cut_t * Dar_ObjCuts( Aig_Obj_t * pObj ) { return pObj->pData; } +static inline void Dar_ObjSetCuts( Aig_Obj_t * pObj, Dar_Cut_t * pCuts ) { assert( !Aig_ObjIsNone(pObj) ); pObj->pData = pCuts; } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over all cuts of the node +#define Dar_ObjForEachCutAll( pObj, pCut, i ) \ + for ( (pCut) = Dar_ObjCuts(pObj), i = 0; i < (int)(pObj)->nCuts; i++, pCut++ ) +#define Dar_ObjForEachCut( pObj, pCut, i ) \ + for ( (pCut) = Dar_ObjCuts(pObj), i = 0; i < (int)(pObj)->nCuts; i++, pCut++ ) if ( (pCut)->fUsed==0 ) {} else +// iterator over leaves of the cut +#define Dar_CutForEachLeaf( p, pCut, pLeaf, i ) \ + for ( i = 0; (i < (int)(pCut)->nLeaves) && (((pLeaf) = Aig_ManObj(p, (pCut)->pLeaves[i])), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== darBalance.c ========================================================*/ +/*=== darCore.c ===========================================================*/ +/*=== darCut.c ============================================================*/ +extern void Dar_ManCutsStart( Dar_Man_t * p ); +extern void Dar_ManCutsFree( Dar_Man_t * p ); +extern Dar_Cut_t * Dar_ObjComputeCuts_rec( Dar_Man_t * p, Aig_Obj_t * pObj ); +extern Dar_Cut_t * Dar_ObjComputeCuts( Dar_Man_t * p, Aig_Obj_t * pObj ); +/*=== darData.c ===========================================================*/ +extern Vec_Int_t * Dar_LibReadNodes(); +extern Vec_Int_t * Dar_LibReadOuts(); +extern Vec_Int_t * Dar_LibReadPrios(); +/*=== darLib.c ============================================================*/ +extern void Dar_LibStart(); +extern void Dar_LibStop(); +extern void Dar_LibPrepare( int nSubgraphs ); +extern void Dar_LibReturnCanonicals( unsigned * pCanons ); +extern void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required ); +extern Aig_Obj_t * Dar_LibBuildBest( Dar_Man_t * p ); +/*=== darMan.c ============================================================*/ +extern Dar_Man_t * Dar_ManStart( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ); +extern void Dar_ManStop( Dar_Man_t * p ); +extern void Dar_ManPrintStats( Dar_Man_t * p ); +/*=== darPrec.c ============================================================*/ +extern char ** Dar_Permutations( int n ); +extern void Dar_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/dar/darLib.c b/abc70930/src/aig/dar/darLib.c new file mode 100644 index 00000000..e0e97055 --- /dev/null +++ b/abc70930/src/aig/dar/darLib.c @@ -0,0 +1,980 @@ +/**CFile**************************************************************** + + FileName [darLib.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [Library of AIG subgraphs used for rewriting.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: darLib.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "darInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Dar_Lib_t_ Dar_Lib_t; +typedef struct Dar_LibObj_t_ Dar_LibObj_t; +typedef struct Dar_LibDat_t_ Dar_LibDat_t; + +struct Dar_LibObj_t_ // library object (2 words) +{ + unsigned Fan0 : 16; // the first fanin + unsigned Fan1 : 16; // the second fanin + unsigned fCompl0 : 1; // the first compl attribute + unsigned fCompl1 : 1; // the second compl attribute + unsigned fPhase : 1; // the phase of the node + unsigned fTerm : 1; // indicates a PI + unsigned Num : 28; // internal use +}; + +struct Dar_LibDat_t_ // library object data +{ + Aig_Obj_t * pFunc; // the corresponding AIG node if it exists + int Level; // level of this node after it is constructured + int TravId; // traversal ID of the library object data + unsigned char fMffc; // set to one if node is part of MFFC + unsigned char nLats[3]; // the number of latches on the input/output stem +}; + +struct Dar_Lib_t_ // library +{ + // objects + Dar_LibObj_t * pObjs; // the set of library objects + int nObjs; // the number of objects used + int iObj; // the current object + // structures by class + int nSubgr[222]; // the number of subgraphs by class + int * pSubgr[222]; // the subgraphs for each class + int * pSubgrMem; // memory for subgraph pointers + int nSubgrTotal; // the total number of subgraph + // structure priorities + int * pPriosMem; // memory for priority of structures + int * pPrios[222]; // pointers to the priority numbers + // structure places in the priorities + int * pPlaceMem; // memory for places of structures in the priority lists + int * pPlace[222]; // pointers to the places numbers + // structure scores + int * pScoreMem; // memory for scores of structures + int * pScore[222]; // pointers to the scores numbers + // nodes by class + int nNodes[222]; // the number of nodes by class + int * pNodes[222]; // the nodes for each class + int * pNodesMem; // memory for nodes pointers + int nNodesTotal; // the total number of nodes + // prepared library + int nSubgraphs; + int nNodes0Max; + // nodes by class + int nNodes0[222]; // the number of nodes by class + int * pNodes0[222]; // the nodes for each class + int * pNodes0Mem; // memory for nodes pointers + int nNodes0Total; // the total number of nodes + // structures by class + int nSubgr0[222]; // the number of subgraphs by class + int * pSubgr0[222]; // the subgraphs for each class + int * pSubgr0Mem; // memory for subgraph pointers + int nSubgr0Total; // the total number of subgraph + // object data + Dar_LibDat_t * pDatas; + int nDatas; + // information about NPN classes + char ** pPerms4; + unsigned short * puCanons; + char * pPhases; + char * pPerms; + unsigned char * pMap; +}; + +static Dar_Lib_t * s_DarLib = NULL; + +static inline Dar_LibObj_t * Dar_LibObj( Dar_Lib_t * p, int Id ) { return p->pObjs + Id; } +static inline int Dar_LibObjTruth( Dar_LibObj_t * pObj ) { return pObj->Num < (0xFFFF & ~pObj->Num) ? pObj->Num : (0xFFFF & ~pObj->Num); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dar_Lib_t * Dar_LibAlloc( int nObjs ) +{ + unsigned uTruths[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 }; + Dar_Lib_t * p; + int i;//, clk = clock(); + p = ALLOC( Dar_Lib_t, 1 ); + memset( p, 0, sizeof(Dar_Lib_t) ); + // allocate objects + p->nObjs = nObjs; + p->pObjs = ALLOC( Dar_LibObj_t, nObjs ); + memset( p->pObjs, 0, sizeof(Dar_LibObj_t) * nObjs ); + // allocate canonical data + p->pPerms4 = Dar_Permutations( 4 ); + Dar_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap ); + // start the elementary objects + p->iObj = 4; + for ( i = 0; i < 4; i++ ) + { + p->pObjs[i].fTerm = 1; + p->pObjs[i].Num = uTruths[i]; + } +// PRT( "Library start", clock() - clk ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibFree( Dar_Lib_t * p ) +{ + free( p->pObjs ); + free( p->pDatas ); + free( p->pNodesMem ); + free( p->pNodes0Mem ); + free( p->pSubgrMem ); + free( p->pSubgr0Mem ); + free( p->pPriosMem ); + FREE( p->pPlaceMem ); + FREE( p->pScoreMem ); + free( p->pPerms4 ); + free( p->puCanons ); + free( p->pPhases ); + free( p->pPerms ); + free( p->pMap ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns canonical truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibReturnCanonicals( unsigned * pCanons ) +{ + int Visits[222] = {0}; + int i, k; + // find canonical truth tables + for ( i = k = 0; i < (1<<16); i++ ) + if ( !Visits[s_DarLib->pMap[i]] ) + { + Visits[s_DarLib->pMap[i]] = 1; + pCanons[k++] = ((i<<16) | i); + } + assert( k == 222 ); +} + +/**Function************************************************************* + + Synopsis [Adds one AND to the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibAddNode( Dar_Lib_t * p, int Id0, int Id1, int fCompl0, int fCompl1 ) +{ + Dar_LibObj_t * pFan0 = Dar_LibObj( p, Id0 ); + Dar_LibObj_t * pFan1 = Dar_LibObj( p, Id1 ); + Dar_LibObj_t * pObj = p->pObjs + p->iObj++; + pObj->Fan0 = Id0; + pObj->Fan1 = Id1; + pObj->fCompl0 = fCompl0; + pObj->fCompl1 = fCompl1; + pObj->fPhase = (fCompl0 ^ pFan0->fPhase) & (fCompl1 ^ pFan1->fPhase); + pObj->Num = 0xFFFF & (fCompl0? ~pFan0->Num : pFan0->Num) & (fCompl1? ~pFan1->Num : pFan1->Num); +} + +/**Function************************************************************* + + Synopsis [Adds one AND to the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibSetup_rec( Dar_Lib_t * p, Dar_LibObj_t * pObj, int Class, int fCollect ) +{ + if ( pObj->fTerm || (int)pObj->Num == Class ) + return; + pObj->Num = Class; + Dar_LibSetup_rec( p, Dar_LibObj(p, pObj->Fan0), Class, fCollect ); + Dar_LibSetup_rec( p, Dar_LibObj(p, pObj->Fan1), Class, fCollect ); + if ( fCollect ) + p->pNodes[Class][ p->nNodes[Class]++ ] = pObj-p->pObjs; + else + p->nNodes[Class]++; +} + +/**Function************************************************************* + + Synopsis [Adds one AND to the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibSetup( Dar_Lib_t * p, Vec_Int_t * vOuts, Vec_Int_t * vPrios ) +{ + int fTraining = 0; + Dar_LibObj_t * pObj; + int nNodesTotal, uTruth, Class, Out, i, k; + assert( p->iObj == p->nObjs ); + + // count the number of representatives of each class + for ( i = 0; i < 222; i++ ) + p->nSubgr[i] = p->nNodes[i] = 0; + Vec_IntForEachEntry( vOuts, Out, i ) + { + pObj = Dar_LibObj( p, Out ); + uTruth = Dar_LibObjTruth( pObj ); + Class = p->pMap[uTruth]; + p->nSubgr[Class]++; + } + // allocate memory for the roots of each class + p->pSubgrMem = ALLOC( int, Vec_IntSize(vOuts) ); + p->pSubgr0Mem = ALLOC( int, Vec_IntSize(vOuts) ); + p->nSubgrTotal = 0; + for ( i = 0; i < 222; i++ ) + { + p->pSubgr[i] = p->pSubgrMem + p->nSubgrTotal; + p->pSubgr0[i] = p->pSubgr0Mem + p->nSubgrTotal; + p->nSubgrTotal += p->nSubgr[i]; + p->nSubgr[i] = 0; + } + assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); + // add the outputs to storage + Vec_IntForEachEntry( vOuts, Out, i ) + { + pObj = Dar_LibObj( p, Out ); + uTruth = Dar_LibObjTruth( pObj ); + Class = p->pMap[uTruth]; + p->pSubgr[Class][ p->nSubgr[Class]++ ] = Out; + } + + if ( fTraining ) + { + // allocate memory for the priority of roots of each class + p->pPriosMem = ALLOC( int, Vec_IntSize(vOuts) ); + p->nSubgrTotal = 0; + for ( i = 0; i < 222; i++ ) + { + p->pPrios[i] = p->pPriosMem + p->nSubgrTotal; + p->nSubgrTotal += p->nSubgr[i]; + for ( k = 0; k < p->nSubgr[i]; k++ ) + p->pPrios[i][k] = k; + + } + assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); + + // allocate memory for the priority of roots of each class + p->pPlaceMem = ALLOC( int, Vec_IntSize(vOuts) ); + p->nSubgrTotal = 0; + for ( i = 0; i < 222; i++ ) + { + p->pPlace[i] = p->pPlaceMem + p->nSubgrTotal; + p->nSubgrTotal += p->nSubgr[i]; + for ( k = 0; k < p->nSubgr[i]; k++ ) + p->pPlace[i][k] = k; + + } + assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); + + // allocate memory for the priority of roots of each class + p->pScoreMem = ALLOC( int, Vec_IntSize(vOuts) ); + p->nSubgrTotal = 0; + for ( i = 0; i < 222; i++ ) + { + p->pScore[i] = p->pScoreMem + p->nSubgrTotal; + p->nSubgrTotal += p->nSubgr[i]; + for ( k = 0; k < p->nSubgr[i]; k++ ) + p->pScore[i][k] = 0; + + } + assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); + } + else + { + int Counter = 0; + // allocate memory for the priority of roots of each class + p->pPriosMem = ALLOC( int, Vec_IntSize(vOuts) ); + p->nSubgrTotal = 0; + for ( i = 0; i < 222; i++ ) + { + p->pPrios[i] = p->pPriosMem + p->nSubgrTotal; + p->nSubgrTotal += p->nSubgr[i]; + for ( k = 0; k < p->nSubgr[i]; k++ ) + p->pPrios[i][k] = Vec_IntEntry(vPrios, Counter++); + + } + assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); + assert( Counter == Vec_IntSize(vPrios) ); + } + + // create traversal IDs + for ( i = 0; i < p->iObj; i++ ) + Dar_LibObj(p, i)->Num = 0xff; + // count nodes in each class + for ( i = 0; i < 222; i++ ) + for ( k = 0; k < p->nSubgr[i]; k++ ) + Dar_LibSetup_rec( p, Dar_LibObj(p, p->pSubgr[i][k]), i, 0 ); + // count the total number of nodes + p->nNodesTotal = 0; + for ( i = 0; i < 222; i++ ) + p->nNodesTotal += p->nNodes[i]; + // allocate memory for the nodes of each class + p->pNodesMem = ALLOC( int, p->nNodesTotal ); + p->pNodes0Mem = ALLOC( int, p->nNodesTotal ); + p->nNodesTotal = 0; + for ( i = 0; i < 222; i++ ) + { + p->pNodes[i] = p->pNodesMem + p->nNodesTotal; + p->pNodes0[i] = p->pNodes0Mem + p->nNodesTotal; + p->nNodesTotal += p->nNodes[i]; + p->nNodes[i] = 0; + } + // create traversal IDs + for ( i = 0; i < p->iObj; i++ ) + Dar_LibObj(p, i)->Num = 0xff; + // add the nodes to storage + nNodesTotal = 0; + for ( i = 0; i < 222; i++ ) + { + for ( k = 0; k < p->nSubgr[i]; k++ ) + Dar_LibSetup_rec( p, Dar_LibObj(p, p->pSubgr[i][k]), i, 1 ); + nNodesTotal += p->nNodes[i]; +//printf( "Class %3d : Subgraphs = %4d. Nodes = %5d.\n", i, p->nSubgr[i], p->nNodes[i] ); + } + assert( nNodesTotal == p->nNodesTotal ); + // prepare the number of the PI nodes + for ( i = 0; i < 4; i++ ) + Dar_LibObj(p, i)->Num = i; +} + +/**Function************************************************************* + + Synopsis [Starts the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibCreateData( Dar_Lib_t * p, int nDatas ) +{ + if ( p->nDatas == nDatas ) + return; + FREE( p->pDatas ); + // allocate datas + p->nDatas = nDatas; + p->pDatas = ALLOC( Dar_LibDat_t, nDatas ); + memset( p->pDatas, 0, sizeof(Dar_LibDat_t) * nDatas ); +} + +/**Function************************************************************* + + Synopsis [Adds one AND to the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibSetup0_rec( Dar_Lib_t * p, Dar_LibObj_t * pObj, int Class, int fCollect ) +{ + if ( pObj->fTerm || (int)pObj->Num == Class ) + return; + pObj->Num = Class; + Dar_LibSetup0_rec( p, Dar_LibObj(p, pObj->Fan0), Class, fCollect ); + Dar_LibSetup0_rec( p, Dar_LibObj(p, pObj->Fan1), Class, fCollect ); + if ( fCollect ) + p->pNodes0[Class][ p->nNodes0[Class]++ ] = pObj-p->pObjs; + else + p->nNodes0[Class]++; +} + +/**Function************************************************************* + + Synopsis [Starts the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibPrepare( int nSubgraphs ) +{ + Dar_Lib_t * p = s_DarLib; + int i, k, nNodes0Total; + if ( p->nSubgraphs == nSubgraphs ) + return; + + // favor special classes: + // 1 : F = (!d*!c*!b*!a) + // 4 : F = (!d*!c*!(b*a)) + // 12 : F = (!d*!(c*!(!b*!a))) + // 20 : F = (!d*!(c*b*a)) + + // set the subgraph counters + p->nSubgr0Total = 0; + for ( i = 0; i < 222; i++ ) + { +// if ( i == 1 || i == 4 || i == 12 || i == 20 ) // special classes + if ( i == 1 ) // special classes + p->nSubgr0[i] = p->nSubgr[i]; + else + p->nSubgr0[i] = AIG_MIN( p->nSubgr[i], nSubgraphs ); + p->nSubgr0Total += p->nSubgr0[i]; + for ( k = 0; k < p->nSubgr0[i]; k++ ) + p->pSubgr0[i][k] = p->pSubgr[i][ p->pPrios[i][k] ]; + } + + // count the number of nodes + // clean node counters + for ( i = 0; i < 222; i++ ) + p->nNodes0[i] = 0; + // create traversal IDs + for ( i = 0; i < p->iObj; i++ ) + Dar_LibObj(p, i)->Num = 0xff; + // count nodes in each class + // count the total number of nodes and the largest class + p->nNodes0Total = 0; + p->nNodes0Max = 0; + for ( i = 0; i < 222; i++ ) + { + for ( k = 0; k < p->nSubgr0[i]; k++ ) + Dar_LibSetup0_rec( p, Dar_LibObj(p, p->pSubgr0[i][k]), i, 0 ); + p->nNodes0Total += p->nNodes0[i]; + p->nNodes0Max = AIG_MAX( p->nNodes0Max, p->nNodes0[i] ); + } + + // clean node counters + for ( i = 0; i < 222; i++ ) + p->nNodes0[i] = 0; + // create traversal IDs + for ( i = 0; i < p->iObj; i++ ) + Dar_LibObj(p, i)->Num = 0xff; + // add the nodes to storage + nNodes0Total = 0; + for ( i = 0; i < 222; i++ ) + { + for ( k = 0; k < p->nSubgr0[i]; k++ ) + Dar_LibSetup0_rec( p, Dar_LibObj(p, p->pSubgr0[i][k]), i, 1 ); + nNodes0Total += p->nNodes0[i]; + } + assert( nNodes0Total == p->nNodes0Total ); + // prepare the number of the PI nodes + for ( i = 0; i < 4; i++ ) + Dar_LibObj(p, i)->Num = i; + + // realloc the datas + Dar_LibCreateData( p, p->nNodes0Max + 32 ); + // allocated more because Dar_LibBuildBest() sometimes requires more entries +} + +/**Function************************************************************* + + Synopsis [Reads library from array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dar_Lib_t * Dar_LibRead() +{ + Vec_Int_t * vObjs, * vOuts, * vPrios; + Dar_Lib_t * p; + int i; + // read nodes and outputs + vObjs = Dar_LibReadNodes(); + vOuts = Dar_LibReadOuts(); + vPrios = Dar_LibReadPrios(); + // create library + p = Dar_LibAlloc( Vec_IntSize(vObjs)/2 + 4 ); + // create nodes + for ( i = 0; i < vObjs->nSize; i += 2 ) + Dar_LibAddNode( p, vObjs->pArray[i] >> 1, vObjs->pArray[i+1] >> 1, + vObjs->pArray[i] & 1, vObjs->pArray[i+1] & 1 ); + // create outputs + Dar_LibSetup( p, vOuts, vPrios ); + Vec_IntFree( vObjs ); + Vec_IntFree( vOuts ); + Vec_IntFree( vPrios ); + return p; +} + +/**Function************************************************************* + + Synopsis [Starts the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibStart() +{ +// int clk = clock(); + assert( s_DarLib == NULL ); + s_DarLib = Dar_LibRead(); +// printf( "The 4-input library started with %d nodes and %d subgraphs. ", s_DarLib->nObjs - 4, s_DarLib->nSubgrTotal ); +// PRT( "Time", clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Stops the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibStop() +{ + assert( s_DarLib != NULL ); + Dar_LibFree( s_DarLib ); + s_DarLib = NULL; +} + +/**Function************************************************************* + + Synopsis [Updates the score of the class and adjusts the priority of this class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibIncrementScore( int Class, int Out, int Gain ) +{ + int * pPrios = s_DarLib->pPrios[Class]; // pPrios[i] = Out + int * pPlace = s_DarLib->pPlace[Class]; // pPlace[Out] = i + int * pScore = s_DarLib->pScore[Class]; // score of Out + int Out2; + assert( Class >= 0 && Class < 222 ); + assert( Out >= 0 && Out < s_DarLib->nSubgr[Class] ); + assert( pPlace[pPrios[Out]] == Out ); + // increment the score + pScore[Out] += Gain; + // move the out in the order + while ( pPlace[Out] > 0 && pScore[Out] > pScore[ pPrios[pPlace[Out]-1] ] ) + { + // get the previous output in the priority list + Out2 = pPrios[pPlace[Out]-1]; + // swap Out and Out2 + pPlace[Out]--; + pPlace[Out2]++; + pPrios[pPlace[Out]] = Out; + pPrios[pPlace[Out2]] = Out2; + } +} + +/**Function************************************************************* + + Synopsis [Prints out the priorities into the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibDumpPriorities() +{ + int i, k, Out, Out2, Counter = 0, Printed = 0; + printf( "\nOutput priorities (total = %d):\n", s_DarLib->nSubgrTotal ); + for ( i = 0; i < 222; i++ ) + { +// printf( "Class%d: ", i ); + for ( k = 0; k < s_DarLib->nSubgr[i]; k++ ) + { + Out = s_DarLib->pPrios[i][k]; + Out2 = k == 0 ? Out : s_DarLib->pPrios[i][k-1]; + assert( s_DarLib->pScore[i][Out2] >= s_DarLib->pScore[i][Out] ); +// printf( "%d(%d), ", Out, s_DarLib->pScore[i][Out] ); + printf( "%d, ", Out ); + Printed++; + if ( ++Counter == 15 ) + { + printf( "\n" ); + Counter = 0; + } + } + } + printf( "\n" ); + assert( Printed == s_DarLib->nSubgrTotal ); +} + + +/**Function************************************************************* + + Synopsis [Matches the cut with its canonical form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_LibCutMatch( Dar_Man_t * p, Dar_Cut_t * pCut ) +{ + Aig_Obj_t * pFanin; + unsigned uPhase; + char * pPerm; + int i; + assert( pCut->nLeaves == 4 ); + // get the fanin permutation + uPhase = s_DarLib->pPhases[pCut->uTruth]; + pPerm = s_DarLib->pPerms4[ (int)s_DarLib->pPerms[pCut->uTruth] ]; + // collect fanins with the corresponding permutation/phase + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + pFanin = Aig_ManObj( p->pAig, pCut->pLeaves[ (int)pPerm[i] ] ); + if ( pFanin == NULL ) + { + p->nCutsBad++; + return 0; + } + pFanin = Aig_NotCond(pFanin, ((uPhase >> i) & 1) ); + s_DarLib->pDatas[i].pFunc = pFanin; + s_DarLib->pDatas[i].Level = Aig_Regular(pFanin)->Level; + } + p->nCutsGood++; + return 1; +} + + + +/**Function************************************************************* + + Synopsis [Marks the MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_LibCutMarkMffc( Aig_Man_t * p, Aig_Obj_t * pRoot, int nLeaves ) +{ + int i, nNodes; + // mark the cut leaves + for ( i = 0; i < nLeaves; i++ ) + Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs++; + // label MFFC with current ID + nNodes = Aig_NodeMffsLabel( p, pRoot ); + // unmark the cut leaves + for ( i = 0; i < nLeaves; i++ ) + Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs--; + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Evaluates one cut.] + + Description [Returns the best gain.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibObjPrint_rec( Dar_LibObj_t * pObj ) +{ + if ( pObj->fTerm ) + { + printf( "%c", 'a' + (int)(pObj - s_DarLib->pObjs) ); + return; + } + printf( "(" ); + Dar_LibObjPrint_rec( Dar_LibObj(s_DarLib, pObj->Fan0) ); + if ( pObj->fCompl0 ) + printf( "\'" ); + Dar_LibObjPrint_rec( Dar_LibObj(s_DarLib, pObj->Fan1) ); + if ( pObj->fCompl0 ) + printf( "\'" ); + printf( ")" ); +} + + +/**Function************************************************************* + + Synopsis [Assigns numbers to the nodes of one class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibEvalAssignNums( Dar_Man_t * p, int Class ) +{ + Dar_LibObj_t * pObj; + Dar_LibDat_t * pData, * pData0, * pData1; + Aig_Obj_t * pFanin0, * pFanin1; + int i; + for ( i = 0; i < s_DarLib->nNodes0[Class]; i++ ) + { + // get one class node, assign its temporary number and set its data + pObj = Dar_LibObj(s_DarLib, s_DarLib->pNodes0[Class][i]); + pObj->Num = 4 + i; + assert( (int)pObj->Num < s_DarLib->nNodes0Max + 4 ); + pData = s_DarLib->pDatas + pObj->Num; + pData->fMffc = 0; + pData->pFunc = NULL; + pData->TravId = 0xFFFF; + + // explore the fanins + assert( (int)Dar_LibObj(s_DarLib, pObj->Fan0)->Num < s_DarLib->nNodes0Max + 4 ); + assert( (int)Dar_LibObj(s_DarLib, pObj->Fan1)->Num < s_DarLib->nNodes0Max + 4 ); + pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num; + pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num; + pData->Level = 1 + AIG_MAX(pData0->Level, pData1->Level); + if ( pData0->pFunc == NULL || pData1->pFunc == NULL ) + continue; + pFanin0 = Aig_NotCond( pData0->pFunc, pObj->fCompl0 ); + pFanin1 = Aig_NotCond( pData1->pFunc, pObj->fCompl1 ); + pData->pFunc = Aig_TableLookupTwo( p->pAig, pFanin0, pFanin1 ); + if ( pData->pFunc ) + { + // update the level to be more accurate + pData->Level = Aig_Regular(pData->pFunc)->Level; + // mark the node if it is part of MFFC + pData->fMffc = Aig_ObjIsTravIdCurrent(p->pAig, pData->pFunc); + } + } +} + +/**Function************************************************************* + + Synopsis [Evaluates one cut.] + + Description [Returns the best gain.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required ) +{ + Dar_LibDat_t * pData; + int Area; + if ( pObj->fTerm ) + return 0; + assert( pObj->Num > 3 ); + pData = s_DarLib->pDatas + pObj->Num; + if ( pData->Level > Required ) + return 0xff; + if ( pData->pFunc && !pData->fMffc ) + return 0; + if ( pData->TravId == Out ) + return 0; + pData->TravId = Out; + // this is a new node - get a bound on the area of its branches + nNodesSaved--; + Area = Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out, nNodesSaved, Required+1 ); + if ( Area > nNodesSaved ) + return 0xff; + Area += Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out, nNodesSaved, Required+1 ); + if ( Area > nNodesSaved ) + return 0xff; + return Area + 1; +} + +/**Function************************************************************* + + Synopsis [Evaluates one cut.] + + Description [Returns the best gain.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required ) +{ + int fTraining = 0; + Dar_LibObj_t * pObj; + int Out, k, Class, nNodesSaved, nNodesAdded, nNodesGained, clk; + clk = clock(); + if ( pCut->nLeaves != 4 ) + return; + // check if the cut exits and assigns leaves and their levels + if ( !Dar_LibCutMatch(p, pCut) ) + return; + // mark MFFC of the node + nNodesSaved = Dar_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves ); + // evaluate the cut + Class = s_DarLib->pMap[pCut->uTruth]; + Dar_LibEvalAssignNums( p, Class ); + // profile outputs by their savings + p->nTotalSubgs += s_DarLib->nSubgr0[Class]; + p->ClassSubgs[Class] += s_DarLib->nSubgr0[Class]; + for ( Out = 0; Out < s_DarLib->nSubgr0[Class]; Out++ ) + { + pObj = Dar_LibObj(s_DarLib, s_DarLib->pSubgr0[Class][Out]); + if ( Aig_Regular(s_DarLib->pDatas[pObj->Num].pFunc) == pRoot ) + continue; + nNodesAdded = Dar_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required ); + nNodesGained = nNodesSaved - nNodesAdded; + if ( fTraining && nNodesGained >= 0 ) + Dar_LibIncrementScore( Class, Out, nNodesGained + 1 ); + if ( nNodesGained < 0 || (nNodesGained == 0 && !p->pPars->fUseZeros) ) + continue; + if ( nNodesGained < p->GainBest || + (nNodesGained == p->GainBest && s_DarLib->pDatas[pObj->Num].Level >= p->LevelBest) ) + continue; + // remember this possibility + Vec_PtrClear( p->vLeavesBest ); + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + Vec_PtrPush( p->vLeavesBest, s_DarLib->pDatas[k].pFunc ); + p->OutBest = s_DarLib->pSubgr0[Class][Out]; + p->OutNumBest = Out; + p->LevelBest = s_DarLib->pDatas[pObj->Num].Level; + p->GainBest = nNodesGained; + p->ClassBest = Class; + assert( p->LevelBest <= Required ); + } +clk = clock() - clk; +p->ClassTimes[Class] += clk; +p->timeEval += clk; +} + +/**Function************************************************************* + + Synopsis [Clears the fields of the nodes used in this cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_LibBuildClear_rec( Dar_LibObj_t * pObj, int * pCounter ) +{ + if ( pObj->fTerm ) + return; + pObj->Num = (*pCounter)++; + s_DarLib->pDatas[ pObj->Num ].pFunc = NULL; + Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan0), pCounter ); + Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan1), pCounter ); +} + +/**Function************************************************************* + + Synopsis [Reconstructs the best cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Dar_LibBuildBest_rec( Dar_Man_t * p, Dar_LibObj_t * pObj ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + Dar_LibDat_t * pData = s_DarLib->pDatas + pObj->Num; + if ( pData->pFunc ) + return pData->pFunc; + pFanin0 = Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan0) ); + pFanin1 = Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan1) ); + pFanin0 = Aig_NotCond( pFanin0, pObj->fCompl0 ); + pFanin1 = Aig_NotCond( pFanin1, pObj->fCompl1 ); + pData->pFunc = Aig_And( p->pAig, pFanin0, pFanin1 ); +// assert( pData->Level == (int)Aig_Regular(pData->pFunc)->Level ); + return pData->pFunc; +} + +/**Function************************************************************* + + Synopsis [Reconstructs the best cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Dar_LibBuildBest( Dar_Man_t * p ) +{ + int i, Counter = 4; + for ( i = 0; i < Vec_PtrSize(p->vLeavesBest); i++ ) + s_DarLib->pDatas[i].pFunc = Vec_PtrEntry( p->vLeavesBest, i ); + Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, p->OutBest), &Counter ); + return Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, p->OutBest) ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/dar/darMan.c b/abc70930/src/aig/dar/darMan.c new file mode 100644 index 00000000..0a5a36b1 --- /dev/null +++ b/abc70930/src/aig/dar/darMan.c @@ -0,0 +1,133 @@ +/**CFile**************************************************************** + + FileName [darMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [AIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: darMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "darInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dar_Man_t * Dar_ManStart( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) +{ + Dar_Man_t * p; + // start the manager + p = ALLOC( Dar_Man_t, 1 ); + memset( p, 0, sizeof(Dar_Man_t) ); + p->pPars = pPars; + p->pAig = pAig; + // prepare the internal memory manager + p->pMemCuts = Aig_MmFixedStart( p->pPars->nCutsMax * sizeof(Dar_Cut_t), 1024 ); + // other data + p->vLeavesBest = Vec_PtrAlloc( 4 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_ManStop( Dar_Man_t * p ) +{ + if ( p->pPars->fVerbose ) + Dar_ManPrintStats( p ); + if ( p->pMemCuts ) + Aig_MmFixedStop( p->pMemCuts, 0 ); + if ( p->vLeavesBest ) + Vec_PtrFree( p->vLeavesBest ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_ManPrintStats( Dar_Man_t * p ) +{ + unsigned pCanons[222]; + int Gain, i; + extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); + + Gain = p->nNodesInit - Aig_ManNodeNum(p->pAig); + printf( "Tried = %8d. Beg = %8d. End = %8d. Gain = %6d. (%6.2f %%). Cut mem = %d Mb\n", + p->nNodesTried, p->nNodesInit, Aig_ManNodeNum(p->pAig), Gain, 100.0*Gain/p->nNodesInit, p->nCutMemUsed ); + printf( "Cuts = %8d. Tried = %8d. Used = %8d. Bad = %5d. Skipped = %5d. Ave = %.2f.\n", + p->nCutsAll, p->nCutsTried, p->nCutsUsed, p->nCutsBad, p->nCutsSkipped, + (float)p->nCutsUsed/Aig_ManNodeNum(p->pAig) ); + + printf( "Bufs = %5d. BufMax = %5d. BufReplace = %6d. BufFix = %6d. Levels = %4d.\n", + Aig_ManBufNum(p->pAig), p->pAig->nBufMax, p->pAig->nBufReplaces, p->pAig->nBufFixes, Aig_ManLevels(p->pAig) ); + PRT( "Cuts ", p->timeCuts ); + PRT( "Eval ", p->timeEval ); + PRT( "Other ", p->timeOther ); + PRT( "TOTAL ", p->timeTotal ); + + if ( !p->pPars->fVeryVerbose ) + return; + Dar_LibReturnCanonicals( pCanons ); + for ( i = 0; i < 222; i++ ) + { + if ( p->ClassGains[i] == 0 && p->ClassTimes[i] == 0 ) + continue; + printf( "%3d : ", i ); + printf( "G = %6d (%5.2f %%) ", p->ClassGains[i], Gain? 100.0*p->ClassGains[i]/Gain : 0.0 ); + printf( "S = %8d (%5.2f %%) ", p->ClassSubgs[i], p->nTotalSubgs? 100.0*p->ClassSubgs[i]/p->nTotalSubgs : 0.0 ); + printf( "R = %7d ", p->ClassGains[i]? p->ClassSubgs[i]/p->ClassGains[i] : 9999999 ); +// Kit_DsdPrintFromTruth( pCanons + i, 4 ); +// PRTP( "T", p->ClassTimes[i], p->timeEval ); + printf( "\n" ); + } +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/dar/darPrec.c b/abc70930/src/aig/dar/darPrec.c new file mode 100644 index 00000000..8c3a4ce3 --- /dev/null +++ b/abc70930/src/aig/dar/darPrec.c @@ -0,0 +1,387 @@ +/**CFile**************************************************************** + + FileName [darPrec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [Truth table precomputation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: darPrec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "darInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocated one-memory-chunk array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char ** Dar_ArrayAlloc( int nCols, int nRows, int Size ) +{ + char ** pRes; + char * pBuffer; + int i; + assert( nCols > 0 && nRows > 0 && Size > 0 ); + pBuffer = ALLOC( char, nCols * (sizeof(void *) + nRows * Size) ); + pRes = (char **)pBuffer; + pRes[0] = pBuffer + nCols * sizeof(void *); + for ( i = 1; i < nCols; i++ ) + pRes[i] = pRes[0] + i * nRows * Size; + return pRes; +} + +/**Function******************************************************************** + + Synopsis [Computes the factorial.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Dar_Factorial( int n ) +{ + int i, Res = 1; + for ( i = 1; i <= n; i++ ) + Res *= i; + return Res; +} + +/**Function******************************************************************** + + Synopsis [Fills in the array of permutations.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Dar_Permutations_rec( char ** pRes, int nFact, int n, char Array[] ) +{ + char ** pNext; + int nFactNext; + int iTemp, iCur, iLast, k; + + if ( n == 1 ) + { + pRes[0][0] = Array[0]; + return; + } + + // get the next factorial + nFactNext = nFact / n; + // get the last entry + iLast = n - 1; + + for ( iCur = 0; iCur < n; iCur++ ) + { + // swap Cur and Last + iTemp = Array[iCur]; + Array[iCur] = Array[iLast]; + Array[iLast] = iTemp; + + // get the pointer to the current section + pNext = pRes + (n - 1 - iCur) * nFactNext; + + // set the last entry + for ( k = 0; k < nFactNext; k++ ) + pNext[k][iLast] = Array[iLast]; + + // call recursively for this part + Dar_Permutations_rec( pNext, nFactNext, n - 1, Array ); + + // swap them back + iTemp = Array[iCur]; + Array[iCur] = Array[iLast]; + Array[iLast] = iTemp; + } +} + +/**Function******************************************************************** + + Synopsis [Computes the set of all permutations.] + + Description [The number of permutations in the array is n!. The number of + entries in each permutation is n. Therefore, the resulting array is a + two-dimentional array of the size: n! x n. To free the resulting array, + call free() on the pointer returned by this procedure.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +char ** Dar_Permutations( int n ) +{ + char Array[50]; + char ** pRes; + int nFact, i; + // allocate memory + nFact = Dar_Factorial( n ); + pRes = Dar_ArrayAlloc( nFact, n, sizeof(char) ); + // fill in the permutations + for ( i = 0; i < n; i++ ) + Array[i] = i; + Dar_Permutations_rec( pRes, nFact, n, Array ); + // print the permutations +/* + { + int i, k; + for ( i = 0; i < nFact; i++ ) + { + printf( "{" ); + for ( k = 0; k < n; k++ ) + printf( " %d", pRes[i][k] ); + printf( " }\n" ); + } + } +*/ + return pRes; +} + +/**Function************************************************************* + + Synopsis [Permutes the given vector of minterms.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_TruthPermute_int( int * pMints, int nMints, char * pPerm, int nVars, int * pMintsP ) +{ + int m, v; + // clean the storage for minterms + memset( pMintsP, 0, sizeof(int) * nMints ); + // go through minterms and add the variables + for ( m = 0; m < nMints; m++ ) + for ( v = 0; v < nVars; v++ ) + if ( pMints[m] & (1 << v) ) + pMintsP[m] |= (1 << pPerm[v]); +} + +/**Function************************************************************* + + Synopsis [Permutes the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Dar_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse ) +{ + unsigned Result; + int * pMints; + int * pMintsP; + int nMints; + int i, m; + + assert( nVars < 6 ); + nMints = (1 << nVars); + pMints = ALLOC( int, nMints ); + pMintsP = ALLOC( int, nMints ); + for ( i = 0; i < nMints; i++ ) + pMints[i] = i; + + Dar_TruthPermute_int( pMints, nMints, pPerms, nVars, pMintsP ); + + Result = 0; + if ( fReverse ) + { + for ( m = 0; m < nMints; m++ ) + if ( Truth & (1 << pMintsP[m]) ) + Result |= (1 << m); + } + else + { + for ( m = 0; m < nMints; m++ ) + if ( Truth & (1 << m) ) + Result |= (1 << pMintsP[m]); + } + + free( pMints ); + free( pMintsP ); + + return Result; +} + +/**Function************************************************************* + + Synopsis [Changes the phase of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Dar_TruthPolarize( unsigned uTruth, int Polarity, int nVars ) +{ + // elementary truth tables + static unsigned Signs[5] = { + 0xAAAAAAAA, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0xCCCCCCCC, // 1010 1010 1010 1010 1010 1010 1010 1010 + 0xF0F0F0F0, // 1111 0000 1111 0000 1111 0000 1111 0000 + 0xFF00FF00, // 1111 1111 0000 0000 1111 1111 0000 0000 + 0xFFFF0000 // 1111 1111 1111 1111 0000 0000 0000 0000 + }; + unsigned uTruthRes, uCof0, uCof1; + int nMints, Shift, v; + assert( nVars < 6 ); + nMints = (1 << nVars); + uTruthRes = uTruth; + for ( v = 0; v < nVars; v++ ) + if ( Polarity & (1 << v) ) + { + uCof0 = uTruth & ~Signs[v]; + uCof1 = uTruth & Signs[v]; + Shift = (1 << v); + uCof0 <<= Shift; + uCof1 >>= Shift; + uTruth = uCof0 | uCof1; + } + return uTruth; +} + +/**Function************************************************************* + + Synopsis [Computes NPN canonical forms for 4-variable functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ) +{ + unsigned short * uCanons; + unsigned char * uMap; + unsigned uTruth, uPhase, uPerm; + char ** pPerms4, * uPhases, * uPerms; + int nFuncs, nClasses; + int i, k; + + nFuncs = (1 << 16); + uCanons = ALLOC( unsigned short, nFuncs ); + uPhases = ALLOC( char, nFuncs ); + uPerms = ALLOC( char, nFuncs ); + uMap = ALLOC( unsigned char, nFuncs ); + memset( uCanons, 0, sizeof(unsigned short) * nFuncs ); + memset( uPhases, 0, sizeof(char) * nFuncs ); + memset( uPerms, 0, sizeof(char) * nFuncs ); + memset( uMap, 0, sizeof(unsigned char) * nFuncs ); + pPerms4 = Dar_Permutations( 4 ); + + nClasses = 1; + nFuncs = (1 << 15); + for ( uTruth = 1; uTruth < (unsigned)nFuncs; uTruth++ ) + { + // skip already assigned + if ( uCanons[uTruth] ) + { + assert( uTruth > uCanons[uTruth] ); + uMap[~uTruth & 0xFFFF] = uMap[uTruth] = uMap[uCanons[uTruth]]; + continue; + } + uMap[uTruth] = nClasses++; + for ( i = 0; i < 16; i++ ) + { + uPhase = Dar_TruthPolarize( uTruth, i, 4 ); + for ( k = 0; k < 24; k++ ) + { + uPerm = Dar_TruthPermute( uPhase, pPerms4[k], 4, 0 ); + if ( uCanons[uPerm] == 0 ) + { + uCanons[uPerm] = uTruth; + uPhases[uPerm] = i; + uPerms[uPerm] = k; + + uPerm = ~uPerm & 0xFFFF; + uCanons[uPerm] = uTruth; + uPhases[uPerm] = i | 16; + uPerms[uPerm] = k; + } + else + assert( uCanons[uPerm] == uTruth ); + } + uPhase = Dar_TruthPolarize( ~uTruth & 0xFFFF, i, 4 ); + for ( k = 0; k < 24; k++ ) + { + uPerm = Dar_TruthPermute( uPhase, pPerms4[k], 4, 0 ); + if ( uCanons[uPerm] == 0 ) + { + uCanons[uPerm] = uTruth; + uPhases[uPerm] = i; + uPerms[uPerm] = k; + + uPerm = ~uPerm & 0xFFFF; + uCanons[uPerm] = uTruth; + uPhases[uPerm] = i | 16; + uPerms[uPerm] = k; + } + else + assert( uCanons[uPerm] == uTruth ); + } + } + } + uPhases[(1<<16)-1] = 16; + assert( nClasses == 222 ); + free( pPerms4 ); + if ( puCanons ) + *puCanons = uCanons; + else + free( uCanons ); + if ( puPhases ) + *puPhases = uPhases; + else + free( uPhases ); + if ( puPerms ) + *puPerms = uPerms; + else + free( uPerms ); + if ( puMap ) + *puMap = uMap; + else + free( uMap ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/dar/darRefact.c b/abc70930/src/aig/dar/darRefact.c new file mode 100644 index 00000000..a765ec30 --- /dev/null +++ b/abc70930/src/aig/dar/darRefact.c @@ -0,0 +1,591 @@ +/**CFile**************************************************************** + + FileName [darRefact.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [Refactoring.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: darRefact.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "darInt.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the refactoring manager +typedef struct Ref_Man_t_ Ref_Man_t; +struct Ref_Man_t_ +{ + // input data + Dar_RefPar_t * pPars; // rewriting parameters + Aig_Man_t * pAig; // AIG manager + // computed cuts + Vec_Vec_t * vCuts; // the storage for cuts + // truth table and ISOP + Vec_Ptr_t * vTruthElem; // elementary truth tables + Vec_Ptr_t * vTruthStore; // storage for truth tables + Vec_Int_t * vMemory; // storage for ISOP + Vec_Ptr_t * vCutNodes; // storage for internal nodes of the cut + // various data members + Vec_Ptr_t * vLeavesBest; // the best set of leaves + Kit_Graph_t * pGraphBest; // the best factored form + int GainBest; // the best gain + int LevelBest; // the level of node with the best gain + // node statistics + int nNodesInit; // the initial number of nodes + int nNodesTried; // the number of nodes tried + int nNodesBelow; // the number of nodes below the level limit + int nNodesExten; // the number of nodes with extended cut + int nCutsUsed; // the number of rewriting steps + int nCutsTried; // the number of cuts tries + // timing statistics + int timeCuts; + int timeEval; + int timeOther; + int timeTotal; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the structure with default assignment of parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_ManDefaultRefParams( Dar_RefPar_t * pPars ) +{ + memset( pPars, 0, sizeof(Dar_RefPar_t) ); + pPars->nMffcMin = 2; // the min MFFC size for which refactoring is used + pPars->nLeafMax = 12; // the max number of leaves of a cut + pPars->nCutsMax = 5; // the max number of cuts to consider + pPars->fUpdateLevel = 0; + pPars->fUseZeros = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; +} + +/**Function************************************************************* + + Synopsis [Starts the rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ref_Man_t * Dar_ManRefStart( Aig_Man_t * pAig, Dar_RefPar_t * pPars ) +{ + Ref_Man_t * p; + // start the manager + p = ALLOC( Ref_Man_t, 1 ); + memset( p, 0, sizeof(Ref_Man_t) ); + p->pAig = pAig; + p->pPars = pPars; + // other data + p->vCuts = Vec_VecStart( pPars->nCutsMax ); + p->vTruthElem = Vec_PtrAllocTruthTables( pPars->nLeafMax ); + p->vTruthStore = Vec_PtrAllocSimInfo( 256, Kit_TruthWordNum(pPars->nLeafMax) ); + p->vMemory = Vec_IntAlloc( 1 << 16 ); + p->vCutNodes = Vec_PtrAlloc( 256 ); + p->vLeavesBest = Vec_PtrAlloc( pPars->nLeafMax ); + return p; +} + +/**Function************************************************************* + + Synopsis [Prints out the statistics of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_ManRefPrintStats( Ref_Man_t * p ) +{ + int Gain = p->nNodesInit - Aig_ManNodeNum(p->pAig); + printf( "NodesBeg = %8d. NodesEnd = %8d. Gain = %6d. (%6.2f %%).\n", + p->nNodesInit, Aig_ManNodeNum(p->pAig), Gain, 100.0*Gain/p->nNodesInit ); + printf( "Tried = %6d. Below = %5d. Extended = %5d. Used = %5d. Levels = %4d.\n", + p->nNodesTried, p->nNodesBelow, p->nNodesExten, p->nCutsUsed, Aig_ManLevels(p->pAig) ); + PRT( "Cuts ", p->timeCuts ); + PRT( "Eval ", p->timeEval ); + PRT( "Other ", p->timeOther ); + PRT( "TOTAL ", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Stops the rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dar_ManRefStop( Ref_Man_t * p ) +{ + if ( p->pPars->fVerbose ) + Dar_ManRefPrintStats( p ); + Vec_VecFree( p->vCuts ); + Vec_PtrFree( p->vTruthElem ); + Vec_PtrFree( p->vTruthStore ); + Vec_PtrFree( p->vLeavesBest ); + Vec_IntFree( p->vMemory ); + Vec_PtrFree( p->vCutNodes ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ref_ObjComputeCuts( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Vec_t * vCuts ) +{ +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ref_ObjPrint( Aig_Obj_t * pObj ) +{ + printf( "%d", pObj? Aig_Regular(pObj)->Id : -1 ); + if ( pObj ) + printf( "(%d) ", Aig_IsComplement(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of new nodes added when using this graph.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure. + Returns -1 if the number of nodes and levels exceeded the given limit or + the number of levels exceeded the maximum allowed level.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_RefactTryGraph( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph, int NodeMax, int LevelMax ) +{ + Kit_Node_t * pNode, * pNode0, * pNode1; + Aig_Obj_t * pAnd, * pAnd0, * pAnd1; + int i, Counter, LevelNew, LevelOld; + // check for constant function or a literal + if ( Kit_GraphIsConst(pGraph) || Kit_GraphIsVar(pGraph) ) + return 0; + // set the levels of the leaves + Kit_GraphForEachLeaf( pGraph, pNode, i ) + { + pNode->pFunc = Vec_PtrEntry(vCut, i); + pNode->Level = Aig_Regular(pNode->pFunc)->Level; + assert( Aig_Regular(pNode->pFunc)->Level < (1<<14)-1 ); + } +//printf( "Trying:\n" ); + // compute the AIG size after adding the internal nodes + Counter = 0; + Kit_GraphForEachNode( pGraph, pNode, i ) + { + // get the children of this node + pNode0 = Kit_GraphNode( pGraph, pNode->eEdge0.Node ); + pNode1 = Kit_GraphNode( pGraph, pNode->eEdge1.Node ); + // get the AIG nodes corresponding to the children + pAnd0 = pNode0->pFunc; + pAnd1 = pNode1->pFunc; + if ( pAnd0 && pAnd1 ) + { + // if they are both present, find the resulting node + pAnd0 = Aig_NotCond( pAnd0, pNode->eEdge0.fCompl ); + pAnd1 = Aig_NotCond( pAnd1, pNode->eEdge1.fCompl ); + pAnd = Aig_TableLookupTwo( pAig, pAnd0, pAnd1 ); + // return -1 if the node is the same as the original root + if ( Aig_Regular(pAnd) == pRoot ) + return -1; + } + else + pAnd = NULL; + // count the number of added nodes + if ( pAnd == NULL || Aig_ObjIsTravIdCurrent(pAig, Aig_Regular(pAnd)) ) + { + if ( ++Counter > NodeMax ) + return -1; + } + // count the number of new levels + LevelNew = 1 + AIG_MAX( pNode0->Level, pNode1->Level ); + if ( pAnd ) + { + if ( Aig_Regular(pAnd) == Aig_ManConst1(pAig) ) + LevelNew = 0; + else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd0) ) + LevelNew = (int)Aig_Regular(pAnd0)->Level; + else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd1) ) + LevelNew = (int)Aig_Regular(pAnd1)->Level; + LevelOld = (int)Aig_Regular(pAnd)->Level; +// assert( LevelNew == LevelOld ); + } + if ( LevelNew > LevelMax ) + return -1; + pNode->pFunc = pAnd; + pNode->Level = LevelNew; +/* +printf( "Checking " ); +Ref_ObjPrint( pAnd0 ); +printf( " and " ); +Ref_ObjPrint( pAnd1 ); +printf( " Result " ); +Ref_ObjPrint( pNode->pFunc ); +printf( "\n" ); +*/ + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Dar_RefactBuildGraph( Aig_Man_t * pAig, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph ) +{ + Aig_Obj_t * pAnd0, * pAnd1; + Kit_Node_t * pNode = NULL; + int i; + // check for constant function + if ( Kit_GraphIsConst(pGraph) ) + return Aig_NotCond( Aig_ManConst1(pAig), Kit_GraphIsComplement(pGraph) ); + // set the leaves + Kit_GraphForEachLeaf( pGraph, pNode, i ) + pNode->pFunc = Vec_PtrEntry(vCut, i); + // check for a literal + if ( Kit_GraphIsVar(pGraph) ) + return Aig_NotCond( Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph +//printf( "Building (current number %d):\n", Aig_ManObjNumMax(pAig) ); + Kit_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Aig_NotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Aig_NotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Aig_And( pAig, pAnd0, pAnd1 ); +/* +printf( "Checking " ); +Ref_ObjPrint( pAnd0 ); +printf( " and " ); +Ref_ObjPrint( pAnd1 ); +printf( " Result " ); +Ref_ObjPrint( pNode->pFunc ); +printf( "\n" ); +*/ + } + // complement the result if necessary + return Aig_NotCond( pNode->pFunc, Kit_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_ManRefactorTryCuts( Ref_Man_t * p, Aig_Obj_t * pObj, int nNodesSaved, int Required ) +{ + Vec_Ptr_t * vCut; + Kit_Graph_t * pGraphCur; + int k, RetValue, GainCur, nNodesAdded; + unsigned * pTruth; + + p->GainBest = -1; + p->pGraphBest = NULL; + Vec_VecForEachLevel( p->vCuts, vCut, k ) + { + if ( Vec_PtrSize(vCut) == 0 ) + continue; +// if ( Vec_PtrSize(vCut) != 0 && Vec_PtrSize(Vec_VecEntry(p->vCuts, k+1)) != 0 ) +// continue; + + p->nCutsTried++; + // get the cut nodes + Aig_ObjCollectCut( pObj, vCut, p->vCutNodes ); + // get the truth table + pTruth = Aig_ManCutTruth( pObj, vCut, p->vCutNodes, p->vTruthElem, p->vTruthStore ); + if ( Kit_TruthIsConst0(pTruth, Vec_PtrSize(vCut)) ) + { + p->GainBest = Vec_PtrSize(p->vCutNodes); + p->pGraphBest = Kit_GraphCreateConst0(); + Vec_PtrCopy( p->vLeavesBest, vCut ); + return p->GainBest; + } + if ( Kit_TruthIsConst1(pTruth, Vec_PtrSize(vCut)) ) + { + p->GainBest = Vec_PtrSize(p->vCutNodes); + p->pGraphBest = Kit_GraphCreateConst1(); + Vec_PtrCopy( p->vLeavesBest, vCut ); + return p->GainBest; + } + + // try the positive phase + RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 ); + if ( RetValue > -1 ) + { + pGraphCur = Kit_SopFactor( p->vMemory, 0, Vec_PtrSize(vCut), p->vMemory ); + nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required ); + if ( nNodesAdded > -1 ) + { + GainCur = nNodesSaved - nNodesAdded; + if ( p->GainBest < GainCur || (p->GainBest == GainCur && + (Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) ) + { + p->GainBest = GainCur; + if ( p->pGraphBest ) + Kit_GraphFree( p->pGraphBest ); + p->pGraphBest = pGraphCur; + Vec_PtrCopy( p->vLeavesBest, vCut ); + } + else + Kit_GraphFree( pGraphCur ); + } + else + Kit_GraphFree( pGraphCur ); + } + // try negative phase + Kit_TruthNot( pTruth, pTruth, Vec_PtrSize(vCut) ); + RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 ); + if ( RetValue > -1 ) + { + pGraphCur = Kit_SopFactor( p->vMemory, 1, Vec_PtrSize(vCut), p->vMemory ); + nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required ); + if ( nNodesAdded > -1 ) + { + GainCur = nNodesSaved - nNodesAdded; + if ( p->GainBest < GainCur || (p->GainBest == GainCur && + (Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) ) + { + p->GainBest = GainCur; + if ( p->pGraphBest ) + Kit_GraphFree( p->pGraphBest ); + p->pGraphBest = pGraphCur; + Vec_PtrCopy( p->vLeavesBest, vCut ); + } + else + Kit_GraphFree( pGraphCur ); + } + else + Kit_GraphFree( pGraphCur ); + } + } + return p->GainBest; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if a non-PI node has nLevelMin or below.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_ObjCutLevelAchieved( Vec_Ptr_t * vCut, int nLevelMin ) +{ + Aig_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( vCut, pObj, i ) + if ( !Aig_ObjIsPi(pObj) && (int)pObj->Level <= nLevelMin ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars ) +{ +// Bar_Progress_t * pProgress; + Ref_Man_t * p; + Vec_Ptr_t * vCut, * vCut2; + Aig_Obj_t * pObj, * pObjNew; + int nNodesOld, nNodeBefore, nNodeAfter, nNodesSaved, nNodesSaved2; + int i, Required, nLevelMin, clkStart, clk; + + // start the manager + p = Dar_ManRefStart( pAig, pPars ); + // remove dangling nodes + Aig_ManCleanup( pAig ); + // if updating levels is requested, start fanout and timing + Aig_ManFanoutStart( pAig ); + if ( p->pPars->fUpdateLevel ) + Aig_ManStartReverseLevels( pAig, 0 ); + + // resynthesize each node once + clkStart = clock(); + vCut = Vec_VecEntry( p->vCuts, 0 ); + vCut2 = Vec_VecEntry( p->vCuts, 1 ); + p->nNodesInit = Aig_ManNodeNum(pAig); + nNodesOld = Vec_PtrSize( pAig->vObjs ); +// pProgress = Bar_ProgressStart( stdout, nNodesOld ); + Aig_ManForEachObj( pAig, pObj, i ) + { +// Bar_ProgressUpdate( pProgress, i, NULL ); + if ( !Aig_ObjIsNode(pObj) ) + continue; + if ( i > nNodesOld ) + break; + Vec_VecClear( p->vCuts ); + +//printf( "\nConsidering node %d.\n", pObj->Id ); + // get the bounded MFFC size +clk = clock(); + nLevelMin = AIG_MAX( 0, Aig_ObjLevel(pObj) - 10 ); + nNodesSaved = Aig_NodeMffsSupp( pAig, pObj, nLevelMin, vCut ); + if ( nNodesSaved < p->pPars->nMffcMin ) // too small to consider + { +p->timeCuts += clock() - clk; + continue; + } + p->nNodesTried++; + if ( Vec_PtrSize(vCut) > p->pPars->nLeafMax ) // get one reconv-driven cut + { + Aig_ManFindCut( pObj, vCut, p->vCutNodes, p->pPars->nLeafMax, 50 ); + nNodesSaved = Aig_NodeMffsLabelCut( p->pAig, pObj, vCut ); + } + else if ( Vec_PtrSize(vCut) < p->pPars->nLeafMax - 2 && p->pPars->fExtend ) + { + if ( !Dar_ObjCutLevelAchieved(vCut, nLevelMin) ) + { + if ( Aig_NodeMffsExtendCut( pAig, pObj, vCut, vCut2 ) ) + { + nNodesSaved2 = Aig_NodeMffsLabelCut( p->pAig, pObj, vCut ); + assert( nNodesSaved2 == nNodesSaved ); + } + if ( Vec_PtrSize(vCut2) > p->pPars->nLeafMax ) + Vec_PtrClear(vCut2); + if ( Vec_PtrSize(vCut2) > 0 ) + { + p->nNodesExten++; +// printf( "%d(%d) ", Vec_PtrSize(vCut), Vec_PtrSize(vCut2) ); + } + } + else + p->nNodesBelow++; + } +p->timeCuts += clock() - clk; + + // try the cuts +clk = clock(); + Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : AIG_INFINITY; + Dar_ManRefactorTryCuts( p, pObj, nNodesSaved, Required ); +p->timeEval += clock() - clk; + + // check the best gain + if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) + { + if ( p->pGraphBest ) + Kit_GraphFree( p->pGraphBest ); + continue; + } +//printf( "\n" ); + + // if we end up here, a rewriting step is accepted + nNodeBefore = Aig_ManNodeNum( pAig ); + pObjNew = Dar_RefactBuildGraph( pAig, p->vLeavesBest, p->pGraphBest ); + assert( (int)Aig_Regular(pObjNew)->Level <= Required ); + // replace the node + Aig_ObjReplace( pAig, pObj, pObjNew, 1, p->pPars->fUpdateLevel ); + // compare the gains + nNodeAfter = Aig_ManNodeNum( pAig ); + assert( p->GainBest <= nNodeBefore - nNodeAfter ); + Kit_GraphFree( p->pGraphBest ); + p->nCutsUsed++; +// break; + } +p->timeTotal = clock() - clkStart; +p->timeOther = p->timeTotal - p->timeCuts - p->timeEval; + +// Bar_ProgressStop( pProgress ); + // put the nodes into the DFS order and reassign their IDs +// Aig_NtkReassignIds( p ); + // fix the levels + Aig_ManFanoutStop( pAig ); + if ( p->pPars->fUpdateLevel ) + Aig_ManStopReverseLevels( pAig ); + + // stop the rewriting manager + Dar_ManRefStop( p ); + Aig_ManCheckPhase( pAig ); + if ( !Aig_ManCheck( pAig ) ) + { + printf( "Dar_ManRefactor: The network check has failed.\n" ); + return 0; + } + return 1; + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/dar/darResub.c b/abc70930/src/aig/dar/darResub.c new file mode 100644 index 00000000..f819934e --- /dev/null +++ b/abc70930/src/aig/dar/darResub.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [darResub.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: darResub.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "darInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/dar/darScript.c b/abc70930/src/aig/dar/darScript.c new file mode 100644 index 00000000..bd1d7ac1 --- /dev/null +++ b/abc70930/src/aig/dar/darScript.c @@ -0,0 +1,392 @@ +/**CFile**************************************************************** + + FileName [darScript.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [Rewriting scripts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: darScript.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "darInt.h" +//#include "ioa.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs one iteration of AIG rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_ManRewriteDefault( Aig_Man_t * pAig ) +{ + Aig_Man_t * pTemp; + Dar_RwrPar_t Pars, * pPars = &Pars; + Dar_ManDefaultRwrParams( pPars ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + Dar_ManRewrite( pAig, pPars ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + return pAig; +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [] + + SideEffects [This procedure does not tighten level during restructuring.] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose ) +//alias rwsat "st; rw -l; b -l; rw -l; rf -l" +{ + Aig_Man_t * pTemp; + + Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr; + Dar_RefPar_t ParsRef, * pParsRef = &ParsRef; + + Dar_ManDefaultRwrParams( pParsRwr ); + Dar_ManDefaultRefParams( pParsRef ); + + pParsRwr->fUpdateLevel = 0; + pParsRef->fUpdateLevel = 0; + + pParsRwr->fVerbose = fVerbose; + pParsRef->fVerbose = fVerbose; + + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + } + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + + return pAig; +} + + +/**Function************************************************************* + + Synopsis [Reproduces script "compress".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ) +//alias compress2 "b -l; rw -l; rwz -l; b -l; rwz -l; b -l" +{ + Aig_Man_t * pTemp; + + Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr; + Dar_RefPar_t ParsRef, * pParsRef = &ParsRef; + + Dar_ManDefaultRwrParams( pParsRwr ); + Dar_ManDefaultRefParams( pParsRef ); + + pParsRwr->fUpdateLevel = fUpdateLevel; + pParsRef->fUpdateLevel = fUpdateLevel; + + pParsRwr->fVerbose = 0;//fVerbose; + pParsRef->fVerbose = 0;//fVerbose; + + pAig = Aig_ManDup( pAig, 0 ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { +// pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); +// Aig_ManStop( pTemp ); +// if ( fVerbose ) Aig_ManPrintStats( pAig ); + } + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + } + + pParsRwr->fUseZeros = 1; + pParsRef->fUseZeros = 1; + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + return pAig; +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ) +//alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l" +{ + Aig_Man_t * pTemp; + + Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr; + Dar_RefPar_t ParsRef, * pParsRef = &ParsRef; + + Dar_ManDefaultRwrParams( pParsRwr ); + Dar_ManDefaultRefParams( pParsRef ); + + pParsRwr->fUpdateLevel = fUpdateLevel; + pParsRef->fUpdateLevel = fUpdateLevel; + + pParsRwr->fVerbose = 0;//fVerbose; + pParsRef->fVerbose = 0;//fVerbose; + + pAig = Aig_ManDup( pAig, 0 ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { +// pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); +// Aig_ManStop( pTemp ); +// if ( fVerbose ) Aig_ManPrintStats( pAig ); + } + + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // balance +// if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + } + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + pParsRwr->fUseZeros = 1; + pParsRef->fUseZeros = 1; + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + } + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDup( pTemp = pAig, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + } + return pAig; +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ) +//alias resyn "b; rw; rwz; b; rwz; b" +//alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" +{ + Vec_Ptr_t * vAigs; + vAigs = Vec_PtrAlloc( 3 ); + pAig = Aig_ManDup(pAig, 0); + Vec_PtrPush( vAigs, pAig ); + pAig = Dar_ManCompress (pAig, 0, fUpdateLevel, fVerbose); + Vec_PtrPush( vAigs, pAig ); + pAig = Dar_ManCompress2(pAig, fBalance, fUpdateLevel, fVerbose); + Vec_PtrPush( vAigs, pAig ); + return vAigs; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +Vec_Ptr_t * Dar_ManChoiceSynthesisExt() +{ + Vec_Ptr_t * vAigs; + Aig_Man_t * pMan; + vAigs = Vec_PtrAlloc( 3 ); + pMan = Ioa_ReadAiger( "i10_1.aig", 1 ); + Vec_PtrPush( vAigs, pMan ); + pMan = Ioa_ReadAiger( "i10_2.aig", 1 ); + Vec_PtrPush( vAigs, pMan ); + pMan = Ioa_ReadAiger( "i10_3.aig", 1 ); + Vec_PtrPush( vAigs, pMan ); + return vAigs; +} +*/ + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ) +{ +/* + Aig_Man_t * pMan, * pTemp; + Vec_Ptr_t * vAigs; + int i, clk; + +clk = clock(); +// vAigs = Dar_ManChoiceSynthesisExt(); + vAigs = Dar_ManChoiceSynthesis( pAig, fBalance, fUpdateLevel, fVerbose ); + + // swap the first and last network + // this should lead to the primary choice being "better" because of synthesis + pMan = Vec_PtrPop( vAigs ); + Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); + Vec_PtrWriteEntry( vAigs, 0, pMan ); + +if ( fVerbose ) +{ +PRT( "Synthesis time", clock() - clk ); +} +clk = clock(); + pMan = Aig_ManChoicePartitioned( vAigs, 300 ); + Vec_PtrForEachEntry( vAigs, pTemp, i ) + Aig_ManStop( pTemp ); + Vec_PtrFree( vAigs ); +if ( fVerbose ) +{ +PRT( "Choicing time ", clock() - clk ); +} + return pMan; +*/ + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/dar/dar_.c b/abc70930/src/aig/dar/dar_.c new file mode 100644 index 00000000..12fd7d17 --- /dev/null +++ b/abc70930/src/aig/dar/dar_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [dar_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: dar_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "darInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/dar/module.make b/abc70930/src/aig/dar/module.make new file mode 100644 index 00000000..b1b0332c --- /dev/null +++ b/abc70930/src/aig/dar/module.make @@ -0,0 +1,10 @@ +SRC += src/aig/dar/darBalance.c \ + src/aig/dar/darCore.c \ + src/aig/dar/darCut.c \ + src/aig/dar/darData.c \ + src/aig/dar/darLib.c \ + src/aig/dar/darMan.c \ + src/aig/dar/darPrec.c \ + src/aig/dar/darRefact.c \ + src/aig/dar/darResub.c \ + src/aig/dar/darScript.c diff --git a/abc70930/src/aig/deco/deco.h b/abc70930/src/aig/deco/deco.h new file mode 100644 index 00000000..67126902 --- /dev/null +++ b/abc70930/src/aig/deco/deco.h @@ -0,0 +1,703 @@ +/**CFile**************************************************************** + + FileName [deco.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [A simple decomposition tree/node data structure and its APIs.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: deco.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __DEC_H__ +#define __DEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Dec_Edge_t_ Dec_Edge_t; +struct Dec_Edge_t_ +{ + unsigned fCompl : 1; // the complemented bit + unsigned Node : 30; // the decomposition node pointed by the edge +}; + +typedef struct Dec_Node_t_ Dec_Node_t; +struct Dec_Node_t_ +{ + Dec_Edge_t eEdge0; // the left child of the node + Dec_Edge_t eEdge1; // the right child of the node + // other info + void * pFunc; // the function of the node (BDD or AIG) + unsigned Level : 14; // the level of this node in the global AIG + // printing info + unsigned fNodeOr : 1; // marks the original OR node + unsigned fCompl0 : 1; // marks the original complemented edge + unsigned fCompl1 : 1; // marks the original complemented edge + // latch info + unsigned nLat0 : 5; // the number of latches on the first edge + unsigned nLat1 : 5; // the number of latches on the second edge + unsigned nLat2 : 5; // the number of latches on the output edge +}; + +typedef struct Dec_Graph_t_ Dec_Graph_t; +struct Dec_Graph_t_ +{ + int fConst; // marks the constant 1 graph + int nLeaves; // the number of leaves + int nSize; // the number of nodes (including the leaves) + int nCap; // the number of allocated nodes + Dec_Node_t * pNodes; // the array of leaves and internal nodes + Dec_Edge_t eRoot; // the pointer to the topmost node +}; + +typedef struct Dec_Man_t_ Dec_Man_t; +struct Dec_Man_t_ +{ + void * pMvcMem; // memory manager for MVC cover (used for factoring) + Vec_Int_t * vCubes; // storage for cubes + Vec_Int_t * vLits; // storage for literals + // precomputation information about 4-variable functions + unsigned short * puCanons; // canonical forms + char * pPhases; // canonical phases + char * pPerms; // canonical permutations + unsigned char * pMap; // mapping of functions into class numbers +}; + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// interator throught the leaves +#define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \ + for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ ) +// interator throught the internal nodes +#define Dec_GraphForEachNode( pGraph, pAnd, i ) \ + for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates an edge pointing to the node in the given polarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl ) +{ + Dec_Edge_t eEdge = { fCompl, Node }; + return eEdge; +} + +/**Function************************************************************* + + Synopsis [Converts the edge into unsigned integer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge ) +{ + return (eEdge.Node << 1) | eEdge.fCompl; +} + +/**Function************************************************************* + + Synopsis [Converts unsigned integer into the edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge ) +{ + return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); +} + +/**Function************************************************************* + + Synopsis [Converts the edge into unsigned integer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge ) +{ + return *(unsigned *)&eEdge; +} + +/**Function************************************************************* + + Synopsis [Converts unsigned integer into the edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge ) +{ + return *(Dec_Edge_t *)&Edge; +} + +/**Function************************************************************* + + Synopsis [Creates a graph with the given number of leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves ) +{ + Dec_Graph_t * pGraph; + pGraph = ALLOC( Dec_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Dec_Graph_t) ); + pGraph->nLeaves = nLeaves; + pGraph->nSize = nLeaves; + pGraph->nCap = 2 * nLeaves + 50; + pGraph->pNodes = ALLOC( Dec_Node_t, pGraph->nCap ); + memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates constant 0 graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreateConst0() +{ + Dec_Graph_t * pGraph; + pGraph = ALLOC( Dec_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Dec_Graph_t) ); + pGraph->fConst = 1; + pGraph->eRoot.fCompl = 1; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates constant 1 graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreateConst1() +{ + Dec_Graph_t * pGraph; + pGraph = ALLOC( Dec_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Dec_Graph_t) ); + pGraph->fConst = 1; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates the literal graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ) +{ + Dec_Graph_t * pGraph; + assert( 0 <= iLeaf && iLeaf < nLeaves ); + pGraph = Dec_GraphCreate( nLeaves ); + pGraph->eRoot.Node = iLeaf; + pGraph->eRoot.fCompl = fCompl; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates a graph with the given number of leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Dec_GraphFree( Dec_Graph_t * pGraph ) +{ + FREE( pGraph->pNodes ); + free( pGraph ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph ) +{ + return pGraph->fConst; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph ) +{ + return pGraph->fConst && pGraph->eRoot.fCompl; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph ) +{ + return pGraph->fConst && !pGraph->eRoot.fCompl; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is complemented.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph ) +{ + return pGraph->eRoot.fCompl; +} + +/**Function************************************************************* + + Synopsis [Checks if the graph is complemented.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Dec_GraphComplement( Dec_Graph_t * pGraph ) +{ + pGraph->eRoot.fCompl ^= 1; +} + + +/**Function************************************************************* + + Synopsis [Returns the number of leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph ) +{ + return pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the number of internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph ) +{ + return pGraph->nSize - pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i ) +{ + return pGraph->pNodes + i; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph ) +{ + return pGraph->pNodes + pGraph->nSize - 1; +} + +/**Function************************************************************* + + Synopsis [Returns the number of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) +{ + return pNode - pGraph->pNodes; +} + +/**Function************************************************************* + + Synopsis [Check if the graph represents elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph ) +{ + return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Check if the graph represents elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) +{ + return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the elementary variable elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph ) +{ + assert( Dec_GraphIsVar( pGraph ) ); + return Dec_GraphNode( pGraph, pGraph->eRoot.Node ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of the elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph ) +{ + assert( Dec_GraphIsVar( pGraph ) ); + return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Sets the root of the graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot ) +{ + pGraph->eRoot = eRoot; +} + +/**Function************************************************************* + + Synopsis [Appends a new node to the graph.] + + Description [This procedure is meant for internal use.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph ) +{ + Dec_Node_t * pNode; + if ( pGraph->nSize == pGraph->nCap ) + { + pGraph->pNodes = REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); + pGraph->nCap = 2 * pGraph->nCap; + } + pNode = pGraph->pNodes + pGraph->nSize++; + memset( pNode, 0, sizeof(Dec_Node_t) ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates an AND node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) +{ + Dec_Node_t * pNode; + // get the new node + pNode = Dec_GraphAppendNode( pGraph ); + // set the inputs and other info + pNode->eEdge0 = eEdge0; + pNode->eEdge1 = eEdge1; + pNode->fCompl0 = eEdge0.fCompl; + pNode->fCompl1 = eEdge1.fCompl; + return Dec_EdgeCreate( pGraph->nSize - 1, 0 ); +} + +/**Function************************************************************* + + Synopsis [Creates an OR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) +{ + Dec_Node_t * pNode; + // get the new node + pNode = Dec_GraphAppendNode( pGraph ); + // set the inputs and other info + pNode->eEdge0 = eEdge0; + pNode->eEdge1 = eEdge1; + pNode->fCompl0 = eEdge0.fCompl; + pNode->fCompl1 = eEdge1.fCompl; + // make adjustments for the OR gate + pNode->fNodeOr = 1; + pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl; + pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl; + return Dec_EdgeCreate( pGraph->nSize - 1, 1 ); +} + +/**Function************************************************************* + + Synopsis [Creates an XOR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type ) +{ + Dec_Edge_t eNode0, eNode1, eNode; + if ( Type == 0 ) + { + // derive the first AND + eEdge0.fCompl ^= 1; + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + eEdge0.fCompl ^= 1; + // derive the second AND + eEdge1.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + } + else + { + // derive the first AND + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the second AND + eEdge0.fCompl ^= 1; + eEdge1.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + eNode.fCompl ^= 1; + } + return eNode; +} + +/**Function************************************************************* + + Synopsis [Creates an XOR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type ) +{ + Dec_Edge_t eNode0, eNode1, eNode; + if ( Type == 0 ) + { + // derive the first AND + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); + // derive the second AND + eEdgeC.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + } + else + { + // complement the arguments + eEdgeT.fCompl ^= 1; + eEdgeE.fCompl ^= 1; + // derive the first AND + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); + // derive the second AND + eEdgeC.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + eNode.fCompl ^= 1; + } + return eNode; +} + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/deco/module.make b/abc70930/src/aig/deco/module.make new file mode 100644 index 00000000..d6d908e7 --- /dev/null +++ b/abc70930/src/aig/deco/module.make @@ -0,0 +1 @@ +SRC += diff --git a/abc70930/src/aig/fra/fra.h b/abc70930/src/aig/fra/fra.h new file mode 100644 index 00000000..210af244 --- /dev/null +++ b/abc70930/src/aig/fra/fra.h @@ -0,0 +1,300 @@ +/**CFile**************************************************************** + + FileName [fra.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [[New FRAIG package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fra.h,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __FRA_H__ +#define __FRA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "vec.h" +#include "aig.h" +#include "dar.h" +#include "satSolver.h" +#include "bar.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Fra_Par_t_ Fra_Par_t; +typedef struct Fra_Man_t_ Fra_Man_t; +typedef struct Fra_Cla_t_ Fra_Cla_t; +typedef struct Fra_Sml_t_ Fra_Sml_t; +typedef struct Fra_Bmc_t_ Fra_Bmc_t; + +// FRAIG parameters +struct Fra_Par_t_ +{ + int nSimWords; // the number of words in the simulation info + double dSimSatur; // the ratio of refined classes when saturation is reached + int fPatScores; // enables simulation pattern scoring + int MaxScore; // max score after which resimulation is used + double dActConeRatio; // the ratio of cone to be bumped + double dActConeBumpMax; // the largest bump in activity + int fChoicing; // enables choicing + int fSpeculate; // use speculative reduction + int fProve; // prove the miter outputs + int fVerbose; // verbose output + int fDoSparse; // skip sparse functions + int fConeBias; // bias variables in the cone (good for unsat runs) + int nBTLimitNode; // conflict limit at a node + int nBTLimitMiter; // conflict limit at an output + int nFramesP; // the number of timeframes to in the prefix + int nFramesK; // the number of timeframes to unroll + int nMaxImps; // the maximum number of implications to consider + int fRewrite; // use rewriting for constraint reduction + int fLatchCorr; // computes latch correspondence only + int fUseImps; // use implications + int fWriteImps; // record implications +}; + +// FRAIG equivalence classes +struct Fra_Cla_t_ +{ + Aig_Man_t * pAig; // the original AIG manager + Aig_Obj_t ** pMemRepr; // pointers to representatives of each node + Vec_Ptr_t * vClasses; // equivalence classes + Vec_Ptr_t * vClasses1; // equivalence class of Const1 node + Vec_Ptr_t * vClassesTemp; // temporary storage for new classes + Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes + Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used + Vec_Ptr_t * vClassOld; // old equivalence class after splitting + Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting + int nPairs; // the number of pairs of nodes + int fRefinement; // set to 1 when refinement has happened + Vec_Int_t * vImps; // implications + // procedures used for class refinement + int (*pFuncNodeHash) (Aig_Obj_t *, int); // returns has key of the node + int (*pFuncNodeIsConst) (Aig_Obj_t *); // returns 1 if the node is a constant + int (*pFuncNodesAreEqual)(Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement +}; + +// simulation manager +struct Fra_Sml_t_ +{ + Aig_Man_t * pAig; // the original AIG manager + int nPref; // the number of times frames in the prefix + int nFrames; // the number of times frames + int nWordsFrame; // the number of words in each time frame + int nWordsTotal; // the total number of words at a node + int nWordsPref; // the number of word in the prefix + int fNonConstOut; // have seen a non-const-0 output during simulation + int nSimRounds; // statistics + int timeSim; // statistics + unsigned pData[0]; // simulation data for the nodes +}; + +// FRAIG manager +struct Fra_Man_t_ +{ + // high-level data + Fra_Par_t * pPars; // parameters governing fraiging + // AIG managers + Aig_Man_t * pManAig; // the starting AIG manager + Aig_Man_t * pManFraig; // the final AIG manager + // mapping AIG into FRAIG + int nFramesAll; // the number of timeframes used + Aig_Obj_t ** pMemFraig; // memory allocated for points to the fraig nodes + int nSizeAlloc; // allocated size of the arrays for timeframe nodes + // equivalence classes + Fra_Cla_t * pCla; // representation of (candidate) equivalent nodes + // simulation info + Fra_Sml_t * pSml; // simulation manager + // bounded model checking manager + Fra_Bmc_t * pBmc; + // counter example storage + int nPatWords; // the number of words in the counter example + unsigned * pPatWords; // the counter example + Vec_Int_t * vCex; + // satisfiability solving + sat_solver * pSat; // SAT solver + int nSatVars; // the number of variables currently used + Vec_Ptr_t * vPiVars; // the PIs of the cone used + sint64 nBTLimitGlobal; // resource limit + sint64 nInsLimitGlobal; // resource limit + Vec_Ptr_t ** pMemFanins; // the arrays of fanins for some FRAIG nodes + int * pMemSatNums; // the array of SAT numbers for some FRAIG nodes + int nMemAlloc; // allocated size of the arrays for FRAIG varnums and fanins + Vec_Ptr_t * vTimeouts; // the nodes, for which equivalence checking timed out + // statistics + int nSimRounds; + int nNodesMiter; + int nLitsBeg; + int nLitsEnd; + int nNodesBeg; + int nNodesEnd; + int nRegsBeg; + int nRegsEnd; + int nSatCalls; + int nSatCallsSat; + int nSatCallsUnsat; + int nSatProof; + int nSatFails; + int nSatFailsReal; + int nSpeculs; + int nChoices; + int nChoicesFake; + int nSatCallsRecent; + int nSatCallsSkipped; + // runtime + int timeSim; + int timeTrav; + int timeRwr; + int timeSat; + int timeSatUnsat; + int timeSatSat; + int timeSatFail; + int timeRef; + int timeTotal; + int time1; + int time2; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline unsigned * Fra_ObjSim( Fra_Sml_t * p, int Id ) { return p->pData + p->nWordsTotal * Id; } +static inline unsigned Fra_ObjRandomSim() { return (rand() << 24) ^ (rand() << 12) ^ rand(); } + +static inline Aig_Obj_t * Fra_ObjFraig( Aig_Obj_t * pObj, int i ) { return ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i]; } +static inline void Fra_ObjSetFraig( Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i] = pNode; } + +static inline Vec_Ptr_t * Fra_ObjFaninVec( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id]; } +static inline void Fra_ObjSetFaninVec( Aig_Obj_t * pObj, Vec_Ptr_t * vFanins ) { ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id] = vFanins; } + +static inline int Fra_ObjSatNum( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id]; } +static inline void Fra_ObjSetSatNum( Aig_Obj_t * pObj, int Num ) { ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id] = Num; } + +static inline Aig_Obj_t * Fra_ClassObjRepr( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id]; } +static inline void Fra_ClassObjSetRepr( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id] = pNode; } + +static inline Aig_Obj_t * Fra_ObjChild0Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Fra_ObjChild1Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } + +static inline int Fra_ImpLeft( int Imp ) { return Imp & 0xFFFF; } +static inline int Fra_ImpRight( int Imp ) { return Imp >> 16; } +static inline int Fra_ImpCreate( int Left, int Right ) { return (Right << 16) | Left; } + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== fraClass.c ========================================================*/ +extern int Fra_BmcNodeIsConst( Aig_Obj_t * pObj ); +extern int Fra_BmcNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); +extern void Fra_BmcStop( Fra_Bmc_t * p ); +extern void Fra_BmcPerform( Fra_Man_t * p, int nPref, int nDepth ); +/*=== fraClass.c ========================================================*/ +extern Fra_Cla_t * Fra_ClassesStart( Aig_Man_t * pAig ); +extern void Fra_ClassesStop( Fra_Cla_t * p ); +extern void Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed ); +extern void Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose ); +extern void Fra_ClassesPrepare( Fra_Cla_t * p, int fLatchCorr ); +extern int Fra_ClassesRefine( Fra_Cla_t * p ); +extern int Fra_ClassesRefine1( Fra_Cla_t * p, int fRefineNewClass, int * pSkipped ); +extern int Fra_ClassesCountLits( Fra_Cla_t * p ); +extern int Fra_ClassesCountPairs( Fra_Cla_t * p ); +extern void Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 ); +extern void Fra_ClassesLatchCorr( Fra_Man_t * p ); +extern void Fra_ClassesPostprocess( Fra_Cla_t * p ); +extern void Fra_ClassesSelectRepr( Fra_Cla_t * p ); +extern Aig_Man_t * Fra_ClassesDeriveAig( Fra_Cla_t * p, int nFramesK ); +/*=== fraCnf.c ========================================================*/ +extern void Fra_CnfNodeAddToSolver( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); +/*=== fraCore.c ========================================================*/ +extern void Fra_FraigSweep( Fra_Man_t * pManAig ); +extern int Fra_FraigMiterStatus( Aig_Man_t * p ); +extern Aig_Man_t * Fra_FraigPerform( Aig_Man_t * pManAig, Fra_Par_t * pPars ); +extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax ); +extern Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax ); +/*=== fraImp.c ========================================================*/ +extern Vec_Int_t * Fra_ImpDerive( Fra_Man_t * p, int nImpMaxLimit, int nImpUseLimit, int fLatchCorr ); +extern void Fra_ImpAddToSolver( Fra_Man_t * p, Vec_Int_t * vImps, int * pSatVarNums ); +extern int Fra_ImpCheckForNode( Fra_Man_t * p, Vec_Int_t * vImps, Aig_Obj_t * pNode, int Pos ); +extern int Fra_ImpRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vImps ); +extern void Fra_ImpCompactArray( Vec_Int_t * vImps ); +extern double Fra_ImpComputeStateSpaceRatio( Fra_Man_t * p ); +extern int Fra_ImpVerifyUsingSimulation( Fra_Man_t * p ); +extern void Fra_ImpRecordInManager( Fra_Man_t * p, Aig_Man_t * pNew ); +/*=== fraInd.c ========================================================*/ +extern Aig_Man_t * Fra_FraigInduction( Aig_Man_t * p, int nFramesP, int nFramesK, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose, int * pnIter ); +/*=== fraLcr.c ========================================================*/ +extern Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter ); +/*=== fraMan.c ========================================================*/ +extern void Fra_ParamsDefault( Fra_Par_t * pParams ); +extern void Fra_ParamsDefaultSeq( Fra_Par_t * pParams ); +extern Fra_Man_t * Fra_ManStart( Aig_Man_t * pManAig, Fra_Par_t * pParams ); +extern void Fra_ManClean( Fra_Man_t * p, int nNodesMax ); +extern Aig_Man_t * Fra_ManPrepareComb( Fra_Man_t * p ); +extern void Fra_ManFinalizeComb( Fra_Man_t * p ); +extern void Fra_ManStop( Fra_Man_t * p ); +extern void Fra_ManPrint( Fra_Man_t * p ); +/*=== fraSat.c ========================================================*/ +extern int Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); +extern int Fra_NodesAreImp( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR ); +extern int Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew ); +/*=== fraSec.c ========================================================*/ +extern int Fra_FraigSec( Aig_Man_t * p, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ); +/*=== fraSim.c ========================================================*/ +extern int Fra_SmlNodeHash( Aig_Obj_t * pObj, int nTableSize ); +extern int Fra_SmlNodeIsConst( Aig_Obj_t * pObj ); +extern int Fra_SmlNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); +extern int Fra_SmlNodeNotEquWeight( Fra_Sml_t * p, int Left, int Right ); +extern int Fra_SmlCheckOutput( Fra_Man_t * p ); +extern void Fra_SmlSavePattern( Fra_Man_t * p ); +extern void Fra_SmlSimulate( Fra_Man_t * p, int fInit ); +extern void Fra_SmlResimulate( Fra_Man_t * p ); +extern Fra_Sml_t * Fra_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ); +extern void Fra_SmlStop( Fra_Sml_t * p ); +extern Fra_Sml_t * Fra_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ); +extern Fra_Sml_t * Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords ); + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/fra/fraBmc.c b/abc70930/src/aig/fra/fraBmc.c new file mode 100644 index 00000000..1140f3a4 --- /dev/null +++ b/abc70930/src/aig/fra/fraBmc.c @@ -0,0 +1,362 @@ +/**CFile**************************************************************** + + FileName [fraBmc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [Bounded model checking.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraBmc.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// simulation manager +struct Fra_Bmc_t_ +{ + // parameters + int nPref; // the size of the prefix + int nDepth; // the depth of the frames + int nFramesAll; // the total number of timeframes + // implications to be filtered + Vec_Int_t * vImps; + // AIG managers + Aig_Man_t * pAig; // the original AIG manager + Aig_Man_t * pAigFrames; // initialized timeframes + Aig_Man_t * pAigFraig; // the fraiged initialized timeframes + // mapping of nodes + Aig_Obj_t ** pObjToFrames; // mapping of the original node into frames + Aig_Obj_t ** pObjToFraig; // mapping of the frames node into fraig +}; + +static inline Aig_Obj_t * Bmc_ObjFrames( Aig_Obj_t * pObj, int i ) { return ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFrames[((Fra_Man_t *)pObj->pData)->pBmc->nFramesAll*pObj->Id + i]; } +static inline void Bmc_ObjSetFrames( Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFrames[((Fra_Man_t *)pObj->pData)->pBmc->nFramesAll*pObj->Id + i] = pNode; } + +static inline Aig_Obj_t * Bmc_ObjFraig( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFraig[pObj->Id]; } +static inline void Bmc_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFraig[pObj->Id] = pNode; } + +static inline Aig_Obj_t * Bmc_ObjChild0Frames( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Bmc_ObjFrames(Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Bmc_ObjChild1Frames( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Bmc_ObjFrames(Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns 1 if the nodes are equivalent.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_BmcNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + Fra_Man_t * p = pObj0->pData; + Aig_Obj_t * pObjFrames0, * pObjFrames1; + Aig_Obj_t * pObjFraig0, * pObjFraig1; + int i; + for ( i = p->pBmc->nPref; i < p->pBmc->nFramesAll; i++ ) + { + pObjFrames0 = Aig_Regular( Bmc_ObjFrames(pObj0, i) ); + pObjFrames1 = Aig_Regular( Bmc_ObjFrames(pObj1, i) ); + if ( pObjFrames0 == pObjFrames1 ) + continue; + pObjFraig0 = Aig_Regular( Bmc_ObjFraig(pObjFrames0) ); + pObjFraig1 = Aig_Regular( Bmc_ObjFraig(pObjFrames1) ); + if ( pObjFraig0 != pObjFraig1 ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is costant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_BmcNodeIsConst( Aig_Obj_t * pObj ) +{ + Fra_Man_t * p = pObj->pData; + return Fra_BmcNodesAreEqual( pObj, Aig_ManConst1(p->pManAig) ); +} + +/**Function************************************************************* + + Synopsis [Refines implications using BMC.] + + Description [The input is the combinational FRAIG manager, + which is used to FRAIG the timeframes. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_BmcFilterImplications( Fra_Man_t * p, Fra_Bmc_t * pBmc ) +{ + Aig_Obj_t * pLeft, * pRight; + Aig_Obj_t * pLeftT, * pRightT; + Aig_Obj_t * pLeftF, * pRightF; + int i, f, Imp, Left, Right; + int fComplL, fComplR; + assert( p->nFramesAll == 1 ); + assert( p->pManAig == pBmc->pAigFrames ); + Vec_IntForEachEntry( pBmc->vImps, Imp, i ) + { + if ( Imp == 0 ) + continue; + Left = Fra_ImpLeft(Imp); + Right = Fra_ImpRight(Imp); + // get the corresponding nodes + pLeft = Aig_ManObj( pBmc->pAig, Left ); + pRight = Aig_ManObj( pBmc->pAig, Right ); + // iterate through the timeframes + for ( f = pBmc->nPref; f < pBmc->nFramesAll; f++ ) + { + // get timeframe nodes + pLeftT = Bmc_ObjFrames( pLeft, f ); + pRightT = Bmc_ObjFrames( pRight, f ); + // get the corresponding FRAIG nodes + pLeftF = Fra_ObjFraig( Aig_Regular(pLeftT), 0 ); + pRightF = Fra_ObjFraig( Aig_Regular(pRightT), 0 ); + // get the complemented attributes + fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF) ^ Aig_IsComplement(pLeftT); + fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF) ^ Aig_IsComplement(pRightT); + // check equality + if ( Aig_Regular(pLeftF) == Aig_Regular(pRightF) ) + { + if ( fComplL == fComplR ) // x => x - always true + continue; + assert( fComplL != fComplR ); + // consider 4 possibilities: + // NOT(1) => 1 or 0 => 1 - always true + // 1 => NOT(1) or 1 => 0 - never true + // NOT(x) => x or x - not always true + // x => NOT(x) or NOT(x) - not always true + if ( Aig_ObjIsConst1(Aig_Regular(pLeftF)) && fComplL ) // proved implication + continue; + // disproved implication + Vec_IntWriteEntry( pBmc->vImps, i, 0 ); + break; + } + // check the implication + if ( Fra_NodesAreImp( p, Aig_Regular(pLeftF), Aig_Regular(pRightF), fComplL, fComplR ) != 1 ) + { + Vec_IntWriteEntry( pBmc->vImps, i, 0 ); + break; + } + } + } + Fra_ImpCompactArray( pBmc->vImps ); +} + + +/**Function************************************************************* + + Synopsis [Starts the BMC manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Bmc_t * Fra_BmcStart( Aig_Man_t * pAig, int nPref, int nDepth ) +{ + Fra_Bmc_t * p; + p = ALLOC( Fra_Bmc_t, 1 ); + memset( p, 0, sizeof(Fra_Bmc_t) ); + p->pAig = pAig; + p->nPref = nPref; + p->nDepth = nDepth; + p->nFramesAll = nPref + nDepth; + p->pObjToFrames = ALLOC( Aig_Obj_t *, p->nFramesAll * Aig_ManObjNumMax(pAig) ); + memset( p->pObjToFrames, 0, sizeof(Aig_Obj_t *) * p->nFramesAll * Aig_ManObjNumMax(pAig) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the BMC manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_BmcStop( Fra_Bmc_t * p ) +{ + Aig_ManStop( p->pAigFrames ); + Aig_ManStop( p->pAigFraig ); + free( p->pObjToFrames ); + free( p->pObjToFraig ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Constructs initialized timeframes of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_BmcFrames( Fra_Bmc_t * p ) +{ + Aig_Man_t * pAigFrames; + Aig_Obj_t * pObj, * pObjNew; + Aig_Obj_t ** pLatches; + int i, k, f; + + // start the fraig package + pAigFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFramesAll ); + pAigFrames->pName = Aig_UtilStrsav( p->pAig->pName ); + // create PI nodes for the frames + for ( f = 0; f < p->nFramesAll; f++ ) + Bmc_ObjSetFrames( Aig_ManConst1(p->pAig), f, Aig_ManConst1(pAigFrames) ); + for ( f = 0; f < p->nFramesAll; f++ ) + Aig_ManForEachPiSeq( p->pAig, pObj, i ) + Bmc_ObjSetFrames( pObj, f, Aig_ObjCreatePi(pAigFrames) ); + // set initial state for the latches + Aig_ManForEachLoSeq( p->pAig, pObj, i ) + Bmc_ObjSetFrames( pObj, 0, Aig_ManConst0(pAigFrames) ); + + // add timeframes + pLatches = ALLOC( Aig_Obj_t *, Aig_ManRegNum(p->pAig) ); + for ( f = 0; f < p->nFramesAll; f++ ) + { + // add internal nodes of this frame + Aig_ManForEachNode( p->pAig, pObj, i ) + { + pObjNew = Aig_And( pAigFrames, Bmc_ObjChild0Frames(pObj,f), Bmc_ObjChild1Frames(pObj,f) ); + Bmc_ObjSetFrames( pObj, f, pObjNew ); + } + if ( f == p->nFramesAll - 1 ) + break; + // save the latch input values + k = 0; + Aig_ManForEachLiSeq( p->pAig, pObj, i ) + pLatches[k++] = Bmc_ObjChild0Frames(pObj,f); + assert( k == Aig_ManRegNum(p->pAig) ); + // insert them to the latch output values + k = 0; + Aig_ManForEachLoSeq( p->pAig, pObj, i ) + Bmc_ObjSetFrames( pObj, f+1, pLatches[k++] ); + assert( k == Aig_ManRegNum(p->pAig) ); + } + free( pLatches ); + // add POs to all the dangling nodes + Aig_ManForEachObj( pAigFrames, pObjNew, i ) + if ( Aig_ObjIsNode(pObjNew) && pObjNew->nRefs == 0 ) + Aig_ObjCreatePo( pAigFrames, pObjNew ); + + // return the new manager + return pAigFrames; +} + +/**Function************************************************************* + + Synopsis [Performs BMC for the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_BmcPerform( Fra_Man_t * p, int nPref, int nDepth ) +{ + Aig_Obj_t * pObj; + int i, nImpsOld, clk = clock(); + assert( p->pBmc == NULL ); + // derive and fraig the frames + p->pBmc = Fra_BmcStart( p->pManAig, nPref, nDepth ); + p->pBmc->pAigFrames = Fra_BmcFrames( p->pBmc ); + // if implications are present, configure the AIG manager to check them + if ( p->pCla->vImps ) + { + p->pBmc->pAigFrames->pImpFunc = Fra_BmcFilterImplications; + p->pBmc->pAigFrames->pImpData = p->pBmc; + p->pBmc->vImps = p->pCla->vImps; + nImpsOld = Vec_IntSize(p->pCla->vImps); + } + p->pBmc->pAigFraig = Fra_FraigEquivence( p->pBmc->pAigFrames, 1000000 ); + p->pBmc->pObjToFraig = p->pBmc->pAigFrames->pObjCopies; + p->pBmc->pAigFrames->pObjCopies = NULL; + // annotate frames nodes with pointers to the manager + Aig_ManForEachObj( p->pBmc->pAigFrames, pObj, i ) + pObj->pData = p; + // report the results + if ( p->pPars->fVerbose ) + { + printf( "Original AIG = %d. Init %d frames = %d. Fraig = %d. ", + Aig_ManNodeNum(p->pBmc->pAig), p->pBmc->nFramesAll, + Aig_ManNodeNum(p->pBmc->pAigFrames), Aig_ManNodeNum(p->pBmc->pAigFraig) ); + PRT( "Time", clock() - clk ); + printf( "Before BMC: " ); +// Fra_ClassesPrint( p->pCla, 0 ); + printf( "Const = %5d. Class = %5d. Lit = %5d. ", + Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); + if ( p->pCla->vImps ) + printf( "Imp = %5d. ", nImpsOld ); + printf( "\n" ); + } + // refine the classes + p->pCla->pFuncNodeIsConst = Fra_BmcNodeIsConst; + p->pCla->pFuncNodesAreEqual = Fra_BmcNodesAreEqual; + Fra_ClassesRefine( p->pCla ); + Fra_ClassesRefine1( p->pCla, 1, NULL ); + p->pCla->pFuncNodeIsConst = Fra_SmlNodeIsConst; + p->pCla->pFuncNodesAreEqual = Fra_SmlNodesAreEqual; + // report the results + if ( p->pPars->fVerbose ) + { + printf( "After BMC: " ); +// Fra_ClassesPrint( p->pCla, 0 ); + printf( "Const = %5d. Class = %5d. Lit = %5d. ", + Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); + if ( p->pCla->vImps ) + printf( "Imp = %5d. ", Vec_IntSize(p->pCla->vImps) ); + printf( "\n" ); + } + // free the BMC manager + Fra_BmcStop( p->pBmc ); + p->pBmc = NULL; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraCec.c b/abc70930/src/aig/fra/fraCec.c new file mode 100644 index 00000000..e705f4fc --- /dev/null +++ b/abc70930/src/aig/fra/fraCec.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [fraCec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [CEC engined based on fraiging.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraCec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraClass.c b/abc70930/src/aig/fra/fraClass.c new file mode 100644 index 00000000..a03fa6e5 --- /dev/null +++ b/abc70930/src/aig/fra/fraClass.c @@ -0,0 +1,854 @@ +/**CFile**************************************************************** + + FileName [fraClass.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraClass.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +/* + The candidate equivalence classes are stored as a vector of pointers + to the array of pointers to the nodes in each class. + The first node of the class is its representative node. + The representative has the smallest topological order among the class nodes. + The nodes inside each class are ordered according to their topological order. + The classes are ordered according to the topological order of their representatives. + The array of pointers to the class nodes is terminated with a NULL pointer. + To enable dynamic addition of new classes (during class refinement), + each array has at least as many NULLs in the end, as there are nodes in the class. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline Aig_Obj_t * Fra_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } +static inline void Fra_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Cla_t * Fra_ClassesStart( Aig_Man_t * pAig ) +{ + Fra_Cla_t * p; + p = ALLOC( Fra_Cla_t, 1 ); + memset( p, 0, sizeof(Fra_Cla_t) ); + p->pAig = pAig; + p->pMemRepr = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); + memset( p->pMemRepr, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pAig) ); + p->vClasses = Vec_PtrAlloc( 100 ); + p->vClasses1 = Vec_PtrAlloc( 100 ); + p->vClassesTemp = Vec_PtrAlloc( 100 ); + p->vClassOld = Vec_PtrAlloc( 100 ); + p->vClassNew = Vec_PtrAlloc( 100 ); + p->pFuncNodeHash = Fra_SmlNodeHash; + p->pFuncNodeIsConst = Fra_SmlNodeIsConst; + p->pFuncNodesAreEqual = Fra_SmlNodesAreEqual; + return p; +} + +/**Function************************************************************* + + Synopsis [Stop representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClassesStop( Fra_Cla_t * p ) +{ + FREE( p->pMemClasses ); + FREE( p->pMemRepr ); + if ( p->vClassesTemp ) Vec_PtrFree( p->vClassesTemp ); + if ( p->vClassNew ) Vec_PtrFree( p->vClassNew ); + if ( p->vClassOld ) Vec_PtrFree( p->vClassOld ); + if ( p->vClasses1 ) Vec_PtrFree( p->vClasses1 ); + if ( p->vClasses ) Vec_PtrFree( p->vClasses ); + if ( p->vImps ) Vec_IntFree( p->vImps ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Starts representation of equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManReprStart( p->pAig, Aig_ManObjNumMax(p->pAig) ); + memmove( p->pAig->pReprs, p->pMemRepr, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p->pAig) ); + if ( Vec_PtrSize(p->vClasses1) == 0 && Vec_PtrSize(p->vClasses) == 0 ) + { + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( p->pAig->pReprs[i] != NULL ) + printf( "Classes are not cleared!\n" ); + assert( p->pAig->pReprs[i] == NULL ); + } + } + if ( vFailed ) + Vec_PtrForEachEntry( vFailed, pObj, i ) + p->pAig->pReprs[pObj->Id] = NULL; +} + +/**Function************************************************************* + + Synopsis [Prints simulation classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClassCount( Aig_Obj_t ** pClass ) +{ + Aig_Obj_t * pTemp; + int i; + for ( i = 0; pTemp = pClass[i]; i++ ); + return i; +} + +/**Function************************************************************* + + Synopsis [Count the number of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClassesCountLits( Fra_Cla_t * p ) +{ + Aig_Obj_t ** pClass; + int i, nNodes, nLits = 0; + nLits = Vec_PtrSize( p->vClasses1 ); + Vec_PtrForEachEntry( p->vClasses, pClass, i ) + { + nNodes = Fra_ClassCount( pClass ); + assert( nNodes > 1 ); + nLits += nNodes - 1; + } + return nLits; +} + +/**Function************************************************************* + + Synopsis [Count the number of pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClassesCountPairs( Fra_Cla_t * p ) +{ + Aig_Obj_t ** pClass; + int i, nNodes, nPairs = 0; + Vec_PtrForEachEntry( p->vClasses, pClass, i ) + { + nNodes = Fra_ClassCount( pClass ); + assert( nNodes > 1 ); + nPairs += nNodes * (nNodes - 1) / 2; + } + return nPairs; +} + +/**Function************************************************************* + + Synopsis [Prints simulation classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_PrintClass( Aig_Obj_t ** pClass ) +{ + Aig_Obj_t * pTemp; + int i; + for ( i = 1; pTemp = pClass[i]; i++ ) + assert( Fra_ClassObjRepr(pTemp) == pClass[0] ); + printf( "{ " ); + for ( i = 0; pTemp = pClass[i]; i++ ) + printf( "%d(%d) ", pTemp->Id, pTemp->Level ); + printf( "}\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints simulation classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose ) +{ + Aig_Obj_t ** pClass; + Aig_Obj_t * pObj; + int i; + + printf( "Const = %5d. Class = %5d. Lit = %5d. ", + Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses), Fra_ClassesCountLits(p) ); + if ( p->vImps && Vec_IntSize(p->vImps) > 0 ) + printf( "Imp = %5d. ", Vec_IntSize(p->vImps) ); + printf( "\n" ); + + if ( fVeryVerbose ) + { + Vec_PtrForEachEntry( p->vClasses1, pObj, i ) + assert( Fra_ClassObjRepr(pObj) == Aig_ManConst1(p->pAig) ); + printf( "Constants { " ); + Vec_PtrForEachEntry( p->vClasses1, pObj, i ) + printf( "%d ", pObj->Id ); + printf( "}\n" ); + Vec_PtrForEachEntry( p->vClasses, pClass, i ) + { + printf( "%3d (%3d) : ", i, Fra_ClassCount(pClass) ); + Fra_PrintClass( pClass ); + } + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Creates initial simulation classes.] + + Description [Assumes that simulation info is assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClassesPrepare( Fra_Cla_t * p, int fLatchCorr ) +{ + Aig_Obj_t ** ppTable, ** ppNexts; + Aig_Obj_t * pObj, * pTemp; + int i, k, nTableSize, nEntries, nNodes, iEntry; + + // allocate the hash table hashing simulation info into nodes + nTableSize = Aig_PrimeCudd( Aig_ManObjNumMax(p->pAig) ); + ppTable = ALLOC( Aig_Obj_t *, nTableSize ); + ppNexts = ALLOC( Aig_Obj_t *, nTableSize ); + memset( ppTable, 0, sizeof(Aig_Obj_t *) * nTableSize ); + + // add all the nodes to the hash table + Vec_PtrClear( p->vClasses1 ); + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( fLatchCorr ) + { + if ( !Aig_ObjIsPi(pObj) ) + continue; + } + else + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + // skip the node with more that the given number of levels +// if ( pObj->Level > 3 ) +// continue; + } + // hash the node by its simulation info + iEntry = p->pFuncNodeHash( pObj, nTableSize ); + // check if the node belongs to the class of constant 1 + if ( p->pFuncNodeIsConst( pObj ) ) + { + Vec_PtrPush( p->vClasses1, pObj ); + Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pAig) ); + continue; + } + // add the node to the class + if ( ppTable[iEntry] == NULL ) + { + ppTable[iEntry] = pObj; + Fra_ObjSetNext( ppNexts, pObj, pObj ); + } + else + { + Fra_ObjSetNext( ppNexts, pObj, Fra_ObjNext(ppNexts,ppTable[iEntry]) ); + Fra_ObjSetNext( ppNexts, ppTable[iEntry], pObj ); + } + } + + // count the total number of nodes in the non-trivial classes + // mark the representative nodes of each equivalence class + nEntries = 0; + for ( i = 0; i < nTableSize; i++ ) + if ( ppTable[i] && ppTable[i] != Fra_ObjNext(ppNexts, ppTable[i]) ) + { + for ( pTemp = Fra_ObjNext(ppNexts, ppTable[i]), k = 1; + pTemp != ppTable[i]; + pTemp = Fra_ObjNext(ppNexts, pTemp), k++ ); + assert( k > 1 ); + nEntries += k; + // mark the node + assert( ppTable[i]->fMarkA == 0 ); + ppTable[i]->fMarkA = 1; + } + + // allocate room for classes + p->pMemClasses = ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->vClasses1)) ); + p->pMemClassesFree = p->pMemClasses + 2*nEntries; + + // copy the entries into storage in the topological order + Vec_PtrClear( p->vClasses ); + nEntries = 0; + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + // skip the nodes that are not representatives of non-trivial classes + if ( pObj->fMarkA == 0 ) + continue; + pObj->fMarkA = 0; + // add the class of nodes + Vec_PtrPush( p->vClasses, p->pMemClasses + 2*nEntries ); + // count the number of entries in this class + for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1; + pTemp != pObj; + pTemp = Fra_ObjNext(ppNexts, pTemp), k++ ); + nNodes = k; + assert( nNodes > 1 ); + // add the nodes to the class in the topological order + p->pMemClasses[2*nEntries] = pObj; + for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1; + pTemp != pObj; + pTemp = Fra_ObjNext(ppNexts, pTemp), k++ ) + { + p->pMemClasses[2*nEntries+nNodes-k] = pTemp; + Fra_ClassObjSetRepr( pTemp, pObj ); + } + // add as many empty entries + p->pMemClasses[2*nEntries + nNodes] = NULL; + // increment the number of entries + nEntries += k; + } + free( ppTable ); + free( ppNexts ); + // now it is time to refine the classes + Fra_ClassesRefine( p ); +} + +/**Function************************************************************* + + Synopsis [Refines one class using simulation info.] + + Description [Returns the new class if refinement happened.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t ** Fra_RefineClassOne( Fra_Cla_t * p, Aig_Obj_t ** ppClass ) +{ + Aig_Obj_t * pObj, ** ppThis; + int i; + assert( ppClass[0] != NULL && ppClass[1] != NULL ); + + // check if the class is going to be refined + for ( ppThis = ppClass + 1; pObj = *ppThis; ppThis++ ) + if ( !p->pFuncNodesAreEqual(ppClass[0], pObj) ) + break; + if ( pObj == NULL ) + return NULL; + // split the class + Vec_PtrClear( p->vClassOld ); + Vec_PtrClear( p->vClassNew ); + Vec_PtrPush( p->vClassOld, ppClass[0] ); + for ( ppThis = ppClass + 1; pObj = *ppThis; ppThis++ ) + if ( p->pFuncNodesAreEqual(ppClass[0], pObj) ) + Vec_PtrPush( p->vClassOld, pObj ); + else + Vec_PtrPush( p->vClassNew, pObj ); +/* + printf( "Refining class (" ); + Vec_PtrForEachEntry( p->vClassOld, pObj, i ) + printf( "%d,", pObj->Id ); + printf( ") + (" ); + Vec_PtrForEachEntry( p->vClassNew, pObj, i ) + printf( "%d,", pObj->Id ); + printf( ")\n" ); +*/ + // put the nodes back into the class memory + Vec_PtrForEachEntry( p->vClassOld, pObj, i ) + { + ppClass[i] = pObj; + ppClass[Vec_PtrSize(p->vClassOld)+i] = NULL; + Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL ); + } + ppClass += 2*Vec_PtrSize(p->vClassOld); + // put the new nodes into the class memory + Vec_PtrForEachEntry( p->vClassNew, pObj, i ) + { + ppClass[i] = pObj; + ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL; + Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL ); + } + return ppClass; +} + +/**Function************************************************************* + + Synopsis [Iteratively refines the classes after simulation.] + + Description [Returns the number of refinements performed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_RefineClassLastIter( Fra_Cla_t * p, Vec_Ptr_t * vClasses ) +{ + Aig_Obj_t ** pClass, ** pClass2; + int nRefis; + pClass = Vec_PtrEntryLast( vClasses ); + for ( nRefis = 0; pClass2 = Fra_RefineClassOne( p, pClass ); nRefis++ ) + { + // if the original class is trivial, remove it + if ( pClass[1] == NULL ) + Vec_PtrPop( vClasses ); + // if the new class is trivial, stop + if ( pClass2[1] == NULL ) + { + nRefis++; + break; + } + // othewise, add the class and continue + assert( pClass2[0] != NULL ); + Vec_PtrPush( vClasses, pClass2 ); + pClass = pClass2; + } + return nRefis; +} + +/**Function************************************************************* + + Synopsis [Refines the classes after simulation.] + + Description [Assumes that simulation info is assigned. Returns the + number of classes refined.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClassesRefine( Fra_Cla_t * p ) +{ + Vec_Ptr_t * vTemp; + Aig_Obj_t ** pClass; + int i, nRefis; + // refine the classes + nRefis = 0; + Vec_PtrClear( p->vClassesTemp ); + Vec_PtrForEachEntry( p->vClasses, pClass, i ) + { + // add the class to the new array + assert( pClass[0] != NULL ); + Vec_PtrPush( p->vClassesTemp, pClass ); + // refine the class iteratively + nRefis += Fra_RefineClassLastIter( p, p->vClassesTemp ); + } + // exchange the class representation + vTemp = p->vClassesTemp; + p->vClassesTemp = p->vClasses; + p->vClasses = vTemp; + return nRefis; +} + +/**Function************************************************************* + + Synopsis [Refines constant 1 equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ClassesRefine1( Fra_Cla_t * p, int fRefineNewClass, int * pSkipped ) +{ + Aig_Obj_t * pObj, ** ppClass; + int i, k, nRefis = 1; + // check if there is anything to refine + if ( Vec_PtrSize(p->vClasses1) == 0 ) + return 0; + // make sure constant 1 class contains only non-constant nodes + assert( Vec_PtrEntry(p->vClasses1,0) != Aig_ManConst1(p->pAig) ); + // collect all the nodes to be refined + k = 0; + Vec_PtrClear( p->vClassNew ); + Vec_PtrForEachEntry( p->vClasses1, pObj, i ) + { + if ( p->pFuncNodeIsConst( pObj ) ) + Vec_PtrWriteEntry( p->vClasses1, k++, pObj ); + else + Vec_PtrPush( p->vClassNew, pObj ); + } + Vec_PtrShrink( p->vClasses1, k ); + if ( Vec_PtrSize(p->vClassNew) == 0 ) + return 0; +/* + printf( "Refined const-1 class: {" ); + Vec_PtrForEachEntry( p->vClassNew, pObj, i ) + printf( " %d", pObj->Id ); + printf( " }\n" ); +*/ + if ( Vec_PtrSize(p->vClassNew) == 1 ) + { + Fra_ClassObjSetRepr( Vec_PtrEntry(p->vClassNew,0), NULL ); + return 1; + } + // create a new class composed of these nodes + ppClass = p->pMemClassesFree; + p->pMemClassesFree += 2 * Vec_PtrSize(p->vClassNew); + Vec_PtrForEachEntry( p->vClassNew, pObj, i ) + { + ppClass[i] = pObj; + ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL; + Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL ); + } + assert( ppClass[0] != NULL ); + Vec_PtrPush( p->vClasses, ppClass ); + // iteratively refine this class + if ( fRefineNewClass ) + nRefis += Fra_RefineClassLastIter( p, p->vClasses ); + else if ( pSkipped ) + (*pSkipped)++; + return nRefis; +} + +/**Function************************************************************* + + Synopsis [Starts representation of equivalence classes with one class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 ) +{ + Aig_Obj_t ** pClass; + p->pMemClasses = ALLOC( Aig_Obj_t *, 4 ); + pClass = p->pMemClasses; + assert( Id1 < Id2 ); + pClass[0] = Aig_ManObj( p->pAig, Id1 ); + pClass[1] = Aig_ManObj( p->pAig, Id2 ); + pClass[2] = NULL; + pClass[3] = NULL; + Fra_ClassObjSetRepr( pClass[1], pClass[0] ); + Vec_PtrPush( p->vClasses, pClass ); +} + +/**Function************************************************************* + + Synopsis [Creates latch correspondence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClassesLatchCorr( Fra_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, nEntries = 0; + Vec_PtrClear( p->pCla->vClasses1 ); + Aig_ManForEachLoSeq( p->pManAig, pObj, i ) + { + Vec_PtrPush( p->pCla->vClasses1, pObj ); + Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pManAig) ); + } + // allocate room for classes + p->pCla->pMemClasses = ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->pCla->vClasses1)) ); + p->pCla->pMemClassesFree = p->pCla->pMemClasses + 2*nEntries; +} + +/**Function************************************************************* + + Synopsis [Postprocesses the classes by removing half of the less useful.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClassesPostprocess( Fra_Cla_t * p ) +{ + int Ratio = 2; + Fra_Sml_t * pComb; + Aig_Obj_t * pObj, * pRepr, ** ppClass; + int * pWeights, WeightMax = 0, i, k, c; + // perform combinational simulation + pComb = Fra_SmlSimulateComb( p->pAig, 32 ); + // compute the weight of each node in the classes + pWeights = ALLOC( int, Aig_ManObjNumMax(p->pAig) ); + memset( pWeights, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) ); + Aig_ManForEachObj( p->pAig, pObj, i ) + { + pRepr = Fra_ClassObjRepr( pObj ); + if ( pRepr == NULL ) + continue; + pWeights[i] = Fra_SmlNodeNotEquWeight( pComb, pRepr->Id, pObj->Id ); + WeightMax = AIG_MAX( WeightMax, pWeights[i] ); + } + Fra_SmlStop( pComb ); + printf( "Before: Const = %6d. Class = %6d. ", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) ); + // remove nodes from classes whose weight is less than WeightMax/Ratio + k = 0; + Vec_PtrForEachEntry( p->vClasses1, pObj, i ) + { + if ( pWeights[pObj->Id] >= WeightMax/Ratio ) + Vec_PtrWriteEntry( p->vClasses1, k++, pObj ); + else + Fra_ClassObjSetRepr( pObj, NULL ); + } + Vec_PtrShrink( p->vClasses1, k ); + // in each class, compact the nodes + Vec_PtrForEachEntry( p->vClasses, ppClass, i ) + { + k = 1; + for ( c = 1; ppClass[c]; c++ ) + { + if ( pWeights[ppClass[c]->Id] >= WeightMax/Ratio ) + ppClass[k++] = ppClass[c]; + else + Fra_ClassObjSetRepr( ppClass[c], NULL ); + } + ppClass[k] = NULL; + } + // remove classes with only repr + k = 0; + Vec_PtrForEachEntry( p->vClasses, ppClass, i ) + if ( ppClass[1] != NULL ) + Vec_PtrWriteEntry( p->vClasses, k++, ppClass ); + Vec_PtrShrink( p->vClasses, k ); + printf( "After: Const = %6d. Class = %6d. \n", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) ); + free( pWeights ); +} + +/**Function************************************************************* + + Synopsis [Postprocesses the classes by selecting representative lowest in top order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClassesSelectRepr( Fra_Cla_t * p ) +{ + Aig_Obj_t ** pClass, * pNodeMin; + int i, c, cMinSupp, nSuppSizeMin, nSuppSizeCur; + // reassign representatives in each class + Vec_PtrForEachEntry( p->vClasses, pClass, i ) + { + // collect support sizes and find the min-support node + pNodeMin = NULL; + nSuppSizeMin = AIG_INFINITY; + for ( c = 0; pClass[c]; c++ ) + { + nSuppSizeCur = Aig_SupportSize( p->pAig, pClass[c] ); +// nSuppSizeCur = 1; + if ( nSuppSizeMin > nSuppSizeCur || + (nSuppSizeMin == nSuppSizeCur && pNodeMin->Level > pClass[c]->Level) ) + { + nSuppSizeMin = nSuppSizeCur; + pNodeMin = pClass[c]; + cMinSupp = c; + } + } + // skip the case when the repr did not change + if ( cMinSupp == 0 ) + continue; + // make the new node the representative of the class + pClass[cMinSupp] = pClass[0]; + pClass[0] = pNodeMin; + // set the representative + for ( c = 0; pClass[c]; c++ ) + Fra_ClassObjSetRepr( pClass[c], c? pClass[0] : NULL ); + } +} + + + +static inline Aig_Obj_t * Fra_ObjEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return ppEquivs[pObj->Id]; } +static inline void Fra_ObjSetEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ppEquivs[pObj->Id] = pNode; } + +static inline Aig_Obj_t * Fra_ObjChild0Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)); } +static inline Aig_Obj_t * Fra_ObjChild1Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)); } + +/**Function************************************************************* + + Synopsis [Add the node and its constraints to the new AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fra_ClassesDeriveNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, Aig_Obj_t ** ppEquivs ) +{ + Aig_Obj_t * pObjNew, * pObjRepr, * pObjReprNew, * pMiter;//, * pObjNew2; + // skip nodes without representative + if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL ) + return; + assert( pObjRepr->Id < pObj->Id ); + // get the new node + pObjNew = Fra_ObjEqu( ppEquivs, pObj ); + // get the new node of the representative + pObjReprNew = Fra_ObjEqu( ppEquivs, pObjRepr ); + // if this is the same node, no need to add constraints + if ( Aig_Regular(pObjNew) == Aig_Regular(pObjReprNew) ) + return; + // these are different nodes - perform speculative reduction +// pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase ); + // set the new node +// Fra_ObjSetEqu( ppEquivs, pObj, pObjNew2 ); + // add the constraint + pMiter = Aig_Exor( pManFraig, Aig_Regular(pObjNew), Aig_Regular(pObjReprNew) ); + pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) ); + pMiter = Aig_Not( pMiter ); + Aig_ObjCreatePo( pManFraig, pMiter ); +} + +/**Function************************************************************* + + Synopsis [Derives AIG for the partitioned problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_ClassesDeriveAig( Fra_Cla_t * p, int nFramesK ) +{ + Aig_Man_t * pManFraig; + Aig_Obj_t * pObj, * pObjNew; + Aig_Obj_t ** pLatches, ** ppEquivs; + int i, k, f, nFramesAll = nFramesK + 1; + assert( Aig_ManRegNum(p->pAig) > 0 ); + assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) ); + assert( nFramesK > 0 ); + // start the fraig package + pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * nFramesAll ); + pManFraig->pName = Aig_UtilStrsav( p->pAig->pName ); + // allocate place for the node mapping + ppEquivs = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) ); + Fra_ObjSetEqu( ppEquivs, Aig_ManConst1(p->pAig), Aig_ManConst1(pManFraig) ); + // create latches for the first frame + Aig_ManForEachLoSeq( p->pAig, pObj, i ) + Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreatePi(pManFraig) ); + // add timeframes + pLatches = ALLOC( Aig_Obj_t *, Aig_ManRegNum(p->pAig) ); + for ( f = 0; f < nFramesAll; f++ ) + { + // create PIs for this frame + Aig_ManForEachPiSeq( p->pAig, pObj, i ) + Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreatePi(pManFraig) ); + // set the constraints on the latch outputs + Aig_ManForEachLoSeq( p->pAig, pObj, i ) + Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs ); + // add internal nodes of this frame + Aig_ManForEachNode( p->pAig, pObj, i ) + { + pObjNew = Aig_And( pManFraig, Fra_ObjChild0Equ(ppEquivs, pObj), Fra_ObjChild1Equ(ppEquivs, pObj) ); + Fra_ObjSetEqu( ppEquivs, pObj, pObjNew ); + Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs ); + } + if ( f == nFramesAll - 1 ) + break; + if ( f == nFramesAll - 2 ) + pManFraig->nAsserts = Aig_ManPoNum(pManFraig); + // save the latch input values + k = 0; + Aig_ManForEachLiSeq( p->pAig, pObj, i ) + pLatches[k++] = Fra_ObjChild0Equ( ppEquivs, pObj ); + // insert them to the latch output values + k = 0; + Aig_ManForEachLoSeq( p->pAig, pObj, i ) + Fra_ObjSetEqu( ppEquivs, pObj, pLatches[k++] ); + } + free( pLatches ); + free( ppEquivs ); + // mark the asserts + assert( Aig_ManPoNum(pManFraig) % nFramesAll == 0 ); +printf( "Assert miters = %6d. Output miters = %6d.\n", + pManFraig->nAsserts, Aig_ManPoNum(pManFraig) - pManFraig->nAsserts ); + // remove dangling nodes + Aig_ManCleanup( pManFraig ); + return pManFraig; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraCnf.c b/abc70930/src/aig/fra/fraCnf.c new file mode 100644 index 00000000..d56c0254 --- /dev/null +++ b/abc70930/src/aig/fra/fraCnf.c @@ -0,0 +1,286 @@ +/**CFile**************************************************************** + + FileName [fraCnf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraCnf.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_AddClausesMux( Fra_Man_t * p, Aig_Obj_t * pNode ) +{ + Aig_Obj_t * pNodeI, * pNodeT, * pNodeE; + int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; + + assert( !Aig_IsComplement( pNode ) ); + assert( Aig_ObjIsMuxType( pNode ) ); + // get nodes (I = if, T = then, E = else) + pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the variable numbers + VarF = Fra_ObjSatNum(pNode); + VarI = Fra_ObjSatNum(pNodeI); + VarT = Fra_ObjSatNum(Aig_Regular(pNodeT)); + VarE = Fra_ObjSatNum(Aig_Regular(pNodeE)); + // get the complementation flags + fCompT = Aig_IsComplement(pNodeT); + fCompE = Aig_IsComplement(pNodeE); + + // f = ITE(i, t, e) + + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + + // create four clauses + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 1^fCompT); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 0^fCompT); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + + // two additional clauses + // t' & e' -> f' + // t & e -> f + + // t + e + f' + // t' + e' + f + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return; + } + + pLits[0] = toLitCond(VarT, 0^fCompT); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarT, 1^fCompT); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_AddClausesSuper( Fra_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper ) +{ + Aig_Obj_t * pFanin; + int * pLits, nLits, RetValue, i; + assert( !Aig_IsComplement(pNode) ); + assert( Aig_ObjIsNode( pNode ) ); + // create storage for literals + nLits = Vec_PtrSize(vSuper) + 1; + pLits = ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + pLits[0] = toLitCond(Fra_ObjSatNum(Aig_Regular(pFanin)), Aig_IsComplement(pFanin)); + pLits[1] = toLitCond(Fra_ObjSatNum(pNode), 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + } + // add A & B => C or !A + !B + C + Vec_PtrForEachEntry( vSuper, pFanin, i ) + pLits[i] = toLitCond(Fra_ObjSatNum(Aig_Regular(pFanin)), !Aig_IsComplement(pFanin)); + pLits[nLits-1] = toLitCond(Fra_ObjSatNum(pNode), 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); + assert( RetValue ); + free( pLits ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) || (!fFirst && Aig_ObjRefs(pObj) > 1) || + (fUseMuxes && Aig_ObjIsMuxType(pObj)) ) + { + Vec_PtrPushUnique( vSuper, pObj ); + return; + } + // go through the branches + Fra_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes ); + Fra_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Fra_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes ) +{ + Vec_Ptr_t * vSuper; + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsPi(pObj) ); + vSuper = Vec_PtrAlloc( 4 ); + Fra_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); + return vSuper; +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ObjAddToFrontier( Fra_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier ) +{ + Fra_Man_t * pTemp = pObj->pData; + assert( !Aig_IsComplement(pObj) ); + if ( Fra_ObjSatNum(pObj) ) + return; + assert( Fra_ObjSatNum(pObj) == 0 ); + assert( Fra_ObjFaninVec(pObj) == NULL ); + if ( Aig_ObjIsConst1(pObj) ) + return; +//printf( "Assigning node %d number %d\n", pObj->Id, p->nSatVars ); + Fra_ObjSetSatNum( pObj, p->nSatVars++ ); + if ( Aig_ObjIsNode(pObj) ) + Vec_PtrPush( vFrontier, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_CnfNodeAddToSolver( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) +{ + Vec_Ptr_t * vFrontier, * vFanins; + Aig_Obj_t * pNode, * pFanin; + int i, k, fUseMuxes = 1; + assert( pOld || pNew ); + // quit if CNF is ready + if ( (!pOld || Fra_ObjFaninVec(pOld)) && (!pNew || Fra_ObjFaninVec(pNew)) ) + return; + // start the frontier + vFrontier = Vec_PtrAlloc( 100 ); + if ( pOld ) Fra_ObjAddToFrontier( p, pOld, vFrontier ); + if ( pNew ) Fra_ObjAddToFrontier( p, pNew, vFrontier ); + // explore nodes in the frontier + Vec_PtrForEachEntry( vFrontier, pNode, i ) + { + // create the supergate + assert( Fra_ObjSatNum(pNode) ); + assert( Fra_ObjFaninVec(pNode) == NULL ); + if ( fUseMuxes && Aig_ObjIsMuxType(pNode) ) + { + vFanins = Vec_PtrAlloc( 4 ); + Vec_PtrPushUnique( vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) ); + Vec_PtrPushUnique( vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) ); + Vec_PtrForEachEntry( vFanins, pFanin, k ) + Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); + Fra_AddClausesMux( p, pNode ); + } + else + { + vFanins = Fra_CollectSuper( pNode, fUseMuxes ); + Vec_PtrForEachEntry( vFanins, pFanin, k ) + Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); + Fra_AddClausesSuper( p, pNode, vFanins ); + } + assert( Vec_PtrSize(vFanins) > 1 ); + Fra_ObjSetFaninVec( pNode, vFanins ); + } + Vec_PtrFree( vFrontier ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraCore.c b/abc70930/src/aig/fra/fraCore.c new file mode 100644 index 00000000..b390edbe --- /dev/null +++ b/abc70930/src/aig/fra/fraCore.c @@ -0,0 +1,428 @@ +/**CFile**************************************************************** + + FileName [fraCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraCore.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + Speculating reduction in the sequential case leads to an interesting + situation when a counter-ex may not refine any classes. This happens + for non-constant equivalence classes. In such cases the representative + of the class (proved by simulation to be non-constant) may be reduced + to a constant during the speculative reduction. The fraig-representative + of this representative node is a constant node, even though this is a + non-constant class. Experiments have shown that this situation happens + very often at the beginning of the refinement iteration when there are + many spurious candidate equivalence classes (especially if heavy-duty + simulatation of BMC was node used at the beginning). As a result, the + SAT solver run may return a counter-ex that distinguishes the given + representative node from the constant-1 node but this counter-ex + does not distinguish the nodes in the non-costant class... This is why + there is no check of refinment after a counter-ex in the sequential case. +*/ + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reports the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_FraigMiterStatus( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pObjNew; + int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; + if ( p->pData ) + return 0; + Aig_ManForEachPoSeq( p, pObj, i ) + { + pObjNew = Aig_ObjChild0(pObj); + // check if the output is constant 0 + if ( pObjNew == Aig_ManConst0(p) ) + { + CountConst0++; + continue; + } + // check if the output is constant 1 + if ( pObjNew == Aig_ManConst1(p) ) + { + CountNonConst0++; + continue; + } + // check if the output can be constant 0 + if ( Aig_Regular(pObjNew)->fPhase != (unsigned)Aig_IsComplement(pObjNew) ) + { + CountNonConst0++; + continue; + } + CountUndecided++; + } +/* + if ( p->pParams->fVerbose ) + { + printf( "Miter has %d outputs. ", Aig_ManPoNum(p->pManAig) ); + printf( "Const0 = %d. ", CountConst0 ); + printf( "NonConst0 = %d. ", CountNonConst0 ); + printf( "Undecided = %d. ", CountUndecided ); + printf( "\n" ); + } +*/ + if ( CountNonConst0 ) + return 0; + if ( CountUndecided ) + return -1; + return 1; +} + +/**Function************************************************************* + + Synopsis [Write speculative miter for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fra_FraigNodeSpeculate( Fra_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pObjFraig, Aig_Obj_t * pObjReprFraig ) +{ + static int Counter = 0; + char FileName[20]; + Aig_Man_t * pTemp; + Aig_Obj_t * pNode; + int i; + // create manager with the logic for these two nodes + pTemp = Aig_ManExtractMiter( p->pManFraig, pObjFraig, pObjReprFraig ); + // dump the logic into a file + sprintf( FileName, "aig\\%03d.blif", ++Counter ); + Aig_ManDumpBlif( pTemp, FileName ); + printf( "Speculation cone with %d nodes was written into file \"%s\".\n", Aig_ManNodeNum(pTemp), FileName ); + // clean up + Aig_ManStop( pTemp ); + Aig_ManForEachObj( p->pManFraig, pNode, i ) + pNode->pData = p; +} + +/**Function************************************************************* + + Synopsis [Verifies the generated counter-ex.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_FraigVerifyCounterEx( Fra_Man_t * p, Vec_Int_t * vCex ) +{ + Aig_Obj_t * pObj, ** ppClass; + int i, c; + assert( Aig_ManPiNum(p->pManAig) == Vec_IntSize(vCex) ); + // make sure the input pattern is not used + Aig_ManForEachObj( p->pManAig, pObj, i ) + assert( !pObj->fMarkB ); + // simulate the cex through the AIG + Aig_ManConst1(p->pManAig)->fMarkB = 1; + Aig_ManForEachPi( p->pManAig, pObj, i ) + pObj->fMarkB = Vec_IntEntry(vCex, i); + Aig_ManForEachNode( p->pManAig, pObj, i ) + pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & + (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); + Aig_ManForEachPo( p->pManAig, pObj, i ) + pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); + // check if the classes hold + Vec_PtrForEachEntry( p->pCla->vClasses1, pObj, i ) + { + if ( pObj->fPhase != pObj->fMarkB ) + printf( "The node %d is not constant under cex!\n", pObj->Id ); + } + Vec_PtrForEachEntry( p->pCla->vClasses, ppClass, i ) + { + for ( c = 1; ppClass[c]; c++ ) + if ( (ppClass[0]->fPhase ^ ppClass[c]->fPhase) != (ppClass[0]->fMarkB ^ ppClass[c]->fMarkB) ) + printf( "The nodes %d and %d are not equal under cex!\n", ppClass[0]->Id, ppClass[c]->Id ); +// for ( c = 0; ppClass[c]; c++ ) +// if ( Fra_ObjFraig(ppClass[c],p->pPars->nFramesK) == Aig_ManConst1(p->pManFraig) ) +// printf( "A member of non-constant class has a constant repr!\n" ); + } + // clean the simulation pattern + Aig_ManForEachObj( p->pManAig, pObj, i ) + pObj->fMarkB = 0; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fra_FraigNode( Fra_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; + int RetValue; + assert( !Aig_IsComplement(pObj) ); + // get representative of this class + pObjRepr = Fra_ClassObjRepr( pObj ); + if ( pObjRepr == NULL || // this is a unique node + (!p->pPars->fDoSparse && pObjRepr == Aig_ManConst1(p->pManAig)) ) // this is a sparse node + return; + // get the fraiged node + pObjFraig = Fra_ObjFraig( pObj, p->pPars->nFramesK ); + // get the fraiged representative + pObjReprFraig = Fra_ObjFraig( pObjRepr, p->pPars->nFramesK ); + // if the fraiged nodes are the same, return + if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) + { + p->nSatCallsSkipped++; + return; + } + assert( p->pPars->nFramesK || Aig_Regular(pObjFraig) != Aig_ManConst1(p->pManFraig) ); + // if they are proved different, the c-ex will be in p->pPatWords + RetValue = Fra_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); + if ( RetValue == 1 ) // proved equivalent + { +// if ( p->pPars->fChoicing ) +// Aig_ObjCreateRepr( p->pManFraig, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); + // the nodes proved equal + pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); + Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjFraig2 ); + return; + } + if ( RetValue == -1 ) // failed + { + if ( p->vTimeouts == NULL ) + p->vTimeouts = Vec_PtrAlloc( 100 ); + Vec_PtrPush( p->vTimeouts, pObj ); + if ( !p->pPars->fSpeculate ) + return; + assert( 0 ); + // speculate + p->nSpeculs++; + pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); + Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjFraig2 ); + Fra_FraigNodeSpeculate( p, pObj, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); + return; + } + // disprove the nodes + p->pCla->fRefinement = 1; + // if we do not include the node into those disproved, we may end up + // merging this node with another representative, for which proof has timed out + if ( p->vTimeouts ) + Vec_PtrPush( p->vTimeouts, pObj ); + // verify that the counter-example satisfies all the constraints +// if ( p->vCex ) +// Fra_FraigVerifyCounterEx( p, p->vCex ); + // simulate the counter-example and return the Fraig node + Fra_SmlResimulate( p ); + if ( !p->pPars->nFramesK && Fra_ClassObjRepr(pObj) == pObjRepr ) + printf( "Fra_FraigNode(): Error in class refinement!\n" ); + assert( p->pPars->nFramesK || Fra_ClassObjRepr(pObj) != pObjRepr ); +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_FraigSweep( Fra_Man_t * p ) +{ + Bar_Progress_t * pProgress; + Aig_Obj_t * pObj, * pObjNew; + int i, k = 0, Pos = 0; + // fraig latch outputs + Aig_ManForEachLoSeq( p->pManAig, pObj, i ) + { + Fra_FraigNode( p, pObj ); + if ( p->pPars->fUseImps ) + Pos = Fra_ImpCheckForNode( p, p->pCla->vImps, pObj, Pos ); + } + if ( p->pPars->fLatchCorr ) + return; + // fraig internal nodes + pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pManAig) ); + Aig_ManForEachNode( p->pManAig, pObj, i ) + { + Bar_ProgressUpdate( pProgress, i, NULL ); + // derive and remember the new fraig node + pObjNew = Aig_And( p->pManFraig, Fra_ObjChild0Fra(pObj,p->pPars->nFramesK), Fra_ObjChild1Fra(pObj,p->pPars->nFramesK) ); + Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjNew ); + Aig_Regular(pObjNew)->pData = p; + // quit if simulation detected a counter-example for a PO + if ( p->pManFraig->pData ) + continue; + // perform fraiging + Fra_FraigNode( p, pObj ); + if ( p->pPars->fUseImps ) + Pos = Fra_ImpCheckForNode( p, p->pCla->vImps, pObj, Pos ); + } + Bar_ProgressStop( pProgress ); + // try to prove the outputs of the miter + p->nNodesMiter = Aig_ManNodeNum(p->pManFraig); +// Fra_MiterStatus( p->pManFraig ); +// if ( p->pPars->fProve && p->pManFraig->pData == NULL ) +// Fra_MiterProve( p ); + // compress implications after processing all of them + if ( p->pPars->fUseImps ) + Fra_ImpCompactArray( p->pCla->vImps ); +} + +/**Function************************************************************* + + Synopsis [Performs fraiging of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_FraigPerform( Aig_Man_t * pManAig, Fra_Par_t * pPars ) +{ + Fra_Man_t * p; + Aig_Man_t * pManAigNew; + int clk; + if ( Aig_ManNodeNum(pManAig) == 0 ) + return Aig_ManDup(pManAig, 1); +clk = clock(); + assert( Aig_ManLatchNum(pManAig) == 0 ); + p = Fra_ManStart( pManAig, pPars ); + p->pManFraig = Fra_ManPrepareComb( p ); + p->pSml = Fra_SmlStart( pManAig, 0, 1, pPars->nSimWords ); + Fra_SmlSimulate( p, 0 ); +// if ( p->pPars->fChoicing ) +// Aig_ManReprStart( p->pManFraig, Aig_ManObjNumMax(p->pManAig) ); + // collect initial states + p->nLitsBeg = Fra_ClassesCountLits( p->pCla ); + p->nNodesBeg = Aig_ManNodeNum(pManAig); + p->nRegsBeg = Aig_ManRegNum(pManAig); + // perform fraig sweep + Fra_FraigSweep( p ); + // call back the procedure to check implications + if ( pManAig->pImpFunc ) + pManAig->pImpFunc( p, pManAig->pImpData ); + // finalize the fraiged manager + Fra_ManFinalizeComb( p ); + if ( p->pPars->fChoicing ) + { +int clk2 = clock(); + Fra_ClassesCopyReprs( p->pCla, p->vTimeouts ); + pManAigNew = Aig_ManDupRepr( p->pManAig, 1 ); + Aig_ManReprStart( pManAigNew, Aig_ManObjNumMax(pManAigNew) ); + Aig_ManTransferRepr( pManAigNew, p->pManAig ); + Aig_ManMarkValidChoices( pManAigNew ); + Aig_ManStop( p->pManFraig ); + p->pManFraig = NULL; +p->timeTrav += clock() - clk2; + } + else + { + Aig_ManCleanup( p->pManFraig ); + pManAigNew = p->pManFraig; + p->pManFraig = NULL; + } +p->timeTotal = clock() - clk; + // collect final stats + p->nLitsEnd = Fra_ClassesCountLits( p->pCla ); + p->nNodesEnd = Aig_ManNodeNum(pManAigNew); + p->nRegsEnd = Aig_ManRegNum(pManAigNew); + Fra_ManStop( p ); + return pManAigNew; +} + +/**Function************************************************************* + + Synopsis [Performs choicing of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax ) +{ + Fra_Par_t Pars, * pPars = &Pars; + Fra_ParamsDefault( pPars ); + pPars->nBTLimitNode = nConfMax; + pPars->fChoicing = 1; + pPars->fDoSparse = 1; + pPars->fSpeculate = 0; + pPars->fProve = 0; + pPars->fVerbose = 0; + return Fra_FraigPerform( pManAig, pPars ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax ) +{ + Aig_Man_t * pFraig; + Fra_Par_t Pars, * pPars = &Pars; + Fra_ParamsDefault( pPars ); + pPars->nBTLimitNode = nConfMax; + pPars->fChoicing = 0; + pPars->fDoSparse = 1; + pPars->fSpeculate = 0; + pPars->fProve = 0; + pPars->fVerbose = 0; + pFraig = Fra_FraigPerform( pManAig, pPars ); + return pFraig; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraImp.c b/abc70930/src/aig/fra/fraImp.c new file mode 100644 index 00000000..a5fc7d58 --- /dev/null +++ b/abc70930/src/aig/fra/fraImp.c @@ -0,0 +1,721 @@ +/**CFile**************************************************************** + + FileName [fraImp.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [Detecting and proving implications.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraImp.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Counts the number of 1s in each siminfo of each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Fra_SmlCountOnesOne( Fra_Sml_t * p, int Node ) +{ + unsigned * pSim; + int k, Counter = 0; + pSim = Fra_ObjSim( p, Node ); + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + Counter += Aig_WordCountOnes( pSim[k] ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of 1s in each siminfo of each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int * Fra_SmlCountOnes( Fra_Sml_t * p ) +{ + Aig_Obj_t * pObj; + int i, * pnBits; + pnBits = ALLOC( int, Aig_ManObjNumMax(p->pAig) ); + memset( pnBits, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) ); + Aig_ManForEachObj( p->pAig, pObj, i ) + pnBits[i] = Fra_SmlCountOnesOne( p, i ); + return pnBits; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if implications holds.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Sml_NodeCheckImp( Fra_Sml_t * p, int Left, int Right ) +{ + unsigned * pSimL, * pSimR; + int k; + pSimL = Fra_ObjSim( p, Left ); + pSimR = Fra_ObjSim( p, Right ); + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + if ( pSimL[k] & ~pSimR[k] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Counts the number of 1s in the complement of the implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Sml_NodeNotImpWeight( Fra_Sml_t * p, int Left, int Right ) +{ + unsigned * pSimL, * pSimR; + int k, Counter = 0; + pSimL = Fra_ObjSim( p, Left ); + pSimR = Fra_ObjSim( p, Right ); + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + Counter += Aig_WordCountOnes( pSimL[k] & ~pSimR[k] ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Computes the complement of the implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Sml_NodeSaveNotImpPatterns( Fra_Sml_t * p, int Left, int Right, unsigned * pResult ) +{ + unsigned * pSimL, * pSimR; + int k; + pSimL = Fra_ObjSim( p, Left ); + pSimR = Fra_ObjSim( p, Right ); + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + pResult[k] |= pSimL[k] & ~pSimR[k]; +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes sorted by the number of 1s.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Fra_SmlSortUsingOnes( Fra_Sml_t * p, int fLatchCorr ) +{ + Aig_Obj_t * pObj; + Vec_Ptr_t * vNodes; + int i, nNodes, nTotal, nBits, * pnNodes, * pnBits, * pMemory; + assert( p->nWordsTotal > 0 ); + // count 1s in each node's siminfo + pnBits = Fra_SmlCountOnes( p ); + // count number of nodes having that many 1s + nNodes = 0; + nBits = p->nWordsTotal * 32; + pnNodes = ALLOC( int, nBits + 1 ); + memset( pnNodes, 0, sizeof(int) * (nBits + 1) ); + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( i == 0 ) continue; + // skip non-PI and non-internal nodes + if ( fLatchCorr ) + { + if ( !Aig_ObjIsPi(pObj) ) + continue; + } + else + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + } + // skip nodes participating in the classes +// if ( Fra_ClassObjRepr(pObj) ) +// continue; + assert( pnBits[i] <= nBits ); // "<" because of normalized info + pnNodes[pnBits[i]]++; + nNodes++; + } + // allocate memory for all the nodes + pMemory = ALLOC( int, nNodes + nBits + 1 ); + // markup the memory for each node + vNodes = Vec_PtrAlloc( nBits + 1 ); + Vec_PtrPush( vNodes, pMemory ); + for ( i = 1; i <= nBits; i++ ) + { + pMemory += pnNodes[i-1] + 1; + Vec_PtrPush( vNodes, pMemory ); + } + // add the nodes + memset( pnNodes, 0, sizeof(int) * (nBits + 1) ); + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( i == 0 ) continue; + // skip non-PI and non-internal nodes + if ( fLatchCorr ) + { + if ( !Aig_ObjIsPi(pObj) ) + continue; + } + else + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) + continue; + } + // skip nodes participating in the classes +// if ( Fra_ClassObjRepr(pObj) ) +// continue; + pMemory = Vec_PtrEntry( vNodes, pnBits[i] ); + pMemory[ pnNodes[pnBits[i]]++ ] = i; + } + // add 0s in the end + nTotal = 0; + Vec_PtrForEachEntry( vNodes, pMemory, i ) + { + pMemory[ pnNodes[i]++ ] = 0; + nTotal += pnNodes[i]; + } + assert( nTotal == nNodes + nBits + 1 ); + free( pnNodes ); + free( pnBits ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the array of implications with the highest cost.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Fra_SmlSelectMaxCost( Vec_Int_t * vImps, int * pCosts, int nCostMax, int nImpLimit, int * pCostRange ) +{ + Vec_Int_t * vImpsNew; + int * pCostCount, nImpCount, Imp, i, c; + assert( Vec_IntSize(vImps) >= nImpLimit ); + // count how many implications have each cost + pCostCount = ALLOC( int, nCostMax + 1 ); + memset( pCostCount, 0, sizeof(int) * (nCostMax + 1) ); + for ( i = 0; i < Vec_IntSize(vImps); i++ ) + { + assert( pCosts[i] <= nCostMax ); + pCostCount[ pCosts[i] ]++; + } + assert( pCostCount[0] == 0 ); + // select the bound on the cost (above this bound, implication will be included) + nImpCount = 0; + for ( c = nCostMax; c > 0; c-- ) + { + nImpCount += pCostCount[c]; + if ( nImpCount >= nImpLimit ) + break; + } +// printf( "Cost range >= %d.\n", c ); + // collect implications with the given costs + vImpsNew = Vec_IntAlloc( nImpLimit ); + Vec_IntForEachEntry( vImps, Imp, i ) + { + if ( pCosts[i] < c ) + continue; + Vec_IntPush( vImpsNew, Imp ); + if ( Vec_IntSize( vImpsNew ) == nImpLimit ) + break; + } + free( pCostCount ); + if ( pCostRange ) + *pCostRange = c; + return vImpsNew; +} + +/**Function************************************************************* + + Synopsis [Compares two implications using their largest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sml_CompareMaxId( unsigned short * pImp1, unsigned short * pImp2 ) +{ + int Max1 = AIG_MAX( pImp1[0], pImp1[1] ); + int Max2 = AIG_MAX( pImp2[0], pImp2[1] ); + if ( Max1 < Max2 ) + return -1; + if ( Max1 > Max2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Derives implication candidates.] + + Description [Implication candidates have the property that + (1) they hold using sequential simulation information + (2) they do not hold using combinational simulation information + (3) they have as high expressive power as possible (heuristically) + that is, they are easy to disprove combinationally + meaning they cover relatively larger sequential subspace.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Fra_ImpDerive( Fra_Man_t * p, int nImpMaxLimit, int nImpUseLimit, int fLatchCorr ) +{ + int nSimWords = 64; + Fra_Sml_t * pSeq, * pComb; + Vec_Int_t * vImps, * vTemp; + Vec_Ptr_t * vNodes; + int * pImpCosts, * pNodesI, * pNodesK; + int nImpsTotal = 0, nImpsTried = 0, nImpsNonSeq = 0, nImpsComb = 0, nImpsCollected = 0; + int CostMin = AIG_INFINITY, CostMax = 0; + int i, k, Imp, CostRange, clk = clock(); + assert( Aig_ManObjNumMax(p->pManAig) < (1 << 15) ); + assert( nImpMaxLimit > 0 && nImpUseLimit > 0 && nImpUseLimit <= nImpMaxLimit ); + // normalize both managers + pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords ); + pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nSimWords, 1 ); + // get the nodes sorted by the number of 1s + vNodes = Fra_SmlSortUsingOnes( pSeq, fLatchCorr ); + // count the total number of implications + for ( k = nSimWords * 32; k > 0; k-- ) + for ( i = k - 1; i > 0; i-- ) + for ( pNodesI = Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ ) + for ( pNodesK = Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ ) + nImpsTotal++; + + // compute implications and their costs + pImpCosts = ALLOC( int, nImpMaxLimit ); + vImps = Vec_IntAlloc( nImpMaxLimit ); + for ( k = pSeq->nWordsTotal * 32; k > 0; k-- ) + for ( i = k - 1; i > 0; i-- ) + { + for ( pNodesI = Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ ) + for ( pNodesK = Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ ) + { + nImpsTried++; + if ( !Sml_NodeCheckImp(pSeq, *pNodesI, *pNodesK) ) + { + nImpsNonSeq++; + continue; + } + if ( Sml_NodeCheckImp(pComb, *pNodesI, *pNodesK) ) + { + nImpsComb++; + continue; + } + nImpsCollected++; + Imp = Fra_ImpCreate( *pNodesI, *pNodesK ); + pImpCosts[ Vec_IntSize(vImps) ] = Sml_NodeNotImpWeight(pComb, *pNodesI, *pNodesK); + CostMin = AIG_MIN( CostMin, pImpCosts[ Vec_IntSize(vImps) ] ); + CostMax = AIG_MAX( CostMax, pImpCosts[ Vec_IntSize(vImps) ] ); + Vec_IntPush( vImps, Imp ); + if ( Vec_IntSize(vImps) == nImpMaxLimit ) + goto finish; + } + } +finish: + Fra_SmlStop( pComb ); + Fra_SmlStop( pSeq ); + + // select implications with the highest cost + CostRange = CostMin; + if ( Vec_IntSize(vImps) > nImpUseLimit ) + { + vImps = Fra_SmlSelectMaxCost( vTemp = vImps, pImpCosts, nSimWords * 32, nImpUseLimit, &CostRange ); + Vec_IntFree( vTemp ); + } + + // dealloc + free( pImpCosts ); + free( Vec_PtrEntry(vNodes, 0) ); + Vec_PtrFree( vNodes ); + // reorder implications topologically + qsort( (void *)Vec_IntArray(vImps), Vec_IntSize(vImps), sizeof(int), + (int (*)(const void *, const void *)) Sml_CompareMaxId ); +if ( p->pPars->fVerbose ) +{ +printf( "Implications: All = %d. Try = %d. NonSeq = %d. Comb = %d. Res = %d.\n", + nImpsTotal, nImpsTried, nImpsNonSeq, nImpsComb, nImpsCollected ); +printf( "Implication weight: Min = %d. Pivot = %d. Max = %d. ", + CostMin, CostRange, CostMax ); +PRT( "Time", clock() - clk ); +} + return vImps; +} + + +// the following three procedures are called to +// - add implications to the SAT solver +// - check implications using the SAT solver +// - refine implications using after a cex is generated + +/**Function************************************************************* + + Synopsis [Add implication clauses to the SAT solver.] + + Description [Note that implications should be checked in the first frame!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ImpAddToSolver( Fra_Man_t * p, Vec_Int_t * vImps, int * pSatVarNums ) +{ + sat_solver * pSat = p->pSat; + Aig_Obj_t * pLeft, * pRight; + Aig_Obj_t * pLeftF, * pRightF; + int pLits[2], Imp, Left, Right, i, f, status; + int fComplL, fComplR; + Vec_IntForEachEntry( vImps, Imp, i ) + { + // get the corresponding nodes + pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) ); + pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) ); + // check if all the nodes are present + for ( f = 0; f < p->pPars->nFramesK; f++ ) + { + // map these info fraig + pLeftF = Fra_ObjFraig( pLeft, f ); + pRightF = Fra_ObjFraig( pRight, f ); + if ( Aig_ObjIsNone(Aig_Regular(pLeftF)) || Aig_ObjIsNone(Aig_Regular(pRightF)) ) + { + Vec_IntWriteEntry( vImps, i, 0 ); + break; + } + } + if ( f < p->pPars->nFramesK ) + continue; + // add constraints in each timeframe + for ( f = 0; f < p->pPars->nFramesK; f++ ) + { + // map these info fraig + pLeftF = Fra_ObjFraig( pLeft, f ); + pRightF = Fra_ObjFraig( pRight, f ); + // get the corresponding SAT numbers + Left = pSatVarNums[ Aig_Regular(pLeftF)->Id ]; + Right = pSatVarNums[ Aig_Regular(pRightF)->Id ]; + assert( Left > 0 && Left < p->nSatVars ); + assert( Right > 0 && Right < p->nSatVars ); + // get the complemented attributes + fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF); + fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF); + // get the constraint + // L => R L' v R (complement = L & R') + pLits[0] = 2 * Left + !fComplL; + pLits[1] = 2 * Right + fComplR; + // add contraint to solver + if ( !sat_solver_addclause( pSat, pLits, pLits + 2 ) ) + { + sat_solver_delete( pSat ); + p->pSat = NULL; + return; + } + } + } + status = sat_solver_simplify(pSat); + if ( status == 0 ) + { + sat_solver_delete( pSat ); + p->pSat = NULL; + } +// printf( "Total imps = %d. ", Vec_IntSize(vImps) ); + Fra_ImpCompactArray( vImps ); +// printf( "Valid imps = %d. \n", Vec_IntSize(vImps) ); +} + +/**Function************************************************************* + + Synopsis [Check implications for the node (if they are present).] + + Description [Returns the new position in the array.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ImpCheckForNode( Fra_Man_t * p, Vec_Int_t * vImps, Aig_Obj_t * pNode, int Pos ) +{ + Aig_Obj_t * pLeft, * pRight; + Aig_Obj_t * pLeftF, * pRightF; + int i, Imp, Left, Right, Max, RetValue; + int fComplL, fComplR; + Vec_IntForEachEntryStart( vImps, Imp, i, Pos ) + { + if ( Imp == 0 ) + continue; + Left = Fra_ImpLeft(Imp); + Right = Fra_ImpRight(Imp); + Max = AIG_MAX( Left, Right ); + assert( Max >= pNode->Id ); + if ( Max > pNode->Id ) + return i; + // get the corresponding nodes + pLeft = Aig_ManObj( p->pManAig, Left ); + pRight = Aig_ManObj( p->pManAig, Right ); + // get the corresponding FRAIG nodes + pLeftF = Fra_ObjFraig( pLeft, p->pPars->nFramesK ); + pRightF = Fra_ObjFraig( pRight, p->pPars->nFramesK ); + // get the complemented attributes + fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF); + fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF); + // check equality + if ( Aig_Regular(pLeftF) == Aig_Regular(pRightF) ) + { + if ( fComplL == fComplR ) // x => x - always true + continue; + assert( fComplL != fComplR ); + // consider 4 possibilities: + // NOT(1) => 1 or 0 => 1 - always true + // 1 => NOT(1) or 1 => 0 - never true + // NOT(x) => x or x - not always true + // x => NOT(x) or NOT(x) - not always true + if ( Aig_ObjIsConst1(Aig_Regular(pLeftF)) && fComplL ) // proved implication + continue; + // disproved implication + p->pCla->fRefinement = 1; + Vec_IntWriteEntry( vImps, i, 0 ); + continue; + } + // check the implication + // - if true, a clause is added + // - if false, a cex is simulated + // make sure the implication is refined + RetValue = Fra_NodesAreImp( p, Aig_Regular(pLeftF), Aig_Regular(pRightF), fComplL, fComplR ); + if ( RetValue != 1 ) + { + p->pCla->fRefinement = 1; + if ( RetValue == 0 ) + Fra_SmlResimulate( p ); + if ( Vec_IntEntry(vImps, i) != 0 ) + printf( "Fra_ImpCheckForNode(): Implication is not refined!\n" ); + assert( Vec_IntEntry(vImps, i) == 0 ); + } + } + return i; +} + +/**Function************************************************************* + + Synopsis [Removes those implications that no longer hold.] + + Description [Returns 1 if refinement has happened.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ImpRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vImps ) +{ + Aig_Obj_t * pLeft, * pRight; + int Imp, i, RetValue = 0; + Vec_IntForEachEntry( vImps, Imp, i ) + { + if ( Imp == 0 ) + continue; + // get the corresponding nodes + pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) ); + pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) ); + // check if implication holds using this simulation info + if ( !Sml_NodeCheckImp(p->pSml, pLeft->Id, pRight->Id) ) + { + Vec_IntWriteEntry( vImps, i, 0 ); + RetValue = 1; + } + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Removes empty implications.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ImpCompactArray( Vec_Int_t * vImps ) +{ + int i, k, Imp; + k = 0; + Vec_IntForEachEntry( vImps, Imp, i ) + if ( Imp ) + Vec_IntWriteEntry( vImps, k++, Imp ); + Vec_IntShrink( vImps, k ); +} + +/**Function************************************************************* + + Synopsis [Determines the ratio of the state space by computed implications.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +double Fra_ImpComputeStateSpaceRatio( Fra_Man_t * p ) +{ + int nSimWords = 64; + Fra_Sml_t * pComb; + unsigned * pResult; + double Ratio = 0.0; + int Left, Right, Imp, i; + if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 ) + return Ratio; + // simulate the AIG manager with combinational patterns + pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords ); + // go through the implications and collect where they do not hold + pResult = Fra_ObjSim( pComb, 0 ); + assert( pResult[0] == 0 ); + Vec_IntForEachEntry( p->pCla->vImps, Imp, i ) + { + Left = Fra_ImpLeft(Imp); + Right = Fra_ImpRight(Imp); + Sml_NodeSaveNotImpPatterns( pComb, Left, Right, pResult ); + } + // count the number of ones in this area + Ratio = 100.0 * Fra_SmlCountOnesOne( pComb, 0 ) / (32*(pComb->nWordsTotal-pComb->nWordsPref)); + Fra_SmlStop( pComb ); + return Ratio; +} + +/**Function************************************************************* + + Synopsis [Returns the number of failed implications.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_ImpVerifyUsingSimulation( Fra_Man_t * p ) +{ + int nFrames = 2000; + int nSimWords = 8; + Fra_Sml_t * pSeq; + char * pfFails; + int Left, Right, Imp, i, Counter; + if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 ) + return 0; + // simulate the AIG manager with combinational patterns + pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nFrames, nSimWords ); + // go through the implications and check how many of them do not hold + pfFails = ALLOC( char, Vec_IntSize(p->pCla->vImps) ); + memset( pfFails, 0, sizeof(char) * Vec_IntSize(p->pCla->vImps) ); + Vec_IntForEachEntry( p->pCla->vImps, Imp, i ) + { + Left = Fra_ImpLeft(Imp); + Right = Fra_ImpRight(Imp); + pfFails[i] = !Sml_NodeCheckImp( pSeq, Left, Right ); + } + // count how many has failed + Counter = 0; + for ( i = 0; i < Vec_IntSize(p->pCla->vImps); i++ ) + Counter += pfFails[i]; + free( pfFails ); + Fra_SmlStop( pSeq ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Record proven implications in the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ImpRecordInManager( Fra_Man_t * p, Aig_Man_t * pNew ) +{ + Aig_Obj_t * pLeft, * pRight, * pMiter; + int nPosOld, Imp, i; + if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 ) + return; + // go through the implication + nPosOld = Aig_ManPoNum(pNew); + Vec_IntForEachEntry( p->pCla->vImps, Imp, i ) + { + pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) ); + pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) ); + // record the implication: L' + R + pMiter = Aig_Or( pNew, + Aig_NotCond(pLeft->pData, !pLeft->fPhase), + Aig_NotCond(pRight->pData, pRight->fPhase) ); + Aig_ObjCreatePo( pNew, pMiter ); + } + pNew->nAsserts = Aig_ManPoNum(pNew) - nPosOld; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraInd.c b/abc70930/src/aig/fra/fraInd.c new file mode 100644 index 00000000..f45e8af0 --- /dev/null +++ b/abc70930/src/aig/fra/fraInd.c @@ -0,0 +1,479 @@ +/**CFile**************************************************************** + + FileName [fraInd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [Inductive prover.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraInd.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" +#include "cnf.h" +#include "dar.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs AIG rewriting on the constaint manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_FraigInductionRewrite( Fra_Man_t * p ) +{ + Aig_Man_t * pTemp; + Aig_Obj_t * pObj, * pObjPo; + int nTruePis, k, i, clk = clock(); + // perform AIG rewriting on the speculated frames + pTemp = Aig_ManDup( p->pManFraig, 0 ); +// pTemp = Dar_ManRwsat( pTemp, 1, 0 ); + pTemp = Dar_ManRewriteDefault( pTemp ); +// printf( "Before = %6d. After = %6d.\n", Aig_ManNodeNum(p->pManFraig), Aig_ManNodeNum(pTemp) ); +//Aig_ManDumpBlif( p->pManFraig, "1.blif" ); +//Aig_ManDumpBlif( pTemp, "2.blif" ); +// Fra_FramesWriteCone( pTemp ); +// Aig_ManStop( pTemp ); + // transfer PI/register pointers + assert( p->pManFraig->nRegs == pTemp->nRegs ); + assert( p->pManFraig->nAsserts == pTemp->nAsserts ); + nTruePis = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); + memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll ); + Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), p->pPars->nFramesK, Aig_ManConst1(pTemp) ); + Aig_ManForEachPiSeq( p->pManAig, pObj, i ) + Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ManPi(pTemp,nTruePis*p->pPars->nFramesK+i) ); + k = 0; + assert( Aig_ManRegNum(p->pManAig) == Aig_ManPoNum(pTemp) - pTemp->nAsserts ); + Aig_ManForEachLoSeq( p->pManAig, pObj, i ) + { + pObjPo = Aig_ManPo(pTemp, pTemp->nAsserts + k++); + Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ObjChild0(pObjPo) ); + } + // exchange + Aig_ManStop( p->pManFraig ); + p->pManFraig = pTemp; +p->timeRwr += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [Performs speculative reduction for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Fra_FramesConstrainNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, int iFrame ) +{ + Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter; + // skip nodes without representative + if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL ) + return; + assert( pObjRepr->Id < pObj->Id ); + // get the new node + pObjNew = Fra_ObjFraig( pObj, iFrame ); + // get the new node of the representative + pObjReprNew = Fra_ObjFraig( pObjRepr, iFrame ); + // if this is the same node, no need to add constraints + if ( Aig_Regular(pObjNew) == Aig_Regular(pObjReprNew) ) + return; + // these are different nodes - perform speculative reduction + pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase ); + // set the new node + Fra_ObjSetFraig( pObj, iFrame, pObjNew2 ); + // add the constraint + pMiter = Aig_Exor( pManFraig, Aig_Regular(pObjNew), Aig_Regular(pObjReprNew) ); + pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) ); + pMiter = Aig_Not( pMiter ); + Aig_ObjCreatePo( pManFraig, pMiter ); +} + +/**Function************************************************************* + + Synopsis [Prepares the inductive case with speculative reduction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_FramesWithClasses( Fra_Man_t * p ) +{ + Aig_Man_t * pManFraig; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; + int i, k, f; + assert( p->pManFraig == NULL ); + assert( Aig_ManRegNum(p->pManAig) > 0 ); + assert( Aig_ManRegNum(p->pManAig) < Aig_ManPiNum(p->pManAig) ); + + // start the fraig package + pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pManAig) * p->nFramesAll ); + pManFraig->pName = Aig_UtilStrsav( p->pManAig->pName ); + pManFraig->nRegs = p->pManAig->nRegs; + // create PI nodes for the frames + for ( f = 0; f < p->nFramesAll; f++ ) + Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), f, Aig_ManConst1(pManFraig) ); + for ( f = 0; f < p->nFramesAll; f++ ) + Aig_ManForEachPiSeq( p->pManAig, pObj, i ) + Fra_ObjSetFraig( pObj, f, Aig_ObjCreatePi(pManFraig) ); + // create latches for the first frame + Aig_ManForEachLoSeq( p->pManAig, pObj, i ) + Fra_ObjSetFraig( pObj, 0, Aig_ObjCreatePi(pManFraig) ); + + // add timeframes +// pManFraig->fAddStrash = 1; + for ( f = 0; f < p->nFramesAll - 1; f++ ) + { + // set the constraints on the latch outputs + Aig_ManForEachLoSeq( p->pManAig, pObj, i ) + Fra_FramesConstrainNode( pManFraig, pObj, f ); + // add internal nodes of this frame + Aig_ManForEachNode( p->pManAig, pObj, i ) + { + pObjNew = Aig_And( pManFraig, Fra_ObjChild0Fra(pObj,f), Fra_ObjChild1Fra(pObj,f) ); + Fra_ObjSetFraig( pObj, f, pObjNew ); + Fra_FramesConstrainNode( pManFraig, pObj, f ); + } + // transfer latch input to the latch outputs + Aig_ManForEachLiLoSeq( p->pManAig, pObjLi, pObjLo, k ) + Fra_ObjSetFraig( pObjLo, f+1, Fra_ObjChild0Fra(pObjLi,f) ); + } +// pManFraig->fAddStrash = 0; + // mark the asserts + pManFraig->nAsserts = Aig_ManPoNum(pManFraig); + // add the POs for the latch outputs of the last frame + Aig_ManForEachLoSeq( p->pManAig, pObj, i ) + Aig_ObjCreatePo( pManFraig, Fra_ObjFraig(pObj,p->nFramesAll-1) ); + + // remove dangling nodes + Aig_ManCleanup( pManFraig ); + // make sure the satisfying assignment is node assigned + assert( pManFraig->pData == NULL ); + return pManFraig; +} + +/**Function************************************************************* + + Synopsis [Prepares the inductive case with speculative reduction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_FramesAddMore( Aig_Man_t * p, int nFrames ) +{ + Aig_Obj_t * pObj, ** pLatches; + int i, k, f, nNodesOld; + // set copy pointer of each object to point to itself + Aig_ManForEachObj( p, pObj, i ) + pObj->pData = pObj; + // iterate and add objects + nNodesOld = Aig_ManObjNumMax(p); + pLatches = ALLOC( Aig_Obj_t *, Aig_ManRegNum(p) ); + for ( f = 0; f < nFrames; f++ ) + { + // clean latch inputs and outputs + Aig_ManForEachLiSeq( p, pObj, i ) + pObj->pData = NULL; + Aig_ManForEachLoSeq( p, pObj, i ) + pObj->pData = NULL; + // save the latch input values + k = 0; + Aig_ManForEachLiSeq( p, pObj, i ) + { + if ( Aig_ObjFanin0(pObj)->pData ) + pLatches[k++] = Aig_ObjChild0Copy(pObj); + else + pLatches[k++] = NULL; + } + // insert them as the latch output values + k = 0; + Aig_ManForEachLoSeq( p, pObj, i ) + pObj->pData = pLatches[k++]; + // create the next time frame of nodes + Aig_ManForEachNode( p, pObj, i ) + { + if ( i > nNodesOld ) + break; + if ( Aig_ObjFanin0(pObj)->pData && Aig_ObjFanin1(pObj)->pData ) + pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + else + pObj->pData = NULL; + } + } + free( pLatches ); +} + +/**Function************************************************************* + + Synopsis [Performs choicing of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, int nFramesP, int nFramesK, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose, int * pnIter ) +{ + int fUseSimpleCnf = 0; + int fUseOldSimulation = 0; + // other paramaters affecting performance + // - presence of FRAIGing in Abc_NtkDarSeqSweep() + // - using distance-1 patterns in Fra_SmlAssignDist1() + // - the number of simulation patterns + // - the number of BMC frames + + Fra_Man_t * p; + Fra_Par_t Pars, * pPars = &Pars; + Aig_Obj_t * pObj; + Cnf_Dat_t * pCnf; + Aig_Man_t * pManAigNew; + int nNodesBeg, nRegsBeg; + int nIter, i, clk = clock(), clk2; + + if ( Aig_ManNodeNum(pManAig) == 0 ) + { + if ( pnIter ) *pnIter = 0; + return Aig_ManDup(pManAig, 1); + } + assert( Aig_ManLatchNum(pManAig) == 0 ); + assert( Aig_ManRegNum(pManAig) > 0 ); + assert( nFramesK > 0 ); +//Aig_ManShow( pManAig, 0, NULL ); + + nNodesBeg = Aig_ManNodeNum(pManAig); + nRegsBeg = Aig_ManRegNum(pManAig); + + // enhance the AIG by adding timeframes +// Fra_FramesAddMore( pManAig, 3 ); + + // get parameters + Fra_ParamsDefaultSeq( pPars ); + pPars->nFramesP = nFramesP; + pPars->nFramesK = nFramesK; + pPars->nMaxImps = nMaxImps; + pPars->fVerbose = fVerbose; + pPars->fRewrite = fRewrite; + pPars->fLatchCorr = fLatchCorr; + pPars->fUseImps = fUseImps; + pPars->fWriteImps = fWriteImps; + + // start the fraig manager for this run + p = Fra_ManStart( pManAig, pPars ); + // derive and refine e-classes using K initialized frames + if ( fUseOldSimulation ) + { + if ( pPars->nFramesP > 0 ) + { + pPars->nFramesP = 0; + printf( "Fra_FraigInduction(): Prefix cannot be used.\n" ); + } + p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords ); + Fra_SmlSimulate( p, 1 ); + } + else + { + // bug: r iscas/blif/s5378.blif ; st; ssw -v + // bug: r iscas/blif/s1238.blif ; st; ssw -v + // refine the classes with more simulation rounds +if ( fVerbose ) +printf( "Simulating %d AIG nodes for %d cycles ... ", Aig_ManNodeNum(pManAig), pPars->nFramesP + 32 ); + p->pSml = Fra_SmlSimulateSeq( pManAig, pPars->nFramesP, 32, 1 ); //pPars->nFramesK + 1, 1 ); +if ( fVerbose ) +{ +PRT( "Time", clock() - clk ); +} + Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr ); +// Fra_ClassesPostprocess( p->pCla ); + // allocate new simulation manager for simulating counter-examples + Fra_SmlStop( p->pSml ); + p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords ); + } + + // select the most expressive implications + if ( pPars->fUseImps ) + p->pCla->vImps = Fra_ImpDerive( p, 5000000, pPars->nMaxImps, pPars->fLatchCorr ); + + // perform BMC (for the min number of frames) + Fra_BmcPerform( p, pPars->nFramesP, pPars->nFramesK+1 ); // +1 is needed to prevent non-refinement +//Fra_ClassesPrint( p->pCla, 1 ); +// if ( p->vCex == NULL ) +// p->vCex = Vec_IntAlloc( 1000 ); + + p->nLitsBeg = Fra_ClassesCountLits( p->pCla ); + p->nNodesBeg = nNodesBeg; // Aig_ManNodeNum(pManAig); + p->nRegsBeg = nRegsBeg; // Aig_ManRegNum(pManAig); + + // dump AIG of the timeframes +// pManAigNew = Fra_ClassesDeriveAig( p->pCla, pPars->nFramesK ); +// Aig_ManDumpBlif( pManAigNew, "frame_aig.blif" ); +// Fra_ManPartitionTest2( pManAigNew ); +// Aig_ManStop( pManAigNew ); + + // iterate the inductive case + p->pCla->fRefinement = 1; + for ( nIter = 0; p->pCla->fRefinement; nIter++ ) + { + int nLitsOld = Fra_ClassesCountLits(p->pCla); + int nImpsOld = p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0; + // mark the classes as non-refined + p->pCla->fRefinement = 0; + // derive non-init K-timeframes while implementing e-classes +clk2 = clock(); + p->pManFraig = Fra_FramesWithClasses( p ); +p->timeTrav += clock() - clk2; +//Aig_ManDumpBlif( p->pManFraig, "testaig.blif" ); + + // perform AIG rewriting + if ( p->pPars->fRewrite ) + Fra_FraigInductionRewrite( p ); + + // convert the manager to SAT solver (the last nLatches outputs are inputs) + if ( fUseSimpleCnf || pPars->fUseImps ) + pCnf = Cnf_DeriveSimple( p->pManFraig, Aig_ManRegNum(p->pManFraig) ); + else + pCnf = Cnf_Derive( p->pManFraig, Aig_ManRegNum(p->pManFraig) ); +//Cnf_DataWriteIntoFile( pCnf, "temp.cnf", 1 ); + + p->pSat = Cnf_DataWriteIntoSolver( pCnf ); + p->nSatVars = pCnf->nVars; + assert( p->pSat != NULL ); + if ( p->pSat == NULL ) + printf( "Fra_FraigInduction(): Computed CNF is not valid.\n" ); + if ( pPars->fUseImps ) + { + Fra_ImpAddToSolver( p, p->pCla->vImps, pCnf->pVarNums ); + if ( p->pSat == NULL ) + printf( "Fra_FraigInduction(): Adding implicationsn to CNF led to a conflict.\n" ); + } + + // set the pointers to the manager + Aig_ManForEachObj( p->pManFraig, pObj, i ) + pObj->pData = p; + + // prepare solver for fraiging the last timeframe + Fra_ManClean( p, Aig_ManObjNumMax(p->pManFraig) + Aig_ManNodeNum(p->pManAig) ); + + // transfer PI/LO variable numbers + Aig_ManForEachObj( p->pManFraig, pObj, i ) + { + if ( pCnf->pVarNums[pObj->Id] == -1 ) + continue; + Fra_ObjSetSatNum( pObj, pCnf->pVarNums[pObj->Id] ); + Fra_ObjSetFaninVec( pObj, (void *)1 ); + } + Cnf_DataFree( pCnf ); + + // report the intermediate results + if ( fVerbose ) + { + printf( "%3d : Const = %6d. Class = %6d. L = %6d. LR = %6d. ", + nIter, Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), + Fra_ClassesCountLits(p->pCla), p->pManFraig->nAsserts ); + if ( p->pCla->vImps ) + printf( "I = %6d. ", Vec_IntSize(p->pCla->vImps) ); + printf( "NR = %6d.\n", Aig_ManNodeNum(p->pManFraig) ); + } + + // perform sweeping + p->nSatCallsRecent = 0; + p->nSatCallsSkipped = 0; + Fra_FraigSweep( p ); + +// Sat_SolverPrintStats( stdout, p->pSat ); + + // remove FRAIG and SAT solver + Aig_ManStop( p->pManFraig ); p->pManFraig = NULL; + sat_solver_delete( p->pSat ); p->pSat = NULL; + memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll ); +// printf( "Recent SAT called = %d. Skipped = %d.\n", p->nSatCallsRecent, p->nSatCallsSkipped ); + assert( p->vTimeouts == NULL ); + if ( p->vTimeouts ) + printf( "Fra_FraigInduction(): SAT solver timed out!\n" ); + // check if refinement has happened +// p->pCla->fRefinement = (int)(nLitsOld != Fra_ClassesCountLits(p->pCla)); + if ( p->pCla->fRefinement && + nLitsOld == Fra_ClassesCountLits(p->pCla) && + nImpsOld == (p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0) ) + { + printf( "Fra_FraigInduction(): Internal error. The result may not verify.\n" ); + break; + } + } +/* + // verify implications using simulation + if ( p->pCla->vImps && Vec_IntSize(p->pCla->vImps) ) + { + int Temp, clk = clock(); + if ( Temp = Fra_ImpVerifyUsingSimulation( p ) ) + printf( "Implications failing the simulation test = %d (out of %d). ", Temp, Vec_IntSize(p->pCla->vImps) ); + else + printf( "All %d implications have passed the simulation test. ", Vec_IntSize(p->pCla->vImps) ); + PRT( "Time", clock() - clk ); + } +*/ + + // move the classes into representatives and reduce AIG +clk2 = clock(); +// Fra_ClassesPrint( p->pCla, 1 ); + Fra_ClassesSelectRepr( p->pCla ); + Fra_ClassesCopyReprs( p->pCla, p->vTimeouts ); + pManAigNew = Aig_ManDupRepr( pManAig, 0 ); + // add implications to the manager + if ( fWriteImps && p->pCla->vImps && Vec_IntSize(p->pCla->vImps) ) + Fra_ImpRecordInManager( p, pManAigNew ); + // cleanup the new manager + Aig_ManSeqCleanup( pManAigNew ); +// Aig_ManCountMergeRegs( pManAigNew ); +p->timeTrav += clock() - clk2; +p->timeTotal = clock() - clk; + // get the final stats + p->nLitsEnd = Fra_ClassesCountLits( p->pCla ); + p->nNodesEnd = Aig_ManNodeNum(pManAigNew); + p->nRegsEnd = Aig_ManRegNum(pManAigNew); + // free the manager + Fra_ManStop( p ); + // check the output +// if ( Aig_ManPoNum(pManAigNew) - Aig_ManRegNum(pManAigNew) == 1 ) +// if ( Aig_ObjChild0( Aig_ManPo(pManAigNew,0) ) == Aig_ManConst0(pManAigNew) ) +// printf( "Proved output constant 0.\n" ); + if ( pnIter ) *pnIter = nIter; + return pManAigNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraLcr.c b/abc70930/src/aig/fra/fraLcr.c new file mode 100644 index 00000000..50fd6687 --- /dev/null +++ b/abc70930/src/aig/fra/fraLcr.c @@ -0,0 +1,655 @@ +/**CFile**************************************************************** + + FileName [fraLcorr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [Latch correspondence computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraLcorr.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Fra_Lcr_t_ Fra_Lcr_t; +struct Fra_Lcr_t_ +{ + // original AIG + Aig_Man_t * pAig; + // equivalence class representation + Fra_Cla_t * pCla; + // partitioning information + Vec_Ptr_t * vParts; // output partitions + int * pInToOutPart; // mapping of PI num into PO partition num + int * pInToOutNum; // mapping of PI num into the num of this PO in the partition + // AIGs for the partitions + Vec_Ptr_t * vFraigs; + // other variables + int fRefining; + // parameters + int nFramesP; + int fVerbose; + // statistics + int nIters; + int nLitsBeg; + int nLitsEnd; + int nNodesBeg; + int nNodesEnd; + int nRegsBeg; + int nRegsEnd; + // runtime + int timeSim; + int timePart; + int timeTrav; + int timeFraig; + int timeUpdate; + int timeTotal; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the retiming manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Lcr_t * Lcr_ManAlloc( Aig_Man_t * pAig ) +{ + Fra_Lcr_t * p; + p = ALLOC( Fra_Lcr_t, 1 ); + memset( p, 0, sizeof(Fra_Lcr_t) ); + p->pAig = pAig; + p->pInToOutPart = ALLOC( int, Aig_ManPiNum(pAig) ); + memset( p->pInToOutPart, 0, sizeof(int) * Aig_ManPiNum(pAig) ); + p->pInToOutNum = ALLOC( int, Aig_ManPiNum(pAig) ); + memset( p->pInToOutNum, 0, sizeof(int) * Aig_ManPiNum(pAig) ); + p->vFraigs = Vec_PtrAlloc( 1000 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Prints stats for the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lcr_ManPrint( Fra_Lcr_t * p ) +{ + printf( "Iterations = %d. LitBeg = %d. LitEnd = %d. (%6.2f %%).\n", + p->nIters, p->nLitsBeg, p->nLitsEnd, 100.0*p->nLitsEnd/p->nLitsBeg ); + printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", + p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg, + p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/p->nRegsBeg ); + PRT( "AIG simulation ", p->timeSim ); + PRT( "AIG partitioning", p->timePart ); + PRT( "AIG rebuiding ", p->timeTrav ); + PRT( "FRAIGing ", p->timeFraig ); + PRT( "AIG updating ", p->timeUpdate ); + PRT( "TOTAL RUNTIME ", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Deallocates the retiming manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lcr_ManFree( Fra_Lcr_t * p ) +{ + Aig_Obj_t * pObj; + int i; + if ( p->fVerbose ) + Lcr_ManPrint( p ); + Aig_ManForEachPi( p->pAig, pObj, i ) + pObj->pNext = NULL; + Vec_PtrFree( p->vFraigs ); + if ( p->pCla ) Fra_ClassesStop( p->pCla ); + if ( p->vParts ) Vec_VecFree( (Vec_Vec_t *)p->vParts ); + free( p->pInToOutPart ); + free( p->pInToOutNum ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Prepare the AIG for class computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Man_t * Fra_LcrAigPrepare( Aig_Man_t * pAig ) +{ + Fra_Man_t * p; + Aig_Obj_t * pObj; + int i; + p = ALLOC( Fra_Man_t, 1 ); + memset( p, 0, sizeof(Fra_Man_t) ); + Aig_ManForEachPi( pAig, pObj, i ) + pObj->pData = p; + return p; +} + +/**Function************************************************************* + + Synopsis [Prepare the AIG for class computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_LcrAigPrepareTwo( Aig_Man_t * pAig, Fra_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachPi( pAig, pObj, i ) + pObj->pData = p; +} + +/**Function************************************************************* + + Synopsis [Compares two nodes for equivalence after partitioned fraiging.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_LcrNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + Fra_Man_t * pTemp = pObj0->pData; + Fra_Lcr_t * pLcr = (Fra_Lcr_t *)pTemp->pBmc; + Aig_Man_t * pFraig; + Aig_Obj_t * pOut0, * pOut1; + int nPart0, nPart1; + assert( Aig_ObjIsPi(pObj0) ); + assert( Aig_ObjIsPi(pObj1) ); + // find the partition to which these nodes belong + nPart0 = pLcr->pInToOutPart[(int)pObj0->pNext]; + nPart1 = pLcr->pInToOutPart[(int)pObj1->pNext]; + // if this is the result of refinement of the class created const-1 nodes + // the nodes may end up in different partions - we assume them equivalent + if ( nPart0 != nPart1 ) + { + assert( 0 ); + return 1; + } + assert( nPart0 == nPart1 ); + pFraig = Vec_PtrEntry( pLcr->vFraigs, nPart0 ); + // get the fraig outputs + pOut0 = Aig_ManPo( pFraig, pLcr->pInToOutNum[(int)pObj0->pNext] ); + pOut1 = Aig_ManPo( pFraig, pLcr->pInToOutNum[(int)pObj1->pNext] ); + return Aig_ObjFanin0(pOut0) == Aig_ObjFanin0(pOut1); +} + +/**Function************************************************************* + + Synopsis [Compares the node with a constant after partioned fraiging.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_LcrNodeIsConst( Aig_Obj_t * pObj ) +{ + Fra_Man_t * pTemp = pObj->pData; + Fra_Lcr_t * pLcr = (Fra_Lcr_t *)pTemp->pBmc; + Aig_Man_t * pFraig; + Aig_Obj_t * pOut; + int nPart; + assert( Aig_ObjIsPi(pObj) ); + // find the partition to which these nodes belong + nPart = pLcr->pInToOutPart[(int)pObj->pNext]; + pFraig = Vec_PtrEntry( pLcr->vFraigs, nPart ); + // get the fraig outputs + pOut = Aig_ManPo( pFraig, pLcr->pInToOutNum[(int)pObj->pNext] ); + return Aig_ObjFanin0(pOut) == Aig_ManConst1(pFraig); +} + +/**Function************************************************************* + + Synopsis [Give the AIG and classes, reduces AIG for partitioning.] + + Description [Ignores registers that are not in the classes. + Places candidate equivalent classes of registers into single outputs + (for ease of partitioning). The resulting combinational AIG contains + outputs in the same order as equivalence classes of registers, + followed by constant-1 registers. Preserves the set of all inputs. + Complemented attributes of the outputs do not matter because we need + then only for collecting the structural info.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_LcrDeriveAigForPartitioning( Fra_Lcr_t * pLcr ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjPo, * pObjNew, ** ppClass, * pMiter; + int i, c, Offset; + // remember the numbers of the inputs of the original AIG + Aig_ManForEachPi( pLcr->pAig, pObj, i ) + { + pObj->pData = pLcr; + pObj->pNext = (Aig_Obj_t *)i; + } + // compute the LO/LI offset + Offset = Aig_ManPoNum(pLcr->pAig) - Aig_ManPiNum(pLcr->pAig); + // create the PIs + Aig_ManCleanData( pLcr->pAig ); + pNew = Aig_ManStartFrom( pLcr->pAig ); + // go over the equivalence classes + Vec_PtrForEachEntry( pLcr->pCla->vClasses, ppClass, i ) + { + pMiter = Aig_ManConst0(pNew); + for ( c = 0; ppClass[c]; c++ ) + { + assert( Aig_ObjIsPi(ppClass[c]) ); + pObjPo = Aig_ManPo( pLcr->pAig, Offset+(int)ppClass[c]->pNext ); + pObjNew = Aig_ManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) ); + pMiter = Aig_Exor( pNew, pMiter, pObjNew ); + } + Aig_ObjCreatePo( pNew, pMiter ); + } + // go over the constant candidates + Vec_PtrForEachEntry( pLcr->pCla->vClasses1, pObj, i ) + { + assert( Aig_ObjIsPi(pObj) ); + pObjPo = Aig_ManPo( pLcr->pAig, Offset+(int)pObj->pNext ); + pMiter = Aig_ManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) ); + Aig_ObjCreatePo( pNew, pMiter ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Remaps partitions into the inputs of original AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_LcrRemapPartitions( Vec_Ptr_t * vParts, Fra_Cla_t * pCla, int * pInToOutPart, int * pInToOutNum ) +{ + Vec_Int_t * vOne, * vOneNew; + Aig_Obj_t ** ppClass, * pObjPi; + int Out, Offset, i, k, c; + // compute the LO/LI offset + Offset = Aig_ManPoNum(pCla->pAig) - Aig_ManPiNum(pCla->pAig); + Vec_PtrForEachEntry( vParts, vOne, i ) + { + vOneNew = Vec_IntAlloc( Vec_IntSize(vOne) ); + Vec_IntForEachEntry( vOne, Out, k ) + { + if ( Out < Vec_PtrSize(pCla->vClasses) ) + { + ppClass = Vec_PtrEntry( pCla->vClasses, Out ); + for ( c = 0; ppClass[c]; c++ ) + { + pInToOutPart[(int)ppClass[c]->pNext] = i; + pInToOutNum[(int)ppClass[c]->pNext] = Vec_IntSize(vOneNew); + Vec_IntPush( vOneNew, Offset+(int)ppClass[c]->pNext ); + } + } + else + { + pObjPi = Vec_PtrEntry( pCla->vClasses1, Out - Vec_PtrSize(pCla->vClasses) ); + pInToOutPart[(int)pObjPi->pNext] = i; + pInToOutNum[(int)pObjPi->pNext] = Vec_IntSize(vOneNew); + Vec_IntPush( vOneNew, Offset+(int)pObjPi->pNext ); + } + } + // replace the class + Vec_PtrWriteEntry( vParts, i, vOneNew ); + Vec_IntFree( vOne ); + } +} + +/**Function************************************************************* + + Synopsis [Creates AIG of one partition with speculative reduction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Fra_LcrCreatePart_rec( Fra_Cla_t * pCla, Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return pObj->pData; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsPi(pObj) ) + { +// Aig_Obj_t * pRepr = Fra_ClassObjRepr(pObj); + Aig_Obj_t * pRepr = pCla->pMemRepr[pObj->Id]; + if ( pRepr == NULL ) + pObj->pData = Aig_ObjCreatePi( pNew ); + else + { + pObj->pData = Fra_LcrCreatePart_rec( pCla, pNew, p, pRepr ); + pObj->pData = Aig_NotCond( pObj->pData, pRepr->fPhase ^ pObj->fPhase ); + } + return pObj->pData; + } + Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin0(pObj) ); + Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin1(pObj) ); + return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Creates AIG of one partition with speculative reduction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_LcrCreatePart( Fra_Lcr_t * p, Vec_Int_t * vPart ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew; + int Out, i; + // create new AIG for this partition + pNew = Aig_ManStartFrom( p->pAig ); + Aig_ManIncrementTravId( p->pAig ); + Aig_ObjSetTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) ); + Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew); + Vec_IntForEachEntry( vPart, Out, i ) + { + pObj = Aig_ManPo( p->pAig, Out ); + if ( pObj->fMarkA ) + { + pObjNew = Fra_LcrCreatePart_rec( p->pCla, pNew, p->pAig, Aig_ObjFanin0(pObj) ); + pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ); + } + else + pObjNew = Aig_ManConst1( pNew ); + Aig_ObjCreatePo( pNew, pObjNew ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes belonging to the equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClassNodesMark( Fra_Lcr_t * p ) +{ + Aig_Obj_t * pObj, ** ppClass; + int i, c, Offset; + // compute the LO/LI offset + Offset = Aig_ManPoNum(p->pCla->pAig) - Aig_ManPiNum(p->pCla->pAig); + // mark the nodes remaining in the classes + Vec_PtrForEachEntry( p->pCla->vClasses1, pObj, i ) + { + pObj = Aig_ManPo( p->pCla->pAig, Offset+(int)pObj->pNext ); + pObj->fMarkA = 1; + } + Vec_PtrForEachEntry( p->pCla->vClasses, ppClass, i ) + { + for ( c = 0; ppClass[c]; c++ ) + { + pObj = Aig_ManPo( p->pCla->pAig, Offset+(int)ppClass[c]->pNext ); + pObj->fMarkA = 1; + } + } +} + +/**Function************************************************************* + + Synopsis [Unmarks the nodes belonging to the equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ClassNodesUnmark( Fra_Lcr_t * p ) +{ + Aig_Obj_t * pObj, ** ppClass; + int i, c, Offset; + // compute the LO/LI offset + Offset = Aig_ManPoNum(p->pCla->pAig) - Aig_ManPiNum(p->pCla->pAig); + // mark the nodes remaining in the classes + Vec_PtrForEachEntry( p->pCla->vClasses1, pObj, i ) + { + pObj = Aig_ManPo( p->pCla->pAig, Offset+(int)pObj->pNext ); + pObj->fMarkA = 0; + } + Vec_PtrForEachEntry( p->pCla->vClasses, ppClass, i ) + { + for ( c = 0; ppClass[c]; c++ ) + { + pObj = Aig_ManPo( p->pCla->pAig, Offset+(int)ppClass[c]->pNext ); + pObj->fMarkA = 0; + } + } +} + +/**Function************************************************************* + + Synopsis [Performs choicing of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter ) +{ + int nPartSize = 200; + int fReprSelect = 0; + + Fra_Lcr_t * p; + Fra_Sml_t * pSml; + Fra_Man_t * pTemp; + Aig_Man_t * pAigPart, * pAigNew = NULL; + Vec_Int_t * vPart; +// Aig_Obj_t * pObj = Aig_ManObj(pAig, 2078); + int i, nIter, timeSim, clk = clock(), clk2, clk3; + if ( Aig_ManNodeNum(pAig) == 0 ) + { + if ( pnIter ) *pnIter = 0; + return Aig_ManDup(pAig, 1); + } + assert( Aig_ManLatchNum(pAig) == 0 ); + assert( Aig_ManRegNum(pAig) > 0 ); + + // simulate the AIG +clk2 = clock(); +if ( fVerbose ) +printf( "Simulating AIG with %d nodes for %d cycles ... ", Aig_ManNodeNum(pAig), nFramesP + 32 ); + pSml = Fra_SmlSimulateSeq( pAig, nFramesP, 32, 1 ); +if ( fVerbose ) +{ +PRT( "Time", clock() - clk2 ); +timeSim = clock() - clk2; +} + // check if simulation discovered non-constant-0 POs + if ( fProve && pSml->fNonConstOut ) + { + Fra_SmlStop( pSml ); + return NULL; + } + + // start the manager + p = Lcr_ManAlloc( pAig ); + p->nFramesP = nFramesP; + p->fVerbose = fVerbose; + p->timeSim += timeSim; + + pTemp = Fra_LcrAigPrepare( pAig ); + pTemp->pBmc = (Fra_Bmc_t *)p; + pTemp->pSml = pSml; + + // get preliminary info about equivalence classes + pTemp->pCla = p->pCla = Fra_ClassesStart( p->pAig ); + Fra_ClassesPrepare( p->pCla, 1 ); + p->pCla->pFuncNodeIsConst = Fra_LcrNodeIsConst; + p->pCla->pFuncNodesAreEqual = Fra_LcrNodesAreEqual; + Fra_SmlStop( pTemp->pSml ); + + // partition the AIG for latch correspondence computation +clk2 = clock(); +if ( fVerbose ) +printf( "Partitioning AIG ... " ); + pAigPart = Fra_LcrDeriveAigForPartitioning( p ); + p->vParts = (Vec_Ptr_t *)Aig_ManPartitionSmart( pAigPart, nPartSize, 0, NULL ); + Fra_LcrRemapPartitions( p->vParts, p->pCla, p->pInToOutPart, p->pInToOutNum ); + Aig_ManStop( pAigPart ); +if ( fVerbose ) +{ +PRT( "Time", clock() - clk2 ); +p->timePart += clock() - clk2; +} + + // get the initial stats + p->nLitsBeg = Fra_ClassesCountLits( p->pCla ); + p->nNodesBeg = Aig_ManNodeNum(p->pAig); + p->nRegsBeg = Aig_ManRegNum(p->pAig); + + // perforn interative reduction of the partitions + p->fRefining = 1; + for ( nIter = 0; p->fRefining; nIter++ ) + { + p->fRefining = 0; + clk3 = clock(); + // derive AIGs for each partition + Fra_ClassNodesMark( p ); + Vec_PtrClear( p->vFraigs ); + Vec_PtrForEachEntry( p->vParts, vPart, i ) + { +clk2 = clock(); + pAigPart = Fra_LcrCreatePart( p, vPart ); +p->timeTrav += clock() - clk2; +clk2 = clock(); + pAigNew = Fra_FraigEquivence( pAigPart, nConfMax ); +p->timeFraig += clock() - clk2; + Vec_PtrPush( p->vFraigs, pAigNew ); + Aig_ManStop( pAigPart ); + } + Fra_ClassNodesUnmark( p ); + // report the intermediate results + if ( fVerbose ) + { + printf( "%3d : Const = %6d. Class = %6d. L = %6d. Part = %3d. ", + nIter, Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), + Fra_ClassesCountLits(p->pCla), Vec_PtrSize(p->vParts) ); + PRT( "T", clock() - clk3 ); + } + // refine the classes + Fra_LcrAigPrepareTwo( p->pAig, pTemp ); + if ( Fra_ClassesRefine( p->pCla ) ) + p->fRefining = 1; + if ( Fra_ClassesRefine1( p->pCla, 0, NULL ) ) + p->fRefining = 1; + // clean the fraigs + Vec_PtrForEachEntry( p->vFraigs, pAigPart, i ) + Aig_ManStop( pAigPart ); + + // repartition if needed + if ( 1 ) + { +clk2 = clock(); + Vec_VecFree( (Vec_Vec_t *)p->vParts ); + pAigPart = Fra_LcrDeriveAigForPartitioning( p ); + p->vParts = (Vec_Ptr_t *)Aig_ManPartitionSmart( pAigPart, nPartSize, 0, NULL ); + Fra_LcrRemapPartitions( p->vParts, p->pCla, p->pInToOutPart, p->pInToOutNum ); + Aig_ManStop( pAigPart ); +p->timePart += clock() - clk2; + } + } + free( pTemp ); + p->nIters = nIter; + + // move the classes into representatives and reduce AIG +clk2 = clock(); +// Fra_ClassesPrint( p->pCla, 1 ); + if ( fReprSelect ) + Fra_ClassesSelectRepr( p->pCla ); + Fra_ClassesCopyReprs( p->pCla, NULL ); + pAigNew = Aig_ManDupRepr( p->pAig, 0 ); + Aig_ManSeqCleanup( pAigNew ); +// Aig_ManCountMergeRegs( pAigNew ); +p->timeUpdate += clock() - clk2; +p->timeTotal = clock() - clk; + // get the final stats + p->nLitsEnd = Fra_ClassesCountLits( p->pCla ); + p->nNodesEnd = Aig_ManNodeNum(pAigNew); + p->nRegsEnd = Aig_ManRegNum(pAigNew); + Lcr_ManFree( p ); + if ( pnIter ) *pnIter = nIter; + return pAigNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraMan.c b/abc70930/src/aig/fra/fraMan.c new file mode 100644 index 00000000..f505b0c2 --- /dev/null +++ b/abc70930/src/aig/fra/fraMan.c @@ -0,0 +1,304 @@ +/**CFile**************************************************************** + + FileName [fraMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [Starts the FRAIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraMan.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets the default solving parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ParamsDefault( Fra_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Fra_Par_t) ); + pPars->nSimWords = 32; // the number of words in the simulation info + pPars->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached + pPars->fPatScores = 0; // enables simulation pattern scoring + pPars->MaxScore = 25; // max score after which resimulation is used + pPars->fDoSparse = 1; // skips sparse functions +// pPars->dActConeRatio = 0.05; // the ratio of cone to be bumped +// pPars->dActConeBumpMax = 5.0; // the largest bump of activity + pPars->dActConeRatio = 0.3; // the ratio of cone to be bumped + pPars->dActConeBumpMax = 10.0; // the largest bump of activity + pPars->nBTLimitNode = 100; // conflict limit at a node + pPars->nBTLimitMiter = 500000; // conflict limit at an output + pPars->nFramesK = 0; // the number of timeframes to unroll + pPars->fConeBias = 1; + pPars->fRewrite = 0; +} + +/**Function************************************************************* + + Synopsis [Sets the default solving parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ParamsDefaultSeq( Fra_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Fra_Par_t) ); + pPars->nSimWords = 1; // the number of words in the simulation info + pPars->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached + pPars->fPatScores = 0; // enables simulation pattern scoring + pPars->MaxScore = 25; // max score after which resimulation is used + pPars->fDoSparse = 1; // skips sparse functions + pPars->dActConeRatio = 0.3; // the ratio of cone to be bumped + pPars->dActConeBumpMax = 10.0; // the largest bump of activity + pPars->nBTLimitNode = 10000000; // conflict limit at a node + pPars->nBTLimitMiter = 500000; // conflict limit at an output + pPars->nFramesK = 1; // the number of timeframes to unroll + pPars->fConeBias = 0; + pPars->fRewrite = 0; + pPars->fLatchCorr = 0; +} + +/**Function************************************************************* + + Synopsis [Starts the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Man_t * Fra_ManStart( Aig_Man_t * pManAig, Fra_Par_t * pPars ) +{ + Fra_Man_t * p; + Aig_Obj_t * pObj; + int i; + // allocate the fraiging manager + p = ALLOC( Fra_Man_t, 1 ); + memset( p, 0, sizeof(Fra_Man_t) ); + p->pPars = pPars; + p->pManAig = pManAig; + p->nSizeAlloc = Aig_ManObjNumMax( pManAig ); + p->nFramesAll = pPars->nFramesK + 1; + // allocate storage for sim pattern + p->nPatWords = Aig_BitWordNum( (Aig_ManPiNum(pManAig) - Aig_ManRegNum(pManAig)) * p->nFramesAll + Aig_ManRegNum(pManAig) ); + p->pPatWords = ALLOC( unsigned, p->nPatWords ); + p->vPiVars = Vec_PtrAlloc( 100 ); + // equivalence classes + p->pCla = Fra_ClassesStart( pManAig ); + // allocate other members + p->pMemFraig = ALLOC( Aig_Obj_t *, p->nSizeAlloc * p->nFramesAll ); + memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll ); + // set random number generator + srand( 0xABCABC ); + // set the pointer to the manager + Aig_ManForEachObj( p->pManAig, pObj, i ) + pObj->pData = p; + return p; +} + +/**Function************************************************************* + + Synopsis [Starts the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ManClean( Fra_Man_t * p, int nNodesMax ) +{ + int i; + // remove old arrays + for ( i = 0; i < p->nMemAlloc; i++ ) + if ( p->pMemFanins[i] && p->pMemFanins[i] != (void *)1 ) + Vec_PtrFree( p->pMemFanins[i] ); + // realloc for the new size + if ( p->nMemAlloc < nNodesMax ) + { + int nMemAllocNew = nNodesMax + 5000; + p->pMemFanins = REALLOC( Vec_Ptr_t *, p->pMemFanins, nMemAllocNew ); + p->pMemSatNums = REALLOC( int, p->pMemSatNums, nMemAllocNew ); + p->nMemAlloc = nMemAllocNew; + } + // prepare for the new run + memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc ); + memset( p->pMemSatNums, 0, sizeof(int) * p->nMemAlloc ); +} + +/**Function************************************************************* + + Synopsis [Prepares the new manager to begin fraiging.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Fra_ManPrepareComb( Fra_Man_t * p ) +{ + Aig_Man_t * pManFraig; + Aig_Obj_t * pObj; + int i; + assert( p->pManFraig == NULL ); + // start the fraig package + pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pManAig) ); + pManFraig->pName = Aig_UtilStrsav( p->pManAig->pName ); + pManFraig->nRegs = p->pManAig->nRegs; + pManFraig->nAsserts = p->pManAig->nAsserts; + // set the pointers to the available fraig nodes + Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), 0, Aig_ManConst1(pManFraig) ); + Aig_ManForEachPi( p->pManAig, pObj, i ) + Fra_ObjSetFraig( pObj, 0, Aig_ObjCreatePi(pManFraig) ); + // set the pointers to the manager + Aig_ManForEachObj( pManFraig, pObj, i ) + pObj->pData = p; + // allocate memory for mapping FRAIG nodes into SAT numbers and fanins + p->nMemAlloc = p->nSizeAlloc; + p->pMemFanins = ALLOC( Vec_Ptr_t *, p->nMemAlloc ); + memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc ); + p->pMemSatNums = ALLOC( int, p->nMemAlloc ); + memset( p->pMemSatNums, 0, sizeof(int) * p->nMemAlloc ); + // make sure the satisfying assignment is node assigned + assert( pManFraig->pData == NULL ); + return pManFraig; +} + +/**Function************************************************************* + + Synopsis [Finalizes the combinational miter after fraiging.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ManFinalizeComb( Fra_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + // add the POs + Aig_ManForEachPo( p->pManAig, pObj, i ) + Aig_ObjCreatePo( p->pManFraig, Fra_ObjChild0Fra(pObj,0) ); + // postprocess + Aig_ManCleanMarkB( p->pManFraig ); +} + + +/**Function************************************************************* + + Synopsis [Stops the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ManStop( Fra_Man_t * p ) +{ + if ( p->pPars->fVerbose ) + Fra_ManPrint( p ); + // save mapping from original nodes into FRAIG nodes + if ( p->pManAig ) + { + if ( p->pManAig->pObjCopies ) + free( p->pManAig->pObjCopies ); + p->pManAig->pObjCopies = p->pMemFraig; + p->pMemFraig = NULL; + } + Fra_ManClean( p, 0 ); + if ( p->vTimeouts ) Vec_PtrFree( p->vTimeouts ); + if ( p->vPiVars ) Vec_PtrFree( p->vPiVars ); + if ( p->pSat ) sat_solver_delete( p->pSat ); + if ( p->pCla ) Fra_ClassesStop( p->pCla ); + if ( p->pSml ) Fra_SmlStop( p->pSml ); + if ( p->vCex ) Vec_IntFree( p->vCex ); + FREE( p->pMemFraig ); + FREE( p->pMemFanins ); + FREE( p->pMemSatNums ); + FREE( p->pPatWords ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Prints stats for the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ManPrint( Fra_Man_t * p ) +{ + double nMemory = 1.0*Aig_ManObjNumMax(p->pManAig)*(p->pSml->nWordsTotal*sizeof(unsigned)+6*sizeof(void*))/(1<<20); + printf( "SimWord = %d. Round = %d. Mem = %0.2f Mb. LitBeg = %d. LitEnd = %d. (%6.2f %%).\n", + p->pPars->nSimWords, p->pSml->nSimRounds, nMemory, p->nLitsBeg, p->nLitsEnd, 100.0*p->nLitsEnd/(p->nLitsBeg?p->nLitsBeg:1) ); + printf( "Proof = %d. Cex = %d. Fail = %d. FailReal = %d. C-lim = %d. ImpRatio = %6.2f %%\n", + p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->pPars->nBTLimitNode, Fra_ImpComputeStateSpaceRatio(p) ); + printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", + p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/(p->nNodesBeg?p->nNodesBeg:1), + p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/(p->nRegsBeg?p->nRegsBeg:1) ); + if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat ); + PRT( "AIG simulation ", p->pSml->timeSim ); + PRT( "AIG traversal ", p->timeTrav ); + if ( p->timeRwr ) + { + PRT( "AIG rewriting ", p->timeRwr ); + } + PRT( "SAT solving ", p->timeSat ); + PRT( " Unsat ", p->timeSatUnsat ); + PRT( " Sat ", p->timeSatSat ); + PRT( " Fail ", p->timeSatFail ); + PRT( "Class refining ", p->timeRef ); + PRT( "TOTAL RUNTIME ", p->timeTotal ); + if ( p->time1 ) { PRT( "time1 ", p->time1 ); } + if ( p->nSpeculs ) + printf( "Speculations = %d.\n", p->nSpeculs ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraPart.c b/abc70930/src/aig/fra/fraPart.c new file mode 100644 index 00000000..691b2b3d --- /dev/null +++ b/abc70930/src/aig/fra/fraPart.c @@ -0,0 +1,263 @@ +/**CFile**************************************************************** + + FileName [fraPart.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [Partitioning for induction.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraPart.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ManPartitionTest( Aig_Man_t * p, int nComLim ) +{ + Bar_Progress_t * pProgress; + Vec_Vec_t * vSupps, * vSuppsIn; + Vec_Ptr_t * vSuppsNew; + Vec_Int_t * vSupNew, * vSup, * vSup2, * vTemp;//, * vSupIn; + Vec_Int_t * vOverNew, * vQuantNew; + Aig_Obj_t * pObj; + int i, k, nCommon, CountOver, CountQuant; + int nTotalSupp, nTotalSupp2, Entry, Largest;//, iVar; + double Ratio, R; + int clk; + + nTotalSupp = 0; + nTotalSupp2 = 0; + Ratio = 0.0; + + // compute supports +clk = clock(); + vSupps = (Vec_Vec_t *)Aig_ManSupports( p ); +PRT( "Supports", clock() - clk ); + // remove last entry + Aig_ManForEachPo( p, pObj, i ) + { + vSup = Vec_VecEntry( vSupps, i ); + Vec_IntPop( vSup ); + // remember support +// pObj->pNext = (Aig_Obj_t *)vSup; + } + + // create reverse supports +clk = clock(); + vSuppsIn = Vec_VecStart( Aig_ManPiNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + { + vSup = Vec_VecEntry( vSupps, i ); + Vec_IntForEachEntry( vSup, Entry, k ) + Vec_VecPush( vSuppsIn, Entry, (void *)i ); + } +PRT( "Inverse ", clock() - clk ); + +clk = clock(); + // compute extended supports + Largest = 0; + vSuppsNew = Vec_PtrAlloc( Aig_ManPoNum(p) ); + vOverNew = Vec_IntAlloc( Aig_ManPoNum(p) ); + vQuantNew = Vec_IntAlloc( Aig_ManPoNum(p) ); + pProgress = Bar_ProgressStart( stdout, Aig_ManPoNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + { + Bar_ProgressUpdate( pProgress, i, NULL ); + // get old supports + vSup = Vec_VecEntry( vSupps, i ); + if ( Vec_IntSize(vSup) < 2 ) + continue; + // compute new supports + CountOver = CountQuant = 0; + vSupNew = Vec_IntDup( vSup ); + // go through the nodes where the first var appears + Aig_ManForEachPo( p, pObj, k ) +// iVar = Vec_IntEntry( vSup, 0 ); +// vSupIn = Vec_VecEntry( vSuppsIn, iVar ); +// Vec_IntForEachEntry( vSupIn, Entry, k ) + { +// pObj = Aig_ManObj( p, Entry ); + // get support of this output +// vSup2 = (Vec_Int_t *)pObj->pNext; + vSup2 = Vec_VecEntry( vSupps, k ); + // count the number of common vars + nCommon = Vec_IntTwoCountCommon(vSup, vSup2); + if ( nCommon < 2 ) + continue; + if ( nCommon > nComLim ) + { + vSupNew = Vec_IntTwoMerge( vTemp = vSupNew, vSup2 ); + Vec_IntFree( vTemp ); + CountOver++; + } + else + CountQuant++; + } + // save the results + Vec_PtrPush( vSuppsNew, vSupNew ); + Vec_IntPush( vOverNew, CountOver ); + Vec_IntPush( vQuantNew, CountQuant ); + + if ( Largest < Vec_IntSize(vSupNew) ) + Largest = Vec_IntSize(vSupNew); + + nTotalSupp += Vec_IntSize(vSup); + nTotalSupp2 += Vec_IntSize(vSupNew); + if ( Vec_IntSize(vSup) ) + R = Vec_IntSize(vSupNew) / Vec_IntSize(vSup); + else + R = 0; + Ratio += R; + + if ( R < 5.0 ) + continue; + + printf( "%6d : ", i ); + printf( "S = %5d. ", Vec_IntSize(vSup) ); + printf( "SNew = %5d. ", Vec_IntSize(vSupNew) ); + printf( "R = %7.2f. ", R ); + printf( "Over = %5d. ", CountOver ); + printf( "Quant = %5d. ", CountQuant ); + printf( "\n" ); +/* + Vec_IntForEachEntry( vSupNew, Entry, k ) + printf( "%d ", Entry ); + printf( "\n" ); +*/ + } + Bar_ProgressStop( pProgress ); +PRT( "Scanning", clock() - clk ); + + // print cumulative statistics + printf( "PIs = %6d. POs = %6d. Lim = %3d. AveS = %3d. SN = %3d. R = %4.2f Max = %5d.\n", + Aig_ManPiNum(p), Aig_ManPoNum(p), nComLim, + nTotalSupp/Aig_ManPoNum(p), nTotalSupp2/Aig_ManPoNum(p), + Ratio/Aig_ManPoNum(p), Largest ); + + Vec_VecFree( vSupps ); + Vec_VecFree( vSuppsIn ); + Vec_VecFree( (Vec_Vec_t *)vSuppsNew ); + Vec_IntFree( vOverNew ); + Vec_IntFree( vQuantNew ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_ManPartitionTest2( Aig_Man_t * p ) +{ + Vec_Vec_t * vSupps, * vSuppsIn; + Vec_Int_t * vSup, * vSup2, * vSup3; + Aig_Obj_t * pObj; + int Entry, Entry2, Entry3, Counter; + int i, k, m, n, clk; + char * pSupp; + + // compute supports +clk = clock(); + vSupps = (Vec_Vec_t *)Aig_ManSupports( p ); +PRT( "Supports", clock() - clk ); + // remove last entry + Aig_ManForEachPo( p, pObj, i ) + { + vSup = Vec_VecEntry( vSupps, i ); + Vec_IntPop( vSup ); + // remember support +// pObj->pNext = (Aig_Obj_t *)vSup; + } + + // create reverse supports +clk = clock(); + vSuppsIn = Vec_VecStart( Aig_ManPiNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + { + if ( i == p->nAsserts ) + break; + vSup = Vec_VecEntry( vSupps, i ); + Vec_IntForEachEntry( vSup, Entry, k ) + Vec_VecPush( vSuppsIn, Entry, (void *)i ); + } +PRT( "Inverse ", clock() - clk ); + + // create affective supports +clk = clock(); + pSupp = ALLOC( char, Aig_ManPiNum(p) ); + Aig_ManForEachPo( p, pObj, i ) + { + if ( i % 50 != 0 ) + continue; + vSup = Vec_VecEntry( vSupps, i ); + memset( pSupp, 0, sizeof(char) * Aig_ManPiNum(p) ); + // go through each input of this output + Vec_IntForEachEntry( vSup, Entry, k ) + { + pSupp[Entry] = 1; + vSup2 = Vec_VecEntry( vSuppsIn, Entry ); + // go though each assert of this input + Vec_IntForEachEntry( vSup2, Entry2, m ) + { + vSup3 = Vec_VecEntry( vSupps, Entry2 ); + // go through each input of this assert + Vec_IntForEachEntry( vSup3, Entry3, n ) + { + pSupp[Entry3] = 1; + } + } + } + // count the entries + Counter = 0; + for ( m = 0; m < Aig_ManPiNum(p); m++ ) + Counter += pSupp[m]; + printf( "%d(%d) ", Vec_IntSize(vSup), Counter ); + } + printf( "\n" ); +PRT( "Extension ", clock() - clk ); + + free( pSupp ); + Vec_VecFree( vSupps ); + Vec_VecFree( vSuppsIn ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraSat.c b/abc70930/src/aig/fra/fraSat.c new file mode 100644 index 00000000..11029b69 --- /dev/null +++ b/abc70930/src/aig/fra/fraSat.c @@ -0,0 +1,452 @@ +/**CFile**************************************************************** + + FileName [fraSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraSat.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "fra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Fra_SetActivityFactors( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Runs equivalence test for the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) +{ + int pLits[4], RetValue, RetValue1, nBTLimit, clk, clk2 = clock(); + int status; + + // make sure the nodes are not complemented + assert( !Aig_IsComplement(pNew) ); + assert( !Aig_IsComplement(pOld) ); + assert( pNew != pOld ); + + // if at least one of the nodes is a failed node, perform adjustments: + // if the backtrack limit is small, simply skip this node + // if the backtrack limit is > 10, take the quare root of the limit + nBTLimit = p->pPars->nBTLimitNode; + if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) ) + { + p->nSatFails++; + // fail immediately +// return -1; + if ( nBTLimit <= 10 ) + return -1; + nBTLimit = (int)pow(nBTLimit, 0.7); + } + + p->nSatCalls++; + p->nSatCallsRecent++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + { + p->pSat = sat_solver_new(); + p->nSatVars = 1; + sat_solver_setnvars( p->pSat, 1000 ); + // var 0 is reserved for const1 node - add the clause + pLits[0] = toLit( 0 ); + sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + } + + // if the nodes do not have SAT variables, allocate them + Fra_CnfNodeAddToSolver( p, pOld, pNew ); + + if ( p->pSat->qtail != p->pSat->qhead ) + { + status = sat_solver_simplify(p->pSat); + assert( status != 0 ); + assert( p->pSat->qtail == p->pSat->qhead ); + } + + // prepare variable activity + if ( p->pPars->fConeBias ) + Fra_SetActivityFactors( p, pOld, pNew ); + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 +clk = clock(); + pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 ); + pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); +//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, + (sint64)nBTLimit, (sint64)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + // continue solving the other implication + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + Fra_SmlSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += clock() - clk; + // mark the node as the failed node + if ( pOld != p->pManFraig->pConst1 ) + pOld->fMarkB = 1; + pNew->fMarkB = 1; + p->nSatFailsReal++; + return -1; + } + + // if the old node was constant 0, we already know the answer + if ( pOld == p->pManFraig->pConst1 ) + { + p->nSatProof++; + return 1; + } + + // solve under assumptions + // A = 0; B = 1 OR A = 0; B = 0 +clk = clock(); + pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 1 ); + pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, + (sint64)nBTLimit, (sint64)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + Fra_SmlSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += clock() - clk; + // mark the node as the failed node + pOld->fMarkB = 1; + pNew->fMarkB = 1; + p->nSatFailsReal++; + return -1; + } +/* + // check BDD proof + { + int RetVal; + PRT( "Sat", clock() - clk2 ); + clk2 = clock(); + RetVal = Fra_NodesAreEquivBdd( pOld, pNew ); +// printf( "%d ", RetVal ); + assert( RetVal ); + PRT( "Bdd", clock() - clk2 ); + printf( "\n" ); + } +*/ + // return SAT proof + p->nSatProof++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Runs the result of test for pObj => pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_NodesAreImp( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR ) +{ + int pLits[4], RetValue, RetValue1, nBTLimit, clk, clk2 = clock(); + int status; + + // make sure the nodes are not complemented + assert( !Aig_IsComplement(pNew) ); + assert( !Aig_IsComplement(pOld) ); + assert( pNew != pOld ); + + // if at least one of the nodes is a failed node, perform adjustments: + // if the backtrack limit is small, simply skip this node + // if the backtrack limit is > 10, take the quare root of the limit + nBTLimit = p->pPars->nBTLimitNode; +/* + if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) ) + { + p->nSatFails++; + // fail immediately +// return -1; + if ( nBTLimit <= 10 ) + return -1; + nBTLimit = (int)pow(nBTLimit, 0.7); + } +*/ + p->nSatCalls++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + { + p->pSat = sat_solver_new(); + p->nSatVars = 1; + sat_solver_setnvars( p->pSat, 1000 ); + // var 0 is reserved for const1 node - add the clause + pLits[0] = toLit( 0 ); + sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + } + + // if the nodes do not have SAT variables, allocate them + Fra_CnfNodeAddToSolver( p, pOld, pNew ); + + if ( p->pSat->qtail != p->pSat->qhead ) + { + status = sat_solver_simplify(p->pSat); + assert( status != 0 ); + assert( p->pSat->qtail == p->pSat->qhead ); + } + + // prepare variable activity + if ( p->pPars->fConeBias ) + Fra_SetActivityFactors( p, pOld, pNew ); + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 +clk = clock(); +// pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 ); +// pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); + pLits[0] = toLitCond( Fra_ObjSatNum(pOld), fComplL ); + pLits[1] = toLitCond( Fra_ObjSatNum(pNew), !fComplR ); +//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, + (sint64)nBTLimit, (sint64)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + // continue solving the other implication + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + Fra_SmlSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += clock() - clk; + // mark the node as the failed node + if ( pOld != p->pManFraig->pConst1 ) + pOld->fMarkB = 1; + pNew->fMarkB = 1; + p->nSatFailsReal++; + return -1; + } + // return SAT proof + p->nSatProof++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Runs equivalence test for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew ) +{ + int pLits[2], RetValue1, RetValue, clk; + + // make sure the nodes are not complemented + assert( !Aig_IsComplement(pNew) ); + assert( pNew != p->pManFraig->pConst1 ); + p->nSatCalls++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + { + p->pSat = sat_solver_new(); + p->nSatVars = 1; + sat_solver_setnvars( p->pSat, 1000 ); + // var 0 is reserved for const1 node - add the clause + pLits[0] = toLit( 0 ); + sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + } + + // if the nodes do not have SAT variables, allocate them + Fra_CnfNodeAddToSolver( p, NULL, pNew ); + + // prepare variable activity + if ( p->pPars->fConeBias ) + Fra_SetActivityFactors( p, NULL, pNew ); + + // solve under assumptions +clk = clock(); + pLits[0] = toLitCond( Fra_ObjSatNum(pNew), pNew->fPhase ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, + (sint64)p->pPars->nBTLimitMiter, (sint64)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + assert( RetValue ); + // continue solving the other implication + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + if ( p->pPatWords ) + Fra_SmlSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += clock() - clk; + // mark the node as the failed node + pNew->fMarkB = 1; + p->nSatFailsReal++; + return -1; + } + + // return SAT proof + p->nSatProof++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Sets variable activities in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_SetActivityFactors_rec( Fra_Man_t * p, Aig_Obj_t * pObj, int LevelMin, int LevelMax ) +{ + Vec_Ptr_t * vFanins; + Aig_Obj_t * pFanin; + int i, Counter = 0; + assert( !Aig_IsComplement(pObj) ); + assert( Fra_ObjSatNum(pObj) ); + // skip visited variables + if ( Aig_ObjIsTravIdCurrent(p->pManFraig, pObj) ) + return 0; + Aig_ObjSetTravIdCurrent(p->pManFraig, pObj); + // add the PI to the list + if ( pObj->Level <= (unsigned)LevelMin || Aig_ObjIsPi(pObj) ) + return 0; + // set the factor of this variable + // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pPars->dActConeBumpMax / ThisBump + p->pSat->factors[Fra_ObjSatNum(pObj)] = p->pPars->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin); + veci_push(&p->pSat->act_vars, Fra_ObjSatNum(pObj)); + // explore the fanins + vFanins = Fra_ObjFaninVec( pObj ); + Vec_PtrForEachEntry( vFanins, pFanin, i ) + Counter += Fra_SetActivityFactors_rec( p, Aig_Regular(pFanin), LevelMin, LevelMax ); + return 1 + Counter; +} + +/**Function************************************************************* + + Synopsis [Sets variable activities in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_SetActivityFactors( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) +{ + int clk, LevelMin, LevelMax; + assert( pOld || pNew ); +clk = clock(); + // reset the active variables + veci_resize(&p->pSat->act_vars, 0); + // prepare for traversal + Aig_ManIncrementTravId( p->pManFraig ); + // determine the min and max level to visit + assert( p->pPars->dActConeRatio > 0 && p->pPars->dActConeRatio < 1 ); + LevelMax = AIG_MAX( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) ); + LevelMin = (int)(LevelMax * (1.0 - p->pPars->dActConeRatio)); + // traverse + if ( pOld && !Aig_ObjIsConst1(pOld) ) + Fra_SetActivityFactors_rec( p, pOld, LevelMin, LevelMax ); + if ( pNew && !Aig_ObjIsConst1(pNew) ) + Fra_SetActivityFactors_rec( p, pNew, LevelMin, LevelMax ); +//Fra_PrintActivity( p ); +p->timeTrav += clock() - clk; + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraSec.c b/abc70930/src/aig/fra/fraSec.c new file mode 100644 index 00000000..eaa97709 --- /dev/null +++ b/abc70930/src/aig/fra/fraSec.c @@ -0,0 +1,283 @@ +/**CFile**************************************************************** + + FileName [fraSec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [Performs SEC based on seq sweeping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraSec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" +#include "ioa.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_FraigSec2( Aig_Man_t * p, int nFramesFix, int fVerbose, int fVeryVerbose ) +{ + Aig_Man_t * pNew; + int nFrames, RetValue, nIter, clk, clkTotal = clock(); + int fLatchCorr = 0; + if ( nFramesFix ) + { + nFrames = nFramesFix; + // perform seq sweeping for one frame number + pNew = Fra_FraigInduction( p, 0, nFrames, 0, 0, 0, fLatchCorr, 0, fVeryVerbose, &nIter ); + } + else + { + // perform seq sweeping while increasing the number of frames + for ( nFrames = 1; ; nFrames++ ) + { +clk = clock(); + pNew = Fra_FraigInduction( p, 0, nFrames, 0, 0, 0, fLatchCorr, 0, fVeryVerbose, &nIter ); + RetValue = Fra_FraigMiterStatus( pNew ); + if ( fVerbose ) + { + printf( "FRAMES %3d : Iters = %3d. ", nFrames, nIter ); + if ( RetValue == 1 ) + printf( "UNSAT " ); + else + printf( "UNDECIDED " ); +PRT( "Time", clock() - clk ); + } + if ( RetValue != -1 ) + break; + Aig_ManStop( pNew ); + } + } + + // get the miter status + RetValue = Fra_FraigMiterStatus( pNew ); + Aig_ManStop( pNew ); + + // report the miter + if ( RetValue == 1 ) + printf( "Networks are equivalent after seq sweeping with K=%d frames (%d iters). ", nFrames, nIter ); + else if ( RetValue == 0 ) + printf( "Networks are NOT EQUIVALENT. " ); + else + printf( "Networks are UNDECIDED after seq sweeping with K=%d frames (%d iters). ", nFrames, nIter ); +PRT( "Time", clock() - clkTotal ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_FraigSec( Aig_Man_t * p, int nFramesMax, int fRetimeFirst, int fVerbose, int fVeryVerbose ) +{ + Fra_Sml_t * pSml; + Aig_Man_t * pNew, * pTemp; + int nFrames, RetValue, nIter, clk, clkTotal = clock(); + int fLatchCorr = 0; + + pNew = Aig_ManDup( p, 1 ); + if ( fVerbose ) + { + printf( "Original miter: Latches = %5d. Nodes = %6d.\n", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); + } +//Aig_ManDumpBlif( pNew, "after.blif" ); + + // perform sequential cleanup +clk = clock(); + if ( pNew->nRegs ) + pNew = Aig_ManReduceLaches( pNew, 0 ); + if ( pNew->nRegs ) + pNew = Aig_ManConstReduce( pNew, 0 ); + if ( fVerbose ) + { + printf( "Sequential cleanup: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +PRT( "Time", clock() - clk ); + } + + // perform forward retiming + if ( fRetimeFirst && pNew->nRegs ) + { +clk = clock(); + pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) + { + printf( "Forward retiming: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +PRT( "Time", clock() - clk ); + } + } + + // run latch correspondence +clk = clock(); + if ( pNew->nRegs ) + { + pNew = Aig_ManDup( pTemp = pNew, 1 ); + Aig_ManStop( pTemp ); + pNew = Fra_FraigLatchCorrespondence( pTemp = pNew, 0, 100000, 1, fVeryVerbose, &nIter ); + Aig_ManStop( pTemp ); + if ( pNew == NULL ) + { + RetValue = 0; + printf( "Networks are NOT EQUIVALENT after simulation. " ); +PRT( "Time", clock() - clkTotal ); + return RetValue; + } + + if ( fVerbose ) + { + printf( "Latch-corr (I=%3d): Latches = %5d. Nodes = %6d. ", + nIter, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +PRT( "Time", clock() - clk ); + } + } + + // perform fraiging +clk = clock(); + pNew = Fra_FraigEquivence( pTemp = pNew, 100 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) + { + printf( "Fraiging: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +PRT( "Time", clock() - clk ); + } + + // perform seq sweeping while increasing the number of frames + RetValue = Fra_FraigMiterStatus( pNew ); + if ( RetValue == -1 ) + for ( nFrames = 1; nFrames <= nFramesMax; nFrames *= 2 ) + { +clk = clock(); + pNew = Fra_FraigInduction( pTemp = pNew, 0, nFrames, 0, 0, 0, fLatchCorr, 0, fVeryVerbose, &nIter ); + Aig_ManStop( pTemp ); + RetValue = Fra_FraigMiterStatus( pNew ); + if ( fVerbose ) + { + printf( "K-step (K=%2d,I=%3d): Latches = %5d. Nodes = %6d. ", + nFrames, nIter, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +PRT( "Time", clock() - clk ); + } + if ( RetValue != -1 ) + break; + + // perform rewriting +clk = clock(); + pNew = Aig_ManDup( pTemp = pNew, 1 ); + Aig_ManStop( pTemp ); + pNew = Dar_ManRewriteDefault( pNew ); + if ( fVerbose ) + { + printf( "Rewriting: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +PRT( "Time", clock() - clk ); + } + + // perform retiming + if ( pNew->nRegs ) + { +clk = clock(); + pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); + Aig_ManStop( pTemp ); + pNew = Aig_ManDup( pTemp = pNew, 1 ); + Aig_ManStop( pTemp ); + if ( fVerbose ) + { + printf( "Forward retiming: Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +PRT( "Time", clock() - clk ); + } + } + + if ( pNew->nRegs ) + pNew = Aig_ManConstReduce( pNew, 0 ); + + // perform sequential simulation +clk = clock(); + pSml = Fra_SmlSimulateSeq( pNew, 0, 128 * nFrames, 1 + 16/(1+Aig_ManNodeNum(pNew)/1000) ); + if ( fVerbose ) + { + printf( "Seq simulation : Latches = %5d. Nodes = %6d. ", + Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); +PRT( "Time", clock() - clk ); + } + if ( pSml->fNonConstOut ) + { + Fra_SmlStop( pSml ); + Aig_ManStop( pNew ); + RetValue = 0; + printf( "Networks are NOT EQUIVALENT after simulation. " ); +PRT( "Time", clock() - clkTotal ); + return RetValue; + } + Fra_SmlStop( pSml ); + } + + // get the miter status + RetValue = Fra_FraigMiterStatus( pNew ); + + // report the miter + if ( RetValue == 1 ) + { + printf( "Networks are equivalent. " ); +PRT( "Time", clock() - clkTotal ); + } + else if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT. " ); +PRT( "Time", clock() - clkTotal ); + } + else + { + static int Counter = 1; + char pFileName[1000]; + printf( "Networks are UNDECIDED. " ); +PRT( "Time", clock() - clkTotal ); + sprintf( pFileName, "sm%03d.aig", Counter++ ); + Ioa_WriteAiger( pNew, pFileName, 0 ); + printf( "The unsolved reduced miter is written into file \"%s\".\n", pFileName ); + } + Aig_ManStop( pNew ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fraSim.c b/abc70930/src/aig/fra/fraSim.c new file mode 100644 index 00000000..b77c775a --- /dev/null +++ b/abc70930/src/aig/fra/fraSim.c @@ -0,0 +1,823 @@ +/**CFile**************************************************************** + + FileName [fraSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fraSim.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_SmlNodeHash( Aig_Obj_t * pObj, int nTableSize ) +{ + Fra_Man_t * p = pObj->pData; + static int s_FPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + unsigned * pSims; + unsigned uHash; + int i; +// assert( p->pSml->nWordsTotal <= 128 ); + uHash = 0; + pSims = Fra_ObjSim(p->pSml, pObj->Id); + for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ ) + uHash ^= pSims[i] * s_FPrimes[i & 0x7F]; + return uHash % nTableSize; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_SmlNodeIsConst( Aig_Obj_t * pObj ) +{ + Fra_Man_t * p = pObj->pData; + unsigned * pSims; + int i; + pSims = Fra_ObjSim(p->pSml, pObj->Id); + for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ ) + if ( pSims[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation infos are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_SmlNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + Fra_Man_t * p = pObj0->pData; + unsigned * pSims0, * pSims1; + int i; + pSims0 = Fra_ObjSim(p->pSml, pObj0->Id); + pSims1 = Fra_ObjSim(p->pSml, pObj1->Id); + for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ ) + if ( pSims0[i] != pSims1[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Counts the number of 1s in the XOR of simulation data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_SmlNodeNotEquWeight( Fra_Sml_t * p, int Left, int Right ) +{ + unsigned * pSimL, * pSimR; + int k, Counter = 0; + pSimL = Fra_ObjSim( p, Left ); + pSimR = Fra_ObjSim( p, Right ); + for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) + Counter += Aig_WordCountOnes( pSimL[k] ^ pSimR[k] ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_SmlNodeIsZero( Fra_Sml_t * p, Aig_Obj_t * pObj ) +{ + unsigned * pSims; + int i; + pSims = Fra_ObjSim(p, pObj->Id); + for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) + if ( pSims[i] ) + return 0; + return 1; +} + + + +/**Function************************************************************* + + Synopsis [Generated const 0 pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlSavePattern0( Fra_Man_t * p, int fInit ) +{ + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); +} + +/**Function************************************************************* + + Synopsis [[Generated const 1 pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlSavePattern1( Fra_Man_t * p, int fInit ) +{ + Aig_Obj_t * pObj; + int i, k, nTruePis; + memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords ); + if ( !fInit ) + return; + // clear the state bits to correspond to all-0 initial state + nTruePis = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); + k = 0; + Aig_ManForEachLoSeq( p->pManAig, pObj, i ) + Aig_InfoXorBit( p->pPatWords, nTruePis * p->nFramesAll + k++ ); +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlSavePattern( Fra_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); + Aig_ManForEachPi( p->pManFraig, pObj, i ) + if ( p->pSat->model.ptr[Fra_ObjSatNum(pObj)] == l_True ) + Aig_InfoSetBit( p->pPatWords, i ); + + if ( p->vCex ) + { + Vec_IntClear( p->vCex ); + for ( i = 0; i < Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); i++ ) + Vec_IntPush( p->vCex, Aig_InfoHasBit( p->pPatWords, i ) ); + for ( i = Aig_ManPiNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); i < Aig_ManPiNum(p->pManFraig); i++ ) + Vec_IntPush( p->vCex, Aig_InfoHasBit( p->pPatWords, i ) ); + } + +/* + printf( "Pattern: " ); + Aig_ManForEachPi( p->pManFraig, pObj, i ) + printf( "%d", Aig_InfoHasBit( p->pPatWords, i ) ); + printf( "\n" ); +*/ +} + + + +/**Function************************************************************* + + Synopsis [Creates the counter-example from the successful pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlCheckOutputSavePattern( Fra_Man_t * p, Aig_Obj_t * pObj ) +{ + unsigned * pSims; + int i, k, BestPat, * pModel; + // find the word of the pattern + pSims = Fra_ObjSim(p->pSml, pObj->Id); + for ( i = 0; i < p->pSml->nWordsTotal; i++ ) + if ( pSims[i] ) + break; + assert( i < p->pSml->nWordsTotal ); + // find the bit of the pattern + for ( k = 0; k < 32; k++ ) + if ( pSims[i] & (1 << k) ) + break; + assert( k < 32 ); + // determine the best pattern + BestPat = i * 32 + k; + // fill in the counter-example data + pModel = ALLOC( int, Aig_ManPiNum(p->pManFraig) ); + Aig_ManForEachPi( p->pManAig, pObj, i ) + { + pModel[i] = Aig_InfoHasBit(Fra_ObjSim(p->pSml, pObj->Id), BestPat); +// printf( "%d", pModel[i] ); + } +// printf( "\n" ); + // set the model + assert( p->pManFraig->pData == NULL ); + p->pManFraig->pData = pModel; + return; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the one of the output is already non-constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_SmlCheckOutput( Fra_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + // make sure the reference simulation pattern does not detect the bug + pObj = Aig_ManPo( p->pManAig, 0 ); + assert( Aig_ObjFanin0(pObj)->fPhase == (unsigned)Aig_ObjFaninC0(pObj) ); + Aig_ManForEachPo( p->pManAig, pObj, i ) + { + if ( !Fra_SmlNodeIsConst( Aig_ObjFanin0(pObj) ) ) + { + // create the counter-example from this pattern + Fra_SmlCheckOutputSavePattern( p, Aig_ObjFanin0(pObj) ); + return 1; + } + } + return 0; +} + + + +/**Function************************************************************* + + Synopsis [Assigns random patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlAssignRandom( Fra_Sml_t * p, Aig_Obj_t * pObj ) +{ + unsigned * pSims; + int i; + assert( Aig_ObjIsPi(pObj) ); + pSims = Fra_ObjSim( p, pObj->Id ); + for ( i = 0; i < p->nWordsTotal; i++ ) + pSims[i] = Fra_ObjRandomSim(); +} + +/**Function************************************************************* + + Synopsis [Assigns constant patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlAssignConst( Fra_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ) +{ + unsigned * pSims; + int i; + assert( Aig_ObjIsPi(pObj) ); + pSims = Fra_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = fConst1? ~(unsigned)0 : 0; +} + +/**Function************************************************************* + + Synopsis [Assings random simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlInitialize( Fra_Sml_t * p, int fInit ) +{ + Aig_Obj_t * pObj; + int i; + if ( fInit ) + { + assert( Aig_ManRegNum(p->pAig) > 0 ); + assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) ); + // assign random info for primary inputs + Aig_ManForEachPiSeq( p->pAig, pObj, i ) + Fra_SmlAssignRandom( p, pObj ); + // assign the initial state for the latches + Aig_ManForEachLoSeq( p->pAig, pObj, i ) + Fra_SmlAssignConst( p, pObj, 0, 0 ); + } + else + { + Aig_ManForEachPi( p->pAig, pObj, i ) + Fra_SmlAssignRandom( p, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Assings distance-1 simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlAssignDist1( Fra_Sml_t * p, unsigned * pPat ) +{ + Aig_Obj_t * pObj; + int f, i, k, Limit, nTruePis; + assert( p->nFrames > 0 ); + if ( p->nFrames == 1 ) + { + // copy the PI info + Aig_ManForEachPi( p->pAig, pObj, i ) + Fra_SmlAssignConst( p, pObj, Aig_InfoHasBit(pPat, i), 0 ); + // flip one bit + Limit = AIG_MIN( Aig_ManPiNum(p->pAig), p->nWordsTotal * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Aig_InfoXorBit( Fra_ObjSim( p, Aig_ManPi(p->pAig,i)->Id ), i+1 ); + } + else + { + int fUseDist1 = 0; + + // copy the PI info for each frame + nTruePis = Aig_ManPiNum(p->pAig) - Aig_ManRegNum(p->pAig); + for ( f = 0; f < p->nFrames; f++ ) + Aig_ManForEachPiSeq( p->pAig, pObj, i ) + Fra_SmlAssignConst( p, pObj, Aig_InfoHasBit(pPat, nTruePis * f + i), f ); + // copy the latch info + k = 0; + Aig_ManForEachLoSeq( p->pAig, pObj, i ) + Fra_SmlAssignConst( p, pObj, Aig_InfoHasBit(pPat, nTruePis * p->nFrames + k++), 0 ); +// assert( p->pManFraig == NULL || nTruePis * p->nFrames + k == Aig_ManPiNum(p->pManFraig) ); + + // flip one bit of the last frame + if ( fUseDist1 ) //&& p->nFrames == 2 ) + { + Limit = AIG_MIN( nTruePis, p->nWordsFrame * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Aig_InfoXorBit( Fra_ObjSim( p, Aig_ManPi(p->pAig, i)->Id ) + p->nWordsFrame*(p->nFrames-1), i+1 ); + } + } +} + + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlNodeSimulate( Fra_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) +{ + unsigned * pSims, * pSims0, * pSims1; + int fCompl, fCompl0, fCompl1, i; + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsNode(pObj) ); + assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); + // get hold of the simulation information + pSims = Fra_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; + pSims0 = Fra_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame; + pSims1 = Fra_ObjSim(p, Aig_ObjFanin1(pObj)->Id) + p->nWordsFrame * iFrame; + // get complemented attributes of the children using their random info + fCompl = pObj->fPhase; + fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj)); + fCompl1 = Aig_ObjPhaseReal(Aig_ObjChild1(pObj)); + // simulate + if ( fCompl0 && fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = (pSims0[i] | pSims1[i]); + else + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = ~(pSims0[i] | pSims1[i]); + } + else if ( fCompl0 && !fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = (pSims0[i] | ~pSims1[i]); + else + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = (~pSims0[i] & pSims1[i]); + } + else if ( !fCompl0 && fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = (~pSims0[i] | pSims1[i]); + else + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = (pSims0[i] & ~pSims1[i]); + } + else // if ( !fCompl0 && !fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = ~(pSims0[i] & pSims1[i]); + else + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = (pSims0[i] & pSims1[i]); + } +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlNodeCopyFanin( Fra_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) +{ + unsigned * pSims, * pSims0; + int fCompl, fCompl0, i; + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsPo(pObj) ); + assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); + // get hold of the simulation information + pSims = Fra_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; + pSims0 = Fra_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame; + // get complemented attributes of the children using their random info + fCompl = pObj->fPhase; + fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj)); + // copy information as it is + if ( fCompl0 ) + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = ~pSims0[i]; + else + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims[i] = pSims0[i]; +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlNodeTransferNext( Fra_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn, int iFrame ) +{ + unsigned * pSims0, * pSims1; + int i; + assert( !Aig_IsComplement(pOut) ); + assert( !Aig_IsComplement(pIn) ); + assert( Aig_ObjIsPo(pOut) ); + assert( Aig_ObjIsPi(pIn) ); + assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); + // get hold of the simulation information + pSims0 = Fra_ObjSim(p, pOut->Id) + p->nWordsFrame * iFrame; + pSims1 = Fra_ObjSim(p, pIn->Id) + p->nWordsFrame * (iFrame+1); + // copy information as it is + for ( i = 0; i < p->nWordsFrame; i++ ) + pSims1[i] = pSims0[i]; +} + + +/**Function************************************************************* + + Synopsis [Check if any of the POs becomes non-constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fra_SmlCheckNonConstOutputs( Fra_Sml_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachPoSeq( p->pAig, pObj, i ) + if ( !Fra_SmlNodeIsZero(p, pObj) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Simulates AIG manager.] + + Description [Assumes that the PI simulation info is attached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlSimulateOne( Fra_Sml_t * p ) +{ + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int f, i, clk; +clk = clock(); + for ( f = 0; f < p->nFrames; f++ ) + { + // simulate the nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + Fra_SmlNodeSimulate( p, pObj, f ); + // copy simulation info into outputs + Aig_ManForEachPoSeq( p->pAig, pObj, i ) + Fra_SmlNodeCopyFanin( p, pObj, f ); + // quit if this is the last timeframe + if ( f == p->nFrames - 1 ) + break; + // copy simulation info into outputs + Aig_ManForEachLiSeq( p->pAig, pObj, i ) + Fra_SmlNodeCopyFanin( p, pObj, f ); + // copy simulation info into the inputs + Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) + Fra_SmlNodeTransferNext( p, pObjLi, pObjLo, f ); + } +p->timeSim += clock() - clk; +p->nSimRounds++; +} + + +/**Function************************************************************* + + Synopsis [Resimulates fraiging manager after finding a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlResimulate( Fra_Man_t * p ) +{ + int nChanges, clk; + Fra_SmlAssignDist1( p->pSml, p->pPatWords ); + Fra_SmlSimulateOne( p->pSml ); +// if ( p->pPars->fPatScores ) +// Fra_CleanPatScores( p ); + if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) + return; +clk = clock(); + nChanges = Fra_ClassesRefine( p->pCla ); + nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); + if ( p->pCla->vImps ) + nChanges += Fra_ImpRefineUsingCex( p, p->pCla->vImps ); +p->timeRef += clock() - clk; + if ( !p->pPars->nFramesK && nChanges < 1 ) + printf( "Error: A counter-example did not refine classes!\n" ); +// assert( nChanges >= 1 ); +//printf( "Refined classes = %5d. Changes = %4d.\n", Vec_PtrSize(p->vClasses), nChanges ); +} + +/**Function************************************************************* + + Synopsis [Performs simulation of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlSimulate( Fra_Man_t * p, int fInit ) +{ + int fVerbose = 0; + int nChanges, nClasses, clk; + assert( !fInit || Aig_ManRegNum(p->pManAig) ); + // start the classes + Fra_SmlInitialize( p->pSml, fInit ); + Fra_SmlSimulateOne( p->pSml ); + Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr ); +// Fra_ClassesPrint( p->pCla, 0 ); +if ( fVerbose ) +printf( "Starting classes = %5d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); + +//return; + + // refine classes by walking 0/1 patterns + Fra_SmlSavePattern0( p, fInit ); + Fra_SmlAssignDist1( p->pSml, p->pPatWords ); + Fra_SmlSimulateOne( p->pSml ); + if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) + return; +clk = clock(); + nChanges = Fra_ClassesRefine( p->pCla ); + nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); +p->timeRef += clock() - clk; +if ( fVerbose ) +printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) ); + Fra_SmlSavePattern1( p, fInit ); + Fra_SmlAssignDist1( p->pSml, p->pPatWords ); + Fra_SmlSimulateOne( p->pSml ); + if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) + return; +clk = clock(); + nChanges = Fra_ClassesRefine( p->pCla ); + nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); +p->timeRef += clock() - clk; + +if ( fVerbose ) +printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) ); + // refine classes by random simulation + do { + Fra_SmlInitialize( p->pSml, fInit ); + Fra_SmlSimulateOne( p->pSml ); + nClasses = Vec_PtrSize(p->pCla->vClasses); + if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) + return; +clk = clock(); + nChanges = Fra_ClassesRefine( p->pCla ); + nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); +p->timeRef += clock() - clk; +if ( fVerbose ) +printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) ); + } while ( (double)nChanges / nClasses > p->pPars->dSimSatur ); + +// if ( p->pPars->fVerbose ) +// printf( "Consts = %6d. Classes = %6d. Literals = %6d.\n", +// Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); +// Fra_ClassesPrint( p->pCla, 0 ); +} + + +/**Function************************************************************* + + Synopsis [Allocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Sml_t * Fra_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ) +{ + Fra_Sml_t * p; + p = (Fra_Sml_t *)malloc( sizeof(Fra_Sml_t) + sizeof(unsigned) * Aig_ManObjNumMax(pAig) * (nPref + nFrames) * nWordsFrame ); + memset( p, 0, sizeof(Fra_Sml_t) + sizeof(unsigned) * (nPref + nFrames) * nWordsFrame ); + p->pAig = pAig; + p->nPref = nPref; + p->nFrames = nPref + nFrames; + p->nWordsFrame = nWordsFrame; + p->nWordsTotal = (nPref + nFrames) * nWordsFrame; + p->nWordsPref = nPref * nWordsFrame; + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fra_SmlStop( Fra_Sml_t * p ) +{ + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Performs simulation of the uninitialized circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Sml_t * Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords ) +{ + Fra_Sml_t * p; + p = Fra_SmlStart( pAig, 0, 1, nWords ); + Fra_SmlInitialize( p, 0 ); + Fra_SmlSimulateOne( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [Performs simulation of the initialized circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fra_Sml_t * Fra_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ) +{ + Fra_Sml_t * p; + p = Fra_SmlStart( pAig, nPref, nFrames, nWords ); + Fra_SmlInitialize( p, 1 ); + Fra_SmlSimulateOne( p ); + p->fNonConstOut = Fra_SmlCheckNonConstOutputs( p ); + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/fra_.c b/abc70930/src/aig/fra/fra_.c new file mode 100644 index 00000000..2b601587 --- /dev/null +++ b/abc70930/src/aig/fra/fra_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [fra_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [New FRAIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 30, 2007.] + + Revision [$Id: fra_.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/fra/module.make b/abc70930/src/aig/fra/module.make new file mode 100644 index 00000000..e7264fdc --- /dev/null +++ b/abc70930/src/aig/fra/module.make @@ -0,0 +1,12 @@ +SRC += src/aig/fra/fraBmc.c \ + src/aig/fra/fraCec.c \ + src/aig/fra/fraClass.c \ + src/aig/fra/fraCnf.c \ + src/aig/fra/fraCore.c \ + src/aig/fra/fraImp.c \ + src/aig/fra/fraInd.c \ + src/aig/fra/fraLcr.c \ + src/aig/fra/fraMan.c \ + src/aig/fra/fraSat.c \ + src/aig/fra/fraSec.c \ + src/aig/fra/fraSim.c diff --git a/abc70930/src/aig/hop/cudd2.c b/abc70930/src/aig/hop/cudd2.c new file mode 100644 index 00000000..ac912663 --- /dev/null +++ b/abc70930/src/aig/hop/cudd2.c @@ -0,0 +1,356 @@ +/**CFile**************************************************************** + + FileName [cudd2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Recording AIGs for the BDD operations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 3, 2006.] + + Revision [$Id: cudd2.c,v 1.00 2006/10/03 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" +#include "st.h" +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Aig_CuddMan_t_ Aig_CuddMan_t; +struct Aig_CuddMan_t_ +{ + Aig_Man_t * pAig; // internal AIG package + st_table * pTable; // hash table mapping BDD nodes into AIG nodes +}; + +// static Cudd AIG manager used in this experiment +static Aig_CuddMan_t * s_pCuddMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start AIG recording.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_Init( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ) +{ + int v; + // start the BDD-to-AIG manager when the first BDD manager is allocated + if ( s_pCuddMan != NULL ) + return; + s_pCuddMan = ALLOC( Aig_CuddMan_t, 1 ); + s_pCuddMan->pAig = Aig_ManStart(); + s_pCuddMan->pTable = st_init_table( st_ptrcmp, st_ptrhash ); + for ( v = 0; v < (int)numVars; v++ ) + Aig_ObjCreatePi( s_pCuddMan->pAig ); +} + +/**Function************************************************************* + + Synopsis [Stops AIG recording.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_Quit( void * pCudd ) +{ + assert( s_pCuddMan != NULL ); + Aig_ManDumpBlif( s_pCuddMan->pAig, "aig_temp.blif" ); + Aig_ManStop( s_pCuddMan->pAig ); + st_free_table( s_pCuddMan->pTable ); + free( s_pCuddMan ); + s_pCuddMan = NULL; +} + +/**Function************************************************************* + + Synopsis [Fetches AIG node corresponding to the BDD node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Aig_Obj_t * Cudd2_GetArg( void * pArg ) +{ + Aig_Obj_t * pNode; + assert( s_pCuddMan != NULL ); + if ( !st_lookup( s_pCuddMan->pTable, (char *)Aig_Regular(pArg), (char **)&pNode ) ) + { + printf( "Cudd2_GetArg(): An argument BDD is not in the hash table.\n" ); + return NULL; + } + return Aig_NotCond( pNode, Aig_IsComplement(pArg) ); +} + +/**Function************************************************************* + + Synopsis [Inserts the AIG node corresponding to the BDD node into the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Cudd2_SetArg( Aig_Obj_t * pNode, void * pResult ) +{ + assert( s_pCuddMan != NULL ); + if ( st_is_member( s_pCuddMan->pTable, (char *)Aig_Regular(pResult) ) ) + return; + pNode = Aig_NotCond( pNode, Aig_IsComplement(pResult) ); + st_insert( s_pCuddMan->pTable, (char *)Aig_Regular(pResult), (char *)pNode ); +} + +/**Function************************************************************* + + Synopsis [Registers constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddOne( void * pCudd, void * pResult ) +{ + Cudd2_SetArg( Aig_ManConst1(s_pCuddMan->pAig), pResult ); +} + +/**Function************************************************************* + + Synopsis [Adds elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddIthVar( void * pCudd, int iVar, void * pResult ) +{ + int v; + assert( s_pCuddMan != NULL ); + for ( v = Aig_ManPiNum(s_pCuddMan->pAig); v <= iVar; v++ ) + Aig_ObjCreatePi( s_pCuddMan->pAig ); + Cudd2_SetArg( Aig_ManPi(s_pCuddMan->pAig, iVar), pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddAnd( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_And( s_pCuddMan->pAig, pNode0, pNode1 ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddOr( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), Aig_Not(pResult) ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddNand( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddAnd( pCudd, pArg0, pArg1, Aig_Not(pResult) ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddNor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddXor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddXnor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddXor( pCudd, pArg0, pArg1, Aig_Not(pResult) ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddIte( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode2, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode2 = Cudd2_GetArg( pArg2 ); + pNode = Aig_Mux( s_pCuddMan->pAig, pNode0, pNode1, pNode2 ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_Compose( s_pCuddMan->pAig, pNode0, pNode1, v ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Should be called after each containment check.] + + Description [Result should be 1 if Cudd2_bddLeq returned 1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddLeq( void * pCudd, void * pArg0, void * pArg1, int Result ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_And( s_pCuddMan->pAig, pNode0, Aig_Not(pNode1) ); + Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); +} + +/**Function************************************************************* + + Synopsis [Should be called after each equality check.] + + Description [Result should be 1 if they are equal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddEqual( void * pCudd, void * pArg0, void * pArg1, int Result ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); + Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/hop/cudd2.h b/abc70930/src/aig/hop/cudd2.h new file mode 100644 index 00000000..69711c11 --- /dev/null +++ b/abc70930/src/aig/hop/cudd2.h @@ -0,0 +1,82 @@ +/**CFile**************************************************************** + + FileName [cudd2.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 3, 2006.] + + Revision [$Id: cudd2.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CUDD2_H__ +#define __CUDD2_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +// HA: Added for printing messages +#ifndef MSG +#define MSG(msg) (printf("%s = \n",(msg))); +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Cudd2_Init ( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ); +extern void Cudd2_Quit ( void * pCudd ); +extern void Cudd2_bddOne ( void * pCudd, void * pResult ); +extern void Cudd2_bddIthVar ( void * pCudd, int iVar, void * pResult ); +extern void Cudd2_bddAnd ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddOr ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddNand ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddNor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddXor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddXnor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddIte ( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ); +extern void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ); +extern void Cudd2_bddLeq ( void * pCudd, void * pArg0, void * pArg1, int Result ); +extern void Cudd2_bddEqual ( void * pCudd, void * pArg0, void * pArg1, int Result ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/hop/hop.h b/abc70930/src/aig/hop/hop.h new file mode 100644 index 00000000..e8e916cc --- /dev/null +++ b/abc70930/src/aig/hop/hop.h @@ -0,0 +1,347 @@ +/**CFile**************************************************************** + + FileName [hop.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hop.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __HOP_H__ +#define __HOP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Hop_Man_t_ Hop_Man_t; +typedef struct Hop_Obj_t_ Hop_Obj_t; +typedef int Hop_Edge_t; + +// object types +typedef enum { + AIG_NONE, // 0: non-existent object + AIG_CONST1, // 1: constant 1 + AIG_PI, // 2: primary input + AIG_PO, // 3: primary output + AIG_AND, // 4: AND node + AIG_EXOR, // 5: EXOR node + AIG_VOID // 6: unused object +} Hop_Type_t; + +// the AIG node +struct Hop_Obj_t_ // 6 words +{ + void * pData; // misc + Hop_Obj_t * pNext; // strashing table + Hop_Obj_t * pFanin0; // fanin + Hop_Obj_t * pFanin1; // fanin + unsigned int Type : 3; // object type + unsigned int fPhase : 1; // value under 000...0 pattern + unsigned int fMarkA : 1; // multipurpose mask + unsigned int fMarkB : 1; // multipurpose mask + unsigned int nRefs : 26; // reference count (level) + int Id; // unique ID of the node +}; + +// the AIG manager +struct Hop_Man_t_ +{ + // AIG nodes + Vec_Ptr_t * vPis; // the array of PIs + Vec_Ptr_t * vPos; // the array of POs + Vec_Ptr_t * vObjs; // the array of all nodes (optional) + Hop_Obj_t * pConst1; // the constant 1 node + Hop_Obj_t Ghost; // the ghost node + // AIG node counters + int nObjs[AIG_VOID];// the number of objects by type + int nCreated; // the number of created objects + int nDeleted; // the number of deleted objects + // stuctural hash table + Hop_Obj_t ** pTable; // structural hash table + int nTableSize; // structural hash table size + // various data members + void * pData; // the temporary data + int nTravIds; // the current traversal ID + int fRefCount; // enables reference counting + int fCatchExor; // enables EXOR nodes + // memory management + Vec_Ptr_t * vChunks; // allocated memory pieces + Vec_Ptr_t * vPages; // memory pages used by nodes + Hop_Obj_t * pListFree; // the list of free nodes + // timing statistics + int time1; + int time2; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define AIG_MIN(a,b) (((a) < (b))? (a) : (b)) +#define AIG_MAX(a,b) (((a) > (b))? (a) : (b)) + +#ifndef PRT +#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) +#endif + +static inline int Hop_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } +static inline int Hop_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline int Hop_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } +static inline void Hop_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } +static inline void Hop_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } +static inline int Hop_Base2Log( unsigned n ) { int r; assert( n >= 0 ); if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ); return r; } +static inline int Hop_Base10Log( unsigned n ) { int r; assert( n >= 0 ); if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ); return r; } + +static inline Hop_Obj_t * Hop_Regular( Hop_Obj_t * p ) { return (Hop_Obj_t *)((unsigned long)(p) & ~01); } +static inline Hop_Obj_t * Hop_Not( Hop_Obj_t * p ) { return (Hop_Obj_t *)((unsigned long)(p) ^ 01); } +static inline Hop_Obj_t * Hop_NotCond( Hop_Obj_t * p, int c ) { return (Hop_Obj_t *)((unsigned long)(p) ^ (c)); } +static inline int Hop_IsComplement( Hop_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } + +static inline Hop_Obj_t * Hop_ManConst0( Hop_Man_t * p ) { return Hop_Not(p->pConst1); } +static inline Hop_Obj_t * Hop_ManConst1( Hop_Man_t * p ) { return p->pConst1; } +static inline Hop_Obj_t * Hop_ManGhost( Hop_Man_t * p ) { return &p->Ghost; } +static inline Hop_Obj_t * Hop_ManPi( Hop_Man_t * p, int i ) { return (Hop_Obj_t *)Vec_PtrEntry(p->vPis, i); } +static inline Hop_Obj_t * Hop_ManPo( Hop_Man_t * p, int i ) { return (Hop_Obj_t *)Vec_PtrEntry(p->vPos, i); } +static inline Hop_Obj_t * Hop_ManObj( Hop_Man_t * p, int i ) { return p->vObjs ? (Hop_Obj_t *)Vec_PtrEntry(p->vObjs, i) : NULL; } + +static inline Hop_Edge_t Hop_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } +static inline int Hop_EdgeId( Hop_Edge_t Edge ) { return Edge >> 1; } +static inline int Hop_EdgeIsComplement( Hop_Edge_t Edge ) { return Edge & 1; } +static inline Hop_Edge_t Hop_EdgeRegular( Hop_Edge_t Edge ) { return (Edge >> 1) << 1; } +static inline Hop_Edge_t Hop_EdgeNot( Hop_Edge_t Edge ) { return Edge ^ 1; } +static inline Hop_Edge_t Hop_EdgeNotCond( Hop_Edge_t Edge, int fCond ) { return Edge ^ fCond; } + +static inline int Hop_ManPiNum( Hop_Man_t * p ) { return p->nObjs[AIG_PI]; } +static inline int Hop_ManPoNum( Hop_Man_t * p ) { return p->nObjs[AIG_PO]; } +static inline int Hop_ManAndNum( Hop_Man_t * p ) { return p->nObjs[AIG_AND]; } +static inline int Hop_ManExorNum( Hop_Man_t * p ) { return p->nObjs[AIG_EXOR]; } +static inline int Hop_ManNodeNum( Hop_Man_t * p ) { return p->nObjs[AIG_AND]+p->nObjs[AIG_EXOR];} +static inline int Hop_ManGetCost( Hop_Man_t * p ) { return p->nObjs[AIG_AND]+3*p->nObjs[AIG_EXOR]; } +static inline int Hop_ManObjNum( Hop_Man_t * p ) { return p->nCreated - p->nDeleted; } + +static inline Hop_Type_t Hop_ObjType( Hop_Obj_t * pObj ) { return (Hop_Type_t)pObj->Type; } +static inline int Hop_ObjIsNone( Hop_Obj_t * pObj ) { return pObj->Type == AIG_NONE; } +static inline int Hop_ObjIsConst1( Hop_Obj_t * pObj ) { assert(!Hop_IsComplement(pObj)); return pObj->Type == AIG_CONST1; } +static inline int Hop_ObjIsPi( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PI; } +static inline int Hop_ObjIsPo( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PO; } +static inline int Hop_ObjIsAnd( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND; } +static inline int Hop_ObjIsExor( Hop_Obj_t * pObj ) { return pObj->Type == AIG_EXOR; } +static inline int Hop_ObjIsNode( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } +static inline int Hop_ObjIsTerm( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PI || pObj->Type == AIG_PO || pObj->Type == AIG_CONST1; } +static inline int Hop_ObjIsHash( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } + +static inline int Hop_ObjIsMarkA( Hop_Obj_t * pObj ) { return pObj->fMarkA; } +static inline void Hop_ObjSetMarkA( Hop_Obj_t * pObj ) { pObj->fMarkA = 1; } +static inline void Hop_ObjClearMarkA( Hop_Obj_t * pObj ) { pObj->fMarkA = 0; } + +static inline void Hop_ObjSetTravId( Hop_Obj_t * pObj, int TravId ) { pObj->pData = (void *)TravId; } +static inline void Hop_ObjSetTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj ) { pObj->pData = (void *)p->nTravIds; } +static inline void Hop_ObjSetTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj ) { pObj->pData = (void *)(p->nTravIds - 1); } +static inline int Hop_ObjIsTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj ) { return (int )((int)pObj->pData == p->nTravIds); } +static inline int Hop_ObjIsTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj ) { return (int )((int)pObj->pData == p->nTravIds - 1); } + +static inline int Hop_ObjTravId( Hop_Obj_t * pObj ) { return (int)pObj->pData; } +static inline int Hop_ObjPhase( Hop_Obj_t * pObj ) { return pObj->fPhase; } +static inline int Hop_ObjRefs( Hop_Obj_t * pObj ) { return pObj->nRefs; } +static inline void Hop_ObjRef( Hop_Obj_t * pObj ) { pObj->nRefs++; } +static inline void Hop_ObjDeref( Hop_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } +static inline void Hop_ObjClearRef( Hop_Obj_t * pObj ) { pObj->nRefs = 0; } +static inline int Hop_ObjFaninC0( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj->pFanin0); } +static inline int Hop_ObjFaninC1( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj->pFanin1); } +static inline Hop_Obj_t * Hop_ObjFanin0( Hop_Obj_t * pObj ) { return Hop_Regular(pObj->pFanin0); } +static inline Hop_Obj_t * Hop_ObjFanin1( Hop_Obj_t * pObj ) { return Hop_Regular(pObj->pFanin1); } +static inline Hop_Obj_t * Hop_ObjChild0( Hop_Obj_t * pObj ) { return pObj->pFanin0; } +static inline Hop_Obj_t * Hop_ObjChild1( Hop_Obj_t * pObj ) { return pObj->pFanin1; } +static inline Hop_Obj_t * Hop_ObjChild0Copy( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin0(pObj)? Hop_NotCond((Hop_Obj_t *)Hop_ObjFanin0(pObj)->pData, Hop_ObjFaninC0(pObj)) : NULL; } +static inline Hop_Obj_t * Hop_ObjChild1Copy( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin1(pObj)? Hop_NotCond((Hop_Obj_t *)Hop_ObjFanin1(pObj)->pData, Hop_ObjFaninC1(pObj)) : NULL; } +static inline int Hop_ObjLevel( Hop_Obj_t * pObj ) { return pObj->nRefs; } +static inline int Hop_ObjLevelNew( Hop_Obj_t * pObj ) { return 1 + Hop_ObjIsExor(pObj) + AIG_MAX(Hop_ObjFanin0(pObj)->nRefs, Hop_ObjFanin1(pObj)->nRefs); } +static inline int Hop_ObjFaninPhase( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj)? !Hop_Regular(pObj)->fPhase : pObj->fPhase; } +static inline void Hop_ObjClean( Hop_Obj_t * pObj ) { memset( pObj, 0, sizeof(Hop_Obj_t) ); } +static inline int Hop_ObjWhatFanin( Hop_Obj_t * pObj, Hop_Obj_t * pFanin ) +{ + if ( Hop_ObjFanin0(pObj) == pFanin ) return 0; + if ( Hop_ObjFanin1(pObj) == pFanin ) return 1; + assert(0); return -1; +} +static inline int Hop_ObjFanoutC( Hop_Obj_t * pObj, Hop_Obj_t * pFanout ) +{ + if ( Hop_ObjFanin0(pFanout) == pObj ) return Hop_ObjFaninC0(pObj); + if ( Hop_ObjFanin1(pFanout) == pObj ) return Hop_ObjFaninC1(pObj); + assert(0); return -1; +} + +// create the ghost of the new node +static inline Hop_Obj_t * Hop_ObjCreateGhost( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ) +{ + Hop_Obj_t * pGhost; + assert( Type != AIG_AND || !Hop_ObjIsConst1(Hop_Regular(p0)) ); + assert( p1 == NULL || !Hop_ObjIsConst1(Hop_Regular(p1)) ); + assert( Type == AIG_PI || Hop_Regular(p0) != Hop_Regular(p1) ); + pGhost = Hop_ManGhost(p); + pGhost->Type = Type; + if ( Hop_Regular(p0)->Id < Hop_Regular(p1)->Id ) + { + pGhost->pFanin0 = p0; + pGhost->pFanin1 = p1; + } + else + { + pGhost->pFanin0 = p1; + pGhost->pFanin1 = p0; + } + return pGhost; +} + +// internal memory manager +static inline Hop_Obj_t * Hop_ManFetchMemory( Hop_Man_t * p ) +{ + extern void Hop_ManAddMemory( Hop_Man_t * p ); + Hop_Obj_t * pTemp; + if ( p->pListFree == NULL ) + Hop_ManAddMemory( p ); + pTemp = p->pListFree; + p->pListFree = *((Hop_Obj_t **)pTemp); + memset( pTemp, 0, sizeof(Hop_Obj_t) ); + if ( p->vObjs ) + { + assert( p->nCreated == Vec_PtrSize(p->vObjs) ); + Vec_PtrPush( p->vObjs, pTemp ); + } + pTemp->Id = p->nCreated++; + return pTemp; +} +static inline void Hop_ManRecycleMemory( Hop_Man_t * p, Hop_Obj_t * pEntry ) +{ + pEntry->Type = AIG_NONE; // distinquishes dead node from live node + *((Hop_Obj_t **)pEntry) = p->pListFree; + p->pListFree = pEntry; +} + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the primary inputs +#define Hop_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPis, pObj, i ) +// iterator over the primary outputs +#define Hop_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPos, pObj, i ) +// iterator over all objects, including those currently not used +#define Hop_ManForEachNode( p, pObj, i ) \ + for ( i = 0; i < p->nTableSize; i++ ) \ + if ( ((pObj) = p->pTable[i]) == NULL ) {} else + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== hopBalance.c ========================================================*/ +extern Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel ); +extern Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel ); +/*=== hopCheck.c ========================================================*/ +extern int Hop_ManCheck( Hop_Man_t * p ); +/*=== hopDfs.c ==========================================================*/ +extern Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p ); +extern Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode ); +extern int Hop_ManCountLevels( Hop_Man_t * p ); +extern void Hop_ManCreateRefs( Hop_Man_t * p ); +extern int Hop_DagSize( Hop_Obj_t * pObj ); +extern void Hop_ConeUnmark_rec( Hop_Obj_t * pObj ); +extern Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pObj, int nVars ); +extern Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar ); +/*=== hopMan.c ==========================================================*/ +extern Hop_Man_t * Hop_ManStart(); +extern Hop_Man_t * Hop_ManDup( Hop_Man_t * p ); +extern void Hop_ManStop( Hop_Man_t * p ); +extern int Hop_ManCleanup( Hop_Man_t * p ); +extern void Hop_ManPrintStats( Hop_Man_t * p ); +/*=== hopMem.c ==========================================================*/ +extern void Hop_ManStartMemory( Hop_Man_t * p ); +extern void Hop_ManStopMemory( Hop_Man_t * p ); +/*=== hopObj.c ==========================================================*/ +extern Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p ); +extern Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver ); +extern Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost ); +extern void Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 ); +extern void Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern Hop_Obj_t * Hop_ObjRepr( Hop_Obj_t * pObj ); +extern void Hop_ObjCreateChoice( Hop_Obj_t * pOld, Hop_Obj_t * pNew ); +/*=== hopOper.c =========================================================*/ +extern Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i ); +extern Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ); +extern Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); +extern Hop_Obj_t * Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); +extern Hop_Obj_t * Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); +extern Hop_Obj_t * Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 ); +extern Hop_Obj_t * Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC ); +extern Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs ); +extern Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars ); +extern Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars ); +extern Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars ); +/*=== hopTable.c ========================================================*/ +extern Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost ); +extern void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern int Hop_TableCountEntries( Hop_Man_t * p ); +extern void Hop_TableProfile( Hop_Man_t * p ); +/*=== hopUtil.c =========================================================*/ +extern void Hop_ManIncrementTravId( Hop_Man_t * p ); +extern void Hop_ManCleanData( Hop_Man_t * p ); +extern void Hop_ObjCleanData_rec( Hop_Obj_t * pObj ); +extern void Hop_ObjCollectMulti( Hop_Obj_t * pFunc, Vec_Ptr_t * vSuper ); +extern int Hop_ObjIsMuxType( Hop_Obj_t * pObj ); +extern int Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ); +extern Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pObj, Hop_Obj_t ** ppObjT, Hop_Obj_t ** ppObjE ); +extern void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); +extern void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); +extern void Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig ); +extern void Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig ); +extern void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/hop/hopBalance.c b/abc70930/src/aig/hop/hopBalance.c new file mode 100644 index 00000000..73c90685 --- /dev/null +++ b/abc70930/src/aig/hop/hopBalance.c @@ -0,0 +1,391 @@ +/**CFile**************************************************************** + + FileName [hopBalance.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Algebraic AIG balancing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); +static Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); +static int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); +static void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); +static void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs algebraic balancing of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel ) +{ + Hop_Man_t * pNew; + Hop_Obj_t * pObj, * pObjNew; + Vec_Vec_t * vStore; + int i; + // create the new manager + pNew = Hop_ManStart(); + pNew->fRefCount = 0; + // map the PI nodes + Hop_ManCleanData( p ); + Hop_ManConst1(p)->pData = Hop_ManConst1(pNew); + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = Hop_ObjCreatePi(pNew); + // balance the AIG + vStore = Vec_VecAlloc( 50 ); + Hop_ManForEachPo( p, pObj, i ) + { + pObjNew = Hop_NodeBalance_rec( pNew, Hop_ObjFanin0(pObj), vStore, 0, fUpdateLevel ); + Hop_ObjCreatePo( pNew, Hop_NotCond( pObjNew, Hop_ObjFaninC0(pObj) ) ); + } + Vec_VecFree( vStore ); + // remove dangling nodes +// Hop_ManCreateRefs( pNew ); +// if ( i = Hop_ManCleanup( pNew ) ) +// printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); + // check the resulting AIG + if ( !Hop_ManCheck(pNew) ) + printf( "Hop_ManBalance(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns the new node constructed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) +{ + Hop_Obj_t * pObjNew; + Vec_Ptr_t * vSuper; + int i; + assert( !Hop_IsComplement(pObjOld) ); + // return if the result is known + if ( pObjOld->pData ) + return pObjOld->pData; + assert( Hop_ObjIsNode(pObjOld) ); + // get the implication supergate + vSuper = Hop_NodeBalanceCone( pObjOld, vStore, Level ); + // check if supergate contains two nodes in the opposite polarity + if ( vSuper->nSize == 0 ) + return pObjOld->pData = Hop_ManConst0(pNew); + if ( Vec_PtrSize(vSuper) < 2 ) + printf( "BUG!\n" ); + // for each old node, derive the new well-balanced node + for ( i = 0; i < Vec_PtrSize(vSuper); i++ ) + { + pObjNew = Hop_NodeBalance_rec( pNew, Hop_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); + vSuper->pArray[i] = Hop_NotCond( pObjNew, Hop_IsComplement(vSuper->pArray[i]) ); + } + // build the supergate + pObjNew = Hop_NodeBalanceBuildSuper( pNew, vSuper, Hop_ObjType(pObjOld), fUpdateLevel ); + // make sure the balanced node is not assigned +// assert( pObjOld->Level >= Hop_Regular(pObjNew)->Level ); + assert( pObjOld->pData == NULL ); + return pObjOld->pData = pObjNew; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_NodeBalanceCone_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Hop_Regular(pObj)->fMarkB ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pObj ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Hop_Not(pObj) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( pObj != pRoot && (Hop_IsComplement(pObj) || Hop_ObjType(pObj) != Hop_ObjType(pRoot) || Hop_ObjRefs(pObj) > 1) ) + { + Vec_PtrPush( vSuper, pObj ); + Hop_Regular(pObj)->fMarkB = 1; + return 0; + } + assert( !Hop_IsComplement(pObj) ); + assert( Hop_ObjIsNode(pObj) ); + // go through the branches + RetValue1 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild0(pObj), vSuper ); + RetValue2 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild1(pObj), vSuper ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) +{ + Vec_Ptr_t * vNodes; + int RetValue, i; + assert( !Hop_IsComplement(pObj) ); + // extend the storage + if ( Vec_VecSize( vStore ) <= Level ) + Vec_VecPush( vStore, Level, 0 ); + // get the temporary array of nodes + vNodes = Vec_VecEntry( vStore, Level ); + Vec_PtrClear( vNodes ); + // collect the nodes in the implication supergate + RetValue = Hop_NodeBalanceCone_rec( pObj, pObj, vNodes ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + Hop_Regular(pObj)->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_NodeCompareLevelsDecrease( Hop_Obj_t ** pp1, Hop_Obj_t ** pp2 ) +{ + int Diff = Hop_ObjLevel(Hop_Regular(*pp1)) - Hop_ObjLevel(Hop_Regular(*pp2)); + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Builds implication supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel ) +{ + Hop_Obj_t * pObj1, * pObj2; + int LeftBound; + assert( vSuper->nSize > 1 ); + // sort the new nodes by level in the decreasing order + Vec_PtrSort( vSuper, Hop_NodeCompareLevelsDecrease ); + // balance the nodes + while ( vSuper->nSize > 1 ) + { + // find the left bound on the node to be paired + LeftBound = (!fUpdateLevel)? 0 : Hop_NodeBalanceFindLeft( vSuper ); + // find the node that can be shared (if no such node, randomize choice) + Hop_NodeBalancePermute( p, vSuper, LeftBound, Type == AIG_EXOR ); + // pull out the last two nodes + pObj1 = Vec_PtrPop(vSuper); + pObj2 = Vec_PtrPop(vSuper); + Hop_NodeBalancePushUniqueOrderByLevel( vSuper, Hop_Oper(p, pObj1, pObj2, Type) ); + } + return Vec_PtrEntry(vSuper, 0); +} + +/**Function************************************************************* + + Synopsis [Finds the left bound on the next candidate to be paired.] + + Description [The nodes in the array are in the decreasing order of levels. + The last node in the array has the smallest level. By default it would be paired + with the next node on the left. However, it may be possible to pair it with some + other node on the left, in such a way that the new node is shared. This procedure + finds the index of the left-most node, which can be paired with the last node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) +{ + Hop_Obj_t * pObjRight, * pObjLeft; + int Current; + // if two or less nodes, pair with the first + if ( Vec_PtrSize(vSuper) < 3 ) + return 0; + // set the pointer to the one before the last + Current = Vec_PtrSize(vSuper) - 2; + pObjRight = Vec_PtrEntry( vSuper, Current ); + // go through the nodes to the left of this one + for ( Current--; Current >= 0; Current-- ) + { + // get the next node on the left + pObjLeft = Vec_PtrEntry( vSuper, Current ); + // if the level of this node is different, quit the loop + if ( Hop_ObjLevel(Hop_Regular(pObjLeft)) != Hop_ObjLevel(Hop_Regular(pObjRight)) ) + break; + } + Current++; + // get the node, for which the equality holds + pObjLeft = Vec_PtrEntry( vSuper, Current ); + assert( Hop_ObjLevel(Hop_Regular(pObjLeft)) == Hop_ObjLevel(Hop_Regular(pObjRight)) ); + return Current; +} + +/**Function************************************************************* + + Synopsis [Moves closer to the end the node that is best for sharing.] + + Description [If there is no node with sharing, randomly chooses one of + the legal nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) +{ + Hop_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; + int RightBound, i; + // get the right bound + RightBound = Vec_PtrSize(vSuper) - 2; + assert( LeftBound <= RightBound ); + if ( LeftBound == RightBound ) + return; + // get the two last nodes + pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); + pObj2 = Vec_PtrEntry( vSuper, RightBound ); + if ( Hop_Regular(pObj1) == p->pConst1 || Hop_Regular(pObj2) == p->pConst1 ) + return; + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + pObj3 = Vec_PtrEntry( vSuper, i ); + if ( Hop_Regular(pObj3) == p->pConst1 ) + { + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + pGhost = Hop_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_EXOR : AIG_AND ); + if ( Hop_TableLookup( p, pGhost ) ) + { + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + } +/* + // we did not find the node to share, randomize choice + { + int Choice = rand() % (RightBound - LeftBound + 1); + pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj ) +{ + Hop_Obj_t * pObj1, * pObj2; + int i; + if ( Vec_PtrPushUnique(vStore, pObj) ) + return; + // find the p of the node + for ( i = vStore->nSize-1; i > 0; i-- ) + { + pObj1 = vStore->pArray[i ]; + pObj2 = vStore->pArray[i-1]; + if ( Hop_ObjLevel(Hop_Regular(pObj1)) <= Hop_ObjLevel(Hop_Regular(pObj2)) ) + break; + vStore->pArray[i ] = pObj2; + vStore->pArray[i-1] = pObj1; + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/hop/hopCheck.c b/abc70930/src/aig/hop/hopCheck.c new file mode 100644 index 00000000..9120906f --- /dev/null +++ b/abc70930/src/aig/hop/hopCheck.c @@ -0,0 +1,110 @@ +/**CFile**************************************************************** + + FileName [hopCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [AIG checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the consistency of the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ManCheck( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj, * pObj2; + int i; + // check primary inputs + Hop_ManForEachPi( p, pObj, i ) + { + if ( Hop_ObjFanin0(pObj) || Hop_ObjFanin1(pObj) ) + { + printf( "Hop_ManCheck: The PI node \"%p\" has fanins.\n", pObj ); + return 0; + } + } + // check primary outputs + Hop_ManForEachPo( p, pObj, i ) + { + if ( !Hop_ObjFanin0(pObj) ) + { + printf( "Hop_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj ); + return 0; + } + if ( Hop_ObjFanin1(pObj) ) + { + printf( "Hop_ManCheck: The PO node \"%p\" has second fanin.\n", pObj ); + return 0; + } + } + // check internal nodes + Hop_ManForEachNode( p, pObj, i ) + { + if ( !Hop_ObjFanin0(pObj) || !Hop_ObjFanin1(pObj) ) + { + printf( "Hop_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj ); + return 0; + } + if ( Hop_ObjFanin0(pObj)->Id >= Hop_ObjFanin1(pObj)->Id ) + { + printf( "Hop_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj ); + return 0; + } + pObj2 = Hop_TableLookup( p, pObj ); + if ( pObj2 != pObj ) + { + printf( "Hop_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj ); + return 0; + } + } + // count the total number of nodes + if ( Hop_ManObjNum(p) != 1 + Hop_ManPiNum(p) + Hop_ManPoNum(p) + Hop_ManAndNum(p) + Hop_ManExorNum(p) ) + { + printf( "Hop_ManCheck: The number of created nodes is wrong.\n" ); + return 0; + } + // count the number of nodes in the table + if ( Hop_TableCountEntries(p) != Hop_ManAndNum(p) + Hop_ManExorNum(p) ) + { + printf( "Hop_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); + return 0; + } +// if ( !Hop_ManIsAcyclic(p) ) +// return 0; + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/hop/hopDfs.c b/abc70930/src/aig/hop/hopDfs.c new file mode 100644 index 00000000..49e5f221 --- /dev/null +++ b/abc70930/src/aig/hop/hopDfs.c @@ -0,0 +1,399 @@ +/**CFile**************************************************************** + + FileName [hopDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [DFS traversal procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManDfs_rec( Hop_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_ManDfs_rec( Hop_ObjFanin0(pObj), vNodes ); + Hop_ManDfs_rec( Hop_ObjFanin1(pObj), vNodes ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA(pObj); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i; + vNodes = Vec_PtrAlloc( Hop_ManNodeNum(p) ); + Hop_ManForEachNode( p, pObj, i ) + Hop_ManDfs_rec( pObj, vNodes ); + Hop_ManForEachNode( p, pObj, i ) + Hop_ObjClearMarkA(pObj); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i; + assert( !Hop_IsComplement(pNode) ); + vNodes = Vec_PtrAlloc( 16 ); + Hop_ManDfs_rec( pNode, vNodes ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + Hop_ObjClearMarkA(pObj); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the max number of levels in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ManCountLevels( Hop_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i, LevelsMax, Level0, Level1; + // initialize the levels + Hop_ManConst1(p)->pData = NULL; + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = NULL; + // compute levels in a DFS order + vNodes = Hop_ManDfs( p ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + Level0 = (int)Hop_ObjFanin0(pObj)->pData; + Level1 = (int)Hop_ObjFanin1(pObj)->pData; + pObj->pData = (void *)(1 + Hop_ObjIsExor(pObj) + AIG_MAX(Level0, Level1)); + } + Vec_PtrFree( vNodes ); + // get levels of the POs + LevelsMax = 0; + Hop_ManForEachPo( p, pObj, i ) + LevelsMax = AIG_MAX( LevelsMax, (int)Hop_ObjFanin0(pObj)->pData ); + return LevelsMax; +} + +/**Function************************************************************* + + Synopsis [Creates correct reference counters at each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManCreateRefs( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + int i; + if ( p->fRefCount ) + return; + p->fRefCount = 1; + // clear refs + Hop_ObjClearRef( Hop_ManConst1(p) ); + Hop_ManForEachPi( p, pObj, i ) + Hop_ObjClearRef( pObj ); + Hop_ManForEachNode( p, pObj, i ) + Hop_ObjClearRef( pObj ); + Hop_ManForEachPo( p, pObj, i ) + Hop_ObjClearRef( pObj ); + // set refs + Hop_ManForEachNode( p, pObj, i ) + { + Hop_ObjRef( Hop_ObjFanin0(pObj) ); + Hop_ObjRef( Hop_ObjFanin1(pObj) ); + } + Hop_ManForEachPo( p, pObj, i ) + Hop_ObjRef( Hop_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ConeMark_rec( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_ConeMark_rec( Hop_ObjFanin0(pObj) ); + Hop_ConeMark_rec( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ConeCleanAndMark_rec( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_ConeCleanAndMark_rec( Hop_ObjFanin0(pObj) ); + Hop_ConeCleanAndMark_rec( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ConeCountAndMark_rec( Hop_Obj_t * pObj ) +{ + int Counter; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return 0; + Counter = 1 + Hop_ConeCountAndMark_rec( Hop_ObjFanin0(pObj) ) + + Hop_ConeCountAndMark_rec( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ConeUnmark_rec( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) + return; + Hop_ConeUnmark_rec( Hop_ObjFanin0(pObj) ); + Hop_ConeUnmark_rec( Hop_ObjFanin1(pObj) ); + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_DagSize( Hop_Obj_t * pObj ) +{ + int Counter; + Counter = Hop_ConeCountAndMark_rec( Hop_Regular(pObj) ); + Hop_ConeUnmark_rec( Hop_Regular(pObj) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_Transfer_rec( Hop_Man_t * pDest, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_Transfer_rec( pDest, Hop_ObjFanin0(pObj) ); + Hop_Transfer_rec( pDest, Hop_ObjFanin1(pObj) ); + pObj->pData = Hop_And( pDest, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pRoot, int nVars ) +{ + Hop_Obj_t * pObj; + int i; + // solve simple cases + if ( pSour == pDest ) + return pRoot; + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return Hop_NotCond( Hop_ManConst1(pDest), Hop_IsComplement(pRoot) ); + // set the PI mapping + Hop_ManForEachPi( pSour, pObj, i ) + { + if ( i == nVars ) + break; + pObj->pData = Hop_IthVar(pDest, i); + } + // transfer and set markings + Hop_Transfer_rec( pDest, Hop_Regular(pRoot) ); + // clear the markings + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + return Hop_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + +/**Function************************************************************* + + Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_Compose_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFunc, Hop_Obj_t * pVar ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( Hop_ObjIsMarkA(pObj) ) + return; + if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) + { + pObj->pData = pObj == pVar ? pFunc : pObj; + return; + } + Hop_Compose_rec( p, Hop_ObjFanin0(pObj), pFunc, pVar ); + Hop_Compose_rec( p, Hop_ObjFanin1(pObj), pFunc, pVar ); + pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar ) +{ + // quit if the PI variable is not defined + if ( iVar >= Hop_ManPiNum(p) ) + { + printf( "Hop_Compose(): The PI variable %d is not defined.\n", iVar ); + return NULL; + } + // recursively perform composition + Hop_Compose_rec( p, Hop_Regular(pRoot), pFunc, Hop_ManPi(p, iVar) ); + // clear the markings + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + return Hop_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/hop/hopMan.c b/abc70930/src/aig/hop/hopMan.c new file mode 100644 index 00000000..99f5d316 --- /dev/null +++ b/abc70930/src/aig/hop/hopMan.c @@ -0,0 +1,164 @@ +/**CFile**************************************************************** + + FileName [hopMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [AIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopMan.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Hop_ManStart() +{ + Hop_Man_t * p; + // start the manager + p = ALLOC( Hop_Man_t, 1 ); + memset( p, 0, sizeof(Hop_Man_t) ); + // perform initializations + p->nTravIds = 1; + p->fRefCount = 1; + p->fCatchExor = 0; + // allocate arrays for nodes + p->vPis = Vec_PtrAlloc( 100 ); + p->vPos = Vec_PtrAlloc( 100 ); + // prepare the internal memory manager + Hop_ManStartMemory( p ); + // create the constant node + p->pConst1 = Hop_ManFetchMemory( p ); + p->pConst1->Type = AIG_CONST1; + p->pConst1->fPhase = 1; + p->nCreated = 1; + // start the table +// p->nTableSize = 107; + p->nTableSize = 10007; + p->pTable = ALLOC( Hop_Obj_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManStop( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + int i; + // make sure the nodes have clean marks + pObj = Hop_ManConst1(p); + assert( !pObj->fMarkA && !pObj->fMarkB ); + Hop_ManForEachPi( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + Hop_ManForEachPo( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + Hop_ManForEachNode( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + // print time + if ( p->time1 ) { PRT( "time1", p->time1 ); } + if ( p->time2 ) { PRT( "time2", p->time2 ); } +// Hop_TableProfile( p ); + if ( p->vChunks ) Hop_ManStopMemory( p ); + if ( p->vPis ) Vec_PtrFree( p->vPis ); + if ( p->vPos ) Vec_PtrFree( p->vPos ); + if ( p->vObjs ) Vec_PtrFree( p->vObjs ); + free( p->pTable ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ManCleanup( Hop_Man_t * p ) +{ + Vec_Ptr_t * vObjs; + Hop_Obj_t * pNode; + int i, nNodesOld; + assert( p->fRefCount ); + nNodesOld = Hop_ManNodeNum(p); + // collect roots of dangling nodes + vObjs = Vec_PtrAlloc( 100 ); + Hop_ManForEachNode( p, pNode, i ) + if ( Hop_ObjRefs(pNode) == 0 ) + Vec_PtrPush( vObjs, pNode ); + // recursively remove dangling nodes + Vec_PtrForEachEntry( vObjs, pNode, i ) + Hop_ObjDelete_rec( p, pNode ); + Vec_PtrFree( vObjs ); + return nNodesOld - Hop_ManNodeNum(p); +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManPrintStats( Hop_Man_t * p ) +{ + printf( "PI/PO = %d/%d. ", Hop_ManPiNum(p), Hop_ManPoNum(p) ); + printf( "A = %7d. ", Hop_ManAndNum(p) ); + printf( "X = %5d. ", Hop_ManExorNum(p) ); + printf( "Cre = %7d. ", p->nCreated ); + printf( "Del = %7d. ", p->nDeleted ); + printf( "Lev = %3d. ", Hop_ManCountLevels(p) ); + printf( "\n" ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/hop/hopMem.c b/abc70930/src/aig/hop/hopMem.c new file mode 100644 index 00000000..0665470a --- /dev/null +++ b/abc70930/src/aig/hop/hopMem.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [hopMem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Memory management for the AIG nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// memory management +#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes +#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManStartMemory( Hop_Man_t * p ) +{ + p->vChunks = Vec_PtrAlloc( 128 ); + p->vPages = Vec_PtrAlloc( 128 ); +} + +/**Function************************************************************* + + Synopsis [Stops the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManStopMemory( Hop_Man_t * p ) +{ + void * pMemory; + int i; + Vec_PtrForEachEntry( p->vChunks, pMemory, i ) + free( pMemory ); + Vec_PtrFree( p->vChunks ); + Vec_PtrFree( p->vPages ); + p->pListFree = NULL; +} + +/**Function************************************************************* + + Synopsis [Allocates additional memory for the nodes.] + + Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. + Records the pointer to the AIG manager in the -1 entry.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManAddMemory( Hop_Man_t * p ) +{ + char * pMemory; + int i, nBytes; + assert( sizeof(Hop_Obj_t) <= 64 ); + assert( p->pListFree == NULL ); +// assert( (Hop_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); + // allocate new memory page + nBytes = sizeof(Hop_Obj_t) * (1<vChunks, pMemory ); + // align memory at the 32-byte boundary + pMemory = pMemory + 64 - (((int)pMemory) & 63); + // remember the manager in the first entry + Vec_PtrPush( p->vPages, pMemory ); + // break the memory down into nodes + p->pListFree = (Hop_Obj_t *)pMemory; + for ( i = 1; i <= IVY_PAGE_MASK; i++ ) + { + *((char **)pMemory) = pMemory + sizeof(Hop_Obj_t); + pMemory += sizeof(Hop_Obj_t); + } + *((char **)pMemory) = NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/hop/hopObj.c b/abc70930/src/aig/hop/hopObj.c new file mode 100644 index 00000000..c8e70dd3 --- /dev/null +++ b/abc70930/src/aig/hop/hopObj.c @@ -0,0 +1,271 @@ +/**CFile**************************************************************** + + FileName [hopObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Adding/removing objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates primary input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + pObj = Hop_ManFetchMemory( p ); + pObj->Type = AIG_PI; + Vec_PtrPush( p->vPis, pObj ); + p->nObjs[AIG_PI]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates primary output with the given driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver ) +{ + Hop_Obj_t * pObj; + pObj = Hop_ManFetchMemory( p ); + pObj->Type = AIG_PO; + Vec_PtrPush( p->vPos, pObj ); + // add connections + pObj->pFanin0 = pDriver; + if ( p->fRefCount ) + Hop_ObjRef( Hop_Regular(pDriver) ); + else + pObj->nRefs = Hop_ObjLevel( Hop_Regular(pDriver) ); + // set the phase + pObj->fPhase = Hop_ObjFaninPhase(pDriver); + // update node counters of the manager + p->nObjs[AIG_PO]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost ) +{ + Hop_Obj_t * pObj; + assert( !Hop_IsComplement(pGhost) ); + assert( Hop_ObjIsNode(pGhost) ); + assert( pGhost == &p->Ghost ); + // get memory for the new object + pObj = Hop_ManFetchMemory( p ); + pObj->Type = pGhost->Type; + // add connections + Hop_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); + // update node counters of the manager + p->nObjs[Hop_ObjType(pObj)]++; + assert( pObj->pData == NULL ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 ) +{ + assert( !Hop_IsComplement(pObj) ); + assert( Hop_ObjIsNode(pObj) ); + // add the first fanin + pObj->pFanin0 = pFan0; + pObj->pFanin1 = pFan1; + // increment references of the fanins and add their fanouts + if ( p->fRefCount ) + { + if ( pFan0 != NULL ) + Hop_ObjRef( Hop_ObjFanin0(pObj) ); + if ( pFan1 != NULL ) + Hop_ObjRef( Hop_ObjFanin1(pObj) ); + } + else + pObj->nRefs = Hop_ObjLevelNew( pObj ); + // set the phase + pObj->fPhase = Hop_ObjFaninPhase(pFan0) & Hop_ObjFaninPhase(pFan1); + // add the node to the structural hash table + Hop_TableInsert( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + assert( Hop_ObjIsNode(pObj) ); + // remove connections + if ( pObj->pFanin0 != NULL ) + Hop_ObjDeref(Hop_ObjFanin0(pObj)); + if ( pObj->pFanin1 != NULL ) + Hop_ObjDeref(Hop_ObjFanin1(pObj)); + // remove the node from the structural hash table + Hop_TableDelete( p, pObj ); + // add the first fanin + pObj->pFanin0 = NULL; + pObj->pFanin1 = NULL; +} + +/**Function************************************************************* + + Synopsis [Deletes the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + assert( !Hop_ObjIsTerm(pObj) ); + assert( Hop_ObjRefs(pObj) == 0 ); + // update node counters of the manager + p->nObjs[pObj->Type]--; + p->nDeleted++; + // remove connections + Hop_ObjDisconnect( p, pObj ); + // remove PIs/POs from the arrays + if ( Hop_ObjIsPi(pObj) ) + Vec_PtrRemove( p->vPis, pObj ); + // free the node + Hop_ManRecycleMemory( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Deletes the MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + Hop_Obj_t * pFanin0, * pFanin1; + assert( !Hop_IsComplement(pObj) ); + if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) + return; + assert( Hop_ObjIsNode(pObj) ); + pFanin0 = Hop_ObjFanin0(pObj); + pFanin1 = Hop_ObjFanin1(pObj); + Hop_ObjDelete( p, pObj ); + if ( pFanin0 && !Hop_ObjIsNone(pFanin0) && Hop_ObjRefs(pFanin0) == 0 ) + Hop_ObjDelete_rec( p, pFanin0 ); + if ( pFanin1 && !Hop_ObjIsNone(pFanin1) && Hop_ObjRefs(pFanin1) == 0 ) + Hop_ObjDelete_rec( p, pFanin1 ); +} + +/**Function************************************************************* + + Synopsis [Returns the representative of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjRepr( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( pObj->pData == NULL || pObj->pData == pObj ) + return pObj; + return Hop_ObjRepr( pObj->pData ); +} + +/**Function************************************************************* + + Synopsis [Sets an equivalence relation between the nodes.] + + Description [Makes the representative of pNew point to the representaive of pOld.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjCreateChoice( Hop_Obj_t * pOld, Hop_Obj_t * pNew ) +{ + Hop_Obj_t * pOldRepr; + Hop_Obj_t * pNewRepr; + assert( pOld != NULL && pNew != NULL ); + pOldRepr = Hop_ObjRepr(pOld); + pNewRepr = Hop_ObjRepr(pNew); + if ( pNewRepr != pOldRepr ) + pNewRepr->pData = pOldRepr; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/hop/hopOper.c b/abc70930/src/aig/hop/hopOper.c new file mode 100644 index 00000000..a31ca0f2 --- /dev/null +++ b/abc70930/src/aig/hop/hopOper.c @@ -0,0 +1,373 @@ +/**CFile**************************************************************** + + FileName [hopOper.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [AIG operations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// procedure to detect an EXOR gate +static inline int Hop_ObjIsExorType( Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ) +{ + if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) ) + return 0; + p0 = Hop_Regular(p0); + p1 = Hop_Regular(p1); + if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) ) + return 0; + if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) ) + return 0; + if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Hop_ObjChild0(p0); + *ppFan1 = Hop_ObjChild1(p0); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns i-th elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i ) +{ + int v; + for ( v = Hop_ManPiNum(p); v <= i; v++ ) + Hop_ObjCreatePi( p ); + assert( i < Vec_PtrSize(p->vPis) ); + return Hop_ManPi( p, i ); +} + +/**Function************************************************************* + + Synopsis [Perform one operation.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ) +{ + if ( Type == AIG_AND ) + return Hop_And( p, p0, p1 ); + if ( Type == AIG_EXOR ) + return Hop_Exor( p, p0, p1 ); + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) +{ + Hop_Obj_t * pGhost, * pResult; +// Hop_Obj_t * pFan0, * pFan1; + // check trivial cases + if ( p0 == p1 ) + return p0; + if ( p0 == Hop_Not(p1) ) + return Hop_Not(p->pConst1); + if ( Hop_Regular(p0) == p->pConst1 ) + return p0 == p->pConst1 ? p1 : Hop_Not(p->pConst1); + if ( Hop_Regular(p1) == p->pConst1 ) + return p1 == p->pConst1 ? p0 : Hop_Not(p->pConst1); + // check if it can be an EXOR gate +// if ( Hop_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) +// return Hop_Exor( p, pFan0, pFan1 ); + // check the table + pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_AND ); + if ( pResult = Hop_TableLookup( p, pGhost ) ) + return pResult; + return Hop_ObjCreate( p, pGhost ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) +{ +/* + Hop_Obj_t * pGhost, * pResult; + // check trivial cases + if ( p0 == p1 ) + return Hop_Not(p->pConst1); + if ( p0 == Hop_Not(p1) ) + return p->pConst1; + if ( Hop_Regular(p0) == p->pConst1 ) + return Hop_NotCond( p1, p0 == p->pConst1 ); + if ( Hop_Regular(p1) == p->pConst1 ) + return Hop_NotCond( p0, p1 == p->pConst1 ); + // check the table + pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_EXOR ); + if ( pResult = Hop_TableLookup( p, pGhost ) ) + return pResult; + return Hop_ObjCreate( p, pGhost ); +*/ + return Hop_Or( p, Hop_And(p, p0, Hop_Not(p1)), Hop_And(p, Hop_Not(p0), p1) ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) +{ + return Hop_Not( Hop_And( p, Hop_Not(p0), Hop_Not(p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 ) +{ +/* + Hop_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; + int Count0, Count1; + // consider trivial cases + if ( p0 == Hop_Not(p1) ) + return Hop_Exor( p, pC, p0 ); + // other cases can be added + // implement the first MUX (F = C * x1 + C' * x0) + + // check for constants here!!! + + pTempA1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC, p1, AIG_AND) ); + pTempA2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), p0, AIG_AND) ); + if ( pTempA1 && pTempA2 ) + { + pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempA1), Hop_Not(pTempA2), AIG_AND) ); + if ( pTemp ) return Hop_Not(pTemp); + } + Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); + // implement the second MUX (F' = C * x1' + C' * x0') + pTempB1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC, Hop_Not(p1), AIG_AND) ); + pTempB2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), Hop_Not(p0), AIG_AND) ); + if ( pTempB1 && pTempB2 ) + { + pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempB1), Hop_Not(pTempB2), AIG_AND) ); + if ( pTemp ) return pTemp; + } + Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); + // compare and decide which one to implement + if ( Count0 >= Count1 ) + { + pTempA1 = pTempA1? pTempA1 : Hop_And(p, pC, p1); + pTempA2 = pTempA2? pTempA2 : Hop_And(p, Hop_Not(pC), p0); + return Hop_Or( p, pTempA1, pTempA2 ); + } + pTempB1 = pTempB1? pTempB1 : Hop_And(p, pC, Hop_Not(p1)); + pTempB2 = pTempB2? pTempB2 : Hop_And(p, Hop_Not(pC), Hop_Not(p0)); + return Hop_Not( Hop_Or( p, pTempB1, pTempB2 ) ); +*/ + return Hop_Or( p, Hop_And(p, pC, p1), Hop_And(p, Hop_Not(pC), p0) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC ) +{ + return Hop_Or( p, Hop_Or(p, Hop_And(p, pA, pB), Hop_And(p, pA, pC)), Hop_And(p, pB, pC) ); +} + +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Multi_rec( Hop_Man_t * p, Hop_Obj_t ** ppObjs, int nObjs, Hop_Type_t Type ) +{ + Hop_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Hop_Multi_rec( p, ppObjs, nObjs/2, Type ); + pObj2 = Hop_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Hop_Oper( p, pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Multi( Hop_Man_t * p, Hop_Obj_t ** pArgs, int nArgs, Hop_Type_t Type ) +{ + assert( Type == AIG_AND || Type == AIG_EXOR ); + assert( nArgs > 0 ); + return Hop_Multi_rec( p, pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs ) +{ + int i; + assert( vPairs->nSize > 0 ); + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Hop_Not( Hop_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) ); + vPairs->nSize = vPairs->nSize/2; + return Hop_Not( Hop_Multi_rec( p, (Hop_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_AND ) ); +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars ) +{ + Hop_Obj_t * pFunc; + int i; + pFunc = Hop_ManConst1( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Hop_And( p, pFunc, Hop_IthVar(p, i) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars ) +{ + Hop_Obj_t * pFunc; + int i; + pFunc = Hop_ManConst0( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Hop_Or( p, pFunc, Hop_IthVar(p, i) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars ) +{ + Hop_Obj_t * pFunc; + int i; + pFunc = Hop_ManConst0( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Hop_Exor( p, pFunc, Hop_IthVar(p, i) ); + return pFunc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/hop/hopTable.c b/abc70930/src/aig/hop/hopTable.c new file mode 100644 index 00000000..76390054 --- /dev/null +++ b/abc70930/src/aig/hop/hopTable.c @@ -0,0 +1,262 @@ +/**CFile**************************************************************** + + FileName [hopTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Structural hashing table.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006. ] + + Revision [$Id: hopTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// hashing the node +static unsigned long Hop_Hash( Hop_Obj_t * pObj, int TableSize ) +{ + unsigned long Key = Hop_ObjIsExor(pObj) * 1699; + Key ^= Hop_ObjFanin0(pObj)->Id * 7937; + Key ^= Hop_ObjFanin1(pObj)->Id * 2971; + Key ^= Hop_ObjFaninC0(pObj) * 911; + Key ^= Hop_ObjFaninC1(pObj) * 353; + return Key % TableSize; +} + +// returns the place where this node is stored (or should be stored) +static Hop_Obj_t ** Hop_TableFind( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + Hop_Obj_t ** ppEntry; + assert( Hop_ObjChild0(pObj) && Hop_ObjChild1(pObj) ); + assert( Hop_ObjFanin0(pObj)->Id < Hop_ObjFanin1(pObj)->Id ); + for ( ppEntry = p->pTable + Hop_Hash(pObj, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) + if ( *ppEntry == pObj ) + return ppEntry; + assert( *ppEntry == NULL ); + return ppEntry; +} + +static void Hop_TableResize( Hop_Man_t * p ); +static unsigned int Cudd_PrimeAig( unsigned int p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if a node with the given attributes is in the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost ) +{ + Hop_Obj_t * pEntry; + assert( !Hop_IsComplement(pGhost) ); + assert( Hop_ObjChild0(pGhost) && Hop_ObjChild1(pGhost) ); + assert( Hop_ObjFanin0(pGhost)->Id < Hop_ObjFanin1(pGhost)->Id ); + if ( p->fRefCount && (!Hop_ObjRefs(Hop_ObjFanin0(pGhost)) || !Hop_ObjRefs(Hop_ObjFanin1(pGhost))) ) + return NULL; + for ( pEntry = p->pTable[Hop_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext ) + { + if ( Hop_ObjChild0(pEntry) == Hop_ObjChild0(pGhost) && + Hop_ObjChild1(pEntry) == Hop_ObjChild1(pGhost) && + Hop_ObjType(pEntry) == Hop_ObjType(pGhost) ) + return pEntry; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Adds the new node to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + Hop_Obj_t ** ppPlace; + assert( !Hop_IsComplement(pObj) ); + assert( Hop_TableLookup(p, pObj) == NULL ); + if ( (pObj->Id & 0xFF) == 0 && 2 * p->nTableSize < Hop_ManNodeNum(p) ) + Hop_TableResize( p ); + ppPlace = Hop_TableFind( p, pObj ); + assert( *ppPlace == NULL ); + *ppPlace = pObj; +} + +/**Function************************************************************* + + Synopsis [Deletes the node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + Hop_Obj_t ** ppPlace; + assert( !Hop_IsComplement(pObj) ); + ppPlace = Hop_TableFind( p, pObj ); + assert( *ppPlace == pObj ); // node should be in the table + // remove the node + *ppPlace = pObj->pNext; + pObj->pNext = NULL; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_TableCountEntries( Hop_Man_t * p ) +{ + Hop_Obj_t * pEntry; + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [Typically this procedure should not be called.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_TableResize( Hop_Man_t * p ) +{ + Hop_Obj_t * pEntry, * pNext; + Hop_Obj_t ** pTableOld, ** ppPlace; + int nTableSizeOld, Counter, nEntries, i, clk; +clk = clock(); + // save the old table + pTableOld = p->pTable; + nTableSizeOld = p->nTableSize; + // get the new table + p->nTableSize = Cudd_PrimeAig( 2 * Hop_ManNodeNum(p) ); + p->pTable = ALLOC( Hop_Obj_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < nTableSizeOld; i++ ) + for ( pEntry = pTableOld[i], pNext = pEntry? pEntry->pNext : NULL; pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL ) + { + // get the place where this entry goes in the table + ppPlace = Hop_TableFind( p, pEntry ); + assert( *ppPlace == NULL ); // should not be there + // add the entry to the list + *ppPlace = pEntry; + pEntry->pNext = NULL; + Counter++; + } + nEntries = Hop_ManNodeNum(p); + assert( Counter == nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); +// PRT( "Time", clock() - clk ); + // replace the table and the parameters + free( pTableOld ); +} + +/**Function******************************************************************** + + Synopsis [Profiles the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Hop_TableProfile( Hop_Man_t * p ) +{ + Hop_Obj_t * pEntry; + int i, Counter; + for ( i = 0; i < p->nTableSize; i++ ) + { + Counter = 0; + for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) + Counter++; + if ( Counter ) + printf( "%d ", Counter ); + } +} + +/**Function******************************************************************** + + Synopsis [Returns the next prime >= p.] + + Description [Copied from CUDD, for stand-aloneness.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +unsigned int Cudd_PrimeAig( unsigned int p) +{ + int i,pn; + p--; + do { + p++; + if (p&1) { + pn = 1; + i = 3; + while ((unsigned) (i * i) <= p) { + if (p % i == 0) { + pn = 0; + break; + } + i += 2; + } + } else { + pn = 0; + } + } while (!pn); + return(p); + +} /* end of Cudd_Prime */ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/hop/hopUtil.c b/abc70930/src/aig/hop/hopUtil.c new file mode 100644 index 00000000..87fdb15e --- /dev/null +++ b/abc70930/src/aig/hop/hopUtil.c @@ -0,0 +1,572 @@ +/**CFile**************************************************************** + + FileName [hopUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Various procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Increments the current traversal ID of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManIncrementTravId( Hop_Man_t * p ) +{ + if ( p->nTravIds >= (1<<30)-1 ) + Hop_ManCleanData( p ); + p->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Cleans the data pointers for the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManCleanData( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + int i; + p->nTravIds = 1; + Hop_ManConst1(p)->pData = NULL; + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = NULL; + Hop_ManForEachPo( p, pObj, i ) + pObj->pData = NULL; + Hop_ManForEachNode( p, pObj, i ) + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Recursively cleans the data pointers in the cone of the node.] + + Description [Applicable to small AIGs only because no caching is performed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjCleanData_rec( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + assert( !Hop_ObjIsPo(pObj) ); + if ( Hop_ObjIsAnd(pObj) ) + { + Hop_ObjCleanData_rec( Hop_ObjFanin0(pObj) ); + Hop_ObjCleanData_rec( Hop_ObjFanin1(pObj) ); + } + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjCollectMulti_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + if ( pRoot != pObj && (Hop_IsComplement(pObj) || Hop_ObjIsPi(pObj) || Hop_ObjType(pRoot) != Hop_ObjType(pObj)) ) + { + Vec_PtrPushUnique(vSuper, pObj); + return; + } + Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild0(pObj), vSuper ); + Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild1(pObj), vSuper ); +} + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjCollectMulti( Hop_Obj_t * pRoot, Vec_Ptr_t * vSuper ) +{ + assert( !Hop_IsComplement(pRoot) ); + Vec_PtrClear( vSuper ); + Hop_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ObjIsMuxType( Hop_Obj_t * pNode ) +{ + Hop_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Hop_IsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Hop_ObjIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Hop_ObjFaninC0(pNode) || !Hop_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Hop_ObjFanin0(pNode); + pNode1 = Hop_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( !Hop_ObjIsAnd(pNode0) || !Hop_ObjIsAnd(pNode1) ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren + return (Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1))) || + (Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1))) || + (Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1))) || + (Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1))); +} + + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are inputs of the EXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ) +{ + Hop_Obj_t * p0, * p1; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) ) + return 0; + if ( Hop_ObjIsExor(pObj) ) + { + *ppFan0 = Hop_ObjChild0(pObj); + *ppFan1 = Hop_ObjChild1(pObj); + return 1; + } + assert( Hop_ObjIsAnd(pObj) ); + p0 = Hop_ObjChild0(pObj); + p1 = Hop_ObjChild1(pObj); + if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) ) + return 0; + p0 = Hop_Regular(p0); + p1 = Hop_Regular(p1); + if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) ) + return 0; + if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) ) + return 0; + if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Hop_ObjChild0(p0); + *ppFan1 = Hop_ObjChild1(p0); + return 1; +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pNode, Hop_Obj_t ** ppNodeT, Hop_Obj_t ** ppNodeE ) +{ + Hop_Obj_t * pNode0, * pNode1; + assert( !Hop_IsComplement(pNode) ); + assert( Hop_ObjIsMuxType(pNode) ); + // get children + pNode0 = Hop_ObjFanin0(pNode); + pNode1 = Hop_ObjFanin1(pNode); + + // find the control variable + if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Hop_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + return Hop_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + return Hop_ObjChild1(pNode0);//pNode1->p2; + } + } + else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Hop_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + return Hop_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + return Hop_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Hop_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + return Hop_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + return Hop_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Hop_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + return Hop_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + return Hop_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Prints Eqn formula for the AIG rooted at this node.] + + Description [The formula is in terms of PIs, which should have + their names assigned in pObj->pData fields.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) +{ + Vec_Ptr_t * vSuper; + Hop_Obj_t * pFanin; + int fCompl, i; + // store the complemented attribute + fCompl = Hop_IsComplement(pObj); + pObj = Hop_Regular(pObj); + // constant case + if ( Hop_ObjIsConst1(pObj) ) + { + fprintf( pFile, "%d", !fCompl ); + return; + } + // PI case + if ( Hop_ObjIsPi(pObj) ) + { + fprintf( pFile, "%s%s", fCompl? "!" : "", pObj->pData ); + return; + } + // AND case + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry(vLevels, Level); + Hop_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + Hop_ObjPrintEqn( pFile, Hop_NotCond(pFanin, fCompl), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " %s ", fCompl? "+" : "*" ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; +} + +/**Function************************************************************* + + Synopsis [Prints Verilog formula for the AIG rooted at this node.] + + Description [The formula is in terms of PIs, which should have + their names assigned in pObj->pData fields.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) +{ + Vec_Ptr_t * vSuper; + Hop_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC; + int fCompl, i; + // store the complemented attribute + fCompl = Hop_IsComplement(pObj); + pObj = Hop_Regular(pObj); + // constant case + if ( Hop_ObjIsConst1(pObj) ) + { + fprintf( pFile, "1\'b%d", !fCompl ); + return; + } + // PI case + if ( Hop_ObjIsPi(pObj) ) + { + fprintf( pFile, "%s%s", fCompl? "~" : "", pObj->pData ); + return; + } + // EXOR case + if ( Hop_ObjIsExor(pObj) ) + { + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry( vLevels, Level ); + Hop_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " ^ " ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; + } + // MUX case + if ( Hop_ObjIsMuxType(pObj) ) + { + if ( Hop_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) + { + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1 ); + fprintf( pFile, " ^ " ); + Hop_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 ); + fprintf( pFile, "%s", (Level==0? "" : ")") ); + } + else + { + pFaninC = Hop_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Hop_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 ); + fprintf( pFile, " ? " ); + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin1, fCompl), vLevels, Level+1 ); + fprintf( pFile, " : " ); + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1 ); + fprintf( pFile, "%s", (Level==0? "" : ")") ); + } + return; + } + // AND case + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry(vLevels, Level); + Hop_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, fCompl), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " %s ", fCompl? "|" : "&" ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; +} + + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig ) +{ + assert( !Hop_IsComplement(pObj) ); + printf( "Node %p : ", pObj ); + if ( Hop_ObjIsConst1(pObj) ) + printf( "constant 1" ); + else if ( Hop_ObjIsPi(pObj) ) + printf( "PI" ); + else + printf( "AND( %p%s, %p%s )", + Hop_ObjFanin0(pObj), (Hop_ObjFaninC0(pObj)? "\'" : " "), + Hop_ObjFanin1(pObj), (Hop_ObjFaninC1(pObj)? "\'" : " ") ); + printf( " (refs = %3d)", Hop_ObjRefs(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i; + printf( "PIs: " ); + Hop_ManForEachPi( p, pObj, i ) + printf( " %p", pObj ); + printf( "\n" ); + vNodes = Hop_ManDfs( p ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + Hop_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the AIG into the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj, * pConst1 = NULL; + int i, nDigits, Counter = 0; + if ( Hop_ManPoNum(p) == 0 ) + { + printf( "Hop_ManDumpBlif(): AIG manager does not have POs.\n" ); + return; + } + // collect nodes in the DFS order + vNodes = Hop_ManDfs( p ); + // assign IDs to objects + Hop_ManConst1(p)->pData = (void *)Counter++; + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = (void *)Counter++; + Hop_ManForEachPo( p, pObj, i ) + pObj->pData = (void *)Counter++; + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pData = (void *)Counter++; + nDigits = Hop_Base10Log( Counter ); + // write the file + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# BLIF file written by procedure Hop_ManDumpBlif() in ABC\n" ); + fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); + fprintf( pFile, ".model test\n" ); + // write PIs + fprintf( pFile, ".inputs" ); + Hop_ManForEachPi( p, pObj, i ) + fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData ); + fprintf( pFile, "\n" ); + // write POs + fprintf( pFile, ".outputs" ); + Hop_ManForEachPo( p, pObj, i ) + fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData ); + fprintf( pFile, "\n" ); + // write nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + fprintf( pFile, ".names n%0*d n%0*d n%0*d\n", + nDigits, (int)Hop_ObjFanin0(pObj)->pData, + nDigits, (int)Hop_ObjFanin1(pObj)->pData, + nDigits, (int)pObj->pData ); + fprintf( pFile, "%d%d 1\n", !Hop_ObjFaninC0(pObj), !Hop_ObjFaninC1(pObj) ); + } + // write POs + Hop_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, ".names n%0*d n%0*d\n", + nDigits, (int)Hop_ObjFanin0(pObj)->pData, + nDigits, (int)pObj->pData ); + fprintf( pFile, "%d 1\n", !Hop_ObjFaninC0(pObj) ); + if ( Hop_ObjIsConst1(Hop_ObjFanin0(pObj)) ) + pConst1 = Hop_ManConst1(p); + } + if ( pConst1 ) + fprintf( pFile, ".names n%0*d\n 1\n", nDigits, (int)pConst1->pData ); + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); + Vec_PtrFree( vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/hop/hop_.c b/abc70930/src/aig/hop/hop_.c new file mode 100644 index 00000000..468413fa --- /dev/null +++ b/abc70930/src/aig/hop/hop_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [ivy_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/hop/module.make b/abc70930/src/aig/hop/module.make new file mode 100644 index 00000000..b06d91fd --- /dev/null +++ b/abc70930/src/aig/hop/module.make @@ -0,0 +1,9 @@ +SRC += src/aig/hop/hopBalance.c \ + src/aig/hop/hopCheck.c \ + src/aig/hop/hopDfs.c \ + src/aig/hop/hopMan.c \ + src/aig/hop/hopMem.c \ + src/aig/hop/hopObj.c \ + src/aig/hop/hopOper.c \ + src/aig/hop/hopTable.c \ + src/aig/hop/hopUtil.c diff --git a/abc70930/src/aig/ioa/ioa.h b/abc70930/src/aig/ioa/ioa.h new file mode 100644 index 00000000..3458d12e --- /dev/null +++ b/abc70930/src/aig/ioa/ioa.h @@ -0,0 +1,80 @@ +/**CFile**************************************************************** + + FileName [ioa.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: ioa.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __IOA_H__ +#define __IOA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "vec.h" +#include "bar.h" +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== ioaReadAig.c ========================================================*/ +extern Aig_Man_t * Ioa_ReadAiger( char * pFileName, int fCheck ); +/*=== ioaWriteAig.c =======================================================*/ +extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols ); +/*=== ioaUtil.c =======================================================*/ +extern int Ioa_FileSize( char * pFileName ); +extern char * Ioa_FileNameGeneric( char * FileName ); +extern char * Ioa_TimeStamp(); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/ioa/ioaReadAig.c b/abc70930/src/aig/ioa/ioaReadAig.c new file mode 100644 index 00000000..937e446f --- /dev/null +++ b/abc70930/src/aig/ioa/ioaReadAig.c @@ -0,0 +1,312 @@ +/**CFile**************************************************************** + + FileName [ioaReadAiger.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioaReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ioa.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +unsigned Ioa_ReadAigerDecode( char ** ppPos ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ioa_ReadAiger( char * pFileName, int fCheck ) +{ + Bar_Progress_t * pProgress; + FILE * pFile; + Vec_Ptr_t * vNodes, * vDrivers;//, * vTerms; + Aig_Obj_t * pObj, * pNode0, * pNode1; + Aig_Man_t * pManNew; + int nTotal, nInputs, nOutputs, nLatches, nAnds, nFileSize, i;//, iTerm, nDigits; + char * pContents, * pDrivers, * pSymbols, * pCur, * pName;//, * pType; + unsigned uLit0, uLit1, uLit; + + // read the file into the buffer + nFileSize = Ioa_FileSize( pFileName ); + pFile = fopen( pFileName, "rb" ); + pContents = ALLOC( char, nFileSize ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + + // check if the input file format is correct + if ( strncmp(pContents, "aig", 3) != 0 ) + { + fprintf( stdout, "Wrong input file format.\n" ); + return NULL; + } + + // read the file type + pCur = pContents; while ( *pCur++ != ' ' ); + // read the number of objects + nTotal = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of inputs + nInputs = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of latches + nLatches = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of outputs + nOutputs = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of nodes + nAnds = atoi( pCur ); while ( *pCur++ != '\n' ); + // check the parameters + if ( nTotal != nInputs + nLatches + nAnds ) + { + fprintf( stdout, "The paramters are wrong.\n" ); + return NULL; + } + + // allocate the empty AIG + pManNew = Aig_ManStart( nAnds ); + pName = Ioa_FileNameGeneric( pFileName ); + pManNew->pName = Aig_UtilStrsav( pName ); +// pManNew->pSpec = Ioa_UtilStrsav( pFileName ); + free( pName ); + + // prepare the array of nodes + vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); + Vec_PtrPush( vNodes, Aig_ManConst0(pManNew) ); + + // create the PIs + for ( i = 0; i < nInputs + nLatches; i++ ) + { + pObj = Aig_ObjCreatePi(pManNew); + Vec_PtrPush( vNodes, pObj ); + } +/* + // create the POs + for ( i = 0; i < nOutputs + nLatches; i++ ) + { + pObj = Aig_ObjCreatePo(pManNew); + } +*/ + // create the latches + pManNew->nRegs = nLatches; +/* + nDigits = Ioa_Base10Log( nLatches ); + for ( i = 0; i < nLatches; i++ ) + { + pObj = Aig_ObjCreateLatch(pManNew); + Aig_LatchSetInit0( pObj ); + pNode0 = Aig_ObjCreateBi(pManNew); + pNode1 = Aig_ObjCreateBo(pManNew); + Aig_ObjAddFanin( pObj, pNode0 ); + Aig_ObjAddFanin( pNode1, pObj ); + Vec_PtrPush( vNodes, pNode1 ); + // assign names to latch and its input +// Aig_ObjAssignName( pObj, Aig_ObjNameDummy("_L", i, nDigits), NULL ); +// printf( "Creating latch %s with input %d and output %d.\n", Aig_ObjName(pObj), pNode0->Id, pNode1->Id ); + } +*/ + + // remember the beginning of latch/PO literals + pDrivers = pCur; + + // scroll to the beginning of the binary data + for ( i = 0; i < nLatches + nOutputs; ) + if ( *pCur++ == '\n' ) + i++; + + // create the AND gates + pProgress = Bar_ProgressStart( stdout, nAnds ); + for ( i = 0; i < nAnds; i++ ) + { + Bar_ProgressUpdate( pProgress, i, NULL ); + uLit = ((i + 1 + nInputs + nLatches) << 1); + uLit1 = uLit - Ioa_ReadAigerDecode( &pCur ); + uLit0 = uLit1 - Ioa_ReadAigerDecode( &pCur ); +// assert( uLit1 > uLit0 ); + pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); + pNode1 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); + assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches ); + Vec_PtrPush( vNodes, Aig_And(pManNew, pNode0, pNode1) ); + } + Bar_ProgressStop( pProgress ); + + // remember the place where symbols begin + pSymbols = pCur; + + // read the latch driver literals + vDrivers = Vec_PtrAlloc( nLatches + nOutputs ); + pCur = pDrivers; +// Aig_ManForEachLatchInput( pManNew, pObj, i ) + for ( i = 0; i < nLatches; i++ ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); +// Aig_ObjAddFanin( pObj, pNode0 ); + Vec_PtrPush( vDrivers, pNode0 ); + } + // read the PO driver literals +// Aig_ManForEachPo( pManNew, pObj, i ) + for ( i = 0; i < nOutputs; i++ ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); +// Aig_ObjAddFanin( pObj, pNode0 ); + Vec_PtrPush( vDrivers, pNode0 ); + } + + + // create the POs + for ( i = 0; i < nOutputs; i++ ) + Aig_ObjCreatePo( pManNew, Vec_PtrEntry(vDrivers, nLatches + i) ); + for ( i = 0; i < nLatches; i++ ) + Aig_ObjCreatePo( pManNew, Vec_PtrEntry(vDrivers, i) ); + Vec_PtrFree( vDrivers ); + +/* + // read the names if present + pCur = pSymbols; + if ( *pCur != 'c' ) + { + int Counter = 0; + while ( pCur < pContents + nFileSize && *pCur != 'c' ) + { + // get the terminal type + pType = pCur; + if ( *pCur == 'i' ) + vTerms = pManNew->vPis; + else if ( *pCur == 'l' ) + vTerms = pManNew->vBoxes; + else if ( *pCur == 'o' ) + vTerms = pManNew->vPos; + else + { + fprintf( stdout, "Wrong terminal type.\n" ); + return NULL; + } + // get the terminal number + iTerm = atoi( ++pCur ); while ( *pCur++ != ' ' ); + // get the node + if ( iTerm >= Vec_PtrSize(vTerms) ) + { + fprintf( stdout, "The number of terminal is out of bound.\n" ); + return NULL; + } + pObj = Vec_PtrEntry( vTerms, iTerm ); + if ( *pType == 'l' ) + pObj = Aig_ObjFanout0(pObj); + // assign the name + pName = pCur; while ( *pCur++ != '\n' ); + // assign this name + *(pCur-1) = 0; + Aig_ObjAssignName( pObj, pName, NULL ); + if ( *pType == 'l' ) + { + Aig_ObjAssignName( Aig_ObjFanin0(pObj), Aig_ObjName(pObj), "L" ); + Aig_ObjAssignName( Aig_ObjFanin0(Aig_ObjFanin0(pObj)), Aig_ObjName(pObj), "_in" ); + } + // mark the node as named + pObj->pCopy = (Aig_Obj_t *)Aig_ObjName(pObj); + } + + // assign the remaining names + Aig_ManForEachPi( pManNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); + Counter++; + } + Aig_ManForEachLatchOutput( pManNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); + Aig_ObjAssignName( Aig_ObjFanin0(pObj), Aig_ObjName(pObj), "L" ); + Aig_ObjAssignName( Aig_ObjFanin0(Aig_ObjFanin0(pObj)), Aig_ObjName(pObj), "_in" ); + Counter++; + } + Aig_ManForEachPo( pManNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); + Counter++; + } + if ( Counter ) + printf( "Ioa_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter ); + } + else + { +// printf( "Ioa_ReadAiger(): I/O/register names are not given. Generating short names.\n" ); + Aig_ManShortNames( pManNew ); + } +*/ + + // skipping the comments + free( pContents ); + Vec_PtrFree( vNodes ); + + // remove the extra nodes + Aig_ManCleanup( pManNew ); + + // check the result + if ( fCheck && !Aig_ManCheck( pManNew ) ) + { + printf( "Ioa_ReadAiger: The network check has failed.\n" ); + Aig_ManStop( pManNew ); + return NULL; + } + return pManNew; +} + + +/**Function************************************************************* + + Synopsis [Extracts one unsigned AIG edge from the input buffer.] + + Description [This procedure is a slightly modified version of Armin Biere's + procedure "unsigned decode (FILE * file)". ] + + SideEffects [Updates the current reading position.] + + SeeAlso [] + +***********************************************************************/ +unsigned Ioa_ReadAigerDecode( char ** ppPos ) +{ + unsigned x = 0, i = 0; + unsigned char ch; + +// while ((ch = getnoneofch (file)) & 0x80) + while ((ch = *(*ppPos)++) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + + return x | (ch << (7 * i)); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ioa/ioaUtil.c b/abc70930/src/aig/ioa/ioaUtil.c new file mode 100644 index 00000000..79dcca1e --- /dev/null +++ b/abc70930/src/aig/ioa/ioaUtil.c @@ -0,0 +1,117 @@ +/**CFile**************************************************************** + + FileName [ioaUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioaUtil.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ioa.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the file size.] + + Description [The file should be closed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ioa_FileSize( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Ioa_FileSize(): The file is unavailable (absent or open).\n" ); + return 0; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + fclose( pFile ); + return nFileSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ioa_FileNameGeneric( char * FileName ) +{ + char * pDot; + char * pUnd; + char * pRes; + + // find the generic name of the file + pRes = Aig_UtilStrsav( FileName ); + // find the pointer to the "." symbol in the file name +// pUnd = strstr( FileName, "_" ); + pUnd = NULL; + pDot = strstr( FileName, "." ); + if ( pUnd ) + pRes[pUnd - FileName] = 0; + else if ( pDot ) + pRes[pDot - FileName] = 0; + return pRes; +} + +/**Function************************************************************* + + Synopsis [Returns the time stamp.] + + Description [The file should be closed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ioa_TimeStamp() +{ + static char Buffer[100]; + char * TimeStamp; + time_t ltime; + // get the current time + time( <ime ); + TimeStamp = asctime( localtime( <ime ) ); + TimeStamp[ strlen(TimeStamp) - 1 ] = 0; + strcpy( Buffer, TimeStamp ); + return Buffer; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ioa/ioaWriteAig.c b/abc70930/src/aig/ioa/ioaWriteAig.c new file mode 100644 index 00000000..a6c23fd4 --- /dev/null +++ b/abc70930/src/aig/ioa/ioaWriteAig.c @@ -0,0 +1,292 @@ +/**CFile**************************************************************** + + FileName [ioaWriteAiger.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioaWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ioa.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + The following is taken from the AIGER format description, + which can be found at http://fmv.jku.at/aiger +*/ + + +/* + The AIGER And-Inverter Graph (AIG) Format Version 20061129 + ---------------------------------------------------------- + Armin Biere, Johannes Kepler University, 2006 + + This report describes the AIG file format as used by the AIGER library. + The purpose of this report is not only to motivate and document the + format, but also to allow independent implementations of writers and + readers by giving precise and unambiguous definitions. + + ... + +Introduction + + The name AIGER contains as one part the acronym AIG of And-Inverter + Graphs and also if pronounced in German sounds like the name of the + 'Eiger', a mountain in the Swiss alps. This choice should emphasize the + origin of this format. It was first openly discussed at the Alpine + Verification Meeting 2006 in Ascona as a way to provide a simple, compact + file format for a model checking competition affiliated to CAV 2007. + + ... + +Binary Format Definition + + The binary format is semantically a subset of the ASCII format with a + slightly different syntax. The binary format may need to reencode + literals, but translating a file in binary format into ASCII format and + then back in to binary format will result in the same file. + + The main differences of the binary format to the ASCII format are as + follows. After the header the list of input literals and all the + current state literals of a latch can be omitted. Furthermore the + definitions of the AND gates are binary encoded. However, the symbol + table and the comment section are as in the ASCII format. + + The header of an AIGER file in binary format has 'aig' as format + identifier, but otherwise is identical to the ASCII header. The standard + file extension for the binary format is therefore '.aig'. + + A header for the binary format is still in ASCII encoding: + + aig M I L O A + + Constants, variables and literals are handled in the same way as in the + ASCII format. The first simplifying restriction is on the variable + indices of inputs and latches. The variable indices of inputs come first, + followed by the pseudo-primary inputs of the latches and then the variable + indices of all LHS of AND gates: + + input variable indices 1, 2, ... , I + latch variable indices I+1, I+2, ... , (I+L) + AND variable indices I+L+1, I+L+2, ... , (I+L+A) == M + + The corresponding unsigned literals are + + input literals 2, 4, ... , 2*I + latch literals 2*I+2, 2*I+4, ... , 2*(I+L) + AND literals 2*(I+L)+2, 2*(I+L)+4, ... , 2*(I+L+A) == 2*M + + All literals have to be defined, and therefore 'M = I + L + A'. With this + restriction it becomes possible that the inputs and the current state + literals of the latches do not have to be listed explicitly. Therefore, + after the header only the list of 'L' next state literals follows, one per + latch on a single line, and then the 'O' outputs, again one per line. + + In the binary format we assume that the AND gates are ordered and respect + the child parent relation. AND gates with smaller literals on the LHS + come first. Therefore we can assume that the literals on the right-hand + side of a definition of an AND gate are smaller than the LHS literal. + Furthermore we can sort the literals on the RHS, such that the larger + literal comes first. A definition thus consists of three literals + + lhs rhs0 rhs1 + + with 'lhs' even and 'lhs > rhs0 >= rhs1'. Also the variable indices are + pairwise different to avoid combinational self loops. Since the LHS + indices of the definitions are all consecutive (as even integers), + the binary format does not have to keep 'lhs'. In addition, we can use + the order restriction and only write the differences 'delta0' and 'delta1' + instead of 'rhs0' and 'rhs1', with + + delta0 = lhs - rhs0, delta1 = rhs0 - rhs1 + + The differences will all be strictly positive, and in practice often very + small. We can take advantage of this fact by the simple little-endian + encoding of unsigned integers of the next section. After the binary delta + encoding of the RHSs of all AND gates, the optional symbol table and + optional comment section start in the same format as in the ASCII case. + + ... + +*/ + +static unsigned Ioa_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } +static unsigned Ioa_ObjAigerNum( Aig_Obj_t * pObj ) { return (unsigned)pObj->pData; } +static void Ioa_ObjSetAigerNum( Aig_Obj_t * pObj, unsigned Num ) { pObj->pData = (void *)Num; } + +int Ioa_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols ) +{ + Bar_Progress_t * pProgress; + FILE * pFile; + Aig_Obj_t * pObj, * pDriver; + int i, nNodes, Pos, nBufferSize; + unsigned char * pBuffer; + unsigned uLit0, uLit1, uLit; + +// assert( Aig_ManIsStrash(pMan) ); + // start the output stream + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Ioa_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } +/* + Aig_ManForEachLatch( pMan, pObj, i ) + if ( !Aig_LatchIsInit0(pObj) ) + { + fprintf( stdout, "Ioa_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" ); + return; + } +*/ + // set the node numbers to be used in the output file + nNodes = 0; + Ioa_ObjSetAigerNum( Aig_ManConst1(pMan), nNodes++ ); + Aig_ManForEachPi( pMan, pObj, i ) + Ioa_ObjSetAigerNum( pObj, nNodes++ ); + Aig_ManForEachNode( pMan, pObj, i ) + Ioa_ObjSetAigerNum( pObj, nNodes++ ); + + // write the header "M I L O A" where M = I + L + A + fprintf( pFile, "aig %u %u %u %u %u\n", + Aig_ManPiNum(pMan) + Aig_ManNodeNum(pMan), + Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan), + Aig_ManRegNum(pMan), + Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan), + Aig_ManNodeNum(pMan) ); + + // if the driver node is a constant, we need to complement the literal below + // because, in the AIGER format, literal 0/1 is represented as number 0/1 + // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0 + + // write latch drivers + Aig_ManForEachLiSeq( pMan, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); + } + + // write PO drivers + Aig_ManForEachPoSeq( pMan, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); + } + + // write the nodes into the buffer + Pos = 0; + nBufferSize = 6 * Aig_ManNodeNum(pMan) + 100; // skeptically assuming 3 chars per one AIG edge + pBuffer = ALLOC( char, nBufferSize ); + pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(pMan) ); + Aig_ManForEachNode( pMan, pObj, i ) + { + Bar_ProgressUpdate( pProgress, i, NULL ); + uLit = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pObj), 0 ); + uLit0 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); + uLit1 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); + assert( uLit0 < uLit1 ); + Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); + Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); + if ( Pos > nBufferSize - 10 ) + { + printf( "Ioa_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); + fclose( pFile ); + return; + } + } + assert( Pos < nBufferSize ); + Bar_ProgressStop( pProgress ); + + // write the buffer + fwrite( pBuffer, 1, Pos, pFile ); + free( pBuffer ); +/* + // write the symbol table + if ( fWriteSymbols ) + { + // write PIs + Aig_ManForEachPi( pMan, pObj, i ) + fprintf( pFile, "i%d %s\n", i, Aig_ObjName(pObj) ); + // write latches + Aig_ManForEachLatch( pMan, pObj, i ) + fprintf( pFile, "l%d %s\n", i, Aig_ObjName(Aig_ObjFanout0(pObj)) ); + // write POs + Aig_ManForEachPo( pMan, pObj, i ) + fprintf( pFile, "o%d %s\n", i, Aig_ObjName(pObj) ); + } +*/ + // write the comment + fprintf( pFile, "c\n" ); + if ( pMan->pName ) + fprintf( pFile, ".model %s\n", pMan->pName ); + fprintf( pFile, "This file was produced by the AIG package in ABC on %s\n", Ioa_TimeStamp() ); + fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Adds one unsigned AIG edge to the output buffer.] + + Description [This procedure is a slightly modified version of Armin Biere's + procedure "void encode (FILE * file, unsigned x)" ] + + SideEffects [Returns the current writing position.] + + SeeAlso [] + +***********************************************************************/ +int Ioa_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; +// putc (ch, file); + pBuffer[Pos++] = ch; + x >>= 7; + } + ch = x; +// putc (ch, file); + pBuffer[Pos++] = ch; + return Pos; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ioa/module.make b/abc70930/src/aig/ioa/module.make new file mode 100644 index 00000000..66b4a0d5 --- /dev/null +++ b/abc70930/src/aig/ioa/module.make @@ -0,0 +1,3 @@ +SRC += src/aig/ioa/ioaReadAig.c \ + src/aig/ioa/ioaWriteAig.c \ + src/aig/ioa/ioaUtil.c diff --git a/abc70930/src/aig/ivy/attr.h b/abc70930/src/aig/ivy/attr.h new file mode 100644 index 00000000..16cf0b84 --- /dev/null +++ b/abc70930/src/aig/ivy/attr.h @@ -0,0 +1,414 @@ +/**CFile**************************************************************** + + FileName [attr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network attributes.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: attr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __ATTR_H__ +#define __ATTR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Attr_ManStruct_t_ Attr_Man_t; +struct Attr_ManStruct_t_ +{ + // attribute info + int nAttrSize; // the size of each attribute in bytes + Extra_MmFixed_t * pManMem; // memory manager for attributes + int nAttrs; // the number of attributes allocated + void ** pAttrs; // the array of attributes + int fUseInt; // uses integer attributes + // attribute specific info + void * pManAttr; // the manager for this attribute + void (*pFuncFreeMan) (void *); // the procedure to call to free attribute-specific manager + void (*pFuncFreeObj) (void *, void *); // the procedure to call to free attribute-specific data +}; + +// at any time, an attribute of the given ID can be +// - not available (p->nAttrs < Id) +// - available but not allocated (p->nAttrs >= Id && p->pAttrs[Id] == NULL) +// - available and allocated (p->nAttrs >= Id && p->pAttrs[Id] != NULL) + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the attribute manager.] + + Description [The manager is simple if it does not need memory manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManAlloc( int nAttrSize, int fManMem ) +{ + Attr_Man_t * p; + p = ALLOC( Attr_Man_t, 1 ); + memset( p, 0, sizeof(Attr_Man_t) ); + p->nAttrSize = nAttrSize; + if ( fManMem ) + p->pManMem = Extra_MmFixedStart( nAttrSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Start the attribute manager for integers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManStartInt( int nAttrs ) +{ + Attr_Man_t * p; + p = Attr_ManAlloc( sizeof(int), 0 ); + p->nAttrs = nAttrs; + p->pAttrs = (void **)ALLOC( int, nAttrs ); + memset( (int *)p->pAttrs, 0, sizeof(int) * nAttrs ); + p->fUseInt = 1; + return p; +} + +/**Function************************************************************* + + Synopsis [Start the attribute manager for pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManStartPtr( int nAttrs ) +{ + Attr_Man_t * p; + p = Attr_ManAlloc( sizeof(void *), 0 ); + p->nAttrs = nAttrs; + p->pAttrs = ALLOC( void *, nAttrs ); + memset( p->pAttrs, 0, sizeof(void *) * nAttrs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Start the attribute manager for the fixed entry size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManStartPtrMem( int nAttrs, int nAttrSize ) +{ + Attr_Man_t * p; + int i; + p = Attr_ManAlloc( nAttrSize, 1 ); + p->nAttrs = nAttrs; + p->pAttrs = ALLOC( void *, nAttrs ); + for ( i = 0; i < p->nAttrs; i++ ) + { + p->pAttrs[i] = Extra_MmFixedEntryFetch( p->pManMem ); + memset( p->pAttrs[i], 0, nAttrSize ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [Stop the attribute manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManStop( Attr_Man_t * p ) +{ + // free the attributes of objects + if ( p->pFuncFreeObj ) + { + int i; + if ( p->fUseInt ) + { + for ( i = 0; i < p->nAttrs; i++ ) + if ( ((int *)p->pAttrs)[i] ) + p->pFuncFreeObj( p->pManAttr, (void *)((int *)p->pAttrs)[i] ); + } + else + { + for ( i = 0; i < p->nAttrs; i++ ) + if ( p->pAttrs[i] ) + p->pFuncFreeObj( p->pManAttr, p->pAttrs[i] ); + } + } + // free the attribute manager + if ( p->pManAttr && p->pFuncFreeMan ) + p->pFuncFreeMan( p->pManAttr ); + // free the memory manager + if ( p->pManMem ) + Extra_MmFixedStop( p->pManMem); + // free the attribute manager + FREE( p->pAttrs ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Reads the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Attr_ManReadAttrInt( Attr_Man_t * p, int Id ) +{ + assert( p->fUseInt ); + if ( Id >= p->nAttrs ) + return 0; + return ((int *)p->pAttrs)[Id]; +} + +/**Function************************************************************* + + Synopsis [Reads the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Attr_ManReadAttrPtr( Attr_Man_t * p, int Id ) +{ + assert( !p->fUseInt ); + if ( Id >= p->nAttrs ) + return NULL; + return p->pAttrs[Id]; +} + +/**Function************************************************************* + + Synopsis [Writes the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManWriteAttrInt( Attr_Man_t * p, int Id, int Attr ) +{ + assert( p->fUseInt ); + ((int *)p->pAttrs)[Id] = Attr; +} + +/**Function************************************************************* + + Synopsis [Writes the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManWriteAttrPtr( Attr_Man_t * p, int Id, void * pAttr ) +{ + assert( !p->fUseInt ); + assert( p->pManMem == NULL ); + p->pAttrs[Id] = pAttr; +} + +/**Function************************************************************* + + Synopsis [Returns or creates the pointer to the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int * Attr_ManFetchSpotInt( Attr_Man_t * p, int Id ) +{ + assert( p->fUseInt ); + if ( Id >= p->nAttrs ) + { + // save the old size + int i, nAttrsOld = p->nAttrs; + // get the new size + p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024; + p->pAttrs = realloc( p->pAttrs, sizeof(int) * p->nAttrs ); + // fill in the empty spots + for ( i = nAttrsOld; i < p->nAttrs; i++ ) + ((int *)p->pAttrs)[Id] = 0; + } + return ((int *)p->pAttrs) + Id; +} + +/**Function************************************************************* + + Synopsis [Returns or creates the pointer to the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void ** Attr_ManFetchSpotPtr( Attr_Man_t * p, int Id ) +{ + assert( !p->fUseInt ); + if ( Id >= p->nAttrs ) + { + // save the old size + int i, nAttrsOld = p->nAttrs; + // get the new size + p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024; + p->pAttrs = realloc( p->pAttrs, sizeof(void *) * p->nAttrs ); + // fill in the empty spots + for ( i = nAttrsOld; i < p->nAttrs; i++ ) + p->pAttrs[Id] = NULL; + } + // if memory manager is available but entry is not created, create it + if ( p->pManMem && p->pAttrs[Id] != NULL ) + { + p->pAttrs[Id] = Extra_MmFixedEntryFetch( p->pManMem ); + memset( p->pAttrs[Id], 0, p->nAttrSize ); + } + return p->pAttrs + Id; +} + + +/**Function************************************************************* + + Synopsis [Returns or creates the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Attr_ManFetchAttrInt( Attr_Man_t * p, int Id ) +{ + return *Attr_ManFetchSpotInt( p, Id ); +} + +/**Function************************************************************* + + Synopsis [Returns or creates the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Attr_ManFetchAttrPtr( Attr_Man_t * p, int Id ) +{ + return *Attr_ManFetchSpotPtr( p, Id ); +} + +/**Function************************************************************* + + Synopsis [Sets the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManSetAttrInt( Attr_Man_t * p, int Id, int Attr ) +{ + *Attr_ManFetchSpotInt( p, Id ) = Attr; +} + +/**Function************************************************************* + + Synopsis [Sets the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManSetAttrPtr( Attr_Man_t * p, int Id, void * pAttr ) +{ + assert( p->pManMem == NULL ); + *Attr_ManFetchSpotPtr( p, Id ) = pAttr; +} + + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/ivy/ivy.h b/abc70930/src/aig/ivy/ivy.h new file mode 100644 index 00000000..ed19d67c --- /dev/null +++ b/abc70930/src/aig/ivy/ivy.h @@ -0,0 +1,557 @@ +/**CFile**************************************************************** + + FileName [ivy.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivy.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __IVY_H__ +#define __IVY_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "extra.h" +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ivy_Man_t_ Ivy_Man_t; +typedef struct Ivy_Obj_t_ Ivy_Obj_t; +typedef int Ivy_Edge_t; +typedef struct Ivy_FraigParams_t_ Ivy_FraigParams_t; + +// object types +typedef enum { + IVY_NONE, // 0: non-existent object + IVY_PI, // 1: primary input (and constant 1 node) + IVY_PO, // 2: primary output + IVY_ASSERT, // 3: assertion + IVY_LATCH, // 4: sequential element + IVY_AND, // 5: AND node + IVY_EXOR, // 6: EXOR node + IVY_BUF, // 7: buffer (temporary) + IVY_VOID // 8: unused object +} Ivy_Type_t; + +// latch initial values +typedef enum { + IVY_INIT_NONE, // 0: not a latch + IVY_INIT_0, // 1: zero + IVY_INIT_1, // 2: one + IVY_INIT_DC // 3: don't-care +} Ivy_Init_t; + +// the AIG node +struct Ivy_Obj_t_ // 24 bytes (32-bit) or 32 bytes (64-bit) // 10 words - 16 words +{ + int Id; // integer ID + int TravId; // traversal ID + unsigned Type : 4; // object type + unsigned fMarkA : 1; // multipurpose mask + unsigned fMarkB : 1; // multipurpose mask + unsigned fExFan : 1; // set to 1 if last fanout added is EXOR + unsigned fPhase : 1; // value under 000...0 pattern + unsigned fFailTfo : 1; // the TFO of the failed node + unsigned Init : 2; // latch initial value + unsigned Level : 21; // logic level + int nRefs; // reference counter + Ivy_Obj_t * pFanin0; // fanin + Ivy_Obj_t * pFanin1; // fanin + Ivy_Obj_t * pFanout; // fanout + Ivy_Obj_t * pNextFan0; // next fanout of the first fanin + Ivy_Obj_t * pNextFan1; // next fanout of the second fanin + Ivy_Obj_t * pPrevFan0; // prev fanout of the first fanin + Ivy_Obj_t * pPrevFan1; // prev fanout of the second fanin + Ivy_Obj_t * pEquiv; // equivalent node +}; + +// the AIG manager +struct Ivy_Man_t_ +{ + // AIG nodes + Vec_Ptr_t * vPis; // the array of PIs + Vec_Ptr_t * vPos; // the array of POs + Vec_Ptr_t * vBufs; // the array of buffers + Vec_Ptr_t * vObjs; // the array of objects + Ivy_Obj_t * pConst1; // the constant 1 node + Ivy_Obj_t Ghost; // the ghost node + // AIG node counters + int nObjs[IVY_VOID];// the number of objects by type + int nCreated; // the number of created objects + int nDeleted; // the number of deleted objects + // stuctural hash table + int * pTable; // structural hash table + int nTableSize; // structural hash table size + // various data members + int fCatchExor; // set to 1 to detect EXORs + int nTravIds; // the traversal ID + int nLevelMax; // the maximum level + Vec_Int_t * vRequired; // required times + int fFanout; // fanout is allocated + void * pData; // the temporary data + void * pCopy; // the temporary data + Ivy_Man_t * pHaig; // history AIG if present + int nClassesSkip; // the number of skipped classes + // memory management + Vec_Ptr_t * vChunks; // allocated memory pieces + Vec_Ptr_t * vPages; // memory pages used by nodes + Ivy_Obj_t * pListFree; // the list of free nodes + // timing statistics + int time1; + int time2; +}; + +struct Ivy_FraigParams_t_ +{ + int nSimWords; // the number of words in the simulation info + double dSimSatur; // the ratio of refined classes when saturation is reached + int fPatScores; // enables simulation pattern scoring + int MaxScore; // max score after which resimulation is used + double dActConeRatio; // the ratio of cone to be bumped + double dActConeBumpMax; // the largest bump in activity + int fProve; // prove the miter outputs + int fVerbose; // verbose output + int fDoSparse; // skip sparse functions + int nBTLimitNode; // conflict limit at a node + int nBTLimitMiter; // conflict limit at an output +// int nBTLimitGlobal; // conflict limit global +// int nInsLimitNode; // inspection limit at a node +// int nInsLimitMiter; // inspection limit at an output +// int nInsLimitGlobal; // inspection limit global +}; + + +#define IVY_CUT_LIMIT 256 +#define IVY_CUT_INPUT 6 + +typedef struct Ivy_Cut_t_ Ivy_Cut_t; +struct Ivy_Cut_t_ +{ + int nLatches; + short nSize; + short nSizeMax; + int pArray[IVY_CUT_INPUT]; + unsigned uHash; +}; + +typedef struct Ivy_Store_t_ Ivy_Store_t; +struct Ivy_Store_t_ +{ + int nCuts; + int nCutsM; + int nCutsMax; + int fSatur; + Ivy_Cut_t pCuts[IVY_CUT_LIMIT]; // storage for cuts +}; + +#define IVY_LEAF_MASK 255 +#define IVY_LEAF_BITS 8 + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IVY_MIN(a,b) (((a) < (b))? (a) : (b)) +#define IVY_MAX(a,b) (((a) > (b))? (a) : (b)) + +static inline int Ivy_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } +static inline int Ivy_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline int Ivy_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } +static inline void Ivy_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } +static inline void Ivy_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } + +static inline Ivy_Obj_t * Ivy_Regular( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned long)(p) & ~01); } +static inline Ivy_Obj_t * Ivy_Not( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned long)(p) ^ 01); } +static inline Ivy_Obj_t * Ivy_NotCond( Ivy_Obj_t * p, int c ) { return (Ivy_Obj_t *)((unsigned long)(p) ^ (c)); } +static inline int Ivy_IsComplement( Ivy_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } + +static inline Ivy_Obj_t * Ivy_ManConst0( Ivy_Man_t * p ) { return Ivy_Not(p->pConst1); } +static inline Ivy_Obj_t * Ivy_ManConst1( Ivy_Man_t * p ) { return p->pConst1; } +static inline Ivy_Obj_t * Ivy_ManGhost( Ivy_Man_t * p ) { return &p->Ghost; } +static inline Ivy_Obj_t * Ivy_ManPi( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPis, i); } +static inline Ivy_Obj_t * Ivy_ManPo( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPos, i); } +static inline Ivy_Obj_t * Ivy_ManObj( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vObjs, i); } + +static inline Ivy_Edge_t Ivy_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } +static inline int Ivy_EdgeId( Ivy_Edge_t Edge ) { return Edge >> 1; } +static inline int Ivy_EdgeIsComplement( Ivy_Edge_t Edge ) { return Edge & 1; } +static inline Ivy_Edge_t Ivy_EdgeRegular( Ivy_Edge_t Edge ) { return (Edge >> 1) << 1; } +static inline Ivy_Edge_t Ivy_EdgeNot( Ivy_Edge_t Edge ) { return Edge ^ 1; } +static inline Ivy_Edge_t Ivy_EdgeNotCond( Ivy_Edge_t Edge, int fCond ) { return Edge ^ fCond; } +static inline Ivy_Edge_t Ivy_EdgeFromNode( Ivy_Obj_t * pNode ) { return Ivy_EdgeCreate( Ivy_Regular(pNode)->Id, Ivy_IsComplement(pNode) ); } +static inline Ivy_Obj_t * Ivy_EdgeToNode( Ivy_Man_t * p, Ivy_Edge_t Edge ){ return Ivy_NotCond( Ivy_ManObj(p, Ivy_EdgeId(Edge)), Ivy_EdgeIsComplement(Edge) ); } + +static inline int Ivy_LeafCreate( int Id, int Lat ) { return (Id << IVY_LEAF_BITS) | Lat; } +static inline int Ivy_LeafId( int Leaf ) { return Leaf >> IVY_LEAF_BITS; } +static inline int Ivy_LeafLat( int Leaf ) { return Leaf & IVY_LEAF_MASK; } + +static inline int Ivy_ManPiNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PI]; } +static inline int Ivy_ManPoNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PO]; } +static inline int Ivy_ManAssertNum( Ivy_Man_t * p ) { return p->nObjs[IVY_ASSERT]; } +static inline int Ivy_ManLatchNum( Ivy_Man_t * p ) { return p->nObjs[IVY_LATCH]; } +static inline int Ivy_ManAndNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]; } +static inline int Ivy_ManExorNum( Ivy_Man_t * p ) { return p->nObjs[IVY_EXOR]; } +static inline int Ivy_ManBufNum( Ivy_Man_t * p ) { return p->nObjs[IVY_BUF]; } +static inline int Ivy_ManObjNum( Ivy_Man_t * p ) { return p->nCreated - p->nDeleted; } +static inline int Ivy_ManObjIdMax( Ivy_Man_t * p ) { return Vec_PtrSize(p->vObjs)-1; } +static inline int Ivy_ManNodeNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR];} +static inline int Ivy_ManHashObjNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR]+p->nObjs[IVY_LATCH]; } +static inline int Ivy_ManGetCost( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+3*p->nObjs[IVY_EXOR]+8*p->nObjs[IVY_LATCH]; } + +static inline Ivy_Type_t Ivy_ObjType( Ivy_Obj_t * pObj ) { return pObj->Type; } +static inline Ivy_Init_t Ivy_ObjInit( Ivy_Obj_t * pObj ) { return pObj->Init; } +static inline int Ivy_ObjIsConst1( Ivy_Obj_t * pObj ) { return pObj->Id == 0; } +static inline int Ivy_ObjIsGhost( Ivy_Obj_t * pObj ) { return pObj->Id < 0; } +static inline int Ivy_ObjIsNone( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_NONE; } +static inline int Ivy_ObjIsPi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI; } +static inline int Ivy_ObjIsPo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO; } +static inline int Ivy_ObjIsCi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsCo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsAssert( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_ASSERT; } +static inline int Ivy_ObjIsLatch( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsAnd( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND; } +static inline int Ivy_ObjIsExor( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_EXOR; } +static inline int Ivy_ObjIsBuf( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_BUF; } +static inline int Ivy_ObjIsNode( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR; } +static inline int Ivy_ObjIsTerm( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; } +static inline int Ivy_ObjIsHash( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; } + +static inline int Ivy_ObjIsMarkA( Ivy_Obj_t * pObj ) { return pObj->fMarkA; } +static inline void Ivy_ObjSetMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 1; } +static inline void Ivy_ObjClearMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 0; } + +static inline void Ivy_ObjSetTravId( Ivy_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } +static inline void Ivy_ObjSetTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } +static inline void Ivy_ObjSetTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } +static inline int Ivy_ObjIsTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); } +static inline int Ivy_ObjIsTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds - 1); } + +static inline int Ivy_ObjId( Ivy_Obj_t * pObj ) { return pObj->Id; } +static inline int Ivy_ObjTravId( Ivy_Obj_t * pObj ) { return pObj->TravId; } +static inline int Ivy_ObjPhase( Ivy_Obj_t * pObj ) { return pObj->fPhase; } +static inline int Ivy_ObjExorFanout( Ivy_Obj_t * pObj ) { return pObj->fExFan; } +static inline int Ivy_ObjRefs( Ivy_Obj_t * pObj ) { return pObj->nRefs; } +static inline void Ivy_ObjRefsInc( Ivy_Obj_t * pObj ) { pObj->nRefs++; } +static inline void Ivy_ObjRefsDec( Ivy_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } +static inline int Ivy_ObjFaninId0( Ivy_Obj_t * pObj ) { return pObj->pFanin0? Ivy_ObjId(Ivy_Regular(pObj->pFanin0)) : 0; } +static inline int Ivy_ObjFaninId1( Ivy_Obj_t * pObj ) { return pObj->pFanin1? Ivy_ObjId(Ivy_Regular(pObj->pFanin1)) : 0; } +static inline int Ivy_ObjFaninC0( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin0); } +static inline int Ivy_ObjFaninC1( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin1); } +static inline Ivy_Obj_t * Ivy_ObjFanin0( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin0); } +static inline Ivy_Obj_t * Ivy_ObjFanin1( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin1); } +static inline Ivy_Obj_t * Ivy_ObjChild0( Ivy_Obj_t * pObj ) { return pObj->pFanin0; } +static inline Ivy_Obj_t * Ivy_ObjChild1( Ivy_Obj_t * pObj ) { return pObj->pFanin1; } +static inline Ivy_Obj_t * Ivy_ObjChild0Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin0(pObj)? Ivy_NotCond(Ivy_ObjFanin0(pObj)->pEquiv, Ivy_ObjFaninC0(pObj)) : NULL; } +static inline Ivy_Obj_t * Ivy_ObjChild1Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin1(pObj)? Ivy_NotCond(Ivy_ObjFanin1(pObj)->pEquiv, Ivy_ObjFaninC1(pObj)) : NULL; } +static inline Ivy_Obj_t * Ivy_ObjEquiv( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj)->pEquiv? Ivy_NotCond(Ivy_Regular(pObj)->pEquiv, Ivy_IsComplement(pObj)) : NULL; } +static inline int Ivy_ObjLevel( Ivy_Obj_t * pObj ) { return pObj->Level; } +static inline int Ivy_ObjLevelNew( Ivy_Obj_t * pObj ) { return 1 + Ivy_ObjIsExor(pObj) + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level); } +static inline int Ivy_ObjFaninPhase( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj)? !Ivy_Regular(pObj)->fPhase : pObj->fPhase; } + +static inline void Ivy_ObjClean( Ivy_Obj_t * pObj ) +{ + int IdSaved = pObj->Id; + memset( pObj, 0, sizeof(Ivy_Obj_t) ); + pObj->Id = IdSaved; +} +static inline void Ivy_ObjOverwrite( Ivy_Obj_t * pBase, Ivy_Obj_t * pData ) +{ + int IdSaved = pBase->Id; + memcpy( pBase, pData, sizeof(Ivy_Obj_t) ); + pBase->Id = IdSaved; +} +static inline int Ivy_ObjWhatFanin( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanin ) +{ + if ( Ivy_ObjFanin0(pObj) == pFanin ) return 0; + if ( Ivy_ObjFanin1(pObj) == pFanin ) return 1; + assert(0); return -1; +} +static inline int Ivy_ObjFanoutC( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + if ( Ivy_ObjFanin0(pFanout) == pObj ) return Ivy_ObjFaninC0(pObj); + if ( Ivy_ObjFanin1(pFanout) == pObj ) return Ivy_ObjFaninC1(pObj); + assert(0); return -1; +} + +// create the ghost of the new node +static inline Ivy_Obj_t * Ivy_ObjCreateGhost( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type, Ivy_Init_t Init ) +{ + Ivy_Obj_t * pGhost, * pTemp; + assert( Type != IVY_AND || !Ivy_ObjIsConst1(Ivy_Regular(p0)) ); + assert( p1 == NULL || !Ivy_ObjIsConst1(Ivy_Regular(p1)) ); + assert( Type == IVY_PI || Ivy_Regular(p0) != Ivy_Regular(p1) ); + assert( Type != IVY_LATCH || !Ivy_IsComplement(p0) ); +// assert( p1 == NULL || (!Ivy_ObjIsLatch(Ivy_Regular(p0)) || !Ivy_ObjIsLatch(Ivy_Regular(p1))) ); + pGhost = Ivy_ManGhost(p); + pGhost->Type = Type; + pGhost->Init = Init; + pGhost->pFanin0 = p0; + pGhost->pFanin1 = p1; + if ( p1 && Ivy_ObjFaninId0(pGhost) > Ivy_ObjFaninId1(pGhost) ) + pTemp = pGhost->pFanin0, pGhost->pFanin0 = pGhost->pFanin1, pGhost->pFanin1 = pTemp; + return pGhost; +} + +// get the complemented initial state +static Ivy_Init_t Ivy_InitNotCond( Ivy_Init_t Init, int fCompl ) +{ + assert( Init != IVY_INIT_NONE ); + if ( fCompl == 0 ) + return Init; + if ( Init == IVY_INIT_0 ) + return IVY_INIT_1; + if ( Init == IVY_INIT_1 ) + return IVY_INIT_0; + return IVY_INIT_DC; +} + +// get the initial state after forward retiming over AND gate +static Ivy_Init_t Ivy_InitAnd( Ivy_Init_t InitA, Ivy_Init_t InitB ) +{ + assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); + if ( InitA == IVY_INIT_0 || InitB == IVY_INIT_0 ) + return IVY_INIT_0; + if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) + return IVY_INIT_DC; + return IVY_INIT_1; +} + +// get the initial state after forward retiming over EXOR gate +static Ivy_Init_t Ivy_InitExor( Ivy_Init_t InitA, Ivy_Init_t InitB ) +{ + assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); + if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) + return IVY_INIT_DC; + if ( InitA == IVY_INIT_0 && InitB == IVY_INIT_1 ) + return IVY_INIT_1; + if ( InitA == IVY_INIT_1 && InitB == IVY_INIT_0 ) + return IVY_INIT_1; + return IVY_INIT_0; +} + +// internal memory manager +static inline Ivy_Obj_t * Ivy_ManFetchMemory( Ivy_Man_t * p ) +{ + extern void Ivy_ManAddMemory( Ivy_Man_t * p ); + Ivy_Obj_t * pTemp; + if ( p->pListFree == NULL ) + Ivy_ManAddMemory( p ); + pTemp = p->pListFree; + p->pListFree = *((Ivy_Obj_t **)pTemp); + memset( pTemp, 0, sizeof(Ivy_Obj_t) ); + return pTemp; +} +static inline void Ivy_ManRecycleMemory( Ivy_Man_t * p, Ivy_Obj_t * pEntry ) +{ + pEntry->Type = IVY_NONE; // distinquishes dead node from live node + *((Ivy_Obj_t **)pEntry) = p->pListFree; + p->pListFree = pEntry; +} + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the primary inputs +#define Ivy_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPis, pObj, i ) +// iterator over the primary outputs +#define Ivy_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vPos, pObj, i ) +// iterator over all objects, including those currently not used +#define Ivy_ManForEachObj( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else +// iterator over the combinational inputs +#define Ivy_ManForEachCi( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCi(pObj) ) {} else +// iterator over the combinational outputs +#define Ivy_ManForEachCo( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCo(pObj) ) {} else +// iterator over logic nodes (AND and EXOR gates) +#define Ivy_ManForEachNode( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsNode(pObj) ) {} else +// iterator over logic latches +#define Ivy_ManForEachLatch( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsLatch(pObj) ) {} else +// iterator over the nodes whose IDs are stored in the array +#define Ivy_ManForEachNodeVec( p, vIds, pObj, i ) \ + for ( i = 0; i < Vec_IntSize(vIds) && ((pObj) = Ivy_ManObj(p, Vec_IntEntry(vIds,i))); i++ ) +// iterator over the fanouts of an object +#define Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, i ) \ + for ( i = 0, Ivy_ObjCollectFanouts(p, pObj, vArray); \ + i < Vec_PtrSize(vArray) && ((pFanout) = Vec_PtrEntry(vArray,i)); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== ivyBalance.c ========================================================*/ +extern Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ); +extern Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ); +/*=== ivyCanon.c ========================================================*/ +extern Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); +/*=== ivyCheck.c ========================================================*/ +extern int Ivy_ManCheck( Ivy_Man_t * p ); +extern int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ); +extern int Ivy_ManCheckFanouts( Ivy_Man_t * p ); +extern int Ivy_ManCheckChoices( Ivy_Man_t * p ); +/*=== ivyCut.c ==========================================================*/ +extern void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ); +extern Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); +/*=== ivyDfs.c ==========================================================*/ +extern Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ); +extern Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ); +extern void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ); +extern Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ); +extern Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ); +extern int Ivy_ManIsAcyclic( Ivy_Man_t * p ); +extern int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ); +/*=== ivyDsd.c ==========================================================*/ +extern int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ); +extern void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ); +extern unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ); +extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); +extern Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ); +/*=== ivyFanout.c ==========================================================*/ +extern void Ivy_ManStartFanout( Ivy_Man_t * p ); +extern void Ivy_ManStopFanout( Ivy_Man_t * p ); +extern void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); +extern void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); +extern void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ); +extern void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ); +extern Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +/*=== ivyFastMap.c =============================================================*/ +extern void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ); +extern void Ivy_FastMapStop( Ivy_Man_t * pAig ); +extern void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ); +extern void Ivy_FastMapReverseLevel( Ivy_Man_t * pAig ); +/*=== ivyFraig.c ==========================================================*/ +extern int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ); +extern Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +extern Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +extern void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ); +/*=== ivyHaig.c ==========================================================*/ +extern void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ); +extern void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ); +extern void Ivy_ManHaigStop( Ivy_Man_t * p ); +extern void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ); +extern void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ); +extern void Ivy_ManHaigSimulate( Ivy_Man_t * p ); +/*=== ivyMan.c ==========================================================*/ +extern Ivy_Man_t * Ivy_ManStart(); +extern Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ); +extern Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ); +extern Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ); +extern void Ivy_ManStop( Ivy_Man_t * p ); +extern int Ivy_ManCleanup( Ivy_Man_t * p ); +extern int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ); +extern void Ivy_ManPrintStats( Ivy_Man_t * p ); +extern void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ); +/*=== ivyMem.c ==========================================================*/ +extern void Ivy_ManStartMemory( Ivy_Man_t * p ); +extern void Ivy_ManStopMemory( Ivy_Man_t * p ); +/*=== ivyMulti.c ==========================================================*/ +extern Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_Multi1( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +extern int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSol ); +/*=== ivyObj.c ==========================================================*/ +extern Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ); +extern Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ); +extern Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ); +extern void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ); +extern void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ); +extern void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); +extern void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); +extern void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ); +extern void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ); +/*=== ivyOper.c =========================================================*/ +extern Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ); +extern Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ); +extern Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ); +extern Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); +/*=== ivyResyn.c =========================================================*/ +extern Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); +extern Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); +extern Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ); +/*=== ivyRewrite.c =========================================================*/ +extern int Ivy_ManSeqRewrite( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); +extern int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); +extern int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ); +/*=== ivySeq.c =========================================================*/ +extern int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ); +/*=== ivyShow.c =========================================================*/ +extern void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ); +/*=== ivyTable.c ========================================================*/ +extern Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ); +extern int Ivy_TableCountEntries( Ivy_Man_t * p ); +extern void Ivy_TableProfile( Ivy_Man_t * p ); +/*=== ivyUtil.c =========================================================*/ +extern void Ivy_ManIncrementTravId( Ivy_Man_t * p ); +extern void Ivy_ManCleanTravId( Ivy_Man_t * p ); +extern unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ); +extern void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ); +extern Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ); +extern int Ivy_ManLevels( Ivy_Man_t * p ); +extern void Ivy_ManResetLevels( Ivy_Man_t * p ); +extern int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ); +extern int Ivy_ObjIsMuxType( Ivy_Obj_t * pObj ); +extern Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pObj, Ivy_Obj_t ** ppObjT, Ivy_Obj_t ** ppObjE ); +extern Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ); +extern void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ); +extern void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ); +extern int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/ivy/ivyBalance.c b/abc70930/src/aig/ivy/ivyBalance.c new file mode 100644 index 00000000..5627039a --- /dev/null +++ b/abc70930/src/aig/ivy/ivyBalance.c @@ -0,0 +1,404 @@ +/**CFile**************************************************************** + + FileName [ivyBalance.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Algebraic AIG balancing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); +static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); +static int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); +static void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); +static void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs algebraic balancing of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ) +{ + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj, * pDriver; + Vec_Vec_t * vStore; + int i, NewNodeId; + // clean the old manager + Ivy_ManCleanTravId( p ); + // create the new manager + pNew = Ivy_ManStart(); + // map the nodes + Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) ); + Ivy_ManForEachPi( p, pObj, i ) + pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) ); + // if HAIG is defined, trasfer the pointers to the PIs/latches +// if ( p->pHaig ) +// Ivy_ManHaigTrasfer( p, pNew ); + // balance the AIG + vStore = Vec_VecAlloc( 50 ); + Ivy_ManForEachPo( p, pObj, i ) + { + pDriver = Ivy_ObjReal( Ivy_ObjChild0(pObj) ); + NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel ); + NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) ); + Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) ); + } + Vec_VecFree( vStore ); + if ( i = Ivy_ManCleanup( pNew ) ) + { +// printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); + } + // check the resulting AIG + if ( !Ivy_ManCheck(pNew) ) + printf( "Ivy_ManBalance(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCompareLevelsDecrease( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) +{ + int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level; + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the ID of new node constructed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) +{ + Ivy_Obj_t * pObjNew; + Vec_Ptr_t * vSuper; + int i, NewNodeId; + assert( !Ivy_IsComplement(pObjOld) ); + assert( !Ivy_ObjIsBuf(pObjOld) ); + // return if the result is known + if ( Ivy_ObjIsConst1(pObjOld) ) + return pObjOld->TravId; + if ( pObjOld->TravId ) + return pObjOld->TravId; + assert( Ivy_ObjIsNode(pObjOld) ); + // get the implication supergate + vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level ); + if ( vSuper->nSize == 0 ) + { // it means that the supergate contains two nodes in the opposite polarity + pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) ); + return pObjOld->TravId; + } + if ( vSuper->nSize < 2 ) + printf( "BUG!\n" ); + // for each old node, derive the new well-balanced node + for ( i = 0; i < vSuper->nSize; i++ ) + { + NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); + NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(vSuper->pArray[i]) ); + vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId ); + } + // build the supergate + pObjNew = Ivy_NodeBalanceBuildSuper( pNew, vSuper, Ivy_ObjType(pObjOld), fUpdateLevel ); + vSuper->nSize = 0; + // make sure the balanced node is not assigned + assert( pObjOld->TravId == 0 ); + pObjOld->TravId = Ivy_EdgeFromNode( pObjNew ); +// assert( pObjOld->Level >= Ivy_Regular(pObjNew)->Level ); + return pObjOld->TravId; +} + +/**Function************************************************************* + + Synopsis [Builds implication supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ) +{ + Ivy_Obj_t * pObj1, * pObj2; + int LeftBound; + assert( vSuper->nSize > 1 ); + // sort the new nodes by level in the decreasing order + Vec_PtrSort( vSuper, Ivy_NodeCompareLevelsDecrease ); + // balance the nodes + while ( vSuper->nSize > 1 ) + { + // find the left bound on the node to be paired + LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper ); + // find the node that can be shared (if no such node, randomize choice) + Ivy_NodeBalancePermute( p, vSuper, LeftBound, Type == IVY_EXOR ); + // pull out the last two nodes + pObj1 = Vec_PtrPop(vSuper); + pObj2 = Vec_PtrPop(vSuper); + Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(p, pObj1, pObj2, Type) ); + } + return Vec_PtrEntry(vSuper, 0); +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Ivy_Regular(pObj)->fMarkB ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pObj ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Ivy_Not(pObj) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1) ) + { + Vec_PtrPush( vSuper, pObj ); + Ivy_Regular(pObj)->fMarkB = 1; + return 0; + } + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + // go through the branches + RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper ); + RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) +{ + Vec_Ptr_t * vNodes; + int RetValue, i; + assert( !Ivy_IsComplement(pObj) ); + // extend the storage + if ( Vec_VecSize( vStore ) <= Level ) + Vec_VecPush( vStore, Level, 0 ); + // get the temporary array of nodes + vNodes = Vec_VecEntry( vStore, Level ); + Vec_PtrClear( vNodes ); + // collect the nodes in the implication supergate + RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + Ivy_Regular(pObj)->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Finds the left bound on the next candidate to be paired.] + + Description [The nodes in the array are in the decreasing order of levels. + The last node in the array has the smallest level. By default it would be paired + with the next node on the left. However, it may be possible to pair it with some + other node on the left, in such a way that the new node is shared. This procedure + finds the index of the left-most node, which can be paired with the last node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) +{ + Ivy_Obj_t * pObjRight, * pObjLeft; + int Current; + // if two or less nodes, pair with the first + if ( Vec_PtrSize(vSuper) < 3 ) + return 0; + // set the pointer to the one before the last + Current = Vec_PtrSize(vSuper) - 2; + pObjRight = Vec_PtrEntry( vSuper, Current ); + // go through the nodes to the left of this one + for ( Current--; Current >= 0; Current-- ) + { + // get the next node on the left + pObjLeft = Vec_PtrEntry( vSuper, Current ); + // if the level of this node is different, quit the loop + if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level ) + break; + } + Current++; + // get the node, for which the equality holds + pObjLeft = Vec_PtrEntry( vSuper, Current ); + assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level ); + return Current; +} + +/**Function************************************************************* + + Synopsis [Moves closer to the end the node that is best for sharing.] + + Description [If there is no node with sharing, randomly chooses one of + the legal nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) +{ + Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; + int RightBound, i; + // get the right bound + RightBound = Vec_PtrSize(vSuper) - 2; + assert( LeftBound <= RightBound ); + if ( LeftBound == RightBound ) + return; + // get the two last nodes + pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); + pObj2 = Vec_PtrEntry( vSuper, RightBound ); + if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 ) + return; + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + pObj3 = Vec_PtrEntry( vSuper, i ); + if ( Ivy_Regular(pObj3) == p->pConst1 ) + { + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE ); + if ( Ivy_TableLookup( p, pGhost ) ) + { + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + } +/* + // we did not find the node to share, randomize choice + { + int Choice = rand() % (RightBound - LeftBound + 1); + pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pObj1, * pObj2; + int i; + if ( Vec_PtrPushUnique(vStore, pObj) ) + return; + // find the p of the node + for ( i = vStore->nSize-1; i > 0; i-- ) + { + pObj1 = vStore->pArray[i ]; + pObj2 = vStore->pArray[i-1]; + if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level ) + break; + vStore->pArray[i ] = pObj2; + vStore->pArray[i-1] = pObj1; + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyCanon.c b/abc70930/src/aig/ivy/ivyCanon.c new file mode 100644 index 00000000..5768b87e --- /dev/null +++ b/abc70930/src/aig/ivy/ivyCanon.c @@ -0,0 +1,144 @@ +/**CFile**************************************************************** + + FileName [ivyCanon.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Finding canonical form of objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCanon.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Ivy_Obj_t * Ivy_TableLookupPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1, int fCompl0, int fCompl1, Ivy_Type_t Type ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) +{ + Ivy_Obj_t * pResult, * pLat0, * pLat1; + Ivy_Init_t Init, Init0, Init1; + int fCompl0, fCompl1; + Ivy_Type_t Type; + assert( Ivy_ObjIsNode(pGhost) ); + assert( Ivy_ObjIsAnd(pGhost) || (!Ivy_ObjFaninC0(pGhost) && !Ivy_ObjFaninC1(pGhost)) ); + assert( Ivy_ObjFaninId0(pGhost) != 0 && Ivy_ObjFaninId1(pGhost) != 0 ); + // consider the case when the pair is canonical + if ( !Ivy_ObjIsLatch(Ivy_ObjFanin0(pGhost)) || !Ivy_ObjIsLatch(Ivy_ObjFanin1(pGhost)) ) + { + if ( pResult = Ivy_TableLookup( p, pGhost ) ) + return pResult; + return Ivy_ObjCreate( p, pGhost ); + } + /// remember the latches + pLat0 = Ivy_ObjFanin0(pGhost); + pLat1 = Ivy_ObjFanin1(pGhost); + // remember type and compls + Type = Ivy_ObjType(pGhost); + fCompl0 = Ivy_ObjFaninC0(pGhost); + fCompl1 = Ivy_ObjFaninC1(pGhost); + // call recursively + pResult = Ivy_Oper( p, Ivy_NotCond(Ivy_ObjFanin0(pLat0), fCompl0), Ivy_NotCond(Ivy_ObjFanin0(pLat1), fCompl1), Type ); + // build latch on top of this + Init0 = Ivy_InitNotCond( Ivy_ObjInit(pLat0), fCompl0 ); + Init1 = Ivy_InitNotCond( Ivy_ObjInit(pLat1), fCompl1 ); + Init = (Type == IVY_AND)? Ivy_InitAnd(Init0, Init1) : Ivy_InitExor(Init0, Init1); + return Ivy_Latch( p, pResult, Init ); +} + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) +{ + Ivy_Obj_t * pGhost, * pResult; + pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_AND, IVY_INIT_NONE ); + pResult = Ivy_CanonPair_rec( p, pGhost ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) +{ + Ivy_Obj_t * pGhost, * pResult; + int fCompl = Ivy_IsComplement(pObj0) ^ Ivy_IsComplement(pObj1); + pObj0 = Ivy_Regular(pObj0); + pObj1 = Ivy_Regular(pObj1); + pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_EXOR, IVY_INIT_NONE ); + pResult = Ivy_CanonPair_rec( p, pGhost ); + return Ivy_NotCond( pResult, fCompl ); +} + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) +{ + Ivy_Obj_t * pGhost, * pResult; + int fCompl = Ivy_IsComplement(pObj); + pObj = Ivy_Regular(pObj); + pGhost = Ivy_ObjCreateGhost( p, pObj, NULL, IVY_LATCH, Ivy_InitNotCond(Init, fCompl) ); + pResult = Ivy_TableLookup( p, pGhost ); + if ( pResult == NULL ) + pResult = Ivy_ObjCreate( p, pGhost ); + return Ivy_NotCond( pResult, fCompl ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyCheck.c b/abc70930/src/aig/ivy/ivyCheck.c new file mode 100644 index 00000000..55448f19 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyCheck.c @@ -0,0 +1,273 @@ +/**CFile**************************************************************** + + FileName [ivyCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the consistency of the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheck( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj, * pObj2; + int i; + Ivy_ManForEachObj( p, pObj, i ) + { + // skip deleted nodes + if ( Ivy_ObjId(pObj) != i ) + { + printf( "Ivy_ManCheck: Node with ID %d is listed as number %d in the array of objects.\n", pObj->Id, i ); + return 0; + } + // consider the constant node and PIs + if ( i == 0 || Ivy_ObjIsPi(pObj) ) + { + if ( Ivy_ObjFaninId0(pObj) || Ivy_ObjFaninId1(pObj) || Ivy_ObjLevel(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has non-standard constant or PI node with ID \"%d\".\n", pObj->Id ); + return 0; + } + continue; + } + if ( Ivy_ObjIsPo(pObj) ) + { + if ( Ivy_ObjFaninId1(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has non-standard PO node with ID \"%d\".\n", pObj->Id ); + return 0; + } + continue; + } + if ( Ivy_ObjIsBuf(pObj) ) + { + if ( Ivy_ObjFanin1(pObj) ) + { + printf( "Ivy_ManCheck: The buffer with ID \"%d\" contains second fanin.\n", pObj->Id ); + return 0; + } + continue; + } + if ( Ivy_ObjIsLatch(pObj) ) + { + if ( Ivy_ObjFanin1(pObj) ) + { + printf( "Ivy_ManCheck: The latch with ID \"%d\" contains second fanin.\n", pObj->Id ); + return 0; + } + if ( Ivy_ObjInit(pObj) == IVY_INIT_NONE ) + { + printf( "Ivy_ManCheck: The latch with ID \"%d\" does not have initial state.\n", pObj->Id ); + return 0; + } + pObj2 = Ivy_TableLookup( p, pObj ); + if ( pObj2 != pObj ) + printf( "Ivy_ManCheck: Latch with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); + continue; + } + // consider the AND node + if ( !Ivy_ObjFanin0(pObj) || !Ivy_ObjFanin1(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has internal node \"%d\" with a NULL fanin.\n", pObj->Id ); + return 0; + } + if ( Ivy_ObjFaninId0(pObj) >= Ivy_ObjFaninId1(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has node \"%d\" with a wrong ordering of fanins.\n", pObj->Id ); + return 0; + } + if ( Ivy_ObjLevel(pObj) != Ivy_ObjLevelNew(pObj) ) + printf( "Ivy_ManCheck: Node with ID \"%d\" has level %d but should have level %d.\n", pObj->Id, Ivy_ObjLevel(pObj), Ivy_ObjLevelNew(pObj) ); + pObj2 = Ivy_TableLookup( p, pObj ); + if ( pObj2 != pObj ) + printf( "Ivy_ManCheck: Node with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); + if ( Ivy_ObjRefs(pObj) == 0 ) + printf( "Ivy_ManCheck: Node with ID \"%d\" has no fanouts.\n", pObj->Id ); + // check fanouts + if ( p->fFanout && Ivy_ObjRefs(pObj) != Ivy_ObjFanoutNum(p, pObj) ) + printf( "Ivy_ManCheck: Node with ID \"%d\" has mismatch between the number of fanouts and refs.\n", pObj->Id ); + } + // count the number of nodes in the table + if ( Ivy_TableCountEntries(p) != Ivy_ManAndNum(p) + Ivy_ManExorNum(p) + Ivy_ManLatchNum(p) ) + { + printf( "Ivy_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); + return 0; + } +// if ( !Ivy_ManCheckFanouts(p) ) +// return 0; + if ( !Ivy_ManIsAcyclic(p) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies the fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i, Counter = 0; + Ivy_ManForEachObj( p, pObj, i ) + if ( Ivy_ObjIsNode(pObj) ) + Counter += (Ivy_ObjRefs(pObj) == 0); + if ( Counter ) + printf( "Sequential AIG has %d dangling nodes.\n", Counter ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Verifies the fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheckFanouts( Ivy_Man_t * p ) +{ + Vec_Ptr_t * vFanouts; + Ivy_Obj_t * pObj, * pFanout, * pFanin; + int i, k, RetValue = 1; + if ( !p->fFanout ) + return 1; + vFanouts = Vec_PtrAlloc( 100 ); + // make sure every fanin is a fanout + Ivy_ManForEachObj( p, pObj, i ) + { + pFanin = Ivy_ObjFanin0(pObj); + if ( pFanin == NULL ) + continue; + Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) + if ( pFanout == pObj ) + break; + if ( k == Vec_PtrSize(vFanouts) ) + { + printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); + RetValue = 0; + } + + pFanin = Ivy_ObjFanin1(pObj); + if ( pFanin == NULL ) + continue; + Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) + if ( pFanout == pObj ) + break; + if ( k == Vec_PtrSize(vFanouts) ) + { + printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); + RetValue = 0; + } + // check that the previous fanout has the same fanin + if ( pObj->pPrevFan0 ) + { + if ( Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) ) + { + printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan0->Id ); + RetValue = 0; + } + } + // check that the previous fanout has the same fanin + if ( pObj->pPrevFan1 ) + { + if ( Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) ) + { + printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan1->Id ); + RetValue = 0; + } + } + } + // make sure every fanout is a fanin + Ivy_ManForEachObj( p, pObj, i ) + { + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, k ) + if ( Ivy_ObjFanin0(pFanout) != pObj && Ivy_ObjFanin1(pFanout) != pObj ) + { + printf( "Node %d is a fanout of node %d but the fanin is not there.\n", pFanout->Id, pObj->Id ); + RetValue = 0; + } + } + Vec_PtrFree( vFanouts ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Checks that each choice node has exactly one node with fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheckChoices( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj, * pTemp; + int i; + Ivy_ManForEachObj( p->pHaig, pObj, i ) + { + if ( Ivy_ObjRefs(pObj) == 0 ) + continue; + // count the number of nodes in the loop + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp && pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + if ( Ivy_ObjRefs(pTemp) > 1 ) + printf( "Node %d has member %d in its equiv class with %d fanouts.\n", pObj->Id, pTemp->Id, Ivy_ObjRefs(pTemp) ); + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyCut.c b/abc70930/src/aig/ivy/ivyCut.c new file mode 100644 index 00000000..e257d8a6 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyCut.c @@ -0,0 +1,989 @@ +/**CFile**************************************************************** + + FileName [ivyCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Computes reconvergence driven sequential cut.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCut.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Ivy_NodeCutHashValue( int NodeId ) { return 1 << (NodeId % 31); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Evaluate the cost of removing the node from the set of leaves.] + + Description [Returns the number of new leaves that will be brought in. + Returns large number if the node cannot be removed from the set of leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeGetLeafCostOne( Ivy_Man_t * p, int Leaf, Vec_Int_t * vInside ) +{ + Ivy_Obj_t * pNode; + int nLatches, FaninLeaf, Cost; + // make sure leaf is not a contant node + assert( Leaf > 0 ); + // get the node + pNode = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); + // cannot expand over the PI node + if ( Ivy_ObjIsPi(pNode) || Ivy_ObjIsConst1(pNode) ) + return 999; + // get the number of latches + nLatches = Ivy_LeafLat(Leaf) + Ivy_ObjIsLatch(pNode); + if ( nLatches > 15 ) + return 999; + // get the first fanin + FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); + Cost = FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); + // quit if this is the one fanin node + if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) + return Cost; + assert( Ivy_ObjIsNode(pNode) ); + // get the second fanin + FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); + Cost += FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); + return Cost; +} + +/**Function************************************************************* + + Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] + + Description [This procedure looks at the current leaves and tries to change + one leaf at a time in such a way that the cut grows as little as possible. + In evaluating the fanins, this procedure looks only at their immediate + predecessors (this is why it is called a one-level construction procedure).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManSeqFindCut_int( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSizeLimit ) +{ + Ivy_Obj_t * pNode; + int CostBest, CostCur, Leaf, LeafBest, Next, nLatches, i; + int LeavesBest[10]; + int Counter; + + // add random selection of the best fanin!!! + + // find the best fanin + CostBest = 99; + LeafBest = -1; + Counter = -1; +//printf( "Evaluating fanins of the cut:\n" ); + Vec_IntForEachEntry( vFront, Leaf, i ) + { + CostCur = Ivy_NodeGetLeafCostOne( p, Leaf, vInside ); +//printf( " Fanin %s has cost %d.\n", Ivy_ObjName(pNode), CostCur ); + if ( CostBest > CostCur ) + { + CostBest = CostCur; + LeafBest = Leaf; + LeavesBest[0] = Leaf; + Counter = 1; + } + else if ( CostBest == CostCur ) + LeavesBest[Counter++] = Leaf; + + if ( CostBest <= 1 ) // can be if ( CostBest <= 1 ) + break; + } + if ( CostBest == 99 ) + return 0; +// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); + + assert( CostBest < 3 ); + if ( Vec_IntSize(vFront) - 1 + CostBest > nSizeLimit ) + return 0; +// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); + + assert( Counter > 0 ); +printf( "%d", Counter ); + + LeafBest = LeavesBest[rand() % Counter]; + + // remove the node from the array + assert( LeafBest >= 0 ); + Vec_IntRemove( vFront, LeafBest ); +//printf( "Removing fanin %s.\n", Ivy_ObjName(pNode) ); + + // get the node and its latches + pNode = Ivy_ManObj( p, Ivy_LeafId(LeafBest) ); + nLatches = Ivy_LeafLat(LeafBest) + Ivy_ObjIsLatch(pNode); + assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ); + + // add the left child to the fanins + Next = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); + if ( Next && Vec_IntFind(vInside, Next) == -1 ) + { +//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); + Vec_IntPush( vFront, Next ); + Vec_IntPush( vInside, Next ); + } + + // quit if this is the one fanin node + if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) + return 1; + assert( Ivy_ObjIsNode(pNode) ); + + // add the right child to the fanins + Next = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); + if ( Next && Vec_IntFind(vInside, Next) == -1 ) + { +//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); + Vec_IntPush( vFront, Next ); + Vec_IntPush( vInside, Next ); + } + assert( Vec_IntSize(vFront) <= nSizeLimit ); + // keep doing this + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes one sequential cut of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ) +{ + assert( !Ivy_IsComplement(pRoot) ); + assert( Ivy_ObjIsNode(pRoot) ); + assert( Ivy_ObjFaninId0(pRoot) ); + assert( Ivy_ObjFaninId1(pRoot) ); + + // start the cut + Vec_IntClear( vFront ); + Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); + Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); + + // start the visited nodes + Vec_IntClear( vInside ); + Vec_IntPush( vInside, Ivy_LeafCreate(pRoot->Id, 0) ); + Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); + Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); + + // compute the cut + while ( Ivy_ManSeqFindCut_int( p, vFront, vInside, nSize ) ); + assert( Vec_IntSize(vFront) <= nSize ); +} + + + + + +/**Function************************************************************* + + Synopsis [Computing Boolean cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindBoolCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume, Ivy_Obj_t * pPivot ) +{ + int RetValue0, RetValue1; + if ( pObj == pPivot ) + { + Vec_PtrPushUnique( vLeaves, pObj ); + Vec_PtrPushUnique( vVolume, pObj ); + return 1; + } + if ( pObj->fMarkA ) + return 0; + +// assert( !Ivy_ObjIsCi(pObj) ); + if ( Ivy_ObjIsCi(pObj) ) + return 0; + + if ( Ivy_ObjIsBuf(pObj) ) + { + RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); + if ( !RetValue0 ) + return 0; + Vec_PtrPushUnique( vVolume, pObj ); + return 1; + } + assert( Ivy_ObjIsNode(pObj) ); + RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); + RetValue1 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin1(pObj), vLeaves, vVolume, pPivot ); + if ( !RetValue0 && !RetValue1 ) + return 0; + // add new leaves + if ( !RetValue0 ) + { + Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin0(pObj) ); + Vec_PtrPushUnique( vVolume, Ivy_ObjFanin0(pObj) ); + } + if ( !RetValue1 ) + { + Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin1(pObj) ); + Vec_PtrPushUnique( vVolume, Ivy_ObjFanin1(pObj) ); + } + Vec_PtrPushUnique( vVolume, pObj ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns the cost of one node (how many new nodes are added.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindBoolCutCost( Ivy_Obj_t * pObj ) +{ + int Cost; + // make sure the node is in the construction zone + assert( pObj->fMarkA == 1 ); + // cannot expand over the PI node + if ( Ivy_ObjIsCi(pObj) ) + return 999; + // always expand over the buffer + if ( Ivy_ObjIsBuf(pObj) ) + return !Ivy_ObjFanin0(pObj)->fMarkA; + // get the cost of the cone + Cost = (!Ivy_ObjFanin0(pObj)->fMarkA) + (!Ivy_ObjFanin1(pObj)->fMarkA); + // return the number of nodes to be added to the leaves if this node is removed + return Cost; +} + +/**Function************************************************************* + + Synopsis [Computing Boolean cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindBoolCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVolume, Vec_Ptr_t * vLeaves ) +{ + Ivy_Obj_t * pObj, * pFaninC, * pFanin0, * pFanin1, * pPivot; + int RetValue, LevelLimit, Lev, k; + assert( !Ivy_IsComplement(pRoot) ); + // clear the frontier and collect the nodes + Vec_PtrClear( vFront ); + Vec_PtrClear( vVolume ); + if ( Ivy_ObjIsMuxType(pRoot) ) + pFaninC = Ivy_ObjRecognizeMux( pRoot, &pFanin0, &pFanin1 ); + else + { + pFaninC = NULL; + pFanin0 = Ivy_ObjFanin0(pRoot); + pFanin1 = Ivy_ObjFanin1(pRoot); + } + // start cone A + pFanin0->fMarkA = 1; + Vec_PtrPush( vFront, pFanin0 ); + Vec_PtrPush( vVolume, pFanin0 ); + // start cone B + pFanin1->fMarkB = 1; + Vec_PtrPush( vFront, pFanin1 ); + Vec_PtrPush( vVolume, pFanin1 ); + // iteratively expand until the common node (pPivot) is found or limit is reached + assert( Ivy_ObjLevel(pRoot) == Ivy_ObjLevelNew(pRoot) ); + pPivot = NULL; + LevelLimit = IVY_MAX( Ivy_ObjLevel(pRoot) - 10, 1 ); + for ( Lev = Ivy_ObjLevel(pRoot) - 1; Lev >= LevelLimit; Lev-- ) + { + while ( 1 ) + { + // find the next node to expand on this level + Vec_PtrForEachEntry( vFront, pObj, k ) + if ( (int)pObj->Level == Lev ) + break; + if ( k == Vec_PtrSize(vFront) ) + break; + assert( (int)pObj->Level <= Lev ); + assert( pObj->fMarkA ^ pObj->fMarkB ); + // remove the old node + Vec_PtrRemove( vFront, pObj ); + + // expand this node + pFanin0 = Ivy_ObjFanin0(pObj); + if ( !pFanin0->fMarkA && !pFanin0->fMarkB ) + { + Vec_PtrPush( vFront, pFanin0 ); + Vec_PtrPush( vVolume, pFanin0 ); + } + // mark the new nodes + if ( pObj->fMarkA ) + pFanin0->fMarkA = 1; + if ( pObj->fMarkB ) + pFanin0->fMarkB = 1; + + if ( Ivy_ObjIsBuf(pObj) ) + { + if ( pFanin0->fMarkA && pFanin0->fMarkB ) + { + pPivot = pFanin0; + break; + } + continue; + } + + // expand this node + pFanin1 = Ivy_ObjFanin1(pObj); + if ( !pFanin1->fMarkA && !pFanin1->fMarkB ) + { + Vec_PtrPush( vFront, pFanin1 ); + Vec_PtrPush( vVolume, pFanin1 ); + } + // mark the new nodes + if ( pObj->fMarkA ) + pFanin1->fMarkA = 1; + if ( pObj->fMarkB ) + pFanin1->fMarkB = 1; + + // consider if it is time to quit + if ( pFanin0->fMarkA && pFanin0->fMarkB ) + { + pPivot = pFanin0; + break; + } + if ( pFanin1->fMarkA && pFanin1->fMarkB ) + { + pPivot = pFanin1; + break; + } + } + if ( pPivot != NULL ) + break; + } + if ( pPivot == NULL ) + return 0; + // if the MUX control is defined, it should not be + if ( pFaninC && !pFaninC->fMarkA && !pFaninC->fMarkB ) + Vec_PtrPush( vFront, pFaninC ); + // clean the markings + Vec_PtrForEachEntry( vVolume, pObj, k ) + pObj->fMarkA = pObj->fMarkB = 0; + + // mark the nodes on the frontier (including the pivot) + Vec_PtrForEachEntry( vFront, pObj, k ) + pObj->fMarkA = 1; + // cut exists, collect all the nodes on the shortest path to the pivot + Vec_PtrClear( vLeaves ); + Vec_PtrClear( vVolume ); + RetValue = Ivy_ManFindBoolCut_rec( p, pRoot, vLeaves, vVolume, pPivot ); + assert( RetValue == 1 ); + // unmark the nodes on the frontier (including the pivot) + Vec_PtrForEachEntry( vFront, pObj, k ) + pObj->fMarkA = 0; + + // mark the nodes in the volume + Vec_PtrForEachEntry( vVolume, pObj, k ) + pObj->fMarkA = 1; + // expand the cut without increasing its size + while ( 1 ) + { + Vec_PtrForEachEntry( vLeaves, pObj, k ) + if ( Ivy_ManFindBoolCutCost(pObj) < 2 ) + break; + if ( k == Vec_PtrSize(vLeaves) ) + break; + // the node can be expanded + // remove the old node + Vec_PtrRemove( vLeaves, pObj ); + // expand this node + pFanin0 = Ivy_ObjFanin0(pObj); + if ( !pFanin0->fMarkA ) + { + pFanin0->fMarkA = 1; + Vec_PtrPush( vVolume, pFanin0 ); + Vec_PtrPush( vLeaves, pFanin0 ); + } + if ( Ivy_ObjIsBuf(pObj) ) + continue; + // expand this node + pFanin1 = Ivy_ObjFanin1(pObj); + if ( !pFanin1->fMarkA ) + { + pFanin1->fMarkA = 1; + Vec_PtrPush( vVolume, pFanin1 ); + Vec_PtrPush( vLeaves, pFanin1 ); + } + } + // unmark the nodes in the volume + Vec_PtrForEachEntry( vVolume, pObj, k ) + pObj->fMarkA = 0; + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManTestCutsBool( Ivy_Man_t * p ) +{ + Vec_Ptr_t * vFront, * vVolume, * vLeaves; + Ivy_Obj_t * pObj;//, * pTemp; + int i, RetValue;//, k; + vFront = Vec_PtrAlloc( 100 ); + vVolume = Vec_PtrAlloc( 100 ); + vLeaves = Vec_PtrAlloc( 100 ); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + if ( Ivy_ObjIsMuxType(pObj) ) + { + printf( "m" ); + continue; + } + if ( Ivy_ObjIsExor(pObj) ) + printf( "x" ); + RetValue = Ivy_ManFindBoolCut( p, pObj, vFront, vVolume, vLeaves ); + if ( RetValue == 0 ) + printf( "- " ); + else + printf( "%d ", Vec_PtrSize(vLeaves) ); +/* + printf( "( " ); + Vec_PtrForEachEntry( vFront, pTemp, k ) + printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); + printf( ")\n" ); +*/ + } + printf( "\n" ); + Vec_PtrFree( vFront ); + Vec_PtrFree( vVolume ); + Vec_PtrFree( vLeaves ); +} + + + +/**Function************************************************************* + + Synopsis [Find the hash value of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) +{ + int i; +// for ( i = 1; i < pCut->nSize; i++ ) +// assert( pCut->pArray[i-1] < pCut->pArray[i] ); + pCut->uHash = 0; + for ( i = 0; i < pCut->nSize; i++ ) + pCut->uHash |= (1 << (pCut->pArray[i] % 31)); + return pCut->uHash; +} + +/**Function************************************************************* + + Synopsis [Removes one node to the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Ivy_NodeCutShrink( Ivy_Cut_t * pCut, int iOld ) +{ + int i, k; + for ( i = k = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] != iOld ) + pCut->pArray[k++] = pCut->pArray[i]; + assert( k == pCut->nSize - 1 ); + pCut->nSize--; +} + +/**Function************************************************************* + + Synopsis [Adds one node to the cut.] + + Description [Returns 1 if the cuts is still okay.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeCutExtend( Ivy_Cut_t * pCut, int iNew ) +{ + int i; + for ( i = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] == iNew ) + return 1; + // check if there is room + if ( pCut->nSize == pCut->nSizeMax ) + return 0; + // add the new one + for ( i = pCut->nSize - 1; i >= 0; i-- ) + if ( pCut->pArray[i] > iNew ) + pCut->pArray[i+1] = pCut->pArray[i]; + else + { + assert( pCut->pArray[i] < iNew ); + break; + } + pCut->pArray[i+1] = iNew; + pCut->nSize++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeCutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) +{ + int i; + if ( pCut->nSize < pCut->nSizeMax ) + return 1; + for ( i = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeCutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + unsigned uHash = 0; + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_NodeCutHashValue( IdNew0 ); + } + IdNew0 = 0x7FFFFFFF; + } + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_NodeCutHashValue( IdNew1 ); + } + IdNew1 = 0x7FFFFFFF; + } + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + uHash |= Ivy_NodeCutHashValue( pCut->pArray[i] ); + } + if ( IdNew0 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_NodeCutHashValue( IdNew0 ); + } + if ( IdNew1 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_NodeCutHashValue( IdNew1 ); + } + pCutNew->nSize = k; + pCutNew->uHash = uHash; + assert( pCutNew->nSize <= pCut->nSizeMax ); +// for ( i = 1; i < pCutNew->nSize; i++ ) +// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Check if the cut exists.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCutFindOrAdd( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) +{ + Ivy_Cut_t * pCut; + int i, k; + assert( pCutNew->uHash ); + // try to find the cut + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->uHash == pCutNew->uHash && pCut->nSize == pCutNew->nSize ) + { + for ( k = 0; k < pCutNew->nSize; k++ ) + if ( pCut->pArray[k] != pCutNew->pArray[k] ) + break; + if ( k == pCutNew->nSize ) + return 1; + } + } + assert( pCutStore->nCuts < pCutStore->nCutsMax ); + // add the cut + pCut = pCutStore->pCuts + pCutStore->nCuts++; + *pCut = *pCutNew; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) +{ + int i, k; + for ( i = 0; i < pDom->nSize; i++ ) + { + for ( k = 0; k < pCut->nSize; k++ ) + if ( pDom->pArray[i] == pCut->pArray[k] ) + break; + if ( k == pCut->nSize ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Check if the cut exists.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) +{ + Ivy_Cut_t * pCut; + int i, k; + assert( pCutNew->uHash ); + // try to find the cut + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + if ( pCut->nSize == pCutNew->nSize ) + { + if ( pCut->uHash == pCutNew->uHash ) + { + for ( k = 0; k < pCutNew->nSize; k++ ) + if ( pCut->pArray[k] != pCutNew->pArray[k] ) + break; + if ( k == pCutNew->nSize ) + return 1; + } + continue; + } + if ( pCut->nSize < pCutNew->nSize ) + { + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) + return 1; + continue; + } + // check potential containment of other cut + + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) + { + // remove the current cut +// --pCutStore->nCuts; +// for ( k = i; k < pCutStore->nCuts; k++ ) +// pCutStore->pCuts[k] = pCutStore->pCuts[k+1]; +// i--; + pCut->nSize = 0; + } + } + assert( pCutStore->nCuts < pCutStore->nCutsMax ); + // add the cut + pCut = pCutStore->pCuts + pCutStore->nCuts++; + *pCut = *pCutNew; + return 0; +} + +/**Function************************************************************* + + Synopsis [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeCompactCuts( Ivy_Store_t * pCutStore ) +{ + Ivy_Cut_t * pCut; + int i, k; + for ( i = k = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + pCutStore->pCuts[k++] = *pCut; + } + pCutStore->nCuts = k; +} + +/**Function************************************************************* + + Synopsis [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodePrintCut( Ivy_Cut_t * pCut ) +{ + int i; + assert( pCut->nSize > 0 ); + printf( "%d : {", pCut->nSize ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %d", pCut->pArray[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodePrintCuts( Ivy_Store_t * pCutStore ) +{ + int i; + printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); + for ( i = 0; i < pCutStore->nCuts; i++ ) + Ivy_NodePrintCut( pCutStore->pCuts + i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_Obj_t * Ivy_ObjRealFanin( Ivy_Obj_t * pObj ) +{ + if ( !Ivy_ObjIsBuf(pObj) ) + return pObj; + return Ivy_ObjRealFanin( Ivy_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) +{ + static Ivy_Store_t CutStore, * pCutStore = &CutStore; + Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; + Ivy_Obj_t * pLeaf; + int i, k, iLeaf0, iLeaf1; + + assert( nLeaves <= IVY_CUT_INPUT ); + + // start the structure + pCutStore->nCuts = 0; + pCutStore->nCutsMax = IVY_CUT_LIMIT; + // start the trivial cut + pCutNew->uHash = 0; + pCutNew->nSize = 1; + pCutNew->nSizeMax = nLeaves; + pCutNew->pArray[0] = pObj->Id; + Ivy_NodeCutHash( pCutNew ); + // add the trivial cut + Ivy_NodeCutFindOrAdd( pCutStore, pCutNew ); + assert( pCutStore->nCuts == 1 ); + + // explore the cuts + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + // expand this cut + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + for ( k = 0; k < pCut->nSize; k++ ) + { + pLeaf = Ivy_ManObj( p, pCut->pArray[k] ); + if ( Ivy_ObjIsCi(pLeaf) ) + continue; +/* + *pCutNew = *pCut; + Ivy_NodeCutShrink( pCutNew, pLeaf->Id ); + if ( !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId0(pLeaf) ) ) + continue; + if ( Ivy_ObjIsNode(pLeaf) && !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId1(pLeaf) ) ) + continue; + Ivy_NodeCutHash( pCutNew ); +*/ + iLeaf0 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin0(pLeaf)) ); + iLeaf1 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin1(pLeaf)) ); +// if ( iLeaf0 == iLeaf1 ) // strange situation observed on Jan 18, 2007 +// continue; + if ( !Ivy_NodeCutPrescreen( pCut, iLeaf0, iLeaf1 ) ) + continue; + if ( iLeaf0 > iLeaf1 ) + Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf1, iLeaf0 ); + else + Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ); + Ivy_NodeCutFindOrAddFilter( pCutStore, pCutNew ); + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + Ivy_NodeCompactCuts( pCutStore ); +// Ivy_NodePrintCuts( pCutStore ); + return pCutStore; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManTestCutsAll( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; + int clk = clock(); + nNodeTotal = nNodeOver = 0; + nCutsTotal = -Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + nCutsCut = Ivy_NodeFindCutsAll( p, pObj, 5 )->nCuts; + nCutsTotal += nCutsCut; + nNodeOver += (nCutsCut == IVY_CUT_LIMIT); + nNodeTotal++; + } + printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", + nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); + PRT( "Time", clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyCutTrav.c b/abc70930/src/aig/ivy/ivyCutTrav.c new file mode 100644 index 00000000..ea57c9f5 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyCutTrav.c @@ -0,0 +1,473 @@ +/**CFile**************************************************************** + + FileName [ivyCutTrav.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCutTrav.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ); +static void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ); +static void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes cuts for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Store_t * Ivy_NodeFindCutsTravAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves, int nNodeLimit, + Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront, Vec_Int_t * vStore, Vec_Vec_t * vBitCuts ) +{ + static Ivy_Store_t CutStore, * pCutStore = &CutStore; + Vec_Ptr_t * vCuts, * vCuts0, * vCuts1; + unsigned * pBitCut; + Ivy_Obj_t * pLeaf; + Ivy_Cut_t * pCut; + int i, k, nWords, nNodes; + + assert( nLeaves <= IVY_CUT_INPUT ); + + // find the given number of nodes in the TFI + Ivy_NodeComputeVolume( pObj, nNodeLimit - 1, vNodes, vFront ); + nNodes = Vec_PtrSize(vNodes); +// assert( nNodes <= nNodeLimit ); + + // make sure vBitCuts has enough room + Vec_VecExpand( vBitCuts, nNodes-1 ); + Vec_VecClear( vBitCuts ); + + // prepare the memory manager + Vec_IntClear( vStore ); + Vec_IntGrow( vStore, 64000 ); + + // set elementary cuts for the leaves + nWords = Extra_BitWordNum( nNodes ); + Vec_PtrForEachEntry( vFront, pLeaf, i ) + { + assert( Ivy_ObjTravId(pLeaf) < nNodes ); + // get the new bitcut + pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); + // set it as the cut of this leaf + Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); + } + + // compute the cuts for each node + Vec_PtrForEachEntry( vNodes, pLeaf, i ) + { + // skip the leaves + vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pLeaf) ); + if ( Vec_PtrSize(vCuts) > 0 ) + continue; + // add elementary cut + pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); + // set it as the cut of this leaf + Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); + // get the fanin cuts + vCuts0 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin0(pLeaf) ) ); + vCuts1 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin1(pLeaf) ) ); + assert( Vec_PtrSize(vCuts0) > 0 ); + assert( Vec_PtrSize(vCuts1) > 0 ); + // merge the cuts + Ivy_NodeFindCutsMerge( vCuts0, vCuts1, vCuts, nLeaves, nWords, vStore ); + } + + // start the structure + pCutStore->nCuts = 0; + pCutStore->nCutsMax = IVY_CUT_LIMIT; + // collect the cuts of the root node + vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pObj) ); + Vec_PtrForEachEntry( vCuts, pBitCut, i ) + { + pCut = pCutStore->pCuts + pCutStore->nCuts++; + pCut->nSize = 0; + pCut->nSizeMax = nLeaves; + pCut->uHash = 0; + for ( k = 0; k < nNodes; k++ ) + if ( Extra_TruthHasBit(pBitCut, k) ) + pCut->pArray[ pCut->nSize++ ] = Ivy_ObjId( Vec_PtrEntry(vNodes, k) ); + assert( pCut->nSize <= nLeaves ); + if ( pCutStore->nCuts == pCutStore->nCutsMax ) + break; + } + + // clean the travIds + Vec_PtrForEachEntry( vNodes, pLeaf, i ) + pLeaf->TravId = 0; + return pCutStore; +} + +/**Function************************************************************* + + Synopsis [Creates elementary bit-cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ) +{ + unsigned * pBitCut; + pBitCut = Vec_IntFetch( vStore, nWords ); + memset( pBitCut, 0, 4 * nWords ); + Extra_TruthSetBit( pBitCut, NodeId ); + return pBitCut; +} + +/**Function************************************************************* + + Synopsis [Compares the node by level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_CompareNodesByLevel( Ivy_Obj_t ** ppObj1, Ivy_Obj_t ** ppObj2 ) +{ + Ivy_Obj_t * pObj1 = *ppObj1; + Ivy_Obj_t * pObj2 = *ppObj2; + if ( pObj1->Level < pObj2->Level ) + return -1; + if ( pObj1->Level > pObj2->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Mark all nodes up to the given depth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolumeTrav1_rec( Ivy_Obj_t * pObj, int Depth ) +{ + if ( Ivy_ObjIsCi(pObj) || Depth == 0 ) + return; + Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin0(pObj), Depth - 1 ); + Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin1(pObj), Depth - 1 ); + pObj->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Collect the marked nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolumeTrav2_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( !pObj->fMarkA ) + return; + Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin0(pObj), vNodes ); + Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pTemp, * pFanin; + int i, nNodes; + // mark nodes up to the given depth + Ivy_NodeComputeVolumeTrav1_rec( pObj, 6 ); + // collect the marked nodes + Vec_PtrClear( vFront ); + Ivy_NodeComputeVolumeTrav2_rec( pObj, vFront ); + // find the fanins that are not marked + Vec_PtrClear( vNodes ); + Vec_PtrForEachEntry( vFront, pTemp, i ) + { + pFanin = Ivy_ObjFanin0(pTemp); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + } + pFanin = Ivy_ObjFanin1(pTemp); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + } + } + // remember the number of nodes in the frontier + nNodes = Vec_PtrSize( vNodes ); + // add the remaining nodes + Vec_PtrForEachEntry( vFront, pTemp, i ) + Vec_PtrPush( vNodes, pTemp ); + // unmark the nodes + Vec_PtrForEachEntry( vNodes, pTemp, i ) + { + pTemp->fMarkA = 0; + pTemp->TravId = i; + } + // collect the frontier nodes + Vec_PtrClear( vFront ); + Vec_PtrForEachEntryStop( vNodes, pTemp, i, nNodes ) + Vec_PtrPush( vFront, pTemp ); +// printf( "%d ", Vec_PtrSize(vNodes) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pLeaf, * pPivot, * pFanin; + int LevelMax, i; + assert( Ivy_ObjIsNode(pObj) ); + // clear arrays + Vec_PtrClear( vNodes ); + Vec_PtrClear( vFront ); + // add the root + pObj->fMarkA = 1; + Vec_PtrPush( vNodes, pObj ); + Vec_PtrPush( vFront, pObj ); + // expand node with maximum level + LevelMax = pObj->Level; + do { + // get the node to expand + pPivot = NULL; + Vec_PtrForEachEntryReverse( vFront, pLeaf, i ) + { + if ( (int)pLeaf->Level == LevelMax ) + { + pPivot = pLeaf; + break; + } + } + // decrease level if we did not find the node + if ( pPivot == NULL ) + { + if ( --LevelMax == 0 ) + break; + continue; + } + // the node to expand is found + // remove it from frontier + Vec_PtrRemove( vFront, pPivot ); + // add fanins + pFanin = Ivy_ObjFanin0(pPivot); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + Vec_PtrPush( vFront, pFanin ); + } + pFanin = Ivy_ObjFanin1(pPivot); + if ( pFanin && !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + Vec_PtrPush( vFront, pFanin ); + } + // quit if we collected enough nodes + } while ( Vec_PtrSize(vNodes) < nNodeLimit ); + + // sort nodes by level + Vec_PtrSort( vNodes, Ivy_CompareNodesByLevel ); + // make sure the nodes are ordered in the increasing number of levels + pFanin = Vec_PtrEntry( vNodes, 0 ); + pPivot = Vec_PtrEntryLast( vNodes ); + assert( pFanin->Level <= pPivot->Level ); + + // clean the marks and remember node numbers in the TravId + Vec_PtrForEachEntry( vNodes, pFanin, i ) + { + pFanin->fMarkA = 0; + pFanin->TravId = i; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Extra_TruthOrWords( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nWords ) +{ + int w; + for ( w = nWords-1; w >= 0; w-- ) + pOut[w] = pIn0[w] | pIn1[w]; +} +static inline int Extra_TruthIsImplyWords( unsigned * pIn1, unsigned * pIn2, int nWords ) +{ + int w; + for ( w = nWords-1; w >= 0; w-- ) + if ( pIn1[w] & ~pIn2[w] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Merges two sets of bit-cuts at a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, + int nLeaves, int nWords, Vec_Int_t * vStore ) +{ + unsigned * pBitCut, * pBitCut0, * pBitCut1, * pBitCutTest; + int i, k, c, w, Counter; + // iterate through the cut pairs + Vec_PtrForEachEntry( vCuts0, pBitCut0, i ) + Vec_PtrForEachEntry( vCuts1, pBitCut1, k ) + { + // skip infeasible cuts + Counter = 0; + for ( w = 0; w < nWords; w++ ) + { + Counter += Extra_WordCountOnes( pBitCut0[w] | pBitCut1[w] ); + if ( Counter > nLeaves ) + break; + } + if ( Counter > nLeaves ) + continue; + // the new cut is feasible - create it + pBitCutTest = Vec_IntFetch( vStore, nWords ); + Extra_TruthOrWords( pBitCutTest, pBitCut0, pBitCut1, nWords ); + // filter contained cuts; try to find containing cut + w = 0; + Vec_PtrForEachEntry( vCuts, pBitCut, c ) + { + if ( Extra_TruthIsImplyWords( pBitCut, pBitCutTest, nWords ) ) + break; + if ( Extra_TruthIsImplyWords( pBitCutTest, pBitCut, nWords ) ) + continue; + Vec_PtrWriteEntry( vCuts, w++, pBitCut ); + } + if ( c != Vec_PtrSize(vCuts) ) + continue; + Vec_PtrShrink( vCuts, w ); + // add the cut + Vec_PtrPush( vCuts, pBitCutTest ); + } +} + +/**Function************************************************************* + + Synopsis [Compute the set of all cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManTestCutsTravAll( Ivy_Man_t * p ) +{ + Ivy_Store_t * pStore; + Ivy_Obj_t * pObj; + Vec_Ptr_t * vNodes, * vFront; + Vec_Int_t * vStore; + Vec_Vec_t * vBitCuts; + int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; + int clk = clock(); + + vNodes = Vec_PtrAlloc( 100 ); + vFront = Vec_PtrAlloc( 100 ); + vStore = Vec_IntAlloc( 100 ); + vBitCuts = Vec_VecAlloc( 100 ); + + nNodeTotal = nNodeOver = 0; + nCutsTotal = -Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + pStore = Ivy_NodeFindCutsTravAll( p, pObj, 4, 60, vNodes, vFront, vStore, vBitCuts ); + nCutsCut = pStore->nCuts; + nCutsTotal += nCutsCut; + nNodeOver += (nCutsCut == IVY_CUT_LIMIT); + nNodeTotal++; + } + printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", + nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); + PRT( "Time", clock() - clk ); + + Vec_PtrFree( vNodes ); + Vec_PtrFree( vFront ); + Vec_IntFree( vStore ); + Vec_VecFree( vBitCuts ); + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyDfs.c b/abc70930/src/aig/ivy/ivyDfs.c new file mode 100644 index 00000000..c27cba31 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyDfs.c @@ -0,0 +1,493 @@ +/**CFile**************************************************************** + + FileName [ivyDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [DFS collection procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManDfs_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( Ivy_ObjIsMarkA(pObj) ) + return; + Ivy_ObjSetMarkA(pObj); + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) + { + if ( p->pHaig == NULL && pObj->pEquiv ) + Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); + return; + } +//printf( "visiting node %d\n", pObj->Id ); +/* + if ( pObj->Id == 87 || pObj->Id == 90 ) + { + int y = 0; + } +*/ + assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + if ( !Ivy_ObjIsBuf(pObj) ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin1(pObj), vNodes ); + if ( p->pHaig == NULL && pObj->pEquiv ) + Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); + Vec_IntPush( vNodes, pObj->Id ); + +//printf( "adding node %d with fanins %d and %d and equiv %d (refs = %d)\n", +// pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id, +// pObj->pEquiv? Ivy_Regular(pObj->pEquiv)->Id: -1, Ivy_ObjRefs(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ) +{ + Vec_Int_t * vNodes; + Ivy_Obj_t * pObj; + int i; + assert( Ivy_ManLatchNum(p) == 0 ); + // make sure the nodes are not marked + Ivy_ManForEachObj( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + // collect the nodes + vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + // unmark the collected nodes +// Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) +// Ivy_ObjClearMarkA(pObj); + Ivy_ManForEachObj( p, pObj, i ) + Ivy_ObjClearMarkA(pObj); + // make sure network does not have dangling nodes + assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ) +{ + Vec_Int_t * vNodes, * vLatches; + Ivy_Obj_t * pObj; + int i; +// assert( Ivy_ManLatchNum(p) > 0 ); + // make sure the nodes are not marked + Ivy_ManForEachObj( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + // collect the latches + vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); + Ivy_ManForEachLatch( p, pObj, i ) + Vec_IntPush( vLatches, pObj->Id ); + // collect the nodes + vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + // unmark the collected nodes +// Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) +// Ivy_ObjClearMarkA(pObj); + Ivy_ManForEachObj( p, pObj, i ) + Ivy_ObjClearMarkA(pObj); + // make sure network does not have dangling nodes +// assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); + +// temporary!!! + + if ( pvLatches == NULL ) + Vec_IntFree( vLatches ); + else + *pvLatches = vLatches; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects nodes in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCone_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vCone ) +{ + if ( pObj->fMarkA ) + return; + if ( Ivy_ObjIsBuf(pObj) ) + { + Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); + Vec_PtrPush( vCone, pObj ); + return; + } + assert( Ivy_ObjIsNode(pObj) ); + Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); + Ivy_ManCollectCone_rec( Ivy_ObjFanin1(pObj), vCone ); + Vec_PtrPushUnique( vCone, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) +{ + Ivy_Obj_t * pTemp; + int i; + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + // mark the nodes + Vec_PtrForEachEntry( vFront, pTemp, i ) + Ivy_Regular(pTemp)->fMarkA = 1; + assert( pObj->fMarkA == 0 ); + // collect the cone + Vec_PtrClear( vCone ); + Ivy_ManCollectCone_rec( pObj, vCone ); + // unmark the nodes + Vec_PtrForEachEntry( vFront, pTemp, i ) + Ivy_Regular(pTemp)->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Returns the nodes by level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ) +{ + Vec_Vec_t * vNodes; + Ivy_Obj_t * pObj; + int i; + vNodes = Vec_VecAlloc( 100 ); + Ivy_ManForEachObj( p, pObj, i ) + { + assert( !Ivy_ObjIsBuf(pObj) ); + if ( Ivy_ObjIsNode(pObj) ) + Vec_VecPush( vNodes, pObj->Level, pObj ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes required levels for each node.] + + Description [Assumes topological ordering of the nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + Vec_Int_t * vLevelsR; + Vec_Vec_t * vNodes; + int i, k, Level, LevelMax; + assert( p->vRequired == NULL ); + // start the required times + vLevelsR = Vec_IntStart( Ivy_ManObjIdMax(p) + 1 ); + // iterate through the nodes in the reverse order + vNodes = Ivy_ManLevelize( p ); + Vec_VecForEachEntryReverseReverse( vNodes, pObj, i, k ) + { + Level = Vec_IntEntry( vLevelsR, pObj->Id ) + 1 + Ivy_ObjIsExor(pObj); + if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId0(pObj) ) < Level ) + Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId0(pObj), Level ); + if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId1(pObj) ) < Level ) + Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId1(pObj), Level ); + } + Vec_VecFree( vNodes ); + // convert it into the required times + LevelMax = Ivy_ManLevels( p ); +//printf( "max %5d\n",LevelMax ); + Ivy_ManForEachObj( p, pObj, i ) + { + Level = Vec_IntEntry( vLevelsR, pObj->Id ); + Vec_IntWriteEntry( vLevelsR, pObj->Id, LevelMax - Level ); +//printf( "%5d : %5d %5d\n", pObj->Id, Level, LevelMax - Level ); + } + p->vRequired = vLevelsR; + return vLevelsR; +} + +/**Function************************************************************* + + Synopsis [Recursively detects combinational loops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManIsAcyclic_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + // skip the node if it is already visited + if ( Ivy_ObjIsTravIdPrevious(p, pObj) ) + return 1; + // check if the node is part of the combinational loop + if ( Ivy_ObjIsTravIdCurrent(p, pObj) ) + { + fprintf( stdout, "Manager contains combinational loop!\n" ); + fprintf( stdout, "Node \"%d\" is encountered twice on the following path:\n", Ivy_ObjId(pObj) ); + fprintf( stdout, " %d", Ivy_ObjId(pObj) ); + return 0; + } + // mark this node as a node on the current path + Ivy_ObjSetTravIdCurrent( p, pObj ); + // explore equivalent nodes if pObj is the main node + if ( p->pHaig == NULL && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) + { + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { + // traverse the fanin's cone searching for the loop + if ( !Ivy_ManIsAcyclic_rec(p, pTemp) ) + { + // return as soon as the loop is detected + fprintf( stdout, " -> (%d", Ivy_ObjId(pObj) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + fprintf( stdout, " %d", Ivy_ObjId(pTemp) ); + fprintf( stdout, ")" ); + return 0; + } + } + } + // quite if it is a CI node + if ( Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) + { + // mark this node as a visited node + Ivy_ObjSetTravIdPrevious( p, pObj ); + return 1; + } + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + // traverse the fanin's cone searching for the loop + if ( !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) ) + { + // return as soon as the loop is detected + fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); + return 0; + } + // traverse the fanin's cone searching for the loop + if ( Ivy_ObjIsNode(pObj) && !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin1(pObj)) ) + { + // return as soon as the loop is detected + fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); + return 0; + } + // mark this node as a visited node + Ivy_ObjSetTravIdPrevious( p, pObj ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Detects combinational loops.] + + Description [This procedure is based on the idea suggested by Donald Chai. + As we traverse the network and visit the nodes, we need to distinquish + three types of nodes: (1) those that are visited for the first time, + (2) those that have been visited in this traversal but are currently not + on the traversal path, (3) those that have been visited and are currently + on the travesal path. When the node of type (3) is encountered, it means + that there is a combinational loop. To mark the three types of nodes, + two new values of the traversal IDs are used.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManIsAcyclic( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int fAcyclic, i; + // set the traversal ID for this DFS ordering + Ivy_ManIncrementTravId( p ); + Ivy_ManIncrementTravId( p ); + // pObj->TravId == pNet->nTravIds means "pObj is on the path" + // pObj->TravId == pNet->nTravIds - 1 means "pObj is visited but is not on the path" + // pObj->TravId < pNet->nTravIds - 1 means "pObj is not visited" + // traverse the network to detect cycles + fAcyclic = 1; + Ivy_ManForEachCo( p, pObj, i ) + { + // traverse the output logic cone + if ( fAcyclic = Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) ) + continue; + // stop as soon as the first loop is detected + fprintf( stdout, " (cone of %s \"%d\")\n", Ivy_ObjIsLatch(pObj)? "latch" : "PO", Ivy_ObjId(pObj) ); + break; + } + return fAcyclic; +} + +/**Function************************************************************* + + Synopsis [Sets the levels of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManSetLevels_rec( Ivy_Obj_t * pObj, int fHaig ) +{ + // quit if the node is visited + if ( Ivy_ObjIsMarkA(pObj) ) + return pObj->Level; + Ivy_ObjSetMarkA(pObj); + // quit if this is a CI + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) + return 0; + assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); + // get levels of the fanins + Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); + if ( !Ivy_ObjIsBuf(pObj) ) + Ivy_ManSetLevels_rec( Ivy_ObjFanin1(pObj), fHaig ); + // get level of the node + if ( Ivy_ObjIsBuf(pObj) ) + pObj->Level = 1 + Ivy_ObjFanin0(pObj)->Level; + else if ( Ivy_ObjIsNode(pObj) ) + pObj->Level = Ivy_ObjLevelNew( pObj ); + else assert( 0 ); + // get level of other choices + if ( fHaig && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) + { + Ivy_Obj_t * pTemp; + unsigned LevelMax = pObj->Level; + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { + Ivy_ManSetLevels_rec( pTemp, fHaig ); + LevelMax = IVY_MAX( LevelMax, pTemp->Level ); + } + // get this level + pObj->Level = LevelMax; + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + pTemp->Level = LevelMax; + } + return pObj->Level; +} + +/**Function************************************************************* + + Synopsis [Sets the levels of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ) +{ + Ivy_Obj_t * pObj; + int i, LevelMax; + // check if CIs have choices + if ( fHaig ) + { + Ivy_ManForEachCi( p, pObj, i ) + if ( pObj->pEquiv ) + printf( "CI %d has a choice, which will not be visualized.\n", pObj->Id ); + } + // clean the levels + Ivy_ManForEachObj( p, pObj, i ) + pObj->Level = 0; + // compute the levels + LevelMax = 0; + Ivy_ManForEachCo( p, pObj, i ) + { + Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); + LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); + } + // compute levels of nodes without fanout + Ivy_ManForEachObj( p, pObj, i ) + if ( (Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj)) && Ivy_ObjRefs(pObj) == 0 ) + { + Ivy_ManSetLevels_rec( pObj, fHaig ); + LevelMax = IVY_MAX( LevelMax, (int)pObj->Level ); + } + // clean the marks + Ivy_ManForEachObj( p, pObj, i ) + Ivy_ObjClearMarkA(pObj); + return LevelMax; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyDsd.c b/abc70930/src/aig/ivy/ivyDsd.c new file mode 100644 index 00000000..3b8a2e68 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyDsd.c @@ -0,0 +1,819 @@ +/**CFile**************************************************************** + + FileName [ivyDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Disjoint-support decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyDsd.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// decomposition types +typedef enum { + IVY_DEC_PI, // 0: var + IVY_DEC_CONST1, // 1: CONST1 + IVY_DEC_BUF, // 2: BUF + IVY_DEC_AND, // 3: AND + IVY_DEC_EXOR, // 4: EXOR + IVY_DEC_MUX, // 5: MUX + IVY_DEC_MAJ, // 6: MAJ + IVY_DEC_PRIME // 7: undecomposable +} Ivy_DecType_t; + +typedef struct Ivy_Dec_t_ Ivy_Dec_t; +struct Ivy_Dec_t_ +{ + unsigned Type : 4; // the node type (PI, CONST1, AND, EXOR, MUX, PRIME) + unsigned fCompl : 1; // shows if node is complemented (root node only) + unsigned nFans : 3; // the number of fanins + unsigned Fan0 : 4; // fanin 0 + unsigned Fan1 : 4; // fanin 1 + unsigned Fan2 : 4; // fanin 2 + unsigned Fan3 : 4; // fanin 3 + unsigned Fan4 : 4; // fanin 4 + unsigned Fan5 : 4; // fanin 5 +}; + +static inline int Ivy_DecToInt( Ivy_Dec_t Node ) { return *((int *)&Node); } +static inline Ivy_Dec_t Ivy_IntToDec( int Node ) { return *((Ivy_Dec_t *)&Node); } +static inline void Ivy_DecClear( Ivy_Dec_t * pNode ) { *((int *)pNode) = 0; } + + +static unsigned s_Masks[6][2] = { + { 0x55555555, 0xAAAAAAAA }, + { 0x33333333, 0xCCCCCCCC }, + { 0x0F0F0F0F, 0xF0F0F0F0 }, + { 0x00FF00FF, 0xFF00FF00 }, + { 0x0000FFFF, 0xFFFF0000 }, + { 0x00000000, 0xFFFFFFFF } +}; + +static inline int Ivy_TruthWordCountOnes( unsigned uWord ) +{ + uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); + uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); + uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); + uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); + return (uWord & 0x0000FFFF) + (uWord>>16); +} + +static inline int Ivy_TruthCofactorIsConst( unsigned uTruth, int Var, int Cof, int Const ) +{ + if ( Const == 0 ) + return (uTruth & s_Masks[Var][Cof]) == 0; + else + return (uTruth & s_Masks[Var][Cof]) == s_Masks[Var][Cof]; +} + +static inline int Ivy_TruthCofactorIsOne( unsigned uTruth, int Var ) +{ + return (uTruth & s_Masks[Var][0]) == 0; +} + +static inline unsigned Ivy_TruthCofactor( unsigned uTruth, int Var ) +{ + unsigned uCofactor = uTruth & s_Masks[Var >> 1][(Var & 1) == 0]; + int Shift = (1 << (Var >> 1)); + if ( Var & 1 ) + return uCofactor | (uCofactor << Shift); + return uCofactor | (uCofactor >> Shift); +} + +static inline unsigned Ivy_TruthCofactor2( unsigned uTruth, int Var0, int Var1 ) +{ + return Ivy_TruthCofactor( Ivy_TruthCofactor(uTruth, Var0), Var1 ); +} + +// returns 1 if the truth table depends on this var (var is regular interger var) +static inline int Ivy_TruthDepends( unsigned uTruth, int Var ) +{ + return Ivy_TruthCofactor(uTruth, Var << 1) != Ivy_TruthCofactor(uTruth, (Var << 1) | 1); +} + +static inline void Ivy_DecSetVar( Ivy_Dec_t * pNode, int iNum, unsigned Var ) +{ + assert( iNum >= 0 && iNum <= 5 ); + switch( iNum ) + { + case 0: pNode->Fan0 = Var; break; + case 1: pNode->Fan1 = Var; break; + case 2: pNode->Fan2 = Var; break; + case 3: pNode->Fan3 = Var; break; + case 4: pNode->Fan4 = Var; break; + case 5: pNode->Fan5 = Var; break; + } +} + +static inline unsigned Ivy_DecGetVar( Ivy_Dec_t * pNode, int iNum ) +{ + assert( iNum >= 0 && iNum <= 5 ); + switch( iNum ) + { + case 0: return pNode->Fan0; + case 1: return pNode->Fan1; + case 2: return pNode->Fan2; + case 3: return pNode->Fan3; + case 4: return pNode->Fan4; + case 5: return pNode->Fan5; + } + return ~0; +} + +static int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ); +static int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ); + +//int nTruthDsd; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes DSD of truth table of 5 variables or less.] + + Description [Returns 1 if the function is a constant or is fully + DSD decomposable using AND/EXOR/MUX gates.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ) +{ + Ivy_Dec_t Node; + int i, RetValue; + // set the PI variables + Vec_IntClear( vTree ); + for ( i = 0; i < 5; i++ ) + Vec_IntPush( vTree, 0 ); + // check if it is a constant + if ( uTruth == 0 || ~uTruth == 0 ) + { + Ivy_DecClear( &Node ); + Node.Type = IVY_DEC_CONST1; + Node.fCompl = (uTruth == 0); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return 1; + } + // perform the decomposition + RetValue = Ivy_TruthDecompose_rec( uTruth, vTree ); + if ( RetValue == -1 ) + return 0; + // get the topmost node + if ( (RetValue >> 1) < 5 ) + { // add buffer + Ivy_DecClear( &Node ); + Node.Type = IVY_DEC_BUF; + Node.fCompl = (RetValue & 1); + Node.Fan0 = ((RetValue >> 1) << 1); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + } + else if ( RetValue & 1 ) + { // check if the topmost node has to be complemented + Node = Ivy_IntToDec( Vec_IntPop(vTree) ); + assert( Node.fCompl == 0 ); + Node.fCompl = (RetValue & 1); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + } + if ( uTruth != Ivy_TruthDsdCompute(vTree) ) + printf( "Verification failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes DSD of truth table.] + + Description [Returns the number of topmost decomposition node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ) +{ + Ivy_Dec_t Node; + int Supp[5], Vars0[5], Vars1[5], Vars2[5], * pVars; + int nSupp, Count0, Count1, Count2, nVars, RetValue, fCompl, i; + unsigned uTruthCof, uCof0, uCof1; + + // get constant confactors + Count0 = Count1 = Count2 = nSupp = 0; + for ( i = 0; i < 5; i++ ) + { + if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 0) ) + Vars0[Count0++] = (i << 1) | 0; + else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 0) ) + Vars0[Count0++] = (i << 1) | 1; + else if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 1) ) + Vars1[Count1++] = (i << 1) | 0; + else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 1) ) + Vars1[Count1++] = (i << 1) | 1; + else + { + uCof0 = Ivy_TruthCofactor( uTruth, (i << 1) | 1 ); + uCof1 = Ivy_TruthCofactor( uTruth, (i << 1) | 0 ); + if ( uCof0 == ~uCof1 ) + Vars2[Count2++] = (i << 1) | 0; + else if ( uCof0 != uCof1 ) + Supp[nSupp++] = i; + } + } + assert( Count0 == 0 || Count1 == 0 ); + assert( Count0 == 0 || Count2 == 0 ); + assert( Count1 == 0 || Count2 == 0 ); + + // consider the case of a single variable + if ( Count0 == 1 && nSupp == 0 ) + return Vars0[0]; + + // consider more complex decompositions + if ( Count0 == 0 && Count1 == 0 && Count2 == 0 ) + return Ivy_TruthRecognizeMuxMaj( uTruth, Supp, nSupp, vTree ); + + // extract the nodes + Ivy_DecClear( &Node ); + if ( Count0 > 0 ) + nVars = Count0, pVars = Vars0, Node.Type = IVY_DEC_AND, fCompl = 0; + else if ( Count1 > 0 ) + nVars = Count1, pVars = Vars1, Node.Type = IVY_DEC_AND, fCompl = 1, uTruth = ~uTruth; + else if ( Count2 > 0 ) + nVars = Count2, pVars = Vars2, Node.Type = IVY_DEC_EXOR, fCompl = 0; + else + assert( 0 ); + Node.nFans = nVars+(nSupp>0); + + // compute cofactor + uTruthCof = uTruth; + for ( i = 0; i < nVars; i++ ) + { + uTruthCof = Ivy_TruthCofactor( uTruthCof, pVars[i] ); + Ivy_DecSetVar( &Node, i, pVars[i] ); + } + + if ( Node.Type == IVY_DEC_EXOR ) + fCompl ^= ((Node.nFans & 1) == 0); + + if ( nSupp > 0 ) + { + assert( uTruthCof != 0 && ~uTruthCof != 0 ); + // call recursively + RetValue = Ivy_TruthDecompose_rec( uTruthCof, vTree ); + // quit if non-decomposable + if ( RetValue == -1 ) + return -1; + // remove the complement from the child if the node is EXOR + if ( Node.Type == IVY_DEC_EXOR && (RetValue & 1) ) + { + fCompl ^= 1; + RetValue ^= 1; + } + // set the new decomposition + Ivy_DecSetVar( &Node, nVars, RetValue ); + } + else if ( Node.Type == IVY_DEC_EXOR ) + fCompl ^= (uTruthCof == 0); + + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return ((Vec_IntSize(vTree)-1) << 1) | fCompl; +} + +/**Function************************************************************* + + Synopsis [Returns a non-negative number if the truth table is a MUX.] + + Description [If the truth table is a MUX, returns the variable as follows: + first, control variable; second, positive cofactor; third, negative cofactor.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ) +{ + Ivy_Dec_t Node; + int i, k, RetValue0, RetValue1; + unsigned uCof0, uCof1, Num; + char Count[3]; + assert( nSupp >= 3 ); + // start the node + Ivy_DecClear( &Node ); + Node.Type = IVY_DEC_MUX; + Node.nFans = 3; + // try each of the variables + for ( i = 0; i < nSupp; i++ ) + { + // get the cofactors with respect to these variables + uCof0 = Ivy_TruthCofactor( uTruth, (pSupp[i] << 1) | 1 ); + uCof1 = Ivy_TruthCofactor( uTruth, pSupp[i] << 1 ); + // go through all other variables and make sure + // each of them belongs to the support of one cofactor + for ( k = 0; k < nSupp; k++ ) + { + if ( k == i ) + continue; + if ( Ivy_TruthDepends(uCof0, pSupp[k]) && Ivy_TruthDepends(uCof1, pSupp[k]) ) + break; + } + if ( k < nSupp ) + continue; + // MUX decomposition exists + RetValue0 = Ivy_TruthDecompose_rec( uCof0, vTree ); + if ( RetValue0 == -1 ) + break; + RetValue1 = Ivy_TruthDecompose_rec( uCof1, vTree ); + if ( RetValue1 == -1 ) + break; + // both of them exist; create the node + Ivy_DecSetVar( &Node, 0, pSupp[i] << 1 ); + Ivy_DecSetVar( &Node, 1, RetValue1 ); + Ivy_DecSetVar( &Node, 2, RetValue0 ); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return ((Vec_IntSize(vTree)-1) << 1) | 0; + } + // check majority gate + if ( nSupp > 3 ) + return -1; + if ( Ivy_TruthWordCountOnes(uTruth) != 16 ) + return -1; + // this is a majority gate; determine polarity + Node.Type = IVY_DEC_MAJ; + Count[0] = Count[1] = Count[2] = 0; + for ( i = 0; i < 8; i++ ) + { + Num = 0; + for ( k = 0; k < 3; k++ ) + if ( i & (1 << k) ) + Num |= (1 << pSupp[k]); + assert( Num < 32 ); + if ( (uTruth & (1 << Num)) == 0 ) + continue; + for ( k = 0; k < 3; k++ ) + if ( i & (1 << k) ) + Count[k]++; + } + assert( Count[0] == 1 || Count[0] == 3 ); + assert( Count[1] == 1 || Count[1] == 3 ); + assert( Count[2] == 1 || Count[2] == 3 ); + Ivy_DecSetVar( &Node, 0, (pSupp[0] << 1)|(Count[0] == 1) ); + Ivy_DecSetVar( &Node, 1, (pSupp[1] << 1)|(Count[1] == 1) ); + Ivy_DecSetVar( &Node, 2, (pSupp[2] << 1)|(Count[2] == 1) ); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return ((Vec_IntSize(vTree)-1) << 1) | 0; +} + + +/**Function************************************************************* + + Synopsis [Computes truth table of decomposition tree for verification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_TruthDsdCompute_rec( int iNode, Vec_Int_t * vTree ) +{ + unsigned uTruthChild, uTruthTotal; + int Var, i; + // get the node + Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); + // compute the node function + if ( Node.Type == IVY_DEC_CONST1 ) + return s_Masks[5][ !Node.fCompl ]; + if ( Node.Type == IVY_DEC_PI ) + return s_Masks[iNode][ !Node.fCompl ]; + if ( Node.Type == IVY_DEC_BUF ) + { + uTruthTotal = Ivy_TruthDsdCompute_rec( Node.Fan0 >> 1, vTree ); + return Node.fCompl? ~uTruthTotal : uTruthTotal; + } + if ( Node.Type == IVY_DEC_AND ) + { + uTruthTotal = s_Masks[5][1]; + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + uTruthChild = Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); + uTruthTotal = (Var & 1)? uTruthTotal & ~uTruthChild : uTruthTotal & uTruthChild; + } + return Node.fCompl? ~uTruthTotal : uTruthTotal; + } + if ( Node.Type == IVY_DEC_EXOR ) + { + uTruthTotal = 0; + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + uTruthTotal ^= Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); + assert( (Var & 1) == 0 ); + } + return Node.fCompl? ~uTruthTotal : uTruthTotal; + } + assert( Node.fCompl == 0 ); + if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) + { + unsigned uTruthChildC, uTruthChild1, uTruthChild0; + int VarC, Var1, Var0; + VarC = Ivy_DecGetVar( &Node, 0 ); + Var1 = Ivy_DecGetVar( &Node, 1 ); + Var0 = Ivy_DecGetVar( &Node, 2 ); + uTruthChildC = Ivy_TruthDsdCompute_rec( VarC >> 1, vTree ); + uTruthChild1 = Ivy_TruthDsdCompute_rec( Var1 >> 1, vTree ); + uTruthChild0 = Ivy_TruthDsdCompute_rec( Var0 >> 1, vTree ); + assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); + uTruthChildC = (VarC & 1)? ~uTruthChildC : uTruthChildC; + uTruthChild1 = (Var1 & 1)? ~uTruthChild1 : uTruthChild1; + uTruthChild0 = (Var0 & 1)? ~uTruthChild0 : uTruthChild0; + if ( Node.Type == IVY_DEC_MUX ) + return (uTruthChildC & uTruthChild1) | (~uTruthChildC & uTruthChild0); + else + return (uTruthChildC & uTruthChild1) | (uTruthChildC & uTruthChild0) | (uTruthChild1 & uTruthChild0); + } + assert( 0 ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Computes truth table of decomposition tree for verification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ) +{ + return Ivy_TruthDsdCompute_rec( Vec_IntSize(vTree)-1, vTree ); +} + +/**Function************************************************************* + + Synopsis [Prints the decomposition tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthDsdPrint_rec( FILE * pFile, int iNode, Vec_Int_t * vTree ) +{ + int Var, i; + // get the node + Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); + // compute the node function + if ( Node.Type == IVY_DEC_CONST1 ) + fprintf( pFile, "Const1%s", (Node.fCompl? "\'" : "") ); + else if ( Node.Type == IVY_DEC_PI ) + fprintf( pFile, "%c%s", 'a' + iNode, (Node.fCompl? "\'" : "") ); + else if ( Node.Type == IVY_DEC_BUF ) + { + Ivy_TruthDsdPrint_rec( pFile, Node.Fan0 >> 1, vTree ); + fprintf( pFile, "%s", (Node.fCompl? "\'" : "") ); + } + else if ( Node.Type == IVY_DEC_AND ) + { + fprintf( pFile, "AND(" ); + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); + fprintf( pFile, "%s", (Var & 1)? "\'" : "" ); + if ( i != (int)Node.nFans-1 ) + fprintf( pFile, "," ); + } + fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); + } + else if ( Node.Type == IVY_DEC_EXOR ) + { + fprintf( pFile, "EXOR(" ); + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); + if ( i != (int)Node.nFans-1 ) + fprintf( pFile, "," ); + assert( (Var & 1) == 0 ); + } + fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); + } + else if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) + { + int VarC, Var1, Var0; + assert( Node.fCompl == 0 ); + VarC = Ivy_DecGetVar( &Node, 0 ); + Var1 = Ivy_DecGetVar( &Node, 1 ); + Var0 = Ivy_DecGetVar( &Node, 2 ); + fprintf( pFile, "%s", (Node.Type == IVY_DEC_MUX)? "MUX(" : "MAJ(" ); + Ivy_TruthDsdPrint_rec( pFile, VarC >> 1, vTree ); + fprintf( pFile, "%s", (VarC & 1)? "\'" : "" ); + fprintf( pFile, "," ); + Ivy_TruthDsdPrint_rec( pFile, Var1 >> 1, vTree ); + fprintf( pFile, "%s", (Var1 & 1)? "\'" : "" ); + fprintf( pFile, "," ); + Ivy_TruthDsdPrint_rec( pFile, Var0 >> 1, vTree ); + fprintf( pFile, "%s", (Var0 & 1)? "\'" : "" ); + fprintf( pFile, ")" ); + } + else assert( 0 ); +} + + +/**Function************************************************************* + + Synopsis [Prints the decomposition tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ) +{ + fprintf( pFile, "F = " ); + Ivy_TruthDsdPrint_rec( pFile, Vec_IntSize(vTree)-1, vTree ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Implement DSD in the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ManDsdConstruct_rec( Ivy_Man_t * p, Vec_Int_t * vFront, int iNode, Vec_Int_t * vTree ) +{ + Ivy_Obj_t * pResult, * pChild, * pNodes[16]; + int Var, i; + // get the node + Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); + // compute the node function + if ( Node.Type == IVY_DEC_CONST1 ) + return Ivy_NotCond( Ivy_ManConst1(p), Node.fCompl ); + if ( Node.Type == IVY_DEC_PI ) + { + pResult = Ivy_ManObj( p, Vec_IntEntry(vFront, iNode) ); + return Ivy_NotCond( pResult, Node.fCompl ); + } + if ( Node.Type == IVY_DEC_BUF ) + { + pResult = Ivy_ManDsdConstruct_rec( p, vFront, Node.Fan0 >> 1, vTree ); + return Ivy_NotCond( pResult, Node.fCompl ); + } + if ( Node.Type == IVY_DEC_AND || Node.Type == IVY_DEC_EXOR ) + { + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + assert( Node.Type == IVY_DEC_AND || (Var & 1) == 0 ); + pChild = Ivy_ManDsdConstruct_rec( p, vFront, Var >> 1, vTree ); + pChild = Ivy_NotCond( pChild, (Var & 1) ); + pNodes[i] = pChild; + } + +// Ivy_MultiEval( pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); + + pResult = Ivy_Multi( p, pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); + return Ivy_NotCond( pResult, Node.fCompl ); + } + assert( Node.fCompl == 0 ); + if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) + { + int VarC, Var1, Var0; + VarC = Ivy_DecGetVar( &Node, 0 ); + Var1 = Ivy_DecGetVar( &Node, 1 ); + Var0 = Ivy_DecGetVar( &Node, 2 ); + pNodes[0] = Ivy_ManDsdConstruct_rec( p, vFront, VarC >> 1, vTree ); + pNodes[1] = Ivy_ManDsdConstruct_rec( p, vFront, Var1 >> 1, vTree ); + pNodes[2] = Ivy_ManDsdConstruct_rec( p, vFront, Var0 >> 1, vTree ); + assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); + pNodes[0] = Ivy_NotCond( pNodes[0], (VarC & 1) ); + pNodes[1] = Ivy_NotCond( pNodes[1], (Var1 & 1) ); + pNodes[2] = Ivy_NotCond( pNodes[2], (Var0 & 1) ); + if ( Node.Type == IVY_DEC_MUX ) + return Ivy_Mux( p, pNodes[0], pNodes[1], pNodes[2] ); + else + return Ivy_Maj( p, pNodes[0], pNodes[1], pNodes[2] ); + } + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Implement DSD in the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ) +{ + int Entry, i; + // implement latches on the frontier (TEMPORARY!!!) + Vec_IntForEachEntry( vFront, Entry, i ) + Vec_IntWriteEntry( vFront, i, Ivy_LeafId(Entry) ); + // recursively construct the tree + return Ivy_ManDsdConstruct_rec( p, vFront, Vec_IntSize(vTree)-1, vTree ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthDsdComputePrint( unsigned uTruth ) +{ + static Vec_Int_t * vTree = NULL; + if ( vTree == NULL ) + vTree = Vec_IntAlloc( 12 ); + if ( Ivy_TruthDsd( uTruth, vTree ) ) + Ivy_TruthDsdPrint( stdout, vTree ); + else + printf( "Undecomposable\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTestOne( unsigned uTruth ) +{ + static int Counter = 0; + static Vec_Int_t * vTree = NULL; + // decompose + if ( vTree == NULL ) + vTree = Vec_IntAlloc( 12 ); + + if ( !Ivy_TruthDsd( uTruth, vTree ) ) + { +// printf( "Undecomposable\n" ); + } + else + { +// nTruthDsd++; + printf( "%5d : ", Counter++ ); + Extra_PrintBinary( stdout, &uTruth, 32 ); + printf( " " ); + Ivy_TruthDsdPrint( stdout, vTree ); + if ( uTruth != Ivy_TruthDsdCompute(vTree) ) + printf( "Verification failed.\n" ); + } +// Vec_IntFree( vTree ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTest() +{ + FILE * pFile; + char Buffer[100]; + unsigned uTruth; + int i; + + pFile = fopen( "npn4.txt", "r" ); + for ( i = 0; i < 222; i++ ) +// pFile = fopen( "npn5.txt", "r" ); +// for ( i = 0; i < 616126; i++ ) + { + fscanf( pFile, "%s", Buffer ); + Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); +// Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); + uTruth |= (uTruth << 16); +// uTruth = ~uTruth; + Ivy_TruthTestOne( uTruth ); + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTest3() +{ + FILE * pFile; + char Buffer[100]; + unsigned uTruth; + int i; + + pFile = fopen( "npn3.txt", "r" ); + for ( i = 0; i < 14; i++ ) + { + fscanf( pFile, "%s", Buffer ); + Extra_ReadHexadecimal( &uTruth, Buffer+2, 3 ); + uTruth = uTruth | (uTruth << 8) | (uTruth << 16) | (uTruth << 24); + Ivy_TruthTestOne( uTruth ); + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTest5() +{ + FILE * pFile; + char Buffer[100]; + unsigned uTruth; + int i; + +// pFile = fopen( "npn4.txt", "r" ); +// for ( i = 0; i < 222; i++ ) + pFile = fopen( "npn5.txt", "r" ); + for ( i = 0; i < 616126; i++ ) + { + fscanf( pFile, "%s", Buffer ); +// Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); + Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); +// uTruth |= (uTruth << 16); +// uTruth = ~uTruth; + Ivy_TruthTestOne( uTruth ); + } + fclose( pFile ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyFanout.c b/abc70930/src/aig/ivy/ivyFanout.c new file mode 100644 index 00000000..3930186a --- /dev/null +++ b/abc70930/src/aig/ivy/ivyFanout.c @@ -0,0 +1,309 @@ +/**CFile**************************************************************** + + FileName [ivyFanout.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Representation of the fanouts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyFanout.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// getting hold of the next fanout of the node +static inline Ivy_Obj_t * Ivy_ObjNextFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( pFanout == NULL ) + return NULL; + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return pFanout->pNextFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return pFanout->pNextFan1; +} + +// getting hold of the previous fanout of the node +static inline Ivy_Obj_t * Ivy_ObjPrevFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( pFanout == NULL ) + return NULL; + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return pFanout->pPrevFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return pFanout->pPrevFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return &pFanout->pNextFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return &pFanout->pNextFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return &pFanout->pPrevFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return &pFanout->pPrevFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjPrevNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + pTemp = Ivy_ObjPrevFanout(pObj, pFanout); + if ( pTemp == NULL ) + return &pObj->pFanout; + if ( Ivy_ObjFanin0(pTemp) == pObj ) + return &pTemp->pNextFan0; + assert( Ivy_ObjFanin1(pTemp) == pObj ); + return &pTemp->pNextFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjNextPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + pTemp = Ivy_ObjNextFanout(pObj, pFanout); + if ( pTemp == NULL ) + return NULL; + if ( Ivy_ObjFanin0(pTemp) == pObj ) + return &pTemp->pPrevFan0; + assert( Ivy_ObjFanin1(pTemp) == pObj ); + return &pTemp->pPrevFan1; +} + +// iterator through the fanouts of the node +#define Ivy_ObjForEachFanoutInt( pObj, pFanout ) \ + for ( pFanout = (pObj)->pFanout; pFanout; \ + pFanout = Ivy_ObjNextFanout(pObj, pFanout) ) + +// safe iterator through the fanouts of the node +#define Ivy_ObjForEachFanoutIntSafe( pObj, pFanout, pFanout2 ) \ + for ( pFanout = (pObj)->pFanout, \ + pFanout2 = Ivy_ObjNextFanout(pObj, pFanout); \ + pFanout; \ + pFanout = pFanout2, \ + pFanout2 = Ivy_ObjNextFanout(pObj, pFanout) ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the fanout representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStartFanout( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + assert( !p->fFanout ); + p->fFanout = 1; + Ivy_ManForEachObj( p, pObj, i ) + { + if ( Ivy_ObjFanin0(pObj) ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); + if ( Ivy_ObjFanin1(pObj) ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Stops the fanout representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStopFanout( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + assert( p->fFanout ); + p->fFanout = 0; + Ivy_ManForEachObj( p, pObj, i ) + pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; +} + +/**Function************************************************************* + + Synopsis [Add the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) +{ + assert( p->fFanout ); + if ( pFanin->pFanout ) + { + *Ivy_ObjNextFanoutPlace(pFanin, pFanout) = pFanin->pFanout; + *Ivy_ObjPrevFanoutPlace(pFanin, pFanin->pFanout) = pFanout; + } + pFanin->pFanout = pFanout; +} + +/**Function************************************************************* + + Synopsis [Removes the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) +{ + Ivy_Obj_t ** ppPlace1, ** ppPlace2, ** ppPlaceN; + assert( pFanin->pFanout != NULL ); + + ppPlace1 = Ivy_ObjNextFanoutPlace(pFanin, pFanout); + ppPlaceN = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanout); + assert( *ppPlaceN == pFanout ); + if ( ppPlaceN ) + *ppPlaceN = *ppPlace1; + + ppPlace2 = Ivy_ObjPrevFanoutPlace(pFanin, pFanout); + ppPlaceN = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanout); + assert( ppPlaceN == NULL || *ppPlaceN == pFanout ); + if ( ppPlaceN ) + *ppPlaceN = *ppPlace2; + + *ppPlace1 = NULL; + *ppPlace2 = NULL; +} + +/**Function************************************************************* + + Synopsis [Replaces the fanout of pOld to be pFanoutNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ) +{ + Ivy_Obj_t ** ppPlace; + ppPlace = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanoutOld); + assert( *ppPlace == pFanoutOld ); + if ( ppPlace ) + *ppPlace = pFanoutNew; + ppPlace = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanoutOld); + assert( ppPlace == NULL || *ppPlace == pFanoutOld ); + if ( ppPlace ) + *ppPlace = pFanoutNew; + // assuming that pFanoutNew already points to the next fanout +} + +/**Function************************************************************* + + Synopsis [Starts iteration through the fanouts.] + + Description [Copies the currently available fanouts into the array.] + + SideEffects [Can be used while the fanouts are being removed.] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ) +{ + Ivy_Obj_t * pFanout; + assert( p->fFanout ); + assert( !Ivy_IsComplement(pObj) ); + Vec_PtrClear( vArray ); + Ivy_ObjForEachFanoutInt( pObj, pFanout ) + Vec_PtrPush( vArray, pFanout ); +} + +/**Function************************************************************* + + Synopsis [Reads one fanout.] + + Description [Returns fanout if there is only one fanout.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + return pObj->pFanout; +} + +/**Function************************************************************* + + Synopsis [Reads one fanout.] + + Description [Returns fanout if there is only one fanout.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanout; + int Counter = 0; + Ivy_ObjForEachFanoutInt( pObj, pFanout ) + Counter++; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyFastMap.c b/abc70930/src/aig/ivy/ivyFastMap.c new file mode 100644 index 00000000..c4a043f2 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyFastMap.c @@ -0,0 +1,1593 @@ +/**CFile**************************************************************** + + FileName [ivyFastMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Fast FPGA mapping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyFastMap.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IVY_INFINITY 10000 + +typedef struct Ivy_SuppMan_t_ Ivy_SuppMan_t; +struct Ivy_SuppMan_t_ +{ + int nLimit; // the limit on the number of inputs + int nObjs; // the number of entries + int nSize; // size of each entry in bytes + char * pMem; // memory allocated + Vec_Vec_t * vLuts; // the array of nodes used in the mapping +}; + +typedef struct Ivy_Supp_t_ Ivy_Supp_t; +struct Ivy_Supp_t_ +{ + char nSize; // the number of support nodes + char fMark; // multipurpose mask + char fMark2; // multipurpose mask + char fMark3; // multipurpose mask + int nRefs; // the number of references + short Delay; // the delay of the node + short DelayR; // the reverse delay of the node + int pArray[0]; // the support nodes +}; + +static inline Ivy_Supp_t * Ivy_ObjSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + return (Ivy_Supp_t *)(((Ivy_SuppMan_t*)pAig->pData)->pMem + pObj->Id * ((Ivy_SuppMan_t*)pAig->pData)->nSize); +} +static inline Ivy_Supp_t * Ivy_ObjSuppStart( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp; + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->fMark = 0; + pSupp->Delay = 0; + pSupp->nSize = 1; + pSupp->pArray[0] = pObj->Id; + return pSupp; +} + +static void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, int Time, char * pStr ); +static int Ivy_FastMapDelay( Ivy_Man_t * pAig ); +static int Ivy_FastMapArea( Ivy_Man_t * pAig ); +static void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); +static void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); +static int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ); +static void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ); +static void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ); +static int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ); +static int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); + + +extern int s_MappingTime; +extern int s_MappingMem; + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs fast K-LUT mapping of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ) +{ + Ivy_SuppMan_t * pMan; + Ivy_Obj_t * pObj; + int i, Delay, Area, clk, clkTotal = clock(); + // start the memory for supports + pMan = ALLOC( Ivy_SuppMan_t, 1 ); + memset( pMan, 0, sizeof(Ivy_SuppMan_t) ); + pMan->nLimit = nLimit; + pMan->nObjs = Ivy_ManObjIdMax(pAig) + 1; + pMan->nSize = sizeof(Ivy_Supp_t) + nLimit * sizeof(int); + pMan->pMem = (char *)malloc( pMan->nObjs * pMan->nSize ); + memset( pMan->pMem, 0, pMan->nObjs * pMan->nSize ); + pMan->vLuts = Vec_VecAlloc( 100 ); + pAig->pData = pMan; +clk = clock(); + // set the PI mapping + Ivy_ObjSuppStart( pAig, Ivy_ManConst1(pAig) ); + Ivy_ManForEachPi( pAig, pObj, i ) + Ivy_ObjSuppStart( pAig, pObj ); + // iterate through all nodes in the topological order + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_FastMapNode( pAig, pObj, nLimit ); + // find the best arrival time and area + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Delay oriented mapping: " ); + +// 2-1-2 (doing 2-1-2-1-2 improves 0.5%) + + if ( fRecovery ) + { +clk = clock(); + Ivy_FastMapRequired( pAig, Delay, 0 ); + // remap the nodes + Ivy_FastMapRecover( pAig, nLimit ); + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 2 : " ); + +clk = clock(); + Ivy_FastMapRequired( pAig, Delay, 0 ); + // iterate through all nodes in the topological order + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_FastMapNodeArea( pAig, pObj, nLimit ); + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 1 : " ); + +clk = clock(); + Ivy_FastMapRequired( pAig, Delay, 0 ); + // remap the nodes + Ivy_FastMapRecover( pAig, nLimit ); + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 2 : " ); + } + + + s_MappingTime = clock() - clkTotal; + s_MappingMem = pMan->nObjs * pMan->nSize; +/* + { + Vec_Ptr_t * vNodes; + vNodes = Vec_PtrAlloc( 100 ); + Vec_VecForEachEntry( pMan->vLuts, pObj, i, k ) + Vec_PtrPush( vNodes, pObj ); + Ivy_ManShow( pAig, 0, vNodes ); + Vec_PtrFree( vNodes ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Cleans memory used for decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapStop( Ivy_Man_t * pAig ) +{ + Ivy_SuppMan_t * p = pAig->pData; + Vec_VecFree( p->vLuts ); + free( p->pMem ); + free( p ); + pAig->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Prints statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, int Time, char * pStr ) +{ + printf( "%s : Delay = %3d. Area = %6d. ", pStr, Delay, Area ); + PRT( "Time", Time ); +} + +/**Function************************************************************* + + Synopsis [Computes delay after LUT mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapDelay( Ivy_Man_t * pAig ) +{ + Ivy_Supp_t * pSupp; + Ivy_Obj_t * pObj; + int i, DelayMax = 0; + Ivy_ManForEachPo( pAig, pObj, i ) + { + pObj = Ivy_ObjFanin0(pObj); + if ( !Ivy_ObjIsNode(pObj) ) + continue; + pSupp = Ivy_ObjSupp( pAig, pObj ); + if ( DelayMax < pSupp->Delay ) + DelayMax = pSupp->Delay; + } + return DelayMax; +} + +/**Function************************************************************* + + Synopsis [Computes area after mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapArea_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Vec_t * vLuts ) +{ + Ivy_Supp_t * pSupp; + int i, Counter; + pSupp = Ivy_ObjSupp( pAig, pObj ); + // skip visited nodes and PIs + if ( pSupp->fMark || pSupp->nSize == 1 ) + return 0; + pSupp->fMark = 1; + // compute the area of this node + Counter = 0; + for ( i = 0; i < pSupp->nSize; i++ ) + Counter += Ivy_FastMapArea_rec( pAig, Ivy_ManObj(pAig, pSupp->pArray[i]), vLuts ); + // add the node to the array of LUTs + Vec_VecPush( vLuts, pSupp->Delay, pObj ); + return 1 + Counter; +} + +/**Function************************************************************* + + Synopsis [Computes area after mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapArea( Ivy_Man_t * pAig ) +{ + Vec_Vec_t * vLuts; + Ivy_Obj_t * pObj; + int i, Counter = 0; + // get the array to store the nodes + vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; + Vec_VecClear( vLuts ); + // explore starting from each node + Ivy_ManForEachPo( pAig, pObj, i ) + Counter += Ivy_FastMapArea_rec( pAig, Ivy_ObjFanin0(pObj), vLuts ); + // clean the marks + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_ObjSupp( pAig, pObj )->fMark = 0; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_ObjIsNodeInt1( Ivy_Obj_t * pObj ) +{ + return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) == 1; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_ObjIsNodeInt2( Ivy_Obj_t * pObj ) +{ + return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) <= 2; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntSelectSort( int * pArray, int nSize ) +{ + int temp, i, j, best_i; + for ( i = 0; i < nSize-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nSize; j++ ) + if ( pArray[j] < pArray[best_i] ) + best_i = j; + temp = pArray[i]; + pArray[i] = pArray[best_i]; + pArray[best_i] = temp; + } +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntRemoveDup( int * pArray, int nSize ) +{ + int i, k; + if ( nSize < 2 ) + return nSize; + for ( i = k = 1; i < nSize; i++ ) + if ( pArray[i] != pArray[i-1] ) + pArray[k++] = pArray[i]; + return k; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeArea2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) +{ + static int Store[32], StoreSize; + static char Supp0[16], Supp1[16]; + static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; + static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; + Ivy_Obj_t * pFanin0, * pFanin1; + Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; + int RetValue, DelayOld; + assert( nLimit <= 32 ); + assert( Ivy_ObjIsNode(pObj) ); + // get the fanins + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + // get the supports + pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); + pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->fMark == 0 ); + // get the old delay of the node + DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); + assert( DelayOld <= pSupp->DelayR ); + // copy the current cut + memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); + StoreSize = pSupp->nSize; + // get the fanin support + if ( Ivy_ObjRefs(pFanin0) > 1 && pSupp0->Delay < pSupp->DelayR ) + { + pSupp0 = pTemp0; + pSupp0->nSize = 1; + pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); + } + // get the fanin support + if ( Ivy_ObjRefs(pFanin1) > 1 && pSupp1->Delay < pSupp->DelayR ) + { + pSupp1 = pTemp1; + pSupp1->nSize = 1; + pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); + } + // merge the cuts + if ( pSupp0->nSize < pSupp1->nSize ) + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + else + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + if ( !RetValue ) + { + pSupp->nSize = 2; + pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); + pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); + } + // check the resulting delay + pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); + if ( pSupp->Delay > pSupp->DelayR ) + { + pSupp->nSize = StoreSize; + memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); + pSupp->Delay = DelayOld; + } +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) +{ + static int Store[32], StoreSize; + static char Supp0[16], Supp1[16]; + static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; + static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; + Ivy_Obj_t * pFanin0, * pFanin1; + Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; + int RetValue, DelayOld, RefsOld; + int AreaBef, AreaAft; + assert( nLimit <= 32 ); + assert( Ivy_ObjIsNode(pObj) ); + // get the fanins + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + // get the supports + pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); + pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->fMark == 0 ); + + // get the area + if ( pSupp->nRefs == 0 ) + AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + else + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); +// if ( AreaBef == 1 ) +// return; + + // deref the cut if the node is refed + if ( pSupp->nRefs != 0 ) + Ivy_FastMapNodeDeref( pAig, pObj ); + + // get the old delay of the node + DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); + assert( DelayOld <= pSupp->DelayR ); + // copy the current cut + memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); + StoreSize = pSupp->nSize; + // get the fanin support + if ( Ivy_ObjRefs(pFanin0) > 2 && pSupp0->Delay < pSupp->DelayR ) +// if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results + { + pSupp0 = pTemp0; + pSupp0->nSize = 1; + pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); + } + // get the fanin support + if ( Ivy_ObjRefs(pFanin1) > 2 && pSupp1->Delay < pSupp->DelayR ) +// if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR ) + { + pSupp1 = pTemp1; + pSupp1->nSize = 1; + pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); + } + // merge the cuts + if ( pSupp0->nSize < pSupp1->nSize ) + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + else + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + if ( !RetValue ) + { + pSupp->nSize = 2; + pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); + pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); + } + + // check the resulting delay + pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); + + RefsOld = pSupp->nRefs; pSupp->nRefs = 0; + AreaAft = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + pSupp->nRefs = RefsOld; + + if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) +// if ( pSupp->Delay > pSupp->DelayR ) + { + pSupp->nSize = StoreSize; + memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); + pSupp->Delay = DelayOld; +// printf( "-" ); + } +// else +// printf( "+" ); + + if ( pSupp->nRefs != 0 ) + Ivy_FastMapNodeRef( pAig, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) +{ + Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; + int fFaninParam = 2; + int RetValue; + assert( Ivy_ObjIsNode(pObj) ); + // get the supports + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->fMark = 0; + // get the delays + if ( pSupp0->Delay == pSupp1->Delay ) + pSupp->Delay = (pSupp0->Delay == 0) ? pSupp0->Delay + 1: pSupp0->Delay; + else if ( pSupp0->Delay > pSupp1->Delay ) + { + pSupp->Delay = pSupp0->Delay; + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); + } + else // if ( pSupp0->Delay < pSupp1->Delay ) + { + pSupp->Delay = pSupp1->Delay; + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); + } + // merge the cuts + if ( pSupp0->nSize < pSupp1->nSize ) + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + else + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + if ( !RetValue ) + { + pSupp->Delay++; + if ( fFaninParam == 2 ) + { + pSupp->nSize = 2; + pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); + pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); + } + else if ( fFaninParam == 3 ) + { + Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + pSupp->nSize = 0; + // process the first fanin + if ( Ivy_ObjIsNodeInt1(pFanin0) ) + { + pFaninA = Ivy_ObjFanin0(pFanin0); + pFaninB = Ivy_ObjFanin1(pFanin0); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); + else + { + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); + // process the second fanin + if ( Ivy_ObjIsNodeInt1(pFanin1) ) + { + pFaninA = Ivy_ObjFanin0(pFanin1); + pFaninB = Ivy_ObjFanin1(pFanin1); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); + else + { + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); + // sort the fanins + Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); + pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); + assert( pSupp->pArray[0] < pSupp->pArray[1] ); + } + else if ( fFaninParam == 4 ) + { + Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + pSupp->nSize = 0; + // consider the case when exactly one of them is internal + if ( Ivy_ObjIsNodeInt1(pFanin0) ^ Ivy_ObjIsNodeInt1(pFanin1) ) + { + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); + if ( Ivy_ObjIsNodeInt1(pFanin0) && pSupp0->nSize < nLimit ) + { + pSupp->Delay = IVY_MAX( pSupp0->Delay, pSupp1->Delay + 1 ); + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp1->pArray[0] = Ivy_ObjId(pFanin1); + // merge the cuts + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + assert( RetValue ); + assert( pSupp->nSize > 1 ); + return; + } + if ( Ivy_ObjIsNodeInt1(pFanin1) && pSupp1->nSize < nLimit ) + { + pSupp->Delay = IVY_MAX( pSupp1->Delay, pSupp0->Delay + 1 ); + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp0->pArray[0] = Ivy_ObjId(pFanin0); + // merge the cuts + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + assert( RetValue ); + assert( pSupp->nSize > 1 ); + return; + } + } + // process the first fanin + if ( Ivy_ObjIsNodeInt1(pFanin0) ) + { + pFaninA = Ivy_ObjFanin0(pFanin0); + pFaninB = Ivy_ObjFanin1(pFanin0); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); + else + { + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); + // process the second fanin + if ( Ivy_ObjIsNodeInt1(pFanin1) ) + { + pFaninA = Ivy_ObjFanin0(pFanin1); + pFaninB = Ivy_ObjFanin1(pFanin1); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); + else + { + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); + // sort the fanins + Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); + pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); + assert( pSupp->pArray[0] < pSupp->pArray[1] ); + assert( pSupp->nSize > 1 ); + } + } + assert( pSupp->Delay > 0 ); +} + +/**Function************************************************************* + + Synopsis [Merges two supports] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ) +{ + int i, k, c; + assert( pSupp0->nSize >= pSupp1->nSize ); + // the case of the largest cut sizes + if ( pSupp0->nSize == nLimit && pSupp1->nSize == nLimit ) + { + for ( i = 0; i < pSupp0->nSize; i++ ) + if ( pSupp0->pArray[i] != pSupp1->pArray[i] ) + return 0; + for ( i = 0; i < pSupp0->nSize; i++ ) + pSupp->pArray[i] = pSupp0->pArray[i]; + pSupp->nSize = pSupp0->nSize; + return 1; + } + // the case when one of the cuts is the largest + if ( pSupp0->nSize == nLimit ) + { + for ( i = 0; i < pSupp1->nSize; i++ ) + { + for ( k = pSupp0->nSize - 1; k >= 0; k-- ) + if ( pSupp0->pArray[k] == pSupp1->pArray[i] ) + break; + if ( k == -1 ) // did not find + return 0; + } + for ( i = 0; i < pSupp0->nSize; i++ ) + pSupp->pArray[i] = pSupp0->pArray[i]; + pSupp->nSize = pSupp0->nSize; + return 1; + } + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < nLimit; c++ ) + { + if ( k == pSupp1->nSize ) + { + if ( i == pSupp0->nSize ) + { + pSupp->nSize = c; + return 1; + } + pSupp->pArray[c] = pSupp0->pArray[i++]; + continue; + } + if ( i == pSupp0->nSize ) + { + if ( k == pSupp1->nSize ) + { + pSupp->nSize = c; + return 1; + } + pSupp->pArray[c] = pSupp1->pArray[k++]; + continue; + } + if ( pSupp0->pArray[i] < pSupp1->pArray[k] ) + { + pSupp->pArray[c] = pSupp0->pArray[i++]; + continue; + } + if ( pSupp0->pArray[i] > pSupp1->pArray[k] ) + { + pSupp->pArray[c] = pSupp1->pArray[k++]; + continue; + } + pSupp->pArray[c] = pSupp0->pArray[i++]; + k++; + } + if ( i < pSupp0->nSize || k < pSupp1->nSize ) + return 0; + pSupp->nSize = c; + return 1; +} + +/**Function************************************************************* + + Synopsis [Creates integer vector with the support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ) +{ + Ivy_Supp_t * pSupp; + pSupp = Ivy_ObjSupp( pAig, pObj ); + vLeaves->nCap = 8; + vLeaves->nSize = pSupp->nSize; + vLeaves->pArray = pSupp->pArray; +} + +/**Function************************************************************* + + Synopsis [Sets the required times of the intermediate nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapRequired_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Ivy_Obj_t * pRoot, int DelayR ) +{ + Ivy_Supp_t * pSupp; + pSupp = Ivy_ObjSupp( pAig, pObj ); + if ( pObj != pRoot && (pSupp->nRefs > 0 || Ivy_ObjIsCi(pObj)) ) + return; + Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin0(pObj), pRoot, DelayR ); + Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin1(pObj), pRoot, DelayR ); +// assert( pObj == pRoot || pSupp->DelayR == IVY_INFINITY ); + pSupp->DelayR = DelayR; +} + +/**Function************************************************************* + + Synopsis [Computes the required times for each node.] + + Description [Sets reference counters for each node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ) +{ + Vec_Vec_t * vLuts; + Vec_Ptr_t * vNodes; + Ivy_Obj_t * pObj; + Ivy_Supp_t * pSupp, * pSuppF; + int i, k, c; + // clean the required times + Ivy_ManForEachPi( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->DelayR = IVY_INFINITY; + pSupp->nRefs = 0; + } + Ivy_ManForEachNode( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->DelayR = IVY_INFINITY; + pSupp->nRefs = 0; + } + // set the required times of the POs + Ivy_ManForEachPo( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); + pSupp->DelayR = Delay; + pSupp->nRefs++; + } + // get the levelized nodes used in the mapping + vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; + // propagate the required times + Vec_VecForEachLevelReverse( vLuts, vNodes, i ) + Vec_PtrForEachEntry( vNodes, pObj, k ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nRefs > 0 ); + for ( c = 0; c < pSupp->nSize; c++ ) + { + pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); + pSuppF->DelayR = IVY_MIN( pSuppF->DelayR, pSupp->DelayR - 1 ); + pSuppF->nRefs++; + } + } +/* + // print out some of the required times + Ivy_ManForEachPi( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + printf( "%d ", pSupp->DelayR ); + } + printf( "\n" ); +*/ + + if ( fSetInter ) + { + // set the required times of the intermediate nodes + Vec_VecForEachLevelReverse( vLuts, vNodes, i ) + Vec_PtrForEachEntry( vNodes, pObj, k ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + Ivy_FastMapRequired_rec( pAig, pObj, pObj, pSupp->DelayR ); + } + // make sure that all required times are assigned + Ivy_ManForEachNode( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->DelayR < IVY_INFINITY ); + } + } +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ) +{ + Vec_Ptr_t * vFront, * vFrontOld; + Ivy_Obj_t * pObj; + int i; + vFront = Vec_PtrAlloc( nLimit ); + vFrontOld = Vec_PtrAlloc( nLimit ); + Ivy_ManCleanTravId( pAig ); + // iterate through all nodes in the topological order + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_FastMapNodeRecover( pAig, pObj, nLimit, vFront, vFrontOld ); + Vec_PtrFree( vFrontOld ); + Vec_PtrFree( vFront ); +} + +/**Function************************************************************* + + Synopsis [Computes the delay of the cut rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp, * pSuppF; + int c, Delay = 0; + pSupp = Ivy_ObjSupp( pAig, pObj ); + for ( c = 0; c < pSupp->nSize; c++ ) + { + pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); + Delay = IVY_MAX( Delay, pSuppF->Delay ); + } + return 1 + Delay; +} + + +/**function************************************************************* + + synopsis [References the cut.] + + description [This procedure is similar to the procedure NodeReclaim.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp, * pSuppF; + Ivy_Obj_t * pNodeChild; + int aArea, i; + // start the area of this cut + aArea = 1; + // go through the children + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nSize > 1 ); + for ( i = 0; i < pSupp->nSize; i++ ) + { + pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); + pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); + assert( pSuppF->nRefs >= 0 ); + if ( pSuppF->nRefs++ > 0 ) + continue; + if ( pSuppF->nSize == 1 ) + continue; + aArea += Ivy_FastMapNodeRef( pAig, pNodeChild ); + } + return aArea; +} + +/**function************************************************************* + + synopsis [Dereferences the cut.] + + description [This procedure is similar to the procedure NodeRecusiveDeref.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp, * pSuppF; + Ivy_Obj_t * pNodeChild; + int aArea, i; + // start the area of this cut + aArea = 1; + // go through the children + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nSize > 1 ); + for ( i = 0; i < pSupp->nSize; i++ ) + { + pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); + pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); + assert( pSuppF->nRefs > 0 ); + if ( --pSuppF->nRefs > 0 ) + continue; + if ( pSuppF->nSize == 1 ) + continue; + aArea += Ivy_FastMapNodeDeref( pAig, pNodeChild ); + } + return aArea; +} + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp; + int aResult, aResult2; + if ( Ivy_ObjIsCi(pObj) ) + return 0; + assert( Ivy_ObjIsNode(pObj) ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nRefs > 0 ); + aResult = Ivy_FastMapNodeDeref( pAig, pObj ); + aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); + assert( aResult == aResult2 ); + return aResult; +} + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp; + int aResult, aResult2; + if ( Ivy_ObjIsCi(pObj) ) + return 0; + assert( Ivy_ObjIsNode(pObj) ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nRefs == 0 ); + aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); + aResult = Ivy_FastMapNodeDeref( pAig, pObj ); + assert( aResult == aResult2 ); + return aResult; +} + + + + +/**Function************************************************************* + + Synopsis [Counts the number of nodes with no external fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapCutCost( Ivy_Man_t * pAig, Vec_Ptr_t * vFront ) +{ + Ivy_Supp_t * pSuppF; + Ivy_Obj_t * pFanin; + int i, Counter = 0; + Vec_PtrForEachEntry( vFront, pFanin, i ) + { + pSuppF = Ivy_ObjSupp( pAig, pFanin ); + if ( pSuppF->nRefs == 0 ) + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapMark_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + if ( Ivy_ObjIsTravIdCurrent(pAig, pObj) ) + return; + assert( Ivy_ObjIsNode(pObj) ); + Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin0(pObj) ); + Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin1(pObj) ); + Ivy_ObjSetTravIdCurrent(pAig, pObj); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the number of fanins will grow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeWillGrow( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanin0, * pFanin1; + assert( Ivy_ObjIsNode(pObj) ); + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + return !Ivy_ObjIsTravIdCurrent(pAig, pFanin0) && !Ivy_ObjIsTravIdCurrent(pAig, pFanin1); +} + +/**Function************************************************************* + + Synopsis [Returns the increase in the number of fanins with no external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCost( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSuppF; + Ivy_Obj_t * pFanin; + int Counter = 0; + assert( Ivy_ObjIsNode(pObj) ); + // check if the node has external refs + pSuppF = Ivy_ObjSupp( pAig, pObj ); + if ( pSuppF->nRefs == 0 ) + Counter--; + // increment the number of fanins without external refs + pFanin = Ivy_ObjFanin0(pObj); + pSuppF = Ivy_ObjSupp( pAig, pFanin ); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) + Counter++; + // increment the number of fanins without external refs + pFanin = Ivy_ObjFanin1(pObj); + pSuppF = Ivy_ObjSupp( pAig, pFanin ); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Updates the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeFaninUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + assert( Ivy_ObjIsNode(pObj) ); + Vec_PtrRemove( vFront, pObj ); + pFanin = Ivy_ObjFanin0(pObj); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) + { + Ivy_ObjSetTravIdCurrent(pAig, pFanin); + Vec_PtrPush( vFront, pFanin ); + } + pFanin = Ivy_ObjFanin1(pObj); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) + { + Ivy_ObjSetTravIdCurrent(pAig, pFanin); + Vec_PtrPush( vFront, pFanin ); + } +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact0( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( vFront, pFanin, i ) + { + if ( Ivy_ObjIsCi(pFanin) ) + continue; + if ( Ivy_FastMapNodeWillGrow(pAig, pFanin) ) + continue; + if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) + { + Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact1( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( vFront, pFanin, i ) + { + if ( Ivy_ObjIsCi(pFanin) ) + continue; + if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) < 0 ) + { + Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( vFront, pFanin, i ) + { + if ( Ivy_ObjIsCi(pFanin) ) + continue; + if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) + { + Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact_int( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + if ( Ivy_FastMapNodeFaninCompact0(pAig, pObj, nLimit, vFront) ) + return 1; + if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact1(pAig, pObj, nLimit, vFront) ) + return 1; + if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact2(pAig, pObj, nLimit, vFront) ) + return 1; + assert( Vec_PtrSize(vFront) <= nLimit ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeFaninCompact( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + while ( Ivy_FastMapNodeFaninCompact_int( pAig, pObj, nLimit, vFront ) ); +} + +/**Function************************************************************* + + Synopsis [Prepares node mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodePrepare( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + Ivy_Obj_t * pFanin; + int i; + pSupp = Ivy_ObjSupp( pAig, pObj ); + // expand the cut downwards from the given place + Vec_PtrClear( vFront ); + Vec_PtrClear( vFrontOld ); + Ivy_ManIncrementTravId( pAig ); + for ( i = 0; i < pSupp->nSize; i++ ) + { + pFanin = Ivy_ManObj(pAig, pSupp->pArray[i]); + Vec_PtrPush( vFront, pFanin ); + Vec_PtrPush( vFrontOld, pFanin ); + Ivy_ObjSetTravIdCurrent( pAig, pFanin ); + } + // mark the nodes in the cone + Ivy_FastMapMark_rec( pAig, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) +{ + Ivy_Supp_t * pSupp; + Ivy_Obj_t * pFanin; + int i; + pSupp = Ivy_ObjSupp( pAig, pObj ); + // deref node's cut + Ivy_FastMapNodeDeref( pAig, pObj ); + // update the node's cut + pSupp->nSize = Vec_PtrSize(vFront); + Vec_PtrForEachEntry( vFront, pFanin, i ) + pSupp->pArray[i] = pFanin->Id; + // ref the new cut + Ivy_FastMapNodeRef( pAig, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeRecover2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + int CostBef, CostAft; + int AreaBef, AreaAft; + pSupp = Ivy_ObjSupp( pAig, pObj ); +// if ( pSupp->nRefs == 0 ) +// return; + if ( pSupp->nRefs == 0 ) + AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + else + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + // get the area + if ( AreaBef == 1 ) + return; + + if ( pSupp->nRefs == 0 ) + { + pSupp->nRefs = 1000000; + Ivy_FastMapNodeRef( pAig, pObj ); + } + // the cut is non-trivial + Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); + // iteratively modify the cut + CostBef = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); + CostAft = Ivy_FastMapCutCost( pAig, vFront ); + assert( CostBef >= CostAft ); + // update the node + Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); + // get the new area + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaAft > AreaBef ) + { + Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + assert( AreaAft == AreaBef ); + } + if ( pSupp->nRefs == 1000000 ) + { + pSupp->nRefs = 0; + Ivy_FastMapNodeDeref( pAig, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + int CostBef, CostAft; + int AreaBef, AreaAft; + int DelayOld; + pSupp = Ivy_ObjSupp( pAig, pObj ); + DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + assert( pSupp->Delay <= pSupp->DelayR ); + if ( pSupp->nRefs == 0 ) + return; + // get the area + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); +// if ( AreaBef == 1 ) +// return; + if ( pObj->Id == 102 ) + { + int x = 0; + } + // the cut is non-trivial + Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); + // iteratively modify the cut + Ivy_FastMapNodeDeref( pAig, pObj ); + CostBef = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); + CostAft = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeRef( pAig, pObj ); + assert( CostBef >= CostAft ); + // update the node + Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); + pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + // get the new area + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) + { + Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + assert( AreaAft == AreaBef ); + pSupp->Delay = DelayOld; + } +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeRecover4( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + int CostBef, CostAft; + int AreaBef, AreaAft; + int DelayOld; + pSupp = Ivy_ObjSupp( pAig, pObj ); + DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + assert( pSupp->Delay <= pSupp->DelayR ); +// if ( pSupp->nRefs == 0 ) +// return; +// AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + // get the area + if ( pSupp->nRefs == 0 ) + AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + else + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaBef == 1 ) + return; + + if ( pSupp->nRefs == 0 ) + { + pSupp->nRefs = 1000000; + Ivy_FastMapNodeRef( pAig, pObj ); + } + // the cut is non-trivial + Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); + // iteratively modify the cut + CostBef = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); + CostAft = Ivy_FastMapCutCost( pAig, vFront ); + assert( CostBef >= CostAft ); + // update the node + Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); + pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + // get the new area + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) + { + Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + assert( AreaAft == AreaBef ); + pSupp->Delay = DelayOld; + } + if ( pSupp->nRefs == 1000000 ) + { + pSupp->nRefs = 0; + Ivy_FastMapNodeDeref( pAig, pObj ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyFraig.c b/abc70930/src/aig/ivy/ivyFraig.c new file mode 100644 index 00000000..1ab91dd2 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyFraig.c @@ -0,0 +1,2762 @@ +/**CFile**************************************************************** + + FileName [ivyFraig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Functional reduction of AIGs] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyFraig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "satSolver.h" +#include "extra.h" +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ivy_FraigMan_t_ Ivy_FraigMan_t; +typedef struct Ivy_FraigSim_t_ Ivy_FraigSim_t; +typedef struct Ivy_FraigList_t_ Ivy_FraigList_t; + +struct Ivy_FraigList_t_ +{ + Ivy_Obj_t * pHead; + Ivy_Obj_t * pTail; + int nItems; +}; + +struct Ivy_FraigSim_t_ +{ + int Type; + Ivy_FraigSim_t * pNext; + Ivy_FraigSim_t * pFanin0; + Ivy_FraigSim_t * pFanin1; + unsigned pData[0]; +}; + +struct Ivy_FraigMan_t_ +{ + // general info + Ivy_FraigParams_t * pParams; // various parameters + // temporary backtrack limits because "sint64" cannot be defined in Ivy_FraigParams_t ... + sint64 nBTLimitGlobal; // global limit on the number of backtracks + sint64 nInsLimitGlobal;// global limit on the number of clause inspects + // AIG manager + Ivy_Man_t * pManAig; // the starting AIG manager + Ivy_Man_t * pManFraig; // the final AIG manager + // simulation information + int nSimWords; // the number of words + char * pSimWords; // the simulation info + Ivy_FraigSim_t * pSimStart; // the list of simulation info for internal nodes + // counter example storage + int nPatWords; // the number of words in the counter example + unsigned * pPatWords; // the counter example + int * pPatScores; // the scores of each pattern + // equivalence classes + Ivy_FraigList_t lClasses; // equivalence classes + Ivy_FraigList_t lCand; // candidatates + int nPairs; // the number of pairs of nodes + // equivalence checking + sat_solver * pSat; // SAT solver + int nSatVars; // the number of variables currently used + Vec_Ptr_t * vPiVars; // the PIs of the cone used + // other + ProgressBar * pProgress; + // statistics + int nSimRounds; + int nNodesMiter; + int nClassesZero; + int nClassesBeg; + int nClassesEnd; + int nPairsBeg; + int nPairsEnd; + int nSatCalls; + int nSatCallsSat; + int nSatCallsUnsat; + int nSatProof; + int nSatFails; + int nSatFailsReal; + // runtime + int timeSim; + int timeTrav; + int timeSat; + int timeSatUnsat; + int timeSatSat; + int timeSatFail; + int timeRef; + int timeTotal; + int time1; + int time2; +}; + +typedef struct Prove_ParamsStruct_t_ Prove_Params_t; +struct Prove_ParamsStruct_t_ +{ + // general parameters + int fUseFraiging; // enables fraiging + int fUseRewriting; // enables rewriting + int fUseBdds; // enables BDD construction when other methods fail + int fVerbose; // prints verbose stats + // iterations + int nItersMax; // the number of iterations + // mitering + int nMiteringLimitStart; // starting mitering limit + float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // rewriting + int nRewritingLimitStart; // the number of rewriting iterations + float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // fraiging + int nFraigingLimitStart; // starting backtrack(conflict) limit + float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // last-gasp BDD construction + int nBddSizeLimit; // the number of BDD nodes when construction is aborted + int fBddReorder; // enables dynamic BDD variable reordering + // last-gasp mitering + int nMiteringLimitLast; // final mitering limit + // global SAT solver limits + sint64 nTotalBacktrackLimit; // global limit on the number of backtracks + sint64 nTotalInspectLimit; // global limit on the number of clause inspects + // global resources applied + sint64 nTotalBacktracksMade; // the total number of backtracks made + sint64 nTotalInspectsMade; // the total number of inspects made +}; + +static inline Ivy_FraigSim_t * Ivy_ObjSim( Ivy_Obj_t * pObj ) { return (Ivy_FraigSim_t *)pObj->pFanout; } +static inline Ivy_Obj_t * Ivy_ObjClassNodeLast( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } +static inline Ivy_Obj_t * Ivy_ObjClassNodeRepr( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } +static inline Ivy_Obj_t * Ivy_ObjClassNodeNext( Ivy_Obj_t * pObj ) { return pObj->pNextFan1; } +static inline Ivy_Obj_t * Ivy_ObjNodeHashNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } +static inline Ivy_Obj_t * Ivy_ObjEquivListNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } +static inline Ivy_Obj_t * Ivy_ObjEquivListPrev( Ivy_Obj_t * pObj ) { return pObj->pPrevFan1; } +static inline Ivy_Obj_t * Ivy_ObjFraig( Ivy_Obj_t * pObj ) { return pObj->pEquiv; } +static inline int Ivy_ObjSatNum( Ivy_Obj_t * pObj ) { return (int)pObj->pNextFan0; } +static inline Vec_Ptr_t * Ivy_ObjFaninVec( Ivy_Obj_t * pObj ) { return (Vec_Ptr_t *)pObj->pNextFan1; } + +static inline void Ivy_ObjSetSim( Ivy_Obj_t * pObj, Ivy_FraigSim_t * pSim ) { pObj->pFanout = (Ivy_Obj_t *)pSim; } +static inline void Ivy_ObjSetClassNodeLast( Ivy_Obj_t * pObj, Ivy_Obj_t * pLast ) { pObj->pNextFan0 = pLast; } +static inline void Ivy_ObjSetClassNodeRepr( Ivy_Obj_t * pObj, Ivy_Obj_t * pRepr ) { pObj->pNextFan0 = pRepr; } +static inline void Ivy_ObjSetClassNodeNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pNextFan1 = pNext; } +static inline void Ivy_ObjSetNodeHashNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } +static inline void Ivy_ObjSetEquivListNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } +static inline void Ivy_ObjSetEquivListPrev( Ivy_Obj_t * pObj, Ivy_Obj_t * pPrev ) { pObj->pPrevFan1 = pPrev; } +static inline void Ivy_ObjSetFraig( Ivy_Obj_t * pObj, Ivy_Obj_t * pNode ) { pObj->pEquiv = pNode; } +static inline void Ivy_ObjSetSatNum( Ivy_Obj_t * pObj, int Num ) { pObj->pNextFan0 = (Ivy_Obj_t *)Num; } +static inline void Ivy_ObjSetFaninVec( Ivy_Obj_t * pObj, Vec_Ptr_t * vFanins ) { pObj->pNextFan1 = (Ivy_Obj_t *)vFanins; } + +static inline unsigned Ivy_ObjRandomSim() { return (rand() << 24) ^ (rand() << 12) ^ rand(); } + +// iterate through equivalence classes +#define Ivy_FraigForEachEquivClass( pList, pEnt ) \ + for ( pEnt = pList; \ + pEnt; \ + pEnt = Ivy_ObjEquivListNext(pEnt) ) +#define Ivy_FraigForEachEquivClassSafe( pList, pEnt, pEnt2 ) \ + for ( pEnt = pList, \ + pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL ) +// iterate through nodes in one class +#define Ivy_FraigForEachClassNode( pClass, pEnt ) \ + for ( pEnt = pClass; \ + pEnt; \ + pEnt = Ivy_ObjClassNodeNext(pEnt) ) +// iterate through nodes in the hash table +#define Ivy_FraigForEachBinNode( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = Ivy_ObjNodeHashNext(pEnt) ) + +static Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +static Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +static Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, sint64 nBTLimitGlobal, sint64 nInsLimitGlobal, sint64 * pnSatConfs, sint64 * pnSatInspects ); +static void Ivy_FraigPrint( Ivy_FraigMan_t * p ); +static void Ivy_FraigStop( Ivy_FraigMan_t * p ); +static void Ivy_FraigSimulate( Ivy_FraigMan_t * p ); +static void Ivy_FraigSweep( Ivy_FraigMan_t * p ); +static Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ); +static int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); +static int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ); +static void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); +static int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ); +static void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ); +static int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ); +static void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ); +static void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, int clk, int fVerbose ); +static int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ); + +static int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ); + +static sint64 s_nBTLimitGlobal = 0; +static sint64 s_nInsLimitGlobal = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets the default solving parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ) +{ + memset( pParams, 0, sizeof(Ivy_FraigParams_t) ); + pParams->nSimWords = 32; // the number of words in the simulation info + pParams->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached + pParams->fPatScores = 0; // enables simulation pattern scoring + pParams->MaxScore = 25; // max score after which resimulation is used + pParams->fDoSparse = 1; // skips sparse functions +// pParams->dActConeRatio = 0.05; // the ratio of cone to be bumped +// pParams->dActConeBumpMax = 5.0; // the largest bump of activity + pParams->dActConeRatio = 0.3; // the ratio of cone to be bumped + pParams->dActConeBumpMax = 10.0; // the largest bump of activity + + pParams->nBTLimitNode = 100; // conflict limit at a node + pParams->nBTLimitMiter = 500000; // conflict limit at an output +// pParams->nBTLimitGlobal = 0; // conflict limit global +// pParams->nInsLimitGlobal = 0; // inspection limit global +} + +/**Function************************************************************* + + Synopsis [Performs combinational equivalence checking for the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ) +{ + Prove_Params_t * pParams = pPars; + Ivy_FraigParams_t Params, * pIvyParams = &Params; + Ivy_Man_t * pManAig, * pManTemp; + int RetValue, nIter, clk, timeStart = clock();//, Counter; + sint64 nSatConfs, nSatInspects; + + // start the network and parameters + pManAig = *ppManAig; + Ivy_FraigParamsDefault( pIvyParams ); + pIvyParams->fVerbose = pParams->fVerbose; + pIvyParams->fProve = 1; + + if ( pParams->fVerbose ) + { + printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", + pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); + printf( "Mitering = %d (%3.1f). Rewriting = %d (%3.1f). Fraiging = %d (%3.1f).\n", + pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, + pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, + pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti ); + printf( "Mitering last = %d.\n", + pParams->nMiteringLimitLast ); + } + + // if SAT only, solve without iteration + if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) + { + clk = clock(); + pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); + pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); + *ppManAig = pManAig; + return RetValue; + } + + if ( Ivy_ManNodeNum(pManAig) < 500 ) + { + // run the first mitering + clk = clock(); + pIvyParams->nBTLimitMiter = pParams->nMiteringLimitStart / Ivy_ManPoNum(pManAig); + pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); + if ( RetValue >= 0 ) + { + *ppManAig = pManAig; + return RetValue; + } + } + + // check the current resource limits + RetValue = -1; + for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) + { + if ( pParams->fVerbose ) + { + printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, + (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), + (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); + fflush( stdout ); + } + + // try rewriting + if ( pParams->fUseRewriting ) + { // bug in Ivy_NodeFindCutsAll() when leaves are identical! +/* + clk = clock(); + Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); + pManAig = Ivy_ManRwsat( pManAig, 0 ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "Rewriting ", clk, pParams->fVerbose ); +*/ + } + if ( RetValue >= 0 ) + break; + + // try fraiging followed by mitering + if ( pParams->fUseFraiging ) + { + clk = clock(); + pIvyParams->nBTLimitNode = (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)); + pIvyParams->nBTLimitMiter = (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)) / Ivy_ManPoNum(pManAig); + pManAig = Ivy_FraigPerform_int( pManTemp = pManAig, pIvyParams, pParams->nTotalBacktrackLimit, pParams->nTotalInspectLimit, &nSatConfs, &nSatInspects ); Ivy_ManStop( pManTemp ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "Fraiging ", clk, pParams->fVerbose ); + } + if ( RetValue >= 0 ) + break; + + // add to the number of backtracks and inspects + pParams->nTotalBacktracksMade += nSatConfs; + pParams->nTotalInspectsMade += nSatInspects; + // check if global resource limit is reached + if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || + (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) + { + printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); + *ppManAig = pManAig; + return -1; + } + } + + if ( RetValue < 0 ) + { + if ( pParams->fVerbose ) + { + printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); + fflush( stdout ); + } + clk = clock(); + pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); + if ( pParams->nTotalBacktrackLimit ) + s_nBTLimitGlobal = pParams->nTotalBacktrackLimit - pParams->nTotalBacktracksMade; + if ( pParams->nTotalInspectLimit ) + s_nInsLimitGlobal = pParams->nTotalInspectLimit - pParams->nTotalInspectsMade; + pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); + s_nBTLimitGlobal = 0; + s_nInsLimitGlobal = 0; + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); + // make sure that the sover never returns "undecided" when infinite resource limits are set + if( RetValue == -1 && pParams->nTotalInspectLimit == 0 && + pParams->nTotalBacktrackLimit == 0 ) + { + extern void Prove_ParamsPrint( Prove_Params_t * pParams ); + Prove_ParamsPrint( pParams ); + printf("ERROR: ABC has returned \"undecided\" in spite of no limits...\n"); + exit(1); + } + } + + // assign the model if it was proved by rewriting (const 1 miter) + if ( RetValue == 0 && pManAig->pData == NULL ) + { + pManAig->pData = ALLOC( int, Ivy_ManPiNum(pManAig) ); + memset( pManAig->pData, 0, sizeof(int) * Ivy_ManPiNum(pManAig) ); + } + *ppManAig = pManAig; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, sint64 nBTLimitGlobal, sint64 nInsLimitGlobal, sint64 * pnSatConfs, sint64 * pnSatInspects ) +{ + Ivy_FraigMan_t * p; + Ivy_Man_t * pManAigNew; + int clk; + if ( Ivy_ManNodeNum(pManAig) == 0 ) + return Ivy_ManDup(pManAig); +clk = clock(); + assert( Ivy_ManLatchNum(pManAig) == 0 ); + p = Ivy_FraigStart( pManAig, pParams ); + // set global limits + p->nBTLimitGlobal = nBTLimitGlobal; + p->nInsLimitGlobal = nInsLimitGlobal; + + Ivy_FraigSimulate( p ); + Ivy_FraigSweep( p ); + pManAigNew = p->pManFraig; +p->timeTotal = clock() - clk; + if ( pnSatConfs ) + *pnSatConfs = p->pSat? p->pSat->stats.conflicts : 0; + if ( pnSatInspects ) + *pnSatInspects = p->pSat? p->pSat->stats.inspects : 0; + Ivy_FraigStop( p ); + return pManAigNew; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + Ivy_Man_t * pManAigNew; + int clk; + if ( Ivy_ManNodeNum(pManAig) == 0 ) + return Ivy_ManDup(pManAig); +clk = clock(); + assert( Ivy_ManLatchNum(pManAig) == 0 ); + p = Ivy_FraigStart( pManAig, pParams ); + Ivy_FraigSimulate( p ); + Ivy_FraigSweep( p ); + pManAigNew = p->pManFraig; +p->timeTotal = clock() - clk; + Ivy_FraigStop( p ); + return pManAigNew; +} + +/**Function************************************************************* + + Synopsis [Applies brute-force SAT to the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + Ivy_Man_t * pManAigNew; + Ivy_Obj_t * pObj; + int i, clk; +clk = clock(); + assert( Ivy_ManLatchNum(pManAig) == 0 ); + p = Ivy_FraigStartSimple( pManAig, pParams ); + // set global limits + p->nBTLimitGlobal = s_nBTLimitGlobal; + p->nInsLimitGlobal = s_nInsLimitGlobal; + // duplicate internal nodes + Ivy_ManForEachNode( p->pManAig, pObj, i ) + pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + // try to prove each output of the miter + Ivy_FraigMiterProve( p ); + // add the POs + Ivy_ManForEachPo( p->pManAig, pObj, i ) + Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); + // clean the new manager + Ivy_ManForEachObj( p->pManFraig, pObj, i ) + { + if ( Ivy_ObjFaninVec(pObj) ) + Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); + pObj->pNextFan0 = pObj->pNextFan1 = NULL; + } + // remove dangling nodes + Ivy_ManCleanup( p->pManFraig ); + pManAigNew = p->pManFraig; +p->timeTotal = clock() - clk; + +//printf( "Final nodes = %6d. ", Ivy_ManNodeNum(pManAigNew) ); +//PRT( "Time", p->timeTotal ); + Ivy_FraigStop( p ); + return pManAigNew; +} + +/**Function************************************************************* + + Synopsis [Starts the fraiging manager without simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + // allocat the fraiging manager + p = ALLOC( Ivy_FraigMan_t, 1 ); + memset( p, 0, sizeof(Ivy_FraigMan_t) ); + p->pParams = pParams; + p->pManAig = pManAig; + p->pManFraig = Ivy_ManStartFrom( pManAig ); + p->vPiVars = Vec_PtrAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Starts the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + Ivy_FraigSim_t * pSims; + Ivy_Obj_t * pObj; + int i, k, EntrySize; + // clean the fanout representation + Ivy_ManForEachObj( pManAig, pObj, i ) +// pObj->pEquiv = pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; + assert( !pObj->pEquiv && !pObj->pFanout ); + // allocat the fraiging manager + p = ALLOC( Ivy_FraigMan_t, 1 ); + memset( p, 0, sizeof(Ivy_FraigMan_t) ); + p->pParams = pParams; + p->pManAig = pManAig; + p->pManFraig = Ivy_ManStartFrom( pManAig ); + // allocate simulation info + p->nSimWords = pParams->nSimWords; +// p->pSimWords = ALLOC( unsigned, Ivy_ManObjNum(pManAig) * p->nSimWords ); + EntrySize = sizeof(Ivy_FraigSim_t) + sizeof(unsigned) * p->nSimWords; + p->pSimWords = (char *)malloc( Ivy_ManObjNum(pManAig) * EntrySize ); + memset( p->pSimWords, 0, EntrySize ); + k = 0; + Ivy_ManForEachObj( pManAig, pObj, i ) + { + pSims = (Ivy_FraigSim_t *)(p->pSimWords + EntrySize * k++); + pSims->pNext = NULL; + if ( Ivy_ObjIsNode(pObj) ) + { + if ( p->pSimStart == NULL ) + p->pSimStart = pSims; + else + ((Ivy_FraigSim_t *)(p->pSimWords + EntrySize * (k-2)))->pNext = pSims; + pSims->pFanin0 = Ivy_ObjSim( Ivy_ObjFanin0(pObj) ); + pSims->pFanin1 = Ivy_ObjSim( Ivy_ObjFanin1(pObj) ); + pSims->Type = (Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) << 2) | (Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)) << 1) | pObj->fPhase; + } + else + { + pSims->pFanin0 = NULL; + pSims->pFanin1 = NULL; + pSims->Type = 0; + } + Ivy_ObjSetSim( pObj, pSims ); + } + assert( k == Ivy_ManObjNum(pManAig) ); + // allocate storage for sim pattern + p->nPatWords = Ivy_BitWordNum( Ivy_ManPiNum(pManAig) ); + p->pPatWords = ALLOC( unsigned, p->nPatWords ); + p->pPatScores = ALLOC( int, 32 * p->nSimWords ); + p->vPiVars = Vec_PtrAlloc( 100 ); + // set random number generator + srand( 0xABCABC ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigStop( Ivy_FraigMan_t * p ) +{ + if ( p->pParams->fVerbose ) + Ivy_FraigPrint( p ); + if ( p->vPiVars ) Vec_PtrFree( p->vPiVars ); + if ( p->pSat ) sat_solver_delete( p->pSat ); + FREE( p->pPatScores ); + FREE( p->pPatWords ); + FREE( p->pSimWords ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Prints stats for the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrint( Ivy_FraigMan_t * p ) +{ + double nMemory; + nMemory = (double)Ivy_ManObjNum(p->pManAig)*p->nSimWords*sizeof(unsigned)/(1<<20); + printf( "SimWords = %d. Rounds = %d. Mem = %0.2f Mb. ", p->nSimWords, p->nSimRounds, nMemory ); + printf( "Classes: Beg = %d. End = %d.\n", p->nClassesBeg, p->nClassesEnd ); + printf( "Limits: BTNode = %d. BTMiter = %d.\n", p->pParams->nBTLimitNode, p->pParams->nBTLimitMiter ); + printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", + p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->nClassesZero ); + printf( "Final = %d. Miter = %d. Total = %d. Mux = %d. (Exor = %d.) SatVars = %d.\n", + Ivy_ManNodeNum(p->pManFraig), p->nNodesMiter, Ivy_ManNodeNum(p->pManAig), 0, 0, p->nSatVars ); + if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat ); + PRT( "AIG simulation ", p->timeSim ); + PRT( "AIG traversal ", p->timeTrav ); + PRT( "SAT solving ", p->timeSat ); + PRT( " Unsat ", p->timeSatUnsat ); + PRT( " Sat ", p->timeSatSat ); + PRT( " Fail ", p->timeSatFail ); + PRT( "Class refining ", p->timeRef ); + PRT( "TOTAL RUNTIME ", p->timeTotal ); + if ( p->time1 ) { PRT( "time1 ", p->time1 ); } +} + + + +/**Function************************************************************* + + Synopsis [Assigns random patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeAssignRandom( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims; + int i; + assert( Ivy_ObjIsPi(pObj) ); + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = Ivy_ObjRandomSim(); +} + +/**Function************************************************************* + + Synopsis [Assigns constant patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeAssignConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int fConst1 ) +{ + Ivy_FraigSim_t * pSims; + int i; + assert( Ivy_ObjIsPi(pObj) ); + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = fConst1? ~(unsigned)0 : 0; +} + +/**Function************************************************************* + + Synopsis [Assings random simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAssignRandom( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + Ivy_ManForEachPi( p->pManAig, pObj, i ) + Ivy_NodeAssignRandom( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Assings distance-1 simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAssignDist1( Ivy_FraigMan_t * p, unsigned * pPat ) +{ + Ivy_Obj_t * pObj; + int i, Limit; + Ivy_ManForEachPi( p->pManAig, pObj, i ) + { + Ivy_NodeAssignConst( p, pObj, Ivy_InfoHasBit(pPat, i) ); +// printf( "%d", Ivy_InfoHasBit(pPat, i) ); + } +// printf( "\n" ); + + Limit = IVY_MIN( Ivy_ManPiNum(p->pManAig), p->nSimWords * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Ivy_InfoXorBit( Ivy_ObjSim( Ivy_ManPi(p->pManAig,i) )->pData, i+1 ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeHasZeroSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims; + int i; + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + if ( pSims->pData[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComplementSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims; + int i; + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = ~pSims->pData[i]; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation infos are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCompareSims( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) +{ + Ivy_FraigSim_t * pSims0, * pSims1; + int i; + pSims0 = Ivy_ObjSim(pObj0); + pSims1 = Ivy_ObjSim(pObj1); + for ( i = 0; i < p->nSimWords; i++ ) + if ( pSims0->pData[i] != pSims1->pData[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeSimulateSim( Ivy_FraigMan_t * p, Ivy_FraigSim_t * pSims ) +{ + unsigned * pData, * pData0, * pData1; + int i; + pData = pSims->pData; + pData0 = pSims->pFanin0->pData; + pData1 = pSims->pFanin1->pData; + switch( pSims->Type ) + { + case 0: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] & pData1[i]); + break; + case 1: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = ~(pData0[i] & pData1[i]); + break; + case 2: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] & ~pData1[i]); + break; + case 3: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (~pData0[i] | pData1[i]); + break; + case 4: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (~pData0[i] & pData1[i]); + break; + case 5: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] | ~pData1[i]); + break; + case 6: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = ~(pData0[i] | pData1[i]); + break; + case 7: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] | pData1[i]); + break; + } +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeSimulate( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims, * pSims0, * pSims1; + int fCompl, fCompl0, fCompl1, i; + assert( !Ivy_IsComplement(pObj) ); + // get hold of the simulation information + pSims = Ivy_ObjSim(pObj); + pSims0 = Ivy_ObjSim(Ivy_ObjFanin0(pObj)); + pSims1 = Ivy_ObjSim(Ivy_ObjFanin1(pObj)); + // get complemented attributes of the children using their random info + fCompl = pObj->fPhase; + fCompl0 = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); + fCompl1 = Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); + // simulate + if ( fCompl0 && fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] | pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = ~(pSims0->pData[i] | pSims1->pData[i]); + } + else if ( fCompl0 && !fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] | ~pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (~pSims0->pData[i] & pSims1->pData[i]); + } + else if ( !fCompl0 && fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (~pSims0->pData[i] | pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] & ~pSims1->pData[i]); + } + else // if ( !fCompl0 && !fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = ~(pSims0->pData[i] & pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] & pSims1->pData[i]); + } +} + +/**Function************************************************************* + + Synopsis [Computes hash value using simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_NodeHash( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + static int s_FPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + Ivy_FraigSim_t * pSims; + unsigned uHash; + int i; + assert( p->nSimWords <= 128 ); + uHash = 0; + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + uHash ^= pSims->pData[i] * s_FPrimes[i]; + return uHash; +} + +/**Function************************************************************* + + Synopsis [Simulates AIG manager.] + + Description [Assumes that the PI simulation info is attached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSimulateOne( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i, clk; +clk = clock(); + Ivy_ManForEachNode( p->pManAig, pObj, i ) + { + Ivy_NodeSimulate( p, pObj ); +/* + if ( Ivy_ObjFraig(pObj) == NULL ) + printf( "%3d --- -- %d : ", pObj->Id, pObj->fPhase ); + else + printf( "%3d %3d %2d %d : ", pObj->Id, Ivy_Regular(Ivy_ObjFraig(pObj))->Id, Ivy_ObjSatNum(Ivy_Regular(Ivy_ObjFraig(pObj))), pObj->fPhase ); + Extra_PrintBinary( stdout, Ivy_ObjSim(pObj), 30 ); + printf( "\n" ); +*/ + } +p->timeSim += clock() - clk; +p->nSimRounds++; +} + +/**Function************************************************************* + + Synopsis [Simulates AIG manager.] + + Description [Assumes that the PI simulation info is attached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSimulateOneSim( Ivy_FraigMan_t * p ) +{ + Ivy_FraigSim_t * pSims; + int clk; +clk = clock(); + for ( pSims = p->pSimStart; pSims; pSims = pSims->pNext ) + Ivy_NodeSimulateSim( p, pSims ); +p->timeSim += clock() - clk; +p->nSimRounds++; +} + +/**Function************************************************************* + + Synopsis [Adds one node to the equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeAddToClass( Ivy_Obj_t * pClass, Ivy_Obj_t * pObj ) +{ + if ( Ivy_ObjClassNodeNext(pClass) == NULL ) + Ivy_ObjSetClassNodeNext( pClass, pObj ); + else + Ivy_ObjSetClassNodeNext( Ivy_ObjClassNodeLast(pClass), pObj ); + Ivy_ObjSetClassNodeLast( pClass, pObj ); + Ivy_ObjSetClassNodeRepr( pObj, pClass ); + Ivy_ObjSetClassNodeNext( pObj, NULL ); +} + +/**Function************************************************************* + + Synopsis [Adds equivalence class to the list of classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) +{ + if ( pList->pHead == NULL ) + { + pList->pHead = pClass; + pList->pTail = pClass; + Ivy_ObjSetEquivListPrev( pClass, NULL ); + Ivy_ObjSetEquivListNext( pClass, NULL ); + } + else + { + Ivy_ObjSetEquivListNext( pList->pTail, pClass ); + Ivy_ObjSetEquivListPrev( pClass, pList->pTail ); + Ivy_ObjSetEquivListNext( pClass, NULL ); + pList->pTail = pClass; + } + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [Updates the list of classes after base class has split.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigInsertClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pBase, Ivy_Obj_t * pClass ) +{ + Ivy_ObjSetEquivListPrev( pClass, pBase ); + Ivy_ObjSetEquivListNext( pClass, Ivy_ObjEquivListNext(pBase) ); + if ( Ivy_ObjEquivListNext(pBase) ) + Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pBase), pClass ); + Ivy_ObjSetEquivListNext( pBase, pClass ); + if ( pList->pTail == pBase ) + pList->pTail = pClass; + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [Removes equivalence class from the list of classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigRemoveClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) +{ + if ( pList->pHead == pClass ) + pList->pHead = Ivy_ObjEquivListNext(pClass); + if ( pList->pTail == pClass ) + pList->pTail = Ivy_ObjEquivListPrev(pClass); + if ( Ivy_ObjEquivListPrev(pClass) ) + Ivy_ObjSetEquivListNext( Ivy_ObjEquivListPrev(pClass), Ivy_ObjEquivListNext(pClass) ); + if ( Ivy_ObjEquivListNext(pClass) ) + Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pClass), Ivy_ObjEquivListPrev(pClass) ); + Ivy_ObjSetEquivListNext( pClass, NULL ); + Ivy_ObjSetEquivListPrev( pClass, NULL ); + pClass->fMarkA = 0; + pList->nItems--; +} + +/**Function************************************************************* + + Synopsis [Count the number of pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigCountPairsClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pClass, * pNode; + int nPairs = 0, nNodes; + return nPairs; + + Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) + { + nNodes = 0; + Ivy_FraigForEachClassNode( pClass, pNode ) + nNodes++; + nPairs += nNodes * (nNodes - 1) / 2; + } + return nPairs; +} + +/**Function************************************************************* + + Synopsis [Creates initial simulation classes.] + + Description [Assumes that simulation info is assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCreateClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t ** pTable; + Ivy_Obj_t * pObj, * pConst1, * pBin, * pEntry; + int i, nTableSize; + unsigned Hash; + pConst1 = Ivy_ManConst1(p->pManAig); + // allocate the table + nTableSize = Ivy_ManObjNum(p->pManAig) / 2 + 13; + pTable = ALLOC( Ivy_Obj_t *, nTableSize ); + memset( pTable, 0, sizeof(Ivy_Obj_t *) * nTableSize ); + // collect nodes into the table + Ivy_ManForEachObj( p->pManAig, pObj, i ) + { + if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) + continue; + Hash = Ivy_NodeHash( p, pObj ); + if ( Hash == 0 && Ivy_NodeHasZeroSim( p, pObj ) ) + { + Ivy_NodeAddToClass( pConst1, pObj ); + continue; + } + // add the node to the table + pBin = pTable[Hash % nTableSize]; + Ivy_FraigForEachBinNode( pBin, pEntry ) + if ( Ivy_NodeCompareSims( p, pEntry, pObj ) ) + { + Ivy_NodeAddToClass( pEntry, pObj ); + break; + } + // check if the entry was added + if ( pEntry ) + continue; + Ivy_ObjSetNodeHashNext( pObj, pBin ); + pTable[Hash % nTableSize] = pObj; + } + // collect non-trivial classes + assert( p->lClasses.pHead == NULL ); + Ivy_ManForEachObj( p->pManAig, pObj, i ) + { + if ( !Ivy_ObjIsConst1(pObj) && !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) + continue; + Ivy_ObjSetNodeHashNext( pObj, NULL ); + if ( Ivy_ObjClassNodeRepr(pObj) == NULL ) + { + assert( Ivy_ObjClassNodeNext(pObj) == NULL ); + continue; + } + // recognize the head of the class + if ( Ivy_ObjClassNodeNext( Ivy_ObjClassNodeRepr(pObj) ) != NULL ) + continue; + // clean the class representative and add it to the list + Ivy_ObjSetClassNodeRepr( pObj, NULL ); + Ivy_FraigAddClass( &p->lClasses, pObj ); + } + // free the table + free( pTable ); +} + +/**Function************************************************************* + + Synopsis [Recursively refines the class after simulation.] + + Description [Returns 1 if the class has changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigRefineClass_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass ) +{ + Ivy_Obj_t * pClassNew, * pListOld, * pListNew, * pNode; + int RetValue = 0; + // check if there is refinement + pListOld = pClass; + Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClass), pClassNew ) + { + if ( !Ivy_NodeCompareSims(p, pClass, pClassNew) ) + { + if ( p->pParams->fPatScores ) + Ivy_FraigAddToPatScores( p, pClass, pClassNew ); + break; + } + pListOld = pClassNew; + } + if ( pClassNew == NULL ) + return 0; + // set representative of the new class + Ivy_ObjSetClassNodeRepr( pClassNew, NULL ); + // start the new list + pListNew = pClassNew; + // go through the remaining nodes and sort them into two groups: + // (1) matches of the old node; (2) non-matches of the old node + Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClassNew), pNode ) + if ( Ivy_NodeCompareSims( p, pClass, pNode ) ) + { + Ivy_ObjSetClassNodeNext( pListOld, pNode ); + pListOld = pNode; + } + else + { + Ivy_ObjSetClassNodeNext( pListNew, pNode ); + Ivy_ObjSetClassNodeRepr( pNode, pClassNew ); + pListNew = pNode; + } + // finish both lists + Ivy_ObjSetClassNodeNext( pListNew, NULL ); + Ivy_ObjSetClassNodeNext( pListOld, NULL ); + // update the list of classes + Ivy_FraigInsertClass( &p->lClasses, pClass, pClassNew ); + // if the old class is trivial, remove it + if ( Ivy_ObjClassNodeNext(pClass) == NULL ) + Ivy_FraigRemoveClass( &p->lClasses, pClass ); + // if the new class is trivial, remove it; otherwise, try to refine it + if ( Ivy_ObjClassNodeNext(pClassNew) == NULL ) + Ivy_FraigRemoveClass( &p->lClasses, pClassNew ); + else + RetValue = Ivy_FraigRefineClass_rec( p, pClassNew ); + return RetValue + 1; +} + +/**Function************************************************************* + + Synopsis [Creates the counter-example from the successful pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCheckOutputSimsSavePattern( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims; + int i, k, BestPat, * pModel; + // find the word of the pattern + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + if ( pSims->pData[i] ) + break; + assert( i < p->nSimWords ); + // find the bit of the pattern + for ( k = 0; k < 32; k++ ) + if ( pSims->pData[i] & (1 << k) ) + break; + assert( k < 32 ); + // determine the best pattern + BestPat = i * 32 + k; + // fill in the counter-example data + pModel = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); + Ivy_ManForEachPi( p->pManAig, pObj, i ) + { + pModel[i] = Ivy_InfoHasBit(Ivy_ObjSim(pObj)->pData, BestPat); +// printf( "%d", pModel[i] ); + } +// printf( "\n" ); + // set the model + assert( p->pManFraig->pData == NULL ); + p->pManFraig->pData = pModel; + return; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the one of the output is already non-constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigCheckOutputSims( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + // make sure the reference simulation pattern does not detect the bug + pObj = Ivy_ManPo( p->pManAig, 0 ); + assert( Ivy_ObjFanin0(pObj)->fPhase == (unsigned)Ivy_ObjFaninC0(pObj) ); // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) == 0 + Ivy_ManForEachPo( p->pManAig, pObj, i ) + { + // complement simulation info +// if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) +// Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); + // check + if ( !Ivy_NodeHasZeroSim( p, Ivy_ObjFanin0(pObj) ) ) + { + // create the counter-example from this pattern + Ivy_FraigCheckOutputSimsSavePattern( p, Ivy_ObjFanin0(pObj) ); + return 1; + } + // complement simulation info +// if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) +// Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Refines the classes after simulation.] + + Description [Assumes that simulation info is assigned. Returns the + number of classes refined.] + + SideEffects [Large equivalence class of constant 0 may cause problems.] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigRefineClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pClass, * pClass2; + int clk, RetValue, Counter = 0; + // check if some outputs already became non-constant + // this is a special case when computation can be stopped!!! + if ( p->pParams->fProve ) + Ivy_FraigCheckOutputSims( p ); + if ( p->pManFraig->pData ) + return 0; + // refine the classed +clk = clock(); + Ivy_FraigForEachEquivClassSafe( p->lClasses.pHead, pClass, pClass2 ) + { + if ( pClass->fMarkA ) + continue; + RetValue = Ivy_FraigRefineClass_rec( p, pClass ); + Counter += ( RetValue > 0 ); +//if ( Ivy_ObjIsConst1(pClass) ) +//printf( "%d ", RetValue ); +//if ( Ivy_ObjIsConst1(pClass) ) +// p->time1 += clock() - clk; + } +p->timeRef += clock() - clk; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Print the class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrintClass( Ivy_Obj_t * pClass ) +{ + Ivy_Obj_t * pObj; + printf( "Class {" ); + Ivy_FraigForEachClassNode( pClass, pObj ) + printf( " %d(%d)%c", pObj->Id, pObj->Level, pObj->fPhase? '+' : '-' ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Count the number of elements in the class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigCountClassNodes( Ivy_Obj_t * pClass ) +{ + Ivy_Obj_t * pObj; + int Counter = 0; + Ivy_FraigForEachClassNode( pClass, pObj ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Prints simulation classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrintSimClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pClass; + Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) + { +// Ivy_FraigPrintClass( pClass ); + printf( "%d ", Ivy_FraigCountClassNodes( pClass ) ); + } +// printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Generated const 0 pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern0( Ivy_FraigMan_t * p ) +{ + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); +} + +/**Function************************************************************* + + Synopsis [[Generated const 1 pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern1( Ivy_FraigMan_t * p ) +{ + memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords ); +} + +/**Function************************************************************* + + Synopsis [Generates the counter-example satisfying the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ) +{ + int * pModel; + Ivy_Obj_t * pObj; + int i; + pModel = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); + Ivy_ManForEachPi( p->pManFraig, pObj, i ) + pModel[i] = ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ); + return pModel; +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); + Ivy_ManForEachPi( p->pManFraig, pObj, i ) +// Vec_PtrForEachEntry( p->vPiVars, pObj, i ) + if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) + Ivy_InfoSetBit( p->pPatWords, i ); +// Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern2( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); +// Ivy_ManForEachPi( p->pManFraig, pObj, i ) + Vec_PtrForEachEntry( p->vPiVars, pObj, i ) + if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) +// Ivy_InfoSetBit( p->pPatWords, i ); + Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern3( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + for ( i = 0; i < p->nPatWords; i++ ) + p->pPatWords[i] = Ivy_ObjRandomSim(); + Vec_PtrForEachEntry( p->vPiVars, pObj, i ) + if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ (p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True) ) + Ivy_InfoXorBit( p->pPatWords, pObj->Id - 1 ); +} + + +/**Function************************************************************* + + Synopsis [Performs simulation of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSimulate( Ivy_FraigMan_t * p ) +{ + int nChanges, nClasses; + // start the classes + Ivy_FraigAssignRandom( p ); + Ivy_FraigSimulateOne( p ); + Ivy_FraigCreateClasses( p ); +//printf( "Starting classes = %5d. Pairs = %6d.\n", p->lClasses.nItems, Ivy_FraigCountPairsClasses(p) ); + // refine classes by walking 0/1 patterns + Ivy_FraigSavePattern0( p ); + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + Ivy_FraigSavePattern1( p ); + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + // refine classes by random simulation + do { + Ivy_FraigAssignRandom( p ); + Ivy_FraigSimulateOne( p ); + nClasses = p->lClasses.nItems; + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + } while ( (double)nChanges / nClasses > p->pParams->dSimSatur ); +// Ivy_FraigPrintSimClasses( p ); +} + + + +/**Function************************************************************* + + Synopsis [Cleans pattern scores.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCleanPatScores( Ivy_FraigMan_t * p ) +{ + int i, nLimit = p->nSimWords * 32; + for ( i = 0; i < nLimit; i++ ) + p->pPatScores[i] = 0; +} + +/**Function************************************************************* + + Synopsis [Adds to pattern scores.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ) +{ + Ivy_FraigSim_t * pSims0, * pSims1; + unsigned uDiff; + int i, w; + // get hold of the simulation information + pSims0 = Ivy_ObjSim(pClass); + pSims1 = Ivy_ObjSim(pClassNew); + // iterate through the differences and record the score + for ( w = 0; w < p->nSimWords; w++ ) + { + uDiff = pSims0->pData[w] ^ pSims1->pData[w]; + if ( uDiff == 0 ) + continue; + for ( i = 0; i < 32; i++ ) + if ( uDiff & ( 1 << i ) ) + p->pPatScores[w*32+i]++; + } +} + +/**Function************************************************************* + + Synopsis [Selects the best pattern.] + + Description [Returns 1 if such pattern is found.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigSelectBestPat( Ivy_FraigMan_t * p ) +{ + Ivy_FraigSim_t * pSims; + Ivy_Obj_t * pObj; + int i, nLimit = p->nSimWords * 32, MaxScore = 0, BestPat = -1; + for ( i = 1; i < nLimit; i++ ) + { + if ( MaxScore < p->pPatScores[i] ) + { + MaxScore = p->pPatScores[i]; + BestPat = i; + } + } + if ( MaxScore == 0 ) + return 0; +// if ( MaxScore > p->pParams->MaxScore ) +// printf( "Max score is %3d. ", MaxScore ); + // copy the best pattern into the selected pattern + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); + Ivy_ManForEachPi( p->pManAig, pObj, i ) + { + pSims = Ivy_ObjSim(pObj); + if ( Ivy_InfoHasBit(pSims->pData, BestPat) ) + Ivy_InfoSetBit(p->pPatWords, i); + } + return MaxScore; +} + +/**Function************************************************************* + + Synopsis [Resimulates fraiging manager after finding a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigResimulate( Ivy_FraigMan_t * p ) +{ + int nChanges; + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + if ( p->pParams->fPatScores ) + Ivy_FraigCleanPatScores( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; + if ( nChanges < 1 ) + printf( "Error: A counter-example did not refine classes!\n" ); + assert( nChanges >= 1 ); +//printf( "Refined classes! = %5d. Changes = %4d.\n", p->lClasses.nItems, nChanges ); + if ( !p->pParams->fPatScores ) + return; + + // perform additional simulation using dist1 patterns derived from successful patterns + while ( Ivy_FraigSelectBestPat(p) > p->pParams->MaxScore ) + { + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + Ivy_FraigCleanPatScores( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined class!!! = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + if ( nChanges == 0 ) + break; + } +} + + +/**Function************************************************************* + + Synopsis [Prints the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, int clk, int fVerbose ) +{ + if ( !fVerbose ) + return; + printf( "Nodes = %7d. Levels = %4d. ", Ivy_ManNodeNum(pNtk), Ivy_ManLevels(pNtk) ); + PRT( pString, clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Reports the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ) +{ + Ivy_Obj_t * pObj, * pObjNew; + int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; + if ( pMan->pData ) + return 0; + Ivy_ManForEachPo( pMan, pObj, i ) + { + pObjNew = Ivy_ObjChild0(pObj); + // check if the output is constant 1 + if ( pObjNew == pMan->pConst1 ) + { + CountNonConst0++; + continue; + } + // check if the output is constant 0 + if ( pObjNew == Ivy_Not(pMan->pConst1) ) + { + CountConst0++; + continue; + } + // check if the output can be constant 0 + if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) + { + CountNonConst0++; + continue; + } + CountUndecided++; + } +/* + if ( p->pParams->fVerbose ) + { + printf( "Miter has %d outputs. ", Ivy_ManPoNum(p->pManAig) ); + printf( "Const0 = %d. ", CountConst0 ); + printf( "NonConst0 = %d. ", CountNonConst0 ); + printf( "Undecided = %d. ", CountUndecided ); + printf( "\n" ); + } +*/ + if ( CountNonConst0 ) + return 0; + if ( CountUndecided ) + return -1; + return 1; +} + +/**Function************************************************************* + + Synopsis [Tries to prove each output of the miter until encountering a sat output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj, * pObjNew; + int i, RetValue, clk = clock(); + int fVerbose = 0; + Ivy_ManForEachPo( p->pManAig, pObj, i ) + { + if ( i && fVerbose ) + { + PRT( "Time", clock() -clk ); + } + pObjNew = Ivy_ObjChild0Equiv(pObj); + // check if the output is constant 1 + if ( pObjNew == p->pManFraig->pConst1 ) + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) is constant 1. ", i, Ivy_ManPoNum(p->pManAig) ); + // assing constant 0 model + p->pManFraig->pData = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); + memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); + break; + } + // check if the output is constant 0 + if ( pObjNew == Ivy_Not(p->pManFraig->pConst1) ) + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) is already constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + continue; + } + // check if the output can be constant 0 + if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) cannot be constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + // assing constant 0 model + p->pManFraig->pData = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); + memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); + break; + } +/* + // check the representative of this node + pRepr = Ivy_ObjClassNodeRepr(Ivy_ObjFanin0(pObj)); + if ( Ivy_Regular(pRepr) != p->pManAig->pConst1 ) + printf( "Representative is not constant 1.\n" ); + else + printf( "Representative is constant 1.\n" ); +*/ + // try to prove the output constant 0 + RetValue = Ivy_FraigNodeIsConst( p, Ivy_Regular(pObjNew) ); + if ( RetValue == 1 ) // proved equivalent + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) was proved constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + // set the constant miter + Ivy_ObjFanin0(pObj)->pEquiv = Ivy_NotCond( p->pManFraig->pConst1, !Ivy_ObjFaninC0(pObj) ); + continue; + } + if ( RetValue == -1 ) // failed + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) has timed out at %d backtracks. ", i, Ivy_ManPoNum(p->pManAig), p->pParams->nBTLimitMiter ); + continue; + } + // proved satisfiable + if ( fVerbose ) + printf( "Output %2d (out of %2d) was proved NOT a constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + // create the model + p->pManFraig->pData = Ivy_FraigCreateModel(p); + break; + } + if ( fVerbose ) + { + PRT( "Time", clock() -clk ); + } +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSweep( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj;//, * pTemp; + int i, k = 0; +p->nClassesZero = p->lClasses.pHead? (Ivy_ObjIsConst1(p->lClasses.pHead) ? Ivy_FraigCountClassNodes(p->lClasses.pHead) : 0) : 0; +p->nClassesBeg = p->lClasses.nItems; + // duplicate internal nodes + p->pProgress = Extra_ProgressBarStart( stdout, Ivy_ManNodeNum(p->pManAig) ); + Ivy_ManForEachNode( p->pManAig, pObj, i ) + { + Extra_ProgressBarUpdate( p->pProgress, k++, NULL ); + // default to simple strashing if simulation detected a counter-example for a PO + if ( p->pManFraig->pData ) + pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + else + pObj->pEquiv = Ivy_FraigAnd( p, pObj ); + assert( pObj->pEquiv != NULL ); +// pTemp = Ivy_Regular(pObj->pEquiv); +// assert( Ivy_Regular(pObj->pEquiv)->Type ); + } + Extra_ProgressBarStop( p->pProgress ); +p->nClassesEnd = p->lClasses.nItems; + // try to prove the outputs of the miter + p->nNodesMiter = Ivy_ManNodeNum(p->pManFraig); +// Ivy_FraigMiterStatus( p->pManFraig ); + if ( p->pParams->fProve && p->pManFraig->pData == NULL ) + Ivy_FraigMiterProve( p ); + // add the POs + Ivy_ManForEachPo( p->pManAig, pObj, i ) + Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); + // clean the old manager + Ivy_ManForEachObj( p->pManAig, pObj, i ) + pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; + // clean the new manager + Ivy_ManForEachObj( p->pManFraig, pObj, i ) + { + if ( Ivy_ObjFaninVec(pObj) ) + Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); + pObj->pNextFan0 = pObj->pNextFan1 = NULL; + } + // remove dangling nodes + Ivy_ManCleanup( p->pManFraig ); + // clean up the class marks + Ivy_FraigForEachEquivClass( p->lClasses.pHead, pObj ) + pObj->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ) +{ + Ivy_Obj_t * pObjNew, * pFanin0New, * pFanin1New, * pObjReprNew; + int RetValue; + // get the fraiged fanins + pFanin0New = Ivy_ObjChild0Equiv(pObjOld); + pFanin1New = Ivy_ObjChild1Equiv(pObjOld); + // get the candidate fraig node + pObjNew = Ivy_And( p->pManFraig, pFanin0New, pFanin1New ); + // get representative of this class + if ( Ivy_ObjClassNodeRepr(pObjOld) == NULL || // this is a unique node + (!p->pParams->fDoSparse && Ivy_ObjClassNodeRepr(pObjOld) == p->pManAig->pConst1) ) // this is a sparse node + { + assert( Ivy_Regular(pFanin0New) != Ivy_Regular(pFanin1New) ); + assert( pObjNew != Ivy_Regular(pFanin0New) ); + assert( pObjNew != Ivy_Regular(pFanin1New) ); + return pObjNew; + } + // get the fraiged representative + pObjReprNew = Ivy_ObjFraig(Ivy_ObjClassNodeRepr(pObjOld)); + // if the fraiged nodes are the same return + if ( Ivy_Regular(pObjNew) == Ivy_Regular(pObjReprNew) ) + return pObjNew; + assert( Ivy_Regular(pObjNew) != Ivy_ManConst1(p->pManFraig) ); +// printf( "Node = %d. Repr = %d.\n", pObjOld->Id, Ivy_ObjClassNodeRepr(pObjOld)->Id ); + + // they are different (the counter-example is in p->pPatWords) + RetValue = Ivy_FraigNodesAreEquiv( p, Ivy_Regular(pObjReprNew), Ivy_Regular(pObjNew) ); + if ( RetValue == 1 ) // proved equivalent + { + // mark the class as proved + if ( Ivy_ObjClassNodeNext(pObjOld) == NULL ) + Ivy_ObjClassNodeRepr(pObjOld)->fMarkA = 1; + return Ivy_NotCond( pObjReprNew, pObjOld->fPhase ^ Ivy_ObjClassNodeRepr(pObjOld)->fPhase ); + } + if ( RetValue == -1 ) // failed + return pObjNew; + // simulate the counter-example and return the new node + Ivy_FraigResimulate( p ); + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Prints variable activity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrintActivity( Ivy_FraigMan_t * p ) +{ + int i; + for ( i = 0; i < p->nSatVars; i++ ) + printf( "%d %.3f ", i, p->pSat->activity[i] ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Runs equivalence test for the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) +{ + int pLits[4], RetValue, RetValue1, nBTLimit, clk, clk2 = clock(); + + // make sure the nodes are not complemented + assert( !Ivy_IsComplement(pNew) ); + assert( !Ivy_IsComplement(pOld) ); + assert( pNew != pOld ); + + // if at least one of the nodes is a failed node, perform adjustments: + // if the backtrack limit is small, simply skip this node + // if the backtrack limit is > 10, take the quare root of the limit + nBTLimit = p->pParams->nBTLimitNode; + if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) + { + p->nSatFails++; + // fail immediately +// return -1; + if ( nBTLimit <= 10 ) + return -1; + nBTLimit = (int)pow(nBTLimit, 0.7); + } + p->nSatCalls++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + { + p->pSat = sat_solver_new(); + p->nSatVars = 1; + sat_solver_setnvars( p->pSat, 1000 ); + // var 0 is reserved for const1 node - add the clause +// pLits[0] = toLit( 0 ); +// sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + } + + // if the nodes do not have SAT variables, allocate them + Ivy_FraigNodeAddToSolver( p, pOld, pNew ); + + // prepare variable activity + Ivy_FraigSetActivityFactors( p, pOld, pNew ); + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 +clk = clock(); + pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 0 ); + pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); +//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, + (sint64)nBTLimit, (sint64)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + // continue solving the other implication + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + Ivy_FraigSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += clock() - clk; + // mark the node as the failed node + if ( pOld != p->pManFraig->pConst1 ) + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; + p->nSatFailsReal++; + return -1; + } + + // if the old node was constant 0, we already know the answer + if ( pOld == p->pManFraig->pConst1 ) + { + p->nSatProof++; + return 1; + } + + // solve under assumptions + // A = 0; B = 1 OR A = 0; B = 0 +clk = clock(); + pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 1 ); + pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, + (sint64)nBTLimit, (sint64)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + Ivy_FraigSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += clock() - clk; + // mark the node as the failed node + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; + p->nSatFailsReal++; + return -1; + } +/* + // check BDD proof + { + int RetVal; + PRT( "Sat", clock() - clk2 ); + clk2 = clock(); + RetVal = Ivy_FraigNodesAreEquivBdd( pOld, pNew ); +// printf( "%d ", RetVal ); + assert( RetVal ); + PRT( "Bdd", clock() - clk2 ); + printf( "\n" ); + } +*/ + // return SAT proof + p->nSatProof++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Runs equivalence test for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pNew ) +{ + int pLits[2], RetValue1, RetValue, clk; + + // make sure the nodes are not complemented + assert( !Ivy_IsComplement(pNew) ); + assert( pNew != p->pManFraig->pConst1 ); + p->nSatCalls++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + { + p->pSat = sat_solver_new(); + p->nSatVars = 1; + sat_solver_setnvars( p->pSat, 1000 ); + // var 0 is reserved for const1 node - add the clause +// pLits[0] = toLit( 0 ); +// sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + } + + // if the nodes do not have SAT variables, allocate them + Ivy_FraigNodeAddToSolver( p, NULL, pNew ); + + // prepare variable activity + Ivy_FraigSetActivityFactors( p, NULL, pNew ); + + // solve under assumptions +clk = clock(); + pLits[0] = toLitCond( Ivy_ObjSatNum(pNew), pNew->fPhase ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, + (sint64)p->pParams->nBTLimitMiter, (sint64)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + assert( RetValue ); + // continue solving the other implication + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += clock() - clk; + if ( p->pPatWords ) + Ivy_FraigSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += clock() - clk; + // mark the node as the failed node + pNew->fFailTfo = 1; + p->nSatFailsReal++; + return -1; + } + + // return SAT proof + p->nSatProof++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddClausesMux( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode ) +{ + Ivy_Obj_t * pNodeI, * pNodeT, * pNodeE; + int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; + + assert( !Ivy_IsComplement( pNode ) ); + assert( Ivy_ObjIsMuxType( pNode ) ); + // get nodes (I = if, T = then, E = else) + pNodeI = Ivy_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the variable numbers + VarF = Ivy_ObjSatNum(pNode); + VarI = Ivy_ObjSatNum(pNodeI); + VarT = Ivy_ObjSatNum(Ivy_Regular(pNodeT)); + VarE = Ivy_ObjSatNum(Ivy_Regular(pNodeE)); + // get the complementation flags + fCompT = Ivy_IsComplement(pNodeT); + fCompE = Ivy_IsComplement(pNodeE); + + // f = ITE(i, t, e) + + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + + // create four clauses + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 1^fCompT); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 0^fCompT); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + + // two additional clauses + // t' & e' -> f' + // t & e -> f + + // t + e + f' + // t' + e' + f + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return; + } + + pLits[0] = toLitCond(VarT, 0^fCompT); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarT, 1^fCompT); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddClausesSuper( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode, Vec_Ptr_t * vSuper ) +{ + Ivy_Obj_t * pFanin; + int * pLits, nLits, RetValue, i; + assert( !Ivy_IsComplement(pNode) ); + assert( Ivy_ObjIsNode( pNode ) ); + // create storage for literals + nLits = Vec_PtrSize(vSuper) + 1; + pLits = ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + pLits[0] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), Ivy_IsComplement(pFanin)); + pLits[1] = toLitCond(Ivy_ObjSatNum(pNode), 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + } + // add A & B => C or !A + !B + C + Vec_PtrForEachEntry( vSuper, pFanin, i ) + pLits[i] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), !Ivy_IsComplement(pFanin)); + pLits[nLits-1] = toLitCond(Ivy_ObjSatNum(pNode), 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); + assert( RetValue ); + free( pLits ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCollectSuper_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Ivy_IsComplement(pObj) || Ivy_ObjIsPi(pObj) || (!fFirst && Ivy_ObjRefs(pObj) > 1) || + (fUseMuxes && Ivy_ObjIsMuxType(pObj)) ) + { + Vec_PtrPushUnique( vSuper, pObj ); + return; + } + // go through the branches + Ivy_FraigCollectSuper_rec( Ivy_ObjChild0(pObj), vSuper, 0, fUseMuxes ); + Ivy_FraigCollectSuper_rec( Ivy_ObjChild1(pObj), vSuper, 0, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ivy_FraigCollectSuper( Ivy_Obj_t * pObj, int fUseMuxes ) +{ + Vec_Ptr_t * vSuper; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_ObjIsPi(pObj) ); + vSuper = Vec_PtrAlloc( 4 ); + Ivy_FraigCollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); + return vSuper; +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigObjAddToFrontier( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vFrontier ) +{ + assert( !Ivy_IsComplement(pObj) ); + if ( Ivy_ObjSatNum(pObj) ) + return; + assert( Ivy_ObjSatNum(pObj) == 0 ); + assert( Ivy_ObjFaninVec(pObj) == NULL ); + if ( Ivy_ObjIsConst1(pObj) ) + return; +//printf( "Assigning node %d number %d\n", pObj->Id, p->nSatVars ); + Ivy_ObjSetSatNum( pObj, p->nSatVars++ ); + if ( Ivy_ObjIsNode(pObj) ) + Vec_PtrPush( vFrontier, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) +{ + Vec_Ptr_t * vFrontier, * vFanins; + Ivy_Obj_t * pNode, * pFanin; + int i, k, fUseMuxes = 1; + assert( pOld || pNew ); + // quit if CNF is ready + if ( (!pOld || Ivy_ObjFaninVec(pOld)) && (!pNew || Ivy_ObjFaninVec(pNew)) ) + return; + // start the frontier + vFrontier = Vec_PtrAlloc( 100 ); + if ( pOld ) Ivy_FraigObjAddToFrontier( p, pOld, vFrontier ); + if ( pNew ) Ivy_FraigObjAddToFrontier( p, pNew, vFrontier ); + // explore nodes in the frontier + Vec_PtrForEachEntry( vFrontier, pNode, i ) + { + // create the supergate + assert( Ivy_ObjSatNum(pNode) ); + assert( Ivy_ObjFaninVec(pNode) == NULL ); + if ( fUseMuxes && Ivy_ObjIsMuxType(pNode) ) + { + vFanins = Vec_PtrAlloc( 4 ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin1(pNode) ) ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin1(pNode) ) ); + Vec_PtrForEachEntry( vFanins, pFanin, k ) + Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); + Ivy_FraigAddClausesMux( p, pNode ); + } + else + { + vFanins = Ivy_FraigCollectSuper( pNode, fUseMuxes ); + Vec_PtrForEachEntry( vFanins, pFanin, k ) + Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); + Ivy_FraigAddClausesSuper( p, pNode, vFanins ); + } + assert( Vec_PtrSize(vFanins) > 1 ); + Ivy_ObjSetFaninVec( pNode, vFanins ); + } + Vec_PtrFree( vFrontier ); +} + +/**Function************************************************************* + + Synopsis [Sets variable activities in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigSetActivityFactors_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int LevelMin, int LevelMax ) +{ + Vec_Ptr_t * vFanins; + Ivy_Obj_t * pFanin; + int i, Counter = 0; + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjSatNum(pObj) ); + // skip visited variables + if ( Ivy_ObjIsTravIdCurrent(p->pManFraig, pObj) ) + return 0; + Ivy_ObjSetTravIdCurrent(p->pManFraig, pObj); + // add the PI to the list + if ( pObj->Level <= (unsigned)LevelMin || Ivy_ObjIsPi(pObj) ) + return 0; + // set the factor of this variable + // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pParams->dActConeBumpMax / ThisBump + p->pSat->factors[Ivy_ObjSatNum(pObj)] = p->pParams->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin); + veci_push(&p->pSat->act_vars, Ivy_ObjSatNum(pObj)); + // explore the fanins + vFanins = Ivy_ObjFaninVec( pObj ); + Vec_PtrForEachEntry( vFanins, pFanin, i ) + Counter += Ivy_FraigSetActivityFactors_rec( p, Ivy_Regular(pFanin), LevelMin, LevelMax ); + return 1 + Counter; +} + +/**Function************************************************************* + + Synopsis [Sets variable activities in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) +{ + int clk, LevelMin, LevelMax; + assert( pOld || pNew ); +clk = clock(); + // reset the active variables + veci_resize(&p->pSat->act_vars, 0); + // prepare for traversal + Ivy_ManIncrementTravId( p->pManFraig ); + // determine the min and max level to visit + assert( p->pParams->dActConeRatio > 0 && p->pParams->dActConeRatio < 1 ); + LevelMax = IVY_MAX( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) ); + LevelMin = (int)(LevelMax * (1.0 - p->pParams->dActConeRatio)); + // traverse + if ( pOld && !Ivy_ObjIsConst1(pOld) ) + Ivy_FraigSetActivityFactors_rec( p, pOld, LevelMin, LevelMax ); + if ( pNew && !Ivy_ObjIsConst1(pNew) ) + Ivy_FraigSetActivityFactors_rec( p, pNew, LevelMin, LevelMax ); +//Ivy_FraigPrintActivity( p ); +p->timeTrav += clock() - clk; + return 1; +} + + + +#include "cuddInt.h" + +/**Function************************************************************* + + Synopsis [Checks equivalence using BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Ivy_FraigNodesAreEquivBdd_int( DdManager * dd, DdNode * bFunc, Vec_Ptr_t * vFront, int Level ) +{ + DdNode ** pFuncs; + DdNode * bFuncNew; + Vec_Ptr_t * vTemp; + Ivy_Obj_t * pObj, * pFanin; + int i, NewSize; + // create new frontier + vTemp = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( vFront, pObj, i ) + { + if ( (int)pObj->Level != Level ) + { + pObj->fMarkB = 1; + pObj->TravId = Vec_PtrSize(vTemp); + Vec_PtrPush( vTemp, pObj ); + continue; + } + + pFanin = Ivy_ObjFanin0(pObj); + if ( pFanin->fMarkB == 0 ) + { + pFanin->fMarkB = 1; + pFanin->TravId = Vec_PtrSize(vTemp); + Vec_PtrPush( vTemp, pFanin ); + } + + pFanin = Ivy_ObjFanin1(pObj); + if ( pFanin->fMarkB == 0 ) + { + pFanin->fMarkB = 1; + pFanin->TravId = Vec_PtrSize(vTemp); + Vec_PtrPush( vTemp, pFanin ); + } + } + // collect the permutation + NewSize = IVY_MAX(dd->size, Vec_PtrSize(vTemp)); + pFuncs = ALLOC( DdNode *, NewSize ); + Vec_PtrForEachEntry( vFront, pObj, i ) + { + if ( (int)pObj->Level != Level ) + pFuncs[i] = Cudd_bddIthVar( dd, pObj->TravId ); + else + pFuncs[i] = Cudd_bddAnd( dd, + Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ), + Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ) ); + Cudd_Ref( pFuncs[i] ); + } + // add the remaining vars + assert( NewSize == dd->size ); + for ( i = Vec_PtrSize(vFront); i < dd->size; i++ ) + { + pFuncs[i] = Cudd_bddIthVar( dd, i ); + Cudd_Ref( pFuncs[i] ); + } + + // create new + bFuncNew = Cudd_bddVectorCompose( dd, bFunc, pFuncs ); Cudd_Ref( bFuncNew ); + // clean trav Id + Vec_PtrForEachEntry( vTemp, pObj, i ) + { + pObj->fMarkB = 0; + pObj->TravId = 0; + } + // deref + for ( i = 0; i < dd->size; i++ ) + Cudd_RecursiveDeref( dd, pFuncs[i] ); + free( pFuncs ); + + free( vFront->pArray ); + *vFront = *vTemp; + + vTemp->nCap = vTemp->nSize = 0; + vTemp->pArray = NULL; + Vec_PtrFree( vTemp ); + + Cudd_Deref( bFuncNew ); + return bFuncNew; +} + +/**Function************************************************************* + + Synopsis [Checks equivalence using BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ) +{ + static DdManager * dd = NULL; + DdNode * bFunc, * bTemp; + Vec_Ptr_t * vFront; + Ivy_Obj_t * pObj; + int i, RetValue, Iter, Level; + // start the manager + if ( dd == NULL ) + dd = Cudd_Init( 50, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + // create front + vFront = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vFront, pObj1 ); + Vec_PtrPush( vFront, pObj2 ); + // get the function + bFunc = Cudd_bddXor( dd, Cudd_bddIthVar(dd,0), Cudd_bddIthVar(dd,1) ); Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, pObj1->fPhase != pObj2->fPhase ); + // try running BDDs + for ( Iter = 0; ; Iter++ ) + { + // find max level + Level = 0; + Vec_PtrForEachEntry( vFront, pObj, i ) + if ( Level < (int)pObj->Level ) + Level = (int)pObj->Level; + if ( Level == 0 ) + break; + bFunc = Ivy_FraigNodesAreEquivBdd_int( dd, bTemp = bFunc, vFront, Level ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + if ( bFunc == Cudd_ReadLogicZero(dd) ) // proved + {printf( "%d", Iter ); break;} + if ( Cudd_DagSize(bFunc) > 1000 ) + {printf( "b" ); break;} + if ( dd->size > 120 ) + {printf( "s" ); break;} + if ( Iter > 50 ) + {printf( "i" ); break;} + } + if ( bFunc == Cudd_ReadLogicZero(dd) ) // unsat + RetValue = 1; + else if ( Level == 0 ) // sat + RetValue = 0; + else + RetValue = -1; // spaceout/timeout + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vFront ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyHaig.c b/abc70930/src/aig/ivy/ivyHaig.c new file mode 100644 index 00000000..87021600 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyHaig.c @@ -0,0 +1,530 @@ +/**CFile**************************************************************** + + FileName [ivyHaig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [HAIG management procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyHaig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + HAIGing rules in working AIG: + - Each node in the working AIG has a pointer to the corresponding node in HAIG + (this node is not necessarily the representative of the equivalence class of HAIG nodes) + - This pointer is complemented if the AIG node and its corresponding HAIG node have different phase + + Choice node rules in HAIG: + - Equivalent nodes are linked into a ring + - Exactly one node in the ring has fanouts (this node is called the representative) + - The pointer going from a node to the next node in the ring is complemented + if the first node is complemented, compared to the representative node of the equivalence class + - (consequence of the above) The representative node always has non-complemented pointer to the next node + - New nodes are inserted into the ring immediately after the representative node +*/ + +// returns the representative node of the given HAIG node +static inline Ivy_Obj_t * Ivy_HaigObjRepr( Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj) ); + // if the node has no equivalent node or has fanout, it is representative + if ( pObj->pEquiv == NULL || Ivy_ObjRefs(pObj) > 0 ) + return pObj; + // the node belongs to a class and is not a representative + // complemented edge (pObj->pEquiv) tells if it is complemented w.r.t. the repr + for ( pTemp = Ivy_Regular(pObj->pEquiv); pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + if ( Ivy_ObjRefs(pTemp) > 0 ) + break; + // return the representative node + assert( Ivy_ObjRefs(pTemp) > 0 ); + return Ivy_NotCond( pTemp, Ivy_IsComplement(pObj->pEquiv) ); +} + +// counts the number of nodes in the equivalence class +static inline int Ivy_HaigObjCountClass( Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pTemp; + int Counter; + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjRefs(pObj) > 0 ); + if ( pObj->pEquiv == NULL ) + return 1; + assert( !Ivy_IsComplement(pObj->pEquiv) ); + Counter = 1; + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + Counter++; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts HAIG for the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ) +{ + Vec_Int_t * vLatches; + Ivy_Obj_t * pObj; + int i; + assert( p->pHaig == NULL ); + p->pHaig = Ivy_ManDup( p ); + + if ( fVerbose ) + { + printf( "Starting : " ); + Ivy_ManPrintStats( p->pHaig ); + } + + // collect latches of design D and set their values to be DC + vLatches = Vec_IntAlloc( 100 ); + Ivy_ManForEachLatch( p->pHaig, pObj, i ) + { + pObj->Init = IVY_INIT_DC; + Vec_IntPush( vLatches, pObj->Id ); + } + p->pHaig->pData = vLatches; +/* + { + int x; + Ivy_ManShow( p, 0, NULL ); + Ivy_ManShow( p->pHaig, 1, NULL ); + x = 0; + } +*/ +} + +/**Function************************************************************* + + Synopsis [Transfers the HAIG to the newly created manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ) +{ + Ivy_Obj_t * pObj; + int i; + assert( p->pHaig != NULL ); + Ivy_ManConst1(pNew)->pEquiv = Ivy_ManConst1(p)->pEquiv; + Ivy_ManForEachPi( pNew, pObj, i ) + pObj->pEquiv = Ivy_ManPi( p, i )->pEquiv; + pNew->pHaig = p->pHaig; +} + +/**Function************************************************************* + + Synopsis [Stops HAIG for the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigStop( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + assert( p->pHaig != NULL ); + Vec_IntFree( p->pHaig->pData ); + Ivy_ManStop( p->pHaig ); + p->pHaig = NULL; + // remove dangling pointers to the HAIG objects + Ivy_ManForEachObj( p, pObj, i ) + pObj->pEquiv = NULL; +} + +/**Function************************************************************* + + Synopsis [Creates a new node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pEquiv0, * pEquiv1; + assert( p->pHaig != NULL ); + assert( !Ivy_IsComplement(pObj) ); + if ( Ivy_ObjType(pObj) == IVY_BUF ) + pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); + else if ( Ivy_ObjType(pObj) == IVY_LATCH ) + { +// pObj->pEquiv = Ivy_Latch( p->pHaig, Ivy_ObjChild0Equiv(pObj), pObj->Init ); + pEquiv0 = Ivy_ObjChild0Equiv(pObj); + pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); + pObj->pEquiv = Ivy_Latch( p->pHaig, pEquiv0, pObj->Init ); + } + else if ( Ivy_ObjType(pObj) == IVY_AND ) + { +// pObj->pEquiv = Ivy_And( p->pHaig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + pEquiv0 = Ivy_ObjChild0Equiv(pObj); + pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); + pEquiv1 = Ivy_ObjChild1Equiv(pObj); + pEquiv1 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv1)), Ivy_IsComplement(pEquiv1) ); + pObj->pEquiv = Ivy_And( p->pHaig, pEquiv0, pEquiv1 ); + } + else assert( 0 ); + // make sure the node points to the representative +// pObj->pEquiv = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObj->pEquiv)), Ivy_IsComplement(pObj->pEquiv) ); +} + +/**Function************************************************************* + + Synopsis [Checks if the old node is in the TFI of the new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjIsInTfi_rec( Ivy_Obj_t * pObjNew, Ivy_Obj_t * pObjOld, int Levels ) +{ + if ( pObjNew == pObjOld ) + return 1; + if ( Levels == 0 || Ivy_ObjIsCi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) + return 0; + if ( Ivy_ObjIsInTfi_rec( Ivy_ObjFanin0(pObjNew), pObjOld, Levels - 1 ) ) + return 1; + if ( Ivy_ObjIsNode(pObjNew) && Ivy_ObjIsInTfi_rec( Ivy_ObjFanin1(pObjNew), pObjOld, Levels - 1 ) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Sets the pair of equivalent nodes in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ) +{ + Ivy_Obj_t * pObjOldHaig, * pObjNewHaig; + Ivy_Obj_t * pObjOldHaigR, * pObjNewHaigR; + int fCompl; +//printf( "\nCreating choice for %d and %d in AIG\n", pObjOld->Id, Ivy_Regular(pObjNew)->Id ); + + assert( p->pHaig != NULL ); + assert( !Ivy_IsComplement(pObjOld) ); + // get pointers to the representatives of pObjOld and pObjNew + pObjOldHaig = pObjOld->pEquiv; + pObjNewHaig = Ivy_NotCond( Ivy_Regular(pObjNew)->pEquiv, Ivy_IsComplement(pObjNew) ); + // get the classes + pObjOldHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjOldHaig)), Ivy_IsComplement(pObjOldHaig) ); + pObjNewHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjNewHaig)), Ivy_IsComplement(pObjNewHaig) ); + // get regular pointers + pObjOldHaigR = Ivy_Regular(pObjOldHaig); + pObjNewHaigR = Ivy_Regular(pObjNewHaig); + // check if there is phase difference between them + fCompl = (Ivy_IsComplement(pObjOldHaig) != Ivy_IsComplement(pObjNewHaig)); + // if the class is the same, nothing to do + if ( pObjOldHaigR == pObjNewHaigR ) + return; + // if the second node belongs to a class, do not merge classes (for the time being) + if ( Ivy_ObjRefs(pObjOldHaigR) == 0 || pObjNewHaigR->pEquiv != NULL || + Ivy_ObjRefs(pObjNewHaigR) > 0 ) //|| Ivy_ObjIsInTfi_rec(pObjNewHaigR, pObjOldHaigR, 10) ) + { +/* + if ( pObjNewHaigR->pEquiv != NULL ) + printf( "c" ); + if ( Ivy_ObjRefs(pObjNewHaigR) > 0 ) + printf( "f" ); + printf( " " ); +*/ + p->pHaig->nClassesSkip++; + return; + } + + // add this node to the class of pObjOldHaig + assert( Ivy_ObjRefs(pObjOldHaigR) > 0 ); + assert( !Ivy_IsComplement(pObjOldHaigR->pEquiv) ); + if ( pObjOldHaigR->pEquiv == NULL ) + pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ); + else + pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR->pEquiv, fCompl ); + pObjOldHaigR->pEquiv = pObjNewHaigR; +//printf( "Setting choice node %d -> %d.\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); + // update the class of the new node +// Ivy_Regular(pObjNew)->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ^ Ivy_IsComplement(pObjNew) ); +//printf( "Creating choice for %d and %d in HAIG\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); + +// if ( pObjOldHaigR->Id == 13 ) +// { +// Ivy_ManShow( p, 0 ); +// Ivy_ManShow( p->pHaig, 1 ); +// } +// if ( !Ivy_ManIsAcyclic( p->pHaig ) ) +// printf( "HAIG contains a cycle\n" ); +} + +/**Function************************************************************* + + Synopsis [Count the number of choices and choice nodes in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManHaigCountChoices( Ivy_Man_t * p, int * pnChoices ) +{ + Ivy_Obj_t * pObj; + int nChoices, nChoiceNodes, Counter, i; + assert( p->pHaig != NULL ); + nChoices = nChoiceNodes = 0; + Ivy_ManForEachObj( p->pHaig, pObj, i ) + { + if ( Ivy_ObjIsTerm(pObj) || i == 0 ) + continue; + if ( Ivy_ObjRefs(pObj) == 0 ) + continue; + Counter = Ivy_HaigObjCountClass( pObj ); + nChoiceNodes += (int)(Counter > 1); + nChoices += Counter - 1; +// if ( Counter > 1 ) +// printf( "Choice node %d %s\n", pObj->Id, Ivy_ObjIsLatch(pObj)? "(latch)": "" ); + } + *pnChoices = nChoices; + return nChoiceNodes; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ) +{ + int nChoices, nChoiceNodes; + + assert( p->pHaig != NULL ); + + if ( fVerbose ) + { + printf( "Final : " ); + Ivy_ManPrintStats( p ); + printf( "HAIG : " ); + Ivy_ManPrintStats( p->pHaig ); + + // print choice node stats + nChoiceNodes = Ivy_ManHaigCountChoices( p, &nChoices ); + printf( "Total choice nodes = %d. Total choices = %d. Skipped classes = %d.\n", + nChoiceNodes, nChoices, p->pHaig->nClassesSkip ); + } + + if ( Ivy_ManIsAcyclic( p->pHaig ) ) + { + if ( fVerbose ) + printf( "HAIG is acyclic\n" ); + } + else + printf( "HAIG contains a cycle\n" ); + +// if ( fVerbose ) +// Ivy_ManHaigSimulate( p ); +} + + +/**Function************************************************************* + + Synopsis [Applies the simulation rules.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_Init_t Ivy_ManHaigSimulateAnd( Ivy_Init_t In0, Ivy_Init_t In1 ) +{ + assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); + if ( In0 == IVY_INIT_DC || In1 == IVY_INIT_DC ) + return IVY_INIT_DC; + if ( In0 == IVY_INIT_1 && In1 == IVY_INIT_1 ) + return IVY_INIT_1; + return IVY_INIT_0; +} + +/**Function************************************************************* + + Synopsis [Applies the simulation rules.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_Init_t Ivy_ManHaigSimulateChoice( Ivy_Init_t In0, Ivy_Init_t In1 ) +{ + assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); + if ( (In0 == IVY_INIT_0 && In1 == IVY_INIT_1) || (In0 == IVY_INIT_1 && In1 == IVY_INIT_0) ) + { + printf( "Compatibility fails.\n" ); + return IVY_INIT_0; + } + if ( In0 == IVY_INIT_DC && In1 == IVY_INIT_DC ) + return IVY_INIT_DC; + if ( In0 != IVY_INIT_DC ) + return In0; + return In1; +} + +/**Function************************************************************* + + Synopsis [Simulate HAIG using modified 3-valued simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigSimulate( Ivy_Man_t * p ) +{ + Vec_Int_t * vNodes, * vLatches, * vLatchesD; + Ivy_Obj_t * pObj, * pTemp; + Ivy_Init_t In0, In1; + int i, k, Counter; + int fVerbose = 0; + + // check choices + Ivy_ManCheckChoices( p ); + + // switch to HAIG + assert( p->pHaig != NULL ); + p = p->pHaig; + +if ( fVerbose ) +Ivy_ManForEachPi( p, pObj, i ) +printf( "Setting PI %d\n", pObj->Id ); + + // collect latches and nodes in the DFS order + vNodes = Ivy_ManDfsSeq( p, &vLatches ); + +if ( fVerbose ) +Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) +printf( "Collected node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); + + // set the PI values + Ivy_ManConst1(p)->Init = IVY_INIT_1; + Ivy_ManForEachPi( p, pObj, i ) + pObj->Init = IVY_INIT_0; + + // set the latch values + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->Init = IVY_INIT_DC; + // set the latches of D to be determinate + vLatchesD = p->pData; + Ivy_ManForEachNodeVec( p, vLatchesD, pObj, i ) + pObj->Init = IVY_INIT_0; + + // perform several rounds of simulation + for ( k = 0; k < 10; k++ ) + { + // count the number of non-determinate values + Counter = 0; + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + Counter += ( pObj->Init == IVY_INIT_DC ); + printf( "Iter %d : Non-determinate = %d\n", k, Counter ); + + // simulate the internal nodes + Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) + { +if ( fVerbose ) +printf( "Processing node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); + In0 = Ivy_InitNotCond( Ivy_ObjFanin0(pObj)->Init, Ivy_ObjFaninC0(pObj) ); + In1 = Ivy_InitNotCond( Ivy_ObjFanin1(pObj)->Init, Ivy_ObjFaninC1(pObj) ); + pObj->Init = Ivy_ManHaigSimulateAnd( In0, In1 ); + // simulate the equivalence class if the node is a representative + if ( pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) + { +if ( fVerbose ) +printf( "Processing choice node %d\n", pObj->Id ); + In0 = pObj->Init; + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { +if ( fVerbose ) +printf( "Processing secondary node %d\n", pTemp->Id ); + In1 = Ivy_InitNotCond( pTemp->Init, Ivy_IsComplement(pTemp->pEquiv) ); + In0 = Ivy_ManHaigSimulateChoice( In0, In1 ); + } + pObj->Init = In0; + } + } + + // simulate the latches + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + { + pObj->Level = Ivy_ObjFanin0(pObj)->Init; +if ( fVerbose ) +printf( "Using latch %d with fanin %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id ); + } + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->Init = pObj->Level, pObj->Level = 0; + } + // free arrays + Vec_IntFree( vNodes ); + Vec_IntFree( vLatches ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyMan.c b/abc70930/src/aig/ivy/ivyMan.c new file mode 100644 index 00000000..07faef85 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyMan.c @@ -0,0 +1,546 @@ +/**CFile**************************************************************** + + FileName [ivyMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManStart() +{ + Ivy_Man_t * p; + // start the manager + p = ALLOC( Ivy_Man_t, 1 ); + memset( p, 0, sizeof(Ivy_Man_t) ); + // perform initializations + p->Ghost.Id = -1; + p->nTravIds = 1; + p->fCatchExor = 1; + // allocate arrays for nodes + p->vPis = Vec_PtrAlloc( 100 ); + p->vPos = Vec_PtrAlloc( 100 ); + p->vBufs = Vec_PtrAlloc( 100 ); + p->vObjs = Vec_PtrAlloc( 100 ); + // prepare the internal memory manager + Ivy_ManStartMemory( p ); + // create the constant node + p->pConst1 = Ivy_ManFetchMemory( p ); + p->pConst1->fPhase = 1; + Vec_PtrPush( p->vObjs, p->pConst1 ); + p->nCreated = 1; + // start the table + p->nTableSize = 10007; + p->pTable = ALLOC( int, p->nTableSize ); + memset( p->pTable, 0, sizeof(int) * p->nTableSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ) +{ + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj; + int i; + // create the new manager + pNew = Ivy_ManStart(); + // create the PIs + Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); + Ivy_ManForEachPi( p, pObj, i ) + pObj->pEquiv = Ivy_ObjCreatePi(pNew); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ) +{ + Vec_Int_t * vNodes, * vLatches; + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj; + int i; + // collect latches and nodes in the DFS order + vNodes = Ivy_ManDfsSeq( p, &vLatches ); + // create the new manager + pNew = Ivy_ManStart(); + // create the PIs + Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); + Ivy_ManForEachPi( p, pObj, i ) + pObj->pEquiv = Ivy_ObjCreatePi(pNew); + // create the fake PIs for latches + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->pEquiv = Ivy_ObjCreatePi(pNew); + // duplicate internal nodes + Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) + if ( Ivy_ObjIsBuf(pObj) ) + pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); + else + pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + // add the POs + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(pObj) ); + // transform additional PI nodes into latches and connect them + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + { + assert( !Ivy_ObjFaninC0(pObj) ); + pObj->pEquiv->Type = IVY_LATCH; + pObj->pEquiv->Init = pObj->Init; + Ivy_ObjConnect( pNew, pObj->pEquiv, Ivy_ObjChild0Equiv(pObj), NULL ); + } + // shrink the arrays + Vec_PtrShrink( pNew->vPis, Ivy_ManPiNum(p) ); + // update the counters of different objects + pNew->nObjs[IVY_PI] -= Ivy_ManLatchNum(p); + pNew->nObjs[IVY_LATCH] += Ivy_ManLatchNum(p); + // free arrays + Vec_IntFree( vNodes ); + Vec_IntFree( vLatches ); + // make sure structural hashing did not change anything + assert( Ivy_ManNodeNum(p) == Ivy_ManNodeNum(pNew) ); + assert( Ivy_ManLatchNum(p) == Ivy_ManLatchNum(pNew) ); + // check the resulting network + if ( !Ivy_ManCheck(pNew) ) + printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ) +{ + Vec_Ptr_t * vMapping; + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj; + int i, f, nPis, nPos, nIdMax; + assert( Ivy_ManLatchNum(pMan) == 0 ); + assert( nFrames > 0 ); + // prepare the mapping + nPis = Ivy_ManPiNum(pMan) - nLatches; + nPos = Ivy_ManPoNum(pMan) - nLatches; + nIdMax = Ivy_ManObjIdMax(pMan); + // create the new manager + pNew = Ivy_ManStart(); + // set the starting values of latch inputs + for ( i = 0; i < nLatches; i++ ) + Ivy_ManPo(pMan, nPos+i)->pEquiv = fInit? Ivy_Not(Ivy_ManConst1(pNew)) : Ivy_ObjCreatePi(pNew); + // add timeframes + vMapping = Vec_PtrStart( nIdMax * nFrames + 1 ); + for ( f = 0; f < nFrames; f++ ) + { + // create PIs + Ivy_ManConst1(pMan)->pEquiv = Ivy_ManConst1(pNew); + for ( i = 0; i < nPis; i++ ) + Ivy_ManPi(pMan, i)->pEquiv = Ivy_ObjCreatePi(pNew); + // transfer values to latch outputs + for ( i = 0; i < nLatches; i++ ) + Ivy_ManPi(pMan, nPis+i)->pEquiv = Ivy_ManPo(pMan, nPos+i)->pEquiv; + // perform strashing + Ivy_ManForEachNode( pMan, pObj, i ) + pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + // create POs + for ( i = 0; i < nPos; i++ ) + Ivy_ManPo(pMan, i)->pEquiv = Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, i)) ); + // set the results of latch inputs + for ( i = 0; i < nLatches; i++ ) + Ivy_ManPo(pMan, nPos+i)->pEquiv = Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, nPos+i)); + // save the pointers in this frame + Ivy_ManForEachObj( pMan, pObj, i ) + Vec_PtrWriteEntry( vMapping, f * nIdMax + i, pObj->pEquiv ); + } + // connect latches + if ( !fInit ) + for ( i = 0; i < nLatches; i++ ) + Ivy_ObjCreatePo( pNew, Ivy_ManPo(pMan, nPos+i)->pEquiv ); + // remove dangling nodes + Ivy_ManCleanup(pNew); + *pvMapping = vMapping; + // check the resulting network + if ( !Ivy_ManCheck(pNew) ) + printf( "Ivy_ManFrames(): The check has failed.\n" ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStop( Ivy_Man_t * p ) +{ + if ( p->time1 ) { PRT( "Update lev ", p->time1 ); } + if ( p->time2 ) { PRT( "Update levR ", p->time2 ); } +// Ivy_TableProfile( p ); +// if ( p->vFanouts ) Ivy_ManStopFanout( p ); + if ( p->vChunks ) Ivy_ManStopMemory( p ); + if ( p->vRequired ) Vec_IntFree( p->vRequired ); + if ( p->vPis ) Vec_PtrFree( p->vPis ); + if ( p->vPos ) Vec_PtrFree( p->vPos ); + if ( p->vBufs ) Vec_PtrFree( p->vBufs ); + if ( p->vObjs ) Vec_PtrFree( p->vObjs ); + free( p->pTable ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Removes nodes without fanout.] + + Description [Returns the number of dangling nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCleanup( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pNode; + int i, nNodesOld; + nNodesOld = Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pNode, i ) + if ( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) + if ( Ivy_ObjRefs(pNode) == 0 ) + Ivy_ObjDelete_rec( p, pNode, 1 ); +//printf( "Cleanup removed %d nodes.\n", nNodesOld - Ivy_ManNodeNum(p) ); + return nNodesOld - Ivy_ManNodeNum(p); +} + +/**Function************************************************************* + + Synopsis [Marks nodes reachable from the given one.] + + Description [Returns the number of dangling nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCleanupSeq_rec( Ivy_Obj_t * pObj ) +{ + if ( Ivy_ObjIsMarkA(pObj) ) + return; + Ivy_ObjSetMarkA(pObj); + if ( pObj->pFanin0 != NULL ) + Ivy_ManCleanupSeq_rec( Ivy_ObjFanin0(pObj) ); + if ( pObj->pFanin1 != NULL ) + Ivy_ManCleanupSeq_rec( Ivy_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Removes logic that does not feed into POs.] + + Description [Returns the number of dangling nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCleanupSeq( Ivy_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Ivy_Obj_t * pObj; + int i, RetValue; + // mark the constant and PIs + Ivy_ObjSetMarkA( Ivy_ManConst1(p) ); + Ivy_ManForEachPi( p, pObj, i ) + Ivy_ObjSetMarkA( pObj ); + // mark nodes visited from POs + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ManCleanupSeq_rec( pObj ); + // collect unmarked nodes + vNodes = Vec_PtrAlloc( 100 ); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( Ivy_ObjIsMarkA(pObj) ) + Ivy_ObjClearMarkA(pObj); + else + Vec_PtrPush( vNodes, pObj ); + } + if ( Vec_PtrSize(vNodes) == 0 ) + { + Vec_PtrFree( vNodes ); +//printf( "Sequential sweep cleaned out %d nodes.\n", 0 ); + return 0; + } + // disconnect the marked objects + Vec_PtrForEachEntry( vNodes, pObj, i ) + Ivy_ObjDisconnect( p, pObj ); + // remove the dangling objects + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsLatch(pObj) || Ivy_ObjIsBuf(pObj) ); + assert( Ivy_ObjRefs(pObj) == 0 ); + // update node counters of the manager + p->nObjs[pObj->Type]--; + p->nDeleted++; + // delete buffer from the array of buffers + if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) + Vec_PtrRemove( p->vBufs, pObj ); + // free the node + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Ivy_ManRecycleMemory( p, pObj ); + } + // return the number of nodes freed + RetValue = Vec_PtrSize(vNodes); + Vec_PtrFree( vNodes ); +//printf( "Sequential sweep cleaned out %d nodes.\n", RetValue ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManLatchIsSelfFeed_rec( Ivy_Obj_t * pLatch, Ivy_Obj_t * pLatchRoot ) +{ + if ( !Ivy_ObjIsLatch(pLatch) && !Ivy_ObjIsBuf(pLatch) ) + return 0; + if ( pLatch == pLatchRoot ) + return 1; + return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatchRoot ); +} + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManLatchIsSelfFeed( Ivy_Obj_t * pLatch ) +{ + if ( !Ivy_ObjIsLatch(pLatch) ) + return 0; + return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatch ); +} + + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ) +{ + Ivy_Obj_t * pNode; + int LimitFactor = 100; + int NodeBeg = Ivy_ManNodeNum(p); + int nSteps; + for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ ) + { + pNode = Vec_PtrEntryLast(p->vBufs); + while ( Ivy_ObjIsBuf(pNode) ) + pNode = Ivy_ObjReadFirstFanout( p, pNode ); + // check if this buffer should remain + if ( Ivy_ManLatchIsSelfFeed(pNode) ) + { + Vec_PtrPop(p->vBufs); + continue; + } +//printf( "Propagating buffer %d with input %d and output %d\n", Ivy_ObjFaninId0(pNode), Ivy_ObjFaninId0(Ivy_ObjFanin0(pNode)), pNode->Id ); +//printf( "Latch num %d\n", Ivy_ManLatchNum(p) ); + Ivy_NodeFixBufferFanins( p, pNode, fUpdateLevel ); + if ( nSteps > NodeBeg * LimitFactor ) + { + printf( "Structural hashing is not finished after %d forward latch moves.\n", NodeBeg * LimitFactor ); + printf( "This circuit cannot be forward-retimed completely. Quitting.\n" ); + break; + } + } +// printf( "Number of steps = %d. Nodes beg = %d. Nodes end = %d.\n", nSteps, NodeBeg, Ivy_ManNodeNum(p) ); + return nSteps; +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManPrintStats( Ivy_Man_t * p ) +{ + printf( "PI/PO = %d/%d ", Ivy_ManPiNum(p), Ivy_ManPoNum(p) ); + printf( "A = %7d. ", Ivy_ManAndNum(p) ); + printf( "L = %5d. ", Ivy_ManLatchNum(p) ); +// printf( "X = %d. ", Ivy_ManExorNum(p) ); +// printf( "B = %3d. ", Ivy_ManBufNum(p) ); + printf( "MaxID = %7d. ", Ivy_ManObjIdMax(p) ); +// printf( "Cre = %d. ", p->nCreated ); +// printf( "Del = %d. ", p->nDeleted ); + printf( "Lev = %3d. ", Ivy_ManLatchNum(p)? -1 : Ivy_ManLevels(p) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Converts a combinational AIG manager into a sequential one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ) +{ + Ivy_Obj_t * pObj, * pLatch; + Ivy_Init_t Init; + int i; + if ( nLatches == 0 ) + return; + assert( nLatches < Ivy_ManPiNum(p) && nLatches < Ivy_ManPoNum(p) ); + assert( Ivy_ManPiNum(p) == Vec_PtrSize(p->vPis) ); + assert( Ivy_ManPoNum(p) == Vec_PtrSize(p->vPos) ); + assert( Vec_PtrSize( p->vBufs ) == 0 ); + // create fanouts + if ( p->fFanout == 0 ) + Ivy_ManStartFanout( p ); + // collect the POs to be converted into latches + for ( i = 0; i < nLatches; i++ ) + { + // get the latch value + Init = pInits? pInits[i] : IVY_INIT_0; + // create latch + pObj = Ivy_ManPo( p, Ivy_ManPoNum(p) - nLatches + i ); + pLatch = Ivy_Latch( p, Ivy_ObjChild0(pObj), Init ); + Ivy_ObjDisconnect( p, pObj ); + // recycle the old PO object + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Ivy_ManRecycleMemory( p, pObj ); + // convert the corresponding PI to a buffer and connect it to the latch + pObj = Ivy_ManPi( p, Ivy_ManPiNum(p) - nLatches + i ); + pObj->Type = IVY_BUF; + Ivy_ObjConnect( p, pObj, pLatch, NULL ); + // save the buffer + Vec_PtrPush( p->vBufs, pObj ); + } + // shrink the arrays + Vec_PtrShrink( p->vPis, Ivy_ManPiNum(p) - nLatches ); + Vec_PtrShrink( p->vPos, Ivy_ManPoNum(p) - nLatches ); + // update the counters of different objects + p->nObjs[IVY_PI] -= nLatches; + p->nObjs[IVY_PO] -= nLatches; + p->nObjs[IVY_BUF] += nLatches; + p->nDeleted -= 2 * nLatches; + // remove dangling nodes + Ivy_ManCleanup(p); + Ivy_ManCleanupSeq(p); +/* + // check for dangling nodes + Ivy_ManForEachObj( p, pObj, i ) + if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsPo(pObj) && !Ivy_ObjIsConst1(pObj) ) + { + assert( Ivy_ObjRefs(pObj) > 0 ); + assert( Ivy_ObjRefs(pObj) == Ivy_ObjFanoutNum(p, pObj) ); + } +*/ + // perform hashing by propagating the buffers + Ivy_ManPropagateBuffers( p, 0 ); + if ( Ivy_ManBufNum(p) ) + printf( "The number of remaining buffers is %d.\n", Ivy_ManBufNum(p) ); + // fix the levels + Ivy_ManResetLevels( p ); + // check the resulting network + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyMem.c b/abc70930/src/aig/ivy/ivyMem.c new file mode 100644 index 00000000..2a96857c --- /dev/null +++ b/abc70930/src/aig/ivy/ivyMem.c @@ -0,0 +1,116 @@ +/**CFile**************************************************************** + + FileName [ivyMem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Memory management for the AIG nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// memory management +#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes +#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStartMemory( Ivy_Man_t * p ) +{ + p->vChunks = Vec_PtrAlloc( 128 ); + p->vPages = Vec_PtrAlloc( 128 ); +} + +/**Function************************************************************* + + Synopsis [Stops the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStopMemory( Ivy_Man_t * p ) +{ + void * pMemory; + int i; + Vec_PtrForEachEntry( p->vChunks, pMemory, i ) + free( pMemory ); + Vec_PtrFree( p->vChunks ); + Vec_PtrFree( p->vPages ); + p->pListFree = NULL; +} + +/**Function************************************************************* + + Synopsis [Allocates additional memory for the nodes.] + + Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. + Records the pointer to the AIG manager in the -1 entry.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManAddMemory( Ivy_Man_t * p ) +{ + char * pMemory; + int i, nBytes; + int EntrySizeMax = 128; + assert( sizeof(Ivy_Obj_t) <= EntrySizeMax ); + assert( p->pListFree == NULL ); +// assert( (Ivy_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); + // allocate new memory page + nBytes = sizeof(Ivy_Obj_t) * (1<vChunks, pMemory ); + // align memory at the 32-byte boundary + pMemory = pMemory + EntrySizeMax - (((int)pMemory) & (EntrySizeMax-1)); + // remember the manager in the first entry + Vec_PtrPush( p->vPages, pMemory ); + // break the memory down into nodes + p->pListFree = (Ivy_Obj_t *)pMemory; + for ( i = 1; i <= IVY_PAGE_MASK; i++ ) + { + *((char **)pMemory) = pMemory + sizeof(Ivy_Obj_t); + pMemory += sizeof(Ivy_Obj_t); + } + *((char **)pMemory) = NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyMulti.c b/abc70930/src/aig/ivy/ivyMulti.c new file mode 100644 index 00000000..a7970156 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyMulti.c @@ -0,0 +1,301 @@ +/**CFile**************************************************************** + + FileName [ivyMulti.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Constructing multi-input AND/EXOR gates.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IVY_EVAL_LIMIT 128 + +typedef struct Ivy_Eva_t_ Ivy_Eva_t; +struct Ivy_Eva_t_ +{ + Ivy_Obj_t * pArg; // the argument node + unsigned Mask; // the mask of covered nodes + int Weight; // the number of covered nodes +}; + +static void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ); +static int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructs a balanced tree while taking sharing into account.] + + Description [Returns 1 if the implementation exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSols ) +{ + static Ivy_Eva_t pEvals[IVY_EVAL_LIMIT]; + Ivy_Eva_t * pEval, * pFan0, * pFan1; + Ivy_Obj_t * pObj, * pTemp; + int nEvals, nEvalsOld, i, k, x, nLeaves; + unsigned uMaskAll; + + // consider special cases + nLeaves = Vec_PtrSize(vLeaves); + assert( nLeaves > 2 ); + if ( nLeaves > 32 || nLeaves + Vec_PtrSize(vCone) > IVY_EVAL_LIMIT ) + return 0; +// if ( nLeaves == 1 ) +// return Vec_PtrEntry( vLeaves, 0 ); +// if ( nLeaves == 2 ) +// return Ivy_Oper( Vec_PtrEntry(vLeaves, 0), Vec_PtrEntry(vLeaves, 1), Type ); + + // set the leaf entries + uMaskAll = ((1 << nLeaves) - 1); + nEvals = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + pEval = pEvals + nEvals; + pEval->pArg = pObj; + pEval->Mask = (1 << nEvals); + pEval->Weight = 1; + // mark the leaf + Ivy_Regular(pObj)->TravId = nEvals; + nEvals++; + } + + // propagate masks through the cone + Vec_PtrForEachEntry( vCone, pObj, i ) + { + pObj->TravId = nEvals + i; + if ( Ivy_ObjIsBuf(pObj) ) + pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask; + else + pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask | pEvals[Ivy_ObjFanin1(pObj)->TravId].Mask; + } + + // set the internal entries + Vec_PtrForEachEntry( vCone, pObj, i ) + { + if ( i == Vec_PtrSize(vCone) - 1 ) + break; + // skip buffers + if ( Ivy_ObjIsBuf(pObj) ) + continue; + // skip nodes without external fanout + if ( Ivy_ObjRefs(pObj) == 0 ) + continue; + assert( !Ivy_IsComplement(pObj) ); + pEval = pEvals + nEvals; + pEval->pArg = pObj; + pEval->Mask = pEvals[pObj->TravId].Mask; + pEval->Weight = Extra_WordCountOnes(pEval->Mask); + // mark the node + pObj->TravId = nEvals; + nEvals++; + } + + // find the available nodes + nEvalsOld = nEvals; + for ( i = 1; i < nEvals; i++ ) + for ( k = 0; k < i; k++ ) + { + pFan0 = pEvals + i; + pFan1 = pEvals + k; + pTemp = Ivy_TableLookup(p, Ivy_ObjCreateGhost(p, pFan0->pArg, pFan1->pArg, Type, IVY_INIT_NONE)); + // skip nodes in the cone + if ( pTemp == NULL || pTemp->fMarkB ) + continue; + // skip the leaves + for ( x = 0; x < nLeaves; x++ ) + if ( pTemp == Ivy_Regular(vLeaves->pArray[x]) ) + break; + if ( x < nLeaves ) + continue; + pEval = pEvals + nEvals; + pEval->pArg = pTemp; + pEval->Mask = pFan0->Mask | pFan1->Mask; + pEval->Weight = (pFan0->Mask & pFan1->Mask) ? Extra_WordCountOnes(pEval->Mask) : pFan0->Weight + pFan1->Weight; + // save the argument + pObj->TravId = nEvals; + nEvals++; + // quit if the number of entries exceeded the limit + if ( nEvals == IVY_EVAL_LIMIT ) + goto Outside; + // quit if we found an acceptable implementation + if ( pEval->Mask == uMaskAll ) + goto Outside; + } +Outside: + +// Ivy_MultiPrint( pEvals, nLeaves, nEvals ); + if ( !Ivy_MultiCover( p, pEvals, nLeaves, nEvals, nLimit, vSols ) ) + return 0; + assert( Vec_PtrSize( vSols ) > 0 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes how many uncovered ones this one covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ) +{ + Ivy_Eva_t * pEval; + int i, k; + for ( i = nLeaves; i < nEvals; i++ ) + { + pEval = pEvals + i; + printf( "%2d (id = %5d) : |", i-nLeaves, Ivy_ObjId(pEval->pArg) ); + for ( k = 0; k < nLeaves; k++ ) + { + if ( pEval->Mask & (1 << k) ) + printf( "+" ); + else + printf( " " ); + } + printf( "| Lev = %d.\n", Ivy_ObjLevel(pEval->pArg) ); + } +} + +/**Function************************************************************* + + Synopsis [Computes how many uncovered ones this one covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_MultiWeight( unsigned uMask, int nMaskOnes, unsigned uFound ) +{ + assert( uMask & ~uFound ); + if ( (uMask & uFound) == 0 ) + return nMaskOnes; + return Extra_WordCountOnes( uMask & ~uFound ); +} + +/**Function************************************************************* + + Synopsis [Finds the cover.] + + Description [Returns 1 if the cover is found.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ) +{ + int fVerbose = 0; + Ivy_Eva_t * pEval, * pEvalBest; + unsigned uMaskAll, uFound, uTemp; + int i, k, BestK, WeightBest, WeightCur, LevelBest, LevelCur; + uMaskAll = (nLeaves == 32)? (~(unsigned)0) : ((1 << nLeaves) - 1); + uFound = 0; + // solve the covering problem + if ( fVerbose ) + printf( "Solution: " ); + Vec_PtrClear( vSols ); + for ( i = 0; i < nLimit; i++ ) + { + BestK = -1; + for ( k = nEvals - 1; k >= 0; k-- ) + { + pEval = pEvals + k; + if ( (pEval->Mask & ~uFound) == 0 ) + continue; + if ( BestK == -1 ) + { + BestK = k; + pEvalBest = pEval; + WeightBest = Ivy_MultiWeight( pEvalBest->Mask, pEvalBest->Weight, uFound ); + LevelBest = Ivy_ObjLevel( Ivy_Regular(pEvalBest->pArg) ); + continue; + } + // compare BestK and the new one (k) + WeightCur = Ivy_MultiWeight( pEval->Mask, pEval->Weight, uFound ); + LevelCur = Ivy_ObjLevel( Ivy_Regular(pEval->pArg) ); + if ( WeightBest < WeightCur || + (WeightBest == WeightCur && LevelBest > LevelCur) ) + { + BestK = k; + pEvalBest = pEval; + WeightBest = WeightCur; + LevelBest = LevelCur; + } + } + assert( BestK != -1 ); + // if the cost is only 1, take the leaf + if ( WeightBest == 1 && BestK >= nLeaves ) + { + uTemp = (pEvalBest->Mask & ~uFound); + for ( k = 0; k < nLeaves; k++ ) + if ( uTemp & (1 << k) ) + break; + assert( k < nLeaves ); + BestK = k; + pEvalBest = pEvals + BestK; + } + if ( fVerbose ) + { + if ( BestK < nLeaves ) + printf( "L(%d) ", BestK ); + else + printf( "%d ", BestK - nLeaves ); + } + // update the found set + Vec_PtrPush( vSols, pEvalBest->pArg ); + uFound |= pEvalBest->Mask; + if ( uFound == uMaskAll ) + break; + } + if ( uFound == uMaskAll ) + { + if ( fVerbose ) + printf( " Found \n\n" ); + return 1; + } + else + { + if ( fVerbose ) + printf( " Not found \n\n" ); + return 0; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyMulti8.c b/abc70930/src/aig/ivy/ivyMulti8.c new file mode 100644 index 00000000..059d1500 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyMulti8.c @@ -0,0 +1,427 @@ +/**CFile**************************************************************** + + FileName [ivyMulti.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Constructing multi-input AND/EXOR gates.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ivy_Eval_t_ Ivy_Eval_t; +struct Ivy_Eval_t_ +{ + unsigned Mask : 5; // the mask of covered nodes + unsigned Weight : 3; // the number of covered nodes + unsigned Cost : 4; // the number of overlapping nodes + unsigned Level : 12; // the level of this node + unsigned Fan0 : 4; // the first fanin + unsigned Fan1 : 4; // the second fanin +}; + +static Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +static void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ); +static int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ); +static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Ivy_Multi_rec( ppObjs, nObjs/2, Type ); + pObj2 = Ivy_Multi_rec( ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Ivy_Oper( pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Constructs a balanced tree while taking sharing into account.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgsInit, int nArgs, Ivy_Type_t Type ) +{ + static char NumBits[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5}; + static Ivy_Eval_t pEvals[15+15*14/2]; + static Ivy_Obj_t * pArgs[16]; + Ivy_Eval_t * pEva, * pEvaBest; + int nArgsNew, nEvals, i, k; + Ivy_Obj_t * pTemp; + + // consider the case of one argument + assert( nArgs > 0 ); + if ( nArgs == 1 ) + return pArgsInit[0]; + // consider the case of two arguments + if ( nArgs == 2 ) + return Ivy_Oper( pArgsInit[0], pArgsInit[1], Type ); + +//Ivy_MultiEval( pArgsInit, nArgs, Type ); printf( "\n" ); + + // set the initial ones + for ( i = 0; i < nArgs; i++ ) + { + pArgs[i] = pArgsInit[i]; + pEva = pEvals + i; + pEva->Mask = (1 << i); + pEva->Weight = 1; + pEva->Cost = 0; + pEva->Level = Ivy_Regular(pArgs[i])->Level; + pEva->Fan0 = 0; + pEva->Fan1 = 0; + } + + // find the available nodes + pEvaBest = pEvals; + nArgsNew = nArgs; + for ( i = 1; i < nArgsNew; i++ ) + for ( k = 0; k < i; k++ ) + if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)) ) + { + pEva = pEvals + nArgsNew; + pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; + pEva->Weight = NumBits[pEva->Mask]; + pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; + pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); + pEva->Fan0 = k; + pEva->Fan1 = i; +// assert( pEva->Level == (unsigned)Ivy_ObjLevel(pTemp) ); + // compare + if ( pEvaBest->Weight < pEva->Weight || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) + pEvaBest = pEva; + // save the argument + pArgs[nArgsNew++] = pTemp; + if ( nArgsNew == 15 ) + goto Outside; + } +Outside: + +// printf( "Best = %d.\n", pEvaBest - pEvals ); + + // the case of no common nodes + if ( nArgsNew == nArgs ) + { + Ivy_MultiSort( pArgs, nArgs ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); + } + // the case of one common node + if ( nArgsNew == nArgs + 1 ) + { + assert( pEvaBest - pEvals == nArgs ); + k = 0; + for ( i = 0; i < nArgs; i++ ) + if ( i != (int)pEvaBest->Fan0 && i != (int)pEvaBest->Fan1 ) + pArgs[k++] = pArgs[i]; + pArgs[k++] = pArgs[nArgs]; + assert( k == nArgs - 1 ); + nArgs = k; + Ivy_MultiSort( pArgs, nArgs ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); + } + // the case when there is a node that covers everything + if ( (int)pEvaBest->Mask == ((1 << nArgs) - 1) ) + return Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); + + // evaluate node pairs + nEvals = nArgsNew; + for ( i = 1; i < nArgsNew; i++ ) + for ( k = 0; k < i; k++ ) + { + pEva = pEvals + nEvals; + pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; + pEva->Weight = NumBits[pEva->Mask]; + pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; + pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); + pEva->Fan0 = k; + pEva->Fan1 = i; + // compare + if ( pEvaBest->Weight < pEva->Weight || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) + pEvaBest = pEva; + // save the argument + nEvals++; + } + assert( pEvaBest - pEvals >= nArgsNew ); + +// printf( "Used (%d, %d).\n", pEvaBest->Fan0, pEvaBest->Fan1 ); + + // get the best implementation + pTemp = Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); + + // collect those not covered by EvaBest + k = 0; + for ( i = 0; i < nArgs; i++ ) + if ( (pEvaBest->Mask & (1 << i)) == 0 ) + pArgs[k++] = pArgs[i]; + pArgs[k++] = pTemp; + assert( k == nArgs - (int)pEvaBest->Weight + 1 ); + nArgs = k; + Ivy_MultiSort( pArgs, nArgs ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements multi-input AND/EXOR operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pNode0, * pNode1; + if ( iNum < nArgs ) + return pArgs[iNum]; + pNode0 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan0, pArgs, nArgs, Type ); + pNode1 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan1, pArgs, nArgs, Type ); + return Ivy_Oper( pNode0, pNode1, Type ); +} + +/**Function************************************************************* + + Synopsis [Selection-sorts the nodes in the decreasing over of level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ) +{ + Ivy_Obj_t * pTemp; + int i, j, iBest; + + for ( i = 0; i < nArgs-1; i++ ) + { + iBest = i; + for ( j = i+1; j < nArgs; j++ ) + if ( Ivy_Regular(pArgs[j])->Level > Ivy_Regular(pArgs[iBest])->Level ) + iBest = j; + pTemp = pArgs[i]; + pArgs[i] = pArgs[iBest]; + pArgs[iBest] = pTemp; + } +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ) +{ + Ivy_Obj_t * pNode1, * pNode2; + int i; + // try to find the node in the array + for ( i = 0; i < nArgs; i++ ) + if ( pArray[i] == pNode ) + return nArgs; + // put the node last + pArray[nArgs++] = pNode; + // find the place to put the new node + for ( i = nArgs-1; i > 0; i-- ) + { + pNode1 = pArray[i ]; + pNode2 = pArray[i-1]; + if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level ) + break; + pArray[i ] = pNode2; + pArray[i-1] = pNode1; + } + return nArgs; +} + +/**Function************************************************************* + + Synopsis [Balances the array recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pNodeNew; + // consider the case of one argument + assert( nArgs > 0 ); + if ( nArgs == 1 ) + return pArgs[0]; + // consider the case of two arguments + if ( nArgs == 2 ) + return Ivy_Oper( pArgs[0], pArgs[1], Type ); + // get the last two nodes + pNodeNew = Ivy_Oper( pArgs[nArgs-1], pArgs[nArgs-2], Type ); + // add the new node + nArgs = Ivy_MultiPushUniqueOrderByLevel( pArgs, nArgs - 2, pNodeNew ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements multi-input AND/EXOR operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pTemp; + int i, k; + int nArgsOld = nArgs; + for ( i = 0; i < nArgs; i++ ) + printf( "%d[%d] ", i, Ivy_Regular(pArgs[i])->Level ); + for ( i = 1; i < nArgs; i++ ) + for ( k = 0; k < i; k++ ) + { + pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)); + if ( pTemp != NULL ) + { + printf( "%d[%d]=(%d,%d) ", nArgs, Ivy_Regular(pTemp)->Level, k, i ); + pArgs[nArgs++] = pTemp; + } + } + printf( " ((%d/%d)) ", nArgsOld, nArgs-nArgsOld ); + return NULL; +} + + + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pArgsRef[5], * pTemp; + int i, k, m, nArgsNew, Counter = 0; + + +//Ivy_MultiEval( pArgs, nArgs, Type ); printf( "\n" ); + + + assert( Type == IVY_AND || Type == IVY_EXOR ); + assert( nArgs > 0 ); + if ( nArgs == 1 ) + return pArgs[0]; + + // find the nodes with more than one fanout + nArgsNew = 0; + for ( i = 0; i < nArgs; i++ ) + if ( Ivy_ObjRefs( Ivy_Regular(pArgs[i]) ) > 0 ) + pArgsRef[nArgsNew++] = pArgs[i]; + + // go through pairs + if ( nArgsNew >= 2 ) + for ( i = 0; i < nArgsNew; i++ ) + for ( k = i + 1; k < nArgsNew; k++ ) + if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) + Counter++; +// printf( "%d", Counter ); + + // go through pairs + if ( nArgsNew >= 2 ) + for ( i = 0; i < nArgsNew; i++ ) + for ( k = i + 1; k < nArgsNew; k++ ) + if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) + { + nArgsNew = 0; + for ( m = 0; m < nArgs; m++ ) + if ( pArgs[m] != pArgsRef[i] && pArgs[m] != pArgsRef[k] ) + pArgs[nArgsNew++] = pArgs[m]; + pArgs[nArgsNew++] = pTemp; + assert( nArgsNew == nArgs - 1 ); + return Ivy_Multi1( pArgs, nArgsNew, Type ); + } + return Ivy_Multi_rec( pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi2( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + assert( Type == IVY_AND || Type == IVY_EXOR ); + assert( nArgs > 0 ); + return Ivy_Multi_rec( pArgs, nArgs, Type ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyObj.c b/abc70930/src/aig/ivy/ivyObj.c new file mode 100644 index 00000000..59dda19c --- /dev/null +++ b/abc70930/src/aig/ivy/ivyObj.c @@ -0,0 +1,476 @@ +/**CFile**************************************************************** + + FileName [ivyObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Adding/removing objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ) +{ + return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, NULL, NULL, IVY_PI, IVY_INIT_NONE) ); +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ) +{ + return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pDriver, NULL, IVY_PO, IVY_INIT_NONE) ); +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) +{ + Ivy_Obj_t * pObj; + assert( !Ivy_IsComplement(pGhost) ); + assert( Ivy_ObjIsGhost(pGhost) ); + assert( Ivy_TableLookup(p, pGhost) == NULL ); + // get memory for the new object + pObj = Ivy_ManFetchMemory( p ); + assert( Ivy_ObjIsNone(pObj) ); + pObj->Id = Vec_PtrSize(p->vObjs); + Vec_PtrPush( p->vObjs, pObj ); + // add basic info (fanins, compls, type, init) + pObj->Type = pGhost->Type; + pObj->Init = pGhost->Init; + // add connections + Ivy_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); + // compute level + if ( Ivy_ObjIsNode(pObj) ) + pObj->Level = Ivy_ObjLevelNew(pObj); + else if ( Ivy_ObjIsLatch(pObj) ) + pObj->Level = 0; + else if ( Ivy_ObjIsOneFanin(pObj) ) + pObj->Level = Ivy_ObjFanin0(pObj)->Level; + else if ( !Ivy_ObjIsPi(pObj) ) + assert( 0 ); + // create phase + if ( Ivy_ObjIsNode(pObj) ) + pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) & Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); + else if ( Ivy_ObjIsOneFanin(pObj) ) + pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); + // set the fail TFO flag + if ( Ivy_ObjIsNode(pObj) ) + pObj->fFailTfo = Ivy_ObjFanin0(pObj)->fFailTfo | Ivy_ObjFanin1(pObj)->fFailTfo; + // mark the fanins in a special way if the node is EXOR + if ( Ivy_ObjIsExor(pObj) ) + { + Ivy_ObjFanin0(pObj)->fExFan = 1; + Ivy_ObjFanin1(pObj)->fExFan = 1; + } + // add PIs/POs to the arrays + if ( Ivy_ObjIsPi(pObj) ) + Vec_PtrPush( p->vPis, pObj ); + else if ( Ivy_ObjIsPo(pObj) ) + Vec_PtrPush( p->vPos, pObj ); +// else if ( Ivy_ObjIsBuf(pObj) ) +// Vec_PtrPush( p->vBufs, pObj ); + if ( p->vRequired && Vec_IntSize(p->vRequired) <= pObj->Id ) + Vec_IntFillExtra( p->vRequired, 2 * Vec_IntSize(p->vRequired), 1000000 ); + // update node counters of the manager + p->nObjs[Ivy_ObjType(pObj)]++; + p->nCreated++; + +// printf( "Adding %sAIG node: ", p->pHaig==NULL? "H":" " ); +// Ivy_ObjPrintVerbose( p, pObj, p->pHaig==NULL ); +// printf( "\n" ); + + // if HAIG is defined, create a corresponding node + if ( p->pHaig ) + Ivy_ManHaigCreateObj( p, pObj ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || pFan1 != NULL ); + // add the first fanin + pObj->pFanin0 = pFan0; + pObj->pFanin1 = pFan1; + // increment references of the fanins and add their fanouts + if ( Ivy_ObjFanin0(pObj) != NULL ) + { + Ivy_ObjRefsInc( Ivy_ObjFanin0(pObj) ); + if ( p->fFanout ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); + } + if ( Ivy_ObjFanin1(pObj) != NULL ) + { + Ivy_ObjRefsInc( Ivy_ObjFanin1(pObj) ); + if ( p->fFanout ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); + } + // add the node to the structural hash table + Ivy_TableInsert( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || Ivy_ObjFanin1(pObj) != NULL ); + // remove connections + if ( pObj->pFanin0 != NULL ) + { + Ivy_ObjRefsDec(Ivy_ObjFanin0(pObj)); + if ( p->fFanout ) + Ivy_ObjDeleteFanout( p, Ivy_ObjFanin0(pObj), pObj ); + } + if ( pObj->pFanin1 != NULL ) + { + Ivy_ObjRefsDec(Ivy_ObjFanin1(pObj)); + if ( p->fFanout ) + Ivy_ObjDeleteFanout( p, Ivy_ObjFanin1(pObj), pObj ); + } + assert( pObj->pNextFan0 == NULL ); + assert( pObj->pNextFan1 == NULL ); + assert( pObj->pPrevFan0 == NULL ); + assert( pObj->pPrevFan1 == NULL ); + // remove the node from the structural hash table + Ivy_TableDelete( p, pObj ); + // add the first fanin + pObj->pFanin0 = NULL; + pObj->pFanin1 = NULL; +} + +/**Function************************************************************* + + Synopsis [Replaces the first fanin of the node by the new fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ) +{ + Ivy_Obj_t * pFaninOld; + assert( !Ivy_IsComplement(pObj) ); + pFaninOld = Ivy_ObjFanin0(pObj); + // decrement ref and remove fanout + Ivy_ObjRefsDec( pFaninOld ); + if ( p->fFanout ) + Ivy_ObjDeleteFanout( p, pFaninOld, pObj ); + // update the fanin + pObj->pFanin0 = pFaninNew; + // increment ref and add fanout + Ivy_ObjRefsInc( Ivy_Regular(pFaninNew) ); + if ( p->fFanout ) + Ivy_ObjAddFanout( p, Ivy_Regular(pFaninNew), pObj ); + // get rid of old fanin + if ( !Ivy_ObjIsPi(pFaninOld) && !Ivy_ObjIsConst1(pFaninOld) && Ivy_ObjRefs(pFaninOld) == 0 ) + Ivy_ObjDelete_rec( p, pFaninOld, 1 ); +} + +/**Function************************************************************* + + Synopsis [Deletes the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjRefs(pObj) == 0 || !fFreeTop ); + // update node counters of the manager + p->nObjs[pObj->Type]--; + p->nDeleted++; + // remove connections + Ivy_ObjDisconnect( p, pObj ); + // remove PIs/POs from the arrays + if ( Ivy_ObjIsPi(pObj) ) + Vec_PtrRemove( p->vPis, pObj ); + else if ( Ivy_ObjIsPo(pObj) ) + Vec_PtrRemove( p->vPos, pObj ); + else if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) + Vec_PtrRemove( p->vBufs, pObj ); + // clean and recycle the entry + if ( fFreeTop ) + { + // free the node + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Ivy_ManRecycleMemory( p, pObj ); + } + else + { + int nRefsOld = pObj->nRefs; + Ivy_Obj_t * pFanout = pObj->pFanout; + Ivy_ObjClean( pObj ); + pObj->pFanout = pFanout; + pObj->nRefs = nRefsOld; + } +} + +/**Function************************************************************* + + Synopsis [Deletes the MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) +{ + Ivy_Obj_t * pFanin0, * pFanin1; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_ObjIsNone(pObj) ); + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsPi(pObj) ) + return; + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + Ivy_ObjDelete( p, pObj, fFreeTop ); + if ( pFanin0 && !Ivy_ObjIsNone(pFanin0) && Ivy_ObjRefs(pFanin0) == 0 ) + Ivy_ObjDelete_rec( p, pFanin0, 1 ); + if ( pFanin1 && !Ivy_ObjIsNone(pFanin1) && Ivy_ObjRefs(pFanin1) == 0 ) + Ivy_ObjDelete_rec( p, pFanin1, 1 ); +} + +/**Function************************************************************* + + Synopsis [Replaces one object by another.] + + Description [Both objects are currently in the manager. The new object + (pObjNew) should be used instead of the old object (pObjOld). If the + new object is complemented or used, the buffer is added.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ) +{ + int nRefsOld;//, clk; + // the object to be replaced cannot be complemented + assert( !Ivy_IsComplement(pObjOld) ); + // the object to be replaced cannot be a terminal + assert( Ivy_ObjIsNone(pObjOld) || !Ivy_ObjIsPi(pObjOld) ); + // the object to be used cannot be a PO or assert + assert( !Ivy_ObjIsBuf(Ivy_Regular(pObjNew)) ); + // the object cannot be the same + assert( pObjOld != Ivy_Regular(pObjNew) ); +//printf( "Replacing %d by %d.\n", Ivy_Regular(pObjOld)->Id, Ivy_Regular(pObjNew)->Id ); + + // if HAIG is defined, create the choice node + if ( p->pHaig ) + { +// if ( pObjOld->Id == 31 ) +// { +// Ivy_ManShow( p, 0 ); +// Ivy_ManShow( p->pHaig, 1 ); +// } + Ivy_ManHaigCreateChoice( p, pObjOld, pObjNew ); + } + // if the new object is complemented or already used, add the buffer + if ( Ivy_IsComplement(pObjNew) || Ivy_ObjIsLatch(pObjNew) || Ivy_ObjRefs(pObjNew) > 0 || Ivy_ObjIsPi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) + pObjNew = Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pObjNew, NULL, IVY_BUF, IVY_INIT_NONE) ); + assert( !Ivy_IsComplement(pObjNew) ); + if ( fUpdateLevel ) + { +//clk = clock(); + // if the new node's arrival time is different, recursively update arrival time of the fanouts + if ( p->fFanout && !Ivy_ObjIsBuf(pObjNew) && pObjOld->Level != pObjNew->Level ) + { + assert( Ivy_ObjIsNode(pObjOld) ); + pObjOld->Level = pObjNew->Level; + Ivy_ObjUpdateLevel_rec( p, pObjOld ); + } +//p->time1 += clock() - clk; + // if the new node's required time has changed, recursively update required time of the fanins +//clk = clock(); + if ( p->vRequired ) + { + int ReqNew = Vec_IntEntry(p->vRequired, pObjOld->Id); + if ( ReqNew < Vec_IntEntry(p->vRequired, pObjNew->Id) ) + { + Vec_IntWriteEntry( p->vRequired, pObjNew->Id, ReqNew ); + Ivy_ObjUpdateLevelR_rec( p, pObjNew, ReqNew ); + } + } +//p->time2 += clock() - clk; + } + // delete the old object + if ( fDeleteOld ) + Ivy_ObjDelete_rec( p, pObjOld, fFreeTop ); + // make sure object is not pointing to itself + assert( Ivy_ObjFanin0(pObjNew) == NULL || pObjOld != Ivy_ObjFanin0(pObjNew) ); + assert( Ivy_ObjFanin1(pObjNew) == NULL || pObjOld != Ivy_ObjFanin1(pObjNew) ); + // make sure the old node has no fanin fanout pointers + if ( p->fFanout ) + { + assert( pObjOld->pFanout != NULL ); + assert( pObjNew->pFanout == NULL ); + pObjNew->pFanout = pObjOld->pFanout; + } + // transfer the old object + assert( Ivy_ObjRefs(pObjNew) == 0 ); + nRefsOld = pObjOld->nRefs; + Ivy_ObjOverwrite( pObjOld, pObjNew ); + pObjOld->nRefs = nRefsOld; + // patch the fanout of the fanins + if ( p->fFanout ) + { + Ivy_ObjPatchFanout( p, Ivy_ObjFanin0(pObjOld), pObjNew, pObjOld ); + if ( Ivy_ObjFanin1(pObjOld) ) + Ivy_ObjPatchFanout( p, Ivy_ObjFanin1(pObjOld), pObjNew, pObjOld ); + } + // update the hash table + Ivy_TableUpdate( p, pObjNew, pObjOld->Id ); + // recycle the object that was taken over by pObjOld + Vec_PtrWriteEntry( p->vObjs, pObjNew->Id, NULL ); + Ivy_ManRecycleMemory( p, pObjNew ); + // if the new node is the buffer propagate it + if ( p->fFanout && Ivy_ObjIsBuf(pObjOld) ) + Vec_PtrPush( p->vBufs, pObjOld ); +// Ivy_ManCheckFanouts( p ); +// printf( "\n" ); +/* + if ( p->pHaig ) + { + int x; + Ivy_ManShow( p, 0, NULL ); + Ivy_ManShow( p->pHaig, 1, NULL ); + x = 0; + } +*/ +// if ( Ivy_ManCheckFanoutNums(p) ) +// { +// int x = 0; +// } +} + +/**Function************************************************************* + + Synopsis [Fixes buffer fanins.] + + Description [This situation happens because NodeReplace is a lazy + procedure, which does not propagate the change to the fanouts but + instead records the change in the form of a buf/inv node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ) +{ + Ivy_Obj_t * pFanReal0, * pFanReal1, * pResult; + if ( Ivy_ObjIsPo(pNode) ) + { + if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ) + return; + pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); + Ivy_ObjPatchFanin0( p, pNode, pFanReal0 ); +// Ivy_ManCheckFanouts( p ); + return; + } + if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) && !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ) + return; + // get the real fanins + pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); + pFanReal1 = Ivy_ObjReal( Ivy_ObjChild1(pNode) ); + // get the new node + if ( Ivy_ObjIsNode(pNode) ) + pResult = Ivy_Oper( p, pFanReal0, pFanReal1, Ivy_ObjType(pNode) ); + else if ( Ivy_ObjIsLatch(pNode) ) + pResult = Ivy_Latch( p, pFanReal0, Ivy_ObjInit(pNode) ); + else + assert( 0 ); + +//printf( "===== Replacing %d by %d.\n", pNode->Id, pResult->Id ); +//Ivy_ObjPrintVerbose( p, pNode, 0 ); printf( "\n" ); +//Ivy_ObjPrintVerbose( p, pResult, 0 ); printf( "\n" ); + + // perform the replacement + Ivy_ObjReplace( p, pNode, pResult, 1, 0, fUpdateLevel ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyOper.c b/abc70930/src/aig/ivy/ivyOper.c new file mode 100644 index 00000000..8115ce4f --- /dev/null +++ b/abc70930/src/aig/ivy/ivyOper.c @@ -0,0 +1,293 @@ +/**CFile**************************************************************** + + FileName [ivyOper.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG operations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// procedure to detect an EXOR gate +static inline int Ivy_ObjIsExorType( Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Obj_t ** ppFan0, Ivy_Obj_t ** ppFan1 ) +{ + if ( !Ivy_IsComplement(p0) || !Ivy_IsComplement(p1) ) + return 0; + p0 = Ivy_Regular(p0); + p1 = Ivy_Regular(p1); + if ( !Ivy_ObjIsAnd(p0) || !Ivy_ObjIsAnd(p1) ) + return 0; + if ( Ivy_ObjFanin0(p0) != Ivy_ObjFanin0(p1) || Ivy_ObjFanin1(p0) != Ivy_ObjFanin1(p1) ) + return 0; + if ( Ivy_ObjFaninC0(p0) == Ivy_ObjFaninC0(p1) || Ivy_ObjFaninC1(p0) == Ivy_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Ivy_ObjChild0(p0); + *ppFan1 = Ivy_ObjChild1(p0); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Perform one operation.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ) +{ + if ( Type == IVY_AND ) + return Ivy_And( p, p0, p1 ); + if ( Type == IVY_EXOR ) + return Ivy_Exor( p, p0, p1 ); + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) +{ +// Ivy_Obj_t * pFan0, * pFan1; + // check trivial cases + if ( p0 == p1 ) + return p0; + if ( p0 == Ivy_Not(p1) ) + return Ivy_Not(p->pConst1); + if ( Ivy_Regular(p0) == p->pConst1 ) + return p0 == p->pConst1 ? p1 : Ivy_Not(p->pConst1); + if ( Ivy_Regular(p1) == p->pConst1 ) + return p1 == p->pConst1 ? p0 : Ivy_Not(p->pConst1); + // check if it can be an EXOR gate +// if ( Ivy_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) +// return Ivy_CanonExor( pFan0, pFan1 ); + return Ivy_CanonAnd( p, p0, p1 ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) +{ +/* + // check trivial cases + if ( p0 == p1 ) + return Ivy_Not(p->pConst1); + if ( p0 == Ivy_Not(p1) ) + return p->pConst1; + if ( Ivy_Regular(p0) == p->pConst1 ) + return Ivy_NotCond( p1, p0 == p->pConst1 ); + if ( Ivy_Regular(p1) == p->pConst1 ) + return Ivy_NotCond( p0, p1 == p->pConst1 ); + // check the table + return Ivy_CanonExor( p, p0, p1 ); +*/ + return Ivy_Or( p, Ivy_And(p, p0, Ivy_Not(p1)), Ivy_And(p, Ivy_Not(p0), p1) ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) +{ + return Ivy_Not( Ivy_And( p, Ivy_Not(p0), Ivy_Not(p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ) +{ + Ivy_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; + int Count0, Count1; + // consider trivial cases + if ( p0 == Ivy_Not(p1) ) + return Ivy_Exor( p, pC, p0 ); + // other cases can be added + // implement the first MUX (F = C * x1 + C' * x0) + pTempA1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, p1, IVY_AND, IVY_INIT_NONE) ); + pTempA2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), p0, IVY_AND, IVY_INIT_NONE) ); + if ( pTempA1 && pTempA2 ) + { + pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempA1), Ivy_Not(pTempA2), IVY_AND, IVY_INIT_NONE) ); + if ( pTemp ) return Ivy_Not(pTemp); + } + Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); + // implement the second MUX (F' = C * x1' + C' * x0') + pTempB1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, Ivy_Not(p1), IVY_AND, IVY_INIT_NONE) ); + pTempB2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), Ivy_Not(p0), IVY_AND, IVY_INIT_NONE) ); + if ( pTempB1 && pTempB2 ) + { + pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempB1), Ivy_Not(pTempB2), IVY_AND, IVY_INIT_NONE) ); + if ( pTemp ) return pTemp; + } + Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); + // compare and decide which one to implement + if ( Count0 >= Count1 ) + { + pTempA1 = pTempA1? pTempA1 : Ivy_And(p, pC, p1); + pTempA2 = pTempA2? pTempA2 : Ivy_And(p, Ivy_Not(pC), p0); + return Ivy_Or( p, pTempA1, pTempA2 ); + } + pTempB1 = pTempB1? pTempB1 : Ivy_And(p, pC, Ivy_Not(p1)); + pTempB2 = pTempB2? pTempB2 : Ivy_And(p, Ivy_Not(pC), Ivy_Not(p0)); + return Ivy_Not( Ivy_Or( p, pTempB1, pTempB2 ) ); + +// return Ivy_Or( Ivy_And(pC, p1), Ivy_And(Ivy_Not(pC), p0) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ) +{ + return Ivy_Or( p, Ivy_Or(p, Ivy_And(p, pA, pB), Ivy_And(p, pA, pC)), Ivy_And(p, pB, pC) ); +} + +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Ivy_Multi_rec( p, ppObjs, nObjs/2, Type ); + pObj2 = Ivy_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Ivy_Oper( p, pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + assert( Type == IVY_AND || Type == IVY_EXOR ); + assert( nArgs > 0 ); + return Ivy_Multi_rec( p, pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ) +{ + int i; + assert( vPairs->nSize > 0 ); + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Ivy_Not( Ivy_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) ); + vPairs->nSize = vPairs->nSize/2; + return Ivy_Not( Ivy_Multi_rec( p, (Ivy_Obj_t **)vPairs->pArray, vPairs->nSize, IVY_AND ) ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) +{ + return Ivy_CanonLatch( p, pObj, Init ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyResyn.c b/abc70930/src/aig/ivy/ivyResyn.c new file mode 100644 index 00000000..f42d7464 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyResyn.c @@ -0,0 +1,196 @@ +/**CFile**************************************************************** + + FileName [ivyResyn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG rewriting script.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyResyn.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs several passes of rewriting on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) +{ + int clk; + Ivy_Man_t * pTemp; + +if ( fVerbose ) { printf( "Original:\n" ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pMan, fUpdateLevel ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); +clk = clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Performs several passes of rewriting on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) +{ + int clk; + Ivy_Man_t * pTemp; + +if ( fVerbose ) { printf( "Original:\n" ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pMan, fUpdateLevel ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); +clk = clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); +clk = clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); +clk = clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Performs several passes of rewriting on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ) +{ + int clk; + Ivy_Man_t * pTemp; + +if ( fVerbose ) { printf( "Original:\n" ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + Ivy_ManRewritePre( pMan, 0, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, 0 ); +// pMan = Ivy_ManDup( pTemp = pMan ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +/* +clk = clock(); + Ivy_ManRewritePre( pMan, 0, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = clock(); + pMan = Ivy_ManBalance( pTemp = pMan, 0 ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { PRT( "Balance", clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); +*/ + return pMan; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyRwr.c b/abc70930/src/aig/ivy/ivyRwr.c new file mode 100644 index 00000000..3f8720ba --- /dev/null +++ b/abc70930/src/aig/ivy/ivyRwr.c @@ -0,0 +1,609 @@ +/**CFile**************************************************************** + + FileName [ivyRwt.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Rewriting based on precomputation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyRwt.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" +#include "deco.h" +#include "rwt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ); +static int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ); +static Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, + Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ); + +static int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); +static void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ) +{ + Rwt_Man_t * pManRwt; + Ivy_Obj_t * pNode; + int i, nNodes, nGain; + int clk, clkStart = clock(); + // start the rewriting manager + pManRwt = Rwt_ManStart( 0 ); + p->pData = pManRwt; + if ( pManRwt == NULL ) + return 0; + // create fanouts + if ( fUpdateLevel && p->fFanout == 0 ) + Ivy_ManStartFanout( p ); + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Ivy_ManRequiredLevels( p ); + // set the number of levels +// p->nLevelMax = Ivy_ManLevels( p ); + // resynthesize each node once + nNodes = Ivy_ManObjIdMax(p); + Ivy_ManForEachNode( p, pNode, i ) + { + // fix the fanin buffer problem + Ivy_NodeFixBufferFanins( p, pNode, 1 ); + if ( Ivy_ObjIsBuf(pNode) ) + continue; + // stop if all nodes have been tried once + if ( i > nNodes ) + break; + // for each cut, try to resynthesize it + nGain = Ivy_NodeRewrite( p, pManRwt, pNode, fUpdateLevel, fUseZeroCost ); + if ( nGain > 0 || nGain == 0 && fUseZeroCost ) + { + Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt); + int fCompl = Rwt_ManReadCompl(pManRwt); +/* + { + Ivy_Obj_t * pObj; + int i; + printf( "USING: (" ); + Vec_PtrForEachEntry( Rwt_ManReadLeaves(pManRwt), pObj, i ) + printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pObj)) ); + printf( ") Gain = %d.\n", nGain ); + } + if ( nGain > 0 ) + { // print stats on the MFFC + extern void Ivy_NodeMffsConeSuppPrint( Ivy_Obj_t * pNode ); + printf( "Node %6d : Gain = %4d ", pNode->Id, nGain ); + Ivy_NodeMffsConeSuppPrint( pNode ); + } +*/ + // complement the FF if needed +clk = clock(); + if ( fCompl ) Dec_GraphComplement( pGraph ); + Ivy_GraphUpdateNetwork( p, pNode, pGraph, fUpdateLevel, nGain ); + if ( fCompl ) Dec_GraphComplement( pGraph ); +Rwt_ManAddTimeUpdate( pManRwt, clock() - clk ); + } + } +Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart ); + // print stats + if ( fVerbose ) + Rwt_ManPrintStats( pManRwt ); + // delete the managers + Rwt_ManStop( pManRwt ); + p->pData = NULL; + // fix the levels + if ( fUpdateLevel ) + Vec_IntFree( p->vRequired ), p->vRequired = NULL; + else + Ivy_ManResetLevels( p ); + // check + if ( i = Ivy_ManCleanup(p) ) + printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManRewritePre(): The check has failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs rewriting for one node.] + + Description [This procedure considers all the cuts computed for the node + and tries to rewrite each of them using the "forest" of different AIG + structures precomputed and stored in the RWR manager. + Determines the best rewriting and computes the gain in the number of AIG + nodes in the final network. In the end, p->vFanins contains information + about the best cut that can be used for rewriting, while p->pGraph gives + the decomposition dag (represented using decomposition graph data structure). + Returns gain in the number of nodes or -1 if node cannot be rewritten.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ) +{ + int fVeryVerbose = 0; + Dec_Graph_t * pGraph; + Ivy_Store_t * pStore; + Ivy_Cut_t * pCut; + Ivy_Obj_t * pFanin; + unsigned uPhase, uTruthBest, uTruth; + char * pPerm; + int Required, nNodesSaved, nNodesSaveCur; + int i, c, GainCur, GainBest = -1; + int clk, clk2; + + p->nNodesConsidered++; + // get the required times + Required = fUpdateLevel? Vec_IntEntry( pMan->vRequired, pNode->Id ) : 1000000; + // get the node's cuts +clk = clock(); + pStore = Ivy_NodeFindCutsAll( pMan, pNode, 5 ); +p->timeCut += clock() - clk; + + // go through the cuts +clk = clock(); + for ( c = 1; c < pStore->nCuts; c++ ) + { + pCut = pStore->pCuts + c; + // consider only 4-input cuts + if ( pCut->nSize != 4 ) + continue; + // skip the cuts with buffers + for ( i = 0; i < (int)pCut->nSize; i++ ) + if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, pCut->pArray[i]) ) ) + break; + if ( i != pCut->nSize ) + { + p->nCutsBad++; + continue; + } + p->nCutsGood++; + // get the fanin permutation +clk2 = clock(); + uTruth = 0xFFFF & Ivy_NodeGetTruth( pNode, pCut->pArray, pCut->nSize ); // truth table +p->timeTruth += clock() - clk2; + pPerm = p->pPerms4[ p->pPerms[uTruth] ]; + uPhase = p->pPhases[uTruth]; + // collect fanins with the corresponding permutation/phase + Vec_PtrClear( p->vFaninsCur ); + Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); + for ( i = 0; i < (int)pCut->nSize; i++ ) + { + pFanin = Ivy_ManObj( pMan, pCut->pArray[pPerm[i]] ); + assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) ); + pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); + Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); + } +clk2 = clock(); +/* + printf( "Considering: (" ); + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pFanin)) ); + printf( ")\n" ); +*/ + // mark the fanin boundary + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); + // label MFFC with current ID + Ivy_ManIncrementTravId( pMan ); + nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); + // unmark the fanin boundary + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); +p->timeMffc += clock() - clk2; + + // evaluate the cut +clk2 = clock(); + pGraph = Rwt_CutEvaluate( pMan, p, pNode, p->vFaninsCur, nNodesSaved, Required, &GainCur, uTruth ); +p->timeEval += clock() - clk2; + + // check if the cut is better than the current best one + if ( pGraph != NULL && GainBest < GainCur ) + { + // save this form + nNodesSaveCur = nNodesSaved; + GainBest = GainCur; + p->pGraph = pGraph; + p->fCompl = ((uPhase & (1<<4)) > 0); + uTruthBest = uTruth; + // collect fanins in the + Vec_PtrClear( p->vFanins ); + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Vec_PtrPush( p->vFanins, pFanin ); + } + } +p->timeRes += clock() - clk; + + if ( GainBest == -1 ) + return -1; + +// printf( "%d", nNodesSaveCur - GainBest ); +/* + if ( GainBest > 0 ) + { + if ( Rwt_CutIsintean( pNode, p->vFanins ) ) + printf( "b" ); + else + { + printf( "Node %d : ", pNode->Id ); + Vec_PtrForEachEntry( p->vFanins, pFanin, i ) + printf( "%d ", Ivy_Regular(pFanin)->Id ); + printf( "a" ); + } + } +*/ +/* + if ( GainBest > 0 ) + if ( p->fCompl ) + printf( "c" ); + else + printf( "." ); +*/ + + // copy the leaves + Vec_PtrForEachEntry( p->vFanins, pFanin, i ) + Dec_GraphNode(p->pGraph, i)->pFunc = pFanin; + + p->nScores[p->pMap[uTruthBest]]++; + p->nNodesGained += GainBest; + if ( fUseZeroCost || GainBest > 0 ) + p->nNodesRewritten++; + + // report the progress + if ( fVeryVerbose && GainBest > 0 ) + { + printf( "Node %6d : ", Ivy_ObjId(pNode) ); + printf( "Fanins = %d. ", p->vFanins->nSize ); + printf( "Save = %d. ", nNodesSaveCur ); + printf( "Add = %d. ", nNodesSaveCur-GainBest ); + printf( "GAIN = %d. ", GainBest ); + printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); + printf( "Class = %d. ", p->pMap[uTruthBest] ); + printf( "\n" ); + } + return GainBest; +} + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_NodeGetTruth_rec( Ivy_Obj_t * pObj, int * pNums, int nNums ) +{ + static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + unsigned uTruth0, uTruth1; + int i; + for ( i = 0; i < nNums; i++ ) + if ( pObj->Id == pNums[i] ) + return uMasks[i]; + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + uTruth0 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin0(pObj), pNums, nNums ); + if ( Ivy_ObjFaninC0(pObj) ) + uTruth0 = ~uTruth0; + if ( Ivy_ObjIsBuf(pObj) ) + return uTruth0; + uTruth1 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin1(pObj), pNums, nNums ); + if ( Ivy_ObjFaninC1(pObj) ) + uTruth1 = ~uTruth1; + return uTruth0 & uTruth1; +} + + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ) +{ + assert( nNums < 6 ); + return Ivy_NodeGetTruth_rec( pObj, pNums, nNums ); +} + +/**Function************************************************************* + + Synopsis [Evaluates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ) +{ + Vec_Ptr_t * vSubgraphs; + Dec_Graph_t * pGraphBest, * pGraphCur; + Rwt_Node_t * pNode, * pFanin; + int nNodesAdded, GainBest, i, k; + // find the matching class of subgraphs + vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); + p->nSubgraphs += vSubgraphs->nSize; + // determine the best subgraph + GainBest = -1; + Vec_PtrForEachEntry( vSubgraphs, pNode, i ) + { + // get the current graph + pGraphCur = (Dec_Graph_t *)pNode->pNext; + // copy the leaves + Vec_PtrForEachEntry( vFaninsCur, pFanin, k ) + Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; + // detect how many unlabeled nodes will be reused + nNodesAdded = Ivy_GraphToNetworkCount( pMan, pRoot, pGraphCur, nNodesSaved, LevelMax ); + if ( nNodesAdded == -1 ) + continue; + assert( nNodesSaved >= nNodesAdded ); + // count the gain at this node + if ( GainBest < nNodesSaved - nNodesAdded ) + { + GainBest = nNodesSaved - nNodesAdded; + pGraphBest = pGraphCur; + } + } + if ( GainBest == -1 ) + return NULL; + *pGainBest = GainBest; + return pGraphBest; +} + + +/**Function************************************************************* + + Synopsis [Counts the number of new nodes added when using this graph.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure. + Returns -1 if the number of nodes and levels exceeded the given limit or + the number of levels exceeded the maximum allowed level.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ) +{ + Dec_Node_t * pNode, * pNode0, * pNode1; + Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; + int i, Counter, LevelNew, LevelOld; + // check for constant function or a literal + if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) + return 0; + // set the levels of the leaves + Dec_GraphForEachLeaf( pGraph, pNode, i ) + pNode->Level = Ivy_Regular(pNode->pFunc)->Level; + // compute the AIG size after adding the internal nodes + Counter = 0; + Dec_GraphForEachNode( pGraph, pNode, i ) + { + // get the children of this node + pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); + pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); + // get the AIG nodes corresponding to the children + pAnd0 = pNode0->pFunc; + pAnd1 = pNode1->pFunc; + if ( pAnd0 && pAnd1 ) + { + // if they are both present, find the resulting node + pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); + pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); + // return -1 if the node is the same as the original root + if ( Ivy_Regular(pAnd) == pRoot ) + return -1; + } + else + pAnd = NULL; + // count the number of added nodes + if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) + { + if ( ++Counter > NodeMax ) + return -1; + } + // count the number of new levels + LevelNew = 1 + RWT_MAX( pNode0->Level, pNode1->Level ); + if ( pAnd ) + { + if ( Ivy_Regular(pAnd) == p->pConst1 ) + LevelNew = 0; + else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd0) ) + LevelNew = (int)Ivy_Regular(pAnd0)->Level; + else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd1) ) + LevelNew = (int)Ivy_Regular(pAnd1)->Level; + LevelOld = (int)Ivy_Regular(pAnd)->Level; +// assert( LevelNew == LevelOld ); + } + if ( LevelNew > LevelMax ) + return -1; + pNode->pFunc = pAnd; + pNode->Level = LevelNew; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_GraphToNetwork( Ivy_Man_t * p, Dec_Graph_t * pGraph ) +{ + Ivy_Obj_t * pAnd0, * pAnd1; + Dec_Node_t * pNode; + int i; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Ivy_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); + } + // complement the result if necessary + return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Replaces MFFC of the node by the new factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) +{ + Ivy_Obj_t * pRootNew; + int nNodesNew, nNodesOld, Required; + Required = fUpdateLevel? Vec_IntEntry( p->vRequired, pRoot->Id ) : 1000000; + nNodesOld = Ivy_ManNodeNum(p); + // create the new structure of nodes + pRootNew = Ivy_GraphToNetwork( p, pGraph ); + assert( (int)Ivy_Regular(pRootNew)->Level <= Required ); +// if ( Ivy_Regular(pRootNew)->Level == Required ) +// printf( "Difference %d.\n", Ivy_Regular(pRootNew)->Level - Required ); + // remove the old nodes +// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); +/* + if ( Ivy_IsComplement(pRootNew) ) + printf( "c" ); + else + printf( "d" ); + if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) + printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); + printf( " " ); +*/ + Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 1 ); + // compare the gains + nNodesNew = Ivy_ManNodeNum(p); + assert( nGain <= nNodesOld - nNodesNew ); + // propagate the buffer + Ivy_ManPropagateBuffers( p, 1 ); +} + +/**Function************************************************************* + + Synopsis [Replaces MFFC of the node by the new factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphUpdateNetwork3( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) +{ + Ivy_Obj_t * pRootNew, * pFanin; + int nNodesNew, nNodesOld, i, nRefsOld; + nNodesOld = Ivy_ManNodeNum(p); + +//printf( "Before = %d. ", Ivy_ManNodeNum(p) ); + // mark the cut + Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) + Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); + // deref the old cone + nRefsOld = pRoot->nRefs; + pRoot->nRefs = 0; + Ivy_ObjDelete_rec( p, pRoot, 0 ); + pRoot->nRefs = nRefsOld; + // unmark the cut + Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) + Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); +//printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); + + // create the new structure of nodes + pRootNew = Ivy_GraphToNetwork( p, pGraph ); +//printf( "Create = %d. ", Ivy_ManNodeNum(p) ); + // remove the old nodes +// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); +/* + if ( Ivy_IsComplement(pRootNew) ) + printf( "c" ); + else + printf( "d" ); + if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) + printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); + printf( " " ); +*/ + Ivy_ObjReplace( p, pRoot, pRootNew, 0, 0, 1 ); +//printf( "Replace = %d. ", Ivy_ManNodeNum(p) ); + + // delete remaining dangling nodes + Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) + { + pFanin = Ivy_Regular(pFanin); + if ( !Ivy_ObjIsNone(pFanin) && Ivy_ObjRefs(pFanin) == 0 ) + Ivy_ObjDelete_rec( p, pFanin, 1 ); + } +//printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); +//printf( "\n" ); + + // compare the gains + nNodesNew = Ivy_ManNodeNum(p); + assert( nGain <= nNodesOld - nNodesNew ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyRwrAlg.c b/abc70930/src/aig/ivy/ivyRwrAlg.c new file mode 100644 index 00000000..fc48deb0 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyRwrAlg.c @@ -0,0 +1,408 @@ +/**CFile**************************************************************** + + FileName [ivyRwrAlg.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Algebraic AIG rewriting.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyRwrAlg.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ); +static Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ); +static int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Algebraic AIG rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ) +{ + Vec_Int_t * vRequired; + Vec_Ptr_t * vFront, * vLeaves, * vCone, * vSol; + Ivy_Obj_t * pObj, * pResult; + int i, RetValue, LevelR, nNodesOld; + int CountUsed, CountUndo; + vRequired = fUpdateLevel? Ivy_ManRequiredLevels( p ) : NULL; + vFront = Vec_PtrAlloc( 100 ); + vLeaves = Vec_PtrAlloc( 100 ); + vCone = Vec_PtrAlloc( 100 ); + vSol = Vec_PtrAlloc( 100 ); + // go through the nodes in the topological order + CountUsed = CountUndo = 0; + nNodesOld = Ivy_ManObjIdNext(p); + Ivy_ManForEachObj( p, pObj, i ) + { + assert( !Ivy_ObjIsBuf(pObj) ); + if ( i >= nNodesOld ) + break; + // skip no-nodes and MUX roots + if ( !Ivy_ObjIsNode(pObj) || Ivy_ObjIsExor(pObj) || Ivy_ObjIsMuxType(pObj) ) + continue; +// if ( pObj->Id > 297 ) // 296 --- 297 +// break; + if ( pObj->Id == 297 ) + { + int x = 0; + } + // get the largest algebraic cut + RetValue = Ivy_ManFindAlgCut( pObj, vFront, vLeaves, vCone ); + // the case of a trivial tree cut + if ( RetValue == 1 ) + continue; + // the case of constant 0 cone + if ( RetValue == -1 ) + { + Ivy_ObjReplace( pObj, Ivy_ManConst0(p), 1, 0, 1 ); + continue; + } + assert( Vec_PtrSize(vLeaves) > 2 ); + // get the required level for this node + LevelR = vRequired? Vec_IntEntry(vRequired, pObj->Id) : 1000000; + // create a new cone + pResult = Ivy_NodeRewriteAlg( pObj, vFront, vLeaves, vCone, vSol, LevelR, fUseZeroCost ); + if ( pResult == NULL || pResult == pObj ) + continue; + assert( Vec_PtrSize(vSol) == 1 || !Ivy_IsComplement(pResult) ); + if ( Ivy_ObjLevel(Ivy_Regular(pResult)) > LevelR && Ivy_ObjRefs(Ivy_Regular(pResult)) == 0 ) + Ivy_ObjDelete_rec(Ivy_Regular(pResult), 1), CountUndo++; + else + Ivy_ObjReplace( pObj, pResult, 1, 0, 1 ), CountUsed++; + } + printf( "Used = %d. Undo = %d.\n", CountUsed, CountUndo ); + Vec_PtrFree( vFront ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSol ); + if ( vRequired ) Vec_IntFree( vRequired ); + if ( i = Ivy_ManCleanup(p) ) + printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManRewriteAlg(): The check has failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Analizes one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ) +{ + int fVerbose = 0; + Ivy_Obj_t * pTemp; + int k, Counter, nMffc, RetValue; + + if ( fVerbose ) + { + if ( Ivy_ObjIsExor(pObj) ) + printf( "x " ); + else + printf( " " ); + } + +/* + printf( "%d ", Vec_PtrSize(vFront) ); + printf( "( " ); + Vec_PtrForEachEntry( vFront, pTemp, k ) + printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); + printf( ")\n" ); +*/ + // collect nodes in the cone + if ( Ivy_ObjIsExor(pObj) ) + Ivy_ManCollectCone( pObj, vFront, vCone ); + else + Ivy_ManCollectCone( pObj, vLeaves, vCone ); + + // deref nodes in the cone + Vec_PtrForEachEntry( vCone, pTemp, k ) + { + Ivy_ObjRefsDec( Ivy_ObjFanin0(pTemp) ); + Ivy_ObjRefsDec( Ivy_ObjFanin1(pTemp) ); + pTemp->fMarkB = 1; + } + + // count the MFFC size + Vec_PtrForEachEntry( vFront, pTemp, k ) + Ivy_Regular(pTemp)->fMarkA = 1; + nMffc = Ivy_NodeCountMffc( pObj ); + Vec_PtrForEachEntry( vFront, pTemp, k ) + Ivy_Regular(pTemp)->fMarkA = 0; + + if ( fVerbose ) + { + Counter = 0; + Vec_PtrForEachEntry( vCone, pTemp, k ) + Counter += (Ivy_ObjRefs(pTemp) > 0); + printf( "%5d : Leaves = %2d. Cone = %2d. ConeRef = %2d. Mffc = %d. Lev = %d. LevR = %d.\n", + pObj->Id, Vec_PtrSize(vFront), Vec_PtrSize(vCone), Counter-1, nMffc, Ivy_ObjLevel(pObj), LevelR ); + } +/* + printf( "Leaves:" ); + Vec_PtrForEachEntry( vLeaves, pTemp, k ) + printf( " %d%s", Ivy_Regular(pTemp)->Id, Ivy_IsComplement(pTemp)? "\'" : "" ); + printf( "\n" ); + printf( "Cone:\n" ); + Vec_PtrForEachEntry( vCone, pTemp, k ) + printf( " %5d = %d%s %d%s\n", pTemp->Id, + Ivy_ObjFaninId0(pTemp), Ivy_ObjFaninC0(pTemp)? "\'" : "", + Ivy_ObjFaninId1(pTemp), Ivy_ObjFaninC1(pTemp)? "\'" : "" ); +*/ + + RetValue = Ivy_MultiPlus( vLeaves, vCone, Ivy_ObjType(pObj), nMffc + fUseZeroCost, vSols ); + + // ref nodes in the cone + Vec_PtrForEachEntry( vCone, pTemp, k ) + { + Ivy_ObjRefsInc( Ivy_ObjFanin0(pTemp) ); + Ivy_ObjRefsInc( Ivy_ObjFanin1(pTemp) ); + pTemp->fMarkA = 0; + pTemp->fMarkB = 0; + } + + if ( !RetValue ) + return NULL; + + if ( Vec_PtrSize( vSols ) == 1 ) + return Vec_PtrEntry( vSols, 0 ); + return Ivy_NodeBalanceBuildSuper( vSols, Ivy_ObjType(pObj), 1 ); +} + +/**Function************************************************************* + + Synopsis [Comparison for node pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCountMffc_rec( Ivy_Obj_t * pNode ) +{ + if ( Ivy_ObjRefs(pNode) > 0 || Ivy_ObjIsCi(pNode) || pNode->fMarkA ) + return 0; + assert( pNode->fMarkB ); + pNode->fMarkA = 1; +// printf( "%d ", pNode->Id ); + if ( Ivy_ObjIsBuf(pNode) ) + return Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ); + return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Comparison for node pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ) +{ + assert( pNode->fMarkB ); + return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Comparison for node pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindAlgCutCompare( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) +{ + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Computing one algebraic cut.] + + Description [Returns 1 if the tree-leaves of this node where traversed + and found to have no external references (and have not been collected). + Returns 0 if the tree-leaves have external references and are collected.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindAlgCut_rec( Ivy_Obj_t * pObj, Ivy_Type_t Type, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) +{ + int RetValue0, RetValue1; + Ivy_Obj_t * pObjR = Ivy_Regular(pObj); + assert( !Ivy_ObjIsBuf(pObjR) ); + assert( Type != IVY_EXOR || !Ivy_IsComplement(pObj) ); + + // make sure the node is not visited twice in different polarities + if ( Ivy_IsComplement(pObj) ) + { // if complemented, mark B + if ( pObjR->fMarkA ) + return -1; + pObjR->fMarkB = 1; + } + else + { // if non-complicated, mark A + if ( pObjR->fMarkB ) + return -1; + pObjR->fMarkA = 1; + } + Vec_PtrPush( vCone, pObjR ); + + // if the node is the end of the tree, return + if ( Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Type ) + { + if ( Ivy_ObjRefs(pObjR) == 1 ) + return 1; + assert( Ivy_ObjRefs(pObjR) > 1 ); + Vec_PtrPush( vFront, pObj ); + return 0; + } + + // branch on the node + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + // what if buffer has more than one fanout??? + RetValue0 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild0(pObj) ), Type, vFront, vCone ); + RetValue1 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild1(pObj) ), Type, vFront, vCone ); + if ( RetValue0 == -1 || RetValue1 == -1 ) + return -1; + + // the case when both have no external references + if ( RetValue0 && RetValue1 ) + { + if ( Ivy_ObjRefs(pObj) == 1 ) + return 1; + assert( Ivy_ObjRefs(pObj) > 1 ); + Vec_PtrPush( vFront, pObj ); + return 0; + } + // the case when one of them has external references + if ( RetValue0 ) + Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild0(pObj) ) ); + if ( RetValue1 ) + Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild1(pObj) ) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Computing one algebraic cut.] + + Description [Algebraic cut stops when we hit (a) CI, (b) complemented edge, + (c) boundary of different gates. Returns 1 if this is a pure tree. + Returns -1 if the contant 0 is detected. Return 0 if the array can be used.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ) +{ + Ivy_Obj_t * pObj, * pPrev; + int RetValue, i; + assert( !Ivy_IsComplement(pRoot) ); + assert( Ivy_ObjIsNode(pRoot) ); + // clear the frontier and collect the nodes + Vec_PtrClear( vCone ); + Vec_PtrClear( vFront ); + Vec_PtrClear( vLeaves ); + RetValue = Ivy_ManFindAlgCut_rec( pRoot, Ivy_ObjType(pRoot), vFront, vCone ); + // clean the marks + Vec_PtrForEachEntry( vCone, pObj, i ) + pObj->fMarkA = pObj->fMarkB = 0; + // quit if the same node is found in both polarities + if ( RetValue == -1 ) + return -1; + // return if the node is the root of a tree + if ( RetValue == 1 ) + return 1; + // return if the cut is composed of two nodes + if ( Vec_PtrSize(vFront) <= 2 ) + return 1; + // sort the entries in increasing order + Vec_PtrSort( vFront, Ivy_ManFindAlgCutCompare ); + // remove duplicates from vFront and save the nodes in vLeaves + pPrev = Vec_PtrEntry(vFront, 0); + Vec_PtrPush( vLeaves, pPrev ); + Vec_PtrForEachEntryStart( vFront, pObj, i, 1 ) + { + // compare current entry and the previous entry + if ( pObj == pPrev ) + { + if ( Ivy_ObjIsExor(pRoot) ) // A <+> A = 0 + { + // vLeaves are no longer structural support of pRoot!!! + Vec_PtrPop(vLeaves); + pPrev = Vec_PtrSize(vLeaves) == 0 ? NULL : Vec_PtrEntryLast(vLeaves); + } + continue; + } + if ( pObj == Ivy_Not(pPrev) ) + { + assert( Ivy_ObjIsAnd(pRoot) ); + return -1; + } + pPrev = pObj; + Vec_PtrPush( vLeaves, pObj ); + } + if ( Vec_PtrSize(vLeaves) == 0 ) + return -1; + if ( Vec_PtrSize(vLeaves) <= 2 ) + return 1; + return 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivySeq.c b/abc70930/src/aig/ivy/ivySeq.c new file mode 100644 index 00000000..0ee29fee --- /dev/null +++ b/abc70930/src/aig/ivy/ivySeq.c @@ -0,0 +1,1134 @@ +/**CFile**************************************************************** + + FileName [ivySeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivySeq.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" +#include "deco.h" +#include "rwt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ); +static void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ); +static unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ); +static Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ); +static int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ); +static Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ); +static void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ); +static Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); + +static inline int Ivy_CutHashValue( int NodeId ) { return 1 << (NodeId % 31); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//int nMoves; +//int nMovesS; +//int nClauses; +//int timeInv; + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ) +{ + Rwt_Man_t * pManRwt; + Ivy_Obj_t * pNode; + int i, nNodes, nGain; + int clk, clkStart = clock(); + + // set the DC latch values + Ivy_ManForEachLatch( p, pNode, i ) + pNode->Init = IVY_INIT_DC; + // start the rewriting manager + pManRwt = Rwt_ManStart( 0 ); + p->pData = pManRwt; + if ( pManRwt == NULL ) + return 0; + // create fanouts + if ( p->fFanout == 0 ) + Ivy_ManStartFanout( p ); + // resynthesize each node once + nNodes = Ivy_ManObjIdMax(p); + Ivy_ManForEachNode( p, pNode, i ) + { + assert( !Ivy_ObjIsBuf(pNode) ); + assert( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ); + assert( !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ); + // fix the fanin buffer problem +// Ivy_NodeFixBufferFanins( p, pNode ); +// if ( Ivy_ObjIsBuf(pNode) ) +// continue; + // stop if all nodes have been tried once + if ( i > nNodes ) + break; + // for each cut, try to resynthesize it + nGain = Ivy_NodeRewriteSeq( p, pManRwt, pNode, fUseZeroCost ); + if ( nGain > 0 || nGain == 0 && fUseZeroCost ) + { + Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt); + int fCompl = Rwt_ManReadCompl(pManRwt); + // complement the FF if needed +clk = clock(); + if ( fCompl ) Dec_GraphComplement( pGraph ); + Ivy_GraphUpdateNetworkSeq( p, pNode, pGraph, nGain ); + if ( fCompl ) Dec_GraphComplement( pGraph ); +Rwt_ManAddTimeUpdate( pManRwt, clock() - clk ); + } + } +Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart ); + // print stats + if ( fVerbose ) + Rwt_ManPrintStats( pManRwt ); + // delete the managers + Rwt_ManStop( pManRwt ); + p->pData = NULL; + // fix the levels + Ivy_ManResetLevels( p ); +// if ( Ivy_ManCheckFanoutNums(p) ) +// printf( "Ivy_ManRewritePre(): The check has failed.\n" ); + // check + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManRewritePre(): The check has failed.\n" ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Performs rewriting for one node.] + + Description [This procedure considers all the cuts computed for the node + and tries to rewrite each of them using the "forest" of different AIG + structures precomputed and stored in the RWR manager. + Determines the best rewriting and computes the gain in the number of AIG + nodes in the final network. In the end, p->vFanins contains information + about the best cut that can be used for rewriting, while p->pGraph gives + the decomposition dag (represented using decomposition graph data structure). + Returns gain in the number of nodes or -1 if node cannot be rewritten.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ) +{ + int fVeryVerbose = 0; + Dec_Graph_t * pGraph; + Ivy_Store_t * pStore; + Ivy_Cut_t * pCut; + Ivy_Obj_t * pFanin;//, * pFanout; + Vec_Ptr_t * vFanout; + unsigned uPhase, uTruthBest, uTruth;//, nNewClauses; + char * pPerm; + int nNodesSaved, nNodesSaveCur; + int i, c, GainCur, GainBest = -1; + int clk, clk2;//, clk3; + + p->nNodesConsidered++; + // get the node's cuts +clk = clock(); + pStore = Ivy_CutComputeForNode( pMan, pNode, 5 ); +p->timeCut += clock() - clk; + + // go through the cuts +clk = clock(); + vFanout = Vec_PtrAlloc( 100 ); + for ( c = 1; c < pStore->nCuts; c++ ) + { + pCut = pStore->pCuts + c; + // consider only 4-input cuts + if ( pCut->nSize != 4 ) + continue; + // skip the cuts with buffers + for ( i = 0; i < (int)pCut->nSize; i++ ) + if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, Ivy_LeafId(pCut->pArray[i])) ) ) + break; + if ( i != pCut->nSize ) + { + p->nCutsBad++; + continue; + } + p->nCutsGood++; + // get the fanin permutation +clk2 = clock(); + uTruth = 0xFFFF & Ivy_CutGetTruth( pMan, pNode, pCut->pArray, pCut->nSize ); // truth table +p->timeTruth += clock() - clk2; + pPerm = p->pPerms4[ p->pPerms[uTruth] ]; + uPhase = p->pPhases[uTruth]; + // collect fanins with the corresponding permutation/phase + Vec_PtrClear( p->vFaninsCur ); + Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); + for ( i = 0; i < (int)pCut->nSize; i++ ) + { + pFanin = Ivy_ManObj( pMan, Ivy_LeafId( pCut->pArray[pPerm[i]] ) ); + assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) || Ivy_ObjIsConst1(pFanin) ); + pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); + Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); + } +clk2 = clock(); + // mark the fanin boundary + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); + // label MFFC with current ID + Ivy_ManIncrementTravId( pMan ); + nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); + // label fanouts with the current ID +// Ivy_ObjForEachFanout( pMan, pNode, vFanout, pFanout, i ) +// Ivy_ObjSetTravIdCurrent( pMan, pFanout ); + // unmark the fanin boundary + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); +p->timeMffc += clock() - clk2; + + // evaluate the cut +clk2 = clock(); + pGraph = Rwt_CutEvaluateSeq( pMan, p, pNode, pCut, pPerm, p->vFaninsCur, nNodesSaved, &GainCur, uTruth ); +p->timeEval += clock() - clk2; + + + // check if the cut is better than the current best one + if ( pGraph != NULL && GainBest < GainCur ) + { + // save this form + nNodesSaveCur = nNodesSaved; + GainBest = GainCur; + p->pGraph = pGraph; + p->pCut = pCut; + p->pPerm = pPerm; + p->fCompl = ((uPhase & (1<<4)) > 0); + uTruthBest = uTruth; + // collect fanins in the + Vec_PtrClear( p->vFanins ); + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Vec_PtrPush( p->vFanins, pFanin ); + } + } + Vec_PtrFree( vFanout ); +p->timeRes += clock() - clk; + + if ( GainBest == -1 ) + return -1; +/* + { + Ivy_Cut_t * pCut = p->pCut; + printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); + printf( " }\n" ); + } +*/ + +//clk3 = clock(); +//nNewClauses = Ivy_CutTruthPrint( pMan, p->pCut, uTruth ); +//timeInv += clock() - clk; + +// nClauses += nNewClauses; +// nMoves++; +// if ( nNewClauses > 0 ) +// nMovesS++; + + // copy the leaves + Ivy_GraphPrepare( p->pGraph, p->pCut, p->vFanins, p->pPerm ); + + p->nScores[p->pMap[uTruthBest]]++; + p->nNodesGained += GainBest; + if ( fUseZeroCost || GainBest > 0 ) + p->nNodesRewritten++; + +/* + if ( GainBest > 0 ) + { + Ivy_Cut_t * pCut = p->pCut; + printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %5d(%2d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); + printf( " }\n" ); + } +*/ + + // report the progress + if ( fVeryVerbose && GainBest > 0 ) + { + printf( "Node %6d : ", Ivy_ObjId(pNode) ); + printf( "Fanins = %d. ", p->vFanins->nSize ); + printf( "Save = %d. ", nNodesSaveCur ); + printf( "Add = %d. ", nNodesSaveCur-GainBest ); + printf( "GAIN = %d. ", GainBest ); + printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); + printf( "Class = %d. ", p->pMap[uTruthBest] ); + printf( "\n" ); + } + return GainBest; +} + + +/**Function************************************************************* + + Synopsis [Evaluates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ) +{ + Vec_Ptr_t * vSubgraphs; + Dec_Graph_t * pGraphBest, * pGraphCur; + Rwt_Node_t * pNode; + int nNodesAdded, GainBest, i; + // find the matching class of subgraphs + vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); + p->nSubgraphs += vSubgraphs->nSize; + // determine the best subgraph + GainBest = -1; + Vec_PtrForEachEntry( vSubgraphs, pNode, i ) + { + // get the current graph + pGraphCur = (Dec_Graph_t *)pNode->pNext; + +// if ( pRoot->Id == 8648 ) +// Dec_GraphPrint( stdout, pGraphCur, NULL, NULL ); + // copy the leaves +// Vec_PtrForEachEntry( vFaninsCur, pFanin, k ) +// Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; + Ivy_GraphPrepare( pGraphCur, pCut, vFaninsCur, pPerm ); + + // detect how many unlabeled nodes will be reused + nNodesAdded = Ivy_GraphToNetworkSeqCountSeq( pMan, pRoot, pGraphCur, nNodesSaved ); + if ( nNodesAdded == -1 ) + continue; + assert( nNodesSaved >= nNodesAdded ); + // count the gain at this node + if ( GainBest < nNodesSaved - nNodesAdded ) + { + GainBest = nNodesSaved - nNodesAdded; + pGraphBest = pGraphCur; + } + } + if ( GainBest == -1 ) + return NULL; + *pGainBest = GainBest; + return pGraphBest; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ) +{ + Dec_Node_t * pNode, * pNode0, * pNode1; + int i; + assert( Dec_GraphLeaveNum(pGraph) == pCut->nSize ); + assert( Vec_PtrSize(vFanins) == pCut->nSize ); + // label the leaves with latch numbers + Dec_GraphForEachLeaf( pGraph, pNode, i ) + { + pNode->pFunc = Vec_PtrEntry( vFanins, i ); + pNode->nLat2 = Ivy_LeafLat( pCut->pArray[pPerm[i]] ); + } + // propagate latches through the nodes + Dec_GraphForEachNode( pGraph, pNode, i ) + { + // get the children of this node + pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); + pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); + // distribute the latches + pNode->nLat2 = IVY_MIN( pNode0->nLat2, pNode1->nLat2 ); + pNode->nLat0 = pNode0->nLat2 - pNode->nLat2; + pNode->nLat1 = pNode1->nLat2 - pNode->nLat2; + } +} + +/**Function************************************************************* + + Synopsis [Counts the number of new nodes added when using this graph.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure. + Returns -1 if the number of nodes and levels exceeded the given limit or + the number of levels exceeded the maximum allowed level.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ) +{ + Dec_Node_t * pNode, * pNode0, * pNode1; + Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; + int i, k, Counter, fCompl; + // check for constant function or a literal + if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) + return 0; + // compute the AIG size after adding the internal nodes + Counter = 0; + Dec_GraphForEachNode( pGraph, pNode, i ) + { + // get the children of this node + pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); + pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); + // get the AIG nodes corresponding to the children + pAnd0 = pNode0->pFunc; + pAnd1 = pNode1->pFunc; + // skip the latches + for ( k = 0; pAnd0 && k < (int)pNode->nLat0; k++ ) + { + fCompl = Ivy_IsComplement(pAnd0); + pAnd0 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd0), NULL, IVY_LATCH, IVY_INIT_DC) ); + if ( pAnd0 ) + pAnd0 = Ivy_NotCond( pAnd0, fCompl ); + } + for ( k = 0; pAnd1 && k < (int)pNode->nLat1; k++ ) + { + fCompl = Ivy_IsComplement(pAnd1); + pAnd1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd1), NULL, IVY_LATCH, IVY_INIT_DC) ); + if ( pAnd1 ) + pAnd1 = Ivy_NotCond( pAnd1, fCompl ); + } + // get the new node + if ( pAnd0 && pAnd1 ) + { + // if they are both present, find the resulting node + pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); + assert( !Ivy_ObjIsLatch(Ivy_Regular(pAnd0)) || !Ivy_ObjIsLatch(Ivy_Regular(pAnd1)) ); + if ( Ivy_Regular(pAnd0) == Ivy_Regular(pAnd1) || Ivy_ObjIsConst1(Ivy_Regular(pAnd0)) || Ivy_ObjIsConst1(Ivy_Regular(pAnd1)) ) + pAnd = Ivy_And( p, pAnd0, pAnd1 ); + else + pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); + // return -1 if the node is the same as the original root + if ( Ivy_Regular(pAnd) == pRoot ) + return -1; + } + else + pAnd = NULL; + // count the number of added nodes + if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) + { + if ( ++Counter > NodeMax ) + return -1; + } + pNode->pFunc = pAnd; + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ) +{ + Ivy_Obj_t * pAnd0, * pAnd1; + Dec_Node_t * pNode; + int i, k; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + { + // get the variable node + pNode = Dec_GraphVar(pGraph); + // add the remaining latches + for ( k = 0; k < (int)pNode->nLat2; k++ ) + pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC ); + return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); + } + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + // add the latches + for ( k = 0; k < (int)pNode->nLat0; k++ ) + pAnd0 = Ivy_Latch( p, pAnd0, IVY_INIT_DC ); + for ( k = 0; k < (int)pNode->nLat1; k++ ) + pAnd1 = Ivy_Latch( p, pAnd1, IVY_INIT_DC ); + // create the node + pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); + } + // add the remaining latches + for ( k = 0; k < (int)pNode->nLat2; k++ ) + pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC ); + // complement the result if necessary + return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Replaces MFFC of the node by the new factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ) +{ + Ivy_Obj_t * pRootNew; + int nNodesNew, nNodesOld; + nNodesOld = Ivy_ManNodeNum(p); + // create the new structure of nodes + pRootNew = Ivy_GraphToNetworkSeq( p, pGraph ); + Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 0 ); + // compare the gains + nNodesNew = Ivy_ManNodeNum(p); + assert( nGain <= nNodesOld - nNodesNew ); + // propagate the buffer + Ivy_ManPropagateBuffers( p, 0 ); +} + + + + + + + + + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_CutGetTruth_rec( Ivy_Man_t * p, int Leaf, int * pNums, int nNums ) +{ + static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + unsigned uTruth0, uTruth1; + Ivy_Obj_t * pObj; + int i; + for ( i = 0; i < nNums; i++ ) + if ( Leaf == pNums[i] ) + return uMasks[i]; + pObj = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); + if ( Ivy_ObjIsLatch(pObj) ) + { + assert( !Ivy_ObjFaninC0(pObj) ); + Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) + 1 ); + return Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); + } + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) ); + uTruth0 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); + if ( Ivy_ObjFaninC0(pObj) ) + uTruth0 = ~uTruth0; + if ( Ivy_ObjIsBuf(pObj) ) + return uTruth0; + Leaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pObj), Ivy_LeafLat(Leaf) ); + uTruth1 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); + if ( Ivy_ObjFaninC1(pObj) ) + uTruth1 = ~uTruth1; + return uTruth0 & uTruth1; +} + + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ) +{ + assert( Ivy_ObjIsNode(pObj) ); + assert( nNums < 6 ); + return Ivy_CutGetTruth_rec( p, Ivy_LeafCreate(pObj->Id, 0), pNums, nNums ); +} + + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) +{ + int i; + if ( pCut->nSize < pCut->nSizeMax ) + return 1; + for ( i = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutDeriveNew2( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + unsigned uHash = 0; + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 >= 0 ) + { + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + IdNew0 = -1; + } + } + if ( IdNew1 >= 0 ) + { + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + IdNew1 = -1; + } + } + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + uHash |= Ivy_CutHashValue( pCut->pArray[i] ); + } + if ( IdNew0 >= 0 ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + if ( IdNew1 >= 0 ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + pCutNew->nSize = k; + pCutNew->uHash = uHash; + assert( pCutNew->nSize <= pCut->nSizeMax ); + for ( i = 1; i < pCutNew->nSize; i++ ) + assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + unsigned uHash = 0; + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + IdNew0 = 0x7FFFFFFF; + } + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + IdNew1 = 0x7FFFFFFF; + } + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + uHash |= Ivy_CutHashValue( pCut->pArray[i] ); + } + if ( IdNew0 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + if ( IdNew1 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + pCutNew->nSize = k; + pCutNew->uHash = uHash; + assert( pCutNew->nSize <= pCut->nSizeMax ); +// for ( i = 1; i < pCutNew->nSize; i++ ) +// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Find the hash value of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) +{ + int i; + pCut->uHash = 0; + for ( i = 0; i < pCut->nSize; i++ ) + pCut->uHash |= (1 << (pCut->pArray[i] % 31)); + return pCut->uHash; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutDeriveNew3( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + pCutNew->pArray[ k++ ] = IdNew0; + IdNew0 = 0x7FFFFFFF; + } + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + pCutNew->pArray[ k++ ] = IdNew1; + IdNew1 = 0x7FFFFFFF; + } + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + } + if ( IdNew0 < 0x7FFFFFFF ) + pCutNew->pArray[ k++ ] = IdNew0; + if ( IdNew1 < 0x7FFFFFFF ) + pCutNew->pArray[ k++ ] = IdNew1; + pCutNew->nSize = k; + assert( pCutNew->nSize <= pCut->nSizeMax ); + Ivy_NodeCutHash( pCutNew ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) +{ + int i, k; + for ( i = 0; i < pDom->nSize; i++ ) + { + assert( i==0 || pDom->pArray[i-1] < pDom->pArray[i] ); + for ( k = 0; k < pCut->nSize; k++ ) + if ( pDom->pArray[i] == pCut->pArray[k] ) + break; + if ( k == pCut->nSize ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Check if the cut exists.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_CutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) +{ + Ivy_Cut_t * pCut; + int i, k; + assert( pCutNew->uHash ); + // try to find the cut + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + if ( pCut->nSize == pCutNew->nSize ) + { + if ( pCut->uHash == pCutNew->uHash ) + { + for ( k = 0; k < pCutNew->nSize; k++ ) + if ( pCut->pArray[k] != pCutNew->pArray[k] ) + break; + if ( k == pCutNew->nSize ) + return 1; + } + continue; + } + if ( pCut->nSize < pCutNew->nSize ) + { + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) + return 1; + continue; + } + // check potential containment of other cut + + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) + { + // remove the current cut + pCut->nSize = 0; + } + } + assert( pCutStore->nCuts < pCutStore->nCutsMax ); + // add the cut + pCut = pCutStore->pCuts + pCutStore->nCuts++; + *pCut = *pCutNew; + return 0; +} + +/**Function************************************************************* + + Synopsis [Compresses the cut representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutCompactAll( Ivy_Store_t * pCutStore ) +{ + Ivy_Cut_t * pCut; + int i, k; + pCutStore->nCutsM = 0; + for ( i = k = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + if ( pCut->nSize < pCut->nSizeMax ) + pCutStore->nCutsM++; + pCutStore->pCuts[k++] = *pCut; + } + pCutStore->nCuts = k; +} + +/**Function************************************************************* + + Synopsis [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutPrintForNode( Ivy_Cut_t * pCut ) +{ + int i; + assert( pCut->nSize > 0 ); + printf( "%d : {", pCut->nSize ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %d", pCut->pArray[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutPrintForNodes( Ivy_Store_t * pCutStore ) +{ + int i; + printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); + for ( i = 0; i < pCutStore->nCuts; i++ ) + Ivy_CutPrintForNode( pCutStore->pCuts + i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutReadLeaf( Ivy_Obj_t * pFanin ) +{ + int nLats, iLeaf; + assert( !Ivy_IsComplement(pFanin) ); + if ( !Ivy_ObjIsLatch(pFanin) ) + return Ivy_LeafCreate( pFanin->Id, 0 ); + iLeaf = Ivy_CutReadLeaf(Ivy_ObjFanin0(pFanin)); + nLats = Ivy_LeafLat(iLeaf); + assert( nLats < IVY_LEAF_MASK ); + return 1 + iLeaf; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) +{ + static Ivy_Store_t CutStore, * pCutStore = &CutStore; + Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; + Ivy_Man_t * pMan = p; + Ivy_Obj_t * pLeaf; + int i, k, Temp, nLats, iLeaf0, iLeaf1; + + assert( nLeaves <= IVY_CUT_INPUT ); + + // start the structure + pCutStore->nCuts = 0; + pCutStore->nCutsMax = IVY_CUT_LIMIT; + // start the trivial cut + pCutNew->uHash = 0; + pCutNew->nSize = 1; + pCutNew->nSizeMax = nLeaves; + pCutNew->pArray[0] = Ivy_LeafCreate( pObj->Id, 0 ); + pCutNew->uHash = Ivy_CutHashValue( pCutNew->pArray[0] ); + // add the trivial cut + pCutStore->pCuts[pCutStore->nCuts++] = *pCutNew; + assert( pCutStore->nCuts == 1 ); + + // explore the cuts + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + // expand this cut + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + for ( k = 0; k < pCut->nSize; k++ ) + { + pLeaf = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[k]) ); + if ( Ivy_ObjIsCi(pLeaf) || Ivy_ObjIsConst1(pLeaf) ) + continue; + assert( Ivy_ObjIsNode(pLeaf) ); + nLats = Ivy_LeafLat(pCut->pArray[k]); + + // get the fanins fanins + iLeaf0 = Ivy_CutReadLeaf( Ivy_ObjFanin0(pLeaf) ); + iLeaf1 = Ivy_CutReadLeaf( Ivy_ObjFanin1(pLeaf) ); + assert( nLats + Ivy_LeafLat(iLeaf0) < IVY_LEAF_MASK && nLats + Ivy_LeafLat(iLeaf1) < IVY_LEAF_MASK ); + iLeaf0 = nLats + iLeaf0; + iLeaf1 = nLats + iLeaf1; + if ( !Ivy_CutPrescreen( pCut, iLeaf0, iLeaf1 ) ) + continue; + // the given cut exist + if ( iLeaf0 > iLeaf1 ) + Temp = iLeaf0, iLeaf0 = iLeaf1, iLeaf1 = Temp; + // create the new cut + if ( !Ivy_CutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ) ) + continue; + // add the cut + Ivy_CutFindOrAddFilter( pCutStore, pCutNew ); + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + pCutStore->fSatur = 1; + else + pCutStore->fSatur = 0; +// printf( "%d ", pCutStore->nCuts ); + Ivy_CutCompactAll( pCutStore ); +// printf( "%d \n", pCutStore->nCuts ); +// Ivy_CutPrintForNodes( pCutStore ); + return pCutStore; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs ) +{ + Ivy_Store_t * pStore; + Ivy_Obj_t * pObj; + int i, nCutsTotal, nCutsTotalM, nNodeTotal, nNodeOver; + int clk = clock(); + if ( nInputs > IVY_CUT_INPUT ) + { + printf( "Cannot compute cuts for more than %d inputs.\n", IVY_CUT_INPUT ); + return; + } + nNodeTotal = nNodeOver = 0; + nCutsTotal = nCutsTotalM = -Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + pStore = Ivy_CutComputeForNode( p, pObj, nInputs ); + nCutsTotal += pStore->nCuts; + nCutsTotalM += pStore->nCutsM; + nNodeOver += pStore->fSatur; + nNodeTotal++; + } + printf( "All = %6d. Minus = %6d. Triv = %6d. Node = %6d. Satur = %6d. ", + nCutsTotal, nCutsTotalM, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); + PRT( "Time", clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyShow.c b/abc70930/src/aig/ivy/ivyShow.c new file mode 100644 index 00000000..cd726e43 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyShow.c @@ -0,0 +1,338 @@ +/**CFile**************************************************************** + + FileName [ivyShow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Visualization of HAIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) +{ + extern void Abc_ShowFile( char * FileNameDot ); + static Counter = 0; + char FileNameDot[200]; + FILE * pFile; + // create the file name +// Ivy_ShowGetFileName( pMan->pName, FileNameDot ); + sprintf( FileNameDot, "temp%02d.dot", Counter++ ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + // generate the file + Ivy_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); + // visualize the file + Abc_ShowFile( FileNameDot ); +} + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ) +{ + FILE * pFile; + Ivy_Obj_t * pNode, * pTemp, * pPrev; + int LevelMax, Level, i; + + if ( Ivy_ManNodeNum(pMan) > 200 ) + { + fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" ); + return; + } + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // mark the nodes + if ( vBold ) + Vec_PtrForEachEntry( vBold, pNode, i ) + pNode->fMarkB = 1; + + // compute levels + LevelMax = 1 + Ivy_ManSetLevels( pMan, fHaig ); + + // write the DOT header + fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph AIG {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != 0 ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "AIG structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); + fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Ivy_ManNodeNum(pMan), LevelMax ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the COs + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the CO nodes + Ivy_ManForEachCo( pMan, pNode, i ) + { + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":""), + Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); + fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"invtriangle") ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate nodes of each rank + for ( Level = LevelMax - 1; Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Ivy_ManForEachObj( pMan, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + else + fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, + Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); + fprintf( pFile, ", shape = ellipse" ); + if ( vBold && pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the CI nodes + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", 0 ); + // generate constant node + if ( Ivy_ObjRefs(Ivy_ManConst1(pMan)) > 0 ) + { + pNode = Ivy_ManConst1(pMan); + // check if the costant node is present + fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); + fprintf( pFile, ", shape = ellipse" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + // generate the CI nodes + Ivy_ManForEachCi( pMan, pNode, i ) + { + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":""), + Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); + fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"triangle") ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Ivy_ManForEachCo( pMan, pNode, i ) + fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); + + // generate edges + Ivy_ManForEachObj( pMan, pNode, i ) + { + if ( !Ivy_ObjIsNode(pNode) && !Ivy_ObjIsCo(pNode) && !Ivy_ObjIsBuf(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d%s", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d%s", Ivy_ObjFaninId0(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin0(pNode))? "_out":"") ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Ivy_ObjFaninC0(pNode)? "dotted" : "bold" ); +// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + if ( !Ivy_ObjIsNode(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d%s", Ivy_ObjFaninId1(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin1(pNode))? "_out":"") ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Ivy_ObjFaninC1(pNode)? "dotted" : "bold" ); +// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + // generate the edges between the equivalent nodes + if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 ) + { + pPrev = pNode; + for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pTemp->Id ); + fprintf( pFile, " [style = %s]", Ivy_IsComplement(pTemp->pEquiv)? "dotted" : "bold" ); + fprintf( pFile, ";\n" ); + pPrev = pTemp; + } + // connect the last node with the first + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " [style = %s]", Ivy_IsComplement(pPrev->pEquiv)? "dotted" : "bold" ); + fprintf( pFile, ";\n" ); + } + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark nodes + if ( vBold ) + Vec_PtrForEachEntry( vBold, pNode, i ) + pNode->fMarkB = 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyTable.c b/abc70930/src/aig/ivy/ivyTable.c new file mode 100644 index 00000000..2ac0ae49 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyTable.c @@ -0,0 +1,301 @@ +/**CFile**************************************************************** + + FileName [ivyTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Structural hashing table.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006. ] + + Revision [$Id: ivyTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// hashing the node +static unsigned Ivy_Hash( Ivy_Obj_t * pObj, int TableSize ) +{ + unsigned Key = Ivy_ObjIsExor(pObj) * 1699; + Key ^= Ivy_ObjFaninId0(pObj) * 7937; + Key ^= Ivy_ObjFaninId1(pObj) * 2971; + Key ^= Ivy_ObjFaninC0(pObj) * 911; + Key ^= Ivy_ObjFaninC1(pObj) * 353; + Key ^= Ivy_ObjInit(pObj) * 911; + return Key % TableSize; +} + +// returns the place where this node is stored (or should be stored) +static int * Ivy_TableFind( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + int i; + assert( Ivy_ObjIsHash(pObj) ); + for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) + if ( p->pTable[i] == pObj->Id ) + break; + return p->pTable + i; +} + +static void Ivy_TableResize( Ivy_Man_t * p ); +static unsigned int Cudd_PrimeAig( unsigned int p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if node with the given attributes is in the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pEntry; + int i; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return NULL; + assert( Ivy_ObjIsLatch(pObj) || Ivy_ObjFaninId0(pObj) > 0 ); + assert( Ivy_ObjFaninId1(pObj) == 0 || Ivy_ObjFaninId0(pObj) < Ivy_ObjFaninId1(pObj) ); + if ( Ivy_ObjFanin0(pObj)->nRefs == 0 || (Ivy_ObjChild1(pObj) && Ivy_ObjFanin1(pObj)->nRefs == 0) ) + return NULL; + for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) + { + pEntry = Ivy_ManObj( p, p->pTable[i] ); + if ( Ivy_ObjChild0(pEntry) == Ivy_ObjChild0(pObj) && + Ivy_ObjChild1(pEntry) == Ivy_ObjChild1(pObj) && + Ivy_ObjInit(pEntry) == Ivy_ObjInit(pObj) && + Ivy_ObjType(pEntry) == Ivy_ObjType(pObj) ) + return pEntry; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Adds the node to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + int * pPlace; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return; + if ( (pObj->Id & 63) == 0 ) + { + if ( p->nTableSize < 2 * Ivy_ManHashObjNum(p) ) + Ivy_TableResize( p ); + } + pPlace = Ivy_TableFind( p, pObj ); + assert( *pPlace == 0 ); + *pPlace = pObj->Id; +} + +/**Function************************************************************* + + Synopsis [Deletes the node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pEntry; + int i, * pPlace; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return; + pPlace = Ivy_TableFind( p, pObj ); + assert( *pPlace == pObj->Id ); // node should be in the table + *pPlace = 0; + // rehash the adjacent entries + i = pPlace - p->pTable; + for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize ) + { + pEntry = Ivy_ManObj( p, p->pTable[i] ); + p->pTable[i] = 0; + Ivy_TableInsert( p, pEntry ); + } +} + +/**Function************************************************************* + + Synopsis [Updates the table to point to the new node.] + + Description [If the old node (pObj) is in the table, updates the table + to point to an object with different ID (ObjIdNew). The table should + not contain an object with ObjIdNew (this is currently not checked).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ) +{ + int * pPlace; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return; + pPlace = Ivy_TableFind( p, pObj ); + assert( *pPlace == pObj->Id ); // node should be in the table + *pPlace = ObjIdNew; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TableCountEntries( Ivy_Man_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + Counter += (p->pTable[i] != 0); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [Typically this procedure should not be called.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableResize( Ivy_Man_t * p ) +{ + int * pTableOld, * pPlace; + int nTableSizeOld, Counter, nEntries, e, clk; +clk = clock(); + // save the old table + pTableOld = p->pTable; + nTableSizeOld = p->nTableSize; + // get the new table + p->nTableSize = Cudd_PrimeAig( 5 * Ivy_ManHashObjNum(p) ); + p->pTable = ALLOC( int, p->nTableSize ); + memset( p->pTable, 0, sizeof(int) * p->nTableSize ); + // rehash the entries from the old table + Counter = 0; + for ( e = 0; e < nTableSizeOld; e++ ) + { + if ( pTableOld[e] == 0 ) + continue; + Counter++; + // get the place where this entry goes in the table table + pPlace = Ivy_TableFind( p, Ivy_ManObj(p, pTableOld[e]) ); + assert( *pPlace == 0 ); // should not be in the table + *pPlace = pTableOld[e]; + } + nEntries = Ivy_ManHashObjNum(p); +// assert( Counter == nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); +// PRT( "Time", clock() - clk ); + // replace the table and the parameters + free( pTableOld ); +} + +/**Function******************************************************************** + + Synopsis [Profiles the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Ivy_TableProfile( Ivy_Man_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + { + if ( p->pTable[i] ) + Counter++; + else if ( Counter ) + { + printf( "%d ", Counter ); + Counter = 0; + } + } +} + +/**Function******************************************************************** + + Synopsis [Returns the next prime >= p.] + + Description [Copied from CUDD, for stand-aloneness.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +unsigned int Cudd_PrimeAig( unsigned int p) +{ + int i,pn; + + p--; + do { + p++; + if (p&1) { + pn = 1; + i = 3; + while ((unsigned) (i * i) <= p) { + if (p % i == 0) { + pn = 0; + break; + } + i += 2; + } + } else { + pn = 0; + } + } while (!pn); + return(p); + +} /* end of Cudd_Prime */ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivyUtil.c b/abc70930/src/aig/ivy/ivyUtil.c new file mode 100644 index 00000000..ab62a276 --- /dev/null +++ b/abc70930/src/aig/ivy/ivyUtil.c @@ -0,0 +1,818 @@ +/**CFile**************************************************************** + + FileName [ivyUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Various procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Increments the current traversal ID of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManIncrementTravId( Ivy_Man_t * p ) +{ + if ( p->nTravIds >= (1<<30)-1 - 1000 ) + Ivy_ManCleanTravId( p ); + p->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Sets the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCleanTravId( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + p->nTravIds = 1; + Ivy_ManForEachObj( p, pObj, i ) + pObj->TravId = 0; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vNodes ) +{ + if ( pNode->fMarkA ) + return; + pNode->fMarkA = 1; + assert( Ivy_ObjIsAnd(pNode) || Ivy_ObjIsExor(pNode) ); + Ivy_ManCollectCut_rec( p, Ivy_ObjFanin0(pNode), vNodes ); + Ivy_ManCollectCut_rec( p, Ivy_ObjFanin1(pNode), vNodes ); + Vec_IntPush( vNodes, pNode->Id ); +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [Does not modify the array of leaves. Uses array vTruth to store + temporary truth tables. The returned pointer should be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) +{ + int i, Leaf; + // collect and mark the leaves + Vec_IntClear( vNodes ); + Vec_IntForEachEntry( vLeaves, Leaf, i ) + { + Vec_IntPush( vNodes, Leaf ); + Ivy_ManObj(p, Leaf)->fMarkA = 1; + } + // collect and mark the nodes + Ivy_ManCollectCut_rec( p, pRoot, vNodes ); + // clean the nodes + Vec_IntForEachEntry( vNodes, Leaf, i ) + Ivy_ManObj(p, Leaf)->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ivy_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth ) +{ + return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCutTruthOne( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vTruth, int nWords ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + int i; + pTruth = Ivy_ObjGetTruthStore( pNode->TravId, vTruth ); + pTruth0 = Ivy_ObjGetTruthStore( Ivy_ObjFanin0(pNode)->TravId, vTruth ); + pTruth1 = Ivy_ObjGetTruthStore( Ivy_ObjFanin1(pNode)->TravId, vTruth ); + if ( Ivy_ObjIsExor(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] ^ pTruth1[i]; + else if ( !Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & pTruth1[i]; + else if ( !Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & ~pTruth1[i]; + else if ( Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & pTruth1[i]; + else // if ( Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [Does not modify the array of leaves. Uses array vTruth to store + temporary truth tables. The returned pointer should be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ) +{ + static unsigned uTruths[8][8] = { // elementary truth tables + { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, + { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, + { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, + { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, + { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, + { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, + { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, + { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } + }; + int i, Leaf; + // collect the cut + Ivy_ManCollectCut( p, pRoot, vLeaves, vNodes ); + // set the node numbers + Vec_IntForEachEntry( vNodes, Leaf, i ) + Ivy_ManObj(p, Leaf)->TravId = i; + // alloc enough memory + Vec_IntClear( vTruth ); + Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) ); + // set the elementary truth tables + Vec_IntForEachEntry( vLeaves, Leaf, i ) + memcpy( Ivy_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) ); + // compute truths for other nodes + Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) ) + Ivy_ManCutTruthOne( p, Ivy_ManObj(p, Leaf), vTruth, 8 ); + return Ivy_ObjGetTruthStore( pRoot->TravId, vTruth ); +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ) +{ + Vec_Int_t * vLatches; + Ivy_Obj_t * pObj; + int i; + vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); + Ivy_ManForEachLatch( p, pObj, i ) + Vec_IntPush( vLatches, pObj->Id ); + return vLatches; +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManLevels( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i, LevelMax = 0; + Ivy_ManForEachPo( p, pObj, i ) + LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManResetLevels_rec( Ivy_Obj_t * pObj ) +{ + if ( pObj->Level || Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) + return pObj->Level; + if ( Ivy_ObjIsBuf(pObj) ) + return pObj->Level = Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); + Ivy_ManResetLevels_rec( Ivy_ObjFanin1(pObj) ); + return pObj->Level = Ivy_ObjLevelNew( pObj ); +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManResetLevels( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + Ivy_ManForEachObj( p, pObj, i ) + pObj->Level = 0; + Ivy_ManForEachCo( p, pObj, i ) + Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [References/references the node and returns MFFC size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjRefDeref( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fReference, int fLabel ) +{ + Ivy_Obj_t * pNode0, * pNode1; + int Counter; + // label visited nodes + if ( fLabel ) + Ivy_ObjSetTravIdCurrent( p, pNode ); + // skip the CI + if ( Ivy_ObjIsPi(pNode) ) + return 0; + assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsBuf(pNode) || Ivy_ObjIsLatch(pNode) ); + // process the internal node + pNode0 = Ivy_ObjFanin0(pNode); + pNode1 = Ivy_ObjFanin1(pNode); + Counter = Ivy_ObjIsNode(pNode); + if ( fReference ) + { + if ( pNode0->nRefs++ == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); + if ( pNode1 && pNode1->nRefs++ == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); + } + else + { + assert( pNode0->nRefs > 0 ); + assert( pNode1 == NULL || pNode1->nRefs > 0 ); + if ( --pNode0->nRefs == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); + if ( pNode1 && --pNode1->nRefs == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Labels MFFC with the current label.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; + assert( !Ivy_IsComplement( pNode ) ); + assert( Ivy_ObjIsNode( pNode ) ); + nConeSize1 = Ivy_ObjRefDeref( p, pNode, 0, 1 ); // dereference + nConeSize2 = Ivy_ObjRefDeref( p, pNode, 1, 0 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [Recursively updates fanout levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanout; + Vec_Ptr_t * vFanouts; + int i, LevelNew; + assert( p->fFanout ); + assert( Ivy_ObjIsNode(pObj) ); + vFanouts = Vec_PtrAlloc( 10 ); + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) + { + if ( Ivy_ObjIsCo(pFanout) ) + { +// assert( (int)Ivy_ObjFanin0(pFanout)->Level <= p->nLevelMax ); + continue; + } + LevelNew = Ivy_ObjLevelNew( pFanout ); + if ( (int)pFanout->Level == LevelNew ) + continue; + pFanout->Level = LevelNew; + Ivy_ObjUpdateLevel_rec( p, pFanout ); + } + Vec_PtrFree( vFanouts ); +} + +/**Function************************************************************* + + Synopsis [Compute the new required level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjLevelRNew( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanout; + Vec_Ptr_t * vFanouts; + int i, Required, LevelNew = 1000000; + assert( p->fFanout && p->vRequired ); + vFanouts = Vec_PtrAlloc( 10 ); + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) + { + Required = Vec_IntEntry(p->vRequired, pFanout->Id); + LevelNew = IVY_MIN( LevelNew, Required ); + } + Vec_PtrFree( vFanouts ); + return LevelNew - 1; +} + +/**Function************************************************************* + + Synopsis [Recursively updates fanout levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ) +{ + Ivy_Obj_t * pFanin; + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) + return; + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + // process the first fanin + pFanin = Ivy_ObjFanin0(pObj); + if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) + { + Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); + Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); + } + if ( Ivy_ObjIsBuf(pObj) ) + return; + // process the second fanin + pFanin = Ivy_ObjFanin1(pObj); + if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) + { + Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); + Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); + } +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjIsMuxType( Ivy_Obj_t * pNode ) +{ + Ivy_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Ivy_IsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Ivy_ObjIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Ivy_ObjFaninC0(pNode) || !Ivy_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Ivy_ObjFanin0(pNode); + pNode1 = Ivy_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( !Ivy_ObjIsAnd(pNode0) || !Ivy_ObjIsAnd(pNode1) ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren + return (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || + (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1))) || + (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || + (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1))); +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pNode, Ivy_Obj_t ** ppNodeT, Ivy_Obj_t ** ppNodeE ) +{ + Ivy_Obj_t * pNode0, * pNode1; + assert( !Ivy_IsComplement(pNode) ); + assert( Ivy_ObjIsMuxType(pNode) ); + // get children + pNode0 = Ivy_ObjFanin0(pNode); + pNode1 = Ivy_ObjFanin1(pNode); + // find the control variable +// if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) + if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Ivy_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + return Ivy_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + return Ivy_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) + else if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Ivy_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + return Ivy_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + return Ivy_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) + else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Ivy_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + return Ivy_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + return Ivy_ObjChild1(pNode0);//pNode1->p2; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) + else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Ivy_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + return Ivy_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + return Ivy_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the real fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanin; + if ( pObj == NULL || !Ivy_ObjIsBuf( Ivy_Regular(pObj) ) ) + return pObj; + pFanin = Ivy_ObjReal( Ivy_ObjChild0(Ivy_Regular(pObj)) ); + return Ivy_NotCond( pFanin, Ivy_IsComplement(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ) +{ + Ivy_Obj_t * pTemp; + int fShowFanouts = 0; + assert( !Ivy_IsComplement(pObj) ); + printf( "Node %5d : ", Ivy_ObjId(pObj) ); + if ( Ivy_ObjIsConst1(pObj) ) + printf( "constant 1" ); + else if ( Ivy_ObjIsPi(pObj) ) + printf( "PI" ); + else if ( Ivy_ObjIsPo(pObj) ) + printf( "PO" ); + else if ( Ivy_ObjIsLatch(pObj) ) + printf( "latch (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); + else if ( Ivy_ObjIsBuf(pObj) ) + printf( "buffer (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); + else + printf( "AND( %5d%s, %5d%s )", + Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " "), + Ivy_ObjFanin1(pObj)->Id, (Ivy_ObjFaninC1(pObj)? "\'" : " ") ); + printf( " (refs = %3d)", Ivy_ObjRefs(pObj) ); + if ( fShowFanouts ) + { + Vec_Ptr_t * vFanouts; + Ivy_Obj_t * pFanout; + int i; + vFanouts = Vec_PtrAlloc( 10 ); + printf( "\nFanouts:\n" ); + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) + { + printf( " " ); + printf( "Node %5d : ", Ivy_ObjId(pFanout) ); + if ( Ivy_ObjIsPo(pFanout) ) + printf( "PO" ); + else if ( Ivy_ObjIsLatch(pFanout) ) + printf( "latch (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); + else if ( Ivy_ObjIsBuf(pFanout) ) + printf( "buffer (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); + else + printf( "AND( %5d%s, %5d%s )", + Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " "), + Ivy_ObjFanin1(pFanout)->Id, (Ivy_ObjFaninC1(pFanout)? "\'" : " ") ); + printf( "\n" ); + } + Vec_PtrFree( vFanouts ); + return; + } + if ( !fHaig ) + { + if ( pObj->pEquiv == NULL ) + printf( " HAIG node not given" ); + else + printf( " HAIG node = %d%s", Ivy_Regular(pObj->pEquiv)->Id, (Ivy_IsComplement(pObj->pEquiv)? "\'" : " ") ); + return; + } + if ( pObj->pEquiv == NULL ) + return; + // there are choices + if ( Ivy_ObjRefs(pObj) > 0 ) + { + // print equivalence class + printf( " { %5d ", pObj->Id ); + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + printf( " %5d%s", pTemp->Id, (Ivy_IsComplement(pTemp->pEquiv)? "\'" : " ") ); + printf( " }" ); + return; + } + // this is a secondary node + for ( pTemp = Ivy_Regular(pObj->pEquiv); Ivy_ObjRefs(pTemp) == 0; pTemp = Ivy_Regular(pTemp->pEquiv) ); + assert( Ivy_ObjRefs(pTemp) > 0 ); + printf( " class of %d", pTemp->Id ); +} + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ) +{ + Vec_Int_t * vNodes; + Ivy_Obj_t * pObj; + int i; + printf( "PIs: " ); + Ivy_ManForEachPi( p, pObj, i ) + printf( " %d", pObj->Id ); + printf( "\n" ); + printf( "POs: " ); + Ivy_ManForEachPo( p, pObj, i ) + printf( " %d", pObj->Id ); + printf( "\n" ); + printf( "Latches: " ); + Ivy_ManForEachLatch( p, pObj, i ) + printf( " %d=%d%s", pObj->Id, Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); + printf( "\n" ); + vNodes = Ivy_ManDfsSeq( p, NULL ); + Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) + Ivy_ObjPrintVerbose( p, pObj, fHaig ), printf( "\n" ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_CutTruthPrint2( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ) +{ + int i; + printf( "Trying cut : {" ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); + printf( " } " ); + Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ) +{ + Vec_Ptr_t * vArray; + Ivy_Obj_t * pObj, * pFanout; + int nLatches = 0; + int nPresent = 0; + int i, k; + int fVerbose = 0; + + if ( fVerbose ) + printf( "Trying cut : {" ); + for ( i = 0; i < pCut->nSize; i++ ) + { + if ( fVerbose ) + printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); + nLatches += Ivy_LeafLat(pCut->pArray[i]); + } + if ( fVerbose ) + printf( " } " ); + if ( fVerbose ) + printf( "Latches = %d. ", nLatches ); + + // check if there are latches on the fanout edges + vArray = Vec_PtrAlloc( 100 ); + for ( i = 0; i < pCut->nSize; i++ ) + { + pObj = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[i]) ); + Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, k ) + { + if ( Ivy_ObjIsLatch(pFanout) ) + { + nPresent++; + break; + } + } + } + Vec_PtrSize( vArray ); + if ( fVerbose ) + { + printf( "Present = %d. ", nPresent ); + if ( nLatches > nPresent ) + printf( "Clauses = %d. ", 2*(nLatches - nPresent) ); + printf( "\n" ); + } + return ( nLatches > nPresent ) ? 2*(nLatches - nPresent) : 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/ivy_.c b/abc70930/src/aig/ivy/ivy_.c new file mode 100644 index 00000000..65689689 --- /dev/null +++ b/abc70930/src/aig/ivy/ivy_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [ivy_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/ivy/module.make b/abc70930/src/aig/ivy/module.make new file mode 100644 index 00000000..daef43df --- /dev/null +++ b/abc70930/src/aig/ivy/module.make @@ -0,0 +1,22 @@ +SRC += src/aig/ivy/ivyBalance.c \ + src/aig/ivy/ivyCanon.c \ + src/aig/ivy/ivyCheck.c \ + src/aig/ivy/ivyCut.c \ + src/aig/ivy/ivyCutTrav.c \ + src/aig/ivy/ivyDfs.c \ + src/aig/ivy/ivyDsd.c \ + src/aig/ivy/ivyFanout.c \ + src/aig/ivy/ivyFastMap.c \ + src/aig/ivy/ivyFraig.c \ + src/aig/ivy/ivyHaig.c \ + src/aig/ivy/ivyMan.c \ + src/aig/ivy/ivyMem.c \ + src/aig/ivy/ivyMulti.c \ + src/aig/ivy/ivyObj.c \ + src/aig/ivy/ivyOper.c \ + src/aig/ivy/ivyResyn.c \ + src/aig/ivy/ivyRwr.c \ + src/aig/ivy/ivySeq.c \ + src/aig/ivy/ivyShow.c \ + src/aig/ivy/ivyTable.c \ + src/aig/ivy/ivyUtil.c diff --git a/abc70930/src/aig/kit/cloud.c b/abc70930/src/aig/kit/cloud.c new file mode 100644 index 00000000..6e6691f0 --- /dev/null +++ b/abc70930/src/aig/kit/cloud.c @@ -0,0 +1,987 @@ +/**CFile**************************************************************** + + FileName [cloudCore.c] + + PackageName [Fast application-specific BDD package.] + + Synopsis [The package core.] + + Author [Alan Mishchenko ] + + Affiliation [ECE Department. Portland State University, Portland, Oregon.] + + Date [Ver. 1.0. Started - June 10, 2002.] + + Revision [$Id: cloudCore.c,v 1.0 2002/06/10 03:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cloud.h" + +// the number of operators using cache +static int CacheOperNum = 4; + +// the ratio of cache size to the unique table size for each operator +static int CacheLogRatioDefault[4] = { + 2, // CLOUD_OPER_AND, + 8, // CLOUD_OPER_XOR, + 8, // CLOUD_OPER_BDIFF, + 8 // CLOUD_OPER_LEQ +}; + +// the ratio of cache size to the unique table size for each operator +static int CacheSize[4] = { + 2, // CLOUD_OPER_AND, + 2, // CLOUD_OPER_XOR, + 2, // CLOUD_OPER_BDIFF, + 2 // CLOUD_OPER_LEQ +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// static functions +static CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ); +static void cloudCacheAllocate( CloudManager * dd, CloudOper oper ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function******************************************************************** + + Synopsis [Starts the cloud manager.] + + Description [The first arguments is the number of elementary variables used. + The second arguments is the number of bits of the unsigned integer used to + represent nodes in the unique table. If the second argument is 0, the package + assumes 23 to represent nodes, which is equivalent to 2^23 = 8,388,608 nodes.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +CloudManager * Cloud_Init( int nVars, int nBits ) +{ + CloudManager * dd; + int i; + int clk1, clk2; + + assert( nVars <= 100000 ); + assert( nBits < 32 ); + + // assign the defaults + if ( nBits == 0 ) + nBits = CLOUD_NODE_BITS; + + // start the manager + dd = CALLOC( CloudManager, 1 ); + dd->nMemUsed += sizeof(CloudManager); + + // variables + dd->nVars = nVars; // the number of variables allocated + // bits + dd->bitsNode = nBits; // the number of bits used for the node + for ( i = 0; i < CacheOperNum; i++ ) + dd->bitsCache[i] = nBits - CacheLogRatioDefault[i]; + // shifts + dd->shiftUnique = 8*sizeof(unsigned) - (nBits + 1); // gets node index in the hash table + for ( i = 0; i < CacheOperNum; i++ ) + dd->shiftCache[i] = 8*sizeof(unsigned) - dd->bitsCache[i]; + // nodes + dd->nNodesAlloc = (1 << (nBits + 1)); // 2 ^ (nBits + 1) + dd->nNodesLimit = (1 << nBits); // 2 ^ nBits + + // unique table +clk1 = clock(); + dd->tUnique = CALLOC( CloudNode, dd->nNodesAlloc ); + dd->nMemUsed += sizeof(CloudNode) * dd->nNodesAlloc; +clk2 = clock(); +//PRT( "calloc() time", clk2 - clk1 ); + + // set up the constant node (the only node that is not in the hash table) + dd->nSignCur = 1; + dd->tUnique[0].s = dd->nSignCur; + dd->tUnique[0].v = CLOUD_CONST_INDEX; + dd->tUnique[0].e = CLOUD_VOID; + dd->tUnique[0].t = CLOUD_VOID; + dd->one = dd->tUnique; + dd->zero = Cloud_Not(dd->one); + dd->nNodesCur = 1; + + // special nodes + dd->pNodeStart = dd->tUnique + 1; + dd->pNodeEnd = dd->tUnique + dd->nNodesAlloc; + + // set up the elementary variables + dd->vars = ALLOC( CloudNode *, dd->nVars ); + dd->nMemUsed += sizeof(CloudNode *) * dd->nVars; + for ( i = 0; i < dd->nVars; i++ ) + dd->vars[i] = cloudMakeNode( dd, i, dd->one, dd->zero ); + + return dd; +}; + +/**Function******************************************************************** + + Synopsis [Stops the cloud manager.] + + Description [The first arguments tells show many elementary variables are used. + The second arguments tells how many bits of the unsigned integer are used + to represent regular nodes in the unique table.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Cloud_Quit( CloudManager * dd ) +{ + int i; + FREE( dd->ppNodes ); + free( dd->tUnique ); + free( dd->vars ); + for ( i = 0; i < 4; i++ ) + FREE( dd->tCaches[i] ); + free( dd ); +} + +/**Function******************************************************************** + + Synopsis [Prepares the manager for another run.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Cloud_Restart( CloudManager * dd ) +{ + int i; + assert( dd->one->s == dd->nSignCur ); + dd->nSignCur++; + dd->one->s++; + for ( i = 0; i < dd->nVars; i++ ) + dd->vars[i]->s++; + dd->nNodesCur = 1 + dd->nVars; +} + +/**Function******************************************************************** + + Synopsis [This optional function allocates operation cache of the given size.] + + Description [Cache for each operation is allocated independently when the first + operation of the given type is performed. The user can allocate cache of his/her + preferred size by calling Cloud_CacheAllocate before the first operation of the + given type is performed, but this call is optional. Argument "logratio" gives + the binary logarithm of the ratio of the size of the unique table to that of cache. + For example, if "logratio" is equal to 3, and the unique table will be 2^3=8 times + larger than cache; so, if unique table is 2^23 = 8,388,608 nodes, the cache size + will be 2^3=8 times smaller and equal to 2^20 = 1,048,576 entries.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Cloud_CacheAllocate( CloudManager * dd, CloudOper oper, int logratio ) +{ + assert( logratio > 0 ); // cache cannot be larger than the unique table + assert( logratio < dd->bitsNode ); // cache cannot be smaller than 2 entries + + if ( logratio ) + { + dd->bitsCache[oper] = dd->bitsNode - logratio; + dd->shiftCache[oper] = 8*sizeof(unsigned) - dd->bitsCache[oper]; + } + cloudCacheAllocate( dd, oper ); +} + +/**Function******************************************************************** + + Synopsis [Internal cache allocation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void cloudCacheAllocate( CloudManager * dd, CloudOper oper ) +{ + int nCacheEntries = (1 << dd->bitsCache[oper]); + + if ( CacheSize[oper] == 1 ) + { + dd->tCaches[oper] = (CloudCacheEntry2 *)CALLOC( CloudCacheEntry1, nCacheEntries ); + dd->nMemUsed += sizeof(CloudCacheEntry1) * nCacheEntries; + } + else if ( CacheSize[oper] == 2 ) + { + dd->tCaches[oper] = (CloudCacheEntry2 *)CALLOC( CloudCacheEntry2, nCacheEntries ); + dd->nMemUsed += sizeof(CloudCacheEntry2) * nCacheEntries; + } + else if ( CacheSize[oper] == 3 ) + { + dd->tCaches[oper] = (CloudCacheEntry2 *)CALLOC( CloudCacheEntry3, nCacheEntries ); + dd->nMemUsed += sizeof(CloudCacheEntry3) * nCacheEntries; + } +} + + + +/**Function******************************************************************** + + Synopsis [Returns or creates a new node] + + Description [Checks the unique table for the existance of the node. If the node is + present, returns the node. If the node is absent, creates a new node.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +CloudNode * Cloud_MakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ) +{ + CloudNode * pRes; + CLOUD_ASSERT(t); + CLOUD_ASSERT(e); + assert( v < Cloud_V(t) && v < Cloud_V(e) ); // variable should be above in the order + if ( Cloud_IsComplement(t) ) + { + pRes = cloudMakeNode( dd, v, Cloud_Not(t), Cloud_Not(e) ); + if ( pRes != CLOUD_VOID ) + pRes = Cloud_Not(pRes); + } + else + pRes = cloudMakeNode( dd, v, t, e ); + return pRes; +} + +/**Function******************************************************************** + + Synopsis [Returns or creates a new node] + + Description [Checks the unique table for the existance of the node. If the node is + present, returns the node. If the node is absent, creates a new node.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ) +{ + CloudNode * entryUnique; + + CLOUD_ASSERT(t); + CLOUD_ASSERT(e); + + assert( ((int)v) >= 0 && ((int)v) < dd->nVars ); // the variable must be in the range + assert( v < Cloud_V(t) && v < Cloud_V(e) ); // variable should be above in the order + assert( !Cloud_IsComplement(t) ); // the THEN edge must not be complemented + + // make sure we are not searching for the constant node + assert( t && e ); + + // get the unique entry + entryUnique = dd->tUnique + cloudHashCudd3(v, t, e, dd->shiftUnique); + while ( entryUnique->s == dd->nSignCur ) + { + // compare the node + if ( entryUnique->v == v && entryUnique->t == t && entryUnique->e == e ) + { // the node is found + dd->nUniqueHits++; + return entryUnique; // returns the node + } + // increment the hash value modulus the hash table size + if ( ++entryUnique - dd->tUnique == dd->nNodesAlloc ) + entryUnique = dd->tUnique + 1; + // increment the number of steps through the table + dd->nUniqueSteps++; + } + dd->nUniqueMisses++; + + // check if the new node can be created + if ( ++dd->nNodesCur == dd->nNodesLimit ) + { // initiate the restart + printf( "Cloud needs restart!\n" ); +// fflush( stdout ); +// exit(1); + return CLOUD_VOID; + } + // create the node + entryUnique->s = dd->nSignCur; + entryUnique->v = v; + entryUnique->t = t; + entryUnique->e = e; + return entryUnique; // returns the node +} + + +/**Function******************************************************************** + + Synopsis [Performs the AND or two BDDs] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +CloudNode * cloudBddAnd( CloudManager * dd, CloudNode * f, CloudNode * g ) +{ + CloudNode * F, * G, * r; + CloudCacheEntry2 * cacheEntry; + CloudNode * fv, * fnv, * gv, * gnv, * t, * e; + CloudVar var; + + assert( f <= g ); + + // terminal cases + F = Cloud_Regular(f); + G = Cloud_Regular(g); + if ( F == G ) + { + if ( f == g ) + return f; + else + return dd->zero; + } + if ( F == dd->one ) + { + if ( f == dd->one ) + return g; + else + return f; + } + + // check cache + cacheEntry = dd->tCaches[CLOUD_OPER_AND] + cloudHashCudd2(f, g, dd->shiftCache[CLOUD_OPER_AND]); +// cacheEntry = dd->tCaches[CLOUD_OPER_AND] + cloudHashBuddy2(f, g, dd->shiftCache[CLOUD_OPER_AND]); + r = cloudCacheLookup2( cacheEntry, dd->nSignCur, f, g ); + if ( r != CLOUD_VOID ) + { + dd->nCacheHits++; + return r; + } + dd->nCacheMisses++; + + + // compute cofactors + if ( cloudV(F) <= cloudV(G) ) + { + var = cloudV(F); + if ( Cloud_IsComplement(f) ) + { + fnv = Cloud_Not(cloudE(F)); + fv = Cloud_Not(cloudT(F)); + } + else + { + fnv = cloudE(F); + fv = cloudT(F); + } + } + else + { + var = cloudV(G); + fv = fnv = f; + } + + if ( cloudV(G) <= cloudV(F) ) + { + if ( Cloud_IsComplement(g) ) + { + gnv = Cloud_Not(cloudE(G)); + gv = Cloud_Not(cloudT(G)); + } + else + { + gnv = cloudE(G); + gv = cloudT(G); + } + } + else + { + gv = gnv = g; + } + + if ( fv <= gv ) + t = cloudBddAnd( dd, fv, gv ); + else + t = cloudBddAnd( dd, gv, fv ); + + if ( t == CLOUD_VOID ) + return CLOUD_VOID; + + if ( fnv <= gnv ) + e = cloudBddAnd( dd, fnv, gnv ); + else + e = cloudBddAnd( dd, gnv, fnv ); + + if ( e == CLOUD_VOID ) + return CLOUD_VOID; + + if ( t == e ) + r = t; + else + { + if ( Cloud_IsComplement(t) ) + { + r = cloudMakeNode( dd, var, Cloud_Not(t), Cloud_Not(e) ); + if ( r == CLOUD_VOID ) + return CLOUD_VOID; + r = Cloud_Not(r); + } + else + { + r = cloudMakeNode( dd, var, t, e ); + if ( r == CLOUD_VOID ) + return CLOUD_VOID; + } + } + cloudCacheInsert2( cacheEntry, dd->nSignCur, f, g, r ); + return r; +} + +/**Function******************************************************************** + + Synopsis [Performs the AND or two BDDs] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +static inline CloudNode * cloudBddAnd_gate( CloudManager * dd, CloudNode * f, CloudNode * g ) +{ + if ( f <= g ) + return cloudBddAnd(dd,f,g); + else + return cloudBddAnd(dd,g,f); +} + +/**Function******************************************************************** + + Synopsis [Performs the AND or two BDDs] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +CloudNode * Cloud_bddAnd( CloudManager * dd, CloudNode * f, CloudNode * g ) +{ + if ( Cloud_Regular(f) == CLOUD_VOID || Cloud_Regular(g) == CLOUD_VOID ) + return CLOUD_VOID; + CLOUD_ASSERT(f); + CLOUD_ASSERT(g); + if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) + cloudCacheAllocate( dd, CLOUD_OPER_AND ); + return cloudBddAnd_gate( dd, f, g ); +} + +/**Function******************************************************************** + + Synopsis [Performs the OR or two BDDs] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +CloudNode * Cloud_bddOr( CloudManager * dd, CloudNode * f, CloudNode * g ) +{ + CloudNode * res; + if ( Cloud_Regular(f) == CLOUD_VOID || Cloud_Regular(g) == CLOUD_VOID ) + return CLOUD_VOID; + CLOUD_ASSERT(f); + CLOUD_ASSERT(g); + if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) + cloudCacheAllocate( dd, CLOUD_OPER_AND ); + res = cloudBddAnd_gate( dd, Cloud_Not(f), Cloud_Not(g) ); + res = Cloud_NotCond( res, res != CLOUD_VOID ); + return res; +} + +/**Function******************************************************************** + + Synopsis [Performs the XOR or two BDDs] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +CloudNode * Cloud_bddXor( CloudManager * dd, CloudNode * f, CloudNode * g ) +{ + CloudNode * t0, * t1, * r; + if ( Cloud_Regular(f) == CLOUD_VOID || Cloud_Regular(g) == CLOUD_VOID ) + return CLOUD_VOID; + CLOUD_ASSERT(f); + CLOUD_ASSERT(g); + if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) + cloudCacheAllocate( dd, CLOUD_OPER_AND ); + t0 = cloudBddAnd_gate( dd, f, Cloud_Not(g) ); + if ( t0 == CLOUD_VOID ) + return CLOUD_VOID; + t1 = cloudBddAnd_gate( dd, Cloud_Not(f), g ); + if ( t1 == CLOUD_VOID ) + return CLOUD_VOID; + r = Cloud_bddOr( dd, t0, t1 ); + return r; +} + + + +/**Function******************************************************************** + + Synopsis [Performs a DFS from f, clearing the LSB of the next + pointers.] + + Description [] + + SideEffects [None] + + SeeAlso [cloudSupport cloudDagSize] + +******************************************************************************/ +static void cloudClearMark( CloudManager * dd, CloudNode * n ) +{ + if ( !cloudNodeIsMarked(n) ) + return; + // clear visited flag + cloudNodeUnmark(n); + if ( cloudIsConstant(n) ) + return; + cloudClearMark( dd, cloudT(n) ); + cloudClearMark( dd, Cloud_Regular(cloudE(n)) ); +} + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cloud_Support.] + + Description [Performs the recursive step of Cloud_Support. Performs a + DFS from f. The support is accumulated in supp as a side effect. Uses + the LSB of the then pointer as visited flag.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void cloudSupport( CloudManager * dd, CloudNode * n, int * support ) +{ + if ( cloudIsConstant(n) || cloudNodeIsMarked(n) ) + return; + // set visited flag + cloudNodeMark(n); + support[cloudV(n)] = 1; + cloudSupport( dd, cloudT(n), support ); + cloudSupport( dd, Cloud_Regular(cloudE(n)), support ); +} + +/**Function******************************************************************** + + Synopsis [Finds the variables on which a DD depends.] + + Description [Finds the variables on which a DD depends. + Returns a BDD consisting of the product of the variables if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +CloudNode * Cloud_Support( CloudManager * dd, CloudNode * n ) +{ + CloudNode * res; + int * support, i; + + CLOUD_ASSERT(n); + + // allocate and initialize support array for cloudSupport + support = CALLOC( int, dd->nVars ); + + // compute support and clean up markers + cloudSupport( dd, Cloud_Regular(n), support ); + cloudClearMark( dd, Cloud_Regular(n) ); + + // transform support from array to cube + res = dd->one; + for ( i = dd->nVars - 1; i >= 0; i-- ) // for each level bottom-up + if ( support[i] == 1 ) + { + res = Cloud_bddAnd( dd, res, dd->vars[i] ); + if ( res == CLOUD_VOID ) + break; + } + FREE( support ); + return res; +} + +/**Function******************************************************************** + + Synopsis [Counts the variables on which a DD depends.] + + Description [Counts the variables on which a DD depends. + Returns the number of the variables if successful; Cloud_OUT_OF_MEM + otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int Cloud_SupportSize( CloudManager * dd, CloudNode * n ) +{ + int * support, i, count; + + CLOUD_ASSERT(n); + + // allocate and initialize support array for cloudSupport + support = CALLOC( int, dd->nVars ); + + // compute support and clean up markers + cloudSupport( dd, Cloud_Regular(n), support ); + cloudClearMark( dd, Cloud_Regular(n) ); + + // count support variables + count = 0; + for ( i = 0; i < dd->nVars; i++ ) + { + if ( support[i] == 1 ) + count++; + } + + FREE( support ); + return count; +} + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cloud_DagSize.] + + Description [Performs the recursive step of Cloud_DagSize. Returns the + number of nodes in the graph rooted at n.] + + SideEffects [None] + +******************************************************************************/ +static int cloudDagSize( CloudManager * dd, CloudNode * n ) +{ + int tval, eval; + if ( cloudNodeIsMarked(n) ) + return 0; + // set visited flag + cloudNodeMark(n); + if ( cloudIsConstant(n) ) + return 1; + tval = cloudDagSize( dd, cloudT(n) ); + eval = cloudDagSize( dd, Cloud_Regular(cloudE(n)) ); + return tval + eval + 1; + +} + +/**Function******************************************************************** + + Synopsis [Counts the number of nodes in a DD.] + + Description [Counts the number of nodes in a DD. Returns the number + of nodes in the graph rooted at node.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Cloud_DagSize( CloudManager * dd, CloudNode * n ) +{ + int res; + res = cloudDagSize( dd, Cloud_Regular( n ) ); + cloudClearMark( dd, Cloud_Regular( n ) ); + return res; + +} + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cloud_DagSize.] + + Description [Performs the recursive step of Cloud_DagSize. Returns the + number of nodes in the graph rooted at n.] + + SideEffects [None] + +******************************************************************************/ +static int Cloud_DagCollect_rec( CloudManager * dd, CloudNode * n, int * pCounter ) +{ + int tval, eval; + if ( cloudNodeIsMarked(n) ) + return 0; + // set visited flag + cloudNodeMark(n); + if ( cloudIsConstant(n) ) + { + dd->ppNodes[(*pCounter)++] = n; + return 1; + } + tval = Cloud_DagCollect_rec( dd, cloudT(n), pCounter ); + eval = Cloud_DagCollect_rec( dd, Cloud_Regular(cloudE(n)), pCounter ); + dd->ppNodes[(*pCounter)++] = n; + return tval + eval + 1; + +} + +/**Function******************************************************************** + + Synopsis [Counts the number of nodes in a DD.] + + Description [Counts the number of nodes in a DD. Returns the number + of nodes in the graph rooted at node.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Cloud_DagCollect( CloudManager * dd, CloudNode * n ) +{ + int res, Counter = 0; + if ( dd->ppNodes == NULL ) + dd->ppNodes = ALLOC( CloudNode *, dd->nNodesLimit ); + res = Cloud_DagCollect_rec( dd, Cloud_Regular( n ), &Counter ); + cloudClearMark( dd, Cloud_Regular( n ) ); + assert( res == Counter ); + return res; + +} + +/**Function******************************************************************** + + Synopsis [Counts the number of nodes in an array of DDs.] + + Description [Counts the number of nodes in a DD. Returns the number + of nodes in the graph rooted at node.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Cloud_SharingSize( CloudManager * dd, CloudNode ** pn, int nn ) +{ + int res, i; + res = 0; + for ( i = 0; i < nn; i++ ) + res += cloudDagSize( dd, Cloud_Regular( pn[i] ) ); + for ( i = 0; i < nn; i++ ) + cloudClearMark( dd, Cloud_Regular( pn[i] ) ); + return res; +} + + +/**Function******************************************************************** + + Synopsis [Returns one cube contained in the given BDD.] + + Description [] + + SideEffects [] + +******************************************************************************/ +CloudNode * Cloud_GetOneCube( CloudManager * dd, CloudNode * bFunc ) +{ + CloudNode * bFunc0, * bFunc1, * res; + + if ( Cloud_IsConstant(bFunc) ) + return bFunc; + + // cofactor + if ( Cloud_IsComplement(bFunc) ) + { + bFunc0 = Cloud_Not( cloudE(bFunc) ); + bFunc1 = Cloud_Not( cloudT(bFunc) ); + } + else + { + bFunc0 = cloudE(bFunc); + bFunc1 = cloudT(bFunc); + } + + // try to find the cube with the negative literal + res = Cloud_GetOneCube( dd, bFunc0 ); + if ( res == CLOUD_VOID ) + return CLOUD_VOID; + + if ( res != dd->zero ) + { + res = Cloud_bddAnd( dd, res, Cloud_Not(dd->vars[Cloud_V(bFunc)]) ); + } + else + { + // try to find the cube with the positive literal + res = Cloud_GetOneCube( dd, bFunc1 ); + if ( res == CLOUD_VOID ) + return CLOUD_VOID; + assert( res != dd->zero ); + res = Cloud_bddAnd( dd, res, dd->vars[Cloud_V(bFunc)] ); + } + return res; +} + +/**Function******************************************************************** + + Synopsis [Prints the BDD as a set of disjoint cubes to the standard output.] + + Description [] + + SideEffects [] + +******************************************************************************/ +void Cloud_bddPrint( CloudManager * dd, CloudNode * Func ) +{ + CloudNode * Cube; + int fFirst = 1; + + if ( Func == dd->zero ) + printf( "Constant 0." ); + else if ( Func == dd->one ) + printf( "Constant 1." ); + else + { + while ( 1 ) + { + Cube = Cloud_GetOneCube( dd, Func ); + if ( Cube == CLOUD_VOID || Cube == dd->zero ) + break; + if ( fFirst ) fFirst = 0; + else printf( " + " ); + Cloud_bddPrintCube( dd, Cube ); + Func = Cloud_bddAnd( dd, Func, Cloud_Not(Cube) ); + } + } + printf( "\n" ); +} + +/**Function******************************************************************** + + Synopsis [Prints one cube.] + + Description [] + + SideEffects [] + +******************************************************************************/ +void Cloud_bddPrintCube( CloudManager * dd, CloudNode * bCube ) +{ + CloudNode * bCube0, * bCube1; + + assert( !Cloud_IsConstant(bCube) ); + while ( 1 ) + { + // get the node structure + if ( Cloud_IsConstant(bCube) ) + break; + + // cofactor the cube + if ( Cloud_IsComplement(bCube) ) + { + bCube0 = Cloud_Not( cloudE(bCube) ); + bCube1 = Cloud_Not( cloudT(bCube) ); + } + else + { + bCube0 = cloudE(bCube); + bCube1 = cloudT(bCube); + } + + if ( bCube0 != dd->zero ) + { + assert( bCube1 == dd->zero ); + printf( "[%d]'", cloudV(bCube) ); + bCube = bCube0; + } + else + { + assert( bCube1 != dd->zero ); + printf( "[%d]", cloudV(bCube) ); + bCube = bCube1; + } + } +} + + +/**Function******************************************************************** + + Synopsis [Prints info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Cloud_PrintInfo( CloudManager * dd ) +{ + if ( dd == NULL ) return; + printf( "The number of unique table nodes allocated = %12d.\n", dd->nNodesAlloc ); + printf( "The number of unique table nodes present = %12d.\n", dd->nNodesCur ); + printf( "The number of unique table hits = %12d.\n", dd->nUniqueHits ); + printf( "The number of unique table misses = %12d.\n", dd->nUniqueMisses ); + printf( "The number of unique table steps = %12d.\n", dd->nUniqueSteps ); + printf( "The number of cache hits = %12d.\n", dd->nCacheHits ); + printf( "The number of cache misses = %12d.\n", dd->nCacheMisses ); + printf( "The current signature = %12d.\n", dd->nSignCur ); + printf( "The total memory in use = %12d.\n", dd->nMemUsed ); +} + +/**Function******************************************************************** + + Synopsis [Prints the state of the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Cloud_PrintHashTable( CloudManager * dd ) +{ + int i; + + for ( i = 0; i < dd->nNodesAlloc; i++ ) + if ( dd->tUnique[i].v == CLOUD_CONST_INDEX ) + printf( "-" ); + else + printf( "+" ); + printf( "\n" ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/kit/cloud.h b/abc70930/src/aig/kit/cloud.h new file mode 100644 index 00000000..ac9d45f4 --- /dev/null +++ b/abc70930/src/aig/kit/cloud.h @@ -0,0 +1,269 @@ +/**CFile**************************************************************** + + FileName [cloud.h] + + PackageName [Fast application-specific BDD package.] + + Synopsis [Interface of the package.] + + Author [Alan Mishchenko ] + + Affiliation [ECE Department. Portland State University, Portland, Oregon.] + + Date [Ver. 1.0. Started - June 10, 2002.] + + Revision [$Id: cloud.h,v 1.0 2002/06/10 03:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CLOUD_H__ +#define __CLOUD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +//////////////////////////////////////////////////////////////////////// +// n | 2^n || n | 2^n || n | 2^n || n | 2^n // +//====================================================================// +// 1 | 2 || 9 | 512 || 17 | 131,072 || 25 | 33,554,432 // +// 2 | 4 || 10 | 1,024 || 18 | 262,144 || 26 | 67,108,864 // +// 3 | 8 || 11 | 2,048 || 19 | 524,288 || 27 | 134,217,728 // +// 4 | 16 || 12 | 4,096 || 20 | 1,048,576 || 28 | 268,435,456 // +// 5 | 32 || 13 | 8,192 || 21 | 2,097,152 || 29 | 536,870,912 // +// 6 | 64 || 14 | 16,384 || 22 | 4,194,304 || 30 | 1,073,741,824 // +// 7 | 128 || 15 | 32,768 || 23 | 8,388,608 || 31 | 2,147,483,648 // +// 8 | 256 || 16 | 65,536 || 24 | 16,777,216 || 32 | 4,294,967,296 // +//////////////////////////////////////////////////////////////////////// + +// data structure typedefs +typedef struct cloudManager CloudManager; +typedef unsigned CloudVar; +typedef unsigned CloudSign; +typedef struct cloudNode CloudNode; +typedef struct cloudCacheEntry1 CloudCacheEntry1; +typedef struct cloudCacheEntry2 CloudCacheEntry2; +typedef struct cloudCacheEntry3 CloudCacheEntry3; + +// operation codes used to set up the cache +typedef enum { + CLOUD_OPER_AND, + CLOUD_OPER_XOR, + CLOUD_OPER_BDIFF, + CLOUD_OPER_LEQ +} CloudOper; + +/* +// the number of operators using cache +static int CacheOperNum = 4; + +// the ratio of cache size to the unique table size for each operator +static int CacheLogRatioDefault[4] = { + 4, // CLOUD_OPER_AND, + 8, // CLOUD_OPER_XOR, + 8, // CLOUD_OPER_BDIFF, + 8 // CLOUD_OPER_LEQ +}; + +// the ratio of cache size to the unique table size for each operator +static int CacheSize[4] = { + 2, // CLOUD_OPER_AND, + 2, // CLOUD_OPER_XOR, + 2, // CLOUD_OPER_BDIFF, + 2 // CLOUD_OPER_LEQ +}; +*/ + +// data structure definitions +struct cloudManager // the fast bdd manager +{ + // variables + int nVars; // the number of variables allocated + // bits + int bitsNode; // the number of bits used for the node + int bitsCache[4]; // default: bitsNode - CacheSizeRatio[i] + // shifts + int shiftUnique; // 8*sizeof(unsigned) - (bitsNode + 1) + int shiftCache[4]; // 8*sizeof(unsigned) - bitsCache[i] + // nodes + int nNodesAlloc; // 2 ^ (bitsNode + 1) + int nNodesLimit; // 2 ^ bitsNode + int nNodesCur; // the current number of nodes (including const1 and vars) + // signature + CloudSign nSignCur; + + // statistics + int nMemUsed; // memory usage in bytes + // cache stats + int nUniqueHits; // hits in the unique table + int nUniqueMisses; // misses in the unique table + int nCacheHits; // hits in the caches + int nCacheMisses; // misses in the caches + // the number of steps through the hash table + int nUniqueSteps; + + // tables + CloudNode * tUnique; // the unique table to store BDD nodes + + // special nodes + CloudNode * pNodeStart; // the pointer to the first node + CloudNode * pNodeEnd; // the pointer to the first node out of the table + + // constants and variables + CloudNode * one; // the one function + CloudNode * zero; // the zero function + CloudNode ** vars; // the elementary variables + + // temporary storage for nodes + CloudNode ** ppNodes; + + // caches + CloudCacheEntry2 * tCaches[20]; // caches +}; + +struct cloudNode // representation of the node in the unique table +{ + CloudSign s; // signature + CloudVar v; // variable + CloudNode * e; // negative cofactor + CloudNode * t; // positive cofactor +}; +struct cloudCacheEntry1 // one-argument cache +{ + CloudSign s; // signature + CloudNode * a; // argument 1 + CloudNode * r; // result +}; +struct cloudCacheEntry2 // the two-argument cache +{ + CloudSign s; // signature + CloudNode * a; + CloudNode * b; + CloudNode * r; +}; +struct cloudCacheEntry3 // the three-argument cache +{ + CloudSign s; // signature + CloudNode * a; + CloudNode * b; + CloudNode * c; + CloudNode * r; +}; + + +// parameters +#define CLOUD_NODE_BITS 23 +#define CLOUD_ONE ((unsigned)0x00000001) +#define CLOUD_NOT_ONE ((unsigned)0xfffffffe) +#define CLOUD_VOID ((unsigned)0x00000000) + +#define CLOUD_CONST_INDEX ((unsigned)0x0fffffff) +#define CLOUD_MARK_ON ((unsigned)0x10000000) +#define CLOUD_MARK_OFF ((unsigned)0xefffffff) + +// hash functions a la Buddy +#define cloudHashBuddy2(x,y,s) ((((x)+(y))*((x)+(y)+1)/2) & ((1<<(32-(s)))-1)) +#define cloudHashBuddy3(x,y,z,s) (cloudHashBuddy2((cloudHashBuddy2((x),(y),(s))),(z),(s)) & ((1<<(32-(s)))-1)) +// hash functions a la Cudd +#define DD_P1 12582917 +#define DD_P2 4256249 +#define DD_P3 741457 +#define DD_P4 1618033999 +#define cloudHashCudd2(f,g,s) ((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) +#define cloudHashCudd3(f,g,h,s) (((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2 + (unsigned)(h)) * DD_P3) >> (s)) + +// node complementation (using node) +#define Cloud_Regular(p) ((CloudNode*)(((unsigned)(p)) & CLOUD_NOT_ONE)) // get the regular node (w/o bubble) +#define Cloud_Not(p) ((CloudNode*)(((unsigned)(p)) ^ CLOUD_ONE)) // complement the node +#define Cloud_NotCond(p,c) (((int)(c))? Cloud_Not(p):(p)) // complement the node conditionally +#define Cloud_IsComplement(p) ((int)(((unsigned)(p)) & CLOUD_ONE)) // check if complemented +// checking constants (using node) +#define Cloud_IsConstant(p) (((Cloud_Regular(p))->v & CLOUD_MARK_OFF) == CLOUD_CONST_INDEX) +#define cloudIsConstant(p) (((p)->v & CLOUD_MARK_OFF) == CLOUD_CONST_INDEX) + +// retrieving values from the node (using node structure) +#define Cloud_V(p) ((Cloud_Regular(p))->v) +#define Cloud_E(p) ((Cloud_Regular(p))->e) +#define Cloud_T(p) ((Cloud_Regular(p))->t) +// retrieving values from the regular node (using node structure) +#define cloudV(p) ((p)->v) +#define cloudE(p) ((p)->e) +#define cloudT(p) ((p)->t) +// marking/unmarking (using node structure) +#define cloudNodeMark(p) ((p)->v |= CLOUD_MARK_ON) +#define cloudNodeUnmark(p) ((p)->v &= CLOUD_MARK_OFF) +#define cloudNodeIsMarked(p) ((int)((p)->v & CLOUD_MARK_ON)) + +// cache lookups and inserts (using node) +#define cloudCacheLookup1(p,sign,f) (((p)->s == (sign) && (p)->a == (f))? ((p)->r): (CLOUD_VOID)) +#define cloudCacheLookup2(p,sign,f,g) (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g))? ((p)->r): (CLOUD_VOID)) +#define cloudCacheLookup3(p,sign,f,g,h) (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g) && (p)->c == (h))? ((p)->r): (CLOUD_VOID)) +// cache inserts +#define cloudCacheInsert1(p,sign,f,r) (((p)->s = (sign)), ((p)->a = (f)), ((p)->r = (r))) +#define cloudCacheInsert2(p,sign,f,g,r) (((p)->s = (sign)), ((p)->a = (f)), ((p)->b = (g)), ((p)->r = (r))) +#define cloudCacheInsert3(p,sign,f,g,h,r) (((p)->s = (sign)), ((p)->a = (f)), ((p)->b = (g)), ((p)->c = (h)), ((p)->r = (r))) + +//#define CLOUD_ASSERT(p) (assert((p) >= (dd->pNodeStart-1) && (p) < dd->pNodeEnd)) +#define CLOUD_ASSERT(p) assert((p) >= dd->tUnique && (p) < dd->tUnique+dd->nNodesAlloc) + +// utility macros +#ifndef ALLOC +#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#endif + +#ifndef CALLOC +#define CALLOC(type, num) ((type *) calloc((num), sizeof(type))) +#endif + +#ifndef FREE +#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#endif + +#ifndef PRT +#define PRT(a,t) fprintf( stdout, "%s = ", (a)); printf( "%.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) ) +#endif + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// +// starting/stopping +extern CloudManager * Cloud_Init( int nVars, int nBits ); +extern void Cloud_Quit( CloudManager * dd ); +extern void Cloud_Restart( CloudManager * dd ); +extern void Cloud_CacheAllocate( CloudManager * dd, CloudOper oper, int size ); +extern CloudNode * Cloud_MakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ); +// support and node count +extern CloudNode * Cloud_Support( CloudManager * dd, CloudNode * n ); +extern int Cloud_SupportSize( CloudManager * dd, CloudNode * n ); +extern int Cloud_DagSize( CloudManager * dd, CloudNode * n ); +extern int Cloud_DagCollect( CloudManager * dd, CloudNode * n ); +extern int Cloud_SharingSize( CloudManager * dd, CloudNode * * pn, int nn ); +// cubes +extern CloudNode * Cloud_GetOneCube( CloudManager * dd, CloudNode * n ); +extern void Cloud_bddPrint( CloudManager * dd, CloudNode * Func ); +extern void Cloud_bddPrintCube( CloudManager * dd, CloudNode * Cube ); +// operations +extern CloudNode * Cloud_bddAnd( CloudManager * dd, CloudNode * f, CloudNode * g ); +extern CloudNode * Cloud_bddOr( CloudManager * dd, CloudNode * f, CloudNode * g ); +// stats +extern void Cloud_PrintInfo( CloudManager * dd ); +extern void Cloud_PrintHashTable( CloudManager * dd ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/aig/kit/kit.h b/abc70930/src/aig/kit/kit.h new file mode 100644 index 00000000..06a93cf0 --- /dev/null +++ b/abc70930/src/aig/kit/kit.h @@ -0,0 +1,594 @@ +/**CFile**************************************************************** + + FileName [kit.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kit.h,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __KIT_H__ +#define __KIT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "vec.h" +#include "extra.h" +#include "cloud.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Kit_Sop_t_ Kit_Sop_t; +struct Kit_Sop_t_ +{ + int nCubes; // the number of cubes + unsigned * pCubes; // the storage for cubes +}; + +typedef struct Kit_Edge_t_ Kit_Edge_t; +struct Kit_Edge_t_ +{ + unsigned fCompl : 1; // the complemented bit + unsigned Node : 30; // the decomposition node pointed by the edge +}; + +typedef struct Kit_Node_t_ Kit_Node_t; +struct Kit_Node_t_ +{ + Kit_Edge_t eEdge0; // the left child of the node + Kit_Edge_t eEdge1; // the right child of the node + // other info + void * pFunc; // the function of the node (BDD or AIG) + unsigned Level : 14; // the level of this node in the global AIG + // printing info + unsigned fNodeOr : 1; // marks the original OR node + unsigned fCompl0 : 1; // marks the original complemented edge + unsigned fCompl1 : 1; // marks the original complemented edge + // latch info + unsigned nLat0 : 5; // the number of latches on the first edge + unsigned nLat1 : 5; // the number of latches on the second edge + unsigned nLat2 : 5; // the number of latches on the output edge +}; + +typedef struct Kit_Graph_t_ Kit_Graph_t; +struct Kit_Graph_t_ +{ + int fConst; // marks the constant 1 graph + int nLeaves; // the number of leaves + int nSize; // the number of nodes (including the leaves) + int nCap; // the number of allocated nodes + Kit_Node_t * pNodes; // the array of leaves and internal nodes + Kit_Edge_t eRoot; // the pointer to the topmost node +}; + + +// DSD node types +typedef enum { + KIT_DSD_NONE = 0, // 0: unknown + KIT_DSD_CONST1, // 1: constant 1 + KIT_DSD_VAR, // 2: elementary variable + KIT_DSD_AND, // 3: multi-input AND + KIT_DSD_XOR, // 4: multi-input XOR + KIT_DSD_PRIME // 5: arbitrary function of 3+ variables +} Kit_Dsd_t; + +// DSD node +typedef struct Kit_DsdObj_t_ Kit_DsdObj_t; +struct Kit_DsdObj_t_ +{ + unsigned Id : 6; // the number of this node + unsigned Type : 3; // none, const, var, AND, XOR, MUX, PRIME + unsigned fMark : 1; // finished checking output + unsigned Offset : 8; // offset to the truth table + unsigned nRefs : 8; // offset to the truth table + unsigned nFans : 6; // the number of fanins of this node + unsigned char pFans[0]; // the fanin literals +}; + +// DSD network +typedef struct Kit_DsdNtk_t_ Kit_DsdNtk_t; +struct Kit_DsdNtk_t_ +{ + unsigned char nVars; // at most 16 (perhaps 18?) + unsigned char nNodesAlloc; // the number of allocated nodes (at most nVars) + unsigned char nNodes; // the number of nodes + unsigned char Root; // the root of the tree + unsigned * pMem; // memory for the truth tables (memory manager?) + unsigned * pSupps; // supports of the nodes + Kit_DsdObj_t** pNodes; // the nodes +}; + +// DSD manager +typedef struct Kit_DsdMan_t_ Kit_DsdMan_t; +struct Kit_DsdMan_t_ +{ + int nVars; // the maximum number of variables + int nWords; // the number of words in TTs + Vec_Ptr_t * vTtElems; // elementary truth tables + Vec_Ptr_t * vTtNodes; // the node truth tables + // BDD representation + CloudManager * dd; // BDD package + Vec_Ptr_t * vTtBdds; // the node truth tables + Vec_Int_t * vNodes; // temporary array for BDD nodes +}; + +static inline int Kit_DsdVar2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } +static inline int Kit_DsdLit2Var( int Lit ) { return Lit >> 1; } +static inline int Kit_DsdLitIsCompl( int Lit ) { return Lit & 1; } +static inline int Kit_DsdLitNot( int Lit ) { return Lit ^ 1; } +static inline int Kit_DsdLitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } +static inline int Kit_DsdLitRegular( int Lit ) { return Lit & 0xfe; } + +static inline unsigned Kit_DsdObjOffset( int nFans ) { return (nFans >> 2) + ((nFans & 3) > 0); } +static inline unsigned * Kit_DsdObjTruth( Kit_DsdObj_t * pObj ) { return pObj->Type == KIT_DSD_PRIME ? (unsigned *)pObj->pFans + pObj->Offset: NULL; } +static inline int Kit_DsdNtkObjNum( Kit_DsdNtk_t * pNtk ){ return pNtk->nVars + pNtk->nNodes; } +static inline Kit_DsdObj_t * Kit_DsdNtkObj( Kit_DsdNtk_t * pNtk, int Id ) { assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return Id < pNtk->nVars ? NULL : pNtk->pNodes[Id - pNtk->nVars]; } +static inline Kit_DsdObj_t * Kit_DsdNtkRoot( Kit_DsdNtk_t * pNtk ) { return Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(pNtk->Root) ); } +static inline int Kit_DsdLitIsLeaf( Kit_DsdNtk_t * pNtk, int Lit ) { int Id = Kit_DsdLit2Var(Lit); assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return Id < pNtk->nVars; } +static inline unsigned Kit_DsdLitSupport( Kit_DsdNtk_t * pNtk, int Lit ) { int Id = Kit_DsdLit2Var(Lit); assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return pNtk->pSupps? (Id < pNtk->nVars? (1 << Id) : pNtk->pSupps[Id - pNtk->nVars]) : 0; } + +#define Kit_DsdNtkForEachObj( pNtk, pObj, i ) \ + for ( i = 0; (i < (pNtk)->nNodes) && ((pObj) = (pNtk)->pNodes[i]); i++ ) +#define Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) \ + for ( i = 0; (i < (pObj)->nFans) && ((iLit) = (pObj)->pFans[i], 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define KIT_MIN(a,b) (((a) < (b))? (a) : (b)) +#define KIT_MAX(a,b) (((a) > (b))? (a) : (b)) +#define KIT_INFINITY (100000000) + +#ifndef ALLOC +#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#endif + +#ifndef FREE +#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#endif + +#ifndef REALLOC +#define REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) +#endif + +static inline int Kit_CubeHasLit( unsigned uCube, int i ) { return(uCube & (unsigned)(1< 0; } +static inline unsigned Kit_CubeSetLit( unsigned uCube, int i ) { return uCube | (unsigned)(1<> (32-nVar); } + +static inline int Kit_CubeIsMarked( unsigned uCube ) { return Kit_CubeHasLit( uCube, 31 ); } +static inline unsigned Kit_CubeMark( unsigned uCube ) { return Kit_CubeSetLit( uCube, 31 ); } +static inline unsigned Kit_CubeUnmark( unsigned uCube ) { return Kit_CubeRemLit( uCube, 31 ); } + +static inline int Kit_SopCubeNum( Kit_Sop_t * cSop ) { return cSop->nCubes; } +static inline unsigned Kit_SopCube( Kit_Sop_t * cSop, int i ) { return cSop->pCubes[i]; } +static inline void Kit_SopShrink( Kit_Sop_t * cSop, int nCubesNew ) { cSop->nCubes = nCubesNew; } +static inline void Kit_SopPushCube( Kit_Sop_t * cSop, unsigned uCube ) { cSop->pCubes[cSop->nCubes++] = uCube; } +static inline void Kit_SopWriteCube( Kit_Sop_t * cSop, unsigned uCube, int i ) { cSop->pCubes[i] = uCube; } + +static inline Kit_Edge_t Kit_EdgeCreate( int Node, int fCompl ) { Kit_Edge_t eEdge = { fCompl, Node }; return eEdge; } +static inline unsigned Kit_EdgeToInt( Kit_Edge_t eEdge ) { return (eEdge.Node << 1) | eEdge.fCompl; } +static inline Kit_Edge_t Kit_IntToEdge( unsigned Edge ) { return Kit_EdgeCreate( Edge >> 1, Edge & 1 ); } +static inline unsigned Kit_EdgeToInt_( Kit_Edge_t eEdge ) { return *(unsigned *)&eEdge; } +static inline Kit_Edge_t Kit_IntToEdge_( unsigned Edge ) { return *(Kit_Edge_t *)&Edge; } + +static inline int Kit_GraphIsConst( Kit_Graph_t * pGraph ) { return pGraph->fConst; } +static inline int Kit_GraphIsConst0( Kit_Graph_t * pGraph ) { return pGraph->fConst && pGraph->eRoot.fCompl; } +static inline int Kit_GraphIsConst1( Kit_Graph_t * pGraph ) { return pGraph->fConst && !pGraph->eRoot.fCompl; } +static inline int Kit_GraphIsComplement( Kit_Graph_t * pGraph ) { return pGraph->eRoot.fCompl; } +static inline int Kit_GraphIsVar( Kit_Graph_t * pGraph ) { return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; } +static inline void Kit_GraphComplement( Kit_Graph_t * pGraph ) { pGraph->eRoot.fCompl ^= 1; } +static inline void Kit_GraphSetRoot( Kit_Graph_t * pGraph, Kit_Edge_t eRoot ) { pGraph->eRoot = eRoot; } +static inline int Kit_GraphLeaveNum( Kit_Graph_t * pGraph ) { return pGraph->nLeaves; } +static inline int Kit_GraphNodeNum( Kit_Graph_t * pGraph ) { return pGraph->nSize - pGraph->nLeaves; } +static inline Kit_Node_t * Kit_GraphNode( Kit_Graph_t * pGraph, int i ) { return pGraph->pNodes + i; } +static inline Kit_Node_t * Kit_GraphNodeLast( Kit_Graph_t * pGraph ) { return pGraph->pNodes + pGraph->nSize - 1; } +static inline int Kit_GraphNodeInt( Kit_Graph_t * pGraph, Kit_Node_t * pNode ) { return pNode - pGraph->pNodes; } +static inline int Kit_GraphNodeIsVar( Kit_Graph_t * pGraph, Kit_Node_t * pNode ) { return Kit_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; } +static inline Kit_Node_t * Kit_GraphVar( Kit_Graph_t * pGraph ) { assert( Kit_GraphIsVar( pGraph ) ); return Kit_GraphNode( pGraph, pGraph->eRoot.Node ); } +static inline int Kit_GraphVarInt( Kit_Graph_t * pGraph ) { assert( Kit_GraphIsVar( pGraph ) ); return Kit_GraphNodeInt( pGraph, Kit_GraphVar(pGraph) ); } +static inline Kit_Node_t * Kit_GraphNodeFanin0( Kit_Graph_t * pGraph, Kit_Node_t * pNode ){ return Kit_GraphNodeIsVar(pGraph, pNode)? NULL : Kit_GraphNode(pGraph, pNode->eEdge0.Node); } +static inline Kit_Node_t * Kit_GraphNodeFanin1( Kit_Graph_t * pGraph, Kit_Node_t * pNode ){ return Kit_GraphNodeIsVar(pGraph, pNode)? NULL : Kit_GraphNode(pGraph, pNode->eEdge1.Node); } +static inline int Kit_GraphRootLevel( Kit_Graph_t * pGraph ) { return Kit_GraphNode(pGraph, pGraph->eRoot.Node)->Level; } + +static inline int Kit_Float2Int( float Val ) { return *((int *)&Val); } +static inline float Kit_Int2Float( int Num ) { return *((float *)&Num); } +static inline int Kit_BitWordNum( int nBits ) { return nBits/(8*sizeof(unsigned)) + ((nBits%(8*sizeof(unsigned))) > 0); } +static inline int Kit_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline unsigned Kit_BitMask( int nBits ) { assert( nBits <= 32 ); return ~((~(unsigned)0) << nBits); } + +static inline void Kit_TruthSetBit( unsigned * p, int Bit ) { p[Bit>>5] |= (1<<(Bit & 31)); } +static inline void Kit_TruthXorBit( unsigned * p, int Bit ) { p[Bit>>5] ^= (1<<(Bit & 31)); } +static inline int Kit_TruthHasBit( unsigned * p, int Bit ) { return (p[Bit>>5] & (1<<(Bit & 31))) > 0; } + +static inline int Kit_WordFindFirstBit( unsigned uWord ) +{ + int i; + for ( i = 0; i < 32; i++ ) + if ( uWord & (1 << i) ) + return i; + return -1; +} +static inline int Kit_WordHasOneBit( unsigned uWord ) +{ + return (uWord & (uWord - 1)) == 0; +} +static inline int Kit_WordCountOnes( unsigned uWord ) +{ + uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); + uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); + uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); + uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); + return (uWord & 0x0000FFFF) + (uWord>>16); +} +static inline int Kit_TruthCountOnes( unsigned * pIn, int nVars ) +{ + int w, Counter = 0; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + Counter += Kit_WordCountOnes(pIn[w]); + return Counter; +} +static inline int Kit_TruthFindFirstBit( unsigned * pIn, int nVars ) +{ + int w; + for ( w = 0; w < Kit_TruthWordNum(nVars); w++ ) + if ( pIn[w] ) + return 32*w + Kit_WordFindFirstBit(pIn[w]); + return -1; +} +static inline int Kit_TruthFindFirstZero( unsigned * pIn, int nVars ) +{ + int w; + for ( w = 0; w < Kit_TruthWordNum(nVars); w++ ) + if ( ~pIn[w] ) + return 32*w + Kit_WordFindFirstBit(~pIn[w]); + return -1; +} +static inline int Kit_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn0[w] != pIn1[w] ) + return 0; + return 1; +} +static inline int Kit_TruthIsOpposite( unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn0[w] != ~pIn1[w] ) + return 0; + return 1; +} +static inline int Kit_TruthIsEqualWithPhase( unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + if ( (pIn0[0] & 1) == (pIn1[0] & 1) ) + { + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn0[w] != pIn1[w] ) + return 0; + } + else + { + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn0[w] != ~pIn1[w] ) + return 0; + } + return 1; +} +static inline int Kit_TruthIsConst0( unsigned * pIn, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn[w] ) + return 0; + return 1; +} +static inline int Kit_TruthIsConst1( unsigned * pIn, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn[w] != ~(unsigned)0 ) + return 0; + return 1; +} +static inline int Kit_TruthIsImply( unsigned * pIn1, unsigned * pIn2, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn1[w] & ~pIn2[w] ) + return 0; + return 1; +} +static inline int Kit_TruthIsDisjoint( unsigned * pIn1, unsigned * pIn2, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn1[w] & pIn2[w] ) + return 0; + return 1; +} +static inline int Kit_TruthIsDisjoint3( unsigned * pIn1, unsigned * pIn2, unsigned * pIn3, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn1[w] & pIn2[w] & pIn3[w] ) + return 0; + return 1; +} +static inline void Kit_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn[w]; +} +static inline void Kit_TruthClear( unsigned * pOut, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = 0; +} +static inline void Kit_TruthFill( unsigned * pOut, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~(unsigned)0; +} +static inline void Kit_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~pIn[w]; +} +static inline void Kit_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] & pIn1[w]; +} +static inline void Kit_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] | pIn1[w]; +} +static inline void Kit_TruthXor( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] ^ pIn1[w]; +} +static inline void Kit_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] & ~pIn1[w]; +} +static inline void Kit_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~(pIn0[w] & pIn1[w]); +} +static inline void Kit_TruthAndPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 ) +{ + int w; + if ( fCompl0 && fCompl1 ) + { + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~(pIn0[w] | pIn1[w]); + } + else if ( fCompl0 && !fCompl1 ) + { + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~pIn0[w] & pIn1[w]; + } + else if ( !fCompl0 && fCompl1 ) + { + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] & ~pIn1[w]; + } + else // if ( !fCompl0 && !fCompl1 ) + { + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] & pIn1[w]; + } +} +static inline void Kit_TruthMux( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, unsigned * pCtrl, int nVars ) +{ + int w; + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = (pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]); +} +static inline void Kit_TruthMuxPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, unsigned * pCtrl, int nVars, int fComp0 ) +{ + int w; + if ( fComp0 ) + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = (~pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]); + else + for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = (pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]); +} +static inline void Kit_TruthIthVar( unsigned * pTruth, int nVars, int iVar ) +{ + unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + int k, nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5))); + if ( iVar < 5 ) + { + for ( k = 0; k < nWords; k++ ) + pTruth[k] = Masks[iVar]; + } + else + { + for ( k = 0; k < nWords; k++ ) + if ( k & (1 << (iVar-5)) ) + pTruth[k] = ~(unsigned)0; + else + pTruth[k] = 0; + } +} + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +#define Kit_SopForEachCube( cSop, uCube, i ) \ + for ( i = 0; (i < Kit_SopCubeNum(cSop)) && ((uCube) = Kit_SopCube(cSop, i)); i++ ) +#define Kit_CubeForEachLiteral( uCube, Lit, nLits, i ) \ + for ( i = 0; (i < (nLits)) && ((Lit) = Kit_CubeHasLit(uCube, i)); i++ ) + +#define Kit_GraphForEachLeaf( pGraph, pLeaf, i ) \ + for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Kit_GraphNode(pGraph, i)), 1); i++ ) +#define Kit_GraphForEachNode( pGraph, pAnd, i ) \ + for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Kit_GraphNode(pGraph, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== kitBdd.c ==========================================================*/ +extern DdNode * Kit_SopToBdd( DdManager * dd, Kit_Sop_t * cSop, int nVars ); +extern DdNode * Kit_GraphToBdd( DdManager * dd, Kit_Graph_t * pGraph ); +extern DdNode * Kit_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars, int fMSBonTop ); +/*=== kitCloud.c ==========================================================*/ +extern CloudNode * Kit_TruthToCloud( CloudManager * dd, unsigned * pTruth, int nVars ); +extern unsigned * Kit_CloudToTruth( Vec_Int_t * vNodes, int nVars, Vec_Ptr_t * vStore, int fInv ); +extern int Kit_CreateCloud( CloudManager * dd, CloudNode * pFunc, Vec_Int_t * vNodes ); +extern int Kit_CreateCloudFromTruth( CloudManager * dd, unsigned * pTruth, int nVars, Vec_Int_t * vNodes ); +extern unsigned * Kit_TruthCompose( CloudManager * dd, unsigned * pTruth, int nVars, unsigned ** pInputs, int nVarsAll, Vec_Ptr_t * vStore, Vec_Int_t * vNodes ); +extern void Kit_TruthCofSupports( Vec_Int_t * vBddDir, Vec_Int_t * vBddInv, int nVars, Vec_Int_t * vMemory, unsigned * puSupps ); +/*=== kitDsd.c ==========================================================*/ +extern Kit_DsdMan_t * Kit_DsdManAlloc( int nVars, int nNodes ); +extern void Kit_DsdManFree( Kit_DsdMan_t * p ); +extern Kit_DsdNtk_t * Kit_DsdDeriveNtk( unsigned * pTruth, int nVars, int nLutSize ); +extern unsigned * Kit_DsdTruthCompute( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk ); +extern void Kit_DsdTruth( Kit_DsdNtk_t * pNtk, unsigned * pTruthRes ); +extern void Kit_DsdTruthPartial( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned * pTruthRes, unsigned uSupp ); +extern void Kit_DsdTruthPartialTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthCo, unsigned * pTruthDec ); +extern void Kit_DsdPrint( FILE * pFile, Kit_DsdNtk_t * pNtk ); +extern void Kit_DsdPrintExpanded( Kit_DsdNtk_t * pNtk ); +extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); +extern Kit_DsdNtk_t * Kit_DsdDecompose( unsigned * pTruth, int nVars ); +extern Kit_DsdNtk_t * Kit_DsdDecomposeExpand( unsigned * pTruth, int nVars ); +extern Kit_DsdNtk_t * Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nDecMux ); +extern void Kit_DsdVerify( Kit_DsdNtk_t * pNtk, unsigned * pTruth, int nVars ); +extern void Kit_DsdNtkFree( Kit_DsdNtk_t * pNtk ); +extern int Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk ); +extern unsigned Kit_DsdNonDsdSupports( Kit_DsdNtk_t * pNtk ); +extern unsigned Kit_DsdGetSupports( Kit_DsdNtk_t * p ); +extern Kit_DsdNtk_t * Kit_DsdExpand( Kit_DsdNtk_t * p ); +extern Kit_DsdNtk_t * Kit_DsdShrink( Kit_DsdNtk_t * p, int pPrios[] ); +extern void Kit_DsdRotate( Kit_DsdNtk_t * p, int pFreqs[] ); +extern int Kit_DsdCofactoring( unsigned * pTruth, int nVars, int * pCofVars, int nLimit, int fVerbose ); +/*=== kitFactor.c ==========================================================*/ +extern Kit_Graph_t * Kit_SopFactor( Vec_Int_t * vCover, int fCompl, int nVars, Vec_Int_t * vMemory ); +/*=== kitGraph.c ==========================================================*/ +extern Kit_Graph_t * Kit_GraphCreate( int nLeaves ); +extern Kit_Graph_t * Kit_GraphCreateConst0(); +extern Kit_Graph_t * Kit_GraphCreateConst1(); +extern Kit_Graph_t * Kit_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ); +extern void Kit_GraphFree( Kit_Graph_t * pGraph ); +extern Kit_Node_t * Kit_GraphAppendNode( Kit_Graph_t * pGraph ); +extern Kit_Edge_t Kit_GraphAddNodeAnd( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ); +extern Kit_Edge_t Kit_GraphAddNodeOr( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ); +extern Kit_Edge_t Kit_GraphAddNodeXor( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1, int Type ); +extern Kit_Edge_t Kit_GraphAddNodeMux( Kit_Graph_t * pGraph, Kit_Edge_t eEdgeC, Kit_Edge_t eEdgeT, Kit_Edge_t eEdgeE, int Type ); +extern unsigned Kit_GraphToTruth( Kit_Graph_t * pGraph ); +extern Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); +extern int Kit_GraphLeafDepth_rec( Kit_Graph_t * pGraph, Kit_Node_t * pNode, Kit_Node_t * pLeaf ); +/*=== kitHop.c ==========================================================*/ +//extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); +//extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); +//extern Hop_Obj_t * Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory ); +/*=== kitIsop.c ==========================================================*/ +extern int Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth ); +/*=== kitSop.c ==========================================================*/ +extern void Kit_SopCreate( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory ); +extern void Kit_SopCreateInverse( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory ); +extern void Kit_SopDup( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ); +extern void Kit_SopDivideByLiteralQuo( Kit_Sop_t * cSop, int iLit ); +extern void Kit_SopDivideByCube( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ); +extern void Kit_SopDivideInternal( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ); +extern void Kit_SopMakeCubeFree( Kit_Sop_t * cSop ); +extern int Kit_SopIsCubeFree( Kit_Sop_t * cSop ); +extern void Kit_SopCommonCubeCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ); +extern int Kit_SopAnyLiteral( Kit_Sop_t * cSop, int nLits ); +extern int Kit_SopDivisor( Kit_Sop_t * cResult, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ); +extern void Kit_SopBestLiteralCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, unsigned uCube, int nLits, Vec_Int_t * vMemory ); +/*=== kitTruth.c ==========================================================*/ +extern void Kit_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start ); +extern void Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ); +extern void Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ); +extern int Kit_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ); +extern int Kit_TruthSupportSize( unsigned * pTruth, int nVars ); +extern unsigned Kit_TruthSupport( unsigned * pTruth, int nVars ); +extern void Kit_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ); +extern void Kit_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ); +extern void Kit_TruthCofactor0New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ); +extern void Kit_TruthCofactor1New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ); +extern void Kit_TruthExist( unsigned * pTruth, int nVars, int iVar ); +extern void Kit_TruthExistNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ); +extern void Kit_TruthExistSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ); +extern void Kit_TruthForall( unsigned * pTruth, int nVars, int iVar ); +extern void Kit_TruthForallNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ); +extern void Kit_TruthForallSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ); +extern void Kit_TruthUniqueNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ); +extern void Kit_TruthMuxVar( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ); +extern void Kit_TruthMuxVarPhase( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar, int fCompl0 ); +extern void Kit_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ); +extern int Kit_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ); +extern int Kit_TruthBestCofVar( unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 ); +extern void Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ); +extern void Kit_TruthCountOnesInCofsSlow( unsigned * pTruth, int nVars, short * pStore, unsigned * pAux ); +extern unsigned Kit_TruthHash( unsigned * pIn, int nWords ); +extern unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ); +extern char * Kit_TruthDumpToFile( unsigned * pTruth, int nVars, int nFile ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/kit/kitAig.c b/abc70930/src/aig/kit/kitAig.c new file mode 100644 index 00000000..83012a8c --- /dev/null +++ b/abc70930/src/aig/kit/kitAig.c @@ -0,0 +1,121 @@ +/**CFile**************************************************************** + + FileName [kitAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [Procedures involving AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kitAig.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" +#include "aig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Kit_GraphToAigInternal( Aig_Man_t * pMan, Kit_Graph_t * pGraph ) +{ + Kit_Node_t * pNode = NULL; + Aig_Obj_t * pAnd0, * pAnd1; + int i; + // check for constant function + if ( Kit_GraphIsConst(pGraph) ) + return Aig_NotCond( Aig_ManConst1(pMan), Kit_GraphIsComplement(pGraph) ); + // check for a literal + if ( Kit_GraphIsVar(pGraph) ) + return Aig_NotCond( Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Kit_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Aig_NotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Aig_NotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Aig_And( pMan, pAnd0, pAnd1 ); + } + // complement the result if necessary + return Aig_NotCond( pNode->pFunc, Kit_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Kit_GraphToAig( Aig_Man_t * pMan, Aig_Obj_t ** pFanins, Kit_Graph_t * pGraph ) +{ + Kit_Node_t * pNode = NULL; + int i; + // collect the fanins + Kit_GraphForEachLeaf( pGraph, pNode, i ) + pNode->pFunc = pFanins[i]; + // perform strashing + return Kit_GraphToAigInternal( pMan, pGraph ); +} + +/**Function************************************************************* + + Synopsis [Strashed onen logic nodes using its truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Kit_TruthToAig( Aig_Man_t * pMan, Aig_Obj_t ** pFanins, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) +{ + Aig_Obj_t * pObj; + Kit_Graph_t * pGraph; + // transform truth table into the decomposition tree + if ( vMemory == NULL ) + { + vMemory = Vec_IntAlloc( 0 ); + pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); + Vec_IntFree( vMemory ); + } + else + pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); + // derive the AIG for the decomposition tree + pObj = Kit_GraphToAig( pMan, pFanins, pGraph ); + Kit_GraphFree( pGraph ); + return pObj; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/kit/kitBdd.c b/abc70930/src/aig/kit/kitBdd.c new file mode 100644 index 00000000..9c8d4f7a --- /dev/null +++ b/abc70930/src/aig/kit/kitBdd.c @@ -0,0 +1,231 @@ +/**CFile**************************************************************** + + FileName [kitBdd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [Procedures involving BDDs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kitBdd.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the BDD for the given SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Kit_SopToBdd( DdManager * dd, Kit_Sop_t * cSop, int nVars ) +{ + DdNode * bSum, * bCube, * bTemp, * bVar; + unsigned uCube; + int Value, i, v; + assert( nVars < 16 ); + // start the cover + bSum = Cudd_ReadLogicZero(dd); Cudd_Ref( bSum ); + // check the logic function of the node + Kit_SopForEachCube( cSop, uCube, i ) + { + bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); + for ( v = 0; v < nVars; v++ ) + { + Value = ((uCube >> 2*v) & 3); + if ( Value == 1 ) + bVar = Cudd_Not( Cudd_bddIthVar( dd, v ) ); + else if ( Value == 2 ) + bVar = Cudd_bddIthVar( dd, v ); + else + continue; + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + bSum = Cudd_bddOr( dd, bTemp = bSum, bCube ); + Cudd_Ref( bSum ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + // complement the result if necessary + Cudd_Deref( bSum ); + return bSum; +} + +/**Function************************************************************* + + Synopsis [Converts graph to BDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Kit_GraphToBdd( DdManager * dd, Kit_Graph_t * pGraph ) +{ + DdNode * bFunc, * bFunc0, * bFunc1; + Kit_Node_t * pNode; + int i; + + // sanity checks + assert( Kit_GraphLeaveNum(pGraph) >= 0 ); + assert( Kit_GraphLeaveNum(pGraph) <= pGraph->nSize ); + + // check for constant function + if ( Kit_GraphIsConst(pGraph) ) + return Cudd_NotCond( b1, Kit_GraphIsComplement(pGraph) ); + // check for a literal + if ( Kit_GraphIsVar(pGraph) ) + return Cudd_NotCond( Cudd_bddIthVar(dd, Kit_GraphVarInt(pGraph)), Kit_GraphIsComplement(pGraph) ); + + // assign the elementary variables + Kit_GraphForEachLeaf( pGraph, pNode, i ) + pNode->pFunc = Cudd_bddIthVar( dd, i ); + + // compute the function for each internal node + Kit_GraphForEachNode( pGraph, pNode, i ) + { + bFunc0 = Cudd_NotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + bFunc1 = Cudd_NotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( pNode->pFunc ); + } + + // deref the intermediate results + bFunc = pNode->pFunc; Cudd_Ref( bFunc ); + Kit_GraphForEachNode( pGraph, pNode, i ) + Cudd_RecursiveDeref( dd, pNode->pFunc ); + Cudd_Deref( bFunc ); + + // complement the result if necessary + return Cudd_NotCond( bFunc, Kit_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Kit_TruthToBdd_rec( DdManager * dd, unsigned * pTruth, int iBit, int nVars, int nVarsTotal, int fMSBonTop ) +{ + DdNode * bF0, * bF1, * bF; + int Var; + if ( nVars <= 5 ) + { + unsigned uTruth, uMask; + uMask = ((~(unsigned)0) >> (32 - (1<>5] >> (iBit&31)) & uMask; + if ( uTruth == 0 ) + return b0; + if ( uTruth == uMask ) + return b1; + } + // find the variable to use + Var = fMSBonTop? nVarsTotal-nVars : nVars-1; + // other special cases can be added + bF0 = Kit_TruthToBdd_rec( dd, pTruth, iBit, nVars-1, nVarsTotal, fMSBonTop ); Cudd_Ref( bF0 ); + bF1 = Kit_TruthToBdd_rec( dd, pTruth, iBit+(1<<(nVars-1)), nVars-1, nVarsTotal, fMSBonTop ); Cudd_Ref( bF1 ); + bF = Cudd_bddIte( dd, dd->vars[Var], bF1, bF0 ); Cudd_Ref( bF ); + Cudd_RecursiveDeref( dd, bF0 ); + Cudd_RecursiveDeref( dd, bF1 ); + Cudd_Deref( bF ); + return bF; +} + +/**Function************************************************************* + + Synopsis [Compute BDD corresponding to the truth table.] + + Description [If truth table has N vars, the BDD depends on N topmost + variables of the BDD manager. The most significant variable of the table + is encoded by the topmost variable of the manager. BDD construction is + efficient in this case because BDD is constructed one node at a time, + by simply adding BDD nodes on top of existent BDD nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Kit_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars, int fMSBonTop ) +{ + return Kit_TruthToBdd_rec( dd, pTruth, 0, nVars, nVars, fMSBonTop ); +} + +/**Function************************************************************* + + Synopsis [Verifies that the factoring is correct.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_SopFactorVerify( Vec_Int_t * vCover, Kit_Graph_t * pFForm, int nVars ) +{ + static DdManager * dd = NULL; + Kit_Sop_t Sop, * cSop = &Sop; + DdNode * bFunc1, * bFunc2; + Vec_Int_t * vMemory; + int RetValue; + // get the manager + if ( dd == NULL ) + dd = Cudd_Init( 16, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + // derive SOP + vMemory = Vec_IntAlloc( Vec_IntSize(vCover) ); + Kit_SopCreate( cSop, vCover, nVars, vMemory ); + // get the functions + bFunc1 = Kit_SopToBdd( dd, cSop, nVars ); Cudd_Ref( bFunc1 ); + bFunc2 = Kit_GraphToBdd( dd, pFForm ); Cudd_Ref( bFunc2 ); +//Extra_bddPrint( dd, bFunc1 ); printf("\n"); +//Extra_bddPrint( dd, bFunc2 ); printf("\n"); + RetValue = (bFunc1 == bFunc2); + if ( bFunc1 != bFunc2 ) + { + int s; + Extra_bddPrint( dd, bFunc1 ); printf("\n"); + Extra_bddPrint( dd, bFunc2 ); printf("\n"); + s = 0; + } + Cudd_RecursiveDeref( dd, bFunc1 ); + Cudd_RecursiveDeref( dd, bFunc2 ); + Vec_IntFree( vMemory ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/kit/kitCloud.c b/abc70930/src/aig/kit/kitCloud.c new file mode 100644 index 00000000..7b160fea --- /dev/null +++ b/abc70930/src/aig/kit/kitCloud.c @@ -0,0 +1,368 @@ +/**CFile**************************************************************** + + FileName [kitCloud.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [Procedures using BDD package CLOUD.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kitCloud.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// internal representation of the function to be decomposed +typedef struct Kit_Mux_t_ Kit_Mux_t; +struct Kit_Mux_t_ +{ + unsigned v : 5; // variable + unsigned t : 12; // then edge + unsigned e : 12; // else edge + unsigned c : 1; // complemented attr of else edge + unsigned i : 1; // complemented attr of top node +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derive BDD from the truth table for 5 variable functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +CloudNode * Kit_TruthToCloud5_rec( CloudManager * dd, unsigned uTruth, int nVars, int nVarsAll ) +{ + static unsigned uVars[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + CloudNode * pCof0, * pCof1; + unsigned uCof0, uCof1; + assert( nVars <= 5 ); + if ( uTruth == 0 ) + return dd->zero; + if ( uTruth == ~0 ) + return dd->one; + if ( nVars == 1 ) + { + if ( uTruth == uVars[0] ) + return dd->vars[nVarsAll-1]; + if ( uTruth == ~uVars[0] ) + return Cloud_Not(dd->vars[nVarsAll-1]); + assert( 0 ); + } +// Count++; + assert( nVars > 1 ); + uCof0 = uTruth & ~uVars[nVars-1]; + uCof1 = uTruth & uVars[nVars-1]; + uCof0 |= uCof0 << (1<<(nVars-1)); + uCof1 |= uCof1 >> (1<<(nVars-1)); + if ( uCof0 == uCof1 ) + return Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll ); + if ( uCof0 == ~uCof1 ) + { + pCof0 = Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll ); + pCof1 = Cloud_Not( pCof0 ); + } + else + { + pCof0 = Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll ); + pCof1 = Kit_TruthToCloud5_rec( dd, uCof1, nVars - 1, nVarsAll ); + } + return Cloud_MakeNode( dd, nVarsAll - nVars, pCof1, pCof0 ); +} + +/**Function******************************************************************** + + Synopsis [Compute BDD for the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +CloudNode * Kit_TruthToCloud_rec( CloudManager * dd, unsigned * pTruth, int nVars, int nVarsAll ) +{ + CloudNode * pCof0, * pCof1; + unsigned * pTruth0, * pTruth1; + if ( nVars <= 5 ) + return Kit_TruthToCloud5_rec( dd, pTruth[0], nVars, nVarsAll ); + if ( Kit_TruthIsConst0(pTruth, nVars) ) + return dd->zero; + if ( Kit_TruthIsConst1(pTruth, nVars) ) + return dd->one; +// Count++; + pTruth0 = pTruth; + pTruth1 = pTruth + Kit_TruthWordNum(nVars-1); + if ( Kit_TruthIsEqual( pTruth0, pTruth1, nVars - 1 ) ) + return Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll ); + if ( Kit_TruthIsOpposite( pTruth0, pTruth1, nVars - 1 ) ) + { + pCof0 = Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll ); + pCof1 = Cloud_Not( pCof0 ); + } + else + { + pCof0 = Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll ); + pCof1 = Kit_TruthToCloud_rec( dd, pTruth1, nVars - 1, nVarsAll ); + } + return Cloud_MakeNode( dd, nVarsAll - nVars, pCof1, pCof0 ); +} + +/**Function******************************************************************** + + Synopsis [Compute BDD for the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +CloudNode * Kit_TruthToCloud( CloudManager * dd, unsigned * pTruth, int nVars ) +{ + CloudNode * pRes; + pRes = Kit_TruthToCloud_rec( dd, pTruth, nVars, nVars ); +// printf( "%d/%d ", Count, Cloud_DagSize(dd, pRes) ); + return pRes; +} + +/**Function******************************************************************** + + Synopsis [Transforms the array of BDDs into the integer array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Kit_CreateCloud( CloudManager * dd, CloudNode * pFunc, Vec_Int_t * vNodes ) +{ + Kit_Mux_t Mux; + int nNodes, i; + // collect BDD nodes + nNodes = Cloud_DagCollect( dd, pFunc ); + if ( nNodes >= (1<<12) ) // because in Kit_Mux_t edge is 12 bit + return 0; + assert( nNodes == Cloud_DagSize( dd, pFunc ) ); + assert( nNodes < dd->nNodesLimit ); + Vec_IntClear( vNodes ); + Vec_IntPush( vNodes, 0 ); // const1 node + dd->ppNodes[0]->s = 0; + for ( i = 1; i < nNodes; i++ ) + { + dd->ppNodes[i]->s = i; + Mux.v = dd->ppNodes[i]->v; + Mux.t = dd->ppNodes[i]->t->s; + Mux.e = Cloud_Regular(dd->ppNodes[i]->e)->s; + Mux.c = Cloud_IsComplement(dd->ppNodes[i]->e); + Mux.i = (i == nNodes - 1)? Cloud_IsComplement(pFunc) : 0; + // put the MUX into the array + Vec_IntPush( vNodes, *((int *)&Mux) ); + } + assert( Vec_IntSize(vNodes) == nNodes ); + // reset signatures + for ( i = 0; i < nNodes; i++ ) + dd->ppNodes[i]->s = dd->nSignCur; + return 1; +} + +/**Function******************************************************************** + + Synopsis [Transforms the array of BDDs into the integer array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Kit_CreateCloudFromTruth( CloudManager * dd, unsigned * pTruth, int nVars, Vec_Int_t * vNodes ) +{ + CloudNode * pFunc; + Cloud_Restart( dd ); + pFunc = Kit_TruthToCloud( dd, pTruth, nVars ); + Vec_IntClear( vNodes ); + return Kit_CreateCloud( dd, pFunc, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Computes composition of truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Kit_CloudToTruth( Vec_Int_t * vNodes, int nVars, Vec_Ptr_t * vStore, int fInv ) +{ + unsigned * pThis, * pFan0, * pFan1; + Kit_Mux_t Mux; + int i, Entry; + assert( Vec_IntSize(vNodes) <= Vec_PtrSize(vStore) ); + pThis = Vec_PtrEntry( vStore, 0 ); + Kit_TruthFill( pThis, nVars ); + Vec_IntForEachEntryStart( vNodes, Entry, i, 1 ) + { + Mux = *((Kit_Mux_t *)&Entry); + assert( (int)Mux.e < i && (int)Mux.t < i && (int)Mux.v < nVars ); + pFan0 = Vec_PtrEntry( vStore, Mux.e ); + pFan1 = Vec_PtrEntry( vStore, Mux.t ); + pThis = Vec_PtrEntry( vStore, i ); + Kit_TruthMuxVarPhase( pThis, pFan0, pFan1, nVars, fInv? Mux.v : nVars-1-Mux.v, Mux.c ); + } + // complement the result + if ( Mux.i ) + Kit_TruthNot( pThis, pThis, nVars ); + return pThis; +} + +/**Function************************************************************* + + Synopsis [Computes composition of truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Kit_TruthCompose( CloudManager * dd, unsigned * pTruth, int nVars, + unsigned ** pInputs, int nVarsAll, Vec_Ptr_t * vStore, Vec_Int_t * vNodes ) +{ + CloudNode * pFunc; + unsigned * pThis, * pFan0, * pFan1; + Kit_Mux_t Mux; + int i, Entry, RetValue; + // derive BDD from truth table + Cloud_Restart( dd ); + pFunc = Kit_TruthToCloud( dd, pTruth, nVars ); + // convert it into nodes + RetValue = Kit_CreateCloud( dd, pFunc, vNodes ); + if ( RetValue == 0 ) + printf( "Kit_TruthCompose(): Internal failure!!!\n" ); + // verify the result +// pFan0 = Kit_CloudToTruth( vNodes, nVars, vStore, 0 ); +// if ( !Kit_TruthIsEqual( pTruth, pFan0, nVars ) ) +// printf( "Failed!\n" ); + // compute truth table from the BDD + assert( Vec_IntSize(vNodes) <= Vec_PtrSize(vStore) ); + pThis = Vec_PtrEntry( vStore, 0 ); + Kit_TruthFill( pThis, nVarsAll ); + Vec_IntForEachEntryStart( vNodes, Entry, i, 1 ) + { + Mux = *((Kit_Mux_t *)&Entry); + pFan0 = Vec_PtrEntry( vStore, Mux.e ); + pFan1 = Vec_PtrEntry( vStore, Mux.t ); + pThis = Vec_PtrEntry( vStore, i ); + Kit_TruthMuxPhase( pThis, pFan0, pFan1, pInputs[nVars-1-Mux.v], nVarsAll, Mux.c ); + } + // complement the result + if ( Mux.i ) + Kit_TruthNot( pThis, pThis, nVarsAll ); + return pThis; +} + +/**Function******************************************************************** + + Synopsis [Compute BDD for the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Kit_TruthCofSupports( Vec_Int_t * vBddDir, Vec_Int_t * vBddInv, int nVars, Vec_Int_t * vMemory, unsigned * puSupps ) +{ + Kit_Mux_t Mux; + unsigned * puSuppAll, * pThis, * pFan0, * pFan1; + int i, v, Var, Entry, nSupps; + nSupps = 2 * nVars; + + // extend storage + if ( Vec_IntSize( vMemory ) < nSupps * Vec_IntSize(vBddDir) ) + Vec_IntGrow( vMemory, nSupps * Vec_IntSize(vBddDir) ); + puSuppAll = Vec_IntArray( vMemory ); + // clear storage for the const node + memset( puSuppAll, 0, sizeof(unsigned) * nSupps ); + // compute supports from nodes + Vec_IntForEachEntryStart( vBddDir, Entry, i, 1 ) + { + Mux = *((Kit_Mux_t *)&Entry); + Var = nVars - 1 - Mux.v; + pFan0 = puSuppAll + nSupps * Mux.e; + pFan1 = puSuppAll + nSupps * Mux.t; + pThis = puSuppAll + nSupps * i; + for ( v = 0; v < nSupps; v++ ) + pThis[v] = pFan0[v] | pFan1[v] | (1<nVars = nVars; + p->nWords = Kit_TruthWordNum( p->nVars ); + p->vTtElems = Vec_PtrAllocTruthTables( p->nVars ); + p->vTtNodes = Vec_PtrAllocSimInfo( nNodes, p->nWords ); + p->dd = Cloud_Init( 16, 14 ); + p->vTtBdds = Vec_PtrAllocSimInfo( (1<<12), p->nWords ); + p->vNodes = Vec_IntAlloc( 512 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the DSD manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdManFree( Kit_DsdMan_t * p ) +{ + Cloud_Quit( p->dd ); + Vec_IntFree( p->vNodes ); + Vec_PtrFree( p->vTtBdds ); + Vec_PtrFree( p->vTtElems ); + Vec_PtrFree( p->vTtNodes ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Allocates the DSD node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdObj_t * Kit_DsdObjAlloc( Kit_DsdNtk_t * pNtk, Kit_Dsd_t Type, int nFans ) +{ + Kit_DsdObj_t * pObj; + int nSize = sizeof(Kit_DsdObj_t) + sizeof(unsigned) * (Kit_DsdObjOffset(nFans) + (Type == KIT_DSD_PRIME) * Kit_TruthWordNum(nFans)); + pObj = (Kit_DsdObj_t *)ALLOC( char, nSize ); + memset( pObj, 0, nSize ); + pObj->Id = pNtk->nVars + pNtk->nNodes; + pObj->Type = Type; + pObj->nFans = nFans; + pObj->Offset = Kit_DsdObjOffset( nFans ); + // add the object + if ( pNtk->nNodes == pNtk->nNodesAlloc ) + { + pNtk->nNodesAlloc *= 2; + pNtk->pNodes = REALLOC( Kit_DsdObj_t *, pNtk->pNodes, pNtk->nNodesAlloc ); + } + assert( pNtk->nNodes < pNtk->nNodesAlloc ); + pNtk->pNodes[pNtk->nNodes++] = pObj; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Deallocates the DSD node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdObjFree( Kit_DsdNtk_t * p, Kit_DsdObj_t * pObj ) +{ + free( pObj ); +} + +/**Function************************************************************* + + Synopsis [Allocates the DSD network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdNtk_t * Kit_DsdNtkAlloc( int nVars ) +{ + Kit_DsdNtk_t * pNtk; + pNtk = ALLOC( Kit_DsdNtk_t, 1 ); + memset( pNtk, 0, sizeof(Kit_DsdNtk_t) ); + pNtk->pNodes = ALLOC( Kit_DsdObj_t *, nVars ); + pNtk->nVars = nVars; + pNtk->nNodesAlloc = nVars; + pNtk->pMem = ALLOC( unsigned, 6 * Kit_TruthWordNum(nVars) ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Deallocate the DSD network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdNtkFree( Kit_DsdNtk_t * pNtk ) +{ + Kit_DsdObj_t * pObj; + unsigned i; + Kit_DsdNtkForEachObj( pNtk, pObj, i ) + free( pObj ); + FREE( pNtk->pSupps ); + free( pNtk->pNodes ); + free( pNtk->pMem ); + free( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Prints the hex unsigned into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdPrintHex( FILE * pFile, unsigned * pTruth, int nFans ) +{ + int nDigits, Digit, k; + nDigits = (1 << nFans) / 4; + for ( k = nDigits - 1; k >= 0; k-- ) + { + Digit = ((pTruth[k/8] >> ((k%8) * 4)) & 15); + if ( Digit < 10 ) + fprintf( pFile, "%d", Digit ); + else + fprintf( pFile, "%c", 'A' + Digit-10 ); + } +} + +/**Function************************************************************* + + Synopsis [Recursively print the DSD formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdPrint_rec( FILE * pFile, Kit_DsdNtk_t * pNtk, int Id ) +{ + Kit_DsdObj_t * pObj; + unsigned iLit, i; + char Symbol; + + pObj = Kit_DsdNtkObj( pNtk, Id ); + if ( pObj == NULL ) + { + assert( Id < pNtk->nVars ); + fprintf( pFile, "%c", 'a' + Id ); + return; + } + + if ( pObj->Type == KIT_DSD_CONST1 ) + { + assert( pObj->nFans == 0 ); + fprintf( pFile, "Const1" ); + return; + } + + if ( pObj->Type == KIT_DSD_VAR ) + assert( pObj->nFans == 1 ); + + if ( pObj->Type == KIT_DSD_AND ) + Symbol = '*'; + else if ( pObj->Type == KIT_DSD_XOR ) + Symbol = '+'; + else + Symbol = ','; + + if ( pObj->Type == KIT_DSD_PRIME ) + Kit_DsdPrintHex( stdout, Kit_DsdObjTruth(pObj), pObj->nFans ); + + fprintf( pFile, "(" ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + if ( Kit_DsdLitIsCompl(iLit) ) + fprintf( pFile, "!" ); + Kit_DsdPrint_rec( pFile, pNtk, Kit_DsdLit2Var(iLit) ); + if ( i < pObj->nFans - 1 ) + fprintf( pFile, "%c", Symbol ); + } + fprintf( pFile, ")" ); +} + +/**Function************************************************************* + + Synopsis [Print the DSD formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdPrint( FILE * pFile, Kit_DsdNtk_t * pNtk ) +{ + fprintf( pFile, "F = " ); + if ( Kit_DsdLitIsCompl(pNtk->Root) ) + fprintf( pFile, "!" ); + Kit_DsdPrint_rec( pFile, pNtk, Kit_DsdLit2Var(pNtk->Root) ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Print the DSD formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdPrintExpanded( Kit_DsdNtk_t * pNtk ) +{ + Kit_DsdNtk_t * pTemp; + pTemp = Kit_DsdExpand( pNtk ); + Kit_DsdPrint( stdout, pTemp ); + Kit_DsdNtkFree( pTemp ); +} + +/**Function************************************************************* + + Synopsis [Print the DSD formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ) +{ + Kit_DsdNtk_t * pTemp; + pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 ); + Kit_DsdVerify( pTemp, pTruth, nVars ); + Kit_DsdPrintExpanded( pTemp ); + Kit_DsdNtkFree( pTemp ); +} + +/**Function************************************************************* + + Synopsis [Derives the truth table of the DSD node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Kit_DsdTruthComputeNode_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id ) +{ + Kit_DsdObj_t * pObj; + unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp; + unsigned i, iLit, fCompl; +// unsigned m, nMints, * pTruthPrime, * pTruthMint; + + // get the node with this ID + pObj = Kit_DsdNtkObj( pNtk, Id ); + pTruthRes = Vec_PtrEntry( p->vTtNodes, Id ); + + // special case: literal of an internal node + if ( pObj == NULL ) + { + assert( Id < pNtk->nVars ); + return pTruthRes; + } + + // constant node + if ( pObj->Type == KIT_DSD_CONST1 ) + { + assert( pObj->nFans == 0 ); + Kit_TruthFill( pTruthRes, pNtk->nVars ); + return pTruthRes; + } + + // elementary variable node + if ( pObj->Type == KIT_DSD_VAR ) + { + assert( pObj->nFans == 1 ); + iLit = pObj->pFans[0]; + pTruthFans[0] = Kit_DsdTruthComputeNode_rec( p, pNtk, Kit_DsdLit2Var(iLit) ); + if ( Kit_DsdLitIsCompl(iLit) ) + Kit_TruthNot( pTruthRes, pTruthFans[0], pNtk->nVars ); + else + Kit_TruthCopy( pTruthRes, pTruthFans[0], pNtk->nVars ); + return pTruthRes; + } + + // collect the truth tables of the fanins + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + pTruthFans[i] = Kit_DsdTruthComputeNode_rec( p, pNtk, Kit_DsdLit2Var(iLit) ); + // create the truth table + + // simple gates + if ( pObj->Type == KIT_DSD_AND ) + { + Kit_TruthFill( pTruthRes, pNtk->nVars ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Kit_DsdLitIsCompl(iLit) ); + return pTruthRes; + } + if ( pObj->Type == KIT_DSD_XOR ) + { + Kit_TruthClear( pTruthRes, pNtk->nVars ); + fCompl = 0; + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); + fCompl ^= Kit_DsdLitIsCompl(iLit); + } + if ( fCompl ) + Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); + return pTruthRes; + } + assert( pObj->Type == KIT_DSD_PRIME ); +/* + // get the truth table of the prime node + pTruthPrime = Kit_DsdObjTruth( pObj ); + // get storage for the temporary minterm + pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); + + // go through the minterms + nMints = (1 << pObj->nFans); + Kit_TruthClear( pTruthRes, pNtk->nVars ); + for ( m = 0; m < nMints; m++ ) + { + if ( !Kit_TruthHasBit(pTruthPrime, m) ) + continue; + Kit_TruthFill( pTruthMint, pNtk->nVars ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<nVars ); + } +*/ + pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); + Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); + return pTruthRes; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table of the DSD network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Kit_DsdTruthCompute( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk ) +{ + unsigned * pTruthRes; + int i; + // assign elementary truth ables + assert( pNtk->nVars <= p->nVars ); + for ( i = 0; i < (int)pNtk->nVars; i++ ) + Kit_TruthCopy( Vec_PtrEntry(p->vTtNodes, i), Vec_PtrEntry(p->vTtElems, i), p->nVars ); + // compute truth table for each node + pTruthRes = Kit_DsdTruthComputeNode_rec( p, pNtk, Kit_DsdLit2Var(pNtk->Root) ); + // complement the truth table if needed + if ( Kit_DsdLitIsCompl(pNtk->Root) ) + Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); + return pTruthRes; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table of the DSD node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Kit_DsdTruthComputeNodeOne_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id, unsigned uSupp ) +{ + Kit_DsdObj_t * pObj; + unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp; + unsigned i, iLit, fCompl, nPartial = 0; +// unsigned m, nMints, * pTruthPrime, * pTruthMint; + + // get the node with this ID + pObj = Kit_DsdNtkObj( pNtk, Id ); + pTruthRes = Vec_PtrEntry( p->vTtNodes, Id ); + + // special case: literal of an internal node + if ( pObj == NULL ) + { + assert( Id < pNtk->nVars ); + assert( !uSupp || uSupp != (uSupp & ~(1<Type == KIT_DSD_CONST1 ) + { + assert( pObj->nFans == 0 ); + Kit_TruthFill( pTruthRes, pNtk->nVars ); + return pTruthRes; + } + + // elementary variable node + if ( pObj->Type == KIT_DSD_VAR ) + { + assert( pObj->nFans == 1 ); + iLit = pObj->pFans[0]; + assert( Kit_DsdLitIsLeaf( pNtk, iLit ) ); + pTruthFans[0] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(iLit), uSupp ); + if ( Kit_DsdLitIsCompl(iLit) ) + Kit_TruthNot( pTruthRes, pTruthFans[0], pNtk->nVars ); + else + Kit_TruthCopy( pTruthRes, pTruthFans[0], pNtk->nVars ); + return pTruthRes; + } + + // collect the truth tables of the fanins + if ( uSupp ) + { + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + if ( uSupp != (uSupp & ~Kit_DsdLitSupport(pNtk, iLit)) ) + pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(iLit), uSupp ); + else + { + pTruthFans[i] = NULL; + nPartial = 1; + } + } + else + { + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(iLit), uSupp ); + } + // create the truth table + + // simple gates + if ( pObj->Type == KIT_DSD_AND ) + { + Kit_TruthFill( pTruthRes, pNtk->nVars ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + if ( pTruthFans[i] ) + Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Kit_DsdLitIsCompl(iLit) ); + return pTruthRes; + } + if ( pObj->Type == KIT_DSD_XOR ) + { + Kit_TruthClear( pTruthRes, pNtk->nVars ); + fCompl = 0; + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + if ( pTruthFans[i] ) + { + Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); + fCompl ^= Kit_DsdLitIsCompl(iLit); + } + } + if ( fCompl ) + Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); + return pTruthRes; + } + assert( pObj->Type == KIT_DSD_PRIME ); + + if ( uSupp && nPartial ) + { + // find the only non-empty component + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + if ( pTruthFans[i] ) + break; + assert( i < pObj->nFans ); + return pTruthFans[i]; + } +/* + // get the truth table of the prime node + pTruthPrime = Kit_DsdObjTruth( pObj ); + // get storage for the temporary minterm + pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); + + // go through the minterms + nMints = (1 << pObj->nFans); + Kit_TruthClear( pTruthRes, pNtk->nVars ); + for ( m = 0; m < nMints; m++ ) + { + if ( !Kit_TruthHasBit(pTruthPrime, m) ) + continue; + Kit_TruthFill( pTruthMint, pNtk->nVars ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<nVars ); + } +*/ + pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); + Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); + return pTruthRes; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table of the DSD network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Kit_DsdTruthComputeOne( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp ) +{ + unsigned * pTruthRes; + int i; + // if support is specified, request that supports are available + if ( uSupp ) + Kit_DsdGetSupports( pNtk ); + // assign elementary truth tables + assert( pNtk->nVars <= p->nVars ); + for ( i = 0; i < (int)pNtk->nVars; i++ ) + Kit_TruthCopy( Vec_PtrEntry(p->vTtNodes, i), Vec_PtrEntry(p->vTtElems, i), p->nVars ); + // compute truth table for each node + pTruthRes = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(pNtk->Root), uSupp ); + // complement the truth table if needed + if ( Kit_DsdLitIsCompl(pNtk->Root) ) + Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); + return pTruthRes; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table of the DSD node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Kit_DsdTruthComputeNodeTwo_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id, unsigned uSupp, int iVar, unsigned * pTruthDec ) +{ + Kit_DsdObj_t * pObj; + int pfBoundSet[16]; + unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp; + unsigned i, iLit, fCompl, nPartial, uSuppFan, uSuppCur; +// unsigned m, nMints, * pTruthPrime, * pTruthMint; + assert( uSupp > 0 ); + + // get the node with this ID + pObj = Kit_DsdNtkObj( pNtk, Id ); + pTruthRes = Vec_PtrEntry( p->vTtNodes, Id ); + if ( pObj == NULL ) + { + assert( Id < pNtk->nVars ); + return pTruthRes; + } + assert( pObj->Type != KIT_DSD_CONST1 ); + assert( pObj->Type != KIT_DSD_VAR ); + + // count the number of intersecting fanins + // collect the total support of the intersecting fanins + nPartial = 0; + uSuppFan = 0; + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + uSuppCur = Kit_DsdLitSupport(pNtk, iLit); + if ( uSupp & uSuppCur ) + { + nPartial++; + uSuppFan |= uSuppCur; + } + } + + // if there is no intersection, or full intersection, use simple procedure + if ( nPartial == 0 || nPartial == pObj->nFans ) + return Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Id, 0 ); + + // if support of the component includes some other variables + // we need to continue constructing it as usual by the two-function procedure + if ( uSuppFan != (uSuppFan & uSupp) ) + { + assert( nPartial == 1 ); +// return Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Id, uSupp, iVar, pTruthDec ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + if ( uSupp & Kit_DsdLitSupport(pNtk, iLit) ) + pTruthFans[i] = Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Kit_DsdLit2Var(iLit), uSupp, iVar, pTruthDec ); + else + pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(iLit), 0 ); + } + + // create composition/decomposition functions + if ( pObj->Type == KIT_DSD_AND ) + { + Kit_TruthFill( pTruthRes, pNtk->nVars ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Kit_DsdLitIsCompl(iLit) ); + return pTruthRes; + } + if ( pObj->Type == KIT_DSD_XOR ) + { + Kit_TruthClear( pTruthRes, pNtk->nVars ); + fCompl = 0; + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + fCompl ^= Kit_DsdLitIsCompl(iLit); + Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); + } + if ( fCompl ) + Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); + return pTruthRes; + } + assert( pObj->Type == KIT_DSD_PRIME ); + } + else + { + assert( uSuppFan == (uSuppFan & uSupp) ); + assert( nPartial < pObj->nFans ); + // the support of the insecting component(s) is contained in the bound-set + // and yet there are components that are not contained in the bound set + + // solve the fanins and collect info, which components belong to the bound set + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(iLit), 0 ); + pfBoundSet[i] = (int)((uSupp & Kit_DsdLitSupport(pNtk, iLit)) > 0); + } + + // create composition/decomposition functions + if ( pObj->Type == KIT_DSD_AND ) + { + Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar ); + Kit_TruthFill( pTruthDec, pNtk->nVars ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + if ( pfBoundSet[i] ) + Kit_TruthAndPhase( pTruthDec, pTruthDec, pTruthFans[i], pNtk->nVars, 0, Kit_DsdLitIsCompl(iLit) ); + else + Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Kit_DsdLitIsCompl(iLit) ); + return pTruthRes; + } + if ( pObj->Type == KIT_DSD_XOR ) + { + Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar ); + Kit_TruthClear( pTruthDec, pNtk->nVars ); + fCompl = 0; + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + { + fCompl ^= Kit_DsdLitIsCompl(iLit); + if ( pfBoundSet[i] ) + Kit_TruthXor( pTruthDec, pTruthDec, pTruthFans[i], pNtk->nVars ); + else + Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); + } + if ( fCompl ) + Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); + return pTruthRes; + } + assert( pObj->Type == KIT_DSD_PRIME ); + assert( nPartial == 1 ); + + // find the only non-empty component + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + if ( pfBoundSet[i] ) + break; + assert( i < pObj->nFans ); + + // save this component as the decomposed function + Kit_TruthCopy( pTruthDec, pTruthFans[i], pNtk->nVars ); + // set the corresponding component to be the new variable + Kit_TruthIthVar( pTruthFans[i], pNtk->nVars, iVar ); + } +/* + // get the truth table of the prime node + pTruthPrime = Kit_DsdObjTruth( pObj ); + // get storage for the temporary minterm + pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); + + // go through the minterms + nMints = (1 << pObj->nFans); + Kit_TruthClear( pTruthRes, pNtk->nVars ); + for ( m = 0; m < nMints; m++ ) + { + if ( !Kit_TruthHasBit(pTruthPrime, m) ) + continue; + Kit_TruthFill( pTruthMint, pNtk->nVars ); + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<nVars ); + } +*/ + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + assert( !Kit_DsdLitIsCompl(iLit) ); + pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); + Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); + return pTruthRes; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table of the DSD network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Kit_DsdTruthComputeTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthDec ) +{ + unsigned * pTruthRes, uSuppAll; + int i; + assert( uSupp > 0 ); + assert( pNtk->nVars <= p->nVars ); + // compute support of all nodes + uSuppAll = Kit_DsdGetSupports( pNtk ); + // consider special case - there is no overlap + if ( (uSupp & uSuppAll) == 0 ) + { + Kit_TruthClear( pTruthDec, pNtk->nVars ); + return Kit_DsdTruthCompute( p, pNtk ); + } + // consider special case - support is fully contained + if ( (uSupp & uSuppAll) == uSuppAll ) + { + pTruthRes = Kit_DsdTruthCompute( p, pNtk ); + Kit_TruthCopy( pTruthDec, pTruthRes, pNtk->nVars ); + Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar ); + return pTruthRes; + } + // assign elementary truth tables + for ( i = 0; i < (int)pNtk->nVars; i++ ) + Kit_TruthCopy( Vec_PtrEntry(p->vTtNodes, i), Vec_PtrEntry(p->vTtElems, i), p->nVars ); + // compute truth table for each node + pTruthRes = Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Kit_DsdLit2Var(pNtk->Root), uSupp, iVar, pTruthDec ); + // complement the truth table if needed + if ( Kit_DsdLitIsCompl(pNtk->Root) ) + Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); + return pTruthRes; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table of the DSD network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdTruth( Kit_DsdNtk_t * pNtk, unsigned * pTruthRes ) +{ + Kit_DsdMan_t * p; + unsigned * pTruth; + p = Kit_DsdManAlloc( pNtk->nVars, Kit_DsdNtkObjNum(pNtk) ); + pTruth = Kit_DsdTruthCompute( p, pNtk ); + Kit_TruthCopy( pTruthRes, pTruth, pNtk->nVars ); + Kit_DsdManFree( p ); +} + +/**Function************************************************************* + + Synopsis [Derives the truth table of the DSD network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdTruthPartialTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthCo, unsigned * pTruthDec ) +{ + unsigned * pTruth = Kit_DsdTruthComputeTwo( p, pNtk, uSupp, iVar, pTruthDec ); + if ( pTruthCo ) + Kit_TruthCopy( pTruthCo, pTruth, pNtk->nVars ); +} + +/**Function************************************************************* + + Synopsis [Derives the truth table of the DSD network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdTruthPartial( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned * pTruthRes, unsigned uSupp ) +{ + unsigned * pTruth = Kit_DsdTruthComputeOne( p, pNtk, uSupp ); + Kit_TruthCopy( pTruthRes, pTruth, pNtk->nVars ); +/* + // verification + { + // compute the same function using different procedure + unsigned * pTruthTemp = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes + 1); + pNtk->pSupps = NULL; + Kit_DsdTruthComputeTwo( p, pNtk, uSupp, -1, pTruthTemp ); +// if ( !Kit_TruthIsEqual( pTruthTemp, pTruthRes, pNtk->nVars ) ) + if ( !Kit_TruthIsEqualWithPhase( pTruthTemp, pTruthRes, pNtk->nVars ) ) + { + printf( "Verification FAILED!\n" ); + Kit_DsdPrint( stdout, pNtk ); + Kit_DsdPrintFromTruth( pTruthRes, pNtk->nVars ); + Kit_DsdPrintFromTruth( pTruthTemp, pNtk->nVars ); + } +// else +// printf( "Verification successful.\n" ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Counts the number of blocks of the given number of inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdCountLuts_rec( Kit_DsdNtk_t * pNtk, int nLutSize, int Id, int * pCounter ) +{ + Kit_DsdObj_t * pObj; + unsigned iLit, i, Res0, Res1; + pObj = Kit_DsdNtkObj( pNtk, Id ); + if ( pObj == NULL ) + return 0; + if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) + { + assert( pObj->nFans == 2 ); + Res0 = Kit_DsdCountLuts_rec( pNtk, nLutSize, Kit_DsdLit2Var(pObj->pFans[0]), pCounter ); + Res1 = Kit_DsdCountLuts_rec( pNtk, nLutSize, Kit_DsdLit2Var(pObj->pFans[1]), pCounter ); + if ( Res0 == 0 && Res1 > 0 ) + return Res1 - 1; + if ( Res0 > 0 && Res1 == 0 ) + return Res0 - 1; + (*pCounter)++; + return nLutSize - 2; + } + assert( pObj->Type == KIT_DSD_PRIME ); + if ( (int)pObj->nFans > nLutSize ) //+ 1 ) + { + *pCounter = 1000; + return 0; + } + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + Kit_DsdCountLuts_rec( pNtk, nLutSize, Kit_DsdLit2Var(iLit), pCounter ); + (*pCounter)++; +// if ( (int)pObj->nFans == nLutSize + 1 ) +// (*pCounter)++; + return nLutSize - pObj->nFans; +} + +/**Function************************************************************* + + Synopsis [Counts the number of blocks of the given number of inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdCountLuts( Kit_DsdNtk_t * pNtk, int nLutSize ) +{ + int Counter = 0; + if ( Kit_DsdNtkRoot(pNtk)->Type == KIT_DSD_CONST1 ) + return 0; + if ( Kit_DsdNtkRoot(pNtk)->Type == KIT_DSD_VAR ) + return 0; + Kit_DsdCountLuts_rec( pNtk, nLutSize, Kit_DsdLit2Var(pNtk->Root), &Counter ); + if ( Counter >= 1000 ) + return -1; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of blocks of the given number of inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk ) +{ + Kit_DsdObj_t * pObj; + unsigned i, nSizeMax = 0; + Kit_DsdNtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->Type != KIT_DSD_PRIME ) + continue; + if ( nSizeMax < pObj->nFans ) + nSizeMax = pObj->nFans; + } + return nSizeMax; +} + +/**Function************************************************************* + + Synopsis [Finds the union of supports of the non-DSD blocks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Kit_DsdNonDsdSupports( Kit_DsdNtk_t * pNtk ) +{ + Kit_DsdObj_t * pObj; + unsigned i, uSupport = 0; +// FREE( pNtk->pSupps ); + Kit_DsdGetSupports( pNtk ); + Kit_DsdNtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->Type != KIT_DSD_PRIME ) + continue; + uSupport |= Kit_DsdLitSupport( pNtk, Kit_DsdVar2Lit(pObj->Id,0) ); + } + return uSupport; +} + + +/**Function************************************************************* + + Synopsis [Expands the node.] + + Description [Returns the new literal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdExpandCollectAnd_rec( Kit_DsdNtk_t * p, int iLit, int * piLitsNew, int * nLitsNew ) +{ + Kit_DsdObj_t * pObj; + unsigned i, iLitFanin; + // check the end of the supergate + pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); + if ( Kit_DsdLitIsCompl(iLit) || Kit_DsdLit2Var(iLit) < p->nVars || pObj->Type != KIT_DSD_AND ) + { + piLitsNew[(*nLitsNew)++] = iLit; + return; + } + // iterate through the fanins + Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) + Kit_DsdExpandCollectAnd_rec( p, iLitFanin, piLitsNew, nLitsNew ); +} + +/**Function************************************************************* + + Synopsis [Expands the node.] + + Description [Returns the new literal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdExpandCollectXor_rec( Kit_DsdNtk_t * p, int iLit, int * piLitsNew, int * nLitsNew ) +{ + Kit_DsdObj_t * pObj; + unsigned i, iLitFanin; + // check the end of the supergate + pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); + if ( Kit_DsdLit2Var(iLit) < p->nVars || pObj->Type != KIT_DSD_XOR ) + { + piLitsNew[(*nLitsNew)++] = iLit; + return; + } + // iterate through the fanins + pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); + Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) + Kit_DsdExpandCollectXor_rec( p, iLitFanin, piLitsNew, nLitsNew ); + // if the literal was complemented, pass the complemented attribute somewhere + if ( Kit_DsdLitIsCompl(iLit) ) + piLitsNew[0] = Kit_DsdLitNot( piLitsNew[0] ); +} + +/**Function************************************************************* + + Synopsis [Expands the node.] + + Description [Returns the new literal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdExpandNode_rec( Kit_DsdNtk_t * pNew, Kit_DsdNtk_t * p, int iLit ) +{ + unsigned * pTruth, * pTruthNew; + unsigned i, iLitFanin, piLitsNew[16], nLitsNew = 0; + Kit_DsdObj_t * pObj, * pObjNew; + + // consider the case of simple gate + pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); + if ( pObj == NULL ) + return iLit; + if ( pObj->Type == KIT_DSD_AND ) + { + Kit_DsdExpandCollectAnd_rec( p, Kit_DsdLitRegular(iLit), piLitsNew, &nLitsNew ); + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_AND, nLitsNew ); + for ( i = 0; i < pObjNew->nFans; i++ ) + pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, piLitsNew[i] ); + return Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(iLit) ); + } + if ( pObj->Type == KIT_DSD_XOR ) + { + int fCompl = Kit_DsdLitIsCompl(iLit); + Kit_DsdExpandCollectXor_rec( p, Kit_DsdLitRegular(iLit), piLitsNew, &nLitsNew ); + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_XOR, nLitsNew ); + for ( i = 0; i < pObjNew->nFans; i++ ) + { + pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, Kit_DsdLitRegular(piLitsNew[i]) ); + fCompl ^= Kit_DsdLitIsCompl(piLitsNew[i]); + } + return Kit_DsdVar2Lit( pObjNew->Id, fCompl ); + } + assert( pObj->Type == KIT_DSD_PRIME ); + + // create new PRIME node + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_PRIME, pObj->nFans ); + // copy the truth table + pTruth = Kit_DsdObjTruth( pObj ); + pTruthNew = Kit_DsdObjTruth( pObjNew ); + Kit_TruthCopy( pTruthNew, pTruth, pObj->nFans ); + // create fanins + Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i ) + { + pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, iLitFanin ); + // complement the corresponding inputs of the truth table + if ( Kit_DsdLitIsCompl(pObjNew->pFans[i]) ) + { + pObjNew->pFans[i] = Kit_DsdLitRegular(pObjNew->pFans[i]); + Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i ); + } + } + // if the incoming phase is complemented, absorb it into the prime node + if ( Kit_DsdLitIsCompl(iLit) ) + Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans ); + return Kit_DsdVar2Lit( pObjNew->Id, 0 ); +} + +/**Function************************************************************* + + Synopsis [Expands the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdNtk_t * Kit_DsdExpand( Kit_DsdNtk_t * p ) +{ + Kit_DsdNtk_t * pNew; + Kit_DsdObj_t * pObjNew; + assert( p->nVars <= 16 ); + // create a new network + pNew = Kit_DsdNtkAlloc( p->nVars ); + // consider simple special cases + if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) + { + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 ); + pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(p->Root) ); + return pNew; + } + if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) + { + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 ); + pObjNew->pFans[0] = Kit_DsdNtkRoot(p)->pFans[0]; + pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(p->Root) ); + return pNew; + } + // convert the root node + pNew->Root = Kit_DsdExpandNode_rec( pNew, p, p->Root ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Sorts the literals by their support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdCompSort( int pPrios[], unsigned uSupps[], unsigned char * piLits, int nVars, int piLitsRes[] ) +{ + int nSuppSizes[16], Priority[16], pOrder[16]; + int i, k, iVarBest, SuppMax, PrioMax; + // compute support sizes and priorities of the components + for ( i = 0; i < nVars; i++ ) + { + assert( uSupps[i] ); + pOrder[i] = i; + Priority[i] = KIT_INFINITY; + for ( k = 0; k < 16; k++ ) + if ( uSupps[i] & (1 << k) ) + Priority[i] = KIT_MIN( Priority[i], pPrios[k] ); + assert( Priority[i] != 16 ); + nSuppSizes[i] = Kit_WordCountOnes(uSupps[i]); + } + // sort the components by pririty + Extra_BubbleSort( pOrder, Priority, nVars, 0 ); + // find the component by with largest size and lowest priority + iVarBest = -1; + SuppMax = 0; + PrioMax = 0; + for ( i = 0; i < nVars; i++ ) + { + if ( SuppMax < nSuppSizes[i] || (SuppMax == nSuppSizes[i] && PrioMax < Priority[i]) ) + { + SuppMax = nSuppSizes[i]; + PrioMax = Priority[i]; + iVarBest = i; + } + } + assert( iVarBest != -1 ); + // copy the resulting literals + k = 0; + piLitsRes[k++] = piLits[iVarBest]; + for ( i = 0; i < nVars; i++ ) + { + if ( pOrder[i] == iVarBest ) + continue; + piLitsRes[k++] = piLits[pOrder[i]]; + } + assert( k == nVars ); +} + +/**Function************************************************************* + + Synopsis [Shrinks multi-input nodes.] + + Description [Takes the array of variable priorities pPrios.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdShrink_rec( Kit_DsdNtk_t * pNew, Kit_DsdNtk_t * p, int iLit, int pPrios[] ) +{ + Kit_DsdObj_t * pObj, * pObjNew; + unsigned * pTruth, * pTruthNew; + unsigned i, piLitsNew[16], uSupps[16]; + int iLitFanin, iLitNew; + + // consider the case of simple gate + pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); + if ( pObj == NULL ) + return iLit; + if ( pObj->Type == KIT_DSD_AND ) + { + // get the supports + Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) + uSupps[i] = Kit_DsdLitSupport( p, iLitFanin ); + // put the largest component last + // sort other components in the decreasing order of priority of their vars + Kit_DsdCompSort( pPrios, uSupps, pObj->pFans, pObj->nFans, piLitsNew ); + // construct the two-input node network + iLitNew = Kit_DsdShrink_rec( pNew, p, piLitsNew[0], pPrios ); + for ( i = 1; i < pObj->nFans; i++ ) + { + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_AND, 2 ); + pObjNew->pFans[0] = Kit_DsdShrink_rec( pNew, p, piLitsNew[i], pPrios ); + pObjNew->pFans[1] = iLitNew; + iLitNew = Kit_DsdVar2Lit( pObjNew->Id, 0 ); + } + return Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(iLit) ); + } + if ( pObj->Type == KIT_DSD_XOR ) + { + // get the supports + Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) + { + assert( !Kit_DsdLitIsCompl(iLitFanin) ); + uSupps[i] = Kit_DsdLitSupport( p, iLitFanin ); + } + // put the largest component last + // sort other components in the decreasing order of priority of their vars + Kit_DsdCompSort( pPrios, uSupps, pObj->pFans, pObj->nFans, piLitsNew ); + // construct the two-input node network + iLitNew = Kit_DsdShrink_rec( pNew, p, piLitsNew[0], pPrios ); + for ( i = 1; i < pObj->nFans; i++ ) + { + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_XOR, 2 ); + pObjNew->pFans[0] = Kit_DsdShrink_rec( pNew, p, piLitsNew[i], pPrios ); + pObjNew->pFans[1] = iLitNew; + iLitNew = Kit_DsdVar2Lit( pObjNew->Id, 0 ); + } + return Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(iLit) ); + } + assert( pObj->Type == KIT_DSD_PRIME ); + + // create new PRIME node + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_PRIME, pObj->nFans ); + // copy the truth table + pTruth = Kit_DsdObjTruth( pObj ); + pTruthNew = Kit_DsdObjTruth( pObjNew ); + Kit_TruthCopy( pTruthNew, pTruth, pObj->nFans ); + // create fanins + Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i ) + { + pObjNew->pFans[i] = Kit_DsdShrink_rec( pNew, p, iLitFanin, pPrios ); + // complement the corresponding inputs of the truth table + if ( Kit_DsdLitIsCompl(pObjNew->pFans[i]) ) + { + pObjNew->pFans[i] = Kit_DsdLitRegular(pObjNew->pFans[i]); + Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i ); + } + } + // if the incoming phase is complemented, absorb it into the prime node + if ( Kit_DsdLitIsCompl(iLit) ) + Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans ); + return Kit_DsdVar2Lit( pObjNew->Id, 0 ); +} + +/**Function************************************************************* + + Synopsis [Shrinks the network.] + + Description [Transforms the network to have two-input nodes so that the + higher-ordered nodes were decomposed out first.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdNtk_t * Kit_DsdShrink( Kit_DsdNtk_t * p, int pPrios[] ) +{ + Kit_DsdNtk_t * pNew; + Kit_DsdObj_t * pObjNew; + assert( p->nVars <= 16 ); + // create a new network + pNew = Kit_DsdNtkAlloc( p->nVars ); + // consider simple special cases + if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) + { + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 ); + pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(p->Root) ); + return pNew; + } + if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) + { + pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 ); + pObjNew->pFans[0] = Kit_DsdNtkRoot(p)->pFans[0]; + pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(p->Root) ); + return pNew; + } + // convert the root node + pNew->Root = Kit_DsdShrink_rec( pNew, p, p->Root, pPrios ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Rotates the network.] + + Description [Transforms prime nodes to have the fanin with the + highest frequency of supports go first.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdRotate( Kit_DsdNtk_t * p, int pFreqs[] ) +{ + Kit_DsdObj_t * pObj; + unsigned * pIn, * pOut, * pTemp, k; + int i, v, Temp, uSuppFanin, iFaninLit, WeightMax, FaninMax, nSwaps; + int Weights[16]; + // go through the prime nodes + Kit_DsdNtkForEachObj( p, pObj, i ) + { + if ( pObj->Type != KIT_DSD_PRIME ) + continue; + // count the fanin frequencies + Kit_DsdObjForEachFanin( p, pObj, iFaninLit, k ) + { + uSuppFanin = Kit_DsdLitSupport( p, iFaninLit ); + Weights[k] = 0; + for ( v = 0; v < 16; v++ ) + if ( uSuppFanin & (1 << v) ) + Weights[k] += pFreqs[v] - 1; + } + // find the most frequent fanin + WeightMax = 0; + FaninMax = -1; + for ( k = 0; k < pObj->nFans; k++ ) + if ( WeightMax < Weights[k] ) + { + WeightMax = Weights[k]; + FaninMax = k; + } + // no need to reorder if there are no frequent fanins + if ( FaninMax == -1 ) + continue; + // move the fanins number k to the first place + nSwaps = 0; + pIn = Kit_DsdObjTruth(pObj); + pOut = p->pMem; +// for ( v = FaninMax; v < ((int)pObj->nFans)-1; v++ ) + for ( v = FaninMax-1; v >= 0; v-- ) + { + // swap the fanins + Temp = pObj->pFans[v]; + pObj->pFans[v] = pObj->pFans[v+1]; + pObj->pFans[v+1] = Temp; + // swap the truth table variables + Kit_TruthSwapAdjacentVars( pOut, pIn, pObj->nFans, v ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + nSwaps++; + } + if ( nSwaps & 1 ) + Kit_TruthCopy( pOut, pIn, pObj->nFans ); + } +} + +/**Function************************************************************* + + Synopsis [Compute the support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Kit_DsdGetSupports_rec( Kit_DsdNtk_t * p, int iLit ) +{ + Kit_DsdObj_t * pObj; + unsigned uSupport, k; + int iFaninLit; + pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); + if ( pObj == NULL ) + return Kit_DsdLitSupport( p, iLit ); + uSupport = 0; + Kit_DsdObjForEachFanin( p, pObj, iFaninLit, k ) + uSupport |= Kit_DsdGetSupports_rec( p, iFaninLit ); + p->pSupps[pObj->Id - p->nVars] = uSupport; + assert( uSupport <= 0xFFFF ); + return uSupport; +} + +/**Function************************************************************* + + Synopsis [Compute the support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Kit_DsdGetSupports( Kit_DsdNtk_t * p ) +{ + Kit_DsdObj_t * pRoot; + unsigned uSupport; + assert( p->pSupps == NULL ); + p->pSupps = ALLOC( unsigned, p->nNodes ); + // consider simple special cases + pRoot = Kit_DsdNtkRoot(p); + if ( pRoot->Type == KIT_DSD_CONST1 ) + { + assert( p->nNodes == 1 ); + uSupport = p->pSupps[0] = 0; + } + if ( pRoot->Type == KIT_DSD_VAR ) + { + assert( p->nNodes == 1 ); + uSupport = p->pSupps[0] = Kit_DsdLitSupport( p, pRoot->pFans[0] ); + } + else + uSupport = Kit_DsdGetSupports_rec( p, p->Root ); + assert( uSupport <= 0xFFFF ); + return uSupport; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if there is a component with more than 3 inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdFindLargeBox_rec( Kit_DsdNtk_t * pNtk, int Id, int Size ) +{ + Kit_DsdObj_t * pObj; + unsigned iLit, i, RetValue; + pObj = Kit_DsdNtkObj( pNtk, Id ); + if ( pObj == NULL ) + return 0; + if ( pObj->Type == KIT_DSD_PRIME && (int)pObj->nFans > Size ) + return 1; + RetValue = 0; + Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) + RetValue |= Kit_DsdFindLargeBox_rec( pNtk, Kit_DsdLit2Var(iLit), Size ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if there is a component with more than 3 inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdFindLargeBox( Kit_DsdNtk_t * pNtk, int Size ) +{ + return Kit_DsdFindLargeBox_rec( pNtk, Kit_DsdLit2Var(pNtk->Root), Size ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the non-DSD 4-var func is implementable with two 3-LUTs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdRootNodeHasCommonVars( Kit_DsdObj_t * pObj0, Kit_DsdObj_t * pObj1 ) +{ + unsigned i, k; + for ( i = 0; i < pObj0->nFans; i++ ) + { + if ( Kit_DsdLit2Var(pObj0->pFans[i]) >= 4 ) + continue; + for ( k = 0; k < pObj1->nFans; k++ ) + if ( Kit_DsdLit2Var(pObj0->pFans[i]) == Kit_DsdLit2Var(pObj1->pFans[k]) ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the non-DSD 4-var func is implementable with two 3-LUTs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdCheckVar4Dec2( Kit_DsdNtk_t * pNtk0, Kit_DsdNtk_t * pNtk1 ) +{ + assert( pNtk0->nVars == 4 ); + assert( pNtk1->nVars == 4 ); + if ( Kit_DsdFindLargeBox(pNtk0, 2) ) + return 0; + if ( Kit_DsdFindLargeBox(pNtk1, 2) ) + return 0; + return Kit_DsdRootNodeHasCommonVars( Kit_DsdNtkRoot(pNtk0), Kit_DsdNtkRoot(pNtk1) ); +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdDecompose_rec( Kit_DsdNtk_t * pNtk, Kit_DsdObj_t * pObj, unsigned uSupp, unsigned char * pPar, int nDecMux ) +{ + Kit_DsdObj_t * pRes, * pRes0, * pRes1; + int nWords = Kit_TruthWordNum(pObj->nFans); + unsigned * pTruth = Kit_DsdObjTruth(pObj); + unsigned * pCofs2[2] = { pNtk->pMem, pNtk->pMem + nWords }; + unsigned * pCofs4[2][2] = { {pNtk->pMem + 2 * nWords, pNtk->pMem + 3 * nWords}, {pNtk->pMem + 4 * nWords, pNtk->pMem + 5 * nWords} }; + int i, iLit0, iLit1, nFans0, nFans1, nPairs; + int fEquals[2][2], fOppos, fPairs[4][4]; + unsigned j, k, nFansNew, uSupp0, uSupp1; + + assert( pObj->nFans > 0 ); + assert( pObj->Type == KIT_DSD_PRIME ); + assert( uSupp == (uSupp0 = (unsigned)Kit_TruthSupport(pTruth, pObj->nFans)) ); + + // compress the truth table + if ( uSupp != Kit_BitMask(pObj->nFans) ) + { + nFansNew = Kit_WordCountOnes(uSupp); + Kit_TruthShrink( pNtk->pMem, pTruth, nFansNew, pObj->nFans, uSupp, 1 ); + for ( j = k = 0; j < pObj->nFans; j++ ) + if ( uSupp & (1 << j) ) + pObj->pFans[k++] = pObj->pFans[j]; + assert( k == nFansNew ); + pObj->nFans = k; + uSupp = Kit_BitMask(pObj->nFans); + } + + // consider the single variable case + if ( pObj->nFans == 1 ) + { + pObj->Type = KIT_DSD_NONE; + if ( pTruth[0] == 0x55555555 ) + pObj->pFans[0] = Kit_DsdLitNot(pObj->pFans[0]); + else + assert( pTruth[0] == 0xAAAAAAAA ); + // update the parent pointer + *pPar = Kit_DsdLitNotCond( pObj->pFans[0], Kit_DsdLitIsCompl(*pPar) ); + return; + } + + // decompose the output + if ( !pObj->fMark ) + for ( i = pObj->nFans - 1; i >= 0; i-- ) + { + // get the two-variable cofactors + Kit_TruthCofactor0New( pCofs2[0], pTruth, pObj->nFans, i ); + Kit_TruthCofactor1New( pCofs2[1], pTruth, pObj->nFans, i ); +// assert( !Kit_TruthVarInSupport( pCofs2[0], pObj->nFans, i) ); +// assert( !Kit_TruthVarInSupport( pCofs2[1], pObj->nFans, i) ); + // get the constant cofs + fEquals[0][0] = Kit_TruthIsConst0( pCofs2[0], pObj->nFans ); + fEquals[0][1] = Kit_TruthIsConst0( pCofs2[1], pObj->nFans ); + fEquals[1][0] = Kit_TruthIsConst1( pCofs2[0], pObj->nFans ); + fEquals[1][1] = Kit_TruthIsConst1( pCofs2[1], pObj->nFans ); + fOppos = Kit_TruthIsOpposite( pCofs2[0], pCofs2[1], pObj->nFans ); + assert( !Kit_TruthIsEqual(pCofs2[0], pCofs2[1], pObj->nFans) ); + if ( fEquals[0][0] + fEquals[0][1] + fEquals[1][0] + fEquals[1][1] + fOppos == 0 ) + { + // check the MUX decomposition + uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans ); + uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans ); + assert( uSupp == (uSupp0 | uSupp1 | (1<nFans ); + pRes1 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans ); + for ( k = 0; k < pObj->nFans; k++ ) + { + pRes0->pFans[k] = (uSupp0 & (1 << k))? pObj->pFans[k] : 127; + pRes1->pFans[k] = (uSupp1 & (1 << k))? pObj->pFans[k] : 127; + } + Kit_TruthCopy( Kit_DsdObjTruth(pRes0), pCofs2[0], pObj->nFans ); + Kit_TruthCopy( Kit_DsdObjTruth(pRes1), pCofs2[1], pObj->nFans ); + // update the current one + assert( pObj->Type == KIT_DSD_PRIME ); + pTruth[0] = 0xCACACACA; + pObj->nFans = 3; + pObj->pFans[2] = pObj->pFans[i]; + pObj->pFans[0] = 2*pRes0->Id; pRes0->nRefs++; + pObj->pFans[1] = 2*pRes1->Id; pRes1->nRefs++; + // call recursively + Kit_DsdDecompose_rec( pNtk, pRes0, uSupp0, pObj->pFans + 0, nDecMux ); + Kit_DsdDecompose_rec( pNtk, pRes1, uSupp1, pObj->pFans + 1, nDecMux ); + return; + } + + // create the new node + pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_AND, 2 ); + pRes->nRefs++; + pRes->nFans = 2; + pRes->pFans[0] = pObj->pFans[i]; pObj->pFans[i] = 127; uSupp &= ~(1 << i); + pRes->pFans[1] = 2*pObj->Id; + // update the parent pointer + *pPar = Kit_DsdLitNotCond( 2 * pRes->Id, Kit_DsdLitIsCompl(*pPar) ); + // consider different decompositions + if ( fEquals[0][0] ) + { + Kit_TruthCopy( pTruth, pCofs2[1], pObj->nFans ); + } + else if ( fEquals[0][1] ) + { + pRes->pFans[0] = Kit_DsdLitNot(pRes->pFans[0]); + Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans ); + } + else if ( fEquals[1][0] ) + { + *pPar = Kit_DsdLitNot(*pPar); + pRes->pFans[1] = Kit_DsdLitNot(pRes->pFans[1]); + Kit_TruthCopy( pTruth, pCofs2[1], pObj->nFans ); + } + else if ( fEquals[1][1] ) + { + *pPar = Kit_DsdLitNot(*pPar); + pRes->pFans[0] = Kit_DsdLitNot(pRes->pFans[0]); + pRes->pFans[1] = Kit_DsdLitNot(pRes->pFans[1]); + Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans ); + } + else if ( fOppos ) + { + pRes->Type = KIT_DSD_XOR; + Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans ); + } + else + assert( 0 ); + // decompose the remainder + assert( Kit_DsdObjTruth(pObj) == pTruth ); + Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pRes->pFans + 1, nDecMux ); + return; + } + pObj->fMark = 1; + + // decompose the input + for ( i = pObj->nFans - 1; i >= 0; i-- ) + { + assert( Kit_TruthVarInSupport( pTruth, pObj->nFans, i ) ); + // get the single variale cofactors + Kit_TruthCofactor0New( pCofs2[0], pTruth, pObj->nFans, i ); + Kit_TruthCofactor1New( pCofs2[1], pTruth, pObj->nFans, i ); + // check the existence of MUX decomposition + uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans ); + uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans ); + assert( uSupp == (uSupp0 | uSupp1 | (1<fMark = 0; + Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux ); + return; + } + assert( uSupp0 && uSupp1 ); + // get the number of unique variables + nFans0 = Kit_WordCountOnes( uSupp0 & ~uSupp1 ); + nFans1 = Kit_WordCountOnes( uSupp1 & ~uSupp0 ); + if ( nFans0 == 1 && nFans1 == 1 ) + { + // get the cofactors w.r.t. the unique variables + iLit0 = Kit_WordFindFirstBit( uSupp0 & ~uSupp1 ); + iLit1 = Kit_WordFindFirstBit( uSupp1 & ~uSupp0 ); + // get four cofactors + Kit_TruthCofactor0New( pCofs4[0][0], pCofs2[0], pObj->nFans, iLit0 ); + Kit_TruthCofactor1New( pCofs4[0][1], pCofs2[0], pObj->nFans, iLit0 ); + Kit_TruthCofactor0New( pCofs4[1][0], pCofs2[1], pObj->nFans, iLit1 ); + Kit_TruthCofactor1New( pCofs4[1][1], pCofs2[1], pObj->nFans, iLit1 ); + // check existence conditions + fEquals[0][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][0], pObj->nFans ); + fEquals[0][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][1], pObj->nFans ); + fEquals[1][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][1], pObj->nFans ); + fEquals[1][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][0], pObj->nFans ); + if ( (fEquals[0][0] && fEquals[0][1]) || (fEquals[1][0] && fEquals[1][1]) ) + { + // construct the MUX + pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, 3 ); + Kit_DsdObjTruth(pRes)[0] = 0xCACACACA; + pRes->nRefs++; + pRes->nFans = 3; + pRes->pFans[0] = pObj->pFans[iLit0]; pObj->pFans[iLit0] = 127; uSupp &= ~(1 << iLit0); + pRes->pFans[1] = pObj->pFans[iLit1]; pObj->pFans[iLit1] = 127; uSupp &= ~(1 << iLit1); + pRes->pFans[2] = pObj->pFans[i]; pObj->pFans[i] = 2 * pRes->Id; // remains in support + // update the node +// if ( fEquals[0][0] && fEquals[0][1] ) +// Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, i ); +// else +// Kit_TruthMuxVar( pTruth, pCofs4[0][1], pCofs4[0][0], pObj->nFans, i ); + Kit_TruthMuxVar( pTruth, pCofs4[1][0], pCofs4[1][1], pObj->nFans, i ); + if ( fEquals[1][0] && fEquals[1][1] ) + pRes->pFans[0] = Kit_DsdLitNot(pRes->pFans[0]); + // decompose the remainder + Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux ); + return; + } + } + + // try other inputs + for ( k = i+1; k < pObj->nFans; k++ ) + { + // get four cofactors ik + Kit_TruthCofactor0New( pCofs4[0][0], pCofs2[0], pObj->nFans, k ); // 00 + Kit_TruthCofactor1New( pCofs4[0][1], pCofs2[0], pObj->nFans, k ); // 01 + Kit_TruthCofactor0New( pCofs4[1][0], pCofs2[1], pObj->nFans, k ); // 10 + Kit_TruthCofactor1New( pCofs4[1][1], pCofs2[1], pObj->nFans, k ); // 11 + // compare equal pairs + fPairs[0][1] = fPairs[1][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[0][1], pObj->nFans ); + fPairs[0][2] = fPairs[2][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][0], pObj->nFans ); + fPairs[0][3] = fPairs[3][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][1], pObj->nFans ); + fPairs[1][2] = fPairs[2][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][0], pObj->nFans ); + fPairs[1][3] = fPairs[3][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][1], pObj->nFans ); + fPairs[2][3] = fPairs[3][2] = Kit_TruthIsEqual( pCofs4[1][0], pCofs4[1][1], pObj->nFans ); + nPairs = fPairs[0][1] + fPairs[0][2] + fPairs[0][3] + fPairs[1][2] + fPairs[1][3] + fPairs[2][3]; + if ( nPairs != 3 && nPairs != 2 ) + continue; + + // decomposition exists + pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_AND, 2 ); + pRes->nRefs++; + pRes->nFans = 2; + pRes->pFans[0] = pObj->pFans[k]; pObj->pFans[k] = 2 * pRes->Id; // remains in support + pRes->pFans[1] = pObj->pFans[i]; pObj->pFans[i] = 127; uSupp &= ~(1 << i); + if ( !fPairs[0][1] && !fPairs[0][2] && !fPairs[0][3] ) // 00 + { + pRes->pFans[0] = Kit_DsdLitNot(pRes->pFans[0]); + pRes->pFans[1] = Kit_DsdLitNot(pRes->pFans[1]); + Kit_TruthMuxVar( pTruth, pCofs4[1][1], pCofs4[0][0], pObj->nFans, k ); + } + else if ( !fPairs[1][0] && !fPairs[1][2] && !fPairs[1][3] ) // 01 + { + pRes->pFans[1] = Kit_DsdLitNot(pRes->pFans[1]); + Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, k ); + } + else if ( !fPairs[2][0] && !fPairs[2][1] && !fPairs[2][3] ) // 10 + { + pRes->pFans[0] = Kit_DsdLitNot(pRes->pFans[0]); + Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[1][0], pObj->nFans, k ); + } + else if ( !fPairs[3][0] && !fPairs[3][1] && !fPairs[3][2] ) // 11 + { +// unsigned uSupp0 = Kit_TruthSupport(pCofs4[0][0], pObj->nFans); +// unsigned uSupp1 = Kit_TruthSupport(pCofs4[1][1], pObj->nFans); +// unsigned uSupp; +// Extra_PrintBinary( stdout, &uSupp0, pObj->nFans ); printf( "\n" ); +// Extra_PrintBinary( stdout, &uSupp1, pObj->nFans ); printf( "\n" ); + Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[1][1], pObj->nFans, k ); +// uSupp = Kit_TruthSupport(pTruth, pObj->nFans); +// Extra_PrintBinary( stdout, &uSupp, pObj->nFans ); printf( "\n" ); printf( "\n" ); + } + else + { + assert( fPairs[0][3] && fPairs[1][2] ); + pRes->Type = KIT_DSD_XOR;; + Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, k ); + } + // decompose the remainder + Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux ); + return; + } + } +/* + // if all decomposition methods failed and we are still above the limit, perform MUX-decomposition + if ( nDecMux > 0 && (int)pObj->nFans > nDecMux ) + { + int iBestVar = Kit_TruthBestCofVar( pTruth, pObj->nFans, pCofs2[0], pCofs2[1] ); + uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans ); + uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans ); + // perform MUX decomposition + pRes0 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans ); + pRes1 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans ); + for ( k = 0; k < pObj->nFans; k++ ) + pRes0->pFans[k] = pRes1->pFans[k] = pObj->pFans[k]; + Kit_TruthCopy( Kit_DsdObjTruth(pRes0), pCofs2[0], pObj->nFans ); + Kit_TruthCopy( Kit_DsdObjTruth(pRes1), pCofs2[1], pObj->nFans ); + // update the current one + assert( pObj->Type == KIT_DSD_PRIME ); + pTruth[0] = 0xCACACACA; + pObj->nFans = 3; + pObj->pFans[0] = 2*pRes0->Id; pRes0->nRefs++; + pObj->pFans[1] = 2*pRes1->Id; pRes1->nRefs++; + pObj->pFans[2] = pObj->pFans[iBestVar]; + // call recursively + Kit_DsdDecompose_rec( pNtk, pRes0, uSupp0, pObj->pFans + 0, nDecMux ); + Kit_DsdDecompose_rec( pNtk, pRes1, uSupp1, pObj->pFans + 1, nDecMux ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdNtk_t * Kit_DsdDecomposeInt( unsigned * pTruth, int nVars, int nDecMux ) +{ + Kit_DsdNtk_t * pNtk; + Kit_DsdObj_t * pObj; + unsigned uSupp; + int i, nVarsReal; + assert( nVars <= 16 ); + pNtk = Kit_DsdNtkAlloc( nVars ); + pNtk->Root = Kit_DsdVar2Lit( pNtk->nVars, 0 ); + // create the first node + pObj = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, nVars ); + assert( pNtk->pNodes[0] == pObj ); + for ( i = 0; i < nVars; i++ ) + pObj->pFans[i] = Kit_DsdVar2Lit( i, 0 ); + Kit_TruthCopy( Kit_DsdObjTruth(pObj), pTruth, nVars ); + uSupp = Kit_TruthSupport( pTruth, nVars ); + // consider special cases + nVarsReal = Kit_WordCountOnes( uSupp ); + if ( nVarsReal == 0 ) + { + pObj->Type = KIT_DSD_CONST1; + pObj->nFans = 0; + if ( pTruth[0] == 0 ) + pNtk->Root = Kit_DsdLitNot(pNtk->Root); + return pNtk; + } + if ( nVarsReal == 1 ) + { + pObj->Type = KIT_DSD_VAR; + pObj->nFans = 1; + pObj->pFans[0] = Kit_DsdVar2Lit( Kit_WordFindFirstBit(uSupp), (pTruth[0] & 1) ); + return pNtk; + } + Kit_DsdDecompose_rec( pNtk, pNtk->pNodes[0], uSupp, &pNtk->Root, nDecMux ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdNtk_t * Kit_DsdDecompose( unsigned * pTruth, int nVars ) +{ + return Kit_DsdDecomposeInt( pTruth, nVars, 0 ); +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdNtk_t * Kit_DsdDecomposeExpand( unsigned * pTruth, int nVars ) +{ + Kit_DsdNtk_t * pNtk, * pTemp; + pNtk = Kit_DsdDecomposeInt( pTruth, nVars, 0 ); + pNtk = Kit_DsdExpand( pTemp = pNtk ); + Kit_DsdNtkFree( pTemp ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of the truth table.] + + Description [Uses MUXes to break-down large prime nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_DsdNtk_t * Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nDecMux ) +{ + return Kit_DsdDecomposeInt( pTruth, nVars, nDecMux ); +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdTestCofs( Kit_DsdNtk_t * pNtk, unsigned * pTruthInit ) +{ + Kit_DsdNtk_t * pNtk0, * pNtk1, * pTemp; +// Kit_DsdObj_t * pRoot; + unsigned * pCofs2[2] = { pNtk->pMem, pNtk->pMem + Kit_TruthWordNum(pNtk->nVars) }; + unsigned i, * pTruth; + int fVerbose = 1; + int RetValue = 0; + + pTruth = pTruthInit; +// pRoot = Kit_DsdNtkRoot(pNtk); +// pTruth = Kit_DsdObjTruth(pRoot); +// assert( pRoot->nFans == pNtk->nVars ); + + if ( fVerbose ) + { + printf( "Function: " ); +// Extra_PrintBinary( stdout, pTruth, (1 << pNtk->nVars) ); + Extra_PrintHexadecimal( stdout, pTruth, pNtk->nVars ); + printf( "\n" ); + Kit_DsdPrint( stdout, pNtk ); + } + for ( i = 0; i < pNtk->nVars; i++ ) + { + Kit_TruthCofactor0New( pCofs2[0], pTruth, pNtk->nVars, i ); + pNtk0 = Kit_DsdDecompose( pCofs2[0], pNtk->nVars ); + pNtk0 = Kit_DsdExpand( pTemp = pNtk0 ); + Kit_DsdNtkFree( pTemp ); + + if ( fVerbose ) + { + printf( "Cof%d0: ", i ); + Kit_DsdPrint( stdout, pNtk0 ); + } + + Kit_TruthCofactor1New( pCofs2[1], pTruth, pNtk->nVars, i ); + pNtk1 = Kit_DsdDecompose( pCofs2[1], pNtk->nVars ); + pNtk1 = Kit_DsdExpand( pTemp = pNtk1 ); + Kit_DsdNtkFree( pTemp ); + + if ( fVerbose ) + { + printf( "Cof%d1: ", i ); + Kit_DsdPrint( stdout, pNtk1 ); + } + +// if ( Kit_DsdCheckVar4Dec2( pNtk0, pNtk1 ) ) +// RetValue = 1; + + Kit_DsdNtkFree( pNtk0 ); + Kit_DsdNtkFree( pNtk1 ); + } + if ( fVerbose ) + printf( "\n" ); + + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdEval( unsigned * pTruth, int nVars, int nLutSize ) +{ + Kit_DsdMan_t * p; + Kit_DsdNtk_t * pNtk; + unsigned * pTruthC; + int Result; + + // decompose the function + pNtk = Kit_DsdDecompose( pTruth, nVars ); + Result = Kit_DsdCountLuts( pNtk, nLutSize ); +// printf( "\n" ); +// Kit_DsdPrint( stdout, pNtk ); +// printf( "Eval = %d.\n", Result ); + + // recompute the truth table + p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk) ); + pTruthC = Kit_DsdTruthCompute( p, pNtk ); + if ( !Kit_TruthIsEqual( pTruth, pTruthC, nVars ) ) + printf( "Verification failed.\n" ); + Kit_DsdManFree( p ); + + Kit_DsdNtkFree( pNtk ); + return Result; +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdVerify( Kit_DsdNtk_t * pNtk, unsigned * pTruth, int nVars ) +{ + Kit_DsdMan_t * p; + unsigned * pTruthC; + p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk)+2 ); + pTruthC = Kit_DsdTruthCompute( p, pNtk ); + if ( !Extra_TruthIsEqual( pTruth, pTruthC, nVars ) ) + printf( "Verification failed.\n" ); + Kit_DsdManFree( p ); +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdTest( unsigned * pTruth, int nVars ) +{ + Kit_DsdMan_t * p; + unsigned * pTruthC; + Kit_DsdNtk_t * pNtk, * pTemp; + pNtk = Kit_DsdDecompose( pTruth, nVars ); + +// if ( Kit_DsdFindLargeBox(pNtk, Kit_DsdLit2Var(pNtk->Root)) ) +// Kit_DsdPrint( stdout, pNtk ); + +// if ( Kit_DsdNtkRoot(pNtk)->nFans == (unsigned)nVars && nVars == 6 ) + + printf( "\n" ); + Kit_DsdPrint( stdout, pNtk ); + + pNtk = Kit_DsdExpand( pTemp = pNtk ); + Kit_DsdNtkFree( pTemp ); + + Kit_DsdPrint( stdout, pNtk ); + +// if ( Kit_DsdFindLargeBox(pNtk, Kit_DsdLit2Var(pNtk->Root)) ) +// Kit_DsdTestCofs( pNtk, pTruth ); + + // recompute the truth table + p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk) ); + pTruthC = Kit_DsdTruthCompute( p, pNtk ); +// Extra_PrintBinary( stdout, pTruth, 1 << nVars ); printf( "\n" ); +// Extra_PrintBinary( stdout, pTruthC, 1 << nVars ); printf( "\n" ); + if ( Extra_TruthIsEqual( pTruth, pTruthC, nVars ) ) + { +// printf( "Verification is okay.\n" ); + } + else + printf( "Verification failed.\n" ); + Kit_DsdManFree( p ); + + + Kit_DsdNtkFree( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdPrecompute4Vars() +{ + Kit_DsdMan_t * p; + Kit_DsdNtk_t * pNtk, * pTemp; + FILE * pFile; + unsigned uTruth; + unsigned * pTruthC; + char Buffer[256]; + int i, RetValue; + int Counter1 = 0, Counter2 = 0; + + pFile = fopen( "5npn/npn4.txt", "r" ); + for ( i = 0; fgets( Buffer, 100, pFile ); i++ ) + { + Buffer[6] = 0; + Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); + uTruth = ((uTruth & 0xffff) << 16) | (uTruth & 0xffff); + pNtk = Kit_DsdDecompose( &uTruth, 4 ); + + pNtk = Kit_DsdExpand( pTemp = pNtk ); + Kit_DsdNtkFree( pTemp ); + + + if ( Kit_DsdFindLargeBox(pNtk, 3) ) + { +// RetValue = 0; + RetValue = Kit_DsdTestCofs( pNtk, &uTruth ); + printf( "\n" ); + printf( "%3d : Non-DSD function %s %s\n", i, Buffer + 2, RetValue? "implementable" : "" ); + Kit_DsdPrint( stdout, pNtk ); + + Counter1++; + Counter2 += RetValue; + } + +/* + printf( "%3d : Function %s ", i, Buffer + 2 ); + if ( !Kit_DsdFindLargeBox(pNtk, 3) ) + Kit_DsdPrint( stdout, pNtk ); + else + printf( "\n" ); +*/ + + p = Kit_DsdManAlloc( 4, Kit_DsdNtkObjNum(pNtk) ); + pTruthC = Kit_DsdTruthCompute( p, pNtk ); + if ( !Extra_TruthIsEqual( &uTruth, pTruthC, 4 ) ) + printf( "Verification failed.\n" ); + Kit_DsdManFree( p ); + + Kit_DsdNtkFree( pNtk ); + } + fclose( pFile ); + printf( "non-DSD = %d implementable = %d\n", Counter1, Counter2 ); +} + + +/**Function************************************************************* + + Synopsis [Returns the set of cofactoring variables.] + + Description [If there is no DSD components returns 0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdCofactoringGetVars( Kit_DsdNtk_t ** ppNtk, int nSize, int * pVars ) +{ + Kit_DsdObj_t * pObj; + unsigned m; + int i, k, v, Var, nVars, iFaninLit; + // go through all the networks + nVars = 0; + for ( i = 0; i < nSize; i++ ) + { + // go through the prime objects of each networks + Kit_DsdNtkForEachObj( ppNtk[i], pObj, k ) + { + if ( pObj->Type != KIT_DSD_PRIME ) + continue; + if ( pObj->nFans == 3 ) + continue; + // collect direct fanin variables + Kit_DsdObjForEachFanin( ppNtk[i], pObj, iFaninLit, m ) + { + if ( !Kit_DsdLitIsLeaf(ppNtk[i], iFaninLit) ) + continue; + // add it to the array + Var = Kit_DsdLit2Var( iFaninLit ); + for ( v = 0; v < nVars; v++ ) + if ( pVars[v] == Var ) + break; + if ( v == nVars ) + pVars[nVars++] = Var; + } + } + } + return nVars; +} + +/**Function************************************************************* + + Synopsis [Canonical decomposition into completely DSD-structure.] + + Description [Returns the number of cofactoring steps. Also returns + the cofactoring variables in pVars.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_DsdCofactoring( unsigned * pTruth, int nVars, int * pCofVars, int nLimit, int fVerbose ) +{ + Kit_DsdNtk_t * ppNtks[5][16] = {0}, * pTemp; + unsigned * ppCofs[5][16]; + int pTryVars[16], nTryVars; + int nPrimeSizeMin, nPrimeSizeMax, nPrimeSizeCur; + int nSuppSizeMin, nSuppSizeMax, iVarBest; + int i, k, v, nStep, nSize, nMemSize; + assert( nLimit < 5 ); + + // allocate storage for cofactors + nMemSize = Kit_TruthWordNum(nVars); + ppCofs[0][0] = ALLOC( unsigned, 80 * nMemSize ); + nSize = 0; + for ( i = 0; i < 5; i++ ) + for ( k = 0; k < 16; k++ ) + ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++; + assert( nSize == 80 ); + + // copy the function + Kit_TruthCopy( ppCofs[0][0], pTruth, nVars ); + ppNtks[0][0] = Kit_DsdDecompose( ppCofs[0][0], nVars ); + + if ( fVerbose ) + printf( "\nProcessing prime function with %d support variables:\n", nVars ); + + // perform recursive cofactoring + for ( nStep = 0; nStep < nLimit; nStep++ ) + { + nSize = (1 << nStep); + // find the variables to use in the cofactoring step + nTryVars = Kit_DsdCofactoringGetVars( ppNtks[nStep], nSize, pTryVars ); + if ( nTryVars == 0 ) + break; + // cofactor w.r.t. the above variables + iVarBest = -1; + nPrimeSizeMin = 10000; + nSuppSizeMin = 10000; + for ( v = 0; v < nTryVars; v++ ) + { + nPrimeSizeMax = 0; + nSuppSizeMax = 0; + for ( i = 0; i < nSize; i++ ) + { + // cofactor and decompose cofactors + Kit_TruthCofactor0New( ppCofs[nStep+1][2*i+0], ppCofs[nStep][i], nVars, pTryVars[v] ); + Kit_TruthCofactor1New( ppCofs[nStep+1][2*i+1], ppCofs[nStep][i], nVars, pTryVars[v] ); + ppNtks[nStep+1][2*i+0] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+0], nVars ); + ppNtks[nStep+1][2*i+1] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+1], nVars ); + // compute the largest non-decomp block + nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[nStep+1][2*i+0]); + nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); + nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[nStep+1][2*i+1]); + nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); + // compute the sum total of supports + nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nStep+1][2*i+0], nVars ); + nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nStep+1][2*i+1], nVars ); + // free the networks + Kit_DsdNtkFree( ppNtks[nStep+1][2*i+0] ); + Kit_DsdNtkFree( ppNtks[nStep+1][2*i+1] ); + } + // find the min max support size of the prime component + if ( nPrimeSizeMin > nPrimeSizeMax || (nPrimeSizeMin == nPrimeSizeMax && nSuppSizeMin > nSuppSizeMax) ) + { + nPrimeSizeMin = nPrimeSizeMax; + nSuppSizeMin = nSuppSizeMax; + iVarBest = pTryVars[v]; + } + } + assert( iVarBest != -1 ); + // save the variable + if ( pCofVars ) + pCofVars[nStep] = iVarBest; + // cofactor w.r.t. the best + for ( i = 0; i < nSize; i++ ) + { + Kit_TruthCofactor0New( ppCofs[nStep+1][2*i+0], ppCofs[nStep][i], nVars, iVarBest ); + Kit_TruthCofactor1New( ppCofs[nStep+1][2*i+1], ppCofs[nStep][i], nVars, iVarBest ); + ppNtks[nStep+1][2*i+0] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+0], nVars ); + ppNtks[nStep+1][2*i+1] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+1], nVars ); + if ( fVerbose ) + { + ppNtks[nStep+1][2*i+0] = Kit_DsdExpand( pTemp = ppNtks[nStep+1][2*i+0] ); + Kit_DsdNtkFree( pTemp ); + ppNtks[nStep+1][2*i+1] = Kit_DsdExpand( pTemp = ppNtks[nStep+1][2*i+1] ); + Kit_DsdNtkFree( pTemp ); + + printf( "Cof%d%d: ", nStep+1, 2*i+0 ); + Kit_DsdPrint( stdout, ppNtks[nStep+1][2*i+0] ); + printf( "Cof%d%d: ", nStep+1, 2*i+1 ); + Kit_DsdPrint( stdout, ppNtks[nStep+1][2*i+1] ); + } + } + } + + // free the networks + for ( i = 0; i < 5; i++ ) + for ( k = 0; k < 16; k++ ) + if ( ppNtks[i][k] ) + Kit_DsdNtkFree( ppNtks[i][k] ); + free( ppCofs[0][0] ); + + assert( nStep <= nLimit ); + return nStep; +} + +/**Function************************************************************* + + Synopsis [Canonical decomposition into completely DSD-structure.] + + Description [Returns the number of cofactoring steps. Also returns + the cofactoring variables in pVars.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose ) +{ + Kit_DsdNtk_t * ppNtks[32] = {0}, * pTemp; + unsigned * ppCofs[5][16]; + int piCofVar[5]; + int nPrimeSizeMax, nPrimeSizeCur, nSuppSizeMax; + int i, k, v1, v2, v3, v4, s, nSteps, nSize, nMemSize; + assert( nCofLevel < 5 ); + + // print the function + ppNtks[0] = Kit_DsdDecompose( pTruth, nVars ); + ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); + Kit_DsdNtkFree( pTemp ); + if ( fVerbose ) + Kit_DsdPrint( stdout, ppNtks[0] ); + Kit_DsdNtkFree( ppNtks[0] ); + + // allocate storage for cofactors + nMemSize = Kit_TruthWordNum(nVars); + ppCofs[0][0] = ALLOC( unsigned, 80 * nMemSize ); + nSize = 0; + for ( i = 0; i < 5; i++ ) + for ( k = 0; k < 16; k++ ) + ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++; + assert( nSize == 80 ); + + // copy the function + Kit_TruthCopy( ppCofs[0][0], pTruth, nVars ); + + if ( nCofLevel == 1 ) + for ( v1 = 0; v1 < nVars; v1++ ) + { + nSteps = 0; + piCofVar[nSteps++] = v1; + + printf( " Variables { " ); + for ( i = 0; i < nSteps; i++ ) + printf( "%c ", 'a' + piCofVar[i] ); + printf( "}\n" ); + + // single cofactors + for ( s = 1; s <= nSteps; s++ ) + { + for ( k = 0; k < s; k++ ) + { + nSize = (1 << k); + for ( i = 0; i < nSize; i++ ) + { + Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); + Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); + } + } + } + // compute DSD networks + nSize = (1 << nSteps); + nPrimeSizeMax = 0; + nSuppSizeMax = 0; + for ( i = 0; i < nSize; i++ ) + { + ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); + ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); + Kit_DsdNtkFree( pTemp ); + if ( fVerbose ) + { + printf( "Cof%d%d: ", nSteps, i ); + Kit_DsdPrint( stdout, ppNtks[i] ); + } + // compute the largest non-decomp block + nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); + nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); + Kit_DsdNtkFree( ppNtks[i] ); + nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); + } + printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); + } + + if ( nCofLevel == 2 ) + for ( v1 = 0; v1 < nVars; v1++ ) + for ( v2 = v1+1; v2 < nVars; v2++ ) + { + nSteps = 0; + piCofVar[nSteps++] = v1; + piCofVar[nSteps++] = v2; + + printf( " Variables { " ); + for ( i = 0; i < nSteps; i++ ) + printf( "%c ", 'a' + piCofVar[i] ); + printf( "}\n" ); + + // single cofactors + for ( s = 1; s <= nSteps; s++ ) + { + for ( k = 0; k < s; k++ ) + { + nSize = (1 << k); + for ( i = 0; i < nSize; i++ ) + { + Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); + Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); + } + } + } + // compute DSD networks + nSize = (1 << nSteps); + nPrimeSizeMax = 0; + nSuppSizeMax = 0; + for ( i = 0; i < nSize; i++ ) + { + ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); + ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); + Kit_DsdNtkFree( pTemp ); + if ( fVerbose ) + { + printf( "Cof%d%d: ", nSteps, i ); + Kit_DsdPrint( stdout, ppNtks[i] ); + } + // compute the largest non-decomp block + nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); + nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); + Kit_DsdNtkFree( ppNtks[i] ); + nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); + } + printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); + } + + if ( nCofLevel == 3 ) + for ( v1 = 0; v1 < nVars; v1++ ) + for ( v2 = v1+1; v2 < nVars; v2++ ) + for ( v3 = v2+1; v3 < nVars; v3++ ) + { + nSteps = 0; + piCofVar[nSteps++] = v1; + piCofVar[nSteps++] = v2; + piCofVar[nSteps++] = v3; + + printf( " Variables { " ); + for ( i = 0; i < nSteps; i++ ) + printf( "%c ", 'a' + piCofVar[i] ); + printf( "}\n" ); + + // single cofactors + for ( s = 1; s <= nSteps; s++ ) + { + for ( k = 0; k < s; k++ ) + { + nSize = (1 << k); + for ( i = 0; i < nSize; i++ ) + { + Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); + Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); + } + } + } + // compute DSD networks + nSize = (1 << nSteps); + nPrimeSizeMax = 0; + nSuppSizeMax = 0; + for ( i = 0; i < nSize; i++ ) + { + ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); + ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); + Kit_DsdNtkFree( pTemp ); + if ( fVerbose ) + { + printf( "Cof%d%d: ", nSteps, i ); + Kit_DsdPrint( stdout, ppNtks[i] ); + } + // compute the largest non-decomp block + nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); + nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); + Kit_DsdNtkFree( ppNtks[i] ); + nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); + } + printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); + } + + if ( nCofLevel == 4 ) + for ( v1 = 0; v1 < nVars; v1++ ) + for ( v2 = v1+1; v2 < nVars; v2++ ) + for ( v3 = v2+1; v3 < nVars; v3++ ) + for ( v4 = v3+1; v4 < nVars; v4++ ) + { + nSteps = 0; + piCofVar[nSteps++] = v1; + piCofVar[nSteps++] = v2; + piCofVar[nSteps++] = v3; + piCofVar[nSteps++] = v4; + + printf( " Variables { " ); + for ( i = 0; i < nSteps; i++ ) + printf( "%c ", 'a' + piCofVar[i] ); + printf( "}\n" ); + + // single cofactors + for ( s = 1; s <= nSteps; s++ ) + { + for ( k = 0; k < s; k++ ) + { + nSize = (1 << k); + for ( i = 0; i < nSize; i++ ) + { + Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); + Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); + } + } + } + // compute DSD networks + nSize = (1 << nSteps); + nPrimeSizeMax = 0; + nSuppSizeMax = 0; + for ( i = 0; i < nSize; i++ ) + { + ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); + ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); + Kit_DsdNtkFree( pTemp ); + if ( fVerbose ) + { + printf( "Cof%d%d: ", nSteps, i ); + Kit_DsdPrint( stdout, ppNtks[i] ); + } + // compute the largest non-decomp block + nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); + nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); + Kit_DsdNtkFree( ppNtks[i] ); + nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); + } + printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); + } + + + free( ppCofs[0][0] ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/kit/kitFactor.c b/abc70930/src/aig/kit/kitFactor.c new file mode 100644 index 00000000..e3288342 --- /dev/null +++ b/abc70930/src/aig/kit/kitFactor.c @@ -0,0 +1,339 @@ +/**CFile**************************************************************** + + FileName [kitFactor.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [Algebraic factoring.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kitFactor.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// factoring fails if intermediate memory usage exceed this limit +#define KIT_FACTOR_MEM_LIMIT (1<<16) + +static Kit_Edge_t Kit_SopFactor_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ); +static Kit_Edge_t Kit_SopFactorLF_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, Kit_Sop_t * cSimple, int nLits, Vec_Int_t * vMemory ); +static Kit_Edge_t Kit_SopFactorTrivial( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits ); +static Kit_Edge_t Kit_SopFactorTrivialCube( Kit_Graph_t * pFForm, unsigned uCube, int nLits ); + +extern int Kit_SopFactorVerify( Vec_Int_t * cSop, Kit_Graph_t * pFForm, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Factors the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Graph_t * Kit_SopFactor( Vec_Int_t * vCover, int fCompl, int nVars, Vec_Int_t * vMemory ) +{ + Kit_Sop_t Sop, * cSop = &Sop; + Kit_Graph_t * pFForm; + Kit_Edge_t eRoot; +// int nCubes; + + // works for up to 15 variables because divisin procedure + // used the last bit for marking the cubes going to the remainder + assert( nVars < 16 ); + + // check for trivial functions + if ( Vec_IntSize(vCover) == 0 ) + return Kit_GraphCreateConst0(); + if ( Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover, 0) == 0 ) + return Kit_GraphCreateConst1(); + + // prepare memory manager +// Vec_IntClear( vMemory ); + Vec_IntGrow( vMemory, KIT_FACTOR_MEM_LIMIT ); + + // perform CST + Kit_SopCreateInverse( cSop, vCover, 2 * nVars, vMemory ); // CST + + // start the factored form + pFForm = Kit_GraphCreate( nVars ); + // factor the cover + eRoot = Kit_SopFactor_rec( pFForm, cSop, 2 * nVars, vMemory ); + // finalize the factored form + Kit_GraphSetRoot( pFForm, eRoot ); + if ( fCompl ) + Kit_GraphComplement( pFForm ); + + // verify the factored form +// nCubes = Vec_IntSize(vCover); +// Vec_IntShrink( vCover, nCubes ); +// if ( !Kit_SopFactorVerify( vCover, pFForm, nVars ) ) +// printf( "Verification has failed.\n" ); + return pFForm; +} + +/**Function************************************************************* + + Synopsis [Recursive factoring procedure.] + + Description [For the pseudo-code, see Hachtel/Somenzi, + Logic synthesis and verification algorithms, Kluwer, 1996, p. 432.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Edge_t Kit_SopFactor_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ) +{ + Kit_Sop_t Div, Quo, Rem, Com; + Kit_Sop_t * cDiv = &Div, * cQuo = &Quo, * cRem = &Rem, * cCom = &Com; + Kit_Edge_t eNodeDiv, eNodeQuo, eNodeRem, eNodeAnd; + + // make sure the cover contains some cubes + assert( Kit_SopCubeNum(cSop) > 0 ); + + // get the divisor + if ( !Kit_SopDivisor(cDiv, cSop, nLits, vMemory) ) + return Kit_SopFactorTrivial( pFForm, cSop, nLits ); + + // divide the cover by the divisor + Kit_SopDivideInternal( cSop, cDiv, cQuo, cRem, vMemory ); + + // check the trivial case + assert( Kit_SopCubeNum(cQuo) > 0 ); + if ( Kit_SopCubeNum(cQuo) == 1 ) + return Kit_SopFactorLF_rec( pFForm, cSop, cQuo, nLits, vMemory ); + + // make the quotient cube free + Kit_SopMakeCubeFree( cQuo ); + + // divide the cover by the quotient + Kit_SopDivideInternal( cSop, cQuo, cDiv, cRem, vMemory ); + + // check the trivial case + if ( Kit_SopIsCubeFree( cDiv ) ) + { + eNodeDiv = Kit_SopFactor_rec( pFForm, cDiv, nLits, vMemory ); + eNodeQuo = Kit_SopFactor_rec( pFForm, cQuo, nLits, vMemory ); + eNodeAnd = Kit_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); + if ( Kit_SopCubeNum(cRem) == 0 ) + return eNodeAnd; + eNodeRem = Kit_SopFactor_rec( pFForm, cRem, nLits, vMemory ); + return Kit_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); + } + + // get the common cube + Kit_SopCommonCubeCover( cCom, cDiv, vMemory ); + + // solve the simple problem + return Kit_SopFactorLF_rec( pFForm, cSop, cCom, nLits, vMemory ); +} + + +/**Function************************************************************* + + Synopsis [Internal recursive factoring procedure for the leaf case.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Edge_t Kit_SopFactorLF_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, Kit_Sop_t * cSimple, int nLits, Vec_Int_t * vMemory ) +{ + Kit_Sop_t Div, Quo, Rem; + Kit_Sop_t * cDiv = &Div, * cQuo = &Quo, * cRem = &Rem; + Kit_Edge_t eNodeDiv, eNodeQuo, eNodeRem, eNodeAnd; + assert( Kit_SopCubeNum(cSimple) == 1 ); + // get the most often occurring literal + Kit_SopBestLiteralCover( cDiv, cSop, Kit_SopCube(cSimple, 0), nLits, vMemory ); + // divide the cover by the literal + Kit_SopDivideByCube( cSop, cDiv, cQuo, cRem, vMemory ); + // get the node pointer for the literal + eNodeDiv = Kit_SopFactorTrivialCube( pFForm, Kit_SopCube(cDiv, 0), nLits ); + // factor the quotient and remainder + eNodeQuo = Kit_SopFactor_rec( pFForm, cQuo, nLits, vMemory ); + eNodeAnd = Kit_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); + if ( Kit_SopCubeNum(cRem) == 0 ) + return eNodeAnd; + eNodeRem = Kit_SopFactor_rec( pFForm, cRem, nLits, vMemory ); + return Kit_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); +} + + +/**Function************************************************************* + + Synopsis [Factoring cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Edge_t Kit_SopFactorTrivialCube_rec( Kit_Graph_t * pFForm, unsigned uCube, int nStart, int nFinish ) +{ + Kit_Edge_t eNode1, eNode2; + int i, iLit = -1, nLits, nLits1, nLits2; + assert( uCube ); + // count the number of literals in this interval + nLits = 0; + for ( i = nStart; i < nFinish; i++ ) + if ( Kit_CubeHasLit(uCube, i) ) + { + iLit = i; + nLits++; + } + assert( iLit != -1 ); + // quit if there is only one literal + if ( nLits == 1 ) + return Kit_EdgeCreate( iLit/2, iLit%2 ); // CST + // split the literals into two parts + nLits1 = nLits/2; + nLits2 = nLits - nLits1; +// nLits2 = nLits/2; +// nLits1 = nLits - nLits2; + // find the splitting point + nLits = 0; + for ( i = nStart; i < nFinish; i++ ) + if ( Kit_CubeHasLit(uCube, i) ) + { + if ( nLits == nLits1 ) + break; + nLits++; + } + // recursively construct the tree for the parts + eNode1 = Kit_SopFactorTrivialCube_rec( pFForm, uCube, nStart, i ); + eNode2 = Kit_SopFactorTrivialCube_rec( pFForm, uCube, i, nFinish ); + return Kit_GraphAddNodeAnd( pFForm, eNode1, eNode2 ); +} + +/**Function************************************************************* + + Synopsis [Factoring cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Edge_t Kit_SopFactorTrivialCube( Kit_Graph_t * pFForm, unsigned uCube, int nLits ) +{ + return Kit_SopFactorTrivialCube_rec( pFForm, uCube, 0, nLits ); +} + +/**Function************************************************************* + + Synopsis [Factoring SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Edge_t Kit_SopFactorTrivial_rec( Kit_Graph_t * pFForm, unsigned * pCubes, int nCubes, int nLits ) +{ + Kit_Edge_t eNode1, eNode2; + int nCubes1, nCubes2; + if ( nCubes == 1 ) + return Kit_SopFactorTrivialCube_rec( pFForm, pCubes[0], 0, nLits ); + // split the cubes into two parts + nCubes1 = nCubes/2; + nCubes2 = nCubes - nCubes1; +// nCubes2 = nCubes/2; +// nCubes1 = nCubes - nCubes2; + // recursively construct the tree for the parts + eNode1 = Kit_SopFactorTrivial_rec( pFForm, pCubes, nCubes1, nLits ); + eNode2 = Kit_SopFactorTrivial_rec( pFForm, pCubes + nCubes1, nCubes2, nLits ); + return Kit_GraphAddNodeOr( pFForm, eNode1, eNode2 ); +} + +/**Function************************************************************* + + Synopsis [Factoring the cover, which has no algebraic divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Edge_t Kit_SopFactorTrivial( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits ) +{ + return Kit_SopFactorTrivial_rec( pFForm, cSop->pCubes, cSop->nCubes, nLits ); +} + + +/**Function************************************************************* + + Synopsis [Testing procedure for the factoring code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_FactorTest( unsigned * pTruth, int nVars ) +{ + Vec_Int_t * vCover, * vMemory; + Kit_Graph_t * pGraph; +// unsigned uTruthRes; + int RetValue; + + // derive SOP + vCover = Vec_IntAlloc( 0 ); + RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 ); + assert( RetValue == 0 ); + + // derive factored form + vMemory = Vec_IntAlloc( 0 ); + pGraph = Kit_SopFactor( vCover, 0, nVars, vMemory ); +/* + // derive truth table + assert( nVars <= 5 ); + uTruthRes = Kit_GraphToTruth( pGraph ); + if ( uTruthRes != pTruth[0] ) + printf( "Verification failed!" ); +*/ + printf( "Vars = %2d. Cubes = %3d. FFNodes = %3d. FF_memory = %3d.\n", + nVars, Vec_IntSize(vCover), Kit_GraphNodeNum(pGraph), Vec_IntSize(vMemory) ); + + Vec_IntFree( vMemory ); + Vec_IntFree( vCover ); + Kit_GraphFree( pGraph ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/kit/kitGraph.c b/abc70930/src/aig/kit/kitGraph.c new file mode 100644 index 00000000..80dcbdc0 --- /dev/null +++ b/abc70930/src/aig/kit/kitGraph.c @@ -0,0 +1,397 @@ +/**CFile**************************************************************** + + FileName [kitGraph.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [Decomposition graph representation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kitGraph.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a graph with the given number of leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Graph_t * Kit_GraphCreate( int nLeaves ) +{ + Kit_Graph_t * pGraph; + pGraph = ALLOC( Kit_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Kit_Graph_t) ); + pGraph->nLeaves = nLeaves; + pGraph->nSize = nLeaves; + pGraph->nCap = 2 * nLeaves + 50; + pGraph->pNodes = ALLOC( Kit_Node_t, pGraph->nCap ); + memset( pGraph->pNodes, 0, sizeof(Kit_Node_t) * pGraph->nSize ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates constant 0 graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Graph_t * Kit_GraphCreateConst0() +{ + Kit_Graph_t * pGraph; + pGraph = ALLOC( Kit_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Kit_Graph_t) ); + pGraph->fConst = 1; + pGraph->eRoot.fCompl = 1; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates constant 1 graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Graph_t * Kit_GraphCreateConst1() +{ + Kit_Graph_t * pGraph; + pGraph = ALLOC( Kit_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Kit_Graph_t) ); + pGraph->fConst = 1; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates the literal graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Graph_t * Kit_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ) +{ + Kit_Graph_t * pGraph; + assert( 0 <= iLeaf && iLeaf < nLeaves ); + pGraph = Kit_GraphCreate( nLeaves ); + pGraph->eRoot.Node = iLeaf; + pGraph->eRoot.fCompl = fCompl; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates a graph with the given number of leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_GraphFree( Kit_Graph_t * pGraph ) +{ + FREE( pGraph->pNodes ); + free( pGraph ); +} + +/**Function************************************************************* + + Synopsis [Appends a new node to the graph.] + + Description [This procedure is meant for internal use.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Node_t * Kit_GraphAppendNode( Kit_Graph_t * pGraph ) +{ + Kit_Node_t * pNode; + if ( pGraph->nSize == pGraph->nCap ) + { + pGraph->pNodes = REALLOC( Kit_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); + pGraph->nCap = 2 * pGraph->nCap; + } + pNode = pGraph->pNodes + pGraph->nSize++; + memset( pNode, 0, sizeof(Kit_Node_t) ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates an AND node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Edge_t Kit_GraphAddNodeAnd( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ) +{ + Kit_Node_t * pNode; + // get the new node + pNode = Kit_GraphAppendNode( pGraph ); + // set the inputs and other info + pNode->eEdge0 = eEdge0; + pNode->eEdge1 = eEdge1; + pNode->fCompl0 = eEdge0.fCompl; + pNode->fCompl1 = eEdge1.fCompl; + return Kit_EdgeCreate( pGraph->nSize - 1, 0 ); +} + +/**Function************************************************************* + + Synopsis [Creates an OR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Edge_t Kit_GraphAddNodeOr( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ) +{ + Kit_Node_t * pNode; + // get the new node + pNode = Kit_GraphAppendNode( pGraph ); + // set the inputs and other info + pNode->eEdge0 = eEdge0; + pNode->eEdge1 = eEdge1; + pNode->fCompl0 = eEdge0.fCompl; + pNode->fCompl1 = eEdge1.fCompl; + // make adjustments for the OR gate + pNode->fNodeOr = 1; + pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl; + pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl; + return Kit_EdgeCreate( pGraph->nSize - 1, 1 ); +} + +/**Function************************************************************* + + Synopsis [Creates an XOR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Edge_t Kit_GraphAddNodeXor( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1, int Type ) +{ + Kit_Edge_t eNode0, eNode1, eNode; + if ( Type == 0 ) + { + // derive the first AND + eEdge0.fCompl ^= 1; + eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + eEdge0.fCompl ^= 1; + // derive the second AND + eEdge1.fCompl ^= 1; + eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the final OR + eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + } + else + { + // derive the first AND + eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the second AND + eEdge0.fCompl ^= 1; + eEdge1.fCompl ^= 1; + eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the final OR + eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + eNode.fCompl ^= 1; + } + return eNode; +} + +/**Function************************************************************* + + Synopsis [Creates an XOR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Edge_t Kit_GraphAddNodeMux( Kit_Graph_t * pGraph, Kit_Edge_t eEdgeC, Kit_Edge_t eEdgeT, Kit_Edge_t eEdgeE, int Type ) +{ + Kit_Edge_t eNode0, eNode1, eNode; + if ( Type == 0 ) + { + // derive the first AND + eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); + // derive the second AND + eEdgeC.fCompl ^= 1; + eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); + // derive the final OR + eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + } + else + { + // complement the arguments + eEdgeT.fCompl ^= 1; + eEdgeE.fCompl ^= 1; + // derive the first AND + eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); + // derive the second AND + eEdgeC.fCompl ^= 1; + eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); + // derive the final OR + eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + eNode.fCompl ^= 1; + } + return eNode; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Kit_GraphToTruth( Kit_Graph_t * pGraph ) +{ + unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + unsigned uTruth = 0, uTruth0, uTruth1; + Kit_Node_t * pNode; + int i; + + // sanity checks + assert( Kit_GraphLeaveNum(pGraph) >= 0 ); + assert( Kit_GraphLeaveNum(pGraph) <= pGraph->nSize ); + assert( Kit_GraphLeaveNum(pGraph) <= 5 ); + + // check for constant function + if ( Kit_GraphIsConst(pGraph) ) + return Kit_GraphIsComplement(pGraph)? 0 : ~((unsigned)0); + // check for a literal + if ( Kit_GraphIsVar(pGraph) ) + return Kit_GraphIsComplement(pGraph)? ~uTruths[Kit_GraphVarInt(pGraph)] : uTruths[Kit_GraphVarInt(pGraph)]; + + // assign the elementary variables + Kit_GraphForEachLeaf( pGraph, pNode, i ) + pNode->pFunc = (void *)(long)uTruths[i]; + + // compute the function for each internal node + Kit_GraphForEachNode( pGraph, pNode, i ) + { + uTruth0 = (unsigned)(long)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; + uTruth1 = (unsigned)(long)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; + uTruth0 = pNode->eEdge0.fCompl? ~uTruth0 : uTruth0; + uTruth1 = pNode->eEdge1.fCompl? ~uTruth1 : uTruth1; + uTruth = uTruth0 & uTruth1; + pNode->pFunc = (void *)(long)uTruth; + } + + // complement the result if necessary + return Kit_GraphIsComplement(pGraph)? ~uTruth : uTruth; +} + +/**Function************************************************************* + + Synopsis [Derives the factored form from the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) +{ + Kit_Graph_t * pGraph; + int RetValue; + // derive SOP + RetValue = Kit_TruthIsop( pTruth, nVars, vMemory, 1 ); // tried 1 and found not useful in "renode" + if ( RetValue == -1 ) + return NULL; + if ( Vec_IntSize(vMemory) > 128 ) + return NULL; +// printf( "Isop size = %d.\n", Vec_IntSize(vMemory) ); + assert( RetValue == 0 || RetValue == 1 ); + // derive factored form + pGraph = Kit_SopFactor( vMemory, RetValue, nVars, vMemory ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Derives the maximum depth from the leaf to the root.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_GraphLeafDepth_rec( Kit_Graph_t * pGraph, Kit_Node_t * pNode, Kit_Node_t * pLeaf ) +{ + int Depth0, Depth1, Depth; + if ( pNode == pLeaf ) + return 0; + if ( Kit_GraphNodeIsVar(pGraph, pNode) ) + return -100; + Depth0 = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeFanin0(pGraph, pNode), pLeaf ); + Depth1 = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeFanin1(pGraph, pNode), pLeaf ); + Depth = KIT_MAX( Depth0, Depth1 ); + Depth = (Depth == -100) ? -100 : Depth + 1; + return Depth; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/kit/kitHop.c b/abc70930/src/aig/kit/kitHop.c new file mode 100644 index 00000000..86ec5a88 --- /dev/null +++ b/abc70930/src/aig/kit/kitHop.c @@ -0,0 +1,144 @@ +/**CFile**************************************************************** + + FileName [kitHop.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [Procedures involving AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kitHop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" +#include "hop.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Kit_GraphToHopInternal( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) +{ + Kit_Node_t * pNode = NULL; + Hop_Obj_t * pAnd0, * pAnd1; + int i; + // check for constant function + if ( Kit_GraphIsConst(pGraph) ) + return Hop_NotCond( Hop_ManConst1(pMan), Kit_GraphIsComplement(pGraph) ); + // check for a literal + if ( Kit_GraphIsVar(pGraph) ) + return Hop_NotCond( Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Kit_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Hop_NotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Hop_NotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 ); + } + // complement the result if necessary + return Hop_NotCond( pNode->pFunc, Kit_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) +{ + Kit_Node_t * pNode = NULL; + int i; + // collect the fanins + Kit_GraphForEachLeaf( pGraph, pNode, i ) + pNode->pFunc = Hop_IthVar( pMan, i ); + // perform strashing + return Kit_GraphToHopInternal( pMan, pGraph ); +} + +/**Function************************************************************* + + Synopsis [Strashed onen logic nodes using its truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) +{ + Hop_Obj_t * pObj; + Kit_Graph_t * pGraph; + // transform truth table into the decomposition tree + if ( vMemory == NULL ) + { + vMemory = Vec_IntAlloc( 0 ); + pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); + Vec_IntFree( vMemory ); + } + else + pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); + // derive the AIG for the decomposition tree + pObj = Kit_GraphToHop( pMan, pGraph ); + Kit_GraphFree( pGraph ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory ) +{ + Kit_Graph_t * pGraph; + Hop_Obj_t * pFunc; + // perform factoring + pGraph = Kit_SopFactor( vCover, 0, nVars, vMemory ); + // convert graph to the AIG + pFunc = Kit_GraphToHop( pMan, pGraph ); + Kit_GraphFree( pGraph ); + return pFunc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/kit/kitIsop.c b/abc70930/src/aig/kit/kitIsop.c new file mode 100644 index 00000000..42fae2ea --- /dev/null +++ b/abc70930/src/aig/kit/kitIsop.c @@ -0,0 +1,325 @@ +/**CFile**************************************************************** + + FileName [kitIsop.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [ISOP computation based on Morreale's algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kitIsop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// ISOP computation fails if intermediate memory usage exceed this limit +#define KIT_ISOP_MEM_LIMIT (1<<16) + +// static procedures to compute ISOP +static unsigned * Kit_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ); +static unsigned Kit_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes ISOP from TT.] + + Description [Returns the cover in vMemory. Uses the rest of array in vMemory + as an intermediate memory storage. Returns the cover with -1 cubes, if the + the computation exceeded the memory limit (KIT_ISOP_MEM_LIMIT words of + intermediate data).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth ) +{ + Kit_Sop_t cRes, * pcRes = &cRes; + Kit_Sop_t cRes2, * pcRes2 = &cRes2; + unsigned * pResult; + int RetValue = 0; + assert( nVars >= 0 && nVars < 16 ); + // if nVars < 5, make sure it does not depend on those vars +// for ( i = nVars; i < 5; i++ ) +// assert( !Kit_TruthVarInSupport(puTruth, 5, i) ); + // prepare memory manager + Vec_IntClear( vMemory ); + Vec_IntGrow( vMemory, KIT_ISOP_MEM_LIMIT ); + // compute ISOP for the direct polarity + pResult = Kit_TruthIsop_rec( puTruth, puTruth, nVars, pcRes, vMemory ); + if ( pcRes->nCubes == -1 ) + { + vMemory->nSize = -1; + return -1; + } + assert( Kit_TruthIsEqual( puTruth, pResult, nVars ) ); + if ( pcRes->nCubes == 0 || (pcRes->nCubes == 1 && pcRes->pCubes[0] == 0) ) + { + vMemory->pArray[0] = 0; + Vec_IntShrink( vMemory, pcRes->nCubes ); + return 0; + } + if ( fTryBoth ) + { + // compute ISOP for the complemented polarity + Kit_TruthNot( puTruth, puTruth, nVars ); + pResult = Kit_TruthIsop_rec( puTruth, puTruth, nVars, pcRes2, vMemory ); + if ( pcRes2->nCubes >= 0 ) + { + assert( Kit_TruthIsEqual( puTruth, pResult, nVars ) ); + if ( pcRes->nCubes > pcRes2->nCubes ) + { + RetValue = 1; + pcRes = pcRes2; + } + } + Kit_TruthNot( puTruth, puTruth, nVars ); + } +// printf( "%d ", vMemory->nSize ); + // move the cover representation to the beginning of the memory buffer + memmove( vMemory->pArray, pcRes->pCubes, pcRes->nCubes * sizeof(unsigned) ); + Vec_IntShrink( vMemory, pcRes->nCubes ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Computes ISOP 6 variables or more.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Kit_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ) +{ + Kit_Sop_t cRes0, cRes1, cRes2; + Kit_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2; + unsigned * puRes0, * puRes1, * puRes2; + unsigned * puOn0, * puOn1, * puOnDc0, * puOnDc1, * pTemp, * pTemp0, * pTemp1; + int i, k, Var, nWords, nWordsAll; +// assert( Kit_TruthIsImply( puOn, puOnDc, nVars ) ); + // allocate room for the resulting truth table + nWordsAll = Kit_TruthWordNum( nVars ); + pTemp = Vec_IntFetch( vStore, nWordsAll ); + if ( pTemp == NULL ) + { + pcRes->nCubes = -1; + return NULL; + } + // check for constants + if ( Kit_TruthIsConst0( puOn, nVars ) ) + { + pcRes->nCubes = 0; + pcRes->pCubes = NULL; + Kit_TruthClear( pTemp, nVars ); + return pTemp; + } + if ( Kit_TruthIsConst1( puOnDc, nVars ) ) + { + pcRes->nCubes = 1; + pcRes->pCubes = Vec_IntFetch( vStore, 1 ); + if ( pcRes->pCubes == NULL ) + { + pcRes->nCubes = -1; + return NULL; + } + pcRes->pCubes[0] = 0; + Kit_TruthFill( pTemp, nVars ); + return pTemp; + } + assert( nVars > 0 ); + // find the topmost var + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Kit_TruthVarInSupport( puOn, nVars, Var ) || + Kit_TruthVarInSupport( puOnDc, nVars, Var ) ) + break; + assert( Var >= 0 ); + // consider a simple case when one-word computation can be used + if ( Var < 5 ) + { + unsigned uRes = Kit_TruthIsop5_rec( puOn[0], puOnDc[0], Var+1, pcRes, vStore ); + for ( i = 0; i < nWordsAll; i++ ) + pTemp[i] = uRes; + return pTemp; + } + assert( Var >= 5 ); + nWords = Kit_TruthWordNum( Var ); + // cofactor + puOn0 = puOn; puOn1 = puOn + nWords; + puOnDc0 = puOnDc; puOnDc1 = puOnDc + nWords; + pTemp0 = pTemp; pTemp1 = pTemp + nWords; + // solve for cofactors + Kit_TruthSharp( pTemp0, puOn0, puOnDc1, Var ); + puRes0 = Kit_TruthIsop_rec( pTemp0, puOnDc0, Var, pcRes0, vStore ); + if ( pcRes0->nCubes == -1 ) + { + pcRes->nCubes = -1; + return NULL; + } + Kit_TruthSharp( pTemp1, puOn1, puOnDc0, Var ); + puRes1 = Kit_TruthIsop_rec( pTemp1, puOnDc1, Var, pcRes1, vStore ); + if ( pcRes1->nCubes == -1 ) + { + pcRes->nCubes = -1; + return NULL; + } + Kit_TruthSharp( pTemp0, puOn0, puRes0, Var ); + Kit_TruthSharp( pTemp1, puOn1, puRes1, Var ); + Kit_TruthOr( pTemp0, pTemp0, pTemp1, Var ); + Kit_TruthAnd( pTemp1, puOnDc0, puOnDc1, Var ); + puRes2 = Kit_TruthIsop_rec( pTemp0, pTemp1, Var, pcRes2, vStore ); + if ( pcRes2->nCubes == -1 ) + { + pcRes->nCubes = -1; + return NULL; + } + // create the resulting cover + pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes; + pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes ); + if ( pcRes->pCubes == NULL ) + { + pcRes->nCubes = -1; + return NULL; + } + k = 0; + for ( i = 0; i < pcRes0->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+0)); + for ( i = 0; i < pcRes1->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+1)); + for ( i = 0; i < pcRes2->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes2->pCubes[i]; + assert( k == pcRes->nCubes ); + // create the resulting truth table + Kit_TruthOr( pTemp0, puRes0, puRes2, Var ); + Kit_TruthOr( pTemp1, puRes1, puRes2, Var ); + // copy the table if needed + nWords <<= 1; + for ( i = 1; i < nWordsAll/nWords; i++ ) + for ( k = 0; k < nWords; k++ ) + pTemp[i*nWords + k] = pTemp[k]; + // verify in the end +// assert( Kit_TruthIsImply( puOn, pTemp, nVars ) ); +// assert( Kit_TruthIsImply( pTemp, puOnDc, nVars ) ); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [Computes ISOP for 5 variables or less.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Kit_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ) +{ + unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + Kit_Sop_t cRes0, cRes1, cRes2; + Kit_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2; + unsigned uOn0, uOn1, uOnDc0, uOnDc1, uRes0, uRes1, uRes2; + int i, k, Var; + assert( nVars <= 5 ); + assert( (uOn & ~uOnDc) == 0 ); + if ( uOn == 0 ) + { + pcRes->nCubes = 0; + pcRes->pCubes = NULL; + return 0; + } + if ( uOnDc == 0xFFFFFFFF ) + { + pcRes->nCubes = 1; + pcRes->pCubes = Vec_IntFetch( vStore, 1 ); + if ( pcRes->pCubes == NULL ) + { + pcRes->nCubes = -1; + return 0; + } + pcRes->pCubes[0] = 0; + return 0xFFFFFFFF; + } + assert( nVars > 0 ); + // find the topmost var + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Kit_TruthVarInSupport( &uOn, 5, Var ) || + Kit_TruthVarInSupport( &uOnDc, 5, Var ) ) + break; + assert( Var >= 0 ); + // cofactor + uOn0 = uOn1 = uOn; + uOnDc0 = uOnDc1 = uOnDc; + Kit_TruthCofactor0( &uOn0, Var + 1, Var ); + Kit_TruthCofactor1( &uOn1, Var + 1, Var ); + Kit_TruthCofactor0( &uOnDc0, Var + 1, Var ); + Kit_TruthCofactor1( &uOnDc1, Var + 1, Var ); + // solve for cofactors + uRes0 = Kit_TruthIsop5_rec( uOn0 & ~uOnDc1, uOnDc0, Var, pcRes0, vStore ); + if ( pcRes0->nCubes == -1 ) + { + pcRes->nCubes = -1; + return 0; + } + uRes1 = Kit_TruthIsop5_rec( uOn1 & ~uOnDc0, uOnDc1, Var, pcRes1, vStore ); + if ( pcRes1->nCubes == -1 ) + { + pcRes->nCubes = -1; + return 0; + } + uRes2 = Kit_TruthIsop5_rec( (uOn0 & ~uRes0) | (uOn1 & ~uRes1), uOnDc0 & uOnDc1, Var, pcRes2, vStore ); + if ( pcRes2->nCubes == -1 ) + { + pcRes->nCubes = -1; + return 0; + } + // create the resulting cover + pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes; + pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes ); + if ( pcRes->pCubes == NULL ) + { + pcRes->nCubes = -1; + return 0; + } + k = 0; + for ( i = 0; i < pcRes0->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+0)); + for ( i = 0; i < pcRes1->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+1)); + for ( i = 0; i < pcRes2->nCubes; i++ ) + pcRes->pCubes[k++] = pcRes2->pCubes[i]; + assert( k == pcRes->nCubes ); + // derive the final truth table + uRes2 |= (uRes0 & ~uMasks[Var]) | (uRes1 & uMasks[Var]); +// assert( (uOn & ~uRes2) == 0 ); +// assert( (uRes2 & ~uOnDc) == 0 ); + return uRes2; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/kit/kitSop.c b/abc70930/src/aig/kit/kitSop.c new file mode 100644 index 00000000..20ad0651 --- /dev/null +++ b/abc70930/src/aig/kit/kitSop.c @@ -0,0 +1,572 @@ +/**CFile**************************************************************** + + FileName [kitSop.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [Procedures involving SOPs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kitSop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates SOP from the cube array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_SopCreate( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory ) +{ + unsigned uCube; + int i; + // start the cover + cResult->nCubes = 0; + cResult->pCubes = Vec_IntFetch( vMemory, Vec_IntSize(vInput) ); + // add the cubes + Vec_IntForEachEntry( vInput, uCube, i ) + Kit_SopPushCube( cResult, uCube ); +} + +/**Function************************************************************* + + Synopsis [Creates SOP from the cube array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_SopCreateInverse( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nLits, Vec_Int_t * vMemory ) +{ + unsigned uCube, uMask = 0; + int i, nCubes = Vec_IntSize(vInput); + // start the cover + cResult->nCubes = 0; + cResult->pCubes = Vec_IntFetch( vMemory, nCubes ); + // add the cubes +// Vec_IntForEachEntry( vInput, uCube, i ) + for ( i = 0; i < nCubes; i++ ) + { + uCube = Vec_IntEntry( vInput, i ); + uMask = ((uCube | (uCube >> 1)) & 0x55555555); + uMask |= (uMask << 1); + Kit_SopPushCube( cResult, uCube ^ uMask ); + } +} + +/**Function************************************************************* + + Synopsis [Duplicates SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_SopDup( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ) +{ + unsigned uCube; + int i; + // start the cover + cResult->nCubes = 0; + cResult->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) ); + // add the cubes + Kit_SopForEachCube( cSop, uCube, i ) + Kit_SopPushCube( cResult, uCube ); +} + +/**Function************************************************************* + + Synopsis [Derives the quotient of division by literal.] + + Description [Reduces the cover to be equal to the result of + division of the given cover by the literal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_SopDivideByLiteralQuo( Kit_Sop_t * cSop, int iLit ) +{ + unsigned uCube; + int i, k = 0; + Kit_SopForEachCube( cSop, uCube, i ) + { + if ( Kit_CubeHasLit(uCube, iLit) ) + Kit_SopWriteCube( cSop, Kit_CubeRemLit(uCube, iLit), k++ ); + } + Kit_SopShrink( cSop, k ); +} + + +/**Function************************************************************* + + Synopsis [Divides cover by one cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_SopDivideByCube( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ) +{ + unsigned uCube, uDiv; + int i; + // get the only cube + assert( Kit_SopCubeNum(cDiv) == 1 ); + uDiv = Kit_SopCube(cDiv, 0); + // allocate covers + vQuo->nCubes = 0; + vQuo->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) ); + vRem->nCubes = 0; + vRem->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) ); + // sort the cubes + Kit_SopForEachCube( cSop, uCube, i ) + { + if ( Kit_CubeContains( uCube, uDiv ) ) + Kit_SopPushCube( vQuo, Kit_CubeSharp(uCube, uDiv) ); + else + Kit_SopPushCube( vRem, uCube ); + } +} + +/**Function************************************************************* + + Synopsis [Divides cover by one cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_SopDivideInternal( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ) +{ + unsigned uCube, uDiv, uCube2, uDiv2, uQuo; + int i, i2, k, k2, nCubesRem; + assert( Kit_SopCubeNum(cSop) >= Kit_SopCubeNum(cDiv) ); + // consider special case + if ( Kit_SopCubeNum(cDiv) == 1 ) + { + Kit_SopDivideByCube( cSop, cDiv, vQuo, vRem, vMemory ); + return; + } + // allocate quotient + vQuo->nCubes = 0; + vQuo->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) / Kit_SopCubeNum(cDiv) ); + // for each cube of the cover + // it either belongs to the quotient or to the remainder + Kit_SopForEachCube( cSop, uCube, i ) + { + // skip taken cubes + if ( Kit_CubeIsMarked(uCube) ) + continue; + // find a matching cube in the divisor + uDiv = ~0; + Kit_SopForEachCube( cDiv, uDiv, k ) + if ( Kit_CubeContains( uCube, uDiv ) ) + break; + // the cube is not found + if ( k == Kit_SopCubeNum(cDiv) ) + continue; + // the quotient cube exists + uQuo = Kit_CubeSharp( uCube, uDiv ); + // find corresponding cubes for other cubes of the divisor + uDiv2 = ~0; + Kit_SopForEachCube( cDiv, uDiv2, k2 ) + { + if ( k2 == k ) + continue; + // find a matching cube + Kit_SopForEachCube( cSop, uCube2, i2 ) + { + // skip taken cubes + if ( Kit_CubeIsMarked(uCube2) ) + continue; + // check if the cube can be used + if ( Kit_CubeContains( uCube2, uDiv2 ) && uQuo == Kit_CubeSharp( uCube2, uDiv2 ) ) + break; + } + // the case when the cube is not found + if ( i2 == Kit_SopCubeNum(cSop) ) + break; + } + // we did not find some cubes - continue looking at other cubes + if ( k2 != Kit_SopCubeNum(cDiv) ) + continue; + // we found all cubes - add the quotient cube + Kit_SopPushCube( vQuo, uQuo ); + + // mark the first cube + Kit_SopWriteCube( cSop, Kit_CubeMark(uCube), i ); + // mark other cubes that have this quotient + Kit_SopForEachCube( cDiv, uDiv2, k2 ) + { + if ( k2 == k ) + continue; + // find a matching cube + Kit_SopForEachCube( cSop, uCube2, i2 ) + { + // skip taken cubes + if ( Kit_CubeIsMarked(uCube2) ) + continue; + // check if the cube can be used + if ( Kit_CubeContains( uCube2, uDiv2 ) && uQuo == Kit_CubeSharp( uCube2, uDiv2 ) ) + break; + } + assert( i2 < Kit_SopCubeNum(cSop) ); + // the cube is found, mark it + // (later we will add all unmarked cubes to the remainder) + Kit_SopWriteCube( cSop, Kit_CubeMark(uCube2), i2 ); + } + } + // determine the number of cubes in the remainder + nCubesRem = Kit_SopCubeNum(cSop) - Kit_SopCubeNum(vQuo) * Kit_SopCubeNum(cDiv); + // allocate remainder + vRem->nCubes = 0; + vRem->pCubes = Vec_IntFetch( vMemory, nCubesRem ); + // finally add the remaining unmarked cubes to the remainder + // and clean the marked cubes in the cover + Kit_SopForEachCube( cSop, uCube, i ) + { + if ( !Kit_CubeIsMarked(uCube) ) + { + Kit_SopPushCube( vRem, uCube ); + continue; + } + Kit_SopWriteCube( cSop, Kit_CubeUnmark(uCube), i ); + } + assert( nCubesRem == Kit_SopCubeNum(vRem) ); +} + +/**Function************************************************************* + + Synopsis [Returns the common cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Kit_SopCommonCube( Kit_Sop_t * cSop ) +{ + unsigned uMask, uCube; + int i; + uMask = ~(unsigned)0; + Kit_SopForEachCube( cSop, uCube, i ) + uMask &= uCube; + return uMask; +} + +/**Function************************************************************* + + Synopsis [Makes the cover cube-free.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_SopMakeCubeFree( Kit_Sop_t * cSop ) +{ + unsigned uMask, uCube; + int i; + uMask = Kit_SopCommonCube( cSop ); + if ( uMask == 0 ) + return; + // remove the common cube + Kit_SopForEachCube( cSop, uCube, i ) + Kit_SopWriteCube( cSop, Kit_CubeSharp(uCube, uMask), i ); +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is cube-free.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_SopIsCubeFree( Kit_Sop_t * cSop ) +{ + return Kit_SopCommonCube( cSop ) == 0; +} + +/**Function************************************************************* + + Synopsis [Creates SOP composes of the common cube of the given SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_SopCommonCubeCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ) +{ + assert( Kit_SopCubeNum(cSop) > 0 ); + cResult->nCubes = 0; + cResult->pCubes = Vec_IntFetch( vMemory, 1 ); + Kit_SopPushCube( cResult, Kit_SopCommonCube(cSop) ); +} + + +/**Function************************************************************* + + Synopsis [Find any literal that occurs more than once.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_SopAnyLiteral( Kit_Sop_t * cSop, int nLits ) +{ + unsigned uCube; + int i, k, nLitsCur; + // go through each literal + for ( i = 0; i < nLits; i++ ) + { + // go through all the cubes + nLitsCur = 0; + Kit_SopForEachCube( cSop, uCube, k ) + if ( Kit_CubeHasLit(uCube, i) ) + nLitsCur++; + if ( nLitsCur > 1 ) + return i; + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Find the least often occurring literal.] + + Description [Find the least often occurring literal among those + that occur more than once.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_SopWorstLiteral( Kit_Sop_t * cSop, int nLits ) +{ + unsigned uCube; + int i, k, iMin, nLitsMin, nLitsCur; + int fUseFirst = 1; + + // go through each literal + iMin = -1; + nLitsMin = 1000000; + for ( i = 0; i < nLits; i++ ) + { + // go through all the cubes + nLitsCur = 0; + Kit_SopForEachCube( cSop, uCube, k ) + if ( Kit_CubeHasLit(uCube, i) ) + nLitsCur++; + // skip the literal that does not occur or occurs once + if ( nLitsCur < 2 ) + continue; + // check if this is the best literal + if ( fUseFirst ) + { + if ( nLitsMin > nLitsCur ) + { + nLitsMin = nLitsCur; + iMin = i; + } + } + else + { + if ( nLitsMin >= nLitsCur ) + { + nLitsMin = nLitsCur; + iMin = i; + } + } + } + if ( nLitsMin < 1000000 ) + return iMin; + return -1; +} + +/**Function************************************************************* + + Synopsis [Find the least often occurring literal.] + + Description [Find the least often occurring literal among those + that occur more than once.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_SopBestLiteral( Kit_Sop_t * cSop, int nLits, unsigned uMask ) +{ + unsigned uCube; + int i, k, iMax, nLitsMax, nLitsCur; + int fUseFirst = 1; + + // go through each literal + iMax = -1; + nLitsMax = -1; + for ( i = 0; i < nLits; i++ ) + { + if ( !Kit_CubeHasLit(uMask, i) ) + continue; + // go through all the cubes + nLitsCur = 0; + Kit_SopForEachCube( cSop, uCube, k ) + if ( Kit_CubeHasLit(uCube, i) ) + nLitsCur++; + // skip the literal that does not occur or occurs once + if ( nLitsCur < 2 ) + continue; + // check if this is the best literal + if ( fUseFirst ) + { + if ( nLitsMax < nLitsCur ) + { + nLitsMax = nLitsCur; + iMax = i; + } + } + else + { + if ( nLitsMax <= nLitsCur ) + { + nLitsMax = nLitsCur; + iMax = i; + } + } + } + if ( nLitsMax >= 0 ) + return iMax; + return -1; +} + +/**Function************************************************************* + + Synopsis [Computes a level-zero kernel.] + + Description [Modifies the cover to contain one level-zero kernel.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_SopDivisorZeroKernel_rec( Kit_Sop_t * cSop, int nLits ) +{ + int iLit; + // find any literal that occurs at least two times + iLit = Kit_SopWorstLiteral( cSop, nLits ); + if ( iLit == -1 ) + return; + // derive the cube-free quotient + Kit_SopDivideByLiteralQuo( cSop, iLit ); // the same cover + Kit_SopMakeCubeFree( cSop ); // the same cover + // call recursively + Kit_SopDivisorZeroKernel_rec( cSop, nLits ); // the same cover +} + +/**Function************************************************************* + + Synopsis [Computes the quick divisor of the cover.] + + Description [Returns 0, if there is no divisor other than trivial.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_SopDivisor( Kit_Sop_t * cResult, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ) +{ + if ( Kit_SopCubeNum(cSop) <= 1 ) + return 0; + if ( Kit_SopAnyLiteral( cSop, nLits ) == -1 ) + return 0; + // duplicate the cover + Kit_SopDup( cResult, cSop, vMemory ); + // perform the kerneling + Kit_SopDivisorZeroKernel_rec( cResult, nLits ); + assert( Kit_SopCubeNum(cResult) > 0 ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Create the one-literal cover with the best literal from cSop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_SopBestLiteralCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, unsigned uCube, int nLits, Vec_Int_t * vMemory ) +{ + int iLitBest; + // get the best literal + iLitBest = Kit_SopBestLiteral( cSop, nLits, uCube ); + // start the cover + cResult->nCubes = 0; + cResult->pCubes = Vec_IntFetch( vMemory, 1 ); + // set the cube + Kit_SopPushCube( cResult, Kit_CubeSetLit(0, iLitBest) ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/kit/kitTruth.c b/abc70930/src/aig/kit/kitTruth.c new file mode 100644 index 00000000..dab60132 --- /dev/null +++ b/abc70930/src/aig/kit/kitTruth.c @@ -0,0 +1,1721 @@ +/**CFile**************************************************************** + + FileName [kitTruth.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [Procedures involving truth tables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kitTruth.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Swaps two adjacent variables in the truth table.] + + Description [Swaps var number Start and var number Start+1 (0-based numbers). + The input truth table is pIn. The output truth table is pOut.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) +{ + static unsigned PMasks[4][3] = { + { 0x99999999, 0x22222222, 0x44444444 }, + { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 }, + { 0xF00FF00F, 0x00F000F0, 0x0F000F00 }, + { 0xFF0000FF, 0x0000FF00, 0x00FF0000 } + }; + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step, Shift; + + assert( iVar < nVars - 1 ); + if ( iVar < 4 ) + { + Shift = (1 << iVar); + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift); + } + else if ( iVar > 4 ) + { + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 4*Step ) + { + for ( i = 0; i < Step; i++ ) + pOut[i] = pIn[i]; + for ( i = 0; i < Step; i++ ) + pOut[Step+i] = pIn[2*Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[2*Step+i] = pIn[Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[3*Step+i] = pIn[3*Step+i]; + pIn += 4*Step; + pOut += 4*Step; + } + } + else // if ( iVar == 4 ) + { + for ( i = 0; i < nWords; i += 2 ) + { + pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); + pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); + } + } +} + +/**Function************************************************************* + + Synopsis [Swaps two adjacent variables in the truth table.] + + Description [Swaps var number Start and var number Start+1 (0-based numbers). + The input truth table is pIn. The output truth table is pOut.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int Start ) +{ + int nWords = (nVars <= 5)? 1 : (1 << (nVars-5)); + int i, k, Step; + + assert( Start < nVars - 1 ); + switch ( Start ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0x99999999) | ((pIn[i] & 0x22222222) << 1) | ((pIn[i] & 0x44444444) >> 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xC3C3C3C3) | ((pIn[i] & 0x0C0C0C0C) << 2) | ((pIn[i] & 0x30303030) >> 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xF00FF00F) | ((pIn[i] & 0x00F000F0) << 4) | ((pIn[i] & 0x0F000F00) >> 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xFF0000FF) | ((pIn[i] & 0x0000FF00) << 8) | ((pIn[i] & 0x00FF0000) >> 8); + return; + case 4: + for ( i = 0; i < nWords; i += 2 ) + { + pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); + pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); + } + return; + default: + Step = (1 << (Start - 5)); + for ( k = 0; k < nWords; k += 4*Step ) + { + for ( i = 0; i < Step; i++ ) + pOut[i] = pIn[i]; + for ( i = 0; i < Step; i++ ) + pOut[Step+i] = pIn[2*Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[2*Step+i] = pIn[Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[3*Step+i] = pIn[3*Step+i]; + pIn += 4*Step; + pOut += 4*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Expands the truth table according to the phase.] + + Description [The input and output truth tables are in pIn/pOut. The current number + of variables is nVars. The total number of variables in nVarsAll. The last argument + (Phase) contains shows where the variables should go.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ) +{ + unsigned * pTemp; + int i, k, Var = nVars - 1, Counter = 0; + for ( i = nVarsAll - 1; i >= 0; i-- ) + if ( Phase & (1 << i) ) + { + for ( k = Var; k < i; k++ ) + { + Kit_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + Counter++; + } + Var--; + } + assert( Var == -1 ); + // swap if it was moved an even number of times + if ( fReturnIn ^ !(Counter & 1) ) + Kit_TruthCopy( pOut, pIn, nVarsAll ); +} + +/**Function************************************************************* + + Synopsis [Shrinks the truth table according to the phase.] + + Description [The input and output truth tables are in pIn/pOut. The current number + of variables is nVars. The total number of variables in nVarsAll. The last argument + (Phase) contains shows what variables should remain.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ) +{ + unsigned * pTemp; + int i, k, Var = 0, Counter = 0; + for ( i = 0; i < nVarsAll; i++ ) + if ( Phase & (1 << i) ) + { + for ( k = i-1; k >= Var; k-- ) + { + Kit_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + Counter++; + } + Var++; + } + assert( Var == nVars ); + // swap if it was moved an even number of times + if ( fReturnIn ^ !(Counter & 1) ) + Kit_TruthCopy( pOut, pIn, nVarsAll ); +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if TT depends on the given variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) ) + return 1; + return 0; + case 1: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) ) + return 1; + return 0; + case 2: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) ) + return 1; + return 0; + case 3: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) ) + return 1; + return 0; + case 4: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) ) + return 1; + return 0; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + if ( pTruth[i] != pTruth[Step+i] ) + return 1; + pTruth += 2*Step; + } + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Returns the number of support vars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthSupportSize( unsigned * pTruth, int nVars ) +{ + int i, Counter = 0; + for ( i = 0; i < nVars; i++ ) + Counter += Kit_TruthVarInSupport( pTruth, nVars, i ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns support of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Kit_TruthSupport( unsigned * pTruth, int nVars ) +{ + int i, Support = 0; + for ( i = 0; i < nVars; i++ ) + if ( Kit_TruthVarInSupport( pTruth, nVars, i ) ) + Support |= (1 << i); + return Support; +} + + + +/**Function************************************************************* + + Synopsis [Computes negative cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x55555555) | ((pTruth[i] & 0x55555555) << 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x33333333) | ((pTruth[i] & 0x33333333) << 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x0F0F0F0F) | ((pTruth[i] & 0x0F0F0F0F) << 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x00FF00FF) | ((pTruth[i] & 0x00FF00FF) << 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x0000FFFF) | ((pTruth[i] & 0x0000FFFF) << 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + pTruth[Step+i] = pTruth[i]; + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Computes positive cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xAAAAAAAA) | ((pTruth[i] & 0xAAAAAAAA) >> 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xCCCCCCCC) | ((pTruth[i] & 0xCCCCCCCC) >> 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xF0F0F0F0) | ((pTruth[i] & 0xF0F0F0F0) >> 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xFF00FF00) | ((pTruth[i] & 0xFF00FF00) >> 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xFFFF0000) | ((pTruth[i] & 0xFFFF0000) >> 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + pTruth[i] = pTruth[Step+i]; + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Computes positive cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthCofactor0New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0x55555555) | ((pIn[i] & 0x55555555) << 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0x33333333) | ((pIn[i] & 0x33333333) << 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0x0F0F0F0F) | ((pIn[i] & 0x0F0F0F0F) << 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0x00FF00FF) | ((pIn[i] & 0x00FF00FF) << 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i] & 0x0000FFFF) << 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + pOut[i] = pOut[Step+i] = pIn[i]; + pIn += 2*Step; + pOut += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Computes positive cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthCofactor1New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xAAAAAAAA) | ((pIn[i] & 0xAAAAAAAA) >> 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xCCCCCCCC) | ((pIn[i] & 0xCCCCCCCC) >> 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xF0F0F0F0) | ((pIn[i] & 0xF0F0F0F0) >> 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xFF00FF00) | ((pIn[i] & 0xFF00FF00) >> 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + pOut[i] = pOut[Step+i] = pIn[Step+i]; + pIn += 2*Step; + pOut += 2*Step; + } + return; + } +} + + +/**Function************************************************************* + + Synopsis [Existentially quantifies the variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthExist( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] |= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] |= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] |= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] |= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] |= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + pTruth[i] |= pTruth[Step+i]; + pTruth[Step+i] = pTruth[i]; + } + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Existentially quantifies the variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthExistNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] | ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] | ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] | ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] | ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] | ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + pRes[i] = pTruth[i] | pTruth[Step+i]; + pRes[Step+i] = pRes[i]; + } + pRes += 2*Step; + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Existantially quantifies the set of variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthExistSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ) +{ + int v; + Kit_TruthCopy( pRes, pTruth, nVars ); + for ( v = 0; v < nVars; v++ ) + if ( uMask & (1 << v) ) + Kit_TruthExist( pRes, nVars, v ); +} + +/**Function************************************************************* + + Synopsis [Unversally quantifies the variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthForall( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] &= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] &= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] &= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] &= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] &= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + pTruth[i] &= pTruth[Step+i]; + pTruth[Step+i] = pTruth[i]; + } + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Universally quantifies the variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthForallNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] & (((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1)); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] & (((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2)); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] & (((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4)); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] & (((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8)); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] & (((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16)); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + pRes[i] = pTruth[i] & pTruth[Step+i]; + pRes[Step+i] = pRes[i]; + } + pRes += 2*Step; + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Universally quantifies the variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthUniqueNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1)); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2)); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4)); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8)); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16)); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + pRes[i] = pTruth[i] ^ pTruth[Step+i]; + pRes[Step+i] = pRes[i]; + } + pRes += 2*Step; + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Universally quantifies the set of variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthForallSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ) +{ + int v; + Kit_TruthCopy( pRes, pTruth, nVars ); + for ( v = 0; v < nVars; v++ ) + if ( uMask & (1 << v) ) + Kit_TruthForall( pRes, nVars, v ); +} + + +/**Function************************************************************* + + Synopsis [Multiplexes two functions with the given variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthMuxVar( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + pOut[i] = pCof0[i]; + pOut[Step+i] = pCof1[Step+i]; + } + pOut += 2*Step; + pCof0 += 2*Step; + pCof1 += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Multiplexes two functions with the given variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthMuxVarPhase( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar, int fCompl0 ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + + if ( fCompl0 == 0 ) + { + Kit_TruthMuxVar( pOut, pCof0, pCof1, nVars, iVar ); + return; + } + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (~pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (~pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (~pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (~pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (~pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + pOut[i] = ~pCof0[i]; + pOut[Step+i] = pCof1[Step+i]; + } + pOut += 2*Step; + pCof0 += 2*Step; + pCof1 += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Checks symmetry of two variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) +{ + static unsigned uTemp0[16], uTemp1[16]; + assert( nVars <= 9 ); + // compute Cof01 + Kit_TruthCopy( uTemp0, pTruth, nVars ); + Kit_TruthCofactor0( uTemp0, nVars, iVar0 ); + Kit_TruthCofactor1( uTemp0, nVars, iVar1 ); + // compute Cof10 + Kit_TruthCopy( uTemp1, pTruth, nVars ); + Kit_TruthCofactor1( uTemp1, nVars, iVar0 ); + Kit_TruthCofactor0( uTemp1, nVars, iVar1 ); + // compare + return Kit_TruthIsEqual( uTemp0, uTemp1, nVars ); +} + +/**Function************************************************************* + + Synopsis [Checks antisymmetry of two variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) +{ + static unsigned uTemp0[16], uTemp1[16]; + assert( nVars <= 9 ); + // compute Cof00 + Kit_TruthCopy( uTemp0, pTruth, nVars ); + Kit_TruthCofactor0( uTemp0, nVars, iVar0 ); + Kit_TruthCofactor0( uTemp0, nVars, iVar1 ); + // compute Cof11 + Kit_TruthCopy( uTemp1, pTruth, nVars ); + Kit_TruthCofactor1( uTemp1, nVars, iVar0 ); + Kit_TruthCofactor1( uTemp1, nVars, iVar1 ); + // compare + return Kit_TruthIsEqual( uTemp0, uTemp1, nVars ); +} + +/**Function************************************************************* + + Synopsis [Changes phase of the function w.r.t. one variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Step; + unsigned Temp; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x55555555) << 1) | ((pTruth[i] & 0xAAAAAAAA) >> 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x33333333) << 2) | ((pTruth[i] & 0xCCCCCCCC) >> 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x0F0F0F0F) << 4) | ((pTruth[i] & 0xF0F0F0F0) >> 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x00FF00FF) << 8) | ((pTruth[i] & 0xFF00FF00) >> 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x0000FFFF) << 16) | ((pTruth[i] & 0xFFFF0000) >> 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + Temp = pTruth[i]; + pTruth[i] = pTruth[Step+i]; + pTruth[Step+i] = Temp; + } + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Computes minimum overlap in supports of cofactors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ) +{ + static unsigned uCofactor[16]; + int i, ValueCur, ValueMin, VarMin; + unsigned uSupp0, uSupp1; + int nVars0, nVars1; + assert( nVars <= 9 ); + ValueMin = 32; + VarMin = -1; + for ( i = 0; i < nVars; i++ ) + { + // get negative cofactor + Kit_TruthCopy( uCofactor, pTruth, nVars ); + Kit_TruthCofactor0( uCofactor, nVars, i ); + uSupp0 = Kit_TruthSupport( uCofactor, nVars ); + nVars0 = Kit_WordCountOnes( uSupp0 ); +//Kit_PrintBinary( stdout, &uSupp0, 8 ); printf( "\n" ); + // get positive cofactor + Kit_TruthCopy( uCofactor, pTruth, nVars ); + Kit_TruthCofactor1( uCofactor, nVars, i ); + uSupp1 = Kit_TruthSupport( uCofactor, nVars ); + nVars1 = Kit_WordCountOnes( uSupp1 ); +//Kit_PrintBinary( stdout, &uSupp1, 8 ); printf( "\n" ); + // get the number of common vars + ValueCur = Kit_WordCountOnes( uSupp0 & uSupp1 ); + if ( ValueMin > ValueCur && nVars0 <= 5 && nVars1 <= 5 ) + { + ValueMin = ValueCur; + VarMin = i; + } + if ( ValueMin == 0 ) + break; + } + if ( pVarMin ) + *pVarMin = VarMin; + return ValueMin; +} + + +/**Function************************************************************* + + Synopsis [Find the best cofactoring variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthBestCofVar( unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 ) +{ + int i, iBestVar, nSuppSizeCur0, nSuppSizeCur1, nSuppSizeCur, nSuppSizeMin; + if ( Kit_TruthIsConst0(pTruth, nVars) || Kit_TruthIsConst1(pTruth, nVars) ) + return -1; + // iterate through variables + iBestVar = -1; + nSuppSizeMin = KIT_INFINITY; + for ( i = 0; i < nVars; i++ ) + { + // cofactor the functiona and get support sizes + Kit_TruthCofactor0New( pCof0, pTruth, nVars, i ); + Kit_TruthCofactor1New( pCof1, pTruth, nVars, i ); + nSuppSizeCur0 = Kit_TruthSupportSize( pCof0, nVars ); + nSuppSizeCur1 = Kit_TruthSupportSize( pCof1, nVars ); + nSuppSizeCur = nSuppSizeCur0 + nSuppSizeCur1; + // compare this variable with other variables + if ( nSuppSizeMin > nSuppSizeCur ) + { + nSuppSizeMin = nSuppSizeCur; + iBestVar = i; + } + } + assert( iBestVar != -1 ); + // cofactor w.r.t. this variable + Kit_TruthCofactor0New( pCof0, pTruth, nVars, iBestVar ); + Kit_TruthCofactor1New( pCof1, pTruth, nVars, iBestVar ); + return iBestVar; +} + + +/**Function************************************************************* + + Synopsis [Counts the number of 1's in each cofactor.] + + Description [The resulting numbers are stored in the array of shorts, + whose length is 2*nVars. The number of 1's is counted in a different + space than the original function. For example, if the function depends + on k variables, the cofactors are assumed to depend on k-1 variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ) +{ + int nWords = Kit_TruthWordNum( nVars ); + int i, k, Counter; + memset( pStore, 0, sizeof(short) * 2 * nVars ); + if ( nVars <= 5 ) + { + if ( nVars > 0 ) + { + pStore[2*0+0] = Kit_WordCountOnes( pTruth[0] & 0x55555555 ); + pStore[2*0+1] = Kit_WordCountOnes( pTruth[0] & 0xAAAAAAAA ); + } + if ( nVars > 1 ) + { + pStore[2*1+0] = Kit_WordCountOnes( pTruth[0] & 0x33333333 ); + pStore[2*1+1] = Kit_WordCountOnes( pTruth[0] & 0xCCCCCCCC ); + } + if ( nVars > 2 ) + { + pStore[2*2+0] = Kit_WordCountOnes( pTruth[0] & 0x0F0F0F0F ); + pStore[2*2+1] = Kit_WordCountOnes( pTruth[0] & 0xF0F0F0F0 ); + } + if ( nVars > 3 ) + { + pStore[2*3+0] = Kit_WordCountOnes( pTruth[0] & 0x00FF00FF ); + pStore[2*3+1] = Kit_WordCountOnes( pTruth[0] & 0xFF00FF00 ); + } + if ( nVars > 4 ) + { + pStore[2*4+0] = Kit_WordCountOnes( pTruth[0] & 0x0000FFFF ); + pStore[2*4+1] = Kit_WordCountOnes( pTruth[0] & 0xFFFF0000 ); + } + return; + } + // nVars >= 6 + // count 1's for all other variables + for ( k = 0; k < nWords; k++ ) + { + Counter = Kit_WordCountOnes( pTruth[k] ); + for ( i = 5; i < nVars; i++ ) + if ( k & (1 << (i-5)) ) + pStore[2*i+1] += Counter; + else + pStore[2*i+0] += Counter; + } + // count 1's for the first five variables + for ( k = 0; k < nWords/2; k++ ) + { + pStore[2*0+0] += Kit_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) ); + pStore[2*0+1] += Kit_WordCountOnes( (pTruth[0] & 0xAAAAAAAA) | ((pTruth[1] & 0xAAAAAAAA) >> 1) ); + pStore[2*1+0] += Kit_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) ); + pStore[2*1+1] += Kit_WordCountOnes( (pTruth[0] & 0xCCCCCCCC) | ((pTruth[1] & 0xCCCCCCCC) >> 2) ); + pStore[2*2+0] += Kit_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) ); + pStore[2*2+1] += Kit_WordCountOnes( (pTruth[0] & 0xF0F0F0F0) | ((pTruth[1] & 0xF0F0F0F0) >> 4) ); + pStore[2*3+0] += Kit_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) ); + pStore[2*3+1] += Kit_WordCountOnes( (pTruth[0] & 0xFF00FF00) | ((pTruth[1] & 0xFF00FF00) >> 8) ); + pStore[2*4+0] += Kit_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) ); + pStore[2*4+1] += Kit_WordCountOnes( (pTruth[0] & 0xFFFF0000) | ((pTruth[1] & 0xFFFF0000) >> 16) ); + pTruth += 2; + } +} + +/**Function************************************************************* + + Synopsis [Counts the number of 1's in each cofactor.] + + Description [Verifies the above procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthCountOnesInCofsSlow( unsigned * pTruth, int nVars, short * pStore, unsigned * pAux ) +{ + int i; + for ( i = 0; i < nVars; i++ ) + { + Kit_TruthCofactor0New( pAux, pTruth, nVars, i ); + pStore[2*i+0] = Kit_TruthCountOnes( pAux, nVars ) / 2; + Kit_TruthCofactor1New( pAux, pTruth, nVars, i ); + pStore[2*i+1] = Kit_TruthCountOnes( pAux, nVars ) / 2; + } +} + +/**Function************************************************************* + + Synopsis [Canonicize the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Kit_TruthHash( unsigned * pIn, int nWords ) +{ + // The 1,024 smallest prime numbers used to compute the hash value + // http://www.math.utah.edu/~alfeld/math/primelist.html + static int HashPrimes[1024] = { 2, 3, 5, + 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, + 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, + 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, + 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, + 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, + 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, + 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, + 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, + 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, + 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, + 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, + 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, + 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, + 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, + 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, + 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, + 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, + 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, + 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, + 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, + 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, + 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, + 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, + 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, + 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, + 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, + 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, + 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, + 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, + 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, + 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, + 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, + 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, + 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, + 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, + 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, + 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, + 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, + 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, + 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, + 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, + 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, + 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, + 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, + 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, + 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, + 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, + 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, + 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, + 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, + 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, + 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, + 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, + 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, + 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, + 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, + 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, + 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, + 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, + 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, + 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, + 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, + 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, + 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, + 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, + 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, + 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, + 8147, 8161 }; + int i; + unsigned uHashKey; + assert( nWords <= 1024 ); + uHashKey = 0; + for ( i = 0; i < nWords; i++ ) + uHashKey ^= HashPrimes[i] * pIn[i]; + return uHashKey; +} + + +/**Function************************************************************* + + Synopsis [Canonicize the truth table.] + + Description [Returns the phase. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ) +{ +// short pStore2[32]; + unsigned * pIn = pInOut, * pOut = pAux, * pTemp; +// int nWords = Kit_TruthWordNum( nVars ); + int i, Temp, fChange, Counter;//, nOnes;//, k, j, w, Limit; + unsigned uCanonPhase; + + // canonicize output + uCanonPhase = 0; +/* + nOnes = Kit_TruthCountOnes(pIn, nVars); + if ( (nOnes > nWords * 16) )//|| ((nOnes == nWords * 16) && (pIn[0] & 1)) ) + { + uCanonPhase |= (1 << nVars); + Kit_TruthNot( pIn, pIn, nVars ); + } +*/ + // collect the minterm counts + Kit_TruthCountOnesInCofs( pIn, nVars, pStore ); +// Kit_TruthCountOnesInCofsSlow( pIn, nVars, pStore2, pAux ); +// for ( i = 0; i < 2*nVars; i++ ) +// { +// assert( pStore[i] == pStore2[i] ); +// } + + // canonicize phase + for ( i = 0; i < nVars; i++ ) + { + if ( pStore[2*i+0] >= pStore[2*i+1] ) + continue; + uCanonPhase |= (1 << i); + Temp = pStore[2*i+0]; + pStore[2*i+0] = pStore[2*i+1]; + pStore[2*i+1] = Temp; + Kit_TruthChangePhase( pIn, nVars, i ); + } + +// Kit_PrintHexadecimal( stdout, pIn, nVars ); +// printf( "\n" ); + + // permute + Counter = 0; + do { + fChange = 0; + for ( i = 0; i < nVars-1; i++ ) + { + if ( pStore[2*i] >= pStore[2*(i+1)] ) + continue; + Counter++; + fChange = 1; + + Temp = pCanonPerm[i]; + pCanonPerm[i] = pCanonPerm[i+1]; + pCanonPerm[i+1] = Temp; + + Temp = pStore[2*i]; + pStore[2*i] = pStore[2*(i+1)]; + pStore[2*(i+1)] = Temp; + + Temp = pStore[2*i+1]; + pStore[2*i+1] = pStore[2*(i+1)+1]; + pStore[2*(i+1)+1] = Temp; + + // if the polarity of variables is different, swap them + if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) ) + { + uCanonPhase ^= (1 << i); + uCanonPhase ^= (1 << (i+1)); + } + + Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + } while ( fChange ); + +/* + Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " ); + for ( i = 0; i < nVars; i++ ) + printf( "%d=%d/%d ", pCanonPerm[i], pStore[2*i], pStore[2*i+1] ); + printf( " C = %d\n", Counter ); + Extra_PrintHexadecimal( stdout, pIn, nVars ); + printf( "\n" ); +*/ + +/* + // process symmetric variable groups + uSymms = 0; + for ( i = 0; i < nVars-1; i++ ) + { + if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric + continue; + if ( pStore[2*i] != pStore[2*i+1] ) + continue; + if ( Kit_TruthVarsSymm( pIn, nVars, i, i+1 ) ) + continue; + if ( Kit_TruthVarsAntiSymm( pIn, nVars, i, i+1 ) ) + Kit_TruthChangePhase( pIn, nVars, i+1 ); + } +*/ + +/* + // process symmetric variable groups + uSymms = 0; + for ( i = 0; i < nVars-1; i++ ) + { + if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric + continue; + // i and i+1 can be symmetric + // find the end of this group + for ( k = i+1; k < nVars; k++ ) + if ( pStore[2*i] != pStore[2*k] ) + break; + Limit = k; + assert( i < Limit-1 ); + // go through the variables in this group + for ( j = i + 1; j < Limit; j++ ) + { + // check symmetry + if ( Kit_TruthVarsSymm( pIn, nVars, i, j ) ) + { + uSymms |= (1 << j); + continue; + } + // they are phase-unknown + if ( pStore[2*i] == pStore[2*i+1] ) + { + if ( Kit_TruthVarsAntiSymm( pIn, nVars, i, j ) ) + { + Kit_TruthChangePhase( pIn, nVars, j ); + uCanonPhase ^= (1 << j); + uSymms |= (1 << j); + continue; + } + } + + // they are not symmetric - move j as far as it goes in the group + for ( k = j; k < Limit-1; k++ ) + { + Counter++; + + Temp = pCanonPerm[k]; + pCanonPerm[k] = pCanonPerm[k+1]; + pCanonPerm[k+1] = Temp; + + assert( pStore[2*k] == pStore[2*(k+1)] ); + Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, k ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + Limit--; + j--; + } + i = Limit - 1; + } +*/ + + // swap if it was moved an even number of times + if ( Counter & 1 ) + Kit_TruthCopy( pOut, pIn, nVars ); + return uCanonPhase; +} + + +/**Function************************************************************* + + Synopsis [Fast counting minterms in the cofactors of a function.] + + Description [Returns the total number of minterms in the function. + The resulting array (pRes) contains the number of minterms in 0-cofactor + w.r.t. each variables. The additional array (pBytes) is used for internal + storage. It should have the size equal to the number of truth table bytes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kit_TruthCountMinterms( unsigned * pTruth, int nVars, int * pRes, int * pBytes ) +{ + // the number of 1s if every byte as well as in the 0-cofactors w.r.t. three variables + static unsigned Table[256] = { + 0x00000000, 0x01010101, 0x01010001, 0x02020102, 0x01000101, 0x02010202, 0x02010102, 0x03020203, + 0x01000001, 0x02010102, 0x02010002, 0x03020103, 0x02000102, 0x03010203, 0x03010103, 0x04020204, + 0x00010101, 0x01020202, 0x01020102, 0x02030203, 0x01010202, 0x02020303, 0x02020203, 0x03030304, + 0x01010102, 0x02020203, 0x02020103, 0x03030204, 0x02010203, 0x03020304, 0x03020204, 0x04030305, + 0x00010001, 0x01020102, 0x01020002, 0x02030103, 0x01010102, 0x02020203, 0x02020103, 0x03030204, + 0x01010002, 0x02020103, 0x02020003, 0x03030104, 0x02010103, 0x03020204, 0x03020104, 0x04030205, + 0x00020102, 0x01030203, 0x01030103, 0x02040204, 0x01020203, 0x02030304, 0x02030204, 0x03040305, + 0x01020103, 0x02030204, 0x02030104, 0x03040205, 0x02020204, 0x03030305, 0x03030205, 0x04040306, + 0x00000101, 0x01010202, 0x01010102, 0x02020203, 0x01000202, 0x02010303, 0x02010203, 0x03020304, + 0x01000102, 0x02010203, 0x02010103, 0x03020204, 0x02000203, 0x03010304, 0x03010204, 0x04020305, + 0x00010202, 0x01020303, 0x01020203, 0x02030304, 0x01010303, 0x02020404, 0x02020304, 0x03030405, + 0x01010203, 0x02020304, 0x02020204, 0x03030305, 0x02010304, 0x03020405, 0x03020305, 0x04030406, + 0x00010102, 0x01020203, 0x01020103, 0x02030204, 0x01010203, 0x02020304, 0x02020204, 0x03030305, + 0x01010103, 0x02020204, 0x02020104, 0x03030205, 0x02010204, 0x03020305, 0x03020205, 0x04030306, + 0x00020203, 0x01030304, 0x01030204, 0x02040305, 0x01020304, 0x02030405, 0x02030305, 0x03040406, + 0x01020204, 0x02030305, 0x02030205, 0x03040306, 0x02020305, 0x03030406, 0x03030306, 0x04040407, + 0x00000001, 0x01010102, 0x01010002, 0x02020103, 0x01000102, 0x02010203, 0x02010103, 0x03020204, + 0x01000002, 0x02010103, 0x02010003, 0x03020104, 0x02000103, 0x03010204, 0x03010104, 0x04020205, + 0x00010102, 0x01020203, 0x01020103, 0x02030204, 0x01010203, 0x02020304, 0x02020204, 0x03030305, + 0x01010103, 0x02020204, 0x02020104, 0x03030205, 0x02010204, 0x03020305, 0x03020205, 0x04030306, + 0x00010002, 0x01020103, 0x01020003, 0x02030104, 0x01010103, 0x02020204, 0x02020104, 0x03030205, + 0x01010003, 0x02020104, 0x02020004, 0x03030105, 0x02010104, 0x03020205, 0x03020105, 0x04030206, + 0x00020103, 0x01030204, 0x01030104, 0x02040205, 0x01020204, 0x02030305, 0x02030205, 0x03040306, + 0x01020104, 0x02030205, 0x02030105, 0x03040206, 0x02020205, 0x03030306, 0x03030206, 0x04040307, + 0x00000102, 0x01010203, 0x01010103, 0x02020204, 0x01000203, 0x02010304, 0x02010204, 0x03020305, + 0x01000103, 0x02010204, 0x02010104, 0x03020205, 0x02000204, 0x03010305, 0x03010205, 0x04020306, + 0x00010203, 0x01020304, 0x01020204, 0x02030305, 0x01010304, 0x02020405, 0x02020305, 0x03030406, + 0x01010204, 0x02020305, 0x02020205, 0x03030306, 0x02010305, 0x03020406, 0x03020306, 0x04030407, + 0x00010103, 0x01020204, 0x01020104, 0x02030205, 0x01010204, 0x02020305, 0x02020205, 0x03030306, + 0x01010104, 0x02020205, 0x02020105, 0x03030206, 0x02010205, 0x03020306, 0x03020206, 0x04030307, + 0x00020204, 0x01030305, 0x01030205, 0x02040306, 0x01020305, 0x02030406, 0x02030306, 0x03040407, + 0x01020205, 0x02030306, 0x02030206, 0x03040307, 0x02020306, 0x03030407, 0x03030307, 0x04040408 + }; + unsigned uSum; + unsigned char * pTruthC, * pLimit; + int i, iVar, Step, nWords, nBytes, nTotal; + + assert( nVars <= 20 ); + + // clear storage + memset( pRes, 0, sizeof(int) * nVars ); + + // count the number of one's in 0-cofactors of the first three variables + nTotal = uSum = 0; + nWords = Kit_TruthWordNum( nVars ); + nBytes = nWords * 4; + pTruthC = (unsigned char *)pTruth; + pLimit = pTruthC + nBytes; + for ( ; pTruthC < pLimit; pTruthC++ ) + { + uSum += Table[*pTruthC]; + *pBytes++ = (Table[*pTruthC] & 0xff); + if ( (uSum & 0xff) > 246 ) + { + nTotal += (uSum & 0xff); + pRes[0] += ((uSum >> 8) & 0xff); + pRes[2] += ((uSum >> 16) & 0xff); + pRes[3] += ((uSum >> 24) & 0xff); + uSum = 0; + } + } + if ( uSum ) + { + nTotal += (uSum & 0xff); + pRes[0] += ((uSum >> 8) & 0xff); + pRes[1] += ((uSum >> 16) & 0xff); + pRes[2] += ((uSum >> 24) & 0xff); + } + + // count all other variables + for ( iVar = 3, Step = 1; Step < nBytes; Step *= 2, iVar++ ) + for ( i = 0; i < nBytes; i += Step + Step ) + { + pRes[iVar] += pBytes[i]; + pBytes[i] += pBytes[i+Step]; + } + assert( pBytes[0] == nTotal ); + assert( iVar == nVars ); + return nTotal; +} + +/**Function************************************************************* + + Synopsis [Prints the hex unsigned into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ) +{ + int nDigits, Digit, k; + // write the number into the file + nDigits = (1 << nVars) / 4; + for ( k = nDigits - 1; k >= 0; k-- ) + { + Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15); + if ( Digit < 10 ) + fprintf( pFile, "%d", Digit ); + else + fprintf( pFile, "%c", 'a' + Digit-10 ); + } +// fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Fast counting minterms for the functions.] + + Description [Returns 0 if the function is a constant.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kit_TruthCountMintermsPrecomp() +{ + int bit_count[256] = { + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 + }; + unsigned i, uWord; + for ( i = 0; i < 256; i++ ) + { + if ( i % 8 == 0 ) + printf( "\n" ); + uWord = bit_count[i]; + uWord |= (bit_count[i & 0x55] << 8); + uWord |= (bit_count[i & 0x33] << 16); + uWord |= (bit_count[i & 0x0f] << 24); + printf( "0x" ); + Kit_PrintHexadecimal( stdout, &uWord, 5 ); + printf( ", " ); + } +} + +/**Function************************************************************* + + Synopsis [Dumps truth table into a file.] + + Description [Generates script file for reading into ABC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Kit_TruthDumpToFile( unsigned * pTruth, int nVars, int nFile ) +{ + static char pFileName[100]; + FILE * pFile; + sprintf( pFileName, "tt\\s%04d", nFile ); + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "rt " ); + Kit_PrintHexadecimal( pFile, pTruth, nVars ); + fprintf( pFile, "; bdd; sop; ps\n" ); + fclose( pFile ); + return pFileName; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/kit/kit_.c b/abc70930/src/aig/kit/kit_.c new file mode 100644 index 00000000..5c68ee3c --- /dev/null +++ b/abc70930/src/aig/kit/kit_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [kit_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Computation kit.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Dec 6, 2006.] + + Revision [$Id: kit_.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/kit/module.make b/abc70930/src/aig/kit/module.make new file mode 100644 index 00000000..ea62381b --- /dev/null +++ b/abc70930/src/aig/kit/module.make @@ -0,0 +1,10 @@ +SRC += src/aig/kit/kitAig.c \ + src/aig/kit/kitBdd.c \ + src/aig/kit/kitCloud.c src/aig/kit/cloud.c \ + src/aig/kit/kitDsd.c \ + src/aig/kit/kitFactor.c \ + src/aig/kit/kitGraph.c \ + src/aig/kit/kitHop.c \ + src/aig/kit/kitIsop.c \ + src/aig/kit/kitSop.c \ + src/aig/kit/kitTruth.c diff --git a/abc70930/src/aig/mem/mem.c b/abc70930/src/aig/mem/mem.c new file mode 100644 index 00000000..f5bfbfd8 --- /dev/null +++ b/abc70930/src/aig/mem/mem.c @@ -0,0 +1,604 @@ +/**CFile**************************************************************** + + FileName [esopMem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Cover manipulation package.] + + Synopsis [Memory managers.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: esopMem.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include "mem.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Mem_Fixed_t_ +{ + // information about individual entries + int nEntrySize; // the size of one entry + int nEntriesAlloc; // the total number of entries allocated + int nEntriesUsed; // the number of entries in use + int nEntriesMax; // the max number of entries in use + char * pEntriesFree; // the linked list of free entries + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Mem_Flex_t_ +{ + // information about individual entries + int nEntriesUsed; // the number of entries allocated + char * pCurrent; // the current pointer to free memory + char * pEnd; // the first entry outside the free memory + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Mem_Step_t_ +{ + int nMems; // the number of fixed memory managers employed + Mem_Fixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc + int nMapSize; // the size of the memory array + Mem_Fixed_t ** pMap; // maps the number of bytes into its memory manager +}; + +#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#define REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates memory pieces of fixed size.] + + Description [The size of the chunk is computed as the minimum of + 1024 entries and 64K. Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mem_Fixed_t * Mem_FixedStart( int nEntrySize ) +{ + Mem_Fixed_t * p; + + p = ALLOC( Mem_Fixed_t, 1 ); + memset( p, 0, sizeof(Mem_Fixed_t) ); + + p->nEntrySize = nEntrySize; + p->nEntriesAlloc = 0; + p->nEntriesUsed = 0; + p->pEntriesFree = NULL; + + if ( nEntrySize * (1 << 10) < (1<<16) ) + p->nChunkSize = (1 << 10); + else + p->nChunkSize = (1<<16) / nEntrySize; + if ( p->nChunkSize < 8 ) + p->nChunkSize = 8; + + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", + p->nEntrySize, p->nChunkSize, p->nChunks ); + printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", + p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Mem_FixedEntryFetch( Mem_Fixed_t * p ) +{ + char * pTemp; + int i; + + // check if there are still free entries + if ( p->nEntriesUsed == p->nEntriesAlloc ) + { // need to allocate more entries + assert( p->pEntriesFree == NULL ); + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); + p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; + // transform these entries into a linked list + pTemp = p->pEntriesFree; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pEntriesFree; + // add to the number of entries allocated + p->nEntriesAlloc += p->nChunkSize; + } + // incrememt the counter of used entries + p->nEntriesUsed++; + if ( p->nEntriesMax < p->nEntriesUsed ) + p->nEntriesMax = p->nEntriesUsed; + // return the first entry in the free entry list + pTemp = p->pEntriesFree; + p->pEntriesFree = *((char **)pTemp); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry ) +{ + // decrement the counter of used entries + p->nEntriesUsed--; + // add the entry to the linked list of free entries + *((char **)pEntry) = p->pEntriesFree; + p->pEntriesFree = pEntry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_FixedRestart( Mem_Fixed_t * p ) +{ + int i; + char * pTemp; + + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + p->nChunks = 1; + // transform these entries into a linked list + pTemp = p->pChunks[0]; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // set the free entry list + p->pEntriesFree = p->pChunks[0]; + // set the correct statistics + p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; + p->nMemoryUsed = 0; + p->nEntriesAlloc = p->nChunkSize; + p->nEntriesUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mem_FixedReadMemUsage( Mem_Fixed_t * p ) +{ + return p->nMemoryAlloc; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p ) +{ + return p->nEntriesMax; +} + + + +/**Function************************************************************* + + Synopsis [Allocates entries of flexible size.] + + Description [Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mem_Flex_t * Mem_FlexStart() +{ + Mem_Flex_t * p; + + p = ALLOC( Mem_Flex_t, 1 ); + memset( p, 0, sizeof(Mem_Flex_t) ); + + p->nEntriesUsed = 0; + p->pCurrent = NULL; + p->pEnd = NULL; + + p->nChunkSize = (1 << 14); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_FlexStop( Mem_Flex_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", + p->nChunkSize, p->nChunks ); + printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", + p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes ) +{ + char * pTemp; + // check if there are still free entries + if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) + { // need to allocate more entries + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + if ( nBytes > p->nChunkSize ) + { + // resize the chunk size if more memory is requested than it can give + // (ideally, this should never happen) + p->nChunkSize = 2 * nBytes; + } + p->pCurrent = ALLOC( char, p->nChunkSize ); + p->pEnd = p->pCurrent + p->nChunkSize; + p->nMemoryAlloc += p->nChunkSize; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pCurrent; + } + assert( p->pCurrent + nBytes <= p->pEnd ); + // increment the counter of used entries + p->nEntriesUsed++; + // keep track of the memory used + p->nMemoryUsed += nBytes; + // return the next entry + pTemp = p->pCurrent; + p->pCurrent += nBytes; + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_FlexRestart( Mem_Flex_t * p ) +{ + int i; + if ( p->nChunks == 0 ) + return; + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + p->nChunks = 1; + p->nMemoryAlloc = p->nChunkSize; + // transform these entries into a linked list + p->pCurrent = p->pChunks[0]; + p->pEnd = p->pCurrent + p->nChunkSize; + p->nEntriesUsed = 0; + p->nMemoryUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mem_FlexReadMemUsage( Mem_Flex_t * p ) +{ + return p->nMemoryUsed; +} + + + + + +/**Function************************************************************* + + Synopsis [Starts the hierarchical memory manager.] + + Description [This manager can allocate entries of any size. + Iternally they are mapped into the entries with the number of bytes + equal to the power of 2. The smallest entry size is 8 bytes. The + next one is 16 bytes etc. So, if the user requests 6 bytes, he gets + 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. + The input parameters "nSteps" says how many fixed memory managers + are employed internally. Calling this procedure with nSteps equal + to 10 results in 10 hierarchically arranged internal memory managers, + which can allocate up to 4096 (1Kb) entries. Requests for larger + entries are handed over to malloc() and then free()ed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mem_Step_t * Mem_StepStart( int nSteps ) +{ + Mem_Step_t * p; + int i, k; + p = ALLOC( Mem_Step_t, 1 ); + memset( p, 0, sizeof(Mem_Step_t) ); + p->nMems = nSteps; + // start the fixed memory managers + p->pMems = ALLOC( Mem_Fixed_t *, p->nMems ); + for ( i = 0; i < p->nMems; i++ ) + p->pMems[i] = Mem_FixedStart( (8<nMapSize = (4<nMems); + p->pMap = ALLOC( Mem_Fixed_t *, p->nMapSize+1 ); + p->pMap[0] = NULL; + for ( k = 1; k <= 4; k++ ) + p->pMap[k] = p->pMems[0]; + for ( i = 0; i < p->nMems; i++ ) + for ( k = (4<pMap[k] = p->pMems[i]; +//for ( i = 1; i < 100; i ++ ) +//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_StepStop( Mem_Step_t * p, int fVerbose ) +{ + int i; + for ( i = 0; i < p->nMems; i++ ) + Mem_FixedStop( p->pMems[i], fVerbose ); +// if ( p->pLargeChunks ) +// { +// for ( i = 0; i < p->nLargeChunks; i++ ) +// free( p->pLargeChunks[i] ); +// free( p->pLargeChunks ); +// } + free( p->pMems ); + free( p->pMap ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Creates the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes ) +{ + if ( nBytes == 0 ) + return NULL; + if ( nBytes > p->nMapSize ) + { +// printf( "Allocating %d bytes.\n", nBytes ); +/* + if ( p->nLargeChunks == p->nLargeChunksAlloc ) + { + if ( p->nLargeChunksAlloc == 0 ) + p->nLargeChunksAlloc = 5; + p->nLargeChunksAlloc *= 2; + p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); + } + p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes ); + return p->pLargeChunks[ p->nLargeChunks - 1 ]; +*/ + return ALLOC( char, nBytes ); + } + return Mem_FixedEntryFetch( p->pMap[nBytes] ); +} + + +/**Function************************************************************* + + Synopsis [Recycles the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes ) +{ + if ( nBytes == 0 ) + return; + if ( nBytes > p->nMapSize ) + { + free( pEntry ); + return; + } + Mem_FixedEntryRecycle( p->pMap[nBytes], pEntry ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mem_StepReadMemUsage( Mem_Step_t * p ) +{ + int i, nMemTotal = 0; + for ( i = 0; i < p->nMems; i++ ) + nMemTotal += p->pMems[i]->nMemoryAlloc; + return nMemTotal; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/aig/mem/mem.h b/abc70930/src/aig/mem/mem.h new file mode 100644 index 00000000..d43e5fc3 --- /dev/null +++ b/abc70930/src/aig/mem/mem.h @@ -0,0 +1,72 @@ +/**CFile**************************************************************** + + FileName [mem.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Memory management.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mem.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __MEM_H__ +#define __MEM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Mem_Fixed_t_ Mem_Fixed_t; +typedef struct Mem_Flex_t_ Mem_Flex_t; +typedef struct Mem_Step_t_ Mem_Step_t; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== mem.c ===========================================================*/ +// fixed-size-block memory manager +extern Mem_Fixed_t * Mem_FixedStart( int nEntrySize ); +extern void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose ); +extern char * Mem_FixedEntryFetch( Mem_Fixed_t * p ); +extern void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry ); +extern void Mem_FixedRestart( Mem_Fixed_t * p ); +extern int Mem_FixedReadMemUsage( Mem_Fixed_t * p ); +extern int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p ); +// flexible-size-block memory manager +extern Mem_Flex_t * Mem_FlexStart(); +extern void Mem_FlexStop( Mem_Flex_t * p, int fVerbose ); +extern char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes ); +extern void Mem_FlexRestart( Mem_Flex_t * p ); +extern int Mem_FlexReadMemUsage( Mem_Flex_t * p ); +// hierarchical memory manager +extern Mem_Step_t * Mem_StepStart( int nSteps ); +extern void Mem_StepStop( Mem_Step_t * p, int fVerbose ); +extern char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes ); +extern void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes ); +extern int Mem_StepReadMemUsage( Mem_Step_t * p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/mem/module.make b/abc70930/src/aig/mem/module.make new file mode 100644 index 00000000..ae6fcbe4 --- /dev/null +++ b/abc70930/src/aig/mem/module.make @@ -0,0 +1 @@ +SRC += src/aig/mem/mem.c diff --git a/abc70930/src/aig/rwt/module.make b/abc70930/src/aig/rwt/module.make new file mode 100644 index 00000000..439d576f --- /dev/null +++ b/abc70930/src/aig/rwt/module.make @@ -0,0 +1,3 @@ +SRC += src/aig/rwt/rwtDec.c \ + src/aig/rwt/rwtMan.c \ + src/aig/rwt/rwtUtil.c diff --git a/abc70930/src/aig/rwt/rwt.h b/abc70930/src/aig/rwt/rwt.h new file mode 100644 index 00000000..9199ff2a --- /dev/null +++ b/abc70930/src/aig/rwt/rwt.h @@ -0,0 +1,156 @@ +/**CFile**************************************************************** + + FileName [rwt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __RWT_H__ +#define __RWT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "mem.h" +#include "extra.h" +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +#define RWT_LIMIT 1048576/4 // ((1 << 20) +#define RWT_MIN(a,b) (((a) < (b))? (a) : (b)) +#define RWT_MAX(a,b) (((a) > (b))? (a) : (b)) + +typedef struct Rwt_Man_t_ Rwt_Man_t; +typedef struct Rwt_Node_t_ Rwt_Node_t; + +struct Rwt_Man_t_ +{ + // internal lookups + int nFuncs; // number of four var functions + unsigned short * puCanons; // canonical forms + char * pPhases; // canonical phases + char * pPerms; // canonical permutations + unsigned char * pMap; // mapping of functions into class numbers + unsigned short * pMapInv; // mapping of classes into functions + char * pPractical; // practical NPN classes + char ** pPerms4; // four-var permutations + // node space + Vec_Ptr_t * vForest; // all the nodes + Rwt_Node_t ** pTable; // the hash table of nodes by their canonical form + Vec_Vec_t * vClasses; // the nodes of the equivalence classes + Mem_Fixed_t * pMmNode; // memory for nodes and cuts + // statistical variables + int nTravIds; // the counter of traversal IDs + int nConsidered; // the number of nodes considered + int nAdded; // the number of nodes added to lists + int nClasses; // the number of NN classes + // the result of resynthesis + int fCompl; // indicates if the output of FF should be complemented + void * pCut; // the decomposition tree (temporary) + void * pGraph; // the decomposition tree (temporary) + char * pPerm; // permutation used for the best cut + Vec_Ptr_t * vFanins; // the fanins array (temporary) + Vec_Ptr_t * vFaninsCur; // the fanins array (temporary) + Vec_Int_t * vLevNums; // the array of levels (temporary) + Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary) + // node statistics + int nNodesConsidered; + int nNodesRewritten; + int nNodesGained; + int nScores[222]; + int nCutsGood; + int nCutsBad; + int nSubgraphs; + // runtime statistics + int timeStart; + int timeTruth; + int timeCut; + int timeRes; + int timeEval; + int timeMffc; + int timeUpdate; + int timeTotal; +}; + +struct Rwt_Node_t_ // 24 bytes +{ + int Id; // ID + int TravId; // traversal ID + unsigned uTruth : 16; // truth table + unsigned Volume : 8; // volume + unsigned Level : 6; // level + unsigned fUsed : 1; // mark + unsigned fExor : 1; // mark + Rwt_Node_t * p0; // first child + Rwt_Node_t * p1; // second child + Rwt_Node_t * pNext; // next in the table +}; + +// manipulation of complemented attributes +static inline int Rwt_IsComplement( Rwt_Node_t * p ) { return (int)(((unsigned long)p) & 01); } +static inline Rwt_Node_t * Rwt_Regular( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned long)(p) & ~01); } +static inline Rwt_Node_t * Rwt_Not( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned long)(p) ^ 01); } +static inline Rwt_Node_t * Rwt_NotCond( Rwt_Node_t * p, int c ) { return (Rwt_Node_t *)((unsigned long)(p) ^ (c)); } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== rwrDec.c ========================================================*/ +extern void Rwt_ManPreprocess( Rwt_Man_t * p ); +/*=== rwrMan.c ========================================================*/ +extern Rwt_Man_t * Rwt_ManStart( int fPrecompute ); +extern void Rwt_ManStop( Rwt_Man_t * p ); +extern void Rwt_ManPrintStats( Rwt_Man_t * p ); +extern void Rwt_ManPrintStatsFile( Rwt_Man_t * p ); +extern void * Rwt_ManReadDecs( Rwt_Man_t * p ); +extern Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p ); +extern int Rwt_ManReadCompl( Rwt_Man_t * p ); +extern void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time ); +extern void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time ); +extern void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time ); +/*=== rwrUtil.c ========================================================*/ +extern void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose ); +extern char * Rwt_ManGetPractical( Rwt_Man_t * p ); +extern Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute ); +extern void Rwt_ManIncTravId( Rwt_Man_t * p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/aig/rwt/rwtDec.c b/abc70930/src/aig/rwt/rwtDec.c new file mode 100644 index 00000000..98019629 --- /dev/null +++ b/abc70930/src/aig/rwt/rwtDec.c @@ -0,0 +1,150 @@ +/**CFile**************************************************************** + + FileName [rwtDec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Evaluation and decomposition procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwtDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwt.h" +#include "deco.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode ); +static Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Preprocesses computed library of subgraphs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManPreprocess( Rwt_Man_t * p ) +{ + Dec_Graph_t * pGraph; + Rwt_Node_t * pNode; + int i, k; + // put the nodes into the structure + p->pMapInv = ALLOC( unsigned short, 222 ); + memset( p->pMapInv, 0, sizeof(unsigned short) * 222 ); + p->vClasses = Vec_VecStart( 222 ); + for ( i = 0; i < p->nFuncs; i++ ) + { + if ( p->pTable[i] == NULL ) + continue; + // consider all implementations of this function + for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext ) + { + assert( pNode->uTruth == p->pTable[i]->uTruth ); + assert( p->pMap[pNode->uTruth] >= 0 && p->pMap[pNode->uTruth] < 222 ); + Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode ); + p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth]; + } + } + // compute decomposition forms for each node and verify them + Vec_VecForEachEntry( p->vClasses, pNode, i, k ) + { + pGraph = Rwt_NodePreprocess( p, pNode ); + pNode->pNext = (Rwt_Node_t *)pGraph; +// assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) ); + } +} + +/**Function************************************************************* + + Synopsis [Preprocesses subgraphs rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot; + assert( !Rwt_IsComplement(pNode) ); + // consider constant + if ( pNode->uTruth == 0 ) + return Dec_GraphCreateConst0(); + // consider the case of elementary var + if ( pNode->uTruth == 0x00FF ) + return Dec_GraphCreateLeaf( 3, 4, 1 ); + // start the subgraphs + pGraph = Dec_GraphCreate( 4 ); + // collect the nodes + Rwt_ManIncTravId( p ); + eRoot = Rwt_TravCollect_rec( p, pNode, pGraph ); + Dec_GraphSetRoot( pGraph, eRoot ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph ) +{ + Dec_Edge_t eNode0, eNode1, eNode; + // elementary variable + if ( pNode->fUsed ) + return Dec_EdgeCreate( pNode->Id - 1, 0 ); + // previously visited node + if ( pNode->TravId == p->nTravIds ) + return Dec_IntToEdge( pNode->Volume ); + pNode->TravId = p->nTravIds; + // solve for children + eNode0 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p0), pGraph ); + if ( Rwt_IsComplement(pNode->p0) ) + eNode0.fCompl = !eNode0.fCompl; + eNode1 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p1), pGraph ); + if ( Rwt_IsComplement(pNode->p1) ) + eNode1.fCompl = !eNode1.fCompl; + // create the decomposition node(s) + if ( pNode->fExor ) + eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 ); + else + eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); + // save the result + pNode->Volume = Dec_EdgeToInt( eNode ); + return eNode; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/rwt/rwtMan.c b/abc70930/src/aig/rwt/rwtMan.c new file mode 100644 index 00000000..869043a4 --- /dev/null +++ b/abc70930/src/aig/rwt/rwtMan.c @@ -0,0 +1,358 @@ +/**CFile**************************************************************** + + FileName [rwtMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Rewriting manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwt.h" +#include "deco.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned short * s_puCanons = NULL; +static char * s_pPhases = NULL; +static char * s_pPerms = NULL; +static unsigned char * s_pMap = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts residual rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManGlobalStart() +{ + if ( s_puCanons == NULL ) + Extra_Truth4VarNPN( &s_puCanons, &s_pPhases, &s_pPerms, &s_pMap ); +} + +/**Function************************************************************* + + Synopsis [Starts residual rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManGlobalStop() +{ + FREE( s_puCanons ); + FREE( s_pPhases ); + FREE( s_pPerms ); + FREE( s_pMap ); +} + +/**Function************************************************************* + + Synopsis [Starts rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rwt_Man_t * Rwt_ManStart( int fPrecompute ) +{ + Rwt_Man_t * p; + int clk = clock(); +clk = clock(); + p = ALLOC( Rwt_Man_t, 1 ); + memset( p, 0, sizeof(Rwt_Man_t) ); + p->nFuncs = (1<<16); + // copy the global tables + Rwt_ManGlobalStart(); + p->puCanons = s_puCanons; + p->pPhases = s_pPhases; + p->pPerms = s_pPerms; + p->pMap = s_pMap; + // initialize practical NPN classes + p->pPractical = Rwt_ManGetPractical( p ); + // create the table + p->pTable = ALLOC( Rwt_Node_t *, p->nFuncs ); + memset( p->pTable, 0, sizeof(Rwt_Node_t *) * p->nFuncs ); + // create the elementary nodes + p->pMmNode = Mem_FixedStart( sizeof(Rwt_Node_t) ); + p->vForest = Vec_PtrAlloc( 100 ); + Rwt_ManAddVar( p, 0x0000, fPrecompute ); // constant 0 + Rwt_ManAddVar( p, 0xAAAA, fPrecompute ); // var A + Rwt_ManAddVar( p, 0xCCCC, fPrecompute ); // var B + Rwt_ManAddVar( p, 0xF0F0, fPrecompute ); // var C + Rwt_ManAddVar( p, 0xFF00, fPrecompute ); // var D + p->nClasses = 5; + // other stuff + p->nTravIds = 1; + p->pPerms4 = Extra_Permutations( 4 ); + p->vLevNums = Vec_IntAlloc( 50 ); + p->vFanins = Vec_PtrAlloc( 50 ); + p->vFaninsCur = Vec_PtrAlloc( 50 ); + p->vNodesTemp = Vec_PtrAlloc( 50 ); + if ( fPrecompute ) + { // precompute subgraphs +// Rwt_ManPrecompute( p ); +// Rwt_ManPrint( p ); +// Rwt_ManWriteToArray( p ); + } + else + { // load saved subgraphs + Rwt_ManLoadFromArray( p, 0 ); +// Rwt_ManPrint( p ); + Rwt_ManPreprocess( p ); + } +p->timeStart = clock() - clk; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManStop( Rwt_Man_t * p ) +{ + if ( p->vClasses ) + { + Rwt_Node_t * pNode; + int i, k; + Vec_VecForEachEntry( p->vClasses, pNode, i, k ) + Dec_GraphFree( (Dec_Graph_t *)pNode->pNext ); + } + if ( p->vClasses ) Vec_VecFree( p->vClasses ); + Vec_PtrFree( p->vNodesTemp ); + Vec_PtrFree( p->vForest ); + Vec_IntFree( p->vLevNums ); + Vec_PtrFree( p->vFanins ); + Vec_PtrFree( p->vFaninsCur ); + Mem_FixedStop( p->pMmNode, 0 ); + FREE( p->pMapInv ); + free( p->pTable ); + free( p->pPractical ); + free( p->pPerms4 ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManPrintStats( Rwt_Man_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < 222; i++ ) + Counter += (p->nScores[i] > 0); + + printf( "Rewriting statistics:\n" ); + printf( "Total cuts tries = %8d.\n", p->nCutsGood ); + printf( "Bad cuts found = %8d.\n", p->nCutsBad ); + printf( "Total subgraphs = %8d.\n", p->nSubgraphs ); + printf( "Used NPN classes = %8d.\n", Counter ); + printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); + printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten ); + printf( "Calculated gain = %8d.\n", p->nNodesGained ); + PRT( "Start ", p->timeStart ); + PRT( "Cuts ", p->timeCut ); + PRT( "Truth ", p->timeTruth ); + PRT( "Resynthesis ", p->timeRes ); + PRT( " Mffc ", p->timeMffc ); + PRT( " Eval ", p->timeEval ); + PRT( "Update ", p->timeUpdate ); + PRT( "TOTAL ", p->timeTotal ); + +/* + printf( "The scores are:\n" ); + for ( i = 0; i < 222; i++ ) + if ( p->nScores[i] > 0 ) + { + extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); + printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] ); + Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) ); + } + printf( "\n" ); +*/ +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManPrintStatsFile( Rwt_Man_t * p ) +{ + FILE * pTable; + pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%d ", p->nCutsGood ); + fprintf( pTable, "%d ", p->nSubgraphs ); + fprintf( pTable, "%d ", p->nNodesRewritten ); + fprintf( pTable, "%d", p->nNodesGained ); + fprintf( pTable, "\n" ); + fclose( pTable ); +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Rwt_ManReadDecs( Rwt_Man_t * p ) +{ + return p->pGraph; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p ) +{ + return p->vFanins; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwt_ManReadCompl( Rwt_Man_t * p ) +{ + return p->fCompl; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time ) +{ + p->timeCut += Time; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time ) +{ + p->timeUpdate += Time; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time ) +{ + p->timeTotal += Time; +} + + +/**Function************************************************************* + + Synopsis [Precomputes AIG subgraphs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_Precompute() +{ + Rwt_Man_t * p; + p = Rwt_ManStart( 1 ); + Rwt_ManStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/aig/rwt/rwtUtil.c b/abc70930/src/aig/rwt/rwtUtil.c new file mode 100644 index 00000000..af3e1893 --- /dev/null +++ b/abc70930/src/aig/rwt/rwtUtil.c @@ -0,0 +1,665 @@ +/**CFile**************************************************************** + + FileName [rwtUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwtUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// precomputed data +#ifdef _WIN32 +unsigned short s_RwtPracticalClasses[]; +unsigned short s_RwtAigSubgraphs[]; +#else +static unsigned short s_RwtPracticalClasses[]; +static unsigned short s_RwtAigSubgraphs[]; +#endif + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Adds the node to the end of the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ListAddToTail( Rwt_Node_t ** ppList, Rwt_Node_t * pNode ) +{ + Rwt_Node_t * pTemp; + // find the last one + for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext ) + ppList = &pTemp->pNext; + // attach at the end + *ppList = pNode; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute ) +{ + Rwt_Node_t * pNew; + pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode ); + pNew->Id = p->vForest->nSize; + pNew->TravId = 0; + pNew->uTruth = uTruth; + pNew->Level = 0; + pNew->Volume = 0; + pNew->fUsed = 1; + pNew->fExor = 0; + pNew->p0 = NULL; + pNew->p1 = NULL; + pNew->pNext = NULL; + Vec_PtrPush( p->vForest, pNew ); + if ( fPrecompute ) + Rwt_ListAddToTail( p->pTable + uTruth, pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rwt_Node_t * Rwt_ManAddNode( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1, int fExor, int Level, int Volume ) +{ + Rwt_Node_t * pNew; + unsigned uTruth; + // compute truth table, leve, volume + p->nConsidered++; + if ( fExor ) + uTruth = (p0->uTruth ^ p1->uTruth); + else + uTruth = (Rwt_IsComplement(p0)? ~Rwt_Regular(p0)->uTruth : Rwt_Regular(p0)->uTruth) & + (Rwt_IsComplement(p1)? ~Rwt_Regular(p1)->uTruth : Rwt_Regular(p1)->uTruth) & 0xFFFF; + // create the new node + pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode ); + pNew->Id = p->vForest->nSize; + pNew->TravId = 0; + pNew->uTruth = uTruth; + pNew->Level = Level; + pNew->Volume = Volume; + pNew->fUsed = 0; + pNew->fExor = fExor; + pNew->p0 = p0; + pNew->p1 = p1; + pNew->pNext = NULL; + Vec_PtrPush( p->vForest, pNew ); + // do not add if the node is not essential + if ( uTruth != p->puCanons[uTruth] ) + return pNew; + + // add to the list + p->nAdded++; + if ( p->pTable[uTruth] == NULL ) + p->nClasses++; + Rwt_ListAddToTail( p->pTable + uTruth, pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_Trav_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, int * pVolume ) +{ + if ( pNode->fUsed || pNode->TravId == p->nTravIds ) + return; + pNode->TravId = p->nTravIds; + (*pVolume)++; + if ( pNode->fExor ) + (*pVolume)++; + Rwt_Trav_rec( p, Rwt_Regular(pNode->p0), pVolume ); + Rwt_Trav_rec( p, Rwt_Regular(pNode->p1), pVolume ); +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManIncTravId( Rwt_Man_t * p ) +{ + Rwt_Node_t * pNode; + int i; + if ( p->nTravIds++ < 0x8FFFFFFF ) + return; + Vec_PtrForEachEntry( p->vForest, pNode, i ) + pNode->TravId = 0; + p->nTravIds = 1; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwt_ManNodeVolume( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1 ) +{ + int Volume = 0; + Rwt_ManIncTravId( p ); + Rwt_Trav_rec( p, p0, &Volume ); + Rwt_Trav_rec( p, p1, &Volume ); + return Volume; +} + +/**Function************************************************************* + + Synopsis [Loads data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose ) +{ + unsigned short * pArray = s_RwtAigSubgraphs; + Rwt_Node_t * p0, * p1; + unsigned Entry0, Entry1; + int Level, Volume, nEntries, fExor; + int i, clk = clock(); + + // reconstruct the forest + for ( i = 0; ; i++ ) + { + Entry0 = pArray[2*i + 0]; + Entry1 = pArray[2*i + 1]; + if ( Entry0 == 0 && Entry1 == 0 ) + break; + // get EXOR flag + fExor = (Entry0 & 1); + Entry0 >>= 1; + // get the nodes + p0 = p->vForest->pArray[Entry0 >> 1]; + p1 = p->vForest->pArray[Entry1 >> 1]; + // compute the level and volume of the new nodes + Level = 1 + RWT_MAX( p0->Level, p1->Level ); + Volume = 1 + Rwt_ManNodeVolume( p, p0, p1 ); + // set the complemented attributes + p0 = Rwt_NotCond( p0, (Entry0 & 1) ); + p1 = Rwt_NotCond( p1, (Entry1 & 1) ); + // add the node +// Rwt_ManTryNode( p, p0, p1, Level, Volume ); + Rwt_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor ); + } + nEntries = i - 1; + if ( fVerbose ) + { + printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded ); + printf( "The number of nodes loaded = %d. ", nEntries ); PRT( "Loading", clock() - clk ); + } +} + +/**Function************************************************************* + + Synopsis [Create practical classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Rwt_ManGetPractical( Rwt_Man_t * p ) +{ + char * pPractical; + int i; + pPractical = ALLOC( char, p->nFuncs ); + memset( pPractical, 0, sizeof(char) * p->nFuncs ); + pPractical[0] = 1; + for ( i = 1; ; i++ ) + { + if ( s_RwtPracticalClasses[i] == 0 ) + break; + pPractical[ s_RwtPracticalClasses[i] ] = 1; + } + return pPractical; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +// the following 135 practical NPN classes of 4-variable functions were computed +// by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks +static unsigned short s_RwtPracticalClasses[] = +{ + 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b, + 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff, + 0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c, + 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, + 0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab, + 0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe, + 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368, + 0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5, + 0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669, + 0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2, + 0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8, + 0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4, + 0x1ee1, 0x3cc3, 0x6996, 0x0000 +}; + +static unsigned short s_RwtAigSubgraphs[] = +{ + 0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002, + 0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002, + 0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004, + 0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002, + 0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004, + 0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006, + 0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007, + 0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009, + 0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007, + 0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005, + 0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006, + 0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008, + 0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006, + 0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008, + 0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006, + 0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004, + 0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009, + 0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e, + 0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005, + 0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f, + 0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009, + 0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e, + 0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005, + 0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008, + 0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013, + 0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008, + 0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012, + 0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003, + 0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009, + 0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013, + 0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002, + 0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d, + 0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c, + 0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007, + 0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012, + 0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002, + 0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008, + 0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f, + 0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019, + 0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002, + 0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008, + 0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011, + 0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017, + 0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d, + 0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009, + 0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019, + 0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024, + 0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004, + 0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b, + 0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021, + 0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024, + 0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009, + 0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024, + 0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004, + 0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d, + 0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020, + 0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024, + 0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027, + 0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f, + 0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d, + 0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024, + 0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006, + 0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015, + 0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f, + 0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002, + 0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016, + 0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025, + 0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b, + 0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a, + 0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003, + 0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f, + 0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018, + 0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b, + 0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003, + 0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006, + 0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019, + 0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022, + 0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f, + 0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004, + 0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f, + 0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017, + 0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f, + 0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002, + 0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011, + 0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037, + 0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010, + 0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b, + 0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002, + 0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005, + 0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d, + 0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011, + 0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012, + 0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039, + 0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005, + 0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011, + 0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017, + 0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b, + 0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009, + 0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037, + 0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010, + 0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030, + 0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009, + 0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d, + 0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008, + 0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010, + 0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030, + 0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044, + 0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011, + 0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043, + 0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017, + 0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a, + 0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f, + 0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f, + 0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023, + 0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007, + 0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033, + 0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b, + 0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037, + 0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d, + 0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067, + 0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038, + 0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d, + 0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006, + 0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025, + 0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014, + 0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f, + 0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008, + 0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d, + 0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058, + 0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008, + 0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d, + 0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059, + 0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b, + 0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b, + 0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019, + 0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043, + 0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061, + 0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007, + 0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004, + 0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045, + 0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d, + 0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009, + 0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044, + 0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044, + 0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097, + 0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f, + 0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048, + 0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a, + 0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009, + 0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044, + 0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a, + 0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029, + 0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a, + 0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013, + 0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5, + 0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f, + 0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095, + 0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009, + 0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f, + 0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013, + 0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095, + 0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030, + 0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6, + 0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e, + 0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061, + 0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc, + 0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044, + 0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a, + 0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008, + 0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8, + 0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095, + 0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004, + 0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029, + 0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068, + 0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c, + 0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029, + 0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c, + 0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013, + 0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067, + 0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf, + 0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d, + 0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003, + 0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f, + 0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099, + 0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf, + 0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f, + 0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176, + 0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3, + 0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b, + 0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f, + 0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008, + 0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095, + 0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b, + 0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec, + 0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3, + 0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009, + 0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009, + 0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a, + 0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030, + 0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009, + 0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033, + 0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e, + 0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158, + 0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a, + 0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d, + 0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168, + 0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e, + 0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133, + 0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b, + 0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f, + 0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da, + 0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d, + 0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef, + 0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181, + 0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027, + 0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a, + 0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f, + 0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181, + 0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205, + 0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033, + 0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225, + 0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0, + 0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1, + 0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d, + 0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006, + 0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a, + 0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b, + 0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033, + 0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231, + 0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4, + 0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e, + 0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec, + 0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e, + 0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3, + 0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a, + 0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef, + 0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175, + 0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0, + 0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f, + 0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3, + 0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e, + 0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086, + 0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5, + 0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e, + 0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181, + 0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0, + 0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095, + 0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b, + 0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276, + 0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4, + 0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006, + 0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3, + 0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d, + 0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103, + 0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234, + 0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d, + 0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106, + 0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8, + 0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044, + 0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0, + 0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a, + 0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6, + 0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238, + 0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e, + 0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067, + 0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020, + 0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021, + 0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183, + 0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268, + 0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc, + 0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213, + 0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023, + 0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b, + 0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da, + 0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287, + 0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce, + 0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf, + 0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338, + 0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328, + 0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003, + 0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330, + 0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282, + 0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a, + 0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9, + 0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247, + 0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d, + 0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce, + 0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0, + 0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004, + 0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315, + 0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d, + 0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd, + 0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb, + 0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f, + 0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173, + 0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029, + 0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3, + 0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053, + 0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030, + 0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021, + 0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2, + 0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9, + 0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285, + 0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b, + 0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a, + 0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315, + 0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f, + 0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c, + 0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e, + 0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089, + 0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021, + 0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354, + 0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f, + 0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095, + 0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3, + 0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e, + 0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009, + 0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009, + 0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b, + 0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381, + 0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008, + 0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb, + 0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5, + 0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027, + 0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030, + 0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb, + 0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a, + 0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009, + 0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027, + 0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d, + 0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271, + 0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f, + 0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009, + 0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009, + 0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f, + 0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9, + 0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235, + 0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d, + 0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085, + 0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3, + 0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043, + 0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7, + 0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f, + 0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059, + 0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d, + 0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009, + 0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b, + 0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061, + 0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9, + 0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027, + 0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019, + 0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1, + 0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b, + 0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7, + 0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb, + 0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d, + 0x0000,0x0000 +}; + + diff --git a/abc70930/src/base/.DS_Store b/abc70930/src/base/.DS_Store new file mode 100644 index 00000000..a4d90d14 Binary files /dev/null and b/abc70930/src/base/.DS_Store differ diff --git a/abc70930/src/base/abc/abc.h b/abc70930/src/base/abc/abc.h new file mode 100644 index 00000000..2e2b379b --- /dev/null +++ b/abc70930/src/base/abc/abc.h @@ -0,0 +1,929 @@ +/**CFile**************************************************************** + + FileName [abc.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __ABC_H__ +#define __ABC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include "cuddInt.h" +#include "hop.h" +#include "extra.h" +#include "vec.h" +#include "stmm.h" +#include "nm.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// network types +typedef enum { + ABC_NTK_NONE = 0, // 0: unknown + ABC_NTK_NETLIST, // 1: network with PIs/POs, latches, nodes, and nets + ABC_NTK_LOGIC, // 2: network with PIs/POs, latches, and nodes + ABC_NTK_STRASH, // 3: structurally hashed AIG (two input AND gates with c-attributes on edges) + ABC_NTK_OTHER // 4: unused +} Abc_NtkType_t; + +// network functionality +typedef enum { + ABC_FUNC_NONE = 0, // 0: unknown + ABC_FUNC_SOP, // 1: sum-of-products + ABC_FUNC_BDD, // 2: binary decision diagrams + ABC_FUNC_AIG, // 3: and-inverter graphs + ABC_FUNC_MAP, // 4: standard cell library + ABC_FUNC_BLIFMV, // 5: BLIF-MV node functions + ABC_FUNC_BLACKBOX, // 6: black box about which nothing is known + ABC_FUNC_OTHER // 7: unused +} Abc_NtkFunc_t; + +// Supported type/functionality combinations: +/*------------------------------------------| +| | SOP | BDD | AIG | Map | +|-----------|-------|-------|-------|-------| +| Netlist | x | | x | x | +|-----------|-------|-------|-------|-------| +| Logic | x | x | x | x | +|-----------|-------|-------|-------|-------| +| Strash | | | x | | +--------------------------------------------|*/ + +// object types +typedef enum { + ABC_OBJ_NONE = 0, // 0: unknown + ABC_OBJ_CONST1, // 1: constant 1 node (AIG only) + ABC_OBJ_PIO, // 2: inout terminal + ABC_OBJ_PI, // 3: primary input terminal + ABC_OBJ_PO, // 4: primary output terminal + ABC_OBJ_BI, // 5: box input terminal + ABC_OBJ_BO, // 6: box output terminal + ABC_OBJ_ASSERT, // 7: assertion terminal + ABC_OBJ_NET, // 8: net + ABC_OBJ_NODE, // 9: node + ABC_OBJ_LATCH, // 10: latch + ABC_OBJ_WHITEBOX, // 11: box with known contents + ABC_OBJ_BLACKBOX, // 12: box with unknown contents + ABC_OBJ_NUMBER // 13: unused +} Abc_ObjType_t; + +// latch initial values +typedef enum { + ABC_INIT_NONE = 0, // 0: unknown + ABC_INIT_ZERO, // 1: zero + ABC_INIT_ONE, // 2: one + ABC_INIT_DC, // 3: don't-care + ABC_INIT_OTHER // 4: unused +} Abc_InitType_t; + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//typedef int bool; +#ifndef __cplusplus +#ifndef bool +#define bool int +#endif +#endif + +#ifndef SINT64 +#define SINT64 + +#ifdef _WIN32 +typedef signed __int64 sint64; // compatible with MS VS 6.0 +#else +typedef long long sint64; +#endif + +#endif + +typedef struct Abc_Lib_t_ Abc_Lib_t; +typedef struct Abc_Ntk_t_ Abc_Ntk_t; +typedef struct Abc_Obj_t_ Abc_Obj_t; +typedef struct Abc_Aig_t_ Abc_Aig_t; +typedef struct Abc_ManTime_t_ Abc_ManTime_t; +typedef struct Abc_ManCut_t_ Abc_ManCut_t; +typedef struct Abc_Time_t_ Abc_Time_t; + +struct Abc_Time_t_ +{ + float Rise; + float Fall; + float Worst; +}; + +struct Abc_Obj_t_ // 12 words +{ + // high-level information + Abc_Ntk_t * pNtk; // the host network + int Id; // the object ID + int TravId; // the traversal ID (if changed, update Abc_NtkIncrementTravId) + // internal information + unsigned Type : 4; // the object type + unsigned fMarkA : 1; // the multipurpose mark + unsigned fMarkB : 1; // the multipurpose mark + unsigned fMarkC : 1; // the multipurpose mark + unsigned fPhase : 1; // the flag to mark the phase of equivalent node + unsigned fExor : 1; // marks AIG node that is a root of EXOR + unsigned fPersist: 1; // marks the persistant AIG node + unsigned fCompl0 : 1; // complemented attribute of the first fanin in the AIG + unsigned fCompl1 : 1; // complemented attribute of the second fanin in the AIG + unsigned Level : 20; // the level of the node + // connectivity + Vec_Int_t vFanins; // the array of fanins + Vec_Int_t vFanouts; // the array of fanouts + // miscellaneous + void * pData; // the network specific data (SOP, BDD, gate, equiv class, etc) + Abc_Obj_t * pNext; // the next pointer in the hash table + Abc_Obj_t * pCopy; // the copy of this object + Hop_Obj_t * pEquiv; // pointer to the HAIG node +}; + +struct Abc_Ntk_t_ +{ + // general information + Abc_NtkType_t ntkType; // type of the network + Abc_NtkFunc_t ntkFunc; // functionality of the network + char * pName; // the network name + char * pSpec; // the name of the spec file if present + Nm_Man_t * pManName; // name manager (stores names of objects) + // components of the network + Vec_Ptr_t * vObjs; // the array of all objects (net, nodes, latches, etc) + Vec_Ptr_t * vPis; // the array of primary inputs + Vec_Ptr_t * vPos; // the array of primary outputs + Vec_Ptr_t * vCis; // the array of combinational inputs (PIs, latches) + Vec_Ptr_t * vCos; // the array of combinational outputs (POs, asserts, latches) + Vec_Ptr_t * vPios; // the array of PIOs + Vec_Ptr_t * vAsserts; // the array of assertions + Vec_Ptr_t * vBoxes; // the array of boxes + // the number of living objects + int nObjs; // the number of live objs + int nObjCounts[ABC_OBJ_NUMBER]; // the number of objects by type + // the backup network and the step number + Abc_Ntk_t * pNetBackup; // the pointer to the previous backup network + int iStep; // the generation number for the given network + // hierarchy + Abc_Lib_t * pDesign; + short fHieVisited; // flag to mark the visited network + short fHiePath; // flag to mark the network on the path + // miscellaneous data members + int nTravIds; // the unique traversal IDs of nodes + Extra_MmFixed_t * pMmObj; // memory manager for objects + Extra_MmStep_t * pMmStep; // memory manager for arrays + void * pManFunc; // functionality manager (AIG manager, BDD manager, or memory manager for SOPs) +// Abc_Lib_t * pVerLib; // for structural verilog designs + Abc_ManTime_t * pManTime; // the timing manager (for mapped networks) stores arrival/required times for all nodes + void * pManCut; // the cut manager (for AIGs) stores information about the cuts computed for the nodes + int LevelMax; // maximum number of levels + Vec_Int_t * vLevelsR; // level in the reverse topological order (for AIGs) + Vec_Ptr_t * vSupps; // CO support information + int * pModel; // counter-example (for miters) + Abc_Ntk_t * pExdc; // the EXDC network (if given) + void * pData; // misc + Abc_Ntk_t * pCopy; + Hop_Man_t * pHaig; // history AIG + // node attributes + Vec_Ptr_t * vAttrs; // managers of various node attributes (node functionality, global BDDs, etc) +}; + +struct Abc_Lib_t_ +{ + char * pName; // the name of the library + void * pManFunc; // functionality manager for the nodes + Vec_Ptr_t * vTops; // the array of top-level modules + Vec_Ptr_t * vModules; // the array of modules + st_table * tModules; // the table hashing module names into their networks + Abc_Lib_t * pLibrary; // the library used to map this design + void * pGenlib; // the genlib library used to map this design +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// maximum/minimum operators +#define ABC_MIN(a,b) (((a) < (b))? (a) : (b)) +#define ABC_MAX(a,b) (((a) > (b))? (a) : (b)) +#define ABC_ABS(a) (((a) >= 0)? (a) :-(a)) +#define ABC_INFINITY (100000000) + +// transforming floats into ints and back +static inline int Abc_Float2Int( float Val ) { return *((int *)&Val); } +static inline float Abc_Int2Float( int Num ) { return *((float *)&Num); } +static inline int Abc_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } +static inline int Abc_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline int Abc_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } +static inline void Abc_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } +static inline void Abc_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } +static inline unsigned Abc_InfoRandomWord() { return ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())); } // #define RAND_MAX 0x7fff +static inline void Abc_InfoRandom( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = Abc_InfoRandomWord(); } +static inline void Abc_InfoClear( unsigned * p, int nWords ) { memset( p, 0, sizeof(unsigned) * nWords ); } +static inline void Abc_InfoFill( unsigned * p, int nWords ) { memset( p, 0xff, sizeof(unsigned) * nWords );} +static inline void Abc_InfoNot( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = ~p[i]; } +static inline int Abc_InfoIsZero( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( p[i] ) return 0; return 1; } +static inline int Abc_InfoIsOne( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~p[i] ) return 0; return 1; } +static inline void Abc_InfoCopy( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = q[i]; } +static inline void Abc_InfoAnd( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] &= q[i]; } +static inline void Abc_InfoOr( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= q[i]; } +static inline void Abc_InfoXor( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] ^= q[i]; } +static inline int Abc_InfoIsOrOne( unsigned * p, unsigned * q, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i]) ) return 0; return 1; } +static inline int Abc_InfoIsOrOne3( unsigned * p, unsigned * q, unsigned * r, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i] | r[i]) ) return 0; return 1; } + +// checking the network type +static inline bool Abc_NtkIsNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_NETLIST; } +static inline bool Abc_NtkIsLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_LOGIC; } +static inline bool Abc_NtkIsStrash( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_STRASH; } + +static inline bool Abc_NtkHasSop( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP; } +static inline bool Abc_NtkHasBdd( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD; } +static inline bool Abc_NtkHasAig( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG; } +static inline bool Abc_NtkHasMapping( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP; } +static inline bool Abc_NtkHasBlifMv( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV; } +static inline bool Abc_NtkHasBlackbox( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLACKBOX; } + +static inline bool Abc_NtkIsSopNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline bool Abc_NtkIsAigNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline bool Abc_NtkIsMappedNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline bool Abc_NtkIsBlifMvNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline bool Abc_NtkIsSopLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_LOGIC ; } +static inline bool Abc_NtkIsBddLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD && pNtk->ntkType == ABC_NTK_LOGIC ; } +static inline bool Abc_NtkIsAigLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_LOGIC ; } +static inline bool Abc_NtkIsMappedLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_LOGIC ; } + +// reading data members of the network +static inline char * Abc_NtkName( Abc_Ntk_t * pNtk ) { return pNtk->pName; } +static inline char * Abc_NtkSpec( Abc_Ntk_t * pNtk ) { return pNtk->pSpec; } +static inline int Abc_NtkTravId( Abc_Ntk_t * pNtk ) { return pNtk->nTravIds; } +static inline Abc_Ntk_t * Abc_NtkExdc( Abc_Ntk_t * pNtk ) { return pNtk->pExdc; } +static inline Abc_Ntk_t * Abc_NtkBackup( Abc_Ntk_t * pNtk ) { return pNtk->pNetBackup; } +static inline int Abc_NtkStep ( Abc_Ntk_t * pNtk ) { return pNtk->iStep; } + +// setting data members of the network +static inline void Abc_NtkSetName ( Abc_Ntk_t * pNtk, char * pName ) { pNtk->pName = pName; } +static inline void Abc_NtkSetSpec ( Abc_Ntk_t * pNtk, char * pName ) { pNtk->pSpec = pName; } +static inline void Abc_NtkSetBackup( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNetBackup ) { pNtk->pNetBackup = pNetBackup; } +static inline void Abc_NtkSetStep ( Abc_Ntk_t * pNtk, int iStep ) { pNtk->iStep = iStep; } + +// getting the number of objects +static inline int Abc_NtkObjNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjs; } +static inline int Abc_NtkObjNumMax( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vObjs); } +static inline int Abc_NtkPiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPis); } +static inline int Abc_NtkPoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPos); } +static inline int Abc_NtkCiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCis); } +static inline int Abc_NtkCoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCos); } +static inline int Abc_NtkAssertNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vAsserts); } +static inline int Abc_NtkBoxNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vBoxes); } +static inline int Abc_NtkBiNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BI]; } +static inline int Abc_NtkBoNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BO]; } +static inline int Abc_NtkNetNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NET]; } +static inline int Abc_NtkNodeNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NODE]; } +static inline int Abc_NtkLatchNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_LATCH]; } +static inline int Abc_NtkWhiteboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_WHITEBOX]; } +static inline int Abc_NtkBlackboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BLACKBOX]; } +static inline bool Abc_NtkIsComb( Abc_Ntk_t * pNtk ) { return Abc_NtkLatchNum(pNtk) == 0; } +static inline bool Abc_NtkHasOnlyLatchBoxes(Abc_Ntk_t * pNtk ){ return Abc_NtkLatchNum(pNtk) == Abc_NtkBoxNum(pNtk); } + +// creating simple objects +extern Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); +static inline Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PI ); } +static inline Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PO ); } +static inline Abc_Obj_t * Abc_NtkCreateBi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BI ); } +static inline Abc_Obj_t * Abc_NtkCreateBo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BO ); } +static inline Abc_Obj_t * Abc_NtkCreateAssert( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_ASSERT ); } +static inline Abc_Obj_t * Abc_NtkCreateNet( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NET ); } +static inline Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NODE ); } +static inline Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_LATCH ); } +static inline Abc_Obj_t * Abc_NtkCreateWhitebox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_WHITEBOX ); } +static inline Abc_Obj_t * Abc_NtkCreateBlackbox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BLACKBOX ); } + +// reading objects +static inline Abc_Obj_t * Abc_NtkObj( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vObjs, i ); } +static inline Abc_Obj_t * Abc_NtkPi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i ); } +static inline Abc_Obj_t * Abc_NtkPo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i ); } +static inline Abc_Obj_t * Abc_NtkCi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i ); } +static inline Abc_Obj_t * Abc_NtkCo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i ); } +static inline Abc_Obj_t * Abc_NtkAssert( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vAsserts, i );} +static inline Abc_Obj_t * Abc_NtkBox( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i ); } + +// working with complemented attributes of objects +static inline bool Abc_ObjIsComplement( Abc_Obj_t * p ) { return (bool)((unsigned long)p & (unsigned long)01); } +static inline Abc_Obj_t * Abc_ObjRegular( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned long)p & ~(unsigned long)01); } +static inline Abc_Obj_t * Abc_ObjNot( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned long)p ^ (unsigned long)01); } +static inline Abc_Obj_t * Abc_ObjNotCond( Abc_Obj_t * p, int c ) { return (Abc_Obj_t *)((unsigned long)p ^ (unsigned long)(c!=0)); } + +// reading data members of the object +static inline unsigned Abc_ObjType( Abc_Obj_t * pObj ) { return pObj->Type; } +static inline unsigned Abc_ObjId( Abc_Obj_t * pObj ) { return pObj->Id; } +static inline int Abc_ObjTravId( Abc_Obj_t * pObj ) { return pObj->TravId; } +static inline int Abc_ObjLevel( Abc_Obj_t * pObj ) { return pObj->Level; } +static inline Vec_Int_t * Abc_ObjFaninVec( Abc_Obj_t * pObj ) { return &pObj->vFanins; } +static inline Vec_Int_t * Abc_ObjFanoutVec( Abc_Obj_t * pObj ) { return &pObj->vFanouts; } +static inline Abc_Obj_t * Abc_ObjCopy( Abc_Obj_t * pObj ) { return pObj->pCopy; } +static inline Abc_Ntk_t * Abc_ObjNtk( Abc_Obj_t * pObj ) { return pObj->pNtk; } +static inline void * Abc_ObjData( Abc_Obj_t * pObj ) { return pObj->pData; } +static inline Hop_Obj_t * Abc_ObjEquiv( Abc_Obj_t * pObj ) { return pObj->pEquiv; } +static inline Abc_Obj_t * Abc_ObjCopyCond( Abc_Obj_t * pObj ) { return Abc_ObjRegular(pObj)->pCopy? Abc_ObjNotCond(Abc_ObjRegular(pObj)->pCopy, Abc_ObjIsComplement(pObj)) : NULL; } + +// setting data members of the network +static inline void Abc_ObjSetLevel( Abc_Obj_t * pObj, int Level ) { pObj->Level = Level; } +static inline void Abc_ObjSetCopy( Abc_Obj_t * pObj, Abc_Obj_t * pCopy ) { pObj->pCopy = pCopy; } +static inline void Abc_ObjSetData( Abc_Obj_t * pObj, void * pData ) { pObj->pData = pData; } + +// checking the object type +static inline bool Abc_ObjIsPio( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PIO; } +static inline bool Abc_ObjIsPi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI; } +static inline bool Abc_ObjIsPo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO; } +static inline bool Abc_ObjIsBi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BI; } +static inline bool Abc_ObjIsBo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BO; } +static inline bool Abc_ObjIsAssert( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_ASSERT; } +static inline bool Abc_ObjIsCi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_BO; } +static inline bool Abc_ObjIsCo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_BI || pObj->Type == ABC_OBJ_ASSERT; } +static inline bool Abc_ObjIsTerm( Abc_Obj_t * pObj ) { return Abc_ObjIsCi(pObj) || Abc_ObjIsCo(pObj); } +static inline bool Abc_ObjIsNet( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NET; } +static inline bool Abc_ObjIsNode( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NODE; } +static inline bool Abc_ObjIsLatch( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH; } +static inline bool Abc_ObjIsBox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH || pObj->Type == ABC_OBJ_WHITEBOX || pObj->Type == ABC_OBJ_BLACKBOX; } +static inline bool Abc_ObjIsWhitebox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_WHITEBOX;} +static inline bool Abc_ObjIsBlackbox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BLACKBOX;} +static inline void Abc_ObjBlackboxToWhitebox( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBlackbox(pObj) ); pObj->Type = ABC_OBJ_WHITEBOX; pObj->pNtk->nObjCounts[ABC_OBJ_BLACKBOX]--; pObj->pNtk->nObjCounts[ABC_OBJ_WHITEBOX]++; } + +// working with fanin/fanout edges +static inline int Abc_ObjFaninNum( Abc_Obj_t * pObj ) { return pObj->vFanins.nSize; } +static inline int Abc_ObjFanoutNum( Abc_Obj_t * pObj ) { return pObj->vFanouts.nSize; } +static inline int Abc_ObjFaninId( Abc_Obj_t * pObj, int i) { return pObj->vFanins.pArray[i]; } +static inline int Abc_ObjFaninId0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0]; } +static inline int Abc_ObjFaninId1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1]; } +static inline int Abc_ObjFanoutEdgeNum( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { assert( Abc_NtkHasAig(pObj->pNtk) ); if ( Abc_ObjFaninId0(pFanout) == pObj->Id ) return 0; if ( Abc_ObjFaninId1(pFanout) == pObj->Id ) return 1; assert( 0 ); return -1; } +static inline Abc_Obj_t * Abc_ObjFanout( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[i] ]; } +static inline Abc_Obj_t * Abc_ObjFanout0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[0] ]; } +static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[i] ]; } +static inline Abc_Obj_t * Abc_ObjFanin0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[0] ]; } +static inline Abc_Obj_t * Abc_ObjFanin1( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[1] ]; } +static inline Abc_Obj_t * Abc_ObjFanin0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanin0(pObj) : pObj); } +static inline Abc_Obj_t * Abc_ObjFanout0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanout0(pObj) : pObj); } +static inline bool Abc_ObjFaninC0( Abc_Obj_t * pObj ) { return pObj->fCompl0; } +static inline bool Abc_ObjFaninC1( Abc_Obj_t * pObj ) { return pObj->fCompl1; } +static inline bool Abc_ObjFaninC( Abc_Obj_t * pObj, int i ) { assert( i >=0 && i < 2 ); return i? pObj->fCompl1 : pObj->fCompl0; } +static inline void Abc_ObjSetFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1 = 1; else pObj->fCompl0 = 1; } +static inline void Abc_ObjXorFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1^= 1; else pObj->fCompl0^= 1; } +static inline Abc_Obj_t * Abc_ObjChild( Abc_Obj_t * pObj, int i ) { return Abc_ObjNotCond( Abc_ObjFanin(pObj,i), Abc_ObjFaninC(pObj,i) );} +static inline Abc_Obj_t * Abc_ObjChild0( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild1( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj), Abc_ObjFaninC1(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChildCopy( Abc_Obj_t * pObj, int i ){ return Abc_ObjNotCond( Abc_ObjFanin(pObj,i)->pCopy, Abc_ObjFaninC(pObj,i) ); } +static inline Abc_Obj_t * Abc_ObjChild0Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild1Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild0Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin0(pObj)->pData, Abc_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild1Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin1(pObj)->pData, Abc_ObjFaninC1(pObj) ); } +static inline Hop_Obj_t * Abc_ObjChild0Equiv( Abc_Obj_t * pObj ) { return Hop_NotCond( Abc_ObjFanin0(pObj)->pEquiv, Abc_ObjFaninC0(pObj) ); } +static inline Hop_Obj_t * Abc_ObjChild1Equiv( Abc_Obj_t * pObj ) { return Hop_NotCond( Abc_ObjFanin1(pObj)->pEquiv, Abc_ObjFaninC1(pObj) ); } + +// checking the AIG node types +static inline bool Abc_AigNodeIsConst( Abc_Obj_t * pNode ) { assert(Abc_NtkIsStrash(Abc_ObjRegular(pNode)->pNtk)); return Abc_ObjRegular(pNode)->Type == ABC_OBJ_CONST1; } +static inline bool Abc_AigNodeIsAnd( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return Abc_ObjFaninNum(pNode) == 2; } +static inline bool Abc_AigNodeIsChoice( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return pNode->pData != NULL && Abc_ObjFanoutNum(pNode) > 0; } + +// handling persistent nodes +static inline int Abc_NodeIsPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); return pNode->fPersist; } +static inline void Abc_NodeSetPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 1; } +static inline void Abc_NodeClearPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 0; } + +// working with the traversal ID +static inline void Abc_NodeSetTravId( Abc_Obj_t * pNode, int TravId ) { pNode->TravId = TravId; } +static inline void Abc_NodeSetTravIdCurrent( Abc_Obj_t * pNode ) { pNode->TravId = pNode->pNtk->nTravIds; } +static inline void Abc_NodeSetTravIdPrevious( Abc_Obj_t * pNode ) { pNode->TravId = pNode->pNtk->nTravIds - 1; } +static inline bool Abc_NodeIsTravIdCurrent( Abc_Obj_t * pNode ) { return (bool)(pNode->TravId == pNode->pNtk->nTravIds); } +static inline bool Abc_NodeIsTravIdPrevious( Abc_Obj_t * pNode ) { return (bool)(pNode->TravId == pNode->pNtk->nTravIds - 1); } + +// checking initial state of the latches +static inline void Abc_LatchSetInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_NONE; } +static inline void Abc_LatchSetInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ZERO; } +static inline void Abc_LatchSetInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ONE; } +static inline void Abc_LatchSetInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_DC; } +static inline bool Abc_LatchIsInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_NONE; } +static inline bool Abc_LatchIsInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ZERO; } +static inline bool Abc_LatchIsInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ONE; } +static inline bool Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_DC; } +static inline int Abc_LatchInit( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return (int)pLatch->pData; } + +// global BDDs of the nodes +static inline void * Abc_NtkGlobalBdd( Abc_Ntk_t * pNtk ) { return (void *)Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD); } +static inline DdManager * Abc_NtkGlobalBddMan( Abc_Ntk_t * pNtk ) { return (DdManager *)Vec_AttMan( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); } +static inline DdNode ** Abc_NtkGlobalBddArray( Abc_Ntk_t * pNtk ) { return (DdNode **)Vec_AttArray( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); } +static inline DdNode * Abc_ObjGlobalBdd( Abc_Obj_t * pObj ) { return (DdNode *)Vec_AttEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id ); } +static inline void Abc_ObjSetGlobalBdd( Abc_Obj_t * pObj, DdNode * bF ) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id, bF ); } + +// MV variables of the nodes +static inline void * Abc_NtkMvVar( Abc_Ntk_t * pNtk ) { return Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_MVVAR); } +static inline void * Abc_NtkMvVarMan( Abc_Ntk_t * pNtk ) { return Abc_NtkMvVar(pNtk)? Vec_AttMan( (Vec_Att_t *)Abc_NtkMvVar(pNtk) ) : NULL; } +static inline void * Abc_ObjMvVar( Abc_Obj_t * pObj ) { return Abc_NtkMvVar(pObj->pNtk)? Vec_AttEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id ) : NULL; } +static inline int Abc_ObjMvVarNum( Abc_Obj_t * pObj ) { return (Abc_NtkMvVar(pObj->pNtk) && Abc_ObjMvVar(pObj))? *((int*)Abc_ObjMvVar(pObj)) : 2; } +static inline void Abc_ObjSetMvVar( Abc_Obj_t * pObj, void * pV) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id, pV ); } + +// outputs the runtime in seconds +#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// objects of the network +#define Abc_NtkForEachObj( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pObj) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pObj) == NULL ) {} else +#define Abc_NtkForEachNet( pNtk, pNet, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNet) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNet) == NULL || !Abc_ObjIsNet(pNet) ) {} else +#define Abc_NtkForEachNode( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) ) {} else +#define Abc_NtkForEachGate( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_ObjIsGate(pNode) ) {} else +#define Abc_AigForEachAnd( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_AigNodeIsAnd(pNode) ) {} else +// various boxes +#define Abc_NtkForEachBox( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachLatch( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ + if ( !Abc_ObjIsLatch(pObj) ) {} else +#define Abc_NtkForEachLatchInput( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \ + if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanin0(Abc_NtkBox(pNtk, i))), 1)) ) {} else +#define Abc_NtkForEachLatchOutput( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \ + if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanout0(Abc_NtkBox(pNtk, i))), 1)) ) {} else +#define Abc_NtkForEachWhitebox( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ + if ( !Abc_ObjIsWhitebox(pObj) ) {} else +#define Abc_NtkForEachBlackbox( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ + if ( !Abc_ObjIsBlackbox(pObj) ) {} else +// inputs and outputs +#define Abc_NtkForEachPi( pNtk, pPi, i ) \ + for ( i = 0; (i < Abc_NtkPiNum(pNtk)) && (((pPi) = Abc_NtkPi(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachCi( pNtk, pCi, i ) \ + for ( i = 0; (i < Abc_NtkCiNum(pNtk)) && (((pCi) = Abc_NtkCi(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachPo( pNtk, pPo, i ) \ + for ( i = 0; (i < Abc_NtkPoNum(pNtk)) && (((pPo) = Abc_NtkPo(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachCo( pNtk, pCo, i ) \ + for ( i = 0; (i < Abc_NtkCoNum(pNtk)) && (((pCo) = Abc_NtkCo(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachAssert( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vAsserts)) && (((pObj) = Abc_NtkAssert(pNtk, i)), 1); i++ ) +// fanin and fanouts +#define Abc_ObjForEachFanin( pObj, pFanin, i ) \ + for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((pFanin) = Abc_ObjFanin(pObj, i)), 1); i++ ) +#define Abc_ObjForEachFanout( pObj, pFanout, i ) \ + for ( i = 0; (i < Abc_ObjFanoutNum(pObj)) && (((pFanout) = Abc_ObjFanout(pObj, i)), 1); i++ ) +// cubes and literals +#define Abc_SopForEachCube( pSop, nFanins, pCube ) \ + for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) +#define Abc_CubeForEachVar( pCube, Value, i ) \ + for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ ) + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== abcAig.c ==========================================================*/ +extern Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtk ); +extern void Abc_AigFree( Abc_Aig_t * pMan ); +extern int Abc_AigCleanup( Abc_Aig_t * pMan ); +extern bool Abc_AigCheck( Abc_Aig_t * pMan ); +extern int Abc_AigLevel( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType ); +extern Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType ); +extern Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ); +extern void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool fUpdateLevel ); +extern void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld ); +extern void Abc_AigRehash( Abc_Aig_t * pMan ); +extern bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ); +extern bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ); +extern void Abc_AigPrintNode( Abc_Obj_t * pNode ); +extern bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ); +extern void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan ); +extern void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets ); +extern void Abc_AigUpdateStop( Abc_Aig_t * pMan ); +extern void Abc_AigUpdateReset( Abc_Aig_t * pMan ); +/*=== abcAttach.c ==========================================================*/ +extern int Abc_NtkAttach( Abc_Ntk_t * pNtk ); +/*=== abcBlifMv.c ==========================================================*/ +extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ); +extern void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ); +extern void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues ); +extern Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic ); +extern int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk ); +extern char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ); +extern int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ); +/*=== abcBalance.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel ); +/*=== abcCheck.c ==========================================================*/ +extern bool Abc_NtkCheck( Abc_Ntk_t * pNtk ); +extern bool Abc_NtkCheckRead( Abc_Ntk_t * pNtk ); +extern bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ); +extern bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); +extern bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb ); +extern int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ); +extern int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ); +extern int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ); +extern int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ); +/*=== abcCollapse.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ); +/*=== abcCut.c ==========================================================*/ +extern void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); +extern void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); +extern void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fFirst ); +extern void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ); +extern void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ); +/*=== abcDfs.c ==========================================================*/ +extern Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll ); +extern Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ); +extern Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll ); +extern bool Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ); +extern Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi ); +extern int Abc_NtkLevel( Abc_Ntk_t * pNtk ); +extern int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ); +extern bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ); +/*=== abcFanio.c ==========================================================*/ +extern void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); +extern void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); +extern void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ); +extern void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew ); +extern Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ); +extern void Abc_ObjTransferFanout( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); +extern void Abc_ObjReplace( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); +extern int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ); +/*=== abcFraig.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ); +extern void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ); +extern Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk ); +extern int Abc_NtkFraigStore( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkFraigRestore(); +extern void Abc_NtkFraigStoreClean(); +/*=== abcFunc.c ==========================================================*/ +extern int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ); +extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop ); +extern char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode ); +extern int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ); +extern void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ); +extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); +extern void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ); +extern int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ); +extern int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ); +extern unsigned * Abc_ConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst ); +extern int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ); +extern int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fDirect ); +extern int Abc_NtkToBdd( Abc_Ntk_t * pNtk ); +extern int Abc_NtkToAig( Abc_Ntk_t * pNtk ); +/*=== abcHaig.c ==========================================================*/ +extern int Abc_NtkHaigStart( Abc_Ntk_t * pNtk ); +extern int Abc_NtkHaigStop( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkHaigUse( Abc_Ntk_t * pNtk ); +/*=== abcHie.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL ); +/*=== abcLatch.c ==========================================================*/ +extern bool Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ); +extern int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ); +extern int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ); +extern Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk ); +extern void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ); +extern Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init ); +extern void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk ); + /*=== abcLib.c ==========================================================*/ +extern Abc_Lib_t * Abc_LibCreate( char * pName ); +extern void Abc_LibFree( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk ); +extern void Abc_LibPrint( Abc_Lib_t * pLib ); +extern int Abc_LibAddModel( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_LibFindModelByName( Abc_Lib_t * pLib, char * pName ); +extern int Abc_LibFindTopLevelModels( Abc_Lib_t * pLib ); +extern Abc_Ntk_t * Abc_LibDeriveRoot( Abc_Lib_t * pLib ); +/*=== abcMiter.c ==========================================================*/ +extern int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ); +extern int Abc_NodeMinimumBase( Abc_Obj_t * pNode ); +extern int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ); +extern int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ); +/*=== abcMiter.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ); +extern void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pNode ); +extern Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 ); +extern Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ); +extern Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ); +extern Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ); +extern Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ); +extern int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ); +extern void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ); +extern Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial ); +/*=== abcNames.c ====================================================*/ +extern char * Abc_ObjName( Abc_Obj_t * pNode ); +extern char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix ); +extern char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ); +extern char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits ); +extern void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +extern void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +extern Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ); +extern Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ); +extern void Abc_NodeFreeNames( Vec_Ptr_t * vNames ); +extern char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos ); +extern int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); +extern void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ); +extern void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ); +extern void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ); +extern void Abc_NtkAddDummyAssertNames( Abc_Ntk_t * pNtk ); +extern void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ); +extern void Abc_NtkShortNames( Abc_Ntk_t * pNtk ); +/*=== abcNetlist.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ); +/*=== abcNtbdd.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ); +extern Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ); +extern DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fVerbose ); +extern DdManager * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ); +extern int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ); +/*=== abcNtk.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ); +extern Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); +extern Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); +extern void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +extern Abc_Ntk_t * Abc_NtkStartRead( char * pName ); +extern void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ); +extern Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ); +extern Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis ); +extern void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ); +extern Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ); +extern Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ); +extern Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); +extern Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ); +extern void Abc_NtkDelete( Abc_Ntk_t * pNtk ); +extern void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ); +extern void Abc_NtkMakeComb( Abc_Ntk_t * pNtk ); +/*=== abcObj.c ==========================================================*/ +extern Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); +extern void Abc_ObjRecycle( Abc_Obj_t * pObj ); +extern Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); +extern void Abc_NtkDeleteObj( Abc_Obj_t * pObj ); +extern void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes ); +extern void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ); +extern Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName ); +extern Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName ); +extern Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pNode ); +extern Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); +extern Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); +extern Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); +extern Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); +extern Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); +extern Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ); +extern bool Abc_NodeIsConst( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsConst0( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsConst1( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsBuf( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsInv( Abc_Obj_t * pNode ); +extern void Abc_NodeComplement( Abc_Obj_t * pNode ); +/*=== abcPrint.c ==========================================================*/ +extern void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ); +extern void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk ); +extern void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ); +extern void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk ); +extern void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ); +extern void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ); +extern void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ); +extern void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes ); +extern void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ); +extern void Abc_NtkPrintSkews( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintAll ); +extern void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ); +/*=== abcProve.c ==========================================================*/ +extern int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pParams ); +extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ); +/*=== abcRec.c ==========================================================*/ +extern void Abc_NtkRecStart( Abc_Ntk_t * pNtk, int nVars, int nCuts ); +extern void Abc_NtkRecStop(); +extern void Abc_NtkRecAdd( Abc_Ntk_t * pNtk ); +extern void Abc_NtkRecPs(); +extern void Abc_NtkRecFilter( int iVar, int iPlus ); +extern Abc_Ntk_t * Abc_NtkRecUse(); +extern int Abc_NtkRecIsRunning(); +extern int Abc_NtkRecVarNum(); +extern Vec_Int_t * Abc_NtkRecMemory(); +extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ); +/*=== abcReconv.c ==========================================================*/ +extern Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ); +extern void Abc_NtkManCutStop( Abc_ManCut_t * p ); +extern Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p ); +extern Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p ); +extern Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p ); +extern Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain ); +extern void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited, int fIncludeFanins ); +extern DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited ); +extern DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited ); +extern Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, int LevelMax ); +/*=== abcRefs.c ==========================================================*/ +extern int Abc_NodeMffcSize( Abc_Obj_t * pNode ); +extern int Abc_NodeMffcSizeSupp( Abc_Obj_t * pNode ); +extern int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ); +extern int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ); +extern int Abc_NodeMffcLabel( Abc_Obj_t * pNode ); +extern void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ); +extern int Abc_NodeDeref_rec( Abc_Obj_t * pNode ); +extern int Abc_NodeRef_rec( Abc_Obj_t * pNode ); +/*=== abcRefactor.c ==========================================================*/ +extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); +/*=== abcRewrite.c ==========================================================*/ +extern int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ); +/*=== abcSat.c ==========================================================*/ +extern int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects ); +extern void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes ); +/*=== abcSop.c ==========================================================*/ +extern char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName ); +extern char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars ); +extern char * Abc_SopCreateConst0( Extra_MmFlex_t * pMan ); +extern char * Abc_SopCreateConst1( Extra_MmFlex_t * pMan ); +extern char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 ); +extern char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ); +extern char * Abc_SopCreateNand( Extra_MmFlex_t * pMan, int nVars ); +extern char * Abc_SopCreateOr( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ); +extern char * Abc_SopCreateOrMultiCube( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ); +extern char * Abc_SopCreateNor( Extra_MmFlex_t * pMan, int nVars ); +extern char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars ); +extern char * Abc_SopCreateXorSpecial( Extra_MmFlex_t * pMan, int nVars ); +extern char * Abc_SopCreateNxor( Extra_MmFlex_t * pMan, int nVars ); +extern char * Abc_SopCreateMux( Extra_MmFlex_t * pMan ); +extern char * Abc_SopCreateInv( Extra_MmFlex_t * pMan ); +extern char * Abc_SopCreateBuf( Extra_MmFlex_t * pMan ); +extern char * Abc_SopCreateFromTruth( Extra_MmFlex_t * pMan, int nVars, unsigned * pTruth ); +extern char * Abc_SopCreateFromIsop( Extra_MmFlex_t * pMan, int nVars, Vec_Int_t * vCover ); +extern int Abc_SopGetCubeNum( char * pSop ); +extern int Abc_SopGetLitNum( char * pSop ); +extern int Abc_SopGetVarNum( char * pSop ); +extern int Abc_SopGetPhase( char * pSop ); +extern int Abc_SopGetIthCareLit( char * pSop, int i ); +extern void Abc_SopComplement( char * pSop ); +extern bool Abc_SopIsComplement( char * pSop ); +extern bool Abc_SopIsConst0( char * pSop ); +extern bool Abc_SopIsConst1( char * pSop ); +extern bool Abc_SopIsBuf( char * pSop ); +extern bool Abc_SopIsInv( char * pSop ); +extern bool Abc_SopIsAndType( char * pSop ); +extern bool Abc_SopIsOrType( char * pSop ); +extern int Abc_SopIsExorType( char * pSop ); +extern bool Abc_SopCheck( char * pSop, int nFanins ); +extern char * Abc_SopFromTruthBin( char * pTruth ); +extern char * Abc_SopFromTruthHex( char * pTruth ); +extern char * Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues ); +extern char * Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues ); +extern char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues ); +extern char * Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues ); +/*=== abcStrash.c ==========================================================*/ +extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord ); +extern Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int fRecord ); +extern int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ); +extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); +/*=== abcSweep.c ==========================================================*/ +extern int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ); +extern int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ); +extern int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose ); +/*=== abcTiming.c ==========================================================*/ +extern Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ); +extern Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ); +extern Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk ); +extern Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ); +extern void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ); +extern void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ); +extern void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ); +extern void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ); +extern void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk ); +extern void Abc_ManTimeStop( Abc_ManTime_t * p ); +extern void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ); +extern void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtk ); +extern float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk ); +extern Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk ); +extern float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk ); +extern int Abc_ObjLevelNew( Abc_Obj_t * pObj ); +extern int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ); +extern int Abc_ObjRequiredLevel( Abc_Obj_t * pObj ); +extern int Abc_ObjReverseLevel( Abc_Obj_t * pObj ); +extern void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR ); +extern void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease ); +extern void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ); +extern void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); +extern void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); +extern void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); +/*=== abcUtil.c ==========================================================*/ +extern void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ); +extern void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk ); +extern void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk ); +extern double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ); +extern int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk ); +extern void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ); +extern void Abc_NtkCleanData( Abc_Ntk_t * pNtk ); +extern void Abc_NtkCleanEquiv( Abc_Ntk_t * pNtk ); +extern int Abc_NtkCountCopy( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ); +extern void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ); +extern void Abc_NtkCleanNext( Abc_Ntk_t * pNtk ); +extern void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode ); +extern Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode ); +extern Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ); +extern bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ); +extern int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDuplicate ); +extern void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ); +extern bool Abc_NodeIsExorType( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsMuxType( Abc_Obj_t * pNode ); +extern bool Abc_NodeIsMuxControlType( Abc_Obj_t * pNode ); +extern Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ); +extern int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2 ); +extern void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); +extern void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); +extern Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk ); +extern int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); +extern int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); +extern Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ); +extern Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk ); +extern void Abc_NtkReassignIds( Abc_Ntk_t * pNtk ); +extern int Abc_ObjPointerCompare( void ** pp1, void ** pp2 ); +extern void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ); +/*=== abcVerify.c ==========================================================*/ +extern int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames ); +extern int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/abc/abcAig.c b/abc70930/src/base/abc/abcAig.c new file mode 100644 index 00000000..16f66dc6 --- /dev/null +++ b/abc70930/src/base/abc/abcAig.c @@ -0,0 +1,1476 @@ +/**CFile**************************************************************** + + FileName [abcAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Simple structural hashing package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +/* + AIG is an And-Inv Graph with structural hashing. + It is always structurally hashed. It means that at any time: + - for each AND gate, there are no other AND gates with the same children + - the constants are propagated + - there is no single-input nodes (inverters/buffers) + Additionally the following invariants are satisfied: + - there are no dangling nodes (the nodes without fanout) + - the level of each AND gate reflects the levels of this fanins + - the EXOR-status of each node is up-to-date + - the AND nodes are in the topological order + - the constant 1 node has always number 0 in the object list + The operations that are performed on AIGs: + - building new nodes (Abc_AigAnd) + - performing elementary Boolean operations (Abc_AigOr, Abc_AigXor, etc) + - replacing one node by another (Abc_AigReplace) + - propagating constants (Abc_AigReplace) + When AIG is duplicated, the new graph is structurally hashed too. + If this repeated hashing leads to fewer nodes, it means the original + AIG was not strictly hashed (one of the conditions above is violated). +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the simple AIG manager +struct Abc_Aig_t_ +{ + Abc_Ntk_t * pNtkAig; // the AIG network + Abc_Obj_t * pConst1; // the constant 1 object (not a node!) + Abc_Obj_t ** pBins; // the table bins + int nBins; // the size of the table + int nEntries; // the total number of entries in the table + Vec_Ptr_t * vNodes; // the temporary array of nodes + Vec_Ptr_t * vStackReplaceOld; // the nodes to be replaced + Vec_Ptr_t * vStackReplaceNew; // the nodes to be used for replacement + Vec_Vec_t * vLevels; // the nodes to be updated + Vec_Vec_t * vLevelsR; // the nodes to be updated + Vec_Ptr_t * vAddedCells; // the added nodes + Vec_Ptr_t * vUpdatedNets; // the nodes whose fanouts have changed + + int nStrash0; + int nStrash1; + int nStrash5; + int nStrash2; +}; + +// iterators through the entries in the linked lists of nodes +#define Abc_AigBinForEachEntry( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = pEnt->pNext ) +#define Abc_AigBinForEachEntrySafe( pBin, pEnt, pEnt2 ) \ + for ( pEnt = pBin, \ + pEnt2 = pEnt? pEnt->pNext: NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? pEnt->pNext: NULL ) + +// hash key for the structural hash table +//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; } +//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)((a)->Id + (b)->Id) * ((a)->Id + (b)->Id + 1) / 2) % TableSize; } + +// hashing the node +static unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) +{ + unsigned Key = 0; + Key ^= Abc_ObjRegular(p0)->Id * 7937; + Key ^= Abc_ObjRegular(p1)->Id * 2971; + Key ^= Abc_ObjIsComplement(p0) * 911; + Key ^= Abc_ObjIsComplement(p1) * 353; + return Key % TableSize; +} + +// structural hash table procedures +static Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +static Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd ); +static void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis ); +static void Abc_AigResize( Abc_Aig_t * pMan ); +// incremental AIG procedures +static void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ); +static void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ); +static void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ); +static void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ); +static void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the local AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig ) +{ + Abc_Aig_t * pMan; + // start the manager + pMan = ALLOC( Abc_Aig_t, 1 ); + memset( pMan, 0, sizeof(Abc_Aig_t) ); + // allocate the table + pMan->nBins = Cudd_PrimeCopy( 10000 ); + pMan->pBins = ALLOC( Abc_Obj_t *, pMan->nBins ); + memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); + pMan->vNodes = Vec_PtrAlloc( 100 ); + pMan->vLevels = Vec_VecAlloc( 100 ); + pMan->vLevelsR = Vec_VecAlloc( 100 ); + pMan->vStackReplaceOld = Vec_PtrAlloc( 100 ); + pMan->vStackReplaceNew = Vec_PtrAlloc( 100 ); + // create the constant node + assert( pNtkAig->vObjs->nSize == 0 ); + pMan->pConst1 = Abc_NtkCreateObj( pNtkAig, ABC_OBJ_NODE ); + pMan->pConst1->Type = ABC_OBJ_CONST1; + pMan->pConst1->fPhase = 1; + pNtkAig->nObjCounts[ABC_OBJ_NODE]--; + // save the current network + pMan->pNtkAig = pNtkAig; + return pMan; +} + +/**Function************************************************************* + + Synopsis [Deallocates the local AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigFree( Abc_Aig_t * pMan ) +{ + assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 ); + assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 ); + // free the table + if ( pMan->vAddedCells ) + Vec_PtrFree( pMan->vAddedCells ); + if ( pMan->vUpdatedNets ) + Vec_PtrFree( pMan->vUpdatedNets ); + Vec_VecFree( pMan->vLevels ); + Vec_VecFree( pMan->vLevelsR ); + Vec_PtrFree( pMan->vStackReplaceOld ); + Vec_PtrFree( pMan->vStackReplaceNew ); + Vec_PtrFree( pMan->vNodes ); + free( pMan->pBins ); + free( pMan ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigCleanup( Abc_Aig_t * pMan ) +{ + Vec_Ptr_t * vDangles; + Abc_Obj_t * pAnd; + int i, nNodesOld; +// printf( "Strash0 = %d. Strash1 = %d. Strash100 = %d. StrashM = %d.\n", +// pMan->nStrash0, pMan->nStrash1, pMan->nStrash5, pMan->nStrash2 ); + nNodesOld = pMan->nEntries; + // collect the AND nodes that do not fanout + vDangles = Vec_PtrAlloc( 100 ); + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) + if ( Abc_ObjFanoutNum(pAnd) == 0 ) + Vec_PtrPush( vDangles, pAnd ); + // process the dangling nodes and their MFFCs + Vec_PtrForEachEntry( vDangles, pAnd, i ) + Abc_AigDeleteNode( pMan, pAnd ); + Vec_PtrFree( vDangles ); + return nNodesOld - pMan->nEntries; +} + +/**Function************************************************************* + + Synopsis [Makes sure that every node in the table is in the network and vice versa.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_AigCheck( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pObj, * pAnd; + int i, nFanins, Counter; + Abc_NtkForEachNode( pMan->pNtkAig, pObj, i ) + { + nFanins = Abc_ObjFaninNum(pObj); + if ( nFanins == 0 ) + { + if ( !Abc_AigNodeIsConst(pObj) ) + { + printf( "Abc_AigCheck: The AIG has non-standard constant nodes.\n" ); + return 0; + } + continue; + } + if ( nFanins == 1 ) + { + printf( "Abc_AigCheck: The AIG has single input nodes.\n" ); + return 0; + } + if ( nFanins > 2 ) + { + printf( "Abc_AigCheck: The AIG has non-standard nodes.\n" ); + return 0; + } + if ( pObj->Level != 1 + ABC_MAX( Abc_ObjFanin0(pObj)->Level, Abc_ObjFanin1(pObj)->Level ) ) + printf( "Abc_AigCheck: Node \"%s\" has level that does not agree with the fanin levels.\n", Abc_ObjName(pObj) ); + pAnd = Abc_AigAndLookup( pMan, Abc_ObjChild0(pObj), Abc_ObjChild1(pObj) ); + if ( pAnd != pObj ) + printf( "Abc_AigCheck: Node \"%s\" is not in the structural hashing table.\n", Abc_ObjName(pObj) ); + } + // count the number of nodes in the table + Counter = 0; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) + Counter++; + if ( Counter != Abc_NtkNodeNum(pMan->pNtkAig) ) + { + printf( "Abc_AigCheck: The number of nodes in the structural hashing table is wrong.\n" ); + return 0; + } + // if the node is a choice node, nodes in its class should not have fanouts + Abc_NtkForEachNode( pMan->pNtkAig, pObj, i ) + if ( Abc_AigNodeIsChoice(pObj) ) + for ( pAnd = pObj->pData; pAnd; pAnd = pAnd->pData ) + if ( Abc_ObjFanoutNum(pAnd) > 0 ) + { + printf( "Abc_AigCheck: Representative %s", Abc_ObjName(pAnd) ); + printf( " of choice node %s has %d fanouts.\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pAnd) ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigLevel( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, LevelsMax; + assert( Abc_NtkIsStrash(pNtk) ); + // perform the traversal + LevelsMax = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + if ( LevelsMax < (int)Abc_ObjFanin0(pNode)->Level ) + LevelsMax = (int)Abc_ObjFanin0(pNode)->Level; + return LevelsMax; +} + + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + Abc_Obj_t * pAnd; + unsigned Key; + // check if it is a good time for table resizing + if ( pMan->nEntries > 2 * pMan->nBins ) + Abc_AigResize( pMan ); + // order the arguments + if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) + pAnd = p0, p0 = p1, p1 = pAnd; + // create the new node + pAnd = Abc_NtkCreateNode( pMan->pNtkAig ); + Abc_ObjAddFanin( pAnd, p0 ); + Abc_ObjAddFanin( pAnd, p1 ); + // set the level of the new node + pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); + pAnd->fExor = Abc_NodeIsExorType(pAnd); + pAnd->fPhase = (Abc_ObjIsComplement(p0) ^ Abc_ObjRegular(p0)->fPhase) & (Abc_ObjIsComplement(p1) ^ Abc_ObjRegular(p1)->fPhase); + // add the node to the corresponding linked list in the table + Key = Abc_HashKey2( p0, p1, pMan->nBins ); + pAnd->pNext = pMan->pBins[Key]; + pMan->pBins[Key] = pAnd; + pMan->nEntries++; + // create the cuts if defined +// if ( pAnd->pNtk->pManCut ) +// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd ); + pAnd->pCopy = NULL; + // add the node to the list of updated nodes + if ( pMan->vAddedCells ) + Vec_PtrPush( pMan->vAddedCells, pAnd ); + // create HAIG + if ( pAnd->pNtk->pHaig ) + pAnd->pEquiv = Hop_And( pAnd->pNtk->pHaig, Abc_ObjChild0Equiv(pAnd), Abc_ObjChild1Equiv(pAnd) ); + return pAnd; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd ) +{ + Abc_Obj_t * pTemp; + unsigned Key; + assert( !Abc_ObjIsComplement(pAnd) ); + // order the arguments + if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) + pTemp = p0, p0 = p1, p1 = pTemp; + // create the new node + Abc_ObjAddFanin( pAnd, p0 ); + Abc_ObjAddFanin( pAnd, p1 ); + // set the level of the new node + pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); + pAnd->fExor = Abc_NodeIsExorType(pAnd); + // add the node to the corresponding linked list in the table + Key = Abc_HashKey2( p0, p1, pMan->nBins ); + pAnd->pNext = pMan->pBins[Key]; + pMan->pBins[Key] = pAnd; + pMan->nEntries++; + // create the cuts if defined +// if ( pAnd->pNtk->pManCut ) +// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd ); + pAnd->pCopy = NULL; + // add the node to the list of updated nodes +// if ( pMan->vAddedCells ) +// Vec_PtrPush( pMan->vAddedCells, pAnd ); + // create HAIG + if ( pAnd->pNtk->pHaig ) + pAnd->pEquiv = Hop_And( pAnd->pNtk->pHaig, Abc_ObjChild0Equiv(pAnd), Abc_ObjChild1Equiv(pAnd) ); + return pAnd; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + Abc_Obj_t * pAnd, * pConst1; + unsigned Key; + assert( Abc_ObjRegular(p0)->pNtk->pManFunc == pMan ); + assert( Abc_ObjRegular(p1)->pNtk->pManFunc == pMan ); + // check for trivial cases + pConst1 = Abc_AigConst1(pMan->pNtkAig); + if ( p0 == p1 ) + return p0; + if ( p0 == Abc_ObjNot(p1) ) + return Abc_ObjNot(pConst1); + if ( Abc_ObjRegular(p0) == pConst1 ) + { + if ( p0 == pConst1 ) + return p1; + return Abc_ObjNot(pConst1); + } + if ( Abc_ObjRegular(p1) == pConst1 ) + { + if ( p1 == pConst1 ) + return p0; + return Abc_ObjNot(pConst1); + } +/* + { + int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) ); + int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) ); + if ( nFans0 == 0 || nFans1 == 0 ) + pMan->nStrash0++; + else if ( nFans0 == 1 || nFans1 == 1 ) + pMan->nStrash1++; + else if ( nFans0 <= 100 && nFans1 <= 100 ) + pMan->nStrash5++; + else + pMan->nStrash2++; + } +*/ + { + int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) ); + int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) ); + if ( nFans0 == 0 || nFans1 == 0 ) + return NULL; + } + + // order the arguments + if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) + pAnd = p0, p0 = p1, p1 = pAnd; + // get the hash key for these two nodes + Key = Abc_HashKey2( p0, p1, pMan->nBins ); + // find the matching node in the table + Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd ) + if ( p0 == Abc_ObjChild0(pAnd) && p1 == Abc_ObjChild1(pAnd) ) + { +// assert( Abc_ObjFanoutNum(Abc_ObjRegular(p0)) && Abc_ObjFanoutNum(p1) ); + return pAnd; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType ) +{ + Abc_Obj_t * pNode1, * pNode2, * pNode; + // set the flag to zero + if ( pType ) *pType = 0; + // check the case of XOR(a,b) = OR(ab, a'b')' + if ( (pNode1 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), Abc_ObjNot(p1))) && + (pNode2 = Abc_AigAndLookup(pMan, p0, p1)) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + if ( pNode && pType ) *pType = 1; + return pNode; + } + // check the case of XOR(a,b) = OR(a'b, ab') + if ( (pNode1 = Abc_AigAndLookup(pMan, p0, Abc_ObjNot(p1))) && + (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), p1)) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + return pNode? Abc_ObjNot(pNode) : NULL; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType ) +{ + Abc_Obj_t * pNode1, * pNode2, * pNode; + // set the flag to zero + if ( pType ) *pType = 0; + // check the case of MUX(c,t,e) = OR(ct', c'e')' + if ( (pNode1 = Abc_AigAndLookup(pMan, pC, Abc_ObjNot(pT))) && + (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), Abc_ObjNot(pE))) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + if ( pNode && pType ) *pType = 1; + return pNode; + } + // check the case of MUX(c,t,e) = OR(ct, c'e) + if ( (pNode1 = Abc_AigAndLookup(pMan, pC, pT)) && + (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), pE)) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + return pNode? Abc_ObjNot(pNode) : NULL; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Deletes an AIG node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis ) +{ + Abc_Obj_t * pAnd, * pAnd0, * pAnd1, ** ppPlace; + unsigned Key; + assert( !Abc_ObjIsComplement(pThis) ); + assert( Abc_ObjIsNode(pThis) ); + assert( Abc_ObjFaninNum(pThis) == 2 ); + assert( pMan->pNtkAig == pThis->pNtk ); + // get the hash key for these two nodes + pAnd0 = Abc_ObjRegular( Abc_ObjChild0(pThis) ); + pAnd1 = Abc_ObjRegular( Abc_ObjChild1(pThis) ); + Key = Abc_HashKey2( Abc_ObjChild0(pThis), Abc_ObjChild1(pThis), pMan->nBins ); + // find the matching node in the table + ppPlace = pMan->pBins + Key; + Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd ) + { + if ( pAnd != pThis ) + { + ppPlace = &pAnd->pNext; + continue; + } + *ppPlace = pAnd->pNext; + break; + } + assert( pAnd == pThis ); + pMan->nEntries--; + // delete the cuts if defined + if ( pThis->pNtk->pManCut ) + Abc_NodeFreeCuts( pThis->pNtk->pManCut, pThis ); +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigResize( Abc_Aig_t * pMan ) +{ + Abc_Obj_t ** pBinsNew; + Abc_Obj_t * pEnt, * pEnt2; + int nBinsNew, Counter, i, clk; + unsigned Key; + +clk = clock(); + // get the new table size + nBinsNew = Cudd_PrimeCopy( 3 * pMan->nBins ); + // allocate a new array + pBinsNew = ALLOC( Abc_Obj_t *, nBinsNew ); + memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 ) + { + Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), nBinsNew ); + pEnt->pNext = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == pMan->nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", pMan->nBins, nBinsNew ); +// PRT( "Time", clock() - clk ); + // replace the table and the parameters + free( pMan->pBins ); + pMan->pBins = pBinsNew; + pMan->nBins = nBinsNew; +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigRehash( Abc_Aig_t * pMan ) +{ + Abc_Obj_t ** pBinsNew; + Abc_Obj_t * pEnt, * pEnt2; + int * pArray; + unsigned Key; + int Counter, Temp, i; + + // allocate a new array + pBinsNew = ALLOC( Abc_Obj_t *, pMan->nBins ); + memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 ) + { + // swap the fanins if needed + pArray = pEnt->vFanins.pArray; + if ( pArray[0] > pArray[1] ) + { + Temp = pArray[0]; + pArray[0] = pArray[1]; + pArray[1] = Temp; + Temp = pEnt->fCompl0; + pEnt->fCompl0 = pEnt->fCompl1; + pEnt->fCompl1 = Temp; + } + // rehash the node + Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), pMan->nBins ); + pEnt->pNext = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == pMan->nEntries ); + // replace the table and the parameters + free( pMan->pBins ); + pMan->pBins = pBinsNew; +} + + + + + + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ) +{ + assert( Abc_NtkIsStrash(pNtk) ); + return ((Abc_Aig_t *)pNtk->pManFunc)->pConst1; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + Abc_Obj_t * pAnd; + if ( (pAnd = Abc_AigAndLookup( pMan, p0, p1 )) ) + return pAnd; + return Abc_AigAndCreate( pMan, p0, p1 ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + return Abc_ObjNot( Abc_AigAnd( pMan, Abc_ObjNot(p0), Abc_ObjNot(p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + return Abc_AigOr( pMan, Abc_AigAnd(pMan, p0, Abc_ObjNot(p1)), + Abc_AigAnd(pMan, p1, Abc_ObjNot(p0)) ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMiter_rec( Abc_Aig_t * pMan, Abc_Obj_t ** ppObjs, int nObjs ) +{ + Abc_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Abc_AigMiter_rec( pMan, ppObjs, nObjs/2 ); + pObj2 = Abc_AigMiter_rec( pMan, ppObjs + nObjs/2, nObjs - nObjs/2 ); + return Abc_AigOr( pMan, pObj1, pObj2 ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ) +{ + int i; + if ( vPairs->nSize == 0 ) + return Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) ); + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Abc_AigXor( pMan, vPairs->pArray[i], vPairs->pArray[i+1] ); + vPairs->nSize = vPairs->nSize/2; + return Abc_AigMiter_rec( pMan, (Abc_Obj_t **)vPairs->pArray, vPairs->nSize ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMiter2( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ) +{ + Abc_Obj_t * pMiter, * pXor; + int i; + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + pMiter = Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) ); + for ( i = 0; i < vPairs->nSize; i += 2 ) + { + pXor = Abc_AigXor( pMan, vPairs->pArray[i], vPairs->pArray[i+1] ); + pMiter = Abc_AigOr( pMan, pMiter, pXor ); + } + return pMiter; +} + + + + +/**Function************************************************************* + + Synopsis [Replaces one AIG node by the other.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool fUpdateLevel ) +{ + assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 ); + assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 ); + Vec_PtrPush( pMan->vStackReplaceOld, pOld ); + Vec_PtrPush( pMan->vStackReplaceNew, pNew ); + assert( !Abc_ObjIsComplement(pOld) ); + // create HAIG + if ( pOld->pNtk->pHaig ) + Hop_ObjCreateChoice( pOld->pEquiv, Abc_ObjRegular(pNew)->pEquiv ); + // process the replacements + while ( Vec_PtrSize(pMan->vStackReplaceOld) ) + { + pOld = Vec_PtrPop( pMan->vStackReplaceOld ); + pNew = Vec_PtrPop( pMan->vStackReplaceNew ); + Abc_AigReplace_int( pMan, pOld, pNew, fUpdateLevel ); + } + if ( fUpdateLevel ) + { + Abc_AigUpdateLevel_int( pMan ); + if ( pMan->pNtkAig->vLevelsR ) + Abc_AigUpdateLevelR_int( pMan ); + } +} + +/**Function************************************************************* + + Synopsis [Performs internal replacement step.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ) +{ + Abc_Obj_t * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout; + int k, v, iFanin; + // make sure the old node is regular and has fanouts + // (the new node can be complemented and can have fanouts) + assert( !Abc_ObjIsComplement(pOld) ); + assert( Abc_ObjFanoutNum(pOld) > 0 ); + // look at the fanouts of old node + Abc_NodeCollectFanouts( pOld, pMan->vNodes ); + Vec_PtrForEachEntry( pMan->vNodes, pFanout, k ) + { + if ( Abc_ObjIsCo(pFanout) ) + { + Abc_ObjPatchFanin( pFanout, pOld, pNew ); + continue; + } + // find the old node as a fanin of this fanout + iFanin = Vec_IntFind( &pFanout->vFanins, pOld->Id ); + assert( iFanin == 0 || iFanin == 1 ); + // get the new fanin + pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) ); + assert( Abc_ObjRegular(pFanin1) != pFanout ); + // get another fanin + pFanin2 = Abc_ObjChild( pFanout, iFanin ^ 1 ); + assert( Abc_ObjRegular(pFanin2) != pFanout ); + // check if the node with these fanins exists + if ( (pFanoutNew = Abc_AigAndLookup( pMan, pFanin1, pFanin2 )) ) + { // such node exists (it may be a constant) + // schedule replacement of the old fanout by the new fanout + Vec_PtrPush( pMan->vStackReplaceOld, pFanout ); + Vec_PtrPush( pMan->vStackReplaceNew, pFanoutNew ); + continue; + } + // such node does not exist - modify the old fanout node + // (this way the change will not propagate all the way to the COs) + assert( Abc_ObjRegular(pFanin1) != Abc_ObjRegular(pFanin2) ); + + // if the node is in the level structure, remove it + if ( pFanout->fMarkA ) + Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout ); + // if the node is in the level structure, remove it + if ( pFanout->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanout ); + + // remove the old fanout node from the structural hashing table + Abc_AigAndDelete( pMan, pFanout ); + // remove the fanins of the old fanout + Abc_ObjRemoveFanins( pFanout ); + // recreate the old fanout with new fanins and add it to the table + Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout ); + assert( Abc_AigNodeIsAcyclic(pFanout, pFanout) ); + + if ( fUpdateLevel ) + { + // schedule the updated fanout for updating direct level + assert( pFanout->fMarkA == 0 ); + pFanout->fMarkA = 1; + Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout ); + // schedule the updated fanout for updating reverse level + if ( pMan->pNtkAig->vLevelsR ) + { + assert( pFanout->fMarkB == 0 ); + pFanout->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, Abc_ObjReverseLevel(pFanout), pFanout ); + } + } + + // the fanout has changed, update EXOR status of its fanouts + Abc_ObjForEachFanout( pFanout, pFanoutFanout, v ) + if ( Abc_AigNodeIsAnd(pFanoutFanout) ) + pFanoutFanout->fExor = Abc_NodeIsExorType(pFanoutFanout); + } + // if the node has no fanouts left, remove its MFFC + if ( Abc_ObjFanoutNum(pOld) == 0 ) + Abc_AigDeleteNode( pMan, pOld ); +} + +/**Function************************************************************* + + Synopsis [Performs internal deletion step.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1, * pTemp; + int i, k; + + // make sure the node is regular and dangling + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + assert( Abc_ObjFaninNum(pNode) == 2 ); + assert( Abc_ObjFanoutNum(pNode) == 0 ); + + // when deleting an old node that is scheduled for replacement, remove it from the replacement queue + Vec_PtrForEachEntry( pMan->vStackReplaceOld, pTemp, i ) + if ( pNode == pTemp ) + { + // remove the entry from the replacement array + for ( k = i; k < pMan->vStackReplaceOld->nSize - 1; k++ ) + { + pMan->vStackReplaceOld->pArray[k] = pMan->vStackReplaceOld->pArray[k+1]; + pMan->vStackReplaceNew->pArray[k] = pMan->vStackReplaceNew->pArray[k+1]; + } + pMan->vStackReplaceOld->nSize--; + pMan->vStackReplaceNew->nSize--; + } + + // when deleting a new node that should replace another node, do not delete + Vec_PtrForEachEntry( pMan->vStackReplaceNew, pTemp, i ) + if ( pNode == Abc_ObjRegular(pTemp) ) + return; + + // remember the node's fanins + pNode0 = Abc_ObjFanin0( pNode ); + pNode1 = Abc_ObjFanin1( pNode ); + + // add the node to the list of updated nodes + if ( pMan->vUpdatedNets ) + { + Vec_PtrPushUnique( pMan->vUpdatedNets, pNode0 ); + Vec_PtrPushUnique( pMan->vUpdatedNets, pNode1 ); + } + + // remove the node from the table + Abc_AigAndDelete( pMan, pNode ); + // if the node is in the level structure, remove it + if ( pNode->fMarkA ) + Abc_AigRemoveFromLevelStructure( pMan->vLevels, pNode ); + if ( pNode->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pNode ); + // remove the node from the network + Abc_NtkDeleteObj( pNode ); + + // call recursively for the fanins + if ( Abc_ObjIsNode(pNode0) && pNode0->vFanouts.nSize == 0 ) + Abc_AigDeleteNode( pMan, pNode0 ); + if ( Abc_ObjIsNode(pNode1) && pNode1->vFanouts.nSize == 0 ) + Abc_AigDeleteNode( pMan, pNode1 ); +} + + +/**Function************************************************************* + + Synopsis [Updates the level of the node after it has changed.] + + Description [This procedure is based on the observation that + after the node's level has changed, the fanouts levels can change too, + but the new fanout levels are always larger than the node's level. + As a result, we can accumulate the nodes to be updated in the queue + and process them in the increasing order of levels.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pNode, * pFanout; + Vec_Ptr_t * vVec; + int LevelNew, i, k, v; + + // go through the nodes and update the level of their fanouts + Vec_VecForEachLevel( pMan->vLevels, vVec, i ) + { + if ( Vec_PtrSize(vVec) == 0 ) + continue; + Vec_PtrForEachEntry( vVec, pNode, k ) + { + if ( pNode == NULL ) + continue; + assert( Abc_ObjIsNode(pNode) ); + assert( (int)pNode->Level == i ); + // clean the mark + assert( pNode->fMarkA == 1 ); + pNode->fMarkA = 0; + // iterate through the fanouts + Abc_ObjForEachFanout( pNode, pFanout, v ) + { + if ( Abc_ObjIsCo(pFanout) ) + continue; + // get the new level of this fanout + LevelNew = 1 + ABC_MAX( Abc_ObjFanin0(pFanout)->Level, Abc_ObjFanin1(pFanout)->Level ); + assert( LevelNew > i ); + if ( (int)pFanout->Level == LevelNew ) // no change + continue; + // if the fanout is present in the data structure, pull it out + if ( pFanout->fMarkA ) + Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout ); + // update the fanout level + pFanout->Level = LevelNew; + // add the fanout to the data structure to update its fanouts + assert( pFanout->fMarkA == 0 ); + pFanout->fMarkA = 1; + Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout ); + } + } + Vec_PtrClear( vVec ); + } +} + +/**Function************************************************************* + + Synopsis [Updates the level of the node after it has changed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pNode, * pFanin, * pFanout; + Vec_Ptr_t * vVec; + int LevelNew, i, k, v, j; + + // go through the nodes and update the level of their fanouts + Vec_VecForEachLevel( pMan->vLevelsR, vVec, i ) + { + if ( Vec_PtrSize(vVec) == 0 ) + continue; + Vec_PtrForEachEntry( vVec, pNode, k ) + { + if ( pNode == NULL ) + continue; + assert( Abc_ObjIsNode(pNode) ); + assert( Abc_ObjReverseLevel(pNode) == i ); + // clean the mark + assert( pNode->fMarkB == 1 ); + pNode->fMarkB = 0; + // iterate through the fanins + Abc_ObjForEachFanin( pNode, pFanin, v ) + { + if ( Abc_ObjIsCi(pFanin) ) + continue; + // get the new reverse level of this fanin + LevelNew = 0; + Abc_ObjForEachFanout( pFanin, pFanout, j ) + if ( LevelNew < Abc_ObjReverseLevel(pFanout) ) + LevelNew = Abc_ObjReverseLevel(pFanout); + LevelNew += 1; + assert( LevelNew > i ); + if ( Abc_ObjReverseLevel(pFanin) == LevelNew ) // no change + continue; + // if the fanin is present in the data structure, pull it out + if ( pFanin->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanin ); + // update the reverse level + Abc_ObjSetReverseLevel( pFanin, LevelNew ); + // add the fanin to the data structure to update its fanins + assert( pFanin->fMarkB == 0 ); + pFanin->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, LevelNew, pFanin ); + } + } + Vec_PtrClear( vVec ); + } +} + +/**Function************************************************************* + + Synopsis [Removes the node from the level structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vVecTemp; + Abc_Obj_t * pTemp; + int m; + assert( pNode->fMarkA ); + vVecTemp = Vec_VecEntry( vStruct, pNode->Level ); + Vec_PtrForEachEntry( vVecTemp, pTemp, m ) + { + if ( pTemp != pNode ) + continue; + Vec_PtrWriteEntry( vVecTemp, m, NULL ); + break; + } + assert( m < Vec_PtrSize(vVecTemp) ); // found + pNode->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Removes the node from the level structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vVecTemp; + Abc_Obj_t * pTemp; + int m; + assert( pNode->fMarkB ); + vVecTemp = Vec_VecEntry( vStruct, Abc_ObjReverseLevel(pNode) ); + Vec_PtrForEachEntry( vVecTemp, pTemp, m ) + { + if ( pTemp != pNode ) + continue; + Vec_PtrWriteEntry( vVecTemp, m, NULL ); + break; + } + assert( m < Vec_PtrSize(vVecTemp) ); // found + pNode->fMarkB = 0; +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the node has at least one complemented fanout.] + + Description [A fanout is complemented if the fanout's fanin edge pointing + to the given node is complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i, iFanin; + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); + assert( iFanin >= 0 ); + if ( Abc_ObjFaninC( pFanout, iFanin ) ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node has at least one complemented fanout.] + + Description [A fanout is complemented if the fanout's fanin edge pointing + to the given node is complemented. Only the fanouts with current TravId + are counted.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i, iFanin; + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + if ( !Abc_NodeIsTravIdCurrent(pFanout) ) + continue; + iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); + assert( iFanin >= 0 ); + if ( Abc_ObjFaninC( pFanout, iFanin ) ) + return 1; + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [Prints the AIG node for debugging purposes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigPrintNode( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNodeR = Abc_ObjRegular(pNode); + if ( Abc_ObjIsCi(pNodeR) ) + { + printf( "CI %4s%s.\n", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" ); + return; + } + if ( Abc_AigNodeIsConst(pNodeR) ) + { + printf( "Constant 1 %s.\n", Abc_ObjIsComplement(pNode)? "(complemented)" : "" ); + return; + } + // print the node's function + printf( "%7s%s", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" ); + printf( " = " ); + printf( "%7s%s", Abc_ObjName(Abc_ObjFanin0(pNodeR)), Abc_ObjFaninC0(pNodeR)? "\'" : "" ); + printf( " * " ); + printf( "%7s%s", Abc_ObjName(Abc_ObjFanin1(pNodeR)), Abc_ObjFaninC1(pNodeR)? "\'" : "" ); + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Check if the node has a combination loop of depth 1 or 2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ) +{ + Abc_Obj_t * pFanin0, * pFanin1; + Abc_Obj_t * pChild00, * pChild01; + Abc_Obj_t * pChild10, * pChild11; + if ( !Abc_AigNodeIsAnd(pNode) ) + return 1; + pFanin0 = Abc_ObjFanin0(pNode); + pFanin1 = Abc_ObjFanin1(pNode); + if ( pRoot == pFanin0 || pRoot == pFanin1 ) + return 0; + if ( Abc_ObjIsCi(pFanin0) ) + { + pChild00 = NULL; + pChild01 = NULL; + } + else + { + pChild00 = Abc_ObjFanin0(pFanin0); + pChild01 = Abc_ObjFanin1(pFanin0); + if ( pRoot == pChild00 || pRoot == pChild01 ) + return 0; + } + if ( Abc_ObjIsCi(pFanin1) ) + { + pChild10 = NULL; + pChild11 = NULL; + } + else + { + pChild10 = Abc_ObjFanin0(pFanin1); + pChild11 = Abc_ObjFanin1(pFanin1); + if ( pRoot == pChild10 || pRoot == pChild11 ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pEnt; + int i; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pEnt ) + { + if ( Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id > Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id ) + { +// int i0 = Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id; +// int i1 = Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id; + printf( "Node %d has incorrect ordering of fanins.\n", pEnt->Id ); + } + } +} + +/**Function************************************************************* + + Synopsis [Sets the correct phase of the nodes.] + + Description [The AIG nodes should be in the DFS order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsDfsOrdered(pNtk) ); + Abc_AigConst1(pNtk)->fPhase = 1; + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->fPhase = 0; + Abc_NtkForEachLatchOutput( pNtk, pObj, i ) + pObj->fPhase = Abc_LatchIsInit1(pObj); + Abc_AigForEachAnd( pNtk, pObj, i ) + pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)) & (Abc_ObjFanin1(pObj)->fPhase ^ Abc_ObjFaninC1(pObj)); + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)); + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)); +} + + + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets ) +{ + assert( pMan->vAddedCells == NULL ); + pMan->vAddedCells = Vec_PtrAlloc( 1000 ); + pMan->vUpdatedNets = Vec_PtrAlloc( 1000 ); + *pvUpdatedNets = pMan->vUpdatedNets; + return pMan->vAddedCells; +} + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateStop( Abc_Aig_t * pMan ) +{ + assert( pMan->vAddedCells != NULL ); + Vec_PtrFree( pMan->vAddedCells ); + Vec_PtrFree( pMan->vUpdatedNets ); + pMan->vAddedCells = NULL; + pMan->vUpdatedNets = NULL; +} + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateReset( Abc_Aig_t * pMan ) +{ + assert( pMan->vAddedCells != NULL ); + Vec_PtrClear( pMan->vAddedCells ); + Vec_PtrClear( pMan->vUpdatedNets ); +} + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigCountNext( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pAnd; + int i, Counter = 0, CounterTotal = 0; + // count how many nodes have pNext set + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) + { + Counter += (pAnd->pNext != NULL); + CounterTotal++; + } + printf( "Counter = %d. Nodes = %d. Ave = %6.2f\n", Counter, CounterTotal, 1.0 * CounterTotal/pMan->nBins ); + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcBlifMv.c b/abc70930/src/base/abc/abcBlifMv.c new file mode 100644 index 00000000..48ec58c0 --- /dev/null +++ b/abc70930/src/base/abc/abcBlifMv.c @@ -0,0 +1,970 @@ +/**CFile**************************************************************** + + FileName [abcBlifMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to process BLIF-MV networks and AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the Mv-Var manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ) +{ + Vec_Att_t * pAttMan; + assert( Abc_NtkMvVar(pNtk) == NULL ); + pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, Extra_MmFlexStart(), Extra_MmFlexStop, NULL, NULL ); + Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_MVVAR, pAttMan ); +//printf( "allocing attr\n" ); +} + +/**Function************************************************************* + + Synopsis [Stops the Mv-Var manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ) +{ + void * pUserMan; + pUserMan = Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, 0 ); + Extra_MmFlexStop( pUserMan ); +} + +/**Function************************************************************* + + Synopsis [Duplicate the MV variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues ) +{ + Extra_MmFlex_t * pFlex; + struct temp + { + int nValues; + char ** pNames; + } * pVarStruct; + assert( nValues > 1 ); + // skip binary signals + if ( nValues == 2 ) + return; + // skip already assigned signals + if ( Abc_ObjMvVar(pObj) != NULL ) + return; + // create the structure + pFlex = Abc_NtkMvVarMan( pObj->pNtk ); + pVarStruct = (void *)Extra_MmFlexEntryFetch( pFlex, sizeof(struct temp) ); + pVarStruct->nValues = nValues; + pVarStruct->pNames = NULL; + Abc_ObjSetMvVar( pObj, pVarStruct ); +} + +/**Function************************************************************* + + Synopsis [Strashes the BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_StringGetNumber( char ** ppStr ) +{ + char * pStr = *ppStr; + int Number = 0; + assert( *pStr >= '0' && *pStr <= '9' ); + for ( ; *pStr >= '0' && *pStr <= '9'; pStr++ ) + Number = 10 * Number + *pStr - '0'; + *ppStr = pStr; + return Number; +} + +/**Function************************************************************* + + Synopsis [Strashes one node in the BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeStrashBlifMv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) +{ + char * pSop; + Abc_Obj_t ** pValues, ** pValuesF, ** pValuesF2; + Abc_Obj_t * pTemp, * pTemp2, * pFanin, * pFanin2, * pNet; + int k, v, Def, DefIndex, Index, nValues, nValuesF, nValuesF2; + + // start the output values + assert( Abc_ObjIsNode(pObj) ); + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + pValues = ALLOC( Abc_Obj_t *, nValues ); + for ( k = 0; k < nValues; k++ ) + pValues[k] = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + + // get the BLIF-MV formula + pSop = pObj->pData; + // skip the value line +// while ( *pSop++ != '\n' ); + + // handle the constant + if ( Abc_ObjFaninNum(pObj) == 0 ) + { + // skip the default if present + if ( *pSop == 'd' ) + while ( *pSop++ != '\n' ); + // skip space if present + if ( *pSop == ' ' ) + pSop++; + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValues ); + pValues[Index] = Abc_AigConst1(pNtkNew); + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + return 1; + } + + // parse the default line + Def = DefIndex = -1; + if ( *pSop == 'd' ) + { + pSop++; + if ( *pSop == '=' ) + { + pSop++; + DefIndex = Abc_StringGetNumber( &pSop ); + assert( DefIndex < Abc_ObjFaninNum(pObj) ); + } + else if ( *pSop == '-' ) + { + pSop++; + Def = 0; + } + else + { + Def = Abc_StringGetNumber( &pSop ); + assert( Def < nValues ); + } + assert( *pSop == '\n' ); + pSop++; + } + + // convert the values + while ( *pSop ) + { + // extract the values for each cube + pTemp = Abc_AigConst1(pNtkNew); + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( *pSop == '-' ) + { + pSop += 2; + continue; + } + if ( *pSop == '!' ) + { + printf( "Abc_NodeStrashBlifMv(): Cannot handle complement in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); + return 0; + } + if ( *pSop == '{' ) + { + printf( "Abc_NodeStrashBlifMv(): Cannot handle braces in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); + return 0; + } + // get the value set + nValuesF = Abc_ObjMvVarNum(pFanin); + pValuesF = (Abc_Obj_t **)pFanin->pCopy; + if ( *pSop == '(' ) + { + pSop++; + pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + while ( *pSop != ')' ) + { + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValuesF ); + pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, pValuesF[Index] ); + assert( *pSop == ')' || *pSop == ',' ); + if ( *pSop == ',' ) + pSop++; + } + assert( *pSop == ')' ); + pSop++; + } + else if ( *pSop == '=' ) + { + pSop++; + // get the fanin index + Index = Abc_StringGetNumber( &pSop ); + assert( Index < Abc_ObjFaninNum(pObj) ); + assert( Index != k ); + // get the fanin + pFanin2 = Abc_ObjFanin( pObj, Index ); + nValuesF2 = Abc_ObjMvVarNum(pFanin2); + pValuesF2 = (Abc_Obj_t **)pFanin2->pCopy; + // create the sum of products of values + assert( nValuesF == nValuesF2 ); + pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + for ( v = 0; v < nValues; v++ ) + pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, Abc_AigAnd(pNtkNew->pManFunc, pValuesF[v], pValuesF2[v]) ); + } + else + { + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValuesF ); + pTemp2 = pValuesF[Index]; + } + // compute the compute + pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, pTemp2 ); + // advance the reading point + assert( *pSop == ' ' ); + pSop++; + } + // check if the output value is an equal construct + if ( *pSop == '=' ) + { + pSop++; + // get the output value + Index = Abc_StringGetNumber( &pSop ); + assert( Index < Abc_ObjFaninNum(pObj) ); + // add values of the given fanin with the given cube + pFanin = Abc_ObjFanin( pObj, Index ); + nValuesF = Abc_ObjMvVarNum(pFanin); + pValuesF = (Abc_Obj_t **)pFanin->pCopy; + assert( nValuesF == nValues ); // should be guaranteed by the parser + for ( k = 0; k < nValuesF; k++ ) + pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) ); + } + else + { + // get the output value + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValues ); + pValues[Index] = Abc_AigOr( pNtkNew->pManFunc, pValues[Index], pTemp ); + } + // advance the reading point + assert( *pSop == '\n' ); + pSop++; + } + + // compute the default value + if ( Def >= 0 || DefIndex >= 0 ) + { + pTemp = Abc_AigConst1(pNtkNew); + for ( k = 0; k < nValues; k++ ) + { + if ( k == Def ) + continue; + pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, Abc_ObjNot(pValues[k]) ); + } + + // assign the default value + if ( Def >= 0 ) + pValues[Def] = pTemp; + else + { + assert( DefIndex >= 0 ); + // add values of the given fanin with the given cube + pFanin = Abc_ObjFanin( pObj, DefIndex ); + nValuesF = Abc_ObjMvVarNum(pFanin); + pValuesF = (Abc_Obj_t **)pFanin->pCopy; + assert( nValuesF == nValues ); // should be guaranteed by the parser + for ( k = 0; k < nValuesF; k++ ) + pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) ); + } + + } + + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + return 1; +} + +/**Function************************************************************* + + Synopsis [Assigns name with index.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index ) +{ + char Suffix[16]; + assert( Abc_ObjIsTerm(pObj) ); + assert( Abc_ObjIsNet(pNet) ); + sprintf( Suffix, "[%d]", Index ); + Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix ); +} + +/**Function************************************************************* + + Synopsis [Strashes the BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ) +{ + int fUsePositional = 0; + Vec_Ptr_t * vNodes; + Abc_Obj_t ** pBits; + Abc_Obj_t ** pValues; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pTemp, * pBit, * pNet; + int i, k, v, nValues, nValuesMax, nBits; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasBlifMv(pNtk) ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + assert( Abc_NtkBlackboxNum(pNtk) == 0 ); + + // get the largest number of values + nValuesMax = 2; + Abc_NtkForEachNet( pNtk, pObj, i ) + { + nValues = Abc_ObjMvVarNum(pObj); + if ( nValuesMax < nValues ) + nValuesMax = nValues; + } + nBits = Extra_Base2Log( nValuesMax ); + pBits = ALLOC( Abc_Obj_t *, nBits ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // collect the nodes + vNodes = Abc_NtkDfs( pNtk, 0 ); + + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); +// pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName ); + + // encode the CI nets + Abc_NtkIncrementTravId( pNtk ); + if ( fUsePositional ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + pValues = ALLOC( Abc_Obj_t *, nValues ); + // create PIs for the values + for ( v = 0; v < nValues; v++ ) + { + pValues[v] = Abc_NtkCreatePi( pNtkNew ); + Abc_NtkConvertAssignName( pValues[v], pNet, v ); + } + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + else + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + pValues = ALLOC( Abc_Obj_t *, nValues ); + // create PIs for the encoding bits + nBits = Extra_Base2Log( nValues ); + for ( k = 0; k < nBits; k++ ) + { + pBits[k] = Abc_NtkCreatePi( pNtkNew ); + Abc_NtkConvertAssignName( pBits[k], pNet, k ); + } + // encode the values + for ( v = 0; v < nValues; v++ ) + { + pValues[v] = Abc_AigConst1(pNtkNew); + for ( k = 0; k < nBits; k++ ) + { + pBit = Abc_ObjNotCond( pBits[k], (v&(1<pManFunc, pValues[v], pBit ); + } + } + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + + // process nodes in the topological order + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( !Abc_NodeStrashBlifMv( pNtkNew, pObj ) ) + { + Abc_NtkDelete( pNtkNew ); + return NULL; + } + Vec_PtrFree( vNodes ); + + // encode the CO nets + if ( fUsePositional ) + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(pObj); + // skip marked nets + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + pValues = (Abc_Obj_t **)pNet->pCopy; + for ( v = 0; v < nValues; v++ ) + { + pTemp = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pTemp, pValues[v] ); + Abc_NtkConvertAssignName( pTemp, pNet, v ); + } + } + } + else + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(pObj); + // skip marked nets + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + pValues = (Abc_Obj_t **)pNet->pCopy; + nBits = Extra_Base2Log( nValues ); + for ( k = 0; k < nBits; k++ ) + { + pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + for ( v = 0; v < nValues; v++ ) + if ( v & (1<pManFunc, pBit, pValues[v] ); + pTemp = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pTemp, pBit ); + Abc_NtkConvertAssignName( pTemp, pNet, k ); + } + } + } + + // cleanup + free( pBits ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy ) + free( pObj->pCopy ); + + // remove dangling nodes + i = Abc_AigCleanup(pNtkNew->pManFunc); +// printf( "Cleanup removed %d nodes.\n", i ); +// Abc_NtkReassignIds( pNtkNew ); + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkStrashBlifMv(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Extract the MV-skeleton of the BLIF-MV network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkSkeletonBlifMv( Abc_Ntk_t * pNtk ) +{ + int fUsePositional = 0; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNet, * pNetNew, * pNodeNew, * pTermNew, * pBoxNew; + int i, k, v, nValues, nBits; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasBlifMv(pNtk) ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + assert( Abc_NtkBlackboxNum(pNtk) == 0 ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName ); + // create the internal box (it is important to put it first!) + pBoxNew = Abc_NtkCreateWhitebox( pNtkNew ); + // create PIs and their nets + Abc_NtkForEachPi( pNtk, pObj, i ) + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + pNet = Abc_ObjFanout0(pObj); + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( pNet->pCopy, pObj->pCopy ); + } + // create POs and their nets + Abc_NtkForEachPo( pNtk, pObj, i ) + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + pNet = Abc_ObjFanin0(pObj); + if ( pNet->pCopy == NULL ) + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( pObj->pCopy, pNet->pCopy ); + } + // create latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + Abc_NtkDupBox( pNtkNew, pObj, 0 ); + // latch outputs + pNet = Abc_ObjFanout0(Abc_ObjFanout0(pObj)); + assert( pNet->pCopy == NULL ); + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( pNet->pCopy, Abc_ObjFanout0(pObj)->pCopy ); + // latch inputs + pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); + if ( pNet->pCopy == NULL ) + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( Abc_ObjFanin0(pObj)->pCopy, pNet->pCopy ); + } + + // encode the CI nets + Abc_NtkIncrementTravId( pNtk ); + if ( fUsePositional ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + for ( v = 0; v < nValues; v++ ) + { + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopEncoderPos( pNtkNew->pManFunc, v, nValues ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + pTermNew = Abc_NtkCreateBi( pNtkNew ); + Abc_ObjAddFanin( pNodeNew, pNet->pCopy ); + Abc_ObjAddFanin( pNetNew, pNodeNew ); + Abc_ObjAddFanin( pTermNew, pNetNew ); + Abc_ObjAddFanin( pBoxNew, pTermNew ); + } + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + else + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + nBits = Extra_Base2Log( nValues ); + for ( k = 0; k < nBits; k++ ) + { + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopEncoderLog( pNtkNew->pManFunc, k, nValues ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + pTermNew = Abc_NtkCreateBi( pNtkNew ); + Abc_ObjAddFanin( pNodeNew, pNet->pCopy ); + Abc_ObjAddFanin( pNetNew, pNodeNew ); + Abc_ObjAddFanin( pTermNew, pNetNew ); + Abc_ObjAddFanin( pBoxNew, pTermNew ); + } + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + + // encode the CO nets + if ( fUsePositional ) + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(pObj); + // skip marked nets + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopDecoderPos( pNtkNew->pManFunc, nValues ); + for ( v = 0; v < nValues; v++ ) + { + pTermNew = Abc_NtkCreateBo( pNtkNew ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + Abc_ObjAddFanin( pTermNew, pBoxNew ); + Abc_ObjAddFanin( pNetNew, pTermNew ); + Abc_ObjAddFanin( pNodeNew, pNetNew ); + } + Abc_ObjAddFanin( pNet->pCopy, pNodeNew ); + } + } + else + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(pObj); + // skip marked nets + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + nBits = Extra_Base2Log( nValues ); + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopDecoderLog( pNtkNew->pManFunc, nValues ); + for ( k = 0; k < nBits; k++ ) + { + pTermNew = Abc_NtkCreateBo( pNtkNew ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + Abc_ObjAddFanin( pTermNew, pBoxNew ); + Abc_ObjAddFanin( pNetNew, pTermNew ); + Abc_ObjAddFanin( pNodeNew, pNetNew ); + } + Abc_ObjAddFanin( pNet->pCopy, pNodeNew ); + } + } + + // if it is a BLIF-MV netlist transfer the values of all nets + if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) + { + if ( Abc_NtkMvVar( pNtkNew ) == NULL ) + Abc_NtkStartMvVars( pNtkNew ); + Abc_NtkForEachNet( pNtk, pObj, i ) + if ( pObj->pCopy ) + Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); + } + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkSkeletonBlifMv(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Inserts processed network into original base MV network.] + + Description [The original network remembers the interface of combinational + logic (PIs/POs/latches names and values). The processed network may + be binary or multi-valued (currently, multi-value is not supported). + The resulting network has the same interface as the original network + while the internal logic is the same as that of the processed network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic ) +{ + Abc_Ntk_t * pNtkSkel, * pNtkNew; + Abc_Obj_t * pBox; + + assert( Abc_NtkIsNetlist(pNtkBase) ); + assert( Abc_NtkHasBlifMv(pNtkBase) ); + assert( Abc_NtkWhiteboxNum(pNtkBase) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkBase) == 0 ); + + assert( Abc_NtkIsNetlist(pNtkLogic) ); + assert( Abc_NtkHasBlifMv(pNtkLogic) ); + assert( Abc_NtkWhiteboxNum(pNtkLogic) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkLogic) == 0 ); + + // extract the skeleton of the old network + pNtkSkel = Abc_NtkSkeletonBlifMv( pNtkBase ); + + // set the implementation of the box to be the same as the processed network + assert( Abc_NtkWhiteboxNum(pNtkSkel) == 1 ); + pBox = Abc_NtkBox( pNtkSkel, 0 ); + assert( Abc_ObjIsWhitebox(pBox) ); + assert( pBox->pData == NULL ); + assert( Abc_ObjFaninNum(pBox) == Abc_NtkPiNum(pNtkLogic) ); + assert( Abc_ObjFanoutNum(pBox) == Abc_NtkPoNum(pNtkLogic) ); + pBox->pData = pNtkLogic; + + // flatten the hierarchy to insert the processed network + pNtkNew = Abc_NtkFlattenLogicHierarchy( pNtkSkel ); + pBox->pData = NULL; + Abc_NtkDelete( pNtkSkel ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts SOP netlist into BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk ) +{ + Extra_MmFlex_t * pMmFlex; + Abc_Obj_t * pNode; + Vec_Str_t * vCube; + char * pSop0, * pSop1, * pBlifMv, * pCube, * pCur; + int Value, nCubes, nSize, i, k; + + assert( Abc_NtkIsNetlist(pNtk) ); + if ( !Abc_NtkToBdd(pNtk) ) + { + printf( "Converting logic functions to BDDs has failed.\n" ); + return 0; + } + + pMmFlex = Extra_MmFlexStart(); + vCube = Vec_StrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // convert BDD into cubes for on-set and off-set + Abc_NodeBddToCnf( pNode, pMmFlex, vCube, 0, &pSop0, &pSop1 ); + // allocate room for the MV-SOP + nCubes = Abc_SopGetCubeNum(pSop0) + Abc_SopGetCubeNum(pSop1); + nSize = nCubes*(2*Abc_ObjFaninNum(pNode) + 2)+1; + pBlifMv = Extra_MmFlexEntryFetch( pMmFlex, nSize ); + // add the cubes + pCur = pBlifMv; + Abc_SopForEachCube( pSop0, Abc_ObjFaninNum(pNode), pCube ) + { + Abc_CubeForEachVar( pCube, Value, k ) + { + *pCur++ = Value; + *pCur++ = ' '; + } + *pCur++ = '0'; + *pCur++ = '\n'; + } + Abc_SopForEachCube( pSop1, Abc_ObjFaninNum(pNode), pCube ) + { + Abc_CubeForEachVar( pCube, Value, k ) + { + *pCur++ = Value; + *pCur++ = ' '; + } + *pCur++ = '1'; + *pCur++ = '\n'; + } + *pCur++ = 0; + assert( pCur - pBlifMv == nSize ); + // update the node representation + Cudd_RecursiveDeref( pNtk->pManFunc, pNode->pData ); + pNode->pData = pBlifMv; + } + + // update the functionality type + pNtk->ntkFunc = ABC_FUNC_BLIFMV; + Cudd_Quit( pNtk->pManFunc ); + pNtk->pManFunc = pMmFlex; + + Vec_StrFree( vCube ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Converts SOP into MV-SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) +{ + char * pMvSop, * pCur; + unsigned uCube; + int nCubes, nSize, Value, i, k; + // consider the case of the constant node + if ( Vec_IntSize(vSop0) == 0 || Vec_IntSize(vSop1) == 0 ) + { + // (temporary) create a tautology cube + pMvSop = ALLOC( char, nVars + 3 ); + for ( k = 0; k < nVars; k++ ) + pMvSop[k] = '-'; + pMvSop[nVars] = '0' + (int)(Vec_IntSize(vSop1) > 0); + pMvSop[nVars+1] = '\n'; + pMvSop[nVars+2] = 0; + return pMvSop; + } + // find the total number of cubes + nCubes = Vec_IntSize(vSop0) + Vec_IntSize(vSop1); + // find the size of the MVSOP represented as a C-string + // (each cube has nVars variables + one output literal + end-of-line, + // and the string is zero-terminated) + nSize = nCubes * (nVars + 2) + 1; + // allocate memory + pMvSop = pCur = ALLOC( char, nSize ); + // fill in the negative polarity cubes + Vec_IntForEachEntry( vSop0, uCube, i ) + { + for ( k = 0; k < nVars; k++ ) + { + Value = (uCube >> (2*k)) & 3; + if ( Value == 1 ) + *pCur++ = '0'; + else if ( Value == 2 ) + *pCur++ = '1'; + else if ( Value == 0 ) + *pCur++ = '-'; + else + assert( 0 ); + } + *pCur++ = '0'; + *pCur++ = '\n'; + } + // fill in the positive polarity cubes + Vec_IntForEachEntry( vSop1, uCube, i ) + { + for ( k = 0; k < nVars; k++ ) + { + Value = (uCube >> (2*k)) & 3; + if ( Value == 1 ) + *pCur++ = '0'; + else if ( Value == 2 ) + *pCur++ = '1'; + else if ( Value == 0 ) + *pCur++ = '-'; + else + assert( 0 ); + } + *pCur++ = '1'; + *pCur++ = '\n'; + } + *pCur++ = 0; + assert( pCur - pMvSop == nSize ); + return pMvSop; +} + + +/**Function************************************************************* + + Synopsis [A prototype of internal cost evaluation procedure.] + + Description [This procedure takes the number of variables (nVars), + the array of values of the inputs and the output (pVarValues) + (note that this array has nVars+1 entries), and an MV-SOP represented + as a C-string with one charater for each literal, including inputs + and output. Each cube is terminated with the new-line character ('\n'). + The string is zero-terminated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeEvalMvCostInternal( int nVars, int * pVarValues, char * pMvSop ) +{ + // for now, return the number of cubes in the MV-SOP + int Counter = 0; + while ( *pMvSop ) Counter += (*pMvSop++ == '\n'); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Evaluates the cost of the cut.] + + Description [The Boolean function of the cut is specified by two SOPs, + which represent the negative/positive polarities of the cut function. + Converts these two SOPs into a mutually-agreed-upon representation + to be passed to the internal cost-evaluation procedure (see the above + prototype Abc_NodeEvalMvCostInternal).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) +{ + char * pMvSop; + int * pVarValues; + int i, RetValue; + // collect the input and output values (currently, they are binary) + pVarValues = ALLOC( int, nVars + 1 ); + for ( i = 0; i <= nVars; i++ ) + pVarValues[i] = 2; + // prepare MV-SOP for evaluation + pMvSop = Abc_NodeConvertSopToMvSop( nVars, vSop0, vSop1 ); + // have a look at the MV-SOP: +// printf( "%s\n", pMvSop ); + // get the result of internal cost evaluation + RetValue = Abc_NodeEvalMvCostInternal( nVars, pVarValues, pMvSop ); + // cleanup + free( pVarValues ); + free( pMvSop ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcCheck.c b/abc70930/src/base/abc/abcCheck.c new file mode 100644 index 00000000..3072e40f --- /dev/null +++ b/abc70930/src/base/abc/abcCheck.c @@ -0,0 +1,939 @@ +/**CFile**************************************************************** + + FileName [abcCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Consistency checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +//#include "seq.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk ); +static bool Abc_NtkCheckPis( Abc_Ntk_t * pNtk ); +static bool Abc_NtkCheckPos( Abc_Ntk_t * pNtk ); +//static bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); +static bool Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ); +static bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); +static bool Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ); + +static bool Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); +static bool Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); +static bool Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); + +static inline char * Abc_ObjNameNet( Abc_Obj_t * pObj ) { return (Abc_ObjIsNode(pObj) && Abc_NtkIsNetlist(pObj->pNtk)) ? Abc_ObjName(Abc_ObjFanout0(pObj)) : Abc_ObjName(pObj); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the integrity of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheck( Abc_Ntk_t * pNtk ) +{ + return !Abc_FrameIsFlagEnabled( "check" ) || Abc_NtkDoCheck( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of the network after reading.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckRead( Abc_Ntk_t * pNtk ) +{ + return !Abc_FrameIsFlagEnabled( "checkread" ) || Abc_NtkDoCheck( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pNet, * pNode; + int i; + + // check network types + if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Unknown network type.\n" ); + return 0; + } + if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasBlackbox(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Unknown functionality type.\n" ); + return 0; + } + if ( Abc_NtkHasMapping(pNtk) ) + { + if ( pNtk->pManFunc != Abc_FrameReadLibGen() ) + { + fprintf( stdout, "NetworkCheck: The library of the mapped network is not the global library.\n" ); + return 0; + } + } + + if ( Abc_NtkHasOnlyLatchBoxes(pNtk) ) + { + // check CI/CO numbers + if ( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCiNum(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Number of CIs does not match number of PIs and latches.\n" ); + fprintf( stdout, "One possible reason is that latches are added twice:\n" ); + fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" ); + return 0; + } + if ( Abc_NtkPoNum(pNtk) + Abc_NtkAssertNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCoNum(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Number of COs does not match number of POs, asserts, and latches.\n" ); + fprintf( stdout, "One possible reason is that latches are added twice:\n" ); + fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" ); + return 0; + } + } + + // check the names + if ( !Abc_NtkCheckNames( pNtk ) ) + return 0; + + // check PIs and POs + Abc_NtkCleanCopy( pNtk ); + if ( !Abc_NtkCheckPis( pNtk ) ) + return 0; + if ( !Abc_NtkCheckPos( pNtk ) ) + return 0; + + if ( Abc_NtkHasBlackbox(pNtk) ) + return 1; + + // check the connectivity of objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NtkCheckObj( pNtk, pObj ) ) + return 0; + + // if it is a netlist change nets and latches + if ( Abc_NtkIsNetlist(pNtk) ) + { + if ( Abc_NtkNetNum(pNtk) == 0 ) + { + fprintf( stdout, "NetworkCheck: Netlist has no nets.\n" ); + return 0; + } + // check the nets + Abc_NtkForEachNet( pNtk, pNet, i ) + if ( !Abc_NtkCheckNet( pNtk, pNet ) ) + return 0; + } + else + { + if ( Abc_NtkNetNum(pNtk) != 0 ) + { + fprintf( stdout, "NetworkCheck: A network that is not a netlist has nets.\n" ); + return 0; + } + } + + // check the nodes + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigCheck( pNtk->pManFunc ); + else + { + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( !Abc_NtkCheckNode( pNtk, pNode ) ) + return 0; + } + + // check the latches + Abc_NtkForEachLatch( pNtk, pNode, i ) + if ( !Abc_NtkCheckLatch( pNtk, pNode ) ) + return 0; + + // finally, check for combinational loops +// clk = clock(); + if ( !Abc_NtkIsAcyclic( pNtk ) ) + { + fprintf( stdout, "NetworkCheck: Network contains a combinational loop.\n" ); + return 0; + } +// PRT( "Acyclic ", clock() - clk ); + + // check the EXDC network if present + if ( pNtk->pExdc ) + Abc_NtkCheck( pNtk->pExdc ); +/* + // check the hierarchy + if ( Abc_NtkIsNetlist(pNtk) && pNtk->tName2Model ) + { + stmm_generator * gen; + Abc_Ntk_t * pNtkTemp; + char * pName; + // check other networks + stmm_foreach_item( pNtk->tName2Model, gen, &pName, (char **)&pNtkTemp ) + { + pNtkTemp->fHiePath = pNtkTemp->fHieVisited = 0; + if ( !Abc_NtkCheck( pNtkTemp ) ) + return 0; + } + // check acyclic dependency of the models + if ( !Abc_NtkIsAcyclicHierarchy( pNtk ) ) + { + fprintf( stdout, "NetworkCheck: Network hierarchical dependences contains a cycle.\n" ); + return 0; + } + } +*/ + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + Vec_Int_t * vNameIds; + char * pName; + int i, NameId; + + if ( Abc_NtkIsNetlist(pNtk) ) + return 1; + + // check that each CI/CO has a name + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pObj = Abc_ObjFanout0Ntk(pObj); + if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) + { + fprintf( stdout, "NetworkCheck: CI with ID %d is in the network but not in the name table.\n", pObj->Id ); + return 0; + } + } + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pObj = Abc_ObjFanin0Ntk(pObj); + if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) + { + fprintf( stdout, "NetworkCheck: CO with ID %d is in the network but not in the name table.\n", pObj->Id ); + return 0; + } + } + + // return the array of all IDs, which have names + vNameIds = Nm_ManReturnNameIds( pNtk->pManName ); + // make sure that these IDs correspond to live objects + Vec_IntForEachEntry( vNameIds, NameId, i ) + { + if ( Vec_PtrEntry( pNtk->vObjs, NameId ) == NULL ) + { + Vec_IntFree( vNameIds ); + pName = Nm_ManFindNameById(pObj->pNtk->pManName, NameId); + fprintf( stdout, "NetworkCheck: Object with ID %d is deleted but its name \"%s\" remains in the name table.\n", NameId, pName ); + return 0; + } + } + Vec_IntFree( vNameIds ); + + // make sure the CI names are unique + if ( !Abc_NtkCheckUniqueCiNames(pNtk) ) + return 0; + + // make sure the CO names are unique + if ( !Abc_NtkCheckUniqueCoNames(pNtk) ) + return 0; + + // make sure that if a CO has the same name as a CI, they point directly + if ( !Abc_NtkCheckUniqueCioNames(pNtk) ) + return 0; + + return 1; +} + + +/**Function************************************************************* + + Synopsis [Checks the PIs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckPis( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + // check that PIs are indeed PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + { + if ( !Abc_ObjIsPi(pObj) ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is in the PI list but is not a PI.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + if ( pObj->pData ) + { + fprintf( stdout, "NetworkCheck: A PI \"%s\" has a logic function.\n", Abc_ObjName(pObj) ); + return 0; + } + if ( Abc_ObjFaninNum(pObj) > 0 ) + { + fprintf( stdout, "NetworkCheck: A PI \"%s\" has fanins.\n", Abc_ObjName(pObj) ); + return 0; + } + pObj->pCopy = (Abc_Obj_t *)1; + } + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->pCopy == NULL && Abc_ObjIsPi(pObj) ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is a PI but is not in the PI list.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + pObj->pCopy = NULL; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the POs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckPos( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + // check that POs are indeed POs + Abc_NtkForEachPo( pNtk, pObj, i ) + { + if ( !Abc_ObjIsPo(pObj) ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in the PO list but is not a PO.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + if ( pObj->pData ) + { + fprintf( stdout, "NetworkCheck: A PO \"%s\" has a logic function.\n", Abc_ObjName(pObj) ); + return 0; + } + if ( Abc_ObjFaninNum(pObj) != 1 ) + { + fprintf( stdout, "NetworkCheck: A PO \"%s\" does not have one fanin.\n", Abc_ObjName(pObj) ); + return 0; + } + if ( Abc_ObjFanoutNum(pObj) > 0 ) + { + fprintf( stdout, "NetworkCheck: A PO \"%s\" has fanouts.\n", Abc_ObjName(pObj) ); + return 0; + } + pObj->pCopy = (Abc_Obj_t *)1; + } + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->pCopy == NULL && Abc_ObjIsPo(pObj) ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in a PO but is not in the PO list.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + pObj->pCopy = NULL; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Checks the connectivity of the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin, * pFanout; + int i, Value = 1; + int k; + + // check the network + if ( pObj->pNtk != pNtk ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" does not belong to the network.\n", Abc_ObjName(pObj) ); + return 0; + } + // check the object ID + if ( pObj->Id < 0 || (int)pObj->Id >= Abc_NtkObjNumMax(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" has incorrect ID.\n", Abc_ObjName(pObj) ); + return 0; + } + + if ( !Abc_FrameIsFlagEnabled("checkfio") ) + return Value; + + // go through the fanins of the object and make sure fanins have this object as a fanout + Abc_ObjForEachFanin( pObj, pFanin, i ) + { + if ( Vec_IntFind( &pFanin->vFanouts, pObj->Id ) == -1 ) + { + fprintf( stdout, "NodeCheck: Object \"%s\" has fanin ", Abc_ObjName(pObj) ); + fprintf( stdout, "\"%s\" but the fanin does not have it as a fanout.\n", Abc_ObjName(pFanin) ); + Value = 0; + } + } + // go through the fanouts of the object and make sure fanouts have this object as a fanin + Abc_ObjForEachFanout( pObj, pFanout, i ) + { + if ( Vec_IntFind( &pFanout->vFanins, pObj->Id ) == -1 ) + { + fprintf( stdout, "NodeCheck: Object \"%s\" has fanout ", Abc_ObjName(pObj) ); + fprintf( stdout, "\"%s\" but the fanout does not have it as a fanin.\n", Abc_ObjName(pFanout) ); + Value = 0; + } + } + + // make sure fanins are not duplicated + for ( i = 0; i < pObj->vFanins.nSize; i++ ) + for ( k = i + 1; k < pObj->vFanins.nSize; k++ ) + if ( pObj->vFanins.pArray[k] == pObj->vFanins.pArray[i] ) + { + printf( "Warning: Node %s has", Abc_ObjName(pObj) ); + printf( " duplicated fanin %s.\n", Abc_ObjName(Abc_ObjFanin(pObj,k)) ); + } + + // save time: do not check large fanout lists + if ( pObj->vFanouts.nSize > 100 ) + return Value; + + // make sure fanouts are not duplicated + for ( i = 0; i < pObj->vFanouts.nSize; i++ ) + for ( k = i + 1; k < pObj->vFanouts.nSize; k++ ) + if ( pObj->vFanouts.pArray[k] == pObj->vFanouts.pArray[i] ) + { + printf( "Warning: Node %s has", Abc_ObjName(pObj) ); + printf( " duplicated fanout %s.\n", Abc_ObjName(Abc_ObjFanout(pObj,k)) ); + } + + return Value; +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of a net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ) +{ + if ( Abc_ObjFaninNum(pNet) == 0 ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" is not driven.\n", Abc_ObjName(pNet) ); + return 0; + } + if ( Abc_ObjFaninNum(pNet) > 1 ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" has more than one driver.\n", Abc_ObjName(pNet) ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) +{ + // detect internal nodes that do not have nets + if ( Abc_NtkIsNetlist(pNtk) && Abc_ObjFanoutNum(pNode) == 0 ) + { + fprintf( stdout, "Node (id = %d) has no net to drive.\n", pNode->Id ); + return 0; + } + // the node should have a function assigned unless it is an AIG + if ( pNode->pData == NULL ) + { + fprintf( stdout, "NodeCheck: An internal node \"%s\" does not have a logic function.\n", Abc_ObjNameNet(pNode) ); + return 0; + } + // the netlist and SOP logic network should have SOPs + if ( Abc_NtkHasSop(pNtk) ) + { + if ( !Abc_SopCheck( pNode->pData, Abc_ObjFaninNum(pNode) ) ) + { + fprintf( stdout, "NodeCheck: SOP check for node \"%s\" has failed.\n", Abc_ObjNameNet(pNode) ); + return 0; + } + } + else if ( Abc_NtkHasBdd(pNtk) ) + { + int nSuppSize = Cudd_SupportSize(pNtk->pManFunc, pNode->pData); + if ( nSuppSize > Abc_ObjFaninNum(pNode) ) + { + fprintf( stdout, "NodeCheck: BDD of the node \"%s\" has incorrect support size.\n", Abc_ObjNameNet(pNode) ); + return 0; + } + } + else if ( !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasAig(pNtk) ) + { + assert( 0 ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of a latch.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ) +{ + int Value = 1; + // check whether the object is a latch + if ( !Abc_ObjIsLatch(pLatch) ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" is in a latch list but is not a latch.\n", Abc_ObjName(pLatch) ); + Value = 0; + } + // make sure the latch has a reasonable return value + if ( (int)pLatch->pData < ABC_INIT_ZERO || (int)pLatch->pData > ABC_INIT_DC ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" has incorrect reset value (%d).\n", + Abc_ObjName(pLatch), (int)pLatch->pData ); + Value = 0; + } + // make sure the latch has only one fanin + if ( Abc_ObjFaninNum(pLatch) != 1 ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanins.\n", Abc_ObjName(pLatch), Abc_ObjFaninNum(pLatch) ); + Value = 0; + } + // make sure the latch has only one fanout + if ( Abc_ObjFanoutNum(pLatch) != 1 ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanouts.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) ); + Value = 0; + } + // make sure the latch input has only one fanin + if ( Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanins.\n", + Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) ); + Value = 0; + } + // make sure the latch input has only one fanout + if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanouts.\n", + Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) ); + Value = 0; + } + // make sure the latch output has only one fanin + if ( Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Output of latch \"%s\" has wrong number (%d) of fanins.\n", + Abc_ObjName(Abc_ObjFanout0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) ); + Value = 0; + } + return Value; +} + + + + +/**Function************************************************************* + + Synopsis [Compares the PIs of the two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) +{ + Abc_Obj_t * pObj1; + int i; + if ( Abc_NtkPiNum(pNtk1) != Abc_NtkPiNum(pNtk2) ) + { + printf( "Networks have different number of primary inputs.\n" ); + return 0; + } + // for each PI of pNet1 find corresponding PI of pNet2 and reorder them + Abc_NtkForEachPi( pNtk1, pObj1, i ) + { + if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ) != 0 ) + { + printf( "Primary input #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", + i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares the POs of the two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) +{ + Abc_Obj_t * pObj1; + int i; + if ( Abc_NtkPoNum(pNtk1) != Abc_NtkPoNum(pNtk2) ) + { + printf( "Networks have different number of primary outputs.\n" ); + return 0; + } + // for each PO of pNet1 find corresponding PO of pNet2 and reorder them + Abc_NtkForEachPo( pNtk1, pObj1, i ) + { + if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ) != 0 ) + { + printf( "Primary output #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", + i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares the latches of the two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCompareBoxes( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) +{ + Abc_Obj_t * pObj1; + int i; + assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); + if ( !fComb ) + return 1; + if ( Abc_NtkBoxNum(pNtk1) != Abc_NtkBoxNum(pNtk2) ) + { + printf( "Networks have different number of latches.\n" ); + return 0; + } + // for each PI of pNet1 find corresponding PI of pNet2 and reorder them + Abc_NtkForEachBox( pNtk1, pObj1, i ) + { + if ( strcmp( Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ) != 0 ) + { + printf( "Box #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", + i, Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares the signals of the networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb ) +{ + Abc_NtkOrderObjsByName( pNtk1, fComb ); + Abc_NtkOrderObjsByName( pNtk2, fComb ); + if ( !Abc_NtkComparePis( pNtk1, pNtk2, fComb ) ) + return 0; + if ( !fOnlyPis ) + { + if ( !Abc_NtkCompareBoxes( pNtk1, pNtk2, fComb ) ) + return 0; + if ( !Abc_NtkComparePos( pNtk1, pNtk2, fComb ) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if the network hierachy contains a cycle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsAcyclicHierarchy_rec( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNext; + Abc_Obj_t * pObj; + int i; + // return if visited + if ( pNtk->fHieVisited ) + return 1; + pNtk->fHieVisited = 1; + // return if black box + if ( Abc_NtkHasBlackbox(pNtk) ) + return 1; + assert( Abc_NtkIsNetlist(pNtk) ); + // go through all the children networks + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + pNtkNext = pObj->pData; + assert( pNtkNext != NULL ); + if ( pNtkNext->fHiePath ) + return 0; + pNtk->fHiePath = 1; + if ( !Abc_NtkIsAcyclicHierarchy_rec( pNtkNext ) ) + return 0; + pNtk->fHiePath = 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if the network hierachy contains a cycle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pTemp; + int i, RetValue; + assert( Abc_NtkIsNetlist(pNtk) && pNtk->pDesign ); + // clear the modules + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pTemp, i ) + pTemp->fHieVisited = pTemp->fHiePath = 0; + // traverse + pNtk->fHiePath = 1; + RetValue = Abc_NtkIsAcyclicHierarchy_rec( pNtk ); + pNtk->fHiePath = 0; + // clear the modules + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pTemp, i ) + pTemp->fHieVisited = pTemp->fHiePath = 0; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if CI names are repeated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkNamesCompare( char ** pName1, char ** pName2 ) +{ + return strcmp( *pName1, *pName2 ); +} + +/**Function************************************************************* + + Synopsis [Returns 0 if CI names are repeated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNames; + Abc_Obj_t * pObj; + int i, fRetValue = 1; + assert( !Abc_NtkIsNetlist(pNtk) ); + vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Vec_PtrPush( vNames, Abc_ObjName(pObj) ); + Vec_PtrSort( vNames, Abc_NtkNamesCompare ); + for ( i = 1; i < Abc_NtkCiNum(pNtk); i++ ) + if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) ) + { + printf( "Abc_NtkCheck: Repeated CI names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ); + fRetValue = 0; + } + Vec_PtrFree( vNames ); + return fRetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if CO names are repeated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNames; + Abc_Obj_t * pObj; + int i, fRetValue = 1; + assert( !Abc_NtkIsNetlist(pNtk) ); + vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vNames, Abc_ObjName(pObj) ); + Vec_PtrSort( vNames, Abc_NtkNamesCompare ); + for ( i = 1; i < Abc_NtkCoNum(pNtk); i++ ) + { +// printf( "%s\n", Vec_PtrEntry(vNames,i) ); + if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) ) + { + printf( "Abc_NtkCheck: Repeated CO names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ); + fRetValue = 0; + } + } + Vec_PtrFree( vNames ); + return fRetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if there is a pair of CI/CO with the same name and logic in between.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pObjCi; + int i, nCiId, fRetValue = 1; + assert( !Abc_NtkIsNetlist(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + nCiId = Nm_ManFindIdByNameTwoTypes( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); + if ( nCiId == -1 ) + continue; + pObjCi = Abc_NtkObj( pNtk, nCiId ); + assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) ); + if ( Abc_ObjFanin0(pObj) != pObjCi ) + { + printf( "Abc_NtkCheck: A CI/CO pair share the name (%s) but do not link directly.\n", Abc_ObjName(pObj) ); + fRetValue = 0; + } + } + return fRetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcDfs.c b/abc70930/src/base/abc/abcDfs.c new file mode 100644 index 00000000..39e985c0 --- /dev/null +++ b/abc70930/src/base/abc/abcDfs.c @@ -0,0 +1,1264 @@ +/**CFile**************************************************************** + + FileName [abcDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures that use depth-first search.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) + return; + assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + { +// pFanin = Abc_ObjFanin( pNode, Abc_ObjFaninNum(pNode)-1-i ); + Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); + } + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving CIs and CO. + However it marks with the current TravId both CIs and COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); + } + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDfs_rec( pObj, vNodes ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out PIs, POs and latches.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + for ( i = 0; i < nNodes; i++ ) + { + if ( Abc_ObjIsCo(ppNodes[i]) ) + { + Abc_NodeSetTravIdCurrent(ppNodes[i]); + Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(ppNodes[i])), vNodes ); + } + else if ( Abc_ObjIsNode(ppNodes[i]) ) + Abc_NtkDfs_rec( ppNodes[i], vNodes ); + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCo(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + pNode = Abc_ObjFanout0Ntk(pNode); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_NtkDfsReverse_rec( pFanout, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the reverse DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanout; + int i, k; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachCi( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + pObj = Abc_ObjFanout0Ntk(pObj); + Abc_ObjForEachFanout( pObj, pFanout, k ) + Abc_NtkDfsReverse_rec( pFanout, vNodes ); + } + // add constant nodes in the end + if ( !Abc_NtkIsStrash(pNtk) ) + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( Abc_NodeIsConst(pObj) ) + Vec_PtrPush( vNodes, pObj ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsReverseNodes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCo(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + pNode = Abc_ObjFanout0Ntk(pNode); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_NtkDfsReverseNodes_rec( pFanout, vNodes ); + // add the node after the fanins have been added +// Vec_PtrPush( vNodes, pNode ); + Vec_PtrFillExtra( vNodes, pNode->Level + 1, NULL ); + pNode->pCopy = Vec_PtrEntry( vNodes, pNode->Level ); + Vec_PtrWriteEntry( vNodes, pNode->Level, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the levelized array of TFO nodes.] + + Description [Collects the levelized array of internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanout; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrStart( Abc_AigLevel(pNtk) + 1 ); + for ( i = 0; i < nNodes; i++ ) + { + pObj = ppNodes[i]; + assert( Abc_ObjIsCi(pObj) ); + Abc_NodeSetTravIdCurrent( pObj ); + pObj = Abc_ObjFanout0Ntk(pObj); + Abc_ObjForEachFanout( pObj, pFanout, k ) + Abc_NtkDfsReverseNodes_rec( pFanout, vNodes ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the levelized array of TFO nodes.] + + Description [Collects the levelized array of internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId. + Collects only the nodes whose support does not exceed the set of given CI nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanout, * pFanin; + int i, k, m, nLevels; + // set the levels + nLevels = Abc_NtkLevel( pNtk ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrStart( nLevels + 2 ); + for ( i = 0; i < nNodes; i++ ) + { + pObj = ppNodes[i]; + assert( Abc_ObjIsCi(pObj) ); + Abc_NodeSetTravIdCurrent( pObj ); + // add to the array + assert( pObj->Level == 0 ); + pObj->pCopy = Vec_PtrEntry( vNodes, pObj->Level ); + Vec_PtrWriteEntry( vNodes, pObj->Level, pObj ); + } + // iterate through the levels + for ( i = 0; i <= nLevels; i++ ) + { + // iterate through the nodes on each level + for ( pObj = Vec_PtrEntry(vNodes, i); pObj; pObj = pObj->pCopy ) + { + // iterate through the fanouts of each node + Abc_ObjForEachFanout( pObj, pFanout, k ) + { + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pFanout) ) + continue; + // visit the fanins of this fanout + Abc_ObjForEachFanin( pFanout, pFanin, m ) + { + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + break; + } + if ( m < Abc_ObjFaninNum(pFanout) ) + continue; + // all fanins are already collected + + // mark the node as visited + Abc_NodeSetTravIdCurrent( pFanout ); + // handle the COs + if ( Abc_ObjIsCo(pFanout) ) + pFanout->Level = nLevels + 1; + // add to the array + pFanout->pCopy = Vec_PtrEntry( vNodes, pFanout->Level ); + Vec_PtrWriteEntry( vNodes, pFanout->Level, pFanout ); + // handle the COs + if ( Abc_ObjIsCo(pFanout) ) + pFanout->Level = 0; + } + } + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsSeq_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkDfsSeq_rec( pFanin, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes and latches reachable from POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + assert( !Abc_NtkIsNetlist(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDfsSeq_rec( pObj, vNodes ); + // mark the PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDfsSeq_rec( pObj, vNodes ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsSeqReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin of the node + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_NtkDfsSeqReverse_rec( pFanout, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes and latches reachable from POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + assert( !Abc_NtkIsNetlist(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDfsSeqReverse_rec( pObj, vNodes ); + // mark the logic feeding into POs + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDfsSeq_rec( pObj, vNodes ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Iterative version of the DFS procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfs_iter( Vec_Ptr_t * vStack, Abc_Obj_t * pRoot, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pNode, * pFanin; + int iFanin; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pRoot ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pRoot ); + // skip the CI + if ( Abc_ObjIsCi(pRoot) || (Abc_NtkIsStrash(pRoot->pNtk) && Abc_AigNodeIsConst(pRoot)) ) + return; + // add the CI + Vec_PtrClear( vStack ); + Vec_PtrPush( vStack, pRoot ); + Vec_PtrPush( vStack, (void *)0 ); + while ( Vec_PtrSize(vStack) > 0 ) + { + // get the node and its fanin + iFanin = (int)Vec_PtrPop(vStack); + pNode = Vec_PtrPop(vStack); + assert( !Abc_ObjIsNet(pNode) ); + // add it to the array of nodes if we finished + if ( iFanin == Abc_ObjFaninNum(pNode) ) + { + Vec_PtrPush( vNodes, pNode ); + continue; + } + // explore the next fanin + Vec_PtrPush( vStack, pNode ); + Vec_PtrPush( vStack, (void *)(iFanin+1) ); + // get the fanin + pFanin = Abc_ObjFanin0Ntk( Abc_ObjFanin(pNode,iFanin) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pFanin ) ) + continue; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pFanin ); + // skip the CI + if ( Abc_ObjIsCi(pFanin) || (Abc_NtkIsStrash(pFanin->pNtk) && Abc_AigNodeIsConst(pFanin)) ) + continue; + Vec_PtrPush( vStack, pFanin ); + Vec_PtrPush( vStack, (void *)0 ); + } +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving CIs and CO. + However it marks with the current TravId both CIs and COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ) +{ + Vec_Ptr_t * vNodes, * vStack; + Abc_Obj_t * pObj; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 1000 ); + vStack = Vec_PtrAlloc( 1000 ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkDfs_iter( vStack, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); + } + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDfs_iter( vStack, pObj, vNodes ); + } + Vec_PtrFree( vStack ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsHie_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pObj ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NtkDfsHie_rec( pFanin, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of all objects.] + + Description [This procedure collects everything from POs to PIs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDfsHie_rec( pObj, vNodes ); + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDfs_rec( pObj, vNodes ); + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the ordering of nodes is DFS.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pFanin; + int i, k; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // mark the CIs + Abc_NtkForEachCi( pNtk, pNode, i ) + Abc_NodeSetTravIdCurrent( pNode ); + // go through the nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // check the fanins of the node + Abc_ObjForEachFanin( pNode, pFanin, k ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + return 0; + // check the choices of the node + if ( Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsChoice(pNode) ) + for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + return 0; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // collect the CI + if ( Abc_ObjIsCi(pNode) || Abc_ObjFaninNum(pNode) == 0 ) + { + Vec_PtrPush( vNodes, pNode ); + return; + } + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkNodeSupport_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); +} + +/**Function************************************************************* + + Synopsis [Returns the set of CI nodes in the support of the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_NtkNodeSupport_rec( Abc_ObjFanin0(pNode), vNodes ); + // add unused CIs + Abc_NtkForEachCi( pNtk, pNode, i ) + if ( !Abc_NodeIsTravIdCurrent( pNode ) ) + Vec_PtrPush( vNodes, pNode ); + assert( Vec_PtrSize(vNodes) == Abc_NtkCiNum(pNtk) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the set of CI nodes in the support of the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + for ( i = 0; i < nNodes; i++ ) + if ( Abc_ObjIsCo(ppNodes[i]) ) + Abc_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes ); + else + Abc_NtkNodeSupport_rec( ppNodes[i], vNodes ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the PI + if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_AigDfs_rec( pFanin, vNodes ); + // visit the equivalent nodes + if ( Abc_AigNodeIsChoice( pNode ) ) + for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData ) + Abc_AigDfs_rec( pFanin, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes ); + Abc_NodeSetTravIdCurrent( pNode ); + if ( fCollectCos ) + Vec_PtrPush( vNodes, pNode ); + } + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( !Abc_NodeIsTravIdCurrent(pNode) ) + Abc_AigDfs_rec( pNode, vNodes ); + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Collects nodes in the DFS manner by level.] + + Description [The number of levels should be set!!!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels ) +{ + Abc_Obj_t * pFanout; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the terminals + if ( Abc_ObjIsCo(pNode) ) + return; + assert( Abc_ObjIsNode(pNode) ); + // add the node to the structure + Vec_VecPush( vLevels, pNode->Level, pNode ); + // visit the TFO + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_DfsLevelizedTfo_rec( pFanout, vLevels ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes in the DFS manner by level.] + + Description [The number of levels should be set!!!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi ) +{ + Vec_Vec_t * vLevels; + Abc_Obj_t * pFanout; + int i; + assert( fTfi == 0 ); + assert( !Abc_NtkIsNetlist(pNode->pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNode->pNtk ); + vLevels = Vec_VecAlloc( 100 ); + if ( Abc_ObjIsNode(pNode) ) + Abc_DfsLevelizedTfo_rec( pNode, vLevels ); + else + { + assert( Abc_ObjIsCi(pNode) ); + Abc_NodeSetTravIdCurrent( pNode ); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_DfsLevelizedTfo_rec( pFanout, vLevels ); + } + return vLevels; +} + + +/**Function************************************************************* + + Synopsis [Recursively counts the number of logic levels of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevel_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNext; + int i, Level; + assert( !Abc_ObjIsNet(pNode) ); + // skip the PI + if ( Abc_ObjIsCi(pNode) ) + return pNode->Level; + assert( Abc_ObjIsNode( pNode ) ); + // if this node is already visited, return + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return pNode->Level; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + pNode->Level = 0; + Abc_ObjForEachFanin( pNode, pNext, i ) + { + Level = Abc_NtkLevel_rec( Abc_ObjFanin0Ntk(pNext) ); + if ( pNode->Level < (unsigned)Level ) + pNode->Level = Level; + } + if ( Abc_ObjFaninNum(pNode) > 0 ) + pNode->Level++; + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Recursively counts the number of logic levels of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevelReverse_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNext; + int i, Level; + assert( !Abc_ObjIsNet(pNode) ); + // skip the PI + if ( Abc_ObjIsCo(pNode) ) + return pNode->Level; + assert( Abc_ObjIsNode( pNode ) ); + // if this node is already visited, return + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return pNode->Level; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + pNode->Level = 0; + Abc_ObjForEachFanout( pNode, pNext, i ) + { + Level = Abc_NtkLevelReverse_rec( Abc_ObjFanout0Ntk(pNext) ); + if ( pNode->Level < (unsigned)Level ) + pNode->Level = Level; + } + if ( Abc_ObjFaninNum(pNode) > 0 ) + pNode->Level++; + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevel( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, LevelsMax; + // set the CI levels to zero + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->Level = 0; + // perform the traversal + LevelsMax = 0; + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Abc_NtkLevel_rec( pNode ); + if ( LevelsMax < (int)pNode->Level ) + LevelsMax = (int)pNode->Level; + } + return LevelsMax; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, LevelsMax; + // set the CO levels to zero + Abc_NtkForEachCo( pNtk, pNode, i ) + pNode->Level = 0; + // perform the traversal + LevelsMax = 0; + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Abc_NtkLevelReverse_rec( pNode ); + if ( LevelsMax < (int)pNode->Level ) + LevelsMax = (int)pNode->Level; + } + return LevelsMax; +} + + +/**Function************************************************************* + + Synopsis [Recursively detects combinational loops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + Abc_Obj_t * pFanin; + int fAcyclic, i; + assert( !Abc_ObjIsNet(pNode) ); + if ( Abc_ObjIsCi(pNode) || Abc_ObjIsBox(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) + return 1; + assert( Abc_ObjIsNode(pNode) ); + // make sure the node is not visited + assert( !Abc_NodeIsTravIdPrevious(pNode) ); + // check if the node is part of the combinational loop + if ( Abc_NodeIsTravIdCurrent(pNode) ) + { + fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) ); + fprintf( stdout, "Node \"%s\" is encountered twice on the following path to the COs:\n", Abc_ObjName(pNode) ); + return 0; + } + // mark this node as a node on the current path + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + pFanin = Abc_ObjFanin0Ntk(pFanin); + // make sure there is no mixing of networks + assert( pFanin->pNtk == pNode->pNtk ); + // check if the fanin is visited + if ( Abc_NodeIsTravIdPrevious(pFanin) ) + continue; + // traverse the fanin's cone searching for the loop + if ( fAcyclic = Abc_NtkIsAcyclic_rec(pFanin) ) + continue; + // return as soon as the loop is detected + fprintf( stdout, " %s ->", Abc_ObjName(pFanin) ); + return 0; + } + // visit choices + if ( Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsChoice(pNode) ) + { + for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData ) + { + // check if the fanin is visited + if ( Abc_NodeIsTravIdPrevious(pFanin) ) + continue; + // traverse the fanin's cone searching for the loop + if ( fAcyclic = Abc_NtkIsAcyclic_rec(pFanin) ) + continue; + // return as soon as the loop is detected + fprintf( stdout, " %s", Abc_ObjName(pFanin) ); + fprintf( stdout, " (choice of %s) -> ", Abc_ObjName(pNode) ); + return 0; + } + } + // mark this node as a visited node + Abc_NodeSetTravIdPrevious( pNode ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Detects combinational loops.] + + Description [This procedure is based on the idea suggested by Donald Chai. + As we traverse the network and visit the nodes, we need to distinquish + three types of nodes: (1) those that are visited for the first time, + (2) those that have been visited in this traversal but are currently not + on the traversal path, (3) those that have been visited and are currently + on the travesal path. When the node of type (3) is encountered, it means + that there is a combinational loop. To mark the three types of nodes, + two new values of the traversal IDs are used.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int fAcyclic, i; + // set the traversal ID for this DFS ordering + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkIncrementTravId( pNtk ); + // pNode->TravId == pNet->nTravIds means "pNode is on the path" + // pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path" + // pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited" + // traverse the network to detect cycles + fAcyclic = 1; + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode)); + if ( Abc_NodeIsTravIdPrevious(pNode) ) + continue; + // traverse the output logic cone + if ( fAcyclic = Abc_NtkIsAcyclic_rec(pNode) ) + continue; + // stop as soon as the first loop is detected + fprintf( stdout, " CO \"%s\"\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + break; + } + return fAcyclic; +} + + +/**Function************************************************************* + + Synopsis [Analyses choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeSetChoiceLevel_rec( Abc_Obj_t * pNode, int fMaximum ) +{ + Abc_Obj_t * pTemp; + int Level1, Level2, Level, LevelE; + // skip the visited node + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return (int)pNode->pCopy; + Abc_NodeSetTravIdCurrent( pNode ); + // compute levels of the children nodes + Level1 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pNode), fMaximum ); + Level2 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin1(pNode), fMaximum ); + Level = 1 + ABC_MAX( Level1, Level2 ); + if ( pNode->pData ) + { + LevelE = Abc_NodeSetChoiceLevel_rec( pNode->pData, fMaximum ); + if ( fMaximum ) + Level = ABC_MAX( Level, LevelE ); + else + Level = ABC_MIN( Level, LevelE ); + // set the level of all equivalent nodes to be the same minimum + for ( pTemp = pNode->pData; pTemp; pTemp = pTemp->pData ) + pTemp->pCopy = (void *)Level; + } + pNode->pCopy = (void *)Level; + return Level; +} + +/**Function************************************************************* + + Synopsis [Resets the levels of the nodes in the choice graph.] + + Description [Makes the level of the choice nodes to be equal to the + maximum of the level of the nodes in the equivalence class. This way + sorting by level leads to the reverse topological order, which is + needed for the required time computation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigSetChoiceLevels( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i, LevelMax, LevelCur; + assert( Abc_NtkIsStrash(pNtk) ); + // set the new travid counter + Abc_NtkIncrementTravId( pNtk ); + // set levels of the CI and constant + Abc_NtkForEachCi( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + pObj->pCopy = NULL; + } + pObj = Abc_AigConst1( pNtk ); + Abc_NodeSetTravIdCurrent( pObj ); + pObj->pCopy = NULL; + // set levels of all other nodes + LevelMax = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + LevelCur = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pObj), 1 ); + LevelMax = ABC_MAX( LevelMax, LevelCur ); + } + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Returns nodes by level from the smallest to the largest.] + + Description [Correctly handles the case of choice nodes, by first + spreading them out across several levels and then collecting.] + + SideEffects [What happens with dangling nodes???] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ) +{ + Vec_Ptr_t * vNodes, * vLevels; + Abc_Obj_t * pNode, ** ppHead; + int LevelMax, i; + assert( Abc_NtkIsStrash(pNtk) ); + // set the correct levels + Abc_NtkCleanCopy( pNtk ); + LevelMax = Abc_AigSetChoiceLevels( pNtk ); + // relink nodes by level + vLevels = Vec_PtrStart( LevelMax + 1 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + ppHead = ((Abc_Obj_t **)vLevels->pArray) + (int)pNode->pCopy; + pNode->pCopy = *ppHead; + *ppHead = pNode; + } + // recollect nodes + vNodes = Vec_PtrStart( Abc_NtkNodeNum(pNtk) ); + Vec_PtrForEachEntryStart( vLevels, pNode, i, !fCollectCis ) + for ( ; pNode; pNode = pNode->pCopy ) + Vec_PtrPush( vNodes, pNode ); + Vec_PtrFree( vLevels ); + return vNodes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcFanio.c b/abc70930/src/base/abc/abcFanio.c new file mode 100644 index 00000000..c8536695 --- /dev/null +++ b/abc70930/src/base/abc/abcFanio.c @@ -0,0 +1,336 @@ +/**CFile**************************************************************** + + FileName [abcFanio.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Various procedures to connect fanins/fanouts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntPushMem( Extra_MmStep_t * pMemMan, Vec_Int_t * p, int Entry ) +{ + if ( p->nSize == p->nCap ) + { + int * pArray; + int i; + + if ( p->nSize == 0 ) + p->nCap = 1; + if ( pMemMan ) + pArray = (int *)Extra_MmStepEntryFetch( pMemMan, p->nCap * 8 ); + else + pArray = ALLOC( int, p->nCap * 2 ); + if ( p->pArray ) + { + for ( i = 0; i < p->nSize; i++ ) + pArray[i] = p->pArray[i]; + if ( pMemMan ) + Extra_MmStepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 ); + else + free( p->pArray ); + } + p->nCap *= 2; + p->pArray = pArray; + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [Creates fanout/fanin relationship between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pFaninR = Abc_ObjRegular(pFanin); + assert( !Abc_ObjIsComplement(pObj) ); + assert( pObj->pNtk == pFaninR->pNtk ); + assert( pObj->Id >= 0 && pFaninR->Id >= 0 ); + Vec_IntPushMem( pObj->pNtk->pMmStep, &pObj->vFanins, pFaninR->Id ); + Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninR->vFanouts, pObj->Id ); + if ( Abc_ObjIsComplement(pFanin) ) + Abc_ObjSetFaninC( pObj, Abc_ObjFaninNum(pObj)-1 ); + if ( Abc_ObjIsNet(pObj) && Abc_ObjFaninNum(pObj) > 1 ) + { + int x = 0; + } +// printf( "Adding fanin of %s ", Abc_ObjName(pObj) ); +// printf( "to be %s\n", Abc_ObjName(pFanin) ); +} + + +/**Function************************************************************* + + Synopsis [Destroys fanout/fanin relationship between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +{ + assert( !Abc_ObjIsComplement(pObj) ); + assert( !Abc_ObjIsComplement(pFanin) ); + assert( pObj->pNtk == pFanin->pNtk ); + assert( pObj->Id >= 0 && pFanin->Id >= 0 ); + if ( !Vec_IntRemove( &pObj->vFanins, pFanin->Id ) ) + { + printf( "The obj %d is not found among the fanins of obj %d ...\n", pFanin->Id, pObj->Id ); + return; + } + if ( !Vec_IntRemove( &pFanin->vFanouts, pObj->Id ) ) + { + printf( "The obj %d is not found among the fanouts of obj %d ...\n", pObj->Id, pFanin->Id ); + return; + } +} + + +/**Function************************************************************* + + Synopsis [Destroys fanout/fanin relationship between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ) +{ + Vec_Int_t * vFaninsOld; + Abc_Obj_t * pFanin; + int k; + // remove old fanins + vFaninsOld = &pObj->vFanins; + for ( k = vFaninsOld->nSize - 1; k >= 0; k-- ) + { + pFanin = Abc_NtkObj( pObj->pNtk, vFaninsOld->pArray[k] ); + Abc_ObjDeleteFanin( pObj, pFanin ); + } + pObj->fCompl0 = 0; + pObj->fCompl1 = 0; + assert( vFaninsOld->nSize == 0 ); +} + +/**Function************************************************************* + + Synopsis [Replaces a fanin of the node.] + + Description [The node is pObj. An old fanin of this node (pFaninOld) has to be + replaced by a new fanin (pFaninNew). Assumes that the node and the old fanin + are not complemented. The new fanin can be complemented. In this case, the + polarity of the new fanin will change, compared to the polarity of the old fanin.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew ) +{ + Abc_Obj_t * pFaninNewR = Abc_ObjRegular(pFaninNew); + int iFanin;//, nLats;//, fCompl; + assert( !Abc_ObjIsComplement(pObj) ); + assert( !Abc_ObjIsComplement(pFaninOld) ); + assert( pFaninOld != pFaninNewR ); +// assert( pObj != pFaninOld ); +// assert( pObj != pFaninNewR ); + assert( pObj->pNtk == pFaninOld->pNtk ); + assert( pObj->pNtk == pFaninNewR->pNtk ); + if ( (iFanin = Vec_IntFind( &pObj->vFanins, pFaninOld->Id )) == -1 ) + { + printf( "Node %s is not among", Abc_ObjName(pFaninOld) ); + printf( " the fanins of node %s...\n", Abc_ObjName(pObj) ); + return; + } + + // remember the attributes of the old fanin +// fCompl = Abc_ObjFaninC(pObj, iFanin); + // replace the old fanin entry by the new fanin entry (removes attributes) + Vec_IntWriteEntry( &pObj->vFanins, iFanin, pFaninNewR->Id ); + // set the attributes of the new fanin +// if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) ) +// Abc_ObjSetFaninC( pObj, iFanin ); + if ( Abc_ObjIsComplement(pFaninNew) ) + Abc_ObjXorFaninC( pObj, iFanin ); + +// if ( Abc_NtkIsSeq(pObj->pNtk) && (nLats = Seq_ObjFaninL(pObj, iFanin)) ) +// Seq_ObjSetFaninL( pObj, iFanin, nLats ); + // update the fanout of the fanin + if ( !Vec_IntRemove( &pFaninOld->vFanouts, pObj->Id ) ) + { + printf( "Node %s is not among", Abc_ObjName(pObj) ); + printf( " the fanouts of its old fanin %s...\n", Abc_ObjName(pFaninOld) ); +// return; + } + Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Inserts one-input node of the type specified between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ) +{ + Abc_Obj_t * pNodeNew; + int iFanoutIndex, iFaninIndex; + // find pNodeOut among the fanouts of pNodeIn + if ( (iFanoutIndex = Vec_IntFind( &pNodeIn->vFanouts, pNodeOut->Id )) == -1 ) + { + printf( "Node %s is not among", Abc_ObjName(pNodeOut) ); + printf( " the fanouts of node %s...\n", Abc_ObjName(pNodeIn) ); + return NULL; + } + // find pNodeIn among the fanins of pNodeOut + if ( (iFaninIndex = Vec_IntFind( &pNodeOut->vFanins, pNodeIn->Id )) == -1 ) + { + printf( "Node %s is not among", Abc_ObjName(pNodeIn) ); + printf( " the fanins of node %s...\n", Abc_ObjName(pNodeOut) ); + return NULL; + } + // create the new node + pNodeNew = Abc_NtkCreateObj( pNodeIn->pNtk, Type ); + // add pNodeIn as fanin and pNodeOut as fanout + Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanins, pNodeIn->Id ); + Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanouts, pNodeOut->Id ); + // update the fanout of pNodeIn + Vec_IntWriteEntry( &pNodeIn->vFanouts, iFanoutIndex, pNodeNew->Id ); + // update the fanin of pNodeOut + Vec_IntWriteEntry( &pNodeOut->vFanins, iFaninIndex, pNodeNew->Id ); + return pNodeNew; +} + +/**Function************************************************************* + + Synopsis [Transfers fanout from the old node to the new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjTransferFanout( Abc_Obj_t * pNodeFrom, Abc_Obj_t * pNodeTo ) +{ + Vec_Ptr_t * vFanouts; + int nFanoutsOld, i; + assert( !Abc_ObjIsComplement(pNodeFrom) ); + assert( !Abc_ObjIsComplement(pNodeTo) ); + assert( !Abc_ObjIsPo(pNodeFrom) && !Abc_ObjIsPo(pNodeTo) ); + assert( pNodeFrom->pNtk == pNodeTo->pNtk ); + assert( pNodeFrom != pNodeTo ); + assert( Abc_ObjFanoutNum(pNodeFrom) > 0 ); + // get the fanouts of the old node + nFanoutsOld = Abc_ObjFanoutNum(pNodeTo); + vFanouts = Vec_PtrAlloc( nFanoutsOld ); + Abc_NodeCollectFanouts( pNodeFrom, vFanouts ); + // patch the fanin of each of them + for ( i = 0; i < vFanouts->nSize; i++ ) + Abc_ObjPatchFanin( vFanouts->pArray[i], pNodeFrom, pNodeTo ); + assert( Abc_ObjFanoutNum(pNodeFrom) == 0 ); + assert( Abc_ObjFanoutNum(pNodeTo) == nFanoutsOld + vFanouts->nSize ); + Vec_PtrFree( vFanouts ); +} + +/**Function************************************************************* + + Synopsis [Replaces the node by a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjReplace( Abc_Obj_t * pNodeOld, Abc_Obj_t * pNodeNew ) +{ + assert( !Abc_ObjIsComplement(pNodeOld) ); + assert( !Abc_ObjIsComplement(pNodeNew) ); + assert( pNodeOld->pNtk == pNodeNew->pNtk ); + assert( pNodeOld != pNodeNew ); + assert( Abc_ObjFanoutNum(pNodeOld) > 0 ); + // transfer the fanouts to the old node + Abc_ObjTransferFanout( pNodeOld, pNodeNew ); + // remove the old node + Abc_NtkDeleteObj_rec( pNodeOld, 1 ); +} + +/**Function************************************************************* + + Synopsis [Returns the index of the fanin in the fanin list of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pObj; + int i; + Abc_ObjForEachFanin( pFanout, pObj, i ) + if ( pObj == pFanin ) + return i; + return -1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcFunc.c b/abc70930/src/base/abc/abcFunc.c new file mode 100644 index 00000000..f3297d8f --- /dev/null +++ b/abc70930/src/base/abc/abcFunc.c @@ -0,0 +1,1154 @@ +/**CFile**************************************************************** + + FileName [abcFunc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Transformations between different functionality representations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFunc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_MUX_CUBES 100000 + +static int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); +static DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot); +static Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts the network from SOP to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + DdManager * dd; + int nFaninsMax, i; + + assert( Abc_NtkHasSop(pNtk) ); + + // start the functionality manager + nFaninsMax = Abc_NtkGetFaninMax( pNtk ); + if ( nFaninsMax == 0 ) + printf( "Warning: The network has only constant nodes.\n" ); + + dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + // convert each node from SOP to BDD + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + pNode->pData = Abc_ConvertSopToBdd( dd, pNode->pData ); + if ( pNode->pData == NULL ) + { + printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" ); + return 0; + } + Cudd_Ref( pNode->pData ); + } + + Extra_MmFlexStop( pNtk->pManFunc ); + pNtk->pManFunc = dd; + + // update the network type + pNtk->ntkFunc = ABC_FUNC_BDD; + return 1; +} + +/**Function************************************************************* + + Synopsis [Converts the node from SOP to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop ) +{ + DdNode * bSum, * bCube, * bTemp, * bVar; + char * pCube; + int nVars, Value, v; + + // start the cover + nVars = Abc_SopGetVarNum(pSop); + bSum = Cudd_ReadLogicZero(dd); Cudd_Ref( bSum ); + if ( Abc_SopIsExorType(pSop) ) + { + for ( v = 0; v < nVars; v++ ) + { + bSum = Cudd_bddXor( dd, bTemp = bSum, Cudd_bddIthVar(dd, v) ); Cudd_Ref( bSum ); + Cudd_RecursiveDeref( dd, bTemp ); + } + } + else + { + // check the logic function of the node + Abc_SopForEachCube( pSop, nVars, pCube ) + { + bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); + Abc_CubeForEachVar( pCube, Value, v ) + { + if ( Value == '0' ) + bVar = Cudd_Not( Cudd_bddIthVar( dd, v ) ); + else if ( Value == '1' ) + bVar = Cudd_bddIthVar( dd, v ); + else + continue; + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + bSum = Cudd_bddOr( dd, bTemp = bSum, bCube ); + Cudd_Ref( bSum ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + } + // complement the result if necessary + bSum = Cudd_NotCond( bSum, !Abc_SopGetPhase(pSop) ); + Cudd_Deref( bSum ); + return bSum; +} + +/**Function************************************************************* + + Synopsis [Removes complemented SOP covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) +{ + DdManager * dd; + DdNode * bFunc; + Vec_Str_t * vCube; + Abc_Obj_t * pNode; + int nFaninsMax, fFound, i; + + assert( Abc_NtkHasSop(pNtk) ); + + // check if there are nodes with complemented SOPs + fFound = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_SopIsComplement(pNode->pData) ) + { + fFound = 1; + break; + } + if ( !fFound ) + return; + + // start the BDD package + nFaninsMax = Abc_NtkGetFaninMax( pNtk ); + if ( nFaninsMax == 0 ) + printf( "Warning: The network has only constant nodes.\n" ); + dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + // change the cover of negated nodes + vCube = Vec_StrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_SopIsComplement(pNode->pData) ) + { + bFunc = Abc_ConvertSopToBdd( dd, pNode->pData ); Cudd_Ref( bFunc ); + pNode->pData = Abc_ConvertBddToSop( pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, 1 ); + Cudd_RecursiveDeref( dd, bFunc ); + assert( !Abc_SopIsComplement(pNode->pData) ); + } + Vec_StrFree( vCube ); + Extra_StopManager( dd ); +} + + + + + +/**Function************************************************************* + + Synopsis [Converts the network from BDD to SOP representation.] + + Description [If the flag is set to 1, forces the direct phase of all covers.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ) +{ + Abc_Obj_t * pNode; + Extra_MmFlex_t * pManNew; + DdManager * dd = pNtk->pManFunc; + DdNode * bFunc; + Vec_Str_t * vCube; + int i, fMode; + + if ( fDirect ) + fMode = 1; + else + fMode = -1; + + assert( Abc_NtkHasBdd(pNtk) ); + if ( dd->size > 0 ) + Cudd_zddVarsFromBddVars( dd, 2 ); + // create the new manager + pManNew = Extra_MmFlexStart(); + + // go through the objects + vCube = Vec_StrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + bFunc = pNode->pData; + pNode->pNext = (Abc_Obj_t *)Abc_ConvertBddToSop( pManNew, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, fMode ); + if ( pNode->pNext == NULL ) + { + Extra_MmFlexStop( pManNew ); + Abc_NtkCleanNext( pNtk ); +// printf( "Converting from BDDs to SOPs has failed.\n" ); + Vec_StrFree( vCube ); + return 0; + } + } + Vec_StrFree( vCube ); + + // update the network type + pNtk->ntkFunc = ABC_FUNC_SOP; + // set the new manager + pNtk->pManFunc = pManNew; + // transfer from next to data + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Cudd_RecursiveDeref( dd, pNode->pData ); + pNode->pData = pNode->pNext; + pNode->pNext = NULL; + } + + // check for remaining references in the package + Extra_StopManager( dd ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Converts the node from BDD to SOP representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode ) +{ + int fVerify = 0; + char * pSop; + DdNode * bFuncNew, * bCover, * zCover, * zCover0, * zCover1; + int nCubes, nCubes0, nCubes1, fPhase; + + assert( bFuncOn == bFuncOnDc || Cudd_bddLeq( dd, bFuncOn, bFuncOnDc ) ); + if ( Cudd_IsConstant(bFuncOn) || Cudd_IsConstant(bFuncOnDc) ) + { + if ( fMode == -1 ) // if the phase is not known, write constant 1 + fMode = 1; + Vec_StrFill( vCube, nFanins, '-' ); + Vec_StrPush( vCube, '\0' ); + if ( pMan ) + pSop = Extra_MmFlexEntryFetch( pMan, nFanins + 4 ); + else + pSop = ALLOC( char, nFanins + 4 ); + if ( bFuncOn == Cudd_ReadOne(dd) ) + sprintf( pSop, "%s %d\n", vCube->pArray, fMode ); + else + sprintf( pSop, "%s %d\n", vCube->pArray, !fMode ); + return pSop; + } + + + if ( fMode == -1 ) + { // try both phases + assert( fAllPrimes == 0 ); + + // get the ZDD of the negative polarity + bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover0 ); + Cudd_Ref( zCover0 ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + nCubes0 = Abc_CountZddCubes( dd, zCover0 ); + + // get the ZDD of the positive polarity + bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover1 ); + Cudd_Ref( zCover1 ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + nCubes1 = Abc_CountZddCubes( dd, zCover1 ); + + // compare the number of cubes + if ( nCubes1 <= nCubes0 ) + { // use positive polarity + nCubes = nCubes1; + zCover = zCover1; + Cudd_RecursiveDerefZdd( dd, zCover0 ); + fPhase = 1; + } + else + { // use negative polarity + nCubes = nCubes0; + zCover = zCover0; + Cudd_RecursiveDerefZdd( dd, zCover1 ); + fPhase = 0; + } + } + else if ( fMode == 0 ) + { + // get the ZDD of the negative polarity + if ( fAllPrimes ) + { + zCover = Extra_zddPrimes( dd, Cudd_Not(bFuncOnDc) ); + Cudd_Ref( zCover ); + } + else + { + bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover ); + Cudd_Ref( zCover ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + } + nCubes = Abc_CountZddCubes( dd, zCover ); + fPhase = 0; + } + else if ( fMode == 1 ) + { + // get the ZDD of the positive polarity + if ( fAllPrimes ) + { + zCover = Extra_zddPrimes( dd, bFuncOnDc ); + Cudd_Ref( zCover ); + } + else + { + bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover ); + Cudd_Ref( zCover ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + } + nCubes = Abc_CountZddCubes( dd, zCover ); + fPhase = 1; + } + else + { + assert( 0 ); + } + + if ( nCubes > ABC_MUX_CUBES ) + { + Cudd_RecursiveDerefZdd( dd, zCover ); + printf( "The number of cubes exceeded the predefined limit (%d).\n", ABC_MUX_CUBES ); + return NULL; + } + + // allocate memory for the cover + if ( pMan ) + pSop = Extra_MmFlexEntryFetch( pMan, (nFanins + 3) * nCubes + 1 ); + else + pSop = ALLOC( char, (nFanins + 3) * nCubes + 1 ); + pSop[(nFanins + 3) * nCubes] = 0; + // create the SOP + Vec_StrFill( vCube, nFanins, '-' ); + Vec_StrPush( vCube, '\0' ); + Abc_ConvertZddToSop( dd, zCover, pSop, nFanins, vCube, fPhase ); + Cudd_RecursiveDerefZdd( dd, zCover ); + + // verify + if ( fVerify ) + { + bFuncNew = Abc_ConvertSopToBdd( dd, pSop ); Cudd_Ref( bFuncNew ); + if ( bFuncOn == bFuncOnDc ) + { + if ( bFuncNew != bFuncOn ) + printf( "Verification failed.\n" ); + } + else + { + if ( !Cudd_bddLeq(dd, bFuncOn, bFuncNew) || !Cudd_bddLeq(dd, bFuncNew, bFuncOnDc) ) + printf( "Verification failed.\n" ); + } + Cudd_RecursiveDeref( dd, bFuncNew ); + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Derive the SOP from the ZDD representation of the cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertZddToSop_rec( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase, int * pnCubes ) +{ + DdNode * zC0, * zC1, * zC2; + int Index; + + if ( zCover == dd->zero ) + return; + if ( zCover == dd->one ) + { + char * pCube; + pCube = pSop + (*pnCubes) * (nFanins + 3); + sprintf( pCube, "%s %d\n", vCube->pArray, fPhase ); + (*pnCubes)++; + return; + } + Index = zCover->index/2; + assert( Index < nFanins ); + extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 ); + vCube->pArray[Index] = '0'; + Abc_ConvertZddToSop_rec( dd, zC0, pSop, nFanins, vCube, fPhase, pnCubes ); + vCube->pArray[Index] = '1'; + Abc_ConvertZddToSop_rec( dd, zC1, pSop, nFanins, vCube, fPhase, pnCubes ); + vCube->pArray[Index] = '-'; + Abc_ConvertZddToSop_rec( dd, zC2, pSop, nFanins, vCube, fPhase, pnCubes ); +} + +/**Function************************************************************* + + Synopsis [Derive the BDD for the function in the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ) +{ + int nCubes = 0; + Abc_ConvertZddToSop_rec( dd, zCover, pSop, nFanins, vCube, fPhase, &nCubes ); + return nCubes; +} + + +/**Function************************************************************* + + Synopsis [Computes the SOPs of the negative and positive phase of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ) +{ + assert( Abc_NtkHasBdd(pNode->pNtk) ); + *ppSop0 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 0 ); + *ppSop1 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 1 ); +} + + + + +/**Function************************************************************* + + Synopsis [Count the number of paths in the ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_CountZddCubes_rec( DdManager * dd, DdNode * zCover, int * pnCubes ) +{ + DdNode * zC0, * zC1, * zC2; + if ( zCover == dd->zero ) + return; + if ( zCover == dd->one ) + { + (*pnCubes)++; + return; + } + if ( (*pnCubes) > ABC_MUX_CUBES ) + return; + extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 ); + Abc_CountZddCubes_rec( dd, zC0, pnCubes ); + Abc_CountZddCubes_rec( dd, zC1, pnCubes ); + Abc_CountZddCubes_rec( dd, zC2, pnCubes ); +} + +/**Function************************************************************* + + Synopsis [Count the number of paths in the ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ) +{ + int nCubes = 0; + Abc_CountZddCubes_rec( dd, zCover, &nCubes ); + return nCubes; +} + + +/**Function************************************************************* + + Synopsis [Converts the network from SOP to AIG representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + Hop_Man_t * pMan; + int i; + + assert( Abc_NtkHasSop(pNtk) ); + + // start the functionality manager + pMan = Hop_ManStart(); + + // convert each node from SOP to BDD + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + pNode->pData = Abc_ConvertSopToAig( pMan, pNode->pData ); + if ( pNode->pData == NULL ) + { + printf( "Abc_NtkSopToAig: Error while converting SOP into AIG.\n" ); + return 0; + } + } + Extra_MmFlexStop( pNtk->pManFunc ); + pNtk->pManFunc = pMan; + + // update the network type + pNtk->ntkFunc = ABC_FUNC_AIG; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_ConvertSopToAigInternal( Hop_Man_t * pMan, char * pSop ) +{ + Hop_Obj_t * pAnd, * pSum; + int i, Value, nFanins; + char * pCube; + // get the number of variables + nFanins = Abc_SopGetVarNum(pSop); + // go through the cubes of the node's SOP + pSum = Hop_ManConst0(pMan); + Abc_SopForEachCube( pSop, nFanins, pCube ) + { + // create the AND of literals + pAnd = Hop_ManConst1(pMan); + Abc_CubeForEachVar( pCube, Value, i ) + { + if ( Value == '1' ) + pAnd = Hop_And( pMan, pAnd, Hop_IthVar(pMan,i) ); + else if ( Value == '0' ) + pAnd = Hop_And( pMan, pAnd, Hop_Not(Hop_IthVar(pMan,i)) ); + } + // add to the sum of cubes + pSum = Hop_Or( pMan, pSum, pAnd ); + } + // decide whether to complement the result + if ( Abc_SopIsComplement(pSop) ) + pSum = Hop_Not(pSum); + return pSum; +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ) +{ + extern Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop ); + int fUseFactor = 1; + // consider the constant node + if ( Abc_SopGetVarNum(pSop) == 0 ) + return Hop_NotCond( Hop_ManConst1(pMan), Abc_SopIsConst0(pSop) ); + // consider the special case of EXOR function + if ( Abc_SopIsExorType(pSop) ) + return Hop_NotCond( Hop_CreateExor(pMan, Abc_SopGetVarNum(pSop)), Abc_SopIsComplement(pSop) ); + // decide when to use factoring + if ( fUseFactor && Abc_SopGetVarNum(pSop) > 2 && Abc_SopGetCubeNum(pSop) > 1 ) + return Dec_GraphFactorSop( pMan, pSop ); + return Abc_ConvertSopToAigInternal( pMan, pSop ); +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + Hop_Man_t * pMan; + DdManager * dd; + int nFaninsMax, i; + + assert( Abc_NtkHasAig(pNtk) ); + + // start the functionality manager + nFaninsMax = Abc_NtkGetFaninMax( pNtk ); + if ( nFaninsMax == 0 ) + printf( "Warning: The network has only constant nodes.\n" ); + + dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + // set the mapping of elementary AIG nodes into the elementary BDD nodes + pMan = pNtk->pManFunc; + assert( Hop_ManPiNum(pMan) >= nFaninsMax ); + for ( i = 0; i < nFaninsMax; i++ ) + { + Hop_ManPi(pMan, i)->pData = Cudd_bddIthVar(dd, i); + Cudd_Ref( Hop_ManPi(pMan, i)->pData ); + } + + // convert each node from SOP to BDD + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + pNode->pData = Abc_ConvertAigToBdd( dd, pNode->pData ); + if ( pNode->pData == NULL ) + { + printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" ); + return 0; + } + Cudd_Ref( pNode->pData ); + } + + // dereference intermediate BDD nodes + for ( i = 0; i < nFaninsMax; i++ ) + Cudd_RecursiveDeref( dd, Hop_ManPi(pMan, i)->pData ); + + Hop_ManStop( pNtk->pManFunc ); + pNtk->pManFunc = dd; + + // update the network type + pNtk->ntkFunc = ABC_FUNC_BDD; + return 1; +} + +/**Function************************************************************* + + Synopsis [Construct BDDs and mark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertAigToBdd_rec1( DdManager * dd, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, (DdNode *)Hop_ObjChild0Copy(pObj), (DdNode *)Hop_ObjChild1Copy(pObj) ); + Cudd_Ref( pObj->pData ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Dereference BDDs and unmark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertAigToBdd_rec2( DdManager * dd, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin1(pObj) ); + Cudd_RecursiveDeref( dd, pObj->pData ); + pObj->pData = NULL; + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot ) +{ + DdNode * bFunc; + // check the case of a constant + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return Cudd_NotCond( Cudd_ReadOne(dd), Hop_IsComplement(pRoot) ); + // construct BDD + Abc_ConvertAigToBdd_rec1( dd, Hop_Regular(pRoot) ); + // hold on to the result + bFunc = Cudd_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); Cudd_Ref( bFunc ); + // dereference BDD + Abc_ConvertAigToBdd_rec2( dd, Hop_Regular(pRoot) ); + // return the result + Cudd_Deref( bFunc ); + return bFunc; +} + + + +/**Function************************************************************* + + Synopsis [Construct BDDs and mark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ConvertAigToTruth_rec1( Hop_Obj_t * pObj ) +{ + int Counter = 0; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return 0; + Counter += Abc_ConvertAigToTruth_rec1( Hop_ObjFanin0(pObj) ); + Counter += Abc_ConvertAigToTruth_rec1( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); + return Counter + 1; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Abc_ConvertAigToTruth_rec2( Hop_Obj_t * pObj, Vec_Int_t * vTruth, int nWords ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + int i; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) + return pObj->pData; + // compute the truth tables of the fanins + pTruth0 = Abc_ConvertAigToTruth_rec2( Hop_ObjFanin0(pObj), vTruth, nWords ); + pTruth1 = Abc_ConvertAigToTruth_rec2( Hop_ObjFanin1(pObj), vTruth, nWords ); + // creat the truth table of the node + pTruth = Vec_IntFetch( vTruth, nWords ); + if ( Hop_ObjIsExor(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] ^ pTruth1[i]; + else if ( !Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & pTruth1[i]; + else if ( !Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & ~pTruth1[i]; + else if ( Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & pTruth1[i]; + else // if ( Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); + pObj->pData = pTruth; + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the node.] + + Description [Assumes that the structural support is no more than 8 inputs. + Uses array vTruth to store temporary truth tables. The returned pointer should + be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Abc_ConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst ) +{ + static unsigned uTruths[8][8] = { // elementary truth tables + { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, + { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, + { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, + { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, + { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, + { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, + { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, + { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } + }; + Hop_Obj_t * pObj; + unsigned * pTruth, * pTruth2; + int i, nWords, nNodes; + Vec_Ptr_t * vTtElems; + + // if the number of variables is more than 8, allocate truth tables + if ( nVars > 8 ) + vTtElems = Vec_PtrAllocTruthTables( nVars ); + else + vTtElems = NULL; + + // clear the data fields and set marks + nNodes = Abc_ConvertAigToTruth_rec1( pRoot ); + // prepare memory + nWords = Hop_TruthWordNum( nVars ); + Vec_IntClear( vTruth ); + Vec_IntGrow( vTruth, nWords * (nNodes+1) ); + pTruth = Vec_IntFetch( vTruth, nWords ); + // check the case of a constant + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + { + assert( nNodes == 0 ); + if ( Hop_IsComplement(pRoot) ) + Extra_TruthClear( pTruth, nVars ); + else + Extra_TruthFill( pTruth, nVars ); + return pTruth; + } + // set elementary truth tables at the leaves + assert( nVars <= Hop_ManPiNum(p) ); +// assert( Hop_ManPiNum(p) <= 8 ); + if ( fMsbFirst ) + { + Hop_ManForEachPi( p, pObj, i ) + { + if ( vTtElems ) + pObj->pData = Vec_PtrEntry(vTtElems, nVars-1-i); + else + pObj->pData = (void *)uTruths[nVars-1-i]; + } + } + else + { + Hop_ManForEachPi( p, pObj, i ) + { + if ( vTtElems ) + pObj->pData = Vec_PtrEntry(vTtElems, i); + else + pObj->pData = (void *)uTruths[i]; + } + } + // clear the marks and compute the truth table + pTruth2 = Abc_ConvertAigToTruth_rec2( pRoot, vTruth, nWords ); + // copy the result + Extra_TruthCopy( pTruth, pTruth2, nVars ); + if ( vTtElems ) + Vec_PtrFree( vTtElems ); + return pTruth; +} + + +/**Function************************************************************* + + Synopsis [Construct BDDs and mark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertAigToAig_rec( Abc_Ntk_t * pNtkAig, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin1(pObj) ); + pObj->pData = Abc_AigAnd( pNtkAig->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObjOld ) +{ + Hop_Man_t * pHopMan; + Hop_Obj_t * pRoot; + Abc_Obj_t * pFanin; + int i; + // get the local AIG + pHopMan = pObjOld->pNtk->pManFunc; + pRoot = pObjOld->pData; + // check the case of a constant + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return Abc_ObjNotCond( Abc_AigConst1(pNtkAig), Hop_IsComplement(pRoot) ); + // assign the fanin nodes + Abc_ObjForEachFanin( pObjOld, pFanin, i ) + { + assert( pFanin->pCopy != NULL ); + Hop_ManPi(pHopMan, i)->pData = pFanin->pCopy; + } + // construct the AIG + Abc_ConvertAigToAig_rec( pNtkAig, Hop_Regular(pRoot) ); + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + // return the result + return Abc_ObjNotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + + +/**Function************************************************************* + + Synopsis [Unmaps the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ) +{ + extern void * Abc_FrameReadLibGen(); + Abc_Obj_t * pNode; + char * pSop; + int i; + + assert( Abc_NtkHasMapping(pNtk) ); + // update the functionality manager + assert( pNtk->pManFunc == Abc_FrameReadLibGen() ); + pNtk->pManFunc = Extra_MmFlexStart(); + pNtk->ntkFunc = ABC_FUNC_SOP; + // update the nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + { + pSop = Mio_GateReadSop(pNode->pData); + assert( Abc_SopGetVarNum(pSop) == Abc_ObjFaninNum(pNode) ); + pNode->pData = Abc_SopRegister( pNtk->pManFunc, pSop ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Converts SOP functions into BLIF-MV functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSopToBlifMv( Abc_Ntk_t * pNtk ) +{ + return 1; +} + +/**Function************************************************************* + + Synopsis [Convers logic network to the SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fDirect ) +{ + assert( !Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkHasSop(pNtk) ) + { + if ( !fDirect ) + return 1; + if ( !Abc_NtkSopToBdd(pNtk) ) + return 0; + return Abc_NtkBddToSop(pNtk, fDirect); + } + if ( Abc_NtkHasMapping(pNtk) ) + return Abc_NtkMapToSop(pNtk); + if ( Abc_NtkHasBdd(pNtk) ) + return Abc_NtkBddToSop(pNtk, fDirect); + if ( Abc_NtkHasAig(pNtk) ) + { + if ( !Abc_NtkAigToBdd(pNtk) ) + return 0; + return Abc_NtkBddToSop(pNtk, fDirect); + } + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Convers logic network to the SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkToBdd( Abc_Ntk_t * pNtk ) +{ + assert( !Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkHasBdd(pNtk) ) + return 1; + if ( Abc_NtkHasMapping(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + return Abc_NtkSopToBdd(pNtk); + } + if ( Abc_NtkHasSop(pNtk) ) + return Abc_NtkSopToBdd(pNtk); + if ( Abc_NtkHasAig(pNtk) ) + return Abc_NtkAigToBdd(pNtk); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Convers logic network to the SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkToAig( Abc_Ntk_t * pNtk ) +{ + assert( !Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkHasAig(pNtk) ) + return 1; + if ( Abc_NtkHasMapping(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + return Abc_NtkSopToAig(pNtk); + } + if ( Abc_NtkHasBdd(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk,0) ) + return 0; + return Abc_NtkSopToAig(pNtk); + } + if ( Abc_NtkHasSop(pNtk) ) + return Abc_NtkSopToAig(pNtk); + assert( 0 ); + return 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcHie.c b/abc70930/src/base/abc/abcHie.c new file mode 100644 index 00000000..56333a36 --- /dev/null +++ b/abc70930/src/base/abc/abcHie.c @@ -0,0 +1,492 @@ +/**CFile**************************************************************** + + FileName [abcHie.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to handle hierarchy.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Recursively flattens logic hierarchy of the netlist.] + + Description [When this procedure is called, the PI/PO nets of the old + netlist point to the corresponding nets of the flattened netlist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFlattenLogicHierarchy_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter ) +{ + char Suffix[1000] = {0}; + Abc_Ntk_t * pNtkModel; + Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin; + int i, k; + + // process the blackbox + if ( Abc_NtkHasBlackbox(pNtk) ) + { + // duplicate the blackbox + assert( Abc_NtkBoxNum(pNtk) == 1 ); + pObj = Abc_NtkBox( pNtk, 0 ); + Abc_NtkDupBox( pNtkNew, pObj, 1 ); + pObj->pCopy->pData = pNtk; + + // connect blackbox fanins to the PI nets + assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy ); + + // connect blackbox fanouts to the PO nets + assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) ); + Abc_NtkForEachPo( pNtk, pTerm, i ) + Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) ); + return; + } + + (*pCounter)++; + + // create the prefix, which will be appended to the internal names + if ( *pCounter ) + sprintf( Suffix, "_%s_%d", Abc_NtkName(pNtk), *pCounter ); + + // duplicate nets of all boxes, including latches + Abc_NtkForEachBox( pNtk, pObj, i ) + { + Abc_ObjForEachFanin( pObj, pTerm, k ) + { + pNet = Abc_ObjFanin0(pTerm); + if ( pNet->pCopy ) + continue; + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) ); + } + Abc_ObjForEachFanout( pObj, pTerm, k ) + { + pNet = Abc_ObjFanout0(pTerm); + if ( pNet->pCopy ) + continue; + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) ); + } + } + + // mark objects that will not be used + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_NtkForEachPo( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + Abc_NodeSetTravIdCurrent( pObj ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_NodeSetTravIdCurrent( pTerm ); + } + + // duplicate objects that do not have prototypes yet + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Abc_NodeIsTravIdCurrent(pObj) ) + continue; + if ( pObj->pCopy ) + continue; + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + } + + // connect objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // call recursively + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + pNtkModel = pObj->pData; + // check the match between the number of actual and formal parameters + assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) ); + assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) ); + // clean the node copy fields + Abc_NtkCleanCopy( pNtkModel ); + // map PIs/POs + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy; + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy; + // call recursively + Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtkModel, pCounter ); + } + + // if it is a BLIF-MV netlist transfer the values of all nets + if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) + { + if ( Abc_NtkMvVar( pNtkNew ) == NULL ) + Abc_NtkStartMvVars( pNtkNew ); + Abc_NtkForEachNet( pNtk, pObj, i ) + Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); + } +} + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pTerm, * pNet; + int i, Counter; + extern Abc_Lib_t * Abc_LibDupBlackboxes( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave ); + + assert( Abc_NtkIsNetlist(pNtk) ); + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + + // duplicate PIs/POs and their nets + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + Abc_NtkDupObj( pNtkNew, pTerm, 0 ); + pNet = Abc_ObjFanout0( pTerm ); + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); + Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy ); + } + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + Abc_NtkDupObj( pNtkNew, pTerm, 0 ); + pNet = Abc_ObjFanin0( pTerm ); + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); + Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy ); + } + + // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes + Counter = -1; + Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtk, &Counter ); + printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n", + Counter, Abc_NtkBlackboxNum(pNtkNew) ); + + if ( pNtk->pDesign ) + { + // pass on the design + assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk ); + pNtkNew->pDesign = Abc_LibDupBlackboxes( pNtk->pDesign, pNtkNew ); + // update the pointers + Abc_NtkForEachBlackbox( pNtkNew, pTerm, i ) + pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy; + } + + // copy the timing information +// Abc_ManTimeDup( pNtk, pNtkNew ); + // duplicate EXDC + if ( pNtk->pExdc ) + printf( "EXDC is not transformed.\n" ); + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkFlattenLogicHierarchy(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Extracts blackboxes by making them into additional PIs/POs.] + + Description [The input netlist has not logic hierarchy. The resulting + netlist has additional PIs/POs for each blackbox input/output.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNet, * pFanin, * pTerm; + int i, k; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + + // mark the nodes that should not be connected + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachBlackbox( pNtk, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkForEachCi( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_NtkForEachCo( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + // unmark PIs and LIs/LOs + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_NodeSetTravIdPrevious( pTerm ); + Abc_NtkForEachLatchInput( pNtk, pTerm, i ) + Abc_NodeSetTravIdPrevious( pTerm ); + Abc_NtkForEachLatchOutput( pNtk, pTerm, i ) + Abc_NodeSetTravIdPrevious( pTerm ); + // copy the box outputs + Abc_NtkForEachBlackbox( pNtk, pObj, i ) + Abc_ObjForEachFanout( pObj, pTerm, k ) + pTerm->pCopy = Abc_NtkCreatePi( pNtkNew ); + + // duplicate other objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDupObj( pNtkNew, pObj, Abc_ObjIsNet(pObj) ); + + // connect all objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // create unique PO for each net feeding into blackboxes or POs + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pTerm, i ) + { + // skip latch inputs + assert( Abc_ObjFanoutNum(pTerm) <= 1 ); + if ( Abc_ObjFanoutNum(pTerm) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pTerm)) ) + continue; + // check if the net is visited + pNet = Abc_ObjFanin0(pTerm); + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + // create PO + Abc_NodeSetTravIdCurrent( pNet ); + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNet->pCopy ); + } + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkConvertBlackboxes(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Inserts blackboxes into the netlist.] + + Description [The first arg is the netlist with blackboxes without logic hierarchy. + The second arg is a non-hierarchical netlist derived from the above netlist after processing. + This procedure create a new netlist, which is comparable to the original netlist with + blackboxes, except that it contains logic nodes from the netlist after processing.] + + SideEffects [This procedure silently assumes that blackboxes appear + only in the top-level model. If they appear in other models as well, + the name of the model and its number were appended to the names of + blackbox inputs/outputs.] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL ) +{ + Abc_Lib_t * pDesign; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjH, * pObjL, * pNetH, * pNetL, * pTermH; + int i, k; + + assert( Abc_NtkIsNetlist(pNtkH) ); + assert( Abc_NtkWhiteboxNum(pNtkH) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkH) > 0 ); + + assert( Abc_NtkIsNetlist(pNtkL) ); + assert( Abc_NtkWhiteboxNum(pNtkL) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkL) == 0 ); + + // prepare the logic network for copying + Abc_NtkCleanCopy( pNtkL ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtkL->ntkType, pNtkL->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtkH->pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtkH->pSpec ); + + // make sure every PI/PO has a PI/PO in the processed network + Abc_NtkForEachPi( pNtkH, pObjH, i ) + { + pNetH = Abc_ObjFanout0(pObjH); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) ) + { + printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the PI %s.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + if ( pNetL->pCopy ) + { + printf( "Error in Abc_NtkInsertNewLogic(): Primary input %s is repeated twice.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + // create the new net + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_NtkDupObj( pNtkNew, Abc_ObjFanin0(pNetL), 0 ); + } + + // make sure every BB has a PI/PO in the processed network + Abc_NtkForEachBlackbox( pNtkH, pObjH, i ) + { + // duplicate the box + Abc_NtkDupBox( pNtkNew, pObjH, 0 ); + pObjH->pCopy->pData = pObjH->pData; + // create PIs + Abc_ObjForEachFanout( pObjH, pTermH, k ) + { + pNetH = Abc_ObjFanout0( pTermH ); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) ) + { + printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the inpout %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + if ( pNetL->pCopy ) + { + printf( "Error in Abc_NtkInsertNewLogic(): Box output %s is repeated twice.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + // create net and map the PI + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_ObjFanin0(pNetL)->pCopy = pTermH->pCopy; + } + } + + Abc_NtkForEachPo( pNtkH, pObjH, i ) + { + pNetH = Abc_ObjFanin0(pObjH); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) ) + { + printf( "Error in Abc_NtkInsertNewLogic(): There is no PO corresponding to the PO %s.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + if ( pNetL->pCopy ) + continue; + // create the new net + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_NtkDupObj( pNtkNew, Abc_ObjFanout0(pNetL), 0 ); + } + Abc_NtkForEachBlackbox( pNtkH, pObjH, i ) + { + Abc_ObjForEachFanin( pObjH, pTermH, k ) + { + char * pName; + pNetH = Abc_ObjFanin0( pTermH ); + pName = Abc_ObjName(pNetH); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) ) + { + printf( "There is no PO corresponding to the input %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + // create net and map the PO + if ( pNetL->pCopy ) + { + if ( Abc_ObjFanout0(pNetL)->pCopy == NULL ) + Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy; + else + Abc_ObjAddFanin( pTermH->pCopy, pNetL->pCopy ); + continue; + } + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy; + } + } + + // duplicate other objects of the logic network + Abc_NtkForEachObj( pNtkL, pObjL, i ) + if ( pObjL->pCopy == NULL && !Abc_ObjIsPo(pObjL) ) // skip POs feeding into PIs + Abc_NtkDupObj( pNtkNew, pObjL, Abc_ObjIsNet(pObjL) ); + + // connect objects + Abc_NtkForEachObj( pNtkL, pObjL, i ) + Abc_ObjForEachFanin( pObjL, pNetL, k ) + if ( pObjL->pCopy ) + Abc_ObjAddFanin( pObjL->pCopy, pNetL->pCopy ); + + // transfer the design + pDesign = pNtkH->pDesign; pNtkH->pDesign = NULL; + assert( Vec_PtrEntry( pDesign->vModules, 0 ) == pNtkH ); + Vec_PtrWriteEntry( pDesign->vModules, 0, pNtkNew ); + pNtkNew->pDesign = pDesign; + +//Abc_NtkPrintStats( stdout, pNtkH, 0 ); +//Abc_NtkPrintStats( stdout, pNtkNew, 0 ); + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkInsertNewLogic(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcInt.h b/abc70930/src/base/abc/abcInt.h new file mode 100644 index 00000000..0e35e774 --- /dev/null +++ b/abc70930/src/base/abc/abcInt.h @@ -0,0 +1,52 @@ +/**CFile**************************************************************** + + FileName [abcInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __ABC_INT_H__ +#define __ABC_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_NUM_STEPS 10 + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcLatch.c b/abc70930/src/base/abc/abcLatch.c new file mode 100644 index 00000000..d96bbfac --- /dev/null +++ b/abc70930/src/base/abc/abcLatch.c @@ -0,0 +1,326 @@ +/**CFile**************************************************************** + + FileName [abcLatch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures working with latches.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcLatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkLatchIsSelfFeed_rec( Abc_Obj_t * pLatch, Abc_Obj_t * pLatchRoot ) +{ + Abc_Obj_t * pFanin; + assert( Abc_ObjIsLatch(pLatch) ); + if ( pLatch == pLatchRoot ) + return 1; + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) + return 0; + return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); +} + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ) +{ + Abc_Obj_t * pFanin; + assert( Abc_ObjIsLatch(pLatch) ); + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) + return 0; + return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); +} + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch; + int i, Counter; + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { +// if ( Abc_NtkLatchIsSelfFeed(pLatch) && Abc_ObjFanoutNum(pLatch) > 1 ) +// printf( "Fanouts = %d.\n", Abc_ObjFanoutNum(pLatch) ); + Counter += Abc_NtkLatchIsSelfFeed( pLatch ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Replaces self-feeding latches by latches with constant inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch, * pConst1; + int i, Counter; + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( Abc_NtkLatchIsSelfFeed( pLatch ) ) + { + if ( Abc_NtkIsStrash(pNtk) ) + pConst1 = Abc_AigConst1(pNtk); + else + pConst1 = Abc_NtkCreateNodeConst1(pNtk); + Abc_ObjPatchFanin( Abc_ObjFanin0(pLatch), Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pConst1 ); + Counter++; + } + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Pipelines the network with latches.] + + Description [] + + SideEffects [Does not check the names of the added latches!!!] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pLatch, * pFanin, * pFanout; + int i, k, nTotal, nDigits; + if ( nLatches < 1 ) + return; + nTotal = nLatches * Abc_NtkPiNum(pNtk); + nDigits = Extra_Base10Log( nTotal ); + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + // remember current fanins of the PI + Abc_NodeCollectFanouts( pObj, vNodes ); + // create the latches + for ( pFanin = pObj, k = 0; k < nLatches; k++, pFanin = pLatch ) + { + pLatch = Abc_NtkCreateLatch( pNtk ); + Abc_ObjAddFanin( pLatch, pFanin ); + Abc_LatchSetInitDc( pLatch ); + // create the name of the new latch + Abc_ObjAssignName( pLatch, Abc_ObjNameDummy("LL", i*nLatches + k, nDigits), NULL ); + } + // patch the PI fanouts + Vec_PtrForEachEntry( vNodes, pFanout, k ) + Abc_ObjPatchFanin( pFanout, pObj, pFanin ); + } + Vec_PtrFree( vNodes ); + Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vValues; + Abc_Obj_t * pLatch; + int i; + vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Vec_IntPush( vValues, Abc_LatchIsInit1(pLatch) ); + return vValues; +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ) +{ + Abc_Obj_t * pLatch; + int i; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pData = (void *)(vValues? (Vec_IntEntry(vValues,i)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC); +} + +/**Function************************************************************* + + Synopsis [Creates latch with the given initial value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init ) +{ + Abc_Obj_t * pLatchOut, * pLatch, * pLatchIn; + pLatchOut = Abc_NtkCreateBo(pNtk); + pLatch = Abc_NtkCreateLatch(pNtk); + pLatchIn = Abc_NtkCreateBi(pNtk); + Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_lo" ); + Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_li" ); + Abc_ObjAddFanin( pLatchOut, pLatch ); + Abc_ObjAddFanin( pLatch, pLatchIn ); + Abc_ObjAddFanin( pLatchIn, pDriver ); + pLatch->pData = (void *)Init; + return pLatchOut; +} + +/**Function************************************************************* + + Synopsis [Creates MUX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkNodeConvertToMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0, Abc_Obj_t * pMux ) +{ + assert( Abc_NtkIsLogic(pNtk) ); + Abc_ObjAddFanin( pMux, pNodeC ); + Abc_ObjAddFanin( pMux, pNode1 ); + Abc_ObjAddFanin( pMux, pNode0 ); + if ( Abc_NtkHasSop(pNtk) ) + pMux->pData = Abc_SopRegister( pNtk->pManFunc, "11- 1\n0-1 1\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pMux->pData = Cudd_bddIte(pNtk->pManFunc,Cudd_bddIthVar(pNtk->pManFunc,0),Cudd_bddIthVar(pNtk->pManFunc,1),Cudd_bddIthVar(pNtk->pManFunc,2)), Cudd_Ref( pMux->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pMux->pData = Hop_Mux(pNtk->pManFunc,Hop_IthVar(pNtk->pManFunc,0),Hop_IthVar(pNtk->pManFunc,1),Hop_IthVar(pNtk->pManFunc,2)); + else + assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [Converts registers with DC values into additional PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pCtrl, * pLatch, * pMux, * pPi; + Abc_InitType_t Init = ABC_INIT_ZERO; + int i, fFound = 0, Counter; + // check if there are latches with DC values + Abc_NtkForEachLatch( pNtk, pLatch, i ) + if ( Abc_LatchIsInitDc(pLatch) ) + { + fFound = 1; + break; + } + if ( !fFound ) + return; + // add control latch + pCtrl = Abc_NtkAddLatch( pNtk, Abc_NtkCreateNodeConst1(pNtk), Init ); + // add fanouts for each latch with DC values + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( !Abc_LatchIsInitDc(pLatch) ) + continue; + // change latch value + pLatch->pData = (void *)Init; + // if the latch output has the same name as a PO, rename it + if ( Abc_NodeFindCoFanout( Abc_ObjFanout0(pLatch) ) ) + { + Nm_ManDeleteIdName( pLatch->pNtk->pManName, Abc_ObjFanout0(pLatch)->Id ); + Abc_ObjAssignName( Abc_ObjFanout0(pLatch), Abc_ObjName(pLatch), "_lo" ); + } + // create new PIs + pPi = Abc_NtkCreatePi( pNtk ); + Abc_ObjAssignName( pPi, Abc_ObjName(pLatch), "_pi" ); + // create a new node and transfer fanout from latch output to the new node + pMux = Abc_NtkCreateNode( pNtk ); + Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pMux ); + // convert the node into a mux + Abc_NtkNodeConvertToMux( pNtk, pCtrl, Abc_ObjFanout0(pLatch), pPi, pMux ); + Counter++; + } + printf( "The number of converted latches with DC values = %d.\n", Counter ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcLib.c b/abc70930/src/base/abc/abcLib.c new file mode 100644 index 00000000..f5b90e90 --- /dev/null +++ b/abc70930/src/base/abc/abcLib.c @@ -0,0 +1,455 @@ +/**CFile**************************************************************** + + FileName [abcLib.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Functions to manipulate verilog libraries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Lib_t * Abc_LibCreate( char * pName ) +{ + Abc_Lib_t * p; + p = ALLOC( Abc_Lib_t, 1 ); + memset( p, 0, sizeof(Abc_Lib_t) ); + p->pName = Extra_UtilStrsav( pName ); + p->tModules = st_init_table( strcmp, st_strhash ); + p->vTops = Vec_PtrAlloc( 100 ); + p->vModules = Vec_PtrAlloc( 100 ); + p->pManFunc = Hop_ManStart(); + p->pLibrary = NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_LibFree( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave ) +{ + Abc_Ntk_t * pNtk; + int i; + if ( pLib->pName ) + free( pLib->pName ); + if ( pLib->pManFunc ) + Hop_ManStop( pLib->pManFunc ); + if ( pLib->tModules ) + st_free_table( pLib->tModules ); + if ( pLib->vModules ) + { + Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) + { +// pNtk->pManFunc = NULL; + if ( pNtk == pNtkSave ) + continue; + pNtk->pManFunc = NULL; + pNtk->pDesign = NULL; + Abc_NtkDelete( pNtk ); + } + Vec_PtrFree( pLib->vModules ); + } + if ( pLib->vTops ) + Vec_PtrFree( pLib->vTops ); + free( pLib ); +} + +/**Function************************************************************* + + Synopsis [Frees the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Lib_t * Abc_LibDupBlackboxes( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave ) +{ + Abc_Lib_t * pLibNew; + Abc_Ntk_t * pNtkTemp; + int i; + assert( Vec_PtrSize(pLib->vTops) > 0 ); + assert( Vec_PtrSize(pLib->vModules) > 1 ); + pLibNew = Abc_LibCreate( pLib->pName ); +// pLibNew->pManFunc = pNtkSave->pManFunc; + Vec_PtrPush( pLibNew->vTops, pNtkSave ); + Vec_PtrPush( pLibNew->vModules, pNtkSave ); + Vec_PtrForEachEntry( pLib->vModules, pNtkTemp, i ) + if ( Abc_NtkHasBlackbox( pNtkTemp ) ) + Vec_PtrPush( pLibNew->vModules, Abc_NtkDup(pNtkTemp) ); + return pLibNew; +} + + +/**Function************************************************************* + + Synopsis [Prints the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_LibPrint( Abc_Lib_t * pLib ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj; + int i, k; + printf( "Models of design %s:\n", pLib->pName ); + Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) + { + printf( "%2d : %20s ", i+1, pNtk->pName ); + printf( "nd = %6d lat = %6d whitebox = %3d blackbox = %3d\n", + Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk), + Abc_NtkWhiteboxNum(pNtk), Abc_NtkBlackboxNum(pNtk) ); + if ( Abc_NtkBlackboxNum(pNtk) == 0 ) + continue; + Abc_NtkForEachWhitebox( pNtk, pObj, k ) + printf( " %20s (whitebox)\n", Abc_NtkName(pObj->pData) ); + Abc_NtkForEachBlackbox( pNtk, pObj, k ) + printf( " %20s (blackbox)\n", Abc_NtkName(pObj->pData) ); + } +} + +/**Function************************************************************* + + Synopsis [Create the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_LibAddModel( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk ) +{ + if ( st_is_member( pLib->tModules, (char *)pNtk->pName ) ) + return 0; + st_insert( pLib->tModules, (char *)pNtk->pName, (char *)pNtk ); + Vec_PtrPush( pLib->vModules, pNtk ); + pNtk->pDesign = pLib; + return 1; +} + +/**Function************************************************************* + + Synopsis [Create the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_LibFindModelByName( Abc_Lib_t * pLib, char * pName ) +{ + Abc_Ntk_t * pNtk; + if ( !st_is_member( pLib->tModules, (char *)pName ) ) + return NULL; + st_lookup( pLib->tModules, (char *)pName, (char **)&pNtk ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Frees the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_LibDeriveRoot( Abc_Lib_t * pLib ) +{ + Abc_Ntk_t * pNtk; + if ( Vec_PtrSize(pLib->vModules) > 1 ) + { + printf( "The design includes more than one module and is currently not used.\n" ); + return NULL; + } + pNtk = Vec_PtrEntry( pLib->vModules, 0 ); Vec_PtrClear( pLib->vModules ); + pNtk->pManFunc = pLib->pManFunc; pLib->pManFunc = NULL; + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Detects the top-level models.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_LibFindTopLevelModels( Abc_Lib_t * pLib ) +{ + Abc_Ntk_t * pNtk, * pNtkBox; + Abc_Obj_t * pObj; + int i, k; + assert( Vec_PtrSize( pLib->vModules ) > 0 ); + // clear the models + Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) + pNtk->fHieVisited = 0; + // mark all the models reachable from other models + Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) + { + Abc_NtkForEachBox( pNtk, pObj, k ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + if ( pObj->pData == NULL ) + continue; + pNtkBox = pObj->pData; + pNtkBox->fHieVisited = 1; + } + } + // collect the models that are not marked + Vec_PtrClear( pLib->vTops ); + Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) + { + if ( pNtk->fHieVisited == 0 ) + Vec_PtrPush( pLib->vTops, pNtk ); + else + pNtk->fHieVisited = 0; + } + return Vec_PtrSize( pLib->vTops ); +} + + +/**Function************************************************************* + + Synopsis [Surround boxes without content (black boxes) with BIs/BOs.] + + Description [Returns the number of black boxes converted.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_LibDeriveBlackBoxes( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib ) +{ +/* + Abc_Obj_t * pObj, * pFanin, * pFanout; + int i, k; + assert( Abc_NtkIsNetlist(pNtk) ); + // collect blackbox nodes + assert( Vec_PtrSize(pNtk->vBoxes) == 0 ); + Vec_PtrClear( pNtk->vBoxes ); + Abc_NtkForEachBox( pNtk, pObj, i ) + if ( Abc_NtkNodeNum(pObj->pData) == 0 ) + Vec_PtrPush( pNtk->vBoxes, pObj ); + // return if there is no black boxes without content + if ( Vec_PtrSize(pNtk->vBoxes) == 0 ) + return 0; + // print the boxes + printf( "Black boxes are: " ); + Abc_NtkForEachBox( pNtk, pObj, i ) + printf( " %s", ((Abc_Ntk_t *)pObj->pData)->pName ); + printf( "\n" ); + // iterate through the boxes and add BIs/BOs + Abc_NtkForEachBox( pNtk, pObj, i ) + { + // go through the fanin nets + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjInsertBetween( pFanin, pObj, ABC_OBJ_BI ); + // go through the fanout nets + Abc_ObjForEachFanout( pObj, pFanout, k ) + { + Abc_ObjInsertBetween( pObj, pFanout, ABC_OBJ_BO ); + // if the name is not given assign name + if ( pFanout->pData == NULL ) + { + pFanout->pData = Abc_ObjName( pFanout ); + Nm_ManStoreIdName( pNtk->pManName, pFanout->Id, pFanout->pData, NULL ); + } + } + } + return Vec_PtrSize(pNtk->vBoxes); +*/ + return 0; +} + +/**Function************************************************************* + + Synopsis [Derive the AIG of the logic in the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeStrashUsingNetwork_rec( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pObj) ); + if ( pObj->pCopy ) + return; + // call for the fanins + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) ); + // compute for the node + pObj->pCopy = Abc_NodeStrash( pNtkAig, pObj, 0 ); + // set for the fanout net + Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; +} + +/**Function************************************************************* + + Synopsis [Derive the AIG of the logic in the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeStrashUsingNetwork( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pBox ) +{ + Abc_Ntk_t * pNtkGate; + Abc_Obj_t * pObj; + unsigned * pPolarity; + int i, fCompl; + assert( Abc_ObjIsBox(pBox) ); + pNtkGate = pBox->pData; + pPolarity = (unsigned *)pBox->pNext; + assert( Abc_NtkIsNetlist(pNtkGate) ); + assert( Abc_NtkLatchNum(pNtkGate) == 0 ); + Abc_NtkCleanCopy( pNtkGate ); + // set the PI values + Abc_NtkForEachPi( pNtkGate, pObj, i ) + { + fCompl = (pPolarity && Abc_InfoHasBit(pPolarity, i)); + pObj->pCopy = Abc_ObjNotCond( Abc_ObjFanin(pBox,i)->pCopy, fCompl ); + Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; + } + // build recursively and set the PO values + Abc_NtkForEachPo( pNtkGate, pObj, i ) + { + Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) ); + Abc_ObjFanout(pBox,i)->pCopy = Abc_ObjFanin0(pObj)->pCopy; + } +//printf( "processing %d\n", pBox->Id ); +} + +/**Function************************************************************* + + Synopsis [Derive the AIG of the logic in the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_LibDeriveAig( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkAig; + Abc_Obj_t * pObj; + int i, nBoxes; + // explicitly derive black boxes + assert( Abc_NtkIsNetlist(pNtk) ); + nBoxes = Abc_LibDeriveBlackBoxes( pNtk, pLib ); + if ( nBoxes ) + printf( "Detected and transformed %d black boxes.\n", nBoxes ); + // create the new network with black boxes in place + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transer to the nets + Abc_NtkForEachCi( pNtk, pObj, i ) + Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; + // build the AIG for the remaining logic in the netlist + vNodes = Abc_NtkDfs( pNtk, 0 ); + pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( Abc_ObjIsNode(pObj) ) + { + pObj->pCopy = Abc_NodeStrash( pNtkAig, pObj, 0 ); + Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; + continue; + } + Abc_NodeStrashUsingNetwork( pNtkAig, pObj ); + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + // deallocate memory manager, which remembers the phase + if ( pNtk->pData ) + { + Extra_MmFlexStop( pNtk->pData ); + pNtk->pData = NULL; + } + // set the COs +// Abc_NtkFinalize( pNtk, pNtkAig ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); + Abc_AigCleanup( pNtkAig->pManFunc ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_LibDeriveAig: The network check has failed.\n" ); + return 0; + } + return pNtkAig; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcMinBase.c b/abc70930/src/base/abc/abcMinBase.c new file mode 100644 index 00000000..13f422f4 --- /dev/null +++ b/abc70930/src/base/abc/abcMinBase.c @@ -0,0 +1,256 @@ +/**CFile**************************************************************** + + FileName [abcMinBase.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Makes nodes of the network minimum base.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMinBase.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Makes nodes minimum base.] + + Description [Returns the number of changed nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter; + assert( Abc_NtkIsBddLogic(pNtk) ); + Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeMinimumBase( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Makes one node minimum base.] + + Description [Returns 1 if the node is changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) +{ + Vec_Str_t * vSupport; + Vec_Ptr_t * vFanins; + DdNode * bTemp; + int i, nVars; + + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + + // compute support + vSupport = Vec_StrAlloc( 10 ); + nVars = Abc_NodeSupport( Cudd_Regular(pNode->pData), vSupport, Abc_ObjFaninNum(pNode) ); + if ( nVars == Abc_ObjFaninNum(pNode) ) + { + Vec_StrFree( vSupport ); + return 0; + } + + // remove unused fanins + vFanins = Vec_PtrAlloc( Abc_ObjFaninNum(pNode) ); + Abc_NodeCollectFanins( pNode, vFanins ); + for ( i = 0; i < vFanins->nSize; i++ ) + if ( vSupport->pArray[i] == 0 ) + Abc_ObjDeleteFanin( pNode, vFanins->pArray[i] ); + assert( nVars == Abc_ObjFaninNum(pNode) ); + + // update the function of the node + pNode->pData = Extra_bddRemapUp( pNode->pNtk->pManFunc, bTemp = pNode->pData ); Cudd_Ref( pNode->pData ); + Cudd_RecursiveDeref( pNode->pNtk->pManFunc, bTemp ); + Vec_PtrFree( vFanins ); + Vec_StrFree( vSupport ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Makes nodes of the network fanin-dup-free.] + + Description [Returns the number of pairs of duplicated fanins.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter; + assert( Abc_NtkIsBddLogic(pNtk) ); + Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeRemoveDupFanins( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Removes one pair of duplicated fanins if present.] + + Description [Returns 1 if the node is changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRemoveDupFanins_int( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin1, * pFanin2; + int i, k; + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + // make sure fanins are not duplicated + Abc_ObjForEachFanin( pNode, pFanin2, i ) + { + Abc_ObjForEachFanin( pNode, pFanin1, k ) + { + if ( k >= i ) + break; + if ( pFanin1 == pFanin2 ) + { + DdManager * dd = pNode->pNtk->pManFunc; + DdNode * bVar1 = Cudd_bddIthVar( dd, i ); + DdNode * bVar2 = Cudd_bddIthVar( dd, k ); + DdNode * bTrans, * bTemp; + bTrans = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bTrans ); + pNode->pData = Cudd_bddAndAbstract( dd, bTemp = pNode->pData, bTrans, bVar2 ); Cudd_Ref( pNode->pData ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bTrans ); + Abc_NodeMinimumBase( pNode ); + return 1; + } + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Removes duplicated fanins if present.] + + Description [Returns the number of fanins removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ) +{ + int Counter = 0; + while ( Abc_NodeRemoveDupFanins_int(pNode) ) + Counter++; + return Counter; +} +/**Function************************************************************* + + Synopsis [Computes support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSupport_rec( DdNode * bFunc, Vec_Str_t * vSupport ) +{ + if ( cuddIsConstant(bFunc) || Cudd_IsComplement(bFunc->next) ) + return; + vSupport->pArray[ bFunc->index ] = 1; + Abc_NodeSupport_rec( cuddT(bFunc), vSupport ); + Abc_NodeSupport_rec( Cudd_Regular(cuddE(bFunc)), vSupport ); + bFunc->next = Cudd_Not(bFunc->next); +} + +/**Function************************************************************* + + Synopsis [Computes support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSupportClear_rec( DdNode * bFunc ) +{ + if ( !Cudd_IsComplement(bFunc->next) ) + return; + bFunc->next = Cudd_Regular(bFunc->next); + if ( cuddIsConstant(bFunc) ) + return; + Abc_NodeSupportClear_rec( cuddT(bFunc) ); + Abc_NodeSupportClear_rec( Cudd_Regular(cuddE(bFunc)) ); +} + +/**Function************************************************************* + + Synopsis [Computes support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ) +{ + int Counter, i; + // compute the support by marking the BDD + Vec_StrFill( vSupport, nVars, 0 ); + Abc_NodeSupport_rec( bFunc, vSupport ); + // clear the marak + Abc_NodeSupportClear_rec( bFunc ); + // get the number of support variables + Counter = 0; + for ( i = 0; i < nVars; i++ ) + Counter += vSupport->pArray[i]; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcNames.c b/abc70930/src/base/abc/abcNames.c new file mode 100644 index 00000000..91964dfa --- /dev/null +++ b/abc70930/src/base/abc/abcNames.c @@ -0,0 +1,467 @@ +/**CFile**************************************************************** + + FileName [abcNames.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures working with net and node names.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcNames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the unique name for the object.] + + Description [If the name previously did not exist, creates a new unique + name but does not assign this name to the object. The temporary unique + name is stored in a static buffer inside this procedure. It is important + that the name is used before the function is called again!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjName( Abc_Obj_t * pObj ) +{ + return Nm_ManCreateUniqueName( pObj->pNtk->pManName, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Assigns the given name to the object.] + + Description [The object should not have a name assigned. The same + name may be used for several objects, which they share the same net + in the original netlist. (For example, latch output and primary output + may have the same name.) This procedure returns the pointer to the + internally stored representation of the given name.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix ) +{ + assert( pName != NULL ); + return Nm_ManStoreIdName( pObj->pNtk->pManName, pObj->Id, pObj->Type, pName, pSuffix ); +} + +/**Function************************************************************* + + Synopsis [Gets the long name of the node.] + + Description [This name is the output net's name.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ) +{ + static char Buffer[500]; + sprintf( Buffer, "%s%s", Abc_ObjName(pObj), pSuffix ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Returns the dummy PI name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits ) +{ + static char Buffer[100]; + sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Tranfers names to the old network.] + + Description [Assumes that the new nodes are attached using pObj->pCopy.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); + assert( Abc_NtkBoxNum(pNtk) == Abc_NtkBoxNum(pNtkNew) ); + assert( Abc_NtkAssertNum(pNtk) == Abc_NtkAssertNum(pNtkNew) ); + assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); + assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); + // copy the CI/CO/box names + Abc_NtkForEachCi( pNtk, pObj, i ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); +} + +/**Function************************************************************* + + Synopsis [Tranfers names to the old network.] + + Description [Assumes that the new nodes are attached using pObj->pCopy.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); + assert( Abc_NtkAssertNum(pNtk) == Abc_NtkAssertNum(pNtkNew) ); + assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); + assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); + // copy the CI/CO/box name and skip latches and theirs inputs/outputs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFaninNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); + Abc_NtkForEachCo( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); + Abc_NtkForEachBox( pNtk, pObj, i ) + if ( !Abc_ObjIsLatch(pObj) ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); +} + +/**Function************************************************************* + + Synopsis [Gets fanin node names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pFanin; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Vec_PtrPush( vNodes, Extra_UtilStrsav(Abc_ObjName(pFanin)) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Gets fanin node names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ) +{ + Vec_Ptr_t * vNames; + char Buffer[5]; + int i; + + vNames = Vec_PtrAlloc( nNames ); + for ( i = 0; i < nNames; i++ ) + { + if ( nNames < 26 ) + { + Buffer[0] = 'a' + i; + Buffer[1] = 0; + } + else + { + Buffer[0] = 'a' + i%26; + Buffer[1] = '0' + i/26; + Buffer[2] = 0; + } + Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); + } + return vNames; +} + +/**Function************************************************************* + + Synopsis [Gets fanin node names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeFreeNames( Vec_Ptr_t * vNames ) +{ + int i; + if ( vNames == NULL ) + return; + for ( i = 0; i < vNames->nSize; i++ ) + free( vNames->pArray[i] ); + Vec_PtrFree( vNames ); +} + +/**Function************************************************************* + + Synopsis [Collects the CI or CO names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos ) +{ + Abc_Obj_t * pObj; + char ** ppNames; + int i; + if ( fCollectCos ) + { + ppNames = ALLOC( char *, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + ppNames[i] = Abc_ObjName(pObj); + } + else + { + ppNames = ALLOC( char *, Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + ppNames[i] = Abc_ObjName(pObj); + } + return ppNames; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + int Diff = strcmp( (char *)(*pp1)->pCopy, (char *)(*pp2)->pCopy ); + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Orders PIs/POs/latches alphabetically.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkAssertNum(pNtk) == 0 ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + // temporarily store the names in the copy field + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); + Abc_NtkForEachBox( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(Abc_ObjFanout0(pObj)); + // order objects alphabetically + qsort( (void *)Vec_PtrArray(pNtk->vPis), Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareNames ); + qsort( (void *)Vec_PtrArray(pNtk->vPos), Vec_PtrSize(pNtk->vPos), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareNames ); + // if the comparison if combinational (latches as PIs/POs), order them too + if ( fComb ) + qsort( (void *)Vec_PtrArray(pNtk->vBoxes), Vec_PtrSize(pNtk->vBoxes), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareNames ); + // order CIs/COs first PIs/POs(Asserts) then latches + Abc_NtkOrderCisCos( pNtk ); + // clean the copy fields + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = NULL; + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->pCopy = NULL; + Abc_NtkForEachBox( pNtk, pObj, i ) + pObj->pCopy = NULL; +} + +/**Function************************************************************* + + Synopsis [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nDigits, i; + nDigits = Extra_Base10Log( Abc_NtkPiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, Abc_ObjNameDummy("pi", i, nDigits), NULL ); +} + +/**Function************************************************************* + + Synopsis [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nDigits, i; + nDigits = Extra_Base10Log( Abc_NtkPoNum(pNtk) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, Abc_ObjNameDummy("po", i, nDigits), NULL ); +} + +/**Function************************************************************* + + Synopsis [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyAssertNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nDigits, i; + nDigits = Extra_Base10Log( Abc_NtkAssertNum(pNtk) ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, Abc_ObjNameDummy("a", i, nDigits), NULL ); +} + +/**Function************************************************************* + + Synopsis [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nDigits, i; + assert( !Abc_NtkIsNetlist(pNtk) ); + nDigits = Extra_Base10Log( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + Abc_ObjAssignName( pObj, Abc_ObjNameDummy("l", i, nDigits), NULL ); + Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjNameDummy("li", i, nDigits), NULL ); + Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjNameDummy("lo", i, nDigits), NULL ); + } +/* + nDigits = Extra_Base10Log( Abc_NtkBlackboxNum(pNtk) ); + Abc_NtkForEachBlackbox( pNtk, pObj, i ) + { + pName = Abc_ObjAssignName( pObj, Abc_ObjNameDummy("B", i, nDigits), NULL ); + nDigitsF = Extra_Base10Log( Abc_ObjFaninNum(pObj) ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("i", k, nDigitsF) ); + nDigitsF = Extra_Base10Log( Abc_ObjFanoutNum(pObj) ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("o", k, nDigitsF) ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Replaces names by short names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkShortNames( Abc_Ntk_t * pNtk ) +{ + Nm_ManFree( pNtk->pManName ); + pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) ); + Abc_NtkAddDummyPiNames( pNtk ); + Abc_NtkAddDummyPoNames( pNtk ); + Abc_NtkAddDummyAssertNames( pNtk ); + Abc_NtkAddDummyBoxNames( pNtk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcNetlist.c b/abc70930/src/base/abc/abcNetlist.c new file mode 100644 index 00000000..26b88c68 --- /dev/null +++ b/abc70930/src/base/abc/abcNetlist.c @@ -0,0 +1,411 @@ +/**CFile**************************************************************** + + FileName [abcNetlist.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Transforms netlist into a logic network and vice versa.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcNetlist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +//#include "seq.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transform the netlist into a logic network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + // consider the case of the AIG + if ( Abc_NtkIsStrash(pNtk) ) + return Abc_NtkAigToLogicSop( pNtk ); + assert( Abc_NtkIsNetlist(pNtk) ); + // consider simple case when there is hierarchy +// assert( pNtk->pDesign == NULL ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + assert( Abc_NtkBlackboxNum(pNtk) == 0 ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, pNtk->ntkFunc ); + // duplicate the nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect the internal nodes in the new network + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pFanin)->pCopy ); + // collect the CO nodes + Abc_NtkFinalize( pNtk, pNtkNew ); + // fix the problem with CO pointing directly to CIs + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkToLogic( pNtk->pExdc ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkToLogic(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transform the logic network into a netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew, * pNtkTemp; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkAigToLogicSop(pNtk); + pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); + Abc_NtkDelete( pNtkTemp ); + return pNtkNew; + } + return Abc_NtkLogicToNetlist( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Converts the AIG into the netlist.] + + Description [This procedure does not copy the choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew, * pNtkTemp; + assert( Abc_NtkIsStrash(pNtk) ); + pNtkTemp = Abc_NtkAigToLogicSopBench( pNtk ); + pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); + Abc_NtkDelete( pNtkTemp ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transform the logic network into a netlist.] + + Description [The logic network given to this procedure should + have exactly the same structure as the resulting netlist. The COs + can only point to CIs if they have identical names. Otherwise, + they should have a node between them, even if this node is + inverter or buffer.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNet, * pDriver, * pFanin; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) ); + + // remove dangling nodes + Abc_NtkCleanup( pNtk, 0 ); + + // make sure the CO names are unique + Abc_NtkCheckUniqueCiNames( pNtk ); + Abc_NtkCheckUniqueCoNames( pNtk ); + Abc_NtkCheckUniqueCioNames( pNtk ); + +// assert( Abc_NtkLogicHasSimpleCos(pNtk) ); + if ( !Abc_NtkLogicHasSimpleCos(pNtk) ) + { + printf( "Abc_NtkLogicToNetlist() warning: The network is converted to have simple COs.\n" ); + Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); + } + + // start the netlist by creating PI/PO/Latch objects + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc ); + // create the CI nets and remember them in the new CI nodes + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); + Abc_ObjAddFanin( pNet, pObj->pCopy ); + pObj->pCopy->pCopy = pNet; + } + // duplicate all nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // first add the nets to the CO drivers + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0(pObj); + if ( Abc_ObjIsCi(pDriver) ) + { + assert( !strcmp( Abc_ObjName(pDriver), Abc_ObjName(pObj) ) ); + Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); + continue; + } + assert( Abc_ObjIsNode(pDriver) ); + // if the CO driver has no net, create it + if ( pDriver->pCopy->pCopy == NULL ) + { + // create the CO net and connect it to CO + pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); + Abc_ObjAddFanin( pObj->pCopy, pNet ); + // connect the CO net to the new driver and remember it in the new driver + Abc_ObjAddFanin( pNet, pDriver->pCopy ); + pDriver->pCopy->pCopy = pNet; + } + else + { + assert( !strcmp( Abc_ObjName(pDriver->pCopy->pCopy), Abc_ObjName(pObj) ) ); + Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); + } + } + // create the missing nets + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( pObj->pCopy->pCopy ) // the net of the new object is already created + continue; + // create the new net + pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create ridiculous names net line "n48", where 48 is the ID of the node + Abc_ObjAddFanin( pNet, pObj->pCopy ); + pObj->pCopy->pCopy = pNet; + } + // connect nodes to the fanins nets + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkLogicToNetlist(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the AIG into the logic network with SOPs.] + + Description [Correctly handles the case of choice nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pNodeNew; + Vec_Int_t * vInts; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + // if the constant node is used, duplicate it + pObj = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); + // duplicate the nodes and create node functions + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Abc_NtkDupObj(pNtkNew, pObj, 0); + pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + } + // create the choice nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( !Abc_AigNodeIsChoice(pObj) ) + continue; + // create an OR gate + pNodeNew = Abc_NtkCreateNode(pNtkNew); + // add fanins + vInts = Vec_IntAlloc( 10 ); + for ( pFanin = pObj; pFanin; pFanin = pFanin->pData ) + { + Vec_IntPush( vInts, (int)(pObj->fPhase != pFanin->fPhase) ); + Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); + } + // create the logic function + pNodeNew->pData = Abc_SopCreateOrMultiCube( pNtkNew->pManFunc, Vec_IntSize(vInts), Vec_IntArray(vInts) ); + // set the new node + pObj->pCopy->pCopy = pNodeNew; + Vec_IntFree( vInts ); + } + // connect the internal nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( pFanin->pCopy->pCopy ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + else + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + // connect the COs +// Abc_NtkFinalize( pNtk, pNtkNew ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pFanin = Abc_ObjFanin0(pObj); + if ( pFanin->pCopy->pCopy ) + pNodeNew = Abc_ObjNotCond(pFanin->pCopy->pCopy, Abc_ObjFaninC0(pObj)); + else + pNodeNew = Abc_ObjNotCond(pFanin->pCopy, Abc_ObjFaninC0(pObj)); + Abc_ObjAddFanin( pObj->pCopy, pNodeNew ); + } + + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + { + if ( Abc_NtkIsStrash(pNtk->pExdc) ) + pNtkNew->pExdc = Abc_NtkAigToLogicSop( pNtk->pExdc ); + else + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAigToLogicSop(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the AIG into the logic network with SOPs for bench writing.] + + Description [This procedure does not copy the choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + Vec_Ptr_t * vNodes; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkGetChoiceNum(pNtk) ) + printf( "Warning: Choice nodes are skipped.\n" ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + // collect the nodes to be used (marks all nodes with current TravId) + vNodes = Abc_NtkDfs( pNtk, 0 ); + // create inverters for the CI and remember them + pObj = Abc_AigConst1(pNtk); + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + { + pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + } + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + // duplicate the nodes, create node functions, and inverters + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + pObj->pCopy->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, 2, NULL ); + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + } + // connect the objects + Vec_PtrForEachEntry( vNodes, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( Abc_ObjFaninC( pObj, k ) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + else + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + Vec_PtrFree( vNodes ); + // connect the COs + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pFanin = Abc_ObjFanin0(pObj); + if ( Abc_ObjFaninC0( pObj ) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + else + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + printf( "Warning: The EXDc network is skipped.\n" ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAigToLogicSopBench(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Adds buffers for each PO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pFanin, * pFaninNew; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pFanin = Abc_ObjChild0(pObj); + pFaninNew = Abc_NtkCreateNode(pNtk); + Abc_ObjAddFanin( pFaninNew, pFanin ); + Abc_ObjPatchFanin( pObj, pFanin, pFaninNew ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcNtk.c b/abc70930/src/base/abc/abcNtk.c new file mode 100644 index 00000000..adaaf7be --- /dev/null +++ b/abc70930/src/base/abc/abcNtk.c @@ -0,0 +1,1235 @@ +/**CFile**************************************************************** + + FileName [abcNtk.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Network creation/duplication/deletion procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcNtk.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "abcInt.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a new Ntk.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ) +{ + Abc_Ntk_t * pNtk; + pNtk = ALLOC( Abc_Ntk_t, 1 ); + memset( pNtk, 0, sizeof(Abc_Ntk_t) ); + pNtk->ntkType = Type; + pNtk->ntkFunc = Func; + // start the object storage + pNtk->vObjs = Vec_PtrAlloc( 100 ); + pNtk->vAsserts = Vec_PtrAlloc( 100 ); + pNtk->vPios = Vec_PtrAlloc( 100 ); + pNtk->vPis = Vec_PtrAlloc( 100 ); + pNtk->vPos = Vec_PtrAlloc( 100 ); + pNtk->vCis = Vec_PtrAlloc( 100 ); + pNtk->vCos = Vec_PtrAlloc( 100 ); + pNtk->vBoxes = Vec_PtrAlloc( 100 ); + // start the memory managers + pNtk->pMmObj = fUseMemMan? Extra_MmFixedStart( sizeof(Abc_Obj_t) ) : NULL; + pNtk->pMmStep = fUseMemMan? Extra_MmStepStart( ABC_NUM_STEPS ) : NULL; + // get ready to assign the first Obj ID + pNtk->nTravIds = 1; + // start the functionality manager + if ( Abc_NtkIsStrash(pNtk) ) + pNtk->pManFunc = Abc_AigAlloc( pNtk ); + else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + pNtk->pManFunc = Extra_MmFlexStart(); + else if ( Abc_NtkHasBdd(pNtk) ) + pNtk->pManFunc = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + else if ( Abc_NtkHasAig(pNtk) ) + pNtk->pManFunc = Hop_ManStart(); + else if ( Abc_NtkHasMapping(pNtk) ) + pNtk->pManFunc = Abc_FrameReadLibGen(); + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + // name manager + pNtk->pManName = Nm_ManCreate( 200 ); + // attribute manager + pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Starts a new network using existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + int fCopyNames, i; + if ( pNtk == NULL ) + return NULL; + // decide whether to copy the names + fCopyNames = ( Type != ABC_NTK_NETLIST ); + // start the network + pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // map the constant nodes + if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkDupBox( pNtkNew, pObj, fCopyNames ); + // transfer the names +// Abc_NtkTrasferNames( pNtk, pNtkNew ); + Abc_ManTimeDup( pNtk, pNtkNew ); + // check that the CI/CO/latches are copied correctly + assert( Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkNew) ); + assert( Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkNew) ); + assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Starts a new network using existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + int i; + if ( pNtk == NULL ) + return NULL; + assert( Type != ABC_NTK_NETLIST ); + // start the network + pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // map the constant nodes + if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + Abc_NtkDupBox(pNtkNew, pObj, 1); + } + // transfer the names +// Abc_NtkTrasferNamesNoLatches( pNtk, pNtkNew ); + Abc_ManTimeDup( pNtk, pNtkNew ); + // check that the CI/CO/latches are copied correctly + assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Finalizes the network using the existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj, * pDriver, * pDriverNew; + int i; + // set the COs of the strashed network + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) ); + pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj)); + Abc_ObjAddFanin( pObj->pCopy, pDriverNew ); + } +} + +/**Function************************************************************* + + Synopsis [Starts a new network using existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStartRead( char * pName ) +{ + Abc_Ntk_t * pNtkNew; + // allocate the empty network + pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); + // set the specs + pNtkNew->pName = Extra_FileNameGeneric(pName); + pNtkNew->pSpec = Extra_UtilStrsav(pName); + if ( pNtkNew->pName == NULL || strlen(pNtkNew->pName) == 0 ) + { + FREE( pNtkNew->pName ); + pNtkNew->pName = Extra_UtilStrsav("unknown"); + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Finalizes the network using the existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pBox, * pObj, * pTerm, * pNet; + int i; + if ( Abc_NtkHasBlackbox(pNtk) && Abc_NtkBoxNum(pNtk) == 0 ) + { + pBox = Abc_NtkCreateBlackbox(pNtk); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + pTerm = Abc_NtkCreateBi(pNtk); + Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) ); + Abc_ObjAddFanin( pBox, pTerm ); + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pTerm = Abc_NtkCreateBo(pNtk); + Abc_ObjAddFanin( pTerm, pBox ); + Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm ); + } + return; + } + assert( Abc_NtkIsNetlist(pNtk) ); + + // check if constant 0 net is used + pNet = Abc_NtkFindNet( pNtk, "1\'b0" ); + if ( pNet ) + { + if ( Abc_ObjFanoutNum(pNet) == 0 ) + Abc_NtkDeleteObj(pNet); + else if ( Abc_ObjFaninNum(pNet) == 0 ) + Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) ); + } + // check if constant 1 net is used + pNet = Abc_NtkFindNet( pNtk, "1\'b1" ); + if ( pNet ) + { + if ( Abc_ObjFanoutNum(pNet) == 0 ) + Abc_NtkDeleteObj(pNet); + else if ( Abc_ObjFaninNum(pNet) == 0 ) + Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) ); + } + // fix the net drivers + Abc_NtkFixNonDrivenNets( pNtk ); + + // reorder the CI/COs to PI/POs first + Abc_NtkOrderCisCos( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Duplicate the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + if ( pNtk == NULL ) + return NULL; + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); + // copy the internal nodes + if ( Abc_NtkIsStrash(pNtk) ) + { + // copy the AND gates + Abc_AigForEachAnd( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // relink the choice nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + if ( pObj->pData ) + pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy; + // relink the CO nodes + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + // get the number of nodes before and after + if ( Abc_NtkNodeNum(pNtk) != Abc_NtkNodeNum(pNtkNew) ) + printf( "Warning: Structural hashing during duplication reduced %d nodes (this is a minor bug).\n", + Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNtkNew) ); + } + else + { + // duplicate the nets and nodes (CIs/COs/latches already dupped) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy == NULL ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); + pNtk->pCopy = pNtkNew; + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Duplicate the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk ) +{ + char Buffer[500]; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + assert( Abc_NtkIsLogic(pNtk) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + sprintf( Buffer, "%s%s", pNtk->pName, "_2x" ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkDupBox( pNtkNew, pObj, 0 ); + // copy the internal nodes + // duplicate the nets and nodes (CIs/COs/latches already dupped) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy == NULL ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkDupBox( pNtkNew, pObj, 0 ); + // copy the internal nodes + // duplicate the nets and nodes (CIs/COs/latches already dupped) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy == NULL ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // assign names + Abc_NtkForEachCi( pNtk, pObj, i ) + { + Abc_ObjAssignName( Abc_NtkCi(pNtkNew, i), "1_", Abc_ObjName(pObj) ); + Abc_ObjAssignName( Abc_NtkCi(pNtkNew, Abc_NtkCiNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); + } + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_ObjAssignName( Abc_NtkCo(pNtkNew, i), "1_", Abc_ObjName(pObj) ); + Abc_ObjAssignName( Abc_NtkCo(pNtkNew, Abc_NtkCoNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); + } + + // perform the final check + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Attaches the second network at the bottom of the first.] + + Description [Returns the first network. Deletes the second network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom ) +{ + Abc_Obj_t * pObj, * pFanin, * pBuffer; + Vec_Ptr_t * vNodes; + int i, k; + assert( pNtkBottom != NULL ); + if ( pNtkTop == NULL ) + return pNtkBottom; + // make sure the networks are combinational + assert( Abc_NtkPiNum(pNtkTop) == Abc_NtkCiNum(pNtkTop) ); + assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkCiNum(pNtkBottom) ); + // make sure the POs of the bottom correspond to the PIs of the top + assert( Abc_NtkPoNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); + assert( Abc_NtkPiNum(pNtkBottom) < Abc_NtkPiNum(pNtkTop) ); + // add buffers for the PIs of the top - save results in the POs of the bottom + Abc_NtkForEachPi( pNtkTop, pObj, i ) + { + pBuffer = Abc_NtkCreateNodeBuf( pNtkTop, NULL ); + Abc_ObjTransferFanout( pObj, pBuffer ); + Abc_NtkPo(pNtkBottom, i)->pCopy = pBuffer; + } + // remove useless PIs of the top + for ( i = Abc_NtkPiNum(pNtkTop) - 1; i >= Abc_NtkPiNum(pNtkBottom); i-- ) + Abc_NtkDeleteObj( Abc_NtkPi(pNtkTop, i) ); + assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); + // copy the bottom network + Abc_NtkForEachPi( pNtkBottom, pObj, i ) + Abc_NtkPi(pNtkBottom, i)->pCopy = Abc_NtkPi(pNtkTop, i); + // construct all nodes + vNodes = Abc_NtkDfs( pNtkBottom, 0 ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + Abc_NtkDupObj(pNtkTop, pObj, 0); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + Vec_PtrFree( vNodes ); + // connect the POs + Abc_NtkForEachPo( pNtkBottom, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); + // delete old network + Abc_NtkDelete( pNtkBottom ); + // return the network + if ( !Abc_NtkCheck( pNtkTop ) ) + fprintf( stdout, "Abc_NtkAttachBottom(): Network check has failed.\n" ); + return pNtkTop; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of one logic cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ) +{ + Abc_Ntk_t * pNtkNew; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; + char Buffer[1000]; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // set the name + sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // establish connection between the constant nodes + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // collect the nodes in the TFI of the output (mark the TFI) + vNodes = Abc_NtkDfsNodes( pNtk, &pNode, 1 ); + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + } + // add the PO corresponding to this output + pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); + // copy the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // if it is an AIG, add to the hash table + if ( Abc_NtkIsStrash(pNtk) ) + { + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + } + else + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + } + // connect the internal nodes to the new CO + Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); + Vec_PtrFree( vNodes ); + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of several logic cones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis ) +{ + Abc_Ntk_t * pNtkNew; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; + char Buffer[1000]; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // set the name + sprintf( Buffer, "%s_part", pNtk->pName ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // establish connection between the constant nodes + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // collect the nodes in the TFI of the output (mark the TFI) + vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); + + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + } + + // copy the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // if it is an AIG, add to the hash table + if ( Abc_NtkIsStrash(pNtk) ) + { + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + } + else + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + } + Vec_PtrFree( vNodes ); + + // add the POs corresponding to the root nodes + Vec_PtrForEachEntry( vRoots, pObj, i ) + { + // create the PO node + pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); + // connect the internal nodes to the new CO + if ( Abc_ObjIsCo(pObj) ) + Abc_ObjAddFanin( pNodeCoNew, Abc_ObjChild0Copy(pObj) ); + else + Abc_ObjAddFanin( pNodeCoNew, pObj->pCopy ); + // assign the name + Abc_ObjAssignName( pNodeCoNew, Abc_ObjName(pObj), NULL ); + } + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateConeArray(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Adds new nodes to the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i, iNodeId; + + assert( Abc_NtkIsStrash(pNtkNew) ); + assert( Abc_NtkIsStrash(pNtk) ); + + // collect the nodes in the TFI of the output (mark the TFI) + vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); + + // establish connection between the constant nodes + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + // skip CIs that are not used + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + continue; + // find the corresponding CI in the new network + iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); + if ( iNodeId == -1 ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + else + pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); + } + + // copy the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + Vec_PtrFree( vNodes ); + + // do not add the COs + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAppendToCone(): Network check has failed.\n" ); +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of MFFC of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; + Vec_Ptr_t * vCone, * vSupp; + char Buffer[1000]; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // set the name + sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // establish connection between the constant nodes + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // collect the nodes in MFFC + vCone = Vec_PtrAlloc( 100 ); + vSupp = Vec_PtrAlloc( 100 ); + Abc_NodeDeref_rec( pNode ); + Abc_NodeMffsConeSupp( pNode, vCone, vSupp ); + Abc_NodeRef_rec( pNode ); + // create the PIs + Vec_PtrForEachEntry( vSupp, pObj, i ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + // create the PO + pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); + // copy the nodes + Vec_PtrForEachEntry( vCone, pObj, i ) + { + // if it is an AIG, add to the hash table + if ( Abc_NtkIsStrash(pNtk) ) + { + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + } + else + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + } + // connect the topmost node + Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSupp ); + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateMffc(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the miter composed of one multi-output cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFinal, * pOther, * pNodePo; + int i; + + assert( Abc_NtkIsLogic(pNtk) ); + + // start the network + Abc_NtkCleanCopy( pNtk ); + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + + // collect the nodes in the TFI of the output + vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)vRoots->pArray, vRoots->nSize ); + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + // copy the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pCopy = Abc_NodeStrash( pNtkNew, pObj, 0 ); + Vec_PtrFree( vNodes ); + + // add the PO + pFinal = Abc_AigConst1( pNtkNew ); + Vec_PtrForEachEntry( vRoots, pObj, i ) + { + if ( Abc_ObjIsCo(pObj) ) + pOther = Abc_ObjFanin0(pObj)->pCopy; + else + pOther = pObj->pCopy; + if ( Vec_IntEntry(vValues, i) == 0 ) + pOther = Abc_ObjNot(pOther); + pFinal = Abc_AigAnd( pNtkNew->pManFunc, pFinal, pOther ); + } + + // add the PO corresponding to this output + pNodePo = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pNodePo, pFinal ); + Abc_ObjAssignName( pNodePo, "miter", NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateTarget(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pFanin, * pNodePo; + int i; + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + pNtkNew->pName = Extra_UtilStrsav(Abc_ObjName(pNode)); + // add the PIs corresponding to the fanins of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + pFanin->pCopy = Abc_NtkCreatePi( pNtkNew ); + Abc_ObjAssignName( pFanin->pCopy, Abc_ObjName(pFanin), NULL ); + } + // duplicate and connect the node + pNode->pCopy = Abc_NtkDupObj( pNtkNew, pNode, 0 ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy ); + // create the only PO + pNodePo = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pNodePo, pNode->pCopy ); + Abc_ObjAssignName( pNodePo, Abc_ObjName(pNode), NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of one node with the given SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pFanin, * pNode, * pNodePo; + Vec_Ptr_t * vNames; + int i, nVars; + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtkNew->pName = Extra_UtilStrsav("ex"); + // create PIs + Vec_PtrPush( pNtkNew->vObjs, NULL ); + nVars = Abc_SopGetVarNum( pSop ); + vNames = Abc_NodeGetFakeNames( nVars ); + for ( i = 0; i < nVars; i++ ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Vec_PtrEntry(vNames, i), NULL ); + Abc_NodeFreeNames( vNames ); + // create the node, add PIs as fanins, set the function + pNode = Abc_NtkCreateNode( pNtkNew ); + Abc_NtkForEachPi( pNtkNew, pFanin, i ) + Abc_ObjAddFanin( pNode, pFanin ); + pNode->pData = Abc_SopRegister( pNtkNew->pManFunc, pSop ); + // create the only PO + pNodePo = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAddFanin( pNodePo, pNode ); + Abc_ObjAssignName( pNodePo, "F", NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateWithNode(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Deletes the Ntk.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDelete( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + void * pAttrMan; + int TotalMemory, i; + int LargePiece = (4 << ABC_NUM_STEPS); + if ( pNtk == NULL ) + return; + // free the HAIG + if ( pNtk->pHaig ) + Abc_NtkHaigStop( pNtk ); + // free EXDC Ntk + if ( pNtk->pExdc ) + Abc_NtkDelete( pNtk->pExdc ); + // dereference the BDDs + if ( Abc_NtkHasBdd(pNtk) ) + { + Abc_NtkForEachNode( pNtk, pObj, i ) + Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData ); + } + // make sure all the marks are clean + Abc_NtkForEachObj( pNtk, pObj, i ) + { + // free large fanout arrays + if ( pNtk->pMmObj && pObj->vFanouts.nCap * 4 > LargePiece ) + FREE( pObj->vFanouts.pArray ); + // these flags should be always zero + // if this is not true, something is wrong somewhere + assert( pObj->fMarkA == 0 ); + assert( pObj->fMarkB == 0 ); + assert( pObj->fMarkC == 0 ); + } + // free the nodes + if ( pNtk->pMmStep == NULL ) + { + Abc_NtkForEachObj( pNtk, pObj, i ) + { + FREE( pObj->vFanouts.pArray ); + FREE( pObj->vFanins.pArray ); + } + } + if ( pNtk->pMmObj == NULL ) + { + Abc_NtkForEachObj( pNtk, pObj, i ) + free( pObj ); + } + + // free the arrays + Vec_PtrFree( pNtk->vPios ); + Vec_PtrFree( pNtk->vPis ); + Vec_PtrFree( pNtk->vPos ); + Vec_PtrFree( pNtk->vCis ); + Vec_PtrFree( pNtk->vCos ); + Vec_PtrFree( pNtk->vAsserts ); + Vec_PtrFree( pNtk->vObjs ); + Vec_PtrFree( pNtk->vBoxes ); + if ( pNtk->vLevelsR ) Vec_IntFree( pNtk->vLevelsR ); + if ( pNtk->pModel ) free( pNtk->pModel ); + TotalMemory = 0; + TotalMemory += pNtk->pMmObj? Extra_MmFixedReadMemUsage(pNtk->pMmObj) : 0; + TotalMemory += pNtk->pMmStep? Extra_MmStepReadMemUsage(pNtk->pMmStep) : 0; +// fprintf( stdout, "The total memory allocated internally by the network = %0.2f Mb.\n", ((double)TotalMemory)/(1<<20) ); + // free the storage + if ( pNtk->pMmObj ) + Extra_MmFixedStop( pNtk->pMmObj ); + if ( pNtk->pMmStep ) + Extra_MmStepStop ( pNtk->pMmStep ); + // name manager + Nm_ManFree( pNtk->pManName ); + // free the timing manager + if ( pNtk->pManTime ) + Abc_ManTimeStop( pNtk->pManTime ); + // start the functionality manager + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigFree( pNtk->pManFunc ); + else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + Extra_MmFlexStop( pNtk->pManFunc ); + else if ( Abc_NtkHasBdd(pNtk) ) + Extra_StopManager( pNtk->pManFunc ); + else if ( Abc_NtkHasAig(pNtk) ) + { if ( pNtk->pManFunc ) Hop_ManStop( pNtk->pManFunc ); } + else if ( Abc_NtkHasMapping(pNtk) ) + pNtk->pManFunc = NULL; + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + // free the hierarchy + if ( pNtk->pDesign ) + { + Abc_LibFree( pNtk->pDesign, pNtk ); + pNtk->pDesign = NULL; + } +// if ( pNtk->pBlackBoxes ) +// Vec_IntFree( pNtk->pBlackBoxes ); + // free node attributes + Vec_PtrForEachEntry( pNtk->vAttrs, pAttrMan, i ) + if ( pAttrMan ) + { +//printf( "deleting attr\n" ); + Vec_AttFree( pAttrMan, 1 ); + } + Vec_PtrFree( pNtk->vAttrs ); + FREE( pNtk->pName ); + FREE( pNtk->pSpec ); + free( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Reads the verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNets; + Abc_Obj_t * pNet, * pNode; + int i; + + if ( Abc_NtkNodeNum(pNtk) == 0 && Abc_NtkBoxNum(pNtk) == 0 ) + return; + + // check for non-driven nets + vNets = Vec_PtrAlloc( 100 ); + Abc_NtkForEachNet( pNtk, pNet, i ) + { + if ( Abc_ObjFaninNum(pNet) > 0 ) + continue; + // add the constant 0 driver + pNode = Abc_NtkCreateNodeConst0( pNtk ); + // add the fanout net + Abc_ObjAddFanin( pNet, pNode ); + // add the net to those for which the warning will be printed + Vec_PtrPush( vNets, pNet ); + } + + // print the warning + if ( vNets->nSize > 0 ) + { + printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName ); + Vec_PtrForEachEntry( vNets, pNet, i ) + { + printf( "%s%s", (i? ", ": ""), Abc_ObjName(pNet) ); + if ( i == 3 ) + { + if ( Vec_PtrSize(vNets) > 3 ) + printf( " ..." ); + break; + } + } + printf( "\n" ); + } + Vec_PtrFree( vNets ); +} + + +/**Function************************************************************* + + Synopsis [Converts the network to combinational.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMakeComb( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + if ( Abc_NtkIsComb(pNtk) ) + return; + + assert( !Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + + // detach the latches +// Abc_NtkForEachLatch( pNtk, pObj, i ) + Vec_PtrForEachEntryReverse( pNtk->vBoxes, pObj, i ) + Abc_NtkDeleteObj( pObj ); + assert( Abc_NtkLatchNum(pNtk) == 0 ); + assert( Abc_NtkBoxNum(pNtk) == 0 ); + + // move CIs to become PIs + Vec_PtrClear( pNtk->vPis ); + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( Abc_ObjIsBo(pObj) ) + { + pObj->Type = ABC_OBJ_PI; + pNtk->nObjCounts[ABC_OBJ_PI]++; + pNtk->nObjCounts[ABC_OBJ_BO]--; + } + Vec_PtrPush( pNtk->vPis, pObj ); + } + assert( Abc_NtkBoNum(pNtk) == 0 ); + + // move COs to become POs + Vec_PtrClear( pNtk->vPos ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( Abc_ObjIsBi(pObj) ) + { + pObj->Type = ABC_OBJ_PO; + pNtk->nObjCounts[ABC_OBJ_PO]++; + pNtk->nObjCounts[ABC_OBJ_BI]--; + } + Vec_PtrPush( pNtk->vPos, pObj ); + } + assert( Abc_NtkBiNum(pNtk) == 0 ); + + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" ); +} + + +/**Function************************************************************* + + Synopsis [Removes POs with suppsize less than 2 and PIs without fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i, k, m; + + // filter POs + k = m = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( Abc_ObjIsPo(pObj) ) + { + // remove constant nodes and PI pointers + if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 0 ) + { + Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); + if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 && !Abc_ObjIsPi(Abc_ObjFanin0(pObj)) ) + Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); + pNtk->vObjs->pArray[pObj->Id] = NULL; + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + Abc_ObjRecycle( pObj ); + continue; + } + // remove buffers/inverters of PIs + if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 1 ) + { + if ( Abc_ObjIsPi(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) ) + { + Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); + if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 ) + Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); + pNtk->vObjs->pArray[pObj->Id] = NULL; + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + Abc_ObjRecycle( pObj ); + continue; + } + } + Vec_PtrWriteEntry( pNtk->vPos, m++, pObj ); + } + Vec_PtrWriteEntry( pNtk->vCos, k++, pObj ); + } + Vec_PtrShrink( pNtk->vPos, m ); + Vec_PtrShrink( pNtk->vCos, k ); + + // filter PIs + k = m = 0; + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( Abc_ObjIsPi(pObj) ) + { + if ( Abc_ObjFanoutNum(pObj) == 0 ) + { + pNtk->vObjs->pArray[pObj->Id] = NULL; + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + Abc_ObjRecycle( pObj ); + continue; + } + Vec_PtrWriteEntry( pNtk->vPis, m++, pObj ); + } + Vec_PtrWriteEntry( pNtk->vCis, k++, pObj ); + } + Vec_PtrShrink( pNtk->vPis, m ); + Vec_PtrShrink( pNtk->vCis, k ); + + return Abc_NtkDup( pNtk ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcObj.c b/abc70930/src/base/abc/abcObj.c new file mode 100644 index 00000000..7a995c71 --- /dev/null +++ b/abc70930/src/base/abc/abcObj.c @@ -0,0 +1,976 @@ +/**CFile**************************************************************** + + FileName [abcObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Object creation/duplication/deletion procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcObj.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "abcInt.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a new object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) +{ + Abc_Obj_t * pObj; + if ( pNtk->pMmObj ) + pObj = (Abc_Obj_t *)Extra_MmFixedEntryFetch( pNtk->pMmObj ); + else + pObj = (Abc_Obj_t *)ALLOC( Abc_Obj_t, 1 ); + memset( pObj, 0, sizeof(Abc_Obj_t) ); + pObj->pNtk = pNtk; + pObj->Type = Type; + pObj->Id = -1; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Recycles the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjRecycle( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + int LargePiece = (4 << ABC_NUM_STEPS); + // free large fanout arrays + if ( pNtk->pMmStep && pObj->vFanouts.nCap * 4 > LargePiece ) + FREE( pObj->vFanouts.pArray ); + if ( pNtk->pMmStep == NULL ) + { + FREE( pObj->vFanouts.pArray ); + FREE( pObj->vFanins.pArray ); + } + // clean the memory to make deleted object distinct from the live one + memset( pObj, 0, sizeof(Abc_Obj_t) ); + // recycle the object + if ( pNtk->pMmObj ) + Extra_MmFixedEntryRecycle( pNtk->pMmObj, (char *)pObj ); + else + free( pObj ); +} + +/**Function************************************************************* + + Synopsis [Adds the node to the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) +{ + Abc_Obj_t * pObj; + // create new object, assign ID, and add to the array + pObj = Abc_ObjAlloc( pNtk, Type ); + pObj->Id = pNtk->vObjs->nSize; + Vec_PtrPush( pNtk->vObjs, pObj ); + pNtk->nObjCounts[Type]++; + pNtk->nObjs++; + // perform specialized operations depending on the object type + switch (Type) + { + case ABC_OBJ_NONE: + assert(0); + break; + case ABC_OBJ_CONST1: + assert(0); + break; + case ABC_OBJ_PIO: + assert(0); + break; + case ABC_OBJ_PI: + Vec_PtrPush( pNtk->vPis, pObj ); + Vec_PtrPush( pNtk->vCis, pObj ); + break; + case ABC_OBJ_PO: + Vec_PtrPush( pNtk->vPos, pObj ); + Vec_PtrPush( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BI: + if ( pNtk->vCos ) Vec_PtrPush( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BO: + if ( pNtk->vCis ) Vec_PtrPush( pNtk->vCis, pObj ); + break; + case ABC_OBJ_ASSERT: + Vec_PtrPush( pNtk->vAsserts, pObj ); + Vec_PtrPush( pNtk->vCos, pObj ); + break; + case ABC_OBJ_NET: + case ABC_OBJ_NODE: + break; + case ABC_OBJ_LATCH: + pObj->pData = (void *)ABC_INIT_NONE; + case ABC_OBJ_WHITEBOX: + case ABC_OBJ_BLACKBOX: + if ( pNtk->vBoxes ) Vec_PtrPush( pNtk->vBoxes, pObj ); + break; + default: + assert(0); + break; + } + return pObj; +} + +/**Function************************************************************* + + Synopsis [Deletes the object from the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDeleteObj( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + Vec_Ptr_t * vNodes; + int i; + assert( !Abc_ObjIsComplement(pObj) ); + // remove from the table of names + if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) ) + Nm_ManDeleteIdName(pObj->pNtk->pManName, pObj->Id); + // delete fanins and fanouts + vNodes = Vec_PtrAlloc( 100 ); + Abc_NodeCollectFanouts( pObj, vNodes ); + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_ObjDeleteFanin( vNodes->pArray[i], pObj ); + Abc_NodeCollectFanins( pObj, vNodes ); + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_ObjDeleteFanin( pObj, vNodes->pArray[i] ); + Vec_PtrFree( vNodes ); + // remove from the list of objects + Vec_PtrWriteEntry( pNtk->vObjs, pObj->Id, NULL ); + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + // perform specialized operations depending on the object type + switch (pObj->Type) + { + case ABC_OBJ_NONE: + assert(0); + break; + case ABC_OBJ_CONST1: + assert(0); + break; + case ABC_OBJ_PIO: + assert(0); + break; + case ABC_OBJ_PI: + Vec_PtrRemove( pNtk->vPis, pObj ); + Vec_PtrRemove( pNtk->vCis, pObj ); + break; + case ABC_OBJ_PO: + Vec_PtrRemove( pNtk->vPos, pObj ); + Vec_PtrRemove( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BI: + if ( pNtk->vCos ) Vec_PtrRemove( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BO: + if ( pNtk->vCis ) Vec_PtrRemove( pNtk->vCis, pObj ); + break; + case ABC_OBJ_ASSERT: + Vec_PtrRemove( pNtk->vAsserts, pObj ); + Vec_PtrRemove( pNtk->vCos, pObj ); + break; + case ABC_OBJ_NET: + break; + case ABC_OBJ_NODE: + if ( Abc_NtkHasBdd(pNtk) ) + Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData ); + pObj->pData = NULL; + break; + case ABC_OBJ_LATCH: + case ABC_OBJ_WHITEBOX: + case ABC_OBJ_BLACKBOX: + if ( pNtk->vBoxes ) Vec_PtrRemove( pNtk->vBoxes, pObj ); + break; + default: + assert(0); + break; + } + // recycle the object memory + Abc_ObjRecycle( pObj ); +} + +/**Function************************************************************* + + Synopsis [Deletes the node and MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + assert( !Abc_ObjIsComplement(pObj) ); + assert( !Abc_ObjIsPi(pObj) ); + assert( Abc_ObjFanoutNum(pObj) == 0 ); + // delete fanins and fanouts + vNodes = Vec_PtrAlloc( 100 ); + Abc_NodeCollectFanins( pObj, vNodes ); + Abc_NtkDeleteObj( pObj ); + if ( fOnlyNodes ) + { + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) + Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); + } + else + { + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( !Abc_ObjIsPi(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) + Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); + } + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Deletes the node and MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ) +{ + Vec_Ptr_t * vNodes; + int i; + assert( !Abc_ObjIsComplement(pObj) ); + assert( Abc_ObjFanoutNum(pObj) == 0 ); + // delete fanins and fanouts + vNodes = Vec_PtrAlloc( 100 ); + Abc_NodeCollectFanins( pObj, vNodes ); + Abc_NtkDeleteObj( pObj ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( !Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) + Abc_NtkDeleteAll_rec( pObj ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Duplicate the Obj.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName ) +{ + Abc_Obj_t * pObjNew; + // create the new object + pObjNew = Abc_NtkCreateObj( pNtkNew, pObj->Type ); + // transfer names of the terminal objects + if ( fCopyName ) + { + if ( Abc_ObjIsCi(pObj) ) + { + if ( !Abc_NtkIsNetlist(pNtkNew) ) + Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); + } + else if ( Abc_ObjIsCo(pObj) ) + { + if ( !Abc_NtkIsNetlist(pNtkNew) ) + { + if ( Abc_ObjIsPo(pObj) ) + Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); + else + { + assert( Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ); + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + } + } + } + else if ( Abc_ObjIsBox(pObj) || Abc_ObjIsNet(pObj) ) + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + } + // copy functionality/names + if ( Abc_ObjIsNode(pObj) ) // copy the function if functionality is compatible + { + if ( pNtkNew->ntkFunc == pObj->pNtk->ntkFunc ) + { + if ( Abc_NtkIsStrash(pNtkNew) ) + {} + else if ( Abc_NtkHasSop(pNtkNew) || Abc_NtkHasBlifMv(pNtkNew) ) + pObjNew->pData = Abc_SopRegister( pNtkNew->pManFunc, pObj->pData ); + else if ( Abc_NtkHasBdd(pNtkNew) ) + pObjNew->pData = Cudd_bddTransfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData), Cudd_Ref(pObjNew->pData); + else if ( Abc_NtkHasAig(pNtkNew) ) + pObjNew->pData = Hop_Transfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData, Abc_ObjFaninNum(pObj)); + else if ( Abc_NtkHasMapping(pNtkNew) ) + pObjNew->pData = pObj->pData; + else assert( 0 ); + } + } + else if ( Abc_ObjIsNet(pObj) ) // copy the name + { + } + else if ( Abc_ObjIsLatch(pObj) ) // copy the reset value + pObjNew->pData = pObj->pData; + // transfer HAIG +// pObjNew->pEquiv = pObj->pEquiv; + // remember the new node in the old node + pObj->pCopy = pObjNew; + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the latch with its input/output terminals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName ) +{ + Abc_Obj_t * pTerm, * pBoxNew; + int i; + assert( Abc_ObjIsBox(pBox) ); + // duplicate the box + pBoxNew = Abc_NtkDupObj( pNtkNew, pBox, fCopyName ); + // duplicate the fanins and connect them + Abc_ObjForEachFanin( pBox, pTerm, i ) + Abc_ObjAddFanin( pBoxNew, Abc_NtkDupObj(pNtkNew, pTerm, fCopyName) ); + // duplicate the fanouts and connect them + Abc_ObjForEachFanout( pBox, pTerm, i ) + Abc_ObjAddFanin( Abc_NtkDupObj(pNtkNew, pTerm, fCopyName), pBoxNew ); + return pBoxNew; +} + +/**Function************************************************************* + + Synopsis [Clones the objects in the same network but does not assign its function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pClone, * pFanin; + int i; + pClone = Abc_NtkCreateObj( pObj->pNtk, pObj->Type ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_ObjAddFanin( pClone, pFanin ); + return pClone; +} + + +/**Function************************************************************* + + Synopsis [Returns the net with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pObj; + int Num; + // try to find the terminal + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO ); + if ( Num >= 0 ) + return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI ); + if ( Num >= 0 ) + return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NODE ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + // find the internal node + if ( pName[0] != 'n' ) + { + printf( "Name \"%s\" is not found among CO or node names (internal names often look as \"n\").\n", pName ); + return NULL; + } + Num = atoi( pName + 1 ); + if ( Num < 0 || Num >= Abc_NtkObjNumMax(pNtk) ) + { + printf( "The node \"%s\" with ID %d is not in the current network.\n", pName, Num ); + return NULL; + } + pObj = Abc_NtkObj( pNtk, Num ); + if ( pObj == NULL ) + { + printf( "The node \"%s\" with ID %d has been removed from the current network.\n", pName, Num ); + return NULL; + } + if ( !Abc_ObjIsNode(pObj) ) + { + printf( "Object with ID %d is not a node.\n", Num ); + return NULL; + } + return pObj; +} + +/**Function************************************************************* + + Synopsis [Returns the net with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet; + int ObjId; + assert( Abc_NtkIsNetlist(pNtk) ); + ObjId = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NET ); + if ( ObjId == -1 ) + return NULL; + pNet = Abc_NtkObj( pNtk, ObjId ); + return pNet; +} + +/**Function************************************************************* + + Synopsis [Returns CI with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName ) +{ + int Num; + assert( !Abc_NtkIsNetlist(pNtk) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PI ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BO ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns CO with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ) +{ + int Num; + assert( !Abc_NtkIsNetlist(pNtk) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Finds or creates the net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet; + assert( Abc_NtkIsNetlist(pNtk) ); + if ( pName && (pNet = Abc_NtkFindNet( pNtk, pName )) ) + return pNet; +//printf( "Creating net %s.\n", pName ); + // create a new net + pNet = Abc_NtkCreateNet( pNtk ); + if ( pName ) + Nm_ManStoreIdName( pNtk->pManName, pNet->Id, pNet->Type, pName, NULL ); + return pNet; +} + +/**Function************************************************************* + + Synopsis [Creates constant 0 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_ReadLogicZero(pNtk->pManFunc), Cudd_Ref( pNode->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_ManConst0(pNtk->pManFunc); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadConst0(Abc_FrameReadLibGen()); + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 1\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_ReadOne(pNtk->pManFunc), Cudd_Ref( pNode->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_ManConst1(pNtk->pManFunc); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadConst1(Abc_FrameReadLibGen()); + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates inverter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopRegister( pNtk->pManFunc, "0 1\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_Not(Cudd_bddIthVar(pNtk->pManFunc,0)), Cudd_Ref( pNode->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_Not(Hop_IthVar(pNtk->pManFunc,0)); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadInv(Abc_FrameReadLibGen()); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopRegister( pNtk->pManFunc, "1 1\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_bddIthVar(pNtk->pManFunc,0), Cudd_Ref( pNode->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_IthVar(pNtk->pManFunc,0); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadBuf(Abc_FrameReadLibGen()); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates AND.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < vFanins->nSize; i++ ) + Abc_ObjAddFanin( pNode, vFanins->pArray[i] ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopCreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins), NULL ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Extra_bddCreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins) ); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < vFanins->nSize; i++ ) + Abc_ObjAddFanin( pNode, vFanins->pArray[i] ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopCreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins), NULL ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Extra_bddCreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_CreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins) ); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates EXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < vFanins->nSize; i++ ) + Abc_ObjAddFanin( pNode, vFanins->pArray[i] ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopCreateXorSpecial( pNtk->pManFunc, Vec_PtrSize(vFanins) ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Extra_bddCreateExor( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_CreateExor( pNtk->pManFunc, Vec_PtrSize(vFanins) ); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates MUX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + Abc_ObjAddFanin( pNode, pNodeC ); + Abc_ObjAddFanin( pNode, pNode1 ); + Abc_ObjAddFanin( pNode, pNode0 ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopRegister( pNtk->pManFunc, "11- 1\n0-1 1\n" ); + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_bddIte(pNtk->pManFunc,Cudd_bddIthVar(pNtk->pManFunc,0),Cudd_bddIthVar(pNtk->pManFunc,1),Cudd_bddIthVar(pNtk->pManFunc,2)), Cudd_Ref( pNode->pData ); + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_Mux(pNtk->pManFunc,Hop_IthVar(pNtk->pManFunc,0),Hop_IthVar(pNtk->pManFunc,1),Hop_IthVar(pNtk->pManFunc,2)); + else + assert( 0 ); + return pNode; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a constant 0 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsConst( Abc_Obj_t * pNode ) +{ + assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) ); + return Abc_ObjIsNode(pNode) && Abc_ObjFaninNum(pNode) == 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a constant 0 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsConst0( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( !Abc_NodeIsConst(pNode) ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsConst0(pNode->pData); + if ( Abc_NtkHasBdd(pNtk) ) + return Cudd_IsComplement(pNode->pData); + if ( Abc_NtkHasAig(pNtk) ) + return Hop_IsComplement(pNode->pData); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadConst0(Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsConst1( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( !Abc_NodeIsConst(pNode) ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsConst1(pNode->pData); + if ( Abc_NtkHasBdd(pNtk) ) + return !Cudd_IsComplement(pNode->pData); + if ( Abc_NtkHasAig(pNtk) ) + return !Hop_IsComplement(pNode->pData); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadConst1(Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsBuf( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 1 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsBuf(pNode->pData); + if ( Abc_NtkHasBdd(pNtk) ) + return !Cudd_IsComplement(pNode->pData); + if ( Abc_NtkHasAig(pNtk) ) + return !Hop_IsComplement(pNode->pData); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadBuf(Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is an inverter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsInv( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 1 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsInv(pNode->pData); + if ( Abc_NtkHasBdd(pNtk) ) + return Cudd_IsComplement(pNode->pData); + if ( Abc_NtkHasAig(pNtk) ) + return Hop_IsComplement(pNode->pData); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadInv(Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Complements the local functions of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeComplement( Abc_Obj_t * pNode ) +{ + assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_NtkHasSop(pNode->pNtk) ) + Abc_SopComplement( pNode->pData ); + else if ( Abc_NtkHasBdd(pNode->pNtk) ) + pNode->pData = Cudd_Not( pNode->pData ); + else if ( Abc_NtkHasAig(pNode->pNtk) ) + pNode->pData = Hop_Not( pNode->pData ); + else + assert( 0 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/abc/abcRefs.c b/abc70930/src/base/abc/abcRefs.c new file mode 100644 index 00000000..604c5ffa --- /dev/null +++ b/abc70930/src/base/abc/abcRefs.c @@ -0,0 +1,452 @@ +/**CFile**************************************************************** + + FileName [abcRefs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures using reference counting of the AIG nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRefs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel ); +static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the MFFC size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcSize( Abc_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; +// assert( Abc_NtkIsStrash(pNode->pNtk) ); +// assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + if ( Abc_ObjFaninNum(pNode) == 0 ) + return 0; + nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference + nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [Returns the MFFC size while stopping at the complemented edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; + assert( Abc_NtkIsStrash(pNode->pNtk) ); + assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + if ( Abc_ObjFaninNum(pNode) == 0 ) + return 0; + nConeSize1 = Abc_NodeRefDerefStop( pNode, 0 ); // dereference + nConeSize2 = Abc_NodeRefDerefStop( pNode, 1 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [Labels MFFC with the current traversal ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; + assert( Abc_NtkIsStrash(pNode->pNtk) ); + assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + if ( Abc_ObjFaninNum(pNode) == 0 ) + return 0; + nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1 ); // dereference + nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [References/references the node and returns MFFC size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel ) +{ + Abc_Obj_t * pNode0, * pNode1; + int Counter; + // label visited nodes + if ( fLabel ) + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCi(pNode) ) + return 0; + // process the internal node + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + Counter = 1; + if ( fReference ) + { + if ( pNode0->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); + if ( pNode1->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); + } + else + { + assert( pNode0->vFanouts.nSize > 0 ); + assert( pNode1->vFanouts.nSize > 0 ); + if ( --pNode0->vFanouts.nSize == 0 ) + Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); + if ( --pNode1->vFanouts.nSize == 0 ) + Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [References/references the node and returns MFFC size.] + + Description [Stops at the complemented edges.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference ) +{ + Abc_Obj_t * pNode0, * pNode1; + int Counter; + // skip the CI + if ( Abc_ObjIsCi(pNode) ) + return 0; + // process the internal node + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + Counter = 1; + if ( fReference ) + { + if ( pNode0->vFanouts.nSize++ == 0 && !Abc_ObjFaninC0(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode0, fReference ); + if ( pNode1->vFanouts.nSize++ == 0 && !Abc_ObjFaninC1(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode1, fReference ); + } + else + { + assert( pNode0->vFanouts.nSize > 0 ); + assert( pNode1->vFanouts.nSize > 0 ); + if ( --pNode0->vFanouts.nSize == 0 && !Abc_ObjFaninC0(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode0, fReference ); + if ( --pNode1->vFanouts.nSize == 0 && !Abc_ObjFaninC1(pNode) ) + Counter += Abc_NodeRefDerefStop( pNode1, fReference ); + } + return Counter; +} + + + + +/**Function************************************************************* + + Synopsis [Dereferences the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeDeref_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i, Counter = 1; + if ( Abc_ObjIsCi(pNode) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + assert( pFanin->vFanouts.nSize > 0 ); + if ( --pFanin->vFanouts.nSize == 0 ) + Counter += Abc_NodeDeref_rec( pFanin ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRef_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i, Counter = 1; + if ( Abc_ObjIsCi(pNode) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pFanin->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRef_rec( pFanin ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffsConeSupp_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost ) +{ + Abc_Obj_t * pFanin; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + Abc_NodeSetTravIdCurrent(pNode); + // add to the new support nodes + if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) ) + { + if ( vSupp ) Vec_PtrPush( vSupp, pNode ); + return; + } + // recur on the children + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NodeMffsConeSupp_rec( pFanin, vCone, vSupp, 0 ); + // collect the internal node + if ( vCone ) Vec_PtrPush( vCone, pNode ); +// printf( "%d ", pNode->Id ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ) +{ + assert( Abc_ObjIsNode(pNode) ); + assert( !Abc_ObjIsComplement(pNode) ); + if ( vCone ) Vec_PtrClear( vCone ); + if ( vSupp ) Vec_PtrClear( vSupp ); + Abc_NtkIncrementTravId( pNode->pNtk ); + Abc_NodeMffsConeSupp_rec( pNode, vCone, vSupp, 1 ); +// printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vCone, * vSupp; + Abc_Obj_t * pObj; + int i; + vCone = Vec_PtrAlloc( 100 ); + vSupp = Vec_PtrAlloc( 100 ); + Abc_NodeDeref_rec( pNode ); + Abc_NodeMffsConeSupp( pNode, vCone, vSupp ); + Abc_NodeRef_rec( pNode ); + printf( "Node = %6s : Supp = %3d Cone = %3d (", + Abc_ObjName(pNode), Vec_PtrSize(vSupp), Vec_PtrSize(vCone) ); + Vec_PtrForEachEntry( vCone, pObj, i ) + printf( " %s", Abc_ObjName(pObj) ); + printf( " )\n" ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSupp ); +} + +/**Function************************************************************* + + Synopsis [Collects the internal nodes of the MFFC limited by cut.] + + Description [] + + SideEffects [Increments the trav ID and marks visited nodes.] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffsInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside ) +{ + Abc_Obj_t * pObj; + int i, Count1, Count2; + // increment the fanout counters for the leaves + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->vFanouts.nSize++; + // dereference the node + Count1 = Abc_NodeDeref_rec( pNode ); + // collect the nodes inside the MFFC + Abc_NodeMffsConeSupp( pNode, vInside, NULL ); + // reference it back + Count2 = Abc_NodeRef_rec( pNode ); + assert( Count1 == Count2 ); + // remove the extra counters + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->vFanouts.nSize--; + return Count1; +} + +/**Function************************************************************* + + Synopsis [Collects the internal nodes of the MFFC limited by cut.] + + Description [] + + SideEffects [Increments the trav ID and marks visited nodes.] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeMffsInsideCollect( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vInside; + int Count1, Count2; + // dereference the node + Count1 = Abc_NodeDeref_rec( pNode ); + // collect the nodes inside the MFFC + vInside = Vec_PtrAlloc( 10 ); + Abc_NodeMffsConeSupp( pNode, vInside, NULL ); + // reference it back + Count2 = Abc_NodeRef_rec( pNode ); + assert( Count1 == Count2 ); + return vInside; +} + +/**Function************************************************************* + + Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffcLabel_rec( Abc_Obj_t * pNode, int fTopmost ) +{ + Abc_Obj_t * pFanin; + int i; + // add to the new support nodes + if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) ) + return; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + Abc_NodeSetTravIdCurrent(pNode); + // recur on the children + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NodeMffcLabel_rec( pFanin, 0 ); + // collect the internal node +// printf( "%d ", pNode->Id ); +} + +/**Function************************************************************* + + Synopsis [Collects the internal nodes of the MFFC limited by cut.] + + Description [] + + SideEffects [Increments the trav ID and marks visited nodes.] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcLabel( Abc_Obj_t * pNode ) +{ + int Count1, Count2; + // dereference the node + Count1 = Abc_NodeDeref_rec( pNode ); + // collect the nodes inside the MFFC + Abc_NtkIncrementTravId( pNode->pNtk ); + Abc_NodeMffcLabel_rec( pNode, 1 ); + // reference it back + Count2 = Abc_NodeRef_rec( pNode ); + assert( Count1 == Count2 ); + return Count1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcShow.c b/abc70930/src/base/abc/abcShow.c new file mode 100644 index 00000000..40d1dcad --- /dev/null +++ b/abc70930/src/base/abc/abcShow.c @@ -0,0 +1,318 @@ +/**CFile**************************************************************** + + FileName [abcShow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Visualization procedures using DOT software and GSView.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcShow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifdef WIN32 +#include +#endif + +#include "abc.h" +#include "main.h" +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Abc_ShowFile( char * FileNameDot ); +static void Abc_ShowGetFileName( char * pName, char * pBuffer ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Visualizes BDD of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeShowBdd( Abc_Obj_t * pNode ) +{ + FILE * pFile; + Vec_Ptr_t * vNamesIn; + char FileNameDot[200]; + char * pNameOut; + + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + // create the file name + Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + + // set the node names + vNamesIn = Abc_NodeGetFaninNames( pNode ); + pNameOut = Abc_ObjName(pNode); + Cudd_DumpDot( pNode->pNtk->pManFunc, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); + Abc_NodeFreeNames( vNamesIn ); + Abc_NtkCleanCopy( pNode->pNtk ); + fclose( pFile ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} + +/**Function************************************************************* + + Synopsis [Visualizes a reconvergence driven cut at the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) +{ + FILE * pFile; + char FileNameDot[200]; + Abc_ManCut_t * p; + Vec_Ptr_t * vCutSmall; + Vec_Ptr_t * vCutLarge; + Vec_Ptr_t * vInside; + Vec_Ptr_t * vNodesTfo; + Abc_Obj_t * pTemp; + int i; + + assert( Abc_NtkIsStrash(pNode->pNtk) ); + + // start the cut computation manager + p = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, ABC_INFINITY ); + // get the recovergence driven cut + vCutSmall = Abc_NodeFindCut( p, pNode, 1 ); + // get the containing cut + vCutLarge = Abc_NtkManCutReadCutLarge( p ); + // get the array for the inside nodes + vInside = Abc_NtkManCutReadVisited( p ); + // get the inside nodes of the containing cone + Abc_NodeConeCollect( &pNode, 1, vCutLarge, vInside, 1 ); + + // add the nodes in the TFO + vNodesTfo = Abc_NodeCollectTfoCands( p, pNode, vCutSmall, ABC_INFINITY ); + Vec_PtrForEachEntry( vNodesTfo, pTemp, i ) + Vec_PtrPushUnique( vInside, pTemp ); + + // create the file name + Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + // add the root node to the cone (for visualization) + Vec_PtrPush( vCutSmall, pNode ); + // write the DOT file + Io_WriteDotNtk( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0, 0 ); + // stop the cut computation manager + Abc_NtkManCutStop( p ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} + +/**Function************************************************************* + + Synopsis [Visualizes AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse ) +{ + FILE * pFile; + Abc_Obj_t * pNode; + Vec_Ptr_t * vNodes; + char FileNameDot[200]; + int i; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + if ( Abc_NtkIsStrash(pNtk) && Abc_NtkGetChoiceNum(pNtk) ) + { + printf( "Temporarily visualization of AIGs with choice nodes is disabled.\n" ); + return; + } + // convert to logic SOP + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkToSop( pNtk, 0 ); + // create the file name + Abc_ShowGetFileName( pNtk->pName, FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + + // collect all nodes in the network + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pNode, i ) + Vec_PtrPush( vNodes, pNode ); + // write the DOT file + if ( fSeq ) + Io_WriteDotSeq( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); + else + Io_WriteDotNtk( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); + Vec_PtrFree( vNodes ); + + // visualize the file + Abc_ShowFile( FileNameDot ); +} + + +/**Function************************************************************* + + Synopsis [Shows the given DOT file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ShowFile( char * FileNameDot ) +{ + FILE * pFile; + char * FileGeneric; + char FileNamePs[200]; + char CommandDot[1000]; + char * pDotName; + char * pDotNameWin = "dot.exe"; + char * pDotNameUnix = "dot"; + char * pGsNameWin = "gsview32.exe"; + char * pGsNameUnix = "gv"; + int RetValue; + + // get DOT names from the resource file + if ( Abc_FrameReadFlag("dotwin") ) + pDotNameWin = Abc_FrameReadFlag("dotwin"); + if ( Abc_FrameReadFlag("dotunix") ) + pDotNameUnix = Abc_FrameReadFlag("dotunix"); + +#ifdef WIN32 + pDotName = pDotNameWin; +#else + pDotName = pDotNameUnix; +#endif + + // check if the input DOT file is okay + if ( (pFile = fopen( FileNameDot, "r" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + + // create the PostScript file name + FileGeneric = Extra_FileNameGeneric( FileNameDot ); + sprintf( FileNamePs, "%s.ps", FileGeneric ); + free( FileGeneric ); + + // generate the PostScript file using DOT + sprintf( CommandDot, "%s -Tps -o %s %s", pDotName, FileNamePs, FileNameDot ); + RetValue = system( CommandDot ); + if ( RetValue == -1 ) + { + fprintf( stdout, "Command \"%s\" did not succeed.\n", CommandDot ); + return; + } + // check that the input PostScript file is okay + if ( (pFile = fopen( FileNamePs, "r" )) == NULL ) + { + fprintf( stdout, "Cannot open intermediate file \"%s\".\n", FileNamePs ); + return; + } + fclose( pFile ); + + + // get GSVIEW names from the resource file + if ( Abc_FrameReadFlag("gsviewwin") ) + pGsNameWin = Abc_FrameReadFlag("gsviewwin"); + if ( Abc_FrameReadFlag("gsviewunix") ) + pGsNameUnix = Abc_FrameReadFlag("gsviewunix"); + + // spawn the viewer +#ifdef WIN32 + _unlink( FileNameDot ); + if ( _spawnl( _P_NOWAIT, pGsNameWin, pGsNameWin, FileNamePs, NULL ) == -1 ) + if ( _spawnl( _P_NOWAIT, "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", + "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", FileNamePs, NULL ) == -1 ) + { + fprintf( stdout, "Cannot find \"%s\".\n", pGsNameWin ); + return; + } +#else + { + char CommandPs[1000]; + unlink( FileNameDot ); + sprintf( CommandPs, "%s %s &", pGsNameUnix, FileNamePs ); + if ( system( CommandPs ) == -1 ) + { + fprintf( stdout, "Cannot execute \"%s\".\n", CommandPs ); + return; + } + } +#endif +} + +/**Function************************************************************* + + Synopsis [Derives the DOT file name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ShowGetFileName( char * pName, char * pBuffer ) +{ + char * pCur; + // creat the file name + sprintf( pBuffer, "%s.dot", pName ); + // get rid of not-alpha-numeric characters + for ( pCur = pBuffer; *pCur; pCur++ ) + if ( !((*pCur >= '0' && *pCur <= '9') || (*pCur >= 'a' && *pCur <= 'z') || + (*pCur >= 'A' && *pCur <= 'Z') || (*pCur == '.')) ) + *pCur = '_'; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcSop.c b/abc70930/src/base/abc/abcSop.c new file mode 100644 index 00000000..106901ab --- /dev/null +++ b/abc70930/src/base/abc/abcSop.c @@ -0,0 +1,1075 @@ +/**CFile**************************************************************** + + FileName [abcSop.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Implementation of a simple SOP representation of nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcSop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +/* + The SOPs in this package are represented using char * strings. + For example, the SOP of the node: + + .names c d0 d1 MUX + 01- 1 + 1-1 1 + + is the string: "01- 1\n1-1 1\n" where '\n' is a single char. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Registers the cube string with the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName ) +{ + char * pRegName; + if ( pName == NULL ) return NULL; + pRegName = Extra_MmFlexEntryFetch( pMan, strlen(pName) + 1 ); + strcpy( pRegName, pName ); + return pRegName; +} + +/**Function************************************************************* + + Synopsis [Creates the constant 1 cover with the given number of variables and cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars ) +{ + char * pSopCover, * pCube; + int i, Length; + + Length = nCubes * (nVars + 3); + pSopCover = Extra_MmFlexEntryFetch( pMan, Length + 1 ); + memset( pSopCover, '-', Length ); + pSopCover[Length] = 0; + + for ( i = 0; i < nCubes; i++ ) + { + pCube = pSopCover + i * (nVars + 3); + pCube[nVars + 0] = ' '; + pCube[nVars + 1] = '1'; + pCube[nVars + 2] = '\n'; + } + return pSopCover; +} + +/**Function************************************************************* + + Synopsis [Creates the constant 1 cover with 0 variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateConst1( Extra_MmFlex_t * pMan ) +{ + return Abc_SopRegister( pMan, " 1\n" ); +} + +/**Function************************************************************* + + Synopsis [Creates the constant 1 cover with 0 variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateConst0( Extra_MmFlex_t * pMan ) +{ + return Abc_SopRegister( pMan, " 0\n" ); +} + +/**Function************************************************************* + + Synopsis [Creates the AND2 cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 ) +{ + char Buffer[6]; + Buffer[0] = '1' - fCompl0; + Buffer[1] = '1' - fCompl1; + Buffer[2] = ' '; + Buffer[3] = '1'; + Buffer[4] = '\n'; + Buffer[5] = 0; + return Abc_SopRegister( pMan, Buffer ); +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input AND cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '1' - (pfCompl? pfCompl[i] : 0); + pSop[nVars + 1] = '1'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input NAND cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateNand( Extra_MmFlex_t * pMan, int nVars ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '1'; + pSop[nVars + 1] = '0'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input OR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateOr( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '0' + (pfCompl? pfCompl[i] : 0); + pSop[nVars + 1] = '0'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input OR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateOrMultiCube( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) +{ + char * pSop, * pCube; + int i; + pSop = Abc_SopStart( pMan, nVars, nVars ); + i = 0; + Abc_SopForEachCube( pSop, nVars, pCube ) + { + pCube[i] = '1' - (pfCompl? pfCompl[i] : 0); + i++; + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input NOR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateNor( Extra_MmFlex_t * pMan, int nVars ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '0'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input XOR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars ) +{ + assert( nVars == 2 ); + return Abc_SopRegister(pMan, "01 1\n10 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input XOR cover (special case).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateXorSpecial( Extra_MmFlex_t * pMan, int nVars ) +{ + char * pSop; + pSop = Abc_SopCreateAnd( pMan, nVars, NULL ); + pSop[nVars+1] = 'x'; + assert( pSop[nVars+2] == '\n' ); + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input XNOR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateNxor( Extra_MmFlex_t * pMan, int nVars ) +{ + assert( nVars == 2 ); + return Abc_SopRegister(pMan, "11 1\n00 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the MUX cover.] + + Description [The first input of MUX is the control. The second input + is DATA1. The third input is DATA0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateMux( Extra_MmFlex_t * pMan ) +{ + return Abc_SopRegister(pMan, "11- 1\n0-1 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the inv cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateInv( Extra_MmFlex_t * pMan ) +{ + return Abc_SopRegister(pMan, "0 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the buf cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateBuf( Extra_MmFlex_t * pMan ) +{ + return Abc_SopRegister(pMan, "1 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the arbitrary cover from the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateFromTruth( Extra_MmFlex_t * pMan, int nVars, unsigned * pTruth ) +{ + char * pSop, * pCube; + int nMints, Counter, i, k; + // count the number of true minterms + Counter = 0; + nMints = (1 << nVars); + for ( i = 0; i < nMints; i++ ) + Counter += ((pTruth[i>>5] & (1 << (i&31))) > 0); + // SOP is not well-defined if the truth table is constant 0 + assert( Counter > 0 ); + if ( Counter == 0 ) + return NULL; + // start the cover + pSop = Abc_SopStart( pMan, Counter, nVars ); + // create true minterms + Counter = 0; + for ( i = 0; i < nMints; i++ ) + if ( (pTruth[i>>5] & (1 << (i&31))) > 0 ) + { + pCube = pSop + Counter * (nVars + 3); + for ( k = 0; k < nVars; k++ ) + pCube[k] = '0' + ((i & (1 << k)) > 0); + Counter++; + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the cover from the ISOP computed from TT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateFromIsop( Extra_MmFlex_t * pMan, int nVars, Vec_Int_t * vCover ) +{ + char * pSop, * pCube; + int i, k, Entry, Literal; + assert( Vec_IntSize(vCover) > 0 ); + if ( Vec_IntSize(vCover) == 0 ) + return NULL; + // start the cover + pSop = Abc_SopStart( pMan, Vec_IntSize(vCover), nVars ); + // create cubes + Vec_IntForEachEntry( vCover, Entry, i ) + { + pCube = pSop + i * (nVars + 3); + for ( k = 0; k < nVars; k++ ) + { + Literal = 3 & (Entry >> (k << 1)); + if ( Literal == 1 ) + pCube[k] = '0'; + else if ( Literal == 2 ) + pCube[k] = '1'; + else if ( Literal != 0 ) + assert( 0 ); + } + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Reads the number of cubes in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetCubeNum( char * pSop ) +{ + char * pCur; + int nCubes = 0; + if ( pSop == NULL ) + return 0; + for ( pCur = pSop; *pCur; pCur++ ) + nCubes += (*pCur == '\n'); + return nCubes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of SOP literals in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetLitNum( char * pSop ) +{ + char * pCur; + int nLits = 0; + if ( pSop == NULL ) + return 0; + for ( pCur = pSop; *pCur; pCur++ ) + { + nLits -= (*pCur == '\n'); + nLits += (*pCur == '0' || *pCur == '1'); + } + return nLits; +} + +/**Function************************************************************* + + Synopsis [Reads the number of variables in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetVarNum( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur != '\n'; pCur++ ); + return pCur - pSop - 2; +} + +/**Function************************************************************* + + Synopsis [Reads the phase of the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetPhase( char * pSop ) +{ + int nVars = Abc_SopGetVarNum( pSop ); + if ( pSop[nVars+1] == '0' || pSop[nVars+1] == 'n' ) + return 0; + if ( pSop[nVars+1] == '1' || pSop[nVars+1] == 'x' ) + return 1; + assert( 0 ); + return -1; +} + +/**Function************************************************************* + + Synopsis [Returns the i-th literal of the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetIthCareLit( char * pSop, int i ) +{ + char * pCube; + int nVars; + nVars = Abc_SopGetVarNum( pSop ); + Abc_SopForEachCube( pSop, nVars, pCube ) + if ( pCube[i] != '-' ) + return pCube[i] - '0'; + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SopComplement( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur; pCur++ ) + if ( *pCur == '\n' ) + { + if ( *(pCur - 1) == '0' ) + *(pCur - 1) = '1'; + else if ( *(pCur - 1) == '1' ) + *(pCur - 1) = '0'; + else if ( *(pCur - 1) == 'x' ) + *(pCur - 1) = 'n'; + else if ( *(pCur - 1) == 'n' ) + *(pCur - 1) = 'x'; + else + assert( 0 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsComplement( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur; pCur++ ) + if ( *pCur == '\n' ) + return (int)(*(pCur - 1) == '0' || *(pCur - 1) == 'n'); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsConst0( char * pSop ) +{ + return pSop[0] == ' ' && pSop[1] == '0'; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsConst1( char * pSop ) +{ + return pSop[0] == ' ' && pSop[1] == '1'; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsBuf( char * pSop ) +{ + if ( pSop[4] != 0 ) + return 0; + if ( (pSop[0] == '1' && pSop[2] == '1') || (pSop[0] == '0' && pSop[2] == '0') ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsInv( char * pSop ) +{ + if ( pSop[4] != 0 ) + return 0; + if ( (pSop[0] == '0' && pSop[2] == '1') || (pSop[0] == '1' && pSop[2] == '0') ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is AND with possibly complemented inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsAndType( char * pSop ) +{ + char * pCur; + if ( Abc_SopGetCubeNum(pSop) != 1 ) + return 0; + for ( pCur = pSop; *pCur != ' '; pCur++ ) + if ( *pCur == '-' ) + return 0; + if ( pCur[1] != '1' ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is OR with possibly complemented inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopIsOrType( char * pSop ) +{ + char * pCube, * pCur; + int nVars, nLits; + nVars = Abc_SopGetVarNum( pSop ); + if ( nVars != Abc_SopGetCubeNum(pSop) ) + return 0; + Abc_SopForEachCube( pSop, nVars, pCube ) + { + // count the number of literals in the cube + nLits = 0; + for ( pCur = pCube; *pCur != ' '; pCur++ ) + nLits += ( *pCur != '-' ); + if ( nLits != 1 ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopIsExorType( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur; pCur++ ) + if ( *pCur == '\n' ) + return (int)(*(pCur - 1) == 'x' || *(pCur - 1) == 'n'); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_SopCheck( char * pSop, int nFanins ) +{ + char * pCubes, * pCubesOld; + int fFound0 = 0, fFound1 = 0; + + // check the logic function of the node + for ( pCubes = pSop; *pCubes; pCubes++ ) + { + // get the end of the next cube + for ( pCubesOld = pCubes; *pCubes != ' '; pCubes++ ); + // compare the distance + if ( pCubes - pCubesOld != nFanins ) + { + fprintf( stdout, "Abc_SopCheck: SOP has a mismatch between its cover size (%d) and its fanin number (%d).\n", + pCubes - pCubesOld, nFanins ); + return 0; + } + // check the output values for this cube + pCubes++; + if ( *pCubes == '0' ) + fFound0 = 1; + else if ( *pCubes == '1' ) + fFound1 = 1; + else if ( *pCubes != 'x' && *pCubes != 'n' ) + { + fprintf( stdout, "Abc_SopCheck: SOP has a strange character (%c) in the output part of its cube.\n", *pCubes ); + return 0; + } + // check the last symbol (new line) + pCubes++; + if ( *pCubes != '\n' ) + { + fprintf( stdout, "Abc_SopCheck: SOP has a cube without new line in the end.\n" ); + return 0; + } + } + if ( fFound0 && fFound1 ) + { + fprintf( stdout, "Abc_SopCheck: SOP has cubes in both phases.\n" ); + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Derives SOP from the truth table representation.] + + Description [Truth table is expected to be in the hexadecimal notation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopFromTruthBin( char * pTruth ) +{ + char * pSopCover, * pCube; + int nTruthSize, nVars, Digit, Length, Mint, i, b; + Vec_Int_t * vMints; + + // get the number of variables + nTruthSize = strlen(pTruth); + nVars = Extra_Base2Log( nTruthSize ); + if ( nTruthSize != (1 << (nVars)) ) + { + printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars ); + return NULL; + } + + // collect the on-set minterms + vMints = Vec_IntAlloc( 100 ); + for ( i = 0; i < nTruthSize; i++ ) + { + if ( pTruth[i] >= '0' && pTruth[i] <= '1' ) + Digit = pTruth[i] - '0'; + else + { + printf( "String %s does not look like a binary representation of the truth table.\n", pTruth ); + return NULL; + } + if ( Digit == 1 ) + Vec_IntPush( vMints, nTruthSize - 1 - i ); + } + if ( Vec_IntSize( vMints ) == 0 || Vec_IntSize( vMints ) == nTruthSize ) + { + Vec_IntFree( vMints ); + printf( "Cannot create constant function.\n" ); + return NULL; + } + + // create the SOP representation of the minterms + Length = Vec_IntSize(vMints) * (nVars + 3); + pSopCover = ALLOC( char, Length + 1 ); + pSopCover[Length] = 0; + Vec_IntForEachEntry( vMints, Mint, i ) + { + pCube = pSopCover + i * (nVars + 3); + for ( b = 0; b < nVars; b++ ) + if ( Mint & (1 << (nVars-1-b)) ) +// if ( Mint & (1 << b) ) + pCube[b] = '1'; + else + pCube[b] = '0'; + pCube[nVars + 0] = ' '; + pCube[nVars + 1] = '1'; + pCube[nVars + 2] = '\n'; + } + Vec_IntFree( vMints ); + return pSopCover; +} + +/**Function************************************************************* + + Synopsis [Derives SOP from the truth table representation.] + + Description [Truth table is expected to be in the hexadecimal notation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopFromTruthHex( char * pTruth ) +{ + char * pSopCover, * pCube; + int nTruthSize, nVars, Digit, Length, Mint, i, b; + Vec_Int_t * vMints; + + // get the number of variables + nTruthSize = strlen(pTruth); + nVars = Extra_Base2Log( nTruthSize ) + 2; + if ( nTruthSize != (1 << (nVars-2)) ) + { + printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars ); + return NULL; + } + + // collect the on-set minterms + vMints = Vec_IntAlloc( 100 ); + for ( i = 0; i < nTruthSize; i++ ) + { + if ( pTruth[i] >= '0' && pTruth[i] <= '9' ) + Digit = pTruth[i] - '0'; + else if ( pTruth[i] >= 'a' && pTruth[i] <= 'f' ) + Digit = 10 + pTruth[i] - 'a'; + else if ( pTruth[i] >= 'A' && pTruth[i] <= 'F' ) + Digit = 10 + pTruth[i] - 'A'; + else + { + printf( "String %s does not look like a hexadecimal representation of the truth table.\n", pTruth ); + return NULL; + } + for ( b = 0; b < 4; b++ ) + if ( Digit & (1 << b) ) + Vec_IntPush( vMints, 4*(nTruthSize-1-i)+b ); + } + + // create the SOP representation of the minterms + Length = Vec_IntSize(vMints) * (nVars + 3); + pSopCover = ALLOC( char, Length + 1 ); + pSopCover[Length] = 0; + Vec_IntForEachEntry( vMints, Mint, i ) + { + pCube = pSopCover + i * (nVars + 3); + for ( b = 0; b < nVars; b++ ) +// if ( Mint & (1 << (nVars-1-b)) ) + if ( Mint & (1 << b) ) + pCube[b] = '1'; + else + pCube[b] = '0'; + pCube[nVars + 0] = ' '; + pCube[nVars + 1] = '1'; + pCube[nVars + 2] = '\n'; + } + Vec_IntFree( vMints ); + return pSopCover; +} + +/**Function************************************************************* + + Synopsis [Creates one encoder node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues ) +{ + char Buffer[32]; + assert( iValue < nValues ); + sprintf( Buffer, "d0\n%d 1\n", iValue ); + return Abc_SopRegister( pMan, Buffer ); +} + +/**Function************************************************************* + + Synopsis [Creates one encoder node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues ) +{ + char * pResult; + Vec_Str_t * vSop; + int v, Counter, fFirst = 1, nBits = Extra_Base2Log(nValues); + assert( iBit < nBits ); + // count the number of literals + Counter = 0; + for ( v = 0; v < nValues; v++ ) + Counter += ( (v & (1 << iBit)) > 0 ); + // create the cover + vSop = Vec_StrAlloc( 100 ); + Vec_StrPrintStr( vSop, "d0\n" ); + if ( Counter > 1 ) + Vec_StrPrintStr( vSop, "(" ); + for ( v = 0; v < nValues; v++ ) + if ( v & (1 << iBit) ) + { + if ( fFirst ) + fFirst = 0; + else + Vec_StrPush( vSop, ',' ); + Vec_StrPrintNum( vSop, v ); + } + if ( Counter > 1 ) + Vec_StrPrintStr( vSop, ")" ); + Vec_StrPrintStr( vSop, " 1\n" ); + Vec_StrPush( vSop, 0 ); + pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); + Vec_StrFree( vSop ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Creates the decoder node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues ) +{ + char * pResult; + Vec_Str_t * vSop; + int i, k; + assert( nValues > 1 ); + vSop = Vec_StrAlloc( 100 ); + for ( i = 0; i < nValues; i++ ) + { + for ( k = 0; k < nValues; k++ ) + { + if ( k == i ) + Vec_StrPrintStr( vSop, "1 " ); + else + Vec_StrPrintStr( vSop, "- " ); + } + Vec_StrPrintNum( vSop, i ); + Vec_StrPush( vSop, '\n' ); + } + Vec_StrPush( vSop, 0 ); + pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); + Vec_StrFree( vSop ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Creates the decover node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues ) +{ + char * pResult; + Vec_Str_t * vSop; + int i, b, nBits = Extra_Base2Log(nValues); + assert( nValues > 1 && nValues <= (1< 0) ); + Vec_StrPush( vSop, ' ' ); + } + Vec_StrPrintNum( vSop, i ); + Vec_StrPush( vSop, '\n' ); + } + Vec_StrPush( vSop, 0 ); + pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); + Vec_StrFree( vSop ); + return pResult; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abcUtil.c b/abc70930/src/base/abc/abcUtil.c new file mode 100644 index 00000000..b4a97223 --- /dev/null +++ b/abc70930/src/base/abc/abcUtil.c @@ -0,0 +1,1764 @@ +/**CFile**************************************************************** + + FileName [abcUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mio.h" +#include "dec.h" +//#include "seq.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Frees one attribute manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ) +{ + void * pUserMan; + Vec_Att_t * pAttrMan; + pAttrMan = Vec_PtrEntry( pNtk->vAttrs, Attr ); + Vec_PtrWriteEntry( pNtk->vAttrs, Attr, NULL ); + pUserMan = Vec_AttFree( pAttrMan, fFreeMan ); + return pUserMan; +} + +/**Function************************************************************* + + Synopsis [Increments the current traversal ID of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + if ( pNtk->nTravIds >= (1<<30)-1 ) + { + pNtk->nTravIds = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->TravId = 0; + } + pNtk->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Order CI/COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pTerm; + int i, k; + Vec_PtrClear( pNtk->vCis ); + Vec_PtrClear( pNtk->vCos ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Vec_PtrPush( pNtk->vCis, pObj ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Vec_PtrPush( pNtk->vCos, pObj ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Vec_PtrPush( pNtk->vCos, pObj ); + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + Abc_ObjForEachFanin( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCos, pTerm ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCis, pTerm ); + } + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( !Abc_ObjIsLatch(pObj) ) + continue; + Abc_ObjForEachFanin( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCos, pTerm ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCis, pTerm ); + } +} + +/**Function************************************************************* + + Synopsis [Reads the number of cubes of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nCubes = 0; + assert( Abc_NtkHasSop(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + assert( pNode->pData ); + nCubes += Abc_SopGetCubeNum( pNode->pData ); + } + return nCubes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of cubes of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nCubes, nCubePairs = 0; + assert( Abc_NtkHasSop(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + assert( pNode->pData ); + nCubes = Abc_SopGetCubeNum( pNode->pData ); + nCubePairs += nCubes * (nCubes - 1) / 2; + } + return nCubePairs; +} + +/**Function************************************************************* + + Synopsis [Reads the number of literals in the SOPs of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nLits = 0; + assert( Abc_NtkHasSop(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + nLits += Abc_SopGetLitNum( pNode->pData ); + } + return nLits; +} + +/**Function************************************************************* + + Synopsis [Counts the number of literals in the factored forms.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk ) +{ + Dec_Graph_t * pFactor; + Abc_Obj_t * pNode; + int nNodes, i; + assert( Abc_NtkHasSop(pNtk) ); + nNodes = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + pFactor = Dec_Factor( pNode->pData ); + nNodes += 1 + Dec_GraphNodeNum(pFactor); + Dec_GraphFree( pFactor ); + } + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nNodes = 0; + assert( Abc_NtkIsBddLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + if ( Abc_ObjFaninNum(pNode) < 2 ) + continue; + nNodes += pNode->pData? -1 + Cudd_DagSize( pNode->pData ) : 0; + } + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nNodes = 0; + assert( Abc_NtkIsAigLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + if ( Abc_ObjFaninNum(pNode) < 2 ) + continue; +//printf( "%d ", Hop_DagSize( pNode->pData ) ); + nNodes += pNode->pData? Hop_DagSize( pNode->pData ) : 0; + } + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + DdNode * bCover, * zCover, * bFunc; + DdManager * dd = pNtk->pManFunc; + int i, nClauses = 0; + assert( Abc_NtkIsBddLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + bFunc = pNode->pData; + + bCover = Cudd_zddIsop( dd, bFunc, bFunc, &zCover ); + Cudd_Ref( bCover ); + Cudd_Ref( zCover ); + nClauses += Abc_CountZddCubes( dd, zCover ); + Cudd_RecursiveDeref( dd, bCover ); + Cudd_RecursiveDerefZdd( dd, zCover ); + + bCover = Cudd_zddIsop( dd, Cudd_Not(bFunc), Cudd_Not(bFunc), &zCover ); + Cudd_Ref( bCover ); + Cudd_Ref( zCover ); + nClauses += Abc_CountZddCubes( dd, zCover ); + Cudd_RecursiveDeref( dd, bCover ); + Cudd_RecursiveDerefZdd( dd, zCover ); + } + return nClauses; +} + +/**Function************************************************************* + + Synopsis [Computes the area of the mapped circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + double TotalArea; + int i; + assert( Abc_NtkHasMapping(pNtk) ); + TotalArea = 0.0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { +// assert( pNode->pData ); + if ( pNode->pData == NULL ) + { + printf( "Node without mapping is encountered.\n" ); + continue; + } + TotalArea += Mio_GateReadArea( pNode->pData ); + } + return TotalArea; +} + +/**Function************************************************************* + + Synopsis [Counts the number of exors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += pNode->fExor; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of exors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeIsMuxType(pNode); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if it is an AIG with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter; + if ( !Abc_NtkIsStrash(pNtk) ) + return 0; + Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_AigNodeIsChoice( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Reads the maximum number of fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nFaninsMax = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( nFaninsMax < Abc_ObjFaninNum(pNode) ) + nFaninsMax = Abc_ObjFaninNum(pNode); + } + return nFaninsMax; +} + +/**Function************************************************************* + + Synopsis [Reads the total number of all fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nFanins = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + nFanins += Abc_ObjFaninNum(pNode); + return nFanins; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pCopy = NULL; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanData( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanEquiv( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pEquiv = NULL; +} + +/**Function************************************************************* + + Synopsis [Counts the number of nodes having non-trivial copies.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountCopy( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i, Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Abc_ObjIsNode(pObj) ) + Counter += (pObj->pCopy != NULL); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Saves copy field of the objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vCopies; + Abc_Obj_t * pObj; + int i; + vCopies = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachObj( pNtk, pObj, i ) + Vec_PtrWriteEntry( vCopies, i, pObj->pCopy ); + return vCopies; +} + +/**Function************************************************************* + + Synopsis [Loads copy field of the objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pCopy = Vec_PtrEntry( vCopies, i ); +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanNext( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pNext = NULL; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the internal node has CO fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i; + Abc_ObjForEachFanout( pNode, pFanout, i ) + if ( Abc_ObjIsCo(pFanout) ) + return pFanout; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Checks if the internal node has CO fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i; + Abc_ObjForEachFanout( pNode, pFanout, i ) + if ( !Abc_ObjIsCo(pFanout) ) + return pFanout; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Checks if the internal node has CO drivers with the same name.] + + Description [Checks if the internal node can borrow its name from CO fanouts. + This is possible if all COs with non-complemented fanin edge pointing to this + node have the same name.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout, * pFanoutCo; + int i; + pFanoutCo = NULL; + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + if ( !Abc_ObjIsCo(pFanout) ) + continue; + if ( Abc_ObjFaninC0(pFanout) ) + continue; + if ( pFanoutCo == NULL ) + { + assert( Abc_ObjFaninNum(pFanout) == 1 ); + assert( Abc_ObjFanin0(pFanout) == pNode ); + pFanoutCo = pFanout; + continue; + } + if ( strcmp( Abc_ObjName(pFanoutCo), Abc_ObjName(pFanout) ) ) // they have diff names + return NULL; + } + return pFanoutCo; +} + +/**Function************************************************************* + + Synopsis [Fixes the CO driver problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFixCoDriverProblem( Abc_Obj_t * pDriver, Abc_Obj_t * pNodeCo, int fDuplicate ) +{ + Abc_Ntk_t * pNtk = pDriver->pNtk; + Abc_Obj_t * pDriverNew, * pFanin; + int k; + if ( fDuplicate && !Abc_ObjIsCi(pDriver) ) + { + pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); + Abc_ObjForEachFanin( pDriver, pFanin, k ) + Abc_ObjAddFanin( pDriverNew, pFanin ); + if ( Abc_ObjFaninC0(pNodeCo) ) + { + // change polarity of the duplicated driver + Abc_NodeComplement( pDriverNew ); + Abc_ObjXorFaninC( pNodeCo, 0 ); + } + } + else + { + // add inverters and buffers when necessary + if ( Abc_ObjFaninC0(pNodeCo) ) + { + pDriverNew = Abc_NtkCreateNodeInv( pNtk, pDriver ); + Abc_ObjXorFaninC( pNodeCo, 0 ); + } + else + pDriverNew = Abc_NtkCreateNodeBuf( pNtk, pDriver ); + } + // update the fanin of the PO node + Abc_ObjPatchFanin( pNodeCo, pDriver, pDriverNew ); + assert( Abc_ObjFanoutNum(pDriverNew) == 1 ); + // remove the old driver if it dangles + // (this happens when the duplicated driver had only one complemented fanout) + if ( Abc_ObjFanoutNum(pDriver) == 0 ) + Abc_NtkDeleteObj( pDriver ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if COs of a logic network are simple.] + + Description [The COs of a logic network are simple under three conditions: + (1) The edge from CO to its driver is not complemented. + (2) If CI is a driver of a CO, they have the same name.] + (3) If two COs share the same driver, they have the same name.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pDriver; + int i; + assert( Abc_NtkIsLogic(pNtk) ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // if the driver is complemented, this is an error + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjFaninC0(pNode) ) + return 0; + // if the driver is a CI and has different name, this is an error + if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) + return 0; + // if the driver is visited for the first time, remember the CO name + if ( !Abc_NodeIsTravIdCurrent(pDriver) ) + { + pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); + Abc_NodeSetTravIdCurrent(pDriver); + continue; + } + // the driver has second CO - if they have different name, this is an error + if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Transforms the network to have simple COs.] + + Description [The COs of a logic network are simple under three conditions: + (1) The edge from CO to its driver is not complemented. + (2) If CI is a driver of a CO, they have the same name.] + (3) If two COs share the same driver, they have the same name. + In some cases, such as FPGA mapping, we prevent the increase in delay + by duplicating the driver nodes, rather than adding invs/bufs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDuplicate ) +{ + Abc_Obj_t * pNode, * pDriver; + int i, nDupGates = 0; + assert( Abc_NtkIsLogic(pNtk) ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // if the driver is complemented, this is an error + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjFaninC0(pNode) ) + { + Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); + nDupGates++; + continue; + } + // if the driver is a CI and has different name, this is an error + if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) + { + Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); + nDupGates++; + continue; + } + // if the driver is visited for the first time, remember the CO name + if ( !Abc_NodeIsTravIdCurrent(pDriver) ) + { + pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); + Abc_NodeSetTravIdCurrent(pDriver); + continue; + } + // the driver has second CO - if they have different name, this is an error + if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names + { + Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); + nDupGates++; + continue; + } + } + assert( Abc_NtkLogicHasSimpleCos(pNtk) ); + return nDupGates; +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode1, * pNode2; + int i; + if ( Vec_PtrPushUnique(p, pNode) ) + return; + // find the p of the node + for ( i = p->nSize-1; i > 0; i-- ) + { + pNode1 = p->pArray[i ]; + pNode2 = p->pArray[i-1]; + if ( Abc_ObjRegular(pNode1)->Level <= Abc_ObjRegular(pNode2)->Level ) + break; + p->pArray[i ] = pNode2; + p->pArray[i-1] = pNode1; + } +} + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsExorType( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Abc_ObjIsComplement(pNode) ); + // if the node is not AND, this is not EXOR + if ( !Abc_AigNodeIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not EXOR + if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + // if the children are not ANDs, this is not EXOR + if ( Abc_ObjFaninNum(pNode0) != 2 || Abc_ObjFaninNum(pNode1) != 2 ) + return 0; + // otherwise, the node is EXOR iff its grand-children are the same + return (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) || Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1)) && + (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) || Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1)); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsMuxType( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Abc_ObjIsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Abc_AigNodeIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( Abc_ObjFaninNum(pNode0) != 2 || Abc_ObjFaninNum(pNode1) != 2 ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren + return (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1))) || + (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1))) || + (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1))) || + (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1))); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the control type of the MUX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsMuxControlType( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Abc_ObjIsComplement(pNode) ); + // skip the node that do not have two fanouts + if ( Abc_ObjFanoutNum(pNode) != 2 ) + return 0; + // get the fanouts + pNode0 = Abc_ObjFanout( pNode, 0 ); + pNode1 = Abc_ObjFanout( pNode, 1 ); + // if they have more than one fanout, we are not interested + if ( Abc_ObjFanoutNum(pNode0) != 1 || Abc_ObjFanoutNum(pNode1) != 1 ) + return 0; + // if the fanouts have the same fanout, this is MUX or EXOR (or a redundant gate (CA)(CB)) + return Abc_ObjFanout0(pNode0) == Abc_ObjFanout0(pNode1); +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ) +{ + Abc_Obj_t * pNode0, * pNode1; + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_NodeIsMuxType(pNode) ); + // get children + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + // find the control variable +// if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) + if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Abc_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + return Abc_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + return Abc_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) + else if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Abc_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + return Abc_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + return Abc_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) + else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Abc_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + return Abc_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + return Abc_ObjChild1(pNode0);//pNode1->p2; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) + else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Abc_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + return Abc_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + return Abc_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + +/**Function************************************************************* + + Synopsis [Prepares two network for a two-argument command similar to "verify".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, + Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2 ) +{ + int fCheck = 1; + FILE * pFile; + Abc_Ntk_t * pNtk1, * pNtk2; + int util_optind = 0; + + *pfDelete1 = 0; + *pfDelete2 = 0; + if ( argc == util_optind ) + { // use the spec + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty current network.\n" ); + return 0; + } + if ( pNtk->pSpec == NULL ) + { + fprintf( pErr, "The external spec is not given.\n" ); + return 0; + } + pFile = fopen( pNtk->pSpec, "r" ); + if ( pFile == NULL ) + { + fprintf( pErr, "Cannot open the external spec file \"%s\".\n", pNtk->pSpec ); + return 0; + } + else + fclose( pFile ); + pNtk1 = pNtk; + pNtk2 = Io_Read( pNtk->pSpec, Io_ReadFileType(pNtk->pSpec), fCheck ); + if ( pNtk2 == NULL ) + return 0; + *pfDelete2 = 1; + } + else if ( argc == util_optind + 1 ) + { + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty current network.\n" ); + return 0; + } + pNtk1 = pNtk; + pNtk2 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck ); + if ( pNtk2 == NULL ) + return 0; + *pfDelete2 = 1; + } + else if ( argc == util_optind + 2 ) + { + pNtk1 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck ); + if ( pNtk1 == NULL ) + return 0; + pNtk2 = Io_Read( argv[util_optind+1], Io_ReadFileType(argv[util_optind+1]), fCheck ); + if ( pNtk2 == NULL ) + { + Abc_NtkDelete( pNtk1 ); + return 0; + } + *pfDelete1 = 1; + *pfDelete2 = 1; + } + else + { + fprintf( pErr, "Wrong number of arguments.\n" ); + return 0; + } + *ppNtk1 = pNtk1; + *ppNtk2 = pNtk2; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if it is an AIG with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + Vec_PtrClear(vNodes); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Vec_PtrPush( vNodes, pFanin ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if it is an AIG with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + Vec_PtrClear(vNodes); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Vec_PtrPush( vNodes, pFanout ); +} + +/**Function************************************************************* + + Synopsis [Collects all latches in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vLatches; + Abc_Obj_t * pObj; + int i; + vLatches = Vec_PtrAlloc( 10 ); + Abc_NtkForEachObj( pNtk, pObj, i ) + Vec_PtrPush( vLatches, pObj ); + return vLatches; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in increasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level; + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level; + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Creates the array of fanout counters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vFanNums; + Abc_Obj_t * pObj; + int i; + vFanNums = Vec_IntAlloc( 0 ); + Vec_IntFill( vFanNums, Abc_NtkObjNumMax(pNtk), -1 ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) ) + Vec_IntWriteEntry( vFanNums, i, Abc_ObjFanoutNum(pObj) ); + return vFanNums; +} + +/**Function************************************************************* + + Synopsis [Collects all objects into one array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pNode, i ) + Vec_PtrPush( vNodes, pNode ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the array of CI IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vCiIds; + Abc_Obj_t * pObj; + int i; + vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Vec_IntPush( vCiIds, pObj->Id ); + return vCiIds; +} + +/**Function************************************************************* + + Synopsis [Puts the nodes into the DFS order and reassign their IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkReassignIds( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Vec_Ptr_t * vObjsNew; + Abc_Obj_t * pNode, * pTemp, * pConst1; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); +//printf( "Total = %d. Current = %d.\n", Abc_NtkObjNumMax(pNtk), Abc_NtkObjNum(pNtk) ); + // start the array of objects with new IDs + vObjsNew = Vec_PtrAlloc( pNtk->nObjs ); + // put constant node first + pConst1 = Abc_AigConst1(pNtk); + assert( pConst1->Id == 0 ); + Vec_PtrPush( vObjsNew, pConst1 ); + // put PI nodes next + Abc_NtkForEachPi( pNtk, pNode, i ) + { + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + } + // put PO nodes next + Abc_NtkForEachPo( pNtk, pNode, i ) + { + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + } + // put assert nodes next + Abc_NtkForEachAssert( pNtk, pNode, i ) + { + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + } + // put latches and their inputs/outputs next + Abc_NtkForEachBox( pNtk, pNode, i ) + { + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + Abc_ObjForEachFanin( pNode, pTemp, k ) + { + pTemp->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pTemp ); + } + Abc_ObjForEachFanout( pNode, pTemp, k ) + { + pTemp->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pTemp ); + } + } + // finally, internal nodes in the DFS order + vNodes = Abc_AigDfs( pNtk, 1, 0 ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( pNode == pConst1 ) + continue; + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + } + Vec_PtrFree( vNodes ); + assert( Vec_PtrSize(vObjsNew) == pNtk->nObjs ); + + // update the fanin/fanout arrays + Abc_NtkForEachObj( pNtk, pNode, i ) + { + Abc_ObjForEachFanin( pNode, pTemp, k ) + pNode->vFanins.pArray[k] = pTemp->Id; + Abc_ObjForEachFanout( pNode, pTemp, k ) + pNode->vFanouts.pArray[k] = pTemp->Id; + } + + // replace the array of objs + Vec_PtrFree( pNtk->vObjs ); + pNtk->vObjs = vObjsNew; + + // rehash the AIG + Abc_AigRehash( pNtk->pManFunc ); + + // update the name manager!!! +} + +/**Function************************************************************* + + Synopsis [Detect cases when non-trivial FF matching is possible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDetectMatching( Abc_Ntk_t * pNtk ) +{ +/* + Abc_Obj_t * pLatch, * pFanin; + int i, nTFFs, nJKFFs; + nTFFs = nJKFFs = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pFanin = Abc_ObjFanin0(pLatch); + if ( Abc_ObjFaninNum(pFanin) != 2 ) + continue; + if ( Abc_NodeIsExorType(pLatch) ) + { + if ( Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch || + Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch ) + nTFFs++; + } + if ( Abc_ObjFaninNum( Abc_ObjFanin0(pFanin) ) != 2 || + Abc_ObjFaninNum( Abc_ObjFanin1(pFanin) ) != 2 ) + continue; + + if ( (Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch || + Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch) && + (Abc_ObjFanin0(Abc_ObjFanin1(pFanin)) == pLatch || + Abc_ObjFanin1(Abc_ObjFanin1(pFanin)) == pLatch) ) + { + nJKFFs++; + } + } + printf( "D = %6d. T = %6d. JK = %6d. (%6.2f %%)\n", + Abc_NtkLatchNum(pNtk), nTFFs, nJKFFs, 100.0 * nJKFFs / Abc_NtkLatchNum(pNtk) ); +*/ +} + + +/**Function************************************************************* + + Synopsis [Compares the pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjPointerCompare( void ** pp1, void ** pp2 ) +{ + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Adjusts the copy pointers.] + + Description [This procedure assumes that the network was transformed + into another network, which was in turn transformed into yet another + network. It makes the pCopy pointers of the original network point to + the objects of the yet another network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsNet(pObj) ) + pObj->pCopy = pObj->pCopy? Abc_ObjCopyCond(pObj->pCopy) : NULL; +} + + +/**Function************************************************************* + + Synopsis [Increaments the cut counter.] + + Description [Returns 1 if it becomes equal to the ref counter.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_ObjCrossCutInc( Abc_Obj_t * pObj ) +{ +// pObj->pCopy = (void *)(((int)pObj->pCopy)++); + int Value = (int)pObj->pCopy; + pObj->pCopy = (void *)(Value + 1); + return (int)pObj->pCopy == Abc_ObjFanoutNum(pObj); +} + +/**Function************************************************************* + + Synopsis [Computes cross-cut of the circuit.] + + Description [Returns 1 if it is the last visit to the node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCrossCut_rec( Abc_Obj_t * pObj, int * pnCutSize, int * pnCutSizeMax ) +{ + Abc_Obj_t * pFanin; + int i, nDecrem = 0; + int fReverse = 0; + if ( Abc_ObjIsCi(pObj) ) + return 0; + // if visited, increment visit counter + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return Abc_ObjCrossCutInc( pObj ); + Abc_NodeSetTravIdCurrent( pObj ); + // visit the fanins + if ( !Abc_ObjIsCi(pObj) ) + { + if ( fReverse ) + { + Abc_ObjForEachFanin( pObj, pFanin, i ) + { + pFanin = Abc_ObjFanin( pObj, Abc_ObjFaninNum(pObj) - 1 - i ); + nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax ); + } + } + else + { + Abc_ObjForEachFanin( pObj, pFanin, i ) + nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax ); + } + } + // count the node + (*pnCutSize)++; + if ( *pnCutSizeMax < *pnCutSize ) + *pnCutSizeMax = *pnCutSize; + (*pnCutSize) -= nDecrem; + return Abc_ObjCrossCutInc( pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes cross-cut of the circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCrossCut( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nCutSize = 0, nCutSizeMax = 0; + int i; + Abc_NtkCleanCopy( pNtk ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_NtkCrossCut_rec( pObj, &nCutSize, &nCutSizeMax ); + nCutSize--; + } + assert( nCutSize == 0 ); + printf( "Max cross cut size = %6d. Ratio = %6.2f %%\n", nCutSizeMax, 100.0 * nCutSizeMax/Abc_NtkObjNum(pNtk) ); + return nCutSizeMax; +} + + +/**Function************************************************************* + + Synopsis [Prints all 3-var functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrint256() +{ + FILE * pFile; + unsigned i; + pFile = fopen( "4varfs.txt", "w" ); + for ( i = 1; i < (1<<16)-1; i++ ) + { + fprintf( pFile, "read_truth " ); + Extra_PrintBinary( pFile, &i, 16 ); + fprintf( pFile, "; clp; st; w 1.blif; map; cec 1.blif\n" ); + } + fclose( pFile ); +} + + +static int * pSupps; + +/**Function************************************************************* + + Synopsis [Compares the supergates by their level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCompareConesCompare( int * pNum1, int * pNum2 ) +{ + if ( pSupps[*pNum1] > pSupps[*pNum2] ) + return -1; + if ( pSupps[*pNum1] < pSupps[*pNum2] ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Analyze choice node support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCompareCones( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupp, * vNodes, * vReverse; + Abc_Obj_t * pObj, * pTemp; + int Iter, i, k, Counter, CounterCos, CounterCosNew; + int * pPerms; + + // sort COs by support size + pPerms = ALLOC( int, Abc_NtkCoNum(pNtk) ); + pSupps = ALLOC( int, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pPerms[i] = i; + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + pSupps[i] = Vec_PtrSize(vSupp); + Vec_PtrFree( vSupp ); + } + qsort( (void *)pPerms, Abc_NtkCoNum(pNtk), sizeof(int), (int (*)(const void *, const void *)) Abc_NtkCompareConesCompare ); + + // consider COs in this order + Iter = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pObj = Abc_NtkCo( pNtk, pPerms[i] ); + if ( pObj->fMarkA ) + continue; + Iter++; + + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); + vReverse = Abc_NtkDfsReverseNodesContained( pNtk, (Abc_Obj_t **)Vec_PtrArray(vSupp), Vec_PtrSize(vSupp) ); + // count the number of nodes in the reverse cone + Counter = 0; + for ( k = 1; k < Vec_PtrSize(vReverse) - 1; k++ ) + for ( pTemp = Vec_PtrEntry(vReverse, k); pTemp; pTemp = pTemp->pCopy ) + Counter++; + CounterCos = CounterCosNew = 0; + for ( pTemp = Vec_PtrEntryLast(vReverse); pTemp; pTemp = pTemp->pCopy ) + { + assert( Abc_ObjIsCo(pTemp) ); + CounterCos++; + if ( pTemp->fMarkA == 0 ) + CounterCosNew++; + pTemp->fMarkA = 1; + } + // print statistics + printf( "%4d CO %5d : Supp = %5d. Lev = %3d. Cone = %5d. Rev = %5d. COs = %3d (%3d).\n", + Iter, pPerms[i], Vec_PtrSize(vSupp), Abc_ObjLevel(Abc_ObjFanin0(pObj)), Vec_PtrSize(vNodes), Counter, CounterCos, CounterCosNew ); + + // free arrays + Vec_PtrFree( vSupp ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vReverse ); + + if ( Vec_PtrSize(vSupp) < 10 ) + break; + } + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->fMarkA = 0; + + free( pPerms ); + free( pSupps ); +} + +/**Function************************************************************* + + Synopsis [Analyze choice node support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupp; + Abc_Obj_t * pObj, * pTemp; + int i, nNodesOld; + assert( Abc_NtkIsStrash(pNtk) ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + if ( !Abc_AigNodeIsChoice(pObj) ) + continue; + + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + nNodesOld = Vec_PtrSize(vSupp); + Vec_PtrFree( vSupp ); + + for ( pTemp = pObj->pData; pTemp; pTemp = pTemp->pData ) + { + vSupp = Abc_NtkNodeSupport( pNtk, &pTemp, 1 ); + if ( nNodesOld != Vec_PtrSize(vSupp) ) + printf( "Choice orig = %3d Choice new = %3d\n", nNodesOld, Vec_PtrSize(vSupp) ); + Vec_PtrFree( vSupp ); + } + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/abc_.c b/abc70930/src/base/abc/abc_.c new file mode 100644 index 00000000..50558bdb --- /dev/null +++ b/abc70930/src/base/abc/abc_.c @@ -0,0 +1,47 @@ +/**CFile**************************************************************** + + FileName [abc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abc/module.make b/abc70930/src/base/abc/module.make new file mode 100644 index 00000000..7b34d8f6 --- /dev/null +++ b/abc70930/src/base/abc/module.make @@ -0,0 +1,18 @@ +SRC += src/base/abc/abcAig.c \ + src/base/abc/abcBlifMv.c \ + src/base/abc/abcCheck.c \ + src/base/abc/abcDfs.c \ + src/base/abc/abcFanio.c \ + src/base/abc/abcFunc.c \ + src/base/abc/abcHie.c \ + src/base/abc/abcLatch.c \ + src/base/abc/abcLib.c \ + src/base/abc/abcMinBase.c \ + src/base/abc/abcNames.c \ + src/base/abc/abcNetlist.c \ + src/base/abc/abcNtk.c \ + src/base/abc/abcObj.c \ + src/base/abc/abcRefs.c \ + src/base/abc/abcShow.c \ + src/base/abc/abcSop.c \ + src/base/abc/abcUtil.c diff --git a/abc70930/src/base/abci/abc.c b/abc70930/src/base/abci/abc.c new file mode 100644 index 00000000..a331e7fa --- /dev/null +++ b/abc70930/src/base/abci/abc.c @@ -0,0 +1,12765 @@ +/**CFile**************************************************************** + + FileName [abc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Command file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "mainInt.h" +#include "fraig.h" +#include "fxu.h" +#include "cut.h" +#include "fpga.h" +#include "if.h" +#include "res.h" +#include "lpk.h" +#include "aig.h" +#include "dar.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_CommandPrintStats ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintExdc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintIo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintLatch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintFanio ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintMffc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintFactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintLevel ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintSupport ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintSymms ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintUnate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintAuto ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintKMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintGates ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintSharing ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintXCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintDsd ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandCollapse ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBalance ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMulti ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRenode ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFastExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDisjoint ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandImfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLutpack ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRestructure ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandResubstitute ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDemiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOrPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAndPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAppend ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFrames ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandReorder ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOrder ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMuxes ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCone ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandNode ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTopmost ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTrim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExdcFree ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExdcGet ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExdcSet ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//static int Abc_CommandXyz ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDouble ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandQuaVar ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandQuaRel ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandQuaReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandIStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandICut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDCompress2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDrwsat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIRewriteSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIResyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandISat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandHaig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMini ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandQbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigTrust ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigStore ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigRestore ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigClean ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigDress ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandHaigStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandHaigStop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandHaigUse ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandRecStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecStop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecAdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecUse ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAttach ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSuperChoiceLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFpgaFast ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIf ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandScut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandInit ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandZero ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUndc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPipe ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUnseq ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLcorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCycle ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandXsim ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDebug ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandTraceStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTraceCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Init( Abc_Frame_t * pAbc ) +{ +// Abc_NtkBddImplicationTest(); + + Cmd_CommandAdd( pAbc, "Printing", "print_stats", Abc_CommandPrintStats, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_exdc", Abc_CommandPrintExdc, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_io", Abc_CommandPrintIo, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_latch", Abc_CommandPrintLatch, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_fanio", Abc_CommandPrintFanio, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_mffc", Abc_CommandPrintMffc, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_symm", Abc_CommandPrintSymms, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_unate", Abc_CommandPrintUnate, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_auto", Abc_CommandPrintAuto, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_kmap", Abc_CommandPrintKMap, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_gates", Abc_CommandPrintGates, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_sharing", Abc_CommandPrintSharing, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_xcut", Abc_CommandPrintXCut, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_dsd", Abc_CommandPrintDsd, 0 ); + + Cmd_CommandAdd( pAbc, "Printing", "show", Abc_CommandShow, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "show_cut", Abc_CommandShowCut, 0 ); + + Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "balance", Abc_CommandBalance, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "multi", Abc_CommandMulti, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "renode", Abc_CommandRenode, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "cleanup", Abc_CommandCleanup, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "sweep", Abc_CommandSweep, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "fx", Abc_CommandFastExtract, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "dsd", Abc_CommandDisjoint, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "imfs", Abc_CommandImfs, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "lutpack", Abc_CommandLutpack, 1 ); + + Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 ); +// Cmd_CommandAdd( pAbc, "Synthesis", "restructure", Abc_CommandRestructure, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "resub", Abc_CommandResubstitute, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); + + Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 ); + Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 ); + Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 ); + Cmd_CommandAdd( pAbc, "Various", "demiter", Abc_CommandDemiter, 1 ); + Cmd_CommandAdd( pAbc, "Various", "orpos", Abc_CommandOrPos, 1 ); + Cmd_CommandAdd( pAbc, "Various", "andpos", Abc_CommandAndPos, 1 ); + Cmd_CommandAdd( pAbc, "Various", "append", Abc_CommandAppend, 1 ); + Cmd_CommandAdd( pAbc, "Various", "frames", Abc_CommandFrames, 1 ); + Cmd_CommandAdd( pAbc, "Various", "sop", Abc_CommandSop, 0 ); + Cmd_CommandAdd( pAbc, "Various", "bdd", Abc_CommandBdd, 0 ); + Cmd_CommandAdd( pAbc, "Various", "aig", Abc_CommandAig, 0 ); + Cmd_CommandAdd( pAbc, "Various", "reorder", Abc_CommandReorder, 0 ); + Cmd_CommandAdd( pAbc, "Various", "order", Abc_CommandOrder, 0 ); + Cmd_CommandAdd( pAbc, "Various", "muxes", Abc_CommandMuxes, 1 ); + Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 ); + Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandCone, 1 ); + Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandNode, 1 ); + Cmd_CommandAdd( pAbc, "Various", "topmost", Abc_CommandTopmost, 1 ); + Cmd_CommandAdd( pAbc, "Various", "trim", Abc_CommandTrim, 1 ); + Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 ); + Cmd_CommandAdd( pAbc, "Various", "exdc_free", Abc_CommandExdcFree, 1 ); + Cmd_CommandAdd( pAbc, "Various", "exdc_get", Abc_CommandExdcGet, 1 ); + Cmd_CommandAdd( pAbc, "Various", "exdc_set", Abc_CommandExdcSet, 1 ); + Cmd_CommandAdd( pAbc, "Various", "cut", Abc_CommandCut, 0 ); + Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 ); + Cmd_CommandAdd( pAbc, "Various", "gen", Abc_CommandGen, 0 ); +// Cmd_CommandAdd( pAbc, "Various", "xyz", Abc_CommandXyz, 1 ); + Cmd_CommandAdd( pAbc, "Various", "double", Abc_CommandDouble, 1 ); + Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 ); + + Cmd_CommandAdd( pAbc, "Various", "qvar", Abc_CommandQuaVar, 1 ); + Cmd_CommandAdd( pAbc, "Various", "qrel", Abc_CommandQuaRel, 1 ); + Cmd_CommandAdd( pAbc, "Various", "qreach", Abc_CommandQuaReach, 1 ); + + Cmd_CommandAdd( pAbc, "New AIG", "istrash", Abc_CommandIStrash, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "icut", Abc_CommandICut, 0 ); + Cmd_CommandAdd( pAbc, "New AIG", "irw", Abc_CommandIRewrite, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "drw", Abc_CommandDRewrite, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "drf", Abc_CommandDRefactor, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "dcompress2", Abc_CommandDCompress2, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "dchoice", Abc_CommandDChoice, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "drwsat", Abc_CommandDrwsat, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "irws", Abc_CommandIRewriteSeq, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "iresyn", Abc_CommandIResyn, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "isat", Abc_CommandISat, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "ifraig", Abc_CommandIFraig, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "dfraig", Abc_CommandDFraig, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "csweep", Abc_CommandCSweep, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "iprove", Abc_CommandIProve, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "haig", Abc_CommandHaig, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "mini", Abc_CommandMini, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "_bmc", Abc_CommandBmc, 0 ); + Cmd_CommandAdd( pAbc, "New AIG", "qbf", Abc_CommandQbf, 0 ); + + Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_trust", Abc_CommandFraigTrust, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_store", Abc_CommandFraigStore, 0 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_restore", Abc_CommandFraigRestore, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_clean", Abc_CommandFraigClean, 0 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_sweep", Abc_CommandFraigSweep, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "dress", Abc_CommandFraigDress, 1 ); + + Cmd_CommandAdd( pAbc, "Choicing", "haig_start", Abc_CommandHaigStart, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "haig_stop", Abc_CommandHaigStop, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "haig_use", Abc_CommandHaigUse, 1 ); + + Cmd_CommandAdd( pAbc, "Choicing", "rec_start", Abc_CommandRecStart, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_stop", Abc_CommandRecStop, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_add", Abc_CommandRecAdd, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_ps", Abc_CommandRecPs, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_use", Abc_CommandRecUse, 1 ); + + Cmd_CommandAdd( pAbc, "SC mapping", "map", Abc_CommandMap, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "unmap", Abc_CommandUnmap, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "attach", Abc_CommandAttach, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "sc", Abc_CommandSuperChoice, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "scl", Abc_CommandSuperChoiceLut, 1 ); + + Cmd_CommandAdd( pAbc, "FPGA mapping", "fpga", Abc_CommandFpga, 1 ); + Cmd_CommandAdd( pAbc, "FPGA mapping", "ffpga", Abc_CommandFpgaFast, 1 ); + Cmd_CommandAdd( pAbc, "FPGA mapping", "if", Abc_CommandIf, 1 ); + +// Cmd_CommandAdd( pAbc, "Sequential", "scut", Abc_CommandScut, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "init", Abc_CommandInit, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "zero", Abc_CommandZero, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "undc", Abc_CommandUndc, 1 ); +// Cmd_CommandAdd( pAbc, "Sequential", "pipe", Abc_CommandPipe, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "retime", Abc_CommandRetime, 1 ); +// Cmd_CommandAdd( pAbc, "Sequential", "sfpga", Abc_CommandSeqFpga, 1 ); +// Cmd_CommandAdd( pAbc, "Sequential", "smap", Abc_CommandSeqMap, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "ssweep", Abc_CommandSeqSweep, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "lcorr", Abc_CommandLcorr, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "scleanup", Abc_CommandSeqCleanup, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "cycle", Abc_CommandCycle, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "xsim", Abc_CommandXsim, 0 ); + + Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "dprove", Abc_CommandDProve, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "sat", Abc_CommandSat, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "dsat", Abc_CommandDSat, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "prove", Abc_CommandProve, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "debug", Abc_CommandDebug, 0 ); + +// Cmd_CommandAdd( pAbc, "Verification", "trace_start", Abc_CommandTraceStart, 0 ); +// Cmd_CommandAdd( pAbc, "Verification", "trace_check", Abc_CommandTraceCheck, 0 ); + +// Rwt_Man4ExploreStart(); +// Map_Var3Print(); +// Map_Var4Test(); + +// Abc_NtkPrint256(); +// Kit_TruthCountMintermsPrecomp(); +// Kit_DsdPrecompute4Vars(); + + { + extern void Dar_LibStart(); + Dar_LibStart(); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_End() +{ +// Dar_LibDumpPriorities(); + + { + extern void Cnf_ClearMemory(); + Cnf_ClearMemory(); + } + { + extern void Dar_LibStop(); + Dar_LibStop(); + } + + Abc_NtkFraigStoreClean(); +// Rwt_Man4ExplorePrint(); + +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + bool fShort; + int c; + int fFactor; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + fShort = 1; + fFactor = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sfh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fShort ^= 1; + break; + case 'f': + fFactor ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" ); + return 1; + } + Abc_NtkPrintStats( pOut, pNtk, fFactor ); + return 0; + +usage: + fprintf( pErr, "usage: print_stats [-fh]\n" ); + fprintf( pErr, "\t prints the network statistics\n" ); + fprintf( pErr, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp; + double Percentage; + bool fShort; + int c; + int fPrintDc; + + extern double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + fShort = 1; + fPrintDc = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sdh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fShort ^= 1; + break; + case 'd': + fPrintDc ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" ); + return 1; + } + if ( pNtk->pExdc == NULL ) + { + fprintf( Abc_FrameReadErr(pAbc), "Network has no EXDC.\n" ); + return 1; + } + + if ( fPrintDc ) + { + if ( !Abc_NtkIsStrash(pNtk->pExdc) ) + { + pNtkTemp = Abc_NtkStrash(pNtk->pExdc, 0, 0, 0); + Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtkTemp, 0) ) ); + Abc_NtkDelete( pNtkTemp ); + } + else + Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtk->pExdc, 0) ) ); + + printf( "EXDC network statistics: " ); + printf( "(" ); + if ( Percentage > 0.05 && Percentage < 99.95 ) + printf( "%.2f", Percentage ); + else if ( Percentage > 0.000005 && Percentage < 99.999995 ) + printf( "%.6f", Percentage ); + else + printf( "%f", Percentage ); + printf( " %% don't-cares)\n" ); + } + else + printf( "EXDC network statistics: \n" ); + Abc_NtkPrintStats( pOut, pNtk->pExdc, 0 ); + return 0; + +usage: + fprintf( pErr, "usage: print_exdc [-dh]\n" ); + fprintf( pErr, "\t prints the EXDC network statistics\n" ); + fprintf( pErr, "\t-d : toggles printing don't-care percentage [default = %s]\n", fPrintDc? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Abc_NodePrintFanio( pOut, pNode ); + return 0; + } + // print the nodes + Abc_NtkPrintIo( pOut, pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_io [-h] \n" ); + fprintf( pErr, "\t prints the PIs/POs or fanins/fanouts of a node\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tnode : the node to print fanins/fanouts\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + // print the nodes + Abc_NtkPrintLatch( pOut, pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_latch [-h]\n" ); + fprintf( pErr, "\t prints information about latches\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // print the nodes + Abc_NtkPrintFanio( pOut, pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_fanio [-h]\n" ); + fprintf( pErr, "\t prints the statistics about fanins/fanouts of all nodes\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintMffc( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + extern void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // print the nodes + Abc_NtkPrintMffc( pOut, pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_mffc [-h]\n" ); + fprintf( pErr, "\t prints the MFFC of each node in the network\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + int fUseRealNames; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseRealNames = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fUseRealNames ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + fprintf( pErr, "Printing factored forms can be done for SOP networks.\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Abc_NodePrintFactor( pOut, pNode, fUseRealNames ); + return 0; + } + // print the nodes + Abc_NtkPrintFactor( pOut, pNtk, fUseRealNames ); + return 0; + +usage: + fprintf( pErr, "usage: print_factor [-nh] \n" ); + fprintf( pErr, "\t prints the factored forms of nodes\n" ); + fprintf( pErr, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tnode : (optional) one node to consider\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + int fListNodes; + int fProfile; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fListNodes = 0; + fProfile = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fListNodes ^= 1; + break; + case 'p': + fProfile ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !fProfile && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Abc_NodePrintLevel( pOut, pNode ); + return 0; + } + // process all COs + Abc_NtkPrintLevel( pOut, pNtk, fProfile, fListNodes ); + return 0; + +usage: + fprintf( pErr, "usage: print_level [-nph] \n" ); + fprintf( pErr, "\t prints information about node level and cone size\n" ); + fprintf( pErr, "\t-n : toggles printing nodes by levels [default = %s]\n", fListNodes? "yes": "no" ); + fprintf( pErr, "\t-p : toggles printing level profile [default = %s]\n", fProfile? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tnode : (optional) one node to consider\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Vec_Ptr_t * vSuppFun; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fStruct; + int fVerbose; + extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ); + extern void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fStruct = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fStruct ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // print support information + if ( fStruct ) + { + Abc_NtkPrintStrSupports( pNtk ); + return 0; + } + + if ( !Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + vSuppFun = Sim_ComputeFunSupp( pNtk, fVerbose ); + free( vSuppFun->pArray[0] ); + Vec_PtrFree( vSuppFun ); + return 0; + +usage: + fprintf( pErr, "usage: print_supp [-svh]\n" ); + fprintf( pErr, "\t prints the supports of the CO nodes\n" ); + fprintf( pErr, "\t-s : toggle printing structural support only [default = %s].\n", fStruct? "yes": "no" ); + fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseBdds; + int fNaive; + int fReorder; + int fVerbose; + extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseBdds = 0; + fNaive = 0; + fReorder = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bnrvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fUseBdds ^= 1; + break; + case 'n': + fNaive ^= 1; + break; + case 'r': + fReorder ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); + Abc_NtkDelete( pNtk ); + } + return 0; + +usage: + fprintf( pErr, "usage: print_symm [-bnrvh]\n" ); + fprintf( pErr, "\t computes symmetries of the PO functions\n" ); + fprintf( pErr, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" ); + fprintf( pErr, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" ); + fprintf( pErr, "\t-r : enable dynamic BDD variable reordering [default = %s].\n", fReorder? "yes": "no" ); + fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintUnate( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseBdds; + int fUseNaive; + int fVerbose; + extern void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseBdds = 1; + fUseNaive = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fUseBdds ^= 1; + break; + case 'n': + fUseNaive ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + Abc_NtkPrintUnate( pNtk, fUseBdds, fUseNaive, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: print_unate [-bnvh]\n" ); + fprintf( pErr, "\t computes unate variables of the PO functions\n" ); + fprintf( pErr, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" ); + fprintf( pErr, "\t-n : toggle naive BDD-based computation [default = %s].\n", fUseNaive? "yes": "no" ); + fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int Output; + int fNaive; + int fVerbose; + extern void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Output = -1; + fNaive = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Onvh" ) ) != EOF ) + { + switch ( c ) + { + case 'O': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + Output = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Output < 0 ) + goto usage; + break; + case 'n': + fNaive ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + + + Abc_NtkAutoPrint( pNtk, Output, fNaive, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: print_auto [-O num] [-nvh]\n" ); + fprintf( pErr, "\t computes autosymmetries of the PO functions\n" ); + fprintf( pErr, "\t-O num : (optional) the 0-based number of the output [default = all]\n"); + fprintf( pErr, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" ); + fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + int fUseRealNames; + + extern void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseRealNames = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fUseRealNames ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Visualization of Karnaugh maps works for logic networks.\n" ); + return 1; + } + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + if ( argc == globalUtilOptind ) + { + pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); + if ( !Abc_ObjIsNode(pNode) ) + { + fprintf( pErr, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) ); + return 1; + } + } + else + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + } + Abc_NtkToBdd(pNtk); + Abc_NodePrintKMap( pNode, fUseRealNames ); + return 0; + +usage: + fprintf( pErr, "usage: print_kmap [-nh] \n" ); + fprintf( pErr, " shows the truth table of the node\n" ); + fprintf( pErr, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tnode : the node to consider (default = the driver of the first PO)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseLibrary; + + extern void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseLibrary = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLibrary ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkHasAig(pNtk) ) + { + fprintf( pErr, "Printing gates does not work for AIGs and sequential AIGs.\n" ); + return 1; + } + + Abc_NtkPrintGates( pNtk, fUseLibrary ); + return 0; + +usage: + fprintf( pErr, "usage: print_gates [-lh]\n" ); + fprintf( pErr, "\t prints statistics about gates used in the network\n" ); + fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseLibrary; + + extern void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseLibrary = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLibrary ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + Abc_NtkPrintSharing( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_sharing [-h]\n" ); + fprintf( pErr, "\t prints the number of shared nodes in the TFI cones of the COs\n" ); +// fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseLibrary; + + extern int Abc_NtkCrossCut( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseLibrary = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLibrary ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + Abc_NtkCrossCut( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: print_xcut [-h]\n" ); + fprintf( pErr, "\t prints the size of the cross cut of the current network\n" ); +// fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fCofactor; + int nCofLevel; + + extern void Kit_DsdTest( unsigned * pTruth, int nVars ); + extern void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nCofLevel = 1; + fCofactor = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nch" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nCofLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCofLevel < 0 ) + goto usage; + break; + case 'c': + fCofactor ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + // get the truth table of the first output + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Currently works only for logic networks.\n" ); + return 1; + } + Abc_NtkToAig( pNtk ); + // convert it to truth table + { + Abc_Obj_t * pObj = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); + Vec_Int_t * vMemory = Vec_IntAlloc(0); + unsigned * pTruth; + if ( !Abc_ObjIsNode(pObj) ) + { + fprintf( pErr, "The fanin of the first PO node does not have a logic function.\n" ); + return 1; + } + if ( Abc_ObjFaninNum(pObj) > 16 ) + { + fprintf( pErr, "Currently works only for up to 16 inputs.\n" ); + return 1; + } + pTruth = Abc_ConvertAigToTruth( pNtk->pManFunc, Hop_Regular(pObj->pData), Abc_ObjFaninNum(pObj), vMemory, 0 ); + if ( Hop_IsComplement(pObj->pData) ) + Extra_TruthNot( pTruth, pTruth, Abc_ObjFaninNum(pObj) ); + Extra_PrintBinary( stdout, pTruth, 1 << Abc_ObjFaninNum(pObj) ); + printf( "\n" ); + if ( fCofactor ) + Kit_DsdPrintCofactors( pTruth, Abc_ObjFaninNum(pObj), nCofLevel, 1 ); + else + Kit_DsdTest( pTruth, Abc_ObjFaninNum(pObj) ); + Vec_IntFree( vMemory ); + } + return 0; + +usage: + fprintf( pErr, "usage: print_dsd [-ch] [-N num]\n" ); + fprintf( pErr, "\t print DSD formula for a single-output function with less than 16 variables\n" ); + fprintf( pErr, "\t-c : toggle recursive cofactoring [default = %s]\n", fCofactor? "yes": "no" ); + fprintf( pErr, "\t-N num : the number of levels to cofactor [default = %d]\n", nCofLevel ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fSeq; + int fGateNames; + int fUseReverse; + extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fSeq = 0; + fGateNames = 0; + fUseReverse = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rsgh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + fUseReverse ^= 1; + break; + case 's': + fSeq ^= 1; + break; + case 'g': + fGateNames ^= 1; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse ); + return 0; + +usage: + fprintf( pErr, "usage: show [-srgh]\n" ); + fprintf( pErr, " visualizes the network structure using DOT and GSVIEW\n" ); +#ifdef WIN32 + fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + fprintf( pErr, "\t-s : toggles visualization of sequential networks [default = %s].\n", fSeq? "yes": "no" ); + fprintf( pErr, "\t-r : toggles ordering nodes in reverse order [default = %s].\n", fUseReverse? "yes": "no" ); + fprintf( pErr, "\t-g : toggles printing gate names for mapped network [default = %s].\n", fGateNames? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + extern void Abc_NodeShowBdd( Abc_Obj_t * pNode ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsBddLogic(pNtk) ) + { + fprintf( pErr, "Visualizing BDDs can only be done for logic BDD networks (run \"bdd\").\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + if ( argc == globalUtilOptind ) + { + pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); + if ( !Abc_ObjIsNode(pNode) ) + { + fprintf( pErr, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) ); + return 1; + } + } + else + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + } + Abc_NodeShowBdd( pNode ); + return 0; + +usage: + fprintf( pErr, "usage: show_bdd [-h] \n" ); + fprintf( pErr, " visualizes the BDD of a node using DOT and GSVIEW\n" ); +#ifdef WIN32 + fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + fprintf( pErr, "\tnode : the node to consider [default = the driver of the first PO]\n"); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c; + int nNodeSizeMax; + int nConeSizeMax; + extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nNodeSizeMax = 10; + nConeSizeMax = ABC_INFINITY; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NCh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodeSizeMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConeSizeMax < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Visualizing cuts only works for AIGs (run \"strash\").\n" ); + return 1; + } + if ( argc != globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax ); + return 0; + +usage: + fprintf( pErr, "usage: show_cut [-N num] [-C num] [-h] \n" ); + fprintf( pErr, " visualizes the cut of a node using DOT and GSVIEW\n" ); +#ifdef WIN32 + fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + fprintf( pErr, "\t-N num : the max size of the cut to be computed [default = %d]\n", nNodeSizeMax ); + fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax ); + fprintf( pErr, "\tnode : the node to consider\n"); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int fVerbose; + int fBddSizeMax; + int fDualRail; + int fReorder; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 1; + fReorder = 1; + fDualRail = 0; + fBddSizeMax = 50000000; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Brdvh" ) ) != EOF ) + { + switch ( c ) + { + case 'B': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + fBddSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fBddSizeMax < 0 ) + goto usage; + break; + case 'd': + fDualRail ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'r': + fReorder ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Can only collapse a logic network or an AIG.\n" ); + return 1; + } + + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); + Abc_NtkDelete( pNtk ); + } + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Collapsing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: collapse [-B num] [-rdvh]\n" ); + fprintf( pErr, "\t collapses the network by constructing global BDDs\n" ); + fprintf( pErr, "\t-B num : limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax ); + fprintf( pErr, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); + fprintf( pErr, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" ); + fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fAllNodes; + int fRecord; + int fCleanup; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fAllNodes = 0; + fCleanup = 1; + fRecord = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "acrh" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fAllNodes ^= 1; + break; + case 'c': + fCleanup ^= 1; + break; + case 'r': + fRecord ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup, fRecord ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Strashing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: strash [-acrh]\n" ); + fprintf( pErr, "\t transforms combinational logic into an AIG\n" ); + fprintf( pErr, "\t-a : toggles between using all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "DFS" ); + fprintf( pErr, "\t-c : toggles cleanup to remove the dagling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" ); + fprintf( pErr, "\t-r : enables using the record of AIG subgraphs [default = %s]\n", fRecord? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; + int c; + bool fDuplicate; + bool fSelective; + bool fUpdateLevel; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDuplicate = 0; + fSelective = 0; + fUpdateLevel = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ldsh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'd': + fDuplicate ^= 1; + break; + case 's': + fSelective ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + { + pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel ); + } + else + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtkTemp == NULL ) + { + fprintf( pErr, "Strashing before balancing has failed.\n" ); + return 1; + } + pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective, fUpdateLevel ); + Abc_NtkDelete( pNtkTemp ); + } + + // check if balancing worked + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Balancing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: balance [-ldsh]\n" ); + fprintf( pErr, "\t transforms the current network into a well-balanced AIG\n" ); + fprintf( pErr, "\t-l : toggle minimizing the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + fprintf( pErr, "\t-s : toggle duplication on the critical paths [default = %s]\n", fSelective? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int nThresh, nFaninMax, c; + int fCnf; + int fMulti; + int fSimple; + int fFactor; + extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nThresh = 1; + nFaninMax = 20; + fCnf = 0; + fMulti = 1; + fSimple = 0; + fFactor = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "TFmcsfh" ) ) != EOF ) + { + switch ( c ) + { + case 'T': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nThresh = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nThresh < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFaninMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFaninMax < 0 ) + goto usage; + break; + case 'c': + fCnf ^= 1; + break; + case 'm': + fMulti ^= 1; + break; + case 's': + fSimple ^= 1; + break; + case 'f': + fFactor ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkMulti( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Renoding has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: multi [-T num] [-F num] [-msfch]\n" ); + fprintf( pErr, "\t transforms an AIG into a logic network by creating larger nodes\n" ); + fprintf( pErr, "\t-F num : the maximum fanin size after renoding [default = %d]\n", nFaninMax ); + fprintf( pErr, "\t-T num : the threshold for AIG node duplication [default = %d]\n", nThresh ); + fprintf( pErr, "\t (an AIG node is the root of a new node after renoding\n" ); + fprintf( pErr, "\t if this leads to duplication of no more than %d AIG nodes,\n", nThresh ); + fprintf( pErr, "\t that is, if [(numFanouts(Node)-1) * size(MFFC(Node))] <= %d)\n", nThresh ); + fprintf( pErr, "\t-m : creates multi-input AND graph [default = %s]\n", fMulti? "yes": "no" ); + fprintf( pErr, "\t-s : creates a simple AIG (no renoding) [default = %s]\n", fSimple? "yes": "no" ); + fprintf( pErr, "\t-f : creates a factor-cut network [default = %s]\n", fFactor? "yes": "no" ); + fprintf( pErr, "\t-c : performs renoding to derive the CNF [default = %s]\n", fCnf? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int nLutSize, nCutsMax, c; + int nFlowIters, nAreaIters; + int fArea; + int fUseBdds; + int fUseSops; + int fUseCnfs; + int fUseMv; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLutSize = 8; + nCutsMax = 4; + nFlowIters = 1; + nAreaIters = 1; + fArea = 0; + fUseBdds = 0; + fUseSops = 0; + fUseCnfs = 0; + fUseMv = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscivh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by a positive integer.\n" ); + goto usage; + } + nFlowIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFlowIters < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-A\" should be followed by a positive integer.\n" ); + goto usage; + } + nAreaIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nAreaIters < 0 ) + goto usage; + break; + case 'a': + fArea ^= 1; + break; + case 'b': + fUseBdds ^= 1; + break; + case 's': + fUseSops ^= 1; + break; + case 'c': + fUseCnfs ^= 1; + break; + case 'i': + fUseMv ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( fUseBdds + fUseSops + fUseCnfs + fUseMv > 1 ) + { + fprintf( pErr, "Cannot optimize two parameters at the same time.\n" ); + return 1; + } + + if ( nLutSize < 3 || nLutSize > IF_MAX_FUNC_LUTSIZE ) + { + fprintf( pErr, "Incorrect LUT size (%d).\n", nLutSize ); + return 1; + } + + if ( nCutsMax < 1 || nCutsMax >= (1<<12) ) + { + fprintf( pErr, "Incorrect number of cuts.\n" ); + return 1; + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fUseMv, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Renoding has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: renode [-K num] [-C num] [-F num] [-A num] [-sbciav]\n" ); + fprintf( pErr, "\t transforms the AIG into a logic network with larger nodes\n" ); + fprintf( pErr, "\t while minimizing the number of FF literals of the node SOPs\n" ); + fprintf( pErr, "\t-K num : the max cut size for renoding (2 < num < %d) [default = %d]\n", IF_MAX_FUNC_LUTSIZE+1, nLutSize ); + fprintf( pErr, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCutsMax ); + fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", nFlowIters ); + fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", nAreaIters ); + fprintf( pErr, "\t-s : toggles minimizing SOP cubes instead of FF lits [default = %s]\n", fUseSops? "yes": "no" ); + fprintf( pErr, "\t-b : toggles minimizing BDD nodes instead of FF lits [default = %s]\n", fUseBdds? "yes": "no" ); + fprintf( pErr, "\t-c : toggles minimizing CNF clauses instead of FF lits [default = %s]\n", fUseCnfs? "yes": "no" ); + fprintf( pErr, "\t-i : toggles minimizing MV-SOP instead of FF lits [default = %s]\n", fUseMv? "yes": "no" ); + fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", fArea? "yes": "no" ); + fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Cleanup cannot be performed on the AIG.\n" ); + return 1; + } + // modify the current network + Abc_NtkCleanup( pNtk, 1 ); + return 0; + +usage: + fprintf( pErr, "usage: cleanup [-h]\n" ); + fprintf( pErr, "\t removes dangling nodes\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "The classical (SIS-like) sweep can only be performed on a logic network.\n" ); + return 1; + } + // modify the current network + Abc_NtkSweep( pNtk, 0 ); + return 0; + +usage: + fprintf( pErr, "usage: sweep [-h]\n" ); + fprintf( pErr, "\t removes dangling nodes; propagates constant, buffers, inverters\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + FILE * pOut, * pErr; + Fxu_Data_t * p = NULL; + int c; + extern bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); + extern void Abc_NtkFxuFreeInfo( Fxu_Data_t * p ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // allocate the structure + p = ALLOC( Fxu_Data_t, 1 ); + memset( p, 0, sizeof(Fxu_Data_t) ); + // set the defaults + p->nSingleMax = 20000; + p->nPairsMax = 30000; + p->nNodesExt = 10000; + p->fOnlyS = 0; + p->fOnlyD = 0; + p->fUse0 = 0; + p->fUseCompl = 1; + p->fVerbose = 0; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "SDNsdzcvh")) != EOF ) + { + switch (c) + { + case 'S': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + p->nSingleMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( p->nSingleMax < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + p->nPairsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( p->nPairsMax < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + p->nNodesExt = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( p->nNodesExt < 0 ) + goto usage; + break; + case 's': + p->fOnlyS ^= 1; + break; + case 'd': + p->fOnlyD ^= 1; + break; + case 'z': + p->fUse0 ^= 1; + break; + case 'c': + p->fUseCompl ^= 1; + break; + case 'v': + p->fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + Abc_NtkFxuFreeInfo( p ); + return 1; + } + + if ( Abc_NtkNodeNum(pNtk) == 0 ) + { + fprintf( pErr, "The network does not have internal nodes.\n" ); + Abc_NtkFxuFreeInfo( p ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Fast extract can only be applied to a logic network (run \"renode\").\n" ); + Abc_NtkFxuFreeInfo( p ); + return 1; + } + + + // the nodes to be merged are linked into the special linked list + Abc_NtkFastExtract( pNtk, p ); + Abc_NtkFxuFreeInfo( p ); + return 0; + +usage: + fprintf( pErr, "usage: fx [-S num] [-D num] [-N num] [-sdzcvh]\n"); + fprintf( pErr, "\t performs unate fast extract on the current network\n"); + fprintf( pErr, "\t-S num : max number of single-cube divisors to consider [default = %d]\n", p->nSingleMax ); + fprintf( pErr, "\t-D num : max number of double-cube divisors to consider [default = %d]\n", p->nPairsMax ); + fprintf( pErr, "\t-N num : the maximum number of divisors to extract [default = %d]\n", p->nNodesExt ); + fprintf( pErr, "\t-s : use only single-cube divisors [default = %s]\n", p->fOnlyS? "yes": "no" ); + fprintf( pErr, "\t-d : use only double-cube divisors [default = %s]\n", p->fOnlyD? "yes": "no" ); + fprintf( pErr, "\t-z : use zero-weight divisors [default = %s]\n", p->fUse0? "yes": "no" ); + fprintf( pErr, "\t-c : use complement in the binary case [default = %s]\n", p->fUseCompl? "yes": "no" ); + fprintf( pErr, "\t-v : print verbose information [default = %s]\n", p->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + Abc_NtkFxuFreeInfo( p ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkNew; + int fGlobal, fRecursive, fVerbose, fPrint, fShort, c; + + extern Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ); + extern int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fGlobal = 1; + fRecursive = 0; + fVerbose = 0; + fPrint = 0; + fShort = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "grvpsh" ) ) != EOF ) + { + switch ( c ) + { + case 'g': + fGlobal ^= 1; + break; + case 'r': + fRecursive ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'p': + fPrint ^= 1; + break; + case 's': + fShort ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( fGlobal ) + { +// fprintf( stdout, "Performing DSD of global functions of the network.\n" ); + // get the new network + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkDsdGlobal( pNtkNew, fVerbose, fPrint, fShort ); + Abc_NtkDelete( pNtkNew ); + } + else + { + pNtkRes = Abc_NtkDsdGlobal( pNtk, fVerbose, fPrint, fShort ); + } + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Global DSD has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } + else if ( fRecursive ) + { + if ( !Abc_NtkIsBddLogic( pNtk ) ) + { + fprintf( pErr, "This command is only applicable to logic BDD networks.\n" ); + return 1; + } + fprintf( stdout, "Performing recursive DSD and MUX decomposition of local functions.\n" ); + if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) ) + fprintf( pErr, "Recursive DSD has failed.\n" ); + } + else + { + if ( !Abc_NtkIsBddLogic( pNtk ) ) + { + fprintf( pErr, "This command is only applicable to logic BDD networks (run \"bdd\").\n" ); + return 1; + } + fprintf( stdout, "Performing simple non-recursive DSD of local functions.\n" ); + if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) ) + fprintf( pErr, "Simple DSD of local functions has failed.\n" ); + } + return 0; + +usage: + fprintf( pErr, "usage: dsd [-grvpsh]\n" ); + fprintf( pErr, "\t decomposes the network using disjoint-support decomposition\n" ); + fprintf( pErr, "\t-g : toggle DSD of global and local functions [default = %s]\n", fGlobal? "global": "local" ); + fprintf( pErr, "\t-r : toggle recursive DSD/MUX and simple DSD [default = %s]\n", fRecursive? "recursive DSD/MUX": "simple DSD" ); + fprintf( pErr, "\t-v : prints DSD statistics and runtime [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-p : prints DSD structure to the standard output [default = %s]\n", fPrint? "yes": "no" ); + fprintf( pErr, "\t-s : use short PI names when printing DSD structure [default = %s]\n", fShort? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandImfs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Res_Par_t Pars, * pPars = &Pars; + int c; + +// printf( "Implementation of this command is not finished.\n" ); +// return 1; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + pPars->nWindow = 62; + pPars->nGrowthLevel = 1; + pPars->nCands = 5; + pPars->nSimWords = 4; + pPars->fArea = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WSCLavwh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nWindow = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nWindow < 1 || pPars->nWindow > 99 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nSimWords = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nSimWords < 1 || pPars->nSimWords > 256 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nCands = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCands < 0 || pPars->nCands > ABC_INFINITY ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) + goto usage; + break; + case 'a': + pPars->fArea ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "This command can only be applied to a logic network.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkResynthesize( pNtk, pPars ) ) + { + fprintf( pErr, "Resynthesis has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: imfs [-W ] [-L ] [-C ] [-S ] [-avwh]\n" ); + fprintf( pErr, "\t performs resubstitution-based resynthesis with interpolation\n" ); + fprintf( pErr, "\t-W : fanin/fanout levels (NxM) of the window (00 <= NM <= 99) [default = %d%d]\n", pPars->nWindow/10, pPars->nWindow%10 ); + fprintf( pErr, "\t-L : the largest increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); + fprintf( pErr, "\t-C : the max number of resub candidates (1 <= n) [default = %d]\n", pPars->nCands ); + fprintf( pErr, "\t-S : the number of simulation words (1 <= n <= 256) [default = %d]\n", pPars->nSimWords ); + fprintf( pErr, "\t-a : toggle optimization for area only [default = %s]\n", pPars->fArea? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle printout subgraph statistics [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Lpk_Par_t Pars, * pPars = &Pars; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + memset( pPars, 0, sizeof(Lpk_Par_t) ); + pPars->nLutsMax = 4; // (N) the maximum number of LUTs in the structure + pPars->nLutsOver = 3; // (Q) the maximum number of LUTs not in the MFFC + pPars->nVarsShared = 0; // (S) the maximum number of shared variables (crossbars) + pPars->nGrowthLevel = 0; // (L) the maximum number of increased levels + pPars->fSatur = 1; + pPars->fZeroCost = 0; + pPars->fFirst = 0; + pPars->fOldAlgo = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NQSLszfovwh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutsMax < 2 || pPars->nLutsMax > 8 ) + goto usage; + break; + case 'Q': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-Q\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLutsOver = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutsOver < 0 || pPars->nLutsOver > 8 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nVarsShared = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 4 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) + goto usage; + break; + case 's': + pPars->fSatur ^= 1; + break; + case 'z': + pPars->fZeroCost ^= 1; + break; + case 'f': + pPars->fFirst ^= 1; + break; + case 'o': + pPars->fOldAlgo ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "This command can only be applied to a logic network.\n" ); + return 1; + } + if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 3 ) + { + fprintf( pErr, "The number of shared variables (%d) is not in the range 0 <= S <= 3.\n", pPars->nVarsShared ); + return 1; + } + + // modify the current network + if ( !Lpk_Resynthesize( pNtk, pPars ) ) + { + fprintf( pErr, "Resynthesis has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: lutpack [-N ] [-Q ] [-S ] [-L ] [-szfovwh]\n" ); + fprintf( pErr, "\t performs \"rewriting\" for LUT networks\n" ); + fprintf( pErr, "\t-N : the max number of LUTs in the structure (2 <= num) [default = %d]\n", pPars->nLutsMax ); + fprintf( pErr, "\t-Q : the max number of LUTs not in MFFC (0 <= num) [default = %d]\n", pPars->nLutsOver ); + fprintf( pErr, "\t-S : the max number of LUT inputs shared (0 <= num <= 3) [default = %d]\n", pPars->nVarsShared ); + fprintf( pErr, "\t-L : max level increase after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); + fprintf( pErr, "\t-s : toggle iteration till saturation [default = %s]\n", pPars->fSatur? "yes": "no" ); + fprintf( pErr, "\t-z : toggle zero-cost replacements [default = %s]\n", pPars->fZeroCost? "yes": "no" ); + fprintf( pErr, "\t-f : toggle using only first node and first cut [default = %s]\n", pPars->fFirst? "yes": "no" ); + fprintf( pErr, "\t-o : toggle using old implementation [default = %s]\n", pPars->fOldAlgo? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle detailed printout of decomposed functions [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + bool fUpdateLevel; + bool fPrecompute; + bool fUseZeros; + bool fVerbose; + bool fVeryVerbose; + bool fPlaceEnable; + // external functions + extern void Rwr_Precompute(); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUpdateLevel = 1; + fPrecompute = 0; + fUseZeros = 0; + fVerbose = 0; + fVeryVerbose = 0; + fPlaceEnable = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'x': + fPrecompute ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'p': + fPlaceEnable ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( fPrecompute ) + { + Rwr_Precompute(); + return 0; + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ) ) + { + fprintf( pErr, "Rewriting has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: rewrite [-lzvwh]\n" ); + fprintf( pErr, "\t performs technology-independent rewriting of the AIG\n" ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle printout subgraph statistics [default = %s]\n", fVeryVerbose? "yes": "no" ); +// fprintf( pErr, "\t-p : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nNodeSizeMax; + int nConeSizeMax; + bool fUpdateLevel; + bool fUseZeros; + bool fUseDcs; + bool fVerbose; + extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nNodeSizeMax = 10; + nConeSizeMax = 16; + fUpdateLevel = 1; + fUseZeros = 0; + fUseDcs = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NClzdvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodeSizeMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConeSizeMax < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'd': + fUseDcs ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + if ( fUseDcs && nNodeSizeMax >= nConeSizeMax ) + { + fprintf( pErr, "For don't-care to work, containing cone should be larger than collapsed node.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ) ) + { + fprintf( pErr, "Refactoring has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: refactor [-N num] [-C num] [-lzdvh]\n" ); + fprintf( pErr, "\t performs technology-independent refactoring of the AIG\n" ); + fprintf( pErr, "\t-N num : the max support of the collapsed node [default = %d]\n", nNodeSizeMax ); + fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-d : toggle using don't-cares [default = %s]\n", fUseDcs? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nCutsMax; + bool fUpdateLevel; + bool fUseZeros; + bool fVerbose; + extern int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutsMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nCutsMax = 5; + fUpdateLevel = 0; + fUseZeros = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Klzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( nCutsMax < 4 || nCutsMax > CUT_SIZE_MAX ) + { + fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", 4, CUT_SIZE_MAX ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRestructure( pNtk, nCutsMax, fUpdateLevel, fUseZeros, fVerbose ) ) + { + fprintf( pErr, "Refactoring has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: restructure [-K num] [-lzvh]\n" ); + fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" ); + fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, nCutsMax ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int RS_CUT_MIN = 4; + int RS_CUT_MAX = 16; + int c; + int nCutsMax; + int nNodesMax; + int nLevelsOdc; + bool fUpdateLevel; + bool fUseZeros; + bool fVerbose; + bool fVeryVerbose; + extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nLevelsOdc, bool fUpdateLevel, bool fVerbose, bool fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nCutsMax = 8; + nNodesMax = 1; + nLevelsOdc = 0; + fUpdateLevel = 1; + fUseZeros = 0; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KNFlzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodesMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodesMax < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nLevelsOdc = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevelsOdc < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX ) + { + fprintf( pErr, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX ); + return 1; + } + if ( nNodesMax < 0 || nNodesMax > 3 ) + { + fprintf( pErr, "Can only resubstitute at most 3 nodes.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) ) + { + fprintf( pErr, "Refactoring has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: resub [-K num] [-N num] [-F num] [-lzvwh]\n" ); + fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" ); + fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax ); + fprintf( pErr, "\t-N num : the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax ); + fprintf( pErr, "\t-F num : the number of fanout levels for ODC computation [default = %d]\n", nLevelsOdc ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle verbose printout of ODC computation [default = %s]\n", fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRr( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c, Window; + int nFaninLevels; + int nFanoutLevels; + int fUseFanouts; + int fVerbose; + extern int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFaninLevels = 3; + nFanoutLevels = 3; + fUseFanouts = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Wfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + Window = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Window < 0 ) + goto usage; + nFaninLevels = Window / 10; + nFanoutLevels = Window % 10; + break; + case 'f': + fUseFanouts ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRR( pNtk, nFaninLevels, nFanoutLevels, fUseFanouts, fVerbose ) ) + { + fprintf( pErr, "Redundancy removal has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: rr [-W NM] [-fvh]\n" ); + fprintf( pErr, "\t removes combinational redundancies in the current network\n" ); + fprintf( pErr, "\t-W NM : window size: TFI (N) and TFO (M) logic levels [default = %d%d]\n", nFaninLevels, nFanoutLevels ); + fprintf( pErr, "\t-f : toggle RR w.r.t. fanouts [default = %s]\n", fUseFanouts? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nLutSize; + int fCheck; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLutSize = 12; + fCheck = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kcvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'c': + fCheck ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Can only collapse a logic network or an AIG.\n" ); + return 1; + } + + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose ); + Abc_NtkDelete( pNtk ); + } + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Cascade synthesis has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: cascade [-K ] [-cvh]\n" ); + fprintf( pErr, "\t performs LUT cascade synthesis for the current network\n" ); + fprintf( pErr, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize ); + fprintf( pErr, "\t-c : check equivalence after synthesis [default = %s]\n", fCheck? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t \n"); + fprintf( pErr, " A lookup-table cascade is a programmable architecture developed by\n"); + fprintf( pErr, " Professor Tsutomu Sasao (sasao@cse.kyutech.ac.jp) at Kyushu Institute\n"); + fprintf( pErr, " of Technology. This work received Takeda Techno-Entrepreneurship Award:\n"); + fprintf( pErr, " http://www.lsi-cad.com/sasao/photo/takeda.html\n"); + fprintf( pErr, "\t \n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash( pNtk ) ) + { + fprintf( pErr, "This command is only applicable to strashed networks.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkToLogic( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Converting to a logic network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: logic [-h]\n" ); + fprintf( pErr, "\t transforms an AIG into a logic network with SOPs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandComb( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The network is already combinational.\n" ); + return 0; + } + + // get the new network + pNtkRes = Abc_NtkDup( pNtk ); + Abc_NtkMakeComb( pNtkRes ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: comb [-h]\n" ); + fprintf( pErr, "\t makes the current network combinational by replacing latches by PI/PO pairs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[32]; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fCheck; + int fComb; + int nPartSize; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fComb = 1; + fCheck = 1; + nPartSize = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Pch" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPartSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPartSize < 0 ) + goto usage; + break; + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + + // compute the miter + pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb, nPartSize ); + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + + // get the new network + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Miter computation has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( nPartSize == 0 ) + strcpy( Buffer, "unused" ); + else + sprintf( Buffer, "%d", nPartSize ); + fprintf( pErr, "usage: miter [-P num] [-ch] \n" ); + fprintf( pErr, "\t computes the miter of the two circuits\n" ); + fprintf( pErr, "\t-P num : output partition size [default = %s]\n", Buffer ); + fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); + fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); + fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk;//, * pNtkRes; + int fComb; + int c; + extern int Abc_NtkDemiter( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "The network is not strashed.\n" ); + return 1; + } + + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( pErr, "The network is not a miter.\n" ); + return 1; + } + + if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) + { + fprintf( pErr, "The miter's PO is not an EXOR.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkDemiter( pNtk ) ) + { + fprintf( pErr, "Demitering has failed.\n" ); + return 1; + } + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: demiter [-h]\n" ); + fprintf( pErr, "\t removes topmost EXOR from the miter to create two POs\n" ); +// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandOrPos( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk;//, * pNtkRes; + int fComb; + int c; + extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "The network is not strashed.\n" ); + return 1; + } +/* + if ( Abc_NtkPoNum(pNtk) == 1 ) + { + fprintf( pErr, "The network already has one PO.\n" ); + return 1; + } +*/ +/* + if ( Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "The miter has latches. ORing is not performed.\n" ); + return 1; + } +*/ + // get the new network + if ( !Abc_NtkCombinePos( pNtk, 0 ) ) + { + fprintf( pErr, "ORing the POs has failed.\n" ); + return 1; + } + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: orpos [-h]\n" ); + fprintf( pErr, "\t creates single-output miter by ORing the POs of the current network\n" ); +// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAndPos( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk;//, * pNtkRes; + int fComb; + int c; + extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "The network is not strashed.\n" ); + return 1; + } + + if ( Abc_NtkPoNum(pNtk) == 1 ) + { + fprintf( pErr, "The network already has one PO.\n" ); + return 1; + } + + if ( Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "The miter has latches. ORing is not performed.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkCombinePos( pNtk, 1 ) ) + { + fprintf( pErr, "ANDing the POs has failed.\n" ); + return 1; + } + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: andpos [-h]\n" ); + fprintf( pErr, "\t creates single-output miter by ANDing the POs of the current network\n" ); +// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAppend( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk2; + char * FileName; + int fComb; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + // get the second network + if ( argc != globalUtilOptind + 1 ) + { + fprintf( pErr, "The network to append is not given.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "The base network should be strashed for the appending to work.\n" ); + return 1; + } + + // read the second network + FileName = argv[globalUtilOptind]; + pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1 ); + if ( pNtk2 == NULL ) + return 1; + + // check if the second network is combinational + if ( Abc_NtkLatchNum(pNtk2) ) + { + fprintf( pErr, "The second network has latches. Appending does not work for such networks.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkAppend( pNtk, pNtk2, 1 ) ) + { + Abc_NtkDelete( pNtk2 ); + fprintf( pErr, "Appending the networks failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk2 ); + // sweep dangling logic + Abc_AigCleanup( pNtk->pManFunc ); + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: append [-h] \n" ); + fprintf( pErr, "\t appends a combinational network on top of the current network\n" ); +// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t : file name with the second network\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp, * pNtkRes; + int fInitial; + int nFrames; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fInitial = 0; + nFrames = 5; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Fih" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames <= 0 ) + goto usage; + break; + case 'i': + fInitial ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkFrames( pNtkTemp, nFrames, fInitial ); + Abc_NtkDelete( pNtkTemp ); + } + else + pNtkRes = Abc_NtkFrames( pNtk, nFrames, fInitial ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Unrolling the network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: frames [-F num] [-ih]\n" ); + fprintf( pErr, "\t unrolls the network for a number of time frames\n" ); + fprintf( pErr, "\t-F num : the number of frames to unroll [default = %d]\n", nFrames ); + fprintf( pErr, "\t-i : toggles initializing the first frame [default = %s]\n", fInitial? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int fDirect; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDirect = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDirect ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Converting to SOP is possible only for logic networks.\n" ); + return 1; + } + if ( !Abc_NtkToSop(pNtk, fDirect) ) + { + fprintf( pErr, "Converting to SOP has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: sop [-dh]\n" ); + fprintf( pErr, "\t converts node functions to SOP\n" ); + fprintf( pErr, "\t-d : toggles using both phases or only positive [default = %s]\n", fDirect? "direct": "both" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Converting to BDD is possible only for logic networks.\n" ); + return 1; + } + if ( Abc_NtkIsBddLogic(pNtk) ) + { + fprintf( pOut, "The logic network is already in the BDD form.\n" ); + return 0; + } + if ( !Abc_NtkToBdd(pNtk) ) + { + fprintf( pErr, "Converting to BDD has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: bdd [-h]\n" ); + fprintf( pErr, "\t converts node functions to BDD\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Converting to AIG is possible only for logic networks.\n" ); + return 1; + } + if ( Abc_NtkIsAigLogic(pNtk) ) + { + fprintf( pOut, "The logic network is already in the AIG form.\n" ); + return 0; + } + if ( !Abc_NtkToAig(pNtk) ) + { + fprintf( pErr, "Converting to AIG has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: aig [-h]\n" ); + fprintf( pErr, "\t converts node functions to AIG\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandReorder( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fVerbose; + extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkIsBddLogic(pNtk) ) + { + fprintf( pErr, "Variable reordering is possible when node functions are BDDs (run \"bdd\").\n" ); + return 1; + } + Abc_NtkBddReorder( pNtk, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: reorder [-vh]\n" ); + fprintf( pErr, "\t reorders local functions of the nodes using sifting\n" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr, * pFile; + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + int fReverse; + int fVerbose; + extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ); + extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fReverse = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + fReverse ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } +// if ( Abc_NtkLatchNum(pNtk) > 0 ) +// { +// printf( "Currently this procedure does not work for sequential networks.\n" ); +// return 1; +// } + + // if the var order file is given, implement this order + pFileName = NULL; + if ( argc == globalUtilOptind + 1 ) + { + pFileName = argv[globalUtilOptind]; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + fprintf( pErr, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName ); + return 1; + } + fclose( pFile ); + } + if ( pFileName ) + Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose ); + else + Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: order [-rvh] \n" ); + fprintf( pErr, "\t computes a good static CI variable order\n" ); + fprintf( pErr, "\t-r : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t : (optional) file with the given variable order\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsBddLogic(pNtk) ) + { + fprintf( pErr, "Only a BDD logic network can be converted to MUXes.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkBddToMuxes( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Converting to MUXes has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: muxes [-h]\n" ); + fprintf( pErr, "\t converts the current network by a network derived by\n" ); + fprintf( pErr, "\t replacing all nodes by DAGs isomorphic to the local BDDs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fVerbose; + extern int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNet, bool fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + fprintf( stdout, "The current network has no latches.\n" ); + return 0; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Extracting sequential don't-cares works only for AIGs (run \"strash\").\n" ); + return 0; + } + if ( !Abc_NtkExtractSequentialDcs( pNtk, fVerbose ) ) + { + fprintf( stdout, "Extracting sequential don't-cares has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: ext_seq_dcs [-vh]\n" ); + fprintf( pErr, "\t create EXDC network using unreachable states\n" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCone( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Obj_t * pNode, * pNodeCo; + int c; + int fUseAllCis; + int fUseMffc; + int Output; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseAllCis = 0; + fUseMffc = 0; + Output = -1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Omah" ) ) != EOF ) + { + switch ( c ) + { + case 'O': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + Output = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Output < 0 ) + goto usage; + break; + case 'm': + fUseMffc ^= 1; + case 'a': + fUseAllCis ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Currently can only be applied to the logic network or an AIG.\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + pNodeCo = NULL; + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + if ( fUseMffc ) + pNtkRes = Abc_NtkCreateMffc( pNtk, pNode, argv[globalUtilOptind] ); + else + pNtkRes = Abc_NtkCreateCone( pNtk, pNode, argv[globalUtilOptind], fUseAllCis ); + } + else + { + if ( Output == -1 ) + { + fprintf( pErr, "The node is not specified.\n" ); + return 1; + } + if ( Output >= Abc_NtkCoNum(pNtk) ) + { + fprintf( pErr, "The 0-based output number (%d) is larger than the number of outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) ); + return 1; + } + pNodeCo = Abc_NtkCo( pNtk, Output ); + if ( fUseMffc ) + pNtkRes = Abc_NtkCreateMffc( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo) ); + else + pNtkRes = Abc_NtkCreateCone( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo), fUseAllCis ); + } + if ( pNodeCo && Abc_ObjFaninC0(pNodeCo) ) + printf( "The extracted cone represents the complement function of the CO.\n" ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Writing the logic cone of one node has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: cone [-O num] [-amh] \n" ); + fprintf( pErr, "\t replaces the current network by one logic cone\n" ); + fprintf( pErr, "\t-a : toggle writing all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" ); + fprintf( pErr, "\t-m : toggle writing only MFFC or complete TFI cone [default = %s]\n", fUseMffc? "MFFC": "TFI cone" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t-O num : (optional) the 0-based number of the CO to extract\n"); + fprintf( pErr, "\tname : (optional) the name of the node to extract\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandNode( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Obj_t * pNode; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Currently can only be applied to a logic network.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 1 ) + { + fprintf( pErr, "Wrong number of auguments.\n" ); + goto usage; + } + + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + + pNtkRes = Abc_NtkCreateFromNode( pNtk, pNode ); +// pNtkRes = Abc_NtkDeriveFromBdd( pNtk->pManFunc, pNode->pData, NULL, NULL ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Splitting one node has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: node [-h] \n" ); + fprintf( pErr, "\t replaces the current network by the network composed of one node\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tname : the node name\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTopmost( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nLevels; + extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLevels = 10; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); + return 0; + } + + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( stdout, "Currently can only works for combinational circuits.\n" ); + return 0; + } + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( stdout, "Currently expects a single-output miter.\n" ); + return 0; + } + + pNtkRes = Abc_NtkTopmost( pNtk, nLevels ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: topmost [-N num] [-h]\n" ); + fprintf( pErr, "\t replaces the current network by several of its topmost levels\n" ); + fprintf( pErr, "\t-N num : max number of levels [default = %d]\n", nLevels ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tname : the node name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTrim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nLevels; + extern Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLevels = 10; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { +/* + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; +*/ + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Currently only works for logic circuits.\n" ); + return 0; + } + + pNtkRes = Abc_NtkTrim( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: trim [-h]\n" ); + fprintf( pErr, "\t removes POs fed by PIs and constants, and PIs w/o fanout\n" ); +// fprintf( pErr, "\t-N num : max number of levels [default = %d]\n", nLevels ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + Abc_NtkShortNames( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: short_names [-h]\n" ); + fprintf( pErr, "\t replaces PI/PO/latch names by short char strings\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExdcFree( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( pNtk->pExdc == NULL ) + { + fprintf( pErr, "The network has no EXDC.\n" ); + return 1; + } + + Abc_NtkDelete( pNtk->pExdc ); + pNtk->pExdc = NULL; + + // replace the current network + pNtkRes = Abc_NtkDup( pNtk ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: exdc_free [-h]\n" ); + fprintf( pErr, "\t frees the EXDC network of the current network\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExdcGet( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( pNtk->pExdc == NULL ) + { + fprintf( pErr, "The network has no EXDC.\n" ); + return 1; + } + + // replace the current network + pNtkRes = Abc_NtkDup( pNtk->pExdc ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: exdc_get [-h]\n" ); + fprintf( pErr, "\t replaces the current network by the EXDC of the current network\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr, * pFile; + Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; + char * FileName; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); + if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) ) + fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName ); + fprintf( pAbc->Err, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pNtkNew = Io_Read( FileName, Io_ReadFileType(FileName), 1 ); + if ( pNtkNew == NULL ) + { + fprintf( pAbc->Err, "Reading network from file has failed.\n" ); + return 1; + } + + // replace the EXDC + if ( pNtk->pExdc ) + { + Abc_NtkDelete( pNtk->pExdc ); + pNtk->pExdc = NULL; + } + pNtkRes = Abc_NtkDup( pNtk ); + pNtkRes->pExdc = pNtkNew; + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: exdc_set [-h] \n" ); + fprintf( pErr, "\t sets the network from file as EXDC for the current network\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t : file with the new EXDC network\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pCutMan; + Cut_Oracle_t * pCutOracle; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fOracle; + extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); + extern void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * pCutOracle ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fOracle = 0; + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 1000; // the max number of cuts kept at a node + pParams->fTruth = 0; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fDrop = 0; // drop cuts on the fly + pParams->fDag = 0; // compute DAG cuts + pParams->fTree = 0; // compute tree cuts + pParams->fGlobal = 0; // compute global cuts + pParams->fLocal = 0; // compute local cuts + pParams->fFancy = 0; // compute something fancy + pParams->fMap = 0; // compute mapping delay + pParams->fVerbose = 0; // the verbosiness flag + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzmvoh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nVarsMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nKeepMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nKeepMax < 0 ) + goto usage; + break; + case 't': + pParams->fTruth ^= 1; + break; + case 'f': + pParams->fFilter ^= 1; + break; + case 'd': + pParams->fDrop ^= 1; + break; + case 'x': + pParams->fDag ^= 1; + break; + case 'y': + pParams->fTree ^= 1; + break; + case 'g': + pParams->fGlobal ^= 1; + break; + case 'l': + pParams->fLocal ^= 1; + break; + case 'z': + pParams->fFancy ^= 1; + break; + case 'm': + pParams->fMap ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 'o': + fOracle ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Cut computation is available only for AIGs (run \"strash\").\n" ); + return 1; + } + if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) + { + fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); + return 1; + } + if ( pParams->fDag && pParams->fTree ) + { + fprintf( pErr, "Cannot compute both DAG cuts and tree cuts at the same time.\n" ); + return 1; + } + + if ( fOracle ) + pParams->fRecord = 1; + pCutMan = Abc_NtkCuts( pNtk, pParams ); + if ( fOracle ) + pCutOracle = Cut_OracleStart( pCutMan ); + Cut_ManStop( pCutMan ); + if ( fOracle ) + { + Abc_NtkCutsOracle( pNtk, pCutOracle ); + Cut_OracleStop( pCutOracle ); + } + return 0; + +usage: + fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdxyzmvh]\n" ); + fprintf( pErr, "\t computes k-feasible cuts for the AIG\n" ); + fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); + fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); + fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); + fprintf( pErr, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" ); + fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" ); + fprintf( pErr, "\t-x : toggle computing only DAG cuts [default = %s]\n", pParams->fDag? "yes": "no" ); + fprintf( pErr, "\t-y : toggle computing only tree cuts [default = %s]\n", pParams->fTree? "yes": "no" ); + fprintf( pErr, "\t-g : toggle computing only global cuts [default = %s]\n", pParams->fGlobal? "yes": "no" ); + fprintf( pErr, "\t-l : toggle computing only local cuts [default = %s]\n", pParams->fLocal? "yes": "no" ); + fprintf( pErr, "\t-z : toggle fancy computations [default = %s]\n", pParams->fFancy? "yes": "no" ); + fprintf( pErr, "\t-m : toggle delay-oriented FPGA mapping [default = %s]\n", pParams->fMap? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pCutMan; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 1000; // the max number of cuts kept at a node + pParams->fTruth = 0; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fSeq = 1; // compute sequential cuts + pParams->fVerbose = 0; // the verbosiness flag + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMtvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nVarsMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nKeepMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nKeepMax < 0 ) + goto usage; + break; + case 't': + pParams->fTruth ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } +/* + if ( !Abc_NtkIsSeq(pNtk) ) + { + fprintf( pErr, "Sequential cuts can be computed for sequential AIGs (run \"seq\").\n" ); + return 1; + } +*/ + if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) + { + fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); + return 1; + } + + pCutMan = Abc_NtkSeqCuts( pNtk, pParams ); + Cut_ManStop( pCutMan ); + return 0; + +usage: + fprintf( pErr, "usage: scut [-K num] [-M num] [-tvh]\n" ); + fprintf( pErr, "\t computes k-feasible cuts for the sequential AIG\n" ); + fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); + fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); + fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandEspresso( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fVerbose; + extern void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "SOP minimization is possible for logic networks (run \"renode\").\n" ); + return 1; + } + Abc_NtkEspresso( pNtk, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: espresso [-vh]\n" ); + fprintf( pErr, "\t minimizes SOPs of the local functions using Espresso\n" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nVars; + int fAdder; + int fSorter; + int fMesh; + int fFpga; + int fVerbose; + char * FileName; + extern void Abc_GenAdder( char * pFileName, int nVars ); + extern void Abc_GenSorter( char * pFileName, int nVars ); + extern void Abc_GenMesh( char * pFileName, int nVars ); + extern void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars ); + + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nVars = 8; + fAdder = 0; + fSorter = 0; + fMesh = 0; + fFpga = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nasmfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'a': + fAdder ^= 1; + break; + case 's': + fSorter ^= 1; + break; + case 'm': + fMesh ^= 1; + break; + case 'f': + fFpga ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( fAdder ) + Abc_GenAdder( FileName, nVars ); + else if ( fSorter ) + Abc_GenSorter( FileName, nVars ); + else if ( fMesh ) + Abc_GenMesh( FileName, nVars ); + else if ( fFpga ) + Abc_GenFpga( FileName, 4, 3, 10 ); +// Abc_GenFpga( FileName, 2, 2, 3 ); +// Abc_GenFpga( FileName, 3, 2, 5 ); + else + printf( "Type of circuit is not specified.\n" ); + return 0; + +usage: + fprintf( pErr, "usage: gen [-N] [-asmfvh] \n" ); + fprintf( pErr, "\t generates simple circuits\n" ); + fprintf( pErr, "\t-N num : the number of variables [default = %d]\n", nVars ); + fprintf( pErr, "\t-a : generate ripple-carry adder [default = %s]\n", fAdder? "yes": "no" ); + fprintf( pErr, "\t-s : generate a sorter [default = %s]\n", fSorter? "yes": "no" ); + fprintf( pErr, "\t-m : generate a mesh [default = %s]\n", fMesh? "yes": "no" ); + fprintf( pErr, "\t-f : generate a LUT FPGA structure [default = %s]\n", fFpga? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t : output file name\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandXyz( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes;//, * pNtkTemp; + int c; + int nLutMax; + int nPlaMax; + int RankCost; + int fFastMode; + int fRewriting; + int fSynthesis; + int fVerbose; +// extern Abc_Ntk_t * Abc_NtkXyz( Abc_Ntk_t * pNtk, int nPlaMax, bool fEsop, bool fSop, bool fInvs, bool fVerbose ); + extern void * Abc_NtkPlayer( void * pNtk, int nLutMax, int nPlaMax, int RankCost, int fFastMode, int fRewriting, int fSynthesis, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLutMax = 8; + nPlaMax = 128; + RankCost = 96000; + fFastMode = 1; + fRewriting = 0; + fSynthesis = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "LPRfrsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nLutMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutMax < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPlaMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPlaMax < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + RankCost = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( RankCost < 0 ) + goto usage; + break; + case 'f': + fFastMode ^= 1; + break; + case 'r': + fRewriting ^= 1; + break; + case 's': + fSynthesis ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Only works for strashed networks.\n" ); + return 1; + } +/* + if ( nLutMax < 2 || nLutMax > 12 || nPlaMax < 8 || nPlaMax > 128 ) + { + fprintf( pErr, "Incorrect LUT/PLA parameters.\n" ); + return 1; + } +*/ + // run the command +// pNtkRes = Abc_NtkXyz( pNtk, nPlaMax, 1, 0, fInvs, fVerbose ); +/* + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 ); + pNtkRes = Abc_NtkPlayer( pNtkTemp, nLutMax, nPlaMax, RankCost, fFastMode, fRewriting, fSynthesis, fVerbose ); + Abc_NtkDelete( pNtkTemp ); + } + else + pNtkRes = Abc_NtkPlayer( pNtk, nLutMax, nPlaMax, RankCost, fFastMode, fRewriting, fSynthesis, fVerbose ); +*/ + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: xyz [-L num] [-P num] [-R num] [-frsvh]\n" ); + fprintf( pErr, "\t specilized LUT/PLA decomposition\n" ); + fprintf( pErr, "\t-L num : maximum number of LUT inputs (2<=num<=8) [default = %d]\n", nLutMax ); + fprintf( pErr, "\t-P num : maximum number of PLA inputs/cubes (8<=num<=128) [default = %d]\n", nPlaMax ); + fprintf( pErr, "\t-R num : maximum are of one decomposition rank [default = %d]\n", RankCost ); + fprintf( pErr, "\t-f : toggle using fast LUT mapping mode [default = %s]\n", fFastMode? "yes": "no" ); + fprintf( pErr, "\t-r : toggle using one pass of AIG rewriting [default = %s]\n", fRewriting? "yes": "no" ); + fprintf( pErr, "\t-s : toggle using synthesis by AIG rewriting [default = %s]\n", fSynthesis? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDouble( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nFrames; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames = 50; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + fprintf( pErr, "Only works for logic SOP networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkDouble( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: double [-vh]\n" ); + fprintf( pErr, "\t puts together two parallel copies of the current network\n" ); +// fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nLevels; + int fVerbose; +// extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ); +// extern Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ); +// extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ); +// extern int Pr_ManProofTest( char * pFileName ); + extern void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk ); + extern void Abc_NtkCompareCones( Abc_Ntk_t * pNtk ); + extern Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk ); + extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName ); + extern Abc_Ntk_t * Abc_NtkFilter( Abc_Ntk_t * pNtk ); + extern Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkPcmTest( Abc_Ntk_t * pNtk, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + nLevels = 1000; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } +/* + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsSeq(pNtk) ) + { + fprintf( pErr, "Only works for non-sequential networks.\n" ); + return 1; + } +*/ + +// Abc_NtkTestEsop( pNtk ); +// Abc_NtkTestSop( pNtk ); +// printf( "This command is currently not used.\n" ); + // run the command +// pNtkRes = Abc_NtkMiterForCofactors( pNtk, 0, 0, -1 ); +// pNtkRes = Abc_NtkNewAig( pNtk ); + +/* + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); +*/ + +// if ( Cut_CellIsRunning() ) +// Cut_CellDumpToFile(); +// else +// Cut_CellPrecompute(); +// Cut_CellLoad(); +/* + { + Abc_Ntk_t * pNtkRes; + extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); + pNtkRes = Abc_NtkTopmost( pNtk, nLevels ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } +*/ +// Abc_NtkSimulteBuggyMiter( pNtk ); + +// Rwr_Temp(); +// Abc_MvExperiment(); +// Ivy_TruthTest(); + + +// Ivy_TruthEstimateNodesTest(); +/* + pNtkRes = Abc_NtkIvy( pNtk ); +// pNtkRes = Abc_NtkPlayer( pNtk, nLevels, 0 ); +// pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); +*/ +// Abc_NtkMaxFlowTest( pNtk ); +// Pr_ManProofTest( "trace.cnf" ); + +// Abc_NtkCompareSupports( pNtk ); +// Abc_NtkCompareCones( pNtk ); +/* + { + extern Vec_Vec_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int fVerbose ); + Vec_Vec_t * vParts; + vParts = Abc_NtkPartitionSmart( pNtk, 1 ); + Vec_VecFree( vParts ); + } +*/ +// Abc_Ntk4VarTable( pNtk ); +// Dar_NtkGenerateArrays( pNtk ); +// Dar_ManDeriveCnfTest2(); +/* + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Network should be strashed. Command has failed.\n" ); + return 1; + } +*/ +/* + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); + return 0; + } +*/ + if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Currently only works for logic circuits.\n" ); + return 0; + } + +// pNtkRes = Abc_NtkDar( pNtk ); +// pNtkRes = Abc_NtkDarRetime( pNtk, nLevels, 1 ); +// pNtkRes = Abc_NtkPcmTest( pNtk, fVerbose ); + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; +usage: + fprintf( pErr, "usage: test [-h]\n" ); + fprintf( pErr, "\t testbench for new procedures\n" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQuaVar( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, iVar, fUniv, fVerbose, RetValue; + extern int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + iVar = 0; + fUniv = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Iuvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + iVar = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iVar < 0 ) + goto usage; + break; + case 'u': + fUniv ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" ); + return 1; + } + + // get the strashed network + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + RetValue = Abc_NtkQuantify( pNtkRes, fUniv, iVar, fVerbose ); + // clean temporary storage for the cofactors + Abc_NtkCleanData( pNtkRes ); + Abc_AigCleanup( pNtkRes->pManFunc ); + // check the result + if ( !RetValue ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: qvar [-I num] [-uvh]\n" ); + fprintf( pErr, "\t quantifies one variable using the AIG\n" ); + fprintf( pErr, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar ); + fprintf( pErr, "\t-u : toggle universal quantification [default = %s]\n", fUniv? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQuaRel( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, iVar, fInputs, fVerbose; + extern Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + iVar = 0; + fInputs = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Iqvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + iVar = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iVar < 0 ) + goto usage; + break; + case 'q': + fInputs ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" ); + return 1; + } + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "This command works only for sequential circuits.\n" ); + return 1; + } + + // get the strashed network + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); + pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose ); + Abc_NtkDelete( pNtk ); + } + else + pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose ); + // check if the result is available + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: qrel [-qvh]\n" ); + fprintf( pErr, "\t computes transition relation of the sequential network\n" ); +// fprintf( pErr, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar ); + fprintf( pErr, "\t-q : perform quantification of inputs [default = %s]\n", fInputs? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQuaReach( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nIters, fVerbose; + extern Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtk, int nIters, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nIters = 256; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" ); + return 1; + } + if ( !Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "This command works only for combinational transition relations.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + if ( Abc_NtkPoNum(pNtk) > 1 ) + { + fprintf( pErr, "The transition relation should have one output.\n" ); + return 1; + } + if ( Abc_NtkPiNum(pNtk) % 2 != 0 ) + { + fprintf( pErr, "The transition relation should have an even number of inputs.\n" ); + return 1; + } + + pNtkRes = Abc_NtkReachability( pNtk, nIters, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: qreach [-I num] [-vh]\n" ); + fprintf( pErr, "\t computes unreachable states using AIG-based quantification\n" ); + fprintf( pErr, "\t assumes that the current network is a transition relation\n" ); + fprintf( pErr, "\t assumes that the initial state is composed of all zeros\n" ); + fprintf( pErr, "\t-I num : the number of image computations to perform [default = %d]\n", nIters ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; + int c; + extern Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 ); + pNtkRes = Abc_NtkIvyStrash( pNtkTemp ); + Abc_NtkDelete( pNtkTemp ); + } + else + pNtkRes = Abc_NtkIvyStrash( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: istrash [-h]\n" ); + fprintf( pErr, "\t perform sequential structural hashing\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandICut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c, nInputs; + extern void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nInputs = 5; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nInputs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInputs < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + Abc_NtkIvyCuts( pNtk, nInputs ); + return 0; + +usage: + fprintf( pErr, "usage: icut [-K num] [-h]\n" ); + fprintf( pErr, "\t computes sequential cuts of the given size\n" ); + fprintf( pErr, "\t-K num : the number of cut inputs (2 <= num <= 6) [default = %d]\n", nInputs ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fUseZeroCost, fVerbose; + extern Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUpdateLevel = 1; + fUseZeroCost = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeroCost ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyRewrite( pNtk, fUpdateLevel, fUseZeroCost, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: irw [-lzvh]\n" ); + fprintf( pErr, "\t perform combinational AIG rewriting\n" ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + Dar_RwrPar_t Pars, * pPars = &Pars; + int c; + + extern Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Dar_ManDefaultRwrParams( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CNflzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCutsMax < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nSubgMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nSubgMax < 0 ) + goto usage; + break; + case 'f': + pPars->fFanout ^= 1; + break; + case 'l': + pPars->fUpdateLevel ^= 1; + break; + case 'z': + pPars->fUseZeros ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDRewrite( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: drw [-C num] [-N num] [-flzvwh]\n" ); + fprintf( pErr, "\t performs combinational AIG rewriting\n" ); + fprintf( pErr, "\t-C num : the max number of cuts at a node [default = %d]\n", pPars->nCutsMax ); + fprintf( pErr, "\t-N num : the max number of subgraphs tried [default = %d]\n", pPars->nSubgMax ); + fprintf( pErr, "\t-f : toggle representing fanouts [default = %s]\n", pPars->fFanout? "yes": "no" ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + Dar_RefPar_t Pars, * pPars = &Pars; + int c; + + extern Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Dar_ManDefaultRefParams( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "MKCelzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'M': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMffcMin = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMffcMin < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLeafMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLeafMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCutsMax < 0 ) + goto usage; + break; + case 'e': + pPars->fExtend ^= 1; + break; + case 'l': + pPars->fUpdateLevel ^= 1; + break; + case 'z': + pPars->fUseZeros ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + if ( pPars->nLeafMax < 4 || pPars->nLeafMax > 15 ) + { + fprintf( pErr, "This command only works for cut sizes 4 <= K <= 15.\n" ); + return 1; + } + pNtkRes = Abc_NtkDRefactor( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: drf [-M num] [-K num] [-C num] [-elzvwh]\n" ); + fprintf( pErr, "\t performs combinational AIG refactoring\n" ); + fprintf( pErr, "\t-M num : the min MFFC size to attempt refactoring [default = %d]\n", pPars->nMffcMin ); + fprintf( pErr, "\t-K num : the max number of cuts leaves [default = %d]\n", pPars->nLeafMax ); + fprintf( pErr, "\t-C num : the max number of cuts to try at a node [default = %d]\n", pPars->nCutsMax ); + fprintf( pErr, "\t-e : toggle extending tbe cut below MFFC [default = %s]\n", pPars->fExtend? "yes": "no" ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int fBalance, fVerbose, fUpdateLevel, c; + + extern Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fBalance = 0; + fVerbose = 0; + fUpdateLevel = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "blvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fBalance ^= 1; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDCompress2( pNtk, fBalance, fUpdateLevel, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: dcompress2 [-blvh]\n" ); + fprintf( pErr, "\t performs combinational AIG optimization\n" ); + fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); + fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int fBalance, fVerbose, fUpdateLevel, c; + + extern Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fBalance = 1; + fUpdateLevel = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "blvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fBalance ^= 1; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDChoice( pNtk, fBalance, fUpdateLevel, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: dchoice [-blvh]\n" ); + fprintf( pErr, "\t performs partitioned choicing using a new AIG package\n" ); + fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); + fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDrwsat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int fBalance, fVerbose, c; + + extern Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fBalance = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fBalance ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDrwsat( pNtk, fBalance, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: drwsat [-bvh]\n" ); + fprintf( pErr, "\t performs combinational AIG optimization for SAT\n" ); + fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIRewriteSeq( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fUseZeroCost, fVerbose; + extern Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUpdateLevel = 0; + fUseZeroCost = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeroCost ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyRewriteSeq( pNtk, fUseZeroCost, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: irws [-zvh]\n" ); + fprintf( pErr, "\t perform sequential AIG rewriting\n" ); +// fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIResyn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fVerbose; + extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUpdateLevel = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyResyn( pNtk, fUpdateLevel, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: iresyn [-lvh]\n" ); + fprintf( pErr, "\t performs combinational resynthesis\n" ); + fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandISat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fVerbose; + int nConfLimit; + + extern Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nConfLimit = 100000; + fUpdateLevel = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Clzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvySat( pNtk, nConfLimit, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: isat [-C num] [-vh]\n" ); + fprintf( pErr, "\t tries to prove the miter constant 0\n" ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); +// fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fProve, fVerbose, fDoSparse; + int nConfLimit; + + extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nConfLimit = 100; + fDoSparse = 0; + fProve = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cspvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 's': + fDoSparse ^= 1; + break; + case 'p': + fProve ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: ifraig [-C num] [-spvh]\n" ); + fprintf( pErr, "\t performs fraiging using a new method\n" ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" ); + fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nConfLimit, fDoSparse, fProve, fSpeculate, fChoicing, fVerbose; + + extern Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nConfLimit = 100; + fDoSparse = 1; + fProve = 0; + fSpeculate = 0; + fChoicing = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Csprcvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 's': + fDoSparse ^= 1; + break; + case 'p': + fProve ^= 1; + break; + case 'r': + fSpeculate ^= 1; + break; + case 'c': + fChoicing ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkDarFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fSpeculate, fChoicing, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: dfraig [-C num] [-sprcvh]\n" ); + fprintf( pErr, "\t performs fraiging using a new method\n" ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" ); + fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" ); + fprintf( pErr, "\t-r : toggle speculative reduction [default = %s]\n", fSpeculate? "yes": "no" ); + fprintf( pErr, "\t-c : toggle accumulation of choices [default = %s]\n", fChoicing? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nCutsMax, nLeafMax, fVerbose; + + extern Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nCutsMax = 8; + nLeafMax = 6; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CKvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLeafMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLeafMax < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( nCutsMax < 2 ) + { + fprintf( pErr, "The number of cuts cannot be less than 2.\n" ); + return 1; + } + + if ( nLeafMax < 3 || nLeafMax > 16 ) + { + fprintf( pErr, "The number of leaves is infeasible.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkCSweep( pNtk, nCutsMax, nLeafMax, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: csweep [-C num] [-K num] [-vh]\n" ); + fprintf( pErr, "\t performs cut sweeping using a new method\n" ); + fprintf( pErr, "\t-C num : limit on the number of cuts (C >= 2) [default = %d]\n", nCutsMax ); + fprintf( pErr, "\t-K num : limit on the cut size (3 <= K <= 16) [default = %d]\n", nLeafMax ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Prove_Params_t Params, * pParams = &Params; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp; + int c, clk, RetValue; + + extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Prove_ParamsSetDefault( pParams ); + pParams->fUseRewriting = 1; + pParams->fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + pParams->fUseRewriting ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + clk = clock(); + + if ( Abc_NtkIsStrash(pNtk) ) + pNtkTemp = Abc_NtkDup( pNtk ); + else + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + + RetValue = Abc_NtkIvyProve( &pNtkTemp, pParams ); + + // verify that the pattern is correct + if ( RetValue == 0 ) + { + int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); + free( pSimInfo ); + } + + if ( RetValue == -1 ) + printf( "UNDECIDED " ); + else if ( RetValue == 0 ) + printf( "SATISFIABLE " ); + else + printf( "UNSATISFIABLE " ); + //printf( "\n" ); + + PRT( "Time", clock() - clk ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp ); + return 0; + +usage: + fprintf( pErr, "usage: iprove [-rvh]\n" ); + fprintf( pErr, "\t performs CEC using a new method\n" ); + fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pParams->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandHaig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUseZeroCost, fVerbose, nIters; + extern Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nIters = 2; + fUseZeroCost = 0; + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Izvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'z': + fUseZeroCost ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyHaig( pNtk, nIters, fUseZeroCost, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: haig [-Izvh]\n" ); + fprintf( pErr, "\t prints HAIG stats after sequential rewriting\n" ); + fprintf( pErr, "\t-I num : the number of rewriting iterations [default = %d]\n", nIters ); + fprintf( pErr, "\t-z : toggle zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMini( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + extern Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Only works for combinatinally strashed AIG networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkMiniBalance( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: mini [-h]\n" ); + fprintf( pErr, "\t perform balancing using new package\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBmc( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nFrames; + int fInit; + int fVerbose; + + extern void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames = 5; + fInit = 0; + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kivh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'i': + fInit ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkBmc( pNtk, nFrames, fInit, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkBmc( pNtk, nFrames, fInit, fVerbose ); + Abc_NtkDelete( pNtk ); + } + return 0; + +usage: + fprintf( pErr, "usage: _bmc [-K num] [-ivh]\n" ); + fprintf( pErr, "\t perform bounded model checking\n" ); + fprintf( pErr, "\t-K num : number of time frames [default = %d]\n", nFrames ); + fprintf( pErr, "\t-i : toggle initialization of the first frame [default = %s]\n", fInit? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nPars; + int fVerbose; + + extern void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nPars = -1; + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Pvh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPars < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "Works only for combinational networks.\n" ); + return 1; + } + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( pErr, "The miter should have one primary output.\n" ); + return 1; + } + if ( !(nPars > 0 && nPars < Abc_NtkPiNum(pNtk)) ) + { + fprintf( pErr, "The number of paramter variables is invalid (should be > 0 and < PI num).\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkQbf( pNtk, nPars, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkQbf( pNtk, nPars, fVerbose ); + Abc_NtkDelete( pNtk ); + } + return 0; + +usage: + fprintf( pErr, "usage: qbf [-P num] [-vh]\n" ); + fprintf( pErr, "\t solves a quantified boolean formula problem EpVxM(p,x)\n" ); + fprintf( pErr, "\t-P num : number of paramters (should be the first PIs) [default = %d]\n", nPars ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[100]; + Fraig_Params_t Params, * pParams = &Params; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int fAllNodes; + int fExdc; + int c; + int fPartition = 0; + extern void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fExdc = 0; + fAllNodes = 0; + memset( pParams, 0, sizeof(Fraig_Params_t) ); + pParams->nPatsRand = 2048; // the number of words of random simulation info + pParams->nPatsDyna = 2048; // the number of words of dynamic simulation info + pParams->nBTLimit = 100; // the max number of backtracks to perform + pParams->fFuncRed = 1; // performs only one level hashing + pParams->fFeedBack = 1; // enables solver feedback + pParams->fDist1Pats = 1; // enables distance-1 patterns + pParams->fDoSparse = 1; // performs equiv tests for sparse functions + pParams->fChoicing = 0; // enables recording structural choices + pParams->fTryProve = 0; // tries to solve the final miter + pParams->fVerbose = 0; // the verbosiness flag + pParams->fVerboseP = 0; // the verbosiness flag + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "RDCrscptvaeh" ) ) != EOF ) + { + switch ( c ) + { + case 'R': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nPatsRand = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nPatsRand < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nPatsDyna = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nPatsDyna < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nBTLimit < 0 ) + goto usage; + break; + + case 'r': + pParams->fFuncRed ^= 1; + break; + case 's': + pParams->fDoSparse ^= 1; + break; + case 'c': + pParams->fChoicing ^= 1; + break; + case 'p': + pParams->fTryProve ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 't': + fPartition ^= 1; + break; + case 'a': + fAllNodes ^= 1; + break; + case 'e': + fExdc ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Can only fraig a logic network or an AIG.\n" ); + return 1; + } + + // report the proof + pParams->fVerboseP = pParams->fTryProve; + + // get the new network + if ( fPartition ) + { + pNtkRes = Abc_NtkDup( pNtk ); + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkFraigPartitionedTime( pNtk, &Params ); + else + { + pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 ); + Abc_NtkFraigPartitionedTime( pNtk, &Params ); + Abc_NtkDelete( pNtk ); + } + } + else + { + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc ); + else + { + pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 ); + pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc ); + Abc_NtkDelete( pNtk ); + } + } + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Fraiging has failed.\n" ); + return 1; + } + + if ( pParams->fTryProve ) // report the result + Abc_NtkMiterReport( pNtkRes ); + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + sprintf( Buffer, "%d", pParams->nBTLimit ); + fprintf( pErr, "usage: fraig [-R num] [-D num] [-C num] [-rscpvtah]\n" ); + fprintf( pErr, "\t transforms a logic network into a functionally reduced AIG\n" ); + fprintf( pErr, "\t-R num : number of random patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsRand ); + fprintf( pErr, "\t-D num : number of systematic patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsDyna ); + fprintf( pErr, "\t-C num : number of backtracks for one SAT problem [default = %s]\n", pParams->nBTLimit==-1? "infinity" : Buffer ); + fprintf( pErr, "\t-r : toggle functional reduction [default = %s]\n", pParams->fFuncRed? "yes": "no" ); + fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", pParams->fDoSparse? "yes": "no" ); + fprintf( pErr, "\t-c : toggle accumulation of choices [default = %s]\n", pParams->fChoicing? "yes": "no" ); + fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", pParams->fTryProve? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", pParams->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" ); + fprintf( pErr, "\t-a : toggle between all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "dfs" ); + fprintf( pErr, "\t-t : toggle using partitioned representation [default = %s]\n", fPartition? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigTrust( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fDuplicate; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDuplicate = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDuplicate ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkFraigTrust( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Fraiging in the trust mode has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: fraig_trust [-h]\n" ); + fprintf( pErr, "\t transforms the current network into an AIG assuming it is FRAIG with choices\n" ); +// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fDuplicate; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDuplicate = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDuplicate ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkFraigStore( pNtk ) ) + { + fprintf( pErr, "Fraig storing has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: fraig_store [-h]\n" ); + fprintf( pErr, "\t saves the current network in the AIG database\n" ); +// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigRestore( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fDuplicate; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDuplicate = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDuplicate ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkFraigRestore(); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Fraig restoring has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: fraig_restore [-h]\n" ); + fprintf( pErr, "\t makes the current network by fraiging the AIG database\n" ); +// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fDuplicate; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fDuplicate = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDuplicate ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + Abc_NtkFraigStoreClean(); + return 0; + +usage: + fprintf( pErr, "usage: fraig_clean [-h]\n" ); + fprintf( pErr, "\t cleans the internal FRAIG storage\n" ); +// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fUseInv; + int fExdc; + int fVerbose; + int fVeryVerbose; + extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fUseInv = 1; + fExdc = 0; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ievwh" ) ) != EOF ) + { + switch ( c ) + { + case 'i': + fUseInv ^= 1; + break; + case 'e': + fExdc ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Cannot sweep AIGs (use \"fraig\").\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "Transform the current network into a logic network.\n" ); + return 1; + } + // modify the current network + if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fExdc, fVerbose, fVeryVerbose ) ) + { + fprintf( pErr, "Sweeping has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: fraig_sweep [-evwh]\n" ); + fprintf( pErr, "\t performs technology-dependent sweep\n" ); + fprintf( pErr, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : prints equivalence class information [default = %s]\n", fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigDress( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + int fVerbose; + extern void Abc_NtkDress( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for logic networks.\n" ); + return 1; + } + if ( argc != globalUtilOptind && argc != globalUtilOptind + 1 ) + goto usage; + if ( argc == globalUtilOptind && Abc_NtkSpec(pNtk) == NULL ) + { + fprintf( pErr, "The current network has no spec.\n" ); + return 1; + } + // get the input file name + pFileName = (argc == globalUtilOptind + 1) ? argv[globalUtilOptind] : Abc_NtkSpec(pNtk); + // modify the current network + Abc_NtkDress( pNtk, pFileName, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: dress [-vh] \n" ); + fprintf( pErr, "\t transfers internal node names from file to the current network\n" ); + fprintf( pErr, "\t : network with names (if not given, the current network spec is used)\n" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandHaigStart( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); + return 0; + } + Abc_NtkHaigStart( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: haig_start [-h]\n" ); + fprintf( pErr, "\t starts constructive accumulation of combinational choices\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandHaigStop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); + return 0; + } + Abc_NtkHaigStop( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: haig_stop [-h]\n" ); + fprintf( pErr, "\t cleans the internal storage for combinational choices\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandHaigUse( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); + return 0; + } + // get the new network + pNtkRes = Abc_NtkHaigUse( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Transforming internal storage into AIG with choices has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: haig_use [-h]\n" ); + fprintf( pErr, "\t transforms internal storage into an AIG with choices\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecStart( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nVars; + int nCuts; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nVars = 4; + nCuts = 8; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KCh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 1 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCuts < 1 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !(nVars >= 3 && nVars <= 16) ) + { + fprintf( pErr, "The range of allowed values is 3 <= K <= 16.\n" ); + return 0; + } + if ( Abc_NtkRecIsRunning() ) + { + fprintf( pErr, "The AIG subgraph recording is already started.\n" ); + return 0; + } + if ( pNtk && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); + return 0; + } + Abc_NtkRecStart( pNtk, nVars, nCuts ); + return 0; + +usage: + fprintf( pErr, "usage: rec_start [-K num] [-C num] [-h]\n" ); + fprintf( pErr, "\t starts recording AIG subgraphs (should be called for\n" ); + fprintf( pErr, "\t an empty network or after reading in a previous record)\n" ); + fprintf( pErr, "\t-K num : the largest number of inputs [default = %d]\n", nVars ); + fprintf( pErr, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCuts ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecStop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning() ) + { + fprintf( pErr, "This command works only after calling \"rec_start\".\n" ); + return 0; + } + Abc_NtkRecStop(); + return 0; + +usage: + fprintf( pErr, "usage: rec_stop [-h]\n" ); + fprintf( pErr, "\t cleans the internal storage for AIG subgraphs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecAdd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works for AIGs.\n" ); + return 0; + } + if ( !Abc_NtkRecIsRunning() ) + { + fprintf( pErr, "This command works for AIGs after calling \"rec_start\".\n" ); + return 0; + } + Abc_NtkRecAdd( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: rec_add [-h]\n" ); + fprintf( pErr, "\t adds subgraphs from the current network to the set\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecPs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning() ) + { + fprintf( pErr, "This command works for AIGs only after calling \"rec_start\".\n" ); + return 0; + } + Abc_NtkRecPs(); + return 0; + +usage: + fprintf( pErr, "usage: rec_ps [-h]\n" ); + fprintf( pErr, "\t prints statistics about the recorded AIG subgraphs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecUse( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning() ) + { + fprintf( pErr, "This command works for AIGs only after calling \"rec_start\".\n" ); + return 0; + } + // get the new network + pNtkRes = Abc_NtkRecUse(); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Transforming internal AIG subgraphs into an AIG with choices has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: rec_use [-h]\n" ); + fprintf( pErr, "\t transforms internal storage into an AIG with choices\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + char Buffer[100]; + double DelayTarget; + int fRecovery; + int fSweep; + int fSwitching; + int fVerbose; + int c; + extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int fSwitching, int fVerbose ); + extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + DelayTarget =-1; + fRecovery = 1; + fSweep = 1; + fSwitching = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Daspvh" ) ) != EOF ) + { + switch ( c ) + { + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + goto usage; + } + DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( DelayTarget <= 0.0 ) + goto usage; + break; + case 'a': + fRecovery ^= 1; + break; + case 's': + fSweep ^= 1; + break; + case 'p': + fSwitching ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Strashing before mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Balancing before mapping has failed.\n" ); + return 1; + } + fprintf( pOut, "The network was strashed and balanced before mapping.\n" ); + // get the new network + pNtkRes = Abc_NtkMap( pNtk, DelayTarget, fRecovery, fSwitching, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + fprintf( pErr, "Mapping has failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk ); + } + else + { + // get the new network + pNtkRes = Abc_NtkMap( pNtk, DelayTarget, fRecovery, fSwitching, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Mapping has failed.\n" ); + return 1; + } + } + + if ( fSweep ) + Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 ); + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( DelayTarget == -1 ) + sprintf( Buffer, "not used" ); + else + sprintf( Buffer, "%.3f", DelayTarget ); + fprintf( pErr, "usage: map [-D float] [-aspvh]\n" ); + fprintf( pErr, "\t performs standard cell mapping of the current network\n" ); + fprintf( pErr, "\t-D float : sets the global required times [default = %s]\n", Buffer ); + fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); + fprintf( pErr, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" ); + fprintf( pErr, "\t-p : optimizes power by minimizing switching [default = %s]\n", fSwitching? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkHasMapping(pNtk) ) + { + fprintf( pErr, "Cannot unmap the network that is not mapped.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkMapToSop( pNtk ) ) + { + fprintf( pErr, "Unmapping has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: unmap [-h]\n" ); + fprintf( pErr, "\t replaces the library gates by the logic nodes represented using SOPs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAttach( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + fprintf( pErr, "Can only attach gates if the nodes have SOP representations.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkAttach( pNtk ) ) + { + fprintf( pErr, "Attaching gates has failed.\n" ); + return 1; + } + return 0; + +usage: + fprintf( pErr, "usage: attach [-h]\n" ); + fprintf( pErr, "\t replaces the SOP functions by the gates from the library\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Superchoicing works only for the AIG representation (run \"strash\").\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkSuperChoice( pNtk ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Superchoicing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: sc [-h]\n" ); + fprintf( pErr, "\t performs superchoicing\n" ); + fprintf( pErr, "\t (accumulate: \"r file.blif; rsup; b; sc; f -ac; wb file_sc.blif\")\n" ); + fprintf( pErr, "\t (map without supergate library: \"r file_sc.blif; ft; map\")\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSuperChoiceLut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nLutSize; + int nCutSizeMax; + int fVerbose; + extern int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 1; + nLutSize = 4; + nCutSizeMax = 10; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KNh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by a positive integer.\n" ); + goto usage; + } + nCutSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutSizeMax < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Superchoicing works only for the AIG representation (run \"strash\").\n" ); + return 1; + } + + // convert the network into the SOP network + pNtkRes = Abc_NtkToLogic( pNtk ); + + // get the new network + if ( !Abc_NtkSuperChoiceLut( pNtkRes, nLutSize, nCutSizeMax, fVerbose ) ) + { + Abc_NtkDelete( pNtkRes ); + fprintf( pErr, "Superchoicing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: scl [-K num] [-N num] [-vh]\n" ); + fprintf( pErr, "\t performs superchoicing for K-LUTs\n" ); + fprintf( pErr, "\t (accumulate: \"r file.blif; b; scl; f -ac; wb file_sc.blif\")\n" ); + fprintf( pErr, "\t (FPGA map: \"r file_sc.blif; ft; read_lut lutlibK; fpga\")\n" ); + fprintf( pErr, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize ); + fprintf( pErr, "\t-N num : the max size of the cut [default = %d]\n", nCutSizeMax ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[100]; + char LutSize[100]; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fRecovery; + int fSwitching; + int fLatchPaths; + int fVerbose; + int nLutSize; + float DelayTarget; + + extern Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fRecovery = 1; + fSwitching = 0; + fLatchPaths = 0; + fVerbose = 0; + DelayTarget =-1; + nLutSize =-1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "aplvhDK" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fRecovery ^= 1; + break; + case 'p': + fSwitching ^= 1; + break; + case 'l': + fLatchPaths ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + goto usage; + } + DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( DelayTarget <= 0.0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // create the new LUT library + if ( nLutSize >= 3 && nLutSize <= 10 ) + Fpga_SetSimpleLutLib( nLutSize ); +/* + else + { + fprintf( pErr, "Cannot perform FPGA mapping with LUT size %d.\n", nLutSize ); + return 1; + } +*/ + if ( !Abc_NtkIsStrash(pNtk) ) + { + // strash and balance the network + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); + return 1; + } + fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" ); + // get the new network + pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk ); + } + else + { + // get the new network + pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 1; + } + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( DelayTarget == -1 ) + sprintf( Buffer, "best possible" ); + else + sprintf( Buffer, "%.2f", DelayTarget ); + if ( nLutSize == -1 ) + sprintf( LutSize, "library" ); + else + sprintf( LutSize, "%d", nLutSize ); + fprintf( pErr, "usage: fpga [-D float] [-K num] [-aplvh]\n" ); + fprintf( pErr, "\t performs FPGA mapping of the current network\n" ); + fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); + fprintf( pErr, "\t-p : optimizes power by minimizing switching activity [default = %s]\n", fSwitching? "yes": "no" ); + fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", fLatchPaths? "yes": "no" ); + fprintf( pErr, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer ); + fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < 11) [default = %s]%s\n", LutSize, (nLutSize == -1 ? " (type \"print_lut\")" : "") ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : prints the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFpgaFast( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[100]; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fRecovery; + int fVerbose; + int nLutSize; + float DelayTarget; + + extern Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fRecovery = 1; + fVerbose = 0; + DelayTarget =-1; + nLutSize = 5; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "avhDK" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fRecovery ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + goto usage; + } + DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( DelayTarget <= 0.0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + // strash and balance the network + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); + return 1; + } + fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" ); + // get the new network + pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk ); + } + else + { + // get the new network + pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 1; + } + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( DelayTarget == -1 ) + sprintf( Buffer, "not used" ); + else + sprintf( Buffer, "%.2f", DelayTarget ); + fprintf( pErr, "usage: ffpga [-K num] [-avh]\n" ); + fprintf( pErr, "\t performs fast FPGA mapping of the current network\n" ); + fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); +// fprintf( pErr, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer ); + fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < 32) [default = %d]\n", nLutSize ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : prints the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[100]; + char LutSize[100]; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + If_Par_t Pars, * pPars = &Pars; + int c; + extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + memset( pPars, 0, sizeof(If_Par_t) ); + // user-controlable paramters + pPars->nLutSize = -1; + pPars->nCutsMax = 8; + pPars->nFlowIters = 1; + pPars->nAreaIters = 2; + pPars->DelayTarget = -1; + pPars->fPreprocess = 1;// + pPars->fArea = 0; + pPars->fFancy = 0; + pPars->fExpRed = 1;// + pPars->fLatchPaths = 0; + pPars->fSeqMap = 0; + pPars->fVerbose = 0;// + // internal parameters + pPars->fTruth = 0; + pPars->nLatches = pNtk? Abc_NtkLatchNum(pNtk) : 0; + pPars->fLiftLeaves = 0; + pPars->pLutLib = Abc_FrameReadLibLut(); + pPars->pTimesArr = NULL; + pPars->pTimesArr = NULL; + pPars->pFuncCost = NULL; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADpaflrstvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutSize < 0 ) + goto usage; + // if the LUT size is specified, disable library + pPars->pLutLib = NULL; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCutsMax < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nFlowIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nFlowIters < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-A\" should be followed by a positive integer.\n" ); + goto usage; + } + pPars->nAreaIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nAreaIters < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->DelayTarget <= 0.0 ) + goto usage; + break; + case 'p': + pPars->fPreprocess ^= 1; + break; + case 'a': + pPars->fArea ^= 1; + break; + case 'f': + pPars->fFancy ^= 1; + break; + case 'l': + pPars->fLatchPaths ^= 1; + break; + case 'r': + pPars->fExpRed ^= 1; + break; + case 's': + pPars->fSeqMap ^= 1; + break; + case 't': + pPars->fLiftLeaves ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( pPars->fSeqMap && pPars->nLatches == 0 ) + { + fprintf( pErr, "The network has no latches. Use combinational mapping instead of sequential.\n" ); + return 1; + } + + if ( pPars->nLutSize == -1 ) + { + if ( pPars->pLutLib == NULL ) + { + fprintf( pErr, "The LUT library is not given.\n" ); + return 1; + } + // get LUT size from the library + pPars->nLutSize = pPars->pLutLib->LutMax; + } + + if ( pPars->nLutSize < 3 || pPars->nLutSize > IF_MAX_LUTSIZE ) + { + fprintf( pErr, "Incorrect LUT size (%d).\n", pPars->nLutSize ); + return 1; + } + + if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) ) + { + fprintf( pErr, "Incorrect number of cuts.\n" ); + return 1; + } + + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + printf( "Performing FPGA mapping with choices.\n" ); +// printf( "Currently mapping with choices is not enabled.\n" ); + pPars->fTruth = 1; +// return 1; + } + + if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE ) + { + fprintf( pErr, "Mapping with choices requires computing truth tables. In this case, the LUT size cannot be more than %d.\n", IF_MAX_FUNC_LUTSIZE ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + // strash and balance the network + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtk == NULL ) + { + fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); + return 1; + } + fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" ); + // get the new network + pNtkRes = Abc_NtkIf( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 0; + } + Abc_NtkDelete( pNtk ); + } + else + { + // get the new network + pNtkRes = Abc_NtkIf( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "FPGA mapping has failed.\n" ); + return 0; + } + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( pPars->DelayTarget == -1 ) + sprintf( Buffer, "best possible" ); + else + sprintf( Buffer, "%.2f", pPars->DelayTarget ); + if ( pPars->nLutSize == -1 ) + sprintf( LutSize, "library" ); + else + sprintf( LutSize, "%d", pPars->nLutSize ); + fprintf( pErr, "usage: if [-K num] [-C num] [-F num] [-A num] [-D float] [-pafrsvh]\n" ); + fprintf( pErr, "\t performs FPGA technology mapping of the network\n" ); + fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); + fprintf( pErr, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); + fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters ); + fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters ); + fprintf( pErr, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); + fprintf( pErr, "\t-p : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); + fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); +// fprintf( pErr, "\t-f : toggles one fancy feature [default = %s]\n", pPars->fFancy? "yes": "no" ); + fprintf( pErr, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); + fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" ); + fprintf( pErr, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" ); +// fprintf( pErr, "\t-t : toggles the use of true sequential cuts [default = %s]\n", pPars->fLiftLeaves? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : prints the command usage\n"); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandInit( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj; + int c, i; + int fZeros; + int fOnes; + int fRandom; + int fDontCare; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fZeros = 0; + fOnes = 0; + fRandom = 0; + fDontCare = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "zordh" ) ) != EOF ) + { + switch ( c ) + { + case 'z': + fZeros ^= 1; + break; + case 'o': + fOnes ^= 1; + break; + case 'r': + fRandom ^= 1; + break; + case 'd': + fDontCare ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The current network is combinational.\n" ); + return 0; + } + + if ( fZeros ) + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_LatchSetInit0( pObj ); + } + else if ( fOnes ) + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_LatchSetInit1( pObj ); + } + else if ( fRandom ) + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( rand() & 1 ) + Abc_LatchSetInit1( pObj ); + else + Abc_LatchSetInit0( pObj ); + } + else if ( fDontCare ) + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_LatchSetInitDc( pObj ); + } + else + printf( "The initial states remain unchanged.\n" ); + return 0; + +usage: + fprintf( pErr, "usage: init [-zordh]\n" ); + fprintf( pErr, "\t resets initial states of all latches\n" ); + fprintf( pErr, "\t-z : set zeros initial states [default = %s]\n", fZeros? "yes": "no" ); + fprintf( pErr, "\t-o : set ones initial states [default = %s]\n", fOnes? "yes": "no" ); + fprintf( pErr, "\t-d : set don't-care initial states [default = %s]\n", fDontCare? "yes": "no" ); + fprintf( pErr, "\t-r : set random initial states [default = %s]\n", fRandom? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandZero( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + extern Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, bool fCleanup ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The current network is combinational.\n" ); + return 0; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command works only for AIGs.\n" ); + return 0; + } + + // get the new network + pNtkRes = Abc_NtkRestrashZero( pNtk, 0 ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Converting to sequential AIG has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: zero [-h]\n" ); + fprintf( pErr, "\t converts latches to have const-0 initial value\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandUndc( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The current network is combinational.\n" ); + return 0; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "This command works only for logic networks.\n" ); + return 0; + } + + // get the new network + Abc_NtkConvertDcLatches( pNtk ); + return 0; + +usage: + fprintf( pErr, "usage: undc [-h]\n" ); + fprintf( pErr, "\t converts latches with DC init values into free PIs\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPipe( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nLatches; + extern void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nLatches = 5; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Lh" ) ) != EOF ) + { + switch ( c ) + { + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by a positive integer.\n" ); + goto usage; + } + nLatches = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLatches < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The current network is combinational.\n" ); + return 1; + } + + // update the network + Abc_NtkLatchPipe( pNtk, nLatches ); + return 0; + +usage: + fprintf( pErr, "usage: pipe [-L num] [-h]\n" ); + fprintf( pErr, "\t inserts the given number of latches at each PI for pipelining\n" ); + fprintf( pErr, "\t-L num : the number of latches to insert [default = %d]\n", nLatches ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + fprintf( pErr, "The network has no latches.\n" ); + return 0; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Conversion to sequential AIG works only for combinational AIGs (run \"strash\").\n" ); + return 1; + } + + // get the new network +// pNtkRes = Abc_NtkAigToSeq( pNtk ); + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Converting to sequential AIG has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: seq [-h]\n" ); + fprintf( pErr, "\t converts AIG into sequential AIG\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandUnseq( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fShare; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fShare = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fShare ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } +/* + if ( !Abc_NtkIsSeq(pNtk) ) + { + fprintf( pErr, "Conversion to combinational AIG works only for sequential AIG (run \"seq\").\n" ); + return 1; + } +*/ + // share the latches on the fanout edges +// if ( fShare ) +// Seq_NtkShareFanouts(pNtk); + + // get the new network +// pNtkRes = Abc_NtkSeqToLogicSop( pNtk ); + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Converting sequential AIG into an SOP logic network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: unseq [-sh]\n" ); + fprintf( pErr, "\t converts sequential AIG into an SOP logic network\n" ); + fprintf( pErr, "\t-s : toggle sharing latches [default = %s]\n", fShare? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nMaxIters; + int fForward; + int fBackward; + int fOneStep; + int fVerbose; + int Mode; + extern int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Mode = 5; + fForward = 0; + fBackward = 0; + fOneStep = 0; + fVerbose = 0; + nMaxIters = 15; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Mfbsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'M': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-M\" should be followed by a positive integer.\n" ); + goto usage; + } + Mode = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Mode < 0 ) + goto usage; + break; + case 'f': + fForward ^= 1; + break; + case 'b': + fBackward ^= 1; + break; + case 's': + fOneStep ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( fForward && fBackward ) + { + fprintf( pErr, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" ); + return 1; + } + + if ( !Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "The network has no latches. Retiming is not performed.\n" ); + return 0; + } + + if ( Mode < 0 || Mode > 6 ) + { + fprintf( pErr, "The mode (%d) is incorrect. Retiming is not performed.\n", Mode ); + return 0; + } + + if ( Abc_NtkIsStrash(pNtk) ) + { + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "Retiming with choice nodes is not implemented.\n" ); + return 0; + } + // convert the network into an SOP network + pNtkRes = Abc_NtkToLogic( pNtk ); + // perform the retiming + Abc_NtkRetime( pNtkRes, Mode, fForward, fBackward, fOneStep, fVerbose ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + } + + // get the network in the SOP form + if ( !Abc_NtkToSop(pNtk, 0) ) + { + printf( "Converting to SOPs has failed.\n" ); + return 0; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "The network is not a logic network. Retiming is not performed.\n" ); + return 0; + } + + // perform the retiming + Abc_NtkRetime( pNtk, Mode, fForward, fBackward, fOneStep, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: retime [-M num] [-fbvh]\n" ); + fprintf( pErr, "\t retimes the current network using one of the algorithms:\n" ); + fprintf( pErr, "\t 1: most forward retiming\n" ); + fprintf( pErr, "\t 2: most backward retiming\n" ); + fprintf( pErr, "\t 3: forward and backward min-area retiming\n" ); + fprintf( pErr, "\t 4: forward and backward min-delay retiming\n" ); + fprintf( pErr, "\t 5: mode 3 followed by mode 4\n" ); + fprintf( pErr, "\t 6: Pan's optimum-delay retiming using binary search\n" ); + fprintf( pErr, "\t-M num : the retiming algorithm to use [default = %d]\n", Mode ); + fprintf( pErr, "\t-f : enables forward-only retiming in modes 3,4,5 [default = %s]\n", fForward? "yes": "no" ); + fprintf( pErr, "\t-b : enables backward-only retiming in modes 3,4,5 [default = %s]\n", fBackward? "yes": "no" ); + fprintf( pErr, "\t-s : enables retiming one step only in mode 4 [default = %s]\n", fOneStep? "yes": "no" ); + fprintf( pErr, "\t-v : enables verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +// fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); +// fprintf( pErr, "\t-f : toggle forward retiming (for AIGs) [default = %s]\n", fForward? "yes": "no" ); +// fprintf( pErr, "\t-b : toggle backward retiming (for AIGs) [default = %s]\n", fBackward? "yes": "no" ); +// fprintf( pErr, "\t-i : toggle computation of initial state [default = %s]\n", fInitial? "yes": "no" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; + int c, nMaxIters; + int fVerbose; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nMaxIters = 15; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nMaxIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxIters < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkHasAig(pNtk) ) + { +/* + // quit if there are choice nodes + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "Currently cannot map/retime networks with choice nodes.\n" ); + return 0; + } +*/ +// if ( Abc_NtkIsStrash(pNtk) ) +// pNtkNew = Abc_NtkAigToSeq(pNtk); +// else +// pNtkNew = Abc_NtkDup(pNtk); + pNtkNew = NULL; + } + else + { + // strash and balance the network + pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Strashing before FPGA mapping/retiming has failed.\n" ); + return 1; + } + + pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); + return 1; + } + + // convert into a sequential AIG +// pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew ); + pNtkNew = NULL; + Abc_NtkDelete( pNtkRes ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Converting into a seq AIG before FPGA mapping/retiming has failed.\n" ); + return 1; + } + + fprintf( pOut, "The network was strashed and balanced before FPGA mapping/retiming.\n" ); + } + + // get the new network +// pNtkRes = Seq_NtkFpgaMapRetime( pNtkNew, nMaxIters, fVerbose ); + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { +// fprintf( pErr, "Sequential FPGA mapping has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return 0; + } + Abc_NtkDelete( pNtkNew ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: sfpga [-I num] [-vh]\n" ); + fprintf( pErr, "\t performs integrated sequential FPGA mapping/retiming\n" ); + fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; + int c, nMaxIters; + int fVerbose; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nMaxIters = 15; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nMaxIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxIters < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkHasAig(pNtk) ) + { +/* + // quit if there are choice nodes + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + fprintf( pErr, "Currently cannot map/retime networks with choice nodes.\n" ); + return 0; + } +*/ +// if ( Abc_NtkIsStrash(pNtk) ) +// pNtkNew = Abc_NtkAigToSeq(pNtk); +// else +// pNtkNew = Abc_NtkDup(pNtk); + pNtkNew = NULL; + } + else + { + // strash and balance the network + pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Strashing before SC mapping/retiming has failed.\n" ); + return 1; + } + + pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Balancing before SC mapping/retiming has failed.\n" ); + return 1; + } + + // convert into a sequential AIG +// pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew ); + pNtkNew = NULL; + Abc_NtkDelete( pNtkRes ); + if ( pNtkNew == NULL ) + { + fprintf( pErr, "Converting into a seq AIG before SC mapping/retiming has failed.\n" ); + return 1; + } + + fprintf( pOut, "The network was strashed and balanced before SC mapping/retiming.\n" ); + } + + // get the new network +// pNtkRes = Seq_MapRetime( pNtkNew, nMaxIters, fVerbose ); + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { +// fprintf( pErr, "Sequential FPGA mapping has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return 0; + } + Abc_NtkDelete( pNtkNew ); + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: smap [-I num] [-vh]\n" ); + fprintf( pErr, "\t performs integrated sequential standard-cell mapping/retiming\n" ); + fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nFramesP; + int nFramesK; + int nMaxImps; + int fUseImps; + int fRewrite; + int fLatchCorr; + int fWriteImps; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFrames, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFramesP = 0; + nFramesK = 1; + nMaxImps = 5000; + fUseImps = 0; + fRewrite = 0; + fLatchCorr = 0; + fWriteImps = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "PFIirlevh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nFramesP = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFramesP < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFramesK = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFramesK <= 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nMaxImps = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxImps <= 0 ) + goto usage; + break; + case 'i': + fUseImps ^= 1; + break; + case 'r': + fRewrite ^= 1; + break; + case 'l': + fLatchCorr ^= 1; + break; + case 'e': + fWriteImps ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); + return 0; + } + + // get the new network + pNtkRes = Abc_NtkDarSeqSweep( pNtk, nFramesP, nFramesK, nMaxImps, fRewrite, fUseImps, fLatchCorr, fWriteImps, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Sequential sweeping has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: ssweep [-P num] [-F num] [-I num] [-ilrevh]\n" ); + fprintf( pErr, "\t performs sequential sweep using K-step induction\n" ); + fprintf( pErr, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP ); + fprintf( pErr, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", nFramesK ); + fprintf( pErr, "\t-I num : max number of implications to consider [default = %d]\n", nMaxImps ); + fprintf( pErr, "\t-i : toggle using implications [default = %s]\n", fUseImps? "yes": "no" ); + fprintf( pErr, "\t-l : toggle latch correspondence only [default = %s]\n", fLatchCorr? "yes": "no" ); + fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", fRewrite? "yes": "no" ); + fprintf( pErr, "\t-e : toggle writing implications as assertions [default = %s]\n", fWriteImps? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nFramesP; + int nConfMax; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFramesP = 0; + nConfMax = 10000; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "PCvh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nFramesP = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFramesP < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfMax < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkIsComb(pNtk) ) + { + fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); + return 0; + } + + // get the new network + pNtkRes = Abc_NtkDarLcorr( pNtk, nFramesP, nConfMax, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Sequential sweeping has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: lcorr [-P num] [-C num] [-vh]\n" ); + fprintf( pErr, "\t computes latch correspondence using 1-step induction\n" ); + fprintf( pErr, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP ); + fprintf( pErr, "\t-C num : max conflict number when proving latch equivalence [default = %d]\n", nConfMax ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fLatchSweep; + int fAutoSweep; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fLatchSweep = 0; + fAutoSweep = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lavh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fLatchSweep ^= 1; + break; + case 'a': + fAutoSweep ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Only works for structrally hashed networks.\n" ); + return 1; + } + if ( !Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "Only works for sequential networks.\n" ); + return 1; + } + // modify the current network + pNtkRes = Abc_NtkDarLatchSweep( pNtk, fLatchSweep, fVerbose ); + if ( pNtkRes == NULL ) + { + fprintf( pErr, "Sequential cleanup has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + fprintf( pErr, "usage: scleanup [-lvh]\n" ); + fprintf( pErr, "\t performs sequential cleanup\n" ); + fprintf( pErr, "\t - removes nodes/latches that do not feed into POs\n" ); + fprintf( pErr, "\t - removes stuck-at and identical latches (latch sweep)\n" ); +// fprintf( pErr, "\t - replaces autonomous logic by free PI variables\n" ); + fprintf( pErr, "\t (the latter may change sequential behaviour)\n" ); + fprintf( pErr, "\t-l : toggle sweeping latches [default = %s]\n", fLatchSweep? "yes": "no" ); +// fprintf( pErr, "\t-a : toggle removing autonomous logic [default = %s]\n", fAutoSweep? "yes": "no" ); + fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCycle( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nFrames; + int fVerbose; + extern void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); + extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames = 100; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSopLogic(pNtk) ) + { + fprintf( pErr, "Only works for strashed networks or logic SOP networks.\n" ); + return 1; + } + if ( !Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "Only works for sequential networks.\n" ); + return 1; + } + + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkCycleInitState( pNtk, nFrames, fVerbose ); + else + Abc_NtkCycleInitStateSop( pNtk, nFrames, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: cycle [-F num] [-vh]\n" ); + fprintf( pErr, "\t cycles sequiential circuit for the given number of timeframes\n" ); + fprintf( pErr, "\t to derive a new initial state (which may be on the envelope)\n" ); + fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandXsim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int nFrames; + int fXInputs; + int fXState; + int fVerbose; + extern void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames = 10; + fXInputs = 0; + fXState = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Fisvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'i': + fXInputs ^= 1; + break; + case 's': + fXState ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "Only works for strashed networks.\n" ); + return 1; + } + if ( !Abc_NtkLatchNum(pNtk) ) + { + fprintf( pErr, "Only works for sequential networks.\n" ); + return 1; + } + Abc_NtkXValueSimulate( pNtk, nFrames, fXInputs, fXState, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: xsim [-F num] [-isvh]\n" ); + fprintf( pErr, "\t performs X-valued simulation of the AIG\n" ); + fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); + fprintf( pErr, "\t-i : toggle X-valued representation of inputs [default = %s]\n", fXInputs? "yes": "no" ); + fprintf( pErr, "\t-s : toggle X-valued representation of state [default = %s]\n", fXState? "yes": "no" ); + fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[16]; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fSat; + int fVerbose; + int nSeconds; + int nPartSize; + int nConfLimit; + int nInsLimit; + int fPartition; + + extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ); + extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); + extern void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose ); + extern void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fSat = 0; + fVerbose = 0; + nSeconds = 20; + nPartSize = 0; + nConfLimit = 10000; + nInsLimit = 0; + fPartition = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "TCIPpsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'T': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nSeconds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSeconds < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nInsLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInsLimit < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPartSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPartSize < 0 ) + goto usage; + break; + case 'p': + fPartition ^= 1; + break; + case 's': + fSat ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + + // perform equivalence checking + if ( fPartition ) + Abc_NtkCecFraigPartAuto( pNtk1, pNtk2, nSeconds, fVerbose ); + else if ( nPartSize ) + Abc_NtkCecFraigPart( pNtk1, pNtk2, nSeconds, nPartSize, fVerbose ); + else if ( fSat ) + Abc_NtkCecSat( pNtk1, pNtk2, nConfLimit, nInsLimit ); + else + Abc_NtkCecFraig( pNtk1, pNtk2, nSeconds, fVerbose ); + + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + return 0; + +usage: + if ( nPartSize == 0 ) + strcpy( Buffer, "unused" ); + else + sprintf( Buffer, "%d", nPartSize ); + fprintf( pErr, "usage: cec [-T num] [-C num] [-I num] [-P num] [-psvh] \n" ); + fprintf( pErr, "\t performs combinational equivalence checking\n" ); + fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of clause inspections [default = %d]\n", nInsLimit ); + fprintf( pErr, "\t-P num : partition size for multi-output networks [default = %s]\n", Buffer ); + fprintf( pErr, "\t-p : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" ); + fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); + fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); + fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fRetime; + int fSat; + int fVerbose; + int nFrames; + int nSeconds; + int nConfLimit; + int nInsLimit; + + extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames ); + extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ); + extern void Abc_NtkSecRetime( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); + + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fRetime = 0; // verification after retiming + fSat = 0; + fVerbose = 0; + nFrames = 5; + nSeconds = 20; + nConfLimit = 10000; + nInsLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "FTCIsrvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames <= 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nSeconds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSeconds < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nInsLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInsLimit < 0 ) + goto usage; + break; + case 'r': + fRetime ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 's': + fSat ^= 1; + break; + default: + goto usage; + } + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + + if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) + { + printf( "The network has no latches. Used combinational command \"cec\".\n" ); + return 0; + } + + // perform equivalence checking + if ( fRetime ) + Abc_NtkSecRetime( pNtk1, pNtk2 ); + else if ( fSat ) + Abc_NtkSecSat( pNtk1, pNtk2, nConfLimit, nInsLimit, nFrames ); + else + Abc_NtkSecFraig( pNtk1, pNtk2, nSeconds, nFrames, fVerbose ); + + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + return 0; + +usage: + fprintf( pErr, "usage: sec [-F num] [-T num] [-C num] [-I num] [-srvh] \n" ); + fprintf( pErr, "\t performs bounded sequential equivalence checking\n" ); + fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" ); + fprintf( pErr, "\t-r : toggles retiming verification [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t-F num : the number of time frames to use [default = %d]\n", nFrames ); + fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit ); + fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); + fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); + fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fRetimeFirst; + int fVerbose; + int fVeryVerbose; + int nFrames; + + extern int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames =16; + fRetimeFirst = 1; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Krwvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'r': + fRetimeFirst ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) + return 1; + + if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) + { + printf( "The network has no latches. Used combinational command \"cec\".\n" ); + return 0; + } + + // perform verification + Abc_NtkDarSec( pNtk1, pNtk2, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); + + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + return 0; + +usage: + fprintf( pErr, "usage: dsec [-K num] [-rwvh] \n" ); + fprintf( pErr, "\t performs inductive sequential equivalence checking\n" ); + fprintf( pErr, "\t-K num : the limit on the depth of induction [default = %d]\n", nFrames ); + fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", fRetimeFirst? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); + fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); + fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); + fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int fRetimeFirst; + int fVerbose; + int fVeryVerbose; + int nFrames; + + extern int Abc_NtkDarProve( Abc_Ntk_t * pNtk, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + nFrames = 16; + fRetimeFirst = 1; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Krwvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'r': + fRetimeFirst ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + printf( "The network has no latches. Used combinational command \"iprove\".\n" ); + return 0; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); + return 0; + } + + // perform verification + Abc_NtkDarProve( pNtk, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: dprove [-K num] [-rwvh]\n" ); + fprintf( pErr, "\t performs SEC on the sequential miter\n" ); + fprintf( pErr, "\t-K num : the limit on the depth of induction [default = %d]\n", nFrames ); + fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", fRetimeFirst? "yes": "no" ); + fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", fVeryVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int RetValue; + int fVerbose; + int nConfLimit; + int nInsLimit; + int clk; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + nConfLimit = 100000; + nInsLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nInsLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInsLimit < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" ); + return 0; + } + + clk = clock(); + if ( Abc_NtkIsStrash(pNtk) ) + { + RetValue = Abc_NtkMiterSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose, NULL, NULL ); + } + else + { + assert( Abc_NtkIsLogic(pNtk) ); + Abc_NtkToBdd( pNtk ); + RetValue = Abc_NtkMiterSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose, NULL, NULL ); + } + + // verify that the pattern is correct + if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 ) + { + //int i; + //Abc_Obj_t * pObj; + int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" ); + free( pSimInfo ); + /* + // print model + Abc_NtkForEachPi( pNtk, pObj, i ) + { + printf( "%d", (int)(pNtk->pModel[i] > 0) ); + if ( i == 70 ) + break; + } + printf( "\n" ); + */ + } + + if ( RetValue == -1 ) + printf( "UNDECIDED " ); + else if ( RetValue == 0 ) + printf( "SATISFIABLE " ); + else + printf( "UNSATISFIABLE " ); + //printf( "\n" ); + PRT( "Time", clock() - clk ); + return 0; + +usage: + fprintf( pErr, "usage: sat [-C num] [-I num] [-vh]\n" ); + fprintf( pErr, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" ); + fprintf( pErr, "\t derives CNF from the current network and leave it unchanged\n" ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDSat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + int RetValue; + int fVerbose; + int nConfLimit; + int nInsLimit; + int clk; + + extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ); + + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fVerbose = 0; + nConfLimit = 100000; + nInsLimit = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nInsLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInsLimit < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" ); + return 0; + } + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( stdout, "Currently expects a single-output miter.\n" ); + return 0; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); + return 0; + } + + clk = clock(); + RetValue = Abc_NtkDSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose ); + // verify that the pattern is correct + if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 ) + { + //int i; + //Abc_Obj_t * pObj; + int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" ); + free( pSimInfo ); + /* + // print model + Abc_NtkForEachPi( pNtk, pObj, i ) + { + printf( "%d", (int)(pNtk->pModel[i] > 0) ); + if ( i == 70 ) + break; + } + printf( "\n" ); + */ + } + + if ( RetValue == -1 ) + printf( "UNDECIDED " ); + else if ( RetValue == 0 ) + printf( "SATISFIABLE " ); + else + printf( "UNSATISFIABLE " ); + //printf( "\n" ); + PRT( "Time", clock() - clk ); + return 0; + +usage: + fprintf( pErr, "usage: dsat [-C num] [-I num] [-vh]\n" ); + fprintf( pErr, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" ); + fprintf( pErr, "\t derives CNF from the current network and leave it unchanged\n" ); + fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkTemp; + Prove_Params_t Params, * pParams = &Params; + int c, clk, RetValue; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Prove_ParamsSetDefault( pParams ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NCFLIrfbvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nItersMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nItersMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nMiteringLimitStart = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nMiteringLimitStart < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nFraigingLimitStart = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nFraigingLimitStart < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nMiteringLimitLast < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nTotalInspectLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nTotalInspectLimit < 0 ) + goto usage; + break; + case 'r': + pParams->fUseRewriting ^= 1; + break; + case 'f': + pParams->fUseFraiging ^= 1; + break; + case 'b': + pParams->fUseBdds ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" ); + return 0; + } + if ( Abc_NtkCoNum(pNtk) != 1 ) + { + fprintf( stdout, "Currently can only solve the miter with one output.\n" ); + return 0; + } + clk = clock(); + + if ( Abc_NtkIsStrash(pNtk) ) + pNtkTemp = Abc_NtkDup( pNtk ); + else + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + + RetValue = Abc_NtkMiterProve( &pNtkTemp, pParams ); + + // verify that the pattern is correct + if ( RetValue == 0 ) + { + int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); + free( pSimInfo ); + } + + if ( RetValue == -1 ) + printf( "UNDECIDED " ); + else if ( RetValue == 0 ) + printf( "SATISFIABLE " ); + else + printf( "UNSATISFIABLE " ); + //printf( "\n" ); + + PRT( "Time", clock() - clk ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp ); + return 0; + +usage: + fprintf( pErr, "usage: prove [-N num] [-C num] [-F num] [-L num] [-I num] [-rfbvh]\n" ); + fprintf( pErr, "\t solves combinational miter by rewriting, FRAIGing, and SAT\n" ); + fprintf( pErr, "\t replaces the current network by the cone modified by rewriting\n" ); + fprintf( pErr, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax ); + fprintf( pErr, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart ); + fprintf( pErr, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart ); + fprintf( pErr, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast ); + fprintf( pErr, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit ); + fprintf( pErr, "\t-r : toggle the use of rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" ); + fprintf( pErr, "\t-f : toggle the use of FRAIGing [default = %s]\n", pParams->fUseFraiging? "yes": "no" ); + fprintf( pErr, "\t-b : toggle the use of BDDs [default = %s]\n", pParams->fUseBdds? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDebug( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + extern void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) ); + extern int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pErr, "This command is applicable to logic networks.\n" ); + return 1; + } + + Abc_NtkAutoDebug( pNtk, Abc_NtkRetimeDebug ); + return 0; + +usage: + fprintf( pErr, "usage: debug [-h]\n" ); + fprintf( pErr, "\t performs automated debugging of the given procedure\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTraceStart( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command is applicable to AIGs.\n" ); + return 1; + } +/* + Abc_HManStart(); + if ( !Abc_HManPopulate( pNtk ) ) + { + fprintf( pErr, "Failed to start the tracing database.\n" ); + return 1; + } +*/ + return 0; + +usage: + fprintf( pErr, "usage: trace_start [-h]\n" ); + fprintf( pErr, "\t starts verification tracing\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTraceCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( pErr, "This command is applicable to AIGs.\n" ); + return 1; + } +/* + if ( !Abc_HManIsRunning(pNtk) ) + { + fprintf( pErr, "The tracing database is not available.\n" ); + return 1; + } + + if ( !Abc_HManVerify( 1, pNtk->Id ) ) + fprintf( pErr, "Verification failed.\n" ); + Abc_HManStop(); +*/ + return 0; + +usage: + fprintf( pErr, "usage: trace_check [-h]\n" ); + fprintf( pErr, "\t checks the current network using verification trace\n" ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcAttach.c b/abc70930/src/base/abci/abcAttach.c new file mode 100644 index 00000000..d5d2aa16 --- /dev/null +++ b/abc70930/src/base/abci/abcAttach.c @@ -0,0 +1,404 @@ +/**CFile**************************************************************** + + FileName [abcAttach.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Attaches the library gates to the current network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcAttach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ATTACH_FULL (~((unsigned)0)) +#define ATTACH_MASK(n) ((~((unsigned)0)) >> (32-(n))) + +static void Abc_AttachSetupTruthTables( unsigned uTruths[][2] ); +static void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthNode ); +static Mio_Gate_t * Abc_AttachFind( Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned * uTruthNode, int * Perm ); +static int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode ); +static int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] ); +static void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm ); + +static char ** s_pPerms = NULL; +static int s_nPerms; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Attaches gates from the current library to the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkAttach( Abc_Ntk_t * pNtk ) +{ + Mio_Library_t * pGenlib; + unsigned ** puTruthGates; + unsigned uTruths[6][2]; + Abc_Obj_t * pNode; + Mio_Gate_t ** ppGates; + int nGates, nFanins, i; + + assert( Abc_NtkIsSopLogic(pNtk) ); + + // check that the library is available + pGenlib = Abc_FrameReadLibGen(); + if ( pGenlib == NULL ) + { + printf( "The current library is not available.\n" ); + return 0; + } + + // start the truth tables + Abc_AttachSetupTruthTables( uTruths ); + + // collect all the gates + ppGates = Mio_CollectRoots( pGenlib, 6, (float)1.0e+20, 1, &nGates ); + + // derive the gate truth tables + puTruthGates = ALLOC( unsigned *, nGates ); + puTruthGates[0] = ALLOC( unsigned, 2 * nGates ); + for ( i = 1; i < nGates; i++ ) + puTruthGates[i] = puTruthGates[i-1] + 2; + for ( i = 0; i < nGates; i++ ) + Mio_DeriveTruthTable( ppGates[i], uTruths, Mio_GateReadInputs(ppGates[i]), 6, puTruthGates[i] ); + + // assign the gates to pNode->pCopy + Abc_NtkCleanCopy( pNtk ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + nFanins = Abc_ObjFaninNum(pNode); + if ( nFanins == 0 ) + { + if ( Abc_SopIsConst1(pNode->pData) ) + pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst1(pGenlib); + else + pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst0(pGenlib); + } + else if ( nFanins == 1 ) + { + if ( Abc_SopIsBuf(pNode->pData) ) + pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadBuf(pGenlib); + else + pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadInv(pGenlib); + } + else if ( nFanins > 6 ) + { + printf( "Cannot attach gate with more than 6 inputs to node %s.\n", Abc_ObjName(pNode) ); + free( puTruthGates[0] ); + free( puTruthGates ); + free( ppGates ); + return 0; + } + else if ( !Abc_NodeAttach( pNode, ppGates, puTruthGates, nGates, uTruths ) ) + { + printf( "Could not attach the library gate to node %s.\n", Abc_ObjName(pNode) ); + free( puTruthGates[0] ); + free( puTruthGates ); + free( ppGates ); + return 0; + } + } + free( puTruthGates[0] ); + free( puTruthGates ); + free( ppGates ); + FREE( s_pPerms ); + + // perform the final transformation + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( pNode->pCopy == NULL ) + { + printf( "Some elementary gates (constant, buffer, or inverter) are missing in the library.\n" ); + return 0; + } + } + + // replace SOP representation by the gate representation + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->pData = pNode->pCopy, pNode->pCopy = NULL; + pNtk->ntkFunc = ABC_FUNC_MAP; + Extra_MmFlexStop( pNtk->pManFunc ); + pNtk->pManFunc = pGenlib; + + printf( "Library gates are successfully attached to the nodes.\n" ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkAttach: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] ) +{ + int Perm[10]; + int pTempInts[10]; + unsigned uTruthNode[2]; + Abc_Obj_t * pFanin; + Mio_Gate_t * pGate; + int nFanins, i; + + // compute the node's truth table + Abc_AttachComputeTruth( pNode->pData, uTruths, uTruthNode ); + // find the matching gate and permutation + pGate = Abc_AttachFind( ppGates, puTruthGates, nGates, uTruthNode, Perm ); + if ( pGate == NULL ) + return 0; + // permute the fanins + nFanins = Abc_ObjFaninNum(pNode); + Abc_ObjForEachFanin( pNode, pFanin, i ) + pTempInts[i] = pFanin->Id; + for ( i = 0; i < nFanins; i++ ) + pNode->vFanins.pArray[Perm[i]] = pTempInts[i]; + // set the gate + pNode->pCopy = (Abc_Obj_t *)pGate; + return 1; +} + +/**Function************************************************************* + + Synopsis [Sets up the truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AttachSetupTruthTables( unsigned uTruths[][2] ) +{ + int m, v; + for ( v = 0; v < 5; v++ ) + uTruths[v][0] = 0; + // set up the truth tables + for ( m = 0; m < 32; m++ ) + for ( v = 0; v < 5; v++ ) + if ( m & (1 << v) ) + uTruths[v][0] |= (1 << m); + // make adjustments for the case of 6 variables + for ( v = 0; v < 5; v++ ) + uTruths[v][1] = uTruths[v][0]; + uTruths[5][0] = 0; + uTruths[5][1] = ATTACH_FULL; +} + +/**Function************************************************************* + + Synopsis [Compute the truth table of the node's cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthRes ) +{ +// Mvc_Cube_t * pCube; + unsigned uSignCube[2]; + int Value; +// int nInputs = pCover->nBits/2; + int nInputs = 6; + int nFanins = Abc_SopGetVarNum(pSop); + char * pCube; + int k; + + // make sure that the number of input truth tables in equal to the number of gate inputs + assert( nInputs < 7 ); + + // clean the resulting truth table + uTruthRes[0] = 0; + uTruthRes[1] = 0; + if ( nInputs < 6 ) + { + // consider the case when only one unsigned can be used +// Mvc_CoverForEachCube( pCover, pCube ) + Abc_SopForEachCube( pSop, nFanins, pCube ) + { + uSignCube[0] = ATTACH_FULL; +// Mvc_CubeForEachVarValue( pCover, pCube, Var, Value ) + Abc_CubeForEachVar( pCube, Value, k ) + { + if ( Value == '0' ) + uSignCube[0] &= ~uTruthsIn[k][0]; + else if ( Value == '1' ) + uSignCube[0] &= uTruthsIn[k][0]; + } + uTruthRes[0] |= uSignCube[0]; + } + if ( Abc_SopGetPhase(pSop) == 0 ) + uTruthRes[0] = ~uTruthRes[0]; + if ( nInputs < 5 ) + uTruthRes[0] &= ATTACH_MASK(1<= 0 ) + { + for ( v = 0; v < 6; v++ ) + Perm[v] = v; + return ppGates[iNum]; + } + // get permutations + if ( s_pPerms == NULL ) + { + s_pPerms = Extra_Permutations( 6 ); + s_nPerms = Extra_Factorial( 6 ); + } + // try permutations + for ( i = 0; i < s_nPerms; i++ ) + { + Abc_TruthPermute( s_pPerms[i], 6, uTruthNode, uTruthPerm ); + if ( (iNum = Abc_AttachCompare( puTruthGates, nGates, uTruthPerm )) >= 0 ) + { + for ( v = 0; v < 6; v++ ) + Perm[v] = (int)s_pPerms[i][v]; + return ppGates[iNum]; + } + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Find the gate by truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode ) +{ + int i; + for ( i = 0; i < nGates; i++ ) + if ( puTruthGates[i][0] == uTruthNode[0] && puTruthGates[i][1] == uTruthNode[1] ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Permutes the 6-input truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm ) +{ + int nMints, iMintPerm, iMint, v; + uTruthPerm[0] = uTruthPerm[1] = 0; + nMints = (1 << nVars); + for ( iMint = 0; iMint < nMints; iMint++ ) + { + if ( (uTruthNode[iMint>>5] & (1 << (iMint&31))) == 0 ) + continue; + iMintPerm = 0; + for ( v = 0; v < nVars; v++ ) + if ( iMint & (1 << v) ) + iMintPerm |= (1 << pPerm[v]); + uTruthPerm[iMintPerm>>5] |= (1 << (iMintPerm&31)); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcAuto.c b/abc70930/src/base/abci/abcAuto.c new file mode 100644 index 00000000..40212c17 --- /dev/null +++ b/abc70930/src/base/abci/abcAuto.c @@ -0,0 +1,239 @@ +/**CFile**************************************************************** + + FileName [abcAuto.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computation of autosymmetries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcAuto.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive ); +static void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ) +{ + DdManager * dd; // the BDD manager used to hold shared BDDs + DdNode ** pbGlobal; // temporary storage for global BDDs + char ** pInputNames; // pointers to the CI names + char ** pOutputNames; // pointers to the CO names + int nOutputs, nInputs, i; + Vec_Ptr_t * vFuncsGlob; + Abc_Obj_t * pObj; + + // compute the global BDDs + if ( Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose) == NULL ) + return; + + // get information about the network + nInputs = Abc_NtkCiNum(pNtk); + nOutputs = Abc_NtkCoNum(pNtk); +// dd = pNtk->pManGlob; + dd = Abc_NtkGlobalBddMan( pNtk ); + + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); + pbGlobal = (DdNode **)Vec_PtrArray( vFuncsGlob ); + + // get the network names + pInputNames = Abc_NtkCollectCioNames( pNtk, 0 ); + pOutputNames = Abc_NtkCollectCioNames( pNtk, 1 ); + + // print the size of the BDDs + if ( fVerbose ) + printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // allocate additional variables + for ( i = 0; i < nInputs; i++ ) + Cudd_bddNewVar( dd ); + assert( Cudd_ReadSize(dd) == 2 * nInputs ); + + // create ZDD variables in the manager + Cudd_zddVarsFromBddVars( dd, 2 ); + + // perform the analysis of the primary output functions for auto-symmetry + if ( Output == -1 ) + Abc_NtkAutoPrintAll( dd, nInputs, pbGlobal, nOutputs, pInputNames, pOutputNames, fNaive ); + else + Abc_NtkAutoPrintOne( dd, nInputs, pbGlobal, Output, pInputNames, pOutputNames, fNaive ); + + // deref the PO functions +// Abc_NtkFreeGlobalBdds( pNtk ); + // stop the global BDD manager +// Extra_StopManager( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; + Abc_NtkFreeGlobalBdds( pNtk, 1 ); + free( pInputNames ); + free( pOutputNames ); + Vec_PtrFree( vFuncsGlob ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive ) +{ + DdNode * bSpace1, * bSpace2, * bCanVars, * bReduced, * zEquations; + double nMints; + int nSupp, SigCounter, o; + + int nAutos; + int nAutoSyms; + int nAutoSymsMax; + int nAutoSymsMaxSupp; + int nAutoSymOuts; + int nSuppSizeMax; + int clk; + + nAutoSymOuts = 0; + nAutoSyms = 0; + nAutoSymsMax = 0; + nAutoSymsMaxSupp = 0; + nSuppSizeMax = 0; + clk = clock(); + + SigCounter = 0; + for ( o = 0; o < nOutputs; o++ ) + { +// bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[o] ); Cudd_Ref( bSpace1 ); + bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[o], pbOutputs[o] ); Cudd_Ref( bSpace1 ); + bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars ); + bReduced = Extra_bddSpaceReduce( dd, pbOutputs[o], bCanVars ); Cudd_Ref( bReduced ); + zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations ); + + nSupp = Cudd_SupportSize( dd, bSpace1 ); + nMints = Cudd_CountMinterm( dd, bSpace1, nSupp ); + nAutos = Extra_Base2LogDouble(nMints); + printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", o, nSupp, nAutos ); + + if ( nAutos > 0 ) + { + nAutoSymOuts++; + nAutoSyms += nAutos; + if ( nAutoSymsMax < nAutos ) + { + nAutoSymsMax = nAutos; + nAutoSymsMaxSupp = nSupp; + } + } + if ( nSuppSizeMax < nSupp ) + nSuppSizeMax = nSupp; + + +//PRB( dd, bCanVars ); +//PRB( dd, bReduced ); +//Cudd_PrintMinterm( dd, bReduced ); +//printf( "The equations are:\n" ); +//Cudd_zddPrintCover( dd, zEquations ); +//printf( "\n" ); +//fflush( stdout ); + + bSpace2 = Extra_bddSpaceFromMatrixPos( dd, zEquations ); Cudd_Ref( bSpace2 ); +//PRB( dd, bSpace1 ); +//PRB( dd, bSpace2 ); + if ( bSpace1 != bSpace2 ) + printf( "Spaces are NOT EQUAL!\n" ); +// else +// printf( "Spaces are equal.\n" ); + + Cudd_RecursiveDeref( dd, bSpace1 ); + Cudd_RecursiveDeref( dd, bSpace2 ); + Cudd_RecursiveDeref( dd, bCanVars ); + Cudd_RecursiveDeref( dd, bReduced ); + Cudd_RecursiveDerefZdd( dd, zEquations ); + } + + printf( "The cumulative statistics for all outputs:\n" ); + printf( "Ins=%3d ", nInputs ); + printf( "InMax=%3d ", nSuppSizeMax ); + printf( "Outs=%3d ", nOutputs ); + printf( "Auto=%3d ", nAutoSymOuts ); + printf( "SumK=%3d ", nAutoSyms ); + printf( "KMax=%2d ", nAutoSymsMax ); + printf( "Supp=%3d ", nAutoSymsMaxSupp ); + printf( "Time=%4.2f ", (float)(clock() - clk)/(float)(CLOCKS_PER_SEC) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive ) +{ + DdNode * bSpace1, * bCanVars, * bReduced, * zEquations; + double nMints; + int nSupp, SigCounter; + int nAutos; + + SigCounter = 0; + bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[Output] ); Cudd_Ref( bSpace1 ); +// bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[Output], pbOutputs[Output] ); Cudd_Ref( bSpace1 ); + bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars ); + bReduced = Extra_bddSpaceReduce( dd, pbOutputs[Output], bCanVars ); Cudd_Ref( bReduced ); + zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations ); + + nSupp = Cudd_SupportSize( dd, bSpace1 ); + nMints = Cudd_CountMinterm( dd, bSpace1, nSupp ); + nAutos = Extra_Base2LogDouble(nMints); + printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", Output, nSupp, nAutos ); + + Cudd_RecursiveDeref( dd, bSpace1 ); + Cudd_RecursiveDeref( dd, bCanVars ); + Cudd_RecursiveDeref( dd, bReduced ); + Cudd_RecursiveDerefZdd( dd, zEquations ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcBalance.c b/abc70930/src/base/abci/abcBalance.c new file mode 100644 index 00000000..f9b3384e --- /dev/null +++ b/abc70930/src/base/abci/abcBalance.c @@ -0,0 +1,613 @@ +/**CFile**************************************************************** + + FileName [abcBalance.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Performs global balancing of the AIG by the number of levels.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel ); +static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel ); +static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int Level, int fDuplicate, bool fSelective ); +static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective ); +static void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ); +static Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Balances the AIG network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel ) +{ + extern void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ); + Abc_Ntk_t * pNtkAig; + assert( Abc_NtkIsStrash(pNtk) ); + // compute the required times + if ( fSelective ) + { + Abc_NtkStartReverseLevels( pNtk, 0 ); + Abc_NtkMarkCriticalNodes( pNtk ); + } + // perform balancing + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer HAIG + Abc_NtkHaigTranfer( pNtk, pNtkAig ); + // perform balancing + Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate, fSelective, fUpdateLevel ); + Abc_NtkFinalize( pNtk, pNtkAig ); + // undo the required times + if ( fSelective ) + { + Abc_NtkStopReverseLevels( pNtk ); + Abc_NtkCleanMarkA( pNtk ); + } + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkBalance: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Balances the AIG network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel ) +{ + int fCheck = 1; + ProgressBar * pProgress; + Vec_Vec_t * vStorage; + Abc_Obj_t * pNode, * pDriver; + int i; + + // set the level of PIs of AIG according to the arrival times of the old network + Abc_NtkSetNodeLevelsArrival( pNtk ); + // allocate temporary storage for supergates + vStorage = Vec_VecStart( 10 ); + // perform balancing of POs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // strash the driver node + pDriver = Abc_ObjFanin0(pNode); + Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, 0, fDuplicate, fSelective, fUpdateLevel ); + } + Extra_ProgressBarStop( pProgress ); + Vec_VecFree( vStorage ); +} + +/**Function************************************************************* + + Synopsis [Finds the left bound on the next candidate to be paired.] + + Description [The nodes in the array are in the decreasing order of levels. + The last node in the array has the smallest level. By default it would be paired + with the next node on the left. However, it may be possible to pair it with some + other node on the left, in such a way that the new node is shared. This procedure + finds the index of the left-most node, which can be paired with the last node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) +{ + Abc_Obj_t * pNodeRight, * pNodeLeft; + int Current; + // if two or less nodes, pair with the first + if ( Vec_PtrSize(vSuper) < 3 ) + return 0; + // set the pointer to the one before the last + Current = Vec_PtrSize(vSuper) - 2; + pNodeRight = Vec_PtrEntry( vSuper, Current ); + // go through the nodes to the left of this one + for ( Current--; Current >= 0; Current-- ) + { + // get the next node on the left + pNodeLeft = Vec_PtrEntry( vSuper, Current ); + // if the level of this node is different, quit the loop + if ( Abc_ObjRegular(pNodeLeft)->Level != Abc_ObjRegular(pNodeRight)->Level ) + break; + } + Current++; + // get the node, for which the equality holds + pNodeLeft = Vec_PtrEntry( vSuper, Current ); + assert( Abc_ObjRegular(pNodeLeft)->Level == Abc_ObjRegular(pNodeRight)->Level ); + return Current; +} + +/**Function************************************************************* + + Synopsis [Moves closer to the end the node that is best for sharing.] + + Description [If there is no node with sharing, randomly chooses one of + the legal nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeBalancePermute( Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vSuper, int LeftBound ) +{ + Abc_Obj_t * pNode1, * pNode2, * pNode3; + int RightBound, i; + // get the right bound + RightBound = Vec_PtrSize(vSuper) - 2; + assert( LeftBound <= RightBound ); + if ( LeftBound == RightBound ) + return; + // get the two last nodes + pNode1 = Vec_PtrEntry( vSuper, RightBound + 1 ); + pNode2 = Vec_PtrEntry( vSuper, RightBound ); + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + pNode3 = Vec_PtrEntry( vSuper, i ); + if ( Abc_AigAndLookup( pNtkNew->pManFunc, pNode1, pNode3 ) ) + { + if ( pNode3 == pNode2 ) + return; + Vec_PtrWriteEntry( vSuper, i, pNode2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pNode3 ); + return; + } + } +/* + // we did not find the node to share, randomize choice + { + int Choice = rand() % (RightBound - LeftBound + 1); + pNode3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); + if ( pNode3 == pNode2 ) + return; + Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pNode2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pNode3 ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Rebalances the multi-input node rooted at pNodeOld.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel ) +{ + Abc_Aig_t * pMan = pNtkNew->pManFunc; + Abc_Obj_t * pNodeNew, * pNode1, * pNode2; + Vec_Ptr_t * vSuper; + int i, LeftBound; + assert( !Abc_ObjIsComplement(pNodeOld) ); + // return if the result if known + if ( pNodeOld->pCopy ) + return pNodeOld->pCopy; + assert( Abc_ObjIsNode(pNodeOld) ); + // get the implication supergate +// Abc_NodeBalanceConeExor( pNodeOld ); + vSuper = Abc_NodeBalanceCone( pNodeOld, vStorage, Level, fDuplicate, fSelective ); + if ( vSuper->nSize == 0 ) + { // it means that the supergate contains two nodes in the opposite polarity + pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pNtkNew)); + return pNodeOld->pCopy; + } + // for each old node, derive the new well-balanced node + for ( i = 0; i < vSuper->nSize; i++ ) + { + pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), vStorage, Level + 1, fDuplicate, fSelective, fUpdateLevel ); + vSuper->pArray[i] = Abc_ObjNotCond( pNodeNew, Abc_ObjIsComplement(vSuper->pArray[i]) ); + } + if ( vSuper->nSize < 2 ) + printf( "BUG!\n" ); + // sort the new nodes by level in the decreasing order + Vec_PtrSort( vSuper, Abc_NodeCompareLevelsDecrease ); + // balance the nodes + assert( vSuper->nSize > 1 ); + while ( vSuper->nSize > 1 ) + { + // find the left bound on the node to be paired + LeftBound = (!fUpdateLevel)? 0 : Abc_NodeBalanceFindLeft( vSuper ); + // find the node that can be shared (if no such node, randomize choice) + Abc_NodeBalancePermute( pNtkNew, vSuper, LeftBound ); + // pull out the last two nodes + pNode1 = Vec_PtrPop(vSuper); + pNode2 = Vec_PtrPop(vSuper); + Abc_VecObjPushUniqueOrderByLevel( vSuper, Abc_AigAnd(pMan, pNode1, pNode2) ); + } + // make sure the balanced node is not assigned + assert( pNodeOld->pCopy == NULL ); + // mark the old node with the new node + pNodeOld->pCopy = vSuper->pArray[0]; + vSuper->nSize = 0; +// if ( Abc_ObjRegular(pNodeOld->pCopy) == Abc_AigConst1(pNtkNew) ) +// printf( "Constant node\n" ); +// assert( pNodeOld->Level >= Abc_ObjRegular(pNodeOld->pCopy)->Level ); + // update HAIG + if ( Abc_ObjRegular(pNodeOld->pCopy)->pNtk->pHaig ) + Hop_ObjCreateChoice( pNodeOld->pEquiv, Abc_ObjRegular(pNodeOld->pCopy)->pEquiv ); + return pNodeOld->pCopy; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes in the cone delimited by fMarkA==1.] + + Description [Returns -1 if the AND-cone has the same node in both polarities. + Returns 1 if the AND-cone has the same node in the same polarity. Returns 0 + if the AND-cone has no repeated nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, int fDuplicate, bool fSelective ) +{ + Vec_Ptr_t * vNodes; + int RetValue, i; + assert( !Abc_ObjIsComplement(pNode) ); + // extend the storage + if ( Vec_VecSize( vStorage ) <= Level ) + Vec_VecPush( vStorage, Level, 0 ); + // get the temporary array of nodes + vNodes = Vec_VecEntry( vStorage, Level ); + Vec_PtrClear( vNodes ); + // collect the nodes in the implication supergate + RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate, fSelective ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Collects the nodes in the cone delimited by fMarkA==1.] + + Description [Returns -1 if the AND-cone has the same node in both polarities. + Returns 1 if the AND-cone has the same node in the same polarity. Returns 0 + if the AND-cone has no repeated nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Abc_ObjRegular(pNode)->fMarkB ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pNode ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Abc_ObjNot(pNode) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || !fDuplicate && !fSelective && (Abc_ObjFanoutNum(pNode) > 1)) ) + { + Vec_PtrPush( vSuper, pNode ); + Abc_ObjRegular(pNode)->fMarkB = 1; + return 0; + } + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + // go through the branches + RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate, fSelective ); + RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate, fSelective ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBalanceConeExor_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst ) +{ + int RetValue1, RetValue2, i; + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pNode ) + return 1; + // if the new node is complemented or a PI, another gate begins + if ( !fFirst && (!pNode->fExor || !Abc_ObjIsNode(pNode)) ) + { + Vec_PtrPush( vSuper, pNode ); + return 0; + } + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + assert( pNode->fExor ); + // go through the branches + RetValue1 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin0(Abc_ObjFanin0(pNode)), vSuper, 0 ); + RetValue2 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin1(Abc_ObjFanin0(pNode)), vSuper, 0 ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vSuper; + if ( !pNode->fExor ) + return NULL; + vSuper = Vec_PtrAlloc( 10 ); + Abc_NodeBalanceConeExor_rec( pNode, vSuper, 1 ); + printf( "%d ", Vec_PtrSize(vSuper) ); + Vec_PtrFree( vSuper ); + return NULL; +} + + + +/**Function************************************************************* + + Synopsis [Collects the nodes in the implication supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeFindCone_rec( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNodeC, * pNodeT, * pNodeE; + int RetValue, i; + assert( !Abc_ObjIsComplement(pNode) ); + if ( Abc_ObjIsCi(pNode) ) + return NULL; + // start the new array + vNodes = Vec_PtrAlloc( 4 ); + // if the node is the MUX collect its fanins + if ( Abc_NodeIsMuxType(pNode) ) + { + pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); + Vec_PtrPush( vNodes, Abc_ObjRegular(pNodeC) ); + Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeT) ); + Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeE) ); + } + else + { + // collect the nodes in the implication supergate + RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, 1, 0 ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + Abc_ObjRegular(pNode)->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; + } + // call for the fanin + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + pNode = Abc_ObjRegular(pNode); + if ( pNode->pCopy ) + continue; + pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Attaches the implication supergates to internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + Abc_NtkCleanCopy( pNtk ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pNode = Abc_ObjFanin0(pNode); + if ( pNode->pCopy ) + continue; + pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode ); + } +} + +/**Function************************************************************* + + Synopsis [Attaches the implication supergates to internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( pNode->pCopy ) + { + Vec_PtrFree( (Vec_Ptr_t *)pNode->pCopy ); + pNode->pCopy = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Compute levels of implication supergates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkBalanceLevel_rec( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vSuper; + Abc_Obj_t * pFanin; + int i, LevelMax; + assert( !Abc_ObjIsComplement(pNode) ); + if ( pNode->Level > 0 ) + return pNode->Level; + if ( Abc_ObjIsCi(pNode) ) + return 0; + vSuper = (Vec_Ptr_t *)pNode->pCopy; + assert( vSuper != NULL ); + LevelMax = 0; + Vec_PtrForEachEntry( vSuper, pFanin, i ) + { + pFanin = Abc_ObjRegular(pFanin); + Abc_NtkBalanceLevel_rec(pFanin); + if ( LevelMax < (int)pFanin->Level ) + LevelMax = pFanin->Level; + } + pNode->Level = LevelMax + 1; + return pNode->Level; +} + + +/**Function************************************************************* + + Synopsis [Compute levels of implication supergates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBalanceLevel( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + Abc_NtkForEachObj( pNtk, pNode, i ) + pNode->Level = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_NtkBalanceLevel_rec( Abc_ObjFanin0(pNode) ); +} + + +/**Function************************************************************* + + Synopsis [Marks the nodes on the critical and near critical paths.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_ObjRequiredLevel(pNode) - pNode->Level <= 1 ) + pNode->fMarkA = 1, Counter++; + printf( "The number of nodes on the critical paths = %6d (%5.2f %%)\n", Counter, 100.0 * Counter / Abc_NtkNodeNum(pNtk) ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcBmc.c b/abc70930/src/base/abci/abcBmc.c new file mode 100644 index 00000000..af6d237b --- /dev/null +++ b/abc70930/src/base/abci/abcBmc.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [abcBmc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Performs bounded model check.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcBmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ); + +static void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose ) +{ + Ivy_FraigParams_t Params, * pParams = &Params; + Ivy_Man_t * pMan, * pFrames, * pFraig; + Vec_Ptr_t * vMapping; + // convert to IVY manager + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + // generate timeframes + pFrames = Ivy_ManFrames( pMan, Abc_NtkLatchNum(pNtk), nFrames, fInit, &vMapping ); + // fraig the timeframes + Ivy_FraigParamsDefault( pParams ); + pParams->nBTLimitNode = ABC_INFINITY; + pParams->fVerbose = 0; + pParams->fProve = 0; + pFraig = Ivy_FraigPerform( pFrames, pParams ); +printf( "Frames have %6d nodes. ", Ivy_ManNodeNum(pFrames) ); +printf( "Fraig has %6d nodes.\n", Ivy_ManNodeNum(pFraig) ); + // report the classes +// if ( fVerbose ) +// Abc_NtkBmcReport( pMan, pFrames, pFraig, vMapping, nFrames ); + // free stuff + Vec_PtrFree( vMapping ); + Ivy_ManStop( pFraig ); + Ivy_ManStop( pFrames ); + Ivy_ManStop( pMan ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames ) +{ + Ivy_Obj_t * pFirst1, * pFirst2, * pFirst3; + int i, f, nIdMax, Prev2, Prev3; + nIdMax = Ivy_ManObjIdMax(pMan); + // check what is the number of nodes in each frame + Prev2 = Prev3 = 0; + for ( f = 0; f < nFrames; f++ ) + { + Ivy_ManForEachNode( pMan, pFirst1, i ) + { + pFirst2 = Ivy_Regular( Vec_PtrEntry(vMapping, f * nIdMax + pFirst1->Id) ); + if ( Ivy_ObjIsConst1(pFirst2) || pFirst2->Type == 0 ) + continue; + pFirst3 = Ivy_Regular( pFirst2->pEquiv ); + if ( Ivy_ObjIsConst1(pFirst3) || pFirst3->Type == 0 ) + continue; + break; + } + if ( f ) + printf( "Frame %3d : Strash = %5d Fraig = %5d\n", f, pFirst2->Id - Prev2, pFirst3->Id - Prev3 ); + Prev2 = pFirst2->Id; + Prev3 = pFirst3->Id; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcCas.c b/abc70930/src/base/abci/abcCas.c new file mode 100644 index 00000000..4ed7a774 --- /dev/null +++ b/abc70930/src/base/abci/abcCas.c @@ -0,0 +1,111 @@ +/**CFile**************************************************************** + + FileName [abcCas.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Decomposition of shared BDDs into LUT cascade.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCas.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +/* + This LUT cascade synthesis algorithm is described in the paper: + A. Mishchenko and T. Sasao, "Encoding of Boolean functions and its + application to LUT cascade synthesis", Proc. IWLS '02, pp. 115-120. + http://www.eecs.berkeley.edu/~alanmi/publications/2002/iwls02_enc.pdf +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ) +{ + DdManager * dd; + DdNode ** ppOutputs; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode; + char * pFileGeneric; + int fBddSizeMax = 500000; + int fReorder = 1; + int i, clk = clock(); + + assert( Abc_NtkIsStrash(pNtk) ); + // compute the global BDDs + if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL ) + return NULL; + + if ( fVerbose ) + { + DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); + printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + PRT( "BDD construction time", clock() - clk ); + } + + // collect global BDDs + dd = Abc_NtkGlobalBddMan( pNtk ); + ppOutputs = ALLOC( DdNode *, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + ppOutputs[i] = Abc_ObjGlobalBdd(pNode); + + // call the decomposition + pFileGeneric = Extra_FileNameGeneric( pNtk->pSpec ); + if ( !Abc_CascadeExperiment( pFileGeneric, dd, ppOutputs, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), nLutSize, fCheck, fVerbose ) ) + { + // the LUT size is too small + } + + // for now, duplicate the network + pNtkNew = Abc_NtkDup( pNtk ); + + // cleanup + Abc_NtkFreeGlobalBdds( pNtk, 1 ); + free( ppOutputs ); + free( pFileGeneric ); + +// if ( pNtk->pExdc ) +// pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkCollapse: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcClpBdd.c b/abc70930/src/base/abci/abcClpBdd.c new file mode 100644 index 00000000..341ff5b0 --- /dev/null +++ b/abc70930/src/base/abci/abcClpBdd.c @@ -0,0 +1,162 @@ +/**CFile**************************************************************** + + FileName [abcCollapse.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Collapsing the network into two-levels.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ); +static Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collapses the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew; + int clk = clock(); + + assert( Abc_NtkIsStrash(pNtk) ); + // compute the global BDDs + if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL ) + return NULL; + if ( fVerbose ) + { + DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); + printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + PRT( "BDD construction time", clock() - clk ); + } + + // create the new network + pNtkNew = Abc_NtkFromGlobalBdds( pNtk ); +// Abc_NtkFreeGlobalBdds( pNtk ); + Abc_NtkFreeGlobalBdds( pNtk, 1 ); + if ( pNtkNew == NULL ) + { +// Cudd_Quit( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; + return NULL; + } +// Extra_StopManager( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; + + // make the network minimum base + Abc_NtkMinimumBase( pNtkNew ); + + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkCollapse: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Derives the network with the given global BDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pDriver, * pNodeNew; +// DdManager * dd = pNtk->pManGlob; + DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); + int i; + // start the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + // make sure the new manager has the same number of inputs + Cudd_bddIthVar( pNtkNew->pManFunc, dd->size-1 ); + // process the POs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjIsCi(pDriver) && !strcmp(Abc_ObjName(pNode), Abc_ObjName(pDriver)) ) + { + Abc_ObjAddFanin( pNode->pCopy, pDriver->pCopy ); + continue; + } +// pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) ); + pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Abc_ObjGlobalBdd(pNode) ); + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + } + Extra_ProgressBarStop( pProgress ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Derives the network with the given global BDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc ) +{ + Abc_Obj_t * pNodeNew, * pTemp; + int i; + // create a new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + // add the fanins in the order, in which they appear in the reordered manager + Abc_NtkForEachCi( pNtkNew, pTemp, i ) + Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtkNew, dd->invperm[i]) ); + // transfer the function + pNodeNew->pData = Extra_TransferLevelByLevel( dd, pNtkNew->pManFunc, bFunc ); Cudd_Ref( pNodeNew->pData ); + return pNodeNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcClpSop.c b/abc70930/src/base/abci/abcClpSop.c new file mode 100644 index 00000000..de92243f --- /dev/null +++ b/abc70930/src/base/abci/abcClpSop.c @@ -0,0 +1,53 @@ +/**CFile**************************************************************** + + FileName [abcCollapse.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Collapsing the network into two-levels.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collapses the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCollapseSop( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew; + pNtkNew = NULL; + return pNtkNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcCut.c b/abc70930/src/base/abci/abcCut.c new file mode 100644 index 00000000..d399ce5f --- /dev/null +++ b/abc70930/src/base/abci/abcCut.c @@ -0,0 +1,620 @@ +/**CFile**************************************************************** + + FileName [abcCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface to cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "cut.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ); +static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ); + +extern int nTotal, nGood, nEqual; + +static Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); +static int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) +{ + ProgressBar * pProgress; + Cut_Man_t * p; + Abc_Obj_t * pObj, * pNode; + Vec_Ptr_t * vNodes; + Vec_Int_t * vChoices; + int i; + int clk = clock(); + + extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ); + extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); + + nTotal = nGood = nEqual = 0; + + assert( Abc_NtkIsStrash(pNtk) ); + // start the manager + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + p = Cut_ManStart( pParams ); + // compute node attributes if local or global cuts are requested + if ( pParams->fGlobal || pParams->fLocal ) + { + extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); + Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) ); + } + // prepare for cut dropping + if ( pParams->fDrop ) + Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( p, pObj->Id ); + // compute cuts for internal nodes + vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs + vChoices = Vec_IntAlloc( 100 ); + pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // when we reached a CO, it is time to deallocate the cuts + if ( Abc_ObjIsCo(pObj) ) + { + if ( pParams->fDrop ) + Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + continue; + } + // skip constant node, it has no cuts +// if ( Abc_NodeIsConst(pObj) ) +// continue; + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // compute the cuts to the internal node + Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree ); + // consider dropping the fanins cuts + if ( pParams->fDrop ) + { + Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); + } + // add cuts due to choices + if ( Abc_AigNodeIsChoice(pObj) ) + { + Vec_IntClear( vChoices ); + for ( pNode = pObj; pNode; pNode = pNode->pData ) + Vec_IntPush( vChoices, pNode->Id ); + Cut_NodeUnionCuts( p, vChoices ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + Vec_IntFree( vChoices ); + Cut_ManPrintStats( p ); +PRT( "TOTAL ", clock() - clk ); + printf( "Area = %d.\n", Abc_NtkComputeArea( pNtk, p ) ); +//Abc_NtkPrintCuts( p, pNtk, 0 ); +// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk ); + + // temporary printout of stats + if ( nTotal ) + printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal ); + return p; +} + +/**Function************************************************************* + + Synopsis [Cut computation using the oracle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p ) +{ + Abc_Obj_t * pObj; + Vec_Ptr_t * vNodes; + int i, clk = clock(); + int fDrop = Cut_OracleReadDrop(p); + + assert( Abc_NtkIsStrash(pNtk) ); + + // prepare cut droppping + if ( fDrop ) + Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); + + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_OracleNodeSetTriv( p, pObj->Id ); + + // compute cuts for internal nodes + vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // when we reached a CO, it is time to deallocate the cuts + if ( Abc_ObjIsCo(pObj) ) + { + if ( fDrop ) + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + continue; + } + // skip constant node, it has no cuts +// if ( Abc_NodeIsConst(pObj) ) +// continue; + // compute the cuts to the internal node + Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + // consider dropping the fanins cuts + if ( fDrop ) + { + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); + } + } + Vec_PtrFree( vNodes ); +//PRT( "Total", clock() - clk ); +//Abc_NtkPrintCuts_( p, pNtk, 0 ); +} + + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) +{ +/* + Cut_Man_t * p; + Abc_Obj_t * pObj, * pNode; + int i, nIters, fStatus; + Vec_Int_t * vChoices; + int clk = clock(); + + assert( Abc_NtkIsSeq(pNtk) ); + assert( pParams->fSeq ); +// assert( Abc_NtkIsDfsOrdered(pNtk) ); + + // start the manager + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk ); + p = Cut_ManStart( pParams ); + + // set cuts for the constant node and the PIs + pObj = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( p, pObj->Id ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { +//printf( "Setting trivial cut %d.\n", pObj->Id ); + Cut_NodeSetTriv( p, pObj->Id ); + } + // label the cutset nodes and set their number in the array + // assign the elementary cuts to the cutset nodes + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + { + assert( pObj->fMarkC == 0 ); + pObj->fMarkC = 1; + pObj->pCopy = (Abc_Obj_t *)i; + Cut_NodeSetTriv( p, pObj->Id ); +//printf( "Setting trivial cut %d.\n", pObj->Id ); + } + + // process the nodes + vChoices = Vec_IntAlloc( 100 ); + for ( nIters = 0; nIters < 10; nIters++ ) + { +//printf( "ITERATION %d:\n", nIters ); + // compute the cuts for the internal nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + { + Abc_NodeGetCutsSeq( p, pObj, nIters==0 ); + // add cuts due to choices + if ( Abc_AigNodeIsChoice(pObj) ) + { + Vec_IntClear( vChoices ); + for ( pNode = pObj; pNode; pNode = pNode->pData ) + Vec_IntPush( vChoices, pNode->Id ); + Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 ); + } + } + // merge the new cuts with the old cuts + Abc_NtkForEachPi( pNtk, pObj, i ) + Cut_NodeNewMergeWithOld( p, pObj->Id ); + Abc_AigForEachAnd( pNtk, pObj, i ) + Cut_NodeNewMergeWithOld( p, pObj->Id ); + // for the cutset, transfer temp cuts to new cuts + fStatus = 0; + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i ); + if ( fStatus == 0 ) + break; + } + Vec_IntFree( vChoices ); + + // if the status is not finished, transfer new to old for the cutset + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + Cut_NodeNewMergeWithOld( p, pObj->Id ); + + // transfer the old cuts to the new positions + Abc_NtkForEachObj( pNtk, pObj, i ) + Cut_NodeOldTransferToNew( p, pObj->Id ); + + // unlabel the cutset nodes + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + pObj->fMarkC = 0; +if ( pParams->fVerbose ) +{ + Cut_ManPrintStats( p ); +PRT( "TOTAL ", clock() - clk ); +printf( "Converged after %d iterations.\n", nIters ); +} +//Abc_NtkPrintCuts( p, pNtk, 1 ); + return p; +*/ + return NULL; +} + +/**Function************************************************************* + + Synopsis [Computes area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p ) +{ + Abc_Obj_t * pObj; + int Counter, i; + Counter = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + Counter += Cut_ManMappingArea_rec( p, Abc_ObjFaninId0(pObj) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) +{ + void * pList; + if ( pList = Abc_NodeReadCuts( p, pObj ) ) + return pList; + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree ); + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree ); + return Abc_NodeGetCuts( p, pObj, fDag, fTree ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) +{ + Abc_Obj_t * pFanin; + int fDagNode, fTriv, TreeCode = 0; +// assert( Abc_NtkIsStrash(pObj->pNtk) ); + assert( Abc_ObjFaninNum(pObj) == 2 ); + + + // check if the node is a DAG node + fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)); + // increment the counter of DAG nodes + if ( fDagNode ) Cut_ManIncrementDagNodes( p ); + // add the trivial cut if the node is a DAG node, or if we compute all cuts + fTriv = fDagNode || !fDag; + // check if fanins are DAG nodes + if ( fTree ) + { + pFanin = Abc_ObjFanin0(pObj); + TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)); + pFanin = Abc_ObjFanin1(pObj); + TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1); + } + + + // changes due to the global/local cut computation + { + Cut_Params_t * pParams = Cut_ManReadParams(p); + if ( pParams->fLocal ) + { + Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p); + fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id ); + if ( fDagNode ) Cut_ManIncrementDagNodes( p ); +// fTriv = fDagNode || !pParams->fGlobal; + fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id ); + TreeCode = 0; + pFanin = Abc_ObjFanin0(pObj); + TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id ); + pFanin = Abc_ObjFanin1(pObj); + TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1); + } + } + return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv ) +{ +/* + int CutSetNum; + assert( Abc_NtkIsSeq(pObj->pNtk) ); + assert( Abc_ObjFaninNum(pObj) == 2 ); + fTriv = pObj->fMarkC ? 0 : fTriv; + CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1; + Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum ); +*/ +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ) +{ + return Cut_NodeReadCutsNew( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ) +{ + Cut_NodeFreeCuts( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ) +{ + Cut_Man_t * pMan = p; + Cut_Cut_t * pList; + Abc_Obj_t * pObj; + int i; + printf( "Cuts of the network:\n" ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + pList = Abc_NodeReadCuts( p, pObj ); + printf( "Node %s:\n", Abc_ObjName(pObj) ); + Cut_CutPrintList( pList, fSeq ); + } +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ) +{ + Cut_Man_t * pMan = p; + Cut_Cut_t * pList; + Abc_Obj_t * pObj; + pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 ); + pList = Abc_NodeReadCuts( p, pObj ); + printf( "Node %s:\n", Abc_ObjName(pObj) ); + Cut_CutPrintList( pList, fSeq ); +} + + + + +/**Function************************************************************* + + Synopsis [Assigns global attributes randomly.] + + Description [Old code.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vAttrs; +// Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj;//, * pTemp; + int i;//, k; + int nNodesTotal = 0, nMffcsTotal = 0; + extern Vec_Ptr_t * Abc_NodeMffsInsideCollect( Abc_Obj_t * pNode ); + + vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); +// Abc_NtkForEachCi( pNtk, pObj, i ) +// Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); + + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Abc_ObjIsNode(pObj) ) + nNodesTotal++; + if ( Abc_ObjIsCo(pObj) && Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) + nMffcsTotal += Abc_NodeMffcSize( Abc_ObjFanin0(pObj) ); +// if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) ) +// if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) ) + if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) ) + { + int nMffc = Abc_NodeMffcSize(pObj); + nMffcsTotal += Abc_NodeMffcSize(pObj); +// printf( "%d ", nMffc ); + + if ( nMffc > 2 || Abc_ObjFanoutNum(pObj) > 8 ) + Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); + } + } +/* + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Vec_IntEntry( vAttrs, pObj->Id ) ) + { + vNodes = Abc_NodeMffsInsideCollect( pObj ); + Vec_PtrForEachEntry( vNodes, pTemp, k ) + if ( pTemp != pObj ) + Vec_IntWriteEntry( vAttrs, pTemp->Id, 0 ); + Vec_PtrFree( vNodes ); + } + } +*/ + printf( "Total nodes = %d. Total MFFC nodes = %d.\n", nNodesTotal, nMffcsTotal ); + return vAttrs; +} + +/**Function************************************************************* + + Synopsis [Assigns global attributes randomly.] + + Description [Old code.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSubDagSize_rec( Abc_Obj_t * pObj, Vec_Int_t * vAttrs ) +{ + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + if ( Vec_IntEntry( vAttrs, pObj->Id ) ) + return 0; + if ( Abc_ObjIsCi(pObj) ) + return 1; + assert( Abc_ObjFaninNum(pObj) == 2 ); + return 1 + Abc_NtkSubDagSize_rec(Abc_ObjFanin0(pObj), vAttrs) + + Abc_NtkSubDagSize_rec(Abc_ObjFanin1(pObj), vAttrs); +} + +/**Function************************************************************* + + Synopsis [Assigns global attributes randomly.] + + Description [Old code.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkGetNodeAttributes2( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vAttrs; + Abc_Obj_t * pObj; + int i, nSize; + assert( Abc_NtkIsDfsOrdered(pNtk) ); + vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + // skip no-nodes and nodes without fanouts + if ( pObj->Id == 0 || !(Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) ) + continue; + // the node has more than one fanout - count its sub-DAG size + Abc_NtkIncrementTravId( pNtk ); + nSize = Abc_NtkSubDagSize_rec( pObj, vAttrs ); + if ( nSize > 15 ) + Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); + } + return vAttrs; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcDar.c b/abc70930/src/base/abci/abcDar.c new file mode 100644 index 00000000..90fe35e9 --- /dev/null +++ b/abc70930/src/base/abci/abcDar.c @@ -0,0 +1,1212 @@ +/**CFile**************************************************************** + + FileName [abcDar.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [DAG-aware rewriting.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDar.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "aig.h" +#include "dar.h" +#include "cnf.h" +#include "fra.h" +#include "fraig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [Assumes that registers are ordered after PIs/POs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters ) +{ + Aig_Man_t * pMan; + Aig_Obj_t * pObjNew; + Abc_Obj_t * pObj; + int i, nNodes, nDontCares; + // make sure the latches follow PIs/POs + if ( fRegisters ) + { + assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( i < Abc_NtkPiNum(pNtk) ) + assert( Abc_ObjIsPi(pObj) ); + else + assert( Abc_ObjIsBo(pObj) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + if ( i < Abc_NtkPoNum(pNtk) ) + assert( Abc_ObjIsPo(pObj) ); + else + assert( Abc_ObjIsBi(pObj) ); + // print warning about initial values + nDontCares = 0; + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( Abc_LatchIsInitDc(pObj) ) + { + Abc_LatchSetInit0(pObj); + nDontCares++; + } + if ( nDontCares ) + { + printf( "Warning: %d registers in this network have don't-care init values.\n", nDontCares ); + printf( "The don't-care are assumed to be 0. The result may not verify.\n" ); + printf( "Use command \"print_latch\" to see the init values of registers.\n" ); + printf( "Use command \"init\" to change the values.\n" ); + } + } + // create the manager + pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 ); + pMan->pName = Extra_UtilStrsav( pNtk->pName ); + // save the number of registers + if ( fRegisters ) + { + pMan->nRegs = Abc_NtkLatchNum(pNtk); + pMan->vFlopNums = Vec_IntStartNatural( pMan->nRegs ); + } + // transfer the pointers to the basic nodes + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreatePi(pMan); + // complement the 1-values registers + if ( fRegisters ) + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( Abc_LatchIsInit1(pObj) ) + Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy); + // perform the conversion of the internal nodes (assumes DFS ordering) +// pMan->fAddStrash = 1; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) ); +// printf( "%d->%d ", pObj->Id, ((Aig_Obj_t *)pObj->pCopy)->Id ); + } + pMan->fAddStrash = 0; + // create the POs + Abc_NtkForEachCo( pNtk, pObj, i ) + Aig_ObjCreatePo( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj) ); + // complement the 1-valued registers + if ( fRegisters ) + Aig_ManForEachLiSeq( pMan, pObjNew, i ) + if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) ) + pObjNew->pFanin0 = Aig_Not(pObjNew->pFanin0); + // remove dangling nodes + if ( nNodes = Aig_ManCleanup( pMan ) ) + printf( "Abc_NtkToDar(): Unexpected %d dangling nodes when converting to AIG!\n", nNodes ); +//Aig_ManDumpVerilog( pMan, "test.v" ); + if ( !Aig_ManCheck( pMan ) ) + { + printf( "Abc_NtkToDar: AIG check has failed.\n" ); + Aig_ManStop( pMan ); + return NULL; + } + return pMan; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjNew; + Aig_Obj_t * pObj; + int i; +// assert( Aig_ManRegNum(pMan) == Abc_NtkLatchNum(pNtkOld) ); + // perform strashing + pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Aig_ManForEachPi( pMan, pObj, i ) + pObj->pData = Abc_NtkCi(pNtkNew, i); + // rebuild the AIG + vNodes = Aig_ManDfs( pMan ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( Aig_ObjIsBuf(pObj) ) + pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); + else + pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); + Vec_PtrFree( vNodes ); + // connect the PO nodes + Aig_ManForEachPo( pMan, pObj, i ) + { + if ( pMan->nAsserts && i == Aig_ManPoNum(pMan) - pMan->nAsserts ) + break; + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); + } + // if there are assertions, add them + if ( pMan->nAsserts > 0 ) + Aig_ManForEachAssert( pMan, pObj, i ) + { + pObjNew = Abc_NtkCreateAssert(pNtkNew); + Abc_ObjAssignName( pObjNew, "assert_", Abc_ObjName(pObjNew) ); + Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [This procedure should be called after seq sweeping, + which changes the number of registers.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjNew, * pLatch; + Aig_Obj_t * pObj, * pObjLo, * pObjLi; + int i; +// assert( Aig_ManRegNum(pMan) != Abc_NtkLatchNum(pNtkOld) ); + // perform strashing + pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Aig_ManForEachPiSeq( pMan, pObj, i ) + pObj->pData = Abc_NtkCi(pNtkNew, i); + // create as many latches as there are registers in the manager + Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i ) + { + pObjNew = Abc_NtkCreateLatch( pNtkNew ); + pObjLi->pData = Abc_NtkCreateBi( pNtkNew ); + pObjLo->pData = Abc_NtkCreateBo( pNtkNew ); + Abc_ObjAddFanin( pObjNew, pObjLi->pData ); + Abc_ObjAddFanin( pObjLo->pData, pObjNew ); + Abc_LatchSetInit0( pObjNew ); + } + if ( pMan->vFlopNums == NULL ) + Abc_NtkAddDummyBoxNames( pNtkNew ); + else + { + assert( Abc_NtkBoxNum(pNtkOld) == Abc_NtkLatchNum(pNtkOld) ); + Abc_NtkForEachLatch( pNtkNew, pObjNew, i ) + { + pLatch = Abc_NtkBox( pNtkOld, Vec_IntEntry( pMan->vFlopNums, i ) ); + Abc_ObjAssignName( pObjNew, Abc_ObjName(pLatch), NULL ); + Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pLatch)), NULL ); + Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pLatch)), NULL ); + } + } + // rebuild the AIG + vNodes = Aig_ManDfs( pMan ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + if ( Aig_ObjIsBuf(pObj) ) + pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); + else + pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); + Vec_PtrFree( vNodes ); + // connect the PO nodes + Aig_ManForEachPo( pMan, pObj, i ) + { + if ( pMan->nAsserts && i == Aig_ManPoNum(pMan) - pMan->nAsserts ) + break; + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); + } + // if there are assertions, add them + if ( pMan->nAsserts > 0 ) + Aig_ManForEachAssert( pMan, pObj, i ) + { + pObjNew = Abc_NtkCreateAssert(pNtkNew); + Abc_ObjAssignName( pObjNew, "assert_", Abc_ObjName(pObjNew) ); + Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Aig_Obj_t * pObj, * pTemp; + int i; + assert( pMan->pEquivs != NULL ); + assert( Aig_ManBufNum(pMan) == 0 ); + // perform strashing + pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Aig_ManForEachPi( pMan, pObj, i ) + pObj->pData = Abc_NtkCi(pNtkNew, i); + + // rebuild the AIG + vNodes = Aig_ManDfsChoices( pMan ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); + if ( pTemp = pMan->pEquivs[pObj->Id] ) + { + Abc_Obj_t * pAbcRepr, * pAbcObj; + assert( pTemp->pData != NULL ); + pAbcRepr = pObj->pData; + pAbcObj = pTemp->pData; + pAbcObj->pData = pAbcRepr->pData; + pAbcRepr->pData = pAbcObj; + } + } +//printf( "Total = %d. Collected = %d.\n", Aig_ManNodeNum(pMan), Vec_PtrSize(vNodes) ); + Vec_PtrFree( vNodes ); + // connect the PO nodes + Aig_ManForEachPo( pMan, pObj, i ) + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromDarSeq( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; + Aig_Obj_t * pObj; + int i; +// assert( Aig_ManLatchNum(pMan) > 0 ); + // perform strashing + pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Aig_ManForEachPi( pMan, pObj, i ) + pObj->pData = Abc_NtkPi(pNtkNew, i); + // create latches of the new network + Aig_ManForEachObj( pMan, pObj, i ) + { + if ( !Aig_ObjIsLatch(pObj) ) + continue; + pObjNew = Abc_NtkCreateLatch( pNtkNew ); + pFaninNew0 = Abc_NtkCreateBi( pNtkNew ); + pFaninNew1 = Abc_NtkCreateBo( pNtkNew ); + Abc_ObjAddFanin( pObjNew, pFaninNew0 ); + Abc_ObjAddFanin( pFaninNew1, pObjNew ); + Abc_LatchSetInit0( pObjNew ); + pObj->pData = Abc_ObjFanout0( pObjNew ); + } + Abc_NtkAddDummyBoxNames( pNtkNew ); + // rebuild the AIG + vNodes = Aig_ManDfs( pMan ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // add the first fanin + pObj->pData = pFaninNew0 = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); + if ( Aig_ObjIsBuf(pObj) ) + continue; + // add the second fanin + pFaninNew1 = (Abc_Obj_t *)Aig_ObjChild1Copy(pObj); + // create the new node + if ( Aig_ObjIsExor(pObj) ) + pObj->pData = pObjNew = Abc_AigXor( pNtkNew->pManFunc, pFaninNew0, pFaninNew1 ); + else + pObj->pData = pObjNew = Abc_AigAnd( pNtkNew->pManFunc, pFaninNew0, pFaninNew1 ); + } + Vec_PtrFree( vNodes ); + // connect the PO nodes + Aig_ManForEachPo( pMan, pObj, i ) + { + pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, i), pFaninNew ); + } + // connect the latches + Aig_ManForEachObj( pMan, pObj, i ) + { + if ( !Aig_ObjIsLatch(pObj) ) + continue; + pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj ); + Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pObj->pData)), pFaninNew ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Collect latch values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkGetLatchValues( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vInits; + Abc_Obj_t * pLatch; + int i; + vInits = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + assert( Abc_LatchIsInit1(pLatch) == 0 ); + Vec_IntPush( vInits, Abc_LatchIsInit1(pLatch) ); + } + return vInits; +} + +/**Function************************************************************* + + Synopsis [Performs verification after retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSecRetime( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ) +{ + int fRemove1, fRemove2; + Aig_Man_t * pMan1, * pMan2; + int * pArray; + + fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0)); + fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0)); + + + pMan1 = Abc_NtkToDar( pNtk1, 0 ); + pMan2 = Abc_NtkToDar( pNtk2, 0 ); + + Aig_ManPrintStats( pMan1 ); + Aig_ManPrintStats( pMan2 ); + +// pArray = Abc_NtkGetLatchValues(pNtk1); + pArray = NULL; + Aig_ManSeqStrash( pMan1, Abc_NtkLatchNum(pNtk1), pArray ); + free( pArray ); + +// pArray = Abc_NtkGetLatchValues(pNtk2); + pArray = NULL; + Aig_ManSeqStrash( pMan2, Abc_NtkLatchNum(pNtk2), pArray ); + free( pArray ); + + Aig_ManPrintStats( pMan1 ); + Aig_ManPrintStats( pMan2 ); + + Aig_ManStop( pMan1 ); + Aig_ManStop( pMan2 ); + + + if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); + if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkAig = NULL; + Aig_Man_t * pMan; + extern void Fra_ManPartitionTest( Aig_Man_t * p, int nComLim ); + + assert( Abc_NtkIsStrash(pNtk) ); + // convert to the AIG manager + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; + + // perform computation +// Fra_ManPartitionTest( pMan, 4 ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + + // make sure everything is okay + if ( pNtkAig && !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkDar: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose ) +{ + Fra_Par_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtkAig; + Aig_Man_t * pMan, * pTemp; + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; + Fra_ParamsDefault( pPars ); + pPars->nBTLimitNode = nConfLimit; + pPars->fChoicing = fChoicing; + pPars->fDoSparse = fDoSparse; + pPars->fSpeculate = fSpeculate; + pPars->fProve = fProve; + pPars->fVerbose = fVerbose; + pMan = Fra_FraigPerform( pTemp = pMan, pPars ); + if ( fChoicing ) + pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan ); + else + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pTemp ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose ) +{ + extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose ); + Abc_Ntk_t * pNtkAig; + Aig_Man_t * pMan, * pTemp; + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; + pMan = Csw_Sweep( pTemp = pMan, nCutsMax, nLeafMax, fVerbose ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pTemp ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + int clk; + assert( Abc_NtkIsStrash(pNtk) ); + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; +// Aig_ManPrintStats( pMan ); +/* +// Aig_ManSupports( pMan ); + { + Vec_Vec_t * vParts; + vParts = Aig_ManPartitionSmart( pMan, 50, 1, NULL ); + Vec_VecFree( vParts ); + } +*/ + Dar_ManRewrite( pMan, pPars ); +// pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel ); +// Aig_ManStop( pTemp ); + +clk = clock(); + pMan = Aig_ManDup( pTemp = pMan, 0 ); + Aig_ManStop( pTemp ); +//PRT( "time", clock() - clk ); + +// Aig_ManPrintStats( pMan ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + int clk; + assert( Abc_NtkIsStrash(pNtk) ); + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; +// Aig_ManPrintStats( pMan ); + + Dar_ManRefactor( pMan, pPars ); +// pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel ); +// Aig_ManStop( pTemp ); + +clk = clock(); + pMan = Aig_ManDup( pTemp = pMan, 0 ); + Aig_ManStop( pTemp ); +//PRT( "time", clock() - clk ); + +// Aig_ManPrintStats( pMan ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + int clk; + assert( Abc_NtkIsStrash(pNtk) ); + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; +// Aig_ManPrintStats( pMan ); + +clk = clock(); + pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fVerbose ); + Aig_ManStop( pTemp ); +//PRT( "time", clock() - clk ); + +// Aig_ManPrintStats( pMan ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + assert( Abc_NtkIsStrash(pNtk) ); + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; + pMan = Dar_ManChoice( pTemp = pMan, fBalance, fUpdateLevel, fVerbose ); + Aig_ManStop( pTemp ); + pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + int clk; + assert( Abc_NtkIsStrash(pNtk) ); + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; +// Aig_ManPrintStats( pMan ); + +clk = clock(); + pMan = Dar_ManRwsat( pTemp = pMan, fBalance, fVerbose ); + Aig_ManStop( pTemp ); +//PRT( "time", clock() - clk ); + +// Aig_ManPrintStats( pMan ); + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkConstructFromCnf( Abc_Ntk_t * pNtk, Cnf_Man_t * p, Vec_Ptr_t * vMapped ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pNodeNew; + Aig_Obj_t * pObj, * pLeaf; + Cnf_Cut_t * pCut; + Vec_Int_t * vCover; + unsigned uTruth; + int i, k, nDupGates; + // create the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + // make the mapper point to the new network + Aig_ManConst1(p->pManAig)->pData = Abc_NtkCreateNodeConst1(pNtkNew); + Abc_NtkForEachCi( pNtk, pNode, i ) + Aig_ManPi(p->pManAig, i)->pData = pNode->pCopy; + // process the nodes in topological order + vCover = Vec_IntAlloc( 1 << 16 ); + Vec_PtrForEachEntry( vMapped, pObj, i ) + { + // create new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + // add fanins according to the cut + pCut = pObj->pData; + Cnf_CutForEachLeaf( p->pManAig, pCut, pLeaf, k ) + Abc_ObjAddFanin( pNodeNew, pLeaf->pData ); + // add logic function + if ( pCut->nFanins < 5 ) + { + uTruth = 0xFFFF & *Cnf_CutTruth(pCut); + Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vCover ); + pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, pCut->nFanins, vCover ); + } + else + pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, pCut->nFanins, pCut->vIsop[1] ); + // save the node + pObj->pData = pNodeNew; + } + Vec_IntFree( vCover ); + // add the CO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pObj = Aig_ManPo(p->pManAig, i); + pNodeNew = Abc_ObjNotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + } + + // remove the constant node if not used + pNodeNew = (Abc_Obj_t *)Aig_ManConst1(p->pManAig)->pData; + if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) + Abc_NtkDeleteObj( pNodeNew ); + // minimize the node +// Abc_NtkSweep( pNtkNew, 0 ); + // decouple the PO driver nodes to reduce the number of levels + nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); +// if ( nDupGates && If_ManReadVerbose(pIfMan) ) +// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkConstructFromCnf(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Vec_Ptr_t * vMapped; + Aig_Man_t * pMan; + Cnf_Man_t * pManCnf; + Cnf_Dat_t * pCnf; + Abc_Ntk_t * pNtkNew = NULL; + assert( Abc_NtkIsStrash(pNtk) ); + + // convert to the AIG manager + pMan = Abc_NtkToDar( pNtk, 0 ); + if ( pMan == NULL ) + return NULL; + if ( !Aig_ManCheck( pMan ) ) + { + printf( "Abc_NtkDarToCnf: AIG check has failed.\n" ); + Aig_ManStop( pMan ); + return NULL; + } + // perform balance + Aig_ManPrintStats( pMan ); + + // derive CNF + pCnf = Cnf_Derive( pMan, 0 ); + pManCnf = Cnf_ManRead(); + + // write the network for verification + vMapped = Cnf_ManScanMapping( pManCnf, 1, 0 ); + pNtkNew = Abc_NtkConstructFromCnf( pNtk, pManCnf, vMapped ); + Vec_PtrFree( vMapped ); + + // write CNF into a file + Cnf_DataWriteIntoFile( pCnf, pFileName, 0 ); + Cnf_DataFree( pCnf ); + Cnf_ClearMemory(); + + Aig_ManStop( pMan ); + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Solves combinational miter using a SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ) +{ + sat_solver * pSat; + Aig_Man_t * pMan; + Cnf_Dat_t * pCnf; + int status, RetValue, clk = clock(); + Vec_Int_t * vCiIds; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkLatchNum(pNtk) == 0 ); + assert( Abc_NtkPoNum(pNtk) == 1 ); + + // conver to the manager + pMan = Abc_NtkToDar( pNtk, 0 ); + // derive CNF + pCnf = Cnf_Derive( pMan, 0 ); +// pCnf = Cnf_DeriveSimple( pMan, 0 ); + // convert into the SAT solver + pSat = Cnf_DataWriteIntoSolver( pCnf ); + vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan ); + Aig_ManStop( pMan ); + Cnf_DataFree( pCnf ); + // solve SAT + if ( pSat == NULL ) + { + Vec_IntFree( vCiIds ); +// printf( "Trivially unsat\n" ); + return 1; + } + + +// printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); +// PRT( "Time", clock() - clk ); + + // simplify the problem + clk = clock(); + status = sat_solver_simplify(pSat); +// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); +// PRT( "Time", clock() - clk ); + if ( status == 0 ) + { + Vec_IntFree( vCiIds ); + sat_solver_delete( pSat ); +// printf( "The problem is UNSATISFIABLE after simplification.\n" ); + return 1; + } + + // solve the miter + clk = clock(); + if ( fVerbose ) + pSat->verbosity = 1; + status = sat_solver_solve( pSat, NULL, NULL, (sint64)nConfLimit, (sint64)nInsLimit, (sint64)0, (sint64)0 ); + if ( status == l_Undef ) + { +// printf( "The problem timed out.\n" ); + RetValue = -1; + } + else if ( status == l_True ) + { +// printf( "The problem is SATISFIABLE.\n" ); + RetValue = 0; + } + else if ( status == l_False ) + { +// printf( "The problem is UNSATISFIABLE.\n" ); + RetValue = 1; + } + else + assert( 0 ); +// PRT( "SAT sat_solver time", clock() - clk ); +// printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts ); + + // if the problem is SAT, get the counterexample + if ( status == l_True ) + { + pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); + } + // free the sat_solver + if ( fVerbose ) + Sat_SolverPrintStats( stdout, pSat ); +//sat_solver_store_write( pSat, "trace.cnf" ); +//sat_solver_store_free( pSat ); + sat_solver_delete( pSat ); + Vec_IntFree( vCiIds ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFramesK, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose ) +{ + Fraig_Params_t Params; + Abc_Ntk_t * pNtkAig, * pNtkFraig; + Aig_Man_t * pMan, * pTemp; + int clk = clock(); + + // preprocess the miter by fraiging it + // (note that for each functional class, fraiging leaves one representative; + // so fraiging does not reduce the number of functions represented by nodes + Fraig_ParamsSetDefault( &Params ); + Params.nBTLimit = 100000; +// pNtkFraig = Abc_NtkFraig( pNtk, &Params, 0, 0 ); + pNtkFraig = Abc_NtkDup( pNtk ); +if ( fVerbose ) +{ +PRT( "Initial fraiging time", clock() - clk ); +} + + pMan = Abc_NtkToDar( pNtkFraig, 1 ); + Abc_NtkDelete( pNtkFraig ); + if ( pMan == NULL ) + return NULL; + + pMan = Fra_FraigInduction( pTemp = pMan, nFramesP, nFramesK, nMaxImps, fRewrite, fUseImps, fLatchCorr, fWriteImps, fVerbose, NULL ); + Aig_ManStop( pTemp ); + + if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) + pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); + else + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Computes latch correspondence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose ) +{ + Aig_Man_t * pMan, * pTemp; + Abc_Ntk_t * pNtkAig; + pMan = Abc_NtkToDar( pNtk, 1 ); + if ( pMan == NULL ) + return NULL; + pMan = Fra_FraigLatchCorrespondence( pTemp = pMan, nFramesP, nConfMax, 0, fVerbose, NULL ); + Aig_ManStop( pTemp ); + if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) + pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); + else + pNtkAig = Abc_NtkFromDar( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDarProve( Abc_Ntk_t * pNtk, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ) +{ + Aig_Man_t * pMan; + int RetValue; + // derive the AIG manager + pMan = Abc_NtkToDar( pNtk, 1 ); + if ( pMan == NULL ) + { + printf( "Converting miter into AIG has failed.\n" ); + return -1; + } + assert( pMan->nRegs > 0 ); + // perform verification + RetValue = Fra_FraigSec( pMan, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); + Aig_ManStop( pMan ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ) +{ +// Fraig_Params_t Params; + Aig_Man_t * pMan; + Abc_Ntk_t * pMiter;//, * pTemp; + int RetValue; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return 0; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); + Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return 0; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are equivalent after structural hashing.\n" ); + return 1; + } + + // commented out because something became non-inductive +/* + // preprocess the miter by fraiging it + // (note that for each functional class, fraiging leaves one representative; + // so fraiging does not reduce the number of functions represented by nodes + Fraig_ParamsSetDefault( &Params ); + Params.nBTLimit = 100000; + pMiter = Abc_NtkFraig( pTemp = pMiter, &Params, 0, 0 ); + Abc_NtkDelete( pTemp ); + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); + Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return 0; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are equivalent after structural hashing.\n" ); + return 1; + } +*/ + // derive the AIG manager + pMan = Abc_NtkToDar( pMiter, 1 ); + Abc_NtkDelete( pMiter ); + if ( pMan == NULL ) + { + printf( "Converting miter into AIG has failed.\n" ); + return -1; + } + assert( pMan->nRegs > 0 ); + + // perform verification + RetValue = Fra_FraigSec( pMan, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); + Aig_ManStop( pMan ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Aig_Man_t * pMan; + pMan = Abc_NtkToDar( pNtk, 1 ); + if ( pMan == NULL ) + return NULL; + Aig_ManSeqCleanup( pMan ); + if ( fLatchSweep ) + { + if ( pMan->nRegs ) + pMan = Aig_ManReduceLaches( pMan, fVerbose ); + if ( pMan->nRegs ) + pMan = Aig_ManConstReduce( pMan, fVerbose ); + } + pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Aig_Man_t * pMan, * pTemp; + pMan = Abc_NtkToDar( pNtk, 1 ); + if ( pMan == NULL ) + return NULL; +// Aig_ManReduceLachesCount( pMan ); + + pMan = Rtm_ManRetime( pTemp = pMan, 1, nStepsMax, 0 ); + Aig_ManStop( pTemp ); + +// pMan = Aig_ManReduceLaches( pMan, 1 ); +// pMan = Aig_ManConstReduce( pMan, 1 ); + + pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); + Aig_ManStop( pMan ); + return pNtkAig; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcDebug.c b/abc70930/src/base/abci/abcDebug.c new file mode 100644 index 00000000..95b95d89 --- /dev/null +++ b/abc70930/src/base/abci/abcDebug.c @@ -0,0 +1,208 @@ +/**CFile**************************************************************** + + FileName [abcDebug.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Automated debugging procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDebug.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtk, int ObjNum, int fConst1 ); + +extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Takes a network and a procedure to test.] + + Description [The network demonstrates the bug in the procedure. + Procedure should return 1 if the bug is demonstrated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) ) +{ + Abc_Ntk_t * pNtkMod; + char * pFileName = "bug_found.blif"; + int i, nSteps, nIter, ModNum, RandNum = 1, clk, clkTotal = clock(); + assert( Abc_NtkIsLogic(pNtk) ); + srand( 0x123123 ); + // create internal copy of the network + pNtk = Abc_NtkDup(pNtk); + if ( !(*pFuncError)( pNtk ) ) + { + printf( "The original network does not cause the bug. Quitting.\n" ); + Abc_NtkDelete( pNtk ); + return; + } + // perform incremental modifications + for ( nIter = 0; ; nIter++ ) + { + clk = clock(); + // count how many ways of modifying the network exists + nSteps = 2 * Abc_NtkCountFaninsTotal(pNtk); + // try modifying the network as many times + RandNum ^= rand(); + for ( i = 0; i < nSteps; i++ ) + { + // get the shifted number of bug + ModNum = (i + RandNum) % nSteps; + // get the modified network + pNtkMod = Abc_NtkAutoDebugModify( pNtk, ModNum/2, ModNum%2 ); + // write the network + Io_WriteBlifLogic( pNtk, "bug_temp.blif", 1 ); + // check if the bug is still there + if ( (*pFuncError)( pNtkMod ) ) // bug is still there + { + Abc_NtkDelete( pNtk ); + pNtk = pNtkMod; + break; + } + else // no bug + Abc_NtkDelete( pNtkMod ); + } + printf( "Iter %6d : Latches = %6d. Nodes = %6d. Steps = %6d. Error step = %3d. ", + nIter, Abc_NtkLatchNum(pNtk), Abc_NtkNodeNum(pNtk), nSteps, i ); + PRT( "Time", clock() - clk ); + if ( i == nSteps ) // could not modify it while preserving the bug + break; + } + // write out the final network + Io_WriteBlifLogic( pNtk, pFileName, 1 ); + printf( "Final network written into file \"%s\". ", pFileName ); + PRT( "Total time", clock() - clkTotal ); + Abc_NtkDelete( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Counts the total number of fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k, Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) ) + continue; + if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 ) + continue; + if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) ) + continue; + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the node and fanin to be modified.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkFindGivenFanin( Abc_Ntk_t * pNtk, int Step, Abc_Obj_t ** ppObj, Abc_Obj_t ** ppFanin ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k, Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) ) + continue; + if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 ) + continue; + if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) ) + continue; + if ( Counter++ == Step ) + { + *ppObj = pObj; + *ppFanin = pFanin; + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Perform modification with the given number.] + + Description [Modification consists of replacing the node by a constant.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtkInit, int Step, int fConst1 ) +{ + extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj, * pFanin, * pConst; + // copy the network + pNtk = Abc_NtkDup( pNtkInit ); + assert( Abc_NtkNodeNum(pNtk) == Abc_NtkNodeNum(pNtkInit) ); + // find the object number + Abc_NtkFindGivenFanin( pNtk, Step, &pObj, &pFanin ); + // consider special case + if ( Abc_ObjIsPo(pObj) && Abc_NodeIsConst(pFanin) ) + { + Abc_NtkDeleteAll_rec( pObj ); + return pNtk; + } + // plug in a constant node + pConst = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); + Abc_ObjTransferFanout( pFanin, pConst ); + Abc_NtkDeleteAll_rec( pFanin ); + + Abc_NtkSweep( pNtk, 0 ); + Abc_NtkCleanupSeq( pNtk, 0, 0, 0 ); + Abc_NtkToSop( pNtk, 0 ); + Abc_NtkCycleInitStateSop( pNtk, 50, 0 ); + return pNtk; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcDress.c b/abc70930/src/base/abci/abcDress.c new file mode 100644 index 00000000..f8182532 --- /dev/null +++ b/abc70930/src/base/abci/abcDress.c @@ -0,0 +1,209 @@ +/**CFile**************************************************************** + + FileName [abcDress.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Transfers names from one netlist to the other.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDress.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk ); +static void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose ); + +extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transfers names from one netlist to the other.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDress( Abc_Ntk_t * pNtkLogic, char * pFileName, int fVerbose ) +{ + Abc_Ntk_t * pNtkOrig, * pNtkLogicOrig; + Abc_Ntk_t * pMiter, * pMiterFraig; + stmm_table * tMapping; + + assert( Abc_NtkIsLogic(pNtkLogic) ); + + // get the original netlist + pNtkOrig = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 1 ); + if ( pNtkOrig == NULL ) + return; + assert( Abc_NtkIsNetlist(pNtkOrig) ); + + Abc_NtkCleanCopy(pNtkLogic); + Abc_NtkCleanCopy(pNtkOrig); + + // convert it into the logic network + pNtkLogicOrig = Abc_NtkToLogic( pNtkOrig ); + // check that the networks have the same PIs/POs/latches + if ( !Abc_NtkCompareSignals( pNtkLogic, pNtkLogicOrig, 1, 1 ) ) + { + Abc_NtkDelete( pNtkOrig ); + Abc_NtkDelete( pNtkLogicOrig ); + return; + } + + // convert the current logic network into an AIG + pMiter = Abc_NtkStrash( pNtkLogic, 1, 0, 0 ); + + // convert it into the AIG and make the netlist point to the AIG + Abc_NtkAppend( pMiter, pNtkLogicOrig, 1 ); + Abc_NtkTransferCopy( pNtkOrig ); + Abc_NtkDelete( pNtkLogicOrig ); + +if ( fVerbose ) +{ +printf( "After mitering:\n" ); +printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) ); +printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) ); +} + + // fraig the miter (miter nodes point to the fraiged miter) + pMiterFraig = Abc_NtkIvyFraig( pMiter, 100, 1, 0, 1, 0 ); + // make netlists point to the fraiged miter + Abc_NtkTransferCopy( pNtkLogic ); + Abc_NtkTransferCopy( pNtkOrig ); + Abc_NtkDelete( pMiter ); + +if ( fVerbose ) +{ +printf( "After fraiging:\n" ); +printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) ); +printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) ); +} + + // derive mapping from the fraiged nodes into their prototype nodes in the original netlist + tMapping = Abc_NtkDressDeriveMapping( pNtkOrig ); + + // transfer the names to the new netlist + Abc_NtkDressTransferNames( pNtkLogic, tMapping, fVerbose ); + + // clean up + stmm_free_table( tMapping ); + Abc_NtkDelete( pMiterFraig ); + Abc_NtkDelete( pNtkOrig ); +} + +/**Function************************************************************* + + Synopsis [Returns the mapping from the fraig nodes point into the nodes of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk ) +{ + stmm_table * tResult; + Abc_Obj_t * pNode, * pNodeMap, * pNodeFraig; + int i; + assert( Abc_NtkIsNetlist(pNtk) ); + tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // get the fraiged node + pNodeFraig = Abc_ObjRegular(pNode->pCopy); + // if this node is already mapped, skip + if ( stmm_is_member( tResult, (char *)pNodeFraig ) ) + continue; + // get the mapping of this node + pNodeMap = Abc_ObjNotCond( pNode, Abc_ObjIsComplement(pNode->pCopy) ); + // add the mapping + stmm_insert( tResult, (char *)pNodeFraig, (char *)pNodeMap ); + } + return tResult; +} + +/**Function************************************************************* + + Synopsis [Attaches the names of to the new netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose ) +{ + Abc_Obj_t * pNet, * pNode, * pNodeMap, * pNodeFraig; + char * pName; + int i, Counter = 0, CounterInv = 0, CounterInit = stmm_count(tMapping); + assert( Abc_NtkIsLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // if the node already has a name, quit + pName = Nm_ManFindNameById( pNtk->pManName, pNode->Id ); + if ( pName != NULL ) + continue; + // get the fraiged node + pNodeFraig = Abc_ObjRegular(pNode->pCopy); + // find the matching node of the original netlist + if ( !stmm_lookup( tMapping, (char *)pNodeFraig, (char **)&pNodeMap ) ) + continue; + // find the true match + pNodeMap = Abc_ObjNotCond( pNodeMap, Abc_ObjIsComplement(pNode->pCopy) ); + // get the name + pNet = Abc_ObjFanout0(Abc_ObjRegular(pNodeMap)); + pName = Nm_ManFindNameById( pNet->pNtk->pManName, pNet->Id ); + assert( pName != NULL ); + // set the name + if ( Abc_ObjIsComplement(pNodeMap) ) + { + Abc_ObjAssignName( pNode, pName, "_inv" ); + CounterInv++; + } + else + { + Abc_ObjAssignName( pNode, pName, NULL ); + Counter++; + } + // remove the name + stmm_delete( tMapping, (char **)&pNodeFraig, (char **)&pNodeMap ); + } + if ( fVerbose ) + { + printf( "Total number of names collected = %5d.\n", CounterInit ); + printf( "Total number of names assigned = %5d. (Dir = %5d. Compl = %5d.)\n", + Counter + CounterInv, Counter, CounterInv ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcDsd.c b/abc70930/src/base/abci/abcDsd.c new file mode 100644 index 00000000..c00a7d7c --- /dev/null +++ b/abc70930/src/base/abci/abcDsd.c @@ -0,0 +1,551 @@ +/**CFile**************************************************************** + + FileName [abcDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Decomposes the network using disjoint-support decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dsd.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ); +static void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +static Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters ); + +static Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk ); +static void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive, int * pCounters ); +static bool Abc_NodeIsForDsd( Abc_Obj_t * pNode ); +static int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the DSD network.] + + Description [Takes the strashed network (pNtk), derives global BDDs for + the combinational outputs of this network, and decomposes these BDDs using + disjoint support decomposition. Finally, constructs and return a new + network, which is topologically equivalent to the decomposition tree. + Allocates and frees a new BDD manager and a new DSD manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ) +{ + DdManager * dd; + Abc_Ntk_t * pNtkNew; + assert( Abc_NtkIsStrash(pNtk) ); + dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); + if ( dd == NULL ) + return NULL; + if ( fVerbose ) + printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + // transform the result of mapping into a BDD network + pNtkNew = Abc_NtkDsdInternal( pNtk, fVerbose, fPrint, fShort ); + Extra_StopManager( dd ); + if ( pNtkNew == NULL ) + return NULL; + // copy EXDC network + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkDsdGlobal: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Constructs the decomposed network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ) +{ + char ** ppNamesCi, ** ppNamesCo; + Vec_Ptr_t * vFuncsGlob; + Dsd_Manager_t * pManDsd; + Abc_Ntk_t * pNtkNew; + DdManager * dd; + Abc_Obj_t * pObj; + int i; + + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Cudd_NotCond(Abc_ObjGlobalBdd(pObj), Abc_ObjFaninC0(pObj)) ); + + // perform the decomposition + dd = Abc_NtkGlobalBddMan(pNtk); + pManDsd = Dsd_ManagerStart( dd, Abc_NtkCiNum(pNtk), fVerbose ); + Dsd_Decompose( pManDsd, (DdNode **)vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) ); + Vec_PtrFree( vFuncsGlob ); + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + if ( pManDsd == NULL ) + { + Cudd_Quit( dd ); + return NULL; + } + + // start the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + // make sure the new manager has enough inputs + Cudd_bddIthVar( pNtkNew->pManFunc, dd->size-1 ); + // put the results into the new network (save new CO drivers in old CO drivers) + Abc_NtkDsdConstruct( pManDsd, pNtk, pNtkNew ); + // finalize the new network + Abc_NtkFinalize( pNtk, pNtkNew ); + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + if ( fPrint ) + { + ppNamesCi = Abc_NtkCollectCioNames( pNtk, 0 ); + ppNamesCo = Abc_NtkCollectCioNames( pNtk, 1 ); + Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, fShort, -1 ); + free( ppNamesCi ); + free( ppNamesCo ); + } + + // stop the DSD manager + Dsd_ManagerStop( pManDsd ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Constructs the decomposed network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Dsd_Node_t ** ppNodesDsd; + Dsd_Node_t * pNodeDsd; + Abc_Obj_t * pNode, * pNodeNew, * pDriver; + int i, nNodesDsd; + + // save the CI nodes in the DSD nodes + Dsd_NodeSetMark( Dsd_ManagerReadConst1(pManDsd), (int)Abc_NtkCreateNodeConst1(pNtkNew) ); + Abc_NtkForEachCi( pNtk, pNode, i ) + { + pNodeDsd = Dsd_ManagerReadInput( pManDsd, i ); + Dsd_NodeSetMark( pNodeDsd, (int)pNode->pCopy ); + } + + // collect DSD nodes in DFS order (leaves and const1 are not collected) + ppNodesDsd = Dsd_TreeCollectNodesDfs( pManDsd, &nNodesDsd ); + for ( i = 0; i < nNodesDsd; i++ ) + Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNtkNew, NULL ); + free( ppNodesDsd ); + + // set the pointers to the CO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0( pNode ); + if ( !Abc_ObjIsNode(pDriver) ) + continue; + if ( !Abc_AigNodeIsAnd(pDriver) ) + continue; + pNodeDsd = Dsd_ManagerReadRoot( pManDsd, i ); + pNodeNew = (Abc_Obj_t *)Dsd_NodeReadMark( Dsd_Regular(pNodeDsd) ); + assert( !Abc_ObjIsComplement(pNodeNew) ); + pDriver->pCopy = Abc_ObjNotCond( pNodeNew, Dsd_IsComplement(pNodeDsd) ); + } +} + +/**Function************************************************************* + + Synopsis [Performs DSD using the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters ) +{ + DdManager * ddDsd = Dsd_ManagerReadDd( pManDsd ); + DdManager * ddNew = pNtkNew->pManFunc; + Dsd_Node_t * pFaninDsd; + Abc_Obj_t * pNodeNew, * pFanin; + DdNode * bLocal, * bTemp, * bVar; + Dsd_Type_t Type; + int i, nDecs; + + // create the new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + // add the fanins + Type = Dsd_NodeReadType( pNodeDsd ); + nDecs = Dsd_NodeReadDecsNum( pNodeDsd ); + assert( nDecs > 1 ); + for ( i = 0; i < nDecs; i++ ) + { + pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i ); + pFanin = (Abc_Obj_t *)Dsd_NodeReadMark(Dsd_Regular(pFaninDsd)); + Abc_ObjAddFanin( pNodeNew, pFanin ); + assert( Type == DSD_NODE_OR || !Dsd_IsComplement(pFaninDsd) ); + } + + // create the local function depending on the type of the node + ddNew = pNtkNew->pManFunc; + switch ( Type ) + { + case DSD_NODE_CONST1: + { + bLocal = ddNew->one; Cudd_Ref( bLocal ); + break; + } + case DSD_NODE_OR: + { + bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal ); + for ( i = 0; i < nDecs; i++ ) + { + pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i ); + bVar = Cudd_NotCond( ddNew->vars[i], Dsd_IsComplement(pFaninDsd) ); + bLocal = Cudd_bddOr( ddNew, bTemp = bLocal, bVar ); Cudd_Ref( bLocal ); + Cudd_RecursiveDeref( ddNew, bTemp ); + } + break; + } + case DSD_NODE_EXOR: + { + bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal ); + for ( i = 0; i < nDecs; i++ ) + { + bLocal = Cudd_bddXor( ddNew, bTemp = bLocal, ddNew->vars[i] ); Cudd_Ref( bLocal ); + Cudd_RecursiveDeref( ddNew, bTemp ); + } + break; + } + case DSD_NODE_PRIME: + { + if ( pCounters ) + { + if ( nDecs < 10 ) + pCounters[nDecs]++; + else + pCounters[10]++; + } + bLocal = Dsd_TreeGetPrimeFunction( ddDsd, pNodeDsd ); Cudd_Ref( bLocal ); + bLocal = Extra_TransferLevelByLevel( ddDsd, ddNew, bTemp = bLocal ); Cudd_Ref( bLocal ); +/* +if ( nDecs == 3 ) +{ +Extra_bddPrint( ddDsd, bTemp ); +printf( "\n" ); +} +*/ + Cudd_RecursiveDeref( ddDsd, bTemp ); + // bLocal is now in the new BDD manager + break; + } + default: + { + assert( 0 ); + break; + } + } + pNodeNew->pData = bLocal; + Dsd_NodeSetMark( pNodeDsd, (int)pNodeNew ); + return pNodeNew; +} + + + + + + +/**Function************************************************************* + + Synopsis [Recursively decomposes internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive ) +{ + Dsd_Manager_t * pManDsd; + DdManager * dd = pNtk->pManFunc; + Vec_Ptr_t * vNodes; + int i; + int pCounters[11] = {0}; + + assert( Abc_NtkIsBddLogic(pNtk) ); + + // make the network minimum base + Abc_NtkMinimumBase( pNtk ); + + // start the DSD manager + pManDsd = Dsd_ManagerStart( dd, dd->size, 0 ); + + // collect nodes for decomposition + vNodes = Abc_NtkCollectNodesForDsd( pNtk ); + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_NodeDecompDsdAndMux( vNodes->pArray[i], vNodes, pManDsd, fRecursive, pCounters ); + Vec_PtrFree( vNodes ); + + printf( "Number of non-decomposable functions:\n" ); + for ( i = 3; i < 10; i++ ) + printf( "Inputs = %d. Functions = %6d.\n", i, pCounters[i] ); + printf( "Inputs > %d. Functions = %6d.\n", 9, pCounters[10] ); + + // stop the DSD manager + Dsd_ManagerStop( pManDsd ); + + // make sure everything is okay + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkDsdRecursive: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes that may need decomposition.] + + Description [The nodes that do not need decomposition are those + whose BDD has more internal nodes than the support size.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsForDsd(pNode) ) + Vec_PtrPush( vNodes, pNode ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive, int * pCounters ) +{ + DdManager * dd = pNode->pNtk->pManFunc; + Abc_Obj_t * pRoot, * pFanin, * pNode1, * pNode2, * pNodeC; + Dsd_Node_t ** ppNodesDsd, * pNodeDsd, * pFaninDsd; + int i, nNodesDsd, iVar, fCompl; + + // try disjoint support decomposition + pNodeDsd = Dsd_DecomposeOne( pManDsd, pNode->pData ); + fCompl = Dsd_IsComplement( pNodeDsd ); + pNodeDsd = Dsd_Regular( pNodeDsd ); + + // determine what decomposition to use + if ( !fRecursive || Dsd_NodeReadDecsNum(pNodeDsd) != Abc_ObjFaninNum(pNode) ) + { // perform DSD + + // set the inputs + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + pFaninDsd = Dsd_ManagerReadInput( pManDsd, i ); + Dsd_NodeSetMark( pFaninDsd, (int)pFanin ); + } + + // construct the intermediate nodes + ppNodesDsd = Dsd_TreeCollectNodesDfsOne( pManDsd, pNodeDsd, &nNodesDsd ); + for ( i = 0; i < nNodesDsd; i++ ) + { + pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk, pCounters ); + if ( Abc_NodeIsForDsd(pRoot) && fRecursive ) + Vec_PtrPush( vNodes, pRoot ); + } + free( ppNodesDsd ); + + // remove the current fanins + Abc_ObjRemoveFanins( pNode ); + // add fanin to the root + Abc_ObjAddFanin( pNode, pRoot ); + // update the function to be that of buffer + Cudd_RecursiveDeref( dd, pNode->pData ); + pNode->pData = Cudd_NotCond( dd->vars[0], fCompl ); Cudd_Ref( pNode->pData ); + } + else // perform MUX-decomposition + { + // get the cofactoring variable + iVar = Abc_NodeFindMuxVar( dd, pNode->pData, Abc_ObjFaninNum(pNode) ); + pNodeC = Abc_ObjFanin( pNode, iVar ); + + // get the negative cofactor + pNode1 = Abc_NtkCloneObj( pNode ); + pNode1->pData = Cudd_Cofactor( dd, pNode->pData, Cudd_Not(dd->vars[iVar]) ); Cudd_Ref( pNode1->pData ); + Abc_NodeMinimumBase( pNode1 ); + if ( Abc_NodeIsForDsd(pNode1) ) + Vec_PtrPush( vNodes, pNode1 ); + + // get the positive cofactor + pNode2 = Abc_NtkCloneObj( pNode ); + pNode2->pData = Cudd_Cofactor( dd, pNode->pData, dd->vars[iVar] ); Cudd_Ref( pNode2->pData ); + Abc_NodeMinimumBase( pNode2 ); + if ( Abc_NodeIsForDsd(pNode2) ) + Vec_PtrPush( vNodes, pNode2 ); + + // remove the current fanins + Abc_ObjRemoveFanins( pNode ); + // add new fanins + Abc_ObjAddFanin( pNode, pNodeC ); + Abc_ObjAddFanin( pNode, pNode2 ); + Abc_ObjAddFanin( pNode, pNode1 ); + // update the function to be that of MUX + Cudd_RecursiveDeref( dd, pNode->pData ); + pNode->pData = Cudd_bddIte( dd, dd->vars[0], dd->vars[1], dd->vars[2] ); Cudd_Ref( pNode->pData ); + } +} + +/**Function************************************************************* + + Synopsis [Checks if the node should be decomposed by DSD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NodeIsForDsd( Abc_Obj_t * pNode ) +{ + DdManager * dd = pNode->pNtk->pManFunc; +// DdNode * bFunc, * bFunc0, * bFunc1; + assert( Abc_ObjIsNode(pNode) ); +// if ( Cudd_DagSize(pNode->pData)-1 > Abc_ObjFaninNum(pNode) ) +// return 1; +// return 0; + +/* + // this does not catch things like a(b+c), which should be decomposed + for ( bFunc = Cudd_Regular(pNode->pData); !cuddIsConstant(bFunc); ) + { + bFunc0 = Cudd_Regular( cuddE(bFunc) ); + bFunc1 = cuddT(bFunc); + if ( bFunc0 == b1 ) + bFunc = bFunc1; + else if ( bFunc1 == b1 || bFunc0 == bFunc1 ) + bFunc = bFunc0; + else + return 1; + } +*/ + if ( Abc_ObjFaninNum(pNode) > 2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Determines a cofactoring variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars ) +{ + DdNode * bVar, * bCof0, * bCof1; + int SuppSumMin = 1000000; + int i, nSSD, nSSQ, iVar; + +// printf( "\n\nCofactors:\n\n" ); + iVar = -1; + for ( i = 0; i < nVars; i++ ) + { + bVar = dd->vars[i]; + + bCof0 = Cudd_Cofactor( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_Cofactor( dd, bFunc, bVar ); Cudd_Ref( bCof1 ); + +// nodD = Cudd_DagSize(bCof0); +// nodQ = Cudd_DagSize(bCof1); +// printf( "+%02d: D=%2d. Q=%2d. ", i, nodD, nodQ ); +// printf( "S=%2d. D=%2d. ", nodD + nodQ, abs(nodD-nodQ) ); + + nSSD = Cudd_SupportSize( dd, bCof0 ); + nSSQ = Cudd_SupportSize( dd, bCof1 ); + +// printf( "SD=%2d. SQ=%2d. ", nSSD, nSSQ ); +// printf( "S=%2d. D=%2d. ", nSSD + nSSQ, abs(nSSD - nSSQ) ); +// printf( "Cost=%3d. ", Cost(nodD,nodQ,nSSD,nSSQ) ); +// printf( "\n" ); + + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); + + if ( SuppSumMin > nSSD + nSSQ ) + { + SuppSumMin = nSSD + nSSQ; + iVar = i; + } + } + return iVar; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcEspresso.c b/abc70930/src/base/abci/abcEspresso.c new file mode 100644 index 00000000..8f9c7277 --- /dev/null +++ b/abc70930/src/base/abci/abcEspresso.c @@ -0,0 +1,250 @@ +/**CFile**************************************************************** + + FileName [abcEspresso.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to minimize SOPs using Espresso.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcEspresso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "espresso.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NodeEspresso( Abc_Obj_t * pNode ); +static pset_family Abc_SopToEspresso( char * pSop ); +static char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover ); +static pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Minimizes SOP representations using Espresso.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsLogic(pNtk) ); + // convert the network to have SOPs + if ( Abc_NtkHasMapping(pNtk) ) + Abc_NtkMapToSop(pNtk); + else if ( Abc_NtkHasBdd(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Abc_NtkEspresso(): Converting to SOPs has failed.\n" ); + return; + } + } + // minimize SOPs of all nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( i ) Abc_NodeEspresso( pNode ); +} + +/**Function************************************************************* + + Synopsis [Minimizes SOP representation of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeEspresso( Abc_Obj_t * pNode ) +{ + extern void define_cube_size( int n ); + pset_family Cover; + int fCompl; + + assert( Abc_ObjIsNode(pNode) ); + // define the cube for this node + define_cube_size( Abc_ObjFaninNum(pNode) ); + // create the Espresso cover + fCompl = Abc_SopIsComplement( pNode->pData ); + Cover = Abc_SopToEspresso( pNode->pData ); + // perform minimization + Cover = Abc_EspressoMinimize( Cover, NULL ); // deletes also cover + // convert back onto the node's SOP representation + pNode->pData = Abc_SopFromEspresso( pNode->pNtk->pManFunc, Cover ); + if ( fCompl ) Abc_SopComplement( pNode->pData ); + sf_free(Cover); +} + +/**Function************************************************************* + + Synopsis [Converts SOP in ABC into SOP representation in Espresso.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +pset_family Abc_SopToEspresso( char * pSop ) +{ + char * pCube; + pset_family Cover; + pset set; + int nCubes, nVars, Value, v; + + if ( pSop == NULL ) + return NULL; + + nVars = Abc_SopGetVarNum(pSop); + nCubes = Abc_SopGetCubeNum(pSop); + assert( cube.size == 2 * nVars ); + + if ( Abc_SopIsConst0(pSop) ) + { + Cover = sf_new(0, cube.size); + return Cover; + } + if ( Abc_SopIsConst1(pSop) ) + { + Cover = sf_new(1, cube.size); + set = GETSET(Cover, Cover->count++); + set_copy( set, cube.fullset ); + return Cover; + } + + // create the cover + Cover = sf_new(nCubes, cube.size); + // fill in the cubes + Abc_SopForEachCube( pSop, nVars, pCube ) + { + set = GETSET(Cover, Cover->count++); + set_copy( set, cube.fullset ); + Abc_CubeForEachVar( pCube, Value, v ) + { + if ( Value == '0' ) + set_remove(set, 2*v+1); + else if ( Value == '1' ) + set_remove(set, 2*v); + } + } + return Cover; +} + +/**Function************************************************************* + + Synopsis [Converts SOP representation in Espresso into SOP in ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover ) +{ + pset set; + char * pSop, * pCube; + int Lit, nVars, nCubes, i, k; + + nVars = Cover->sf_size/2; + nCubes = Cover->count; + + pSop = Abc_SopStart( pMan, nCubes, nVars ); + + // go through the cubes + i = 0; + Abc_SopForEachCube( pSop, nVars, pCube ) + { + set = GETSET(Cover, i++); + for ( k = 0; k < nVars; k++ ) + { + Lit = GETINPUT(set, k); + if ( Lit == ZERO ) + pCube[k] = '0'; + else if ( Lit == ONE ) + pCube[k] = '1'; + } + } + return pSop; +} + + +/**Function************************************************************* + + Synopsis [Minimizes the cover using Espresso.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset ) +{ + pset_family pOffset; + int fNewDcset, i; + int fSimple = 0; + int fSparse = 0; + + if ( fSimple ) + { + for ( i = 0; i < cube.num_vars; i++ ) + pOnset = d1merge( pOnset, i ); + pOnset = sf_contain( pOnset ); + return pOnset; + } + + // create the dcset + fNewDcset = (pDcset == NULL); + if ( pDcset == NULL ) + pDcset = sf_new( 1, cube.size ); + pDcset->wsize = pOnset->wsize; + pDcset->sf_size = pOnset->sf_size; + + // derive the offset + if ( pDcset->sf_size == 0 || pDcset->count == 0 ) + pOffset = complement(cube1list(pOnset)); + else + pOffset = complement(cube2list(pOnset, pDcset)); + + // perform minimization + skip_make_sparse = !fSparse; + pOnset = espresso( pOnset, pDcset, pOffset ); + + // free covers + sf_free( pOffset ); + if ( fNewDcset ) + sf_free( pDcset ); + return pOnset; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcExtract.c b/abc70930/src/base/abci/abcExtract.c new file mode 100644 index 00000000..52ea03a3 --- /dev/null +++ b/abc70930/src/base/abci/abcExtract.c @@ -0,0 +1,51 @@ +/**CFile**************************************************************** + + FileName [abcMvCost.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Calculating the cost of one MV block.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMvCost.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvCostTest( Abc_Ntk_t * pNtk ) +{ + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcFpga.c b/abc70930/src/base/abci/abcFpga.c new file mode 100644 index 00000000..3bc9fbed --- /dev/null +++ b/abc70930/src/base/abci/abcFpga.c @@ -0,0 +1,278 @@ +/**CFile**************************************************************** + + FileName [abcFpga.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFpga.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose ); +static Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ); +static Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Interface with the FPGA mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose ) +{ + int fShowSwitching = 1; + Abc_Ntk_t * pNtkNew; + Fpga_Man_t * pMan; + Vec_Int_t * vSwitching; + float * pSwitching = NULL; + + assert( Abc_NtkIsStrash(pNtk) ); + + // print a warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing FPGA mapping with choices.\n" ); + + // compute switching activity + fShowSwitching |= fSwitching; + if ( fShowSwitching ) + { + extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ); + vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 ); + pSwitching = (float *)vSwitching->pArray; + } + + // perform FPGA mapping + pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, fLatchPaths, fVerbose ); + if ( pSwitching ) Vec_IntFree( vSwitching ); + if ( pMan == NULL ) + return NULL; + Fpga_ManSetSwitching( pMan, fSwitching ); + Fpga_ManSetLatchPaths( pMan, fLatchPaths ); + Fpga_ManSetLatchNum( pMan, Abc_NtkLatchNum(pNtk) ); + Fpga_ManSetDelayTarget( pMan, DelayTarget ); + if ( !Fpga_Mapping( pMan ) ) + { + Fpga_ManFree( pMan ); + return NULL; + } + + // transform the result of mapping into a BDD network + pNtkNew = Abc_NtkFromFpga( pMan, pNtk ); + if ( pNtkNew == NULL ) + return NULL; + Fpga_ManFree( pMan ); + + // make the network minimum base + Abc_NtkMinimumBase( pNtkNew ); + + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkFpga: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Load the network into FPGA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose ) +{ + Fpga_Man_t * pMan; + ProgressBar * pProgress; + Fpga_Node_t * pNodeFpga; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanin, * pPrev; + float * pfArrivals; + int i; + + assert( Abc_NtkIsStrash(pNtk) ); + + // start the mapping manager and set its parameters + pMan = Fpga_ManCreate( Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), fVerbose ); + if ( pMan == NULL ) + return NULL; + Fpga_ManSetAreaRecovery( pMan, fRecovery ); + Fpga_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); + pfArrivals = Abc_NtkGetCiArrivalFloats(pNtk); + if ( fLatchPaths ) + { + for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) + pfArrivals[i] = -FPGA_FLOAT_LARGE; + } + Fpga_ManSetInputArrivals( pMan, pfArrivals ); + + // create PIs and remember them in the old nodes + Abc_NtkCleanCopy( pNtk ); + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan); + Abc_NtkForEachCi( pNtk, pNode, i ) + { + pNodeFpga = Fpga_ManReadInputs(pMan)[i]; + pNode->pCopy = (Abc_Obj_t *)pNodeFpga; + if ( pSwitching ) + Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] ); + } + + // load the AIG into the mapper + vNodes = Abc_AigDfs( pNtk, 0, 0 ); + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // add the node to the mapper + pNodeFpga = Fpga_NodeAnd( pMan, + Fpga_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), + Fpga_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); + assert( pNode->pCopy == NULL ); + // remember the node + pNode->pCopy = (Abc_Obj_t *)pNodeFpga; + if ( pSwitching ) + Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] ); + // set up the choice node + if ( Abc_AigNodeIsChoice( pNode ) ) + for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) + { + Fpga_NodeSetNextE( (Fpga_Node_t *)pPrev->pCopy, (Fpga_Node_t *)pFanin->pCopy ); + Fpga_NodeSetRepr( (Fpga_Node_t *)pFanin->pCopy, (Fpga_Node_t *)pNode->pCopy ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + + // set the primary outputs without copying the phase + Abc_NtkForEachCo( pNtk, pNode, i ) + Fpga_ManReadOutputs(pMan)[i] = (Fpga_Node_t *)Abc_ObjFanin0(pNode)->pCopy; + return pMan; +} + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pNodeNew; + int i, nDupGates; + // create the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + // make the mapper point to the new network + Fpga_CutsCleanSign( pMan ); + Fpga_ManCleanData0( pMan ); + Abc_NtkForEachCi( pNtk, pNode, i ) + Fpga_NodeSetData0( Fpga_ManReadInputs(pMan)[i], (char *)pNode->pCopy ); + // set the constant node +// if ( Fpga_NodeReadRefs(Fpga_ManReadConst1(pMan)) > 0 ) + Fpga_NodeSetData0( Fpga_ManReadConst1(pMan), (char *)Abc_NtkCreateNodeConst1(pNtkNew) ); + // process the nodes in topological order + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNodeNew = Abc_NodeFromFpga_rec( pNtkNew, Fpga_ManReadOutputs(pMan)[i] ); + assert( !Abc_ObjIsComplement(pNodeNew) ); + Abc_ObjFanin0(pNode)->pCopy = pNodeNew; + } + Extra_ProgressBarStop( pProgress ); + // finalize the new network + Abc_NtkFinalize( pNtk, pNtkNew ); + // remove the constant node if not used + pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0(Fpga_ManReadConst1(pMan)); + if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) + Abc_NtkDeleteObj( pNodeNew ); + // decouple the PO driver nodes to reduce the number of levels + nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); +// if ( nDupGates && Fpga_ManReadVerbose(pMan) ) +// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Derive one node after FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga ) +{ + Fpga_Cut_t * pCutBest; + Fpga_Node_t ** ppLeaves; + Abc_Obj_t * pNodeNew; + int i, nLeaves; + assert( !Fpga_IsComplement(pNodeFpga) ); + // return if the result if known + pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0( pNodeFpga ); + if ( pNodeNew ) + return pNodeNew; + assert( Fpga_NodeIsAnd(pNodeFpga) ); + // get the parameters of the best cut + pCutBest = Fpga_NodeReadCutBest( pNodeFpga ); + ppLeaves = Fpga_CutReadLeaves( pCutBest ); + nLeaves = Fpga_CutReadLeavesNum( pCutBest ); + // create a new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < nLeaves; i++ ) + Abc_ObjAddFanin( pNodeNew, Abc_NodeFromFpga_rec(pNtkNew, ppLeaves[i]) ); + // derive the function of this node + pNodeNew->pData = Fpga_TruthsCutBdd( pNtkNew->pManFunc, pCutBest ); Cudd_Ref( pNodeNew->pData ); + Fpga_NodeSetData0( pNodeFpga, (char *)pNodeNew ); + return pNodeNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcFpgaFast.c b/abc70930/src/base/abci/abcFpgaFast.c new file mode 100644 index 00000000..356b855e --- /dev/null +++ b/abc70930/src/base/abci/abcFpgaFast.c @@ -0,0 +1,190 @@ +/**CFile**************************************************************** + + FileName [abcFpgaFast.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Fast FPGA mapper.] + + Author [Sungmin Cho] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFpgaFast.c,v 1.00 2006/09/02 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ); + +static Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ); +static Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes ); + +static inline void Abc_ObjSetIvy2Abc( Ivy_Man_t * p, int IvyId, Abc_Obj_t * pObjAbc ) { assert(Vec_PtrEntry(p->pCopy, IvyId) == NULL); assert(!Abc_ObjIsComplement(pObjAbc)); Vec_PtrWriteEntry( p->pCopy, IvyId, pObjAbc ); } +static inline Abc_Obj_t * Abc_ObjGetIvy2Abc( Ivy_Man_t * p, int IvyId ) { return Vec_PtrEntry( p->pCopy, IvyId ); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs fast FPGA mapping of the network.] + + Description [Takes the AIG to be mapped, the LUT size, and verbosity + flag. Produces the new network by fast FPGA mapping of the current + network. If the current network in ABC in not an AIG, the user should + run command "strash" to make sure that the current network into an AIG + before calling this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose ) +{ + Ivy_Man_t * pMan; + Abc_Ntk_t * pNtkNew; + // make sure the network is an AIG + assert( Abc_NtkIsStrash(pNtk) ); + // convert the network into the AIG + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + // perform fast FPGA mapping + Ivy_FastMapPerform( pMan, nLutSize, fRecovery, fVerbose ); + // convert back into the ABC network + pNtkNew = Ivy_ManFpgaToAbc( pNtk, pMan ); + Ivy_FastMapStop( pMan ); + Ivy_ManStop( pMan ); + // make sure that the final network passes the test + if ( pNtkNew != NULL && !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkFastMap: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Constructs the ABC network after mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjAbc, * pObj; + Ivy_Obj_t * pObjIvy; + Vec_Int_t * vNodes; + int i; + // start mapping from Ivy into Abc + pMan->pCopy = Vec_PtrStart( Ivy_ManObjIdMax(pMan) + 1 ); + // start the new ABC network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Abc_ObjSetIvy2Abc( pMan, Ivy_ManConst1(pMan)->Id, Abc_NtkCreateNodeConst1(pNtkNew) ); + Abc_NtkForEachCi( pNtkNew, pObjAbc, i ) + Abc_ObjSetIvy2Abc( pMan, Ivy_ManPi(pMan, i)->Id, pObjAbc ); + // recursively construct the network + vNodes = Vec_IntAlloc( 100 ); + Ivy_ManForEachPo( pMan, pObjIvy, i ) + { + // get the new ABC node corresponding to the old fanin of the PO in IVY + pObjAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ObjFanin0(pObjIvy), vNodes ); + // consider the case of complemented fanin of the PO + if ( Ivy_ObjFaninC0(pObjIvy) ) // complement + { + if ( Abc_ObjIsCi(pObjAbc) ) + pObjAbc = Abc_NtkCreateNodeInv( pNtkNew, pObjAbc ); + else + { + // clone the node + pObj = Abc_NtkCloneObj( pObjAbc ); + // set complemented functions + pObj->pData = Hop_Not( pObjAbc->pData ); + // return the new node + pObjAbc = pObj; + } + } + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjAbc ); + } + Vec_IntFree( vNodes ); + Vec_PtrFree( pMan->pCopy ); + pMan->pCopy = NULL; + // remove dangling nodes + Abc_NtkCleanup( pNtkNew, 0 ); + // fix CIs feeding directly into COs + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Recursively construct the new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes ) +{ + Vec_Int_t Supp, * vSupp = &Supp; + Abc_Obj_t * pObjAbc, * pFaninAbc; + Ivy_Obj_t * pNodeIvy; + int i, Entry; + // skip the node if it is a constant or already processed + pObjAbc = Abc_ObjGetIvy2Abc( pMan, pObjIvy->Id ); + if ( pObjAbc ) + return pObjAbc; + assert( Ivy_ObjIsAnd(pObjIvy) || Ivy_ObjIsExor(pObjIvy) ); + // get the support of K-LUT + Ivy_FastMapReadSupp( pMan, pObjIvy, vSupp ); + // create new ABC node and its fanins + pObjAbc = Abc_NtkCreateNode( pNtkNew ); + Vec_IntForEachEntry( vSupp, Entry, i ) + { + pFaninAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ManObj(pMan, Entry), vNodes ); + Abc_ObjAddFanin( pObjAbc, pFaninAbc ); + } + // collect the nodes used in the cut + Ivy_ManCollectCut( pMan, pObjIvy, vSupp, vNodes ); + // create the local function + Ivy_ManForEachNodeVec( pMan, vNodes, pNodeIvy, i ) + { + if ( i < Vec_IntSize(vSupp) ) + pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_IthVar( pNtkNew->pManFunc, i ); + else + pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_And( pNtkNew->pManFunc, (Hop_Obj_t *)Ivy_ObjChild0Equiv(pNodeIvy), (Hop_Obj_t *)Ivy_ObjChild1Equiv(pNodeIvy) ); + } + // set the local function + pObjAbc->pData = (Abc_Obj_t *)pObjIvy->pEquiv; + // set the node + Abc_ObjSetIvy2Abc( pMan, pObjIvy->Id, pObjAbc ); + return pObjAbc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcFraig.c b/abc70930/src/base/abci/abcFraig.c new file mode 100644 index 00000000..be8a25f1 --- /dev/null +++ b/abc70930/src/base/abci/abcFraig.c @@ -0,0 +1,803 @@ +/**CFile**************************************************************** + + FileName [abcFraig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures interfacing with the FRAIG package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFraig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" +#include "main.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); +static Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig ); +static void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs ); +extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc ); +static void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); + +static int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk ); +static void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +static Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ) +{ + Fraig_Params_t * pPars = pParams; + Abc_Ntk_t * pNtkNew; + Fraig_Man_t * pMan; + // check if EXDC is present + if ( fExdc && pNtk->pExdc == NULL ) + fExdc = 0, printf( "Warning: Networks has no EXDC.\n" ); + // perform fraiging + pMan = Abc_NtkToFraig( pNtk, pParams, fAllNodes, fExdc ); + // add algebraic choices +// if ( pPars->fChoicing ) +// Fraig_ManAddChoices( pMan, 0, 6 ); + // prove the miter if asked to + if ( pPars->fTryProve ) + Fraig_ManProveMiter( pMan ); + // reconstruct FRAIG in the new network + if ( fExdc ) + pNtkNew = Abc_NtkFromFraig2( pMan, pNtk ); + else + pNtkNew = Abc_NtkFromFraig( pMan, pNtk ); + Fraig_ManFree( pMan ); + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkFraig: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transforms the strashed network into FRAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ) +{ + int fInternal = ((Fraig_Params_t *)pParams)->fInternal; + Fraig_Man_t * pMan; + ProgressBar * pProgress; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + + assert( Abc_NtkIsStrash(pNtk) ); + + // create the FRAIG manager + pMan = Fraig_ManCreate( pParams ); + + // map the constant node + Abc_NtkCleanCopy( pNtk ); + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan); + // create PIs and remember them in the old nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, i); + + // perform strashing + vNodes = Abc_AigDfs( pNtk, fAllNodes, 0 ); + if ( !fInternal ) + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; + if ( !fInternal ) + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNode->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan, + Fraig_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), + Fraig_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); + } + if ( !fInternal ) + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + + // use EXDC to change the mapping of nodes into FRAIG nodes + if ( fExdc ) + Abc_NtkFraigRemapUsingExdc( pMan, pNtk ); + + // set the primary outputs + Abc_NtkForEachCo( pNtk, pNode, i ) + Fraig_ManSetPo( pMan, (Fraig_Node_t *)Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Derives EXDC node for the given network.] + + Description [Assumes that EXDCs of all POs are the same. + Returns the EXDC of the first PO.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc ) +{ + Abc_Ntk_t * pNtkStrash; + Abc_Obj_t * pObj; + Fraig_Node_t * gResult; + char ** ppNames; + int i, k; + // strash the EXDC network + pNtkStrash = Abc_NtkStrash( pNtkExdc, 0, 0, 0 ); + Abc_NtkCleanCopy( pNtkStrash ); + Abc_AigConst1(pNtkStrash)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan); + // set the mapping of the PI nodes + ppNames = Abc_NtkCollectCioNames( pNtkMain, 0 ); + Abc_NtkForEachCi( pNtkStrash, pObj, i ) + { + for ( k = 0; k < Abc_NtkCiNum(pNtkMain); k++ ) + if ( strcmp( Abc_ObjName(pObj), ppNames[k] ) == 0 ) + { + pObj->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, k); + break; + } + assert( pObj->pCopy != NULL ); + } + free( ppNames ); + // build FRAIG for each node + Abc_AigForEachAnd( pNtkStrash, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan, + Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ), + Fraig_NotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ) ); + // get the EXDC to be returned + pObj = Abc_NtkPo( pNtkStrash, 0 ); + gResult = Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); + Abc_NtkDelete( pNtkStrash ); + return gResult; +} + + +/**Function************************************************************* + + Synopsis [Changes mapping of the old nodes into FRAIG nodes using EXDC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + Fraig_Node_t * gNodeNew, * gNodeExdc; + stmm_table * tTable; + stmm_generator * gen; + Abc_Obj_t * pNode, * pNodeBest; + Abc_Obj_t * pClass, ** ppSlot; + Vec_Ptr_t * vNexts; + int i; + + // get the global don't-cares + assert( pNtk->pExdc ); + gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc ); + + // save the next pointers + vNexts = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + Vec_PtrWriteEntry( vNexts, pNode->Id, pNode->pNext ); + + // find the classes of AIG nodes which have FRAIG nodes assigned + Abc_NtkCleanNext( pNtk ); + tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( pNode->pCopy ) + { + gNodeNew = Fraig_NodeAnd( pMan, (Fraig_Node_t *)pNode->pCopy, Fraig_Not(gNodeExdc) ); + if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(gNodeNew), (char ***)&ppSlot ) ) + *ppSlot = NULL; + pNode->pNext = *ppSlot; + *ppSlot = pNode; + } + + // for reach non-trival class, find the node with minimum level, and replace other nodes by it + Abc_AigSetNodePhases( pNtk ); + stmm_foreach_item( tTable, gen, (char **)&gNodeNew, (char **)&pClass ) + { + if ( pClass->pNext == NULL ) + continue; + // find the node with minimum level + pNodeBest = pClass; + for ( pNode = pClass->pNext; pNode; pNode = pNode->pNext ) + if ( pNodeBest->Level > pNode->Level ) + pNodeBest = pNode; + // remap the class nodes + for ( pNode = pClass; pNode; pNode = pNode->pNext ) + pNode->pCopy = Abc_ObjNotCond( pNodeBest->pCopy, pNode->fPhase ^ pNodeBest->fPhase ); + } + stmm_free_table( tTable ); + + // restore the next pointers + Abc_NtkCleanNext( pNtk ); + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->pNext = Vec_PtrEntry( vNexts, pNode->Id ); + Vec_PtrFree( vNexts ); +} + +/**Function************************************************************* + + Synopsis [Transforms FRAIG into strashed network with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pNodeNew; + int i; + // create the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // make the mapper point to the new network + Abc_NtkForEachCi( pNtk, pNode, i ) + Fraig_NodeSetData1( Fraig_ManReadIthVar(pMan, i), (Fraig_Node_t *)pNode->pCopy ); + // set the constant node + Fraig_NodeSetData1( Fraig_ManReadConst1(pMan), (Fraig_Node_t *)Abc_AigConst1(pNtkNew) ); + // process the nodes in topological order + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNodeNew = Abc_NodeFromFraig_rec( pNtkNew, Fraig_ManReadOutputs(pMan)[i] ); + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + } + Extra_ProgressBarStop( pProgress ); + Abc_NtkReassignIds( pNtkNew ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transforms into AIG one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig ) +{ + Abc_Obj_t * pRes, * pRes0, * pRes1, * pResMin, * pResCur; + Fraig_Node_t * pNodeTemp, * pNodeFraigR = Fraig_Regular(pNodeFraig); + void ** ppTail; + // check if the node was already considered + if ( pRes = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeFraigR) ) + return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) ); + // solve the children + pRes0 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadOne(pNodeFraigR) ); + pRes1 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadTwo(pNodeFraigR) ); + // derive the new node + pRes = Abc_AigAnd( pNtkNew->pManFunc, pRes0, pRes1 ); + pRes->fPhase = Fraig_NodeReadSimInv( pNodeFraigR ); + // if the node has an equivalence class, find its representative + if ( Fraig_NodeReadRepr(pNodeFraigR) == NULL && Fraig_NodeReadNextE(pNodeFraigR) != NULL ) + { + // go through the FRAIG nodes belonging to this equivalence class + // and find the representative node (the node with the smallest level) + pResMin = pRes; + for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) ) + { + assert( Fraig_NodeReadData1(pNodeTemp) == NULL ); + pResCur = Abc_NodeFromFraig_rec( pNtkNew, pNodeTemp ); + if ( pResMin->Level > pResCur->Level ) + pResMin = pResCur; + } + // link the nodes in such a way that representative goes first + ppTail = &pResMin->pData; + if ( pRes != pResMin ) + { + *ppTail = pRes; + ppTail = &pRes->pData; + } + for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) ) + { + pResCur = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeTemp); + assert( pResCur ); + if ( pResMin == pResCur ) + continue; + *ppTail = pResCur; + ppTail = &pResCur->pData; + } + assert( *ppTail == NULL ); + + // update the phase of the node + pRes = Abc_ObjNotCond( pResMin, (pRes->fPhase ^ pResMin->fPhase) ); + } + Fraig_NodeSetData1( pNodeFraigR, (Fraig_Node_t *)pRes ); + return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) ); +} + +/**Function************************************************************* + + Synopsis [Transforms FRAIG into strashed network without choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + stmm_table * tTable; + Vec_Ptr_t * vNodeReprs; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pRepr, ** ppSlot; + int i; + + // map the nodes into their lowest level representives + tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); + pNode = Abc_AigConst1(pNtk); + if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) + *ppSlot = pNode; + Abc_NtkForEachCi( pNtk, pNode, i ) + if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) + *ppSlot = pNode; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( pNode->pCopy ) + { + if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) + *ppSlot = pNode; + else if ( (*ppSlot)->Level > pNode->Level ) + *ppSlot = pNode; + } + // save representatives for each node + vNodeReprs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( pNode->pCopy ) + { + if ( !stmm_lookup( tTable, (char *)Fraig_Regular(pNode->pCopy), (char **)&pRepr ) ) + assert( 0 ); + if ( pNode != pRepr ) + Vec_PtrWriteEntry( vNodeReprs, pNode->Id, pRepr ); + } + stmm_free_table( tTable ); + + // create the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + + // perform strashing + Abc_AigSetNodePhases( pNtk ); + Abc_NtkIncrementTravId( pNtk ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs ); + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodeReprs ); + + // finalize the network + Abc_NtkFinalize( pNtk, pNtkNew ); + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Transforms into AIG one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs ) +{ + Abc_Obj_t * pRepr; + // skip the PIs and constants + if ( Abc_ObjFaninNum(pNode) < 2 ) + return; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + assert( Abc_ObjIsNode( pNode ) ); + // get the node's representative + if ( pRepr = Vec_PtrEntry(vNodeReprs, pNode->Id) ) + { + Abc_NtkFromFraig2_rec( pNtkNew, pRepr, vNodeReprs ); + pNode->pCopy = Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pNode->fPhase ); + return; + } + Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs ); + Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin1(pNode), vNodeReprs ); + pNode->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); +} + + + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + printf( "Abc_NtkFraigTrust: Trust mode works for netlists and logic SOP networks.\n" ); + return NULL; + } + + if ( !Abc_NtkFraigTrustCheck(pNtk) ) + { + printf( "Abc_NtkFraigTrust: The network does not look like an AIG with choice nodes.\n" ); + return NULL; + } + + // perform strashing + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + Abc_NtkFraigTrustOne( pNtk, pNtkNew ); + Abc_NtkFinalize( pNtk, pNtkNew ); + Abc_NtkReassignIds( pNtkNew ); + + // print a warning about choice nodes + printf( "Warning: The resulting AIG contains %d choice nodes.\n", Abc_NtkGetChoiceNum( pNtkNew ) ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkFraigTrust: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Checks whether the node can be processed in the trust mode.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nFanins; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + nFanins = Abc_ObjFaninNum(pNode); + if ( nFanins < 2 ) + continue; + if ( nFanins == 2 && Abc_SopIsAndType(pNode->pData) ) + continue; + if ( !Abc_SopIsOrType(pNode->pData) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pNodeNew, * pObj; + int i; + + // perform strashing + vNodes = Abc_NtkDfs( pNtk, 0 ); + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // get the node + assert( Abc_ObjIsNode(pNode) ); + // strash the node + pNodeNew = Abc_NodeFraigTrust( pNtkNew, pNode ); + // get the old object + if ( Abc_NtkIsNetlist(pNtk) ) + pObj = Abc_ObjFanout0( pNode ); // the fanout net + else + pObj = pNode; // the node itself + // make sure the node is not yet strashed + assert( pObj->pCopy == NULL ); + // mark the old object with the new AIG node + pObj->pCopy = pNodeNew; + } + Vec_PtrFree( vNodes ); + Extra_ProgressBarStop( pProgress ); +} + +/**Function************************************************************* + + Synopsis [Transforms one node into a FRAIG in the trust mode.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pSum, * pFanin; + void ** ppTail; + int i, nFanins, fCompl; + + assert( Abc_ObjIsNode(pNode) ); + // get the number of node's fanins + nFanins = Abc_ObjFaninNum( pNode ); + assert( nFanins == Abc_SopGetVarNum(pNode->pData) ); + // check if it is a constant + if ( nFanins == 0 ) + return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Abc_SopIsConst0(pNode->pData) ); + if ( nFanins == 1 ) + return Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_SopIsInv(pNode->pData) ); + if ( nFanins == 2 && Abc_SopIsAndType(pNode->pData) ) + return Abc_AigAnd( pNtkNew->pManFunc, + Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, !Abc_SopGetIthCareLit(pNode->pData,0) ), + Abc_ObjNotCond( Abc_ObjFanin1(pNode)->pCopy, !Abc_SopGetIthCareLit(pNode->pData,1) ) ); + assert( Abc_SopIsOrType(pNode->pData) ); + fCompl = Abc_SopGetIthCareLit(pNode->pData,0); + // get the root of the choice node (the first fanin) + pSum = Abc_ObjFanin0(pNode)->pCopy; + // connect other fanins + ppTail = &pSum->pData; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( i == 0 ) + continue; + *ppTail = pFanin->pCopy; + ppTail = &pFanin->pCopy->pData; + // set the complemented bit of this cut + if ( fCompl ^ Abc_SopGetIthCareLit(pNode->pData, i) ) + pFanin->pCopy->fPhase = 1; + } + assert( *ppTail == NULL ); + return pSum; +} + + + + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd ) +{ + Vec_Ptr_t * vStore; + Abc_Ntk_t * pNtk; + // create the network to be stored + pNtk = Abc_NtkStrash( pNtkAdd, 0, 0, 0 ); + if ( pNtk == NULL ) + { + printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" ); + return 0; + } + // get the network currently stored + vStore = Abc_FrameReadStore(); + if ( Vec_PtrSize(vStore) > 0 ) + { + // check that the networks have the same PIs + // reorder PIs of pNtk2 according to pNtk1 + if ( !Abc_NtkCompareSignals( pNtk, Vec_PtrEntry(vStore, 0), 1, 1 ) ) + { + printf( "Trying to store the network with different primary inputs.\n" ); + printf( "The previously stored networks are deleted and this one is added.\n" ); + Abc_NtkFraigStoreClean(); + } + } + Vec_PtrPush( vStore, pNtk ); +// printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pNtk) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFraigRestore() +{ + extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams ); + Fraig_Params_t Params; + Vec_Ptr_t * vStore; + Abc_Ntk_t * pNtk, * pFraig; + int nWords1, nWords2, nWordsMin; + int clk = clock(); + + // get the stored network + vStore = Abc_FrameReadStore(); + if ( Vec_PtrSize(vStore) == 0 ) + { + printf( "There are no network currently in storage.\n" ); + return NULL; + } +// printf( "Currently stored %d networks will be fraiged.\n", Vec_PtrSize(vStore) ); + pNtk = Vec_PtrEntry( vStore, 0 ); + + // swap the first and last network + // this should lead to the primary choice being "better" because of synthesis + pNtk = Vec_PtrPop( vStore ); + Vec_PtrPush( vStore, Vec_PtrEntry(vStore,0) ); + Vec_PtrWriteEntry( vStore, 0, pNtk ); + + // to determine the number of simulation patterns + // use the following strategy + // at least 64 words (32 words random and 32 words dynamic) + // no more than 256M for one circuit (128M + 128M) + nWords1 = 32; + nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk)); + nWordsMin = ABC_MIN( nWords1, nWords2 ); + + // set parameters for fraiging + Fraig_ParamsSetDefault( &Params ); + Params.nPatsRand = nWordsMin * 32; // the number of words of random simulation info + Params.nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info + Params.nBTLimit = 1000; // the max number of backtracks to perform + Params.fFuncRed = 1; // performs only one level hashing + Params.fFeedBack = 1; // enables solver feedback + Params.fDist1Pats = 1; // enables distance-1 patterns + Params.fDoSparse = 1; // performs equiv tests for sparse functions + Params.fChoicing = 1; // enables recording structural choices + Params.fTryProve = 0; // tries to solve the final miter + Params.fVerbose = 0; // the verbosiness flag + + // perform partitioned computation of structural choices + pFraig = Abc_NtkFraigPartitioned( vStore, &Params ); + Abc_NtkFraigStoreClean(); +//PRT( "Total choicing time", clock() - clk ); + return pFraig; +} + +/**Function************************************************************* + + Synopsis [Interfaces the network with the FRAIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigStoreClean() +{ + Vec_Ptr_t * vStore; + Abc_Ntk_t * pNtk; + int i; + vStore = Abc_FrameReadStore(); + Vec_PtrForEachEntry( vStore, pNtk, i ) + Abc_NtkDelete( pNtk ); + Vec_PtrClear( vStore ); +} + +/**Function************************************************************* + + Synopsis [Checks the correctness of stored networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigStoreCheck( Abc_Ntk_t * pFraig ) +{ + Abc_Obj_t * pNode0, * pNode1; + int nPoOrig, nPoFinal, nStored; + int i, k; + // check that the PO functions are correct + nPoFinal = Abc_NtkPoNum(pFraig); + nStored = Abc_FrameReadStoreSize(); + assert( nPoFinal % nStored == 0 ); + nPoOrig = nPoFinal / nStored; + for ( i = 0; i < nPoOrig; i++ ) + { + pNode0 = Abc_ObjFanin0( Abc_NtkPo(pFraig, i) ); + for ( k = 1; k < nStored; k++ ) + { + pNode1 = Abc_ObjFanin0( Abc_NtkPo(pFraig, k*nPoOrig+i) ); + if ( pNode0 != pNode1 ) + printf( "Verification for PO #%d of network #%d has failed. The PO function is not used.\n", i+1, k+1 ); + } + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcFxu.c b/abc70930/src/base/abci/abcFxu.c new file mode 100644 index 00000000..45515dd1 --- /dev/null +++ b/abc70930/src/base/abci/abcFxu.c @@ -0,0 +1,260 @@ +/**CFile**************************************************************** + + FileName [abcFxu.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface with the fast extract package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFxu.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fxu.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk ); +static void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); +static void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Performs fast_extract on the current network.] + + Description [Takes the network and the maximum number of nodes to extract. + Uses the concurrent double-cube and single cube divisor extraction procedure. + Modifies the network in the end, after extracting all nodes. Note that + Ntk_NetworkSweep() may increase the performance of this procedure because + the single-literal nodes will not be created in the sparse matrix. Returns 1 + if the network has been changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) +{ + assert( Abc_NtkIsLogic(pNtk) ); + // if the network is already in the SOP form, it may come from BLIF file + // and it may not be SCC-free, in which case FXU will not work correctly + if ( Abc_NtkIsSopLogic(pNtk) ) + { // to make sure the SOPs are SCC-free +// Abc_NtkSopToBdd(pNtk); +// Abc_NtkBddToSop(pNtk); + } + // get the network in the SOP form + if ( !Abc_NtkToSop(pNtk, 0) ) + { + printf( "Abc_NtkFastExtract(): Converting to SOPs has failed.\n" ); + return 0; + } + // check if the network meets the requirements + if ( !Abc_NtkFxuCheck(pNtk) ) + { + printf( "Abc_NtkFastExtract: Nodes have duplicated or complemented fanins. FXU is not performed.\n" ); + return 0; + } + // sweep removes useless nodes + Abc_NtkCleanup( pNtk, 0 ); + // collect information about the covers + Abc_NtkFxuCollectInfo( pNtk, p ); + // call the fast extract procedure + if ( Fxu_FastExtract(p) > 0 ) + { + // update the network + Abc_NtkFxuReconstruct( pNtk, p ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtk ) ) + printf( "Abc_NtkFastExtract: The network check has failed.\n" ); + return 1; + } + else + printf( "Warning: The network has not been changed by \"fx\".\n" ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Makes sure the nodes do not have complemented and duplicated fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pFanin1, * pFanin2; + int n, i, k; + Abc_NtkForEachNode( pNtk, pNode, n ) + { + Abc_ObjForEachFanin( pNode, pFanin1, i ) + { + if ( i < 2 && Abc_ObjFaninC(pNode, i) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin2, k ) + { + if ( i == k ) + continue; + if ( pFanin1 == pFanin2 ) + return 0; + } + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Collect information about the network for fast_extract.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) +{ + Abc_Obj_t * pNode; + int i; + // add information to the manager + p->pManSop = pNtk->pManFunc; + p->vSops = Vec_PtrAlloc(0); + p->vFanins = Vec_PtrAlloc(0); + p->vSopsNew = Vec_PtrAlloc(0); + p->vFaninsNew = Vec_PtrAlloc(0); + Vec_PtrFill( p->vSops, Abc_NtkObjNumMax(pNtk), NULL ); + Vec_PtrFill( p->vFanins, Abc_NtkObjNumMax(pNtk), NULL ); + Vec_PtrFill( p->vSopsNew, Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL ); + Vec_PtrFill( p->vFaninsNew, Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL ); + // add SOPs and fanin array + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_SopGetVarNum(pNode->pData) < 2 ) + continue; + if ( Abc_SopGetCubeNum(pNode->pData) < 1 ) + continue; + p->vSops->pArray[i] = pNode->pData; + p->vFanins->pArray[i] = &pNode->vFanins; + } + p->nNodesOld = Abc_NtkObjNumMax(pNtk); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFxuFreeInfo( Fxu_Data_t * p ) +{ + int i; + // free the arrays of new fanins + if ( p->vFaninsNew ) + for ( i = 0; i < p->vFaninsNew->nSize; i++ ) + if ( p->vFaninsNew->pArray[i] ) + Vec_IntFree( p->vFaninsNew->pArray[i] ); + // free the arrays + if ( p->vSops ) Vec_PtrFree( p->vSops ); + if ( p->vSopsNew ) Vec_PtrFree( p->vSopsNew ); + if ( p->vFanins ) Vec_PtrFree( p->vFanins ); + if ( p->vFaninsNew ) Vec_PtrFree( p->vFaninsNew ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Recostructs the network after FX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) +{ + Vec_Int_t * vFanins; + Abc_Obj_t * pNode, * pFanin; + int i, k; + + assert( p->vFanins->nSize < p->vFaninsNew->nSize ); + // create the new nodes + for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ ) + { + // start the node + pNode = Abc_NtkCreateNode( pNtk ); + assert( i == (int)pNode->Id ); + } + // update the old nodes + for ( i = 0; i < p->vFanins->nSize; i++ ) + { + // the new array of fanins + vFanins = p->vFaninsNew->pArray[i]; + if ( vFanins == NULL ) + continue; + // remove old fanins + pNode = Abc_NtkObj( pNtk, i ); + Abc_ObjRemoveFanins( pNode ); + // add new fanins + vFanins = p->vFaninsNew->pArray[i]; + for ( k = 0; k < vFanins->nSize; k++ ) + { + pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] ); + Abc_ObjAddFanin( pNode, pFanin ); + } + pNode->pData = p->vSopsNew->pArray[i]; + assert( pNode->pData != NULL ); + } + // set up the new nodes + for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ ) + { + // get the new node + pNode = Abc_NtkObj( pNtk, i ); + // add the fanins + vFanins = p->vFaninsNew->pArray[i]; + for ( k = 0; k < vFanins->nSize; k++ ) + { + pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] ); + Abc_ObjAddFanin( pNode, pFanin ); + } + pNode->pData = p->vSopsNew->pArray[i]; + assert( pNode->pData != NULL ); + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcGen.c b/abc70930/src/base/abci/abcGen.c new file mode 100644 index 00000000..bfb41374 --- /dev/null +++ b/abc70930/src/base/abci/abcGen.c @@ -0,0 +1,511 @@ +/**CFile**************************************************************** + + FileName [abc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 ); +void Abc_WriteComp( FILE * pFile ); +void Abc_WriteFullAdder( FILE * pFile ); + +void Abc_GenAdder( char * pFileName, int nVars ); +void Abc_GenSorter( char * pFileName, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenAdder( char * pFileName, int nVars ) +{ + FILE * pFile; + int i; + + assert( nVars > 0 ); + + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# %d-bit ripple-carry adder generated by ABC on %s\n", nVars, Extra_TimeStamp() ); + fprintf( pFile, ".model Adder%02d\n", nVars ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " a%02d", i ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " b%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".outputs" ); + for ( i = 0; i <= nVars; i++ ) + fprintf( pFile, " y%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".names c\n" ); + if ( nVars == 1 ) + fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=y01\n" ); + else + { + fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=%02d\n", 0 ); + for ( i = 1; i < nVars-1; i++ ) + fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=%02d\n", i, i, i-1, i, i ); + fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=y%02d\n", i, i, i-1, i, i+1 ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); + + Abc_WriteFullAdder( pFile ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenSorter( char * pFileName, int nVars ) +{ + FILE * pFile; + int i, k, Counter, nDigits; + + assert( nVars > 1 ); + + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# %d-bit sorter generated by ABC on %s\n", nVars, Extra_TimeStamp() ); + fprintf( pFile, ".model Sorter%02d\n", nVars ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " x%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".outputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " y%02d", i ); + fprintf( pFile, "\n" ); + + Counter = 0; + nDigits = Extra_Base10Log( (nVars-2)*nVars ); + if ( nVars == 2 ) + fprintf( pFile, ".subckt Comp a=x00 b=x01 x=y00 y=y01\n" ); + else + { + fprintf( pFile, ".subckt Layer0" ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " x%02d=x%02d", k, k ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ ); + fprintf( pFile, "\n" ); + Counter -= nVars; + for ( i = 1; i < nVars-2; i++ ) + { + fprintf( pFile, ".subckt Layer%d", (i&1) ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ ); + fprintf( pFile, "\n" ); + Counter -= nVars; + } + fprintf( pFile, ".subckt Layer%d", (i&1) ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ ); + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, " y%02d=y%02d", k, k ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); + + Abc_WriteLayer( pFile, nVars, 0 ); + Abc_WriteLayer( pFile, nVars, 1 ); + Abc_WriteComp( pFile ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 ) +{ + int i; + fprintf( pFile, ".model Layer%d\n", fSkip1 ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " x%02d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " y%02d", i ); + fprintf( pFile, "\n" ); + if ( fSkip1 ) + { + fprintf( pFile, ".names x00 y00\n" ); + fprintf( pFile, "1 1\n" ); + i = 1; + } + else + i = 0; + for ( ; i + 1 < nVars; i += 2 ) + fprintf( pFile, ".subckt Comp a=x%02d b=x%02d x=y%02d y=y%02d\n", i, i+1, i, i+1 ); + if ( i < nVars ) + { + fprintf( pFile, ".names x%02d y%02d\n", i, i ); + fprintf( pFile, "1 1\n" ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteComp( FILE * pFile ) +{ + fprintf( pFile, ".model Comp\n" ); + fprintf( pFile, ".inputs a b\n" ); + fprintf( pFile, ".outputs x y\n" ); + fprintf( pFile, ".names a b x\n" ); + fprintf( pFile, "11 1\n" ); + fprintf( pFile, ".names a b y\n" ); + fprintf( pFile, "1- 1\n" ); + fprintf( pFile, "-1 1\n" ); + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteFullAdder( FILE * pFile ) +{ + fprintf( pFile, ".model FA\n" ); + fprintf( pFile, ".inputs a b cin\n" ); + fprintf( pFile, ".outputs s cout\n" ); + fprintf( pFile, ".names a b k\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names k cin s\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names a b cin cout\n" ); + fprintf( pFile, "11- 1\n" ); + fprintf( pFile, "1-1 1\n" ); + fprintf( pFile, "-11 1\n" ); + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteCell( FILE * pFile ) +{ + fprintf( pFile, ".model cell\n" ); + fprintf( pFile, ".inputs px1 px2 py1 py2 x y\n" ); + fprintf( pFile, ".outputs fx fy\n" ); + fprintf( pFile, ".names x y a\n" ); + fprintf( pFile, "11 1\n" ); + fprintf( pFile, ".names px1 a x nx\n" ); + fprintf( pFile, "11- 1\n" ); + fprintf( pFile, "0-1 1\n" ); + fprintf( pFile, ".names py1 a y ny\n" ); + fprintf( pFile, "11- 1\n" ); + fprintf( pFile, "0-1 1\n" ); + fprintf( pFile, ".names px2 nx fx\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".names py2 ny fy\n" ); + fprintf( pFile, "10 1\n" ); + fprintf( pFile, "01 1\n" ); + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenMesh( char * pFileName, int nVars ) +{ + FILE * pFile; + int i, k; + + assert( nVars > 0 ); + + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# %dx%d mesh generated by ABC on %s\n", nVars, nVars, Extra_TimeStamp() ); + fprintf( pFile, ".model mesh%d\n", nVars ); + + for ( i = 0; i < nVars; i++ ) + for ( k = 0; k < nVars; k++ ) + { + fprintf( pFile, ".inputs" ); + fprintf( pFile, " p%d%dx1", i, k ); + fprintf( pFile, " p%d%dx2", i, k ); + fprintf( pFile, " p%d%dy1", i, k ); + fprintf( pFile, " p%d%dy2", i, k ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " v%02d v%02d", 2*i, 2*i+1 ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".outputs" ); + fprintf( pFile, " fx00" ); + fprintf( pFile, "\n" ); + + for ( i = 0; i < nVars; i++ ) // horizontal + for ( k = 0; k < nVars; k++ ) // vertical + { + fprintf( pFile, ".subckt cell" ); + fprintf( pFile, " px1=p%d%dx1", i, k ); + fprintf( pFile, " px2=p%d%dx2", i, k ); + fprintf( pFile, " py1=p%d%dy1", i, k ); + fprintf( pFile, " py2=p%d%dy2", i, k ); + if ( k == nVars - 1 ) + fprintf( pFile, " x=v%02d", i ); + else + fprintf( pFile, " x=fx%d%d", i, k+1 ); + if ( i == nVars - 1 ) + fprintf( pFile, " y=v%02d", nVars+k ); + else + fprintf( pFile, " y=fy%d%d", i+1, k ); + // outputs + fprintf( pFile, " fx=fx%d%d", i, k ); + fprintf( pFile, " fy=fy%d%d", i, k ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + Abc_WriteCell( pFile ); + fclose( pFile ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_WriteKLut( FILE * pFile, int nLutSize ) +{ + int i, iVar, iNext, nPars = (1 << nLutSize); + fprintf( pFile, "\n" ); + fprintf( pFile, ".model lut%d\n", nLutSize ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nPars; i++ ) + fprintf( pFile, " p%02d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nLutSize; i++ ) + fprintf( pFile, " i%d", i ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs o\n" ); + fprintf( pFile, ".names n01 o\n" ); + fprintf( pFile, "1 1\n" ); + // write internal MUXes + iVar = 0; + iNext = 2; + for ( i = 1; i < nPars; i++ ) + { + if ( i == iNext ) + { + iNext *= 2; + iVar++; + } + if ( iVar == nLutSize - 1 ) + fprintf( pFile, ".names i%d p%02d p%02d n%02d\n", iVar, 2*(i-nPars/2), 2*(i-nPars/2)+1, i ); + else + fprintf( pFile, ".names i%d n%02d n%02d n%02d\n", iVar, 2*i, 2*i+1, i ); + fprintf( pFile, "01- 1\n" ); + fprintf( pFile, "1-1 1\n" ); + } + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Generates structure of L K-LUTs implementing an N-var function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars ) +{ + FILE * pFile; + int nVarsLut = (1 << nLutSize); // the number of LUT variables + int nVarsLog = Extra_Base2Log( nVars + nLuts - 1 ); // the number of encoding vars + int nVarsDeg = (1 << nVarsLog); // the number of LUT variables (total) + int nParsLut = nLuts * (1 << nLutSize); // the number of LUT params + int nParsVar = nLuts * nLutSize * nVarsLog; // the number of var params + int i, j, k; + + assert( nVars > 0 ); + + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# Structure with %d %d-LUTs for %d-var function generated by ABC on %s\n", nLuts, nLutSize, nVars, Extra_TimeStamp() ); + fprintf( pFile, ".model struct%dx%d_%d\n", nLuts, nLutSize, nVars ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nParsLut; i++ ) + fprintf( pFile, " pl%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nParsVar; i++ ) + fprintf( pFile, " pv%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nVars; i++ ) + fprintf( pFile, " v%02d", i ); + fprintf( pFile, "\n" ); + + fprintf( pFile, ".outputs" ); + fprintf( pFile, " v%02d", nVars + nLuts - 1 ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".names Gnd\n" ); + fprintf( pFile, " 0\n" ); + + // generate LUTs + for ( i = 0; i < nLuts; i++ ) + { + fprintf( pFile, ".subckt lut%d", nLutSize ); + // generate config parameters + for ( k = 0; k < nVarsLut; k++ ) + fprintf( pFile, " p%02d=pl%02d", k, i * nVarsLut + k ); + // generate the inputs + for ( k = 0; k < nLutSize; k++ ) + fprintf( pFile, " i%d=s%02d", k, i * nLutSize + k ); + // generate the output + fprintf( pFile, " o=v%02d", nVars + i ); + fprintf( pFile, "\n" ); + } + + // generate LUT inputs + for ( i = 0; i < nLuts; i++ ) + { + for ( j = 0; j < nLutSize; j++ ) + { + fprintf( pFile, ".subckt lut%d", nVarsLog ); + // generate config parameters + for ( k = 0; k < nVarsDeg; k++ ) + { + if ( k < nVars + nLuts - 1 && k < nVars + i ) + fprintf( pFile, " p%02d=v%02d", k, k ); + else + fprintf( pFile, " p%02d=Gnd", k ); + } + // generate the inputs + for ( k = 0; k < nVarsLog; k++ ) + fprintf( pFile, " i%d=pv%02d", k, (i * nLutSize + j) * nVarsLog + k ); + // generate the output + fprintf( pFile, " o=s%02d", i * nLutSize + j ); + fprintf( pFile, "\n" ); + } + } + + fprintf( pFile, ".end\n" ); + fprintf( pFile, "\n" ); + + // generate LUTs + Abc_WriteKLut( pFile, nLutSize ); + if ( nVarsLog != nLutSize ) + Abc_WriteKLut( pFile, nVarsLog ); + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcHaig.c b/abc70930/src/base/abci/abcHaig.c new file mode 100644 index 00000000..d3513bbe --- /dev/null +++ b/abc70930/src/base/abci/abcHaig.c @@ -0,0 +1,726 @@ +/**CFile**************************************************************** + + FileName [abcHaig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Implements history AIG for combinational rewriting.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcHaig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start history AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigStart( Abc_Ntk_t * pNtk ) +{ + Hop_Man_t * p; + Abc_Obj_t * pObj, * pTemp; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + // check if the package is already started + if ( pNtk->pHaig ) + { + Abc_NtkHaigStop( pNtk ); + assert( pNtk->pHaig == NULL ); + printf( "Warning: Previous history AIG was removed.\n" ); + } + // make sure the data is clean + Abc_NtkForEachObj( pNtk, pObj, i ) + assert( pObj->pEquiv == NULL ); + // start the HOP package + p = Hop_ManStart(); + p->vObjs = Vec_PtrAlloc( 4096 ); + Vec_PtrPush( p->vObjs, Hop_ManConst1(p) ); + // map the constant node + Abc_AigConst1(pNtk)->pEquiv = Hop_ManConst1(p); + // map the CIs + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pEquiv = Hop_ObjCreatePi(p); + // map the internal nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pEquiv = Hop_And( p, Abc_ObjChild0Equiv(pObj), Abc_ObjChild1Equiv(pObj) ); + // map the choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + // print warning about choice nodes + printf( "Warning: The choice nodes in the original AIG are converted into HAIG.\n" ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( !Abc_AigNodeIsChoice( pObj ) ) + continue; + for ( pTemp = pObj->pData; pTemp; pTemp = pTemp->pData ) + Hop_ObjCreateChoice( pObj->pEquiv, pTemp->pEquiv ); + } + } + // make sure everything is okay + if ( !Hop_ManCheck(p) ) + { + printf( "Abc_NtkHaigStart: Check for History AIG has failed.\n" ); + Hop_ManStop(p); + return 0; + } + pNtk->pHaig = p; + return 1; +} + +/**Function************************************************************* + + Synopsis [Stops history AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigStop( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + if ( pNtk->pHaig == NULL ) + { + printf( "Warning: History AIG is not allocated.\n" ); + return 1; + } + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pEquiv = NULL; + Hop_ManStop( pNtk->pHaig ); + pNtk->pHaig = NULL; + return 1; +} + +/**Function************************************************************* + + Synopsis [Transfers the HAIG to the new network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; + int i; + if ( pNtkOld->pHaig == NULL ) + return; + // transfer the package + assert( pNtkNew->pHaig == NULL ); + pNtkNew->pHaig = pNtkOld->pHaig; + pNtkOld->pHaig = NULL; + // transfer constant pointer + Abc_AigConst1(pNtkOld)->pCopy->pEquiv = Abc_AigConst1(pNtkOld)->pEquiv; + // transfer the CI pointers + Abc_NtkForEachCi( pNtkOld, pObj, i ) + pObj->pCopy->pEquiv = pObj->pEquiv; +} + + + +/**Function************************************************************* + + Synopsis [Collects the nodes in the classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkHaigCollectMembers( Hop_Man_t * p ) +{ + Vec_Ptr_t * vObjs; + Hop_Obj_t * pObj; + int i; + vObjs = Vec_PtrAlloc( 4098 ); + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( pObj->pData == NULL ) + continue; + pObj->pData = Hop_ObjRepr( pObj ); + Vec_PtrPush( vObjs, pObj ); + } + return vObjs; +} + +/**Function************************************************************* + + Synopsis [Creates classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkHaigCreateClasses( Vec_Ptr_t * vMembers ) +{ + Vec_Ptr_t * vClasses; + Hop_Obj_t * pObj, * pRepr; + int i; + + // count classes + vClasses = Vec_PtrAlloc( 4098 ); + Vec_PtrForEachEntry( vMembers, pObj, i ) + { + pRepr = pObj->pData; + assert( pRepr->pData == NULL ); + if ( pRepr->fMarkA == 0 ) // new + { + pRepr->fMarkA = 1; + Vec_PtrPush( vClasses, pRepr ); + } + } + + // set representatives as representatives + Vec_PtrForEachEntry( vClasses, pObj, i ) + { + pObj->fMarkA = 0; + pObj->pData = pObj; + } + + // go through the members and update + Vec_PtrForEachEntry( vMembers, pObj, i ) + { + pRepr = pObj->pData; + if ( ((Hop_Obj_t *)pRepr->pData)->Id > pObj->Id ) + pRepr->pData = pObj; + } + + // change representatives of the class + Vec_PtrForEachEntry( vMembers, pObj, i ) + { + pRepr = pObj->pData; + pObj->pData = pRepr->pData; + assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id ); + } + + // update classes + Vec_PtrForEachEntry( vClasses, pObj, i ) + { + pRepr = pObj->pData; + assert( pRepr->pData == pRepr ); +// pRepr->pData = NULL; + Vec_PtrWriteEntry( vClasses, i, pRepr ); + Vec_PtrPush( vMembers, pObj ); + } + + Vec_PtrForEachEntry( vMembers, pObj, i ) + if ( pObj->pData == pObj ) + pObj->pData = NULL; + +/* + Vec_PtrForEachEntry( vMembers, pObj, i ) + { + printf( "ObjId = %4d : ", pObj->Id ); + if ( pObj->pData == NULL ) + { + printf( "NULL" ); + } + else + { + printf( "%4d", ((Hop_Obj_t *)pObj->pData)->Id ); + assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id ); + } + printf( "\n" ); + } +*/ + return vClasses; +} + +/**Function************************************************************* + + Synopsis [Counts how many data members have non-trivial fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigCountFans( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( pObj->pData == NULL ) + continue; + if ( Hop_ObjRefs(pObj) > 0 ) + Counter++; + } + printf( "The number of class members with fanouts = %5d.\n", Counter ); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Hop_Obj_t * Hop_ObjReprHop( Hop_Obj_t * pObj ) +{ + Hop_Obj_t * pRepr; + assert( pObj->pNext != NULL ); + if ( pObj->pData == NULL ) + return pObj->pNext; + pRepr = pObj->pData; + assert( pRepr->pData == pRepr ); + return Hop_NotCond( pRepr->pNext, pObj->fPhase ^ pRepr->fPhase ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Hop_Obj_t * Hop_ObjChild0Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin0(pObj)), Hop_ObjFaninC0(pObj) ); } +static inline Hop_Obj_t * Hop_ObjChild1Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin1(pObj)), Hop_ObjFaninC1(pObj) ); } + +/**Function************************************************************* + + Synopsis [Stops history AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Abc_NtkHaigReconstruct( Hop_Man_t * p ) +{ + Hop_Man_t * pNew; + Hop_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + pObj->pNext = NULL; + // start the HOP package + pNew = Hop_ManStart(); + pNew->vObjs = Vec_PtrAlloc( p->nCreated ); + Vec_PtrPush( pNew->vObjs, Hop_ManConst1(pNew) ); + // map the constant node + Hop_ManConst1(p)->pNext = Hop_ManConst1(pNew); + // map the CIs + Hop_ManForEachPi( p, pObj, i ) + pObj->pNext = Hop_ObjCreatePi(pNew); + // map the internal nodes + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( !Hop_ObjIsNode(pObj) ) + continue; + pObj->pNext = Hop_And( pNew, Hop_ObjChild0Hop(pObj), Hop_ObjChild1Hop(pObj) ); +// assert( !Hop_IsComplement(pObj->pNext) ); + if ( Hop_ManConst1(pNew) == Hop_Regular(pObj->pNext) ) + Counter++; + if ( pObj->pData ) // member of the class + Hop_Regular(pObj->pNext)->pData = Hop_Regular(((Hop_Obj_t *)pObj->pData)->pNext); + } +// printf( " Counter = %d.\n", Counter ); + // transfer the POs + Hop_ManForEachPo( p, pObj, i ) + Hop_ObjCreatePo( pNew, Hop_ObjChild0Hop(pObj) ); + // check the new manager + if ( !Hop_ManCheck(pNew) ) + { + printf( "Abc_NtkHaigReconstruct: Check for History AIG has failed.\n" ); + Hop_ManStop(pNew); + return NULL; + } + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigCheckTfi_rec( Abc_Obj_t * pNode, Abc_Obj_t * pOld ) +{ + if ( pNode == NULL ) + return 0; + if ( pNode == pOld ) + return 1; + // check the trivial cases + if ( Abc_ObjIsCi(pNode) ) + return 0; + assert( Abc_ObjIsNode(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return 0; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // check the children + if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin0(pNode), pOld ) ) + return 1; + if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin1(pNode), pOld ) ) + return 1; + // check equivalent nodes + return Abc_NtkHaigCheckTfi_rec( pNode->pData, pOld ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigCheckTfi( Abc_Ntk_t * pNtk, Abc_Obj_t * pOld, Abc_Obj_t * pNew ) +{ + assert( !Abc_ObjIsComplement(pOld) ); + assert( !Abc_ObjIsComplement(pNew) ); + Abc_NtkIncrementTravId(pNtk); + return Abc_NtkHaigCheckTfi_rec( pNew, pOld ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Abc_Obj_t * Hop_ObjChild0Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin0(pObj)->pNext, Hop_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Hop_ObjChild1Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin1(pObj)->pNext, Hop_ObjFaninC1(pObj) ); } + +/**Function************************************************************* + + Synopsis [Stops history AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkHaigRecreateAig( Abc_Ntk_t * pNtk, Hop_Man_t * p ) +{ + Abc_Ntk_t * pNtkAig; + Abc_Obj_t * pObjOld, * pObjAbcThis, * pObjAbcRepr; + Hop_Obj_t * pObj; + int i; + assert( p->nCreated == Vec_PtrSize(p->vObjs) ); + + // start the new network + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + + // transfer new nodes to the PIs of HOP + Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig ); + Hop_ManForEachPi( p, pObj, i ) + pObj->pNext = (Hop_Obj_t *)Abc_NtkCi( pNtkAig, i ); + + // construct new nodes + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( !Hop_ObjIsNode(pObj) ) + continue; + pObj->pNext = (Hop_Obj_t *)Abc_AigAnd( pNtkAig->pManFunc, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) ); + assert( !Hop_IsComplement(pObj->pNext) ); + } + + // set the COs + Abc_NtkForEachCo( pNtk, pObjOld, i ) + Abc_ObjAddFanin( pObjOld->pCopy, Hop_ObjChild0Next(Hop_ManPo(p,i)) ); + + // construct choice nodes + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + // skip the node without choices + if ( pObj->pData == NULL ) + continue; + // skip the representative of the class + if ( pObj->pData == pObj ) + continue; + // do not create choices for constant 1 and PIs + if ( !Hop_ObjIsNode(pObj->pData) ) + continue; + // get the corresponding new nodes + pObjAbcThis = (Abc_Obj_t *)pObj->pNext; + pObjAbcRepr = (Abc_Obj_t *)((Hop_Obj_t *)pObj->pData)->pNext; + // the new node cannot be already in the class + assert( pObjAbcThis->pData == NULL ); + // the new node cannot have fanouts + assert( Abc_ObjFanoutNum(pObjAbcThis) == 0 ); + // these should be different nodes + assert( pObjAbcRepr != pObjAbcThis ); + // do not create choices if there is a path from pObjAbcThis to pObjAbcRepr + if ( !Abc_NtkHaigCheckTfi( pNtkAig, pObjAbcRepr, pObjAbcThis ) ) + { + // find the last node in the class + while ( pObjAbcRepr->pData ) + pObjAbcRepr = pObjAbcRepr->pData; + // add the new node at the end of the list + pObjAbcRepr->pData = pObjAbcThis; + } + } + + // finish the new network +// Abc_NtkFinalize( pNtk, pNtkAig ); +// Abc_AigCleanup( pNtkAig->pManFunc ); + // check correctness of the network + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkHaigUse: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Resets representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkHaigResetReprsOld( Hop_Man_t * pMan ) +{ + Vec_Ptr_t * vMembers, * vClasses; + + // collect members of the classes and make them point to reprs + vMembers = Abc_NtkHaigCollectMembers( pMan ); + printf( "Collected %6d class members.\n", Vec_PtrSize(vMembers) ); + + // create classes + vClasses = Abc_NtkHaigCreateClasses( vMembers ); + printf( "Collected %6d classes. (Ave = %5.2f)\n", Vec_PtrSize(vClasses), + (float)(Vec_PtrSize(vMembers))/Vec_PtrSize(vClasses) ); + + Vec_PtrFree( vMembers ); + Vec_PtrFree( vClasses ); +} + +/**Function************************************************************* + + Synopsis [Resets representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkHaigResetReprs( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj, * pRepr; + int i, nClasses, nMembers, nFanouts, nNormals; + // clear self-classes + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + // fix the strange situation of double-loop + pRepr = pObj->pData; + if ( pRepr && pRepr->pData == pObj ) + pRepr->pData = pRepr; + // remove self-loops + if ( pObj->pData == pObj ) + pObj->pData = NULL; + } + // set representatives + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( pObj->pData == NULL ) + continue; + // get representative of the node + pRepr = Hop_ObjRepr( pObj ); + pRepr->pData = pRepr; + // set the representative + pObj->pData = pRepr; + } + // make each class point to the smallest topological order + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( pObj->pData == NULL ) + continue; + pRepr = Hop_ObjRepr( pObj ); + if ( pRepr->Id > pObj->Id ) + { + pRepr->pData = pObj; + pObj->pData = pObj; + } + else + pObj->pData = pRepr; + } + // count classes, members, and fanouts - and verify + nMembers = nClasses = nFanouts = nNormals = 0; + Vec_PtrForEachEntry( p->vObjs, pObj, i ) + { + if ( pObj->pData == NULL ) + continue; + // count members + nMembers++; + // count the classes and fanouts + if ( pObj->pData == pObj ) + nClasses++; + else if ( Hop_ObjRefs(pObj) > 0 ) + nFanouts++; + else + nNormals++; + // compare representatives + pRepr = Hop_ObjRepr( pObj ); + assert( pObj->pData == pRepr ); + assert( pRepr->Id <= pObj->Id ); + } +// printf( "Nodes = %7d. Member = %7d. Classes = %6d. Fanouts = %6d. Normals = %6d.\n", +// Hop_ManNodeNum(p), nMembers, nClasses, nFanouts, nNormals ); + return nFanouts; +} + +/**Function************************************************************* + + Synopsis [Stops history AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkHaigUse( Abc_Ntk_t * pNtk ) +{ + Hop_Man_t * pMan, * pManTemp; + Abc_Ntk_t * pNtkAig; + Abc_Obj_t * pObj; + int i; + + // check if HAIG is available + assert( Abc_NtkIsStrash(pNtk) ); + if ( pNtk->pHaig == NULL ) + { + printf( "Warning: History AIG is not available.\n" ); + return NULL; + } + // convert HOP package into AIG with choices + // print HAIG stats +// Hop_ManPrintStats( pMan ); // USES DATA!!! + + // add the POs + Abc_NtkForEachCo( pNtk, pObj, i ) + Hop_ObjCreatePo( pNtk->pHaig, Abc_ObjChild0Equiv(pObj) ); + + // clean the old network + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pEquiv = NULL; + pMan = pNtk->pHaig; + pNtk->pHaig = 0; + + // iteratively reconstruct the HOP manager to create choice nodes + while ( Abc_NtkHaigResetReprs( pMan ) ) + { + pMan = Abc_NtkHaigReconstruct( pManTemp = pMan ); + Hop_ManStop( pManTemp ); + } + + // traverse in the topological order and create new AIG + pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan ); + Hop_ManStop( pMan ); + + // free HAIG + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Transform HOP manager into the one without loops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ) +{ + Abc_Ntk_t * pNtkAig; + Hop_Man_t * pManTemp; + + // iteratively reconstruct the HOP manager to create choice nodes + while ( Abc_NtkHaigResetReprs( pMan ) ) + { + pMan = Abc_NtkHaigReconstruct( pManTemp = pMan ); + Hop_ManStop( pManTemp ); + } + + // traverse in the topological order and create new AIG + pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan ); + Hop_ManStop( pMan ); + return pNtkAig; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcIf.c b/abc70930/src/base/abci/abcIf.c new file mode 100644 index 00000000..bb56c22c --- /dev/null +++ b/abc70930/src/base/abci/abcIf.c @@ -0,0 +1,497 @@ +/**CFile**************************************************************** + + FileName [abcIf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface with the FPGA mapping package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: abcIf.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "if.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); +static Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ); +extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ); +static Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj ); +static Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk ); + +extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Interface with the FPGA mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) +{ + Abc_Ntk_t * pNtkNew; + If_Man_t * pIfMan; + + assert( Abc_NtkIsStrash(pNtk) ); + + // get timing information + pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk); + pPars->pTimesReq = NULL; + + // set the latch paths + if ( pPars->fLatchPaths && pPars->pTimesArr ) + { + int c; + for ( c = 0; c < Abc_NtkPiNum(pNtk); c++ ) + pPars->pTimesArr[c] = -ABC_INFINITY; + } + + // perform FPGA mapping + pIfMan = Abc_NtkToIf( pNtk, pPars ); + if ( pIfMan == NULL ) + return NULL; + if ( !If_ManPerformMapping( pIfMan ) ) + { + If_ManStop( pIfMan ); + return NULL; + } + + // transform the result of mapping into the new network + pNtkNew = Abc_NtkFromIf( pIfMan, pNtk ); + if ( pNtkNew == NULL ) + return NULL; + If_ManStop( pIfMan ); + + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkIf: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Load the network into FPGA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) +{ + ProgressBar * pProgress; + If_Man_t * pIfMan; + Abc_Obj_t * pNode, * pFanin, * pPrev; + Vec_Ptr_t * vNodes; + int i; + + assert( Abc_NtkIsStrash(pNtk) ); +// vNodes = Abc_NtkFindGoodOrder( pNtk ); + vNodes = Abc_AigDfs( pNtk, 0, 0 ); + + // start the mapping manager and set its parameters + pIfMan = If_ManStart( pPars ); + + // print warning about excessive memory usage + if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30) > 1.0 ) + printf( "Warning: The mapper will allocate %.1f Gb for to represent the subject graph with %d AIG nodes.\n", + 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) ); + + // create PIs and remember them in the old nodes + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan ); + Abc_NtkForEachCi( pNtk, pNode, i ) + { + pNode->pCopy = (Abc_Obj_t *)If_ManCreateCi( pIfMan ); +//printf( "AIG CI %2d -> IF CI %2d\n", pNode->Id, ((If_Obj_t *)pNode->pCopy)->Id ); + } + + // load the AIG into the mapper + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); +// Abc_AigForEachAnd( pNtk, pNode, i ) + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, "Initial" ); + // add the node to the mapper + pNode->pCopy = (Abc_Obj_t *)If_ManCreateAnd( pIfMan, + If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), + If_NotCond( (If_Obj_t *)Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); + // set up the choice node + if ( Abc_AigNodeIsChoice( pNode ) ) + { + pIfMan->nChoices++; + for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) + If_ObjSetChoice( (If_Obj_t *)pPrev->pCopy, (If_Obj_t *)pFanin->pCopy ); + If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pCopy ); + } +//printf( "AIG node %2d -> IF node %2d\n", pNode->Id, ((If_Obj_t *)pNode->pCopy)->Id ); + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + + // set the primary outputs without copying the phase + Abc_NtkForEachCo( pNtk, pNode, i ) + If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) ); + return pIfMan; +} + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [Assuming the copy field of the mapped nodes are NULL.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode, * pNodeNew; + Vec_Int_t * vCover; + int i, nDupGates; + // create the new network + if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + else if ( pIfMan->pPars->fUseSops ) + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + else + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); + // prepare the mapping manager + If_ManCleanNodeCopy( pIfMan ); + If_ManCleanCutData( pIfMan ); + // make the mapper point to the new network + If_ObjSetCopy( If_ManConst1(pIfMan), Abc_NtkCreateNodeConst1(pNtkNew) ); + Abc_NtkForEachCi( pNtk, pNode, i ) + If_ObjSetCopy( If_ManCi(pIfMan, i), pNode->pCopy ); + // process the nodes in topological order + vCover = Vec_IntAlloc( 1 << 16 ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, "Final" ); + pNodeNew = Abc_NodeFromIf_rec( pNtkNew, pIfMan, If_ObjFanin0(If_ManCo(pIfMan, i)), vCover ); + pNodeNew = Abc_ObjNotCond( pNodeNew, If_ObjFaninC0(If_ManCo(pIfMan, i)) ); + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + } + Extra_ProgressBarStop( pProgress ); + Vec_IntFree( vCover ); + // remove the constant node if not used + pNodeNew = (Abc_Obj_t *)If_ObjCopy( If_ManConst1(pIfMan) ); + if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) + Abc_NtkDeleteObj( pNodeNew ); + // minimize the node + if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) + Abc_NtkSweep( pNtkNew, 0 ); + if ( pIfMan->pPars->fUseBdds ) + Abc_NtkBddReorder( pNtkNew, 0 ); + // decouple the PO driver nodes to reduce the number of levels + nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); +// if ( nDupGates && If_ManReadVerbose(pIfMan) ) +// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Derive one node after FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ) +{ + Abc_Obj_t * pNodeNew; + If_Cut_t * pCutBest; + If_Obj_t * pIfLeaf; + int i; + // return if the result if known + pNodeNew = (Abc_Obj_t *)If_ObjCopy( pIfObj ); + if ( pNodeNew ) + return pNodeNew; + assert( pIfObj->Type == IF_AND ); + // get the parameters of the best cut + // create a new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pCutBest = If_ObjCutBest( pIfObj ); + if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) + { + If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) + Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); + } + else + { + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) + Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); + } + // set the level of the new node + pNodeNew->Level = Abc_ObjLevelNew( pNodeNew ); + // derive the function of this node + if ( pIfMan->pPars->fTruth ) + { + if ( pIfMan->pPars->fUseBdds ) + { + // transform truth table into the BDD + pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 0 ); Cudd_Ref(pNodeNew->pData); + } + else if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) + { + // transform truth table into the BDD + pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 1 ); Cudd_Ref(pNodeNew->pData); + } + else if ( pIfMan->pPars->fUseSops ) + { + // transform truth table into the SOP + int RetValue = Kit_TruthIsop( If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover, 1 ); + assert( RetValue == 0 || RetValue == 1 ); + // check the case of constant cover + if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) + { + assert( RetValue == 0 ); + pNodeNew->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), NULL ); + pNodeNew = (Vec_IntSize(vCover) == 0) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew); + } + else + { + // derive the AIG for that tree + pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), vCover ); + if ( RetValue ) + Abc_SopComplement( pNodeNew->pData ); + } + } + else + { + extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); + pNodeNew->pData = Kit_TruthToHop( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover ); + } + // complement the node if the cut was complemented + if ( pCutBest->fCompl ) + Abc_NodeComplement( pNodeNew ); + } + else + pNodeNew->pData = Abc_NodeIfToHop( pNtkNew->pManFunc, pIfMan, pIfObj ); + If_ObjSetCopy( pIfObj, pNodeNew ); + return pNodeNew; +} + +/**Function************************************************************* + + Synopsis [Recursively derives the truth table for the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited ) +{ + If_Cut_t * pCut; + Hop_Obj_t * gFunc, * gFunc0, * gFunc1; + // get the best cut + pCut = If_ObjCutBest(pIfObj); + // if the cut is visited, return the result + if ( If_CutData(pCut) ) + return If_CutData(pCut); + // compute the functions of the children + gFunc0 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin0, vVisited ); + gFunc1 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin1, vVisited ); + // get the function of the cut + gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pIfObj->fCompl0), Hop_NotCond(gFunc1, pIfObj->fCompl1) ); + assert( If_CutData(pCut) == NULL ); + If_CutSetData( pCut, gFunc ); + // add this cut to the visited list + Vec_PtrPush( vVisited, pCut ); + return gFunc; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table for one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj ) +{ + If_Cut_t * pCut; + Hop_Obj_t * gFunc; + If_Obj_t * pLeaf; + int i; + // get the best cut + pCut = If_ObjCutBest(pIfObj); + assert( pCut->nLeaves > 1 ); + // set the leaf variables + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) ); + // recursively compute the function while collecting visited cuts + Vec_PtrClear( pIfMan->vTemp ); + gFunc = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp ); +// printf( "%d ", Vec_PtrSize(p->vTemp) ); + // clean the cuts + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + If_CutSetData( If_ObjCutBest(pLeaf), NULL ); + Vec_PtrForEachEntry( pIfMan->vTemp, pCut, i ) + If_CutSetData( pCut, NULL ); + return gFunc; +} + + +/**Function************************************************************* + + Synopsis [Comparison for two nodes with the flow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjCompareFlow( Abc_Obj_t ** ppNode0, Abc_Obj_t ** ppNode1 ) +{ + float Flow0 = Abc_Int2Float((int)(*ppNode0)->pCopy); + float Flow1 = Abc_Int2Float((int)(*ppNode1)->pCopy); + if ( Flow0 > Flow1 ) + return -1; + if ( Flow0 < Flow1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Orders AIG nodes so that nodes from larger cones go first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFindGoodOrder_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + if ( !Abc_ObjIsNode(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin of the node + Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes ); + Abc_NtkFindGoodOrder_rec( Abc_ObjFanin1(pNode), vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Orders AIG nodes so that nodes from larger cones go first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes, * vCos; + Abc_Obj_t * pNode, * pFanin0, * pFanin1; + float Flow0, Flow1; + int i; + + // initialize the flow + Abc_AigConst1(pNtk)->pCopy = NULL; + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = NULL; + // compute the flow + Abc_AigForEachAnd( pNtk, pNode, i ) + { + pFanin0 = Abc_ObjFanin0(pNode); + pFanin1 = Abc_ObjFanin1(pNode); + Flow0 = Abc_Int2Float((int)pFanin0->pCopy)/Abc_ObjFanoutNum(pFanin0); + Flow1 = Abc_Int2Float((int)pFanin1->pCopy)/Abc_ObjFanoutNum(pFanin1); + pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int(Flow0 + Flow1+(float)1.0); + } + // find the flow of the COs + vCos = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pNode->pCopy = Abc_ObjFanin0(pNode)->pCopy; +// pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int((float)Abc_ObjFanin0(pNode)->Level); + Vec_PtrPush( vCos, pNode ); + } + + // sort nodes in the increasing order of the flow + qsort( (Abc_Obj_t **)Vec_PtrArray(vCos), Abc_NtkCoNum(pNtk), + sizeof(Abc_Obj_t *), (int (*)(const void *, const void *))Abc_ObjCompareFlow ); + // verify sorting + pFanin0 = Vec_PtrEntry(vCos, 0); + pFanin1 = Vec_PtrEntryLast(vCos); + assert( Abc_Int2Float((int)pFanin0->pCopy) >= Abc_Int2Float((int)pFanin1->pCopy) ); + + // collect the nodes in the topological order from the new array + Abc_NtkIncrementTravId( pNtk ); + vNodes = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( vCos, pNode, i ) + { + Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes ); +// printf( "%.2f ", Abc_Int2Float((int)pNode->pCopy) ); + } + Vec_PtrFree( vCos ); + return vNodes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcIvy.c b/abc70930/src/base/abci/abcIvy.c new file mode 100644 index 00000000..b878091b --- /dev/null +++ b/abc70930/src/base/abci/abcIvy.c @@ -0,0 +1,1101 @@ +/**CFile**************************************************************** + + FileName [abcIvy.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Strashing of the current network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcIvy.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" +#include "ivy.h" +#include "fraig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan ); +static Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig ); +static Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld ); + +static void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ); +static Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode ); +static Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); +static Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); +static Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); +extern char * Mio_GateReadSop( void * pGate ); + +typedef int Abc_Edge_t; +static inline Abc_Edge_t Abc_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } +static inline int Abc_EdgeId( Abc_Edge_t Edge ) { return Edge >> 1; } +static inline int Abc_EdgeIsComplement( Abc_Edge_t Edge ) { return Edge & 1; } +static inline Abc_Edge_t Abc_EdgeRegular( Abc_Edge_t Edge ) { return (Edge >> 1) << 1; } +static inline Abc_Edge_t Abc_EdgeNot( Abc_Edge_t Edge ) { return Edge ^ 1; } +static inline Abc_Edge_t Abc_EdgeNotCond( Abc_Edge_t Edge, int fCond ) { return Edge ^ fCond; } +static inline Abc_Edge_t Abc_EdgeFromNode( Abc_Obj_t * pNode ) { return Abc_EdgeCreate( Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ); } +static inline Abc_Obj_t * Abc_EdgeToNode( Abc_Ntk_t * p, Abc_Edge_t Edge ) { return Abc_ObjNotCond( Abc_NtkObj(p, Abc_EdgeId(Edge)), Abc_EdgeIsComplement(Edge) ); } + +static inline Abc_Obj_t * Abc_ObjFanin0Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Abc_ObjFanin1Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ); } + +static Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs ); + +extern int timeRetime; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Prepares the IVY package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ) +{ + Ivy_Man_t * pMan; + int fCleanup = 1; +//timeRetime = clock(); + assert( !Abc_NtkIsNetlist(pNtk) ); + if ( Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Abc_NtkIvyBefore(): Converting to SOPs has failed.\n" ); + return NULL; + } + } + if ( fSeq && Abc_NtkCountSelfFeedLatches(pNtk) ) + { + printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtk) ); +// return NULL; + } + // print warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" ); + // convert to the AIG manager + pMan = Abc_NtkToIvy( pNtk ); + if ( !Ivy_ManCheck( pMan ) ) + { + printf( "AIG check has failed.\n" ); + Ivy_ManStop( pMan ); + return NULL; + } +// Ivy_ManPrintStats( pMan ); + if ( fSeq ) + { + int nLatches = Abc_NtkLatchNum(pNtk); + Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, fUseDc ); + Ivy_ManMakeSeq( pMan, nLatches, vInit->pArray ); + Vec_IntFree( vInit ); +// Ivy_ManPrintStats( pMan ); + } +//timeRetime = clock() - timeRetime; + return pMan; +} + +/**Function************************************************************* + + Synopsis [Prepares the IVY package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyAfter( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan, int fSeq, int fHaig ) +{ + Abc_Ntk_t * pNtkAig; + int nNodes, fCleanup = 1; + // convert from the AIG manager + if ( fSeq ) + pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan, fHaig ); + else + pNtkAig = Abc_NtkFromIvy( pNtk, pMan ); + // report the cleanup results + if ( !fHaig && fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) + printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan; + pMan = Abc_NtkIvyBefore( pNtk, 1, 0 ); + if ( pMan == NULL ) + return NULL; + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan; + int clk; +// int i; +/* +extern int nMoves; +extern int nMovesS; +extern int nClauses; +extern int timeInv; + +nMoves = 0; +nMovesS = 0; +nClauses = 0; +timeInv = 0; +*/ + pMan = Abc_NtkIvyBefore( pNtk, 1, 1 ); + if ( pMan == NULL ) + return NULL; +//timeRetime = clock(); + +clk = clock(); + Ivy_ManHaigStart( pMan, fVerbose ); +// Ivy_ManRewriteSeq( pMan, 0, 0 ); +// for ( i = 0; i < nIters; i++ ) +// Ivy_ManRewriteSeq( pMan, fUseZeroCost, 0 ); + +//printf( "%d ", Ivy_ManNodeNum(pMan) ); + Ivy_ManRewriteSeq( pMan, 0, 0 ); + Ivy_ManRewriteSeq( pMan, 0, 0 ); + Ivy_ManRewriteSeq( pMan, 1, 0 ); +//printf( "%d ", Ivy_ManNodeNum(pMan) ); +//printf( "%d ", Ivy_ManNodeNum(pMan->pHaig) ); +//PRT( " ", clock() - clk ); +//printf( "\n" ); +/* + printf( "Moves = %d. ", nMoves ); + printf( "MovesS = %d. ", nMovesS ); + printf( "Clauses = %d. ", nClauses ); + PRT( "Time", timeInv ); +*/ +// Ivy_ManRewriteSeq( pMan, 1, 0 ); +//printf( "Haig size = %d.\n", Ivy_ManNodeNum(pMan->pHaig) ); +// Ivy_ManHaigPostprocess( pMan, fVerbose ); +//timeRetime = clock() - timeRetime; + + // write working AIG into the current network +// pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); + // write HAIG into the current network + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan->pHaig, 1, 1 ); + + Ivy_ManHaigStop( pMan ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs ) +{ + extern void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs ); + Ivy_Man_t * pMan; + pMan = Abc_NtkIvyBefore( pNtk, 1, 0 ); + if ( pMan == NULL ) + return; + Ivy_CutComputeAll( pMan, nInputs ); + Ivy_ManStop( pMan ); +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan; + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + if ( pMan == NULL ) + return NULL; +//timeRetime = clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, fUseZeroCost, fVerbose ); +//timeRetime = clock() - timeRetime; + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan; + pMan = Abc_NtkIvyBefore( pNtk, 1, 1 ); + if ( pMan == NULL ) + return NULL; +//timeRetime = clock(); + Ivy_ManRewriteSeq( pMan, fUseZeroCost, fVerbose ); +//timeRetime = clock() - timeRetime; +// Ivy_ManRewriteSeq( pMan, 1, 0 ); +// Ivy_ManRewriteSeq( pMan, 1, 0 ); + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyResyn0( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan, * pTemp; + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + if ( pMan == NULL ) + return NULL; + pMan = Ivy_ManResyn0( pTemp = pMan, fUpdateLevel, fVerbose ); + Ivy_ManStop( pTemp ); + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ) +{ + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan, * pTemp; + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + if ( pMan == NULL ) + return NULL; + pMan = Ivy_ManResyn( pTemp = pMan, fUpdateLevel, fVerbose ); + Ivy_ManStop( pTemp ); + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose ) +{ + Ivy_FraigParams_t Params, * pParams = &Params; + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan, * pTemp; + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + if ( pMan == NULL ) + return NULL; + Ivy_FraigParamsDefault( pParams ); + pParams->nBTLimitMiter = nConfLimit; + pParams->fVerbose = fVerbose; +// pMan = Ivy_FraigPerform( pTemp = pMan, pParams ); + pMan = Ivy_FraigMiter( pTemp = pMan, pParams ); + Ivy_ManStop( pTemp ); + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Sets the final nodes to point to the original nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTransferPointers( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig ) +{ + Abc_Obj_t * pObj; + Ivy_Obj_t * pObjIvy, * pObjFraig; + int i; + pObj = Abc_AigConst1(pNtk); + pObj->pCopy = Abc_AigConst1(pNtkAig); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkCi(pNtkAig, i); + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkCo(pNtkAig, i); + Abc_NtkForEachLatch( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkBox(pNtkAig, i); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pObjIvy = (Ivy_Obj_t *)pObj->pCopy; + if ( pObjIvy == NULL ) + continue; + pObjFraig = Ivy_ObjEquiv( pObjIvy ); + if ( pObjFraig == NULL ) + continue; + pObj->pCopy = Abc_EdgeToNode( pNtkAig, Ivy_Regular(pObjFraig)->TravId ); + pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, Ivy_IsComplement(pObjFraig) ); + } +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ) +{ + Ivy_FraigParams_t Params, * pParams = &Params; + Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan, * pTemp; + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + if ( pMan == NULL ) + return NULL; + Ivy_FraigParamsDefault( pParams ); + pParams->nBTLimitNode = nConfLimit; + pParams->fVerbose = fVerbose; + pParams->fProve = fProve; + pParams->fDoSparse = fDoSparse; + pMan = Ivy_FraigPerform( pTemp = pMan, pParams ); + // transfer the pointers + if ( fTransfer == 1 ) + { + Vec_Ptr_t * vCopies; + vCopies = Abc_NtkSaveCopy( pNtk ); + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Abc_NtkLoadCopy( pNtk, vCopies ); + Vec_PtrFree( vCopies ); + Abc_NtkTransferPointers( pNtk, pNtkAig ); + } + else + pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); + Ivy_ManStop( pTemp ); + Ivy_ManStop( pMan ); + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ) +{ + Prove_Params_t * pParams = pPars; + Abc_Ntk_t * pNtk = *ppNtk, * pNtkTemp; + Abc_Obj_t * pObj, * pFanin; + Ivy_Man_t * pMan; + int RetValue; + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + // experiment with various parameters settings +// pParams->fUseBdds = 1; +// pParams->fBddReorder = 1; +// pParams->nTotalBacktrackLimit = 10000; + + // strash the network if it is not strashed already + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash( pNtkTemp = pNtk, 0, 1, 0 ); + Abc_NtkDelete( pNtkTemp ); + } + + // check the case when the 0000 simulation pattern detect the bug + pObj = Abc_NtkPo(pNtk,0); + pFanin = Abc_ObjFanin0(pObj); + if ( Abc_ObjFanin0(pObj)->fPhase != (unsigned)Abc_ObjFaninC0(pObj) ) + { + pNtk->pModel = ALLOC( int, Abc_NtkPiNum(pNtk) ); + memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkPiNum(pNtk) ); + return 0; + } + + // if SAT only, solve without iteration + RetValue = Abc_NtkMiterSat( pNtk, 2*(sint64)pParams->nMiteringLimitStart, (sint64)0, 0, NULL, NULL ); + if ( RetValue >= 0 ) + return RetValue; + + // apply AIG rewriting + if ( pParams->fUseRewriting && Abc_NtkNodeNum(pNtk) > 500 ) + { + pParams->fUseRewriting = 0; + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); + Abc_NtkDelete( pNtkTemp ); + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); + Abc_NtkDelete( pNtkTemp ); + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + } + + // convert ABC network into IVY network + pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); + + // solve the CEC problem + RetValue = Ivy_FraigProve( &pMan, pParams ); + // convert IVY network into ABC network + pNtk = Abc_NtkIvyAfter( pNtkTemp = pNtk, pMan, 0, 0 ); + Abc_NtkDelete( pNtkTemp ); + // transfer model if given + pNtk->pModel = pMan->pData; pMan->pData = NULL; + Ivy_ManStop( pMan ); + + // try to prove it using brute force SAT + if ( RetValue < 0 && pParams->fUseBdds ) + { + if ( pParams->fVerbose ) + { + printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); + fflush( stdout ); + } + pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); + if ( pNtk ) + { + Abc_NtkDelete( pNtkTemp ); + RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) ); + } + else + pNtk = pNtkTemp; + } + + // return the result + *ppNtk = pNtk; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ) +{ +// Abc_Ntk_t * pNtkAig; + Ivy_Man_t * pMan;//, * pTemp; + int fCleanup = 1; +// int nNodes; + int nLatches = Abc_NtkLatchNum(pNtk); + Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, 0 ); + + assert( !Abc_NtkIsNetlist(pNtk) ); + if ( Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + Vec_IntFree( vInit ); + printf( "Abc_NtkIvy(): Converting to SOPs has failed.\n" ); + return NULL; + } + } + if ( Abc_NtkCountSelfFeedLatches(pNtk) ) + { + printf( "Warning: The network has %d self-feeding latches. Quitting.\n", Abc_NtkCountSelfFeedLatches(pNtk) ); + return NULL; + } + + // print warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" ); + + // convert to the AIG manager + pMan = Abc_NtkToIvy( pNtk ); + if ( !Ivy_ManCheck( pMan ) ) + { + Vec_IntFree( vInit ); + printf( "AIG check has failed.\n" ); + Ivy_ManStop( pMan ); + return NULL; + } + +// Ivy_MffcTest( pMan ); +// Ivy_ManPrintStats( pMan ); + +// pMan = Ivy_ManBalance( pTemp = pMan, 1 ); +// Ivy_ManStop( pTemp ); + +// Ivy_ManSeqRewrite( pMan, 0, 0 ); +// Ivy_ManTestCutsAlg( pMan ); +// Ivy_ManTestCutsBool( pMan ); +// Ivy_ManRewriteAlg( pMan, 1, 1 ); + +// pMan = Ivy_ManResyn( pTemp = pMan, 1, 0 ); +// Ivy_ManStop( pTemp ); + +// Ivy_ManTestCutsAll( pMan ); +// Ivy_ManTestCutsTravAll( pMan ); + +// Ivy_ManPrintStats( pMan ); + +// Ivy_ManPrintStats( pMan ); +// Ivy_ManRewritePre( pMan, 1, 0, 0 ); +// Ivy_ManPrintStats( pMan ); +// printf( "\n" ); + +// Ivy_ManPrintStats( pMan ); +// Ivy_ManMakeSeq( pMan, nLatches, pInit ); +// Ivy_ManPrintStats( pMan ); + +// Ivy_ManRequiredLevels( pMan ); + +// Ivy_FastMapPerform( pMan, 8 ); + Ivy_ManStop( pMan ); + return NULL; + + +/* + // convert from the AIG manager + pNtkAig = Abc_NtkFromIvy( pNtk, pMan ); +// pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan ); + Ivy_ManStop( pMan ); + + // report the cleanup results + if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) + printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + FREE( pInit ); + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + + FREE( pInit ); + return pNtkAig; +*/ +} + + + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan ) +{ + Vec_Int_t * vNodes; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; + Ivy_Obj_t * pNode; + int i; + // perform strashing + pNtk = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) ); + Abc_NtkForEachCi( pNtkOld, pObj, i ) + Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy ); + // rebuild the AIG + vNodes = Ivy_ManDfs( pMan ); + Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i ) + { + // add the first fanin + pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode ); + if ( Ivy_ObjIsBuf(pNode) ) + { + pNode->TravId = Abc_EdgeFromNode( pFaninNew0 ); + continue; + } + // add the second fanin + pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode ); + // create the new node + if ( Ivy_ObjIsExor(pNode) ) + pObjNew = Abc_AigXor( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); + else + pObjNew = Abc_AigAnd( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); + pNode->TravId = Abc_EdgeFromNode( pObjNew ); + } + // connect the PO nodes + Abc_NtkForEachCo( pNtkOld, pObj, i ) + { + pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) ); + Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); + } + Vec_IntFree( vNodes ); + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkFromIvy(): Network check has failed.\n" ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig ) +{ + Vec_Int_t * vNodes, * vLatches; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; + Ivy_Obj_t * pNode, * pTemp; + int i; +// assert( Ivy_ManLatchNum(pMan) > 0 ); + // perform strashing + pNtk = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) ); + Abc_NtkForEachPi( pNtkOld, pObj, i ) + Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy ); + // create latches of the new network + vNodes = Ivy_ManDfsSeq( pMan, &vLatches ); + Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i ) + { + pObjNew = Abc_NtkCreateLatch( pNtk ); + pFaninNew0 = Abc_NtkCreateBi( pNtk ); + pFaninNew1 = Abc_NtkCreateBo( pNtk ); + Abc_ObjAddFanin( pObjNew, pFaninNew0 ); + Abc_ObjAddFanin( pFaninNew1, pObjNew ); + if ( fHaig || Ivy_ObjInit(pNode) == IVY_INIT_DC ) + Abc_LatchSetInitDc( pObjNew ); + else if ( Ivy_ObjInit(pNode) == IVY_INIT_1 ) + Abc_LatchSetInit1( pObjNew ); + else if ( Ivy_ObjInit(pNode) == IVY_INIT_0 ) + Abc_LatchSetInit0( pObjNew ); + else assert( 0 ); + pNode->TravId = Abc_EdgeFromNode( pFaninNew1 ); + } + Abc_NtkAddDummyBoxNames( pNtk ); + // rebuild the AIG + Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i ) + { + // add the first fanin + pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode ); + if ( Ivy_ObjIsBuf(pNode) ) + { + pNode->TravId = Abc_EdgeFromNode( pFaninNew0 ); + continue; + } + // add the second fanin + pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode ); + // create the new node + if ( Ivy_ObjIsExor(pNode) ) + pObjNew = Abc_AigXor( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); + else + pObjNew = Abc_AigAnd( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); + pNode->TravId = Abc_EdgeFromNode( pObjNew ); + // process the choice nodes + if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 ) + { + pFaninNew = Abc_EdgeToNode( pNtk, pNode->TravId ); +// pFaninNew->fPhase = 0; + assert( !Ivy_IsComplement(pNode->pEquiv) ); + for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { + pFaninNew1 = Abc_EdgeToNode( pNtk, pTemp->TravId ); +// pFaninNew1->fPhase = Ivy_IsComplement( pTemp->pEquiv ); + pFaninNew->pData = pFaninNew1; + pFaninNew = pFaninNew1; + } + pFaninNew->pData = NULL; +// printf( "Writing choice node %d.\n", pNode->Id ); + } + } + // connect the PO nodes + Abc_NtkForEachPo( pNtkOld, pObj, i ) + { + pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) ); + Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); + } + // connect the latches + Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i ) + { + pFaninNew = Abc_ObjFanin0Ivy( pNtk, pNode ); + Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(pNtk, i)), pFaninNew ); + } + Vec_IntFree( vLatches ); + Vec_IntFree( vNodes ); + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld ) +{ + Ivy_Man_t * pMan; + Abc_Obj_t * pObj; + Ivy_Obj_t * pFanin; + int i; + // create the manager + assert( Abc_NtkHasSop(pNtkOld) || Abc_NtkIsStrash(pNtkOld) ); + pMan = Ivy_ManStart(); + // create the PIs + if ( Abc_NtkIsStrash(pNtkOld) ) + Abc_AigConst1(pNtkOld)->pCopy = (Abc_Obj_t *)Ivy_ManConst1(pMan); + Abc_NtkForEachCi( pNtkOld, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Ivy_ObjCreatePi(pMan); + // perform the conversion of the internal nodes + Abc_NtkStrashPerformAig( pNtkOld, pMan ); + // create the POs + Abc_NtkForEachCo( pNtkOld, pObj, i ) + { + pFanin = (Ivy_Obj_t *)Abc_ObjFanin0(pObj)->pCopy; + pFanin = Ivy_NotCond( pFanin, Abc_ObjFaninC0(pObj) ); + Ivy_ObjCreatePo( pMan, pFanin ); + } + Ivy_ManCleanup( pMan ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Prepares the network for strashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ) +{ +// ProgressBar * pProgress; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + vNodes = Abc_NtkDfs( pNtk, 0 ); +// pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { +// Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNode->pCopy = (Abc_Obj_t *)Abc_NodeStrashAig( pMan, pNode ); + } +// Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode ) +{ + int fUseFactor = 1; + char * pSop; + Ivy_Obj_t * pFanin0, * pFanin1; + + assert( Abc_ObjIsNode(pNode) ); + + // consider the case when the graph is an AIG + if ( Abc_NtkIsStrash(pNode->pNtk) ) + { + if ( Abc_AigNodeIsConst(pNode) ) + return Ivy_ManConst1(pMan); + pFanin0 = (Ivy_Obj_t *)Abc_ObjFanin0(pNode)->pCopy; + pFanin0 = Ivy_NotCond( pFanin0, Abc_ObjFaninC0(pNode) ); + pFanin1 = (Ivy_Obj_t *)Abc_ObjFanin1(pNode)->pCopy; + pFanin1 = Ivy_NotCond( pFanin1, Abc_ObjFaninC1(pNode) ); + return Ivy_And( pMan, pFanin0, pFanin1 ); + } + + // get the SOP of the node + if ( Abc_NtkHasMapping(pNode->pNtk) ) + pSop = Mio_GateReadSop(pNode->pData); + else + pSop = pNode->pData; + + // consider the constant node + if ( Abc_NodeIsConst(pNode) ) + return Ivy_NotCond( Ivy_ManConst1(pMan), Abc_SopIsConst0(pSop) ); + + // consider the special case of EXOR function + if ( Abc_SopIsExorType(pSop) ) + return Abc_NodeStrashAigExorAig( pMan, pNode, pSop ); + + // decide when to use factoring + if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 ) + return Abc_NodeStrashAigFactorAig( pMan, pNode, pSop ); + return Abc_NodeStrashAigSopAig( pMan, pNode, pSop ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ) +{ + Abc_Obj_t * pFanin; + Ivy_Obj_t * pAnd, * pSum; + char * pCube; + int i, nFanins; + + // get the number of node's fanins + nFanins = Abc_ObjFaninNum( pNode ); + assert( nFanins == Abc_SopGetVarNum(pSop) ); + // go through the cubes of the node's SOP + pSum = Ivy_Not( Ivy_ManConst1(pMan) ); + Abc_SopForEachCube( pSop, nFanins, pCube ) + { + // create the AND of literals + pAnd = Ivy_ManConst1(pMan); + Abc_ObjForEachFanin( pNode, pFanin, i ) // pFanin can be a net + { + if ( pCube[i] == '1' ) + pAnd = Ivy_And( pMan, pAnd, (Ivy_Obj_t *)pFanin->pCopy ); + else if ( pCube[i] == '0' ) + pAnd = Ivy_And( pMan, pAnd, Ivy_Not((Ivy_Obj_t *)pFanin->pCopy) ); + } + // add to the sum of cubes + pSum = Ivy_Or( pMan, pSum, pAnd ); + } + // decide whether to complement the result + if ( Abc_SopIsComplement(pSop) ) + pSum = Ivy_Not(pSum); + return pSum; +} + +/**Function************************************************************* + + Synopsis [Strashed n-input XOR function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ) +{ + Abc_Obj_t * pFanin; + Ivy_Obj_t * pSum; + int i, nFanins; + // get the number of node's fanins + nFanins = Abc_ObjFaninNum( pNode ); + assert( nFanins == Abc_SopGetVarNum(pSop) ); + // go through the cubes of the node's SOP + pSum = Ivy_Not( Ivy_ManConst1(pMan) ); + for ( i = 0; i < nFanins; i++ ) + { + pFanin = Abc_ObjFanin( pNode, i ); + pSum = Ivy_Exor( pMan, pSum, (Ivy_Obj_t *)pFanin->pCopy ); + } + if ( Abc_SopIsComplement(pSop) ) + pSum = Ivy_Not(pSum); + return pSum; +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pRoot, char * pSop ) +{ + Dec_Graph_t * pFForm; + Dec_Node_t * pNode; + Ivy_Obj_t * pAnd; + int i; + +// extern Ivy_Obj_t * Dec_GraphToNetworkAig( Ivy_Man_t * pMan, Dec_Graph_t * pGraph ); + extern Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph ); + +// assert( 0 ); + + // perform factoring + pFForm = Dec_Factor( pSop ); + // collect the fanins + Dec_GraphForEachLeaf( pFForm, pNode, i ) + pNode->pFunc = Abc_ObjFanin(pRoot,i)->pCopy; + // perform strashing +// pAnd = Dec_GraphToNetworkAig( pMan, pFForm ); + pAnd = Dec_GraphToNetworkIvy( pMan, pFForm ); +// pAnd = NULL; + + Dec_GraphFree( pFForm ); + return pAnd; +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs ) +{ + Abc_Obj_t * pLatch; + Vec_Int_t * vArray; + int i; + vArray = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( fUseDcs || Abc_LatchIsInitDc(pLatch) ) + Vec_IntPush( vArray, IVY_INIT_DC ); + else if ( Abc_LatchIsInit1(pLatch) ) + Vec_IntPush( vArray, IVY_INIT_1 ); + else if ( Abc_LatchIsInit0(pLatch) ) + Vec_IntPush( vArray, IVY_INIT_0 ); + else assert( 0 ); + } + return vArray; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcLut.c b/abc70930/src/base/abci/abcLut.c new file mode 100644 index 00000000..afa76cc8 --- /dev/null +++ b/abc70930/src/base/abci/abcLut.c @@ -0,0 +1,786 @@ +/**CFile**************************************************************** + + FileName [abcLut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Superchoicing for K-LUTs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "cut.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define SCL_LUT_MAX 6 // the maximum LUT size +#define SCL_VARS_MAX 15 // the maximum number of variables +#define SCL_NODE_MAX 1000 // the maximum number of nodes + +typedef struct Abc_ManScl_t_ Abc_ManScl_t; +struct Abc_ManScl_t_ +{ + // paramers + int nLutSize; // the LUT size + int nCutSizeMax; // the max number of leaves of the cone + int nNodesMax; // the max number of divisors in the cone + int nWords; // the number of machine words in sim info + // structural representation of the cone + Vec_Ptr_t * vLeaves; // leaves of the cut + Vec_Ptr_t * vVolume; // volume of the cut + int pBSet[SCL_VARS_MAX]; // bound set + // functional representation of the cone + unsigned * uTruth; // truth table of the cone + // representation of truth tables + unsigned ** uVars; // elementary truth tables + unsigned ** uSims; // truth tables of the nodes + unsigned ** uCofs; // truth tables of the cofactors +}; + +static Vec_Ptr_t * s_pLeaves = NULL; + +static Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize ); +static Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax ); +static void Abc_ManSclStop( Abc_ManScl_t * p ); +static void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj ); + +static Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * pManScl, Abc_Obj_t * pObj ); +static int Abc_NodeDecomposeStep( Abc_ManScl_t * pManScl ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs superchoicing for K-LUTs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose ) +{ + ProgressBar * pProgress; + Abc_ManCut_t * pManCut; + Abc_ManScl_t * pManScl; + Cut_Man_t * pManCuts; + Abc_Obj_t * pObj, * pFanin, * pObjTop; + int i, LevelMax, nNodes; + int nNodesTried, nNodesDec, nNodesExist, nNodesUsed; + + assert( Abc_NtkIsSopLogic(pNtk) ); + if ( nLutSize < 3 || nLutSize > SCL_LUT_MAX ) + { + printf( "LUT size (%d) does not belong to the interval: 3 <= LUT size <= %d\n", nLutSize, SCL_LUT_MAX ); + return 0; + } + if ( nCutSizeMax <= nLutSize || nCutSizeMax > SCL_VARS_MAX ) + { + printf( "Cut size (%d) does not belong to the interval: LUT size (%d) < Cut size <= %d\n", nCutSizeMax, nLutSize, SCL_VARS_MAX ); + return 0; + } + + assert( nLutSize <= SCL_LUT_MAX ); + assert( nCutSizeMax <= SCL_VARS_MAX ); + nNodesTried = nNodesDec = nNodesExist = nNodesUsed = 0; + + // set the delays of the CIs + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->Level = 0; + +//Abc_NtkLevel( pNtk ); + + // start the managers + pManScl = Abc_ManSclStart( nLutSize, nCutSizeMax, 1000 ); + pManCuts = Abc_NtkStartCutManForScl( pNtk, nLutSize ); + pManCut = Abc_NtkManCutStart( nCutSizeMax, 100000, 100000, 100000 ); + s_pLeaves = Abc_NtkManCutReadCutSmall( pManCut ); + pManScl->vVolume = Abc_NtkManCutReadVisited( pManCut ); + + // process each internal node (assuming topological order of nodes!!!) + nNodes = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { +// if ( i != nNodes-1 ) +// continue; + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( i >= nNodes ) + break; + if ( Abc_ObjFaninNum(pObj) != 2 ) + continue; + nNodesTried++; + + // map this node using regular cuts +// pObj->Level = 0; + Abc_NodeLutMap( pManCuts, pObj ); + // compute the cut + pManScl->vLeaves = Abc_NodeFindCut( pManCut, pObj, 0 ); + if ( Vec_PtrSize(pManScl->vLeaves) <= nLutSize ) + continue; + // get the volume of the cut + if ( Vec_PtrSize(pManScl->vVolume) > SCL_NODE_MAX ) + continue; + nNodesDec++; + + // decompose the cut + pObjTop = Abc_NodeSuperChoiceLut( pManScl, pObj ); + if ( pObjTop == NULL ) + continue; + nNodesExist++; + + // if there is no delay improvement, skip; otherwise, update level + if ( pObjTop->Level >= pObj->Level ) + { + Abc_NtkDeleteObj_rec( pObjTop, 1 ); + continue; + } + pObj->Level = pObjTop->Level; + nNodesUsed++; + } + Extra_ProgressBarStop( pProgress ); + + // delete the managers + Abc_ManSclStop( pManScl ); + Abc_NtkManCutStop( pManCut ); + Cut_ManStop( pManCuts ); + + // get the largest arrival time + LevelMax = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pFanin = Abc_ObjFanin0( pObj ); + // skip inv/buf + if ( Abc_ObjFaninNum(pFanin) == 1 ) + pFanin = Abc_ObjFanin0( pFanin ); + // get the new level + LevelMax = ABC_MAX( LevelMax, (int)pFanin->Level ); + } + + if ( fVerbose ) + printf( "Try = %d. Dec = %d. Exist = %d. Use = %d. SUPER = %d levels of %d-LUTs.\n", + nNodesTried, nNodesDec, nNodesExist, nNodesUsed, LevelMax, nLutSize ); +// if ( fVerbose ) +// printf( "The network is superchoiced for %d levels of %d-LUTs.\n", LevelMax, nLutSize ); + + // clean the data field + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pNext = NULL; + + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkSuperChoiceLut: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs LUT mapping of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj ) +{ + Cut_Cut_t * pCut; + Abc_Obj_t * pFanin; + int i, DelayMax; + pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCuts, pObj, 0, 0 ); + assert( pCut != NULL ); + assert( pObj->Level == 0 ); + // go through the cuts + pObj->Level = ABC_INFINITY; + for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) + { + DelayMax = 0; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + pFanin = Abc_NtkObj( pObj->pNtk, pCut->pLeaves[i] ); +// assert( Abc_ObjIsCi(pFanin) || pFanin->Level > 0 ); // should hold if node ordering is topological + if ( DelayMax < (int)pFanin->Level ) + DelayMax = pFanin->Level; + } + if ( (int)pObj->Level > DelayMax ) + pObj->Level = DelayMax; + } + assert( pObj->Level < ABC_INFINITY ); + pObj->Level++; +// printf( "%d(%d) ", pObj->Id, pObj->Level ); +} + +/**Function************************************************************* + + Synopsis [Starts the cut manager for rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize ) +{ + static Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pManCut; + Abc_Obj_t * pObj; + int i; + // start the cut manager + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = nLutSize; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 500; // the max number of cuts kept at a node + pParams->fTruth = 0; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fSeq = 0; // compute sequential cuts + pParams->fDrop = 0; // drop cuts on the fly + pParams->fVerbose = 0; // the verbosiness flag + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + pManCut = Cut_ManStart( pParams ); + if ( pParams->fDrop ) + Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( pManCut, pObj->Id ); + return pManCut; +} + +/**Function************************************************************* + + Synopsis [Starts the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax ) +{ + Abc_ManScl_t * p; + int i, k; + assert( sizeof(unsigned) == 4 ); + p = ALLOC( Abc_ManScl_t, 1 ); + memset( p, 0, sizeof(Abc_ManScl_t) ); + p->nLutSize = nLutSize; + p->nCutSizeMax = nCutSizeMax; + p->nNodesMax = nNodesMax; + p->nWords = Extra_TruthWordNum(nCutSizeMax); + // allocate simulation info + p->uVars = (unsigned **)Extra_ArrayAlloc( nCutSizeMax, p->nWords, 4 ); + p->uSims = (unsigned **)Extra_ArrayAlloc( nNodesMax, p->nWords, 4 ); + p->uCofs = (unsigned **)Extra_ArrayAlloc( 2 << nLutSize, p->nWords, 4 ); + memset( p->uVars[0], 0, nCutSizeMax * p->nWords * 4 ); + // assign elementary truth tables + for ( k = 0; k < p->nCutSizeMax; k++ ) + for ( i = 0; i < p->nWords * 32; i++ ) + if ( i & (1 << k) ) + p->uVars[k][i>>5] |= (1 << (i&31)); + // other data structures +// p->vBound = Vec_IntAlloc( nCutSizeMax ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManSclStop( Abc_ManScl_t * p ) +{ +// Vec_IntFree( p->vBound ); + free( p->uVars ); + free( p->uSims ); + free( p->uCofs ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Abc_NodeSuperChoiceTruth( Abc_ManScl_t * pManScl ) +{ + Abc_Obj_t * pObj; + unsigned * puData0, * puData1, * puData; + char * pSop; + int i, k; + // set elementary truth tables + Vec_PtrForEachEntry( pManScl->vLeaves, pObj, i ) + pObj->pNext = (Abc_Obj_t *)pManScl->uVars[i]; + // compute truth tables for internal nodes + Vec_PtrForEachEntry( pManScl->vVolume, pObj, i ) + { + // set storage for the node's simulation info + pObj->pNext = (Abc_Obj_t *)pManScl->uSims[i]; + // get pointer to the simulation info + puData = (unsigned *)pObj->pNext; + puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pNext; + puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pNext; + // simulate + pSop = pObj->pData; + if ( pSop[0] == '0' && pSop[1] == '0' ) + for ( k = 0; k < pManScl->nWords; k++ ) + puData[k] = ~puData0[k] & ~puData1[k]; + else if ( pSop[0] == '0' ) + for ( k = 0; k < pManScl->nWords; k++ ) + puData[k] = ~puData0[k] & puData1[k]; + else if ( pSop[1] == '0' ) + for ( k = 0; k < pManScl->nWords; k++ ) + puData[k] = puData0[k] & ~puData1[k]; + else + for ( k = 0; k < pManScl->nWords; k++ ) + puData[k] = puData0[k] & puData1[k]; + } + return puData; +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSuperChoiceCollect2_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vVolume ) +{ + if ( pObj->fMarkC ) + return; + pObj->fMarkC = 1; + assert( Abc_ObjFaninNum(pObj) == 2 ); + Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin0(pObj), vVolume ); + Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin1(pObj), vVolume ); + Vec_PtrPush( vVolume, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSuperChoiceCollect2( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) +{ + Abc_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->fMarkC = 1; + Vec_PtrClear( vVolume ); + Abc_NodeSuperChoiceCollect2_rec( pRoot, vVolume ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->fMarkC = 0; + Vec_PtrForEachEntry( vVolume, pObj, i ) + pObj->fMarkC = 0; +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSuperChoiceCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) +{ + if ( pObj->fMarkB ) + { + Vec_PtrPush( vLeaves, pObj ); + pObj->fMarkB = 0; + } + if ( pObj->fMarkC ) + return; + pObj->fMarkC = 1; + assert( Abc_ObjFaninNum(pObj) == 2 ); + Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin0(pObj), vLeaves, vVolume ); + Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin1(pObj), vLeaves, vVolume ); + Vec_PtrPush( vVolume, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [Orders the leaves topologically.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSuperChoiceCollect( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) +{ + Abc_Obj_t * pObj; + int i, nLeaves; + nLeaves = Vec_PtrSize(vLeaves); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->fMarkB = pObj->fMarkC = 1; + Vec_PtrClear( vVolume ); + Vec_PtrClear( vLeaves ); + Abc_NodeSuperChoiceCollect_rec( pRoot, vLeaves, vVolume ); + assert( Vec_PtrSize(vLeaves) == nLeaves ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->fMarkC = 0; + Vec_PtrForEachEntry( vVolume, pObj, i ) + pObj->fMarkC = 0; +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeLeavesRemove( Vec_Ptr_t * vLeaves, unsigned uPhase, int nVars ) +{ + int i; + for ( i = nVars - 1; i >= 0; i-- ) + if ( uPhase & (1 << i) ) + Vec_PtrRemove( vLeaves, Vec_PtrEntry(vLeaves, i) ); +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeGetLevel( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i, Level; + Level = 0; + Abc_ObjForEachFanin( pObj, pFanin, i ) + Level = ABC_MAX( Level, (int)pFanin->Level ); + return Level + 1; +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * p, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin, * pObjNew; + int i, nVars, uSupport, nSuppVars; + // collect the cone using DFS (excluding leaves) + Abc_NodeSuperChoiceCollect2( pObj, p->vLeaves, p->vVolume ); + assert( Vec_PtrEntryLast(p->vVolume) == pObj ); + // compute the truth table + p->uTruth = Abc_NodeSuperChoiceTruth( p ); + // get the support of this truth table + nVars = Vec_PtrSize(p->vLeaves); + uSupport = Extra_TruthSupport(p->uTruth, nVars); + nSuppVars = Extra_WordCountOnes(uSupport); + assert( nSuppVars <= nVars ); + if ( nSuppVars == 0 ) + { + pObj->Level = 0; + return NULL; + } + if ( nSuppVars == 1 ) + { + // find the variable + for ( i = 0; i < nVars; i++ ) + if ( uSupport & (1 << i) ) + break; + assert( i < nVars ); + pFanin = Vec_PtrEntry( p->vLeaves, i ); + pObj->Level = pFanin->Level; + return NULL; + } + // support-minimize the truth table + if ( nSuppVars != nVars ) + { + Extra_TruthShrink( p->uCofs[0], p->uTruth, nSuppVars, nVars, uSupport ); + Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars ); + Abc_NodeLeavesRemove( p->vLeaves, ((1 << nVars) - 1) & ~uSupport, nVars ); + } +// return NULL; + // decompose the truth table recursively + while ( Vec_PtrSize(p->vLeaves) > p->nLutSize ) + if ( !Abc_NodeDecomposeStep( p ) ) + { + Vec_PtrForEachEntry( p->vLeaves, pFanin, i ) + if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 0 ) + Abc_NtkDeleteObj_rec( pFanin, 1 ); + return NULL; + } + // create the topmost node + pObjNew = Abc_NtkCreateNode( pObj->pNtk ); + Vec_PtrForEachEntry( p->vLeaves, pFanin, i ) + Abc_ObjAddFanin( pObjNew, pFanin ); + // create the function + pObjNew->pData = Abc_SopCreateFromTruth( pObj->pNtk->pManFunc, Vec_PtrSize(p->vLeaves), p->uTruth ); // need ISOP + pObjNew->Level = Abc_NodeGetLevel( pObjNew ); + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in increasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareLevelsInc( int * pp1, int * pp2 ) +{ + Abc_Obj_t * pNode1, * pNode2; + pNode1 = Vec_PtrEntry(s_pLeaves, *pp1); + pNode2 = Vec_PtrEntry(s_pLeaves, *pp2); + if ( pNode1->Level < pNode2->Level ) + return -1; + if ( pNode1->Level > pNode2->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Selects the earliest arriving nodes from the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeDecomposeSort( Abc_Obj_t ** pLeaves, int nVars, int * pBSet, int nLutSize ) +{ + Abc_Obj_t * pTemp[SCL_VARS_MAX]; + int i, k, kBest, LevelMin; + assert( nLutSize < nVars ); + assert( nVars <= SCL_VARS_MAX ); + // copy nodes into the internal storage +// printf( "(" ); + for ( i = 0; i < nVars; i++ ) + { + pTemp[i] = pLeaves[i]; +// printf( " %d", pLeaves[i]->Level ); + } +// printf( " )\n" ); + // choose one node at a time + for ( i = 0; i < nLutSize; i++ ) + { + kBest = -1; + LevelMin = ABC_INFINITY; + for ( k = 0; k < nVars; k++ ) + if ( pTemp[k] && LevelMin > (int)pTemp[k]->Level ) + { + LevelMin = pTemp[k]->Level; + kBest = k; + } + pBSet[i] = kBest; + pTemp[kBest] = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Performs superchoicing for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeDecomposeStep( Abc_ManScl_t * p ) +{ + static char pCofClasses[1<vLeaves, 0))->pNtk; + // find the earliest nodes + nVars = Vec_PtrSize(p->vLeaves); + assert( nVars > p->nLutSize ); +/* + for ( v = 0; v < nVars; v++ ) + p->pBSet[v] = v; + qsort( (void *)p->pBSet, nVars, sizeof(int), + (int (*)(const void *, const void *)) Abc_NodeCompareLevelsInc ); +*/ + Abc_NodeDecomposeSort( (Abc_Obj_t **)Vec_PtrArray(p->vLeaves), Vec_PtrSize(p->vLeaves), p->pBSet, p->nLutSize ); + assert( ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[0]))->Level <= + ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[1]))->Level ); + // cofactor w.r.t. the selected variables + Extra_TruthCopy( p->uCofs[1], p->uTruth, nVars ); + c = 2; + for ( v = 0; v < p->nLutSize; v++ ) + for ( k = 0; k < (1<uCofs[c], p->uCofs[c/2], nVars ); + Extra_TruthCopy( p->uCofs[c+1], p->uCofs[c/2], nVars ); + Extra_TruthCofactor0( p->uCofs[c], nVars, p->pBSet[v] ); + Extra_TruthCofactor1( p->uCofs[c+1], nVars, p->pBSet[v] ); + c += 2; + } + assert( c == (2 << p->nLutSize) ); + // count unique cofactors + nClasses = 0; + nCofs = (1 << p->nLutSize); + for ( i = 0; i < nCofs; i++ ) + { + pTruthCof = p->uCofs[ nCofs + i ]; + for ( k = 0; k < nClasses; k++ ) + { + pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ]; + if ( Extra_TruthIsEqual( pTruthCof, pTruthClass, nVars ) ) + { + pCofClasses[k][ nCofClasses[k]++ ] = i; + break; + } + } + if ( k != nClasses ) + continue; + // not found + pCofClasses[nClasses][0] = i; + nCofClasses[nClasses] = 1; + nClasses++; + if ( nClasses > nCofs/2 ) + return 0; + } + // the number of cofactors is acceptable + nVarsNew = Extra_Base2Log( nClasses ); + assert( nVarsNew < p->nLutSize ); + // create the remainder truth table + // for each class of cofactors, multiply cofactor truth table by its code + Extra_TruthClear( p->uTruth, nVars ); + for ( k = 0; k < nClasses; k++ ) + { + pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ]; + for ( v = 0; v < nVarsNew; v++ ) + if ( k & (1 << v) ) + Extra_TruthAnd( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars ); + else + Extra_TruthSharp( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars ); + Extra_TruthOr( p->uTruth, p->uTruth, pTruthClass, nVars ); + } + // create nodes + pTruth = p->uCofs[0]; + for ( v = 0; v < nVarsNew; v++ ) + { + Extra_TruthClear( pTruth, p->nLutSize ); + for ( k = 0; k < nClasses; k++ ) + if ( k & (1 << v) ) + for ( i = 0; i < nCofClasses[k]; i++ ) + { + pTruthCof = p->uCofs[1]; + Extra_TruthFill( pTruthCof, p->nLutSize ); + for ( w = 0; w < p->nLutSize; w++ ) + if ( pCofClasses[k][i] & (1 << (p->nLutSize-1-w)) ) + Extra_TruthAnd( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize ); + else + Extra_TruthSharp( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize ); + Extra_TruthOr( pTruth, pTruth, pTruthCof, p->nLutSize ); + } + // implement the node + pObjNew = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < p->nLutSize; i++ ) + { + pFanin = Vec_PtrEntry( p->vLeaves, p->pBSet[i] ); + Abc_ObjAddFanin( pObjNew, pFanin ); + } + // create the function + pObjNew->pData = Abc_SopCreateFromTruth( pNtk->pManFunc, p->nLutSize, pTruth ); // need ISOP + pObjNew->Level = Abc_NodeGetLevel( pObjNew ); + pNodesNew[v] = pObjNew; + } + // put the new nodes back into the list + for ( v = 0; v < nVarsNew; v++ ) + Vec_PtrWriteEntry( p->vLeaves, p->pBSet[v], pNodesNew[v] ); + // compute the variables that should be removed + uPhase = 0; + for ( v = nVarsNew; v < p->nLutSize; v++ ) + uPhase |= (1 << p->pBSet[v]); + // remove entries from the array + Abc_NodeLeavesRemove( p->vLeaves, uPhase, nVars ); + // update truth table + Extra_TruthShrink( p->uCofs[0], p->uTruth, nVars - p->nLutSize + nVarsNew, nVars, ((1 << nVars) - 1) & ~uPhase ); + Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars ); + assert( !Extra_TruthVarInSupport( p->uTruth, nVars, nVars - p->nLutSize + nVarsNew ) ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMap.c b/abc70930/src/base/abci/abcMap.c new file mode 100644 index 00000000..d4d50923 --- /dev/null +++ b/abc70930/src/base/abci/abcMap.c @@ -0,0 +1,657 @@ +/**CFile**************************************************************** + + FileName [abcMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface with the SC mapping package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mio.h" +#include "mapper.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ); +static Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk ); +static Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ); +static Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ); +static Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ); + +static Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ); +static void Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ); +static void Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase ); +static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Interface with the mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int fSwitching, int fVerbose ) +{ + int fShowSwitching = 1; + Abc_Ntk_t * pNtkNew; + Map_Man_t * pMan; + Vec_Int_t * vSwitching; + float * pSwitching = NULL; + int clk; + + assert( Abc_NtkIsStrash(pNtk) ); + + // check that the library is available + if ( Abc_FrameReadLibGen() == NULL ) + { + printf( "The current library is not available.\n" ); + return 0; + } + + // derive the supergate library + if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() ) + { + printf( "A simple supergate library is derived from gate library \"%s\".\n", + Mio_LibraryReadName(Abc_FrameReadLibGen()) ); + Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() ); + } + + // print a warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing mapping with choices.\n" ); + + // compute switching activity + fShowSwitching |= fSwitching; + if ( fShowSwitching ) + { + extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ); + vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 ); + pSwitching = (float *)vSwitching->pArray; + } + + // perform the mapping + pMan = Abc_NtkToMap( pNtk, DelayTarget, fRecovery, pSwitching, fVerbose ); + if ( pSwitching ) Vec_IntFree( vSwitching ); + if ( pMan == NULL ) + return NULL; +clk = clock(); + Map_ManSetSwitching( pMan, fSwitching ); + if ( !Map_Mapping( pMan ) ) + { + Map_ManFree( pMan ); + return NULL; + } +// Map_ManPrintStatsToFile( pNtk->pSpec, Map_ManReadAreaFinal(pMan), Map_ManReadRequiredGlo(pMan), clock()-clk ); + + // reconstruct the network after mapping + pNtkNew = Abc_NtkFromMap( pMan, pNtk ); + if ( pNtkNew == NULL ) + return NULL; + Map_ManFree( pMan ); + + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkMap: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Load the network into manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ) +{ + Map_Man_t * pMan; + ProgressBar * pProgress; + Map_Node_t * pNodeMap; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanin, * pPrev; + int i; + + assert( Abc_NtkIsStrash(pNtk) ); + + // start the mapping manager and set its parameters + pMan = Map_ManCreate( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk), Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk), fVerbose ); + if ( pMan == NULL ) + return NULL; + Map_ManSetAreaRecovery( pMan, fRecovery ); + Map_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); + Map_ManSetDelayTarget( pMan, (float)DelayTarget ); + Map_ManSetInputArrivals( pMan, (Map_Time_t *)Abc_NtkGetCiArrivalTimes(pNtk) ); + + // create PIs and remember them in the old nodes + Abc_NtkCleanCopy( pNtk ); + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan); + Abc_NtkForEachCi( pNtk, pNode, i ) + { + pNodeMap = Map_ManReadInputs(pMan)[i]; + pNode->pCopy = (Abc_Obj_t *)pNodeMap; + if ( pSwitching ) + Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); + } + + // load the AIG into the mapper + vNodes = Abc_AigDfs( pNtk, 0, 0 ); + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // add the node to the mapper + pNodeMap = Map_NodeAnd( pMan, + Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), + Map_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); + assert( pNode->pCopy == NULL ); + // remember the node + pNode->pCopy = (Abc_Obj_t *)pNodeMap; + if ( pSwitching ) + Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); + // set up the choice node + if ( Abc_AigNodeIsChoice( pNode ) ) + for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) + { + Map_NodeSetNextE( (Map_Node_t *)pPrev->pCopy, (Map_Node_t *)pFanin->pCopy ); + Map_NodeSetRepr( (Map_Node_t *)pFanin->pCopy, (Map_Node_t *)pNode->pCopy ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + + // set the primary outputs in the required phase + Abc_NtkForEachCo( pNtk, pNode, i ) + Map_ManReadOutputs(pMan)[i] = Map_NotCond( (Map_Node_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew; + Map_Node_t * pNodeMap; + Abc_Obj_t * pNode, * pNodeNew; + int i, nDupGates; + // create the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP ); + // make the mapper point to the new network + Map_ManCleanData( pMan ); + Abc_NtkForEachCi( pNtk, pNode, i ) + Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy ); + // assign the mapping of the required phase to the POs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNodeMap = Map_ManReadOutputs(pMan)[i]; + pNodeNew = Abc_NodeFromMap_rec( pNtkNew, Map_Regular(pNodeMap), !Map_IsComplement(pNodeMap) ); + assert( !Abc_ObjIsComplement(pNodeNew) ); + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + } + Extra_ProgressBarStop( pProgress ); + // decouple the PO driver nodes to reduce the number of levels + nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); +// if ( nDupGates && Map_ManReadVerbose(pMan) ) +// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Constructs the nodes corrresponding to one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ) +{ + Abc_Obj_t * pNodeNew, * pNodeInv; + + // check the case of constant node + if ( Map_NodeIsConst(pNodeMap) ) + return fPhase? Abc_NtkCreateNodeConst1(pNtkNew) : Abc_NtkCreateNodeConst0(pNtkNew); + + // check if the phase is already implemented + pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase ); + if ( pNodeNew ) + return pNodeNew; + + // implement the node if the best cut is assigned + if ( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL ) + return Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, fPhase ); + + // if the cut is not assigned, implement the node + assert( Map_NodeReadCutBest(pNodeMap, !fPhase) != NULL || Map_NodeIsConst(pNodeMap) ); + pNodeNew = Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, !fPhase ); + + // add the inverter + pNodeInv = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pNodeInv, pNodeNew ); + pNodeInv->pData = Mio_LibraryReadInv(Map_ManReadGenLib(Map_NodeReadMan(pNodeMap))); + + // set the inverter + Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeInv ); + return pNodeInv; +} + +/**Function************************************************************* + + Synopsis [Constructs the nodes corrresponding to one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ) +{ + Abc_Obj_t * pNodePIs[10]; + Abc_Obj_t * pNodeNew; + Map_Node_t ** ppLeaves; + Map_Cut_t * pCutBest; + Map_Super_t * pSuperBest; + unsigned uPhaseBest; + int i, fInvPin, nLeaves; + + // make sure the node can be implemented in this phase + assert( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL || Map_NodeIsConst(pNodeMap) ); + // check if the phase is already implemented + pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase ); + if ( pNodeNew ) + return pNodeNew; + + // get the information about the best cut + pCutBest = Map_NodeReadCutBest( pNodeMap, fPhase ); + pSuperBest = Map_CutReadSuperBest( pCutBest, fPhase ); + uPhaseBest = Map_CutReadPhaseBest( pCutBest, fPhase ); + nLeaves = Map_CutReadLeavesNum( pCutBest ); + ppLeaves = Map_CutReadLeaves( pCutBest ); + + // collect the PI nodes + for ( i = 0; i < nLeaves; i++ ) + { + fInvPin = ((uPhaseBest & (1 << i)) > 0); + pNodePIs[i] = Abc_NodeFromMap_rec( pNtkNew, ppLeaves[i], !fInvPin ); + assert( pNodePIs[i] != NULL ); + } + + // implement the supergate + pNodeNew = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, pSuperBest, pNodePIs, nLeaves ); + Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeNew ); + return pNodeNew; +} + +/**Function************************************************************* + + Synopsis [Constructs the nodes corrresponding to one supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ) +{ + Mio_Gate_t * pRoot; + Map_Super_t ** ppFanins; + Abc_Obj_t * pNodeNew, * pNodeFanin; + int nFanins, Number, i; + + // get the parameters of the supergate + pRoot = Map_SuperReadRoot(pSuper); + if ( pRoot == NULL ) + { + Number = Map_SuperReadNum(pSuper); + if ( Number < nNodePis ) + { + return pNodePis[Number]; + } + else + { +// assert( 0 ); + /* It might happen that a super gate with 5 inputs is constructed that + * actually depends only on the first four variables; i.e the fifth is a + * don't care -- in that case we connect constant node for the fifth + * (since the cut only has 4 variables). An interesting question is what + * if the first variable (and not the fifth one is the redundant one; + * can that happen?) */ + return Abc_NtkCreateNodeConst0(pNtkNew); + } + } + + // get information about the fanins of the supergate + nFanins = Map_SuperReadFaninNum( pSuper ); + ppFanins = Map_SuperReadFanins( pSuper ); + // create a new node with these fanins + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < nFanins; i++ ) + { + pNodeFanin = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, ppFanins[i], pNodePis, nNodePis ); + Abc_ObjAddFanin( pNodeNew, pNodeFanin ); + } + pNodeNew->pData = pRoot; + return pNodeNew; +} + + + + + +/**Function************************************************************* + + Synopsis [Interface with the mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + + Map_Man_t * pMan; + + assert( Abc_NtkIsStrash(pNtk) ); + + // check that the library is available + if ( Abc_FrameReadLibGen() == NULL ) + { + printf( "The current library is not available.\n" ); + return 0; + } + + // derive the supergate library + if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() ) + { + printf( "A simple supergate library is derived from gate library \"%s\".\n", + Mio_LibraryReadName(Abc_FrameReadLibGen()) ); + Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() ); + } + + // print a warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing mapping with choices.\n" ); + + // perform the mapping + pMan = Abc_NtkToMap( pNtk, -1, 1, NULL, 0 ); + if ( pMan == NULL ) + return NULL; + if ( !Map_Mapping( pMan ) ) + { + Map_ManFree( pMan ); + return NULL; + } + + // reconstruct the network after mapping + pNtkNew = Abc_NtkFromMapSuperChoice( pMan, pNtk ); + if ( pNtkNew == NULL ) + return NULL; + Map_ManFree( pMan ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkMap: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); + ProgressBar * pProgress; + Abc_Ntk_t * pNtkNew, * pNtkNew2; + Abc_Obj_t * pNode; + int i; + + // save the pointer to the mapped nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pNext = pNode->pCopy; + Abc_NtkForEachPo( pNtk, pNode, i ) + pNode->pNext = pNode->pCopy; + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->pNext = pNode->pCopy; + + // duplicate the network + pNtkNew2 = Abc_NtkDup( pNtk ); + pNtkNew = Abc_NtkMulti( pNtkNew2, 0, 20, 0, 0, 1, 0 ); + if ( !Abc_NtkBddToSop( pNtkNew, 0 ) ) + { + printf( "Abc_NtkFromMapSuperChoice(): Converting to SOPs has failed.\n" ); + return NULL; + } + + // set the old network to point to the new network + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = pNode->pCopy->pCopy; + Abc_NtkForEachPo( pNtk, pNode, i ) + pNode->pCopy = pNode->pCopy->pCopy; + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->pCopy = pNode->pCopy->pCopy; + Abc_NtkDelete( pNtkNew2 ); + + // set the pointers from the mapper to the new nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + { + Map_NodeSetData( Map_ManReadInputs(pMan)[i], 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) ); + Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy ); + } + Abc_NtkForEachNode( pNtk, pNode, i ) + { +// if ( Abc_NodeIsConst(pNode) ) +// continue; + Map_NodeSetData( (Map_Node_t *)pNode->pNext, 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) ); + Map_NodeSetData( (Map_Node_t *)pNode->pNext, 1, (char *)pNode->pCopy ); + } + + // assign the mapping of the required phase to the POs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); +// if ( Abc_NodeIsConst(pNode) ) +// continue; + Abc_NodeSuperChoice( pNtkNew, pNode ); + } + Extra_ProgressBarStop( pProgress ); + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Creates the mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) +{ + Map_Node_t * pMapNode = (Map_Node_t *)pNode->pNext; + Map_Cut_t * pCuts, * pTemp; + + pCuts = Map_NodeReadCuts(pMapNode); + for ( pTemp = Map_CutReadNext(pCuts); pTemp; pTemp = Map_CutReadNext(pTemp) ) + { + Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 0 ); + Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 1 ); + } +} + + +/**Function************************************************************* + + Synopsis [Constructs the nodes corrresponding to one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase ) +{ + Abc_Obj_t * pNodePIs[10]; + Map_Node_t ** ppLeaves; + Map_Super_t * pSuperBest; + unsigned uPhaseBest; + int i, fInvPin, nLeaves; + + pSuperBest = Map_CutReadSuperBest( pCut, fPhase ); + if ( pSuperBest == NULL ) + return; + + // get the information about the best cut + uPhaseBest = Map_CutReadPhaseBest( pCut, fPhase ); + nLeaves = Map_CutReadLeavesNum( pCut ); + ppLeaves = Map_CutReadLeaves( pCut ); + + // collect the PI nodes + for ( i = 0; i < nLeaves; i++ ) + { + fInvPin = ((uPhaseBest & (1 << i)) > 0); + pNodePIs[i] = (Abc_Obj_t *)Map_NodeReadData( ppLeaves[i], !fInvPin ); + assert( pNodePIs[i] != NULL ); + } + + // implement the supergate + Abc_NodeFromMapSuperChoice_rec( pNtkNew, pSuperBest, pNodePIs, nLeaves ); +} + + +/**Function************************************************************* + + Synopsis [Constructs the nodes corrresponding to one supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ) +{ + Mio_Gate_t * pRoot; + Map_Super_t ** ppFanins; + Abc_Obj_t * pNodeNew, * pNodeFanin; + int nFanins, Number, i; + + // get the parameters of the supergate + pRoot = Map_SuperReadRoot(pSuper); + if ( pRoot == NULL ) + { + Number = Map_SuperReadNum(pSuper); + if ( Number < nNodePis ) + { + return pNodePis[Number]; + } + else + { +// assert( 0 ); + /* It might happen that a super gate with 5 inputs is constructed that + * actually depends only on the first four variables; i.e the fifth is a + * don't care -- in that case we connect constant node for the fifth + * (since the cut only has 4 variables). An interesting question is what + * if the first variable (and not the fifth one is the redundant one; + * can that happen?) */ + return Abc_NtkCreateNodeConst0(pNtkNew); + } + } + + // get information about the fanins of the supergate + nFanins = Map_SuperReadFaninNum( pSuper ); + ppFanins = Map_SuperReadFanins( pSuper ); + // create a new node with these fanins + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < nFanins; i++ ) + { + pNodeFanin = Abc_NodeFromMapSuperChoice_rec( pNtkNew, ppFanins[i], pNodePis, nNodePis ); + Abc_ObjAddFanin( pNodeNew, pNodeFanin ); + } + pNodeNew->pData = Abc_SopRegister( pNtkNew->pManFunc, Mio_GateReadSop(pRoot) ); + return pNodeNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMeasure.c b/abc70930/src/base/abci/abcMeasure.c new file mode 100644 index 00000000..6604a0c4 --- /dev/null +++ b/abc70930/src/base/abci/abcMeasure.c @@ -0,0 +1,478 @@ +/**CFile**************************************************************** + + FileName [abc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintMeasures( unsigned * pTruth, int nVars ) +{ + unsigned uCofs[10][32]; + int i, k, nOnes; + + // total pairs + nOnes = Kit_TruthCountOnes( uCofs[0], nVars ); + printf( "Total = %d.\n", nOnes * ((1 << nVars) - nOnes) ); + + // print measures for individual variables + for ( i = 0; i < nVars; i++ ) + { + Kit_TruthUniqueNew( uCofs[0], pTruth, nVars, i ); + nOnes = Kit_TruthCountOnes( uCofs[0], nVars ); + printf( "%7d ", nOnes ); + } + printf( "\n" ); + + // consider pairs + for ( i = 0; i < nVars; i++ ) + for ( k = 0; k < nVars; k++ ) + { + if ( i == k ) + { + printf( " " ); + continue; + } + Kit_TruthCofactor0New( uCofs[0], pTruth, nVars, i ); + Kit_TruthCofactor1New( uCofs[1], pTruth, nVars, i ); + + Kit_TruthCofactor0New( uCofs[2], uCofs[0], nVars, k ); // 00 + Kit_TruthCofactor1New( uCofs[3], uCofs[0], nVars, k ); // 01 + Kit_TruthCofactor0New( uCofs[4], uCofs[1], nVars, k ); // 10 + Kit_TruthCofactor1New( uCofs[5], uCofs[1], nVars, k ); // 11 + + Kit_TruthAndPhase( uCofs[6], uCofs[2], uCofs[5], nVars, 0, 1 ); // 00 & 11' + Kit_TruthAndPhase( uCofs[7], uCofs[2], uCofs[5], nVars, 1, 0 ); // 00' & 11 + Kit_TruthAndPhase( uCofs[8], uCofs[3], uCofs[4], nVars, 0, 1 ); // 01 & 10' + Kit_TruthAndPhase( uCofs[9], uCofs[3], uCofs[4], nVars, 1, 0 ); // 01' & 10 + + nOnes = Kit_TruthCountOnes( uCofs[6], nVars ) + + Kit_TruthCountOnes( uCofs[7], nVars ) + + Kit_TruthCountOnes( uCofs[8], nVars ) + + Kit_TruthCountOnes( uCofs[9], nVars ); + + printf( "%7d ", nOnes ); + if ( k == nVars - 1 ) + printf( "\n" ); + } + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Ntk4VarObjPrint_rec( Abc_Obj_t * pObj ) +{ + if ( pObj == Abc_AigConst1(pObj->pNtk) ) + { + printf( "1" ); + return; + } + if ( Abc_ObjIsPi(pObj) ) + { + printf( "%c", pObj->Id - 1 + 'a' ); + return; + } + + printf( "(" ); + Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) ); + if ( Abc_ObjFaninC0(pObj) ) + printf( "\'" ); + Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin1(pObj) ); + if ( Abc_ObjFaninC1(pObj) ) + printf( "\'" ); + printf( ")" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Abc_Ntk4VarObj( Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pObj; + unsigned uTruth0, uTruth1; + int i; + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + uTruth0 = (unsigned)(Abc_ObjFanin0(pObj)->pCopy); + uTruth1 = (unsigned)(Abc_ObjFanin1(pObj)->pCopy); + if ( Abc_ObjFaninC0(pObj) ) + uTruth0 = ~uTruth0; + if ( Abc_ObjFaninC1(pObj) ) + uTruth1 = ~uTruth1; + pObj->pCopy = (void *)(uTruth0 & uTruth1); + } + return uTruth0 & uTruth1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Ntk4VarTable( Abc_Ntk_t * pNtk ) +{ + static unsigned u4VarTruths[4] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00 }; + static unsigned u4VarTts[222] = { + 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, + 0x001b, 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, + 0x007f, 0x00ff, 0x0116, 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, + 0x012c, 0x012d, 0x012f, 0x013c, 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016a, + 0x016b, 0x016e, 0x016f, 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0186, + 0x0187, 0x0189, 0x018b, 0x018f, 0x0196, 0x0197, 0x0198, 0x0199, 0x019a, 0x019b, + 0x019e, 0x019f, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x01af, + 0x01bc, 0x01bd, 0x01be, 0x01bf, 0x01e8, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, + 0x01fe, 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, + 0x035e, 0x035f, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, + 0x037c, 0x037d, 0x037e, 0x03c0, 0x03c1, 0x03c3, 0x03c5, 0x03c6, 0x03c7, 0x03cf, + 0x03d4, 0x03d5, 0x03d6, 0x03d7, 0x03d8, 0x03d9, 0x03db, 0x03dc, 0x03dd, 0x03de, + 0x03fc, 0x0660, 0x0661, 0x0662, 0x0663, 0x0666, 0x0667, 0x0669, 0x066b, 0x066f, + 0x0672, 0x0673, 0x0676, 0x0678, 0x0679, 0x067a, 0x067b, 0x067e, 0x0690, 0x0691, + 0x0693, 0x0696, 0x0697, 0x069f, 0x06b0, 0x06b1, 0x06b2, 0x06b3, 0x06b4, 0x06b5, + 0x06b6, 0x06b7, 0x06b9, 0x06bd, 0x06f0, 0x06f1, 0x06f2, 0x06f6, 0x06f9, 0x0776, + 0x0778, 0x0779, 0x077a, 0x077e, 0x07b0, 0x07b1, 0x07b4, 0x07b5, 0x07b6, 0x07bc, + 0x07e0, 0x07e1, 0x07e2, 0x07e3, 0x07e6, 0x07e9, 0x07f0, 0x07f1, 0x07f2, 0x07f8, + 0x0ff0, 0x1668, 0x1669, 0x166a, 0x166b, 0x166e, 0x167e, 0x1681, 0x1683, 0x1686, + 0x1687, 0x1689, 0x168b, 0x168e, 0x1696, 0x1697, 0x1698, 0x1699, 0x169a, 0x169b, + 0x169e, 0x16a9, 0x16ac, 0x16ad, 0x16bc, 0x16e9, 0x177e, 0x178e, 0x1796, 0x1798, + 0x179a, 0x17ac, 0x17e8, 0x18e7, 0x19e1, 0x19e3, 0x19e6, 0x1bd8, 0x1be4, 0x1ee1, + 0x3cc3, 0x6996 + }; + int Counters[222] = {0}; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + unsigned uTruth; + int i, k, Count = 0; + + unsigned short * puCanons = NULL; + unsigned char * puMap = NULL; + Extra_Truth4VarNPN( &puCanons, NULL, NULL, &puMap ); + + // set elementary truth tables + assert( Abc_NtkPiNum(pNtk) == 4 ); + Abc_AigConst1(pNtk)->pCopy = (void *)0xFFFFFFFF; + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = (void *)u4VarTruths[i]; + + // create truth tables + Abc_NtkForEachPo( pNtk, pObj, i ) + { + vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); + if ( Vec_PtrSize(vNodes) == 0 ) + uTruth = (unsigned)Abc_ObjFanin0(pObj)->pCopy; + else + uTruth = Abc_Ntk4VarObj( vNodes ); + + if ( (uTruth & 0xFFFF) < (~uTruth & 0xFFFF) ) + uTruth = uTruth & 0xFFFF; + else + uTruth = ~uTruth & 0xFFFF; + + for ( k = 0; k < 222; k++ ) + if ( u4VarTts[k] == uTruth ) + break; + if ( k == 222 ) + continue; +/* +// if ( uTruth == 1725 ) + if ( k == 96 ) + { + printf( "%d : ", Vec_PtrSize(vNodes) ); + Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) ); + printf( "\n" ); + } +*/ + Counters[k]++; + +// Counters[ puMap[uTruth & 0xFFFF] ]++; + Vec_PtrFree( vNodes ); + } + free( puCanons ); + free( puMap ); + + Count = 0; + for ( k = 0; k < 222; k++ ) + { + printf( "%d/%x/%d ", k, u4VarTts[k], Counters[k] ); + Count += Counters[k]; + } + printf( " Total = %d\n", Count ); +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if there are no more than 2 unique cofactors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkPrintOneDecompCheckCofList( unsigned * uCofs, int nCofs ) +{ + int i, Ind = -1; + assert( nCofs > 2 ); + for ( i = 1; i < nCofs; i++ ) + { + if ( uCofs[i] == uCofs[0] ) + continue; + if ( Ind == -1 ) + { + Ind = i; + continue; + } + if ( uCofs[i] == uCofs[Ind] ) + continue; + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks all cofactors with the given mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkPrintOneDecompCheck( unsigned * uCofs, int nCofs, unsigned uMask ) +{ + unsigned pCofs[32][32]; + int nCofNums[32] = {0}; + int uMasks[32]; + int nGroups = 0; + int i, k; + for ( i = 0; i < nCofs; i++ ) + { + // find group of this cof + for ( k = 0; k < nGroups; k++ ) + if ( (int)(i & uMask) == uMasks[k] ) + break; + if ( k == nGroups ) + { + uMasks[k] = (i & uMask); + nGroups++; + } + // save cof in the group + pCofs[k][ nCofNums[k]++ ] = uCofs[i]; + assert( nCofNums[k] <= 32 ); + assert( nGroups <= 32 ); + } + // check the groups + for ( i = 0; i < nGroups; i++ ) + if ( !Abc_NtkPrintOneDecompCheckCofList(pCofs[i], nCofNums[i]) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintOneDecomp_rec( unsigned * uCofs, int nCofs, int nVars, unsigned uMask, int * pBestSize, unsigned * puBestMask ) +{ + unsigned uMaskNew; + int v, last, Counter = 0; + // find the last variable in the mask + for ( v = 0; v < nVars; v++ ) + if ( uMask & (1< 3 ) + return; + // try adding one variable after the last + for ( v = last + 1; v < nVars; v++ ) + { + uMaskNew = uMask | (1 << v); + if ( !Abc_NtkPrintOneDecompCheck( uCofs, nCofs, uMaskNew ) ) + continue; + if ( *pBestSize < Counter + 1 ) + { + *pBestSize = Counter + 1; + *puBestMask = uMaskNew; + } + // try other masks + Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, uMaskNew, pBestSize, puBestMask ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintOneDecomp( unsigned * pTruth, int nVars ) +{ + int BoundSet = 6; + unsigned uCofs[64], uMask, uBestMask = 0; + int i, nCofs, nMints, nMintShift, BestSize = 1; + + assert( nVars > BoundSet ); + assert( nVars <= BoundSet + 5 ); // at most 5 variable cofactors + + // collect the cofactors + nCofs = (1 << BoundSet); + nMints = (1 << (nVars-BoundSet)); + nMintShift = 0; + uMask = Kit_CubeMask( nMints ); + for ( i = 0; i < nCofs; i++ ) + { + uCofs[i] = (pTruth[nMintShift/32] >> (nMintShift % 32)) & uMask; + nMintShift += nMints; + } + + // try removing variables + for ( i = 0; i < BoundSet; i++ ) + Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, (1 << i), &BestSize, &uBestMask ); + + printf( "Best size = %d ", BestSize ); + printf( "Best mask = " ); + Extra_PrintBinary( stdout, &uBestMask, nVars ); + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintOneDec( unsigned * pTruth, int nVars ) +{ + unsigned uCof[(1<<11)], * pOut = uCof, * pIn = pTruth, * pTemp; + int nDiffs[16]; + int Order[16]; + int i, fChange, Temp, Counter; + + // find the ordering + for ( i = 0; i < nVars; i++ ) + { + Kit_TruthUniqueNew( uCof, pTruth, nVars, i ); + nDiffs[i] = Kit_TruthCountOnes( uCof, nVars ); + Order[i] = i; + } + + // permute truth table to least active variable first + Counter = 0; + do { + fChange = 0; + for ( i = 0; i < nVars-1; i++ ) + { + if ( nDiffs[i] <= nDiffs[i+1] ) + continue; + fChange = 1; + Counter++; + + Temp = nDiffs[i]; + nDiffs[i] = nDiffs[i+1]; + nDiffs[i+1] = Temp; + + Temp = Order[i]; + Order[i] = Order[i+1]; + Order[i+1] = Temp; + + Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + } while ( fChange ); + + // swap if it was moved an even number of times + if ( Counter & 1 ) + Extra_TruthCopy( pOut, pIn, nVars ); + + // call the decomposition + Abc_NtkPrintOneDecomp( pTruth, nVars ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMini.c b/abc70930/src/base/abci/abcMini.c new file mode 100644 index 00000000..92985423 --- /dev/null +++ b/abc70930/src/base/abci/abcMini.c @@ -0,0 +1,153 @@ +/**CFile**************************************************************** + + FileName [abcMini.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface to the minimalistic AIG package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMini.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtkOld, Hop_Man_t * pMan ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkAig; + Hop_Man_t * pMan, * pTemp; + assert( Abc_NtkIsStrash(pNtk) ); + // convert to the AIG manager + pMan = Abc_NtkToMini( pNtk ); + if ( pMan == NULL ) + return NULL; + if ( !Hop_ManCheck( pMan ) ) + { + printf( "AIG check has failed.\n" ); + Hop_ManStop( pMan ); + return NULL; + } + // perform balance + Hop_ManPrintStats( pMan ); +// Hop_ManDumpBlif( pMan, "aig_temp.blif" ); + pMan = Hop_ManBalance( pTemp = pMan, 1 ); + Hop_ManStop( pTemp ); + Hop_ManPrintStats( pMan ); + // convert from the AIG manager + pNtkAig = Abc_NtkFromMini( pNtk, pMan ); + if ( pNtkAig == NULL ) + return NULL; + Hop_ManStop( pMan ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk ) +{ + Hop_Man_t * pMan; + Abc_Obj_t * pObj; + int i; + // create the manager + pMan = Hop_ManStart(); + // transfer the pointers to the basic nodes + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Hop_ManConst1(pMan); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Hop_ObjCreatePi(pMan); + // perform the conversion of the internal nodes (assumes DFS ordering) + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Hop_And( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj), (Hop_Obj_t *)Abc_ObjChild1Copy(pObj) ); + // create the POs + Abc_NtkForEachCo( pNtk, pObj, i ) + Hop_ObjCreatePo( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj) ); + Hop_ManCleanup( pMan ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the AIG manager into ABC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Hop_Obj_t * pObj; + int i; + // perform strashing + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // transfer the pointers to the basic nodes + Hop_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); + Hop_ManForEachPi( pMan, pObj, i ) + pObj->pData = Abc_NtkCi(pNtkNew, i); + // rebuild the AIG + vNodes = Hop_ManDfs( pMan ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); + Vec_PtrFree( vNodes ); + // connect the PO nodes + Hop_ManForEachPo( pMan, pObj, i ) + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Hop_ObjChild0Copy(pObj) ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkFromMini(): Network check has failed.\n" ); + return pNtkNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMiter.c b/abc70930/src/base/abci/abcMiter.c new file mode 100644 index 00000000..adda6653 --- /dev/null +++ b/abc70930/src/base/abci/abcMiter.c @@ -0,0 +1,1138 @@ +/**CFile**************************************************************** + + FileName [abcMiter.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to derive the miter of two circuits.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMiter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ); +static void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ); +static void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ); +static void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ); +static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int iFrame ); + +// to be exported +typedef void (*AddFrameMapping)( Abc_Obj_t*, Abc_Obj_t*, int, void*); +extern Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg ); +static void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the miter of two networks.] + + Description [Preprocesses the networks to make sure that they are strashed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ) +{ + Abc_Ntk_t * pTemp = NULL; + int fRemove1, fRemove2; + assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); + // check that the networks have the same PIs/POs/latches + if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 0, fComb ) ) + return NULL; + // make sure the circuits are strashed + fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0)); + fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0)); + if ( pNtk1 && pNtk2 ) + pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb, nPartSize ); + if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); + if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [Derives the miter of two sequential networks.] + + Description [Assumes that the networks are strashed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ) +{ + char Buffer[1000]; + Abc_Ntk_t * pNtkMiter; + + assert( Abc_NtkIsStrash(pNtk1) ); + assert( Abc_NtkIsStrash(pNtk2) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); + + // perform strashing + Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); + Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); + Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); + Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); + Abc_AigCleanup(pNtkMiter->pManFunc); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiter: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} + +/**Function************************************************************* + + Synopsis [Prepares the network for mitering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ) +{ + Abc_Obj_t * pObj, * pObjNew; + int i; + // clean the copy field in all objects +// Abc_NtkCleanCopy( pNtk1 ); +// Abc_NtkCleanCopy( pNtk2 ); + Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter); + Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter); + + if ( fComb ) + { + // create new PIs and remember them in the old PIs + Abc_NtkForEachCi( pNtk1, pObj, i ) + { + pObjNew = Abc_NtkCreatePi( pNtkMiter ); + // remember this PI in the old PIs + pObj->pCopy = pObjNew; + pObj = Abc_NtkCi(pNtk2, i); + pObj->pCopy = pObjNew; + // add name + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + } + if ( nPartSize <= 0 ) + { + // create the only PO + pObjNew = Abc_NtkCreatePo( pNtkMiter ); + // add the PO name + Abc_ObjAssignName( pObjNew, "miter", NULL ); + } + } + else + { + // create new PIs and remember them in the old PIs + Abc_NtkForEachPi( pNtk1, pObj, i ) + { + pObjNew = Abc_NtkCreatePi( pNtkMiter ); + // remember this PI in the old PIs + pObj->pCopy = pObjNew; + pObj = Abc_NtkPi(pNtk2, i); + pObj->pCopy = pObjNew; + // add name + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + } + if ( nPartSize <= 0 ) + { + // create the only PO + pObjNew = Abc_NtkCreatePo( pNtkMiter ); + // add the PO name + Abc_ObjAssignName( pObjNew, "miter", NULL ); + } + // create the latches + Abc_NtkForEachLatch( pNtk1, pObj, i ) + { + pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 ); + // add names + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_1" ); + Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_1" ); + Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_1" ); + } + Abc_NtkForEachLatch( pNtk2, pObj, i ) + { + pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 ); + // add name + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_2" ); + Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_2" ); + Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_2" ); + } + } +} + +/**Function************************************************************* + + Synopsis [Performs mitering for one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsDfsOrdered(pNtk) ); + Abc_AigForEachAnd( pNtk, pNode, i ) + pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Performs mitering for one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pRoot ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + // map the constant nodes + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkMiter); + // perform strashing + vNodes = Abc_NtkDfsNodes( pNtk, &pRoot, 1 ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + if ( Abc_AigNodeIsAnd(pNode) ) + pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); + Vec_PtrFree( vNodes ); +} + + +/**Function************************************************************* + + Synopsis [Finalizes the miter by adding the output part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ) +{ + Vec_Ptr_t * vPairs; + Abc_Obj_t * pMiter, * pNode; + int i; + // collect the PO pairs from both networks + vPairs = Vec_PtrAlloc( 100 ); + if ( fComb ) + { + // collect the CO nodes for the miter + Abc_NtkForEachCo( pNtk1, pNode, i ) + { + Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); + pNode = Abc_NtkCo( pNtk2, i ); + Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); + } + } + else + { + // collect the PO nodes for the miter + Abc_NtkForEachPo( pNtk1, pNode, i ) + { + Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); + pNode = Abc_NtkPo( pNtk2, i ); + Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); + } + // connect new latches + Abc_NtkForEachLatch( pNtk1, pNode, i ) + Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); + Abc_NtkForEachLatch( pNtk2, pNode, i ) + Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); + } + // add the miter + if ( nPartSize <= 0 ) + { + pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairs ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); + Vec_PtrFree( vPairs ); + } + else + { + char Buffer[1024]; + Vec_Ptr_t * vPairsPart; + int nParts, i, k, iCur; + assert( Vec_PtrSize(vPairs) == 2 * Abc_NtkCoNum(pNtk1) ); + // create partitions + nParts = Abc_NtkCoNum(pNtk1) / nPartSize + (int)((Abc_NtkCoNum(pNtk1) % nPartSize) > 0); + vPairsPart = Vec_PtrAlloc( nPartSize ); + for ( i = 0; i < nParts; i++ ) + { + Vec_PtrClear( vPairsPart ); + for ( k = 0; k < nPartSize; k++ ) + { + iCur = i * nPartSize + k; + if ( iCur >= Abc_NtkCoNum(pNtk1) ) + break; + Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur ) ); + Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur+1) ); + } + pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairsPart ); + pNode = Abc_NtkCreatePo( pNtkMiter ); + Abc_ObjAddFanin( pNode, pMiter ); + // assign the name to the node + if ( nPartSize == 1 ) + sprintf( Buffer, "%s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) ); + else + sprintf( Buffer, "%d", i ); + Abc_ObjAssignName( pNode, "miter_", Buffer ); + } + Vec_PtrFree( vPairsPart ); + Vec_PtrFree( vPairs ); + } +} + + + +/**Function************************************************************* + + Synopsis [Derives the AND of two miters.] + + Description [The network should have the same names of PIs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 ) +{ + char Buffer[1000]; + Abc_Ntk_t * pNtkMiter; + Abc_Obj_t * pOutput1, * pOutput2; + Abc_Obj_t * pRoot1, * pRoot2, * pMiter; + + assert( Abc_NtkIsStrash(pNtk1) ); + assert( Abc_NtkIsStrash(pNtk2) ); + assert( 1 == Abc_NtkCoNum(pNtk1) ); + assert( 1 == Abc_NtkCoNum(pNtk2) ); + assert( 0 == Abc_NtkLatchNum(pNtk1) ); + assert( 0 == Abc_NtkLatchNum(pNtk2) ); + assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); +// sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); + sprintf( Buffer, "product" ); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); + + // perform strashing + Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, 1, -1 ); + Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); + Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); +// Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, 1 ); + pRoot1 = Abc_NtkPo(pNtk1,0); + pRoot2 = Abc_NtkPo(pNtk2,0); + pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot1)->pCopy, Abc_ObjFaninC0(pRoot1) ); + pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot2)->pCopy, Abc_ObjFaninC0(pRoot2) ^ fCompl2 ); + + // create the miter of the two outputs + if ( fOr ) + pMiter = Abc_AigOr( pNtkMiter->pManFunc, pOutput1, pOutput2 ); + else + pMiter = Abc_AigAnd( pNtkMiter->pManFunc, pOutput1, pOutput2 ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiterAnd: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} + + +/**Function************************************************************* + + Synopsis [Derives the cofactor of the miter w.r.t. the set of vars.] + + Description [The array of variable values contains -1/0/1 for each PI. + -1 means this PI remains, 0/1 means this PI is set to 0/1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) +{ + char Buffer[1000]; + Abc_Ntk_t * pNtkMiter; + Abc_Obj_t * pRoot, * pOutput1; + int Value, i; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( 1 == Abc_NtkCoNum(pNtk) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + sprintf( Buffer, "%s_miter", pNtk->pName ); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); + + // get the root output + pRoot = Abc_NtkCo( pNtk, 0 ); + + // perform strashing + Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 ); + // set the first cofactor + Vec_IntForEachEntry( vPiValues, Value, i ) + { + if ( Value == -1 ) + continue; + if ( Value == 0 ) + { + Abc_NtkCi(pNtk, i)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); + continue; + } + if ( Value == 1 ) + { + Abc_NtkCi(pNtk, i)->pCopy = Abc_AigConst1(pNtkMiter); + continue; + } + assert( 0 ); + } + // add the first cofactor + Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); + + // save the output + pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); + + // create the miter of the two outputs + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pOutput1 ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiterCofactor: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} +/**Function************************************************************* + + Synopsis [Derives the miter of two cofactors of one output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ) +{ + char Buffer[1000]; + Abc_Ntk_t * pNtkMiter; + Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( Out < Abc_NtkCoNum(pNtk) ); + assert( In1 < Abc_NtkCiNum(pNtk) ); + assert( In2 < Abc_NtkCiNum(pNtk) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) ); + pNtkMiter->pName = Extra_UtilStrsav(Buffer); + + // get the root output + pRoot = Abc_NtkCo( pNtk, Out ); + + // perform strashing + Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 ); + // set the first cofactor + Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); + if ( In2 >= 0 ) + Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1(pNtkMiter); + // add the first cofactor + Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); + + // save the output + pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; + + // set the second cofactor + Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1(pNtkMiter); + if ( In2 >= 0 ) + Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); + // add the second cofactor + Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); + + // save the output + pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; + + // create the miter of the two outputs + pMiter = Abc_AigXor( pNtkMiter->pManFunc, pOutput1, pOutput2 ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiter: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} + + +/**Function************************************************************* + + Synopsis [Derives the miter of two cofactors of one output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ) +{ + Abc_Ntk_t * pNtkMiter; + Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( 1 == Abc_NtkCoNum(pNtk) ); + assert( In < Abc_NtkCiNum(pNtk) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + + // start the new network + pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkMiter->pName = Extra_UtilStrsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) ); + + // get the root output + pRoot = Abc_NtkCo( pNtk, 0 ); + + // perform strashing + Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 ); + // set the first cofactor + Abc_NtkCi(pNtk, In)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); + // add the first cofactor + Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); + // save the output +// pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; + pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); + + // set the second cofactor + Abc_NtkCi(pNtk, In)->pCopy = Abc_AigConst1(pNtkMiter); + // add the second cofactor + Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); + // save the output +// pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; + pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); + + // create the miter of the two outputs + if ( fExist ) + pMiter = Abc_AigOr( pNtkMiter->pManFunc, pOutput1, pOutput2 ); + else + pMiter = Abc_AigAnd( pNtkMiter->pManFunc, pOutput1, pOutput2 ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkMiter ) ) + { + printf( "Abc_NtkMiter: The network check has failed.\n" ); + Abc_NtkDelete( pNtkMiter ); + return NULL; + } + return pNtkMiter; +} + +/**Function************************************************************* + + Synopsis [Quantifies all the PIs existentially from the only PO of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkTemp; + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + + Abc_NtkForEachPi( pNtk, pObj, i ) + { + if ( Abc_ObjFanoutNum(pObj) == 0 ) + continue; + pNtk = Abc_NtkMiterQuantify( pNtkTemp = pNtk, i, 1 ); + Abc_NtkDelete( pNtkTemp ); + } + + return pNtk; +} + + + + +/**Function************************************************************* + + Synopsis [Checks the status of the miter.] + + Description [Return 0 if the miter is sat for at least one output. + Return 1 if the miter is unsat for all its outputs. Returns -1 if the + miter is undecided for some outputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ) +{ + Abc_Obj_t * pNodePo, * pChild; + int i; + assert( Abc_NtkIsStrash(pMiter) ); + Abc_NtkForEachPo( pMiter, pNodePo, i ) + { + pChild = Abc_ObjChild0( pNodePo ); + if ( Abc_AigNodeIsConst(pChild) ) + { + assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter) ); + if ( !Abc_ObjIsComplement(pChild) ) + { + // if the miter is constant 1, return immediately +// printf( "MITER IS CONSTANT 1!\n" ); + return 0; + } + } + // if the miter is undecided (or satisfiable), return immediately + else + return -1; + } + // return 1, meaning all outputs are constant zero + return 1; +} + +/**Function************************************************************* + + Synopsis [Reports the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ) +{ + Abc_Obj_t * pChild, * pNode; + int i; + if ( Abc_NtkPoNum(pMiter) == 1 ) + { + pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,0) ); + if ( Abc_AigNodeIsConst(pChild) ) + { + if ( Abc_ObjIsComplement(pChild) ) + printf( "Unsatisfiable.\n" ); + else + printf( "Satisfiable. (Constant 1).\n" ); + } + else + printf( "Satisfiable.\n" ); + } + else + { + Abc_NtkForEachPo( pMiter, pNode, i ) + { + pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) ); + printf( "Output #%2d : ", i ); + if ( Abc_AigNodeIsConst(pChild) ) + { + if ( Abc_ObjIsComplement(pChild) ) + printf( "Unsatisfiable.\n" ); + else + printf( "Satisfiable. (Constant 1).\n" ); + } + else + printf( "Satisfiable.\n" ); + } + } +} + + +/**Function************************************************************* + + Synopsis [Derives the timeframes of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial ) +{ + char Buffer[1000]; + ProgressBar * pProgress; + Abc_Ntk_t * pNtkFrames; + Abc_Obj_t * pLatch, * pLatchOut; + int i, Counter; + assert( nFrames > 0 ); + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkIsDfsOrdered(pNtk) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + // start the new network + pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); + pNtkFrames->pName = Extra_UtilStrsav(Buffer); + // map the constant nodes + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkFrames); + // create new latches (or their initial values) and remember them in the new latches + if ( !fInitial ) + { + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Abc_NtkDupBox( pNtkFrames, pLatch, 1 ); + } + else + { + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pLatchOut = Abc_ObjFanout0(pLatch); + if ( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI + { + pLatchOut->pCopy = Abc_NtkCreatePi(pNtkFrames); + Abc_ObjAssignName( pLatchOut->pCopy, Abc_ObjName(pLatchOut), NULL ); + Counter++; + } + else + pLatchOut->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) ); + } + if ( Counter ) + printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter ); + } + + // create the timeframes + pProgress = Extra_ProgressBarStart( stdout, nFrames ); + for ( i = 0; i < nFrames; i++ ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Abc_NtkAddFrame( pNtkFrames, pNtk, i ); + } + Extra_ProgressBarStop( pProgress ); + + // connect the new latches to the outputs of the last frame + if ( !fInitial ) + { + // we cannot use pLatch->pCopy here because pLatch->pCopy is used for temporary storage of strashed values + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Abc_ObjAddFanin( Abc_ObjFanin0(pLatch)->pCopy, Abc_ObjFanout0(pLatch)->pCopy ); + } + + // remove dangling nodes + Abc_AigCleanup( pNtkFrames->pManFunc ); + // reorder the latches + Abc_NtkOrderCisCos( pNtkFrames ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkFrames ) ) + { + printf( "Abc_NtkFrames: The network check has failed.\n" ); + Abc_NtkDelete( pNtkFrames ); + return NULL; + } + return pNtkFrames; +} + +/**Function************************************************************* + + Synopsis [Adds one time frame to the new network.] + + Description [Assumes that the latches of the old network point + to the outputs of the previous frame of the new network (pLatch->pCopy). + In the end, updates the latches of the old network to point to the + outputs of the current frame of the new network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame ) +{ + char Buffer[10]; + Abc_Obj_t * pNode, * pLatch; + int i; + // create the prefix to be added to the node names + sprintf( Buffer, "_%02d", iFrame ); + // add the new PI nodes + Abc_NtkForEachPi( pNtk, pNode, i ) + Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); + // add the internal nodes + Abc_AigForEachAnd( pNtk, pNode, i ) + pNode->pCopy = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); + // add the new POs + Abc_NtkForEachPo( pNtk, pNode, i ) + { + Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); + Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) ); + } + // add the new asserts + Abc_NtkForEachAssert( pNtk, pNode, i ) + { + Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); + Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) ); + } + // transfer the implementation of the latch inputs to the latch outputs + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pCopy = Abc_ObjChild0Copy(Abc_ObjFanin0(pLatch)); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Abc_ObjFanout0(pLatch)->pCopy = pLatch->pCopy; +} + + + +/**Function************************************************************* + + Synopsis [Derives the timeframes of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg ) +{ +/* + char Buffer[1000]; + ProgressBar * pProgress; + Abc_Ntk_t * pNtkFrames; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pLatch, * pLatchNew; + int i, Counter; + assert( nFrames > 0 ); + assert( Abc_NtkIsStrash(pNtk) ); + // start the new network + pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); + pNtkFrames->pName = Extra_UtilStrsav(Buffer); + // create new latches (or their initial values) and remember them in the new latches + if ( !fInitial ) + { + Abc_NtkForEachLatch( pNtk, pLatch, i ) { + Abc_NtkDupObj( pNtkFrames, pLatch ); + if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); + } + } + else + { + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI + { + pLatch->pCopy = Abc_NtkCreatePi(pNtkFrames); + Abc_ObjAssignName( pLatch->pCopy, Abc_ObjName(pLatch), NULL ); + Counter++; + } + else { + pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) ); + } + + if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); + } + if ( Counter ) + printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter ); + } + + // create the timeframes + vNodes = Abc_NtkDfs( pNtk, 0 ); + pProgress = Extra_ProgressBarStart( stdout, nFrames ); + for ( i = 0; i < nFrames; i++ ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Abc_NtkAddFrame2( pNtkFrames, pNtk, i, vNodes, addFrameMapping, arg ); + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + + // connect the new latches to the outputs of the last frame + if ( !fInitial ) + { + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pLatchNew = Abc_NtkBox(pNtkFrames, i); + Abc_ObjAddFanin( pLatchNew, pLatch->pCopy ); + Abc_ObjAssignName( pLatchNew, Abc_ObjName(pLatch), NULL ); + } + } + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pNext = NULL; + + // remove dangling nodes + Abc_AigCleanup( pNtkFrames->pManFunc ); + + // reorder the latches + Abc_NtkOrderCisCos( pNtkFrames ); + + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtkFrames ) ) + { + printf( "Abc_NtkFrames: The network check has failed.\n" ); + Abc_NtkDelete( pNtkFrames ); + return NULL; + } + return pNtkFrames; +*/ + return NULL; +} + +/**Function************************************************************* + + Synopsis [Adds one time frame to the new network.] + + Description [Assumes that the latches of the old network point + to the outputs of the previous frame of the new network (pLatch->pCopy). + In the end, updates the latches of the old network to point to the + outputs of the current frame of the new network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ) +{ +/* + char Buffer[10]; + Abc_Obj_t * pNode, * pNodeNew, * pLatch; + Abc_Obj_t * pConst1, * pConst1New; + int i; + // get the constant nodes + pConst1 = Abc_AigConst1(pNtk); + pConst1New = Abc_AigConst1(pNtkFrames); + // create the prefix to be added to the node names + sprintf( Buffer, "_%02d", iFrame ); + // add the new PI nodes + Abc_NtkForEachPi( pNtk, pNode, i ) + { + pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode ); + Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer ); + if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); + } + // add the internal nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( pNode == pConst1 ) + pNodeNew = pConst1New; + else + pNodeNew = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); + pNode->pCopy = pNodeNew; + if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); + } + // add the new POs + Abc_NtkForEachPo( pNtk, pNode, i ) + { + pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode ); + Abc_ObjAddFanin( pNodeNew, Abc_ObjChild0Copy(pNode) ); + Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer ); + if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); + } + // transfer the implementation of the latch drivers to the latches + + // it is important that these two steps are performed it two loops + // and not in the same loop + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pNext = Abc_ObjChild0Copy(pLatch); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pCopy = pLatch->pNext; + + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if (addFrameMapping) { + // don't give Mike complemented pointers because he doesn't like it + if (Abc_ObjIsComplement(pLatch->pCopy)) { + pNodeNew = Abc_NtkCreateNode( pNtkFrames ); + Abc_ObjAddFanin( pNodeNew, pLatch->pCopy ); + assert(Abc_ObjFaninNum(pNodeNew) == 1); + pNodeNew->Level = 1 + Abc_ObjRegular(pLatch->pCopy)->Level; + + pLatch->pNext = pNodeNew; + pLatch->pCopy = pNodeNew; + } + addFrameMapping(pLatch->pCopy, pLatch, iFrame+1, arg); + } + } +*/ +} + + + +/**Function************************************************************* + + Synopsis [Splits the miter into two logic cones combined by an EXOR] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDemiter( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNodeC, * pNodeA, * pNodeB, * pNode; + Abc_Obj_t * pPoNew; + Vec_Ptr_t * vNodes1, * vNodes2; + int nCommon, i; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkPoNum(pNtk) == 1 ); + if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) + { + printf( "The root of the miter is not an EXOR gate.\n" ); + return 0; + } + pNodeC = Abc_NodeRecognizeMux( Abc_ObjFanin0(Abc_NtkPo(pNtk,0)), &pNodeA, &pNodeB ); + assert( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) ); + if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk,0)) ) + { + pNodeA = Abc_ObjNot(pNodeA); + pNodeB = Abc_ObjNot(pNodeB); + } + + // add the PO corresponding to control input + pPoNew = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pPoNew, pNodeC ); + Abc_ObjAssignName( pPoNew, "addOut1", NULL ); + + // add the PO corresponding to other input + pPoNew = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pPoNew, pNodeB ); + Abc_ObjAssignName( pPoNew, "addOut2", NULL ); + + // mark the nodes in the first cone + pNodeB = Abc_ObjRegular(pNodeB); + vNodes1 = Abc_NtkDfsNodes( pNtk, &pNodeC, 1 ); + vNodes2 = Abc_NtkDfsNodes( pNtk, &pNodeB, 1 ); + + Vec_PtrForEachEntry( vNodes1, pNode, i ) + pNode->fMarkA = 1; + nCommon = 0; + Vec_PtrForEachEntry( vNodes2, pNode, i ) + nCommon += pNode->fMarkA; + Vec_PtrForEachEntry( vNodes1, pNode, i ) + pNode->fMarkA = 0; + + printf( "First cone = %6d. Second cone = %6d. Common = %6d.\n", vNodes1->nSize, vNodes2->nSize, nCommon ); + Vec_PtrFree( vNodes1 ); + Vec_PtrFree( vNodes2 ); + + // reorder the latches + Abc_NtkOrderCisCos( pNtk ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtk ) ) + printf( "Abc_NtkDemiter: The network check has failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes OR or AND of the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ) +{ + Abc_Obj_t * pNode, * pMiter; + int i; + assert( Abc_NtkIsStrash(pNtk) ); +// assert( Abc_NtkLatchNum(pNtk) == 0 ); + if ( Abc_NtkPoNum(pNtk) == 1 ) + return 1; + // start the result + if ( fAnd ) + pMiter = Abc_AigConst1(pNtk); + else + pMiter = Abc_ObjNot( Abc_AigConst1(pNtk) ); + // perform operations on the POs + Abc_NtkForEachPo( pNtk, pNode, i ) + if ( fAnd ) + pMiter = Abc_AigAnd( pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); + else + pMiter = Abc_AigOr( pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); + // remove the POs and their names + for ( i = Abc_NtkPoNum(pNtk) - 1; i >= 0; i-- ) + Abc_NtkDeleteObj( Abc_NtkPo(pNtk, i) ); + assert( Abc_NtkPoNum(pNtk) == 0 ); + // create the new PO + pNode = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pNode, pMiter ); + Abc_ObjAssignName( pNode, "miter", NULL ); + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkOrPos: The network check has failed.\n" ); + return 0; + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMulti.c b/abc70930/src/base/abci/abcMulti.c new file mode 100644 index 00000000..e93360a0 --- /dev/null +++ b/abc70930/src/base/abci/abcMulti.c @@ -0,0 +1,643 @@ +/**CFile**************************************************************** + + FileName [abcMulti.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures which transform an AIG into multi-input AND-graph.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMulti.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +static Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld ); + +static DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins ); +static DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ); + +static void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax ); +static void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk ); +static void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh ); +static void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk ); +static void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk ); +static void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transforms the AIG into nodes.] + + Description [Threhold is the max number of nodes duplicated at a node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ) +{ + Abc_Ntk_t * pNtkNew; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( nThresh >= 0 ); + assert( nFaninMax > 1 ); + + // print a warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Warning: The choice nodes in the AIG are removed by renoding.\n" ); + + // define the boundary + if ( fCnf ) + Abc_NtkMultiSetBoundsCnf( pNtk ); + else if ( fMulti ) + Abc_NtkMultiSetBoundsMulti( pNtk, nThresh ); + else if ( fSimple ) + Abc_NtkMultiSetBoundsSimple( pNtk ); + else if ( fFactor ) + Abc_NtkMultiSetBoundsFactor( pNtk ); + else + Abc_NtkMultiSetBounds( pNtk, nThresh, nFaninMax ); + + // perform renoding for this boundary + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); + Abc_NtkMultiInt( pNtk, pNtkNew ); + Abc_NtkFinalize( pNtk, pNtkNew ); + + // make the network minimum base + Abc_NtkMinimumBase( pNtkNew ); + + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + + // report the number of CNF objects + if ( fCnf ) + { +// int nClauses = Abc_NtkGetClauseNum(pNtkNew) + 2*Abc_NtkPoNum(pNtkNew) + 2*Abc_NtkLatchNum(pNtkNew); +// printf( "CNF variables = %d. CNF clauses = %d.\n", Abc_NtkNodeNum(pNtkNew), nClauses ); + } +//printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) ); + + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkMulti: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transforms the AIG into nodes.] + + Description [Threhold is the max number of nodes duplicated at a node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pConst1, * pNodeNew; + int i; + + // set the constant node + pConst1 = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pConst1) > 0 ) + { + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData ); + pConst1->pCopy = pNodeNew; + } + + // perform renoding for POs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) + continue; + Abc_NtkMulti_rec( pNtkNew, Abc_ObjFanin0(pNode) ); + } + Extra_ProgressBarStop( pProgress ); + + // clean the boundaries and data field in the old network + Abc_NtkForEachObj( pNtk, pNode, i ) + { + pNode->fMarkA = 0; + pNode->pData = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Find the best multi-input node rooted at the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld ) +{ + Vec_Ptr_t * vCone; + Abc_Obj_t * pNodeNew; + int i; + + assert( !Abc_ObjIsComplement(pNodeOld) ); + // return if the result if known + if ( pNodeOld->pCopy ) + return pNodeOld->pCopy; + assert( Abc_ObjIsNode(pNodeOld) ); + assert( !Abc_AigNodeIsConst(pNodeOld) ); + assert( pNodeOld->fMarkA ); + +//printf( "%d ", Abc_NodeMffcSizeSupp(pNodeOld) ); + + // collect the renoding cone + vCone = Vec_PtrAlloc( 10 ); + Abc_NtkMultiCone( pNodeOld, vCone ); + + // create a new node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < vCone->nSize; i++ ) + Abc_ObjAddFanin( pNodeNew, Abc_NtkMulti_rec(pNtkNew, vCone->pArray[i]) ); + + // derive the function of this node + pNodeNew->pData = Abc_NtkMultiDeriveBdd( pNtkNew->pManFunc, pNodeOld, vCone ); + Cudd_Ref( pNodeNew->pData ); + Vec_PtrFree( vCone ); + + // remember the node + pNodeOld->pCopy = pNodeNew; + return pNodeOld->pCopy; +} + + +/**Function************************************************************* + + Synopsis [Derives the local BDD of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ) +{ + Abc_Obj_t * pFaninOld; + DdNode * bFunc; + int i; + assert( !Abc_AigNodeIsConst(pNodeOld) ); + assert( Abc_ObjIsNode(pNodeOld) ); + // set the elementary BDD variables for the input nodes + for ( i = 0; i < vFaninsOld->nSize; i++ ) + { + pFaninOld = vFaninsOld->pArray[i]; + pFaninOld->pData = Cudd_bddIthVar( dd, i ); Cudd_Ref( pFaninOld->pData ); + pFaninOld->fMarkC = 1; + } + // call the recursive BDD computation + bFunc = Abc_NtkMultiDeriveBdd_rec( dd, pNodeOld, vFaninsOld ); Cudd_Ref( bFunc ); + // dereference the intermediate nodes + for ( i = 0; i < vFaninsOld->nSize; i++ ) + { + pFaninOld = vFaninsOld->pArray[i]; + Cudd_RecursiveDeref( dd, pFaninOld->pData ); + pFaninOld->fMarkC = 0; + } + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Derives the local BDD of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins ) +{ + DdNode * bFunc, * bFunc0, * bFunc1; + assert( !Abc_ObjIsComplement(pNode) ); + // if the result is available return + if ( pNode->fMarkC ) + { + assert( pNode->pData ); // network has a cycle + return pNode->pData; + } + // mark the node as visited + pNode->fMarkC = 1; + Vec_PtrPush( vFanins, pNode ); + // compute the result for both branches + bFunc0 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 ); + bFunc1 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,1), vFanins ); Cudd_Ref( bFunc1 ); + bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) ); + bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) ); + // get the final result + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bFunc0 ); + Cudd_RecursiveDeref( dd, bFunc1 ); + // set the result + pNode->pData = bFunc; + assert( pNode->pData ); + return bFunc; +} + + + +/**Function************************************************************* + + Synopsis [Limits the cones to be no more than the given size.] + + Description [Returns 1 if the last cone was limited. Returns 0 if no changes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMultiLimit_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax, int fCanStop, int fFirst ) +{ + int nNodes0, nNodes1; + assert( !Abc_ObjIsComplement(pNode) ); + // check if the node should be added to the fanins + if ( !fFirst && (pNode->fMarkA || !Abc_ObjIsNode(pNode)) ) + { + Vec_PtrPushUnique( vCone, pNode ); + return 0; + } + // if we cannot stop in this branch, collect all nodes + if ( !fCanStop ) + { + Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 ); + Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); + return 0; + } + // if we can stop, try the left branch first, and return if we stopped + assert( vCone->nSize == 0 ); + if ( Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 1, 0 ) ) + return 1; + // save the number of nodes in the left branch and call for the right branch + nNodes0 = vCone->nSize; + assert( nNodes0 <= nFaninMax ); + Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); + // check the number of nodes + if ( vCone->nSize <= nFaninMax ) + return 0; + // the number of nodes exceeds the limit + + // get the number of nodes in the right branch + vCone->nSize = 0; + Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); + // if this number exceeds the limit, solve the problem for this branch + if ( vCone->nSize > nFaninMax ) + { + int RetValue; + vCone->nSize = 0; + RetValue = Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 1, 0 ); + assert( RetValue == 1 ); + return 1; + } + + nNodes1 = vCone->nSize; + assert( nNodes1 <= nFaninMax ); + if ( nNodes0 >= nNodes1 ) + { // the left branch is larger - cut it + assert( Abc_ObjFanin(pNode,0)->fMarkA == 0 ); + Abc_ObjFanin(pNode,0)->fMarkA = 1; + } + else + { // the right branch is larger - cut it + assert( Abc_ObjFanin(pNode,1)->fMarkA == 0 ); + Abc_ObjFanin(pNode,1)->fMarkA = 1; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Limits the cones to be no more than the given size.] + + Description [Returns 1 if the last cone was limited. Returns 0 if no changes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMultiLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax ) +{ + vCone->nSize = 0; + return Abc_NtkMultiLimit_rec( pNode, vCone, nFaninMax, 1, 1 ); +} + +/**Function************************************************************* + + Synopsis [Sets the expansion boundary for multi-input nodes.] + + Description [The boundary includes the set of PIs and all nodes such that + when expanding over the node we duplicate no more than nThresh nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax ) +{ + Vec_Ptr_t * vCone = Vec_PtrAlloc(10); + Abc_Obj_t * pNode; + int i, nFanouts, nConeSize; + + // make sure the mark is not set + Abc_NtkForEachObj( pNtk, pNode, i ) + assert( pNode->fMarkA == 0 ); + + // mark the nodes where expansion stops using pNode->fMarkA + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // mark the nodes with multiple fanouts + nFanouts = Abc_ObjFanoutNum(pNode); + nConeSize = Abc_NodeMffcSize(pNode); + if ( (nFanouts - 1) * nConeSize > nThresh ) + pNode->fMarkA = 1; + } + + // mark the PO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_ObjFanin0(pNode)->fMarkA = 1; + + // make sure the fanin limit is met + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + if ( pNode->fMarkA == 0 ) + continue; + // continue cutting branches until it meets the fanin limit + while ( Abc_NtkMultiLimit(pNode, vCone, nFaninMax) ); + assert( vCone->nSize <= nFaninMax ); + } + Vec_PtrFree(vCone); +/* + // make sure the fanin limit is met + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + if ( pNode->fMarkA == 0 ) + continue; + Abc_NtkMultiCone( pNode, vCone ); + assert( vCone->nSize <= nFaninMax ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Sets the expansion boundary for conversion into CNF.] + + Description [The boundary includes the set of PIs, the roots of MUXes, + the nodes with multiple fanouts and the nodes with complemented outputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nMuxes; + + // make sure the mark is not set + Abc_NtkForEachObj( pNtk, pNode, i ) + assert( pNode->fMarkA == 0 ); + + // mark the nodes where expansion stops using pNode->fMarkA + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // mark the nodes with multiple fanouts + if ( Abc_ObjFanoutNum(pNode) > 1 ) + pNode->fMarkA = 1; + // mark the nodes that are roots of MUXes + if ( Abc_NodeIsMuxType( pNode ) ) + { + pNode->fMarkA = 1; + Abc_ObjFanin0( Abc_ObjFanin0(pNode) )->fMarkA = 1; + Abc_ObjFanin0( Abc_ObjFanin1(pNode) )->fMarkA = 1; + Abc_ObjFanin1( Abc_ObjFanin0(pNode) )->fMarkA = 1; + Abc_ObjFanin1( Abc_ObjFanin1(pNode) )->fMarkA = 1; + } + else // mark the complemented edges + { + if ( Abc_ObjFaninC0(pNode) ) + Abc_ObjFanin0(pNode)->fMarkA = 1; + if ( Abc_ObjFaninC1(pNode) ) + Abc_ObjFanin1(pNode)->fMarkA = 1; + } + } + + // mark the PO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_ObjFanin0(pNode)->fMarkA = 1; + + // count the number of MUXes + nMuxes = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + if ( Abc_NodeIsMuxType(pNode) && + Abc_ObjFanin0(pNode)->fMarkA == 0 && + Abc_ObjFanin1(pNode)->fMarkA == 0 ) + nMuxes++; + } +// printf( "The number of MUXes detected = %d (%5.2f %% of logic).\n", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) ); +} + +/**Function************************************************************* + + Synopsis [Sets the expansion boundary for conversion into multi-input AND graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh ) +{ + Abc_Obj_t * pNode; + int i, nFanouts, nConeSize; + + // make sure the mark is not set + Abc_NtkForEachObj( pNtk, pNode, i ) + assert( pNode->fMarkA == 0 ); + + // mark the nodes where expansion stops using pNode->fMarkA + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip PI/PO nodes +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // mark the nodes with multiple fanouts +// if ( Abc_ObjFanoutNum(pNode) > 1 ) +// pNode->fMarkA = 1; + // mark the nodes with multiple fanouts + nFanouts = Abc_ObjFanoutNum(pNode); + nConeSize = Abc_NodeMffcSizeStop(pNode); + if ( (nFanouts - 1) * nConeSize > nThresh ) + pNode->fMarkA = 1; + // mark the children if they are pointed by the complemented edges + if ( Abc_ObjFaninC0(pNode) ) + Abc_ObjFanin0(pNode)->fMarkA = 1; + if ( Abc_ObjFaninC1(pNode) ) + Abc_ObjFanin1(pNode)->fMarkA = 1; + } + + // mark the PO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_ObjFanin0(pNode)->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Sets a simple boundary.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + // make sure the mark is not set + Abc_NtkForEachObj( pNtk, pNode, i ) + assert( pNode->fMarkA == 0 ); + // mark the nodes where expansion stops using pNode->fMarkA + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Sets a factor-cut boundary.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + // make sure the mark is not set + Abc_NtkForEachObj( pNtk, pNode, i ) + assert( pNode->fMarkA == 0 ); + // mark the nodes where expansion stops using pNode->fMarkA + Abc_NtkForEachNode( pNtk, pNode, i ) + pNode->fMarkA = (pNode->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pNode)); + // mark the PO drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_ObjFanin0(pNode)->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Collects the fanins of a large node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ) +{ + assert( !Abc_ObjIsComplement(pNode) ); + if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) ) + { + Vec_PtrPushUnique( vCone, pNode ); + return; + } + Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone ); + Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone ); +} + +/**Function************************************************************* + + Synopsis [Collects the fanins of a large node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ) +{ + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + vCone->nSize = 0; + Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone ); + Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcMv.c b/abc70930/src/base/abci/abcMv.c new file mode 100644 index 00000000..2858b8a7 --- /dev/null +++ b/abc70930/src/base/abci/abcMv.c @@ -0,0 +1,369 @@ +/**CFile**************************************************************** + + FileName [abcMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Multi-valued decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Mv_Man_t_ Mv_Man_t; +struct Mv_Man_t_ +{ + int nInputs; // the number of 4-valued input variables + int nFuncs; // the number of 4-valued functions + DdManager * dd; // representation of functions + DdNode * bValues[15][4]; // representation of i-sets + DdNode * bValueDcs[15][4]; // representation of i-sets don't-cares + DdNode * bFuncs[15]; // representation of functions +}; + +static void Abc_MvDecompose( Mv_Man_t * p ); +static void Abc_MvPrintStats( Mv_Man_t * p ); +static void Abc_MvRead( Mv_Man_t * p ); +static void Abc_MvDeref( Mv_Man_t * p ); +static DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvExperiment() +{ + Mv_Man_t * p; + // get the functions + p = ALLOC( Mv_Man_t, 1 ); + memset( p, 0, sizeof(Mv_Man_t) ); + p->dd = Cudd_Init( 32, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + p->nFuncs = 15; + p->nInputs = 9; + Abc_MvRead( p ); + // process the functions + Abc_MvPrintStats( p ); +// Cudd_ReduceHeap( p->dd, CUDD_REORDER_SYMM_SIFT, 1 ); +// Abc_MvPrintStats( p ); + // try detecting support reducing bound set + Abc_MvDecompose( p ); + + // remove the manager + Abc_MvDeref( p ); + Extra_StopManager( p->dd ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvPrintStats( Mv_Man_t * p ) +{ + int i, v; + for ( i = 0; i < 15; i++ ) + { + printf( "%2d : ", i ); + printf( "%3d (%2d) ", Cudd_DagSize(p->bFuncs[i])-1, Cudd_SupportSize(p->dd, p->bFuncs[i]) ); + for ( v = 0; v < 4; v++ ) + printf( "%d = %3d (%2d) ", v, Cudd_DagSize(p->bValues[i][v])-1, Cudd_SupportSize(p->dd, p->bValues[i][v]) ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars ) +{ + DdNode * bCube, * bVar, * bTemp; + int i; + bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); + for ( i = 0; i < nVars; i++ ) + { + if ( pLine[i] == '-' ) + continue; + else if ( pLine[i] == '0' ) // 0 + bVar = Cudd_Not( Cudd_bddIthVar(dd, 29-i) ); + else if ( pLine[i] == '1' ) // 1 + bVar = Cudd_bddIthVar(dd, 29-i); + else assert(0); + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bCube ); + return bCube; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvRead( Mv_Man_t * p ) +{ + FILE * pFile; + char Buffer[1000], * pLine; + DdNode * bCube, * bTemp, * bProd, * bVar0, * bVar1, * bCubeSum; + int i, v; + + // start the cube + bCubeSum = Cudd_ReadLogicZero(p->dd); Cudd_Ref( bCubeSum ); + + // start the values + for ( i = 0; i < 15; i++ ) + for ( v = 0; v < 4; v++ ) + { + p->bValues[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValues[i][v] ); + p->bValueDcs[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValueDcs[i][v] ); + } + + // read the file + pFile = fopen( "input.pla", "r" ); + while ( fgets( Buffer, 1000, pFile ) ) + { + if ( Buffer[0] == '#' ) + continue; + if ( Buffer[0] == '.' ) + { + if ( Buffer[1] == 'e' ) + break; + continue; + } + + // get the cube + bCube = Abc_MvReadCube( p->dd, Buffer, 18 ); Cudd_Ref( bCube ); + + // add it to the values of the output functions + pLine = Buffer + 19; + for ( i = 0; i < 15; i++ ) + { + if ( pLine[2*i] == '-' && pLine[2*i+1] == '-' ) + { + for ( v = 0; v < 4; v++ ) + { + p->bValueDcs[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValueDcs[i][v], bCube ); Cudd_Ref( p->bValueDcs[i][v] ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + continue; + } + else if ( pLine[2*i] == '0' && pLine[2*i+1] == '0' ) // 0 + v = 0; + else if ( pLine[2*i] == '1' && pLine[2*i+1] == '0' ) // 1 + v = 1; + else if ( pLine[2*i] == '0' && pLine[2*i+1] == '1' ) // 2 + v = 2; + else if ( pLine[2*i] == '1' && pLine[2*i+1] == '1' ) // 3 + v = 3; + else assert( 0 ); + // add the value + p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], bCube ); Cudd_Ref( p->bValues[i][v] ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + + // add the cube + bCubeSum = Cudd_bddOr( p->dd, bTemp = bCubeSum, bCube ); Cudd_Ref( bCubeSum ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bCube ); + } + + // add the complement of the domain to all values + for ( i = 0; i < 15; i++ ) + for ( v = 0; v < 4; v++ ) + { + if ( p->bValues[i][v] == Cudd_Not(Cudd_ReadOne(p->dd)) ) + continue; + p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], p->bValueDcs[i][v] ); Cudd_Ref( p->bValues[i][v] ); + Cudd_RecursiveDeref( p->dd, bTemp ); + p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], Cudd_Not(bCubeSum) ); Cudd_Ref( p->bValues[i][v] ); + Cudd_RecursiveDeref( p->dd, bTemp ); + } + printf( "Domain = %5.2f %%.\n", 100.0*Cudd_CountMinterm(p->dd, bCubeSum, 32)/Cudd_CountMinterm(p->dd, Cudd_ReadOne(p->dd), 32) ); + Cudd_RecursiveDeref( p->dd, bCubeSum ); + + // create each output function + for ( i = 0; i < 15; i++ ) + { + p->bFuncs[i] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bFuncs[i] ); + for ( v = 0; v < 4; v++ ) + { + bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 30), ((v & 1) == 0) ); + bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 31), ((v & 2) == 0) ); + bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); + bProd = Cudd_bddAnd( p->dd, p->bValues[i][v], bCube ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( p->dd, bCube ); + // add the value + p->bFuncs[i] = Cudd_bddOr( p->dd, bTemp = p->bFuncs[i], bProd ); Cudd_Ref( p->bFuncs[i] ); + Cudd_RecursiveDeref( p->dd, bTemp ); + Cudd_RecursiveDeref( p->dd, bProd ); + } + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvDeref( Mv_Man_t * p ) +{ + int i, v; + for ( i = 0; i < 15; i++ ) + for ( v = 0; v < 4; v++ ) + { + Cudd_RecursiveDeref( p->dd, p->bValues[i][v] ); + Cudd_RecursiveDeref( p->dd, p->bValueDcs[i][v] ); + } + for ( i = 0; i < 15; i++ ) + Cudd_RecursiveDeref( p->dd, p->bFuncs[i] ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_MvDecompose( Mv_Man_t * p ) +{ + DdNode * bCofs[16], * bVarCube1, * bVarCube2, * bVarCube, * bCube, * bVar0, * bVar1;//, * bRes; + int k, i1, i2, v1, v2;//, c1, c2, Counter; + + bVar0 = Cudd_bddIthVar(p->dd, 30); + bVar1 = Cudd_bddIthVar(p->dd, 31); + bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); + + for ( k = 0; k < p->nFuncs; k++ ) + { + printf( "FUNCTION %d\n", k ); + for ( i1 = 0; i1 < p->nFuncs; i1++ ) + for ( i2 = i1+1; i2 < p->nFuncs; i2++ ) + { + Vec_Ptr_t * vCofs; + + for ( v1 = 0; v1 < 4; v1++ ) + { + bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1 ), ((v1 & 1) == 0) ); + bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1-1), ((v1 & 2) == 0) ); + bVarCube1 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube1 ); + for ( v2 = 0; v2 < 4; v2++ ) + { + bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2 ), ((v2 & 1) == 0) ); + bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2-1), ((v2 & 2) == 0) ); + bVarCube2 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube2 ); + bVarCube = Cudd_bddAnd( p->dd, bVarCube1, bVarCube2 ); Cudd_Ref( bVarCube ); + bCofs[v1 * 4 + v2] = Cudd_Cofactor( p->dd, p->bFuncs[k], bVarCube ); Cudd_Ref( bCofs[v1 * 4 + v2] ); + Cudd_RecursiveDeref( p->dd, bVarCube ); + Cudd_RecursiveDeref( p->dd, bVarCube2 ); + } + Cudd_RecursiveDeref( p->dd, bVarCube1 ); + } +/* + // check the compatibility of cofactors + Counter = 0; + for ( c1 = 0; c1 < 16; c1++ ) + { + for ( c2 = 0; c2 <= c1; c2++ ) + printf( " " ); + for ( c2 = c1+1; c2 < 16; c2++ ) + { + bRes = Cudd_bddAndAbstract( p->dd, bCofs[c1], bCofs[c2], bCube ); Cudd_Ref( bRes ); + if ( bRes == Cudd_ReadOne(p->dd) ) + { + printf( "+" ); + Counter++; + } + else + { + printf( " " ); + } + Cudd_RecursiveDeref( p->dd, bRes ); + } + printf( "\n" ); + } +*/ + + vCofs = Vec_PtrAlloc( 16 ); + for ( v1 = 0; v1 < 4; v1++ ) + for ( v2 = 0; v2 < 4; v2++ ) + Vec_PtrPushUnique( vCofs, bCofs[v1 * 4 + v2] ); + printf( "%d ", Vec_PtrSize(vCofs) ); + Vec_PtrFree( vCofs ); + + // free the cofactors + for ( v1 = 0; v1 < 4; v1++ ) + for ( v2 = 0; v2 < 4; v2++ ) + Cudd_RecursiveDeref( p->dd, bCofs[v1 * 4 + v2] ); + + printf( "\n" ); +// printf( "%2d, %2d : %3d\n", i1, i2, Counter ); + } + } + + Cudd_RecursiveDeref( p->dd, bCube ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcNtbdd.c b/abc70930/src/base/abci/abcNtbdd.c new file mode 100644 index 00000000..f127811e --- /dev/null +++ b/abc70930/src/base/abci/abcNtbdd.c @@ -0,0 +1,582 @@ +/**CFile**************************************************************** + + FileName [abcNtbdd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to translate between the BDD and the network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +static Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ); +static Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node ); +static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructs the network isomorphic to the given BDD.] + + Description [Assumes that the BDD depends on the variables whose indexes + correspond to the names in the array (pNamesPi). Otherwise, returns NULL. + The resulting network comes with one node, whose functionality is + equal to the given BDD. To decompose this BDD into the network of + multiplexers use Abc_NtkBddToMuxes(). To decompose this BDD into + an And-Inverter Graph, use Abc_NtkStrash().] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ) +{ + Abc_Ntk_t * pNtk; + Vec_Ptr_t * vNamesPiFake = NULL; + Abc_Obj_t * pNode, * pNodePi, * pNodePo; + DdNode * bSupp, * bTemp; + char * pName; + int i; + + // supply fake names if real names are not given + if ( pNamePo == NULL ) + pNamePo = "F"; + if ( vNamesPi == NULL ) + { + vNamesPiFake = Abc_NodeGetFakeNames( dd->size ); + vNamesPi = vNamesPiFake; + } + + // make sure BDD depends on the variables whose index + // does not exceed the size of the array with PI names + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) + if ( (int)Cudd_NodeReadIndex(bTemp) >= Vec_PtrSize(vNamesPi) ) + break; + Cudd_RecursiveDeref( dd, bSupp ); + if ( bTemp != Cudd_ReadOne(dd) ) + return NULL; + + // start the network + pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 ); + pNtk->pName = Extra_UtilStrsav(pNamePo); + // make sure the new manager has enough inputs + Cudd_bddIthVar( pNtk->pManFunc, Vec_PtrSize(vNamesPi) ); + // add the PIs corresponding to the names + Vec_PtrForEachEntry( vNamesPi, pName, i ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), pName, NULL ); + // create the node + pNode = Abc_NtkCreateNode( pNtk ); + pNode->pData = Cudd_bddTransfer( dd, pNtk->pManFunc, bFunc ); Cudd_Ref(pNode->pData); + Abc_NtkForEachPi( pNtk, pNodePi, i ) + Abc_ObjAddFanin( pNode, pNodePi ); + // create the only PO + pNodePo = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pNodePo, pNode ); + Abc_ObjAssignName( pNodePo, pNamePo, NULL ); + // make the network minimum base + Abc_NtkMinimumBase( pNtk ); + if ( vNamesPiFake ) + Abc_NodeFreeNames( vNamesPiFake ); + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkDeriveFromBdd(): Network check has failed.\n" ); + return pNtk; +} + + + +/**Function************************************************************* + + Synopsis [Creates the network isomorphic to the union of local BDDs of the nodes.] + + Description [The nodes of the local BDDs are converted into the network nodes + with logic functions equal to the MUX.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + assert( Abc_NtkIsBddLogic(pNtk) ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + Abc_NtkBddToMuxesPerform( pNtk, pNtkNew ); + Abc_NtkFinalize( pNtk, pNtkNew ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkBddToMuxes: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the network to MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pNodeNew; + Vec_Ptr_t * vNodes; + int i; + // perform conversion in the topological order + vNodes = Abc_NtkDfs( pNtk, 0 ); + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // convert one node + assert( Abc_ObjIsNode(pNode) ); + pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew ); + // mark the old node with the new one + assert( pNode->pCopy == NULL ); + pNode->pCopy = pNodeNew; + } + Vec_PtrFree( vNodes ); + Extra_ProgressBarStop( pProgress ); +} + +/**Function************************************************************* + + Synopsis [Converts the node to MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ) +{ + DdManager * dd = pNodeOld->pNtk->pManFunc; + DdNode * bFunc = pNodeOld->pData; + Abc_Obj_t * pFaninOld, * pNodeNew; + st_table * tBdd2Node; + int i; + // create the table mapping BDD nodes into the ABC nodes + tBdd2Node = st_init_table( st_ptrcmp, st_ptrhash ); + // add the constant and the elementary vars + Abc_ObjForEachFanin( pNodeOld, pFaninOld, i ) + st_insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pFaninOld->pCopy ); + // create the new nodes recursively + pNodeNew = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNtkNew, tBdd2Node ); + st_free_table( tBdd2Node ); + if ( Cudd_IsComplement(bFunc) ) + pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew ); + return pNodeNew; +} + +/**Function************************************************************* + + Synopsis [Converts the node to MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node ) +{ + Abc_Obj_t * pNodeNew, * pNodeNew0, * pNodeNew1, * pNodeNewC; + assert( !Cudd_IsComplement(bFunc) ); + if ( bFunc == b1 ) + return Abc_NtkCreateNodeConst1(pNtkNew); + if ( st_lookup( tBdd2Node, (char *)bFunc, (char **)&pNodeNew ) ) + return pNodeNew; + // solve for the children nodes + pNodeNew0 = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(cuddE(bFunc)), pNtkNew, tBdd2Node ); + if ( Cudd_IsComplement(cuddE(bFunc)) ) + pNodeNew0 = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew0 ); + pNodeNew1 = Abc_NodeBddToMuxes_rec( dd, cuddT(bFunc), pNtkNew, tBdd2Node ); + if ( !st_lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeNewC ) ) + assert( 0 ); + // create the MUX node + pNodeNew = Abc_NtkCreateNodeMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 ); + st_insert( tBdd2Node, (char *)bFunc, (char *)pNodeNew ); + return pNodeNew; +} + + +/**Function************************************************************* + + Synopsis [Derives global BDDs for the COs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pObj, * pFanin; + Vec_Att_t * pAttMan; + DdManager * dd; + DdNode * bFunc; + int i, k, Counter; + + // remove dangling nodes + Abc_AigCleanup( pNtk->pManFunc ); + + // start the manager + assert( Abc_NtkGlobalBdd(pNtk) == NULL ); + dd = Cudd_Init( Abc_NtkCiNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, dd, Extra_StopManager, NULL, Cudd_RecursiveDeref ); + Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD, pAttMan ); + + // set reordering + if ( fReorder ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + + // assign the constant node BDD + pObj = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + { + bFunc = dd->one; + Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc ); + } + // set the elementary variables + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + { + bFunc = dd->vars[i]; +// bFunc = dd->vars[Abc_NtkCiNum(pNtk) - 1 - i]; + Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc ); + } + + // collect the global functions of the COs + Counter = 0; + // construct the BDDs + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose ); + if ( bFunc == NULL ) + { + if ( fVerbose ) + printf( "Constructing global BDDs is aborted.\n" ); + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + Cudd_Quit( dd ); + return NULL; + } + bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); + Abc_ObjSetGlobalBdd( pObj, bFunc ); + } + Extra_ProgressBarStop( pProgress ); + +/* + // derefence the intermediate BDDs + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( pObj->pCopy ) + { + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pCopy ); + pObj->pCopy = NULL; + } +*/ +/* + // make sure all nodes are derefed + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->pCopy != NULL ) + printf( "Abc_NtkBuildGlobalBdds() error: Node %d has BDD assigned\n", pObj->Id ); + if ( pObj->vFanouts.nSize > 0 ) + printf( "Abc_NtkBuildGlobalBdds() error: Node %d has refs assigned\n", pObj->Id ); + } +*/ + // reset references + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + pFanin->vFanouts.nSize++; + + // reorder one more time + if ( fReorder ) + { + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); + Cudd_AutodynDisable( dd ); + } +// Cudd_PrintInfo( dd, stdout ); + return dd; +} + +/**Function************************************************************* + + Synopsis [Derives the global BDD for one AIG node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) +{ + DdNode * bFunc, * bFunc0, * bFunc1, * bFuncC; + int fDetectMuxes = 1; + assert( !Abc_ObjIsComplement(pNode) ); + if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) + { + Extra_ProgressBarStop( pProgress ); + if ( fVerbose ) + printf( "The number of live nodes reached %d.\n", nBddSizeMax ); + fflush( stdout ); + return NULL; + } + // if the result is available return + if ( Abc_ObjGlobalBdd(pNode) == NULL ) + { + Abc_Obj_t * pNodeC, * pNode0, * pNode1; + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + // check for the special case when it is MUX/EXOR + if ( fDetectMuxes && + Abc_ObjGlobalBdd(pNode0) == NULL && Abc_ObjGlobalBdd(pNode1) == NULL && + Abc_ObjIsNode(pNode0) && Abc_ObjFanoutNum(pNode0) == 1 && + Abc_ObjIsNode(pNode1) && Abc_ObjFanoutNum(pNode1) == 1 && + Abc_NodeIsMuxType(pNode) ) + { + // deref the fanins + pNode0->vFanouts.nSize--; + pNode1->vFanouts.nSize--; + // recognize the MUX + pNodeC = Abc_NodeRecognizeMux( pNode, &pNode1, &pNode0 ); + assert( Abc_ObjFanoutNum(pNodeC) > 1 ); + // dereference the control once (the second time it will be derefed when BDDs are computed) + pNodeC->vFanouts.nSize--; + + // compute the result for all branches + bFuncC = Abc_NodeGlobalBdds_rec( dd, pNodeC, nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFuncC == NULL ) + return NULL; + Cudd_Ref( bFuncC ); + bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc0 == NULL ) + return NULL; + Cudd_Ref( bFunc0 ); + bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc1 == NULL ) + return NULL; + Cudd_Ref( bFunc1 ); + + // complement the branch BDDs + bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjIsComplement(pNode0) ); + bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjIsComplement(pNode1) ); + // get the final result + bFunc = Cudd_bddIte( dd, bFuncC, bFunc1, bFunc0 ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bFunc0 ); + Cudd_RecursiveDeref( dd, bFunc1 ); + Cudd_RecursiveDeref( dd, bFuncC ); + // add the number of used nodes + (*pCounter) += 3; + } + else + { + // compute the result for both branches + bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc0 == NULL ) + return NULL; + Cudd_Ref( bFunc0 ); + bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); + if ( bFunc1 == NULL ) + return NULL; + Cudd_Ref( bFunc1 ); + bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) ); + bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) ); + // get the final result + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bFunc0 ); + Cudd_RecursiveDeref( dd, bFunc1 ); + // add the number of used nodes + (*pCounter)++; + } + // set the result + assert( Abc_ObjGlobalBdd(pNode) == NULL ); + Abc_ObjSetGlobalBdd( pNode, bFunc ); + // increment the progress bar + if ( pProgress ) + Extra_ProgressBarUpdate( pProgress, *pCounter, NULL ); + } + // prepare the return value + bFunc = Abc_ObjGlobalBdd(pNode); + // dereference BDD at the node + if ( --pNode->vFanouts.nSize == 0 && fDropInternal ) + { + Cudd_Deref( bFunc ); + Abc_ObjSetGlobalBdd( pNode, NULL ); + } + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Frees the global BDDs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ) +{ + return Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, fFreeMan ); +} + +/**Function************************************************************* + + Synopsis [Returns the shared size of global BDDs of the COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vFuncsGlob; + Abc_Obj_t * pObj; + int RetValue, i; + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); + RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) ); + Vec_PtrFree( vFuncsGlob ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Computes the BDD of the logic cone of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ) +{ + /* + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pNodeR; + DdManager * dd; + DdNode * bFunc; + double Result; + int i; + pNodeR = Abc_ObjRegular(pNode); + assert( Abc_NtkIsStrash(pNodeR->pNtk) ); + Abc_NtkCleanCopy( pNodeR->pNtk ); + // get the CIs in the support of the node + vNodes = Abc_NtkNodeSupport( pNodeR->pNtk, &pNodeR, 1 ); + // start the manager + dd = Cudd_Init( Vec_PtrSize(vNodes), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + // assign elementary BDDs for the CIs + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)dd->vars[i]; + // build the BDD of the cone + bFunc = Abc_NodeGlobalBdds_rec( dd, pNodeR, 10000000, 1, NULL, NULL, 1 ); Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, pNode != pNodeR ); + // count minterms + Result = Cudd_CountMinterm( dd, bFunc, dd->size ); + // get the percentagle + Result *= 100.0; + for ( i = 0; i < dd->size; i++ ) + Result /= 2; + // clean up + Cudd_Quit( dd ); + Vec_PtrFree( vNodes ); + return Result; + */ + return 0.0; +} + + + + +/**Function************************************************************* + + Synopsis [Experiment with BDD-based representation of implications.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBddImplicationTest() +{ + DdManager * dd; + DdNode * bImp, * bSum, * bTemp; + int nVars = 200; + int nImps = 200; + int i, clk; +clk = clock(); + dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SIFT ); + bSum = b0; Cudd_Ref( bSum ); + for ( i = 0; i < nImps; i++ ) + { + printf( "." ); + bImp = Cudd_bddAnd( dd, dd->vars[rand()%nVars], dd->vars[rand()%nVars] ); Cudd_Ref( bImp ); + bSum = Cudd_bddOr( dd, bTemp = bSum, bImp ); Cudd_Ref( bSum ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bImp ); + } + printf( "The BDD before = %d.\n", Cudd_DagSize(bSum) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SIFT, 1 ); + printf( "The BDD after = %d.\n", Cudd_DagSize(bSum) ); +PRT( "Time", clock() - clk ); + Cudd_RecursiveDeref( dd, bSum ); + Cudd_Quit( dd ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcOdc.c b/abc70930/src/base/abci/abcOdc.c new file mode 100644 index 00000000..d6e59328 --- /dev/null +++ b/abc70930/src/base/abci/abcOdc.c @@ -0,0 +1,1134 @@ +/**CFile**************************************************************** + + FileName [abcOdc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Scalable computation of observability don't-cares.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcOdc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_DC_MAX_NODES (1<<15) + +typedef unsigned short Odc_Lit_t; + +typedef struct Odc_Obj_t_ Odc_Obj_t; // 16 bytes +struct Odc_Obj_t_ +{ + Odc_Lit_t iFan0; // first fanin + Odc_Lit_t iFan1; // second fanin + Odc_Lit_t iNext; // next node in the hash table + unsigned short TravId; // the traversal ID + unsigned uData; // the computed data + unsigned uMask; // the variable mask +}; + +typedef struct Odc_Man_t_ Odc_Man_t; +struct Odc_Man_t_ +{ + // dont'-care parameters + int nVarsMax; // the max number of cut variables + int nLevels; // the number of ODC levels + int fVerbose; // the verbosiness flag + int fVeryVerbose;// the verbosiness flag to print per-node stats + int nPercCutoff; // cutoff percentage + + // windowing + Abc_Obj_t * pNode; // the node for windowing + Vec_Ptr_t * vLeaves; // the number of the cut + Vec_Ptr_t * vRoots; // the roots of the cut + Vec_Ptr_t * vBranches; // additional inputs + + // internal AIG package + // objects + int nPis; // number of PIs (nVarsMax + 32) + int nObjs; // number of objects (Const1, PIs, ANDs) + int nObjsAlloc; // number of objects allocated + Odc_Obj_t * pObjs; // objects + Odc_Lit_t iRoot; // the root object + unsigned short nTravIds; // the number of travIDs + // structural hashing + Odc_Lit_t * pTable; // hash table + int nTableSize; // hash table size + Vec_Int_t * vUsedSpots; // the used spots + + // truth tables + int nBits; // the number of bits + int nWords; // the number of words + Vec_Ptr_t * vTruths; // truth tables for each node + Vec_Ptr_t * vTruthsElem; // elementary truth tables for the PIs + unsigned * puTruth; // the place where the resulting truth table does + + // statistics + int nWins; // the number of windows processed + int nWinsEmpty; // the number of empty windows + int nSimsEmpty; // the number of empty simulation infos + int nQuantsOver; // the number of quantification overflows + int nWinsFinish; // the number of windows that finished + int nTotalDcs; // total percentage of DCs + + // runtime + int timeClean; // windowing + int timeWin; // windowing + int timeMiter; // computing the miter + int timeSim; // simulation + int timeQuant; // quantification + int timeTruth; // truth table + int timeTotal; // useful runtime + int timeAbort; // aborted runtime +}; + + +// quantity of different objects +static inline int Odc_PiNum( Odc_Man_t * p ) { return p->nPis; } +static inline int Odc_NodeNum( Odc_Man_t * p ) { return p->nObjs - p->nPis - 1; } +static inline int Odc_ObjNum( Odc_Man_t * p ) { return p->nObjs; } + +// complemented attributes of objects +static inline int Odc_IsComplement( Odc_Lit_t Lit ) { return Lit & (Odc_Lit_t)1; } +static inline Odc_Lit_t Odc_Regular( Odc_Lit_t Lit ) { return Lit & ~(Odc_Lit_t)1; } +static inline Odc_Lit_t Odc_Not( Odc_Lit_t Lit ) { return Lit ^ (Odc_Lit_t)1; } +static inline Odc_Lit_t Odc_NotCond( Odc_Lit_t Lit, int c ) { return Lit ^ (Odc_Lit_t)(c!=0); } + +// specialized Literals +static inline Odc_Lit_t Odc_Const0() { return 1; } +static inline Odc_Lit_t Odc_Const1() { return 0; } +static inline Odc_Lit_t Odc_Var( Odc_Man_t * p, int i ) { assert( i >= 0 && i < p->nPis ); return (i+1) << 1; } +static inline int Odc_IsConst( Odc_Lit_t Lit ) { return Lit < (Odc_Lit_t)2; } +static inline int Odc_IsTerm( Odc_Man_t * p, Odc_Lit_t Lit ) { return (int)(Lit>>1) <= p->nPis; } + +// accessing internal storage +static inline Odc_Obj_t * Odc_ObjNew( Odc_Man_t * p ) { assert( p->nObjs < p->nObjsAlloc ); return p->pObjs + p->nObjs++; } +static inline Odc_Lit_t Odc_Obj2Lit( Odc_Man_t * p, Odc_Obj_t * pObj ) { assert( pObj ); return (pObj - p->pObjs) << 1; } +static inline Odc_Obj_t * Odc_Lit2Obj( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) && (int)(Lit>>1) < p->nObjs ); return p->pObjs + (Lit>>1); } + +// fanins and their complements +static inline Odc_Lit_t Odc_ObjChild0( Odc_Obj_t * pObj ) { return pObj->iFan0; } +static inline Odc_Lit_t Odc_ObjChild1( Odc_Obj_t * pObj ) { return pObj->iFan1; } +static inline Odc_Lit_t Odc_ObjFanin0( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan0); } +static inline Odc_Lit_t Odc_ObjFanin1( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan1); } +static inline int Odc_ObjFaninC0( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan0); } +static inline int Odc_ObjFaninC1( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan1); } + +// traversal IDs +static inline void Odc_ManIncrementTravId( Odc_Man_t * p ) { p->nTravIds++; } +static inline void Odc_ObjSetTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } +static inline int Odc_ObjIsTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); } + +// truth tables +static inline unsigned * Odc_ObjTruth( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) ); return Vec_PtrEntry(p->vTruths, Lit >> 1); } + +// iterators +#define Odc_ForEachPi( p, Lit, i ) \ + for ( i = 0; (i < Odc_PiNum(p)) && (((Lit) = Odc_Var(p, i)), 1); i++ ) +#define Odc_ForEachAnd( p, pObj, i ) \ + for ( i = 1 + Odc_CiNum(p); (i < Odc_ObjNum(p)) && ((pObj) = (p)->pObjs + i); i++ ) + + +// exported functions +extern Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ); +extern void Abc_NtkDontCareClear( Odc_Man_t * p ); +extern void Abc_NtkDontCareFree( Odc_Man_t * p ); +extern int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the don't-care manager.] + + Description [The parameters are the max number of cut variables, + the number of fanout levels used for the ODC computation, and verbosiness.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ) +{ + Odc_Man_t * p; + unsigned * pData; + int i, k; + p = ALLOC( Odc_Man_t, 1 ); + memset( p, 0, sizeof(Odc_Man_t) ); + assert( nVarsMax > 4 && nVarsMax < 16 ); + assert( nLevels > 0 && nLevels < 10 ); + + srand( 0xABC ); + + // dont'-care parameters + p->nVarsMax = nVarsMax; + p->nLevels = nLevels; + p->fVerbose = fVerbose; + p->fVeryVerbose = fVeryVerbose; + p->nPercCutoff = 10; + + // windowing + p->vRoots = Vec_PtrAlloc( 128 ); + p->vBranches = Vec_PtrAlloc( 128 ); + + // internal AIG package + // allocate room for objects + p->nObjsAlloc = ABC_DC_MAX_NODES; + p->pObjs = ALLOC( Odc_Obj_t, p->nObjsAlloc * sizeof(Odc_Obj_t) ); + p->nPis = nVarsMax + 32; + p->nObjs = 1 + p->nPis; + memset( p->pObjs, 0, p->nObjs * sizeof(Odc_Obj_t) ); + // set the PI masks + for ( i = 0; i < 32; i++ ) + p->pObjs[1 + p->nVarsMax + i].uMask = (1 << i); + // allocate hash table + p->nTableSize = p->nObjsAlloc/3 + 1; + p->pTable = ALLOC( Odc_Lit_t, p->nTableSize * sizeof(Odc_Lit_t) ); + memset( p->pTable, 0, p->nTableSize * sizeof(Odc_Lit_t) ); + p->vUsedSpots = Vec_IntAlloc( 1000 ); + + // truth tables + p->nWords = Abc_TruthWordNum( p->nVarsMax ); + p->nBits = p->nWords * 8 * sizeof(unsigned); + p->vTruths = Vec_PtrAllocSimInfo( p->nObjsAlloc, p->nWords ); + p->vTruthsElem = Vec_PtrAllocSimInfo( p->nVarsMax, p->nWords ); + + // set elementary truth tables + Abc_InfoFill( Vec_PtrEntry(p->vTruths, 0), p->nWords ); + for ( k = 0; k < p->nVarsMax; k++ ) + { +// pData = Odc_ObjTruth( p, Odc_Var(p, k) ); + pData = Vec_PtrEntry( p->vTruthsElem, k ); + Abc_InfoClear( pData, p->nWords ); + for ( i = 0; i < p->nBits; i++ ) + if ( i & (1 << k) ) + pData[i>>5] |= (1 << (i&31)); + } + + // set random truth table for the additional inputs + for ( k = p->nVarsMax; k < p->nPis; k++ ) + { + pData = Odc_ObjTruth( p, Odc_Var(p, k) ); + Abc_InfoRandom( pData, p->nWords ); + } + + // set the miter to the unused value + p->iRoot = 0xffff; + return p; +} + +/**Function************************************************************* + + Synopsis [Clears the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareClear( Odc_Man_t * p ) +{ + int clk = clock(); + // clean the structural hashing table + if ( Vec_IntSize(p->vUsedSpots) > p->nTableSize/3 ) // more than one third + memset( p->pTable, 0, sizeof(Odc_Lit_t) * p->nTableSize ); + else + { + int iSpot, i; + Vec_IntForEachEntry( p->vUsedSpots, iSpot, i ) + p->pTable[iSpot] = 0; + } + Vec_IntClear( p->vUsedSpots ); + // reset the number of nodes + p->nObjs = 1 + p->nPis; + // reset the root node + p->iRoot = 0xffff; + +p->timeClean += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [Frees the don't-care manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareFree( Odc_Man_t * p ) +{ + if ( p->fVerbose ) + { + printf( "Wins = %5d. Empty = %5d. SimsEmpty = %5d. QuantOver = %5d. WinsFinish = %5d.\n", + p->nWins, p->nWinsEmpty, p->nSimsEmpty, p->nQuantsOver, p->nWinsFinish ); + printf( "Ave DCs per window = %6.2f %%. Ave DCs per finished window = %6.2f %%.\n", + 1.0*p->nTotalDcs/p->nWins, 1.0*p->nTotalDcs/p->nWinsFinish ); + printf( "Runtime stats of the ODC manager:\n" ); + PRT( "Cleaning ", p->timeClean ); + PRT( "Windowing ", p->timeWin ); + PRT( "Miter ", p->timeMiter ); + PRT( "Simulation ", p->timeSim ); + PRT( "Quantifying ", p->timeQuant ); + PRT( "Truth table ", p->timeTruth ); + PRT( "TOTAL ", p->timeTotal ); + PRT( "Aborted ", p->timeAbort ); + } + Vec_PtrFree( p->vRoots ); + Vec_PtrFree( p->vBranches ); + Vec_PtrFree( p->vTruths ); + Vec_PtrFree( p->vTruthsElem ); + Vec_IntFree( p->vUsedSpots ); + free( p->pObjs ); + free( p->pTable ); + free( p ); +} + + + +/**Function************************************************************* + + Synopsis [Marks the TFO of the collected nodes up to the given level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareWinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i; + if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit || pObj == pNode ) + return; + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return; + Abc_NodeSetTravIdCurrent( pObj ); + //////////////////////////////////////// + // try to reduce the runtime + if ( Abc_ObjFanoutNum(pObj) > 100 ) + return; + //////////////////////////////////////// + Abc_ObjForEachFanout( pObj, pFanout, i ) + Abc_NtkDontCareWinSweepLeafTfo_rec( pFanout, nLevelLimit, pNode ); +} + +/**Function************************************************************* + + Synopsis [Marks the TFO of the collected nodes up to the given level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareWinSweepLeafTfo( Odc_Man_t * p ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Vec_PtrForEachEntry( p->vLeaves, pObj, i ) + Abc_NtkDontCareWinSweepLeafTfo_rec( pObj, p->pNode->Level + p->nLevels, p->pNode ); +} + +/**Function************************************************************* + + Synopsis [Recursively collects the roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareWinCollectRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots ) +{ + Abc_Obj_t * pFanout; + int i; + assert( Abc_ObjIsNode(pObj) ); + assert( Abc_NodeIsTravIdCurrent(pObj) ); + // check if the node has all fanouts marked + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( !Abc_NodeIsTravIdCurrent(pFanout) ) + break; + // if some of the fanouts are unmarked, add the node to the root + if ( i < Abc_ObjFanoutNum(pObj) ) + { + Vec_PtrPushUnique( vRoots, pObj ); + return; + } + // otherwise, call recursively + Abc_ObjForEachFanout( pObj, pFanout, i ) + Abc_NtkDontCareWinCollectRoots_rec( pFanout, vRoots ); +} + +/**Function************************************************************* + + Synopsis [Collects the roots of the window.] + + Description [Roots of the window are the nodes that have at least + one fanout that it not in the TFO of the leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareWinCollectRoots( Odc_Man_t * p ) +{ + assert( !Abc_NodeIsTravIdCurrent(p->pNode) ); + // mark the node with the old traversal ID + Abc_NodeSetTravIdCurrent( p->pNode ); + // collect the roots + Vec_PtrClear( p->vRoots ); + Abc_NtkDontCareWinCollectRoots_rec( p->pNode, p->vRoots ); +} + +/**Function************************************************************* + + Synopsis [Recursively adds missing nodes and leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareWinAddMissing_rec( Odc_Man_t * p, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + // skip the already collected leaves and branches + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 1; + // if this is not an internal node - make it a new branch + if ( !Abc_NodeIsTravIdPrevious(pObj) || Abc_ObjIsCi(pObj) ) //|| (int)pObj->Level <= p->nLevLeaves ) + { + Abc_NodeSetTravIdCurrent( pObj ); + Vec_PtrPush( p->vBranches, pObj ); + return Vec_PtrSize(p->vBranches) <= 32; + } + // visit the fanins of the node + Abc_ObjForEachFanin( pObj, pFanin, i ) + if ( !Abc_NtkDontCareWinAddMissing_rec( p, pFanin ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds to the window nodes and leaves in the TFI of the roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareWinAddMissing( Odc_Man_t * p ) +{ + Abc_Obj_t * pObj; + int i; + // set the leaves + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Vec_PtrForEachEntry( p->vLeaves, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // explore from the roots + Vec_PtrClear( p->vBranches ); + Vec_PtrForEachEntry( p->vRoots, pObj, i ) + if ( !Abc_NtkDontCareWinAddMissing_rec( p, pObj ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes window for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareWindow( Odc_Man_t * p ) +{ + // mark the TFO of the collected nodes up to the given level (p->pNode->Level + p->nWinTfoMax) + Abc_NtkDontCareWinSweepLeafTfo( p ); + // find the roots of the window + Abc_NtkDontCareWinCollectRoots( p ); + if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode ) + { +// printf( "Empty window\n" ); + return 0; + } + // add the nodes in the TFI of the roots that are not yet in the window + if ( !Abc_NtkDontCareWinAddMissing( p ) ) + { +// printf( "Too many branches (%d)\n", Vec_PtrSize(p->vBranches) ); + return 0; + } + return 1; +} + + + + + +/**Function************************************************************* + + Synopsis [Performing hashing of two AIG Literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Odc_HashKey( Odc_Lit_t iFan0, Odc_Lit_t iFan1, int TableSize ) +{ + unsigned Key = 0; + Key ^= Odc_Regular(iFan0) * 7937; + Key ^= Odc_Regular(iFan1) * 2971; + Key ^= Odc_IsComplement(iFan0) * 911; + Key ^= Odc_IsComplement(iFan1) * 353; + return Key % TableSize; +} + +/**Function************************************************************* + + Synopsis [Checks if the given name node already exists in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Odc_Lit_t * Odc_HashLookup( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) +{ + Odc_Obj_t * pObj; + Odc_Lit_t * pEntry; + unsigned uHashKey; + assert( iFan0 < iFan1 ); + // get the hash key for this node + uHashKey = Odc_HashKey( iFan0, iFan1, p->nTableSize ); + // remember the spot in the hash table that will be used + if ( p->pTable[uHashKey] == 0 ) + Vec_IntPush( p->vUsedSpots, uHashKey ); + // find the entry + for ( pEntry = p->pTable + uHashKey; *pEntry; pEntry = &pObj->iNext ) + { + pObj = Odc_Lit2Obj( p, *pEntry ); + if ( pObj->iFan0 == iFan0 && pObj->iFan1 == iFan1 ) + return pEntry; + } + return pEntry; +} + +/**Function************************************************************* + + Synopsis [Finds node by structural hashing or creates a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Odc_Lit_t Odc_And( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) +{ + Odc_Obj_t * pObj; + Odc_Lit_t * pEntry; + unsigned uMask0, uMask1; + int Temp; + // consider trivial cases + if ( iFan0 == iFan1 ) + return iFan0; + if ( iFan0 == Odc_Not(iFan1) ) + return Odc_Const0(); + if ( Odc_Regular(iFan0) == Odc_Const1() ) + return iFan0 == Odc_Const1() ? iFan1 : Odc_Const0(); + if ( Odc_Regular(iFan1) == Odc_Const1() ) + return iFan1 == Odc_Const1() ? iFan0 : Odc_Const0(); + // canonicize the fanin order + if ( iFan0 > iFan1 ) + Temp = iFan0, iFan0 = iFan1, iFan1 = Temp; + // check if a node with these fanins exists + pEntry = Odc_HashLookup( p, iFan0, iFan1 ); + if ( *pEntry ) + return *pEntry; + // create a new node + pObj = Odc_ObjNew( p ); + pObj->iFan0 = iFan0; + pObj->iFan1 = iFan1; + pObj->iNext = 0; + pObj->TravId = 0; + // set the mask + uMask0 = Odc_Lit2Obj(p, Odc_Regular(iFan0))->uMask; + uMask1 = Odc_Lit2Obj(p, Odc_Regular(iFan1))->uMask; + pObj->uMask = uMask0 | uMask1; + // add to the table + *pEntry = Odc_Obj2Lit( p, pObj ); + return *pEntry; +} + +/**Function************************************************************* + + Synopsis [Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Odc_Lit_t Odc_Or( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) +{ + return Odc_Not( Odc_And(p, Odc_Not(iFan0), Odc_Not(iFan1)) ); +} + +/**Function************************************************************* + + Synopsis [Boolean XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Odc_Lit_t Odc_Xor( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) +{ + return Odc_Or( p, Odc_And(p, iFan0, Odc_Not(iFan1)), Odc_And(p, Odc_Not(iFan0), iFan1) ); +} + + + + + +/**Function************************************************************* + + Synopsis [Transfers the window into the AIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NtkDontCareTransfer_rec( Odc_Man_t * p, Abc_Obj_t * pNode, Abc_Obj_t * pPivot ) +{ + unsigned uData0, uData1; + Odc_Lit_t uLit0, uLit1, uRes0, uRes1; + assert( !Abc_ObjIsComplement(pNode) ); + // skip visited objects + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return pNode->pCopy; + Abc_NodeSetTravIdCurrent(pNode); + assert( Abc_ObjIsNode(pNode) ); + // consider the case when the node is the pivot + if ( pNode == pPivot ) + return pNode->pCopy = (void *)((Odc_Const1() << 16) | Odc_Const0()); + // compute the cofactors + uData0 = (unsigned)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin0(pNode), pPivot ); + uData1 = (unsigned)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin1(pNode), pPivot ); + // find the 0-cofactor + uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Abc_ObjFaninC0(pNode) ); + uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Abc_ObjFaninC1(pNode) ); + uRes0 = Odc_And( p, uLit0, uLit1 ); + // find the 1-cofactor + uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Abc_ObjFaninC0(pNode) ); + uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Abc_ObjFaninC1(pNode) ); + uRes1 = Odc_And( p, uLit0, uLit1 ); + // find the result + return pNode->pCopy = (void *)((uRes1 << 16) | uRes0); +} + +/**Function************************************************************* + + Synopsis [Transfers the window into the AIG package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareTransfer( Odc_Man_t * p ) +{ + Abc_Obj_t * pObj; + Odc_Lit_t uRes0, uRes1; + Odc_Lit_t uLit; + unsigned uData; + int i; + Abc_NtkIncrementTravId( p->pNode->pNtk ); + // set elementary variables at the leaves + Vec_PtrForEachEntry( p->vLeaves, pObj, i ) + { + uLit = Odc_Var( p, i ); + pObj->pCopy = (void *)((uLit << 16) | uLit); + Abc_NodeSetTravIdCurrent(pObj); + } + // set elementary variables at the branched + Vec_PtrForEachEntry( p->vBranches, pObj, i ) + { + uLit = Odc_Var( p, i+p->nVarsMax ); + pObj->pCopy = (void *)((uLit << 16) | uLit); + Abc_NodeSetTravIdCurrent(pObj); + } + // compute the AIG for the window + p->iRoot = Odc_Const0(); + Vec_PtrForEachEntry( p->vRoots, pObj, i ) + { + uData = (unsigned)Abc_NtkDontCareTransfer_rec( p, pObj, p->pNode ); + // get the cofactors + uRes0 = uData & 0xffff; + uRes1 = uData >> 16; + // compute the miter +// assert( uRes0 != uRes1 ); // may be false if the node is redundant w.r.t. this root + uLit = Odc_Xor( p, uRes0, uRes1 ); + p->iRoot = Odc_Or( p, p->iRoot, uLit ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Recursively computes the pair of cofactors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Abc_NtkDontCareCofactors_rec( Odc_Man_t * p, Odc_Lit_t Lit, unsigned uMask ) +{ + Odc_Obj_t * pObj; + unsigned uData0, uData1; + Odc_Lit_t uLit0, uLit1, uRes0, uRes1; + assert( !Odc_IsComplement(Lit) ); + // skip visited objects + pObj = Odc_Lit2Obj( p, Lit ); + if ( Odc_ObjIsTravIdCurrent(p, pObj) ) + return pObj->uData; + Odc_ObjSetTravIdCurrent(p, pObj); + // skip objects out of the cone + if ( (pObj->uMask & uMask) == 0 ) + return pObj->uData = ((Lit << 16) | Lit); + // consider the case when the node is the var + if ( pObj->uMask == uMask && Odc_IsTerm(p, Lit) ) + return pObj->uData = ((Odc_Const1() << 16) | Odc_Const0()); + // compute the cofactors + uData0 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin0(pObj), uMask ); + uData1 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin1(pObj), uMask ); + // find the 0-cofactor + uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Odc_ObjFaninC0(pObj) ); + uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Odc_ObjFaninC1(pObj) ); + uRes0 = Odc_And( p, uLit0, uLit1 ); + // find the 1-cofactor + uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Odc_ObjFaninC0(pObj) ); + uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Odc_ObjFaninC1(pObj) ); + uRes1 = Odc_And( p, uLit0, uLit1 ); + // find the result + return pObj->uData = ((uRes1 << 16) | uRes0); +} + +/**Function************************************************************* + + Synopsis [Quantifies the branch variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareQuantify( Odc_Man_t * p ) +{ + Odc_Lit_t uRes0, uRes1; + unsigned uData; + int i; + assert( p->iRoot < 0xffff ); + assert( Vec_PtrSize(p->vBranches) <= 32 ); // the mask size + for ( i = 0; i < Vec_PtrSize(p->vBranches); i++ ) + { + // compute the cofactors w.r.t. this variable + Odc_ManIncrementTravId( p ); + uData = Abc_NtkDontCareCofactors_rec( p, Odc_Regular(p->iRoot), (1 << i) ); + uRes0 = Odc_NotCond( (Odc_Lit_t)(uData & 0xffff), Odc_IsComplement(p->iRoot) ); + uRes1 = Odc_NotCond( (Odc_Lit_t)(uData >> 16), Odc_IsComplement(p->iRoot) ); + // quantify this variable existentially + p->iRoot = Odc_Or( p, uRes0, uRes1 ); + // check the limit + if ( Odc_ObjNum(p) > ABC_DC_MAX_NODES/2 ) + return 0; + } + assert( p->nObjs <= p->nObjsAlloc ); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [Set elementary truth tables for PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareSimulateSetElem2( Odc_Man_t * p ) +{ + unsigned * pData; + int i, k; + for ( k = 0; k < p->nVarsMax; k++ ) + { + pData = Odc_ObjTruth( p, Odc_Var(p, k) ); + Abc_InfoClear( pData, p->nWords ); + for ( i = 0; i < p->nBits; i++ ) + if ( i & (1 << k) ) + pData[i>>5] |= (1 << (i&31)); + } +} + +/**Function************************************************************* + + Synopsis [Set elementary truth tables for PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareSimulateSetElem( Odc_Man_t * p ) +{ + unsigned * pData, * pData2; + int k; + for ( k = 0; k < p->nVarsMax; k++ ) + { + pData = Odc_ObjTruth( p, Odc_Var(p, k) ); + pData2 = Vec_PtrEntry( p->vTruthsElem, k ); + Abc_InfoCopy( pData, pData2, p->nWords ); + } +} + +/**Function************************************************************* + + Synopsis [Set random simulation words for PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareSimulateSetRand( Odc_Man_t * p ) +{ + unsigned * pData; + int w, k, Number; + for ( w = 0; w < p->nWords; w++ ) + { + Number = rand(); + for ( k = 0; k < p->nVarsMax; k++ ) + { + pData = Odc_ObjTruth( p, Odc_Var(p, k) ); + pData[w] = (Number & (1<nWords; w++ ) + if ( puTruth[w] ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareTruthOne( Odc_Man_t * p, Odc_Lit_t Lit ) +{ + Odc_Obj_t * pObj; + unsigned * pInfo, * pInfo1, * pInfo2; + int k, fComp1, fComp2; + assert( !Odc_IsComplement( Lit ) ); + assert( !Odc_IsTerm( p, Lit ) ); + // get the truth tables + pObj = Odc_Lit2Obj( p, Lit ); + pInfo = Odc_ObjTruth( p, Lit ); + pInfo1 = Odc_ObjTruth( p, Odc_ObjFanin0(pObj) ); + pInfo2 = Odc_ObjTruth( p, Odc_ObjFanin1(pObj) ); + fComp1 = Odc_ObjFaninC0( pObj ); + fComp2 = Odc_ObjFaninC1( pObj ); + // simulate + if ( fComp1 && fComp2 ) + for ( k = 0; k < p->nWords; k++ ) + pInfo[k] = ~pInfo1[k] & ~pInfo2[k]; + else if ( fComp1 && !fComp2 ) + for ( k = 0; k < p->nWords; k++ ) + pInfo[k] = ~pInfo1[k] & pInfo2[k]; + else if ( !fComp1 && fComp2 ) + for ( k = 0; k < p->nWords; k++ ) + pInfo[k] = pInfo1[k] & ~pInfo2[k]; + else // if ( fComp1 && fComp2 ) + for ( k = 0; k < p->nWords; k++ ) + pInfo[k] = pInfo1[k] & pInfo2[k]; +} + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDontCareSimulate_rec( Odc_Man_t * p, Odc_Lit_t Lit ) +{ + Odc_Obj_t * pObj; + assert( !Odc_IsComplement(Lit) ); + // skip terminals + if ( Odc_IsTerm(p, Lit) ) + return; + // skip visited objects + pObj = Odc_Lit2Obj( p, Lit ); + if ( Odc_ObjIsTravIdCurrent(p, pObj) ) + return; + Odc_ObjSetTravIdCurrent(p, pObj); + // call recursively + Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin0(pObj) ); + Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin1(pObj) ); + // construct the truth table + Abc_NtkDontCareTruthOne( p, Lit ); +} + +/**Function************************************************************* + + Synopsis [Computes the truth table of the care set.] + + Description [Returns the number of ones in the simulation info.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareSimulate( Odc_Man_t * p, unsigned * puTruth ) +{ + Odc_ManIncrementTravId( p ); + Abc_NtkDontCareSimulate_rec( p, Odc_Regular(p->iRoot) ); + Abc_InfoCopy( puTruth, Odc_ObjTruth(p, Odc_Regular(p->iRoot)), p->nWords ); + if ( Odc_IsComplement(p->iRoot) ) + Abc_InfoNot( puTruth, p->nWords ); + return Extra_TruthCountOnes( puTruth, p->nVarsMax ); +} + +/**Function************************************************************* + + Synopsis [Computes the truth table of the care set.] + + Description [Returns the number of ones in the simulation info.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareSimulateBefore( Odc_Man_t * p, unsigned * puTruth ) +{ + int nIters = 2; + int nRounds, Counter, r; + // decide how many rounds to simulate + nRounds = p->nBits / p->nWords; + Counter = 0; + for ( r = 0; r < nIters; r++ ) + { + Abc_NtkDontCareSimulateSetRand( p ); + Abc_NtkDontCareSimulate( p, puTruth ); + Counter += Abc_NtkDontCareCountMintsWord( p, puTruth ); + } + // normalize + Counter = Counter * nRounds / nIters; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Computes ODCs for the node in terms of the cut variables.] + + Description [Returns the number of don't care minterms in the truth table. + In particular, this procedure returns 0 if there is no don't-cares.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ) +{ + int nMints, RetValue; + int clk, clkTotal = clock(); + + p->nWins++; + + // set the parameters + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + assert( Vec_PtrSize(vLeaves) <= p->nVarsMax ); + p->vLeaves = vLeaves; + p->pNode = pNode; + + // compute the window +clk = clock(); + RetValue = Abc_NtkDontCareWindow( p ); +p->timeWin += clock() - clk; + if ( !RetValue ) + { +p->timeAbort += clock() - clkTotal; + Abc_InfoFill( puTruth, p->nWords ); + p->nWinsEmpty++; + return 0; + } + + if ( p->fVeryVerbose ) + { + printf( " %5d : ", pNode->Id ); + printf( "Leaf = %2d ", Vec_PtrSize(p->vLeaves) ); + printf( "Root = %2d ", Vec_PtrSize(p->vRoots) ); + printf( "Bran = %2d ", Vec_PtrSize(p->vBranches) ); + printf( " | " ); + } + + // transfer the window into the AIG package +clk = clock(); + Abc_NtkDontCareTransfer( p ); +p->timeMiter += clock() - clk; + + // simulate to estimate the amount of don't-cares +clk = clock(); + nMints = Abc_NtkDontCareSimulateBefore( p, puTruth ); +p->timeSim += clock() - clk; + if ( p->fVeryVerbose ) + { + printf( "AIG = %5d ", Odc_NodeNum(p) ); + printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits ); + } + + // if there is less then the given percentage of don't-cares, skip + if ( 100.0 * (p->nBits - nMints) / p->nBits < 1.0 * p->nPercCutoff ) + { +p->timeAbort += clock() - clkTotal; + if ( p->fVeryVerbose ) + printf( "Simulation cutoff.\n" ); + Abc_InfoFill( puTruth, p->nWords ); + p->nSimsEmpty++; + return 0; + } + + // quantify external variables +clk = clock(); + RetValue = Abc_NtkDontCareQuantify( p ); +p->timeQuant += clock() - clk; + if ( !RetValue ) + { +p->timeAbort += clock() - clkTotal; + if ( p->fVeryVerbose ) + printf( "=== Overflow! ===\n" ); + Abc_InfoFill( puTruth, p->nWords ); + p->nQuantsOver++; + return 0; + } + + // get the truth table +clk = clock(); + Abc_NtkDontCareSimulateSetElem( p ); + nMints = Abc_NtkDontCareSimulate( p, puTruth ); +p->timeTruth += clock() - clk; + if ( p->fVeryVerbose ) + { + printf( "AIG = %5d ", Odc_NodeNum(p) ); + printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits ); + printf( "\n" ); + } +p->timeTotal += clock() - clkTotal; + p->nWinsFinish++; + p->nTotalDcs += (int)(100.0 * (p->nBits - nMints) / p->nBits); + return nMints; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcOrder.c b/abc70930/src/base/abci/abcOrder.c new file mode 100644 index 00000000..04417f77 --- /dev/null +++ b/abc70930/src/base/abci/abcOrder.c @@ -0,0 +1,131 @@ +/**CFile**************************************************************** + + FileName [abcOrder.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Exploring static BDD variable orders.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Changes the order of primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ) +{ + Vec_Ptr_t * vSupp; + vSupp = Abc_NtkSupport( pNtk ); + Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse ); + Vec_PtrFree( vSupp ); +} + +/**Function************************************************************* + + Synopsis [Implements the given variable order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ) +{ + char Buffer[1000]; + FILE * pFile; + Vec_Ptr_t * vSupp; + Abc_Obj_t * pObj; + pFile = fopen( pFileName, "r" ); + vSupp = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) ); + while ( fscanf( pFile, "%s", Buffer ) == 1 ) + { + pObj = Abc_NtkFindCi( pNtk, Buffer ); + if ( pObj == NULL || !Abc_ObjIsCi(pObj) ) + { + printf( "Name \"%s\" is not a PI name. Cannot use this order.\n", Buffer ); + Vec_PtrFree( vSupp ); + fclose( pFile ); + return; + } + Vec_PtrPush( vSupp, pObj ); + } + fclose( pFile ); + if ( Vec_PtrSize(vSupp) != Abc_NtkCiNum(pNtk) ) + { + printf( "The number of names in the order (%d) is not the same as the number of PIs (%d).\n", Vec_PtrSize(vSupp), Abc_NtkCiNum(pNtk) ); + Vec_PtrFree( vSupp ); + return; + } + Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse ); + Vec_PtrFree( vSupp ); +} + +/**Function************************************************************* + + Synopsis [Changes the order of primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse ) +{ + Abc_Obj_t * pObj; + int i; + assert( Vec_PtrSize(vSupp) == Abc_NtkCiNum(pNtk) ); + // order CIs using the array + if ( fReverse ) + Vec_PtrForEachEntry( vSupp, pObj, i ) + Vec_PtrWriteEntry( pNtk->vCis, Vec_PtrSize(vSupp)-1-i, pObj ); + else + Vec_PtrForEachEntry( vSupp, pObj, i ) + Vec_PtrWriteEntry( pNtk->vCis, i, pObj ); + // order PIs accordingly + Vec_PtrClear( pNtk->vPis ); + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjIsPi(pObj) ) + Vec_PtrPush( pNtk->vPis, pObj ); +// Abc_NtkForEachCi( pNtk, pObj, i ) +// printf( "%s ", Abc_ObjName(pObj) ); +// printf( "\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcPart.c b/abc70930/src/base/abci/abcPart.c new file mode 100644 index 00000000..85c4e918 --- /dev/null +++ b/abc70930/src/base/abci/abcPart.c @@ -0,0 +1,1205 @@ +/**CFile**************************************************************** + + FileName [abcPart.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Output partitioning package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcPart.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Supp_Man_t_ Supp_Man_t; +struct Supp_Man_t_ +{ + int nChunkSize; // the size of one chunk of memory (~1 Mb) + int nStepSize; // the step size in saving memory (~64 bytes) + char * pFreeBuf; // the pointer to free memory + int nFreeSize; // the size of remaining free memory + Vec_Ptr_t * vMemory; // the memory allocated + Vec_Ptr_t * vFree; // the vector of free pieces of memory +}; + +typedef struct Supp_One_t_ Supp_One_t; +struct Supp_One_t_ +{ + int nRefs; // the number of references + int nOuts; // the number of outputs + int nOutsAlloc; // the array size + int pOuts[0]; // the array of outputs +}; + +static inline int Supp_SizeType( int nSize, int nStepSize ) { return nSize / nStepSize + ((nSize % nStepSize) > 0); } +static inline char * Supp_OneNext( char * pPart ) { return *((char **)pPart); } +static inline void Supp_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Supp_Man_t * Supp_ManStart( int nChunkSize, int nStepSize ) +{ + Supp_Man_t * p; + p = ALLOC( Supp_Man_t, 1 ); + memset( p, 0, sizeof(Supp_Man_t) ); + p->nChunkSize = nChunkSize; + p->nStepSize = nStepSize; + p->vMemory = Vec_PtrAlloc( 1000 ); + p->vFree = Vec_PtrAlloc( 1000 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Supp_ManStop( Supp_Man_t * p ) +{ + void * pMemory; + int i; + Vec_PtrForEachEntry( p->vMemory, pMemory, i ) + free( pMemory ); + Vec_PtrFree( p->vMemory ); + Vec_PtrFree( p->vFree ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Fetches the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Supp_ManFetch( Supp_Man_t * p, int nSize ) +{ + int Type, nSizeReal; + char * pMemory; + assert( nSize > 0 ); + Type = Supp_SizeType( nSize, p->nStepSize ); + Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); + if ( pMemory = Vec_PtrEntry( p->vFree, Type ) ) + { + Vec_PtrWriteEntry( p->vFree, Type, Supp_OneNext(pMemory) ); + return pMemory; + } + nSizeReal = p->nStepSize * Type; + if ( p->nFreeSize < nSizeReal ) + { + p->pFreeBuf = ALLOC( char, p->nChunkSize ); + p->nFreeSize = p->nChunkSize; + Vec_PtrPush( p->vMemory, p->pFreeBuf ); + } + assert( p->nFreeSize >= nSizeReal ); + pMemory = p->pFreeBuf; + p->pFreeBuf += nSizeReal; + p->nFreeSize -= nSizeReal; + return pMemory; +} + +/**Function************************************************************* + + Synopsis [Recycles the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Supp_ManRecycle( Supp_Man_t * p, char * pMemory, int nSize ) +{ + int Type; + Type = Supp_SizeType( nSize, p->nStepSize ); + Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); + Supp_OneSetNext( pMemory, Vec_PtrEntry(p->vFree, Type) ); + Vec_PtrWriteEntry( p->vFree, Type, pMemory ); +} + +/**Function************************************************************* + + Synopsis [Fetches the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Supp_One_t * Supp_ManFetchEntry( Supp_Man_t * p, int nWords, int nRefs ) +{ + Supp_One_t * pPart; + pPart = (Supp_One_t *)Supp_ManFetch( p, sizeof(Supp_One_t) + sizeof(int) * nWords ); + pPart->nRefs = nRefs; + pPart->nOuts = 0; + pPart->nOutsAlloc = nWords; + return pPart; +} + +/**Function************************************************************* + + Synopsis [Recycles the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Supp_ManRecycleEntry( Supp_Man_t * p, Supp_One_t * pEntry ) +{ + assert( pEntry->nOuts <= pEntry->nOutsAlloc ); + assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 ); + Supp_ManRecycle( p, (char *)pEntry, sizeof(Supp_One_t) + sizeof(int) * pEntry->nOutsAlloc ); +} + +/**Function************************************************************* + + Synopsis [Merges two entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Supp_One_t * Supp_ManMergeEntry( Supp_Man_t * pMan, Supp_One_t * p1, Supp_One_t * p2, int nRefs ) +{ + Supp_One_t * p = Supp_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs ); + int * pBeg1 = p1->pOuts; + int * pBeg2 = p2->pOuts; + int * pBeg = p->pOuts; + int * pEnd1 = p1->pOuts + p1->nOuts; + int * pEnd2 = p2->pOuts + p2->nOuts; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( *pBeg1 == *pBeg2 ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( *pBeg1 < *pBeg2 ) + *pBeg++ = *pBeg1++; + else + *pBeg++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pBeg++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pBeg++ = *pBeg2++; + p->nOuts = pBeg - p->pOuts; + assert( p->nOuts <= p->nOutsAlloc ); + assert( p->nOuts >= p1->nOuts ); + assert( p->nOuts >= p2->nOuts ); + return p; +} + +/**Function************************************************************* + + Synopsis [Tranfers the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Supp_ManTransferEntry( Supp_One_t * p ) +{ + Vec_Int_t * vSupp; + int i; + vSupp = Vec_IntAlloc( p->nOuts ); + for ( i = 0; i < p->nOuts; i++ ) + Vec_IntPush( vSupp, p->pOuts[i] ); + return vSupp; +} + +/**Function************************************************************* + + Synopsis [Computes supports of the POs in the multi-output AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsNatural( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pNext; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); + vNodes = Vec_PtrAlloc( Abc_NtkObjNum(pNtk) ); + Abc_NtkIncrementTravId( pNtk ); + // add the constant-1 nodes + pObj = Abc_AigConst1(pNtk); + Abc_NodeSetTravIdCurrent( pObj ); + Vec_PtrPush( vNodes, pObj ); + // add the CIs/nodes/COs in the topological order + Abc_NtkForEachNode( pNtk, pObj, i ) + { + // check the fanins and add CIs + Abc_ObjForEachFanin( pObj, pNext, k ) + if ( Abc_ObjIsCi(pNext) && !Abc_NodeIsTravIdCurrent(pNext) ) + { + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vNodes, pNext ); + } + // add the node + Vec_PtrPush( vNodes, pObj ); + // check the fanouts and add COs + Abc_ObjForEachFanout( pObj, pNext, k ) + if ( Abc_ObjIsCo(pNext) && !Abc_NodeIsTravIdCurrent(pNext) ) + { + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vNodes, pNext ); + } + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes supports of the POs.] + + Description [Returns the ptr-vector of int-vectors.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkComputeSupportsSmart( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupports; + Vec_Ptr_t * vNodes; + Vec_Int_t * vSupp; + Supp_Man_t * p; + Supp_One_t * pPart0, * pPart1; + Abc_Obj_t * pObj; + int i; + // set the number of PIs/POs + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pNext = (Abc_Obj_t *)i; + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->pNext = (Abc_Obj_t *)i; + // start the support computation manager + p = Supp_ManStart( 1 << 20, 1 << 6 ); + // consider objects in the topological order + vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkCleanCopy(pNtk); + // order the nodes so that the PIs and POs follow naturally + vNodes = Abc_NtkDfsNatural( pNtk ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( Abc_ObjIsNode(pObj) ) + { + pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy; + pPart1 = (Supp_One_t *)Abc_ObjFanin1(pObj)->pCopy; + pObj->pCopy = (Abc_Obj_t *)Supp_ManMergeEntry( p, pPart0, pPart1, Abc_ObjFanoutNum(pObj) ); + assert( pPart0->nRefs > 0 ); + if ( --pPart0->nRefs == 0 ) + Supp_ManRecycleEntry( p, pPart0 ); + assert( pPart1->nRefs > 0 ); + if ( --pPart1->nRefs == 0 ) + Supp_ManRecycleEntry( p, pPart1 ); + continue; + } + if ( Abc_ObjIsCo(pObj) ) + { + pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy; + // only save the CO if it is non-trivial + if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) + { + vSupp = Supp_ManTransferEntry(pPart0); + Vec_IntPush( vSupp, (int)pObj->pNext ); + Vec_PtrPush( vSupports, vSupp ); + } + assert( pPart0->nRefs > 0 ); + if ( --pPart0->nRefs == 0 ) + Supp_ManRecycleEntry( p, pPart0 ); + continue; + } + if ( Abc_ObjIsCi(pObj) ) + { + if ( Abc_ObjFanoutNum(pObj) ) + { + pPart0 = (Supp_One_t *)Supp_ManFetchEntry( p, 1, Abc_ObjFanoutNum(pObj) ); + pPart0->pOuts[ pPart0->nOuts++ ] = (int)pObj->pNext; + pObj->pCopy = (Abc_Obj_t *)pPart0; + } + continue; + } + if ( pObj == Abc_AigConst1(pNtk) ) + { + if ( Abc_ObjFanoutNum(pObj) ) + pObj->pCopy = (Abc_Obj_t *)Supp_ManFetchEntry( p, 0, Abc_ObjFanoutNum(pObj) ); + continue; + } + assert( 0 ); + } + Vec_PtrFree( vNodes ); +//printf( "Memory usage = %d Mb.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) ); + Supp_ManStop( p ); + // sort supports by size + Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); + // clear the number of PIs/POs + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pNext = NULL; + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->pNext = NULL; +/* + Vec_PtrForEachEntry( vSupports, vSupp, i ) + printf( "%d ", Vec_IntSize(vSupp) ); + printf( "\n" ); +*/ + return vSupports; +} + + +/**Function************************************************************* + + Synopsis [Computes supports of the POs using naive method.] + + Description [Returns the ptr-vector of int-vectors.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkComputeSupportsNaive( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupp, * vSupports; + Vec_Int_t * vSuppI; + Abc_Obj_t * pObj, * pTemp; + int i, k; + // set the PI numbers + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pNext = (void *)i; + // save the CI numbers + vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( !Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) + continue; + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + vSuppI = (Vec_Int_t *)vSupp; + Vec_PtrForEachEntry( vSupp, pTemp, k ) + Vec_IntWriteEntry( vSuppI, k, (int)pTemp->pNext ); + Vec_IntSort( vSuppI, 0 ); + // append the number of this output + Vec_IntPush( vSuppI, i ); + // save the support in the vector + Vec_PtrPush( vSupports, vSuppI ); + } + // clean the CI numbers + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pNext = NULL; + // sort supports by size + Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); +/* + Vec_PtrForEachEntry( vSupports, vSuppI, i ) + printf( "%d ", Vec_IntSize(vSuppI) ); + printf( "\n" ); +*/ + return vSupports; +} + +/**Function************************************************************* + + Synopsis [Start bitwise support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Abc_NtkSuppCharStart( Vec_Int_t * vOne, int nPis ) +{ + unsigned * pBuffer; + int i, Entry; + int nWords = Abc_BitWordNum(nPis); + pBuffer = ALLOC( unsigned, nWords ); + memset( pBuffer, 0, sizeof(unsigned) * nWords ); + Vec_IntForEachEntry( vOne, Entry, i ) + { + assert( Entry < nPis ); + Abc_InfoSetBit( pBuffer, Entry ); + } + return pBuffer; +} + +/**Function************************************************************* + + Synopsis [Add to bitwise support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis ) +{ + int i, Entry; + Vec_IntForEachEntry( vOne, Entry, i ) + { + assert( Entry < nPis ); + Abc_InfoSetBit( pBuffer, Entry ); + } +} + +/**Function************************************************************* + + Synopsis [Find the common variables using bitwise support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne ) +{ + int i, Entry, nCommon = 0; + Vec_IntForEachEntry( vOne, Entry, i ) + nCommon += Abc_InfoHasBit(pBuffer, Entry); + return nCommon; +} + +/**Function************************************************************* + + Synopsis [Find the best partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsChar, int nSuppSizeLimit, Vec_Int_t * vOne ) +{ +/* + Vec_Int_t * vPartSupp, * vPart; + double Attract, Repulse, Cost, CostBest; + int i, nCommon, iBest; + iBest = -1; + CostBest = 0.0; + Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i ) + { + vPart = Vec_PtrEntry( vPartsAll, i ); + if ( nPartSizeLimit > 0 && Vec_IntSize(vPart) >= nPartSizeLimit ) + continue; + nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne ); + if ( nCommon == 0 ) + continue; + if ( nCommon == Vec_IntSize(vOne) ) + return i; + Attract = 1.0 * nCommon / Vec_IntSize(vOne); + if ( Vec_IntSize(vPartSupp) < 100 ) + Repulse = 1.0; + else + Repulse = log10( Vec_IntSize(vPartSupp) / 10.0 ); + Cost = pow( Attract, pow(Repulse, 5.0) ); + if ( CostBest < Cost ) + { + CostBest = Cost; + iBest = i; + } + } + if ( CostBest < 0.6 ) + return -1; + return iBest; +*/ + + Vec_Int_t * vPartSupp;//, * vPart; + int Attract, Repulse, Value, ValueBest; + int i, nCommon, iBest; +// int nCommon2; + iBest = -1; + ValueBest = 0; + Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i ) + { + // skip partitions with too many outputs +// vPart = Vec_PtrEntry( vPartsAll, i ); +// if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit ) +// continue; + // find the number of common variables between this output and the partitions +// nCommon2 = Vec_IntTwoCountCommon( vPartSupp, vOne ); + nCommon = Abc_NtkSuppCharCommon( Vec_PtrEntry(vPartSuppsChar, i), vOne ); +// assert( nCommon2 == nCommon ); + // if no common variables, continue searching + if ( nCommon == 0 ) + continue; + // if all variables are common, the best partition if found + if ( nCommon == Vec_IntSize(vOne) ) + return i; + // skip partitions whose size exceeds the limit + if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit ) + continue; + // figure out might be the good partition for this one + Attract = 1000 * nCommon / Vec_IntSize(vOne); + if ( Vec_IntSize(vPartSupp) < 100 ) + Repulse = 1; + else + Repulse = 1+Extra_Base2Log(Vec_IntSize(vPartSupp)-100); + Value = Attract/Repulse; + if ( ValueBest < Value ) + { + ValueBest = Value; + iBest = i; + } + } + if ( ValueBest < 75 ) + return -1; + return iBest; +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll ) +{ + Vec_Int_t * vOne; + int i, nOutputs, Counter; + + Counter = 0; + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + { + nOutputs = Vec_IntSize(Vec_PtrEntry(vPartsAll, i)); + printf( "%d=(%d,%d) ", i, Vec_IntSize(vOne), nOutputs ); + Counter += nOutputs; + if ( i == Vec_PtrSize(vPartsAll) - 1 ) + break; + } +// assert( Counter == Abc_NtkCoNum(pNtk) ); + printf( "\nTotal = %d. Outputs = %d.\n", Counter, Abc_NtkCoNum(pNtk) ); +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit ) +{ + Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; + int i, iPart; + + if ( nSuppSizeLimit == 0 ) + nSuppSizeLimit = 200; + + // pack smaller partitions into larger blocks + iPart = 0; + vPart = vPartSupp = NULL; + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + { + if ( Vec_IntSize(vOne) < nSuppSizeLimit ) + { + if ( vPartSupp == NULL ) + { + assert( vPart == NULL ); + vPartSupp = Vec_IntDup(vOne); + vPart = Vec_PtrEntry(vPartsAll, i); + } + else + { + vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); + Vec_IntFree( vTemp ); + vPart = Vec_IntTwoMerge( vTemp = vPart, Vec_PtrEntry(vPartsAll, i) ); + Vec_IntFree( vTemp ); + Vec_IntFree( Vec_PtrEntry(vPartsAll, i) ); + } + if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit ) + continue; + } + else + vPart = Vec_PtrEntry(vPartsAll, i); + // add the partition + Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); + vPart = NULL; + if ( vPartSupp ) + { + Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) ); + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + vPartSupp = NULL; + } + iPart++; + } + // add the last one + if ( vPart ) + { + Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); + vPart = NULL; + + assert( vPartSupp != NULL ); + Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) ); + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + vPartSupp = NULL; + iPart++; + } + Vec_PtrShrink( vPartsAll, iPart ); + Vec_PtrShrink( vPartsAll, iPart ); +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [Returns the ptr-vector of int-vectors.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nSuppSizeLimit, int fVerbose ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vPartSuppsChar; + Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll; + Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; + int i, iPart, iOut, clk, clk2, timeFind = 0; + + // compute the supports for all outputs +clk = clock(); +// vSupps = Abc_NtkComputeSupportsNaive( pNtk ); + vSupps = Abc_NtkComputeSupportsSmart( pNtk ); +if ( fVerbose ) +{ +PRT( "Supps", clock() - clk ); +} + // start char-based support representation + vPartSuppsChar = Vec_PtrAlloc( 1000 ); + + // create partitions +clk = clock(); + vPartsAll = Vec_PtrAlloc( 256 ); + vPartSuppsAll = Vec_PtrAlloc( 256 ); + pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vSupps) ); + Vec_PtrForEachEntry( vSupps, vOne, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); +// if ( i % 1000 == 0 ) +// printf( "CIs = %6d. COs = %6d. Processed = %6d (out of %6d). Parts = %6d.\r", +// Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), i, Vec_PtrSize(vSupps), Vec_PtrSize(vPartsAll) ); + // get the output number + iOut = Vec_IntPop(vOne); + // find closely matching part +clk2 = clock(); + iPart = Abc_NtkPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsChar, nSuppSizeLimit, vOne ); +timeFind += clock() - clk2; + if ( iPart == -1 ) + { + // create new partition + vPart = Vec_IntAlloc( 32 ); + Vec_IntPush( vPart, iOut ); + // create new partition support + vPartSupp = Vec_IntDup( vOne ); + // add this partition and its support + Vec_PtrPush( vPartsAll, vPart ); + Vec_PtrPush( vPartSuppsAll, vPartSupp ); + + Vec_PtrPush( vPartSuppsChar, Abc_NtkSuppCharStart(vOne, Abc_NtkCiNum(pNtk)) ); + } + else + { + // add output to this partition + vPart = Vec_PtrEntry( vPartsAll, iPart ); + Vec_IntPush( vPart, iOut ); + // merge supports + vPartSupp = Vec_PtrEntry( vPartSuppsAll, iPart ); + vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); + Vec_IntFree( vTemp ); + // reinsert new support + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + + Abc_NtkSuppCharAdd( Vec_PtrEntry(vPartSuppsChar, iPart), vOne, Abc_NtkCiNum(pNtk) ); + } + } + Extra_ProgressBarStop( pProgress ); + + // stop char-based support representation + Vec_PtrForEachEntry( vPartSuppsChar, vTemp, i ) + free( vTemp ); + Vec_PtrFree( vPartSuppsChar ); + +//printf( "\n" ); +if ( fVerbose ) +{ +PRT( "Parts", clock() - clk ); +//PRT( "Find ", timeFind ); +} + +clk = clock(); + // remember number of supports + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + Vec_IntPush( vOne, i ); + // sort the supports in the decreasing order + Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 ); + // reproduce partitions + vPartsAll2 = Vec_PtrAlloc( 256 ); + Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) + Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) ); + Vec_PtrFree( vPartsAll ); + vPartsAll = vPartsAll2; + + // compact small partitions +// Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll ); + Abc_NtkPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit ); + +if ( fVerbose ) +{ +PRT( "Comps", clock() - clk ); +} + if ( fVerbose ) + printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) ); +// Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll ); + + // cleanup + Vec_VecFree( (Vec_Vec_t *)vSupps ); + Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll ); +/* + // converts from intergers to nodes + Vec_PtrForEachEntry( vPartsAll, vPart, iPart ) + { + vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) ); + Vec_IntForEachEntry( vPart, iOut, i ) + Vec_PtrPush( vPartPtr, Abc_NtkCo(pNtk, iOut) ); + Vec_IntFree( vPart ); + Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr ); + } +*/ + return vPartsAll; +} + +/**Function************************************************************* + + Synopsis [Perform the naive partitioning.] + + Description [Returns the ptr-vector of int-vectors.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize ) +{ + Vec_Ptr_t * vParts; + Abc_Obj_t * pObj; + int nParts, i; + nParts = (Abc_NtkCoNum(pNtk) / nPartSize) + ((Abc_NtkCoNum(pNtk) % nPartSize) > 0); + vParts = (Vec_Ptr_t *)Vec_VecStart( nParts ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_IntPush( Vec_PtrEntry(vParts, i / nPartSize), i ); + return vParts; +} + +/**Function************************************************************* + + Synopsis [Converts from intergers to pointers for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOutsPtr ) +{ + int Out, i; + Vec_PtrClear( vOutsPtr ); + Vec_IntForEachEntry( vOuts, Out, i ) + Vec_PtrPush( vOutsPtr, Abc_NtkCo(pNtk, Out) ); +} + +/**Function************************************************************* + + Synopsis [Returns representative of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkPartStitchFindRepr_rec( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pRepr; + pRepr = Vec_PtrEntry( vEquiv, pObj->Id ); + if ( pRepr == NULL || pRepr == pObj ) + return pObj; + return Abc_NtkPartStitchFindRepr_rec( vEquiv, pRepr ); +} + +/**Function************************************************************* + + Synopsis [Returns the representative of the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Abc_Obj_t * Abc_NtkPartStitchCopy0( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFan = Abc_ObjFanin0( pObj ); + Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan ); + return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ Abc_ObjFaninC1(pObj) ); +} +static inline Abc_Obj_t * Abc_NtkPartStitchCopy1( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFan = Abc_ObjFanin1( pObj ); + Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan ); + return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ Abc_ObjFaninC1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Hop_Obj_t * Hop_ObjChild0Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin0(pObj)->pNext, Abc_ObjFaninC0(pObj) ); } +static inline Hop_Obj_t * Hop_ObjChild1Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin1(pObj)->pNext, Abc_ObjFaninC1(pObj) ); } + + +/**Function************************************************************* + + Synopsis [Stitches together several networks with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk ) +{ + Hop_Man_t * pMan; + Abc_Obj_t * pObj; + int i; + // start the HOP package + pMan = Hop_ManStart(); + pMan->vObjs = Vec_PtrAlloc( Abc_NtkObjNumMax(pNtk) + 1 ); + Vec_PtrPush( pMan->vObjs, Hop_ManConst1(pMan) ); + // map constant node and PIs + Abc_AigConst1(pNtk)->pNext = (Abc_Obj_t *)Hop_ManConst1(pMan); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pNext = (Abc_Obj_t *)Hop_ObjCreatePi(pMan); + // map the internal nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + { + pObj->pNext = (Abc_Obj_t *)Hop_And( pMan, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) ); + assert( !Abc_ObjIsComplement(pObj->pNext) ); + } + // set the choice nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + { + if ( pObj->pCopy ) + ((Hop_Obj_t *)pObj->pNext)->pData = pObj->pCopy->pNext; + } + // transfer the POs + Abc_NtkForEachCo( pNtk, pObj, i ) + Hop_ObjCreatePo( pMan, Hop_ObjChild0Next(pObj) ); + // check the new manager + if ( !Hop_ManCheck(pMan) ) + printf( "Abc_NtkPartStartHop: HOP manager check has failed.\n" ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Stitches together several networks with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts ) +{ + extern Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ); + + Hop_Man_t * pMan; + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew, * pNtkTemp; + Abc_Obj_t * pObj, * pFanin; + int i, k, iNodeId; + + // start a new network similar to the original one + assert( Abc_NtkIsStrash(pNtk) ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + + // annotate parts to point to the new network + Vec_PtrForEachEntry( vParts, pNtkTemp, i ) + { + assert( Abc_NtkIsStrash(pNtkTemp) ); + Abc_NtkCleanCopy( pNtkTemp ); + + // map the CI nodes + Abc_AigConst1(pNtkTemp)->pCopy = Abc_AigConst1(pNtkNew); + Abc_NtkForEachCi( pNtkTemp, pObj, k ) + { + iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); + if ( iNodeId == -1 ) + { + printf( "Cannot find CI node %s in the original network.\n", Abc_ObjName(pObj) ); + return NULL; + } + pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); + } + + // add the internal nodes while saving representatives + vNodes = Abc_AigDfs( pNtkTemp, 1, 0 ); + Vec_PtrForEachEntry( vNodes, pObj, k ) + { + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + assert( !Abc_ObjIsComplement(pObj->pCopy) ); + if ( Abc_AigNodeIsChoice(pObj) ) + for ( pFanin = pObj->pData; pFanin; pFanin = pFanin->pData ) + pFanin->pCopy->pCopy = pObj->pCopy; + } + Vec_PtrFree( vNodes ); + + // map the CO nodes + Abc_NtkForEachCo( pNtkTemp, pObj, k ) + { + iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI ); + if ( iNodeId == -1 ) + { + printf( "Cannot find CO node %s in the original network.\n", Abc_ObjName(pObj) ); + return NULL; + } + pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + } + } + + // connect the remaining POs +/* + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkCi( pNtkNew, i ); + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkCo( pNtkNew, i ); +*/ + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( Abc_ObjFaninNum(pObj->pCopy) == 0 ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + } + + // transform into the HOP manager + pMan = Abc_NtkPartStartHop( pNtkNew ); + pNtkNew = Abc_NtkHopRemoveLoops( pNtkTemp = pNtkNew, pMan ); + Abc_NtkDelete( pNtkTemp ); + + // check correctness of the new network + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkPartStitchChoices: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Stitches together several networks with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams ) +{ + extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); + extern void * Abc_FrameGetGlobalFrame(); + + Vec_Ptr_t * vParts, * vFraigs, * vOnePtr; + Vec_Int_t * vOne; + Abc_Ntk_t * pNtk, * pNtk2, * pNtkAig, * pNtkFraig; + int i, k; + + // perform partitioning + pNtk = Vec_PtrEntry( vStore, 0 ); + assert( Abc_NtkIsStrash(pNtk) ); +// vParts = Abc_NtkPartitionNaive( pNtk, 20 ); + vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 ); + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); + + // fraig each partition + vOnePtr = Vec_PtrAlloc( 1000 ); + vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) ); + Vec_PtrForEachEntry( vParts, vOne, i ) + { + // start the partition + Abc_NtkConvertCos( pNtk, vOne, vOnePtr ); + pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 ); + // add nodes to the partition + Vec_PtrForEachEntryStart( vStore, pNtk2, k, 1 ) + { + Abc_NtkConvertCos( pNtk2, vOne, vOnePtr ); + Abc_NtkAppendToCone( pNtkAig, pNtk2, vOnePtr ); + } + printf( "Fraiging part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", + i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pNtkAig), Abc_NtkPoNum(pNtkAig), + Abc_NtkNodeNum(pNtkAig), Abc_AigLevel(pNtkAig) ); + // fraig the partition + pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 1, 0 ); + Vec_PtrPush( vFraigs, pNtkFraig ); + Abc_NtkDelete( pNtkAig ); + } + printf( " \r" ); + Vec_VecFree( (Vec_Vec_t *)vParts ); + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); + + // derive the final network + pNtkFraig = Abc_NtkPartStitchChoices( pNtk, vFraigs ); + Vec_PtrForEachEntry( vFraigs, pNtkAig, i ) + Abc_NtkDelete( pNtkAig ); + Vec_PtrFree( vFraigs ); + Vec_PtrFree( vOnePtr ); + return pNtkFraig; +} + +/**Function************************************************************* + + Synopsis [Stitches together several networks with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams ) +{ + extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); + extern void * Abc_FrameGetGlobalFrame(); + + Vec_Ptr_t * vParts, * vFraigs, * vOnePtr; + Vec_Int_t * vOne; + Abc_Ntk_t * pNtkAig, * pNtkFraig; + int i; + int clk = clock(); + + // perform partitioning + assert( Abc_NtkIsStrash(pNtk) ); +// vParts = Abc_NtkPartitionNaive( pNtk, 20 ); + vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 ); + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); + + // fraig each partition + vOnePtr = Vec_PtrAlloc( 1000 ); + vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) ); + Vec_PtrForEachEntry( vParts, vOne, i ) + { + Abc_NtkConvertCos( pNtk, vOne, vOnePtr ); + pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 ); + pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 0, 0 ); + Vec_PtrPush( vFraigs, pNtkFraig ); + Abc_NtkDelete( pNtkAig ); + + printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) ); + } + Vec_VecFree( (Vec_Vec_t *)vParts ); + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); + + // derive the final network + Vec_PtrForEachEntry( vFraigs, pNtkAig, i ) + Abc_NtkDelete( pNtkAig ); + Vec_PtrFree( vFraigs ); + Vec_PtrFree( vOnePtr ); + PRT( "Partitioned fraiging time", clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcPlace.c b/abc70930/src/base/abci/abcPlace.c new file mode 100644 index 00000000..87c99e99 --- /dev/null +++ b/abc70930/src/base/abci/abcPlace.c @@ -0,0 +1,255 @@ +/**CFile**************************************************************** + + FileName [abcPlace.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface with a placer.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcPlace.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +// placement includes +#include "place_base.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +AbstractCell *abstractCells = NULL; +ConcreteCell *cells = NULL; +ConcreteNet *nets = NULL; +int nAllocSize = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a new cell.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_PlaceCreateCell( Abc_Obj_t * pObj, int fAnd ) +{ + assert( cells[pObj->Id].m_id == 0 ); + + cells[pObj->Id].m_id = pObj->Id; + cells[pObj->Id].m_label = ""; + cells[pObj->Id].m_parent = &(abstractCells[fAnd]); + cells[pObj->Id].m_fixed = 0; + addConcreteCell(&(cells[pObj->Id])); +} + +/**Function************************************************************* + + Synopsis [Updates the net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_PlaceUpdateNet( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int k; + // free the old array of net terminals + if ( nets[pObj->Id].m_terms ) + free( nets[pObj->Id].m_terms ); + // fill in the net with the new information + nets[pObj->Id].m_id = pObj->Id; + nets[pObj->Id].m_weight = 1.0; + nets[pObj->Id].m_numTerms = Abc_ObjFanoutNum(pObj); //fanout + nets[pObj->Id].m_terms = ALLOC(ConcreteCell*, Abc_ObjFanoutNum(pObj)); + Abc_ObjForEachFanout( pObj, pFanout, k ) + nets[pObj->Id].m_terms[k] = &(cells[pFanout->Id]); + addConcreteNet(&(nets[pObj->Id])); +} + +/**Function************************************************************* + + Synopsis [Returns the placement cost of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pObj; +// double x, y; + int i; + Vec_PtrForEachEntry( vFanins, pObj, i ) + { +// pObj->Id + } + return 0.0; +} + +/**Function************************************************************* + + Synopsis [Updates placement after one step of rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k; + Vec_Ptr_t * vCells, * vNets; + + // start the arrays of new cells and nets + vCells = Vec_PtrAlloc( 16 ); + vNets = Vec_PtrAlloc( 32 ); + + // go through the new nodes + Vec_PtrForEachEntry( vAddedCells, pObj, i ) + { + assert( !Abc_ObjIsComplement(pObj) ); + Abc_PlaceCreateCell( pObj, 1 ); + Abc_PlaceUpdateNet( pObj ); + + // add the new cell and its fanin nets to temporary storage + Vec_PtrPush( vCells, &(cells[pObj->Id]) ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Vec_PtrPushUnique( vNets, &(nets[pFanin->Id]) ); + } + + // go through the modified nets + Vec_PtrForEachEntry( vUpdatedNets, pObj, i ) + { + assert( !Abc_ObjIsComplement(pObj) ); + if ( Abc_ObjType(pObj) == ABC_OBJ_NONE ) // dead node + continue; + Abc_PlaceUpdateNet( pObj ); + } + + // update the placement +// fastPlace( Vec_PtrSize(vCells), (ConcreteCell **)Vec_PtrArray(vCells), +// Vec_PtrSize(vNets), (ConcreteNet **)Vec_PtrArray(vNets) ); + + // clean up + Vec_PtrFree( vCells ); + Vec_PtrFree( vNets ); +} + +/**Function************************************************************* + + Synopsis [This procedure is called before the writing start.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_PlaceBegin( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + // allocate and clean internal storage + nAllocSize = 5 * Abc_NtkObjNumMax(pNtk); + cells = REALLOC(ConcreteCell, cells, nAllocSize); + nets = REALLOC(ConcreteNet, nets, nAllocSize); + memset( cells, 0, sizeof(ConcreteCell) * nAllocSize ); + memset( nets, 0, sizeof(ConcreteNet) * nAllocSize ); + + // create AbstractCells + // 1: pad + // 2: and + if (!abstractCells) + abstractCells = ALLOC(AbstractCell,2); + + abstractCells[0].m_height = 1.0; + abstractCells[0].m_width = 1.0; + abstractCells[0].m_label = "pio"; + abstractCells[0].m_pad = 1; + + abstractCells[1].m_height = 1.0; + abstractCells[1].m_width = 1.0; + abstractCells[1].m_label = "and"; + abstractCells[1].m_pad = 0; + + // input pads + Abc_NtkForEachCi( pNtk, pObj, i ) + Abc_PlaceCreateCell( pObj, 0 ); + + // ouput pads + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_PlaceCreateCell( pObj, 0 ); + + // AND nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + Abc_PlaceCreateCell( pObj, 1 ); + + // all nets + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( !Abc_ObjIsCi(pObj) && !Abc_ObjIsNode(pObj) ) + continue; + Abc_PlaceUpdateNet( pObj ); + } + + globalPreplace((float)0.8); + globalPlace(); +} + +/**Function************************************************************* + + Synopsis [This procedure is called after the writing completes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_PlaceEnd( Abc_Ntk_t * pNtk ) +{ + int i; + + + // clean up + for ( i = 0; i < nAllocSize; i++ ) + FREE( nets[i].m_terms ); + FREE( abstractCells ); + FREE( cells ); + FREE( nets ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcPrint.c b/abc70930/src/base/abci/abcPrint.c new file mode 100644 index 00000000..bfb380f3 --- /dev/null +++ b/abc70930/src/base/abci/abcPrint.c @@ -0,0 +1,953 @@ +/**CFile**************************************************************** + + FileName [abcPrint.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Printing statistics.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcPrint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" +#include "main.h" +#include "mio.h" +//#include "seq.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//extern int s_TotalNodes = 0; +//extern int s_TotalChanges = 0; + +int s_MappingTime = 0; +int s_MappingMem = 0; +int s_ResubTime = 0; +int s_ResynTime = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Print the vital stats of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) +{ + int Num; + +// if ( Abc_NtkIsStrash(pNtk) ) +// Abc_AigCountNext( pNtk->pManFunc ); + + fprintf( pFile, "%-13s:", pNtk->pName ); + if ( Abc_NtkAssertNum(pNtk) ) + fprintf( pFile, " i/o/a = %4d/%4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkAssertNum(pNtk) ); + else + fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); + fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) ); + if ( Abc_NtkIsNetlist(pNtk) ) + { + fprintf( pFile, " net = %5d", Abc_NtkNetNum(pNtk) ); + fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); + fprintf( pFile, " wbox = %3d", Abc_NtkWhiteboxNum(pNtk) ); + fprintf( pFile, " bbox = %3d", Abc_NtkBlackboxNum(pNtk) ); + } + else if ( Abc_NtkIsStrash(pNtk) ) + { + fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) ); + if ( Num = Abc_NtkGetChoiceNum(pNtk) ) + fprintf( pFile, " (choice = %d)", Num ); + if ( Num = Abc_NtkGetExorNum(pNtk) ) + fprintf( pFile, " (exor = %d)", Num ); +// if ( Num2 = Abc_NtkGetMuxNum(pNtk) ) +// fprintf( pFile, " (mux = %d)", Num2-Num ); +// if ( Num2 ) +// fprintf( pFile, " (other = %d)", Abc_NtkNodeNum(pNtk)-3*Num2 ); + } + else + { + fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); + fprintf( pFile, " net = %5d", Abc_NtkGetTotalFanins(pNtk) ); + } + + if ( Abc_NtkIsStrash(pNtk) || Abc_NtkIsNetlist(pNtk) ) + { + } + else if ( Abc_NtkHasSop(pNtk) ) + { + + fprintf( pFile, " cube = %5d", Abc_NtkGetCubeNum(pNtk) ); +// fprintf( pFile, " lit(sop) = %5d", Abc_NtkGetLitNum(pNtk) ); + if ( fFactored ) + fprintf( pFile, " lit(fac) = %5d", Abc_NtkGetLitFactNum(pNtk) ); + } + else if ( Abc_NtkHasAig(pNtk) ) + fprintf( pFile, " aig = %5d", Abc_NtkGetAigNodeNum(pNtk) ); + else if ( Abc_NtkHasBdd(pNtk) ) + fprintf( pFile, " bdd = %5d", Abc_NtkGetBddNodeNum(pNtk) ); + else if ( Abc_NtkHasMapping(pNtk) ) + { + fprintf( pFile, " area = %5.2f", Abc_NtkGetMappedArea(pNtk) ); + fprintf( pFile, " delay = %5.2f", Abc_NtkDelayTrace(pNtk) ); + } + else if ( !Abc_NtkHasBlackbox(pNtk) ) + { + assert( 0 ); + } + + if ( Abc_NtkIsStrash(pNtk) ) + fprintf( pFile, " lev = %3d", Abc_AigLevel(pNtk) ); + else + fprintf( pFile, " lev = %3d", Abc_NtkLevel(pNtk) ); + + fprintf( pFile, "\n" ); + +// Abc_NtkCrossCut( pNtk ); + + // print the statistic into a file +/* + { + FILE * pTable; + pTable = fopen( "ibm/seq_stats.txt", "a+" ); +// fprintf( pTable, "%s ", pNtk->pName ); +// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + +/* + // print the statistic into a file + { + FILE * pTable; + pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%s ", pNtk->pSpec ); + fprintf( pTable, "%.0f ", Abc_NtkGetMappedArea(pNtk) ); + fprintf( pTable, "%.2f ", Abc_NtkDelayTrace(pNtk) ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + +/* + // print the statistic into a file + { + FILE * pTable; + pTable = fopen( "x/stats_new.txt", "a+" ); + fprintf( pTable, "%s ", pNtk->pName ); +// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkGetTotalFanins(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); +// fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) ); + fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) ); +// fprintf( pTable, "%.2f", (float)(s_ResynTime)/(float)(CLOCKS_PER_SEC) ); + fprintf( pTable, "\n" ); + fclose( pTable ); + + s_ResynTime = 0; + } +*/ + +/* + // print the statistic into a file + { + static int Counter = 0; + extern int timeRetime; + FILE * pTable; + Counter++; + pTable = fopen( "a/ret__stats.txt", "a+" ); + fprintf( pTable, "%s ", pNtk->pName ); + fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); + fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) ); + if ( Counter % 4 == 0 ) + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + +/* + // print the statistic into a file + { + static int Counter = 0; + extern int timeRetime; + FILE * pTable; + Counter++; + pTable = fopen( "d/stats.txt", "a+" ); + fprintf( pTable, "%s ", pNtk->pName ); +// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); +// fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); + fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); + fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + +/* + s_TotalNodes += Abc_NtkNodeNum(pNtk); + printf( "Total nodes = %6d %6.2f Mb Changes = %6d.\n", + s_TotalNodes, s_TotalNodes * 20.0 / (1<<20), s_TotalChanges ); +*/ + +// if ( Abc_NtkHasSop(pNtk) ) +// printf( "The total number of cube pairs = %d.\n", Abc_NtkGetCubePairNum(pNtk) ); +} + +/**Function************************************************************* + + Synopsis [Prints PIs/POs and LIs/LOs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + fprintf( pFile, "Primary inputs (%d): ", Abc_NtkPiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, " %s", Abc_ObjName(pObj) ); +// fprintf( pFile, " %s(%d)", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) ); + fprintf( pFile, "\n" ); + + fprintf( pFile, "Primary outputs (%d):", Abc_NtkPoNum(pNtk) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + fprintf( pFile, " %s", Abc_ObjName(pObj) ); + fprintf( pFile, "\n" ); + + fprintf( pFile, "Latches (%d): ", Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + fprintf( pFile, " %s(%s=%s)", Abc_ObjName(pObj), + Abc_ObjName(Abc_ObjFanout0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints statistics about latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch, * pFanin; + int i, Counter0, Counter1, Counter2; + int InitNums[4], Init; + + assert( !Abc_NtkIsNetlist(pNtk) ); + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + fprintf( pFile, "The network is combinational.\n" ); + return; + } + + for ( i = 0; i < 4; i++ ) + InitNums[i] = 0; + Counter0 = Counter1 = Counter2 = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + Init = Abc_LatchInit( pLatch ); + assert( Init < 4 ); + InitNums[Init]++; + + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + if ( Abc_NtkIsLogic(pNtk) ) + { + if ( !Abc_NodeIsConst(pFanin) ) + continue; + } + else if ( Abc_NtkIsStrash(pNtk) ) + { + if ( !Abc_AigNodeIsConst(pFanin) ) + continue; + } + else + assert( 0 ); + + // the latch input is a constant node + Counter0++; + if ( Abc_LatchIsInitDc(pLatch) ) + { + Counter1++; + continue; + } + // count the number of cases when the constant is equal to the initial value + if ( Abc_NtkIsStrash(pNtk) ) + { + if ( Abc_LatchIsInit1(pLatch) == !Abc_ObjFaninC0(pLatch) ) + Counter2++; + } + else + { + if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(Abc_ObjFanin0(Abc_ObjFanin0(pLatch))) ) + Counter2++; + } + } + fprintf( pFile, "%-15s: ", pNtk->pName ); + fprintf( pFile, "Latch = %6d. No = %4d. Zero = %4d. One = %4d. DC = %4d.\n", + Abc_NtkLatchNum(pNtk), InitNums[0], InitNums[1], InitNums[2], InitNums[3] ); + fprintf( pFile, "Const fanin = %3d. DC init = %3d. Matching init = %3d. ", Counter0, Counter1, Counter2 ); + fprintf( pFile, "Self-feed latches = %2d.\n", -1 ); //Abc_NtkCountSelfFeedLatches(pNtk) ); +} + +/**Function************************************************************* + + Synopsis [Prints the distribution of fanins/fanouts in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, k, nFanins, nFanouts; + Vec_Int_t * vFanins, * vFanouts; + int nOldSize, nNewSize; + + vFanins = Vec_IntAlloc( 0 ); + vFanouts = Vec_IntAlloc( 0 ); + Vec_IntFill( vFanins, 100, 0 ); + Vec_IntFill( vFanouts, 100, 0 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + nFanins = Abc_ObjFaninNum(pNode); + if ( Abc_NtkIsNetlist(pNtk) ) + nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) ); + else + nFanouts = Abc_ObjFanoutNum(pNode); +// nFanouts = Abc_NodeMffcSize(pNode); + if ( nFanins > vFanins->nSize || nFanouts > vFanouts->nSize ) + { + nOldSize = vFanins->nSize; + nNewSize = ABC_MAX(nFanins, nFanouts) + 10; + Vec_IntGrow( vFanins, nNewSize ); + Vec_IntGrow( vFanouts, nNewSize ); + for ( k = nOldSize; k < nNewSize; k++ ) + { + Vec_IntPush( vFanins, 0 ); + Vec_IntPush( vFanouts, 0 ); + } + } + vFanins->pArray[nFanins]++; + vFanouts->pArray[nFanouts]++; + } + fprintf( pFile, "The distribution of fanins and fanouts in the network:\n" ); + fprintf( pFile, " Number Nodes with fanin Nodes with fanout\n" ); + for ( k = 0; k < vFanins->nSize; k++ ) + { + if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 ) + continue; + fprintf( pFile, "%5d : ", k ); + if ( vFanins->pArray[k] == 0 ) + fprintf( pFile, " " ); + else + fprintf( pFile, "%12d ", vFanins->pArray[k] ); + fprintf( pFile, " " ); + if ( vFanouts->pArray[k] == 0 ) + fprintf( pFile, " " ); + else + fprintf( pFile, "%12d ", vFanouts->pArray[k] ); + fprintf( pFile, "\n" ); + } + Vec_IntFree( vFanins ); + Vec_IntFree( vFanouts ); +} + +/**Function************************************************************* + + Synopsis [Prints the fanins/fanouts of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode2; + int i; + if ( Abc_ObjIsPo(pNode) ) + pNode = Abc_ObjFanin0(pNode); + + fprintf( pFile, "Node %s", Abc_ObjName(pNode) ); + fprintf( pFile, "\n" ); + + fprintf( pFile, "Fanins (%d): ", Abc_ObjFaninNum(pNode) ); + Abc_ObjForEachFanin( pNode, pNode2, i ) + fprintf( pFile, " %s", Abc_ObjName(pNode2) ); + fprintf( pFile, "\n" ); + + fprintf( pFile, "Fanouts (%d): ", Abc_ObjFaninNum(pNode) ); + Abc_ObjForEachFanout( pNode, pNode2, i ) + fprintf( pFile, " %s", Abc_ObjName(pNode2) ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the MFFCs of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + extern void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode ); + Abc_NtkForEachNode( pNtk, pNode, i ) + Abc_NodeMffsConeSuppPrint( pNode ); +} + +/**Function************************************************************* + + Synopsis [Prints the factored form of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsSopLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + Abc_NodePrintFactor( pFile, pNode, fUseRealNames ); +} + +/**Function************************************************************* + + Synopsis [Prints the factored form of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ) +{ + Dec_Graph_t * pGraph; + Vec_Ptr_t * vNamesIn; + if ( Abc_ObjIsCo(pNode) ) + pNode = Abc_ObjFanin0(pNode); + if ( Abc_ObjIsPi(pNode) ) + { + fprintf( pFile, "Skipping the PI node.\n" ); + return; + } + if ( Abc_ObjIsLatch(pNode) ) + { + fprintf( pFile, "Skipping the latch.\n" ); + return; + } + assert( Abc_ObjIsNode(pNode) ); + pGraph = Dec_Factor( pNode->pData ); + if ( fUseRealNames ) + { + vNamesIn = Abc_NodeGetFaninNames(pNode); + Dec_GraphPrint( stdout, pGraph, (char **)vNamesIn->pArray, Abc_ObjName(pNode) ); + Abc_NodeFreeNames( vNamesIn ); + } + else + Dec_GraphPrint( stdout, pGraph, (char **)NULL, Abc_ObjName(pNode) ); + Dec_GraphFree( pGraph ); +} + + +/**Function************************************************************* + + Synopsis [Prints the level stats of the PO node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes ) +{ + Abc_Obj_t * pNode; + int i, k, Length; + + if ( fListNodes ) + { + int nLevels; + nLevels = Abc_NtkLevel(pNtk); + printf( "Nodes by level:\n" ); + for ( i = 0; i <= nLevels; i++ ) + { + printf( "%2d : ", i ); + Abc_NtkForEachNode( pNtk, pNode, k ) + if ( (int)pNode->Level == i ) + printf( " %s", Abc_ObjName(pNode) ); + printf( "\n" ); + } + return; + } + + // print the delay profile + if ( fProfile && Abc_NtkHasMapping(pNtk) ) + { + int nIntervals = 12; + float DelayMax, DelayCur, DelayDelta; + int * pLevelCounts; + int DelayInt, nOutsSum, nOutsTotal; + + // get the max delay and delta + DelayMax = Abc_NtkDelayTrace( pNtk ); + DelayDelta = DelayMax/nIntervals; + // collect outputs by delay + pLevelCounts = ALLOC( int, nIntervals ); + memset( pLevelCounts, 0, sizeof(int) * nIntervals ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + DelayCur = Abc_NodeReadArrival( Abc_ObjFanin0(pNode) )->Worst; + DelayInt = (int)(DelayCur / DelayDelta); + if ( DelayInt >= nIntervals ) + DelayInt = nIntervals - 1; + pLevelCounts[DelayInt]++; + } + + nOutsSum = 0; + nOutsTotal = Abc_NtkCoNum(pNtk); + for ( i = 0; i < nIntervals; i++ ) + { + nOutsSum += pLevelCounts[i]; + printf( "[%8.2f - %8.2f] : COs = %4d. %5.1f %%\n", + DelayDelta * i, DelayDelta * (i+1), pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal ); + } + free( pLevelCounts ); + return; + } + else if ( fProfile ) + { + int LevelMax, * pLevelCounts; + int nOutsSum, nOutsTotal; + + if ( !Abc_NtkIsStrash(pNtk) ) + Abc_NtkLevel(pNtk); + + LevelMax = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + if ( LevelMax < (int)Abc_ObjFanin0(pNode)->Level ) + LevelMax = Abc_ObjFanin0(pNode)->Level; + pLevelCounts = ALLOC( int, LevelMax + 1 ); + memset( pLevelCounts, 0, sizeof(int) * (LevelMax + 1) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + pLevelCounts[Abc_ObjFanin0(pNode)->Level]++; + + nOutsSum = 0; + nOutsTotal = Abc_NtkCoNum(pNtk); + for ( i = 0; i <= LevelMax; i++ ) + if ( pLevelCounts[i] ) + { + nOutsSum += pLevelCounts[i]; + printf( "Level = %4d. COs = %4d. %5.1f %%\n", i, pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal ); + } + free( pLevelCounts ); + return; + } + assert( Abc_NtkIsStrash(pNtk) ); + + // find the longest name + Length = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + if ( Length < (int)strlen(Abc_ObjName(pNode)) ) + Length = strlen(Abc_ObjName(pNode)); + if ( Length < 5 ) + Length = 5; + // print stats for each output + Abc_NtkForEachCo( pNtk, pNode, i ) + { + fprintf( pFile, "CO %4d : %*s ", i, Length, Abc_ObjName(pNode) ); + Abc_NodePrintLevel( pFile, pNode ); + } +} + +/**Function************************************************************* + + Synopsis [Prints the factored form of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pDriver; + Vec_Ptr_t * vNodes; + + pDriver = Abc_ObjIsCo(pNode)? Abc_ObjFanin0(pNode) : pNode; + if ( Abc_ObjIsPi(pDriver) ) + { + fprintf( pFile, "Primary input.\n" ); + return; + } + if ( Abc_ObjIsLatch(pDriver) ) + { + fprintf( pFile, "Latch.\n" ); + return; + } + if ( Abc_NodeIsConst(pDriver) ) + { + fprintf( pFile, "Constant %d.\n", !Abc_ObjFaninC0(pNode) ); + return; + } + // print the level + fprintf( pFile, "Level = %3d. ", pDriver->Level ); + // print the size of MFFC + fprintf( pFile, "Mffc = %5d. ", Abc_NodeMffcSize(pDriver) ); + // print the size of the shole cone + vNodes = Abc_NtkDfsNodes( pNode->pNtk, &pDriver, 1 ); + fprintf( pFile, "Cone = %5d. ", Vec_PtrSize(vNodes) ); + Vec_PtrFree( vNodes ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the factored form of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames ) +{ + Vec_Ptr_t * vNamesIn; + if ( fUseRealNames ) + { + vNamesIn = Abc_NodeGetFaninNames(pNode); + Extra_PrintKMap( stdout, pNode->pNtk->pManFunc, pNode->pData, Cudd_Not(pNode->pData), + Abc_ObjFaninNum(pNode), NULL, 0, (char **)vNamesIn->pArray ); + Abc_NodeFreeNames( vNamesIn ); + } + else + Extra_PrintKMap( stdout, pNode->pNtk->pManFunc, pNode->pData, Cudd_Not(pNode->pData), + Abc_ObjFaninNum(pNode), NULL, 0, NULL ); + +} + +/**Function************************************************************* + + Synopsis [Prints statistics about gates used in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary ) +{ + Abc_Obj_t * pObj; + int fHasBdds, i; + int CountConst, CountBuf, CountInv, CountAnd, CountOr, CountOther, CounterTotal; + char * pSop; + + if ( fUseLibrary && Abc_NtkHasMapping(pNtk) ) + { + stmm_table * tTable; + stmm_generator * gen; + char * pName; + int * pCounter, Counter; + double Area, AreaTotal; + + // count the gates by name + CounterTotal = 0; + tTable = stmm_init_table(strcmp, stmm_strhash); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) continue; + if ( !stmm_find_or_add( tTable, Mio_GateReadName(pObj->pData), (char ***)&pCounter ) ) + *pCounter = 0; + (*pCounter)++; + CounterTotal++; + } + // print the gates + AreaTotal = Abc_NtkGetMappedArea(pNtk); + stmm_foreach_item( tTable, gen, (char **)&pName, (char **)&Counter ) + { + Area = Counter * Mio_GateReadArea(Mio_LibraryReadGateByName(pNtk->pManFunc,pName)); + printf( "%-12s = %8d %10.2f %6.2f %%\n", pName, Counter, Area, 100.0 * Area / AreaTotal ); + } + printf( "%-12s = %8d %10.2f %6.2f %%\n", "TOTAL", CounterTotal, AreaTotal, 100.0 ); + stmm_free_table( tTable ); + return; + } + + if ( Abc_NtkIsAigLogic(pNtk) ) + return; + + // transform logic functions from BDD to SOP + if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Abc_NtkPrintGates(): Converting to SOPs has failed.\n" ); + return; + } + } + + // get hold of the SOP of the node + CountConst = CountBuf = CountInv = CountAnd = CountOr = CountOther = CounterTotal = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) continue; + if ( Abc_NtkHasMapping(pNtk) ) + pSop = Mio_GateReadSop(pObj->pData); + else + pSop = pObj->pData; + // collect the stats + if ( Abc_SopIsConst0(pSop) || Abc_SopIsConst1(pSop) ) + CountConst++; + else if ( Abc_SopIsBuf(pSop) ) + CountBuf++; + else if ( Abc_SopIsInv(pSop) ) + CountInv++; + else if ( !Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop) || Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop) ) + CountAnd++; + else if ( Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop) || !Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop) ) + CountOr++; + else + CountOther++; + CounterTotal++; + } + printf( "Const = %8d %6.2f %%\n", CountConst , 100.0 * CountConst / CounterTotal ); + printf( "Buffer = %8d %6.2f %%\n", CountBuf , 100.0 * CountBuf / CounterTotal ); + printf( "Inverter = %8d %6.2f %%\n", CountInv , 100.0 * CountInv / CounterTotal ); + printf( "And = %8d %6.2f %%\n", CountAnd , 100.0 * CountAnd / CounterTotal ); + printf( "Or = %8d %6.2f %%\n", CountOr , 100.0 * CountOr / CounterTotal ); + printf( "Other = %8d %6.2f %%\n", CountOther , 100.0 * CountOther / CounterTotal ); + printf( "TOTAL = %8d %6.2f %%\n", CounterTotal, 100.0 * CounterTotal / CounterTotal ); + + // convert the network back into BDDs if this is how it was + if ( fHasBdds ) + Abc_NtkSopToBdd(pNtk); +} + +/**Function************************************************************* + + Synopsis [Prints statistics about gates used in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes1, * vNodes2; + Abc_Obj_t * pObj1, * pObj2, * pNode1, * pNode2; + int i, k, m, n, Counter; + + // print the template + printf( "Statistics about sharing of logic nodes among the CO pairs.\n" ); + printf( "(CO1,CO2)=NumShared : " ); + // go though the CO pairs + Abc_NtkForEachCo( pNtk, pObj1, i ) + { + vNodes1 = Abc_NtkDfsNodes( pNtk, &pObj1, 1 ); + // mark the nodes + Vec_PtrForEachEntry( vNodes1, pNode1, m ) + pNode1->fMarkA = 1; + // go through the second COs + Abc_NtkForEachCo( pNtk, pObj2, k ) + { + if ( i >= k ) + continue; + vNodes2 = Abc_NtkDfsNodes( pNtk, &pObj2, 1 ); + // count the number of marked + Counter = 0; + Vec_PtrForEachEntry( vNodes2, pNode2, n ) + Counter += pNode2->fMarkA; + // print + printf( "(%d,%d)=%d ", i, k, Counter ); + Vec_PtrFree( vNodes2 ); + } + // unmark the nodes + Vec_PtrForEachEntry( vNodes1, pNode1, m ) + pNode1->fMarkA = 0; + Vec_PtrFree( vNodes1 ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints info for each output cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupp, * vNodes; + Abc_Obj_t * pObj; + int i; + printf( "Structural support info:\n" ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); + printf( "%20s : Cone = %5d. Supp = %5d.\n", + Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vSupp ); + } +} + +/**Function************************************************************* + + Synopsis [Prints information about the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + fprintf( pFile, "Object %5d : ", pObj->Id ); + switch ( pObj->Type ) + { + case ABC_OBJ_NONE: + fprintf( pFile, "NONE " ); + break; + case ABC_OBJ_CONST1: + fprintf( pFile, "Const1 " ); + break; + case ABC_OBJ_PIO: + fprintf( pFile, "PIO " ); + break; + case ABC_OBJ_PI: + fprintf( pFile, "PI " ); + break; + case ABC_OBJ_PO: + fprintf( pFile, "PO " ); + break; + case ABC_OBJ_BI: + fprintf( pFile, "BI " ); + break; + case ABC_OBJ_BO: + fprintf( pFile, "BO " ); + break; + case ABC_OBJ_ASSERT: + fprintf( pFile, "Assert " ); + break; + case ABC_OBJ_NET: + fprintf( pFile, "Net " ); + break; + case ABC_OBJ_NODE: + fprintf( pFile, "Node " ); + break; + case ABC_OBJ_LATCH: + fprintf( pFile, "Latch " ); + break; + case ABC_OBJ_WHITEBOX: + fprintf( pFile, "Whitebox" ); + break; + case ABC_OBJ_BLACKBOX: + fprintf( pFile, "Blackbox" ); + break; + default: + assert(0); + break; + } + // print the fanins + fprintf( pFile, " Fanins ( " ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + fprintf( pFile, "%d ", pFanin->Id ); + fprintf( pFile, ") " ); +/* + fprintf( pFile, " Fanouts ( " ); + Abc_ObjForEachFanout( pObj, pFanin, i ) + fprintf( pFile, "%d(%c) ", pFanin->Id, Abc_NodeIsTravIdCurrent(pFanin)? '+' : '-' ); + fprintf( pFile, ") " ); +*/ + // print the logic function + if ( Abc_ObjIsNode(pObj) && Abc_NtkIsSopLogic(pObj->pNtk) ) + fprintf( pFile, " %s", pObj->pData ); + else + fprintf( pFile, "\n" ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcProve.c b/abc70930/src/base/abci/abcProve.c new file mode 100644 index 00000000..a4220216 --- /dev/null +++ b/abc70930/src/base/abci/abcProve.c @@ -0,0 +1,343 @@ +/**CFile**************************************************************** + + FileName [abcProve.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Proves the miter using AIG rewriting, FRAIGing, and SAT solving.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcProve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" +#include "math.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); +extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); + +static Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, sint64 nInspLimit, int * pRetValue, int * pNumFails, sint64 * pNumConfs, sint64 * pNumInspects ); +static void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Attempts to solve the miter using a number of tricks.] + + Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT. Returns + a simplified version of the original network (or a constant 0 network). + In case the network is not a constant zero and a SAT assignment is found, + pNtk->pModel contains a satisfying assignment.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars ) +{ + Prove_Params_t * pParams = pPars; + Abc_Ntk_t * pNtk, * pNtkTemp; + int RetValue, nIter, nSatFails, Counter, clk, timeStart = clock(); + sint64 nSatConfs, nSatInspects, nInspectLimit; + + // get the starting network + pNtk = *ppNtk; + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkPoNum(pNtk) == 1 ); + + if ( pParams->fVerbose ) + { + printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", + pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); + printf( "Mitering = %d (%3.1f). Rewriting = %d (%3.1f). Fraiging = %d (%3.1f).\n", + pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, + pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, + pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti ); + printf( "Mitering last = %d.\n", + pParams->nMiteringLimitLast ); + } + + // if SAT only, solve without iteration + if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) + { + clk = clock(); + RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)0, 0, NULL, NULL ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); + *ppNtk = pNtk; + return RetValue; + } + + // check the current resource limits + for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) + { + if ( pParams->fVerbose ) + { + printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, + (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), + (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); + fflush( stdout ); + } + + // try brute-force SAT + clk = clock(); + nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; + RetValue = Abc_NtkMiterSat( pNtk, (sint64)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (sint64)nInspectLimit, 0, &nSatConfs, &nSatInspects ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); + if ( RetValue >= 0 ) + break; + + // add to the number of backtracks and inspects + pParams->nTotalBacktracksMade += nSatConfs; + pParams->nTotalInspectsMade += nSatInspects; + // check if global resource limit is reached + if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || + (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) + { + printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); + *ppNtk = pNtk; + return -1; + } + + // try rewriting + if ( pParams->fUseRewriting ) + { + clk = clock(); + Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); +// Counter = 1; + while ( 1 ) + { +/* + extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); + pNtk = Abc_NtkIvyResyn( pNtkTemp = pNtk, 0, 0 ); Abc_NtkDelete( pNtkTemp ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; +*/ +/* + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; +*/ + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); + if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) + break; + if ( --Counter == 0 ) + break; + } + Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, pParams->fVerbose ); + } + + if ( pParams->fUseFraiging ) + { + // try FRAIGing + clk = clock(); + nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; + pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)), nInspectLimit, &RetValue, &nSatFails, &nSatConfs, &nSatInspects ); Abc_NtkDelete( pNtkTemp ); + Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, pParams->fVerbose ); +// printf( "NumFails = %d\n", nSatFails ); + if ( RetValue >= 0 ) + break; + + // add to the number of backtracks and inspects + pParams->nTotalBacktracksMade += nSatConfs; + pParams->nTotalInspectsMade += nSatInspects; + // check if global resource limit is reached + if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || + (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) + { + printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); + *ppNtk = pNtk; + return -1; + } + } + + } + + // try to prove it using brute force SAT + if ( RetValue < 0 && pParams->fUseBdds ) + { + if ( pParams->fVerbose ) + { + printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); + fflush( stdout ); + } + clk = clock(); + pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); + if ( pNtk ) + { + Abc_NtkDelete( pNtkTemp ); + RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) ); + } + else + pNtk = pNtkTemp; + Abc_NtkMiterPrint( pNtk, "BDD building", clk, pParams->fVerbose ); + } + + if ( RetValue < 0 ) + { + if ( pParams->fVerbose ) + { + printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); + fflush( stdout ); + } + clk = clock(); + nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; + RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)nInspectLimit, 0, NULL, NULL ); + Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); + } + + // assign the model if it was proved by rewriting (const 1 miter) + if ( RetValue == 0 && pNtk->pModel == NULL ) + { + pNtk->pModel = ALLOC( int, Abc_NtkCiNum(pNtk) ); + memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) ); + } + *ppNtk = pNtk; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Attempts to solve the miter using a number of tricks.] + + Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, sint64 nInspLimit, int * pRetValue, int * pNumFails, sint64 * pNumConfs, sint64 * pNumInspects ) +{ + Abc_Ntk_t * pNtkNew; + Fraig_Params_t Params, * pParams = &Params; + Fraig_Man_t * pMan; + int nWords1, nWords2, nWordsMin, RetValue; + int * pModel; + + // to determine the number of simulation patterns + // use the following strategy + // at least 64 words (32 words random and 32 words dynamic) + // no more than 256M for one circuit (128M + 128M) + nWords1 = 32; + nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk)); + nWordsMin = ABC_MIN( nWords1, nWords2 ); + + // set the FRAIGing parameters + Fraig_ParamsSetDefault( pParams ); + pParams->nPatsRand = nWordsMin * 32; // the number of words of random simulation info + pParams->nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info + pParams->nBTLimit = nBTLimit; // the max number of backtracks + pParams->nSeconds = -1; // the runtime limit + pParams->fTryProve = 0; // do not try to prove the final miter + pParams->fDoSparse = 1; // try proving sparse functions + pParams->fVerbose = 0; + pParams->nInspLimit = nInspLimit; + + // transform the target into a fraig + pMan = Abc_NtkToFraig( pNtk, pParams, 0, 0 ); + Fraig_ManProveMiter( pMan ); + RetValue = Fraig_ManCheckMiter( pMan ); + + // create the network + pNtkNew = Abc_NtkFromFraig( pMan, pNtk ); + + // save model + if ( RetValue == 0 ) + { + pModel = Fraig_ManReadModel( pMan ); + FREE( pNtkNew->pModel ); + pNtkNew->pModel = ALLOC( int, Abc_NtkCiNum(pNtkNew) ); + memcpy( pNtkNew->pModel, pModel, sizeof(int) * Abc_NtkCiNum(pNtkNew) ); + } + + // save the return values + *pRetValue = RetValue; + *pNumFails = Fraig_ManReadSatFails( pMan ); + *pNumConfs = Fraig_ManReadConflicts( pMan ); + *pNumInspects = Fraig_ManReadInspects( pMan ); + + // delete the fraig manager + Fraig_ManFree( pMan ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Attempts to solve the miter using a number of tricks.] + + Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose ) +{ + if ( !fVerbose ) + return; + printf( "Nodes = %7d. Levels = %4d. ", Abc_NtkNodeNum(pNtk), + Abc_NtkIsStrash(pNtk)? Abc_AigLevel(pNtk) : Abc_NtkLevel(pNtk) ); + PRT( pString, clock() - clk ); +} + + +/**Function************************************************************* + + Synopsis [Implements resynthesis for CEC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMiterRwsat( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkTemp; + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + return pNtk; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcQbf.c b/abc70930/src/base/abci/abcQbf.c new file mode 100644 index 00000000..b839f812 --- /dev/null +++ b/abc70930/src/base/abci/abcQbf.c @@ -0,0 +1,260 @@ +/**CFile**************************************************************** + + FileName [abcQbf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Implementation of a simple QBF solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcQbf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +/* + Implementation of a simple QBF solver along the lines of + A. Solar-Lezama, L. Tancau, R. Bodik, V. Saraswat, and S. Seshia, + "Combinatorial sketching for finite programs", 12th International + Conference on Architectural Support for Programming Languages and + Operating Systems (ASPLOS 2006), San Jose, CA, October 2006. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ); +static void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars ); +static void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ); +static void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars ); +static void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Solve the QBF problem EpAx[M(p,x)].] + + Description [Variables p go first, followed by variable x. + The number of parameters is nPars. The miter is in pNtk. + The miter expresses EQUALITY of the implementation and spec.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int fVerbose ) +{ + Abc_Ntk_t * pNtkVer, * pNtkSyn, * pNtkSyn2, * pNtkTemp; + Vec_Int_t * vPiValues; + int clkTotal = clock(), clkS, clkV; + int nIters, nIterMax = 500, nInputs, RetValue, fFound = 0; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkIsComb(pNtk) ); + assert( Abc_NtkPoNum(pNtk) == 1 ); + assert( nPars > 0 && nPars < Abc_NtkPiNum(pNtk) ); + assert( Abc_NtkPiNum(pNtk)-nPars < 32 ); + nInputs = Abc_NtkPiNum(pNtk) - nPars; + + // initialize the synthesized network with 0000-combination + vPiValues = Vec_IntStart( Abc_NtkPiNum(pNtk) ); + Abc_NtkVectorClearPars( vPiValues, nPars ); + pNtkSyn = Abc_NtkMiterCofactor( pNtk, vPiValues ); + if ( fVerbose ) + { + printf( "Iter %2d : ", 0 ); + printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) ); + Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars ); + printf( "\n" ); + } + + // iteratively solve + for ( nIters = 0; nIters < nIterMax; nIters++ ) + { + // solve the synthesis instance +clkS = clock(); + RetValue = Abc_NtkMiterSat( pNtkSyn, 0, 0, 0, NULL, NULL ); +clkS = clock() - clkS; + if ( RetValue == 0 ) + Abc_NtkModelToVector( pNtkSyn, vPiValues ); + if ( RetValue == 1 ) + { + break; + } + if ( RetValue == -1 ) + { + printf( "Synthesis timed out.\n" ); + break; + } + // there is a counter-example + + // construct the verification instance + Abc_NtkVectorClearVars( pNtk, vPiValues, nPars ); + pNtkVer = Abc_NtkMiterCofactor( pNtk, vPiValues ); + // complement the output + Abc_ObjXorFaninC( Abc_NtkPo(pNtkVer,0), 0 ); + + // solve the verification instance +clkV = clock(); + RetValue = Abc_NtkMiterSat( pNtkVer, 0, 0, 0, NULL, NULL ); +clkV = clock() - clkV; + if ( RetValue == 0 ) + Abc_NtkModelToVector( pNtkVer, vPiValues ); + Abc_NtkDelete( pNtkVer ); + if ( RetValue == 1 ) + { + fFound = 1; + break; + } + if ( RetValue == -1 ) + { + printf( "Verification timed out.\n" ); + break; + } + // there is a counter-example + + // create a new synthesis network + Abc_NtkVectorClearPars( vPiValues, nPars ); + pNtkSyn2 = Abc_NtkMiterCofactor( pNtk, vPiValues ); + // add to the synthesis instance + pNtkSyn = Abc_NtkMiterAnd( pNtkTemp = pNtkSyn, pNtkSyn2, 0, 0 ); + Abc_NtkDelete( pNtkSyn2 ); + Abc_NtkDelete( pNtkTemp ); + + if ( fVerbose ) + { + printf( "Iter %2d : ", nIters+1 ); + printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) ); + Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars ); + printf( " " ); +// PRTn( "Syn", clkS ); + PRT( "Ver", clkV ); + } + } + Abc_NtkDelete( pNtkSyn ); + // report the results + if ( fFound ) + { + printf( "Parameters: " ); + Abc_NtkVectorPrintPars( vPiValues, nPars ); + printf( "\n" ); + printf( "Solved after %d interations. ", nIters ); + } + else if ( nIters == nIterMax ) + printf( "Unsolved after %d interations. ", nIters ); + else + printf( "Implementation does not exist. " ); + PRT( "Total runtime", clock() - clkTotal ); + Vec_IntFree( vPiValues ); +} + + +/**Function************************************************************* + + Synopsis [Translates model into the vector of values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) +{ + int * pModel, i; + pModel = pNtk->pModel; + for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) + Vec_IntWriteEntry( vPiValues, i, pModel[i] ); +} + +/**Function************************************************************* + + Synopsis [Clears parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars ) +{ + int i; + for ( i = 0; i < nPars; i++ ) + Vec_IntWriteEntry( vPiValues, i, -1 ); +} + +/**Function************************************************************* + + Synopsis [Clears variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ) +{ + int i; + for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) + Vec_IntWriteEntry( vPiValues, i, -1 ); +} + +/**Function************************************************************* + + Synopsis [Clears variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars ) +{ + int i; + for ( i = 0; i < nPars; i++ ) + printf( "%d", Vec_IntEntry(vPiValues,i) ); +} + +/**Function************************************************************* + + Synopsis [Clears variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ) +{ + int i; + for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) + printf( "%d", Vec_IntEntry(vPiValues,i) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcQuant.c b/abc70930/src/base/abci/abcQuant.c new file mode 100644 index 00000000..0f2bd72f --- /dev/null +++ b/abc70930/src/base/abci/abcQuant.c @@ -0,0 +1,419 @@ +/**CFile**************************************************************** + + FileName [abcQuant.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [AIG-based variable quantification.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcQuant.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs fast synthesis.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSynthesize( Abc_Ntk_t ** ppNtk, int fMoreEffort ) +{ + Abc_Ntk_t * pNtk, * pNtkTemp; + + pNtk = *ppNtk; + + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); + Abc_NtkDelete( pNtkTemp ); + + if ( fMoreEffort ) + { + Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); + Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); + pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); + Abc_NtkDelete( pNtkTemp ); + } + + *ppNtk = pNtk; +} + +/**Function************************************************************* + + Synopsis [Existentially quantifies one variable.] + + Description [] + + SideEffects [This procedure creates dangling nodes in the AIG.] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pNext, * pFanin; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + assert( iVar < Abc_NtkCiNum(pNtk) ); + + // collect the internal nodes + pObj = Abc_NtkCi( pNtk, iVar ); + vNodes = Abc_NtkDfsReverseNodes( pNtk, &pObj, 1 ); + + // assign the cofactors of the CI node to be constants + pObj->pCopy = Abc_ObjNot( Abc_AigConst1(pNtk) ); + pObj->pData = Abc_AigConst1(pNtk); + + // quantify the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + for ( pNext = pObj? pObj->pCopy : pObj; pObj; pObj = pNext, pNext = pObj? pObj->pCopy : pObj ) + { + pFanin = Abc_ObjFanin0(pObj); + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + pFanin->pCopy = pFanin->pData = pFanin; + pFanin = Abc_ObjFanin1(pObj); + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + pFanin->pCopy = pFanin->pData = pFanin; + pObj->pCopy = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + pObj->pData = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Data(pObj), Abc_ObjChild1Data(pObj) ); + } + } + Vec_PtrFree( vNodes ); + + // update the affected COs + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + continue; + pFanin = Abc_ObjFanin0(pObj); + // get the result of quantification + if ( fUniv ) + pNext = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) ); + else + pNext = Abc_AigOr( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) ); + pNext = Abc_ObjNotCond( pNext, Abc_ObjFaninC0(pObj) ); + if ( Abc_ObjRegular(pNext) == pFanin ) + continue; + // update the fanins of the CO + Abc_ObjPatchFanin( pObj, pFanin, pNext ); +// if ( Abc_ObjFanoutNum(pFanin) == 0 ) +// Abc_AigDeleteNode( pNtk->pManFunc, pFanin ); + } + + // make sure the node has no fanouts +// pObj = Abc_NtkCi( pNtk, iVar ); +// assert( Abc_ObjFanoutNum(pObj) == 0 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Constructs the transition relation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose ) +{ + char Buffer[1000]; + Vec_Ptr_t * vPairs; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pMiter; + int i, nLatches; + int fSynthesis = 1; + + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkLatchNum(pNtk) ); + nLatches = Abc_NtkLatchNum(pNtk); + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + // duplicate the name and the spec + sprintf( Buffer, "%s_TR", pNtk->pName ); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); +// pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + Abc_NtkCleanCopy( pNtk ); + // create current state variables + Abc_NtkForEachLatchOutput( pNtk, pObj, i ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + // create next state variables + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pObj), NULL ); + // create PI variables + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + // create the PO + Abc_NtkCreatePo( pNtkNew ); + // restrash the nodes (assuming a topological order of the old network) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // create the function of the primary output + assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); + vPairs = Vec_PtrAlloc( 2*nLatches ); + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + { + Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pObj) ); + Vec_PtrPush( vPairs, Abc_NtkPi(pNtkNew, i+nLatches) ); + } + pMiter = Abc_AigMiter( pNtkNew->pManFunc, vPairs ); + Vec_PtrFree( vPairs ); + // add the primary output + Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), Abc_ObjNot(pMiter) ); + Abc_ObjAssignName( Abc_NtkPo(pNtkNew,0), "rel", NULL ); + + // quantify inputs + if ( fInputs ) + { + assert( Abc_NtkPiNum(pNtkNew) == Abc_NtkPiNum(pNtk) + 2*nLatches ); + for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- ) +// for ( i = 2*nLatches; i < Abc_NtkPiNum(pNtkNew); i++ ) + { + Abc_NtkQuantify( pNtkNew, 0, i, fVerbose ); +// if ( fSynthesis && (i % 3 == 2) ) + if ( fSynthesis ) + { + Abc_NtkCleanData( pNtkNew ); + Abc_AigCleanup( pNtkNew->pManFunc ); + Abc_NtkSynthesize( &pNtkNew, 1 ); + } +// printf( "Var = %3d. Nodes = %6d. ", Abc_NtkPiNum(pNtkNew) - 1 - i, Abc_NtkNodeNum(pNtkNew) ); +// printf( "Var = %3d. Nodes = %6d. ", i - 2*nLatches, Abc_NtkNodeNum(pNtkNew) ); + } +// printf( "\n" ); + Abc_NtkCleanData( pNtkNew ); + Abc_AigCleanup( pNtkNew->pManFunc ); + for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- ) + { + pObj = Abc_NtkPi( pNtkNew, i ); + assert( Abc_ObjFanoutNum(pObj) == 0 ); + Abc_NtkDeleteObj( pObj ); + } + } + + // check consistency of the network + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkTransRel: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Performs one image computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkInitialState( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pMiter; + int i, nVars = Abc_NtkPiNum(pNtk)/2; + assert( Abc_NtkIsStrash(pNtk) ); + // start the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // compute the all-zero state in terms of the CS variables + pMiter = Abc_AigConst1(pNtkNew); + for ( i = 0; i < nVars; i++ ) + pMiter = Abc_AigAnd( pNtkNew->pManFunc, pMiter, Abc_ObjNot( Abc_NtkPi(pNtkNew, i) ) ); + // add the PO + Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Swaps current state and next state variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkSwapVariables( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pMiter, * pObj, * pObj0, * pObj1; + int i, nVars = Abc_NtkPiNum(pNtk)/2; + assert( Abc_NtkIsStrash(pNtk) ); + // start the new network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // update the PIs + for ( i = 0; i < nVars; i++ ) + { + pObj0 = Abc_NtkPi( pNtk, i ); + pObj1 = Abc_NtkPi( pNtk, i+nVars ); + pMiter = pObj0->pCopy; + pObj0->pCopy = pObj1->pCopy; + pObj1->pCopy = pMiter; + } + // restrash + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // add the PO + pMiter = Abc_ObjChild0Copy( Abc_NtkPo(pNtk,0) ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Performs reachability analisys.] + + Description [Assumes that the input is the transition relation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtkRel, int nIters, int fVerbose ) +{ + Abc_Obj_t * pObj; + Abc_Ntk_t * pNtkFront, * pNtkReached, * pNtkNext, * pNtkTemp; + int clk, i, v, nVars, nNodesOld, nNodesNew, nNodesPrev; + int fFixedPoint = 0; + int fSynthesis = 1; + int fMoreEffort = 1; + + assert( Abc_NtkIsStrash(pNtkRel) ); + assert( Abc_NtkLatchNum(pNtkRel) == 0 ); + assert( Abc_NtkPiNum(pNtkRel) % 2 == 0 ); + + // compute the network composed of the initial states + pNtkFront = Abc_NtkInitialState( pNtkRel ); + pNtkReached = Abc_NtkDup( pNtkFront ); +//Abc_NtkShow( pNtkReached, 0, 0, 0 ); + +// if ( fVerbose ) +// printf( "Transition relation = %6d.\n", Abc_NtkNodeNum(pNtkRel) ); + + // perform iterations of reachability analysis + nNodesPrev = Abc_NtkNodeNum(pNtkFront); + nVars = Abc_NtkPiNum(pNtkRel)/2; + for ( i = 0; i < nIters; i++ ) + { + clk = clock(); + // get the set of next states + pNtkNext = Abc_NtkMiterAnd( pNtkRel, pNtkFront, 0, 0 ); + Abc_NtkDelete( pNtkFront ); + // quantify the current state variables + for ( v = 0; v < nVars; v++ ) + { + Abc_NtkQuantify( pNtkNext, 0, v, fVerbose ); + if ( fSynthesis && (v % 3 == 2) ) + { + Abc_NtkCleanData( pNtkNext ); + Abc_AigCleanup( pNtkNext->pManFunc ); + Abc_NtkSynthesize( &pNtkNext, fMoreEffort ); + } + } + Abc_NtkCleanData( pNtkNext ); + Abc_AigCleanup( pNtkNext->pManFunc ); + if ( fSynthesis ) + Abc_NtkSynthesize( &pNtkNext, 1 ); + // map the next states into the current states + pNtkNext = Abc_NtkSwapVariables( pNtkTemp = pNtkNext ); + Abc_NtkDelete( pNtkTemp ); + // check the termination condition + if ( Abc_ObjFanin0(Abc_NtkPo(pNtkNext,0)) == Abc_AigConst1(pNtkNext) ) + { + fFixedPoint = 1; + printf( "Fixed point is reached!\n" ); + Abc_NtkDelete( pNtkNext ); + break; + } + // compute new front + pNtkFront = Abc_NtkMiterAnd( pNtkNext, pNtkReached, 0, 1 ); + Abc_NtkDelete( pNtkNext ); + // add the reached states + pNtkReached = Abc_NtkMiterAnd( pNtkTemp = pNtkReached, pNtkFront, 1, 0 ); + Abc_NtkDelete( pNtkTemp ); + // compress the size of Front + nNodesOld = Abc_NtkNodeNum(pNtkFront); + if ( fSynthesis ) + { + Abc_NtkSynthesize( &pNtkFront, fMoreEffort ); + Abc_NtkSynthesize( &pNtkReached, fMoreEffort ); + } + nNodesNew = Abc_NtkNodeNum(pNtkFront); + // print statistics + if ( fVerbose ) + { + printf( "I = %3d : Reach = %6d Fr = %6d FrM = %6d %7.2f %% ", + i + 1, Abc_NtkNodeNum(pNtkReached), nNodesOld, nNodesNew, 100.0*(nNodesNew-nNodesPrev)/nNodesPrev ); + PRT( "T", clock() - clk ); + } + nNodesPrev = Abc_NtkNodeNum(pNtkFront); + } + if ( !fFixedPoint ) + fprintf( stdout, "Reachability analysis stopped after %d iterations.\n", nIters ); + + // complement the output to represent the set of unreachable states + Abc_ObjXorFaninC( Abc_NtkPo(pNtkReached,0), 0 ); + + // remove next state variables + for ( i = 2*nVars - 1; i >= nVars; i-- ) + { + pObj = Abc_NtkPi( pNtkReached, i ); + assert( Abc_ObjFanoutNum(pObj) == 0 ); + Abc_NtkDeleteObj( pObj ); + } + + // check consistency of the network + if ( !Abc_NtkCheck( pNtkReached ) ) + { + printf( "Abc_NtkReachability: The network check has failed.\n" ); + Abc_NtkDelete( pNtkReached ); + return NULL; + } + return pNtkReached; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRec.c b/abc70930/src/base/abci/abcRec.c new file mode 100644 index 00000000..a6ec6981 --- /dev/null +++ b/abc70930/src/base/abci/abcRec.c @@ -0,0 +1,1173 @@ +/**CFile**************************************************************** + + FileName [abcRec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Record of semi-canonical AIG subgraphs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "if.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_ManRec_t_ Abc_ManRec_t; +struct Abc_ManRec_t_ +{ + Abc_Ntk_t * pNtk; // the record + Vec_Ptr_t * vTtElems; // the elementary truth tables + Vec_Ptr_t * vTtNodes; // the node truth tables + Abc_Obj_t ** pBins; // hash table mapping truth tables into nodes + int nBins; // the number of allocated bins + int nVars; // the number of variables + int nVarsInit; // the number of variables requested initially + int nWords; // the number of TT words + int nCuts; // the max number of cuts to use + // temporaries + int * pBytes; // temporary storage for minterms + int * pMints; // temporary storage for minterm counters + unsigned * pTemp1; // temporary truth table + unsigned * pTemp2; // temporary truth table + Vec_Ptr_t * vNodes; // the temporary nodes + Vec_Ptr_t * vTtTemps; // the truth tables for the internal nodes of the cut + Vec_Ptr_t * vLabels; // temporary storage for AIG node labels + Vec_Str_t * vCosts; // temporary storage for costs + Vec_Int_t * vMemory; // temporary memory for truth tables + // statistics + int nTried; // the number of cuts tried + int nFilterSize; // the number of same structures + int nFilterRedund; // the number of same structures + int nFilterVolume; // the number of same structures + int nFilterTruth; // the number of same structures + int nFilterError; // the number of same structures + int nFilterSame; // the number of same structures + int nAdded; // the number of subgraphs added + int nAddedFuncs; // the number of functions added + // rewriting + int nFunsFound; // the found functions + int nFunsNotFound; // the missing functions + // runtime + int timeCollect; // the runtime to canonicize + int timeTruth; // the runtime to canonicize + int timeCanon; // the runtime to canonicize + int timeOther; // the runtime to canonicize + int timeTotal; // the runtime to canonicize +}; + +// the truth table is canonicized in such a way that for (00000) its value is 0 + +static Abc_Obj_t ** Abc_NtkRecTableLookup( Abc_ManRec_t * p, unsigned * pTruth, int nVars ); +static int Abc_NtkRecComputeTruth( Abc_Obj_t * pObj, Vec_Ptr_t * vTtNodes, int nVars ); +static int Abc_NtkRecAddCutCheckCycle_rec( Abc_Obj_t * pRoot, Abc_Obj_t * pObj ); + +static Abc_ManRec_t * s_pMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the record for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecIsRunning() +{ + return s_pMan != NULL; +} + +/**Function************************************************************* + + Synopsis [Starts the record for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecVarNum() +{ + return (s_pMan != NULL)? s_pMan->nVars : -1; +} + +/**Function************************************************************* + + Synopsis [Starts the record for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkRecMemory() +{ + return s_pMan->vMemory; +} + +/**Function************************************************************* + + Synopsis [Starts the record for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecStart( Abc_Ntk_t * pNtk, int nVars, int nCuts ) +{ + Abc_ManRec_t * p; + Abc_Obj_t * pObj, ** ppSpot; + char Buffer[10]; + unsigned * pTruth; + int i, RetValue; + int clkTotal = clock(), clk; + + assert( s_pMan == NULL ); + if ( pNtk == NULL ) + { + assert( nVars > 2 && nVars <= 16 ); + pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtk->pName = Extra_UtilStrsav( "record" ); + } + else + { + if ( Abc_NtkGetChoiceNum(pNtk) > 0 ) + { + printf( "The starting record should be a network without choice nodes.\n" ); + return; + } + if ( Abc_NtkPiNum(pNtk) > 16 ) + { + printf( "The starting record should be a network with no more than %d primary inputs.\n", 16 ); + return; + } + if ( Abc_NtkPiNum(pNtk) > nVars ) + printf( "The starting record has %d inputs (warning only).\n", Abc_NtkPiNum(pNtk) ); + pNtk = Abc_NtkDup( pNtk ); + } + // create the primary inputs + for ( i = Abc_NtkPiNum(pNtk); i < nVars; i++ ) + { + pObj = Abc_NtkCreatePi( pNtk ); + Buffer[0] = 'a' + i; + Buffer[1] = 0; + Abc_ObjAssignName( pObj, Buffer, NULL ); + } + Abc_NtkCleanCopy( pNtk ); + Abc_NtkCleanEquiv( pNtk ); + + // start the manager + p = ALLOC( Abc_ManRec_t, 1 ); + memset( p, 0, sizeof(Abc_ManRec_t) ); + p->pNtk = pNtk; + p->nVars = Abc_NtkPiNum(pNtk); + p->nWords = Kit_TruthWordNum( p->nVars ); + p->nCuts = nCuts; + p->nVarsInit = nVars; + + // create elementary truth tables + p->vTtElems = Vec_PtrAlloc( 0 ); assert( p->vTtElems->pArray == NULL ); + p->vTtElems->nSize = p->nVars; + p->vTtElems->nCap = p->nVars; + p->vTtElems->pArray = (void *)Extra_TruthElementary( p->nVars ); + + // allocate room for node truth tables + if ( Abc_NtkObjNum(pNtk) > (1<<14) ) + p->vTtNodes = Vec_PtrAllocSimInfo( 2 * Abc_NtkObjNum(pNtk), p->nWords ); + else + p->vTtNodes = Vec_PtrAllocSimInfo( 1<<14, p->nWords ); + + // create hash table + p->nBins = 50011; + p->pBins = ALLOC( Abc_Obj_t *, p->nBins ); + memset( p->pBins, 0, sizeof(Abc_Obj_t *) * p->nBins ); + + // set elementary tables + Kit_TruthFill( Vec_PtrEntry(p->vTtNodes, 0), p->nVars ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Kit_TruthCopy( Vec_PtrEntry(p->vTtNodes, pObj->Id), Vec_PtrEntry(p->vTtElems, i), p->nVars ); + + // compute the tables +clk = clock(); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + RetValue = Abc_NtkRecComputeTruth( pObj, p->vTtNodes, p->nVars ); + assert( RetValue ); + } +p->timeTruth += clock() - clk; + + // insert the PO nodes into the table + Abc_NtkForEachPo( pNtk, pObj, i ) + { + p->nTried++; + p->nAdded++; + + pObj = Abc_ObjFanin0(pObj); + pTruth = Vec_PtrEntry( p->vTtNodes, pObj->Id ); + + if ( pTruth[0] == 1128481603 ) + { + int x = 0; + } + + // add the resulting truth table to the hash table + ppSpot = Abc_NtkRecTableLookup( p, pTruth, p->nVars ); + assert( pObj->pEquiv == NULL ); + assert( pObj->pCopy == NULL ); + if ( *ppSpot == NULL ) + { + p->nAddedFuncs++; + *ppSpot = pObj; + } + else + { + pObj->pEquiv = (*ppSpot)->pEquiv; + (*ppSpot)->pEquiv = (Hop_Obj_t *)pObj; + if ( !Abc_NtkRecAddCutCheckCycle_rec(*ppSpot, pObj) ) + printf( "Loop!\n" ); + } + } + + // temporaries + p->pBytes = ALLOC( int, 4*p->nWords ); + p->pMints = ALLOC( int, 2*p->nVars ); + p->pTemp1 = ALLOC( unsigned, p->nWords ); + p->pTemp2 = ALLOC( unsigned, p->nWords ); + p->vNodes = Vec_PtrAlloc( 100 ); + p->vTtTemps = Vec_PtrAllocSimInfo( 64, p->nWords ); + p->vMemory = Vec_IntAlloc( Abc_TruthWordNum(p->nVars) * 1000 ); + + // set the manager + s_pMan = p; +p->timeTotal += clock() - clkTotal; +} + +/**Function************************************************************* + + Synopsis [Returns the given record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecStop() +{ + assert( s_pMan != NULL ); + if ( s_pMan->pNtk ) + Abc_NtkDelete( s_pMan->pNtk ); + Vec_PtrFree( s_pMan->vTtNodes ); + Vec_PtrFree( s_pMan->vTtElems ); + free( s_pMan->pBins ); + + // temporaries + free( s_pMan->pBytes ); + free( s_pMan->pMints ); + free( s_pMan->pTemp1 ); + free( s_pMan->pTemp2 ); + Vec_PtrFree( s_pMan->vNodes ); + Vec_PtrFree( s_pMan->vTtTemps ); + if ( s_pMan->vLabels ) + Vec_PtrFree( s_pMan->vLabels ); + if ( s_pMan->vCosts ) + Vec_StrFree( s_pMan->vCosts ); + Vec_IntFree( s_pMan->vMemory ); + + free( s_pMan ); + s_pMan = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the given record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRecUse() +{ + Abc_ManRec_t * p = s_pMan; + Abc_Ntk_t * pNtk = p->pNtk; + assert( p != NULL ); + Abc_NtkRecPs(); + p->pNtk = NULL; + Abc_NtkRecStop(); + return pNtk; +} + +static inline void Abc_ObjSetMax( Abc_Obj_t * pObj, int Value ) { assert( pObj->Level < 0xff ); pObj->Level = (Value << 8) | (pObj->Level & 0xff); } +static inline void Abc_ObjClearMax( Abc_Obj_t * pObj ) { pObj->Level = (pObj->Level & 0xff); } +static inline int Abc_ObjGetMax( Abc_Obj_t * pObj ) { return (pObj->Level >> 8) & 0xff; } + +/**Function************************************************************* + + Synopsis [Print statistics about the current record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecPs() +{ + int Counter, Counters[17] = {0}; + int CounterS, CountersS[17] = {0}; + Abc_ManRec_t * p = s_pMan; + Abc_Ntk_t * pNtk = p->pNtk; + Abc_Obj_t * pObj, * pEntry, * pTemp; + int i; + + // set the max PI number + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetMax( pObj, i+1 ); + Abc_AigForEachAnd( pNtk, pObj, i ) + Abc_ObjSetMax( pObj, ABC_MAX( Abc_ObjGetMax(Abc_ObjFanin0(pObj)), Abc_ObjGetMax(Abc_ObjFanin1(pObj)) ) ); + // go through the table + Counter = CounterS = 0; + for ( i = 0; i < p->nBins; i++ ) + for ( pEntry = p->pBins[i]; pEntry; pEntry = pEntry->pCopy ) + { + Counters[ Abc_ObjGetMax(pEntry) ]++; + Counter++; + for ( pTemp = pEntry; pTemp; pTemp = (Abc_Obj_t *)pTemp->pEquiv ) + { + assert( Abc_ObjGetMax(pTemp) == Abc_ObjGetMax(pEntry) ); + CountersS[ Abc_ObjGetMax(pTemp) ]++; + CounterS++; + } + } +// printf( "Functions = %d. Expected = %d.\n", Counter, p->nAddedFuncs ); +// printf( "Subgraphs = %d. Expected = %d.\n", CounterS, p->nAdded ); + assert( Counter == p->nAddedFuncs ); + assert( CounterS == p->nAdded ); + + // clean + Abc_NtkForEachObj( pNtk, pObj, i ) + { + Abc_ObjClearMax( pObj ); + } + + printf( "The record with %d AND nodes in %d subgraphs for %d functions with %d inputs:\n", + Abc_NtkNodeNum(pNtk), Abc_NtkPoNum(pNtk), p->nAddedFuncs, Abc_NtkPiNum(pNtk) ); + for ( i = 0; i <= 16; i++ ) + { + if ( Counters[i] ) + printf( "Inputs = %2d. Funcs = %8d. Subgrs = %8d. Ratio = %6.2f.\n", i, Counters[i], CountersS[i], 1.0*CountersS[i]/Counters[i] ); + } + + printf( "Subgraphs tried = %8d. (%6.2f %%)\n", p->nTried, !p->nTried? 0 : 100.0*p->nTried/p->nTried ); + printf( "Subgraphs filtered by support size = %8d. (%6.2f %%)\n", p->nFilterSize, !p->nTried? 0 : 100.0*p->nFilterSize/p->nTried ); + printf( "Subgraphs filtered by structural redundancy = %8d. (%6.2f %%)\n", p->nFilterRedund, !p->nTried? 0 : 100.0*p->nFilterRedund/p->nTried ); + printf( "Subgraphs filtered by volume = %8d. (%6.2f %%)\n", p->nFilterVolume, !p->nTried? 0 : 100.0*p->nFilterVolume/p->nTried ); + printf( "Subgraphs filtered by TT redundancy = %8d. (%6.2f %%)\n", p->nFilterTruth, !p->nTried? 0 : 100.0*p->nFilterTruth/p->nTried ); + printf( "Subgraphs filtered by error = %8d. (%6.2f %%)\n", p->nFilterError, !p->nTried? 0 : 100.0*p->nFilterError/p->nTried ); + printf( "Subgraphs filtered by isomorphism = %8d. (%6.2f %%)\n", p->nFilterSame, !p->nTried? 0 : 100.0*p->nFilterSame/p->nTried ); + printf( "Subgraphs added = %8d. (%6.2f %%)\n", p->nAdded, !p->nTried? 0 : 100.0*p->nAdded/p->nTried ); + printf( "Functions added = %8d. (%6.2f %%)\n", p->nAddedFuncs, !p->nTried? 0 : 100.0*p->nAddedFuncs/p->nTried ); + + p->timeOther = p->timeTotal - p->timeCollect - p->timeTruth - p->timeCanon; + PRTP( "Collecting nodes ", p->timeCollect, p->timeTotal ); + PRTP( "Computing truth ", p->timeTruth, p->timeTotal ); + PRTP( "Canonicizing ", p->timeCanon, p->timeTotal ); + PRTP( "Other ", p->timeOther, p->timeTotal ); + PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + if ( p->nFunsFound ) + printf( "During rewriting found = %d and not found = %d functions.\n", p->nFunsFound, p->nFunsNotFound ); +} + +/**Function************************************************************* + + Synopsis [Filters the current record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecFilter( int iVar, int iPlus ) +{ +} + +/**Function************************************************************* + + Synopsis [Returns the hash key.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Abc_NtkRecTableHash( unsigned * pTruth, int nVars, int nBins, int * pPrimes ) +{ + int i, nWords = Kit_TruthWordNum( nVars ); + unsigned uHash = 0; + for ( i = 0; i < nWords; i++ ) + uHash ^= pTruth[i] * pPrimes[i & 0x7]; + return uHash % nBins; +} + +/**Function************************************************************* + + Synopsis [Returns the given record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t ** Abc_NtkRecTableLookup( Abc_ManRec_t * p, unsigned * pTruth, int nVars ) +{ + static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; + Abc_Obj_t ** ppSpot, * pEntry; + ppSpot = p->pBins + Abc_NtkRecTableHash( pTruth, nVars, p->nBins, s_Primes ); + for ( pEntry = *ppSpot; pEntry; ppSpot = &pEntry->pCopy, pEntry = pEntry->pCopy ) + if ( Kit_TruthIsEqualWithPhase(Vec_PtrEntry(p->vTtNodes, pEntry->Id), pTruth, nVars) ) + return ppSpot; + return ppSpot; +} + +/**Function************************************************************* + + Synopsis [Computes the truth table of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecComputeTruth( Abc_Obj_t * pObj, Vec_Ptr_t * vTtNodes, int nVars ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + int RetValue; + assert( Abc_ObjIsNode(pObj) ); + pTruth = Vec_PtrEntry( vTtNodes, pObj->Id ); + pTruth0 = Vec_PtrEntry( vTtNodes, Abc_ObjFaninId0(pObj) ); + pTruth1 = Vec_PtrEntry( vTtNodes, Abc_ObjFaninId1(pObj) ); + Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + assert( (pTruth[0] & 1) == pObj->fPhase ); + RetValue = ((pTruth[0] & 1) == pObj->fPhase); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Performs renoding as technology mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecAdd( Abc_Ntk_t * pNtk ) +{ + extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); + extern int Abc_NtkRecAddCut( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut ); + + If_Par_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtkNew; + int clk = clock(); + + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing renoding with choices.\n" ); + + // set defaults + memset( pPars, 0, sizeof(If_Par_t) ); + // user-controlable paramters + pPars->nLutSize = s_pMan->nVarsInit; + pPars->nCutsMax = s_pMan->nCuts; + pPars->nFlowIters = 0; + pPars->nAreaIters = 0; + pPars->DelayTarget = -1; + pPars->fPreprocess = 0; + pPars->fArea = 1; + pPars->fFancy = 0; + pPars->fExpRed = 0; + pPars->fLatchPaths = 0; + pPars->fSeqMap = 0; + pPars->fVerbose = 0; + // internal parameters + pPars->fTruth = 0; + pPars->fUsePerm = 0; + pPars->nLatches = 0; + pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); + pPars->pTimesArr = NULL; + pPars->pTimesArr = NULL; + pPars->fUseBdds = 0; + pPars->fUseSops = 0; + pPars->fUseCnfs = 0; + pPars->fUseMv = 0; + pPars->pFuncCost = NULL; + pPars->pFuncUser = Abc_NtkRecAddCut; + + // perform recording + pNtkNew = Abc_NtkIf( pNtk, pPars ); + Abc_NtkDelete( pNtkNew ); +s_pMan->timeTotal += clock() - clk; + +// if ( !Abc_NtkCheck( s_pMan->pNtk ) ) +// printf( "Abc_NtkRecAdd: The network check has failed.\n" ); +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRecCollectNodes_rec( If_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + if ( pNode->fMark ) + return; + pNode->fMark = 1; + assert( If_ObjIsAnd(pNode) ); + Abc_NtkRecCollectNodes_rec( If_ObjFanin0(pNode), vNodes ); + Abc_NtkRecCollectNodes_rec( If_ObjFanin1(pNode), vNodes ); + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecCollectNodes( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ) +{ + If_Obj_t * pLeaf; + int i, RetValue = 1; + + // collect the internal nodes of the cut + Vec_PtrClear( vNodes ); + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + { + Vec_PtrPush( vNodes, pLeaf ); + assert( pLeaf->fMark == 0 ); + pLeaf->fMark = 1; + } + + // collect other nodes + Abc_NtkRecCollectNodes_rec( pRoot, vNodes ); + + // check if there are leaves, such that both of their fanins are marked + // this indicates a redundant cut + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + { + if ( !If_ObjIsAnd(pLeaf) ) + continue; + if ( If_ObjFanin0(pLeaf)->fMark && If_ObjFanin1(pLeaf)->fMark ) + { + RetValue = 0; + break; + } + } + + // clean the mark + Vec_PtrForEachEntry( vNodes, pLeaf, i ) + pLeaf->fMark = 0; +/* + if ( pRoot->Id == 2639 ) + { + // print the cut + Vec_PtrForEachEntry( vNodes, pLeaf, i ) + { + if ( If_ObjIsAnd(pLeaf) ) + printf( "%4d = %c%4d & %c%4d\n", pLeaf->Id, + (If_ObjFaninC0(pLeaf)? '-':'+'), If_ObjFanin0(pLeaf)->Id, + (If_ObjFaninC1(pLeaf)? '-':'+'), If_ObjFanin1(pLeaf)->Id ); + else + printf( "%4d = pi\n", pLeaf->Id ); + } + printf( "\n" ); + } +*/ + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Computes truth tables of nodes in the cut.] + + Description [Returns 0 if the TT does not depend on some cut variables. + Or if the TT can be expressed simpler using other nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecCutTruth( Vec_Ptr_t * vNodes, int nLeaves, Vec_Ptr_t * vTtTemps, Vec_Ptr_t * vTtElems ) +{ + unsigned * pSims, * pSims0, * pSims1; + unsigned * pTemp = s_pMan->pTemp2; + unsigned uWord; + If_Obj_t * pObj, * pObj2, * pRoot; + int i, k, nLimit, nInputs = s_pMan->nVars; + + assert( Vec_PtrSize(vNodes) > nLeaves ); + + // set the elementary truth tables and compute the truth tables of the nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + pObj->pCopy = Vec_PtrEntry(vTtTemps, i); + pSims = (unsigned *)pObj->pCopy; + if ( i < nLeaves ) + { + Kit_TruthCopy( pSims, Vec_PtrEntry(vTtElems, i), nInputs ); + continue; + } + assert( If_ObjIsAnd(pObj) ); + // get hold of the simulation information + pSims0 = (unsigned *)If_ObjFanin0(pObj)->pCopy; + pSims1 = (unsigned *)If_ObjFanin1(pObj)->pCopy; + // simulate the node + Kit_TruthAndPhase( pSims, pSims0, pSims1, nInputs, If_ObjFaninC0(pObj), If_ObjFaninC1(pObj) ); + } + + // check the support size + pRoot = Vec_PtrEntryLast( vNodes ); + pSims = (unsigned *)pRoot->pCopy; + if ( Kit_TruthSupport(pSims, nInputs) != Kit_BitMask(nLeaves) ) + return 0; + + // make sure none of the nodes has the same simulation info as the output + // check pairwise comparisons + nLimit = Vec_PtrSize(vNodes) - 1; + Vec_PtrForEachEntryStop( vNodes, pObj, i, nLimit ) + { + pSims0 = (unsigned *)pObj->pCopy; + if ( Kit_TruthIsEqualWithPhase(pSims, pSims0, nInputs) ) + return 0; + Vec_PtrForEachEntryStop( vNodes, pObj2, k, i ) + { + if ( (If_ObjFanin0(pRoot) == pObj && If_ObjFanin1(pRoot) == pObj2) || + (If_ObjFanin1(pRoot) == pObj && If_ObjFanin0(pRoot) == pObj2) ) + continue; + pSims1 = (unsigned *)pObj2->pCopy; + + uWord = pSims0[0] & pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 0 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + + uWord = pSims0[0] & ~pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 1 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + + uWord = ~pSims0[0] & pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 0 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + + uWord = ~pSims0[0] & ~pSims1[0]; + if ( pSims[0] == uWord || pSims[0] == ~uWord ) + { + Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 1 ); + if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) + return 0; + } + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecAddCutCheckCycle_rec( Abc_Obj_t * pRoot, Abc_Obj_t * pObj ) +{ + assert( pRoot->Level > 0 ); + if ( pObj->Level < pRoot->Level ) + return 1; + if ( pObj == pRoot ) + return 0; + if ( !Abc_NtkRecAddCutCheckCycle_rec(pRoot, Abc_ObjFanin0(pObj)) ) + return 0; + if ( !Abc_NtkRecAddCutCheckCycle_rec(pRoot, Abc_ObjFanin1(pObj)) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds the cut function to the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecAddCut( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut ) +{ + static int s_MaxSize[16] = { 0 }; + char Buffer[40], Name[20], Truth[20]; + char pCanonPerm[16]; + Abc_Obj_t * pObj, * pFanin0, * pFanin1, ** ppSpot, * pObjPo; + Abc_Ntk_t * pAig = s_pMan->pNtk; + If_Obj_t * pIfObj; + Vec_Ptr_t * vNodes = s_pMan->vNodes; + unsigned * pInOut = s_pMan->pTemp1; + unsigned * pTemp = s_pMan->pTemp2; + unsigned * pTruth; + int i, RetValue, nNodes, nNodesBeg, nInputs = s_pMan->nVars, nLeaves = If_CutLeaveNum(pCut); + unsigned uCanonPhase; + int clk; + + if ( pRoot->Id == 2639 ) + { + int y = 0; + } + + assert( nInputs <= 16 ); + assert( nInputs == (int)pCut->nLimit ); + s_pMan->nTried++; + + // skip small cuts + if ( nLeaves < 3 ) + { + s_pMan->nFilterSize++; + return 1; + } + + // collect internal nodes and skip redundant cuts +clk = clock(); + RetValue = Abc_NtkRecCollectNodes( pIfMan, pRoot, pCut, vNodes ); +s_pMan->timeCollect += clock() - clk; + if ( !RetValue ) + { + s_pMan->nFilterRedund++; + return 1; + } + + // skip cuts with very large volume + if ( Vec_PtrSize(vNodes) > nLeaves + 3*(nLeaves-1) + s_MaxSize[nLeaves] ) + { + s_pMan->nFilterVolume++; + return 1; + } + + // compute truth table and skip the redundant structures +clk = clock(); + RetValue = Abc_NtkRecCutTruth( vNodes, nLeaves, s_pMan->vTtTemps, s_pMan->vTtElems ); +s_pMan->timeTruth += clock() - clk; + if ( !RetValue ) + { + s_pMan->nFilterTruth++; + return 1; + } + + // copy the truth table + Kit_TruthCopy( pInOut, (unsigned *)pRoot->pCopy, nInputs ); + + // set permutation + for ( i = 0; i < nInputs; i++ ) + pCanonPerm[i] = i; + + // semi-canonicize the truth table +clk = clock(); + uCanonPhase = Kit_TruthSemiCanonicize( pInOut, pTemp, nInputs, pCanonPerm, (short *)s_pMan->pMints ); +s_pMan->timeCanon += clock() - clk; + // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth + + // go through the variables in the new truth table + for ( i = 0; i < nLeaves; i++ ) + { + // get hold of the corresponding leaf + pIfObj = If_ManObj( pIfMan, pCut->pLeaves[pCanonPerm[i]] ); + // get hold of the corresponding new node + pObj = Abc_NtkPi( pAig, i ); + pObj = Abc_ObjNotCond( pObj, (uCanonPhase & (1 << i)) ); + // map them + pIfObj->pCopy = pObj; +/* + if ( pRoot->Id == 2639 ) + { + unsigned uSupp; + printf( "Node %6d : ", pIfObj->Id ); + printf( "Support " ); + uSupp = Kit_TruthSupport(Vec_PtrEntry( s_pMan->vTtNodes, Abc_ObjRegular(pObj)->Id ), nInputs); + Extra_PrintBinary( stdout, &uSupp, nInputs ); + printf( " " ); + Extra_PrintBinary( stdout, Vec_PtrEntry( s_pMan->vTtNodes, Abc_ObjRegular(pObj)->Id ), 1<<6 ); + printf( "\n" ); + } +*/ + } + + // build the node and compute its truth table + nNodesBeg = Abc_NtkObjNumMax( pAig ); + Vec_PtrForEachEntryStart( vNodes, pIfObj, i, nLeaves ) + { + pFanin0 = Abc_ObjNotCond( If_ObjFanin0(pIfObj)->pCopy, If_ObjFaninC0(pIfObj) ); + pFanin1 = Abc_ObjNotCond( If_ObjFanin1(pIfObj)->pCopy, If_ObjFaninC1(pIfObj) ); + + nNodes = Abc_NtkObjNumMax( pAig ); + pObj = Abc_AigAnd( pAig->pManFunc, pFanin0, pFanin1 ); + assert( !Abc_ObjIsComplement(pObj) ); + pIfObj->pCopy = pObj; + + if ( pObj->Id == nNodes ) + { + // increase storage for truth tables + if ( Vec_PtrSize(s_pMan->vTtNodes) <= pObj->Id ) + Vec_PtrDoubleSimInfo(s_pMan->vTtNodes); + // compute the truth table + RetValue = Abc_NtkRecComputeTruth( pObj, s_pMan->vTtNodes, nInputs ); + if ( RetValue == 0 ) + { + s_pMan->nFilterError++; + printf( "T" ); + return 1; + } + } + } + + pTruth = Vec_PtrEntry( s_pMan->vTtNodes, pObj->Id ); + if ( Kit_TruthSupport(pTruth, nInputs) != Kit_BitMask(nLeaves) ) + { + s_pMan->nFilterError++; + printf( "S" ); + return 1; + } + + // compare the truth tables + if ( !Kit_TruthIsEqualWithPhase( pTruth, pInOut, nInputs ) ) + { + s_pMan->nFilterError++; + printf( "F" ); + return 1; + } +// Extra_PrintBinary( stdout, pInOut, 8 ); printf( "\n" ); + + // if not new nodes were added and the node has a CO fanout + if ( nNodesBeg == Abc_NtkObjNumMax(pAig) && Abc_NodeFindCoFanout(pObj) != NULL ) + { + s_pMan->nFilterSame++; + return 1; + } + s_pMan->nAdded++; + + // create PO for this node + pObjPo = Abc_NtkCreatePo(pAig); + Abc_ObjAddFanin( pObjPo, pObj ); + + // assign the name to this PO + sprintf( Name, "%d_%06d", nLeaves, Abc_NtkPoNum(pAig) ); + if ( (nInputs <= 6) && 0 ) + { + Extra_PrintHexadecimalString( Truth, pInOut, nInputs ); + sprintf( Buffer, "%s_%s", Name, Truth ); + } + else + { + sprintf( Buffer, "%s", Name ); + } + Abc_ObjAssignName( pObjPo, Buffer, NULL ); + + // add the resulting truth table to the hash table + ppSpot = Abc_NtkRecTableLookup( s_pMan, pTruth, nInputs ); + assert( pObj->pEquiv == NULL ); + assert( pObj->pCopy == NULL ); + if ( *ppSpot == NULL ) + { + s_pMan->nAddedFuncs++; + *ppSpot = pObj; + } + else + { + pObj->pEquiv = (*ppSpot)->pEquiv; + (*ppSpot)->pEquiv = (Hop_Obj_t *)pObj; + if ( !Abc_NtkRecAddCutCheckCycle_rec(*ppSpot, pObj) ) + printf( "Loop!\n" ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Labels the record AIG with the corresponding new AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkRecStrashNodeLabel_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fBuild, Vec_Ptr_t * vLabels ) +{ + Abc_Obj_t * pFanin0New, * pFanin1New, * pLabel; + assert( !Abc_ObjIsComplement(pObj) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return Vec_PtrEntry( vLabels, pObj->Id ); + assert( Abc_ObjIsNode(pObj) ); + // mark the node as visited + Abc_NodeSetTravIdCurrent( pObj ); + // label the fanins + pFanin0New = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, Abc_ObjFanin0(pObj), fBuild, vLabels ); + pFanin1New = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, Abc_ObjFanin1(pObj), fBuild, vLabels ); + // label the node if possible + pLabel = NULL; + if ( pFanin0New && pFanin1New ) + { + pFanin0New = Abc_ObjNotCond( pFanin0New, Abc_ObjFaninC0(pObj) ); + pFanin1New = Abc_ObjNotCond( pFanin1New, Abc_ObjFaninC1(pObj) ); + if ( fBuild ) + pLabel = Abc_AigAnd( pNtkNew->pManFunc, pFanin0New, pFanin1New ); + else + pLabel = Abc_AigAndLookup( pNtkNew->pManFunc, pFanin0New, pFanin1New ); + } + Vec_PtrWriteEntry( vLabels, pObj->Id, pLabel ); + return pLabel; +} + +/**Function************************************************************* + + Synopsis [Counts the area of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecStrashNodeCount_rec( Abc_Obj_t * pObj, Vec_Str_t * vCosts, Vec_Ptr_t * vLabels ) +{ + int Cost0, Cost1; + if ( Vec_PtrEntry( vLabels, pObj->Id ) ) + return 0; + assert( Abc_ObjIsNode(pObj) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return Vec_StrEntry( vCosts, pObj->Id ); + // mark the node as visited + Abc_NodeSetTravIdCurrent( pObj ); + // count for the fanins + Cost0 = Abc_NtkRecStrashNodeCount_rec( Abc_ObjFanin0(pObj), vCosts, vLabels ); + Cost1 = Abc_NtkRecStrashNodeCount_rec( Abc_ObjFanin1(pObj), vCosts, vLabels ); + Vec_StrWriteEntry( vCosts, pObj->Id, (char)(Cost0 + Cost1 + 1) ); + return Cost0 + Cost1 + 1; +} + +/**Function************************************************************* + + Synopsis [Strashes the given node using its local function.] + + Description [Assumes that the fanins are already strashed. + Returns 0 if the function is not found in the table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ) +{ + char pCanonPerm[16]; + Abc_Ntk_t * pAig = s_pMan->pNtk; + unsigned * pInOut = s_pMan->pTemp1; + unsigned * pTemp = s_pMan->pTemp2; + unsigned * pTruthRec; + Abc_Obj_t * pCand, * pCandMin, * pLeaf, * pFanin, ** ppSpot; + unsigned uCanonPhase; + int i, nLeaves, CostMin, Cost, nOnes, fCompl; + + // check if the record works + nLeaves = Abc_ObjFaninNum(pObj); + assert( nLeaves >= 3 && nLeaves <= s_pMan->nVars ); + pFanin = Abc_ObjFanin0(pObj); + assert( Abc_ObjRegular(pFanin->pCopy)->pNtk == pNtkNew ); + assert( s_pMan != NULL ); + assert( nVars == s_pMan->nVars ); + + // copy the truth table + Kit_TruthCopy( pInOut, pTruth, nVars ); + + // set permutation + for ( i = 0; i < nVars; i++ ) + pCanonPerm[i] = i; + + // canonicize the truth table + uCanonPhase = Kit_TruthSemiCanonicize( pInOut, pTemp, nVars, pCanonPerm, (short *)s_pMan->pMints ); + + // get hold of the curresponding class + ppSpot = Abc_NtkRecTableLookup( s_pMan, pInOut, nVars ); + if ( *ppSpot == NULL ) + { + s_pMan->nFunsNotFound++; +// printf( "The class of a function with %d inputs is not found.\n", nLeaves ); + return 0; + } + s_pMan->nFunsFound++; + + // make sure the truth table is the same + pTruthRec = Vec_PtrEntry( s_pMan->vTtNodes, (*ppSpot)->Id ); + if ( !Kit_TruthIsEqualWithPhase( pTruthRec, pInOut, nVars ) ) + { + assert( 0 ); + return 0; + } + + + // allocate storage for costs + if ( s_pMan->vLabels && Vec_PtrSize(s_pMan->vLabels) < Abc_NtkObjNumMax(pAig) ) + { + Vec_PtrFree( s_pMan->vLabels ); + s_pMan->vLabels = NULL; + } + if ( s_pMan->vLabels == NULL ) + s_pMan->vLabels = Vec_PtrStart( Abc_NtkObjNumMax(pAig) ); + + // go through the variables in the new truth table + Abc_NtkIncrementTravId( pAig ); + for ( i = 0; i < nLeaves; i++ ) + { + // get hold of the corresponding fanin + pFanin = Abc_ObjFanin( pObj, pCanonPerm[i] )->pCopy; + pFanin = Abc_ObjNotCond( pFanin, (uCanonPhase & (1 << i)) ); + // label the PI of the AIG subgraphs with this fanin + pLeaf = Abc_NtkPi( pAig, i ); + Vec_PtrWriteEntry( s_pMan->vLabels, pLeaf->Id, pFanin ); + Abc_NodeSetTravIdCurrent( pLeaf ); + } + + // go through the candidates - and recursively label them + for ( pCand = *ppSpot; pCand; pCand = (Abc_Obj_t *)pCand->pEquiv ) + Abc_NtkRecStrashNodeLabel_rec( pNtkNew, pCand, 0, s_pMan->vLabels ); + + + // allocate storage for costs + if ( s_pMan->vCosts && Vec_StrSize(s_pMan->vCosts) < Abc_NtkObjNumMax(pAig) ) + { + Vec_StrFree( s_pMan->vCosts ); + s_pMan->vCosts = NULL; + } + if ( s_pMan->vCosts == NULL ) + s_pMan->vCosts = Vec_StrStart( Abc_NtkObjNumMax(pAig) ); + + // find the best subgraph + CostMin = ABC_INFINITY; + pCandMin = NULL; + for ( pCand = *ppSpot; pCand; pCand = (Abc_Obj_t *)pCand->pEquiv ) + { + // label the leaves + Abc_NtkIncrementTravId( pAig ); + // count the number of non-labeled nodes + Cost = Abc_NtkRecStrashNodeCount_rec( pCand, s_pMan->vCosts, s_pMan->vLabels ); + if ( CostMin > Cost ) + { +// printf( "%d ", Cost ); + CostMin = Cost; + pCandMin = pCand; + } + } +// printf( "\n" ); + assert( pCandMin != NULL ); + if ( pCandMin == NULL ) + return 0; + + + // label the leaves + Abc_NtkIncrementTravId( pAig ); + for ( i = 0; i < nLeaves; i++ ) + Abc_NodeSetTravIdCurrent( Abc_NtkPi(pAig, i) ); + + // implement the subgraph + pObj->pCopy = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, pCandMin, 1, s_pMan->vLabels ); + assert( Abc_ObjRegular(pObj->pCopy)->pNtk == pNtkNew ); + + // determine phase difference + nOnes = Kit_TruthCountOnes(pTruth, nVars); + fCompl = (nOnes > (1<< nVars)/2); +// assert( fCompl == ((uCanonPhase & (1 << nVars)) > 0) ); + + nOnes = Kit_TruthCountOnes(pTruthRec, nVars); + fCompl ^= (nOnes > (1<< nVars)/2); + // complement + pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, fCompl ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcReconv.c b/abc70930/src/base/abci/abcReconv.c new file mode 100644 index 00000000..e77f055a --- /dev/null +++ b/abc70930/src/base/abci/abcReconv.c @@ -0,0 +1,762 @@ +/**CFile**************************************************************** + + FileName [abcReconv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computation of reconvergence-driven cuts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcReconv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Abc_ManCut_t_ +{ + // user specified parameters + int nNodeSizeMax; // the limit on the size of the supernode + int nConeSizeMax; // the limit on the size of the containing cone + int nNodeFanStop; // the limit on the size of the supernode + int nConeFanStop; // the limit on the size of the containing cone + // internal parameters + Vec_Ptr_t * vNodeLeaves; // fanins of the collapsed node (the cut) + Vec_Ptr_t * vConeLeaves; // fanins of the containing cone + Vec_Ptr_t * vVisited; // the visited nodes + Vec_Vec_t * vLevels; // the data structure to compute TFO nodes + Vec_Ptr_t * vNodesTfo; // the nodes in the TFO of the cut +}; + +static int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit ); +static int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit ); +static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Unmarks the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_NodesMark( Vec_Ptr_t * vVisited ) +{ + Abc_Obj_t * pNode; + int i; + Vec_PtrForEachEntry( vVisited, pNode, i ) + pNode->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Unmarks the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_NodesUnmark( Vec_Ptr_t * vVisited ) +{ + Abc_Obj_t * pNode; + int i; + Vec_PtrForEachEntry( vVisited, pNode, i ) + pNode->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Unmarks the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_NodesUnmarkB( Vec_Ptr_t * vVisited ) +{ + Abc_Obj_t * pNode; + int i; + Vec_PtrForEachEntry( vVisited, pNode, i ) + pNode->fMarkB = 0; +} + +/**Function************************************************************* + + Synopsis [Evaluate the cost of removing the node from the set of leaves.] + + Description [Returns the number of new leaves that will be brought in. + Returns large number if the node cannot be removed from the set of leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_NodeGetLeafCostOne( Abc_Obj_t * pNode, int nFaninLimit ) +{ + int Cost; + // make sure the node is in the construction zone + assert( pNode->fMarkB == 1 ); + // cannot expand over the PI node + if ( Abc_ObjIsCi(pNode) ) + return 999; + // get the cost of the cone + Cost = (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB); + // always accept if the number of leaves does not increase + if ( Cost < 2 ) + return Cost; + // skip nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > nFaninLimit ) + return 999; + // return the number of nodes that will be on the leaves if this node is removed + return Cost; +} + +/**Function************************************************************* + + Synopsis [Evaluate the cost of removing the node from the set of leaves.] + + Description [Returns the number of new leaves that will be brought in. + Returns large number if the node cannot be removed from the set of leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_NodeGetLeafCostTwo( Abc_Obj_t * pNode, int nFaninLimit, + Abc_Obj_t ** ppLeafToAdd, Abc_Obj_t ** pNodeToMark1, Abc_Obj_t ** pNodeToMark2 ) +{ + Abc_Obj_t * pFanin0, * pFanin1, * pTemp; + Abc_Obj_t * pGrand, * pGrandToAdd; + // make sure the node is in the construction zone + assert( pNode->fMarkB == 1 ); + // cannot expand over the PI node + if ( Abc_ObjIsCi(pNode) ) + return 999; + // skip nodes with many fanouts +// if ( Abc_ObjFanoutNum(pNode) > nFaninLimit ) +// return 999; + // get the children + pFanin0 = Abc_ObjFanin0(pNode); + pFanin1 = Abc_ObjFanin1(pNode); + assert( !pFanin0->fMarkB && !pFanin1->fMarkB ); + // count the number of unique grandchildren that will be included + // return infinite cost if this number if more than 1 + if ( Abc_ObjIsCi(pFanin0) && Abc_ObjIsCi(pFanin1) ) + return 999; + // consider the special case when a non-CI fanin can be dropped + if ( !Abc_ObjIsCi(pFanin0) && Abc_ObjFanin0(pFanin0)->fMarkB && Abc_ObjFanin1(pFanin0)->fMarkB ) + { + *ppLeafToAdd = pFanin1; + *pNodeToMark1 = pFanin0; + *pNodeToMark2 = NULL; + return 1; + } + if ( !Abc_ObjIsCi(pFanin1) && Abc_ObjFanin0(pFanin1)->fMarkB && Abc_ObjFanin1(pFanin1)->fMarkB ) + { + *ppLeafToAdd = pFanin0; + *pNodeToMark1 = pFanin1; + *pNodeToMark2 = NULL; + return 1; + } + + // make the first node CI if any + if ( Abc_ObjIsCi(pFanin1) ) + pTemp = pFanin0, pFanin0 = pFanin1, pFanin1 = pTemp; + // consider the first node + pGrandToAdd = NULL; + if ( Abc_ObjIsCi(pFanin0) ) + { + *pNodeToMark1 = NULL; + pGrandToAdd = pFanin0; + } + else + { + *pNodeToMark1 = pFanin0; + pGrand = Abc_ObjFanin0(pFanin0); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) + return 999; + pGrandToAdd = pGrand; + } + pGrand = Abc_ObjFanin1(pFanin0); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) + return 999; + pGrandToAdd = pGrand; + } + } + // consider the second node + *pNodeToMark2 = pFanin1; + pGrand = Abc_ObjFanin0(pFanin1); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) + return 999; + pGrandToAdd = pGrand; + } + pGrand = Abc_ObjFanin1(pFanin1); + if ( !pGrand->fMarkB ) + { + if ( pGrandToAdd && pGrandToAdd != pGrand ) + return 999; + pGrandToAdd = pGrand; + } + assert( pGrandToAdd != NULL ); + *ppLeafToAdd = pGrandToAdd; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Finds a fanin-limited, reconvergence-driven cut for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain ) +{ + Abc_Obj_t * pNode; + int i; + + assert( !Abc_ObjIsComplement(pRoot) ); + assert( Abc_ObjIsNode(pRoot) ); + + // start the visited nodes and mark them + Vec_PtrClear( p->vVisited ); + Vec_PtrPush( p->vVisited, pRoot ); + Vec_PtrPush( p->vVisited, Abc_ObjFanin0(pRoot) ); + Vec_PtrPush( p->vVisited, Abc_ObjFanin1(pRoot) ); + pRoot->fMarkB = 1; + Abc_ObjFanin0(pRoot)->fMarkB = 1; + Abc_ObjFanin1(pRoot)->fMarkB = 1; + + // start the cut + Vec_PtrClear( p->vNodeLeaves ); + Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin0(pRoot) ); + Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin1(pRoot) ); + + // compute the cut + while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vNodeLeaves, p->nNodeSizeMax, p->nNodeFanStop ) ); + assert( Vec_PtrSize(p->vNodeLeaves) <= p->nNodeSizeMax ); + + // return if containing cut is not requested + if ( !fContain ) + { + // unmark both fMarkA and fMarkB in tbe TFI + Abc_NodesUnmarkB( p->vVisited ); + return p->vNodeLeaves; + } + +//printf( "\n\n\n" ); + // compute the containing cut + assert( p->nNodeSizeMax < p->nConeSizeMax ); + // copy the current boundary + Vec_PtrClear( p->vConeLeaves ); + Vec_PtrForEachEntry( p->vNodeLeaves, pNode, i ) + Vec_PtrPush( p->vConeLeaves, pNode ); + // compute the containing cut + while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vConeLeaves, p->nConeSizeMax, p->nConeFanStop ) ); + assert( Vec_PtrSize(p->vConeLeaves) <= p->nConeSizeMax ); + // unmark TFI using fMarkA and fMarkB + Abc_NodesUnmarkB( p->vVisited ); + return p->vNodeLeaves; +} + +/**Function************************************************************* + + Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] + + Description [This procedure looks at the current leaves and tries to change + one leaf at a time in such a way that the cut grows as little as possible. + In evaluating the fanins, this procedure looks only at their immediate + predecessors (this is why it is called a one-level construction procedure).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit ) +{ + Abc_Obj_t * pNode, * pFaninBest, * pNext; + int CostBest, CostCur, i; + // find the best fanin + CostBest = 100; + pFaninBest = NULL; +//printf( "Evaluating fanins of the cut:\n" ); + Vec_PtrForEachEntry( vLeaves, pNode, i ) + { + CostCur = Abc_NodeGetLeafCostOne( pNode, nFaninLimit ); +//printf( " Fanin %s has cost %d.\n", Abc_ObjName(pNode), CostCur ); +// if ( CostBest > CostCur ) // performance improvement: expand the variable with the smallest level + if ( CostBest > CostCur || + (CostBest == CostCur && pNode->Level > pFaninBest->Level) ) + { + CostBest = CostCur; + pFaninBest = pNode; + } + if ( CostBest == 0 ) + break; + } + if ( pFaninBest == NULL ) + return 0; +// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit ); + + assert( CostBest < 3 ); + if ( vLeaves->nSize - 1 + CostBest > nSizeLimit ) + return 0; +// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit ); + + assert( Abc_ObjIsNode(pFaninBest) ); + // remove the node from the array + Vec_PtrRemove( vLeaves, pFaninBest ); +//printf( "Removing fanin %s.\n", Abc_ObjName(pFaninBest) ); + + // add the left child to the fanins + pNext = Abc_ObjFanin0(pFaninBest); + if ( !pNext->fMarkB ) + { +//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) ); + pNext->fMarkB = 1; + Vec_PtrPush( vLeaves, pNext ); + Vec_PtrPush( vVisited, pNext ); + } + // add the right child to the fanins + pNext = Abc_ObjFanin1(pFaninBest); + if ( !pNext->fMarkB ) + { +//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) ); + pNext->fMarkB = 1; + Vec_PtrPush( vLeaves, pNext ); + Vec_PtrPush( vVisited, pNext ); + } + assert( vLeaves->nSize <= nSizeLimit ); + // keep doing this + return 1; +} + +/**Function************************************************************* + + Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] + + Description [This procedure looks at the current leaves and tries to change + one leaf at a time in such a way that the cut grows as little as possible. + In evaluating the fanins, this procedure looks across two levels of fanins + (this is why it is called a two-level construction procedure).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit ) +{ + Abc_Obj_t * pNode, * pLeafToAdd, * pNodeToMark1, * pNodeToMark2; + int CostCur, i; + // find the best fanin + Vec_PtrForEachEntry( vLeaves, pNode, i ) + { + CostCur = Abc_NodeGetLeafCostTwo( pNode, nFaninLimit, &pLeafToAdd, &pNodeToMark1, &pNodeToMark2 ); + if ( CostCur < 2 ) + break; + } + if ( CostCur > 2 ) + return 0; + // remove the node from the array + Vec_PtrRemove( vLeaves, pNode ); + // add the node to the leaves + if ( pLeafToAdd ) + { + assert( !pLeafToAdd->fMarkB ); + pLeafToAdd->fMarkB = 1; + Vec_PtrPush( vLeaves, pLeafToAdd ); + Vec_PtrPush( vVisited, pLeafToAdd ); + } + // mark the other nodes + if ( pNodeToMark1 ) + { + assert( !pNodeToMark1->fMarkB ); + pNodeToMark1->fMarkB = 1; + Vec_PtrPush( vVisited, pNodeToMark1 ); + } + if ( pNodeToMark2 ) + { + assert( !pNodeToMark2->fMarkB ); + pNodeToMark2->fMarkB = 1; + Vec_PtrPush( vVisited, pNodeToMark2 ); + } + // keep doing this + return 1; +} + + +/**Function************************************************************* + + Synopsis [Get the nodes contained in the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited, int fIncludeFanins ) +{ + Abc_Obj_t * pTemp; + int i; + // mark the fanins of the cone + Abc_NodesMark( vLeaves ); + // collect the nodes in the DFS order + Vec_PtrClear( vVisited ); + // add the fanins + if ( fIncludeFanins ) + Vec_PtrForEachEntry( vLeaves, pTemp, i ) + Vec_PtrPush( vVisited, pTemp ); + // add other nodes + for ( i = 0; i < nRoots; i++ ) + Abc_NodeConeMarkCollect_rec( ppRoots[i], vVisited ); + // unmark both sets + Abc_NodesUnmark( vLeaves ); + Abc_NodesUnmark( vVisited ); +} + +/**Function************************************************************* + + Synopsis [Marks the TFI cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ) +{ + if ( pNode->fMarkA == 1 ) + return; + // visit transitive fanin + if ( Abc_ObjIsNode(pNode) ) + { + Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited ); + Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited ); + } + assert( pNode->fMarkA == 0 ); + pNode->fMarkA = 1; + Vec_PtrPush( vVisited, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns BDD representing the logic function of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited ) +{ + Abc_Obj_t * pNode; + DdNode * bFunc0, * bFunc1, * bFunc; + int i; + // get the nodes in the cut without fanins in the DFS order + Abc_NodeConeCollect( &pRoot, 1, vLeaves, vVisited, 0 ); + // set the elementary BDDs + Vec_PtrForEachEntry( vLeaves, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)pbVars[i]; + // compute the BDDs for the collected nodes + Vec_PtrForEachEntry( vVisited, pNode, i ) + { + assert( !Abc_ObjIsPi(pNode) ); + bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ); + bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ); + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + pNode->pCopy = (Abc_Obj_t *)bFunc; + } + Cudd_Ref( bFunc ); + // dereference the intermediate ones + Vec_PtrForEachEntry( vVisited, pNode, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy ); + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Returns BDD representing the transition relation of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited ) +{ + DdNode * bFunc0, * bFunc1, * bFunc, * bTrans, * bTemp, * bCube, * bResult; + Abc_Obj_t * pNode; + int i; + // get the nodes in the cut without fanins in the DFS order + Abc_NodeConeCollect( (Abc_Obj_t **)vRoots->pArray, vRoots->nSize, vLeaves, vVisited, 0 ); + // set the elementary BDDs + Vec_PtrForEachEntry( vLeaves, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)pbVarsX[i]; + // compute the BDDs for the collected nodes + Vec_PtrForEachEntry( vVisited, pNode, i ) + { + bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ); + bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ); + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + pNode->pCopy = (Abc_Obj_t *)bFunc; + } + // compute the transition relation of the cone + bTrans = b1; Cudd_Ref( bTrans ); + Vec_PtrForEachEntry( vRoots, pNode, i ) + { + bFunc = Cudd_bddXnor( dd, (DdNode *)pNode->pCopy, pbVarsY[i] ); Cudd_Ref( bFunc ); + bTrans = Cudd_bddAnd( dd, bTemp = bTrans, bFunc ); Cudd_Ref( bTrans ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bFunc ); + } + // dereference the intermediate ones + Vec_PtrForEachEntry( vVisited, pNode, i ) + Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy ); + // compute don't-cares + bCube = Extra_bddComputeRangeCube( dd, vRoots->nSize, vRoots->nSize + vLeaves->nSize ); Cudd_Ref( bCube ); + bResult = Cudd_bddExistAbstract( dd, bTrans, bCube ); Cudd_Ref( bResult ); + bResult = Cudd_Not( bResult ); + Cudd_RecursiveDeref( dd, bCube ); + Cudd_RecursiveDeref( dd, bTrans ); + Cudd_Deref( bResult ); + return bResult; +} + +/**Function************************************************************* + + Synopsis [Starts the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ) +{ + Abc_ManCut_t * p; + p = ALLOC( Abc_ManCut_t, 1 ); + memset( p, 0, sizeof(Abc_ManCut_t) ); + p->vNodeLeaves = Vec_PtrAlloc( 100 ); + p->vConeLeaves = Vec_PtrAlloc( 100 ); + p->vVisited = Vec_PtrAlloc( 100 ); + p->vLevels = Vec_VecAlloc( 100 ); + p->vNodesTfo = Vec_PtrAlloc( 100 ); + p->nNodeSizeMax = nNodeSizeMax; + p->nConeSizeMax = nConeSizeMax; + p->nNodeFanStop = nNodeFanStop; + p->nConeFanStop = nConeFanStop; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkManCutStop( Abc_ManCut_t * p ) +{ + Vec_PtrFree( p->vNodeLeaves ); + Vec_PtrFree( p->vConeLeaves ); + Vec_PtrFree( p->vVisited ); + Vec_VecFree( p->vLevels ); + Vec_PtrFree( p->vNodesTfo ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the leaves of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p ) +{ + return p->vConeLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the leaves of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p ) +{ + return p->vNodeLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the leaves of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p ) +{ + return p->vVisited; +} + + + +/**Function************************************************************* + + Synopsis [Collects the TFO of the cut in the topological order.] + + Description [TFO of the cut is defined as a set of nodes, for which the cut + is a cut, that is, every path from the collected nodes to the CIs goes through + a node in the cut. The nodes are collected if their level does not exceed + the given number (LevelMax). The nodes are returned in the topological order. + If the root node is given, its MFFC is marked, so that the collected nodes + do not contain any nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int LevelMax ) +{ + Abc_Ntk_t * pNtk = pRoot->pNtk; + Vec_Ptr_t * vVec; + Abc_Obj_t * pNode, * pFanout; + int i, k, v, LevelMin; + assert( Abc_NtkIsStrash(pNtk) ); + + // assuming that the structure is clean + Vec_VecForEachLevel( p->vLevels, vVec, i ) + assert( vVec->nSize == 0 ); + + // put fanins into the structure while labeling them + Abc_NtkIncrementTravId( pNtk ); + LevelMin = -1; + Vec_PtrForEachEntry( vLeaves, pNode, i ) + { + if ( pNode->Level > (unsigned)LevelMax ) + continue; + Abc_NodeSetTravIdCurrent( pNode ); + Vec_VecPush( p->vLevels, pNode->Level, pNode ); + if ( LevelMin < (int)pNode->Level ) + LevelMin = pNode->Level; + } + assert( LevelMin >= 0 ); + + // mark MFFC + if ( pRoot ) + Abc_NodeMffcLabelAig( pRoot ); + + // go through the levels up + Vec_PtrClear( p->vNodesTfo ); + Vec_VecForEachEntryStart( p->vLevels, pNode, i, k, LevelMin ) + { + if ( i > LevelMax ) + break; + // if the node is not marked, it is not a fanin + if ( !Abc_NodeIsTravIdCurrent(pNode) ) + { + // check if it belongs to the TFO + if ( !Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pNode)) || + !Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pNode)) ) + continue; + // save the node in the TFO and label it + Vec_PtrPush( p->vNodesTfo, pNode ); + Abc_NodeSetTravIdCurrent( pNode ); + } + // go through the fanouts and add them to the structure if they meet the conditions + Abc_ObjForEachFanout( pNode, pFanout, v ) + { + // skip if fanout is a CO or its level exceeds + if ( Abc_ObjIsCo(pFanout) || pFanout->Level > (unsigned)LevelMax ) + continue; + // skip if it is already added or if it is in MFFC + if ( Abc_NodeIsTravIdCurrent(pFanout) ) + continue; + // add it to the structure but do not mark it (until tested later) + Vec_VecPushUnique( p->vLevels, pFanout->Level, pFanout ); + } + } + + // clear the levelized structure + Vec_VecForEachLevelStart( p->vLevels, vVec, i, LevelMin ) + { + if ( i > LevelMax ) + break; + Vec_PtrClear( vVec ); + } + return p->vNodesTfo; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRefactor.c b/abc70930/src/base/abci/abcRefactor.c new file mode 100644 index 00000000..d2b77ed2 --- /dev/null +++ b/abc70930/src/base/abci/abcRefactor.c @@ -0,0 +1,379 @@ +/**CFile**************************************************************** + + FileName [abcRefactor.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Resynthesis based on collapsing and refactoring.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRefactor.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_ManRef_t_ Abc_ManRef_t; +struct Abc_ManRef_t_ +{ + // user specified parameters + int nNodeSizeMax; // the limit on the size of the supernode + int nConeSizeMax; // the limit on the size of the containing cone + int fVerbose; // the verbosity flag + // internal data structures + DdManager * dd; // the BDD manager + Vec_Str_t * vCube; // temporary + Vec_Int_t * vForm; // temporary + Vec_Ptr_t * vVisited; // temporary + Vec_Ptr_t * vLeaves; // temporary + // node statistics + int nLastGain; + int nNodesConsidered; + int nNodesRefactored; + int nNodesGained; + int nNodesBeg; + int nNodesEnd; + // runtime statistics + int timeCut; + int timeBdd; + int timeDcs; + int timeSop; + int timeFact; + int timeEval; + int timeRes; + int timeNtk; + int timeTotal; +}; + +static void Abc_NtkManRefPrintStats( Abc_ManRef_t * p ); +static Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose ); +static void Abc_NtkManRefStop( Abc_ManRef_t * p ); +static Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs incremental resynthesis of the AIG.] + + Description [Starting from each node, computes a reconvergence-driven cut, + derives BDD of the cut function, constructs ISOP, factors the ISOP, + and replaces the current implementation of the MFFC of the node by the + new factored form, if the number of AIG nodes is reduced and the total + number of levels of the AIG network is not increated. Returns the + number of AIG nodes saved.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ) +{ + ProgressBar * pProgress; + Abc_ManRef_t * pManRef; + Abc_ManCut_t * pManCut; + Dec_Graph_t * pFForm; + Vec_Ptr_t * vFanins; + Abc_Obj_t * pNode; + int clk, clkStart = clock(); + int i, nNodes; + + assert( Abc_NtkIsStrash(pNtk) ); + // cleanup the AIG + Abc_AigCleanup(pNtk->pManFunc); + // start the managers + pManCut = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, 1000 ); + pManRef = Abc_NtkManRefStart( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose ); + pManRef->vLeaves = Abc_NtkManCutReadCutLarge( pManCut ); + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Abc_NtkStartReverseLevels( pNtk, 0 ); + + // resynthesize each node once + pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk); + nNodes = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // skip the constant node +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + continue; + // skip the nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + continue; + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + // compute a reconvergence-driven cut +clk = clock(); + vFanins = Abc_NodeFindCut( pManCut, pNode, fUseDcs ); +pManRef->timeCut += clock() - clk; + // evaluate this cut +clk = clock(); + pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ); +pManRef->timeRes += clock() - clk; + if ( pFForm == NULL ) + continue; + // acceptable replacement found, update the graph +clk = clock(); + Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRef->nLastGain ); +pManRef->timeNtk += clock() - clk; + Dec_GraphFree( pFForm ); +// { +// extern int s_TotalChanges; +// s_TotalChanges++; +// } + } + Extra_ProgressBarStop( pProgress ); +pManRef->timeTotal = clock() - clkStart; + pManRef->nNodesEnd = Abc_NtkNodeNum(pNtk); + + // print statistics of the manager + if ( fVerbose ) + Abc_NtkManRefPrintStats( pManRef ); + // delete the managers + Abc_NtkManCutStop( pManCut ); + Abc_NtkManRefStop( pManRef ); + // put the nodes into the DFS order and reassign their IDs + Abc_NtkReassignIds( pNtk ); +// Abc_AigCheckFaninOrder( pNtk->pManFunc ); + // fix the levels + if ( fUpdateLevel ) + Abc_NtkStopReverseLevels( pNtk ); + else + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkRefactor: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Resynthesizes the node using refactoring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ) +{ + int fVeryVerbose = 0; + Abc_Obj_t * pFanin; + Dec_Graph_t * pFForm; + DdNode * bNodeFunc; + int nNodesSaved, nNodesAdded, i, clk; + char * pSop; + int Required; + + Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; + + p->nNodesConsidered++; + + // get the function of the cut +clk = clock(); + bNodeFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pNode, vFanins, p->vVisited ); Cudd_Ref( bNodeFunc ); +p->timeBdd += clock() - clk; + + // if don't-care are used, transform the function into ISOP + if ( fUseDcs ) + { + DdNode * bNodeDc, * bNodeOn, * bNodeOnDc; + int nMints, nMintsDc; +clk = clock(); + // get the don't-cares + bNodeDc = Abc_NodeConeDcs( p->dd, p->dd->vars + vFanins->nSize, p->dd->vars, p->vLeaves, vFanins, p->vVisited ); Cudd_Ref( bNodeDc ); + nMints = (1 << vFanins->nSize); + nMintsDc = (int)Cudd_CountMinterm( p->dd, bNodeDc, vFanins->nSize ); +// printf( "Percentage of minterms = %5.2f.\n", 100.0 * nMintsDc / nMints ); + // get the ISF + bNodeOn = Cudd_bddAnd( p->dd, bNodeFunc, Cudd_Not(bNodeDc) ); Cudd_Ref( bNodeOn ); + bNodeOnDc = Cudd_bddOr ( p->dd, bNodeFunc, bNodeDc ); Cudd_Ref( bNodeOnDc ); + Cudd_RecursiveDeref( p->dd, bNodeFunc ); + Cudd_RecursiveDeref( p->dd, bNodeDc ); + // get the ISOP + bNodeFunc = Cudd_bddIsop( p->dd, bNodeOn, bNodeOnDc ); Cudd_Ref( bNodeFunc ); + Cudd_RecursiveDeref( p->dd, bNodeOn ); + Cudd_RecursiveDeref( p->dd, bNodeOnDc ); +p->timeDcs += clock() - clk; + } + + // always accept the case of constant node + if ( Cudd_IsConstant(bNodeFunc) ) + { + p->nLastGain = Abc_NodeMffcSize( pNode ); + p->nNodesGained += p->nLastGain; + p->nNodesRefactored++; + Cudd_RecursiveDeref( p->dd, bNodeFunc ); + if ( Cudd_IsComplement(bNodeFunc) ) + return Dec_GraphCreateConst0(); + return Dec_GraphCreateConst1(); + } + + // get the SOP of the cut +clk = clock(); + pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, 0, p->vCube, -1 ); +p->timeSop += clock() - clk; + + // get the factored form +clk = clock(); + pFForm = Dec_Factor( pSop ); + free( pSop ); +p->timeFact += clock() - clk; + + // mark the fanin boundary + // (can mark only essential fanins, belonging to bNodeFunc!) + Vec_PtrForEachEntry( vFanins, pFanin, i ) + pFanin->vFanouts.nSize++; + // label MFFC with current traversal ID + Abc_NtkIncrementTravId( pNode->pNtk ); + nNodesSaved = Abc_NodeMffcLabelAig( pNode ); + // unmark the fanin boundary and set the fanins as leaves in the form + Vec_PtrForEachEntry( vFanins, pFanin, i ) + { + pFanin->vFanouts.nSize--; + Dec_GraphNode(pFForm, i)->pFunc = pFanin; + } + + // detect how many new nodes will be added (while taking into account reused nodes) +clk = clock(); + nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Required ); +p->timeEval += clock() - clk; + // quit if there is no improvement + if ( nNodesAdded == -1 || nNodesAdded == nNodesSaved && !fUseZeros ) + { + Cudd_RecursiveDeref( p->dd, bNodeFunc ); + Dec_GraphFree( pFForm ); + return NULL; + } + + // compute the total gain in the number of nodes + p->nLastGain = nNodesSaved - nNodesAdded; + p->nNodesGained += p->nLastGain; + p->nNodesRefactored++; + + // report the progress + if ( fVeryVerbose ) + { + printf( "Node %6s : ", Abc_ObjName(pNode) ); + printf( "Cone = %2d. ", vFanins->nSize ); + printf( "BDD = %2d. ", Cudd_DagSize(bNodeFunc) ); + printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pFForm) ); + printf( "MFFC = %2d. ", nNodesSaved ); + printf( "Add = %2d. ", nNodesAdded ); + printf( "GAIN = %2d. ", p->nLastGain ); + printf( "\n" ); + } + Cudd_RecursiveDeref( p->dd, bNodeFunc ); + return pFForm; +} + + +/**Function************************************************************* + + Synopsis [Starts the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose ) +{ + Abc_ManRef_t * p; + p = ALLOC( Abc_ManRef_t, 1 ); + memset( p, 0, sizeof(Abc_ManRef_t) ); + p->vCube = Vec_StrAlloc( 100 ); + p->vVisited = Vec_PtrAlloc( 100 ); + p->nNodeSizeMax = nNodeSizeMax; + p->nConeSizeMax = nConeSizeMax; + p->fVerbose = fVerbose; + // start the BDD manager + if ( fUseDcs ) + p->dd = Cudd_Init( p->nNodeSizeMax + p->nConeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + else + p->dd = Cudd_Init( p->nNodeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_zddVarsFromBddVars( p->dd, 2 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkManRefStop( Abc_ManRef_t * p ) +{ + Extra_StopManager( p->dd ); + Vec_PtrFree( p->vVisited ); + Vec_StrFree( p->vCube ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkManRefPrintStats( Abc_ManRef_t * p ) +{ + printf( "Refactoring statistics:\n" ); + printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); + printf( "Nodes refactored = %8d.\n", p->nNodesRefactored ); + printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg ); + PRT( "Cuts ", p->timeCut ); + PRT( "Resynthesis", p->timeRes ); + PRT( " BDD ", p->timeBdd ); + PRT( " DCs ", p->timeDcs ); + PRT( " SOP ", p->timeSop ); + PRT( " FF ", p->timeFact ); + PRT( " Eval ", p->timeEval ); + PRT( "AIG update ", p->timeNtk ); + PRT( "TOTAL ", p->timeTotal ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRenode.c b/abc70930/src/base/abci/abcRenode.c new file mode 100644 index 00000000..8e8e8719 --- /dev/null +++ b/abc70930/src/base/abci/abcRenode.c @@ -0,0 +1,311 @@ +/**CFile**************************************************************** + + FileName [abcRenode.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRenode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "reo.h" +#include "if.h" +#include "kit.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NtkRenodeEvalAig( If_Cut_t * pCut ); +static int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut ); +static int Abc_NtkRenodeEvalSop( If_Cut_t * pCut ); +static int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut ); +static int Abc_NtkRenodeEvalMv( If_Cut_t * pCut ); + +static reo_man * s_pReo = NULL; +static DdManager * s_pDd = NULL; +static Vec_Int_t * s_vMemory = NULL; +static Vec_Int_t * s_vMemory2 = NULL; + +static int nDsdCounter = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs renoding as technology mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose ) +{ + extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); + If_Par_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtkNew; + + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Performing renoding with choices.\n" ); + + nDsdCounter = 0; + + // set defaults + memset( pPars, 0, sizeof(If_Par_t) ); + // user-controlable paramters + pPars->nLutSize = nFaninMax; + pPars->nCutsMax = nCubeMax; + pPars->nFlowIters = nFlowIters; + pPars->nAreaIters = nAreaIters; + pPars->DelayTarget = -1; + pPars->fPreprocess = 1; + pPars->fArea = fArea; + pPars->fFancy = 0; + pPars->fExpRed = 0; // + pPars->fLatchPaths = 0; + pPars->fSeqMap = 0; + pPars->fVerbose = fVerbose; + // internal parameters + pPars->fTruth = 1; + pPars->fUsePerm = 1; + pPars->nLatches = 0; + pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); + pPars->pTimesArr = NULL; + pPars->pTimesArr = NULL; + pPars->fUseBdds = fUseBdds; + pPars->fUseSops = fUseSops; + pPars->fUseCnfs = fUseCnfs; + pPars->fUseMv = fUseMv; + if ( fUseBdds ) + pPars->pFuncCost = Abc_NtkRenodeEvalBdd; + else if ( fUseSops ) + pPars->pFuncCost = Abc_NtkRenodeEvalSop; + else if ( fUseCnfs ) + { + pPars->fArea = 1; + pPars->pFuncCost = Abc_NtkRenodeEvalCnf; + } + else if ( fUseMv ) + pPars->pFuncCost = Abc_NtkRenodeEvalMv; + else + pPars->pFuncCost = Abc_NtkRenodeEvalAig; + + // start the manager + if ( fUseBdds ) + { + assert( s_pReo == NULL ); + s_pDd = Cudd_Init( nFaninMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + s_pReo = Extra_ReorderInit( nFaninMax, 100 ); + pPars->pReoMan = s_pReo; + } + else + { + assert( s_vMemory == NULL ); + s_vMemory = Vec_IntAlloc( 1 << 16 ); + s_vMemory2 = Vec_IntAlloc( 1 << 16 ); + } + + // perform mapping/renoding + pNtkNew = Abc_NtkIf( pNtk, pPars ); + + // start the manager + if ( fUseBdds ) + { + Extra_StopManager( s_pDd ); + Extra_ReorderQuit( s_pReo ); + s_pReo = NULL; + s_pDd = NULL; + } + else + { + Vec_IntFree( s_vMemory ); + Vec_IntFree( s_vMemory2 ); + s_vMemory = NULL; + s_vMemory2 = NULL; + } + +// printf( "Decomposed %d functions.\n", nDsdCounter ); + + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Computes the cost based on the factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRenodeEvalAig( If_Cut_t * pCut ) +{ + Kit_Graph_t * pGraph; + int i, nNodes; +/* +extern void Kit_DsdTest( unsigned * pTruth, int nVars ); +if ( If_CutLeaveNum(pCut) == 8 ) +{ + nDsdCounter++; + Kit_DsdTest( If_CutTruth(pCut), If_CutLeaveNum(pCut) ); +} +*/ + pGraph = Kit_TruthToGraph( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory ); + if ( pGraph == NULL ) + { + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = 100; + return IF_COST_MAX; + } + nNodes = Kit_GraphNodeNum( pGraph ); + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeLast(pGraph), Kit_GraphNode(pGraph, i) ); + Kit_GraphFree( pGraph ); + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the cost based on the BDD size after reordering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut ) +{ + int pOrder[IF_MAX_LUTSIZE]; + DdNode * bFunc, * bFuncNew; + int i, k, nNodes; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = pOrder[i] = -100; + bFunc = Kit_TruthToBdd( s_pDd, If_CutTruth(pCut), If_CutLeaveNum(pCut), 0 ); Cudd_Ref( bFunc ); + bFuncNew = Extra_Reorder( s_pReo, s_pDd, bFunc, pOrder ); Cudd_Ref( bFuncNew ); + for ( i = k = 0; i < If_CutLeaveNum(pCut); i++ ) + if ( pOrder[i] >= 0 ) + pCut->pPerm[pOrder[i]] = ++k; // double-check this! + nNodes = -1 + Cudd_DagSize( bFuncNew ); + Cudd_RecursiveDeref( s_pDd, bFuncNew ); + Cudd_RecursiveDeref( s_pDd, bFunc ); + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the cost based on ISOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRenodeEvalSop( If_Cut_t * pCut ) +{ + int i, RetValue; + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = 1; + RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 1 ); + if ( RetValue == -1 ) + return IF_COST_MAX; + assert( RetValue == 0 || RetValue == 1 ); + return Vec_IntSize( s_vMemory ); +} + +/**Function************************************************************* + + Synopsis [Computes the cost based on two ISOPs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut ) +{ + int i, RetValue, nClauses; + // set internal mapper parameters + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = 1; + // compute ISOP for the positive phase + RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); + if ( RetValue == -1 ) + return IF_COST_MAX; + assert( RetValue == 0 || RetValue == 1 ); + nClauses = Vec_IntSize( s_vMemory ); + // compute ISOP for the negative phase + Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); + RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); + Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); + if ( RetValue == -1 ) + return IF_COST_MAX; + assert( RetValue == 0 || RetValue == 1 ); + nClauses += Vec_IntSize( s_vMemory ); + return nClauses; +} + +/**Function************************************************************* + + Synopsis [Computes the cost of MV-SOP of the cut function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRenodeEvalMv( If_Cut_t * pCut ) +{ + int i, RetValue; + // set internal mapper parameters + for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) + pCut->pPerm[i] = 1; + // compute ISOP for the positive phase + RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); + if ( RetValue == -1 ) + return IF_COST_MAX; + assert( RetValue == 0 || RetValue == 1 ); + // compute ISOP for the negative phase + Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); + RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory2, 0 ); + Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); + if ( RetValue == -1 ) + return IF_COST_MAX; + assert( RetValue == 0 || RetValue == 1 ); + // return the cost of the cut + RetValue = Abc_NodeEvalMvCost( If_CutLeaveNum(pCut), s_vMemory, s_vMemory2 ); + if ( RetValue >= IF_COST_MAX ) + return IF_COST_MAX; + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcReorder.c b/abc70930/src/base/abci/abcReorder.c new file mode 100644 index 00000000..d6dee49b --- /dev/null +++ b/abc70930/src/base/abci/abcReorder.c @@ -0,0 +1,100 @@ +/**CFile**************************************************************** + + FileName [abcReorder.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Reordering local BDDs of the nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcReorder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "reo.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reorders BDD of the local function of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeBddReorder( reo_man * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + DdNode * bFunc; + int * pOrder, i; + // create the temporary array for the variable order + pOrder = ALLOC( int, Abc_ObjFaninNum(pNode) ); + for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) + pOrder[i] = -1; + // reorder the BDD + bFunc = Extra_Reorder( p, pNode->pNtk->pManFunc, pNode->pData, pOrder ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( pNode->pNtk->pManFunc, pNode->pData ); + pNode->pData = bFunc; + // update the fanin order + Abc_ObjForEachFanin( pNode, pFanin, i ) + pOrder[i] = pNode->vFanins.pArray[ pOrder[i] ]; + Abc_ObjForEachFanin( pNode, pFanin, i ) + pNode->vFanins.pArray[i] = pOrder[i]; + free( pOrder ); +} + +/**Function************************************************************* + + Synopsis [Reorders BDDs of the local functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ) +{ + reo_man * p; + Abc_Obj_t * pNode; + int i; + p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjFaninNum(pNode) < 3 ) + continue; + if ( fVerbose ) + fprintf( stdout, "%10s: ", Abc_ObjName(pNode) ); + if ( fVerbose ) + fprintf( stdout, "Before = %5d BDD nodes. ", Cudd_DagSize(pNode->pData) ); + Abc_NodeBddReorder( p, pNode ); + if ( fVerbose ) + fprintf( stdout, "After = %5d BDD nodes.\n", Cudd_DagSize(pNode->pData) ); + } + Extra_ReorderQuit( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRestruct.c b/abc70930/src/base/abci/abcRestruct.c new file mode 100644 index 00000000..326d1543 --- /dev/null +++ b/abc70930/src/base/abci/abcRestruct.c @@ -0,0 +1,1496 @@ +/**CFile**************************************************************** + + FileName [abcRestruct.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRestruct.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" +#include "dsd.h" +#include "cut.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define RST_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) + +typedef struct Abc_ManRst_t_ Abc_ManRst_t; +struct Abc_ManRst_t_ +{ + // the network + Abc_Ntk_t * pNtk; // the network for restructuring + // user specified parameters + int nCutMax; // the limit on the size of the supernode + int fUpdateLevel; // turns on watching the number of levels + int fUseZeros; // turns on zero-cost replacements + int fVerbose; // the verbosity flag + // internal data structures + DdManager * dd; // the BDD manager + Dsd_Manager_t * pManDsd; // the DSD manager + Vec_Ptr_t * vVisited; // temporary + Vec_Ptr_t * vLeaves; // temporary + Vec_Ptr_t * vDecs; // temporary + Vec_Ptr_t * vTemp; // temporary + Vec_Int_t * vSims; // temporary + Vec_Int_t * vRands; // temporary + Vec_Int_t * vOnes; // temporary + Vec_Int_t * vBinate; // temporary + Vec_Int_t * vTwos; // temporary + // node statistics + int nLastGain; + int nCutsConsidered; + int nCutsExplored; + int nNodesConsidered; + int nNodesRestructured; + int nNodesGained; + // runtime statistics + int timeCut; + int timeBdd; + int timeDsd; + int timeEval; + int timeRes; + int timeNtk; + int timeTotal; +}; + +static Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ); + +static Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ); +static Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCut ); +static Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded ); + +static Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag ); +static Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ); +static void Abc_NtkManRstStop( Abc_ManRst_t * p ); +static void Abc_NtkManRstPrintStats( Abc_ManRst_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Implements AIG restructuring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ) +{ + ProgressBar * pProgress; + Abc_ManRst_t * pManRst; + Cut_Man_t * pManCut; + Cut_Cut_t * pCutList; + Dec_Graph_t * pGraph; + Abc_Obj_t * pNode; + int clk, clkStart = clock(); + int fMulti = 1; + int fResub = 0; + int i, nNodes; + + assert( Abc_NtkIsStrash(pNtk) ); + // cleanup the AIG + Abc_AigCleanup(pNtk->pManFunc); + Abc_NtkCleanCopy(pNtk); + + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Abc_NtkStartReverseLevels( pNtk, 0 ); + + // start the restructuring manager + pManRst = Abc_NtkManRstStart( nCutMax, fUpdateLevel, fUseZeros, fVerbose ); + pManRst->pNtk = pNtk; + // start the cut manager +clk = clock(); + pManCut = Abc_NtkStartCutManForRestruct( pNtk, nCutMax, fMulti ); +pManRst->timeCut += clock() - clk; +// pNtk->pManCut = pManCut; + + // resynthesize each node once + nNodes = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // skip the constant node +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + continue; + // skip the node if it is inside the tree +// if ( Abc_ObjFanoutNum(pNode) < 2 ) +// continue; + // skip the nodes with too many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + continue; + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + // get the cuts for the given node +clk = clock(); + pCutList = Abc_NodeGetCutsRecursive( pManCut, pNode, fMulti, 0 ); +pManRst->timeCut += clock() - clk; + + // perform restructuring +clk = clock(); + if ( fResub ) + pGraph = Abc_NodeResubstitute( pManRst, pNode, pCutList ); + else + pGraph = Abc_NodeRestructure( pManRst, pNode, pCutList ); +pManRst->timeRes += clock() - clk; + if ( pGraph == NULL ) + continue; + + // acceptable replacement found, update the graph +clk = clock(); + Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, pManRst->nLastGain ); +pManRst->timeNtk += clock() - clk; + Dec_GraphFree( pGraph ); + } + Extra_ProgressBarStop( pProgress ); +pManRst->timeTotal = clock() - clkStart; + + // print statistics of the manager +// if ( fVerbose ) + Abc_NtkManRstPrintStats( pManRst ); + // delete the managers + Cut_ManStop( pManCut ); + Abc_NtkManRstStop( pManRst ); + // put the nodes into the DFS order and reassign their IDs + Abc_NtkReassignIds( pNtk ); +// Abc_AigCheckFaninOrder( pNtk->pManFunc ); + // fix the levels + if ( fUpdateLevel ) + Abc_NtkStopReverseLevels( pNtk ); + else + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkRefactor: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RestructNodeDivisors( Abc_ManRst_t * p, Abc_Obj_t * pRoot, int nNodesSaved ) +{ + Abc_Obj_t * pNode, * pFanout;//, * pFanin; + int i, k; + // start with the leaves + Vec_PtrClear( p->vDecs ); + Vec_PtrForEachEntry( p->vLeaves, pNode, i ) + { + Vec_PtrPush( p->vDecs, pNode ); + assert( pNode->fMarkC == 0 ); + pNode->fMarkC = 1; + } + // explore the fanouts + Vec_PtrForEachEntry( p->vDecs, pNode, i ) + { + // if the fanout has both fanins in the set, add it + Abc_ObjForEachFanout( pNode, pFanout, k ) + { + if ( pFanout->fMarkC || Abc_ObjIsPo(pFanout) ) + continue; + if ( Abc_ObjFanin0(pFanout)->fMarkC && Abc_ObjFanin1(pFanout)->fMarkC ) + { + Vec_PtrPush( p->vDecs, pFanout ); + pFanout->fMarkC = 1; + } + } + } + // unmark the nodes + Vec_PtrForEachEntry( p->vDecs, pNode, i ) + pNode->fMarkC = 0; +/* + // print the nodes + Vec_PtrForEachEntryStart( p->vDecs, pNode, i, Vec_PtrSize(p->vLeaves) ) + { + printf( "%2d %s = ", i, Abc_NodeIsTravIdCurrent(pNode)? "*" : " " ); + // find the first fanin + Vec_PtrForEachEntry( p->vDecs, pFanin, k ) + if ( Abc_ObjFanin0(pNode) == pFanin ) + break; + if ( k < Vec_PtrSize(p->vLeaves) ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); + // find the second fanin + Vec_PtrForEachEntry( p->vDecs, pFanin, k ) + if ( Abc_ObjFanin1(pNode) == pFanin ) + break; + if ( k < Vec_PtrSize(p->vLeaves) ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); + printf( "\n" ); + } +*/ + printf( "%d\n", Vec_PtrSize(p->vDecs)-nNodesSaved-Vec_PtrSize(p->vLeaves) ); +} + + +/**Function************************************************************* + + Synopsis [Starts the cut manager for rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ) +{ + Dec_Graph_t * pGraph; + Cut_Cut_t * pCut; +// int nCuts; + p->nNodesConsidered++; +/* + // count the number of cuts with four inputs or more + nCuts = 0; + for ( pCut = pCutList; pCut; pCut = pCut->pNext ) + nCuts += (int)(pCut->nLeaves > 3); + printf( "-----------------------------------\n" ); + printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts ); +*/ + // go through the interesting cuts + for ( pCut = pCutList; pCut; pCut = pCut->pNext ) + { + if ( pCut->nLeaves < 4 ) + continue; + if ( pGraph = Abc_NodeRestructureCut( p, pNode, pCut ) ) + return pGraph; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Starts the cut manager for rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) +{ + Dec_Graph_t * pGraph; + Dsd_Node_t * pNodeDsd; + Abc_Obj_t * pLeaf; + DdNode * bFunc; + int nNodesSaved, nNodesAdded; + int Required, nMaxSize, clk, i; + int fVeryVerbose = 0; + + p->nCutsConsidered++; + + // get the required time for the node + Required = p->fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY; + + // collect the leaves of the cut + Vec_PtrClear( p->vLeaves ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + pLeaf = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]); + if ( pLeaf == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes + return NULL; + Vec_PtrPush( p->vLeaves, pLeaf ); + } + + if ( pRoot->Id == 29 ) + { + int x = 0; + } + +clk = clock(); + // collect the internal nodes of the cut +// Abc_NodeConeCollect( &pRoot, 1, p->vLeaves, p->vVisited, 0 ); + // derive the BDD of the cut + bFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pRoot, p->vLeaves, p->vVisited ); Cudd_Ref( bFunc ); +p->timeBdd += clock() - clk; + + // consider the special case, when the function is a constant + if ( Cudd_IsConstant(bFunc) ) + { + p->nLastGain = Abc_NodeMffcSize( pRoot ); + p->nNodesGained += p->nLastGain; + p->nNodesRestructured++; + Cudd_RecursiveDeref( p->dd, bFunc ); + if ( Cudd_IsComplement(bFunc) ) + return Dec_GraphCreateConst0(); + return Dec_GraphCreateConst1(); + } + +clk = clock(); + // try disjoint support decomposition + pNodeDsd = Dsd_DecomposeOne( p->pManDsd, bFunc ); +p->timeDsd += clock() - clk; + + // skip nodes with non-decomposable blocks + Dsd_TreeNodeGetInfoOne( pNodeDsd, NULL, &nMaxSize ); + if ( nMaxSize > 3 ) + { + Cudd_RecursiveDeref( p->dd, bFunc ); + return NULL; + } + + +/* + // skip nodes that cannot be improved + if ( Vec_PtrSize(p->vVisited) <= Dsd_TreeGetAigCost(pNodeDsd) ) + { + Cudd_RecursiveDeref( p->dd, bFunc ); + return NULL; + } +*/ + + p->nCutsExplored++; + + // mark the fanin boundary + // (can mark only essential fanins, belonging to bNodeFunc!) + Vec_PtrForEachEntry( p->vLeaves, pLeaf, i ) + pLeaf->vFanouts.nSize++; + // label MFFC with current traversal ID + Abc_NtkIncrementTravId( pRoot->pNtk ); + nNodesSaved = Abc_NodeMffcLabelAig( pRoot ); + // unmark the fanin boundary and set the fanins as leaves in the form + Vec_PtrForEachEntry( p->vLeaves, pLeaf, i ) + pLeaf->vFanouts.nSize--; +/* + if ( nNodesSaved < 3 ) + { + Cudd_RecursiveDeref( p->dd, bFunc ); + return NULL; + } +*/ + +/* + printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d.\n", + pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd), + nNodesSaved ); + Dsd_NodePrint( stdout, pNodeDsd ); + + Abc_RestructNodeDivisors( p, pRoot ); + + if ( pRoot->Id == 433 ) + { + int x = 0; + } +*/ +// Abc_RestructNodeDivisors( p, pRoot, nNodesSaved ); + + + // detect how many new nodes will be added (while taking into account reused nodes) +clk = clock(); + if ( nMaxSize > 3 ) + pGraph = NULL; + else + pGraph = Abc_NodeEvaluateDsd( p, pNodeDsd, pRoot, Required, nNodesSaved, &nNodesAdded ); +// pGraph = NULL; +p->timeEval += clock() - clk; + + // quit if there is no improvement + if ( pGraph == NULL || nNodesAdded == -1 || nNodesAdded == nNodesSaved && !p->fUseZeros ) + { + Cudd_RecursiveDeref( p->dd, bFunc ); + if ( pGraph ) Dec_GraphFree( pGraph ); + return NULL; + } + +/* + // print stats + printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d. New MFFC = %2d. Gain = %d.\n", + pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd), + nNodesSaved, nNodesAdded, (nNodesAdded == -1)? 0 : nNodesSaved-nNodesAdded ); +// Dsd_NodePrint( stdout, pNodeDsd ); +// Dec_GraphPrint( stdout, pGraph, NULL, NULL ); +*/ + + // compute the total gain in the number of nodes + p->nLastGain = nNodesSaved - nNodesAdded; + p->nNodesGained += p->nLastGain; + p->nNodesRestructured++; + + // report the progress + if ( fVeryVerbose ) + { + printf( "Node %6s : ", Abc_ObjName(pRoot) ); + printf( "Cone = %2d. ", p->vLeaves->nSize ); + printf( "BDD = %2d. ", Cudd_DagSize(bFunc) ); + printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pGraph) ); + printf( "MFFC = %2d. ", nNodesSaved ); + printf( "Add = %2d. ", nNodesAdded ); + printf( "GAIN = %2d. ", p->nLastGain ); + printf( "\n" ); + } + Cudd_RecursiveDeref( p->dd, bFunc ); + return pGraph; +} + + +/**Function************************************************************* + + Synopsis [Moves closer to the end the node that is best for sharing.] + + Description [If the flag is set, tries to find an EXOR, otherwise, tries + to find an OR.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeEdgeDsdPermute( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Vec_Int_t * vEdges, int fExor ) +{ + Dec_Edge_t eNode1, eNode2, eNode3; + Abc_Obj_t * pNode1, * pNode2, * pNode3, * pTemp; + int LeftBound = 0, RightBound, i; + // get the right bound + RightBound = Vec_IntSize(vEdges) - 2; + assert( LeftBound <= RightBound ); + if ( LeftBound == RightBound ) + return; + // get the two last nodes + eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound + 1) ); + eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound ) ); + pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; + pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); + pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); + // quit if the last node does not exist + if ( pNode1 == NULL ) + return; + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + // get the third node + eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, i) ); + pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc; + pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl ); + if ( pNode3 == NULL ) + continue; + // check if the node exists + if ( fExor ) + { + if ( pNode1 && pNode3 ) + { + pTemp = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode3, NULL ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + continue; + + if ( pNode3 == pNode2 ) + return; + Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) ); + Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) ); + return; + } + } + else + { + if ( pNode1 && pNode3 ) + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + continue; + + if ( eNode3.Node == eNode2.Node ) + return; + Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) ); + Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) ); + return; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Adds the new edge in the given order.] + + Description [Similar to Vec_IntPushOrder, except in decreasing order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeEdgeDsdPushOrdered( Dec_Graph_t * pGraph, Vec_Int_t * vEdges, int Edge ) +{ + int i, NodeOld, NodeNew; + vEdges->nSize++; + for ( i = vEdges->nSize-2; i >= 0; i-- ) + { + NodeOld = Dec_IntToEdge(vEdges->pArray[i]).Node; + NodeNew = Dec_IntToEdge(Edge).Node; + // use <= because we are trying to push the new (non-existent) nodes as far as possible + if ( Dec_GraphNode(pGraph, NodeOld)->Level <= Dec_GraphNode(pGraph, NodeNew)->Level ) + vEdges->pArray[i+1] = vEdges->pArray[i]; + else + break; + } + vEdges->pArray[i+1] = Edge; +} + +/**Function************************************************************* + + Synopsis [Evaluation one DSD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Abc_NodeEvaluateDsd_rec( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, int Required, int nNodesSaved, int * pnNodesAdded ) +{ + Dec_Edge_t eNode1, eNode2, eNode3, eResult, eQuit = { 0, 2006 }; + Abc_Obj_t * pNode1, * pNode2, * pNode3, * pNode4, * pTemp; + Dsd_Node_t * pChildDsd; + Dsd_Type_t DecType; + Vec_Int_t * vEdges; + int Level1, Level2, Level3, Level4; + int i, Index, fCompl, Type; + + // remove the complemented attribute + fCompl = Dsd_IsComplement( pNodeDsd ); + pNodeDsd = Dsd_Regular( pNodeDsd ); + + // consider the trivial case + DecType = Dsd_NodeReadType( pNodeDsd ); + if ( DecType == DSD_NODE_BUF ) + { + Index = Dsd_NodeReadFunc(pNodeDsd)->index; + assert( Index < Dec_GraphLeaveNum(pGraph) ); + eResult = Dec_EdgeCreate( Index, fCompl ); + return eResult; + } + assert( DecType == DSD_NODE_OR || DecType == DSD_NODE_EXOR || DecType == DSD_NODE_PRIME ); + + // solve the problem for the children + vEdges = Vec_IntAlloc( Dsd_NodeReadDecsNum(pNodeDsd) ); + Dsd_NodeForEachChild( pNodeDsd, i, pChildDsd ) + { + eResult = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pChildDsd, Required, nNodesSaved, pnNodesAdded ); + if ( eResult.Node == eQuit.Node ) // infeasible + { + Vec_IntFree( vEdges ); + return eQuit; + } + // order the inputs only if this is OR or EXOR + if ( DecType == DSD_NODE_PRIME ) + Vec_IntPush( vEdges, Dec_EdgeToInt(eResult) ); + else + Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eResult) ); + } + // the edges are sorted by the level of their nodes in decreasing order + + + // consider special cases + if ( DecType == DSD_NODE_OR ) + { + // try to balance the nodes by delay + assert( Vec_IntSize(vEdges) > 1 ); + while ( Vec_IntSize(vEdges) > 1 ) + { + // permute the last two entries + if ( Vec_IntSize(vEdges) > 2 ) + Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 0 ); + // get the two last nodes + eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) ); + eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) ); + pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; + pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); + pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); + // check if the new node exists + pNode3 = NULL; + if ( pNode1 && pNode2 ) + { + pNode3 = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + pNode3 = !pNode3? NULL : Abc_ObjNot(pNode3); + } + // create the new node + eNode3 = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 ); + // set level + Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; + Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; + Dec_GraphNode( pGraph, eNode3.Node )->Level = 1 + ABC_MAX(Level1, Level2); + // get the new node if possible + if ( pNode3 ) + { + Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl); + Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; + assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level ); + } + if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) ) + { + (*pnNodesAdded)++; + if ( *pnNodesAdded > nNodesSaved ) + { + Vec_IntFree( vEdges ); + return eQuit; + } + } + // add the resulting node to the form + Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) ); + } + // get the last node + eResult = Dec_IntToEdge( Vec_IntPop(vEdges) ); + Vec_IntFree( vEdges ); + // complement the graph if the node was complemented + eResult.fCompl ^= fCompl; + return eResult; + } + if ( DecType == DSD_NODE_EXOR ) + { + // try to balance the nodes by delay + assert( Vec_IntSize(vEdges) > 1 ); + while ( Vec_IntSize(vEdges) > 1 ) + { + // permute the last two entries + if ( Vec_IntSize(vEdges) > 2 ) + Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 1 ); + // get the two last nodes + eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) ); + eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) ); + pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; + pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); + pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); + // check if the new node exists + Type = 0; + pNode3 = NULL; + if ( pNode1 && pNode2 ) + pNode3 = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, &Type ); + // create the new node + eNode3 = Dec_GraphAddNodeXor( pGraph, eNode1, eNode2, Type ); // should have the same structure as in AIG + // set level + Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; + Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; + Dec_GraphNode( pGraph, eNode3.Node )->Level = 2 + ABC_MAX(Level1, Level2); + // get the new node if possible + if ( pNode3 ) + { + Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl); + Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; + assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level ); + } + if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) ) + { + (*pnNodesAdded)++; + if ( !pNode1 || !pNode2 ) + (*pnNodesAdded) += 2; + else if ( Type == 0 ) + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode2 ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + if ( *pnNodesAdded > nNodesSaved ) + { + Vec_IntFree( vEdges ); + return eQuit; + } + } + // add the resulting node to the form + Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) ); + } + // get the last node + eResult = Dec_IntToEdge( Vec_IntPop(vEdges) ); + Vec_IntFree( vEdges ); + // complement the graph if the node is complemented + eResult.fCompl ^= fCompl; + return eResult; + } + if ( DecType == DSD_NODE_PRIME ) + { + DdNode * bLocal, * bVar, * bCofT, * bCofE; + bLocal = Dsd_TreeGetPrimeFunction( pManRst->dd, pNodeDsd ); Cudd_Ref( bLocal ); +//Extra_bddPrint( pManRst->dd, bLocal ); + + bVar = pManRst->dd->vars[0]; + bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); + bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); + if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) + { + Cudd_RecursiveDeref( pManRst->dd, bCofE ); + Cudd_RecursiveDeref( pManRst->dd, bCofT ); + bVar = pManRst->dd->vars[1]; + bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); + bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); + if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) + { + Cudd_RecursiveDeref( pManRst->dd, bCofE ); + Cudd_RecursiveDeref( pManRst->dd, bCofT ); + bVar = pManRst->dd->vars[2]; + bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); + bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); + if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) + { + Cudd_RecursiveDeref( pManRst->dd, bCofE ); + Cudd_RecursiveDeref( pManRst->dd, bCofT ); + Cudd_RecursiveDeref( pManRst->dd, bLocal ); + Vec_IntFree( vEdges ); + return eQuit; + } + } + } + Cudd_RecursiveDeref( pManRst->dd, bLocal ); + // we found the control variable (bVar) and the var-cofactors (bCofT, bCofE) + + // find the graph nodes + eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, bVar->index) ); + eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofT)->index) ); + eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofE)->index) ); + // add the complements to the graph nodes + eNode2.fCompl ^= Cudd_IsComplement(bCofT); + eNode3.fCompl ^= Cudd_IsComplement(bCofE); + + // because the cofactors are vars, we can just as well deref them here + Cudd_RecursiveDeref( pManRst->dd, bCofE ); + Cudd_RecursiveDeref( pManRst->dd, bCofT ); + + // find the ABC nodes + pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; + pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; + pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc; + pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); + pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); + pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl ); + + // check if the new node exists + Type = 0; + pNode4 = NULL; + if ( pNode1 && pNode2 && pNode3 ) + pNode4 = Abc_AigMuxLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, pNode3, &Type ); + + // create the new node + eResult = Dec_GraphAddNodeMux( pGraph, eNode1, eNode2, eNode3, Type ); // should have the same structure as AIG + + // set level + Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; + Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; + Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; + Dec_GraphNode( pGraph, eResult.Node )->Level = 2 + ABC_MAX( ABC_MAX(Level1, Level2), Level3 ); + // get the new node if possible + if ( pNode4 ) + { + Dec_GraphNode( pGraph, eResult.Node )->pFunc = Abc_ObjNotCond(pNode4, eResult.fCompl); + Level4 = Dec_GraphNode( pGraph, eResult.Node )->Level; + assert( Required == ABC_INFINITY || Level4 == (int)Abc_ObjRegular(pNode4)->Level ); + } + if ( !pNode4 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode4)) ) + { + (*pnNodesAdded)++; + if ( Type == 0 ) + { + if ( !pNode1 || !pNode2 ) + (*pnNodesAdded)++; + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + if ( !pNode1 || !pNode3 ) + (*pnNodesAdded)++; + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode3 ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + } + else + { + if ( !pNode1 || !pNode2 ) + (*pnNodesAdded)++; + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + if ( !pNode1 || !pNode3 ) + (*pnNodesAdded)++; + else + { + pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) ); + if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) + (*pnNodesAdded)++; + } + } + if ( *pnNodesAdded > nNodesSaved ) + { + Vec_IntFree( vEdges ); + return eQuit; + } + } + + Vec_IntFree( vEdges ); + // complement the graph if the node was complemented + eResult.fCompl ^= fCompl; + return eResult; + } + Vec_IntFree( vEdges ); + return eQuit; +} + +/**Function************************************************************* + + Synopsis [Evaluation one DSD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t gEdge; + Abc_Obj_t * pLeaf; + Dec_Node_t * pNode; + int i; + + // create the graph and set the leaves + pGraph = Dec_GraphCreate( Vec_PtrSize(pManRst->vLeaves) ); + Dec_GraphForEachLeaf( pGraph, pNode, i ) + { + pLeaf = Vec_PtrEntry( pManRst->vLeaves, i ); + pNode->pFunc = pLeaf; + pNode->Level = pLeaf->Level; + } + + // create the decomposition structure from the DSD + *pnNodesAdded = 0; + gEdge = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pNodeDsd, Required, nNodesSaved, pnNodesAdded ); + if ( gEdge.Node > 1000 ) // infeasible + { + *pnNodesAdded = -1; + Dec_GraphFree( pGraph ); + return NULL; + } + + // quit if the root node is the same + pLeaf = Dec_GraphNode( pGraph, gEdge.Node )->pFunc; + if ( Abc_ObjRegular(pLeaf) == pRoot ) + { + *pnNodesAdded = -1; + Dec_GraphFree( pGraph ); + return NULL; + } + + Dec_GraphSetRoot( pGraph, gEdge ); + return pGraph; +} + + + +/**Function************************************************************* + + Synopsis [Starts the cut manager for rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag ) +{ + static Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pManCut; + Abc_Obj_t * pObj; + int i; + // start the cut manager + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = nCutMax; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 250; // the max number of cuts kept at a node + pParams->fTruth = 0; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fSeq = 0; // compute sequential cuts + pParams->fDrop = 0; // drop cuts on the fly + pParams->fDag = fDag; // compute DAG cuts + pParams->fTree = 0; // compute tree cuts + pParams->fVerbose = 0; // the verbosiness flag + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + pManCut = Cut_ManStart( pParams ); + if ( pParams->fDrop ) + Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( pManCut, pObj->Id ); + return pManCut; +} + +/**Function************************************************************* + + Synopsis [Starts the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ) +{ + Abc_ManRst_t * p; + p = ALLOC( Abc_ManRst_t, 1 ); + memset( p, 0, sizeof(Abc_ManRst_t) ); + // set the parameters + p->nCutMax = nCutMax; + p->fUpdateLevel = fUpdateLevel; + p->fUseZeros = fUseZeros; + p->fVerbose = fVerbose; + // start the BDD manager + p->dd = Cudd_Init( p->nCutMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_zddVarsFromBddVars( p->dd, 2 ); + // start the DSD manager + p->pManDsd = Dsd_ManagerStart( p->dd, p->dd->size, 0 ); + // other temp datastructures + p->vVisited = Vec_PtrAlloc( 100 ); + p->vLeaves = Vec_PtrAlloc( 100 ); + p->vDecs = Vec_PtrAlloc( 100 ); + p->vTemp = Vec_PtrAlloc( 100 ); + p->vSims = Vec_IntAlloc( 100 ); + p->vOnes = Vec_IntAlloc( 100 ); + p->vBinate = Vec_IntAlloc( 100 ); + p->vTwos = Vec_IntAlloc( 100 ); + p->vRands = Vec_IntAlloc( 20 ); + + { + int i; + for ( i = 0; i < 20; i++ ) + Vec_IntPush( p->vRands, (int)RST_RANDOM_UNSIGNED ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkManRstStop( Abc_ManRst_t * p ) +{ + Dsd_ManagerStop( p->pManDsd ); + Extra_StopManager( p->dd ); + Vec_PtrFree( p->vDecs ); + Vec_PtrFree( p->vLeaves ); + Vec_PtrFree( p->vVisited ); + Vec_PtrFree( p->vTemp ); + Vec_IntFree( p->vSims ); + Vec_IntFree( p->vOnes ); + Vec_IntFree( p->vBinate ); + Vec_IntFree( p->vTwos ); + Vec_IntFree( p->vRands ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkManRstPrintStats( Abc_ManRst_t * p ) +{ + printf( "Refactoring statistics:\n" ); + printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); + printf( "Cuts considered = %8d.\n", p->nCutsConsidered ); + printf( "Cuts explored = %8d.\n", p->nCutsExplored ); + printf( "Nodes restructured = %8d.\n", p->nNodesRestructured ); + printf( "Calculated gain = %8d.\n", p->nNodesGained ); + PRT( "Cuts ", p->timeCut ); + PRT( "Resynthesis", p->timeRes ); + PRT( " BDD ", p->timeBdd ); + PRT( " DSD ", p->timeDsd ); + PRT( " Eval ", p->timeEval ); + PRT( "AIG update ", p->timeNtk ); + PRT( "TOTAL ", p->timeTotal ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_Abc_NodeResubCollectDivs( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) +{ + Abc_Obj_t * pNode, * pFanout; + int i, k; + // collect the leaves of the cut + Vec_PtrClear( p->vDecs ); + Abc_NtkIncrementTravId( pRoot->pNtk ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + pNode = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]); + if ( pNode == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes + return 0; + Vec_PtrPush( p->vDecs, pNode ); + Abc_NodeSetTravIdCurrent( pNode ); + } + // explore the fanouts + Vec_PtrForEachEntry( p->vDecs, pNode, i ) + { + // if the fanout has both fanins in the set, add it + Abc_ObjForEachFanout( pNode, pFanout, k ) + { + if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsPo(pFanout) ) + continue; + if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) ) + { + Vec_PtrPush( p->vDecs, pFanout ); + Abc_NodeSetTravIdCurrent( pFanout ); + } + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeResubMffc_rec( Abc_Obj_t * pNode ) +{ + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return 0; + Abc_NodeSetTravIdCurrent( pNode ); + return 1 + Abc_NodeResubMffc_rec( Abc_ObjFanin0(pNode) ) + + Abc_NodeResubMffc_rec( Abc_ObjFanin1(pNode) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeResubMffc( Abc_ManRst_t * p, Vec_Ptr_t * vDecs, int nLeaves, Abc_Obj_t * pRoot ) +{ + Abc_Obj_t * pObj; + int Counter, i, k; + // increment the traversal ID for the leaves + Abc_NtkIncrementTravId( pRoot->pNtk ); + // label the leaves + Vec_PtrForEachEntryStop( vDecs, pObj, i, nLeaves ) + Abc_NodeSetTravIdCurrent( pObj ); + // make sure the node is in the cone and is no one of the leaves + assert( Abc_NodeIsTravIdPrevious(pRoot) ); + Counter = Abc_NodeResubMffc_rec( pRoot ); + // move the labeled nodes to the end + Vec_PtrClear( p->vTemp ); + k = 0; + Vec_PtrForEachEntryStart( vDecs, pObj, i, nLeaves ) + if ( Abc_NodeIsTravIdCurrent(pObj) ) + Vec_PtrPush( p->vTemp, pObj ); + else + Vec_PtrWriteEntry( vDecs, k++, pObj ); + // add the labeled nodes + Vec_PtrForEachEntry( p->vTemp, pObj, i ) + Vec_PtrWriteEntry( vDecs, k++, pObj ); + assert( k == Vec_PtrSize(p->vDecs) ); + assert( pRoot == Vec_PtrEntryLast(p->vDecs) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Performs simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffcSimulate( Vec_Ptr_t * vDecs, int nLeaves, Vec_Int_t * vRands, Vec_Int_t * vSims ) +{ + Abc_Obj_t * pObj; + unsigned uData0, uData1, uData; + int i; + // initialize random simulation data + Vec_IntClear( vSims ); + Vec_PtrForEachEntryStop( vDecs, pObj, i, nLeaves ) + { + uData = (unsigned)Vec_IntEntry( vRands, i ); + pObj->pData = (void *)uData; + Vec_IntPush( vSims, uData ); + } + // simulate + Vec_PtrForEachEntryStart( vDecs, pObj, i, nLeaves ) + { + uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; + uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData; + uData = (Abc_ObjFaninC0(pObj)? ~uData0 : uData0) & (Abc_ObjFaninC1(pObj)? ~uData1 : uData1); + pObj->pData = (void *)uData; + Vec_IntPush( vSims, uData ); + } +} + +/**Function************************************************************* + + Synopsis [Full equality check.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCheckFull( Abc_ManRst_t * p, Dec_Graph_t * pGraph ) +{ + return 1; +} +/**Function************************************************************* + + Synopsis [Detect contants.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeMffcConstants( Abc_ManRst_t * p, Vec_Int_t * vSims ) +{ + Dec_Graph_t * pGraph; + unsigned uRoot; + // get the root node + uRoot = (unsigned)Vec_IntEntryLast( vSims ); + // get the graph if the node looks constant + if ( uRoot == 0 ) + pGraph = Dec_GraphCreateConst0(); + else if ( uRoot == ~(unsigned)0 ) + pGraph = Dec_GraphCreateConst1(); + // check the graph + if ( Abc_NodeCheckFull( p, pGraph ) ) + return pGraph; + Dec_GraphFree( pGraph ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Detect single non-overlaps.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeMffcSingleVar( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) +{ + Dec_Graph_t * pGraph; + unsigned uRoot, uNode; + int i; + + Vec_IntClear( vOnes ); + Vec_IntClear( p->vBinate ); + uRoot = (unsigned)Vec_IntEntryLast( vSims ); + for ( i = 0; i < nNodes; i++ ) + { + uNode = (unsigned)Vec_IntEntry( vSims, i ); + if ( uRoot == uNode || uRoot == ~uNode ) + { + pGraph = Dec_GraphCreate( 1 ); + Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, i ); + Dec_GraphSetRoot( pGraph, Dec_IntToEdge( (int)(uRoot == ~uNode) ) ); + // check the graph + if ( Abc_NodeCheckFull( p, pGraph ) ) + return pGraph; + Dec_GraphFree( pGraph ); + } + if ( (uRoot & uNode) == 0 ) + Vec_IntPush( vOnes, i << 1 ); + else if ( (uRoot & ~uNode) == 0 ) + Vec_IntPush( vOnes, (i << 1) + 1 ); + else + Vec_IntPush( p->vBinate, i ); + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Detect single non-overlaps.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeMffcSingleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eNode0, eNode1, eRoot; + unsigned uRoot; + int i, k; + uRoot = (unsigned)Vec_IntEntryLast( vSims ); + for ( i = 0; i < vOnes->nSize; i++ ) + for ( k = i+1; k < vOnes->nSize; k++ ) + if ( ~uRoot == ((unsigned)vOnes->pArray[i] | (unsigned)vOnes->pArray[k]) ) + { + eNode0 = Dec_IntToEdge( vOnes->pArray[i] ^ 1 ); + eNode1 = Dec_IntToEdge( vOnes->pArray[k] ^ 1 ); + pGraph = Dec_GraphCreate( 2 ); + Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, eNode0.Node ); + Dec_GraphNode( pGraph, 1 )->pFunc = Vec_PtrEntry( p->vDecs, eNode1.Node ); + eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); + Dec_GraphSetRoot( pGraph, eRoot ); + if ( Abc_NodeCheckFull( p, pGraph ) ) + return pGraph; + Dec_GraphFree( pGraph ); + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Detect single non-overlaps.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeMffcDoubleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) +{ +// Dec_Graph_t * pGraph; +// unsigned uRoot, uNode; +// int i; + + + return NULL; +} + +/**Function************************************************************* + + Synopsis [Evaluates resubstution of one cut.] + + Description [Returns the graph to add if any.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeResubEval( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) +{ + Dec_Graph_t * pGraph; + int nNodesSaved; + + // collect the nodes in the cut + if ( !Abc_Abc_NodeResubCollectDivs( p, pRoot, pCut ) ) + return NULL; + + // label MFFC and count its size + nNodesSaved = Abc_NodeResubMffc( p, p->vDecs, pCut->nLeaves, pRoot ); + assert( nNodesSaved > 0 ); + + // simulate MFFC + Abc_NodeMffcSimulate( p->vDecs, pCut->nLeaves, p->vRands, p->vSims ); + + // check for constant output + pGraph = Abc_NodeMffcConstants( p, p->vSims ); + if ( pGraph ) + { + p->nNodesGained += nNodesSaved; + p->nNodesRestructured++; + return pGraph; + } + + // check for one literal (fill up the ones array) + pGraph = Abc_NodeMffcSingleVar( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); + if ( pGraph ) + { + p->nNodesGained += nNodesSaved; + p->nNodesRestructured++; + return pGraph; + } + if ( nNodesSaved == 1 ) + return NULL; + + // look for one node + pGraph = Abc_NodeMffcSingleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); + if ( pGraph ) + { + p->nNodesGained += nNodesSaved - 1; + p->nNodesRestructured++; + return pGraph; + } + if ( nNodesSaved == 2 ) + return NULL; + + // look for two nodes + pGraph = Abc_NodeMffcDoubleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); + if ( pGraph ) + { + p->nNodesGained += nNodesSaved - 2; + p->nNodesRestructured++; + return pGraph; + } + if ( nNodesSaved == 3 ) + return NULL; +/* + // look for MUX/EXOR + pGraph = Abc_NodeMffcMuxNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved ); + if ( pGraph ) + { + p->nNodesGained += nNodesSaved - 1; + p->nNodesRestructured++; + return pGraph; + } +*/ + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs resubstution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ) +{ + Dec_Graph_t * pGraph, * pGraphBest = NULL; + Cut_Cut_t * pCut; + int nCuts; + p->nNodesConsidered++; + + // count the number of cuts with four inputs or more + nCuts = 0; + for ( pCut = pCutList; pCut; pCut = pCut->pNext ) + nCuts += (int)(pCut->nLeaves > 3); + printf( "-----------------------------------\n" ); + printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts ); + + // go through the interesting cuts + for ( pCut = pCutList; pCut; pCut = pCut->pNext ) + { + if ( pCut->nLeaves < 4 ) + continue; + pGraph = Abc_NodeResubEval( p, pNode, pCut ); + if ( pGraph == NULL ) + continue; + if ( !pGraphBest || Dec_GraphNodeNum(pGraph) < Dec_GraphNodeNum(pGraphBest) ) + { + if ( pGraphBest ) + Dec_GraphFree(pGraphBest); + pGraphBest = pGraph; + } + else + Dec_GraphFree(pGraph); + } + return pGraphBest; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcResub.c b/abc70930/src/base/abci/abcResub.c new file mode 100644 index 00000000..309c328d --- /dev/null +++ b/abc70930/src/base/abci/abcResub.c @@ -0,0 +1,1951 @@ +/**CFile**************************************************************** + + FileName [abcResub.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Resubstitution manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_RS_DIV1_MAX 150 // the max number of divisors to consider +#define ABC_RS_DIV2_MAX 500 // the max number of pair-wise divisors to consider + +typedef struct Abc_ManRes_t_ Abc_ManRes_t; +struct Abc_ManRes_t_ +{ + // paramers + int nLeavesMax; // the max number of leaves in the cone + int nDivsMax; // the max number of divisors in the cone + // representation of the cone + Abc_Obj_t * pRoot; // the root of the cone + int nLeaves; // the number of leaves + int nDivs; // the number of all divisor (including leaves) + int nMffc; // the size of MFFC + int nLastGain; // the gain the number of nodes + Vec_Ptr_t * vDivs; // the divisors + // representation of the simulation info + int nBits; // the number of simulation bits + int nWords; // the number of unsigneds for siminfo + Vec_Ptr_t * vSims; // simulation info + unsigned * pInfo; // pointer to simulation info + // observability don't-cares + unsigned * pCareSet; + // internal divisor storage + Vec_Ptr_t * vDivs1UP; // the single-node unate divisors + Vec_Ptr_t * vDivs1UN; // the single-node unate divisors + Vec_Ptr_t * vDivs1B; // the single-node binate divisors + Vec_Ptr_t * vDivs2UP0; // the double-node unate divisors + Vec_Ptr_t * vDivs2UP1; // the double-node unate divisors + Vec_Ptr_t * vDivs2UN0; // the double-node unate divisors + Vec_Ptr_t * vDivs2UN1; // the double-node unate divisors + // other data + Vec_Ptr_t * vTemp; // temporary array of nodes + // runtime statistics + int timeCut; + int timeTruth; + int timeRes; + int timeDiv; + int timeMffc; + int timeSim; + int timeRes1; + int timeResD; + int timeRes2; + int timeRes3; + int timeNtk; + int timeTotal; + // improvement statistics + int nUsedNodeC; + int nUsedNode0; + int nUsedNode1Or; + int nUsedNode1And; + int nUsedNode2Or; + int nUsedNode2And; + int nUsedNode2OrAnd; + int nUsedNode2AndOr; + int nUsedNode3OrAnd; + int nUsedNode3AndOr; + int nUsedNodeTotal; + int nTotalDivs; + int nTotalLeaves; + int nTotalGain; + int nNodesBeg; + int nNodesEnd; +}; + +// external procedures +static Abc_ManRes_t* Abc_ManResubStart( int nLeavesMax, int nDivsMax ); +static void Abc_ManResubStop( Abc_ManRes_t * p ); +static Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, bool fUpdateLevel, int fVerbose ); +static void Abc_ManResubCleanup( Abc_ManRes_t * p ); +static void Abc_ManResubPrint( Abc_ManRes_t * p ); + +// other procedures +static int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required ); +static void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords ); +static void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ); + +static void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required ); +static void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required ); +static Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p ); +static Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p ); +static Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required ); +static Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required ); +static Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required ); +static Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required ); + +static Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax ); +static int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ); + +// don't-care manager +extern void * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ); +extern void Abc_NtkDontCareClear( void * p ); +extern void Abc_NtkDontCareFree( void * p ); +extern int Abc_NtkDontCareCompute( void * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ); + +extern int s_ResubTime; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs incremental resynthesis of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nLevelsOdc, bool fUpdateLevel, bool fVerbose, bool fVeryVerbose ) +{ + ProgressBar * pProgress; + Abc_ManRes_t * pManRes; + Abc_ManCut_t * pManCut; + void * pManOdc = NULL; + Dec_Graph_t * pFForm; + Vec_Ptr_t * vLeaves; + Abc_Obj_t * pNode; + int clk, clkStart = clock(); + int i, nNodes; + + assert( Abc_NtkIsStrash(pNtk) ); + + // cleanup the AIG + Abc_AigCleanup(pNtk->pManFunc); + // start the managers + pManCut = Abc_NtkManCutStart( nCutMax, 100000, 100000, 100000 ); + pManRes = Abc_ManResubStart( nCutMax, ABC_RS_DIV1_MAX ); + if ( nLevelsOdc > 0 ) + pManOdc = Abc_NtkDontCareAlloc( nCutMax, nLevelsOdc, fVerbose, fVeryVerbose ); + + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Abc_NtkStartReverseLevels( pNtk, 0 ); + + if ( Abc_NtkLatchNum(pNtk) ) + Abc_NtkForEachLatch(pNtk, pNode, i) + pNode->pNext = pNode->pData; + + // resynthesize each node once + pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk); + nNodes = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // skip the constant node +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + continue; + // skip the nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + continue; + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + + // compute a reconvergence-driven cut +clk = clock(); + vLeaves = Abc_NodeFindCut( pManCut, pNode, 0 ); +// vLeaves = Abc_CutFactorLarge( pNode, nCutMax ); +pManRes->timeCut += clock() - clk; +/* + if ( fVerbose && vLeaves ) + printf( "Node %6d : Leaves = %3d. Volume = %3d.\n", pNode->Id, Vec_PtrSize(vLeaves), Abc_CutVolumeCheck(pNode, vLeaves) ); + if ( vLeaves == NULL ) + continue; +*/ + // get the don't-cares + if ( pManOdc ) + { +clk = clock(); + Abc_NtkDontCareClear( pManOdc ); + Abc_NtkDontCareCompute( pManOdc, pNode, vLeaves, pManRes->pCareSet ); +pManRes->timeTruth += clock() - clk; + } + + // evaluate this cut +clk = clock(); + pFForm = Abc_ManResubEval( pManRes, pNode, vLeaves, nStepsMax, fUpdateLevel, fVerbose ); +// Vec_PtrFree( vLeaves ); +// Abc_ManResubCleanup( pManRes ); +pManRes->timeRes += clock() - clk; + if ( pFForm == NULL ) + continue; + pManRes->nTotalGain += pManRes->nLastGain; +/* + if ( pManRes->nLeaves == 4 && pManRes->nMffc == 2 && pManRes->nLastGain == 1 ) + { + printf( "%6d : L = %2d. V = %2d. Mffc = %2d. Divs = %3d. Up = %3d. Un = %3d. B = %3d.\n", + pNode->Id, pManRes->nLeaves, Abc_CutVolumeCheck(pNode, vLeaves), pManRes->nMffc, pManRes->nDivs, + pManRes->vDivs1UP->nSize, pManRes->vDivs1UN->nSize, pManRes->vDivs1B->nSize ); + Abc_ManResubPrintDivs( pManRes, pNode, vLeaves ); + } +*/ + // acceptable replacement found, update the graph +clk = clock(); + Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRes->nLastGain ); +pManRes->timeNtk += clock() - clk; + Dec_GraphFree( pFForm ); + } + Extra_ProgressBarStop( pProgress ); +pManRes->timeTotal = clock() - clkStart; + pManRes->nNodesEnd = Abc_NtkNodeNum(pNtk); + + // print statistics + if ( fVerbose ) + Abc_ManResubPrint( pManRes ); + + // delete the managers + Abc_ManResubStop( pManRes ); + Abc_NtkManCutStop( pManCut ); + if ( pManOdc ) Abc_NtkDontCareFree( pManOdc ); + + // clean the data field + Abc_NtkForEachObj( pNtk, pNode, i ) + pNode->pData = NULL; + + if ( Abc_NtkLatchNum(pNtk) ) + Abc_NtkForEachLatch(pNtk, pNode, i) + pNode->pData = pNode->pNext, pNode->pNext = NULL; + + // put the nodes into the DFS order and reassign their IDs + Abc_NtkReassignIds( pNtk ); +// Abc_AigCheckFaninOrder( pNtk->pManFunc ); + // fix the levels + if ( fUpdateLevel ) + Abc_NtkStopReverseLevels( pNtk ); + else + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkRefactor: The network check has failed.\n" ); + return 0; + } +s_ResubTime = clock() - clkStart; + return 1; +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManRes_t * Abc_ManResubStart( int nLeavesMax, int nDivsMax ) +{ + Abc_ManRes_t * p; + unsigned * pData; + int i, k; + assert( sizeof(unsigned) == 4 ); + p = ALLOC( Abc_ManRes_t, 1 ); + memset( p, 0, sizeof(Abc_ManRes_t) ); + p->nLeavesMax = nLeavesMax; + p->nDivsMax = nDivsMax; + p->vDivs = Vec_PtrAlloc( p->nDivsMax ); + // allocate simulation info + p->nBits = (1 << p->nLeavesMax); + p->nWords = (p->nBits <= 32)? 1 : (p->nBits / 32); + p->pInfo = ALLOC( unsigned, p->nWords * (p->nDivsMax + 1) ); + memset( p->pInfo, 0, sizeof(unsigned) * p->nWords * p->nLeavesMax ); + p->vSims = Vec_PtrAlloc( p->nDivsMax ); + for ( i = 0; i < p->nDivsMax; i++ ) + Vec_PtrPush( p->vSims, p->pInfo + i * p->nWords ); + // assign the care set + p->pCareSet = p->pInfo + p->nDivsMax * p->nWords; + Abc_InfoFill( p->pCareSet, p->nWords ); + // set elementary truth tables + for ( k = 0; k < p->nLeavesMax; k++ ) + { + pData = p->vSims->pArray[k]; + for ( i = 0; i < p->nBits; i++ ) + if ( i & (1 << k) ) + pData[i>>5] |= (1 << (i&31)); + } + // create the remaining divisors + p->vDivs1UP = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs1UN = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs1B = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs2UP0 = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs2UP1 = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs2UN0 = Vec_PtrAlloc( p->nDivsMax ); + p->vDivs2UN1 = Vec_PtrAlloc( p->nDivsMax ); + p->vTemp = Vec_PtrAlloc( p->nDivsMax ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubStop( Abc_ManRes_t * p ) +{ + Vec_PtrFree( p->vDivs ); + Vec_PtrFree( p->vSims ); + Vec_PtrFree( p->vDivs1UP ); + Vec_PtrFree( p->vDivs1UN ); + Vec_PtrFree( p->vDivs1B ); + Vec_PtrFree( p->vDivs2UP0 ); + Vec_PtrFree( p->vDivs2UP1 ); + Vec_PtrFree( p->vDivs2UN0 ); + Vec_PtrFree( p->vDivs2UN1 ); + Vec_PtrFree( p->vTemp ); + free( p->pInfo ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubPrint( Abc_ManRes_t * p ) +{ + printf( "Used constants = %6d. ", p->nUsedNodeC ); PRT( "Cuts ", p->timeCut ); + printf( "Used replacements = %6d. ", p->nUsedNode0 ); PRT( "Resub ", p->timeRes ); + printf( "Used single ORs = %6d. ", p->nUsedNode1Or ); PRT( " Div ", p->timeDiv ); + printf( "Used single ANDs = %6d. ", p->nUsedNode1And ); PRT( " Mffc ", p->timeMffc ); + printf( "Used double ORs = %6d. ", p->nUsedNode2Or ); PRT( " Sim ", p->timeSim ); + printf( "Used double ANDs = %6d. ", p->nUsedNode2And ); PRT( " 1 ", p->timeRes1 ); + printf( "Used OR-AND = %6d. ", p->nUsedNode2OrAnd ); PRT( " D ", p->timeResD ); + printf( "Used AND-OR = %6d. ", p->nUsedNode2AndOr ); PRT( " 2 ", p->timeRes2 ); + printf( "Used OR-2ANDs = %6d. ", p->nUsedNode3OrAnd ); PRT( "Truth ", p->timeTruth ); //PRT( " 3 ", p->timeRes3 ); + printf( "Used AND-2ORs = %6d. ", p->nUsedNode3AndOr ); PRT( "AIG ", p->timeNtk ); + printf( "TOTAL = %6d. ", p->nUsedNodeC + + p->nUsedNode0 + + p->nUsedNode1Or + + p->nUsedNode1And + + p->nUsedNode2Or + + p->nUsedNode2And + + p->nUsedNode2OrAnd + + p->nUsedNode2AndOr + + p->nUsedNode3OrAnd + + p->nUsedNode3AndOr + ); PRT( "TOTAL ", p->timeTotal ); + printf( "Total leaves = %8d.\n", p->nTotalLeaves ); + printf( "Total divisors = %8d.\n", p->nTotalDivs ); +// printf( "Total gain = %8d.\n", p->nTotalGain ); + printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubCollectDivs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vInternal ) +{ + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + Abc_NodeSetTravIdCurrent(pNode); + // collect the fanins + Abc_ManResubCollectDivs_rec( Abc_ObjFanin0(pNode), vInternal ); + Abc_ManResubCollectDivs_rec( Abc_ObjFanin1(pNode), vInternal ); + // collect the internal node + if ( pNode->fMarkA == 0 ) + Vec_PtrPush( vInternal, pNode ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required ) +{ + Abc_Obj_t * pNode, * pFanout; + int i, k, Limit, Counter; + + Vec_PtrClear( p->vDivs1UP ); + Vec_PtrClear( p->vDivs1UN ); + Vec_PtrClear( p->vDivs1B ); + + // add the leaves of the cuts to the divisors + Vec_PtrClear( p->vDivs ); + Abc_NtkIncrementTravId( pRoot->pNtk ); + Vec_PtrForEachEntry( vLeaves, pNode, i ) + { + Vec_PtrPush( p->vDivs, pNode ); + Abc_NodeSetTravIdCurrent( pNode ); + } + + // mark nodes in the MFFC + Vec_PtrForEachEntry( p->vTemp, pNode, i ) + pNode->fMarkA = 1; + // collect the cone (without MFFC) + Abc_ManResubCollectDivs_rec( pRoot, p->vDivs ); + // unmark the current MFFC + Vec_PtrForEachEntry( p->vTemp, pNode, i ) + pNode->fMarkA = 0; + + // check if the number of divisors is not exceeded + if ( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp) >= Vec_PtrSize(p->vSims) - p->nLeavesMax ) + return 0; + + // get the number of divisors to collect + Limit = Vec_PtrSize(p->vSims) - p->nLeavesMax - (Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp)); + + // explore the fanouts, which are not in the MFFC + Counter = 0; + Vec_PtrForEachEntry( p->vDivs, pNode, i ) + { + if ( Abc_ObjFanoutNum(pNode) > 100 ) + { +// printf( "%d ", Abc_ObjFanoutNum(pNode) ); + continue; + } + // if the fanout has both fanins in the set, add it + Abc_ObjForEachFanout( pNode, pFanout, k ) + { + if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsCo(pFanout) || (int)pFanout->Level > Required ) + continue; + if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) ) + { + if ( Abc_ObjFanin0(pFanout) == pRoot || Abc_ObjFanin1(pFanout) == pRoot ) + continue; + Vec_PtrPush( p->vDivs, pFanout ); + Abc_NodeSetTravIdCurrent( pFanout ); + // quit computing divisors if there is too many of them + if ( ++Counter == Limit ) + goto Quits; + } + } + } + +Quits : + // get the number of divisors + p->nDivs = Vec_PtrSize(p->vDivs); + + // add the nodes in the MFFC + Vec_PtrForEachEntry( p->vTemp, pNode, i ) + Vec_PtrPush( p->vDivs, pNode ); + assert( pRoot == Vec_PtrEntryLast(p->vDivs) ); + + assert( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) <= Vec_PtrSize(p->vSims) - p->nLeavesMax ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ) +{ + Abc_Obj_t * pFanin, * pNode; + int i, k; + // print the nodes + Vec_PtrForEachEntry( p->vDivs, pNode, i ) + { + if ( i < Vec_PtrSize(vLeaves) ) + { + printf( "%6d : %c\n", pNode->Id, 'a'+i ); + continue; + } + printf( "%6d : %2d = ", pNode->Id, i ); + // find the first fanin + Vec_PtrForEachEntry( p->vDivs, pFanin, k ) + if ( Abc_ObjFanin0(pNode) == pFanin ) + break; + if ( k < Vec_PtrSize(vLeaves) ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); + // find the second fanin + Vec_PtrForEachEntry( p->vDivs, pFanin, k ) + if ( Abc_ObjFanin1(pNode) == pFanin ) + break; + if ( k < Vec_PtrSize(vLeaves) ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); + if ( pNode == pRoot ) + printf( " root" ); + printf( "\n" ); + } + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Performs simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords ) +{ + Abc_Obj_t * pObj; + unsigned * puData0, * puData1, * puData; + int i, k; + assert( Vec_PtrSize(vDivs) - nLeaves <= Vec_PtrSize(vSims) - nLeavesMax ); + // simulate + Vec_PtrForEachEntry( vDivs, pObj, i ) + { + if ( i < nLeaves ) + { // initialize the leaf + pObj->pData = Vec_PtrEntry( vSims, i ); + continue; + } + // set storage for the node's simulation info + pObj->pData = Vec_PtrEntry( vSims, i - nLeaves + nLeavesMax ); + // get pointer to the simulation info + puData = pObj->pData; + puData0 = Abc_ObjFanin0(pObj)->pData; + puData1 = Abc_ObjFanin1(pObj)->pData; + // simulate + if ( Abc_ObjFaninC0(pObj) && Abc_ObjFaninC1(pObj) ) + for ( k = 0; k < nWords; k++ ) + puData[k] = ~puData0[k] & ~puData1[k]; + else if ( Abc_ObjFaninC0(pObj) ) + for ( k = 0; k < nWords; k++ ) + puData[k] = ~puData0[k] & puData1[k]; + else if ( Abc_ObjFaninC1(pObj) ) + for ( k = 0; k < nWords; k++ ) + puData[k] = puData0[k] & ~puData1[k]; + else + for ( k = 0; k < nWords; k++ ) + puData[k] = puData0[k] & puData1[k]; + } + // normalize + Vec_PtrForEachEntry( vDivs, pObj, i ) + { + puData = pObj->pData; + pObj->fPhase = (puData[0] & 1); + if ( pObj->fPhase ) + for ( k = 0; k < nWords; k++ ) + puData[k] = ~puData[k]; + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit0( Abc_Obj_t * pRoot, Abc_Obj_t * pObj ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot; + pGraph = Dec_GraphCreate( 1 ); + Dec_GraphNode( pGraph, 0 )->pFunc = pObj; + eRoot = Dec_EdgeCreate( 0, pObj->fPhase ); + Dec_GraphSetRoot( pGraph, eRoot ); + if ( pRoot->fPhase ) + Dec_GraphComplement( pGraph ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit1( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, int fOrGate ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot, eNode0, eNode1; + assert( pObj0 != pObj1 ); + assert( !Abc_ObjIsComplement(pObj0) ); + assert( !Abc_ObjIsComplement(pObj1) ); + pGraph = Dec_GraphCreate( 2 ); + Dec_GraphNode( pGraph, 0 )->pFunc = pObj0; + Dec_GraphNode( pGraph, 1 )->pFunc = pObj1; + eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase ); + eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase ); + if ( fOrGate ) + eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + else + eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); + Dec_GraphSetRoot( pGraph, eRoot ); + if ( pRoot->fPhase ) + Dec_GraphComplement( pGraph ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit21( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot, eNode0, eNode1, eNode2; + assert( pObj0 != pObj1 ); + assert( !Abc_ObjIsComplement(pObj0) ); + assert( !Abc_ObjIsComplement(pObj1) ); + assert( !Abc_ObjIsComplement(pObj2) ); + pGraph = Dec_GraphCreate( 3 ); + Dec_GraphNode( pGraph, 0 )->pFunc = pObj0; + Dec_GraphNode( pGraph, 1 )->pFunc = pObj1; + Dec_GraphNode( pGraph, 2 )->pFunc = pObj2; + eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase ); + eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase ); + eNode2 = Dec_EdgeCreate( 2, pObj2->fPhase ); + if ( fOrGate ) + { + eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + eRoot = Dec_GraphAddNodeOr( pGraph, eNode2, eRoot ); + } + else + { + eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); + eRoot = Dec_GraphAddNodeAnd( pGraph, eNode2, eRoot ); + } + Dec_GraphSetRoot( pGraph, eRoot ); + if ( pRoot->fPhase ) + Dec_GraphComplement( pGraph ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit2( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot, ePrev, eNode0, eNode1, eNode2; + assert( pObj0 != pObj1 ); + assert( pObj0 != pObj2 ); + assert( pObj1 != pObj2 ); + assert( !Abc_ObjIsComplement(pObj0) ); + pGraph = Dec_GraphCreate( 3 ); + Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0); + Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1); + Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2); + eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ); + if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) + { + eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ); + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); + ePrev = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 ); + } + else + { + eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) ); + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); + ePrev = Dec_GraphAddNodeAnd( pGraph, eNode1, eNode2 ); + } + if ( fOrGate ) + eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, ePrev ); + else + eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, ePrev ); + Dec_GraphSetRoot( pGraph, eRoot ); + if ( pRoot->fPhase ) + Dec_GraphComplement( pGraph ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit3( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, Abc_Obj_t * pObj3, int fOrGate ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot, ePrev0, ePrev1, eNode0, eNode1, eNode2, eNode3; + assert( pObj0 != pObj1 ); + assert( pObj2 != pObj3 ); + pGraph = Dec_GraphCreate( 4 ); + Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0); + Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1); + Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2); + Dec_GraphNode( pGraph, 3 )->pFunc = Abc_ObjRegular(pObj3); + if ( Abc_ObjIsComplement(pObj0) && Abc_ObjIsComplement(pObj1) ) + { + eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ); + eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ); + ePrev0 = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) ) + { + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); + eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ); + ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 ); + } + else + { + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); + eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) ); + ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 ); + } + } + else + { + eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ^ Abc_ObjIsComplement(pObj0) ); + eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) ); + ePrev0 = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); + if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) ) + { + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); + eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ); + ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 ); + } + else + { + eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); + eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) ); + ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 ); + } + } + if ( fOrGate ) + eRoot = Dec_GraphAddNodeOr( pGraph, ePrev0, ePrev1 ); + else + eRoot = Dec_GraphAddNodeAnd( pGraph, ePrev0, ePrev1 ); + Dec_GraphSetRoot( pGraph, eRoot ); + if ( pRoot->fPhase ) + Dec_GraphComplement( pGraph ); + return pGraph; +} + + + + +/**Function************************************************************* + + Synopsis [Derives single-node unate/binate divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj; + unsigned * puData, * puDataR; + int i, w; + Vec_PtrClear( p->vDivs1UP ); + Vec_PtrClear( p->vDivs1UN ); + Vec_PtrClear( p->vDivs1B ); + puDataR = p->pRoot->pData; + Vec_PtrForEachEntryStop( p->vDivs, pObj, i, p->nDivs ) + { + if ( (int)pObj->Level > Required - 1 ) + continue; + + puData = pObj->pData; + // check positive containment + for ( w = 0; w < p->nWords; w++ ) +// if ( puData[w] & ~puDataR[w] ) + if ( puData[w] & ~puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs1UP, pObj ); + continue; + } + // check negative containment + for ( w = 0; w < p->nWords; w++ ) +// if ( ~puData[w] & puDataR[w] ) + if ( ~puData[w] & puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs1UN, pObj ); + continue; + } + // add the node to binates + Vec_PtrPush( p->vDivs1B, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Derives double-node unate/binate divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj0, * pObj1; + unsigned * puData0, * puData1, * puDataR; + int i, k, w; + Vec_PtrClear( p->vDivs2UP0 ); + Vec_PtrClear( p->vDivs2UP1 ); + Vec_PtrClear( p->vDivs2UN0 ); + Vec_PtrClear( p->vDivs2UN1 ); + puDataR = p->pRoot->pData; + Vec_PtrForEachEntry( p->vDivs1B, pObj0, i ) + { + if ( (int)pObj0->Level > Required - 2 ) + continue; + + puData0 = pObj0->pData; + Vec_PtrForEachEntryStart( p->vDivs1B, pObj1, k, i + 1 ) + { + if ( (int)pObj1->Level > Required - 2 ) + continue; + + puData1 = pObj1->pData; + + if ( Vec_PtrSize(p->vDivs2UP0) < ABC_RS_DIV2_MAX ) + { + // get positive unate divisors + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & puData1[w]) & ~puDataR[w] ) + if ( (puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UP0, pObj0 ); + Vec_PtrPush( p->vDivs2UP1, pObj1 ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( (~puData0[w] & puData1[w]) & ~puDataR[w] ) + if ( (~puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) ); + Vec_PtrPush( p->vDivs2UP1, pObj1 ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] ) + if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UP0, pObj0 ); + Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | puData1[w]) & ~puDataR[w] ) + if ( (puData0[w] | puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) ); + Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) ); + } + } + + if ( Vec_PtrSize(p->vDivs2UN0) < ABC_RS_DIV2_MAX ) + { + // get negative unate divisors + for ( w = 0; w < p->nWords; w++ ) +// if ( ~(puData0[w] & puData1[w]) & puDataR[w] ) + if ( ~(puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UN0, pObj0 ); + Vec_PtrPush( p->vDivs2UN1, pObj1 ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( ~(~puData0[w] & puData1[w]) & puDataR[w] ) + if ( ~(~puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) ); + Vec_PtrPush( p->vDivs2UN1, pObj1 ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] ) + if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UN0, pObj0 ); + Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) ); + } + for ( w = 0; w < p->nWords; w++ ) +// if ( ~(puData0[w] | puData1[w]) & puDataR[w] ) + if ( ~(puData0[w] | puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) ); + Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) ); + } + } + } + } +// printf( "%d %d ", Vec_PtrSize(p->vDivs2UP0), Vec_PtrSize(p->vDivs2UN0) ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p ) +{ + Dec_Graph_t * pGraph; + unsigned * upData; + int w; + upData = p->pRoot->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( upData[w] ) + if ( upData[w] & p->pCareSet[w] ) // care set + break; + if ( w != p->nWords ) + return NULL; + // get constant node graph + if ( p->pRoot->fPhase ) + pGraph = Dec_GraphCreateConst1(); + else + pGraph = Dec_GraphCreateConst0(); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p ) +{ + Abc_Obj_t * pObj; + unsigned * puData, * puDataR; + int i, w; + puDataR = p->pRoot->pData; + Vec_PtrForEachEntryStop( p->vDivs, pObj, i, p->nDivs ) + { + puData = pObj->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( puData[w] != puDataR[w] ) + if ( (puData[w] ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + return Abc_ManResubQuit0( p->pRoot, pObj ); + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj0, * pObj1; + unsigned * puData0, * puData1, * puDataR; + int i, k, w; + puDataR = p->pRoot->pData; + // check positive unate divisors + Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntryStart( p->vDivs1UP, pObj1, k, i + 1 ) + { + puData1 = pObj1->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | puData1[w]) != puDataR[w] ) + if ( ((puData0[w] | puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + p->nUsedNode1Or++; + return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 1 ); + } + } + } + // check negative unate divisors + Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntryStart( p->vDivs1UN, pObj1, k, i + 1 ) + { + puData1 = pObj1->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & puData1[w]) != puDataR[w] ) + if ( ((puData0[w] & puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + p->nUsedNode1And++; + return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 0 ); + } + } + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObjMax, * pObjMin0, * pObjMin1; + unsigned * puData0, * puData1, * puData2, * puDataR; + int i, k, j, w, LevelMax; + puDataR = p->pRoot->pData; + // check positive unate divisors + Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntryStart( p->vDivs1UP, pObj1, k, i + 1 ) + { + puData1 = pObj1->pData; + Vec_PtrForEachEntryStart( p->vDivs1UP, pObj2, j, k + 1 ) + { + puData2 = pObj2->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | puData1[w] | puData2[w]) != puDataR[w] ) + if ( ((puData0[w] | puData1[w] | puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) ); + assert( LevelMax <= Required - 1 ); + + pObjMax = NULL; + if ( (int)pObj0->Level == LevelMax ) + pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2; + if ( (int)pObj1->Level == LevelMax ) + { + if ( pObjMax ) continue; + pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2; + } + if ( (int)pObj2->Level == LevelMax ) + { + if ( pObjMax ) continue; + pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1; + } + + p->nUsedNode2Or++; + return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 1 ); + } + } + } + } + // check negative unate divisors + Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntryStart( p->vDivs1UN, pObj1, k, i + 1 ) + { + puData1 = pObj1->pData; + Vec_PtrForEachEntryStart( p->vDivs1UN, pObj2, j, k + 1 ) + { + puData2 = pObj2->pData; + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & puData1[w] & puData2[w]) != puDataR[w] ) + if ( ((puData0[w] & puData1[w] & puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + if ( w == p->nWords ) + { + LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) ); + assert( LevelMax <= Required - 1 ); + + pObjMax = NULL; + if ( (int)pObj0->Level == LevelMax ) + pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2; + if ( (int)pObj1->Level == LevelMax ) + { + if ( pObjMax ) continue; + pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2; + } + if ( (int)pObj2->Level == LevelMax ) + { + if ( pObjMax ) continue; + pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1; + } + + p->nUsedNode2And++; + return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 0 ); + } + } + } + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj0, * pObj1, * pObj2; + unsigned * puData0, * puData1, * puData2, * puDataR; + int i, k, w; + puDataR = p->pRoot->pData; + // check positive unate divisors + Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntry( p->vDivs2UP0, pObj1, k ) + { + pObj2 = Vec_PtrEntry( p->vDivs2UP1, k ); + + puData1 = Abc_ObjRegular(pObj1)->pData; + puData2 = Abc_ObjRegular(pObj2)->pData; + if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | (puData1[w] | puData2[w])) != puDataR[w] ) + if ( ((puData0[w] | (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else if ( Abc_ObjIsComplement(pObj1) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | (~puData1[w] & puData2[w])) != puDataR[w] ) + if ( ((puData0[w] | (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else if ( Abc_ObjIsComplement(pObj2) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | (puData1[w] & ~puData2[w])) != puDataR[w] ) + if ( ((puData0[w] | (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] | (puData1[w] & puData2[w])) != puDataR[w] ) + if ( ((puData0[w] | (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + if ( w == p->nWords ) + { + p->nUsedNode2OrAnd++; + return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 1 ); + } + } + } + // check negative unate divisors + Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i ) + { + puData0 = pObj0->pData; + Vec_PtrForEachEntry( p->vDivs2UN0, pObj1, k ) + { + pObj2 = Vec_PtrEntry( p->vDivs2UN1, k ); + + puData1 = Abc_ObjRegular(pObj1)->pData; + puData2 = Abc_ObjRegular(pObj2)->pData; + if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & (puData1[w] | puData2[w])) != puDataR[w] ) + if ( ((puData0[w] & (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else if ( Abc_ObjIsComplement(pObj1) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & (~puData1[w] & puData2[w])) != puDataR[w] ) + if ( ((puData0[w] & (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else if ( Abc_ObjIsComplement(pObj2) ) + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & (puData1[w] & ~puData2[w])) != puDataR[w] ) + if ( ((puData0[w] & (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + else + { + for ( w = 0; w < p->nWords; w++ ) +// if ( (puData0[w] & (puData1[w] & puData2[w])) != puDataR[w] ) + if ( ((puData0[w] & (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + } + if ( w == p->nWords ) + { + p->nUsedNode2AndOr++; + return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 0 ); + } + } + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required ) +{ + Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObj3; + unsigned * puData0, * puData1, * puData2, * puData3, * puDataR; + int i, k, w, Flag; + puDataR = p->pRoot->pData; + // check positive unate divisors + Vec_PtrForEachEntry( p->vDivs2UP0, pObj0, i ) + { + pObj1 = Vec_PtrEntry( p->vDivs2UP1, i ); + puData0 = Abc_ObjRegular(pObj0)->pData; + puData1 = Abc_ObjRegular(pObj1)->pData; + Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2); + + Vec_PtrForEachEntryStart( p->vDivs2UP0, pObj2, k, i + 1 ) + { + pObj3 = Vec_PtrEntry( p->vDivs2UP1, k ); + puData2 = Abc_ObjRegular(pObj2)->pData; + puData3 = Abc_ObjRegular(pObj3)->pData; + + Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3); + assert( Flag < 16 ); + switch( Flag ) + { + case 0: // 0000 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 1: // 0001 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 2: // 0010 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 3: // 0011 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + + case 4: // 0100 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 5: // 0101 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 6: // 0110 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 7: // 0111 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) + if ( (((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + + case 8: // 1000 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 9: // 1001 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) + if ( (((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 10: // 1010 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 11: // 1011 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) + if ( (((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + + case 12: // 1100 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set + break; + break; + case 13: // 1101 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) + if ( (((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) + break; + break; + case 14: // 1110 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) + if ( (((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) + break; + break; + case 15: // 1111 + for ( w = 0; w < p->nWords; w++ ) +// if ( ((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) + if ( (((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) + break; + break; + + } + if ( w == p->nWords ) + { + p->nUsedNode3OrAnd++; + return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 1 ); + } + } + } +/* + // check negative unate divisors + Vec_PtrForEachEntry( p->vDivs2UN0, pObj0, i ) + { + pObj1 = Vec_PtrEntry( p->vDivs2UN1, i ); + puData0 = Abc_ObjRegular(pObj0)->pData; + puData1 = Abc_ObjRegular(pObj1)->pData; + Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2); + + Vec_PtrForEachEntryStart( p->vDivs2UN0, pObj2, k, i + 1 ) + { + pObj3 = Vec_PtrEntry( p->vDivs2UN1, k ); + puData2 = Abc_ObjRegular(pObj2)->pData; + puData3 = Abc_ObjRegular(pObj3)->pData; + + Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3); + assert( Flag < 16 ); + switch( Flag ) + { + case 0: // 0000 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 1: // 0001 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) + break; + break; + case 2: // 0010 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 3: // 0011 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) + break; + break; + + case 4: // 0100 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 5: // 0101 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) + break; + break; + case 6: // 0110 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & ~puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 7: // 0111 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] & ~puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) + break; + break; + + case 8: // 1000 + for ( w = 0; w < p->nWords; w++ ) + if ( ((~puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 9: // 1001 + for ( w = 0; w < p->nWords; w++ ) + if ( ((~puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) + break; + break; + case 10: // 1010 + for ( w = 0; w < p->nWords; w++ ) + if ( ((~puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 11: // 1011 + for ( w = 0; w < p->nWords; w++ ) + if ( ((~puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) + break; + break; + + case 12: // 1100 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] | puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 13: // 1101 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] | puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) + break; + break; + case 14: // 1110 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] | puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) + break; + break; + case 15: // 1111 + for ( w = 0; w < p->nWords; w++ ) + if ( ((puData0[w] | puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) + break; + break; + + } + if ( w == p->nWords ) + { + p->nUsedNode3AndOr++; + return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 0 ); + } + } + } +*/ + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManResubCleanup( Abc_ManRes_t * p ) +{ + Abc_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( p->vDivs, pObj, i ) + pObj->pData = NULL; + Vec_PtrClear( p->vDivs ); + p->pRoot = NULL; +} + +/**Function************************************************************* + + Synopsis [Evaluates resubstution of one cut.] + + Description [Returns the graph to add if any.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, bool fUpdateLevel, bool fVerbose ) +{ + extern int Abc_NodeMffsInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside ); + Dec_Graph_t * pGraph; + int Required; + int clk; + + Required = fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY; + + assert( nSteps >= 0 ); + assert( nSteps <= 3 ); + p->pRoot = pRoot; + p->nLeaves = Vec_PtrSize(vLeaves); + p->nLastGain = -1; + + // collect the MFFC +clk = clock(); + p->nMffc = Abc_NodeMffsInside( pRoot, vLeaves, p->vTemp ); +p->timeMffc += clock() - clk; + assert( p->nMffc > 0 ); + + // collect the divisor nodes +clk = clock(); + if ( !Abc_ManResubCollectDivs( p, pRoot, vLeaves, Required ) ) + return NULL; + p->timeDiv += clock() - clk; + + p->nTotalDivs += p->nDivs; + p->nTotalLeaves += p->nLeaves; + + // simulate the nodes +clk = clock(); + Abc_ManResubSimulate( p->vDivs, p->nLeaves, p->vSims, p->nLeavesMax, p->nWords ); +p->timeSim += clock() - clk; + +clk = clock(); + // consider constants + if ( pGraph = Abc_ManResubQuit( p ) ) + { + p->nUsedNodeC++; + p->nLastGain = p->nMffc; + return pGraph; + } + + // consider equal nodes + if ( pGraph = Abc_ManResubDivs0( p ) ) + { +p->timeRes1 += clock() - clk; + p->nUsedNode0++; + p->nLastGain = p->nMffc; + return pGraph; + } + if ( nSteps == 0 || p->nMffc == 1 ) + { +p->timeRes1 += clock() - clk; + return NULL; + } + + // get the one level divisors + Abc_ManResubDivsS( p, Required ); + + // consider one node + if ( pGraph = Abc_ManResubDivs1( p, Required ) ) + { +p->timeRes1 += clock() - clk; + p->nLastGain = p->nMffc - 1; + return pGraph; + } +p->timeRes1 += clock() - clk; + if ( nSteps == 1 || p->nMffc == 2 ) + return NULL; + +clk = clock(); + // consider triples + if ( pGraph = Abc_ManResubDivs12( p, Required ) ) + { +p->timeRes2 += clock() - clk; + p->nLastGain = p->nMffc - 2; + return pGraph; + } +p->timeRes2 += clock() - clk; + + // get the two level divisors +clk = clock(); + Abc_ManResubDivsD( p, Required ); +p->timeResD += clock() - clk; + + // consider two nodes +clk = clock(); + if ( pGraph = Abc_ManResubDivs2( p, Required ) ) + { +p->timeRes2 += clock() - clk; + p->nLastGain = p->nMffc - 2; + return pGraph; + } +p->timeRes2 += clock() - clk; + if ( nSteps == 2 || p->nMffc == 3 ) + return NULL; + + // consider two nodes +clk = clock(); + if ( pGraph = Abc_ManResubDivs3( p, Required ) ) + { +p->timeRes3 += clock() - clk; + p->nLastGain = p->nMffc - 3; + return pGraph; + } +p->timeRes3 += clock() - clk; + if ( nSteps == 3 || p->nLeavesMax == 4 ) + return NULL; + return NULL; +} + + + + +/**Function************************************************************* + + Synopsis [Computes the volume and checks if the cut is feasible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CutVolumeCheck_rec( Abc_Obj_t * pObj ) +{ + // quit if the node is visited (or if it is a leaf) + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + // report the error + if ( Abc_ObjIsCi(pObj) ) + printf( "Abc_CutVolumeCheck() ERROR: The set of nodes is not a cut!\n" ); + // count the number of nodes in the leaves + return 1 + Abc_CutVolumeCheck_rec( Abc_ObjFanin0(pObj) ) + + Abc_CutVolumeCheck_rec( Abc_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Computes the volume and checks if the cut is feasible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) +{ + Abc_Obj_t * pObj; + int i; + // mark the leaves + Abc_NtkIncrementTravId( pNode->pNtk ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // traverse the nodes starting from the given one and count them + return Abc_CutVolumeCheck_rec( pNode ); +} + +/**Function************************************************************* + + Synopsis [Computes the factor cut of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_CutFactor_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ) +{ + if ( pObj->fMarkA ) + return; + if ( Abc_ObjIsCi(pObj) || (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) ) + { + Vec_PtrPush( vLeaves, pObj ); + pObj->fMarkA = 1; + return; + } + Abc_CutFactor_rec( Abc_ObjFanin0(pObj), vLeaves ); + Abc_CutFactor_rec( Abc_ObjFanin1(pObj), vLeaves ); +} + +/**Function************************************************************* + + Synopsis [Computes the factor cut of the node.] + + Description [Factor-cut is the cut at a node in terms of factor-nodes. + Factor-nodes are roots of the node trees (MUXes/EXORs are counted as single nodes). + Factor-cut is unique for the given node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_CutFactor( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vLeaves; + Abc_Obj_t * pObj; + int i; + assert( !Abc_ObjIsCi(pNode) ); + vLeaves = Vec_PtrAlloc( 10 ); + Abc_CutFactor_rec( Abc_ObjFanin0(pNode), vLeaves ); + Abc_CutFactor_rec( Abc_ObjFanin1(pNode), vLeaves ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->fMarkA = 0; + return vLeaves; +} + +/**Function************************************************************* + + Synopsis [Cut computation.] + + Description [This cut computation works as follows: + It starts with the factor cut at the node. If the factor-cut is large, quit. + It supports the set of leaves of the cut under construction and labels all nodes + in the cut under construction, including the leaves. + It computes the factor-cuts of the leaves and checks if it is easible to add any of them. + If it is, it randomly chooses one feasible and continues.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax ) +{ + Vec_Ptr_t * vLeaves, * vFactors, * vFact, * vNext; + Vec_Int_t * vFeasible; + Abc_Obj_t * pLeaf, * pTemp; + int i, k, Counter, RandLeaf; + int BestCut, BestShare; + assert( Abc_ObjIsNode(pNode) ); + // get one factor-cut + vLeaves = Abc_CutFactor( pNode ); + if ( Vec_PtrSize(vLeaves) > nLeavesMax ) + { + Vec_PtrFree(vLeaves); + return NULL; + } + if ( Vec_PtrSize(vLeaves) == nLeavesMax ) + return vLeaves; + // initialize the factor cuts for the leaves + vFactors = Vec_PtrAlloc( nLeavesMax ); + Abc_NtkIncrementTravId( pNode->pNtk ); + Vec_PtrForEachEntry( vLeaves, pLeaf, i ) + { + Abc_NodeSetTravIdCurrent( pLeaf ); + if ( Abc_ObjIsCi(pLeaf) ) + Vec_PtrPush( vFactors, NULL ); + else + Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) ); + } + // construct larger factor cuts + vFeasible = Vec_IntAlloc( nLeavesMax ); + while ( 1 ) + { + BestCut = -1; + // find the next feasible cut to add + Vec_IntClear( vFeasible ); + Vec_PtrForEachEntry( vFactors, vFact, i ) + { + if ( vFact == NULL ) + continue; + // count the number of unmarked leaves of this factor cut + Counter = 0; + Vec_PtrForEachEntry( vFact, pTemp, k ) + Counter += !Abc_NodeIsTravIdCurrent(pTemp); + // if the number of new leaves is smaller than the diff, it is feasible + if ( Counter <= nLeavesMax - Vec_PtrSize(vLeaves) + 1 ) + { + Vec_IntPush( vFeasible, i ); + if ( BestCut == -1 || BestShare < Vec_PtrSize(vFact) - Counter ) + BestCut = i, BestShare = Vec_PtrSize(vFact) - Counter; + } + } + // quit if there is no feasible factor cuts + if ( Vec_IntSize(vFeasible) == 0 ) + break; + // randomly choose one leaf and get its factor cut +// RandLeaf = Vec_IntEntry( vFeasible, rand() % Vec_IntSize(vFeasible) ); + // choose the cut that has most sharing with the other cuts + RandLeaf = BestCut; + + pLeaf = Vec_PtrEntry( vLeaves, RandLeaf ); + vNext = Vec_PtrEntry( vFactors, RandLeaf ); + // unmark this leaf + Abc_NodeSetTravIdPrevious( pLeaf ); + // remove this cut from the leaves and factor cuts + for ( i = RandLeaf; i < Vec_PtrSize(vLeaves)-1; i++ ) + { + Vec_PtrWriteEntry( vLeaves, i, Vec_PtrEntry(vLeaves, i+1) ); + Vec_PtrWriteEntry( vFactors, i, Vec_PtrEntry(vFactors,i+1) ); + } + Vec_PtrShrink( vLeaves, Vec_PtrSize(vLeaves) -1 ); + Vec_PtrShrink( vFactors, Vec_PtrSize(vFactors)-1 ); + // add new leaves, compute their factor cuts + Vec_PtrForEachEntry( vNext, pLeaf, i ) + { + if ( Abc_NodeIsTravIdCurrent(pLeaf) ) + continue; + Abc_NodeSetTravIdCurrent( pLeaf ); + Vec_PtrPush( vLeaves, pLeaf ); + if ( Abc_ObjIsCi(pLeaf) ) + Vec_PtrPush( vFactors, NULL ); + else + Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) ); + } + Vec_PtrFree( vNext ); + assert( Vec_PtrSize(vLeaves) <= nLeavesMax ); + if ( Vec_PtrSize(vLeaves) == nLeavesMax ) + break; + } + + // remove temporary storage + Vec_PtrForEachEntry( vFactors, vFact, i ) + if ( vFact ) Vec_PtrFree( vFact ); + Vec_PtrFree( vFactors ); + Vec_IntFree( vFeasible ); + return vLeaves; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRewrite.c b/abc70930/src/base/abci/abcRewrite.c new file mode 100644 index 00000000..b615f47e --- /dev/null +++ b/abc70930/src/base/abci/abcRewrite.c @@ -0,0 +1,414 @@ +/**CFile**************************************************************** + + FileName [abcRewrite.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Technology-independent resynthesis of the AIG based on DAG aware rewriting.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRewrite.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "rwr.h" +#include "dec.h" + +/* + The ideas realized in this package are inspired by the paper: + Per Bjesse, Arne Boralv, "DAG-aware circuit compression for + formal verification", Proc. ICCAD 2004, pp. 42-49. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ); +static void Abc_NodePrintCuts( Abc_Obj_t * pNode ); +static void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ); + +extern void Abc_PlaceBegin( Abc_Ntk_t * pNtk ); +extern void Abc_PlaceEnd( Abc_Ntk_t * pNtk ); +extern void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ) +{ + ProgressBar * pProgress; + Cut_Man_t * pManCut; + Rwr_Man_t * pManRwr; + Abc_Obj_t * pNode; + Vec_Ptr_t * vAddedCells = NULL, * vUpdatedNets = NULL; + Dec_Graph_t * pGraph; + int i, nNodes, nGain, fCompl; + int clk, clkStart = clock(); + + assert( Abc_NtkIsStrash(pNtk) ); + // cleanup the AIG + Abc_AigCleanup(pNtk->pManFunc); +/* + { + Vec_Vec_t * vParts; + vParts = Abc_NtkPartitionSmart( pNtk, 50, 1 ); + Vec_VecFree( vParts ); + } +*/ + + // start placement package +// if ( fPlaceEnable ) +// { +// Abc_PlaceBegin( pNtk ); +// vAddedCells = Abc_AigUpdateStart( pNtk->pManFunc, &vUpdatedNets ); +// } + + // start the rewriting manager + pManRwr = Rwr_ManStart( 0 ); + if ( pManRwr == NULL ) + return 0; + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Abc_NtkStartReverseLevels( pNtk, 0 ); + // start the cut manager +clk = clock(); + pManCut = Abc_NtkStartCutManForRewrite( pNtk ); +Rwr_ManAddTimeCuts( pManRwr, clock() - clk ); + pNtk->pManCut = pManCut; + + if ( fVeryVerbose ) + Rwr_ScoresClean( pManRwr ); + + // resynthesize each node once + pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk); + nNodes = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + continue; + // skip the nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + continue; + + // for each cut, try to resynthesize it + nGain = Rwr_NodeRewrite( pManRwr, pManCut, pNode, fUpdateLevel, fUseZeros, fPlaceEnable ); + if ( !(nGain > 0 || nGain == 0 && fUseZeros) ) + continue; + // if we end up here, a rewriting step is accepted + + // get hold of the new subgraph to be added to the AIG + pGraph = Rwr_ManReadDecs(pManRwr); + fCompl = Rwr_ManReadCompl(pManRwr); + + // reset the array of the changed nodes + if ( fPlaceEnable ) + Abc_AigUpdateReset( pNtk->pManFunc ); + + // complement the FF if needed + if ( fCompl ) Dec_GraphComplement( pGraph ); +clk = clock(); + Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain ); +Rwr_ManAddTimeUpdate( pManRwr, clock() - clk ); + if ( fCompl ) Dec_GraphComplement( pGraph ); + + // use the array of changed nodes to update placement +// if ( fPlaceEnable ) +// Abc_PlaceUpdate( vAddedCells, vUpdatedNets ); + } + Extra_ProgressBarStop( pProgress ); +Rwr_ManAddTimeTotal( pManRwr, clock() - clkStart ); + // print stats + pManRwr->nNodesEnd = Abc_NtkNodeNum(pNtk); + if ( fVerbose ) + Rwr_ManPrintStats( pManRwr ); +// Rwr_ManPrintStatsFile( pManRwr ); + if ( fVeryVerbose ) + Rwr_ScoresReport( pManRwr ); + // delete the managers + Rwr_ManStop( pManRwr ); + Cut_ManStop( pManCut ); + pNtk->pManCut = NULL; + + // start placement package +// if ( fPlaceEnable ) +// { +// Abc_PlaceEnd( pNtk ); +// Abc_AigUpdateStop( pNtk->pManFunc ); +// } + + // put the nodes into the DFS order and reassign their IDs + { +// int clk = clock(); + Abc_NtkReassignIds( pNtk ); +// PRT( "time", clock() - clk ); + } +// Abc_AigCheckFaninOrder( pNtk->pManFunc ); + // fix the levels + if ( fUpdateLevel ) + Abc_NtkStopReverseLevels( pNtk ); + else + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkRewrite: The network check has failed.\n" ); + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Starts the cut manager for rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ) +{ + static Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pManCut; + Abc_Obj_t * pObj; + int i; + // start the cut manager + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = 4; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 250; // the max number of cuts kept at a node + pParams->fTruth = 1; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fSeq = 0; // compute sequential cuts + pParams->fDrop = 0; // drop cuts on the fly + pParams->fVerbose = 0; // the verbosiness flag + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + pManCut = Cut_ManStart( pParams ); + if ( pParams->fDrop ) + Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( pManCut, pObj->Id ); + return pManCut; +} + +/**Function************************************************************* + + Synopsis [Prints the cuts at the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodePrintCuts( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vCuts; + Cut_Cut_t * pCut; + int k; + + printf( "\nNode %s\n", Abc_ObjName(pNode) ); + vCuts = (Vec_Ptr_t *)pNode->pCopy; + Vec_PtrForEachEntry( vCuts, pCut, k ) + { + Extra_PrintBinary( stdout, (unsigned *)&pCut->uSign, 16 ); + printf( " " ); + Cut_CutPrint( pCut, 0 ); + printf( "\n" ); + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManRewritePrintDivs( Vec_Ptr_t * vDivs, int nLeaves ) +{ + Abc_Obj_t * pFanin, * pNode, * pRoot; + int i, k; + pRoot = Vec_PtrEntryLast(vDivs); + // print the nodes + Vec_PtrForEachEntry( vDivs, pNode, i ) + { + if ( i < nLeaves ) + { + printf( "%6d : %c\n", pNode->Id, 'a'+i ); + continue; + } + printf( "%6d : %2d = ", pNode->Id, i ); + // find the first fanin + Vec_PtrForEachEntry( vDivs, pFanin, k ) + if ( Abc_ObjFanin0(pNode) == pFanin ) + break; + if ( k < nLeaves ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); + // find the second fanin + Vec_PtrForEachEntry( vDivs, pFanin, k ) + if ( Abc_ObjFanin1(pNode) == pFanin ) + break; + if ( k < nLeaves ) + printf( "%c", 'a' + k ); + else + printf( "%d", k ); + printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); + if ( pNode == pRoot ) + printf( " root" ); + printf( "\n" ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManShowCutCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vDivs ) +{ + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + Abc_NodeSetTravIdCurrent(pNode); + Abc_ManShowCutCone_rec( Abc_ObjFanin0(pNode), vDivs ); + Abc_ManShowCutCone_rec( Abc_ObjFanin1(pNode), vDivs ); + Vec_PtrPush( vDivs, pNode ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + Abc_Obj_t * pObj; + Vec_Ptr_t * vDivs; + int i; + vDivs = Vec_PtrAlloc( 100 ); + Abc_NtkIncrementTravId( pNtk ); + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + Abc_NodeSetTravIdCurrent( Abc_ObjRegular(pObj) ); + Vec_PtrPush( vDivs, Abc_ObjRegular(pObj) ); + } + Abc_ManShowCutCone_rec( pNode, vDivs ); + Abc_ManRewritePrintDivs( vDivs, Vec_PtrSize(vLeaves) ); + Vec_PtrFree( vDivs ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RwrExpWithCut_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, int fUseA ) +{ + if ( Vec_PtrFind(vLeaves, pNode) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pNode)) >= 0 ) + { + if ( fUseA ) + Abc_ObjRegular(pNode)->fMarkA = 1; + else + Abc_ObjRegular(pNode)->fMarkB = 1; + return; + } + assert( Abc_ObjIsNode(pNode) ); + Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, fUseA ); + Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, fUseA ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RwrExpWithCut( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) +{ + Abc_Obj_t * pObj; + int i, CountA, CountB; + Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, 1 ); + Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, 0 ); + CountA = CountB = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + CountA += Abc_ObjRegular(pObj)->fMarkA; + CountB += Abc_ObjRegular(pObj)->fMarkB; + Abc_ObjRegular(pObj)->fMarkA = 0; + Abc_ObjRegular(pObj)->fMarkB = 0; + } + printf( "(%d,%d:%d) ", CountA, CountB, CountA+CountB-Vec_PtrSize(vLeaves) ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcRr.c b/abc70930/src/base/abci/abcRr.c new file mode 100644 index 00000000..92adc718 --- /dev/null +++ b/abc70930/src/base/abci/abcRr.c @@ -0,0 +1,999 @@ +/**CFile**************************************************************** + + FileName [abcRr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Redundancy removal.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_RRMan_t_ Abc_RRMan_t; +struct Abc_RRMan_t_ +{ + // the parameters + Abc_Ntk_t * pNtk; // the network + int nFaninLevels; // the number of fanin levels + int nFanoutLevels; // the number of fanout levels + // the node/fanin/fanout + Abc_Obj_t * pNode; // the node + Abc_Obj_t * pFanin; // the fanin + Abc_Obj_t * pFanout; // the fanout + // the intermediate cones + Vec_Ptr_t * vFaninLeaves; // the leaves of the fanin cone + Vec_Ptr_t * vFanoutRoots; // the roots of the fanout cone + // the window + Vec_Ptr_t * vLeaves; // the leaves of the window + Vec_Ptr_t * vCone; // the internal nodes of the window + Vec_Ptr_t * vRoots; // the roots of the window + Abc_Ntk_t * pWnd; // the window derived for the edge + // the miter + Abc_Ntk_t * pMiter; // the miter derived from the window + Prove_Params_t * pParams; // the miter proving parameters + // statistical variables + int nNodesOld; // the old number of nodes + int nLevelsOld; // the old number of levels + int nEdgesTried; // the number of nodes tried + int nEdgesRemoved; // the number of nodes proved + int timeWindow; // the time to construct the window + int timeMiter; // the time to construct the miter + int timeProve; // the time to prove the miter + int timeUpdate; // the network update time + int timeTotal; // the total runtime +}; + +static Abc_RRMan_t * Abc_RRManStart(); +static void Abc_RRManStop( Abc_RRMan_t * p ); +static void Abc_RRManPrintStats( Abc_RRMan_t * p ); +static void Abc_RRManClean( Abc_RRMan_t * p ); +static int Abc_NtkRRProve( Abc_RRMan_t * p ); +static int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ); +static int Abc_NtkRRWindow( Abc_RRMan_t * p ); + +static int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit ); +static int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ); +static int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ); +static void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit ); +static Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots ); + +static void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk ); +static void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Removes stuck-at redundancies.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose ) +{ + ProgressBar * pProgress; + Abc_RRMan_t * p; + Abc_Obj_t * pNode, * pFanin, * pFanout; + int i, k, m, nNodes, RetValue, clk, clkTotal = clock(); + // start the manager + p = Abc_RRManStart( nFaninLevels, nFanoutLevels ); + p->pNtk = pNtk; + p->nFaninLevels = nFaninLevels; + p->nFanoutLevels = nFanoutLevels; + p->nNodesOld = Abc_NtkNodeNum(pNtk); + p->nLevelsOld = Abc_AigLevel(pNtk); + // remember latch values +// Abc_NtkForEachLatch( pNtk, pNode, i ) +// pNode->pNext = pNode->pData; + // go through the nodes + Abc_NtkCleanCopy(pNtk); + nNodes = Abc_NtkObjNumMax(pNtk); + Abc_NtkRRSimulateStart(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // stop if all nodes have been tried once + if ( i >= nNodes ) + break; + // skip the constant node +// if ( Abc_NodeIsConst(pNode) ) +// continue; + // skip persistant nodes + if ( Abc_NodeIsPersistant(pNode) ) + continue; + // skip the nodes with many fanouts + if ( Abc_ObjFanoutNum(pNode) > 1000 ) + continue; + // construct the window + if ( !fUseFanouts ) + { + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + // skip the nodes with only one fanout (tree nodes) + if ( Abc_ObjFanoutNum(pFanin) == 1 ) + continue; +/* + if ( pFanin->Id == 228 && pNode->Id == 2649 ) + { + int k = 0; + } +*/ + p->nEdgesTried++; + Abc_RRManClean( p ); + p->pNode = pNode; + p->pFanin = pFanin; + p->pFanout = NULL; + + clk = clock(); + RetValue = Abc_NtkRRWindow( p ); + p->timeWindow += clock() - clk; + if ( !RetValue ) + continue; +/* + if ( pFanin->Id == 228 && pNode->Id == 2649 ) + { + Abc_NtkShowAig( p->pWnd, 0 ); + } +*/ + clk = clock(); + RetValue = Abc_NtkRRProve( p ); + p->timeMiter += clock() - clk; + if ( !RetValue ) + continue; +//printf( "%d -> %d (%d)\n", pFanin->Id, pNode->Id, k ); + + clk = clock(); + Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); + p->timeUpdate += clock() - clk; + + p->nEdgesRemoved++; + break; + } + continue; + } + // use the fanouts + Abc_ObjForEachFanin( pNode, pFanin, k ) + Abc_ObjForEachFanout( pNode, pFanout, m ) + { + // skip the nodes with only one fanout (tree nodes) +// if ( Abc_ObjFanoutNum(pFanin) == 1 && Abc_ObjFanoutNum(pNode) == 1 ) +// continue; + + p->nEdgesTried++; + Abc_RRManClean( p ); + p->pNode = pNode; + p->pFanin = pFanin; + p->pFanout = pFanout; + + clk = clock(); + RetValue = Abc_NtkRRWindow( p ); + p->timeWindow += clock() - clk; + if ( !RetValue ) + continue; + + clk = clock(); + RetValue = Abc_NtkRRProve( p ); + p->timeMiter += clock() - clk; + if ( !RetValue ) + continue; + + clk = clock(); + Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); + p->timeUpdate += clock() - clk; + + p->nEdgesRemoved++; + break; + } + } + Abc_NtkRRSimulateStop(pNtk); + Extra_ProgressBarStop( pProgress ); + p->timeTotal = clock() - clkTotal; + if ( fVerbose ) + Abc_RRManPrintStats( p ); + Abc_RRManStop( p ); + // restore latch values +// Abc_NtkForEachLatch( pNtk, pNode, i ) +// pNode->pData = pNode->pNext, pNode->pNext = NULL; + // put the nodes into the DFS order and reassign their IDs + Abc_NtkReassignIds( pNtk ); + Abc_NtkLevel( pNtk ); + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkRR: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Start the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_RRMan_t * Abc_RRManStart() +{ + Abc_RRMan_t * p; + p = ALLOC( Abc_RRMan_t, 1 ); + memset( p, 0, sizeof(Abc_RRMan_t) ); + p->vFaninLeaves = Vec_PtrAlloc( 100 ); // the leaves of the fanin cone + p->vFanoutRoots = Vec_PtrAlloc( 100 ); // the roots of the fanout cone + p->vLeaves = Vec_PtrAlloc( 100 ); // the leaves of the window + p->vCone = Vec_PtrAlloc( 100 ); // the internal nodes of the window + p->vRoots = Vec_PtrAlloc( 100 ); // the roots of the window + p->pParams = ALLOC( Prove_Params_t, 1 ); + memset( p->pParams, 0, sizeof(Prove_Params_t) ); + Prove_ParamsSetDefault( p->pParams ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stop the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RRManStop( Abc_RRMan_t * p ) +{ + Abc_RRManClean( p ); + Vec_PtrFree( p->vFaninLeaves ); + Vec_PtrFree( p->vFanoutRoots ); + Vec_PtrFree( p->vLeaves ); + Vec_PtrFree( p->vCone ); + Vec_PtrFree( p->vRoots ); + free( p->pParams ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Stop the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RRManPrintStats( Abc_RRMan_t * p ) +{ + double Ratio = 100.0*(p->nNodesOld - Abc_NtkNodeNum(p->pNtk))/p->nNodesOld; + printf( "Redundancy removal statistics:\n" ); + printf( "Edges tried = %6d.\n", p->nEdgesTried ); + printf( "Edges removed = %6d. (%5.2f %%)\n", p->nEdgesRemoved, 100.0*p->nEdgesRemoved/p->nEdgesTried ); + printf( "Node gain = %6d. (%5.2f %%)\n", p->nNodesOld - Abc_NtkNodeNum(p->pNtk), Ratio ); + printf( "Level gain = %6d.\n", p->nLevelsOld - Abc_AigLevel(p->pNtk) ); + PRT( "Windowing ", p->timeWindow ); + PRT( "Miter ", p->timeMiter ); + PRT( " Construct ", p->timeMiter - p->timeProve ); + PRT( " Prove ", p->timeProve ); + PRT( "Update ", p->timeUpdate ); + PRT( "TOTAL ", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Clean the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_RRManClean( Abc_RRMan_t * p ) +{ + p->pNode = NULL; + p->pFanin = NULL; + p->pFanout = NULL; + Vec_PtrClear( p->vFaninLeaves ); + Vec_PtrClear( p->vFanoutRoots ); + Vec_PtrClear( p->vLeaves ); + Vec_PtrClear( p->vCone ); + Vec_PtrClear( p->vRoots ); + if ( p->pWnd ) Abc_NtkDelete( p->pWnd ); + if ( p->pMiter ) Abc_NtkDelete( p->pMiter ); + p->pWnd = NULL; + p->pMiter = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the miter is constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRProve( Abc_RRMan_t * p ) +{ + Abc_Ntk_t * pWndCopy; + int RetValue, clk; +// Abc_NtkShowAig( p->pWnd, 0 ); + pWndCopy = Abc_NtkDup( p->pWnd ); + Abc_NtkRRUpdate( pWndCopy, p->pNode->pCopy->pCopy, p->pFanin->pCopy->pCopy, p->pFanout? p->pFanout->pCopy->pCopy : NULL ); + if ( !Abc_NtkIsDfsOrdered(pWndCopy) ) + Abc_NtkReassignIds(pWndCopy); + p->pMiter = Abc_NtkMiter( p->pWnd, pWndCopy, 1, 0 ); + Abc_NtkDelete( pWndCopy ); +clk = clock(); + RetValue = Abc_NtkMiterProve( &p->pMiter, p->pParams ); +p->timeProve += clock() - clk; + if ( RetValue == 1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Updates the network after redundancy removal.] + + Description [This procedure assumes that non-control value of the fanin + was proved redundant. It is okay to concentrate on non-control values + because the control values can be seen as redundancy of the fanout edge.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ) +{ + Abc_Obj_t * pNodeNew, * pFanoutNew; + assert( pFanout == NULL ); + assert( !Abc_ObjIsComplement(pNode) ); + assert( !Abc_ObjIsComplement(pFanin) ); + assert( !Abc_ObjIsComplement(pFanout) ); + // find the node after redundancy removal + if ( pFanin == Abc_ObjFanin0(pNode) ) + pNodeNew = Abc_ObjChild1(pNode); + else if ( pFanin == Abc_ObjFanin1(pNode) ) + pNodeNew = Abc_ObjChild0(pNode); + else assert( 0 ); + // replace + if ( pFanout == NULL ) + { + Abc_AigReplace( pNtk->pManFunc, pNode, pNodeNew, 1 ); + return 1; + } + // find the fanout after redundancy removal + if ( pNode == Abc_ObjFanin0(pFanout) ) + pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC0(pFanout)), Abc_ObjChild1(pFanout) ); + else if ( pNode == Abc_ObjFanin1(pFanout) ) + pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC1(pFanout)), Abc_ObjChild0(pFanout) ); + else assert( 0 ); + // replace + Abc_AigReplace( pNtk->pManFunc, pFanout, pFanoutNew, 1 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Constructs window for checking RR.] + + Description [If the window (p->pWnd) with the given scope (p->nFaninLevels, + p->nFanoutLevels) cannot be constructed, returns 0. Otherwise, returns 1. + The levels are measured from the fanin node (pFanin) and the fanout node + (pEdgeFanout), respectively.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRWindow( Abc_RRMan_t * p ) +{ + Abc_Obj_t * pObj, * pEdgeFanin, * pEdgeFanout; + int i, LevelMin, LevelMax, RetValue; + + // get the edge + pEdgeFanout = p->pFanout? p->pFanout : p->pNode; + pEdgeFanin = p->pFanout? p->pNode : p->pFanin; + // get the minimum and maximum levels of the window + LevelMin = ABC_MAX( 0, ((int)p->pFanin->Level) - p->nFaninLevels ); + LevelMax = (int)pEdgeFanout->Level + p->nFanoutLevels; + + // start the TFI leaves with the fanin + Abc_NtkIncrementTravId( p->pNtk ); + Abc_NodeSetTravIdCurrent( p->pFanin ); + Vec_PtrPush( p->vFaninLeaves, p->pFanin ); + // mark the TFI cone and collect the leaves down to the given level + while ( Abc_NtkRRTfi_int(p->vFaninLeaves, LevelMin) ); + + // mark the leaves with the new TravId + Abc_NtkIncrementTravId( p->pNtk ); + Vec_PtrForEachEntry( p->vFaninLeaves, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // traverse the TFO cone of the leaves (while skipping the edge) + // (a) mark the nodes in the cone using the current TravId + // (b) collect the nodes that have external fanouts into p->vFanoutRoots + while ( Abc_NtkRRTfo_int(p->vFaninLeaves, p->vFanoutRoots, LevelMax, pEdgeFanin, pEdgeFanout) ); + + // mark the fanout roots + Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i ) + pObj->fMarkA = 1; + // collect roots reachable from the fanout (p->vRoots) + RetValue = Abc_NtkRRTfo_rec( pEdgeFanout, p->vRoots, LevelMax + 1 ); + // unmark the fanout roots + Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i ) + pObj->fMarkA = 0; + + // return if the window is infeasible + if ( RetValue == 0 ) + return 0; + + // collect the DFS-ordered new cone (p->vCone) and new leaves (p->vLeaves) + // using the previous marks coming from the TFO cone + Abc_NtkIncrementTravId( p->pNtk ); + Vec_PtrForEachEntry( p->vRoots, pObj, i ) + Abc_NtkRRTfi_rec( pObj, p->vLeaves, p->vCone, LevelMin ); + + // create a new network + p->pWnd = Abc_NtkWindow( p->pNtk, p->vLeaves, p->vCone, p->vRoots ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes in the TFI and collects their leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit ) +{ + Abc_Obj_t * pObj, * pNext; + int i, k, LevelMax, nSize; + assert( LevelLimit >= 0 ); + // find the maximum level of leaves + LevelMax = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + if ( LevelMax < (int)pObj->Level ) + LevelMax = pObj->Level; + // if the nodes are all PIs, LevelMax == 0 + if ( LevelMax <= LevelLimit ) + return 0; + // expand the nodes with the minimum level + nSize = Vec_PtrSize(vLeaves); + Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize ) + { + if ( LevelMax != (int)pObj->Level ) + continue; + Abc_ObjForEachFanin( pObj, pNext, k ) + { + if ( Abc_NodeIsTravIdCurrent(pNext) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vLeaves, pNext ); + } + } + // remove old nodes (cannot remove a PI) + k = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + if ( LevelMax == (int)pObj->Level ) + continue; + Vec_PtrWriteEntry( vLeaves, k++, pObj ); + } + Vec_PtrShrink( vLeaves, k ); + if ( Vec_PtrSize(vLeaves) > 2000 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes in the TFO and collects their roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ) +{ + Abc_Obj_t * pObj, * pNext; + int i, k, LevelMin, nSize, fObjIsRoot; + // find the minimum level of leaves + LevelMin = ABC_INFINITY; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + if ( LevelMin > (int)pObj->Level ) + LevelMin = pObj->Level; + // if the minimum level exceed the limit, we are done + if ( LevelMin > LevelLimit ) + return 0; + // expand the nodes with the minimum level + nSize = Vec_PtrSize(vLeaves); + Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize ) + { + if ( LevelMin != (int)pObj->Level ) + continue; + fObjIsRoot = 0; + Abc_ObjForEachFanout( pObj, pNext, k ) + { + // check if the fanout is outside of the cone + if ( Abc_ObjIsCo(pNext) || pNext->Level > (unsigned)LevelLimit ) + { + fObjIsRoot = 1; + continue; + } + // skip the edge under check + if ( pObj == pEdgeFanin && pNext == pEdgeFanout ) + continue; + // skip the visited fanouts + if ( Abc_NodeIsTravIdCurrent(pNext) ) + continue; + Abc_NodeSetTravIdCurrent( pNext ); + Vec_PtrPush( vLeaves, pNext ); + } + if ( fObjIsRoot ) + Vec_PtrPush( vRoots, pObj ); + } + // remove old nodes + k = 0; + Vec_PtrForEachEntry( vLeaves, pObj, i ) + { + if ( LevelMin == (int)pObj->Level ) + continue; + Vec_PtrWriteEntry( vLeaves, k++, pObj ); + } + Vec_PtrShrink( vLeaves, k ); + if ( Vec_PtrSize(vLeaves) > 2000 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Collects the roots in the TFO of the node.] + + Description [Note that this procedure can be improved by + marking and skipping the visited nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ) +{ + Abc_Obj_t * pFanout; + int i; + // if we encountered a node outside of the TFO cone of the fanins, quit + if ( Abc_ObjIsCo(pNode) || pNode->Level > (unsigned)LevelLimit ) + return 0; + // if we encountered a node on the boundary, add it to the roots + if ( pNode->fMarkA ) + { + Vec_PtrPushUnique( vRoots, pNode ); + return 1; + } + // mark the node with the current TravId (needed to have all internal nodes marked) + Abc_NodeSetTravIdCurrent( pNode ); + // traverse the fanouts + Abc_ObjForEachFanout( pNode, pFanout, i ) + if ( !Abc_NtkRRTfo_rec( pFanout, vRoots, LevelLimit ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Collects the leaves and cone of the roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit ) +{ + Abc_Obj_t * pFanin; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + // add node to leaves if it is not in TFI cone of the leaves (marked before) or below the limit + if ( !Abc_NodeIsTravIdPrevious(pNode) || (int)pNode->Level <= LevelLimit ) + { + Abc_NodeSetTravIdCurrent( pNode ); + Vec_PtrPush( vLeaves, pNode ); + return; + } + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // call for the node's fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkRRTfi_rec( pFanin, vLeaves, vCone, LevelLimit ); + // add the node to the cone in topological order + Vec_PtrPush( vCone, pNode ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + int fCheck = 1; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( "temp" ); + // map the constant nodes + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // create and map the PIs + Vec_PtrForEachEntry( vLeaves, pObj, i ) + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + // copy the AND gates + Vec_PtrForEachEntry( vCone, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // compare the number of nodes before and after + if ( Vec_PtrSize(vCone) != Abc_NtkNodeNum(pNtkNew) ) + printf( "Warning: Structural hashing during windowing reduced %d nodes (this is a bug).\n", + Vec_PtrSize(vCone) - Abc_NtkNodeNum(pNtkNew) ); + // create the POs + Vec_PtrForEachEntry( vRoots, pObj, i ) + { + assert( !Abc_ObjIsComplement(pObj->pCopy) ); + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObj->pCopy ); + } + // add the PI/PO names + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + Abc_NtkAddDummyAssertNames( pNtkNew ); + // check + if ( fCheck && !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkWindow: The network check has failed.\n" ); + return NULL; + } + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Starts simulation to detect non-redundant edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + unsigned uData, uData0, uData1; + int i; + Abc_AigConst1(pNtk)->pData = (void *)~((unsigned)0); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pData = (void *)SIM_RANDOM_UNSIGNED; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) continue; + uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; + uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData; + uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0; + uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1; + assert( pObj->pData == NULL ); + pObj->pData = (void *)uData; + } +} + +/**Function************************************************************* + + Synopsis [Stops simulation to detect non-redundant edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pData = NULL; +} + + + + + + + +static void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes ); +static void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField ); +static void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField ); + +/**Function************************************************************* + + Synopsis [Simulation to detect non-redundant edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Abc_NtkRRSimulate( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes, * vField; + Vec_Str_t * vTargets; + Abc_Obj_t * pObj; + unsigned uData, uData0, uData1; + int PrevCi, Phase, i, k; + + // start the candidates + vTargets = Vec_StrStart( Abc_NtkObjNumMax(pNtk) + 1 ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Phase = ((Abc_ObjFanoutNum(Abc_ObjFanin1(pObj)) > 1) << 1); + Phase |= (Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) > 1); + Vec_StrWriteEntry( vTargets, pObj->Id, (char)Phase ); + } + + // simulate patters and store them in copy + Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)~((unsigned)0); + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)SIM_RANDOM_UNSIGNED; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) continue; + uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; + uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData; + uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0; + uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1; + pObj->pCopy = (Abc_Obj_t *)uData; + } + // store the result in data + Abc_NtkForEachCo( pNtk, pObj, i ) + { + uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; + if ( Abc_ObjFaninC0(pObj) ) + pObj->pData = (void *)~uData0; + else + pObj->pData = (void *)uData0; + } + + // refine the candidates + for ( PrevCi = 0; PrevCi < Abc_NtkCiNum(pNtk); PrevCi = i ) + { + vNodes = Vec_PtrAlloc( 10 ); + Abc_NtkIncrementTravId( pNtk ); + for ( i = PrevCi; i < Abc_NtkCiNum(pNtk); i++ ) + { + Sim_TraverseNodes_rec( Abc_NtkCi(pNtk, i), vTargets, vNodes ); + if ( Vec_PtrSize(vNodes) > 128 ) + break; + } + // collect the marked nodes in the topological order + vField = Vec_PtrAlloc( 10 ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pObj, k ) + Sim_CollectNodes_rec( pObj, vField ); + + // simulate these nodes + Sim_SimulateCollected( vTargets, vNodes, vField ); + // prepare for the next loop + Vec_PtrFree( vNodes ); + } + + // clean + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pData = NULL; + return vTargets; +} + +/**Function************************************************************* + + Synopsis [Collects nodes starting from the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + char Entry; + int k; + if ( Abc_NodeIsTravIdCurrent(pRoot) ) + return; + Abc_NodeSetTravIdCurrent( pRoot ); + // save the reached targets + Entry = Vec_StrEntry(vTargets, pRoot->Id); + if ( Entry & 1 ) + Vec_PtrPush( vNodes, Abc_ObjNot(pRoot) ); + if ( Entry & 2 ) + Vec_PtrPush( vNodes, pRoot ); + // explore the fanouts + Abc_ObjForEachFanout( pRoot, pFanout, k ) + Sim_TraverseNodes_rec( pFanout, vTargets, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes starting from the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField ) +{ + Abc_Obj_t * pFanin; + int i; + if ( Abc_NodeIsTravIdCurrent(pRoot) ) + return; + if ( !Abc_NodeIsTravIdPrevious(pRoot) ) + return; + Abc_NodeSetTravIdCurrent( pRoot ); + Abc_ObjForEachFanin( pRoot, pFanin, i ) + Sim_CollectNodes_rec( pFanin, vField ); + if ( !Abc_ObjIsCo(pRoot) ) + pRoot->pData = (void *)Vec_PtrSize(vField); + Vec_PtrPush( vField, pRoot ); +} + +/**Function************************************************************* + + Synopsis [Simulate the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField ) +{ + Abc_Obj_t * pObj, * pFanin0, * pFanin1, * pDisproved; + Vec_Ptr_t * vSims; + unsigned * pUnsigned, * pUnsignedF; + int i, k, Phase, fCompl; + // get simulation info + vSims = Sim_UtilInfoAlloc( Vec_PtrSize(vField), Vec_PtrSize(vNodes), 0 ); + // simulate the nodes + Vec_PtrForEachEntry( vField, pObj, i ) + { + if ( Abc_ObjIsCi(pObj) ) + { + pUnsigned = Vec_PtrEntry( vSims, i ); + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + pUnsigned[k] = (unsigned)pObj->pCopy; + continue; + } + if ( Abc_ObjIsCo(pObj) ) + { + pUnsigned = Vec_PtrEntry( vSims, i ); + pUnsignedF = Vec_PtrEntry( vSims, (int)Abc_ObjFanin0(pObj)->pData ); + if ( Abc_ObjFaninC0(pObj) ) + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + pUnsigned[k] = ~pUnsignedF[k]; + else + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + pUnsigned[k] = pUnsignedF[k]; + // update targets + for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) + { + if ( pUnsigned[k] == (unsigned)pObj->pData ) + continue; + pDisproved = Vec_PtrEntry( vNodes, k ); + fCompl = Abc_ObjIsComplement(pDisproved); + pDisproved = Abc_ObjRegular(pDisproved); + Phase = Vec_StrEntry( vTargets, pDisproved->Id ); + if ( fCompl ) + Phase = (Phase & 2); + else + Phase = (Phase & 1); + Vec_StrWriteEntry( vTargets, pDisproved->Id, (char)Phase ); + } + continue; + } + // simulate the node + pFanin0 = Abc_ObjFanin0(pObj); + pFanin1 = Abc_ObjFanin1(pObj); + } +} + + + +/* + { + unsigned uData; + if ( pFanin == Abc_ObjFanin0(pNode) ) + { + uData = (unsigned)Abc_ObjFanin1(pNode)->pData; + uData = Abc_ObjFaninC1(pNode)? ~uData : uData; + } + else if ( pFanin == Abc_ObjFanin1(pNode) ) + { + uData = (unsigned)Abc_ObjFanin0(pNode)->pData; + uData = Abc_ObjFaninC0(pNode)? ~uData : uData; + } + uData ^= (unsigned)pNode->pData; +// Extra_PrintBinary( stdout, &uData, 32 ); printf( "\n" ); + if ( Extra_WordCountOnes(uData) > 8 ) + continue; + } +*/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcSat.c b/abc70930/src/base/abci/abcSat.c new file mode 100644 index 00000000..58614584 --- /dev/null +++ b/abc70930/src/base/abci/abcSat.c @@ -0,0 +1,884 @@ +/**CFile**************************************************************** + + FileName [abcSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to solve the miter using the internal SAT sat_solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "satSolver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes ); +extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); +static nMuxes; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Attempts to solve the miter using an internal SAT sat_solver.] + + Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects ) +{ + sat_solver * pSat; + lbool status; + int RetValue, clk; + + if ( pNumConfs ) + *pNumConfs = 0; + if ( pNumInspects ) + *pNumInspects = 0; + + assert( Abc_NtkLatchNum(pNtk) == 0 ); + +// if ( Abc_NtkPoNum(pNtk) > 1 ) +// fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) ); + + // load clauses into the sat_solver + clk = clock(); + pSat = Abc_NtkMiterSatCreate( pNtk, 0 ); + if ( pSat == NULL ) + return 1; +//printf( "%d \n", pSat->clauses.size ); +//sat_solver_delete( pSat ); +//return 1; + +// printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); +// PRT( "Time", clock() - clk ); + + // simplify the problem + clk = clock(); + status = sat_solver_simplify(pSat); +// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); +// PRT( "Time", clock() - clk ); + if ( status == 0 ) + { + sat_solver_delete( pSat ); +// printf( "The problem is UNSATISFIABLE after simplification.\n" ); + return 1; + } + + // solve the miter + clk = clock(); + if ( fVerbose ) + pSat->verbosity = 1; + status = sat_solver_solve( pSat, NULL, NULL, (sint64)nConfLimit, (sint64)nInsLimit, (sint64)0, (sint64)0 ); + if ( status == l_Undef ) + { +// printf( "The problem timed out.\n" ); + RetValue = -1; + } + else if ( status == l_True ) + { +// printf( "The problem is SATISFIABLE.\n" ); + RetValue = 0; + } + else if ( status == l_False ) + { +// printf( "The problem is UNSATISFIABLE.\n" ); + RetValue = 1; + } + else + assert( 0 ); +// PRT( "SAT sat_solver time", clock() - clk ); +// printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts ); + + // if the problem is SAT, get the counterexample + if ( status == l_True ) + { +// Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk ); + Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); + pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); + Vec_IntFree( vCiIds ); + } + // free the sat_solver + if ( fVerbose ) + Sat_SolverPrintStats( stdout, pSat ); + + if ( pNumConfs ) + *pNumConfs = (int)pSat->stats.conflicts; + if ( pNumInspects ) + *pNumInspects = (int)pSat->stats.inspects; + +sat_solver_store_write( pSat, "trace.cnf" ); +sat_solver_store_free( pSat ); + + sat_solver_delete( pSat ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns the array of CI IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vCiIds; + Abc_Obj_t * pObj; + int i; + vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Vec_IntPush( vCiIds, (int)pObj->pCopy ); + return vCiIds; +} + + + +/**Function************************************************************* + + Synopsis [Adds trivial clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkClauseTriv( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) +{ +//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses ); + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) ); +// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) ); + return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); +} + +/**Function************************************************************* + + Synopsis [Adds trivial clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkClauseTop( sat_solver * pSat, Vec_Ptr_t * vNodes, Vec_Int_t * vVars ) +{ + Abc_Obj_t * pNode; + int i; +//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses ); + vVars->nSize = 0; + Vec_PtrForEachEntry( vNodes, pNode, i ) + Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) ); +// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) ); + return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); +} + +/**Function************************************************************* + + Synopsis [Adds trivial clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkClauseAnd( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, Vec_Int_t * vVars ) +{ + int fComp1, Var, Var1, i; +//printf( "Adding AND %d. (%d) %d\n", pNode->Id, vSuper->nSize+1, (int)pSat->sat_solver_stats.clauses ); + + assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + +// nVars = sat_solver_nvars(pSat); + Var = (int)pNode->pCopy; +// Var = pNode->Id; + +// assert( Var < nVars ); + for ( i = 0; i < vSuper->nSize; i++ ) + { + // get the predecessor nodes + // get the complemented attributes of the nodes + fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]); + // determine the variable numbers + Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy; +// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id; + + // check that the variables are in the SAT manager +// assert( Var1 < nVars ); + + // suppose the AND-gate is A * B = C + // add !A => !C or A + !C + // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 ); + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(Var1, fComp1) ); + Vec_IntPush( vVars, toLitCond(Var, 1 ) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + } + + // add A & B => C or !A + !B + C +// fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 ); + vVars->nSize = 0; + for ( i = 0; i < vSuper->nSize; i++ ) + { + // get the predecessor nodes + // get the complemented attributes of the nodes + fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]); + // determine the variable numbers + Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy; +// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id; + // add this variable to the array + Vec_IntPush( vVars, toLitCond(Var1, !fComp1) ); + } + Vec_IntPush( vVars, toLitCond(Var, 0) ); + return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); +} + +/**Function************************************************************* + + Synopsis [Adds trivial clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkClauseMux( sat_solver * pSat, Abc_Obj_t * pNode, Abc_Obj_t * pNodeC, Abc_Obj_t * pNodeT, Abc_Obj_t * pNodeE, Vec_Int_t * vVars ) +{ + int VarF, VarI, VarT, VarE, fCompT, fCompE; +//printf( "Adding mux %d. %d\n", pNode->Id, (int)pSat->sat_solver_stats.clauses ); + + assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_NodeIsMuxType( pNode ) ); + // get the variable numbers + VarF = (int)pNode->pCopy; + VarI = (int)pNodeC->pCopy; + VarT = (int)Abc_ObjRegular(pNodeT)->pCopy; + VarE = (int)Abc_ObjRegular(pNodeE)->pCopy; +// VarF = (int)pNode->Id; +// VarI = (int)pNodeC->Id; +// VarT = (int)Abc_ObjRegular(pNodeT)->Id; +// VarE = (int)Abc_ObjRegular(pNodeE)->Id; + + // get the complementation flags + fCompT = Abc_ObjIsComplement(pNodeT); + fCompE = Abc_ObjIsComplement(pNodeE); + + // f = ITE(i, t, e) + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + // create four clauses + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarI, 1) ); + Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) ); + Vec_IntPush( vVars, toLitCond(VarF, 0) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarI, 1) ); + Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) ); + Vec_IntPush( vVars, toLitCond(VarF, 1) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarI, 0) ); + Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) ); + Vec_IntPush( vVars, toLitCond(VarF, 0) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarI, 0) ); + Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) ); + Vec_IntPush( vVars, toLitCond(VarF, 1) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return 1; + } + + // two additional clauses + // t' & e' -> f' t + e + f' + // t & e -> f t' + e' + f + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) ); + Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) ); + Vec_IntPush( vVars, toLitCond(VarF, 1) ); + if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) + return 0; + vVars->nSize = 0; + Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) ); + Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) ); + Vec_IntPush( vVars, toLitCond(VarF, 0) ); + return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCollectSupergate_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fStopAtMux ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Abc_ObjRegular(pNode)->fMarkB ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pNode ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Abc_ObjNot(pNode) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( !fFirst ) + if ( Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || Abc_ObjFanoutNum(pNode) > 1 || fStopAtMux && Abc_NodeIsMuxType(pNode) ) + { + Vec_PtrPush( vSuper, pNode ); + Abc_ObjRegular(pNode)->fMarkB = 1; + return 0; + } + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + // go through the branches + RetValue1 = Abc_NtkCollectSupergate_rec( Abc_ObjChild0(pNode), vSuper, 0, fStopAtMux ); + RetValue2 = Abc_NtkCollectSupergate_rec( Abc_ObjChild1(pNode), vSuper, 0, fStopAtMux ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNodes ) +{ + int RetValue, i; + assert( !Abc_ObjIsComplement(pNode) ); + // collect the nodes in the implication supergate + Vec_PtrClear( vNodes ); + RetValue = Abc_NtkCollectSupergate_rec( pNode, vNodes, 1, fStopAtMux ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; +} + + +/**Function************************************************************* + + Synopsis [Computes the factor of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkNodeFactor( Abc_Obj_t * pObj, int nLevelMax ) +{ +// nLevelMax = ((nLevelMax)/2)*3; + assert( (int)pObj->Level <= nLevelMax ); +// return (int)(100000000.0 * pow(0.999, nLevelMax - pObj->Level)); + return (int)(100000000.0 * (1 + 0.01 * pObj->Level)); +// return (int)(100000000.0 / ((nLevelMax)/2)*3 - pObj->Level); +} + +/**Function************************************************************* + + Synopsis [Sets up the SAT sat_solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMiterSatCreateInt( sat_solver * pSat, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE; + Vec_Ptr_t * vNodes, * vSuper; + Vec_Int_t * vVars; + int i, k, fUseMuxes = 1; + int clk1 = clock(); +// int fOrderCiVarsFirst = 0; + int nLevelsMax = Abc_AigLevel(pNtk); + int RetValue = 0; + + assert( Abc_NtkIsStrash(pNtk) ); + + // clean the CI node pointers + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = NULL; + + // start the data structures + vNodes = Vec_PtrAlloc( 1000 ); // the nodes corresponding to vars in the sat_solver + vSuper = Vec_PtrAlloc( 100 ); // the nodes belonging to the given implication supergate + vVars = Vec_IntAlloc( 100 ); // the temporary array for variables in the clause + + // add the clause for the constant node + pNode = Abc_AigConst1(pNtk); + pNode->fMarkA = 1; + pNode->pCopy = (Abc_Obj_t *)vNodes->nSize; + Vec_PtrPush( vNodes, pNode ); + Abc_NtkClauseTriv( pSat, pNode, vVars ); +/* + // add the PI variables first + Abc_NtkForEachCi( pNtk, pNode, i ) + { + pNode->fMarkA = 1; + pNode->pCopy = (Abc_Obj_t *)vNodes->nSize; + Vec_PtrPush( vNodes, pNode ); + } +*/ + // collect the nodes that need clauses and top-level assignments + Vec_PtrClear( vSuper ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // get the fanin + pFanin = Abc_ObjFanin0(pNode); + // create the node's variable + if ( pFanin->fMarkA == 0 ) + { + pFanin->fMarkA = 1; + pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize; + Vec_PtrPush( vNodes, pFanin ); + } + // add the trivial clause + Vec_PtrPush( vSuper, Abc_ObjChild0(pNode) ); + } + if ( !Abc_NtkClauseTop( pSat, vSuper, vVars ) ) + goto Quits; + + + // add the clauses + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + assert( !Abc_ObjIsComplement(pNode) ); + if ( !Abc_AigNodeIsAnd(pNode) ) + continue; +//printf( "%d ", pNode->Id ); + + // add the clauses + if ( fUseMuxes && Abc_NodeIsMuxType(pNode) ) + { + nMuxes++; + + pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); + Vec_PtrClear( vSuper ); + Vec_PtrPush( vSuper, pNodeC ); + Vec_PtrPush( vSuper, pNodeT ); + Vec_PtrPush( vSuper, pNodeE ); + // add the fanin nodes to explore + Vec_PtrForEachEntry( vSuper, pFanin, k ) + { + pFanin = Abc_ObjRegular(pFanin); + if ( pFanin->fMarkA == 0 ) + { + pFanin->fMarkA = 1; + pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize; + Vec_PtrPush( vNodes, pFanin ); + } + } + // add the clauses + if ( !Abc_NtkClauseMux( pSat, pNode, pNodeC, pNodeT, pNodeE, vVars ) ) + goto Quits; + } + else + { + // get the supergate + Abc_NtkCollectSupergate( pNode, fUseMuxes, vSuper ); + // add the fanin nodes to explore + Vec_PtrForEachEntry( vSuper, pFanin, k ) + { + pFanin = Abc_ObjRegular(pFanin); + if ( pFanin->fMarkA == 0 ) + { + pFanin->fMarkA = 1; + pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize; + Vec_PtrPush( vNodes, pFanin ); + } + } + // add the clauses + if ( vSuper->nSize == 0 ) + { + if ( !Abc_NtkClauseTriv( pSat, Abc_ObjNot(pNode), vVars ) ) +// if ( !Abc_NtkClauseTriv( pSat, pNode, vVars ) ) + goto Quits; + } + else + { + if ( !Abc_NtkClauseAnd( pSat, pNode, vSuper, vVars ) ) + goto Quits; + } + } + } +/* + // set preferred variables + if ( fOrderCiVarsFirst ) + { + int * pPrefVars = ALLOC( int, Abc_NtkCiNum(pNtk) ); + int nVars = 0; + Abc_NtkForEachCi( pNtk, pNode, i ) + { + if ( pNode->fMarkA == 0 ) + continue; + pPrefVars[nVars++] = (int)pNode->pCopy; + } + nVars = ABC_MIN( nVars, 10 ); + ASat_SolverSetPrefVars( pSat, pPrefVars, nVars ); + } +*/ + RetValue = 1; +Quits : + // delete + Vec_IntFree( vVars ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vSuper ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Sets up the SAT sat_solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes ) +{ + sat_solver * pSat; + Abc_Obj_t * pNode; + int RetValue, i, clk = clock(); + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsBddLogic(pNtk) ); + if ( Abc_NtkIsBddLogic(pNtk) ) + return Abc_NtkMiterSatCreateLogic(pNtk, fAllPrimes); + + nMuxes = 0; + pSat = sat_solver_new(); +//sat_solver_store_alloc( pSat ); + RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk ); +sat_solver_store_mark_roots( pSat ); + + Abc_NtkForEachObj( pNtk, pNode, i ) + pNode->fMarkA = 0; +// ASat_SolverWriteDimacs( pSat, "temp_sat.cnf", NULL, NULL, 1 ); + if ( RetValue == 0 ) + { + sat_solver_delete(pSat); + return NULL; + } +// printf( "Ands = %6d. Muxes = %6d (%5.2f %%). ", Abc_NtkNodeNum(pNtk), nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) ); +// PRT( "Creating sat_solver", clock() - clk ); + return pSat; +} + + + + +/**Function************************************************************* + + Synopsis [Adds clauses for the internal node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeAddClauses( sat_solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars ) +{ + Abc_Obj_t * pFanin; + int i, c, nFanins; + int RetValue; + char * pCube; + + nFanins = Abc_ObjFaninNum( pNode ); + assert( nFanins == Abc_SopGetVarNum( pSop0 ) ); + +// if ( nFanins == 0 ) + if ( Cudd_Regular(pNode->pData) == Cudd_ReadOne(pNode->pNtk->pManFunc) ) + { + vVars->nSize = 0; +// if ( Abc_SopIsConst1(pSop1) ) + if ( !Cudd_IsComplement(pNode->pData) ) + Vec_IntPush( vVars, toLit(pNode->Id) ); + else + Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + return 1; + } + + // add clauses for the negative phase + for ( c = 0; ; c++ ) + { + // get the cube + pCube = pSop0 + c * (nFanins + 3); + if ( *pCube == 0 ) + break; + // add the clause + vVars->nSize = 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pCube[i] == '0' ) + Vec_IntPush( vVars, toLit(pFanin->Id) ); + else if ( pCube[i] == '1' ) + Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); + } + Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + } + + // add clauses for the positive phase + for ( c = 0; ; c++ ) + { + // get the cube + pCube = pSop1 + c * (nFanins + 3); + if ( *pCube == 0 ) + break; + // add the clause + vVars->nSize = 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pCube[i] == '0' ) + Vec_IntPush( vVars, toLit(pFanin->Id) ); + else if ( pCube[i] == '1' ) + Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); + } + Vec_IntPush( vVars, toLit(pNode->Id) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds clauses for the PO node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) +{ + Abc_Obj_t * pFanin; + int RetValue; + + pFanin = Abc_ObjFanin0(pNode); + if ( Abc_ObjFaninC0(pNode) ) + { + vVars->nSize = 0; + Vec_IntPush( vVars, toLit(pFanin->Id) ); + Vec_IntPush( vVars, toLit(pNode->Id) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + + vVars->nSize = 0; + Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); + Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + } + else + { + vVars->nSize = 0; + Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); + Vec_IntPush( vVars, toLit(pNode->Id) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + + vVars->nSize = 0; + Vec_IntPush( vVars, toLit(pFanin->Id) ); + Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + } + + vVars->nSize = 0; + Vec_IntPush( vVars, toLit(pNode->Id) ); + RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); + if ( !RetValue ) + { + printf( "The CNF is trivially UNSAT.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Sets up the SAT sat_solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes ) +{ + sat_solver * pSat; + Extra_MmFlex_t * pMmFlex; + Abc_Obj_t * pNode; + Vec_Str_t * vCube; + Vec_Int_t * vVars; + char * pSop0, * pSop1; + int i; + + assert( Abc_NtkIsBddLogic(pNtk) ); + + // transfer the IDs to the copy field + Abc_NtkForEachPi( pNtk, pNode, i ) + pNode->pCopy = (void *)pNode->Id; + + // start the data structures + pSat = sat_solver_new(); +sat_solver_store_alloc( pSat ); + pMmFlex = Extra_MmFlexStart(); + vCube = Vec_StrAlloc( 100 ); + vVars = Vec_IntAlloc( 100 ); + + // add clauses for each internal nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // derive SOPs for both phases of the node + Abc_NodeBddToCnf( pNode, pMmFlex, vCube, fAllPrimes, &pSop0, &pSop1 ); + // add the clauses to the sat_solver + if ( !Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars ) ) + { + sat_solver_delete( pSat ); + pSat = NULL; + goto finish; + } + } + // add clauses for each PO + Abc_NtkForEachPo( pNtk, pNode, i ) + { + if ( !Abc_NodeAddClausesTop( pSat, pNode, vVars ) ) + { + sat_solver_delete( pSat ); + pSat = NULL; + goto finish; + } + } +sat_solver_store_mark_roots( pSat ); + +finish: + // delete + Vec_StrFree( vCube ); + Vec_IntFree( vVars ); + Extra_MmFlexStop( pMmFlex ); + return pSat; +} + + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcStrash.c b/abc70930/src/base/abci/abcStrash.c new file mode 100644 index 00000000..c77f8dea --- /dev/null +++ b/abc70930/src/base/abci/abcStrash.c @@ -0,0 +1,478 @@ +/**CFile**************************************************************** + + FileName [abcStrash.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Strashing of the current network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "extra.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reapplies structural hashing to the AIG.] + + Description [Because of the structural hashing, this procedure should not + change the number of nodes. It is useful to detect the bugs in the original AIG.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup ) +{ + extern int timeRetime; + Abc_Ntk_t * pNtkAig; + Abc_Obj_t * pObj; + int i, nNodes;//, RetValue; + assert( Abc_NtkIsStrash(pNtk) ); +//timeRetime = clock(); + // print warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" ); + // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // restrash the nodes (assuming a topological order of the old network) + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // finalize the network + Abc_NtkFinalize( pNtk, pNtkAig ); + // print warning about self-feed latches +// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) +// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); + // perform cleanup if requested + if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) + printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } +//timeRetime = clock() - timeRetime; +// if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) ) +// printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue ); + return pNtkAig; + +} + +/**Function************************************************************* + + Synopsis [Reapplies structural hashing to the AIG.] + + Description [Because of the structural hashing, this procedure should not + change the number of nodes. It is useful to detect the bugs in the original AIG.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, bool fCleanup ) +{ + extern int timeRetime; + Abc_Ntk_t * pNtkAig; + Abc_Obj_t * pObj; + int i, nNodes;//, RetValue; + assert( Abc_NtkIsStrash(pNtk) ); +//timeRetime = clock(); + // print warning about choice nodes + if ( Abc_NtkGetChoiceNum( pNtk ) ) + printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" ); + // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + // complement the 1-values registers + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( Abc_LatchIsInit1(pObj) ) + Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy); + // restrash the nodes (assuming a topological order of the old network) + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // finalize the network + Abc_NtkFinalize( pNtk, pNtkAig ); + // complement the 1-valued registers + Abc_NtkForEachLatch( pNtkAig, pObj, i ) + if ( Abc_LatchIsInit1(pObj) ) + Abc_ObjXorFaninC( Abc_ObjFanin0(pObj), 0 ); + // set all constant-0 values + Abc_NtkForEachLatch( pNtkAig, pObj, i ) + Abc_LatchSetInit0( pObj ); + + // print warning about self-feed latches +// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) +// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); + // perform cleanup if requested + if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) + printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } +//timeRetime = clock() - timeRetime; +// if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) ) +// printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue ); + return pNtkAig; + +} + +/**Function************************************************************* + + Synopsis [Transforms logic network into structurally hashed AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord ) +{ + Abc_Ntk_t * pNtkAig; + int nNodes; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + // consider the special case when the network is already structurally hashed + if ( Abc_NtkIsStrash(pNtk) ) + return Abc_NtkRestrash( pNtk, fCleanup ); + // convert the node representation in the logic network to the AIG form + if ( !Abc_NtkToAig(pNtk) ) + { + printf( "Converting to AIGs has failed.\n" ); + return NULL; + } + // perform strashing +// Abc_NtkCleanCopy( pNtk ); + pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); + Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes, fRecord ); + Abc_NtkFinalize( pNtk, pNtkAig ); + // print warning about self-feed latches +// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) +// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); + // perform cleanup if requested + nNodes = fCleanup? Abc_AigCleanup(pNtkAig->pManFunc) : 0; +// if ( nNodes ) +// printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; +} + +/**Function************************************************************* + + Synopsis [Appends the second network to the first.] + + Description [Modifies the first network by adding the logic of the second. + Performs structural hashing while appending the networks. Does not change + the second network. Returns 0 if the appending failed, 1 otherise.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ) +{ + Abc_Obj_t * pObj; + char * pName; + int i, nNewCis; + // the first network should be an AIG + assert( Abc_NtkIsStrash(pNtk1) ); + assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsStrash(pNtk2) ); + if ( Abc_NtkIsLogic(pNtk2) && !Abc_NtkToAig(pNtk2) ) + { + printf( "Converting to AIGs has failed.\n" ); + return 0; + } + // check that the networks have the same PIs + // reorder PIs of pNtk2 according to pNtk1 + if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1, 1 ) ) + printf( "Abc_NtkAppend(): The union of the network PIs is computed (warning).\n" ); + // perform strashing + nNewCis = 0; + Abc_NtkCleanCopy( pNtk2 ); + if ( Abc_NtkIsStrash(pNtk2) ) + Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtk1); + Abc_NtkForEachCi( pNtk2, pObj, i ) + { + pName = Abc_ObjName(pObj); + pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj)); + if ( pObj->pCopy == NULL ) + { + pObj->pCopy = Abc_NtkDupObj(pNtk1, pObj, 1); + nNewCis++; + } + } + if ( nNewCis ) + printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis ); + // add pNtk2 to pNtk1 while strashing + if ( Abc_NtkIsLogic(pNtk2) ) + Abc_NtkStrashPerform( pNtk2, pNtk1, 1, 0 ); + else + Abc_NtkForEachNode( pNtk2, pObj, i ) + pObj->pCopy = Abc_AigAnd( pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // add the COs of the second network + if ( fAddPos ) + { + Abc_NtkForEachPo( pNtk2, pObj, i ) + { + Abc_NtkDupObj( pNtk1, pObj, 0 ); + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj->pCopy), NULL ); + } + } + else + { + Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew; + int fCompl, iNodeId; + // OR the choices + Abc_NtkForEachCo( pNtk2, pObj, i ) + { + iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI ); + assert( iNodeId >= 0 ); + pObjOld = Abc_NtkObj( pNtk1, iNodeId ); + // derive the new driver + pDriverOld = Abc_ObjChild0( pObjOld ); + pDriverNew = Abc_ObjChild0Copy( pObj ); + pDriverNew = Abc_AigOr( pNtk1->pManFunc, pDriverOld, pDriverNew ); + if ( Abc_ObjRegular(pDriverOld) == Abc_ObjRegular(pDriverNew) ) + continue; + // replace the old driver by the new driver + fCompl = Abc_ObjRegular(pDriverOld)->fPhase ^ Abc_ObjRegular(pDriverNew)->fPhase; + Abc_ObjPatchFanin( pObjOld, Abc_ObjRegular(pDriverOld), Abc_ObjNotCond(Abc_ObjRegular(pDriverNew), fCompl) ); + } + } + // make sure that everything is okay + if ( !Abc_NtkCheck( pNtk1 ) ) + { + printf( "Abc_NtkAppend: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Prepares the network for strashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNodeOld; + int i, clk = clock(); + assert( Abc_NtkIsLogic(pNtkOld) ); + assert( Abc_NtkIsStrash(pNtkNew) ); +// vNodes = Abc_NtkDfs( pNtkOld, fAllNodes ); + vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes ); +//printf( "Nodes = %d. ", Vec_PtrSize(vNodes) ); +//PRT( "Time", clock() - clk ); + pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); + Vec_PtrForEachEntry( vNodes, pNodeOld, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord ); + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Abc_NodeStrash_rec( pMan, Hop_ObjFanin0(pObj) ); + Abc_NodeStrash_rec( pMan, Hop_ObjFanin1(pObj) ); + pObj->pData = Abc_AigAnd( pMan, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node.] + + Description [Assume the network is in the AIG form] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, int fRecord ) +{ + Hop_Man_t * pMan; + Hop_Obj_t * pRoot; + Abc_Obj_t * pFanin; + int i; + assert( Abc_ObjIsNode(pNodeOld) ); + assert( Abc_NtkHasAig(pNodeOld->pNtk) && !Abc_NtkIsStrash(pNodeOld->pNtk) ); + // get the local AIG manager and the local root node + pMan = pNodeOld->pNtk->pManFunc; + pRoot = pNodeOld->pData; + // check the constant case + if ( Abc_NodeIsConst(pNodeOld) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) ) + return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Hop_IsComplement(pRoot) ); + // perform special case-strashing using the record of AIG subgraphs + if ( fRecord && Abc_NtkRecIsRunning() && Abc_ObjFaninNum(pNodeOld) > 2 && Abc_ObjFaninNum(pNodeOld) <= Abc_NtkRecVarNum() ) + { + extern Vec_Int_t * Abc_NtkRecMemory(); + extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ); + int nVars = Abc_NtkRecVarNum(); + Vec_Int_t * vMemory = Abc_NtkRecMemory(); + unsigned * pTruth = Abc_ConvertAigToTruth( pMan, Hop_Regular(pRoot), nVars, vMemory, 0 ); + assert( Extra_TruthSupportSize(pTruth, nVars) == Abc_ObjFaninNum(pNodeOld) ); // should be swept + if ( Hop_IsComplement(pRoot) ) + Extra_TruthNot( pTruth, pTruth, nVars ); + if ( Abc_NtkRecStrashNode( pNtkNew, pNodeOld, pTruth, nVars ) ) + return pNodeOld->pCopy; + } + // set elementary variables + Abc_ObjForEachFanin( pNodeOld, pFanin, i ) + Hop_IthVar(pMan, i)->pData = pFanin->pCopy; + // strash the AIG of this node + Abc_NodeStrash_rec( pNtkNew->pManFunc, Hop_Regular(pRoot) ); + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + // return the final node + return Abc_ObjNotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + + + + + + + +/**Function************************************************************* + + Synopsis [Copies the topmost levels of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut ) +{ + assert( !Abc_ObjIsComplement(pNode) ); + if ( pNode->pCopy ) + return pNode->pCopy; + if ( pNode->Level <= (unsigned)LevelCut ) + return pNode->pCopy = Abc_NtkCreatePi( pNtkNew ); + Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(pNode), LevelCut ); + Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin1(pNode), LevelCut ); + return pNode->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Copies the topmost levels of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjNew, * pPoNew; + int LevelCut; + assert( Abc_NtkIsStrash(pNtk) ); + assert( Abc_NtkCoNum(pNtk) == 1 ); + // get the cutoff level + LevelCut = ABC_MAX( 0, Abc_AigLevel(pNtk) - nLevels ); + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // create PIs below the cut and nodes above the cut + Abc_NtkCleanCopy( pNtk ); + pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(Abc_NtkPo(pNtk, 0)), LevelCut ); + pObjNew = Abc_ObjNotCond( pObjNew, Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) ); + // add the PO node and name + pPoNew = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAddFanin( pPoNew, pObjNew ); + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_ObjAssignName( pPoNew, Abc_ObjName(Abc_NtkPo(pNtk, 0)), NULL ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkTopmost: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcSweep.c b/abc70930/src/base/abci/abcSweep.c new file mode 100644 index 00000000..1ae8745b --- /dev/null +++ b/abc70930/src/base/abci/abcSweep.c @@ -0,0 +1,948 @@ +/**CFile**************************************************************** + + FileName [abcDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Technology dependent sweep.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); +static stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose ); +static void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, bool fVerbose ); +static void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ); +static void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ); +static int Abc_NodeDroppingCost( Abc_Obj_t * pNode ); + +static int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ); +static void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose ); +static void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0 ); +static void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sweping functionally equivalence nodes.] + + Description [Removes gates with equivalent functionality. Works for + both technology-independent and mapped networks. If the flag is set, + allows adding inverters at the gate outputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ) +{ + Fraig_Params_t Params; + Abc_Ntk_t * pNtkAig; + Fraig_Man_t * pMan; + stmm_table * tEquiv; + Abc_Obj_t * pObj; + int i, fUseTrick; + + assert( !Abc_NtkIsStrash(pNtk) ); + + // save gate assignments + fUseTrick = 0; + if ( Abc_NtkIsMappedLogic(pNtk) ) + { + fUseTrick = 1; + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pNext = pObj->pData; + } + // derive the AIG + pNtkAig = Abc_NtkStrash( pNtk, 0, 1, 0 ); + // reconstruct gate assignments + if ( fUseTrick ) + { + extern void * Abc_FrameReadLibGen(); + Hop_ManStop( pNtk->pManFunc ); + pNtk->pManFunc = Abc_FrameReadLibGen(); + pNtk->ntkFunc = ABC_FUNC_MAP; + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pData = pObj->pNext, pObj->pNext = NULL; + } + + // perform fraiging of the AIG + Fraig_ParamsSetDefault( &Params ); + pMan = Abc_NtkToFraig( pNtkAig, &Params, 0, 0 ); + // cannot use EXDC with FRAIG because it can create classes of equivalent FRAIG nodes + // with representative nodes that do not correspond to the nodes with the current network + + // update FRAIG using EXDC + if ( fExdc ) + { + if ( pNtk->pExdc == NULL ) + printf( "Warning: Networks has no EXDC.\n" ); + else + Abc_NtkFraigSweepUsingExdc( pMan, pNtk ); + } + // assign levels to the nodes of the network + Abc_NtkLevel( pNtk ); + + // collect the classes of equivalent nets + tEquiv = Abc_NtkFraigEquiv( pNtk, fUseInv, fVerbose, fVeryVerbose ); + + // transform the network into the equivalent one + Abc_NtkFraigTransform( pNtk, tEquiv, fUseInv, fVerbose ); + stmm_free_table( tEquiv ); + + // free the manager + Fraig_ManFree( pMan ); + Abc_NtkDelete( pNtkAig ); + + // cleanup the dangling nodes + if ( Abc_NtkHasMapping(pNtk) ) + Abc_NtkCleanup( pNtk, fVerbose ); + else + Abc_NtkSweep( pNtk, fVerbose ); + + // check + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Abc_NtkFraigSweep: The network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Sweep the network using EXDC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + Fraig_Node_t * gNodeExdc, * gNode, * gNodeRes; + Abc_Obj_t * pNode, * pNodeAig; + int i; + extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkExdc ); + + assert( pNtk->pExdc ); + // derive FRAIG node representing don't-cares in the EXDC network + gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc ); + // update the node pointers + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // skip the constant input nodes + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; + // get the strashed node + pNodeAig = pNode->pCopy; + // skip the dangling nodes + if ( pNodeAig == NULL ) + continue; + // get the FRAIG node + gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, Abc_ObjIsComplement(pNodeAig) ); + // perform ANDing with EXDC + gNodeRes = Fraig_NodeAnd( pMan, gNode, Fraig_Not(gNodeExdc) ); + // write the node back + Abc_ObjRegular(pNodeAig)->pCopy = (Abc_Obj_t *)Fraig_NotCond( gNodeRes, Abc_ObjIsComplement(pNodeAig) ); + } +} + +/**Function************************************************************* + + Synopsis [Collects equivalence classses of node in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose ) +{ + Abc_Obj_t * pList, * pNode, * pNodeAig; + Fraig_Node_t * gNode; + Abc_Obj_t ** ppSlot; + stmm_table * tStrash2Net; + stmm_table * tResult; + stmm_generator * gen; + int c, Counter; + + // create mapping of strashed nodes into the corresponding network nodes + tStrash2Net = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); + Abc_NtkForEachNode( pNtk, pNode, c ) + { + // skip the constant input nodes + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; + // get the strashed node + pNodeAig = pNode->pCopy; + // skip the dangling nodes + if ( pNodeAig == NULL ) + continue; + // skip the nodes that fanout into COs + if ( Abc_NodeFindCoFanout(pNode) ) + continue; + // get the FRAIG node + gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, Abc_ObjIsComplement(pNodeAig) ); + if ( !stmm_find_or_add( tStrash2Net, (char *)Fraig_Regular(gNode), (char ***)&ppSlot ) ) + *ppSlot = NULL; + // add the node to the list + pNode->pNext = *ppSlot; + *ppSlot = pNode; + // mark the node if it is complemented + pNode->fPhase = Fraig_IsComplement(gNode); + } + + // print the classes + c = 0; + Counter = 0; + tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); + stmm_foreach_item( tStrash2Net, gen, (char **)&gNode, (char **)&pList ) + { + // skip the trival classes + if ( pList == NULL || pList->pNext == NULL ) + continue; + // add the non-trival class + stmm_insert( tResult, (char *)pList, NULL ); + // count nodes in the non-trival classes + for ( pNode = pList; pNode; pNode = pNode->pNext ) + Counter++; + + if ( fVeryVerbose ) + { + printf( "Class %2d : {", c ); + for ( pNode = pList; pNode; pNode = pNode->pNext ) + { + pNode->pCopy = NULL; + printf( " %s", Abc_ObjName(pNode) ); + printf( "(%c)", pNode->fPhase? '-' : '+' ); + printf( "(%d)", pNode->Level ); + } + printf( " }\n" ); + c++; + } + } + if ( fVerbose || fVeryVerbose ) + { + printf( "Sweeping stats for network \"%s\":\n", pNtk->pName ); + printf( "Internal nodes = %d. Different functions (up to compl) = %d.\n", Abc_NtkNodeNum(pNtk), stmm_count(tStrash2Net) ); + printf( "Non-trivial classes = %d. Nodes in non-trivial classes = %d.\n", stmm_count(tResult), Counter ); + } + stmm_free_table( tStrash2Net ); + return tResult; +} + + +/**Function************************************************************* + + Synopsis [Transforms the network using the equivalence relation on nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, bool fVerbose ) +{ + stmm_generator * gen; + Abc_Obj_t * pList; + if ( stmm_count(tEquiv) == 0 ) + return; + // merge nodes in the classes + if ( Abc_NtkHasMapping( pNtk ) ) + { + Abc_NtkDelayTrace( pNtk ); + stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL ) + Abc_NtkFraigMergeClassMapped( pNtk, pList, fUseInv, fVerbose ); + } + else + { + stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL ) + Abc_NtkFraigMergeClass( pNtk, pList, fUseInv, fVerbose ); + } +} + + +/**Function************************************************************* + + Synopsis [Transforms the list of one-phase equivalent nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ) +{ + Abc_Obj_t * pListDir, * pListInv; + Abc_Obj_t * pNodeMin, * pNode, * pNext; + float Arrival1, Arrival2; + + assert( pChain ); + assert( pChain->pNext ); + + // divide the nodes into two parts: + // those that need the invertor and those that don't need + pListDir = pListInv = NULL; + for ( pNode = pChain, pNext = pChain->pNext; + pNode; + pNode = pNext, pNext = pNode? pNode->pNext : NULL ) + { + // check to which class the node belongs + if ( pNode->fPhase == 1 ) + { + pNode->pNext = pListDir; + pListDir = pNode; + } + else + { + pNode->pNext = pListInv; + pListInv = pNode; + } + } + + // find the node with the smallest number of logic levels + pNodeMin = pListDir; + for ( pNode = pListDir; pNode; pNode = pNode->pNext ) + { + Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst; + Arrival2 = Abc_NodeReadArrival(pNode )->Worst; +// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 ); +// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 ); + if ( Arrival1 > Arrival2 || + Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level || + Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level && + Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) + pNodeMin = pNode; + } + + // move the fanouts of the direct nodes + for ( pNode = pListDir; pNode; pNode = pNode->pNext ) + if ( pNode != pNodeMin ) + Abc_ObjTransferFanout( pNode, pNodeMin ); + + // find the node with the smallest number of logic levels + pNodeMin = pListInv; + for ( pNode = pListInv; pNode; pNode = pNode->pNext ) + { + Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst; + Arrival2 = Abc_NodeReadArrival(pNode )->Worst; +// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 ); +// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 ); + if ( Arrival1 > Arrival2 || + Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level || + Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level && + Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) + pNodeMin = pNode; + } + + // move the fanouts of the direct nodes + for ( pNode = pListInv; pNode; pNode = pNode->pNext ) + if ( pNode != pNodeMin ) + Abc_ObjTransferFanout( pNode, pNodeMin ); +} + +/**Function************************************************************* + + Synopsis [Process one equivalence class of nodes.] + + Description [This function does not remove the nodes. It only switches + around the connections.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ) +{ + Abc_Obj_t * pListDir, * pListInv; + Abc_Obj_t * pNodeMin, * pNodeMinInv; + Abc_Obj_t * pNode, * pNext; + + assert( pChain ); + assert( pChain->pNext ); + + // find the node with the smallest number of logic levels + pNodeMin = pChain; + for ( pNode = pChain->pNext; pNode; pNode = pNode->pNext ) + if ( pNodeMin->Level > pNode->Level || + ( pNodeMin->Level == pNode->Level && + Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) ) + pNodeMin = pNode; + + // divide the nodes into two parts: + // those that need the invertor and those that don't need + pListDir = pListInv = NULL; + for ( pNode = pChain, pNext = pChain->pNext; + pNode; + pNode = pNext, pNext = pNode? pNode->pNext : NULL ) + { + if ( pNode == pNodeMin ) + continue; + // check to which class the node belongs + if ( pNodeMin->fPhase == pNode->fPhase ) + { + pNode->pNext = pListDir; + pListDir = pNode; + } + else + { + pNode->pNext = pListInv; + pListInv = pNode; + } + } + + // move the fanouts of the direct nodes + for ( pNode = pListDir; pNode; pNode = pNode->pNext ) + Abc_ObjTransferFanout( pNode, pNodeMin ); + + // skip if there are no inverted nodes + if ( pListInv == NULL ) + return; + + // add the invertor + pNodeMinInv = Abc_NtkCreateNodeInv( pNtk, pNodeMin ); + + // move the fanouts of the inverted nodes + for ( pNode = pListInv; pNode; pNode = pNode->pNext ) + Abc_ObjTransferFanout( pNode, pNodeMinInv ); +} + + +/**Function************************************************************* + + Synopsis [Returns the number of literals saved if this node becomes useless.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeDroppingCost( Abc_Obj_t * pNode ) +{ + return 1; +} + + + + + +/**Function************************************************************* + + Synopsis [Removes dangling nodes.] + + Description [Returns the number of nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + int Counter; + assert( Abc_NtkIsLogic(pNtk) ); + // mark the nodes reachable from the POs + vNodes = Abc_NtkDfs( pNtk, 0 ); + Counter = Abc_NtkReduceNodes( pNtk, vNodes ); + if ( fVerbose ) + printf( "Cleanup removed %d dangling nodes.\n", Counter ); + Vec_PtrFree( vNodes ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Preserves the nodes collected in the array.] + + Description [Returns the number of nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pNode; + int i, Counter; + assert( Abc_NtkIsLogic(pNtk) ); + // mark the nodes reachable from the POs + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkA = 1; + // remove the non-marked nodes + Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( pNode->fMarkA == 0 ) + { + Abc_NtkDeleteObj( pNode ); + Counter++; + } + // unmark the remaining nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkA = 0; + // check + if ( !Abc_NtkCheck( pNtk ) ) + printf( "Abc_NtkCleanup: The network check has failed.\n" ); + return Counter; +} + + + + +/**Function************************************************************* + + Synopsis [Tranditional sweep of the network.] + + Description [Propagates constant and single-input node, removes dangling nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanout, * pDriver; + int i, nNodesOld; + assert( Abc_NtkIsLogic(pNtk) ); + // convert network to BDD representation + if ( !Abc_NtkToBdd(pNtk) ) + { + fprintf( stdout, "Converting to BDD has failed.\n" ); + return 1; + } + // perform cleanup + nNodesOld = Abc_NtkNodeNum(pNtk); + Abc_NtkCleanup( pNtk, 0 ); + // prepare nodes for sweeping + Abc_NtkRemoveDupFanins(pNtk); + Abc_NtkMinimumBase(pNtk); + // collect sweepable nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_ObjFaninNum(pNode) < 2 ) + Vec_PtrPush( vNodes, pNode ); + // sweep the nodes + while ( Vec_PtrSize(vNodes) > 0 ) + { + // get any sweepable node + pNode = Vec_PtrPop(vNodes); + if ( !Abc_ObjIsNode(pNode) ) + continue; + // get any non-CO fanout of this node + pFanout = Abc_NodeFindNonCoFanout(pNode); + if ( pFanout == NULL ) + continue; + assert( Abc_ObjIsNode(pFanout) ); + // transform the function of the fanout + if ( Abc_ObjFaninNum(pNode) == 0 ) + Abc_NodeConstantInput( pFanout, pNode, Abc_NodeIsConst0(pNode) ); + else + { + assert( Abc_ObjFaninNum(pNode) == 1 ); + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_NodeIsInv(pNode) ) + Abc_NodeComplementInput( pFanout, pNode ); + Abc_ObjPatchFanin( pFanout, pNode, pDriver ); + } + Abc_NodeRemoveDupFanins( pFanout ); + Abc_NodeMinimumBase( pFanout ); + // check if the fanout should be added + if ( Abc_ObjFaninNum(pFanout) < 2 ) + Vec_PtrPush( vNodes, pFanout ); + // check if the node has other fanouts + if ( Abc_ObjFanoutNum(pNode) > 0 ) + Vec_PtrPush( vNodes, pNode ); + else + Abc_NtkDeleteObj_rec( pNode, 1 ); + } + Vec_PtrFree( vNodes ); + // sweep a node into its CO fanout if all of this is true: + // (a) this node is a single-input node + // (b) the driver of the node has only one fanout (this node) + // (c) the driver is a node + Abc_NtkForEachCo( pNtk, pFanout, i ) + { + pNode = Abc_ObjFanin0(pFanout); + if ( Abc_ObjFaninNum(pNode) != 1 ) + continue; + pDriver = Abc_ObjFanin0(pNode); + if ( !(Abc_ObjFanoutNum(pDriver) == 1 && Abc_ObjIsNode(pDriver)) ) + continue; + // trasform this CO + if ( Abc_NodeIsInv(pNode) ) + pDriver->pData = Cudd_Not(pDriver->pData); + Abc_ObjPatchFanin( pFanout, pNode, pDriver ); + } + // perform cleanup + Abc_NtkCleanup( pNtk, 0 ); + // report + if ( fVerbose ) + printf( "Sweep removed %d nodes.\n", nNodesOld - Abc_NtkNodeNum(pNtk) ); + return nNodesOld - Abc_NtkNodeNum(pNtk); +} + + +/**Function************************************************************* + + Synopsis [Replaces the local function by its cofactor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0 ) +{ + DdManager * dd = pNode->pNtk->pManFunc; + DdNode * bVar, * bTemp; + int iFanin; + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 ) + { + printf( "Node %s should be among", Abc_ObjName(pFanin) ); + printf( " the fanins of node %s...\n", Abc_ObjName(pNode) ); + return; + } + bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iFanin), fConst0 ); + pNode->pData = Cudd_Cofactor( dd, bTemp = pNode->pData, bVar ); Cudd_Ref( pNode->pData ); + Cudd_RecursiveDeref( dd, bTemp ); +} + +/**Function************************************************************* + + Synopsis [Changes the polarity of one fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) +{ + DdManager * dd = pNode->pNtk->pManFunc; + DdNode * bVar, * bCof0, * bCof1; + int iFanin; + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 ) + { + printf( "Node %s should be among", Abc_ObjName(pFanin) ); + printf( " the fanins of node %s...\n", Abc_ObjName(pNode) ); + return; + } + bVar = Cudd_bddIthVar( dd, iFanin ); + bCof0 = Cudd_Cofactor( dd, pNode->pData, Cudd_Not(bVar) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_Cofactor( dd, pNode->pData, bVar ); Cudd_Ref( bCof1 ); + Cudd_RecursiveDeref( dd, pNode->pData ); + pNode->pData = Cudd_bddIte( dd, bVar, bCof0, bCof1 ); Cudd_Ref( pNode->pData ); + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); +} + + + +/**Function************************************************************* + + Synopsis [Removes all objects whose trav ID is not current.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRemoveNonCurrentObjects( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int Counter, i; + int fVerbose = 0; + + // report on the nodes to be deleted + if ( fVerbose ) + { + printf( "These nodes will be deleted: \n" ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent( pObj ) ) + { + printf( " " ); + Abc_ObjPrint( stdout, pObj ); + } + } + + // delete the nodes + Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent( pObj ) ) + { + Abc_NtkDeleteObj( pObj ); + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Check if the fanin of this latch is a constant.] + + Description [Returns 0/1 if constant; -1 if not a constant.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSetTravId_rec( Abc_Obj_t * pObj ) +{ + Abc_NodeSetTravIdCurrent(pObj); + if ( Abc_ObjFaninNum(pObj) == 0 ) + return; + assert( Abc_ObjFaninNum(pObj) == 1 ); + Abc_NtkSetTravId_rec( Abc_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Check if the fanin of this latch is a constant.] + + Description [Returns 0/1 if constant; -1 if not a constant.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckConstant_rec( Abc_Obj_t * pObj ) +{ + if ( Abc_ObjFaninNum(pObj) == 0 ) + { + if ( !Abc_ObjIsNode(pObj) ) + return -1; + if ( Abc_NodeIsConst0(pObj) ) + return 0; + if ( Abc_NodeIsConst1(pObj) ) + return 1; + assert( 0 ); + return -1; + } + if ( Abc_ObjIsLatch(pObj) || Abc_ObjFaninNum(pObj) > 1 ) + return -1; + if ( !Abc_ObjIsNode(pObj) || Abc_NodeIsBuf(pObj) ) + return Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) ); + if ( Abc_NodeIsInv(pObj) ) + { + int RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) ); + if ( RetValue == 0 ) + return 1; + if ( RetValue == 1 ) + return 0; + return RetValue; + } + assert( 0 ); + return -1; +} + +/**Function************************************************************* + + Synopsis [Removes redundant latches.] + + Description [The redundant latches are of two types: + - Latches fed by a constant which matches the init value of the latch. + - Latches fed by a constant which does not match the init value of the latch + can be all replaced by one latch.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLatchSweep( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pFanin, * pLatch, * pLatchPivot = NULL; + int Counter, RetValue, i; + Counter = 0; + // go through the latches + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + // check if the latch has constant input + RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pLatch) ); + if ( RetValue == -1 ) + continue; + // found a latch with constant fanin + if ( (RetValue == 1 && Abc_LatchIsInit0(pLatch)) || + (RetValue == 0 && Abc_LatchIsInit1(pLatch)) ) + { + // fanin constant differs from the latch init value + if ( pLatchPivot == NULL ) + { + pLatchPivot = pLatch; + continue; + } + if ( Abc_LatchInit(pLatch) != Abc_LatchInit(pLatchPivot) ) // add inverter + pFanin = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanout0(pLatchPivot) ); + else + pFanin = Abc_ObjFanout0(pLatchPivot); + } + else + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + // replace latch + Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pFanin ); + // delete the extra nodes + Abc_NtkDeleteObj_rec( Abc_ObjFanout0(pLatch), 0 ); + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Replaces autonumnous logic by free inputs.] + + Description [Assumes that non-autonomous logic is marked with + the current ID.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkReplaceAutonomousLogic( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pFanin; + Vec_Ptr_t * vNodes; + int i, k, Counter; + // collect the nodes that feed into the reachable logic + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pNode, i ) + { + // skip non-visited fanins + if ( !Abc_NodeIsTravIdCurrent(pNode) ) + continue; + // look for non-visited fanins + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + // skip visited fanins + if ( Abc_NodeIsTravIdCurrent(pFanin) ) + continue; + // skip constants and latches fed by constants + if ( Abc_NtkCheckConstant_rec(pFanin) != -1 || + (Abc_ObjIsBo(pFanin) && Abc_NtkCheckConstant_rec(Abc_ObjFanin0(Abc_ObjFanin0(pFanin))) != -1) ) + { + Abc_NtkSetTravId_rec( pFanin ); + continue; + } + assert( !Abc_ObjIsLatch(pFanin) ); + Vec_PtrPush( vNodes, pFanin ); + } + } + Vec_PtrUniqify( vNodes, Abc_ObjPointerCompare ); + // replace these nodes by the PIs + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + pFanin = Abc_NtkCreatePi(pNtk); + Abc_ObjAssignName( pFanin, Abc_ObjName(pFanin), NULL ); + Abc_NodeSetTravIdCurrent( pFanin ); + Abc_ObjTransferFanout( pNode, pFanin ); + } + Counter = Vec_PtrSize(vNodes); + Vec_PtrFree( vNodes ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Sequential cleanup.] + + Description [Performs three tasks: + - Removes logic that does not feed into POs. + - Removes latches driven by constant values equal to the initial state. + - Replaces the autonomous components by additional PI variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + int Counter; + assert( Abc_NtkIsLogic(pNtk) ); + // mark the nodes reachable from the POs + vNodes = Abc_NtkDfsSeq( pNtk ); + Vec_PtrFree( vNodes ); + // remove the non-marked nodes + Counter = Abc_NodeRemoveNonCurrentObjects( pNtk ); + if ( fVerbose ) + printf( "Cleanup removed %4d dangling objects.\n", Counter ); + // check if some of the latches can be removed + if ( fLatchSweep ) + { + Counter = Abc_NtkLatchSweep( pNtk ); + if ( fVerbose ) + printf( "Cleanup removed %4d redundant latches.\n", Counter ); + } + // detect the autonomous components + if ( fAutoSweep ) + { + vNodes = Abc_NtkDfsSeqReverse( pNtk ); + Vec_PtrFree( vNodes ); + // replace them by PIs + Counter = Abc_NtkReplaceAutonomousLogic( pNtk ); + if ( fVerbose ) + printf( "Cleanup added %4d additional PIs.\n", Counter ); + // remove the non-marked nodes + Counter = Abc_NodeRemoveNonCurrentObjects( pNtk ); + if ( fVerbose ) + printf( "Cleanup removed %4d autonomous objects.\n", Counter ); + } + // check + if ( !Abc_NtkCheck( pNtk ) ) + printf( "Abc_NtkCleanupSeq: The network check has failed.\n" ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcSymm.c b/abc70930/src/base/abci/abcSymm.c new file mode 100644 index 00000000..0f76065c --- /dev/null +++ b/abc70930/src/base/abci/abcSymm.c @@ -0,0 +1,229 @@ +/**CFile**************************************************************** + + FileName [abcSymm.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computation of two-variable symmetries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcSymm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose ); +static void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose ); +static void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose ); +static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [The top level procedure to compute symmetries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ) +{ + if ( fUseBdds || fNaive ) + Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fReorder, fVerbose ); + else + Abc_NtkSymmetriesUsingSandS( pNtk, fVerbose ); +} + +/**Function************************************************************* + + Synopsis [Symmetry computation using simulation and SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose ) +{ + extern int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose ); + int nSymms = Sim_ComputeTwoVarSymms( pNtk, fVerbose ); + printf( "The total number of symmetries is %d.\n", nSymms ); +} + +/**Function************************************************************* + + Synopsis [Symmetry computation using BDDs (both naive and smart).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose ) +{ + DdManager * dd; + int clk, clkBdd, clkSym; + int fGarbCollect = 1; + + // compute the global functions +clk = clock(); + dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, fVerbose ); + printf( "Shared BDD size = %d nodes.\n", Abc_NtkSizeOfGlobalBdds(pNtk) ); + Cudd_AutodynDisable( dd ); + if ( !fGarbCollect ) + Cudd_DisableGarbageCollection( dd ); + Cudd_zddVarsFromBddVars( dd, 2 ); +clkBdd = clock() - clk; + // create the collapsed network +clk = clock(); + Ntk_NetworkSymmsBdd( dd, pNtk, fNaive, fVerbose ); +clkSym = clock() - clk; + // undo the global functions + Abc_NtkFreeGlobalBdds( pNtk, 1 ); +printf( "Statistics of BDD-based symmetry detection:\n" ); +printf( "Algorithm = %s. Reordering = %s. Garbage collection = %s.\n", + fNaive? "naive" : "fast", fReorder? "yes" : "no", fGarbCollect? "yes" : "no" ); +PRT( "Constructing BDDs", clkBdd ); +PRT( "Computing symms ", clkSym ); +PRT( "TOTAL ", clkBdd + clkSym ); +} + +/**Function************************************************************* + + Synopsis [Symmetry computation using BDDs (both naive and smart).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose ) +{ + Extra_SymmInfo_t * pSymms; + Abc_Obj_t * pNode; + DdNode * bFunc; + int nSymms = 0; + int nSupps = 0; + int i; + + // compute symmetry info for each PO + Abc_NtkForEachCo( pNtk, pNode, i ) + { +// bFunc = pNtk->vFuncsGlob->pArray[i]; + bFunc = Abc_ObjGlobalBdd( pNode ); + nSupps += Cudd_SupportSize( dd, bFunc ); + if ( Cudd_IsConstant(bFunc) ) + continue; + if ( fNaive ) + pSymms = Extra_SymmPairsComputeNaive( dd, bFunc ); + else + pSymms = Extra_SymmPairsCompute( dd, bFunc ); + nSymms += pSymms->nSymms; + if ( fVerbose ) + { + printf( "Output %6s (%d): ", Abc_ObjName(pNode), pSymms->nSymms ); + Ntk_NetworkSymmsPrint( pNtk, pSymms ); + } +//Extra_SymmPairsPrint( pSymms ); + Extra_SymmPairsDissolve( pSymms ); + } + printf( "Total number of vars in functional supports = %8d.\n", nSupps ); + printf( "Total number of two-variable symmetries = %8d.\n", nSymms ); +} + +/**Function************************************************************* + + Synopsis [Printing symmetry groups from the symmetry data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms ) +{ + char ** pInputNames; + int * pVarTaken; + int i, k, nVars, nSize, fStart; + + // get variable names + nVars = Abc_NtkCiNum(pNtk); + pInputNames = Abc_NtkCollectCioNames( pNtk, 0 ); + + // alloc the array of marks + pVarTaken = ALLOC( int, nVars ); + memset( pVarTaken, 0, sizeof(int) * nVars ); + + // print the groups + fStart = 1; + nSize = pSymms->nVars; + for ( i = 0; i < nSize; i++ ) + { + // skip the variable already considered + if ( pVarTaken[i] ) + continue; + // find all the vars symmetric with this one + for ( k = 0; k < nSize; k++ ) + { + if ( k == i ) + continue; + if ( pSymms->pSymms[i][k] == 0 ) + continue; + // vars i and k are symmetric + assert( pVarTaken[k] == 0 ); + // there is a new symmetry pair + if ( fStart == 1 ) + { // start a new symmetry class + fStart = 0; + printf( " { %s", pInputNames[ pSymms->pVars[i] ] ); + // mark the var as taken + pVarTaken[i] = 1; + } + printf( " %s", pInputNames[ pSymms->pVars[k] ] ); + // mark the var as taken + pVarTaken[k] = 1; + } + if ( fStart == 0 ) + { + printf( " }" ); + fStart = 1; + } + } + printf( "\n" ); + + free( pInputNames ); + free( pVarTaken ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcTiming.c b/abc70930/src/base/abci/abcTiming.c new file mode 100644 index 00000000..967e4617 --- /dev/null +++ b/abc70930/src/base/abci/abcTiming.c @@ -0,0 +1,905 @@ +/**CFile**************************************************************** + + FileName [abcTiming.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computation of timing info for mapped circuits.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcTiming.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Abc_ManTime_t_ +{ + Abc_Time_t tArrDef; + Abc_Time_t tReqDef; + Vec_Ptr_t * vArrs; + Vec_Ptr_t * vReqs; +}; + +// static functions +static Abc_ManTime_t * Abc_ManTimeStart(); +static void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive ); +void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk ); + +void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ); + +// accessing the arrival and required times of a node +static inline Abc_Time_t * Abc_NodeArrival( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vArrs->pArray[pNode->Id]; } +static inline Abc_Time_t * Abc_NodeRequired( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vReqs->pArray[pNode->Id]; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ) +{ + assert( pNode->pNtk->pManTime ); + return Abc_NodeArrival(pNode); +} + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ) +{ + assert( pNode->pNtk->pManTime ); + return Abc_NodeRequired(pNode); +} + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk ) +{ + assert( pNtk->pManTime ); + return &pNtk->pManTime->tArrDef; +} + +/**Function************************************************************* + + Synopsis [Reads the arrival time of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ) +{ + assert( pNtk->pManTime ); + return &pNtk->pManTime->tReqDef; +} + +/**Function************************************************************* + + Synopsis [Sets the default arrival time for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ) +{ + if ( Rise == 0.0 && Fall == 0.0 ) + return; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + pNtk->pManTime->tArrDef.Rise = Rise; + pNtk->pManTime->tArrDef.Fall = Fall; + pNtk->pManTime->tArrDef.Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Sets the default arrival time for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ) +{ + if ( Rise == 0.0 && Fall == 0.0 ) + return; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + pNtk->pManTime->tReqDef.Rise = Rise; + pNtk->pManTime->tReqDef.Rise = Fall; + pNtk->pManTime->tReqDef.Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Sets the arrival time for an object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ) +{ + Vec_Ptr_t * vTimes; + Abc_Time_t * pTime; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + if ( pNtk->pManTime->tArrDef.Rise == Rise && pNtk->pManTime->tArrDef.Fall == Fall ) + return; + Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 ); + // set the arrival time + vTimes = pNtk->pManTime->vArrs; + pTime = vTimes->pArray[ObjId]; + pTime->Rise = Rise; + pTime->Fall = Rise; + pTime->Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Sets the arrival time for an object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ) +{ + Vec_Ptr_t * vTimes; + Abc_Time_t * pTime; + if ( pNtk->pManTime == NULL ) + pNtk->pManTime = Abc_ManTimeStart(); + if ( pNtk->pManTime->tReqDef.Rise == Rise && pNtk->pManTime->tReqDef.Fall == Fall ) + return; + Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 ); + // set the required time + vTimes = pNtk->pManTime->vReqs; + pTime = vTimes->pArray[ObjId]; + pTime->Rise = Rise; + pTime->Fall = Rise; + pTime->Worst = ABC_MAX( Rise, Fall ); +} + +/**Function************************************************************* + + Synopsis [Finalizes the timing manager after setting arr/req times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + Abc_Time_t ** ppTimes, * pTime; + int i; + if ( pNtk->pManTime == NULL ) + return; + Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 ); + // set the default timing + ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; + Abc_NtkForEachPi( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + if ( pTime->Worst != -ABC_INFINITY ) + continue; + *pTime = pNtk->pManTime->tArrDef; + } + // set the default timing + ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray; + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + if ( pTime->Worst != -ABC_INFINITY ) + continue; + *pTime = pNtk->pManTime->tReqDef; + } + // set the 0 arrival times for latch outputs and constant nodes + ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; + Abc_NtkForEachLatchOutput( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + pTime->Fall = pTime->Rise = pTime->Worst = 0.0; + } +} + +/**Function************************************************************* + + Synopsis [Prepares the timing manager for delay trace.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + Abc_Time_t ** ppTimes, * pTime; + int i; + // if there is no timing manager, allocate and initialize + if ( pNtk->pManTime == NULL ) + { + pNtk->pManTime = Abc_ManTimeStart(); + Abc_NtkTimeInitialize( pNtk ); + return; + } + // if timing manager is given, expand it if necessary + Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 ); + // clean arrivals except for PIs + ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY; + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pTime = ppTimes[pObj->Id]; + pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY; + } + // clean required except for POs +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_ManTime_t * Abc_ManTimeStart() +{ + Abc_ManTime_t * p; + p = ALLOC( Abc_ManTime_t, 1 ); + memset( p, 0, sizeof(Abc_ManTime_t) ); + p->vArrs = Vec_PtrAlloc( 0 ); + p->vReqs = Vec_PtrAlloc( 0 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManTimeStop( Abc_ManTime_t * p ) +{ + if ( p->vArrs->nSize > 0 ) + { + free( p->vArrs->pArray[0] ); + Vec_PtrFree( p->vArrs ); + } + if ( p->vReqs->nSize > 0 ) + { + free( p->vReqs->pArray[0] ); + Vec_PtrFree( p->vReqs ); + } + free( p ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the timing manager with the PI/PO timing info.] + + Description [The PIs/POs of the new network should be allocated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; + Abc_Time_t ** ppTimesOld, ** ppTimesNew; + int i; + if ( pNtkOld->pManTime == NULL ) + return; + assert( Abc_NtkPiNum(pNtkOld) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtkOld) == Abc_NtkPoNum(pNtkNew) ); + assert( Abc_NtkLatchNum(pNtkOld) == Abc_NtkLatchNum(pNtkNew) ); + // create the new timing manager + pNtkNew->pManTime = Abc_ManTimeStart(); + Abc_ManTimeExpand( pNtkNew->pManTime, Abc_NtkObjNumMax(pNtkNew), 0 ); + // set the default timing + pNtkNew->pManTime->tArrDef = pNtkOld->pManTime->tArrDef; + pNtkNew->pManTime->tReqDef = pNtkOld->pManTime->tReqDef; + // set the CI timing + ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vArrs->pArray; + ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vArrs->pArray; + Abc_NtkForEachCi( pNtkOld, pObj, i ) + *ppTimesNew[ Abc_NtkCi(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ]; + // set the CO timing + ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vReqs->pArray; + ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vReqs->pArray; + Abc_NtkForEachCo( pNtkOld, pObj, i ) + *ppTimesNew[ Abc_NtkCo(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ]; +} + +/**Function************************************************************* + + Synopsis [Expends the storage for timing information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive ) +{ + Vec_Ptr_t * vTimes; + Abc_Time_t * ppTimes, * ppTimesOld, * pTime; + int nSizeOld, nSizeNew, i; + + nSizeOld = p->vArrs->nSize; + if ( nSizeOld >= nSize ) + return; + nSizeNew = fProgressive? 2 * nSize : nSize; + if ( nSizeNew < 100 ) + nSizeNew = 100; + + vTimes = p->vArrs; + Vec_PtrGrow( vTimes, nSizeNew ); + vTimes->nSize = nSizeNew; + ppTimesOld = ( nSizeOld == 0 )? NULL : vTimes->pArray[0]; + ppTimes = REALLOC( Abc_Time_t, ppTimesOld, nSizeNew ); + for ( i = 0; i < nSizeNew; i++ ) + vTimes->pArray[i] = ppTimes + i; + for ( i = nSizeOld; i < nSizeNew; i++ ) + { + pTime = vTimes->pArray[i]; + pTime->Rise = -ABC_INFINITY; + pTime->Fall = -ABC_INFINITY; + pTime->Worst = -ABC_INFINITY; + } + + vTimes = p->vReqs; + Vec_PtrGrow( vTimes, nSizeNew ); + vTimes->nSize = nSizeNew; + ppTimesOld = ( nSizeOld == 0 )? NULL : vTimes->pArray[0]; + ppTimes = REALLOC( Abc_Time_t, ppTimesOld, nSizeNew ); + for ( i = 0; i < nSizeNew; i++ ) + vTimes->pArray[i] = ppTimes + i; + for ( i = nSizeOld; i < nSizeNew; i++ ) + { + pTime = vTimes->pArray[i]; + pTime->Rise = -ABC_INFINITY; + pTime->Fall = -ABC_INFINITY; + pTime->Worst = -ABC_INFINITY; + } +} + + + + + + +/**Function************************************************************* + + Synopsis [Sets the CI node levels according to the arrival info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtkOld ) +{ + Abc_Obj_t * pNodeOld, * pNodeNew; + float tAndDelay; + int i; + if ( pNtkOld->pManTime == NULL ) + return; + if ( Mio_LibraryReadNand2(Abc_FrameReadLibGen()) == NULL ) + return; + tAndDelay = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen()); + Abc_NtkForEachPi( pNtkOld, pNodeOld, i ) + { + pNodeNew = pNodeOld->pCopy; + pNodeNew->Level = (int)(Abc_NodeArrival(pNodeOld)->Worst / tAndDelay); + } +} + +/**Function************************************************************* + + Synopsis [Sets the CI node levels according to the arrival info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk ) +{ + Abc_Time_t * p; + Abc_Obj_t * pNode; + int i; + p = ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtk) ); + memset( p, 0, sizeof(Abc_Time_t) * Abc_NtkCiNum(pNtk) ); + if ( pNtk->pManTime == NULL ) + return p; + // set the PI arrival times + Abc_NtkForEachPi( pNtk, pNode, i ) + p[i] = *Abc_NodeArrival(pNode); + return p; +} + + +/**Function************************************************************* + + Synopsis [Sets the CI node levels according to the arrival info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk ) +{ + float * p; + Abc_Obj_t * pNode; + int i; + p = ALLOC( float, Abc_NtkCiNum(pNtk) ); + memset( p, 0, sizeof(float) * Abc_NtkCiNum(pNtk) ); + if ( pNtk->pManTime == NULL ) + return p; + // set the PI arrival times + Abc_NtkForEachPi( pNtk, pNode, i ) + p[i] = Abc_NodeArrival(pNode)->Worst; + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pDriver; + Vec_Ptr_t * vNodes; + Abc_Time_t * pTime; + float tArrivalMax; + int i; + + assert( Abc_NtkIsMappedLogic(pNtk) ); + + Abc_NtkTimePrepare( pNtk ); + vNodes = Abc_NtkDfs( pNtk, 1 ); + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_NodeDelayTraceArrival( vNodes->pArray[i] ); + Vec_PtrFree( vNodes ); + + // get the latest arrival times + tArrivalMax = -ABC_INFINITY; + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0(pNode); + pTime = Abc_NodeArrival(pDriver); + if ( tArrivalMax < pTime->Worst ) + tArrivalMax = pTime->Worst; + } + return tArrivalMax; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + Abc_Time_t * pTimeIn, * pTimeOut; + float tDelayBlockRise, tDelayBlockFall; + Mio_PinPhase_t PinPhase; + Mio_Pin_t * pPin; + int i; + + // start the arrival time of the node + pTimeOut = Abc_NodeArrival(pNode); + pTimeOut->Rise = pTimeOut->Fall = -ABC_INFINITY; + // go through the pins of the gate + pPin = Mio_GateReadPins(pNode->pData); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + pTimeIn = Abc_NodeArrival(pFanin); + // get the interesting parameters of this pin + PinPhase = Mio_PinReadPhase(pPin); + tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); + tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); + // compute the arrival times of the positive phase + if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present + { + if ( pTimeOut->Rise < pTimeIn->Rise + tDelayBlockRise ) + pTimeOut->Rise = pTimeIn->Rise + tDelayBlockRise; + if ( pTimeOut->Fall < pTimeIn->Fall + tDelayBlockFall ) + pTimeOut->Fall = pTimeIn->Fall + tDelayBlockFall; + } + if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present + { + if ( pTimeOut->Rise < pTimeIn->Fall + tDelayBlockRise ) + pTimeOut->Rise = pTimeIn->Fall + tDelayBlockRise; + if ( pTimeOut->Fall < pTimeIn->Rise + tDelayBlockFall ) + pTimeOut->Fall = pTimeIn->Rise + tDelayBlockFall; + } + pPin = Mio_PinReadNext(pPin); + } + pTimeOut->Worst = ABC_MAX( pTimeOut->Rise, pTimeOut->Fall ); +} + + + + +/**Function************************************************************* + + Synopsis [Computes the level of the node using its fanin levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjLevelNew( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i, Level = 0; + Abc_ObjForEachFanin( pObj, pFanin, i ) + Level = ABC_MAX( Level, Abc_ObjLevel(pFanin) ); + return Level + 1; +} + +/**Function************************************************************* + + Synopsis [Computes the reverse level of the node using its fanout levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i, LevelCur, Level = 0; + Abc_ObjForEachFanout( pObj, pFanout, i ) + { + LevelCur = Abc_ObjReverseLevel( pFanout ); + Level = ABC_MAX( Level, LevelCur ); + } + return Level + 1; +} + +/**Function************************************************************* + + Synopsis [Returns required level of the node.] + + Description [Converts the reverse levels of the node into its required + level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjRequiredLevel( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( pNtk->vLevelsR ); + return pNtk->LevelMax + 1 - Abc_ObjReverseLevel(pObj); +} + +/**Function************************************************************* + + Synopsis [Returns the reverse level of the node.] + + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjReverseLevel( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( pNtk->vLevelsR ); + Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); + return Vec_IntEntry(pNtk->vLevelsR, pObj->Id); +} + +/**Function************************************************************* + + Synopsis [Sets the reverse level of the node.] + + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + assert( pNtk->vLevelsR ); + Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); + Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, LevelR ); +} + +/**Function************************************************************* + + Synopsis [Prepares for the computation of required levels.] + + Description [This procedure should be called before the required times + are used. It starts internal data structures, which records the level + from the COs of the network nodes in reverse topologogical order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + // remember the maximum number of direct levels + pNtk->LevelMax = Abc_NtkLevel(pNtk) + nMaxLevelIncrease; + // start the reverse levels + pNtk->vLevelsR = Vec_IntAlloc( 0 ); + Vec_IntFill( pNtk->vLevelsR, 1 + Abc_NtkObjNumMax(pNtk), 0 ); + // compute levels in reverse topological order + vNodes = Abc_NtkDfsReverse( pNtk ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + Abc_ObjSetReverseLevel( pObj, Abc_ObjReverseLevelNew(pObj) ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Cleans the data structures used to compute required levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ) +{ + assert( pNtk->vLevelsR ); + Vec_IntFree( pNtk->vLevelsR ); + pNtk->vLevelsR = NULL; + pNtk->LevelMax = 0; + +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +{ + Abc_Obj_t * pFanout, * pTemp; + int LevelOld, Lev, k, m; + // check if level has changed + LevelOld = Abc_ObjLevel(pObjNew); + if ( LevelOld == Abc_ObjLevelNew(pObjNew) ) + return; + // start the data structure for level update + // we cannot fail to visit a node when using this structure because the + // nodes are stored by their _old_ levels, which are assumed to be correct + Vec_VecClear( vLevels ); + Vec_VecPush( vLevels, LevelOld, pObjNew ); + pObjNew->fMarkA = 1; + // recursively update level + Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld ) + { + pTemp->fMarkA = 0; + assert( Abc_ObjLevel(pTemp) == Lev ); + Abc_ObjSetLevel( pTemp, Abc_ObjLevelNew(pTemp) ); + // if the level did not change, no need to check the fanout levels + if ( Abc_ObjLevel(pTemp) == Lev ) + continue; + // schedule fanout for level update + Abc_ObjForEachFanout( pTemp, pFanout, m ) + { + if ( !Abc_ObjIsCo(pFanout) && !pFanout->fMarkA ) + { + assert( Abc_ObjLevel(pFanout) >= Lev ); + Vec_VecPush( vLevels, Abc_ObjLevel(pFanout), pFanout ); + pFanout->fMarkA = 1; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +{ + Abc_Obj_t * pFanin, * pTemp; + int LevelOld, LevFanin, Lev, k, m; + // check if level has changed + LevelOld = Abc_ObjReverseLevel(pObjNew); + if ( LevelOld == Abc_ObjReverseLevelNew(pObjNew) ) + return; + // start the data structure for level update + // we cannot fail to visit a node when using this structure because the + // nodes are stored by their _old_ levels, which are assumed to be correct + Vec_VecClear( vLevels ); + Vec_VecPush( vLevels, LevelOld, pObjNew ); + pObjNew->fMarkA = 1; + // recursively update level + Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld ) + { + pTemp->fMarkA = 0; + LevelOld = Abc_ObjReverseLevel(pTemp); + assert( LevelOld == Lev ); + Abc_ObjSetReverseLevel( pTemp, Abc_ObjReverseLevelNew(pTemp) ); + // if the level did not change, no need to check the fanout levels + if ( Abc_ObjReverseLevel(pTemp) == Lev ) + continue; + // schedule fanins for level update + Abc_ObjForEachFanin( pTemp, pFanin, m ) + { + if ( !Abc_ObjIsCi(pFanin) && !pFanin->fMarkA ) + { + LevFanin = Abc_ObjReverseLevel( pFanin ); + assert( LevFanin >= Lev ); + Vec_VecPush( vLevels, LevFanin, pFanin ); + pFanin->fMarkA = 1; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Replaces the node and incrementally updates levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) +{ + // replace the old node by the new node + pObjNew->Level = pObj->Level; + Abc_ObjReplace( pObj, pObjNew ); + // update the level of the node + Abc_NtkUpdateLevel( pObjNew, vLevels ); + Abc_ObjSetReverseLevel( pObjNew, 0 ); + Abc_NtkUpdateReverseLevel( pObjNew, vLevels ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcUnate.c b/abc70930/src/base/abci/abcUnate.c new file mode 100644 index 00000000..20804d19 --- /dev/null +++ b/abc70930/src/base/abci/abcUnate.c @@ -0,0 +1,155 @@ +/**CFile**************************************************************** + + FileName [abcUnate.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcUnate.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose ); +static void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Detects unate variables of the multi-output function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose ) +{ + if ( fUseBdds || fUseNaive ) + Abc_NtkPrintUnateBdd( pNtk, fUseNaive, fVerbose ); + else + Abc_NtkPrintUnateSat( pNtk, fVerbose ); +} + +/**Function************************************************************* + + Synopsis [Detects unate variables using BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose ) +{ + Abc_Obj_t * pNode; + Extra_UnateInfo_t * p; + DdManager * dd; // the BDD manager used to hold shared BDDs +// DdNode ** pbGlobal; // temporary storage for global BDDs + int TotalSupps = 0; + int TotalUnate = 0; + int i, clk = clock(); + int clkBdd, clkUnate; + + // compute the global BDDs + dd = Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose); + if ( dd == NULL ) + return; +clkBdd = clock() - clk; + + // get information about the network +// dd = pNtk->pManGlob; +// dd = Abc_NtkGlobalBddMan( pNtk ); +// pbGlobal = (DdNode **)Vec_PtrArray( pNtk->vFuncsGlob ); + + // print the size of the BDDs + printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // perform naive BDD-based computation + if ( fUseNaive ) + { + Abc_NtkForEachCo( pNtk, pNode, i ) + { +// p = Extra_UnateComputeSlow( dd, pbGlobal[i] ); + p = Extra_UnateComputeSlow( dd, Abc_ObjGlobalBdd(pNode) ); + if ( fVerbose ) + Extra_UnateInfoPrint( p ); + TotalSupps += p->nVars; + TotalUnate += p->nUnate; + Extra_UnateInfoDissolve( p ); + } + } + // perform smart BDD-based computation + else + { + // create ZDD variables in the manager + Cudd_zddVarsFromBddVars( dd, 2 ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { +// p = Extra_UnateComputeFast( dd, pbGlobal[i] ); + p = Extra_UnateComputeFast( dd, Abc_ObjGlobalBdd(pNode) ); + if ( fVerbose ) + Extra_UnateInfoPrint( p ); + TotalSupps += p->nVars; + TotalUnate += p->nUnate; + Extra_UnateInfoDissolve( p ); + } + } +clkUnate = clock() - clk - clkBdd; + + // print stats + printf( "Ins/Outs = %4d/%4d. Total supp = %5d. Total unate = %5d.\n", + Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), TotalSupps, TotalUnate ); + PRT( "Glob BDDs", clkBdd ); + PRT( "Unateness", clkUnate ); + PRT( "Total ", clock() - clk ); + + // deref the PO functions +// Abc_NtkFreeGlobalBdds( pNtk ); + // stop the global BDD manager +// Extra_StopManager( pNtk->pManGlob ); +// pNtk->pManGlob = NULL; + Abc_NtkFreeGlobalBdds( pNtk, 1 ); +} + +/**Function************************************************************* + + Synopsis [Detects unate variables using SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose ) +{ +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcUnreach.c b/abc70930/src/base/abci/abcUnreach.c new file mode 100644 index 00000000..ea0a4cd2 --- /dev/null +++ b/abc70930/src/base/abci/abcUnreach.c @@ -0,0 +1,349 @@ +/**CFile**************************************************************** + + FileName [abcUnreach.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computes unreachable states for small benchmarks.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcUnreach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ); +static DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ); +static DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bRelation, DdNode * bInitial, bool fVerbose ); +static Abc_Ntk_t * Abc_NtkConstructExdc ( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Extracts sequential DCs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose ) +{ + int fReorder = 1; + DdManager * dd; + DdNode * bRelation, * bInitial, * bUnreach; + + // remove EXDC network if present + if ( pNtk->pExdc ) + { + Abc_NtkDelete( pNtk->pExdc ); + pNtk->pExdc = NULL; + } + + // compute the global BDDs of the latches + dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); + if ( dd == NULL ) + return 0; + if ( fVerbose ) + printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // create the transition relation (dereferenced global BDDs) + bRelation = Abc_NtkTransitionRelation( dd, pNtk, fVerbose ); Cudd_Ref( bRelation ); + // create the initial state and the variable map + bInitial = Abc_NtkInitStateAndVarMap( dd, pNtk, fVerbose ); Cudd_Ref( bInitial ); + // compute the unreachable states + bUnreach = Abc_NtkComputeUnreachable( dd, pNtk, bRelation, bInitial, fVerbose ); Cudd_Ref( bUnreach ); + Cudd_RecursiveDeref( dd, bRelation ); + Cudd_RecursiveDeref( dd, bInitial ); + + // reorder and disable reordering + if ( fReorder ) + { + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the unreachable states before reordering %d.\n", Cudd_DagSize(bUnreach) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); + Cudd_AutodynDisable( dd ); + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the unreachable states after reordering %d.\n", Cudd_DagSize(bUnreach) ); + } + + // allocate ZDD variables + Cudd_zddVarsFromBddVars( dd, 2 ); + // create the EXDC network representing the unreachable states + if ( pNtk->pExdc ) + Abc_NtkDelete( pNtk->pExdc ); + pNtk->pExdc = Abc_NtkConstructExdc( dd, pNtk, bUnreach ); + Cudd_RecursiveDeref( dd, bUnreach ); + Extra_StopManager( dd ); +// pNtk->pManGlob = NULL; + + // make sure that everything is okay + if ( pNtk->pExdc && !Abc_NtkCheck( pNtk->pExdc ) ) + { + printf( "Abc_NtkExtractSequentialDcs: The network check has failed.\n" ); + Abc_NtkDelete( pNtk->pExdc ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the transition relation of the network.] + + Description [Assumes that the global BDDs are computed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) +{ + DdNode * bRel, * bTemp, * bProd, * bVar, * bInputs; + Abc_Obj_t * pNode; + int fReorder = 1; + int i; + + // extand the BDD manager to represent NS variables + assert( dd->size == Abc_NtkCiNum(pNtk) ); + Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 ); + + // enable reordering + if ( fReorder ) + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + else + Cudd_AutodynDisable( dd ); + + // compute the transition relation + bRel = b1; Cudd_Ref( bRel ); + Abc_NtkForEachLatch( pNtk, pNode, i ) + { + bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i ); +// bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd ); + bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd ); + bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + // free the global BDDs +// Abc_NtkFreeGlobalBdds( pNtk ); + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + + // quantify the PI variables + bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs ); + bRel = Cudd_bddExistAbstract( dd, bTemp = bRel, bInputs ); Cudd_Ref( bRel ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bInputs ); + + // reorder and disable reordering + if ( fReorder ) + { + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the transition relation before reordering %d.\n", Cudd_DagSize(bRel) ); + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + Cudd_AutodynDisable( dd ); + if ( fVerbose ) + fprintf( stdout, "BDD nodes in the transition relation after reordering %d.\n", Cudd_DagSize(bRel) ); + } + Cudd_Deref( bRel ); + return bRel; +} + +/**Function************************************************************* + + Synopsis [Computes the initial state and sets up the variable map.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) +{ + DdNode ** pbVarsX, ** pbVarsY; + DdNode * bTemp, * bProd, * bVar; + Abc_Obj_t * pLatch; + int i; + + // set the variable mapping for Cudd_bddVarMap() + pbVarsX = ALLOC( DdNode *, dd->size ); + pbVarsY = ALLOC( DdNode *, dd->size ); + bProd = b1; Cudd_Ref( bProd ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pbVarsX[i] = dd->vars[ Abc_NtkPiNum(pNtk) + i ]; + pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ]; + // get the initial value of the latch + bVar = Cudd_NotCond( pbVarsX[i], !Abc_LatchIsInit1(pLatch) ); + bProd = Cudd_bddAnd( dd, bTemp = bProd, bVar ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Abc_NtkLatchNum(pNtk) ); + FREE( pbVarsX ); + FREE( pbVarsY ); + + Cudd_Deref( bProd ); + return bProd; +} + +/**Function************************************************************* + + Synopsis [Computes the set of unreachable states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bTrans, DdNode * bInitial, bool fVerbose ) +{ + DdNode * bRelation, * bReached, * bCubeCs; + DdNode * bCurrent, * bNext, * bTemp; + int nIters, nMints; + + // perform reachability analisys + bCurrent = bInitial; Cudd_Ref( bCurrent ); + bReached = bInitial; Cudd_Ref( bReached ); + bRelation = bTrans; Cudd_Ref( bRelation ); + bCubeCs = Extra_bddComputeRangeCube( dd, Abc_NtkPiNum(pNtk), Abc_NtkCiNum(pNtk) ); Cudd_Ref( bCubeCs ); + for ( nIters = 1; ; nIters++ ) + { + // compute the next states + bNext = Cudd_bddAndAbstract( dd, bRelation, bCurrent, bCubeCs ); Cudd_Ref( bNext ); + Cudd_RecursiveDeref( dd, bCurrent ); + // remap these states into the current state vars + bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext ); + Cudd_RecursiveDeref( dd, bTemp ); + // check if there are any new states + if ( Cudd_bddLeq( dd, bNext, bReached ) ) + break; + // get the new states + bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); + // minimize the new states with the reached states +// bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); +// Cudd_RecursiveDeref( dd, bTemp ); + // add to the reached states + bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bNext ); + // minimize the transition relation +// bRelation = Cudd_bddConstrain( dd, bTemp = bRelation, Cudd_Not(bReached) ); Cudd_Ref( bRelation ); +// Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_RecursiveDeref( dd, bRelation ); + Cudd_RecursiveDeref( dd, bCubeCs ); + Cudd_RecursiveDeref( dd, bNext ); + // report the stats + if ( fVerbose ) + { + nMints = (int)Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) ); + fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters ); + fprintf( stdout, "The number of minterms in the reachable state set = %d. (%6.2f %%)\n", nMints, 100.0*nMints/(1<pName = Extra_UtilStrsav( "exdc" ); + pNtkNew->pSpec = NULL; + + // create PIs corresponding to LOs + Abc_NtkForEachLatchOutput( pNtk, pNode, i ) + Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pNode), NULL ); + // cannot ADD POs here because pLatch->pCopy point to the PIs + + // create a new node + pNodeNew = Abc_NtkCreateNode(pNtkNew); + // add the fanins corresponding to latch outputs + Abc_NtkForEachLatchOutput( pNtk, pNode, i ) + Abc_ObjAddFanin( pNodeNew, pNode->pCopy ); + + // create the logic function + pPermute = ALLOC( int, dd->size ); + for ( i = 0; i < dd->size; i++ ) + pPermute[i] = -1; + Abc_NtkForEachLatch( pNtk, pNode, i ) + pPermute[Abc_NtkPiNum(pNtk) + i] = i; + // remap the functions + pNodeNew->pData = Extra_TransferPermute( dd, pNtkNew->pManFunc, bUnreach, pPermute ); Cudd_Ref( pNodeNew->pData ); + free( pPermute ); + Abc_NodeMinimumBase( pNodeNew ); + + // for each CO, create PO (skip POs equal to CIs because of name conflict) + Abc_NtkForEachPo( pNtk, pNode, i ) + if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) + Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL ); + Abc_NtkForEachLatchInput( pNtk, pNode, i ) + Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL ); + + // link to the POs of the network + Abc_NtkForEachPo( pNtk, pNode, i ) + if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + Abc_NtkForEachLatchInput( pNtk, pNode, i ) + Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); + + // remove the extra nodes + Abc_AigCleanup( pNtkNew->pManFunc ); + + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + + // transform the network to the SOP representation + if ( !Abc_NtkBddToSop( pNtkNew, 0 ) ) + { + printf( "Abc_NtkConstructExdc(): Converting to SOPs has failed.\n" ); + return NULL; + } + return pNtkNew; +// return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcVerify.c b/abc70930/src/base/abci/abcVerify.c new file mode 100644 index 00000000..9c9bbcfd --- /dev/null +++ b/abc70930/src/base/abci/abcVerify.c @@ -0,0 +1,1018 @@ +/**CFile**************************************************************** + + FileName [abcVerify.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Combinational and sequential verification for two networks.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcVerify.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel ); +extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Verifies combinational equivalence by brute-force SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ) +{ + extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); + Abc_Ntk_t * pMiter; + Abc_Ntk_t * pCnf; + int RetValue; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); + Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are equivalent after structural hashing.\n" ); + return; + } + + // convert the miter into a CNF + pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 ); + Abc_NtkDelete( pMiter ); + if ( pCnf == NULL ) + { + printf( "Renoding for CNF has failed.\n" ); + return; + } + + // solve the CNF using the SAT solver + RetValue = Abc_NtkMiterSat( pCnf, (sint64)nConfLimit, (sint64)nInsLimit, 0, NULL, NULL ); + if ( RetValue == -1 ) + printf( "Networks are undecided (SAT solver timed out).\n" ); + else if ( RetValue == 0 ) + printf( "Networks are NOT EQUIVALENT after SAT.\n" ); + else + printf( "Networks are equivalent after SAT.\n" ); + if ( pCnf->pModel ) + Abc_NtkVerifyReportError( pNtk1, pNtk2, pCnf->pModel ); + FREE( pCnf->pModel ); + Abc_NtkDelete( pCnf ); +} + + +/**Function************************************************************* + + Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ) +{ + Prove_Params_t Params, * pParams = &Params; +// Fraig_Params_t Params; +// Fraig_Man_t * pMan; + Abc_Ntk_t * pMiter; + int RetValue; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); + Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return; + } + if ( RetValue == 1 ) + { + printf( "Networks are equivalent after structural hashing.\n" ); + Abc_NtkDelete( pMiter ); + return; + } +/* + // convert the miter into a FRAIG + Fraig_ParamsSetDefault( &Params ); + Params.fVerbose = fVerbose; + Params.nSeconds = nSeconds; +// Params.fFuncRed = 0; +// Params.nPatsRand = 0; +// Params.nPatsDyna = 0; + pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 ); + Fraig_ManProveMiter( pMan ); + + // analyze the result + RetValue = Fraig_ManCheckMiter( pMan ); + // report the result + if ( RetValue == -1 ) + printf( "Networks are undecided (SAT solver timed out on the final miter).\n" ); + else if ( RetValue == 1 ) + printf( "Networks are equivalent after fraiging.\n" ); + else if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after fraiging.\n" ); + Abc_NtkVerifyReportError( pNtk1, pNtk2, Fraig_ManReadModel(pMan) ); + } + else assert( 0 ); + // delete the fraig manager + Fraig_ManFree( pMan ); + // delete the miter + Abc_NtkDelete( pMiter ); +*/ + // solve the CNF using the SAT solver + Prove_ParamsSetDefault( pParams ); + pParams->nItersMax = 5; +// RetValue = Abc_NtkMiterProve( &pMiter, pParams ); +// pParams->fVerbose = 1; + RetValue = Abc_NtkIvyProve( &pMiter, pParams ); + if ( RetValue == -1 ) + printf( "Networks are undecided (resource limits is reached).\n" ); + else if ( RetValue == 0 ) + { + int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiter, pMiter->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); + else + printf( "Networks are NOT EQUIVALENT.\n" ); + free( pSimInfo ); + } + else + printf( "Networks are equivalent.\n" ); + if ( pMiter->pModel ) + Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + Abc_NtkDelete( pMiter ); +} + +/**Function************************************************************* + + Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose ) +{ + extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); + extern void * Abc_FrameGetGlobalFrame(); + + Prove_Params_t Params, * pParams = &Params; + Abc_Ntk_t * pMiter, * pMiterPart; + Abc_Obj_t * pObj; + int i, RetValue, Status, nOutputs; + + // solve the CNF using the SAT solver + Prove_ParamsSetDefault( pParams ); + pParams->nItersMax = 5; + // pParams->fVerbose = 1; + + assert( nPartSize > 0 ); + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, nPartSize ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); + Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return; + } + if ( RetValue == 1 ) + { + printf( "Networks are equivalent after structural hashing.\n" ); + Abc_NtkDelete( pMiter ); + return; + } + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); + + // solve the problem iteratively for each output of the miter + Status = 1; + nOutputs = 0; + Abc_NtkForEachPo( pMiter, pObj, i ) + { + if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pMiter) ) + { + if ( Abc_ObjFaninC0(pObj) ) // complemented -> const 0 + RetValue = 1; + else + RetValue = 0; + pMiterPart = NULL; + } + else + { + // get the cone of this output + pMiterPart = Abc_NtkCreateCone( pMiter, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 0 ); + if ( Abc_ObjFaninC0(pObj) ) + Abc_ObjXorFaninC( Abc_NtkPo(pMiterPart,0), 0 ); + // solve the cone + // RetValue = Abc_NtkMiterProve( &pMiterPart, pParams ); + RetValue = Abc_NtkIvyProve( &pMiterPart, pParams ); + } + + if ( RetValue == -1 ) + { + printf( "Networks are undecided (resource limits is reached).\r" ); + Status = -1; + } + else if ( RetValue == 0 ) + { + int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); + else + printf( "Networks are NOT EQUIVALENT. \n" ); + free( pSimInfo ); + Status = 0; + break; + } + else + { + printf( "Finished part %5d (out of %5d)\r", i+1, Abc_NtkPoNum(pMiter) ); + nOutputs += nPartSize; + } +// if ( pMiter->pModel ) +// Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + if ( pMiterPart ) + Abc_NtkDelete( pMiterPart ); + } + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); + + if ( Status == 1 ) + printf( "Networks are equivalent. \n" ); + else if ( Status == -1 ) + printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) ); + Abc_NtkDelete( pMiter ); +} + +/**Function************************************************************* + + Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ) +{ + extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); + extern Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nPartSizeLimit, int fVerbose ); + extern void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOnePtr ); + extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); + extern void * Abc_FrameGetGlobalFrame(); + + Vec_Ptr_t * vParts, * vOnePtr; + Vec_Int_t * vOne; + Prove_Params_t Params, * pParams = &Params; + Abc_Ntk_t * pMiter, * pMiterPart; + int i, RetValue, Status, nOutputs; + + // solve the CNF using the SAT solver + Prove_ParamsSetDefault( pParams ); + pParams->nItersMax = 5; + // pParams->fVerbose = 1; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 1 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); + Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return; + } + if ( RetValue == 1 ) + { + printf( "Networks are equivalent after structural hashing.\n" ); + Abc_NtkDelete( pMiter ); + return; + } + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); + + // partition the outputs + vParts = Abc_NtkPartitionSmart( pMiter, 300, 0 ); + + // fraig each partition + Status = 1; + nOutputs = 0; + vOnePtr = Vec_PtrAlloc( 1000 ); + Vec_PtrForEachEntry( vParts, vOne, i ) + { + // get this part of the miter + Abc_NtkConvertCos( pMiter, vOne, vOnePtr ); + pMiterPart = Abc_NtkCreateConeArray( pMiter, vOnePtr, 0 ); + Abc_NtkCombinePos( pMiterPart, 0 ); + // check the miter for being constant + RetValue = Abc_NtkMiterIsConstant( pMiterPart ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after partitioning.\n" ); + Abc_NtkDelete( pMiterPart ); + break; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiterPart ); + continue; + } + printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", + i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pMiterPart), Abc_NtkPoNum(pMiterPart), + Abc_NtkNodeNum(pMiterPart), Abc_AigLevel(pMiterPart) ); + // solve the problem + RetValue = Abc_NtkIvyProve( &pMiterPart, pParams ); + if ( RetValue == -1 ) + { + printf( "Networks are undecided (resource limits is reached).\r" ); + Status = -1; + } + else if ( RetValue == 0 ) + { + int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel ); + if ( pSimInfo[0] != 1 ) + printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); + else + printf( "Networks are NOT EQUIVALENT. \n" ); + free( pSimInfo ); + Status = 0; + Abc_NtkDelete( pMiterPart ); + break; + } + else + { +// printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) ); + nOutputs += Vec_IntSize(vOne); + } + Abc_NtkDelete( pMiterPart ); + } + printf( " \r" ); + Vec_VecFree( (Vec_Vec_t *)vParts ); + Vec_PtrFree( vOnePtr ); + + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); + + if ( Status == 1 ) + printf( "Networks are equivalent. \n" ); + else if ( Status == -1 ) + printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) ); + Abc_NtkDelete( pMiter ); +} + +/**Function************************************************************* + + Synopsis [Verifies sequential equivalence by brute-force SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames ) +{ + extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); + Abc_Ntk_t * pMiter; + Abc_Ntk_t * pFrames; + Abc_Ntk_t * pCnf; + int RetValue; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + return; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are equivalent after structural hashing.\n" ); + return; + } + + // create the timeframes + pFrames = Abc_NtkFrames( pMiter, nFrames, 1 ); + Abc_NtkDelete( pMiter ); + if ( pFrames == NULL ) + { + printf( "Frames computation has failed.\n" ); + return; + } + RetValue = Abc_NtkMiterIsConstant( pFrames ); + if ( RetValue == 0 ) + { + Abc_NtkDelete( pFrames ); + printf( "Networks are NOT EQUIVALENT after framing.\n" ); + return; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pFrames ); + printf( "Networks are equivalent after framing.\n" ); + return; + } + + // convert the miter into a CNF + pCnf = Abc_NtkMulti( pFrames, 0, 100, 1, 0, 0, 0 ); + Abc_NtkDelete( pFrames ); + if ( pCnf == NULL ) + { + printf( "Renoding for CNF has failed.\n" ); + return; + } + + // solve the CNF using the SAT solver + RetValue = Abc_NtkMiterSat( pCnf, (sint64)nConfLimit, (sint64)nInsLimit, 0, NULL, NULL ); + if ( RetValue == -1 ) + printf( "Networks are undecided (SAT solver timed out).\n" ); + else if ( RetValue == 0 ) + printf( "Networks are NOT EQUIVALENT after SAT.\n" ); + else + printf( "Networks are equivalent after SAT.\n" ); + Abc_NtkDelete( pCnf ); +} + +/**Function************************************************************* + + Synopsis [Verifies combinational equivalence by fraiging followed by SAT] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ) +{ + Fraig_Params_t Params; + Fraig_Man_t * pMan; + Abc_Ntk_t * pMiter; + Abc_Ntk_t * pFrames; + int RetValue; + + // get the miter of the two networks + pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 ); + if ( pMiter == NULL ) + { + printf( "Miter computation has failed.\n" ); + return 0; + } + RetValue = Abc_NtkMiterIsConstant( pMiter ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); + // report the error + pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); + Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); + FREE( pMiter->pModel ); + Abc_NtkDelete( pMiter ); + return 0; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pMiter ); + printf( "Networks are equivalent after structural hashing.\n" ); + return 1; + } + + // create the timeframes + pFrames = Abc_NtkFrames( pMiter, nFrames, 1 ); + Abc_NtkDelete( pMiter ); + if ( pFrames == NULL ) + { + printf( "Frames computation has failed.\n" ); + return 0; + } + RetValue = Abc_NtkMiterIsConstant( pFrames ); + if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after framing.\n" ); + // report the error + pFrames->pModel = Abc_NtkVerifyGetCleanModel( pFrames, 1 ); +// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pFrames->pModel, nFrames ); + FREE( pFrames->pModel ); + Abc_NtkDelete( pFrames ); + return 0; + } + if ( RetValue == 1 ) + { + Abc_NtkDelete( pFrames ); + printf( "Networks are equivalent after framing.\n" ); + return 1; + } + + // convert the miter into a FRAIG + Fraig_ParamsSetDefault( &Params ); + Params.fVerbose = fVerbose; + Params.nSeconds = nSeconds; +// Params.fFuncRed = 0; +// Params.nPatsRand = 0; +// Params.nPatsDyna = 0; + pMan = Abc_NtkToFraig( pFrames, &Params, 0, 0 ); + Fraig_ManProveMiter( pMan ); + + // analyze the result + RetValue = Fraig_ManCheckMiter( pMan ); + // report the result + if ( RetValue == -1 ) + printf( "Networks are undecided (SAT solver timed out on the final miter).\n" ); + else if ( RetValue == 1 ) + printf( "Networks are equivalent after fraiging.\n" ); + else if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT after fraiging.\n" ); +// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, Fraig_ManReadModel(pMan), nFrames ); + } + else assert( 0 ); + // delete the fraig manager + Fraig_ManFree( pMan ); + // delete the miter + Abc_NtkDelete( pFrames ); + return RetValue == 1; +} + +/**Function************************************************************* + + Synopsis [Returns a dummy pattern full of zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames ) +{ + int * pModel = ALLOC( int, Abc_NtkCiNum(pNtk) * nFrames ); + memset( pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) * nFrames ); + return pModel; +} + +/**Function************************************************************* + + Synopsis [Returns the PO values under the given input pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel ) +{ + Abc_Obj_t * pNode; + int * pValues, Value0, Value1, i; + int fStrashed = 0; + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash(pNtk, 0, 0, 0); + fStrashed = 1; + } +/* + printf( "Counter example: " ); + Abc_NtkForEachCi( pNtk, pNode, i ) + printf( " %d", pModel[i] ); + printf( "\n" ); +*/ + // increment the trav ID + Abc_NtkIncrementTravId( pNtk ); + // set the CI values + Abc_AigConst1(pNtk)->pCopy = (void *)1; + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = (void *)pModel[i]; + // simulate in the topological order + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Value0 = ((int)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode); + Value1 = ((int)Abc_ObjFanin1(pNode)->pCopy) ^ Abc_ObjFaninC1(pNode); + pNode->pCopy = (void *)(Value0 & Value1); + } + // fill the output values + pValues = ALLOC( int, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pNode, i ) + pValues[i] = ((int)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode); + if ( fStrashed ) + Abc_NtkDelete( pNtk ); + return pValues; +} + + +/**Function************************************************************* + + Synopsis [Reports mismatch between the two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int * pValues1, * pValues2; + int nErrors, nPrinted, i, iNode = -1; + + assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); + assert( Abc_NtkCoNum(pNtk1) == Abc_NtkCoNum(pNtk2) ); + // get the CO values under this model + pValues1 = Abc_NtkVerifySimulatePattern( pNtk1, pModel ); + pValues2 = Abc_NtkVerifySimulatePattern( pNtk2, pModel ); + // count the mismatches + nErrors = 0; + for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) + nErrors += (int)( pValues1[i] != pValues2[i] ); + printf( "Verification failed for at least %d outputs: ", nErrors ); + // print the first 3 outputs + nPrinted = 0; + for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) + if ( pValues1[i] != pValues2[i] ) + { + if ( iNode == -1 ) + iNode = i; + printf( " %s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) ); + if ( ++nPrinted == 3 ) + break; + } + if ( nPrinted != nErrors ) + printf( " ..." ); + printf( "\n" ); + // report mismatch for the first output + if ( iNode >= 0 ) + { + printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", + Abc_ObjName(Abc_NtkCo(pNtk1,iNode)), pValues1[iNode], pValues2[iNode] ); + printf( "Input pattern: " ); + // collect PIs in the cone + pNode = Abc_NtkCo(pNtk1,iNode); + vNodes = Abc_NtkNodeSupport( pNtk1, &pNode, 1 ); + // set the PI numbers + Abc_NtkForEachCi( pNtk1, pNode, i ) + pNode->pCopy = (void*)i; + // print the model + pNode = Vec_PtrEntry( vNodes, 0 ); + if ( Abc_ObjIsCi(pNode) ) + { + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + assert( Abc_ObjIsCi(pNode) ); + printf( " %s=%d", Abc_ObjName(pNode), pModel[(int)pNode->pCopy] ); + } + } + printf( "\n" ); + Vec_PtrFree( vNodes ); + } + free( pValues1 ); + free( pValues2 ); +} + + +/**Function************************************************************* + + Synopsis [Computes the COs in the support of the PO in the given frame.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkGetSeqPoSupp( Abc_Ntk_t * pNtk, int iFrame, int iNumPo ) +{ + Abc_Ntk_t * pFrames; + Abc_Obj_t * pObj, * pNodePo; + Vec_Ptr_t * vSupp; + int i, k; + // get the timeframes of the network + pFrames = Abc_NtkFrames( pNtk, iFrame + 1, 0 ); +//Abc_NtkShowAig( pFrames ); + + // get the PO of the timeframes + pNodePo = Abc_NtkPo( pFrames, iFrame * Abc_NtkPoNum(pNtk) + iNumPo ); + // set the support + vSupp = Abc_NtkNodeSupport( pFrames, &pNodePo, 1 ); + // mark the support of the frames + Abc_NtkForEachCi( pFrames, pObj, i ) + pObj->pCopy = NULL; + Vec_PtrForEachEntry( vSupp, pObj, i ) + pObj->pCopy = (void *)1; + // mark the support of the network if the support of the timeframes is marked + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = NULL; + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( Abc_NtkBox(pFrames, i)->pCopy ) + pObj->pCopy = (void *)1; + Abc_NtkForEachPi( pNtk, pObj, i ) + for ( k = 0; k <= iFrame; k++ ) + if ( Abc_NtkPi(pFrames, k*Abc_NtkPiNum(pNtk) + i)->pCopy ) + pObj->pCopy = (void *)1; + // free stuff + Vec_PtrFree( vSupp ); + Abc_NtkDelete( pFrames ); +} + +/**Function************************************************************* + + Synopsis [Reports mismatch between the two sequential networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ) +{ + Vec_Ptr_t * vInfo1, * vInfo2; + Abc_Obj_t * pObj, * pObjError, * pObj1, * pObj2; + int ValueError1, ValueError2; + unsigned * pPats1, * pPats2; + int i, o, k, nErrors, iFrameError, iNodePo, nPrinted; + int fRemove1 = 0, fRemove2 = 0; + + if ( !Abc_NtkIsStrash(pNtk1) ) + fRemove1 = 1, pNtk1 = Abc_NtkStrash( pNtk1, 0, 0, 0 ); + if ( !Abc_NtkIsStrash(pNtk2) ) + fRemove2 = 1, pNtk2 = Abc_NtkStrash( pNtk2, 0, 0, 0 ); + + // simulate sequential circuits + vInfo1 = Sim_SimulateSeqModel( pNtk1, nFrames, pModel ); + vInfo2 = Sim_SimulateSeqModel( pNtk2, nFrames, pModel ); + + // look for a discrepancy in the PO values + nErrors = 0; + pObjError = NULL; + for ( i = 0; i < nFrames; i++ ) + { + if ( pObjError ) + break; + Abc_NtkForEachPo( pNtk1, pObj1, o ) + { + pObj2 = Abc_NtkPo( pNtk2, o ); + pPats1 = Sim_SimInfoGet(vInfo1, pObj1); + pPats2 = Sim_SimInfoGet(vInfo2, pObj2); + if ( pPats1[i] == pPats2[i] ) + continue; + nErrors++; + if ( pObjError == NULL ) + { + pObjError = pObj1; + iFrameError = i; + iNodePo = o; + ValueError1 = (pPats1[i] > 0); + ValueError2 = (pPats2[i] > 0); + } + } + } + + if ( pObjError == NULL ) + { + printf( "No output mismatches detected.\n" ); + Sim_UtilInfoFree( vInfo1 ); + Sim_UtilInfoFree( vInfo2 ); + if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); + if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); + return; + } + + printf( "Verification failed for at least %d output%s of frame %d: ", nErrors, (nErrors>1? "s":""), iFrameError+1 ); + // print the first 3 outputs + nPrinted = 0; + Abc_NtkForEachPo( pNtk1, pObj1, o ) + { + pObj2 = Abc_NtkPo( pNtk2, o ); + pPats1 = Sim_SimInfoGet(vInfo1, pObj1); + pPats2 = Sim_SimInfoGet(vInfo2, pObj2); + if ( pPats1[iFrameError] == pPats2[iFrameError] ) + continue; + printf( " %s", Abc_ObjName(pObj1) ); + if ( ++nPrinted == 3 ) + break; + } + if ( nPrinted != nErrors ) + printf( " ..." ); + printf( "\n" ); + + // mark CIs of the networks in the cone of influence of this output + Abc_NtkGetSeqPoSupp( pNtk1, iFrameError, iNodePo ); + Abc_NtkGetSeqPoSupp( pNtk2, iFrameError, iNodePo ); + + // report mismatch for the first output + printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", + Abc_ObjName(pObjError), ValueError1, ValueError2 ); + + printf( "The cone of influence of output %s in Network1:\n", Abc_ObjName(pObjError) ); + printf( "PIs: " ); + Abc_NtkForEachPi( pNtk1, pObj, i ) + if ( pObj->pCopy ) + printf( "%s ", Abc_ObjName(pObj) ); + printf( "\n" ); + printf( "Latches: " ); + Abc_NtkForEachLatch( pNtk1, pObj, i ) + if ( pObj->pCopy ) + printf( "%s ", Abc_ObjName(pObj) ); + printf( "\n" ); + + printf( "The cone of influence of output %s in Network2:\n", Abc_ObjName(pObjError) ); + printf( "PIs: " ); + Abc_NtkForEachPi( pNtk2, pObj, i ) + if ( pObj->pCopy ) + printf( "%s ", Abc_ObjName(pObj) ); + printf( "\n" ); + printf( "Latches: " ); + Abc_NtkForEachLatch( pNtk2, pObj, i ) + if ( pObj->pCopy ) + printf( "%s ", Abc_ObjName(pObj) ); + printf( "\n" ); + + // print the patterns + for ( i = 0; i <= iFrameError; i++ ) + { + printf( "Frame %d: ", i+1 ); + + printf( "PI(1):" ); + Abc_NtkForEachPi( pNtk1, pObj, k ) + if ( pObj->pCopy ) + printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 ); + printf( " " ); + printf( "L(1):" ); + Abc_NtkForEachLatch( pNtk1, pObj, k ) + if ( pObj->pCopy ) + printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 ); + printf( " " ); + printf( "%s(1):", Abc_ObjName(pObjError) ); + printf( "%d", Sim_SimInfoGet(vInfo1, pObjError)[i] > 0 ); + + printf( " " ); + + printf( "PI(2):" ); + Abc_NtkForEachPi( pNtk2, pObj, k ) + if ( pObj->pCopy ) + printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 ); + printf( " " ); + printf( "L(2):" ); + Abc_NtkForEachLatch( pNtk2, pObj, k ) + if ( pObj->pCopy ) + printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 ); + printf( " " ); + printf( "%s(2):", Abc_ObjName(pObjError) ); + printf( "%d", Sim_SimInfoGet(vInfo2, pObjError)[i] > 0 ); + + printf( "\n" ); + } + Abc_NtkForEachCi( pNtk1, pObj, i ) + pObj->pCopy = NULL; + Abc_NtkForEachCi( pNtk2, pObj, i ) + pObj->pCopy = NULL; + + Sim_UtilInfoFree( vInfo1 ); + Sim_UtilInfoFree( vInfo2 ); + if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); + if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); +} + +/**Function************************************************************* + + Synopsis [Simulates buggy miter emailed by Mike.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSimulteBuggyMiter( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + int * pModel1, * pModel2, * pResult1, * pResult2; + char * vPiValues1 = "01001011100000000011010110101000000"; + char * vPiValues2 = "11001101011101011111110100100010001"; + + assert( strlen(vPiValues1) == (unsigned)Abc_NtkPiNum(pNtk) ); + assert( 1 == Abc_NtkPoNum(pNtk) ); + + pModel1 = ALLOC( int, Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + pModel1[i] = vPiValues1[i] - '0'; + Abc_NtkForEachLatch( pNtk, pObj, i ) + pModel1[Abc_NtkPiNum(pNtk)+i] = ((int)pObj->pData) - 1; + + pResult1 = Abc_NtkVerifySimulatePattern( pNtk, pModel1 ); + printf( "Value = %d\n", pResult1[0] ); + + pModel2 = ALLOC( int, Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + pModel2[i] = vPiValues2[i] - '0'; + Abc_NtkForEachLatch( pNtk, pObj, i ) + pModel2[Abc_NtkPiNum(pNtk)+i] = pResult1[Abc_NtkPoNum(pNtk)+i]; + + pResult2 = Abc_NtkVerifySimulatePattern( pNtk, pModel2 ); + printf( "Value = %d\n", pResult2[0] ); + + free( pModel1 ); + free( pModel2 ); + free( pResult1 ); + free( pResult2 ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abcXsim.c b/abc70930/src/base/abci/abcXsim.c new file mode 100644 index 00000000..5d9e4634 --- /dev/null +++ b/abc70930/src/base/abci/abcXsim.c @@ -0,0 +1,227 @@ +/**CFile**************************************************************** + + FileName [abcXsim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Using X-valued simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcXsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define XVS0 ABC_INIT_ZERO +#define XVS1 ABC_INIT_ONE +#define XVSX ABC_INIT_DC + +static inline void Abc_ObjSetXsim( Abc_Obj_t * pObj, int Value ) { pObj->pCopy = (void *)Value; } +static inline int Abc_ObjGetXsim( Abc_Obj_t * pObj ) { return (int)pObj->pCopy; } +static inline int Abc_XsimInv( int Value ) +{ + if ( Value == XVS0 ) + return XVS1; + if ( Value == XVS1 ) + return XVS0; + assert( Value == XVSX ); + return XVSX; +} +static inline int Abc_XsimAnd( int Value0, int Value1 ) +{ + if ( Value0 == XVS0 || Value1 == XVS0 ) + return XVS0; + if ( Value0 == XVSX || Value1 == XVSX ) + return XVSX; + assert( Value0 == XVS1 && Value1 == XVS1 ); + return XVS1; +} +static inline int Abc_XsimRand2() +{ + return (rand() & 1) ? XVS1 : XVS0; +} +static inline int Abc_XsimRand3() +{ + int RetValue; + do { + RetValue = rand() & 3; + } while ( RetValue == 0 ); + return RetValue; +} +static inline int Abc_ObjGetXsimFanin0( Abc_Obj_t * pObj ) +{ + int RetValue; + RetValue = Abc_ObjGetXsim(Abc_ObjFanin0(pObj)); + return Abc_ObjFaninC0(pObj)? Abc_XsimInv(RetValue) : RetValue; +} +static inline int Abc_ObjGetXsimFanin1( Abc_Obj_t * pObj ) +{ + int RetValue; + RetValue = Abc_ObjGetXsim(Abc_ObjFanin1(pObj)); + return Abc_ObjFaninC1(pObj)? Abc_XsimInv(RetValue) : RetValue; +} +static inline void Abc_XsimPrint( FILE * pFile, int Value ) +{ + if ( Value == XVS0 ) + { + fprintf( pFile, "0" ); + return; + } + if ( Value == XVS1 ) + { + fprintf( pFile, "1" ); + return; + } + assert( Value == XVSX ); + fprintf( pFile, "x" ); +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs X-valued simulation of the sequential network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose ) +{ + Abc_Obj_t * pObj; + int i, f; + assert( Abc_NtkIsStrash(pNtk) ); + srand( 0x12341234 ); + // start simulation + Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); + if ( fXInputs ) + { + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, XVSX ); + } + else + { + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); + } + if ( fXState ) + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjSetXsim( Abc_ObjFanout0(pObj), XVSX ); + } + else + { + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) ); + } + // simulate and print the result + fprintf( stdout, "Frame : Inputs : Latches : Outputs\n" ); + for ( f = 0; f < nFrames; f++ ) + { + Abc_AigForEachAnd( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); + // print out + fprintf( stdout, "%2d : ", f ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); + fprintf( stdout, " : " ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { +// if ( Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) != XVSX ) +// printf( " %s=", Abc_ObjName(pObj) ); + Abc_XsimPrint( stdout, Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) ); + } + fprintf( stdout, " : " ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); + if ( Abc_NtkAssertNum(pNtk) ) + { + fprintf( stdout, " : " ); + Abc_NtkForEachAssert( pNtk, pObj, i ) + Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); + } + fprintf( stdout, "\n" ); + // assign input values + if ( fXInputs ) + { + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, XVSX ); + } + else + { + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); + } + // transfer the latch values + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); + } +} + +/**Function************************************************************* + + Synopsis [Cycles the circuit to create a new initial state.] + + Description [Simulates the circuit with random input for the given + number of timeframes to get a better initial state.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ) +{ + Abc_Obj_t * pObj; + int i, f; + assert( Abc_NtkIsStrash(pNtk) ); + srand( 0x12341234 ); + // initialize the values + Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchIsInit1(pObj)? XVS1 : XVS0 ); + // simulate for the given number of timeframes + for ( f = 0; f < nFrames; f++ ) + { + Abc_AigForEachAnd( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); + // assign input values + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); + // transfer the latch values + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); + } + // set the final values + Abc_NtkForEachLatch( pNtk, pObj, i ) + pObj->pData = (void *)Abc_ObjGetXsim(Abc_ObjFanout0(pObj)); +} + +/////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/abc_.c b/abc70930/src/base/abci/abc_.c new file mode 100644 index 00000000..75ec88c3 --- /dev/null +++ b/abc70930/src/base/abci/abc_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [abc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/abci/module.make b/abc70930/src/base/abci/module.make new file mode 100644 index 00000000..4558119e --- /dev/null +++ b/abc70930/src/base/abci/module.make @@ -0,0 +1,54 @@ +SRC += src/base/abci/abc.c \ + src/base/abci/abcAttach.c \ + src/base/abci/abcAuto.c \ + src/base/abci/abcBalance.c \ + src/base/abci/abcBmc.c \ + src/base/abci/abcCas.c \ + src/base/abci/abcClpBdd.c \ + src/base/abci/abcClpSop.c \ + src/base/abci/abcCut.c \ + src/base/abci/abcDar.c \ + src/base/abci/abcDebug.c \ + src/base/abci/abcDress.c \ + src/base/abci/abcDsd.c \ + src/base/abci/abcEspresso.c \ + src/base/abci/abcExtract.c \ + src/base/abci/abcFpga.c \ + src/base/abci/abcFpgaFast.c \ + src/base/abci/abcFraig.c \ + src/base/abci/abcFxu.c \ + src/base/abci/abcGen.c \ + src/base/abci/abcHaig.c \ + src/base/abci/abcIf.c \ + src/base/abci/abcIvy.c \ + src/base/abci/abcLut.c \ + src/base/abci/abcMap.c \ + src/base/abci/abcMini.c \ + src/base/abci/abcMiter.c \ + src/base/abci/abcMulti.c \ + src/base/abci/abcNtbdd.c \ + src/base/abci/abcOdc.c \ + src/base/abci/abcOrder.c \ + src/base/abci/abcPart.c \ + src/base/abci/abcPrint.c \ + src/base/abci/abcProve.c \ + src/base/abci/abcQbf.c \ + src/base/abci/abcQuant.c \ + src/base/abci/abcRec.c \ + src/base/abci/abcReconv.c \ + src/base/abci/abcRefactor.c \ + src/base/abci/abcRenode.c \ + src/base/abci/abcReorder.c \ + src/base/abci/abcRestruct.c \ + src/base/abci/abcResub.c \ + src/base/abci/abcRewrite.c \ + src/base/abci/abcRr.c \ + src/base/abci/abcSat.c \ + src/base/abci/abcStrash.c \ + src/base/abci/abcSweep.c \ + src/base/abci/abcSymm.c \ + src/base/abci/abcTiming.c \ + src/base/abci/abcUnate.c \ + src/base/abci/abcUnreach.c \ + src/base/abci/abcVerify.c \ + src/base/abci/abcXsim.c diff --git a/abc70930/src/base/cmd/cmd.c b/abc70930/src/base/cmd/cmd.c new file mode 100644 index 00000000..2dc03d5c --- /dev/null +++ b/abc70930/src/base/cmd/cmd.c @@ -0,0 +1,1674 @@ +/**CFile**************************************************************** + + FileName [cmd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Command file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifdef WIN32 +#include +#endif + +#include "mainInt.h" +#include "cmdInt.h" +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int CmdCommandTime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandEcho ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandQuit ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandWhich ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandHistory ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandAlias ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandUnalias ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandHelp ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandSource ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandSetVariable ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandUnsetVariable ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandUndo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandRecall ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandEmpty ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#ifdef WIN32 +static int CmdCommandLs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#endif +static int CmdCommandSis ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandMvsis ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int CmdCommandCapo ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function******************************************************************** + + Synopsis [Initializes the command package.] + + SideEffects [Commands are added to the command table.] + + SeeAlso [Cmd_End] + +******************************************************************************/ +void Cmd_Init( Abc_Frame_t * pAbc ) +{ + pAbc->tCommands = st_init_table(strcmp, st_strhash); + pAbc->tAliases = st_init_table(strcmp, st_strhash); + pAbc->tFlags = st_init_table(strcmp, st_strhash); + pAbc->aHistory = Vec_PtrAlloc( 100 ); + + Cmd_CommandAdd( pAbc, "Basic", "time", CmdCommandTime, 0); + Cmd_CommandAdd( pAbc, "Basic", "echo", CmdCommandEcho, 0); + Cmd_CommandAdd( pAbc, "Basic", "quit", CmdCommandQuit, 0); + Cmd_CommandAdd( pAbc, "Basic", "history", CmdCommandHistory, 0); + Cmd_CommandAdd( pAbc, "Basic", "alias", CmdCommandAlias, 0); + Cmd_CommandAdd( pAbc, "Basic", "unalias", CmdCommandUnalias, 0); + Cmd_CommandAdd( pAbc, "Basic", "help", CmdCommandHelp, 0); + Cmd_CommandAdd( pAbc, "Basic", "source", CmdCommandSource, 0); + Cmd_CommandAdd( pAbc, "Basic", "set", CmdCommandSetVariable, 0); + Cmd_CommandAdd( pAbc, "Basic", "unset", CmdCommandUnsetVariable, 0); + Cmd_CommandAdd( pAbc, "Basic", "undo", CmdCommandUndo, 0); + Cmd_CommandAdd( pAbc, "Basic", "recall", CmdCommandRecall, 0); + Cmd_CommandAdd( pAbc, "Basic", "empty", CmdCommandEmpty, 0); +#ifdef WIN32 + Cmd_CommandAdd( pAbc, "Basic", "ls", CmdCommandLs, 0 ); +#endif + + Cmd_CommandAdd( pAbc, "Various", "sis", CmdCommandSis, 1); + Cmd_CommandAdd( pAbc, "Various", "mvsis", CmdCommandMvsis, 1); + Cmd_CommandAdd( pAbc, "Various", "capo", CmdCommandCapo, 0); +} + +/**Function******************************************************************** + + Synopsis [Ends the command package.] + + Description [Ends the command package. Tables are freed.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Cmd_End( Abc_Frame_t * pAbc ) +{ + st_generator * gen; + char * pKey, * pValue; + int i; + +// st_free_table( pAbc->tCommands, (void (*)()) 0, CmdCommandFree ); +// st_free_table( pAbc->tAliases, (void (*)()) 0, CmdCommandAliasFree ); +// st_free_table( pAbc->tFlags, free, free ); + + st_foreach_item( pAbc->tCommands, gen, (char **)&pKey, (char **)&pValue ) + CmdCommandFree( (Abc_Command *)pValue ); + st_free_table( pAbc->tCommands ); + + st_foreach_item( pAbc->tAliases, gen, (char **)&pKey, (char **)&pValue ) + CmdCommandAliasFree( (Abc_Alias *)pValue ); + st_free_table( pAbc->tAliases ); + + st_foreach_item( pAbc->tFlags, gen, (char **)&pKey, (char **)&pValue ) + free( pKey ), free( pValue ); + st_free_table( pAbc->tFlags ); + + for ( i = 0; i < pAbc->aHistory->nSize; i++ ) + free( pAbc->aHistory->pArray[i] ); + Vec_PtrFree( pAbc->aHistory ); +} + + + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind ) + { + goto usage; + } + + pAbc->TimeTotal += pAbc->TimeCommand; + fprintf( pAbc->Out, "elapse: %3.2f seconds, total: %3.2f seconds\n", + (float)pAbc->TimeCommand / CLOCKS_PER_SEC, (float)pAbc->TimeTotal / CLOCKS_PER_SEC ); +/* + { + FILE * pTable; + pTable = fopen( "runtimes.txt", "a+" ); + fprintf( pTable, "%4.2f\n", (float)pAbc->TimeCommand / CLOCKS_PER_SEC ); + fclose( pTable ); + } +*/ + pAbc->TimeCommand = 0; + return 0; + + usage: + fprintf( pAbc->Err, "usage: time [-h]\n" ); + fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int i; + int c; + int n = 1; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "hn" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + n = 0; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + for ( i = globalUtilOptind; i < argc; i++ ) + fprintf( pAbc->Out, "%s ", argv[i] ); + if ( n ) + fprintf( pAbc->Out, "\n" ); + else + fflush ( pAbc->Out ); + return 0; + + usage: + fprintf( pAbc->Err, "usage: echo [-h] string \n" ); + fprintf( pAbc->Err, " -n \t\tsuppress newline at the end\n" ); + fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); + return ( 1 ); +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "hs" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + case 's': + return -2; + break; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind ) + goto usage; + return -1; + + usage: + fprintf( pAbc->Err, "usage: quit [-h] [-s]\n" ); + fprintf( pAbc->Err, " -h print the command usage\n" ); + fprintf( pAbc->Err, + " -s frees all the memory before quitting\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandWhich( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + return 0; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int i, c, num, size; + + num = 20; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default : + goto usage; + } + } + if ( argc > 2 ) + goto usage; + + // get the number of commands to print + if ( argc == globalUtilOptind + 1 ) + num = atoi(argv[globalUtilOptind]); + // print the commands + size = pAbc->aHistory->nSize; + num = ( num < size ) ? num : size; + for ( i = size - num; i < size; i++ ) + fprintf( pAbc->Out, "%s", pAbc->aHistory->pArray[i] ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: history [-h] \n" ); + fprintf( pAbc->Err, " prints the latest command entered on the command line\n" ); + fprintf( pAbc->Err, " -h : print the command usage\n" ); + fprintf( pAbc->Err, "num : print the last num commands\n" ); + return ( 1 ); +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandAlias( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char *key, *value; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + + if ( argc == 1 ) + { + CmdPrintTable( pAbc->tAliases, 1 ); + return 0; + + } + else if ( argc == 2 ) + { + if ( st_lookup( pAbc->tAliases, argv[1], &value ) ) + CmdCommandAliasPrint( pAbc, ( Abc_Alias * ) value ); + return 0; + } + + // delete any existing alias + key = argv[1]; + if ( st_delete( pAbc->tAliases, &key, &value ) ) + CmdCommandAliasFree( ( Abc_Alias * ) value ); + CmdCommandAliasAdd( pAbc, argv[1], argc - 2, argv + 2 ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: alias [-h] [command [string]]\n" ); + fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); + return ( 1 ); +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandUnalias( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int i; + char *key, *value; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( argc < 2 ) + { + goto usage; + } + + for ( i = 1; i < argc; i++ ) + { + key = argv[i]; + if ( st_delete( pAbc->tAliases, &key, &value ) ) + { + CmdCommandAliasFree( ( Abc_Alias * ) value ); + } + } + return 0; + + usage: + fprintf( pAbc->Err, "usage: unalias [-h] alias_names\n" ); + fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + bool fPrintAll; + int c; + + fPrintAll = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + case 'v': + fPrintAll ^= 1; + break; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind ) + goto usage; + + CmdCommandPrint( pAbc, fPrintAll ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: help [-a] [-h]\n" ); + fprintf( pAbc->Err, " prints the list of available commands by group\n" ); + fprintf( pAbc->Err, " -a toggle printing hidden commands [default = %s]\n", fPrintAll? "yes": "no" ); + fprintf( pAbc->Err, " -h print the command usage\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int c, echo, prompt, silent, interactive, quit_count, lp_count; + int status = 0; /* initialize so that lint doesn't complain */ + int lp_file_index, did_subst; + char *prompt_string, *real_filename, line[MAX_STR], *command; + FILE *fp; + + interactive = silent = prompt = echo = 0; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ipsxh" ) ) != EOF ) + { + switch ( c ) + { + case 'i': /* a hack to distinguish EOF from stdin */ + interactive = 1; + break; + case 'p': + prompt ^= 1; + break; + case 's': + silent ^= 1; + break; + case 'x': + echo ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + /* added to avoid core-dumping when no script file is specified */ + if ( argc == globalUtilOptind ) + { + goto usage; + } + + lp_file_index = globalUtilOptind; + lp_count = 0; + + /* + * FIX (Tom, 5/7/95): I'm not sure what the purpose of this outer do loop + * is. In particular, lp_file_index is never modified in the loop, so it + * looks it would just read the same file over again. Also, SIS had + * lp_count initialized to -1, and hence, any file sourced by SIS (if -l or + * -t options on "source" were used in SIS) would actually be executed + * twice. + */ + do + { + lp_count++; /* increment the loop counter */ + + fp = CmdFileOpen( pAbc, argv[lp_file_index], "r", &real_filename, silent ); + if ( fp == NULL ) + { + FREE( real_filename ); + return !silent; /* error return if not silent */ + } + + quit_count = 0; + do + { + if ( prompt ) + { + prompt_string = Cmd_FlagReadByName( pAbc, "prompt" ); + if ( prompt_string == NULL ) + prompt_string = "abc> "; + + } + else + { + prompt_string = NULL; + } + + /* clear errors -- e.g., EOF reached from stdin */ + clearerr( fp ); + + /* read another command line */ +// if (CmdFgetsFilec(line, MAX_STR, fp, prompt_string) == NULL) { +// Abc_UtilsPrintPrompt(prompt_string); +// fflush(stdout); + if ( fgets( line, MAX_STR, fp ) == NULL ) + { + if ( interactive ) + { + if ( quit_count++ < 5 ) + { + fprintf( pAbc->Err, "\nUse \"quit\" to leave ABC.\n" ); + continue; + } + status = -1; /* fake a 'quit' */ + } + else + { + status = 0; /* successful end of 'source' ; loop? */ + } + break; + } + quit_count = 0; + + if ( echo ) + { + fprintf( pAbc->Out, "abc - > %s", line ); + } + command = CmdHistorySubstitution( pAbc, line, &did_subst ); + if ( command == NULL ) + { + status = 1; + break; + } + if ( did_subst ) + { + if ( interactive ) + { + fprintf( pAbc->Out, "%s\n", command ); + } + } + if ( command != line ) + { + ( void ) strcpy( line, command ); + } + if ( interactive && *line != '\0' ) + { + Cmd_HistoryAddCommand( pAbc, Extra_UtilStrsav(line) ); + if ( pAbc->Hst != NULL ) + { + fprintf( pAbc->Hst, "%s\n", line ); + ( void ) fflush( pAbc->Hst ); + } + } + + status = Cmd_CommandExecute( pAbc, line ); + } + while ( status == 0 ); + + if ( fp != stdin ) + { + if ( status > 0 ) + { + fprintf( pAbc->Err, + "** cmd error: aborting 'source %s'\n", + real_filename ); + } + ( void ) fclose( fp ); + } + FREE( real_filename ); + + } + while ( ( status == 0 ) && ( lp_count <= 0 ) ); + + return status; + + usage: + fprintf( pAbc->Err, "usage: source [-psxh] \n" ); + fprintf( pAbc->Err, "\t-p supply prompt before reading each line [default = %s]\n", prompt? "yes": "no" ); + fprintf( pAbc->Err, "\t-s silently ignore nonexistant file [default = %s]\n", silent? "yes": "no" ); + fprintf( pAbc->Err, "\t-x echo each line as it is executed [default = %s]\n", echo? "yes": "no" ); + fprintf( pAbc->Err, "\t-h print the command usage\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char *flag_value, *key, *value; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == 0 || argc > 3 ) + { + goto usage; + } + else if ( argc == 1 ) + { + CmdPrintTable( pAbc->tFlags, 0 ); + return 0; + } + else + { + key = argv[1]; + if ( st_delete( pAbc->tFlags, &key, &value ) ) + { + FREE( key ); + FREE( value ); + } + + flag_value = argc == 2 ? Extra_UtilStrsav( "" ) : Extra_UtilStrsav( argv[2] ); +// flag_value = argc == 2 ? NULL : Extra_UtilStrsav(argv[2]); + st_insert( pAbc->tFlags, Extra_UtilStrsav(argv[1]), flag_value ); + + if ( strcmp( argv[1], "abcout" ) == 0 ) + { + if ( pAbc->Out != stdout ) + fclose( pAbc->Out ); + if ( strcmp( flag_value, "" ) == 0 ) + flag_value = "-"; + pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); + if ( pAbc->Out == NULL ) + pAbc->Out = stdout; +#if HAVE_SETVBUF + setvbuf( pAbc->Out, ( char * ) NULL, _IOLBF, 0 ); +#endif + } + if ( strcmp( argv[1], "abcerr" ) == 0 ) + { + if ( pAbc->Err != stderr ) + fclose( pAbc->Err ); + if ( strcmp( flag_value, "" ) == 0 ) + flag_value = "-"; + pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); + if ( pAbc->Err == NULL ) + pAbc->Err = stderr; +#if HAVE_SETVBUF + setvbuf( pAbc->Err, ( char * ) NULL, _IOLBF, 0 ); +#endif + } + if ( strcmp( argv[1], "history" ) == 0 ) + { + if ( pAbc->Hst != NULL ) + fclose( pAbc->Hst ); + if ( strcmp( flag_value, "" ) == 0 ) + pAbc->Hst = NULL; + else + { + pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); + if ( pAbc->Hst == NULL ) + pAbc->Hst = NULL; + } + } + return 0; + } + + usage: + fprintf( pAbc->Err, "usage: set [-h] \n" ); + fprintf( pAbc->Err, "\t sets the value of parameter \n" ); + fprintf( pAbc->Err, "\t-h : print the command usage\n" ); + return 1; + +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandUnsetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int i; + char *key, *value; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( argc < 2 ) + { + goto usage; + } + + for ( i = 1; i < argc; i++ ) + { + key = argv[i]; + if ( st_delete( pAbc->tFlags, &key, &value ) ) + { + FREE( key ); + FREE( value ); + } + } + return 0; + + + usage: + fprintf( pAbc->Err, "usage: unset [-h] \n" ); + fprintf( pAbc->Err, "\t removes the value of parameter \n" ); + fprintf( pAbc->Err, "\t-h : print the command usage\n" ); + return 1; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + // if there are no arguments on the command line + // set the current network to be the network from the previous step + if ( argc == 1 ) + return CmdCommandRecall( pAbc, argc, argv ); + + fprintf( pAbc->Err, "usage: undo\n" ); + fprintf( pAbc->Err, " sets the current network to be the previously saved network\n" ); + return 1; + +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandRecall( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtk; + int iStep, iStepFound; + int nNetsToSave, c; + char * pValue; + int iStepStart, iStepStop; + + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + // get the number of networks to save + pValue = Cmd_FlagReadByName( pAbc, "savesteps" ); + // if the value of steps to save is not set, assume 1-level undo + if ( pValue == NULL ) + nNetsToSave = 1; + else + nNetsToSave = atoi(pValue); + + // if there are no arguments on the command line + // set the current network to be the network from the previous step + if ( argc == 1 ) + { + // get the previously saved network + pNtk = Abc_NtkBackup(pAbc->pNtkCur); + if ( pNtk == NULL ) + fprintf( pAbc->Out, "There is no previously saved network.\n" ); + else // set the current network to be the copy of the previous one + Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pNtk) ); + return 0; + } + if ( argc == 2 ) // the second argument is the number of the step to return to + { + // read the number of the step to return to + iStep = atoi(argv[1]); + // check whether it is reasonable + if ( iStep >= pAbc->nSteps ) + { + iStepStart = pAbc->nSteps - nNetsToSave; + if ( iStepStart <= 0 ) + iStepStart = 1; + iStepStop = pAbc->nSteps; + if ( iStepStop <= 0 ) + iStepStop = 1; + if ( iStepStart == iStepStop ) + fprintf( pAbc->Out, "Can only recall step %d.\n", iStepStop ); + else + fprintf( pAbc->Out, "Can only recall steps %d-%d.\n", iStepStart, iStepStop ); + } + else if ( iStep < 0 ) + fprintf( pAbc->Out, "Cannot recall step %d.\n", iStep ); + else if ( iStep == 0 ) + Abc_FrameDeleteAllNetworks( pAbc ); + else + { + // scroll backward through the list of networks + // to determine if such a network exist + iStepFound = 0; + for ( pNtk = pAbc->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk) ) + if ( (iStepFound = Abc_NtkStep(pNtk)) == iStep ) + break; + if ( pNtk == NULL ) + { + iStepStart = iStepFound; + if ( iStepStart <= 0 ) + iStepStart = 1; + iStepStop = pAbc->nSteps; + if ( iStepStop <= 0 ) + iStepStop = 1; + if ( iStepStart == iStepStop ) + fprintf( pAbc->Out, "Can only recall step %d.\n", iStepStop ); + else + fprintf( pAbc->Out, "Can only recall steps %d-%d.\n", iStepStart, iStepStop ); + } + else + Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pNtk) ); + } + return 0; + } + +usage: + + fprintf( pAbc->Err, "usage: recall -h \n" ); + fprintf( pAbc->Err, " set the current network to be one of the previous networks\n" ); + fprintf( pAbc->Err, " : level to return to [default = previous]\n" ); + fprintf( pAbc->Err, " -h : print the command usage\n"); + return 1; +} + + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandEmpty( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + int c; + + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + Abc_FrameDeleteAllNetworks( pAbc ); + Abc_FrameRestart( pAbc ); + return 0; +usage: + + fprintf( pAbc->Err, "usage: empty [-h]\n" ); + fprintf( pAbc->Err, " removes all the currently stored networks\n" ); + fprintf( pAbc->Err, " -h : print the command usage\n"); + return 1; +} + + +#if 0 + +/**Function******************************************************************** + + Synopsis [Donald's version.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtkTemp; + int id, c; + + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + default: + goto usage; + } + } + if (globalUtilOptind <= argc) { + pNtkTemp = pAbc->pNtk; + pAbc->pNtk = pAbc->pNtkSaved; + pAbc->pNtkSaved = pNtkTemp; + } + id = atoi(argv[globalUtilOptind]); + pNtkTemp = Cmd_HistoryGetSnapshot(pAbc, id); + if (!pNtkTemp) + fprintf( pAbc->Err, "Snapshot %d does not exist\n", id); + else + pAbc->pNtk = Abc_NtkDup(pNtkTemp, Abc_NtkMan(pNtkTemp)); + + return 0; +usage: + fprintf( pAbc->Err, "usage: undo\n" ); + fprintf( pAbc->Err, " swaps the current network and the backup network\n" ); + return 1; +} + +#endif + + +#ifdef WIN32 +/**Function************************************************************* + + Synopsis [Command to print the contents of the current directory (Windows).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#include + +// these structures are defined in but are for some reason invisible +typedef unsigned long _fsize_t; // Could be 64 bits for Win32 + +struct _finddata_t { + unsigned attrib; + time_t time_create; // -1 for FAT file systems + time_t time_access; // -1 for FAT file systems + time_t time_write; + _fsize_t size; + char name[260]; +}; + +extern long _findfirst( char *filespec, struct _finddata_t *fileinfo ); +extern int _findnext( long handle, struct _finddata_t *fileinfo ); +extern int _findclose( long handle ); + +int CmdCommandLs( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + struct _finddata_t c_file; + long hFile; + int fLong = 0; + int fOnlyBLIF = 0; + char Buffer[25]; + int Counter = 0; + int fPrintedNewLine; + char c; + + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "lb") ) != EOF ) + { + switch (c) + { + case 'l': + fLong = 1; + break; + case 'b': + fOnlyBLIF = 1; + break; + default: + goto usage; + } + } + + // find first .mv file in current directory + if( (hFile = _findfirst( ((fOnlyBLIF)? "*.mv": "*.*"), &c_file )) == -1L ) + { + if ( fOnlyBLIF ) + fprintf( pAbc->Out, "No *.mv files in the current directory.\n" ); + else + fprintf( pAbc->Out, "No files in the current directory.\n" ); + } + else + { + if ( fLong ) + { + fprintf( pAbc->Out, " File Date Size | File Date Size \n" ); + fprintf( pAbc->Out, " ----------------------------------------------------------------------------- \n" ); + do + { + strcpy( Buffer, ctime( &(c_file.time_write) ) ); + Buffer[16] = 0; + fprintf( pAbc->Out, " %-17s %.24s%7ld", c_file.name, Buffer+4, c_file.size ); + if ( ++Counter % 2 == 0 ) + { + fprintf( pAbc->Out, "\n" ); + fPrintedNewLine = 1; + } + else + { + fprintf( pAbc->Out, " |" ); + fPrintedNewLine = 0; + } + } + while( _findnext( hFile, &c_file ) == 0 ); + } + else + { + do + { + fprintf( pAbc->Out, " %-18s", c_file.name ); + if ( ++Counter % 4 == 0 ) + { + fprintf( pAbc->Out, "\n" ); + fPrintedNewLine = 1; + } + else + { + fprintf( pAbc->Out, " " ); + fPrintedNewLine = 0; + } + } + while( _findnext( hFile, &c_file ) == 0 ); + } + if ( !fPrintedNewLine ) + fprintf( pAbc->Out, "\n" ); + _findclose( hFile ); + } + return 0; + +usage: + fprintf( pAbc->Err, "Usage: ls [-l] [-b]\n" ); + fprintf( pAbc->Err, " print the file names in the current directory\n" ); + fprintf( pAbc->Err, " -l : print in the long format [default = short]\n" ); + fprintf( pAbc->Err, " -b : print only .mv files [default = all]\n" ); + return 1; +} +#endif + + + +#ifdef WIN32 +#define unlink _unlink +#endif + +/**Function******************************************************************** + + Synopsis [Calls SIS internally.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkNew, * pNetlist; + char * pNameWin = "sis.exe"; + char * pNameUnix = "sis"; + char Command[1000], Buffer[100]; + char * pSisName; + int i; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + goto usage; + } + + if ( strcmp( argv[0], "sis" ) != 0 ) + { + fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); + goto usage; + } + + if ( argc == 1 ) + goto usage; + if ( strcmp( argv[1], "-h" ) == 0 ) + goto usage; + if ( strcmp( argv[1], "-?" ) == 0 ) + goto usage; + + // get the names from the resource file + if ( Cmd_FlagReadByName(pAbc, "siswin") ) + pNameWin = Cmd_FlagReadByName(pAbc, "siswin"); + if ( Cmd_FlagReadByName(pAbc, "sisunix") ) + pNameUnix = Cmd_FlagReadByName(pAbc, "sisunix"); + + // check if SIS is available + if ( (pFile = fopen( pNameWin, "r" )) ) + pSisName = pNameWin; + else if ( (pFile = fopen( pNameUnix, "r" )) ) + pSisName = pNameUnix; + else if ( pFile == NULL ) + { + fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pNameWin, pNameUnix ); + goto usage; + } + fclose( pFile ); + + if ( Abc_NtkIsMappedLogic(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + printf( "The current network is unmapped before calling SIS.\n" ); + } + + // write out the current network + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkToSop(pNtk, 0); + pNetlist = Abc_NtkToNetlist(pNtk); + if ( pNetlist == NULL ) + { + fprintf( pErr, "Cannot produce the intermediate network.\n" ); + goto usage; + } + Io_WriteBlif( pNetlist, "_sis_in.blif", 1 ); + Abc_NtkDelete( pNetlist ); + + // create the file for sis + sprintf( Command, "%s -x -c ", pSisName ); + strcat ( Command, "\"" ); + strcat ( Command, "read_blif _sis_in.blif" ); + strcat ( Command, "; " ); + for ( i = 1; i < argc; i++ ) + { + sprintf( Buffer, " %s", argv[i] ); + strcat( Command, Buffer ); + } + strcat( Command, "; " ); + strcat( Command, "write_blif _sis_out.blif" ); + strcat( Command, "\"" ); + + // call SIS + if ( system( Command ) ) + { + fprintf( pErr, "The following command has returned non-zero exit status:\n" ); + fprintf( pErr, "\"%s\"\n", Command ); + unlink( "_sis_in.blif" ); + goto usage; + } + + // read in the SIS output + if ( (pFile = fopen( "_sis_out.blif", "r" )) == NULL ) + { + fprintf( pErr, "Cannot open SIS output file \"%s\".\n", "_sis_out.blif" ); + unlink( "_sis_in.blif" ); + goto usage; + } + fclose( pFile ); + + // set the new network + pNtkNew = Io_Read( "_sis_out.blif", IO_FILE_BLIF, 1 ); + // set the original spec of the new network + if ( pNtk->pSpec ) + { + FREE( pNtkNew->pSpec ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); + + // remove temporary networks + unlink( "_sis_in.blif" ); + unlink( "_sis_out.blif" ); + return 0; + +usage: + fprintf( pErr, "\n" ); + fprintf( pErr, "Usage: sis [-h] \n"); + fprintf( pErr, " invokes SIS command for the current ABC network\n" ); + fprintf( pErr, " (the executable of SIS should be in the same directory)\n" ); + fprintf( pErr, " -h : print the command usage\n" ); + fprintf( pErr, " : a SIS command (or a semicolon-separated list of commands in quotes)\n" ); + fprintf( pErr, " Example 1: sis eliminate 0\n" ); + fprintf( pErr, " Example 2: sis \"ps; rd; fx; ps\"\n" ); + fprintf( pErr, " Example 3: sis source script.rugged\n" ); + return 1; // error exit +} + + +/**Function******************************************************************** + + Synopsis [Calls SIS internally.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNtkNew, * pNetlist; + char Command[1000], Buffer[100]; + char * pNameWin = "mvsis.exe"; + char * pNameUnix = "mvsis"; + char * pMvsisName; + int i; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + goto usage; + } + + if ( strcmp( argv[0], "mvsis" ) != 0 ) + { + fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); + goto usage; + } + + if ( argc == 1 ) + goto usage; + if ( strcmp( argv[1], "-h" ) == 0 ) + goto usage; + if ( strcmp( argv[1], "-?" ) == 0 ) + goto usage; + + // get the names from the resource file + if ( Cmd_FlagReadByName(pAbc, "mvsiswin") ) + pNameWin = Cmd_FlagReadByName(pAbc, "mvsiswin"); + if ( Cmd_FlagReadByName(pAbc, "mvsisunix") ) + pNameUnix = Cmd_FlagReadByName(pAbc, "mvsisunix"); + + // check if MVSIS is available + if ( (pFile = fopen( pNameWin, "r" )) ) + pMvsisName = pNameWin; + else if ( (pFile = fopen( pNameUnix, "r" )) ) + pMvsisName = pNameUnix; + else if ( pFile == NULL ) + { + fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pNameWin, pNameUnix ); + goto usage; + } + fclose( pFile ); + + if ( Abc_NtkIsMappedLogic(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + printf( "The current network is unmapped before calling MVSIS.\n" ); + } + + // write out the current network + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkToSop(pNtk, 0); + pNetlist = Abc_NtkToNetlist(pNtk); + if ( pNetlist == NULL ) + { + fprintf( pErr, "Cannot produce the intermediate network.\n" ); + goto usage; + } + Io_WriteBlif( pNetlist, "_mvsis_in.blif", 1 ); + Abc_NtkDelete( pNetlist ); + + // create the file for MVSIS + sprintf( Command, "%s -x -c ", pMvsisName ); + strcat ( Command, "\"" ); + strcat ( Command, "read_blif _mvsis_in.blif" ); + strcat ( Command, "; " ); + for ( i = 1; i < argc; i++ ) + { + sprintf( Buffer, " %s", argv[i] ); + strcat( Command, Buffer ); + } + strcat( Command, "; " ); + strcat( Command, "write_blif _mvsis_out.blif" ); + strcat( Command, "\"" ); + + // call MVSIS + if ( system( Command ) ) + { + fprintf( pErr, "The following command has returned non-zero exit status:\n" ); + fprintf( pErr, "\"%s\"\n", Command ); + unlink( "_mvsis_in.blif" ); + goto usage; + } + + // read in the MVSIS output + if ( (pFile = fopen( "_mvsis_out.blif", "r" )) == NULL ) + { + fprintf( pErr, "Cannot open MVSIS output file \"%s\".\n", "_mvsis_out.blif" ); + unlink( "_mvsis_in.blif" ); + goto usage; + } + fclose( pFile ); + + // set the new network + pNtkNew = Io_Read( "_mvsis_out.blif", IO_FILE_BLIF, 1 ); + // set the original spec of the new network + if ( pNtk->pSpec ) + { + FREE( pNtkNew->pSpec ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); + + // remove temporary networks + unlink( "_mvsis_in.blif" ); + unlink( "_mvsis_out.blif" ); + return 0; + +usage: + fprintf( pErr, "\n" ); + fprintf( pErr, "Usage: mvsis [-h] \n"); + fprintf( pErr, " invokes MVSIS command for the current ABC network\n" ); + fprintf( pErr, " (the executable of MVSIS should be in the same directory)\n" ); + fprintf( pErr, " -h : print the command usage\n" ); + fprintf( pErr, " : a MVSIS command (or a semicolon-separated list of commands in quotes)\n" ); + fprintf( pErr, " Example 1: mvsis fraig_sweep\n" ); + fprintf( pErr, " Example 2: mvsis \"ps; fxu; ps\"\n" ); + fprintf( pErr, " Example 3: mvsis source mvsis.rugged\n" ); + return 1; // error exit +} + + +/**Function******************************************************************** + + Synopsis [Calls Capo internally.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int CmdCommandCapo( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk, * pNetlist; + char Command[1000], Buffer[100]; + char * pProgNameCapoWin = "capo.exe"; + char * pProgNameCapoUnix = "capo"; + char * pProgNameGnuplotWin = "wgnuplot.exe"; + char * pProgNameGnuplotUnix = "gnuplot"; + char * pProgNameCapo; + char * pProgNameGnuplot; + char * pPlotFileName; + int i; + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + goto usage; + } + + if ( strcmp( argv[0], "capo" ) != 0 ) + { + fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); + goto usage; + } + + if ( argc > 1 ) + { + if ( strcmp( argv[1], "-h" ) == 0 ) + goto usage; + if ( strcmp( argv[1], "-?" ) == 0 ) + goto usage; + } + + // get the names from the resource file + if ( Cmd_FlagReadByName(pAbc, "capowin") ) + pProgNameCapoWin = Cmd_FlagReadByName(pAbc, "capowin"); + if ( Cmd_FlagReadByName(pAbc, "capounix") ) + pProgNameCapoUnix = Cmd_FlagReadByName(pAbc, "capounix"); + + // check if capo is available + if ( (pFile = fopen( pProgNameCapoWin, "r" )) ) + pProgNameCapo = pProgNameCapoWin; + else if ( (pFile = fopen( pProgNameCapoUnix, "r" )) ) + pProgNameCapo = pProgNameCapoUnix; + else if ( pFile == NULL ) + { + fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameCapoWin, pProgNameCapoUnix ); + goto usage; + } + fclose( pFile ); + + if ( Abc_NtkIsMappedLogic(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + printf( "The current network is unmapped before calling Capo.\n" ); + } + + // write out the current network + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkToSop(pNtk, 0); + pNetlist = Abc_NtkToNetlist(pNtk); + if ( pNetlist == NULL ) + { + fprintf( pErr, "Cannot produce the intermediate network.\n" ); + goto usage; + } + Io_WriteBlif( pNetlist, "_capo_in.blif", 1 ); + Abc_NtkDelete( pNetlist ); + + // create the file for Capo + sprintf( Command, "%s -f _capo_in.blif -log out.txt ", pProgNameCapo ); + pPlotFileName = NULL; + for ( i = 1; i < argc; i++ ) + { + sprintf( Buffer, " %s", argv[i] ); + strcat( Command, Buffer ); + if ( !strcmp( argv[i], "-plot" ) ) + pPlotFileName = argv[i+1]; + } + + // call Capo + if ( system( Command ) ) + { + fprintf( pErr, "The following command has returned non-zero exit status:\n" ); + fprintf( pErr, "\"%s\"\n", Command ); + unlink( "_capo_in.blif" ); + goto usage; + } + // remove temporary networks + unlink( "_capo_in.blif" ); + if ( pPlotFileName == NULL ) + return 0; + + // get the file name + sprintf( Buffer, "%s.plt", pPlotFileName ); + pPlotFileName = Buffer; + + // read in the Capo plotting output + if ( (pFile = fopen( pPlotFileName, "r" )) == NULL ) + { + fprintf( pErr, "Cannot open the plot file \"%s\".\n\n", pPlotFileName ); + goto usage; + } + fclose( pFile ); + + // get the names from the plotting software + if ( Cmd_FlagReadByName(pAbc, "gnuplotwin") ) + pProgNameGnuplotWin = Cmd_FlagReadByName(pAbc, "gnuplotwin"); + if ( Cmd_FlagReadByName(pAbc, "gnuplotunix") ) + pProgNameGnuplotUnix = Cmd_FlagReadByName(pAbc, "gnuplotunix"); + + // check if Gnuplot is available + if ( (pFile = fopen( pProgNameGnuplotWin, "r" )) ) + pProgNameGnuplot = pProgNameGnuplotWin; + else if ( (pFile = fopen( pProgNameGnuplotUnix, "r" )) ) + pProgNameGnuplot = pProgNameGnuplotUnix; + else if ( pFile == NULL ) + { + fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameGnuplotWin, pProgNameGnuplotUnix ); + goto usage; + } + fclose( pFile ); + + // spawn the viewer +#ifdef WIN32 + if ( _spawnl( _P_NOWAIT, pProgNameGnuplot, pProgNameGnuplot, pPlotFileName, NULL ) == -1 ) + { + fprintf( stdout, "Cannot find \"%s\".\n", pProgNameGnuplot ); + goto usage; + } +#else + { + sprintf( Command, "%s %s ", pProgNameGnuplot, pPlotFileName ); + if ( system( Command ) == -1 ) + { + fprintf( stdout, "Cannot execute \"%s\".\n", Command ); + goto usage; + } + } +#endif + + // remove temporary networks +// unlink( pPlotFileName ); + return 0; + +usage: + fprintf( pErr, "\n" ); + fprintf( pErr, "Usage: capo [-h] \n"); + fprintf( pErr, " peforms placement of the current network using Capo\n" ); + fprintf( pErr, " a Capo binary should be present in the same directory\n" ); + fprintf( pErr, " (if plotting, the Gnuplot binary should also be present)\n" ); + fprintf( pErr, " -h : print the command usage\n" ); + fprintf( pErr, " : a Capo command\n" ); + fprintf( pErr, " Example 1: capo\n" ); + fprintf( pErr, " (performs placement with default options)\n" ); + fprintf( pErr, " Example 2: capo -AR -WS -save\n" ); + fprintf( pErr, " (specifies the aspect ratio [default = 1.0] and\n" ); + fprintf( pErr, " the whitespace percentage [0%%; 100%%) [default = 15%%])\n" ); + fprintf( pErr, " Example 3: capo -plot \n" ); + fprintf( pErr, " (produces and visualize it using Gnuplot)\n" ); + fprintf( pErr, " Example 4: capo -help\n" ); + fprintf( pErr, " (prints the default usage message of the Capo binary)\n" ); + fprintf( pErr, " Please refer to the Capo webpage for additional information:\n" ); + fprintf( pErr, " http://vlsicad.eecs.umich.edu/BK/PDtools/\n" ); + return 1; // error exit +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/cmd/cmd.h b/abc70930/src/base/cmd/cmd.h new file mode 100644 index 00000000..030b77e8 --- /dev/null +++ b/abc70930/src/base/cmd/cmd.h @@ -0,0 +1,73 @@ +/**CFile**************************************************************** + + FileName [cmd.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [External declarations of the command package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CMD_H__ +#define __CMD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct MvCommand Abc_Command; // one command +typedef struct MvAlias Abc_Alias; // one alias + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cmd.c ===========================================================*/ +extern void Cmd_Init(); +extern void Cmd_End(); +/*=== cmdApi.c ========================================================*/ +extern void Cmd_CommandAdd( Abc_Frame_t * pAbc, char * sGroup, char * sName, void * pFunc, int fChanges ); +extern int Cmd_CommandExecute( Abc_Frame_t * pAbc, char * sCommand ); +/*=== cmdFlag.c ========================================================*/ +extern char * Cmd_FlagReadByName( Abc_Frame_t * pAbc, char * flag ); +extern void Cmd_FlagDeleteByName( Abc_Frame_t * pAbc, char * key ); +extern void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * value ); +/*=== cmdHist.c ========================================================*/ +extern void Cmd_HistoryAddCommand( Abc_Frame_t * pAbc, char * command ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/cmd/cmdAlias.c b/abc70930/src/base/cmd/cmdAlias.c new file mode 100644 index 00000000..0ec3feea --- /dev/null +++ b/abc70930/src/base/cmd/cmdAlias.c @@ -0,0 +1,120 @@ +/**CFile**************************************************************** + + FileName [cmdAlias.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures dealing with aliases in the command package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdAlias.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cmdInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** argv ) +{ + Abc_Alias * pAlias; + int fStatus, i; + + pAlias = ALLOC(Abc_Alias, 1); + pAlias->sName = Extra_UtilStrsav(sName); + pAlias->argc = argc; + pAlias->argv = ALLOC(char *, pAlias->argc); + for(i = 0; i < argc; i++) + pAlias->argv[i] = Extra_UtilStrsav(argv[i]); + fStatus = st_insert( pAbc->tAliases, pAlias->sName, (char *) pAlias ); + assert(!fStatus); +} + +/**Function******************************************************************** + + Synopsis [required] + + Description [optional] + + SideEffects [required] + + SeeAlso [optional] + +******************************************************************************/ +void CmdCommandAliasPrint( Abc_Frame_t * pAbc, Abc_Alias * pAlias ) +{ + int i; + fprintf(pAbc->Out, "%-15s", pAlias->sName); + for(i = 0; i < pAlias->argc; i++) + fprintf( pAbc->Out, " %s", pAlias->argv[i] ); + fprintf( pAbc->Out, "\n" ); +} + +/**Function******************************************************************** + + Synopsis [required] + + Description [optional] + + SideEffects [required] + + SeeAlso [optional] + +******************************************************************************/ +char * CmdCommandAliasLookup( Abc_Frame_t * pAbc, char * sCommand ) +{ + Abc_Alias * pAlias; + char * value; + if (!st_lookup( pAbc->tAliases, sCommand, &value)) + return sCommand; + pAlias = (Abc_Alias *) value; + return pAlias->argv[0]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdCommandAliasFree( Abc_Alias * pAlias ) +{ + CmdFreeArgv( pAlias->argc, pAlias->argv ); + FREE(pAlias->sName); + FREE(pAlias); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/cmd/cmdApi.c b/abc70930/src/base/cmd/cmdApi.c new file mode 100644 index 00000000..7167e22b --- /dev/null +++ b/abc70930/src/base/cmd/cmdApi.c @@ -0,0 +1,104 @@ +/**CFile**************************************************************** + + FileName [cmdApi.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [External procedures of the command package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" +#include "cmdInt.h" +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cmd_CommandAdd( Abc_Frame_t * pAbc, char * sGroup, char * sName, void * pFunc, int fChanges ) +{ + char * key, * value; + Abc_Command * pCommand; + int fStatus; + + key = sName; + if ( st_delete( pAbc->tCommands, &key, &value ) ) + { + // delete existing definition for this command + fprintf( pAbc->Err, "Cmd warning: redefining '%s'\n", sName ); + CmdCommandFree( (Abc_Command *)value ); + } + + // create the new command + pCommand = ALLOC( Abc_Command, 1 ); + pCommand->sName = Extra_UtilStrsav( sName ); + pCommand->sGroup = Extra_UtilStrsav( sGroup ); + pCommand->pFunc = pFunc; + pCommand->fChange = fChanges; + fStatus = st_insert( pAbc->tCommands, sName, (char *)pCommand ); + assert( !fStatus ); // the command should not be in the table +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cmd_CommandExecute( Abc_Frame_t * pAbc, char * sCommand ) +{ + int fStatus = 0, argc, loop; + char * sCommandNext, **argv; + + if ( !pAbc->fAutoexac ) + Cmd_HistoryAddCommand(pAbc, sCommand); + sCommandNext = sCommand; + do + { + sCommandNext = CmdSplitLine( pAbc, sCommandNext, &argc, &argv ); + loop = 0; + fStatus = CmdApplyAlias( pAbc, &argc, &argv, &loop ); + if ( fStatus == 0 ) + fStatus = CmdCommandDispatch( pAbc, argc, argv ); + CmdFreeArgv( argc, argv ); + } + while ( fStatus == 0 && *sCommandNext != '\0' ); + return fStatus; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/cmd/cmdFlag.c b/abc70930/src/base/cmd/cmdFlag.c new file mode 100644 index 00000000..993f2a49 --- /dev/null +++ b/abc70930/src/base/cmd/cmdFlag.c @@ -0,0 +1,104 @@ +/**CFile**************************************************************** + + FileName [cmdFlag.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures working with flags.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdFlag.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function******************************************************************** + + Synopsis [Looks up value of flag in table of named values.] + + Description [The command parser maintains a table of named values. These + are manipulated using the 'set' and 'unset' commands. The value of the + named flag is returned, or NULL is returned if the flag has not been set.] + + SideEffects [] + +******************************************************************************/ +char * Cmd_FlagReadByName( Abc_Frame_t * pAbc, char * flag ) +{ + char * value; + if ( st_lookup(pAbc->tFlags, flag, &value) ) + return value; + return NULL; +} + + +/**Function******************************************************************** + + Synopsis [Updates a set value by calling instead of set command.] + + Description [Updates a set value by calling instead of set command.] + + SideEffects [] + +******************************************************************************/ +void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * value ) +{ + char * oldValue, * newValue; + if ( !key ) + return; + if ( value ) + newValue = Extra_UtilStrsav(value); + else + newValue = Extra_UtilStrsav(""); +// newValue = NULL; + if ( st_delete(pAbc->tFlags, &key, &oldValue) ) + FREE(oldValue); + st_insert( pAbc->tFlags, key, newValue ); +} + + +/**Function******************************************************************** + + Synopsis [Deletes a set value by calling instead of unset command.] + + Description [Deletes a set value by calling instead of unset command.] + + SideEffects [] + +******************************************************************************/ +void Cmd_FlagDeleteByName( Abc_Frame_t * pAbc, char * key ) +{ + char *value; + if ( !key ) + return; + if ( st_delete( pAbc->tFlags, &key, &value ) ) + { + FREE(key); + FREE(value); + } +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/cmd/cmdHist.c b/abc70930/src/base/cmd/cmdHist.c new file mode 100644 index 00000000..fae9382d --- /dev/null +++ b/abc70930/src/base/cmd/cmdHist.c @@ -0,0 +1,55 @@ +/**CFile**************************************************************** + + FileName [cmdHist.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures working with history.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdHist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" +#include "cmd.h" +#include "cmdInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cmd_HistoryAddCommand( Abc_Frame_t * p, char * command ) +{ + static char Buffer[MAX_STR]; + strcpy( Buffer, command ); + if ( command[strlen(command)-1] != '\n' ) + strcat( Buffer, "\n" ); + Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/cmd/cmdInt.h b/abc70930/src/base/cmd/cmdInt.h new file mode 100644 index 00000000..c082bd94 --- /dev/null +++ b/abc70930/src/base/cmd/cmdInt.h @@ -0,0 +1,83 @@ +/**CFile**************************************************************** + + FileName [cmdInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Internal declarations of the command package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CMD_INT_H__ +#define __CMD_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "mainInt.h" +#include "cmd.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +struct MvCommand +{ + char * sName; // the command name + char * sGroup; // the group name + void * pFunc; // the function to execute the command + int fChange; // set to 1 to mark that the network is changed +}; + +struct MvAlias +{ + char * sName; // the alias name + int argc; // the number of alias parts + char ** argv; // the alias parts +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cmdAlias.c =============-========================================*/ +extern void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** argv ); +extern void CmdCommandAliasPrint( Abc_Frame_t * pAbc, Abc_Alias * pAlias ); +extern char * CmdCommandAliasLookup( Abc_Frame_t * pAbc, char * sCommand ); +extern void CmdCommandAliasFree( Abc_Alias * p ); +/*=== cmdUtils.c =======================================================*/ +extern int CmdCommandDispatch( Abc_Frame_t * pAbc, int argc, char ** argv ); +extern char * CmdSplitLine( Abc_Frame_t * pAbc, char * sCommand, int * argc, char *** argv ); +extern int CmdApplyAlias( Abc_Frame_t * pAbc, int * argc, char *** argv, int * loop ); +extern char * CmdHistorySubstitution( Abc_Frame_t * pAbc, char * line, int * changed ); +extern FILE * CmdFileOpen( Abc_Frame_t * pAbc, char * sFileName, char * sMode, char ** pFileNameReal, int silent ); +extern void CmdFreeArgv( int argc, char ** argv ); +extern void CmdCommandFree( Abc_Command * pCommand ); +extern void CmdCommandPrint( Abc_Frame_t * pAbc, bool fPrintAll ); +extern void CmdPrintTable( st_table * tTable, int fAliases ); + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/abc70930/src/base/cmd/cmdUtils.c b/abc70930/src/base/cmd/cmdUtils.c new file mode 100644 index 00000000..47e54bb3 --- /dev/null +++ b/abc70930/src/base/cmd/cmdUtils.c @@ -0,0 +1,649 @@ +/**CFile**************************************************************** + + FileName [cmdUtils.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Various utilities of the command package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cmdUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" +#include "abc.h" +#include "cmdInt.h" +#include // proper declaration of isspace + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int cmdCheckShellEscape( Abc_Frame_t * pAbc, int argc, char ** argv) +{ + if (argv[0][0] == '!') + { + const int size = 4096; + int i; + char buffer[4096]; + strncpy (buffer, &argv[0][1], size); + for (i = 1; i < argc; ++i) + { + strncat (buffer, " ", size); + strncat (buffer, argv[i], size); + } + if (buffer[0] == 0) + strncpy (buffer, "/bin/sh", size); + system (buffer); + + // NOTE: Since we reconstruct the cmdline by concatenating + // the parts, we lose information. So a command like + // `!ls "file name"` will be sent to the system as + // `ls file name` which is a BUG + + return 1; + } + else + { + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Executes one command.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CmdCommandDispatch( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNetCopy; + int (*pFunc) ( Abc_Frame_t *, int, char ** ); + Abc_Command * pCommand; + char * value; + int fError; + int clk; + + if ( argc == 0 ) + return 0; + + if ( cmdCheckShellEscape( pAbc, argc, argv ) == 1 ) + return 0; + + // get the command + if ( !st_lookup( pAbc->tCommands, argv[0], (char **)&pCommand ) ) + { // the command is not in the table + fprintf( pAbc->Err, "** cmd error: unknown command '%s'\n", argv[0] ); + return 1; + } + + // get the backup network if the command is going to change the network + if ( pCommand->fChange ) + { + if ( pAbc->pNtkCur && Abc_FrameIsFlagEnabled( "backup" ) ) + { + pNetCopy = Abc_NtkDup( pAbc->pNtkCur ); + Abc_FrameSetCurrentNetwork( pAbc, pNetCopy ); + // swap the current network and the backup network + // to prevent the effect of resetting the short names + Abc_FrameSwapCurrentAndBackup( pAbc ); + } + } + + // execute the command + clk = Extra_CpuTime(); + pFunc = (int (*)(Abc_Frame_t *, int, char **))pCommand->pFunc; + fError = (*pFunc)( pAbc, argc, argv ); + pAbc->TimeCommand += (Extra_CpuTime() - clk); + + // automatic execution of arbitrary command after each command + // usually this is a passive command ... + if ( fError == 0 && !pAbc->fAutoexac ) + { + if ( st_lookup( pAbc->tFlags, "autoexec", &value ) ) + { + pAbc->fAutoexac = 1; + fError = Cmd_CommandExecute( pAbc, value ); + pAbc->fAutoexac = 0; + } + } + return fError; +} + +/**Function************************************************************* + + Synopsis [Splits the command line string into individual commands.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * CmdSplitLine( Abc_Frame_t * pAbc, char *sCommand, int *argc, char ***argv ) +{ + char *p, *start, c; + int i, j; + char *new_arg; + Vec_Ptr_t * vArgs; + int single_quote, double_quote; + + vArgs = Vec_PtrAlloc( 10 ); + + p = sCommand; + for ( ;; ) + { + // skip leading white space + while ( isspace( ( int ) *p ) ) + { + p++; + } + + // skip until end of this token + single_quote = double_quote = 0; + for ( start = p; ( c = *p ) != '\0'; p++ ) + { + if ( c == ';' || c == '#' || isspace( ( int ) c ) ) + { + if ( !single_quote && !double_quote ) + { + break; + } + } + if ( c == '\'' ) + { + single_quote = !single_quote; + } + if ( c == '"' ) + { + double_quote = !double_quote; + } + } + if ( single_quote || double_quote ) + { + ( void ) fprintf( pAbc->Err, "** cmd warning: ignoring unbalanced quote ...\n" ); + } + if ( start == p ) + break; + + new_arg = ALLOC( char, p - start + 1 ); + j = 0; + for ( i = 0; i < p - start; i++ ) + { + c = start[i]; + if ( ( c != '\'' ) && ( c != '\"' ) ) + { + new_arg[j++] = isspace( ( int ) c ) ? ' ' : start[i]; + } + } + new_arg[j] = '\0'; + Vec_PtrPush( vArgs, new_arg ); + } + + *argc = vArgs->nSize; + *argv = (char **)Vec_PtrReleaseArray( vArgs ); + Vec_PtrFree( vArgs ); + if ( *p == ';' ) + { + p++; + } + else if ( *p == '#' ) + { + for ( ; *p != 0; p++ ); // skip to end of line + } + return p; +} + +/**Function************************************************************* + + Synopsis [Replaces parts of the command line string by aliases if given.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop ) +{ + int i, argc, stopit, added, offset, did_subst, subst, fError, newc, j; + char *arg, **argv, **newv; + Abc_Alias *alias; + + argc = *argcp; + argv = *argvp; + stopit = 0; + for ( ; *loop < 200; ( *loop )++ ) + { + if ( argc == 0 ) + return 0; + if ( stopit != 0 || st_lookup( pAbc->tAliases, argv[0], (char **) &alias ) == 0 ) + { + return 0; + } + if ( strcmp( argv[0], alias->argv[0] ) == 0 ) + { + stopit = 1; + } + FREE( argv[0] ); + added = alias->argc - 1; + + /* shift all the arguments to the right */ + if ( added != 0 ) + { + argv = REALLOC( char *, argv, argc + added ); + for ( i = argc - 1; i >= 1; i-- ) + { + argv[i + added] = argv[i]; + } + for ( i = 1; i <= added; i++ ) + { + argv[i] = NULL; + } + argc += added; + } + subst = 0; + for ( i = 0, offset = 0; i < alias->argc; i++, offset++ ) + { + arg = CmdHistorySubstitution( pAbc, alias->argv[i], &did_subst ); + if ( arg == NULL ) + { + *argcp = argc; + *argvp = argv; + return ( 1 ); + } + if ( did_subst != 0 ) + { + subst = 1; + } + fError = 0; + do + { + arg = CmdSplitLine( pAbc, arg, &newc, &newv ); + /* + * If there's a complete `;' terminated command in `arg', + * when split_line() returns arg[0] != '\0'. + */ + if ( arg[0] == '\0' ) + { /* just a bunch of words */ + break; + } + fError = CmdApplyAlias( pAbc, &newc, &newv, loop ); + if ( fError == 0 ) + { + fError = CmdCommandDispatch( pAbc, newc, newv ); + } + CmdFreeArgv( newc, newv ); + } + while ( fError == 0 ); + if ( fError != 0 ) + { + *argcp = argc; + *argvp = argv; + return ( 1 ); + } + added = newc - 1; + if ( added != 0 ) + { + argv = REALLOC( char *, argv, argc + added ); + for ( j = argc - 1; j > offset; j-- ) + { + argv[j + added] = argv[j]; + } + argc += added; + } + for ( j = 0; j <= added; j++ ) + { + argv[j + offset] = newv[j]; + } + FREE( newv ); + offset += added; + } + if ( subst == 1 ) + { + for ( i = offset; i < argc; i++ ) + { + FREE( argv[i] ); + } + argc = offset; + } + *argcp = argc; + *argvp = argv; + } + + fprintf( pAbc->Err, "** cmd warning: alias loop\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs history substitution (now, disabled).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * CmdHistorySubstitution( Abc_Frame_t * pAbc, char *line, int *changed ) +{ + // as of today, no history substitution + *changed = 0; + return line; +} + +/**Function************************************************************* + + Synopsis [Opens the file with path (now, disabled).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFileNameReal, int silent ) +{ + char * sRealName, * sPathUsr, * sPathLib, * sPathAll; + FILE * pFile; + + if (strcmp(sFileName, "-") == 0) { + if (strcmp(sMode, "w") == 0) { + sRealName = Extra_UtilStrsav( "stdout" ); + pFile = stdout; + } + else { + sRealName = Extra_UtilStrsav( "stdin" ); + pFile = stdin; + } + } + else { + sRealName = NULL; + if (strcmp(sMode, "r") == 0) { + + /* combine both pathes if exist */ + sPathUsr = Cmd_FlagReadByName(pAbc,"open_path"); + sPathLib = Cmd_FlagReadByName(pAbc,"lib_path"); + + if ( sPathUsr == NULL && sPathLib == NULL ) { + sPathAll = NULL; + } + else if ( sPathUsr == NULL ) { + sPathAll = Extra_UtilStrsav( sPathLib ); + } + else if ( sPathLib == NULL ) { + sPathAll = Extra_UtilStrsav( sPathUsr ); + } + else { + sPathAll = ALLOC( char, strlen(sPathLib)+strlen(sPathUsr)+5 ); + sprintf( sPathAll, "%s:%s",sPathUsr, sPathLib ); + } + if ( sPathAll != NULL ) { + sRealName = Extra_UtilFileSearch(sFileName, sPathAll, "r"); + FREE( sPathAll ); + } + } + if (sRealName == NULL) { + sRealName = Extra_UtilTildeExpand(sFileName); + } + if ((pFile = fopen(sRealName, sMode)) == NULL) { + if (! silent) { + perror(sRealName); + } + } + } + if ( pFileNameReal ) + *pFileNameReal = sRealName; + else + FREE(sRealName); + + return pFile; +} + +/**Function************************************************************* + + Synopsis [Frees the previously allocated argv array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdFreeArgv( int argc, char **argv ) +{ + int i; + for ( i = 0; i < argc; i++ ) + FREE( argv[i] ); + FREE( argv ); +} + +/**Function************************************************************* + + Synopsis [Frees the previously allocated command.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdCommandFree( Abc_Command * pCommand ) +{ + free( pCommand->sGroup ); + free( pCommand->sName ); + free( pCommand ); +} + + +/**Function************************************************************* + + Synopsis [Prints commands alphabetically by group.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdCommandPrint( Abc_Frame_t * pAbc, bool fPrintAll ) +{ + char *key, *value; + st_generator * gen; + Abc_Command ** ppCommands; + Abc_Command * pCommands; + int nCommands, i; + char * sGroupCur; + int LenghtMax, nColumns, iCom = 0; + + // put all commands into one array + nCommands = st_count( pAbc->tCommands ); + ppCommands = ALLOC( Abc_Command *, nCommands ); + i = 0; + st_foreach_item( pAbc->tCommands, gen, &key, &value ) + { + pCommands = (Abc_Command *)value; + if ( fPrintAll || pCommands->sName[0] != '_' ) + ppCommands[i++] = pCommands; + } + nCommands = i; + + // sort command by group and then by name, alphabetically + qsort( (void *)ppCommands, nCommands, sizeof(Abc_Command *), + (int (*)(const void *, const void *)) CmdCommandPrintCompare ); + assert( CmdCommandPrintCompare( ppCommands, ppCommands + nCommands - 1 ) <= 0 ); + + // get the longest command name + LenghtMax = 0; + for ( i = 0; i < nCommands; i++ ) + if ( LenghtMax < (int)strlen(ppCommands[i]->sName) ) + LenghtMax = (int)strlen(ppCommands[i]->sName); + // get the number of columns + nColumns = 79 / (LenghtMax + 2); + + // print the starting message + fprintf( pAbc->Out, " Welcome to ABC!" ); + + // print the command by group + sGroupCur = NULL; + for ( i = 0; i < nCommands; i++ ) + if ( sGroupCur && strcmp( sGroupCur, ppCommands[i]->sGroup ) == 0 ) + { // this command belongs to the same group as the previous one + if ( iCom++ % nColumns == 0 ) + fprintf( pAbc->Out, "\n" ); + // print this command + fprintf( pAbc->Out, " %-*s", LenghtMax, ppCommands[i]->sName ); + } + else + { // this command starts the new group of commands + // start the new group + fprintf( pAbc->Out, "\n" ); + fprintf( pAbc->Out, "\n" ); + fprintf( pAbc->Out, "%s commands:\n", ppCommands[i]->sGroup ); + // print this command + fprintf( pAbc->Out, " %-*s", LenghtMax, ppCommands[i]->sName ); + // remember current command group + sGroupCur = ppCommands[i]->sGroup; + // reset the command counter + iCom = 1; + } + fprintf( pAbc->Out, "\n" ); + FREE( ppCommands ); +} + +/**Function************************************************************* + + Synopsis [Comparision function used for sorting commands.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 ) +{ + Abc_Command * pC1 = *ppC1; + Abc_Command * pC2 = *ppC2; + int RetValue; + + RetValue = strcmp( pC1->sGroup, pC2->sGroup ); + if ( RetValue < 0 ) + return -1; + if ( RetValue > 0 ) + return 1; + // the command belong to the same group + + // put commands with "_" at the end of the list + if ( pC1->sName[0] != '_' && pC2->sName[0] == '_' ) + return -1; + if ( pC1->sName[0] == '_' && pC2->sName[0] != '_' ) + return 1; + + RetValue = strcmp( pC1->sName, pC2->sName ); + if ( RetValue < 0 ) + return -1; + if ( RetValue > 0 ) + return 1; + // should not be two indentical commands + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Comparision function used for sorting commands.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CmdNamePrintCompare( char ** ppC1, char ** ppC2 ) +{ + return strcmp( *ppC1, *ppC2 ); +} + +/**Function************************************************************* + + Synopsis [Comparision function used for sorting commands.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CmdPrintTable( st_table * tTable, int fAliases ) +{ + st_generator * gen; + char ** ppNames; + char * key, * value; + int nNames, i; + + // collect keys in the array + ppNames = ALLOC( char *, st_count(tTable) ); + nNames = 0; + st_foreach_item( tTable, gen, &key, &value ) + ppNames[nNames++] = key; + + // sort array by name + qsort( (void *)ppNames, nNames, sizeof(char *), + (int (*)(const void *, const void *))CmdNamePrintCompare ); + + // print in this order + for ( i = 0; i < nNames; i++ ) + { + st_lookup( tTable, ppNames[i], &value ); + if ( fAliases ) + CmdCommandAliasPrint( Abc_FrameGetGlobalFrame(), (Abc_Alias *)value ); + else + fprintf( stdout, "%-15s %-15s\n", ppNames[i], value ); + } + free( ppNames ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/cmd/module.make b/abc70930/src/base/cmd/module.make new file mode 100644 index 00000000..1eca3f65 --- /dev/null +++ b/abc70930/src/base/cmd/module.make @@ -0,0 +1,6 @@ +SRC += src/base/cmd/cmd.c \ + src/base/cmd/cmdAlias.c \ + src/base/cmd/cmdApi.c \ + src/base/cmd/cmdFlag.c \ + src/base/cmd/cmdHist.c \ + src/base/cmd/cmdUtils.c diff --git a/abc70930/src/base/io/io.c b/abc70930/src/base/io/io.c new file mode 100644 index 00000000..7a5e4a5d --- /dev/null +++ b/abc70930/src/base/io/io.c @@ -0,0 +1,1954 @@ +/**CFile**************************************************************** + + FileName [io.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Command file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: io.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "mainInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int IoCommandRead ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadAiger ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadBench ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadDsd ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadEdif ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadInit ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadPla ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadTruth ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadVer ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandReadVerLib ( Abc_Frame_t * pAbc, int argc, char **argv ); + +static int IoCommandWrite ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteHie ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteAiger ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteBench ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteCnf ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteDot ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteGml ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteList ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWritePla ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ); +static int IoCommandWriteVerLib ( Abc_Frame_t * pAbc, int argc, char **argv ); + +extern int glo_fMapped; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_Init( Abc_Frame_t * pAbc ) +{ + Cmd_CommandAdd( pAbc, "I/O", "read", IoCommandRead, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_aiger", IoCommandReadAiger, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_baf", IoCommandReadBaf, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_blif", IoCommandReadBlif, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_blif_mv", IoCommandReadBlifMv, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_bench", IoCommandReadBench, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_dsd", IoCommandReadDsd, 1 ); +// Cmd_CommandAdd( pAbc, "I/O", "read_edif", IoCommandReadEdif, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_eqn", IoCommandReadEqn, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_init", IoCommandReadInit, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_pla", IoCommandReadPla, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_truth", IoCommandReadTruth, 1 ); + Cmd_CommandAdd( pAbc, "I/O", "read_verilog", IoCommandReadVerilog, 1 ); +// Cmd_CommandAdd( pAbc, "I/O", "read_ver", IoCommandReadVer, 1 ); +// Cmd_CommandAdd( pAbc, "I/O", "read_verlib", IoCommandReadVerLib, 0 ); + + Cmd_CommandAdd( pAbc, "I/O", "write", IoCommandWrite, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_hie", IoCommandWriteHie, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_aiger", IoCommandWriteAiger, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_baf", IoCommandWriteBaf, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_blif", IoCommandWriteBlif, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_blif_mv", IoCommandWriteBlifMv, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_bench", IoCommandWriteBench, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_cellnet", IoCommandWriteCellNet, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_counter", IoCommandWriteCounter, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_cnf", IoCommandWriteCnf, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_dot", IoCommandWriteDot, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_eqn", IoCommandWriteEqn, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_gml", IoCommandWriteGml, 0 ); +// Cmd_CommandAdd( pAbc, "I/O", "write_list", IoCommandWriteList, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_pla", IoCommandWritePla, 0 ); + Cmd_CommandAdd( pAbc, "I/O", "write_verilog", IoCommandWriteVerilog, 0 ); +// Cmd_CommandAdd( pAbc, "I/O", "write_verlib", IoCommandWriteVerLib, 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_End() +{ +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + glo_fMapped = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "mch" ) ) != EOF ) + { + switch ( c ) + { + case 'm': + glo_fMapped ^= 1; + break; + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, Io_ReadFileType(pFileName), fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read [-mch] \n" ); + fprintf( pAbc->Err, "\t replaces the current network by the network read from \n" ); + fprintf( pAbc->Err, "\t by calling the parser that matches the extension of \n" ); + fprintf( pAbc->Err, "\t (to read a hierarchical design, use \"read_hie\")\n" ); + fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadAiger( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_AIGER, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_aiger [-ch] \n" ); + fprintf( pAbc->Err, "\t read the network in the AIGER format (http://fmv.jku.at/aiger)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_BAF, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_baf [-ch] \n" ); + fprintf( pAbc->Err, "\t read the network in Binary Aig Format (BAF)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fReadAsAig; + int fCheck; + int c; + extern Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck ); + + fCheck = 1; + fReadAsAig = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ach" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fReadAsAig ^= 1; + break; + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + if ( fReadAsAig ) + pNtk = Io_ReadBlifAsAig( pFileName, fCheck ); + else +// pNtk = Io_Read( pFileName, IO_FILE_BLIF, fCheck ); + { + Abc_Ntk_t * pTemp; + pNtk = Io_ReadBlif( pFileName, fCheck ); + pNtk = Abc_NtkToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + } + + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_blif [-ach] \n" ); + fprintf( pAbc->Err, "\t read the network in binary BLIF format\n" ); + fprintf( pAbc->Err, "\t-a : toggle creating AIG while reading the file [default = %s]\n", fReadAsAig? "yes":"no" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBlifMv( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_BLIFMV, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_blif_mv [-ch] \n" ); + fprintf( pAbc->Err, "\t read the network in BLIF-MV format\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_BENCH, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_bench [-ch] \n" ); + fprintf( pAbc->Err, "\t read the network in BENCH format\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pString; + int fCheck; + int c; + extern Abc_Ntk_t * Io_ReadDsd( char * pFormula ); + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pString = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_ReadDsd( pString ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_dsd [-h] \n" ); + fprintf( pAbc->Err, "\t parses a formula representing DSD of a function\n" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tformula : the formula representing disjoint-support decomposition (DSD)\n" ); + fprintf( pAbc->Err, "\t Example of a formula: !(a*(b+CA(!d,e*f,c))*79B3(g,h,i,k))\n" ); + fprintf( pAbc->Err, "\t where \'!\' is an INV, \'*\' is an AND, \'+\' is an XOR, \n" ); + fprintf( pAbc->Err, "\t CA and 79B3 are hexadecimal representations of truth tables\n" ); + fprintf( pAbc->Err, "\t (in this case CA=11001010 is truth table of MUX(Data0,Data1,Ctrl))\n" ); + fprintf( pAbc->Err, "\t The lower chars (a,b,c,etc) are reserved for elementary variables.\n" ); + fprintf( pAbc->Err, "\t The upper chars (A,B,C,etc) are reserved for hexadecimal digits.\n" ); + fprintf( pAbc->Err, "\t No spaces are allowed in formulas. In parantheses, LSB goes first.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_EDIF, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_edif [-ch] \n" ); + fprintf( pAbc->Err, "\t read the network in EDIF (works only for ISCAS benchmarks)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_EQN, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_eqn [-ch] \n" ); + fprintf( pAbc->Err, "\t read the network in equation format\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadInit( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + extern void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Abc_NtkDup( pNtk ); + Io_ReadBenchInit( pNtk, pFileName ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_init [-h] \n" ); + fprintf( pAbc->Err, "\t reads initial state of the network in BENCH format\n" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_PLA, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_pla [-ch] \n" ); + fprintf( pAbc->Err, "\t read the network in PLA\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pSopCover; + int fHex; + int c; + + fHex = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF ) + { + switch ( c ) + { + case 'x': + fHex ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // convert truth table to SOP + if ( fHex ) + pSopCover = Abc_SopFromTruthHex(argv[globalUtilOptind]); + else + pSopCover = Abc_SopFromTruthBin(argv[globalUtilOptind]); + if ( pSopCover == NULL ) + { + fprintf( pAbc->Err, "Reading truth table has failed.\n" ); + return 1; + } + + pNtk = Abc_NtkCreateWithNode( pSopCover ); + free( pSopCover ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Deriving the network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_truth [-xh] \n" ); + fprintf( pAbc->Err, "\t creates network with node having given truth table\n" ); + fprintf( pAbc->Err, "\t-x : toggles between bin and hex representation [default = %s]\n", fHex? "hex":"bin" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\ttruth : truth table with most signficant bit first (e.g. 1000 for AND(a,b))\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int fCheck; + int c; + + fCheck = 1; + glo_fMapped = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "mch" ) ) != EOF ) + { + switch ( c ) + { + case 'm': + glo_fMapped ^= 1; + break; + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // read the file using the corresponding file reader + pNtk = Io_Read( pFileName, IO_FILE_VERILOG, fCheck ); + if ( pNtk == NULL ) + return 1; + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_verilog [-mch] \n" ); + fprintf( pAbc->Err, "\t read the network in Verilog (IWLS 2002/2005 subset)\n" ); + fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadVer( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkNew; + Abc_Lib_t * pDesign; + char * pFileName; + FILE * pFile; + int fCheck; + int c; + extern Abc_Ntk_t * Abc_LibDeriveAig( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib ); + extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); + + printf( "Stand-alone structural Verilog reader is available as command \"read_verilog\".\n" ); + return 0; + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + pFileName = argv[globalUtilOptind]; + if ( (pFile = fopen( pFileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". ", pFileName ); + if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) + fprintf( pAbc->Err, "Did you mean \"%s\"?", pFileName ); + fprintf( pAbc->Err, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pDesign = Ver_ParseFile( pFileName, Abc_FrameReadLibVer(), fCheck, 1 ); + if ( pDesign == NULL ) + { + fprintf( pAbc->Err, "Reading network from the verilog file has failed.\n" ); + return 1; + } + + // derive root design + pNtk = Abc_LibDeriveRoot( pDesign ); + Abc_LibFree( pDesign, NULL ); + if ( pNtk == NULL ) + { + fprintf( pAbc->Err, "Deriving root module has failed.\n" ); + return 1; + } + + // derive the AIG network from this design + pNtkNew = Abc_LibDeriveAig( pNtk, Abc_FrameReadLibVer() ); + Abc_NtkDelete( pNtk ); + if ( pNtkNew == NULL ) + { + fprintf( pAbc->Err, "Converting root module to AIG has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_ver [-ch] \n" ); + fprintf( pAbc->Err, "\t read a network in structural verilog (using current library)\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandReadVerLib( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Lib_t * pLibrary; + char * pFileName; + FILE * pFile; + int fCheck; + int c; + extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); + + fCheck = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCheck ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + pFileName = argv[globalUtilOptind]; + if ( (pFile = fopen( pFileName, "r" )) == NULL ) + { + fprintf( pAbc->Err, "Cannot open input file \"%s\". ", pFileName ); + if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) + fprintf( pAbc->Err, "Did you mean \"%s\"?", pFileName ); + fprintf( pAbc->Err, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pLibrary = Ver_ParseFile( pFileName, NULL, fCheck, 0 ); + if ( pLibrary == NULL ) + { + fprintf( pAbc->Err, "Reading library from the verilog file has failed.\n" ); + return 1; + } + printf( "The library contains %d gates.\n", st_count(pLibrary->tModules) ); + // free old library + if ( Abc_FrameReadLibVer() ) + Abc_LibFree( Abc_FrameReadLibVer(), NULL ); + // read new library + Abc_FrameSetLibVer( pLibrary ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: read_verlib [-ch] \n" ); + fprintf( pAbc->Err, "\t read a gate library in structural verilog\n" ); + fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); + fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWrite( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write [-h] \n" ); + fprintf( pAbc->Err, "\t writes the current network into by calling\n" ); + fprintf( pAbc->Err, "\t the writer that matches the extension of \n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteHie( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pBaseName, * pFileName; + int c; + + glo_fMapped = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) + { + switch ( c ) + { + case 'm': + glo_fMapped ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 2 ) + goto usage; + // get the output file name + pBaseName = argv[globalUtilOptind]; + pFileName = argv[globalUtilOptind+1]; + // call the corresponding file writer +// Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) ); + Io_WriteHie( pAbc->pNtkCur, pBaseName, pFileName ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_hie [-h] \n" ); + fprintf( pAbc->Err, "\t writes the current network into by calling\n" ); + fprintf( pAbc->Err, "\t the hierarchical writer that matches the extension of \n" ); + fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog for [default = %s]\n", glo_fMapped? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\torig : the name of the original file with the hierarchical design\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteAiger( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int fWriteSymbols; + int c; + + fWriteSymbols = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fWriteSymbols ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + if ( fWriteSymbols ) + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_AIGER ); + else + { + if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) + { + fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); + return 1; + } + Io_WriteAiger( pAbc->pNtkCur, pFileName, 0 ); + } + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_aiger [-sh] \n" ); + fprintf( pAbc->Err, "\t write the network in the AIGER format (http://fmv.jku.at/aiger)\n" ); + fprintf( pAbc->Err, "\t-s : toggle saving I/O names [default = %s]\n", fWriteSymbols? "yes" : "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .aig)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBaf( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BAF ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_baf [-h] \n" ); + fprintf( pAbc->Err, "\t write the network into a BLIF file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .baf)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIF ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_blif [-h] \n" ); + fprintf( pAbc->Err, "\t write the network into a BLIF file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .blif)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBlifMv( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIFMV ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_blif_mv [-h] \n" ); + fprintf( pAbc->Err, "\t write the network into a BLIF-MV file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .mv)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int fUseLuts; + int c; + + fUseLuts = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLuts ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + if ( !fUseLuts ) + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BENCH ); + else + { + Abc_Ntk_t * pNtkTemp; + pNtkTemp = Abc_NtkToNetlist( pAbc->pNtkCur ); + Abc_NtkToAig( pNtkTemp ); + Io_WriteBenchLut( pNtkTemp, pFileName ); + Abc_NtkDelete( pNtkTemp ); + } + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_bench [-lh] \n" ); + fprintf( pAbc->Err, "\t write the network in BENCH format\n" ); + fprintf( pAbc->Err, "\t-l : toggle using LUTs in the output [default = %s]\n", fUseLuts? "yes" : "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .bench)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + extern void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName ); + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + pNtk = pAbc->pNtkCur; + if ( pNtk == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + if ( !Abc_NtkIsLogic(pNtk) ) + { + fprintf( pAbc->Out, "The network should be a logic network (if it an AIG, use command \"logic\")\n" ); + return 0; + } + Io_WriteCellNet( pNtk, pFileName ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_cellnet [-h] \n" ); + fprintf( pAbc->Err, "\t write the network is the cellnet format\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + int fAllPrimes; + int fNewAlgo; + extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName ); + + fNewAlgo = 1; + fAllPrimes = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fNewAlgo ^= 1; + break; + case 'p': + fAllPrimes ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // check if the feature will be used + if ( Abc_NtkIsStrash(pAbc->pNtkCur) && fAllPrimes ) + { + fAllPrimes = 0; + printf( "Warning: Selected option to write all primes has no effect when deriving CNF from AIG.\n" ); + } + // call the corresponding file writer + if ( fNewAlgo ) + Abc_NtkDarToCnf( pAbc->pNtkCur, pFileName ); + else if ( fAllPrimes ) + Io_WriteCnf( pAbc->pNtkCur, pFileName, 1 ); + else + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_CNF ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_cnf [-nph] \n" ); + fprintf( pAbc->Err, "\t write the miter cone into a CNF file\n" ); + fprintf( pAbc->Err, "\t-n : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes" : "no" ); + fprintf( pAbc->Err, "\t-p : toggle using all primes to enhance implicativity [default = %s]\n", fAllPrimes? "yes" : "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_DOT ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_dot [-h] \n" ); + fprintf( pAbc->Err, "\t write the current network into a DOT file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + int fNames; + + fNames = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fNames ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + pNtk = pAbc->pNtkCur; + if ( pNtk == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + // get the input file name + pFileName = argv[globalUtilOptind]; + + if ( pNtk->pModel == NULL ) + { + fprintf( pAbc->Out, "Counter-example is not available.\n" ); + return 0; + } + + // write the counter-example into the file + { + Abc_Obj_t * pObj; + FILE * pFile = fopen( pFileName, "w" ); + int i; + if ( pFile == NULL ) + { + fprintf( stdout, "IoCommandWriteCounter(): Cannot open the output file \"%s\".\n", pFileName ); + return 1; + } + if ( fNames ) + { + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "%s=%c ", Abc_ObjName(pObj), '0'+(pNtk->pModel[i]==1) ); + } + else + { + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "%c", '0'+(pNtk->pModel[i]==1) ); + } + fprintf( pFile, "\n" ); + fclose( pFile ); + } + + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_counter [-nh] \n" ); + fprintf( pAbc->Err, "\t writes the counter-example derived by \"prove\" or \"sat\"\n" ); + fprintf( pAbc->Err, "\t the file contains values for each PI in the natural order\n" ); + fprintf( pAbc->Err, "\t-n : write input names into the file [default = %s]\n", fNames? "yes": "no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_EQN ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_eqn [-h] \n" ); + fprintf( pAbc->Err, "\t write the current network in the equation format\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_GML ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_gml [-h] \n" ); + fprintf( pAbc->Err, "\t write network using graph representation formal GML\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteList( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int fUseHost; + int c; + + printf( "This command currently does not work.\n" ); + return 0; + + fUseHost = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fUseHost ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + if ( pAbc->pNtkCur == NULL ) + { + fprintf( pAbc->Out, "Empty network.\n" ); + return 0; + } +/* + if ( !Abc_NtkIsSeq(pAbc->pNtkCur) ) + { + fprintf( stdout, "IoCommandWriteList(): Can write adjacency list for sequential AIGs only.\n" ); + return 0; + } +*/ + // get the input file name + pFileName = argv[globalUtilOptind]; + // write the file + Io_WriteList( pAbc->pNtkCur, pFileName, fUseHost ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_list [-nh] \n" ); + fprintf( pAbc->Err, "\t write network using graph representation formal GML\n" ); + fprintf( pAbc->Err, "\t-n : toggle writing host node [default = %s]\n", fUseHost? "yes":"no" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_PLA ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_pla [-h] \n" ); + fprintf( pAbc->Err, "\t write the collapsed network into a PLA file\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + char * pFileName; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the corresponding file writer + Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_verilog [-h] \n" ); + fprintf( pAbc->Err, "\t write the current network in Verilog format\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int IoCommandWriteVerLib( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + Abc_Lib_t * pLibrary; + char * pFileName; + int c; + extern void Io_WriteVerilogLibrary( Abc_Lib_t * pLibrary, char * pFileName ); + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + // get the input file name + pFileName = argv[globalUtilOptind]; + // derive the netlist + pLibrary = Abc_FrameReadLibVer(); + if ( pLibrary == NULL ) + { + fprintf( pAbc->Out, "Verilog library is not specified.\n" ); + return 0; + } +// Io_WriteVerilogLibrary( pLibrary, pFileName ); + return 0; + +usage: + fprintf( pAbc->Err, "usage: write_verlib [-h] \n" ); + fprintf( pAbc->Err, "\t write the current verilog library\n" ); + fprintf( pAbc->Err, "\t-h : print the help massage\n" ); + fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/io.h b/abc70930/src/base/io/io.h new file mode 100644 index 00000000..45762b77 --- /dev/null +++ b/abc70930/src/base/io/io.h @@ -0,0 +1,146 @@ +/**CFile**************************************************************** + + FileName [io.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: io.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __IO_H__ +#define __IO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// network functionality +typedef enum { + IO_FILE_NONE = 0, + IO_FILE_AIGER, + IO_FILE_BAF, + IO_FILE_BLIF, + IO_FILE_BLIFMV, + IO_FILE_BENCH, + IO_FILE_CNF, + IO_FILE_DOT, + IO_FILE_EDIF, + IO_FILE_EQN, + IO_FILE_GML, + IO_FILE_LIST, + IO_FILE_PLA, + IO_FILE_VERILOG, + IO_FILE_UNKNOWN +} Io_FileType_t; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IO_WRITE_LINE_LENGTH 78 // the output line length + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== abcReadAiger.c ==========================================================*/ +extern Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ); +/*=== abcReadBaf.c ============================================================*/ +extern Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck ); +/*=== abcReadBlif.c ===========================================================*/ +extern Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ); +/*=== abcReadBlifMv.c =========================================================*/ +extern Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck ); +/*=== abcReadBench.c ==========================================================*/ +extern Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ); +/*=== abcReadEdif.c ===========================================================*/ +extern Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ); +/*=== abcReadEqn.c ============================================================*/ +extern Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ); +/*=== abcReadPla.c ============================================================*/ +extern Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck ); +/*=== abcReadVerilog.c ========================================================*/ +extern Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ); +/*=== abcWriteAiger.c =========================================================*/ +extern void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols ); +/*=== abcWriteBaf.c ===========================================================*/ +extern void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteBlif.c ==========================================================*/ +extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); +extern void Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); +extern void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ); +/*=== abcWriteBlifMv.c ==========================================================*/ +extern void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteBench.c =========================================================*/ +extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); +extern int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteCnf.c ===========================================================*/ +extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName, int fAllPrimes ); +/*=== abcWriteDot.c ===========================================================*/ +extern void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ); +extern void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); +extern void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); +/*=== abcWriteEqn.c ===========================================================*/ +extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteGml.c ===========================================================*/ +extern void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ); +/*=== abcWriteList.c ==========================================================*/ +extern void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ); +/*=== abcWritePla.c ===========================================================*/ +extern int Io_WritePla( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcWriteVerilog.c =======================================================*/ +extern void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * FileName ); +/*=== abcUtil.c ===============================================================*/ +extern Io_FileType_t Io_ReadFileType( char * pFileName ); +extern Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck ); +extern Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck ); +extern void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ); +extern void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName ); +extern Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName ); +extern Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ); +extern Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv ); +extern Abc_Obj_t * Io_ReadCreateResetMux( Abc_Ntk_t * pNtk, char * pResetLO, char * pDataLI, int fBlifMv ); +extern Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs ); +extern Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, bool fConst1 ); +extern Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ); +extern Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ); +extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ); + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/io/ioInt.h b/abc70930/src/base/io/ioInt.h new file mode 100644 index 00000000..3daf3c75 --- /dev/null +++ b/abc70930/src/base/io/ioInt.h @@ -0,0 +1,49 @@ +/**CFile**************************************************************** + + FileName [ioInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __IO_INT_H__ +#define __IO_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/io/ioReadAiger.c b/abc70930/src/base/io/ioReadAiger.c new file mode 100644 index 00000000..d3c4c878 --- /dev/null +++ b/abc70930/src/base/io/ioReadAiger.c @@ -0,0 +1,310 @@ +/**CFile**************************************************************** + + FileName [ioReadAiger.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +unsigned Io_ReadAigerDecode( char ** ppPos ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) +{ + ProgressBar * pProgress; + FILE * pFile; + Vec_Ptr_t * vNodes, * vTerms; + Abc_Obj_t * pObj, * pNode0, * pNode1; + Abc_Ntk_t * pNtkNew; + int nTotal, nInputs, nOutputs, nLatches, nAnds, nFileSize, iTerm, nDigits, i; + char * pContents, * pDrivers, * pSymbols, * pCur, * pName, * pType; + unsigned uLit0, uLit1, uLit; + + // read the file into the buffer + nFileSize = Extra_FileSize( pFileName ); + pFile = fopen( pFileName, "rb" ); + pContents = ALLOC( char, nFileSize ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + + // check if the input file format is correct + if ( strncmp(pContents, "aig", 3) != 0 ) + { + fprintf( stdout, "Wrong input file format.\n" ); + return NULL; + } + + // allocate the empty AIG + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pName = Extra_FileNameGeneric( pFileName ); + pNtkNew->pName = Extra_UtilStrsav( pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pFileName ); + free( pName ); + + + // read the file type + pCur = pContents; while ( *pCur++ != ' ' ); + // read the number of objects + nTotal = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of inputs + nInputs = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of latches + nLatches = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of outputs + nOutputs = atoi( pCur ); while ( *pCur++ != ' ' ); + // read the number of nodes + nAnds = atoi( pCur ); while ( *pCur++ != '\n' ); + // check the parameters + if ( nTotal != nInputs + nLatches + nAnds ) + { + fprintf( stdout, "The paramters are wrong.\n" ); + return NULL; + } + + // prepare the array of nodes + vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); + Vec_PtrPush( vNodes, Abc_ObjNot( Abc_AigConst1(pNtkNew) ) ); + + // create the PIs + for ( i = 0; i < nInputs; i++ ) + { + pObj = Abc_NtkCreatePi(pNtkNew); + Vec_PtrPush( vNodes, pObj ); + } + // create the POs + for ( i = 0; i < nOutputs; i++ ) + { + pObj = Abc_NtkCreatePo(pNtkNew); + } + // create the latches + nDigits = Extra_Base10Log( nLatches ); + for ( i = 0; i < nLatches; i++ ) + { + pObj = Abc_NtkCreateLatch(pNtkNew); + Abc_LatchSetInit0( pObj ); + pNode0 = Abc_NtkCreateBi(pNtkNew); + pNode1 = Abc_NtkCreateBo(pNtkNew); + Abc_ObjAddFanin( pObj, pNode0 ); + Abc_ObjAddFanin( pNode1, pObj ); + Vec_PtrPush( vNodes, pNode1 ); + // assign names to latch and its input +// Abc_ObjAssignName( pObj, Abc_ObjNameDummy("_L", i, nDigits), NULL ); +// printf( "Creating latch %s with input %d and output %d.\n", Abc_ObjName(pObj), pNode0->Id, pNode1->Id ); + } + + // remember the beginning of latch/PO literals + pDrivers = pCur; + + // scroll to the beginning of the binary data + for ( i = 0; i < nLatches + nOutputs; ) + if ( *pCur++ == '\n' ) + i++; + + // create the AND gates + pProgress = Extra_ProgressBarStart( stdout, nAnds ); + for ( i = 0; i < nAnds; i++ ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + uLit = ((i + 1 + nInputs + nLatches) << 1); + uLit1 = uLit - Io_ReadAigerDecode( &pCur ); + uLit0 = uLit1 - Io_ReadAigerDecode( &pCur ); +// assert( uLit1 > uLit0 ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); + pNode1 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); + assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches ); + Vec_PtrPush( vNodes, Abc_AigAnd(pNtkNew->pManFunc, pNode0, pNode1) ); + } + Extra_ProgressBarStop( pProgress ); + + // remember the place where symbols begin + pSymbols = pCur; + + // read the latch driver literals + pCur = pDrivers; + Abc_NtkForEachLatchInput( pNtkNew, pObj, i ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Abc_ObjAddFanin( pObj, pNode0 ); + +// printf( "Adding input %d to latch input %d.\n", pNode0->Id, pObj->Id ); + + } + // read the PO driver literals + Abc_NtkForEachPo( pNtkNew, pObj, i ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Abc_ObjAddFanin( pObj, pNode0 ); + } + + // read the names if present + pCur = pSymbols; + if ( *pCur != 'c' ) + { + int Counter = 0; + while ( pCur < pContents + nFileSize && *pCur != 'c' ) + { + // get the terminal type + pType = pCur; + if ( *pCur == 'i' ) + vTerms = pNtkNew->vPis; + else if ( *pCur == 'l' ) + vTerms = pNtkNew->vBoxes; + else if ( *pCur == 'o' ) + vTerms = pNtkNew->vPos; + else + { + fprintf( stdout, "Wrong terminal type.\n" ); + return NULL; + } + // get the terminal number + iTerm = atoi( ++pCur ); while ( *pCur++ != ' ' ); + // get the node + if ( iTerm >= Vec_PtrSize(vTerms) ) + { + fprintf( stdout, "The number of terminal is out of bound.\n" ); + return NULL; + } + pObj = Vec_PtrEntry( vTerms, iTerm ); + if ( *pType == 'l' ) + pObj = Abc_ObjFanout0(pObj); + // assign the name + pName = pCur; while ( *pCur++ != '\n' ); + // assign this name + *(pCur-1) = 0; + Abc_ObjAssignName( pObj, pName, NULL ); + if ( *pType == 'l' ) + { + Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" ); + Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" ); + } + // mark the node as named + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); + } + + // assign the remaining names + Abc_NtkForEachPi( pNtkNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); + Counter++; + } + Abc_NtkForEachLatchOutput( pNtkNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); + Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" ); + Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" ); + Counter++; + } + Abc_NtkForEachPo( pNtkNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); + Counter++; + } + if ( Counter ) + printf( "Io_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter ); + } + else + { +// printf( "Io_ReadAiger(): I/O/register names are not given. Generating short names.\n" ); + Abc_NtkShortNames( pNtkNew ); + } + + // read the name of the model if given + if ( *pCur == 'c' ) + { + if ( !strncmp( pCur + 2, ".model", 6 ) ) + { + char * pTemp; + for ( pTemp = pCur + 9; *pTemp && *pTemp != '\n'; pTemp++ ); + *pTemp = 0; + free( pNtkNew->pName ); + pNtkNew->pName = Extra_UtilStrsav( pCur + 9 ); + } + } + + + // skipping the comments + free( pContents ); + Vec_PtrFree( vNodes ); + + // remove the extra nodes + Abc_AigCleanup( pNtkNew->pManFunc ); + + // check the result + if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) ) + { + printf( "Io_ReadAiger: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Extracts one unsigned AIG edge from the input buffer.] + + Description [This procedure is a slightly modified version of Armin Biere's + procedure "unsigned decode (FILE * file)". ] + + SideEffects [Updates the current reading position.] + + SeeAlso [] + +***********************************************************************/ +unsigned Io_ReadAigerDecode( char ** ppPos ) +{ + unsigned x = 0, i = 0; + unsigned char ch; + +// while ((ch = getnoneofch (file)) & 0x80) + while ((ch = *(*ppPos)++) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + + return x | (ch << (7 * i)); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBaf.c b/abc70930/src/base/io/ioReadBaf.c new file mode 100644 index 00000000..8dce54af --- /dev/null +++ b/abc70930/src/base/io/ioReadBaf.c @@ -0,0 +1,171 @@ +/**CFile**************************************************************** + + FileName [ioReadBaf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read AIG in the binary format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck ) +{ + ProgressBar * pProgress; + FILE * pFile; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pNode0, * pNode1; + Abc_Ntk_t * pNtkNew; + int nInputs, nOutputs, nLatches, nAnds, nFileSize, Num, i; + char * pContents, * pName, * pCur; + unsigned * pBufferNode; + + // read the file into the buffer + nFileSize = Extra_FileSize( pFileName ); + pFile = fopen( pFileName, "rb" ); + pContents = ALLOC( char, nFileSize ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + + // skip the comments (comment lines begin with '#' and end with '\n') + for ( pCur = pContents; *pCur == '#'; ) + while ( *pCur++ != '\n' ); + + // read the name + pName = pCur; while ( *pCur++ ); + // read the number of inputs + nInputs = atoi( pCur ); while ( *pCur++ ); + // read the number of outputs + nOutputs = atoi( pCur ); while ( *pCur++ ); + // read the number of latches + nLatches = atoi( pCur ); while ( *pCur++ ); + // read the number of nodes + nAnds = atoi( pCur ); while ( *pCur++ ); + + // allocate the empty AIG + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkNew->pName = Extra_UtilStrsav( pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pFileName ); + + // prepare the array of nodes + vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); + Vec_PtrPush( vNodes, Abc_AigConst1(pNtkNew) ); + + // create the PIs + for ( i = 0; i < nInputs; i++ ) + { + pObj = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); + Vec_PtrPush( vNodes, pObj ); + } + // create the POs + for ( i = 0; i < nOutputs; i++ ) + { + pObj = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); + } + // create the latches + for ( i = 0; i < nLatches; i++ ) + { + pObj = Abc_NtkCreateLatch(pNtkNew); + Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); + + pNode0 = Abc_NtkCreateBi(pNtkNew); + Abc_ObjAssignName( pNode0, pCur, NULL ); while ( *pCur++ ); + + pNode1 = Abc_NtkCreateBo(pNtkNew); + Abc_ObjAssignName( pNode1, pCur, NULL ); while ( *pCur++ ); + Vec_PtrPush( vNodes, pNode1 ); + + Abc_ObjAddFanin( pObj, pNode0 ); + Abc_ObjAddFanin( pNode1, pObj ); + } + + // get the pointer to the beginning of the node array + pBufferNode = (int *)(pContents + (nFileSize - (2 * nAnds + nOutputs + nLatches) * sizeof(int)) ); + // make sure we are at the place where the nodes begin + if ( pBufferNode != (int *)pCur ) + { + free( pContents ); + Vec_PtrFree( vNodes ); + Abc_NtkDelete( pNtkNew ); + printf( "Warning: Internal reader error.\n" ); + return NULL; + } + + // create the AND gates + pProgress = Extra_ProgressBarStart( stdout, nAnds ); + for ( i = 0; i < nAnds; i++ ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, pBufferNode[2*i+0] >> 1), pBufferNode[2*i+0] & 1 ); + pNode1 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, pBufferNode[2*i+1] >> 1), pBufferNode[2*i+1] & 1 ); + Vec_PtrPush( vNodes, Abc_AigAnd(pNtkNew->pManFunc, pNode0, pNode1) ); + } + Extra_ProgressBarStop( pProgress ); + + // read the POs + Abc_NtkForEachCo( pNtkNew, pObj, i ) + { + Num = pBufferNode[2*nAnds+i]; + if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) + { + Abc_ObjSetData( Abc_ObjFanout0(pObj), (void *)(Num & 3) ); + Num >>= 2; + } + pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, Num >> 1), Num & 1 ); + Abc_ObjAddFanin( pObj, pNode0 ); + } + free( pContents ); + Vec_PtrFree( vNodes ); + + // remove the extra nodes +// Abc_AigCleanup( pNtkNew->pManFunc ); + + // check the result + if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) ) + { + printf( "Io_ReadBaf: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; + +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBench.c b/abc70930/src/base/io/ioReadBench.c new file mode 100644 index 00000000..007147bc --- /dev/null +++ b/abc70930/src/base/io/ioReadBench.c @@ -0,0 +1,360 @@ +/**CFile**************************************************************** + + FileName [ioReadBench.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BENCH files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from a BENCH file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t,()=" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadBenchNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadBench: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode, * pNet; + Vec_Str_t * vString; + unsigned uTruth[8]; + char * pType, ** ppNames, * pString; + int iLine, nNames, nDigits, fLutsPresent = 0; + + // allocate the empty network + pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); + + // go through the lines of the file + vString = Vec_StrAlloc( 100 ); + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + if ( vTokens->nSize == 1 ) + { + printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + + // get the type of the line + if ( strncmp( vTokens->pArray[0], "INPUT", 5 ) == 0 ) + Io_ReadCreatePi( pNtk, vTokens->pArray[1] ); + else if ( strncmp( vTokens->pArray[0], "OUTPUT", 5 ) == 0 ) + Io_ReadCreatePo( pNtk, vTokens->pArray[1] ); + else + { + // get the node name and the node type + pType = vTokens->pArray[1]; + if ( strncmp(pType, "DFF", 3) == 0 ) // works for both DFF and DFFRSE + { + pNode = Io_ReadCreateLatch( pNtk, vTokens->pArray[2], vTokens->pArray[0] ); +// Abc_LatchSetInit0( pNode ); + if ( pType[3] == '0' ) + Abc_LatchSetInit0( pNode ); + else if ( pType[3] == '1' ) + Abc_LatchSetInit1( pNode ); + else + Abc_LatchSetInitDc( pNode ); + } + else if ( strcmp(pType, "LUT") == 0 ) + { + fLutsPresent = 1; + ppNames = (char **)vTokens->pArray + 3; + nNames = vTokens->nSize - 3; + // check the number of inputs + if ( nNames > 8 ) + { + printf( "%s: Currently cannot read truth tables with more than 8 inputs (%d).\n", Extra_FileReaderGetFileName(p), nNames ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + // get the hex string + pString = vTokens->pArray[2]; + if ( strncmp( pString, "0x", 2 ) ) + { + printf( "%s: The LUT signature (%s) does not look like a hexadecimal beginning with \"0x\".\n", Extra_FileReaderGetFileName(p), pString ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + pString += 2; + // pad the string with zero's if needed + nDigits = (1 << nNames) / 4; + if ( nDigits == 0 ) + nDigits = 1; + if ( strlen(pString) < (unsigned)nDigits ) + { + Vec_StrFill( vString, nDigits - strlen(pString), '0' ); + Vec_StrPrintStr( vString, pString ); + Vec_StrPush( vString, 0 ); + pString = Vec_StrArray( vString ); + } + // read the hex number from the string + if ( !Extra_ReadHexadecimal( uTruth, pString, nNames ) ) + { + printf( "%s: Reading hexadecimal number (%s) has failed.\n", Extra_FileReaderGetFileName(p), pString ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + // check if the node is a constant node + if ( Extra_TruthIsConst0(uTruth, nNames) ) + { + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, 0 ); + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 0\n" ) ); + } + else if ( Extra_TruthIsConst1(uTruth, nNames) ) + { + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, 0 ); + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 1\n" ) ); + } + else + { + // create the node + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, nNames ); + assert( nNames > 0 ); + if ( nNames > 1 ) + Abc_ObjSetData( pNode, Abc_SopCreateFromTruth(pNtk->pManFunc, nNames, uTruth) ); + else if ( pString[0] == '2' ) + Abc_ObjSetData( pNode, Abc_SopCreateBuf(pNtk->pManFunc) ); + else if ( pString[0] == '1' ) + Abc_ObjSetData( pNode, Abc_SopCreateInv(pNtk->pManFunc) ); + else + { + printf( "%s: Reading truth table (%s) of single-input node has failed.\n", Extra_FileReaderGetFileName(p), pString ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + } + else + { + // create a new node and add it to the network + ppNames = (char **)vTokens->pArray + 2; + nNames = vTokens->nSize - 2; + pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, nNames ); + // assign the cover + if ( strcmp(pType, "AND") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateAnd(pNtk->pManFunc, nNames, NULL) ); + else if ( strcmp(pType, "OR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateOr(pNtk->pManFunc, nNames, NULL) ); + else if ( strcmp(pType, "NAND") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateNand(pNtk->pManFunc, nNames) ); + else if ( strcmp(pType, "NOR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateNor(pNtk->pManFunc, nNames) ); + else if ( strcmp(pType, "XOR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateXor(pNtk->pManFunc, nNames) ); + else if ( strcmp(pType, "NXOR") == 0 || strcmp(pType, "XNOR") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateNxor(pNtk->pManFunc, nNames) ); + else if ( strncmp(pType, "BUF", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateBuf(pNtk->pManFunc) ); + else if ( strcmp(pType, "NOT") == 0 ) + Abc_ObjSetData( pNode, Abc_SopCreateInv(pNtk->pManFunc) ); + else if ( strncmp(pType, "MUX", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, "1-0 1\n-11 1\n") ); + else if ( strncmp(pType, "gnd", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 0\n" ) ); + else if ( strncmp(pType, "vdd", 3) == 0 ) + Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 1\n" ) ); + else + { + printf( "Io_ReadBenchNetwork(): Cannot determine gate type \"%s\" in line %d.\n", pType, Extra_FileReaderGetLineNumber(p, 0) ); + Vec_StrFree( vString ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + } + } + Extra_ProgressBarStop( pProgress ); + Vec_StrFree( vString ); + + // check if constant 0 is present + if ( (pNet = Abc_NtkFindNet( pNtk, "gnd" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + Io_ReadCreateConst( pNtk, "gnd", 0 ); + } + if ( (pNet = Abc_NtkFindNet( pNtk, "1" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + { + printf( "Io_ReadBenchNetwork(): Adding constant 0 fanin to non-driven net \"1\".\n" ); + Io_ReadCreateConst( pNtk, "1", 0 ); + } + } + // check if constant 1 is present + if ( (pNet = Abc_NtkFindNet( pNtk, "vdd" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + Io_ReadCreateConst( pNtk, "vdd", 1 ); + } + if ( (pNet = Abc_NtkFindNet( pNtk, "2" )) ) + { + if ( Abc_ObjFaninNum(pNet) == 0 ) + { + printf( "Io_ReadBenchNetwork(): Adding constant 1 fanin to non-driven net \"2\".\n" ); + Io_ReadCreateConst( pNtk, "2", 1 ); + } + } + + Abc_NtkFinalizeRead( pNtk ); + + // if LUTs are present, collapse the truth tables into cubes + if ( fLutsPresent ) + { + if ( !Abc_NtkToBdd(pNtk) ) + { + printf( "Io_ReadBenchNetwork(): Converting to BDD has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + if ( !Abc_NtkToSop(pNtk, 0) ) + { + printf( "Io_ReadBenchNetwork(): Converting to SOP has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + return pNtk; +} + + +/**Function************************************************************* + + Synopsis [Reads initial state in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName ) +{ + char pBuffer[1000]; + FILE * pFile; + char * pToken; + Abc_Obj_t * pObj; + int Num; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Io_ReadBenchInit(): Failed to open file \"%s\".\n", pFileName ); + return; + } + while ( fgets( pBuffer, 999, pFile ) ) + { + pToken = strtok( pBuffer, " \n\t\r" ); + // find the latch output + Num = Nm_ManFindIdByName( pNtk->pManName, pToken, ABC_OBJ_BO ); + if ( Num < 0 ) + { + printf( "Io_ReadBenchInit(): Cannot find register with output %s.\n", pToken ); + continue; + } + pObj = Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); + if ( !Abc_ObjIsLatch(pObj) ) + { + printf( "Io_ReadBenchInit(): The signal is not a register output %s.\n", pToken ); + continue; + } + // assign the new init state + pToken = strtok( NULL, " \n\t\r" ); + if ( pToken[0] == '0' ) + Abc_LatchSetInit0( pObj ); + else if ( pToken[0] == '1' ) + Abc_LatchSetInit1( pObj ); + else if ( pToken[0] == '2' ) + Abc_LatchSetInitDc( pObj ); + else + { + printf( "Io_ReadBenchInit(): The signal %s has unknown initial value (%s).\n", + Abc_ObjName(Abc_ObjFanout0(pObj)), pToken ); + continue; + } + } + fclose( pFile ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadBlif.c b/abc70930/src/base/io/ioReadBlif.c new file mode 100644 index 00000000..d0750178 --- /dev/null +++ b/abc70930/src/base/io/ioReadBlif.c @@ -0,0 +1,1105 @@ +/**CFile**************************************************************** + + FileName [ioReadBlif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BLIF files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Io_ReadBlif_t_ Io_ReadBlif_t; // all reading info +struct Io_ReadBlif_t_ +{ + // general info about file + char * pFileName; // the name of the file + Extra_FileReader_t * pReader; // the input file reader + // current processing info + Abc_Ntk_t * pNtkMaster; // the primary network + Abc_Ntk_t * pNtkCur; // the primary network + int LineCur; // the line currently parsed + // temporary storage for tokens + Vec_Ptr_t * vTokens; // the current tokens + Vec_Ptr_t * vNewTokens; // the temporary storage for the tokens + Vec_Str_t * vCubes; // the temporary storage for the tokens + // the error message + FILE * Output; // the output stream + char sError[1000]; // the error string generated during parsing + int fError; // set to 1 when error occurs +}; + +static Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ); +static void Io_ReadBlifFree( Io_ReadBlif_t * p ); +static void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ); +static Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ); +static char * Io_ReadBlifCleanName( char * pName ); + +static Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ); +static Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ); +static int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkAsserts( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ); +static int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); +static int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the (hierarchical) network from the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) +{ + Io_ReadBlif_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Io_ReadBlifFile( pFileName ); + if ( p == NULL ) + return NULL; + + // read the hierarchical network + pNtk = Io_ReadBlifNetwork( p ); + if ( pNtk == NULL ) + { + Io_ReadBlifFree( p ); + return NULL; + } + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + Abc_NtkTimeInitialize( pNtk ); + Io_ReadBlifFree( p ); + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadBlif: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Iteratively reads several networks in the hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) +{ + Abc_Ntk_t * pNtk, * pNtkMaster; + + // read the name of the master network + p->vTokens = Io_ReadBlifGetTokens(p); + if ( p->vTokens == NULL || strcmp( p->vTokens->pArray[0], ".model" ) ) + { + p->LineCur = 0; + sprintf( p->sError, "Wrong input file format." ); + Io_ReadBlifPrintErrorMessage( p ); + return NULL; + } + + // read networks (with EXDC) + pNtkMaster = NULL; + while ( p->vTokens ) + { + // read the network and its EXDC if present + pNtk = Io_ReadBlifNetworkOne( p ); + if ( pNtk == NULL ) + break; + if ( p->vTokens && strcmp(p->vTokens->pArray[0], ".exdc") == 0 ) + { + pNtk->pExdc = Io_ReadBlifNetworkOne( p ); + Abc_NtkFinalizeRead( pNtk->pExdc ); + if ( pNtk->pExdc == NULL ) + break; + } + // add this network as part of the hierarchy + if ( pNtkMaster == NULL ) // no master network so far + { + p->pNtkMaster = pNtkMaster = pNtk; + continue; + } +/* + // make sure hierarchy does not have the network with this name + if ( pNtkMaster->tName2Model && stmm_is_member( pNtkMaster->tName2Model, pNtk->pName ) ) + { + p->LineCur = 0; + sprintf( p->sError, "Model %s is multiply defined in the file.", pNtk->pName ); + Io_ReadBlifPrintErrorMessage( p ); + Abc_NtkDelete( pNtk ); + Abc_NtkDelete( pNtkMaster ); + pNtkMaster = NULL; + return NULL; + } + // add the network to the hierarchy + if ( pNtkMaster->tName2Model == NULL ) + pNtkMaster->tName2Model = stmm_init_table(strcmp, stmm_strhash); + stmm_insert( pNtkMaster->tName2Model, pNtk->pName, (char *)pNtk ); +*/ + } +/* + // if there is a hierarchy, connect the boxes + if ( pNtkMaster && pNtkMaster->tName2Model ) + { + if ( Io_ReadBlifNetworkConnectBoxes( p, pNtkMaster ) ) + { + Abc_NtkDelete( pNtkMaster ); + return NULL; + } + } + else +*/ + if ( !p->fError ) + Abc_NtkFinalizeRead( pNtkMaster ); + // return the master network + return pNtkMaster; +} + +/**Function************************************************************* + + Synopsis [Reads one (main or exdc) network from the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ) +{ + ProgressBar * pProgress; + Abc_Ntk_t * pNtk; + char * pDirective; + int iLine, fTokensReady, fStatus; + + // make sure the tokens are present + assert( p->vTokens != NULL ); + + // create the new network + p->pNtkCur = pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); + // read the model name + if ( strcmp( p->vTokens->pArray[0], ".model" ) == 0 ) + pNtk->pName = Extra_UtilStrsav( p->vTokens->pArray[1] ); + else if ( strcmp( p->vTokens->pArray[0], ".exdc" ) != 0 ) + { + printf( "%s: File parsing skipped after line %d (\"%s\").\n", p->pFileName, + Extra_FileReaderGetLineNumber(p->pReader, 0), p->vTokens->pArray[0] ); + Abc_NtkDelete(pNtk); + p->pNtkCur = NULL; + return NULL; + } + + // read the inputs/outputs + if ( p->pNtkMaster == NULL ) + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) ); + fTokensReady = fStatus = 0; + for ( iLine = 0; fTokensReady || (p->vTokens = Io_ReadBlifGetTokens(p)); iLine++ ) + { + if ( p->pNtkMaster == NULL && iLine % 1000 == 0 ) + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL ); + + // consider different line types + fTokensReady = 0; + pDirective = p->vTokens->pArray[0]; + if ( !strcmp( pDirective, ".names" ) ) + { fStatus = Io_ReadBlifNetworkNames( p, &p->vTokens ); fTokensReady = 1; } + else if ( !strcmp( pDirective, ".gate" ) ) + fStatus = Io_ReadBlifNetworkGate( p, p->vTokens ); + else if ( !strcmp( pDirective, ".latch" ) ) + fStatus = Io_ReadBlifNetworkLatch( p, p->vTokens ); + else if ( !strcmp( pDirective, ".inputs" ) ) + fStatus = Io_ReadBlifNetworkInputs( p, p->vTokens ); + else if ( !strcmp( pDirective, ".outputs" ) ) + fStatus = Io_ReadBlifNetworkOutputs( p, p->vTokens ); + else if ( !strcmp( pDirective, ".asserts" ) ) + fStatus = Io_ReadBlifNetworkAsserts( p, p->vTokens ); + else if ( !strcmp( pDirective, ".input_arrival" ) ) + fStatus = Io_ReadBlifNetworkInputArrival( p, p->vTokens ); + else if ( !strcmp( pDirective, ".default_input_arrival" ) ) + fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, p->vTokens ); +// else if ( !strcmp( pDirective, ".subckt" ) ) +// fStatus = Io_ReadBlifNetworkSubcircuit( p, p->vTokens ); + else if ( !strcmp( pDirective, ".exdc" ) ) + break; + else if ( !strcmp( pDirective, ".end" ) ) + { + p->vTokens = Io_ReadBlifGetTokens(p); + break; + } + else if ( !strcmp( pDirective, ".blackbox" ) ) + { + pNtk->ntkType = ABC_NTK_NETLIST; + pNtk->ntkFunc = ABC_FUNC_BLACKBOX; + Extra_MmFlexStop( pNtk->pManFunc ); + pNtk->pManFunc = NULL; + } + else + printf( "%s (line %d): Skipping directive \"%s\".\n", p->pFileName, + Extra_FileReaderGetLineNumber(p->pReader, 0), pDirective ); + if ( p->vTokens == NULL ) // some files do not have ".end" in the end + break; + if ( fStatus == 1 ) + { + Extra_ProgressBarStop( pProgress ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + if ( p->pNtkMaster == NULL ) + Extra_ProgressBarStop( pProgress ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + int i; + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePi( p->pNtkCur, vTokens->pArray[i] ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + int i; + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePo( p->pNtkCur, vTokens->pArray[i] ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkAsserts( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + int i; + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreateAssert( p->pNtkCur, vTokens->pArray[i] ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Abc_Ntk_t * pNtk = p->pNtkCur; + Abc_Obj_t * pLatch; + int ResetValue; + if ( vTokens->nSize < 3 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .latch line does not have enough tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // create the latch + pLatch = Io_ReadCreateLatch( pNtk, vTokens->pArray[1], vTokens->pArray[2] ); + // get the latch reset value + if ( vTokens->nSize == 3 ) + Abc_LatchSetInitDc( pLatch ); + else + { + ResetValue = atoi(vTokens->pArray[vTokens->nSize-1]); + if ( ResetValue != 0 && ResetValue != 1 && ResetValue != 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .latch line has an unknown reset value (%s).", vTokens->pArray[3] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + if ( ResetValue == 0 ) + Abc_LatchSetInit0( pLatch ); + else if ( ResetValue == 1 ) + Abc_LatchSetInit1( pLatch ); + else if ( ResetValue == 2 ) + Abc_LatchSetInitDc( pLatch ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ) +{ + Vec_Ptr_t * vTokens = *pvTokens; + Abc_Ntk_t * pNtk = p->pNtkCur; + Abc_Obj_t * pNode; + char * pToken, Char, ** ppNames; + int nFanins, nNames; + + // create a new node and add it to the network + if ( vTokens->nSize < 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .names line has less than two tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // create the node + ppNames = (char **)vTokens->pArray + 1; + nNames = vTokens->nSize - 2; + pNode = Io_ReadCreateNode( pNtk, ppNames[nNames], ppNames, nNames ); + + // derive the functionality of the node + p->vCubes->nSize = 0; + nFanins = vTokens->nSize - 2; + if ( nFanins == 0 ) + { + while ( vTokens = Io_ReadBlifGetTokens(p) ) + { + pToken = vTokens->pArray[0]; + if ( pToken[0] == '.' ) + break; + // read the cube + if ( vTokens->nSize != 1 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The number of tokens in the constant cube is wrong." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // create the cube + Char = ((char *)vTokens->pArray[0])[0]; + Vec_StrPush( p->vCubes, ' ' ); + Vec_StrPush( p->vCubes, Char ); + Vec_StrPush( p->vCubes, '\n' ); + } + } + else + { + while ( vTokens = Io_ReadBlifGetTokens(p) ) + { + pToken = vTokens->pArray[0]; + if ( pToken[0] == '.' ) + break; + // read the cube + if ( vTokens->nSize != 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The number of tokens in the cube is wrong." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // create the cube + Vec_StrAppend( p->vCubes, vTokens->pArray[0] ); + // check the char + Char = ((char *)vTokens->pArray[1])[0]; + if ( Char != '0' && Char != '1' && Char != 'x' && Char != 'n' ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The output character in the constant cube is wrong." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + Vec_StrPush( p->vCubes, ' ' ); + Vec_StrPush( p->vCubes, Char ); + Vec_StrPush( p->vCubes, '\n' ); + } + } + // if there is nothing there + if ( p->vCubes->nSize == 0 ) + { + // create an empty cube + Vec_StrPush( p->vCubes, ' ' ); + Vec_StrPush( p->vCubes, '0' ); + Vec_StrPush( p->vCubes, '\n' ); + } + Vec_StrPush( p->vCubes, 0 ); + + // set the pointer to the functionality of the node + Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, p->vCubes->pArray) ); + + // check the size + if ( Abc_ObjFaninNum(pNode) != Abc_SopGetVarNum(Abc_ObjData(pNode)) ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The number of fanins (%d) of node %s is different from SOP size (%d).", + Abc_ObjFaninNum(pNode), Abc_ObjName(Abc_ObjFanout(pNode,0)), Abc_SopGetVarNum(Abc_ObjData(pNode)) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // return the last array of tokens + *pvTokens = vTokens; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Mio_Library_t * pGenlib; + Mio_Gate_t * pGate; + Abc_Obj_t * pNode; + char ** ppNames; + int i, nNames; + + // check that the library is available + pGenlib = Abc_FrameReadLibGen(); + if ( pGenlib == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The current library is not available." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // create a new node and add it to the network + if ( vTokens->nSize < 2 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .gate line has less than two tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // get the gate + pGate = Mio_LibraryReadGateByName( pGenlib, vTokens->pArray[1] ); + if ( pGate == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Cannot find gate \"%s\" in the library.", vTokens->pArray[1] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // if this is the first line with gate, update the network type + if ( Abc_NtkNodeNum(p->pNtkCur) == 0 ) + { + assert( p->pNtkCur->ntkFunc == ABC_FUNC_SOP ); + p->pNtkCur->ntkFunc = ABC_FUNC_MAP; + Extra_MmFlexStop( p->pNtkCur->pManFunc ); + p->pNtkCur->pManFunc = pGenlib; + } + + // remove the formal parameter names + for ( i = 2; i < vTokens->nSize; i++ ) + { + vTokens->pArray[i] = Io_ReadBlifCleanName( vTokens->pArray[i] ); + if ( vTokens->pArray[i] == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Invalid gate input assignment." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + } + + // create the node + ppNames = (char **)vTokens->pArray + 2; + nNames = vTokens->nSize - 3; + pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames ); + + // set the pointer to the functionality of the node + Abc_ObjSetData( pNode, pGate ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Creates a multi-input multi-output box in the hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Abc_Obj_t * pBox; + Vec_Ptr_t * vNames; + char * pName; + int i; + + // create a new node and add it to the network + if ( vTokens->nSize < 3 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "The .subcircuit line has less than three tokens." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // store the names of formal/actual inputs/outputs of the box + vNames = Vec_PtrAlloc( 10 ); + Vec_PtrForEachEntryStart( vTokens, pName, i, 1 ) +// Vec_PtrPush( vNames, Abc_NtkRegisterName(p->pNtkCur, pName) ); + Vec_PtrPush( vNames, Extra_UtilStrsav(pName) ); // memory leak!!! + + // create a new box and add it to the network + pBox = Abc_NtkCreateBlackbox( p->pNtkCur ); + // set the pointer to the node names + Abc_ObjSetData( pBox, vNames ); + // remember the line of the file + pBox->pCopy = (void *)Extra_FileReaderGetLineNumber(p->pReader, 0); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_ReadBlifCleanName( char * pName ) +{ + int i, Length; + Length = strlen(pName); + for ( i = 0; i < Length; i++ ) + if ( pName[i] == '=' ) + return pName + i + 1; + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + Abc_Obj_t * pNet; + char * pFoo1, * pFoo2; + double TimeRise, TimeFall; + + // make sure this is indeed the .inputs line + assert( strncmp( vTokens->pArray[0], ".input_arrival", 14 ) == 0 ); + if ( vTokens->nSize != 4 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Wrong number of arguments on .input_arrival line." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pNet = Abc_NtkFindNet( p->pNtkCur, vTokens->pArray[1] ); + if ( pNet == NULL ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Cannot find object corresponding to %s on .input_arrival line.", vTokens->pArray[1] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + TimeRise = strtod( vTokens->pArray[2], &pFoo1 ); + TimeFall = strtod( vTokens->pArray[3], &pFoo2 ); + if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .input_arrival line.", vTokens->pArray[2], vTokens->pArray[3] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // set the arrival time + Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) +{ + char * pFoo1, * pFoo2; + double TimeRise, TimeFall; + + // make sure this is indeed the .inputs line + assert( strncmp( vTokens->pArray[0], ".default_input_arrival", 23 ) == 0 ); + if ( vTokens->nSize != 3 ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Wrong number of arguments on .default_input_arrival line." ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + TimeRise = strtod( vTokens->pArray[1], &pFoo1 ); + TimeFall = strtod( vTokens->pArray[2], &pFoo2 ); + if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) + { + p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); + sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_input_arrival line.", vTokens->pArray[1], vTokens->pArray[2] ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // set the arrival time + Abc_NtkTimeSetDefaultArrival( p->pNtkCur, (float)TimeRise, (float)TimeFall ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Prints the error message including the file name and line number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ) +{ + p->fError = 1; + if ( p->LineCur == 0 ) // the line number is not given + fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); + else // print the error message with the line number + fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError ); +} + +/**Function************************************************************* + + Synopsis [Gets the tokens taking into account the line breaks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) +{ + Vec_Ptr_t * vTokens; + char * pLastToken; + int i; + + // get rid of the old tokens + if ( p->vNewTokens->nSize > 0 ) + { + for ( i = 0; i < p->vNewTokens->nSize; i++ ) + free( p->vNewTokens->pArray[i] ); + p->vNewTokens->nSize = 0; + } + + // get the new tokens + vTokens = Extra_FileReaderGetTokens(p->pReader); + if ( vTokens == NULL ) + return vTokens; + + // check if there is a transfer to another line + pLastToken = vTokens->pArray[vTokens->nSize - 1]; + if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' ) + return vTokens; + + // remove the slash + pLastToken[ strlen(pLastToken)-1 ] = 0; + if ( pLastToken[0] == 0 ) + vTokens->nSize--; + // load them into the new array + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + + // load as long as there is the line break + while ( 1 ) + { + // get the new tokens + vTokens = Extra_FileReaderGetTokens(p->pReader); + if ( vTokens->nSize == 0 ) + return p->vNewTokens; + // check if there is a transfer to another line + pLastToken = vTokens->pArray[vTokens->nSize - 1]; + if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' ) + { + // remove the slash + pLastToken[ strlen(pLastToken)-1 ] = 0; + if ( pLastToken[0] == 0 ) + vTokens->nSize--; + // load them into the new array + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + continue; + } + // otherwise, load them and break + for ( i = 0; i < vTokens->nSize; i++ ) + Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); + break; + } + return p->vNewTokens; +} + +/**Function************************************************************* + + Synopsis [Starts the reading data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ) +{ + Extra_FileReader_t * pReader; + Io_ReadBlif_t * p; + + // start the reader + pReader = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t" ); + + if ( pReader == NULL ) + return NULL; + + // start the reading data structure + p = ALLOC( Io_ReadBlif_t, 1 ); + memset( p, 0, sizeof(Io_ReadBlif_t) ); + p->pFileName = pFileName; + p->pReader = pReader; + p->Output = stdout; + p->vNewTokens = Vec_PtrAlloc( 100 ); + p->vCubes = Vec_StrAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the data structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadBlifFree( Io_ReadBlif_t * p ) +{ + Extra_FileReaderFree( p->pReader ); + Vec_PtrFree( p->vNewTokens ); + Vec_StrFree( p->vCubes ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Connect one box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxesOneBox( Io_ReadBlif_t * p, Abc_Obj_t * pBox, stmm_table * tName2Model ) +{ + Vec_Ptr_t * pNames; + Abc_Ntk_t * pNtkModel; + Abc_Obj_t * pObj, * pNet; + char * pName, * pActual; + int i, Length, Start; + + // get the model for this box + pNames = pBox->pData; + if ( !stmm_lookup( tName2Model, Vec_PtrEntry(pNames, 0), (char **)&pNtkModel ) ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find the model for subcircuit %s.", Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + + // create the fanins of the box + Abc_NtkForEachPi( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + if ( Abc_NtkPiNum(pNtkModel) == 0 ) + Start = 1; + else + { + Vec_PtrForEachEntryStart( pNames, pName, i, 1 ) + { + pActual = Io_ReadBlifCleanName(pName); + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + Length = pActual - pName - 1; + pName[Length] = 0; + // find the PI net with this name + pObj = Abc_NtkFindNet( pNtkModel, pName ); + if ( pObj == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find formal input \"%s\" as an PI of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // get the PI + pObj = Abc_ObjFanin0(pObj); + // quit if this is not a PI net + if ( !Abc_ObjIsPi(pObj) ) + { + pName[Length] = '='; + Start = i; + break; + } + // remember the actual name in the net + if ( pObj->pCopy != NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal input \"%s\" is used more than once.", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pObj->pCopy = (void *)pActual; + // quit if we processed all PIs + if ( i == Abc_NtkPiNum(pNtkModel) ) + { + Start = i+1; + break; + } + } + } + // create the fanins of the box + Abc_NtkForEachPi( pNtkModel, pObj, i ) + { + pActual = (void *)pObj->pCopy; + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal input \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); + Abc_ObjAddFanin( pBox, pNet ); + } + Abc_NtkForEachPi( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + + // create the fanouts of the box + Abc_NtkForEachPo( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + Vec_PtrForEachEntryStart( pNames, pName, i, Start ) + { + pActual = Io_ReadBlifCleanName(pName); + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + Length = pActual - pName - 1; + pName[Length] = 0; + // find the PO net with this name + pObj = Abc_NtkFindNet( pNtkModel, pName ); + if ( pObj == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Cannot find formal output \"%s\" as an PO of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + // get the PO + pObj = Abc_ObjFanout0(pObj); + if ( pObj->pCopy != NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal output \"%s\" is used more than once.", pName ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pObj->pCopy = (void *)pActual; + } + // create the fanouts of the box + Abc_NtkForEachPo( pNtkModel, pObj, i ) + { + pActual = (void *)pObj->pCopy; + if ( pActual == NULL ) + { + p->LineCur = (int)pBox->pCopy; + sprintf( p->sError, "Formal output \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) ); + Io_ReadBlifPrintErrorMessage( p ); + return 1; + } + pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); + Abc_ObjAddFanin( pNet, pBox ); + } + Abc_NtkForEachPo( pNtkModel, pObj, i ) + pObj->pCopy = NULL; + + // remove the array of names, assign the pointer to the model + Vec_PtrForEachEntry( pBox->pData, pName, i ) + free( pName ); + Vec_PtrFree( pBox->pData ); + pBox->pData = pNtkModel; + return 0; +} + +/**Function************************************************************* + + Synopsis [Connect the boxes in the hierarchy of networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxesOne( Io_ReadBlif_t * p, Abc_Ntk_t * pNtk, stmm_table * tName2Model ) +{ + Abc_Obj_t * pBox; + int i; + // go through the boxes + Abc_NtkForEachBlackbox( pNtk, pBox, i ) + if ( Io_ReadBlifNetworkConnectBoxesOneBox( p, pBox, tName2Model ) ) + return 1; + Abc_NtkFinalizeRead( pNtk ); + return 0; +} + +#if 0 + +/**Function************************************************************* + + Synopsis [Connect the boxes in the hierarchy of networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ) +{ + stmm_generator * gen; + Abc_Ntk_t * pNtk; + char * pName; + // connect the master network + if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtkMaster, pNtkMaster->tName2Model ) ) + return 1; + // connect other networks + stmm_foreach_item( pNtkMaster->tName2Model, gen, &pName, (char **)&pNtk ) + if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtk, pNtkMaster->tName2Model ) ) + return 1; + return 0; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBlifAig.c b/abc70930/src/base/io/ioReadBlifAig.c new file mode 100644 index 00000000..c448bab6 --- /dev/null +++ b/abc70930/src/base/io/ioReadBlifAig.c @@ -0,0 +1,1013 @@ +/**CFile**************************************************************** + + FileName [ioReadBlifAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BLIF file into AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 23, 2006.] + + Revision [$Id: ioReadBlifAig.c,v 1.00 2006/12/23 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "extra.h" +#include "vecPtr.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// latch initial values +typedef enum { + IO_BLIF_INIT_NONE = 0, // 0: unknown + IO_BLIF_INIT_ZERO, // 1: zero + IO_BLIF_INIT_ONE, // 2: one + IO_BLIF_INIT_DC // 3: don't-care +} Io_BlifInit_t; + +typedef struct Io_BlifObj_t_ Io_BlifObj_t; // parsing object +struct Io_BlifObj_t_ +{ + unsigned fPi : 1; // the object is a primary input + unsigned fPo : 1; // the object is a primary output + unsigned fLi : 1; // the object is a latch input + unsigned fLo : 1; // the object is a latch output + unsigned fDef : 1; // the object is defined as a table (node, PO, LI) + unsigned fLoop : 1; // flag for loop detection + unsigned Init : 2; // the latch initial state + unsigned Offset : 24; // temporary number + char * pName; // the name of this object + void * pEquiv; // the AIG node representing this line + Io_BlifObj_t * pNext; // the next obj in the hash table +}; + +typedef struct Io_BlifMan_t_ Io_BlifMan_t; // parsing manager +struct Io_BlifMan_t_ +{ + // general info about file + char * pFileName; // the name of the file + char * pBuffer; // the begining of the file buffer + Vec_Ptr_t * vLines; // the line beginnings + // temporary objects + Io_BlifObj_t * pObjects; // the storage for objects + int nObjects; // the number of objects allocated + int iObjNext; // the next free object + // file lines + char * pModel; // .model line + Vec_Ptr_t * vInputs; // .inputs lines + Vec_Ptr_t * vOutputs; // .outputs lines + Vec_Ptr_t * vLatches; // .latches lines + Vec_Ptr_t * vNames; // .names lines + // network objects + Vec_Ptr_t * vPis; // the PI structures + Vec_Ptr_t * vPos; // the PO structures + Vec_Ptr_t * vLis; // the LI structures + Vec_Ptr_t * vLos; // the LO structures + // mapping of names into objects + Io_BlifObj_t ** pTable; // the hash table + int nTableSize; // the hash table size + // current processing info + Abc_Ntk_t * pAig; // the network under construction + Vec_Ptr_t * vTokens; // the current tokens + char sError[512]; // the error string generated during parsing + // statistics + int nTablesRead; // the number of processed tables + int nTablesLeft; // the number of dangling tables +}; + +// static functions +static Io_BlifMan_t * Io_BlifAlloc(); +static void Io_BlifFree( Io_BlifMan_t * p ); +static char * Io_BlifLoadFile( char * pFileName ); +static void Io_BlifReadPreparse( Io_BlifMan_t * p ); +static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p ); +static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine ); +static int Io_BlifParseConstruct( Io_BlifMan_t * p ); +static int Io_BlifCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from the BLIF file as an AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck ) +{ + FILE * pFile; + Io_BlifMan_t * p; + Abc_Ntk_t * pAig; + + // check that the file is available + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_Blif(): The file is unavailable (absent or open).\n" ); + return 0; + } + fclose( pFile ); + + // start the file reader + p = Io_BlifAlloc(); + p->pFileName = pFileName; + p->pBuffer = Io_BlifLoadFile( pFileName ); + if ( p->pBuffer == NULL ) + { + Io_BlifFree( p ); + return NULL; + } + // prepare the file for parsing + Io_BlifReadPreparse( p ); + // construct the network + pAig = Io_BlifParse( p ); + if ( p->sError[0] ) + fprintf( stdout, "%s\n", p->sError ); + if ( pAig == NULL ) + return NULL; + Io_BlifFree( p ); + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pAig ) ) + { + printf( "Io_Blif: The network check has failed.\n" ); + Abc_NtkDelete( pAig ); + return NULL; + } + return pAig; +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_BlifMan_t * Io_BlifAlloc() +{ + Io_BlifMan_t * p; + p = ALLOC( Io_BlifMan_t, 1 ); + memset( p, 0, sizeof(Io_BlifMan_t) ); + p->vLines = Vec_PtrAlloc( 512 ); + p->vInputs = Vec_PtrAlloc( 512 ); + p->vOutputs = Vec_PtrAlloc( 512 ); + p->vLatches = Vec_PtrAlloc( 512 ); + p->vNames = Vec_PtrAlloc( 512 ); + p->vTokens = Vec_PtrAlloc( 512 ); + p->vPis = Vec_PtrAlloc( 512 ); + p->vPos = Vec_PtrAlloc( 512 ); + p->vLis = Vec_PtrAlloc( 512 ); + p->vLos = Vec_PtrAlloc( 512 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifFree( Io_BlifMan_t * p ) +{ + if ( p->pAig ) + Abc_NtkDelete( p->pAig ); + if ( p->pBuffer ) free( p->pBuffer ); + if ( p->pObjects ) free( p->pObjects ); + if ( p->pTable ) free( p->pTable ); + Vec_PtrFree( p->vLines ); + Vec_PtrFree( p->vInputs ); + Vec_PtrFree( p->vOutputs ); + Vec_PtrFree( p->vLatches ); + Vec_PtrFree( p->vNames ); + Vec_PtrFree( p->vTokens ); + Vec_PtrFree( p->vPis ); + Vec_PtrFree( p->vPos ); + Vec_PtrFree( p->vLis ); + Vec_PtrFree( p->vLos ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Hashing for character strings.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static unsigned Io_BlifHashString( char * pName, int TableSize ) +{ + static int s_Primes[10] = { + 1291, 1699, 2357, 4177, 5147, + 5647, 6343, 7103, 7873, 8147 + }; + unsigned i, Key = 0; + for ( i = 0; pName[i] != '\0'; i++ ) + Key ^= s_Primes[i%10]*pName[i]*pName[i]; + return Key % TableSize; +} + +/**Function************************************************************* + + Synopsis [Checks if the given name exists in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_BlifObj_t ** Io_BlifHashLookup( Io_BlifMan_t * p, char * pName ) +{ + Io_BlifObj_t ** ppEntry; + for ( ppEntry = p->pTable + Io_BlifHashString(pName, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) + if ( !strcmp((*ppEntry)->pName, pName) ) + return ppEntry; + return ppEntry; +} + +/**Function************************************************************* + + Synopsis [Finds or add the given name to the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_BlifObj_t * Io_BlifHashFindOrAdd( Io_BlifMan_t * p, char * pName ) +{ + Io_BlifObj_t ** ppEntry; + ppEntry = Io_BlifHashLookup( p, pName ); + if ( *ppEntry == NULL ) + { + assert( p->iObjNext < p->nObjects ); + *ppEntry = p->pObjects + p->iObjNext++; + (*ppEntry)->pName = pName; + } + return *ppEntry; +} + + +/**Function************************************************************* + + Synopsis [Collects the already split tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput ) +{ + char * pCur; + Vec_PtrClear( vTokens ); + for ( pCur = pInput; pCur < pOutput; pCur++ ) + { + if ( *pCur == 0 ) + continue; + Vec_PtrPush( vTokens, pCur ); + while ( *++pCur ); + } +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != Stop; pCur++ ) + if ( Io_BlifCharIsSpace(*pCur) ) + *pCur = 0; + // collect tokens + Io_BlifCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Returns the 1-based number of the line in which the token occurs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifGetLine( Io_BlifMan_t * p, char * pToken ) +{ + char * pLine; + int i; + Vec_PtrForEachEntry( p->vLines, pLine, i ) + if ( pToken < pLine ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Conservatively estimates the number of primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifEstimatePiNum( Io_BlifMan_t * p ) +{ + char * pCur; + int i, fSpaces; + int Counter = 0; + Vec_PtrForEachEntry( p->vInputs, pCur, i ) + for ( fSpaces = 0; *pCur; pCur++ ) + { + if ( Io_BlifCharIsSpace(*pCur) ) + { + if ( !fSpaces ) + Counter++; + fSpaces = 1; + } + else + fSpaces = 0; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Conservatively estimates the number of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifEstimateAndNum( Io_BlifMan_t * p ) +{ + Io_BlifObj_t * pObj; + char * pCur; + int i, CounterOne, Counter = 0; + for ( i = 0; i < p->iObjNext; i++ ) + { + pObj = p->pObjects + i; + if ( !pObj->fDef ) + continue; + CounterOne = 0; + for ( pCur = pObj->pName + strlen(pObj->pName); *pCur != '.'; pCur++ ) + if ( *pCur == '0' || *pCur == '1' ) + CounterOne++; + if ( CounterOne ) + Counter += CounterOne - 1; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Reads the file into a character buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_BlifLoadFile( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + char * pContents; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_BlifLoadFile(): The file is unavailable (absent or open).\n" ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + if ( nFileSize == 0 ) + { + printf( "Io_BlifLoadFile(): The file is empty.\n" ); + return NULL; + } + pContents = ALLOC( char, nFileSize + 10 ); + rewind( pFile ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + // finish off the file with the spare .end line + // some benchmarks suddenly break off without this line + strcpy( pContents + nFileSize, "\n.end\n" ); + return pContents; +} + +/**Function************************************************************* + + Synopsis [Prepares the parsing.] + + Description [Performs several preliminary operations: + - Cuts the file buffer into separate lines. + - Removes comments and line extenders. + - Sorts lines by directives. + - Estimates the number of objects. + - Allocates room for the objects. + - Allocates room for the hash table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_BlifReadPreparse( Io_BlifMan_t * p ) +{ + char * pCur, * pPrev; + int i, fComment = 0; + // parse the buffer into lines and remove comments + Vec_PtrPush( p->vLines, p->pBuffer ); + for ( pCur = p->pBuffer; *pCur; pCur++ ) + { + if ( *pCur == '\n' ) + { + *pCur = 0; + fComment = 0; + Vec_PtrPush( p->vLines, pCur + 1 ); + } + else if ( *pCur == '#' ) + fComment = 1; + // remove comments + if ( fComment ) + *pCur = 0; + } + + // unfold the line extensions and sort lines by directive + Vec_PtrForEachEntry( p->vLines, pCur, i ) + { + if ( *pCur == 0 ) + continue; + // find previous non-space character + for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- ) + if ( !Io_BlifCharIsSpace(*pPrev) ) + break; + // if it is the line extender, overwrite it with spaces + if ( *pPrev == '\\' ) + { + for ( ; *pPrev; pPrev++ ) + *pPrev = ' '; + *pPrev = ' '; + continue; + } + // skip spaces at the beginning of the line + while ( Io_BlifCharIsSpace(*pCur++) ); + // parse directives + if ( *(pCur-1) != '.' ) + continue; + if ( !strncmp(pCur, "names", 5) ) + Vec_PtrPush( p->vNames, pCur ); + else if ( !strncmp(pCur, "latch", 5) ) + Vec_PtrPush( p->vLatches, pCur ); + else if ( !strncmp(pCur, "inputs", 6) ) + Vec_PtrPush( p->vInputs, pCur ); + else if ( !strncmp(pCur, "outputs", 7) ) + Vec_PtrPush( p->vOutputs, pCur ); + else if ( !strncmp(pCur, "model", 5) ) + p->pModel = pCur; + else if ( !strncmp(pCur, "end", 3) || !strncmp(pCur, "exdc", 4) ) + break; + else + { + pCur--; + if ( pCur[strlen(pCur)-1] == '\r' ) + pCur[strlen(pCur)-1] = 0; + fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_BlifGetLine(p, pCur), pCur ); + } + } + + // count the number of objects + p->nObjects = Io_BlifEstimatePiNum(p) + Vec_PtrSize(p->vLatches) + Vec_PtrSize(p->vNames) + 512; + + // allocate memory for objects + p->pObjects = ALLOC( Io_BlifObj_t, p->nObjects ); + memset( p->pObjects, 0, p->nObjects * sizeof(Io_BlifObj_t) ); + + // allocate memory for the hash table + p->nTableSize = p->nObjects/2 + 1; + p->pTable = ALLOC( Io_BlifObj_t *, p->nTableSize ); + memset( p->pTable, 0, p->nTableSize * sizeof(Io_BlifObj_t *) ); +} + + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p ) +{ + Abc_Ntk_t * pAig; + char * pLine; + int i; + // parse the model + if ( !Io_BlifParseModel( p, p->pModel ) ) + return NULL; + // parse the inputs + Vec_PtrForEachEntry( p->vInputs, pLine, i ) + if ( !Io_BlifParseInputs( p, pLine ) ) + return NULL; + // parse the outputs + Vec_PtrForEachEntry( p->vOutputs, pLine, i ) + if ( !Io_BlifParseOutputs( p, pLine ) ) + return NULL; + // parse the latches + Vec_PtrForEachEntry( p->vLatches, pLine, i ) + if ( !Io_BlifParseLatch( p, pLine ) ) + return NULL; + // parse the nodes + Vec_PtrForEachEntry( p->vNames, pLine, i ) + if ( !Io_BlifParseNames( p, pLine ) ) + return NULL; + // reconstruct the network from the parsed data + if ( !Io_BlifParseConstruct( p ) ) + return NULL; + // return the network + pAig = p->pAig; + p->pAig = NULL; + return pAig; +} + +/**Function************************************************************* + + Synopsis [Parses the model line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine ) +{ + char * pToken; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry( p->vTokens, 0 ); + assert( !strcmp(pToken, "model") ); + if ( Vec_PtrSize(p->vTokens) != 2 ) + { + sprintf( p->sError, "Line %d: Model line has %d entries while it should have 2.", Io_BlifGetLine(p, pToken), Vec_PtrSize(p->vTokens) ); + return 0; + } + p->pModel = Vec_PtrEntry( p->vTokens, 1 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the inputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pToken; + int i; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(p->vTokens, 0); + assert( !strcmp(pToken, "inputs") ); + Vec_PtrForEachEntryStart( p->vTokens, pToken, i, 1 ) + { + pObj = Io_BlifHashFindOrAdd( p, pToken ); + if ( pObj->fPi ) + { + sprintf( p->sError, "Line %d: Primary input (%s) is defined more than once.", Io_BlifGetLine(p, pToken), pToken ); + return 0; + } + pObj->fPi = 1; + Vec_PtrPush( p->vPis, pObj ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the outputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pToken; + int i; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(p->vTokens, 0); + assert( !strcmp(pToken, "outputs") ); + Vec_PtrForEachEntryStart( p->vTokens, pToken, i, 1 ) + { + pObj = Io_BlifHashFindOrAdd( p, pToken ); + if ( pObj->fPo ) + fprintf( stdout, "Line %d: Primary output (%s) is defined more than once (warning only).\n", Io_BlifGetLine(p, pToken), pToken ); + pObj->fPo = 1; + Vec_PtrPush( p->vPos, pObj ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the latches line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pToken; + int Init; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(p->vTokens,0); + assert( !strcmp(pToken, "latch") ); + if ( Vec_PtrSize(p->vTokens) < 3 ) + { + sprintf( p->sError, "Line %d: Latch does not have input name and output name.", Io_BlifGetLine(p, pToken) ); + return 0; + } + // get initial value + if ( Vec_PtrSize(p->vTokens) > 3 ) + Init = atoi( Vec_PtrEntry(p->vTokens,3) ); + else + Init = 2; + if ( Init < 0 || Init > 2 ) + { + sprintf( p->sError, "Line %d: Initial state of the latch is incorrect (%s).", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,3) ); + return 0; + } + if ( Init == 0 ) + Init = IO_BLIF_INIT_ZERO; + else if ( Init == 1 ) + Init = IO_BLIF_INIT_ONE; + else // if ( Init == 2 ) + Init = IO_BLIF_INIT_DC; + // get latch input + pObj = Io_BlifHashFindOrAdd( p, Vec_PtrEntry(p->vTokens,1) ); + pObj->fLi = 1; + Vec_PtrPush( p->vLis, pObj ); + pObj->Init = Init; + // get latch output + pObj = Io_BlifHashFindOrAdd( p, Vec_PtrEntry(p->vTokens,2) ); + if ( pObj->fPi ) + { + sprintf( p->sError, "Line %d: Primary input (%s) is also defined latch output.", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,2) ); + return 0; + } + if ( pObj->fLo ) + { + sprintf( p->sError, "Line %d: Latch output (%s) is defined as the output of another latch.", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,2) ); + return 0; + } + pObj->fLo = 1; + Vec_PtrPush( p->vLos, pObj ); + pObj->Init = Init; + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine ) +{ + Io_BlifObj_t * pObj; + char * pName; + Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); + assert( !strcmp(Vec_PtrEntry(p->vTokens,0), "names") ); + pName = Vec_PtrEntryLast( p->vTokens ); + pObj = Io_BlifHashFindOrAdd( p, pName ); + if ( pObj->fPi ) + { + sprintf( p->sError, "Line %d: Primary input (%s) has a table.", Io_BlifGetLine(p, pName), pName ); + return 0; + } + if ( pObj->fLo ) + { + sprintf( p->sError, "Line %d: Latch output (%s) has a table.", Io_BlifGetLine(p, pName), pName ); + return 0; + } + if ( pObj->fDef ) + { + sprintf( p->sError, "Line %d: Signal (%s) is defined more than once.", Io_BlifGetLine(p, pName), pName ); + return 0; + } + pObj->fDef = 1; + // remember offset to the first fanin name + pObj->pName = pName; + pObj->Offset = pObj->pName - (char *)Vec_PtrEntry(p->vTokens,1); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Constructs the AIG from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Obj_t * Io_BlifParseTable( Io_BlifMan_t * p, char * pTable, Vec_Ptr_t * vFanins ) +{ + char * pProduct, * pOutput; + Abc_Obj_t * pRes, * pCube; + int i, k, Polarity = -1; + + p->nTablesRead++; + // get the tokens + Io_BlifSplitIntoTokens( p->vTokens, pTable, '.' ); + if ( Vec_PtrSize(p->vTokens) == 0 ) + return Abc_ObjNot( Abc_AigConst1(p->pAig) ); + if ( Vec_PtrSize(p->vTokens) == 1 ) + { + pOutput = Vec_PtrEntry( p->vTokens, 0 ); + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->sError, "Line %d: Constant table has wrong output value (%s).", Io_BlifGetLine(p, pOutput), pOutput ); + return NULL; + } + return Abc_ObjNotCond( Abc_AigConst1(p->pAig), pOutput[0] == '0' ); + } + pProduct = Vec_PtrEntry( p->vTokens, 0 ); + if ( Vec_PtrSize(p->vTokens) % 2 == 1 ) + { + sprintf( p->sError, "Line %d: Table has odd number of tokens (%d).", Io_BlifGetLine(p, pProduct), Vec_PtrSize(p->vTokens) ); + return NULL; + } + // parse the table + pRes = Abc_ObjNot( Abc_AigConst1(p->pAig) ); + for ( i = 0; i < Vec_PtrSize(p->vTokens)/2; i++ ) + { + pProduct = Vec_PtrEntry( p->vTokens, 2*i + 0 ); + pOutput = Vec_PtrEntry( p->vTokens, 2*i + 1 ); + if ( strlen(pProduct) != (unsigned)Vec_PtrSize(vFanins) ) + { + sprintf( p->sError, "Line %d: Cube (%s) has size different from the fanin count (%d).", Io_BlifGetLine(p, pProduct), pProduct, Vec_PtrSize(vFanins) ); + return NULL; + } + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->sError, "Line %d: Output value (%s) is incorrect.", Io_BlifGetLine(p, pProduct), pOutput ); + return NULL; + } + if ( Polarity == -1 ) + Polarity = pOutput[0] - '0'; + else if ( Polarity != pOutput[0] - '0' ) + { + sprintf( p->sError, "Line %d: Output value (%s) differs from the value in the first line of the table (%d).", Io_BlifGetLine(p, pProduct), pOutput, Polarity ); + return NULL; + } + // parse one product product + pCube = Abc_AigConst1(p->pAig); + for ( k = 0; pProduct[k]; k++ ) + { + if ( pProduct[k] == '0' ) + pCube = Abc_AigAnd( p->pAig->pManFunc, pCube, Abc_ObjNot(Vec_PtrEntry(vFanins,k)) ); + else if ( pProduct[k] == '1' ) + pCube = Abc_AigAnd( p->pAig->pManFunc, pCube, Vec_PtrEntry(vFanins,k) ); + else if ( pProduct[k] != '-' ) + { + sprintf( p->sError, "Line %d: Product term (%s) contains character (%c).", Io_BlifGetLine(p, pProduct), pProduct, pProduct[k] ); + return NULL; + } + } + pRes = Abc_AigOr( p->pAig->pManFunc, pRes, pCube ); + } + pRes = Abc_ObjNotCond( pRes, Polarity == 0 ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Constructs the AIG from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Obj_t * Io_BlifParseConstruct_rec( Io_BlifMan_t * p, char * pName ) +{ + Vec_Ptr_t * vFanins; + Abc_Obj_t * pFaninAbc; + Io_BlifObj_t * pObjIo; + char * pNameFanin; + int i; + // get the IO object with this name + pObjIo = *Io_BlifHashLookup( p, pName ); + if ( pObjIo == NULL ) + { + sprintf( p->sError, "Line %d: Signal (%s) is not defined as a table.", Io_BlifGetLine(p, pName), pName ); + return NULL; + } + // loop detection + if ( pObjIo->fLoop ) + { + sprintf( p->sError, "Line %d: Signal (%s) appears twice on a combinational path.", Io_BlifGetLine(p, pName), pName ); + return NULL; + } + // check if the AIG is already constructed + if ( pObjIo->pEquiv ) + return pObjIo->pEquiv; + // mark this node on the path + pObjIo->fLoop = 1; + // construct the AIGs for the fanins + vFanins = Vec_PtrAlloc( 8 ); + Io_BlifCollectTokens( vFanins, pObjIo->pName - pObjIo->Offset, pObjIo->pName ); + Vec_PtrForEachEntry( vFanins, pNameFanin, i ) + { + pFaninAbc = Io_BlifParseConstruct_rec( p, pNameFanin ); + if ( pFaninAbc == NULL ) + { + Vec_PtrFree( vFanins ); + return NULL; + } + Vec_PtrWriteEntry( vFanins, i, pFaninAbc ); + } + // construct the node + pObjIo->pEquiv = Io_BlifParseTable( p, pObjIo->pName + strlen(pObjIo->pName), vFanins ); + Vec_PtrFree( vFanins ); + // unmark this node on the path + pObjIo->fLoop = 0; + // remember the new node + return pObjIo->pEquiv; +} + +/**Function************************************************************* + + Synopsis [Constructs the AIG from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_BlifParseConstruct( Io_BlifMan_t * p ) +{ + Abc_Ntk_t * pAig; + Io_BlifObj_t * pObjIo, * pObjIoInput; + Abc_Obj_t * pObj, * pLatch; + int i; + // allocate the empty AIG + pAig = p->pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pAig->pName = Extra_UtilStrsav( p->pModel ); + pAig->pSpec = Extra_UtilStrsav( p->pFileName ); + // create PIs + Vec_PtrForEachEntry( p->vPis, pObjIo, i ) + { + pObj = Abc_NtkCreatePi( pAig ); + Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); + pObjIo->pEquiv = pObj; + } + // create POs + Vec_PtrForEachEntry( p->vPos, pObjIo, i ) + { + pObj = Abc_NtkCreatePo( pAig ); + Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); + } + // create latches + Vec_PtrForEachEntry( p->vLos, pObjIo, i ) + { + // add the latch input terminal + pObj = Abc_NtkCreateBi( pAig ); + pObjIoInput = Vec_PtrEntry( p->vLis, i ); + Abc_ObjAssignName( pObj, pObjIoInput->pName, NULL ); + + // add the latch box + pLatch = Abc_NtkCreateLatch( pAig ); + pLatch->pData = (void *)pObjIo->Init; + Abc_ObjAssignName( pLatch, pObjIo->pName, "L" ); + Abc_ObjAddFanin( pLatch, pObj ); + + // add the latch output terminal + pObj = Abc_NtkCreateBo( pAig ); + Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); + Abc_ObjAddFanin( pObj, pLatch ); + // set the value of the latch output +// pObjIo->pEquiv = Abc_ObjNotCond( pObj, pObjIo->Init ); + pObjIo->pEquiv = pObj; + } + // traverse the nodes from the POs + Vec_PtrForEachEntry( p->vPos, pObjIo, i ) + { + pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName ); + if ( pObj == NULL ) + return 0; + Abc_ObjAddFanin( Abc_NtkPo(p->pAig, i), pObj ); + } + // traverse the nodes from the latch inputs + Vec_PtrForEachEntry( p->vLis, pObjIo, i ) + { + pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName ); + if ( pObj == NULL ) + return 0; +// pObj = Abc_ObjNotCond( pObj, pObjIo->Init ); + Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(p->pAig, i)), pObj ); + } + p->nTablesLeft = Vec_PtrSize(p->vNames) - p->nTablesRead; + if ( p->nTablesLeft ) + printf( "The number of dangling tables = %d.\n", p->nTablesLeft ); + printf( "AND nodes = %6d. Estimate = %6d.\n", Abc_NtkNodeNum(p->pAig), Io_BlifEstimateAndNum(p) ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadBlifMv.c b/abc70930/src/base/io/ioReadBlifMv.c new file mode 100644 index 00000000..18578cbb --- /dev/null +++ b/abc70930/src/base/io/ioReadBlifMv.c @@ -0,0 +1,1696 @@ +/**CFile**************************************************************** + + FileName [ioReadBlifMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read BLIF-MV file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 8, 2007.] + + Revision [$Id: ioReadBlifMv.c,v 1.00 2007/01/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "extra.h" +#include "vecPtr.h" +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IO_BLIFMV_MAXVALUES 256 + +typedef struct Io_MvVar_t_ Io_MvVar_t; // parsing var +typedef struct Io_MvMod_t_ Io_MvMod_t; // parsing model +typedef struct Io_MvMan_t_ Io_MvMan_t; // parsing manager + +struct Io_MvVar_t_ +{ + int nValues; // the number of values + char ** pNames; // the value names +}; + +struct Io_MvMod_t_ +{ + // file lines + char * pName; // .model line + Vec_Ptr_t * vInputs; // .inputs lines + Vec_Ptr_t * vOutputs; // .outputs lines + Vec_Ptr_t * vLatches; // .latch lines + Vec_Ptr_t * vResets; // .reset lines + Vec_Ptr_t * vNames; // .names lines + Vec_Ptr_t * vSubckts; // .subckt lines + Vec_Ptr_t * vMvs; // .mv lines + int fBlackBox; // indicates blackbox model + // the resulting network + Abc_Ntk_t * pNtk; + Abc_Obj_t * pResetLatch; + // the parent manager + Io_MvMan_t * pMan; +}; + +struct Io_MvMan_t_ +{ + // general info about file + int fBlifMv; // the file is BLIF-MV + int fUseReset; // the reset circuitry is added + char * pFileName; // the name of the file + char * pBuffer; // the contents of the file + Vec_Ptr_t * vLines; // the line beginnings + // the results of reading + Abc_Lib_t * pDesign; // the design under construction + int nNDnodes; // the counter of ND nodes + // intermediate storage for models + Vec_Ptr_t * vModels; // vector of models + Io_MvMod_t * pLatest; // the current model + // current processing info + Vec_Ptr_t * vTokens; // the current tokens + Vec_Ptr_t * vTokens2; // the current tokens + Vec_Str_t * vFunc; // the local function + // error reporting + char sError[512]; // the error string generated during parsing + // statistics + int nTablesRead; // the number of processed tables + int nTablesLeft; // the number of dangling tables +}; + +// static functions +static Io_MvMan_t * Io_MvAlloc(); +static void Io_MvFree( Io_MvMan_t * p ); +static Io_MvMod_t * Io_MvModAlloc(); +static void Io_MvModFree( Io_MvMod_t * p ); +static char * Io_MvLoadFile( char * pFileName ); +static void Io_MvReadPreparse( Io_MvMan_t * p ); +static void Io_MvReadInterfaces( Io_MvMan_t * p ); +static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p ); +static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset ); +static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine ); +static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens ); +static Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar ); + +static int Io_MvCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } +static int Io_MvCharIsMvSymb( char s ) { return s == '(' || s == ')' || s == '{' || s == '}' || s == '-' || s == ',' || s == '!'; } + +extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from the BLIF or BLIF-MV file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck ) +{ + FILE * pFile; + Io_MvMan_t * p; + Abc_Ntk_t * pNtk; + Abc_Lib_t * pDesign; + char * pDesignName; + int RetValue, i; + + // check that the file is available + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_ReadBlifMv(): The file is unavailable (absent or open).\n" ); + return 0; + } + fclose( pFile ); + + // start the file reader + p = Io_MvAlloc(); + p->fBlifMv = fBlifMv; + p->fUseReset = 0; + p->pFileName = pFileName; + p->pBuffer = Io_MvLoadFile( pFileName ); + if ( p->pBuffer == NULL ) + { + Io_MvFree( p ); + return NULL; + } + // set the design name + pDesignName = Extra_FileNameGeneric( pFileName ); + p->pDesign = Abc_LibCreate( pDesignName ); + free( pDesignName ); + // free the HOP manager + Hop_ManStop( p->pDesign->pManFunc ); + p->pDesign->pManFunc = NULL; + // prepare the file for parsing + Io_MvReadPreparse( p ); + // parse interfaces of each network + Io_MvReadInterfaces( p ); + // construct the network + pDesign = Io_MvParse( p ); + if ( p->sError[0] ) + fprintf( stdout, "%s\n", p->sError ); + if ( pDesign == NULL ) + return NULL; + Io_MvFree( p ); +// pDesign should be linked to all models of the design + + // make sure that everything is okay with the network structure + if ( fCheck ) + { + Vec_PtrForEachEntry( pDesign->vModules, pNtk, i ) + { + if ( !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadBlifMv: The network check has failed for network %s.\n", pNtk->pName ); + Abc_LibFree( pDesign, NULL ); + return NULL; + } + } + } + +//Abc_LibPrint( pDesign ); + + // detect top-level model + RetValue = Abc_LibFindTopLevelModels( pDesign ); + pNtk = Vec_PtrEntry( pDesign->vTops, 0 ); + if ( RetValue > 1 ) + printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n", + Vec_PtrSize(pDesign->vTops), pNtk->pName ); + + // extract the master network + pNtk->pDesign = pDesign; + pDesign->pManFunc = NULL; + + // verify the design for cyclic dependence + assert( Vec_PtrSize(pDesign->vModules) > 0 ); + if ( Vec_PtrSize(pDesign->vModules) == 1 ) + { +// printf( "Warning: The design is not hierarchical.\n" ); + Abc_LibFree( pDesign, pNtk ); + pNtk->pDesign = NULL; + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + } + else + Abc_NtkIsAcyclicHierarchy( pNtk ); + +//Io_WriteBlifMv( pNtk, "_temp_.mv" ); + if ( pNtk->pSpec == NULL ) + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_MvMan_t * Io_MvAlloc() +{ + Io_MvMan_t * p; + p = ALLOC( Io_MvMan_t, 1 ); + memset( p, 0, sizeof(Io_MvMan_t) ); + p->vLines = Vec_PtrAlloc( 512 ); + p->vModels = Vec_PtrAlloc( 512 ); + p->vTokens = Vec_PtrAlloc( 512 ); + p->vTokens2 = Vec_PtrAlloc( 512 ); + p->vFunc = Vec_StrAlloc( 512 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the BLIF parsing structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvFree( Io_MvMan_t * p ) +{ + Io_MvMod_t * pMod; + int i; + if ( p->pDesign ) + Abc_LibFree( p->pDesign, NULL ); + if ( p->pBuffer ) + free( p->pBuffer ); + if ( p->vLines ) + Vec_PtrFree( p->vLines ); + if ( p->vModels ) + { + Vec_PtrForEachEntry( p->vModels, pMod, i ) + Io_MvModFree( pMod ); + Vec_PtrFree( p->vModels ); + } + Vec_PtrFree( p->vTokens ); + Vec_PtrFree( p->vTokens2 ); + Vec_StrFree( p->vFunc ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure for one model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Io_MvMod_t * Io_MvModAlloc() +{ + Io_MvMod_t * p; + p = ALLOC( Io_MvMod_t, 1 ); + memset( p, 0, sizeof(Io_MvMod_t) ); + p->vInputs = Vec_PtrAlloc( 512 ); + p->vOutputs = Vec_PtrAlloc( 512 ); + p->vLatches = Vec_PtrAlloc( 512 ); + p->vResets = Vec_PtrAlloc( 512 ); + p->vNames = Vec_PtrAlloc( 512 ); + p->vSubckts = Vec_PtrAlloc( 512 ); + p->vMvs = Vec_PtrAlloc( 512 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates the BLIF parsing structure for one model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvModFree( Io_MvMod_t * p ) +{ +// if ( p->pNtk ) +// Abc_NtkDelete( p->pNtk ); + Vec_PtrFree( p->vInputs ); + Vec_PtrFree( p->vOutputs ); + Vec_PtrFree( p->vLatches ); + Vec_PtrFree( p->vResets ); + Vec_PtrFree( p->vNames ); + Vec_PtrFree( p->vSubckts ); + Vec_PtrFree( p->vMvs ); + free( p ); +} + + + +/**Function************************************************************* + + Synopsis [Counts the number of given chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvCountChars( char * pLine, char Char ) +{ + char * pCur; + int Counter = 0; + for ( pCur = pLine; *pCur; pCur++ ) + if ( *pCur == Char ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the place where the arrow is hiding.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvFindArrow( char * pLine ) +{ + char * pCur; + for ( pCur = pLine; *(pCur+1); pCur++ ) + if ( *pCur == '-' && *(pCur+1) == '>' ) + { + *pCur = ' '; + *(pCur+1) = ' '; + return pCur; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Collects the already split tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput ) +{ + char * pCur; + Vec_PtrClear( vTokens ); + for ( pCur = pInput; pCur < pOutput; pCur++ ) + { + if ( *pCur == 0 ) + continue; + Vec_PtrPush( vTokens, pCur ); + while ( *++pCur ); + } +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != Stop; pCur++ ) + if ( Io_MvCharIsSpace(*pCur) ) + *pCur = 0; + // collect tokens + Io_MvCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens when .default may be present.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvSplitIntoTokensMv( Vec_Ptr_t * vTokens, char * pLine ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != '.' || *(pCur+1) == 'd'; pCur++ ) + if ( Io_MvCharIsSpace(*pCur) ) + *pCur = 0; + // collect tokens + Io_MvCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Splits the line into tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char ) +{ + char * pCur; + // clear spaces + for ( pCur = pLine; *pCur != Stop; pCur++ ) + if ( Io_MvCharIsSpace(*pCur) || *pCur == Char ) + *pCur = 0; + // collect tokens + Io_MvCollectTokens( vTokens, pLine, pCur ); +} + +/**Function************************************************************* + + Synopsis [Returns the 1-based number of the line in which the token occurs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvGetLine( Io_MvMan_t * p, char * pToken ) +{ + char * pLine; + int i; + Vec_PtrForEachEntry( p->vLines, pLine, i ) + if ( pToken < pLine ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Reads the file into a character buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvLoadFile( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + char * pContents; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Io_MvLoadFile(): The file is unavailable (absent or open).\n" ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + if ( nFileSize == 0 ) + { + printf( "Io_MvLoadFile(): The file is empty.\n" ); + return NULL; + } + pContents = ALLOC( char, nFileSize + 10 ); + rewind( pFile ); + fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + // finish off the file with the spare .end line + // some benchmarks suddenly break off without this line + strcpy( pContents + nFileSize, "\n.end\n" ); + return pContents; +} + +/**Function************************************************************* + + Synopsis [Prepares the parsing.] + + Description [Performs several preliminary operations: + - Cuts the file buffer into separate lines. + - Removes comments and line extenders. + - Sorts lines by directives. + - Estimates the number of objects. + - Allocates room for the objects. + - Allocates room for the hash table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvReadPreparse( Io_MvMan_t * p ) +{ + char * pCur, * pPrev; + int i, fComment = 0; + // parse the buffer into lines and remove comments + Vec_PtrPush( p->vLines, p->pBuffer ); + for ( pCur = p->pBuffer; *pCur; pCur++ ) + { + if ( *pCur == '\n' ) + { + *pCur = 0; +// if ( *(pCur-1) == '\r' ) +// *(pCur-1) = 0; + fComment = 0; + Vec_PtrPush( p->vLines, pCur + 1 ); + } + else if ( *pCur == '#' ) + fComment = 1; + // remove comments + if ( fComment ) + *pCur = 0; + } + + // unfold the line extensions and sort lines by directive + Vec_PtrForEachEntry( p->vLines, pCur, i ) + { + if ( *pCur == 0 ) + continue; + // find previous non-space character + for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- ) + if ( !Io_MvCharIsSpace(*pPrev) ) + break; + // if it is the line extender, overwrite it with spaces + if ( *pPrev == '\\' ) + { + for ( ; *pPrev; pPrev++ ) + *pPrev = ' '; + *pPrev = ' '; + continue; + } + // skip spaces at the beginning of the line + while ( Io_MvCharIsSpace(*pCur++) ); + // parse directives + if ( *(pCur-1) != '.' ) + continue; + if ( !strncmp(pCur, "names", 5) || !strncmp(pCur, "table", 5) || !strncmp(pCur, "gate", 4) ) + Vec_PtrPush( p->pLatest->vNames, pCur ); + else if ( p->fBlifMv && (!strncmp(pCur, "def ", 4) || !strncmp(pCur, "default ", 8)) ) + continue; + else if ( !strncmp(pCur, "latch", 5) ) + Vec_PtrPush( p->pLatest->vLatches, pCur ); + else if ( !strncmp(pCur, "r ", 2) || !strncmp(pCur, "reset ", 6) ) + Vec_PtrPush( p->pLatest->vResets, pCur ); + else if ( !strncmp(pCur, "inputs", 6) ) + Vec_PtrPush( p->pLatest->vInputs, pCur ); + else if ( !strncmp(pCur, "outputs", 7) ) + Vec_PtrPush( p->pLatest->vOutputs, pCur ); + else if ( !strncmp(pCur, "subckt", 6) ) + Vec_PtrPush( p->pLatest->vSubckts, pCur ); + else if ( p->fBlifMv && !strncmp(pCur, "mv", 2) ) + Vec_PtrPush( p->pLatest->vMvs, pCur ); + else if ( !strncmp(pCur, "blackbox", 8) ) + p->pLatest->fBlackBox = 1; + else if ( !strncmp(pCur, "model", 5) ) + { + p->pLatest = Io_MvModAlloc(); + p->pLatest->pName = pCur; + p->pLatest->pMan = p; + } + else if ( !strncmp(pCur, "end", 3) ) + { + if ( p->pLatest ) + Vec_PtrPush( p->vModels, p->pLatest ); + p->pLatest = NULL; + } + else if ( !strncmp(pCur, "exdc", 4) ) + { + fprintf( stdout, "Line %d: Skipping EXDC network.\n", Io_MvGetLine(p, pCur) ); + break; + } + else + { + pCur--; + if ( pCur[strlen(pCur)-1] == '\r' ) + pCur[strlen(pCur)-1] = 0; + fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_MvGetLine(p, pCur), pCur ); + } + } +} + +/**Function************************************************************* + + Synopsis [Parses interfaces of the models.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Io_MvReadInterfaces( Io_MvMan_t * p ) +{ + Io_MvMod_t * pMod; + char * pLine; + int i, k; + // iterate through the models + Vec_PtrForEachEntry( p->vModels, pMod, i ) + { + // parse the model + if ( !Io_MvParseLineModel( pMod, pMod->pName ) ) + return; + // add model to the design + if ( !Abc_LibAddModel( p->pDesign, pMod->pNtk ) ) + { + sprintf( p->sError, "Line %d: Model %s is defined twice.", Io_MvGetLine(p, pMod->pName), pMod->pName ); + return; + } + // parse the inputs + Vec_PtrForEachEntry( pMod->vInputs, pLine, k ) + if ( !Io_MvParseLineInputs( pMod, pLine ) ) + return; + // parse the outputs + Vec_PtrForEachEntry( pMod->vOutputs, pLine, k ) + if ( !Io_MvParseLineOutputs( pMod, pLine ) ) + return; + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p ) +{ + Abc_Lib_t * pDesign; + Io_MvMod_t * pMod; + char * pLine; + int i, k; + // iterate through the models + Vec_PtrForEachEntry( p->vModels, pMod, i ) + { + // check if there any MV lines + if ( Vec_PtrSize(pMod->vMvs) > 0 ) + Abc_NtkStartMvVars( pMod->pNtk ); + // parse the mv lines + Vec_PtrForEachEntry( pMod->vMvs, pLine, k ) + if ( !Io_MvParseLineMv( pMod, pLine ) ) + return NULL; + // if reset lines are used there should be the same number of them as latches + if ( Vec_PtrSize(pMod->vResets) > 0 ) + { + if ( Vec_PtrSize(pMod->vLatches) != Vec_PtrSize(pMod->vResets) ) + { + sprintf( p->sError, "Line %d: Model %s has different number of latches (%d) and reset nodes (%d).", + Io_MvGetLine(p, pMod->pName), Abc_NtkName(pMod->pNtk), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vResets) ); + return NULL; + } + // create binary latch with 1-data and 0-init + if ( p->fUseReset ) + pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv ); + } + // parse the latches + Vec_PtrForEachEntry( pMod->vLatches, pLine, k ) + if ( !Io_MvParseLineLatch( pMod, pLine ) ) + return NULL; + // parse the reset lines + if ( p->fUseReset ) + Vec_PtrForEachEntry( pMod->vResets, pLine, k ) + if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) ) + return NULL; + // parse the nodes + if ( p->fBlifMv ) + { + Vec_PtrForEachEntry( pMod->vNames, pLine, k ) + if ( !Io_MvParseLineNamesMv( pMod, pLine, 0 ) ) + return NULL; + } + else + { + Vec_PtrForEachEntry( pMod->vNames, pLine, k ) + if ( !Io_MvParseLineNamesBlif( pMod, pLine ) ) + return NULL; + } + // parse the subcircuits + Vec_PtrForEachEntry( pMod->vSubckts, pLine, k ) + if ( !Io_MvParseLineSubckt( pMod, pLine ) ) + return NULL; + // finalize the network + Abc_NtkFinalizeRead( pMod->pNtk ); + } + if ( p->nNDnodes ) +// printf( "Warning: The parser added %d PIs to replace non-deterministic nodes.\n", p->nNDnodes ); + printf( "Warning: The parser added %d constant 0 nodes to replace non-deterministic nodes.\n", p->nNDnodes ); + // return the network + pDesign = p->pDesign; + p->pDesign = NULL; + return pDesign; +} + +/**Function************************************************************* + + Synopsis [Parses the model line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry( vTokens, 0 ); + assert( !strcmp(pToken, "model") ); + if ( Vec_PtrSize(vTokens) != 2 ) + { + sprintf( p->pMan->sError, "Line %d: Model line has %d entries while it should have 2.", Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) ); + return 0; + } + if ( p->fBlackBox ) + p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, 1 ); + else if ( p->pMan->fBlifMv ) + p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLIFMV, 1 ); + else + p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); + p->pNtk->pName = Extra_UtilStrsav( Vec_PtrEntry(vTokens, 1) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the inputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + int i; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens, 0); + assert( !strcmp(pToken, "inputs") ); + Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) + Io_ReadCreatePi( p->pNtk, pToken ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the outputs line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + char * pToken; + int i; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens, 0); + assert( !strcmp(pToken, "outputs") ); + Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) + Io_ReadCreatePo( p->pNtk, pToken ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the latches line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Obj_t * pObj, * pNet; + char * pToken; + int Init; + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + pToken = Vec_PtrEntry(vTokens,0); + assert( !strcmp(pToken, "latch") ); + if ( Vec_PtrSize(vTokens) < 3 ) + { + sprintf( p->pMan->sError, "Line %d: Latch does not have input name and output name.", Io_MvGetLine(p->pMan, pToken) ); + return 0; + } + // create latch + if ( p->pResetLatch == NULL ) + { + pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Vec_PtrEntry(vTokens,2) ); + // get initial value + if ( p->pMan->fBlifMv ) + Abc_LatchSetInit0( pObj ); + else + { + if ( Vec_PtrSize(vTokens) > 3 ) + Init = atoi( Vec_PtrEntry(vTokens,3) ); + else + Init = 2; + if ( Init < 0 || Init > 2 ) + { + sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) ); + return 0; + } + if ( Init == 0 ) + Abc_LatchSetInit0( pObj ); + else if ( Init == 1 ) + Abc_LatchSetInit1( pObj ); + else // if ( Init == 2 ) + Abc_LatchSetInitDc( pObj ); + } + } + else + { + // get the net corresponding to the output of the latch + pNet = Abc_NtkFindOrCreateNet( p->pNtk, Vec_PtrEntry(vTokens,2) ); + // get the net corresponding to the latch output (feeding into reset MUX) + pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") ); + // create latch + pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) ); + Abc_LatchSetInit0( pObj ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the subckt line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Ntk_t * pModel; + Abc_Obj_t * pBox, * pNet, * pTerm; + char * pToken, * pName, ** ppNames; + int nEquals, i, k; + + // split the line into tokens + nEquals = Io_MvCountChars( pLine, '=' ); + Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' ); + pToken = Vec_PtrEntry(vTokens,0); + assert( !strcmp(pToken, "subckt") ); + + // get the model for this box + pName = Vec_PtrEntry(vTokens,1); + pModel = Abc_LibFindModelByName( p->pMan->pDesign, pName ); + if ( pModel == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Io_MvGetLine(p->pMan, pToken), pName ); + return 0; + } + + // check if the number of tokens is correct + if ( nEquals != Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) ) + { + sprintf( p->pMan->sError, "Line %d: The number of ports (%d) in .subckt differs from the sum of PIs and POs of the model (%d).", + Io_MvGetLine(p->pMan, pToken), nEquals, Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) ); + return 0; + } + + // get the names + ppNames = (char **)Vec_PtrArray(vTokens) + 2 + p->pMan->fBlifMv; + + // create the box with these terminals + if ( Abc_NtkHasBlackbox(pModel) ) + pBox = Abc_NtkCreateBlackbox( p->pNtk ); + else + pBox = Abc_NtkCreateWhitebox( p->pNtk ); + pBox->pData = pModel; + if ( p->pMan->fBlifMv ) + Abc_ObjAssignName( pBox, Vec_PtrEntry(vTokens,2), NULL ); + Abc_NtkForEachPi( pModel, pTerm, i ) + { + // find this terminal among the formal inputs of the subcircuit + pName = Abc_ObjName(Abc_ObjFanout0(pTerm)); + for ( k = 0; k < nEquals; k++ ) + if ( !strcmp( ppNames[2*k], pName ) ) + break; + if ( k == nEquals ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.", + Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) ); + return 0; + } + // create the BI with the actual name + pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); + pTerm = Abc_NtkCreateBi( p->pNtk ); + Abc_ObjAddFanin( pBox, pTerm ); + Abc_ObjAddFanin( pTerm, pNet ); + } + Abc_NtkForEachPo( pModel, pTerm, i ) + { + // find this terminal among the formal outputs of the subcircuit + pName = Abc_ObjName(Abc_ObjFanin0(pTerm)); + for ( k = 0; k < nEquals; k++ ) + if ( !strcmp( ppNames[2*k], pName ) ) + break; + if ( k == nEquals ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find PO \"%s\" of the modell \"%s\" as a formal output of the subcircuit.", + Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) ); + return 0; + } + // create the BI with the actual name + pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); + pTerm = Abc_NtkCreateBo( p->pNtk ); + Abc_ObjAddFanin( pNet, pTerm ); + Abc_ObjAddFanin( pTerm, pBox ); + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Parses the mv line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Obj_t * pObj; + Io_MvVar_t * pVar; + Extra_MmFlex_t * pFlex; + char * pName; + int nCommas, nValues, i, k; + // count commas and get the tokens + nCommas = Io_MvCountChars( pLine, ',' ); + Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', ',' ); + pName = Vec_PtrEntry(vTokens,0); + assert( !strcmp(pName, "mv") ); + // get the number of values + if ( Vec_PtrSize(vTokens) <= nCommas + 2 ) + { + sprintf( p->pMan->sError, "Line %d: The number of values in not specified in .mv line.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } + nValues = atoi( Vec_PtrEntry(vTokens,nCommas+2) ); + if ( nValues < 2 || nValues > IO_BLIFMV_MAXVALUES ) + { + sprintf( p->pMan->sError, "Line %d: The number of values (%d) is incorrect (should be >= 2 and <= %d).", + Io_MvGetLine(p->pMan, pName), nValues, IO_BLIFMV_MAXVALUES ); + return 0; + } + // if there is no symbolic values, quit + if ( nValues == 2 && Vec_PtrSize(vTokens) == nCommas + 3 ) + return 1; + if ( Vec_PtrSize(vTokens) > nCommas + 3 && Vec_PtrSize(vTokens) - (nCommas + 3) != nValues ) + { + sprintf( p->pMan->sError, "Line %d: Wrong number (%d) of symbolic value names (should be %d).", + Io_MvGetLine(p->pMan, pName), Vec_PtrSize(vTokens) - (nCommas + 3), nValues ); + return 0; + } + // go through variables + pFlex = Abc_NtkMvVarMan( p->pNtk ); + for ( i = 0; i <= nCommas; i++ ) + { + pName = Vec_PtrEntry( vTokens, i+1 ); + pObj = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + // allocate variable + pVar = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) ); + pVar->nValues = nValues; + pVar->pNames = NULL; + // create names + if ( Vec_PtrSize(vTokens) > nCommas + 3 ) + { + pVar->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * nValues ); + Vec_PtrForEachEntryStart( vTokens, pName, k, nCommas + 3 ) + { + pVar->pNames[k-(nCommas + 3)] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pName) + 1 ); + strcpy( pVar->pNames[k-(nCommas + 3)], pName ); + } + } + // save the variable + Abc_ObjSetMvVar( pObj, pVar ); + } + // make sure the names are unique + if ( pVar->pNames ) + { + for ( i = 0; i < nValues; i++ ) + for ( k = i+1; k < nValues; k++ ) + if ( !strcmp(pVar->pNames[i], pVar->pNames[k]) ) + { + pName = Vec_PtrEntry(vTokens,0); + sprintf( p->pMan->sError, "Line %d: Symbolic value name \"%s\" is repeated in .mv line.", + Io_MvGetLine(p->pMan, pName), pVar->pNames[i] ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the values into the BLIF-MV representation for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvWriteValues( Abc_Obj_t * pNode, Vec_Str_t * vFunc ) +{ + char Buffer[10]; + Abc_Obj_t * pFanin; + int i; + // add the fanin number of values + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + sprintf( Buffer, "%d", Abc_ObjMvVarNum(pFanin) ); + Vec_StrAppend( vFunc, Buffer ); + Vec_StrPush( vFunc, ' ' ); + } + // add the node number of values + sprintf( Buffer, "%d", Abc_ObjMvVarNum(Abc_ObjFanout0(pNode)) ); + Vec_StrAppend( vFunc, Buffer ); + Vec_StrPush( vFunc, '\n' ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Translated one literal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLiteralMv( Io_MvMod_t * p, Abc_Obj_t * pNode, char * pToken, Vec_Str_t * vFunc, int iLit ) +{ + char Buffer[10]; + Io_MvVar_t * pVar; + Abc_Obj_t * pFanin, * pNet; + char * pCur, * pNext; + int i; + // consider the equality literal + if ( pToken[0] == '=' ) + { + // find the fanins + Abc_ObjForEachFanin( pNode, pFanin, i ) + if ( !strcmp( Abc_ObjName(pFanin), pToken + 1 ) ) + break; + if ( i == Abc_ObjFaninNum(pNode) ) + { + sprintf( p->pMan->sError, "Line %d: Node name in the table \"%s\" cannot be found on .names line.", + Io_MvGetLine(p->pMan, pToken), pToken + 1 ); + return 0; + } + Vec_StrPush( vFunc, '=' ); + sprintf( Buffer, "%d", i ); + Vec_StrAppend( vFunc, Buffer ); + Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); + return 1; + } + // consider regular literal + assert( iLit < Abc_ObjFaninNum(pNode) ); + pNet = iLit >= 0 ? Abc_ObjFanin(pNode, iLit) : Abc_ObjFanout0(pNode); + pVar = Abc_ObjMvVar( pNet ); + // if the var is absent or has no symbolic values quit + if ( pVar == NULL || pVar->pNames == NULL ) + { + Vec_StrAppend( vFunc, pToken ); + Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); + return 1; + } + // parse the literal using symbolic values + for ( pCur = pToken; *pCur; pCur++ ) + { + if ( Io_MvCharIsMvSymb(*pCur) ) + { + Vec_StrPush( vFunc, *pCur ); + continue; + } + // find the next MvSymb char + for ( pNext = pCur+1; *pNext; pNext++ ) + if ( Io_MvCharIsMvSymb(*pNext) ) + break; + // look for the value name + for ( i = 0; i < pVar->nValues; i++ ) + if ( !strncmp( pVar->pNames[i], pCur, pNext-pCur ) ) + break; + if ( i == pVar->nValues ) + { + *pNext = 0; + sprintf( p->pMan->sError, "Line %d: Cannot find value name \"%s\" among the value names of variable \"%s\".", + Io_MvGetLine(p->pMan, pToken), pCur, Abc_ObjName(pNet) ); + return 0; + } + // value name is found + sprintf( Buffer, "%d", i ); + Vec_StrAppend( vFunc, Buffer ); + // update the pointer + pCur = pNext - 1; + } + Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Constructs the MV-SOP cover from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut ) +{ + Vec_Str_t * vFunc = p->pMan->vFunc; + char * pFirst, * pToken; + int iStart, i; + // prepare the place for the cover + Vec_StrClear( vFunc ); + // write the number of values +// Io_MvWriteValues( pNode, vFunc ); + // get the first token + pFirst = Vec_PtrEntry( vTokens2, 0 ); + if ( pFirst[0] == '.' ) + { + // write the default literal + Vec_StrPush( vFunc, 'd' ); + pToken = Vec_PtrEntry(vTokens2, 1 + iOut); + if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) ) + return NULL; + iStart = 1 + nOutputs; + } + else + iStart = 0; + // write the remaining literals + while ( iStart < Vec_PtrSize(vTokens2) ) + { + // input literals + for ( i = 0; i < nInputs; i++ ) + { + pToken = Vec_PtrEntry( vTokens2, iStart + i ); + if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, i ) ) + return NULL; + } + // output literal + pToken = Vec_PtrEntry( vTokens2, iStart + nInputs + iOut ); + if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) ) + return NULL; + // update the counter + iStart += nInputs + nOutputs; + } + Vec_StrPush( vFunc, '\0' ); + return Vec_StrArray( vFunc ); +} + +/**Function************************************************************* + + Synopsis [Adds reset circuitry corresponding to latch with pName.] + + Description [Returns the reset node's net.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Abc_Obj_t * Io_MvParseAddResetCircuit( Io_MvMod_t * p, char * pName ) +{ + char Buffer[50]; + Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pOutNet; + Io_MvVar_t * pVar; + // make sure the reset latch exists + assert( p->pResetLatch != NULL ); + // get the reset net + pResetLONet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch)); + // get the output net + pOutNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + // get the data nets + pData0Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_reset") ); + pData1Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_out") ); + // duplicate MV variables + if ( Abc_NtkMvVar(p->pNtk) ) + { + pVar = Abc_ObjMvVar( pOutNet ); + Abc_ObjSetMvVar( pData0Net, Abc_NtkMvVarDup(p->pNtk, pVar) ); + Abc_ObjSetMvVar( pData1Net, Abc_NtkMvVarDup(p->pNtk, pVar) ); + } + // create the node + pNode = Abc_NtkCreateNode( p->pNtk ); + // create the output net + Abc_ObjAddFanin( pOutNet, pNode ); + // create the function + if ( p->pMan->fBlifMv ) + { +// Vec_Att_t * p = Abc_NtkMvVar( pNtk ); + int nValues = Abc_ObjMvVarNum(pOutNet); +// sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues ); + sprintf( Buffer, "1 - - =1\n0 - - =2\n" ); + pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, Buffer ); + } + else + pNode->pData = Abc_SopCreateMux( p->pNtk->pManFunc ); + // add nets + Abc_ObjAddFanin( pNode, pResetLONet ); + Abc_ObjAddFanin( pNode, pData1Net ); + Abc_ObjAddFanin( pNode, pData0Net ); + return pData0Net; +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineNamesMvOne( Io_MvMod_t * p, Vec_Ptr_t * vTokens, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut, int fReset ) +{ + Abc_Obj_t * pNet, * pNode; + char * pName; + // get the output name + pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + iOut ); + // create the node + if ( fReset ) + { + pNet = Abc_NtkFindNet( p->pNtk, pName ); + if ( pNet == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Latch with output signal \"%s\" does not exist.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } +/* + if ( !Abc_ObjIsBo(Abc_ObjFanin0(pNet)) ) + { + sprintf( p->pMan->sError, "Line %d: Reset line \"%s\" defines signal that is not a latch output.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } +*/ + // construct the reset circuit and get the reset net feeding into it + pNet = Io_MvParseAddResetCircuit( p, pName ); + // create fanins + pNode = Io_ReadCreateNode( p->pNtk, Abc_ObjName(pNet), (char **)(vTokens->pArray + 1), nInputs ); + assert( nInputs == Vec_PtrSize(vTokens) - 2 ); + } + else + { + pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + if ( Abc_ObjFaninNum(pNet) > 0 ) + { + sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } + pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), nInputs ); + } + // create the cover + pNode->pData = Io_MvParseTableMv( p, pNode, vTokens2, nInputs, nOutputs, iOut ); + if ( pNode->pData == NULL ) + return 0; + pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData ); +//printf( "Finished parsing node \"%s\" with table:\n%s\n", pName, pNode->pData ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Vec_Ptr_t * vTokens2 = p->pMan->vTokens2; + Abc_Obj_t * pNet; + char * pName, * pFirst, * pArrow; + int nInputs, nOutputs, nLiterals, nLines, i; + assert( p->pMan->fBlifMv ); + // get the arrow if it is present + pArrow = Io_MvFindArrow( pLine ); + if ( !p->pMan->fBlifMv && pArrow ) + { + sprintf( p->pMan->sError, "Line %d: Multi-output node symbol (->) in binary BLIF file.", Io_MvGetLine(p->pMan, pLine) ); + return 0; + } + // split names line into tokens + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + if ( fReset ) + assert( !strcmp(Vec_PtrEntry(vTokens,0), "r") || !strcmp(Vec_PtrEntry(vTokens,0), "reset") ); + else + assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") || !strcmp(Vec_PtrEntry(vTokens,0), "table") ); + // find the number of inputs and outputs + nInputs = Vec_PtrSize(vTokens) - 2; + nOutputs = 1; + if ( pArrow != NULL ) + { + for ( i = Vec_PtrSize(vTokens) - 2; i >= 1; i-- ) + if ( pArrow < (char*)Vec_PtrEntry(vTokens,i) ) + { + nInputs--; + nOutputs++; + } + } + // split table into tokens + pName = Vec_PtrEntryLast( vTokens ); + Io_MvSplitIntoTokensMv( vTokens2, pName + strlen(pName) ); + pFirst = Vec_PtrEntry( vTokens2, 0 ); + if ( pFirst[0] == '.' ) + { + assert( pFirst[1] == 'd' ); + nLiterals = Vec_PtrSize(vTokens2) - 1 - nOutputs; + } + else + nLiterals = Vec_PtrSize(vTokens2); + // check the number of lines + if ( nLiterals % (nInputs + nOutputs) != 0 ) + { + sprintf( p->pMan->sError, "Line %d: Wrong number of literals in the table of node \"%s\". (Spaces inside literals are not allowed.)", Io_MvGetLine(p->pMan, pFirst), pName ); + return 0; + } + // check for the ND table + nLines = nLiterals / (nInputs + nOutputs); + if ( nInputs == 0 && nLines > 1 ) + { + // add the outputs to the PIs + for ( i = 0; i < nOutputs; i++ ) + { + pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + i ); + // get the net corresponding to this node + pNet = Abc_NtkFindOrCreateNet(p->pNtk, pName); + if ( fReset ) + { + assert( p->pResetLatch != NULL ); + // construct the reset circuit and get the reset net feeding into it + pNet = Io_MvParseAddResetCircuit( p, pName ); + } + // add the new PI node +// Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) ); +// fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName ); + p->pMan->nNDnodes++; + Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(p->pNtk) ); + } + return 1; + } + // iterate through the outputs + for ( i = 0; i < nOutputs; i++ ) + { + if ( !Io_MvParseLineNamesMvOne( p, vTokens, vTokens2, nInputs, nOutputs, i, fReset ) ) + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Constructs the SOP cover from the file parsing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_MvParseTableBlif( Io_MvMod_t * p, char * pTable, int nFanins ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Vec_Str_t * vFunc = p->pMan->vFunc; + char * pProduct, * pOutput; + int i, Polarity = -1; + + p->pMan->nTablesRead++; + // get the tokens + Io_MvSplitIntoTokens( vTokens, pTable, '.' ); + if ( Vec_PtrSize(vTokens) == 0 ) + return Abc_SopCreateConst0( p->pNtk->pManFunc ); + if ( Vec_PtrSize(vTokens) == 1 ) + { + pOutput = Vec_PtrEntry( vTokens, 0 ); + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Io_MvGetLine(p->pMan, pOutput), pOutput ); + return NULL; + } + return pOutput[0] == '0' ? Abc_SopCreateConst0(p->pNtk->pManFunc) : Abc_SopCreateConst1(p->pNtk->pManFunc); + } + pProduct = Vec_PtrEntry( vTokens, 0 ); + if ( Vec_PtrSize(vTokens) % 2 == 1 ) + { + sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Io_MvGetLine(p->pMan, pProduct), Vec_PtrSize(vTokens) ); + return NULL; + } + // parse the table + Vec_StrClear( vFunc ); + for ( i = 0; i < Vec_PtrSize(vTokens)/2; i++ ) + { + pProduct = Vec_PtrEntry( vTokens, 2*i + 0 ); + pOutput = Vec_PtrEntry( vTokens, 2*i + 1 ); + if ( strlen(pProduct) != (unsigned)nFanins ) + { + sprintf( p->pMan->sError, "Line %d: Cube \"%s\" has size different from the fanin count (%d).", Io_MvGetLine(p->pMan, pProduct), pProduct, nFanins ); + return NULL; + } + if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) + { + sprintf( p->pMan->sError, "Line %d: Output value \"%s\" is incorrect.", Io_MvGetLine(p->pMan, pProduct), pOutput ); + return NULL; + } + if ( Polarity == -1 ) + Polarity = pOutput[0] - '0'; + else if ( Polarity != pOutput[0] - '0' ) + { + sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Io_MvGetLine(p->pMan, pProduct), pOutput, Polarity ); + return NULL; + } + // parse one product + Vec_StrAppend( vFunc, pProduct ); + Vec_StrPush( vFunc, ' ' ); + Vec_StrPush( vFunc, pOutput[0] ); + Vec_StrPush( vFunc, '\n' ); + } + Vec_StrPush( vFunc, '\0' ); + return Vec_StrArray( vFunc ); +} + +/**Function************************************************************* + + Synopsis [Parses the nodes line.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine ) +{ + Vec_Ptr_t * vTokens = p->pMan->vTokens; + Abc_Obj_t * pNet, * pNode; + char * pName; + assert( !p->pMan->fBlifMv ); + Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); + // parse the mapped node + if ( !strcmp(Vec_PtrEntry(vTokens,0), "gate") ) + return Io_MvParseLineGateBlif( p, vTokens ); + // parse the regular name line + assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") ); + pName = Vec_PtrEntryLast( vTokens ); + pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); + if ( Abc_ObjFaninNum(pNet) > 0 ) + { + sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName ); + return 0; + } + // create fanins + pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), Vec_PtrSize(vTokens) - 2 ); + // parse the table of this node + pNode->pData = Io_MvParseTableBlif( p, pName + strlen(pName), Abc_ObjFaninNum(pNode) ); + if ( pNode->pData == NULL ) + return 0; + pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Duplicate the MV variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar ) +{ + Extra_MmFlex_t * pFlex; + Io_MvVar_t * pVarDup; + int i; + if ( pVar == NULL ) + return NULL; + pFlex = Abc_NtkMvVarMan( pNtk ); + assert( pFlex != NULL ); + pVarDup = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) ); + pVarDup->nValues = pVar->nValues; + pVarDup->pNames = NULL; + if ( pVar->pNames == NULL ) + return pVarDup; + pVarDup->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * pVar->nValues ); + for ( i = 0; i < pVar->nValues; i++ ) + { + pVarDup->pNames[i] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pVar->pNames[i]) + 1 ); + strcpy( pVarDup->pNames[i], pVar->pNames[i] ); + } + return pVarDup; +} + + +#include "mio.h" +#include "main.h" + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static char * Io_ReadBlifCleanName( char * pName ) +{ + int i, Length; + Length = strlen(pName); + for ( i = 0; i < Length; i++ ) + if ( pName[i] == '=' ) + return pName + i + 1; + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens ) +{ + Mio_Library_t * pGenlib; + Mio_Gate_t * pGate; + Abc_Obj_t * pNode; + char ** ppNames, * pName; + int i, nNames; + + pName = vTokens->pArray[0]; + + // check that the library is available + pGenlib = Abc_FrameReadLibGen(); + if ( pGenlib == NULL ) + { + sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) ); + return 0; + } + + // create a new node and add it to the network + if ( vTokens->nSize < 2 ) + { + sprintf( p->pMan->sError, "Line %d: The .gate line has less than two tokens.", Io_MvGetLine(p->pMan, pName) ); + return 0; + } + + // get the gate + pGate = Mio_LibraryReadGateByName( pGenlib, vTokens->pArray[1] ); + if ( pGate == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Cannot find gate \"%s\" in the library.", Io_MvGetLine(p->pMan, pName), vTokens->pArray[1] ); + return 0; + } + + // if this is the first line with gate, update the network type + if ( Abc_NtkNodeNum(p->pNtk) == 0 ) + { + assert( p->pNtk->ntkFunc == ABC_FUNC_SOP ); + p->pNtk->ntkFunc = ABC_FUNC_MAP; + Extra_MmFlexStop( p->pNtk->pManFunc ); + p->pNtk->pManFunc = pGenlib; + } + + // remove the formal parameter names + for ( i = 2; i < vTokens->nSize; i++ ) + { + vTokens->pArray[i] = Io_ReadBlifCleanName( vTokens->pArray[i] ); + if ( vTokens->pArray[i] == NULL ) + { + sprintf( p->pMan->sError, "Line %d: Invalid gate input assignment.", Io_MvGetLine(p->pMan, pName) ); + return 0; + } + } + + // create the node + ppNames = (char **)vTokens->pArray + 2; + nNames = vTokens->nSize - 3; + pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames ); + + // set the pointer to the functionality of the node + Abc_ObjSetData( pNode, pGate ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioReadDsd.c b/abc70930/src/base/io/ioReadDsd.c new file mode 100644 index 00000000..1ab726e5 --- /dev/null +++ b/abc70930/src/base/io/ioReadDsd.c @@ -0,0 +1,308 @@ +/**CFile**************************************************************** + + FileName [ioReadDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Finds the end of the part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_ReadDsdFindEnd( char * pCur ) +{ + char * pEnd; + int nParts = 0; + assert( *pCur == '(' ); + for ( pEnd = pCur; *pEnd; pEnd++ ) + { + if ( *pEnd == '(' ) + nParts++; + else if ( *pEnd == ')' ) + nParts--; + if ( nParts == 0 ) + return pEnd; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Splits the formula into parts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadDsdStrSplit( char * pCur, char * pParts[], int * pTypeXor ) +{ + int fAnd = 0, fXor = 0, fPri = 0, nParts = 0; + assert( *pCur ); + // process the parts + while ( 1 ) + { + // save the current part + pParts[nParts++] = pCur; + // skip the complement + if ( *pCur == '!' ) + pCur++; + // skip var + if ( *pCur >= 'a' && *pCur <= 'z' ) + pCur++; + else + { + // skip hex truth table + while ( (*pCur >= '0' && *pCur <= '9') || (*pCur >= 'A' && *pCur <= 'F') ) + pCur++; + // process parantheses + if ( *pCur != '(' ) + { + printf( "Cannot find the opening paranthesis.\n" ); + break; + } + // find the corresponding closing paranthesis + pCur = Io_ReadDsdFindEnd( pCur ); + if ( pCur == NULL ) + { + printf( "Cannot find the closing paranthesis.\n" ); + break; + } + pCur++; + } + // check the end + if ( *pCur == 0 ) + break; + // check symbol + if ( *pCur != '*' && *pCur != '+' && *pCur != ',' ) + { + printf( "Wrong separating symbol.\n" ); + break; + } + // remember the symbol + fAnd |= (*pCur == '*'); + fXor |= (*pCur == '+'); + fPri |= (*pCur == ','); + *pCur++ = 0; + } + // check separating symbols + if ( fAnd + fXor + fPri > 1 ) + { + printf( "Different types of separating symbol ennPartsed.\n" ); + return 0; + } + *pTypeXor = fXor; + return nParts; +} + +/**Function************************************************************* + + Synopsis [Recursively parses the formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadDsd_rec( Abc_Ntk_t * pNtk, char * pCur, char * pSop ) +{ + Abc_Obj_t * pObj, * pFanin; + char * pEnd, * pParts[32]; + int i, nParts, TypeExor; + + // consider complemented formula + if ( *pCur == '!' ) + { + pObj = Io_ReadDsd_rec( pNtk, pCur + 1, NULL ); + return Abc_NtkCreateNodeInv( pNtk, pObj ); + } + if ( *pCur == '(' ) + { + assert( pCur[strlen(pCur)-1] == ')' ); + pCur[strlen(pCur)-1] = 0; + nParts = Io_ReadDsdStrSplit( pCur+1, pParts, &TypeExor ); + if ( nParts == 0 ) + { + Abc_NtkDelete( pNtk ); + return NULL; + } + pObj = Abc_NtkCreateNode( pNtk ); + if ( pSop ) + { +// for ( i = nParts - 1; i >= 0; i-- ) + for ( i = 0; i < nParts; i++ ) + { + pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL ); + if ( pFanin == NULL ) + return NULL; + Abc_ObjAddFanin( pObj, pFanin ); + } + } + else + { + for ( i = 0; i < nParts; i++ ) + { + pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL ); + if ( pFanin == NULL ) + return NULL; + Abc_ObjAddFanin( pObj, pFanin ); + } + } + if ( pSop ) + pObj->pData = Abc_SopRegister( pNtk->pManFunc, pSop ); + else if ( TypeExor ) + pObj->pData = Abc_SopCreateXorSpecial( pNtk->pManFunc, nParts ); + else + pObj->pData = Abc_SopCreateAnd( pNtk->pManFunc, nParts, NULL ); + return pObj; + } + if ( *pCur >= 'a' && *pCur <= 'z' ) + { + assert( *(pCur+1) == 0 ); + return Abc_NtkPi( pNtk, *pCur - 'a' ); + } + + // skip hex truth table + pEnd = pCur; + while ( (*pEnd >= '0' && *pEnd <= '9') || (*pEnd >= 'A' && *pEnd <= 'F') ) + pEnd++; + if ( *pEnd != '(' ) + { + printf( "Cannot find the end of hexidecimal truth table.\n" ); + return NULL; + } + + // parse the truth table + *pEnd = 0; + pSop = Abc_SopFromTruthHex( pCur ); + *pEnd = '('; + pObj = Io_ReadDsd_rec( pNtk, pEnd, pSop ); + free( pSop ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Derives the DSD network of the formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadDsd( char * pForm ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj, * pTop; + Vec_Ptr_t * vNames; + char * pCur, * pFormCopy; + int i, nInputs; + + // count the number of elementary variables + nInputs = 0; + for ( pCur = pForm; *pCur; pCur++ ) + if ( *pCur >= 'a' && *pCur <= 'z' ) + nInputs = ABC_MAX( nInputs, *pCur - 'a' ); + nInputs++; + + // create the network + pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtk->pName = Extra_UtilStrsav( "dsd" ); + + // create PIs + vNames = Abc_NodeGetFakeNames( nInputs ); + for ( i = 0; i < nInputs; i++ ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), Vec_PtrEntry(vNames, i), NULL ); + Abc_NodeFreeNames( vNames ); + + // transform the formula by inserting parantheses + // this transforms strings like PRIME(a,b,cd) into (PRIME((a),(b),(cd))) + pCur = pFormCopy = ALLOC( char, 3 * strlen(pForm) + 10 ); + *pCur++ = '('; + for ( ; *pForm; pForm++ ) + if ( *pForm == '(' ) + { + *pCur++ = '('; + *pCur++ = '('; + } + else if ( *pForm == ')' ) + { + *pCur++ = ')'; + *pCur++ = ')'; + } + else if ( *pForm == ',' ) + { + *pCur++ = ')'; + *pCur++ = ','; + *pCur++ = '('; + } + else + *pCur++ = *pForm; + *pCur++ = ')'; + *pCur = 0; + + // parse the formula + pObj = Io_ReadDsd_rec( pNtk, pFormCopy, NULL ); + free( pFormCopy ); + if ( pObj == NULL ) + return NULL; + + // create output + pTop = Abc_NtkCreatePo(pNtk); + Abc_ObjAssignName( pTop, "F", NULL ); + Abc_ObjAddFanin( pTop, pObj ); + + // create the only PO + if ( !Abc_NtkCheck( pNtk ) ) + { + fprintf( stdout, "Io_ReadDsd(): Network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadEdif.c b/abc70930/src/base/io/ioReadEdif.c new file mode 100644 index 00000000..188e5b8c --- /dev/null +++ b/abc70930/src/base/io/ioReadEdif.c @@ -0,0 +1,235 @@ +/**CFile**************************************************************** + + FileName [ioReadEdif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read ISCAS benchmarks in EDIF.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadEdif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from an EDIF file.] + + Description [Works only for the ISCAS benchmarks.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + printf( "Currently this parser does not work!\n" ); + return NULL; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t()" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadEdifNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadEdif: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNet, * pObj, * pFanout; + char * pGateName, * pNetName; + int fTokensReady, iLine, i; + + // read the first line + vTokens = Extra_FileReaderGetTokens(p); + if ( strcmp( vTokens->pArray[0], "edif" ) != 0 ) + { + printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); + return NULL; + } + + // allocate the empty network + pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); + + // go through the lines of the file + fTokensReady = 0; + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 1; fTokensReady || (vTokens = Extra_FileReaderGetTokens(p)); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + // get the type of the line + fTokensReady = 0; + if ( strcmp( vTokens->pArray[0], "instance" ) == 0 ) + { + pNetName = vTokens->pArray[1]; + pNet = Abc_NtkFindOrCreateNet( pNtk, pNetName ); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + pGateName = vTokens->pArray[1]; + if ( strncmp( pGateName, "Flip", 4 ) == 0 ) + { + pObj = Abc_NtkCreateLatch( pNtk ); + Abc_LatchSetInit0( pObj ); + } + else + { + pObj = Abc_NtkCreateNode( pNtk ); +// pObj->pData = Abc_NtkRegisterName( pNtk, pGateName ); + pObj->pData = Extra_UtilStrsav( pGateName ); // memory leak!!! + } + Abc_ObjAddFanin( pNet, pObj ); + } + else if ( strcmp( vTokens->pArray[0], "net" ) == 0 ) + { + pNetName = vTokens->pArray[1]; + if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) + continue; + if ( strcmp( pNetName + strlen(pNetName) - 4, "_out" ) == 0 ) + pNetName[strlen(pNetName) - 4] = 0; + pNet = Abc_NtkFindNet( pNtk, pNetName ); + assert( pNet ); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + while ( strcmp( vTokens->pArray[0], "portRef" ) == 0 ) + { + if ( strcmp( pNetName, vTokens->pArray[3] ) != 0 ) + { + pFanout = Abc_NtkFindNet( pNtk, vTokens->pArray[3] ); + Abc_ObjAddFanin( Abc_ObjFanin0(pFanout), pNet ); + } + vTokens = Extra_FileReaderGetTokens(p); + } + fTokensReady = 1; + } + else if ( strcmp( vTokens->pArray[0], "library" ) == 0 ) + { + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + vTokens = Extra_FileReaderGetTokens(p); + while ( strcmp( vTokens->pArray[0], "port" ) == 0 ) + { + pNetName = vTokens->pArray[1]; + if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) + { + vTokens = Extra_FileReaderGetTokens(p); + continue; + } + if ( strcmp( pNetName + strlen(pNetName) - 3, "_PO" ) == 0 ) + pNetName[strlen(pNetName) - 3] = 0; + if ( strcmp( vTokens->pArray[3], "INPUT" ) == 0 ) + Io_ReadCreatePi( pNtk, vTokens->pArray[1] ); + else if ( strcmp( vTokens->pArray[3], "OUTPUT" ) == 0 ) + Io_ReadCreatePo( pNtk, vTokens->pArray[1] ); + else + { + printf( "%s (line %d): Wrong interface specification.\n", Extra_FileReaderGetFileName(p), iLine ); + Abc_NtkDelete( pNtk ); + return NULL; + } + vTokens = Extra_FileReaderGetTokens(p); + } + } + else if ( strcmp( vTokens->pArray[0], "design" ) == 0 ) + { + free( pNtk->pName ); + pNtk->pName = Extra_UtilStrsav( vTokens->pArray[3] ); + break; + } + } + Extra_ProgressBarStop( pProgress ); + + // assign logic functions + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( strncmp( pObj->pData, "And", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateAnd(pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); + else if ( strncmp( pObj->pData, "Or", 2 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateOr(pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); + else if ( strncmp( pObj->pData, "Nand", 4 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateNand(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Nor", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateNor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Exor", 4 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateXor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Exnor", 5 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateNxor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); + else if ( strncmp( pObj->pData, "Inv", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateInv(pNtk->pManFunc) ); + else if ( strncmp( pObj->pData, "Buf", 3 ) == 0 ) + Abc_ObjSetData( pObj, Abc_SopCreateBuf(pNtk->pManFunc) ); + else + { + printf( "%s: Unknown gate type \"%s\".\n", Extra_FileReaderGetFileName(p), pObj->pData ); + Abc_NtkDelete( pNtk ); + return NULL; + } + } + // check if constants have been added +// if ( pNet = Abc_NtkFindNet( pNtk, "VDD" ) ) +// Io_ReadCreateConst( pNtk, "VDD", 1 ); +// if ( pNet = Abc_NtkFindNet( pNtk, "GND" ) ) +// Io_ReadCreateConst( pNtk, "GND", 0 ); + + Abc_NtkFinalizeRead( pNtk ); + return pNtk; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadEqn.c b/abc70930/src/base/io/ioReadEqn.c new file mode 100644 index 00000000..e04f2b1a --- /dev/null +++ b/abc70930/src/base/io/ioReadEqn.c @@ -0,0 +1,239 @@ +/**CFile**************************************************************** + + FileName [ioReadEqn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read equation format files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ); +static void Io_ReadEqnStrCompact( char * pStr ); +static int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ); +static void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from a BENCH file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", ";", "=" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadEqnNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadEqn: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Vec_Ptr_t * vVars; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + char * pNodeName, * pFormula, * pFormulaCopy, * pVarName; + int iLine, i; + + // allocate the empty network + pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_AIG, 1 ); + // set the specs + pNtk->pName = Extra_FileNameGeneric(Extra_FileReaderGetFileName(p)); + pNtk->pSpec = Extra_UtilStrsav(Extra_FileReaderGetFileName(p)); + + // go through the lines of the file + vVars = Vec_PtrAlloc( 100 ); + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + // check if the first token contains anything + Io_ReadEqnStrCompact( vTokens->pArray[0] ); + if ( strlen(vTokens->pArray[0]) == 0 ) + break; + + // if the number of tokens is different from two, error + if ( vTokens->nSize != 2 ) + { + printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); + Abc_NtkDelete( pNtk ); + return NULL; + } + + // get the type of the line + if ( strncmp( vTokens->pArray[0], "INORDER", 7 ) == 0 ) + { + Io_ReadEqnStrCutAt( vTokens->pArray[1], " \n\r\t", 0, vVars ); + Vec_PtrForEachEntry( vVars, pVarName, i ) + Io_ReadCreatePi( pNtk, pVarName ); + } + else if ( strncmp( vTokens->pArray[0], "OUTORDER", 8 ) == 0 ) + { + Io_ReadEqnStrCutAt( vTokens->pArray[1], " \n\r\t", 0, vVars ); + Vec_PtrForEachEntry( vVars, pVarName, i ) + Io_ReadCreatePo( pNtk, pVarName ); + } + else + { + extern Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ); + + // get hold of the node name and its formula + pNodeName = vTokens->pArray[0]; + pFormula = vTokens->pArray[1]; + // compact the formula + Io_ReadEqnStrCompact( pFormula ); + + // consider the case of the constant node + if ( pFormula[1] == 0 && (pFormula[0] == '0' || pFormula[0] == '1') ) + { + pFormulaCopy = NULL; + Vec_PtrClear( vVars ); + } + else + { + // make a copy of formula for names + pFormulaCopy = Extra_UtilStrsav( pFormula ); + // find the names of the fanins of this node + Io_ReadEqnStrCutAt( pFormulaCopy, "!*+()", 1, vVars ); + } + // create the node + pNode = Io_ReadCreateNode( pNtk, pNodeName, (char **)Vec_PtrArray(vVars), Vec_PtrSize(vVars) ); + // derive the function + pNode->pData = Parse_FormulaParserEqn( stdout, pFormula, vVars, pNtk->pManFunc ); + // remove the cubes + FREE( pFormulaCopy ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vVars ); + Abc_NtkFinalizeRead( pNtk ); + return pNtk; +} + + + +/**Function************************************************************* + + Synopsis [Compacts the string by throwing away space-like chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadEqnStrCompact( char * pStr ) +{ + char * pCur, * pNew; + for ( pNew = pCur = pStr; *pCur; pCur++ ) + if ( !(*pCur == ' ' || *pCur == '\n' || *pCur == '\r' || *pCur == '\t') ) + *pNew++ = *pCur; + *pNew = 0; +} + +/**Function************************************************************* + + Synopsis [Determines unique variables in the string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ) +{ + char * pToken; + int i; + Vec_PtrForEachEntry( vTokens, pToken, i ) + if ( strcmp( pToken, pName ) == 0 ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Cuts the string into pieces using stop chars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ) +{ + char * pToken; + Vec_PtrClear( vTokens ); + for ( pToken = strtok( pStr, pStop ); pToken; pToken = strtok( NULL, pStop ) ) + if ( !fUniqueOnly || Io_ReadEqnStrFind( vTokens, pToken ) == -1 ) + Vec_PtrPush( vTokens, pToken ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadPla.c b/abc70930/src/base/io/ioReadPla.c new file mode 100644 index 00000000..fdfdb4f6 --- /dev/null +++ b/abc70930/src/base/io/ioReadPla.c @@ -0,0 +1,250 @@ +/**CFile**************************************************************** + + FileName [ioReadPla.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadPla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the network from a PLA file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck ) +{ + Extra_FileReader_t * p; + Abc_Ntk_t * pNtk; + + // start the file + p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t|" ); + if ( p == NULL ) + return NULL; + + // read the network + pNtk = Io_ReadPlaNetwork( p ); + Extra_FileReaderFree( p ); + if ( pNtk == NULL ) + return NULL; + + // make sure that everything is okay with the network structure + if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + printf( "Io_ReadPla: The network check has failed.\n" ); + Abc_NtkDelete( pNtk ); + return NULL; + } + return pNtk; +} +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ) +{ + ProgressBar * pProgress; + Vec_Ptr_t * vTokens; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pTermPi, * pTermPo, * pNode; + Vec_Str_t ** ppSops; + char Buffer[100]; + int nInputs = -1, nOutputs = -1, nProducts = -1; + char * pCubeIn, * pCubeOut; + int i, k, iLine, nDigits, nCubes; + + // allocate the empty network + pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); + + // go through the lines of the file + nCubes = 0; + pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); + for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) + { + Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); + + // if it is the end of file, quit the loop + if ( strcmp( vTokens->pArray[0], ".e" ) == 0 ) + break; + + if ( vTokens->nSize == 1 ) + { + printf( "%s (line %d): Wrong number of token.\n", + Extra_FileReaderGetFileName(p), iLine+1 ); + Abc_NtkDelete( pNtk ); + return NULL; + } + + if ( strcmp( vTokens->pArray[0], ".i" ) == 0 ) + nInputs = atoi(vTokens->pArray[1]); + else if ( strcmp( vTokens->pArray[0], ".o" ) == 0 ) + nOutputs = atoi(vTokens->pArray[1]); + else if ( strcmp( vTokens->pArray[0], ".p" ) == 0 ) + nProducts = atoi(vTokens->pArray[1]); + else if ( strcmp( vTokens->pArray[0], ".ilb" ) == 0 ) + { + if ( vTokens->nSize - 1 != nInputs ) + printf( "Warning: Mismatch between the number of PIs on the .i line (%d) and the number of PIs on the .ilb line (%d).\n", nInputs, vTokens->nSize - 1 ); + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePi( pNtk, vTokens->pArray[i] ); + } + else if ( strcmp( vTokens->pArray[0], ".ob" ) == 0 ) + { + if ( vTokens->nSize - 1 != nOutputs ) + printf( "Warning: Mismatch between the number of POs on the .o line (%d) and the number of POs on the .ob line (%d).\n", nOutputs, vTokens->nSize - 1 ); + for ( i = 1; i < vTokens->nSize; i++ ) + Io_ReadCreatePo( pNtk, vTokens->pArray[i] ); + } + else + { + // check if the input/output names are given + if ( Abc_NtkPiNum(pNtk) == 0 ) + { + if ( nInputs == -1 ) + { + printf( "%s: The number of inputs is not specified.\n", Extra_FileReaderGetFileName(p) ); + Abc_NtkDelete( pNtk ); + return NULL; + } + nDigits = Extra_Base10Log( nInputs ); + for ( i = 0; i < nInputs; i++ ) + { + sprintf( Buffer, "x%0*d", nDigits, i ); + Io_ReadCreatePi( pNtk, Buffer ); + } + } + if ( Abc_NtkPoNum(pNtk) == 0 ) + { + if ( nOutputs == -1 ) + { + printf( "%s: The number of outputs is not specified.\n", Extra_FileReaderGetFileName(p) ); + Abc_NtkDelete( pNtk ); + return NULL; + } + nDigits = Extra_Base10Log( nOutputs ); + for ( i = 0; i < nOutputs; i++ ) + { + sprintf( Buffer, "z%0*d", nDigits, i ); + Io_ReadCreatePo( pNtk, Buffer ); + } + } + if ( Abc_NtkNodeNum(pNtk) == 0 ) + { // first time here + // create the PO drivers and add them + // start the SOP covers + ppSops = ALLOC( Vec_Str_t *, nOutputs ); + Abc_NtkForEachPo( pNtk, pTermPo, i ) + { + ppSops[i] = Vec_StrAlloc( 100 ); + // create the node + pNode = Abc_NtkCreateNode(pNtk); + // connect the node to the PO net + Abc_ObjAddFanin( Abc_ObjFanin0Ntk(pTermPo), pNode ); + // connect the node to the PI nets + Abc_NtkForEachPi( pNtk, pTermPi, k ) + Abc_ObjAddFanin( pNode, Abc_ObjFanout0Ntk(pTermPi) ); + } + } + // read the cubes + if ( vTokens->nSize != 2 ) + { + printf( "%s (line %d): Input and output cubes are not specified.\n", + Extra_FileReaderGetFileName(p), iLine+1 ); + Abc_NtkDelete( pNtk ); + return NULL; + } + pCubeIn = vTokens->pArray[0]; + pCubeOut = vTokens->pArray[1]; + if ( strlen(pCubeIn) != (unsigned)nInputs ) + { + printf( "%s (line %d): Input cube length (%d) differs from the number of inputs (%d).\n", + Extra_FileReaderGetFileName(p), iLine+1, strlen(pCubeIn), nInputs ); + Abc_NtkDelete( pNtk ); + return NULL; + } + if ( strlen(pCubeOut) != (unsigned)nOutputs ) + { + printf( "%s (line %d): Output cube length (%d) differs from the number of outputs (%d).\n", + Extra_FileReaderGetFileName(p), iLine+1, strlen(pCubeOut), nOutputs ); + Abc_NtkDelete( pNtk ); + return NULL; + } + for ( i = 0; i < nOutputs; i++ ) + { + if ( pCubeOut[i] == '1' ) + { + Vec_StrAppend( ppSops[i], pCubeIn ); + Vec_StrAppend( ppSops[i], " 1\n" ); + } + } + nCubes++; + } + } + Extra_ProgressBarStop( pProgress ); + if ( nProducts != -1 && nCubes != nProducts ) + printf( "Warning: Mismatch between the number of cubes (%d) and the number on .p line (%d).\n", + nCubes, nProducts ); + + // add the SOP covers + Abc_NtkForEachPo( pNtk, pTermPo, i ) + { + pNode = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pTermPo) ); + if ( ppSops[i]->nSize == 0 ) + { + Abc_ObjRemoveFanins(pNode); + pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" ); + Vec_StrFree( ppSops[i] ); + continue; + } + Vec_StrPush( ppSops[i], 0 ); + pNode->pData = Abc_SopRegister( pNtk->pManFunc, ppSops[i]->pArray ); + Vec_StrFree( ppSops[i] ); + } + free( ppSops ); + Abc_NtkFinalizeRead( pNtk ); + return pNtk; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioReadVerilog.c b/abc70930/src/base/io/ioReadVerilog.c new file mode 100644 index 00000000..c64e330c --- /dev/null +++ b/abc70930/src/base/io/ioReadVerilog.c @@ -0,0 +1,90 @@ +/**CFile**************************************************************** + + FileName [ioReadVerilog.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioReadVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads hierarchical design from the Verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ) +{ + Abc_Ntk_t * pNtk; + Abc_Lib_t * pDesign; + int RetValue; + + // parse the verilog file + pDesign = Ver_ParseFile( pFileName, NULL, fCheck, 1 ); + if ( pDesign == NULL ) + return NULL; + + // detect top-level model + RetValue = Abc_LibFindTopLevelModels( pDesign ); + pNtk = Vec_PtrEntry( pDesign->vTops, 0 ); + if ( RetValue > 1 ) + printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n", + Vec_PtrSize(pDesign->vTops), pNtk->pName ); + + // extract the master network + pNtk->pDesign = pDesign; + pDesign->pManFunc = NULL; + + // verify the design for cyclic dependence + assert( Vec_PtrSize(pDesign->vModules) > 0 ); + if ( Vec_PtrSize(pDesign->vModules) == 1 ) + { +// printf( "Warning: The design is not hierarchical.\n" ); + Abc_LibFree( pDesign, pNtk ); + pNtk->pDesign = NULL; + pNtk->pSpec = Extra_UtilStrsav( pFileName ); + } + else + { + // check that there is no cyclic dependency + Abc_NtkIsAcyclicHierarchy( pNtk ); + } + +//Io_WriteVerilog( pNtk, "_temp.v" ); + return pNtk; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/ioUtil.c b/abc70930/src/base/io/ioUtil.c new file mode 100644 index 00000000..94ec4316 --- /dev/null +++ b/abc70930/src/base/io/ioUtil.c @@ -0,0 +1,752 @@ +/**CFile**************************************************************** + + FileName [ioUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the network in BENCH format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the file type.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Io_FileType_t Io_ReadFileType( char * pFileName ) +{ + char * pExt; + if ( pFileName == NULL ) + return IO_FILE_NONE; + pExt = Extra_FileNameExtension( pFileName ); + if ( pExt == NULL ) + return IO_FILE_NONE; + if ( !strcmp( pExt, "aig" ) ) + return IO_FILE_AIGER; + if ( !strcmp( pExt, "baf" ) ) + return IO_FILE_BAF; + if ( !strcmp( pExt, "blif" ) ) + return IO_FILE_BLIF; + if ( !strcmp( pExt, "bench" ) ) + return IO_FILE_BENCH; + if ( !strcmp( pExt, "cnf" ) ) + return IO_FILE_CNF; + if ( !strcmp( pExt, "dot" ) ) + return IO_FILE_DOT; + if ( !strcmp( pExt, "edif" ) ) + return IO_FILE_EDIF; + if ( !strcmp( pExt, "eqn" ) ) + return IO_FILE_EQN; + if ( !strcmp( pExt, "gml" ) ) + return IO_FILE_GML; + if ( !strcmp( pExt, "list" ) ) + return IO_FILE_LIST; + if ( !strcmp( pExt, "mv" ) ) + return IO_FILE_BLIFMV; + if ( !strcmp( pExt, "pla" ) ) + return IO_FILE_PLA; + if ( !strcmp( pExt, "v" ) ) + return IO_FILE_VERILOG; + return IO_FILE_UNKNOWN; +} + +/**Function************************************************************* + + Synopsis [Read the network from a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck ) +{ + FILE * pFile; + Abc_Ntk_t * pNtk; + if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN ) + { + fprintf( stdout, "The generic file reader requires a known file extension.\n" ); + return NULL; + } + // check if the file exists + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Cannot open input file \"%s\". ", pFileName ); + if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) + fprintf( stdout, "Did you mean \"%s\"?", pFileName ); + fprintf( stdout, "\n" ); + return NULL; + } + fclose( pFile ); + // read the AIG + if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF ) + { + if ( FileType == IO_FILE_AIGER ) + pNtk = Io_ReadAiger( pFileName, fCheck ); + else // if ( FileType == IO_FILE_BAF ) + pNtk = Io_ReadBaf( pFileName, fCheck ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Reading AIG from file has failed.\n" ); + return NULL; + } + return pNtk; + } + // read the new netlist + if ( FileType == IO_FILE_BLIF ) +// pNtk = Io_ReadBlif( pFileName, fCheck ); + pNtk = Io_ReadBlifMv( pFileName, 0, fCheck ); + else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) + pNtk = Io_ReadBlifMv( pFileName, 1, fCheck ); + else if ( FileType == IO_FILE_BENCH ) + pNtk = Io_ReadBench( pFileName, fCheck ); + else if ( FileType == IO_FILE_EDIF ) + pNtk = Io_ReadEdif( pFileName, fCheck ); + else if ( FileType == IO_FILE_EQN ) + pNtk = Io_ReadEqn( pFileName, fCheck ); + else if ( FileType == IO_FILE_PLA ) + pNtk = Io_ReadPla( pFileName, fCheck ); + else if ( FileType == IO_FILE_VERILOG ) + pNtk = Io_ReadVerilog( pFileName, fCheck ); + else + { + fprintf( stderr, "Unknown file format.\n" ); + return NULL; + } + if ( pNtk == NULL ) + { + fprintf( stdout, "Reading network from file has failed.\n" ); + return NULL; + } + if ( Abc_NtkBlackboxNum(pNtk) || Abc_NtkWhiteboxNum(pNtk) ) + fprintf( stdout, "Warning: The network contains hierarchy.\n" ); + return pNtk; +} + + +/**Function************************************************************* + + Synopsis [Read the network from a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck ) +{ + Abc_Ntk_t * pNtk, * pTemp; + // get the netlist + pNtk = Io_ReadNetlist( pFileName, FileType, fCheck ); + if ( pNtk == NULL ) + return NULL; + if ( !Abc_NtkIsNetlist(pNtk) ) + return pNtk; + // flatten logic hierarchy + assert( Abc_NtkIsNetlist(pNtk) ); + if ( Abc_NtkWhiteboxNum(pNtk) > 0 ) + { + pNtk = Abc_NtkFlattenLogicHierarchy( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Flattening logic hierarchy has failed.\n" ); + return NULL; + } + } + // convert blackboxes + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + printf( "Hierarchy reader converted %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtk) ); + pNtk = Abc_NtkConvertBlackboxes( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Converting blackboxes has failed.\n" ); + return NULL; + } + } + // consider the case of BLIF-MV + if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) + { +//Abc_NtkPrintStats( stdout, pNtk, 0 ); +// Io_WriteBlifMv( pNtk, "_temp_.mv" ); + pNtk = Abc_NtkStrashBlifMv( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Converting BLIF-MV to AIG has failed.\n" ); + return NULL; + } + return pNtk; + } + // convert the netlist into the logic network + pNtk = Abc_NtkToLogic( pTemp = pNtk ); + Abc_NtkDelete( pTemp ); + if ( pNtk == NULL ) + { + fprintf( stdout, "Converting netlist to logic network after reading has failed.\n" ); + return NULL; + } + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Write the network into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ) +{ + Abc_Ntk_t * pNtkTemp, * pNtkCopy; + // check if the current network is available + if ( pNtk == NULL ) + { + fprintf( stdout, "Empty network.\n" ); + return; + } + // check if the file extension if given + if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN ) + { + fprintf( stdout, "The generic file writer requires a known file extension.\n" ); + return; + } + // write the AIG formats + if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF ) + { + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); + return; + } + if ( FileType == IO_FILE_AIGER ) + Io_WriteAiger( pNtk, pFileName, 1 ); + else // if ( FileType == IO_FILE_BAF ) + Io_WriteBaf( pNtk, pFileName ); + return; + } + // write non-netlist types + if ( FileType == IO_FILE_CNF ) + { + Io_WriteCnf( pNtk, pFileName, 0 ); + return; + } + if ( FileType == IO_FILE_DOT ) + { + Io_WriteDot( pNtk, pFileName ); + return; + } + if ( FileType == IO_FILE_GML ) + { + Io_WriteGml( pNtk, pFileName ); + return; + } +/* + if ( FileType == IO_FILE_BLIFMV ) + { + Io_WriteBlifMv( pNtk, pFileName ); + return; + } +*/ + // convert logic network into netlist + if ( FileType == IO_FILE_PLA ) + { + if ( Abc_NtkLevel(pNtk) > 1 ) + { + fprintf( stdout, "PLA writing is available for collapsed networks.\n" ); + return; + } + if ( Abc_NtkIsComb(pNtk) ) + pNtkTemp = Abc_NtkToNetlist( pNtk ); + else + { + fprintf( stdout, "Latches are writen into the PLA file at PI/PO pairs.\n" ); + pNtkCopy = Abc_NtkDup( pNtk ); + Abc_NtkMakeComb( pNtkCopy ); + pNtkTemp = Abc_NtkToNetlist( pNtk ); + Abc_NtkDelete( pNtkCopy ); + } + if ( !Abc_NtkToSop( pNtk, 1 ) ) + return; + } + else if ( FileType == IO_FILE_BENCH ) + { + if ( !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "Writing traditional BENCH is available for AIGs only (use \"write_bench\").\n" ); + return; + } + pNtkTemp = Abc_NtkToNetlistBench( pNtk ); + } + else + pNtkTemp = Abc_NtkToNetlist( pNtk ); + + if ( pNtkTemp == NULL ) + { + fprintf( stdout, "Converting to netlist has failed.\n" ); + return; + } + + if ( FileType == IO_FILE_BLIF ) + { + if ( !Abc_NtkHasSop(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) + Abc_NtkToSop( pNtkTemp, 0 ); + Io_WriteBlif( pNtkTemp, pFileName, 1 ); + } + else if ( FileType == IO_FILE_BLIFMV ) + { + if ( !Abc_NtkConvertToBlifMv( pNtkTemp ) ) + return; + Io_WriteBlifMv( pNtkTemp, pFileName ); + } + else if ( FileType == IO_FILE_BENCH ) + Io_WriteBench( pNtkTemp, pFileName ); + else if ( FileType == IO_FILE_PLA ) + Io_WritePla( pNtkTemp, pFileName ); + else if ( FileType == IO_FILE_EQN ) + { + if ( !Abc_NtkHasAig(pNtkTemp) ) + Abc_NtkToAig( pNtkTemp ); + Io_WriteEqn( pNtkTemp, pFileName ); + } + else if ( FileType == IO_FILE_VERILOG ) + { + if ( !Abc_NtkHasAig(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) + Abc_NtkToAig( pNtkTemp ); + Io_WriteVerilog( pNtkTemp, pFileName ); + } + else + fprintf( stderr, "Unknown file format.\n" ); + Abc_NtkDelete( pNtkTemp ); +} + +/**Function************************************************************* + + Synopsis [Write the network into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName ) +{ + Abc_Ntk_t * pNtkTemp, * pNtkResult, * pNtkBase = NULL; + // check if the current network is available + if ( pNtk == NULL ) + { + fprintf( stdout, "Empty network.\n" ); + return; + } + + // read the base network + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIF ) + pNtkBase = Io_ReadBlifMv( pBaseName, 0, 1 ); + else if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) + pNtkBase = Io_ReadBlifMv( pBaseName, 1, 1 ); + else if ( Io_ReadFileType(pBaseName) == IO_FILE_VERILOG ) + pNtkBase = Io_ReadVerilog( pBaseName, 1 ); + else + fprintf( stderr, "Unknown input file format.\n" ); + if ( pNtkBase == NULL ) + return; + + // flatten logic hierarchy if present + if ( Abc_NtkWhiteboxNum(pNtkBase) > 0 ) + { + pNtkBase = Abc_NtkFlattenLogicHierarchy( pNtkTemp = pNtkBase ); + if ( pNtkBase == NULL ) + return; + Abc_NtkDelete( pNtkTemp ); + } + + // reintroduce the boxes into the netlist + if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) + { + if ( Abc_NtkBlackboxNum(pNtkBase) > 0 ) + { + printf( "Hierarchy writer does not support BLIF-MV with blackboxes.\n" ); + Abc_NtkDelete( pNtkBase ); + return; + } + // convert the current network to BLIF-MV + assert( !Abc_NtkIsNetlist(pNtk) ); + pNtkResult = Abc_NtkToNetlist( pNtk ); + if ( !Abc_NtkConvertToBlifMv( pNtkResult ) ) + return; + // reintroduce the network + pNtkResult = Abc_NtkInsertBlifMv( pNtkBase, pNtkTemp = pNtkResult ); + Abc_NtkDelete( pNtkTemp ); + } + else if ( Abc_NtkBlackboxNum(pNtkBase) > 0 ) + { + // derive the netlist + pNtkResult = Abc_NtkToNetlist( pNtk ); + pNtkResult = Abc_NtkInsertNewLogic( pNtkBase, pNtkTemp = pNtkResult ); + Abc_NtkDelete( pNtkTemp ); + if ( pNtkResult ) + printf( "Hierarchy writer reintroduced %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtkBase) ); + } + else + { + printf( "Warning: The output network does not contain blackboxes.\n" ); + pNtkResult = Abc_NtkToNetlist( pNtk ); + } + Abc_NtkDelete( pNtkBase ); + if ( pNtkResult == NULL ) + return; + + // write the resulting network + if ( Io_ReadFileType(pFileName) == IO_FILE_BLIF ) + { + if ( !Abc_NtkHasSop(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) ) + Abc_NtkToSop( pNtkResult, 0 ); + Io_WriteBlif( pNtkResult, pFileName, 1 ); + } + else if ( Io_ReadFileType(pFileName) == IO_FILE_VERILOG ) + { + if ( !Abc_NtkHasAig(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) ) + Abc_NtkToAig( pNtkResult ); + Io_WriteVerilog( pNtkResult, pFileName ); + } + else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) + { + Io_WriteBlifMv( pNtkResult, pFileName ); + } + else + fprintf( stderr, "Unknown output file format.\n" ); + + Abc_NtkDelete( pNtkResult ); +} + +/**Function************************************************************* + + Synopsis [Creates PI terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PI net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet ) + printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PI node + pTerm = Abc_NtkCreatePi( pNtk ); + Abc_ObjAddFanin( pNet, pTerm ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Creates PO terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PO net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) + printf( "Warning: PO \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PO node + pTerm = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Creates PO terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PO net + pNet = Abc_NtkFindNet( pNtk, pName ); + if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) + printf( "Warning: Assert \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PO node + pTerm = Abc_NtkCreateAssert( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Create a latch with the given input/output.] + + Description [By default, the latch value is unknown (ABC_INIT_NONE).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ) +{ + Abc_Obj_t * pLatch, * pTerm, * pNet; + // get the LI net + pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLI ); + // add the BO terminal + pTerm = Abc_NtkCreateBi( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + // add the latch box + pLatch = Abc_NtkCreateLatch( pNtk ); + Abc_ObjAddFanin( pLatch, pTerm ); + // add the BI terminal + pTerm = Abc_NtkCreateBo( pNtk ); + Abc_ObjAddFanin( pTerm, pLatch ); + // get the LO net + pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLO ); + Abc_ObjAddFanin( pNet, pTerm ); + // set latch name + Abc_ObjAssignName( pLatch, pNetLO, "L" ); + return pLatch; +} + +/**Function************************************************************* + + Synopsis [Create the reset latch with data=1 and init=0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv ) +{ + Abc_Obj_t * pLatch, * pNode; + Abc_Obj_t * pNetLI, * pNetLO; + // create latch with 0 init value +// pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" ); + pNetLI = Abc_NtkCreateNet( pNtk ); + pNetLO = Abc_NtkCreateNet( pNtk ); + Abc_ObjAssignName( pNetLI, Abc_ObjName(pNetLI), NULL ); + Abc_ObjAssignName( pNetLO, Abc_ObjName(pNetLO), NULL ); + pLatch = Io_ReadCreateLatch( pNtk, Abc_ObjName(pNetLI), Abc_ObjName(pNetLO) ); + // set the initial value + Abc_LatchSetInit0( pLatch ); + // feed the latch with constant1- node +// pNode = Abc_NtkCreateNode( pNtk ); +// pNode->pData = Abc_SopRegister( pNtk->pManFunc, "2\n1\n" ); + pNode = Abc_NtkCreateNodeConst1( pNtk ); + Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pNode ); + return pLatch; +} + +/**Function************************************************************* + + Synopsis [Create node and the net driven by it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs ) +{ + Abc_Obj_t * pNet, * pNode; + int i; + // create a new node + pNode = Abc_NtkCreateNode( pNtk ); + // add the fanin nets + for ( i = 0; i < nInputs; i++ ) + { + pNet = Abc_NtkFindOrCreateNet( pNtk, pNamesIn[i] ); + Abc_ObjAddFanin( pNode, pNet ); + } + // add the fanout net + pNet = Abc_NtkFindOrCreateNet( pNtk, pNameOut ); + Abc_ObjAddFanin( pNet, pNode ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Create a constant 0 node driving the net with this name.] + + Description [Assumes that the net already exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, bool fConst1 ) +{ + Abc_Obj_t * pNet, * pTerm; + pTerm = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); + pNet = Abc_NtkFindNet(pNtk, pName); assert( pNet ); + Abc_ObjAddFanin( pNet, pTerm ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Create an inverter or buffer for the given net.] + + Description [Assumes that the nets already exist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ) +{ + Abc_Obj_t * pNet, * pNode; + pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet ); + pNode = Abc_NtkCreateNodeInv(pNtk, pNet); + pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet ); + Abc_ObjAddFanin( pNet, pNode ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Create an inverter or buffer for the given net.] + + Description [Assumes that the nets already exist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ) +{ + Abc_Obj_t * pNet, * pNode; + pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet ); + pNode = Abc_NtkCreateNodeBuf(pNtk, pNet); + pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet ); + Abc_ObjAddFanin( pNet, pNode ); + return pNet; +} + + +/**Function************************************************************* + + Synopsis [Provide an fopen replacement with path lookup] + + Description [Provide an fopen replacement where the path stored + in pathvar MVSIS variable is used to look up the path + for name. Returns NULL if file cannot be opened.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ) +{ + char * t = 0, * c = 0, * i; + extern char * Abc_FrameReadFlag( char * pFlag ); + + if ( PathVar == 0 ) + { + return fopen( FileName, Mode ); + } + else + { + if ( c = Abc_FrameReadFlag( (char*)PathVar ) ) + { + char ActualFileName[4096]; + FILE * fp = 0; + t = Extra_UtilStrsav( c ); + for (i = strtok( t, ":" ); i != 0; i = strtok( 0, ":") ) + { +#ifdef WIN32 + _snprintf ( ActualFileName, 4096, "%s/%s", i, FileName ); +#else + snprintf ( ActualFileName, 4096, "%s/%s", i, FileName ); +#endif + if ( ( fp = fopen ( ActualFileName, Mode ) ) ) + { + if ( fVerbose ) + fprintf ( stdout, "Using file %s\n", ActualFileName ); + free( t ); + return fp; + } + } + free( t ); + return 0; + } + else + { + return fopen( FileName, Mode ); + } + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteAiger.c b/abc70930/src/base/io/ioWriteAiger.c new file mode 100644 index 00000000..ff34b177 --- /dev/null +++ b/abc70930/src/base/io/ioWriteAiger.c @@ -0,0 +1,291 @@ +/**CFile**************************************************************** + + FileName [ioWriteAiger.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + The following is taken from the AIGER format description, + which can be found at http://fmv.jku.at/aiger +*/ + + +/* + The AIGER And-Inverter Graph (AIG) Format Version 20061129 + ---------------------------------------------------------- + Armin Biere, Johannes Kepler University, 2006 + + This report describes the AIG file format as used by the AIGER library. + The purpose of this report is not only to motivate and document the + format, but also to allow independent implementations of writers and + readers by giving precise and unambiguous definitions. + + ... + +Introduction + + The name AIGER contains as one part the acronym AIG of And-Inverter + Graphs and also if pronounced in German sounds like the name of the + 'Eiger', a mountain in the Swiss alps. This choice should emphasize the + origin of this format. It was first openly discussed at the Alpine + Verification Meeting 2006 in Ascona as a way to provide a simple, compact + file format for a model checking competition affiliated to CAV 2007. + + ... + +Binary Format Definition + + The binary format is semantically a subset of the ASCII format with a + slightly different syntax. The binary format may need to reencode + literals, but translating a file in binary format into ASCII format and + then back in to binary format will result in the same file. + + The main differences of the binary format to the ASCII format are as + follows. After the header the list of input literals and all the + current state literals of a latch can be omitted. Furthermore the + definitions of the AND gates are binary encoded. However, the symbol + table and the comment section are as in the ASCII format. + + The header of an AIGER file in binary format has 'aig' as format + identifier, but otherwise is identical to the ASCII header. The standard + file extension for the binary format is therefore '.aig'. + + A header for the binary format is still in ASCII encoding: + + aig M I L O A + + Constants, variables and literals are handled in the same way as in the + ASCII format. The first simplifying restriction is on the variable + indices of inputs and latches. The variable indices of inputs come first, + followed by the pseudo-primary inputs of the latches and then the variable + indices of all LHS of AND gates: + + input variable indices 1, 2, ... , I + latch variable indices I+1, I+2, ... , (I+L) + AND variable indices I+L+1, I+L+2, ... , (I+L+A) == M + + The corresponding unsigned literals are + + input literals 2, 4, ... , 2*I + latch literals 2*I+2, 2*I+4, ... , 2*(I+L) + AND literals 2*(I+L)+2, 2*(I+L)+4, ... , 2*(I+L+A) == 2*M + + All literals have to be defined, and therefore 'M = I + L + A'. With this + restriction it becomes possible that the inputs and the current state + literals of the latches do not have to be listed explicitly. Therefore, + after the header only the list of 'L' next state literals follows, one per + latch on a single line, and then the 'O' outputs, again one per line. + + In the binary format we assume that the AND gates are ordered and respect + the child parent relation. AND gates with smaller literals on the LHS + come first. Therefore we can assume that the literals on the right-hand + side of a definition of an AND gate are smaller than the LHS literal. + Furthermore we can sort the literals on the RHS, such that the larger + literal comes first. A definition thus consists of three literals + + lhs rhs0 rhs1 + + with 'lhs' even and 'lhs > rhs0 >= rhs1'. Also the variable indices are + pairwise different to avoid combinational self loops. Since the LHS + indices of the definitions are all consecutive (as even integers), + the binary format does not have to keep 'lhs'. In addition, we can use + the order restriction and only write the differences 'delta0' and 'delta1' + instead of 'rhs0' and 'rhs1', with + + delta0 = lhs - rhs0, delta1 = rhs0 - rhs1 + + The differences will all be strictly positive, and in practice often very + small. We can take advantage of this fact by the simple little-endian + encoding of unsigned integers of the next section. After the binary delta + encoding of the RHSs of all AND gates, the optional symbol table and + optional comment section start in the same format as in the ASCII case. + + ... + +*/ + +static unsigned Io_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } +static unsigned Io_ObjAigerNum( Abc_Obj_t * pObj ) { return (unsigned)pObj->pCopy; } +static void Io_ObjSetAigerNum( Abc_Obj_t * pObj, unsigned Num ) { pObj->pCopy = (void *)Num; } + +int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols ) +{ + ProgressBar * pProgress; + FILE * pFile; + Abc_Obj_t * pObj, * pDriver; + int i, nNodes, Pos, nBufferSize; + unsigned char * pBuffer; + unsigned uLit0, uLit1, uLit; + + assert( Abc_NtkIsStrash(pNtk) ); + // start the output stream + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + Abc_NtkForEachLatch( pNtk, pObj, i ) + if ( !Abc_LatchIsInit0(pObj) ) + { + fprintf( stdout, "Io_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" ); + return; + } + + // set the node numbers to be used in the output file + nNodes = 0; + Io_ObjSetAigerNum( Abc_AigConst1(pNtk), nNodes++ ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Io_ObjSetAigerNum( pObj, nNodes++ ); + Abc_AigForEachAnd( pNtk, pObj, i ) + Io_ObjSetAigerNum( pObj, nNodes++ ); + + // write the header "M I L O A" where M = I + L + A + fprintf( pFile, "aig %u %u %u %u %u\n", + Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) + Abc_NtkNodeNum(pNtk), + Abc_NtkPiNum(pNtk), + Abc_NtkLatchNum(pNtk), + Abc_NtkPoNum(pNtk), + Abc_NtkNodeNum(pNtk) ); + + // if the driver node is a constant, we need to complement the literal below + // because, in the AIGER format, literal 0/1 is represented as number 0/1 + // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0 + + // write latch drivers + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0(pObj); + fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); + } + + // write PO drivers + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0(pObj); + fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); + } + + // write the nodes into the buffer + Pos = 0; + nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge + pBuffer = ALLOC( char, nBufferSize ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + uLit = Io_ObjMakeLit( Io_ObjAigerNum(pObj), 0 ); + uLit0 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin0(pObj)), Abc_ObjFaninC0(pObj) ); + uLit1 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin1(pObj)), Abc_ObjFaninC1(pObj) ); + assert( uLit0 < uLit1 ); + Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); + Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); + if ( Pos > nBufferSize - 10 ) + { + printf( "Io_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); + fclose( pFile ); + return; + } + } + assert( Pos < nBufferSize ); + Extra_ProgressBarStop( pProgress ); + + // write the buffer + fwrite( pBuffer, 1, Pos, pFile ); + free( pBuffer ); + + // write the symbol table + if ( fWriteSymbols ) + { + // write PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "i%d %s\n", i, Abc_ObjName(pObj) ); + // write latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + fprintf( pFile, "l%d %s\n", i, Abc_ObjName(Abc_ObjFanout0(pObj)) ); + // write POs + Abc_NtkForEachPo( pNtk, pObj, i ) + fprintf( pFile, "o%d %s\n", i, Abc_ObjName(pObj) ); + } + + // write the comment + fprintf( pFile, "c\n" ); + if ( pNtk->pName && strlen(pNtk->pName) > 0 ) + fprintf( pFile, ".model %s\n", pNtk->pName ); + fprintf( pFile, "This file was produced by ABC on %s\n", Extra_TimeStamp() ); + fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Adds one unsigned AIG edge to the output buffer.] + + Description [This procedure is a slightly modified version of Armin Biere's + procedure "void encode (FILE * file, unsigned x)" ] + + SideEffects [Returns the current writing position.] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; +// putc (ch, file); + pBuffer[Pos++] = ch; + x >>= 7; + } + ch = x; +// putc (ch, file); + pBuffer[Pos++] = ch; + return Pos; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBaf.c b/abc70930/src/base/io/ioWriteBaf.c new file mode 100644 index 00000000..fc0229a4 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBaf.c @@ -0,0 +1,168 @@ +/**CFile**************************************************************** + + FileName [ioWriteBaf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write AIG in the binary format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + Binary Aig Format + + The motivation for this format is to have + - compact binary representation of large AIGs (~10x more compact than BLIF) + - consequently, fast reading/writing of large AIGs (~10x faster than BLIF) + - representation for all tech-ind info related to an AIG + - human-readable file header + + The header: + (1) May contain several lines of human-readable comments. + Each comment line begins with symbol '#' and ends with symbol '\n'. + (2) Always contains the following data. + - benchmark name + - number of primary inputs + - number of primary outputs + - number of latches + - number of AIG nodes (excluding the constant 1 node) + Each entry is followed by 0-byte (character '\0'): + (3) Next follow the names of the PIs, POs, and latches in this order. + Each name is followed by 0-byte (character '\0'). + Inside each set of names (PIs, POs, latches) there should be no + identical names but the PO names may coincide with PI/latch names. + + The body: + (1) First part of the body contains binary information about the internal AIG nodes. + Each internal AIG node is represented using two edges (each edge is a 4-byte integer). + Each integer is the fanin ID followed by 1-bit representation of the complemented attribute. + (For example, complemented edge to node 10 will be represented as 2*10 + 1 = 21.) + The IDs of the nodes are created as follows: Constant 1 node has ID=0. + CIs (PIs and latch outputs) have 1-based IDs assigned in that order. + Each node in the array of the internal AIG nodes has the ID assigned in that order. + The constant 1 node is not written into the file. + (2) Second part of the body contains binary information about the edges connecting + the COs (POs and latch inputs) to the internal AIG nodes. + Each edge is a 4-byte integer the same way as a node fanin. + The latch initial value (2 bits) is stored in this integer. +*/ + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName ) +{ + ProgressBar * pProgress; + FILE * pFile; + Abc_Obj_t * pObj; + int i, nNodes, nAnds, nBufferSize; + unsigned * pBufferNode; + assert( Abc_NtkIsStrash(pNtk) ); + // start the output stream + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBaf(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + // write the comment + fprintf( pFile, "# BAF (Binary Aig Format) for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + + // write the network name + fprintf( pFile, "%s%c", pNtk->pName, 0 ); + // write the number of PIs + fprintf( pFile, "%d%c", Abc_NtkPiNum(pNtk), 0 ); + // write the number of POs + fprintf( pFile, "%d%c", Abc_NtkPoNum(pNtk), 0 ); + // write the number of latches + fprintf( pFile, "%d%c", Abc_NtkLatchNum(pNtk), 0 ); + // write the number of internal nodes + fprintf( pFile, "%d%c", Abc_NtkNodeNum(pNtk), 0 ); + + // write PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); + // write POs + Abc_NtkForEachPo( pNtk, pObj, i ) + fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); + // write latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); + fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanin0(pObj)), 0 ); + fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanout0(pObj)), 0 ); + } + + // set the node numbers to be used in the output file + Abc_NtkCleanCopy( pNtk ); + nNodes = 1; + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy = (void *)nNodes++; + Abc_AigForEachAnd( pNtk, pObj, i ) + pObj->pCopy = (void *)nNodes++; + + // write the nodes into the buffer + nAnds = 0; + nBufferSize = Abc_NtkNodeNum(pNtk) * 2 + Abc_NtkCoNum(pNtk); + pBufferNode = ALLOC( int, nBufferSize ); + pProgress = Extra_ProgressBarStart( stdout, nBufferSize ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, nAnds, NULL ); + pBufferNode[nAnds++] = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj); + pBufferNode[nAnds++] = (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj); + } + + // write the COs into the buffer + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, nAnds, NULL ); + pBufferNode[nAnds] = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj); + if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) + pBufferNode[nAnds] = (pBufferNode[nAnds] << 2) | ((unsigned)Abc_ObjData(Abc_ObjFanout0(pObj)) & 3); + nAnds++; + } + Extra_ProgressBarStop( pProgress ); + assert( nBufferSize == nAnds ); + + // write the buffer + fwrite( pBufferNode, 1, sizeof(int) * nBufferSize, pFile ); + fclose( pFile ); + free( pBufferNode ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBench.c b/abc70930/src/base/io/ioWriteBench.c new file mode 100644 index 00000000..4b766a47 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBench.c @@ -0,0 +1,335 @@ +/**CFile**************************************************************** + + FileName [ioWriteBench.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the network in BENCH format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk ); + +static int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode ); + +static int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBench( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pExdc; + FILE * pFile; + assert( Abc_NtkIsSopNetlist(pNtk) ); + if ( !Io_WriteBenchCheckNames(pNtk) ) + { + fprintf( stdout, "Io_WriteBench(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" ); + return 0; + } + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" ); + return 0; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the network + Io_WriteBenchOne( pFile, pNtk ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + printf( "Io_WriteBench: EXDC is not written (warning).\n" ); + // finalize the file + fclose( pFile ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode; + int i; + + // write the PIs/POs/latches + Abc_NtkForEachPi( pNtk, pNode, i ) + fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Abc_NtkForEachPo( pNtk, pNode, i ) + fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + Abc_NtkForEachLatch( pNtk, pNode, i ) + fprintf( pFile, "%-11s = DFF(%s)\n", + Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); + + // write internal nodes + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_WriteBenchOneNode( pFile, pNode ); + } + Extra_ProgressBarStop( pProgress ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode ) +{ + int nFanins; + + assert( Abc_ObjIsNode(pNode) ); + nFanins = Abc_ObjFaninNum(pNode); + if ( nFanins == 0 ) + { // write the constant 1 node + assert( Abc_NodeIsConst1(pNode) ); + fprintf( pFile, "%-11s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, " = vdd\n" ); + } + else if ( nFanins == 1 ) + { // write the interver/buffer + if ( Abc_NodeIsBuf(pNode) ) + { + fprintf( pFile, "%-11s = BUFF(", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + } + else + { + fprintf( pFile, "%-11s = NOT(", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + } + } + else + { // write the AND gate + fprintf( pFile, "%-11s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, " = AND(%s, ", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin1(pNode)) ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format with LUTs and DFFRSE.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pExdc; + FILE * pFile; + assert( Abc_NtkIsAigNetlist(pNtk) ); + if ( !Io_WriteBenchCheckNames(pNtk) ) + { + fprintf( stdout, "Io_WriteBenchLut(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" ); + return 0; + } + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" ); + return 0; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the network + Io_WriteBenchLutOne( pFile, pNtk ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + printf( "Io_WriteBench: EXDC is not written (warning).\n" ); + // finalize the file + fclose( pFile ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode; + Vec_Int_t * vMemory; + int i; + + // write the PIs/POs/latches + Abc_NtkForEachPi( pNtk, pNode, i ) + fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Abc_NtkForEachPo( pNtk, pNode, i ) + fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + Abc_NtkForEachLatch( pNtk, pNode, i ) + fprintf( pFile, "%-11s = DFFRSE( %s, gnd, gnd, gnd, gnd )\n", + Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); +//Abc_NtkLevel(pNtk); + // write internal nodes + vMemory = Vec_IntAlloc( 10000 ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_WriteBenchLutOneNode( pFile, pNode, vMemory ); + } + Extra_ProgressBarStop( pProgress ); + Vec_IntFree( vMemory ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Writes the network in BENCH format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth ) +{ + Abc_Obj_t * pFanin; + unsigned * pTruth; + int i, nFanins; + assert( Abc_ObjIsNode(pNode) ); + nFanins = Abc_ObjFaninNum(pNode); + assert( nFanins <= 8 ); + // compute the truth table + pTruth = Abc_ConvertAigToTruth( pNode->pNtk->pManFunc, Hop_Regular(pNode->pData), nFanins, vTruth, 0 ); + if ( Hop_IsComplement(pNode->pData) ) + Extra_TruthNot( pTruth, pTruth, nFanins ); + // consider simple cases + if ( Extra_TruthIsConst0(pTruth, nFanins) ) + { + fprintf( pFile, "%-11s = gnd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return 1; + } + if ( Extra_TruthIsConst1(pTruth, nFanins) ) + { + fprintf( pFile, "%-11s = vdd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return 1; + } + if ( nFanins == 1 ) + { + fprintf( pFile, "%-11s = LUT 0x%d ( %s )\n", + Abc_ObjName(Abc_ObjFanout0(pNode)), + Abc_NodeIsBuf(pNode)? 2 : 1, + Abc_ObjName(Abc_ObjFanin0(pNode)) ); + return 1; + } + // write it in the hexadecimal form + fprintf( pFile, "%-11s = LUT 0x", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Extra_PrintHexadecimal( pFile, pTruth, nFanins ); +/* + { +extern void Kit_DsdTest( unsigned * pTruth, int nVars ); +Abc_ObjForEachFanin( pNode, pFanin, i ) +printf( "%c%d ", 'a'+i, Abc_ObjFanin0(pFanin)->Level ); +printf( "\n" ); +Kit_DsdTest( pTruth, nFanins ); + } + if ( pNode->Id % 1000 == 0 ) + { + int x = 0; + } +*/ + // write the fanins + fprintf( pFile, " (" ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + fprintf( pFile, " %s%s", Abc_ObjName(pFanin), ((i==nFanins-1)? "" : ",") ); + fprintf( pFile, " )\n" ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the names cannot be written into the bench file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + char * pName; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + for ( pName = Nm_ManFindNameById(pNtk->pManName, i); pName && *pName; pName++ ) + if ( *pName == '(' || *pName == ')' ) + return 0; + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBlif.c b/abc70930/src/base/io/ioWriteBlif.c new file mode 100644 index 00000000..c0c29d65 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBlif.c @@ -0,0 +1,591 @@ +/**CFile**************************************************************** + + FileName [ioWriteBlif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write BLIF files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); +static void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ); +static void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ); +static void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) +{ + Abc_Ntk_t * pNtkTemp; + // derive the netlist + pNtkTemp = Abc_NtkToNetlist(pNtk); + if ( pNtkTemp == NULL ) + { + fprintf( stdout, "Writing BLIF has failed.\n" ); + return; + } + Io_WriteBlif( pNtkTemp, FileName, fWriteLatches ); + Abc_NtkDelete( pNtkTemp ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) +{ + FILE * pFile; + Abc_Ntk_t * pNtkTemp; + int i; + assert( Abc_NtkIsNetlist(pNtk) ); + // start writing the file + pFile = fopen( FileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBlif(): Cannot open the output file.\n" ); + return; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the master network + Io_NtkWrite( pFile, pNtk, fWriteLatches ); + // make sure there is no logic hierarchy + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + // write the hierarchy if present + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i ) + { + if ( pNtkTemp == pNtk ) + continue; + fprintf( pFile, "\n\n" ); + Io_NtkWrite( pFile, pNtkTemp, fWriteLatches ); + } + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Ntk_t * pExdc; + assert( Abc_NtkIsNetlist(pNtk) ); + // write the model name + fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); + // write the network + Io_NtkWriteOne( pFile, pNtk, fWriteLatches ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + { + fprintf( pFile, "\n" ); + fprintf( pFile, ".exdc\n" ); + Io_NtkWriteOne( pFile, pExdc, fWriteLatches ); + } + // finalize the file + fprintf( pFile, ".end\n" ); +} + +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pLatch; + int i, Length; + + // write the PIs + fprintf( pFile, ".inputs" ); + Io_NtkWritePis( pFile, pNtk, fWriteLatches ); + fprintf( pFile, "\n" ); + + // write the POs + fprintf( pFile, ".outputs" ); + Io_NtkWritePos( pFile, pNtk, fWriteLatches ); + fprintf( pFile, "\n" ); + + // write the assertions + if ( Abc_NtkAssertNum(pNtk) ) + { + fprintf( pFile, ".asserts" ); + Io_NtkWriteAsserts( pFile, pNtk ); + fprintf( pFile, "\n" ); + } + + // write the blackbox + if ( Abc_NtkHasBlackbox( pNtk ) ) + { + fprintf( pFile, ".blackbox\n" ); + return; + } + + // write the timing info + Io_WriteTimingInfo( pFile, pNtk ); + + // write the latches + if ( fWriteLatches && !Abc_NtkIsComb(pNtk) ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Io_NtkWriteLatch( pFile, pLatch ); + fprintf( pFile, "\n" ); + } + + // write the subcircuits + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachBlackbox( pNtk, pNode, i ) + Io_NtkWriteSubckt( pFile, pNode ); + fprintf( pFile, "\n" ); + } + + // write each internal node + Length = Abc_NtkHasMapping(pNtk)? Mio_LibraryReadGateNameMax(pNtk->pManFunc) : 0; + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_NtkWriteNode( pFile, pNode, Length ); + } + Extra_ProgressBarStop( pProgress ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 7; + NameCounter = 0; + + if ( fWriteLatches ) + { + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } + else + { + Abc_NtkForEachCi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + if ( fWriteLatches ) + { + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } + else + { + Abc_NtkForEachCo( pNtk, pTerm, i ) + { + if ( Abc_ObjIsAssert(pTerm) ) + continue; + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } + } +} + +/**Function************************************************************* + + Synopsis [Writes the assertion list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + Abc_NtkForEachAssert( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pModel = pNode->pData; + Abc_Obj_t * pTerm; + int i; + // write the subcircuit +// fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) ); + fprintf( pFile, ".subckt %s", Abc_NtkName(pModel) ); + // write pairs of the formal=actual names + Abc_NtkForEachPi( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + pTerm = Abc_ObjFanin( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + } + Abc_NtkForEachPo( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + pTerm = Abc_ObjFanout( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + } + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ) +{ + Abc_Obj_t * pNetLi, * pNetLo; + int Reset; + pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); + pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); + Reset = (int)Abc_ObjData( pLatch ); + // write the latch line + fprintf( pFile, ".latch" ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLi) ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLo) ); + fprintf( pFile, " %d\n", Reset-1 ); +} + + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ) +{ + if ( Abc_NtkHasMapping(pNode->pNtk) ) + { + // write the .gate line + fprintf( pFile, ".gate" ); + Io_NtkWriteNodeGate( pFile, pNode, Length ); + fprintf( pFile, "\n" ); + } + else + { + // write the .names line + fprintf( pFile, ".names" ); + Io_NtkWriteNodeFanins( pFile, pNode ); + fprintf( pFile, "\n" ); + // write the cubes + fprintf( pFile, "%s", Abc_ObjData(pNode) ); + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ) +{ + Mio_Gate_t * pGate = pNode->pData; + Mio_Pin_t * pGatePin; + int i; + // write the node + fprintf( pFile, " %-*s ", Length, Mio_GateReadName(pGate) ); + for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) + fprintf( pFile, "%s=%s ", Mio_PinReadName(pGatePin), Abc_ObjName( Abc_ObjFanin(pNode,i) ) ); + assert ( i == Abc_ObjFaninNum(pNode) ); + fprintf( pFile, "%s=%s", Mio_GateReadOutName(pGate), Abc_ObjName( Abc_ObjFanout0(pNode) ) ); +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNet; + int LineLength; + int AddedLength; + int NameCounter; + char * pName; + int i; + + LineLength = 6; + NameCounter = 0; + Abc_ObjForEachFanin( pNode, pNet, i ) + { + // get the fanin name + pName = Abc_ObjName(pNet); + // get the line length after the fanin name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); + LineLength += AddedLength; + NameCounter++; + } + + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength > 75 ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); +} + +/**Function************************************************************* + + Synopsis [Writes the timing info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + Abc_Time_t * pTime, * pTimeDef; + int i; + + if ( pNtk->pManTime == NULL ) + return; + + pTimeDef = Abc_NtkReadDefaultArrival( pNtk ); + fprintf( pFile, ".default_input_arrival %g %g\n", pTimeDef->Rise, pTimeDef->Fall ); + Abc_NtkForEachPi( pNtk, pNode, i ) + { + pTime = Abc_NodeReadArrival(pNode); + if ( pTime->Rise == pTimeDef->Rise && pTime->Fall == pTimeDef->Fall ) + continue; + fprintf( pFile, ".input_arrival %s %g %g\n", Abc_ObjName(pNode), pTime->Rise, pTime->Fall ); + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteBlifMv.c b/abc70930/src/base/io/ioWriteBlifMv.c new file mode 100644 index 00000000..775a2e07 --- /dev/null +++ b/abc70930/src/base/io/ioWriteBlifMv.c @@ -0,0 +1,519 @@ +/**CFile**************************************************************** + + FileName [ioWriteBlifMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write BLIF-MV files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch ); +static void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode ); +static void Io_NtkWriteBlifMvValues( FILE * pFile, Abc_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ) +{ + FILE * pFile; + Abc_Ntk_t * pNtkTemp; + int i; + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasBlifMv(pNtk) ); + // start writing the file + pFile = fopen( FileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteBlifMv(): Cannot open the output file.\n" ); + return; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the master network + Io_NtkWriteBlifMv( pFile, pNtk ); + // write the remaining networks + if ( pNtk->pDesign ) + { + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i ) + { + if ( pNtkTemp == pNtk ) + continue; + fprintf( pFile, "\n\n" ); + Io_NtkWriteBlifMv( pFile, pNtkTemp ); + } + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write the network into a BLIF file with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + assert( Abc_NtkIsNetlist(pNtk) ); + // write the model name + fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); + // write the network + Io_NtkWriteBlifMvOne( pFile, pNtk ); + // write EXDC network if it exists + if ( Abc_NtkExdc(pNtk) ) + printf( "Io_NtkWriteBlifMv(): EXDC is not written.\n" ); + // finalize the file + fprintf( pFile, ".end\n\n\n" ); +} + +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pTerm, * pLatch; + int i; + + // write the PIs + fprintf( pFile, ".inputs" ); + Io_NtkWriteBlifMvPis( pFile, pNtk ); + fprintf( pFile, "\n" ); + + // write the POs + fprintf( pFile, ".outputs" ); + Io_NtkWriteBlifMvPos( pFile, pNtk ); + fprintf( pFile, "\n" ); + + // write the assertions + if ( Abc_NtkAssertNum(pNtk) ) + { + fprintf( pFile, ".asserts" ); + Io_NtkWriteBlifMvAsserts( pFile, pNtk ); + fprintf( pFile, "\n" ); + } + + // write the MV directives + fprintf( pFile, "\n" ); + Abc_NtkForEachCi( pNtk, pTerm, i ) + if ( Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) ); + Abc_NtkForEachCo( pNtk, pTerm, i ) + if ( Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanin0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) ); + + // write the blackbox + if ( Abc_NtkHasBlackbox( pNtk ) ) + { + fprintf( pFile, ".blackbox\n" ); + return; + } + + // write the timing info +// Io_WriteTimingInfo( pFile, pNtk ); + + // write the latches + if ( !Abc_NtkIsComb(pNtk) ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Io_NtkWriteBlifMvLatch( pFile, pLatch ); + fprintf( pFile, "\n" ); + } +/* + // write the subcircuits + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + if ( Abc_NtkBlackboxNum(pNtk) > 0 ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachBlackbox( pNtk, pNode, i ) + Io_NtkWriteBlifMvSubckt( pFile, pNode ); + fprintf( pFile, "\n" ); + } +*/ + if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 ) + { + fprintf( pFile, "\n" ); + Abc_NtkForEachBox( pNtk, pNode, i ) + { + if ( Abc_ObjIsLatch(pNode) ) + continue; + Io_NtkWriteBlifMvSubckt( pFile, pNode ); + } + fprintf( pFile, "\n" ); + } + + // write each internal node + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + Io_NtkWriteBlifMvNode( pFile, pNode ); + } + Extra_ProgressBarStop( pProgress ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 7; + NameCounter = 0; + + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the assertion list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 8; + NameCounter = 0; + + Abc_NtkForEachAssert( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch ) +{ + Abc_Obj_t * pNetLi, * pNetLo; + int Reset; + pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); + pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); + Reset = (int)Abc_ObjData( pLatch ); + // write the latch line + fprintf( pFile, ".latch" ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLi) ); + fprintf( pFile, " %10s", Abc_ObjName(pNetLo) ); + fprintf( pFile, "\n" ); + // write the reset node + fprintf( pFile, ".reset %s\n", Abc_ObjName(pNetLo) ); + fprintf( pFile, "%d\n", Reset-1 ); +} + +/**Function************************************************************* + + Synopsis [Write the latch into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pModel = pNode->pData; + Abc_Obj_t * pTerm; + int i; + // write the MV directives + fprintf( pFile, "\n" ); + Abc_ObjForEachFanin( pNode, pTerm, i ) + if ( Abc_ObjMvVarNum(pTerm) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) ); + Abc_ObjForEachFanout( pNode, pTerm, i ) + if ( Abc_ObjMvVarNum(pTerm) > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) ); + // write the subcircuit + fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) ); + // write pairs of the formal=actual names + Abc_NtkForEachPi( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + pTerm = Abc_ObjFanin( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + } + Abc_NtkForEachPo( pModel, pTerm, i ) + { + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); + pTerm = Abc_ObjFanout( pNode, i ); + fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); + } + fprintf( pFile, "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + char * pCur; + int nValues, iFanin, i; + + // write .mv directives for the fanins + fprintf( pFile, "\n" ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { +// nValues = atoi(pCur); + nValues = Abc_ObjMvVarNum( pFanin ); + if ( nValues > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pFanin), nValues ); +// while ( *pCur++ != ' ' ); + } + + // write .mv directives for the node +// nValues = atoi(pCur); + nValues = Abc_ObjMvVarNum( Abc_ObjFanout0(pNode) ); + if ( nValues > 2 ) + fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), nValues ); +// while ( *pCur++ != '\n' ); + + // write the .names line + fprintf( pFile, ".table" ); + Io_NtkWriteBlifMvNodeFanins( pFile, pNode ); + fprintf( pFile, "\n" ); + + // write the cubes + pCur = Abc_ObjData(pNode); + if ( *pCur == 'd' ) + { + fprintf( pFile, ".default " ); + pCur++; + } + // write the literals + for ( ; *pCur; pCur++ ) + { + fprintf( pFile, "%c", *pCur ); + if ( *pCur != '=' ) + continue; + // get the number + iFanin = atoi( pCur+1 ); + fprintf( pFile, "%s", Abc_ObjName(Abc_ObjFanin(pNode,iFanin)) ); + // scroll on to the next symbol + while ( *pCur != ' ' && *pCur != '\n' ) + pCur++; + pCur--; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNet; + int LineLength; + int AddedLength; + int NameCounter; + char * pName; + int i; + + LineLength = 6; + NameCounter = 0; + Abc_ObjForEachFanin( pNode, pNet, i ) + { + // get the fanin name + pName = Abc_ObjName(pNet); + // get the line length after the fanin name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); + LineLength += AddedLength; + NameCounter++; + } + + // get the output name + pName = Abc_ObjName(Abc_ObjFanout0(pNode)); + // get the line length after the output name is written + AddedLength = strlen(pName) + 1; + if ( NameCounter && LineLength + AddedLength > 75 ) + { // write the line extender + fprintf( pFile, " \\\n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", pName ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteCnf.c b/abc70930/src/base/io/ioWriteCnf.c new file mode 100644 index 00000000..e1b2d956 --- /dev/null +++ b/abc70930/src/base/io/ioWriteCnf.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [ioWriteCnf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to output CNF of the miter cone.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteCnf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "satSolver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * s_pNtk = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the miter cone into a CNF file for the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName, int fAllPrimes ) +{ + sat_solver * pSat; + if ( Abc_NtkIsStrash(pNtk) ) + printf( "Io_WriteCnf() warning: Generating CNF by applying heuristic AIG to CNF conversion.\n" ); + else + printf( "Io_WriteCnf() warning: Generating CNF by convering logic nodes into CNF clauses.\n" ); + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter (the network with one PO).\n" ); + return 0; + } + if ( Abc_NtkLatchNum(pNtk) != 0 ) + { + fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter for combinational circuits.\n" ); + return 0; + } + if ( Abc_NtkNodeNum(pNtk) == 0 ) + { + fprintf( stdout, "The network has no logic nodes. No CNF file is generaled.\n" ); + return 0; + } + // convert to logic BDD network + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkToBdd( pNtk ); + // create solver with clauses + pSat = Abc_NtkMiterSatCreate( pNtk, fAllPrimes ); + if ( pSat == NULL ) + { + fprintf( stdout, "The problem is trivially UNSAT. No CNF file is generated.\n" ); + return 1; + } + // write the clauses + s_pNtk = pNtk; + Sat_SolverWriteDimacs( pSat, pFileName, 0, 0, 1 ); + s_pNtk = NULL; + // free the solver + sat_solver_delete( pSat ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Output the mapping of PIs into variable numbers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteCnfOutputPiMapping( FILE * pFile, int incrementVars ) +{ + extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); + Abc_Ntk_t * pNtk = s_pNtk; + Vec_Int_t * vCiIds; + Abc_Obj_t * pObj; + int i; + vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); + fprintf( pFile, "c PI variable numbers: \n" ); + Abc_NtkForEachCi( pNtk, pObj, i ) + fprintf( pFile, "c %s %d\n", Abc_ObjName(pObj), Vec_IntEntry(vCiIds, i) + (int)(incrementVars > 0) ); + Vec_IntFree( vCiIds ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteDot.c b/abc70930/src/base/io/ioWriteDot.c new file mode 100644 index 00000000..8ae3cc42 --- /dev/null +++ b/abc70930/src/base/io/ioWriteDot.c @@ -0,0 +1,809 @@ +/**CFile**************************************************************** + + FileName [ioWriteDot.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the graph structure of AIG in DOT.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteDot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static char * Abc_NtkPrintSop( char * pSop ); +static int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the graph structure of network for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ) +{ + Vec_Ptr_t * vNodes; + vNodes = Abc_NtkCollectObjects( pNtk ); + Io_WriteDotNtk( pNtk, vNodes, NULL, FileName, 0, 0 ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Writes the graph structure of network for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) +{ + FILE * pFile; + Abc_Obj_t * pNode, * pFanin; + char * pSopString; + int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; + int Limit = 300; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + + if ( vNodes->nSize < 1 ) + { + printf( "The set has no nodes. DOT file is not written.\n" ); + return; + } + + if ( vNodes->nSize > Limit ) + { + printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); + return; + } + + // start the stream + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // transform logic functions from BDD to SOP + if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); + return; + } + } + + // mark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 1; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 1; + + // get the levels of nodes + LevelMax = Abc_NtkLevel( pNtk ); + if ( fUseReverse ) + { + LevelMin = Abc_NtkLevelReverse( pNtk ); + assert( LevelMax == LevelMin ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + if ( Abc_ObjIsNode(pNode) ) + pNode->Level = LevelMax - pNode->Level + 1; + } + + // find the largest and the smallest levels + LevelMin = 10000; + LevelMax = -1; + fHasCos = 0; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + { + fHasCos = 1; + continue; + } + if ( LevelMin > (int)pNode->Level ) + LevelMin = pNode->Level; + if ( LevelMax < (int)pNode->Level ) + LevelMax = pNode->Level; + } + + // set the level of the CO nodes + if ( fHasCos ) + { + LevelMax++; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + pNode->Level = LevelMax; + } + } + + // write the DOT header + fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph network {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "size = \"10,8.5\";\n" ); +// fprintf( pFile, "size = \"14,11\";\n" ); +// fprintf( pFile, "page = \"8,11\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != LevelMin ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "Network structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); + fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) + fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); + else + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the POs + if ( fHasCos ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsCo(pNode) ) + continue; + fprintf( pFile, " Node%d [label = \"%s%s\"", + pNode->Id, + (Abc_ObjIsBi(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)):Abc_ObjName(pNode)), + (Abc_ObjIsBi(pNode)? "_in":"") ); + fprintf( pFile, ", shape = %s", (Abc_ObjIsBi(pNode)? "box":"invtriangle") ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate nodes of each rank + for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; + if ( Abc_ObjFaninNum(pNode) == 0 ) + continue; +// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + if ( Abc_NtkIsStrash(pNtk) ) + pSopString = ""; + else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) + pSopString = Mio_GateReadName(pNode->pData); + else if ( Abc_NtkHasMapping(pNtk) ) + pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); + else + pSopString = Abc_NtkPrintSop(pNode->pData); + fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); + + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the PI nodes if any + if ( LevelMin == 0 ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMin ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsCi(pNode) ) + { + // check if the costant node is present + if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) + { + fprintf( pFile, " Node%d [label = \"Const%d\"", pNode->Id, Abc_NtkIsStrash(pNode->pNtk) || Abc_NodeIsConst1(pNode) ); + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + continue; + } + fprintf( pFile, " Node%d [label = \"%s\"", + pNode->Id, + (Abc_ObjIsBo(pNode)? Abc_ObjName(Abc_ObjFanin0(pNode)):Abc_ObjName(pNode)) ); + fprintf( pFile, ", shape = %s", (Abc_ObjIsBo(pNode)? "box":"triangle") ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( (int)pNode->Level != LevelMax ) + continue; + fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); + } + + // generate edges + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsLatch(pNode) ) + continue; + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + if ( Abc_ObjIsLatch(pFanin) ) + continue; + fCompl = 0; + if ( Abc_NtkIsStrash(pNtk) ) + fCompl = Abc_ObjFaninC(pNode, k); + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pFanin->Id ); + fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); +// fprintf( pFile, ", label = \"%c\"", 'a' + k ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 0; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 0; + + // convert the network back into BDDs if this is how it was + if ( fHasBdds ) + Abc_NtkSopToBdd(pNtk); +} + + +/**Function************************************************************* + + Synopsis [Writes the graph structure of network for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) +{ + FILE * pFile; + Abc_Obj_t * pNode, * pFanin; + char * pSopString; + int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; + int Limit = 300; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + + if ( vNodes->nSize < 1 ) + { + printf( "The set has no nodes. DOT file is not written.\n" ); + return; + } + + if ( vNodes->nSize > Limit ) + { + printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); + return; + } + + // start the stream + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // transform logic functions from BDD to SOP + if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, 0) ) + { + printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); + return; + } + } + + // mark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 1; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 1; + + // get the levels of nodes + LevelMax = Abc_NtkLevel( pNtk ); + if ( fUseReverse ) + { + LevelMin = Abc_NtkLevelReverse( pNtk ); + assert( LevelMax == LevelMin ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + if ( Abc_ObjIsNode(pNode) ) + pNode->Level = LevelMax - pNode->Level + 1; + } + + // find the largest and the smallest levels + LevelMin = 10000; + LevelMax = -1; + fHasCos = 0; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + { + fHasCos = 1; + continue; + } + if ( LevelMin > (int)pNode->Level ) + LevelMin = pNode->Level; + if ( LevelMax < (int)pNode->Level ) + LevelMax = pNode->Level; + } + + // set the level of the CO nodes + if ( fHasCos ) + { + LevelMax++; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsCo(pNode) ) + pNode->Level = LevelMax; + } + } + + // write the DOT header + fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph network {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "size = \"10,8.5\";\n" ); +// fprintf( pFile, "size = \"14,11\";\n" ); +// fprintf( pFile, "page = \"8,11\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= LevelMin; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != LevelMin ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "Network structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); + fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) + fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); + else + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the POs + if ( fHasCos ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsPo(pNode) ) + continue; + fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = %s", "invtriangle" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate nodes of each rank + for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; +// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + if ( Abc_NtkIsStrash(pNtk) ) + pSopString = ""; + else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) + pSopString = Mio_GateReadName(pNode->pData); + else if ( Abc_NtkHasMapping(pNtk) ) + pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); + else + pSopString = Abc_NtkPrintSop(pNode->pData); + fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); + + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the PI nodes if any + if ( LevelMin == 0 ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMin ); + // generate the PO nodes + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( pNode->Level > 0 ) + continue; + if ( !Abc_ObjIsPi(pNode) ) + { + // check if the costant node is present + if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) + { + fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + continue; + } + fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = %s", "triangle" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + +// fprintf( pFile, "{\n" ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsLatch(pNode) ) + continue; + fprintf( pFile, "Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); + fprintf( pFile, ", shape = box" ); + if ( pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } +// fprintf( pFile, "}" ); +// fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( (int)pNode->Level != LevelMax ) + continue; + if ( !Abc_ObjIsPo(pNode) ) + continue; + fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); + } + + // generate edges + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( Abc_ObjIsBi(pNode) || Abc_ObjIsBo(pNode) ) + continue; + Abc_ObjForEachFanin( pNode, pFanin, k ) + { + fCompl = 0; + if ( Abc_NtkIsStrash(pNtk) ) + { + if ( Abc_ObjIsBi(pFanin) ) + fCompl = Abc_ObjFaninC(pFanin, k); + else + fCompl = Abc_ObjFaninC(pNode, k); + } + if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) + pFanin = Abc_ObjFanin0(pFanin); + if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) + pFanin = Abc_ObjFanin0(pFanin); + if ( !pFanin->fMarkC ) + continue; + + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pFanin->Id ); + fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); +// fprintf( pFile, ", label = \"%c\"", 'a' + k ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark the nodes from the set + Vec_PtrForEachEntry( vNodes, pNode, i ) + pNode->fMarkC = 0; + if ( vNodesShow ) + Vec_PtrForEachEntry( vNodesShow, pNode, i ) + pNode->fMarkB = 0; + + // convert the network back into BDDs if this is how it was + if ( fHasBdds ) + Abc_NtkSopToBdd(pNtk); +} + + +/**Function************************************************************* + + Synopsis [Computes the printable SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_NtkPrintSop( char * pSop ) +{ + static char Buffer[1000]; + char * pGet, * pSet; + pSet = Buffer; + for ( pGet = pSop; *pGet; pGet++ ) + { + if ( *pGet == '\n' ) + { + *pSet++ = '\\'; + *pSet++ = 'n'; + } + else + *pSet++ = *pGet; + } + *(pSet-2) = 0; + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Computes the printable SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + if ( !Abc_ObjIsNode(pObj) ) + continue; + if ( Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 ) + continue; + Counter ++; + } + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteEqn.c b/abc70930/src/base/io/ioWriteEqn.c new file mode 100644 index 00000000..95c54577 --- /dev/null +++ b/abc70930/src/base/io/ioWriteEqn.c @@ -0,0 +1,252 @@ +/**CFile**************************************************************** + + FileName [ioWriteEqn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write equation representation of the network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the logic network in the equation format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + + assert( Abc_NtkIsAigNetlist(pNtk) ); + if ( Abc_NtkLatchNum(pNtk) > 0 ) + printf( "Warning: only combinational portion is being written.\n" ); + + // check that the names are fine for the EQN format + if ( !Io_NtkWriteEqnCheck(pNtk) ) + return; + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteEqn(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "# Equations for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + + // write the equations for the network + Io_NtkWriteEqnOne( pFile, pNtk ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Write one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Vec_Vec_t * vLevels; + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pFanin; + int i, k; + + // write the PIs + fprintf( pFile, "INORDER =" ); + Io_NtkWriteEqnCis( pFile, pNtk ); + fprintf( pFile, ";\n" ); + + // write the POs + fprintf( pFile, "OUTORDER =" ); + Io_NtkWriteEqnCos( pFile, pNtk ); + fprintf( pFile, ";\n" ); + + // write each internal node + vLevels = Vec_VecAlloc( 10 ); + pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + fprintf( pFile, "%s = ", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + // set the input names + Abc_ObjForEachFanin( pNode, pFanin, k ) + Hop_IthVar(pNtk->pManFunc, k)->pData = Abc_ObjName(pFanin); + // write the formula + Hop_ObjPrintEqn( pFile, pNode->pData, vLevels, 0 ); + fprintf( pFile, ";\n" ); + } + Extra_ProgressBarStop( pProgress ); + Vec_VecFree( vLevels ); +} + + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 9; + NameCounter = 0; + + Abc_NtkForEachCi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary input list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = 10; + NameCounter = 0; + + Abc_NtkForEachCo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Abc_ObjName(pNet)) + 1; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, " \n" ); + // reset the line length + LineLength = 0; + NameCounter = 0; + } + fprintf( pFile, " %s", Abc_ObjName(pNet) ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Make sure the network does not have offending names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + char * pName; + int i, k, Length; + int RetValue = 1; + + // make sure the network does not have proper names, such as "0" or "1" or containing parantheses + Abc_NtkForEachObj( pNtk, pObj, i ) + { + pName = Nm_ManFindNameById(pNtk->pManName, i); + if ( pName == NULL ) + continue; + Length = strlen(pName); + if ( pName[0] == '0' || pName[0] == '1' ) + { + RetValue = 0; + break; + } + for ( k = 0; k < Length; k++ ) + if ( pName[k] == '(' || pName[k] == ')' || pName[k] == '!' || pName[k] == '*' || pName[k] == '+' ) + { + RetValue = 0; + break; + } + if ( k < Length ) + break; + } + if ( RetValue == 0 ) + { + printf( "The network cannot be written in the EQN format because object %d has name \"%s\".\n", i, pName ); + printf( "Consider renaming the objects using command \"short_names\" and trying again.\n" ); + } + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteGml.c b/abc70930/src/base/io/ioWriteGml.c new file mode 100644 index 00000000..dc897300 --- /dev/null +++ b/abc70930/src/base/io/ioWriteGml.c @@ -0,0 +1,116 @@ +/**CFile**************************************************************** + + FileName [ioWriteGml.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the graph structure of AIG in GML.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteGml.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG in GML.] + + Description [Useful for graph visualization using tools such as yEd: + http://www.yworks.com/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + Abc_Obj_t * pObj, * pFanin; + int i, k; + + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteGml(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "# GML for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + fprintf( pFile, "graph [\n" ); + + // output the POs + fprintf( pFile, "\n" ); + Abc_NtkForEachPo( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FFFF\" ]\n" ); // blue + fprintf( pFile, " ]\n" ); + } + // output the PIs + fprintf( pFile, "\n" ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FF00\" ]\n" ); // green + fprintf( pFile, " ]\n" ); + } + // output the latches + fprintf( pFile, "\n" ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"rectangle\" fill \"#FF0000\" ]\n" ); // red + fprintf( pFile, " ]\n" ); + } + // output the nodes + fprintf( pFile, "\n" ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); + fprintf( pFile, " graphics [ type \"ellipse\" fill \"#CCCCFF\" ]\n" ); // grey + fprintf( pFile, " ]\n" ); + } + + // output the edges + fprintf( pFile, "\n" ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + fprintf( pFile, " edge [ source %5d target %5d\n", pObj->Id, pFanin->Id ); + fprintf( pFile, " graphics [ type \"line\" arrow \"first\" ]\n" ); + fprintf( pFile, " ]\n" ); + } + } + + fprintf( pFile, "]\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteList.c b/abc70930/src/base/io/ioWriteList.c new file mode 100644 index 00000000..71af7c53 --- /dev/null +++ b/abc70930/src/base/io/ioWriteList.c @@ -0,0 +1,288 @@ +/**CFile**************************************************************** + + FileName [ioWriteList.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the graph structure of sequential AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteList.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +/* +-------- Original Message -------- +Subject: Re: abc release and retiming +Date: Sun, 13 Nov 2005 20:31:18 -0500 (EST) +From: Luca Carloni +To: Alan Mishchenko + +Alan, + +My graph-representation file format is based on an adjacency list +representation and is indeed quite simple, in fact maybe too simple... I +used it in order to reason on relatively small weighed direct graphs. I +simply list all vertices, one per line and for each vertex "V_source" I +list all vertices that are "sinks" with respect to it, i.e. such that +there is a distinct arc between "V_source" and each of them (in +paranthesis I list the name of the edge and its weight (number of latency +on that path). For instance, if you look at the following graph, you have +that vertex "v_5" is connected to vertex "v_6" through a directed arc +called "v_5_to_v_6" whose latency is equal to 3, i.e. there are three +flip-flops on this arc. Still, notice that I sometime interpret the graph +also as the representation of a LIS where each node corresponds to a +shell encapsulating a sequential core module (i.e. a module which does not +contain any combinational path between its inputs and its outputs). With +this representation an arc of latency 3 is interpreted as a wire where two +relay stations have been inserted in addition to the flip-flop terminating +the output of the core module. + +Finally, notice that the name of the arc does not necessarily have to be +"v_5_to_v_6", but it could have been something like "arc_222" or "xyz" as +long as it is a unique name in the graph. + +Thanks, +Luca + +Example of graph representation +----------------------------------------------------------------------------- +v_5 > v_6 ([v_5_to_v_6] = 3), v_12 ([v_5_to_v_12] = 2). +v_2 > v_4 ([v_2_to_v_4] = 1), v_10_s0 ([v_2_to_v_10_s0] = 6), v_12 ([v_2_to_v_12] = 3). +v_9 > v_10_s0 ([v_9_to_v_10_s0] = 5), v_12 ([v_9_to_v_12] = 2). +v_12 > v_13 ([v_12_to_v_13] = 5). +v_13 > v_14 ([v_13_to_v_14] = 1). +v_6 > v_7 ([v_6_to_v_7] = 2). +v_4 > v_5 ([v_4_to_v_5] = 2). +v_1 > v_2 ([v_1_to_v_2] = 1). +v_7 > v_8 ([v_7_to_v_8] = 2). +t > . +v_14 > t ([v_14_to_t] = 1), v_5 ([v_14_to_v_5] = 1). +v_8 > v_9 ([v_8_to_v_9] = 2). +s > v_1 ([s_to_v_1] = 1). +v_10_s0 > v_10_s1 ([v_10_s0_to_v_10_s1] = 1). +v_10_s1 > v_4 ([v_10_s1__v_4] = 1), v_8 ([v_10_s1__v_8] = 1). +----------------------------------------------------------------------------- +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj ); +static void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ) +{ + FILE * pFile; + Abc_Obj_t * pObj; + int i; + +// assert( Abc_NtkIsSeq(pNtk) ); + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteList(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + fprintf( pFile, "# Adjacency list for sequential AIG \"%s\"\n", pNtk->pName ); + fprintf( pFile, "# written by ABC on %s\n", Extra_TimeStamp() ); + + // write the constant node + if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk) ) > 0 ) + Io_WriteListEdge( pFile, Abc_AigConst1(pNtk) ); + + // write the PI edges + Abc_NtkForEachPi( pNtk, pObj, i ) + Io_WriteListEdge( pFile, pObj ); + + // write the internal nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + Io_WriteListEdge( pFile, pObj ); + + // write the host node + if ( fUseHost ) + Io_WriteListHost( pFile, pNtk ); + else + Abc_NtkForEachPo( pNtk, pObj, i ) + Io_WriteListEdge( pFile, pObj ); + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for one edge in a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i; + fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); + Abc_ObjForEachFanout( pObj, pFanout, i ) + { + fprintf( pFile, " %s", Abc_ObjName(pFanout) ); + fprintf( pFile, " ([%s_to_", Abc_ObjName(pObj) ); +// fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), Seq_ObjFanoutL(pObj, pFanout) ); + fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), 0 ); + if ( i != Abc_ObjFanoutNum(pObj) - 1 ) + fprintf( pFile, "," ); + } + fprintf( pFile, "." ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for one edge in a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + Abc_NtkForEachPo( pNtk, pObj, i ) + { + fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); + fprintf( pFile, " %s ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), "HOST", 0 ); + fprintf( pFile, "." ); + fprintf( pFile, "\n" ); + } + + fprintf( pFile, "%-10s > ", "HOST" ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + fprintf( pFile, " %s", Abc_ObjName(pObj) ); + fprintf( pFile, " ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), 0 ); + if ( i != Abc_NtkPiNum(pNtk) - 1 ) + fprintf( pFile, "," ); + } + fprintf( pFile, "." ); + fprintf( pFile, "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Writes the adjacency list for a sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + Abc_Obj_t * pObj, * pFanout; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) ); + + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteCellNet(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + fprintf( pFile, "# CellNet file for network \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + + // the only tricky part with writing is handling latches: + // each latch comes with (a) single-input latch-input node, (b) latch proper, (c) single-input latch-output node + // we arbitrarily decide to use the interger ID of the latch-input node to represent the latch in the file + // (this ID is used for both the cell and the net driven by that cell) + + // write the PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + fprintf( pFile, "cell %d is 0\n", pObj->Id ); + // write the POs + Abc_NtkForEachPo( pNtk, pObj, i ) + fprintf( pFile, "cell %d is 1\n", pObj->Id ); + // write the latches (use the ID of latch input) + Abc_NtkForEachLatch( pNtk, pObj, i ) + fprintf( pFile, "cell %d is 2\n", Abc_ObjFanin0(pObj)->Id ); + // write the logic nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + fprintf( pFile, "cell %d is %d\n", pObj->Id, 3+Abc_ObjFaninNum(pObj) ); + + // write the nets driven by PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + { + fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id ); + Abc_ObjForEachFanout( pObj, pFanout, k ) + fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); + fprintf( pFile, "\n" ); + } + // write the nets driven by latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + fprintf( pFile, "net %d %d 0", Abc_ObjFanin0(pObj)->Id, Abc_ObjFanin0(pObj)->Id ); + pObj = Abc_ObjFanout0(pObj); + Abc_ObjForEachFanout( pObj, pFanout, k ) + fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); + fprintf( pFile, "\n" ); + } + // write the nets driven by nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + { + fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id ); + Abc_ObjForEachFanout( pObj, pFanout, k ) + fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); + fprintf( pFile, "\n" ); + } + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWritePla.c b/abc70930/src/base/io/ioWritePla.c new file mode 100644 index 00000000..b119751c --- /dev/null +++ b/abc70930/src/base/io/ioWritePla.c @@ -0,0 +1,197 @@ +/**CFile**************************************************************** + + FileName [ioWritePla.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write the network in BENCH format.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWritePla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the network in PLA format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WritePla( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pExdc; + FILE * pFile; + + assert( Abc_NtkIsSopNetlist(pNtk) ); + assert( Abc_NtkLevel(pNtk) == 1 ); + + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WritePla(): Cannot open the output file.\n" ); + return 0; + } + fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + // write the network + Io_WritePlaOne( pFile, pNtk ); + // write EXDC network if it exists + pExdc = Abc_NtkExdc( pNtk ); + if ( pExdc ) + printf( "Io_WritePla: EXDC is not written (warning).\n" ); + // finalize the file + fclose( pFile ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the network in PLA format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + ProgressBar * pProgress; + Abc_Obj_t * pNode, * pFanin, * pDriver; + char * pCubeIn, * pCubeOut, * pCube; + int i, k, nProducts, nInputs, nOutputs, nFanins; + + nProducts = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); + if ( !Abc_ObjIsNode(pDriver) ) + { + nProducts++; + continue; + } + if ( Abc_NodeIsConst(pDriver) ) + { + if ( Abc_NodeIsConst1(pDriver) ) + nProducts++; + continue; + } + nProducts += Abc_SopGetCubeNum(pDriver->pData); + } + + // collect the parameters + nInputs = Abc_NtkCiNum(pNtk); + nOutputs = Abc_NtkCoNum(pNtk); + pCubeIn = ALLOC( char, nInputs + 1 ); + pCubeOut = ALLOC( char, nOutputs + 1 ); + memset( pCubeIn, '-', nInputs ); pCubeIn[nInputs] = 0; + memset( pCubeOut, '0', nOutputs ); pCubeOut[nOutputs] = 0; + + // write the header + fprintf( pFile, ".i %d\n", nInputs ); + fprintf( pFile, ".o %d\n", nOutputs ); + fprintf( pFile, ".ilb" ); + Abc_NtkForEachCi( pNtk, pNode, i ) + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".ob" ); + Abc_NtkForEachCo( pNtk, pNode, i ) + fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pNode)) ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".p %d\n", nProducts ); + + // mark the CI nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = (Abc_Obj_t *)i; + + // write the cubes + pProgress = Extra_ProgressBarStart( stdout, nOutputs ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // prepare the output cube + if ( i - 1 >= 0 ) + pCubeOut[i-1] = '0'; + pCubeOut[i] = '1'; + + // consider special cases of nodes + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); + if ( !Abc_ObjIsNode(pDriver) ) + { + assert( Abc_ObjIsCi(pDriver) ); + pCubeIn[(int)pDriver->pCopy] = '1' - Abc_ObjFaninC0(pNode); + fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); + pCubeIn[(int)pDriver->pCopy] = '-'; + continue; + } + if ( Abc_NodeIsConst(pDriver) ) + { + if ( Abc_NodeIsConst1(pDriver) ) + fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); + continue; + } + + // make sure the cover is not complemented + assert( !Abc_SopIsComplement( pDriver->pData ) ); + + // write the cubes + nFanins = Abc_ObjFaninNum(pDriver); + Abc_SopForEachCube( pDriver->pData, nFanins, pCube ) + { + Abc_ObjForEachFanin( pDriver, pFanin, k ) + { + pFanin = Abc_ObjFanin0Ntk(pFanin); + assert( (int)pFanin->pCopy < nInputs ); + pCubeIn[(int)pFanin->pCopy] = pCube[k]; + } + fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); + } + // clean the cube for future writing + Abc_ObjForEachFanin( pDriver, pFanin, k ) + { + pFanin = Abc_ObjFanin0Ntk(pFanin); + assert( Abc_ObjIsCi(pFanin) ); + pCubeIn[(int)pFanin->pCopy] = '-'; + } + Extra_ProgressBarUpdate( pProgress, i, NULL ); + } + Extra_ProgressBarStop( pProgress ); + fprintf( pFile, ".e\n" ); + + // clean the CI nodes + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->pCopy = NULL; + free( pCubeIn ); + free( pCubeOut ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/ioWriteVerilog.c b/abc70930/src/base/io/ioWriteVerilog.c new file mode 100644 index 00000000..9e71e3e4 --- /dev/null +++ b/abc70930/src/base/io/ioWriteVerilog.c @@ -0,0 +1,639 @@ +/**CFile**************************************************************** + + FileName [ioWriteVerilog.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to output a special subset of Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: ioWriteVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" +#include "main.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); +static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ); +static void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ); +static int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ); +static char * Io_WriteVerilogGetName( char * pName ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write verilog.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName ) +{ + Abc_Ntk_t * pNetlist; + FILE * pFile; + int i; + // can only write nodes represented using local AIGs + if ( !Abc_NtkIsAigNetlist(pNtk) && !Abc_NtkIsMappedNetlist(pNtk) ) + { + printf( "Io_WriteVerilog(): Can produce Verilog for mapped or AIG netlists only.\n" ); + return; + } + // start the output stream + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Io_WriteVerilog(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + // write the equations for the network + fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); + fprintf( pFile, "\n" ); + + // write modules + if ( pNtk->pDesign ) + { + // write the network first + Io_WriteVerilogInt( pFile, pNtk ); + // write other things + Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNetlist, i ) + { + assert( Abc_NtkIsNetlist(pNetlist) ); + if ( pNetlist == pNtk ) + continue; + fprintf( pFile, "\n" ); + Io_WriteVerilogInt( pFile, pNetlist ); + } + } + else + { + Io_WriteVerilogInt( pFile, pNtk ); + } + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes verilog.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + // write inputs and outputs +// fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) ); + fprintf( pFile, "module %s ( ", Abc_NtkName(pNtk) ); + // add the clock signal if it does not exist + if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) + fprintf( pFile, "clock, " ); + // write other primary inputs + fprintf( pFile, "\n " ); + if ( Abc_NtkPiNum(pNtk) > 0 ) + { + Io_WriteVerilogPis( pFile, pNtk, 3 ); + fprintf( pFile, ",\n " ); + } + if ( Abc_NtkPoNum(pNtk) > 0 ) + Io_WriteVerilogPos( pFile, pNtk, 3 ); + fprintf( pFile, " );\n" ); + // add the clock signal if it does not exist + if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) + fprintf( pFile, " input clock;\n" ); + // write inputs, outputs, registers, and wires + if ( Abc_NtkPiNum(pNtk) > 0 ) + { +// fprintf( pFile, " input gclk," ); + fprintf( pFile, " input " ); + Io_WriteVerilogPis( pFile, pNtk, 10 ); + fprintf( pFile, ";\n" ); + } + if ( Abc_NtkPoNum(pNtk) > 0 ) + { + fprintf( pFile, " output" ); + Io_WriteVerilogPos( pFile, pNtk, 5 ); + fprintf( pFile, ";\n" ); + } + // if this is not a blackbox, write internal signals + if ( !Abc_NtkHasBlackbox(pNtk) ) + { + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + fprintf( pFile, " reg" ); + Io_WriteVerilogRegs( pFile, pNtk, 4 ); + fprintf( pFile, ";\n" ); + } + if ( Io_WriteVerilogWiresCount(pNtk) > 0 ) + { + fprintf( pFile, " wire" ); + Io_WriteVerilogWires( pFile, pNtk, 4 ); + fprintf( pFile, ";\n" ); + } + // write nodes + Io_WriteVerilogObjects( pFile, pNtk ); + // write registers + if ( Abc_NtkLatchNum(pNtk) > 0 ) + Io_WriteVerilogLatches( pFile, pNtk ); + } + // finalize the file + fprintf( pFile, "endmodule\n\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pTerm, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i; + + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanout0(pTerm); + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPiNum(pNtk)-1)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pTerm, * pNet, * pSkip; + int LineLength; + int AddedLength; + int NameCounter; + int i; + int nskip; + + pSkip = 0; + nskip = 0; + + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + pNet = Abc_ObjFanin0(pTerm); + + if ( Abc_ObjIsPi(Abc_ObjFanin0(pNet)) ) + { + // Skip this output since it is a feedthrough -- the same + // name will appear as an input and an output which other + // tools reading verilog do not like. + + nskip++; + pSkip = pNet; // save an example of skipped net + continue; + } + + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPoNum(pNtk)-1)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + + if (nskip != 0) + { + assert (pSkip); + printf( "Io_WriteVerilogPos(): Omitted %d feedthrough nets from output list of module (e.g. %s).\n", nskip, Abc_ObjName(pSkip) ); + return; + } + +} + +/**Function************************************************************* + + Synopsis [Writes the wires.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pObj, * pNet, * pBox, * pTerm; + int LineLength; + int AddedLength; + int NameCounter; + int i, k, Counter, nNodes; + + // count the number of wires + nNodes = Io_WriteVerilogWiresCount( pNtk ); + + // write the wires + Counter = 0; + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) + continue; + pNet = Abc_ObjFanout0(pObj); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + Abc_NtkForEachBox( pNtk, pBox, i ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + Abc_ObjForEachFanin( pBox, pTerm, k ) + { + pNet = Abc_ObjFanin0(pTerm); + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + Abc_ObjForEachFanout( pBox, pTerm, k ) + { + pNet = Abc_ObjFanout0(pTerm); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } + } + assert( Counter == nNodes ); +} + +/**Function************************************************************* + + Synopsis [Writes the regs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) +{ + Abc_Obj_t * pLatch, * pNet; + int LineLength; + int AddedLength; + int NameCounter; + int i, Counter, nNodes; + + // count the number of latches + nNodes = Abc_NtkLatchNum(pNtk); + + // write the wires + Counter = 0; + LineLength = Start; + NameCounter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pNet = Abc_ObjFanout0(Abc_ObjFanout0(pLatch)); + Counter++; + // get the line length after this name is written + AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; + if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) + { // write the line extender + fprintf( pFile, "\n " ); + // reset the line length + LineLength = 3; + NameCounter = 0; + } + fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); + LineLength += AddedLength; + NameCounter++; + } +} + +/**Function************************************************************* + + Synopsis [Writes the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch; + int i; + if ( Abc_NtkLatchNum(pNtk) == 0 ) + return; + // write the latches +// fprintf( pFile, " always @(posedge %s) begin\n", Io_WriteVerilogGetName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0))) ); +// fprintf( pFile, " always begin\n" ); + fprintf( pFile, " always @ (posedge clock) begin\n" ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + fprintf( pFile, " %s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); + fprintf( pFile, " <= %s;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pLatch)))) ); + } + fprintf( pFile, " end\n" ); + // check if there are initial values + Abc_NtkForEachLatch( pNtk, pLatch, i ) + if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO || Abc_LatchInit(pLatch) == ABC_INIT_ONE ) + break; + if ( i == Abc_NtkLatchNum(pNtk) ) + return; + // write the initial values + fprintf( pFile, " initial begin\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0)))) ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO ) + fprintf( pFile, " %s <= 1\'b0;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); + else if ( Abc_LatchInit(pLatch) == ABC_INIT_ONE ) + fprintf( pFile, " %s <= 1\'b1;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); + } + fprintf( pFile, " end\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the nodes and boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ) +{ + Vec_Vec_t * vLevels; + Abc_Ntk_t * pNtkBox; + Abc_Obj_t * pObj, * pTerm, * pFanin; + Hop_Obj_t * pFunc; + int i, k, Counter, nDigits, Length; + + // write boxes + nDigits = Extra_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); + Counter = 0; + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + pNtkBox = pObj->pData; + fprintf( pFile, " %s box%0*d", pNtkBox->pName, nDigits, Counter++ ); + fprintf( pFile, "(" ); + Abc_NtkForEachPi( pNtkBox, pTerm, k ) + { + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pTerm))) ); + fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin(pObj,k)))) ); + } + Abc_NtkForEachPo( pNtkBox, pTerm, k ) + { + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(pTerm))) ); + fprintf( pFile, "(%s)%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout(pObj,k)))), k==Abc_NtkPoNum(pNtkBox)-1? "":", " ); + } + fprintf( pFile, ");\n" ); + } + // write nodes + if ( Abc_NtkHasMapping(pNtk) ) + { + Length = Mio_LibraryReadGateNameMax(pNtk->pManFunc); + nDigits = Extra_Base10Log( Abc_NtkNodeNum(pNtk) ); + Counter = 0; + Abc_NtkForEachNode( pNtk, pObj, k ) + { + Mio_Gate_t * pGate = pObj->pData; + Mio_Pin_t * pGatePin; + // write the node + fprintf( pFile, " %-*s g%0*d", Length, Mio_GateReadName(pGate), nDigits, Counter++ ); + fprintf( pFile, "(" ); + for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) + { + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_PinReadName(pGatePin)) ); + fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanin(pObj,i) )) ); + } + assert ( i == Abc_ObjFaninNum(pObj) ); + fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName(pGate)) ); + fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )) ); + fprintf( pFile, ");\n" ); + } + } + else + { + vLevels = Vec_VecAlloc( 10 ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + pFunc = pObj->pData; + fprintf( pFile, " assign %s = ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); + // set the input names + Abc_ObjForEachFanin( pObj, pFanin, k ) + Hop_IthVar(pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(Abc_ObjName(pFanin))); + // write the formula + Hop_ObjPrintVerilog( pFile, pFunc, vLevels, 0 ); + fprintf( pFile, ";\n" ); + // clear the input names + Abc_ObjForEachFanin( pObj, pFanin, k ) + free( Hop_IthVar(pNtk->pManFunc, k)->pData ); + } + Vec_VecFree( vLevels ); + } +} + +/**Function************************************************************* + + Synopsis [Counts the number of wires.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pNet, * pBox; + int i, k, nWires; + nWires = Abc_NtkLatchNum(pNtk); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) + continue; + pNet = Abc_ObjFanout0(pObj); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + nWires++; + } + Abc_NtkForEachBox( pNtk, pBox, i ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + nWires += Abc_ObjFaninNum(pBox); + Abc_ObjForEachFanout( pBox, pObj, k ) + { + pNet = Abc_ObjFanout0(pObj); + if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) + continue; + nWires++; + } + } + return nWires; +} + +/**Function************************************************************* + + Synopsis [Prepares the name for writing the Verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Io_WriteVerilogGetName( char * pName ) +{ + static char Buffer[500]; + int Length, i; + Length = strlen(pName); + // consider the case of a signal having name "0" or "1" + if ( !(Length == 1 && (pName[0] == '0' || pName[0] == '1')) ) + { + for ( i = 0; i < Length; i++ ) + if ( !((pName[i] >= 'a' && pName[i] <= 'z') || + (pName[i] >= 'A' && pName[i] <= 'Z') || + (pName[i] >= '0' && pName[i] <= '9') || pName[i] == '_') ) + break; + if ( i == Length ) + return pName; + } + // create Verilog style name + Buffer[0] = '\\'; + for ( i = 0; i < Length; i++ ) + Buffer[i+1] = pName[i]; + Buffer[Length+1] = ' '; + Buffer[Length+2] = 0; + return Buffer; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/io/io_.c b/abc70930/src/base/io/io_.c new file mode 100644 index 00000000..62dd60e5 --- /dev/null +++ b/abc70930/src/base/io/io_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [io_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedure to read network from file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: io_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + diff --git a/abc70930/src/base/io/module.make b/abc70930/src/base/io/module.make new file mode 100644 index 00000000..bb35a7fc --- /dev/null +++ b/abc70930/src/base/io/module.make @@ -0,0 +1,25 @@ +SRC += src/base/io/io.c \ + src/base/io/ioReadAiger.c \ + src/base/io/ioReadBaf.c \ + src/base/io/ioReadBench.c \ + src/base/io/ioReadBlif.c \ + src/base/io/ioReadBlifAig.c \ + src/base/io/ioReadBlifMv.c \ + src/base/io/ioReadDsd.c \ + src/base/io/ioReadEdif.c \ + src/base/io/ioReadEqn.c \ + src/base/io/ioReadPla.c \ + src/base/io/ioReadVerilog.c \ + src/base/io/ioUtil.c \ + src/base/io/ioWriteAiger.c \ + src/base/io/ioWriteBaf.c \ + src/base/io/ioWriteBench.c \ + src/base/io/ioWriteBlif.c \ + src/base/io/ioWriteBlifMv.c \ + src/base/io/ioWriteCnf.c \ + src/base/io/ioWriteDot.c \ + src/base/io/ioWriteEqn.c \ + src/base/io/ioWriteGml.c \ + src/base/io/ioWriteList.c \ + src/base/io/ioWritePla.c \ + src/base/io/ioWriteVerilog.c diff --git a/abc70930/src/base/main/libSupport.c b/abc70930/src/base/main/libSupport.c new file mode 100644 index 00000000..471ea09e --- /dev/null +++ b/abc70930/src/base/main/libSupport.c @@ -0,0 +1,193 @@ +/**CFile**************************************************************** + + FileName [libSupport.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [Support for external libaries.] + + Author [Mike Case] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: libSupport.c,v 1.1 2005/09/06 19:59:51 casem Exp $] + +***********************************************************************/ + +#include "mainInt.h" +#include +#include + +#ifndef WIN32 +# include +# include +# include +#endif + +#define MAX_LIBS 256 +static void* libHandles[MAX_LIBS+1]; // will be null terminated + +typedef void (*lib_init_end_func) (Abc_Frame_t * pAbc); + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// This will find all the ABC library extensions in the current directory and load them all. +//////////////////////////////////////////////////////////////////////////////////////////////////// +void open_libs() { + int curr_lib = 0; + +#ifdef WIN32 +// printf("Warning: open_libs WIN32 not implemented.\n"); +#else + DIR* dirp; + struct dirent* dp; + char *env, *init_p, *p; + int done; + + env = getenv ("ABC_LIB_PATH"); + if (env == NULL) { +// printf("Warning: ABC_LIB_PATH not defined. Looking into the current directory.\n"); + init_p = malloc (2*sizeof(char)); + init_p[0]='.'; init_p[1] = 0; + } else { + init_p = malloc ((strlen(env)+1)*sizeof(char)); + strcpy (init_p, env); + } + + // Extract directories and read libraries + done = 0; + p = init_p; + while (!done) { + char *endp = strchr (p,':'); + if (endp == NULL) done = 1; // last directory in the list + else *endp = 0; // end of string + + dirp = opendir(p); + if (dirp == NULL) { +// printf("Warning: directory in ABC_LIB_PATH does not exist (%s).\n", p); + continue; + } + + while ((dp = readdir(dirp)) != NULL) { + if ((strncmp("libabc_", dp->d_name, 7) == 0) && + (strcmp(".so", dp->d_name + strlen(dp->d_name) - 3) == 0)) { + + // make sure we don't overflow the handle array + if (curr_lib >= MAX_LIBS) { + printf("Warning: maximum number of ABC libraries (%d) exceeded. Not loading %s.\n", + MAX_LIBS, + dp->d_name); + } + + // attempt to load it + else { + char* szPrefixed = malloc((strlen(dp->d_name) + strlen(p) + 2) * + sizeof(char)); + sprintf(szPrefixed, "%s/", p); + strcat(szPrefixed, dp->d_name); + libHandles[curr_lib] = dlopen(szPrefixed, RTLD_NOW | RTLD_LOCAL); + + // did the load succeed? + if (libHandles[curr_lib] != 0) { + printf("Loaded ABC library: %s (Abc library extension #%d)\n", szPrefixed, curr_lib); + curr_lib++; + } else { + printf("Warning: failed to load ABC library %s:\n\t%s\n", szPrefixed, dlerror()); + } + + free(szPrefixed); + } + } + } + closedir(dirp); + p = endp+1; + } + + free(init_p); +#endif + + // null terminate the list of handles + libHandles[curr_lib] = 0; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// This will close all open ABC library extensions +//////////////////////////////////////////////////////////////////////////////////////////////////// +void close_libs() { +#ifdef WIN32 + printf("Warning: close_libs WIN32 not implemented.\n"); +#else + int i; + for (i = 0; libHandles[i] != 0; i++) { + if (dlclose(libHandles[i]) != 0) { + printf("Warning: failed to close library %d\n", i); + } + libHandles[i] = 0; + } +#endif +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// This will get a pointer to a function inside of an open library +//////////////////////////////////////////////////////////////////////////////////////////////////// +void* get_fnct_ptr(int lib_num, char* sym_name) { +#ifdef WIN32 + printf("Warning: get_fnct_ptr WIN32 not implemented.\n"); + return 0; +#else + return dlsym(libHandles[lib_num], sym_name); +#endif +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// This will call an initialization function in every open library. +//////////////////////////////////////////////////////////////////////////////////////////////////// +void call_inits(Abc_Frame_t* pAbc) { + int i; + lib_init_end_func init_func; + for (i = 0; libHandles[i] != 0; i++) { + init_func = (lib_init_end_func) get_fnct_ptr(i, "abc_init"); + if (init_func == 0) { + printf("Warning: Failed to initialize library %d.\n", i); + } else { + (*init_func)(pAbc); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// This will call a shutdown function in every open library. +//////////////////////////////////////////////////////////////////////////////////////////////////// +void call_ends(Abc_Frame_t* pAbc) { + int i; + lib_init_end_func end_func; + for (i = 0; libHandles[i] != 0; i++) { + end_func = (lib_init_end_func) get_fnct_ptr(i, "abc_end"); + if (end_func == 0) { + printf("Warning: Failed to end library %d.\n", i); + } else { + (*end_func)(pAbc); + } + } +} + +void Libs_Init(Abc_Frame_t * pAbc) +{ + open_libs(); + call_inits(pAbc); +} + +void Libs_End(Abc_Frame_t * pAbc) +{ + call_ends(pAbc); + + // It's good practice to close our libraries at this point, but this can mess up any backtrace printed by Valgind. + // close_libs(); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/main/main.c b/abc70930/src/base/main/main.c new file mode 100644 index 00000000..8f43c605 --- /dev/null +++ b/abc70930/src/base/main/main.c @@ -0,0 +1,317 @@ +/**CFile**************************************************************** + + FileName [main.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [Here everything starts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: main.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" + +// this line should be included in the library project +//#define _LIB + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int TypeCheck( Abc_Frame_t * pAbc, char * s); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifndef _LIB + +/**Function************************************************************* + + Synopsis [The main() procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int main( int argc, char * argv[] ) +{ + Abc_Frame_t * pAbc; + char sCommandUsr[500], sCommandTmp[100], sReadCmd[20], sWriteCmd[20], c; + char * sCommand, * sOutFile, * sInFile; + int fStatus = 0; + bool fBatch, fInitSource, fInitRead, fFinalWrite; + + // added to detect memory leaks: +#ifdef _DEBUG + _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); +#endif + +// Npn_Experiment(); +// Npn_Generate(); + + // get global frame (singleton pattern) + // will be initialized on first call + pAbc = Abc_FrameGetGlobalFrame(); + + // default options + fBatch = 0; + fInitSource = 1; + fInitRead = 0; + fFinalWrite = 0; + sInFile = sOutFile = NULL; + sprintf( sReadCmd, "read" ); + sprintf( sWriteCmd, "write" ); + + Extra_UtilGetoptReset(); + while ((c = Extra_UtilGetopt(argc, argv, "c:hf:F:o:st:T:x")) != EOF) { + switch(c) { + case 'c': + strcpy( sCommandUsr, globalUtilOptarg ); + fBatch = 1; + break; + + case 'f': + sprintf(sCommandUsr, "source %s", globalUtilOptarg); + fBatch = 1; + break; + + case 'F': + sprintf(sCommandUsr, "source -x %s", globalUtilOptarg); + fBatch = 1; + break; + + case 'h': + goto usage; + break; + + case 'o': + sOutFile = globalUtilOptarg; + fFinalWrite = 1; + break; + + case 's': + fInitSource = 0; + break; + + case 't': + if ( TypeCheck( pAbc, globalUtilOptarg ) ) + { + if ( !strcmp(globalUtilOptarg, "none") == 0 ) + { + fInitRead = 1; + sprintf( sReadCmd, "read_%s", globalUtilOptarg ); + } + } + else { + goto usage; + } + fBatch = 1; + break; + + case 'T': + if ( TypeCheck( pAbc, globalUtilOptarg ) ) + { + if (!strcmp(globalUtilOptarg, "none") == 0) + { + fFinalWrite = 1; + sprintf( sWriteCmd, "write_%s", globalUtilOptarg); + } + } + else { + goto usage; + } + fBatch = 1; + break; + + case 'x': + fFinalWrite = 0; + fInitRead = 0; + fBatch = 1; + break; + + default: + goto usage; + } + } + + if ( fBatch ) + { + pAbc->fBatchMode = 1; + + if (argc - globalUtilOptind == 0) + { + sInFile = NULL; + } + else if (argc - globalUtilOptind == 1) + { + fInitRead = 1; + sInFile = argv[globalUtilOptind]; + } + else + { + Abc_UtilsPrintUsage( pAbc, argv[0] ); + } + + // source the resource file + if ( fInitSource ) + { + Abc_UtilsSource( pAbc ); + } + + fStatus = 0; + if ( fInitRead && sInFile ) + { + sprintf( sCommandTmp, "%s %s", sReadCmd, sInFile ); + fStatus = Cmd_CommandExecute( pAbc, sCommandTmp ); + } + + if ( fStatus == 0 ) + { + /* cmd line contains `source ' */ + fStatus = Cmd_CommandExecute( pAbc, sCommandUsr ); + if ( (fStatus == 0 || fStatus == -1) && fFinalWrite && sOutFile ) + { + sprintf( sCommandTmp, "%s %s", sWriteCmd, sOutFile ); + fStatus = Cmd_CommandExecute( pAbc, sCommandTmp ); + } + } + + } + else + { + // start interactive mode + // print the hello line + Abc_UtilsPrintHello( pAbc ); + + // source the resource file + if ( fInitSource ) + { + Abc_UtilsSource( pAbc ); + } + + // execute commands given by the user + while ( !feof(stdin) ) + { + // print command line prompt and + // get the command from the user + sCommand = Abc_UtilsGetUsersInput( pAbc ); + + // execute the user's command + fStatus = Cmd_CommandExecute( pAbc, sCommand ); + + // stop if the user quitted or an error occurred + if ( fStatus == -1 || fStatus == -2 ) + break; + } + } + + // if the memory should be freed, quit packages + if ( fStatus < 0 ) + { + Abc_Stop(); + } + return 0; + +usage: + Abc_UtilsPrintHello( pAbc ); + Abc_UtilsPrintUsage( pAbc, argv[0] ); + return 1; +} + +#endif + +/**Function************************************************************* + + Synopsis [Initialization procedure for the library project.] + + Description [Note that when Abc_Start() is run in a static library + project, it does not load the resource file by default. As a result, + ABC is not set up the same way, as when it is run on a command line. + For example, some error messages while parsing files will not be + produced, and intermediate networks will not be checked for consistancy. + One possibility is to load the resource file after Abc_Start() as follows: + Abc_UtilsSource( Abc_FrameGetGlobalFrame() );] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Start() +{ + Abc_Frame_t * pAbc; + // added to detect memory leaks: +#ifdef _DEBUG + _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); +#endif + // start the glocal frame + pAbc = Abc_FrameGetGlobalFrame(); + // source the resource file +// Abc_UtilsSource( pAbc ); +} + +/**Function************************************************************* + + Synopsis [Deallocation procedure for the library project.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Stop() +{ + Abc_Frame_t * pAbc; + pAbc = Abc_FrameGetGlobalFrame(); + // perform uninitializations + Abc_FrameEnd( pAbc ); + // stop the framework + Abc_FrameDeallocate( pAbc ); +} + +/**Function******************************************************************** + + Synopsis [Returns 1 if s is a file type recognized, else returns 0.] + + Description [Returns 1 if s is a file type recognized by ABC, else returns 0. + Recognized types are "blif", "bench", "pla", and "none".] + + SideEffects [] + +******************************************************************************/ +static int TypeCheck( Abc_Frame_t * pAbc, char * s ) +{ + if (strcmp(s, "blif") == 0) + return 1; + else if (strcmp(s, "bench") == 0) + return 1; + else if (strcmp(s, "pla") == 0) + return 1; + else if (strcmp(s, "none") == 0) + return 1; + else { + fprintf( pAbc->Err, "unknown type %s\n", s ); + return 0; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/main/main.h b/abc70930/src/base/main/main.h new file mode 100644 index 00000000..4433a8b4 --- /dev/null +++ b/abc70930/src/base/main/main.h @@ -0,0 +1,122 @@ +/**CFile**************************************************************** + + FileName [main.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [External declarations of the main package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: main.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __MAIN_H__ +#define __MAIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// TYPEDEFS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// the framework containing all data +typedef struct Abc_Frame_t_ Abc_Frame_t; + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +// this include should be the first one in the list +// it is used to catch memory leaks on Windows +#include "leaks.h" + +// data structure packages +#include "extra.h" +#include "vec.h" +#include "st.h" + +// core packages +#include "abc.h" +#include "cmd.h" +#include "io.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== main.c ===========================================================*/ +extern void Abc_Start(); +extern void Abc_Stop(); + +/*=== mainFrame.c ===========================================================*/ +extern Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p ); +extern FILE * Abc_FrameReadOut( Abc_Frame_t * p ); +extern FILE * Abc_FrameReadErr( Abc_Frame_t * p ); +extern bool Abc_FrameReadMode( Abc_Frame_t * p ); +extern bool Abc_FrameSetMode( Abc_Frame_t * p, bool fNameMode ); +extern void Abc_FrameRestart( Abc_Frame_t * p ); +extern bool Abc_FrameShowProgress( Abc_Frame_t * p ); + +extern void Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet ); +extern void Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p ); +extern void Abc_FrameReplaceCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet ); +extern void Abc_FrameUnmapAllNetworks( Abc_Frame_t * p ); +extern void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p ); + +extern void Abc_FrameSetGlobalFrame( Abc_Frame_t * p ); +extern Abc_Frame_t * Abc_FrameGetGlobalFrame(); + +extern Vec_Ptr_t * Abc_FrameReadStore(); +extern int Abc_FrameReadStoreSize(); +extern void * Abc_FrameReadLibLut(); +extern void * Abc_FrameReadLibGen(); +extern void * Abc_FrameReadLibSuper(); +extern void * Abc_FrameReadLibVer(); +extern void * Abc_FrameReadManDd(); +extern void * Abc_FrameReadManDec(); +extern char * Abc_FrameReadFlag( char * pFlag ); +extern bool Abc_FrameIsFlagEnabled( char * pFlag ); + +extern void Abc_FrameSetNtkStore( Abc_Ntk_t * pNtk ); +extern void Abc_FrameSetNtkStoreSize( int nStored ); +extern void Abc_FrameSetLibLut( void * pLib ); +extern void Abc_FrameSetLibGen( void * pLib ); +extern void Abc_FrameSetLibSuper( void * pLib ); +extern void Abc_FrameSetLibVer( void * pLib ); +extern void Abc_FrameSetFlag( char * pFlag, char * pValue ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/main/mainFrame.c b/abc70930/src/base/main/mainFrame.c new file mode 100644 index 00000000..eae8b7a6 --- /dev/null +++ b/abc70930/src/base/main/mainFrame.c @@ -0,0 +1,503 @@ +/**CFile**************************************************************** + + FileName [mainFrame.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [The global framework resides in this file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mainFrame.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" +#include "abc.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Frame_t * s_GlobalFrame = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [APIs to access parameters in the flobal frame.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_FrameReadStore() { return s_GlobalFrame->vStore; } +int Abc_FrameReadStoreSize() { return Vec_PtrSize(s_GlobalFrame->vStore); } +void * Abc_FrameReadLibLut() { return s_GlobalFrame->pLibLut; } +void * Abc_FrameReadLibGen() { return s_GlobalFrame->pLibGen; } +void * Abc_FrameReadLibSuper() { return s_GlobalFrame->pLibSuper; } +void * Abc_FrameReadLibVer() { return s_GlobalFrame->pLibVer; } +void * Abc_FrameReadManDd() { if ( s_GlobalFrame->dd == NULL ) s_GlobalFrame->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); return s_GlobalFrame->dd; } +void * Abc_FrameReadManDec() { if ( s_GlobalFrame->pManDec == NULL ) s_GlobalFrame->pManDec = Dec_ManStart(); return s_GlobalFrame->pManDec; } +char * Abc_FrameReadFlag( char * pFlag ) { return Cmd_FlagReadByName( s_GlobalFrame, pFlag ); } + +void Abc_FrameSetLibLut( void * pLib ) { s_GlobalFrame->pLibLut = pLib; } +void Abc_FrameSetLibGen( void * pLib ) { s_GlobalFrame->pLibGen = pLib; } +void Abc_FrameSetLibSuper( void * pLib ) { s_GlobalFrame->pLibSuper = pLib; } +void Abc_FrameSetLibVer( void * pLib ) { s_GlobalFrame->pLibVer = pLib; } +void Abc_FrameSetFlag( char * pFlag, char * pValue ) { Cmd_FlagUpdateValue( s_GlobalFrame, pFlag, pValue ); } + +/**Function************************************************************* + + Synopsis [Returns 1 if the flag is enabled without value or with value 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_FrameIsFlagEnabled( char * pFlag ) +{ + char * pValue; + // if flag is not defined, it is not enabled + pValue = Abc_FrameReadFlag( pFlag ); + if ( pValue == NULL ) + return 0; + // if flag is defined but value is not empty (no parameter) or "1", it is not enabled + if ( strcmp(pValue, "") && strcmp(pValue, "1") ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Frame_t * Abc_FrameAllocate() +{ + Abc_Frame_t * p; + extern void define_cube_size( int n ); + extern void set_espresso_flags(); + // allocate and clean + p = ALLOC( Abc_Frame_t, 1 ); + memset( p, 0, sizeof(Abc_Frame_t) ); + // get version + p->sVersion = Abc_UtilsGetVersion( p ); + // set streams + p->Err = stderr; + p->Out = stdout; + p->Hst = NULL; + // set the starting step + p->nSteps = 1; + p->fBatchMode = 0; + // networks to be used by choice + p->vStore = Vec_PtrAlloc( 16 ); + // initialize decomposition manager + define_cube_size(20); + set_espresso_flags(); + // initialize the trace manager +// Abc_HManStart(); + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameDeallocate( Abc_Frame_t * p ) +{ + extern void Rwt_ManGlobalStop(); + extern void undefine_cube_size(); +// extern void Ivy_TruthManStop(); +// Abc_HManStop(); + undefine_cube_size(); + Rwt_ManGlobalStop(); +// Ivy_TruthManStop(); + if ( p->pLibVer ) Abc_LibFree( p->pLibVer, NULL ); + if ( p->pManDec ) Dec_ManStop( p->pManDec ); + if ( p->dd ) Extra_StopManager( p->dd ); + if ( p->vStore ) Vec_PtrFree( p->vStore ); + Abc_FrameDeleteAllNetworks( p ); + free( p ); + s_GlobalFrame = NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameRestart( Abc_Frame_t * p ) +{ +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_FrameShowProgress( Abc_Frame_t * p ) +{ + return Abc_FrameIsFlagEnabled( "progressbar" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p ) +{ + return p->pNtkCur; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +FILE * Abc_FrameReadOut( Abc_Frame_t * p ) +{ + return p->Out; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +FILE * Abc_FrameReadErr( Abc_Frame_t * p ) +{ + return p->Err; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_FrameReadMode( Abc_Frame_t * p ) +{ + int fShortNames; + char * pValue; + pValue = Cmd_FlagReadByName( p, "namemode" ); + if ( pValue == NULL ) + fShortNames = 0; + else + fShortNames = atoi(pValue); + return fShortNames; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Abc_FrameSetMode( Abc_Frame_t * p, bool fNameMode ) +{ + char Buffer[2]; + bool fNameModeOld; + fNameModeOld = Abc_FrameReadMode( p ); + Buffer[0] = '0' + fNameMode; + Buffer[1] = 0; + Cmd_FlagUpdateValue( p, "namemode", (char *)Buffer ); + return fNameModeOld; +} + + +/**Function************************************************************* + + Synopsis [Sets the given network to be the current one.] + + Description [Takes the network and makes it the current network. + The previous current network is attached to the given network as + a backup copy. In the stack of backup networks contains too many + networks (defined by the paramater "savesteps"), the bottom + most network is deleted.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNtkNew ) +{ + Abc_Ntk_t * pNtk, * pNtk2, * pNtk3; + int nNetsPresent; + int nNetsToSave; + char * pValue; + + // link it to the previous network + Abc_NtkSetBackup( pNtkNew, p->pNtkCur ); + // set the step of this network + Abc_NtkSetStep( pNtkNew, ++p->nSteps ); + // set this network to be the current network + p->pNtkCur = pNtkNew; + + // remove any extra network that may happen to be in the stack + pValue = Cmd_FlagReadByName( p, "savesteps" ); + // if the value of steps to save is not set, assume 1-level undo + if ( pValue == NULL ) + nNetsToSave = 1; + else + nNetsToSave = atoi(pValue); + + // count the network, remember the last one, and the one before the last one + nNetsPresent = 0; + pNtk2 = pNtk3 = NULL; + for ( pNtk = p->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk2) ) + { + nNetsPresent++; + pNtk3 = pNtk2; + pNtk2 = pNtk; + } + + // remove the earliest backup network if it is more steps away than we store + if ( nNetsPresent - 1 > nNetsToSave ) + { // delete the last network + Abc_NtkDelete( pNtk2 ); + // clean the pointer of the network before the last one + Abc_NtkSetBackup( pNtk3, NULL ); + } +} + +/**Function************************************************************* + + Synopsis [This procedure swaps the current and the backup network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p ) +{ + Abc_Ntk_t * pNtkCur, * pNtkBack, * pNtkBack2; + int iStepCur, iStepBack; + + pNtkCur = p->pNtkCur; + pNtkBack = Abc_NtkBackup( pNtkCur ); + iStepCur = Abc_NtkStep ( pNtkCur ); + + // if there is no backup nothing to reset + if ( pNtkBack == NULL ) + return; + + // remember the backup of the backup + pNtkBack2 = Abc_NtkBackup( pNtkBack ); + iStepBack = Abc_NtkStep ( pNtkBack ); + + // set pNtkCur to be the next after the backup's backup + Abc_NtkSetBackup( pNtkCur, pNtkBack2 ); + Abc_NtkSetStep ( pNtkCur, iStepBack ); + + // set pNtkCur to be the next after the backup + Abc_NtkSetBackup( pNtkBack, pNtkCur ); + Abc_NtkSetStep ( pNtkBack, iStepCur ); + + // set the current network + p->pNtkCur = pNtkBack; +} + + +/**Function************************************************************* + + Synopsis [Replaces the current network by the given one.] + + Description [This procedure does not modify the stack of saved + networks.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameReplaceCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNtk ) +{ + if ( pNtk == NULL ) + return; + + // transfer the parameters to the new network + if ( p->pNtkCur && Abc_FrameIsFlagEnabled( "backup" ) ) + { + Abc_NtkSetBackup( pNtk, Abc_NtkBackup(p->pNtkCur) ); + Abc_NtkSetStep( pNtk, Abc_NtkStep(p->pNtkCur) ); + // delete the current network + Abc_NtkDelete( p->pNtkCur ); + } + else + { + Abc_NtkSetBackup( pNtk, NULL ); + Abc_NtkSetStep( pNtk, ++p->nSteps ); + // delete the current network if present but backup is disabled + if ( p->pNtkCur ) + Abc_NtkDelete( p->pNtkCur ); + } + // set the new current network + p->pNtkCur = pNtk; +} + +/**Function************************************************************* + + Synopsis [Removes library binding of all currently stored networks.] + + Description [This procedure is called when the library is freed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameUnmapAllNetworks( Abc_Frame_t * p ) +{ + Abc_Ntk_t * pNtk; + for ( pNtk = p->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk) ) + if ( Abc_NtkHasMapping(pNtk) ) + Abc_NtkMapToSop( pNtk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p ) +{ + Abc_Ntk_t * pNtk, * pNtk2; + // delete all the currently saved networks + for ( pNtk = p->pNtkCur, + pNtk2 = pNtk? Abc_NtkBackup(pNtk): NULL; + pNtk; + pNtk = pNtk2, + pNtk2 = pNtk? Abc_NtkBackup(pNtk): NULL ) + Abc_NtkDelete( pNtk ); + // set the current network empty + p->pNtkCur = NULL; +// fprintf( p->Out, "All networks have been deleted.\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameSetGlobalFrame( Abc_Frame_t * p ) +{ + s_GlobalFrame = p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Frame_t * Abc_FrameGetGlobalFrame() +{ + if ( s_GlobalFrame == 0 ) + { + // start the framework + s_GlobalFrame = Abc_FrameAllocate(); + // perform initializations + Abc_FrameInit( s_GlobalFrame ); + } + return s_GlobalFrame; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/main/mainInit.c b/abc70930/src/base/main/mainInit.c new file mode 100644 index 00000000..03953e5b --- /dev/null +++ b/abc70930/src/base/main/mainInit.c @@ -0,0 +1,100 @@ +/**CFile**************************************************************** + + FileName [mainInit.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [Initialization procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mainInit.c,v 1.3 2005/09/14 22:53:37 casem Exp $] + +***********************************************************************/ + +#include "mainInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Abc_Init( Abc_Frame_t * pAbc ); +extern void Abc_End ( Abc_Frame_t * pAbc ); +extern void Io_Init( Abc_Frame_t * pAbc ); +extern void Io_End ( Abc_Frame_t * pAbc ); +extern void Cmd_Init( Abc_Frame_t * pAbc ); +extern void Cmd_End ( Abc_Frame_t * pAbc ); +extern void Fpga_Init( Abc_Frame_t * pAbc ); +extern void Fpga_End ( Abc_Frame_t * pAbc ); +extern void Map_Init( Abc_Frame_t * pAbc ); +extern void Map_End ( Abc_Frame_t * pAbc ); +extern void Mio_Init( Abc_Frame_t * pAbc ); +extern void Mio_End ( Abc_Frame_t * pAbc ); +extern void Super_Init( Abc_Frame_t * pAbc ); +extern void Super_End ( Abc_Frame_t * pAbc ); +extern void Libs_Init(Abc_Frame_t * pAbc); +extern void Libs_End(Abc_Frame_t * pAbc); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts all the packages.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameInit( Abc_Frame_t * pAbc ) +{ + Cmd_Init( pAbc ); + Io_Init( pAbc ); + Abc_Init( pAbc ); + Fpga_Init( pAbc ); + Map_Init( pAbc ); + Mio_Init( pAbc ); + Super_Init( pAbc ); + Libs_Init( pAbc ); +} + + +/**Function************************************************************* + + Synopsis [Stops all the packages.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameEnd( Abc_Frame_t * pAbc ) +{ + Abc_End( pAbc ); + Io_End( pAbc ); + Cmd_End( pAbc ); + Fpga_End( pAbc ); + Map_End( pAbc ); + Mio_End( pAbc ); + Super_End( pAbc ); + Libs_End( pAbc ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/main/mainInt.h b/abc70930/src/base/main/mainInt.h new file mode 100644 index 00000000..09ad96f3 --- /dev/null +++ b/abc70930/src/base/main/mainInt.h @@ -0,0 +1,109 @@ +/**CFile**************************************************************** + + FileName [mainInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [Internal declarations of the main package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mainInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __MAIN_INT_H__ +#define __MAIN_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "main.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// the current version +#define ABC_VERSION "UC Berkeley, ABC 1.01" + +// the maximum length of an input line +#define MAX_STR 32768 + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Abc_Frame_t_ +{ + // general info + char * sVersion; // the name of the current version + // commands, aliases, etc + st_table * tCommands; // the command table + st_table * tAliases; // the alias table + st_table * tFlags; // the flag table + Vec_Ptr_t * aHistory; // the command history + // the functionality + Abc_Ntk_t * pNtkCur; // the current network + int nSteps; // the counter of different network processed + int fAutoexac; // marks the autoexec mode + int fBatchMode; // are we invoked in batch mode? + // output streams + FILE * Out; + FILE * Err; + FILE * Hst; + // used for runtime measurement + int TimeCommand; // the runtime of the last command + int TimeTotal; // the total runtime of all commands + // temporary storage for structural choices + Vec_Ptr_t * vStore; // networks to be used by choice + // decomposition package + void * pManDec; // decomposition manager + DdManager * dd; // temporary BDD package + // libraries for mapping + void * pLibLut; // the current LUT library + void * pLibGen; // the current genlib + void * pLibSuper; // the current supergate library + void * pLibVer; // the current Verilog library +}; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== mvMain.c ===========================================================*/ +extern int main( int argc, char * argv[] ); +/*=== mvInit.c ===================================================*/ +extern void Abc_FrameInit( Abc_Frame_t * pAbc ); +extern void Abc_FrameEnd( Abc_Frame_t * pAbc ); +/*=== mvFrame.c =====================================================*/ +extern Abc_Frame_t * Abc_FrameAllocate(); +extern void Abc_FrameDeallocate( Abc_Frame_t * p ); +/*=== mvUtils.c =====================================================*/ +extern char * Abc_UtilsGetVersion( Abc_Frame_t * pAbc ); +extern char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc ); +extern void Abc_UtilsPrintHello( Abc_Frame_t * pAbc ); +extern void Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName ); +extern void Abc_UtilsSource( Abc_Frame_t * pAbc ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/base/main/mainUtils.c b/abc70930/src/base/main/mainUtils.c new file mode 100644 index 00000000..58cc33ec --- /dev/null +++ b/abc70930/src/base/main/mainUtils.c @@ -0,0 +1,277 @@ +/**CFile**************************************************************** + + FileName [mainUtils.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [The main package.] + + Synopsis [Miscellaneous utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: mainUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mainInt.h" + +#ifndef _WIN32 +#include "readline/readline.h" +#endif + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// +static char * DateReadFromDateString(char * datestr); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_UtilsGetVersion( Abc_Frame_t * pAbc ) +{ + static char Version[1000]; + sprintf(Version, "%s (compiled %s %s)", ABC_VERSION, __DATE__, __TIME__); + return Version; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc ) +{ + static char Buffer[1000], Prompt[1000]; + sprintf( Prompt, "abc %02d> ", pAbc->nSteps ); +#ifdef _WIN32 + fprintf( pAbc->Out, "%s", Prompt ); + fgets( Buffer, 999, stdin ); + return Buffer; +#else + static char* line = NULL; + if (line != NULL) free(line); + line = readline(Prompt); + if (line == NULL){ printf("***EOF***\n"); exit(0); } + add_history(line); + return line; +#endif +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_UtilsPrintHello( Abc_Frame_t * pAbc ) +{ + fprintf( pAbc->Out, "%s\n", pAbc->sVersion ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName ) +{ + fprintf( pAbc->Err, "\n" ); + fprintf( pAbc->Err, + "usage: %s [-c cmd] [-f script] [-h] [-o file] [-s] [-t type] [-T type] [-x] [file]\n", + ProgName); + fprintf( pAbc->Err, " -c cmd\texecute commands `cmd'\n"); + fprintf( pAbc->Err, " -F script\texecute commands from a script file and echo commands\n"); + fprintf( pAbc->Err, " -f script\texecute commands from a script file\n"); + fprintf( pAbc->Err, " -h\t\tprint the command usage\n"); + fprintf( pAbc->Err, " -o file\tspecify output filename to store the result\n"); + fprintf( pAbc->Err, " -s\t\tdo not read any initialization file\n"); + fprintf( pAbc->Err, " -t type\tspecify input type (blif_mv (default), blif_mvs, blif, or none)\n"); + fprintf( pAbc->Err, " -T type\tspecify output type (blif_mv (default), blif_mvs, blif, or none)\n"); + fprintf( pAbc->Err, " -x\t\tequivalent to '-t none -T none'\n"); + fprintf( pAbc->Err, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_UtilsSource( Abc_Frame_t * pAbc ) +{ +#ifdef WIN32 + if ( Cmd_CommandExecute(pAbc, "source abc.rc") ) + { + if ( Cmd_CommandExecute(pAbc, "source ..\\abc.rc") == 0 ) + printf( "Loaded \"abc.rc\" from the parent directory.\n" ); + else if ( Cmd_CommandExecute(pAbc, "source ..\\..\\abc.rc") == 0 ) + printf( "Loaded \"abc.rc\" from the grandparent directory.\n" ); + } +#else + +#if 0 + { + char * sPath1, * sPath2; + + // If .rc is present in both the home and current directories, then read + // it from the home directory. Otherwise, read it from wherever it's located. + sPath1 = Extra_UtilFileSearch(".rc", "~/", "r"); + sPath2 = Extra_UtilFileSearch(".rc", ".", "r"); + + if ( sPath1 && sPath2 ) { + /* ~/.rc == .rc : Source the file only once */ + (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc"); + } + else { + if (sPath1) { + (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc"); + } + if (sPath2) { + (void) Cmd_CommandExecute(pAbc, "source -s .rc"); + } + } + if ( sPath1 ) FREE(sPath1); + if ( sPath2 ) FREE(sPath2); + + /* execute the abc script which can be open with the "open_path" */ + Cmd_CommandExecute( pAbc, "source -s abc.rc" ); + } +#endif + + { + char * sPath1, * sPath2; + char * home; + + // If .rc is present in both the home and current directories, then read + // it from the home directory. Otherwise, read it from wherever it's located. + home = getenv("HOME"); + if (home){ + char * sPath3 = ALLOC(char, strlen(home) + 2); + (void) sprintf(sPath3, "%s/", home); + sPath1 = Extra_UtilFileSearch(".abc.rc", sPath3, "r"); + FREE(sPath3); + }else + sPath1 = NULL; + + sPath2 = Extra_UtilFileSearch(".abc.rc", ".", "r"); + + if ( sPath1 && sPath2 ) { + /* ~/.rc == .rc : Source the file only once */ + (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc"); + } + else { + if (sPath1) { + (void) Cmd_CommandExecute(pAbc, "source -s ~/.abc.rc"); + } + if (sPath2) { + (void) Cmd_CommandExecute(pAbc, "source -s .abc.rc"); + } + } + if ( sPath1 ) FREE(sPath1); + if ( sPath2 ) FREE(sPath2); + + /* execute the abc script which can be open with the "open_path" */ + Cmd_CommandExecute( pAbc, "source -s abc.rc" ); + } + +#endif //WIN32 + { + // reset command history + char * pName; + int i; + Vec_PtrForEachEntry( pAbc->aHistory, pName, i ) + free( pName ); + pAbc->aHistory->nSize = 0; + } +} + +/**Function******************************************************************** + + Synopsis [Returns the date in a brief format assuming its coming from + the program `date'.] + + Description [optional] + + SideEffects [] + +******************************************************************************/ +char * +DateReadFromDateString( + char * datestr) +{ + static char result[25]; + char day[10]; + char month[10]; + char zone[10]; + char *at; + int date; + int hour; + int minute; + int second; + int year; + + if (sscanf(datestr, "%s %s %2d %2d:%2d:%2d %s %4d", + day, month, &date, &hour, &minute, &second, zone, &year) == 8) { + if (hour >= 12) { + if (hour >= 13) hour -= 12; + at = "PM"; + } + else { + if (hour == 0) hour = 12; + at = "AM"; + } + (void) sprintf(result, "%d-%3s-%02d at %d:%02d %s", + date, month, year % 100, hour, minute, at); + return result; + } + else { + return datestr; + } +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/main/module.make b/abc70930/src/base/main/module.make new file mode 100644 index 00000000..367f89f6 --- /dev/null +++ b/abc70930/src/base/main/module.make @@ -0,0 +1,5 @@ +SRC += src/base/main/main.c \ + src/base/main/mainFrame.c \ + src/base/main/mainInit.c \ + src/base/main/libSupport.c \ + src/base/main/mainUtils.c diff --git a/abc70930/src/base/temp.c b/abc70930/src/base/temp.c new file mode 100644 index 00000000..55709247 --- /dev/null +++ b/abc70930/src/base/temp.c @@ -0,0 +1,83 @@ + +/**Function************************************************************* + + Synopsis [Command procedure to allow for static BDD variable ordering.] + + Description [This procedure should be integrated in "abc\src\base\abci\abc.c" + similar to how procedure Abc_CommandReorder() is currently integrated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pOut, * pErr, * pFile; + Abc_Ntk_t * pNtk; + char * pFileName; + int c; + int fReverse; + int fVerbose; + extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ); + extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set defaults + fReverse = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + fReverse ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty network.\n" ); + return 1; + } + + // if the var order file is given, implement this order + pFileName = NULL; + if ( argc == globalUtilOptind + 1 ) + { + pFileName = argv[globalUtilOptind]; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + fprintf( pErr, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName ); + return 1; + } + fclose( pFile ); + } + if ( pFileName ) + Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose ); + else + Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose ); + return 0; + +usage: + fprintf( pErr, "usage: order [-rvh] \n" ); + fprintf( pErr, "\t computes a good static CI variable order\n" ); + fprintf( pErr, "\t-r : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" ); + fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t : (optional) file with the given variable order\n" ); + return 1; +} diff --git a/abc70930/src/base/ver/module.make b/abc70930/src/base/ver/module.make new file mode 100644 index 00000000..2cc37803 --- /dev/null +++ b/abc70930/src/base/ver/module.make @@ -0,0 +1,4 @@ +SRC += src/base/ver/verCore.c \ + src/base/ver/verFormula.c \ + src/base/ver/verParse.c \ + src/base/ver/verStream.c diff --git a/abc70930/src/base/ver/ver.h b/abc70930/src/base/ver/ver.h new file mode 100644 index 00000000..9c538ac4 --- /dev/null +++ b/abc70930/src/base/ver/ver.h @@ -0,0 +1,118 @@ +/**CFile**************************************************************** + + FileName [ver.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: ver.h,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __VER_H__ +#define __VER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ver_Man_t_ Ver_Man_t; +typedef struct Ver_Stream_t_ Ver_Stream_t; + +struct Ver_Man_t_ +{ + // internal parameters + int fMapped; // mapped verilog + int fUseMemMan; // allocate memory manager in the networks + int fCheck; // checks network for currectness + // input file stream + char * pFileName; + Ver_Stream_t * pReader; + int fNameLast; + ProgressBar * pProgress; + // current design + Abc_Lib_t * pDesign; + st_table * tName2Suffix; + // error handling + FILE * Output; + int fTopLevel; + int fError; + char sError[2000]; + // intermediate structures + Vec_Ptr_t * vNames; + Vec_Ptr_t * vStackFn; + Vec_Int_t * vStackOp; + Vec_Int_t * vPerm; +}; + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== verCore.c ========================================================*/ +extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); +extern void Ver_ParsePrintErrorMessage( Ver_Man_t * p ); +/*=== verFormula.c ========================================================*/ +extern void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ); +extern void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ); +/*=== verParse.c ========================================================*/ +extern int Ver_ParseSkipComments( Ver_Man_t * p ); +extern char * Ver_ParseGetName( Ver_Man_t * p ); +/*=== verStream.c ========================================================*/ +extern Ver_Stream_t * Ver_StreamAlloc( char * pFileName ); +extern void Ver_StreamFree( Ver_Stream_t * p ); +extern char * Ver_StreamGetFileName( Ver_Stream_t * p ); +extern int Ver_StreamGetFileSize( Ver_Stream_t * p ); +extern int Ver_StreamGetCurPosition( Ver_Stream_t * p ); +extern int Ver_StreamGetLineNumber( Ver_Stream_t * p ); + +extern int Ver_StreamIsOkey( Ver_Stream_t * p ); +extern char Ver_StreamScanChar( Ver_Stream_t * p ); +extern char Ver_StreamPopChar( Ver_Stream_t * p ); +extern void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ); +extern void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ); +extern char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/base/ver/verCore.c b/abc70930/src/base/ver/verCore.c new file mode 100644 index 00000000..7a217fd7 --- /dev/null +++ b/abc70930/src/base/ver/verCore.c @@ -0,0 +1,2840 @@ +/**CFile**************************************************************** + + FileName [verCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Parses several flavors of structural Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verCore.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" +#include "mio.h" +#include "main.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// types of verilog signals +typedef enum { + VER_SIG_NONE = 0, + VER_SIG_INPUT, + VER_SIG_OUTPUT, + VER_SIG_INOUT, + VER_SIG_REG, + VER_SIG_WIRE +} Ver_SignalType_t; + +// types of verilog gates +typedef enum { + VER_GATE_AND = 0, + VER_GATE_OR, + VER_GATE_XOR, + VER_GATE_BUF, + VER_GATE_NAND, + VER_GATE_NOR, + VER_GATE_XNOR, + VER_GATE_NOT +} Ver_GateType_t; + +static Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib ); +static void Ver_ParseStop( Ver_Man_t * p ); +static void Ver_ParseFreeData( Ver_Man_t * p ); +static void Ver_ParseInternal( Ver_Man_t * p ); +static int Ver_ParseModule( Ver_Man_t * p ); +static int Ver_ParseSignal( Ver_Man_t * p, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType ); +static int Ver_ParseAlways( Ver_Man_t * p, Abc_Ntk_t * pNtk ); +static int Ver_ParseInitial( Ver_Man_t * p, Abc_Ntk_t * pNtk ); +static int Ver_ParseAssign( Ver_Man_t * p, Abc_Ntk_t * pNtk ); +static int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType ); +static int Ver_ParseGate( Ver_Man_t * p, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate ); +static int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox ); +static int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox ); +static int Ver_ParseAttachBoxes( Ver_Man_t * pMan ); + +static Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ); +static Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ); +static Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO ); +static Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ); + +static void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan ); + +static inline int Ver_NtkIsDefined( Abc_Ntk_t * pNtkBox ) { assert( pNtkBox->pName ); return Abc_NtkPiNum(pNtkBox) || Abc_NtkPoNum(pNtkBox); } +static inline int Ver_ObjIsConnected( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBox(pObj) ); return Abc_ObjFaninNum(pObj) || Abc_ObjFanoutNum(pObj); } + +int glo_fMapped = 0; // this is bad! + +typedef struct Ver_Bundle_t_ Ver_Bundle_t; +struct Ver_Bundle_t_ +{ + char * pNameFormal; // the name of the formal net + Vec_Ptr_t * vNetsActual; // the vector of actual nets (MSB to LSB) +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib ) +{ + Ver_Man_t * p; + p = ALLOC( Ver_Man_t, 1 ); + memset( p, 0, sizeof(Ver_Man_t) ); + p->pFileName = pFileName; + p->pReader = Ver_StreamAlloc( pFileName ); + if ( p->pReader == NULL ) + return NULL; + p->Output = stdout; + p->vNames = Vec_PtrAlloc( 100 ); + p->vStackFn = Vec_PtrAlloc( 100 ); + p->vStackOp = Vec_IntAlloc( 100 ); + p->vPerm = Vec_IntAlloc( 100 ); + // create the design library and assign the technology library + p->pDesign = Abc_LibCreate( pFileName ); + p->pDesign->pLibrary = pGateLib; + p->pDesign->pGenlib = Abc_FrameReadLibGen(); + return p; +} + +/**Function************************************************************* + + Synopsis [Stop parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseStop( Ver_Man_t * p ) +{ + if ( p->pProgress ) + Extra_ProgressBarStop( p->pProgress ); + Ver_StreamFree( p->pReader ); + Vec_PtrFree( p->vNames ); + Vec_PtrFree( p->vStackFn ); + Vec_IntFree( p->vStackOp ); + Vec_IntFree( p->vPerm ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [File parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ) +{ + Ver_Man_t * p; + Abc_Lib_t * pDesign; + // start the parser + p = Ver_ParseStart( pFileName, pGateLib ); + p->fMapped = glo_fMapped; + p->fCheck = fCheck; + p->fUseMemMan = fUseMemMan; + if ( glo_fMapped ) + { + Hop_ManStop(p->pDesign->pManFunc); + p->pDesign->pManFunc = NULL; + } + // parse the file + Ver_ParseInternal( p ); + // save the result + pDesign = p->pDesign; + p->pDesign = NULL; + // stop the parser + Ver_ParseStop( p ); + return pDesign; +} + +/**Function************************************************************* + + Synopsis [File parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseInternal( Ver_Man_t * pMan ) +{ + Abc_Ntk_t * pNtk; + char * pToken; + int i; + + // preparse the modeles + pMan->pProgress = Extra_ProgressBarStart( stdout, Ver_StreamGetFileSize(pMan->pReader) ); + while ( 1 ) + { + // get the next token + pToken = Ver_ParseGetName( pMan ); + if ( pToken == NULL ) + break; + if ( strcmp( pToken, "module" ) ) + { + sprintf( pMan->sError, "Cannot read \"module\" directive." ); + Ver_ParsePrintErrorMessage( pMan ); + return; + } + // parse the module + if ( !Ver_ParseModule(pMan) ) + return; + } + Extra_ProgressBarStop( pMan->pProgress ); + pMan->pProgress = NULL; + + // process defined and undefined boxes + if ( !Ver_ParseAttachBoxes( pMan ) ) + return; + + // connect the boxes and check + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + // fix the dangling nets + Abc_NtkFinalizeRead( pNtk ); + // check the network for correctness + if ( pMan->fCheck && !Abc_NtkCheckRead( pNtk ) ) + { + pMan->fTopLevel = 1; + sprintf( pMan->sError, "The network check has failed for network %s.", pNtk->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return; + } + } +} + +/**Function************************************************************* + + Synopsis [File parser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseFreeData( Ver_Man_t * p ) +{ + if ( p->pDesign ) + { + Abc_LibFree( p->pDesign, NULL ); + p->pDesign = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Prints the error message including the file name and line number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParsePrintErrorMessage( Ver_Man_t * p ) +{ + p->fError = 1; + if ( p->fTopLevel ) // the line number is not given + fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); + else // print the error message with the line number + fprintf( p->Output, "%s (line %d): %s\n", + p->pFileName, Ver_StreamGetLineNumber(p->pReader), p->sError ); + // free the data + Ver_ParseFreeData( p ); +} + +/**Function************************************************************* + + Synopsis [Finds the network by name or create a new blackbox network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Ver_ParseFindOrCreateNetwork( Ver_Man_t * pMan, char * pName ) +{ + Abc_Ntk_t * pNtkNew; + // check if the network exists + if ( pNtkNew = Abc_LibFindModelByName( pMan->pDesign, pName ) ) + return pNtkNew; +//printf( "Creating network %s.\n", pName ); + // create new network + pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, pMan->fUseMemMan ); + pNtkNew->pName = Extra_UtilStrsav( pName ); + pNtkNew->pSpec = NULL; + // add module to the design + Abc_LibAddModel( pMan->pDesign, pNtkNew ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Finds the network by name or create a new blackbox network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseFindNet( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pObj; + if ( pObj = Abc_NtkFindNet(pNtk, pName) ) + return pObj; + if ( !strcmp( pName, "1\'b0" ) || !strcmp( pName, "1\'bx" ) ) + return Abc_NtkFindOrCreateNet( pNtk, "1\'b0" ); + if ( !strcmp( pName, "1\'b1" ) ) + return Abc_NtkFindOrCreateNet( pNtk, "1\'b1" ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Converts the network from the blackbox type into a different one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseConvertNetwork( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, int fMapped ) +{ + if ( fMapped ) + { + // convert from the blackbox into the network with local functions representated by AIGs + if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) + { + // change network type + assert( pNtk->pManFunc == NULL ); + pNtk->ntkFunc = ABC_FUNC_MAP; + pNtk->pManFunc = pMan->pDesign->pGenlib; + } + else if ( pNtk->ntkFunc != ABC_FUNC_MAP ) + { + sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + else + { + // convert from the blackbox into the network with local functions representated by AIGs + if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) + { + // change network type + assert( pNtk->pManFunc == NULL ); + pNtk->ntkFunc = ABC_FUNC_AIG; + pNtk->pManFunc = pMan->pDesign->pManFunc; + } + else if ( pNtk->ntkFunc != ABC_FUNC_AIG ) + { + sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one Verilog module.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseModule( Ver_Man_t * pMan ) +{ + Mio_Gate_t * pGate; + Ver_Stream_t * p = pMan->pReader; + Abc_Ntk_t * pNtk, * pNtkTemp; + char * pWord, Symbol; + int RetValue; + + // get the network name + pWord = Ver_ParseGetName( pMan ); + + // get the network with this name + pNtk = Ver_ParseFindOrCreateNetwork( pMan, pWord ); + + // make sure we stopped at the opening paranthesis + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot find \"(\" after \"module\" in network %s.", pNtk->pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // skip to the end of parantheses + do { + if ( Ver_ParseGetName( pMan ) == NULL ) + return 0; + Symbol = Ver_StreamPopChar(p); + } while ( Symbol == ',' ); + assert( Symbol == ')' ); + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + Symbol = Ver_StreamPopChar(p); + if ( Symbol != ';' ) + { + sprintf( pMan->sError, "Expected closing paranthesis after \"module\"." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // parse the inputs/outputs/registers/wires/inouts + while ( 1 ) + { + Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + if ( !strcmp( pWord, "input" ) ) + RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INPUT ); + else if ( !strcmp( pWord, "output" ) ) + RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_OUTPUT ); + else if ( !strcmp( pWord, "reg" ) ) + RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_REG ); + else if ( !strcmp( pWord, "wire" ) ) + RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_WIRE ); + else if ( !strcmp( pWord, "inout" ) ) + RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INOUT ); + else + break; + if ( RetValue == 0 ) + return 0; + } + + // parse the remaining statements + while ( 1 ) + { + Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); + + if ( !strcmp( pWord, "and" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_AND ); + else if ( !strcmp( pWord, "or" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_OR ); + else if ( !strcmp( pWord, "xor" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XOR ); + else if ( !strcmp( pWord, "buf" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_BUF ); + else if ( !strcmp( pWord, "nand" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NAND ); + else if ( !strcmp( pWord, "nor" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOR ); + else if ( !strcmp( pWord, "xnor" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XNOR ); + else if ( !strcmp( pWord, "not" ) ) + RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOT ); + + else if ( !strcmp( pWord, "assign" ) ) + RetValue = Ver_ParseAssign( pMan, pNtk ); + else if ( !strcmp( pWord, "always" ) ) + RetValue = Ver_ParseAlways( pMan, pNtk ); + else if ( !strcmp( pWord, "initial" ) ) + RetValue = Ver_ParseInitial( pMan, pNtk ); + else if ( !strcmp( pWord, "endmodule" ) ) + break; + else if ( pMan->pDesign->pGenlib && (pGate = Mio_LibraryReadGateByName(pMan->pDesign->pGenlib, pWord)) ) // current design + RetValue = Ver_ParseGate( pMan, pNtk, pGate ); +// else if ( pMan->pDesign->pLibrary && st_lookup(pMan->pDesign->pLibrary->tModules, pWord, (char**)&pNtkTemp) ) // gate library +// RetValue = Ver_ParseGate( pMan, pNtkTemp ); + else // assume this is the box used in the current design + { + pNtkTemp = Ver_ParseFindOrCreateNetwork( pMan, pWord ); + RetValue = Ver_ParseBox( pMan, pNtk, pNtkTemp ); + } + if ( RetValue == 0 ) + return 0; + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get new word + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + } + + // convert from the blackbox into the network with local functions representated by AIGs + if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) + { + if ( Abc_NtkNodeNum(pNtk) > 0 || Abc_NtkBoxNum(pNtk) > 0 ) + { + if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) + return 0; + } + else + { + Abc_Obj_t * pObj, * pBox, * pTerm; + int i; + pBox = Abc_NtkCreateBlackbox(pNtk); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + pTerm = Abc_NtkCreateBi(pNtk); + Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) ); + Abc_ObjAddFanin( pBox, pTerm ); + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pTerm = Abc_NtkCreateBo(pNtk); + Abc_ObjAddFanin( pTerm, pBox ); + Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm ); + } + } + } + + // remove the table if needed + Ver_ParseRemoveSuffixTable( pMan ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Lookups the suffix of the signal of the form [m:n].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseLookupSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb ) +{ + unsigned Value; + *pnMsb = *pnLsb = -1; + if ( pMan->tName2Suffix == NULL ) + return 1; + if ( !st_lookup( pMan->tName2Suffix, (char *)pWord, (char **)&Value ) ) + return 1; + *pnMsb = (Value >> 8) & 0xff; + *pnLsb = Value & 0xff; + return 1; +} + +/**Function************************************************************* + + Synopsis [Lookups the suffix of the signal of the form [m:n].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseInsertsSuffix( Ver_Man_t * pMan, char * pWord, int nMsb, int nLsb ) +{ + unsigned Value; + if ( pMan->tName2Suffix == NULL ) + pMan->tName2Suffix = st_init_table( strcmp, st_strhash ); + if ( st_is_member( pMan->tName2Suffix, pWord ) ) + return 1; + assert( nMsb >= 0 && nMsb < 128 ); + assert( nLsb >= 0 && nLsb < 128 ); + Value = (nMsb << 8) | nLsb; + st_insert( pMan->tName2Suffix, Extra_UtilStrsav(pWord), (char *)Value ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Lookups the suffic of the signal of the form [m:n].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan ) +{ + st_generator * gen; + char * pKey, * pValue; + if ( pMan->tName2Suffix == NULL ) + return; + st_foreach_item( pMan->tName2Suffix, gen, (char **)&pKey, (char **)&pValue ) + free( pKey ); + st_free_table( pMan->tName2Suffix ); + pMan->tName2Suffix = NULL; +} + +/**Function************************************************************* + + Synopsis [Determine signal prefix of the form [Beg:End].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseSignalPrefix( Ver_Man_t * pMan, char ** ppWord, int * pnMsb, int * pnLsb ) +{ + char * pWord = *ppWord; + int nMsb, nLsb; + assert( pWord[0] == '[' ); + // get the beginning + nMsb = atoi( pWord + 1 ); + // find the splitter + while ( *pWord && *pWord != ':' && *pWord != ']' ) + pWord++; + if ( *pWord == 0 ) + { + sprintf( pMan->sError, "Cannot find closing bracket in this line." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + if ( *pWord == ']' ) + nLsb = nMsb; + else + { + assert( *pWord == ':' ); + nLsb = atoi( pWord + 1 ); + // find the closing paranthesis + while ( *pWord && *pWord != ']' ) + pWord++; + if ( *pWord == 0 ) + { + sprintf( pMan->sError, "Cannot find closing bracket in this line." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + assert( *pWord == ']' ); + pWord++; + } + assert( nMsb >= 0 && nLsb >= 0 ); + // return + *ppWord = pWord; + *pnMsb = nMsb; + *pnLsb = nLsb; + return 1; +} + +/**Function************************************************************* + + Synopsis [Determine signal suffix of the form [m:n].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseSignalSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb ) +{ + char * pCur; + int Length; + Length = strlen(pWord); + assert( pWord[Length-1] == ']' ); + // walk backward + for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- ) + if ( *pCur == ':' || *pCur == '[' ) + break; + if ( pCur == pWord ) + { + sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + if ( *pCur == '[' ) + { + *pnMsb = *pnLsb = atoi(pCur+1); + *pCur = 0; + return 1; + } + assert( *pCur == ':' ); + // get the end of the interval + *pnLsb = atoi(pCur+1); + // find the beginning + for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- ) + if ( *pCur == '[' ) + break; + if ( pCur == pWord ) + { + sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + assert( *pCur == '[' ); + // get the beginning of the interval + *pnMsb = atoi(pCur+1); + // cut the word + *pCur = 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns the values of constant bits.] + + Description [The resulting bits are in MSB to LSB order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseConstant( Ver_Man_t * pMan, char * pWord ) +{ + int nBits, i; + assert( pWord[0] >= '1' && pWord[1] <= '9' ); + nBits = atoi(pWord); + // find the next symbol \' + while ( *pWord && *pWord != '\'' ) + pWord++; + if ( *pWord == 0 ) + { + sprintf( pMan->sError, "Cannot find symbol \' in the constant." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + assert( *pWord == '\'' ); + pWord++; + if ( *pWord != 'b' ) + { + sprintf( pMan->sError, "Currently can only handle binary constants." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + pWord++; + // scan the bits + Vec_PtrClear( pMan->vNames ); + for ( i = 0; i < nBits; i++ ) + { + if ( pWord[i] != '0' && pWord[i] != '1' && pWord[i] != 'x' ) + { + sprintf( pMan->sError, "Having problem parsing the binary constant." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + if ( pWord[i] == 'x' ) + Vec_PtrPush( pMan->vNames, (void *)0 ); + else + Vec_PtrPush( pMan->vNames, (void *)(pWord[i]-'0') ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [The signals are added in the order from LSB to MSB.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType ) +{ + Ver_Stream_t * p = pMan->pReader; + char Buffer[1000], Symbol, * pWord; + int nMsb, nLsb, Bit, Limit, i; + nMsb = nLsb = -1; + while ( 1 ) + { + // get the next word + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + + // check if the range is specified + if ( pWord[0] == '[' && !pMan->fNameLast ) + { + assert( nMsb == -1 && nLsb == -1 ); + Ver_ParseSignalPrefix( pMan, &pWord, &nMsb, &nLsb ); + // check the case when there is space between bracket and the next word + if ( *pWord == 0 ) + { + // get the signal name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + } + } + + // create signals + if ( nMsb == -1 && nLsb == -1 ) + { + if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT ) + Ver_ParseCreatePi( pNtk, pWord ); + if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT ) + Ver_ParseCreatePo( pNtk, pWord ); + if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG ) + Abc_NtkFindOrCreateNet( pNtk, pWord ); + } + else + { + assert( nMsb >= 0 && nLsb >= 0 ); + // add to the hash table + Ver_ParseInsertsSuffix( pMan, pWord, nMsb, nLsb ); + // add signals from Lsb to Msb + Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1; + for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 ) + { + sprintf( Buffer, "%s[%d]", pWord, Bit ); + if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT ) + Ver_ParseCreatePi( pNtk, Buffer ); + if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT ) + Ver_ParseCreatePo( pNtk, Buffer ); + if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG ) + Abc_NtkFindOrCreateNet( pNtk, Buffer ); + } + } + + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ',' ) + continue; + if ( Symbol == ';' ) + return 1; + break; + } + sprintf( pMan->sError, "Cannot parse signal line (expected , or ;)." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseAlways( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Obj_t * pNet, * pNet2; + int fStopAfterOne; + char * pWord, * pWord2; + char Symbol; + // parse the directive + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + if ( pWord[0] == '@' ) + { + Ver_StreamSkipToChars( p, ")" ); + Ver_StreamPopChar(p); + // parse the directive + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + } + // decide how many statements to parse + fStopAfterOne = 0; + if ( strcmp( pWord, "begin" ) ) + fStopAfterOne = 1; + // iterate over the initial states + while ( 1 ) + { + if ( !fStopAfterOne ) + { + // get the name of the output signal + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // look for the end of directive + if ( !strcmp( pWord, "end" ) ) + break; + } + // get the fanout net + pNet = Ver_ParseFindNet( pNtk, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the always statement for %s (output wire is not defined).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // get the equality sign + Symbol = Ver_StreamPopChar(p); + if ( Symbol != '<' && Symbol != '=' ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + if ( Symbol == '<' ) + Ver_StreamPopChar(p); + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get the second name + pWord2 = Ver_ParseGetName( pMan ); + if ( pWord2 == NULL ) + return 0; + // check if the name is complemented + if ( pWord2[0] == '~' ) + { + pNet2 = Ver_ParseFindNet( pNtk, pWord2+1 ); + pNet2 = Ver_ParseCreateInv( pNtk, pNet2 ); + } + else + pNet2 = Ver_ParseFindNet( pNtk, pWord2 ); + if ( pNet2 == NULL ) + { + sprintf( pMan->sError, "Cannot read the always statement for %s (input wire is not defined).", pWord2 ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // create the latch + Ver_ParseCreateLatch( pNtk, pNet2, pNet ); + // remove the last symbol + Symbol = Ver_StreamPopChar(p); + assert( Symbol == ';' ); + // quit if only one directive + if ( fStopAfterOne ) + break; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseInitial( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Obj_t * pNode, * pNet; + int fStopAfterOne; + char * pWord, * pEquation; + char Symbol; + // parse the directive + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // decide how many statements to parse + fStopAfterOne = 0; + if ( strcmp( pWord, "begin" ) ) + fStopAfterOne = 1; + // iterate over the initial states + while ( 1 ) + { + if ( !fStopAfterOne ) + { + // get the name of the output signal + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // look for the end of directive + if ( !strcmp( pWord, "end" ) ) + break; + } + // get the fanout net + pNet = Ver_ParseFindNet( pNtk, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the initial statement for %s (output wire is not defined).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // get the equality sign + Symbol = Ver_StreamPopChar(p); + if ( Symbol != '<' && Symbol != '=' ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + if ( Symbol == '<' ) + Ver_StreamPopChar(p); + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get the second name + pEquation = Ver_StreamGetWord( p, ";" ); + if ( pEquation == NULL ) + return 0; + // find the corresponding latch + if ( Abc_ObjFaninNum(pNet) == 0 ) + { + sprintf( pMan->sError, "Cannot find the latch to assign the initial value." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + pNode = Abc_ObjFanin0(Abc_ObjFanin0(pNet)); + assert( Abc_ObjIsLatch(pNode) ); + // set the initial state + if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") ) + Abc_LatchSetInit0( pNode ); + else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") ) + Abc_LatchSetInit1( pNode ); +// else if ( !strcmp(pEquation, "2") ) +// Abc_LatchSetInitDc( pNode ); + else + { + sprintf( pMan->sError, "Incorrect initial value of the latch %s.", Abc_ObjName(pNet) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // remove the last symbol + Symbol = Ver_StreamPopChar(p); + assert( Symbol == ';' ); + // quit if only one directive + if ( fStopAfterOne ) + break; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) +{ + char Buffer[1000], Buffer2[1000]; + Ver_Stream_t * p = pMan->pReader; + Abc_Obj_t * pNode, * pNet; + char * pWord, * pName, * pEquation; + Hop_Obj_t * pFunc; + char Symbol; + int i, Bit, Limit, Length, fReduction; + int nMsb, nLsb; + +// if ( Ver_StreamGetLineNumber(p) == 2756 ) +// { +// int x = 0; +// } + + // convert from the blackbox into the network with local functions representated by AIGs + if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) + return 0; + + while ( 1 ) + { + // get the name of the output signal + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // check for vector-inputs + if ( !Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ) ) + return 0; + // handle special case of constant assignment + if ( nMsb >= 0 && nLsb >= 0 ) + { + // save the fanout name + strcpy( Buffer, pWord ); + // get the equality sign + if ( Ver_StreamPopChar(p) != '=' ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // get the constant + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // check if it is indeed a constant + if ( !(pWord[0] >= '0' && pWord[0] <= '9') ) + { + sprintf( pMan->sError, "Currently can only assign vector-signal \"%s\" to be a constant.", Buffer ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // get individual bits of the constant + if ( !Ver_ParseConstant( pMan, pWord ) ) + return 0; + // check that the constant has the same size + Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1; + if ( Limit != Vec_PtrSize(pMan->vNames) ) + { + sprintf( pMan->sError, "The constant size (%d) is different from the signal\"%s\" size (%d).", + Vec_PtrSize(pMan->vNames), Buffer, Limit ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // iterate through the bits + for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 ) + { + // get the fanin net + if ( Vec_PtrEntry( pMan->vNames, Limit-1-i ) ) + pNet = Ver_ParseFindNet( pNtk, "1\'b1" ); + else + pNet = Ver_ParseFindNet( pNtk, "1\'b0" ); + assert( pNet != NULL ); + + // create the buffer + pNode = Abc_NtkCreateNodeBuf( pNtk, pNet ); + + // get the fanout net + sprintf( Buffer2, "%s[%d]", Buffer, Bit ); + pNet = Ver_ParseFindNet( pNtk, Buffer2 ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Abc_ObjAddFanin( pNet, pNode ); + } + // go to the end of the line + Ver_ParseSkipComments( pMan ); + } + else + { + // consider the case of reduction operations + fReduction = 0; + if ( pWord[0] == '{' && !pMan->fNameLast ) + fReduction = 1; + if ( fReduction ) + { + pWord++; + pWord[strlen(pWord)-1] = 0; + assert( pWord[0] != '\\' ); + } + // get the fanout net + pNet = Ver_ParseFindNet( pNtk, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // get the equality sign + if ( Ver_StreamPopChar(p) != '=' ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // skip the comments + if ( !Ver_ParseSkipComments( pMan ) ) + return 0; + // get the second name + if ( fReduction ) + pEquation = Ver_StreamGetWord( p, ";" ); + else + pEquation = Ver_StreamGetWord( p, ",;" ); + if ( pEquation == NULL ) + { + sprintf( pMan->sError, "Cannot read the equation for %s.", Abc_ObjName(pNet) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // consider the case of mapped network + Vec_PtrClear( pMan->vNames ); + if ( pMan->fMapped ) + { + if ( !strcmp( pEquation, "1\'b0" ) ) + pFunc = (Hop_Obj_t *)Mio_LibraryReadConst0(Abc_FrameReadLibGen()); + else if ( !strcmp( pEquation, "1\'b1" ) ) + pFunc = (Hop_Obj_t *)Mio_LibraryReadConst1(Abc_FrameReadLibGen()); + else + { + // "assign foo = \bar ;" + if ( *pEquation == '\\' ) + { + pEquation++; + pEquation[strlen(pEquation) - 1] = 0; + } + if ( Ver_ParseFindNet(pNtk, pEquation) == NULL ) + { + sprintf( pMan->sError, "Cannot read Verilog with non-trivial assignments in the mapped netlist." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Vec_PtrPush( pMan->vNames, (void *)strlen(pEquation) ); + Vec_PtrPush( pMan->vNames, pEquation ); + // get the buffer + pFunc = (Hop_Obj_t *)Mio_LibraryReadBuf(Abc_FrameReadLibGen()); + if ( pFunc == NULL ) + { + sprintf( pMan->sError, "Reading assign statement for node %s has failed because the genlib library has no buffer.", Abc_ObjName(pNet) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + } + else + { + if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") || !strcmp(pEquation, "1\'bx") ) + pFunc = Hop_ManConst0(pNtk->pManFunc); + else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") ) + pFunc = Hop_ManConst1(pNtk->pManFunc); + else if ( fReduction ) + pFunc = Ver_FormulaReduction( pEquation, pNtk->pManFunc, pMan->vNames, pMan->sError ); + else + pFunc = Ver_FormulaParser( pEquation, pNtk->pManFunc, pMan->vNames, pMan->vStackFn, pMan->vStackOp, pMan->sError ); + if ( pFunc == NULL ) + { + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + + // create the node with the given inputs + pNode = Abc_NtkCreateNode( pNtk ); + pNode->pData = pFunc; + Abc_ObjAddFanin( pNet, pNode ); + // connect to fanin nets + for ( i = 0; i < Vec_PtrSize(pMan->vNames)/2; i++ ) + { + // get the name of this signal + Length = (int)Vec_PtrEntry( pMan->vNames, 2*i ); + pName = Vec_PtrEntry( pMan->vNames, 2*i + 1 ); + pName[Length] = 0; + // find the corresponding net + pNet = Ver_ParseFindNet( pNtk, pName ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %s is not defined).", pWord, pName ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Abc_ObjAddFanin( pNode, pNet ); + } + } + + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ',' ) + continue; + if ( Symbol == ';' ) + return 1; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Obj_t * pNet, * pNode; + char * pWord, Symbol; + + // convert from the blackbox into the network with local functions representated by AIGs + if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) + return 0; + + // this is gate name - throw it away + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot parse a standard gate (expected opening paranthesis)." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + + // create the node + pNode = Abc_NtkCreateNode( pNtk ); + + // parse pairs of formal/actural inputs + while ( 1 ) + { + // parse the output name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // get the net corresponding to this output + pNet = Ver_ParseFindNet( pNtk, pWord ); + if ( pNet == NULL ) + { + sprintf( pMan->sError, "Net is missing in gate %s.", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // if this is the first net, add it as an output + if ( Abc_ObjFanoutNum(pNode) == 0 ) + Abc_ObjAddFanin( pNet, pNode ); + else + Abc_ObjAddFanin( pNode, pNet ); + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ')' ) + break; + // skip comma + if ( Symbol != ',' ) + { + sprintf( pMan->sError, "Cannot parse a standard gate %s (expected closing paranthesis).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + if ( (GateType == VER_GATE_BUF || GateType == VER_GATE_NOT) && Abc_ObjFaninNum(pNode) != 1 ) + { + sprintf( pMan->sError, "Buffer or interver with multiple fanouts %s (currently not supported).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + if ( Ver_StreamPopChar(p) != ';' ) + { + sprintf( pMan->sError, "Cannot read standard gate %s (expected closing semicolumn).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // add logic function + if ( GateType == VER_GATE_AND || GateType == VER_GATE_NAND ) + pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); + else if ( GateType == VER_GATE_OR || GateType == VER_GATE_NOR ) + pNode->pData = Hop_CreateOr( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); + else if ( GateType == VER_GATE_XOR || GateType == VER_GATE_XNOR ) + pNode->pData = Hop_CreateExor( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); + else if ( GateType == VER_GATE_BUF || GateType == VER_GATE_NOT ) + pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); + if ( GateType == VER_GATE_NAND || GateType == VER_GATE_NOR || GateType == VER_GATE_XNOR || GateType == VER_GATE_NOT ) + pNode->pData = Hop_Not( pNode->pData ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns the index of the given pin the gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_FindGateInput( Mio_Gate_t * pGate, char * pName ) +{ + Mio_Pin_t * pGatePin; + int i; + for ( i = 0, pGatePin = Mio_GateReadPins(pGate); pGatePin != NULL; pGatePin = Mio_PinReadNext(pGatePin), i++ ) + if ( strcmp(pName, Mio_PinReadName(pGatePin)) == 0 ) + return i; + if ( strcmp(pName, Mio_GateReadOutName(pGate)) == 0 ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseGate( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate ) +{ + Ver_Stream_t * p = pMan->pReader; + Abc_Obj_t * pNetActual, * pNode; + char * pWord, Symbol; + int Input, i, nFanins = Mio_GateReadInputs(pGate); + + // convert from the blackbox into the network with local functions representated by gates + if ( 1 != pMan->fMapped ) + { + sprintf( pMan->sError, "The network appears to be mapped. Use \"r -m\" to read mapped Verilog." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // update the network type if needed + if ( !Ver_ParseConvertNetwork( pMan, pNtk, 1 ) ) + return 0; + + // parse the directive and set the pointers to the PIs/POs of the gate + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // this is gate name - throw it away + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot parse gate %s (expected opening paranthesis).", Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + + // start the node + pNode = Abc_NtkCreateNode( pNtk ); + pNode->pData = pGate; + + // parse pairs of formal/actural inputs + Vec_IntClear( pMan->vPerm ); + while ( 1 ) + { + // process one pair of formal/actual parameters + if ( Ver_StreamPopChar(p) != '.' ) + { + sprintf( pMan->sError, "Cannot parse gate %s (expected .).", Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // parse the formal name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + + // find the corresponding pin of the gate + Input = Ver_FindGateInput( pGate, pWord ); + if ( Input == -1 ) + { + sprintf( pMan->sError, "Formal input name %s cannot be found in the gate %s.", pWord, Mio_GateReadOutName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // open the paranthesis + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected opening paranthesis).", pWord, Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // parse the actual name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // check if the name is complemented + assert( pWord[0] != '~' ); +/* + fCompl = (pWord[0] == '~'); + if ( fCompl ) + { + fComplUsed = 1; + pWord++; + if ( pNtk->pData == NULL ) + pNtk->pData = Extra_MmFlexStart(); + } +*/ + // get the actual net + pNetActual = Ver_ParseFindNet( pNtk, pWord ); + if ( pNetActual == NULL ) + { + sprintf( pMan->sError, "Actual net %s is missing.", pWord ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // close the paranthesis + if ( Ver_StreamPopChar(p) != ')' ) + { + sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // add the fanin + if ( Input < nFanins ) + { + Vec_IntPush( pMan->vPerm, Input ); + Abc_ObjAddFanin( pNode, pNetActual ); // fanin + } + else + Abc_ObjAddFanin( pNetActual, pNode ); // fanout + + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ')' ) + break; + + // skip comma + if ( Symbol != ',' ) + { + sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + + // check that the gate as the same number of input + if ( !(Abc_ObjFaninNum(pNode) == nFanins && Abc_ObjFanoutNum(pNode) == 1) ) + { + sprintf( pMan->sError, "Parsing of gate %s has failed.", Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + if ( Ver_StreamPopChar(p) != ';' ) + { + sprintf( pMan->sError, "Cannot read gate %s (expected closing semicolumn).", Mio_GateReadName(pGate) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // check if we need to permute the inputs + Vec_IntForEachEntry( pMan->vPerm, Input, i ) + if ( Input != i ) + break; + if ( i < Vec_IntSize(pMan->vPerm) ) + { + // add the fanin numnbers to the end of the permuation array + for ( i = 0; i < nFanins; i++ ) + Vec_IntPush( pMan->vPerm, Abc_ObjFaninId(pNode, i) ); + // write the fanin numbers into their corresponding places (according to the gate) + for ( i = 0; i < nFanins; i++ ) + Vec_IntWriteEntry( &pNode->vFanins, Vec_IntEntry(pMan->vPerm, i), Vec_IntEntry(pMan->vPerm, i+nFanins) ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Parses one directive.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox ) +{ + char Buffer[1000]; + Ver_Stream_t * p = pMan->pReader; + Ver_Bundle_t * pBundle; + Vec_Ptr_t * vBundles; + Abc_Obj_t * pNetActual; + Abc_Obj_t * pNode; + char * pWord, Symbol; + int fCompl, fFormalIsGiven; + int i, k, Bit, Limit, nMsb, nLsb, fQuit, flag; + + // gate the name of the box + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + + // create a box with this name + pNode = Abc_NtkCreateBlackbox( pNtk ); + pNode->pData = pNtkBox; + Abc_ObjAssignName( pNode, pWord, NULL ); + + // continue parsing the box + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot parse box %s (expected opening paranthesis).", Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + + // parse pairs of formal/actual inputs + vBundles = Vec_PtrAlloc( 16 ); + pNode->pCopy = (Abc_Obj_t *)vBundles; + while ( 1 ) + { + // allocate the bundle (formal name + array of actual nets) + pBundle = ALLOC( Ver_Bundle_t, 1 ); + pBundle->pNameFormal = NULL; + pBundle->vNetsActual = Vec_PtrAlloc( 4 ); + Vec_PtrPush( vBundles, pBundle ); + + // process one pair of formal/actual parameters + fFormalIsGiven = 0; + if ( Ver_StreamScanChar(p) == '.' ) + { + fFormalIsGiven = 1; + if ( Ver_StreamPopChar(p) != '.' ) + { + sprintf( pMan->sError, "Cannot parse box %s (expected .).", Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + // parse the formal name + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + + // save the name + pBundle->pNameFormal = Extra_UtilStrsav( pWord ); + + // open the paranthesis + if ( Ver_StreamPopChar(p) != '(' ) + { + sprintf( pMan->sError, "Cannot formal parameter %s of box %s (expected opening paranthesis).", pWord, Abc_ObjName(pNode)); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + + // check if this is the beginning of {} expression + Symbol = Ver_StreamScanChar(p); + + // consider the case of vector-inputs + if ( Symbol == '{' ) + { + // skip this char + Ver_StreamPopChar(p); + + // read actual names + i = 0; + fQuit = 0; + while ( 1 ) + { + // parse the formal name + Ver_ParseSkipComments( pMan ); + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + + // check if the last char is a closing brace + if ( pWord[strlen(pWord)-1] == '}' ) + { + pWord[strlen(pWord)-1] = 0; + fQuit = 1; + } + if ( pWord[0] == 0 ) + break; + + // check for constant + if ( pWord[0] >= '1' && pWord[0] <= '9' ) + { + if ( !Ver_ParseConstant( pMan, pWord ) ) + return 0; + // add constant MSB to LSB + for ( k = 0; k < Vec_PtrSize(pMan->vNames); k++, i++ ) + { + // get the actual net + sprintf( Buffer, "1\'b%d", (int)(Vec_PtrEntry(pMan->vNames,k) != NULL) ); + pNetActual = Ver_ParseFindNet( pNtk, Buffer ); + if ( pNetActual == NULL ) + { + sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", Buffer, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Vec_PtrPush( pBundle->vNetsActual, pNetActual ); + } + } + else + { + // get the suffix of the form [m:n] + if ( pWord[strlen(pWord)-1] == ']' && !pMan->fNameLast ) + Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb ); + else + Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ); + + // generate signals + if ( nMsb == -1 && nLsb == -1 ) + { + // get the actual net + pNetActual = Ver_ParseFindNet( pNtk, pWord ); + if ( pNetActual == NULL ) + { + if ( !strncmp(pWord, "Open_", 5) || + !strncmp(pWord, "dct_unconnected", 15) ) + pNetActual = Abc_NtkCreateNet( pNtk ); + else + { + sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + Vec_PtrPush( pBundle->vNetsActual, pNetActual ); + i++; + } + else + { + // go from MSB to LSB + assert( nMsb >= 0 && nLsb >= 0 ); + Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1; + for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--, i++ ) + { + // get the actual net + sprintf( Buffer, "%s[%d]", pWord, Bit ); + pNetActual = Ver_ParseFindNet( pNtk, Buffer ); + if ( pNetActual == NULL ) + { + if ( !strncmp(pWord, "Open_", 5) || + !strncmp(pWord, "dct_unconnected", 15) ) + pNetActual = Abc_NtkCreateNet( pNtk ); + else + { + sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + Vec_PtrPush( pBundle->vNetsActual, pNetActual ); + } + } + } + + if ( fQuit ) + break; + + // skip comma + Ver_ParseSkipComments( pMan ); + Symbol = Ver_StreamPopChar(p); + if ( Symbol == '}' ) + break; + if ( Symbol != ',' ) + { + sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected comma).", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + } + else + { + // get the next word + pWord = Ver_ParseGetName( pMan ); + if ( pWord == NULL ) + return 0; + // consider the case of empty name + fCompl = 0; + if ( pWord[0] == 0 ) + { + pNetActual = Abc_NtkCreateNet( pNtk ); + Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) ); + } + else + { + // get the actual net + flag=0; + pNetActual = Ver_ParseFindNet( pNtk, pWord ); + if ( pNetActual == NULL ) + { + Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ); + if ( nMsb == -1 && nLsb == -1 ) + { + Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb ); + if ( nMsb == -1 && nLsb == -1 ) + { + if ( !strncmp(pWord, "Open_", 5) || + !strncmp(pWord, "dct_unconnected", 15) ) + { + pNetActual = Abc_NtkCreateNet( pNtk ); + Vec_PtrPush( pBundle->vNetsActual, pNetActual ); + } + else + { + sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + else + { + flag=1; + } + } + else + { + flag=1; + } + if (flag) + { + Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1; + for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--) + { + // get the actual net + sprintf( Buffer, "%s[%d]", pWord, Bit ); + pNetActual = Ver_ParseFindNet( pNtk, Buffer ); + if ( pNetActual == NULL ) + { + if ( !strncmp(pWord, "Open_", 5) || + !strncmp(pWord, "dct_unconnected", 15)) + pNetActual = Abc_NtkCreateNet( pNtk ); + else + { + sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + Vec_PtrPush( pBundle->vNetsActual, pNetActual ); + } + } + } + else + { + Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) ); + } + } + } + + if ( fFormalIsGiven ) + { + // close the paranthesis + Ver_ParseSkipComments( pMan ); + if ( Ver_StreamPopChar(p) != ')' ) + { + sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected closing paranthesis).", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + + // check if it is the end of gate + Symbol = Ver_StreamPopChar(p); + if ( Symbol == ')' ) + break; + // skip comma + if ( Symbol != ',' ) + { + sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected comma).", pWord, Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + Ver_ParseSkipComments( pMan ); + } + + // check if it is the end of gate + Ver_ParseSkipComments( pMan ); + if ( Ver_StreamPopChar(p) != ';' ) + { + sprintf( pMan->sError, "Cannot read box %s (expected closing semicolumn).", Abc_ObjName(pNode) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + + return 1; +} + +/**Function************************************************************* + + Synopsis [Connects one box to the network] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseFreeBundle( Ver_Bundle_t * pBundle ) +{ + FREE( pBundle->pNameFormal ); + Vec_PtrFree( pBundle->vNetsActual ); + free( pBundle ); +} + +/**Function************************************************************* + + Synopsis [Connects one box to the network] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox ) +{ + Vec_Ptr_t * vBundles = (Vec_Ptr_t *)pBox->pCopy; + Abc_Ntk_t * pNtk = pBox->pNtk; + Abc_Ntk_t * pNtkBox = pBox->pData; + Abc_Obj_t * pTerm, * pTermNew, * pNetAct; + Ver_Bundle_t * pBundle; + char * pNameFormal; + int i, k, j, iBundle, Length; + + assert( !Ver_ObjIsConnected(pBox) ); + assert( Ver_NtkIsDefined(pNtkBox) ); + assert( !Abc_NtkHasBlackbox(pNtkBox) || Abc_NtkBoxNum(pNtkBox) == 1 ); +/* + // clean the PI/PO nets + Abc_NtkForEachPi( pNtkBox, pTerm, i ) + Abc_ObjFanout0(pTerm)->pCopy = NULL; + Abc_NtkForEachPo( pNtkBox, pTerm, i ) + Abc_ObjFanin0(pTerm)->pCopy = NULL; +*/ + // check if some of them do not have formal names + Vec_PtrForEachEntry( vBundles, pBundle, k ) + if ( pBundle->pNameFormal == NULL ) + break; + if ( k < Vec_PtrSize(vBundles) ) + { + printf( "Warning: The instance %s of network %s will be connected without using formal names.\n", pNtkBox->pName, Abc_ObjName(pBox) ); + // add all actual nets in the bundles + iBundle = 0; + Vec_PtrForEachEntry( vBundles, pBundle, j ) + iBundle += Vec_PtrSize(pBundle->vNetsActual); + + // check the number of actual nets is the same as the number of formal nets + if ( iBundle != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) + { + sprintf( pMan->sError, "The number of actual IOs (%d) is different from the number of formal IOs (%d) when instantiating network %s in box %s.", + Vec_PtrSize(vBundles), Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox), pNtkBox->pName, Abc_ObjName(pBox) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // connect bundles in the natural order + iBundle = 0; + Abc_NtkForEachPi( pNtkBox, pTerm, i ) + { + pBundle = Vec_PtrEntry( vBundles, iBundle++ ); + // the bundle is found - add the connections - using order LSB to MSB + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) + { + pTermNew = Abc_NtkCreateBi( pNtk ); + Abc_ObjAddFanin( pBox, pTermNew ); + Abc_ObjAddFanin( pTermNew, pNetAct ); + i++; + } + i--; + } + // create fanins of the box + Abc_NtkForEachPo( pNtkBox, pTerm, i ) + { + pBundle = Vec_PtrEntry( vBundles, iBundle++ ); + // the bundle is found - add the connections - using order LSB to MSB + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) + { + pTermNew = Abc_NtkCreateBo( pNtk ); + Abc_ObjAddFanin( pTermNew, pBox ); + Abc_ObjAddFanin( pNetAct, pTermNew ); + i++; + } + i--; + } + + // free the bundling + Vec_PtrForEachEntry( vBundles, pBundle, k ) + Ver_ParseFreeBundle( pBundle ); + Vec_PtrFree( vBundles ); + pBox->pCopy = NULL; + return 1; + } + + // bundles arrive in any order - but inside each bundle the order is MSB to LSB + // make sure every formal PI has a corresponding net + Abc_NtkForEachPi( pNtkBox, pTerm, i ) + { + // get the name of this formal net + pNameFormal = Abc_ObjName( Abc_ObjFanout0(pTerm) ); + // try to find the bundle with this formal net + pBundle = NULL; + Vec_PtrForEachEntry( vBundles, pBundle, k ) + if ( !strcmp(pBundle->pNameFormal, pNameFormal) ) + break; + assert( pBundle != NULL ); + // if the bundle is not found, try without parantheses + if ( k == Vec_PtrSize(vBundles) ) + { + pBundle = NULL; + Length = strlen(pNameFormal); + if ( pNameFormal[Length-1] == ']' ) + { + // find the opening brace + for ( Length--; Length >= 0; Length-- ) + if ( pNameFormal[Length] == '[' ) + break; + // compare names before brace + if ( Length > 0 ) + { + Vec_PtrForEachEntry( vBundles, pBundle, j ) + if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) ) + break; + if ( j == Vec_PtrSize(vBundles) ) + pBundle = NULL; + } + } + if ( pBundle == NULL ) + { + sprintf( pMan->sError, "Cannot find an actual net for the formal net %s when instantiating network %s in box %s.", + pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + // the bundle is found - add the connections - using order LSB to MSB + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) + { + pTermNew = Abc_NtkCreateBi( pNtk ); + Abc_ObjAddFanin( pBox, pTermNew ); + Abc_ObjAddFanin( pTermNew, pNetAct ); + i++; + } + i--; + } + + // connect those formal POs that do have nets + Abc_NtkForEachPo( pNtkBox, pTerm, i ) + { + // get the name of this PI + pNameFormal = Abc_ObjName( Abc_ObjFanin0(pTerm) ); + // try to find this formal net in the bundle + pBundle = NULL; + Vec_PtrForEachEntry( vBundles, pBundle, k ) + if ( !strcmp(pBundle->pNameFormal, pNameFormal) ) + break; + assert( pBundle != NULL ); + // if the name is not found, try without parantheses + if ( k == Vec_PtrSize(vBundles) ) + { + pBundle = NULL; + Length = strlen(pNameFormal); + if ( pNameFormal[Length-1] == ']' ) + { + // find the opening brace + for ( Length--; Length >= 0; Length-- ) + if ( pNameFormal[Length] == '[' ) + break; + // compare names before brace + if ( Length > 0 ) + { + Vec_PtrForEachEntry( vBundles, pBundle, j ) + if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) ) + break; + if ( j == Vec_PtrSize(vBundles) ) + pBundle = NULL; + } + } + if ( pBundle == NULL ) + { +// printf( "Warning: The formal output %s is not driven when instantiating network %s in box %s.", +// pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) ); + continue; + } + } + // the bundle is found - add the connections + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) + { + if ( !strcmp(Abc_ObjName(pNetAct), "1\'b0") || !strcmp(Abc_ObjName(pNetAct), "1\'b1") ) + { + sprintf( pMan->sError, "It looks like formal output %s is driving a constant net (%s) when instantiating network %s in box %s.", + pBundle->pNameFormal, Abc_ObjName(pNetAct), pNtkBox->pName, Abc_ObjName(pBox) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + pTermNew = Abc_NtkCreateBo( pNtk ); + Abc_ObjAddFanin( pTermNew, pBox ); + Abc_ObjAddFanin( pNetAct, pTermNew ); + i++; + } + i--; + } + + // free the bundling + Vec_PtrForEachEntry( vBundles, pBundle, k ) + Ver_ParseFreeBundle( pBundle ); + Vec_PtrFree( vBundles ); + pBox->pCopy = NULL; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Connects the defined boxes.] + + Description [Returns 2 if there are any undef boxes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseConnectDefBoxes( Ver_Man_t * pMan ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pBox; + int i, k, RetValue = 1; + // go through all the modules + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + // go through all the boxes of this module + Abc_NtkForEachBox( pNtk, pBox, k ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + // skip internal boxes of the blackboxes + if ( pBox->pData == NULL ) + continue; + // if the network is undefined, it will be connected later + if ( !Ver_NtkIsDefined(pBox->pData) ) + { + RetValue = 2; + continue; + } + // connect the box + if ( !Ver_ParseConnectBox( pMan, pBox ) ) + return 0; + // if the network is a true blackbox, skip + if ( Abc_NtkHasBlackbox(pBox->pData) ) + continue; + // convert the box to the whitebox + Abc_ObjBlackboxToWhitebox( pBox ); + } + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Collects the undef boxes and maps them into their instances.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ver_ParseCollectUndefBoxes( Ver_Man_t * pMan ) +{ + Vec_Ptr_t * vUndefs; + Abc_Ntk_t * pNtk, * pNtkBox; + Abc_Obj_t * pBox; + int i, k; + // clear the module structures + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + pNtk->pData = NULL; + // go through all the blackboxes + vUndefs = Vec_PtrAlloc( 16 ); + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + Abc_NtkForEachBlackbox( pNtk, pBox, k ) + { + pNtkBox = pBox->pData; + if ( pNtkBox == NULL ) + continue; + if ( Ver_NtkIsDefined(pNtkBox) ) + continue; + if ( pNtkBox->pData == NULL ) + { + // save the box + Vec_PtrPush( vUndefs, pNtkBox ); + pNtkBox->pData = Vec_PtrAlloc( 16 ); + } + // save the instance + Vec_PtrPush( pNtkBox->pData, pBox ); + } + } + return vUndefs; +} + +/**Function************************************************************* + + Synopsis [Reports how many times each type of undefined box occurs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParseReportUndefBoxes( Ver_Man_t * pMan ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pBox; + int i, k, nBoxes; + // clean + nBoxes = 0; + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + pNtk->fHiePath = 0; + if ( !Ver_NtkIsDefined(pNtk) ) + nBoxes++; + } + // count + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + Abc_NtkForEachBlackbox( pNtk, pBox, k ) + if ( pBox->pData && !Ver_NtkIsDefined(pBox->pData) ) + ((Abc_Ntk_t *)pBox->pData)->fHiePath++; + // print the stats + printf( "Warning: The design contains %d undefined objects interpreted as blackboxes:\n", nBoxes ); + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + if ( !Ver_NtkIsDefined(pNtk) ) + printf( "%s (%d) ", Abc_NtkName(pNtk), pNtk->fHiePath ); + printf( "\n" ); + // clean + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + pNtk->fHiePath = 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if there are non-driven nets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseCheckNondrivenNets( Vec_Ptr_t * vUndefs ) +{ + Abc_Ntk_t * pNtk; + Ver_Bundle_t * pBundle; + Abc_Obj_t * pBox, * pNet; + int i, k, j, m; + // go through undef box types + Vec_PtrForEachEntry( vUndefs, pNtk, i ) + // go through instances of this type + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + // go through the bundles of this instance + Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + // go through the actual nets of this bundle + if ( pBundle ) + Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m ) + { + char * pName = Abc_ObjName(pNet); + if ( Abc_ObjFaninNum(pNet) == 0 ) // non-driven + if ( strcmp(Abc_ObjName(pNet), "1\'b0") && strcmp(Abc_ObjName(pNet), "1\'b1") ) // diff from a const + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if formal nets with the given name are driven in any of the instances of undef boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseFormalNetsAreDriven( Abc_Ntk_t * pNtk, char * pNameFormal ) +{ + Ver_Bundle_t * pBundle; + Abc_Obj_t * pBox, * pNet; + int k, j, m; + // go through instances of this type + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + { + // find a bundle with the given name in this instance + Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + if ( pBundle && !strcmp( pBundle->pNameFormal, pNameFormal ) ) + break; + // skip non-driven bundles + if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) + continue; + // check if all nets are driven in this bundle + Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m ) + if ( Abc_ObjFaninNum(pNet) > 0 ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the non-driven bundle that is given distance from the end.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ver_Bundle_t * Ver_ParseGetNondrivenBundle( Abc_Ntk_t * pNtk, int Counter ) +{ + Ver_Bundle_t * pBundle; + Abc_Obj_t * pBox, * pNet; + int k, m; + // go through instances of this type + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + { + if ( Counter >= Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) + continue; + // get the bundle given distance away + pBundle = Vec_PtrEntry( (Vec_Ptr_t *)pBox->pCopy, Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) - 1 - Counter ); + if ( pBundle == NULL ) + continue; + // go through the actual nets of this bundle + Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m ) + if ( !Abc_ObjFaninNum(pNet) && !Ver_ParseFormalNetsAreDriven(pNtk, pBundle->pNameFormal) ) // non-driven + return pBundle; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Drives the bundle in the given undef box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseDriveFormal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_Bundle_t * pBundle0 ) +{ + char Buffer[200]; + char * pName; + Ver_Bundle_t * pBundle; + Abc_Obj_t * pBox, * pTerm, * pTermNew, * pNetAct, * pNetFormal; + int k, j, m; + + // drive this net in the undef box + Vec_PtrForEachEntry( pBundle0->vNetsActual, pNetAct, m ) + { + // create the formal net + if ( Vec_PtrSize(pBundle0->vNetsActual) == 1 ) + sprintf( Buffer, "%s", pBundle0->pNameFormal ); + else + sprintf( Buffer, "%s[%d]", pBundle0->pNameFormal, m ); + assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL ); + pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer ); + // connect it to the box + pTerm = Abc_NtkCreateBo( pNtk ); + assert( Abc_NtkBoxNum(pNtk) <= 1 ); + pBox = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk); + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNetFormal ); + Abc_ObjAddFanin( pNetFormal, pTerm ); + Abc_ObjAddFanin( pTerm, pBox ); + } + + // go through instances of this type + pName = Extra_UtilStrsav(pBundle0->pNameFormal); + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + { + // find a bundle with the given name in this instance + Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + if ( pBundle && !strcmp( pBundle->pNameFormal, pName ) ) + break; + // skip non-driven bundles + if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) + continue; + // check if any nets are driven in this bundle + Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m ) + if ( Abc_ObjFaninNum(pNetAct) > 0 ) + { + sprintf( pMan->sError, "Internal error while trying to connect undefined boxes. It is likely that the algorithm currently used has its limitations." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + // drive the nets by the undef box + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m ) + { + pTermNew = Abc_NtkCreateBo( pNetAct->pNtk ); + Abc_ObjAddFanin( pTermNew, pBox ); + Abc_ObjAddFanin( pNetAct, pTermNew ); + } + // remove the bundle + Ver_ParseFreeBundle( pBundle ); + Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL ); + } + free( pName ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Drives the bundle in the given undef box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseDriveInputs( Ver_Man_t * pMan, Vec_Ptr_t * vUndefs ) +{ + char Buffer[200]; + Ver_Bundle_t * pBundle; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pBox, * pBox2, * pTerm, * pTermNew, * pNetFormal, * pNetAct; + int i, k, j, m, CountCur, CountTotal = -1; + // iterate through the undef boxes + Vec_PtrForEachEntry( vUndefs, pNtk, i ) + { + // count the number of unconnected bundles for instances of this type of box + CountTotal = -1; + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + { + CountCur = 0; + Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + CountCur += (pBundle != NULL); + if ( CountTotal == -1 ) + CountTotal = CountCur; + else if ( CountTotal != CountCur ) + { + sprintf( pMan->sError, "The number of formal inputs (%d) is different from the expected one (%d) when instantiating network %s in box %s.", + CountCur, CountTotal, pNtk->pName, Abc_ObjName(pBox) ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; + } + } + + // create formals + pBox = Vec_PtrEntry( pNtk->pData, 0 ); + Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + { + if ( pBundle == NULL ) + continue; + Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m ) + { + // find create the formal net + if ( Vec_PtrSize(pBundle->vNetsActual) == 1 ) + sprintf( Buffer, "%s", pBundle->pNameFormal ); + else + sprintf( Buffer, "%s[%d]", pBundle->pNameFormal, m ); + assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL ); + pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer ); + // connect + pTerm = Abc_NtkCreateBi( pNtk ); + assert( Abc_NtkBoxNum(pNtk) <= 1 ); + pBox2 = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk); + Abc_ObjAddFanin( pNetFormal, Abc_NtkCreatePi(pNtk) ); + Abc_ObjAddFanin( pTerm, pNetFormal ); + Abc_ObjAddFanin( pBox2, pTerm ); + } + } + + // go through all the boxes + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + { + // go through all the bundles + Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) + { + if ( pBundle == NULL ) + continue; + // drive the nets by the undef box + Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m ) + { + pTermNew = Abc_NtkCreateBi( pNetAct->pNtk ); + Abc_ObjAddFanin( pBox, pTermNew ); + Abc_ObjAddFanin( pTermNew, pNetAct ); + } + // remove the bundle + Ver_ParseFreeBundle( pBundle ); + Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL ); + } + + // free the bundles + Vec_PtrFree( (Vec_Ptr_t *)pBox->pCopy ); + pBox->pCopy = NULL; + } + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Returns the max size of any undef box.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseMaxBoxSize( Vec_Ptr_t * vUndefs ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pBox; + int i, k, nMaxSize = 0; + // go through undef box types + Vec_PtrForEachEntry( vUndefs, pNtk, i ) + // go through instances of this type + Vec_PtrForEachEntry( pNtk->pData, pBox, k ) + // check the number of bundles of this instance + if ( nMaxSize < Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) + nMaxSize = Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy); + return nMaxSize; +} + +/**Function************************************************************* + + Synopsis [Prints the comprehensive report into a log file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_ParsePrintLog( Ver_Man_t * pMan ) +{ + Abc_Ntk_t * pNtk, * pNtkBox; + Abc_Obj_t * pBox; + FILE * pFile; + char * pNameGeneric; + char Buffer[1000]; + int i, k; + + // open the log file + pNameGeneric = Extra_FileNameGeneric( pMan->pFileName ); + sprintf( Buffer, "%s.log", pNameGeneric ); + free( pNameGeneric ); + pFile = fopen( Buffer, "w" ); + + // count the total number of instances and how many times they occur + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + pNtk->fHieVisited = 0; + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + Abc_NtkForEachBox( pNtk, pBox, k ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + pNtkBox = pBox->pData; + if ( pNtkBox == NULL ) + continue; + pNtkBox->fHieVisited++; + } + // print each box and its stats + fprintf( pFile, "The hierarhical design %s contains %d modules:\n", pMan->pFileName, Vec_PtrSize(pMan->pDesign->vModules) ); + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + fprintf( pFile, "%-24s : ", Abc_NtkName(pNtk) ); + if ( !Ver_NtkIsDefined(pNtk) ) + fprintf( pFile, "undefbox" ); + else if ( Abc_NtkHasBlackbox(pNtk) ) + fprintf( pFile, "blackbox" ); + else + fprintf( pFile, "logicbox" ); + fprintf( pFile, " instantiated %6d times ", pNtk->fHieVisited ); +// fprintf( pFile, "\n " ); + fprintf( pFile, " pi = %4d", Abc_NtkPiNum(pNtk) ); + fprintf( pFile, " po = %4d", Abc_NtkPiNum(pNtk) ); + fprintf( pFile, " nd = %8d", Abc_NtkNodeNum(pNtk) ); + fprintf( pFile, " lat = %6d", Abc_NtkLatchNum(pNtk) ); + fprintf( pFile, " box = %6d", Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); + fprintf( pFile, "\n" ); + } + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + pNtk->fHieVisited = 0; + + // report instances with dangling outputs + if ( Vec_PtrSize(pMan->pDesign->vModules) > 1 ) + { + Vec_Ptr_t * vBundles; + Ver_Bundle_t * pBundle; + int j, nActNets, Counter = 0, CounterBoxes = 0; + // count the number of instances with dangling outputs + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + Abc_NtkForEachBox( pNtk, pBox, k ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + vBundles = (Vec_Ptr_t *)pBox->pCopy; + pNtkBox = pBox->pData; + if ( pNtkBox == NULL ) + continue; + if ( !Ver_NtkIsDefined(pNtkBox) ) + continue; + // count the number of actual nets + nActNets = 0; + Vec_PtrForEachEntry( vBundles, pBundle, j ) + nActNets += Vec_PtrSize(pBundle->vNetsActual); + // the box is defined and will be connected + if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) + Counter++; + } + } + if ( Counter == 0 ) + fprintf( pFile, "The outputs of all box instances are connected.\n" ); + else + { + fprintf( pFile, "\n" ); + fprintf( pFile, "The outputs of %d box instances are not connected:\n", Counter ); + // enumerate through the boxes + Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) + { + Abc_NtkForEachBox( pNtk, pBox, k ) + { + if ( Abc_ObjIsLatch(pBox) ) + continue; + vBundles = (Vec_Ptr_t *)pBox->pCopy; + pNtkBox = pBox->pData; + if ( pNtkBox == NULL ) + continue; + if ( !Ver_NtkIsDefined(pNtkBox) ) + continue; + // count the number of actual nets + nActNets = 0; + Vec_PtrForEachEntry( vBundles, pBundle, j ) + nActNets += Vec_PtrSize(pBundle->vNetsActual); + // the box is defined and will be connected + if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) + fprintf( pFile, "In module \"%s\" instance \"%s\" of box \"%s\" has different numbers of actual/formal nets (%d/%d).\n", + Abc_NtkName(pNtk), Abc_ObjName(pBox), Abc_NtkName(pNtkBox), nActNets, Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ); + } + } + } + } + fclose( pFile ); + printf( "Hierarchy statistics can be found in log file \"%s\".\n", Buffer ); +} + + +/**Function************************************************************* + + Synopsis [Attaches the boxes to the network.] + + Description [This procedure is called after the design is parsed. + At that point, all the defined models have their PIs present. + They are connected first. Next undef boxes are processed (if present). + Iteratively, one bundle is selected to be driven by the undef boxes in such + a way that there is no conflict (if it is driven by an instance of the box, + no other net will be driven twice by the same formal net of some other instance + of the same box). In the end, all the remaining nets that cannot be driven + by the undef boxes are connected to the undef boxes as inputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseAttachBoxes( Ver_Man_t * pMan ) +{ + Abc_Ntk_t * pNtk; + Ver_Bundle_t * pBundle; + Vec_Ptr_t * vUndefs; + int i, RetValue, Counter, nMaxBoxSize; + + // print the log file + if ( pMan->pDesign->vModules && Vec_PtrSize(pMan->pDesign->vModules) > 1 ) + Ver_ParsePrintLog( pMan ); + + // connect defined boxes + RetValue = Ver_ParseConnectDefBoxes( pMan ); + if ( RetValue < 2 ) + return RetValue; + + // report the boxes + Ver_ParseReportUndefBoxes( pMan ); + + // collect undef box types and their actual instances + vUndefs = Ver_ParseCollectUndefBoxes( pMan ); + assert( Vec_PtrSize( vUndefs ) > 0 ); + + // go through all undef box types + Counter = 0; + nMaxBoxSize = Ver_ParseMaxBoxSize( vUndefs ); + while ( Ver_ParseCheckNondrivenNets(vUndefs) && Counter < nMaxBoxSize ) + { + // go through undef box types + pBundle = NULL; + Vec_PtrForEachEntry( vUndefs, pNtk, i ) + if ( pBundle = Ver_ParseGetNondrivenBundle( pNtk, Counter ) ) + break; + if ( pBundle == NULL ) + { + Counter++; + continue; + } + // drive this bundle by this box + if ( !Ver_ParseDriveFormal( pMan, pNtk, pBundle ) ) + return 0; + } + + // make all the remaining bundles the drivers of undefs + if ( !Ver_ParseDriveInputs( pMan, vUndefs ) ) + return 0; + + // cleanup + Vec_PtrForEachEntry( vUndefs, pNtk, i ) + { + Vec_PtrFree( pNtk->pData ); + pNtk->pData = NULL; + } + Vec_PtrFree( vUndefs ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Creates PI terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PI net +// pNet = Ver_ParseFindNet( pNtk, pName ); +// if ( pNet ) +// printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PI node + pTerm = Abc_NtkCreatePi( pNtk ); + Abc_ObjAddFanin( pNet, pTerm ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Creates PO terminal and net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet, * pTerm; + // get the PO net +// pNet = Ver_ParseFindNet( pNtk, pName ); +// if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) +// printf( "Warning: PO \"%s\" appears twice in the list.\n", pName ); + pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); + // add the PO node + pTerm = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pTerm, pNet ); + return pTerm; +} + +/**Function************************************************************* + + Synopsis [Create a latch with the given input/output.] + + Description [By default, the latch value is a don't-care.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO ) +{ + Abc_Obj_t * pLatch, * pTerm; + // add the BO terminal + pTerm = Abc_NtkCreateBi( pNtk ); + Abc_ObjAddFanin( pTerm, pNetLI ); + // add the latch box + pLatch = Abc_NtkCreateLatch( pNtk ); + Abc_ObjAddFanin( pLatch, pTerm ); + // add the BI terminal + pTerm = Abc_NtkCreateBo( pNtk ); + Abc_ObjAddFanin( pTerm, pLatch ); + // get the LO net + Abc_ObjAddFanin( pNetLO, pTerm ); + // set latch name + Abc_ObjAssignName( pLatch, Abc_ObjName(pNetLO), "L" ); + Abc_LatchSetInitDc( pLatch ); + return pLatch; +} + +/**Function************************************************************* + + Synopsis [Creates inverter and returns its net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ) +{ + Abc_Obj_t * pObj; + pObj = Abc_NtkCreateNodeInv( pNtk, pNet ); + pNet = Abc_NtkCreateNet( pNtk ); + Abc_ObjAddFanin( pNet, pObj ); + return pNet; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/ver/verFormula.c b/abc70930/src/base/ver/verFormula.c new file mode 100644 index 00000000..19a2c523 --- /dev/null +++ b/abc70930/src/base/ver/verFormula.c @@ -0,0 +1,474 @@ +/**CFile**************************************************************** + + FileName [verFormula.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Formula parser to read Verilog assign statements.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verFormula.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the list of operation symbols to be used in expressions +#define VER_PARSE_SYM_OPEN '(' // opening paranthesis +#define VER_PARSE_SYM_CLOSE ')' // closing paranthesis +#define VER_PARSE_SYM_CONST0 '0' // constant 0 +#define VER_PARSE_SYM_CONST1 '1' // constant 1 +#define VER_PARSE_SYM_NEGBEF1 '!' // negation before the variable +#define VER_PARSE_SYM_NEGBEF2 '~' // negation before the variable +#define VER_PARSE_SYM_AND '&' // logic AND +#define VER_PARSE_SYM_OR '|' // logic OR +#define VER_PARSE_SYM_XOR '^' // logic XOR +#define VER_PARSE_SYM_MUX1 '?' // first symbol of MUX +#define VER_PARSE_SYM_MUX2 ':' // second symbol of MUX + +// the list of opcodes (also specifying operation precedence) +#define VER_PARSE_OPER_NEG 7 // negation (highest precedence) +#define VER_PARSE_OPER_AND 6 // logic AND +#define VER_PARSE_OPER_XOR 5 // logic EXOR (a'b | ab') +#define VER_PARSE_OPER_OR 4 // logic OR +#define VER_PARSE_OPER_EQU 3 // equvalence (a'b'| ab ) +#define VER_PARSE_OPER_MUX 2 // MUX(a,b,c) (ab | a'c ) +#define VER_PARSE_OPER_MARK 1 // OpStack token standing for an opening paranthesis + +// these are values of the internal Flag +#define VER_PARSE_FLAG_START 1 // after the opening parenthesis +#define VER_PARSE_FLAG_VAR 2 // after operation is received +#define VER_PARSE_FLAG_OPER 3 // after operation symbol is received +#define VER_PARSE_FLAG_ERROR 4 // when error is detected + +static Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ); +static int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Parser of the formula encountered in assign statements.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ) +{ + char * pTemp; + Hop_Obj_t * bFunc, * bTemp; + int nParans, Flag; + int Oper, Oper1, Oper2; + int v; + + // clear the stacks and the names + Vec_PtrClear( vNames ); + Vec_PtrClear( vStackFn ); + Vec_IntClear( vStackOp ); + + if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1\'b0") ) + return Hop_ManConst0(pMan); + if ( !strcmp(pFormula, "1") || !strcmp(pFormula, "1\'b1") ) + return Hop_ManConst1(pMan); + + // make sure that the number of opening and closing parantheses is the same + nParans = 0; + for ( pTemp = pFormula; *pTemp; pTemp++ ) + if ( *pTemp == '(' ) + nParans++; + else if ( *pTemp == ')' ) + nParans--; + if ( nParans != 0 ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Different number of opening and closing parantheses ()." ); + return NULL; + } + + // add parantheses + pTemp = pFormula + strlen(pFormula) + 2; + *pTemp-- = 0; *pTemp = ')'; + while ( --pTemp != pFormula ) + *pTemp = *(pTemp - 1); + *pTemp = '('; + + // perform parsing + Flag = VER_PARSE_FLAG_START; + for ( pTemp = pFormula; *pTemp; pTemp++ ) + { + switch ( *pTemp ) + { + // skip all spaces, tabs, and end-of-lines + case ' ': + case '\t': + case '\r': + case '\n': + continue; +/* + // treat Constant 0 as a variable + case VER_PARSE_SYM_CONST0: + Vec_PtrPush( vStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( Hop_ManConst0(pMan) ); + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 0." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Flag = VER_PARSE_FLAG_VAR; + break; + + // the same for Constant 1 + case VER_PARSE_SYM_CONST1: + Vec_PtrPush( vStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( Hop_ManConst1(pMan) ); + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 1." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Flag = VER_PARSE_FLAG_VAR; + break; +*/ + case VER_PARSE_SYM_NEGBEF1: + case VER_PARSE_SYM_NEGBEF2: + if ( Flag == VER_PARSE_FLAG_VAR ) + {// if NEGBEF follows a variable, AND is assumed + sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before negation." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Vec_IntPush( vStackOp, VER_PARSE_OPER_NEG ); + break; + + case VER_PARSE_SYM_AND: + case VER_PARSE_SYM_OR: + case VER_PARSE_SYM_XOR: + case VER_PARSE_SYM_MUX1: + case VER_PARSE_SYM_MUX2: + if ( Flag != VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + if ( *pTemp == VER_PARSE_SYM_AND ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_AND ); + else if ( *pTemp == VER_PARSE_SYM_OR ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_OR ); + else if ( *pTemp == VER_PARSE_SYM_XOR ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_XOR ); + else if ( *pTemp == VER_PARSE_SYM_MUX1 ) + Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); +// else if ( *pTemp == VER_PARSE_SYM_MUX2 ) +// Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); + Flag = VER_PARSE_FLAG_OPER; + break; + + case VER_PARSE_SYM_OPEN: + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before a paranthesis." ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Vec_IntPush( vStackOp, VER_PARSE_OPER_MARK ); + // after an opening bracket, it feels like starting over again + Flag = VER_PARSE_FLAG_START; + break; + + case VER_PARSE_SYM_CLOSE: + if ( Vec_IntSize( vStackOp ) ) + { + while ( 1 ) + { + if ( !Vec_IntSize( vStackOp ) ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + Oper = Vec_IntPop( vStackOp ); + if ( Oper == VER_PARSE_OPER_MARK ) + break; + // skip the second MUX operation +// if ( Oper == VER_PARSE_OPER_MUX2 ) +// { +// Oper = Vec_IntPop( vStackOp ); +// assert( Oper == VER_PARSE_OPER_MUX1 ); +// } + + // perform the given operation + if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper ) == NULL ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); + return NULL; + } + } + } + else + { + sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); + Flag = VER_PARSE_FLAG_ERROR; + break; + } + if ( Flag != VER_PARSE_FLAG_ERROR ) + Flag = VER_PARSE_FLAG_VAR; + break; + + + default: + // scan the next name + v = Ver_FormulaParserFindVar( pTemp, vNames ); + if ( *pTemp == '\\' ) + pTemp++; + pTemp += (int)Vec_PtrEntry( vNames, 2*v ) - 1; + + // assume operation AND, if vars follow one another + if ( Flag == VER_PARSE_FLAG_VAR ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Incorrect state." ); + return NULL; + } + bTemp = Hop_IthVar( pMan, v ); + Vec_PtrPush( vStackFn, bTemp ); // Cudd_Ref( bTemp ); + Flag = VER_PARSE_FLAG_VAR; + break; + } + + if ( Flag == VER_PARSE_FLAG_ERROR ) + break; // error exit + else if ( Flag == VER_PARSE_FLAG_START ) + continue; // go on parsing + else if ( Flag == VER_PARSE_FLAG_VAR ) + while ( 1 ) + { // check if there are negations in the OpStack + if ( !Vec_IntSize(vStackOp) ) + break; + Oper = Vec_IntPop( vStackOp ); + if ( Oper != VER_PARSE_OPER_NEG ) + { + Vec_IntPush( vStackOp, Oper ); + break; + } + else + { +// Vec_PtrPush( vStackFn, Cudd_Not(Vec_PtrPop(vStackFn)) ); + Vec_PtrPush( vStackFn, Hop_Not(Vec_PtrPop(vStackFn)) ); + } + } + else // if ( Flag == VER_PARSE_FLAG_OPER ) + while ( 1 ) + { // execute all the operations in the OpStack + // with precedence higher or equal than the last one + Oper1 = Vec_IntPop( vStackOp ); // the last operation + if ( !Vec_IntSize(vStackOp) ) + { // if it is the only operation, push it back + Vec_IntPush( vStackOp, Oper1 ); + break; + } + Oper2 = Vec_IntPop( vStackOp ); // the operation before the last one + if ( Oper2 >= Oper1 && !(Oper1 == Oper2 && Oper1 == VER_PARSE_OPER_MUX) ) + { // if Oper2 precedence is higher or equal, execute it + if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper2 ) == NULL ) + { + sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); + return NULL; + } + Vec_IntPush( vStackOp, Oper1 ); // push the last operation back + } + else + { // if Oper2 precedence is lower, push them back and done + Vec_IntPush( vStackOp, Oper2 ); + Vec_IntPush( vStackOp, Oper1 ); + break; + } + } + } + + if ( Flag != VER_PARSE_FLAG_ERROR ) + { + if ( Vec_PtrSize(vStackFn) ) + { + bFunc = Vec_PtrPop(vStackFn); + if ( !Vec_PtrSize(vStackFn) ) + if ( !Vec_IntSize(vStackOp) ) + { +// Cudd_Deref( bFunc ); + return bFunc; + } + else + sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the operation stack\n" ); + else + sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the function stack\n" ); + } + else + sprintf( pErrorMessage, "Parse_FormulaParser(): The input string is empty\n" ); + } +// Cudd_Ref( bFunc ); +// Cudd_RecursiveDeref( dd, bFunc ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs the operation on the top entries in the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ) +{ + Hop_Obj_t * bArg0, * bArg1, * bArg2, * bFunc; + // perform the given operation + bArg2 = Vec_PtrPop( vStackFn ); + bArg1 = Vec_PtrPop( vStackFn ); + if ( Oper == VER_PARSE_OPER_AND ) + bFunc = Hop_And( pMan, bArg1, bArg2 ); + else if ( Oper == VER_PARSE_OPER_XOR ) + bFunc = Hop_Exor( pMan, bArg1, bArg2 ); + else if ( Oper == VER_PARSE_OPER_OR ) + bFunc = Hop_Or( pMan, bArg1, bArg2 ); + else if ( Oper == VER_PARSE_OPER_EQU ) + bFunc = Hop_Not( Hop_Exor( pMan, bArg1, bArg2 ) ); + else if ( Oper == VER_PARSE_OPER_MUX ) + { + bArg0 = Vec_PtrPop( vStackFn ); +// bFunc = Cudd_bddIte( dd, bArg0, bArg1, bArg2 ); Cudd_Ref( bFunc ); + bFunc = Hop_Mux( pMan, bArg0, bArg1, bArg2 ); +// Cudd_RecursiveDeref( dd, bArg0 ); +// Cudd_Deref( bFunc ); + } + else + return NULL; +// Cudd_Ref( bFunc ); +// Cudd_RecursiveDeref( dd, bArg1 ); +// Cudd_RecursiveDeref( dd, bArg2 ); + Vec_PtrPush( vStackFn, bFunc ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Returns the index of the new variable found.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ) +{ + char * pTemp, * pTemp2; + int nLength, nLength2, i; + // start the string + pTemp = pString; + // find the end of the string delimited by other characters + if ( *pTemp == '\\' ) + { + pString++; + while ( *pTemp && *pTemp != ' ' ) + pTemp++; + } + else + { + while ( *pTemp && *pTemp != ' ' && *pTemp != '\t' && *pTemp != '\r' && *pTemp != '\n' && *pTemp != ',' && *pTemp != '}' && + *pTemp != VER_PARSE_SYM_OPEN && *pTemp != VER_PARSE_SYM_CLOSE && + *pTemp != VER_PARSE_SYM_NEGBEF1 && *pTemp != VER_PARSE_SYM_NEGBEF2 && + *pTemp != VER_PARSE_SYM_AND && *pTemp != VER_PARSE_SYM_OR && *pTemp != VER_PARSE_SYM_XOR && + *pTemp != VER_PARSE_SYM_MUX1 && *pTemp != VER_PARSE_SYM_MUX2 ) + pTemp++; + } + // look for this string in the array + nLength = pTemp - pString; + for ( i = 0; i < Vec_PtrSize(vNames)/2; i++ ) + { + nLength2 = (int)Vec_PtrEntry( vNames, 2*i + 0 ); + if ( nLength2 != nLength ) + continue; + pTemp2 = Vec_PtrEntry( vNames, 2*i + 1 ); + if ( strncmp( pString, pTemp2, nLength ) ) + continue; + return i; + } + // could not find - add and return the number + Vec_PtrPush( vNames, (void *)nLength ); + Vec_PtrPush( vNames, pString ); + return i; +} + +/**Function************************************************************* + + Synopsis [Returns the AIG representation of the reduction formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ) +{ + Hop_Obj_t * pRes; + int v, fCompl; + char Symbol; + + // get the operation + Symbol = *pFormula++; + fCompl = ( Symbol == '~' ); + if ( fCompl ) + Symbol = *pFormula++; + // check the operation + if ( Symbol != '&' && Symbol != '|' && Symbol != '^' ) + { + sprintf( pErrorMessage, "Ver_FormulaReduction(): Unknown operation (%c)\n", Symbol ); + return NULL; + } + // skip the brace + while ( *pFormula++ != '{' ); + // parse the names + Vec_PtrClear( vNames ); + while ( *pFormula != '}' ) + { + v = Ver_FormulaParserFindVar( pFormula, vNames ); + pFormula += (int)Vec_PtrEntry( vNames, 2*v ); + while ( *pFormula == ' ' || *pFormula == ',' ) + pFormula++; + } + // compute the function + if ( Symbol == '&' ) + pRes = Hop_CreateAnd( pMan, Vec_PtrSize(vNames)/2 ); + else if ( Symbol == '|' ) + pRes = Hop_CreateOr( pMan, Vec_PtrSize(vNames)/2 ); + else if ( Symbol == '^' ) + pRes = Hop_CreateExor( pMan, Vec_PtrSize(vNames)/2 ); + return Hop_NotCond( pRes, fCompl ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/ver/verParse.c b/abc70930/src/base/ver/verParse.c new file mode 100644 index 00000000..9462fc8b --- /dev/null +++ b/abc70930/src/base/ver/verParse.c @@ -0,0 +1,117 @@ +/**CFile**************************************************************** + + FileName [verParse.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Performs some Verilog parsing tasks.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verParse.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Skips the comments of they are present.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_ParseSkipComments( Ver_Man_t * pMan ) +{ + Ver_Stream_t * p = pMan->pReader; + char Symbol; + // skip spaces + Ver_StreamSkipChars( p, " \t\n\r" ); + if ( !Ver_StreamIsOkey(pMan->pReader) ) + return 1; + // read the first symbol + Symbol = Ver_StreamScanChar( p ); + if ( Symbol != '/' ) + return 1; + Ver_StreamPopChar( p ); + // read the second symbol + Symbol = Ver_StreamScanChar( p ); + if ( Symbol == '/' ) + { // skip till the end of line + Ver_StreamSkipToChars( p, "\n" ); + return Ver_ParseSkipComments( pMan ); + } + if ( Symbol == '*' ) + { // skip till the next occurance of */ + Ver_StreamPopChar( p ); + do { + Ver_StreamSkipToChars( p, "*" ); + Ver_StreamPopChar( p ); + } while ( Ver_StreamScanChar( p ) != '/' ); + Ver_StreamPopChar( p ); + return Ver_ParseSkipComments( pMan ); + } + sprintf( pMan->sError, "Cannot parse after symbol \"/\"." ); + Ver_ParsePrintErrorMessage( pMan ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Parses a Verilog name that can be being with a slash.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ver_ParseGetName( Ver_Man_t * pMan ) +{ + Ver_Stream_t * p = pMan->pReader; + char Symbol; + char * pWord; + pMan->fNameLast = 0; + if ( !Ver_StreamIsOkey(p) ) + return NULL; + if ( !Ver_ParseSkipComments( pMan ) ) + return NULL; + Symbol = Ver_StreamScanChar( p ); + if ( Symbol == '\\' ) + { + pMan->fNameLast = 1; + Ver_StreamPopChar( p ); + pWord = Ver_StreamGetWord( p, " \r\n" ); + } + else + pWord = Ver_StreamGetWord( p, " \t\n\r(),;" ); + if ( !Ver_ParseSkipComments( pMan ) ) + return NULL; + return pWord; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/ver/verStream.c b/abc70930/src/base/ver/verStream.c new file mode 100644 index 00000000..9b56bb3f --- /dev/null +++ b/abc70930/src/base/ver/verStream.c @@ -0,0 +1,443 @@ +/**CFile**************************************************************** + + FileName [verStream.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Input file stream, which knows nothing about Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verStream.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define VER_BUFFER_SIZE 1048576 // 1M - size of the data chunk stored in memory +#define VER_OFFSET_SIZE 65536 // 64K - load new data when less than this is left +#define VER_WORD_SIZE 65536 // 64K - the largest token that can be returned + +#define VER_MINIMUM(a,b) (((a) < (b))? (a) : (b)) + +struct Ver_Stream_t_ +{ + // the input file + char * pFileName; // the input file name + FILE * pFile; // the input file pointer + int nFileSize; // the total number of bytes in the file + int nFileRead; // the number of bytes currently read from file + int nLineCounter; // the counter of lines processed + // temporary storage for data + char * pBuffer; // the buffer + int nBufferSize; // the size of the buffer + char * pBufferCur; // the current reading position + char * pBufferEnd; // the first position not used by currently loaded data + char * pBufferStop; // the position where loading new data will be done + // tokens given to the user + char pChars[VER_WORD_SIZE+5]; // temporary storage for a word (plus end-of-string and two parantheses) + int nChars; // the total number of characters in the word + // status of the parser + int fStop; // this flag goes high when the end of file is reached +}; + +static void Ver_StreamReload( Ver_Stream_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the file reader for the given file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ver_Stream_t * Ver_StreamAlloc( char * pFileName ) +{ + Ver_Stream_t * p; + FILE * pFile; + int nCharsToRead; + // check if the file can be opened + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Ver_StreamAlloc(): Cannot open input file \"%s\".\n", pFileName ); + return NULL; + } + // start the file reader + p = ALLOC( Ver_Stream_t, 1 ); + memset( p, 0, sizeof(Ver_Stream_t) ); + p->pFileName = pFileName; + p->pFile = pFile; + // get the file size, in bytes + fseek( pFile, 0, SEEK_END ); + p->nFileSize = ftell( pFile ); + rewind( pFile ); + // allocate the buffer + p->pBuffer = ALLOC( char, VER_BUFFER_SIZE+1 ); + p->nBufferSize = VER_BUFFER_SIZE; + p->pBufferCur = p->pBuffer; + // determine how many chars to read + nCharsToRead = VER_MINIMUM(p->nFileSize, VER_BUFFER_SIZE); + // load the first part into the buffer + fread( p->pBuffer, nCharsToRead, 1, p->pFile ); + p->nFileRead = nCharsToRead; + // set the ponters to the end and the stopping point + p->pBufferEnd = p->pBuffer + nCharsToRead; + p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; + // start the arrays + p->nLineCounter = 1; // 1-based line counting + return p; +} + +/**Function************************************************************* + + Synopsis [Loads new data into the file reader.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamReload( Ver_Stream_t * p ) +{ + int nCharsUsed, nCharsToRead; + assert( !p->fStop ); + assert( p->pBufferCur > p->pBufferStop ); + assert( p->pBufferCur < p->pBufferEnd ); + // figure out how many chars are still not processed + nCharsUsed = p->pBufferEnd - p->pBufferCur; + // move the remaining data to the beginning of the buffer + memmove( p->pBuffer, p->pBufferCur, nCharsUsed ); + p->pBufferCur = p->pBuffer; + // determine how many chars we will read + nCharsToRead = VER_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead ); + // read the chars + fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile ); + p->nFileRead += nCharsToRead; + // set the ponters to the end and the stopping point + p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead; + p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; +} + +/**Function************************************************************* + + Synopsis [Stops the file reader.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamFree( Ver_Stream_t * p ) +{ + if ( p->pFile ) + fclose( p->pFile ); + FREE( p->pBuffer ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the file size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ver_StreamGetFileName( Ver_Stream_t * p ) +{ + return p->pFileName; +} + +/**Function************************************************************* + + Synopsis [Returns the file size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamGetFileSize( Ver_Stream_t * p ) +{ + return p->nFileSize; +} + +/**Function************************************************************* + + Synopsis [Returns the current reading position.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamGetCurPosition( Ver_Stream_t * p ) +{ + return p->nFileRead - (p->pBufferEnd - p->pBufferCur); +} + +/**Function************************************************************* + + Synopsis [Returns the line number for the given token.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamGetLineNumber( Ver_Stream_t * p ) +{ + return p->nLineCounter; +} + + + +/**Function************************************************************* + + Synopsis [Returns current symbol.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ver_StreamIsOkey( Ver_Stream_t * p ) +{ + return !p->fStop; +} + +/**Function************************************************************* + + Synopsis [Returns current symbol.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char Ver_StreamScanChar( Ver_Stream_t * p ) +{ + assert( !p->fStop ); + return *p->pBufferCur; +} + +/**Function************************************************************* + + Synopsis [Returns current symbol and moves to the next.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char Ver_StreamPopChar( Ver_Stream_t * p ) +{ + assert( !p->fStop ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // check if there are symbols left + if ( p->pBufferCur == p->pBufferEnd ) // end of file + { + p->fStop = 1; + return -1; + } + // count the lines + if ( *p->pBufferCur == '\n' ) + p->nLineCounter++; + return *p->pBufferCur++; +} + +/**Function************************************************************* + + Synopsis [Skips the current symbol and all symbols from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ) +{ + char * pChar, * pTemp; + assert( !p->fStop ); + assert( pCharsToSkip != NULL ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // skip the symbols + for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) + { + // skip symbols as long as they are in the list + for ( pTemp = pCharsToSkip; *pTemp; pTemp++ ) + if ( *pChar == *pTemp ) + break; + if ( *pTemp == 0 ) // pChar is not found in the list + { + p->pBufferCur = pChar; + return; + } + // count the lines + if ( *pChar == '\n' ) + p->nLineCounter++; + } + // the file is finished or the last part continued + // through VER_OFFSET_SIZE chars till the end of the buffer + if ( p->pBufferStop == p->pBufferEnd ) // end of file + { + p->fStop = 1; + return; + } + printf( "Ver_StreamSkipSymbol() failed to parse the file \"%s\".\n", p->pFileName ); +} + +/**Function************************************************************* + + Synopsis [Skips all symbols until encountering one from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ) +{ + char * pChar, * pTemp; + assert( !p->fStop ); + assert( pCharsToStop != NULL ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // skip the symbols + for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) + { + // skip symbols as long as they are NOT in the list + for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) + if ( *pChar == *pTemp ) + break; + if ( *pTemp == 0 ) // pChar is not found in the list + { + // count the lines + if ( *pChar == '\n' ) + p->nLineCounter++; + continue; + } + // the symbol is found - move position and return + p->pBufferCur = pChar; + return; + } + // the file is finished or the last part continued + // through VER_OFFSET_SIZE chars till the end of the buffer + if ( p->pBufferStop == p->pBufferEnd ) // end of file + { + p->fStop = 1; + return; + } + printf( "Ver_StreamSkipToSymbol() failed to parse the file \"%s\".\n", p->pFileName ); +} + +/**Function************************************************************* + + Synopsis [Returns current word delimited by the set of symbols.] + + Description [Modifies the stream by inserting 0 at the first encounter + of one of the symbols in the list.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ) +{ + char * pChar, * pTemp; + if ( p->fStop ) + return NULL; + assert( pCharsToStop != NULL ); + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Ver_StreamReload( p ); + // skip the symbols + p->nChars = 0; + for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) + { + // skip symbols as long as they are NOT in the list + for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) + if ( *pChar == *pTemp ) + break; + if ( *pTemp == 0 ) // pChar is not found in the list + { + p->pChars[p->nChars++] = *pChar; + if ( p->nChars == VER_WORD_SIZE ) + { + printf( "Ver_StreamGetWord(): The buffer size is exceeded.\n" ); + return NULL; + } + // count the lines + if ( *pChar == '\n' ) + p->nLineCounter++; + continue; + } + // the symbol is found - move the position, set the word end, return the word + p->pBufferCur = pChar; + p->pChars[p->nChars] = 0; + return p->pChars; + } + // the file is finished or the last part continued + // through VER_OFFSET_SIZE chars till the end of the buffer + if ( p->pBufferStop == p->pBufferEnd ) // end of file + { + p->fStop = 1; + p->pChars[p->nChars] = 0; + return p->pChars; + } + printf( "Ver_StreamGetWord() failed to parse the file \"%s\".\n", p->pFileName ); + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/ver/verWords.c b/abc70930/src/base/ver/verWords.c new file mode 100644 index 00000000..f9d27010 --- /dev/null +++ b/abc70930/src/base/ver/verWords.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [verWords.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Handles keywords that are currently supported.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: verWords.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/base/ver/ver_.c b/abc70930/src/base/ver/ver_.c new file mode 100644 index 00000000..76599dac --- /dev/null +++ b/abc70930/src/base/ver/ver_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [ver_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Verilog parser.] + + Synopsis [Parses several flavors of structural Verilog.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 19, 2006.] + + Revision [$Id: ver_.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/bdd/cas/cas.h b/abc70930/src/bdd/cas/cas.h new file mode 100644 index 00000000..fcc9f890 --- /dev/null +++ b/abc70930/src/bdd/cas/cas.h @@ -0,0 +1,62 @@ +/**CFile**************************************************************** + + FileName [cas.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cas.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CAS_H__ +#define __CAS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define MAXINPUTS 1024 +#define MAXOUTPUTS 1024 + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== zzz.c ==========================================================*/ + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/bdd/cas/casCore.c b/abc70930/src/bdd/cas/casCore.c new file mode 100644 index 00000000..579235b1 --- /dev/null +++ b/abc70930/src/bdd/cas/casCore.c @@ -0,0 +1,1263 @@ +/**CFile**************************************************************** + + FileName [casCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] + + Synopsis [Entrance into the implementation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Spring 2002.] + + Revision [$Id: casCore.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include + +#include "extra.h" +#include "cas.h" + +//////////////////////////////////////////////////////////////////////// +/// static functions /// +//////////////////////////////////////////////////////////////////////// + +DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose ); +DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ); +DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew ); + +extern int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose ); + +void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName ); + +DdNode * Cudd_bddTransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); + +//////////////////////////////////////////////////////////////////////// +/// static varibles /// +//////////////////////////////////////////////////////////////////////// + +//static FILE * pTable = NULL; +//static long s_RemappingTime = 0; + +//////////////////////////////////////////////////////////////////////// +/// debugging macros /// +//////////////////////////////////////////////////////////////////////// + +#define PRD(p) printf( "\nDECOMPOSITION TREE:\n\n" ); PrintDecEntry( (p), 0 ) +#define PRB(f) printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" ) +#define PRK(f,n) Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" ) +#define PRK2(f,g,n) Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" ) + + +//////////////////////////////////////////////////////////////////////// +/// EXTERNAL FUNCTIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose ) +{ + int i; + int nVars = nInputs; + int nOuts = nOutputs; + long clk1; + + int nVarsEnc; // the number of additional variables to encode outputs + DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars + + int nNames; // the total number of all inputs + char * pNames[MAXINPUTS]; // the temporary storage for the input (and output encoding) names + + DdNode * aFunc; // the encoded 0-1 BDD containing all the outputs + + char FileNameIni[100]; + char FileNameFin[100]; + char Buffer[100]; + + +//pTable = fopen( "stats.txt", "a+" ); +//fprintf( pTable, "%s ", pFileGeneric ); +//fprintf( pTable, "%d ", nVars ); +//fprintf( pTable, "%d ", nOuts ); + + + // assign the file names + strcpy( FileNameIni, pFileGeneric ); + strcat( FileNameIni, "_ENC.blif" ); + + strcpy( FileNameFin, pFileGeneric ); + strcat( FileNameFin, "_LUT.blif" ); + + + // create the variables to encode the outputs + nVarsEnc = Extra_Base2Log( nOuts ); + for ( i = 0; i < nVarsEnc; i++ ) + pbVarsEnc[i] = Cudd_bddNewVarAtLevel( dd, i ); + + + // store the input names + nNames = nVars + nVarsEnc; + for ( i = 0; i < nVars; i++ ) + { +// pNames[i] = Extra_UtilStrsav( pFunc->pInputNames[i] ); + sprintf( Buffer, "pi%03d", i ); + pNames[i] = Extra_UtilStrsav( Buffer ); + } + // set the encoding variable name + for ( ; i < nNames; i++ ) + { + sprintf( Buffer, "OutEnc_%02d", i-nVars ); + pNames[i] = Extra_UtilStrsav( Buffer ); + } + + + // print the variable order +// printf( "\n" ); +// printf( "Variable order is: " ); +// for ( i = 0; i < dd->size; i++ ) +// printf( " %d", dd->invperm[i] ); +// printf( "\n" ); + + // derive the single-output function + clk1 = clock(); + aFunc = GetSingleOutputFunction( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc, fVerbose ); Cudd_Ref( aFunc ); +// aFunc = GetSingleOutputFunctionRemapped( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( aFunc ); +// if ( fVerbose ) +// printf( "Single-output function computation time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); + +//fprintf( pTable, "%d ", Cudd_SharingSize( pOutputs, nOutputs ) ); +//fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pOutputs, nOutputs) ); + + // dispose of the multiple-output function +// Extra_Dissolve( pFunc ); + + // reorder the single output function +// if ( fVerbose ) +// printf( "Reordering variables...\n"); + clk1 = clock(); +// if ( fVerbose ) +// printf( "Node count before = %6d\n", Cudd_DagSize( aFunc ) ); +// Cudd_ReduceHeap(dd, CUDD_REORDER_SIFT,1); + Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); + Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); +// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); +// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); +// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); +// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); + if ( fVerbose ) + printf( "MTBDD reordered = %6d nodes\n", Cudd_DagSize( aFunc ) ); + if ( fVerbose ) + printf( "Variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); +// printf( "\n" ); +// printf( "Variable order is: " ); +// for ( i = 0; i < dd->size; i++ ) +// printf( " %d", dd->invperm[i] ); +// printf( "\n" ); +//fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) ); +//fprintf( pTable, "%d ", Extra_ProfileWidthMax(dd, aFunc) ); + + // write the single-output function into BLIF for verification + clk1 = clock(); + if ( fCheck ) + WriteSingleOutputFunctionBlif( dd, aFunc, pNames, nNames, FileNameIni ); +// if ( fVerbose ) +// printf( "Single-output function writing time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); + +/* + /////////////////////////////////////////////////////////////////// + // verification of single output function + clk1 = clock(); + { + BFunc g_Func; + DdNode * aRes; + + g_Func.dd = dd; + g_Func.FileInput = Extra_UtilStrsav(FileNameIni); + + if ( Extra_ReadFile( &g_Func ) == 0 ) + { + printf( "\nSomething did not work out while reading the input file for verification\n"); + Extra_Dissolve( &g_Func ); + return; + } + + aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); + + if ( aRes != aFunc ) + printf( "\nVerification FAILED!\n"); + else + printf( "\nVerification okay!\n"); + + Cudd_RecursiveDeref( dd, aRes ); + + // delocate + Extra_Dissolve( &g_Func ); + } + printf( "Preliminary verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); + /////////////////////////////////////////////////////////////////// +*/ + + if ( !CreateDecomposedNetwork( dd, aFunc, pNames, nNames, FileNameFin, nLutSize, fCheck, fVerbose ) ) + return 0; + +/* + /////////////////////////////////////////////////////////////////// + // verification of the decomposed LUT network + clk1 = clock(); + { + BFunc g_Func; + DdNode * aRes; + + g_Func.dd = dd; + g_Func.FileInput = Extra_UtilStrsav(FileNameFin); + + if ( Extra_ReadFile( &g_Func ) == 0 ) + { + printf( "\nSomething did not work out while reading the input file for verification\n"); + Extra_Dissolve( &g_Func ); + return; + } + + aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); + + if ( aRes != aFunc ) + printf( "\nFinal verification FAILED!\n"); + else + printf( "\nFinal verification okay!\n"); + + Cudd_RecursiveDeref( dd, aRes ); + + // delocate + Extra_Dissolve( &g_Func ); + } + printf( "Final verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); + /////////////////////////////////////////////////////////////////// +*/ + + // verify the results + if ( fCheck ) + { + extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); + extern void * Abc_FrameGetGlobalFrame(); + char Command[200]; + sprintf( Command, "cec %s %s", FileNameIni, FileNameFin ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); + } + + Cudd_RecursiveDeref( dd, aFunc ); + + // release the names + for ( i = 0; i < nNames; i++ ) + free( pNames[i] ); + + +//fprintf( pTable, "\n" ); +//fclose( pTable ); + + return 1; +} + +#if 0 + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Experiment2( BFunc * pFunc ) +{ + int i, x, RetValue; + int nVars = pFunc->nInputs; + int nOuts = pFunc->nOutputs; + DdManager * dd = pFunc->dd; + long clk1; + +// int nVarsEnc; // the number of additional variables to encode outputs +// DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars + + int nNames; // the total number of all inputs + char * pNames[MAXINPUTS]; // the temporary storage for the input (and output encoding) names + + DdNode * aFunc; // the encoded 0-1 BDD containing all the outputs + + char FileNameIni[100]; + char FileNameFin[100]; + char Buffer[100]; + + DdManager * DdNew; + +//pTable = fopen( "stats.txt", "a+" ); +//fprintf( pTable, "%s ", pFunc->FileGeneric ); +//fprintf( pTable, "%d ", nVars ); +//fprintf( pTable, "%d ", nOuts ); + + + // assign the file names + strcpy( FileNameIni, pFunc->FileGeneric ); + strcat( FileNameIni, "_ENC.blif" ); + + strcpy( FileNameFin, pFunc->FileGeneric ); + strcat( FileNameFin, "_LUT.blif" ); + + // derive the single-output function IN THE NEW MANAGER + clk1 = clock(); +// aFunc = GetSingleOutputFunction( dd, pFunc->pOutputs, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( aFunc ); + aFunc = GetSingleOutputFunctionRemappedNewDD( dd, pFunc->pOutputs, nOuts, &DdNew ); Cudd_Ref( aFunc ); + printf( "Single-output function derivation time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); +// s_RemappingTime = clock() - clk1; + + // dispose of the multiple-output function + Extra_Dissolve( pFunc ); + + // reorder the single output function + printf( "\nReordering variables in the new manager...\n"); + clk1 = clock(); + printf( "Node count before = %d\n", Cudd_DagSize( aFunc ) ); +// Cudd_ReduceHeap(DdNew, CUDD_REORDER_SIFT,1); + Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1); +// Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1); + printf( "Node count after = %d\n", Cudd_DagSize( aFunc ) ); + printf( "Variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); + printf( "\n" ); + +//fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) ); +//fprintf( pTable, "%d ", Extra_ProfileWidthMax(DdNew, aFunc) ); + + + // create the names to be used with the new manager + nNames = DdNew->size; + for ( x = 0; x < nNames; x++ ) + { + sprintf( Buffer, "v%02d", x ); + pNames[x] = Extra_UtilStrsav( Buffer ); + } + + + + // write the single-output function into BLIF for verification + clk1 = clock(); + WriteSingleOutputFunctionBlif( DdNew, aFunc, pNames, nNames, FileNameIni ); + printf( "Single-output function writing time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); + + + /////////////////////////////////////////////////////////////////// + // verification of single output function + clk1 = clock(); + { + BFunc g_Func; + DdNode * aRes; + + g_Func.dd = DdNew; + g_Func.FileInput = Extra_UtilStrsav(FileNameIni); + + if ( Extra_ReadFile( &g_Func ) == 0 ) + { + printf( "\nSomething did not work out while reading the input file for verification\n"); + Extra_Dissolve( &g_Func ); + return; + } + + aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); + + if ( aRes != aFunc ) + printf( "\nVerification FAILED!\n"); + else + printf( "\nVerification okay!\n"); + + Cudd_RecursiveDeref( DdNew, aRes ); + + // delocate + Extra_Dissolve( &g_Func ); + } + printf( "Preliminary verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); + /////////////////////////////////////////////////////////////////// + + + CreateDecomposedNetwork( DdNew, aFunc, pNames, nNames, FileNameFin, nLutSize, 0 ); + +/* + /////////////////////////////////////////////////////////////////// + // verification of the decomposed LUT network + clk1 = clock(); + { + BFunc g_Func; + DdNode * aRes; + + g_Func.dd = DdNew; + g_Func.FileInput = Extra_UtilStrsav(FileNameFin); + + if ( Extra_ReadFile( &g_Func ) == 0 ) + { + printf( "\nSomething did not work out while reading the input file for verification\n"); + Extra_Dissolve( &g_Func ); + return; + } + + aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); + + if ( aRes != aFunc ) + printf( "\nFinal verification FAILED!\n"); + else + printf( "\nFinal verification okay!\n"); + + Cudd_RecursiveDeref( DdNew, aRes ); + + // delocate + Extra_Dissolve( &g_Func ); + } + printf( "Final verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); + /////////////////////////////////////////////////////////////////// +*/ + + + Cudd_RecursiveDeref( DdNew, aFunc ); + + // release the names + for ( i = 0; i < nNames; i++ ) + free( pNames[i] ); + + + + ///////////////////////////////////////////////////////////////////// + // check for remaining references in the package + RetValue = Cudd_CheckZeroRef( DdNew ); + printf( "\nThe number of referenced nodes in the new manager = %d\n", RetValue ); + Cudd_Quit( DdNew ); + +//fprintf( pTable, "\n" ); +//fclose( pTable ); + +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// SINGLE OUTPUT FUNCTION /// +//////////////////////////////////////////////////////////////////////// + +// the bit count for the first 256 integer numbers +static unsigned char BitCount8[256] = { + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 +}; + +///////////////////////////////////////////////////////////// +static int s_SuppSize[MAXOUTPUTS]; +int CompareSupports( int *ptrX, int *ptrY ) +{ + return ( s_SuppSize[*ptrY] - s_SuppSize[*ptrX] ); +} +///////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////// +static int s_MintOnes[MAXOUTPUTS]; +int CompareMinterms( int *ptrX, int *ptrY ) +{ + return ( s_MintOnes[*ptrY] - s_MintOnes[*ptrX] ); +} +///////////////////////////////////////////////////////////// + +int GrayCode ( int BinCode ) +{ + return BinCode ^ ( BinCode >> 1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose ) +{ + int i; + DdNode * bResult, * aResult; + DdNode * bCube, * bTemp, * bProd; + + int Order[MAXOUTPUTS]; +// int OrderMint[MAXOUTPUTS]; + + // sort the output according to their support size + for ( i = 0; i < nOuts; i++ ) + { + s_SuppSize[i] = Cudd_SupportSize( dd, pbOuts[i] ); +// s_MintOnes[i] = BitCount8[i]; + Order[i] = i; +// OrderMint[i] = i; + } + + // order the outputs + qsort( (void*)Order, nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareSupports ); + // order the outputs +// qsort( (void*)OrderMint, nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareMinterms ); + + + bResult = b0; Cudd_Ref( bResult ); + for ( i = 0; i < nOuts; i++ ) + { +// bCube = Cudd_bddBitsToCube( dd, OrderMint[i], nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); +// bProd = Cudd_bddAnd( dd, bCube, pbOuts[Order[nOuts-1-i]] ); Cudd_Ref( bProd ); + bCube = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc, 1 ); Cudd_Ref( bCube ); + bProd = Cudd_bddAnd( dd, bCube, pbOuts[Order[i]] ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bCube ); + + bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + + // convert to the ADD +if ( fVerbose ) +printf( "Single BDD size = %6d nodes\n", Cudd_DagSize(bResult) ); + aResult = Cudd_BddToAdd( dd, bResult ); Cudd_Ref( aResult ); + Cudd_RecursiveDeref( dd, bResult ); +if ( fVerbose ) +printf( "MTBDD = %6d nodes\n", Cudd_DagSize(aResult) ); + Cudd_Deref( aResult ); + return aResult; +} +/* +DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ) +{ + int i; + DdNode * bResult, * aResult; + DdNode * bCube, * bTemp, * bProd; + + bResult = b0; Cudd_Ref( bResult ); + for ( i = 0; i < nOuts; i++ ) + { +// bCube = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); + bCube = Extra_bddBitsToCube( dd, nOuts-1-i, nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); + bProd = Cudd_bddAnd( dd, bCube, pbOuts[i] ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bCube ); + + bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + + // conver to the ADD + aResult = Cudd_BddToAdd( dd, bResult ); Cudd_Ref( aResult ); + Cudd_RecursiveDeref( dd, bResult ); + + Cudd_Deref( aResult ); + return aResult; +} +*/ + + +//////////////////////////////////////////////////////////////////////// +/// INPUT REMAPPING /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ) +// returns the ADD of the remapped function +{ + static int Permute[MAXINPUTS]; + static DdNode * pRemapped[MAXOUTPUTS]; + + DdNode * bSupp, * bTemp; + int i, Counter; + int nSuppPrev = -1; + DdNode * bFunc; + DdNode * aFunc; + + Cudd_AutodynDisable(dd); + + // perform the remapping + for ( i = 0; i < nOuts; i++ ) + { + // get support + bSupp = Cudd_Support( dd, pOutputs[i] ); Cudd_Ref( bSupp ); + + // create the variable map + Counter = 0; + for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) + Permute[bTemp->index] = Counter++; + + // transfer the BDD and remap it + pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute ); Cudd_Ref( pRemapped[i] ); + + // remove support + Cudd_RecursiveDeref( dd, bSupp ); + } + + // perform the encoding + bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( bFunc ); + + // convert to ADD + aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc ); + Cudd_RecursiveDeref( dd, bFunc ); + + // deref the intermediate results + for ( i = 0; i < nOuts; i++ ) + Cudd_RecursiveDeref( dd, pRemapped[i] ); + + Cudd_Deref( aFunc ); + return aFunc; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew ) +// returns the ADD of the remapped function +{ + static int Permute[MAXINPUTS]; + static DdNode * pRemapped[MAXOUTPUTS]; + + static DdNode * pbVarsEnc[MAXINPUTS]; + int nVarsEnc; + + DdManager * ddnew; + + DdNode * bSupp, * bTemp; + int i, v, Counter; + int nSuppPrev = -1; + DdNode * bFunc; + + // these are in the new manager + DdNode * bFuncNew; + DdNode * aFuncNew; + + int nVarsMax = 0; + + // perform the remapping and write the DDs into the new manager + for ( i = 0; i < nOuts; i++ ) + { + // get support + bSupp = Cudd_Support( dd, pOutputs[i] ); Cudd_Ref( bSupp ); + + // create the variable map + // to remap the DD into the upper part of the manager + Counter = 0; + for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) + Permute[bTemp->index] = dd->invperm[Counter++]; + + // transfer the BDD and remap it + pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute ); Cudd_Ref( pRemapped[i] ); + + // remove support + Cudd_RecursiveDeref( dd, bSupp ); + + + // determine the largest support size + if ( nVarsMax < Counter ) + nVarsMax = Counter; + } + + // select the encoding variables to follow immediately after the original variables + nVarsEnc = Extra_Base2Log(nOuts); +/* + for ( v = 0; v < nVarsEnc; v++ ) + if ( nVarsMax + v < dd->size ) + pbVarsEnc[v] = dd->var[ dd->invperm[nVarsMax+v] ]; + else + pbVarsEnc[v] = Cudd_bddNewVar( dd ); +*/ + // create the new variables on top of the manager + for ( v = 0; v < nVarsEnc; v++ ) + pbVarsEnc[v] = Cudd_bddNewVarAtLevel( dd, v ); + +//fprintf( pTable, "%d ", Cudd_SharingSize( pRemapped, nOuts ) ); +//fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pRemapped, nOuts) ); + + + // perform the encoding + bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( bFunc ); + + + // find the cross-manager permutation + // the variable from the level v in the old manager + // should become a variable number v in the new manager + for ( v = 0; v < nVarsMax + nVarsEnc; v++ ) + Permute[dd->invperm[v]] = v; + + + /////////////////////////////////////////////////////////////////////////////// + // start the new manager + ddnew = Cudd_Init( nVarsMax + nVarsEnc, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); +// Cudd_AutodynDisable(ddnew); + Cudd_AutodynEnable(dd, CUDD_REORDER_SYMM_SIFT); + + // transfer it to the new manager + bFuncNew = Cudd_bddTransferPermute( dd, ddnew, bFunc, Permute ); Cudd_Ref( bFuncNew ); + /////////////////////////////////////////////////////////////////////////////// + + + // deref the intermediate results in the old manager + Cudd_RecursiveDeref( dd, bFunc ); + for ( i = 0; i < nOuts; i++ ) + Cudd_RecursiveDeref( dd, pRemapped[i] ); + + + /////////////////////////////////////////////////////////////////////////////// + // convert to ADD in the new manager + aFuncNew = Cudd_BddToAdd( ddnew, bFuncNew ); Cudd_Ref( aFuncNew ); + Cudd_RecursiveDeref( ddnew, bFuncNew ); + + // return the manager + *DdNew = ddnew; + /////////////////////////////////////////////////////////////////////////////// + + Cudd_Deref( aFuncNew ); + return aFuncNew; +} + +//////////////////////////////////////////////////////////////////////// +/// BLIF WRITING FUNCTIONS /// +//////////////////////////////////////////////////////////////////////// + +void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName ) +{ + int i; + FILE * pFile; + + // start the file + pFile = fopen( FileName, "w" ); + fprintf( pFile, ".model %s\n", FileName ); + + fprintf( pFile, ".inputs" ); + for ( i = 0; i < nNames; i++ ) + fprintf( pFile, " %s", pNames[i] ); + fprintf( pFile, "\n" ); + fprintf( pFile, ".outputs F" ); + fprintf( pFile, "\n" ); + + // write the DD into the file + WriteDDintoBLIFfile( pFile, aFunc, "F", "", pNames ); + + fprintf( pFile, ".end\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ) +// writes the main part of the BLIF file +// Func is a BDD or a 0-1 ADD to be written +// OutputName is the name of the output +// Prefix is attached to each intermendiate signal to make it unique +// InputNames are the names of the input signals +// (some part of the code is borrowed from Cudd_DumpDot()) +{ + int i; + st_table * visited; + st_generator * gen = NULL; + long refAddr, diff, mask; + DdNode * Node, * Else, * ElseR, * Then; + + /* Initialize symbol table for visited nodes. */ + visited = st_init_table( st_ptrcmp, st_ptrhash ); + + /* Collect all the nodes of this DD in the symbol table. */ + cuddCollectNodes( Cudd_Regular(Func), visited ); + + /* Find how many most significant hex digits are identical + ** in the addresses of all the nodes. Build a mask based + ** on this knowledge, so that digits that carry no information + ** will not be printed. This is done in two steps. + ** 1. We scan the symbol table to find the bits that differ + ** in at least 2 addresses. + ** 2. We choose one of the possible masks. There are 8 possible + ** masks for 32-bit integer, and 16 possible masks for 64-bit + ** integers. + */ + + /* Find the bits that are different. */ + refAddr = ( long )Cudd_Regular(Func); + diff = 0; + gen = st_init_gen( visited ); + while ( st_gen( gen, ( char ** ) &Node, NULL ) ) + { + diff |= refAddr ^ ( long ) Node; + } + st_free_gen( gen ); + gen = NULL; + + /* Choose the mask. */ + for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 ) + { + mask = ( 1 << i ) - 1; + if ( diff <= mask ) + break; + } + + + // write the buffer for the output + fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(Func) ) / sizeof(DdNode), OutputName ); + fprintf( pFile, "%s 1\n", (Cudd_IsComplement(Func))? "0": "1" ); + + + gen = st_init_gen( visited ); + while ( st_gen( gen, ( char ** ) &Node, NULL ) ) + { + if ( Node->index == CUDD_MAXINDEX ) + { + // write the terminal node + fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); + fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" ); + continue; + } + + Else = cuddE(Node); + ElseR = Cudd_Regular(Else); + Then = cuddT(Node); + + assert( InputNames[Node->index] ); + if ( Else == ElseR ) + { // no inverter + fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index], + Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), + Prefix, ( mask & (long)Then ) / sizeof(DdNode), + Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); + fprintf( pFile, "01- 1\n" ); + fprintf( pFile, "1-1 1\n" ); + } + else + { // inverter + int * pSlot; + fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index], + Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), + Prefix, ( mask & (long)Then ) / sizeof(DdNode), + Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); + fprintf( pFile, "01- 1\n" ); + fprintf( pFile, "1-1 1\n" ); + + // if the inverter is written, skip + if ( !st_find( visited, (char *)ElseR, (char ***)&pSlot ) ) + assert( 0 ); + if ( *pSlot ) + continue; + *pSlot = 1; + + fprintf( pFile, ".names %s%lx %s%lx_i\n", + Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), + Prefix, ( mask & (long)ElseR ) / sizeof(DdNode) ); + fprintf( pFile, "0 1\n" ); + } + } + st_free_gen( gen ); + gen = NULL; + st_free_table( visited ); +} + + + + +static DdManager * s_ddmin; + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ) +// writes the main part of the BLIF file +// Func is a BDD or a 0-1 ADD to be written +// OutputName is the name of the output +// Prefix is attached to each intermendiate signal to make it unique +// InputNames are the names of the input signals +// (some part of the code is borrowed from Cudd_DumpDot()) +{ + int i; + st_table * visited; + st_generator * gen = NULL; + long refAddr, diff, mask; + DdNode * Node, * Else, * ElseR, * Then; + + + /////////////////////////////////////////////////////////////// + DdNode * bFmin; + int clk1; + + if ( s_ddmin == NULL ) + s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); + + clk1 = clock(); + bFmin = Cudd_bddTransfer( dd, s_ddmin, Func ); Cudd_Ref( bFmin ); + + // reorder + printf( "Nodes before = %d. ", Cudd_DagSize(bFmin) ); + Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); +// Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT_CONV,1); + printf( "Nodes after = %d. \n", Cudd_DagSize(bFmin) ); + /////////////////////////////////////////////////////////////// + + + + /* Initialize symbol table for visited nodes. */ + visited = st_init_table( st_ptrcmp, st_ptrhash ); + + /* Collect all the nodes of this DD in the symbol table. */ + cuddCollectNodes( Cudd_Regular(bFmin), visited ); + + /* Find how many most significant hex digits are identical + ** in the addresses of all the nodes. Build a mask based + ** on this knowledge, so that digits that carry no information + ** will not be printed. This is done in two steps. + ** 1. We scan the symbol table to find the bits that differ + ** in at least 2 addresses. + ** 2. We choose one of the possible masks. There are 8 possible + ** masks for 32-bit integer, and 16 possible masks for 64-bit + ** integers. + */ + + /* Find the bits that are different. */ + refAddr = ( long )Cudd_Regular(bFmin); + diff = 0; + gen = st_init_gen( visited ); + while ( st_gen( gen, ( char ** ) &Node, NULL ) ) + { + diff |= refAddr ^ ( long ) Node; + } + st_free_gen( gen ); + gen = NULL; + + /* Choose the mask. */ + for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 ) + { + mask = ( 1 << i ) - 1; + if ( diff <= mask ) + break; + } + + + // write the buffer for the output + fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(bFmin) ) / sizeof(DdNode), OutputName ); + fprintf( pFile, "%s 1\n", (Cudd_IsComplement(bFmin))? "0": "1" ); + + + gen = st_init_gen( visited ); + while ( st_gen( gen, ( char ** ) &Node, NULL ) ) + { + if ( Node->index == CUDD_MAXINDEX ) + { + // write the terminal node + fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); + fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" ); + continue; + } + + Else = cuddE(Node); + ElseR = Cudd_Regular(Else); + Then = cuddT(Node); + + assert( InputNames[Node->index] ); + if ( Else == ElseR ) + { // no inverter + fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index], + Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), + Prefix, ( mask & (long)Then ) / sizeof(DdNode), + Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); + fprintf( pFile, "01- 1\n" ); + fprintf( pFile, "1-1 1\n" ); + } + else + { // inverter + fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index], + Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), + Prefix, ( mask & (long)Then ) / sizeof(DdNode), + Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); + fprintf( pFile, "01- 1\n" ); + fprintf( pFile, "1-1 1\n" ); + + fprintf( pFile, ".names %s%lx %s%lx_i\n", + Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), + Prefix, ( mask & (long)ElseR ) / sizeof(DdNode) ); + fprintf( pFile, "0 1\n" ); + } + } + st_free_gen( gen ); + gen = NULL; + st_free_table( visited ); + + + ////////////////////////////////////////////////// + Cudd_RecursiveDeref( s_ddmin, bFmin ); + ////////////////////////////////////////////////// +} + + + + +//////////////////////////////////////////////////////////////////////// +/// TRANSFER WITH MAPPING /// +//////////////////////////////////////////////////////////////////////// +static DdNode * cuddBddTransferPermuteRecur +ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, st_table * table, int * Permute )); + +static DdNode * cuddBddTransferPermute +ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute)); + +/**Function******************************************************************** + + Synopsis [Convert a BDD from a manager to another one.] + + Description [Convert a BDD from a manager to another one. The orders of the + variables in the two managers may be different. Returns a + pointer to the BDD in the destination manager if successful; NULL + otherwise. The i-th entry in the array Permute tells what is the index + of the i-th variable from the old manager in the new manager.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_bddTransferPermute( DdManager * ddSource, + DdManager * ddDestination, DdNode * f, int * Permute ) +{ + DdNode *res; + do + { + ddDestination->reordered = 0; + res = cuddBddTransferPermute( ddSource, ddDestination, f, Permute ); + } + while ( ddDestination->reordered == 1 ); + return ( res ); + +} /* end of Cudd_bddTransferPermute */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Convert a BDD from a manager to another one.] + + Description [Convert a BDD from a manager to another one. Returns a + pointer to the BDD in the destination manager if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddTransferPermute] + +******************************************************************************/ +DdNode * +cuddBddTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ) +{ + DdNode *res; + st_table *table = NULL; + st_generator *gen = NULL; + DdNode *key, *value; + + table = st_init_table( st_ptrcmp, st_ptrhash ); + if ( table == NULL ) + goto failure; + res = cuddBddTransferPermuteRecur( ddS, ddD, f, table, Permute ); + if ( res != NULL ) + cuddRef( res ); + + /* Dereference all elements in the table and dispose of the table. + ** This must be done also if res is NULL to avoid leaks in case of + ** reordering. */ + gen = st_init_gen( table ); + if ( gen == NULL ) + goto failure; + while ( st_gen( gen, ( char ** ) &key, ( char ** ) &value ) ) + { + Cudd_RecursiveDeref( ddD, value ); + } + st_free_gen( gen ); + gen = NULL; + st_free_table( table ); + table = NULL; + + if ( res != NULL ) + cuddDeref( res ); + return ( res ); + + failure: + if ( table != NULL ) + st_free_table( table ); + if ( gen != NULL ) + st_free_gen( gen ); + return ( NULL ); + +} /* end of cuddBddTransferPermute */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddTransferPermute.] + + Description [Performs the recursive step of Cudd_bddTransferPermute. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddBddTransferPermute] + +******************************************************************************/ +static DdNode * +cuddBddTransferPermuteRecur( DdManager * ddS, + DdManager * ddD, DdNode * f, st_table * table, int * Permute ) +{ + DdNode *ft, *fe, *t, *e, *var, *res; + DdNode *one, *zero; + int index; + int comple = 0; + + statLine( ddD ); + one = DD_ONE( ddD ); + comple = Cudd_IsComplement( f ); + + /* Trivial cases. */ + if ( Cudd_IsConstant( f ) ) + return ( Cudd_NotCond( one, comple ) ); + + /* Make canonical to increase the utilization of the cache. */ + f = Cudd_NotCond( f, comple ); + /* Now f is a regular pointer to a non-constant node. */ + + /* Check the cache. */ + if ( st_lookup( table, ( char * ) f, ( char ** ) &res ) ) + return ( Cudd_NotCond( res, comple ) ); + + /* Recursive step. */ + index = Permute[f->index]; + ft = cuddT( f ); + fe = cuddE( f ); + + t = cuddBddTransferPermuteRecur( ddS, ddD, ft, table, Permute ); + if ( t == NULL ) + { + return ( NULL ); + } + cuddRef( t ); + + e = cuddBddTransferPermuteRecur( ddS, ddD, fe, table, Permute ); + if ( e == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + return ( NULL ); + } + cuddRef( e ); + + zero = Cudd_Not( one ); + var = cuddUniqueInter( ddD, index, one, zero ); + if ( var == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + return ( NULL ); + } + res = cuddBddIteRecur( ddD, var, t, e ); + if ( res == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + return ( NULL ); + } + cuddRef( res ); + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + + if ( st_add_direct( table, ( char * ) f, ( char * ) res ) == + ST_OUT_OF_MEM ) + { + Cudd_RecursiveDeref( ddD, res ); + return ( NULL ); + } + return ( Cudd_NotCond( res, comple ) ); + +} /* end of cuddBddTransferPermuteRecur */ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + + diff --git a/abc70930/src/bdd/cas/casDec.c b/abc70930/src/bdd/cas/casDec.c new file mode 100644 index 00000000..a1eb5f36 --- /dev/null +++ b/abc70930/src/bdd/cas/casDec.c @@ -0,0 +1,508 @@ +/**CFile**************************************************************** + + FileName [casDec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] + + Synopsis [BDD-based decomposition with encoding.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Spring 2002.] + + Revision [$Id: casDec.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include + +#include "extra.h" +#include "cas.h" + +//////////////////////////////////////////////////////////////////////// +/// type definitions /// +//////////////////////////////////////////////////////////////////////// + +typedef struct +{ + int nIns; // the number of LUT variables + int nInsP; // the number of inputs coming from the previous LUT + int nCols; // the number of columns in this LUT + int nMulti; // the column multiplicity, [log2(nCols)] + int nSimple; // the number of outputs implemented as direct connections to inputs of the previous block + int Level; // the starting level in the ADD in this LUT + +// DdNode ** pbVarsIn[32]; // the BDDs of the elementary input variables +// DdNode ** pbVarsOut[32]; // the BDDs of the elementary output variables + +// char * pNamesIn[32]; // the names of input variables +// char * pNamesOut[32]; // the names of output variables + + DdNode ** pbCols; // the array of columns represented by BDDs + DdNode ** pbCodes; // the array of codes (in terms of pbVarsOut) + DdNode ** paNodes; // the array of starting ADD nodes on the next level (also referenced) + + DdNode * bRelation; // the relation after encoding + + // the relation depends on the three groups of variables: + // (1) variables on top represent the outputs of the previous cascade + // (2) variables in the middle represent the primary inputs + // (3) variables below (CVars) represent the codes + // + // the replacement is done after computing the relation +} LUT; + + +//////////////////////////////////////////////////////////////////////// +/// static functions /// +//////////////////////////////////////////////////////////////////////// + +// the LUT-2-BLIF writing function +void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName ); + +// the function to write a DD (BDD or ADD) as a network of MUXES +extern void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); +extern void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); + +//////////////////////////////////////////////////////////////////////// +/// static varibles /// +//////////////////////////////////////////////////////////////////////// + +static int s_LutSize = 15; +static int s_nFuncVars; + +long s_EncodingTime; + +long s_EncSearchTime; +long s_EncComputeTime; + +//////////////////////////////////// +// temporary output variables +//FILE * pTable; +//long s_ReadingTime; +//long s_RemappingTime; +//////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// debugging macros /// +//////////////////////////////////////////////////////////////////////// + +#define PRB(f) printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" ) +#define PRK(f,n) Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" ) +#define PRK2(f,g,n) Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" ) + + +//////////////////////////////////////////////////////////////////////// +/// EXTERNAL FUNCTIONS /// +//////////////////////////////////////////////////////////////////////// + +int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose ) +// aFunc is a 0-1 ADD for the given function +// pNames (nNames) are the input variable names +// FileName is the name of the output file for the LUT network +// dynamic variable reordering should be disabled when this function is running +{ + static LUT * pLuts[MAXINPUTS]; // the LUT cascade + static int Profile[MAXINPUTS]; // the profile filled in with the info about the BDD width + static int Permute[MAXINPUTS]; // the array to store a temporary permutation of variables + + LUT * p; // the current LUT + int i, v; + + DdNode * bCVars[32]; // these are variables for the codes + + int nVarsRem; // the number of remaining variables + int PrevMulti; // column multiplicity on the previous level + int fLastLut; // flag to signal the last LUT + int nLuts; + int nLutsTotal = 0; + int nLutOutputs = 0; + int nLutOutputsOrig = 0; + + long clk1; + + s_LutSize = nLutSize; + + s_nFuncVars = nNames; + + // get the profile + clk1 = clock(); + Extra_ProfileWidth( dd, aFunc, Profile, -1 ); + + +// for ( v = 0; v < nNames; v++ ) +// printf( "Level = %2d, Width = %2d\n", v+1, Profile[v] ); + + +//printf( "\n" ); + + // mark-up the LUTs + // assuming that the manager has exactly nNames vars (new vars have not been introduced yet) + nVarsRem = nNames; // the number of remaining variables + PrevMulti = 0; // column multiplicity on the previous level + fLastLut = 0; + nLuts = 0; + do + { + p = (LUT*) malloc( sizeof(LUT) ); + memset( p, 0, sizeof(LUT) ); + + if ( nVarsRem + PrevMulti <= s_LutSize ) // this is the last LUT + { + p->nIns = nVarsRem + PrevMulti; + p->nInsP = PrevMulti; + p->nCols = 2; + p->nMulti = 1; + p->Level = nNames-nVarsRem; + + nVarsRem = 0; + PrevMulti = 1; + + fLastLut = 1; + } + else // this is not the last LUT + { + p->nIns = s_LutSize; + p->nInsP = PrevMulti; + p->nCols = Profile[nNames-(nVarsRem-(s_LutSize-PrevMulti))]; + p->nMulti = Extra_Base2Log(p->nCols); + p->Level = nNames-nVarsRem; + + nVarsRem = nVarsRem-(s_LutSize-PrevMulti); + PrevMulti = p->nMulti; + } + + if ( p->nMulti >= s_LutSize ) + { + printf( "The LUT size is too small\n" ); + return 0; + } + + nLutOutputsOrig += p->nMulti; + + +//if ( fVerbose ) +//printf( "Stage %2d: In = %3d, InP = %3d, Cols = %5d, Multi = %2d, Level = %2d\n", +// nLuts+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->Level ); + + + // there should be as many columns, codes, and nodes, as there are columns on this level + p->pbCols = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); + p->pbCodes = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); + p->paNodes = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); + + pLuts[nLuts] = p; + nLuts++; + } + while ( !fLastLut ); + + +//if ( fVerbose ) +//printf( "The number of cascades = %d\n", nLuts ); + + +//fprintf( pTable, "%d ", nLuts ); + + + // add the new variables at the bottom + for ( i = 0; i < s_LutSize; i++ ) + bCVars[i] = Cudd_bddNewVar(dd); + + // for each LUT - assign the LUT and encode the columns + s_EncodingTime = 0; + for ( i = 0; i < nLuts; i++ ) + { + int RetValue; + DdNode * bVars[32]; + int nVars; + DdNode * bVarsInCube; + DdNode * bVarsCCube; + DdNode * bVarsCube; + int CutLevel; + + p = pLuts[i]; + + // compute the columns of this LUT starting from the given set of nodes with the given codes + // (these codes have been remapped to depend on the topmost variables in the manager) + // for the first LUT, start with the constant 1 BDD + CutLevel = p->Level + p->nIns - p->nInsP; + if ( i == 0 ) + RetValue = Extra_bddNodePathsUnderCutArray( + dd, &aFunc, &(b1), 1, + p->paNodes, p->pbCols, CutLevel ); + else + RetValue = Extra_bddNodePathsUnderCutArray( + dd, pLuts[i-1]->paNodes, pLuts[i-1]->pbCodes, pLuts[i-1]->nCols, + p->paNodes, p->pbCols, CutLevel ); + assert( RetValue == p->nCols ); + // at this point, we have filled out p->paNodes[] and p->pbCols[] of this LUT + // pLuts[i-1]->paNodes depended on normal vars + // pLuts[i-1]->pbCodes depended on the topmost variables + // the resulting p->paNodes depend on normal ADD nodes + // the resulting p->pbCols depend on normal vars and topmost variables in the manager + + // perform the encoding + + // create the cube of these variables + // collect the topmost variables of the manager + nVars = p->nInsP; + for ( v = 0; v < nVars; v++ ) + bVars[v] = dd->vars[ dd->invperm[v] ]; + bVarsCCube = Extra_bddBitsToCube( dd, (1<nIns - p->nInsP; + for ( v = 0; v < nVars; v++ ) + bVars[v] = dd->vars[ dd->invperm[p->Level+v] ]; + bVarsInCube = Extra_bddBitsToCube( dd, (1<nMulti == 1 ); + assert( p->nCols == 2 ); + assert( Cudd_IsConstant( p->paNodes[0] ) ); + assert( Cudd_IsConstant( p->paNodes[1] ) ); + + bVar = ( p->paNodes[0] == a1 )? bCVars[0]: Cudd_Not( bCVars[0] ); + p->bRelation = Cudd_bddIte( dd, bVar, p->pbCols[0], p->pbCols[1] ); Cudd_Ref( p->bRelation ); + } + else + { + long clk2 = clock(); +// p->bRelation = PerformTheEncoding( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple ); Cudd_Ref( p->bRelation ); + p->bRelation = Extra_bddEncodingNonStrict( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple ); Cudd_Ref( p->bRelation ); + s_EncodingTime += clock() - clk2; + } + + // update the number of LUT outputs + nLutOutputs += (p->nMulti - p->nSimple); + nLutsTotal += p->nMulti; + +//if ( fVerbose ) +//printf( "Stage %2d: Simple = %d\n", i+1, p->nSimple ); + +if ( fVerbose ) +printf( "Stage %3d: In = %3d InP = %3d Cols = %5d Multi = %2d Simple = %2d Level = %3d\n", + i+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->nSimple, p->Level ); + + // get the codes from the relation (these are not necessarily cubes) + { + int c; + for ( c = 0; c < p->nCols; c++ ) + { + p->pbCodes[c] = Cudd_bddAndAbstract( dd, p->bRelation, p->pbCols[c], bVarsCube ); Cudd_Ref( p->pbCodes[c] ); + } + } + + Cudd_RecursiveDeref( dd, bVarsCube ); + + // remap the codes to depend on the topmost varibles of the manager + // useful as a preparation for the next step + { + DdNode ** pbTemp; + int k, v; + + pbTemp = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); + + // create the identical permutation + for ( v = 0; v < dd->size; v++ ) + Permute[v] = v; + + // use the topmost variables of the manager + // to represent the previous level codes + for ( v = 0; v < p->nMulti; v++ ) + Permute[bCVars[v]->index] = dd->invperm[v]; + + Extra_bddPermuteArray( dd, p->pbCodes, pbTemp, p->nCols, Permute ); + // the array pbTemp comes already referenced + + // deref the old codes and assign the new ones + for ( k = 0; k < p->nCols; k++ ) + { + Cudd_RecursiveDeref( dd, p->pbCodes[k] ); + p->pbCodes[k] = pbTemp[k]; + } + free( pbTemp ); + } + } + if ( fVerbose ) + printf( "LUTs: Total = %5d. Final = %5d. Simple = %5d. (%6.2f %%) ", + nLutsTotal, nLutOutputs, nLutsTotal-nLutOutputs, 100.0*(nLutsTotal-nLutOutputs)/nLutsTotal ); + if ( fVerbose ) + printf( "Memory = %6.2f Mb\n", 1.0*nLutOutputs*(1<nCols; v++ ) + { + Cudd_RecursiveDeref( dd, p->pbCols[v] ); + Cudd_RecursiveDeref( dd, p->pbCodes[v] ); + Cudd_RecursiveDeref( dd, p->paNodes[v] ); + } + Cudd_RecursiveDeref( dd, p->bRelation ); + + free( p->pbCols ); + free( p->pbCodes ); + free( p->paNodes ); + free( p ); + } + + return 1; +} + +void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName ) +{ + int i, v, o; + static char * pNamesLocalIn[MAXINPUTS]; + static char * pNamesLocalOut[MAXINPUTS]; + static char Buffer[100]; + DdNode * bCube, * bCof, * bFunc; + LUT * p; + + // go through all the LUTs + for ( i = 0; i < nLuts; i++ ) + { + // get the pointer to the LUT + p = pLuts[i]; + + if ( i == nLuts -1 ) + { + assert( p->nMulti == 1 ); + } + + + fprintf( pFile, "#----------------- LUT #%d ----------------------\n", i ); + + + // fill in the names for the current LUT + + // write the outputs of the previous LUT + if ( i != 0 ) + for ( v = 0; v < p->nInsP; v++ ) + { + sprintf( Buffer, "LUT%02d_%02d", i-1, v ); + pNamesLocalIn[dd->invperm[v]] = Extra_UtilStrsav( Buffer ); + } + // write the primary inputs of the current LUT + for ( v = 0; v < p->nIns - p->nInsP; v++ ) + pNamesLocalIn[dd->invperm[p->Level+v]] = Extra_UtilStrsav( pNames[dd->invperm[p->Level+v]] ); + // write the outputs of the current LUT + for ( v = 0; v < p->nMulti; v++ ) + { + sprintf( Buffer, "LUT%02d_%02d", i, v ); + if ( i != nLuts - 1 ) + pNamesLocalOut[v] = Extra_UtilStrsav( Buffer ); + else + pNamesLocalOut[v] = Extra_UtilStrsav( "F" ); + } + + + // write LUT outputs + + // get the prefix + sprintf( Buffer, "L%02d_", i ); + + // get the cube of encoding variables + bCube = Extra_bddBitsToCube( dd, (1<nMulti)-1, p->nMulti, bCVars, 1 ); Cudd_Ref( bCube ); + + // write each output of the LUT + for ( o = 0; o < p->nMulti; o++ ) + { + // get the cofactor of this output + bCof = Cudd_Cofactor( dd, p->bRelation, bCVars[o] ); Cudd_Ref( bCof ); + // quantify the remaining variables to get the function + bFunc = Cudd_bddExistAbstract( dd, bCof, bCube ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bCof ); + + // write BLIF + sprintf( Buffer, "L%02d_%02d_", i, o ); + +// WriteDDintoBLIFfileReorder( dd, pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn ); + // does not work well; the advantage is marginal (30%), the run time is huge... + + WriteDDintoBLIFfile( pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn ); + Cudd_RecursiveDeref( dd, bFunc ); + } + Cudd_RecursiveDeref( dd, bCube ); + + // clean up the previous local names + for ( v = 0; v < dd->size; v++ ) + { + if ( pNamesLocalIn[v] ) + free( pNamesLocalIn[v] ); + pNamesLocalIn[v] = NULL; + } + for ( v = 0; v < p->nMulti; v++ ) + free( pNamesLocalOut[v] ); + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + + + diff --git a/abc70930/src/bdd/cas/module.make b/abc70930/src/bdd/cas/module.make new file mode 100644 index 00000000..7830e47f --- /dev/null +++ b/abc70930/src/bdd/cas/module.make @@ -0,0 +1,3 @@ +SRC += src/bdd/cas/casCore.c \ + src/bdd/cas/casDec.c + diff --git a/abc70930/src/bdd/cudd/cuBdd.make b/abc70930/src/bdd/cudd/cuBdd.make new file mode 100644 index 00000000..b16a27b3 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuBdd.make @@ -0,0 +1,41 @@ +CSRC_cu += cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \ + cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \ + cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c \ + cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \ + cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c cuddExact.c \ + cuddExport.c cuddGenCof.c cuddGenetic.c \ + cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \ + cuddLCache.c cuddLevelQ.c \ + cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \ + cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \ + cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \ + cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \ + cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c cuddZddPort.c \ + cuddZddReord.c cuddZddSetop.c cuddZddSymm.c cuddZddUtil.c +HEADERS_cu += cudd.h cuddInt.h +MISC += testcudd.c r7x8.1.mat doc/cudd.ps doc/cuddAllAbs.html doc/cuddAllDet.html \ + doc/cuddExtAbs.html doc/cuddExtDet.html doc/cuddIntro.css \ + doc/cuddIntro.html doc/footnode.html doc/img1.gif doc/img2.gif \ + doc/img3.gif doc/img4.gif doc/img5.gif doc/index.html \ + doc/node1.html doc/node2.html doc/node3.html doc/node4.html \ + doc/node5.html doc/node6.html doc/node7.html doc/node8.html \ + doc/icons/change_begin.gif \ + doc/icons/change_delete.gif \ + doc/icons/change_end.gif \ + doc/icons/contents_motif.gif \ + doc/icons/cross_ref_motif.gif \ + doc/icons/foot_motif.gif \ + doc/icons/image.gif \ + doc/icons/index_motif.gif \ + doc/icons/next_group_motif.gif \ + doc/icons/next_group_motif_gr.gif \ + doc/icons/next_motif.gif \ + doc/icons/next_motif_gr.gif \ + doc/icons/previous_group_motif.gif \ + doc/icons/previous_group_motif_gr.gif \ + doc/icons/previous_motif.gif \ + doc/icons/previous_motif_gr.gif \ + doc/icons/up_motif.gif \ + doc/icons/up_motif_gr.gif + +DEPENDENCYFILES = $(CSRC_cu) diff --git a/abc70930/src/bdd/cudd/cudd.h b/abc70930/src/bdd/cudd/cudd.h new file mode 100644 index 00000000..a31fcdae --- /dev/null +++ b/abc70930/src/bdd/cudd/cudd.h @@ -0,0 +1,959 @@ +/**CHeaderFile***************************************************************** + + FileName [cudd.h] + + PackageName [cudd] + + Synopsis [The University of Colorado decision diagram package.] + + Description [External functions and data strucures of the CUDD package. +

    +
  • To turn on the gathering of statistics, define DD_STATS. +
  • To link with mis, define DD_MIS. +
+ Modified by Abelardo Pardo to interface it to VIS. + ] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + + Revision [$Id: cudd.h,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $] + +******************************************************************************/ + +#ifndef _CUDD +#define _CUDD + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#include "mtr.h" +#include "epd.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define CUDD_VERSION "2.3.1" + +#ifndef SIZEOF_VOID_P +#define SIZEOF_VOID_P 4 +#endif +#ifndef SIZEOF_INT +#define SIZEOF_INT 4 +#endif +#ifndef SIZEOF_LONG +#define SIZEOF_LONG 4 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#define CUDD_VALUE_TYPE double +#define CUDD_OUT_OF_MEM -1 +/* The sizes of the subtables and the cache must be powers of two. */ +#define CUDD_UNIQUE_SLOTS 256 /* initial size of subtables */ +#define CUDD_CACHE_SLOTS 262144 /* default size of the cache */ + +/* Constants for residue functions. */ +#define CUDD_RESIDUE_DEFAULT 0 +#define CUDD_RESIDUE_MSB 1 +#define CUDD_RESIDUE_TC 2 + +/* CUDD_MAXINDEX is defined in such a way that on 32-bit and 64-bit +** machines one can cast an index to (int) without generating a negative +** number. +*/ +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +#define CUDD_MAXINDEX (((DdHalfWord) ~0) >> 1) +#else +#define CUDD_MAXINDEX ((DdHalfWord) ~0) +#endif + +/* CUDD_CONST_INDEX is the index of constant nodes. Currently this +** is a synonim for CUDD_MAXINDEX. */ +#define CUDD_CONST_INDEX CUDD_MAXINDEX + +/* These constants define the digits used in the representation of +** arbitrary precision integers. The two configurations tested use 8 +** and 16 bits for each digit. The typedefs should be in agreement +** with these definitions. +*/ +#define DD_APA_BITS 16 +#define DD_APA_BASE (1 << DD_APA_BITS) +#define DD_APA_MASK (DD_APA_BASE - 1) +#define DD_APA_HEXPRINT "%04x" + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/**Enum************************************************************************ + + Synopsis [Type of reordering algorithm.] + + Description [Type of reordering algorithm.] + +******************************************************************************/ +typedef enum { + CUDD_REORDER_SAME, + CUDD_REORDER_NONE, + CUDD_REORDER_RANDOM, + CUDD_REORDER_RANDOM_PIVOT, + CUDD_REORDER_SIFT, + CUDD_REORDER_SIFT_CONVERGE, + CUDD_REORDER_SYMM_SIFT, + CUDD_REORDER_SYMM_SIFT_CONV, + CUDD_REORDER_WINDOW2, + CUDD_REORDER_WINDOW3, + CUDD_REORDER_WINDOW4, + CUDD_REORDER_WINDOW2_CONV, + CUDD_REORDER_WINDOW3_CONV, + CUDD_REORDER_WINDOW4_CONV, + CUDD_REORDER_GROUP_SIFT, + CUDD_REORDER_GROUP_SIFT_CONV, + CUDD_REORDER_ANNEALING, + CUDD_REORDER_GENETIC, + CUDD_REORDER_LINEAR, + CUDD_REORDER_LINEAR_CONVERGE, + CUDD_REORDER_LAZY_SIFT, + CUDD_REORDER_EXACT +} Cudd_ReorderingType; + + +/**Enum************************************************************************ + + Synopsis [Type of aggregation methods.] + + Description [Type of aggregation methods.] + +******************************************************************************/ +typedef enum { + CUDD_NO_CHECK, + CUDD_GROUP_CHECK, + CUDD_GROUP_CHECK2, + CUDD_GROUP_CHECK3, + CUDD_GROUP_CHECK4, + CUDD_GROUP_CHECK5, + CUDD_GROUP_CHECK6, + CUDD_GROUP_CHECK7, + CUDD_GROUP_CHECK8, + CUDD_GROUP_CHECK9 +} Cudd_AggregationType; + + +/**Enum************************************************************************ + + Synopsis [Type of hooks.] + + Description [Type of hooks.] + +******************************************************************************/ +typedef enum { + CUDD_PRE_GC_HOOK, + CUDD_POST_GC_HOOK, + CUDD_PRE_REORDERING_HOOK, + CUDD_POST_REORDERING_HOOK +} Cudd_HookType; + + +/**Enum************************************************************************ + + Synopsis [Type of error codes.] + + Description [Type of error codes.] + +******************************************************************************/ +typedef enum { + CUDD_NO_ERROR, + CUDD_MEMORY_OUT, + CUDD_TOO_MANY_NODES, + CUDD_MAX_MEM_EXCEEDED, + CUDD_INVALID_ARG, + CUDD_INTERNAL_ERROR +} Cudd_ErrorType; + + +/**Enum************************************************************************ + + Synopsis [Group type for lazy sifting.] + + Description [Group type for lazy sifting.] + +******************************************************************************/ +typedef enum { + CUDD_LAZY_NONE, + CUDD_LAZY_SOFT_GROUP, + CUDD_LAZY_HARD_GROUP, + CUDD_LAZY_UNGROUP +} Cudd_LazyGroupType; + + +/**Enum************************************************************************ + + Synopsis [Variable type.] + + Description [Variable type. Currently used only in lazy sifting.] + +******************************************************************************/ +typedef enum { + CUDD_VAR_PRIMARY_INPUT, + CUDD_VAR_PRESENT_STATE, + CUDD_VAR_NEXT_STATE +} Cudd_VariableType; + + +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +typedef unsigned int DdHalfWord; +#else +typedef unsigned short DdHalfWord; +#endif + +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + +typedef struct DdNode DdNode; + +typedef struct DdChildren { + struct DdNode *T; + struct DdNode *E; +} DdChildren; + +/* The DdNode structure is the only one exported out of the package */ +struct DdNode { + DdHalfWord index; + DdHalfWord ref; /* reference count */ + DdNode *next; /* next pointer for unique table */ + union { + CUDD_VALUE_TYPE value; /* for constant nodes */ + DdChildren kids; /* for internal nodes */ + } type; +}; + +#ifdef __osf__ +#pragma pointer_size restore +#endif + +typedef struct DdManager DdManager; + +typedef struct DdGen DdGen; + +/* These typedefs for arbitrary precision arithmetic should agree with +** the corresponding constant definitions above. */ +typedef unsigned short int DdApaDigit; +typedef unsigned long int DdApaDoubleDigit; +typedef DdApaDigit * DdApaNumber; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**Macro*********************************************************************** + + Synopsis [Returns 1 if the node is a constant node.] + + Description [Returns 1 if the node is a constant node (rather than an + internal node). All constant nodes have the same index + (CUDD_CONST_INDEX). The pointer passed to Cudd_IsConstant may be either + regular or complemented.] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +#define Cudd_IsConstant(node) ((Cudd_Regular(node))->index == CUDD_CONST_INDEX) + + +/**Macro*********************************************************************** + + Synopsis [Complements a DD.] + + Description [Complements a DD by flipping the complement attribute of + the pointer (the least significant bit).] + + SideEffects [none] + + SeeAlso [Cudd_NotCond] + +******************************************************************************/ +#define Cudd_Not(node) ((DdNode *)((long)(node) ^ 01)) + + +/**Macro*********************************************************************** + + Synopsis [Complements a DD if a condition is true.] + + Description [Complements a DD if condition c is true; c should be + either 0 or 1, because it is used directly (for efficiency). If in + doubt on the values c may take, use "(c) ? Cudd_Not(node) : node".] + + SideEffects [none] + + SeeAlso [Cudd_Not] + +******************************************************************************/ +#define Cudd_NotCond(node,c) ((DdNode *)((long)(node) ^ (c))) + + +/**Macro*********************************************************************** + + Synopsis [Returns the regular version of a pointer.] + + Description [] + + SideEffects [none] + + SeeAlso [Cudd_Complement Cudd_IsComplement] + +******************************************************************************/ +#define Cudd_Regular(node) ((DdNode *)((unsigned long)(node) & ~01)) + + +/**Macro*********************************************************************** + + Synopsis [Returns the complemented version of a pointer.] + + Description [] + + SideEffects [none] + + SeeAlso [Cudd_Regular Cudd_IsComplement] + +******************************************************************************/ +#define Cudd_Complement(node) ((DdNode *)((unsigned long)(node) | 01)) + + +/**Macro*********************************************************************** + + Synopsis [Returns 1 if a pointer is complemented.] + + Description [] + + SideEffects [none] + + SeeAlso [Cudd_Regular Cudd_Complement] + +******************************************************************************/ +#define Cudd_IsComplement(node) ((int) ((long) (node) & 01)) + + +/**Macro*********************************************************************** + + Synopsis [Returns the then child of an internal node.] + + Description [Returns the then child of an internal node. If + node is a constant node, the result is unpredictable.] + + SideEffects [none] + + SeeAlso [Cudd_E Cudd_V] + +******************************************************************************/ +#define Cudd_T(node) ((Cudd_Regular(node))->type.kids.T) + + +/**Macro*********************************************************************** + + Synopsis [Returns the else child of an internal node.] + + Description [Returns the else child of an internal node. If + node is a constant node, the result is unpredictable.] + + SideEffects [none] + + SeeAlso [Cudd_T Cudd_V] + +******************************************************************************/ +#define Cudd_E(node) ((Cudd_Regular(node))->type.kids.E) + + +/**Macro*********************************************************************** + + Synopsis [Returns the value of a constant node.] + + Description [Returns the value of a constant node. If + node is an internal node, the result is unpredictable.] + + SideEffects [none] + + SeeAlso [Cudd_T Cudd_E] + +******************************************************************************/ +#define Cudd_V(node) ((Cudd_Regular(node))->type.value) + + +/**Macro*********************************************************************** + + Synopsis [Returns the current position in the order of variable + index.] + + Description [Returns the current position in the order of variable + index. This macro is obsolete and is kept for compatibility. New + applications should use Cudd_ReadPerm instead.] + + SideEffects [none] + + SeeAlso [Cudd_ReadPerm] + +******************************************************************************/ +#define Cudd_ReadIndex(dd,index) (Cudd_ReadPerm(dd,index)) + + +/**Macro*********************************************************************** + + Synopsis [Iterates over the cubes of a decision diagram.] + + Description [Iterates over the cubes of a decision diagram f. +
    +
  • DdManager *manager; +
  • DdNode *f; +
  • DdGen *gen; +
  • int *cube; +
  • CUDD_VALUE_TYPE value; +
+ Cudd_ForeachCube allocates and frees the generator. Therefore the + application should not try to do that. Also, the cube is freed at the + end of Cudd_ForeachCube and hence is not available outside of the loop.

+ CAUTION: It is assumed that dynamic reordering will not occur while + there are open generators. It is the user's responsibility to make sure + that dynamic reordering does not occur. As long as new nodes are not created + during generation, and dynamic reordering is not called explicitly, + dynamic reordering will not occur. Alternatively, it is sufficient to + disable dynamic reordering. It is a mistake to dispose of a diagram + on which generation is ongoing.] + + SideEffects [none] + + SeeAlso [Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube Cudd_GenFree + Cudd_IsGenEmpty Cudd_AutodynDisable] + +******************************************************************************/ +#define Cudd_ForeachCube(manager, f, gen, cube, value)\ + for((gen) = Cudd_FirstCube(manager, f, &cube, &value);\ + Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ + (void) Cudd_NextCube(gen, &cube, &value)) + + +/**Macro*********************************************************************** + + Synopsis [Iterates over the nodes of a decision diagram.] + + Description [Iterates over the nodes of a decision diagram f. +

    +
  • DdManager *manager; +
  • DdNode *f; +
  • DdGen *gen; +
  • DdNode *node; +
+ The nodes are returned in a seemingly random order. + Cudd_ForeachNode allocates and frees the generator. Therefore the + application should not try to do that.

+ CAUTION: It is assumed that dynamic reordering will not occur while + there are open generators. It is the user's responsibility to make sure + that dynamic reordering does not occur. As long as new nodes are not created + during generation, and dynamic reordering is not called explicitly, + dynamic reordering will not occur. Alternatively, it is sufficient to + disable dynamic reordering. It is a mistake to dispose of a diagram + on which generation is ongoing.] + + SideEffects [none] + + SeeAlso [Cudd_ForeachCube Cudd_FirstNode Cudd_NextNode Cudd_GenFree + Cudd_IsGenEmpty Cudd_AutodynDisable] + +******************************************************************************/ +#define Cudd_ForeachNode(manager, f, gen, node)\ + for((gen) = Cudd_FirstNode(manager, f, &node);\ + Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ + (void) Cudd_NextNode(gen, &node)) + + +/**Macro*********************************************************************** + + Synopsis [Iterates over the paths of a ZDD.] + + Description [Iterates over the paths of a ZDD f. +

    +
  • DdManager *manager; +
  • DdNode *f; +
  • DdGen *gen; +
  • int *path; +
+ Cudd_zddForeachPath allocates and frees the generator. Therefore the + application should not try to do that. Also, the path is freed at the + end of Cudd_zddForeachPath and hence is not available outside of the loop.

+ CAUTION: It is assumed that dynamic reordering will not occur while + there are open generators. It is the user's responsibility to make sure + that dynamic reordering does not occur. As long as new nodes are not created + during generation, and dynamic reordering is not called explicitly, + dynamic reordering will not occur. Alternatively, it is sufficient to + disable dynamic reordering. It is a mistake to dispose of a diagram + on which generation is ongoing.] + + SideEffects [none] + + SeeAlso [Cudd_zddFirstPath Cudd_zddNextPath Cudd_GenFree + Cudd_IsGenEmpty Cudd_AutodynDisable] + +******************************************************************************/ +#define Cudd_zddForeachPath(manager, f, gen, path)\ + for((gen) = Cudd_zddFirstPath(manager, f, &path);\ + Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ + (void) Cudd_zddNextPath(gen, &path)) + + +/* These are potential duplicates. */ +#ifndef EXTERN +# ifdef __cplusplus +# define EXTERN extern "C" +# else +# define EXTERN extern +# endif +#endif +#ifndef ARGS +# if defined(__STDC__) || defined(__cplusplus) +# define ARGS(protos) protos /* ANSI C */ +# else /* !(__STDC__ || __cplusplus) */ +# define ARGS(protos) () /* K&R C */ +# endif /* !(__STDC__ || __cplusplus) */ +#endif + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + +EXTERN DdNode * Cudd_addNewVar ARGS((DdManager *dd)); +EXTERN DdNode * Cudd_addNewVarAtLevel ARGS((DdManager *dd, int level)); +EXTERN DdNode * Cudd_bddNewVar ARGS((DdManager *dd)); +EXTERN DdNode * Cudd_bddNewVarAtLevel ARGS((DdManager *dd, int level)); +EXTERN DdNode * Cudd_addIthVar ARGS((DdManager *dd, int i)); +EXTERN DdNode * Cudd_bddIthVar ARGS((DdManager *dd, int i)); +EXTERN DdNode * Cudd_zddIthVar ARGS((DdManager *dd, int i)); +EXTERN int Cudd_zddVarsFromBddVars ARGS((DdManager *dd, int multiplicity)); +EXTERN DdNode * Cudd_addConst ARGS((DdManager *dd, CUDD_VALUE_TYPE c)); +EXTERN int Cudd_IsNonConstant ARGS((DdNode *f)); +EXTERN void Cudd_AutodynEnable ARGS((DdManager *unique, Cudd_ReorderingType method)); +EXTERN void Cudd_AutodynDisable ARGS((DdManager *unique)); +EXTERN int Cudd_ReorderingStatus ARGS((DdManager *unique, Cudd_ReorderingType *method)); +EXTERN void Cudd_AutodynEnableZdd ARGS((DdManager *unique, Cudd_ReorderingType method)); +EXTERN void Cudd_AutodynDisableZdd ARGS((DdManager *unique)); +EXTERN int Cudd_ReorderingStatusZdd ARGS((DdManager *unique, Cudd_ReorderingType *method)); +EXTERN int Cudd_zddRealignmentEnabled ARGS((DdManager *unique)); +EXTERN void Cudd_zddRealignEnable ARGS((DdManager *unique)); +EXTERN void Cudd_zddRealignDisable ARGS((DdManager *unique)); +EXTERN int Cudd_bddRealignmentEnabled ARGS((DdManager *unique)); +EXTERN void Cudd_bddRealignEnable ARGS((DdManager *unique)); +EXTERN void Cudd_bddRealignDisable ARGS((DdManager *unique)); +EXTERN DdNode * Cudd_ReadOne ARGS((DdManager *dd)); +EXTERN DdNode * Cudd_ReadZddOne ARGS((DdManager *dd, int i)); +EXTERN DdNode * Cudd_ReadZero ARGS((DdManager *dd)); +EXTERN DdNode * Cudd_ReadLogicZero ARGS((DdManager *dd)); +EXTERN DdNode * Cudd_ReadPlusInfinity ARGS((DdManager *dd)); +EXTERN DdNode * Cudd_ReadMinusInfinity ARGS((DdManager *dd)); +EXTERN DdNode * Cudd_ReadBackground ARGS((DdManager *dd)); +EXTERN void Cudd_SetBackground ARGS((DdManager *dd, DdNode *bck)); +EXTERN unsigned int Cudd_ReadCacheSlots ARGS((DdManager *dd)); +EXTERN double Cudd_ReadCacheUsedSlots ARGS((DdManager * dd)); +EXTERN double Cudd_ReadCacheLookUps ARGS((DdManager *dd)); +EXTERN double Cudd_ReadCacheHits ARGS((DdManager *dd)); +EXTERN double Cudd_ReadRecursiveCalls ARGS ((DdManager * dd)); +EXTERN unsigned int Cudd_ReadMinHit ARGS((DdManager *dd)); +EXTERN void Cudd_SetMinHit ARGS((DdManager *dd, unsigned int hr)); +EXTERN unsigned int Cudd_ReadLooseUpTo ARGS((DdManager *dd)); +EXTERN void Cudd_SetLooseUpTo ARGS((DdManager *dd, unsigned int lut)); +EXTERN unsigned int Cudd_ReadMaxCache ARGS((DdManager *dd)); +EXTERN unsigned int Cudd_ReadMaxCacheHard ARGS((DdManager *dd)); +EXTERN void Cudd_SetMaxCacheHard ARGS((DdManager *dd, unsigned int mc)); +EXTERN int Cudd_ReadSize ARGS((DdManager *dd)); +EXTERN int Cudd_ReadZddSize ARGS((DdManager *dd)); +EXTERN unsigned int Cudd_ReadSlots ARGS((DdManager *dd)); +EXTERN double Cudd_ReadUsedSlots ARGS((DdManager * dd)); +EXTERN double Cudd_ExpectedUsedSlots ARGS((DdManager * dd)); +EXTERN unsigned int Cudd_ReadKeys ARGS((DdManager *dd)); +EXTERN unsigned int Cudd_ReadDead ARGS((DdManager *dd)); +EXTERN unsigned int Cudd_ReadMinDead ARGS((DdManager *dd)); +EXTERN int Cudd_ReadReorderings ARGS((DdManager *dd)); +EXTERN long Cudd_ReadReorderingTime ARGS((DdManager * dd)); +EXTERN int Cudd_ReadGarbageCollections ARGS((DdManager * dd)); +EXTERN long Cudd_ReadGarbageCollectionTime ARGS((DdManager * dd)); +EXTERN double Cudd_ReadNodesFreed ARGS((DdManager * dd)); +EXTERN double Cudd_ReadNodesDropped ARGS((DdManager * dd)); +EXTERN double Cudd_ReadUniqueLookUps ARGS((DdManager * dd)); +EXTERN double Cudd_ReadUniqueLinks ARGS((DdManager * dd)); +EXTERN int Cudd_ReadSiftMaxVar ARGS((DdManager *dd)); +EXTERN void Cudd_SetSiftMaxVar ARGS((DdManager *dd, int smv)); +EXTERN int Cudd_ReadSiftMaxSwap ARGS((DdManager *dd)); +EXTERN void Cudd_SetSiftMaxSwap ARGS((DdManager *dd, int sms)); +EXTERN double Cudd_ReadMaxGrowth ARGS((DdManager *dd)); +EXTERN void Cudd_SetMaxGrowth ARGS((DdManager *dd, double mg)); +EXTERN double Cudd_ReadMaxGrowthAlternate ARGS((DdManager * dd)); +EXTERN void Cudd_SetMaxGrowthAlternate ARGS((DdManager * dd, double mg)); +EXTERN int Cudd_ReadReorderingCycle ARGS((DdManager * dd)); +EXTERN void Cudd_SetReorderingCycle ARGS((DdManager * dd, int cycle)); +EXTERN MtrNode * Cudd_ReadTree ARGS((DdManager *dd)); +EXTERN void Cudd_SetTree ARGS((DdManager *dd, MtrNode *tree)); +EXTERN void Cudd_FreeTree ARGS((DdManager *dd)); +EXTERN MtrNode * Cudd_ReadZddTree ARGS((DdManager *dd)); +EXTERN void Cudd_SetZddTree ARGS((DdManager *dd, MtrNode *tree)); +EXTERN void Cudd_FreeZddTree ARGS((DdManager *dd)); +EXTERN unsigned int Cudd_NodeReadIndex ARGS((DdNode *node)); +EXTERN int Cudd_ReadPerm ARGS((DdManager *dd, int i)); +EXTERN int Cudd_ReadPermZdd ARGS((DdManager *dd, int i)); +EXTERN int Cudd_ReadInvPerm ARGS((DdManager *dd, int i)); +EXTERN int Cudd_ReadInvPermZdd ARGS((DdManager *dd, int i)); +EXTERN DdNode * Cudd_ReadVars ARGS((DdManager *dd, int i)); +EXTERN CUDD_VALUE_TYPE Cudd_ReadEpsilon ARGS((DdManager *dd)); +EXTERN void Cudd_SetEpsilon ARGS((DdManager *dd, CUDD_VALUE_TYPE ep)); +EXTERN Cudd_AggregationType Cudd_ReadGroupcheck ARGS((DdManager *dd)); +EXTERN void Cudd_SetGroupcheck ARGS((DdManager *dd, Cudd_AggregationType gc)); +EXTERN int Cudd_GarbageCollectionEnabled ARGS((DdManager *dd)); +EXTERN void Cudd_EnableGarbageCollection ARGS((DdManager *dd)); +EXTERN void Cudd_DisableGarbageCollection ARGS((DdManager *dd)); +EXTERN int Cudd_DeadAreCounted ARGS((DdManager *dd)); +EXTERN void Cudd_TurnOnCountDead ARGS((DdManager *dd)); +EXTERN void Cudd_TurnOffCountDead ARGS((DdManager *dd)); +EXTERN int Cudd_ReadRecomb ARGS((DdManager *dd)); +EXTERN void Cudd_SetRecomb ARGS((DdManager *dd, int recomb)); +EXTERN int Cudd_ReadSymmviolation ARGS((DdManager *dd)); +EXTERN void Cudd_SetSymmviolation ARGS((DdManager *dd, int symmviolation)); +EXTERN int Cudd_ReadArcviolation ARGS((DdManager *dd)); +EXTERN void Cudd_SetArcviolation ARGS((DdManager *dd, int arcviolation)); +EXTERN int Cudd_ReadPopulationSize ARGS((DdManager *dd)); +EXTERN void Cudd_SetPopulationSize ARGS((DdManager *dd, int populationSize)); +EXTERN int Cudd_ReadNumberXovers ARGS((DdManager *dd)); +EXTERN void Cudd_SetNumberXovers ARGS((DdManager *dd, int numberXovers)); +EXTERN long Cudd_ReadMemoryInUse ARGS((DdManager *dd)); +EXTERN int Cudd_PrintInfo ARGS((DdManager *dd, FILE *fp)); +EXTERN long Cudd_ReadPeakNodeCount ARGS((DdManager *dd)); +EXTERN int Cudd_ReadPeakLiveNodeCount ARGS((DdManager * dd)); +EXTERN long Cudd_ReadNodeCount ARGS((DdManager *dd)); +EXTERN long Cudd_zddReadNodeCount ARGS((DdManager *dd)); +EXTERN int Cudd_AddHook ARGS((DdManager *dd, int (*f)(DdManager *, char *, void *), Cudd_HookType where)); +EXTERN int Cudd_RemoveHook ARGS((DdManager *dd, int (*f)(DdManager *, char *, void *), Cudd_HookType where)); +EXTERN int Cudd_IsInHook ARGS((DdManager * dd, int (*f)(DdManager *, char *, void *), Cudd_HookType where)); +EXTERN int Cudd_StdPreReordHook ARGS((DdManager *dd, char *str, void *data)); +EXTERN int Cudd_StdPostReordHook ARGS((DdManager *dd, char *str, void *data)); +EXTERN int Cudd_EnableReorderingReporting ARGS((DdManager *dd)); +EXTERN int Cudd_DisableReorderingReporting ARGS((DdManager *dd)); +EXTERN int Cudd_ReorderingReporting ARGS((DdManager *dd)); +EXTERN Cudd_ErrorType Cudd_ReadErrorCode ARGS((DdManager *dd)); +EXTERN void Cudd_ClearErrorCode ARGS((DdManager *dd)); +EXTERN FILE * Cudd_ReadStdout ARGS((DdManager *dd)); +EXTERN void Cudd_SetStdout ARGS((DdManager *dd, FILE *fp)); +EXTERN FILE * Cudd_ReadStderr ARGS((DdManager *dd)); +EXTERN void Cudd_SetStderr ARGS((DdManager *dd, FILE *fp)); +EXTERN unsigned int Cudd_ReadNextReordering ARGS((DdManager *dd)); +EXTERN void Cudd_SetNextReordering ARGS((DdManager *dd, unsigned int next)); +EXTERN double Cudd_ReadSwapSteps ARGS((DdManager *dd)); +EXTERN unsigned int Cudd_ReadMaxLive ARGS((DdManager *dd)); +EXTERN void Cudd_SetMaxLive ARGS((DdManager *dd, unsigned int maxLive)); +EXTERN long Cudd_ReadMaxMemory ARGS((DdManager *dd)); +EXTERN void Cudd_SetMaxMemory ARGS((DdManager *dd, long maxMemory)); +EXTERN int Cudd_bddBindVar ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddUnbindVar ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddVarIsBound ARGS((DdManager *dd, int index)); +EXTERN DdNode * Cudd_addExistAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); +EXTERN DdNode * Cudd_addUnivAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); +EXTERN DdNode * Cudd_addOrAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); +EXTERN DdNode * Cudd_addApply ARGS((DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_addPlus ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addTimes ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addThreshold ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addSetNZ ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addDivide ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addMinus ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addMinimum ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addMaximum ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addOneZeroMaximum ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addDiff ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addAgreement ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addOr ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addNand ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addNor ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addXor ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addXnor ARGS((DdManager *dd, DdNode **f, DdNode **g)); +EXTERN DdNode * Cudd_addMonadicApply ARGS((DdManager * dd, DdNode * (*op)(DdManager *, DdNode *), DdNode * f)); +EXTERN DdNode * Cudd_addLog ARGS((DdManager * dd, DdNode * f)); +EXTERN DdNode * Cudd_addFindMax ARGS((DdManager *dd, DdNode *f)); +EXTERN DdNode * Cudd_addFindMin ARGS((DdManager *dd, DdNode *f)); +EXTERN DdNode * Cudd_addIthBit ARGS((DdManager *dd, DdNode *f, int bit)); +EXTERN DdNode * Cudd_addScalarInverse ARGS((DdManager *dd, DdNode *f, DdNode *epsilon)); +EXTERN DdNode * Cudd_addIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); +EXTERN DdNode * Cudd_addIteConstant ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); +EXTERN DdNode * Cudd_addEvalConst ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN int Cudd_addLeq ARGS((DdManager * dd, DdNode * f, DdNode * g)); +EXTERN DdNode * Cudd_addCmpl ARGS((DdManager *dd, DdNode *f)); +EXTERN DdNode * Cudd_addNegate ARGS((DdManager *dd, DdNode *f)); +EXTERN DdNode * Cudd_addRoundOff ARGS((DdManager *dd, DdNode *f, int N)); +EXTERN DdNode * Cudd_addWalsh ARGS((DdManager *dd, DdNode **x, DdNode **y, int n)); +EXTERN DdNode * Cudd_addResidue ARGS((DdManager *dd, int n, int m, int options, int top)); +EXTERN DdNode * Cudd_bddAndAbstract ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); +EXTERN int Cudd_ApaNumberOfDigits ARGS((int binaryDigits)); +EXTERN DdApaNumber Cudd_NewApaNumber ARGS((int digits)); +EXTERN void Cudd_ApaCopy ARGS((int digits, DdApaNumber source, DdApaNumber dest)); +EXTERN DdApaDigit Cudd_ApaAdd ARGS((int digits, DdApaNumber a, DdApaNumber b, DdApaNumber sum)); +EXTERN DdApaDigit Cudd_ApaSubtract ARGS((int digits, DdApaNumber a, DdApaNumber b, DdApaNumber diff)); +EXTERN DdApaDigit Cudd_ApaShortDivision ARGS((int digits, DdApaNumber dividend, DdApaDigit divisor, DdApaNumber quotient)); +EXTERN unsigned int Cudd_ApaIntDivision ARGS((int digits, DdApaNumber dividend, unsigned int divisor, DdApaNumber quotient)); +EXTERN void Cudd_ApaShiftRight ARGS((int digits, DdApaDigit in, DdApaNumber a, DdApaNumber b)); +EXTERN void Cudd_ApaSetToLiteral ARGS((int digits, DdApaNumber number, DdApaDigit literal)); +EXTERN void Cudd_ApaPowerOfTwo ARGS((int digits, DdApaNumber number, int power)); +EXTERN int Cudd_ApaCompare ARGS((int digitsFirst, DdApaNumber first, int digitsSecond, DdApaNumber second)); +EXTERN int Cudd_ApaCompareRatios ARGS ((int digitsFirst, DdApaNumber firstNum, unsigned int firstDen, int digitsSecond, DdApaNumber secondNum, unsigned int secondDen)); +EXTERN int Cudd_ApaPrintHex ARGS((FILE *fp, int digits, DdApaNumber number)); +EXTERN int Cudd_ApaPrintDecimal ARGS((FILE *fp, int digits, DdApaNumber number)); +EXTERN int Cudd_ApaPrintExponential ARGS((FILE * fp, int digits, DdApaNumber number, int precision)); +EXTERN DdApaNumber Cudd_ApaCountMinterm ARGS((DdManager *manager, DdNode *node, int nvars, int *digits)); +EXTERN int Cudd_ApaPrintMinterm ARGS((FILE *fp, DdManager *dd, DdNode *node, int nvars)); +EXTERN int Cudd_ApaPrintMintermExp ARGS((FILE * fp, DdManager * dd, DdNode * node, int nvars, int precision)); +EXTERN int Cudd_ApaPrintDensity ARGS((FILE * fp, DdManager * dd, DdNode * node, int nvars)); +EXTERN DdNode * Cudd_UnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality)); +EXTERN DdNode * Cudd_OverApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality)); +EXTERN DdNode * Cudd_RemapUnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, double quality)); +EXTERN DdNode * Cudd_RemapOverApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, double quality)); +EXTERN DdNode * Cudd_BiasedUnderApprox ARGS((DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0)); +EXTERN DdNode * Cudd_BiasedOverApprox ARGS((DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0)); +EXTERN DdNode * Cudd_bddExistAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); +EXTERN DdNode * Cudd_bddXorExistAbstract ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); +EXTERN DdNode * Cudd_bddUnivAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); +EXTERN DdNode * Cudd_bddBooleanDiff ARGS((DdManager *manager, DdNode *f, int x)); +EXTERN int Cudd_bddVarIsDependent ARGS((DdManager *dd, DdNode *f, DdNode *var)); +EXTERN double Cudd_bddCorrelation ARGS((DdManager *manager, DdNode *f, DdNode *g)); +EXTERN double Cudd_bddCorrelationWeights ARGS((DdManager *manager, DdNode *f, DdNode *g, double *prob)); +EXTERN DdNode * Cudd_bddIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); +EXTERN DdNode * Cudd_bddIteConstant ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); +EXTERN DdNode * Cudd_bddIntersect ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_bddAnd ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_bddOr ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_bddNand ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_bddNor ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_bddXor ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_bddXnor ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN int Cudd_bddLeq ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_addBddThreshold ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE value)); +EXTERN DdNode * Cudd_addBddStrictThreshold ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE value)); +EXTERN DdNode * Cudd_addBddInterval ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE lower, CUDD_VALUE_TYPE upper)); +EXTERN DdNode * Cudd_addBddIthBit ARGS((DdManager *dd, DdNode *f, int bit)); +EXTERN DdNode * Cudd_BddToAdd ARGS((DdManager *dd, DdNode *B)); +EXTERN DdNode * Cudd_addBddPattern ARGS((DdManager *dd, DdNode *f)); +EXTERN DdNode * Cudd_bddTransfer ARGS((DdManager *ddSource, DdManager *ddDestination, DdNode *f)); +EXTERN int Cudd_DebugCheck ARGS((DdManager *table)); +EXTERN int Cudd_CheckKeys ARGS((DdManager *table)); +EXTERN DdNode * Cudd_bddClippingAnd ARGS((DdManager *dd, DdNode *f, DdNode *g, int maxDepth, int direction)); +EXTERN DdNode * Cudd_bddClippingAndAbstract ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *cube, int maxDepth, int direction)); +EXTERN DdNode * Cudd_Cofactor ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_bddCompose ARGS((DdManager *dd, DdNode *f, DdNode *g, int v)); +EXTERN DdNode * Cudd_addCompose ARGS((DdManager *dd, DdNode *f, DdNode *g, int v)); +EXTERN DdNode * Cudd_addPermute ARGS((DdManager *manager, DdNode *node, int *permut)); +EXTERN DdNode * Cudd_addSwapVariables ARGS((DdManager *dd, DdNode *f, DdNode **x, DdNode **y, int n)); +EXTERN DdNode * Cudd_bddPermute ARGS((DdManager *manager, DdNode *node, int *permut)); +EXTERN DdNode * Cudd_bddVarMap ARGS((DdManager *manager, DdNode *f)); +EXTERN int Cudd_SetVarMap ARGS((DdManager *manager, DdNode **x, DdNode **y, int n)); +EXTERN DdNode * Cudd_bddSwapVariables ARGS((DdManager *dd, DdNode *f, DdNode **x, DdNode **y, int n)); +EXTERN DdNode * Cudd_bddAdjPermuteX ARGS((DdManager *dd, DdNode *B, DdNode **x, int n)); +EXTERN DdNode * Cudd_addVectorCompose ARGS((DdManager *dd, DdNode *f, DdNode **vector)); +EXTERN DdNode * Cudd_addGeneralVectorCompose ARGS((DdManager *dd, DdNode *f, DdNode **vectorOn, DdNode **vectorOff)); +EXTERN DdNode * Cudd_addNonSimCompose ARGS((DdManager *dd, DdNode *f, DdNode **vector)); +EXTERN DdNode * Cudd_bddVectorCompose ARGS((DdManager *dd, DdNode *f, DdNode **vector)); +EXTERN int Cudd_bddApproxConjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***conjuncts)); +EXTERN int Cudd_bddApproxDisjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***disjuncts)); +EXTERN int Cudd_bddIterConjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***conjuncts)); +EXTERN int Cudd_bddIterDisjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***disjuncts)); +EXTERN int Cudd_bddGenConjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***conjuncts)); +EXTERN int Cudd_bddGenDisjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***disjuncts)); +EXTERN int Cudd_bddVarConjDecomp ARGS((DdManager *dd, DdNode * f, DdNode ***conjuncts)); +EXTERN int Cudd_bddVarDisjDecomp ARGS((DdManager *dd, DdNode * f, DdNode ***disjuncts)); +EXTERN DdNode * Cudd_FindEssential ARGS((DdManager *dd, DdNode *f)); +EXTERN int Cudd_bddIsVarEssential ARGS((DdManager *manager, DdNode *f, int id, int phase)); +EXTERN int Cudd_DumpBlif ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, char *mname, FILE *fp)); +EXTERN int Cudd_DumpBlifBody ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); +EXTERN int Cudd_DumpDot ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); +EXTERN int Cudd_DumpDaVinci ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); +EXTERN int Cudd_DumpDDcal ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); +EXTERN int Cudd_DumpFactoredForm ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); +EXTERN DdNode * Cudd_bddConstrain ARGS((DdManager *dd, DdNode *f, DdNode *c)); +EXTERN DdNode * Cudd_bddRestrict ARGS((DdManager *dd, DdNode *f, DdNode *c)); +EXTERN DdNode * Cudd_addConstrain ARGS((DdManager *dd, DdNode *f, DdNode *c)); +EXTERN DdNode ** Cudd_bddConstrainDecomp ARGS((DdManager *dd, DdNode *f)); +EXTERN DdNode * Cudd_addRestrict ARGS((DdManager *dd, DdNode *f, DdNode *c)); +EXTERN DdNode ** Cudd_bddCharToVect ARGS((DdManager *dd, DdNode *f)); +EXTERN DdNode * Cudd_bddLICompaction ARGS((DdManager *dd, DdNode *f, DdNode *c)); +EXTERN DdNode * Cudd_bddSqueeze ARGS((DdManager *dd, DdNode *l, DdNode *u)); +EXTERN DdNode * Cudd_bddMinimize ARGS((DdManager *dd, DdNode *f, DdNode *c)); +EXTERN DdNode * Cudd_SubsetCompress ARGS((DdManager *dd, DdNode *f, int nvars, int threshold)); +EXTERN DdNode * Cudd_SupersetCompress ARGS((DdManager *dd, DdNode *f, int nvars, int threshold)); +EXTERN MtrNode * Cudd_MakeTreeNode ARGS((DdManager *dd, unsigned int low, unsigned int size, unsigned int type)); +EXTERN int Cudd_addHarwell ARGS((FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, DdNode ***xn, DdNode ***yn_, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy, int pr)); +EXTERN DdManager * Cudd_Init ARGS((unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory)); +EXTERN void Cudd_Quit ARGS((DdManager *unique)); +EXTERN int Cudd_PrintLinear ARGS((DdManager *table)); +EXTERN int Cudd_ReadLinear ARGS((DdManager *table, int x, int y)); +EXTERN DdNode * Cudd_bddLiteralSetIntersection ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_addMatrixMultiply ARGS((DdManager *dd, DdNode *A, DdNode *B, DdNode **z, int nz)); +EXTERN DdNode * Cudd_addTimesPlus ARGS((DdManager *dd, DdNode *A, DdNode *B, DdNode **z, int nz)); +EXTERN DdNode * Cudd_addTriangle ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode **z, int nz)); +EXTERN DdNode * Cudd_addOuterSum ARGS((DdManager *dd, DdNode *M, DdNode *r, DdNode *c)); +EXTERN DdNode * Cudd_PrioritySelect ARGS((DdManager *dd, DdNode *R, DdNode **x, DdNode **y, DdNode **z, DdNode *Pi, int n, DdNode * (*)(DdManager *, int, DdNode **, DdNode **, DdNode **))); +EXTERN DdNode * Cudd_Xgty ARGS((DdManager *dd, int N, DdNode **z, DdNode **x, DdNode **y)); +EXTERN DdNode * Cudd_Xeqy ARGS((DdManager *dd, int N, DdNode **x, DdNode **y)); +EXTERN DdNode * Cudd_addXeqy ARGS((DdManager *dd, int N, DdNode **x, DdNode **y)); +EXTERN DdNode * Cudd_Dxygtdxz ARGS((DdManager *dd, int N, DdNode **x, DdNode **y, DdNode **z)); +EXTERN DdNode * Cudd_Dxygtdyz ARGS((DdManager *dd, int N, DdNode **x, DdNode **y, DdNode **z)); +EXTERN DdNode * Cudd_CProjection ARGS((DdManager *dd, DdNode *R, DdNode *Y)); +EXTERN DdNode * Cudd_addHamming ARGS((DdManager *dd, DdNode **xVars, DdNode **yVars, int nVars)); +EXTERN int Cudd_MinHammingDist ARGS((DdManager *dd, DdNode *f, int *minterm, int upperBound)); +EXTERN DdNode * Cudd_bddClosestCube ARGS((DdManager *dd, DdNode * f, DdNode *g, int *distance)); +EXTERN int Cudd_addRead ARGS((FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, DdNode ***xn, DdNode ***yn_, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy)); +EXTERN int Cudd_bddRead ARGS((FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy)); +EXTERN void Cudd_Ref ARGS((DdNode *n)); +EXTERN void Cudd_RecursiveDeref ARGS((DdManager *table, DdNode *n)); +EXTERN void Cudd_IterDerefBdd ARGS((DdManager *table, DdNode *n)); +EXTERN void Cudd_DelayedDerefBdd ARGS((DdManager * table, DdNode * n)); +EXTERN void Cudd_RecursiveDerefZdd ARGS((DdManager *table, DdNode *n)); +EXTERN void Cudd_Deref ARGS((DdNode *node)); +EXTERN int Cudd_CheckZeroRef ARGS((DdManager *manager)); +EXTERN int Cudd_ReduceHeap ARGS((DdManager *table, Cudd_ReorderingType heuristic, int minsize)); +EXTERN int Cudd_ShuffleHeap ARGS((DdManager *table, int *permutation)); +EXTERN DdNode * Cudd_Eval ARGS((DdManager *dd, DdNode *f, int *inputs)); +EXTERN DdNode * Cudd_ShortestPath ARGS((DdManager *manager, DdNode *f, int *weight, int *support, int *length)); +EXTERN DdNode * Cudd_LargestCube ARGS((DdManager *manager, DdNode *f, int *length)); +EXTERN int Cudd_ShortestLength ARGS((DdManager *manager, DdNode *f, int *weight)); +EXTERN DdNode * Cudd_Decreasing ARGS((DdManager *dd, DdNode *f, int i)); +EXTERN DdNode * Cudd_Increasing ARGS((DdManager *dd, DdNode *f, int i)); +EXTERN int Cudd_EquivDC ARGS((DdManager *dd, DdNode *F, DdNode *G, DdNode *D)); +EXTERN int Cudd_bddLeqUnless ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *D)); +EXTERN int Cudd_EqualSupNorm ARGS((DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE tolerance, int pr)); +EXTERN DdNode * Cudd_bddMakePrime ARGS ((DdManager *dd, DdNode *cube, DdNode *f)); +EXTERN double * Cudd_CofMinterm ARGS((DdManager *dd, DdNode *node)); +EXTERN DdNode * Cudd_SolveEqn ARGS((DdManager * bdd, DdNode *F, DdNode *Y, DdNode **G, int **yIndex, int n)); +EXTERN DdNode * Cudd_VerifySol ARGS((DdManager * bdd, DdNode *F, DdNode **G, int *yIndex, int n)); +EXTERN DdNode * Cudd_SplitSet ARGS((DdManager *manager, DdNode *S, DdNode **xVars, int n, double m)); +EXTERN DdNode * Cudd_SubsetHeavyBranch ARGS((DdManager *dd, DdNode *f, int numVars, int threshold)); +EXTERN DdNode * Cudd_SupersetHeavyBranch ARGS((DdManager *dd, DdNode *f, int numVars, int threshold)); +EXTERN DdNode * Cudd_SubsetShortPaths ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)); +EXTERN DdNode * Cudd_SupersetShortPaths ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)); +EXTERN void Cudd_SymmProfile ARGS((DdManager *table, int lower, int upper)); +EXTERN unsigned int Cudd_Prime ARGS((unsigned int p)); +EXTERN int Cudd_PrintMinterm ARGS((DdManager *manager, DdNode *node)); +EXTERN int Cudd_bddPrintCover ARGS((DdManager *dd, DdNode *l, DdNode *u)); +EXTERN int Cudd_PrintDebug ARGS((DdManager *dd, DdNode *f, int n, int pr)); +EXTERN int Cudd_DagSize ARGS((DdNode *node)); +EXTERN int Cudd_EstimateCofactor ARGS((DdManager *dd, DdNode * node, int i, int phase)); +EXTERN int Cudd_EstimateCofactorSimple ARGS((DdNode * node, int i)); +EXTERN int Cudd_SharingSize ARGS((DdNode **nodeArray, int n)); +EXTERN double Cudd_CountMinterm ARGS((DdManager *manager, DdNode *node, int nvars)); +EXTERN int Cudd_EpdCountMinterm ARGS((DdManager *manager, DdNode *node, int nvars, EpDouble *epd)); +EXTERN double Cudd_CountPath ARGS((DdNode *node)); +EXTERN double Cudd_CountPathsToNonZero ARGS((DdNode *node)); +EXTERN DdNode * Cudd_Support ARGS((DdManager *dd, DdNode *f)); +EXTERN int * Cudd_SupportIndex ARGS((DdManager *dd, DdNode *f)); +EXTERN int Cudd_SupportSize ARGS((DdManager *dd, DdNode *f)); +EXTERN DdNode * Cudd_VectorSupport ARGS((DdManager *dd, DdNode **F, int n)); +EXTERN int * Cudd_VectorSupportIndex ARGS((DdManager *dd, DdNode **F, int n)); +EXTERN int Cudd_VectorSupportSize ARGS((DdManager *dd, DdNode **F, int n)); +EXTERN int Cudd_ClassifySupport ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode **common, DdNode **onlyF, DdNode **onlyG)); +EXTERN int Cudd_CountLeaves ARGS((DdNode *node)); +EXTERN int Cudd_bddPickOneCube ARGS((DdManager *ddm, DdNode *node, char *string)); +EXTERN DdNode * Cudd_bddPickOneMinterm ARGS((DdManager *dd, DdNode *f, DdNode **vars, int n)); +EXTERN DdNode ** Cudd_bddPickArbitraryMinterms ARGS((DdManager *dd, DdNode *f, DdNode **vars, int n, int k)); +EXTERN DdNode * Cudd_SubsetWithMaskVars ARGS((DdManager *dd, DdNode *f, DdNode **vars, int nvars, DdNode **maskVars, int mvars)); +EXTERN DdGen * Cudd_FirstCube ARGS((DdManager *dd, DdNode *f, int **cube, CUDD_VALUE_TYPE *value)); +EXTERN int Cudd_NextCube ARGS((DdGen *gen, int **cube, CUDD_VALUE_TYPE *value)); +EXTERN DdNode * Cudd_bddComputeCube ARGS((DdManager *dd, DdNode **vars, int *phase, int n)); +EXTERN DdNode * Cudd_addComputeCube ARGS((DdManager *dd, DdNode **vars, int *phase, int n)); +EXTERN DdNode * Cudd_CubeArrayToBdd ARGS((DdManager *dd, int *array)); +EXTERN int Cudd_BddToCubeArray ARGS((DdManager *dd, DdNode *cube, int *array)); +EXTERN DdGen * Cudd_FirstNode ARGS((DdManager *dd, DdNode *f, DdNode **node)); +EXTERN int Cudd_NextNode ARGS((DdGen *gen, DdNode **node)); +EXTERN int Cudd_GenFree ARGS((DdGen *gen)); +EXTERN int Cudd_IsGenEmpty ARGS((DdGen *gen)); +EXTERN DdNode * Cudd_IndicesToCube ARGS((DdManager *dd, int *array, int n)); +EXTERN void Cudd_PrintVersion ARGS((FILE *fp)); +EXTERN double Cudd_AverageDistance ARGS((DdManager *dd)); +EXTERN long Cudd_Random ARGS(()); +EXTERN void Cudd_Srandom ARGS((long seed)); +EXTERN double Cudd_Density ARGS((DdManager *dd, DdNode *f, int nvars)); +EXTERN void Cudd_OutOfMem ARGS((long size)); +EXTERN int Cudd_zddCount ARGS((DdManager *zdd, DdNode *P)); +EXTERN double Cudd_zddCountDouble ARGS((DdManager *zdd, DdNode *P)); +EXTERN DdNode * Cudd_zddProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_zddUnateProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_zddWeakDiv ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_zddDivide ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_zddWeakDivF ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_zddDivideF ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * Cudd_zddComplement ARGS((DdManager *dd, DdNode *node)); +EXTERN MtrNode * Cudd_MakeZddTreeNode ARGS((DdManager *dd, unsigned int low, unsigned int size, unsigned int type)); +EXTERN DdNode * Cudd_zddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U, DdNode **zdd_I)); +EXTERN DdNode * Cudd_bddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U)); +EXTERN DdNode * Cudd_MakeBddFromZddCover ARGS((DdManager *dd, DdNode *node)); +EXTERN int Cudd_zddDagSize ARGS((DdNode *p_node)); +EXTERN double Cudd_zddCountMinterm ARGS((DdManager *zdd, DdNode *node, int path)); +EXTERN void Cudd_zddPrintSubtable ARGS((DdManager *table)); +EXTERN DdNode * Cudd_zddPortFromBdd ARGS((DdManager *dd, DdNode *B)); +EXTERN DdNode * Cudd_zddPortToBdd ARGS((DdManager *dd, DdNode *f)); +EXTERN int Cudd_zddReduceHeap ARGS((DdManager *table, Cudd_ReorderingType heuristic, int minsize)); +EXTERN int Cudd_zddShuffleHeap ARGS((DdManager *table, int *permutation)); +EXTERN DdNode * Cudd_zddIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); +EXTERN DdNode * Cudd_zddUnion ARGS((DdManager *dd, DdNode *P, DdNode *Q)); +EXTERN DdNode * Cudd_zddIntersect ARGS((DdManager *dd, DdNode *P, DdNode *Q)); +EXTERN DdNode * Cudd_zddDiff ARGS((DdManager *dd, DdNode *P, DdNode *Q)); +EXTERN DdNode * Cudd_zddDiffConst ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); +EXTERN DdNode * Cudd_zddSubset1 ARGS((DdManager *dd, DdNode *P, int var)); +EXTERN DdNode * Cudd_zddSubset0 ARGS((DdManager *dd, DdNode *P, int var)); +EXTERN DdNode * Cudd_zddChange ARGS((DdManager *dd, DdNode *P, int var)); +EXTERN void Cudd_zddSymmProfile ARGS((DdManager *table, int lower, int upper)); +EXTERN int Cudd_zddPrintMinterm ARGS((DdManager *zdd, DdNode *node)); +EXTERN int Cudd_zddPrintCover ARGS((DdManager *zdd, DdNode *node)); +EXTERN int Cudd_zddPrintDebug ARGS((DdManager *zdd, DdNode *f, int n, int pr)); +EXTERN DdGen * Cudd_zddFirstPath ARGS((DdManager *zdd, DdNode *f, int **path)); +EXTERN int Cudd_zddNextPath ARGS((DdGen *gen, int **path)); +EXTERN char * Cudd_zddCoverPathToString ARGS((DdManager *zdd, int *path, char *str)); +EXTERN int Cudd_zddDumpDot ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); +EXTERN int Cudd_bddSetPiVar ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddSetPsVar ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddSetNsVar ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddIsPiVar ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddIsPsVar ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddIsNsVar ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddSetPairIndex ARGS((DdManager *dd, int index, int pairIndex)); +EXTERN int Cudd_bddReadPairIndex ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddSetVarToBeGrouped ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddSetVarHardGroup ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddResetVarToBeGrouped ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddIsVarToBeGrouped ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddSetVarToBeUngrouped ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddIsVarToBeUngrouped ARGS((DdManager *dd, int index)); +EXTERN int Cudd_bddIsVarHardGroup ARGS((DdManager *dd, int index)); + +/**AutomaticEnd***************************************************************/ + +#endif /* _CUDD */ diff --git a/abc70930/src/bdd/cudd/cudd.make b/abc70930/src/bdd/cudd/cudd.make new file mode 100644 index 00000000..7cb342a2 --- /dev/null +++ b/abc70930/src/bdd/cudd/cudd.make @@ -0,0 +1,42 @@ +CSRC += cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \ + cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \ + cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c\ + cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \ + cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c cuddExact.c \ + cuddExport.c cuddGenCof.c cuddGenetic.c \ + cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \ + cuddLCache.c cuddLevelQ.c \ + cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \ + cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \ + cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \ + cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \ + cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c cuddZddPort.c \ + cuddZddReord.c cuddZddSetop.c cuddZddSymm.c cuddZddUtil.c + +HEADERS += cudd.h cuddInt.h +MISC += testcudd.c r7x8.1.mat doc/cudd.ps doc/cuddAllAbs.html doc/cuddAllDet.html \ + doc/cuddExtAbs.html doc/cuddExtDet.html doc/cuddIntro.css \ + doc/cuddIntro.html doc/footnode.html doc/img1.gif doc/img2.gif \ + doc/img3.gif doc/img4.gif doc/img5.gif doc/index.html \ + doc/node1.html doc/node2.html doc/node3.html doc/node4.html \ + doc/node5.html doc/node6.html doc/node7.html doc/node8.html \ + doc/icons/change_begin.gif \ + doc/icons/change_delete.gif \ + doc/icons/change_end.gif \ + doc/icons/contents_motif.gif \ + doc/icons/cross_ref_motif.gif \ + doc/icons/foot_motif.gif \ + doc/icons/image.gif \ + doc/icons/index_motif.gif \ + doc/icons/next_group_motif.gif \ + doc/icons/next_group_motif_gr.gif \ + doc/icons/next_motif.gif \ + doc/icons/next_motif_gr.gif \ + doc/icons/previous_group_motif.gif \ + doc/icons/previous_group_motif_gr.gif \ + doc/icons/previous_motif.gif \ + doc/icons/previous_motif_gr.gif \ + doc/icons/up_motif.gif \ + doc/icons/up_motif_gr.gif + +DEPENDENCYFILES = $(CSRC) diff --git a/abc70930/src/bdd/cudd/cuddAPI.c b/abc70930/src/bdd/cudd/cuddAPI.c new file mode 100644 index 00000000..a16b82cf --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddAPI.c @@ -0,0 +1,4409 @@ +/**CFile*********************************************************************** + + FileName [cuddAPI.c] + + PackageName [cudd] + + Synopsis [Application interface functions.] + + Description [External procedures included in this module: +

    +
  • Cudd_addNewVar() +
  • Cudd_addNewVarAtLevel() +
  • Cudd_bddNewVar() +
  • Cudd_bddNewVarAtLevel() +
  • Cudd_addIthVar() +
  • Cudd_bddIthVar() +
  • Cudd_zddIthVar() +
  • Cudd_zddVarsFromBddVars() +
  • Cudd_addConst() +
  • Cudd_IsNonConstant() +
  • Cudd_AutodynEnable() +
  • Cudd_AutodynDisable() +
  • Cudd_ReorderingStatus() +
  • Cudd_AutodynEnableZdd() +
  • Cudd_AutodynDisableZdd() +
  • Cudd_ReorderingStatusZdd() +
  • Cudd_zddRealignmentEnabled() +
  • Cudd_zddRealignEnable() +
  • Cudd_zddRealignDisable() +
  • Cudd_bddRealignmentEnabled() +
  • Cudd_bddRealignEnable() +
  • Cudd_bddRealignDisable() +
  • Cudd_ReadOne() +
  • Cudd_ReadZddOne() +
  • Cudd_ReadZero() +
  • Cudd_ReadLogicZero() +
  • Cudd_ReadPlusInfinity() +
  • Cudd_ReadMinusInfinity() +
  • Cudd_ReadBackground() +
  • Cudd_SetBackground() +
  • Cudd_ReadCacheSlots() +
  • Cudd_ReadCacheUsedSlots() +
  • Cudd_ReadCacheLookUps() +
  • Cudd_ReadCacheHits() +
  • Cudd_ReadMinHit() +
  • Cudd_SetMinHit() +
  • Cudd_ReadLooseUpTo() +
  • Cudd_SetLooseUpTo() +
  • Cudd_ReadMaxCache() +
  • Cudd_ReadMaxCacheHard() +
  • Cudd_SetMaxCacheHard() +
  • Cudd_ReadSize() +
  • Cudd_ReadSlots() +
  • Cudd_ReadUsedSlots() +
  • Cudd_ExpectedUsedSlots() +
  • Cudd_ReadKeys() +
  • Cudd_ReadDead() +
  • Cudd_ReadMinDead() +
  • Cudd_ReadReorderings() +
  • Cudd_ReadReorderingTime() +
  • Cudd_ReadGarbageCollections() +
  • Cudd_ReadGarbageCollectionTime() +
  • Cudd_ReadNodesFreed() +
  • Cudd_ReadNodesDropped() +
  • Cudd_ReadUniqueLookUps() +
  • Cudd_ReadUniqueLinks() +
  • Cudd_ReadSiftMaxVar() +
  • Cudd_SetSiftMaxVar() +
  • Cudd_ReadMaxGrowth() +
  • Cudd_SetMaxGrowth() +
  • Cudd_ReadMaxGrowthAlternate() +
  • Cudd_SetMaxGrowthAlternate() +
  • Cudd_ReadReorderingCycle() +
  • Cudd_SetReorderingCycle() +
  • Cudd_ReadTree() +
  • Cudd_SetTree() +
  • Cudd_FreeTree() +
  • Cudd_ReadZddTree() +
  • Cudd_SetZddTree() +
  • Cudd_FreeZddTree() +
  • Cudd_NodeReadIndex() +
  • Cudd_ReadPerm() +
  • Cudd_ReadInvPerm() +
  • Cudd_ReadVars() +
  • Cudd_ReadEpsilon() +
  • Cudd_SetEpsilon() +
  • Cudd_ReadGroupCheck() +
  • Cudd_SetGroupcheck() +
  • Cudd_GarbageCollectionEnabled() +
  • Cudd_EnableGarbageCollection() +
  • Cudd_DisableGarbageCollection() +
  • Cudd_DeadAreCounted() +
  • Cudd_TurnOnCountDead() +
  • Cudd_TurnOffCountDead() +
  • Cudd_ReadRecomb() +
  • Cudd_SetRecomb() +
  • Cudd_ReadSymmviolation() +
  • Cudd_SetSymmviolation() +
  • Cudd_ReadArcviolation() +
  • Cudd_SetArcviolation() +
  • Cudd_ReadPopulationSize() +
  • Cudd_SetPopulationSize() +
  • Cudd_ReadNumberXovers() +
  • Cudd_SetNumberXovers() +
  • Cudd_ReadMemoryInUse() +
  • Cudd_PrintInfo() +
  • Cudd_ReadPeakNodeCount() +
  • Cudd_ReadPeakLiveNodeCount() +
  • Cudd_ReadNodeCount() +
  • Cudd_zddReadNodeCount() +
  • Cudd_AddHook() +
  • Cudd_RemoveHook() +
  • Cudd_IsInHook() +
  • Cudd_StdPreReordHook() +
  • Cudd_StdPostReordHook() +
  • Cudd_EnableReorderingReporting() +
  • Cudd_DisableReorderingReporting() +
  • Cudd_ReorderingReporting() +
  • Cudd_ReadErrorCode() +
  • Cudd_ClearErrorCode() +
  • Cudd_ReadStdout() +
  • Cudd_SetStdout() +
  • Cudd_ReadStderr() +
  • Cudd_SetStderr() +
  • Cudd_ReadNextReordering() +
  • Cudd_SetNextReordering() +
  • Cudd_ReadSwapSteps() +
  • Cudd_ReadMaxLive() +
  • Cudd_SetMaxLive() +
  • Cudd_ReadMaxMemory() +
  • Cudd_SetMaxMemory() +
  • Cudd_bddBindVar() +
  • Cudd_bddUnbindVar() +
  • Cudd_bddVarIsBound() +
  • Cudd_bddSetPiVar() +
  • Cudd_bddSetPsVar() +
  • Cudd_bddSetNsVar() +
  • Cudd_bddIsPiVar() +
  • Cudd_bddIsPsVar() +
  • Cudd_bddIsNsVar() +
  • Cudd_bddSetPairIndex() +
  • Cudd_bddReadPairIndex() +
  • Cudd_bddSetVarToBeGrouped() +
  • Cudd_bddSetVarHardGroup() +
  • Cudd_bddResetVarToBeGrouped() +
  • Cudd_bddIsVarToBeGrouped() +
  • Cudd_bddSetVarToBeUngrouped() +
  • Cudd_bddIsVarToBeUngrouped() +
  • Cudd_bddIsVarHardGroup() +
+ Static procedures included in this module: +
    +
  • fixVarTree() +
] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAPI.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void fixVarTree ARGS((MtrNode *treenode, int *perm, int size)); +static int addMultiplicityGroups ARGS((DdManager *dd, MtrNode *treenode, int multiplicity, char *vmask, char *lmask)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Returns a new ADD variable.] + + Description [Creates a new ADD variable. The new variable has an + index equal to the largest previous index plus 1. Returns a + pointer to the new variable if successful; NULL otherwise. + An ADD variable differs from a BDD variable because it points to the + arithmetic zero, instead of having a complement pointer to 1. ] + + SideEffects [None] + + SeeAlso [Cudd_bddNewVar Cudd_addIthVar Cudd_addConst + Cudd_addNewVarAtLevel] + +******************************************************************************/ +DdNode * +Cudd_addNewVar( + DdManager * dd) +{ + DdNode *res; + + if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); + do { + dd->reordered = 0; + res = cuddUniqueInter(dd,dd->size,DD_ONE(dd),DD_ZERO(dd)); + } while (dd->reordered == 1); + + return(res); + +} /* end of Cudd_addNewVar */ + + +/**Function******************************************************************** + + Synopsis [Returns a new ADD variable at a specified level.] + + Description [Creates a new ADD variable. The new variable has an + index equal to the largest previous index plus 1 and is positioned at + the specified level in the order. Returns a pointer to the new + variable if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel] + +******************************************************************************/ +DdNode * +Cudd_addNewVarAtLevel( + DdManager * dd, + int level) +{ + DdNode *res; + + if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); + if (level >= dd->size) return(Cudd_addIthVar(dd,level)); + if (!cuddInsertSubtables(dd,1,level)) return(NULL); + do { + dd->reordered = 0; + res = cuddUniqueInter(dd,dd->size - 1,DD_ONE(dd),DD_ZERO(dd)); + } while (dd->reordered == 1); + + return(res); + +} /* end of Cudd_addNewVarAtLevel */ + + +/**Function******************************************************************** + + Synopsis [Returns a new BDD variable.] + + Description [Creates a new BDD variable. The new variable has an + index equal to the largest previous index plus 1. Returns a + pointer to the new variable if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel] + +******************************************************************************/ +DdNode * +Cudd_bddNewVar( + DdManager * dd) +{ + DdNode *res; + + if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); + res = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one)); + + return(res); + +} /* end of Cudd_bddNewVar */ + + +/**Function******************************************************************** + + Synopsis [Returns a new BDD variable at a specified level.] + + Description [Creates a new BDD variable. The new variable has an + index equal to the largest previous index plus 1 and is positioned at + the specified level in the order. Returns a pointer to the new + variable if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddNewVar Cudd_bddIthVar Cudd_addNewVarAtLevel] + +******************************************************************************/ +DdNode * +Cudd_bddNewVarAtLevel( + DdManager * dd, + int level) +{ + DdNode *res; + + if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); + if (level >= dd->size) return(Cudd_bddIthVar(dd,level)); + if (!cuddInsertSubtables(dd,1,level)) return(NULL); + res = dd->vars[dd->size - 1]; + + return(res); + +} /* end of Cudd_bddNewVarAtLevel */ + + +/**Function******************************************************************** + + Synopsis [Returns the ADD variable with index i.] + + Description [Retrieves the ADD variable with index i if it already + exists, or creates a new ADD variable. Returns a pointer to the + variable if successful; NULL otherwise. An ADD variable differs from + a BDD variable because it points to the arithmetic zero, instead of + having a complement pointer to 1. ] + + SideEffects [None] + + SeeAlso [Cudd_addNewVar Cudd_bddIthVar Cudd_addConst + Cudd_addNewVarAtLevel] + +******************************************************************************/ +DdNode * +Cudd_addIthVar( + DdManager * dd, + int i) +{ + DdNode *res; + + if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); + do { + dd->reordered = 0; + res = cuddUniqueInter(dd,i,DD_ONE(dd),DD_ZERO(dd)); + } while (dd->reordered == 1); + + return(res); + +} /* end of Cudd_addIthVar */ + + +/**Function******************************************************************** + + Synopsis [Returns the BDD variable with index i.] + + Description [Retrieves the BDD variable with index i if it already + exists, or creates a new BDD variable. Returns a pointer to the + variable if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel + Cudd_ReadVars] + +******************************************************************************/ +DdNode * +Cudd_bddIthVar( + DdManager * dd, + int i) +{ + DdNode *res; + + if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); + if (i < dd->size) { + res = dd->vars[i]; + } else { + res = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); + } + + return(res); + +} /* end of Cudd_bddIthVar */ + + +/**Function******************************************************************** + + Synopsis [Returns the ZDD variable with index i.] + + Description [Retrieves the ZDD variable with index i if it already + exists, or creates a new ZDD variable. Returns a pointer to the + variable if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddIthVar Cudd_addIthVar] + +******************************************************************************/ +DdNode * +Cudd_zddIthVar( + DdManager * dd, + int i) +{ + DdNode *res; + DdNode *zvar; + DdNode *lower; + int j; + + if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); + + /* The i-th variable function has the following structure: + ** at the level corresponding to index i there is a node whose "then" + ** child points to the universe, and whose "else" child points to zero. + ** Above that level there are nodes with identical children. + */ + + /* First we build the node at the level of index i. */ + lower = (i < dd->sizeZ - 1) ? dd->univ[dd->permZ[i]+1] : DD_ONE(dd); + do { + dd->reordered = 0; + zvar = cuddUniqueInterZdd(dd, i, lower, DD_ZERO(dd)); + } while (dd->reordered == 1); + + if (zvar == NULL) + return(NULL); + cuddRef(zvar); + + /* Now we add the "filler" nodes above the level of index i. */ + for (j = dd->permZ[i] - 1; j >= 0; j--) { + do { + dd->reordered = 0; + res = cuddUniqueInterZdd(dd, dd->invpermZ[j], zvar, zvar); + } while (dd->reordered == 1); + if (res == NULL) { + Cudd_RecursiveDerefZdd(dd,zvar); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDerefZdd(dd,zvar); + zvar = res; + } + cuddDeref(zvar); + return(zvar); + +} /* end of Cudd_zddIthVar */ + + +/**Function******************************************************************** + + Synopsis [Creates one or more ZDD variables for each BDD variable.] + + Description [Creates one or more ZDD variables for each BDD + variable. If some ZDD variables already exist, only the missing + variables are created. Parameter multiplicity allows the caller to + control how many variables are created for each BDD variable in + existence. For instance, if ZDDs are used to represent covers, two + ZDD variables are required for each BDD variable. The order of the + BDD variables is transferred to the ZDD variables. If a variable + group tree exists for the BDD variables, a corresponding ZDD + variable group tree is created by expanding the BDD variable + tree. In any case, the ZDD variables derived from the same BDD + variable are merged in a ZDD variable group. If a ZDD variable group + tree exists, it is freed. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel] + +******************************************************************************/ +int +Cudd_zddVarsFromBddVars( + DdManager * dd /* DD manager */, + int multiplicity /* how many ZDD variables are created for each BDD variable */) +{ + int res; + int i, j; + int allnew; + int *permutation; + + if (multiplicity < 1) return(0); + allnew = dd->sizeZ == 0; + if (dd->size * multiplicity > dd->sizeZ) { + res = cuddResizeTableZdd(dd,dd->size * multiplicity - 1); + if (res == 0) return(0); + } + /* Impose the order of the BDD variables to the ZDD variables. */ + if (allnew) { + for (i = 0; i < dd->size; i++) { + for (j = 0; j < multiplicity; j++) { + dd->permZ[i * multiplicity + j] = + dd->perm[i] * multiplicity + j; + dd->invpermZ[dd->permZ[i * multiplicity + j]] = + i * multiplicity + j; + } + } + for (i = 0; i < dd->sizeZ; i++) { + dd->univ[i]->index = dd->invpermZ[i]; + } + } else { + permutation = ALLOC(int,dd->sizeZ); + if (permutation == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (i = 0; i < dd->size; i++) { + for (j = 0; j < multiplicity; j++) { + permutation[i * multiplicity + j] = + dd->invperm[i] * multiplicity + j; + } + } + for (i = dd->size * multiplicity; i < dd->sizeZ; i++) { + permutation[i] = i; + } + res = Cudd_zddShuffleHeap(dd, permutation); + FREE(permutation); + if (res == 0) return(0); + } + /* Copy and expand the variable group tree if it exists. */ + if (dd->treeZ != NULL) { + Cudd_FreeZddTree(dd); + } + if (dd->tree != NULL) { + dd->treeZ = Mtr_CopyTree(dd->tree, multiplicity); + if (dd->treeZ == NULL) return(0); + } else if (multiplicity > 1) { + dd->treeZ = Mtr_InitGroupTree(0, dd->sizeZ); + if (dd->treeZ == NULL) return(0); + dd->treeZ->index = dd->invpermZ[0]; + } + /* Create groups for the ZDD variables derived from the same BDD variable. + */ + if (multiplicity > 1) { + char *vmask, *lmask; + + vmask = ALLOC(char, dd->size); + if (vmask == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + lmask = ALLOC(char, dd->size); + if (lmask == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (i = 0; i < dd->size; i++) { + vmask[i] = lmask[i] = 0; + } + res = addMultiplicityGroups(dd,dd->treeZ,multiplicity,vmask,lmask); + FREE(vmask); + FREE(lmask); + if (res == 0) return(0); + } + return(1); + +} /* end of Cudd_zddVarsFromBddVars */ + + +/**Function******************************************************************** + + Synopsis [Returns the ADD for constant c.] + + Description [Retrieves the ADD for constant c if it already + exists, or creates a new ADD. Returns a pointer to the + ADD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addNewVar Cudd_addIthVar] + +******************************************************************************/ +DdNode * +Cudd_addConst( + DdManager * dd, + CUDD_VALUE_TYPE c) +{ + return(cuddUniqueConst(dd,c)); + +} /* end of Cudd_addConst */ + + +/**Function******************************************************************** + + Synopsis [Returns 1 if a DD node is not constant.] + + Description [Returns 1 if a DD node is not constant. This function is + useful to test the results of Cudd_bddIteConstant, Cudd_addIteConstant, + Cudd_addEvalConst. These results may be a special value signifying + non-constant. In the other cases the macro Cudd_IsConstant can be used.] + + SideEffects [None] + + SeeAlso [Cudd_IsConstant Cudd_bddIteConstant Cudd_addIteConstant + Cudd_addEvalConst] + +******************************************************************************/ +int +Cudd_IsNonConstant( + DdNode *f) +{ + return(f == DD_NON_CONSTANT || !Cudd_IsConstant(f)); + +} /* end of Cudd_IsNonConstant */ + + +/**Function******************************************************************** + + Synopsis [Enables automatic dynamic reordering of BDDs and ADDs.] + + Description [Enables automatic dynamic reordering of BDDs and + ADDs. Parameter method is used to determine the method used for + reordering. If CUDD_REORDER_SAME is passed, the method is + unchanged.] + + SideEffects [None] + + SeeAlso [Cudd_AutodynDisable Cudd_ReorderingStatus + Cudd_AutodynEnableZdd] + +******************************************************************************/ +void +Cudd_AutodynEnable( + DdManager * unique, + Cudd_ReorderingType method) +{ + unique->autoDyn = 1; + if (method != CUDD_REORDER_SAME) { + unique->autoMethod = method; + } +#ifndef DD_NO_DEATH_ROW + /* If reordering is enabled, using the death row causes too many + ** invocations. Hence, we shrink the death row to just one entry. + */ + cuddClearDeathRow(unique); + unique->deathRowDepth = 1; + unique->deadMask = unique->deathRowDepth - 1; + if ((unsigned) unique->nextDead > unique->deadMask) { + unique->nextDead = 0; + } + unique->deathRow = REALLOC(DdNodePtr, unique->deathRow, + unique->deathRowDepth); +#endif + return; + +} /* end of Cudd_AutodynEnable */ + + +/**Function******************************************************************** + + Synopsis [Disables automatic dynamic reordering.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_AutodynEnable Cudd_ReorderingStatus + Cudd_AutodynDisableZdd] + +******************************************************************************/ +void +Cudd_AutodynDisable( + DdManager * unique) +{ + unique->autoDyn = 0; + return; + +} /* end of Cudd_AutodynDisable */ + + +/**Function******************************************************************** + + Synopsis [Reports the status of automatic dynamic reordering of BDDs + and ADDs.] + + Description [Reports the status of automatic dynamic reordering of + BDDs and ADDs. Parameter method is set to the reordering method + currently selected. Returns 1 if automatic reordering is enabled; 0 + otherwise.] + + SideEffects [Parameter method is set to the reordering method currently + selected.] + + SeeAlso [Cudd_AutodynEnable Cudd_AutodynDisable + Cudd_ReorderingStatusZdd] + +******************************************************************************/ +int +Cudd_ReorderingStatus( + DdManager * unique, + Cudd_ReorderingType * method) +{ + *method = unique->autoMethod; + return(unique->autoDyn); + +} /* end of Cudd_ReorderingStatus */ + + +/**Function******************************************************************** + + Synopsis [Enables automatic dynamic reordering of ZDDs.] + + Description [Enables automatic dynamic reordering of ZDDs. Parameter + method is used to determine the method used for reordering ZDDs. If + CUDD_REORDER_SAME is passed, the method is unchanged.] + + SideEffects [None] + + SeeAlso [Cudd_AutodynDisableZdd Cudd_ReorderingStatusZdd + Cudd_AutodynEnable] + +******************************************************************************/ +void +Cudd_AutodynEnableZdd( + DdManager * unique, + Cudd_ReorderingType method) +{ + unique->autoDynZ = 1; + if (method != CUDD_REORDER_SAME) { + unique->autoMethodZ = method; + } + return; + +} /* end of Cudd_AutodynEnableZdd */ + + +/**Function******************************************************************** + + Synopsis [Disables automatic dynamic reordering of ZDDs.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_AutodynEnableZdd Cudd_ReorderingStatusZdd + Cudd_AutodynDisable] + +******************************************************************************/ +void +Cudd_AutodynDisableZdd( + DdManager * unique) +{ + unique->autoDynZ = 0; + return; + +} /* end of Cudd_AutodynDisableZdd */ + + +/**Function******************************************************************** + + Synopsis [Reports the status of automatic dynamic reordering of ZDDs.] + + Description [Reports the status of automatic dynamic reordering of + ZDDs. Parameter method is set to the ZDD reordering method currently + selected. Returns 1 if automatic reordering is enabled; 0 + otherwise.] + + SideEffects [Parameter method is set to the ZDD reordering method currently + selected.] + + SeeAlso [Cudd_AutodynEnableZdd Cudd_AutodynDisableZdd + Cudd_ReorderingStatus] + +******************************************************************************/ +int +Cudd_ReorderingStatusZdd( + DdManager * unique, + Cudd_ReorderingType * method) +{ + *method = unique->autoMethodZ; + return(unique->autoDynZ); + +} /* end of Cudd_ReorderingStatusZdd */ + + +/**Function******************************************************************** + + Synopsis [Tells whether the realignment of ZDD order to BDD order is + enabled.] + + Description [Returns 1 if the realignment of ZDD order to BDD order is + enabled; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddRealignEnable Cudd_zddRealignDisable + Cudd_bddRealignEnable Cudd_bddRealignDisable] + +******************************************************************************/ +int +Cudd_zddRealignmentEnabled( + DdManager * unique) +{ + return(unique->realign); + +} /* end of Cudd_zddRealignmentEnabled */ + + +/**Function******************************************************************** + + Synopsis [Enables realignment of ZDD order to BDD order.] + + Description [Enables realignment of the ZDD variable order to the + BDD variable order after the BDDs and ADDs have been reordered. The + number of ZDD variables must be a multiple of the number of BDD + variables for realignment to make sense. If this condition is not met, + Cudd_ReduceHeap will return 0. Let M be the + ratio of the two numbers. For the purpose of realignment, the ZDD + variables from M*i to (M+1)*i-1 are + reagarded as corresponding to BDD variable i. Realignment + is initially disabled.] + + SideEffects [None] + + SeeAlso [Cudd_ReduceHeap Cudd_zddRealignDisable + Cudd_zddRealignmentEnabled Cudd_bddRealignDisable + Cudd_bddRealignmentEnabled] + +******************************************************************************/ +void +Cudd_zddRealignEnable( + DdManager * unique) +{ + unique->realign = 1; + return; + +} /* end of Cudd_zddRealignEnable */ + + +/**Function******************************************************************** + + Synopsis [Disables realignment of ZDD order to BDD order.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_zddRealignEnable Cudd_zddRealignmentEnabled + Cudd_bddRealignEnable Cudd_bddRealignmentEnabled] + +******************************************************************************/ +void +Cudd_zddRealignDisable( + DdManager * unique) +{ + unique->realign = 0; + return; + +} /* end of Cudd_zddRealignDisable */ + + +/**Function******************************************************************** + + Synopsis [Tells whether the realignment of BDD order to ZDD order is + enabled.] + + Description [Returns 1 if the realignment of BDD order to ZDD order is + enabled; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddRealignEnable Cudd_bddRealignDisable + Cudd_zddRealignEnable Cudd_zddRealignDisable] + +******************************************************************************/ +int +Cudd_bddRealignmentEnabled( + DdManager * unique) +{ + return(unique->realignZ); + +} /* end of Cudd_bddRealignmentEnabled */ + + +/**Function******************************************************************** + + Synopsis [Enables realignment of BDD order to ZDD order.] + + Description [Enables realignment of the BDD variable order to the + ZDD variable order after the ZDDs have been reordered. The + number of ZDD variables must be a multiple of the number of BDD + variables for realignment to make sense. If this condition is not met, + Cudd_zddReduceHeap will return 0. Let M be the + ratio of the two numbers. For the purpose of realignment, the ZDD + variables from M*i to (M+1)*i-1 are + reagarded as corresponding to BDD variable i. Realignment + is initially disabled.] + + SideEffects [None] + + SeeAlso [Cudd_zddReduceHeap Cudd_bddRealignDisable + Cudd_bddRealignmentEnabled Cudd_zddRealignDisable + Cudd_zddRealignmentEnabled] + +******************************************************************************/ +void +Cudd_bddRealignEnable( + DdManager * unique) +{ + unique->realignZ = 1; + return; + +} /* end of Cudd_bddRealignEnable */ + + +/**Function******************************************************************** + + Synopsis [Disables realignment of ZDD order to BDD order.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_bddRealignEnable Cudd_bddRealignmentEnabled + Cudd_zddRealignEnable Cudd_zddRealignmentEnabled] + +******************************************************************************/ +void +Cudd_bddRealignDisable( + DdManager * unique) +{ + unique->realignZ = 0; + return; + +} /* end of Cudd_bddRealignDisable */ + + +/**Function******************************************************************** + + Synopsis [Returns the one constant of the manager.] + + Description [Returns the one constant of the manager. The one + constant is common to ADDs and BDDs.] + + SideEffects [None] + + SeeAlso [Cudd_ReadZero Cudd_ReadLogicZero Cudd_ReadZddOne] + +******************************************************************************/ +DdNode * +Cudd_ReadOne( + DdManager * dd) +{ + return(dd->one); + +} /* end of Cudd_ReadOne */ + + +/**Function******************************************************************** + + Synopsis [Returns the ZDD for the constant 1 function.] + + Description [Returns the ZDD for the constant 1 function. + The representation of the constant 1 function as a ZDD depends on + how many variables it (nominally) depends on. The index of the + topmost variable in the support is given as argument i.] + + SideEffects [None] + + SeeAlso [Cudd_ReadOne] + +******************************************************************************/ +DdNode * +Cudd_ReadZddOne( + DdManager * dd, + int i) +{ + if (i < 0) + return(NULL); + return(i < dd->sizeZ ? dd->univ[i] : DD_ONE(dd)); + +} /* end of Cudd_ReadZddOne */ + + + +/**Function******************************************************************** + + Synopsis [Returns the zero constant of the manager.] + + Description [Returns the zero constant of the manager. The zero + constant is the arithmetic zero, rather than the logic zero. The + latter is the complement of the one constant.] + + SideEffects [None] + + SeeAlso [Cudd_ReadOne Cudd_ReadLogicZero] + +******************************************************************************/ +DdNode * +Cudd_ReadZero( + DdManager * dd) +{ + return(DD_ZERO(dd)); + +} /* end of Cudd_ReadZero */ + + +/**Function******************************************************************** + + Synopsis [Returns the logic zero constant of the manager.] + + Description [Returns the zero constant of the manager. The logic zero + constant is the complement of the one constant, and is distinct from + the arithmetic zero.] + + SideEffects [None] + + SeeAlso [Cudd_ReadOne Cudd_ReadZero] + +******************************************************************************/ +DdNode * +Cudd_ReadLogicZero( + DdManager * dd) +{ + return(Cudd_Not(DD_ONE(dd))); + +} /* end of Cudd_ReadLogicZero */ + + +/**Function******************************************************************** + + Synopsis [Reads the plus-infinity constant from the manager.] + + Description [] + + SideEffects [None] + +******************************************************************************/ +DdNode * +Cudd_ReadPlusInfinity( + DdManager * dd) +{ + return(dd->plusinfinity); + +} /* end of Cudd_ReadPlusInfinity */ + + +/**Function******************************************************************** + + Synopsis [Reads the minus-infinity constant from the manager.] + + Description [] + + SideEffects [None] + +******************************************************************************/ +DdNode * +Cudd_ReadMinusInfinity( + DdManager * dd) +{ + return(dd->minusinfinity); + +} /* end of Cudd_ReadMinusInfinity */ + + +/**Function******************************************************************** + + Synopsis [Reads the background constant of the manager.] + + Description [] + + SideEffects [None] + +******************************************************************************/ +DdNode * +Cudd_ReadBackground( + DdManager * dd) +{ + return(dd->background); + +} /* end of Cudd_ReadBackground */ + + +/**Function******************************************************************** + + Synopsis [Sets the background constant of the manager.] + + Description [Sets the background constant of the manager. It assumes + that the DdNode pointer bck is already referenced.] + + SideEffects [None] + +******************************************************************************/ +void +Cudd_SetBackground( + DdManager * dd, + DdNode * bck) +{ + dd->background = bck; + +} /* end of Cudd_SetBackground */ + + +/**Function******************************************************************** + + Synopsis [Reads the number of slots in the cache.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_ReadCacheUsedSlots] + +******************************************************************************/ +unsigned int +Cudd_ReadCacheSlots( + DdManager * dd) +{ + return(dd->cacheSlots); + +} /* end of Cudd_ReadCacheSlots */ + + +/**Function******************************************************************** + + Synopsis [Reads the fraction of used slots in the cache.] + + Description [Reads the fraction of used slots in the cache. The unused + slots are those in which no valid data is stored. Garbage collection, + variable reordering, and cache resizing may cause used slots to become + unused.] + + SideEffects [None] + + SeeAlso [Cudd_ReadCacheSlots] + +******************************************************************************/ +double +Cudd_ReadCacheUsedSlots( + DdManager * dd) +{ + unsigned long used = 0; + int slots = dd->cacheSlots; + DdCache *cache = dd->cache; + int i; + + for (i = 0; i < slots; i++) { + used += cache[i].h != 0; + } + + return((double)used / (double) dd->cacheSlots); + +} /* end of Cudd_ReadCacheUsedSlots */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of cache look-ups.] + + Description [Returns the number of cache look-ups.] + + SideEffects [None] + + SeeAlso [Cudd_ReadCacheHits] + +******************************************************************************/ +double +Cudd_ReadCacheLookUps( + DdManager * dd) +{ + return(dd->cacheHits + dd->cacheMisses + + dd->totCachehits + dd->totCacheMisses); + +} /* end of Cudd_ReadCacheLookUps */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of cache hits.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_ReadCacheLookUps] + +******************************************************************************/ +double +Cudd_ReadCacheHits( + DdManager * dd) +{ + return(dd->cacheHits + dd->totCachehits); + +} /* end of Cudd_ReadCacheHits */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of recursive calls.] + + Description [Returns the number of recursive calls if the package is + compiled with DD_COUNT defined.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +double +Cudd_ReadRecursiveCalls( + DdManager * dd) +{ +#ifdef DD_COUNT + return(dd->recursiveCalls); +#else + return(-1.0); +#endif + +} /* end of Cudd_ReadRecursiveCalls */ + + + +/**Function******************************************************************** + + Synopsis [Reads the hit rate that causes resizinig of the computed + table.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_SetMinHit] + +******************************************************************************/ +unsigned int +Cudd_ReadMinHit( + DdManager * dd) +{ + /* Internally, the package manipulates the ratio of hits to + ** misses instead of the ratio of hits to accesses. */ + return((unsigned int) (0.5 + 100 * dd->minHit / (1 + dd->minHit))); + +} /* end of Cudd_ReadMinHit */ + + +/**Function******************************************************************** + + Synopsis [Sets the hit rate that causes resizinig of the computed + table.] + + Description [Sets the minHit parameter of the manager. This + parameter controls the resizing of the computed table. If the hit + rate is larger than the specified value, and the cache is not + already too large, then its size is doubled.] + + SideEffects [None] + + SeeAlso [Cudd_ReadMinHit] + +******************************************************************************/ +void +Cudd_SetMinHit( + DdManager * dd, + unsigned int hr) +{ + /* Internally, the package manipulates the ratio of hits to + ** misses instead of the ratio of hits to accesses. */ + dd->minHit = (double) hr / (100.0 - (double) hr); + +} /* end of Cudd_SetMinHit */ + + +/**Function******************************************************************** + + Synopsis [Reads the looseUpTo parameter of the manager.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_SetLooseUpTo Cudd_ReadMinHit Cudd_ReadMinDead] + +******************************************************************************/ +unsigned int +Cudd_ReadLooseUpTo( + DdManager * dd) +{ + return(dd->looseUpTo); + +} /* end of Cudd_ReadLooseUpTo */ + + +/**Function******************************************************************** + + Synopsis [Sets the looseUpTo parameter of the manager.] + + Description [Sets the looseUpTo parameter of the manager. This + parameter of the manager controls the threshold beyond which no fast + growth of the unique table is allowed. The threshold is given as a + number of slots. If the value passed to this function is 0, the + function determines a suitable value based on the available memory.] + + SideEffects [None] + + SeeAlso [Cudd_ReadLooseUpTo Cudd_SetMinHit] + +******************************************************************************/ +void +Cudd_SetLooseUpTo( + DdManager * dd, + unsigned int lut) +{ + if (lut == 0) { + long datalimit = getSoftDataLimit(); + lut = (unsigned int) (datalimit / (sizeof(DdNode) * + DD_MAX_LOOSE_FRACTION)); + } + dd->looseUpTo = lut; + +} /* end of Cudd_SetLooseUpTo */ + + +/**Function******************************************************************** + + Synopsis [Returns the soft limit for the cache size.] + + Description [Returns the soft limit for the cache size. The soft limit] + + SideEffects [None] + + SeeAlso [Cudd_ReadMaxCache] + +******************************************************************************/ +unsigned int +Cudd_ReadMaxCache( + DdManager * dd) +{ + return(2 * dd->cacheSlots + dd->cacheSlack); + +} /* end of Cudd_ReadMaxCache */ + + +/**Function******************************************************************** + + Synopsis [Reads the maxCacheHard parameter of the manager.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_SetMaxCacheHard Cudd_ReadMaxCache] + +******************************************************************************/ +unsigned int +Cudd_ReadMaxCacheHard( + DdManager * dd) +{ + return(dd->maxCacheHard); + +} /* end of Cudd_ReadMaxCache */ + + +/**Function******************************************************************** + + Synopsis [Sets the maxCacheHard parameter of the manager.] + + Description [Sets the maxCacheHard parameter of the manager. The + cache cannot grow larger than maxCacheHard entries. This parameter + allows an application to control the trade-off of memory versus + speed. If the value passed to this function is 0, the function + determines a suitable maximum cache size based on the available memory.] + + SideEffects [None] + + SeeAlso [Cudd_ReadMaxCacheHard Cudd_SetMaxCache] + +******************************************************************************/ +void +Cudd_SetMaxCacheHard( + DdManager * dd, + unsigned int mc) +{ + if (mc == 0) { + long datalimit = getSoftDataLimit(); + mc = (unsigned int) (datalimit / (sizeof(DdCache) * + DD_MAX_CACHE_FRACTION)); + } + dd->maxCacheHard = mc; + +} /* end of Cudd_SetMaxCacheHard */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of BDD variables in existance.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_ReadZddSize] + +******************************************************************************/ +int +Cudd_ReadSize( + DdManager * dd) +{ + return(dd->size); + +} /* end of Cudd_ReadSize */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of ZDD variables in existance.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_ReadSize] + +******************************************************************************/ +int +Cudd_ReadZddSize( + DdManager * dd) +{ + return(dd->sizeZ); + +} /* end of Cudd_ReadZddSize */ + + +/**Function******************************************************************** + + Synopsis [Returns the total number of slots of the unique table.] + + Description [Returns the total number of slots of the unique table. + This number ismainly for diagnostic purposes.] + + SideEffects [None] + +******************************************************************************/ +unsigned int +Cudd_ReadSlots( + DdManager * dd) +{ + return(dd->slots); + +} /* end of Cudd_ReadSlots */ + + +/**Function******************************************************************** + + Synopsis [Reads the fraction of used slots in the unique table.] + + Description [Reads the fraction of used slots in the unique + table. The unused slots are those in which no valid data is + stored. Garbage collection, variable reordering, and subtable + resizing may cause used slots to become unused.] + + SideEffects [None] + + SeeAlso [Cudd_ReadSlots] + +******************************************************************************/ +double +Cudd_ReadUsedSlots( + DdManager * dd) +{ + unsigned long used = 0; + int i, j; + int size = dd->size; + DdNodePtr *nodelist; + DdSubtable *subtable; + DdNode *node; + DdNode *sentinel = &(dd->sentinel); + + /* Scan each BDD/ADD subtable. */ + for (i = 0; i < size; i++) { + subtable = &(dd->subtables[i]); + nodelist = subtable->nodelist; + for (j = 0; (unsigned) j < subtable->slots; j++) { + node = nodelist[j]; + if (node != sentinel) { + used++; + } + } + } + + /* Scan the ZDD subtables. */ + size = dd->sizeZ; + + for (i = 0; i < size; i++) { + subtable = &(dd->subtableZ[i]); + nodelist = subtable->nodelist; + for (j = 0; (unsigned) j < subtable->slots; j++) { + node = nodelist[j]; + if (node != NULL) { + used++; + } + } + } + + /* Constant table. */ + subtable = &(dd->constants); + nodelist = subtable->nodelist; + for (j = 0; (unsigned) j < subtable->slots; j++) { + node = nodelist[j]; + if (node != NULL) { + used++; + } + } + + return((double)used / (double) dd->slots); + +} /* end of Cudd_ReadUsedSlots */ + + +/**Function******************************************************************** + + Synopsis [Computes the expected fraction of used slots in the unique + table.] + + Description [Computes the fraction of slots in the unique table that + should be in use. This expected value is based on the assumption + that the hash function distributes the keys randomly; it can be + compared with the result of Cudd_ReadUsedSlots to monitor the + performance of the unique table hash function.] + + SideEffects [None] + + SeeAlso [Cudd_ReadSlots Cudd_ReadUsedSlots] + +******************************************************************************/ +double +Cudd_ExpectedUsedSlots( + DdManager * dd) +{ + int i; + int size = dd->size; + DdSubtable *subtable; + double empty = 0.0; + + /* To each subtable we apply the corollary to Theorem 8.5 (occupancy + ** distribution) from Sedgewick and Flajolet's Analysis of Algorithms. + ** The corollary says that for a a table with M buckets and a load ratio + ** of r, the expected number of empty buckets is asymptotically given + ** by M * exp(-r). + */ + + /* Scan each BDD/ADD subtable. */ + for (i = 0; i < size; i++) { + subtable = &(dd->subtables[i]); + empty += (double) subtable->slots * + exp(-(double) subtable->keys / (double) subtable->slots); + } + + /* Scan the ZDD subtables. */ + size = dd->sizeZ; + + for (i = 0; i < size; i++) { + subtable = &(dd->subtableZ[i]); + empty += (double) subtable->slots * + exp(-(double) subtable->keys / (double) subtable->slots); + } + + /* Constant table. */ + subtable = &(dd->constants); + empty += (double) subtable->slots * + exp(-(double) subtable->keys / (double) subtable->slots); + + return(1.0 - empty / (double) dd->slots); + +} /* end of Cudd_ExpectedUsedSlots */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of nodes in the unique table.] + + Description [Returns the total number of nodes currently in the unique + table, including the dead nodes.] + + SideEffects [None] + + SeeAlso [Cudd_ReadDead] + +******************************************************************************/ +unsigned int +Cudd_ReadKeys( + DdManager * dd) +{ + return(dd->keys); + +} /* end of Cudd_ReadKeys */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of dead nodes in the unique table.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_ReadKeys] + +******************************************************************************/ +unsigned int +Cudd_ReadDead( + DdManager * dd) +{ + return(dd->dead); + +} /* end of Cudd_ReadDead */ + + +/**Function******************************************************************** + + Synopsis [Reads the minDead parameter of the manager.] + + Description [Reads the minDead parameter of the manager. The minDead + parameter is used by the package to decide whether to collect garbage + or resize a subtable of the unique table when the subtable becomes + too full. The application can indirectly control the value of minDead + by setting the looseUpTo parameter.] + + SideEffects [None] + + SeeAlso [Cudd_ReadDead Cudd_ReadLooseUpTo Cudd_SetLooseUpTo] + +******************************************************************************/ +unsigned int +Cudd_ReadMinDead( + DdManager * dd) +{ + return(dd->minDead); + +} /* end of Cudd_ReadMinDead */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of times reordering has occurred.] + + Description [Returns the number of times reordering has occurred in the + manager. The number includes both the calls to Cudd_ReduceHeap from + the application program and those automatically performed by the + package. However, calls that do not even initiate reordering are not + counted. A call may not initiate reordering if there are fewer than + minsize live nodes in the manager, or if CUDD_REORDER_NONE is specified + as reordering method. The calls to Cudd_ShuffleHeap are not counted.] + + SideEffects [None] + + SeeAlso [Cudd_ReduceHeap Cudd_ReadReorderingTime] + +******************************************************************************/ +int +Cudd_ReadReorderings( + DdManager * dd) +{ + return(dd->reorderings); + +} /* end of Cudd_ReadReorderings */ + + +/**Function******************************************************************** + + Synopsis [Returns the time spent in reordering.] + + Description [Returns the number of milliseconds spent reordering + variables since the manager was initialized. The time spent in collecting + garbage before reordering is included.] + + SideEffects [None] + + SeeAlso [Cudd_ReadReorderings] + +******************************************************************************/ +long +Cudd_ReadReorderingTime( + DdManager * dd) +{ + return(dd->reordTime); + +} /* end of Cudd_ReadReorderingTime */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of times garbage collection has occurred.] + + Description [Returns the number of times garbage collection has + occurred in the manager. The number includes both the calls from + reordering procedures and those caused by requests to create new + nodes.] + + SideEffects [None] + + SeeAlso [Cudd_ReadGarbageCollectionTime] + +******************************************************************************/ +int +Cudd_ReadGarbageCollections( + DdManager * dd) +{ + return(dd->garbageCollections); + +} /* end of Cudd_ReadGarbageCollections */ + + +/**Function******************************************************************** + + Synopsis [Returns the time spent in garbage collection.] + + Description [Returns the number of milliseconds spent doing garbage + collection since the manager was initialized.] + + SideEffects [None] + + SeeAlso [Cudd_ReadGarbageCollections] + +******************************************************************************/ +long +Cudd_ReadGarbageCollectionTime( + DdManager * dd) +{ + return(dd->GCTime); + +} /* end of Cudd_ReadGarbageCollectionTime */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of nodes freed.] + + Description [Returns the number of nodes returned to the free list if the + keeping of this statistic is enabled; -1 otherwise. This statistic is + enabled only if the package is compiled with DD_STATS defined.] + + SideEffects [None] + + SeeAlso [Cudd_ReadNodesDropped] + +******************************************************************************/ +double +Cudd_ReadNodesFreed( + DdManager * dd) +{ +#ifdef DD_STATS + return(dd->nodesFreed); +#else + return(-1.0); +#endif + +} /* end of Cudd_ReadNodesFreed */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of nodes dropped.] + + Description [Returns the number of nodes killed by dereferencing if the + keeping of this statistic is enabled; -1 otherwise. This statistic is + enabled only if the package is compiled with DD_STATS defined.] + + SideEffects [None] + + SeeAlso [Cudd_ReadNodesFreed] + +******************************************************************************/ +double +Cudd_ReadNodesDropped( + DdManager * dd) +{ +#ifdef DD_STATS + return(dd->nodesDropped); +#else + return(-1.0); +#endif + +} /* end of Cudd_ReadNodesDropped */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of look-ups in the unique table.] + + Description [Returns the number of look-ups in the unique table if the + keeping of this statistic is enabled; -1 otherwise. This statistic is + enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.] + + SideEffects [None] + + SeeAlso [Cudd_ReadUniqueLinks] + +******************************************************************************/ +double +Cudd_ReadUniqueLookUps( + DdManager * dd) +{ +#ifdef DD_UNIQUE_PROFILE + return(dd->uniqueLookUps); +#else + return(-1.0); +#endif + +} /* end of Cudd_ReadUniqueLookUps */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of links followed in the unique table.] + + Description [Returns the number of links followed during look-ups in the + unique table if the keeping of this statistic is enabled; -1 otherwise. + If an item is found in the first position of its collision list, the + number of links followed is taken to be 0. If it is in second position, + the number of links is 1, and so on. This statistic is enabled only if + the package is compiled with DD_UNIQUE_PROFILE defined.] + + SideEffects [None] + + SeeAlso [Cudd_ReadUniqueLookUps] + +******************************************************************************/ +double +Cudd_ReadUniqueLinks( + DdManager * dd) +{ +#ifdef DD_UNIQUE_PROFILE + return(dd->uniqueLinks); +#else + return(-1.0); +#endif + +} /* end of Cudd_ReadUniqueLinks */ + + +/**Function******************************************************************** + + Synopsis [Reads the siftMaxVar parameter of the manager.] + + Description [Reads the siftMaxVar parameter of the manager. This + parameter gives the maximum number of variables that will be sifted + for each invocation of sifting.] + + SideEffects [None] + + SeeAlso [Cudd_ReadSiftMaxSwap Cudd_SetSiftMaxVar] + +******************************************************************************/ +int +Cudd_ReadSiftMaxVar( + DdManager * dd) +{ + return(dd->siftMaxVar); + +} /* end of Cudd_ReadSiftMaxVar */ + + +/**Function******************************************************************** + + Synopsis [Sets the siftMaxVar parameter of the manager.] + + Description [Sets the siftMaxVar parameter of the manager. This + parameter gives the maximum number of variables that will be sifted + for each invocation of sifting.] + + SideEffects [None] + + SeeAlso [Cudd_SetSiftMaxSwap Cudd_ReadSiftMaxVar] + +******************************************************************************/ +void +Cudd_SetSiftMaxVar( + DdManager * dd, + int smv) +{ + dd->siftMaxVar = smv; + +} /* end of Cudd_SetSiftMaxVar */ + + +/**Function******************************************************************** + + Synopsis [Reads the siftMaxSwap parameter of the manager.] + + Description [Reads the siftMaxSwap parameter of the manager. This + parameter gives the maximum number of swaps that will be attempted + for each invocation of sifting. The real number of swaps may exceed + the set limit because the package will always complete the sifting + of the variable that causes the limit to be reached.] + + SideEffects [None] + + SeeAlso [Cudd_ReadSiftMaxVar Cudd_SetSiftMaxSwap] + +******************************************************************************/ +int +Cudd_ReadSiftMaxSwap( + DdManager * dd) +{ + return(dd->siftMaxSwap); + +} /* end of Cudd_ReadSiftMaxSwap */ + + +/**Function******************************************************************** + + Synopsis [Sets the siftMaxSwap parameter of the manager.] + + Description [Sets the siftMaxSwap parameter of the manager. This + parameter gives the maximum number of swaps that will be attempted + for each invocation of sifting. The real number of swaps may exceed + the set limit because the package will always complete the sifting + of the variable that causes the limit to be reached.] + + SideEffects [None] + + SeeAlso [Cudd_SetSiftMaxVar Cudd_ReadSiftMaxSwap] + +******************************************************************************/ +void +Cudd_SetSiftMaxSwap( + DdManager * dd, + int sms) +{ + dd->siftMaxSwap = sms; + +} /* end of Cudd_SetSiftMaxSwap */ + + +/**Function******************************************************************** + + Synopsis [Reads the maxGrowth parameter of the manager.] + + Description [Reads the maxGrowth parameter of the manager. This + parameter determines how much the number of nodes can grow during + sifting of a variable. Overall, sifting never increases the size of + the decision diagrams. This parameter only refers to intermediate + results. A lower value will speed up sifting, possibly at the + expense of quality.] + + SideEffects [None] + + SeeAlso [Cudd_SetMaxGrowth Cudd_ReadMaxGrowthAlternate] + +******************************************************************************/ +double +Cudd_ReadMaxGrowth( + DdManager * dd) +{ + return(dd->maxGrowth); + +} /* end of Cudd_ReadMaxGrowth */ + + +/**Function******************************************************************** + + Synopsis [Sets the maxGrowth parameter of the manager.] + + Description [Sets the maxGrowth parameter of the manager. This + parameter determines how much the number of nodes can grow during + sifting of a variable. Overall, sifting never increases the size of + the decision diagrams. This parameter only refers to intermediate + results. A lower value will speed up sifting, possibly at the + expense of quality.] + + SideEffects [None] + + SeeAlso [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate] + +******************************************************************************/ +void +Cudd_SetMaxGrowth( + DdManager * dd, + double mg) +{ + dd->maxGrowth = mg; + +} /* end of Cudd_SetMaxGrowth */ + + +/**Function******************************************************************** + + Synopsis [Reads the maxGrowthAlt parameter of the manager.] + + Description [Reads the maxGrowthAlt parameter of the manager. This + parameter is analogous to the maxGrowth paramter, and is used every + given number of reorderings instead of maxGrowth. The number of + reorderings is set with Cudd_SetReorderingCycle. If the number of + reorderings is 0 (default) maxGrowthAlt is never used.] + + SideEffects [None] + + SeeAlso [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate + Cudd_SetReorderingCycle Cudd_ReadReorderingCycle] + +******************************************************************************/ +double +Cudd_ReadMaxGrowthAlternate( + DdManager * dd) +{ + return(dd->maxGrowthAlt); + +} /* end of Cudd_ReadMaxGrowthAlternate */ + + +/**Function******************************************************************** + + Synopsis [Sets the maxGrowthAlt parameter of the manager.] + + Description [Sets the maxGrowthAlt parameter of the manager. This + parameter is analogous to the maxGrowth paramter, and is used every + given number of reorderings instead of maxGrowth. The number of + reorderings is set with Cudd_SetReorderingCycle. If the number of + reorderings is 0 (default) maxGrowthAlt is never used.] + + SideEffects [None] + + SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowth + Cudd_SetReorderingCycle Cudd_ReadReorderingCycle] + +******************************************************************************/ +void +Cudd_SetMaxGrowthAlternate( + DdManager * dd, + double mg) +{ + dd->maxGrowthAlt = mg; + +} /* end of Cudd_SetMaxGrowthAlternate */ + + +/**Function******************************************************************** + + Synopsis [Reads the reordCycle parameter of the manager.] + + Description [Reads the reordCycle parameter of the manager. This + parameter determines how often the alternate threshold on maximum + growth is used in reordering.] + + SideEffects [None] + + SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate + Cudd_SetReorderingCycle] + +******************************************************************************/ +int +Cudd_ReadReorderingCycle( + DdManager * dd) +{ + return(dd->reordCycle); + +} /* end of Cudd_ReadReorderingCycle */ + + +/**Function******************************************************************** + + Synopsis [Sets the reordCycle parameter of the manager.] + + Description [Sets the reordCycle parameter of the manager. This + parameter determines how often the alternate threshold on maximum + growth is used in reordering.] + + SideEffects [None] + + SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate + Cudd_ReadReorderingCycle] + +******************************************************************************/ +void +Cudd_SetReorderingCycle( + DdManager * dd, + int cycle) +{ + dd->reordCycle = cycle; + +} /* end of Cudd_SetReorderingCycle */ + + +/**Function******************************************************************** + + Synopsis [Returns the variable group tree of the manager.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_SetTree Cudd_FreeTree Cudd_ReadZddTree] + +******************************************************************************/ +MtrNode * +Cudd_ReadTree( + DdManager * dd) +{ + return(dd->tree); + +} /* end of Cudd_ReadTree */ + + +/**Function******************************************************************** + + Synopsis [Sets the variable group tree of the manager.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_FreeTree Cudd_ReadTree Cudd_SetZddTree] + +******************************************************************************/ +void +Cudd_SetTree( + DdManager * dd, + MtrNode * tree) +{ + if (dd->tree != NULL) { + Mtr_FreeTree(dd->tree); + } + dd->tree = tree; + if (tree == NULL) return; + + fixVarTree(tree, dd->perm, dd->size); + return; + +} /* end of Cudd_SetTree */ + + +/**Function******************************************************************** + + Synopsis [Frees the variable group tree of the manager.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_SetTree Cudd_ReadTree Cudd_FreeZddTree] + +******************************************************************************/ +void +Cudd_FreeTree( + DdManager * dd) +{ + if (dd->tree != NULL) { + Mtr_FreeTree(dd->tree); + dd->tree = NULL; + } + return; + +} /* end of Cudd_FreeTree */ + + +/**Function******************************************************************** + + Synopsis [Returns the variable group tree of the manager.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_SetZddTree Cudd_FreeZddTree Cudd_ReadTree] + +******************************************************************************/ +MtrNode * +Cudd_ReadZddTree( + DdManager * dd) +{ + return(dd->treeZ); + +} /* end of Cudd_ReadZddTree */ + + +/**Function******************************************************************** + + Synopsis [Sets the ZDD variable group tree of the manager.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_FreeZddTree Cudd_ReadZddTree Cudd_SetTree] + +******************************************************************************/ +void +Cudd_SetZddTree( + DdManager * dd, + MtrNode * tree) +{ + if (dd->treeZ != NULL) { + Mtr_FreeTree(dd->treeZ); + } + dd->treeZ = tree; + if (tree == NULL) return; + + fixVarTree(tree, dd->permZ, dd->sizeZ); + return; + +} /* end of Cudd_SetZddTree */ + + +/**Function******************************************************************** + + Synopsis [Frees the variable group tree of the manager.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_SetZddTree Cudd_ReadZddTree Cudd_FreeTree] + +******************************************************************************/ +void +Cudd_FreeZddTree( + DdManager * dd) +{ + if (dd->treeZ != NULL) { + Mtr_FreeTree(dd->treeZ); + dd->treeZ = NULL; + } + return; + +} /* end of Cudd_FreeZddTree */ + + +/**Function******************************************************************** + + Synopsis [Returns the index of the node.] + + Description [Returns the index of the node. The node pointer can be + either regular or complemented.] + + SideEffects [None] + + SeeAlso [Cudd_ReadIndex] + +******************************************************************************/ +unsigned int +Cudd_NodeReadIndex( + DdNode * node) +{ + return((unsigned int) Cudd_Regular(node)->index); + +} /* end of Cudd_NodeReadIndex */ + + +/**Function******************************************************************** + + Synopsis [Returns the current position of the i-th variable in the + order.] + + Description [Returns the current position of the i-th variable in + the order. If the index is CUDD_CONST_INDEX, returns + CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns + -1.] + + SideEffects [None] + + SeeAlso [Cudd_ReadInvPerm Cudd_ReadPermZdd] + +******************************************************************************/ +int +Cudd_ReadPerm( + DdManager * dd, + int i) +{ + if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); + if (i < 0 || i >= dd->size) return(-1); + return(dd->perm[i]); + +} /* end of Cudd_ReadPerm */ + + +/**Function******************************************************************** + + Synopsis [Returns the current position of the i-th ZDD variable in the + order.] + + Description [Returns the current position of the i-th ZDD variable + in the order. If the index is CUDD_CONST_INDEX, returns + CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns + -1.] + + SideEffects [None] + + SeeAlso [Cudd_ReadInvPermZdd Cudd_ReadPerm] + +******************************************************************************/ +int +Cudd_ReadPermZdd( + DdManager * dd, + int i) +{ + if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); + if (i < 0 || i >= dd->sizeZ) return(-1); + return(dd->permZ[i]); + +} /* end of Cudd_ReadPermZdd */ + + +/**Function******************************************************************** + + Synopsis [Returns the index of the variable currently in the i-th + position of the order.] + + Description [Returns the index of the variable currently in the i-th + position of the order. If the index is CUDD_CONST_INDEX, returns + CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.] + + SideEffects [None] + + SeeAlso [Cudd_ReadPerm Cudd_ReadInvPermZdd] + +******************************************************************************/ +int +Cudd_ReadInvPerm( + DdManager * dd, + int i) +{ + if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); + if (i < 0 || i >= dd->size) return(-1); + return(dd->invperm[i]); + +} /* end of Cudd_ReadInvPerm */ + + +/**Function******************************************************************** + + Synopsis [Returns the index of the ZDD variable currently in the i-th + position of the order.] + + Description [Returns the index of the ZDD variable currently in the + i-th position of the order. If the index is CUDD_CONST_INDEX, returns + CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.] + + SideEffects [None] + + SeeAlso [Cudd_ReadPerm Cudd_ReadInvPermZdd] + +******************************************************************************/ +int +Cudd_ReadInvPermZdd( + DdManager * dd, + int i) +{ + if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); + if (i < 0 || i >= dd->sizeZ) return(-1); + return(dd->invpermZ[i]); + +} /* end of Cudd_ReadInvPermZdd */ + + +/**Function******************************************************************** + + Synopsis [Returns the i-th element of the vars array.] + + Description [Returns the i-th element of the vars array if it falls + within the array bounds; NULL otherwise. If i is the index of an + existing variable, this function produces the same result as + Cudd_bddIthVar. However, if the i-th var does not exist yet, + Cudd_bddIthVar will create it, whereas Cudd_ReadVars will not.] + + SideEffects [None] + + SeeAlso [Cudd_bddIthVar] + +******************************************************************************/ +DdNode * +Cudd_ReadVars( + DdManager * dd, + int i) +{ + if (i < 0 || i > dd->size) return(NULL); + return(dd->vars[i]); + +} /* end of Cudd_ReadVars */ + + +/**Function******************************************************************** + + Synopsis [Reads the epsilon parameter of the manager.] + + Description [Reads the epsilon parameter of the manager. The epsilon + parameter control the comparison between floating point numbers.] + + SideEffects [None] + + SeeAlso [Cudd_SetEpsilon] + +******************************************************************************/ +CUDD_VALUE_TYPE +Cudd_ReadEpsilon( + DdManager * dd) +{ + return(dd->epsilon); + +} /* end of Cudd_ReadEpsilon */ + + +/**Function******************************************************************** + + Synopsis [Sets the epsilon parameter of the manager to ep.] + + Description [Sets the epsilon parameter of the manager to ep. The epsilon + parameter control the comparison between floating point numbers.] + + SideEffects [None] + + SeeAlso [Cudd_ReadEpsilon] + +******************************************************************************/ +void +Cudd_SetEpsilon( + DdManager * dd, + CUDD_VALUE_TYPE ep) +{ + dd->epsilon = ep; + +} /* end of Cudd_SetEpsilon */ + + +/**Function******************************************************************** + + Synopsis [Reads the groupcheck parameter of the manager.] + + Description [Reads the groupcheck parameter of the manager. The + groupcheck parameter determines the aggregation criterion in group + sifting.] + + SideEffects [None] + + SeeAlso [Cudd_SetGroupcheck] + +******************************************************************************/ +Cudd_AggregationType +Cudd_ReadGroupcheck( + DdManager * dd) +{ + return(dd->groupcheck); + +} /* end of Cudd_ReadGroupCheck */ + + +/**Function******************************************************************** + + Synopsis [Sets the parameter groupcheck of the manager to gc.] + + Description [Sets the parameter groupcheck of the manager to gc. The + groupcheck parameter determines the aggregation criterion in group + sifting.] + + SideEffects [None] + + SeeAlso [Cudd_ReadGroupCheck] + +******************************************************************************/ +void +Cudd_SetGroupcheck( + DdManager * dd, + Cudd_AggregationType gc) +{ + dd->groupcheck = gc; + +} /* end of Cudd_SetGroupcheck */ + + +/**Function******************************************************************** + + Synopsis [Tells whether garbage collection is enabled.] + + Description [Returns 1 if garbage collection is enabled; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_EnableGarbageCollection Cudd_DisableGarbageCollection] + +******************************************************************************/ +int +Cudd_GarbageCollectionEnabled( + DdManager * dd) +{ + return(dd->gcEnabled); + +} /* end of Cudd_GarbageCollectionEnabled */ + + +/**Function******************************************************************** + + Synopsis [Enables garbage collection.] + + Description [Enables garbage collection. Garbage collection is + initially enabled. Therefore it is necessary to call this function + only if garbage collection has been explicitly disabled.] + + SideEffects [None] + + SeeAlso [Cudd_DisableGarbageCollection Cudd_GarbageCollectionEnabled] + +******************************************************************************/ +void +Cudd_EnableGarbageCollection( + DdManager * dd) +{ + dd->gcEnabled = 1; + +} /* end of Cudd_EnableGarbageCollection */ + + +/**Function******************************************************************** + + Synopsis [Disables garbage collection.] + + Description [Disables garbage collection. Garbage collection is + initially enabled. This function may be called to disable it. + However, garbage collection will still occur when a new node must be + created and no memory is left, or when garbage collection is required + for correctness. (E.g., before reordering.)] + + SideEffects [None] + + SeeAlso [Cudd_EnableGarbageCollection Cudd_GarbageCollectionEnabled] + +******************************************************************************/ +void +Cudd_DisableGarbageCollection( + DdManager * dd) +{ + dd->gcEnabled = 0; + +} /* end of Cudd_DisableGarbageCollection */ + + +/**Function******************************************************************** + + Synopsis [Tells whether dead nodes are counted towards triggering + reordering.] + + Description [Tells whether dead nodes are counted towards triggering + reordering. Returns 1 if dead nodes are counted; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_TurnOnCountDead Cudd_TurnOffCountDead] + +******************************************************************************/ +int +Cudd_DeadAreCounted( + DdManager * dd) +{ + return(dd->countDead == 0 ? 1 : 0); + +} /* end of Cudd_DeadAreCounted */ + + +/**Function******************************************************************** + + Synopsis [Causes the dead nodes to be counted towards triggering + reordering.] + + Description [Causes the dead nodes to be counted towards triggering + reordering. This causes more frequent reorderings. By default dead + nodes are not counted.] + + SideEffects [Changes the manager.] + + SeeAlso [Cudd_TurnOffCountDead Cudd_DeadAreCounted] + +******************************************************************************/ +void +Cudd_TurnOnCountDead( + DdManager * dd) +{ + dd->countDead = 0; + +} /* end of Cudd_TurnOnCountDead */ + + +/**Function******************************************************************** + + Synopsis [Causes the dead nodes not to be counted towards triggering + reordering.] + + Description [Causes the dead nodes not to be counted towards + triggering reordering. This causes less frequent reorderings. By + default dead nodes are not counted. Therefore there is no need to + call this function unless Cudd_TurnOnCountDead has been previously + called.] + + SideEffects [Changes the manager.] + + SeeAlso [Cudd_TurnOnCountDead Cudd_DeadAreCounted] + +******************************************************************************/ +void +Cudd_TurnOffCountDead( + DdManager * dd) +{ + dd->countDead = ~0; + +} /* end of Cudd_TurnOffCountDead */ + + +/**Function******************************************************************** + + Synopsis [Returns the current value of the recombination parameter used + in group sifting.] + + Description [Returns the current value of the recombination + parameter used in group sifting. A larger (positive) value makes the + aggregation of variables due to the second difference criterion more + likely. A smaller (negative) value makes aggregation less likely.] + + SideEffects [None] + + SeeAlso [Cudd_SetRecomb] + +******************************************************************************/ +int +Cudd_ReadRecomb( + DdManager * dd) +{ + return(dd->recomb); + +} /* end of Cudd_ReadRecomb */ + + +/**Function******************************************************************** + + Synopsis [Sets the value of the recombination parameter used in group + sifting.] + + Description [Sets the value of the recombination parameter used in + group sifting. A larger (positive) value makes the aggregation of + variables due to the second difference criterion more likely. A + smaller (negative) value makes aggregation less likely. The default + value is 0.] + + SideEffects [Changes the manager.] + + SeeAlso [Cudd_ReadRecomb] + +******************************************************************************/ +void +Cudd_SetRecomb( + DdManager * dd, + int recomb) +{ + dd->recomb = recomb; + +} /* end of Cudd_SetRecomb */ + + +/**Function******************************************************************** + + Synopsis [Returns the current value of the symmviolation parameter used + in group sifting.] + + Description [Returns the current value of the symmviolation + parameter. This parameter is used in group sifting to decide how + many violations to the symmetry conditions f10 = f01 or + f11 = f00 are tolerable when checking for aggregation + due to extended symmetry. The value should be between 0 and 100. A + small value causes fewer variables to be aggregated. The default + value is 0.] + + SideEffects [None] + + SeeAlso [Cudd_SetSymmviolation] + +******************************************************************************/ +int +Cudd_ReadSymmviolation( + DdManager * dd) +{ + return(dd->symmviolation); + +} /* end of Cudd_ReadSymmviolation */ + + +/**Function******************************************************************** + + Synopsis [Sets the value of the symmviolation parameter used + in group sifting.] + + Description [Sets the value of the symmviolation + parameter. This parameter is used in group sifting to decide how + many violations to the symmetry conditions f10 = f01 or + f11 = f00 are tolerable when checking for aggregation + due to extended symmetry. The value should be between 0 and 100. A + small value causes fewer variables to be aggregated. The default + value is 0.] + + SideEffects [Changes the manager.] + + SeeAlso [Cudd_ReadSymmviolation] + +******************************************************************************/ +void +Cudd_SetSymmviolation( + DdManager * dd, + int symmviolation) +{ + dd->symmviolation = symmviolation; + +} /* end of Cudd_SetSymmviolation */ + + +/**Function******************************************************************** + + Synopsis [Returns the current value of the arcviolation parameter used + in group sifting.] + + Description [Returns the current value of the arcviolation + parameter. This parameter is used in group sifting to decide how + many arcs into y not coming from x are + tolerable when checking for aggregation due to extended + symmetry. The value should be between 0 and 100. A small value + causes fewer variables to be aggregated. The default value is 0.] + + SideEffects [None] + + SeeAlso [Cudd_SetArcviolation] + +******************************************************************************/ +int +Cudd_ReadArcviolation( + DdManager * dd) +{ + return(dd->arcviolation); + +} /* end of Cudd_ReadArcviolation */ + + +/**Function******************************************************************** + + Synopsis [Sets the value of the arcviolation parameter used + in group sifting.] + + Description [Sets the value of the arcviolation + parameter. This parameter is used in group sifting to decide how + many arcs into y not coming from x are + tolerable when checking for aggregation due to extended + symmetry. The value should be between 0 and 100. A small value + causes fewer variables to be aggregated. The default value is 0.] + + SideEffects [None] + + SeeAlso [Cudd_ReadArcviolation] + +******************************************************************************/ +void +Cudd_SetArcviolation( + DdManager * dd, + int arcviolation) +{ + dd->arcviolation = arcviolation; + +} /* end of Cudd_SetArcviolation */ + + +/**Function******************************************************************** + + Synopsis [Reads the current size of the population used by the + genetic algorithm for reordering.] + + Description [Reads the current size of the population used by the + genetic algorithm for variable reordering. A larger population size will + cause the genetic algorithm to take more time, but will generally + produce better results. The default value is 0, in which case the + package uses three times the number of variables as population size, + with a maximum of 120.] + + SideEffects [None] + + SeeAlso [Cudd_SetPopulationSize] + +******************************************************************************/ +int +Cudd_ReadPopulationSize( + DdManager * dd) +{ + return(dd->populationSize); + +} /* end of Cudd_ReadPopulationSize */ + + +/**Function******************************************************************** + + Synopsis [Sets the size of the population used by the + genetic algorithm for reordering.] + + Description [Sets the size of the population used by the + genetic algorithm for variable reordering. A larger population size will + cause the genetic algorithm to take more time, but will generally + produce better results. The default value is 0, in which case the + package uses three times the number of variables as population size, + with a maximum of 120.] + + SideEffects [Changes the manager.] + + SeeAlso [Cudd_ReadPopulationSize] + +******************************************************************************/ +void +Cudd_SetPopulationSize( + DdManager * dd, + int populationSize) +{ + dd->populationSize = populationSize; + +} /* end of Cudd_SetPopulationSize */ + + +/**Function******************************************************************** + + Synopsis [Reads the current number of crossovers used by the + genetic algorithm for reordering.] + + Description [Reads the current number of crossovers used by the + genetic algorithm for variable reordering. A larger number of crossovers will + cause the genetic algorithm to take more time, but will generally + produce better results. The default value is 0, in which case the + package uses three times the number of variables as number of crossovers, + with a maximum of 60.] + + SideEffects [None] + + SeeAlso [Cudd_SetNumberXovers] + +******************************************************************************/ +int +Cudd_ReadNumberXovers( + DdManager * dd) +{ + return(dd->numberXovers); + +} /* end of Cudd_ReadNumberXovers */ + + +/**Function******************************************************************** + + Synopsis [Sets the number of crossovers used by the + genetic algorithm for reordering.] + + Description [Sets the number of crossovers used by the genetic + algorithm for variable reordering. A larger number of crossovers + will cause the genetic algorithm to take more time, but will + generally produce better results. The default value is 0, in which + case the package uses three times the number of variables as number + of crossovers, with a maximum of 60.] + + SideEffects [None] + + SeeAlso [Cudd_ReadNumberXovers] + +******************************************************************************/ +void +Cudd_SetNumberXovers( + DdManager * dd, + int numberXovers) +{ + dd->numberXovers = numberXovers; + +} /* end of Cudd_SetNumberXovers */ + +/**Function******************************************************************** + + Synopsis [Returns the memory in use by the manager measured in bytes.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +long +Cudd_ReadMemoryInUse( + DdManager * dd) +{ + return(dd->memused); + +} /* end of Cudd_ReadMemoryInUse */ + + +/**Function******************************************************************** + + Synopsis [Prints out statistics and settings for a CUDD manager.] + + Description [Prints out statistics and settings for a CUDD manager. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_PrintInfo( + DdManager * dd, + FILE * fp) +{ + int retval; + Cudd_ReorderingType autoMethod, autoMethodZ; + + /* Modifiable parameters. */ + retval = fprintf(fp,"**** CUDD modifiable parameters ****\n"); + if (retval == EOF) return(0); + retval = fprintf(fp,"Hard limit for cache size: %u\n", + Cudd_ReadMaxCacheHard(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Cache hit threshold for resizing: %u%%\n", + Cudd_ReadMinHit(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Garbage collection enabled: %s\n", + Cudd_GarbageCollectionEnabled(dd) ? "yes" : "no"); + if (retval == EOF) return(0); + retval = fprintf(fp,"Limit for fast unique table growth: %u\n", + Cudd_ReadLooseUpTo(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp, + "Maximum number of variables sifted per reordering: %d\n", + Cudd_ReadSiftMaxVar(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp, + "Maximum number of variable swaps per reordering: %d\n", + Cudd_ReadSiftMaxSwap(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Maximum growth while sifting a variable: %g\n", + Cudd_ReadMaxGrowth(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Dynamic reordering of BDDs enabled: %s\n", + Cudd_ReorderingStatus(dd,&autoMethod) ? "yes" : "no"); + if (retval == EOF) return(0); + retval = fprintf(fp,"Default BDD reordering method: %d\n", autoMethod); + if (retval == EOF) return(0); + retval = fprintf(fp,"Dynamic reordering of ZDDs enabled: %s\n", + Cudd_ReorderingStatusZdd(dd,&autoMethodZ) ? "yes" : "no"); + if (retval == EOF) return(0); + retval = fprintf(fp,"Default ZDD reordering method: %d\n", autoMethodZ); + if (retval == EOF) return(0); + retval = fprintf(fp,"Realignment of ZDDs to BDDs enabled: %s\n", + Cudd_zddRealignmentEnabled(dd) ? "yes" : "no"); + if (retval == EOF) return(0); + retval = fprintf(fp,"Realignment of BDDs to ZDDs enabled: %s\n", + Cudd_bddRealignmentEnabled(dd) ? "yes" : "no"); + if (retval == EOF) return(0); + retval = fprintf(fp,"Dead nodes counted in triggering reordering: %s\n", + Cudd_DeadAreCounted(dd) ? "yes" : "no"); + if (retval == EOF) return(0); + retval = fprintf(fp,"Group checking criterion: %d\n", + Cudd_ReadGroupcheck(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Recombination threshold: %d\n", Cudd_ReadRecomb(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Symmetry violation threshold: %d\n", + Cudd_ReadSymmviolation(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Arc violation threshold: %d\n", + Cudd_ReadArcviolation(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"GA population size: %d\n", + Cudd_ReadPopulationSize(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of crossovers for GA: %d\n", + Cudd_ReadNumberXovers(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Next reordering threshold: %u\n", + Cudd_ReadNextReordering(dd)); + if (retval == EOF) return(0); + + /* Non-modifiable parameters. */ + retval = fprintf(fp,"**** CUDD non-modifiable parameters ****\n"); + if (retval == EOF) return(0); + retval = fprintf(fp,"Memory in use: %ld\n", Cudd_ReadMemoryInUse(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Peak number of nodes: %ld\n", + Cudd_ReadPeakNodeCount(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Peak number of live nodes: %d\n", + Cudd_ReadPeakLiveNodeCount(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of BDD variables: %d\n", dd->size); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of ZDD variables: %d\n", dd->sizeZ); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of cache entries: %u\n", dd->cacheSlots); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of cache look-ups: %.0f\n", + Cudd_ReadCacheLookUps(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of cache hits: %.0f\n", + Cudd_ReadCacheHits(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of cache insertions: %.0f\n", + dd->cacheinserts); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of cache collisions: %.0f\n", + dd->cachecollisions); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of cache deletions: %.0f\n", + dd->cachedeletions); + if (retval == EOF) return(0); + retval = cuddCacheProfile(dd,fp); + if (retval == 0) return(0); + retval = fprintf(fp,"Soft limit for cache size: %u\n", + Cudd_ReadMaxCache(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of buckets in unique table: %u\n", dd->slots); + if (retval == EOF) return(0); + retval = fprintf(fp,"Used buckets in unique table: %.2f%% (expected %.2f%%)\n", + 100.0 * Cudd_ReadUsedSlots(dd), + 100.0 * Cudd_ExpectedUsedSlots(dd)); + if (retval == EOF) return(0); +#ifdef DD_UNIQUE_PROFILE + retval = fprintf(fp,"Unique lookups: %.0f\n", dd->uniqueLookUps); + if (retval == EOF) return(0); + retval = fprintf(fp,"Unique links: %.0f (%g per lookup)\n", + dd->uniqueLinks, dd->uniqueLinks / dd->uniqueLookUps); + if (retval == EOF) return(0); +#endif + retval = fprintf(fp,"Number of BDD and ADD nodes: %u\n", dd->keys); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of ZDD nodes: %u\n", dd->keysZ); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of dead BDD and ADD nodes: %u\n", dd->dead); + if (retval == EOF) return(0); + retval = fprintf(fp,"Number of dead ZDD nodes: %u\n", dd->deadZ); + if (retval == EOF) return(0); + retval = fprintf(fp,"Total number of nodes allocated: %.0f\n", + dd->allocated); + if (retval == EOF) return(0); + retval = fprintf(fp,"Total number of nodes reclaimed: %.0f\n", + dd->reclaimed); + if (retval == EOF) return(0); +#if DD_STATS + retval = fprintf(fp,"Nodes freed: %.0f\n", dd->nodesFreed); + if (retval == EOF) return(0); + retval = fprintf(fp,"Nodes dropped: %.0f\n", dd->nodesDropped); + if (retval == EOF) return(0); +#endif +#if DD_COUNT + retval = fprintf(fp,"Number of recursive calls: %.0f\n", + Cudd_ReadRecursiveCalls(dd)); + if (retval == EOF) return(0); +#endif + retval = fprintf(fp,"Garbage collections so far: %d\n", + Cudd_ReadGarbageCollections(dd)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Time for garbage collection: %.2f sec\n", + ((double)Cudd_ReadGarbageCollectionTime(dd)/1000.0)); + if (retval == EOF) return(0); + retval = fprintf(fp,"Reorderings so far: %d\n", dd->reorderings); + if (retval == EOF) return(0); + retval = fprintf(fp,"Time for reordering: %.2f sec\n", + ((double)Cudd_ReadReorderingTime(dd)/1000.0)); + if (retval == EOF) return(0); +#if DD_COUNT + retval = fprintf(fp,"Node swaps in reordering: %.0f\n", + Cudd_ReadSwapSteps(dd)); + if (retval == EOF) return(0); +#endif + + return(1); + +} /* end of Cudd_PrintInfo */ + + +/**Function******************************************************************** + + Synopsis [Reports the peak number of nodes.] + + Description [Reports the peak number of nodes. This number includes + node on the free list. At the peak, the number of nodes on the free + list is guaranteed to be less than DD_MEM_CHUNK.] + + SideEffects [None] + + SeeAlso [Cudd_ReadNodeCount Cudd_PrintInfo] + +******************************************************************************/ +long +Cudd_ReadPeakNodeCount( + DdManager * dd) +{ + long count = 0; + DdNodePtr *scan = dd->memoryList; + + while (scan != NULL) { + count += DD_MEM_CHUNK; + scan = (DdNodePtr *) *scan; + } + return(count); + +} /* end of Cudd_ReadPeakNodeCount */ + + +/**Function******************************************************************** + + Synopsis [Reports the peak number of live nodes.] + + Description [Reports the peak number of live nodes. This count is kept + only if CUDD is compiled with DD_STATS defined. If DD_STATS is not + defined, this function returns -1.] + + SideEffects [None] + + SeeAlso [Cudd_ReadNodeCount Cudd_PrintInfo Cudd_ReadPeakNodeCount] + +******************************************************************************/ +int +Cudd_ReadPeakLiveNodeCount( + DdManager * dd) +{ + unsigned int live = dd->keys - dd->dead; + + if (live > dd->peakLiveNodes) { + dd->peakLiveNodes = live; + } + return((int)dd->peakLiveNodes); + +} /* end of Cudd_ReadPeakLiveNodeCount */ + + +/**Function******************************************************************** + + Synopsis [Reports the number of nodes in BDDs and ADDs.] + + Description [Reports the number of live nodes in BDDs and ADDs. This + number does not include the isolated projection functions and the + unused constants. These nodes that are not counted are not part of + the DDs manipulated by the application.] + + SideEffects [None] + + SeeAlso [Cudd_ReadPeakNodeCount Cudd_zddReadNodeCount] + +******************************************************************************/ +long +Cudd_ReadNodeCount( + DdManager * dd) +{ + long count; + int i; + +#ifndef DD_NO_DEATH_ROW + cuddClearDeathRow(dd); +#endif + + count = dd->keys - dd->dead; + + /* Count isolated projection functions. Their number is subtracted + ** from the node count because they are not part of the BDDs. + */ + for (i=0; i < dd->size; i++) { + if (dd->vars[i]->ref == 1) count--; + } + /* Subtract from the count the unused constants. */ + if (DD_ZERO(dd)->ref == 1) count--; + if (DD_PLUS_INFINITY(dd)->ref == 1) count--; + if (DD_MINUS_INFINITY(dd)->ref == 1) count--; + + return(count); + +} /* end of Cudd_ReadNodeCount */ + + + +/**Function******************************************************************** + + Synopsis [Reports the number of nodes in ZDDs.] + + Description [Reports the number of nodes in ZDDs. This + number always includes the two constants 1 and 0.] + + SideEffects [None] + + SeeAlso [Cudd_ReadPeakNodeCount Cudd_ReadNodeCount] + +******************************************************************************/ +long +Cudd_zddReadNodeCount( + DdManager * dd) +{ + return(dd->keysZ - dd->deadZ + 2); + +} /* end of Cudd_zddReadNodeCount */ + + +/**Function******************************************************************** + + Synopsis [Adds a function to a hook.] + + Description [Adds a function to a hook. A hook is a list of + application-provided functions called on certain occasions by the + package. Returns 1 if the function is successfully added; 2 if the + function was already in the list; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_RemoveHook] + +******************************************************************************/ +int +Cudd_AddHook( + DdManager * dd, + int (*f)(DdManager *, char *, void *) , + Cudd_HookType where) +{ + DdHook **hook, *nextHook, *newHook; + + switch (where) { + case CUDD_PRE_GC_HOOK: + hook = &(dd->preGCHook); + break; + case CUDD_POST_GC_HOOK: + hook = &(dd->postGCHook); + break; + case CUDD_PRE_REORDERING_HOOK: + hook = &(dd->preReorderingHook); + break; + case CUDD_POST_REORDERING_HOOK: + hook = &(dd->postReorderingHook); + break; + default: + return(0); + } + /* Scan the list and find whether the function is already there. + ** If so, just return. */ + nextHook = *hook; + while (nextHook != NULL) { + if (nextHook->f == f) { + return(2); + } + hook = &(nextHook->next); + nextHook = nextHook->next; + } + /* The function was not in the list. Create a new item and append it + ** to the end of the list. */ + newHook = ALLOC(DdHook,1); + if (newHook == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newHook->next = NULL; + newHook->f = f; + *hook = newHook; + return(1); + +} /* end of Cudd_AddHook */ + + +/**Function******************************************************************** + + Synopsis [Removes a function from a hook.] + + Description [Removes a function from a hook. A hook is a list of + application-provided functions called on certain occasions by the + package. Returns 1 if successful; 0 the function was not in the list.] + + SideEffects [None] + + SeeAlso [Cudd_AddHook] + +******************************************************************************/ +int +Cudd_RemoveHook( + DdManager * dd, + int (*f)(DdManager *, char *, void *) , + Cudd_HookType where) +{ + DdHook **hook, *nextHook; + + switch (where) { + case CUDD_PRE_GC_HOOK: + hook = &(dd->preGCHook); + break; + case CUDD_POST_GC_HOOK: + hook = &(dd->postGCHook); + break; + case CUDD_PRE_REORDERING_HOOK: + hook = &(dd->preReorderingHook); + break; + case CUDD_POST_REORDERING_HOOK: + hook = &(dd->postReorderingHook); + break; + default: + return(0); + } + nextHook = *hook; + while (nextHook != NULL) { + if (nextHook->f == f) { + *hook = nextHook->next; + FREE(nextHook); + return(1); + } + hook = &(nextHook->next); + nextHook = nextHook->next; + } + + return(0); + +} /* end of Cudd_RemoveHook */ + + +/**Function******************************************************************** + + Synopsis [Checks whether a function is in a hook.] + + Description [Checks whether a function is in a hook. A hook is a list of + application-provided functions called on certain occasions by the + package. Returns 1 if the function is found; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_AddHook Cudd_RemoveHook] + +******************************************************************************/ +int +Cudd_IsInHook( + DdManager * dd, + int (*f)(DdManager *, char *, void *) , + Cudd_HookType where) +{ + DdHook *hook; + + switch (where) { + case CUDD_PRE_GC_HOOK: + hook = dd->preGCHook; + break; + case CUDD_POST_GC_HOOK: + hook = dd->postGCHook; + break; + case CUDD_PRE_REORDERING_HOOK: + hook = dd->preReorderingHook; + break; + case CUDD_POST_REORDERING_HOOK: + hook = dd->postReorderingHook; + break; + default: + return(0); + } + /* Scan the list and find whether the function is already there. */ + while (hook != NULL) { + if (hook->f == f) { + return(1); + } + hook = hook->next; + } + return(0); + +} /* end of Cudd_IsInHook */ + + +/**Function******************************************************************** + + Synopsis [Sample hook function to call before reordering.] + + Description [Sample hook function to call before reordering. + Prints on the manager's stdout reordering method and initial size. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_StdPostReordHook] + +******************************************************************************/ +int +Cudd_StdPreReordHook( + DdManager *dd, + char *str, + void *data) +{ + Cudd_ReorderingType method = (Cudd_ReorderingType) (ptruint) data; + int retval; + + retval = fprintf(dd->out,"%s reordering with ", str); + if (retval == EOF) return(0); + switch (method) { + case CUDD_REORDER_SIFT_CONVERGE: + case CUDD_REORDER_SYMM_SIFT_CONV: + case CUDD_REORDER_GROUP_SIFT_CONV: + case CUDD_REORDER_WINDOW2_CONV: + case CUDD_REORDER_WINDOW3_CONV: + case CUDD_REORDER_WINDOW4_CONV: + case CUDD_REORDER_LINEAR_CONVERGE: + retval = fprintf(dd->out,"converging "); + if (retval == EOF) return(0); + break; + default: + break; + } + switch (method) { + case CUDD_REORDER_RANDOM: + case CUDD_REORDER_RANDOM_PIVOT: + retval = fprintf(dd->out,"random"); + break; + case CUDD_REORDER_SIFT: + case CUDD_REORDER_SIFT_CONVERGE: + retval = fprintf(dd->out,"sifting"); + break; + case CUDD_REORDER_SYMM_SIFT: + case CUDD_REORDER_SYMM_SIFT_CONV: + retval = fprintf(dd->out,"symmetric sifting"); + break; + case CUDD_REORDER_LAZY_SIFT: + retval = fprintf(dd->out,"lazy sifting"); + break; + case CUDD_REORDER_GROUP_SIFT: + case CUDD_REORDER_GROUP_SIFT_CONV: + retval = fprintf(dd->out,"group sifting"); + break; + case CUDD_REORDER_WINDOW2: + case CUDD_REORDER_WINDOW3: + case CUDD_REORDER_WINDOW4: + case CUDD_REORDER_WINDOW2_CONV: + case CUDD_REORDER_WINDOW3_CONV: + case CUDD_REORDER_WINDOW4_CONV: + retval = fprintf(dd->out,"window"); + break; + case CUDD_REORDER_ANNEALING: + retval = fprintf(dd->out,"annealing"); + break; + case CUDD_REORDER_GENETIC: + retval = fprintf(dd->out,"genetic"); + break; + case CUDD_REORDER_LINEAR: + case CUDD_REORDER_LINEAR_CONVERGE: + retval = fprintf(dd->out,"linear sifting"); + break; + case CUDD_REORDER_EXACT: + retval = fprintf(dd->out,"exact"); + break; + default: + return(0); + } + if (retval == EOF) return(0); + + retval = fprintf(dd->out,": from %ld to ... ", strcmp(str, "BDD") == 0 ? + Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd)); + if (retval == EOF) return(0); + fflush(dd->out); + return(1); + +} /* end of Cudd_StdPreReordHook */ + + +/**Function******************************************************************** + + Synopsis [Sample hook function to call after reordering.] + + Description [Sample hook function to call after reordering. + Prints on the manager's stdout final size and reordering time. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_StdPreReordHook] + +******************************************************************************/ +int +Cudd_StdPostReordHook( + DdManager *dd, + char *str, + void *data) +{ + long initialTime = (long) data; + int retval; + long finalTime = util_cpu_time(); + double totalTimeSec = (double)(finalTime - initialTime) / 1000.0; + + retval = fprintf(dd->out,"%ld nodes in %g sec\n", strcmp(str, "BDD") == 0 ? + Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd), + totalTimeSec); + if (retval == EOF) return(0); + retval = fflush(dd->out); + if (retval == EOF) return(0); + return(1); + +} /* end of Cudd_StdPostReordHook */ + + +/**Function******************************************************************** + + Synopsis [Enables reporting of reordering stats.] + + Description [Enables reporting of reordering stats. + Returns 1 if successful; 0 otherwise.] + + SideEffects [Installs functions in the pre-reordering and post-reordering + hooks.] + + SeeAlso [Cudd_DisableReorderingReporting Cudd_ReorderingReporting] + +******************************************************************************/ +int +Cudd_EnableReorderingReporting( + DdManager *dd) +{ + if (!Cudd_AddHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) { + return(0); + } + if (!Cudd_AddHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) { + return(0); + } + return(1); + +} /* end of Cudd_EnableReorderingReporting */ + + +/**Function******************************************************************** + + Synopsis [Disables reporting of reordering stats.] + + Description [Disables reporting of reordering stats. + Returns 1 if successful; 0 otherwise.] + + SideEffects [Removes functions from the pre-reordering and post-reordering + hooks.] + + SeeAlso [Cudd_EnableReorderingReporting Cudd_ReorderingReporting] + +******************************************************************************/ +int +Cudd_DisableReorderingReporting( + DdManager *dd) +{ + if (!Cudd_RemoveHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) { + return(0); + } + if (!Cudd_RemoveHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) { + return(0); + } + return(1); + +} /* end of Cudd_DisableReorderingReporting */ + + +/**Function******************************************************************** + + Synopsis [Returns 1 if reporting of reordering stats is enabled.] + + Description [Returns 1 if reporting of reordering stats is enabled; + 0 otherwise.] + + SideEffects [none] + + SeeAlso [Cudd_EnableReorderingReporting Cudd_DisableReorderingReporting] + +******************************************************************************/ +int +Cudd_ReorderingReporting( + DdManager *dd) +{ + return(Cudd_IsInHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)); + +} /* end of Cudd_ReorderingReporting */ + + +/**Function******************************************************************** + + Synopsis [Returns the code of the last error.] + + Description [Returns the code of the last error. The error codes are + defined in cudd.h.] + + SideEffects [None] + + SeeAlso [Cudd_ClearErrorCode] + +******************************************************************************/ +Cudd_ErrorType +Cudd_ReadErrorCode( + DdManager *dd) +{ + return(dd->errorCode); + +} /* end of Cudd_ReadErrorCode */ + + +/**Function******************************************************************** + + Synopsis [Clear the error code of a manager.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_ReadErrorCode] + +******************************************************************************/ +void +Cudd_ClearErrorCode( + DdManager *dd) +{ + dd->errorCode = CUDD_NO_ERROR; + +} /* end of Cudd_ClearErrorCode */ + + +/**Function******************************************************************** + + Synopsis [Reads the stdout of a manager.] + + Description [Reads the stdout of a manager. This is the file pointer to + which messages normally going to stdout are written. It is initialized + to stdout. Cudd_SetStdout allows the application to redirect it.] + + SideEffects [None] + + SeeAlso [Cudd_SetStdout Cudd_ReadStderr] + +******************************************************************************/ +FILE * +Cudd_ReadStdout( + DdManager *dd) +{ + return(dd->out); + +} /* end of Cudd_ReadStdout */ + + +/**Function******************************************************************** + + Synopsis [Sets the stdout of a manager.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_ReadStdout Cudd_SetStderr] + +******************************************************************************/ +void +Cudd_SetStdout( + DdManager *dd, + FILE *fp) +{ + dd->out = fp; + +} /* end of Cudd_SetStdout */ + + +/**Function******************************************************************** + + Synopsis [Reads the stderr of a manager.] + + Description [Reads the stderr of a manager. This is the file pointer to + which messages normally going to stderr are written. It is initialized + to stderr. Cudd_SetStderr allows the application to redirect it.] + + SideEffects [None] + + SeeAlso [Cudd_SetStderr Cudd_ReadStdout] + +******************************************************************************/ +FILE * +Cudd_ReadStderr( + DdManager *dd) +{ + return(dd->err); + +} /* end of Cudd_ReadStderr */ + + +/**Function******************************************************************** + + Synopsis [Sets the stderr of a manager.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_ReadStderr Cudd_SetStdout] + +******************************************************************************/ +void +Cudd_SetStderr( + DdManager *dd, + FILE *fp) +{ + dd->err = fp; + +} /* end of Cudd_SetStderr */ + + +/**Function******************************************************************** + + Synopsis [Returns the threshold for the next dynamic reordering.] + + Description [Returns the threshold for the next dynamic reordering. + The threshold is in terms of number of nodes and is in effect only + if reordering is enabled. The count does not include the dead nodes, + unless the countDead parameter of the manager has been changed from + its default setting.] + + SideEffects [None] + + SeeAlso [Cudd_SetNextReordering] + +******************************************************************************/ +unsigned int +Cudd_ReadNextReordering( + DdManager *dd) +{ + return(dd->nextDyn); + +} /* end of Cudd_ReadNextReordering */ + + +/**Function******************************************************************** + + Synopsis [Sets the threshold for the next dynamic reordering.] + + Description [Sets the threshold for the next dynamic reordering. + The threshold is in terms of number of nodes and is in effect only + if reordering is enabled. The count does not include the dead nodes, + unless the countDead parameter of the manager has been changed from + its default setting.] + + SideEffects [None] + + SeeAlso [Cudd_ReadNextReordering] + +******************************************************************************/ +void +Cudd_SetNextReordering( + DdManager *dd, + unsigned int next) +{ + dd->nextDyn = next; + +} /* end of Cudd_SetNextReordering */ + + +/**Function******************************************************************** + + Synopsis [Reads the number of elementary reordering steps.] + + Description [] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +double +Cudd_ReadSwapSteps( + DdManager *dd) +{ +#ifdef DD_COUNT + return(dd->swapSteps); +#else + return(-1); +#endif + +} /* end of Cudd_ReadSwapSteps */ + + +/**Function******************************************************************** + + Synopsis [Reads the maximum allowed number of live nodes.] + + Description [Reads the maximum allowed number of live nodes. When this + number is exceeded, the package returns NULL.] + + SideEffects [none] + + SeeAlso [Cudd_SetMaxLive] + +******************************************************************************/ +unsigned int +Cudd_ReadMaxLive( + DdManager *dd) +{ + return(dd->maxLive); + +} /* end of Cudd_ReadMaxLive */ + + +/**Function******************************************************************** + + Synopsis [Sets the maximum allowed number of live nodes.] + + Description [Sets the maximum allowed number of live nodes. When this + number is exceeded, the package returns NULL.] + + SideEffects [none] + + SeeAlso [Cudd_ReadMaxLive] + +******************************************************************************/ +void +Cudd_SetMaxLive( + DdManager *dd, + unsigned int maxLive) +{ + dd->maxLive = maxLive; + +} /* end of Cudd_SetMaxLive */ + + +/**Function******************************************************************** + + Synopsis [Reads the maximum allowed memory.] + + Description [Reads the maximum allowed memory. When this + number is exceeded, the package returns NULL.] + + SideEffects [none] + + SeeAlso [Cudd_SetMaxMemory] + +******************************************************************************/ +long +Cudd_ReadMaxMemory( + DdManager *dd) +{ + return(dd->maxmemhard); + +} /* end of Cudd_ReadMaxMemory */ + + +/**Function******************************************************************** + + Synopsis [Sets the maximum allowed memory.] + + Description [Sets the maximum allowed memory. When this + number is exceeded, the package returns NULL.] + + SideEffects [none] + + SeeAlso [Cudd_ReadMaxMemory] + +******************************************************************************/ +void +Cudd_SetMaxMemory( + DdManager *dd, + long maxMemory) +{ + dd->maxmemhard = maxMemory; + +} /* end of Cudd_SetMaxMemory */ + + +/**Function******************************************************************** + + Synopsis [Prevents sifting of a variable.] + + Description [This function sets a flag to prevent sifting of a + variable. Returns 1 if successful; 0 otherwise (i.e., invalid + variable index).] + + SideEffects [Changes the "bindVar" flag in DdSubtable.] + + SeeAlso [Cudd_bddUnbindVar] + +******************************************************************************/ +int +Cudd_bddBindVar( + DdManager *dd /* manager */, + int index /* variable index */) +{ + if (index >= dd->size || index < 0) return(0); + dd->subtables[dd->perm[index]].bindVar = 1; + return(1); + +} /* end of Cudd_bddBindVar */ + + +/**Function******************************************************************** + + Synopsis [Allows the sifting of a variable.] + + Description [This function resets the flag that prevents the sifting + of a variable. In successive variable reorderings, the variable will + NOT be skipped, that is, sifted. Initially all variables can be + sifted. It is necessary to call this function only to re-enable + sifting after a call to Cudd_bddBindVar. Returns 1 if successful; 0 + otherwise (i.e., invalid variable index).] + + SideEffects [Changes the "bindVar" flag in DdSubtable.] + + SeeAlso [Cudd_bddBindVar] + +******************************************************************************/ +int +Cudd_bddUnbindVar( + DdManager *dd /* manager */, + int index /* variable index */) +{ + if (index >= dd->size || index < 0) return(0); + dd->subtables[dd->perm[index]].bindVar = 0; + return(1); + +} /* end of Cudd_bddUnbindVar */ + + +/**Function******************************************************************** + + Synopsis [Tells whether a variable can be sifted.] + + Description [This function returns 1 if a variable is enabled for + sifting. Initially all variables can be sifted. This function returns + 0 only if there has been a previous call to Cudd_bddBindVar for that + variable not followed by a call to Cudd_bddUnbindVar. The function returns + 0 also in the case in which the index of the variable is out of bounds.] + + SideEffects [none] + + SeeAlso [Cudd_bddBindVar Cudd_bddUnbindVar] + +******************************************************************************/ +int +Cudd_bddVarIsBound( + DdManager *dd /* manager */, + int index /* variable index */) +{ + if (index >= dd->size || index < 0) return(0); + return(dd->subtables[dd->perm[index]].bindVar); + +} /* end of Cudd_bddVarIsBound */ + + +/**Function******************************************************************** + + Synopsis [Sets a variable type to primary input.] + + Description [Sets a variable type to primary input. The variable type is + used by lazy sifting. Returns 1 if successful; 0 otherwise.] + + SideEffects [modifies the manager] + + SeeAlso [Cudd_bddSetPsVar Cudd_bddSetNsVar Cudd_bddIsPiVar] + +******************************************************************************/ +int +Cudd_bddSetPiVar( + DdManager *dd /* manager */, + int index /* variable index */) +{ + if (index >= dd->size || index < 0) return (0); + dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRIMARY_INPUT; + return(1); + +} /* end of Cudd_bddSetPiVar */ + + +/**Function******************************************************************** + + Synopsis [Sets a variable type to present state.] + + Description [Sets a variable type to present state. The variable type is + used by lazy sifting. Returns 1 if successful; 0 otherwise.] + + SideEffects [modifies the manager] + + SeeAlso [Cudd_bddSetPiVar Cudd_bddSetNsVar Cudd_bddIsPsVar] + +******************************************************************************/ +int +Cudd_bddSetPsVar( + DdManager *dd /* manager */, + int index /* variable index */) +{ + if (index >= dd->size || index < 0) return (0); + dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRESENT_STATE; + return(1); + +} /* end of Cudd_bddSetPsVar */ + + +/**Function******************************************************************** + + Synopsis [Sets a variable type to next state.] + + Description [Sets a variable type to next state. The variable type is + used by lazy sifting. Returns 1 if successful; 0 otherwise.] + + SideEffects [modifies the manager] + + SeeAlso [Cudd_bddSetPiVar Cudd_bddSetPsVar Cudd_bddIsNsVar] + +******************************************************************************/ +int +Cudd_bddSetNsVar( + DdManager *dd /* manager */, + int index /* variable index */) +{ + if (index >= dd->size || index < 0) return (0); + dd->subtables[dd->perm[index]].varType = CUDD_VAR_NEXT_STATE; + return(1); + +} /* end of Cudd_bddSetNsVar */ + + +/**Function******************************************************************** + + Synopsis [Checks whether a variable is primary input.] + + Description [Checks whether a variable is primary input. Returns 1 if + the variable's type is primary input; 0 if the variable exists but is + not a primary input; -1 if the variable does not exist.] + + SideEffects [none] + + SeeAlso [Cudd_bddSetPiVar Cudd_bddIsPsVar Cudd_bddIsNsVar] + +******************************************************************************/ +int +Cudd_bddIsPiVar( + DdManager *dd /* manager */, + int index /* variable index */) +{ + if (index >= dd->size || index < 0) return -1; + return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRIMARY_INPUT); + +} /* end of Cudd_bddIsPiVar */ + + +/**Function******************************************************************** + + Synopsis [Checks whether a variable is present state.] + + Description [Checks whether a variable is present state. Returns 1 if + the variable's type is present state; 0 if the variable exists but is + not a present state; -1 if the variable does not exist.] + + SideEffects [none] + + SeeAlso [Cudd_bddSetPsVar Cudd_bddIsPiVar Cudd_bddIsNsVar] + +******************************************************************************/ +int +Cudd_bddIsPsVar( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return -1; + return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRESENT_STATE); + +} /* end of Cudd_bddIsPsVar */ + + +/**Function******************************************************************** + + Synopsis [Checks whether a variable is next state.] + + Description [Checks whether a variable is next state. Returns 1 if + the variable's type is present state; 0 if the variable exists but is + not a present state; -1 if the variable does not exist.] + + SideEffects [none] + + SeeAlso [Cudd_bddSetNsVar Cudd_bddIsPiVar Cudd_bddIsPsVar] + +******************************************************************************/ +int +Cudd_bddIsNsVar( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return -1; + return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_NEXT_STATE); + +} /* end of Cudd_bddIsNsVar */ + + +/**Function******************************************************************** + + Synopsis [Sets a corresponding pair index for a given index.] + + Description [Sets a corresponding pair index for a given index. + These pair indices are present and next state variable. Returns 1 if + successful; 0 otherwise.] + + SideEffects [modifies the manager] + + SeeAlso [Cudd_bddReadPairIndex] + +******************************************************************************/ +int +Cudd_bddSetPairIndex( + DdManager *dd /* manager */, + int index /* variable index */, + int pairIndex /* corresponding variable index */) +{ + if (index >= dd->size || index < 0) return(0); + dd->subtables[dd->perm[index]].pairIndex = pairIndex; + return(1); + +} /* end of Cudd_bddSetPairIndex */ + + +/**Function******************************************************************** + + Synopsis [Reads a corresponding pair index for a given index.] + + Description [Reads a corresponding pair index for a given index. + These pair indices are present and next state variable. Returns the + corresponding variable index if the variable exists; -1 otherwise.] + + SideEffects [modifies the manager] + + SeeAlso [Cudd_bddSetPairIndex] + +******************************************************************************/ +int +Cudd_bddReadPairIndex( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return -1; + return dd->subtables[dd->perm[index]].pairIndex; + +} /* end of Cudd_bddReadPairIndex */ + + +/**Function******************************************************************** + + Synopsis [Sets a variable to be grouped.] + + Description [Sets a variable to be grouped. This function is used for + lazy sifting. Returns 1 if successful; 0 otherwise.] + + SideEffects [modifies the manager] + + SeeAlso [Cudd_bddSetVarHardGroup Cudd_bddResetVarToBeGrouped] + +******************************************************************************/ +int +Cudd_bddSetVarToBeGrouped( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return(0); + if (dd->subtables[dd->perm[index]].varToBeGrouped <= CUDD_LAZY_SOFT_GROUP) { + dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_SOFT_GROUP; + } + return(1); + +} /* end of Cudd_bddSetVarToBeGrouped */ + + +/**Function******************************************************************** + + Synopsis [Sets a variable to be a hard group.] + + Description [Sets a variable to be a hard group. This function is used + for lazy sifting. Returns 1 if successful; 0 otherwise.] + + SideEffects [modifies the manager] + + SeeAlso [Cudd_bddSetVarToBeGrouped Cudd_bddResetVarToBeGrouped + Cudd_bddIsVarHardGroup] + +******************************************************************************/ +int +Cudd_bddSetVarHardGroup( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return(0); + dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_HARD_GROUP; + return(1); + +} /* end of Cudd_bddSetVarHardGrouped */ + + +/**Function******************************************************************** + + Synopsis [Resets a variable not to be grouped.] + + Description [Resets a variable not to be grouped. This function is + used for lazy sifting. Returns 1 if successful; 0 otherwise.] + + SideEffects [modifies the manager] + + SeeAlso [Cudd_bddSetVarToBeGrouped Cudd_bddSetVarHardGroup] + +******************************************************************************/ +int +Cudd_bddResetVarToBeGrouped( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return(0); + if (dd->subtables[dd->perm[index]].varToBeGrouped <= + CUDD_LAZY_SOFT_GROUP) { + dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_NONE; + } + return(1); + +} /* end of Cudd_bddResetVarToBeGrouped */ + + +/**Function******************************************************************** + + Synopsis [Checks whether a variable is set to be grouped.] + + Description [Checks whether a variable is set to be grouped. This + function is used for lazy sifting.] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_bddIsVarToBeGrouped( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return(-1); + if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP) + return(0); + else + return(dd->subtables[dd->perm[index]].varToBeGrouped); + +} /* end of Cudd_bddIsVarToBeGrouped */ + + +/**Function******************************************************************** + + Synopsis [Sets a variable to be ungrouped.] + + Description [Sets a variable to be ungrouped. This function is used + for lazy sifting. Returns 1 if successful; 0 otherwise.] + + SideEffects [modifies the manager] + + SeeAlso [Cudd_bddIsVarToBeUngrouped] + +******************************************************************************/ +int +Cudd_bddSetVarToBeUngrouped( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return(0); + dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_UNGROUP; + return(1); + +} /* end of Cudd_bddSetVarToBeGrouped */ + + +/**Function******************************************************************** + + Synopsis [Checks whether a variable is set to be ungrouped.] + + Description [Checks whether a variable is set to be ungrouped. This + function is used for lazy sifting. Returns 1 if the variable is marked + to be ungrouped; 0 if the variable exists, but it is not marked to be + ungrouped; -1 if the variable does not exist.] + + SideEffects [none] + + SeeAlso [Cudd_bddSetVarToBeUngrouped] + +******************************************************************************/ +int +Cudd_bddIsVarToBeUngrouped( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return(-1); + return dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP; + +} /* end of Cudd_bddIsVarToBeGrouped */ + + +/**Function******************************************************************** + + Synopsis [Checks whether a variable is set to be in a hard group.] + + Description [Checks whether a variable is set to be in a hard group. This + function is used for lazy sifting. Returns 1 if the variable is marked + to be in a hard group; 0 if the variable exists, but it is not marked to be + in a hard group; -1 if the variable does not exist.] + + SideEffects [none] + + SeeAlso [Cudd_bddSetVarHardGroup] + +******************************************************************************/ +int +Cudd_bddIsVarHardGroup( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return(-1); + if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_HARD_GROUP) + return(1); + return(0); + +} /* end of Cudd_bddIsVarToBeGrouped */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Fixes a variable group tree.] + + Description [] + + SideEffects [Changes the variable group tree.] + + SeeAlso [] + +******************************************************************************/ +static void +fixVarTree( + MtrNode * treenode, + int * perm, + int size) +{ + treenode->index = treenode->low; + treenode->low = ((int) treenode->index < size) ? + perm[treenode->index] : treenode->index; + if (treenode->child != NULL) + fixVarTree(treenode->child, perm, size); + if (treenode->younger != NULL) + fixVarTree(treenode->younger, perm, size); + return; + +} /* end of fixVarTree */ + + +/**Function******************************************************************** + + Synopsis [Adds multiplicity groups to a ZDD variable group tree.] + + Description [Adds multiplicity groups to a ZDD variable group tree. + Returns 1 if successful; 0 otherwise. This function creates the groups + for set of ZDD variables (whose cardinality is given by parameter + multiplicity) that are created for each BDD variable in + Cudd_zddVarsFromBddVars. The crux of the matter is to determine the index + each new group. (The index of the first variable in the group.) + We first build all the groups for the children of a node, and then deal + with the ZDD variables that are directly attached to the node. The problem + for these is that the tree itself does not provide information on their + position inside the group. While we deal with the children of the node, + therefore, we keep track of all the positions they occupy. The remaining + positions in the tree can be freely used. Also, we keep track of all the + variables placed in the children. All the remaining variables are directly + attached to the group. We can then place any pair of variables not yet + grouped in any pair of available positions in the node.] + + SideEffects [Changes the variable group tree.] + + SeeAlso [Cudd_zddVarsFromBddVars] + +******************************************************************************/ +static int +addMultiplicityGroups( + DdManager *dd /* manager */, + MtrNode *treenode /* current tree node */, + int multiplicity /* how many ZDD vars per BDD var */, + char *vmask /* variable pairs for which a group has been already built */, + char *lmask /* levels for which a group has already been built*/) +{ + int startV, stopV, startL; + int i, j; + MtrNode *auxnode = treenode; + + while (auxnode != NULL) { + if (auxnode->child != NULL) { + addMultiplicityGroups(dd,auxnode->child,multiplicity,vmask,lmask); + } + /* Build remaining groups. */ + startV = dd->permZ[auxnode->index] / multiplicity; + startL = auxnode->low / multiplicity; + stopV = startV + auxnode->size / multiplicity; + /* Walk down vmask starting at startV and build missing groups. */ + for (i = startV, j = startL; i < stopV; i++) { + if (vmask[i] == 0) { + MtrNode *node; + while (lmask[j] == 1) j++; + node = Mtr_MakeGroup(auxnode, j * multiplicity, multiplicity, + MTR_FIXED); + if (node == NULL) { + return(0); + } + node->index = dd->invpermZ[i * multiplicity]; + vmask[i] = 1; + lmask[j] = 1; + } + } + auxnode = auxnode->younger; + } + return(1); + +} /* end of addMultiplicityGroups */ + diff --git a/abc70930/src/bdd/cudd/cuddAddAbs.c b/abc70930/src/bdd/cudd/cuddAddAbs.c new file mode 100644 index 00000000..b256ad0f --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddAddAbs.c @@ -0,0 +1,566 @@ +/**CFile*********************************************************************** + + FileName [cuddAddAbs.c] + + PackageName [cudd] + + Synopsis [Quantification functions for ADDs.] + + Description [External procedures included in this module: +
    +
  • Cudd_addExistAbstract() +
  • Cudd_addUnivAbstract() +
  • Cudd_addOrAbstract() +
+ Internal procedures included in this module: +
    +
  • cuddAddExistAbstractRecur() +
  • cuddAddUnivAbstractRecur() +
  • cuddAddOrAbstractRecur() +
+ Static procedures included in this module: +
    +
  • addCheckPositiveCube() +
] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAddAbs.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; +#endif + +static DdNode *two; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int addCheckPositiveCube ARGS((DdManager *manager, DdNode *cube)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Existentially Abstracts all the variables in cube from f.] + + Description [Abstracts all the variables in cube from f by summing + over all possible values taken by the variables. Returns the + abstracted ADD.] + + SideEffects [None] + + SeeAlso [Cudd_addUnivAbstract Cudd_bddExistAbstract + Cudd_addOrAbstract] + +******************************************************************************/ +DdNode * +Cudd_addExistAbstract( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *res; + + two = cuddUniqueConst(manager,(CUDD_VALUE_TYPE) 2); + if (two == NULL) return(NULL); + cuddRef(two); + + if (addCheckPositiveCube(manager, cube) == 0) { + (void) fprintf(manager->err,"Error: Can only abstract cubes"); + return(NULL); + } + + do { + manager->reordered = 0; + res = cuddAddExistAbstractRecur(manager, f, cube); + } while (manager->reordered == 1); + + if (res == NULL) { + Cudd_RecursiveDeref(manager,two); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(manager,two); + cuddDeref(res); + + return(res); + +} /* end of Cudd_addExistAbstract */ + + +/**Function******************************************************************** + + Synopsis [Universally Abstracts all the variables in cube from f.] + + Description [Abstracts all the variables in cube from f by taking + the product over all possible values taken by the variable. Returns + the abstracted ADD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addExistAbstract Cudd_bddUnivAbstract + Cudd_addOrAbstract] + +******************************************************************************/ +DdNode * +Cudd_addUnivAbstract( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *res; + + if (addCheckPositiveCube(manager, cube) == 0) { + (void) fprintf(manager->err,"Error: Can only abstract cubes"); + return(NULL); + } + + do { + manager->reordered = 0; + res = cuddAddUnivAbstractRecur(manager, f, cube); + } while (manager->reordered == 1); + + return(res); + +} /* end of Cudd_addUnivAbstract */ + + +/**Function******************************************************************** + + Synopsis [Disjunctively abstracts all the variables in cube from the + 0-1 ADD f.] + + Description [Abstracts all the variables in cube from the 0-1 ADD f + by taking the disjunction over all possible values taken by the + variables. Returns the abstracted ADD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addUnivAbstract Cudd_addExistAbstract] + +******************************************************************************/ +DdNode * +Cudd_addOrAbstract( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *res; + + if (addCheckPositiveCube(manager, cube) == 0) { + (void) fprintf(manager->err,"Error: Can only abstract cubes"); + return(NULL); + } + + do { + manager->reordered = 0; + res = cuddAddOrAbstractRecur(manager, f, cube); + } while (manager->reordered == 1); + return(res); + +} /* end of Cudd_addOrAbstract */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addExistAbstract.] + + Description [Performs the recursive step of Cudd_addExistAbstract. + Returns the ADD obtained by abstracting the variables of cube from f, + if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddAddExistAbstractRecur( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *T, *E, *res, *res1, *res2, *zero; + + statLine(manager); + zero = DD_ZERO(manager); + + /* Cube is guaranteed to be a cube at this point. */ + if (f == zero || cuddIsConstant(cube)) { + return(f); + } + + /* Abstract a variable that does not appear in f => multiply by 2. */ + if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { + res1 = cuddAddExistAbstractRecur(manager, f, cuddT(cube)); + if (res1 == NULL) return(NULL); + cuddRef(res1); + /* Use the "internal" procedure to be alerted in case of + ** dynamic reordering. If dynamic reordering occurs, we + ** have to abort the entire abstraction. + */ + res = cuddAddApplyRecur(manager,Cudd_addTimes,res1,two); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(manager,res1); + cuddDeref(res); + return(res); + } + + if ((res = cuddCacheLookup2(manager, Cudd_addExistAbstract, f, cube)) != NULL) { + return(res); + } + + T = cuddT(f); + E = cuddE(f); + + /* If the two indices are the same, so are their levels. */ + if (f->index == cube->index) { + res1 = cuddAddExistAbstractRecur(manager, T, cuddT(cube)); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddAddExistAbstractRecur(manager, E, cuddT(cube)); + if (res2 == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res2); + res = cuddAddApplyRecur(manager, Cudd_addPlus, res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res); + cuddDeref(res); + return(res); + } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ + res1 = cuddAddExistAbstractRecur(manager, T, cube); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddAddExistAbstractRecur(manager, E, cube); + if (res2 == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res2); + res = (res1 == res2) ? res1 : + cuddUniqueInter(manager, (int) f->index, res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + return(NULL); + } + cuddDeref(res1); + cuddDeref(res2); + cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res); + return(res); + } + +} /* end of cuddAddExistAbstractRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addUnivAbstract.] + + Description [Performs the recursive step of Cudd_addUnivAbstract. + Returns the ADD obtained by abstracting the variables of cube from f, + if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddAddUnivAbstractRecur( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *T, *E, *res, *res1, *res2, *one, *zero; + + statLine(manager); + one = DD_ONE(manager); + zero = DD_ZERO(manager); + + /* Cube is guaranteed to be a cube at this point. + ** zero and one are the only constatnts c such that c*c=c. + */ + if (f == zero || f == one || cube == one) { + return(f); + } + + /* Abstract a variable that does not appear in f. */ + if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { + res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube)); + if (res1 == NULL) return(NULL); + cuddRef(res1); + /* Use the "internal" procedure to be alerted in case of + ** dynamic reordering. If dynamic reordering occurs, we + ** have to abort the entire abstraction. + */ + res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(manager,res1); + cuddDeref(res); + return(res); + } + + if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) { + return(res); + } + + T = cuddT(f); + E = cuddE(f); + + /* If the two indices are the same, so are their levels. */ + if (f->index == cube->index) { + res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube)); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube)); + if (res2 == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res2); + res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); + cuddDeref(res); + return(res); + } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ + res1 = cuddAddUnivAbstractRecur(manager, T, cube); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddAddUnivAbstractRecur(manager, E, cube); + if (res2 == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res2); + res = (res1 == res2) ? res1 : + cuddUniqueInter(manager, (int) f->index, res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + return(NULL); + } + cuddDeref(res1); + cuddDeref(res2); + cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); + return(res); + } + +} /* end of cuddAddUnivAbstractRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addOrAbstract.] + + Description [Performs the recursive step of Cudd_addOrAbstract. + Returns the ADD obtained by abstracting the variables of cube from f, + if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddAddOrAbstractRecur( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *T, *E, *res, *res1, *res2, *one; + + statLine(manager); + one = DD_ONE(manager); + + /* Cube is guaranteed to be a cube at this point. */ + if (cuddIsConstant(f) || cube == one) { + return(f); + } + + /* Abstract a variable that does not appear in f. */ + if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { + res1 = cuddAddOrAbstractRecur(manager, f, cuddT(cube)); + if (res1 == NULL) return(NULL); + cuddRef(res1); + /* Use the "internal" procedure to be alerted in case of + ** dynamic reordering. If dynamic reordering occurs, we + ** have to abort the entire abstraction. + */ + res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res1); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(manager,res1); + cuddDeref(res); + return(res); + } + + if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) { + return(res); + } + + T = cuddT(f); + E = cuddE(f); + + /* If the two indices are the same, so are their levels. */ + if (f->index == cube->index) { + res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube)); + if (res1 == NULL) return(NULL); + cuddRef(res1); + if (res1 != one) { + res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube)); + if (res2 == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res2); + res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + } else { + res = res1; + } + cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); + cuddDeref(res); + return(res); + } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ + res1 = cuddAddOrAbstractRecur(manager, T, cube); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddAddOrAbstractRecur(manager, E, cube); + if (res2 == NULL) { + Cudd_RecursiveDeref(manager,res1); + return(NULL); + } + cuddRef(res2); + res = (res1 == res2) ? res1 : + cuddUniqueInter(manager, (int) f->index, res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(manager,res1); + Cudd_RecursiveDeref(manager,res2); + return(NULL); + } + cuddDeref(res1); + cuddDeref(res2); + cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); + return(res); + } + +} /* end of cuddAddOrAbstractRecur */ + + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Checks whether cube is an ADD representing the product + of positive literals.] + + Description [Checks whether cube is an ADD representing the product of + positive literals. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +addCheckPositiveCube( + DdManager * manager, + DdNode * cube) +{ + if (Cudd_IsComplement(cube)) return(0); + if (cube == DD_ONE(manager)) return(1); + if (cuddIsConstant(cube)) return(0); + if (cuddE(cube) == DD_ZERO(manager)) { + return(addCheckPositiveCube(manager, cuddT(cube))); + } + return(0); + +} /* end of addCheckPositiveCube */ + diff --git a/abc70930/src/bdd/cudd/cuddAddApply.c b/abc70930/src/bdd/cudd/cuddAddApply.c new file mode 100644 index 00000000..60c06de6 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddAddApply.c @@ -0,0 +1,917 @@ +/**CFile*********************************************************************** + + FileName [cuddAddApply.c] + + PackageName [cudd] + + Synopsis [Apply functions for ADDs and their operators.] + + Description [External procedures included in this module: +
    +
  • Cudd_addApply() +
  • Cudd_addMonadicApply() +
  • Cudd_addPlus() +
  • Cudd_addTimes() +
  • Cudd_addThreshold() +
  • Cudd_addSetNZ() +
  • Cudd_addDivide() +
  • Cudd_addMinus() +
  • Cudd_addMinimum() +
  • Cudd_addMaximum() +
  • Cudd_addOneZeroMaximum() +
  • Cudd_addDiff() +
  • Cudd_addAgreement() +
  • Cudd_addOr() +
  • Cudd_addNand() +
  • Cudd_addNor() +
  • Cudd_addXor() +
  • Cudd_addXnor() +
+ Internal procedures included in this module: +
    +
  • cuddAddApplyRecur() +
  • cuddAddMonadicApplyRecur() +
] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at Boulder. + The University of Colorado at Boulder makes no warranty about the + suitability of this software for any purpose. It is presented on an + AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAddApply.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; +#endif + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Applies op to the corresponding discriminants of f and g.] + + Description [Applies op to the corresponding discriminants of f and g. + Returns a pointer to the result if succssful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes + Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum + Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement + Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor] + +******************************************************************************/ +DdNode * +Cudd_addApply( + DdManager * dd, + DdNode * (*op)(DdManager *, DdNode **, DdNode **), + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddAddApplyRecur(dd,op,f,g); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addApply */ + + +/**Function******************************************************************** + + Synopsis [Integer and floating point addition.] + + Description [Integer and floating point addition. Returns NULL if not + a terminal case; f+g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addPlus( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *res; + DdNode *F, *G; + CUDD_VALUE_TYPE value; + + F = *f; G = *g; + if (F == DD_ZERO(dd)) return(G); + if (G == DD_ZERO(dd)) return(F); + if (cuddIsConstant(F) && cuddIsConstant(G)) { + value = cuddV(F)+cuddV(G); + res = cuddUniqueConst(dd,value); + return(res); + } + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addPlus */ + + +/**Function******************************************************************** + + Synopsis [Integer and floating point multiplication.] + + Description [Integer and floating point multiplication. Returns NULL + if not a terminal case; f * g otherwise. This function can be used also + to take the AND of two 0-1 ADDs.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addTimes( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *res; + DdNode *F, *G; + CUDD_VALUE_TYPE value; + + F = *f; G = *g; + if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd)); + if (F == DD_ONE(dd)) return(G); + if (G == DD_ONE(dd)) return(F); + if (cuddIsConstant(F) && cuddIsConstant(G)) { + value = cuddV(F)*cuddV(G); + res = cuddUniqueConst(dd,value); + return(res); + } + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addTimes */ + + +/**Function******************************************************************** + + Synopsis [f if f>=g; 0 if f<g.] + + Description [Threshold operator for Apply (f if f >=g; 0 if f<g). + Returns NULL if not a terminal case; f op g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addThreshold( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G || F == DD_PLUS_INFINITY(dd)) return(F); + if (cuddIsConstant(F) && cuddIsConstant(G)) { + if (cuddV(F) >= cuddV(G)) { + return(F); + } else { + return(DD_ZERO(dd)); + } + } + return(NULL); + +} /* end of Cudd_addThreshold */ + + +/**Function******************************************************************** + + Synopsis [This operator sets f to the value of g wherever g != 0.] + + Description [This operator sets f to the value of g wherever g != 0. + Returns NULL if not a terminal case; f op g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addSetNZ( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(F); + if (F == DD_ZERO(dd)) return(G); + if (G == DD_ZERO(dd)) return(F); + if (cuddIsConstant(G)) return(G); + return(NULL); + +} /* end of Cudd_addSetNZ */ + + +/**Function******************************************************************** + + Synopsis [Integer and floating point division.] + + Description [Integer and floating point division. Returns NULL if not + a terminal case; f / g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addDivide( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *res; + DdNode *F, *G; + CUDD_VALUE_TYPE value; + + F = *f; G = *g; + /* We would like to use F == G -> F/G == 1, but F and G may + ** contain zeroes. */ + if (F == DD_ZERO(dd)) return(DD_ZERO(dd)); + if (G == DD_ONE(dd)) return(F); + if (cuddIsConstant(F) && cuddIsConstant(G)) { + value = cuddV(F)/cuddV(G); + res = cuddUniqueConst(dd,value); + return(res); + } + return(NULL); + +} /* end of Cudd_addDivide */ + + +/**Function******************************************************************** + + Synopsis [Integer and floating point subtraction.] + + Description [Integer and floating point subtraction. Returns NULL if + not a terminal case; f - g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addMinus( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *res; + DdNode *F, *G; + CUDD_VALUE_TYPE value; + + F = *f; G = *g; + if (F == G) return(DD_ZERO(dd)); + if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G)); + if (G == DD_ZERO(dd)) return(F); + if (cuddIsConstant(F) && cuddIsConstant(G)) { + value = cuddV(F)-cuddV(G); + res = cuddUniqueConst(dd,value); + return(res); + } + return(NULL); + +} /* end of Cudd_addMinus */ + + +/**Function******************************************************************** + + Synopsis [Integer and floating point min.] + + Description [Integer and floating point min for Cudd_addApply. + Returns NULL if not a terminal case; min(f,g) otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addMinimum( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == DD_PLUS_INFINITY(dd)) return(G); + if (G == DD_PLUS_INFINITY(dd)) return(F); + if (F == G) return(F); +#if 0 + /* These special cases probably do not pay off. */ + if (F == DD_MINUS_INFINITY(dd)) return(F); + if (G == DD_MINUS_INFINITY(dd)) return(G); +#endif + if (cuddIsConstant(F) && cuddIsConstant(G)) { + if (cuddV(F) <= cuddV(G)) { + return(F); + } else { + return(G); + } + } + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addMinimum */ + + +/**Function******************************************************************** + + Synopsis [Integer and floating point max.] + + Description [Integer and floating point max for Cudd_addApply. + Returns NULL if not a terminal case; max(f,g) otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addMaximum( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(F); + if (F == DD_MINUS_INFINITY(dd)) return(G); + if (G == DD_MINUS_INFINITY(dd)) return(F); +#if 0 + /* These special cases probably do not pay off. */ + if (F == DD_PLUS_INFINITY(dd)) return(F); + if (G == DD_PLUS_INFINITY(dd)) return(G); +#endif + if (cuddIsConstant(F) && cuddIsConstant(G)) { + if (cuddV(F) >= cuddV(G)) { + return(F); + } else { + return(G); + } + } + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addMaximum */ + + +/**Function******************************************************************** + + Synopsis [Returns 1 if f > g and 0 otherwise.] + + Description [Returns 1 if f > g and 0 otherwise. Used in + conjunction with Cudd_addApply. Returns NULL if not a terminal + case.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addOneZeroMaximum( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + + if (*f == *g) return(DD_ZERO(dd)); + if (*g == DD_PLUS_INFINITY(dd)) + return DD_ZERO(dd); + if (cuddIsConstant(*f) && cuddIsConstant(*g)) { + if (cuddV(*f) > cuddV(*g)) { + return(DD_ONE(dd)); + } else { + return(DD_ZERO(dd)); + } + } + + return(NULL); + +} /* end of Cudd_addOneZeroMaximum */ + + +/**Function******************************************************************** + + Synopsis [Returns plusinfinity if f=g; returns min(f,g) if f!=g.] + + Description [Returns NULL if not a terminal case; f op g otherwise, + where f op g is plusinfinity if f=g; min(f,g) if f!=g.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addDiff( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(DD_PLUS_INFINITY(dd)); + if (F == DD_PLUS_INFINITY(dd)) return(G); + if (G == DD_PLUS_INFINITY(dd)) return(F); + if (cuddIsConstant(F) && cuddIsConstant(G)) { + if (cuddV(F) != cuddV(G)) { + if (cuddV(F) < cuddV(G)) { + return(F); + } else { + return(G); + } + } else { + return(DD_PLUS_INFINITY(dd)); + } + } + return(NULL); + +} /* end of Cudd_addDiff */ + + +/**Function******************************************************************** + + Synopsis [f if f==g; background if f!=g.] + + Description [Returns NULL if not a terminal case; f op g otherwise, + where f op g is f if f==g; background if f!=g.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addAgreement( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(F); + if (F == dd->background) return(F); + if (G == dd->background) return(G); + if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background); + return(NULL); + +} /* end of Cudd_addAgreement */ + + +/**Function******************************************************************** + + Synopsis [Disjunction of two 0-1 ADDs.] + + Description [Disjunction of two 0-1 ADDs. Returns NULL + if not a terminal case; f OR g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addOr( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd)); + if (cuddIsConstant(F)) return(G); + if (cuddIsConstant(G)) return(F); + if (F == G) return(F); + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addOr */ + + +/**Function******************************************************************** + + Synopsis [NAND of two 0-1 ADDs.] + + Description [NAND of two 0-1 ADDs. Returns NULL + if not a terminal case; f NAND g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addNand( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd)); + if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addNand */ + + +/**Function******************************************************************** + + Synopsis [NOR of two 0-1 ADDs.] + + Description [NOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f NOR g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addNor( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd)); + if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd)); + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addNor */ + + +/**Function******************************************************************** + + Synopsis [XOR of two 0-1 ADDs.] + + Description [XOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f XOR g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addXor( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(DD_ZERO(dd)); + if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd)); + if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd)); + if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addXor */ + + +/**Function******************************************************************** + + Synopsis [XNOR of two 0-1 ADDs.] + + Description [XNOR of two 0-1 ADDs. Returns NULL + if not a terminal case; f XNOR g otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addXnor( + DdManager * dd, + DdNode ** f, + DdNode ** g) +{ + DdNode *F, *G; + + F = *f; G = *g; + if (F == G) return(DD_ONE(dd)); + if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd)); + if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd)); + if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); + if (F > G) { /* swap f and g */ + *f = G; + *g = F; + } + return(NULL); + +} /* end of Cudd_addXnor */ + + +/**Function******************************************************************** + + Synopsis [Applies op to the discriminants of f.] + + Description [Applies op to the discriminants of f. + Returns a pointer to the result if succssful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addApply Cudd_addLog] + +******************************************************************************/ +DdNode * +Cudd_addMonadicApply( + DdManager * dd, + DdNode * (*op)(DdManager *, DdNode *), + DdNode * f) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddAddMonadicApplyRecur(dd,op,f); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addMonadicApply */ + + +/**Function******************************************************************** + + Synopsis [Natural logarithm of an ADD.] + + Description [Natural logarithm of an ADDs. Returns NULL + if not a terminal case; log(f) otherwise. The discriminants of f must + be positive double's.] + + SideEffects [None] + + SeeAlso [Cudd_addMonadicApply] + +******************************************************************************/ +DdNode * +Cudd_addLog( + DdManager * dd, + DdNode * f) +{ + if (cuddIsConstant(f)) { + CUDD_VALUE_TYPE value = log(cuddV(f)); + DdNode *res = cuddUniqueConst(dd,value); + return(res); + } + return(NULL); + +} /* end of Cudd_addLog */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addApply.] + + Description [Performs the recursive step of Cudd_addApply. Returns a + pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddAddMonadicApplyRecur] + +******************************************************************************/ +DdNode * +cuddAddApplyRecur( + DdManager * dd, + DdNode * (*op)(DdManager *, DdNode **, DdNode **), + DdNode * f, + DdNode * g) +{ + DdNode *res, + *fv, *fvn, *gv, *gvn, + *T, *E; + unsigned int ford, gord; + unsigned int index; + DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); + + /* Check terminal cases. Op may swap f and g to increase the + * cache hit rate. + */ + statLine(dd); + res = (*op)(dd,&f,&g); + if (res != NULL) return(res); + + /* Check cache. */ + cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) op; + res = cuddCacheLookup2(dd,cacheOp,f,g); + if (res != NULL) return(res); + + /* Recursive step. */ + ford = cuddI(dd,f->index); + gord = cuddI(dd,g->index); + if (ford <= gord) { + index = f->index; + fv = cuddT(f); + fvn = cuddE(f); + } else { + index = g->index; + fv = fvn = f; + } + if (gord <= ford) { + gv = cuddT(g); + gvn = cuddE(g); + } else { + gv = gvn = g; + } + + T = cuddAddApplyRecur(dd,op,fv,gv); + if (T == NULL) return(NULL); + cuddRef(T); + + E = cuddAddApplyRecur(dd,op,fvn,gvn); + if (E == NULL) { + Cudd_RecursiveDeref(dd,T); + return(NULL); + } + cuddRef(E); + + res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert2(dd,cacheOp,f,g,res); + + return(res); + +} /* end of cuddAddApplyRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addMonadicApply.] + + Description [Performs the recursive step of Cudd_addMonadicApply. Returns a + pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddAddApplyRecur] + +******************************************************************************/ +DdNode * +cuddAddMonadicApplyRecur( + DdManager * dd, + DdNode * (*op)(DdManager *, DdNode *), + DdNode * f) +{ + DdNode *res, *ft, *fe, *T, *E; + unsigned int ford; + unsigned int index; + + /* Check terminal cases. */ + statLine(dd); + res = (*op)(dd,f); + if (res != NULL) return(res); + + /* Check cache. */ + res = cuddCacheLookup1(dd,op,f); + if (res != NULL) return(res); + + /* Recursive step. */ + ford = cuddI(dd,f->index); + index = f->index; + ft = cuddT(f); + fe = cuddE(f); + + T = cuddAddMonadicApplyRecur(dd,op,ft); + if (T == NULL) return(NULL); + cuddRef(T); + + E = cuddAddMonadicApplyRecur(dd,op,fe); + if (E == NULL) { + Cudd_RecursiveDeref(dd,T); + return(NULL); + } + cuddRef(E); + + res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert1(dd,op,f,res); + + return(res); + +} /* end of cuddAddMonadicApplyRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/cudd/cuddAddFind.c b/abc70930/src/bdd/cudd/cuddAddFind.c new file mode 100644 index 00000000..0469b014 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddAddFind.c @@ -0,0 +1,283 @@ +/**CFile*********************************************************************** + + FileName [cuddAddFind.c] + + PackageName [cudd] + + Synopsis [Functions to find maximum and minimum in an ADD and to + extract the i-th bit.] + + Description [External procedures included in this module: +
    +
  • Cudd_addFindMax() +
  • Cudd_addFindMin() +
  • Cudd_addIthBit() +
+ Static functions included in this module: +
    +
  • addDoIthBit() +
] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAddFind.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; +#endif + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * addDoIthBit ARGS((DdManager *dd, DdNode *f, DdNode *index)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Finds the maximum discriminant of f.] + + Description [Returns a pointer to a constant ADD.] + + SideEffects [None] + +******************************************************************************/ +DdNode * +Cudd_addFindMax( + DdManager * dd, + DdNode * f) +{ + DdNode *t, *e, *res; + + statLine(dd); + if (cuddIsConstant(f)) { + return(f); + } + + res = cuddCacheLookup1(dd,Cudd_addFindMax,f); + if (res != NULL) { + return(res); + } + + t = Cudd_addFindMax(dd,cuddT(f)); + if (t == DD_PLUS_INFINITY(dd)) return(t); + + e = Cudd_addFindMax(dd,cuddE(f)); + + res = (cuddV(t) >= cuddV(e)) ? t : e; + + cuddCacheInsert1(dd,Cudd_addFindMax,f,res); + + return(res); + +} /* end of Cudd_addFindMax */ + + +/**Function******************************************************************** + + Synopsis [Finds the minimum discriminant of f.] + + Description [Returns a pointer to a constant ADD.] + + SideEffects [None] + +******************************************************************************/ +DdNode * +Cudd_addFindMin( + DdManager * dd, + DdNode * f) +{ + DdNode *t, *e, *res; + + statLine(dd); + if (cuddIsConstant(f)) { + return(f); + } + + res = cuddCacheLookup1(dd,Cudd_addFindMin,f); + if (res != NULL) { + return(res); + } + + t = Cudd_addFindMin(dd,cuddT(f)); + if (t == DD_MINUS_INFINITY(dd)) return(t); + + e = Cudd_addFindMin(dd,cuddE(f)); + + res = (cuddV(t) <= cuddV(e)) ? t : e; + + cuddCacheInsert1(dd,Cudd_addFindMin,f,res); + + return(res); + +} /* end of Cudd_addFindMin */ + + +/**Function******************************************************************** + + Synopsis [Extracts the i-th bit from an ADD.] + + Description [Produces an ADD from another ADD by replacing all + discriminants whose i-th bit is equal to 1 with 1, and all other + discriminants with 0. The i-th bit refers to the integer + representation of the leaf value. If the value is has a fractional + part, it is ignored. Repeated calls to this procedure allow one to + transform an integer-valued ADD into an array of ADDs, one for each + bit of the leaf values. Returns a pointer to the resulting ADD if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addBddIthBit] + +******************************************************************************/ +DdNode * +Cudd_addIthBit( + DdManager * dd, + DdNode * f, + int bit) +{ + DdNode *res; + DdNode *index; + + /* Use a constant node to remember the bit, so that we can use the + ** global cache. + */ + index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit); + if (index == NULL) return(NULL); + cuddRef(index); + + do { + dd->reordered = 0; + res = addDoIthBit(dd, f, index); + } while (dd->reordered == 1); + + if (res == NULL) { + Cudd_RecursiveDeref(dd, index); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, index); + cuddDeref(res); + return(res); + +} /* end of Cudd_addIthBit */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step for Cudd_addIthBit.] + + Description [Performs the recursive step for Cudd_addIthBit. + Returns a pointer to the BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +addDoIthBit( + DdManager * dd, + DdNode * f, + DdNode * index) +{ + DdNode *res, *T, *E; + DdNode *fv, *fvn; + int mask, value; + int v; + + statLine(dd); + /* Check terminal case. */ + if (cuddIsConstant(f)) { + mask = 1 << ((int) cuddV(index)); + value = (int) cuddV(f); + return((value & mask) == 0 ? DD_ZERO(dd) : DD_ONE(dd)); + } + + /* Check cache. */ + res = cuddCacheLookup2(dd,addDoIthBit,f,index); + if (res != NULL) return(res); + + /* Recursive step. */ + v = f->index; + fv = cuddT(f); fvn = cuddE(f); + + T = addDoIthBit(dd,fv,index); + if (T == NULL) return(NULL); + cuddRef(T); + + E = addDoIthBit(dd,fvn,index); + if (E == NULL) { + Cudd_RecursiveDeref(dd, T); + return(NULL); + } + cuddRef(E); + + res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert2(dd,addDoIthBit,f,index,res); + + return(res); + +} /* end of addDoIthBit */ + diff --git a/abc70930/src/bdd/cudd/cuddAddInv.c b/abc70930/src/bdd/cudd/cuddAddInv.c new file mode 100644 index 00000000..fc4a340b --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddAddInv.c @@ -0,0 +1,172 @@ +/**CFile*********************************************************************** + + FileName [cuddAddInv.c] + + PackageName [cudd] + + Synopsis [Function to compute the scalar inverse of an ADD.] + + Description [External procedures included in this module: +
    +
  • Cudd_addScalarInverse() +
+ Internal procedures included in this module: +
    +
  • cuddAddScalarInverseRecur() +
] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAddInv.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; +#endif + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes the scalar inverse of an ADD.] + + Description [Computes an n ADD where the discriminants are the + multiplicative inverses of the corresponding discriminants of the + argument ADD. Returns a pointer to the resulting ADD in case of + success. Returns NULL if any discriminants smaller than epsilon is + encountered.] + + SideEffects [None] + +******************************************************************************/ +DdNode * +Cudd_addScalarInverse( + DdManager * dd, + DdNode * f, + DdNode * epsilon) +{ + DdNode *res; + + if (!cuddIsConstant(epsilon)) { + (void) fprintf(dd->err,"Invalid epsilon\n"); + return(NULL); + } + do { + dd->reordered = 0; + res = cuddAddScalarInverseRecur(dd,f,epsilon); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addScalarInverse */ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of addScalarInverse.] + + Description [Returns a pointer to the resulting ADD in case of + success. Returns NULL if any discriminants smaller than epsilon is + encountered.] + + SideEffects [None] + +******************************************************************************/ +DdNode * +cuddAddScalarInverseRecur( + DdManager * dd, + DdNode * f, + DdNode * epsilon) +{ + DdNode *t, *e, *res; + CUDD_VALUE_TYPE value; + + statLine(dd); + if (cuddIsConstant(f)) { + if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL); + value = 1.0 / cuddV(f); + res = cuddUniqueConst(dd,value); + return(res); + } + + res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon); + if (res != NULL) return(res); + + t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon); + if (t == NULL) return(NULL); + cuddRef(t); + + e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon); + if (e == NULL) { + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + cuddRef(e); + + res = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e); + if (res == NULL) { + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + + cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res); + + return(res); + +} /* end of cuddAddScalarInverseRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/cudd/cuddAddIte.c b/abc70930/src/bdd/cudd/cuddAddIte.c new file mode 100644 index 00000000..71f8070f --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddAddIte.c @@ -0,0 +1,613 @@ +/**CFile*********************************************************************** + + FileName [cuddAddIte.c] + + PackageName [cudd] + + Synopsis [ADD ITE function and satellites.] + + Description [External procedures included in this module: +
    +
  • Cudd_addIte() +
  • Cudd_addIteConstant() +
  • Cudd_addEvalConst() +
  • Cudd_addCmpl() +
  • Cudd_addLeq() +
+ Internal procedures included in this module: +
    +
  • cuddAddIteRecur() +
  • cuddAddCmplRecur() +
+ Static procedures included in this module: +
    +
  • addVarToConst() +
] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAddIte.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; +#endif + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void addVarToConst ARGS((DdNode *f, DdNode **gp, DdNode **hp, DdNode *one, DdNode *zero)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements ITE(f,g,h).] + + Description [Implements ITE(f,g,h). This procedure assumes that f is + a 0-1 ADD. Returns a pointer to the resulting ADD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddIte Cudd_addIteConstant Cudd_addApply] + +******************************************************************************/ +DdNode * +Cudd_addIte( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddAddIteRecur(dd,f,g,h); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addIte */ + + +/**Function******************************************************************** + + Synopsis [Implements ITEconstant for ADDs.] + + Description [Implements ITEconstant for ADDs. f must be a 0-1 ADD. + Returns a pointer to the resulting ADD (which may or may not be + constant) or DD_NON_CONSTANT. No new nodes are created. This function + can be used, for instance, to check that g has a constant value + (specified by h) whenever f is 1. If the constant value is unknown, + then one should use Cudd_addEvalConst.] + + SideEffects [None] + + SeeAlso [Cudd_addIte Cudd_addEvalConst Cudd_bddIteConstant] + +******************************************************************************/ +DdNode * +Cudd_addIteConstant( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h) +{ + DdNode *one,*zero; + DdNode *Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*r,*t,*e; + unsigned int topf,topg,toph,v; + + statLine(dd); + /* Trivial cases. */ + if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */ + return(g); + } + if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ + return(h); + } + + /* From now on, f is known not to be a constant. */ + addVarToConst(f,&g,&h,one,zero); + + /* Check remaining one variable cases. */ + if (g == h) { /* ITE(F,G,G) = G */ + return(g); + } + if (cuddIsConstant(g) && cuddIsConstant(h)) { + return(DD_NON_CONSTANT); + } + + topf = cuddI(dd,f->index); + topg = cuddI(dd,g->index); + toph = cuddI(dd,h->index); + v = ddMin(topg,toph); + + /* ITE(F,G,H) = (x,G,H) (non constant) if F = (x,1,0), x < top(G,H). */ + if (topf < v && cuddIsConstant(cuddT(f)) && cuddIsConstant(cuddE(f))) { + return(DD_NON_CONSTANT); + } + + /* Check cache. */ + r = cuddConstantLookup(dd,DD_ADD_ITE_CONSTANT_TAG,f,g,h); + if (r != NULL) { + return(r); + } + + /* Compute cofactors. */ + if (topf <= v) { + v = ddMin(topf,v); /* v = top_var(F,G,H) */ + Fv = cuddT(f); Fnv = cuddE(f); + } else { + Fv = Fnv = f; + } + if (topg == v) { + Gv = cuddT(g); Gnv = cuddE(g); + } else { + Gv = Gnv = g; + } + if (toph == v) { + Hv = cuddT(h); Hnv = cuddE(h); + } else { + Hv = Hnv = h; + } + + /* Recursive step. */ + t = Cudd_addIteConstant(dd,Fv,Gv,Hv); + if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) { + cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); + return(DD_NON_CONSTANT); + } + e = Cudd_addIteConstant(dd,Fnv,Gnv,Hnv); + if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) { + cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); + return(DD_NON_CONSTANT); + } + cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, t); + return(t); + +} /* end of Cudd_addIteConstant */ + + +/**Function******************************************************************** + + Synopsis [Checks whether ADD g is constant whenever ADD f is 1.] + + Description [Checks whether ADD g is constant whenever ADD f is 1. f + must be a 0-1 ADD. Returns a pointer to the resulting ADD (which may + or may not be constant) or DD_NON_CONSTANT. If f is identically 0, + the check is assumed to be successful, and the background value is + returned. No new nodes are created.] + + SideEffects [None] + + SeeAlso [Cudd_addIteConstant Cudd_addLeq] + +******************************************************************************/ +DdNode * +Cudd_addEvalConst( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *zero; + DdNode *Fv,*Fnv,*Gv,*Gnv,*r,*t,*e; + unsigned int topf,topg; + +#ifdef DD_DEBUG + assert(!Cudd_IsComplement(f)); +#endif + + statLine(dd); + /* Terminal cases. */ + if (f == DD_ONE(dd) || cuddIsConstant(g)) { + return(g); + } + if (f == (zero = DD_ZERO(dd))) { + return(dd->background); + } + +#ifdef DD_DEBUG + assert(!cuddIsConstant(f)); +#endif + /* From now on, f and g are known not to be constants. */ + + topf = cuddI(dd,f->index); + topg = cuddI(dd,g->index); + + /* Check cache. */ + r = cuddConstantLookup(dd,DD_ADD_EVAL_CONST_TAG,f,g,g); + if (r != NULL) { + return(r); + } + + /* Compute cofactors. */ + if (topf <= topg) { + Fv = cuddT(f); Fnv = cuddE(f); + } else { + Fv = Fnv = f; + } + if (topg <= topf) { + Gv = cuddT(g); Gnv = cuddE(g); + } else { + Gv = Gnv = g; + } + + /* Recursive step. */ + if (Fv != zero) { + t = Cudd_addEvalConst(dd,Fv,Gv); + if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) { + cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT); + return(DD_NON_CONSTANT); + } + if (Fnv != zero) { + e = Cudd_addEvalConst(dd,Fnv,Gnv); + if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) { + cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT); + return(DD_NON_CONSTANT); + } + } + cuddCacheInsert2(dd,Cudd_addEvalConst,f,g,t); + return(t); + } else { /* Fnv must be != zero */ + e = Cudd_addEvalConst(dd,Fnv,Gnv); + cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, e); + return(e); + } + +} /* end of Cudd_addEvalConst */ + + +/**Function******************************************************************** + + Synopsis [Computes the complement of an ADD a la C language.] + + Description [Computes the complement of an ADD a la C language: The + complement of 0 is 1 and the complement of everything else is 0. + Returns a pointer to the resulting ADD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addNegate] + +******************************************************************************/ +DdNode * +Cudd_addCmpl( + DdManager * dd, + DdNode * f) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddAddCmplRecur(dd,f); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addCmpl */ + + +/**Function******************************************************************** + + Synopsis [Determines whether f is less than or equal to g.] + + Description [Returns 1 if f is less than or equal to g; 0 otherwise. + No new nodes are created. This procedure works for arbitrary ADDs. + For 0-1 ADDs Cudd_addEvalConst is more efficient.] + + SideEffects [None] + + SeeAlso [Cudd_addIteConstant Cudd_addEvalConst Cudd_bddLeq] + +******************************************************************************/ +int +Cudd_addLeq( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *tmp, *fv, *fvn, *gv, *gvn; + unsigned int topf, topg, res; + + /* Terminal cases. */ + if (f == g) return(1); + + statLine(dd); + if (cuddIsConstant(f)) { + if (cuddIsConstant(g)) return(cuddV(f) <= cuddV(g)); + if (f == DD_MINUS_INFINITY(dd)) return(1); + if (f == DD_PLUS_INFINITY(dd)) return(0); /* since f != g */ + } + if (g == DD_PLUS_INFINITY(dd)) return(1); + if (g == DD_MINUS_INFINITY(dd)) return(0); /* since f != g */ + + /* Check cache. */ + tmp = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, + DdNode *))Cudd_addLeq,f,g); + if (tmp != NULL) { + return(tmp == DD_ONE(dd)); + } + + /* Compute cofactors. One of f and g is not constant. */ + topf = cuddI(dd,f->index); + topg = cuddI(dd,g->index); + if (topf <= topg) { + fv = cuddT(f); fvn = cuddE(f); + } else { + fv = fvn = f; + } + if (topg <= topf) { + gv = cuddT(g); gvn = cuddE(g); + } else { + gv = gvn = g; + } + + res = Cudd_addLeq(dd,fvn,gvn) && Cudd_addLeq(dd,fv,gv); + + /* Store result in cache and return. */ + cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *)) + Cudd_addLeq,f,g,Cudd_NotCond(DD_ONE(dd),res==0)); + return(res); + +} /* end of Cudd_addLeq */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_addIte(f,g,h).] + + Description [Implements the recursive step of Cudd_addIte(f,g,h). + Returns a pointer to the resulting ADD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addIte] + +******************************************************************************/ +DdNode * +cuddAddIteRecur( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h) +{ + DdNode *one,*zero; + DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e; + unsigned int topf,topg,toph,v; + int index; + + statLine(dd); + /* Trivial cases. */ + + /* One variable cases. */ + if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */ + return(g); + } + if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ + return(h); + } + + /* From now on, f is known to not be a constant. */ + addVarToConst(f,&g,&h,one,zero); + + /* Check remaining one variable cases. */ + if (g == h) { /* ITE(F,G,G) = G */ + return(g); + } + + if (g == one) { /* ITE(F,1,0) = F */ + if (h == zero) return(f); + } + + topf = cuddI(dd,f->index); + topg = cuddI(dd,g->index); + toph = cuddI(dd,h->index); + v = ddMin(topg,toph); + + /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */ + if (topf < v && cuddT(f) == one && cuddE(f) == zero) { + r = cuddUniqueInter(dd,(int)f->index,g,h); + return(r); + } + if (topf < v && cuddT(f) == zero && cuddE(f) == one) { + r = cuddUniqueInter(dd,(int)f->index,h,g); + return(r); + } + + /* Check cache. */ + r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h); + if (r != NULL) { + return(r); + } + + /* Compute cofactors. */ + if (topf <= v) { + v = ddMin(topf,v); /* v = top_var(F,G,H) */ + index = f->index; + Fv = cuddT(f); Fnv = cuddE(f); + } else { + Fv = Fnv = f; + } + if (topg == v) { + index = g->index; + Gv = cuddT(g); Gnv = cuddE(g); + } else { + Gv = Gnv = g; + } + if (toph == v) { + index = h->index; + Hv = cuddT(h); Hnv = cuddE(h); + } else { + Hv = Hnv = h; + } + + /* Recursive step. */ + t = cuddAddIteRecur(dd,Fv,Gv,Hv); + if (t == NULL) return(NULL); + cuddRef(t); + + e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv); + if (e == NULL) { + Cudd_RecursiveDeref(dd,t); + return(NULL); + } + cuddRef(e); + + r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); + if (r == NULL) { + Cudd_RecursiveDeref(dd,t); + Cudd_RecursiveDeref(dd,e); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + + cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r); + + return(r); + +} /* end of cuddAddIteRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addCmpl.] + + Description [Performs the recursive step of Cudd_addCmpl. Returns a + pointer to the resulting ADD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addCmpl] + +******************************************************************************/ +DdNode * +cuddAddCmplRecur( + DdManager * dd, + DdNode * f) +{ + DdNode *one,*zero; + DdNode *r,*Fv,*Fnv,*t,*e; + + statLine(dd); + one = DD_ONE(dd); + zero = DD_ZERO(dd); + + if (cuddIsConstant(f)) { + if (f == zero) { + return(one); + } else { + return(zero); + } + } + r = cuddCacheLookup1(dd,Cudd_addCmpl,f); + if (r != NULL) { + return(r); + } + Fv = cuddT(f); + Fnv = cuddE(f); + t = cuddAddCmplRecur(dd,Fv); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddAddCmplRecur(dd,Fnv); + if (e == NULL) { + Cudd_RecursiveDeref(dd,t); + return(NULL); + } + cuddRef(e); + r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e); + if (r == NULL) { + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + cuddCacheInsert1(dd,Cudd_addCmpl,f,r); + return(r); + +} /* end of cuddAddCmplRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Replaces variables with constants if possible (part of + canonical form).] + + Description [] + + SideEffects [None] + +******************************************************************************/ +static void +addVarToConst( + DdNode * f, + DdNode ** gp, + DdNode ** hp, + DdNode * one, + DdNode * zero) +{ + DdNode *g = *gp; + DdNode *h = *hp; + + if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ + *gp = one; + } + + if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ + *hp = zero; + } + +} /* end of addVarToConst */ diff --git a/abc70930/src/bdd/cudd/cuddAddNeg.c b/abc70930/src/bdd/cudd/cuddAddNeg.c new file mode 100644 index 00000000..bdb08ddc --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddAddNeg.c @@ -0,0 +1,262 @@ +/**CFile*********************************************************************** + + FileName [cuddAddNeg.c] + + PackageName [cudd] + + Synopsis [function to compute the negation of an ADD.] + + Description [External procedures included in this module: +
    +
  • Cudd_addNegate() +
  • Cudd_addRoundOff() +
+ Internal procedures included in this module: +
    +
  • cuddAddNegateRecur() +
  • cuddAddRoundOffRecur() +
] + + Author [Fabio Somenzi, Balakrishna Kumthekar] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAddNeg.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; +#endif + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes the additive inverse of an ADD.] + + Description [Computes the additive inverse of an ADD. Returns a pointer + to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addCmpl] + +******************************************************************************/ +DdNode * +Cudd_addNegate( + DdManager * dd, + DdNode * f) +{ + DdNode *res; + + do { + res = cuddAddNegateRecur(dd,f); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addNegate */ + + +/**Function******************************************************************** + + Synopsis [Rounds off the discriminants of an ADD.] + + Description [Rounds off the discriminants of an ADD. The discriminants are + rounded off to N digits after the decimal. Returns a pointer to the result + ADD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_addRoundOff( + DdManager * dd, + DdNode * f, + int N) +{ + DdNode *res; + double trunc = pow(10.0,(double)N); + + do { + res = cuddAddRoundOffRecur(dd,f,trunc); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addRoundOff */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_addNegate.] + + Description [Implements the recursive step of Cudd_addNegate. + Returns a pointer to the result.] + + SideEffects [None] + +******************************************************************************/ +DdNode * +cuddAddNegateRecur( + DdManager * dd, + DdNode * f) +{ + DdNode *res, + *fv, *fvn, + *T, *E; + + statLine(dd); + /* Check terminal cases. */ + if (cuddIsConstant(f)) { + res = cuddUniqueConst(dd,-cuddV(f)); + return(res); + } + + /* Check cache */ + res = cuddCacheLookup1(dd,Cudd_addNegate,f); + if (res != NULL) return(res); + + /* Recursive Step */ + fv = cuddT(f); + fvn = cuddE(f); + T = cuddAddNegateRecur(dd,fv); + if (T == NULL) return(NULL); + cuddRef(T); + + E = cuddAddNegateRecur(dd,fvn); + if (E == NULL) { + Cudd_RecursiveDeref(dd,T); + return(NULL); + } + cuddRef(E); + res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert1(dd,Cudd_addNegate,f,res); + + return(res); + +} /* end of cuddAddNegateRecur */ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_addRoundOff.] + + Description [Implements the recursive step of Cudd_addRoundOff. + Returns a pointer to the result.] + + SideEffects [None] + +******************************************************************************/ +DdNode * +cuddAddRoundOffRecur( + DdManager * dd, + DdNode * f, + double trunc) +{ + + DdNode *res, *fv, *fvn, *T, *E; + double n; + DdNode *(*cacheOp)(DdManager *, DdNode *); + + statLine(dd); + if (cuddIsConstant(f)) { + n = ceil(cuddV(f)*trunc)/trunc; + res = cuddUniqueConst(dd,n); + return(res); + } + cacheOp = (DdNode *(*)(DdManager *, DdNode *)) Cudd_addRoundOff; + res = cuddCacheLookup1(dd,cacheOp,f); + if (res != NULL) { + return(res); + } + /* Recursive Step */ + fv = cuddT(f); + fvn = cuddE(f); + T = cuddAddRoundOffRecur(dd,fv,trunc); + if (T == NULL) { + return(NULL); + } + cuddRef(T); + E = cuddAddRoundOffRecur(dd,fvn,trunc); + if (E == NULL) { + Cudd_RecursiveDeref(dd,T); + return(NULL); + } + cuddRef(E); + res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd,T); + Cudd_RecursiveDeref(dd,E); + return(NULL); + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert1(dd,cacheOp,f,res); + return(res); + +} /* end of cuddAddRoundOffRecur */ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/cudd/cuddAddWalsh.c b/abc70930/src/bdd/cudd/cuddAddWalsh.c new file mode 100644 index 00000000..c6a67e34 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddAddWalsh.c @@ -0,0 +1,364 @@ +/**CFile*********************************************************************** + + FileName [cuddAddWalsh.c] + + PackageName [cudd] + + Synopsis [Functions that generate Walsh matrices and residue + functions in ADD form.] + + Description [External procedures included in this module: +
    +
  • Cudd_addWalsh() +
  • Cudd_addResidue() +
+ Static procedures included in this module: +
    +
  • addWalshInt() +
] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAddWalsh.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; +#endif + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * addWalshInt ARGS((DdManager *dd, DdNode **x, DdNode **y, int n)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Generates a Walsh matrix in ADD form.] + + Description [Generates a Walsh matrix in ADD form. Returns a pointer + to the matrixi if successful; NULL otherwise.] + + SideEffects [None] + +******************************************************************************/ +DdNode * +Cudd_addWalsh( + DdManager * dd, + DdNode ** x, + DdNode ** y, + int n) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = addWalshInt(dd, x, y, n); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addWalsh */ + + +/**Function******************************************************************** + + Synopsis [Builds an ADD for the residue modulo m of an n-bit + number.] + + Description [Builds an ADD for the residue modulo m of an n-bit + number. The modulus must be at least 2, and the number of bits at + least 1. Parameter options specifies whether the MSB should be on top + or the LSB; and whther the number whose residue is computed is in + two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT + specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB + specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's + complement residue. To request MSB on top and two's complement residue + simultaneously, one can OR the two macros: + CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC. + Cudd_addResidue returns a pointer to the resulting ADD if successful; + NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_addResidue( + DdManager * dd /* manager */, + int n /* number of bits */, + int m /* modulus */, + int options /* options */, + int top /* index of top variable */) +{ + int msbLsb; /* MSB on top (1) or LSB on top (0) */ + int tc; /* two's complement (1) or unsigned (0) */ + int i, j, k, t, residue, thisOne, previous, index; + DdNode **array[2], *var, *tmp, *res; + + /* Sanity check. */ + if (n < 1 && m < 2) return(NULL); + + msbLsb = options & CUDD_RESIDUE_MSB; + tc = options & CUDD_RESIDUE_TC; + + /* Allocate and initialize working arrays. */ + array[0] = ALLOC(DdNode *,m); + if (array[0] == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + array[1] = ALLOC(DdNode *,m); + if (array[1] == NULL) { + FREE(array[0]); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < m; i++) { + array[0][i] = array[1][i] = NULL; + } + + /* Initialize residues. */ + for (i = 0; i < m; i++) { + tmp = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) i); + if (tmp == NULL) { + for (j = 0; j < i; j++) { + Cudd_RecursiveDeref(dd,array[1][j]); + } + FREE(array[0]); + FREE(array[1]); + return(NULL); + } + cuddRef(tmp); + array[1][i] = tmp; + } + + /* Main iteration. */ + residue = 1; /* residue of 2**0 */ + for (k = 0; k < n; k++) { + /* Choose current and previous arrays. */ + thisOne = k & 1; + previous = thisOne ^ 1; + /* Build an ADD projection function. */ + if (msbLsb) { + index = top+n-k-1; + } else { + index = top+k; + } + var = cuddUniqueInter(dd,index,DD_ONE(dd),DD_ZERO(dd)); + if (var == NULL) { + for (j = 0; j < m; j++) { + Cudd_RecursiveDeref(dd,array[previous][j]); + } + FREE(array[0]); + FREE(array[1]); + return(NULL); + } + cuddRef(var); + for (i = 0; i < m; i ++) { + t = (i + residue) % m; + tmp = Cudd_addIte(dd,var,array[previous][t],array[previous][i]); + if (tmp == NULL) { + for (j = 0; j < i; j++) { + Cudd_RecursiveDeref(dd,array[thisOne][j]); + } + for (j = 0; j < m; j++) { + Cudd_RecursiveDeref(dd,array[previous][j]); + } + FREE(array[0]); + FREE(array[1]); + return(NULL); + } + cuddRef(tmp); + array[thisOne][i] = tmp; + } + /* One layer completed. Free the other array for the next iteration. */ + for (i = 0; i < m; i++) { + Cudd_RecursiveDeref(dd,array[previous][i]); + } + Cudd_RecursiveDeref(dd,var); + /* Update residue of 2**k. */ + residue = (2 * residue) % m; + /* Adjust residue for MSB, if this is a two's complement number. */ + if (tc && (k == n - 1)) { + residue = (m - residue) % m; + } + } + + /* We are only interested in the 0-residue node of the top layer. */ + for (i = 1; i < m; i++) { + Cudd_RecursiveDeref(dd,array[(n - 1) & 1][i]); + } + res = array[(n - 1) & 1][0]; + + FREE(array[0]); + FREE(array[1]); + + cuddDeref(res); + return(res); + +} /* end of Cudd_addResidue */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_addWalsh.] + + Description [Generates a Walsh matrix in ADD form. Returns a pointer + to the matrixi if successful; NULL otherwise.] + + SideEffects [None] + +******************************************************************************/ +static DdNode * +addWalshInt( + DdManager * dd, + DdNode ** x, + DdNode ** y, + int n) +{ + DdNode *one, *minusone; + DdNode *t, *u, *t1, *u1, *v, *w; + int i; + + one = DD_ONE(dd); + if (n == 0) return(one); + + /* Build bottom part of ADD outside loop */ + minusone = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) -1); + if (minusone == NULL) return(NULL); + cuddRef(minusone); + v = Cudd_addIte(dd, y[n-1], minusone, one); + if (v == NULL) { + Cudd_RecursiveDeref(dd, minusone); + return(NULL); + } + cuddRef(v); + u = Cudd_addIte(dd, x[n-1], v, one); + if (u == NULL) { + Cudd_RecursiveDeref(dd, minusone); + Cudd_RecursiveDeref(dd, v); + return(NULL); + } + cuddRef(u); + Cudd_RecursiveDeref(dd, v); + if (n>1) { + w = Cudd_addIte(dd, y[n-1], one, minusone); + if (w == NULL) { + Cudd_RecursiveDeref(dd, minusone); + Cudd_RecursiveDeref(dd, u); + return(NULL); + } + cuddRef(w); + t = Cudd_addIte(dd, x[n-1], w, minusone); + if (t == NULL) { + Cudd_RecursiveDeref(dd, minusone); + Cudd_RecursiveDeref(dd, u); + Cudd_RecursiveDeref(dd, w); + return(NULL); + } + cuddRef(t); + Cudd_RecursiveDeref(dd, w); + } + cuddDeref(minusone); /* minusone is in the result; it won't die */ + + /* Loop to build the rest of the ADD */ + for (i=n-2; i>=0; i--) { + t1 = t; u1 = u; + v = Cudd_addIte(dd, y[i], t1, u1); + if (v == NULL) { + Cudd_RecursiveDeref(dd, u1); + Cudd_RecursiveDeref(dd, t1); + return(NULL); + } + cuddRef(v); + u = Cudd_addIte(dd, x[i], v, u1); + if (u == NULL) { + Cudd_RecursiveDeref(dd, u1); + Cudd_RecursiveDeref(dd, t1); + Cudd_RecursiveDeref(dd, v); + return(NULL); + } + cuddRef(u); + Cudd_RecursiveDeref(dd, v); + if (i>0) { + w = Cudd_addIte(dd, y[i], u1, t1); + if (u == NULL) { + Cudd_RecursiveDeref(dd, u1); + Cudd_RecursiveDeref(dd, t1); + Cudd_RecursiveDeref(dd, u); + return(NULL); + } + cuddRef(w); + t = Cudd_addIte(dd, x[i], w, t1); + if (u == NULL) { + Cudd_RecursiveDeref(dd, u1); + Cudd_RecursiveDeref(dd, t1); + Cudd_RecursiveDeref(dd, u); + Cudd_RecursiveDeref(dd, w); + return(NULL); + } + cuddRef(t); + Cudd_RecursiveDeref(dd, w); + } + Cudd_RecursiveDeref(dd, u1); + Cudd_RecursiveDeref(dd, t1); + } + + cuddDeref(u); + return(u); + +} /* end of addWalshInt */ diff --git a/abc70930/src/bdd/cudd/cuddAndAbs.c b/abc70930/src/bdd/cudd/cuddAndAbs.c new file mode 100644 index 00000000..5ec47beb --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddAndAbs.c @@ -0,0 +1,306 @@ +/**CFile*********************************************************************** + + FileName [cuddAndAbs.c] + + PackageName [cudd] + + Synopsis [Combined AND and existential abstraction for BDDs] + + Description [External procedures included in this module: +
    +
  • Cudd_bddAndAbstract() +
+ Internal procedures included in this module: +
    +
  • cuddBddAndAbstractRecur() +
] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAndAbs.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Takes the AND of two BDDs and simultaneously abstracts the + variables in cube.] + + Description [Takes the AND of two BDDs and simultaneously abstracts + the variables in cube. The variables are existentially abstracted. + Returns a pointer to the result is successful; NULL otherwise. + Cudd_bddAndAbstract implements the semiring matrix multiplication + algorithm for the boolean semiring.] + + SideEffects [None] + + SeeAlso [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd] + +******************************************************************************/ +DdNode * +Cudd_bddAndAbstract( + DdManager * manager, + DdNode * f, + DdNode * g, + DdNode * cube) +{ + DdNode *res; + + do { + manager->reordered = 0; + res = cuddBddAndAbstractRecur(manager, f, g, cube); + } while (manager->reordered == 1); + return(res); + +} /* end of Cudd_bddAndAbstract */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Takes the AND of two BDDs and simultaneously abstracts the + variables in cube.] + + Description [Takes the AND of two BDDs and simultaneously abstracts + the variables in cube. The variables are existentially abstracted. + Returns a pointer to the result is successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddAndAbstract] + +******************************************************************************/ +DdNode * +cuddBddAndAbstractRecur( + DdManager * manager, + DdNode * f, + DdNode * g, + DdNode * cube) +{ + DdNode *F, *ft, *fe, *G, *gt, *ge; + DdNode *one, *zero, *r, *t, *e; + unsigned int topf, topg, topcube, top, index; + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Terminal cases. */ + if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); + if (f == one && g == one) return(one); + + if (cube == one) { + return(cuddBddAndRecur(manager, f, g)); + } + if (f == one || f == g) { + return(cuddBddExistAbstractRecur(manager, g, cube)); + } + if (g == one) { + return(cuddBddExistAbstractRecur(manager, f, cube)); + } + /* At this point f, g, and cube are not constant. */ + + if (f > g) { /* Try to increase cache efficiency. */ + DdNode *tmp = f; + f = g; + g = tmp; + } + + /* Here we can skip the use of cuddI, because the operands are known + ** to be non-constant. + */ + F = Cudd_Regular(f); + G = Cudd_Regular(g); + topf = manager->perm[F->index]; + topg = manager->perm[G->index]; + top = ddMin(topf, topg); + topcube = manager->perm[cube->index]; + + while (topcube < top) { + cube = cuddT(cube); + if (cube == one) { + return(cuddBddAndRecur(manager, f, g)); + } + topcube = manager->perm[cube->index]; + } + /* Now, topcube >= top. */ + + /* Check cache. */ + if (F->ref != 1 || G->ref != 1) { + r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube); + if (r != NULL) { + return(r); + } + } + + if (topf == top) { + index = F->index; + ft = cuddT(F); + fe = cuddE(F); + if (Cudd_IsComplement(f)) { + ft = Cudd_Not(ft); + fe = Cudd_Not(fe); + } + } else { + index = G->index; + ft = fe = f; + } + + if (topg == top) { + gt = cuddT(G); + ge = cuddE(G); + if (Cudd_IsComplement(g)) { + gt = Cudd_Not(gt); + ge = Cudd_Not(ge); + } + } else { + gt = ge = g; + } + + if (topcube == top) { /* quantify */ + DdNode *Cube = cuddT(cube); + t = cuddBddAndAbstractRecur(manager, ft, gt, Cube); + if (t == NULL) return(NULL); + /* Special case: 1 OR anything = 1. Hence, no need to compute + ** the else branch if t is 1. Likewise t + t * anything == t. + ** Notice that t == fe implies that fe does not depend on the + ** variables in Cube. Likewise for t == ge. + */ + if (t == one || t == fe || t == ge) { + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, + f, g, cube, t); + return(t); + } + cuddRef(t); + /* Special case: t + !t * anything == t + anything. */ + if (t == Cudd_Not(fe)) { + e = cuddBddExistAbstractRecur(manager, ge, Cube); + } else if (t == Cudd_Not(ge)) { + e = cuddBddExistAbstractRecur(manager, fe, Cube); + } else { + e = cuddBddAndAbstractRecur(manager, fe, ge, Cube); + } + if (e == NULL) { + Cudd_IterDerefBdd(manager, t); + return(NULL); + } + if (t == e) { + r = t; + cuddDeref(t); + } else { + cuddRef(e); + r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + cuddRef(r); + Cudd_DelayedDerefBdd(manager, t); + Cudd_DelayedDerefBdd(manager, e); + cuddDeref(r); + } + } else { + t = cuddBddAndAbstractRecur(manager, ft, gt, cube); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddBddAndAbstractRecur(manager, fe, ge, cube); + if (e == NULL) { + Cudd_IterDerefBdd(manager, t); + return(NULL); + } + if (t == e) { + r = t; + cuddDeref(t); + } else { + cuddRef(e); + if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(manager, (int) index, + Cudd_Not(t), Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(manager,(int)index,t,e); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + } + cuddDeref(e); + cuddDeref(t); + } + } + + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r); + return (r); + +} /* end of cuddBddAndAbstractRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/cudd/cuddAnneal.c b/abc70930/src/bdd/cudd/cuddAnneal.c new file mode 100644 index 00000000..3d8b56b9 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddAnneal.c @@ -0,0 +1,788 @@ +/**CFile*********************************************************************** + + FileName [cuddAnneal.c] + + PackageName [cudd] + + Synopsis [Reordering of DDs based on simulated annealing] + + Description [Internal procedures included in this file: +
    +
  • cuddAnnealing() +
+ Static procedures included in this file: +
    +
  • stopping_criterion() +
  • random_generator() +
  • ddExchange() +
  • ddJumpingAux() +
  • ddJumpingUp() +
  • ddJumpingDown() +
  • siftBackwardProb() +
  • copyOrder() +
  • restoreOrder() +
+ ] + + SeeAlso [] + + Author [Jae-Young Jang, Jorgen Sivesind] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/* Annealing parameters */ +#define BETA 0.6 +#define ALPHA 0.90 +#define EXC_PROB 0.4 +#define JUMP_UP_PROB 0.36 +#define MAXGEN_RATIO 15.0 +#define STOP_TEMP 1.0 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddAnneal.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +#ifdef DD_STATS +extern int ddTotalNumberSwapping; +extern int ddTotalNISwaps; +static int tosses; +static int acceptances; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int stopping_criterion ARGS((int c1, int c2, int c3, int c4, double temp)); +static double random_generator ARGS(()); +static int ddExchange ARGS((DdManager *table, int x, int y, double temp)); +static int ddJumpingAux ARGS((DdManager *table, int x, int x_low, int x_high, double temp)); +static Move * ddJumpingUp ARGS((DdManager *table, int x, int x_low, int initial_size)); +static Move * ddJumpingDown ARGS((DdManager *table, int x, int x_high, int initial_size)); +static int siftBackwardProb ARGS((DdManager *table, Move *moves, int size, double temp)); +static void copyOrder ARGS((DdManager *table, int *array, int lower, int upper)); +static int restoreOrder ARGS((DdManager *table, int *array, int lower, int upper)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Get new variable-order by simulated annealing algorithm.] + + Description [Get x, y by random selection. Choose either + exchange or jump randomly. In case of jump, choose between jump_up + and jump_down randomly. Do exchange or jump and get optimal case. + Loop until there is no improvement or temperature reaches + minimum. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddAnnealing( + DdManager * table, + int lower, + int upper) +{ + int nvars; + int size; + int x,y; + int result; + int c1, c2, c3, c4; + int BestCost; + int *BestOrder; + double NewTemp, temp; + double rand1; + int innerloop, maxGen; + int ecount, ucount, dcount; + + nvars = upper - lower + 1; + + result = cuddSifting(table,lower,upper); +#ifdef DD_STATS + (void) fprintf(table->out,"\n"); +#endif + if (result == 0) return(0); + + size = table->keys - table->isolated; + + /* Keep track of the best order. */ + BestCost = size; + BestOrder = ALLOC(int,nvars); + if (BestOrder == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + copyOrder(table,BestOrder,lower,upper); + + temp = BETA * size; + maxGen = (int) (MAXGEN_RATIO * nvars); + + c1 = size + 10; + c2 = c1 + 10; + c3 = size; + c4 = c2 + 10; + ecount = ucount = dcount = 0; + + while (!stopping_criterion(c1, c2, c3, c4, temp)) { +#ifdef DD_STATS + (void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t", + temp,size,maxGen); + tosses = acceptances = 0; +#endif + for (innerloop = 0; innerloop < maxGen; innerloop++) { + /* Choose x, y randomly. */ + x = (int) Cudd_Random() % nvars; + do { + y = (int) Cudd_Random() % nvars; + } while (x == y); + x += lower; + y += lower; + if (x > y) { + int tmp = x; + x = y; + y = tmp; + } + + /* Choose move with roulette wheel. */ + rand1 = random_generator(); + if (rand1 < EXC_PROB) { + result = ddExchange(table,x,y,temp); /* exchange */ + ecount++; +#if 0 + (void) fprintf(table->out, + "Exchange of %d and %d: size = %d\n", + x,y,table->keys - table->isolated); +#endif + } else if (rand1 < EXC_PROB + JUMP_UP_PROB) { + result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */ + ucount++; +#if 0 + (void) fprintf(table->out, + "Jump up of %d to %d: size = %d\n", + y,x,table->keys - table->isolated); +#endif + } else { + result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */ + dcount++; +#if 0 + (void) fprintf(table->out, + "Jump down of %d to %d: size = %d\n", + x,y,table->keys - table->isolated); +#endif + } + + if (!result) { + FREE(BestOrder); + return(0); + } + + size = table->keys - table->isolated; /* keep current size */ + if (size < BestCost) { /* update best order */ + BestCost = size; + copyOrder(table,BestOrder,lower,upper); + } + } + c1 = c2; + c2 = c3; + c3 = c4; + c4 = size; + NewTemp = ALPHA * temp; + if (NewTemp >= 1.0) { + maxGen = (int)(log(NewTemp) / log(temp) * maxGen); + } + temp = NewTemp; /* control variable */ +#ifdef DD_STATS + (void) fprintf(table->out,"uphill = %d\taccepted = %d\n", + tosses,acceptances); + fflush(table->out); +#endif + } + + result = restoreOrder(table,BestOrder,lower,upper); + FREE(BestOrder); + if (!result) return(0); +#ifdef DD_STATS + fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount); + fprintf(table->out,"#:N_JUMPUP %8d : total jumps up\n",ucount); + fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount); +#endif + return(1); + +} /* end of cuddAnnealing */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Checks termination condition.] + + Description [If temperature is STOP_TEMP or there is no improvement + then terminates. Returns 1 if the termination criterion is met; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +stopping_criterion( + int c1, + int c2, + int c3, + int c4, + double temp) +{ + if (STOP_TEMP < temp) { + return(0); + } else if ((c1 == c2) && (c1 == c3) && (c1 == c4)) { + return(1); + } else { + return(0); + } + +} /* end of stopping_criterion */ + + +/**Function******************************************************************** + + Synopsis [Random number generator.] + + Description [Returns a double precision value between 0.0 and 1.0.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static double +random_generator( + ) +{ + return((double)(Cudd_Random() / 2147483561.0)); + +} /* end of random_generator */ + + +/**Function******************************************************************** + + Synopsis [This function is for exchanging two variables, x and y.] + + Description [This is the same funcion as ddSwapping except for + comparison expression. Use probability function, exp(-size_change/temp).] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ddExchange( + DdManager * table, + int x, + int y, + double temp) +{ + Move *move,*moves; + int tmp; + int x_ref,y_ref; + int x_next,y_next; + int size, result; + int initial_size, limit_size; + + x_ref = x; + y_ref = y; + + x_next = cuddNextHigh(table,x); + y_next = cuddNextLow(table,y); + moves = NULL; + initial_size = limit_size = table->keys - table->isolated; + + for (;;) { + if (x_next == y_next) { + size = cuddSwapInPlace(table,x,x_next); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + size = cuddSwapInPlace(table,y_next,y); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = y_next; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + size = cuddSwapInPlace(table,x,x_next); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + + tmp = x; + x = y; + y = tmp; + } else if (x == y_next) { + size = cuddSwapInPlace(table,x,x_next); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + tmp = x; + x = y; + y = tmp; + } else { + size = cuddSwapInPlace(table,x,x_next); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + size = cuddSwapInPlace(table,y_next,y); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = y_next; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + x = x_next; + y = y_next; + } + + x_next = cuddNextHigh(table,x); + y_next = cuddNextLow(table,y); + if (x_next > y_ref) break; + + if ((double) size > DD_MAX_REORDER_GROWTH * (double) limit_size) { + break; + } else if (size < limit_size) { + limit_size = size; + } + } + + if (y_next>=x_ref) { + size = cuddSwapInPlace(table,y_next,y); + if (size == 0) goto ddExchangeOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddExchangeOutOfMem; + move->x = y_next; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + } + + /* move backward and stop at best position or accept uphill move */ + result = siftBackwardProb(table,moves,initial_size,temp); + if (!result) goto ddExchangeOutOfMem; + + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return(1); + +ddExchangeOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table,(DdNode *) moves); + moves = move; + } + return(0); + +} /* end of ddExchange */ + + +/**Function******************************************************************** + + Synopsis [Moves a variable to a specified position.] + + Description [If x==x_low, it executes jumping_down. If x==x_high, it + executes jumping_up. This funcion is similar to ddSiftingAux. Returns + 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ddJumpingAux( + DdManager * table, + int x, + int x_low, + int x_high, + double temp) +{ + Move *move; + Move *moves; /* list of moves */ + int initial_size; + int result; + + initial_size = table->keys - table->isolated; + +#ifdef DD_DEBUG + assert(table->subtables[x].keys > 0); +#endif + + moves = NULL; + + if (cuddNextLow(table,x) < x_low) { + if (cuddNextHigh(table,x) > x_high) return(1); + moves = ddJumpingDown(table,x,x_high,initial_size); + /* after that point x --> x_high unless early termination */ + if (moves == NULL) goto ddJumpingAuxOutOfMem; + /* move backward and stop at best position or accept uphill move */ + result = siftBackwardProb(table,moves,initial_size,temp); + if (!result) goto ddJumpingAuxOutOfMem; + } else if (cuddNextHigh(table,x) > x_high) { + moves = ddJumpingUp(table,x,x_low,initial_size); + /* after that point x --> x_low unless early termination */ + if (moves == NULL) goto ddJumpingAuxOutOfMem; + /* move backward and stop at best position or accept uphill move */ + result = siftBackwardProb(table,moves,initial_size,temp); + if (!result) goto ddJumpingAuxOutOfMem; + } else { + (void) fprintf(table->err,"Unexpected condition in ddJumping\n"); + goto ddJumpingAuxOutOfMem; + } + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return(1); + +ddJumpingAuxOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return(0); + +} /* end of ddJumpingAux */ + + +/**Function******************************************************************** + + Synopsis [This function is for jumping up.] + + Description [This is a simplified version of ddSiftingUp. It does not + use lower bounding. Returns the set of moves in case of success; NULL + if memory is full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +ddJumpingUp( + DdManager * table, + int x, + int x_low, + int initial_size) +{ + Move *moves; + Move *move; + int y; + int size; + int limit_size = initial_size; + + moves = NULL; + y = cuddNextLow(table,x); + while (y >= x_low) { + size = cuddSwapInPlace(table,y,x); + if (size == 0) goto ddJumpingUpOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddJumpingUpOutOfMem; + move->x = y; + move->y = x; + move->size = size; + move->next = moves; + moves = move; + if ((double) size > table->maxGrowth * (double) limit_size) { + break; + } else if (size < limit_size) { + limit_size = size; + } + x = y; + y = cuddNextLow(table,x); + } + return(moves); + +ddJumpingUpOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return(NULL); + +} /* end of ddJumpingUp */ + + +/**Function******************************************************************** + + Synopsis [This function is for jumping down.] + + Description [This is a simplified version of ddSiftingDown. It does not + use lower bounding. Returns the set of moves in case of success; NULL + if memory is full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +ddJumpingDown( + DdManager * table, + int x, + int x_high, + int initial_size) +{ + Move *moves; + Move *move; + int y; + int size; + int limit_size = initial_size; + + moves = NULL; + y = cuddNextHigh(table,x); + while (y <= x_high) { + size = cuddSwapInPlace(table,x,y); + if (size == 0) goto ddJumpingDownOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddJumpingDownOutOfMem; + move->x = x; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + if ((double) size > table->maxGrowth * (double) limit_size) { + break; + } else if (size < limit_size) { + limit_size = size; + } + x = y; + y = cuddNextHigh(table,x); + } + return(moves); + +ddJumpingDownOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return(NULL); + +} /* end of ddJumpingDown */ + + +/**Function******************************************************************** + + Synopsis [Returns the DD to the best position encountered during + sifting if there was improvement.] + + Description [Otherwise, "tosses a coin" to decide whether to keep + the current configuration or return the DD to the original + one. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +siftBackwardProb( + DdManager * table, + Move * moves, + int size, + double temp) +{ + Move *move; + int res; + int best_size = size; + double coin, threshold; + + /* Look for best size during the last sifting */ + for (move = moves; move != NULL; move = move->next) { + if (move->size < best_size) { + best_size = move->size; + } + } + + /* If best_size equals size, the last sifting did not produce any + ** improvement. We now toss a coin to decide whether to retain + ** this change or not. + */ + if (best_size == size) { + coin = random_generator(); +#ifdef DD_STATS + tosses++; +#endif + threshold = exp(-((double)(table->keys - table->isolated - size))/temp); + if (coin < threshold) { +#ifdef DD_STATS + acceptances++; +#endif + return(1); + } + } + + /* Either there was improvement, or we have decided not to + ** accept the uphill move. Go to best position. + */ + res = table->keys - table->isolated; + for (move = moves; move != NULL; move = move->next) { + if (res == best_size) return(1); + res = cuddSwapInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); + } + + return(1); + +} /* end of sift_backward_prob */ + + +/**Function******************************************************************** + + Synopsis [Copies the current variable order to array.] + + Description [Copies the current variable order to array. + At the same time inverts the permutation.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +copyOrder( + DdManager * table, + int * array, + int lower, + int upper) +{ + int i; + int nvars; + + nvars = upper - lower + 1; + for (i = 0; i < nvars; i++) { + array[i] = table->invperm[i+lower]; + } + +} /* end of copyOrder */ + + +/**Function******************************************************************** + + Synopsis [Restores the variable order in array by a series of sifts up.] + + Description [Restores the variable order in array by a series of sifts up. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +restoreOrder( + DdManager * table, + int * array, + int lower, + int upper) +{ + int i, x, y, size; + int nvars = upper - lower + 1; + + for (i = 0; i < nvars; i++) { + x = table->perm[array[i]]; +#ifdef DD_DEBUG + assert(x >= lower && x <= upper); +#endif + y = cuddNextLow(table,x); + while (y >= i + lower) { + size = cuddSwapInPlace(table,y,x); + if (size == 0) return(0); + x = y; + y = cuddNextLow(table,x); + } + } + + return(1); + +} /* end of restoreOrder */ + diff --git a/abc70930/src/bdd/cudd/cuddApa.c b/abc70930/src/bdd/cudd/cuddApa.c new file mode 100644 index 00000000..47ab51e8 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddApa.c @@ -0,0 +1,930 @@ +/**CFile*********************************************************************** + + FileName [cuddApa.c] + + PackageName [cudd] + + Synopsis [Arbitrary precision arithmetic functions.] + + Description [External procedures included in this module: +
    +
  • +
+ Internal procedures included in this module: +
    +
  • () +
+ Static procedures included in this module: +
    +
  • () +
] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddApa.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +static DdNode *background, *zero; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdApaNumber cuddApaCountMintermAux ARGS((DdNode * node, int digits, DdApaNumber max, DdApaNumber min, st_table * table)); +static enum st_retval cuddApaStCountfree ARGS((char * key, char * value, char * arg)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Finds the number of digits for an arbitrary precision + integer.] + + Description [Finds the number of digits for an arbitrary precision + integer given the maximum number of binary digits. The number of + binary digits should be positive. Returns the number of digits if + successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_ApaNumberOfDigits( + int binaryDigits) +{ + int digits; + + digits = binaryDigits / DD_APA_BITS; + if ((digits * DD_APA_BITS) != binaryDigits) + digits++; + return(digits); + +} /* end of Cudd_ApaNumberOfDigits */ + + +/**Function******************************************************************** + + Synopsis [Allocates memory for an arbitrary precision integer.] + + Description [Allocates memory for an arbitrary precision + integer. Returns a pointer to the allocated memory if successful; + NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdApaNumber +Cudd_NewApaNumber( + int digits) +{ + return(ALLOC(DdApaDigit, digits)); + +} /* end of Cudd_NewApaNumber */ + + +/**Function******************************************************************** + + Synopsis [Makes a copy of an arbitrary precision integer.] + + Description [Makes a copy of an arbitrary precision integer.] + + SideEffects [Changes parameter dest.] + + SeeAlso [] + +******************************************************************************/ +void +Cudd_ApaCopy( + int digits, + DdApaNumber source, + DdApaNumber dest) +{ + int i; + + for (i = 0; i < digits; i++) { + dest[i] = source[i]; + } + +} /* end of Cudd_ApaCopy */ + + +/**Function******************************************************************** + + Synopsis [Adds two arbitrary precision integers.] + + Description [Adds two arbitrary precision integers. Returns the + carry out of the most significant digit.] + + SideEffects [The result of the sum is stored in parameter sum.] + + SeeAlso [] + +******************************************************************************/ +DdApaDigit +Cudd_ApaAdd( + int digits, + DdApaNumber a, + DdApaNumber b, + DdApaNumber sum) +{ + int i; + DdApaDoubleDigit partial = 0; + + for (i = digits - 1; i >= 0; i--) { + partial = a[i] + b[i] + DD_MSDIGIT(partial); + sum[i] = (DdApaDigit) DD_LSDIGIT(partial); + } + return(DD_MSDIGIT(partial)); + +} /* end of Cudd_ApaAdd */ + + +/**Function******************************************************************** + + Synopsis [Subtracts two arbitrary precision integers.] + + Description [Subtracts two arbitrary precision integers. Returns the + borrow out of the most significant digit.] + + SideEffects [The result of the subtraction is stored in parameter + diff.] + + SeeAlso [] + +******************************************************************************/ +DdApaDigit +Cudd_ApaSubtract( + int digits, + DdApaNumber a, + DdApaNumber b, + DdApaNumber diff) +{ + int i; + DdApaDoubleDigit partial = DD_APA_BASE; + + for (i = digits - 1; i >= 0; i--) { + partial = a[i] - b[i] + DD_MSDIGIT(partial) + DD_APA_MASK; + diff[i] = (DdApaDigit) DD_LSDIGIT(partial); + } + return(DD_MSDIGIT(partial) - 1); + +} /* end of Cudd_ApaSubtract */ + + +/**Function******************************************************************** + + Synopsis [Divides an arbitrary precision integer by a digit.] + + Description [Divides an arbitrary precision integer by a digit.] + + SideEffects [The quotient is returned in parameter quotient.] + + SeeAlso [] + +******************************************************************************/ +DdApaDigit +Cudd_ApaShortDivision( + int digits, + DdApaNumber dividend, + DdApaDigit divisor, + DdApaNumber quotient) +{ + int i; + DdApaDigit remainder; + DdApaDoubleDigit partial; + + remainder = 0; + for (i = 0; i < digits; i++) { + partial = remainder * DD_APA_BASE + dividend[i]; + quotient[i] = (DdApaDigit) (partial/(DdApaDoubleDigit)divisor); + remainder = (DdApaDigit) (partial % divisor); + } + + return(remainder); + +} /* end of Cudd_ApaShortDivision */ + + +/**Function******************************************************************** + + Synopsis [Divides an arbitrary precision integer by an integer.] + + Description [Divides an arbitrary precision integer by a 32-bit + unsigned integer. Returns the remainder of the division. This + procedure relies on the assumption that the number of bits of a + DdApaDigit plus the number of bits of an unsigned int is less the + number of bits of the mantissa of a double. This guarantees that the + product of a DdApaDigit and an unsigned int can be represented + without loss of precision by a double. On machines where this + assumption is not satisfied, this procedure will malfunction.] + + SideEffects [The quotient is returned in parameter quotient.] + + SeeAlso [Cudd_ApaShortDivision] + +******************************************************************************/ +unsigned int +Cudd_ApaIntDivision( + int digits, + DdApaNumber dividend, + unsigned int divisor, + DdApaNumber quotient) +{ + int i; + double partial; + unsigned int remainder = 0; + double ddiv = (double) divisor; + + for (i = 0; i < digits; i++) { + partial = (double) remainder * DD_APA_BASE + dividend[i]; + quotient[i] = (DdApaDigit) (partial / ddiv); + remainder = (unsigned int) (partial - ((double)quotient[i] * ddiv)); + } + + return(remainder); + +} /* end of Cudd_ApaIntDivision */ + + +/**Function******************************************************************** + + Synopsis [Shifts right an arbitrary precision integer by one binary + place.] + + Description [Shifts right an arbitrary precision integer by one + binary place. The most significant binary digit of the result is + taken from parameter in.] + + SideEffects [The result is returned in parameter b.] + + SeeAlso [] + +******************************************************************************/ +void +Cudd_ApaShiftRight( + int digits, + DdApaDigit in, + DdApaNumber a, + DdApaNumber b) +{ + int i; + + for (i = digits - 1; i > 0; i--) { + b[i] = (a[i] >> 1) | ((a[i-1] & 1) << (DD_APA_BITS - 1)); + } + b[0] = (a[0] >> 1) | (in << (DD_APA_BITS - 1)); + +} /* end of Cudd_ApaShiftRight */ + + +/**Function******************************************************************** + + Synopsis [Sets an arbitrary precision integer to a one-digit literal.] + + Description [Sets an arbitrary precision integer to a one-digit literal.] + + SideEffects [The result is returned in parameter number.] + + SeeAlso [] + +******************************************************************************/ +void +Cudd_ApaSetToLiteral( + int digits, + DdApaNumber number, + DdApaDigit literal) +{ + int i; + + for (i = 0; i < digits - 1; i++) + number[i] = 0; + number[digits - 1] = literal; + +} /* end of Cudd_ApaSetToLiteral */ + + +/**Function******************************************************************** + + Synopsis [Sets an arbitrary precision integer to a power of two.] + + Description [Sets an arbitrary precision integer to a power of + two. If the power of two is too large to be represented, the number + is set to 0.] + + SideEffects [The result is returned in parameter number.] + + SeeAlso [] + +******************************************************************************/ +void +Cudd_ApaPowerOfTwo( + int digits, + DdApaNumber number, + int power) +{ + int i; + int index; + + for (i = 0; i < digits; i++) + number[i] = 0; + i = digits - 1 - power / DD_APA_BITS; + if (i < 0) return; + index = power & (DD_APA_BITS - 1); + number[i] = 1 << index; + +} /* end of Cudd_ApaPowerOfTwo */ + + +/**Function******************************************************************** + + Synopsis [Compares two arbitrary precision integers.] + + Description [Compares two arbitrary precision integers. Returns 1 if + the first number is larger; 0 if they are equal; -1 if the second + number is larger.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_ApaCompare( + int digitsFirst, + DdApaNumber first, + int digitsSecond, + DdApaNumber second) +{ + int i; + int firstNZ, secondNZ; + + /* Find first non-zero in both numbers. */ + for (firstNZ = 0; firstNZ < digitsFirst; firstNZ++) + if (first[firstNZ] != 0) break; + for (secondNZ = 0; secondNZ < digitsSecond; secondNZ++) + if (second[secondNZ] != 0) break; + if (digitsFirst - firstNZ > digitsSecond - secondNZ) return(1); + else if (digitsFirst - firstNZ < digitsSecond - secondNZ) return(-1); + for (i = 0; i < digitsFirst - firstNZ; i++) { + if (first[firstNZ + i] > second[secondNZ + i]) return(1); + else if (first[firstNZ + i] < second[secondNZ + i]) return(-1); + } + return(0); + +} /* end of Cudd_ApaCompare */ + + +/**Function******************************************************************** + + Synopsis [Compares the ratios of two arbitrary precision integers to two + unsigned ints.] + + Description [Compares the ratios of two arbitrary precision integers + to two unsigned ints. Returns 1 if the first number is larger; 0 if + they are equal; -1 if the second number is larger.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_ApaCompareRatios( + int digitsFirst, + DdApaNumber firstNum, + unsigned int firstDen, + int digitsSecond, + DdApaNumber secondNum, + unsigned int secondDen) +{ + int result; + DdApaNumber first, second; + unsigned int firstRem, secondRem; + + first = Cudd_NewApaNumber(digitsFirst); + firstRem = Cudd_ApaIntDivision(digitsFirst,firstNum,firstDen,first); + second = Cudd_NewApaNumber(digitsSecond); + secondRem = Cudd_ApaIntDivision(digitsSecond,secondNum,secondDen,second); + result = Cudd_ApaCompare(digitsFirst,first,digitsSecond,second); + if (result == 0) { + if ((double)firstRem/firstDen > (double)secondRem/secondDen) + return(1); + else if ((double)firstRem/firstDen < (double)secondRem/secondDen) + return(-1); + } + return(result); + +} /* end of Cudd_ApaCompareRatios */ + + +/**Function******************************************************************** + + Synopsis [Prints an arbitrary precision integer in hexadecimal format.] + + Description [Prints an arbitrary precision integer in hexadecimal format. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_ApaPrintDecimal Cudd_ApaPrintExponential] + +******************************************************************************/ +int +Cudd_ApaPrintHex( + FILE * fp, + int digits, + DdApaNumber number) +{ + int i, result; + + for (i = 0; i < digits; i++) { + result = fprintf(fp,DD_APA_HEXPRINT,number[i]); + if (result == EOF) + return(0); + } + return(1); + +} /* end of Cudd_ApaPrintHex */ + + +/**Function******************************************************************** + + Synopsis [Prints an arbitrary precision integer in decimal format.] + + Description [Prints an arbitrary precision integer in decimal format. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintExponential] + +******************************************************************************/ +int +Cudd_ApaPrintDecimal( + FILE * fp, + int digits, + DdApaNumber number) +{ + int i, result; + DdApaDigit remainder; + DdApaNumber work; + unsigned char *decimal; + int leadingzero; + int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1; + + work = Cudd_NewApaNumber(digits); + if (work == NULL) + return(0); + decimal = ALLOC(unsigned char, decimalDigits); + if (decimal == NULL) { + FREE(work); + return(0); + } + Cudd_ApaCopy(digits,number,work); + for (i = decimalDigits - 1; i >= 0; i--) { + remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work); + decimal[i] = remainder; + } + FREE(work); + + leadingzero = 1; + for (i = 0; i < decimalDigits; i++) { + leadingzero = leadingzero && (decimal[i] == 0); + if ((!leadingzero) || (i == (decimalDigits - 1))) { + result = fprintf(fp,"%1d",decimal[i]); + if (result == EOF) { + FREE(decimal); + return(0); + } + } + } + FREE(decimal); + return(1); + +} /* end of Cudd_ApaPrintDecimal */ + + +/**Function******************************************************************** + + Synopsis [Prints an arbitrary precision integer in exponential format.] + + Description [Prints an arbitrary precision integer in exponential format. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintDecimal] + +******************************************************************************/ +int +Cudd_ApaPrintExponential( + FILE * fp, + int digits, + DdApaNumber number, + int precision) +{ + int i, first, last, result; + DdApaDigit remainder; + DdApaNumber work; + unsigned char *decimal; + int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1; + + work = Cudd_NewApaNumber(digits); + if (work == NULL) + return(0); + decimal = ALLOC(unsigned char, decimalDigits); + if (decimal == NULL) { + FREE(work); + return(0); + } + Cudd_ApaCopy(digits,number,work); + first = decimalDigits - 1; + for (i = decimalDigits - 1; i >= 0; i--) { + remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work); + decimal[i] = remainder; + if (remainder != 0) first = i; /* keep track of MS non-zero */ + } + FREE(work); + last = ddMin(first + precision, decimalDigits); + + for (i = first; i < last; i++) { + result = fprintf(fp,"%s%1d",i == first+1 ? "." : "", decimal[i]); + if (result == EOF) { + FREE(decimal); + return(0); + } + } + FREE(decimal); + result = fprintf(fp,"e+%d",decimalDigits - first - 1); + if (result == EOF) { + return(0); + } + return(1); + +} /* end of Cudd_ApaPrintExponential */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of minterms of a DD.] + + Description [Counts the number of minterms of a DD. The function is + assumed to depend on nvars variables. The minterm count is + represented as an arbitrary precision unsigned integer, to allow for + any number of variables CUDD supports. Returns a pointer to the + array representing the number of minterms of the function rooted at + node if successful; NULL otherwise.] + + SideEffects [The number of digits of the result is returned in + parameter digits.] + + SeeAlso [Cudd_CountMinterm] + +******************************************************************************/ +DdApaNumber +Cudd_ApaCountMinterm( + DdManager * manager, + DdNode * node, + int nvars, + int * digits) +{ + DdApaNumber max, min; + st_table *table; + DdApaNumber i,count; + + background = manager->background; + zero = Cudd_Not(manager->one); + + *digits = Cudd_ApaNumberOfDigits(nvars+1); + max = Cudd_NewApaNumber(*digits); + if (max == NULL) { + return(NULL); + } + Cudd_ApaPowerOfTwo(*digits,max,nvars); + min = Cudd_NewApaNumber(*digits); + if (min == NULL) { + FREE(max); + return(NULL); + } + Cudd_ApaSetToLiteral(*digits,min,0); + table = st_init_table(st_ptrcmp,st_ptrhash); + if (table == NULL) { + FREE(max); + FREE(min); + return(NULL); + } + i = cuddApaCountMintermAux(Cudd_Regular(node),*digits,max,min,table); + if (i == NULL) { + FREE(max); + FREE(min); + st_foreach(table, cuddApaStCountfree, NULL); + st_free_table(table); + return(NULL); + } + count = Cudd_NewApaNumber(*digits); + if (count == NULL) { + FREE(max); + FREE(min); + st_foreach(table, cuddApaStCountfree, NULL); + st_free_table(table); + if (Cudd_Regular(node)->ref == 1) FREE(i); + return(NULL); + } + if (Cudd_IsComplement(node)) { + (void) Cudd_ApaSubtract(*digits,max,i,count); + } else { + Cudd_ApaCopy(*digits,i,count); + } + FREE(max); + FREE(min); + st_foreach(table, cuddApaStCountfree, NULL); + st_free_table(table); + if (Cudd_Regular(node)->ref == 1) FREE(i); + return(count); + +} /* end of Cudd_ApaCountMinterm */ + + +/**Function******************************************************************** + + Synopsis [Prints the number of minterms of a BDD or ADD using + arbitrary precision arithmetic.] + + Description [Prints the number of minterms of a BDD or ADD using + arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_ApaPrintMintermExp] + +******************************************************************************/ +int +Cudd_ApaPrintMinterm( + FILE * fp, + DdManager * dd, + DdNode * node, + int nvars) +{ + int digits; + int result; + DdApaNumber count; + + count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); + if (count == NULL) + return(0); + result = Cudd_ApaPrintDecimal(fp,digits,count); + FREE(count); + if (fprintf(fp,"\n") == EOF) { + return(0); + } + return(result); + +} /* end of Cudd_ApaPrintMinterm */ + + +/**Function******************************************************************** + + Synopsis [Prints the number of minterms of a BDD or ADD in exponential + format using arbitrary precision arithmetic.] + + Description [Prints the number of minterms of a BDD or ADD in + exponential format using arbitrary precision arithmetic. Parameter + precision controls the number of signficant digits printed. Returns + 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_ApaPrintMinterm] + +******************************************************************************/ +int +Cudd_ApaPrintMintermExp( + FILE * fp, + DdManager * dd, + DdNode * node, + int nvars, + int precision) +{ + int digits; + int result; + DdApaNumber count; + + count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); + if (count == NULL) + return(0); + result = Cudd_ApaPrintExponential(fp,digits,count,precision); + FREE(count); + if (fprintf(fp,"\n") == EOF) { + return(0); + } + return(result); + +} /* end of Cudd_ApaPrintMintermExp */ + + +/**Function******************************************************************** + + Synopsis [Prints the density of a BDD or ADD using + arbitrary precision arithmetic.] + + Description [Prints the density of a BDD or ADD using + arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_ApaPrintDensity( + FILE * fp, + DdManager * dd, + DdNode * node, + int nvars) +{ + int digits; + int result; + DdApaNumber count,density; + unsigned int size, remainder, fractional; + + count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); + if (count == NULL) + return(0); + size = Cudd_DagSize(node); + density = Cudd_NewApaNumber(digits); + remainder = Cudd_ApaIntDivision(digits,count,size,density); + result = Cudd_ApaPrintDecimal(fp,digits,density); + FREE(count); + FREE(density); + fractional = (unsigned int)((double)remainder / size * 1000000); + if (fprintf(fp,".%u\n", fractional) == EOF) { + return(0); + } + return(result); + +} /* end of Cudd_ApaPrintDensity */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_ApaCountMinterm.] + + Description [Performs the recursive step of Cudd_ApaCountMinterm. + It is based on the following identity. Let |f| be the + number of minterms of f. Then: + + |f| = (|f0|+|f1|)/2 + + where f0 and f1 are the two cofactors of f. + Uses the identity |f'| = max - |f|. + The procedure expects the argument "node" to be a regular pointer, and + guarantees this condition is met in the recursive calls. + For efficiency, the result of a call is cached only if the node has + a reference count greater than 1. + Returns the number of minterms of the function rooted at node.] + + SideEffects [None] + +******************************************************************************/ +static DdApaNumber +cuddApaCountMintermAux( + DdNode * node, + int digits, + DdApaNumber max, + DdApaNumber min, + st_table * table) +{ + DdNode *Nt, *Ne; + DdApaNumber mint, mint1, mint2; + DdApaDigit carryout; + + if (cuddIsConstant(node)) { + if (node == background || node == zero) { + return(min); + } else { + return(max); + } + } + if (node->ref > 1 && st_lookup(table, (char *)node, (char **)&mint)) { + return(mint); + } + + Nt = cuddT(node); Ne = cuddE(node); + + mint1 = cuddApaCountMintermAux(Nt, digits, max, min, table); + if (mint1 == NULL) return(NULL); + mint2 = cuddApaCountMintermAux(Cudd_Regular(Ne), digits, max, min, table); + if (mint2 == NULL) { + if (Nt->ref == 1) FREE(mint1); + return(NULL); + } + mint = Cudd_NewApaNumber(digits); + if (mint == NULL) { + if (Nt->ref == 1) FREE(mint1); + if (Cudd_Regular(Ne)->ref == 1) FREE(mint2); + return(NULL); + } + if (Cudd_IsComplement(Ne)) { + (void) Cudd_ApaSubtract(digits,max,mint2,mint); + carryout = Cudd_ApaAdd(digits,mint1,mint,mint); + } else { + carryout = Cudd_ApaAdd(digits,mint1,mint2,mint); + } + Cudd_ApaShiftRight(digits,carryout,mint,mint); + /* If the refernce count of a child is 1, its minterm count + ** hasn't been stored in table. Therefore, it must be explicitly + ** freed here. */ + if (Nt->ref == 1) FREE(mint1); + if (Cudd_Regular(Ne)->ref == 1) FREE(mint2); + + if (node->ref > 1) { + if (st_insert(table, (char *)node, (char *)mint) == ST_OUT_OF_MEM) { + FREE(mint); + return(NULL); + } + } + return(mint); + +} /* end of cuddApaCountMintermAux */ + + +/**Function******************************************************************** + + Synopsis [Frees the memory used to store the minterm counts recorded + in the visited table.] + + Description [Frees the memory used to store the minterm counts + recorded in the visited table. Returns ST_CONTINUE.] + + SideEffects [None] + +******************************************************************************/ +static enum st_retval +cuddApaStCountfree( + char * key, + char * value, + char * arg) +{ + DdApaNumber d; + + d = (DdApaNumber) value; + FREE(d); + return(ST_CONTINUE); + +} /* end of cuddApaStCountfree */ + + diff --git a/abc70930/src/bdd/cudd/cuddApprox.c b/abc70930/src/bdd/cudd/cuddApprox.c new file mode 100644 index 00000000..debcf48b --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddApprox.c @@ -0,0 +1,2192 @@ +/**CFile*********************************************************************** + + FileName [cuddApprox.c] + + PackageName [cudd] + + Synopsis [Procedures to approximate a given BDD.] + + Description [External procedures provided by this module: +
    +
  • Cudd_UnderApprox() +
  • Cudd_OverApprox() +
  • Cudd_RemapUnderApprox() +
  • Cudd_RemapOverApprox() +
  • Cudd_BiasedUnderApprox() +
  • Cudd_BiasedOverApprox() +
+ Internal procedures included in this module: +
    +
  • cuddUnderApprox() +
  • cuddRemapUnderApprox() +
  • cuddBiasedUnderApprox() +
+ Static procedures included in this module: +
    +
  • gatherInfoAux() +
  • gatherInfo() +
  • computeSavings() +
  • UAmarkNodes() +
  • UAbuildSubset() +
  • updateRefs() +
  • RAmarkNodes() +
  • BAmarkNodes() +
  • RAbuildSubset() +
+ ] + + SeeAlso [cuddSubsetHB.c cuddSubsetSP.c cuddGenCof.c] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no + warranty about the suitability of this software for any + purpose. It is presented on an AS IS basis.] + +******************************************************************************/ + +#ifdef __STDC__ +#include +#else +#define DBL_MAX_EXP 1024 +#endif +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define NOTHING 0 +#define REPLACE_T 1 +#define REPLACE_E 2 +#define REPLACE_N 3 +#define REPLACE_TT 4 +#define REPLACE_TE 5 + +#define DONT_CARE 0 +#define CARE 1 +#define TOTAL_CARE 2 +#define CARE_ERROR 3 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/* Data structure to store the information on each node. It keeps the +** number of minterms of the function rooted at this node in terms of +** the number of variables specified by the user; the number of +** minterms of the complement; the impact of the number of minterms of +** this function on the number of minterms of the root function; the +** reference count of the node from within the root function; the +** reference count of the node from an internal node; and the flag +** that says whether the node should be replaced and how. */ +typedef struct NodeData { + double mintermsP; /* minterms for the regular node */ + double mintermsN; /* minterms for the complemented node */ + int functionRef; /* references from within this function */ + char care; /* node intersects care set */ + char replace; /* replacement decision */ + short int parity; /* 1: even; 2: odd; 3: both */ + DdNode *resultP; /* result for even parity */ + DdNode *resultN; /* result for odd parity */ +} NodeData; + +typedef struct ApproxInfo { + DdNode *one; /* one constant */ + DdNode *zero; /* BDD zero constant */ + NodeData *page; /* per-node information */ + st_table *table; /* hash table to access the per-node info */ + int index; /* index of the current node */ + double max; /* max number of minterms */ + int size; /* how many nodes are left */ + double minterms; /* how many minterms are left */ +} ApproxInfo; + +/* Item of the queue used in the levelized traversal of the BDD. */ +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif +typedef struct GlobalQueueItem { + struct GlobalQueueItem *next; + struct GlobalQueueItem *cnext; + DdNode *node; + double impactP; + double impactN; +} GlobalQueueItem; + +typedef struct LocalQueueItem { + struct LocalQueueItem *next; + struct LocalQueueItem *cnext; + DdNode *node; + int localRef; +} LocalQueueItem; +#ifdef __osf__ +#pragma pointer_size restore +#endif + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddApprox.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void updateParity ARGS((DdNode *node, ApproxInfo *info, int newparity)); +static NodeData * gatherInfoAux ARGS((DdNode *node, ApproxInfo *info, int parity)); +static ApproxInfo * gatherInfo ARGS((DdManager *dd, DdNode *node, int numVars, int parity)); +static int computeSavings ARGS((DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue)); +static int updateRefs ARGS((DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue)); +static int UAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, int safe, double quality)); +static DdNode * UAbuildSubset ARGS((DdManager *dd, DdNode *node, ApproxInfo *info)); +static int RAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality)); +static int BAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality1, double quality0)); +static DdNode * RAbuildSubset ARGS((DdManager *dd, DdNode *node, ApproxInfo *info)); +static int BAapplyBias ARGS((DdManager *dd, DdNode *f, DdNode *b, ApproxInfo *info, DdHashTable *cache)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Extracts a dense subset from a BDD with Shiple's + underapproximation method.] + + Description [Extracts a dense subset from a BDD. This procedure uses + a variant of Tom Shiple's underapproximation method. The main + difference from the original method is that density is used as cost + function. Returns a pointer to the BDD of the subset if + successful. NULL if the procedure runs out of memory. The parameter + numVars is the maximum number of variables to be used in minterm + calculation. The optimal number should be as close as possible to + the size of the support of f. However, it is safe to pass the value + returned by Cudd_ReadSize for numVars when the number of variables + is under 1023. If numVars is larger than 1023, it will cause + overflow. If a 0 parameter is passed then the procedure will compute + a value which will avoid overflow but will cause underflow with 2046 + variables or more.] + + SideEffects [None] + + SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize] + +******************************************************************************/ +DdNode * +Cudd_UnderApprox( + DdManager * dd /* manager */, + DdNode * f /* function to be subset */, + int numVars /* number of variables in the support of f */, + int threshold /* when to stop approximation */, + int safe /* enforce safe approximation */, + double quality /* minimum improvement for accepted changes */) +{ + DdNode *subset; + + do { + dd->reordered = 0; + subset = cuddUnderApprox(dd, f, numVars, threshold, safe, quality); + } while (dd->reordered == 1); + + return(subset); + +} /* end of Cudd_UnderApprox */ + + +/**Function******************************************************************** + + Synopsis [Extracts a dense superset from a BDD with Shiple's + underapproximation method.] + + Description [Extracts a dense superset from a BDD. The procedure is + identical to the underapproximation procedure except for the fact that it + works on the complement of the given function. Extracting the subset + of the complement function is equivalent to extracting the superset + of the function. + Returns a pointer to the BDD of the superset if successful. NULL if + intermediate result causes the procedure to run out of memory. The + parameter numVars is the maximum number of variables to be used in + minterm calculation. The optimal number + should be as close as possible to the size of the support of f. + However, it is safe to pass the value returned by Cudd_ReadSize for + numVars when the number of variables is under 1023. If numVars is + larger than 1023, it will overflow. If a 0 parameter is passed then + the procedure will compute a value which will avoid overflow but + will cause underflow with 2046 variables or more.] + + SideEffects [None] + + SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] + +******************************************************************************/ +DdNode * +Cudd_OverApprox( + DdManager * dd /* manager */, + DdNode * f /* function to be superset */, + int numVars /* number of variables in the support of f */, + int threshold /* when to stop approximation */, + int safe /* enforce safe approximation */, + double quality /* minimum improvement for accepted changes */) +{ + DdNode *subset, *g; + + g = Cudd_Not(f); + do { + dd->reordered = 0; + subset = cuddUnderApprox(dd, g, numVars, threshold, safe, quality); + } while (dd->reordered == 1); + + return(Cudd_NotCond(subset, (subset != NULL))); + +} /* end of Cudd_OverApprox */ + + +/**Function******************************************************************** + + Synopsis [Extracts a dense subset from a BDD with the remapping + underapproximation method.] + + Description [Extracts a dense subset from a BDD. This procedure uses + a remapping technique and density as the cost function. + Returns a pointer to the BDD of the subset if + successful. NULL if the procedure runs out of memory. The parameter + numVars is the maximum number of variables to be used in minterm + calculation. The optimal number should be as close as possible to + the size of the support of f. However, it is safe to pass the value + returned by Cudd_ReadSize for numVars when the number of variables + is under 1023. If numVars is larger than 1023, it will cause + overflow. If a 0 parameter is passed then the procedure will compute + a value which will avoid overflow but will cause underflow with 2046 + variables or more.] + + SideEffects [None] + + SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox Cudd_ReadSize] + +******************************************************************************/ +DdNode * +Cudd_RemapUnderApprox( + DdManager * dd /* manager */, + DdNode * f /* function to be subset */, + int numVars /* number of variables in the support of f */, + int threshold /* when to stop approximation */, + double quality /* minimum improvement for accepted changes */) +{ + DdNode *subset; + + do { + dd->reordered = 0; + subset = cuddRemapUnderApprox(dd, f, numVars, threshold, quality); + } while (dd->reordered == 1); + + return(subset); + +} /* end of Cudd_RemapUnderApprox */ + + +/**Function******************************************************************** + + Synopsis [Extracts a dense superset from a BDD with the remapping + underapproximation method.] + + Description [Extracts a dense superset from a BDD. The procedure is + identical to the underapproximation procedure except for the fact that it + works on the complement of the given function. Extracting the subset + of the complement function is equivalent to extracting the superset + of the function. + Returns a pointer to the BDD of the superset if successful. NULL if + intermediate result causes the procedure to run out of memory. The + parameter numVars is the maximum number of variables to be used in + minterm calculation. The optimal number + should be as close as possible to the size of the support of f. + However, it is safe to pass the value returned by Cudd_ReadSize for + numVars when the number of variables is under 1023. If numVars is + larger than 1023, it will overflow. If a 0 parameter is passed then + the procedure will compute a value which will avoid overflow but + will cause underflow with 2046 variables or more.] + + SideEffects [None] + + SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] + +******************************************************************************/ +DdNode * +Cudd_RemapOverApprox( + DdManager * dd /* manager */, + DdNode * f /* function to be superset */, + int numVars /* number of variables in the support of f */, + int threshold /* when to stop approximation */, + double quality /* minimum improvement for accepted changes */) +{ + DdNode *subset, *g; + + g = Cudd_Not(f); + do { + dd->reordered = 0; + subset = cuddRemapUnderApprox(dd, g, numVars, threshold, quality); + } while (dd->reordered == 1); + + return(Cudd_NotCond(subset, (subset != NULL))); + +} /* end of Cudd_RemapOverApprox */ + + +/**Function******************************************************************** + + Synopsis [Extracts a dense subset from a BDD with the biased + underapproximation method.] + + Description [Extracts a dense subset from a BDD. This procedure uses + a biased remapping technique and density as the cost function. The bias + is a function. This procedure tries to approximate where the bias is 0 + and preserve the given function where the bias is 1. + Returns a pointer to the BDD of the subset if + successful. NULL if the procedure runs out of memory. The parameter + numVars is the maximum number of variables to be used in minterm + calculation. The optimal number should be as close as possible to + the size of the support of f. However, it is safe to pass the value + returned by Cudd_ReadSize for numVars when the number of variables + is under 1023. If numVars is larger than 1023, it will cause + overflow. If a 0 parameter is passed then the procedure will compute + a value which will avoid overflow but will cause underflow with 2046 + variables or more.] + + SideEffects [None] + + SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox + Cudd_RemapUnderApprox Cudd_ReadSize] + +******************************************************************************/ +DdNode * +Cudd_BiasedUnderApprox( + DdManager *dd /* manager */, + DdNode *f /* function to be subset */, + DdNode *b /* bias function */, + int numVars /* number of variables in the support of f */, + int threshold /* when to stop approximation */, + double quality1 /* minimum improvement for accepted changes when b=1 */, + double quality0 /* minimum improvement for accepted changes when b=0 */) +{ + DdNode *subset; + + do { + dd->reordered = 0; + subset = cuddBiasedUnderApprox(dd, f, b, numVars, threshold, quality1, + quality0); + } while (dd->reordered == 1); + + return(subset); + +} /* end of Cudd_BiasedUnderApprox */ + + +/**Function******************************************************************** + + Synopsis [Extracts a dense superset from a BDD with the biased + underapproximation method.] + + Description [Extracts a dense superset from a BDD. The procedure is + identical to the underapproximation procedure except for the fact that it + works on the complement of the given function. Extracting the subset + of the complement function is equivalent to extracting the superset + of the function. + Returns a pointer to the BDD of the superset if successful. NULL if + intermediate result causes the procedure to run out of memory. The + parameter numVars is the maximum number of variables to be used in + minterm calculation. The optimal number + should be as close as possible to the size of the support of f. + However, it is safe to pass the value returned by Cudd_ReadSize for + numVars when the number of variables is under 1023. If numVars is + larger than 1023, it will overflow. If a 0 parameter is passed then + the procedure will compute a value which will avoid overflow but + will cause underflow with 2046 variables or more.] + + SideEffects [None] + + SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths + Cudd_RemapOverApprox Cudd_BiasedUnderApprox Cudd_ReadSize] + +******************************************************************************/ +DdNode * +Cudd_BiasedOverApprox( + DdManager *dd /* manager */, + DdNode *f /* function to be superset */, + DdNode *b /* bias function */, + int numVars /* number of variables in the support of f */, + int threshold /* when to stop approximation */, + double quality1 /* minimum improvement for accepted changes when b=1*/, + double quality0 /* minimum improvement for accepted changes when b=0 */) +{ + DdNode *subset, *g; + + g = Cudd_Not(f); + do { + dd->reordered = 0; + subset = cuddBiasedUnderApprox(dd, g, b, numVars, threshold, quality1, + quality0); + } while (dd->reordered == 1); + + return(Cudd_NotCond(subset, (subset != NULL))); + +} /* end of Cudd_BiasedOverApprox */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Applies Tom Shiple's underappoximation algorithm.] + + Description [Applies Tom Shiple's underappoximation algorithm. Proceeds + in three phases: +
    +
  • collect information on each node in the BDD; this is done via DFS. +
  • traverse the BDD in top-down fashion and compute for each node + whether its elimination increases density. +
  • traverse the BDD via DFS and actually perform the elimination. +
+ Returns the approximated BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_UnderApprox] + +******************************************************************************/ +DdNode * +cuddUnderApprox( + DdManager * dd /* DD manager */, + DdNode * f /* current DD */, + int numVars /* maximum number of variables */, + int threshold /* threshold under which approximation stops */, + int safe /* enforce safe approximation */, + double quality /* minimum improvement for accepted changes */) +{ + ApproxInfo *info; + DdNode *subset; + int result; + + if (f == NULL) { + fprintf(dd->err, "Cannot subset, nil object\n"); + return(NULL); + } + + if (Cudd_IsConstant(f)) { + return(f); + } + + /* Create table where node data are accessible via a hash table. */ + info = gatherInfo(dd, f, numVars, safe); + if (info == NULL) { + (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + /* Mark nodes that should be replaced by zero. */ + result = UAmarkNodes(dd, f, info, threshold, safe, quality); + if (result == 0) { + (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); + FREE(info->page); + st_free_table(info->table); + FREE(info); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + /* Build the result. */ + subset = UAbuildSubset(dd, f, info); +#if 1 + if (subset && info->size < Cudd_DagSize(subset)) + (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", + info->size, Cudd_DagSize(subset)); +#endif + FREE(info->page); + st_free_table(info->table); + FREE(info); + +#ifdef DD_DEBUG + if (subset != NULL) { + cuddRef(subset); +#if 0 + (void) Cudd_DebugCheck(dd); + (void) Cudd_CheckKeys(dd); +#endif + if (!Cudd_bddLeq(dd, subset, f)) { + (void) fprintf(dd->err, "Wrong subset\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + } + cuddDeref(subset); + } +#endif + return(subset); + +} /* end of cuddUnderApprox */ + + +/**Function******************************************************************** + + Synopsis [Applies the remapping underappoximation algorithm.] + + Description [Applies the remapping underappoximation algorithm. + Proceeds in three phases: +
    +
  • collect information on each node in the BDD; this is done via DFS. +
  • traverse the BDD in top-down fashion and compute for each node + whether remapping increases density. +
  • traverse the BDD via DFS and actually perform the elimination. +
+ Returns the approximated BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_RemapUnderApprox] + +******************************************************************************/ +DdNode * +cuddRemapUnderApprox( + DdManager * dd /* DD manager */, + DdNode * f /* current DD */, + int numVars /* maximum number of variables */, + int threshold /* threshold under which approximation stops */, + double quality /* minimum improvement for accepted changes */) +{ + ApproxInfo *info; + DdNode *subset; + int result; + + if (f == NULL) { + fprintf(dd->err, "Cannot subset, nil object\n"); + dd->errorCode = CUDD_INVALID_ARG; + return(NULL); + } + + if (Cudd_IsConstant(f)) { + return(f); + } + + /* Create table where node data are accessible via a hash table. */ + info = gatherInfo(dd, f, numVars, TRUE); + if (info == NULL) { + (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + /* Mark nodes that should be replaced by zero. */ + result = RAmarkNodes(dd, f, info, threshold, quality); + if (result == 0) { + (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); + FREE(info->page); + st_free_table(info->table); + FREE(info); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + /* Build the result. */ + subset = RAbuildSubset(dd, f, info); +#if 1 + if (subset && info->size < Cudd_DagSize(subset)) + (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", + info->size, Cudd_DagSize(subset)); +#endif + FREE(info->page); + st_free_table(info->table); + FREE(info); + +#ifdef DD_DEBUG + if (subset != NULL) { + cuddRef(subset); +#if 0 + (void) Cudd_DebugCheck(dd); + (void) Cudd_CheckKeys(dd); +#endif + if (!Cudd_bddLeq(dd, subset, f)) { + (void) fprintf(dd->err, "Wrong subset\n"); + } + cuddDeref(subset); + dd->errorCode = CUDD_INTERNAL_ERROR; + } +#endif + return(subset); + +} /* end of cuddRemapUnderApprox */ + + +/**Function******************************************************************** + + Synopsis [Applies the biased remapping underappoximation algorithm.] + + Description [Applies the biased remapping underappoximation algorithm. + Proceeds in three phases: +
    +
  • collect information on each node in the BDD; this is done via DFS. +
  • traverse the BDD in top-down fashion and compute for each node + whether remapping increases density. +
  • traverse the BDD via DFS and actually perform the elimination. +
+ Returns the approximated BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_BiasedUnderApprox] + +******************************************************************************/ +DdNode * +cuddBiasedUnderApprox( + DdManager *dd /* DD manager */, + DdNode *f /* current DD */, + DdNode *b /* bias function */, + int numVars /* maximum number of variables */, + int threshold /* threshold under which approximation stops */, + double quality1 /* minimum improvement for accepted changes when b=1 */, + double quality0 /* minimum improvement for accepted changes when b=1 */) +{ + ApproxInfo *info; + DdNode *subset; + int result; + DdHashTable *cache; + + if (f == NULL) { + fprintf(dd->err, "Cannot subset, nil object\n"); + dd->errorCode = CUDD_INVALID_ARG; + return(NULL); + } + + if (Cudd_IsConstant(f)) { + return(f); + } + + /* Create table where node data are accessible via a hash table. */ + info = gatherInfo(dd, f, numVars, TRUE); + if (info == NULL) { + (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + cache = cuddHashTableInit(dd,2,2); + result = BAapplyBias(dd, Cudd_Regular(f), b, info, cache); + if (result == CARE_ERROR) { + (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); + cuddHashTableQuit(cache); + FREE(info->page); + st_free_table(info->table); + FREE(info); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + cuddHashTableQuit(cache); + + /* Mark nodes that should be replaced by zero. */ + result = BAmarkNodes(dd, f, info, threshold, quality1, quality0); + if (result == 0) { + (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); + FREE(info->page); + st_free_table(info->table); + FREE(info); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + /* Build the result. */ + subset = RAbuildSubset(dd, f, info); +#if 1 + if (subset && info->size < Cudd_DagSize(subset)) + (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", + info->size, Cudd_DagSize(subset)); +#endif + FREE(info->page); + st_free_table(info->table); + FREE(info); + +#ifdef DD_DEBUG + if (subset != NULL) { + cuddRef(subset); +#if 0 + (void) Cudd_DebugCheck(dd); + (void) Cudd_CheckKeys(dd); +#endif + if (!Cudd_bddLeq(dd, subset, f)) { + (void) fprintf(dd->err, "Wrong subset\n"); + } + cuddDeref(subset); + dd->errorCode = CUDD_INTERNAL_ERROR; + } +#endif + return(subset); + +} /* end of cuddBiasedUnderApprox */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Recursively update the parity of the paths reaching a node.] + + Description [Recursively update the parity of the paths reaching a node. + Assumes that node is regular and propagates the invariant.] + + SideEffects [None] + + SeeAlso [gatherInfoAux] + +******************************************************************************/ +static void +updateParity( + DdNode * node /* function to analyze */, + ApproxInfo * info /* info on BDD */, + int newparity /* new parity for node */) +{ + NodeData *infoN; + DdNode *E; + + if (!st_lookup(info->table, (char *)node, (char **)&infoN)) return; + if ((infoN->parity & newparity) != 0) return; + infoN->parity |= newparity; + if (Cudd_IsConstant(node)) return; + updateParity(cuddT(node),info,newparity); + E = cuddE(node); + if (Cudd_IsComplement(E)) { + updateParity(Cudd_Not(E),info,3-newparity); + } else { + updateParity(E,info,newparity); + } + return; + +} /* end of updateParity */ + + +/**Function******************************************************************** + + Synopsis [Recursively counts minterms and computes reference counts + of each node in the BDD.] + + Description [Recursively counts minterms and computes reference + counts of each node in the BDD. Similar to the cuddCountMintermAux + which recursively counts the number of minterms for the dag rooted + at each node in terms of the total number of variables (max). It assumes + that the node pointer passed to it is regular and it maintains the + invariant.] + + SideEffects [None] + + SeeAlso [gatherInfo] + +******************************************************************************/ +static NodeData * +gatherInfoAux( + DdNode * node /* function to analyze */, + ApproxInfo * info /* info on BDD */, + int parity /* gather parity information */) +{ + DdNode *N, *Nt, *Ne; + NodeData *infoN, *infoT, *infoE; + + N = Cudd_Regular(node); + + /* Check whether entry for this node exists. */ + if (st_lookup(info->table, (char *)N, (char **)&infoN)) { + if (parity) { + /* Update parity and propagate. */ + updateParity(N, info, 1 + (int) Cudd_IsComplement(node)); + } + return(infoN); + } + + /* Compute the cofactors. */ + Nt = Cudd_NotCond(cuddT(N), N != node); + Ne = Cudd_NotCond(cuddE(N), N != node); + + infoT = gatherInfoAux(Nt, info, parity); + if (infoT == NULL) return(NULL); + infoE = gatherInfoAux(Ne, info, parity); + if (infoE == NULL) return(NULL); + + infoT->functionRef++; + infoE->functionRef++; + + /* Point to the correct location in the page. */ + infoN = &(info->page[info->index++]); + infoN->parity |= 1 + (short) Cudd_IsComplement(node); + + infoN->mintermsP = infoT->mintermsP/2; + infoN->mintermsN = infoT->mintermsN/2; + if (Cudd_IsComplement(Ne) ^ Cudd_IsComplement(node)) { + infoN->mintermsP += infoE->mintermsN/2; + infoN->mintermsN += infoE->mintermsP/2; + } else { + infoN->mintermsP += infoE->mintermsP/2; + infoN->mintermsN += infoE->mintermsN/2; + } + + /* Insert entry for the node in the table. */ + if (st_insert(info->table,(char *)N, (char *)infoN) == ST_OUT_OF_MEM) { + return(NULL); + } + return(infoN); + +} /* end of gatherInfoAux */ + + +/**Function******************************************************************** + + Synopsis [Gathers information about each node.] + + Description [Counts minterms and computes reference counts of each + node in the BDD . The minterm count is separately computed for the + node and its complement. This is to avoid cancellation + errors. Returns a pointer to the data structure holding the + information gathered if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddUnderApprox gatherInfoAux] + +******************************************************************************/ +static ApproxInfo * +gatherInfo( + DdManager * dd /* manager */, + DdNode * node /* function to be analyzed */, + int numVars /* number of variables node depends on */, + int parity /* gather parity information */) +{ + ApproxInfo *info; + NodeData *infoTop; + + /* If user did not give numVars value, set it to the maximum + ** exponent that the pow function can take. The -1 is due to the + ** discrepancy in the value that pow takes and the value that + ** log gives. + */ + if (numVars == 0) { + numVars = DBL_MAX_EXP - 1; + } + + info = ALLOC(ApproxInfo,1); + if (info == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + info->max = pow(2.0,(double) numVars); + info->one = DD_ONE(dd); + info->zero = Cudd_Not(info->one); + info->size = Cudd_DagSize(node); + /* All the information gathered will be stored in a contiguous + ** piece of memory, which is allocated here. This can be done + ** efficiently because we have counted the number of nodes of the + ** BDD. info->index points to the next available entry in the array + ** that stores the per-node information. */ + info->page = ALLOC(NodeData,info->size); + if (info->page == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(info); + return(NULL); + } + memset(info->page, 0, info->size * sizeof(NodeData)); /* clear all page */ + info->table = st_init_table(st_ptrcmp,st_ptrhash); + if (info->table == NULL) { + FREE(info->page); + FREE(info); + return(NULL); + } + /* We visit the DAG in post-order DFS. Hence, the constant node is + ** in first position, and the root of the DAG is in last position. */ + + /* Info for the constant node: Initialize only fields different from 0. */ + if (st_insert(info->table, (char *)info->one, (char *)info->page) == ST_OUT_OF_MEM) { + FREE(info->page); + FREE(info); + st_free_table(info->table); + return(NULL); + } + info->page[0].mintermsP = info->max; + info->index = 1; + + infoTop = gatherInfoAux(node,info,parity); + if (infoTop == NULL) { + FREE(info->page); + st_free_table(info->table); + FREE(info); + return(NULL); + } + if (Cudd_IsComplement(node)) { + info->minterms = infoTop->mintermsN; + } else { + info->minterms = infoTop->mintermsP; + } + + infoTop->functionRef = 1; + return(info); + +} /* end of gatherInfo */ + + +/**Function******************************************************************** + + Synopsis [Counts the nodes that would be eliminated if a given node + were replaced by zero.] + + Description [Counts the nodes that would be eliminated if a given + node were replaced by zero. This procedure uses a queue passed by + the caller for efficiency: since the queue is left empty at the + endof the search, it can be reused as is by the next search. Returns + the count (always striclty positive) if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [cuddUnderApprox] + +******************************************************************************/ +static int +computeSavings( + DdManager * dd, + DdNode * f, + DdNode * skip, + ApproxInfo * info, + DdLevelQueue * queue) +{ + NodeData *infoN; + LocalQueueItem *item; + DdNode *node; + int savings = 0; + + node = Cudd_Regular(f); + skip = Cudd_Regular(skip); + /* Insert the given node in the level queue. Its local reference + ** count is set equal to the function reference count so that the + ** search will continue from it when it is retrieved. */ + item = (LocalQueueItem *) + cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); + if (item == NULL) + return(0); + (void) st_lookup(info->table, (char *)node, (char **)&infoN); + item->localRef = infoN->functionRef; + + /* Process the queue. */ + while (queue->first != NULL) { + item = (LocalQueueItem *) queue->first; + node = item->node; + cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); + if (node == skip) continue; + (void) st_lookup(info->table, (char *)node, (char **)&infoN); + if (item->localRef != infoN->functionRef) { + /* This node is shared. */ + continue; + } + savings++; + if (!cuddIsConstant(cuddT(node))) { + item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), + cuddI(dd,cuddT(node)->index)); + if (item == NULL) return(0); + item->localRef++; + } + if (!Cudd_IsConstant(cuddE(node))) { + item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), + cuddI(dd,Cudd_Regular(cuddE(node))->index)); + if (item == NULL) return(0); + item->localRef++; + } + } + +#ifdef DD_DEBUG + /* At the end of a local search the queue should be empty. */ + assert(queue->size == 0); +#endif + return(savings); + +} /* end of computeSavings */ + + +/**Function******************************************************************** + + Synopsis [Update function reference counts.] + + Description [Update function reference counts to account for replacement. + Returns the number of nodes saved if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [UAmarkNodes RAmarkNodes] + +******************************************************************************/ +static int +updateRefs( + DdManager * dd, + DdNode * f, + DdNode * skip, + ApproxInfo * info, + DdLevelQueue * queue) +{ + NodeData *infoN; + LocalQueueItem *item; + DdNode *node; + int savings = 0; + + node = Cudd_Regular(f); + /* Insert the given node in the level queue. Its function reference + ** count is set equal to 0 so that the search will continue from it + ** when it is retrieved. */ + item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); + if (item == NULL) + return(0); + (void) st_lookup(info->table, (char *)node, (char **)&infoN); + infoN->functionRef = 0; + + if (skip != NULL) { + /* Increase the function reference count of the node to be skipped + ** by 1 to account for the node pointing to it that will be created. */ + skip = Cudd_Regular(skip); + (void) st_lookup(info->table, (char *)skip, (char **)&infoN); + infoN->functionRef++; + } + + /* Process the queue. */ + while (queue->first != NULL) { + item = (LocalQueueItem *) queue->first; + node = item->node; + cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); + (void) st_lookup(info->table, (char *)node, (char **)&infoN); + if (infoN->functionRef != 0) { + /* This node is shared or must be skipped. */ + continue; + } + savings++; + if (!cuddIsConstant(cuddT(node))) { + item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), + cuddI(dd,cuddT(node)->index)); + if (item == NULL) return(0); + (void) st_lookup(info->table, (char *)cuddT(node), + (char **)&infoN); + infoN->functionRef--; + } + if (!Cudd_IsConstant(cuddE(node))) { + item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), + cuddI(dd,Cudd_Regular(cuddE(node))->index)); + if (item == NULL) return(0); + (void) st_lookup(info->table, (char *)Cudd_Regular(cuddE(node)), + (char **)&infoN); + infoN->functionRef--; + } + } + +#ifdef DD_DEBUG + /* At the end of a local search the queue should be empty. */ + assert(queue->size == 0); +#endif + return(savings); + +} /* end of updateRefs */ + + +/**Function******************************************************************** + + Synopsis [Marks nodes for replacement by zero.] + + Description [Marks nodes for replacement by zero. Returns 1 if successful; + 0 otherwise.] + + SideEffects [None] + + SeeAlso [cuddUnderApprox] + +******************************************************************************/ +static int +UAmarkNodes( + DdManager * dd /* manager */, + DdNode * f /* function to be analyzed */, + ApproxInfo * info /* info on BDD */, + int threshold /* when to stop approximating */, + int safe /* enforce safe approximation */, + double quality /* minimum improvement for accepted changes */) +{ + DdLevelQueue *queue; + DdLevelQueue *localQueue; + NodeData *infoN; + GlobalQueueItem *item; + DdNode *node; + double numOnset; + double impactP, impactN; + int savings; + +#if 0 + (void) printf("initial size = %d initial minterms = %g\n", + info->size, info->minterms); +#endif + queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); + if (queue == NULL) { + return(0); + } + localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), + dd->initSlots); + if (localQueue == NULL) { + cuddLevelQueueQuit(queue); + return(0); + } + node = Cudd_Regular(f); + item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); + if (item == NULL) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + if (Cudd_IsComplement(f)) { + item->impactP = 0.0; + item->impactN = 1.0; + } else { + item->impactP = 1.0; + item->impactN = 0.0; + } + while (queue->first != NULL) { + /* If the size of the subset is below the threshold, quit. */ + if (info->size <= threshold) + break; + item = (GlobalQueueItem *) queue->first; + node = item->node; + node = Cudd_Regular(node); + (void) st_lookup(info->table, (char *)node, (char **)&infoN); + if (safe && infoN->parity == 3) { + cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); + continue; + } + impactP = item->impactP; + impactN = item->impactN; + numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; + savings = computeSavings(dd,node,NULL,info,localQueue); + if (savings == 0) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); +#if 0 + (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", + node, impactP, impactN, numOnset, savings); +#endif + if ((1 - numOnset / info->minterms) > + quality * (1 - (double) savings / info->size)) { + infoN->replace = TRUE; + info->size -= savings; + info->minterms -=numOnset; +#if 0 + (void) printf("replace: new size = %d new minterms = %g\n", + info->size, info->minterms); +#endif + savings -= updateRefs(dd,node,NULL,info,localQueue); + assert(savings == 0); + continue; + } + if (!cuddIsConstant(cuddT(node))) { + item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), + cuddI(dd,cuddT(node)->index)); + item->impactP += impactP/2.0; + item->impactN += impactN/2.0; + } + if (!Cudd_IsConstant(cuddE(node))) { + item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), + cuddI(dd,Cudd_Regular(cuddE(node))->index)); + if (Cudd_IsComplement(cuddE(node))) { + item->impactP += impactN/2.0; + item->impactN += impactP/2.0; + } else { + item->impactP += impactP/2.0; + item->impactN += impactN/2.0; + } + } + } + + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(1); + +} /* end of UAmarkNodes */ + + +/**Function******************************************************************** + + Synopsis [Builds the subset BDD.] + + Description [Builds the subset BDD. Based on the info table, + replaces selected nodes by zero. Returns a pointer to the result if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddUnderApprox] + +******************************************************************************/ +static DdNode * +UAbuildSubset( + DdManager * dd /* DD manager */, + DdNode * node /* current node */, + ApproxInfo * info /* node info */) +{ + + DdNode *Nt, *Ne, *N, *t, *e, *r; + NodeData *infoN; + + if (Cudd_IsConstant(node)) + return(node); + + N = Cudd_Regular(node); + + if (st_lookup(info->table, (char *)N, (char **)&infoN)) { + if (infoN->replace == TRUE) { + return(info->zero); + } + if (N == node ) { + if (infoN->resultP != NULL) { + return(infoN->resultP); + } + } else { + if (infoN->resultN != NULL) { + return(infoN->resultN); + } + } + } else { + (void) fprintf(dd->err, + "Something is wrong, ought to be in info table\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + + Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node)); + Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node)); + + t = UAbuildSubset(dd, Nt, info); + if (t == NULL) { + return(NULL); + } + cuddRef(t); + + e = UAbuildSubset(dd, Ne, info); + if (e == NULL) { + Cudd_RecursiveDeref(dd,t); + return(NULL); + } + cuddRef(e); + + if (Cudd_IsComplement(t)) { + t = Cudd_Not(t); + e = Cudd_Not(e); + r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); + if (r == NULL) { + Cudd_RecursiveDeref(dd, e); + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); + if (r == NULL) { + Cudd_RecursiveDeref(dd, e); + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + } + cuddDeref(t); + cuddDeref(e); + + if (N == node) { + infoN->resultP = r; + } else { + infoN->resultN = r; + } + + return(r); + +} /* end of UAbuildSubset */ + + +/**Function******************************************************************** + + Synopsis [Marks nodes for remapping.] + + Description [Marks nodes for remapping. Returns 1 if successful; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [cuddRemapUnderApprox] + +******************************************************************************/ +static int +RAmarkNodes( + DdManager * dd /* manager */, + DdNode * f /* function to be analyzed */, + ApproxInfo * info /* info on BDD */, + int threshold /* when to stop approximating */, + double quality /* minimum improvement for accepted changes */) +{ + DdLevelQueue *queue; + DdLevelQueue *localQueue; + NodeData *infoN, *infoT, *infoE; + GlobalQueueItem *item; + DdNode *node, *T, *E; + DdNode *shared; /* grandchild shared by the two children of node */ + double numOnset; + double impact, impactP, impactN; + double minterms; + int savings; + int replace; + +#if 0 + (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n", + info->size, info->minterms); +#endif + queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); + if (queue == NULL) { + return(0); + } + localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), + dd->initSlots); + if (localQueue == NULL) { + cuddLevelQueueQuit(queue); + return(0); + } + /* Enqueue regular pointer to root and initialize impact. */ + node = Cudd_Regular(f); + item = (GlobalQueueItem *) + cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); + if (item == NULL) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + if (Cudd_IsComplement(f)) { + item->impactP = 0.0; + item->impactN = 1.0; + } else { + item->impactP = 1.0; + item->impactN = 0.0; + } + /* The nodes retrieved here are guaranteed to be non-terminal. + ** The initial node is not terminal because constant nodes are + ** dealt with in the calling procedure. Subsequent nodes are inserted + ** only if they are not terminal. */ + while (queue->first != NULL) { + /* If the size of the subset is below the threshold, quit. */ + if (info->size <= threshold) + break; + item = (GlobalQueueItem *) queue->first; + node = item->node; +#ifdef DD_DEBUG + assert(item->impactP >= 0 && item->impactP <= 1.0); + assert(item->impactN >= 0 && item->impactN <= 1.0); + assert(!Cudd_IsComplement(node)); + assert(!Cudd_IsConstant(node)); +#endif + if (!st_lookup(info->table, (char *)node, (char **)&infoN)) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } +#ifdef DD_DEBUG + assert(infoN->parity >= 1 && infoN->parity <= 3); +#endif + if (infoN->parity == 3) { + /* This node can be reached through paths of different parity. + ** It is not safe to replace it, because remapping will give + ** an incorrect result, while replacement by 0 may cause node + ** splitting. */ + cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); + continue; + } + T = cuddT(node); + E = cuddE(node); + shared = NULL; + impactP = item->impactP; + impactN = item->impactN; + if (Cudd_bddLeq(dd,T,E)) { + /* Here we know that E is regular. */ +#ifdef DD_DEBUG + assert(!Cudd_IsComplement(E)); +#endif + (void) st_lookup(info->table, (char *)T, (char **)&infoT); + (void) st_lookup(info->table, (char *)E, (char **)&infoE); + if (infoN->parity == 1) { + impact = impactP; + minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0; + if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { + savings = 1 + computeSavings(dd,E,NULL,info,localQueue); + if (savings == 1) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + } else { + savings = 1; + } + replace = REPLACE_E; + } else { +#ifdef DD_DEBUG + assert(infoN->parity == 2); +#endif + impact = impactN; + minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0; + if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { + savings = 1 + computeSavings(dd,T,NULL,info,localQueue); + if (savings == 1) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + } else { + savings = 1; + } + replace = REPLACE_T; + } + numOnset = impact * minterms; + } else if (Cudd_bddLeq(dd,E,T)) { + /* Here E may be complemented. */ + DdNode *Ereg = Cudd_Regular(E); + (void) st_lookup(info->table, (char *)T, (char **)&infoT); + (void) st_lookup(info->table, (char *)Ereg, (char **)&infoE); + if (infoN->parity == 1) { + impact = impactP; + minterms = infoT->mintermsP/2.0 - + ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0; + if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { + savings = 1 + computeSavings(dd,T,NULL,info,localQueue); + if (savings == 1) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + } else { + savings = 1; + } + replace = REPLACE_T; + } else { +#ifdef DD_DEBUG + assert(infoN->parity == 2); +#endif + impact = impactN; + minterms = ((E == Ereg) ? infoE->mintermsN : + infoE->mintermsP)/2.0 - infoT->mintermsN/2.0; + if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { + savings = 1 + computeSavings(dd,E,NULL,info,localQueue); + if (savings == 1) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + } else { + savings = 1; + } + replace = REPLACE_E; + } + numOnset = impact * minterms; + } else { + DdNode *Ereg = Cudd_Regular(E); + DdNode *TT = cuddT(T); + DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E)); + if (T->index == Ereg->index && TT == ET) { + shared = TT; + replace = REPLACE_TT; + } else { + DdNode *TE = cuddE(T); + DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E)); + if (T->index == Ereg->index && TE == EE) { + shared = TE; + replace = REPLACE_TE; + } else { + replace = REPLACE_N; + } + } + numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; + savings = computeSavings(dd,node,shared,info,localQueue); + if (shared != NULL) { + NodeData *infoS; + (void) st_lookup(info->table, (char *)Cudd_Regular(shared), + (char **)&infoS); + if (Cudd_IsComplement(shared)) { + numOnset -= (infoS->mintermsN * impactP + + infoS->mintermsP * impactN)/2.0; + } else { + numOnset -= (infoS->mintermsP * impactP + + infoS->mintermsN * impactN)/2.0; + } + savings--; + } + } + + cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); +#if 0 + if (replace == REPLACE_T || replace == REPLACE_E) + (void) printf("node %p: impact = %g numOnset = %g savings %d\n", + node, impact, numOnset, savings); + else + (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", + node, impactP, impactN, numOnset, savings); +#endif + if ((1 - numOnset / info->minterms) > + quality * (1 - (double) savings / info->size)) { + infoN->replace = replace; + info->size -= savings; + info->minterms -=numOnset; +#if 0 + (void) printf("remap(%d): new size = %d new minterms = %g\n", + replace, info->size, info->minterms); +#endif + if (replace == REPLACE_N) { + savings -= updateRefs(dd,node,NULL,info,localQueue); + } else if (replace == REPLACE_T) { + savings -= updateRefs(dd,node,E,info,localQueue); + } else if (replace == REPLACE_E) { + savings -= updateRefs(dd,node,T,info,localQueue); + } else { +#ifdef DD_DEBUG + assert(replace == REPLACE_TT || replace == REPLACE_TE); +#endif + savings -= updateRefs(dd,node,shared,info,localQueue) - 1; + } + assert(savings == 0); + } else { + replace = NOTHING; + } + if (replace == REPLACE_N) continue; + if ((replace == REPLACE_E || replace == NOTHING) && + !cuddIsConstant(cuddT(node))) { + item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), + cuddI(dd,cuddT(node)->index)); + if (replace == REPLACE_E) { + item->impactP += impactP; + item->impactN += impactN; + } else { + item->impactP += impactP/2.0; + item->impactN += impactN/2.0; + } + } + if ((replace == REPLACE_T || replace == NOTHING) && + !Cudd_IsConstant(cuddE(node))) { + item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), + cuddI(dd,Cudd_Regular(cuddE(node))->index)); + if (Cudd_IsComplement(cuddE(node))) { + if (replace == REPLACE_T) { + item->impactP += impactN; + item->impactN += impactP; + } else { + item->impactP += impactN/2.0; + item->impactN += impactP/2.0; + } + } else { + if (replace == REPLACE_T) { + item->impactP += impactP; + item->impactN += impactN; + } else { + item->impactP += impactP/2.0; + item->impactN += impactN/2.0; + } + } + } + if ((replace == REPLACE_TT || replace == REPLACE_TE) && + !Cudd_IsConstant(shared)) { + item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared), + cuddI(dd,Cudd_Regular(shared)->index)); + if (Cudd_IsComplement(shared)) { + if (replace == REPLACE_T) { + item->impactP += impactN; + item->impactN += impactP; + } else { + item->impactP += impactN/2.0; + item->impactN += impactP/2.0; + } + } else { + if (replace == REPLACE_T) { + item->impactP += impactP; + item->impactN += impactN; + } else { + item->impactP += impactP/2.0; + item->impactN += impactN/2.0; + } + } + } + } + + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(1); + +} /* end of RAmarkNodes */ + + +/**Function******************************************************************** + + Synopsis [Marks nodes for remapping.] + + Description [Marks nodes for remapping. Returns 1 if successful; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [cuddRemapUnderApprox] + +******************************************************************************/ +static int +BAmarkNodes( + DdManager *dd /* manager */, + DdNode *f /* function to be analyzed */, + ApproxInfo *info /* info on BDD */, + int threshold /* when to stop approximating */, + double quality1 /* minimum improvement for accepted changes when b=1 */, + double quality0 /* minimum improvement for accepted changes when b=0 */) +{ + DdLevelQueue *queue; + DdLevelQueue *localQueue; + NodeData *infoN, *infoT, *infoE; + GlobalQueueItem *item; + DdNode *node, *T, *E; + DdNode *shared; /* grandchild shared by the two children of node */ + double numOnset; + double impact, impactP, impactN; + double minterms; + double quality; + int savings; + int replace; + +#if 0 + (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n", + info->size, info->minterms); +#endif + queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); + if (queue == NULL) { + return(0); + } + localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), + dd->initSlots); + if (localQueue == NULL) { + cuddLevelQueueQuit(queue); + return(0); + } + /* Enqueue regular pointer to root and initialize impact. */ + node = Cudd_Regular(f); + item = (GlobalQueueItem *) + cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); + if (item == NULL) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + if (Cudd_IsComplement(f)) { + item->impactP = 0.0; + item->impactN = 1.0; + } else { + item->impactP = 1.0; + item->impactN = 0.0; + } + /* The nodes retrieved here are guaranteed to be non-terminal. + ** The initial node is not terminal because constant nodes are + ** dealt with in the calling procedure. Subsequent nodes are inserted + ** only if they are not terminal. */ + while (queue->first != NULL) { + /* If the size of the subset is below the threshold, quit. */ + if (info->size <= threshold) + break; + item = (GlobalQueueItem *) queue->first; + node = item->node; +#ifdef DD_DEBUG + assert(item->impactP >= 0 && item->impactP <= 1.0); + assert(item->impactN >= 0 && item->impactN <= 1.0); + assert(!Cudd_IsComplement(node)); + assert(!Cudd_IsConstant(node)); +#endif + if (!st_lookup(info->table, (char *)node, (char **)&infoN)) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + quality = infoN->care ? quality1 : quality0; +#ifdef DD_DEBUG + assert(infoN->parity >= 1 && infoN->parity <= 3); +#endif + if (infoN->parity == 3) { + /* This node can be reached through paths of different parity. + ** It is not safe to replace it, because remapping will give + ** an incorrect result, while replacement by 0 may cause node + ** splitting. */ + cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); + continue; + } + T = cuddT(node); + E = cuddE(node); + shared = NULL; + impactP = item->impactP; + impactN = item->impactN; + if (Cudd_bddLeq(dd,T,E)) { + /* Here we know that E is regular. */ +#ifdef DD_DEBUG + assert(!Cudd_IsComplement(E)); +#endif + (void) st_lookup(info->table, (char *)T, (char **)&infoT); + (void) st_lookup(info->table, (char *)E, (char **)&infoE); + if (infoN->parity == 1) { + impact = impactP; + minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0; + if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { + savings = 1 + computeSavings(dd,E,NULL,info,localQueue); + if (savings == 1) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + } else { + savings = 1; + } + replace = REPLACE_E; + } else { +#ifdef DD_DEBUG + assert(infoN->parity == 2); +#endif + impact = impactN; + minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0; + if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { + savings = 1 + computeSavings(dd,T,NULL,info,localQueue); + if (savings == 1) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + } else { + savings = 1; + } + replace = REPLACE_T; + } + numOnset = impact * minterms; + } else if (Cudd_bddLeq(dd,E,T)) { + /* Here E may be complemented. */ + DdNode *Ereg = Cudd_Regular(E); + (void) st_lookup(info->table, (char *)T, (char **)&infoT); + (void) st_lookup(info->table, (char *)Ereg, (char **)&infoE); + if (infoN->parity == 1) { + impact = impactP; + minterms = infoT->mintermsP/2.0 - + ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0; + if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { + savings = 1 + computeSavings(dd,T,NULL,info,localQueue); + if (savings == 1) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + } else { + savings = 1; + } + replace = REPLACE_T; + } else { +#ifdef DD_DEBUG + assert(infoN->parity == 2); +#endif + impact = impactN; + minterms = ((E == Ereg) ? infoE->mintermsN : + infoE->mintermsP)/2.0 - infoT->mintermsN/2.0; + if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { + savings = 1 + computeSavings(dd,E,NULL,info,localQueue); + if (savings == 1) { + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(0); + } + } else { + savings = 1; + } + replace = REPLACE_E; + } + numOnset = impact * minterms; + } else { + DdNode *Ereg = Cudd_Regular(E); + DdNode *TT = cuddT(T); + DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E)); + if (T->index == Ereg->index && TT == ET) { + shared = TT; + replace = REPLACE_TT; + } else { + DdNode *TE = cuddE(T); + DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E)); + if (T->index == Ereg->index && TE == EE) { + shared = TE; + replace = REPLACE_TE; + } else { + replace = REPLACE_N; + } + } + numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; + savings = computeSavings(dd,node,shared,info,localQueue); + if (shared != NULL) { + NodeData *infoS; + (void) st_lookup(info->table, (char *)Cudd_Regular(shared), + (char **)&infoS); + if (Cudd_IsComplement(shared)) { + numOnset -= (infoS->mintermsN * impactP + + infoS->mintermsP * impactN)/2.0; + } else { + numOnset -= (infoS->mintermsP * impactP + + infoS->mintermsN * impactN)/2.0; + } + savings--; + } + } + + cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); +#if 0 + if (replace == REPLACE_T || replace == REPLACE_E) + (void) printf("node %p: impact = %g numOnset = %g savings %d\n", + node, impact, numOnset, savings); + else + (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", + node, impactP, impactN, numOnset, savings); +#endif + if ((1 - numOnset / info->minterms) > + quality * (1 - (double) savings / info->size)) { + infoN->replace = replace; + info->size -= savings; + info->minterms -=numOnset; +#if 0 + (void) printf("remap(%d): new size = %d new minterms = %g\n", + replace, info->size, info->minterms); +#endif + if (replace == REPLACE_N) { + savings -= updateRefs(dd,node,NULL,info,localQueue); + } else if (replace == REPLACE_T) { + savings -= updateRefs(dd,node,E,info,localQueue); + } else if (replace == REPLACE_E) { + savings -= updateRefs(dd,node,T,info,localQueue); + } else { +#ifdef DD_DEBUG + assert(replace == REPLACE_TT || replace == REPLACE_TE); +#endif + savings -= updateRefs(dd,node,shared,info,localQueue) - 1; + } + assert(savings == 0); + } else { + replace = NOTHING; + } + if (replace == REPLACE_N) continue; + if ((replace == REPLACE_E || replace == NOTHING) && + !cuddIsConstant(cuddT(node))) { + item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), + cuddI(dd,cuddT(node)->index)); + if (replace == REPLACE_E) { + item->impactP += impactP; + item->impactN += impactN; + } else { + item->impactP += impactP/2.0; + item->impactN += impactN/2.0; + } + } + if ((replace == REPLACE_T || replace == NOTHING) && + !Cudd_IsConstant(cuddE(node))) { + item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), + cuddI(dd,Cudd_Regular(cuddE(node))->index)); + if (Cudd_IsComplement(cuddE(node))) { + if (replace == REPLACE_T) { + item->impactP += impactN; + item->impactN += impactP; + } else { + item->impactP += impactN/2.0; + item->impactN += impactP/2.0; + } + } else { + if (replace == REPLACE_T) { + item->impactP += impactP; + item->impactN += impactN; + } else { + item->impactP += impactP/2.0; + item->impactN += impactN/2.0; + } + } + } + if ((replace == REPLACE_TT || replace == REPLACE_TE) && + !Cudd_IsConstant(shared)) { + item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared), + cuddI(dd,Cudd_Regular(shared)->index)); + if (Cudd_IsComplement(shared)) { + if (replace == REPLACE_T) { + item->impactP += impactN; + item->impactN += impactP; + } else { + item->impactP += impactN/2.0; + item->impactN += impactP/2.0; + } + } else { + if (replace == REPLACE_T) { + item->impactP += impactP; + item->impactN += impactN; + } else { + item->impactP += impactP/2.0; + item->impactN += impactN/2.0; + } + } + } + } + + cuddLevelQueueQuit(queue); + cuddLevelQueueQuit(localQueue); + return(1); + +} /* end of BAmarkNodes */ + + +/**Function******************************************************************** + + Synopsis [Builds the subset BDD for cuddRemapUnderApprox.] + + Description [Builds the subset BDDfor cuddRemapUnderApprox. Based + on the info table, performs remapping or replacement at selected + nodes. Returns a pointer to the result if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [cuddRemapUnderApprox] + +******************************************************************************/ +static DdNode * +RAbuildSubset( + DdManager * dd /* DD manager */, + DdNode * node /* current node */, + ApproxInfo * info /* node info */) +{ + DdNode *Nt, *Ne, *N, *t, *e, *r; + NodeData *infoN; + + if (Cudd_IsConstant(node)) + return(node); + + N = Cudd_Regular(node); + + Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node)); + Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node)); + + if (st_lookup(info->table, (char *)N, (char **)&infoN)) { + if (N == node ) { + if (infoN->resultP != NULL) { + return(infoN->resultP); + } + } else { + if (infoN->resultN != NULL) { + return(infoN->resultN); + } + } + if (infoN->replace == REPLACE_T) { + r = RAbuildSubset(dd, Ne, info); + return(r); + } else if (infoN->replace == REPLACE_E) { + r = RAbuildSubset(dd, Nt, info); + return(r); + } else if (infoN->replace == REPLACE_N) { + return(info->zero); + } else if (infoN->replace == REPLACE_TT) { + DdNode *Ntt = Cudd_NotCond(cuddT(cuddT(N)), + Cudd_IsComplement(node)); + int index = cuddT(N)->index; + DdNode *e = info->zero; + DdNode *t = RAbuildSubset(dd, Ntt, info); + if (t == NULL) { + return(NULL); + } + cuddRef(t); + if (Cudd_IsComplement(t)) { + t = Cudd_Not(t); + e = Cudd_Not(e); + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + } + cuddDeref(t); + return(r); + } else if (infoN->replace == REPLACE_TE) { + DdNode *Nte = Cudd_NotCond(cuddE(cuddT(N)), + Cudd_IsComplement(node)); + int index = cuddT(N)->index; + DdNode *t = info->one; + DdNode *e = RAbuildSubset(dd, Nte, info); + if (e == NULL) { + return(NULL); + } + cuddRef(e); + e = Cudd_Not(e); + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + r =Cudd_Not(r); + cuddDeref(e); + return(r); + } + } else { + (void) fprintf(dd->err, + "Something is wrong, ought to be in info table\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + + t = RAbuildSubset(dd, Nt, info); + if (t == NULL) { + return(NULL); + } + cuddRef(t); + + e = RAbuildSubset(dd, Ne, info); + if (e == NULL) { + Cudd_RecursiveDeref(dd,t); + return(NULL); + } + cuddRef(e); + + if (Cudd_IsComplement(t)) { + t = Cudd_Not(t); + e = Cudd_Not(e); + r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); + if (r == NULL) { + Cudd_RecursiveDeref(dd, e); + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); + if (r == NULL) { + Cudd_RecursiveDeref(dd, e); + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + } + cuddDeref(t); + cuddDeref(e); + + if (N == node) { + infoN->resultP = r; + } else { + infoN->resultN = r; + } + + return(r); + +} /* end of RAbuildSubset */ + + +/**Function******************************************************************** + + Synopsis [Finds don't care nodes.] + + Description [Finds don't care nodes by traversing f and b in parallel. + Returns the care status of the visited f node if successful; CARE_ERROR + otherwise.] + + SideEffects [None] + + SeeAlso [cuddBiasedUnderApprox] + +******************************************************************************/ +static int +BAapplyBias( + DdManager *dd, + DdNode *f, + DdNode *b, + ApproxInfo *info, + DdHashTable *cache) +{ + DdNode *one, *zero, *res; + DdNode *Ft, *Fe, *B, *Bt, *Be; + unsigned int topf, topb; + NodeData *infoF; + int careT, careE; + + one = DD_ONE(dd); + zero = Cudd_Not(one); + + if (!st_lookup(info->table, (char *) f, (char **)&infoF)) + return(CARE_ERROR); + if (f == one) return(TOTAL_CARE); + if (b == zero) return(infoF->care); + if (infoF->care == TOTAL_CARE) return(TOTAL_CARE); + + if ((f->ref != 1 || Cudd_Regular(b)->ref != 1) && + (res = cuddHashTableLookup2(cache,f,b)) != NULL) { + if (res->ref == 0) { + cache->manager->dead++; + cache->manager->constants.dead++; + } + return(infoF->care); + } + + topf = dd->perm[f->index]; + B = Cudd_Regular(b); + topb = cuddI(dd,B->index); + if (topf <= topb) { + Ft = cuddT(f); Fe = cuddE(f); + } else { + Ft = Fe = f; + } + if (topb <= topf) { + /* We know that b is not constant because f is not. */ + Bt = cuddT(B); Be = cuddE(B); + if (Cudd_IsComplement(b)) { + Bt = Cudd_Not(Bt); + Be = Cudd_Not(Be); + } + } else { + Bt = Be = b; + } + + careT = BAapplyBias(dd, Ft, Bt, info, cache); + if (careT == CARE_ERROR) + return(CARE_ERROR); + careE = BAapplyBias(dd, Cudd_Regular(Fe), Be, info, cache); + if (careE == CARE_ERROR) + return(CARE_ERROR); + if (careT == TOTAL_CARE && careE == TOTAL_CARE) { + infoF->care = TOTAL_CARE; + } else { + infoF->care = CARE; + } + + if (f->ref != 1 || Cudd_Regular(b)->ref != 1) { + ptrint fanout = (ptrint) f->ref * Cudd_Regular(b)->ref; + cuddSatDec(fanout); + if (!cuddHashTableInsert2(cache,f,b,one,fanout)) { + return(CARE_ERROR); + } + } + return(infoF->care); + +} /* end of BAapplyBias */ diff --git a/abc70930/src/bdd/cudd/cuddBddAbs.c b/abc70930/src/bdd/cudd/cuddBddAbs.c new file mode 100644 index 00000000..9552464e --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddBddAbs.c @@ -0,0 +1,689 @@ +/**CFile*********************************************************************** + + FileName [cuddBddAbs.c] + + PackageName [cudd] + + Synopsis [Quantification functions for BDDs.] + + Description [External procedures included in this module: +
    +
  • Cudd_bddExistAbstract() +
  • Cudd_bddXorExistAbstract() +
  • Cudd_bddUnivAbstract() +
  • Cudd_bddBooleanDiff() +
  • Cudd_bddVarIsDependent() +
+ Internal procedures included in this module: +
    +
  • cuddBddExistAbstractRecur() +
  • cuddBddXorExistAbstractRecur() +
  • cuddBddBooleanDiffRecur() +
+ Static procedures included in this module: +
    +
  • bddCheckPositiveCube() +
+ ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddBddAbs.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int bddCheckPositiveCube ARGS((DdManager *manager, DdNode *cube)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Existentially abstracts all the variables in cube from f.] + + Description [Existentially abstracts all the variables in cube from f. + Returns the abstracted BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddUnivAbstract Cudd_addExistAbstract] + +******************************************************************************/ +DdNode * +Cudd_bddExistAbstract( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *res; + + if (bddCheckPositiveCube(manager, cube) == 0) { + (void) fprintf(manager->err, + "Error: Can only abstract positive cubes\n"); + manager->errorCode = CUDD_INVALID_ARG; + return(NULL); + } + + do { + manager->reordered = 0; + res = cuddBddExistAbstractRecur(manager, f, cube); + } while (manager->reordered == 1); + + return(res); + +} /* end of Cudd_bddExistAbstract */ + + +/**Function******************************************************************** + + Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the + variables in cube.] + + Description [Takes the exclusive OR of two BDDs and simultaneously abstracts + the variables in cube. The variables are existentially abstracted. Returns a + pointer to the result is successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddUnivAbstract Cudd_bddExistAbstract Cudd_bddAndAbstract] + +******************************************************************************/ +DdNode * +Cudd_bddXorExistAbstract( + DdManager * manager, + DdNode * f, + DdNode * g, + DdNode * cube) +{ + DdNode *res; + + if (bddCheckPositiveCube(manager, cube) == 0) { + (void) fprintf(manager->err, + "Error: Can only abstract positive cubes\n"); + manager->errorCode = CUDD_INVALID_ARG; + return(NULL); + } + + do { + manager->reordered = 0; + res = cuddBddXorExistAbstractRecur(manager, f, g, cube); + } while (manager->reordered == 1); + + return(res); + +} /* end of Cudd_bddXorExistAbstract */ + + +/**Function******************************************************************** + + Synopsis [Universally abstracts all the variables in cube from f.] + + Description [Universally abstracts all the variables in cube from f. + Returns the abstracted BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddExistAbstract Cudd_addUnivAbstract] + +******************************************************************************/ +DdNode * +Cudd_bddUnivAbstract( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *res; + + if (bddCheckPositiveCube(manager, cube) == 0) { + (void) fprintf(manager->err, + "Error: Can only abstract positive cubes\n"); + manager->errorCode = CUDD_INVALID_ARG; + return(NULL); + } + + do { + manager->reordered = 0; + res = cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube); + } while (manager->reordered == 1); + if (res != NULL) res = Cudd_Not(res); + + return(res); + +} /* end of Cudd_bddUnivAbstract */ + + +/**Function******************************************************************** + + Synopsis [Computes the boolean difference of f with respect to x.] + + Description [Computes the boolean difference of f with respect to the + variable with index x. Returns the BDD of the boolean difference if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_bddBooleanDiff( + DdManager * manager, + DdNode * f, + int x) +{ + DdNode *res, *var; + + /* If the variable is not currently in the manager, f cannot + ** depend on it. + */ + if (x >= manager->size) return(Cudd_Not(DD_ONE(manager))); + var = manager->vars[x]; + + do { + manager->reordered = 0; + res = cuddBddBooleanDiffRecur(manager, Cudd_Regular(f), var); + } while (manager->reordered == 1); + + return(res); + +} /* end of Cudd_bddBooleanDiff */ + + +/**Function******************************************************************** + + Synopsis [Checks whether a variable is dependent on others in a + function.] + + Description [Checks whether a variable is dependent on others in a + function. Returns 1 if the variable is dependent; 0 otherwise. No + new nodes are created.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_bddVarIsDependent( + DdManager *dd, /* manager */ + DdNode *f, /* function */ + DdNode *var /* variable */) +{ + DdNode *F, *res, *zero, *ft, *fe; + unsigned topf, level; + DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); + int retval; + + zero = Cudd_Not(DD_ONE(dd)); + if (Cudd_IsConstant(f)) return(f == zero); + + /* From now on f is not constant. */ + F = Cudd_Regular(f); + topf = (unsigned) dd->perm[F->index]; + level = (unsigned) dd->perm[var->index]; + + /* Check terminal case. If topf > index of var, f does not depend on var. + ** Therefore, var is not dependent in f. */ + if (topf > level) { + return(0); + } + + cacheOp = + (DdNode *(*)(DdManager *, DdNode *, DdNode *)) Cudd_bddVarIsDependent; + res = cuddCacheLookup2(dd,cacheOp,f,var); + if (res != NULL) { + return(res != zero); + } + + /* Compute cofactors. */ + ft = Cudd_NotCond(cuddT(F), f != F); + fe = Cudd_NotCond(cuddE(F), f != F); + + if (topf == level) { + retval = Cudd_bddLeq(dd,ft,Cudd_Not(fe)); + } else { + retval = Cudd_bddVarIsDependent(dd,ft,var) && + Cudd_bddVarIsDependent(dd,fe,var); + } + + cuddCacheInsert2(dd,cacheOp,f,var,Cudd_NotCond(zero,retval)); + + return(retval); + +} /* Cudd_bddVarIsDependent */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive steps of Cudd_bddExistAbstract.] + + Description [Performs the recursive steps of Cudd_bddExistAbstract. + Returns the BDD obtained by abstracting the variables + of cube from f if successful; NULL otherwise. It is also used by + Cudd_bddUnivAbstract.] + + SideEffects [None] + + SeeAlso [Cudd_bddExistAbstract Cudd_bddUnivAbstract] + +******************************************************************************/ +DdNode * +cuddBddExistAbstractRecur( + DdManager * manager, + DdNode * f, + DdNode * cube) +{ + DdNode *F, *T, *E, *res, *res1, *res2, *one; + + statLine(manager); + one = DD_ONE(manager); + F = Cudd_Regular(f); + + /* Cube is guaranteed to be a cube at this point. */ + if (cube == one || F == one) { + return(f); + } + /* From now on, f and cube are non-constant. */ + + /* Abstract a variable that does not appear in f. */ + while (manager->perm[F->index] > manager->perm[cube->index]) { + cube = cuddT(cube); + if (cube == one) return(f); + } + + /* Check the cache. */ + if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) { + return(res); + } + + /* Compute the cofactors of f. */ + T = cuddT(F); E = cuddE(F); + if (f != F) { + T = Cudd_Not(T); E = Cudd_Not(E); + } + + /* If the two indices are the same, so are their levels. */ + if (F->index == cube->index) { + if (T == one || E == one || T == Cudd_Not(E)) { + return(one); + } + res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube)); + if (res1 == NULL) return(NULL); + if (res1 == one) { + if (F->ref != 1) + cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one); + return(one); + } + cuddRef(res1); + res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube)); + if (res2 == NULL) { + Cudd_IterDerefBdd(manager,res1); + return(NULL); + } + cuddRef(res2); + res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2)); + if (res == NULL) { + Cudd_IterDerefBdd(manager, res1); + Cudd_IterDerefBdd(manager, res2); + return(NULL); + } + res = Cudd_Not(res); + cuddRef(res); + Cudd_IterDerefBdd(manager, res1); + Cudd_IterDerefBdd(manager, res2); + if (F->ref != 1) + cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); + cuddDeref(res); + return(res); + } else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */ + res1 = cuddBddExistAbstractRecur(manager, T, cube); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddBddExistAbstractRecur(manager, E, cube); + if (res2 == NULL) { + Cudd_IterDerefBdd(manager, res1); + return(NULL); + } + cuddRef(res2); + /* ITE takes care of possible complementation of res1 and of the + ** case in which res1 == res2. */ + res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2); + if (res == NULL) { + Cudd_IterDerefBdd(manager, res1); + Cudd_IterDerefBdd(manager, res2); + return(NULL); + } + cuddDeref(res1); + cuddDeref(res2); + if (F->ref != 1) + cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); + return(res); + } + +} /* end of cuddBddExistAbstractRecur */ + + +/**Function******************************************************************** + + Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the + variables in cube.] + + Description [Takes the exclusive OR of two BDDs and simultaneously abstracts + the variables in cube. The variables are existentially abstracted. Returns a + pointer to the result is successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddAndAbstract] + +******************************************************************************/ +DdNode * +cuddBddXorExistAbstractRecur( + DdManager * manager, + DdNode * f, + DdNode * g, + DdNode * cube) +{ + DdNode *F, *fv, *fnv, *G, *gv, *gnv; + DdNode *one, *zero, *r, *t, *e, *Cube; + unsigned int topf, topg, topcube, top, index; + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Terminal cases. */ + if (f == g) { + return(zero); + } + if (f == Cudd_Not(g)) { + return(one); + } + if (cube == one) { + return(cuddBddXorRecur(manager, f, g)); + } + if (f == one) { + return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube)); + } + if (g == one) { + return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube)); + } + if (f == zero) { + return(cuddBddExistAbstractRecur(manager, g, cube)); + } + if (g == zero) { + return(cuddBddExistAbstractRecur(manager, f, cube)); + } + + /* At this point f, g, and cube are not constant. */ + + if (f > g) { /* Try to increase cache efficiency. */ + DdNode *tmp = f; + f = g; + g = tmp; + } + + /* Check cache. */ + r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube); + if (r != NULL) { + return(r); + } + + /* Here we can skip the use of cuddI, because the operands are known + ** to be non-constant. + */ + F = Cudd_Regular(f); + topf = manager->perm[F->index]; + G = Cudd_Regular(g); + topg = manager->perm[G->index]; + top = ddMin(topf, topg); + topcube = manager->perm[cube->index]; + + if (topcube < top) { + return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube))); + } + /* Now, topcube >= top. */ + + if (topf == top) { + index = F->index; + fv = cuddT(F); + fnv = cuddE(F); + if (Cudd_IsComplement(f)) { + fv = Cudd_Not(fv); + fnv = Cudd_Not(fnv); + } + } else { + index = G->index; + fv = fnv = f; + } + + if (topg == top) { + gv = cuddT(G); + gnv = cuddE(G); + if (Cudd_IsComplement(g)) { + gv = Cudd_Not(gv); + gnv = Cudd_Not(gnv); + } + } else { + gv = gnv = g; + } + + if (topcube == top) { + Cube = cuddT(cube); + } else { + Cube = cube; + } + + t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube); + if (t == NULL) return(NULL); + + /* Special case: 1 OR anything = 1. Hence, no need to compute + ** the else branch if t is 1. + */ + if (t == one && topcube == top) { + cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one); + return(one); + } + cuddRef(t); + + e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube); + if (e == NULL) { + Cudd_IterDerefBdd(manager, t); + return(NULL); + } + cuddRef(e); + + if (topcube == top) { /* abstract */ + r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + cuddRef(r); + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + cuddDeref(r); + } else if (t == e) { + r = t; + cuddDeref(t); + cuddDeref(e); + } else { + if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(manager,(int)index,t,e); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + } + cuddDeref(e); + cuddDeref(t); + } + cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r); + return (r); + +} /* end of cuddBddXorExistAbstractRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive steps of Cudd_bddBoleanDiff.] + + Description [Performs the recursive steps of Cudd_bddBoleanDiff. + Returns the BDD obtained by XORing the cofactors of f with respect to + var if successful; NULL otherwise. Exploits the fact that dF/dx = + dF'/dx.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddBddBooleanDiffRecur( + DdManager * manager, + DdNode * f, + DdNode * var) +{ + DdNode *T, *E, *res, *res1, *res2; + + statLine(manager); + if (cuddI(manager,f->index) > manager->perm[var->index]) { + /* f does not depend on var. */ + return(Cudd_Not(DD_ONE(manager))); + } + + /* From now on, f is non-constant. */ + + /* If the two indices are the same, so are their levels. */ + if (f->index == var->index) { + res = cuddBddXorRecur(manager, cuddT(f), cuddE(f)); + return(res); + } + + /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */ + + /* Check the cache. */ + res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var); + if (res != NULL) { + return(res); + } + + /* Compute the cofactors of f. */ + T = cuddT(f); E = cuddE(f); + + res1 = cuddBddBooleanDiffRecur(manager, T, var); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var); + if (res2 == NULL) { + Cudd_IterDerefBdd(manager, res1); + return(NULL); + } + cuddRef(res2); + /* ITE takes care of possible complementation of res1 and of the + ** case in which res1 == res2. */ + res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2); + if (res == NULL) { + Cudd_IterDerefBdd(manager, res1); + Cudd_IterDerefBdd(manager, res2); + return(NULL); + } + cuddDeref(res1); + cuddDeref(res2); + cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res); + return(res); + +} /* end of cuddBddBooleanDiffRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Checks whether cube is an BDD representing the product of + positive literals.] + + Description [Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +bddCheckPositiveCube( + DdManager * manager, + DdNode * cube) +{ + if (Cudd_IsComplement(cube)) return(0); + if (cube == DD_ONE(manager)) return(1); + if (cuddIsConstant(cube)) return(0); + if (cuddE(cube) == Cudd_Not(DD_ONE(manager))) { + return(bddCheckPositiveCube(manager, cuddT(cube))); + } + return(0); + +} /* end of bddCheckPositiveCube */ + diff --git a/abc70930/src/bdd/cudd/cuddBddCorr.c b/abc70930/src/bdd/cudd/cuddBddCorr.c new file mode 100644 index 00000000..c99324a8 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddBddCorr.c @@ -0,0 +1,481 @@ +/**CFile*********************************************************************** + + FileName [cuddBddCorr.c] + + PackageName [cudd] + + Synopsis [Correlation between BDDs.] + + Description [External procedures included in this module: +
    +
  • Cudd_bddCorrelation() +
  • Cudd_bddCorrelationWeights() +
+ Static procedures included in this module: +
    +
  • bddCorrelationAux() +
  • bddCorrelationWeightsAux() +
  • CorrelCompare() +
  • CorrelHash() +
  • CorrelCleanUp() +
+ ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +typedef struct hashEntry { + DdNode *f; + DdNode *g; +} HashEntry; + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddBddCorr.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +#ifdef CORREL_STATS +static int num_calls; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static double bddCorrelationAux ARGS((DdManager *dd, DdNode *f, DdNode *g, st_table *table)); +static double bddCorrelationWeightsAux ARGS((DdManager *dd, DdNode *f, DdNode *g, double *prob, st_table *table)); +static int CorrelCompare ARGS((const char *key1, const char *key2)); +static int CorrelHash ARGS((char *key, int modulus)); +static enum st_retval CorrelCleanUp ARGS((char *key, char *value, char *arg)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes the correlation of f and g.] + + Description [Computes the correlation of f and g. If f == g, their + correlation is 1. If f == g', their correlation is 0. Returns the + fraction of minterms in the ON-set of the EXNOR of f and g. If it + runs out of memory, returns (double)CUDD_OUT_OF_MEM.] + + SideEffects [None] + + SeeAlso [Cudd_bddCorrelationWeights] + +******************************************************************************/ +double +Cudd_bddCorrelation( + DdManager * manager, + DdNode * f, + DdNode * g) +{ + + st_table *table; + double correlation; + +#ifdef CORREL_STATS + num_calls = 0; +#endif + + table = st_init_table(CorrelCompare,CorrelHash); + if (table == NULL) return((double)CUDD_OUT_OF_MEM); + correlation = bddCorrelationAux(manager,f,g,table); + st_foreach(table, CorrelCleanUp, NIL(char)); + st_free_table(table); + return(correlation); + +} /* end of Cudd_bddCorrelation */ + + +/**Function******************************************************************** + + Synopsis [Computes the correlation of f and g for given input + probabilities.] + + Description [Computes the correlation of f and g for given input + probabilities. On input, prob\[i\] is supposed to contain the + probability of the i-th input variable to be 1. + If f == g, their correlation is 1. If f == g', their + correlation is 0. Returns the probability that f and g have the same + value. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM. The + correlation of f and the constant one gives the probability of f.] + + SideEffects [None] + + SeeAlso [Cudd_bddCorrelation] + +******************************************************************************/ +double +Cudd_bddCorrelationWeights( + DdManager * manager, + DdNode * f, + DdNode * g, + double * prob) +{ + + st_table *table; + double correlation; + +#ifdef CORREL_STATS + num_calls = 0; +#endif + + table = st_init_table(CorrelCompare,CorrelHash); + if (table == NULL) return((double)CUDD_OUT_OF_MEM); + correlation = bddCorrelationWeightsAux(manager,f,g,prob,table); + st_foreach(table, CorrelCleanUp, NIL(char)); + st_free_table(table); + return(correlation); + +} /* end of Cudd_bddCorrelationWeights */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddCorrelation.] + + Description [Performs the recursive step of Cudd_bddCorrelation. + Returns the fraction of minterms in the ON-set of the EXNOR of f and + g.] + + SideEffects [None] + + SeeAlso [bddCorrelationWeightsAux] + +******************************************************************************/ +static double +bddCorrelationAux( + DdManager * dd, + DdNode * f, + DdNode * g, + st_table * table) +{ + DdNode *Fv, *Fnv, *G, *Gv, *Gnv; + double min, *pmin, min1, min2, *dummy; + HashEntry *entry; + unsigned int topF, topG; + + statLine(dd); +#ifdef CORREL_STATS + num_calls++; +#endif + + /* Terminal cases: only work for BDDs. */ + if (f == g) return(1.0); + if (f == Cudd_Not(g)) return(0.0); + + /* Standardize call using the following properties: + ** (f EXNOR g) = (g EXNOR f) + ** (f' EXNOR g') = (f EXNOR g). + */ + if (f > g) { + DdNode *tmp = f; + f = g; g = tmp; + } + if (Cudd_IsComplement(f)) { + f = Cudd_Not(f); + g = Cudd_Not(g); + } + /* From now on, f is regular. */ + + entry = ALLOC(HashEntry,1); + if (entry == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(CUDD_OUT_OF_MEM); + } + entry->f = f; entry->g = g; + + /* We do not use the fact that + ** correlation(f,g') = 1 - correlation(f,g) + ** to minimize the risk of cancellation. + */ + if (st_lookup(table, (char *)entry, (char **)&dummy)) { + min = *dummy; + FREE(entry); + return(min); + } + + G = Cudd_Regular(g); + topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); + if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } + if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } + + if (g != G) { + Gv = Cudd_Not(Gv); + Gnv = Cudd_Not(Gnv); + } + + min1 = bddCorrelationAux(dd, Fv, Gv, table) / 2.0; + if (min1 == (double)CUDD_OUT_OF_MEM) { + FREE(entry); + return(CUDD_OUT_OF_MEM); + } + min2 = bddCorrelationAux(dd, Fnv, Gnv, table) / 2.0; + if (min2 == (double)CUDD_OUT_OF_MEM) { + FREE(entry); + return(CUDD_OUT_OF_MEM); + } + min = (min1+min2); + + pmin = ALLOC(double,1); + if (pmin == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return((double)CUDD_OUT_OF_MEM); + } + *pmin = min; + + if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) { + FREE(entry); + FREE(pmin); + return((double)CUDD_OUT_OF_MEM); + } + return(min); + +} /* end of bddCorrelationAux */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddCorrelationWeigths.] + + Description [] + + SideEffects [None] + + SeeAlso [bddCorrelationAux] + +******************************************************************************/ +static double +bddCorrelationWeightsAux( + DdManager * dd, + DdNode * f, + DdNode * g, + double * prob, + st_table * table) +{ + DdNode *Fv, *Fnv, *G, *Gv, *Gnv; + double min, *pmin, min1, min2, *dummy; + HashEntry *entry; + int topF, topG, index; + + statLine(dd); +#ifdef CORREL_STATS + num_calls++; +#endif + + /* Terminal cases: only work for BDDs. */ + if (f == g) return(1.0); + if (f == Cudd_Not(g)) return(0.0); + + /* Standardize call using the following properties: + ** (f EXNOR g) = (g EXNOR f) + ** (f' EXNOR g') = (f EXNOR g). + */ + if (f > g) { + DdNode *tmp = f; + f = g; g = tmp; + } + if (Cudd_IsComplement(f)) { + f = Cudd_Not(f); + g = Cudd_Not(g); + } + /* From now on, f is regular. */ + + entry = ALLOC(HashEntry,1); + if (entry == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return((double)CUDD_OUT_OF_MEM); + } + entry->f = f; entry->g = g; + + /* We do not use the fact that + ** correlation(f,g') = 1 - correlation(f,g) + ** to minimize the risk of cancellation. + */ + if (st_lookup(table, (char *)entry, (char **)&dummy)) { + min = *dummy; + FREE(entry); + return(min); + } + + G = Cudd_Regular(g); + topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); + if (topF <= topG) { + Fv = cuddT(f); Fnv = cuddE(f); + index = f->index; + } else { + Fv = Fnv = f; + index = G->index; + } + if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } + + if (g != G) { + Gv = Cudd_Not(Gv); + Gnv = Cudd_Not(Gnv); + } + + min1 = bddCorrelationWeightsAux(dd, Fv, Gv, prob, table) * prob[index]; + if (min1 == (double)CUDD_OUT_OF_MEM) { + FREE(entry); + return((double)CUDD_OUT_OF_MEM); + } + min2 = bddCorrelationWeightsAux(dd, Fnv, Gnv, prob, table) * (1.0 - prob[index]); + if (min2 == (double)CUDD_OUT_OF_MEM) { + FREE(entry); + return((double)CUDD_OUT_OF_MEM); + } + min = (min1+min2); + + pmin = ALLOC(double,1); + if (pmin == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return((double)CUDD_OUT_OF_MEM); + } + *pmin = min; + + if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) { + FREE(entry); + FREE(pmin); + return((double)CUDD_OUT_OF_MEM); + } + return(min); + +} /* end of bddCorrelationWeightsAux */ + + +/**Function******************************************************************** + + Synopsis [Compares two hash table entries.] + + Description [Compares two hash table entries. Returns 0 if they are + identical; 1 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +CorrelCompare( + const char * key1, + const char * key2) +{ + HashEntry *entry1; + HashEntry *entry2; + + entry1 = (HashEntry *) key1; + entry2 = (HashEntry *) key2; + if (entry1->f != entry2->f || entry1->g != entry2->g) return(1); + + return(0); + +} /* end of CorrelCompare */ + + +/**Function******************************************************************** + + Synopsis [Hashes a hash table entry.] + + Description [Hashes a hash table entry. It is patterned after + st_strhash. Returns a value between 0 and modulus.] + + SideEffects [None] + +******************************************************************************/ +static int +CorrelHash( + char * key, + int modulus) +{ + HashEntry *entry; + int val = 0; + + entry = (HashEntry *) key; +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 + val = ((int) ((long)entry->f))*997 + ((int) ((long)entry->g)); +#else + val = ((int) entry->f)*997 + ((int) entry->g); +#endif + + return ((val < 0) ? -val : val) % modulus; + +} /* end of CorrelHash */ + + +/**Function******************************************************************** + + Synopsis [Frees memory associated with hash table.] + + Description [Frees memory associated with hash table. Returns + ST_CONTINUE.] + + SideEffects [None] + +******************************************************************************/ +static enum st_retval +CorrelCleanUp( + char * key, + char * value, + char * arg) +{ + double *d; + HashEntry *entry; + + entry = (HashEntry *) key; + FREE(entry); + d = (double *)value; + FREE(d); + return ST_CONTINUE; + +} /* end of CorrelCleanUp */ + diff --git a/abc70930/src/bdd/cudd/cuddBddIte.c b/abc70930/src/bdd/cudd/cuddBddIte.c new file mode 100644 index 00000000..b44e40de --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddBddIte.c @@ -0,0 +1,1254 @@ +/**CFile*********************************************************************** + + FileName [cuddBddIte.c] + + PackageName [cudd] + + Synopsis [BDD ITE function and satellites.] + + Description [External procedures included in this module: +
    +
  • Cudd_bddIte() +
  • Cudd_bddIteConstant() +
  • Cudd_bddIntersect() +
  • Cudd_bddAnd() +
  • Cudd_bddOr() +
  • Cudd_bddNand() +
  • Cudd_bddNor() +
  • Cudd_bddXor() +
  • Cudd_bddXnor() +
  • Cudd_bddLeq() +
+ Internal procedures included in this module: +
    +
  • cuddBddIteRecur() +
  • cuddBddIntersectRecur() +
  • cuddBddAndRecur() +
  • cuddBddXorRecur() +
+ Static procedures included in this module: +
    +
  • bddVarToConst() +
  • bddVarToCanonical() +
  • bddVarToCanonicalSimple() +
] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddBddIte.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void bddVarToConst ARGS((DdNode *f, DdNode **gp, DdNode **hp, DdNode *one)); +static int bddVarToCanonical ARGS((DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp)); +static int bddVarToCanonicalSimple ARGS((DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements ITE(f,g,h).] + + Description [Implements ITE(f,g,h). Returns a pointer to the + resulting BDD if successful; NULL if the intermediate result blows + up.] + + SideEffects [None] + + SeeAlso [Cudd_addIte Cudd_bddIteConstant Cudd_bddIntersect] + +******************************************************************************/ +DdNode * +Cudd_bddIte( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddIteRecur(dd,f,g,h); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddIte */ + + +/**Function******************************************************************** + + Synopsis [Implements ITEconstant(f,g,h).] + + Description [Implements ITEconstant(f,g,h). Returns a pointer to the + resulting BDD (which may or may not be constant) or DD_NON_CONSTANT. + No new nodes are created.] + + SideEffects [None] + + SeeAlso [Cudd_bddIte Cudd_bddIntersect Cudd_bddLeq Cudd_addIteConstant] + +******************************************************************************/ +DdNode * +Cudd_bddIteConstant( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h) +{ + DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e; + DdNode *one = DD_ONE(dd); + DdNode *zero = Cudd_Not(one); + int comple; + unsigned int topf, topg, toph, v; + + statLine(dd); + /* Trivial cases. */ + if (f == one) /* ITE(1,G,H) => G */ + return(g); + + if (f == zero) /* ITE(0,G,H) => H */ + return(h); + + /* f now not a constant. */ + bddVarToConst(f, &g, &h, one); /* possibly convert g or h */ + /* to constants */ + + if (g == h) /* ITE(F,G,G) => G */ + return(g); + + if (Cudd_IsConstant(g) && Cudd_IsConstant(h)) + return(DD_NON_CONSTANT); /* ITE(F,1,0) or ITE(F,0,1) */ + /* => DD_NON_CONSTANT */ + + if (g == Cudd_Not(h)) + return(DD_NON_CONSTANT); /* ITE(F,G,G') => DD_NON_CONSTANT */ + /* if F != G and F != G' */ + + comple = bddVarToCanonical(dd, &f, &g, &h, &topf, &topg, &toph); + + /* Cache lookup. */ + r = cuddConstantLookup(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h); + if (r != NULL) { + return(Cudd_NotCond(r,comple && r != DD_NON_CONSTANT)); + } + + v = ddMin(topg, toph); + + /* ITE(F,G,H) = (v,G,H) (non constant) if F = (v,1,0), v < top(G,H). */ + if (topf < v && cuddT(f) == one && cuddE(f) == zero) { + return(DD_NON_CONSTANT); + } + + /* Compute cofactors. */ + if (topf <= v) { + v = ddMin(topf, v); /* v = top_var(F,G,H) */ + Fv = cuddT(f); Fnv = cuddE(f); + } else { + Fv = Fnv = f; + } + + if (topg == v) { + Gv = cuddT(g); Gnv = cuddE(g); + } else { + Gv = Gnv = g; + } + + if (toph == v) { + H = Cudd_Regular(h); + Hv = cuddT(H); Hnv = cuddE(H); + if (Cudd_IsComplement(h)) { + Hv = Cudd_Not(Hv); + Hnv = Cudd_Not(Hnv); + } + } else { + Hv = Hnv = h; + } + + /* Recursion. */ + t = Cudd_bddIteConstant(dd, Fv, Gv, Hv); + if (t == DD_NON_CONSTANT || !Cudd_IsConstant(t)) { + cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); + return(DD_NON_CONSTANT); + } + e = Cudd_bddIteConstant(dd, Fnv, Gnv, Hnv); + if (e == DD_NON_CONSTANT || !Cudd_IsConstant(e) || t != e) { + cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); + return(DD_NON_CONSTANT); + } + cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, t); + return(Cudd_NotCond(t,comple)); + +} /* end of Cudd_bddIteConstant */ + + +/**Function******************************************************************** + + Synopsis [Returns a function included in the intersection of f and g.] + + Description [Computes a function included in the intersection of f and + g. (That is, a witness that the intersection is not empty.) + Cudd_bddIntersect tries to build as few new nodes as possible. If the + only result of interest is whether f and g intersect, + Cudd_bddLeq should be used instead.] + + SideEffects [None] + + SeeAlso [Cudd_bddLeq Cudd_bddIteConstant] + +******************************************************************************/ +DdNode * +Cudd_bddIntersect( + DdManager * dd /* manager */, + DdNode * f /* first operand */, + DdNode * g /* second operand */) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddIntersectRecur(dd,f,g); + } while (dd->reordered == 1); + + return(res); + +} /* end of Cudd_bddIntersect */ + + +/**Function******************************************************************** + + Synopsis [Computes the conjunction of two BDDs f and g.] + + Description [Computes the conjunction of two BDDs f and g. Returns a + pointer to the resulting BDD if successful; NULL if the intermediate + result blows up.] + + SideEffects [None] + + SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect + Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor] + +******************************************************************************/ +DdNode * +Cudd_bddAnd( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddAndRecur(dd,f,g); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddAnd */ + + +/**Function******************************************************************** + + Synopsis [Computes the disjunction of two BDDs f and g.] + + Description [Computes the disjunction of two BDDs f and g. Returns a + pointer to the resulting BDD if successful; NULL if the intermediate + result blows up.] + + SideEffects [None] + + SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddNand Cudd_bddNor + Cudd_bddXor Cudd_bddXnor] + +******************************************************************************/ +DdNode * +Cudd_bddOr( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g)); + } while (dd->reordered == 1); + res = Cudd_NotCond(res,res != NULL); + return(res); + +} /* end of Cudd_bddOr */ + + +/**Function******************************************************************** + + Synopsis [Computes the NAND of two BDDs f and g.] + + Description [Computes the NAND of two BDDs f and g. Returns a + pointer to the resulting BDD if successful; NULL if the intermediate + result blows up.] + + SideEffects [None] + + SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNor + Cudd_bddXor Cudd_bddXnor] + +******************************************************************************/ +DdNode * +Cudd_bddNand( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddAndRecur(dd,f,g); + } while (dd->reordered == 1); + res = Cudd_NotCond(res,res != NULL); + return(res); + +} /* end of Cudd_bddNand */ + + +/**Function******************************************************************** + + Synopsis [Computes the NOR of two BDDs f and g.] + + Description [Computes the NOR of two BDDs f and g. Returns a + pointer to the resulting BDD if successful; NULL if the intermediate + result blows up.] + + SideEffects [None] + + SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNand + Cudd_bddXor Cudd_bddXnor] + +******************************************************************************/ +DdNode * +Cudd_bddNor( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g)); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddNor */ + + +/**Function******************************************************************** + + Synopsis [Computes the exclusive OR of two BDDs f and g.] + + Description [Computes the exclusive OR of two BDDs f and g. Returns a + pointer to the resulting BDD if successful; NULL if the intermediate + result blows up.] + + SideEffects [None] + + SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr + Cudd_bddNand Cudd_bddNor Cudd_bddXnor] + +******************************************************************************/ +DdNode * +Cudd_bddXor( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddXorRecur(dd,f,g); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddXor */ + + +/**Function******************************************************************** + + Synopsis [Computes the exclusive NOR of two BDDs f and g.] + + Description [Computes the exclusive NOR of two BDDs f and g. Returns a + pointer to the resulting BDD if successful; NULL if the intermediate + result blows up.] + + SideEffects [None] + + SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr + Cudd_bddNand Cudd_bddNor Cudd_bddXor] + +******************************************************************************/ +DdNode * +Cudd_bddXnor( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddXorRecur(dd,f,Cudd_Not(g)); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddXnor */ + + +/**Function******************************************************************** + + Synopsis [Determines whether f is less than or equal to g.] + + Description [Returns 1 if f is less than or equal to g; 0 otherwise. + No new nodes are created.] + + SideEffects [None] + + SeeAlso [Cudd_bddIteConstant Cudd_addEvalConst] + +******************************************************************************/ +int +Cudd_bddLeq( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *one, *zero, *tmp, *F, *fv, *fvn, *gv, *gvn; + unsigned int topf, topg, res; + + statLine(dd); + /* Terminal cases and normalization. */ + if (f == g) return(1); + + if (Cudd_IsComplement(g)) { + /* Special case: if f is regular and g is complemented, + ** f(1,...,1) = 1 > 0 = g(1,...,1). + */ + if (!Cudd_IsComplement(f)) return(0); + /* Both are complemented: Swap and complement because + ** f <= g <=> g' <= f' and we want the second argument to be regular. + */ + tmp = g; + g = Cudd_Not(f); + f = Cudd_Not(tmp); + } else if (Cudd_IsComplement(f) && g < f) { + tmp = g; + g = Cudd_Not(f); + f = Cudd_Not(tmp); + } + + /* Now g is regular and, if f is not regular, f < g. */ + one = DD_ONE(dd); + if (g == one) return(1); /* no need to test against zero */ + if (f == one) return(0); /* since at this point g != one */ + if (Cudd_Not(f) == g) return(0); /* because neither is constant */ + zero = Cudd_Not(one); + if (f == zero) return(1); + + /* Here neither f nor g is constant. */ + + /* Check cache. */ + tmp = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, + DdNode *))Cudd_bddLeq,f,g); + if (tmp != NULL) { + return(tmp == one); + } + + /* Compute cofactors. */ + F = Cudd_Regular(f); + topf = dd->perm[F->index]; + topg = dd->perm[g->index]; + if (topf <= topg) { + fv = cuddT(F); fvn = cuddE(F); + if (f != F) { + fv = Cudd_Not(fv); + fvn = Cudd_Not(fvn); + } + } else { + fv = fvn = f; + } + if (topg <= topf) { + gv = cuddT(g); gvn = cuddE(g); + } else { + gv = gvn = g; + } + + /* Recursive calls. Since we want to maximize the probability of + ** the special case f(1,...,1) > g(1,...,1), we consider the negative + ** cofactors first. Indeed, the complementation parity of the positive + ** cofactors is the same as the one of the parent functions. + */ + res = Cudd_bddLeq(dd,fvn,gvn) && Cudd_bddLeq(dd,fv,gv); + + /* Store result in cache and return. */ + cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_bddLeq,f,g,(res ? one : zero)); + return(res); + +} /* end of Cudd_bddLeq */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_bddIte.] + + Description [Implements the recursive step of Cudd_bddIte. Returns a + pointer to the resulting BDD. NULL if the intermediate result blows + up or if reordering occurs.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddBddIteRecur( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h) +{ + DdNode *one, *zero, *res; + DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e; + unsigned int topf, topg, toph, v; + int index; + int comple; + + statLine(dd); + /* Terminal cases. */ + + /* One variable cases. */ + if (f == (one = DD_ONE(dd))) /* ITE(1,G,H) = G */ + return(g); + + if (f == (zero = Cudd_Not(one))) /* ITE(0,G,H) = H */ + return(h); + + /* From now on, f is known not to be a constant. */ + if (g == one || f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ + if (h == zero) { /* ITE(F,1,0) = F */ + return(f); + } else { + res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h)); + return(Cudd_NotCond(res,res != NULL)); + } + } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */ + if (h == one) { /* ITE(F,0,1) = !F */ + return(Cudd_Not(f)); + } else { + res = cuddBddAndRecur(dd,Cudd_Not(f),h); + return(res); + } + } + if (h == zero || f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ + res = cuddBddAndRecur(dd,f,g); + return(res); + } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */ + res = cuddBddAndRecur(dd,f,Cudd_Not(g)); + return(Cudd_NotCond(res,res != NULL)); + } + + /* Check remaining one variable case. */ + if (g == h) { /* ITE(F,G,G) = G */ + return(g); + } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */ + res = cuddBddXorRecur(dd,f,h); + return(res); + } + + /* From here, there are no constants. */ + comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph); + + /* f & g are now regular pointers */ + + v = ddMin(topg, toph); + + /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */ + if (topf < v && cuddT(f) == one && cuddE(f) == zero) { + r = cuddUniqueInter(dd, (int) f->index, g, h); + return(Cudd_NotCond(r,comple && r != NULL)); + } + + /* Check cache. */ + r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h); + if (r != NULL) { + return(Cudd_NotCond(r,comple)); + } + + /* Compute cofactors. */ + if (topf <= v) { + v = ddMin(topf, v); /* v = top_var(F,G,H) */ + index = f->index; + Fv = cuddT(f); Fnv = cuddE(f); + } else { + Fv = Fnv = f; + } + if (topg == v) { + index = g->index; + Gv = cuddT(g); Gnv = cuddE(g); + } else { + Gv = Gnv = g; + } + if (toph == v) { + H = Cudd_Regular(h); + index = H->index; + Hv = cuddT(H); Hnv = cuddE(H); + if (Cudd_IsComplement(h)) { + Hv = Cudd_Not(Hv); + Hnv = Cudd_Not(Hnv); + } + } else { + Hv = Hnv = h; + } + + /* Recursive step. */ + t = cuddBddIteRecur(dd,Fv,Gv,Hv); + if (t == NULL) return(NULL); + cuddRef(t); + + e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv); + if (e == NULL) { + Cudd_IterDerefBdd(dd,t); + return(NULL); + } + cuddRef(e); + + r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); + if (r == NULL) { + Cudd_IterDerefBdd(dd,t); + Cudd_IterDerefBdd(dd,e); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + + cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r); + return(Cudd_NotCond(r,comple)); + +} /* end of cuddBddIteRecur */ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_bddIntersect.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_bddIntersect] + +******************************************************************************/ +DdNode * +cuddBddIntersectRecur( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + DdNode *F, *G, *t, *e; + DdNode *fv, *fnv, *gv, *gnv; + DdNode *one, *zero; + unsigned int index, topf, topg; + + statLine(dd); + one = DD_ONE(dd); + zero = Cudd_Not(one); + + /* Terminal cases. */ + if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); + if (f == g || g == one) return(f); + if (f == one) return(g); + + /* At this point f and g are not constant. */ + if (f > g) { DdNode *tmp = f; f = g; g = tmp; } + res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g); + if (res != NULL) return(res); + + /* Find splitting variable. Here we can skip the use of cuddI, + ** because the operands are known to be non-constant. + */ + F = Cudd_Regular(f); + topf = dd->perm[F->index]; + G = Cudd_Regular(g); + topg = dd->perm[G->index]; + + /* Compute cofactors. */ + if (topf <= topg) { + index = F->index; + fv = cuddT(F); + fnv = cuddE(F); + if (Cudd_IsComplement(f)) { + fv = Cudd_Not(fv); + fnv = Cudd_Not(fnv); + } + } else { + index = G->index; + fv = fnv = f; + } + + if (topg <= topf) { + gv = cuddT(G); + gnv = cuddE(G); + if (Cudd_IsComplement(g)) { + gv = Cudd_Not(gv); + gnv = Cudd_Not(gnv); + } + } else { + gv = gnv = g; + } + + /* Compute partial results. */ + t = cuddBddIntersectRecur(dd,fv,gv); + if (t == NULL) return(NULL); + cuddRef(t); + if (t != zero) { + e = zero; + } else { + e = cuddBddIntersectRecur(dd,fnv,gnv); + if (e == NULL) { + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + } + cuddRef(e); + + if (t == e) { /* both equal zero */ + res = t; + } else if (Cudd_IsComplement(t)) { + res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e)); + if (res == NULL) { + Cudd_IterDerefBdd(dd, t); + Cudd_IterDerefBdd(dd, e); + return(NULL); + } + res = Cudd_Not(res); + } else { + res = cuddUniqueInter(dd,(int)index,t,e); + if (res == NULL) { + Cudd_IterDerefBdd(dd, t); + Cudd_IterDerefBdd(dd, e); + return(NULL); + } + } + cuddDeref(e); + cuddDeref(t); + + cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res); + + return(res); + +} /* end of cuddBddIntersectRecur */ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_bddAnd.] + + Description [Implements the recursive step of Cudd_bddAnd by taking + the conjunction of two BDDs. Returns a pointer to the result is + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddAnd] + +******************************************************************************/ +DdNode * +cuddBddAndRecur( + DdManager * manager, + DdNode * f, + DdNode * g) +{ + DdNode *F, *fv, *fnv, *G, *gv, *gnv; + DdNode *one, *r, *t, *e; + unsigned int topf, topg, index; + + statLine(manager); + one = DD_ONE(manager); + + /* Terminal cases. */ + F = Cudd_Regular(f); + G = Cudd_Regular(g); + if (F == G) { + if (f == g) return(f); + else return(Cudd_Not(one)); + } + if (F == one) { + if (f == one) return(g); + else return(f); + } + if (G == one) { + if (g == one) return(f); + else return(g); + } + + /* At this point f and g are not constant. */ + if (f > g) { /* Try to increase cache efficiency. */ + DdNode *tmp = f; + f = g; + g = tmp; + F = Cudd_Regular(f); + G = Cudd_Regular(g); + } + + /* Check cache. */ + if (F->ref != 1 || G->ref != 1) { + r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g); + if (r != NULL) return(r); + } + + /* Here we can skip the use of cuddI, because the operands are known + ** to be non-constant. + */ + topf = manager->perm[F->index]; + topg = manager->perm[G->index]; + + /* Compute cofactors. */ + if (topf <= topg) { + index = F->index; + fv = cuddT(F); + fnv = cuddE(F); + if (Cudd_IsComplement(f)) { + fv = Cudd_Not(fv); + fnv = Cudd_Not(fnv); + } + } else { + index = G->index; + fv = fnv = f; + } + + if (topg <= topf) { + gv = cuddT(G); + gnv = cuddE(G); + if (Cudd_IsComplement(g)) { + gv = Cudd_Not(gv); + gnv = Cudd_Not(gnv); + } + } else { + gv = gnv = g; + } + + t = cuddBddAndRecur(manager, fv, gv); + if (t == NULL) return(NULL); + cuddRef(t); + + e = cuddBddAndRecur(manager, fnv, gnv); + if (e == NULL) { + Cudd_IterDerefBdd(manager, t); + return(NULL); + } + cuddRef(e); + + if (t == e) { + r = t; + } else { + if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(manager,(int)index,t,e); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + } + } + cuddDeref(e); + cuddDeref(t); + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r); + return(r); + +} /* end of cuddBddAndRecur */ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_bddXor.] + + Description [Implements the recursive step of Cudd_bddXor by taking + the exclusive OR of two BDDs. Returns a pointer to the result is + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddXor] + +******************************************************************************/ +DdNode * +cuddBddXorRecur( + DdManager * manager, + DdNode * f, + DdNode * g) +{ + DdNode *fv, *fnv, *G, *gv, *gnv; + DdNode *one, *zero, *r, *t, *e; + unsigned int topf, topg, index; + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Terminal cases. */ + if (f == g) return(zero); + if (f == Cudd_Not(g)) return(one); + if (f > g) { /* Try to increase cache efficiency and simplify tests. */ + DdNode *tmp = f; + f = g; + g = tmp; + } + if (g == zero) return(f); + if (g == one) return(Cudd_Not(f)); + if (Cudd_IsComplement(f)) { + f = Cudd_Not(f); + g = Cudd_Not(g); + } + /* Now the first argument is regular. */ + if (f == one) return(Cudd_Not(g)); + + /* At this point f and g are not constant. */ + + /* Check cache. */ + r = cuddCacheLookup2(manager, Cudd_bddXor, f, g); + if (r != NULL) return(r); + + /* Here we can skip the use of cuddI, because the operands are known + ** to be non-constant. + */ + topf = manager->perm[f->index]; + G = Cudd_Regular(g); + topg = manager->perm[G->index]; + + /* Compute cofactors. */ + if (topf <= topg) { + index = f->index; + fv = cuddT(f); + fnv = cuddE(f); + } else { + index = G->index; + fv = fnv = f; + } + + if (topg <= topf) { + gv = cuddT(G); + gnv = cuddE(G); + if (Cudd_IsComplement(g)) { + gv = Cudd_Not(gv); + gnv = Cudd_Not(gnv); + } + } else { + gv = gnv = g; + } + + t = cuddBddXorRecur(manager, fv, gv); + if (t == NULL) return(NULL); + cuddRef(t); + + e = cuddBddXorRecur(manager, fnv, gnv); + if (e == NULL) { + Cudd_IterDerefBdd(manager, t); + return(NULL); + } + cuddRef(e); + + if (t == e) { + r = t; + } else { + if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(manager,(int)index,t,e); + if (r == NULL) { + Cudd_IterDerefBdd(manager, t); + Cudd_IterDerefBdd(manager, e); + return(NULL); + } + } + } + cuddDeref(e); + cuddDeref(t); + cuddCacheInsert2(manager, Cudd_bddXor, f, g, r); + return(r); + +} /* end of cuddBddXorRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Replaces variables with constants if possible.] + + Description [This function performs part of the transformation to + standard form by replacing variables with constants if possible.] + + SideEffects [None] + + SeeAlso [bddVarToCanonical bddVarToCanonicalSimple] + +******************************************************************************/ +static void +bddVarToConst( + DdNode * f, + DdNode ** gp, + DdNode ** hp, + DdNode * one) +{ + DdNode *g = *gp; + DdNode *h = *hp; + + if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ + *gp = one; + } else if (f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */ + *gp = Cudd_Not(one); + } + if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ + *hp = Cudd_Not(one); + } else if (f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */ + *hp = one; + } + +} /* end of bddVarToConst */ + + +/**Function******************************************************************** + + Synopsis [Picks unique member from equiv expressions.] + + Description [Reduces 2 variable expressions to canonical form.] + + SideEffects [None] + + SeeAlso [bddVarToConst bddVarToCanonicalSimple] + +******************************************************************************/ +static int +bddVarToCanonical( + DdManager * dd, + DdNode ** fp, + DdNode ** gp, + DdNode ** hp, + unsigned int * topfp, + unsigned int * topgp, + unsigned int * tophp) +{ + register DdNode *F, *G, *H, *r, *f, *g, *h; + register unsigned int topf, topg, toph; + DdNode *one = dd->one; + int comple, change; + + f = *fp; + g = *gp; + h = *hp; + F = Cudd_Regular(f); + G = Cudd_Regular(g); + H = Cudd_Regular(h); + topf = cuddI(dd,F->index); + topg = cuddI(dd,G->index); + toph = cuddI(dd,H->index); + + change = 0; + + if (G == one) { /* ITE(F,c,H) */ + if ((topf > toph) || (topf == toph && f > h)) { + r = h; + h = f; + f = r; /* ITE(F,1,H) = ITE(H,1,F) */ + if (g != one) { /* g == zero */ + f = Cudd_Not(f); /* ITE(F,0,H) = ITE(!H,0,!F) */ + h = Cudd_Not(h); + } + change = 1; + } + } else if (H == one) { /* ITE(F,G,c) */ + if ((topf > topg) || (topf == topg && f > g)) { + r = g; + g = f; + f = r; /* ITE(F,G,0) = ITE(G,F,0) */ + if (h == one) { + f = Cudd_Not(f); /* ITE(F,G,1) = ITE(!G,!F,1) */ + g = Cudd_Not(g); + } + change = 1; + } + } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = ITE(G,F,!F) */ + if ((topf > topg) || (topf == topg && f > g)) { + r = f; + f = g; + g = r; + h = Cudd_Not(r); + change = 1; + } + } + /* adjust pointers so that the first 2 arguments to ITE are regular */ + if (Cudd_IsComplement(f) != 0) { /* ITE(!F,G,H) = ITE(F,H,G) */ + f = Cudd_Not(f); + r = g; + g = h; + h = r; + change = 1; + } + comple = 0; + if (Cudd_IsComplement(g) != 0) { /* ITE(F,!G,H) = !ITE(F,G,!H) */ + g = Cudd_Not(g); + h = Cudd_Not(h); + change = 1; + comple = 1; + } + if (change != 0) { + *fp = f; + *gp = g; + *hp = h; + } + *topfp = cuddI(dd,f->index); + *topgp = cuddI(dd,g->index); + *tophp = cuddI(dd,Cudd_Regular(h)->index); + + return(comple); + +} /* end of bddVarToCanonical */ + + +/**Function******************************************************************** + + Synopsis [Picks unique member from equiv expressions.] + + Description [Makes sure the first two pointers are regular. This + mat require the complementation of the result, which is signaled by + returning 1 instead of 0. This function is simpler than the general + case because it assumes that no two arguments are the same or + complementary, and no argument is constant.] + + SideEffects [None] + + SeeAlso [bddVarToConst bddVarToCanonical] + +******************************************************************************/ +static int +bddVarToCanonicalSimple( + DdManager * dd, + DdNode ** fp, + DdNode ** gp, + DdNode ** hp, + unsigned int * topfp, + unsigned int * topgp, + unsigned int * tophp) +{ + register DdNode *r, *f, *g, *h; + int comple, change; + + f = *fp; + g = *gp; + h = *hp; + + change = 0; + + /* adjust pointers so that the first 2 arguments to ITE are regular */ + if (Cudd_IsComplement(f)) { /* ITE(!F,G,H) = ITE(F,H,G) */ + f = Cudd_Not(f); + r = g; + g = h; + h = r; + change = 1; + } + comple = 0; + if (Cudd_IsComplement(g)) { /* ITE(F,!G,H) = !ITE(F,G,!H) */ + g = Cudd_Not(g); + h = Cudd_Not(h); + change = 1; + comple = 1; + } + if (change) { + *fp = f; + *gp = g; + *hp = h; + } + + /* Here we can skip the use of cuddI, because the operands are known + ** to be non-constant. + */ + *topfp = dd->perm[f->index]; + *topgp = dd->perm[g->index]; + *tophp = dd->perm[Cudd_Regular(h)->index]; + + return(comple); + +} /* end of bddVarToCanonicalSimple */ + diff --git a/abc70930/src/bdd/cudd/cuddBridge.c b/abc70930/src/bdd/cudd/cuddBridge.c new file mode 100644 index 00000000..ccc0893f --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddBridge.c @@ -0,0 +1,981 @@ +/**CFile*********************************************************************** + + FileName [cuddBridge.c] + + PackageName [cudd] + + Synopsis [Translation from BDD to ADD and vice versa and transfer between + different managers.] + + Description [External procedures included in this file: +
    +
  • Cudd_addBddThreshold() +
  • Cudd_addBddStrictThreshold() +
  • Cudd_addBddInterval() +
  • Cudd_addBddIthBit() +
  • Cudd_BddToAdd() +
  • Cudd_addBddPattern() +
  • Cudd_bddTransfer() +
+ Internal procedures included in this file: +
    +
  • cuddBddTransfer() +
  • cuddAddBddDoPattern() +
+ Static procedures included in this file: +
    +
  • addBddDoThreshold() +
  • addBddDoStrictThreshold() +
  • addBddDoInterval() +
  • addBddDoIthBit() +
  • ddBddToAddRecur() +
  • cuddBddTransferRecur() +
+ ] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddBridge.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * addBddDoThreshold ARGS((DdManager *dd, DdNode *f, DdNode *val)); +static DdNode * addBddDoStrictThreshold ARGS((DdManager *dd, DdNode *f, DdNode *val)); +static DdNode * addBddDoInterval ARGS((DdManager *dd, DdNode *f, DdNode *l, DdNode *u)); +static DdNode * addBddDoIthBit ARGS((DdManager *dd, DdNode *f, DdNode *index)); +static DdNode * ddBddToAddRecur ARGS((DdManager *dd, DdNode *B)); +static DdNode * cuddBddTransferRecur ARGS((DdManager *ddS, DdManager *ddD, DdNode *f, st_table *table)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Converts an ADD to a BDD.] + + Description [Converts an ADD to a BDD by replacing all + discriminants greater than or equal to value with 1, and all other + discriminants with 0. Returns a pointer to the resulting BDD if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd + Cudd_addBddStrictThreshold] + +******************************************************************************/ +DdNode * +Cudd_addBddThreshold( + DdManager * dd, + DdNode * f, + CUDD_VALUE_TYPE value) +{ + DdNode *res; + DdNode *val; + + val = cuddUniqueConst(dd,value); + if (val == NULL) return(NULL); + cuddRef(val); + + do { + dd->reordered = 0; + res = addBddDoThreshold(dd, f, val); + } while (dd->reordered == 1); + + if (res == NULL) { + Cudd_RecursiveDeref(dd, val); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, val); + cuddDeref(res); + return(res); + +} /* end of Cudd_addBddThreshold */ + + +/**Function******************************************************************** + + Synopsis [Converts an ADD to a BDD.] + + Description [Converts an ADD to a BDD by replacing all + discriminants STRICTLY greater than value with 1, and all other + discriminants with 0. Returns a pointer to the resulting BDD if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd + Cudd_addBddThreshold] + +******************************************************************************/ +DdNode * +Cudd_addBddStrictThreshold( + DdManager * dd, + DdNode * f, + CUDD_VALUE_TYPE value) +{ + DdNode *res; + DdNode *val; + + val = cuddUniqueConst(dd,value); + if (val == NULL) return(NULL); + cuddRef(val); + + do { + dd->reordered = 0; + res = addBddDoStrictThreshold(dd, f, val); + } while (dd->reordered == 1); + + if (res == NULL) { + Cudd_RecursiveDeref(dd, val); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, val); + cuddDeref(res); + return(res); + +} /* end of Cudd_addBddStrictThreshold */ + + +/**Function******************************************************************** + + Synopsis [Converts an ADD to a BDD.] + + Description [Converts an ADD to a BDD by replacing all + discriminants greater than or equal to lower and less than or equal to + upper with 1, and all other discriminants with 0. Returns a pointer to + the resulting BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addBddThreshold Cudd_addBddStrictThreshold + Cudd_addBddPattern Cudd_BddToAdd] + +******************************************************************************/ +DdNode * +Cudd_addBddInterval( + DdManager * dd, + DdNode * f, + CUDD_VALUE_TYPE lower, + CUDD_VALUE_TYPE upper) +{ + DdNode *res; + DdNode *l; + DdNode *u; + + /* Create constant nodes for the interval bounds, so that we can use + ** the global cache. + */ + l = cuddUniqueConst(dd,lower); + if (l == NULL) return(NULL); + cuddRef(l); + u = cuddUniqueConst(dd,upper); + if (u == NULL) { + Cudd_RecursiveDeref(dd,l); + return(NULL); + } + cuddRef(u); + + do { + dd->reordered = 0; + res = addBddDoInterval(dd, f, l, u); + } while (dd->reordered == 1); + + if (res == NULL) { + Cudd_RecursiveDeref(dd, l); + Cudd_RecursiveDeref(dd, u); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, l); + Cudd_RecursiveDeref(dd, u); + cuddDeref(res); + return(res); + +} /* end of Cudd_addBddInterval */ + + +/**Function******************************************************************** + + Synopsis [Converts an ADD to a BDD by extracting the i-th bit from + the leaves.] + + Description [Converts an ADD to a BDD by replacing all + discriminants whose i-th bit is equal to 1 with 1, and all other + discriminants with 0. The i-th bit refers to the integer + representation of the leaf value. If the value is has a fractional + part, it is ignored. Repeated calls to this procedure allow one to + transform an integer-valued ADD into an array of BDDs, one for each + bit of the leaf values. Returns a pointer to the resulting BDD if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd] + +******************************************************************************/ +DdNode * +Cudd_addBddIthBit( + DdManager * dd, + DdNode * f, + int bit) +{ + DdNode *res; + DdNode *index; + + index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit); + if (index == NULL) return(NULL); + cuddRef(index); + + do { + dd->reordered = 0; + res = addBddDoIthBit(dd, f, index); + } while (dd->reordered == 1); + + if (res == NULL) { + Cudd_RecursiveDeref(dd, index); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, index); + cuddDeref(res); + return(res); + +} /* end of Cudd_addBddIthBit */ + + +/**Function******************************************************************** + + Synopsis [Converts a BDD to a 0-1 ADD.] + + Description [Converts a BDD to a 0-1 ADD. Returns a pointer to the + resulting ADD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addBddPattern Cudd_addBddThreshold Cudd_addBddInterval + Cudd_addBddStrictThreshold] + +******************************************************************************/ +DdNode * +Cudd_BddToAdd( + DdManager * dd, + DdNode * B) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = ddBddToAddRecur(dd, B); + } while (dd->reordered ==1); + return(res); + +} /* end of Cudd_BddToAdd */ + + +/**Function******************************************************************** + + Synopsis [Converts an ADD to a BDD.] + + Description [Converts an ADD to a BDD by replacing all + discriminants different from 0 with 1. Returns a pointer to the + resulting BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_BddToAdd Cudd_addBddThreshold Cudd_addBddInterval + Cudd_addBddStrictThreshold] + +******************************************************************************/ +DdNode * +Cudd_addBddPattern( + DdManager * dd, + DdNode * f) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddAddBddDoPattern(dd, f); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addBddPattern */ + + +/**Function******************************************************************** + + Synopsis [Convert a BDD from a manager to another one.] + + Description [Convert a BDD from a manager to another one. The orders of the + variables in the two managers may be different. Returns a + pointer to the BDD in the destination manager if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_bddTransfer( + DdManager * ddSource, + DdManager * ddDestination, + DdNode * f) +{ + DdNode *res; + do { + ddDestination->reordered = 0; + res = cuddBddTransfer(ddSource, ddDestination, f); + } while (ddDestination->reordered == 1); + return(res); + +} /* end of Cudd_bddTransfer */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Convert a BDD from a manager to another one.] + + Description [Convert a BDD from a manager to another one. Returns a + pointer to the BDD in the destination manager if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddTransfer] + +******************************************************************************/ +DdNode * +cuddBddTransfer( + DdManager * ddS, + DdManager * ddD, + DdNode * f) +{ + DdNode *res; + st_table *table = NULL; + st_generator *gen = NULL; + DdNode *key, *value; + + table = st_init_table(st_ptrcmp,st_ptrhash); + if (table == NULL) goto failure; + res = cuddBddTransferRecur(ddS, ddD, f, table); + if (res != NULL) cuddRef(res); + + /* Dereference all elements in the table and dispose of the table. + ** This must be done also if res is NULL to avoid leaks in case of + ** reordering. */ + gen = st_init_gen(table); + if (gen == NULL) goto failure; + while (st_gen(gen, (char **) &key, (char **) &value)) { + Cudd_RecursiveDeref(ddD, value); + } + st_free_gen(gen); gen = NULL; + st_free_table(table); table = NULL; + + if (res != NULL) cuddDeref(res); + return(res); + +failure: + if (table != NULL) st_free_table(table); + if (gen != NULL) st_free_gen(gen); + return(NULL); + +} /* end of cuddBddTransfer */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step for Cudd_addBddPattern.] + + Description [Performs the recursive step for Cudd_addBddPattern. Returns a + pointer to the resulting BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddAddBddDoPattern( + DdManager * dd, + DdNode * f) +{ + DdNode *res, *T, *E; + DdNode *fv, *fvn; + int v; + + statLine(dd); + /* Check terminal case. */ + if (cuddIsConstant(f)) { + return(Cudd_NotCond(DD_ONE(dd),f == DD_ZERO(dd))); + } + + /* Check cache. */ + res = cuddCacheLookup1(dd,Cudd_addBddPattern,f); + if (res != NULL) return(res); + + /* Recursive step. */ + v = f->index; + fv = cuddT(f); fvn = cuddE(f); + + T = cuddAddBddDoPattern(dd,fv); + if (T == NULL) return(NULL); + cuddRef(T); + + E = cuddAddBddDoPattern(dd,fvn); + if (E == NULL) { + Cudd_RecursiveDeref(dd, T); + return(NULL); + } + cuddRef(E); + if (Cudd_IsComplement(T)) { + res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + res = Cudd_Not(res); + } else { + res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert1(dd,Cudd_addBddPattern,f,res); + + return(res); + +} /* end of cuddAddBddDoPattern */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step for Cudd_addBddThreshold.] + + Description [Performs the recursive step for Cudd_addBddThreshold. + Returns a pointer to the BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [addBddDoStrictThreshold] + +******************************************************************************/ +static DdNode * +addBddDoThreshold( + DdManager * dd, + DdNode * f, + DdNode * val) +{ + DdNode *res, *T, *E; + DdNode *fv, *fvn; + int v; + + statLine(dd); + /* Check terminal case. */ + if (cuddIsConstant(f)) { + return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(val))); + } + + /* Check cache. */ + res = cuddCacheLookup2(dd,addBddDoThreshold,f,val); + if (res != NULL) return(res); + + /* Recursive step. */ + v = f->index; + fv = cuddT(f); fvn = cuddE(f); + + T = addBddDoThreshold(dd,fv,val); + if (T == NULL) return(NULL); + cuddRef(T); + + E = addBddDoThreshold(dd,fvn,val); + if (E == NULL) { + Cudd_RecursiveDeref(dd, T); + return(NULL); + } + cuddRef(E); + if (Cudd_IsComplement(T)) { + res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + res = Cudd_Not(res); + } else { + res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert2(dd,addBddDoThreshold,f,val,res); + + return(res); + +} /* end of addBddDoThreshold */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step for Cudd_addBddStrictThreshold.] + + Description [Performs the recursive step for Cudd_addBddStrictThreshold. + Returns a pointer to the BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [addBddDoThreshold] + +******************************************************************************/ +static DdNode * +addBddDoStrictThreshold( + DdManager * dd, + DdNode * f, + DdNode * val) +{ + DdNode *res, *T, *E; + DdNode *fv, *fvn; + int v; + + statLine(dd); + /* Check terminal case. */ + if (cuddIsConstant(f)) { + return(Cudd_NotCond(DD_ONE(dd),cuddV(f) <= cuddV(val))); + } + + /* Check cache. */ + res = cuddCacheLookup2(dd,addBddDoStrictThreshold,f,val); + if (res != NULL) return(res); + + /* Recursive step. */ + v = f->index; + fv = cuddT(f); fvn = cuddE(f); + + T = addBddDoStrictThreshold(dd,fv,val); + if (T == NULL) return(NULL); + cuddRef(T); + + E = addBddDoStrictThreshold(dd,fvn,val); + if (E == NULL) { + Cudd_RecursiveDeref(dd, T); + return(NULL); + } + cuddRef(E); + if (Cudd_IsComplement(T)) { + res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + res = Cudd_Not(res); + } else { + res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert2(dd,addBddDoStrictThreshold,f,val,res); + + return(res); + +} /* end of addBddDoStrictThreshold */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step for Cudd_addBddInterval.] + + Description [Performs the recursive step for Cudd_addBddInterval. + Returns a pointer to the BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [addBddDoThreshold addBddDoStrictThreshold] + +******************************************************************************/ +static DdNode * +addBddDoInterval( + DdManager * dd, + DdNode * f, + DdNode * l, + DdNode * u) +{ + DdNode *res, *T, *E; + DdNode *fv, *fvn; + int v; + + statLine(dd); + /* Check terminal case. */ + if (cuddIsConstant(f)) { + return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(l) || cuddV(f) > cuddV(u))); + } + + /* Check cache. */ + res = cuddCacheLookup(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u); + if (res != NULL) return(res); + + /* Recursive step. */ + v = f->index; + fv = cuddT(f); fvn = cuddE(f); + + T = addBddDoInterval(dd,fv,l,u); + if (T == NULL) return(NULL); + cuddRef(T); + + E = addBddDoInterval(dd,fvn,l,u); + if (E == NULL) { + Cudd_RecursiveDeref(dd, T); + return(NULL); + } + cuddRef(E); + if (Cudd_IsComplement(T)) { + res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + res = Cudd_Not(res); + } else { + res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u,res); + + return(res); + +} /* end of addBddDoInterval */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step for Cudd_addBddIthBit.] + + Description [Performs the recursive step for Cudd_addBddIthBit. + Returns a pointer to the BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +addBddDoIthBit( + DdManager * dd, + DdNode * f, + DdNode * index) +{ + DdNode *res, *T, *E; + DdNode *fv, *fvn; + int mask, value; + int v; + + statLine(dd); + /* Check terminal case. */ + if (cuddIsConstant(f)) { + mask = 1 << ((int) cuddV(index)); + value = (int) cuddV(f); + return(Cudd_NotCond(DD_ONE(dd),(value & mask) == 0)); + } + + /* Check cache. */ + res = cuddCacheLookup2(dd,addBddDoIthBit,f,index); + if (res != NULL) return(res); + + /* Recursive step. */ + v = f->index; + fv = cuddT(f); fvn = cuddE(f); + + T = addBddDoIthBit(dd,fv,index); + if (T == NULL) return(NULL); + cuddRef(T); + + E = addBddDoIthBit(dd,fvn,index); + if (E == NULL) { + Cudd_RecursiveDeref(dd, T); + return(NULL); + } + cuddRef(E); + if (Cudd_IsComplement(T)) { + res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + res = Cudd_Not(res); + } else { + res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + } + cuddDeref(T); + cuddDeref(E); + + /* Store result. */ + cuddCacheInsert2(dd,addBddDoIthBit,f,index,res); + + return(res); + +} /* end of addBddDoIthBit */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step for Cudd_BddToAdd.] + + Description [Performs the recursive step for Cudd_BddToAdd. Returns a + pointer to the resulting ADD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +ddBddToAddRecur( + DdManager * dd, + DdNode * B) +{ + DdNode *one; + DdNode *res, *res1, *T, *E, *Bt, *Be; + int complement = 0; + + statLine(dd); + one = DD_ONE(dd); + + if (Cudd_IsConstant(B)) { + if (B == one) { + res = one; + } else { + res = DD_ZERO(dd); + } + return(res); + } + /* Check visited table */ + res = cuddCacheLookup1(dd,ddBddToAddRecur,B); + if (res != NULL) return(res); + + if (Cudd_IsComplement(B)) { + complement = 1; + Bt = cuddT(Cudd_Regular(B)); + Be = cuddE(Cudd_Regular(B)); + } else { + Bt = cuddT(B); + Be = cuddE(B); + } + + T = ddBddToAddRecur(dd, Bt); + if (T == NULL) return(NULL); + cuddRef(T); + + E = ddBddToAddRecur(dd, Be); + if (E == NULL) { + Cudd_RecursiveDeref(dd, T); + return(NULL); + } + cuddRef(E); + + /* No need to check for T == E, because it is guaranteed not to happen. */ + res = cuddUniqueInter(dd, (int) Cudd_Regular(B)->index, T, E); + if (res == NULL) { + Cudd_RecursiveDeref(dd ,T); + Cudd_RecursiveDeref(dd ,E); + return(NULL); + } + cuddDeref(T); + cuddDeref(E); + + if (complement) { + cuddRef(res); + res1 = cuddAddCmplRecur(dd, res); + if (res1 == NULL) { + Cudd_RecursiveDeref(dd, res); + return(NULL); + } + cuddRef(res1); + Cudd_RecursiveDeref(dd, res); + res = res1; + cuddDeref(res); + } + + /* Store result. */ + cuddCacheInsert1(dd,ddBddToAddRecur,B,res); + + return(res); + +} /* end of ddBddToAddRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddTransfer.] + + Description [Performs the recursive step of Cudd_bddTransfer. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddBddTransfer] + +******************************************************************************/ +static DdNode * +cuddBddTransferRecur( + DdManager * ddS, + DdManager * ddD, + DdNode * f, + st_table * table) +{ + DdNode *ft, *fe, *t, *e, *var, *res; + DdNode *one, *zero; + int index; + int comple = 0; + + statLine(ddD); + one = DD_ONE(ddD); + comple = Cudd_IsComplement(f); + + /* Trivial cases. */ + if (Cudd_IsConstant(f)) return(Cudd_NotCond(one, comple)); + + /* Make canonical to increase the utilization of the cache. */ + f = Cudd_NotCond(f,comple); + /* Now f is a regular pointer to a non-constant node. */ + + /* Check the cache. */ + if(st_lookup(table, (char *)f, (char **) &res)) + return(Cudd_NotCond(res,comple)); + + /* Recursive step. */ + index = f->index; + ft = cuddT(f); fe = cuddE(f); + + t = cuddBddTransferRecur(ddS, ddD, ft, table); + if (t == NULL) { + return(NULL); + } + cuddRef(t); + + e = cuddBddTransferRecur(ddS, ddD, fe, table); + if (e == NULL) { + Cudd_RecursiveDeref(ddD, t); + return(NULL); + } + cuddRef(e); + + zero = Cudd_Not(one); + var = cuddUniqueInter(ddD,index,one,zero); + if (var == NULL) { + Cudd_RecursiveDeref(ddD, t); + Cudd_RecursiveDeref(ddD, e); + return(NULL); + } + res = cuddBddIteRecur(ddD,var,t,e); + if (res == NULL) { + Cudd_RecursiveDeref(ddD, t); + Cudd_RecursiveDeref(ddD, e); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(ddD, t); + Cudd_RecursiveDeref(ddD, e); + + if (st_add_direct(table, (char *) f, (char *) res) == ST_OUT_OF_MEM) { + Cudd_RecursiveDeref(ddD, res); + return(NULL); + } + return(Cudd_NotCond(res,comple)); + +} /* end of cuddBddTransferRecur */ + diff --git a/abc70930/src/bdd/cudd/cuddCache.c b/abc70930/src/bdd/cudd/cuddCache.c new file mode 100644 index 00000000..d9e40921 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddCache.c @@ -0,0 +1,1023 @@ +/**CFile*********************************************************************** + + FileName [cuddCache.c] + + PackageName [cudd] + + Synopsis [Functions for cache insertion and lookup.] + + Description [Internal procedures included in this module: +
    +
  • cuddInitCache() +
  • cuddCacheInsert() +
  • cuddCacheInsert2() +
  • cuddCacheLookup() +
  • cuddCacheLookupZdd() +
  • cuddCacheLookup2() +
  • cuddCacheLookup2Zdd() +
  • cuddConstantLookup() +
  • cuddCacheProfile() +
  • cuddCacheResize() +
  • cuddCacheFlush() +
  • cuddComputeFloorLog2() +
+ Static procedures included in this module: +
    +
] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#ifdef DD_CACHE_PROFILE +#define DD_HYSTO_BINS 8 +#endif + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddCache.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Initializes the computed table.] + + Description [Initializes the computed table. It is called by + Cudd_Init. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_Init] + +******************************************************************************/ +int +cuddInitCache( + DdManager * unique /* unique table */, + unsigned int cacheSize /* initial size of the cache */, + unsigned int maxCacheSize /* cache size beyond which no resizing occurs */) +{ + int i; + unsigned int logSize; +#ifndef DD_CACHE_PROFILE + DdNodePtr *mem; + ptruint offset; +#endif + + /* Round cacheSize to largest power of 2 not greater than the requested + ** initial cache size. */ + logSize = cuddComputeFloorLog2(ddMax(cacheSize,unique->slots/2)); + cacheSize = 1 << logSize; + unique->acache = ALLOC(DdCache,cacheSize+1); + if (unique->acache == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + /* If the size of the cache entry is a power of 2, we want to + ** enforce alignment to that power of two. This happens when + ** DD_CACHE_PROFILE is not defined. */ +#ifdef DD_CACHE_PROFILE + unique->cache = unique->acache; + unique->memused += (cacheSize) * sizeof(DdCache); +#else + mem = (DdNodePtr *) unique->acache; + offset = (ptruint) mem & (sizeof(DdCache) - 1); + mem += (sizeof(DdCache) - offset) / sizeof(DdNodePtr); + unique->cache = (DdCache *) mem; + assert(((ptruint) unique->cache & (sizeof(DdCache) - 1)) == 0); + unique->memused += (cacheSize+1) * sizeof(DdCache); +#endif + unique->cacheSlots = cacheSize; + unique->cacheShift = sizeof(int) * 8 - logSize; + unique->maxCacheHard = maxCacheSize; + /* If cacheSlack is non-negative, we can resize. */ + unique->cacheSlack = (int) ddMin(maxCacheSize, + DD_MAX_CACHE_TO_SLOTS_RATIO*unique->slots) - + 2 * (int) cacheSize; + Cudd_SetMinHit(unique,DD_MIN_HIT); + /* Initialize to avoid division by 0 and immediate resizing. */ + unique->cacheMisses = (double) (int) (cacheSize * unique->minHit + 1); + unique->cacheHits = 0; + unique->totCachehits = 0; + /* The sum of cacheMisses and totCacheMisses is always correct, + ** even though cacheMisses is larger than it should for the reasons + ** explained above. */ + unique->totCacheMisses = -unique->cacheMisses; + unique->cachecollisions = 0; + unique->cacheinserts = 0; + unique->cacheLastInserts = 0; + unique->cachedeletions = 0; + + /* Initialize the cache */ + for (i = 0; (unsigned) i < cacheSize; i++) { + unique->cache[i].h = 0; /* unused slots */ + unique->cache[i].data = NULL; /* invalid entry */ +#ifdef DD_CACHE_PROFILE + unique->cache[i].count = 0; +#endif + } + + return(1); + +} /* end of cuddInitCache */ + + +/**Function******************************************************************** + + Synopsis [Inserts a result in the cache.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddCacheInsert2 cuddCacheInsert1] + +******************************************************************************/ +void +cuddCacheInsert( + DdManager * table, + ptruint op, + DdNode * f, + DdNode * g, + DdNode * h, + DdNode * data) +{ + int posn; + register DdCache *entry; + ptruint uf, ug, uh; + + uf = (ptruint) f | (op & 0xe); + ug = (ptruint) g | (op >> 4); + uh = (ptruint) h; + + posn = ddCHash2(uh,uf,ug,table->cacheShift); + entry = &table->cache[posn]; + + table->cachecollisions += entry->data != NULL; + table->cacheinserts++; + + entry->f = (DdNode *) uf; + entry->g = (DdNode *) ug; + entry->h = uh; + entry->data = data; +#ifdef DD_CACHE_PROFILE + entry->count++; +#endif + +} /* end of cuddCacheInsert */ + + +/**Function******************************************************************** + + Synopsis [Inserts a result in the cache for a function with two + operands.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddCacheInsert cuddCacheInsert1] + +******************************************************************************/ +void +cuddCacheInsert2( + DdManager * table, + DdNode * (*op)(DdManager *, DdNode *, DdNode *), + DdNode * f, + DdNode * g, + DdNode * data) +{ + int posn; + register DdCache *entry; + + posn = ddCHash2(op,f,g,table->cacheShift); + entry = &table->cache[posn]; + + if (entry->data != NULL) { + table->cachecollisions++; + } + table->cacheinserts++; + + entry->f = f; + entry->g = g; + entry->h = (ptruint) op; + entry->data = data; +#ifdef DD_CACHE_PROFILE + entry->count++; +#endif + +} /* end of cuddCacheInsert2 */ + + +/**Function******************************************************************** + + Synopsis [Inserts a result in the cache for a function with two + operands.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddCacheInsert cuddCacheInsert2] + +******************************************************************************/ +void +cuddCacheInsert1( + DdManager * table, + DdNode * (*op)(DdManager *, DdNode *), + DdNode * f, + DdNode * data) +{ + int posn; + register DdCache *entry; + + posn = ddCHash2(op,f,f,table->cacheShift); + entry = &table->cache[posn]; + + if (entry->data != NULL) { + table->cachecollisions++; + } + table->cacheinserts++; + + entry->f = f; + entry->g = f; + entry->h = (ptruint) op; + entry->data = data; +#ifdef DD_CACHE_PROFILE + entry->count++; +#endif + +} /* end of cuddCacheInsert1 */ + + +/**Function******************************************************************** + + Synopsis [Looks up in the cache for the result of op applied to f, + g, and h.] + + Description [Returns the result if found; it returns NULL if no + result is found.] + + SideEffects [None] + + SeeAlso [cuddCacheLookup2 cuddCacheLookup1] + +******************************************************************************/ +DdNode * +cuddCacheLookup( + DdManager * table, + ptruint op, + DdNode * f, + DdNode * g, + DdNode * h) +{ + int posn; + DdCache *en,*cache; + DdNode *data; + ptruint uf, ug, uh; + + uf = (ptruint) f | (op & 0xe); + ug = (ptruint) g | (op >> 4); + uh = (ptruint) h; + + cache = table->cache; +#ifdef DD_DEBUG + if (cache == NULL) { + return(NULL); + } +#endif + + posn = ddCHash2(uh,uf,ug,table->cacheShift); + en = &cache[posn]; + if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && + en->h==uh) { + data = Cudd_Regular(en->data); + table->cacheHits++; + if (data->ref == 0) { + cuddReclaim(table,data); + } + return(en->data); + } + + /* Cache miss: decide whether to resize. */ + table->cacheMisses++; + + if (table->cacheSlack >= 0 && + table->cacheHits > table->cacheMisses * table->minHit) { + cuddCacheResize(table); + } + + return(NULL); + +} /* end of cuddCacheLookup */ + + +/**Function******************************************************************** + + Synopsis [Looks up in the cache for the result of op applied to f, + g, and h.] + + Description [Returns the result if found; it returns NULL if no + result is found.] + + SideEffects [None] + + SeeAlso [cuddCacheLookup2Zdd cuddCacheLookup1Zdd] + +******************************************************************************/ +DdNode * +cuddCacheLookupZdd( + DdManager * table, + ptruint op, + DdNode * f, + DdNode * g, + DdNode * h) +{ + int posn; + DdCache *en,*cache; + DdNode *data; + ptruint uf, ug, uh; + + uf = (ptruint) f | (op & 0xe); + ug = (ptruint) g | (op >> 4); + uh = (ptruint) h; + + cache = table->cache; +#ifdef DD_DEBUG + if (cache == NULL) { + return(NULL); + } +#endif + + posn = ddCHash2(uh,uf,ug,table->cacheShift); + en = &cache[posn]; + if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && + en->h==uh) { + data = Cudd_Regular(en->data); + table->cacheHits++; + if (data->ref == 0) { + cuddReclaimZdd(table,data); + } + return(en->data); + } + + /* Cache miss: decide whether to resize. */ + table->cacheMisses++; + + if (table->cacheSlack >= 0 && + table->cacheHits > table->cacheMisses * table->minHit) { + cuddCacheResize(table); + } + + return(NULL); + +} /* end of cuddCacheLookupZdd */ + + +/**Function******************************************************************** + + Synopsis [Looks up in the cache for the result of op applied to f + and g.] + + Description [Returns the result if found; it returns NULL if no + result is found.] + + SideEffects [None] + + SeeAlso [cuddCacheLookup cuddCacheLookup1] + +******************************************************************************/ +DdNode * +cuddCacheLookup2( + DdManager * table, + DdNode * (*op)(DdManager *, DdNode *, DdNode *), + DdNode * f, + DdNode * g) +{ + int posn; + DdCache *en,*cache; + DdNode *data; + + cache = table->cache; +#ifdef DD_DEBUG + if (cache == NULL) { + return(NULL); + } +#endif + + posn = ddCHash2(op,f,g,table->cacheShift); + en = &cache[posn]; + if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) { + data = Cudd_Regular(en->data); + table->cacheHits++; + if (data->ref == 0) { + cuddReclaim(table,data); + } + return(en->data); + } + + /* Cache miss: decide whether to resize. */ + table->cacheMisses++; + + if (table->cacheSlack >= 0 && + table->cacheHits > table->cacheMisses * table->minHit) { + cuddCacheResize(table); + } + + return(NULL); + +} /* end of cuddCacheLookup2 */ + + +/**Function******************************************************************** + + Synopsis [Looks up in the cache for the result of op applied to f.] + + Description [Returns the result if found; it returns NULL if no + result is found.] + + SideEffects [None] + + SeeAlso [cuddCacheLookup cuddCacheLookup2] + +******************************************************************************/ +DdNode * +cuddCacheLookup1( + DdManager * table, + DdNode * (*op)(DdManager *, DdNode *), + DdNode * f) +{ + int posn; + DdCache *en,*cache; + DdNode *data; + + cache = table->cache; +#ifdef DD_DEBUG + if (cache == NULL) { + return(NULL); + } +#endif + + posn = ddCHash2(op,f,f,table->cacheShift); + en = &cache[posn]; + if (en->data != NULL && en->f==f && en->h==(ptruint)op) { + data = Cudd_Regular(en->data); + table->cacheHits++; + if (data->ref == 0) { + cuddReclaim(table,data); + } + return(en->data); + } + + /* Cache miss: decide whether to resize. */ + table->cacheMisses++; + + if (table->cacheSlack >= 0 && + table->cacheHits > table->cacheMisses * table->minHit) { + cuddCacheResize(table); + } + + return(NULL); + +} /* end of cuddCacheLookup1 */ + + +/**Function******************************************************************** + + Synopsis [Looks up in the cache for the result of op applied to f + and g.] + + Description [Returns the result if found; it returns NULL if no + result is found.] + + SideEffects [None] + + SeeAlso [cuddCacheLookupZdd cuddCacheLookup1Zdd] + +******************************************************************************/ +DdNode * +cuddCacheLookup2Zdd( + DdManager * table, + DdNode * (*op)(DdManager *, DdNode *, DdNode *), + DdNode * f, + DdNode * g) +{ + int posn; + DdCache *en,*cache; + DdNode *data; + + cache = table->cache; +#ifdef DD_DEBUG + if (cache == NULL) { + return(NULL); + } +#endif + + posn = ddCHash2(op,f,g,table->cacheShift); + en = &cache[posn]; + if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) { + data = Cudd_Regular(en->data); + table->cacheHits++; + if (data->ref == 0) { + cuddReclaimZdd(table,data); + } + return(en->data); + } + + /* Cache miss: decide whether to resize. */ + table->cacheMisses++; + + if (table->cacheSlack >= 0 && + table->cacheHits > table->cacheMisses * table->minHit) { + cuddCacheResize(table); + } + + return(NULL); + +} /* end of cuddCacheLookup2Zdd */ + + +/**Function******************************************************************** + + Synopsis [Looks up in the cache for the result of op applied to f.] + + Description [Returns the result if found; it returns NULL if no + result is found.] + + SideEffects [None] + + SeeAlso [cuddCacheLookupZdd cuddCacheLookup2Zdd] + +******************************************************************************/ +DdNode * +cuddCacheLookup1Zdd( + DdManager * table, + DdNode * (*op)(DdManager *, DdNode *), + DdNode * f) +{ + int posn; + DdCache *en,*cache; + DdNode *data; + + cache = table->cache; +#ifdef DD_DEBUG + if (cache == NULL) { + return(NULL); + } +#endif + + posn = ddCHash2(op,f,f,table->cacheShift); + en = &cache[posn]; + if (en->data != NULL && en->f==f && en->h==(ptruint)op) { + data = Cudd_Regular(en->data); + table->cacheHits++; + if (data->ref == 0) { + cuddReclaimZdd(table,data); + } + return(en->data); + } + + /* Cache miss: decide whether to resize. */ + table->cacheMisses++; + + if (table->cacheSlack >= 0 && + table->cacheHits > table->cacheMisses * table->minHit) { + cuddCacheResize(table); + } + + return(NULL); + +} /* end of cuddCacheLookup1Zdd */ + + +/**Function******************************************************************** + + Synopsis [Looks up in the cache for the result of op applied to f, + g, and h.] + + Description [Looks up in the cache for the result of op applied to f, + g, and h. Assumes that the calling procedure (e.g., + Cudd_bddIteConstant) is only interested in whether the result is + constant or not. Returns the result if found (possibly + DD_NON_CONSTANT); otherwise it returns NULL.] + + SideEffects [None] + + SeeAlso [cuddCacheLookup] + +******************************************************************************/ +DdNode * +cuddConstantLookup( + DdManager * table, + ptruint op, + DdNode * f, + DdNode * g, + DdNode * h) +{ + int posn; + DdCache *en,*cache; + ptruint uf, ug, uh; + + uf = (ptruint) f | (op & 0xe); + ug = (ptruint) g | (op >> 4); + uh = (ptruint) h; + + cache = table->cache; +#ifdef DD_DEBUG + if (cache == NULL) { + return(NULL); + } +#endif + posn = ddCHash2(uh,uf,ug,table->cacheShift); + en = &cache[posn]; + + /* We do not reclaim here because the result should not be + * referenced, but only tested for being a constant. + */ + if (en->data != NULL && + en->f == (DdNodePtr)uf && en->g == (DdNodePtr)ug && en->h == uh) { + table->cacheHits++; + return(en->data); + } + + /* Cache miss: decide whether to resize. */ + table->cacheMisses++; + + if (table->cacheSlack >= 0 && + table->cacheHits > table->cacheMisses * table->minHit) { + cuddCacheResize(table); + } + + return(NULL); + +} /* end of cuddConstantLookup */ + + +/**Function******************************************************************** + + Synopsis [Computes and prints a profile of the cache usage.] + + Description [Computes and prints a profile of the cache usage. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddCacheProfile( + DdManager * table, + FILE * fp) +{ + DdCache *cache = table->cache; + int slots = table->cacheSlots; + int nzeroes = 0; + int i, retval; + double exUsed; + +#ifdef DD_CACHE_PROFILE + double count, mean, meansq, stddev, expected; + long max, min; + int imax, imin; + double *hystogramQ, *hystogramR; /* histograms by quotient and remainder */ + int nbins = DD_HYSTO_BINS; + int bin; + long thiscount; + double totalcount, exStddev; + + meansq = mean = expected = 0.0; + max = min = (long) cache[0].count; + imax = imin = 0; + totalcount = 0.0; + + hystogramQ = ALLOC(double, nbins); + if (hystogramQ == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + hystogramR = ALLOC(double, nbins); + if (hystogramR == NULL) { + FREE(hystogramQ); + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (i = 0; i < nbins; i++) { + hystogramQ[i] = 0; + hystogramR[i] = 0; + } + + for (i = 0; i < slots; i++) { + thiscount = (long) cache[i].count; + if (thiscount > max) { + max = thiscount; + imax = i; + } + if (thiscount < min) { + min = thiscount; + imin = i; + } + if (thiscount == 0) { + nzeroes++; + } + count = (double) thiscount; + mean += count; + meansq += count * count; + totalcount += count; + expected += count * (double) i; + bin = (i * nbins) / slots; + hystogramQ[bin] += (double) thiscount; + bin = i % nbins; + hystogramR[bin] += (double) thiscount; + } + mean /= (double) slots; + meansq /= (double) slots; + + /* Compute the standard deviation from both the data and the + ** theoretical model for a random distribution. */ + stddev = sqrt(meansq - mean*mean); + exStddev = sqrt((1 - 1/(double) slots) * totalcount / (double) slots); + + retval = fprintf(fp,"Cache average accesses = %g\n", mean); + if (retval == EOF) return(0); + retval = fprintf(fp,"Cache access standard deviation = %g ", stddev); + if (retval == EOF) return(0); + retval = fprintf(fp,"(expected = %g)\n", exStddev); + if (retval == EOF) return(0); + retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax); + if (retval == EOF) return(0); + retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin); + if (retval == EOF) return(0); + exUsed = 100.0 * (1.0 - exp(-totalcount / (double) slots)); + retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n", + 100.0 - (double) nzeroes * 100.0 / (double) slots, + exUsed); + if (retval == EOF) return(0); + + if (totalcount > 0) { + expected /= totalcount; + retval = fprintf(fp,"Cache access hystogram for %d bins", nbins); + if (retval == EOF) return(0); + retval = fprintf(fp," (expected bin value = %g)\nBy quotient:", + expected); + if (retval == EOF) return(0); + for (i = nbins - 1; i>=0; i--) { + retval = fprintf(fp," %.0f", hystogramQ[i]); + if (retval == EOF) return(0); + } + retval = fprintf(fp,"\nBy residue: "); + if (retval == EOF) return(0); + for (i = nbins - 1; i>=0; i--) { + retval = fprintf(fp," %.0f", hystogramR[i]); + if (retval == EOF) return(0); + } + retval = fprintf(fp,"\n"); + if (retval == EOF) return(0); + } + + FREE(hystogramQ); + FREE(hystogramR); +#else + for (i = 0; i < slots; i++) { + nzeroes += cache[i].h == 0; + } + exUsed = 100.0 * + (1.0 - exp(-(table->cacheinserts - table->cacheLastInserts) / + (double) slots)); + retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n", + 100.0 - (double) nzeroes * 100.0 / (double) slots, + exUsed); + if (retval == EOF) return(0); +#endif + return(1); + +} /* end of cuddCacheProfile */ + + +/**Function******************************************************************** + + Synopsis [Resizes the cache.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +cuddCacheResize( + DdManager * table) +{ + DdCache *cache, *oldcache, *oldacache, *entry, *old; + int i; + int posn, shift; + unsigned int slots, oldslots; + double offset; + int moved = 0; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); +#ifndef DD_CACHE_PROFILE + ptruint misalignment; + DdNodePtr *mem; +#endif + + oldcache = table->cache; + oldacache = table->acache; + oldslots = table->cacheSlots; + slots = table->cacheSlots = oldslots << 1; + +#ifdef DD_VERBOSE + (void) fprintf(table->err,"Resizing the cache from %d to %d entries\n", + oldslots, slots); + (void) fprintf(table->err, + "\thits = %g\tmisses = %g\thit ratio = %5.3f\n", + table->cacheHits, table->cacheMisses, + table->cacheHits / (table->cacheHits + table->cacheMisses)); +#endif + + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + table->acache = cache = ALLOC(DdCache,slots+1); + MMoutOfMemory = saveHandler; + /* If we fail to allocate the new table we just give up. */ + if (cache == NULL) { +#ifdef DD_VERBOSE + (void) fprintf(table->err,"Resizing failed. Giving up.\n"); +#endif + table->cacheSlots = oldslots; + table->acache = oldacache; + /* Do not try to resize again. */ + table->maxCacheHard = oldslots - 1; + table->cacheSlack = - (oldslots + 1); + return; + } + /* If the size of the cache entry is a power of 2, we want to + ** enforce alignment to that power of two. This happens when + ** DD_CACHE_PROFILE is not defined. */ +#ifdef DD_CACHE_PROFILE + table->cache = cache; +#else + mem = (DdNodePtr *) cache; + misalignment = (ptruint) mem & (sizeof(DdCache) - 1); + mem += (sizeof(DdCache) - misalignment) / sizeof(DdNodePtr); + table->cache = cache = (DdCache *) mem; + assert(((ptruint) table->cache & (sizeof(DdCache) - 1)) == 0); +#endif + shift = --(table->cacheShift); + table->memused += (slots - oldslots) * sizeof(DdCache); + table->cacheSlack -= slots; /* need these many slots to double again */ + + /* Clear new cache. */ + for (i = 0; (unsigned) i < slots; i++) { + cache[i].data = NULL; + cache[i].h = 0; +#ifdef DD_CACHE_PROFILE + cache[i].count = 0; +#endif + } + + /* Copy from old cache to new one. */ + for (i = 0; (unsigned) i < oldslots; i++) { + old = &oldcache[i]; + if (old->data != NULL) { + posn = ddCHash2(old->h,old->f,old->g,shift); + entry = &cache[posn]; + entry->f = old->f; + entry->g = old->g; + entry->h = old->h; + entry->data = old->data; +#ifdef DD_CACHE_PROFILE + entry->count = 1; +#endif + moved++; + } + } + + FREE(oldacache); + + /* Reinitialize measurements so as to avoid division by 0 and + ** immediate resizing. + */ + offset = (double) (int) (slots * table->minHit + 1); + table->totCacheMisses += table->cacheMisses - offset; + table->cacheMisses = offset; + table->totCachehits += table->cacheHits; + table->cacheHits = 0; + table->cacheLastInserts = table->cacheinserts - (double) moved; + +} /* end of cuddCacheResize */ + + +/**Function******************************************************************** + + Synopsis [Flushes the cache.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +cuddCacheFlush( + DdManager * table) +{ + int i, slots; + DdCache *cache; + + slots = table->cacheSlots; + cache = table->cache; + for (i = 0; i < slots; i++) { + table->cachedeletions += cache[i].data != NULL; + cache[i].data = NULL; + } + table->cacheLastInserts = table->cacheinserts; + + return; + +} /* end of cuddCacheFlush */ + + +/**Function******************************************************************** + + Synopsis [Returns the floor of the logarithm to the base 2.] + + Description [Returns the floor of the logarithm to the base 2. + The input value is assumed to be greater than 0.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddComputeFloorLog2( + unsigned int value) +{ + int floorLog = 0; +#ifdef DD_DEBUG + assert(value > 0); +#endif + while (value > 1) { + floorLog++; + value >>= 1; + } + return(floorLog); + +} /* end of cuddComputeFloorLog2 */ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ diff --git a/abc70930/src/bdd/cudd/cuddCheck.c b/abc70930/src/bdd/cudd/cuddCheck.c new file mode 100644 index 00000000..aec8246d --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddCheck.c @@ -0,0 +1,851 @@ +/**CFile*********************************************************************** + + FileName [cuddCheck.c] + + PackageName [cudd] + + Synopsis [Functions to check consistency of data structures.] + + Description [External procedures included in this module: +
    +
  • Cudd_DebugCheck() +
  • Cudd_CheckKeys() +
+ Internal procedures included in this module: +
    +
  • cuddHeapProfile() +
  • cuddPrintNode() +
  • cuddPrintVarGroups() +
+ Static procedures included in this module: +
    +
  • debugFindParent() +
+ ] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddCheck.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void debugFindParent ARGS((DdManager *table, DdNode *node)); +#if 0 +static void debugCheckParent ARGS((DdManager *table, DdNode *node)); +#endif + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Checks for inconsistencies in the DD heap.] + + Description [Checks for inconsistencies in the DD heap: +
    +
  • node has illegal index +
  • live node has dead children +
  • node has illegal Then or Else pointers +
  • BDD/ADD node has identical children +
  • ZDD node has zero then child +
  • wrong number of total nodes +
  • wrong number of dead nodes +
  • ref count error at node +
+ Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is + not enough memory; 1 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_CheckKeys] + +******************************************************************************/ +int +Cudd_DebugCheck( + DdManager * table) +{ + unsigned int i; + int j,count; + int slots; + DdNodePtr *nodelist; + DdNode *f; + DdNode *sentinel = &(table->sentinel); + st_table *edgeTable; /* stores internal ref count for each node */ + st_generator *gen; + int flag = 0; + int totalNode; + int deadNode; + int index; + + + edgeTable = st_init_table(st_ptrcmp,st_ptrhash); + if (edgeTable == NULL) return(CUDD_OUT_OF_MEM); + + /* Check the BDD/ADD subtables. */ + for (i = 0; i < (unsigned) table->size; i++) { + index = table->invperm[i]; + if (i != (unsigned) table->perm[index]) { + (void) fprintf(table->err, + "Permutation corrupted: invperm[%d] = %d\t perm[%d] = %d\n", + i, index, index, table->perm[index]); + } + nodelist = table->subtables[i].nodelist; + slots = table->subtables[i].slots; + + totalNode = 0; + deadNode = 0; + for (j = 0; j < slots; j++) { /* for each subtable slot */ + f = nodelist[j]; + while (f != sentinel) { + totalNode++; + if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) { + if ((int) f->index != index) { + (void) fprintf(table->err, + "Error: node has illegal index\n"); + cuddPrintNode(f,table->err); + flag = 1; + } + if ((unsigned) cuddI(table,cuddT(f)->index) <= i || + (unsigned) cuddI(table,Cudd_Regular(cuddE(f))->index) + <= i) { + (void) fprintf(table->err, + "Error: node has illegal children\n"); + cuddPrintNode(f,table->err); + flag = 1; + } + if (Cudd_Regular(cuddT(f)) != cuddT(f)) { + (void) fprintf(table->err, + "Error: node has illegal form\n"); + cuddPrintNode(f,table->err); + flag = 1; + } + if (cuddT(f) == cuddE(f)) { + (void) fprintf(table->err, + "Error: node has identical children\n"); + cuddPrintNode(f,table->err); + flag = 1; + } + if (cuddT(f)->ref == 0 || Cudd_Regular(cuddE(f))->ref == 0) { + (void) fprintf(table->err, + "Error: live node has dead children\n"); + cuddPrintNode(f,table->err); + flag =1; + } + /* Increment the internal reference count for the + ** then child of the current node. + */ + if (st_lookup(edgeTable,(char *)cuddT(f),(char **)&count)) { + count++; + } else { + count = 1; + } + if (st_insert(edgeTable,(char *)cuddT(f), + (char *)(long)count) == ST_OUT_OF_MEM) { + st_free_table(edgeTable); + return(CUDD_OUT_OF_MEM); + } + + /* Increment the internal reference count for the + ** else child of the current node. + */ + if (st_lookup(edgeTable,(char *)Cudd_Regular(cuddE(f)),(char **)&count)) { + count++; + } else { + count = 1; + } + if (st_insert(edgeTable,(char *)Cudd_Regular(cuddE(f)), + (char *)(long)count) == ST_OUT_OF_MEM) { + st_free_table(edgeTable); + return(CUDD_OUT_OF_MEM); + } + } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) { + deadNode++; +#if 0 + debugCheckParent(table,f); +#endif + } else { + fprintf(table->err, + "Error: node has illegal Then or Else pointers\n"); + cuddPrintNode(f,table->err); + flag = 1; + } + + f = f->next; + } /* for each element of the collision list */ + } /* for each subtable slot */ + + if ((unsigned) totalNode != table->subtables[i].keys) { + fprintf(table->err,"Error: wrong number of total nodes\n"); + flag = 1; + } + if ((unsigned) deadNode != table->subtables[i].dead) { + fprintf(table->err,"Error: wrong number of dead nodes\n"); + flag = 1; + } + } /* for each BDD/ADD subtable */ + + /* Check the ZDD subtables. */ + for (i = 0; i < (unsigned) table->sizeZ; i++) { + index = table->invpermZ[i]; + if (i != (unsigned) table->permZ[index]) { + (void) fprintf(table->err, + "Permutation corrupted: invpermZ[%d] = %d\t permZ[%d] = %d in ZDD\n", + i, index, index, table->permZ[index]); + } + nodelist = table->subtableZ[i].nodelist; + slots = table->subtableZ[i].slots; + + totalNode = 0; + deadNode = 0; + for (j = 0; j < slots; j++) { /* for each subtable slot */ + f = nodelist[j]; + while (f != NULL) { + totalNode++; + if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) { + if ((int) f->index != index) { + (void) fprintf(table->err, + "Error: ZDD node has illegal index\n"); + cuddPrintNode(f,table->err); + flag = 1; + } + if (Cudd_IsComplement(cuddT(f)) || + Cudd_IsComplement(cuddE(f))) { + (void) fprintf(table->err, + "Error: ZDD node has complemented children\n"); + cuddPrintNode(f,table->err); + flag = 1; + } + if ((unsigned) cuddIZ(table,cuddT(f)->index) <= i || + (unsigned) cuddIZ(table,cuddE(f)->index) <= i) { + (void) fprintf(table->err, + "Error: ZDD node has illegal children\n"); + cuddPrintNode(f,table->err); + cuddPrintNode(cuddT(f),table->err); + cuddPrintNode(cuddE(f),table->err); + flag = 1; + } + if (cuddT(f) == DD_ZERO(table)) { + (void) fprintf(table->err, + "Error: ZDD node has zero then child\n"); + cuddPrintNode(f,table->err); + flag = 1; + } + if (cuddT(f)->ref == 0 || cuddE(f)->ref == 0) { + (void) fprintf(table->err, + "Error: ZDD live node has dead children\n"); + cuddPrintNode(f,table->err); + flag =1; + } + /* Increment the internal reference count for the + ** then child of the current node. + */ + if (st_lookup(edgeTable,(char *)cuddT(f),(char **)&count)) { + count++; + } else { + count = 1; + } + if (st_insert(edgeTable,(char *)cuddT(f), + (char *)(long)count) == ST_OUT_OF_MEM) { + st_free_table(edgeTable); + return(CUDD_OUT_OF_MEM); + } + + /* Increment the internal reference count for the + ** else child of the current node. + */ + if (st_lookup(edgeTable,(char *)cuddE(f),(char **)&count)) { + count++; + } else { + count = 1; + } + if (st_insert(edgeTable,(char *)cuddE(f), + (char *)(long)count) == ST_OUT_OF_MEM) { + st_free_table(edgeTable); + table->errorCode = CUDD_MEMORY_OUT; + return(CUDD_OUT_OF_MEM); + } + } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) { + deadNode++; +#if 0 + debugCheckParent(table,f); +#endif + } else { + fprintf(table->err, + "Error: ZDD node has illegal Then or Else pointers\n"); + cuddPrintNode(f,table->err); + flag = 1; + } + + f = f->next; + } /* for each element of the collision list */ + } /* for each subtable slot */ + + if ((unsigned) totalNode != table->subtableZ[i].keys) { + fprintf(table->err, + "Error: wrong number of total nodes in ZDD\n"); + flag = 1; + } + if ((unsigned) deadNode != table->subtableZ[i].dead) { + fprintf(table->err, + "Error: wrong number of dead nodes in ZDD\n"); + flag = 1; + } + } /* for each ZDD subtable */ + + /* Check the constant table. */ + nodelist = table->constants.nodelist; + slots = table->constants.slots; + + totalNode = 0; + deadNode = 0; + for (j = 0; j < slots; j++) { + f = nodelist[j]; + while (f != NULL) { + totalNode++; + if (f->ref != 0) { + if (f->index != CUDD_CONST_INDEX) { + fprintf(table->err,"Error: node has illegal index\n"); +#if SIZEOF_VOID_P == 8 + fprintf(table->err, + " node 0x%lx, id = %d, ref = %d, value = %g\n", + (unsigned long)f,f->index,f->ref,cuddV(f)); +#else + fprintf(table->err, + " node 0x%x, id = %d, ref = %d, value = %g\n", + (unsigned)f,f->index,f->ref,cuddV(f)); +#endif + flag = 1; + } + } else { + deadNode++; + } + f = f->next; + } + } + if ((unsigned) totalNode != table->constants.keys) { + (void) fprintf(table->err, + "Error: wrong number of total nodes in constants\n"); + flag = 1; + } + if ((unsigned) deadNode != table->constants.dead) { + (void) fprintf(table->err, + "Error: wrong number of dead nodes in constants\n"); + flag = 1; + } + gen = st_init_gen(edgeTable); + while (st_gen(gen,(char **)&f,(char **)&count)) { + if (count > (int)(f->ref) && f->ref != DD_MAXREF) { +#if SIZEOF_VOID_P == 8 + fprintf(table->err,"ref count error at node 0x%lx, count = %d, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n",(unsigned long)f,count,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f)); +#else + fprintf(table->err,"ref count error at node 0x%x, count = %d, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",(unsigned)f,count,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f)); +#endif + debugFindParent(table,f); + flag = 1; + } + } + st_free_gen(gen); + st_free_table(edgeTable); + + return (flag); + +} /* end of Cudd_DebugCheck */ + + +/**Function******************************************************************** + + Synopsis [Checks for several conditions that should not occur.] + + Description [Checks for the following conditions: +
    +
  • Wrong sizes of subtables. +
  • Wrong number of keys found in unique subtable. +
  • Wrong number of dead found in unique subtable. +
  • Wrong number of keys found in the constant table +
  • Wrong number of dead found in the constant table +
  • Wrong number of total slots found +
  • Wrong number of maximum keys found +
  • Wrong number of total dead found +
+ Reports the average length of non-empty lists. Returns the number of + subtables for which the number of keys is wrong.] + + SideEffects [None] + + SeeAlso [Cudd_DebugCheck] + +******************************************************************************/ +int +Cudd_CheckKeys( + DdManager * table) +{ + int size; + int i,j; + DdNodePtr *nodelist; + DdNode *node; + DdNode *sentinel = &(table->sentinel); + DdSubtable *subtable; + int keys; + int dead; + int count = 0; + int totalKeys = 0; + int totalSlots = 0; + int totalDead = 0; + int nonEmpty = 0; + unsigned int slots; + int logSlots; + int shift; + + size = table->size; + + for (i = 0; i < size; i++) { + subtable = &(table->subtables[i]); + nodelist = subtable->nodelist; + keys = subtable->keys; + dead = subtable->dead; + totalKeys += keys; + slots = subtable->slots; + shift = subtable->shift; + logSlots = sizeof(int) * 8 - shift; + if (((slots >> logSlots) << logSlots) != slots) { + (void) fprintf(table->err, + "Unique table %d is not the right power of 2\n", i); + (void) fprintf(table->err, + " slots = %u shift = %d\n", slots, shift); + } + totalSlots += slots; + totalDead += dead; + for (j = 0; (unsigned) j < slots; j++) { + node = nodelist[j]; + if (node != sentinel) { + nonEmpty++; + } + while (node != sentinel) { + keys--; + if (node->ref == 0) { + dead--; + } + node = node->next; + } + } + if (keys != 0) { + (void) fprintf(table->err, "Wrong number of keys found \ +in unique table %d (difference=%d)\n", i, keys); + count++; + } + if (dead != 0) { + (void) fprintf(table->err, "Wrong number of dead found \ +in unique table no. %d (difference=%d)\n", i, dead); + } + } /* for each BDD/ADD subtable */ + + /* Check the ZDD subtables. */ + size = table->sizeZ; + + for (i = 0; i < size; i++) { + subtable = &(table->subtableZ[i]); + nodelist = subtable->nodelist; + keys = subtable->keys; + dead = subtable->dead; + totalKeys += keys; + totalSlots += subtable->slots; + totalDead += dead; + for (j = 0; (unsigned) j < subtable->slots; j++) { + node = nodelist[j]; + if (node != NULL) { + nonEmpty++; + } + while (node != NULL) { + keys--; + if (node->ref == 0) { + dead--; + } + node = node->next; + } + } + if (keys != 0) { + (void) fprintf(table->err, "Wrong number of keys found \ +in ZDD unique table no. %d (difference=%d)\n", i, keys); + count++; + } + if (dead != 0) { + (void) fprintf(table->err, "Wrong number of dead found \ +in ZDD unique table no. %d (difference=%d)\n", i, dead); + } + } /* for each ZDD subtable */ + + /* Check the constant table. */ + subtable = &(table->constants); + nodelist = subtable->nodelist; + keys = subtable->keys; + dead = subtable->dead; + totalKeys += keys; + totalSlots += subtable->slots; + totalDead += dead; + for (j = 0; (unsigned) j < subtable->slots; j++) { + node = nodelist[j]; + if (node != NULL) { + nonEmpty++; + } + while (node != NULL) { + keys--; + if (node->ref == 0) { + dead--; + } + node = node->next; + } + } + if (keys != 0) { + (void) fprintf(table->err, "Wrong number of keys found \ +in the constant table (difference=%d)\n", keys); + count++; + } + if (dead != 0) { + (void) fprintf(table->err, "Wrong number of dead found \ +in the constant table (difference=%d)\n", dead); + } + if ((unsigned) totalKeys != table->keys + table->keysZ) { + (void) fprintf(table->err, "Wrong number of total keys found \ +(difference=%d)\n", totalKeys-table->keys); + } + if ((unsigned) totalSlots != table->slots) { + (void) fprintf(table->err, "Wrong number of total slots found \ +(difference=%d)\n", totalSlots-table->slots); + } + if (table->minDead != (unsigned) (table->gcFrac * table->slots)) { + (void) fprintf(table->err, "Wrong number of minimum dead found \ +(%d vs. %d)\n", table->minDead, + (unsigned) (table->gcFrac * (double) table->slots)); + } + if ((unsigned) totalDead != table->dead + table->deadZ) { + (void) fprintf(table->err, "Wrong number of total dead found \ +(difference=%d)\n", totalDead-table->dead); + } + (void)printf("Average length of non-empty lists = %g\n", + (double) table->keys / (double) nonEmpty); + + return(count); + +} /* end of Cudd_CheckKeys */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Prints information about the heap.] + + Description [Prints to the manager's stdout the number of live nodes for each + level of the DD heap that contains at least one live node. It also + prints a summary containing: +
    +
  • total number of tables; +
  • number of tables with live nodes; +
  • table with the largest number of live nodes; +
  • number of nodes in that table. +
+ If more than one table contains the maximum number of live nodes, + only the one of lowest index is reported. Returns 1 in case of success + and 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddHeapProfile( + DdManager * dd) +{ + int ntables = dd->size; + DdSubtable *subtables = dd->subtables; + int i, /* loop index */ + nodes, /* live nodes in i-th layer */ + retval, /* return value of fprintf */ + largest = -1, /* index of the table with most live nodes */ + maxnodes = -1, /* maximum number of live nodes in a table */ + nonempty = 0; /* number of tables with live nodes */ + + /* Print header. */ +#if SIZEOF_VOID_P == 8 + retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n", + (unsigned long) dd); +#else + retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n", + (unsigned) dd); +#endif + if (retval == EOF) return 0; + + /* Print number of live nodes for each nonempty table. */ + for (i=0; iout,"%5d: %5d nodes\n", i, nodes); + if (retval == EOF) return 0; + if (nodes > maxnodes) { + maxnodes = nodes; + largest = i; + } + } + } + + nodes = dd->constants.keys - dd->constants.dead; + if (nodes) { + nonempty++; + retval = fprintf(dd->out,"const: %5d nodes\n", nodes); + if (retval == EOF) return 0; + if (nodes > maxnodes) { + maxnodes = nodes; + largest = CUDD_CONST_INDEX; + } + } + + /* Print summary. */ + retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ", + ntables+1, nonempty, largest); + if (retval == EOF) return 0; + retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes); + if (retval == EOF) return 0; + + return(1); + +} /* end of cuddHeapProfile */ + + +/**Function******************************************************************** + + Synopsis [Prints out information on a node.] + + Description [Prints out information on a node.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +cuddPrintNode( + DdNode * f, + FILE *fp) +{ + f = Cudd_Regular(f); +#if SIZEOF_VOID_P == 8 + (void) fprintf(fp," node 0x%lx, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n",(unsigned long)f,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f)); +#else + (void) fprintf(fp," node 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",(unsigned)f,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f)); +#endif + +} /* end of cuddPrintNode */ + + + +/**Function******************************************************************** + + Synopsis [Prints the variable groups as a parenthesized list.] + + Description [Prints the variable groups as a parenthesized list. + For each group the level range that it represents is printed. After + each group, the group's flags are printed, preceded by a `|'. For + each flag (except MTR_TERMINAL) a character is printed. +
    +
  • F: MTR_FIXED +
  • N: MTR_NEWNODE +
  • S: MTR_SOFT +
+ The second argument, silent, if different from 0, causes + Cudd_PrintVarGroups to only check the syntax of the group tree.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +cuddPrintVarGroups( + DdManager * dd /* manager */, + MtrNode * root /* root of the group tree */, + int zdd /* 0: BDD; 1: ZDD */, + int silent /* flag to check tree syntax only */) +{ + MtrNode *node; + int level; + + assert(root != NULL); + assert(root->younger == NULL || root->younger->elder == root); + assert(root->elder == NULL || root->elder->younger == root); + if (zdd) { + level = dd->permZ[root->index]; + } else { + level = dd->perm[root->index]; + } + if (!silent) (void) printf("(%d",level); + if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) { + if (!silent) (void) printf(","); + } else { + node = root->child; + while (node != NULL) { + assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size)); + assert(node->parent == root); + cuddPrintVarGroups(dd,node,zdd,silent); + node = node->younger; + } + } + if (!silent) { + (void) printf("%d", level + root->size - 1); + if (root->flags != MTR_DEFAULT) { + (void) printf("|"); + if (MTR_TEST(root,MTR_FIXED)) (void) printf("F"); + if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N"); + if (MTR_TEST(root,MTR_SOFT)) (void) printf("S"); + } + (void) printf(")"); + if (root->parent == NULL) (void) printf("\n"); + } + assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0); + return; + +} /* end of cuddPrintVarGroups */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Searches the subtables above node for its parents.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +debugFindParent( + DdManager * table, + DdNode * node) +{ + int i,j; + int slots; + DdNodePtr *nodelist; + DdNode *f; + + for (i = 0; i < cuddI(table,node->index); i++) { + nodelist = table->subtables[i].nodelist; + slots = table->subtables[i].slots; + + for (j=0;jout,"parent is at 0x%lx, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n", + (unsigned long)f,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f)); +#else + (void) fprintf(table->out,"parent is at 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n", + (unsigned)f,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f)); +#endif + } + f = f->next; + } + } + } + +} /* end of debugFindParent */ + + +#if 0 +/**Function******************************************************************** + + Synopsis [Reports an error if a (dead) node has a non-dead parent.] + + Description [Searches all the subtables above node. Very expensive. + The same check is now implemented more efficiently in ddDebugCheck.] + + SideEffects [None] + + SeeAlso [debugFindParent] + +******************************************************************************/ +static void +debugCheckParent( + DdManager * table, + DdNode * node) +{ + int i,j; + int slots; + DdNode **nodelist,*f; + + for (i = 0; i < cuddI(table,node->index); i++) { + nodelist = table->subtables[i].nodelist; + slots = table->subtables[i].slots; + + for (j=0;jref != 0) { + (void) fprintf(table->err, + "error with zero ref count\n"); + (void) fprintf(table->err,"parent is 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",f,f->index,f->ref,cuddT(f),cuddE(f)); + (void) fprintf(table->err,"child is 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",node,node->index,node->ref,cuddT(node),cuddE(node)); + } + f = f->next; + } + } + } +} +#endif diff --git a/abc70930/src/bdd/cudd/cuddClip.c b/abc70930/src/bdd/cudd/cuddClip.c new file mode 100644 index 00000000..4da296ef --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddClip.c @@ -0,0 +1,531 @@ +/**CFile*********************************************************************** + + FileName [cuddClip.c] + + PackageName [cudd] + + Synopsis [Clipping functions.] + + Description [External procedures included in this module: +
    +
  • Cudd_bddClippingAnd() +
  • Cudd_bddClippingAndAbstract() +
+ Internal procedures included in this module: +
    +
  • cuddBddClippingAnd() +
  • cuddBddClippingAndAbstract() +
+ Static procedures included in this module: +
    +
  • cuddBddClippingAndRecur() +
  • cuddBddClipAndAbsRecur() +
+ + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddClip.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * cuddBddClippingAndRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, int distance, int direction)); +static DdNode * cuddBddClipAndAbsRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube, int distance, int direction)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Approximates the conjunction of two BDDs f and g.] + + Description [Approximates the conjunction of two BDDs f and g. Returns a + pointer to the resulting BDD if successful; NULL if the intermediate + result blows up.] + + SideEffects [None] + + SeeAlso [Cudd_bddAnd] + +******************************************************************************/ +DdNode * +Cudd_bddClippingAnd( + DdManager * dd /* manager */, + DdNode * f /* first conjunct */, + DdNode * g /* second conjunct */, + int maxDepth /* maximum recursion depth */, + int direction /* under (0) or over (1) approximation */) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddClippingAnd(dd,f,g,maxDepth,direction); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddClippingAnd */ + + +/**Function******************************************************************** + + Synopsis [Approximates the conjunction of two BDDs f and g and + simultaneously abstracts the variables in cube.] + + Description [Approximates the conjunction of two BDDs f and g and + simultaneously abstracts the variables in cube. The variables are + existentially abstracted. Returns a pointer to the resulting BDD if + successful; NULL if the intermediate result blows up.] + + SideEffects [None] + + SeeAlso [Cudd_bddAndAbstract Cudd_bddClippingAnd] + +******************************************************************************/ +DdNode * +Cudd_bddClippingAndAbstract( + DdManager * dd /* manager */, + DdNode * f /* first conjunct */, + DdNode * g /* second conjunct */, + DdNode * cube /* cube of variables to be abstracted */, + int maxDepth /* maximum recursion depth */, + int direction /* under (0) or over (1) approximation */) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddClippingAndAbstract(dd,f,g,cube,maxDepth,direction); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddClippingAndAbstract */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Approximates the conjunction of two BDDs f and g.] + + Description [Approximates the conjunction of two BDDs f and g. Returns a + pointer to the resulting BDD if successful; NULL if the intermediate + result blows up.] + + SideEffects [None] + + SeeAlso [Cudd_bddClippingAnd] + +******************************************************************************/ +DdNode * +cuddBddClippingAnd( + DdManager * dd /* manager */, + DdNode * f /* first conjunct */, + DdNode * g /* second conjunct */, + int maxDepth /* maximum recursion depth */, + int direction /* under (0) or over (1) approximation */) +{ + DdNode *res; + + res = cuddBddClippingAndRecur(dd,f,g,maxDepth,direction); + + return(res); + +} /* end of cuddBddClippingAnd */ + + +/**Function******************************************************************** + + Synopsis [Approximates the conjunction of two BDDs f and g and + simultaneously abstracts the variables in cube.] + + Description [Approximates the conjunction of two BDDs f and g and + simultaneously abstracts the variables in cube. Returns a + pointer to the resulting BDD if successful; NULL if the intermediate + result blows up.] + + SideEffects [None] + + SeeAlso [Cudd_bddClippingAndAbstract] + +******************************************************************************/ +DdNode * +cuddBddClippingAndAbstract( + DdManager * dd /* manager */, + DdNode * f /* first conjunct */, + DdNode * g /* second conjunct */, + DdNode * cube /* cube of variables to be abstracted */, + int maxDepth /* maximum recursion depth */, + int direction /* under (0) or over (1) approximation */) +{ + DdNode *res; + + res = cuddBddClipAndAbsRecur(dd,f,g,cube,maxDepth,direction); + + return(res); + +} /* end of cuddBddClippingAndAbstract */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_bddClippingAnd.] + + Description [Implements the recursive step of Cudd_bddClippingAnd by taking + the conjunction of two BDDs. Returns a pointer to the result is + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddBddClippingAnd] + +******************************************************************************/ +static DdNode * +cuddBddClippingAndRecur( + DdManager * manager, + DdNode * f, + DdNode * g, + int distance, + int direction) +{ + DdNode *F, *ft, *fe, *G, *gt, *ge; + DdNode *one, *zero, *r, *t, *e; + unsigned int topf, topg, index; + DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Terminal cases. */ + if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); + if (f == g || g == one) return(f); + if (f == one) return(g); + if (distance == 0) { + /* One last attempt at returning the right result. We sort of + ** cheat by calling Cudd_bddLeq. */ + if (Cudd_bddLeq(manager,f,g)) return(f); + if (Cudd_bddLeq(manager,g,f)) return(g); + if (direction == 1) { + if (Cudd_bddLeq(manager,f,Cudd_Not(g)) || + Cudd_bddLeq(manager,g,Cudd_Not(f))) return(zero); + } + return(Cudd_NotCond(one,(direction == 0))); + } + + /* At this point f and g are not constant. */ + distance--; + + /* Check cache. Try to increase cache efficiency by sorting the + ** pointers. */ + if (f > g) { + DdNode *tmp = f; + f = g; g = tmp; + } + F = Cudd_Regular(f); + G = Cudd_Regular(g); + cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) + (direction ? Cudd_bddClippingAnd : cuddBddClippingAnd); + if (F->ref != 1 || G->ref != 1) { + r = cuddCacheLookup2(manager, cacheOp, f, g); + if (r != NULL) return(r); + } + + /* Here we can skip the use of cuddI, because the operands are known + ** to be non-constant. + */ + topf = manager->perm[F->index]; + topg = manager->perm[G->index]; + + /* Compute cofactors. */ + if (topf <= topg) { + index = F->index; + ft = cuddT(F); + fe = cuddE(F); + if (Cudd_IsComplement(f)) { + ft = Cudd_Not(ft); + fe = Cudd_Not(fe); + } + } else { + index = G->index; + ft = fe = f; + } + + if (topg <= topf) { + gt = cuddT(G); + ge = cuddE(G); + if (Cudd_IsComplement(g)) { + gt = Cudd_Not(gt); + ge = Cudd_Not(ge); + } + } else { + gt = ge = g; + } + + t = cuddBddClippingAndRecur(manager, ft, gt, distance, direction); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddBddClippingAndRecur(manager, fe, ge, distance, direction); + if (e == NULL) { + Cudd_RecursiveDeref(manager, t); + return(NULL); + } + cuddRef(e); + + if (t == e) { + r = t; + } else { + if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); + if (r == NULL) { + Cudd_RecursiveDeref(manager, t); + Cudd_RecursiveDeref(manager, e); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(manager,(int)index,t,e); + if (r == NULL) { + Cudd_RecursiveDeref(manager, t); + Cudd_RecursiveDeref(manager, e); + return(NULL); + } + } + } + cuddDeref(e); + cuddDeref(t); + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert2(manager, cacheOp, f, g, r); + return(r); + +} /* end of cuddBddClippingAndRecur */ + + +/**Function******************************************************************** + + Synopsis [Approximates the AND of two BDDs and simultaneously abstracts the + variables in cube.] + + Description [Approximates the AND of two BDDs and simultaneously + abstracts the variables in cube. The variables are existentially + abstracted. Returns a pointer to the result is successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddClippingAndAbstract] + +******************************************************************************/ +static DdNode * +cuddBddClipAndAbsRecur( + DdManager * manager, + DdNode * f, + DdNode * g, + DdNode * cube, + int distance, + int direction) +{ + DdNode *F, *ft, *fe, *G, *gt, *ge; + DdNode *one, *zero, *r, *t, *e, *Cube; + unsigned int topf, topg, topcube, top, index; + ptruint cacheTag; + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Terminal cases. */ + if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); + if (f == one && g == one) return(one); + if (cube == one) { + return(cuddBddClippingAndRecur(manager, f, g, distance, direction)); + } + if (f == one || f == g) { + return (cuddBddExistAbstractRecur(manager, g, cube)); + } + if (g == one) { + return (cuddBddExistAbstractRecur(manager, f, cube)); + } + if (distance == 0) return(Cudd_NotCond(one,(direction == 0))); + + /* At this point f, g, and cube are not constant. */ + distance--; + + /* Check cache. */ + if (f > g) { /* Try to increase cache efficiency. */ + DdNode *tmp = f; + f = g; g = tmp; + } + F = Cudd_Regular(f); + G = Cudd_Regular(g); + cacheTag = direction ? DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG : + DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG; + if (F->ref != 1 || G->ref != 1) { + r = cuddCacheLookup(manager, cacheTag, + f, g, cube); + if (r != NULL) { + return(r); + } + } + + /* Here we can skip the use of cuddI, because the operands are known + ** to be non-constant. + */ + topf = manager->perm[F->index]; + topg = manager->perm[G->index]; + top = ddMin(topf, topg); + topcube = manager->perm[cube->index]; + + if (topcube < top) { + return(cuddBddClipAndAbsRecur(manager, f, g, cuddT(cube), + distance, direction)); + } + /* Now, topcube >= top. */ + + if (topf == top) { + index = F->index; + ft = cuddT(F); + fe = cuddE(F); + if (Cudd_IsComplement(f)) { + ft = Cudd_Not(ft); + fe = Cudd_Not(fe); + } + } else { + index = G->index; + ft = fe = f; + } + + if (topg == top) { + gt = cuddT(G); + ge = cuddE(G); + if (Cudd_IsComplement(g)) { + gt = Cudd_Not(gt); + ge = Cudd_Not(ge); + } + } else { + gt = ge = g; + } + + if (topcube == top) { + Cube = cuddT(cube); + } else { + Cube = cube; + } + + t = cuddBddClipAndAbsRecur(manager, ft, gt, Cube, distance, direction); + if (t == NULL) return(NULL); + + /* Special case: 1 OR anything = 1. Hence, no need to compute + ** the else branch if t is 1. + */ + if (t == one && topcube == top) { + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert(manager, cacheTag, f, g, cube, one); + return(one); + } + cuddRef(t); + + e = cuddBddClipAndAbsRecur(manager, fe, ge, Cube, distance, direction); + if (e == NULL) { + Cudd_RecursiveDeref(manager, t); + return(NULL); + } + cuddRef(e); + + if (topcube == top) { /* abstract */ + r = cuddBddClippingAndRecur(manager, Cudd_Not(t), Cudd_Not(e), + distance, (direction == 0)); + if (r == NULL) { + Cudd_RecursiveDeref(manager, t); + Cudd_RecursiveDeref(manager, e); + return(NULL); + } + r = Cudd_Not(r); + cuddRef(r); + Cudd_RecursiveDeref(manager, t); + Cudd_RecursiveDeref(manager, e); + cuddDeref(r); + } else if (t == e) { + r = t; + cuddDeref(t); + cuddDeref(e); + } else { + if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); + if (r == NULL) { + Cudd_RecursiveDeref(manager, t); + Cudd_RecursiveDeref(manager, e); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(manager,(int)index,t,e); + if (r == NULL) { + Cudd_RecursiveDeref(manager, t); + Cudd_RecursiveDeref(manager, e); + return(NULL); + } + } + cuddDeref(e); + cuddDeref(t); + } + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert(manager, cacheTag, f, g, cube, r); + return (r); + +} /* end of cuddBddClipAndAbsRecur */ + diff --git a/abc70930/src/bdd/cudd/cuddCof.c b/abc70930/src/bdd/cudd/cuddCof.c new file mode 100644 index 00000000..f79e3f91 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddCof.c @@ -0,0 +1,300 @@ +/**CFile*********************************************************************** + + FileName [cuddCof.c] + + PackageName [cudd] + + Synopsis [Cofactoring functions.] + + Description [External procedures included in this module: +
    +
  • Cudd_Cofactor() +
+ Internal procedures included in this module: +
    +
  • cuddGetBranches() +
  • cuddCheckCube() +
  • cuddCofactorRecur() +
+ ] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddCof.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes the cofactor of f with respect to g.] + + Description [Computes the cofactor of f with respect to g; g must be + the BDD or the ADD of a cube. Returns a pointer to the cofactor if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddConstrain Cudd_bddRestrict] + +******************************************************************************/ +DdNode * +Cudd_Cofactor( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res,*zero; + + zero = Cudd_Not(DD_ONE(dd)); + if (g == zero || g == DD_ZERO(dd)) { + (void) fprintf(dd->err,"Cudd_Cofactor: Invalid restriction 1\n"); + dd->errorCode = CUDD_INVALID_ARG; + return(NULL); + } + do { + dd->reordered = 0; + res = cuddCofactorRecur(dd,f,g); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_Cofactor */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes the children of g.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +cuddGetBranches( + DdNode * g, + DdNode ** g1, + DdNode ** g0) +{ + DdNode *G = Cudd_Regular(g); + + *g1 = cuddT(G); + *g0 = cuddE(G); + if (Cudd_IsComplement(g)) { + *g1 = Cudd_Not(*g1); + *g0 = Cudd_Not(*g0); + } + +} /* end of cuddGetBranches */ + + +/**Function******************************************************************** + + Synopsis [Checks whether g is the BDD of a cube.] + + Description [Checks whether g is the BDD of a cube. Returns 1 in case + of success; 0 otherwise. The constant 1 is a valid cube, but all other + constant functions cause cuddCheckCube to return 0.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddCheckCube( + DdManager * dd, + DdNode * g) +{ + DdNode *g1,*g0,*one,*zero; + + one = DD_ONE(dd); + if (g == one) return(1); + if (Cudd_IsConstant(g)) return(0); + + zero = Cudd_Not(one); + cuddGetBranches(g,&g1,&g0); + + if (g0 == zero) { + return(cuddCheckCube(dd, g1)); + } + if (g1 == zero) { + return(cuddCheckCube(dd, g0)); + } + return(0); + +} /* end of cuddCheckCube */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_Cofactor.] + + Description [Performs the recursive step of Cudd_Cofactor. Returns a + pointer to the cofactor if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_Cofactor] + +******************************************************************************/ +DdNode * +cuddCofactorRecur( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r; + unsigned int topf,topg; + int comple; + + statLine(dd); + F = Cudd_Regular(f); + if (cuddIsConstant(F)) return(f); + + one = DD_ONE(dd); + + /* The invariant g != 0 is true on entry to this procedure and is + ** recursively maintained by it. Therefore it suffices to test g + ** against one to make sure it is not constant. + */ + if (g == one) return(f); + /* From now on, f and g are known not to be constants. */ + + comple = f != F; + r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g); + if (r != NULL) { + return(Cudd_NotCond(r,comple)); + } + + topf = dd->perm[F->index]; + G = Cudd_Regular(g); + topg = dd->perm[G->index]; + + /* We take the cofactors of F because we are going to rely on + ** the fact that the cofactors of the complement are the complements + ** of the cofactors to better utilize the cache. Variable comple + ** remembers whether we have to complement the result or not. + */ + if (topf <= topg) { + f1 = cuddT(F); f0 = cuddE(F); + } else { + f1 = f0 = F; + } + if (topg <= topf) { + g1 = cuddT(G); g0 = cuddE(G); + if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); } + } else { + g1 = g0 = g; + } + + zero = Cudd_Not(one); + if (topf >= topg) { + if (g0 == zero || g0 == DD_ZERO(dd)) { + r = cuddCofactorRecur(dd, f1, g1); + } else if (g1 == zero || g1 == DD_ZERO(dd)) { + r = cuddCofactorRecur(dd, f0, g0); + } else { + (void) fprintf(dd->out, + "Cudd_Cofactor: Invalid restriction 2\n"); + dd->errorCode = CUDD_INVALID_ARG; + return(NULL); + } + if (r == NULL) return(NULL); + } else /* if (topf < topg) */ { + t = cuddCofactorRecur(dd, f1, g); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddCofactorRecur(dd, f0, g); + if (e == NULL) { + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + cuddRef(e); + + if (t == e) { + r = t; + } else if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e)); + if (r != NULL) + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(dd,(int)F->index,t,e); + } + if (r == NULL) { + Cudd_RecursiveDeref(dd ,e); + Cudd_RecursiveDeref(dd ,t); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + } + + cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r); + + return(Cudd_NotCond(r,comple)); + +} /* end of cuddCofactorRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/cudd/cuddCompose.c b/abc70930/src/bdd/cudd/cuddCompose.c new file mode 100644 index 00000000..8c858051 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddCompose.c @@ -0,0 +1,1722 @@ +/**CFile*********************************************************************** + + FileName [cuddCompose.c] + + PackageName [cudd] + + Synopsis [Functional composition and variable permutation of DDs.] + + Description [External procedures included in this module: +
    +
  • Cudd_bddCompose() +
  • Cudd_addCompose() +
  • Cudd_addPermute() +
  • Cudd_addSwapVariables() +
  • Cudd_bddPermute() +
  • Cudd_bddVarMap() +
  • Cudd_SetVarMap() +
  • Cudd_bddSwapVariables() +
  • Cudd_bddAdjPermuteX() +
  • Cudd_addVectorCompose() +
  • Cudd_addGeneralVectorCompose() +
  • Cudd_addNonSimCompose() +
  • Cudd_bddVectorCompose() +
+ Internal procedures included in this module: +
    +
  • cuddBddComposeRecur() +
  • cuddAddComposeRecur() +
+ Static procedures included in this module: +
    +
  • cuddAddPermuteRecur() +
  • cuddBddPermuteRecur() +
  • cuddBddVarMapRecur() +
  • cuddAddVectorComposeRecur() +
  • cuddAddGeneralVectorComposeRecur() +
  • cuddAddNonSimComposeRecur() +
  • cuddBddVectorComposeRecur() +
  • ddIsIthAddVar() +
  • ddIsIthAddVarPair() +
+ The permutation functions use a local cache because the results to + be remembered depend on the permutation being applied. Since the + permutation is just an array, it cannot be stored in the global + cache. There are different procedured for BDDs and ADDs. This is + because bddPermuteRecur uses cuddBddIteRecur. If this were changed, + the procedures could be merged.] + + Author [Fabio Somenzi and Kavita Ravi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddCompose.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +#ifdef DD_DEBUG +static int addPermuteRecurHits; +static int bddPermuteRecurHits; +static int bddVectorComposeHits; +static int addVectorComposeHits; + +static int addGeneralVectorComposeHits; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * cuddAddPermuteRecur ARGS((DdManager *manager, DdHashTable *table, DdNode *node, int *permut)); +static DdNode * cuddBddPermuteRecur ARGS((DdManager *manager, DdHashTable *table, DdNode *node, int *permut)); +static DdNode * cuddBddVarMapRecur ARGS((DdManager *manager, DdNode *f)); +static DdNode * cuddAddVectorComposeRecur ARGS((DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest)); +static DdNode * cuddAddNonSimComposeRecur ARGS((DdManager *dd, DdNode *f, DdNode **vector, DdNode *key, DdNode *cube, int lastsub)); +static DdNode * cuddBddVectorComposeRecur ARGS((DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest)); +DD_INLINE static int ddIsIthAddVar ARGS((DdManager *dd, DdNode *f, unsigned int i)); + +static DdNode * cuddAddGeneralVectorComposeRecur ARGS((DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vectorOn, DdNode **vectorOff, int deepest)); +DD_INLINE static int ddIsIthAddVarPair ARGS((DdManager *dd, DdNode *f, DdNode *g, unsigned int i)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Substitutes g for x_v in the BDD for f.] + + Description [Substitutes g for x_v in the BDD for f. v is the index of the + variable to be substituted. Cudd_bddCompose passes the corresponding + projection function to the recursive procedure, so that the cache may + be used. Returns the composed BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addCompose] + +******************************************************************************/ +DdNode * +Cudd_bddCompose( + DdManager * dd, + DdNode * f, + DdNode * g, + int v) +{ + DdNode *proj, *res; + + /* Sanity check. */ + if (v < 0 || v > dd->size) return(NULL); + + proj = dd->vars[v]; + do { + dd->reordered = 0; + res = cuddBddComposeRecur(dd,f,g,proj); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddCompose */ + + +/**Function******************************************************************** + + Synopsis [Substitutes g for x_v in the ADD for f.] + + Description [Substitutes g for x_v in the ADD for f. v is the index of the + variable to be substituted. g must be a 0-1 ADD. Cudd_bddCompose passes + the corresponding projection function to the recursive procedure, so + that the cache may be used. Returns the composed ADD if successful; + NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddCompose] + +******************************************************************************/ +DdNode * +Cudd_addCompose( + DdManager * dd, + DdNode * f, + DdNode * g, + int v) +{ + DdNode *proj, *res; + + /* Sanity check. */ + if (v < 0 || v > dd->size) return(NULL); + + proj = dd->vars[v]; + do { + dd->reordered = 0; + res = cuddAddComposeRecur(dd,f,g,proj); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addCompose */ + + +/**Function******************************************************************** + + Synopsis [Permutes the variables of an ADD.] + + Description [Given a permutation in array permut, creates a new ADD + with permuted variables. There should be an entry in array permut + for each variable in the manager. The i-th entry of permut holds the + index of the variable that is to substitute the i-th + variable. Returns a pointer to the resulting ADD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddPermute Cudd_addSwapVariables] + +******************************************************************************/ +DdNode * +Cudd_addPermute( + DdManager * manager, + DdNode * node, + int * permut) +{ + DdHashTable *table; + DdNode *res; + + do { + manager->reordered = 0; + table = cuddHashTableInit(manager,1,2); + if (table == NULL) return(NULL); + /* Recursively solve the problem. */ + res = cuddAddPermuteRecur(manager,table,node,permut); + if (res != NULL) cuddRef(res); + /* Dispose of local cache. */ + cuddHashTableQuit(table); + } while (manager->reordered == 1); + + if (res != NULL) cuddDeref(res); + return(res); + +} /* end of Cudd_addPermute */ + + +/**Function******************************************************************** + + Synopsis [Swaps two sets of variables of the same size (x and y) in + the ADD f.] + + Description [Swaps two sets of variables of the same size (x and y) in + the ADD f. The size is given by n. The two sets of variables are + assumed to be disjoint. Returns a pointer to the resulting ADD if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] + +******************************************************************************/ +DdNode * +Cudd_addSwapVariables( + DdManager * dd, + DdNode * f, + DdNode ** x, + DdNode ** y, + int n) +{ + DdNode *swapped; + int i, j, k; + int *permut; + + permut = ALLOC(int,dd->size); + if (permut == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < dd->size; i++) permut[i] = i; + for (i = 0; i < n; i++) { + j = x[i]->index; + k = y[i]->index; + permut[j] = k; + permut[k] = j; + } + + swapped = Cudd_addPermute(dd,f,permut); + FREE(permut); + + return(swapped); + +} /* end of Cudd_addSwapVariables */ + + +/**Function******************************************************************** + + Synopsis [Permutes the variables of a BDD.] + + Description [Given a permutation in array permut, creates a new BDD + with permuted variables. There should be an entry in array permut + for each variable in the manager. The i-th entry of permut holds the + index of the variable that is to substitute the i-th variable. + Returns a pointer to the resulting BDD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] + +******************************************************************************/ +DdNode * +Cudd_bddPermute( + DdManager * manager, + DdNode * node, + int * permut) +{ + DdHashTable *table; + DdNode *res; + + do { + manager->reordered = 0; + table = cuddHashTableInit(manager,1,2); + if (table == NULL) return(NULL); + res = cuddBddPermuteRecur(manager,table,node,permut); + if (res != NULL) cuddRef(res); + /* Dispose of local cache. */ + cuddHashTableQuit(table); + + } while (manager->reordered == 1); + + if (res != NULL) cuddDeref(res); + return(res); + +} /* end of Cudd_bddPermute */ + + +/**Function******************************************************************** + + Synopsis [Remaps the variables of a BDD using the default variable map.] + + Description [Remaps the variables of a BDD using the default + variable map. A typical use of this function is to swap two sets of + variables. The variable map must be registered with Cudd_SetVarMap. + Returns a pointer to the resulting BDD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddPermute Cudd_bddSwapVariables Cudd_SetVarMap] + +******************************************************************************/ +DdNode * +Cudd_bddVarMap( + DdManager * manager /* DD manager */, + DdNode * f /* function in which to remap variables */) +{ + DdNode *res; + + if (manager->map == NULL) return(NULL); + do { + manager->reordered = 0; + res = cuddBddVarMapRecur(manager, f); + } while (manager->reordered == 1); + + return(res); + +} /* end of Cudd_bddVarMap */ + + +/**Function******************************************************************** + + Synopsis [Registers a variable mapping with the manager.] + + Description [Registers with the manager a variable mapping described + by two sets of variables. This variable mapping is then used by + functions like Cudd_bddVarMap. This function is convenient for + those applications that perform the same mapping several times. + However, if several different permutations are used, it may be more + efficient not to rely on the registered mapping, because changing + mapping causes the cache to be cleared. (The initial setting, + however, does not clear the cache.) The two sets of variables (x and + y) must have the same size (x and y). The size is given by n. The + two sets of variables are normally disjoint, but this restriction is + not imposeded by the function. When new variables are created, the + map is automatically extended (each new variable maps to + itself). The typical use, however, is to wait until all variables + are created, and then create the map. Returns 1 if the mapping is + successfully registered with the manager; 0 otherwise.] + + SideEffects [Modifies the manager. May clear the cache.] + + SeeAlso [Cudd_bddVarMap Cudd_bddPermute Cudd_bddSwapVariables] + +******************************************************************************/ +int +Cudd_SetVarMap ( + DdManager *manager /* DD manager */, + DdNode **x /* first array of variables */, + DdNode **y /* second array of variables */, + int n /* length of both arrays */) +{ + int i; + + if (manager->map != NULL) { + cuddCacheFlush(manager); + } else { + manager->map = ALLOC(int,manager->maxSize); + if (manager->map == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + return(0); + } + manager->memused += sizeof(int) * manager->maxSize; + } + /* Initialize the map to the identity. */ + for (i = 0; i < manager->size; i++) { + manager->map[i] = i; + } + /* Create the map. */ + for (i = 0; i < n; i++) { + manager->map[x[i]->index] = y[i]->index; + manager->map[y[i]->index] = x[i]->index; + } + return(1); + +} /* end of Cudd_SetVarMap */ + + +/**Function******************************************************************** + + Synopsis [Swaps two sets of variables of the same size (x and y) in + the BDD f.] + + Description [Swaps two sets of variables of the same size (x and y) + in the BDD f. The size is given by n. The two sets of variables are + assumed to be disjoint. Returns a pointer to the resulting BDD if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddPermute Cudd_addSwapVariables] + +******************************************************************************/ +DdNode * +Cudd_bddSwapVariables( + DdManager * dd, + DdNode * f, + DdNode ** x, + DdNode ** y, + int n) +{ + DdNode *swapped; + int i, j, k; + int *permut; + + permut = ALLOC(int,dd->size); + if (permut == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < dd->size; i++) permut[i] = i; + for (i = 0; i < n; i++) { + j = x[i]->index; + k = y[i]->index; + permut[j] = k; + permut[k] = j; + } + + swapped = Cudd_bddPermute(dd,f,permut); + FREE(permut); + + return(swapped); + +} /* end of Cudd_bddSwapVariables */ + + +/**Function******************************************************************** + + Synopsis [Rearranges a set of variables in the BDD B.] + + Description [Rearranges a set of variables in the BDD B. The size of + the set is given by n. This procedure is intended for the + `randomization' of the priority functions. Returns a pointer to the + BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddPermute Cudd_bddSwapVariables + Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_PrioritySelect] + +******************************************************************************/ +DdNode * +Cudd_bddAdjPermuteX( + DdManager * dd, + DdNode * B, + DdNode ** x, + int n) +{ + DdNode *swapped; + int i, j, k; + int *permut; + + permut = ALLOC(int,dd->size); + if (permut == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < dd->size; i++) permut[i] = i; + for (i = 0; i < n-2; i += 3) { + j = x[i]->index; + k = x[i+1]->index; + permut[j] = k; + permut[k] = j; + } + + swapped = Cudd_bddPermute(dd,B,permut); + FREE(permut); + + return(swapped); + +} /* end of Cudd_bddAdjPermuteX */ + + +/**Function******************************************************************** + + Synopsis [Composes an ADD with a vector of 0-1 ADDs.] + + Description [Given a vector of 0-1 ADDs, creates a new ADD by + substituting the 0-1 ADDs for the variables of the ADD f. There + should be an entry in vector for each variable in the manager. + If no substitution is sought for a given variable, the corresponding + projection function should be specified in the vector. + This function implements simultaneous composition. + Returns a pointer to the resulting ADD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addNonSimCompose Cudd_addPermute Cudd_addCompose + Cudd_bddVectorCompose] + +******************************************************************************/ +DdNode * +Cudd_addVectorCompose( + DdManager * dd, + DdNode * f, + DdNode ** vector) +{ + DdHashTable *table; + DdNode *res; + int deepest; + int i; + + do { + dd->reordered = 0; + /* Initialize local cache. */ + table = cuddHashTableInit(dd,1,2); + if (table == NULL) return(NULL); + + /* Find deepest real substitution. */ + for (deepest = dd->size - 1; deepest >= 0; deepest--) { + i = dd->invperm[deepest]; + if (!ddIsIthAddVar(dd,vector[i],i)) { + break; + } + } + + /* Recursively solve the problem. */ + res = cuddAddVectorComposeRecur(dd,table,f,vector,deepest); + if (res != NULL) cuddRef(res); + + /* Dispose of local cache. */ + cuddHashTableQuit(table); + } while (dd->reordered == 1); + + if (res != NULL) cuddDeref(res); + return(res); + +} /* end of Cudd_addVectorCompose */ + + +/**Function******************************************************************** + + Synopsis [Composes an ADD with a vector of ADDs.] + + Description [Given a vector of ADDs, creates a new ADD by substituting the + ADDs for the variables of the ADD f. vectorOn contains ADDs to be substituted + for the x_v and vectorOff the ADDs to be substituted for x_v'. There should + be an entry in vector for each variable in the manager. If no substitution + is sought for a given variable, the corresponding projection function should + be specified in the vector. This function implements simultaneous + composition. Returns a pointer to the resulting ADD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addVectorCompose Cudd_addNonSimCompose Cudd_addPermute + Cudd_addCompose Cudd_bddVectorCompose] + +******************************************************************************/ +DdNode * +Cudd_addGeneralVectorCompose( + DdManager * dd, + DdNode * f, + DdNode ** vectorOn, + DdNode ** vectorOff) +{ + DdHashTable *table; + DdNode *res; + int deepest; + int i; + + do { + dd->reordered = 0; + /* Initialize local cache. */ + table = cuddHashTableInit(dd,1,2); + if (table == NULL) return(NULL); + + /* Find deepest real substitution. */ + for (deepest = dd->size - 1; deepest >= 0; deepest--) { + i = dd->invperm[deepest]; + if (!ddIsIthAddVarPair(dd,vectorOn[i],vectorOff[i],i)) { + break; + } + } + + /* Recursively solve the problem. */ + res = cuddAddGeneralVectorComposeRecur(dd,table,f,vectorOn, + vectorOff,deepest); + if (res != NULL) cuddRef(res); + + /* Dispose of local cache. */ + cuddHashTableQuit(table); + } while (dd->reordered == 1); + + if (res != NULL) cuddDeref(res); + return(res); + +} /* end of Cudd_addGeneralVectorCompose */ + + +/**Function******************************************************************** + + Synopsis [Composes an ADD with a vector of 0-1 ADDs.] + + Description [Given a vector of 0-1 ADDs, creates a new ADD by + substituting the 0-1 ADDs for the variables of the ADD f. There + should be an entry in vector for each variable in the manager. + This function implements non-simultaneous composition. If any of the + functions being composed depends on any of the variables being + substituted, then the result depends on the order of composition, + which in turn depends on the variable order: The variables farther from + the roots in the order are substituted first. + Returns a pointer to the resulting ADD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addVectorCompose Cudd_addPermute Cudd_addCompose] + +******************************************************************************/ +DdNode * +Cudd_addNonSimCompose( + DdManager * dd, + DdNode * f, + DdNode ** vector) +{ + DdNode *cube, *key, *var, *tmp, *piece; + DdNode *res; + int i, lastsub; + + /* The cache entry for this function is composed of three parts: + ** f itself, the replacement relation, and the cube of the + ** variables being substituted. + ** The replacement relation is the product of the terms (yi EXNOR gi). + ** This apporach allows us to use the global cache for this function, + ** with great savings in memory with respect to using arrays for the + ** cache entries. + ** First we build replacement relation and cube of substituted + ** variables from the vector specifying the desired composition. + */ + key = DD_ONE(dd); + cuddRef(key); + cube = DD_ONE(dd); + cuddRef(cube); + for (i = (int) dd->size - 1; i >= 0; i--) { + if (ddIsIthAddVar(dd,vector[i],(unsigned int)i)) { + continue; + } + var = Cudd_addIthVar(dd,i); + if (var == NULL) { + Cudd_RecursiveDeref(dd,key); + Cudd_RecursiveDeref(dd,cube); + return(NULL); + } + cuddRef(var); + /* Update cube. */ + tmp = Cudd_addApply(dd,Cudd_addTimes,var,cube); + if (tmp == NULL) { + Cudd_RecursiveDeref(dd,key); + Cudd_RecursiveDeref(dd,cube); + Cudd_RecursiveDeref(dd,var); + return(NULL); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,cube); + cube = tmp; + /* Update replacement relation. */ + piece = Cudd_addApply(dd,Cudd_addXnor,var,vector[i]); + if (piece == NULL) { + Cudd_RecursiveDeref(dd,key); + Cudd_RecursiveDeref(dd,var); + return(NULL); + } + cuddRef(piece); + Cudd_RecursiveDeref(dd,var); + tmp = Cudd_addApply(dd,Cudd_addTimes,key,piece); + if (tmp == NULL) { + Cudd_RecursiveDeref(dd,key); + Cudd_RecursiveDeref(dd,piece); + return(NULL); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,key); + Cudd_RecursiveDeref(dd,piece); + key = tmp; + } + + /* Now try composition, until no reordering occurs. */ + do { + /* Find real substitution with largest index. */ + for (lastsub = dd->size - 1; lastsub >= 0; lastsub--) { + if (!ddIsIthAddVar(dd,vector[lastsub],(unsigned int)lastsub)) { + break; + } + } + + /* Recursively solve the problem. */ + dd->reordered = 0; + res = cuddAddNonSimComposeRecur(dd,f,vector,key,cube,lastsub+1); + if (res != NULL) cuddRef(res); + + } while (dd->reordered == 1); + + Cudd_RecursiveDeref(dd,key); + Cudd_RecursiveDeref(dd,cube); + if (res != NULL) cuddDeref(res); + return(res); + +} /* end of Cudd_addNonSimCompose */ + + +/**Function******************************************************************** + + Synopsis [Composes a BDD with a vector of BDDs.] + + Description [Given a vector of BDDs, creates a new BDD by + substituting the BDDs for the variables of the BDD f. There + should be an entry in vector for each variable in the manager. + If no substitution is sought for a given variable, the corresponding + projection function should be specified in the vector. + This function implements simultaneous composition. + Returns a pointer to the resulting BDD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddPermute Cudd_bddCompose Cudd_addVectorCompose] + +******************************************************************************/ +DdNode * +Cudd_bddVectorCompose( + DdManager * dd, + DdNode * f, + DdNode ** vector) +{ + DdHashTable *table; + DdNode *res; + int deepest; + int i; + + do { + dd->reordered = 0; + /* Initialize local cache. */ + table = cuddHashTableInit(dd,1,2); + if (table == NULL) return(NULL); + + /* Find deepest real substitution. */ + for (deepest = dd->size - 1; deepest >= 0; deepest--) { + i = dd->invperm[deepest]; + if (vector[i] != dd->vars[i]) { + break; + } + } + + /* Recursively solve the problem. */ + res = cuddBddVectorComposeRecur(dd,table,f,vector, deepest); + if (res != NULL) cuddRef(res); + + /* Dispose of local cache. */ + cuddHashTableQuit(table); + } while (dd->reordered == 1); + + if (res != NULL) cuddDeref(res); + return(res); + +} /* end of Cudd_bddVectorCompose */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddCompose.] + + Description [Performs the recursive step of Cudd_bddCompose. + Exploits the fact that the composition of f' with g + produces the complement of the composition of f with g to better + utilize the cache. Returns the composed BDD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddCompose] + +******************************************************************************/ +DdNode * +cuddBddComposeRecur( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * proj) +{ + DdNode *F, *G, *f1, *f0, *g1, *g0, *r, *t, *e; + unsigned int v, topf, topg, topindex; + int comple; + + statLine(dd); + v = dd->perm[proj->index]; + F = Cudd_Regular(f); + topf = cuddI(dd,F->index); + + /* Terminal case. Subsumes the test for constant f. */ + if (topf > v) return(f); + + /* We solve the problem for a regular pointer, and then complement + ** the result if the pointer was originally complemented. + */ + comple = Cudd_IsComplement(f); + + /* Check cache. */ + r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj); + if (r != NULL) { + return(Cudd_NotCond(r,comple)); + } + + if (topf == v) { + /* Compose. */ + f1 = cuddT(F); + f0 = cuddE(F); + r = cuddBddIteRecur(dd, g, f1, f0); + if (r == NULL) return(NULL); + } else { + /* Compute cofactors of f and g. Remember the index of the top + ** variable. + */ + G = Cudd_Regular(g); + topg = cuddI(dd,G->index); + if (topf > topg) { + topindex = G->index; + f1 = f0 = F; + } else { + topindex = F->index; + f1 = cuddT(F); + f0 = cuddE(F); + } + if (topg > topf) { + g1 = g0 = g; + } else { + g1 = cuddT(G); + g0 = cuddE(G); + if (g != G) { + g1 = Cudd_Not(g1); + g0 = Cudd_Not(g0); + } + } + /* Recursive step. */ + t = cuddBddComposeRecur(dd, f1, g1, proj); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddBddComposeRecur(dd, f0, g0, proj); + if (e == NULL) { + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + cuddRef(e); + + r = cuddBddIteRecur(dd, dd->vars[topindex], t, e); + if (r == NULL) { + Cudd_IterDerefBdd(dd, t); + Cudd_IterDerefBdd(dd, e); + return(NULL); + } + cuddRef(r); + Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */ + Cudd_IterDerefBdd(dd, e); + cuddDeref(r); + } + + cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r); + + return(Cudd_NotCond(r,comple)); + +} /* end of cuddBddComposeRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addCompose.] + + Description [Performs the recursive step of Cudd_addCompose. + Returns the composed BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addCompose] + +******************************************************************************/ +DdNode * +cuddAddComposeRecur( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * proj) +{ + DdNode *f1, *f0, *g1, *g0, *r, *t, *e; + unsigned int v, topf, topg, topindex; + + statLine(dd); + v = dd->perm[proj->index]; + topf = cuddI(dd,f->index); + + /* Terminal case. Subsumes the test for constant f. */ + if (topf > v) return(f); + + /* Check cache. */ + r = cuddCacheLookup(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj); + if (r != NULL) { + return(r); + } + + if (topf == v) { + /* Compose. */ + f1 = cuddT(f); + f0 = cuddE(f); + r = cuddAddIteRecur(dd, g, f1, f0); + if (r == NULL) return(NULL); + } else { + /* Compute cofactors of f and g. Remember the index of the top + ** variable. + */ + topg = cuddI(dd,g->index); + if (topf > topg) { + topindex = g->index; + f1 = f0 = f; + } else { + topindex = f->index; + f1 = cuddT(f); + f0 = cuddE(f); + } + if (topg > topf) { + g1 = g0 = g; + } else { + g1 = cuddT(g); + g0 = cuddE(g); + } + /* Recursive step. */ + t = cuddAddComposeRecur(dd, f1, g1, proj); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddAddComposeRecur(dd, f0, g0, proj); + if (e == NULL) { + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + cuddRef(e); + + if (t == e) { + r = t; + } else { + r = cuddUniqueInter(dd, (int) topindex, t, e); + if (r == NULL) { + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + } + cuddDeref(t); + cuddDeref(e); + } + + cuddCacheInsert(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj,r); + + return(r); + +} /* end of cuddAddComposeRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_addPermute.] + + Description [ Recursively puts the ADD in the order given in the + array permut. Checks for trivial cases to terminate recursion, then + splits on the children of this node. Once the solutions for the + children are obtained, it puts into the current position the node + from the rest of the ADD that should be here. Then returns this ADD. + The key here is that the node being visited is NOT put in its proper + place by this instance, but rather is switched when its proper + position is reached in the recursion tree.

+ The DdNode * that is returned is the same ADD as passed in as node, + but in the new order.] + + SideEffects [None] + + SeeAlso [Cudd_addPermute cuddBddPermuteRecur] + +******************************************************************************/ +static DdNode * +cuddAddPermuteRecur( + DdManager * manager /* DD manager */, + DdHashTable * table /* computed table */, + DdNode * node /* ADD to be reordered */, + int * permut /* permutation array */) +{ + DdNode *T,*E; + DdNode *res,*var; + int index; + + statLine(manager); + /* Check for terminal case of constant node. */ + if (cuddIsConstant(node)) { + return(node); + } + + /* If problem already solved, look up answer and return. */ + if (node->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) { +#ifdef DD_DEBUG + addPermuteRecurHits++; +#endif + return(res); + } + + /* Split and recur on children of this node. */ + T = cuddAddPermuteRecur(manager,table,cuddT(node),permut); + if (T == NULL) return(NULL); + cuddRef(T); + E = cuddAddPermuteRecur(manager,table,cuddE(node),permut); + if (E == NULL) { + Cudd_RecursiveDeref(manager, T); + return(NULL); + } + cuddRef(E); + + /* Move variable that should be in this position to this position + ** by creating a single var ADD for that variable, and calling + ** cuddAddIteRecur with the T and E we just created. + */ + index = permut[node->index]; + var = cuddUniqueInter(manager,index,DD_ONE(manager),DD_ZERO(manager)); + if (var == NULL) return(NULL); + cuddRef(var); + res = cuddAddIteRecur(manager,var,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(manager,var); + Cudd_RecursiveDeref(manager, T); + Cudd_RecursiveDeref(manager, E); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(manager,var); + Cudd_RecursiveDeref(manager, T); + Cudd_RecursiveDeref(manager, E); + + /* Do not keep the result if the reference count is only 1, since + ** it will not be visited again. + */ + if (node->ref != 1) { + ptrint fanout = (ptrint) node->ref; + cuddSatDec(fanout); + if (!cuddHashTableInsert1(table,node,res,fanout)) { + Cudd_RecursiveDeref(manager, res); + return(NULL); + } + } + cuddDeref(res); + return(res); + +} /* end of cuddAddPermuteRecur */ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_bddPermute.] + + Description [ Recursively puts the BDD in the order given in the array permut. + Checks for trivial cases to terminate recursion, then splits on the + children of this node. Once the solutions for the children are + obtained, it puts into the current position the node from the rest of + the BDD that should be here. Then returns this BDD. + The key here is that the node being visited is NOT put in its proper + place by this instance, but rather is switched when its proper position + is reached in the recursion tree.

+ The DdNode * that is returned is the same BDD as passed in as node, + but in the new order.] + + SideEffects [None] + + SeeAlso [Cudd_bddPermute cuddAddPermuteRecur] + +******************************************************************************/ +static DdNode * +cuddBddPermuteRecur( + DdManager * manager /* DD manager */, + DdHashTable * table /* computed table */, + DdNode * node /* BDD to be reordered */, + int * permut /* permutation array */) +{ + DdNode *N,*T,*E; + DdNode *res; + int index; + + statLine(manager); + N = Cudd_Regular(node); + + /* Check for terminal case of constant node. */ + if (cuddIsConstant(N)) { + return(node); + } + + /* If problem already solved, look up answer and return. */ + if (N->ref != 1 && (res = cuddHashTableLookup1(table,N)) != NULL) { +#ifdef DD_DEBUG + bddPermuteRecurHits++; +#endif + return(Cudd_NotCond(res,N != node)); + } + + /* Split and recur on children of this node. */ + T = cuddBddPermuteRecur(manager,table,cuddT(N),permut); + if (T == NULL) return(NULL); + cuddRef(T); + E = cuddBddPermuteRecur(manager,table,cuddE(N),permut); + if (E == NULL) { + Cudd_IterDerefBdd(manager, T); + return(NULL); + } + cuddRef(E); + + /* Move variable that should be in this position to this position + ** by retrieving the single var BDD for that variable, and calling + ** cuddBddIteRecur with the T and E we just created. + */ + index = permut[N->index]; + res = cuddBddIteRecur(manager,manager->vars[index],T,E); + if (res == NULL) { + Cudd_IterDerefBdd(manager, T); + Cudd_IterDerefBdd(manager, E); + return(NULL); + } + cuddRef(res); + Cudd_IterDerefBdd(manager, T); + Cudd_IterDerefBdd(manager, E); + + /* Do not keep the result if the reference count is only 1, since + ** it will not be visited again. + */ + if (N->ref != 1) { + ptrint fanout = (ptrint) N->ref; + cuddSatDec(fanout); + if (!cuddHashTableInsert1(table,N,res,fanout)) { + Cudd_IterDerefBdd(manager, res); + return(NULL); + } + } + cuddDeref(res); + return(Cudd_NotCond(res,N != node)); + +} /* end of cuddBddPermuteRecur */ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_bddVarMap.] + + Description [Implements the recursive step of Cudd_bddVarMap. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddVarMap] + +******************************************************************************/ +static DdNode * +cuddBddVarMapRecur( + DdManager *manager /* DD manager */, + DdNode *f /* BDD to be remapped */) +{ + DdNode *F, *T, *E; + DdNode *res; + int index; + + statLine(manager); + F = Cudd_Regular(f); + + /* Check for terminal case of constant node. */ + if (cuddIsConstant(F)) { + return(f); + } + + /* If problem already solved, look up answer and return. */ + if (F->ref != 1 && + (res = cuddCacheLookup1(manager,Cudd_bddVarMap,F)) != NULL) { + return(Cudd_NotCond(res,F != f)); + } + + /* Split and recur on children of this node. */ + T = cuddBddVarMapRecur(manager,cuddT(F)); + if (T == NULL) return(NULL); + cuddRef(T); + E = cuddBddVarMapRecur(manager,cuddE(F)); + if (E == NULL) { + Cudd_IterDerefBdd(manager, T); + return(NULL); + } + cuddRef(E); + + /* Move variable that should be in this position to this position + ** by retrieving the single var BDD for that variable, and calling + ** cuddBddIteRecur with the T and E we just created. + */ + index = manager->map[F->index]; + res = cuddBddIteRecur(manager,manager->vars[index],T,E); + if (res == NULL) { + Cudd_IterDerefBdd(manager, T); + Cudd_IterDerefBdd(manager, E); + return(NULL); + } + cuddRef(res); + Cudd_IterDerefBdd(manager, T); + Cudd_IterDerefBdd(manager, E); + + /* Do not keep the result if the reference count is only 1, since + ** it will not be visited again. + */ + if (F->ref != 1) { + cuddCacheInsert1(manager,Cudd_bddVarMap,F,res); + } + cuddDeref(res); + return(Cudd_NotCond(res,F != f)); + +} /* end of cuddBddVarMapRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addVectorCompose.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +cuddAddVectorComposeRecur( + DdManager * dd /* DD manager */, + DdHashTable * table /* computed table */, + DdNode * f /* ADD in which to compose */, + DdNode ** vector /* functions to substitute */, + int deepest /* depth of deepest substitution */) +{ + DdNode *T,*E; + DdNode *res; + + statLine(dd); + /* If we are past the deepest substitution, return f. */ + if (cuddI(dd,f->index) > deepest) { + return(f); + } + + if ((res = cuddHashTableLookup1(table,f)) != NULL) { +#ifdef DD_DEBUG + addVectorComposeHits++; +#endif + return(res); + } + + /* Split and recur on children of this node. */ + T = cuddAddVectorComposeRecur(dd,table,cuddT(f),vector,deepest); + if (T == NULL) return(NULL); + cuddRef(T); + E = cuddAddVectorComposeRecur(dd,table,cuddE(f),vector,deepest); + if (E == NULL) { + Cudd_RecursiveDeref(dd, T); + return(NULL); + } + cuddRef(E); + + /* Retrieve the 0-1 ADD for the current top variable and call + ** cuddAddIteRecur with the T and E we just created. + */ + res = cuddAddIteRecur(dd,vector[f->index],T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + + /* Do not keep the result if the reference count is only 1, since + ** it will not be visited again + */ + if (f->ref != 1) { + ptrint fanout = (ptrint) f->ref; + cuddSatDec(fanout); + if (!cuddHashTableInsert1(table,f,res,fanout)) { + Cudd_RecursiveDeref(dd, res); + return(NULL); + } + } + cuddDeref(res); + return(res); + +} /* end of cuddAddVectorComposeRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addGeneralVectorCompose.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +cuddAddGeneralVectorComposeRecur( + DdManager * dd /* DD manager */, + DdHashTable * table /* computed table */, + DdNode * f /* ADD in which to compose */, + DdNode ** vectorOn /* functions to substitute for x_i */, + DdNode ** vectorOff /* functions to substitute for x_i' */, + int deepest /* depth of deepest substitution */) +{ + DdNode *T,*E,*t,*e; + DdNode *res; + + /* If we are past the deepest substitution, return f. */ + if (cuddI(dd,f->index) > deepest) { + return(f); + } + + if ((res = cuddHashTableLookup1(table,f)) != NULL) { +#ifdef DD_DEBUG + addGeneralVectorComposeHits++; +#endif + return(res); + } + + /* Split and recur on children of this node. */ + T = cuddAddGeneralVectorComposeRecur(dd,table,cuddT(f), + vectorOn,vectorOff,deepest); + if (T == NULL) return(NULL); + cuddRef(T); + E = cuddAddGeneralVectorComposeRecur(dd,table,cuddE(f), + vectorOn,vectorOff,deepest); + if (E == NULL) { + Cudd_RecursiveDeref(dd, T); + return(NULL); + } + cuddRef(E); + + /* Retrieve the compose ADDs for the current top variable and call + ** cuddAddApplyRecur with the T and E we just created. + */ + t = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOn[f->index],T); + if (t == NULL) { + Cudd_RecursiveDeref(dd,T); + Cudd_RecursiveDeref(dd,E); + return(NULL); + } + cuddRef(t); + e = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOff[f->index],E); + if (e == NULL) { + Cudd_RecursiveDeref(dd,T); + Cudd_RecursiveDeref(dd,E); + Cudd_RecursiveDeref(dd,t); + return(NULL); + } + cuddRef(e); + res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e); + if (res == NULL) { + Cudd_RecursiveDeref(dd,T); + Cudd_RecursiveDeref(dd,E); + Cudd_RecursiveDeref(dd,t); + Cudd_RecursiveDeref(dd,e); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd,T); + Cudd_RecursiveDeref(dd,E); + Cudd_RecursiveDeref(dd,t); + Cudd_RecursiveDeref(dd,e); + + /* Do not keep the result if the reference count is only 1, since + ** it will not be visited again + */ + if (f->ref != 1) { + ptrint fanout = (ptrint) f->ref; + cuddSatDec(fanout); + if (!cuddHashTableInsert1(table,f,res,fanout)) { + Cudd_RecursiveDeref(dd, res); + return(NULL); + } + } + cuddDeref(res); + return(res); + +} /* end of cuddAddGeneralVectorComposeRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addNonSimCompose.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +cuddAddNonSimComposeRecur( + DdManager * dd, + DdNode * f, + DdNode ** vector, + DdNode * key, + DdNode * cube, + int lastsub) +{ + DdNode *f1, *f0, *key1, *key0, *cube1, *var; + DdNode *T,*E; + DdNode *r; + unsigned int top, topf, topk, topc; + unsigned int index; + int i; + DdNode **vect1; + DdNode **vect0; + + statLine(dd); + /* If we are past the deepest substitution, return f. */ + if (cube == DD_ONE(dd) || cuddIsConstant(f)) { + return(f); + } + + /* If problem already solved, look up answer and return. */ + r = cuddCacheLookup(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube); + if (r != NULL) { + return(r); + } + + /* Find top variable. we just need to look at f, key, and cube, + ** because all the varibles in the gi are in key. + */ + topf = cuddI(dd,f->index); + topk = cuddI(dd,key->index); + top = ddMin(topf,topk); + topc = cuddI(dd,cube->index); + top = ddMin(top,topc); + index = dd->invperm[top]; + + /* Compute the cofactors. */ + if (topf == top) { + f1 = cuddT(f); + f0 = cuddE(f); + } else { + f1 = f0 = f; + } + if (topc == top) { + cube1 = cuddT(cube); + /* We want to eliminate vector[index] from key. Otherwise + ** cache performance is severely affected. Hence we + ** existentially quantify the variable with index "index" from key. + */ + var = Cudd_addIthVar(dd, (int) index); + if (var == NULL) { + return(NULL); + } + cuddRef(var); + key1 = cuddAddExistAbstractRecur(dd, key, var); + if (key1 == NULL) { + Cudd_RecursiveDeref(dd,var); + return(NULL); + } + cuddRef(key1); + Cudd_RecursiveDeref(dd,var); + key0 = key1; + } else { + cube1 = cube; + if (topk == top) { + key1 = cuddT(key); + key0 = cuddE(key); + } else { + key1 = key0 = key; + } + cuddRef(key1); + } + + /* Allocate two new vectors for the cofactors of vector. */ + vect1 = ALLOC(DdNode *,lastsub); + if (vect1 == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd,key1); + return(NULL); + } + vect0 = ALLOC(DdNode *,lastsub); + if (vect0 == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd,key1); + FREE(vect1); + return(NULL); + } + + /* Cofactor the gi. Eliminate vect1[index] and vect0[index], because + ** we do not need them. + */ + for (i = 0; i < lastsub; i++) { + DdNode *gi = vector[i]; + if (gi == NULL) { + vect1[i] = vect0[i] = NULL; + } else if (gi->index == index) { + vect1[i] = cuddT(gi); + vect0[i] = cuddE(gi); + } else { + vect1[i] = vect0[i] = gi; + } + } + vect1[index] = vect0[index] = NULL; + + /* Recur on children. */ + T = cuddAddNonSimComposeRecur(dd,f1,vect1,key1,cube1,lastsub); + FREE(vect1); + if (T == NULL) { + Cudd_RecursiveDeref(dd,key1); + FREE(vect0); + return(NULL); + } + cuddRef(T); + E = cuddAddNonSimComposeRecur(dd,f0,vect0,key0,cube1,lastsub); + FREE(vect0); + if (E == NULL) { + Cudd_RecursiveDeref(dd,key1); + Cudd_RecursiveDeref(dd,T); + return(NULL); + } + cuddRef(E); + Cudd_RecursiveDeref(dd,key1); + + /* Retrieve the 0-1 ADD for the current top variable from vector, + ** and call cuddAddIteRecur with the T and E we just created. + */ + r = cuddAddIteRecur(dd,vector[index],T,E); + if (r == NULL) { + Cudd_RecursiveDeref(dd,T); + Cudd_RecursiveDeref(dd,E); + return(NULL); + } + cuddRef(r); + Cudd_RecursiveDeref(dd,T); + Cudd_RecursiveDeref(dd,E); + cuddDeref(r); + + /* Store answer to trim recursion. */ + cuddCacheInsert(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube,r); + + return(r); + +} /* end of cuddAddNonSimComposeRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddVectorCompose.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +cuddBddVectorComposeRecur( + DdManager * dd /* DD manager */, + DdHashTable * table /* computed table */, + DdNode * f /* BDD in which to compose */, + DdNode ** vector /* functions to be composed */, + int deepest /* depth of the deepest substitution */) +{ + DdNode *F,*T,*E; + DdNode *res; + + statLine(dd); + F = Cudd_Regular(f); + + /* If we are past the deepest substitution, return f. */ + if (cuddI(dd,F->index) > deepest) { + return(f); + } + + /* If problem already solved, look up answer and return. */ + if ((res = cuddHashTableLookup1(table,F)) != NULL) { +#ifdef DD_DEBUG + bddVectorComposeHits++; +#endif + return(Cudd_NotCond(res,F != f)); + } + + /* Split and recur on children of this node. */ + T = cuddBddVectorComposeRecur(dd,table,cuddT(F),vector, deepest); + if (T == NULL) return(NULL); + cuddRef(T); + E = cuddBddVectorComposeRecur(dd,table,cuddE(F),vector, deepest); + if (E == NULL) { + Cudd_IterDerefBdd(dd, T); + return(NULL); + } + cuddRef(E); + + /* Call cuddBddIteRecur with the BDD that replaces the current top + ** variable and the T and E we just created. + */ + res = cuddBddIteRecur(dd,vector[F->index],T,E); + if (res == NULL) { + Cudd_IterDerefBdd(dd, T); + Cudd_IterDerefBdd(dd, E); + return(NULL); + } + cuddRef(res); + Cudd_IterDerefBdd(dd, T); + Cudd_IterDerefBdd(dd, E); + + /* Do not keep the result if the reference count is only 1, since + ** it will not be visited again. + */ + if (F->ref != 1) { + ptrint fanout = (ptrint) F->ref; + cuddSatDec(fanout); + if (!cuddHashTableInsert1(table,F,res,fanout)) { + Cudd_IterDerefBdd(dd, res); + return(NULL); + } + } + cuddDeref(res); + return(Cudd_NotCond(res,F != f)); + +} /* end of cuddBddVectorComposeRecur */ + + +/**Function******************************************************************** + + Synopsis [Comparison of a function to the i-th ADD variable.] + + Description [Comparison of a function to the i-th ADD variable. Returns 1 if + the function is the i-th ADD variable; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DD_INLINE +static int +ddIsIthAddVar( + DdManager * dd, + DdNode * f, + unsigned int i) +{ + return(f->index == i && cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd)); + +} /* end of ddIsIthAddVar */ + + +/**Function******************************************************************** + + Synopsis [Comparison of a pair of functions to the i-th ADD variable.] + + Description [Comparison of a pair of functions to the i-th ADD + variable. Returns 1 if the functions are the i-th ADD variable and its + complement; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DD_INLINE +static int +ddIsIthAddVarPair( + DdManager * dd, + DdNode * f, + DdNode * g, + unsigned int i) +{ + return(f->index == i && g->index == i && + cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd) && + cuddT(g) == DD_ZERO(dd) && cuddE(g) == DD_ONE(dd)); + +} /* end of ddIsIthAddVarPair */ diff --git a/abc70930/src/bdd/cudd/cuddDecomp.c b/abc70930/src/bdd/cudd/cuddDecomp.c new file mode 100644 index 00000000..4fde7392 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddDecomp.c @@ -0,0 +1,2150 @@ +/**CFile*********************************************************************** + + FileName [cuddDecomp.c] + + PackageName [cudd] + + Synopsis [Functions for BDD decomposition.] + + Description [External procedures included in this file: +

    +
  • Cudd_bddApproxConjDecomp() +
  • Cudd_bddApproxDisjDecomp() +
  • Cudd_bddIterConjDecomp() +
  • Cudd_bddIterDisjDecomp() +
  • Cudd_bddGenConjDecomp() +
  • Cudd_bddGenDisjDecomp() +
  • Cudd_bddVarConjDecomp() +
  • Cudd_bddVarDisjDecomp() +
+ Static procedures included in this module: +
    +
  • cuddConjunctsAux() +
  • CreateBotDist() +
  • BuildConjuncts() +
  • ConjunctsFree() +
] + + Author [Kavita Ravi, Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ +#define DEPTH 5 +#define THRESHOLD 10 +#define NONE 0 +#define PAIR_ST 1 +#define PAIR_CR 2 +#define G_ST 3 +#define G_CR 4 +#define H_ST 5 +#define H_CR 6 +#define BOTH_G 7 +#define BOTH_H 8 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ +typedef struct Conjuncts { + DdNode *g; + DdNode *h; +} Conjuncts; + +typedef struct NodeStat { + int distance; + int localRef; +} NodeStat; + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddDecomp.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +static DdNode *one, *zero; +long lastTimeG; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +#define FactorsNotStored(factors) ((int)((long)(factors) & 01)) + +#define FactorsComplement(factors) ((Conjuncts *)((long)(factors) | 01)) + +#define FactorsUncomplement(factors) ((Conjuncts *)((long)(factors) ^ 01)) + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static NodeStat * CreateBotDist ARGS((DdNode * node, st_table * distanceTable)); +static double CountMinterms ARGS((DdNode * node, double max, st_table * mintermTable, FILE *fp)); +static void ConjunctsFree ARGS((DdManager * dd, Conjuncts * factors)); +static int PairInTables ARGS((DdNode * g, DdNode * h, st_table * ghTable)); +static Conjuncts * CheckTablesCacheAndReturn ARGS((DdNode * node, DdNode * g, DdNode * h, st_table * ghTable, st_table * cacheTable)); +static Conjuncts * PickOnePair ARGS((DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st_table * ghTable, st_table * cacheTable)); +static Conjuncts * CheckInTables ARGS((DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st_table * ghTable, st_table * cacheTable, int * outOfMem)); +static Conjuncts * ZeroCase ARGS((DdManager * dd, DdNode * node, Conjuncts * factorsNv, st_table * ghTable, st_table * cacheTable, int switched)); +static Conjuncts * BuildConjuncts ARGS((DdManager * dd, DdNode * node, st_table * distanceTable, st_table * cacheTable, int approxDistance, int maxLocalRef, st_table * ghTable, st_table * mintermTable)); +static int cuddConjunctsAux ARGS((DdManager * dd, DdNode * f, DdNode ** c1, DdNode ** c2)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs two-way conjunctive decomposition of a BDD.] + + Description [Performs two-way conjunctive decomposition of a + BDD. This procedure owes its name to the use of supersetting to + obtain an initial factor of the given function. Returns the number + of conjuncts produced, that is, 2 if successful; 1 if no meaningful + decomposition was found; 0 otherwise. The conjuncts produced by this + procedure tend to be imbalanced.] + + SideEffects [The factors are returned in an array as side effects. + The array is allocated by this function. It is the caller's responsibility + to free it. On successful completion, the conjuncts are already + referenced. If the function returns 0, the array for the conjuncts is + not allocated. If the function returns 1, the only factor equals the + function to be decomposed.] + + SeeAlso [Cudd_bddApproxDisjDecomp Cudd_bddIterConjDecomp + Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox + Cudd_bddSqueeze Cudd_bddLICompaction] + +******************************************************************************/ +int +Cudd_bddApproxConjDecomp( + DdManager * dd /* manager */, + DdNode * f /* function to be decomposed */, + DdNode *** conjuncts /* address of the first factor */) +{ + DdNode *superset1, *superset2, *glocal, *hlocal; + int nvars = Cudd_SupportSize(dd,f); + + /* Find a tentative first factor by overapproximation and minimization. */ + superset1 = Cudd_RemapOverApprox(dd,f,nvars,0,1.0); + if (superset1 == NULL) return(0); + cuddRef(superset1); + superset2 = Cudd_bddSqueeze(dd,f,superset1); + if (superset2 == NULL) { + Cudd_RecursiveDeref(dd,superset1); + return(0); + } + cuddRef(superset2); + Cudd_RecursiveDeref(dd,superset1); + + /* Compute the second factor by minimization. */ + hlocal = Cudd_bddLICompaction(dd,f,superset2); + if (hlocal == NULL) { + Cudd_RecursiveDeref(dd,superset2); + return(0); + } + cuddRef(hlocal); + + /* Refine the first factor by minimization. If h turns out to be f, this + ** step guarantees that g will be 1. */ + glocal = Cudd_bddLICompaction(dd,superset2,hlocal); + if (glocal == NULL) { + Cudd_RecursiveDeref(dd,superset2); + Cudd_RecursiveDeref(dd,hlocal); + return(0); + } + cuddRef(glocal); + Cudd_RecursiveDeref(dd,superset2); + + if (glocal != DD_ONE(dd)) { + if (hlocal != DD_ONE(dd)) { + *conjuncts = ALLOC(DdNode *,2); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,glocal); + Cudd_RecursiveDeref(dd,hlocal); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = glocal; + (*conjuncts)[1] = hlocal; + return(2); + } else { + Cudd_RecursiveDeref(dd,hlocal); + *conjuncts = ALLOC(DdNode *,1); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,glocal); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = glocal; + return(1); + } + } else { + Cudd_RecursiveDeref(dd,glocal); + *conjuncts = ALLOC(DdNode *,1); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,hlocal); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = hlocal; + return(1); + } + +} /* end of Cudd_bddApproxConjDecomp */ + + +/**Function******************************************************************** + + Synopsis [Performs two-way disjunctive decomposition of a BDD.] + + Description [Performs two-way disjunctive decomposition of a BDD. + Returns the number of disjuncts produced, that is, 2 if successful; + 1 if no meaningful decomposition was found; 0 otherwise. The + disjuncts produced by this procedure tend to be imbalanced.] + + SideEffects [The two disjuncts are returned in an array as side effects. + The array is allocated by this function. It is the caller's responsibility + to free it. On successful completion, the disjuncts are already + referenced. If the function returns 0, the array for the disjuncts is + not allocated. If the function returns 1, the only factor equals the + function to be decomposed.] + + SeeAlso [Cudd_bddApproxConjDecomp Cudd_bddIterDisjDecomp + Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp] + +******************************************************************************/ +int +Cudd_bddApproxDisjDecomp( + DdManager * dd /* manager */, + DdNode * f /* function to be decomposed */, + DdNode *** disjuncts /* address of the array of the disjuncts */) +{ + int result, i; + + result = Cudd_bddApproxConjDecomp(dd,Cudd_Not(f),disjuncts); + for (i = 0; i < result; i++) { + (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); + } + return(result); + +} /* end of Cudd_bddApproxDisjDecomp */ + + +/**Function******************************************************************** + + Synopsis [Performs two-way conjunctive decomposition of a BDD.] + + Description [Performs two-way conjunctive decomposition of a + BDD. This procedure owes its name to the iterated use of + supersetting to obtain a factor of the given function. Returns the + number of conjuncts produced, that is, 2 if successful; 1 if no + meaningful decomposition was found; 0 otherwise. The conjuncts + produced by this procedure tend to be imbalanced.] + + SideEffects [The factors are returned in an array as side effects. + The array is allocated by this function. It is the caller's responsibility + to free it. On successful completion, the conjuncts are already + referenced. If the function returns 0, the array for the conjuncts is + not allocated. If the function returns 1, the only factor equals the + function to be decomposed.] + + SeeAlso [Cudd_bddIterDisjDecomp Cudd_bddApproxConjDecomp + Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox + Cudd_bddSqueeze Cudd_bddLICompaction] + +******************************************************************************/ +int +Cudd_bddIterConjDecomp( + DdManager * dd /* manager */, + DdNode * f /* function to be decomposed */, + DdNode *** conjuncts /* address of the array of conjuncts */) +{ + DdNode *superset1, *superset2, *old[2], *res[2]; + int sizeOld, sizeNew; + int nvars = Cudd_SupportSize(dd,f); + + old[0] = DD_ONE(dd); + cuddRef(old[0]); + old[1] = f; + cuddRef(old[1]); + sizeOld = Cudd_SharingSize(old,2); + + do { + /* Find a tentative first factor by overapproximation and + ** minimization. */ + superset1 = Cudd_RemapOverApprox(dd,old[1],nvars,0,1.0); + if (superset1 == NULL) { + Cudd_RecursiveDeref(dd,old[0]); + Cudd_RecursiveDeref(dd,old[1]); + return(0); + } + cuddRef(superset1); + superset2 = Cudd_bddSqueeze(dd,old[1],superset1); + if (superset2 == NULL) { + Cudd_RecursiveDeref(dd,old[0]); + Cudd_RecursiveDeref(dd,old[1]); + Cudd_RecursiveDeref(dd,superset1); + return(0); + } + cuddRef(superset2); + Cudd_RecursiveDeref(dd,superset1); + res[0] = Cudd_bddAnd(dd,old[0],superset2); + if (res[0] == NULL) { + Cudd_RecursiveDeref(dd,superset2); + Cudd_RecursiveDeref(dd,old[0]); + Cudd_RecursiveDeref(dd,old[1]); + return(0); + } + cuddRef(res[0]); + Cudd_RecursiveDeref(dd,superset2); + if (res[0] == old[0]) { + Cudd_RecursiveDeref(dd,res[0]); + break; /* avoid infinite loop */ + } + + /* Compute the second factor by minimization. */ + res[1] = Cudd_bddLICompaction(dd,old[1],res[0]); + if (res[1] == NULL) { + Cudd_RecursiveDeref(dd,old[0]); + Cudd_RecursiveDeref(dd,old[1]); + return(0); + } + cuddRef(res[1]); + + sizeNew = Cudd_SharingSize(res,2); + if (sizeNew <= sizeOld) { + Cudd_RecursiveDeref(dd,old[0]); + old[0] = res[0]; + Cudd_RecursiveDeref(dd,old[1]); + old[1] = res[1]; + sizeOld = sizeNew; + } else { + Cudd_RecursiveDeref(dd,res[0]); + Cudd_RecursiveDeref(dd,res[1]); + break; + } + + } while (1); + + /* Refine the first factor by minimization. If h turns out to + ** be f, this step guarantees that g will be 1. */ + superset1 = Cudd_bddLICompaction(dd,old[0],old[1]); + if (superset1 == NULL) { + Cudd_RecursiveDeref(dd,old[0]); + Cudd_RecursiveDeref(dd,old[1]); + return(0); + } + cuddRef(superset1); + Cudd_RecursiveDeref(dd,old[0]); + old[0] = superset1; + + if (old[0] != DD_ONE(dd)) { + if (old[1] != DD_ONE(dd)) { + *conjuncts = ALLOC(DdNode *,2); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,old[0]); + Cudd_RecursiveDeref(dd,old[1]); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = old[0]; + (*conjuncts)[1] = old[1]; + return(2); + } else { + Cudd_RecursiveDeref(dd,old[1]); + *conjuncts = ALLOC(DdNode *,1); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,old[0]); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = old[0]; + return(1); + } + } else { + Cudd_RecursiveDeref(dd,old[0]); + *conjuncts = ALLOC(DdNode *,1); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,old[1]); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = old[1]; + return(1); + } + +} /* end of Cudd_bddIterConjDecomp */ + + +/**Function******************************************************************** + + Synopsis [Performs two-way disjunctive decomposition of a BDD.] + + Description [Performs two-way disjunctive decomposition of a BDD. + Returns the number of disjuncts produced, that is, 2 if successful; + 1 if no meaningful decomposition was found; 0 otherwise. The + disjuncts produced by this procedure tend to be imbalanced.] + + SideEffects [The two disjuncts are returned in an array as side effects. + The array is allocated by this function. It is the caller's responsibility + to free it. On successful completion, the disjuncts are already + referenced. If the function returns 0, the array for the disjuncts is + not allocated. If the function returns 1, the only factor equals the + function to be decomposed.] + + SeeAlso [Cudd_bddIterConjDecomp Cudd_bddApproxDisjDecomp + Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp] + +******************************************************************************/ +int +Cudd_bddIterDisjDecomp( + DdManager * dd /* manager */, + DdNode * f /* function to be decomposed */, + DdNode *** disjuncts /* address of the array of the disjuncts */) +{ + int result, i; + + result = Cudd_bddIterConjDecomp(dd,Cudd_Not(f),disjuncts); + for (i = 0; i < result; i++) { + (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); + } + return(result); + +} /* end of Cudd_bddIterDisjDecomp */ + + +/**Function******************************************************************** + + Synopsis [Performs two-way conjunctive decomposition of a BDD.] + + Description [Performs two-way conjunctive decomposition of a + BDD. This procedure owes its name to the fact tht it generalizes the + decomposition based on the cofactors with respect to one + variable. Returns the number of conjuncts produced, that is, 2 if + successful; 1 if no meaningful decomposition was found; 0 + otherwise. The conjuncts produced by this procedure tend to be + balanced.] + + SideEffects [The two factors are returned in an array as side effects. + The array is allocated by this function. It is the caller's responsibility + to free it. On successful completion, the conjuncts are already + referenced. If the function returns 0, the array for the conjuncts is + not allocated. If the function returns 1, the only factor equals the + function to be decomposed.] + + SeeAlso [Cudd_bddGenDisjDecomp Cudd_bddApproxConjDecomp + Cudd_bddIterConjDecomp Cudd_bddVarConjDecomp] + +******************************************************************************/ +int +Cudd_bddGenConjDecomp( + DdManager * dd /* manager */, + DdNode * f /* function to be decomposed */, + DdNode *** conjuncts /* address of the array of conjuncts */) +{ + int result; + DdNode *glocal, *hlocal; + + one = DD_ONE(dd); + zero = Cudd_Not(one); + + do { + dd->reordered = 0; + result = cuddConjunctsAux(dd, f, &glocal, &hlocal); + } while (dd->reordered == 1); + + if (result == 0) { + return(0); + } + + if (glocal != one) { + if (hlocal != one) { + *conjuncts = ALLOC(DdNode *,2); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,glocal); + Cudd_RecursiveDeref(dd,hlocal); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = glocal; + (*conjuncts)[1] = hlocal; + return(2); + } else { + Cudd_RecursiveDeref(dd,hlocal); + *conjuncts = ALLOC(DdNode *,1); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,glocal); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = glocal; + return(1); + } + } else { + Cudd_RecursiveDeref(dd,glocal); + *conjuncts = ALLOC(DdNode *,1); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,hlocal); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = hlocal; + return(1); + } + +} /* end of Cudd_bddGenConjDecomp */ + + +/**Function******************************************************************** + + Synopsis [Performs two-way disjunctive decomposition of a BDD.] + + Description [Performs two-way disjunctive decomposition of a BDD. + Returns the number of disjuncts produced, that is, 2 if successful; + 1 if no meaningful decomposition was found; 0 otherwise. The + disjuncts produced by this procedure tend to be balanced.] + + SideEffects [The two disjuncts are returned in an array as side effects. + The array is allocated by this function. It is the caller's responsibility + to free it. On successful completion, the disjuncts are already + referenced. If the function returns 0, the array for the disjuncts is + not allocated. If the function returns 1, the only factor equals the + function to be decomposed.] + + SeeAlso [Cudd_bddGenConjDecomp Cudd_bddApproxDisjDecomp + Cudd_bddIterDisjDecomp Cudd_bddVarDisjDecomp] + +******************************************************************************/ +int +Cudd_bddGenDisjDecomp( + DdManager * dd /* manager */, + DdNode * f /* function to be decomposed */, + DdNode *** disjuncts /* address of the array of the disjuncts */) +{ + int result, i; + + result = Cudd_bddGenConjDecomp(dd,Cudd_Not(f),disjuncts); + for (i = 0; i < result; i++) { + (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); + } + return(result); + +} /* end of Cudd_bddGenDisjDecomp */ + + +/**Function******************************************************************** + + Synopsis [Performs two-way conjunctive decomposition of a BDD.] + + Description [Conjunctively decomposes one BDD according to a + variable. If f is the function of the BDD and + x is the variable, the decomposition is + (f+x)(f+x'). The variable is chosen so as to balance + the sizes of the two conjuncts and to keep them small. Returns the + number of conjuncts produced, that is, 2 if successful; 1 if no + meaningful decomposition was found; 0 otherwise.] + + SideEffects [The two factors are returned in an array as side effects. + The array is allocated by this function. It is the caller's responsibility + to free it. On successful completion, the conjuncts are already + referenced. If the function returns 0, the array for the conjuncts is + not allocated. If the function returns 1, the only factor equals the + function to be decomposed.] + + SeeAlso [Cudd_bddVarDisjDecomp Cudd_bddGenConjDecomp + Cudd_bddApproxConjDecomp Cudd_bddIterConjDecomp] + +*****************************************************************************/ +int +Cudd_bddVarConjDecomp( + DdManager * dd /* manager */, + DdNode * f /* function to be decomposed */, + DdNode *** conjuncts /* address of the array of conjuncts */) +{ + int best; + int min; + DdNode *support, *scan, *var, *glocal, *hlocal; + + /* Find best cofactoring variable. */ + support = Cudd_Support(dd,f); + if (support == NULL) return(0); + if (Cudd_IsConstant(support)) { + *conjuncts = ALLOC(DdNode *,1); + if (*conjuncts == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = f; + cuddRef((*conjuncts)[0]); + return(1); + } + cuddRef(support); + min = 1000000000; + best = -1; + scan = support; + while (!Cudd_IsConstant(scan)) { + int i = scan->index; + int est1 = Cudd_EstimateCofactor(dd,f,i,1); + int est0 = Cudd_EstimateCofactor(dd,f,i,0); + /* Minimize the size of the larger of the two cofactors. */ + int est = (est1 > est0) ? est1 : est0; + if (est < min) { + min = est; + best = i; + } + scan = cuddT(scan); + } +#ifdef DD_DEBUG + assert(best >= 0 && best < dd->size); +#endif + Cudd_RecursiveDeref(dd,support); + + var = Cudd_bddIthVar(dd,best); + glocal = Cudd_bddOr(dd,f,var); + if (glocal == NULL) { + return(0); + } + cuddRef(glocal); + hlocal = Cudd_bddOr(dd,f,Cudd_Not(var)); + if (hlocal == NULL) { + Cudd_RecursiveDeref(dd,glocal); + return(0); + } + cuddRef(hlocal); + + if (glocal != DD_ONE(dd)) { + if (hlocal != DD_ONE(dd)) { + *conjuncts = ALLOC(DdNode *,2); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,glocal); + Cudd_RecursiveDeref(dd,hlocal); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = glocal; + (*conjuncts)[1] = hlocal; + return(2); + } else { + Cudd_RecursiveDeref(dd,hlocal); + *conjuncts = ALLOC(DdNode *,1); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,glocal); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = glocal; + return(1); + } + } else { + Cudd_RecursiveDeref(dd,glocal); + *conjuncts = ALLOC(DdNode *,1); + if (*conjuncts == NULL) { + Cudd_RecursiveDeref(dd,hlocal); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + (*conjuncts)[0] = hlocal; + return(1); + } + +} /* end of Cudd_bddVarConjDecomp */ + + +/**Function******************************************************************** + + Synopsis [Performs two-way disjunctive decomposition of a BDD.] + + Description [Performs two-way disjunctive decomposition of a BDD + according to a variable. If f is the function of the + BDD and x is the variable, the decomposition is + f*x + f*x'. The variable is chosen so as to balance + the sizes of the two disjuncts and to keep them small. Returns the + number of disjuncts produced, that is, 2 if successful; 1 if no + meaningful decomposition was found; 0 otherwise.] + + SideEffects [The two disjuncts are returned in an array as side effects. + The array is allocated by this function. It is the caller's responsibility + to free it. On successful completion, the disjuncts are already + referenced. If the function returns 0, the array for the disjuncts is + not allocated. If the function returns 1, the only factor equals the + function to be decomposed.] + + SeeAlso [Cudd_bddVarConjDecomp Cudd_bddApproxDisjDecomp + Cudd_bddIterDisjDecomp Cudd_bddGenDisjDecomp] + +******************************************************************************/ +int +Cudd_bddVarDisjDecomp( + DdManager * dd /* manager */, + DdNode * f /* function to be decomposed */, + DdNode *** disjuncts /* address of the array of the disjuncts */) +{ + int result, i; + + result = Cudd_bddVarConjDecomp(dd,Cudd_Not(f),disjuncts); + for (i = 0; i < result; i++) { + (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); + } + return(result); + +} /* end of Cudd_bddVarDisjDecomp */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Get longest distance of node from constant.] + + Description [Get longest distance of node from constant. Returns the + distance of the root from the constant if successful; CUDD_OUT_OF_MEM + otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static NodeStat * +CreateBotDist( + DdNode * node, + st_table * distanceTable) +{ + DdNode *N, *Nv, *Nnv; + int distance, distanceNv, distanceNnv; + NodeStat *nodeStat, *nodeStatNv, *nodeStatNnv; + +#if 0 + if (Cudd_IsConstant(node)) { + return(0); + } +#endif + + /* Return the entry in the table if found. */ + N = Cudd_Regular(node); + if (st_lookup(distanceTable, (char *)N, (char **)&nodeStat)) { + nodeStat->localRef++; + return(nodeStat); + } + + Nv = cuddT(N); + Nnv = cuddE(N); + Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); + Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); + + /* Recur on the children. */ + nodeStatNv = CreateBotDist(Nv, distanceTable); + if (nodeStatNv == NULL) return(NULL); + distanceNv = nodeStatNv->distance; + + nodeStatNnv = CreateBotDist(Nnv, distanceTable); + if (nodeStatNnv == NULL) return(NULL); + distanceNnv = nodeStatNnv->distance; + /* Store max distance from constant; note sometimes this distance + ** may be to 0. + */ + distance = (distanceNv > distanceNnv) ? (distanceNv+1) : (distanceNnv + 1); + + nodeStat = ALLOC(NodeStat, 1); + if (nodeStat == NULL) { + return(0); + } + nodeStat->distance = distance; + nodeStat->localRef = 1; + + if (st_insert(distanceTable, (char *)N, (char *)nodeStat) == + ST_OUT_OF_MEM) { + return(0); + + } + return(nodeStat); + +} /* end of CreateBotDist */ + + +/**Function******************************************************************** + + Synopsis [Count the number of minterms of each node ina a BDD and + store it in a hash table.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static double +CountMinterms( + DdNode * node, + double max, + st_table * mintermTable, + FILE *fp) +{ + DdNode *N, *Nv, *Nnv; + double min, minNv, minNnv; + double *dummy; + + N = Cudd_Regular(node); + + if (cuddIsConstant(N)) { + if (node == zero) { + return(0); + } else { + return(max); + } + } + + /* Return the entry in the table if found. */ + if (st_lookup(mintermTable, (char *)node, (char **)&dummy)) { + min = *dummy; + return(min); + } + + Nv = cuddT(N); + Nnv = cuddE(N); + Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); + Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); + + /* Recur on the children. */ + minNv = CountMinterms(Nv, max, mintermTable, fp); + if (minNv == -1.0) return(-1.0); + minNnv = CountMinterms(Nnv, max, mintermTable, fp); + if (minNnv == -1.0) return(-1.0); + min = minNv / 2.0 + minNnv / 2.0; + /* store + */ + + dummy = ALLOC(double, 1); + if (dummy == NULL) return(-1.0); + *dummy = min; + if (st_insert(mintermTable, (char *)node, (char *)dummy) == ST_OUT_OF_MEM) { + (void) fprintf(fp, "st table insert failed\n"); + } + return(min); + +} /* end of CountMinterms */ + + +/**Function******************************************************************** + + Synopsis [Free factors structure] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +ConjunctsFree( + DdManager * dd, + Conjuncts * factors) +{ + Cudd_RecursiveDeref(dd, factors->g); + Cudd_RecursiveDeref(dd, factors->h); + FREE(factors); + return; + +} /* end of ConjunctsFree */ + + +/**Function******************************************************************** + + Synopsis [Check whether the given pair is in the tables.] + + Description [.Check whether the given pair is in the tables. gTable + and hTable are combined. + absence in both is indicated by 0, + presence in gTable is indicated by 1, + presence in hTable by 2 and + presence in both by 3. + The values returned by this function are PAIR_ST, + PAIR_CR, G_ST, G_CR, H_ST, H_CR, BOTH_G, BOTH_H, NONE. + PAIR_ST implies g in gTable and h in hTable + PAIR_CR implies g in hTable and h in gTable + G_ST implies g in gTable and h not in any table + G_CR implies g in hTable and h not in any table + H_ST implies h in hTable and g not in any table + H_CR implies h in gTable and g not in any table + BOTH_G implies both in gTable + BOTH_H implies both in hTable + NONE implies none in table; ] + + SideEffects [] + + SeeAlso [CheckTablesCacheAndReturn CheckInTables] + +******************************************************************************/ +static int +PairInTables( + DdNode * g, + DdNode * h, + st_table * ghTable) +{ + int valueG, valueH, gPresent, hPresent; + + valueG = valueH = gPresent = hPresent = 0; + + gPresent = st_lookup_int(ghTable, (char *)Cudd_Regular(g), &valueG); + hPresent = st_lookup_int(ghTable, (char *)Cudd_Regular(h), &valueH); + + if (!gPresent && !hPresent) return(NONE); + + if (!hPresent) { + if (valueG & 1) return(G_ST); + if (valueG & 2) return(G_CR); + } + if (!gPresent) { + if (valueH & 1) return(H_CR); + if (valueH & 2) return(H_ST); + } + /* both in tables */ + if ((valueG & 1) && (valueH & 2)) return(PAIR_ST); + if ((valueG & 2) && (valueH & 1)) return(PAIR_CR); + + if (valueG & 1) { + return(BOTH_G); + } else { + return(BOTH_H); + } + +} /* end of PairInTables */ + + +/**Function******************************************************************** + + Synopsis [Check the tables for the existence of pair and return one + combination, cache the result.] + + Description [Check the tables for the existence of pair and return + one combination, cache the result. The assumption is that one of the + conjuncts is already in the tables.] + + SideEffects [g and h referenced for the cache] + + SeeAlso [ZeroCase] + +******************************************************************************/ +static Conjuncts * +CheckTablesCacheAndReturn( + DdNode * node, + DdNode * g, + DdNode * h, + st_table * ghTable, + st_table * cacheTable) +{ + int pairValue; + int value; + Conjuncts *factors; + + value = 0; + /* check tables */ + pairValue = PairInTables(g, h, ghTable); + assert(pairValue != NONE); + /* if both dont exist in table, we know one exists(either g or h). + * Therefore store the other and proceed + */ + factors = ALLOC(Conjuncts, 1); + if (factors == NULL) return(NULL); + if ((pairValue == BOTH_H) || (pairValue == H_ST)) { + if (g != one) { + value = 0; + if (st_lookup_int(ghTable, (char *)Cudd_Regular(g), &value)) { + value |= 1; + } else { + value = 1; + } + if (st_insert(ghTable, (char *)Cudd_Regular(g), + (char *)(long)value) == ST_OUT_OF_MEM) { + return(NULL); + } + } + factors->g = g; + factors->h = h; + } else if ((pairValue == BOTH_G) || (pairValue == G_ST)) { + if (h != one) { + value = 0; + if (st_lookup_int(ghTable, (char *)Cudd_Regular(h), &value)) { + value |= 2; + } else { + value = 2; + } + if (st_insert(ghTable, (char *)Cudd_Regular(h), + (char *)(long)value) == ST_OUT_OF_MEM) { + return(NULL); + } + } + factors->g = g; + factors->h = h; + } else if (pairValue == H_CR) { + if (g != one) { + value = 2; + if (st_insert(ghTable, (char *)Cudd_Regular(g), + (char *)(long)value) == ST_OUT_OF_MEM) { + return(NULL); + } + } + factors->g = h; + factors->h = g; + } else if (pairValue == G_CR) { + if (h != one) { + value = 1; + if (st_insert(ghTable, (char *)Cudd_Regular(h), + (char *)(long)value) == ST_OUT_OF_MEM) { + return(NULL); + } + } + factors->g = h; + factors->h = g; + } else if (pairValue == PAIR_CR) { + /* pair exists in table */ + factors->g = h; + factors->h = g; + } else if (pairValue == PAIR_ST) { + factors->g = g; + factors->h = h; + } + + /* cache the result for this node */ + if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) { + FREE(factors); + return(NULL); + } + + return(factors); + +} /* end of CheckTablesCacheAndReturn */ + +/**Function******************************************************************** + + Synopsis [Check the tables for the existence of pair and return one + combination, store in cache.] + + Description [Check the tables for the existence of pair and return + one combination, store in cache. The pair that has more pointers to + it is picked. An approximation of the number of local pointers is + made by taking the reference count of the pairs sent. ] + + SideEffects [] + + SeeAlso [ZeroCase BuildConjuncts] + +******************************************************************************/ +static Conjuncts * +PickOnePair( + DdNode * node, + DdNode * g1, + DdNode * h1, + DdNode * g2, + DdNode * h2, + st_table * ghTable, + st_table * cacheTable) +{ + int value; + Conjuncts *factors; + int oneRef, twoRef; + + factors = ALLOC(Conjuncts, 1); + if (factors == NULL) return(NULL); + + /* count the number of pointers to pair 2 */ + if (h2 == one) { + twoRef = (Cudd_Regular(g2))->ref; + } else if (g2 == one) { + twoRef = (Cudd_Regular(h2))->ref; + } else { + twoRef = ((Cudd_Regular(g2))->ref + (Cudd_Regular(h2))->ref)/2; + } + + /* count the number of pointers to pair 1 */ + if (h1 == one) { + oneRef = (Cudd_Regular(g1))->ref; + } else if (g1 == one) { + oneRef = (Cudd_Regular(h1))->ref; + } else { + oneRef = ((Cudd_Regular(g1))->ref + (Cudd_Regular(h1))->ref)/2; + } + + /* pick the pair with higher reference count */ + if (oneRef >= twoRef) { + factors->g = g1; + factors->h = h1; + } else { + factors->g = g2; + factors->h = h2; + } + + /* + * Store computed factors in respective tables to encourage + * recombination. + */ + if (factors->g != one) { + /* insert g in htable */ + value = 0; + if (st_lookup_int(ghTable, (char *)Cudd_Regular(factors->g), &value)) { + if (value == 2) { + value |= 1; + if (st_insert(ghTable, (char *)Cudd_Regular(factors->g), + (char *)(long)value) == ST_OUT_OF_MEM) { + FREE(factors); + return(NULL); + } + } + } else { + value = 1; + if (st_insert(ghTable, (char *)Cudd_Regular(factors->g), + (char *)(long)value) == ST_OUT_OF_MEM) { + FREE(factors); + return(NULL); + } + } + } + + if (factors->h != one) { + /* insert h in htable */ + value = 0; + if (st_lookup_int(ghTable, (char *)Cudd_Regular(factors->h), &value)) { + if (value == 1) { + value |= 2; + if (st_insert(ghTable, (char *)Cudd_Regular(factors->h), + (char *)(long)value) == ST_OUT_OF_MEM) { + FREE(factors); + return(NULL); + } + } + } else { + value = 2; + if (st_insert(ghTable, (char *)Cudd_Regular(factors->h), + (char *)(long)value) == ST_OUT_OF_MEM) { + FREE(factors); + return(NULL); + } + } + } + + /* Store factors in cache table for later use. */ + if (st_insert(cacheTable, (char *)node, (char *)factors) == + ST_OUT_OF_MEM) { + FREE(factors); + return(NULL); + } + + return(factors); + +} /* end of PickOnePair */ + + +/**Function******************************************************************** + + Synopsis [Check if the two pairs exist in the table, If any of the + conjuncts do exist, store in the cache and return the corresponding pair.] + + Description [Check if the two pairs exist in the table. If any of + the conjuncts do exist, store in the cache and return the + corresponding pair.] + + SideEffects [] + + SeeAlso [ZeroCase BuildConjuncts] + +******************************************************************************/ +static Conjuncts * +CheckInTables( + DdNode * node, + DdNode * g1, + DdNode * h1, + DdNode * g2, + DdNode * h2, + st_table * ghTable, + st_table * cacheTable, + int * outOfMem) +{ + int pairValue1, pairValue2; + Conjuncts *factors; + int value; + + *outOfMem = 0; + + /* check existence of pair in table */ + pairValue1 = PairInTables(g1, h1, ghTable); + pairValue2 = PairInTables(g2, h2, ghTable); + + /* if none of the 4 exist in the gh tables, return NULL */ + if ((pairValue1 == NONE) && (pairValue2 == NONE)) { + return NULL; + } + + factors = ALLOC(Conjuncts, 1); + if (factors == NULL) { + *outOfMem = 1; + return NULL; + } + + /* pairs that already exist in the table get preference. */ + if (pairValue1 == PAIR_ST) { + factors->g = g1; + factors->h = h1; + } else if (pairValue2 == PAIR_ST) { + factors->g = g2; + factors->h = h2; + } else if (pairValue1 == PAIR_CR) { + factors->g = h1; + factors->h = g1; + } else if (pairValue2 == PAIR_CR) { + factors->g = h2; + factors->h = g2; + } else if (pairValue1 == G_ST) { + /* g exists in the table, h is not found in either table */ + factors->g = g1; + factors->h = h1; + if (h1 != one) { + value = 2; + if (st_insert(ghTable, (char *)Cudd_Regular(h1), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } else if (pairValue1 == BOTH_G) { + /* g and h are found in the g table */ + factors->g = g1; + factors->h = h1; + if (h1 != one) { + value = 3; + if (st_insert(ghTable, (char *)Cudd_Regular(h1), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } else if (pairValue1 == H_ST) { + /* h exists in the table, g is not found in either table */ + factors->g = g1; + factors->h = h1; + if (g1 != one) { + value = 1; + if (st_insert(ghTable, (char *)Cudd_Regular(g1), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } else if (pairValue1 == BOTH_H) { + /* g and h are found in the h table */ + factors->g = g1; + factors->h = h1; + if (g1 != one) { + value = 3; + if (st_insert(ghTable, (char *)Cudd_Regular(g1), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } else if (pairValue2 == G_ST) { + /* g exists in the table, h is not found in either table */ + factors->g = g2; + factors->h = h2; + if (h2 != one) { + value = 2; + if (st_insert(ghTable, (char *)Cudd_Regular(h2), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } else if (pairValue2 == BOTH_G) { + /* g and h are found in the g table */ + factors->g = g2; + factors->h = h2; + if (h2 != one) { + value = 3; + if (st_insert(ghTable, (char *)Cudd_Regular(h2), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } else if (pairValue2 == H_ST) { + /* h exists in the table, g is not found in either table */ + factors->g = g2; + factors->h = h2; + if (g2 != one) { + value = 1; + if (st_insert(ghTable, (char *)Cudd_Regular(g2), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } else if (pairValue2 == BOTH_H) { + /* g and h are found in the h table */ + factors->g = g2; + factors->h = h2; + if (g2 != one) { + value = 3; + if (st_insert(ghTable, (char *)Cudd_Regular(g2), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } else if (pairValue1 == G_CR) { + /* g found in h table and h in none */ + factors->g = h1; + factors->h = g1; + if (h1 != one) { + value = 1; + if (st_insert(ghTable, (char *)Cudd_Regular(h1), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } else if (pairValue1 == H_CR) { + /* h found in g table and g in none */ + factors->g = h1; + factors->h = g1; + if (g1 != one) { + value = 2; + if (st_insert(ghTable, (char *)Cudd_Regular(g1), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } else if (pairValue2 == G_CR) { + /* g found in h table and h in none */ + factors->g = h2; + factors->h = g2; + if (h2 != one) { + value = 1; + if (st_insert(ghTable, (char *)Cudd_Regular(h2), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } else if (pairValue2 == H_CR) { + /* h found in g table and g in none */ + factors->g = h2; + factors->h = g2; + if (g2 != one) { + value = 2; + if (st_insert(ghTable, (char *)Cudd_Regular(g2), + (char *)(long)value) == ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + } + } + + /* Store factors in cache table for later use. */ + if (st_insert(cacheTable, (char *)node, (char *)factors) == + ST_OUT_OF_MEM) { + *outOfMem = 1; + FREE(factors); + return(NULL); + } + return factors; +} /* end of CheckInTables */ + + + +/**Function******************************************************************** + + Synopsis [If one child is zero, do explicitly what Restrict does or better] + + Description [If one child is zero, do explicitly what Restrict does or better. + First separate a variable and its child in the base case. In case of a cube + times a function, separate the cube and function. As a last resort, look in + tables.] + + SideEffects [Frees the BDDs in factorsNv. factorsNv itself is not freed + because it is freed above.] + + SeeAlso [BuildConjuncts] + +******************************************************************************/ +static Conjuncts * +ZeroCase( + DdManager * dd, + DdNode * node, + Conjuncts * factorsNv, + st_table * ghTable, + st_table * cacheTable, + int switched) +{ + int topid; + DdNode *g, *h, *g1, *g2, *h1, *h2, *x, *N, *G, *H, *Gv, *Gnv; + DdNode *Hv, *Hnv; + int value; + int outOfMem; + Conjuncts *factors; + + /* get var at this node */ + N = Cudd_Regular(node); + topid = N->index; + x = dd->vars[topid]; + x = (switched) ? Cudd_Not(x): x; + cuddRef(x); + + /* Seprate variable and child */ + if (factorsNv->g == one) { + Cudd_RecursiveDeref(dd, factorsNv->g); + factors = ALLOC(Conjuncts, 1); + if (factors == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd, factorsNv->h); + Cudd_RecursiveDeref(dd, x); + return(NULL); + } + factors->g = x; + factors->h = factorsNv->h; + /* cache the result*/ + if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd, factorsNv->h); + Cudd_RecursiveDeref(dd, x); + FREE(factors); + return NULL; + } + + /* store x in g table, the other node is already in the table */ + if (st_lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) { + value |= 1; + } else { + value = 1; + } + if (st_insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == ST_OUT_OF_MEM) { + dd->errorCode = CUDD_MEMORY_OUT; + return NULL; + } + return(factors); + } + + /* Seprate variable and child */ + if (factorsNv->h == one) { + Cudd_RecursiveDeref(dd, factorsNv->h); + factors = ALLOC(Conjuncts, 1); + if (factors == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd, factorsNv->g); + Cudd_RecursiveDeref(dd, x); + return(NULL); + } + factors->g = factorsNv->g; + factors->h = x; + /* cache the result. */ + if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd, factorsNv->g); + Cudd_RecursiveDeref(dd, x); + FREE(factors); + return(NULL); + } + /* store x in h table, the other node is already in the table */ + if (st_lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) { + value |= 2; + } else { + value = 2; + } + if (st_insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == ST_OUT_OF_MEM) { + dd->errorCode = CUDD_MEMORY_OUT; + return NULL; + } + return(factors); + } + + G = Cudd_Regular(factorsNv->g); + Gv = cuddT(G); + Gnv = cuddE(G); + Gv = Cudd_NotCond(Gv, Cudd_IsComplement(node)); + Gnv = Cudd_NotCond(Gnv, Cudd_IsComplement(node)); + /* if the child below is a variable */ + if ((Gv == zero) || (Gnv == zero)) { + h = factorsNv->h; + g = cuddBddAndRecur(dd, x, factorsNv->g); + if (g != NULL) cuddRef(g); + Cudd_RecursiveDeref(dd, factorsNv->g); + Cudd_RecursiveDeref(dd, x); + if (g == NULL) { + Cudd_RecursiveDeref(dd, factorsNv->h); + return NULL; + } + /* CheckTablesCacheAndReturn responsible for allocating + * factors structure., g,h referenced for cache store the + */ + factors = CheckTablesCacheAndReturn(node, + g, + h, + ghTable, + cacheTable); + if (factors == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd, g); + Cudd_RecursiveDeref(dd, h); + } + return(factors); + } + + H = Cudd_Regular(factorsNv->h); + Hv = cuddT(H); + Hnv = cuddE(H); + Hv = Cudd_NotCond(Hv, Cudd_IsComplement(node)); + Hnv = Cudd_NotCond(Hnv, Cudd_IsComplement(node)); + /* if the child below is a variable */ + if ((Hv == zero) || (Hnv == zero)) { + g = factorsNv->g; + h = cuddBddAndRecur(dd, x, factorsNv->h); + if (h!= NULL) cuddRef(h); + Cudd_RecursiveDeref(dd, factorsNv->h); + Cudd_RecursiveDeref(dd, x); + if (h == NULL) { + Cudd_RecursiveDeref(dd, factorsNv->g); + return NULL; + } + /* CheckTablesCacheAndReturn responsible for allocating + * factors structure.g,h referenced for table store + */ + factors = CheckTablesCacheAndReturn(node, + g, + h, + ghTable, + cacheTable); + if (factors == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd, g); + Cudd_RecursiveDeref(dd, h); + } + return(factors); + } + + /* build g1 = x*g; h1 = h */ + /* build g2 = g; h2 = x*h */ + Cudd_RecursiveDeref(dd, x); + h1 = factorsNv->h; + g1 = cuddBddAndRecur(dd, x, factorsNv->g); + if (g1 != NULL) cuddRef(g1); + if (g1 == NULL) { + Cudd_RecursiveDeref(dd, factorsNv->g); + Cudd_RecursiveDeref(dd, factorsNv->h); + return NULL; + } + + g2 = factorsNv->g; + h2 = cuddBddAndRecur(dd, x, factorsNv->h); + if (h2 != NULL) cuddRef(h2); + if (h2 == NULL) { + Cudd_RecursiveDeref(dd, factorsNv->h); + Cudd_RecursiveDeref(dd, factorsNv->g); + return NULL; + } + + /* check whether any pair is in tables */ + factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem); + if (outOfMem) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd, g1); + Cudd_RecursiveDeref(dd, h1); + Cudd_RecursiveDeref(dd, g2); + Cudd_RecursiveDeref(dd, h2); + return NULL; + } + if (factors != NULL) { + if ((factors->g == g1) || (factors->g == h1)) { + Cudd_RecursiveDeref(dd, g2); + Cudd_RecursiveDeref(dd, h2); + } else { + Cudd_RecursiveDeref(dd, g1); + Cudd_RecursiveDeref(dd, h1); + } + return factors; + } + + /* check for each pair in tables and choose one */ + factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable); + if (factors == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd, g1); + Cudd_RecursiveDeref(dd, h1); + Cudd_RecursiveDeref(dd, g2); + Cudd_RecursiveDeref(dd, h2); + } else { + /* now free what was created and not used */ + if ((factors->g == g1) || (factors->g == h1)) { + Cudd_RecursiveDeref(dd, g2); + Cudd_RecursiveDeref(dd, h2); + } else { + Cudd_RecursiveDeref(dd, g1); + Cudd_RecursiveDeref(dd, h1); + } + } + + return(factors); +} /* end of ZeroCase */ + + +/**Function******************************************************************** + + Synopsis [Builds the conjuncts recursively, bottom up.] + + Description [Builds the conjuncts recursively, bottom up. Constants + are returned as (f, f). The cache is checked for previously computed + result. The decomposition points are determined by the local + reference count of this node and the longest distance from the + constant. At the decomposition point, the factors returned are (f, + 1). Recur on the two children. The order is determined by the + heavier branch. Combine the factors of the two children and pick the + one that already occurs in the gh table. Occurence in g is indicated + by value 1, occurence in h by 2, occurence in both 3.] + + SideEffects [] + + SeeAlso [cuddConjunctsAux] + +******************************************************************************/ +static Conjuncts * +BuildConjuncts( + DdManager * dd, + DdNode * node, + st_table * distanceTable, + st_table * cacheTable, + int approxDistance, + int maxLocalRef, + st_table * ghTable, + st_table * mintermTable) +{ + int topid, distance; + Conjuncts *factorsNv, *factorsNnv, *factors; + Conjuncts *dummy; + DdNode *N, *Nv, *Nnv, *temp, *g1, *g2, *h1, *h2, *topv; + double minNv = 0.0, minNnv = 0.0; + double *doubleDummy; + int switched =0; + int outOfMem; + int freeNv = 0, freeNnv = 0, freeTemp; + NodeStat *nodeStat; + int value; + + /* if f is constant, return (f,f) */ + if (Cudd_IsConstant(node)) { + factors = ALLOC(Conjuncts, 1); + if (factors == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + factors->g = node; + factors->h = node; + return(FactorsComplement(factors)); + } + + /* If result (a pair of conjuncts) in cache, return the factors. */ + if (st_lookup(cacheTable, (char *)node, (char **)&dummy)) { + factors = dummy; + return(factors); + } + + /* check distance and local reference count of this node */ + N = Cudd_Regular(node); + if (!st_lookup(distanceTable, (char *)N, (char **)&nodeStat)) { + (void) fprintf(dd->err, "Not in table, Something wrong\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + distance = nodeStat->distance; + + /* at or below decomposition point, return (f, 1) */ + if (((nodeStat->localRef > maxLocalRef*2/3) && + (distance < approxDistance*2/3)) || + (distance <= approxDistance/4)) { + factors = ALLOC(Conjuncts, 1); + if (factors == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + /* alternate assigning (f,1) */ + value = 0; + if (st_lookup_int(ghTable, (char *)Cudd_Regular(node), &value)) { + if (value == 3) { + if (!lastTimeG) { + factors->g = node; + factors->h = one; + lastTimeG = 1; + } else { + factors->g = one; + factors->h = node; + lastTimeG = 0; + } + } else if (value == 1) { + factors->g = node; + factors->h = one; + } else { + factors->g = one; + factors->h = node; + } + } else if (!lastTimeG) { + factors->g = node; + factors->h = one; + lastTimeG = 1; + value = 1; + if (st_insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == ST_OUT_OF_MEM) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(factors); + return NULL; + } + } else { + factors->g = one; + factors->h = node; + lastTimeG = 0; + value = 2; + if (st_insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == ST_OUT_OF_MEM) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(factors); + return NULL; + } + } + return(FactorsComplement(factors)); + } + + /* get the children and recur */ + Nv = cuddT(N); + Nnv = cuddE(N); + Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); + Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); + + /* Choose which subproblem to solve first based on the number of + * minterms. We go first where there are more minterms. + */ + if (!Cudd_IsConstant(Nv)) { + if (!st_lookup(mintermTable, (char *)Nv, (char **)&doubleDummy)) { + (void) fprintf(dd->err, "Not in table: Something wrong\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + minNv = *doubleDummy; + } + + if (!Cudd_IsConstant(Nnv)) { + if (!st_lookup(mintermTable, (char *)Nnv, (char **)&doubleDummy)) { + (void) fprintf(dd->err, "Not in table: Something wrong\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + minNnv = *doubleDummy; + } + + if (minNv < minNnv) { + temp = Nv; + Nv = Nnv; + Nnv = temp; + switched = 1; + } + + /* build gt, ht recursively */ + if (Nv != zero) { + factorsNv = BuildConjuncts(dd, Nv, distanceTable, + cacheTable, approxDistance, maxLocalRef, + ghTable, mintermTable); + if (factorsNv == NULL) return(NULL); + freeNv = FactorsNotStored(factorsNv); + factorsNv = (freeNv) ? FactorsUncomplement(factorsNv) : factorsNv; + cuddRef(factorsNv->g); + cuddRef(factorsNv->h); + + /* Deal with the zero case */ + if (Nnv == zero) { + /* is responsible for freeing factorsNv */ + factors = ZeroCase(dd, node, factorsNv, ghTable, + cacheTable, switched); + if (freeNv) FREE(factorsNv); + return(factors); + } + } + + /* build ge, he recursively */ + if (Nnv != zero) { + factorsNnv = BuildConjuncts(dd, Nnv, distanceTable, + cacheTable, approxDistance, maxLocalRef, + ghTable, mintermTable); + if (factorsNnv == NULL) { + Cudd_RecursiveDeref(dd, factorsNv->g); + Cudd_RecursiveDeref(dd, factorsNv->h); + if (freeNv) FREE(factorsNv); + return(NULL); + } + freeNnv = FactorsNotStored(factorsNnv); + factorsNnv = (freeNnv) ? FactorsUncomplement(factorsNnv) : factorsNnv; + cuddRef(factorsNnv->g); + cuddRef(factorsNnv->h); + + /* Deal with the zero case */ + if (Nv == zero) { + /* is responsible for freeing factorsNv */ + factors = ZeroCase(dd, node, factorsNnv, ghTable, + cacheTable, switched); + if (freeNnv) FREE(factorsNnv); + return(factors); + } + } + + /* construct the 2 pairs */ + /* g1 = x*gt + x'*ge; h1 = x*ht + x'*he; */ + /* g2 = x*gt + x'*he; h2 = x*ht + x'*ge */ + if (switched) { + factors = factorsNnv; + factorsNnv = factorsNv; + factorsNv = factors; + freeTemp = freeNv; + freeNv = freeNnv; + freeNnv = freeTemp; + } + + /* Build the factors for this node. */ + topid = N->index; + topv = dd->vars[topid]; + + g1 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->g); + if (g1 == NULL) { + Cudd_RecursiveDeref(dd, factorsNv->g); + Cudd_RecursiveDeref(dd, factorsNv->h); + Cudd_RecursiveDeref(dd, factorsNnv->g); + Cudd_RecursiveDeref(dd, factorsNnv->h); + if (freeNv) FREE(factorsNv); + if (freeNnv) FREE(factorsNnv); + return(NULL); + } + + cuddRef(g1); + + h1 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->h); + if (h1 == NULL) { + Cudd_RecursiveDeref(dd, factorsNv->g); + Cudd_RecursiveDeref(dd, factorsNv->h); + Cudd_RecursiveDeref(dd, factorsNnv->g); + Cudd_RecursiveDeref(dd, factorsNnv->h); + Cudd_RecursiveDeref(dd, g1); + if (freeNv) FREE(factorsNv); + if (freeNnv) FREE(factorsNnv); + return(NULL); + } + + cuddRef(h1); + + g2 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->h); + if (g2 == NULL) { + Cudd_RecursiveDeref(dd, factorsNv->h); + Cudd_RecursiveDeref(dd, factorsNv->g); + Cudd_RecursiveDeref(dd, factorsNnv->g); + Cudd_RecursiveDeref(dd, factorsNnv->h); + Cudd_RecursiveDeref(dd, g1); + Cudd_RecursiveDeref(dd, h1); + if (freeNv) FREE(factorsNv); + if (freeNnv) FREE(factorsNnv); + return(NULL); + } + cuddRef(g2); + Cudd_RecursiveDeref(dd, factorsNv->g); + Cudd_RecursiveDeref(dd, factorsNnv->h); + + h2 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->g); + if (h2 == NULL) { + Cudd_RecursiveDeref(dd, factorsNv->g); + Cudd_RecursiveDeref(dd, factorsNv->h); + Cudd_RecursiveDeref(dd, factorsNnv->g); + Cudd_RecursiveDeref(dd, factorsNnv->h); + Cudd_RecursiveDeref(dd, g1); + Cudd_RecursiveDeref(dd, h1); + Cudd_RecursiveDeref(dd, g2); + if (freeNv) FREE(factorsNv); + if (freeNnv) FREE(factorsNnv); + return(NULL); + } + cuddRef(h2); + Cudd_RecursiveDeref(dd, factorsNv->h); + Cudd_RecursiveDeref(dd, factorsNnv->g); + if (freeNv) FREE(factorsNv); + if (freeNnv) FREE(factorsNnv); + + /* check for each pair in tables and choose one */ + factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem); + if (outOfMem) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd, g1); + Cudd_RecursiveDeref(dd, h1); + Cudd_RecursiveDeref(dd, g2); + Cudd_RecursiveDeref(dd, h2); + return(NULL); + } + if (factors != NULL) { + if ((factors->g == g1) || (factors->g == h1)) { + Cudd_RecursiveDeref(dd, g2); + Cudd_RecursiveDeref(dd, h2); + } else { + Cudd_RecursiveDeref(dd, g1); + Cudd_RecursiveDeref(dd, h1); + } + return(factors); + } + + /* if not in tables, pick one pair */ + factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable); + if (factors == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + Cudd_RecursiveDeref(dd, g1); + Cudd_RecursiveDeref(dd, h1); + Cudd_RecursiveDeref(dd, g2); + Cudd_RecursiveDeref(dd, h2); + } else { + /* now free what was created and not used */ + if ((factors->g == g1) || (factors->g == h1)) { + Cudd_RecursiveDeref(dd, g2); + Cudd_RecursiveDeref(dd, h2); + } else { + Cudd_RecursiveDeref(dd, g1); + Cudd_RecursiveDeref(dd, h1); + } + } + + return(factors); + +} /* end of BuildConjuncts */ + + +/**Function******************************************************************** + + Synopsis [Procedure to compute two conjunctive factors of f and place in *c1 and *c2.] + + Description [Procedure to compute two conjunctive factors of f and + place in *c1 and *c2. Sets up the required data - table of distances + from the constant and local reference count. Also minterm table. ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +static int +cuddConjunctsAux( + DdManager * dd, + DdNode * f, + DdNode ** c1, + DdNode ** c2) +{ + st_table *distanceTable = NULL; + st_table *cacheTable = NULL; + st_table *mintermTable = NULL; + st_table *ghTable = NULL; + st_generator *stGen; + char *key, *value; + Conjuncts *factors; + int distance, approxDistance; + double max, minterms; + int freeFactors; + NodeStat *nodeStat; + int maxLocalRef; + + /* initialize */ + *c1 = NULL; + *c2 = NULL; + + /* initialize distances table */ + distanceTable = st_init_table(st_ptrcmp,st_ptrhash); + if (distanceTable == NULL) goto outOfMem; + + /* make the entry for the constant */ + nodeStat = ALLOC(NodeStat, 1); + if (nodeStat == NULL) goto outOfMem; + nodeStat->distance = 0; + nodeStat->localRef = 1; + if (st_insert(distanceTable, (char *)one, (char *)nodeStat) == ST_OUT_OF_MEM) { + goto outOfMem; + } + + /* Count node distances from constant. */ + nodeStat = CreateBotDist(f, distanceTable); + if (nodeStat == NULL) goto outOfMem; + + /* set the distance for the decomposition points */ + approxDistance = (DEPTH < nodeStat->distance) ? nodeStat->distance : DEPTH; + distance = nodeStat->distance; + + if (distance < approxDistance) { + /* Too small to bother. */ + *c1 = f; + *c2 = DD_ONE(dd); + cuddRef(*c1); cuddRef(*c2); + stGen = st_init_gen(distanceTable); + if (stGen == NULL) goto outOfMem; + while(st_gen(stGen, (char **)&key, (char **)&value)) { + FREE(value); + } + st_free_gen(stGen); stGen = NULL; + st_free_table(distanceTable); + return(1); + } + + /* record the maximum local reference count */ + maxLocalRef = 0; + stGen = st_init_gen(distanceTable); + if (stGen == NULL) goto outOfMem; + while(st_gen(stGen, (char **)&key, (char **)&value)) { + nodeStat = (NodeStat *)value; + maxLocalRef = (nodeStat->localRef > maxLocalRef) ? + nodeStat->localRef : maxLocalRef; + } + st_free_gen(stGen); stGen = NULL; + + + /* Count minterms for each node. */ + max = pow(2.0, (double)Cudd_SupportSize(dd,f)); /* potential overflow */ + mintermTable = st_init_table(st_ptrcmp,st_ptrhash); + if (mintermTable == NULL) goto outOfMem; + minterms = CountMinterms(f, max, mintermTable, dd->err); + if (minterms == -1.0) goto outOfMem; + + lastTimeG = Cudd_Random() & 1; + cacheTable = st_init_table(st_ptrcmp, st_ptrhash); + if (cacheTable == NULL) goto outOfMem; + ghTable = st_init_table(st_ptrcmp, st_ptrhash); + if (ghTable == NULL) goto outOfMem; + + /* Build conjuncts. */ + factors = BuildConjuncts(dd, f, distanceTable, cacheTable, + approxDistance, maxLocalRef, ghTable, mintermTable); + if (factors == NULL) goto outOfMem; + + /* free up tables */ + stGen = st_init_gen(distanceTable); + if (stGen == NULL) goto outOfMem; + while(st_gen(stGen, (char **)&key, (char **)&value)) { + FREE(value); + } + st_free_gen(stGen); stGen = NULL; + st_free_table(distanceTable); distanceTable = NULL; + st_free_table(ghTable); ghTable = NULL; + + stGen = st_init_gen(mintermTable); + if (stGen == NULL) goto outOfMem; + while(st_gen(stGen, (char **)&key, (char **)&value)) { + FREE(value); + } + st_free_gen(stGen); stGen = NULL; + st_free_table(mintermTable); mintermTable = NULL; + + freeFactors = FactorsNotStored(factors); + factors = (freeFactors) ? FactorsUncomplement(factors) : factors; + if (factors != NULL) { + *c1 = factors->g; + *c2 = factors->h; + cuddRef(*c1); + cuddRef(*c2); + if (freeFactors) FREE(factors); + +#if 0 + if ((*c1 == f) && (!Cudd_IsConstant(f))) { + assert(*c2 == one); + } + if ((*c2 == f) && (!Cudd_IsConstant(f))) { + assert(*c1 == one); + } + + if ((*c1 != one) && (!Cudd_IsConstant(f))) { + assert(!Cudd_bddLeq(dd, *c2, *c1)); + } + if ((*c2 != one) && (!Cudd_IsConstant(f))) { + assert(!Cudd_bddLeq(dd, *c1, *c2)); + } +#endif + } + + stGen = st_init_gen(cacheTable); + if (stGen == NULL) goto outOfMem; + while(st_gen(stGen, (char **)&key, (char **)&value)) { + ConjunctsFree(dd, (Conjuncts *)value); + } + st_free_gen(stGen); stGen = NULL; + + st_free_table(cacheTable); cacheTable = NULL; + + return(1); + +outOfMem: + if (distanceTable != NULL) { + stGen = st_init_gen(distanceTable); + if (stGen == NULL) goto outOfMem; + while(st_gen(stGen, (char **)&key, (char **)&value)) { + FREE(value); + } + st_free_gen(stGen); stGen = NULL; + st_free_table(distanceTable); distanceTable = NULL; + } + if (mintermTable != NULL) { + stGen = st_init_gen(mintermTable); + if (stGen == NULL) goto outOfMem; + while(st_gen(stGen, (char **)&key, (char **)&value)) { + FREE(value); + } + st_free_gen(stGen); stGen = NULL; + st_free_table(mintermTable); mintermTable = NULL; + } + if (ghTable != NULL) st_free_table(ghTable); + if (cacheTable != NULL) { + stGen = st_init_gen(cacheTable); + if (stGen == NULL) goto outOfMem; + while(st_gen(stGen, (char **)&key, (char **)&value)) { + ConjunctsFree(dd, (Conjuncts *)value); + } + st_free_gen(stGen); stGen = NULL; + st_free_table(cacheTable); cacheTable = NULL; + } + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + +} /* end of cuddConjunctsAux */ diff --git a/abc70930/src/bdd/cudd/cuddEssent.c b/abc70930/src/bdd/cudd/cuddEssent.c new file mode 100644 index 00000000..db4b8b49 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddEssent.c @@ -0,0 +1,279 @@ +/**CFile*********************************************************************** + + FileName [cuddEssent.c] + + PackageName [cudd] + + Synopsis [Functions for the detection of essential variables.] + + Description [External procedures included in this file: +
    +
  • Cudd_FindEssential() +
  • Cudd_bddIsVarEssential() +
+ Static procedures included in this module: +
    +
  • ddFindEssentialRecur() +
] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddEssent.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * ddFindEssentialRecur ARGS((DdManager *dd, DdNode *f)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Finds the essential variables of a DD.] + + Description [Returns the cube of the essential variables. A positive + literal means that the variable must be set to 1 for the function to be + 1. A negative literal means that the variable must be set to 0 for the + function to be 1. Returns a pointer to the cube BDD if successful; + NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddIsVarEssential] + +******************************************************************************/ +DdNode * +Cudd_FindEssential( + DdManager * dd, + DdNode * f) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = ddFindEssentialRecur(dd,f); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_FindEssential */ + + +/**Function******************************************************************** + + Synopsis [Determines whether a given variable is essential with a + given phase in a BDD.] + + Description [Determines whether a given variable is essential with a + given phase in a BDD. Uses Cudd_bddIteConstant. Returns 1 if phase == 1 + and f-->x_id, or if phase == 0 and f-->x_id'.] + + SideEffects [None] + + SeeAlso [Cudd_FindEssential] + +******************************************************************************/ +int +Cudd_bddIsVarEssential( + DdManager * manager, + DdNode * f, + int id, + int phase) +{ + DdNode *var; + int res; + DdNode *one, *zero; + + one = DD_ONE(manager); + zero = Cudd_Not(one); + + var = cuddUniqueInter(manager, id, one, zero); + + var = Cudd_NotCond(var,phase == 0); + + res = Cudd_bddIteConstant(manager, Cudd_Not(f), one, var) == one; + + return(res); + +} /* end of Cudd_bddIsVarEssential */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_FindEssential.] + + Description [Implements the recursive step of Cudd_FindEssential. + Returns a pointer to the cube BDD if successful; NULL otherwise.] + + SideEffects [None] + +******************************************************************************/ +static DdNode * +ddFindEssentialRecur( + DdManager * dd, + DdNode * f) +{ + DdNode *T, *E, *F; + DdNode *essT, *essE, *res; + int index; + DdNode *one, *lzero, *azero; + + one = DD_ONE(dd); + F = Cudd_Regular(f); + /* If f is constant the set of essential variables is empty. */ + if (cuddIsConstant(F)) return(one); + + res = cuddCacheLookup1(dd,Cudd_FindEssential,f); + if (res != NULL) { + return(res); + } + + lzero = Cudd_Not(one); + azero = DD_ZERO(dd); + /* Find cofactors: here f is non-constant. */ + T = cuddT(F); + E = cuddE(F); + if (Cudd_IsComplement(f)) { + T = Cudd_Not(T); E = Cudd_Not(E); + } + + index = F->index; + if (Cudd_IsConstant(T) && T != lzero && T != azero) { + /* if E is zero, index is essential, otherwise there are no + ** essentials, because index is not essential and no other variable + ** can be, since setting index = 1 makes the function constant and + ** different from 0. + */ + if (E == lzero || E == azero) { + res = dd->vars[index]; + } else { + res = one; + } + } else if (T == lzero || T == azero) { + if (Cudd_IsConstant(E)) { /* E cannot be zero here */ + res = Cudd_Not(dd->vars[index]); + } else { /* E == non-constant */ + /* find essentials in the else branch */ + essE = ddFindEssentialRecur(dd,E); + if (essE == NULL) { + return(NULL); + } + cuddRef(essE); + + /* add index to the set with negative phase */ + res = cuddUniqueInter(dd,index,one,Cudd_Not(essE)); + if (res == NULL) { + Cudd_RecursiveDeref(dd,essE); + return(NULL); + } + res = Cudd_Not(res); + cuddDeref(essE); + } + } else { /* T == non-const */ + if (E == lzero || E == azero) { + /* find essentials in the then branch */ + essT = ddFindEssentialRecur(dd,T); + if (essT == NULL) { + return(NULL); + } + cuddRef(essT); + + /* add index to the set with positive phase */ + /* use And because essT may be complemented */ + res = cuddBddAndRecur(dd,dd->vars[index],essT); + if (res == NULL) { + Cudd_RecursiveDeref(dd,essT); + return(NULL); + } + cuddDeref(essT); + } else if (!Cudd_IsConstant(E)) { + /* if E is a non-zero constant there are no essentials + ** because T is non-constant. + */ + essT = ddFindEssentialRecur(dd,T); + if (essT == NULL) { + return(NULL); + } + if (essT == one) { + res = one; + } else { + cuddRef(essT); + essE = ddFindEssentialRecur(dd,E); + if (essE == NULL) { + Cudd_RecursiveDeref(dd,essT); + return(NULL); + } + cuddRef(essE); + + /* res = intersection(essT, essE) */ + res = cuddBddLiteralSetIntersectionRecur(dd,essT,essE); + if (res == NULL) { + Cudd_RecursiveDeref(dd,essT); + Cudd_RecursiveDeref(dd,essE); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd,essT); + Cudd_RecursiveDeref(dd,essE); + cuddDeref(res); + } + } else { /* E is a non-zero constant */ + res = one; + } + } + + cuddCacheInsert1(dd,Cudd_FindEssential, f, res); + return(res); + +} /* end of ddFindEssentialRecur */ + diff --git a/abc70930/src/bdd/cudd/cuddExact.c b/abc70930/src/bdd/cudd/cuddExact.c new file mode 100644 index 00000000..6852be68 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddExact.c @@ -0,0 +1,1004 @@ +/**CFile*********************************************************************** + + FileName [cuddExact.c] + + PackageName [cudd] + + Synopsis [Functions for exact variable reordering.] + + Description [External procedures included in this file: +
    +
+ Internal procedures included in this module: +
    +
  • cuddExact() +
+ Static procedures included in this module: +
    +
  • getMaxBinomial() +
  • gcd() +
  • getMatrix() +
  • freeMatrix() +
  • getLevelKeys() +
  • ddShuffle() +
  • ddSiftUp() +
  • updateUB() +
  • ddCountRoots() +
  • ddClearGlobal() +
  • computeLB() +
  • updateEntry() +
  • pushDown() +
  • initSymmInfo() +
] + + Author [Cheng Hua, Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddExact.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +#ifdef DD_STATS +static int ddTotalShuffles; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int getMaxBinomial ARGS((int n)); +static int gcd ARGS((int x, int y)); +static DdHalfWord ** getMatrix ARGS((int rows, int cols)); +static void freeMatrix ARGS((DdHalfWord **matrix)); +static int getLevelKeys ARGS((DdManager *table, int l)); +static int ddShuffle ARGS((DdManager *table, DdHalfWord *permutation, int lower, int upper)); +static int ddSiftUp ARGS((DdManager *table, int x, int xLow)); +static int updateUB ARGS((DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper)); +static int ddCountRoots ARGS((DdManager *table, int lower, int upper)); +static void ddClearGlobal ARGS((DdManager *table, int lower, int maxlevel)); +static int computeLB ARGS((DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level)); +static int updateEntry ARGS((DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper)); +static void pushDown ARGS((DdHalfWord *order, int j, int level)); +static DdHalfWord * initSymmInfo ARGS((DdManager *table, int lower, int upper)); +static int checkSymmInfo ARGS((DdManager *table, DdHalfWord *symmInfo, int index, int level)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Exact variable ordering algorithm.] + + Description [Exact variable ordering algorithm. Finds an optimum + order for the variables between lower and upper. Returns 1 if + successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddExact( + DdManager * table, + int lower, + int upper) +{ + int k, i, j; + int maxBinomial, oldSubsets, newSubsets; + int subsetCost; + int size; /* number of variables to be reordered */ + int unused, nvars, level, result; + int upperBound, lowerBound, cost; + int roots; + char *mask = NULL; + DdHalfWord *symmInfo = NULL; + DdHalfWord **newOrder = NULL; + DdHalfWord **oldOrder = NULL; + int *newCost = NULL; + int *oldCost = NULL; + DdHalfWord **tmpOrder; + int *tmpCost; + DdHalfWord *bestOrder = NULL; + DdHalfWord *order; +#ifdef DD_STATS + int ddTotalSubsets; +#endif + + /* Restrict the range to be reordered by excluding unused variables + ** at the two ends. */ + while (table->subtables[lower].keys == 1 && + table->vars[table->invperm[lower]]->ref == 1 && + lower < upper) + lower++; + while (table->subtables[upper].keys == 1 && + table->vars[table->invperm[upper]]->ref == 1 && + lower < upper) + upper--; + if (lower == upper) return(1); /* trivial problem */ + + /* Apply symmetric sifting to get a good upper bound and to extract + ** symmetry information. */ + result = cuddSymmSiftingConv(table,lower,upper); + if (result == 0) goto cuddExactOutOfMem; + +#ifdef DD_STATS + (void) fprintf(table->out,"\n"); + ddTotalShuffles = 0; + ddTotalSubsets = 0; +#endif + + /* Initialization. */ + nvars = table->size; + size = upper - lower + 1; + /* Count unused variable among those to be reordered. This is only + ** used to compute maxBinomial. */ + unused = 0; + for (i = lower + 1; i < upper; i++) { + if (table->subtables[i].keys == 1 && + table->vars[table->invperm[i]]->ref == 1) + unused++; + } + + /* Find the maximum number of subsets we may have to store. */ + maxBinomial = getMaxBinomial(size - unused); + if (maxBinomial == -1) goto cuddExactOutOfMem; + + newOrder = getMatrix(maxBinomial, size); + if (newOrder == NULL) goto cuddExactOutOfMem; + + newCost = ALLOC(int, maxBinomial); + if (newCost == NULL) goto cuddExactOutOfMem; + + oldOrder = getMatrix(maxBinomial, size); + if (oldOrder == NULL) goto cuddExactOutOfMem; + + oldCost = ALLOC(int, maxBinomial); + if (oldCost == NULL) goto cuddExactOutOfMem; + + bestOrder = ALLOC(DdHalfWord, size); + if (bestOrder == NULL) goto cuddExactOutOfMem; + + mask = ALLOC(char, nvars); + if (mask == NULL) goto cuddExactOutOfMem; + + symmInfo = initSymmInfo(table, lower, upper); + if (symmInfo == NULL) goto cuddExactOutOfMem; + + roots = ddCountRoots(table, lower, upper); + + /* Initialize the old order matrix for the empty subset and the best + ** order to the current order. The cost for the empty subset includes + ** the cost of the levels between upper and the constants. These levels + ** are not going to change. Hence, we count them only once. + */ + oldSubsets = 1; + for (i = 0; i < size; i++) { + oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower]; + } + subsetCost = table->constants.keys; + for (i = upper + 1; i < nvars; i++) + subsetCost += getLevelKeys(table,i); + oldCost[0] = subsetCost; + /* The upper bound is initialized to the current size of the BDDs. */ + upperBound = table->keys - table->isolated; + + /* Now consider subsets of increasing size. */ + for (k = 1; k <= size; k++) { +#if DD_STATS + (void) fprintf(table->out,"Processing subsets of size %d\n", k); + fflush(table->out); +#endif + newSubsets = 0; + level = size - k; /* offset of first bottom variable */ + + for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */ + order = oldOrder[i]; + cost = oldCost[i]; + lowerBound = computeLB(table, order, roots, cost, lower, upper, + level); + if (lowerBound >= upperBound) + continue; + /* Impose new order. */ + result = ddShuffle(table, order, lower, upper); + if (result == 0) goto cuddExactOutOfMem; + upperBound = updateUB(table,upperBound,bestOrder,lower,upper); + /* For each top bottom variable. */ + for (j = level; j >= 0; j--) { + /* Skip unused variables. */ + if (table->subtables[j+lower-1].keys == 1 && + table->vars[table->invperm[j+lower-1]]->ref == 1) continue; + /* Find cost under this order. */ + subsetCost = cost + getLevelKeys(table, lower + level); + newSubsets = updateEntry(table, order, level, subsetCost, + newOrder, newCost, newSubsets, mask, + lower, upper); + if (j == 0) + break; + if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0) + continue; + pushDown(order,j-1,level); + /* Impose new order. */ + result = ddShuffle(table, order, lower, upper); + if (result == 0) goto cuddExactOutOfMem; + upperBound = updateUB(table,upperBound,bestOrder,lower,upper); + } /* for each bottom variable */ + } /* for each subset of size k */ + + /* New orders become old orders in preparation for next iteration. */ + tmpOrder = oldOrder; tmpCost = oldCost; + oldOrder = newOrder; oldCost = newCost; + newOrder = tmpOrder; newCost = tmpCost; +#ifdef DD_STATS + ddTotalSubsets += newSubsets; +#endif + oldSubsets = newSubsets; + } + result = ddShuffle(table, bestOrder, lower, upper); + if (result == 0) goto cuddExactOutOfMem; +#ifdef DD_STATS +#ifdef DD_VERBOSE + (void) fprintf(table->out,"\n"); +#endif + (void) fprintf(table->out,"#:S_EXACT %8d: total subsets\n", + ddTotalSubsets); + (void) fprintf(table->out,"#:H_EXACT %8d: total shuffles", + ddTotalShuffles); +#endif + + freeMatrix(newOrder); + freeMatrix(oldOrder); + FREE(bestOrder); + FREE(oldCost); + FREE(newCost); + FREE(symmInfo); + FREE(mask); + return(1); + +cuddExactOutOfMem: + + if (newOrder != NULL) freeMatrix(newOrder); + if (oldOrder != NULL) freeMatrix(oldOrder); + if (bestOrder != NULL) FREE(bestOrder); + if (oldCost != NULL) FREE(oldCost); + if (newCost != NULL) FREE(newCost); + if (symmInfo != NULL) FREE(symmInfo); + if (mask != NULL) FREE(mask); + table->errorCode = CUDD_MEMORY_OUT; + return(0); + +} /* end of cuddExact */ + + +/**Function******************************************************************** + + Synopsis [Returns the maximum value of (n choose k) for a given n.] + + Description [Computes the maximum value of (n choose k) for a given + n. The maximum value occurs for k = n/2 when n is even, or k = + (n-1)/2 when n is odd. The algorithm used in this procedure is + quite inefficient, but it avoids intermediate overflow problems. + Returns the computed value if successful; -1 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +getMaxBinomial( + int n) +{ + int *numerator; + int i, j, k, y, g, result; + + k = (n & ~1) >> 1; + + numerator = ALLOC(int,k); + if (numerator == NULL) return(-1); + + for (i = 0; i < k; i++) + numerator[i] = n - i; + + for (i = k; i > 1; i--) { + y = i; + for (j = 0; j < k; j++) { + if (numerator[j] == 1) continue; + g = gcd(numerator[j], y); + if (g != 1) { + numerator[j] /= g; + if (y == g) break; + y /= g; + } + } + } + + result = 1; + for (i = 0; i < k; i++) + result *= numerator[i]; + + FREE(numerator); + return(result); + +} /* end of getMaxBinomial */ + + +/**Function******************************************************************** + + Synopsis [Returns the gcd of two integers.] + + Description [Returns the gcd of two integers. Uses the binary GCD + algorithm described in Cormen, Leiserson, and Rivest.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +gcd( + int x, + int y) +{ + int a; + int b; + int lsbMask; + + /* GCD(n,0) = n. */ + if (x == 0) return(y); + if (y == 0) return(x); + + a = x; b = y; lsbMask = 1; + + /* Here both a and b are != 0. The iteration maintains this invariant. + ** Hence, we only need to check for when they become equal. + */ + while (a != b) { + if (a & lsbMask) { + if (b & lsbMask) { /* both odd */ + if (a < b) { + b = (b - a) >> 1; + } else { + a = (a - b) >> 1; + } + } else { /* a odd, b even */ + b >>= 1; + } + } else { + if (b & lsbMask) { /* a even, b odd */ + a >>= 1; + } else { /* both even */ + lsbMask <<= 1; + } + } + } + + return(a); + +} /* end of gcd */ + + +/**Function******************************************************************** + + Synopsis [Allocates a two-dimensional matrix of ints.] + + Description [Allocates a two-dimensional matrix of ints. + Returns the pointer to the matrix if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [freeMatrix] + +******************************************************************************/ +static DdHalfWord ** +getMatrix( + int rows /* number of rows */, + int cols /* number of columns */) +{ + DdHalfWord **matrix; + int i; + + if (cols*rows == 0) return(NULL); + matrix = ALLOC(DdHalfWord *, rows); + if (matrix == NULL) return(NULL); + matrix[0] = ALLOC(DdHalfWord, cols*rows); + if (matrix[0] == NULL) return(NULL); + for (i = 1; i < rows; i++) { + matrix[i] = matrix[i-1] + cols; + } + return(matrix); + +} /* end of getMatrix */ + + +/**Function******************************************************************** + + Synopsis [Frees a two-dimensional matrix allocated by getMatrix.] + + Description [] + + SideEffects [None] + + SeeAlso [getMatrix] + +******************************************************************************/ +static void +freeMatrix( + DdHalfWord ** matrix) +{ + FREE(matrix[0]); + FREE(matrix); + return; + +} /* end of freeMatrix */ + + +/**Function******************************************************************** + + Synopsis [Returns the number of nodes at one level of a unique table.] + + Description [Returns the number of nodes at one level of a unique table. + The projection function, if isolated, is not counted.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +getLevelKeys( + DdManager * table, + int l) +{ + int isolated; + int x; /* x is an index */ + + x = table->invperm[l]; + isolated = table->vars[x]->ref == 1; + + return(table->subtables[l].keys - isolated); + +} /* end of getLevelKeys */ + + +/**Function******************************************************************** + + Synopsis [Reorders variables according to a given permutation.] + + Description [Reorders variables according to a given permutation. + The i-th permutation array contains the index of the variable that + should be brought to the i-th level. ddShuffle assumes that no + dead nodes are present and that the interaction matrix is properly + initialized. The reordering is achieved by a series of upward sifts. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ddShuffle( + DdManager * table, + DdHalfWord * permutation, + int lower, + int upper) +{ + DdHalfWord index; + int level; + int position; + int numvars; + int result; +#ifdef DD_STATS + long localTime; + int initialSize; +#ifdef DD_VERBOSE + int finalSize; +#endif + int previousSize; +#endif + +#ifdef DD_STATS + localTime = util_cpu_time(); + initialSize = table->keys - table->isolated; +#endif + + numvars = table->size; + +#if 0 + (void) fprintf(table->out,"%d:", ddTotalShuffles); + for (level = 0; level < numvars; level++) { + (void) fprintf(table->out," %d", table->invperm[level]); + } + (void) fprintf(table->out,"\n"); +#endif + + for (level = 0; level <= upper - lower; level++) { + index = permutation[level]; + position = table->perm[index]; +#ifdef DD_STATS + previousSize = table->keys - table->isolated; +#endif + result = ddSiftUp(table,position,level+lower); + if (!result) return(0); + } + +#ifdef DD_STATS + ddTotalShuffles++; +#ifdef DD_VERBOSE + finalSize = table->keys - table->isolated; + if (finalSize < initialSize) { + (void) fprintf(table->out,"-"); + } else if (finalSize > initialSize) { + (void) fprintf(table->out,"+"); + } else { + (void) fprintf(table->out,"="); + } + if ((ddTotalShuffles & 63) == 0) (void) fprintf(table->out,"\n"); + fflush(table->out); +#endif +#endif + + return(1); + +} /* end of ddShuffle */ + + +/**Function******************************************************************** + + Synopsis [Moves one variable up.] + + Description [Takes a variable from position x and sifts it up to + position xLow; xLow should be less than or equal to x. + Returns 1 if successful; 0 otherwise] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ddSiftUp( + DdManager * table, + int x, + int xLow) +{ + int y; + int size; + + y = cuddNextLow(table,x); + while (y >= xLow) { + size = cuddSwapInPlace(table,y,x); + if (size == 0) { + return(0); + } + x = y; + y = cuddNextLow(table,x); + } + return(1); + +} /* end of ddSiftUp */ + + +/**Function******************************************************************** + + Synopsis [Updates the upper bound and saves the best order seen so far.] + + Description [Updates the upper bound and saves the best order seen so far. + Returns the current value of the upper bound.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +updateUB( + DdManager * table, + int oldBound, + DdHalfWord * bestOrder, + int lower, + int upper) +{ + int i; + int newBound = table->keys - table->isolated; + + if (newBound < oldBound) { +#ifdef DD_STATS + (void) fprintf(table->out,"New upper bound = %d\n", newBound); + fflush(table->out); +#endif + for (i = lower; i <= upper; i++) + bestOrder[i-lower] = (DdHalfWord) table->invperm[i]; + return(newBound); + } else { + return(oldBound); + } + +} /* end of updateUB */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of roots.] + + Description [Counts the number of roots at the levels between lower and + upper. The computation is based on breadth-first search. + A node is a root if it is not reachable from any previously visited node. + (All the nodes at level lower are therefore considered roots.) + The visited flag uses the LSB of the next pointer. Returns the root + count. The roots that are constant nodes are always ignored.] + + SideEffects [None] + + SeeAlso [ddClearGlobal] + +******************************************************************************/ +static int +ddCountRoots( + DdManager * table, + int lower, + int upper) +{ + int i,j; + DdNode *f; + DdNodePtr *nodelist; + DdNode *sentinel = &(table->sentinel); + int slots; + int roots = 0; + int maxlevel = lower; + + for (i = lower; i <= upper; i++) { + nodelist = table->subtables[i].nodelist; + slots = table->subtables[i].slots; + for (j = 0; j < slots; j++) { + f = nodelist[j]; + while (f != sentinel) { + /* A node is a root of the DAG if it cannot be + ** reached by nodes above it. If a node was never + ** reached during the previous depth-first searches, + ** then it is a root, and we start a new depth-first + ** search from it. + */ + if (!Cudd_IsComplement(f->next)) { + if (f != table->vars[f->index]) { + roots++; + } + } + if (!Cudd_IsConstant(cuddT(f))) { + cuddT(f)->next = Cudd_Complement(cuddT(f)->next); + if (table->perm[cuddT(f)->index] > maxlevel) + maxlevel = table->perm[cuddT(f)->index]; + } + if (!Cudd_IsConstant(cuddE(f))) { + Cudd_Regular(cuddE(f))->next = + Cudd_Complement(Cudd_Regular(cuddE(f))->next); + if (table->perm[Cudd_Regular(cuddE(f))->index] > maxlevel) + maxlevel = table->perm[Cudd_Regular(cuddE(f))->index]; + } + f = Cudd_Regular(f->next); + } + } + } + ddClearGlobal(table, lower, maxlevel); + + return(roots); + +} /* end of ddCountRoots */ + + +/**Function******************************************************************** + + Synopsis [Scans the DD and clears the LSB of the next pointers.] + + Description [Scans the DD and clears the LSB of the next pointers. + The LSB of the next pointers are used as markers to tell whether a + node was reached. Once the roots are counted, these flags are + reset.] + + SideEffects [None] + + SeeAlso [ddCountRoots] + +******************************************************************************/ +static void +ddClearGlobal( + DdManager * table, + int lower, + int maxlevel) +{ + int i,j; + DdNode *f; + DdNodePtr *nodelist; + DdNode *sentinel = &(table->sentinel); + int slots; + + for (i = lower; i <= maxlevel; i++) { + nodelist = table->subtables[i].nodelist; + slots = table->subtables[i].slots; + for (j = 0; j < slots; j++) { + f = nodelist[j]; + while (f != sentinel) { + f->next = Cudd_Regular(f->next); + f = f->next; + } + } + } + +} /* end of ddClearGlobal */ + + +/**Function******************************************************************** + + Synopsis [Computes a lower bound on the size of a BDD.] + + Description [Computes a lower bound on the size of a BDD from the + following factors: +
    +
  • size of the lower part of it; +
  • size of the part of the upper part not subjected to reordering; +
  • number of roots in the part of the BDD subjected to reordering; +
  • variable in the support of the roots in the upper part of the + BDD subjected to reordering. +
      ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +computeLB( + DdManager * table /* manager */, + DdHalfWord * order /* optimal order for the subset */, + int roots /* roots between lower and upper */, + int cost /* minimum cost for the subset */, + int lower /* lower level to be reordered */, + int upper /* upper level to be reordered */, + int level /* offset for the current top bottom var */ + ) +{ + int i; + int lb = cost; + int lb1 = 0; + int lb2; + int support; + DdHalfWord ref; + + /* The levels not involved in reordering are not going to change. + ** Add their sizes to the lower bound. + */ + for (i = 0; i < lower; i++) { + lb += getLevelKeys(table,i); + } + /* If a variable is in the support, then there is going + ** to be at least one node labeled by that variable. + */ + for (i = lower; i <= lower+level; i++) { + support = table->subtables[i].keys > 1 || + table->vars[order[i-lower]]->ref > 1; + lb1 += support; + } + + /* Estimate the number of nodes required to connect the roots to + ** the nodes in the bottom part. */ + if (lower+level+1 < table->size) { + if (lower+level < upper) + ref = table->vars[order[level+1]]->ref; + else + ref = table->vars[table->invperm[upper+1]]->ref; + lb2 = table->subtables[lower+level+1].keys - + (ref > (DdHalfWord) 1) - roots; + } else { + lb2 = 0; + } + + lb += lb1 > lb2 ? lb1 : lb2; + + return(lb); + +} /* end of computeLB */ + + +/**Function******************************************************************** + + Synopsis [Updates entry for a subset.] + + Description [Updates entry for a subset. Finds the subset, if it exists. + If the new order for the subset has lower cost, or if the subset did not + exist, it stores the new order and cost. Returns the number of subsets + currently in the table.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +updateEntry( + DdManager * table, + DdHalfWord * order, + int level, + int cost, + DdHalfWord ** orders, + int * costs, + int subsets, + char * mask, + int lower, + int upper) +{ + int i, j; + int size = upper - lower + 1; + + /* Build a mask that says what variables are in this subset. */ + for (i = lower; i <= upper; i++) + mask[table->invperm[i]] = 0; + for (i = level; i < size; i++) + mask[order[i]] = 1; + + /* Check each subset until a match is found or all subsets are examined. */ + for (i = 0; i < subsets; i++) { + DdHalfWord *subset = orders[i]; + for (j = level; j < size; j++) { + if (mask[subset[j]] == 0) + break; + } + if (j == size) /* no mismatches: success */ + break; + } + if (i == subsets || cost < costs[i]) { /* add or replace */ + for (j = 0; j < size; j++) + orders[i][j] = order[j]; + costs[i] = cost; + subsets += (i == subsets); + } + return(subsets); + +} /* end of updateEntry */ + + +/**Function******************************************************************** + + Synopsis [Pushes a variable in the order down to position "level."] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +pushDown( + DdHalfWord * order, + int j, + int level) +{ + int i; + DdHalfWord tmp; + + tmp = order[j]; + for (i = j; i < level; i++) { + order[i] = order[i+1]; + } + order[level] = tmp; + return; + +} /* end of pushDown */ + + +/**Function******************************************************************** + + Synopsis [Gathers symmetry information.] + + Description [Translates the symmetry information stored in the next + field of each subtable from level to indices. This procedure is called + immediately after symmetric sifting, so that the next fields are correct. + By translating this informaton in terms of indices, we make it independent + of subsequent reorderings. The format used is that of the next fields: + a circular list where each variable points to the next variable in the + same symmetry group. Only the entries between lower and upper are + considered. The procedure returns a pointer to an array + holding the symmetry information if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [checkSymmInfo] + +******************************************************************************/ +static DdHalfWord * +initSymmInfo( + DdManager * table, + int lower, + int upper) +{ + int level, index, next, nextindex; + DdHalfWord *symmInfo; + + symmInfo = ALLOC(DdHalfWord, table->size); + if (symmInfo == NULL) return(NULL); + + for (level = lower; level <= upper; level++) { + index = table->invperm[level]; + next = table->subtables[level].next; + nextindex = table->invperm[next]; + symmInfo[index] = nextindex; + } + return(symmInfo); + +} /* end of initSymmInfo */ + + +/**Function******************************************************************** + + Synopsis [Check symmetry condition.] + + Description [Returns 1 if a variable is the one with the highest index + among those belonging to a symmetry group that are in the top part of + the BDD. The top part is given by level.] + + SideEffects [None] + + SeeAlso [initSymmInfo] + +******************************************************************************/ +static int +checkSymmInfo( + DdManager * table, + DdHalfWord * symmInfo, + int index, + int level) +{ + int i; + + i = symmInfo[index]; + while (i != index) { + if (index < i && table->perm[i] <= level) + return(0); + i = symmInfo[i]; + } + return(1); + +} /* end of checkSymmInfo */ + diff --git a/abc70930/src/bdd/cudd/cuddExport.c b/abc70930/src/bdd/cudd/cuddExport.c new file mode 100644 index 00000000..d148be42 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddExport.c @@ -0,0 +1,1289 @@ +/**CFile*********************************************************************** + + FileName [cuddExport.c] + + PackageName [cudd] + + Synopsis [Export functions.] + + Description [External procedures included in this module: +
        +
      • Cudd_DumpBlif() +
      • Cudd_DumpBlifBody() +
      • Cudd_DumpDot() +
      • Cudd_DumpDaVinci() +
      • Cudd_DumpDDcal() +
      • Cudd_DumpFactoredForm() +
      + Internal procedures included in this module: +
        +
      + Static procedures included in this module: +
        +
      • ddDoDumpBlif() +
      • ddDoDumpDaVinci() +
      • ddDoDumpDDcal() +
      • ddDoDumpFactoredForm() +
      ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddExport.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int ddDoDumpBlif ARGS((DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names)); +static int ddDoDumpDaVinci ARGS((DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, long mask)); +static int ddDoDumpDDcal ARGS((DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, long mask)); +static int ddDoDumpFactoredForm ARGS((DdManager *dd, DdNode *f, FILE *fp, char **names)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Writes a blif file representing the argument BDDs.] + + Description [Writes a blif file representing the argument BDDs as a + network of multiplexers. One multiplexer is written for each BDD + node. It returns 1 in case of success; 0 otherwise (e.g., + out-of-memory, file system full, or an ADD with constants different + from 0 and 1). Cudd_DumpBlif does not close the file: This is the + caller responsibility. Cudd_DumpBlif uses a minimal unique subset of + the hexadecimal address of a node as name for it. If the argument + inames is non-null, it is assumed to hold the pointers to the names + of the inputs. Similarly for onames.] + + SideEffects [None] + + SeeAlso [Cudd_DumpBlifBody Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal + Cudd_DumpDaVinci Cudd_DumpFactoredForm] + +******************************************************************************/ +int +Cudd_DumpBlif( + DdManager * dd /* manager */, + int n /* number of output nodes to be dumped */, + DdNode ** f /* array of output nodes to be dumped */, + char ** inames /* array of input names (or NULL) */, + char ** onames /* array of output names (or NULL) */, + char * mname /* model name (or NULL) */, + FILE * fp /* pointer to the dump file */) +{ + DdNode *support = NULL; + DdNode *scan; + int *sorted = NULL; + int nvars = dd->size; + int retval; + int i; + + /* Build a bit array with the support of f. */ + sorted = ALLOC(int,nvars); + if (sorted == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + goto failure; + } + for (i = 0; i < nvars; i++) sorted[i] = 0; + + /* Take the union of the supports of each output function. */ + support = Cudd_VectorSupport(dd,f,n); + if (support == NULL) goto failure; + cuddRef(support); + scan = support; + while (!cuddIsConstant(scan)) { + sorted[scan->index] = 1; + scan = cuddT(scan); + } + Cudd_RecursiveDeref(dd,support); + support = NULL; /* so that we do not try to free it in case of failure */ + + /* Write the header (.model .inputs .outputs). */ + if (mname == NULL) { + retval = fprintf(fp,".model DD\n.inputs"); + } else { + retval = fprintf(fp,".model %s\n.inputs",mname); + } + if (retval == EOF) return(0); + + /* Write the input list by scanning the support array. */ + for (i = 0; i < nvars; i++) { + if (sorted[i]) { + if (inames == NULL) { + retval = fprintf(fp," %d", i); + } else { + retval = fprintf(fp," %s", inames[i]); + } + if (retval == EOF) goto failure; + } + } + FREE(sorted); + sorted = NULL; + + /* Write the .output line. */ + retval = fprintf(fp,"\n.outputs"); + if (retval == EOF) goto failure; + for (i = 0; i < n; i++) { + if (onames == NULL) { + retval = fprintf(fp," f%d", i); + } else { + retval = fprintf(fp," %s", onames[i]); + } + if (retval == EOF) goto failure; + } + retval = fprintf(fp,"\n"); + if (retval == EOF) goto failure; + + retval = Cudd_DumpBlifBody(dd, n, f, inames, onames, fp); + if (retval == 0) goto failure; + + /* Write trailer and return. */ + retval = fprintf(fp,".end\n"); + if (retval == EOF) goto failure; + + return(1); + +failure: + if (sorted != NULL) FREE(sorted); + if (support != NULL) Cudd_RecursiveDeref(dd,support); + return(0); + +} /* end of Cudd_DumpBlif */ + + +/**Function******************************************************************** + + Synopsis [Writes a blif body representing the argument BDDs.] + + Description [Writes a blif body representing the argument BDDs as a + network of multiplexers. One multiplexer is written for each BDD + node. It returns 1 in case of success; 0 otherwise (e.g., + out-of-memory, file system full, or an ADD with constants different + from 0 and 1). Cudd_DumpBlif does not close the file: This is the + caller responsibility. Cudd_DumpBlif uses a minimal unique subset of + the hexadecimal address of a node as name for it. If the argument + inames is non-null, it is assumed to hold the pointers to the names + of the inputs. Similarly for onames. This function prints out only + .names part.] + + SideEffects [None] + + SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal + Cudd_DumpDaVinci Cudd_DumpFactoredForm] + +******************************************************************************/ +int +Cudd_DumpBlifBody( + DdManager * dd /* manager */, + int n /* number of output nodes to be dumped */, + DdNode ** f /* array of output nodes to be dumped */, + char ** inames /* array of input names (or NULL) */, + char ** onames /* array of output names (or NULL) */, + FILE * fp /* pointer to the dump file */) +{ + st_table *visited = NULL; + int retval; + int i; + + /* Initialize symbol table for visited nodes. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + if (visited == NULL) goto failure; + + /* Call the function that really gets the job done. */ + for (i = 0; i < n; i++) { + retval = ddDoDumpBlif(dd,Cudd_Regular(f[i]),fp,visited,inames); + if (retval == 0) goto failure; + } + + /* To account for the possible complement on the root, + ** we put either a buffer or an inverter at the output of + ** the multiplexer representing the top node. + */ + for (i = 0; i < n; i++) { + if (onames == NULL) { + retval = fprintf(fp, +#if SIZEOF_VOID_P == 8 + ".names %lx f%d\n", (unsigned long) f[i] / (unsigned long) sizeof(DdNode), i); +#else + ".names %x f%d\n", (unsigned) f[i] / (unsigned) sizeof(DdNode), i); +#endif + } else { + retval = fprintf(fp, +#if SIZEOF_VOID_P == 8 + ".names %lx %s\n", (unsigned long) f[i] / (unsigned long) sizeof(DdNode), onames[i]); +#else + ".names %x %s\n", (unsigned) f[i] / (unsigned) sizeof(DdNode), onames[i]); +#endif + } + if (retval == EOF) goto failure; + if (Cudd_IsComplement(f[i])) { + retval = fprintf(fp,"0 1\n"); + } else { + retval = fprintf(fp,"1 1\n"); + } + if (retval == EOF) goto failure; + } + + st_free_table(visited); + return(1); + +failure: + if (visited != NULL) st_free_table(visited); + return(0); + +} /* end of Cudd_DumpBlifBody */ + + +/**Function******************************************************************** + + Synopsis [Writes a dot file representing the argument DDs.] + + Description [Writes a file representing the argument DDs in a format + suitable for the graph drawing program dot. + It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, + file system full). + Cudd_DumpDot does not close the file: This is the caller + responsibility. Cudd_DumpDot uses a minimal unique subset of the + hexadecimal address of a node as name for it. + If the argument inames is non-null, it is assumed to hold the pointers + to the names of the inputs. Similarly for onames. + Cudd_DumpDot uses the following convention to draw arcs: +
        +
      • solid line: THEN arcs; +
      • dotted line: complement arcs; +
      • dashed line: regular ELSE arcs. +
      + The dot options are chosen so that the drawing fits on a letter-size + sheet. + ] + + SideEffects [None] + + SeeAlso [Cudd_DumpBlif Cudd_PrintDebug Cudd_DumpDDcal + Cudd_DumpDaVinci Cudd_DumpFactoredForm] + +******************************************************************************/ +int +Cudd_DumpDot( + DdManager * dd /* manager */, + int n /* number of output nodes to be dumped */, + DdNode ** f /* array of output nodes to be dumped */, + char ** inames /* array of input names (or NULL) */, + char ** onames /* array of output names (or NULL) */, + FILE * fp /* pointer to the dump file */) +{ + DdNode *support = NULL; + DdNode *scan; + int *sorted = NULL; + int nvars = dd->size; + st_table *visited = NULL; + st_generator *gen = NULL; + int retval; + int i, j; + int slots; + DdNodePtr *nodelist; + long refAddr, diff, mask; + + /* Build a bit array with the support of f. */ + sorted = ALLOC(int,nvars); + if (sorted == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + goto failure; + } + for (i = 0; i < nvars; i++) sorted[i] = 0; + + /* Take the union of the supports of each output function. */ + support = Cudd_VectorSupport(dd,f,n); + if (support == NULL) goto failure; + cuddRef(support); + scan = support; + while (!cuddIsConstant(scan)) { + sorted[scan->index] = 1; + scan = cuddT(scan); + } + Cudd_RecursiveDeref(dd,support); + support = NULL; /* so that we do not try to free it in case of failure */ + + /* Initialize symbol table for visited nodes. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + if (visited == NULL) goto failure; + + /* Collect all the nodes of this DD in the symbol table. */ + for (i = 0; i < n; i++) { + retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); + if (retval == 0) goto failure; + } + + /* Find how many most significant hex digits are identical + ** in the addresses of all the nodes. Build a mask based + ** on this knowledge, so that digits that carry no information + ** will not be printed. This is done in two steps. + ** 1. We scan the symbol table to find the bits that differ + ** in at least 2 addresses. + ** 2. We choose one of the possible masks. There are 8 possible + ** masks for 32-bit integer, and 16 possible masks for 64-bit + ** integers. + */ + + /* Find the bits that are different. */ + refAddr = (long) Cudd_Regular(f[0]); + diff = 0; + gen = st_init_gen(visited); + if (gen == NULL) goto failure; + while (st_gen(gen, (char **) &scan, NULL)) { + diff |= refAddr ^ (long) scan; + } + st_free_gen(gen); gen = NULL; + + /* Choose the mask. */ + for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) { + mask = (1 << i) - 1; + if (diff <= mask) break; + } + + /* Write the header and the global attributes. */ + retval = fprintf(fp,"digraph \"DD\" {\n"); + if (retval == EOF) return(0); + retval = fprintf(fp, + "size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n"); + if (retval == EOF) return(0); + + /* Write the input name subgraph by scanning the support array. */ + retval = fprintf(fp,"{ node [shape = plaintext];\n"); + if (retval == EOF) goto failure; + retval = fprintf(fp," edge [style = invis];\n"); + if (retval == EOF) goto failure; + /* We use a name ("CONST NODES") with an embedded blank, because + ** it is unlikely to appear as an input name. + */ + retval = fprintf(fp," \"CONST NODES\" [style = invis];\n"); + if (retval == EOF) goto failure; + for (i = 0; i < nvars; i++) { + if (sorted[dd->invperm[i]]) { + if (inames == NULL || inames[dd->invperm[i]] == NULL) { + retval = fprintf(fp,"\" %d \" -> ", dd->invperm[i]); + } else { + retval = fprintf(fp,"\" %s \" -> ", inames[dd->invperm[i]]); + } + if (retval == EOF) goto failure; + } + } + retval = fprintf(fp,"\"CONST NODES\"; \n}\n"); + if (retval == EOF) goto failure; + + /* Write the output node subgraph. */ + retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n"); + if (retval == EOF) goto failure; + for (i = 0; i < n; i++) { + if (onames == NULL) { + retval = fprintf(fp,"\"F%d\"", i); + } else { + retval = fprintf(fp,"\" %s \"", onames[i]); + } + if (retval == EOF) goto failure; + if (i == n - 1) { + retval = fprintf(fp,"; }\n"); + } else { + retval = fprintf(fp," -> "); + } + if (retval == EOF) goto failure; + } + + /* Write rank info: All nodes with the same index have the same rank. */ + for (i = 0; i < nvars; i++) { + if (sorted[dd->invperm[i]]) { + retval = fprintf(fp,"{ rank = same; "); + if (retval == EOF) goto failure; + if (inames == NULL || inames[dd->invperm[i]] == NULL) { + retval = fprintf(fp,"\" %d \";\n", dd->invperm[i]); + } else { + retval = fprintf(fp,"\" %s \";\n", inames[dd->invperm[i]]); + } + if (retval == EOF) goto failure; + nodelist = dd->subtables[i].nodelist; + slots = dd->subtables[i].slots; + for (j = 0; j < slots; j++) { + scan = nodelist[j]; + while (scan != NULL) { + if (st_is_member(visited,(char *) scan)) { + retval = fprintf(fp,"\"%lx\";\n", (mask & (long) scan) / sizeof(DdNode)); + if (retval == EOF) goto failure; + } + scan = scan->next; + } + } + retval = fprintf(fp,"}\n"); + if (retval == EOF) goto failure; + } + } + + /* All constants have the same rank. */ + retval = fprintf(fp, + "{ rank = same; \"CONST NODES\";\n{ node [shape = box]; "); + if (retval == EOF) goto failure; + nodelist = dd->constants.nodelist; + slots = dd->constants.slots; + for (j = 0; j < slots; j++) { + scan = nodelist[j]; + while (scan != NULL) { + if (st_is_member(visited,(char *) scan)) { + retval = fprintf(fp,"\"%lx\";\n", (mask & (long) scan) / sizeof(DdNode)); + if (retval == EOF) goto failure; + } + scan = scan->next; + } + } + retval = fprintf(fp,"}\n}\n"); + if (retval == EOF) goto failure; + + /* Write edge info. */ + /* Edges from the output nodes. */ + for (i = 0; i < n; i++) { + if (onames == NULL) { + retval = fprintf(fp,"\"F%d\"", i); + } else { + retval = fprintf(fp,"\" %s \"", onames[i]); + } + if (retval == EOF) goto failure; + /* Account for the possible complement on the root. */ + if (Cudd_IsComplement(f[i])) { + retval = fprintf(fp," -> \"%lx\" [style = dotted];\n", + (mask & (long) f[i]) / sizeof(DdNode)); + } else { + retval = fprintf(fp," -> \"%lx\" [style = solid];\n", + (mask & (long) f[i]) / sizeof(DdNode)); + } + if (retval == EOF) goto failure; + } + + /* Edges from internal nodes. */ + for (i = 0; i < nvars; i++) { + if (sorted[dd->invperm[i]]) { + nodelist = dd->subtables[i].nodelist; + slots = dd->subtables[i].slots; + for (j = 0; j < slots; j++) { + scan = nodelist[j]; + while (scan != NULL) { + if (st_is_member(visited,(char *) scan)) { + retval = fprintf(fp, + "\"%lx\" -> \"%lx\";\n", + (mask & (long) scan) / sizeof(DdNode), + (mask & (long) cuddT(scan)) / sizeof(DdNode)); + if (retval == EOF) goto failure; + if (Cudd_IsComplement(cuddE(scan))) { + retval = fprintf(fp, + "\"%lx\" -> \"%lx\" [style = dotted];\n", + (mask & (long) scan) / sizeof(DdNode), + (mask & (long) cuddE(scan)) / sizeof(DdNode)); + } else { + retval = fprintf(fp, + "\"%lx\" -> \"%lx\" [style = dashed];\n", + (mask & (long) scan) / sizeof(DdNode), + (mask & (long) cuddE(scan)) / sizeof(DdNode)); + } + if (retval == EOF) goto failure; + } + scan = scan->next; + } + } + } + } + + /* Write constant labels. */ + nodelist = dd->constants.nodelist; + slots = dd->constants.slots; + for (j = 0; j < slots; j++) { + scan = nodelist[j]; + while (scan != NULL) { + if (st_is_member(visited,(char *) scan)) { + retval = fprintf(fp,"\"%lx\" [label = \"%g\"];\n", + (mask & (long) scan) / sizeof(DdNode), cuddV(scan)); + if (retval == EOF) goto failure; + } + scan = scan->next; + } + } + + /* Write trailer and return. */ + retval = fprintf(fp,"}\n"); + if (retval == EOF) goto failure; + + st_free_table(visited); + FREE(sorted); + return(1); + +failure: + if (sorted != NULL) FREE(sorted); + if (support != NULL) Cudd_RecursiveDeref(dd,support); + if (visited != NULL) st_free_table(visited); + return(0); + +} /* end of Cudd_DumpDot */ + + +/**Function******************************************************************** + + Synopsis [Writes a daVinci file representing the argument BDDs.] + + Description [Writes a daVinci file representing the argument BDDs. + It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or + file system full). Cudd_DumpDaVinci does not close the file: This + is the caller responsibility. Cudd_DumpDaVinci uses a minimal unique + subset of the hexadecimal address of a node as name for it. If the + argument inames is non-null, it is assumed to hold the pointers to + the names of the inputs. Similarly for onames.] + + SideEffects [None] + + SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDDcal + Cudd_DumpFactoredForm] + +******************************************************************************/ +int +Cudd_DumpDaVinci( + DdManager * dd /* manager */, + int n /* number of output nodes to be dumped */, + DdNode ** f /* array of output nodes to be dumped */, + char ** inames /* array of input names (or NULL) */, + char ** onames /* array of output names (or NULL) */, + FILE * fp /* pointer to the dump file */) +{ + DdNode *support = NULL; + DdNode *scan; + st_table *visited = NULL; + int retval; + int i; + st_generator *gen; + long refAddr, diff, mask; + + /* Initialize symbol table for visited nodes. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + if (visited == NULL) goto failure; + + /* Collect all the nodes of this DD in the symbol table. */ + for (i = 0; i < n; i++) { + retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); + if (retval == 0) goto failure; + } + + /* Find how many most significant hex digits are identical + ** in the addresses of all the nodes. Build a mask based + ** on this knowledge, so that digits that carry no information + ** will not be printed. This is done in two steps. + ** 1. We scan the symbol table to find the bits that differ + ** in at least 2 addresses. + ** 2. We choose one of the possible masks. There are 8 possible + ** masks for 32-bit integer, and 16 possible masks for 64-bit + ** integers. + */ + + /* Find the bits that are different. */ + refAddr = (long) Cudd_Regular(f[0]); + diff = 0; + gen = st_init_gen(visited); + while (st_gen(gen, (char **) &scan, NULL)) { + diff |= refAddr ^ (long) scan; + } + st_free_gen(gen); + + /* Choose the mask. */ + for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) { + mask = (1 << i) - 1; + if (diff <= mask) break; + } + st_free_table(visited); + + /* Initialize symbol table for visited nodes. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + if (visited == NULL) goto failure; + + retval = fprintf(fp, "["); + if (retval == EOF) goto failure; + /* Call the function that really gets the job done. */ + for (i = 0; i < n; i++) { + if (onames == NULL) { + retval = fprintf(fp, + "l(\"f%d\",n(\"root\",[a(\"OBJECT\",\"f%d\")],", + i,i); + } else { + retval = fprintf(fp, + "l(\"%s\",n(\"root\",[a(\"OBJECT\",\"%s\")],", + onames[i], onames[i]); + } + if (retval == EOF) goto failure; + retval = fprintf(fp, "[e(\"edge\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],", + Cudd_IsComplement(f[i]) ? "red" : "blue"); + if (retval == EOF) goto failure; + retval = ddDoDumpDaVinci(dd,Cudd_Regular(f[i]),fp,visited,inames,mask); + if (retval == 0) goto failure; + retval = fprintf(fp, ")]))%s", i == n-1 ? "" : ","); + if (retval == EOF) goto failure; + } + + /* Write trailer and return. */ + retval = fprintf(fp, "]\n"); + if (retval == EOF) goto failure; + + st_free_table(visited); + return(1); + +failure: + if (support != NULL) Cudd_RecursiveDeref(dd,support); + if (visited != NULL) st_free_table(visited); + return(0); + +} /* end of Cudd_DumpDaVinci */ + + +/**Function******************************************************************** + + Synopsis [Writes a DDcal file representing the argument BDDs.] + + Description [Writes a DDcal file representing the argument BDDs. + It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or + file system full). Cudd_DumpDDcal does not close the file: This + is the caller responsibility. Cudd_DumpDDcal uses a minimal unique + subset of the hexadecimal address of a node as name for it. If the + argument inames is non-null, it is assumed to hold the pointers to + the names of the inputs. Similarly for onames.] + + SideEffects [None] + + SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci + Cudd_DumpFactoredForm] + +******************************************************************************/ +int +Cudd_DumpDDcal( + DdManager * dd /* manager */, + int n /* number of output nodes to be dumped */, + DdNode ** f /* array of output nodes to be dumped */, + char ** inames /* array of input names (or NULL) */, + char ** onames /* array of output names (or NULL) */, + FILE * fp /* pointer to the dump file */) +{ + DdNode *support = NULL; + DdNode *scan; + int *sorted = NULL; + int nvars = dd->size; + st_table *visited = NULL; + int retval; + int i; + st_generator *gen; + long refAddr, diff, mask; + + /* Initialize symbol table for visited nodes. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + if (visited == NULL) goto failure; + + /* Collect all the nodes of this DD in the symbol table. */ + for (i = 0; i < n; i++) { + retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); + if (retval == 0) goto failure; + } + + /* Find how many most significant hex digits are identical + ** in the addresses of all the nodes. Build a mask based + ** on this knowledge, so that digits that carry no information + ** will not be printed. This is done in two steps. + ** 1. We scan the symbol table to find the bits that differ + ** in at least 2 addresses. + ** 2. We choose one of the possible masks. There are 8 possible + ** masks for 32-bit integer, and 16 possible masks for 64-bit + ** integers. + */ + + /* Find the bits that are different. */ + refAddr = (long) Cudd_Regular(f[0]); + diff = 0; + gen = st_init_gen(visited); + while (st_gen(gen, (char **) &scan, NULL)) { + diff |= refAddr ^ (long) scan; + } + st_free_gen(gen); + + /* Choose the mask. */ + for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) { + mask = (1 << i) - 1; + if (diff <= mask) break; + } + st_free_table(visited); + + /* Build a bit array with the support of f. */ + sorted = ALLOC(int,nvars); + if (sorted == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + goto failure; + } + for (i = 0; i < nvars; i++) sorted[i] = 0; + + /* Take the union of the supports of each output function. */ + support = Cudd_VectorSupport(dd,f,n); + if (support == NULL) goto failure; + cuddRef(support); + scan = support; + while (!cuddIsConstant(scan)) { + sorted[scan->index] = 1; + scan = cuddT(scan); + } + Cudd_RecursiveDeref(dd,support); + support = NULL; /* so that we do not try to free it in case of failure */ + for (i = 0; i < nvars; i++) { + if (sorted[dd->invperm[i]]) { + if (inames == NULL || inames[dd->invperm[i]] == NULL) { + retval = fprintf(fp,"v%d", dd->invperm[i]); + } else { + retval = fprintf(fp,"%s", inames[dd->invperm[i]]); + } + if (retval == EOF) goto failure; + } + retval = fprintf(fp,"%s", i == nvars - 1 ? "\n" : " * "); + if (retval == EOF) goto failure; + } + FREE(sorted); + sorted = NULL; + + /* Initialize symbol table for visited nodes. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + if (visited == NULL) goto failure; + + /* Call the function that really gets the job done. */ + for (i = 0; i < n; i++) { + retval = ddDoDumpDDcal(dd,Cudd_Regular(f[i]),fp,visited,inames,mask); + if (retval == 0) goto failure; + if (onames == NULL) { + retval = fprintf(fp, "f%d = ", i); + } else { + retval = fprintf(fp, "%s = ", onames[i]); + } + if (retval == EOF) goto failure; + retval = fprintf(fp, "n%lx%s\n", + ((long) f[i] & mask) / sizeof(DdNode), + Cudd_IsComplement(f[i]) ? "'" : ""); + if (retval == EOF) goto failure; + } + + /* Write trailer and return. */ + retval = fprintf(fp, "["); + if (retval == EOF) goto failure; + for (i = 0; i < n; i++) { + if (onames == NULL) { + retval = fprintf(fp, "f%d", i); + } else { + retval = fprintf(fp, "%s", onames[i]); + } + retval = fprintf(fp, "%s", i == n-1 ? "" : " "); + if (retval == EOF) goto failure; + } + retval = fprintf(fp, "]\n"); + if (retval == EOF) goto failure; + + st_free_table(visited); + return(1); + +failure: + if (sorted != NULL) FREE(sorted); + if (support != NULL) Cudd_RecursiveDeref(dd,support); + if (visited != NULL) st_free_table(visited); + return(0); + +} /* end of Cudd_DumpDDcal */ + + +/**Function******************************************************************** + + Synopsis [Writes factored forms representing the argument BDDs.] + + Description [Writes factored forms representing the argument BDDs. + The format of the factored form is the one used in the genlib files + for technology mapping in sis. It returns 1 in case of success; 0 + otherwise (e.g., file system full). Cudd_DumpFactoredForm does not + close the file: This is the caller responsibility. Caution must be + exercised because a factored form may be exponentially larger than + the argument BDD. If the argument inames is non-null, it is assumed + to hold the pointers to the names of the inputs. Similarly for + onames.] + + SideEffects [None] + + SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci + Cudd_DumpDDcal] + +******************************************************************************/ +int +Cudd_DumpFactoredForm( + DdManager * dd /* manager */, + int n /* number of output nodes to be dumped */, + DdNode ** f /* array of output nodes to be dumped */, + char ** inames /* array of input names (or NULL) */, + char ** onames /* array of output names (or NULL) */, + FILE * fp /* pointer to the dump file */) +{ + int retval; + int i; + + /* Call the function that really gets the job done. */ + for (i = 0; i < n; i++) { + if (onames == NULL) { + retval = fprintf(fp, "f%d = ", i); + } else { + retval = fprintf(fp, "%s = ", onames[i]); + } + if (retval == EOF) return(0); + if (f[i] == DD_ONE(dd)) { + retval = fprintf(fp, "CONST1"); + if (retval == EOF) return(0); + } else if (f[i] == Cudd_Not(DD_ONE(dd)) || f[i] == DD_ZERO(dd)) { + retval = fprintf(fp, "CONST0"); + if (retval == EOF) return(0); + } else { + retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? "!(" : ""); + if (retval == EOF) return(0); + retval = ddDoDumpFactoredForm(dd,Cudd_Regular(f[i]),fp,inames); + if (retval == 0) return(0); + retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? ")" : ""); + if (retval == EOF) return(0); + } + retval = fprintf(fp, "%s", i == n-1 ? "" : "\n"); + if (retval == EOF) return(0); + } + + return(1); + +} /* end of Cudd_DumpFactoredForm */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_DumpBlif.] + + Description [Performs the recursive step of Cudd_DumpBlif. Traverses + the BDD f and writes a multiplexer-network description to the file + pointed by fp in blif format. f is assumed to be a regular pointer + and ddDoDumpBlif guarantees this assumption in the recursive calls.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ddDoDumpBlif( + DdManager * dd, + DdNode * f, + FILE * fp, + st_table * visited, + char ** names) +{ + DdNode *T, *E; + int retval; + +#ifdef DD_DEBUG + assert(!Cudd_IsComplement(f)); +#endif + + /* If already visited, nothing to do. */ + if (st_is_member(visited, (char *) f) == 1) + return(1); + + /* Check for abnormal condition that should never happen. */ + if (f == NULL) + return(0); + + /* Mark node as visited. */ + if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) + return(0); + + /* Check for special case: If constant node, generate constant 1. */ + if (f == DD_ONE(dd)) { +#if SIZEOF_VOID_P == 8 + retval = fprintf(fp, ".names %lx\n1\n",(unsigned long) f / (unsigned long) sizeof(DdNode)); +#else + retval = fprintf(fp, ".names %x\n1\n",(unsigned) f / (unsigned) sizeof(DdNode)); +#endif + if (retval == EOF) { + return(0); + } else { + return(1); + } + } + + /* Check whether this is an ADD. We deal with 0-1 ADDs, but not + ** with the general case. + */ + if (f == DD_ZERO(dd)) { +#if SIZEOF_VOID_P == 8 + retval = fprintf(fp, ".names %lx\n",(unsigned long) f / (unsigned long) sizeof(DdNode)); +#else + retval = fprintf(fp, ".names %x\n",(unsigned) f / (unsigned) sizeof(DdNode)); +#endif + if (retval == EOF) { + return(0); + } else { + return(1); + } + } + if (cuddIsConstant(f)) + return(0); + + /* Recursive calls. */ + T = cuddT(f); + retval = ddDoDumpBlif(dd,T,fp,visited,names); + if (retval != 1) return(retval); + E = Cudd_Regular(cuddE(f)); + retval = ddDoDumpBlif(dd,E,fp,visited,names); + if (retval != 1) return(retval); + + /* Write multiplexer taking complement arc into account. */ + if (names != NULL) { + retval = fprintf(fp,".names %s", names[f->index]); + } else { + retval = fprintf(fp,".names %d", f->index); + } + if (retval == EOF) + return(0); + +#if SIZEOF_VOID_P == 8 + if (Cudd_IsComplement(cuddE(f))) { + retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-0 1\n", + (unsigned long) T / (unsigned long) sizeof(DdNode), + (unsigned long) E / (unsigned long) sizeof(DdNode), + (unsigned long) f / (unsigned long) sizeof(DdNode)); + } else { + retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-1 1\n", + (unsigned long) T / (unsigned long) sizeof(DdNode), + (unsigned long) E / (unsigned long) sizeof(DdNode), + (unsigned long) f / (unsigned long) sizeof(DdNode)); + } +#else + if (Cudd_IsComplement(cuddE(f))) { + retval = fprintf(fp," %x %x %x\n11- 1\n0-0 1\n", + (unsigned) T / (unsigned) sizeof(DdNode), + (unsigned) E / (unsigned) sizeof(DdNode), + (unsigned) f / (unsigned) sizeof(DdNode)); + } else { + retval = fprintf(fp," %x %x %x\n11- 1\n0-1 1\n", + (unsigned) T / (unsigned) sizeof(DdNode), + (unsigned) E / (unsigned) sizeof(DdNode), + (unsigned) f / (unsigned) sizeof(DdNode)); + } +#endif + if (retval == EOF) { + return(0); + } else { + return(1); + } + +} /* end of ddDoDumpBlif */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_DumpDaVinci.] + + Description [Performs the recursive step of Cudd_DumpDaVinci. Traverses + the BDD f and writes a term expression to the file + pointed by fp in daVinci format. f is assumed to be a regular pointer + and ddDoDumpDaVinci guarantees this assumption in the recursive calls.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ddDoDumpDaVinci( + DdManager * dd, + DdNode * f, + FILE * fp, + st_table * visited, + char ** names, + long mask) +{ + DdNode *T, *E; + int retval; + long id; + +#ifdef DD_DEBUG + assert(!Cudd_IsComplement(f)); +#endif + + id = ((long) f & mask) / sizeof(DdNode); + + /* If already visited, insert a reference. */ + if (st_is_member(visited, (char *) f) == 1) { + retval = fprintf(fp,"r(\"%lx\")", id); + if (retval == EOF) { + return(0); + } else { + return(1); + } + } + + /* Check for abnormal condition that should never happen. */ + if (f == NULL) + return(0); + + /* Mark node as visited. */ + if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) + return(0); + + /* Check for special case: If constant node, generate constant 1. */ + if (Cudd_IsConstant(f)) { + retval = fprintf(fp, "l(\"%lx\",n(\"constant\",[a(\"OBJECT\",\"%g\")],[]))", id, cuddV(f)); + if (retval == EOF) { + return(0); + } else { + return(1); + } + } + + /* Recursive calls. */ + if (names != NULL) { + retval = fprintf(fp, + "l(\"%lx\",n(\"internal\",[a(\"OBJECT\",\"%s\"),", + id, names[f->index]); + } else { + retval = fprintf(fp, + "l(\"%lx\",n(\"internal\",[a(\"OBJECT\",\"%d\"),", + id, f->index); + } + retval = fprintf(fp, "a(\"_GO\",\"ellipse\")],[e(\"then\",[a(\"EDGECOLOR\",\"blue\"),a(\"_DIR\",\"none\")],"); + if (retval == EOF) return(0); + T = cuddT(f); + retval = ddDoDumpDaVinci(dd,T,fp,visited,names,mask); + if (retval != 1) return(retval); + retval = fprintf(fp, "),e(\"else\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],", + Cudd_IsComplement(cuddE(f)) ? "red" : "green"); + if (retval == EOF) return(0); + E = Cudd_Regular(cuddE(f)); + retval = ddDoDumpDaVinci(dd,E,fp,visited,names,mask); + if (retval != 1) return(retval); + + retval = fprintf(fp,")]))"); + if (retval == EOF) { + return(0); + } else { + return(1); + } + +} /* end of ddDoDumpDaVinci */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_DumpDDcal.] + + Description [Performs the recursive step of Cudd_DumpDDcal. Traverses + the BDD f and writes a line for each node to the file + pointed by fp in DDcal format. f is assumed to be a regular pointer + and ddDoDumpDDcal guarantees this assumption in the recursive calls.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ddDoDumpDDcal( + DdManager * dd, + DdNode * f, + FILE * fp, + st_table * visited, + char ** names, + long mask) +{ + DdNode *T, *E; + int retval; + long id, idT, idE; + +#ifdef DD_DEBUG + assert(!Cudd_IsComplement(f)); +#endif + + id = ((long) f & mask) / sizeof(DdNode); + + /* If already visited, do nothing. */ + if (st_is_member(visited, (char *) f) == 1) { + return(1); + } + + /* Check for abnormal condition that should never happen. */ + if (f == NULL) + return(0); + + /* Mark node as visited. */ + if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) + return(0); + + /* Check for special case: If constant node, assign constant. */ + if (Cudd_IsConstant(f)) { + if (f != DD_ONE(dd) && f != DD_ZERO(dd)) + return(0); + retval = fprintf(fp, "n%lx = %g\n", id, cuddV(f)); + if (retval == EOF) { + return(0); + } else { + return(1); + } + } + + /* Recursive calls. */ + T = cuddT(f); + retval = ddDoDumpDDcal(dd,T,fp,visited,names,mask); + if (retval != 1) return(retval); + E = Cudd_Regular(cuddE(f)); + retval = ddDoDumpDDcal(dd,E,fp,visited,names,mask); + if (retval != 1) return(retval); + idT = ((long) T & mask) / sizeof(DdNode); + idE = ((long) E & mask) / sizeof(DdNode); + if (names != NULL) { + retval = fprintf(fp, "n%lx = %s * n%lx + %s' * n%lx%s\n", + id, names[f->index], idT, names[f->index], + idE, Cudd_IsComplement(cuddE(f)) ? "'" : ""); + } else { + retval = fprintf(fp, "n%lx = v%d * n%lx + v%d' * n%lx%s\n", + id, f->index, idT, f->index, + idE, Cudd_IsComplement(cuddE(f)) ? "'" : ""); + } + if (retval == EOF) { + return(0); + } else { + return(1); + } + +} /* end of ddDoDumpDDcal */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_DumpFactoredForm.] + + Description [Performs the recursive step of + Cudd_DumpFactoredForm. Traverses the BDD f and writes a factored + form for each node to the file pointed by fp in terms of the + factored forms of the children. Constants are propagated, and + absorption is applied. f is assumed to be a regular pointer and + ddDoDumpFActoredForm guarantees this assumption in the recursive + calls.] + + SideEffects [None] + + SeeAlso [Cudd_DumpFactoredForm] + +******************************************************************************/ +static int +ddDoDumpFactoredForm( + DdManager * dd, + DdNode * f, + FILE * fp, + char ** names) +{ + DdNode *T, *E; + int retval; + +#ifdef DD_DEBUG + assert(!Cudd_IsComplement(f)); + assert(!Cudd_IsConstant(f)); +#endif + + /* Check for abnormal condition that should never happen. */ + if (f == NULL) + return(0); + + /* Recursive calls. */ + T = cuddT(f); + E = cuddE(f); + if (T != DD_ZERO(dd)) { + if (E != DD_ONE(dd)) { + if (names != NULL) { + retval = fprintf(fp, "%s", names[f->index]); + } else { + retval = fprintf(fp, "x%d", f->index); + } + if (retval == EOF) return(0); + } + if (T != DD_ONE(dd)) { + retval = fprintf(fp, "%s(", E != DD_ONE(dd) ? " * " : ""); + if (retval == EOF) return(0); + retval = ddDoDumpFactoredForm(dd,T,fp,names); + if (retval != 1) return(retval); + retval = fprintf(fp, ")"); + if (retval == EOF) return(0); + } + if (E == Cudd_Not(DD_ONE(dd)) || E == DD_ZERO(dd)) return(1); + retval = fprintf(fp, " + "); + if (retval == EOF) return(0); + } + E = Cudd_Regular(E); + if (T != DD_ONE(dd)) { + if (names != NULL) { + retval = fprintf(fp, "!%s", names[f->index]); + } else { + retval = fprintf(fp, "!x%d", f->index); + } + if (retval == EOF) return(0); + } + if (E != DD_ONE(dd)) { + retval = fprintf(fp, "%s%s(", T != DD_ONE(dd) ? " * " : "", + E != cuddE(f) ? "!" : ""); + if (retval == EOF) return(0); + retval = ddDoDumpFactoredForm(dd,E,fp,names); + if (retval != 1) return(retval); + retval = fprintf(fp, ")"); + if (retval == EOF) return(0); + } + return(1); + +} /* end of ddDoDumpFactoredForm */ + diff --git a/abc70930/src/bdd/cudd/cuddGenCof.c b/abc70930/src/bdd/cudd/cuddGenCof.c new file mode 100644 index 00000000..142ee27e --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddGenCof.c @@ -0,0 +1,1968 @@ +/**CFile*********************************************************************** + + FileName [cuddGenCof.c] + + PackageName [cudd] + + Synopsis [Generalized cofactors for BDDs and ADDs.] + + Description [External procedures included in this module: +
        +
      • Cudd_bddConstrain() +
      • Cudd_bddRestrict() +
      • Cudd_addConstrain() +
      • Cudd_bddConstrainDecomp() +
      • Cudd_addRestrict() +
      • Cudd_bddCharToVect() +
      • Cudd_bddLICompaction() +
      • Cudd_bddSqueeze() +
      • Cudd_SubsetCompress() +
      • Cudd_SupersetCompress() +
      + Internal procedures included in this module: +
        +
      • cuddBddConstrainRecur() +
      • cuddBddRestrictRecur() +
      • cuddAddConstrainRecur() +
      • cuddAddRestrictRecur() +
      • cuddBddLICompaction() +
      + Static procedures included in this module: +
        +
      • cuddBddConstrainDecomp() +
      • cuddBddCharToVect() +
      • cuddBddLICMarkEdges() +
      • cuddBddLICBuildResult() +
      • cuddBddSqueeze() +
      + ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/* Codes for edge markings in Cudd_bddLICompaction. The codes are defined +** so that they can be bitwise ORed to implement the code priority scheme. +*/ +#define DD_LIC_DC 0 +#define DD_LIC_1 1 +#define DD_LIC_0 2 +#define DD_LIC_NL 3 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/* Key for the cache used in the edge marking phase. */ +typedef struct MarkCacheKey { + DdNode *f; + DdNode *c; +} MarkCacheKey; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddGenCof.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int cuddBddConstrainDecomp ARGS((DdManager *dd, DdNode *f, DdNode **decomp)); +static DdNode * cuddBddCharToVect ARGS((DdManager *dd, DdNode *f, DdNode *x)); +static int cuddBddLICMarkEdges ARGS((DdManager *dd, DdNode *f, DdNode *c, st_table *table, st_table *cache)); +static DdNode * cuddBddLICBuildResult ARGS((DdManager *dd, DdNode *f, st_table *cache, st_table *table)); +static int MarkCacheHash ARGS((char *ptr, int modulus)); +static int MarkCacheCompare ARGS((const char *ptr1, const char *ptr2)); +static enum st_retval MarkCacheCleanUp ARGS((char *key, char *value, char *arg)); +static DdNode * cuddBddSqueeze ARGS((DdManager *dd, DdNode *l, DdNode *u)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes f constrain c.] + + Description [Computes f constrain c (f @ c). + Uses a canonical form: (f' @ c) = ( f @ c)'. (Note: this is not true + for c.) List of special cases: +
        +
      • f @ 0 = 0 +
      • f @ 1 = f +
      • 0 @ c = 0 +
      • 1 @ c = 1 +
      • f @ f = 1 +
      • f @ f'= 0 +
      + Returns a pointer to the result if successful; NULL otherwise. Note that if + F=(f1,...,fn) and reordering takes place while computing F @ c, then the + image restriction property (Img(F,c) = Img(F @ c)) is lost.] + + SideEffects [None] + + SeeAlso [Cudd_bddRestrict Cudd_addConstrain] + +******************************************************************************/ +DdNode * +Cudd_bddConstrain( + DdManager * dd, + DdNode * f, + DdNode * c) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddConstrainRecur(dd,f,c); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddConstrain */ + + +/**Function******************************************************************** + + Synopsis [BDD restrict according to Coudert and Madre's algorithm + (ICCAD90).] + + Description [BDD restrict according to Coudert and Madre's algorithm + (ICCAD90). Returns the restricted BDD if successful; otherwise NULL. + If application of restrict results in a BDD larger than the input + BDD, the input BDD is returned.] + + SideEffects [None] + + SeeAlso [Cudd_bddConstrain Cudd_addRestrict] + +******************************************************************************/ +DdNode * +Cudd_bddRestrict( + DdManager * dd, + DdNode * f, + DdNode * c) +{ + DdNode *suppF, *suppC, *commonSupport; + DdNode *cplus, *res; + int retval; + int sizeF, sizeRes; + + /* Check terminal cases here to avoid computing supports in trivial cases. + ** This also allows us notto check later for the case c == 0, in which + ** there is no common support. */ + if (c == Cudd_Not(DD_ONE(dd))) return(Cudd_Not(DD_ONE(dd))); + if (Cudd_IsConstant(f)) return(f); + if (f == c) return(DD_ONE(dd)); + if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd))); + + /* Check if supports intersect. */ + retval = Cudd_ClassifySupport(dd,f,c,&commonSupport,&suppF,&suppC); + if (retval == 0) { + return(NULL); + } + cuddRef(commonSupport); cuddRef(suppF); cuddRef(suppC); + Cudd_IterDerefBdd(dd,suppF); + + if (commonSupport == DD_ONE(dd)) { + Cudd_IterDerefBdd(dd,commonSupport); + Cudd_IterDerefBdd(dd,suppC); + return(f); + } + Cudd_IterDerefBdd(dd,commonSupport); + + /* Abstract from c the variables that do not appear in f. */ + cplus = Cudd_bddExistAbstract(dd, c, suppC); + if (cplus == NULL) { + Cudd_IterDerefBdd(dd,suppC); + return(NULL); + } + cuddRef(cplus); + Cudd_IterDerefBdd(dd,suppC); + + do { + dd->reordered = 0; + res = cuddBddRestrictRecur(dd, f, cplus); + } while (dd->reordered == 1); + if (res == NULL) { + Cudd_IterDerefBdd(dd,cplus); + return(NULL); + } + cuddRef(res); + Cudd_IterDerefBdd(dd,cplus); + /* Make restric safe by returning the smaller of the input and the + ** result. */ + sizeF = Cudd_DagSize(f); + sizeRes = Cudd_DagSize(res); + if (sizeF <= sizeRes) { + Cudd_IterDerefBdd(dd, res); + return(f); + } else { + cuddDeref(res); + return(res); + } + +} /* end of Cudd_bddRestrict */ + + +/**Function******************************************************************** + + Synopsis [Computes f constrain c for ADDs.] + + Description [Computes f constrain c (f @ c), for f an ADD and c a 0-1 + ADD. List of special cases: +
        +
      • F @ 0 = 0 +
      • F @ 1 = F +
      • 0 @ c = 0 +
      • 1 @ c = 1 +
      • F @ F = 1 +
      + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddConstrain] + +******************************************************************************/ +DdNode * +Cudd_addConstrain( + DdManager * dd, + DdNode * f, + DdNode * c) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddAddConstrainRecur(dd,f,c); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addConstrain */ + + +/**Function******************************************************************** + + Synopsis [BDD conjunctive decomposition as in McMillan's CAV96 paper.] + + Description [BDD conjunctive decomposition as in McMillan's CAV96 + paper. The decomposition is canonical only for a given variable + order. If canonicity is required, variable ordering must be disabled + after the decomposition has been computed. Returns an array with one + entry for each BDD variable in the manager if successful; otherwise + NULL. The components of the solution have their reference counts + already incremented (unlike the results of most other functions in + the package.] + + SideEffects [None] + + SeeAlso [Cudd_bddConstrain Cudd_bddExistAbstract] + +******************************************************************************/ +DdNode ** +Cudd_bddConstrainDecomp( + DdManager * dd, + DdNode * f) +{ + DdNode **decomp; + int res; + int i; + + /* Create an initialize decomposition array. */ + decomp = ALLOC(DdNode *,dd->size); + if (decomp == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < dd->size; i++) { + decomp[i] = NULL; + } + do { + dd->reordered = 0; + /* Clean up the decomposition array in case reordering took place. */ + for (i = 0; i < dd->size; i++) { + if (decomp[i] != NULL) { + Cudd_IterDerefBdd(dd, decomp[i]); + decomp[i] = NULL; + } + } + res = cuddBddConstrainDecomp(dd,f,decomp); + } while (dd->reordered == 1); + if (res == 0) { + FREE(decomp); + return(NULL); + } + /* Missing components are constant ones. */ + for (i = 0; i < dd->size; i++) { + if (decomp[i] == NULL) { + decomp[i] = DD_ONE(dd); + cuddRef(decomp[i]); + } + } + return(decomp); + +} /* end of Cudd_bddConstrainDecomp */ + + +/**Function******************************************************************** + + Synopsis [ADD restrict according to Coudert and Madre's algorithm + (ICCAD90).] + + Description [ADD restrict according to Coudert and Madre's algorithm + (ICCAD90). Returns the restricted ADD if successful; otherwise NULL. + If application of restrict results in an ADD larger than the input + ADD, the input ADD is returned.] + + SideEffects [None] + + SeeAlso [Cudd_addConstrain Cudd_bddRestrict] + +******************************************************************************/ +DdNode * +Cudd_addRestrict( + DdManager * dd, + DdNode * f, + DdNode * c) +{ + DdNode *supp_f, *supp_c; + DdNode *res, *commonSupport; + int intersection; + int sizeF, sizeRes; + + /* Check if supports intersect. */ + supp_f = Cudd_Support(dd, f); + if (supp_f == NULL) { + return(NULL); + } + cuddRef(supp_f); + supp_c = Cudd_Support(dd, c); + if (supp_c == NULL) { + Cudd_RecursiveDeref(dd,supp_f); + return(NULL); + } + cuddRef(supp_c); + commonSupport = Cudd_bddLiteralSetIntersection(dd, supp_f, supp_c); + if (commonSupport == NULL) { + Cudd_RecursiveDeref(dd,supp_f); + Cudd_RecursiveDeref(dd,supp_c); + return(NULL); + } + cuddRef(commonSupport); + Cudd_RecursiveDeref(dd,supp_f); + Cudd_RecursiveDeref(dd,supp_c); + intersection = commonSupport != DD_ONE(dd); + Cudd_RecursiveDeref(dd,commonSupport); + + if (intersection) { + do { + dd->reordered = 0; + res = cuddAddRestrictRecur(dd, f, c); + } while (dd->reordered == 1); + sizeF = Cudd_DagSize(f); + sizeRes = Cudd_DagSize(res); + if (sizeF <= sizeRes) { + cuddRef(res); + Cudd_RecursiveDeref(dd, res); + return(f); + } else { + return(res); + } + } else { + return(f); + } + +} /* end of Cudd_addRestrict */ + + +/**Function******************************************************************** + + Synopsis [Computes a vector whose image equals a non-zero function.] + + Description [Computes a vector of BDDs whose image equals a non-zero + function. + The result depends on the variable order. The i-th component of the vector + depends only on the first i variables in the order. Each BDD in the vector + is not larger than the BDD of the given characteristic function. This + function is based on the description of char-to-vect in "Verification of + Sequential Machines Using Boolean Functional Vectors" by O. Coudert, C. + Berthet and J. C. Madre. + Returns a pointer to an array containing the result if successful; NULL + otherwise. The size of the array equals the number of variables in the + manager. The components of the solution have their reference counts + already incremented (unlike the results of most other functions in + the package.] + + SideEffects [None] + + SeeAlso [Cudd_bddConstrain] + +******************************************************************************/ +DdNode ** +Cudd_bddCharToVect( + DdManager * dd, + DdNode * f) +{ + int i, j; + DdNode **vect; + DdNode *res = NULL; + + if (f == Cudd_Not(DD_ONE(dd))) return(NULL); + + vect = ALLOC(DdNode *, dd->size); + if (vect == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + do { + dd->reordered = 0; + for (i = 0; i < dd->size; i++) { + res = cuddBddCharToVect(dd,f,dd->vars[dd->invperm[i]]); + if (res == NULL) { + /* Clean up the vector array in case reordering took place. */ + for (j = 0; j < i; j++) { + Cudd_IterDerefBdd(dd, vect[dd->invperm[j]]); + } + break; + } + cuddRef(res); + vect[dd->invperm[i]] = res; + } + } while (dd->reordered == 1); + if (res == NULL) { + FREE(vect); + return(NULL); + } + return(vect); + +} /* end of Cudd_bddCharToVect */ + + +/**Function******************************************************************** + + Synopsis [Performs safe minimization of a BDD.] + + Description [Performs safe minimization of a BDD. Given the BDD + f of a function to be minimized and a BDD + c representing the care set, Cudd_bddLICompaction + produces the BDD of a function that agrees with f + wherever c is 1. Safe minimization means that the size + of the result is guaranteed not to exceed the size of + f. This function is based on the DAC97 paper by Hong et + al.. Returns a pointer to the result if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddRestrict] + +******************************************************************************/ +DdNode * +Cudd_bddLICompaction( + DdManager * dd /* manager */, + DdNode * f /* function to be minimized */, + DdNode * c /* constraint (care set) */) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddLICompaction(dd,f,c); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddLICompaction */ + + +/**Function******************************************************************** + + Synopsis [Finds a small BDD in a function interval.] + + Description [Finds a small BDD in a function interval. Given BDDs + l and u, representing the lower bound and + upper bound of a function interval, Cudd_bddSqueeze produces the BDD + of a function within the interval with a small BDD. Returns a + pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction] + +******************************************************************************/ +DdNode * +Cudd_bddSqueeze( + DdManager * dd /* manager */, + DdNode * l /* lower bound */, + DdNode * u /* upper bound */) +{ + DdNode *res; + int sizeRes, sizeL, sizeU; + + do { + dd->reordered = 0; + res = cuddBddSqueeze(dd,l,u); + } while (dd->reordered == 1); + if (res == NULL) return(NULL); + /* We now compare the result with the bounds and return the smallest. + ** We first compare to u, so that in case l == 0 and u == 1, we return + ** 0 as in other minimization algorithms. */ + sizeRes = Cudd_DagSize(res); + sizeU = Cudd_DagSize(u); + if (sizeU <= sizeRes) { + cuddRef(res); + Cudd_IterDerefBdd(dd,res); + res = u; + sizeRes = sizeU; + } + sizeL = Cudd_DagSize(l); + if (sizeL <= sizeRes) { + cuddRef(res); + Cudd_IterDerefBdd(dd,res); + res = l; + sizeRes = sizeL; + } + return(res); + +} /* end of Cudd_bddSqueeze */ + + +/**Function******************************************************************** + + Synopsis [Finds a small BDD that agrees with f over + c.] + + Description [Finds a small BDD that agrees with f over + c. Returns a pointer to the result if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction Cudd_bddSqueeze] + +******************************************************************************/ +DdNode * +Cudd_bddMinimize( + DdManager * dd, + DdNode * f, + DdNode * c) +{ + DdNode *cplus, *res; + + if (c == Cudd_Not(DD_ONE(dd))) return(c); + if (Cudd_IsConstant(f)) return(f); + if (f == c) return(DD_ONE(dd)); + if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd))); + + cplus = Cudd_RemapOverApprox(dd,c,0,0,1.0); + if (cplus == NULL) return(NULL); + cuddRef(cplus); + res = Cudd_bddLICompaction(dd,f,cplus); + if (res == NULL) { + Cudd_IterDerefBdd(dd,cplus); + return(NULL); + } + cuddRef(res); + Cudd_IterDerefBdd(dd,cplus); + cuddDeref(res); + return(res); + +} /* end of Cudd_bddMinimize */ + + +/**Function******************************************************************** + + Synopsis [Find a dense subset of BDD f.] + + Description [Finds a dense subset of BDD f. Density is + the ratio of number of minterms to number of nodes. Uses several + techniques in series. It is more expensive than other subsetting + procedures, but often produces better results. See + Cudd_SubsetShortPaths for a description of the threshold and nvars + parameters. Returns a pointer to the result if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_SubsetRemap Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch + Cudd_bddSqueeze] + +******************************************************************************/ +DdNode * +Cudd_SubsetCompress( + DdManager * dd /* manager */, + DdNode * f /* BDD whose subset is sought */, + int nvars /* number of variables in the support of f */, + int threshold /* maximum number of nodes in the subset */) +{ + DdNode *res, *tmp1, *tmp2; + + tmp1 = Cudd_SubsetShortPaths(dd, f, nvars, threshold, 0); + if (tmp1 == NULL) return(NULL); + cuddRef(tmp1); + tmp2 = Cudd_RemapUnderApprox(dd,tmp1,nvars,0,1.0); + if (tmp2 == NULL) { + Cudd_IterDerefBdd(dd,tmp1); + return(NULL); + } + cuddRef(tmp2); + Cudd_IterDerefBdd(dd,tmp1); + res = Cudd_bddSqueeze(dd,tmp2,f); + if (res == NULL) { + Cudd_IterDerefBdd(dd,tmp2); + return(NULL); + } + cuddRef(res); + Cudd_IterDerefBdd(dd,tmp2); + cuddDeref(res); + return(res); + +} /* end of Cudd_SubsetCompress */ + + +/**Function******************************************************************** + + Synopsis [Find a dense superset of BDD f.] + + Description [Finds a dense superset of BDD f. Density is + the ratio of number of minterms to number of nodes. Uses several + techniques in series. It is more expensive than other supersetting + procedures, but often produces better results. See + Cudd_SupersetShortPaths for a description of the threshold and nvars + parameters. Returns a pointer to the result if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_SubsetCompress Cudd_SupersetRemap Cudd_SupersetShortPaths + Cudd_SupersetHeavyBranch Cudd_bddSqueeze] + +******************************************************************************/ +DdNode * +Cudd_SupersetCompress( + DdManager * dd /* manager */, + DdNode * f /* BDD whose superset is sought */, + int nvars /* number of variables in the support of f */, + int threshold /* maximum number of nodes in the superset */) +{ + DdNode *subset; + + subset = Cudd_SubsetCompress(dd, Cudd_Not(f),nvars,threshold); + + return(Cudd_NotCond(subset, (subset != NULL))); + +} /* end of Cudd_SupersetCompress */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddConstrain.] + + Description [Performs the recursive step of Cudd_bddConstrain. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddConstrain] + +******************************************************************************/ +DdNode * +cuddBddConstrainRecur( + DdManager * dd, + DdNode * f, + DdNode * c) +{ + DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r; + DdNode *one, *zero; + unsigned int topf, topc; + int index; + int comple = 0; + + statLine(dd); + one = DD_ONE(dd); + zero = Cudd_Not(one); + + /* Trivial cases. */ + if (c == one) return(f); + if (c == zero) return(zero); + if (Cudd_IsConstant(f)) return(f); + if (f == c) return(one); + if (f == Cudd_Not(c)) return(zero); + + /* Make canonical to increase the utilization of the cache. */ + if (Cudd_IsComplement(f)) { + f = Cudd_Not(f); + comple = 1; + } + /* Now f is a regular pointer to a non-constant node; c is also + ** non-constant, but may be complemented. + */ + + /* Check the cache. */ + r = cuddCacheLookup2(dd, Cudd_bddConstrain, f, c); + if (r != NULL) { + return(Cudd_NotCond(r,comple)); + } + + /* Recursive step. */ + topf = dd->perm[f->index]; + topc = dd->perm[Cudd_Regular(c)->index]; + if (topf <= topc) { + index = f->index; + Fv = cuddT(f); Fnv = cuddE(f); + } else { + index = Cudd_Regular(c)->index; + Fv = Fnv = f; + } + if (topc <= topf) { + Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); + if (Cudd_IsComplement(c)) { + Cv = Cudd_Not(Cv); + Cnv = Cudd_Not(Cnv); + } + } else { + Cv = Cnv = c; + } + + if (!Cudd_IsConstant(Cv)) { + t = cuddBddConstrainRecur(dd, Fv, Cv); + if (t == NULL) + return(NULL); + } else if (Cv == one) { + t = Fv; + } else { /* Cv == zero: return Fnv @ Cnv */ + if (Cnv == one) { + r = Fnv; + } else { + r = cuddBddConstrainRecur(dd, Fnv, Cnv); + if (r == NULL) + return(NULL); + } + return(Cudd_NotCond(r,comple)); + } + cuddRef(t); + + if (!Cudd_IsConstant(Cnv)) { + e = cuddBddConstrainRecur(dd, Fnv, Cnv); + if (e == NULL) { + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + } else if (Cnv == one) { + e = Fnv; + } else { /* Cnv == zero: return Fv @ Cv previously computed */ + cuddDeref(t); + return(Cudd_NotCond(t,comple)); + } + cuddRef(e); + + if (Cudd_IsComplement(t)) { + t = Cudd_Not(t); + e = Cudd_Not(e); + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_IterDerefBdd(dd, e); + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_IterDerefBdd(dd, e); + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + } + cuddDeref(t); + cuddDeref(e); + + cuddCacheInsert2(dd, Cudd_bddConstrain, f, c, r); + return(Cudd_NotCond(r,comple)); + +} /* end of cuddBddConstrainRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddRestrict.] + + Description [Performs the recursive step of Cudd_bddRestrict. + Returns the restricted BDD if successful; otherwise NULL.] + + SideEffects [None] + + SeeAlso [Cudd_bddRestrict] + +******************************************************************************/ +DdNode * +cuddBddRestrictRecur( + DdManager * dd, + DdNode * f, + DdNode * c) +{ + DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero; + unsigned int topf, topc; + int index; + int comple = 0; + + statLine(dd); + one = DD_ONE(dd); + zero = Cudd_Not(one); + + /* Trivial cases */ + if (c == one) return(f); + if (c == zero) return(zero); + if (Cudd_IsConstant(f)) return(f); + if (f == c) return(one); + if (f == Cudd_Not(c)) return(zero); + + /* Make canonical to increase the utilization of the cache. */ + if (Cudd_IsComplement(f)) { + f = Cudd_Not(f); + comple = 1; + } + /* Now f is a regular pointer to a non-constant node; c is also + ** non-constant, but may be complemented. + */ + + /* Check the cache. */ + r = cuddCacheLookup2(dd, Cudd_bddRestrict, f, c); + if (r != NULL) { + return(Cudd_NotCond(r,comple)); + } + + topf = dd->perm[f->index]; + topc = dd->perm[Cudd_Regular(c)->index]; + + if (topc < topf) { /* abstract top variable from c */ + DdNode *d, *s1, *s2; + + /* Find complements of cofactors of c. */ + if (Cudd_IsComplement(c)) { + s1 = cuddT(Cudd_Regular(c)); + s2 = cuddE(Cudd_Regular(c)); + } else { + s1 = Cudd_Not(cuddT(c)); + s2 = Cudd_Not(cuddE(c)); + } + /* Take the OR by applying DeMorgan. */ + d = cuddBddAndRecur(dd, s1, s2); + if (d == NULL) return(NULL); + d = Cudd_Not(d); + cuddRef(d); + r = cuddBddRestrictRecur(dd, f, d); + if (r == NULL) { + Cudd_IterDerefBdd(dd, d); + return(NULL); + } + cuddRef(r); + Cudd_IterDerefBdd(dd, d); + cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r); + cuddDeref(r); + return(Cudd_NotCond(r,comple)); + } + + /* Recursive step. Here topf <= topc. */ + index = f->index; + Fv = cuddT(f); Fnv = cuddE(f); + if (topc == topf) { + Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); + if (Cudd_IsComplement(c)) { + Cv = Cudd_Not(Cv); + Cnv = Cudd_Not(Cnv); + } + } else { + Cv = Cnv = c; + } + + if (!Cudd_IsConstant(Cv)) { + t = cuddBddRestrictRecur(dd, Fv, Cv); + if (t == NULL) return(NULL); + } else if (Cv == one) { + t = Fv; + } else { /* Cv == zero: return(Fnv @ Cnv) */ + if (Cnv == one) { + r = Fnv; + } else { + r = cuddBddRestrictRecur(dd, Fnv, Cnv); + if (r == NULL) return(NULL); + } + return(Cudd_NotCond(r,comple)); + } + cuddRef(t); + + if (!Cudd_IsConstant(Cnv)) { + e = cuddBddRestrictRecur(dd, Fnv, Cnv); + if (e == NULL) { + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + } else if (Cnv == one) { + e = Fnv; + } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ + cuddDeref(t); + return(Cudd_NotCond(t,comple)); + } + cuddRef(e); + + if (Cudd_IsComplement(t)) { + t = Cudd_Not(t); + e = Cudd_Not(e); + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_IterDerefBdd(dd, e); + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_IterDerefBdd(dd, e); + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + } + cuddDeref(t); + cuddDeref(e); + + cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r); + return(Cudd_NotCond(r,comple)); + +} /* end of cuddBddRestrictRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addConstrain.] + + Description [Performs the recursive step of Cudd_addConstrain. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addConstrain] + +******************************************************************************/ +DdNode * +cuddAddConstrainRecur( + DdManager * dd, + DdNode * f, + DdNode * c) +{ + DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r; + DdNode *one, *zero; + unsigned int topf, topc; + int index; + + statLine(dd); + one = DD_ONE(dd); + zero = DD_ZERO(dd); + + /* Trivial cases. */ + if (c == one) return(f); + if (c == zero) return(zero); + if (Cudd_IsConstant(f)) return(f); + if (f == c) return(one); + + /* Now f and c are non-constant. */ + + /* Check the cache. */ + r = cuddCacheLookup2(dd, Cudd_addConstrain, f, c); + if (r != NULL) { + return(r); + } + + /* Recursive step. */ + topf = dd->perm[f->index]; + topc = dd->perm[c->index]; + if (topf <= topc) { + index = f->index; + Fv = cuddT(f); Fnv = cuddE(f); + } else { + index = c->index; + Fv = Fnv = f; + } + if (topc <= topf) { + Cv = cuddT(c); Cnv = cuddE(c); + } else { + Cv = Cnv = c; + } + + if (!Cudd_IsConstant(Cv)) { + t = cuddAddConstrainRecur(dd, Fv, Cv); + if (t == NULL) + return(NULL); + } else if (Cv == one) { + t = Fv; + } else { /* Cv == zero: return Fnv @ Cnv */ + if (Cnv == one) { + r = Fnv; + } else { + r = cuddAddConstrainRecur(dd, Fnv, Cnv); + if (r == NULL) + return(NULL); + } + return(r); + } + cuddRef(t); + + if (!Cudd_IsConstant(Cnv)) { + e = cuddAddConstrainRecur(dd, Fnv, Cnv); + if (e == NULL) { + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + } else if (Cnv == one) { + e = Fnv; + } else { /* Cnv == zero: return Fv @ Cv previously computed */ + cuddDeref(t); + return(t); + } + cuddRef(e); + + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_RecursiveDeref(dd, e); + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + + cuddCacheInsert2(dd, Cudd_addConstrain, f, c, r); + return(r); + +} /* end of cuddAddConstrainRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addRestrict.] + + Description [Performs the recursive step of Cudd_addRestrict. + Returns the restricted ADD if successful; otherwise NULL.] + + SideEffects [None] + + SeeAlso [Cudd_addRestrict] + +******************************************************************************/ +DdNode * +cuddAddRestrictRecur( + DdManager * dd, + DdNode * f, + DdNode * c) +{ + DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero; + unsigned int topf, topc; + int index; + + statLine(dd); + one = DD_ONE(dd); + zero = DD_ZERO(dd); + + /* Trivial cases */ + if (c == one) return(f); + if (c == zero) return(zero); + if (Cudd_IsConstant(f)) return(f); + if (f == c) return(one); + + /* Now f and c are non-constant. */ + + /* Check the cache. */ + r = cuddCacheLookup2(dd, Cudd_addRestrict, f, c); + if (r != NULL) { + return(r); + } + + topf = dd->perm[f->index]; + topc = dd->perm[c->index]; + + if (topc < topf) { /* abstract top variable from c */ + DdNode *d, *s1, *s2; + + /* Find cofactors of c. */ + s1 = cuddT(c); + s2 = cuddE(c); + /* Take the OR by applying DeMorgan. */ + d = cuddAddApplyRecur(dd, Cudd_addOr, s1, s2); + if (d == NULL) return(NULL); + cuddRef(d); + r = cuddAddRestrictRecur(dd, f, d); + if (r == NULL) { + Cudd_RecursiveDeref(dd, d); + return(NULL); + } + cuddRef(r); + Cudd_RecursiveDeref(dd, d); + cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r); + cuddDeref(r); + return(r); + } + + /* Recursive step. Here topf <= topc. */ + index = f->index; + Fv = cuddT(f); Fnv = cuddE(f); + if (topc == topf) { + Cv = cuddT(c); Cnv = cuddE(c); + } else { + Cv = Cnv = c; + } + + if (!Cudd_IsConstant(Cv)) { + t = cuddAddRestrictRecur(dd, Fv, Cv); + if (t == NULL) return(NULL); + } else if (Cv == one) { + t = Fv; + } else { /* Cv == zero: return(Fnv @ Cnv) */ + if (Cnv == one) { + r = Fnv; + } else { + r = cuddAddRestrictRecur(dd, Fnv, Cnv); + if (r == NULL) return(NULL); + } + return(r); + } + cuddRef(t); + + if (!Cudd_IsConstant(Cnv)) { + e = cuddAddRestrictRecur(dd, Fnv, Cnv); + if (e == NULL) { + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + } else if (Cnv == one) { + e = Fnv; + } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ + cuddDeref(t); + return(t); + } + cuddRef(e); + + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_RecursiveDeref(dd, e); + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + + cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r); + return(r); + +} /* end of cuddAddRestrictRecur */ + + + +/**Function******************************************************************** + + Synopsis [Performs safe minimization of a BDD.] + + Description [Performs safe minimization of a BDD. Given the BDD + f of a function to be minimized and a BDD + c representing the care set, Cudd_bddLICompaction + produces the BDD of a function that agrees with f + wherever c is 1. Safe minimization means that the size + of the result is guaranteed not to exceed the size of + f. This function is based on the DAC97 paper by Hong et + al.. Returns a pointer to the result if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddLICompaction] + +******************************************************************************/ +DdNode * +cuddBddLICompaction( + DdManager * dd /* manager */, + DdNode * f /* function to be minimized */, + DdNode * c /* constraint (care set) */) +{ + st_table *marktable, *markcache, *buildcache; + DdNode *res, *zero; + + zero = Cudd_Not(DD_ONE(dd)); + if (c == zero) return(zero); + + /* We need to use local caches for both steps of this operation. + ** The results of the edge marking step are only valid as long as the + ** edge markings themselves are available. However, the edge markings + ** are lost at the end of one invocation of Cudd_bddLICompaction. + ** Hence, the cache entries for the edge marking step must be + ** invalidated at the end of this function. + ** For the result of the building step we argue as follows. The result + ** for a node and a given constrain depends on the BDD in which the node + ** appears. Hence, the same node and constrain may give different results + ** in successive invocations. + */ + marktable = st_init_table(st_ptrcmp,st_ptrhash); + if (marktable == NULL) { + return(NULL); + } + markcache = st_init_table(MarkCacheCompare,MarkCacheHash); + if (markcache == NULL) { + st_free_table(marktable); + return(NULL); + } + if (cuddBddLICMarkEdges(dd,f,c,marktable,markcache) == CUDD_OUT_OF_MEM) { + st_foreach(markcache, MarkCacheCleanUp, NULL); + st_free_table(marktable); + st_free_table(markcache); + return(NULL); + } + st_foreach(markcache, MarkCacheCleanUp, NULL); + st_free_table(markcache); + buildcache = st_init_table(st_ptrcmp,st_ptrhash); + if (buildcache == NULL) { + st_free_table(marktable); + return(NULL); + } + res = cuddBddLICBuildResult(dd,f,buildcache,marktable); + st_free_table(buildcache); + st_free_table(marktable); + return(res); + +} /* end of cuddBddLICompaction */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddConstrainDecomp.] + + Description [Performs the recursive step of Cudd_bddConstrainDecomp. + Returns f super (i) if successful; otherwise NULL.] + + SideEffects [None] + + SeeAlso [Cudd_bddConstrainDecomp] + +******************************************************************************/ +static int +cuddBddConstrainDecomp( + DdManager * dd, + DdNode * f, + DdNode ** decomp) +{ + DdNode *F, *fv, *fvn; + DdNode *fAbs; + DdNode *result; + int ok; + + if (Cudd_IsConstant(f)) return(1); + /* Compute complements of cofactors. */ + F = Cudd_Regular(f); + fv = cuddT(F); + fvn = cuddE(F); + if (F == f) { + fv = Cudd_Not(fv); + fvn = Cudd_Not(fvn); + } + /* Compute abstraction of top variable. */ + fAbs = cuddBddAndRecur(dd, fv, fvn); + if (fAbs == NULL) { + return(0); + } + cuddRef(fAbs); + fAbs = Cudd_Not(fAbs); + /* Recursively find the next abstraction and the components of the + ** decomposition. */ + ok = cuddBddConstrainDecomp(dd, fAbs, decomp); + if (ok == 0) { + Cudd_IterDerefBdd(dd,fAbs); + return(0); + } + /* Compute the component of the decomposition corresponding to the + ** top variable and store it in the decomposition array. */ + result = cuddBddConstrainRecur(dd, f, fAbs); + if (result == NULL) { + Cudd_IterDerefBdd(dd,fAbs); + return(0); + } + cuddRef(result); + decomp[F->index] = result; + Cudd_IterDerefBdd(dd, fAbs); + return(1); + +} /* end of cuddBddConstrainDecomp */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddCharToVect.] + + Description [Performs the recursive step of Cudd_bddCharToVect. + This function maintains the invariant that f is non-zero. + Returns the i-th component of the vector if successful; otherwise NULL.] + + SideEffects [None] + + SeeAlso [Cudd_bddCharToVect] + +******************************************************************************/ +static DdNode * +cuddBddCharToVect( + DdManager * dd, + DdNode * f, + DdNode * x) +{ + unsigned int topf; + unsigned int level; + int comple; + + DdNode *one, *zero, *res, *F, *fT, *fE, *T, *E; + + statLine(dd); + /* Check the cache. */ + res = cuddCacheLookup2(dd, cuddBddCharToVect, f, x); + if (res != NULL) { + return(res); + } + + F = Cudd_Regular(f); + + topf = cuddI(dd,F->index); + level = dd->perm[x->index]; + + if (topf > level) return(x); + + one = DD_ONE(dd); + zero = Cudd_Not(one); + + comple = F != f; + fT = Cudd_NotCond(cuddT(F),comple); + fE = Cudd_NotCond(cuddE(F),comple); + + if (topf == level) { + if (fT == zero) return(zero); + if (fE == zero) return(one); + return(x); + } + + /* Here topf < level. */ + if (fT == zero) return(cuddBddCharToVect(dd, fE, x)); + if (fE == zero) return(cuddBddCharToVect(dd, fT, x)); + + T = cuddBddCharToVect(dd, fT, x); + if (T == NULL) { + return(NULL); + } + cuddRef(T); + E = cuddBddCharToVect(dd, fE, x); + if (E == NULL) { + Cudd_IterDerefBdd(dd,T); + return(NULL); + } + cuddRef(E); + res = cuddBddIteRecur(dd, dd->vars[F->index], T, E); + if (res == NULL) { + Cudd_IterDerefBdd(dd,T); + Cudd_IterDerefBdd(dd,E); + return(NULL); + } + cuddDeref(T); + cuddDeref(E); + cuddCacheInsert2(dd, cuddBddCharToVect, f, x, res); + return(res); + +} /* end of cuddBddCharToVect */ + + +/**Function******************************************************************** + + Synopsis [Performs the edge marking step of Cudd_bddLICompaction.] + + Description [Performs the edge marking step of Cudd_bddLICompaction. + Returns the LUB of the markings of the two outgoing edges of f + if successful; otherwise CUDD_OUT_OF_MEM.] + + SideEffects [None] + + SeeAlso [Cudd_bddLICompaction cuddBddLICBuildResult] + +******************************************************************************/ +static int +cuddBddLICMarkEdges( + DdManager * dd, + DdNode * f, + DdNode * c, + st_table * table, + st_table * cache) +{ + DdNode *Fv, *Fnv, *Cv, *Cnv; + DdNode *one, *zero; + unsigned int topf, topc; + int index; + int comple; + int resT, resE, res, retval; + char **slot; + MarkCacheKey *key; + + one = DD_ONE(dd); + zero = Cudd_Not(one); + + /* Terminal cases. */ + if (c == zero) return(DD_LIC_DC); + if (f == one) return(DD_LIC_1); + if (f == zero) return(DD_LIC_0); + + /* Make canonical to increase the utilization of the cache. */ + comple = Cudd_IsComplement(f); + f = Cudd_Regular(f); + /* Now f is a regular pointer to a non-constant node; c may be + ** constant, or it may be complemented. + */ + + /* Check the cache. */ + key = ALLOC(MarkCacheKey, 1); + if (key == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(CUDD_OUT_OF_MEM); + } + key->f = f; key->c = c; + if (st_lookup(cache, (char *)key, (char **)&res)) { + FREE(key); + if (comple) { + if (res == DD_LIC_0) res = DD_LIC_1; + else if (res == DD_LIC_1) res = DD_LIC_0; + } + return(res); + } + + /* Recursive step. */ + topf = dd->perm[f->index]; + topc = cuddI(dd,Cudd_Regular(c)->index); + if (topf <= topc) { + index = f->index; + Fv = cuddT(f); Fnv = cuddE(f); + } else { + index = Cudd_Regular(c)->index; + Fv = Fnv = f; + } + if (topc <= topf) { + /* We know that c is not constant because f is not. */ + Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); + if (Cudd_IsComplement(c)) { + Cv = Cudd_Not(Cv); + Cnv = Cudd_Not(Cnv); + } + } else { + Cv = Cnv = c; + } + + resT = cuddBddLICMarkEdges(dd, Fv, Cv, table, cache); + if (resT == CUDD_OUT_OF_MEM) { + FREE(key); + return(CUDD_OUT_OF_MEM); + } + resE = cuddBddLICMarkEdges(dd, Fnv, Cnv, table, cache); + if (resE == CUDD_OUT_OF_MEM) { + FREE(key); + return(CUDD_OUT_OF_MEM); + } + + /* Update edge markings. */ + if (topf <= topc) { + retval = st_find_or_add(table, (char *)f, (char ***)&slot); + if (retval == 0) { + *slot = (char *) (ptrint)((resT << 2) | resE); + } else if (retval == 1) { + *slot = (char *) (ptrint)((int)((ptrint) *slot) | (resT << 2) | resE); + } else { + FREE(key); + return(CUDD_OUT_OF_MEM); + } + } + + /* Cache result. */ + res = resT | resE; + if (st_insert(cache, (char *)key, (char *)(ptrint)res) == ST_OUT_OF_MEM) { + FREE(key); + return(CUDD_OUT_OF_MEM); + } + + /* Take into account possible complementation. */ + if (comple) { + if (res == DD_LIC_0) res = DD_LIC_1; + else if (res == DD_LIC_1) res = DD_LIC_0; + } + return(res); + +} /* end of cuddBddLICMarkEdges */ + + +/**Function******************************************************************** + + Synopsis [Builds the result of Cudd_bddLICompaction.] + + Description [Builds the results of Cudd_bddLICompaction. + Returns a pointer to the minimized BDD if successful; otherwise NULL.] + + SideEffects [None] + + SeeAlso [Cudd_bddLICompaction cuddBddLICMarkEdges] + +******************************************************************************/ +static DdNode * +cuddBddLICBuildResult( + DdManager * dd, + DdNode * f, + st_table * cache, + st_table * table) +{ + DdNode *Fv, *Fnv, *r, *t, *e; + DdNode *one, *zero; + unsigned int topf; + int index; + int comple; + int markT, markE, markings; + + one = DD_ONE(dd); + zero = Cudd_Not(one); + + if (Cudd_IsConstant(f)) return(f); + /* Make canonical to increase the utilization of the cache. */ + comple = Cudd_IsComplement(f); + f = Cudd_Regular(f); + + /* Check the cache. */ + if (st_lookup(cache, (char *)f, (char **)&r)) { + return(Cudd_NotCond(r,comple)); + } + + /* Retrieve the edge markings. */ + if (st_lookup(table, (char *)f, (char **)&markings) == 0) + return(NULL); + markT = markings >> 2; + markE = markings & 3; + + topf = dd->perm[f->index]; + index = f->index; + Fv = cuddT(f); Fnv = cuddE(f); + + if (markT == DD_LIC_NL) { + t = cuddBddLICBuildResult(dd,Fv,cache,table); + if (t == NULL) { + return(NULL); + } + } else if (markT == DD_LIC_1) { + t = one; + } else { + t = zero; + } + cuddRef(t); + if (markE == DD_LIC_NL) { + e = cuddBddLICBuildResult(dd,Fnv,cache,table); + if (e == NULL) { + Cudd_IterDerefBdd(dd,t); + return(NULL); + } + } else if (markE == DD_LIC_1) { + e = one; + } else { + e = zero; + } + cuddRef(e); + + if (markT == DD_LIC_DC && markE != DD_LIC_DC) { + r = e; + } else if (markT != DD_LIC_DC && markE == DD_LIC_DC) { + r = t; + } else { + if (Cudd_IsComplement(t)) { + t = Cudd_Not(t); + e = Cudd_Not(e); + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_IterDerefBdd(dd, e); + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_IterDerefBdd(dd, e); + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + } + } + cuddDeref(t); + cuddDeref(e); + + if (st_insert(cache, (char *)f, (char *)r) == ST_OUT_OF_MEM) { + cuddRef(r); + Cudd_IterDerefBdd(dd,r); + return(NULL); + } + + return(Cudd_NotCond(r,comple)); + +} /* end of cuddBddLICBuildResult */ + + +/**Function******************************************************************** + + Synopsis [Hash function for the computed table of cuddBddLICMarkEdges.] + + Description [Hash function for the computed table of + cuddBddLICMarkEdges. Returns the bucket number.] + + SideEffects [None] + + SeeAlso [Cudd_bddLICompaction] + +******************************************************************************/ +static int +MarkCacheHash( + char * ptr, + int modulus) +{ + int val = 0; + MarkCacheKey *entry; + + entry = (MarkCacheKey *) ptr; + + val = (int) (ptrint) entry->f; + val = val * 997 + (int) (ptrint) entry->c; + + return ((val < 0) ? -val : val) % modulus; + +} /* end of MarkCacheHash */ + + +/**Function******************************************************************** + + Synopsis [Comparison function for the computed table of + cuddBddLICMarkEdges.] + + Description [Comparison function for the computed table of + cuddBddLICMarkEdges. Returns 0 if the two nodes of the key are equal; 1 + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddLICompaction] + +******************************************************************************/ +static int +MarkCacheCompare( + const char * ptr1, + const char * ptr2) +{ + MarkCacheKey *entry1, *entry2; + + entry1 = (MarkCacheKey *) ptr1; + entry2 = (MarkCacheKey *) ptr2; + + return((entry1->f != entry2->f) || (entry1->c != entry2->c)); + +} /* end of MarkCacheCompare */ + + + +/**Function******************************************************************** + + Synopsis [Frees memory associated with computed table of + cuddBddLICMarkEdges.] + + Description [Frees memory associated with computed table of + cuddBddLICMarkEdges. Returns ST_CONTINUE.] + + SideEffects [None] + + SeeAlso [Cudd_bddLICompaction] + +******************************************************************************/ +static enum st_retval +MarkCacheCleanUp( + char * key, + char * value, + char * arg) +{ + MarkCacheKey *entry; + + entry = (MarkCacheKey *) key; + FREE(entry); + return ST_CONTINUE; + +} /* end of MarkCacheCleanUp */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddSqueeze.] + + Description [Performs the recursive step of Cudd_bddSqueeze. This + procedure exploits the fact that if we complement and swap the + bounds of the interval we obtain a valid solution by taking the + complement of the solution to the original problem. Therefore, we + can enforce the condition that the upper bound is always regular. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddSqueeze] + +******************************************************************************/ +static DdNode * +cuddBddSqueeze( + DdManager * dd, + DdNode * l, + DdNode * u) +{ + DdNode *one, *zero, *r, *lt, *le, *ut, *ue, *t, *e; +#if 0 + DdNode *ar; +#endif + int comple = 0; + unsigned int topu, topl; + int index; + + statLine(dd); + if (l == u) { + return(l); + } + one = DD_ONE(dd); + zero = Cudd_Not(one); + /* The only case when l == zero && u == one is at the top level, + ** where returning either one or zero is OK. In all other cases + ** the procedure will detect such a case and will perform + ** remapping. Therefore the order in which we test l and u at this + ** point is immaterial. */ + if (l == zero) return(l); + if (u == one) return(u); + + /* Make canonical to increase the utilization of the cache. */ + if (Cudd_IsComplement(u)) { + DdNode *temp; + temp = Cudd_Not(l); + l = Cudd_Not(u); + u = temp; + comple = 1; + } + /* At this point u is regular and non-constant; l is non-constant, but + ** may be complemented. */ + + /* Here we could check the relative sizes. */ + + /* Check the cache. */ + r = cuddCacheLookup2(dd, Cudd_bddSqueeze, l, u); + if (r != NULL) { + return(Cudd_NotCond(r,comple)); + } + + /* Recursive step. */ + topu = dd->perm[u->index]; + topl = dd->perm[Cudd_Regular(l)->index]; + if (topu <= topl) { + index = u->index; + ut = cuddT(u); ue = cuddE(u); + } else { + index = Cudd_Regular(l)->index; + ut = ue = u; + } + if (topl <= topu) { + lt = cuddT(Cudd_Regular(l)); le = cuddE(Cudd_Regular(l)); + if (Cudd_IsComplement(l)) { + lt = Cudd_Not(lt); + le = Cudd_Not(le); + } + } else { + lt = le = l; + } + + /* If one interval is contained in the other, use the smaller + ** interval. This corresponds to one-sided matching. */ + if ((lt == zero || Cudd_bddLeq(dd,lt,le)) && + (ut == one || Cudd_bddLeq(dd,ue,ut))) { /* remap */ + r = cuddBddSqueeze(dd, le, ue); + if (r == NULL) + return(NULL); + return(Cudd_NotCond(r,comple)); + } else if ((le == zero || Cudd_bddLeq(dd,le,lt)) && + (ue == one || Cudd_bddLeq(dd,ut,ue))) { /* remap */ + r = cuddBddSqueeze(dd, lt, ut); + if (r == NULL) + return(NULL); + return(Cudd_NotCond(r,comple)); + } else if ((le == zero || Cudd_bddLeq(dd,le,Cudd_Not(ut))) && + (ue == one || Cudd_bddLeq(dd,Cudd_Not(lt),ue))) { /* c-remap */ + t = cuddBddSqueeze(dd, lt, ut); + cuddRef(t); + if (Cudd_IsComplement(t)) { + r = cuddUniqueInter(dd, index, Cudd_Not(t), t); + if (r == NULL) { + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = cuddUniqueInter(dd, index, t, Cudd_Not(t)); + if (r == NULL) { + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + } + cuddDeref(t); + if (r == NULL) + return(NULL); + cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); + return(Cudd_NotCond(r,comple)); + } else if ((lt == zero || Cudd_bddLeq(dd,lt,Cudd_Not(ue))) && + (ut == one || Cudd_bddLeq(dd,Cudd_Not(le),ut))) { /* c-remap */ + e = cuddBddSqueeze(dd, le, ue); + cuddRef(e); + if (Cudd_IsComplement(e)) { + r = cuddUniqueInter(dd, index, Cudd_Not(e), e); + if (r == NULL) { + Cudd_IterDerefBdd(dd, e); + return(NULL); + } + } else { + r = cuddUniqueInter(dd, index, e, Cudd_Not(e)); + if (r == NULL) { + Cudd_IterDerefBdd(dd, e); + return(NULL); + } + r = Cudd_Not(r); + } + cuddDeref(e); + if (r == NULL) + return(NULL); + cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); + return(Cudd_NotCond(r,comple)); + } + +#if 0 + /* If the two intervals intersect, take a solution from + ** the intersection of the intervals. This guarantees that the + ** splitting variable will not appear in the result. + ** This approach corresponds to two-sided matching, and is very + ** expensive. */ + if (Cudd_bddLeq(dd,lt,ue) && Cudd_bddLeq(dd,le,ut)) { + DdNode *au, *al; + au = cuddBddAndRecur(dd,ut,ue); + if (au == NULL) + return(NULL); + cuddRef(au); + al = cuddBddAndRecur(dd,Cudd_Not(lt),Cudd_Not(le)); + if (al == NULL) { + Cudd_IterDerefBdd(dd,au); + return(NULL); + } + cuddRef(al); + al = Cudd_Not(al); + ar = cuddBddSqueeze(dd, al, au); + if (ar == NULL) { + Cudd_IterDerefBdd(dd,au); + Cudd_IterDerefBdd(dd,al); + return(NULL); + } + cuddRef(ar); + Cudd_IterDerefBdd(dd,au); + Cudd_IterDerefBdd(dd,al); + } else { + ar = NULL; + } +#endif + + t = cuddBddSqueeze(dd, lt, ut); + if (t == NULL) { + return(NULL); + } + cuddRef(t); + e = cuddBddSqueeze(dd, le, ue); + if (e == NULL) { + Cudd_IterDerefBdd(dd,t); + return(NULL); + } + cuddRef(e); + + if (Cudd_IsComplement(t)) { + t = Cudd_Not(t); + e = Cudd_Not(e); + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_IterDerefBdd(dd, e); + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + r = Cudd_Not(r); + } else { + r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); + if (r == NULL) { + Cudd_IterDerefBdd(dd, e); + Cudd_IterDerefBdd(dd, t); + return(NULL); + } + } + cuddDeref(t); + cuddDeref(e); + +#if 0 + /* Check whether there is a result obtained by abstraction and whether + ** it is better than the one obtained by recursion. */ + cuddRef(r); + if (ar != NULL) { + if (Cudd_DagSize(ar) <= Cudd_DagSize(r)) { + Cudd_IterDerefBdd(dd, r); + r = ar; + } else { + Cudd_IterDerefBdd(dd, ar); + } + } + cuddDeref(r); +#endif + + cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); + return(Cudd_NotCond(r,comple)); + +} /* end of cuddBddSqueeze */ diff --git a/abc70930/src/bdd/cudd/cuddGenetic.c b/abc70930/src/bdd/cudd/cuddGenetic.c new file mode 100644 index 00000000..9fe03dad --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddGenetic.c @@ -0,0 +1,921 @@ +/**CFile*********************************************************************** + + FileName [cuddGenetic.c] + + PackageName [cudd] + + Synopsis [Genetic algorithm for variable reordering.] + + Description [Internal procedures included in this file: +
        +
      • cuddGa() +
      + Static procedures included in this module: +
        +
      • make_random() +
      • sift_up() +
      • build_dd() +
      • largest() +
      • rand_int() +
      • array_hash() +
      • array_compare() +
      • find_best() +
      • find_average_fitness() +
      • PMX() +
      • roulette() +
      + + The genetic algorithm implemented here is as follows. We start with + the current DD order. We sift this order and use this as the + reference DD. We only keep 1 DD around for the entire process and + simply rearrange the order of this DD, storing the various orders + and their corresponding DD sizes. We generate more random orders to + build an initial population. This initial population is 3 times the + number of variables, with a maximum of 120. Each random order is + built (from the reference DD) and its size stored. Each random + order is also sifted to keep the DD sizes fairly small. Then a + crossover is performed between two orders (picked randomly) and the + two resulting DDs are built and sifted. For each new order, if its + size is smaller than any DD in the population, it is inserted into + the population and the DD with the largest number of nodes is thrown + out. The crossover process happens up to 50 times, and at this point + the DD in the population with the smallest size is chosen as the + result. This DD must then be built from the reference DD.] + + SeeAlso [] + + Author [Curt Musfeldt, Alan Shuler, Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddGenetic.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +static int popsize; /* the size of the population */ +static int numvars; /* the number of input variables in the ckt. */ +/* storedd stores the population orders and sizes. This table has two +** extra rows and one extras column. The two extra rows are used for the +** offspring produced by a crossover. Each row stores one order and its +** size. The order is stored by storing the indices of variables in the +** order in which they appear in the order. The table is in reality a +** one-dimensional array which is accessed via a macro to give the illusion +** it is a two-dimensional structure. +*/ +static int *storedd; +static st_table *computed; /* hash table to identify existing orders */ +static int *repeat; /* how many times an order is present */ +static int large; /* stores the index of the population with + ** the largest number of nodes in the DD */ +static int result; +static int cross; /* the number of crossovers to perform */ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/* macro used to access the population table as if it were a +** two-dimensional structure. +*/ +#define STOREDD(i,j) storedd[(i)*(numvars+1)+(j)] + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int make_random ARGS((DdManager *table, int lower)); +static int sift_up ARGS((DdManager *table, int x, int x_low)); +static int build_dd ARGS((DdManager *table, int num, int lower, int upper)); +static int largest ARGS(()); +static int rand_int ARGS((int a)); +static int array_hash ARGS((char *array, int modulus)); +static int array_compare ARGS((const char *array1, const char *array2)); +static int find_best ARGS(()); +static double find_average_fitness ARGS(()); +static int PMX ARGS((int maxvar)); +static int roulette ARGS((int *p1, int *p2)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Genetic algorithm for DD reordering.] + + Description [Genetic algorithm for DD reordering. + The two children of a crossover will be stored in + storedd[popsize] and storedd[popsize+1] --- the last two slots in the + storedd array. (This will make comparisons and replacement easy.) + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddGa( + DdManager * table /* manager */, + int lower /* lowest level to be reordered */, + int upper /* highest level to be reorderded */) +{ + int i,n,m; /* dummy/loop vars */ + int index; + double average_fitness; + int small; /* index of smallest DD in population */ + + /* Do an initial sifting to produce at least one reasonable individual. */ + if (!cuddSifting(table,lower,upper)) return(0); + + /* Get the initial values. */ + numvars = upper - lower + 1; /* number of variables to be reordered */ + if (table->populationSize == 0) { + popsize = 3 * numvars; /* population size is 3 times # of vars */ + if (popsize > 120) { + popsize = 120; /* Maximum population size is 120 */ + } + } else { + popsize = table->populationSize; /* user specified value */ + } + if (popsize < 4) popsize = 4; /* enforce minimum population size */ + + /* Allocate population table. */ + storedd = ALLOC(int,(popsize+2)*(numvars+1)); + if (storedd == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + + /* Initialize the computed table. This table is made up of two data + ** structures: A hash table with the key given by the order, which says + ** if a given order is present in the population; and the repeat + ** vector, which says how many copies of a given order are stored in + ** the population table. If there are multiple copies of an order, only + ** one has a repeat count greater than 1. This copy is the one pointed + ** by the computed table. + */ + repeat = ALLOC(int,popsize); + if (repeat == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + FREE(storedd); + return(0); + } + for (i = 0; i < popsize; i++) { + repeat[i] = 0; + } + computed = st_init_table(array_compare,array_hash); + if (computed == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + FREE(storedd); + FREE(repeat); + return(0); + } + + /* Copy the current DD and its size to the population table. */ + for (i = 0; i < numvars; i++) { + STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */ + } + STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */ + + /* Store the initial order in the computed table. */ + if (st_insert(computed,(char *)storedd,(char *) 0) == ST_OUT_OF_MEM) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + repeat[0]++; + + /* Insert the reverse order as second element of the population. */ + for (i = 0; i < numvars; i++) { + STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */ + } + + /* Now create the random orders. make_random fills the population + ** table with random permutations. The successive loop builds and sifts + ** the DDs for the reverse order and each random permutation, and stores + ** the results in the computed table. + */ + if (!make_random(table,lower)) { + table->errorCode = CUDD_MEMORY_OUT; + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + for (i = 1; i < popsize; i++) { + result = build_dd(table,i,lower,upper); /* build and sift order */ + if (!result) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + if (st_lookup(computed,(char *)&STOREDD(i,0),(char **)&index)) { + repeat[index]++; + } else { + if (st_insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) == + ST_OUT_OF_MEM) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + repeat[i]++; + } + } + +#if 0 +#ifdef DD_STATS + /* Print the initial population. */ + (void) fprintf(table->out,"Initial population after sifting\n"); + for (m = 0; m < popsize; m++) { + for (i = 0; i < numvars; i++) { + (void) fprintf(table->out," %2d",STOREDD(m,i)); + } + (void) fprintf(table->out," : %3d (%d)\n", + STOREDD(m,numvars),repeat[m]); + } +#endif +#endif + + small = find_best(); + average_fitness = find_average_fitness(); +#ifdef DD_STATS + (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); +#endif + + /* Decide how many crossovers should be tried. */ + if (table->numberXovers == 0) { + cross = 3*numvars; + if (cross > 60) { /* do a maximum of 50 crossovers */ + cross = 60; + } + } else { + cross = table->numberXovers; /* use user specified value */ + } + + /* Perform the crossovers to get the best order. */ + for (m = 0; m < cross; m++) { + if (!PMX(table->size)) { /* perform one crossover */ + table->errorCode = CUDD_MEMORY_OUT; + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + /* The offsprings are left in the last two entries of the + ** population table. These are now considered in turn. + */ + for (i = popsize; i <= popsize+1; i++) { + result = build_dd(table,i,lower,upper); /* build and sift child */ + if (!result) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + large = largest(); /* find the largest DD in population */ + + /* If the new child is smaller than the largest DD in the current + ** population, enter it into the population in place of the + ** largest DD. + */ + if (STOREDD(i,numvars) < STOREDD(large,numvars)) { + /* Look up the largest DD in the computed table. + ** Decrease its repetition count. If the repetition count + ** goes to 0, remove the largest DD from the computed table. + */ + result = st_lookup(computed,(char *)&STOREDD(large,0),(char + **)&index); + if (!result) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + repeat[index]--; + if (repeat[index] == 0) { + int *pointer = &STOREDD(index,0); + result = st_delete(computed, (char **)&pointer,NULL); + if (!result) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + } + /* Copy the new individual to the entry of the + ** population table just made available and update the + ** computed table. + */ + for (n = 0; n <= numvars; n++) { + STOREDD(large,n) = STOREDD(i,n); + } + if (st_lookup(computed,(char *)&STOREDD(large,0),(char + **)&index)) { + repeat[index]++; + } else { + if (st_insert(computed,(char *)&STOREDD(large,0), + (char *)(long)large) == ST_OUT_OF_MEM) { + FREE(storedd); + FREE(repeat); + st_free_table(computed); + return(0); + } + repeat[large]++; + } + } + } + } + + /* Find the smallest DD in the population and build it; + ** that will be the result. + */ + small = find_best(); + + /* Print stats on the final population. */ +#ifdef DD_STATS + average_fitness = find_average_fitness(); + (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); +#endif + + /* Clean up, build the result DD, and return. */ + st_free_table(computed); + computed = NULL; + result = build_dd(table,small,lower,upper); + FREE(storedd); + FREE(repeat); + return(result); + +} /* end of cuddGa */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Generates the random sequences for the initial population.] + + Description [Generates the random sequences for the initial population. + The sequences are permutations of the indices between lower and + upper in the current order.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +make_random( + DdManager * table, + int lower) +{ + int i,j; /* loop variables */ + int *used; /* is a number already in a permutation */ + int next; /* next random number without repetitions */ + + used = ALLOC(int,numvars); + if (used == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } +#if 0 +#ifdef DD_STATS + (void) fprintf(table->out,"Initial population before sifting\n"); + for (i = 0; i < 2; i++) { + for (j = 0; j < numvars; j++) { + (void) fprintf(table->out," %2d",STOREDD(i,j)); + } + (void) fprintf(table->out,"\n"); + } +#endif +#endif + for (i = 2; i < popsize; i++) { + for (j = 0; j < numvars; j++) { + used[j] = 0; + } + /* Generate a permutation of {0...numvars-1} and use it to + ** permute the variables in the layesr from lower to upper. + */ + for (j = 0; j < numvars; j++) { + do { + next = rand_int(numvars-1); + } while (used[next] != 0); + used[next] = 1; + STOREDD(i,j) = table->invperm[next+lower]; + } +#if 0 +#ifdef DD_STATS + /* Print the order just generated. */ + for (j = 0; j < numvars; j++) { + (void) fprintf(table->out," %2d",STOREDD(i,j)); + } + (void) fprintf(table->out,"\n"); +#endif +#endif + } + FREE(used); + return(1); + +} /* end of make_random */ + + +/**Function******************************************************************** + + Synopsis [Moves one variable up.] + + Description [Takes a variable from position x and sifts it up to + position x_low; x_low should be less than x. Returns 1 if successful; + 0 otherwise] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +sift_up( + DdManager * table, + int x, + int x_low) +{ + int y; + int size; + + y = cuddNextLow(table,x); + while (y >= x_low) { + size = cuddSwapInPlace(table,y,x); + if (size == 0) { + return(0); + } + x = y; + y = cuddNextLow(table,x); + } + return(1); + +} /* end of sift_up */ + + +/**Function******************************************************************** + + Synopsis [Builds a DD from a given order.] + + Description [Builds a DD from a given order. This procedure also + sifts the final order and inserts into the array the size in nodes + of the result. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +build_dd( + DdManager * table, + int num /* the index of the individual to be built */, + int lower, + int upper) +{ + int i,j; /* loop vars */ + int position; + int index; + int limit; /* how large the DD for this order can grow */ + int size; + + /* Check the computed table. If the order already exists, it + ** suffices to copy the size from the existing entry. + */ + if (computed && st_lookup(computed,(char *)&STOREDD(num,0),(char **)&index)) { + STOREDD(num,numvars) = STOREDD(index,numvars); +#ifdef DD_STATS + (void) fprintf(table->out,"\nCache hit for index %d", index); +#endif + return(1); + } + + /* Stop if the DD grows 20 times larges than the reference size. */ + limit = 20 * STOREDD(0,numvars); + + /* Sift up the variables so as to build the desired permutation. + ** First the variable that has to be on top is sifted to the top. + ** Then the variable that has to occupy the secon position is sifted + ** up to the second position, and so on. + */ + for (j = 0; j < numvars; j++) { + i = STOREDD(num,j); + position = table->perm[i]; + result = sift_up(table,position,j+lower); + if (!result) return(0); + size = table->keys - table->isolated; + if (size > limit) break; + } + + /* Sift the DD just built. */ +#ifdef DD_STATS + (void) fprintf(table->out,"\n"); +#endif + result = cuddSifting(table,lower,upper); + if (!result) return(0); + + /* Copy order and size to table. */ + for (j = 0; j < numvars; j++) { + STOREDD(num,j) = table->invperm[lower+j]; + } + STOREDD(num,numvars) = table->keys - table->isolated; /* size of new DD */ + return(1); + +} /* end of build_dd */ + + +/**Function******************************************************************** + + Synopsis [Finds the largest DD in the population.] + + Description [Finds the largest DD in the population. If an order is + repeated, it avoids choosing the copy that is in the computed table + (it has repeat[i] > 1).] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +largest( + ) +{ + int i; /* loop var */ + int big; /* temporary holder to return result */ + + big = 0; + while (repeat[big] > 1) big++; + for (i = big + 1; i < popsize; i++) { + if (STOREDD(i,numvars) >= STOREDD(big,numvars) && repeat[i] <= 1) { + big = i; + } + } + return(big); + +} /* end of largest */ + + +/**Function******************************************************************** + + Synopsis [Generates a random number between 0 and the integer a.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +rand_int( + int a) +{ + return(Cudd_Random() % (a+1)); + +} /* end of rand_int */ + + +/**Function******************************************************************** + + Synopsis [Hash function for the computed table.] + + Description [Hash function for the computed table. Returns the bucket + number.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +array_hash( + char * array, + int modulus) +{ + int val = 0; + int i; + int *intarray; + + intarray = (int *) array; + + for (i = 0; i < numvars; i++) { + val = val * 997 + intarray[i]; + } + + return ((val < 0) ? -val : val) % modulus; + +} /* end of array_hash */ + + +/**Function******************************************************************** + + Synopsis [Comparison function for the computed table.] + + Description [Comparison function for the computed table. Returns 0 if + the two arrays are equal; 1 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +array_compare( + const char * array1, + const char * array2) +{ + int i; + int *intarray1, *intarray2; + + intarray1 = (int *) array1; + intarray2 = (int *) array2; + + for (i = 0; i < numvars; i++) { + if (intarray1[i] != intarray2[i]) return(1); + } + return(0); + +} /* end of array_compare */ + + +/**Function******************************************************************** + + Synopsis [Returns the index of the fittest individual.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +find_best( + ) +{ + int i,small; + + small = 0; + for (i = 1; i < popsize; i++) { + if (STOREDD(i,numvars) < STOREDD(small,numvars)) { + small = i; + } + } + return(small); + +} /* end of find_best */ + + +/**Function******************************************************************** + + Synopsis [Returns the average fitness of the population.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static double +find_average_fitness( + ) +{ + int i; + int total_fitness = 0; + double average_fitness; + + for (i = 0; i < popsize; i++) { + total_fitness += STOREDD(i,numvars); + } + average_fitness = (double) total_fitness / (double) popsize; + return(average_fitness); + +} /* end of find_average_fitness */ + + +/**Function******************************************************************** + + Synopsis [Performs the crossover between two parents.] + + Description [Performs the crossover between two randomly chosen + parents, and creates two children, x1 and x2. Uses the Partially + Matched Crossover operator.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +PMX( + int maxvar) +{ + int cut1,cut2; /* the two cut positions (random) */ + int mom,dad; /* the two randomly chosen parents */ + int *inv1; /* inverse permutations for repair algo */ + int *inv2; + int i; /* loop vars */ + int u,v; /* aux vars */ + + inv1 = ALLOC(int,maxvar); + if (inv1 == NULL) { + return(0); + } + inv2 = ALLOC(int,maxvar); + if (inv2 == NULL) { + FREE(inv1); + return(0); + } + + /* Choose two orders from the population using roulette wheel. */ + if (!roulette(&mom,&dad)) { + FREE(inv1); + FREE(inv2); + return(0); + } + + /* Choose two random cut positions. A cut in position i means that + ** the cut immediately precedes position i. If cut1 < cut2, we + ** exchange the middle of the two orderings; otherwise, we + ** exchange the beginnings and the ends. + */ + cut1 = rand_int(numvars-1); + do { + cut2 = rand_int(numvars-1); + } while (cut1 == cut2); + +#if 0 + /* Print out the parents. */ + (void) fprintf(table->out, + "Crossover of %d (mom) and %d (dad) between %d and %d\n", + mom,dad,cut1,cut2); + for (i = 0; i < numvars; i++) { + if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); + (void) fprintf(table->out,"%2d ",STOREDD(mom,i)); + } + (void) fprintf(table->out,"\n"); + for (i = 0; i < numvars; i++) { + if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); + (void) fprintf(table->out,"%2d ",STOREDD(dad,i)); + } + (void) fprintf(table->out,"\n"); +#endif + + /* Initialize the inverse permutations: -1 means yet undetermined. */ + for (i = 0; i < maxvar; i++) { + inv1[i] = -1; + inv2[i] = -1; + } + + /* Copy the portions whithin the cuts. */ + for (i = cut1; i != cut2; i = (i == numvars-1) ? 0 : i+1) { + STOREDD(popsize,i) = STOREDD(dad,i); + inv1[STOREDD(popsize,i)] = i; + STOREDD(popsize+1,i) = STOREDD(mom,i); + inv2[STOREDD(popsize+1,i)] = i; + } + + /* Now apply the repair algorithm outside the cuts. */ + for (i = cut2; i != cut1; i = (i == numvars-1 ) ? 0 : i+1) { + v = i; + do { + u = STOREDD(mom,v); + v = inv1[u]; + } while (v != -1); + STOREDD(popsize,i) = u; + inv1[u] = i; + v = i; + do { + u = STOREDD(dad,v); + v = inv2[u]; + } while (v != -1); + STOREDD(popsize+1,i) = u; + inv2[u] = i; + } + +#if 0 + /* Print the results of crossover. */ + for (i = 0; i < numvars; i++) { + if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); + (void) fprintf(table->out,"%2d ",STOREDD(popsize,i)); + } + (void) fprintf(table->out,"\n"); + for (i = 0; i < numvars; i++) { + if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); + (void) fprintf(table->out,"%2d ",STOREDD(popsize+1,i)); + } + (void) fprintf(table->out,"\n"); +#endif + + FREE(inv1); + FREE(inv2); + return(1); + +} /* end of PMX */ + + +/**Function******************************************************************** + + Synopsis [Selects two parents with the roulette wheel method.] + + Description [Selects two distinct parents with the roulette wheel method.] + + SideEffects [The indices of the selected parents are returned as side + effects.] + + SeeAlso [] + +******************************************************************************/ +static int +roulette( + int * p1, + int * p2) +{ + double *wheel; + double spin; + int i; + + wheel = ALLOC(double,popsize); + if (wheel == NULL) { + return(0); + } + + /* The fitness of an individual is the reciprocal of its size. */ + wheel[0] = 1.0 / (double) STOREDD(0,numvars); + + for (i = 1; i < popsize; i++) { + wheel[i] = wheel[i-1] + 1.0 / (double) STOREDD(i,numvars); + } + + /* Get a random number between 0 and wheel[popsize-1] (that is, + ** the sum of all fitness values. 2147483561 is the largest number + ** returned by Cudd_Random. + */ + spin = wheel[numvars-1] * (double) Cudd_Random() / 2147483561.0; + + /* Find the lucky element by scanning the wheel. */ + for (i = 0; i < popsize; i++) { + if (spin <= wheel[i]) break; + } + *p1 = i; + + /* Repeat the process for the second parent, making sure it is + ** distinct from the first. + */ + do { + spin = wheel[popsize-1] * (double) Cudd_Random() / 2147483561.0; + for (i = 0; i < popsize; i++) { + if (spin <= wheel[i]) break; + } + } while (i == *p1); + *p2 = i; + + FREE(wheel); + return(1); + +} /* end of roulette */ + diff --git a/abc70930/src/bdd/cudd/cuddGroup.c b/abc70930/src/bdd/cudd/cuddGroup.c new file mode 100644 index 00000000..81c05d2c --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddGroup.c @@ -0,0 +1,2142 @@ +/**CFile*********************************************************************** + + FileName [cuddGroup.c] + + PackageName [cudd] + + Synopsis [Functions for group sifting.] + + Description [External procedures included in this file: +
        +
      • Cudd_MakeTreeNode() +
      + Internal procedures included in this file: +
        +
      • cuddTreeSifting() +
      + Static procedures included in this module: +
        +
      • ddTreeSiftingAux() +
      • ddCountInternalMtrNodes() +
      • ddReorderChildren() +
      • ddFindNodeHiLo() +
      • ddUniqueCompareGroup() +
      • ddGroupSifting() +
      • ddCreateGroup() +
      • ddGroupSiftingAux() +
      • ddGroupSiftingUp() +
      • ddGroupSiftingDown() +
      • ddGroupMove() +
      • ddGroupMoveBackward() +
      • ddGroupSiftingBackward() +
      • ddMergeGroups() +
      • ddDissolveGroup() +
      • ddNoCheck() +
      • ddSecDiffCheck() +
      • ddExtSymmCheck() +
      • ddVarGroupCheck() +
      • ddSetVarHandled() +
      • ddResetVarHandled() +
      • ddIsVarHandled() +
      ] + + Author [Shipra Panda, Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/* Constants for lazy sifting */ +#define DD_NORMAL_SIFT 0 +#define DD_LAZY_SIFT 1 + +/* Constants for sifting up and down */ +#define DD_SIFT_DOWN 0 +#define DD_SIFT_UP 1 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddGroup.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +static int *entry; +extern int ddTotalNumberSwapping; +#ifdef DD_STATS +extern int ddTotalNISwaps; +static int extsymmcalls; +static int extsymm; +static int secdiffcalls; +static int secdiff; +static int secdiffmisfire; +#endif +#ifdef DD_DEBUG +static int pr = 0; /* flag to enable printing while debugging */ + /* by depositing a 1 into it */ +#endif +static int originalSize; +static int originalLevel; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int ddTreeSiftingAux ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); +#ifdef DD_STATS +static int ddCountInternalMtrNodes ARGS((DdManager *table, MtrNode *treenode)); +#endif +static int ddReorderChildren ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); +static void ddFindNodeHiLo ARGS((DdManager *table, MtrNode *treenode, int *lower, int *upper)); +static int ddUniqueCompareGroup ARGS((int *ptrX, int *ptrY)); +static int ddGroupSifting ARGS((DdManager *table, int lower, int upper, int (*checkFunction)(DdManager *, int, int), int lazyFlag)); +static void ddCreateGroup ARGS((DdManager *table, int x, int y)); +static int ddGroupSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh, int (*checkFunction)(DdManager *, int, int), int lazyFlag)); +static int ddGroupSiftingUp ARGS((DdManager *table, int y, int xLow, int (*checkFunction)(DdManager *, int, int), Move **moves)); +static int ddGroupSiftingDown ARGS((DdManager *table, int x, int xHigh, int (*checkFunction)(DdManager *, int, int), Move **moves)); +static int ddGroupMove ARGS((DdManager *table, int x, int y, Move **moves)); +static int ddGroupMoveBackward ARGS((DdManager *table, int x, int y)); +static int ddGroupSiftingBackward ARGS((DdManager *table, Move *moves, int size, int upFlag, int lazyFlag)); +static void ddMergeGroups ARGS((DdManager *table, MtrNode *treenode, int low, int high)); +static void ddDissolveGroup ARGS((DdManager *table, int x, int y)); +static int ddNoCheck ARGS((DdManager *table, int x, int y)); +static int ddSecDiffCheck ARGS((DdManager *table, int x, int y)); +static int ddExtSymmCheck ARGS((DdManager *table, int x, int y)); +static int ddVarGroupCheck ARGS((DdManager * table, int x, int y)); +static int ddSetVarHandled ARGS((DdManager *dd, int index)); +static int ddResetVarHandled ARGS((DdManager *dd, int index)); +static int ddIsVarHandled ARGS((DdManager *dd, int index)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Creates a new variable group.] + + Description [Creates a new variable group. The group starts at + variable and contains size variables. The parameter low is the index + of the first variable. If the variable already exists, its current + position in the order is known to the manager. If the variable does + not exist yet, the position is assumed to be the same as the index. + The group tree is created if it does not exist yet. + Returns a pointer to the group if successful; NULL otherwise.] + + SideEffects [The variable tree is changed.] + + SeeAlso [Cudd_MakeZddTreeNode] + +******************************************************************************/ +MtrNode * +Cudd_MakeTreeNode( + DdManager * dd /* manager */, + unsigned int low /* index of the first group variable */, + unsigned int size /* number of variables in the group */, + unsigned int type /* MTR_DEFAULT or MTR_FIXED */) +{ + MtrNode *group; + MtrNode *tree; + unsigned int level; + + /* If the variable does not exist yet, the position is assumed to be + ** the same as the index. Therefore, applications that rely on + ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new + ** variables have to create the variables before they group them. + */ + level = (low < (unsigned int) dd->size) ? dd->perm[low] : low; + + if (level + size - 1> (int) MTR_MAXHIGH) + return(NULL); + + /* If the tree does not exist yet, create it. */ + tree = dd->tree; + if (tree == NULL) { + dd->tree = tree = Mtr_InitGroupTree(0, dd->size); + if (tree == NULL) + return(NULL); + tree->index = dd->invperm[0]; + } + + /* Extend the upper bound of the tree if necessary. This allows the + ** application to create groups even before the variables are created. + */ + tree->size = ddMax(tree->size, ddMax(level + size, (unsigned) dd->size)); + + /* Create the group. */ + group = Mtr_MakeGroup(tree, level, size, type); + if (group == NULL) + return(NULL); + + /* Initialize the index field to the index of the variable currently + ** in position low. This field will be updated by the reordering + ** procedure to provide a handle to the group once it has been moved. + */ + group->index = (MtrHalfWord) low; + + return(group); + +} /* end of Cudd_MakeTreeNode */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Tree sifting algorithm.] + + Description [Tree sifting algorithm. Assumes that a tree representing + a group hierarchy is passed as a parameter. It then reorders each + group in postorder fashion by calling ddTreeSiftingAux. Assumes that + no dead nodes are present. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +int +cuddTreeSifting( + DdManager * table /* DD table */, + Cudd_ReorderingType method /* reordering method for the groups of leaves */) +{ + int i; + int nvars; + int result; + int tempTree; + + /* If no tree is provided we create a temporary one in which all + ** variables are in a single group. After reordering this tree is + ** destroyed. + */ + tempTree = table->tree == NULL; + if (tempTree) { + table->tree = Mtr_InitGroupTree(0,table->size); + table->tree->index = table->invperm[0]; + } + nvars = table->size; + +#ifdef DD_DEBUG + if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:"); + Mtr_PrintGroups(table->tree,pr <= 0); +#endif + +#ifdef DD_STATS + extsymmcalls = 0; + extsymm = 0; + secdiffcalls = 0; + secdiff = 0; + secdiffmisfire = 0; + + (void) fprintf(table->out,"\n"); + if (!tempTree) + (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", + ddCountInternalMtrNodes(table,table->tree)); +#endif + + /* Initialize the group of each subtable to itself. Initially + ** there are no groups. Groups are created according to the tree + ** structure in postorder fashion. + */ + for (i = 0; i < nvars; i++) + table->subtables[i].next = i; + + + /* Reorder. */ + result = ddTreeSiftingAux(table, table->tree, method); + +#ifdef DD_STATS /* print stats */ + if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && + (table->groupcheck == CUDD_GROUP_CHECK7 || + table->groupcheck == CUDD_GROUP_CHECK5)) { + (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); + (void) fprintf(table->out,"extsymm = %d",extsymm); + } + if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && + table->groupcheck == CUDD_GROUP_CHECK7) { + (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); + (void) fprintf(table->out,"secdiff = %d\n",secdiff); + (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); + } +#endif + + if (tempTree) + Cudd_FreeTree(table); + return(result); + +} /* end of cuddTreeSifting */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Visits the group tree and reorders each group.] + + Description [Recursively visits the group tree and reorders each + group in postorder fashion. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddTreeSiftingAux( + DdManager * table, + MtrNode * treenode, + Cudd_ReorderingType method) +{ + MtrNode *auxnode; + int res; + Cudd_AggregationType saveCheck; + +#ifdef DD_DEBUG + Mtr_PrintGroups(treenode,1); +#endif + + auxnode = treenode; + while (auxnode != NULL) { + if (auxnode->child != NULL) { + if (!ddTreeSiftingAux(table, auxnode->child, method)) + return(0); + saveCheck = table->groupcheck; + table->groupcheck = CUDD_NO_CHECK; + if (method != CUDD_REORDER_LAZY_SIFT) + res = ddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT); + else + res = ddReorderChildren(table, auxnode, CUDD_REORDER_LAZY_SIFT); + table->groupcheck = saveCheck; + + if (res == 0) + return(0); + } else if (auxnode->size > 1) { + if (!ddReorderChildren(table, auxnode, method)) + return(0); + } + auxnode = auxnode->younger; + } + + return(1); + +} /* end of ddTreeSiftingAux */ + + +#ifdef DD_STATS +/**Function******************************************************************** + + Synopsis [Counts the number of internal nodes of the group tree.] + + Description [Counts the number of internal nodes of the group tree. + Returns the count.] + + SideEffects [None] + +******************************************************************************/ +static int +ddCountInternalMtrNodes( + DdManager * table, + MtrNode * treenode) +{ + MtrNode *auxnode; + int count,nodeCount; + + + nodeCount = 0; + auxnode = treenode; + while (auxnode != NULL) { + if (!(MTR_TEST(auxnode,MTR_TERMINAL))) { + nodeCount++; + count = ddCountInternalMtrNodes(table,auxnode->child); + nodeCount += count; + } + auxnode = auxnode->younger; + } + + return(nodeCount); + +} /* end of ddCountInternalMtrNodes */ +#endif + + +/**Function******************************************************************** + + Synopsis [Reorders the children of a group tree node according to + the options.] + + Description [Reorders the children of a group tree node according to + the options. After reordering puts all the variables in the group + and/or its descendents in a single group. This allows hierarchical + reordering. If the variables in the group do not exist yet, simply + does nothing. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddReorderChildren( + DdManager * table, + MtrNode * treenode, + Cudd_ReorderingType method) +{ + int lower; + int upper; + int result; + unsigned int initialSize; + + ddFindNodeHiLo(table,treenode,&lower,&upper); + /* If upper == -1 these variables do not exist yet. */ + if (upper == -1) + return(1); + + if (treenode->flags == MTR_FIXED) { + result = 1; + } else { +#ifdef DD_STATS + (void) fprintf(table->out," "); +#endif + switch (method) { + case CUDD_REORDER_RANDOM: + case CUDD_REORDER_RANDOM_PIVOT: + result = cuddSwapping(table,lower,upper,method); + break; + case CUDD_REORDER_SIFT: + result = cuddSifting(table,lower,upper); + break; + case CUDD_REORDER_SIFT_CONVERGE: + do { + initialSize = table->keys - table->isolated; + result = cuddSifting(table,lower,upper); + if (initialSize <= table->keys - table->isolated) + break; +#ifdef DD_STATS + else + (void) fprintf(table->out,"\n"); +#endif + } while (result != 0); + break; + case CUDD_REORDER_SYMM_SIFT: + result = cuddSymmSifting(table,lower,upper); + break; + case CUDD_REORDER_SYMM_SIFT_CONV: + result = cuddSymmSiftingConv(table,lower,upper); + break; + case CUDD_REORDER_GROUP_SIFT: + if (table->groupcheck == CUDD_NO_CHECK) { + result = ddGroupSifting(table,lower,upper,ddNoCheck, + DD_NORMAL_SIFT); + } else if (table->groupcheck == CUDD_GROUP_CHECK5) { + result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, + DD_NORMAL_SIFT); + } else if (table->groupcheck == CUDD_GROUP_CHECK7) { + result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, + DD_NORMAL_SIFT); + } else { + (void) fprintf(table->err, + "Unknown group ckecking method\n"); + result = 0; + } + break; + case CUDD_REORDER_GROUP_SIFT_CONV: + do { + initialSize = table->keys - table->isolated; + if (table->groupcheck == CUDD_NO_CHECK) { + result = ddGroupSifting(table,lower,upper,ddNoCheck, + DD_NORMAL_SIFT); + } else if (table->groupcheck == CUDD_GROUP_CHECK5) { + result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, + DD_NORMAL_SIFT); + } else if (table->groupcheck == CUDD_GROUP_CHECK7) { + result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, + DD_NORMAL_SIFT); + } else { + (void) fprintf(table->err, + "Unknown group ckecking method\n"); + result = 0; + } +#ifdef DD_STATS + (void) fprintf(table->out,"\n"); +#endif + result = cuddWindowReorder(table,lower,upper, + CUDD_REORDER_WINDOW4); + if (initialSize <= table->keys - table->isolated) + break; +#ifdef DD_STATS + else + (void) fprintf(table->out,"\n"); +#endif + } while (result != 0); + break; + case CUDD_REORDER_WINDOW2: + case CUDD_REORDER_WINDOW3: + case CUDD_REORDER_WINDOW4: + case CUDD_REORDER_WINDOW2_CONV: + case CUDD_REORDER_WINDOW3_CONV: + case CUDD_REORDER_WINDOW4_CONV: + result = cuddWindowReorder(table,lower,upper,method); + break; + case CUDD_REORDER_ANNEALING: + result = cuddAnnealing(table,lower,upper); + break; + case CUDD_REORDER_GENETIC: + result = cuddGa(table,lower,upper); + break; + case CUDD_REORDER_LINEAR: + result = cuddLinearAndSifting(table,lower,upper); + break; + case CUDD_REORDER_LINEAR_CONVERGE: + do { + initialSize = table->keys - table->isolated; + result = cuddLinearAndSifting(table,lower,upper); + if (initialSize <= table->keys - table->isolated) + break; +#ifdef DD_STATS + else + (void) fprintf(table->out,"\n"); +#endif + } while (result != 0); + break; + case CUDD_REORDER_EXACT: + result = cuddExact(table,lower,upper); + break; + case CUDD_REORDER_LAZY_SIFT: + result = ddGroupSifting(table,lower,upper,ddVarGroupCheck, + DD_LAZY_SIFT); + break; + default: + return(0); + } + } + + /* Create a single group for all the variables that were sifted, + ** so that they will be treated as a single block by successive + ** invocations of ddGroupSifting. + */ + ddMergeGroups(table,treenode,lower,upper); + +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"ddReorderChildren:"); +#endif + + return(result); + +} /* end of ddReorderChildren */ + + +/**Function******************************************************************** + + Synopsis [Finds the lower and upper bounds of the group represented + by treenode.] + + Description [Finds the lower and upper bounds of the group + represented by treenode. From the index and size fields we need to + derive the current positions, and find maximum and minimum.] + + SideEffects [The bounds are returned as side effects.] + + SeeAlso [] + +******************************************************************************/ +static void +ddFindNodeHiLo( + DdManager * table, + MtrNode * treenode, + int * lower, + int * upper) +{ + int low; + int high; + + /* Check whether no variables in this group already exist. + ** If so, return immediately. The calling procedure will know from + ** the values of upper that no reordering is needed. + */ + if ((int) treenode->low >= table->size) { + *lower = table->size; + *upper = -1; + return; + } + + *lower = low = (unsigned int) table->perm[treenode->index]; + high = (int) (low + treenode->size - 1); + + if (high >= table->size) { + /* This is the case of a partially existing group. The aim is to + ** reorder as many variables as safely possible. If the tree + ** node is terminal, we just reorder the subset of the group + ** that is currently in existence. If the group has + ** subgroups, then we only reorder those subgroups that are + ** fully instantiated. This way we avoid breaking up a group. + */ + MtrNode *auxnode = treenode->child; + if (auxnode == NULL) { + *upper = (unsigned int) table->size - 1; + } else { + /* Search the subgroup that strands the table->size line. + ** If the first group starts at 0 and goes past table->size + ** upper will get -1, thus correctly signaling that no reordering + ** should take place. + */ + while (auxnode != NULL) { + int thisLower = table->perm[auxnode->low]; + int thisUpper = thisLower + auxnode->size - 1; + if (thisUpper >= table->size && thisLower < table->size) + *upper = (unsigned int) thisLower - 1; + auxnode = auxnode->younger; + } + } + } else { + /* Normal case: All the variables of the group exist. */ + *upper = (unsigned int) high; + } + +#ifdef DD_DEBUG + /* Make sure that all variables in group are contiguous. */ + assert(treenode->size >= *upper - *lower + 1); +#endif + + return; + +} /* end of ddFindNodeHiLo */ + + +/**Function******************************************************************** + + Synopsis [Comparison function used by qsort.] + + Description [Comparison function used by qsort to order the variables + according to the number of keys in the subtables. Returns the + difference in number of keys between the two variables being + compared.] + + SideEffects [None] + +******************************************************************************/ +static int +ddUniqueCompareGroup( + int * ptrX, + int * ptrY) +{ +#if 0 + if (entry[*ptrY] == entry[*ptrX]) { + return((*ptrX) - (*ptrY)); + } +#endif + return(entry[*ptrY] - entry[*ptrX]); + +} /* end of ddUniqueCompareGroup */ + + +/**Function******************************************************************** + + Synopsis [Sifts from treenode->low to treenode->high.] + + Description [Sifts from treenode->low to treenode->high. If + croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the + end of the initial sifting. If a group is created, it is then sifted + again. After sifting one variable, the group that contains it is + dissolved. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddGroupSifting( + DdManager * table, + int lower, + int upper, + int (*checkFunction)(DdManager *, int, int), + int lazyFlag) +{ + int *var; + int i,j,x,xInit; + int nvars; + int classes; + int result; + int *sifted; + int merged; + int dissolve; +#ifdef DD_STATS + unsigned previousSize; +#endif + int xindex; + + nvars = table->size; + + /* Order variables to sift. */ + entry = NULL; + sifted = NULL; + var = ALLOC(int,nvars); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto ddGroupSiftingOutOfMem; + } + entry = ALLOC(int,nvars); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto ddGroupSiftingOutOfMem; + } + sifted = ALLOC(int,nvars); + if (sifted == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto ddGroupSiftingOutOfMem; + } + + /* Here we consider only one representative for each group. */ + for (i = 0, classes = 0; i < nvars; i++) { + sifted[i] = 0; + x = table->perm[i]; + if ((unsigned) x >= table->subtables[x].next) { + entry[i] = table->subtables[x].keys; + var[classes] = i; + classes++; + } + } + + qsort((void *)var,classes,sizeof(int), + (int (*)(const void *, const void *)) ddUniqueCompareGroup); + + if (lazyFlag) { + for (i = 0; i < nvars; i ++) { + ddResetVarHandled(table, i); + } + } + + /* Now sift. */ + for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { + if (ddTotalNumberSwapping >= table->siftMaxSwap) + break; + xindex = var[i]; + if (sifted[xindex] == 1) /* variable already sifted as part of group */ + continue; + x = table->perm[xindex]; /* find current level of this variable */ + + if (x < lower || x > upper || table->subtables[x].bindVar == 1) + continue; +#ifdef DD_STATS + previousSize = table->keys - table->isolated; +#endif +#ifdef DD_DEBUG + /* x is bottom of group */ + assert((unsigned) x >= table->subtables[x].next); +#endif + if ((unsigned) x == table->subtables[x].next) { + dissolve = 1; + result = ddGroupSiftingAux(table,x,lower,upper,checkFunction, + lazyFlag); + } else { + dissolve = 0; + result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag); + } + if (!result) goto ddGroupSiftingOutOfMem; + + /* check for aggregation */ + merged = 0; + if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) { + x = table->perm[xindex]; /* find current level */ + if ((unsigned) x == table->subtables[x].next) { /* not part of a group */ + if (x != upper && sifted[table->invperm[x+1]] == 0 && + (unsigned) x+1 == table->subtables[x+1].next) { + if (ddSecDiffCheck(table,x,x+1)) { + merged =1; + ddCreateGroup(table,x,x+1); + } + } + if (x != lower && sifted[table->invperm[x-1]] == 0 && + (unsigned) x-1 == table->subtables[x-1].next) { + if (ddSecDiffCheck(table,x-1,x)) { + merged =1; + ddCreateGroup(table,x-1,x); + } + } + } + } + + if (merged) { /* a group was created */ + /* move x to bottom of group */ + while ((unsigned) x < table->subtables[x].next) + x = table->subtables[x].next; + /* sift */ + result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag); + if (!result) goto ddGroupSiftingOutOfMem; +#ifdef DD_STATS + if (table->keys < previousSize + table->isolated) { + (void) fprintf(table->out,"_"); + } else if (table->keys > previousSize + table->isolated) { + (void) fprintf(table->out,"^"); + } else { + (void) fprintf(table->out,"*"); + } + fflush(table->out); + } else { + if (table->keys < previousSize + table->isolated) { + (void) fprintf(table->out,"-"); + } else if (table->keys > previousSize + table->isolated) { + (void) fprintf(table->out,"+"); + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + + /* Mark variables in the group just sifted. */ + x = table->perm[xindex]; + if ((unsigned) x != table->subtables[x].next) { + xInit = x; + do { + j = table->invperm[x]; + sifted[j] = 1; + x = table->subtables[x].next; + } while (x != xInit); + + /* Dissolve the group if it was created. */ + if (lazyFlag == 0 && dissolve) { + do { + j = table->subtables[x].next; + table->subtables[x].next = x; + x = j; + } while (x != xInit); + } + } + +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:"); +#endif + + if (lazyFlag) ddSetVarHandled(table, xindex); + } /* for */ + + FREE(sifted); + FREE(var); + FREE(entry); + + return(1); + +ddGroupSiftingOutOfMem: + if (entry != NULL) FREE(entry); + if (var != NULL) FREE(var); + if (sifted != NULL) FREE(sifted); + + return(0); + +} /* end of ddGroupSifting */ + + +/**Function******************************************************************** + + Synopsis [Creates a group encompassing variables from x to y in the + DD table.] + + Description [Creates a group encompassing variables from x to y in the + DD table. In the current implementation it must be y == x+1. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static void +ddCreateGroup( + DdManager * table, + int x, + int y) +{ + int gybot; + +#ifdef DD_DEBUG + assert(y == x+1); +#endif + + /* Find bottom of second group. */ + gybot = y; + while ((unsigned) gybot < table->subtables[gybot].next) + gybot = table->subtables[gybot].next; + + /* Link groups. */ + table->subtables[x].next = y; + table->subtables[gybot].next = x; + + return; + +} /* ddCreateGroup */ + + +/**Function******************************************************************** + + Synopsis [Sifts one variable up and down until it has taken all + positions. Checks for aggregation.] + + Description [Sifts one variable up and down until it has taken all + positions. Checks for aggregation. There may be at most two sweeps, + even if the group grows. Assumes that x is either an isolated + variable, or it is the bottom of a group. All groups may not have + been found. The variable being moved is returned to the best position + seen during sifting. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddGroupSiftingAux( + DdManager * table, + int x, + int xLow, + int xHigh, + int (*checkFunction)(DdManager *, int, int), + int lazyFlag) +{ + Move *move; + Move *moves; /* list of moves */ + int initialSize; + int result; + int y; + int topbot; + +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out, + "ddGroupSiftingAux from %d to %d\n",xLow,xHigh); + assert((unsigned) x >= table->subtables[x].next); /* x is bottom of group */ +#endif + + initialSize = table->keys - table->isolated; + moves = NULL; + + originalSize = initialSize; /* for lazy sifting */ + + /* If we have a singleton, we check for aggregation in both + ** directions before we sift. + */ + if ((unsigned) x == table->subtables[x].next) { + /* Will go down first, unless x == xHigh: + ** Look for aggregation above x. + */ + for (y = x; y > xLow; y--) { + if (!checkFunction(table,y-1,y)) + break; + topbot = table->subtables[y-1].next; /* find top of y-1's group */ + table->subtables[y-1].next = y; + table->subtables[x].next = topbot; /* x is bottom of group so its */ + /* next is top of y-1's group */ + y = topbot + 1; /* add 1 for y--; new y is top of group */ + } + /* Will go up first unless x == xlow: + ** Look for aggregation below x. + */ + for (y = x; y < xHigh; y++) { + if (!checkFunction(table,y,y+1)) + break; + /* find bottom of y+1's group */ + topbot = y + 1; + while ((unsigned) topbot < table->subtables[topbot].next) { + topbot = table->subtables[topbot].next; + } + table->subtables[topbot].next = table->subtables[y].next; + table->subtables[y].next = y + 1; + y = topbot - 1; /* subtract 1 for y++; new y is bottom of group */ + } + } + + /* Now x may be in the middle of a group. + ** Find bottom of x's group. + */ + while ((unsigned) x < table->subtables[x].next) + x = table->subtables[x].next; + + originalLevel = x; /* for lazy sifting */ + + if (x == xLow) { /* Sift down */ +#ifdef DD_DEBUG + /* x must be a singleton */ + assert((unsigned) x == table->subtables[x].next); +#endif + if (x == xHigh) return(1); /* just one variable */ + + if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) + goto ddGroupSiftingAuxOutOfMem; + /* at this point x == xHigh, unless early term */ + + /* move backward and stop at best position */ + result = ddGroupSiftingBackward(table,moves,initialSize, + DD_SIFT_DOWN,lazyFlag); +#ifdef DD_DEBUG + assert(table->keys - table->isolated <= (unsigned) initialSize); +#endif + if (!result) goto ddGroupSiftingAuxOutOfMem; + + } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ +#ifdef DD_DEBUG + /* x is bottom of group */ + assert((unsigned) x >= table->subtables[x].next); +#endif + /* Find top of x's group */ + x = table->subtables[x].next; + + if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) + goto ddGroupSiftingAuxOutOfMem; + /* at this point x == xLow, unless early term */ + + /* move backward and stop at best position */ + result = ddGroupSiftingBackward(table,moves,initialSize, + DD_SIFT_UP,lazyFlag); +#ifdef DD_DEBUG + assert(table->keys - table->isolated <= (unsigned) initialSize); +#endif + if (!result) goto ddGroupSiftingAuxOutOfMem; + + } else if (x - xLow > xHigh - x) { /* must go down first: shorter */ + if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) + goto ddGroupSiftingAuxOutOfMem; + /* at this point x == xHigh, unless early term */ + + /* Find top of group */ + if (moves) { + x = moves->y; + } + while ((unsigned) x < table->subtables[x].next) + x = table->subtables[x].next; + x = table->subtables[x].next; +#ifdef DD_DEBUG + /* x should be the top of a group */ + assert((unsigned) x <= table->subtables[x].next); +#endif + + if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) + goto ddGroupSiftingAuxOutOfMem; + + /* move backward and stop at best position */ + result = ddGroupSiftingBackward(table,moves,initialSize, + DD_SIFT_UP,lazyFlag); +#ifdef DD_DEBUG + assert(table->keys - table->isolated <= (unsigned) initialSize); +#endif + if (!result) goto ddGroupSiftingAuxOutOfMem; + + } else { /* moving up first: shorter */ + /* Find top of x's group */ + x = table->subtables[x].next; + + if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) + goto ddGroupSiftingAuxOutOfMem; + /* at this point x == xHigh, unless early term */ + + if (moves) { + x = moves->x; + } + while ((unsigned) x < table->subtables[x].next) + x = table->subtables[x].next; +#ifdef DD_DEBUG + /* x is bottom of a group */ + assert((unsigned) x >= table->subtables[x].next); +#endif + + if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) + goto ddGroupSiftingAuxOutOfMem; + + /* move backward and stop at best position */ + result = ddGroupSiftingBackward(table,moves,initialSize, + DD_SIFT_DOWN,lazyFlag); +#ifdef DD_DEBUG + assert(table->keys - table->isolated <= (unsigned) initialSize); +#endif + if (!result) goto ddGroupSiftingAuxOutOfMem; + } + + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + + return(1); + +ddGroupSiftingAuxOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + + return(0); + +} /* end of ddGroupSiftingAux */ + + +/**Function******************************************************************** + + Synopsis [Sifts up a variable until either it reaches position xLow + or the size of the DD heap increases too much.] + + Description [Sifts up a variable until either it reaches position + xLow or the size of the DD heap increases too much. Assumes that y is + the top of a group (or a singleton). Checks y for aggregation to the + adjacent variables. Records all the moves that are appended to the + list of moves received as input and returned as a side effect. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddGroupSiftingUp( + DdManager * table, + int y, + int xLow, + int (*checkFunction)(DdManager *, int, int), + Move ** moves) +{ + Move *move; + int x; + int size; + int i; + int gxtop,gybot; + int limitSize; + int xindex, yindex; + int zindex; + int z; + int isolated; + int L; /* lower bound on DD size */ +#ifdef DD_DEBUG + int checkL; +#endif + + yindex = table->invperm[y]; + + /* Initialize the lower bound. + ** The part of the DD below the bottom of y's group will not change. + ** The part of the DD above y that does not interact with any + ** variable of y's group will not change. + ** The rest may vanish in the best case, except for + ** the nodes at level xLow, which will not vanish, regardless. + ** What we use here is not really a lower bound, because we ignore + ** the interactions with all variables except y. + */ + limitSize = L = table->keys - table->isolated; + gybot = y; + while ((unsigned) gybot < table->subtables[gybot].next) + gybot = table->subtables[gybot].next; + for (z = xLow + 1; z <= gybot; z++) { + zindex = table->invperm[z]; + if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { + isolated = table->vars[zindex]->ref == 1; + L -= table->subtables[z].keys - isolated; + } + } + + originalLevel = y; /* for lazy sifting */ + + x = cuddNextLow(table,y); + while (x >= xLow && L <= limitSize) { +#ifdef DD_DEBUG + gybot = y; + while ((unsigned) gybot < table->subtables[gybot].next) + gybot = table->subtables[gybot].next; + checkL = table->keys - table->isolated; + for (z = xLow + 1; z <= gybot; z++) { + zindex = table->invperm[z]; + if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { + isolated = table->vars[zindex]->ref == 1; + checkL -= table->subtables[z].keys - isolated; + } + } + if (pr > 0 && L != checkL) { + (void) fprintf(table->out, + "Inaccurate lower bound: L = %d checkL = %d\n", + L, checkL); + } +#endif + gxtop = table->subtables[x].next; + if (checkFunction(table,x,y)) { + /* Group found, attach groups */ + table->subtables[x].next = y; + i = table->subtables[y].next; + while (table->subtables[i].next != (unsigned) y) + i = table->subtables[i].next; + table->subtables[i].next = gxtop; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddGroupSiftingUpOutOfMem; + move->x = x; + move->y = y; + move->flags = MTR_NEWNODE; + move->size = table->keys - table->isolated; + move->next = *moves; + *moves = move; + } else if (table->subtables[x].next == (unsigned) x && + table->subtables[y].next == (unsigned) y) { + /* x and y are self groups */ + xindex = table->invperm[x]; + size = cuddSwapInPlace(table,x,y); +#ifdef DD_DEBUG + assert(table->subtables[x].next == (unsigned) x); + assert(table->subtables[y].next == (unsigned) y); +#endif + if (size == 0) goto ddGroupSiftingUpOutOfMem; + /* Update the lower bound. */ + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[xindex]->ref == 1; + L += table->subtables[y].keys - isolated; + } + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddGroupSiftingUpOutOfMem; + move->x = x; + move->y = y; + move->flags = MTR_DEFAULT; + move->size = size; + move->next = *moves; + *moves = move; + +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out, + "ddGroupSiftingUp (2 single groups):\n"); +#endif + if ((double) size > (double) limitSize * table->maxGrowth) + return(1); + if (size < limitSize) limitSize = size; + } else { /* Group move */ + size = ddGroupMove(table,x,y,moves); + if (size == 0) goto ddGroupSiftingUpOutOfMem; + /* Update the lower bound. */ + z = (*moves)->y; + do { + zindex = table->invperm[z]; + if (cuddTestInteract(table,zindex,yindex)) { + isolated = table->vars[zindex]->ref == 1; + L += table->subtables[z].keys - isolated; + } + z = table->subtables[z].next; + } while (z != (int) (*moves)->y); + if ((double) size > (double) limitSize * table->maxGrowth) + return(1); + if (size < limitSize) limitSize = size; + } + y = gxtop; + x = cuddNextLow(table,y); + } + + return(1); + +ddGroupSiftingUpOutOfMem: + while (*moves != NULL) { + move = (*moves)->next; + cuddDeallocNode(table, (DdNode *) *moves); + *moves = move; + } + return(0); + +} /* end of ddGroupSiftingUp */ + + +/**Function******************************************************************** + + Synopsis [Sifts down a variable until it reaches position xHigh.] + + Description [Sifts down a variable until it reaches position xHigh. + Assumes that x is the bottom of a group (or a singleton). Records + all the moves. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddGroupSiftingDown( + DdManager * table, + int x, + int xHigh, + int (*checkFunction)(DdManager *, int, int), + Move ** moves) +{ + Move *move; + int y; + int size; + int limitSize; + int gxtop,gybot; + int R; /* upper bound on node decrease */ + int xindex, yindex; + int isolated, allVars; + int z; + int zindex; +#ifdef DD_DEBUG + int checkR; +#endif + + /* If the group consists of simple variables, there is no point in + ** sifting it down. This check is redundant if the projection functions + ** do not have external references, because the computation of the + ** lower bound takes care of the problem. It is necessary otherwise to + ** prevent the sifting down of simple variables. */ + y = x; + allVars = 1; + do { + if (table->subtables[y].keys != 1) { + allVars = 0; + break; + } + y = table->subtables[y].next; + } while (table->subtables[y].next != (unsigned) x); + if (allVars) + return(1); + + /* Initialize R. */ + xindex = table->invperm[x]; + gxtop = table->subtables[x].next; + limitSize = size = table->keys - table->isolated; + R = 0; + for (z = xHigh; z > gxtop; z--) { + zindex = table->invperm[z]; + if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { + isolated = table->vars[zindex]->ref == 1; + R += table->subtables[z].keys - isolated; + } + } + + originalLevel = x; /* for lazy sifting */ + + y = cuddNextHigh(table,x); + while (y <= xHigh && size - R < limitSize) { +#ifdef DD_DEBUG + gxtop = table->subtables[x].next; + checkR = 0; + for (z = xHigh; z > gxtop; z--) { + zindex = table->invperm[z]; + if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { + isolated = table->vars[zindex]->ref == 1; + checkR += table->subtables[z].keys - isolated; + } + } + assert(R >= checkR); +#endif + /* Find bottom of y group. */ + gybot = table->subtables[y].next; + while (table->subtables[gybot].next != (unsigned) y) + gybot = table->subtables[gybot].next; + + if (checkFunction(table,x,y)) { + /* Group found: attach groups and record move. */ + gxtop = table->subtables[x].next; + table->subtables[x].next = y; + table->subtables[gybot].next = gxtop; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto ddGroupSiftingDownOutOfMem; + move->x = x; + move->y = y; + move->flags = MTR_NEWNODE; + move->size = table->keys - table->isolated; + move->next = *moves; + *moves = move; + } else if (table->subtables[x].next == (unsigned) x && + table->subtables[y].next == (unsigned) y) { + /* x and y are self groups */ + /* Update upper bound on node decrease. */ + yindex = table->invperm[y]; + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[yindex]->ref == 1; + R -= table->subtables[y].keys - isolated; + } + size = cuddSwapInPlace(table,x,y); +#ifdef DD_DEBUG + assert(table->subtables[x].next == (unsigned) x); + assert(table->subtables[y].next == (unsigned) y); +#endif + if (size == 0) goto ddGroupSiftingDownOutOfMem; + + /* Record move. */ + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddGroupSiftingDownOutOfMem; + move->x = x; + move->y = y; + move->flags = MTR_DEFAULT; + move->size = size; + move->next = *moves; + *moves = move; + +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out, + "ddGroupSiftingDown (2 single groups):\n"); +#endif + if ((double) size > (double) limitSize * table->maxGrowth) + return(1); + if (size < limitSize) limitSize = size; + + x = y; + y = cuddNextHigh(table,x); + } else { /* Group move */ + /* Update upper bound on node decrease: first phase. */ + gxtop = table->subtables[x].next; + z = gxtop + 1; + do { + zindex = table->invperm[z]; + if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { + isolated = table->vars[zindex]->ref == 1; + R -= table->subtables[z].keys - isolated; + } + z++; + } while (z <= gybot); + size = ddGroupMove(table,x,y,moves); + if (size == 0) goto ddGroupSiftingDownOutOfMem; + if ((double) size > (double) limitSize * table->maxGrowth) + return(1); + if (size < limitSize) limitSize = size; + + /* Update upper bound on node decrease: second phase. */ + gxtop = table->subtables[gybot].next; + for (z = gxtop + 1; z <= gybot; z++) { + zindex = table->invperm[z]; + if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { + isolated = table->vars[zindex]->ref == 1; + R += table->subtables[z].keys - isolated; + } + } + } + x = gybot; + y = cuddNextHigh(table,x); + } + + return(1); + +ddGroupSiftingDownOutOfMem: + while (*moves != NULL) { + move = (*moves)->next; + cuddDeallocNode(table, (DdNode *) *moves); + *moves = move; + } + + return(0); + +} /* end of ddGroupSiftingDown */ + + +/**Function******************************************************************** + + Synopsis [Swaps two groups and records the move.] + + Description [Swaps two groups and records the move. Returns the + number of keys in the DD table in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddGroupMove( + DdManager * table, + int x, + int y, + Move ** moves) +{ + Move *move; + int size; + int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; + int swapx,swapy; +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + int initialSize,bestSize; +#endif + +#if DD_DEBUG + /* We assume that x < y */ + assert(x < y); +#endif + /* Find top, bottom, and size for the two groups. */ + xbot = x; + xtop = table->subtables[x].next; + xsize = xbot - xtop + 1; + ybot = y; + while ((unsigned) ybot < table->subtables[ybot].next) + ybot = table->subtables[ybot].next; + ytop = y; + ysize = ybot - ytop + 1; + +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + initialSize = bestSize = table->keys - table->isolated; +#endif + /* Sift the variables of the second group up through the first group */ + for (i = 1; i <= ysize; i++) { + for (j = 1; j <= xsize; j++) { + size = cuddSwapInPlace(table,x,y); + if (size == 0) goto ddGroupMoveOutOfMem; +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + if (size < bestSize) + bestSize = size; +#endif + swapx = x; swapy = y; + y = x; + x = cuddNextLow(table,y); + } + y = ytop + i; + x = cuddNextLow(table,y); + } +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + if ((bestSize < initialSize) && (bestSize < size)) + (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size); +#endif + + /* fix groups */ + y = xtop; /* ytop is now where xtop used to be */ + for (i = 0; i < ysize - 1; i++) { + table->subtables[y].next = cuddNextHigh(table,y); + y = cuddNextHigh(table,y); + } + table->subtables[y].next = xtop; /* y is bottom of its group, join */ + /* it to top of its group */ + x = cuddNextHigh(table,y); + newxtop = x; + for (i = 0; i < xsize - 1; i++) { + table->subtables[x].next = cuddNextHigh(table,x); + x = cuddNextHigh(table,x); + } + table->subtables[x].next = newxtop; /* x is bottom of its group, join */ + /* it to top of its group */ +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"ddGroupMove:\n"); +#endif + + /* Store group move */ + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddGroupMoveOutOfMem; + move->x = swapx; + move->y = swapy; + move->flags = MTR_DEFAULT; + move->size = table->keys - table->isolated; + move->next = *moves; + *moves = move; + + return(table->keys - table->isolated); + +ddGroupMoveOutOfMem: + while (*moves != NULL) { + move = (*moves)->next; + cuddDeallocNode(table, (DdNode *) *moves); + *moves = move; + } + return(0); + +} /* end of ddGroupMove */ + + +/**Function******************************************************************** + + Synopsis [Undoes the swap two groups.] + + Description [Undoes the swap two groups. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddGroupMoveBackward( + DdManager * table, + int x, + int y) +{ + int size; + int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; + + +#if DD_DEBUG + /* We assume that x < y */ + assert(x < y); +#endif + + /* Find top, bottom, and size for the two groups. */ + xbot = x; + xtop = table->subtables[x].next; + xsize = xbot - xtop + 1; + ybot = y; + while ((unsigned) ybot < table->subtables[ybot].next) + ybot = table->subtables[ybot].next; + ytop = y; + ysize = ybot - ytop + 1; + + /* Sift the variables of the second group up through the first group */ + for (i = 1; i <= ysize; i++) { + for (j = 1; j <= xsize; j++) { + size = cuddSwapInPlace(table,x,y); + if (size == 0) + return(0); + y = x; + x = cuddNextLow(table,y); + } + y = ytop + i; + x = cuddNextLow(table,y); + } + + /* fix groups */ + y = xtop; + for (i = 0; i < ysize - 1; i++) { + table->subtables[y].next = cuddNextHigh(table,y); + y = cuddNextHigh(table,y); + } + table->subtables[y].next = xtop; /* y is bottom of its group, join */ + /* to its top */ + x = cuddNextHigh(table,y); + newxtop = x; + for (i = 0; i < xsize - 1; i++) { + table->subtables[x].next = cuddNextHigh(table,x); + x = cuddNextHigh(table,x); + } + table->subtables[x].next = newxtop; /* x is bottom of its group, join */ + /* to its top */ +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"ddGroupMoveBackward:\n"); +#endif + + return(1); + +} /* end of ddGroupMoveBackward */ + + +/**Function******************************************************************** + + Synopsis [Determines the best position for a variables and returns + it there.] + + Description [Determines the best position for a variables and returns + it there. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddGroupSiftingBackward( + DdManager * table, + Move * moves, + int size, + int upFlag, + int lazyFlag) +{ + Move *move; + int res; + Move *end_move; + int diff, tmp_diff; + int index, pairlev; + + if (lazyFlag) { + end_move = NULL; + + /* Find the minimum size, and the earliest position at which it + ** was achieved. */ + for (move = moves; move != NULL; move = move->next) { + if (move->size < size) { + size = move->size; + end_move = move; + } else if (move->size == size) { + if (end_move == NULL) end_move = move; + } + } + + /* Find among the moves that give minimum size the one that + ** minimizes the distance from the corresponding variable. */ + if (moves != NULL) { + diff = Cudd_ReadSize(table) + 1; + index = (upFlag == 1) ? + table->invperm[moves->x] : table->invperm[moves->y]; + pairlev = table->perm[Cudd_bddReadPairIndex(table, index)]; + + for (move = moves; move != NULL; move = move->next) { + if (move->size == size) { + if (upFlag == 1) { + tmp_diff = (move->x > pairlev) ? + move->x - pairlev : pairlev - move->x; + } else { + tmp_diff = (move->y > pairlev) ? + move->y - pairlev : pairlev - move->y; + } + if (tmp_diff < diff) { + diff = tmp_diff; + end_move = move; + } + } + } + } + } else { + /* Find the minimum size. */ + for (move = moves; move != NULL; move = move->next) { + if (move->size < size) { + size = move->size; + } + } + } + + /* In case of lazy sifting, end_move identifies the position at + ** which we want to stop. Otherwise, we stop as soon as we meet + ** the minimum size. */ + for (move = moves; move != NULL; move = move->next) { + if (lazyFlag) { + if (move == end_move) return(1); + } else { + if (move->size == size) return(1); + } + if ((table->subtables[move->x].next == move->x) && + (table->subtables[move->y].next == move->y)) { + res = cuddSwapInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n"); + assert(table->subtables[move->x].next == move->x); + assert(table->subtables[move->y].next == move->y); +#endif + } else { /* Group move necessary */ + if (move->flags == MTR_NEWNODE) { + ddDissolveGroup(table,(int)move->x,(int)move->y); + } else { + res = ddGroupMoveBackward(table,(int)move->x,(int)move->y); + if (!res) return(0); + } + } + + } + + return(1); + +} /* end of ddGroupSiftingBackward */ + + +/**Function******************************************************************** + + Synopsis [Merges groups in the DD table.] + + Description [Creates a single group from low to high and adjusts the + index field of the tree node.] + + SideEffects [None] + +******************************************************************************/ +static void +ddMergeGroups( + DdManager * table, + MtrNode * treenode, + int low, + int high) +{ + int i; + MtrNode *auxnode; + int saveindex; + int newindex; + + /* Merge all variables from low to high in one group, unless + ** this is the topmost group. In such a case we do not merge lest + ** we lose the symmetry information. */ + if (treenode != table->tree) { + for (i = low; i < high; i++) + table->subtables[i].next = i+1; + table->subtables[high].next = low; + } + + /* Adjust the index fields of the tree nodes. If a node is the + ** first child of its parent, then the parent may also need adjustment. */ + saveindex = treenode->index; + newindex = table->invperm[low]; + auxnode = treenode; + do { + auxnode->index = newindex; + if (auxnode->parent == NULL || + (int) auxnode->parent->index != saveindex) + break; + auxnode = auxnode->parent; + } while (1); + return; + +} /* end of ddMergeGroups */ + + +/**Function******************************************************************** + + Synopsis [Dissolves a group in the DD table.] + + Description [x and y are variables in a group to be cut in two. The cut + is to pass between x and y.] + + SideEffects [None] + +******************************************************************************/ +static void +ddDissolveGroup( + DdManager * table, + int x, + int y) +{ + int topx; + int boty; + + /* find top and bottom of the two groups */ + boty = y; + while ((unsigned) boty < table->subtables[boty].next) + boty = table->subtables[boty].next; + + topx = table->subtables[boty].next; + + table->subtables[boty].next = y; + table->subtables[x].next = topx; + + return; + +} /* end of ddDissolveGroup */ + + +/**Function******************************************************************** + + Synopsis [Pretends to check two variables for aggregation.] + + Description [Pretends to check two variables for aggregation. Always + returns 0.] + + SideEffects [None] + +******************************************************************************/ +static int +ddNoCheck( + DdManager * table, + int x, + int y) +{ + return(0); + +} /* end of ddNoCheck */ + + +/**Function******************************************************************** + + Synopsis [Checks two variables for aggregation.] + + Description [Checks two variables for aggregation. The check is based + on the second difference of the number of nodes as a function of the + layer. If the second difference is lower than a given threshold + (typically negative) then the two variables should be aggregated. + Returns 1 if the two variables pass the test; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddSecDiffCheck( + DdManager * table, + int x, + int y) +{ + double Nx,Nx_1; + double Sx; + double threshold; + int xindex,yindex; + + if (x==0) return(0); + +#ifdef DD_STATS + secdiffcalls++; +#endif + Nx = (double) table->subtables[x].keys; + Nx_1 = (double) table->subtables[x-1].keys; + Sx = (table->subtables[y].keys/Nx) - (Nx/Nx_1); + + threshold = table->recomb / 100.0; + if (Sx < threshold) { + xindex = table->invperm[x]; + yindex = table->invperm[y]; + if (cuddTestInteract(table,xindex,yindex)) { +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + (void) fprintf(table->out, + "Second difference for %d = %g Pos(%d)\n", + table->invperm[x],Sx,x); +#endif +#ifdef DD_STATS + secdiff++; +#endif + return(1); + } else { +#ifdef DD_STATS + secdiffmisfire++; +#endif + return(0); + } + + } + return(0); + +} /* end of ddSecDiffCheck */ + + +/**Function******************************************************************** + + Synopsis [Checks for extended symmetry of x and y.] + + Description [Checks for extended symmetry of x and y. Returns 1 in + case of extended symmetry; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddExtSymmCheck( + DdManager * table, + int x, + int y) +{ + DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10; + DdNode *one; + int comple; /* f0 is complemented */ + int notproj; /* f is not a projection function */ + int arccount; /* number of arcs from layer x to layer y */ + int TotalRefCount; /* total reference count of layer y minus 1 */ + int counter; /* number of nodes of layer x that are allowed */ + /* to violate extended symmetry conditions */ + int arccounter; /* number of arcs into layer y that are allowed */ + /* to come from layers other than x */ + int i; + int xindex; + int yindex; + int res; + int slots; + DdNodePtr *list; + DdNode *sentinel = &(table->sentinel); + + xindex = table->invperm[x]; + yindex = table->invperm[y]; + + /* If the two variables do not interact, we do not want to merge them. */ + if (!cuddTestInteract(table,xindex,yindex)) + return(0); + +#ifdef DD_DEBUG + /* Checks that x and y do not contain just the projection functions. + ** With the test on interaction, these test become redundant, + ** because an isolated projection function does not interact with + ** any other variable. + */ + if (table->subtables[x].keys == 1) { + assert(table->vars[xindex]->ref != 1); + } + if (table->subtables[y].keys == 1) { + assert(table->vars[yindex]->ref != 1); + } +#endif + +#ifdef DD_STATS + extsymmcalls++; +#endif + + arccount = 0; + counter = (int) (table->subtables[x].keys * + (table->symmviolation/100.0) + 0.5); + one = DD_ONE(table); + + slots = table->subtables[x].slots; + list = table->subtables[x].nodelist; + for (i = 0; i < slots; i++) { + f = list[i]; + while (f != sentinel) { + /* Find f1, f0, f11, f10, f01, f00. */ + f1 = cuddT(f); + f0 = Cudd_Regular(cuddE(f)); + comple = Cudd_IsComplement(cuddE(f)); + notproj = f1 != one || f0 != one || f->ref != (DdHalfWord) 1; + if (f1->index == yindex) { + arccount++; + f11 = cuddT(f1); f10 = cuddE(f1); + } else { + if ((int) f0->index != yindex) { + /* If f is an isolated projection function it is + ** allowed to bypass layer y. + */ + if (notproj) { + if (counter == 0) + return(0); + counter--; /* f bypasses layer y */ + } + } + f11 = f10 = f1; + } + if ((int) f0->index == yindex) { + arccount++; + f01 = cuddT(f0); f00 = cuddE(f0); + } else { + f01 = f00 = f0; + } + if (comple) { + f01 = Cudd_Not(f01); + f00 = Cudd_Not(f00); + } + + /* Unless we are looking at a projection function + ** without external references except the one from the + ** table, we insist that f01 == f10 or f11 == f00 + */ + if (notproj) { + if (f01 != f10 && f11 != f00) { + if (counter == 0) + return(0); + counter--; + } + } + + f = f->next; + } /* while */ + } /* for */ + + /* Calculate the total reference counts of y */ + TotalRefCount = -1; /* -1 for projection function */ + slots = table->subtables[y].slots; + list = table->subtables[y].nodelist; + for (i = 0; i < slots; i++) { + f = list[i]; + while (f != sentinel) { + TotalRefCount += f->ref; + f = f->next; + } + } + + arccounter = (int) (table->subtables[y].keys * + (table->arcviolation/100.0) + 0.5); + res = arccount >= TotalRefCount - arccounter; + +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + if (res) { + (void) fprintf(table->out, + "Found extended symmetry! x = %d\ty = %d\tPos(%d,%d)\n", + xindex,yindex,x,y); + } +#endif + +#ifdef DD_STATS + if (res) + extsymm++; +#endif + return(res); + +} /* end ddExtSymmCheck */ + + +/**Function******************************************************************** + + Synopsis [Checks for grouping of x and y.] + + Description [Checks for grouping of x and y. Returns 1 in + case of grouping; 0 otherwise. This function is used for lazy sifting.] + + SideEffects [None] + +******************************************************************************/ +static int +ddVarGroupCheck( + DdManager * table, + int x, + int y) +{ + int xindex = table->invperm[x]; + int yindex = table->invperm[y]; + + if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0); + + if (Cudd_bddReadPairIndex(table, xindex) == yindex) { + if (ddIsVarHandled(table, xindex) || + ddIsVarHandled(table, yindex)) { + if (Cudd_bddIsVarToBeGrouped(table, xindex) || + Cudd_bddIsVarToBeGrouped(table, yindex) ) { + if (table->keys - table->isolated <= originalSize) { + return(1); + } + } + } + } + + return(0); + +} /* end of ddVarGroupCheck */ + + +/**Function******************************************************************** + + Synopsis [Sets a variable to already handled.] + + Description [Sets a variable to already handled. This function is used + for lazy sifting.] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +static int +ddSetVarHandled( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return(0); + dd->subtables[dd->perm[index]].varHandled = 1; + return(1); + +} /* end of ddSetVarHandled */ + + +/**Function******************************************************************** + + Synopsis [Resets a variable to be processed.] + + Description [Resets a variable to be processed. This function is used + for lazy sifting.] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +static int +ddResetVarHandled( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return(0); + dd->subtables[dd->perm[index]].varHandled = 0; + return(1); + +} /* end of ddResetVarHandled */ + + +/**Function******************************************************************** + + Synopsis [Checks whether a variables is already handled.] + + Description [Checks whether a variables is already handled. This + function is used for lazy sifting.] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +static int +ddIsVarHandled( + DdManager *dd, + int index) +{ + if (index >= dd->size || index < 0) return(-1); + return dd->subtables[dd->perm[index]].varHandled; + +} /* end of ddIsVarHandled */ diff --git a/abc70930/src/bdd/cudd/cuddHarwell.c b/abc70930/src/bdd/cudd/cuddHarwell.c new file mode 100644 index 00000000..063f1922 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddHarwell.c @@ -0,0 +1,541 @@ +/**CFile*********************************************************************** + + FileName [cuddHarwell.c] + + PackageName [cudd] + + Synopsis [Function to read a matrix in Harwell format.] + + Description [External procedures included in this module: +
        +
      • Cudd_addHarwell() +
      + ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddHarwell.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Reads in a matrix in the format of the Harwell-Boeing + benchmark suite.] + + Description [Reads in a matrix in the format of the Harwell-Boeing + benchmark suite. The variables are ordered as follows: +
      + x\[0\] y\[0\] x\[1\] y\[1\] ... +
      + 0 is the most significant bit. On input, nx and ny hold the numbers + of row and column variables already in existence. On output, they + hold the numbers of row and column variables actually used by the + matrix. m and n are set to the numbers of rows and columns of the + matrix. Their values on input are immaterial. Returns 1 on + success; 0 otherwise. The ADD for the sparse matrix is returned in + E, and its reference count is > 0.] + + SideEffects [None] + + SeeAlso [Cudd_addRead Cudd_bddRead] + +******************************************************************************/ +int +Cudd_addHarwell( + FILE * fp /* pointer to the input file */, + DdManager * dd /* DD manager */, + DdNode ** E /* characteristic function of the graph */, + DdNode *** x /* array of row variables */, + DdNode *** y /* array of column variables */, + DdNode *** xn /* array of complemented row variables */, + DdNode *** yn_ /* array of complemented column variables */, + int * nx /* number or row variables */, + int * ny /* number or column variables */, + int * m /* number of rows */, + int * n /* number of columns */, + int bx /* first index of row variables */, + int sx /* step of row variables */, + int by /* first index of column variables */, + int sy /* step of column variables */, + int pr /* verbosity level */) +{ + DdNode *one, *zero; + DdNode *w; + DdNode *cubex, *cubey, *minterm1; + int u, v, err, i, j, nv; + double val; + DdNode **lx, **ly, **lxn, **lyn; /* local copies of x, y, xn, yn_ */ + int lnx, lny; /* local copies of nx and ny */ + char title[73], key[9], mxtype[4], rhstyp[4]; + int totcrd, ptrcrd, indcrd, valcrd, rhscrd, + nrow, ncol, nnzero, neltvl, + nrhs, nrhsix; + int *colptr, *rowind; +#if 0 + int nguess, nexact; + int *rhsptr, *rhsind; +#endif + + if (*nx < 0 || *ny < 0) return(0); + + one = DD_ONE(dd); + zero = DD_ZERO(dd); + + /* Read the header */ + err = fscanf(fp, "%72c %8c", title, key); + if (err == EOF) { + return(0); + } else if (err != 2) { + return(0); + } + title[72] = (char) 0; + key[8] = (char) 0; + + err = fscanf(fp, "%d %d %d %d %d", &totcrd, &ptrcrd, &indcrd, + &valcrd, &rhscrd); + if (err == EOF) { + return(0); + } else if (err != 5) { + return(0); + } + + err = fscanf(fp, "%3s %d %d %d %d", mxtype, &nrow, &ncol, + &nnzero, &neltvl); + if (err == EOF) { + return(0); + } else if (err != 5) { + return(0); + } + + /* Skip FORTRAN formats */ + if (rhscrd == 0) { + err = fscanf(fp, "%*s %*s %*s \n"); + } else { + err = fscanf(fp, "%*s %*s %*s %*s \n"); + } + if (err == EOF) { + return(0); + } else if (err != 0) { + return(0); + } + + /* Print out some stuff if requested to be verbose */ + if (pr>0) { + (void) fprintf(dd->out,"%s: type %s, %d rows, %d columns, %d entries\n", key, + mxtype, nrow, ncol, nnzero); + if (pr>1) (void) fprintf(dd->out,"%s\n", title); + } + + /* Check matrix type */ + if (mxtype[0] != 'R' || mxtype[1] != 'U' || mxtype[2] != 'A') { + (void) fprintf(dd->err,"%s: Illegal matrix type: %s\n", + key, mxtype); + return(0); + } + if (neltvl != 0) return(0); + + /* Read optional 5-th line */ + if (rhscrd != 0) { + err = fscanf(fp, "%3c %d %d", rhstyp, &nrhs, &nrhsix); + if (err == EOF) { + return(0); + } else if (err != 3) { + return(0); + } + rhstyp[3] = (char) 0; + if (rhstyp[0] != 'F') { + (void) fprintf(dd->err, + "%s: Sparse right-hand side not yet supported\n", key); + return(0); + } + if (pr>0) (void) fprintf(dd->out,"%d right-hand side(s)\n", nrhs); + } else { + nrhs = 0; + } + + /* Compute the number of variables */ + + /* row and column numbers start from 0 */ + u = nrow - 1; + for (i=0; u > 0; i++) { + u >>= 1; + } + lnx = i; + if (nrhs == 0) { + v = ncol - 1; + } else { + v = 2* (ddMax(ncol, nrhs) - 1); + } + for (i=0; v > 0; i++) { + v >>= 1; + } + lny = i; + + /* Allocate or reallocate arrays for variables as needed */ + if (*nx == 0) { + if (lnx > 0) { + *x = lx = ALLOC(DdNode *,lnx); + if (lx == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *xn = lxn = ALLOC(DdNode *,lnx); + if (lxn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } else { + *x = *xn = NULL; + } + } else if (lnx > *nx) { + *x = lx = REALLOC(DdNode *, *x, lnx); + if (lx == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *xn = lxn = REALLOC(DdNode *, *xn, lnx); + if (lxn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } else { + lx = *x; + lxn = *xn; + } + if (*ny == 0) { + if (lny >0) { + *y = ly = ALLOC(DdNode *,lny); + if (ly == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *yn_ = lyn = ALLOC(DdNode *,lny); + if (lyn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } else { + *y = *yn_ = NULL; + } + } else if (lny > *ny) { + *y = ly = REALLOC(DdNode *, *y, lny); + if (ly == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *yn_ = lyn = REALLOC(DdNode *, *yn_, lny); + if (lyn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } else { + ly = *y; + lyn = *yn_; + } + + /* Create new variables as needed */ + for (i= *nx,nv=bx+(*nx)*sx; i < lnx; i++,nv+=sx) { + do { + dd->reordered = 0; + lx[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (lx[i] == NULL) return(0); + cuddRef(lx[i]); + do { + dd->reordered = 0; + lxn[i] = cuddUniqueInter(dd, nv, zero, one); + } while (dd->reordered == 1); + if (lxn[i] == NULL) return(0); + cuddRef(lxn[i]); + } + for (i= *ny,nv=by+(*ny)*sy; i < lny; i++,nv+=sy) { + do { + dd->reordered = 0; + ly[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (ly[i] == NULL) return(0); + cuddRef(ly[i]); + do { + dd->reordered = 0; + lyn[i] = cuddUniqueInter(dd, nv, zero, one); + } while (dd->reordered == 1); + if (lyn[i] == NULL) return(0); + cuddRef(lyn[i]); + } + + /* Update matrix parameters */ + *nx = lnx; + *ny = lny; + *m = nrow; + if (nrhs == 0) { + *n = ncol; + } else { + *n = (1 << (lny - 1)) + nrhs; + } + + /* Read structure data */ + colptr = ALLOC(int, ncol+1); + if (colptr == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + rowind = ALLOC(int, nnzero); + if (rowind == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + + for (i=0; ierr,"%s: Unexpected colptr[0] (%d)\n", + key,colptr[0]); + FREE(colptr); + FREE(rowind); + return(0); + } + for (i=0; i=0; nv--) { + if (v & 1) { + w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]); + } else { + w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, cubey); + FREE(colptr); + FREE(rowind); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, cubey); + cubey = w; + v >>= 1; + } + for (i=colptr[j]; i=0; nv--) { + if (u & 1) { + w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]); + } else { + w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, cubey); + Cudd_RecursiveDeref(dd, cubex); + FREE(colptr); + FREE(rowind); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, cubex); + cubex = w; + u >>= 1; + } + minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex); + if (minterm1 == NULL) { + Cudd_RecursiveDeref(dd, cubey); + Cudd_RecursiveDeref(dd, cubex); + FREE(colptr); + FREE(rowind); + return(0); + } + cuddRef(minterm1); + Cudd_RecursiveDeref(dd, cubex); + w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1); + if (w == NULL) { + Cudd_RecursiveDeref(dd, cubey); + FREE(colptr); + FREE(rowind); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + Cudd_RecursiveDeref(dd, *E); + *E = w; + } + Cudd_RecursiveDeref(dd, cubey); + } + FREE(colptr); + FREE(rowind); + + /* Read right-hand sides */ + for (j=0; j=0; nv--) { + if (v & 1) { + w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]); + } else { + w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, cubey); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, cubey); + cubey = w; + v >>= 1; + } + for (i=0; i=0; nv--) { + if (u & 1) { + w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]); + } else { + w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, cubey); + Cudd_RecursiveDeref(dd, cubex); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, cubex); + cubex = w; + u >>= 1; + } + minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex); + if (minterm1 == NULL) { + Cudd_RecursiveDeref(dd, cubey); + Cudd_RecursiveDeref(dd, cubex); + return(0); + } + cuddRef(minterm1); + Cudd_RecursiveDeref(dd, cubex); + w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1); + if (w == NULL) { + Cudd_RecursiveDeref(dd, cubey); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + Cudd_RecursiveDeref(dd, *E); + *E = w; + } + Cudd_RecursiveDeref(dd, cubey); + } + + return(1); + +} /* end of Cudd_addHarwell */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/cudd/cuddInit.c b/abc70930/src/bdd/cudd/cuddInit.c new file mode 100644 index 00000000..8e06a425 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddInit.c @@ -0,0 +1,283 @@ +/**CFile*********************************************************************** + + FileName [cuddInit.c] + + PackageName [cudd] + + Synopsis [Functions to initialize and shut down the DD manager.] + + Description [External procedures included in this module: +
        +
      • Cudd_Init() +
      • Cudd_Quit() +
      + Internal procedures included in this module: +
        +
      • cuddZddInitUniv() +
      • cuddZddFreeUniv() +
      + ] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#define CUDD_MAIN +#include "cuddInt.h" +#undef CUDD_MAIN + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddInit.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Creates a new DD manager.] + + Description [Creates a new DD manager, initializes the table, the + basic constants and the projection functions. If maxMemory is 0, + Cudd_Init decides suitable values for the maximum size of the cache + and for the limit for fast unique table growth based on the available + memory. Returns a pointer to the manager if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_Quit] + +******************************************************************************/ +DdManager * +Cudd_Init( + unsigned int numVars /* initial number of BDD variables (i.e., subtables) */, + unsigned int numVarsZ /* initial number of ZDD variables (i.e., subtables) */, + unsigned int numSlots /* initial size of the unique tables */, + unsigned int cacheSize /* initial size of the cache */, + unsigned long maxMemory /* target maximum memory occupation */) +{ + DdManager *unique; + int i,result; + DdNode *one, *zero; + unsigned int maxCacheSize; + unsigned int looseUpTo; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); + + if (maxMemory == 0) { + maxMemory = getSoftDataLimit(); + } + looseUpTo = (unsigned int) ((maxMemory / sizeof(DdNode)) / + DD_MAX_LOOSE_FRACTION); + unique = cuddInitTable(numVars,numVarsZ,numSlots,looseUpTo); + unique->maxmem = (unsigned) maxMemory / 10 * 9; + if (unique == NULL) return(NULL); + maxCacheSize = (unsigned int) ((maxMemory / sizeof(DdCache)) / + DD_MAX_CACHE_FRACTION); + result = cuddInitCache(unique,cacheSize,maxCacheSize); + if (result == 0) return(NULL); + + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + unique->stash = ALLOC(char,(maxMemory / DD_STASH_FRACTION) + 4); + MMoutOfMemory = saveHandler; + if (unique->stash == NULL) { + (void) fprintf(unique->err,"Unable to set aside memory\n"); + } + + /* Initialize constants. */ + unique->one = cuddUniqueConst(unique,1.0); + if (unique->one == NULL) return(0); + cuddRef(unique->one); + unique->zero = cuddUniqueConst(unique,0.0); + if (unique->zero == NULL) return(0); + cuddRef(unique->zero); +#ifdef HAVE_IEEE_754 + if (DD_PLUS_INF_VAL != DD_PLUS_INF_VAL * 3 || + DD_PLUS_INF_VAL != DD_PLUS_INF_VAL / 3) { + (void) fprintf(unique->err,"Warning: Crippled infinite values\n"); + (void) fprintf(unique->err,"Recompile without -DHAVE_IEEE_754\n"); + } +#endif + unique->plusinfinity = cuddUniqueConst(unique,DD_PLUS_INF_VAL); + if (unique->plusinfinity == NULL) return(0); + cuddRef(unique->plusinfinity); + unique->minusinfinity = cuddUniqueConst(unique,DD_MINUS_INF_VAL); + if (unique->minusinfinity == NULL) return(0); + cuddRef(unique->minusinfinity); + unique->background = unique->zero; + + /* The logical zero is different from the CUDD_VALUE_TYPE zero! */ + one = unique->one; + zero = Cudd_Not(one); + /* Create the projection functions. */ + unique->vars = ALLOC(DdNodePtr,unique->maxSize); + if (unique->vars == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < unique->size; i++) { + unique->vars[i] = cuddUniqueInter(unique,i,one,zero); + if (unique->vars[i] == NULL) return(0); + cuddRef(unique->vars[i]); + } + + if (unique->sizeZ) + cuddZddInitUniv(unique); + + unique->memused += sizeof(DdNode *) * unique->maxSize; + + return(unique); + +} /* end of Cudd_Init */ + + +/**Function******************************************************************** + + Synopsis [Deletes resources associated with a DD manager.] + + Description [Deletes resources associated with a DD manager and + resets the global statistical counters. (Otherwise, another manaqger + subsequently created would inherit the stats of this one.)] + + SideEffects [None] + + SeeAlso [Cudd_Init] + +******************************************************************************/ +void +Cudd_Quit( + DdManager * unique) +{ + if (unique->stash != NULL) FREE(unique->stash); + cuddFreeTable(unique); + +} /* end of Cudd_Quit */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Initializes the ZDD universe.] + + Description [Initializes the ZDD universe. Returns 1 if successful; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [cuddZddFreeUniv] + +******************************************************************************/ +int +cuddZddInitUniv( + DdManager * zdd) +{ + DdNode *p, *res; + int i; + + zdd->univ = ALLOC(DdNodePtr, zdd->sizeZ); + if (zdd->univ == NULL) { + zdd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + + res = DD_ONE(zdd); + cuddRef(res); + for (i = zdd->sizeZ - 1; i >= 0; i--) { + unsigned int index = zdd->invpermZ[i]; + p = res; + res = cuddUniqueInterZdd(zdd, index, p, p); + if (res == NULL) { + Cudd_RecursiveDerefZdd(zdd,p); + FREE(zdd->univ); + return(0); + } + cuddRef(res); + cuddDeref(p); + zdd->univ[i] = res; + } + +#ifdef DD_VERBOSE + cuddZddP(zdd, zdd->univ[0]); +#endif + + return(1); + +} /* end of cuddZddInitUniv */ + + +/**Function******************************************************************** + + Synopsis [Frees the ZDD universe.] + + Description [Frees the ZDD universe.] + + SideEffects [None] + + SeeAlso [cuddZddInitUniv] + +******************************************************************************/ +void +cuddZddFreeUniv( + DdManager * zdd) +{ + if (zdd->univ) { + Cudd_RecursiveDerefZdd(zdd, zdd->univ[0]); + FREE(zdd->univ); + } + +} /* end of cuddZddFreeUniv */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/cudd/cuddInt.h b/abc70930/src/bdd/cudd/cuddInt.h new file mode 100644 index 00000000..a5d0cf16 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddInt.h @@ -0,0 +1,1133 @@ +/**CHeaderFile***************************************************************** + + FileName [cuddInt.h] + + PackageName [cudd] + + Synopsis [Internal data structures of the CUDD package.] + + Description [] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + + Revision [$Id: cuddInt.h,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $] + +******************************************************************************/ + +#ifndef _CUDDINT +#define _CUDDINT + + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +#ifdef DD_MIS +#include "array.h" +#include "list.h" +#include "st.h" +#include "espresso.h" +#include "node.h" +#ifdef SIS +#include "graph.h" +#include "astg.h" +#endif +#include "network.h" +#endif + +#include +#include "cudd.h" +#include "st.h" + +#if defined(__GNUC__) +# define DD_INLINE __inline__ +# if (__GNUC__ >2 || __GNUC_MINOR__ >=7) +# define DD_UNUSED __attribute__ ((__unused__)) +# else +# define DD_UNUSED +# endif +#else +# if defined(__cplusplus) +# define DD_INLINE inline +# else +# define DD_INLINE +# endif +# define DD_UNUSED +#endif + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define DD_MAXREF ((DdHalfWord) ~0) + +#define DD_DEFAULT_RESIZE 10 /* how many extra variables */ + /* should be added when resizing */ +#define DD_MEM_CHUNK 1022 + +/* These definitions work for CUDD_VALUE_TYPE == double */ +#define DD_ONE_VAL (1.0) +#define DD_ZERO_VAL (0.0) +#define DD_EPSILON (1.0e-12) + +/* The definitions of +/- infinity in terms of HUGE_VAL work on +** the DECstations and on many other combinations of OS/compiler. +*/ +#ifdef HAVE_IEEE_754 +# define DD_PLUS_INF_VAL (HUGE_VAL) +#else +# define DD_PLUS_INF_VAL (10e301) +# define DD_CRI_HI_MARK (10e150) +# define DD_CRI_LO_MARK (-(DD_CRI_HI_MARK)) +#endif +#define DD_MINUS_INF_VAL (-(DD_PLUS_INF_VAL)) + +#define DD_NON_CONSTANT ((DdNode *) 1) /* for Cudd_bddIteConstant */ + +/* Unique table and cache management constants. */ +#define DD_MAX_SUBTABLE_DENSITY 4 /* tells when to resize a subtable */ +/* gc when this percent are dead (measured w.r.t. slots, not keys) +** The first limit (LO) applies normally. The second limit applies when +** the package believes more space for the unique table (i.e., more dead +** nodes) would improve performance, and the unique table is not already +** too large. The third limit applies when memory is low. +*/ +#define DD_GC_FRAC_LO DD_MAX_SUBTABLE_DENSITY * 0.25 +#define DD_GC_FRAC_HI DD_MAX_SUBTABLE_DENSITY * 1.0 +#define DD_GC_FRAC_MIN 0.2 +#define DD_MIN_HIT 30 /* resize cache when hit ratio + above this percentage (default) */ +#define DD_MAX_LOOSE_FRACTION 5 /* 1 / (max fraction of memory used for + unique table in fast growth mode) */ +#define DD_MAX_CACHE_FRACTION 3 /* 1 / (max fraction of memory used for + computed table if resizing enabled) */ +#define DD_STASH_FRACTION 64 /* 1 / (fraction of memory set + aside for emergencies) */ +#define DD_MAX_CACHE_TO_SLOTS_RATIO 4 /* used to limit the cache size */ + +/* Variable ordering default parameter values. */ +#define DD_SIFT_MAX_VAR 1000 +#define DD_SIFT_MAX_SWAPS 2000000 +#define DD_DEFAULT_RECOMB 0 +#define DD_MAX_REORDER_GROWTH 1.2 +#define DD_FIRST_REORDER 4004 /* 4 for the constants */ +#define DD_DYN_RATIO 2 /* when to dynamically reorder */ + +/* Primes for cache hash functions. */ +#define DD_P1 12582917 +#define DD_P2 4256249 +#define DD_P3 741457 +#define DD_P4 1618033999 + +/* Cache tags for 3-operand operators. These tags are stored in the +** least significant bits of the cache operand pointers according to +** the following scheme. The tag consists of two hex digits. Both digits +** must be even, so that they do not interfere with complementation bits. +** The least significant one is stored in Bits 3:1 of the f operand in the +** cache entry. Bit 1 is always 1, so that we can differentiate +** three-operand operations from one- and two-operand operations. +** Therefore, the least significant digit is one of {2,6,a,e}. The most +** significant digit occupies Bits 3:1 of the g operand in the cache +** entry. It can by any even digit between 0 and e. This gives a total +** of 5 bits for the tag proper, which means a maximum of 32 three-operand +** operations. */ +#define DD_ADD_ITE_TAG 0x02 +#define DD_BDD_AND_ABSTRACT_TAG 0x06 +#define DD_BDD_XOR_EXIST_ABSTRACT_TAG 0x0a +#define DD_BDD_ITE_TAG 0x0e +#define DD_ADD_BDD_DO_INTERVAL_TAG 0x22 +#define DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG 0x26 +#define DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG 0x2a +#define DD_BDD_COMPOSE_RECUR_TAG 0x2e +#define DD_ADD_COMPOSE_RECUR_TAG 0x42 +#define DD_ADD_NON_SIM_COMPOSE_TAG 0x46 +#define DD_EQUIV_DC_TAG 0x4a +#define DD_ZDD_ITE_TAG 0x4e +#define DD_ADD_ITE_CONSTANT_TAG 0x62 +#define DD_ADD_EVAL_CONST_TAG 0x66 +#define DD_BDD_ITE_CONSTANT_TAG 0x6a +#define DD_ADD_OUT_SUM_TAG 0x6e +#define DD_BDD_LEQ_UNLESS_TAG 0x82 +#define DD_ADD_TRIANGLE_TAG 0x86 + +/* Generator constants. */ +#define CUDD_GEN_CUBES 0 +#define CUDD_GEN_NODES 1 +#define CUDD_GEN_ZDD_PATHS 2 +#define CUDD_GEN_EMPTY 0 +#define CUDD_GEN_NONEMPTY 1 + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +struct DdGen { + DdManager *manager; + int type; + int status; + union { + struct { + int *cube; + CUDD_VALUE_TYPE value; + } cubes; + struct { + st_table *visited; + st_generator *stGen; + } nodes; + } gen; + struct { + int sp; + DdNode **stack; + } stack; + DdNode *node; +}; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/* Hooks in CUDD are functions that the application registers with the +** manager so that they are called at appropriate times. The functions +** are passed the manager as argument; they should return 1 if +** successful and 0 otherwise. +*/ +typedef struct DdHook { /* hook list element */ + int (*f) ARGS((DdManager *, char *, void *)); /* function to be called */ + struct DdHook *next; /* next element in the list */ +} DdHook; + +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +typedef long ptrint; +typedef unsigned long ptruint; +#else +typedef int ptrint; +typedef unsigned int ptruint; +#endif + +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + +typedef DdNode *DdNodePtr; + +/* Generic local cache item. */ +typedef struct DdLocalCacheItem { + DdNode *value; +#ifdef DD_CACHE_PROFILE + ptrint count; +#endif + DdNode *key[1]; +} DdLocalCacheItem; + +/* Local cache. */ +typedef struct DdLocalCache { + DdLocalCacheItem *item; + unsigned int itemsize; + unsigned int keysize; + unsigned int slots; + int shift; + double lookUps; + double minHit; + double hits; + unsigned int maxslots; + DdManager *manager; + struct DdLocalCache *next; +} DdLocalCache; + +/* Generic hash item. */ +typedef struct DdHashItem { + struct DdHashItem *next; + ptrint count; + DdNode *value; + DdNode *key[1]; +} DdHashItem; + +/* Local hash table */ +typedef struct DdHashTable { + unsigned int keysize; + unsigned int itemsize; + DdHashItem **bucket; + DdHashItem *nextFree; + DdHashItem **memoryList; + unsigned int numBuckets; + int shift; + unsigned int size; + unsigned int maxsize; + DdManager *manager; +} DdHashTable; + +typedef struct DdCache { + DdNode *f,*g; /* DDs */ + ptruint h; /* either operator or DD */ + DdNode *data; /* already constructed DD */ +#ifdef DD_CACHE_PROFILE + ptrint count; +#endif +} DdCache; + +typedef struct DdSubtable { /* subtable for one index */ + DdNode **nodelist; /* hash table */ + int shift; /* shift for hash function */ + unsigned int slots; /* size of the hash table */ + unsigned int keys; /* number of nodes stored in this table */ + unsigned int maxKeys; /* slots * DD_MAX_SUBTABLE_DENSITY */ + unsigned int dead; /* number of dead nodes in this table */ + unsigned int next; /* index of next variable in group */ + int bindVar; /* flag to bind this variable to its level */ + /* Fields for lazy sifting. */ + Cudd_VariableType varType; /* variable type (ps, ns, pi) */ + int pairIndex; /* corresponding variable index (ps <-> ns) */ + int varHandled; /* flag: 1 means variable is already handled */ + Cudd_LazyGroupType varToBeGrouped; /* tells what grouping to apply */ +} DdSubtable; + +struct DdManager { /* specialized DD symbol table */ + /* Constants */ + DdNode sentinel; /* for collision lists */ + DdNode *one; /* constant 1 */ + DdNode *zero; /* constant 0 */ + DdNode *plusinfinity; /* plus infinity */ + DdNode *minusinfinity; /* minus infinity */ + DdNode *background; /* background value */ + /* Computed Table */ + DdCache *acache; /* address of allocated memory for cache */ + DdCache *cache; /* the cache-based computed table */ + unsigned int cacheSlots; /* total number of cache entries */ + int cacheShift; /* shift value for cache hash function */ + double cacheMisses; /* number of cache misses (since resizing) */ + double cacheHits; /* number of cache hits (since resizing) */ + double minHit; /* hit percentage above which to resize */ + int cacheSlack; /* slots still available for resizing */ + unsigned int maxCacheHard; /* hard limit for cache size */ + /* Unique Table */ + int size; /* number of unique subtables */ + int sizeZ; /* for ZDD */ + int maxSize; /* max number of subtables before resizing */ + int maxSizeZ; /* for ZDD */ + DdSubtable *subtables; /* array of unique subtables */ + DdSubtable *subtableZ; /* for ZDD */ + DdSubtable constants; /* unique subtable for the constants */ + unsigned int slots; /* total number of hash buckets */ + unsigned int keys; /* total number of BDD and ADD nodes */ + unsigned int keysZ; /* total number of ZDD nodes */ + unsigned int dead; /* total number of dead BDD and ADD nodes */ + unsigned int deadZ; /* total number of dead ZDD nodes */ + unsigned int maxLive; /* maximum number of live nodes */ + unsigned int minDead; /* do not GC if fewer than these dead */ + double gcFrac; /* gc when this fraction is dead */ + int gcEnabled; /* gc is enabled */ + unsigned int looseUpTo; /* slow growth beyond this limit */ + /* (measured w.r.t. slots, not keys) */ + unsigned int initSlots; /* initial size of a subtable */ + DdNode **stack; /* stack for iterative procedures */ + double allocated; /* number of nodes allocated */ + /* (not during reordering) */ + double reclaimed; /* number of nodes brought back from the dead */ + int isolated; /* isolated projection functions */ + int *perm; /* current variable perm. (index to level) */ + int *permZ; /* for ZDD */ + int *invperm; /* current inv. var. perm. (level to index) */ + int *invpermZ; /* for ZDD */ + DdNode **vars; /* projection functions */ + int *map; /* variable map for fast swap */ + DdNode **univ; /* ZDD 1 for each variable */ + int linearSize; /* number of rows and columns of linear */ + long *interact; /* interacting variable matrix */ + long *linear; /* linear transform matrix */ + /* Memory Management */ + DdNode **memoryList; /* memory manager for symbol table */ + DdNode *nextFree; /* list of free nodes */ + char *stash; /* memory reserve */ +#ifndef DD_NO_DEATH_ROW + DdNode **deathRow; /* queue for dereferencing */ + int deathRowDepth; /* number of slots in the queue */ + int nextDead; /* index in the queue */ + unsigned deadMask; /* mask for circular index update */ +#endif + /* General Parameters */ + CUDD_VALUE_TYPE epsilon; /* tolerance on comparisons */ + /* Dynamic Reordering Parameters */ + int reordered; /* flag set at the end of reordering */ + int reorderings; /* number of calls to Cudd_ReduceHeap */ + int siftMaxVar; /* maximum number of vars sifted */ + int siftMaxSwap; /* maximum number of swaps per sifting */ + double maxGrowth; /* maximum growth during reordering */ + double maxGrowthAlt; /* alternate maximum growth for reordering */ + int reordCycle; /* how often to apply alternate threshold */ + int autoDyn; /* automatic dynamic reordering flag (BDD) */ + int autoDynZ; /* automatic dynamic reordering flag (ZDD) */ + Cudd_ReorderingType autoMethod; /* default reordering method */ + Cudd_ReorderingType autoMethodZ; /* default reordering method (ZDD) */ + int realign; /* realign ZDD order after BDD reordering */ + int realignZ; /* realign BDD order after ZDD reordering */ + unsigned int nextDyn; /* reorder if this size is reached */ + unsigned int countDead; /* if 0, count deads to trigger reordering */ + MtrNode *tree; /* Variable group tree (BDD) */ + MtrNode *treeZ; /* Variable group tree (ZDD) */ + Cudd_AggregationType groupcheck; /* Used during group sifting */ + int recomb; /* Used during group sifting */ + int symmviolation; /* Used during group sifting */ + int arcviolation; /* Used during group sifting */ + int populationSize; /* population size for GA */ + int numberXovers; /* number of crossovers for GA */ + DdLocalCache *localCaches; /* local caches currently in existence */ +#ifdef __osf__ +#pragma pointer_size restore +#endif + char *hooks; /* application-specific field (used by vis) */ + DdHook *preGCHook; /* hooks to be called before GC */ + DdHook *postGCHook; /* hooks to be called after GC */ + DdHook *preReorderingHook; /* hooks to be called before reordering */ + DdHook *postReorderingHook; /* hooks to be called after reordering */ + FILE *out; /* stdout for this manager */ + FILE *err; /* stderr for this manager */ +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + Cudd_ErrorType errorCode; /* info on last error */ + /* Statistical counters. */ + long memused; /* total memory allocated for the manager */ + long maxmem; /* target maximum memory */ + long maxmemhard; /* hard limit for maximum memory */ + int garbageCollections; /* number of garbage collections */ + long GCTime; /* total time spent in garbage collection */ + long reordTime; /* total time spent in reordering */ + double totCachehits; /* total number of cache hits */ + double totCacheMisses; /* total number of cache misses */ + double cachecollisions; /* number of cache collisions */ + double cacheinserts; /* number of cache insertions */ + double cacheLastInserts; /* insertions at the last cache resizing */ + double cachedeletions; /* number of deletions during garbage coll. */ +#ifdef DD_STATS + double nodesFreed; /* number of nodes returned to the free list */ + double nodesDropped; /* number of nodes killed by dereferencing */ +#endif + unsigned int peakLiveNodes; /* maximum number of live nodes */ +#ifdef DD_UNIQUE_PROFILE + double uniqueLookUps; /* number of unique table lookups */ + double uniqueLinks; /* total distance traveled in coll. chains */ +#endif +#ifdef DD_COUNT + double recursiveCalls; /* number of recursive calls */ +#ifdef DD_STATS + double nextSample; /* when to write next line of stats */ +#endif + double swapSteps; /* number of elementary reordering steps */ +#endif +#ifdef DD_MIS + /* mis/verif compatibility fields */ + array_t *iton; /* maps ids in ddNode to node_t */ + array_t *order; /* copy of order_list */ + lsHandle handle; /* where it is in network BDD list */ + network_t *network; + st_table *local_order; /* for local BDDs */ + int nvars; /* variables used so far */ + int threshold; /* for pseudo var threshold value*/ +#endif +}; + +typedef struct Move { + DdHalfWord x; + DdHalfWord y; + unsigned int flags; + int size; + struct Move *next; +} Move; + +/* Generic level queue item. */ +typedef struct DdQueueItem { + struct DdQueueItem *next; + struct DdQueueItem *cnext; + void *key; +} DdQueueItem; + +/* Level queue. */ +typedef struct DdLevelQueue { + void *first; + DdQueueItem **last; + DdQueueItem *freelist; + DdQueueItem **buckets; + int levels; + int itemsize; + int size; + int maxsize; + int numBuckets; + int shift; +} DdLevelQueue; + +#ifdef __osf__ +#pragma pointer_size restore +#endif + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**Macro*********************************************************************** + + Synopsis [Adds node to the head of the free list.] + + Description [Adds node to the head of the free list. Does not + deallocate memory chunks that become free. This function is also + used by the dynamic reordering functions.] + + SideEffects [None] + + SeeAlso [cuddAllocNode cuddDynamicAllocNode] + +******************************************************************************/ +#define cuddDeallocNode(unique,node) \ + (node)->next = (unique)->nextFree; \ + (unique)->nextFree = node; + + +/**Macro*********************************************************************** + + Synopsis [Increases the reference count of a node, if it is not + saturated.] + + Description [Increases the reference count of a node, if it is not + saturated. This being a macro, it is faster than Cudd_Ref, but it + cannot be used in constructs like cuddRef(a = b()).] + + SideEffects [none] + + SeeAlso [Cudd_Ref] + +******************************************************************************/ +#define cuddRef(n) cuddSatInc(Cudd_Regular(n)->ref) + + +/**Macro*********************************************************************** + + Synopsis [Decreases the reference count of a node, if it is not + saturated.] + + Description [Decreases the reference count of node. It is primarily + used in recursive procedures to decrease the ref count of a result + node before returning it. This accomplishes the goal of removing the + protection applied by a previous cuddRef. This being a macro, it is + faster than Cudd_Deref, but it cannot be used in constructs like + cuddDeref(a = b()).] + + SideEffects [none] + + SeeAlso [Cudd_Deref] + +******************************************************************************/ +#define cuddDeref(n) cuddSatDec(Cudd_Regular(n)->ref) + + +/**Macro*********************************************************************** + + Synopsis [Returns 1 if the node is a constant node.] + + Description [Returns 1 if the node is a constant node (rather than an + internal node). All constant nodes have the same index + (CUDD_CONST_INDEX). The pointer passed to cuddIsConstant must be regular.] + + SideEffects [none] + + SeeAlso [Cudd_IsConstant] + +******************************************************************************/ +#define cuddIsConstant(node) ((node)->index == CUDD_CONST_INDEX) + + +/**Macro*********************************************************************** + + Synopsis [Returns the then child of an internal node.] + + Description [Returns the then child of an internal node. If + node is a constant node, the result is unpredictable. + The pointer passed to cuddT must be regular.] + + SideEffects [none] + + SeeAlso [Cudd_T] + +******************************************************************************/ +#define cuddT(node) ((node)->type.kids.T) + + +/**Macro*********************************************************************** + + Synopsis [Returns the else child of an internal node.] + + Description [Returns the else child of an internal node. If + node is a constant node, the result is unpredictable. + The pointer passed to cuddE must be regular.] + + SideEffects [none] + + SeeAlso [Cudd_E] + +******************************************************************************/ +#define cuddE(node) ((node)->type.kids.E) + + +/**Macro*********************************************************************** + + Synopsis [Returns the value of a constant node.] + + Description [Returns the value of a constant node. If + node is an internal node, the result is unpredictable. + The pointer passed to cuddV must be regular.] + + SideEffects [none] + + SeeAlso [Cudd_V] + +******************************************************************************/ +#define cuddV(node) ((node)->type.value) + + +/**Macro*********************************************************************** + + Synopsis [Finds the current position of variable index in the + order.] + + Description [Finds the current position of variable index in the + order. This macro duplicates the functionality of Cudd_ReadPerm, + but it does not check for out-of-bounds indices and it is more + efficient.] + + SideEffects [none] + + SeeAlso [Cudd_ReadPerm] + +******************************************************************************/ +#define cuddI(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->perm[(index)]) + + +/**Macro*********************************************************************** + + Synopsis [Finds the current position of ZDD variable index in the + order.] + + Description [Finds the current position of ZDD variable index in the + order. This macro duplicates the functionality of Cudd_ReadPermZdd, + but it does not check for out-of-bounds indices and it is more + efficient.] + + SideEffects [none] + + SeeAlso [Cudd_ReadPermZdd] + +******************************************************************************/ +#define cuddIZ(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->permZ[(index)]) + + +/**Macro*********************************************************************** + + Synopsis [Hash function for the unique table.] + + Description [] + + SideEffects [none] + + SeeAlso [ddCHash ddCHash2] + +******************************************************************************/ +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +#define ddHash(f,g,s) \ +((((unsigned)(unsigned long)(f) * DD_P1 + \ + (unsigned)(unsigned long)(g)) * DD_P2) >> (s)) +#else +#define ddHash(f,g,s) \ +((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) +#endif + + +/**Macro*********************************************************************** + + Synopsis [Hash function for the cache.] + + Description [] + + SideEffects [none] + + SeeAlso [ddHash ddCHash2] + +******************************************************************************/ +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +#define ddCHash(o,f,g,h,s) \ +((((((unsigned)(unsigned long)(f) + (unsigned)(unsigned long)(o)) * DD_P1 + \ + (unsigned)(unsigned long)(g)) * DD_P2 + \ + (unsigned)(unsigned long)(h)) * DD_P3) >> (s)) +#else +#define ddCHash(o,f,g,h,s) \ +((((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2 + \ + (unsigned)(h)) * DD_P3) >> (s)) +#endif + + +/**Macro*********************************************************************** + + Synopsis [Hash function for the cache for functions with two + operands.] + + Description [] + + SideEffects [none] + + SeeAlso [ddHash ddCHash] + +******************************************************************************/ +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +#define ddCHash2(o,f,g,s) \ +(((((unsigned)(unsigned long)(f) + (unsigned)(unsigned long)(o)) * DD_P1 + \ + (unsigned)(unsigned long)(g)) * DD_P2) >> (s)) +#else +#define ddCHash2(o,f,g,s) \ +(((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) +#endif + + +/**Macro*********************************************************************** + + Synopsis [Clears the 4 least significant bits of a pointer.] + + Description [] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +#define cuddClean(p) ((DdNode *)((ptruint)(p) & ~0xf)) + + +/**Macro*********************************************************************** + + Synopsis [Computes the minimum of two numbers.] + + Description [] + + SideEffects [none] + + SeeAlso [ddMax] + +******************************************************************************/ +#define ddMin(x,y) (((y) < (x)) ? (y) : (x)) + + +/**Macro*********************************************************************** + + Synopsis [Computes the maximum of two numbers.] + + Description [] + + SideEffects [none] + + SeeAlso [ddMin] + +******************************************************************************/ +#define ddMax(x,y) (((y) > (x)) ? (y) : (x)) + + +/**Macro*********************************************************************** + + Synopsis [Computes the absolute value of a number.] + + Description [] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +#define ddAbs(x) (((x)<0) ? -(x) : (x)) + + +/**Macro*********************************************************************** + + Synopsis [Returns 1 if the absolute value of the difference of the two + arguments x and y is less than e.] + + Description [] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +#define ddEqualVal(x,y,e) (ddAbs((x)-(y))<(e)) + + +/**Macro*********************************************************************** + + Synopsis [Saturating increment operator.] + + Description [] + + SideEffects [none] + + SeeAlso [cuddSatDec] + +******************************************************************************/ +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +#define cuddSatInc(x) ((x)++) +#else +#define cuddSatInc(x) ((x) += (x) != (DdHalfWord)DD_MAXREF) +#endif + + +/**Macro*********************************************************************** + + Synopsis [Saturating decrement operator.] + + Description [] + + SideEffects [none] + + SeeAlso [cuddSatInc] + +******************************************************************************/ +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +#define cuddSatDec(x) ((x)--) +#else +#define cuddSatDec(x) ((x) -= (x) != (DdHalfWord)DD_MAXREF) +#endif + + +/**Macro*********************************************************************** + + Synopsis [Returns the constant 1 node.] + + Description [] + + SideEffects [none] + + SeeAlso [DD_ZERO DD_PLUS_INFINITY DD_MINUS_INFINITY] + +******************************************************************************/ +#define DD_ONE(dd) ((dd)->one) + + +/**Macro*********************************************************************** + + Synopsis [Returns the arithmetic 0 constant node.] + + Description [Returns the arithmetic 0 constant node. This is different + from the logical zero. The latter is obtained by + Cudd_Not(DD_ONE(dd)).] + + SideEffects [none] + + SeeAlso [DD_ONE Cudd_Not DD_PLUS_INFINITY DD_MINUS_INFINITY] + +******************************************************************************/ +#define DD_ZERO(dd) ((dd)->zero) + + +/**Macro*********************************************************************** + + Synopsis [Returns the plus infinity constant node.] + + Description [] + + SideEffects [none] + + SeeAlso [DD_ONE DD_ZERO DD_MINUS_INFINITY] + +******************************************************************************/ +#define DD_PLUS_INFINITY(dd) ((dd)->plusinfinity) + + +/**Macro*********************************************************************** + + Synopsis [Returns the minus infinity constant node.] + + Description [] + + SideEffects [none] + + SeeAlso [DD_ONE DD_ZERO DD_PLUS_INFINITY] + +******************************************************************************/ +#define DD_MINUS_INFINITY(dd) ((dd)->minusinfinity) + + +/**Macro*********************************************************************** + + Synopsis [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL.] + + Description [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL. + Furthermore, if x <= DD_MINUS_INF_VAL/2, x is set to + DD_MINUS_INF_VAL. Similarly, if DD_PLUS_INF_VAL/2 <= x, x is set to + DD_PLUS_INF_VAL. Normally this macro is a NOOP. However, if + HAVE_IEEE_754 is not defined, it makes sure that a value does not + get larger than infinity in absolute value, and once it gets to + infinity, stays there. If the value overflows before this macro is + applied, no recovery is possible.] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +#ifdef HAVE_IEEE_754 +#define cuddAdjust(x) +#else +#define cuddAdjust(x) ((x) = ((x) >= DD_CRI_HI_MARK) ? DD_PLUS_INF_VAL : (((x) <= DD_CRI_LO_MARK) ? DD_MINUS_INF_VAL : (x))) +#endif + + +/**Macro*********************************************************************** + + Synopsis [Extract the least significant digit of a double digit.] + + Description [Extract the least significant digit of a double digit. Used + in the manipulation of arbitrary precision integers.] + + SideEffects [None] + + SeeAlso [DD_MSDIGIT] + +******************************************************************************/ +#define DD_LSDIGIT(x) ((x) & DD_APA_MASK) + + +/**Macro*********************************************************************** + + Synopsis [Extract the most significant digit of a double digit.] + + Description [Extract the most significant digit of a double digit. Used + in the manipulation of arbitrary precision integers.] + + SideEffects [None] + + SeeAlso [DD_LSDIGIT] + +******************************************************************************/ +#define DD_MSDIGIT(x) ((x) >> DD_APA_BITS) + + +/**Macro*********************************************************************** + + Synopsis [Outputs a line of stats.] + + Description [Outputs a line of stats if DD_COUNT and DD_STATS are + defined. Increments the number of recursive calls if DD_COUNT is + defined.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +#ifdef DD_COUNT +#ifdef DD_STATS +#define statLine(dd) dd->recursiveCalls++; \ +if (dd->recursiveCalls == dd->nextSample) {(void) fprintf(dd->err, \ +"@%.0f: %u nodes %u live %.0f dropped %.0f reclaimed\n", dd->recursiveCalls, \ +dd->keys, dd->keys - dd->dead, dd->nodesDropped, dd->reclaimed); \ +dd->nextSample += 250000;} +#else +#define statLine(dd) dd->recursiveCalls++; +#endif +#else +#define statLine(dd) +#endif + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + +EXTERN DdNode * cuddAddExistAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); +EXTERN DdNode * cuddAddUnivAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); +EXTERN DdNode * cuddAddOrAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); +EXTERN DdNode * cuddAddApplyRecur ARGS((DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g)); +EXTERN DdNode * cuddAddMonadicApplyRecur ARGS((DdManager * dd, DdNode * (*op)(DdManager *, DdNode *), DdNode * f)); +EXTERN DdNode * cuddAddScalarInverseRecur ARGS((DdManager *dd, DdNode *f, DdNode *epsilon)); +EXTERN DdNode * cuddAddIteRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); +EXTERN DdNode * cuddAddCmplRecur ARGS((DdManager *dd, DdNode *f)); +EXTERN DdNode * cuddAddNegateRecur ARGS((DdManager *dd, DdNode *f)); +EXTERN DdNode * cuddAddRoundOffRecur ARGS((DdManager *dd, DdNode *f, double trunc)); +EXTERN DdNode * cuddUnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality)); +EXTERN DdNode * cuddRemapUnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, double quality)); +EXTERN DdNode * cuddBiasedUnderApprox ARGS((DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0)); +EXTERN DdNode * cuddBddAndAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); +EXTERN int cuddAnnealing ARGS((DdManager *table, int lower, int upper)); +EXTERN DdNode * cuddBddExistAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); +EXTERN DdNode * cuddBddXorExistAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); +EXTERN DdNode * cuddBddBooleanDiffRecur ARGS((DdManager *manager, DdNode *f, DdNode *var)); +EXTERN DdNode * cuddBddIteRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); +EXTERN DdNode * cuddBddIntersectRecur ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * cuddBddAndRecur ARGS((DdManager *manager, DdNode *f, DdNode *g)); +EXTERN DdNode * cuddBddXorRecur ARGS((DdManager *manager, DdNode *f, DdNode *g)); +EXTERN DdNode * cuddBddTransfer ARGS((DdManager *ddS, DdManager *ddD, DdNode *f)); +EXTERN DdNode * cuddAddBddDoPattern ARGS((DdManager *dd, DdNode *f)); +EXTERN int cuddInitCache ARGS((DdManager *unique, unsigned int cacheSize, unsigned int maxCacheSize)); +EXTERN void cuddCacheInsert ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h, DdNode *data)); +EXTERN void cuddCacheInsert2 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g, DdNode *data)); +EXTERN void cuddCacheInsert1 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f, DdNode *data)); +EXTERN DdNode * cuddCacheLookup ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)); +EXTERN DdNode * cuddCacheLookupZdd ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)); +EXTERN DdNode * cuddCacheLookup2 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g)); +EXTERN DdNode * cuddCacheLookup1 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f)); +EXTERN DdNode * cuddCacheLookup2Zdd ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g)); +EXTERN DdNode * cuddCacheLookup1Zdd ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f)); +EXTERN DdNode * cuddConstantLookup ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)); +EXTERN int cuddCacheProfile ARGS((DdManager *table, FILE *fp)); +EXTERN void cuddCacheResize ARGS((DdManager *table)); +EXTERN void cuddCacheFlush ARGS((DdManager *table)); +EXTERN int cuddComputeFloorLog2 ARGS((unsigned int value)); +EXTERN int cuddHeapProfile ARGS((DdManager *dd)); +EXTERN void cuddPrintNode ARGS((DdNode *f, FILE *fp)); +EXTERN void cuddPrintVarGroups ARGS((DdManager * dd, MtrNode * root, int zdd, int silent)); +EXTERN DdNode * cuddBddClippingAnd ARGS((DdManager *dd, DdNode *f, DdNode *g, int maxDepth, int direction)); +EXTERN DdNode * cuddBddClippingAndAbstract ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *cube, int maxDepth, int direction)); +EXTERN void cuddGetBranches ARGS((DdNode *g, DdNode **g1, DdNode **g0)); +EXTERN int cuddCheckCube ARGS((DdManager *dd, DdNode *g)); +EXTERN DdNode * cuddCofactorRecur ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * cuddBddComposeRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *proj)); +EXTERN DdNode * cuddAddComposeRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *proj)); +EXTERN int cuddExact ARGS((DdManager *table, int lower, int upper)); +EXTERN DdNode * cuddBddConstrainRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); +EXTERN DdNode * cuddBddRestrictRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); +EXTERN DdNode * cuddAddConstrainRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); +EXTERN DdNode * cuddAddRestrictRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); +EXTERN DdNode * cuddBddLICompaction ARGS((DdManager *dd, DdNode *f, DdNode *c)); +EXTERN int cuddGa ARGS((DdManager *table, int lower, int upper)); +EXTERN int cuddTreeSifting ARGS((DdManager *table, Cudd_ReorderingType method)); +EXTERN int cuddZddInitUniv ARGS((DdManager *zdd)); +EXTERN void cuddZddFreeUniv ARGS((DdManager *zdd)); +EXTERN void cuddSetInteract ARGS((DdManager *table, int x, int y)); +EXTERN int cuddTestInteract ARGS((DdManager *table, int x, int y)); +EXTERN int cuddInitInteract ARGS((DdManager *table)); +EXTERN DdLocalCache * cuddLocalCacheInit ARGS((DdManager *manager, unsigned int keySize, unsigned int cacheSize, unsigned int maxCacheSize)); +EXTERN void cuddLocalCacheQuit ARGS((DdLocalCache *cache)); +EXTERN void cuddLocalCacheInsert ARGS((DdLocalCache *cache, DdNodePtr *key, DdNode *value)); +EXTERN DdNode * cuddLocalCacheLookup ARGS((DdLocalCache *cache, DdNodePtr *key)); +EXTERN void cuddLocalCacheClearDead ARGS((DdManager *manager)); +EXTERN int cuddIsInDeathRow ARGS((DdManager *dd, DdNode *f)); +EXTERN int cuddTimesInDeathRow ARGS((DdManager *dd, DdNode *f)); +EXTERN void cuddLocalCacheClearAll ARGS((DdManager *manager)); +#ifdef DD_CACHE_PROFILE +EXTERN int cuddLocalCacheProfile ARGS((DdLocalCache *cache)); +#endif +EXTERN DdHashTable * cuddHashTableInit ARGS((DdManager *manager, unsigned int keySize, unsigned int initSize)); +EXTERN void cuddHashTableQuit ARGS((DdHashTable *hash)); +EXTERN int cuddHashTableInsert ARGS((DdHashTable *hash, DdNodePtr *key, DdNode *value, ptrint count)); +EXTERN DdNode * cuddHashTableLookup ARGS((DdHashTable *hash, DdNodePtr *key)); +EXTERN int cuddHashTableInsert1 ARGS((DdHashTable *hash, DdNode *f, DdNode *value, ptrint count)); +EXTERN DdNode * cuddHashTableLookup1 ARGS((DdHashTable *hash, DdNode *f)); +EXTERN int cuddHashTableInsert2 ARGS((DdHashTable *hash, DdNode *f, DdNode *g, DdNode *value, ptrint count)); +EXTERN DdNode * cuddHashTableLookup2 ARGS((DdHashTable *hash, DdNode *f, DdNode *g)); +EXTERN int cuddHashTableInsert3 ARGS((DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h, DdNode *value, ptrint count)); +EXTERN DdNode * cuddHashTableLookup3 ARGS((DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h)); +EXTERN DdLevelQueue * cuddLevelQueueInit ARGS((int levels, int itemSize, int numBuckets)); +EXTERN void cuddLevelQueueQuit ARGS((DdLevelQueue *queue)); +EXTERN void * cuddLevelQueueEnqueue ARGS((DdLevelQueue *queue, void *key, int level)); +EXTERN void cuddLevelQueueDequeue ARGS((DdLevelQueue *queue, int level)); +EXTERN int cuddLinearAndSifting ARGS((DdManager *table, int lower, int upper)); +EXTERN DdNode * cuddBddLiteralSetIntersectionRecur ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * cuddCProjectionRecur ARGS((DdManager *dd, DdNode *R, DdNode *Y, DdNode *Ysupp)); +EXTERN DdNode * cuddBddClosestCube ARGS((DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE bound)); +EXTERN void cuddReclaim ARGS((DdManager *table, DdNode *n)); +EXTERN void cuddReclaimZdd ARGS((DdManager *table, DdNode *n)); +EXTERN void cuddClearDeathRow ARGS((DdManager *table)); +EXTERN void cuddShrinkDeathRow ARGS((DdManager *table)); +EXTERN DdNode * cuddDynamicAllocNode ARGS((DdManager *table)); +EXTERN int cuddSifting ARGS((DdManager *table, int lower, int upper)); +EXTERN int cuddSwapping ARGS((DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)); +EXTERN int cuddNextHigh ARGS((DdManager *table, int x)); +EXTERN int cuddNextLow ARGS((DdManager *table, int x)); +EXTERN int cuddSwapInPlace ARGS((DdManager *table, int x, int y)); +EXTERN int cuddBddAlignToZdd ARGS((DdManager *table)); +EXTERN DdNode * cuddBddMakePrime ARGS((DdManager *dd, DdNode *cube, DdNode *f)); +EXTERN DdNode * cuddSolveEqnRecur ARGS((DdManager *bdd, DdNode *F, DdNode *Y, DdNode **G, int n, int *yIndex, int i)); +EXTERN DdNode * cuddVerifySol ARGS((DdManager *bdd, DdNode *F, DdNode **G, int *yIndex, int n)); +#ifdef ST_INCLUDED +EXTERN DdNode* cuddSplitSetRecur ARGS((DdManager *manager, st_table *mtable, int *varSeen, DdNode *p, double n, double max, int index)); +#endif +EXTERN DdNode * cuddSubsetHeavyBranch ARGS((DdManager *dd, DdNode *f, int numVars, int threshold)); +EXTERN DdNode * cuddSubsetShortPaths ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)); +EXTERN int cuddSymmCheck ARGS((DdManager *table, int x, int y)); +EXTERN int cuddSymmSifting ARGS((DdManager *table, int lower, int upper)); +EXTERN int cuddSymmSiftingConv ARGS((DdManager *table, int lower, int upper)); +EXTERN DdNode * cuddAllocNode ARGS((DdManager *unique)); +EXTERN DdManager * cuddInitTable ARGS((unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int looseUpTo)); +EXTERN void cuddFreeTable ARGS((DdManager *unique)); +EXTERN int cuddGarbageCollect ARGS((DdManager *unique, int clearCache)); +EXTERN int cuddGarbageCollectZdd ARGS((DdManager *unique, int clearCache)); +EXTERN DdNode * cuddZddGetNode ARGS((DdManager *zdd, int id, DdNode *T, DdNode *E)); +EXTERN DdNode * cuddZddGetNodeIVO ARGS((DdManager *dd, int index, DdNode *g, DdNode *h)); +EXTERN DdNode * cuddUniqueInter ARGS((DdManager *unique, int index, DdNode *T, DdNode *E)); +EXTERN DdNode * cuddUniqueInterIVO ARGS((DdManager *unique, int index, DdNode *T, DdNode *E)); +EXTERN DdNode * cuddUniqueInterZdd ARGS((DdManager *unique, int index, DdNode *T, DdNode *E)); +EXTERN DdNode * cuddUniqueConst ARGS((DdManager *unique, CUDD_VALUE_TYPE value)); +EXTERN void cuddRehash ARGS((DdManager *unique, int i)); +EXTERN void cuddShrinkSubtable ARGS((DdManager *unique, int i)); +EXTERN int cuddInsertSubtables ARGS((DdManager *unique, int n, int level)); +EXTERN int cuddDestroySubtables ARGS((DdManager *unique, int n)); +EXTERN int cuddResizeTableZdd ARGS((DdManager *unique, int index)); +EXTERN void cuddSlowTableGrowth ARGS((DdManager *unique)); +EXTERN int cuddP ARGS((DdManager *dd, DdNode *f)); +#ifdef ST_INCLUDED +EXTERN enum st_retval cuddStCountfree ARGS((char *key, char *value, char *arg)); +EXTERN int cuddCollectNodes ARGS((DdNode *f, st_table *visited)); +#endif +EXTERN int cuddWindowReorder ARGS((DdManager *table, int low, int high, Cudd_ReorderingType submethod)); +EXTERN DdNode * cuddZddProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * cuddZddUnateProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * cuddZddWeakDiv ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * cuddZddWeakDivF ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * cuddZddDivide ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN DdNode * cuddZddDivideF ARGS((DdManager *dd, DdNode *f, DdNode *g)); +EXTERN int cuddZddGetCofactors3 ARGS((DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0, DdNode **fd)); +EXTERN int cuddZddGetCofactors2 ARGS((DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0)); +EXTERN DdNode * cuddZddComplement ARGS((DdManager *dd, DdNode *node)); +EXTERN int cuddZddGetPosVarIndex(DdManager * dd, int index); +EXTERN int cuddZddGetNegVarIndex(DdManager * dd, int index); +EXTERN int cuddZddGetPosVarLevel(DdManager * dd, int index); +EXTERN int cuddZddGetNegVarLevel(DdManager * dd, int index); +EXTERN int cuddZddTreeSifting ARGS((DdManager *table, Cudd_ReorderingType method)); +EXTERN DdNode * cuddZddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U, DdNode **zdd_I)); +EXTERN DdNode * cuddBddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U)); +EXTERN DdNode * cuddMakeBddFromZddCover ARGS((DdManager *dd, DdNode *node)); +EXTERN int cuddZddLinearSifting ARGS((DdManager *table, int lower, int upper)); +EXTERN int cuddZddAlignToBdd ARGS((DdManager *table)); +EXTERN int cuddZddNextHigh ARGS((DdManager *table, int x)); +EXTERN int cuddZddNextLow ARGS((DdManager *table, int x)); +EXTERN int cuddZddUniqueCompare ARGS((int *ptr_x, int *ptr_y)); +EXTERN int cuddZddSwapInPlace ARGS((DdManager *table, int x, int y)); +EXTERN int cuddZddSwapping ARGS((DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)); +EXTERN int cuddZddSifting ARGS((DdManager *table, int lower, int upper)); +EXTERN DdNode * cuddZddIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); +EXTERN DdNode * cuddZddUnion ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); +EXTERN DdNode * cuddZddIntersect ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); +EXTERN DdNode * cuddZddDiff ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); +EXTERN DdNode * cuddZddChangeAux ARGS((DdManager *zdd, DdNode *P, DdNode *zvar)); +EXTERN DdNode * cuddZddSubset1 ARGS((DdManager *dd, DdNode *P, int var)); +EXTERN DdNode * cuddZddSubset0 ARGS((DdManager *dd, DdNode *P, int var)); +EXTERN DdNode * cuddZddChange ARGS((DdManager *dd, DdNode *P, int var)); +EXTERN int cuddZddSymmCheck ARGS((DdManager *table, int x, int y)); +EXTERN int cuddZddSymmSifting ARGS((DdManager *table, int lower, int upper)); +EXTERN int cuddZddSymmSiftingConv ARGS((DdManager *table, int lower, int upper)); +EXTERN int cuddZddP ARGS((DdManager *zdd, DdNode *f)); + +/**AutomaticEnd***************************************************************/ + +#endif /* _CUDDINT */ diff --git a/abc70930/src/bdd/cudd/cuddInteract.c b/abc70930/src/bdd/cudd/cuddInteract.c new file mode 100644 index 00000000..96613639 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddInteract.c @@ -0,0 +1,402 @@ +/**CFile*********************************************************************** + + FileName [cuddInteract.c] + + PackageName [cudd] + + Synopsis [Functions to manipulate the variable interaction matrix.] + + Description [Internal procedures included in this file: +
        +
      • cuddSetInteract() +
      • cuddTestInteract() +
      • cuddInitInteract() +
      + Static procedures included in this file: +
        +
      • ddSuppInteract() +
      • ddClearLocal() +
      • ddUpdateInteract() +
      • ddClearGlobal() +
      + The interaction matrix tells whether two variables are + both in the support of some function of the DD. The main use of the + interaction matrix is in the in-place swapping. Indeed, if two + variables do not interact, there is no arc connecting the two layers; + therefore, the swap can be performed in constant time, without + scanning the subtables. Another use of the interaction matrix is in + the computation of the lower bounds for sifting. Finally, the + interaction matrix can be used to speed up aggregation checks in + symmetric and group sifting.

      + The computation of the interaction matrix is done with a series of + depth-first searches. The searches start from those nodes that have + only external references. The matrix is stored as a packed array of bits; + since it is symmetric, only the upper triangle is kept in memory. + As a final remark, we note that there may be variables that do + intercat, but that for a given variable order have no arc connecting + their layers when they are adjacent.] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#if SIZEOF_LONG == 8 +#define BPL 64 +#define LOGBPL 6 +#else +#define BPL 32 +#define LOGBPL 5 +#endif + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddInteract.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void ddSuppInteract ARGS((DdNode *f, int *support)); +static void ddClearLocal ARGS((DdNode *f)); +static void ddUpdateInteract ARGS((DdManager *table, int *support)); +static void ddClearGlobal ARGS((DdManager *table)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Set interaction matrix entries.] + + Description [Given a pair of variables 0 <= x < y < table->size, + sets the corresponding bit of the interaction matrix to 1.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +cuddSetInteract( + DdManager * table, + int x, + int y) +{ + int posn, word, bit; + +#ifdef DD_DEBUG + assert(x < y); + assert(y < table->size); + assert(x >= 0); +#endif + + posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1; + word = posn >> LOGBPL; + bit = posn & (BPL-1); + table->interact[word] |= 1L << bit; + +} /* end of cuddSetInteract */ + + +/**Function******************************************************************** + + Synopsis [Test interaction matrix entries.] + + Description [Given a pair of variables 0 <= x < y < table->size, + tests whether the corresponding bit of the interaction matrix is 1. + Returns the value of the bit.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddTestInteract( + DdManager * table, + int x, + int y) +{ + int posn, word, bit, result; + + if (x > y) { + int tmp = x; + x = y; + y = tmp; + } +#ifdef DD_DEBUG + assert(x < y); + assert(y < table->size); + assert(x >= 0); +#endif + + posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1; + word = posn >> LOGBPL; + bit = posn & (BPL-1); + result = (table->interact[word] >> bit) & 1L; + return(result); + +} /* end of cuddTestInteract */ + + +/**Function******************************************************************** + + Synopsis [Initializes the interaction matrix.] + + Description [Initializes the interaction matrix. The interaction + matrix is implemented as a bit vector storing the upper triangle of + the symmetric interaction matrix. The bit vector is kept in an array + of long integers. The computation is based on a series of depth-first + searches, one for each root of the DAG. Two flags are needed: The + local visited flag uses the LSB of the then pointer. The global + visited flag uses the LSB of the next pointer. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddInitInteract( + DdManager * table) +{ + int i,j,k; + int words; + long *interact; + int *support; + DdNode *f; + DdNode *sentinel = &(table->sentinel); + DdNodePtr *nodelist; + int slots; + int n = table->size; + + words = ((n * (n-1)) >> (1 + LOGBPL)) + 1; + table->interact = interact = ALLOC(long,words); + if (interact == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (i = 0; i < words; i++) { + interact[i] = 0; + } + + support = ALLOC(int,n); + if (support == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + FREE(interact); + return(0); + } + + for (i = 0; i < n; i++) { + nodelist = table->subtables[i].nodelist; + slots = table->subtables[i].slots; + for (j = 0; j < slots; j++) { + f = nodelist[j]; + while (f != sentinel) { + /* A node is a root of the DAG if it cannot be + ** reached by nodes above it. If a node was never + ** reached during the previous depth-first searches, + ** then it is a root, and we start a new depth-first + ** search from it. + */ + if (!Cudd_IsComplement(f->next)) { + for (k = 0; k < n; k++) { + support[k] = 0; + } + ddSuppInteract(f,support); + ddClearLocal(f); + ddUpdateInteract(table,support); + } + f = Cudd_Regular(f->next); + } + } + } + ddClearGlobal(table); + + FREE(support); + return(1); + +} /* end of cuddInitInteract */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Find the support of f.] + + Description [Performs a DFS from f. Uses the LSB of the then pointer + as visited flag.] + + SideEffects [Accumulates in support the variables on which f depends.] + + SeeAlso [] + +******************************************************************************/ +static void +ddSuppInteract( + DdNode * f, + int * support) +{ + if (cuddIsConstant(f) || Cudd_IsComplement(cuddT(f))) { + return; + } + + support[f->index] = 1; + ddSuppInteract(cuddT(f),support); + ddSuppInteract(Cudd_Regular(cuddE(f)),support); + /* mark as visited */ + cuddT(f) = Cudd_Complement(cuddT(f)); + f->next = Cudd_Complement(f->next); + return; + +} /* end of ddSuppInteract */ + + +/**Function******************************************************************** + + Synopsis [Performs a DFS from f, clearing the LSB of the then pointers.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +ddClearLocal( + DdNode * f) +{ + if (cuddIsConstant(f) || !Cudd_IsComplement(cuddT(f))) { + return; + } + /* clear visited flag */ + cuddT(f) = Cudd_Regular(cuddT(f)); + ddClearLocal(cuddT(f)); + ddClearLocal(Cudd_Regular(cuddE(f))); + return; + +} /* end of ddClearLocal */ + + +/**Function******************************************************************** + + Synopsis [Marks as interacting all pairs of variables that appear in + support.] + + Description [If support[i] == support[j] == 1, sets the (i,j) entry + of the interaction matrix to 1.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +ddUpdateInteract( + DdManager * table, + int * support) +{ + int i,j; + int n = table->size; + + for (i = 0; i < n-1; i++) { + if (support[i] == 1) { + for (j = i+1; j < n; j++) { + if (support[j] == 1) { + cuddSetInteract(table,i,j); + } + } + } + } + +} /* end of ddUpdateInteract */ + + +/**Function******************************************************************** + + Synopsis [Scans the DD and clears the LSB of the next pointers.] + + Description [The LSB of the next pointers are used as markers to tell + whether a node was reached by at least one DFS. Once the interaction + matrix is built, these flags are reset.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +ddClearGlobal( + DdManager * table) +{ + int i,j; + DdNode *f; + DdNode *sentinel = &(table->sentinel); + DdNodePtr *nodelist; + int slots; + + for (i = 0; i < table->size; i++) { + nodelist = table->subtables[i].nodelist; + slots = table->subtables[i].slots; + for (j = 0; j < slots; j++) { + f = nodelist[j]; + while (f != sentinel) { + f->next = Cudd_Regular(f->next); + f = f->next; + } + } + } + +} /* end of ddClearGlobal */ + diff --git a/abc70930/src/bdd/cudd/cuddLCache.c b/abc70930/src/bdd/cudd/cuddLCache.c new file mode 100644 index 00000000..8bd37ba0 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddLCache.c @@ -0,0 +1,1428 @@ +/**CFile*********************************************************************** + + FileName [cuddLCache.c] + + PackageName [cudd] + + Synopsis [Functions for local caches.] + + Description [Internal procedures included in this module: +

        +
      • cuddLocalCacheInit() +
      • cuddLocalCacheQuit() +
      • cuddLocalCacheInsert() +
      • cuddLocalCacheLookup() +
      • cuddLocalCacheClearDead() +
      • cuddLocalCacheClearAll() +
      • cuddLocalCacheProfile() +
      • cuddHashTableInit() +
      • cuddHashTableQuit() +
      • cuddHashTableInsert() +
      • cuddHashTableLookup() +
      • cuddHashTableInsert2() +
      • cuddHashTableLookup2() +
      • cuddHashTableInsert3() +
      • cuddHashTableLookup3() +
      + Static procedures included in this module: +
        +
      • cuddLocalCacheResize() +
      • ddLCHash() +
      • cuddLocalCacheAddToList() +
      • cuddLocalCacheRemoveFromList() +
      • cuddHashTableResize() +
      • cuddHashTableAlloc() +
      ] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define DD_MAX_HASHTABLE_DENSITY 2 /* tells when to resize a table */ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddLCache.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**Macro*********************************************************************** + + Synopsis [Computes hash function for keys of two operands.] + + Description [] + + SideEffects [None] + + SeeAlso [ddLCHash3 ddLCHash] + +******************************************************************************/ +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +#define ddLCHash2(f,g,shift) \ +((((unsigned)(unsigned long)(f) * DD_P1 + \ + (unsigned)(unsigned long)(g)) * DD_P2) >> (shift)) +#else +#define ddLCHash2(f,g,shift) \ +((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (shift)) +#endif + + +/**Macro*********************************************************************** + + Synopsis [Computes hash function for keys of three operands.] + + Description [] + + SideEffects [None] + + SeeAlso [ddLCHash2 ddLCHash] + +******************************************************************************/ +#define ddLCHash3(f,g,h,shift) ddCHash2(f,g,h,shift) + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void cuddLocalCacheResize ARGS((DdLocalCache *cache)); +DD_INLINE static unsigned int ddLCHash ARGS((DdNodePtr *key, unsigned int keysize, int shift)); +static void cuddLocalCacheAddToList ARGS((DdLocalCache *cache)); +static void cuddLocalCacheRemoveFromList ARGS((DdLocalCache *cache)); +static int cuddHashTableResize ARGS((DdHashTable *hash)); +DD_INLINE static DdHashItem * cuddHashTableAlloc ARGS((DdHashTable *hash)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Initializes a local computed table.] + + Description [Initializes a computed table. Returns a pointer the + the new local cache in case of success; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddInitCache] + +******************************************************************************/ +DdLocalCache * +cuddLocalCacheInit( + DdManager * manager /* manager */, + unsigned int keySize /* size of the key (number of operands) */, + unsigned int cacheSize /* Initial size of the cache */, + unsigned int maxCacheSize /* Size of the cache beyond which no resizing occurs */) +{ + DdLocalCache *cache; + int logSize; + + cache = ALLOC(DdLocalCache,1); + if (cache == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + cache->manager = manager; + cache->keysize = keySize; + cache->itemsize = (keySize + 1) * sizeof(DdNode *); +#ifdef DD_CACHE_PROFILE + cache->itemsize += sizeof(ptrint); +#endif + logSize = cuddComputeFloorLog2(ddMax(cacheSize,manager->slots/2)); + cacheSize = 1 << logSize; + cache->item = (DdLocalCacheItem *) + ALLOC(char, cacheSize * cache->itemsize); + if (cache->item == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + FREE(cache); + return(NULL); + } + cache->slots = cacheSize; + cache->shift = sizeof(int) * 8 - logSize; + cache->maxslots = ddMin(maxCacheSize,manager->slots); + cache->minHit = manager->minHit; + /* Initialize to avoid division by 0 and immediate resizing. */ + cache->lookUps = (double) (int) (cacheSize * cache->minHit + 1); + cache->hits = 0; + manager->memused += cacheSize * cache->itemsize + sizeof(DdLocalCache); + + /* Initialize the cache. */ + memset(cache->item, 0, cacheSize * cache->itemsize); + + /* Add to manager's list of local caches for GC. */ + cuddLocalCacheAddToList(cache); + + return(cache); + +} /* end of cuddLocalCacheInit */ + + +/**Function******************************************************************** + + Synopsis [Shuts down a local computed table.] + + Description [Initializes the computed table. It is called by + Cudd_Init. Returns a pointer the the new local cache in case of + success; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddLocalCacheInit] + +******************************************************************************/ +void +cuddLocalCacheQuit( + DdLocalCache * cache /* cache to be shut down */) +{ + cache->manager->memused -= + cache->slots * cache->itemsize + sizeof(DdLocalCache); + cuddLocalCacheRemoveFromList(cache); + FREE(cache->item); + FREE(cache); + + return; + +} /* end of cuddLocalCacheQuit */ + + +/**Function******************************************************************** + + Synopsis [Inserts a result in a local cache.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +cuddLocalCacheInsert( + DdLocalCache * cache, + DdNodePtr * key, + DdNode * value) +{ + unsigned int posn; + DdLocalCacheItem *entry; + + posn = ddLCHash(key,cache->keysize,cache->shift); + entry = (DdLocalCacheItem *) ((char *) cache->item + + posn * cache->itemsize); + memcpy(entry->key,key,cache->keysize * sizeof(DdNode *)); + entry->value = value; +#ifdef DD_CACHE_PROFILE + entry->count++; +#endif + +} /* end of cuddLocalCacheInsert */ + + +/**Function******************************************************************** + + Synopsis [Looks up in a local cache.] + + Description [Looks up in a local cache. Returns the result if found; + it returns NULL if no result is found.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddLocalCacheLookup( + DdLocalCache * cache, + DdNodePtr * key) +{ + unsigned int posn; + DdLocalCacheItem *entry; + DdNode *value; + + cache->lookUps++; + posn = ddLCHash(key,cache->keysize,cache->shift); + entry = (DdLocalCacheItem *) ((char *) cache->item + + posn * cache->itemsize); + if (entry->value != NULL && + memcmp(key,entry->key,cache->keysize*sizeof(DdNode *)) == 0) { + cache->hits++; + value = Cudd_Regular(entry->value); + if (value->ref == 0) { + cuddReclaim(cache->manager,value); + } + return(entry->value); + } + + /* Cache miss: decide whether to resize */ + + if (cache->slots < cache->maxslots && + cache->hits > cache->lookUps * cache->minHit) { + cuddLocalCacheResize(cache); + } + + return(NULL); + +} /* end of cuddLocalCacheLookup */ + + +/**Function******************************************************************** + + Synopsis [Clears the dead entries of the local caches of a manager.] + + Description [Clears the dead entries of the local caches of a manager. + Used during garbage collection.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +cuddLocalCacheClearDead( + DdManager * manager) +{ + DdLocalCache *cache = manager->localCaches; + unsigned int keysize; + unsigned int itemsize; + unsigned int slots; + DdLocalCacheItem *item; + DdNodePtr *key; + unsigned int i, j; + + while (cache != NULL) { + keysize = cache->keysize; + itemsize = cache->itemsize; + slots = cache->slots; + item = cache->item; + for (i = 0; i < slots; i++) { + if (item->value != NULL && Cudd_Regular(item->value)->ref == 0) { + item->value = NULL; + } else { + key = item->key; + for (j = 0; j < keysize; j++) { + if (Cudd_Regular(key[j])->ref == 0) { + item->value = NULL; + break; + } + } + } + item = (DdLocalCacheItem *) ((char *) item + itemsize); + } + cache = cache->next; + } + return; + +} /* end of cuddLocalCacheClearDead */ + + +/**Function******************************************************************** + + Synopsis [Clears the local caches of a manager.] + + Description [Clears the local caches of a manager. + Used before reordering.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +cuddLocalCacheClearAll( + DdManager * manager) +{ + DdLocalCache *cache = manager->localCaches; + + while (cache != NULL) { + memset(cache->item, 0, cache->slots * cache->itemsize); + cache = cache->next; + } + return; + +} /* end of cuddLocalCacheClearAll */ + + +#ifdef DD_CACHE_PROFILE + +#define DD_HYSTO_BINS 8 + +/**Function******************************************************************** + + Synopsis [Computes and prints a profile of a local cache usage.] + + Description [Computes and prints a profile of a local cache usage. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddLocalCacheProfile( + DdLocalCache * cache) +{ + double count, mean, meansq, stddev, expected; + long max, min; + int imax, imin; + int i, retval, slots; + long *hystogram; + int nbins = DD_HYSTO_BINS; + int bin; + long thiscount; + double totalcount; + int nzeroes; + DdLocalCacheItem *entry; + FILE *fp = cache->manager->out; + + slots = cache->slots; + + meansq = mean = expected = 0.0; + max = min = (long) cache->item[0].count; + imax = imin = nzeroes = 0; + totalcount = 0.0; + + hystogram = ALLOC(long, nbins); + if (hystogram == NULL) { + return(0); + } + for (i = 0; i < nbins; i++) { + hystogram[i] = 0; + } + + for (i = 0; i < slots; i++) { + entry = (DdLocalCacheItem *) ((char *) cache->item + + i * cache->itemsize); + thiscount = (long) entry->count; + if (thiscount > max) { + max = thiscount; + imax = i; + } + if (thiscount < min) { + min = thiscount; + imin = i; + } + if (thiscount == 0) { + nzeroes++; + } + count = (double) thiscount; + mean += count; + meansq += count * count; + totalcount += count; + expected += count * (double) i; + bin = (i * nbins) / slots; + hystogram[bin] += thiscount; + } + mean /= (double) slots; + meansq /= (double) slots; + stddev = sqrt(meansq - mean*mean); + + retval = fprintf(fp,"Cache stats: slots = %d average = %g ", slots, mean); + if (retval == EOF) return(0); + retval = fprintf(fp,"standard deviation = %g\n", stddev); + if (retval == EOF) return(0); + retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax); + if (retval == EOF) return(0); + retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin); + if (retval == EOF) return(0); + retval = fprintf(fp,"Cache unused slots = %d\n", nzeroes); + if (retval == EOF) return(0); + + if (totalcount) { + expected /= totalcount; + retval = fprintf(fp,"Cache access hystogram for %d bins", nbins); + if (retval == EOF) return(0); + retval = fprintf(fp," (expected bin value = %g)\n# ", expected); + if (retval == EOF) return(0); + for (i = nbins - 1; i>=0; i--) { + retval = fprintf(fp,"%ld ", hystogram[i]); + if (retval == EOF) return(0); + } + retval = fprintf(fp,"\n"); + if (retval == EOF) return(0); + } + + FREE(hystogram); + return(1); + +} /* end of cuddLocalCacheProfile */ +#endif + + +/**Function******************************************************************** + + Synopsis [Initializes a hash table.] + + Description [Initializes a hash table. Returns a pointer to the new + table if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddHashTableQuit] + +******************************************************************************/ +DdHashTable * +cuddHashTableInit( + DdManager * manager, + unsigned int keySize, + unsigned int initSize) +{ + DdHashTable *hash; + int logSize; + +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + hash = ALLOC(DdHashTable, 1); + if (hash == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + hash->keysize = keySize; + hash->manager = manager; + hash->memoryList = NULL; + hash->nextFree = NULL; + hash->itemsize = (keySize + 1) * sizeof(DdNode *) + + sizeof(ptrint) + sizeof(DdHashItem *); + /* We have to guarantee that the shift be < 32. */ + if (initSize < 2) initSize = 2; + logSize = cuddComputeFloorLog2(initSize); + hash->numBuckets = 1 << logSize; + hash->shift = sizeof(int) * 8 - logSize; + hash->bucket = ALLOC(DdHashItem *, hash->numBuckets); + if (hash->bucket == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + FREE(hash); + return(NULL); + } + memset(hash->bucket, 0, hash->numBuckets * sizeof(DdHashItem *)); + hash->size = 0; + hash->maxsize = hash->numBuckets * DD_MAX_HASHTABLE_DENSITY; +#ifdef __osf__ +#pragma pointer_size restore +#endif + return(hash); + +} /* end of cuddHashTableInit */ + + +/**Function******************************************************************** + + Synopsis [Shuts down a hash table.] + + Description [Shuts down a hash table, dereferencing all the values.] + + SideEffects [None] + + SeeAlso [cuddHashTableInit] + +******************************************************************************/ +void +cuddHashTableQuit( + DdHashTable * hash) +{ +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + unsigned int i; + DdManager *dd = hash->manager; + DdHashItem *bucket; + DdHashItem **memlist, **nextmem; + unsigned int numBuckets = hash->numBuckets; + + for (i = 0; i < numBuckets; i++) { + bucket = hash->bucket[i]; + while (bucket != NULL) { + Cudd_RecursiveDeref(dd, bucket->value); + bucket = bucket->next; + } + } + + memlist = hash->memoryList; + while (memlist != NULL) { + nextmem = (DdHashItem **) memlist[0]; + FREE(memlist); + memlist = nextmem; + } + + FREE(hash->bucket); + FREE(hash); +#ifdef __osf__ +#pragma pointer_size restore +#endif + + return; + +} /* end of cuddHashTableQuit */ + + +/**Function******************************************************************** + + Synopsis [Inserts an item in a hash table.] + + Description [Inserts an item in a hash table when the key has more than + three pointers. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [[cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableInsert3 + cuddHashTableLookup] + +******************************************************************************/ +int +cuddHashTableInsert( + DdHashTable * hash, + DdNodePtr * key, + DdNode * value, + ptrint count) +{ + int result; + unsigned int posn; + DdHashItem *item; + unsigned int i; + +#ifdef DD_DEBUG + assert(hash->keysize > 3); +#endif + + if (hash->size > hash->maxsize) { + result = cuddHashTableResize(hash); + if (result == 0) return(0); + } + item = cuddHashTableAlloc(hash); + if (item == NULL) return(0); + hash->size++; + item->value = value; + cuddRef(value); + item->count = count; + for (i = 0; i < hash->keysize; i++) { + item->key[i] = key[i]; + } + posn = ddLCHash(key,hash->keysize,hash->shift); + item->next = hash->bucket[posn]; + hash->bucket[posn] = item; + + return(1); + +} /* end of cuddHashTableInsert */ + + +/**Function******************************************************************** + + Synopsis [Looks up a key in a hash table.] + + Description [Looks up a key consisting of more than three pointers + in a hash table. Returns the value associated to the key if there + is an entry for the given key in the table; NULL otherwise. If the + entry is present, its reference counter is decremented if not + saturated. If the counter reaches 0, the value of the entry is + dereferenced, and the entry is returned to the free list.] + + SideEffects [None] + + SeeAlso [cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableLookup3 + cuddHashTableInsert] + +******************************************************************************/ +DdNode * +cuddHashTableLookup( + DdHashTable * hash, + DdNodePtr * key) +{ + unsigned int posn; + DdHashItem *item, *prev; + unsigned int i, keysize; + +#ifdef DD_DEBUG + assert(hash->keysize > 3); +#endif + + posn = ddLCHash(key,hash->keysize,hash->shift); + item = hash->bucket[posn]; + prev = NULL; + + keysize = hash->keysize; + while (item != NULL) { + DdNodePtr *key2 = item->key; + int equal = 1; + for (i = 0; i < keysize; i++) { + if (key[i] != key2[i]) { + equal = 0; + break; + } + } + if (equal) { + DdNode *value = item->value; + cuddSatDec(item->count); + if (item->count == 0) { + cuddDeref(value); + if (prev == NULL) { + hash->bucket[posn] = item->next; + } else { + prev->next = item->next; + } + item->next = hash->nextFree; + hash->nextFree = item; + hash->size--; + } + return(value); + } + prev = item; + item = item->next; + } + return(NULL); + +} /* end of cuddHashTableLookup */ + + +/**Function******************************************************************** + + Synopsis [Inserts an item in a hash table.] + + Description [Inserts an item in a hash table when the key is one pointer. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [cuddHashTableInsert cuddHashTableInsert2 cuddHashTableInsert3 + cuddHashTableLookup1] + +******************************************************************************/ +int +cuddHashTableInsert1( + DdHashTable * hash, + DdNode * f, + DdNode * value, + ptrint count) +{ + int result; + unsigned int posn; + DdHashItem *item; + +#ifdef DD_DEBUG + assert(hash->keysize == 1); +#endif + + if (hash->size > hash->maxsize) { + result = cuddHashTableResize(hash); + if (result == 0) return(0); + } + item = cuddHashTableAlloc(hash); + if (item == NULL) return(0); + hash->size++; + item->value = value; + cuddRef(value); + item->count = count; + item->key[0] = f; + posn = ddLCHash2(f,f,hash->shift); + item->next = hash->bucket[posn]; + hash->bucket[posn] = item; + + return(1); + +} /* end of cuddHashTableInsert1 */ + + +/**Function******************************************************************** + + Synopsis [Looks up a key consisting of one pointer in a hash table.] + + Description [Looks up a key consisting of one pointer in a hash table. + Returns the value associated to the key if there is an entry for the given + key in the table; NULL otherwise. If the entry is present, its reference + counter is decremented if not saturated. If the counter reaches 0, the + value of the entry is dereferenced, and the entry is returned to the free + list.] + + SideEffects [None] + + SeeAlso [cuddHashTableLookup cuddHashTableLookup2 cuddHashTableLookup3 + cuddHashTableInsert1] + +******************************************************************************/ +DdNode * +cuddHashTableLookup1( + DdHashTable * hash, + DdNode * f) +{ + unsigned int posn; + DdHashItem *item, *prev; + +#ifdef DD_DEBUG + assert(hash->keysize == 1); +#endif + + posn = ddLCHash2(f,f,hash->shift); + item = hash->bucket[posn]; + prev = NULL; + + while (item != NULL) { + DdNodePtr *key = item->key; + if (f == key[0]) { + DdNode *value = item->value; + cuddSatDec(item->count); + if (item->count == 0) { + cuddDeref(value); + if (prev == NULL) { + hash->bucket[posn] = item->next; + } else { + prev->next = item->next; + } + item->next = hash->nextFree; + hash->nextFree = item; + hash->size--; + } + return(value); + } + prev = item; + item = item->next; + } + return(NULL); + +} /* end of cuddHashTableLookup1 */ + + +/**Function******************************************************************** + + Synopsis [Inserts an item in a hash table.] + + Description [Inserts an item in a hash table when the key is + composed of two pointers. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert3 + cuddHashTableLookup2] + +******************************************************************************/ +int +cuddHashTableInsert2( + DdHashTable * hash, + DdNode * f, + DdNode * g, + DdNode * value, + ptrint count) +{ + int result; + unsigned int posn; + DdHashItem *item; + +#ifdef DD_DEBUG + assert(hash->keysize == 2); +#endif + + if (hash->size > hash->maxsize) { + result = cuddHashTableResize(hash); + if (result == 0) return(0); + } + item = cuddHashTableAlloc(hash); + if (item == NULL) return(0); + hash->size++; + item->value = value; + cuddRef(value); + item->count = count; + item->key[0] = f; + item->key[1] = g; + posn = ddLCHash2(f,g,hash->shift); + item->next = hash->bucket[posn]; + hash->bucket[posn] = item; + + return(1); + +} /* end of cuddHashTableInsert2 */ + + +/**Function******************************************************************** + + Synopsis [Looks up a key consisting of two pointers in a hash table.] + + Description [Looks up a key consisting of two pointer in a hash table. + Returns the value associated to the key if there is an entry for the given + key in the table; NULL otherwise. If the entry is present, its reference + counter is decremented if not saturated. If the counter reaches 0, the + value of the entry is dereferenced, and the entry is returned to the free + list.] + + SideEffects [None] + + SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup3 + cuddHashTableInsert2] + +******************************************************************************/ +DdNode * +cuddHashTableLookup2( + DdHashTable * hash, + DdNode * f, + DdNode * g) +{ + unsigned int posn; + DdHashItem *item, *prev; + +#ifdef DD_DEBUG + assert(hash->keysize == 2); +#endif + + posn = ddLCHash2(f,g,hash->shift); + item = hash->bucket[posn]; + prev = NULL; + + while (item != NULL) { + DdNodePtr *key = item->key; + if ((f == key[0]) && (g == key[1])) { + DdNode *value = item->value; + cuddSatDec(item->count); + if (item->count == 0) { + cuddDeref(value); + if (prev == NULL) { + hash->bucket[posn] = item->next; + } else { + prev->next = item->next; + } + item->next = hash->nextFree; + hash->nextFree = item; + hash->size--; + } + return(value); + } + prev = item; + item = item->next; + } + return(NULL); + +} /* end of cuddHashTableLookup2 */ + + +/**Function******************************************************************** + + Synopsis [Inserts an item in a hash table.] + + Description [Inserts an item in a hash table when the key is + composed of three pointers. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert2 + cuddHashTableLookup3] + +******************************************************************************/ +int +cuddHashTableInsert3( + DdHashTable * hash, + DdNode * f, + DdNode * g, + DdNode * h, + DdNode * value, + ptrint count) +{ + int result; + unsigned int posn; + DdHashItem *item; + +#ifdef DD_DEBUG + assert(hash->keysize == 3); +#endif + + if (hash->size > hash->maxsize) { + result = cuddHashTableResize(hash); + if (result == 0) return(0); + } + item = cuddHashTableAlloc(hash); + if (item == NULL) return(0); + hash->size++; + item->value = value; + cuddRef(value); + item->count = count; + item->key[0] = f; + item->key[1] = g; + item->key[2] = h; + posn = ddLCHash3(f,g,h,hash->shift); + item->next = hash->bucket[posn]; + hash->bucket[posn] = item; + + return(1); + +} /* end of cuddHashTableInsert3 */ + + +/**Function******************************************************************** + + Synopsis [Looks up a key consisting of three pointers in a hash table.] + + Description [Looks up a key consisting of three pointers in a hash table. + Returns the value associated to the key if there is an entry for the given + key in the table; NULL otherwise. If the entry is present, its reference + counter is decremented if not saturated. If the counter reaches 0, the + value of the entry is dereferenced, and the entry is returned to the free + list.] + + SideEffects [None] + + SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup2 + cuddHashTableInsert3] + +******************************************************************************/ +DdNode * +cuddHashTableLookup3( + DdHashTable * hash, + DdNode * f, + DdNode * g, + DdNode * h) +{ + unsigned int posn; + DdHashItem *item, *prev; + +#ifdef DD_DEBUG + assert(hash->keysize == 3); +#endif + + posn = ddLCHash3(f,g,h,hash->shift); + item = hash->bucket[posn]; + prev = NULL; + + while (item != NULL) { + DdNodePtr *key = item->key; + if ((f == key[0]) && (g == key[1]) && (h == key[2])) { + DdNode *value = item->value; + cuddSatDec(item->count); + if (item->count == 0) { + cuddDeref(value); + if (prev == NULL) { + hash->bucket[posn] = item->next; + } else { + prev->next = item->next; + } + item->next = hash->nextFree; + hash->nextFree = item; + hash->size--; + } + return(value); + } + prev = item; + item = item->next; + } + return(NULL); + +} /* end of cuddHashTableLookup3 */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Resizes a local cache.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +cuddLocalCacheResize( + DdLocalCache * cache) +{ + DdLocalCacheItem *item, *olditem, *entry, *old; + int i, shift; + unsigned int posn; + unsigned int slots, oldslots; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); + + olditem = cache->item; + oldslots = cache->slots; + slots = cache->slots = oldslots << 1; + +#ifdef DD_VERBOSE + (void) fprintf(cache->manager->err, + "Resizing local cache from %d to %d entries\n", + oldslots, slots); + (void) fprintf(cache->manager->err, + "\thits = %.0f\tlookups = %.0f\thit ratio = %5.3f\n", + cache->hits, cache->lookUps, cache->hits / cache->lookUps); +#endif + + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + cache->item = item = + (DdLocalCacheItem *) ALLOC(char, slots * cache->itemsize); + MMoutOfMemory = saveHandler; + /* If we fail to allocate the new table we just give up. */ + if (item == NULL) { +#ifdef DD_VERBOSE + (void) fprintf(cache->manager->err,"Resizing failed. Giving up.\n"); +#endif + cache->slots = oldslots; + cache->item = olditem; + /* Do not try to resize again. */ + cache->maxslots = oldslots - 1; + return; + } + shift = --(cache->shift); + cache->manager->memused += (slots - oldslots) * cache->itemsize; + + /* Clear new cache. */ + memset(item, 0, slots * cache->itemsize); + + /* Copy from old cache to new one. */ + for (i = 0; (unsigned) i < oldslots; i++) { + old = (DdLocalCacheItem *) ((char *) olditem + i * cache->itemsize); + if (old->value != NULL) { + posn = ddLCHash(old->key,cache->keysize,slots); + entry = (DdLocalCacheItem *) ((char *) item + + posn * cache->itemsize); + memcpy(entry->key,old->key,cache->keysize*sizeof(DdNode *)); + entry->value = old->value; + } + } + + FREE(olditem); + + /* Reinitialize measurements so as to avoid division by 0 and + ** immediate resizing. + */ + cache->lookUps = (double) (int) (slots * cache->minHit + 1); + cache->hits = 0; + +} /* end of cuddLocalCacheResize */ + + +/**Function******************************************************************** + + Synopsis [Computes the hash value for a local cache.] + + Description [Computes the hash value for a local cache. Returns the + bucket index.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DD_INLINE +static unsigned int +ddLCHash( + DdNodePtr * key, + unsigned int keysize, + int shift) +{ + unsigned int val = (unsigned int) (ptrint) key[0]; + unsigned int i; + + for (i = 1; i < keysize; i++) { + val = val * DD_P1 + (int) (ptrint) key[i]; + } + + return(val >> shift); + +} /* end of ddLCHash */ + + +/**Function******************************************************************** + + Synopsis [Inserts a local cache in the manager list.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +cuddLocalCacheAddToList( + DdLocalCache * cache) +{ + DdManager *manager = cache->manager; + + cache->next = manager->localCaches; + manager->localCaches = cache; + return; + +} /* end of cuddLocalCacheAddToList */ + + +/**Function******************************************************************** + + Synopsis [Removes a local cache from the manager list.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +cuddLocalCacheRemoveFromList( + DdLocalCache * cache) +{ + DdManager *manager = cache->manager; +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + DdLocalCache **prevCache, *nextCache; +#ifdef __osf__ +#pragma pointer_size restore +#endif + + prevCache = &(manager->localCaches); + nextCache = manager->localCaches; + + while (nextCache != NULL) { + if (nextCache == cache) { + *prevCache = nextCache->next; + return; + } + prevCache = &(nextCache->next); + nextCache = nextCache->next; + } + return; /* should never get here */ + +} /* end of cuddLocalCacheRemoveFromList */ + + +/**Function******************************************************************** + + Synopsis [Resizes a hash table.] + + Description [Resizes a hash table. Returns 1 if successful; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [cuddHashTableInsert] + +******************************************************************************/ +static int +cuddHashTableResize( + DdHashTable * hash) +{ + int j; + unsigned int posn; + DdHashItem *item; + DdHashItem *next; +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + DdNode **key; + int numBuckets; + DdHashItem **buckets; + DdHashItem **oldBuckets = hash->bucket; +#ifdef __osf__ +#pragma pointer_size restore +#endif + int shift; + int oldNumBuckets = hash->numBuckets; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); + + /* Compute the new size of the table. */ + numBuckets = oldNumBuckets << 1; + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + buckets = ALLOC(DdHashItem *, numBuckets); + MMoutOfMemory = saveHandler; + if (buckets == NULL) { + hash->maxsize <<= 1; + return(1); + } + + hash->bucket = buckets; + hash->numBuckets = numBuckets; + shift = --(hash->shift); + hash->maxsize <<= 1; + memset(buckets, 0, numBuckets * sizeof(DdHashItem *)); +#ifdef __osf__ +#pragma pointer_size restore +#endif + if (hash->keysize == 1) { + for (j = 0; j < oldNumBuckets; j++) { + item = oldBuckets[j]; + while (item != NULL) { + next = item->next; + key = item->key; + posn = ddLCHash2(key[0], key[0], shift); + item->next = buckets[posn]; + buckets[posn] = item; + item = next; + } + } + } else if (hash->keysize == 2) { + for (j = 0; j < oldNumBuckets; j++) { + item = oldBuckets[j]; + while (item != NULL) { + next = item->next; + key = item->key; + posn = ddLCHash2(key[0], key[1], shift); + item->next = buckets[posn]; + buckets[posn] = item; + item = next; + } + } + } else if (hash->keysize == 3) { + for (j = 0; j < oldNumBuckets; j++) { + item = oldBuckets[j]; + while (item != NULL) { + next = item->next; + key = item->key; + posn = ddLCHash3(key[0], key[1], key[2], shift); + item->next = buckets[posn]; + buckets[posn] = item; + item = next; + } + } + } else { + for (j = 0; j < oldNumBuckets; j++) { + item = oldBuckets[j]; + while (item != NULL) { + next = item->next; + posn = ddLCHash(item->key, hash->keysize, shift); + item->next = buckets[posn]; + buckets[posn] = item; + item = next; + } + } + } + FREE(oldBuckets); + return(1); + +} /* end of cuddHashTableResize */ + + +/**Function******************************************************************** + + Synopsis [Fast storage allocation for items in a hash table.] + + Description [Fast storage allocation for items in a hash table. The + first 4 bytes of a chunk contain a pointer to the next block; the + rest contains DD_MEM_CHUNK spaces for hash items. Returns a pointer to + a new item if successful; NULL is memory is full.] + + SideEffects [None] + + SeeAlso [cuddAllocNode cuddDynamicAllocNode] + +******************************************************************************/ +DD_INLINE +static DdHashItem * +cuddHashTableAlloc( + DdHashTable * hash) +{ + int i; + unsigned int itemsize = hash->itemsize; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + DdHashItem **mem, *thisOne, *next, *item; + + if (hash->nextFree == NULL) { + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize); + MMoutOfMemory = saveHandler; +#ifdef __osf__ +#pragma pointer_size restore +#endif + if (mem == NULL) { + if (hash->manager->stash != NULL) { + FREE(hash->manager->stash); + hash->manager->stash = NULL; + /* Inhibit resizing of tables. */ + hash->manager->maxCacheHard = hash->manager->cacheSlots - 1; + hash->manager->cacheSlack = -(hash->manager->cacheSlots + 1); + for (i = 0; i < hash->manager->size; i++) { + hash->manager->subtables[i].maxKeys <<= 2; + } + hash->manager->gcFrac = 0.2; + hash->manager->minDead = + (unsigned) (0.2 * (double) hash->manager->slots); +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize); +#ifdef __osf__ +#pragma pointer_size restore +#endif + } + if (mem == NULL) { + (*MMoutOfMemory)((DD_MEM_CHUNK + 1) * itemsize); + hash->manager->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + } + + mem[0] = (DdHashItem *) hash->memoryList; + hash->memoryList = mem; + + thisOne = (DdHashItem *) ((char *) mem + itemsize); + hash->nextFree = thisOne; + for (i = 1; i < DD_MEM_CHUNK; i++) { + next = (DdHashItem *) ((char *) thisOne + itemsize); + thisOne->next = next; + thisOne = next; + } + + thisOne->next = NULL; + + } + item = hash->nextFree; + hash->nextFree = item->next; + return(item); + +} /* end of cuddHashTableAlloc */ diff --git a/abc70930/src/bdd/cudd/cuddLevelQ.c b/abc70930/src/bdd/cudd/cuddLevelQ.c new file mode 100644 index 00000000..3cc8e8d8 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddLevelQ.c @@ -0,0 +1,533 @@ +/**CFile*********************************************************************** + + FileName [cuddLevelQ.c] + + PackageName [cudd] + + Synopsis [Procedure to manage level queues.] + + Description [The functions in this file allow an application to + easily manipulate a queue where nodes are prioritized by level. The + emphasis is on efficiency. Therefore, the queue items can have + variable size. If the application does not need to attach + information to the nodes, it can declare the queue items to be of + type DdQueueItem. Otherwise, it can declare them to be of a + structure type such that the first three fields are data + pointers. The third pointer points to the node. The first two + pointers are used by the level queue functions. The remaining fields + are initialized to 0 when a new item is created, and are then left + to the exclusive use of the application. On the DEC Alphas the three + pointers must be 32-bit pointers when CUDD is compiled with 32-bit + pointers. The level queue functions make sure that each node + appears at most once in the queue. They do so by keeping a hash + table where the node is used as key. Queue items are recycled via a + free list for efficiency. + + Internal procedures provided by this module: +
        +
      • cuddLevelQueueInit() +
      • cuddLevelQueueQuit() +
      • cuddLevelQueueEnqueue() +
      • cuddLevelQueueDequeue() +
      + Static procedures included in this module: +
        +
      • hashLookup() +
      • hashInsert() +
      • hashDelete() +
      • hashResize() +
      + ] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no + warranty about the suitability of this software for any + purpose. It is presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddLevelQ.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**Macro*********************************************************************** + + Synopsis [Hash function for the table of a level queue.] + + Description [Hash function for the table of a level queue.] + + SideEffects [None] + + SeeAlso [hashInsert hashLookup hashDelete] + +******************************************************************************/ +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +#define lqHash(key,shift) \ +(((unsigned)(unsigned long)(key) * DD_P1) >> (shift)) +#else +#define lqHash(key,shift) \ +(((unsigned)(key) * DD_P1) >> (shift)) +#endif + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdQueueItem * hashLookup ARGS((DdLevelQueue *queue, void *key)); +static int hashInsert ARGS((DdLevelQueue *queue, DdQueueItem *item)); +static void hashDelete ARGS((DdLevelQueue *queue, DdQueueItem *item)); +static int hashResize ARGS((DdLevelQueue *queue)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Initializes a level queue.] + + Description [Initializes a level queue. A level queue is a queue + where inserts are based on the levels of the nodes. Within each + level the policy is FIFO. Level queues are useful in traversing a + BDD top-down. Queue items are kept in a free list when dequeued for + efficiency. Returns a pointer to the new queue if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [cuddLevelQueueQuit cuddLevelQueueEnqueue cuddLevelQueueDequeue] + +******************************************************************************/ +DdLevelQueue * +cuddLevelQueueInit( + int levels /* number of levels */, + int itemSize /* size of the item */, + int numBuckets /* initial number of hash buckets */) +{ + DdLevelQueue *queue; + int logSize; + + queue = ALLOC(DdLevelQueue,1); + if (queue == NULL) + return(NULL); +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + /* Keep pointers to the insertion points for all levels. */ + queue->last = ALLOC(DdQueueItem *, levels); +#ifdef __osf__ +#pragma pointer_size restore +#endif + if (queue->last == NULL) { + FREE(queue); + return(NULL); + } + /* Use a hash table to test for uniqueness. */ + if (numBuckets < 2) numBuckets = 2; + logSize = cuddComputeFloorLog2(numBuckets); + queue->numBuckets = 1 << logSize; + queue->shift = sizeof(int) * 8 - logSize; +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + queue->buckets = ALLOC(DdQueueItem *, queue->numBuckets); +#ifdef __osf__ +#pragma pointer_size restore +#endif + if (queue->buckets == NULL) { + FREE(queue->last); + FREE(queue); + return(NULL); + } +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + memset(queue->last, 0, levels * sizeof(DdQueueItem *)); + memset(queue->buckets, 0, queue->numBuckets * sizeof(DdQueueItem *)); +#ifdef __osf__ +#pragma pointer_size restore +#endif + queue->first = NULL; + queue->freelist = NULL; + queue->levels = levels; + queue->itemsize = itemSize; + queue->size = 0; + queue->maxsize = queue->numBuckets * DD_MAX_SUBTABLE_DENSITY; + return(queue); + +} /* end of cuddLevelQueueInit */ + + +/**Function******************************************************************** + + Synopsis [Shuts down a level queue.] + + Description [Shuts down a level queue and releases all the + associated memory.] + + SideEffects [None] + + SeeAlso [cuddLevelQueueInit] + +******************************************************************************/ +void +cuddLevelQueueQuit( + DdLevelQueue * queue) +{ + DdQueueItem *item; + + while (queue->freelist != NULL) { + item = queue->freelist; + queue->freelist = item->next; + FREE(item); + } + while (queue->first != NULL) { + item = (DdQueueItem *) queue->first; + queue->first = item->next; + FREE(item); + } + FREE(queue->buckets); + FREE(queue->last); + FREE(queue); + return; + +} /* end of cuddLevelQueueQuit */ + + +/**Function******************************************************************** + + Synopsis [Inserts a new key in a level queue.] + + Description [Inserts a new key in a level queue. A new entry is + created in the queue only if the node is not already + enqueued. Returns a pointer to the queue item if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [cuddLevelQueueInit cuddLevelQueueDequeue] + +******************************************************************************/ +void * +cuddLevelQueueEnqueue( + DdLevelQueue * queue /* level queue */, + void * key /* key to be enqueued */, + int level /* level at which to insert */) +{ + int plevel; + DdQueueItem *item; + +#ifdef DD_DEBUG + assert(level < queue->levels); +#endif + /* Check whether entry for this node exists. */ + item = hashLookup(queue,key); + if (item != NULL) return(item); + + /* Get a free item from either the free list or the memory manager. */ + if (queue->freelist == NULL) { + item = (DdQueueItem *) ALLOC(char, queue->itemsize); + if (item == NULL) + return(NULL); + } else { + item = queue->freelist; + queue->freelist = item->next; + } + /* Initialize. */ + memset(item, 0, queue->itemsize); + item->key = key; + /* Update stats. */ + queue->size++; + + if (queue->last[level]) { + /* There are already items for this level in the queue. */ + item->next = queue->last[level]->next; + queue->last[level]->next = item; + } else { + /* There are no items at the current level. Look for the first + ** non-empty level preceeding this one. */ + plevel = level; + while (plevel != 0 && queue->last[plevel] == NULL) + plevel--; + if (queue->last[plevel] == NULL) { + /* No element precedes this one in the queue. */ + item->next = (DdQueueItem *) queue->first; + queue->first = item; + } else { + item->next = queue->last[plevel]->next; + queue->last[plevel]->next = item; + } + } + queue->last[level] = item; + + /* Insert entry for the key in the hash table. */ + if (hashInsert(queue,item) == 0) { + return(NULL); + } + return(item); + +} /* end of cuddLevelQueueEnqueue */ + + +/**Function******************************************************************** + + Synopsis [Remove an item from the front of a level queue.] + + Description [Remove an item from the front of a level queue.] + + SideEffects [None] + + SeeAlso [cuddLevelQueueEnqueue] + +******************************************************************************/ +void +cuddLevelQueueDequeue( + DdLevelQueue * queue, + int level) +{ + DdQueueItem *item = (DdQueueItem *) queue->first; + + /* Delete from the hash table. */ + hashDelete(queue,item); + + /* Since we delete from the front, if this is the last item for + ** its level, there are no other items for the same level. */ + if (queue->last[level] == item) + queue->last[level] = NULL; + + queue->first = item->next; + /* Put item on the free list. */ + item->next = queue->freelist; + queue->freelist = item; + /* Update stats. */ + queue->size--; + return; + +} /* end of cuddLevelQueueDequeue */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Looks up a key in the hash table of a level queue.] + + Description [Looks up a key in the hash table of a level queue. Returns + a pointer to the item with the given key if the key is found; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [cuddLevelQueueEnqueue hashInsert] + +******************************************************************************/ +static DdQueueItem * +hashLookup( + DdLevelQueue * queue, + void * key) +{ + int posn; + DdQueueItem *item; + + posn = lqHash(key,queue->shift); + item = queue->buckets[posn]; + + while (item != NULL) { + if (item->key == key) { + return(item); + } + item = item->cnext; + } + return(NULL); + +} /* end of hashLookup */ + + +/**Function******************************************************************** + + Synopsis [Inserts an item in the hash table of a level queue.] + + Description [Inserts an item in the hash table of a level queue. Returns + 1 if successful; 0 otherwise. No check is performed to see if an item with + the same key is already in the hash table.] + + SideEffects [None] + + SeeAlso [cuddLevelQueueEnqueue] + +******************************************************************************/ +static int +hashInsert( + DdLevelQueue * queue, + DdQueueItem * item) +{ + int result; + int posn; + + if (queue->size > queue->maxsize) { + result = hashResize(queue); + if (result == 0) return(0); + } + + posn = lqHash(item->key,queue->shift); + item->cnext = queue->buckets[posn]; + queue->buckets[posn] = item; + + return(1); + +} /* end of hashInsert */ + + +/**Function******************************************************************** + + Synopsis [Removes an item from the hash table of a level queue.] + + Description [Removes an item from the hash table of a level queue. + Nothing is done if the item is not in the table.] + + SideEffects [None] + + SeeAlso [cuddLevelQueueDequeue hashInsert] + +******************************************************************************/ +static void +hashDelete( + DdLevelQueue * queue, + DdQueueItem * item) +{ + int posn; + DdQueueItem *prevItem; + + posn = lqHash(item->key,queue->shift); + prevItem = queue->buckets[posn]; + + if (prevItem == NULL) return; + if (prevItem == item) { + queue->buckets[posn] = prevItem->cnext; + return; + } + + while (prevItem->cnext != NULL) { + if (prevItem->cnext == item) { + prevItem->cnext = item->cnext; + return; + } + prevItem = prevItem->cnext; + } + return; + +} /* end of hashDelete */ + + +/**Function******************************************************************** + + Synopsis [Resizes the hash table of a level queue.] + + Description [Resizes the hash table of a level queue. Returns 1 if + successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [hashInsert] + +******************************************************************************/ +static int +hashResize( + DdLevelQueue * queue) +{ + int j; + int posn; + DdQueueItem *item; + DdQueueItem *next; + int numBuckets; +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + DdQueueItem **buckets; + DdQueueItem **oldBuckets = queue->buckets; +#ifdef __osf__ +#pragma pointer_size restore +#endif + int shift; + int oldNumBuckets = queue->numBuckets; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); + + /* Compute the new size of the subtable. */ + numBuckets = oldNumBuckets << 1; + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + buckets = queue->buckets = ALLOC(DdQueueItem *, numBuckets); + if (buckets == NULL) { + queue->maxsize <<= 1; + return(1); + } + + queue->numBuckets = numBuckets; + shift = --(queue->shift); + queue->maxsize <<= 1; + memset(buckets, 0, numBuckets * sizeof(DdQueueItem *)); +#ifdef __osf__ +#pragma pointer_size restore +#endif + for (j = 0; j < oldNumBuckets; j++) { + item = oldBuckets[j]; + while (item != NULL) { + next = item->cnext; + posn = lqHash(item->key, shift); + item->cnext = buckets[posn]; + buckets[posn] = item; + item = next; + } + } + FREE(oldBuckets); + return(1); + +} /* end of hashResize */ diff --git a/abc70930/src/bdd/cudd/cuddLinear.c b/abc70930/src/bdd/cudd/cuddLinear.c new file mode 100644 index 00000000..7f6b3678 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddLinear.c @@ -0,0 +1,1333 @@ +/**CFile*********************************************************************** + + FileName [cuddLinear.c] + + PackageName [cudd] + + Synopsis [Functions for DD reduction by linear transformations.] + + Description [ Internal procedures included in this module: +
        +
      • cuddLinearAndSifting() +
      + Static procedures included in this module: +
        +
      • ddLinearUniqueCompare() +
      • ddLinearAndSiftingAux() +
      • ddLinearAndSiftingUp() +
      • ddLinearAndSiftingDown() +
      • ddLinearAndSiftingBackward() +
      • ddUndoMoves() +
      • ddUpdateInteractionMatrix() +
      • cuddLinearInPlace() +
      • cuddInitLinear() +
      • cuddResizeLinear() +
      • cuddXorLinear() +
      ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define CUDD_SWAP_MOVE 0 +#define CUDD_LINEAR_TRANSFORM_MOVE 1 +#define CUDD_INVERSE_TRANSFORM_MOVE 2 +#if SIZEOF_LONG == 8 +#define BPL 64 +#define LOGBPL 6 +#else +#define BPL 32 +#define LOGBPL 5 +#endif + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +static int *entry; + +#ifdef DD_STATS +extern int ddTotalNumberSwapping; +extern int ddTotalNISwaps; +static int ddTotalNumberLinearTr; +#endif + +#ifdef DD_DEBUG +static int zero = 0; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int ddLinearUniqueCompare ARGS((int *ptrX, int *ptrY)); +static int ddLinearAndSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); +static Move * ddLinearAndSiftingUp ARGS((DdManager *table, int y, int xLow, Move *prevMoves)); +static Move * ddLinearAndSiftingDown ARGS((DdManager *table, int x, int xHigh, Move *prevMoves)); +static int ddLinearAndSiftingBackward ARGS((DdManager *table, int size, Move *moves)); +static Move* ddUndoMoves ARGS((DdManager *table, Move *moves)); +static int cuddLinearInPlace ARGS((DdManager *table, int x, int y)); +static void ddUpdateInteractionMatrix ARGS((DdManager *table, int xindex, int yindex)); +static int cuddInitLinear ARGS((DdManager *table)); +static int cuddResizeLinear ARGS((DdManager *table)); +static void cuddXorLinear ARGS((DdManager *table, int x, int y)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Prints the linear transform matrix.] + + Description [Prints the linear transform matrix. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_PrintLinear( + DdManager * table) +{ + int i,j,k; + int retval; + int nvars = table->linearSize; + int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; + long word; + + for (i = 0; i < nvars; i++) { + for (j = 0; j < wordsPerRow; j++) { + word = table->linear[i*wordsPerRow + j]; + for (k = 0; k < BPL; k++) { + retval = fprintf(table->out,"%ld",word & 1); + if (retval == 0) return(0); + word >>= 1; + } + } + retval = fprintf(table->out,"\n"); + if (retval == 0) return(0); + } + return(1); + +} /* end of Cudd_PrintLinear */ + + +/**Function******************************************************************** + + Synopsis [Reads an entry of the linear transform matrix.] + + Description [Reads an entry of the linear transform matrix.] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_ReadLinear( + DdManager * table /* CUDD manager */, + int x /* row index */, + int y /* column index */) +{ + int nvars = table->size; + int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; + long word; + int bit; + int result; + + assert(table->size == table->linearSize); + + word = wordsPerRow * x + (y >> LOGBPL); + bit = y & (BPL-1); + result = (int) ((table->linear[word] >> bit) & 1); + return(result); + +} /* end of Cudd_ReadLinear */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [BDD reduction based on combination of sifting and linear + transformations.] + + Description [BDD reduction based on combination of sifting and linear + transformations. Assumes that no dead nodes are present. +
        +
      1. Order all the variables according to the number of entries + in each unique table. +
      2. Sift the variable up and down, remembering each time the + total size of the DD heap. At each position, linear transformation + of the two adjacent variables is tried and is accepted if it reduces + the size of the DD. +
      3. Select the best permutation. +
      4. Repeat 3 and 4 for all variables. +
      + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +int +cuddLinearAndSifting( + DdManager * table, + int lower, + int upper) +{ + int i; + int *var; + int size; + int x; + int result; +#ifdef DD_STATS + int previousSize; +#endif + +#ifdef DD_STATS + ddTotalNumberLinearTr = 0; +#endif + + size = table->size; + + var = NULL; + entry = NULL; + if (table->linear == NULL) { + result = cuddInitLinear(table); + if (result == 0) goto cuddLinearAndSiftingOutOfMem; +#if 0 + (void) fprintf(table->out,"\n"); + result = Cudd_PrintLinear(table); + if (result == 0) goto cuddLinearAndSiftingOutOfMem; +#endif + } else if (table->size != table->linearSize) { + result = cuddResizeLinear(table); + if (result == 0) goto cuddLinearAndSiftingOutOfMem; +#if 0 + (void) fprintf(table->out,"\n"); + result = Cudd_PrintLinear(table); + if (result == 0) goto cuddLinearAndSiftingOutOfMem; +#endif + } + + /* Find order in which to sift variables. */ + entry = ALLOC(int,size); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddLinearAndSiftingOutOfMem; + } + var = ALLOC(int,size); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddLinearAndSiftingOutOfMem; + } + + for (i = 0; i < size; i++) { + x = table->perm[i]; + entry[i] = table->subtables[x].keys; + var[i] = i; + } + + qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddLinearUniqueCompare); + + /* Now sift. */ + for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { + x = table->perm[var[i]]; + if (x < lower || x > upper) continue; +#ifdef DD_STATS + previousSize = table->keys - table->isolated; +#endif + result = ddLinearAndSiftingAux(table,x,lower,upper); + if (!result) goto cuddLinearAndSiftingOutOfMem; +#ifdef DD_STATS + if (table->keys < (unsigned) previousSize + table->isolated) { + (void) fprintf(table->out,"-"); + } else if (table->keys > (unsigned) previousSize + table->isolated) { + (void) fprintf(table->out,"+"); /* should never happen */ + (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif +#ifdef DD_DEBUG + (void) Cudd_DebugCheck(table); +#endif + } + + FREE(var); + FREE(entry); + +#ifdef DD_STATS + (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.", + ddTotalNumberLinearTr); +#endif + + return(1); + +cuddLinearAndSiftingOutOfMem: + + if (entry != NULL) FREE(entry); + if (var != NULL) FREE(var); + + return(0); + +} /* end of cuddLinearAndSifting */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Comparison function used by qsort.] + + Description [Comparison function used by qsort to order the + variables according to the number of keys in the subtables. + Returns the difference in number of keys between the two + variables being compared.] + + SideEffects [None] + +******************************************************************************/ +static int +ddLinearUniqueCompare( + int * ptrX, + int * ptrY) +{ +#if 0 + if (entry[*ptrY] == entry[*ptrX]) { + return((*ptrX) - (*ptrY)); + } +#endif + return(entry[*ptrY] - entry[*ptrX]); + +} /* end of ddLinearUniqueCompare */ + + +/**Function******************************************************************** + + Synopsis [Given xLow <= x <= xHigh moves x up and down between the + boundaries.] + + Description [Given xLow <= x <= xHigh moves x up and down between the + boundaries. At each step a linear transformation is tried, and, if it + decreases the size of the DD, it is accepted. Finds the best position + and does the required changes. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddLinearAndSiftingAux( + DdManager * table, + int x, + int xLow, + int xHigh) +{ + + Move *move; + Move *moveUp; /* list of up moves */ + Move *moveDown; /* list of down moves */ + int initialSize; + int result; + + initialSize = table->keys - table->isolated; + + moveDown = NULL; + moveUp = NULL; + + if (x == xLow) { + moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); + /* At this point x --> xHigh unless bounding occurred. */ + if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; + /* Move backward and stop at best position. */ + result = ddLinearAndSiftingBackward(table,initialSize,moveDown); + if (!result) goto ddLinearAndSiftingAuxOutOfMem; + + } else if (x == xHigh) { + moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); + /* At this point x --> xLow unless bounding occurred. */ + if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; + /* Move backward and stop at best position. */ + result = ddLinearAndSiftingBackward(table,initialSize,moveUp); + if (!result) goto ddLinearAndSiftingAuxOutOfMem; + + } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ + moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); + /* At this point x --> xHigh unless bounding occurred. */ + if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; + moveUp = ddUndoMoves(table,moveDown); +#ifdef DD_DEBUG + assert(moveUp == NULL || moveUp->x == x); +#endif + moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp); + if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; + /* Move backward and stop at best position. */ + result = ddLinearAndSiftingBackward(table,initialSize,moveUp); + if (!result) goto ddLinearAndSiftingAuxOutOfMem; + + } else { /* must go up first: shorter */ + moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); + /* At this point x --> xLow unless bounding occurred. */ + if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; + moveDown = ddUndoMoves(table,moveUp); +#ifdef DD_DEBUG + assert(moveDown == NULL || moveDown->y == x); +#endif + moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown); + if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; + /* Move backward and stop at best position. */ + result = ddLinearAndSiftingBackward(table,initialSize,moveDown); + if (!result) goto ddLinearAndSiftingAuxOutOfMem; + } + + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *) moveDown); + moveDown = move; + } + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *) moveUp); + moveUp = move; + } + + return(1); + +ddLinearAndSiftingAuxOutOfMem: + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *) moveDown); + moveDown = move; + } + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *) moveUp); + moveUp = move; + } + + return(0); + +} /* end of ddLinearAndSiftingAux */ + + +/**Function******************************************************************** + + Synopsis [Sifts a variable up and applies linear transformations.] + + Description [Sifts a variable up and applies linear transformations. + Moves y up until either it reaches the bound (xLow) or the size of + the DD heap increases too much. Returns the set of moves in case of + success; NULL if memory is full.] + + SideEffects [None] + +******************************************************************************/ +static Move * +ddLinearAndSiftingUp( + DdManager * table, + int y, + int xLow, + Move * prevMoves) +{ + Move *moves; + Move *move; + int x; + int size, newsize; + int limitSize; + int xindex, yindex; + int isolated; + int L; /* lower bound on DD size */ +#ifdef DD_DEBUG + int checkL; + int z; + int zindex; +#endif + + moves = prevMoves; + yindex = table->invperm[y]; + + /* Initialize the lower bound. + ** The part of the DD below y will not change. + ** The part of the DD above y that does not interact with y will not + ** change. The rest may vanish in the best case, except for + ** the nodes at level xLow, which will not vanish, regardless. + */ + limitSize = L = table->keys - table->isolated; + for (x = xLow + 1; x < y; x++) { + xindex = table->invperm[x]; + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[xindex]->ref == 1; + L -= table->subtables[x].keys - isolated; + } + } + isolated = table->vars[yindex]->ref == 1; + L -= table->subtables[y].keys - isolated; + + x = cuddNextLow(table,y); + while (x >= xLow && L <= limitSize) { + xindex = table->invperm[x]; +#ifdef DD_DEBUG + checkL = table->keys - table->isolated; + for (z = xLow + 1; z < y; z++) { + zindex = table->invperm[z]; + if (cuddTestInteract(table,zindex,yindex)) { + isolated = table->vars[zindex]->ref == 1; + checkL -= table->subtables[z].keys - isolated; + } + } + isolated = table->vars[yindex]->ref == 1; + checkL -= table->subtables[y].keys - isolated; + if (L != checkL) { + (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L); + } +#endif + size = cuddSwapInPlace(table,x,y); + if (size == 0) goto ddLinearAndSiftingUpOutOfMem; + newsize = cuddLinearInPlace(table,x,y); + if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddLinearAndSiftingUpOutOfMem; + move->x = x; + move->y = y; + move->next = moves; + moves = move; + move->flags = CUDD_SWAP_MOVE; + if (newsize >= size) { + /* Undo transformation. The transformation we apply is + ** its own inverse. Hence, we just apply the transformation + ** again. + */ + newsize = cuddLinearInPlace(table,x,y); + if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; +#ifdef DD_DEBUG + if (newsize != size) { + (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); + } +#endif + } else if (cuddTestInteract(table,xindex,yindex)) { + size = newsize; + move->flags = CUDD_LINEAR_TRANSFORM_MOVE; + ddUpdateInteractionMatrix(table,xindex,yindex); + } + move->size = size; + /* Update the lower bound. */ + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[xindex]->ref == 1; + L += table->subtables[y].keys - isolated; + } + if ((double) size > (double) limitSize * table->maxGrowth) break; + if (size < limitSize) limitSize = size; + y = x; + x = cuddNextLow(table,y); + } + return(moves); + +ddLinearAndSiftingUpOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return((Move *) CUDD_OUT_OF_MEM); + +} /* end of ddLinearAndSiftingUp */ + + +/**Function******************************************************************** + + Synopsis [Sifts a variable down and applies linear transformations.] + + Description [Sifts a variable down and applies linear + transformations. Moves x down until either it reaches the bound + (xHigh) or the size of the DD heap increases too much. Returns the + set of moves in case of success; NULL if memory is full.] + + SideEffects [None] + +******************************************************************************/ +static Move * +ddLinearAndSiftingDown( + DdManager * table, + int x, + int xHigh, + Move * prevMoves) +{ + Move *moves; + Move *move; + int y; + int size, newsize; + int R; /* upper bound on node decrease */ + int limitSize; + int xindex, yindex; + int isolated; +#ifdef DD_DEBUG + int checkR; + int z; + int zindex; +#endif + + moves = prevMoves; + /* Initialize R */ + xindex = table->invperm[x]; + limitSize = size = table->keys - table->isolated; + R = 0; + for (y = xHigh; y > x; y--) { + yindex = table->invperm[y]; + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[yindex]->ref == 1; + R += table->subtables[y].keys - isolated; + } + } + + y = cuddNextHigh(table,x); + while (y <= xHigh && size - R < limitSize) { +#ifdef DD_DEBUG + checkR = 0; + for (z = xHigh; z > x; z--) { + zindex = table->invperm[z]; + if (cuddTestInteract(table,xindex,zindex)) { + isolated = table->vars[zindex]->ref == 1; + checkR += table->subtables[z].keys - isolated; + } + } + if (R != checkR) { + (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R); + } +#endif + /* Update upper bound on node decrease. */ + yindex = table->invperm[y]; + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[yindex]->ref == 1; + R -= table->subtables[y].keys - isolated; + } + size = cuddSwapInPlace(table,x,y); + if (size == 0) goto ddLinearAndSiftingDownOutOfMem; + newsize = cuddLinearInPlace(table,x,y); + if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddLinearAndSiftingDownOutOfMem; + move->x = x; + move->y = y; + move->next = moves; + moves = move; + move->flags = CUDD_SWAP_MOVE; + if (newsize >= size) { + /* Undo transformation. The transformation we apply is + ** its own inverse. Hence, we just apply the transformation + ** again. + */ + newsize = cuddLinearInPlace(table,x,y); + if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; + if (newsize != size) { + (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); + } + } else if (cuddTestInteract(table,xindex,yindex)) { + size = newsize; + move->flags = CUDD_LINEAR_TRANSFORM_MOVE; + ddUpdateInteractionMatrix(table,xindex,yindex); + } + move->size = size; + if ((double) size > (double) limitSize * table->maxGrowth) break; + if (size < limitSize) limitSize = size; + x = y; + y = cuddNextHigh(table,x); + } + return(moves); + +ddLinearAndSiftingDownOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return((Move *) CUDD_OUT_OF_MEM); + +} /* end of ddLinearAndSiftingDown */ + + +/**Function******************************************************************** + + Synopsis [Given a set of moves, returns the DD heap to the order + giving the minimum size.] + + Description [Given a set of moves, returns the DD heap to the + position giving the minimum size. In case of ties, returns to the + closest position giving the minimum size. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddLinearAndSiftingBackward( + DdManager * table, + int size, + Move * moves) +{ + Move *move; + int res; + + for (move = moves; move != NULL; move = move->next) { + if (move->size < size) { + size = move->size; + } + } + + for (move = moves; move != NULL; move = move->next) { + if (move->size == size) return(1); + if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { + res = cuddLinearInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); + } + res = cuddSwapInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); + if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) { + res = cuddLinearInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); + } + } + + return(1); + +} /* end of ddLinearAndSiftingBackward */ + + +/**Function******************************************************************** + + Synopsis [Given a set of moves, returns the DD heap to the order + in effect before the moves.] + + Description [Given a set of moves, returns the DD heap to the + order in effect before the moves. Returns 1 in case of success; + 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static Move* +ddUndoMoves( + DdManager * table, + Move * moves) +{ + Move *invmoves = NULL; + Move *move; + Move *invmove; + int size; + + for (move = moves; move != NULL; move = move->next) { + invmove = (Move *) cuddDynamicAllocNode(table); + if (invmove == NULL) goto ddUndoMovesOutOfMem; + invmove->x = move->x; + invmove->y = move->y; + invmove->next = invmoves; + invmoves = invmove; + if (move->flags == CUDD_SWAP_MOVE) { + invmove->flags = CUDD_SWAP_MOVE; + size = cuddSwapInPlace(table,(int)move->x,(int)move->y); + if (!size) goto ddUndoMovesOutOfMem; + } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { + invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE; + size = cuddLinearInPlace(table,(int)move->x,(int)move->y); + if (!size) goto ddUndoMovesOutOfMem; + size = cuddSwapInPlace(table,(int)move->x,(int)move->y); + if (!size) goto ddUndoMovesOutOfMem; + } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */ +#ifdef DD_DEBUG + (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n"); +#endif + invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE; + size = cuddSwapInPlace(table,(int)move->x,(int)move->y); + if (!size) goto ddUndoMovesOutOfMem; + size = cuddLinearInPlace(table,(int)move->x,(int)move->y); + if (!size) goto ddUndoMovesOutOfMem; + } + invmove->size = size; + } + + return(invmoves); + +ddUndoMovesOutOfMem: + while (invmoves != NULL) { + move = invmoves->next; + cuddDeallocNode(table, (DdNode *) invmoves); + invmoves = move; + } + return((Move *) CUDD_OUT_OF_MEM); + +} /* end of ddUndoMoves */ + + +/**Function******************************************************************** + + Synopsis [Linearly combines two adjacent variables.] + + Description [Linearly combines two adjacent variables. Specifically, + replaces the top variable with the exclusive nor of the two variables. + It assumes that no dead nodes are present on entry to this + procedure. The procedure then guarantees that no dead nodes will be + present when it terminates. cuddLinearInPlace assumes that x < + y. Returns the number of keys in the table if successful; 0 + otherwise.] + + SideEffects [The two subtables corrresponding to variables x and y are + modified. The global counters of the unique table are also affected.] + + SeeAlso [cuddSwapInPlace] + +******************************************************************************/ +static int +cuddLinearInPlace( + DdManager * table, + int x, + int y) +{ + DdNodePtr *xlist, *ylist; + int xindex, yindex; + int xslots, yslots; + int xshift, yshift; + int oldxkeys, oldykeys; + int newxkeys, newykeys; + int comple, newcomplement; + int i; + int posn; + int isolated; + DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; + DdNode *g,*next,*last; + DdNodePtr *previousP; + DdNode *tmp; + DdNode *sentinel = &(table->sentinel); +#if DD_DEBUG + int count, idcheck; +#endif + +#ifdef DD_DEBUG + assert(x < y); + assert(cuddNextHigh(table,x) == y); + assert(table->subtables[x].keys != 0); + assert(table->subtables[y].keys != 0); + assert(table->subtables[x].dead == 0); + assert(table->subtables[y].dead == 0); +#endif + + xindex = table->invperm[x]; + yindex = table->invperm[y]; + + if (cuddTestInteract(table,xindex,yindex)) { +#ifdef DD_STATS + ddTotalNumberLinearTr++; +#endif + /* Get parameters of x subtable. */ + xlist = table->subtables[x].nodelist; + oldxkeys = table->subtables[x].keys; + xslots = table->subtables[x].slots; + xshift = table->subtables[x].shift; + + /* Get parameters of y subtable. */ + ylist = table->subtables[y].nodelist; + oldykeys = table->subtables[y].keys; + yslots = table->subtables[y].slots; + yshift = table->subtables[y].shift; + + newxkeys = 0; + newykeys = oldykeys; + + /* Check whether the two projection functions involved in this + ** swap are isolated. At the end, we'll be able to tell how many + ** isolated projection functions are there by checking only these + ** two functions again. This is done to eliminate the isolated + ** projection functions from the node count. + */ + isolated = - ((table->vars[xindex]->ref == 1) + + (table->vars[yindex]->ref == 1)); + + /* The nodes in the x layer are put in a chain. + ** The chain is handled as a FIFO; g points to the beginning and + ** last points to the end. + */ + g = NULL; + for (i = 0; i < xslots; i++) { + f = xlist[i]; + if (f == sentinel) continue; + xlist[i] = sentinel; + if (g == NULL) { + g = f; + } else { + last->next = f; + } + while ((next = f->next) != sentinel) { + f = next; + } /* while there are elements in the collision chain */ + last = f; + } /* for each slot of the x subtable */ + last->next = NULL; + +#ifdef DD_COUNT + table->swapSteps += oldxkeys; +#endif + /* Take care of the x nodes that must be re-expressed. + ** They form a linked list pointed by g. + */ + f = g; + while (f != NULL) { + next = f->next; + /* Find f1, f0, f11, f10, f01, f00. */ + f1 = cuddT(f); +#ifdef DD_DEBUG + assert(!(Cudd_IsComplement(f1))); +#endif + if ((int) f1->index == yindex) { + f11 = cuddT(f1); f10 = cuddE(f1); + } else { + f11 = f10 = f1; + } +#ifdef DD_DEBUG + assert(!(Cudd_IsComplement(f11))); +#endif + f0 = cuddE(f); + comple = Cudd_IsComplement(f0); + f0 = Cudd_Regular(f0); + if ((int) f0->index == yindex) { + f01 = cuddT(f0); f00 = cuddE(f0); + } else { + f01 = f00 = f0; + } + if (comple) { + f01 = Cudd_Not(f01); + f00 = Cudd_Not(f00); + } + /* Decrease ref count of f1. */ + cuddSatDec(f1->ref); + /* Create the new T child. */ + if (f11 == f00) { + newf1 = f11; + cuddSatInc(newf1->ref); + } else { + /* Check ylist for triple (yindex,f11,f00). */ + posn = ddHash(f11, f00, yshift); + /* For each element newf1 in collision list ylist[posn]. */ + previousP = &(ylist[posn]); + newf1 = *previousP; + while (f11 < cuddT(newf1)) { + previousP = &(newf1->next); + newf1 = *previousP; + } + while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) { + previousP = &(newf1->next); + newf1 = *previousP; + } + if (cuddT(newf1) == f11 && cuddE(newf1) == f00) { + cuddSatInc(newf1->ref); + } else { /* no match */ + newf1 = cuddDynamicAllocNode(table); + if (newf1 == NULL) + goto cuddLinearOutOfMem; + newf1->index = yindex; newf1->ref = 1; + cuddT(newf1) = f11; + cuddE(newf1) = f00; + /* Insert newf1 in the collision list ylist[posn]; + ** increase the ref counts of f11 and f00. + */ + newykeys++; + newf1->next = *previousP; + *previousP = newf1; + cuddSatInc(f11->ref); + tmp = Cudd_Regular(f00); + cuddSatInc(tmp->ref); + } + } + cuddT(f) = newf1; +#ifdef DD_DEBUG + assert(!(Cudd_IsComplement(newf1))); +#endif + + /* Do the same for f0, keeping complement dots into account. */ + /* decrease ref count of f0 */ + tmp = Cudd_Regular(f0); + cuddSatDec(tmp->ref); + /* create the new E child */ + if (f01 == f10) { + newf0 = f01; + tmp = Cudd_Regular(newf0); + cuddSatInc(tmp->ref); + } else { + /* make sure f01 is regular */ + newcomplement = Cudd_IsComplement(f01); + if (newcomplement) { + f01 = Cudd_Not(f01); + f10 = Cudd_Not(f10); + } + /* Check ylist for triple (yindex,f01,f10). */ + posn = ddHash(f01, f10, yshift); + /* For each element newf0 in collision list ylist[posn]. */ + previousP = &(ylist[posn]); + newf0 = *previousP; + while (f01 < cuddT(newf0)) { + previousP = &(newf0->next); + newf0 = *previousP; + } + while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) { + previousP = &(newf0->next); + newf0 = *previousP; + } + if (cuddT(newf0) == f01 && cuddE(newf0) == f10) { + cuddSatInc(newf0->ref); + } else { /* no match */ + newf0 = cuddDynamicAllocNode(table); + if (newf0 == NULL) + goto cuddLinearOutOfMem; + newf0->index = yindex; newf0->ref = 1; + cuddT(newf0) = f01; + cuddE(newf0) = f10; + /* Insert newf0 in the collision list ylist[posn]; + ** increase the ref counts of f01 and f10. + */ + newykeys++; + newf0->next = *previousP; + *previousP = newf0; + cuddSatInc(f01->ref); + tmp = Cudd_Regular(f10); + cuddSatInc(tmp->ref); + } + if (newcomplement) { + newf0 = Cudd_Not(newf0); + } + } + cuddE(f) = newf0; + + /* Re-insert the modified f in xlist. + ** The modified f does not already exists in xlist. + ** (Because of the uniqueness of the cofactors.) + */ + posn = ddHash(newf1, newf0, xshift); + newxkeys++; + previousP = &(xlist[posn]); + tmp = *previousP; + while (newf1 < cuddT(tmp)) { + previousP = &(tmp->next); + tmp = *previousP; + } + while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { + previousP = &(tmp->next); + tmp = *previousP; + } + f->next = *previousP; + *previousP = f; + f = next; + } /* while f != NULL */ + + /* GC the y layer. */ + + /* For each node f in ylist. */ + for (i = 0; i < yslots; i++) { + previousP = &(ylist[i]); + f = *previousP; + while (f != sentinel) { + next = f->next; + if (f->ref == 0) { + tmp = cuddT(f); + cuddSatDec(tmp->ref); + tmp = Cudd_Regular(cuddE(f)); + cuddSatDec(tmp->ref); + cuddDeallocNode(table,f); + newykeys--; + } else { + *previousP = f; + previousP = &(f->next); + } + f = next; + } /* while f */ + *previousP = sentinel; + } /* for every collision list */ + +#if DD_DEBUG +#if 0 + (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y); +#endif + count = 0; + idcheck = 0; + for (i = 0; i < yslots; i++) { + f = ylist[i]; + while (f != sentinel) { + count++; + if (f->index != (DdHalfWord) yindex) + idcheck++; + f = f->next; + } + } + if (count != newykeys) { + fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count); + } + if (idcheck != 0) + fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck); + count = 0; + idcheck = 0; + for (i = 0; i < xslots; i++) { + f = xlist[i]; + while (f != sentinel) { + count++; + if (f->index != (DdHalfWord) xindex) + idcheck++; + f = f->next; + } + } + if (count != newxkeys || newxkeys != oldxkeys) { + fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count); + } + if (idcheck != 0) + fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck); +#endif + + isolated += (table->vars[xindex]->ref == 1) + + (table->vars[yindex]->ref == 1); + table->isolated += isolated; + + /* Set the appropriate fields in table. */ + table->subtables[y].keys = newykeys; + + /* Here we should update the linear combination table + ** to record that x <- x EXNOR y. This is done by complementing + ** the (x,y) entry of the table. + */ + + table->keys += newykeys - oldykeys; + + cuddXorLinear(table,xindex,yindex); + } + +#ifdef DD_DEBUG + if (zero) { + (void) Cudd_DebugCheck(table); + } +#endif + + return(table->keys - table->isolated); + +cuddLinearOutOfMem: + (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n"); + + return (0); + +} /* end of cuddLinearInPlace */ + + +/**Function******************************************************************** + + Synopsis [Updates the interaction matrix.] + + Description [] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +static void +ddUpdateInteractionMatrix( + DdManager * table, + int xindex, + int yindex) +{ + int i; + for (i = 0; i < yindex; i++) { + if (i != xindex && cuddTestInteract(table,i,yindex)) { + if (i < xindex) { + cuddSetInteract(table,i,xindex); + } else { + cuddSetInteract(table,xindex,i); + } + } + } + for (i = yindex+1; i < table->size; i++) { + if (i != xindex && cuddTestInteract(table,yindex,i)) { + if (i < xindex) { + cuddSetInteract(table,i,xindex); + } else { + cuddSetInteract(table,xindex,i); + } + } + } + +} /* end of ddUpdateInteractionMatrix */ + + +/**Function******************************************************************** + + Synopsis [Initializes the linear transform matrix.] + + Description [] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +static int +cuddInitLinear( + DdManager * table) +{ + int words; + int wordsPerRow; + int nvars; + int word; + int bit; + int i; + long *linear; + + nvars = table->size; + wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; + words = wordsPerRow * nvars; + table->linear = linear = ALLOC(long,words); + if (linear == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + table->memused += words * sizeof(long); + table->linearSize = nvars; + for (i = 0; i < words; i++) linear[i] = 0; + for (i = 0; i < nvars; i++) { + word = wordsPerRow * i + (i >> LOGBPL); + bit = i & (BPL-1); + linear[word] = 1 << bit; + } + return(1); + +} /* end of cuddInitLinear */ + + +/**Function******************************************************************** + + Synopsis [Resizes the linear transform matrix.] + + Description [] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +static int +cuddResizeLinear( + DdManager * table) +{ + int words,oldWords; + int wordsPerRow,oldWordsPerRow; + int nvars,oldNvars; + int word,oldWord; + int bit; + int i,j; + long *linear,*oldLinear; + + oldNvars = table->linearSize; + oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1; + oldWords = oldWordsPerRow * oldNvars; + oldLinear = table->linear; + + nvars = table->size; + wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; + words = wordsPerRow * nvars; + table->linear = linear = ALLOC(long,words); + if (linear == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + table->memused += (words - oldWords) * sizeof(long); + for (i = 0; i < words; i++) linear[i] = 0; + + /* Copy old matrix. */ + for (i = 0; i < oldNvars; i++) { + for (j = 0; j < oldWordsPerRow; j++) { + oldWord = oldWordsPerRow * i + j; + word = wordsPerRow * i + j; + linear[word] = oldLinear[oldWord]; + } + } + FREE(oldLinear); + + /* Add elements to the diagonal. */ + for (i = oldNvars; i < nvars; i++) { + word = wordsPerRow * i + (i >> LOGBPL); + bit = i & (BPL-1); + linear[word] = 1 << bit; + } + table->linearSize = nvars; + + return(1); + +} /* end of cuddResizeLinear */ + + +/**Function******************************************************************** + + Synopsis [XORs two rows of the linear transform matrix.] + + Description [XORs two rows of the linear transform matrix and replaces + the first row with the result.] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +static void +cuddXorLinear( + DdManager * table, + int x, + int y) +{ + int i; + int nvars = table->size; + int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; + int xstart = wordsPerRow * x; + int ystart = wordsPerRow * y; + long *linear = table->linear; + + for (i = 0; i < wordsPerRow; i++) { + linear[xstart+i] ^= linear[ystart+i]; + } + +} /* end of cuddXorLinear */ + diff --git a/abc70930/src/bdd/cudd/cuddLiteral.c b/abc70930/src/bdd/cudd/cuddLiteral.c new file mode 100644 index 00000000..43740690 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddLiteral.c @@ -0,0 +1,237 @@ +/**CFile*********************************************************************** + + FileName [cuddLiteral.c] + + PackageName [cudd] + + Synopsis [Functions for manipulation of literal sets represented by + BDDs.] + + Description [External procedures included in this file: +
        +
      • Cudd_bddLiteralSetIntersection() +
      + Internal procedures included in this file: +
        +
      • cuddBddLiteralSetIntersectionRecur() +
      ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddLiteral.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes the intesection of two sets of literals + represented as BDDs.] + + Description [Computes the intesection of two sets of literals + represented as BDDs. Each set is represented as a cube of the + literals in the set. The empty set is represented by the constant 1. + No variable can be simultaneously present in both phases in a set. + Returns a pointer to the BDD representing the intersected sets, if + successful; NULL otherwise.] + + SideEffects [None] + +******************************************************************************/ +DdNode * +Cudd_bddLiteralSetIntersection( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddLiteralSetIntersectionRecur(dd,f,g); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddLiteralSetIntersection */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of + Cudd_bddLiteralSetIntersection.] + + Description [Performs the recursive step of + Cudd_bddLiteralSetIntersection. Scans the cubes for common variables, + and checks whether they agree in phase. Returns a pointer to the + resulting cube if successful; NULL otherwise.] + + SideEffects [None] + +******************************************************************************/ +DdNode * +cuddBddLiteralSetIntersectionRecur( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res, *tmp; + DdNode *F, *G; + DdNode *fc, *gc; + DdNode *one; + DdNode *zero; + unsigned int topf, topg, comple; + int phasef, phaseg; + + statLine(dd); + if (f == g) return(f); + + F = Cudd_Regular(f); + G = Cudd_Regular(g); + one = DD_ONE(dd); + + /* Here f != g. If F == G, then f and g are complementary. + ** Since they are two cubes, this case only occurs when f == v, + ** g == v', and v is a variable or its complement. + */ + if (F == G) return(one); + + zero = Cudd_Not(one); + topf = cuddI(dd,F->index); + topg = cuddI(dd,G->index); + /* Look for a variable common to both cubes. If there are none, this + ** loop will stop when the constant node is reached in both cubes. + */ + while (topf != topg) { + if (topf < topg) { /* move down on f */ + comple = f != F; + f = cuddT(F); + if (comple) f = Cudd_Not(f); + if (f == zero) { + f = cuddE(F); + if (comple) f = Cudd_Not(f); + } + F = Cudd_Regular(f); + topf = cuddI(dd,F->index); + } else if (topg < topf) { + comple = g != G; + g = cuddT(G); + if (comple) g = Cudd_Not(g); + if (g == zero) { + g = cuddE(G); + if (comple) g = Cudd_Not(g); + } + G = Cudd_Regular(g); + topg = cuddI(dd,G->index); + } + } + + /* At this point, f == one <=> g == 1. It suffices to test one of them. */ + if (f == one) return(one); + + res = cuddCacheLookup2(dd,Cudd_bddLiteralSetIntersection,f,g); + if (res != NULL) { + return(res); + } + + /* Here f and g are both non constant and have the same top variable. */ + comple = f != F; + fc = cuddT(F); + phasef = 1; + if (comple) fc = Cudd_Not(fc); + if (fc == zero) { + fc = cuddE(F); + phasef = 0; + if (comple) fc = Cudd_Not(fc); + } + comple = g != G; + gc = cuddT(G); + phaseg = 1; + if (comple) gc = Cudd_Not(gc); + if (gc == zero) { + gc = cuddE(G); + phaseg = 0; + if (comple) gc = Cudd_Not(gc); + } + + tmp = cuddBddLiteralSetIntersectionRecur(dd,fc,gc); + if (tmp == NULL) { + return(NULL); + } + + if (phasef != phaseg) { + res = tmp; + } else { + cuddRef(tmp); + if (phasef == 0) { + res = cuddBddAndRecur(dd,Cudd_Not(dd->vars[F->index]),tmp); + } else { + res = cuddBddAndRecur(dd,dd->vars[F->index],tmp); + } + if (res == NULL) { + Cudd_RecursiveDeref(dd,tmp); + return(NULL); + } + cuddDeref(tmp); /* Just cuddDeref, because it is included in result */ + } + + cuddCacheInsert2(dd,Cudd_bddLiteralSetIntersection,f,g,res); + + return(res); + +} /* end of cuddBddLiteralSetIntersectionRecur */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/cudd/cuddMatMult.c b/abc70930/src/bdd/cudd/cuddMatMult.c new file mode 100644 index 00000000..345e7921 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddMatMult.c @@ -0,0 +1,680 @@ +/**CFile*********************************************************************** + + FileName [cuddMatMult.c] + + PackageName [cudd] + + Synopsis [Matrix multiplication functions.] + + Description [External procedures included in this module: +
        +
      • Cudd_addMatrixMultiply() +
      • Cudd_addTimesPlus() +
      • Cudd_addTriangle() +
      • Cudd_addOuterSum() +
      + Static procedures included in this module: +
        +
      • addMMRecur() +
      • addTriangleRecur() +
      • cuddAddOuterSumRecur() +
      ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddMatMult.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * addMMRecur ARGS((DdManager *dd, DdNode *A, DdNode *B, int topP, int *vars)); +static DdNode * addTriangleRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, int *vars, DdNode *cube)); +static DdNode * cuddAddOuterSumRecur ARGS((DdManager *dd, DdNode *M, DdNode *r, DdNode *c)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Calculates the product of two matrices represented as + ADDs.] + + Description [Calculates the product of two matrices, A and B, + represented as ADDs. This procedure implements the quasiring multiplication + algorithm. A is assumed to depend on variables x (rows) and z + (columns). B is assumed to depend on variables z (rows) and y + (columns). The product of A and B then depends on x (rows) and y + (columns). Only the z variables have to be explicitly identified; + they are the "summation" variables. Returns a pointer to the + result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addTimesPlus Cudd_addTriangle Cudd_bddAndAbstract] + +******************************************************************************/ +DdNode * +Cudd_addMatrixMultiply( + DdManager * dd, + DdNode * A, + DdNode * B, + DdNode ** z, + int nz) +{ + int i, nvars, *vars; + DdNode *res; + + /* Array vars says what variables are "summation" variables. */ + nvars = dd->size; + vars = ALLOC(int,nvars); + if (vars == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < nvars; i++) { + vars[i] = 0; + } + for (i = 0; i < nz; i++) { + vars[z[i]->index] = 1; + } + + do { + dd->reordered = 0; + res = addMMRecur(dd,A,B,-1,vars); + } while (dd->reordered == 1); + FREE(vars); + return(res); + +} /* end of Cudd_addMatrixMultiply */ + + +/**Function******************************************************************** + + Synopsis [Calculates the product of two matrices represented as + ADDs.] + + Description [Calculates the product of two matrices, A and B, + represented as ADDs, using the CMU matrix by matrix multiplication + procedure by Clarke et al.. Matrix A has x's as row variables and z's + as column variables, while matrix B has z's as row variables and y's + as column variables. Returns the pointer to the result if successful; + NULL otherwise. The resulting matrix has x's as row variables and y's + as column variables.] + + SideEffects [None] + + SeeAlso [Cudd_addMatrixMultiply] + +******************************************************************************/ +DdNode * +Cudd_addTimesPlus( + DdManager * dd, + DdNode * A, + DdNode * B, + DdNode ** z, + int nz) +{ + DdNode *w, *cube, *tmp, *res; + int i; + tmp = Cudd_addApply(dd,Cudd_addTimes,A,B); + if (tmp == NULL) return(NULL); + Cudd_Ref(tmp); + Cudd_Ref(cube = DD_ONE(dd)); + for (i = nz-1; i >= 0; i--) { + w = Cudd_addIte(dd,z[i],cube,DD_ZERO(dd)); + if (w == NULL) { + Cudd_RecursiveDeref(dd,tmp); + return(NULL); + } + Cudd_Ref(w); + Cudd_RecursiveDeref(dd,cube); + cube = w; + } + res = Cudd_addExistAbstract(dd,tmp,cube); + if (res == NULL) { + Cudd_RecursiveDeref(dd,tmp); + Cudd_RecursiveDeref(dd,cube); + return(NULL); + } + Cudd_Ref(res); + Cudd_RecursiveDeref(dd,cube); + Cudd_RecursiveDeref(dd,tmp); + Cudd_Deref(res); + return(res); + +} /* end of Cudd_addTimesPlus */ + + +/**Function******************************************************************** + + Synopsis [Performs the triangulation step for the shortest path + computation.] + + Description [Implements the semiring multiplication algorithm used in + the triangulation step for the shortest path computation. f + is assumed to depend on variables x (rows) and z (columns). g is + assumed to depend on variables z (rows) and y (columns). The product + of f and g then depends on x (rows) and y (columns). Only the z + variables have to be explicitly identified; they are the + "abstraction" variables. Returns a pointer to the result if + successful; NULL otherwise. ] + + SideEffects [None] + + SeeAlso [Cudd_addMatrixMultiply Cudd_bddAndAbstract] + +******************************************************************************/ +DdNode * +Cudd_addTriangle( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode ** z, + int nz) +{ + int i, nvars, *vars; + DdNode *res, *cube; + + nvars = dd->size; + vars = ALLOC(int, nvars); + if (vars == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < nvars; i++) vars[i] = -1; + for (i = 0; i < nz; i++) vars[z[i]->index] = i; + cube = Cudd_addComputeCube(dd, z, NULL, nz); + if (cube == NULL) { + FREE(vars); + return(NULL); + } + cuddRef(cube); + + do { + dd->reordered = 0; + res = addTriangleRecur(dd, f, g, vars, cube); + } while (dd->reordered == 1); + if (res != NULL) cuddRef(res); + Cudd_RecursiveDeref(dd,cube); + if (res != NULL) cuddDeref(res); + FREE(vars); + return(res); + +} /* end of Cudd_addTriangle */ + + +/**Function******************************************************************** + + Synopsis [Takes the minimum of a matrix and the outer sum of two vectors.] + + Description [Takes the pointwise minimum of a matrix and the outer + sum of two vectors. This procedure is used in the Floyd-Warshall + all-pair shortest path algorithm. Returns a pointer to the result if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_addOuterSum( + DdManager *dd, + DdNode *M, + DdNode *r, + DdNode *c) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddAddOuterSumRecur(dd, M, r, c); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_addOuterSum */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addMatrixMultiply.] + + Description [Performs the recursive step of Cudd_addMatrixMultiply. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + +******************************************************************************/ +static DdNode * +addMMRecur( + DdManager * dd, + DdNode * A, + DdNode * B, + int topP, + int * vars) +{ + DdNode *zero, + *At, /* positive cofactor of first operand */ + *Ae, /* negative cofactor of first operand */ + *Bt, /* positive cofactor of second operand */ + *Be, /* negative cofactor of second operand */ + *t, /* positive cofactor of result */ + *e, /* negative cofactor of result */ + *scaled, /* scaled result */ + *add_scale, /* ADD representing the scaling factor */ + *res; + int i; /* loop index */ + double scale; /* scaling factor */ + int index; /* index of the top variable */ + CUDD_VALUE_TYPE value; + unsigned int topA, topB, topV; + DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); + + statLine(dd); + zero = DD_ZERO(dd); + + if (A == zero || B == zero) { + return(zero); + } + + if (cuddIsConstant(A) && cuddIsConstant(B)) { + /* Compute the scaling factor. It is 2^k, where k is the + ** number of summation variables below the current variable. + ** Indeed, these constants represent blocks of 2^k identical + ** constant values in both A and B. + */ + value = cuddV(A) * cuddV(B); + for (i = 0; i < dd->size; i++) { + if (vars[i]) { + if (dd->perm[i] > topP) { + value *= (CUDD_VALUE_TYPE) 2; + } + } + } + res = cuddUniqueConst(dd, value); + return(res); + } + + /* Standardize to increase cache efficiency. Clearly, A*B != B*A + ** in matrix multiplication. However, which matrix is which is + ** determined by the variables appearing in the ADDs and not by + ** which one is passed as first argument. + */ + if (A > B) { + DdNode *tmp = A; + A = B; + B = tmp; + } + + topA = cuddI(dd,A->index); topB = cuddI(dd,B->index); + topV = ddMin(topA,topB); + + cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) addMMRecur; + res = cuddCacheLookup2(dd,cacheOp,A,B); + if (res != NULL) { + /* If the result is 0, there is no need to normalize. + ** Otherwise we count the number of z variables between + ** the current depth and the top of the ADDs. These are + ** the missing variables that determine the size of the + ** constant blocks. + */ + if (res == zero) return(res); + scale = 1.0; + for (i = 0; i < dd->size; i++) { + if (vars[i]) { + if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { + scale *= 2; + } + } + } + if (scale > 1.0) { + cuddRef(res); + add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); + if (add_scale == NULL) { + Cudd_RecursiveDeref(dd, res); + return(NULL); + } + cuddRef(add_scale); + scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); + if (scaled == NULL) { + Cudd_RecursiveDeref(dd, add_scale); + Cudd_RecursiveDeref(dd, res); + return(NULL); + } + cuddRef(scaled); + Cudd_RecursiveDeref(dd, add_scale); + Cudd_RecursiveDeref(dd, res); + res = scaled; + cuddDeref(res); + } + return(res); + } + + /* compute the cofactors */ + if (topV == topA) { + At = cuddT(A); + Ae = cuddE(A); + } else { + At = Ae = A; + } + if (topV == topB) { + Bt = cuddT(B); + Be = cuddE(B); + } else { + Bt = Be = B; + } + + t = addMMRecur(dd, At, Bt, (int)topV, vars); + if (t == NULL) return(NULL); + cuddRef(t); + e = addMMRecur(dd, Ae, Be, (int)topV, vars); + if (e == NULL) { + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + cuddRef(e); + + index = dd->invperm[topV]; + if (vars[index] == 0) { + /* We have split on either the rows of A or the columns + ** of B. We just need to connect the two subresults, + ** which correspond to two submatrices of the result. + */ + res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); + if (res == NULL) { + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + cuddRef(res); + cuddDeref(t); + cuddDeref(e); + } else { + /* we have simultaneously split on the columns of A and + ** the rows of B. The two subresults must be added. + */ + res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e); + if (res == NULL) { + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + } + + cuddCacheInsert2(dd,cacheOp,A,B,res); + + /* We have computed (and stored in the computed table) a minimal + ** result; that is, a result that assumes no summation variables + ** between the current depth of the recursion and its top + ** variable. We now take into account the z variables by properly + ** scaling the result. + */ + if (res != zero) { + scale = 1.0; + for (i = 0; i < dd->size; i++) { + if (vars[i]) { + if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { + scale *= 2; + } + } + } + if (scale > 1.0) { + add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); + if (add_scale == NULL) { + Cudd_RecursiveDeref(dd, res); + return(NULL); + } + cuddRef(add_scale); + scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); + if (scaled == NULL) { + Cudd_RecursiveDeref(dd, res); + Cudd_RecursiveDeref(dd, add_scale); + return(NULL); + } + cuddRef(scaled); + Cudd_RecursiveDeref(dd, add_scale); + Cudd_RecursiveDeref(dd, res); + res = scaled; + } + } + cuddDeref(res); + return(res); + +} /* end of addMMRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addTriangle.] + + Description [Performs the recursive step of Cudd_addTriangle. Returns + a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + +******************************************************************************/ +static DdNode * +addTriangleRecur( + DdManager * dd, + DdNode * f, + DdNode * g, + int * vars, + DdNode *cube) +{ + DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res; + CUDD_VALUE_TYPE value; + int top, topf, topg, index; + + statLine(dd); + if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) { + return(DD_PLUS_INFINITY(dd)); + } + + if (cuddIsConstant(f) && cuddIsConstant(g)) { + value = cuddV(f) + cuddV(g); + res = cuddUniqueConst(dd, value); + return(res); + } + if (f < g) { + DdNode *tmp = f; + f = g; + g = tmp; + } + + if (f->ref != 1 || g->ref != 1) { + res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube); + if (res != NULL) { + return(res); + } + } + + topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); + top = ddMin(topf,topg); + + if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;} + if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;} + + t = addTriangleRecur(dd, fv, gv, vars, cube); + if (t == NULL) return(NULL); + cuddRef(t); + e = addTriangleRecur(dd, fvn, gvn, vars, cube); + if (e == NULL) { + Cudd_RecursiveDeref(dd, t); + return(NULL); + } + cuddRef(e); + + index = dd->invperm[top]; + if (vars[index] < 0) { + res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); + if (res == NULL) { + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + } else { + res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e); + if (res == NULL) { + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, t); + Cudd_RecursiveDeref(dd, e); + cuddDeref(res); + } + + if (f->ref != 1 || g->ref != 1) { + cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res); + } + + return(res); + +} /* end of addTriangleRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_addOuterSum.] + + Description [Performs the recursive step of Cudd_addOuterSum. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +cuddAddOuterSumRecur( + DdManager *dd, + DdNode *M, + DdNode *r, + DdNode *c) +{ + DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re; + int topM, topc, topr; + int v, index; + + statLine(dd); + /* Check special cases. */ + if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M); + + if (cuddIsConstant(c) && cuddIsConstant(r)) { + R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r)); + cuddRef(R); + if (cuddIsConstant(M)) { + if (cuddV(R) <= cuddV(M)) { + cuddDeref(R); + return(R); + } else { + Cudd_RecursiveDeref(dd,R); + return(M); + } + } else { + P = Cudd_addApply(dd,Cudd_addMinimum,R,M); + cuddRef(P); + Cudd_RecursiveDeref(dd,R); + cuddDeref(P); + return(P); + } + } + + /* Check the cache. */ + R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c); + if (R != NULL) return(R); + + topM = cuddI(dd,M->index); topr = cuddI(dd,r->index); + topc = cuddI(dd,c->index); + v = ddMin(topM,ddMin(topr,topc)); + + /* Compute cofactors. */ + if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; } + if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; } + if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; } + + /* Recursively solve. */ + Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct); + if (Rt == NULL) return(NULL); + cuddRef(Rt); + Re = cuddAddOuterSumRecur(dd,Me,re,ce); + if (Re == NULL) { + Cudd_RecursiveDeref(dd, Rt); + return(NULL); + } + cuddRef(Re); + index = dd->invperm[v]; + R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re); + if (R == NULL) { + Cudd_RecursiveDeref(dd, Rt); + Cudd_RecursiveDeref(dd, Re); + return(NULL); + } + cuddDeref(Rt); + cuddDeref(Re); + + /* Store the result in the cache. */ + cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R); + + return(R); + +} /* end of cuddAddOuterSumRecur */ diff --git a/abc70930/src/bdd/cudd/cuddPriority.c b/abc70930/src/bdd/cudd/cuddPriority.c new file mode 100644 index 00000000..788fc712 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddPriority.c @@ -0,0 +1,1475 @@ +/**CFile*********************************************************************** + + FileName [cuddPriority.c] + + PackageName [cudd] + + Synopsis [Priority functions.] + + Description [External procedures included in this file: +
        +
      • Cudd_PrioritySelect() +
      • Cudd_Xgty() +
      • Cudd_Xeqy() +
      • Cudd_addXeqy() +
      • Cudd_Dxygtdxz() +
      • Cudd_Dxygtdyz() +
      • Cudd_CProjection() +
      • Cudd_addHamming() +
      • Cudd_MinHammingDist() +
      • Cudd_bddClosestCube() +
      + Internal procedures included in this module: +
        +
      • cuddCProjectionRecur() +
      • cuddBddClosestCube() +
      + Static procedures included in this module: +
        +
      • cuddMinHammingDistRecur() +
      • separateCube() +
      • createResult() +
      + ] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddPriority.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ +static int cuddMinHammingDistRecur ARGS((DdNode * f, int *minterm, DdHashTable * table, int upperBound)); +static DdNode * separateCube ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE *distance)); +static DdNode * createResult ARGS((DdManager *dd, unsigned int index, unsigned int phase, DdNode *cube, CUDD_VALUE_TYPE distance)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Selects pairs from R using a priority function.] + + Description [Selects pairs from a relation R(x,y) (given as a BDD) + in such a way that a given x appears in one pair only. Uses a + priority function to determine which y should be paired to a given x. + Cudd_PrioritySelect returns a pointer to + the selected function if successful; NULL otherwise. + Three of the arguments--x, y, and z--are vectors of BDD variables. + The first two are the variables on which R depends. The third vectore + is a vector of auxiliary variables, used during the computation. This + vector is optional. If a NULL value is passed instead, + Cudd_PrioritySelect will create the working variables on the fly. + The sizes of x and y (and z if it is not NULL) should equal n. + The priority function Pi can be passed as a BDD, or can be built by + Cudd_PrioritySelect. If NULL is passed instead of a DdNode *, + parameter Pifunc is used by Cudd_PrioritySelect to build a BDD for the + priority function. (Pifunc is a pointer to a C function.) If Pi is not + NULL, then Pifunc is ignored. Pifunc should have the same interface as + the standard priority functions (e.g., Cudd_Dxygtdxz). + Cudd_PrioritySelect and Cudd_CProjection can sometimes be used + interchangeably. Specifically, calling Cudd_PrioritySelect with + Cudd_Xgty as Pifunc produces the same result as calling + Cudd_CProjection with the all-zero minterm as reference minterm. + However, depending on the application, one or the other may be + preferable: +
        +
      • When extracting representatives from an equivalence relation, + Cudd_CProjection has the advantage of nor requiring the auxiliary + variables. +
      • When computing matchings in general bipartite graphs, + Cudd_PrioritySelect normally obtains better results because it can use + more powerful matching schemes (e.g., Cudd_Dxygtdxz). +
      + ] + + SideEffects [If called with z == NULL, will create new variables in + the manager.] + + SeeAlso [Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_Xgty + Cudd_bddAdjPermuteX Cudd_CProjection] + +******************************************************************************/ +DdNode * +Cudd_PrioritySelect( + DdManager * dd /* manager */, + DdNode * R /* BDD of the relation */, + DdNode ** x /* array of x variables */, + DdNode ** y /* array of y variables */, + DdNode ** z /* array of z variables (optional: may be NULL) */, + DdNode * Pi /* BDD of the priority function (optional: may be NULL) */, + int n /* size of x, y, and z */, + DdNode * (*Pifunc)(DdManager *, int, DdNode **, DdNode **, DdNode **) /* function used to build Pi if it is NULL */) +{ + DdNode *res = NULL; + DdNode *zcube = NULL; + DdNode *Rxz, *Q; + int createdZ = 0; + int createdPi = 0; + int i; + + /* Create z variables if needed. */ + if (z == NULL) { + if (Pi != NULL) return(NULL); + z = ALLOC(DdNode *,n); + if (z == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + createdZ = 1; + for (i = 0; i < n; i++) { + if (dd->size >= (int) CUDD_MAXINDEX - 1) goto endgame; + z[i] = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one)); + if (z[i] == NULL) goto endgame; + } + } + + /* Create priority function BDD if needed. */ + if (Pi == NULL) { + Pi = Pifunc(dd,n,x,y,z); + if (Pi == NULL) goto endgame; + createdPi = 1; + cuddRef(Pi); + } + + /* Initialize abstraction cube. */ + zcube = DD_ONE(dd); + cuddRef(zcube); + for (i = n - 1; i >= 0; i--) { + DdNode *tmpp; + tmpp = Cudd_bddAnd(dd,z[i],zcube); + if (tmpp == NULL) goto endgame; + cuddRef(tmpp); + Cudd_RecursiveDeref(dd,zcube); + zcube = tmpp; + } + + /* Compute subset of (x,y) pairs. */ + Rxz = Cudd_bddSwapVariables(dd,R,y,z,n); + if (Rxz == NULL) goto endgame; + cuddRef(Rxz); + Q = Cudd_bddAndAbstract(dd,Rxz,Pi,zcube); + if (Q == NULL) { + Cudd_RecursiveDeref(dd,Rxz); + goto endgame; + } + cuddRef(Q); + Cudd_RecursiveDeref(dd,Rxz); + res = Cudd_bddAnd(dd,R,Cudd_Not(Q)); + if (res == NULL) { + Cudd_RecursiveDeref(dd,Q); + goto endgame; + } + cuddRef(res); + Cudd_RecursiveDeref(dd,Q); + +endgame: + if (zcube != NULL) Cudd_RecursiveDeref(dd,zcube); + if (createdZ) { + FREE(z); + } + if (createdPi) { + Cudd_RecursiveDeref(dd,Pi); + } + if (res != NULL) cuddDeref(res); + return(res); + +} /* Cudd_PrioritySelect */ + + +/**Function******************************************************************** + + Synopsis [Generates a BDD for the function x > y.] + + Description [This function generates a BDD for the function x > y. + Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and + y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. + The BDD is built bottom-up. + It has 3*N-1 internal nodes, if the variables are ordered as follows: + x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. + Argument z is not used by Cudd_Xgty: it is included to make it + call-compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz.] + + SideEffects [None] + + SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Dxygtdyz] + +******************************************************************************/ +DdNode * +Cudd_Xgty( + DdManager * dd /* DD manager */, + int N /* number of x and y variables */, + DdNode ** z /* array of z variables: unused */, + DdNode ** x /* array of x variables */, + DdNode ** y /* array of y variables */) +{ + DdNode *u, *v, *w; + int i; + + /* Build bottom part of BDD outside loop. */ + u = Cudd_bddAnd(dd, x[N-1], Cudd_Not(y[N-1])); + if (u == NULL) return(NULL); + cuddRef(u); + + /* Loop to build the rest of the BDD. */ + for (i = N-2; i >= 0; i--) { + v = Cudd_bddAnd(dd, y[i], Cudd_Not(u)); + if (v == NULL) { + Cudd_RecursiveDeref(dd, u); + return(NULL); + } + cuddRef(v); + w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u); + if (w == NULL) { + Cudd_RecursiveDeref(dd, u); + Cudd_RecursiveDeref(dd, v); + return(NULL); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, u); + u = Cudd_bddIte(dd, x[i], Cudd_Not(v), w); + if (u == NULL) { + Cudd_RecursiveDeref(dd, v); + Cudd_RecursiveDeref(dd, w); + return(NULL); + } + cuddRef(u); + Cudd_RecursiveDeref(dd, v); + Cudd_RecursiveDeref(dd, w); + + } + cuddDeref(u); + return(u); + +} /* end of Cudd_Xgty */ + + +/**Function******************************************************************** + + Synopsis [Generates a BDD for the function x==y.] + + Description [This function generates a BDD for the function x==y. + Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and + y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. + The BDD is built bottom-up. + It has 3*N-1 internal nodes, if the variables are ordered as follows: + x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ] + + SideEffects [None] + + SeeAlso [Cudd_addXeqy] + +******************************************************************************/ +DdNode * +Cudd_Xeqy( + DdManager * dd /* DD manager */, + int N /* number of x and y variables */, + DdNode ** x /* array of x variables */, + DdNode ** y /* array of y variables */) +{ + DdNode *u, *v, *w; + int i; + + /* Build bottom part of BDD outside loop. */ + u = Cudd_bddIte(dd, x[N-1], y[N-1], Cudd_Not(y[N-1])); + if (u == NULL) return(NULL); + cuddRef(u); + + /* Loop to build the rest of the BDD. */ + for (i = N-2; i >= 0; i--) { + v = Cudd_bddAnd(dd, y[i], u); + if (v == NULL) { + Cudd_RecursiveDeref(dd, u); + return(NULL); + } + cuddRef(v); + w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u); + if (w == NULL) { + Cudd_RecursiveDeref(dd, u); + Cudd_RecursiveDeref(dd, v); + return(NULL); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, u); + u = Cudd_bddIte(dd, x[i], v, w); + if (u == NULL) { + Cudd_RecursiveDeref(dd, v); + Cudd_RecursiveDeref(dd, w); + return(NULL); + } + cuddRef(u); + Cudd_RecursiveDeref(dd, v); + Cudd_RecursiveDeref(dd, w); + } + cuddDeref(u); + return(u); + +} /* end of Cudd_Xeqy */ + + +/**Function******************************************************************** + + Synopsis [Generates an ADD for the function x==y.] + + Description [This function generates an ADD for the function x==y. + Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and + y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. + The ADD is built bottom-up. + It has 3*N-1 internal nodes, if the variables are ordered as follows: + x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ] + + SideEffects [None] + + SeeAlso [Cudd_Xeqy] + +******************************************************************************/ +DdNode * +Cudd_addXeqy( + DdManager * dd /* DD manager */, + int N /* number of x and y variables */, + DdNode ** x /* array of x variables */, + DdNode ** y /* array of y variables */) +{ + DdNode *one, *zero; + DdNode *u, *v, *w; + int i; + + one = DD_ONE(dd); + zero = DD_ZERO(dd); + + /* Build bottom part of ADD outside loop. */ + v = Cudd_addIte(dd, y[N-1], one, zero); + if (v == NULL) return(NULL); + cuddRef(v); + w = Cudd_addIte(dd, y[N-1], zero, one); + if (w == NULL) { + Cudd_RecursiveDeref(dd, v); + return(NULL); + } + cuddRef(w); + u = Cudd_addIte(dd, x[N-1], v, w); + if (w == NULL) { + Cudd_RecursiveDeref(dd, v); + Cudd_RecursiveDeref(dd, w); + return(NULL); + } + cuddRef(u); + Cudd_RecursiveDeref(dd, v); + Cudd_RecursiveDeref(dd, w); + + /* Loop to build the rest of the ADD. */ + for (i = N-2; i >= 0; i--) { + v = Cudd_addIte(dd, y[i], u, zero); + if (v == NULL) { + Cudd_RecursiveDeref(dd, u); + return(NULL); + } + cuddRef(v); + w = Cudd_addIte(dd, y[i], zero, u); + if (w == NULL) { + Cudd_RecursiveDeref(dd, u); + Cudd_RecursiveDeref(dd, v); + return(NULL); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, u); + u = Cudd_addIte(dd, x[i], v, w); + if (w == NULL) { + Cudd_RecursiveDeref(dd, v); + Cudd_RecursiveDeref(dd, w); + return(NULL); + } + cuddRef(u); + Cudd_RecursiveDeref(dd, v); + Cudd_RecursiveDeref(dd, w); + } + cuddDeref(u); + return(u); + +} /* end of Cudd_addXeqy */ + + +/**Function******************************************************************** + + Synopsis [Generates a BDD for the function d(x,y) > d(x,z).] + + Description [This function generates a BDD for the function d(x,y) + > d(x,z); + x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\], + y\[0\] y\[1\] ... y\[N-1\], and z\[0\] z\[1\] ... z\[N-1\], + with 0 the most significant bit. + The distance d(x,y) is defined as: + \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}). + The BDD is built bottom-up. + It has 7*N-3 internal nodes, if the variables are ordered as follows: + x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ] + + SideEffects [None] + + SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdyz Cudd_Xgty Cudd_bddAdjPermuteX] + +******************************************************************************/ +DdNode * +Cudd_Dxygtdxz( + DdManager * dd /* DD manager */, + int N /* number of x, y, and z variables */, + DdNode ** x /* array of x variables */, + DdNode ** y /* array of y variables */, + DdNode ** z /* array of z variables */) +{ + DdNode *one, *zero; + DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1; + int i; + + one = DD_ONE(dd); + zero = Cudd_Not(one); + + /* Build bottom part of BDD outside loop. */ + y1_ = Cudd_bddIte(dd, y[N-1], one, Cudd_Not(z[N-1])); + if (y1_ == NULL) return(NULL); + cuddRef(y1_); + y2 = Cudd_bddIte(dd, y[N-1], z[N-1], one); + if (y2 == NULL) { + Cudd_RecursiveDeref(dd, y1_); + return(NULL); + } + cuddRef(y2); + x1 = Cudd_bddIte(dd, x[N-1], y1_, y2); + if (x1 == NULL) { + Cudd_RecursiveDeref(dd, y1_); + Cudd_RecursiveDeref(dd, y2); + return(NULL); + } + cuddRef(x1); + Cudd_RecursiveDeref(dd, y1_); + Cudd_RecursiveDeref(dd, y2); + + /* Loop to build the rest of the BDD. */ + for (i = N-2; i >= 0; i--) { + z1 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1)); + if (z1 == NULL) { + Cudd_RecursiveDeref(dd, x1); + return(NULL); + } + cuddRef(z1); + z2 = Cudd_bddIte(dd, z[i], x1, one); + if (z2 == NULL) { + Cudd_RecursiveDeref(dd, x1); + Cudd_RecursiveDeref(dd, z1); + return(NULL); + } + cuddRef(z2); + z3 = Cudd_bddIte(dd, z[i], one, x1); + if (z3 == NULL) { + Cudd_RecursiveDeref(dd, x1); + Cudd_RecursiveDeref(dd, z1); + Cudd_RecursiveDeref(dd, z2); + return(NULL); + } + cuddRef(z3); + z4 = Cudd_bddIte(dd, z[i], x1, zero); + if (z4 == NULL) { + Cudd_RecursiveDeref(dd, x1); + Cudd_RecursiveDeref(dd, z1); + Cudd_RecursiveDeref(dd, z2); + Cudd_RecursiveDeref(dd, z3); + return(NULL); + } + cuddRef(z4); + Cudd_RecursiveDeref(dd, x1); + y1_ = Cudd_bddIte(dd, y[i], z2, Cudd_Not(z1)); + if (y1_ == NULL) { + Cudd_RecursiveDeref(dd, z1); + Cudd_RecursiveDeref(dd, z2); + Cudd_RecursiveDeref(dd, z3); + Cudd_RecursiveDeref(dd, z4); + return(NULL); + } + cuddRef(y1_); + y2 = Cudd_bddIte(dd, y[i], z4, z3); + if (y2 == NULL) { + Cudd_RecursiveDeref(dd, z1); + Cudd_RecursiveDeref(dd, z2); + Cudd_RecursiveDeref(dd, z3); + Cudd_RecursiveDeref(dd, z4); + Cudd_RecursiveDeref(dd, y1_); + return(NULL); + } + cuddRef(y2); + Cudd_RecursiveDeref(dd, z1); + Cudd_RecursiveDeref(dd, z2); + Cudd_RecursiveDeref(dd, z3); + Cudd_RecursiveDeref(dd, z4); + x1 = Cudd_bddIte(dd, x[i], y1_, y2); + if (x1 == NULL) { + Cudd_RecursiveDeref(dd, y1_); + Cudd_RecursiveDeref(dd, y2); + return(NULL); + } + cuddRef(x1); + Cudd_RecursiveDeref(dd, y1_); + Cudd_RecursiveDeref(dd, y2); + } + cuddDeref(x1); + return(Cudd_Not(x1)); + +} /* end of Cudd_Dxygtdxz */ + + +/**Function******************************************************************** + + Synopsis [Generates a BDD for the function d(x,y) > d(y,z).] + + Description [This function generates a BDD for the function d(x,y) + > d(y,z); + x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\], + y\[0\] y\[1\] ... y\[N-1\], and z\[0\] z\[1\] ... z\[N-1\], + with 0 the most significant bit. + The distance d(x,y) is defined as: + \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}). + The BDD is built bottom-up. + It has 7*N-3 internal nodes, if the variables are ordered as follows: + x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ] + + SideEffects [None] + + SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Xgty Cudd_bddAdjPermuteX] + +******************************************************************************/ +DdNode * +Cudd_Dxygtdyz( + DdManager * dd /* DD manager */, + int N /* number of x, y, and z variables */, + DdNode ** x /* array of x variables */, + DdNode ** y /* array of y variables */, + DdNode ** z /* array of z variables */) +{ + DdNode *one, *zero; + DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1; + int i; + + one = DD_ONE(dd); + zero = Cudd_Not(one); + + /* Build bottom part of BDD outside loop. */ + y1_ = Cudd_bddIte(dd, y[N-1], one, z[N-1]); + if (y1_ == NULL) return(NULL); + cuddRef(y1_); + y2 = Cudd_bddIte(dd, y[N-1], z[N-1], zero); + if (y2 == NULL) { + Cudd_RecursiveDeref(dd, y1_); + return(NULL); + } + cuddRef(y2); + x1 = Cudd_bddIte(dd, x[N-1], y1_, Cudd_Not(y2)); + if (x1 == NULL) { + Cudd_RecursiveDeref(dd, y1_); + Cudd_RecursiveDeref(dd, y2); + return(NULL); + } + cuddRef(x1); + Cudd_RecursiveDeref(dd, y1_); + Cudd_RecursiveDeref(dd, y2); + + /* Loop to build the rest of the BDD. */ + for (i = N-2; i >= 0; i--) { + z1 = Cudd_bddIte(dd, z[i], x1, zero); + if (z1 == NULL) { + Cudd_RecursiveDeref(dd, x1); + return(NULL); + } + cuddRef(z1); + z2 = Cudd_bddIte(dd, z[i], x1, one); + if (z2 == NULL) { + Cudd_RecursiveDeref(dd, x1); + Cudd_RecursiveDeref(dd, z1); + return(NULL); + } + cuddRef(z2); + z3 = Cudd_bddIte(dd, z[i], one, x1); + if (z3 == NULL) { + Cudd_RecursiveDeref(dd, x1); + Cudd_RecursiveDeref(dd, z1); + Cudd_RecursiveDeref(dd, z2); + return(NULL); + } + cuddRef(z3); + z4 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1)); + if (z4 == NULL) { + Cudd_RecursiveDeref(dd, x1); + Cudd_RecursiveDeref(dd, z1); + Cudd_RecursiveDeref(dd, z2); + Cudd_RecursiveDeref(dd, z3); + return(NULL); + } + cuddRef(z4); + Cudd_RecursiveDeref(dd, x1); + y1_ = Cudd_bddIte(dd, y[i], z2, z1); + if (y1_ == NULL) { + Cudd_RecursiveDeref(dd, z1); + Cudd_RecursiveDeref(dd, z2); + Cudd_RecursiveDeref(dd, z3); + Cudd_RecursiveDeref(dd, z4); + return(NULL); + } + cuddRef(y1_); + y2 = Cudd_bddIte(dd, y[i], z4, Cudd_Not(z3)); + if (y2 == NULL) { + Cudd_RecursiveDeref(dd, z1); + Cudd_RecursiveDeref(dd, z2); + Cudd_RecursiveDeref(dd, z3); + Cudd_RecursiveDeref(dd, z4); + Cudd_RecursiveDeref(dd, y1_); + return(NULL); + } + cuddRef(y2); + Cudd_RecursiveDeref(dd, z1); + Cudd_RecursiveDeref(dd, z2); + Cudd_RecursiveDeref(dd, z3); + Cudd_RecursiveDeref(dd, z4); + x1 = Cudd_bddIte(dd, x[i], y1_, Cudd_Not(y2)); + if (x1 == NULL) { + Cudd_RecursiveDeref(dd, y1_); + Cudd_RecursiveDeref(dd, y2); + return(NULL); + } + cuddRef(x1); + Cudd_RecursiveDeref(dd, y1_); + Cudd_RecursiveDeref(dd, y2); + } + cuddDeref(x1); + return(Cudd_Not(x1)); + +} /* end of Cudd_Dxygtdyz */ + + +/**Function******************************************************************** + + Synopsis [Computes the compatible projection of R w.r.t. cube Y.] + + Description [Computes the compatible projection of relation R with + respect to cube Y. Returns a pointer to the c-projection if + successful; NULL otherwise. For a comparison between Cudd_CProjection + and Cudd_PrioritySelect, see the documentation of the latter.] + + SideEffects [None] + + SeeAlso [Cudd_PrioritySelect] + +******************************************************************************/ +DdNode * +Cudd_CProjection( + DdManager * dd, + DdNode * R, + DdNode * Y) +{ + DdNode *res; + DdNode *support; + + if (cuddCheckCube(dd,Y) == 0) { + (void) fprintf(dd->err, + "Error: The third argument of Cudd_CProjection should be a cube\n"); + dd->errorCode = CUDD_INVALID_ARG; + return(NULL); + } + + /* Compute the support of Y, which is used by the abstraction step + ** in cuddCProjectionRecur. + */ + support = Cudd_Support(dd,Y); + if (support == NULL) return(NULL); + cuddRef(support); + + do { + dd->reordered = 0; + res = cuddCProjectionRecur(dd,R,Y,support); + } while (dd->reordered == 1); + + if (res == NULL) { + Cudd_RecursiveDeref(dd,support); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd,support); + cuddDeref(res); + + return(res); + +} /* end of Cudd_CProjection */ + + +/**Function******************************************************************** + + Synopsis [Computes the Hamming distance ADD.] + + Description [Computes the Hamming distance ADD. Returns an ADD that + gives the Hamming distance between its two arguments if successful; + NULL otherwise. The two vectors xVars and yVars identify the variables + that form the two arguments.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_addHamming( + DdManager * dd, + DdNode ** xVars, + DdNode ** yVars, + int nVars) +{ + DdNode *result,*tempBdd; + DdNode *tempAdd,*temp; + int i; + + result = DD_ZERO(dd); + cuddRef(result); + + for (i = 0; i < nVars; i++) { + tempBdd = Cudd_bddIte(dd,xVars[i],Cudd_Not(yVars[i]),yVars[i]); + if (tempBdd == NULL) { + Cudd_RecursiveDeref(dd,result); + return(NULL); + } + cuddRef(tempBdd); + tempAdd = Cudd_BddToAdd(dd,tempBdd); + if (tempAdd == NULL) { + Cudd_RecursiveDeref(dd,tempBdd); + Cudd_RecursiveDeref(dd,result); + return(NULL); + } + cuddRef(tempAdd); + Cudd_RecursiveDeref(dd,tempBdd); + temp = Cudd_addApply(dd,Cudd_addPlus,tempAdd,result); + if (temp == NULL) { + Cudd_RecursiveDeref(dd,tempAdd); + Cudd_RecursiveDeref(dd,result); + return(NULL); + } + cuddRef(temp); + Cudd_RecursiveDeref(dd,tempAdd); + Cudd_RecursiveDeref(dd,result); + result = temp; + } + + cuddDeref(result); + return(result); + +} /* end of Cudd_addHamming */ + + +/**Function******************************************************************** + + Synopsis [Returns the minimum Hamming distance between f and minterm.] + + Description [Returns the minimum Hamming distance between the + minterms of a function f and a reference minterm. The function is + given as a BDD; the minterm is given as an array of integers, one + for each variable in the manager. Returns the minimum distance if + it is less than the upper bound; the upper bound if the minimum + distance is at least as large; CUDD_OUT_OF_MEM in case of failure.] + + SideEffects [None] + + SeeAlso [Cudd_addHamming Cudd_bddClosestCube] + +******************************************************************************/ +int +Cudd_MinHammingDist( + DdManager *dd /* DD manager */, + DdNode *f /* function to examine */, + int *minterm /* reference minterm */, + int upperBound /* distance above which an approximate answer is OK */) +{ + DdHashTable *table; + CUDD_VALUE_TYPE epsilon; + int res; + + table = cuddHashTableInit(dd,1,2); + if (table == NULL) { + return(CUDD_OUT_OF_MEM); + } + epsilon = Cudd_ReadEpsilon(dd); + Cudd_SetEpsilon(dd,(CUDD_VALUE_TYPE)0.0); + res = cuddMinHammingDistRecur(f,minterm,table,upperBound); + cuddHashTableQuit(table); + Cudd_SetEpsilon(dd,epsilon); + + return(res); + +} /* end of Cudd_MinHammingDist */ + + +/**Function******************************************************************** + + Synopsis [Finds a cube of f at minimum Hamming distance from g.] + + Description [Finds a cube of f at minimum Hamming distance from the + minterms of g. All the minterms of the cube are at the minimum + distance. If the distance is 0, the cube belongs to the + intersection of f and g. Returns the cube if successful; NULL + otherwise.] + + SideEffects [The distance is returned as a side effect.] + + SeeAlso [Cudd_MinHammingDist] + +******************************************************************************/ +DdNode * +Cudd_bddClosestCube( + DdManager *dd, + DdNode * f, + DdNode *g, + int *distance) +{ + DdNode *res, *acube; + CUDD_VALUE_TYPE rdist; + + /* Compute the cube and distance as a single ADD. */ + do { + dd->reordered = 0; + res = cuddBddClosestCube(dd,f,g,CUDD_CONST_INDEX + 1.0); + } while (dd->reordered == 1); + if (res == NULL) return(NULL); + cuddRef(res); + + /* Unpack distance and cube. */ + do { + dd->reordered = 0; + acube = separateCube(dd, res, &rdist); + } while (dd->reordered == 1); + if (acube == NULL) { + Cudd_RecursiveDeref(dd, res); + return(NULL); + } + cuddRef(acube); + Cudd_RecursiveDeref(dd, res); + + /* Convert cube from ADD to BDD. */ + do { + dd->reordered = 0; + res = cuddAddBddDoPattern(dd, acube); + } while (dd->reordered == 1); + if (res == NULL) { + Cudd_RecursiveDeref(dd, acube); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, acube); + + *distance = (int) rdist; + cuddDeref(res); + return(res); + +} /* end of Cudd_bddClosestCube */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_CProjection.] + + Description [Performs the recursive step of Cudd_CProjection. Returns + the projection if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_CProjection] + +******************************************************************************/ +DdNode * +cuddCProjectionRecur( + DdManager * dd, + DdNode * R, + DdNode * Y, + DdNode * Ysupp) +{ + DdNode *res, *res1, *res2, *resA; + DdNode *r, *y, *RT, *RE, *YT, *YE, *Yrest, *Ra, *Ran, *Gamma, *Alpha; + unsigned int topR, topY, top, index; + DdNode *one = DD_ONE(dd); + + statLine(dd); + if (Y == one) return(R); + +#ifdef DD_DEBUG + assert(!Cudd_IsConstant(Y)); +#endif + + if (R == Cudd_Not(one)) return(R); + + res = cuddCacheLookup2(dd, Cudd_CProjection, R, Y); + if (res != NULL) return(res); + + r = Cudd_Regular(R); + topR = cuddI(dd,r->index); + y = Cudd_Regular(Y); + topY = cuddI(dd,y->index); + + top = ddMin(topR, topY); + + /* Compute the cofactors of R */ + if (topR == top) { + index = r->index; + RT = cuddT(r); + RE = cuddE(r); + if (r != R) { + RT = Cudd_Not(RT); RE = Cudd_Not(RE); + } + } else { + RT = RE = R; + } + + if (topY > top) { + /* Y does not depend on the current top variable. + ** We just need to compute the results on the two cofactors of R + ** and make them the children of a node labeled r->index. + */ + res1 = cuddCProjectionRecur(dd,RT,Y,Ysupp); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res2 = cuddCProjectionRecur(dd,RE,Y,Ysupp); + if (res2 == NULL) { + Cudd_RecursiveDeref(dd,res1); + return(NULL); + } + cuddRef(res2); + res = cuddBddIteRecur(dd, dd->vars[index], res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(dd,res1); + Cudd_RecursiveDeref(dd,res2); + return(NULL); + } + /* If we have reached this point, res1 and res2 are now + ** incorporated in res. cuddDeref is therefore sufficient. + */ + cuddDeref(res1); + cuddDeref(res2); + } else { + /* Compute the cofactors of Y */ + index = y->index; + YT = cuddT(y); + YE = cuddE(y); + if (y != Y) { + YT = Cudd_Not(YT); YE = Cudd_Not(YE); + } + if (YT == Cudd_Not(one)) { + Alpha = Cudd_Not(dd->vars[index]); + Yrest = YE; + Ra = RE; + Ran = RT; + } else { + Alpha = dd->vars[index]; + Yrest = YT; + Ra = RT; + Ran = RE; + } + Gamma = cuddBddExistAbstractRecur(dd,Ra,cuddT(Ysupp)); + if (Gamma == NULL) return(NULL); + if (Gamma == one) { + res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res = cuddBddAndRecur(dd, Alpha, res1); + if (res == NULL) { + Cudd_RecursiveDeref(dd,res1); + return(NULL); + } + cuddDeref(res1); + } else if (Gamma == Cudd_Not(one)) { + res1 = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); + if (res1 == NULL) return(NULL); + cuddRef(res1); + res = cuddBddAndRecur(dd, Cudd_Not(Alpha), res1); + if (res == NULL) { + Cudd_RecursiveDeref(dd,res1); + return(NULL); + } + cuddDeref(res1); + } else { + cuddRef(Gamma); + resA = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); + if (resA == NULL) { + Cudd_RecursiveDeref(dd,Gamma); + return(NULL); + } + cuddRef(resA); + res2 = cuddBddAndRecur(dd, Cudd_Not(Gamma), resA); + if (res2 == NULL) { + Cudd_RecursiveDeref(dd,Gamma); + Cudd_RecursiveDeref(dd,resA); + return(NULL); + } + cuddRef(res2); + Cudd_RecursiveDeref(dd,Gamma); + Cudd_RecursiveDeref(dd,resA); + res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); + if (res1 == NULL) { + Cudd_RecursiveDeref(dd,res2); + return(NULL); + } + cuddRef(res1); + res = cuddBddIteRecur(dd, Alpha, res1, res2); + if (res == NULL) { + Cudd_RecursiveDeref(dd,res1); + Cudd_RecursiveDeref(dd,res2); + return(NULL); + } + cuddDeref(res1); + cuddDeref(res2); + } + } + + cuddCacheInsert2(dd,Cudd_CProjection,R,Y,res); + + return(res); + +} /* end of cuddCProjectionRecur */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddClosestCube.] + + Description [Performs the recursive step of Cudd_bddClosestCube. + Returns the cube if succesful; NULL otherwise. The procedure uses a + four-way recursion to examine all four combinations of cofactors of + f and g. The most interesting feature of this function is the + scheme used for caching the results in the global computed table. + Since we have a cube and a distance, we combine them to form an ADD. + The combination replaces the zero child of the top node of the cube + with the negative of the distance. (The use of the negative is to + avoid ambiguity with 1.) The degenerate cases (zero and one) are + treated specially because the distance is known (0 for one, and + infinity for zero).] + + SideEffects [None] + + SeeAlso [Cudd_bddClosestCube] + +******************************************************************************/ +DdNode * +cuddBddClosestCube( + DdManager *dd, + DdNode *f, + DdNode *g, + CUDD_VALUE_TYPE bound) +{ + DdNode *res, *F, *G, *ft, *fe, *gt, *ge, *tt, *ee; + DdNode *ctt, *cee, *cte, *cet; + CUDD_VALUE_TYPE minD, dtt, dee, dte, det; + DdNode *one = DD_ONE(dd); + DdNode *lzero = Cudd_Not(one); + DdNode *azero = DD_ZERO(dd); + unsigned int topf, topg, index; + + statLine(dd); + if (bound < (f == Cudd_Not(g))) return(azero); + /* Terminal cases. */ + if (g == lzero || f == lzero) return(azero); + if (f == one && g == one) return(one); + + /* Check cache. */ + F = Cudd_Regular(f); + G = Cudd_Regular(g); + if (F->ref != 1 || G->ref != 1) { + res = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, + DdNode *)) Cudd_bddClosestCube, f, g); + if (res != NULL) return(res); + } + + topf = cuddI(dd,F->index); + topg = cuddI(dd,G->index); + + /* Compute cofactors. */ + if (topf <= topg) { + index = F->index; + ft = cuddT(F); + fe = cuddE(F); + if (Cudd_IsComplement(f)) { + ft = Cudd_Not(ft); + fe = Cudd_Not(fe); + } + } else { + index = G->index; + ft = fe = f; + } + + if (topg <= topf) { + gt = cuddT(G); + ge = cuddE(G); + if (Cudd_IsComplement(g)) { + gt = Cudd_Not(gt); + ge = Cudd_Not(ge); + } + } else { + gt = ge = g; + } + + tt = cuddBddClosestCube(dd,ft,gt,bound); + if (tt == NULL) return(NULL); + cuddRef(tt); + ctt = separateCube(dd,tt,&dtt); + if (ctt == NULL) { + Cudd_RecursiveDeref(dd, tt); + return(NULL); + } + cuddRef(ctt); + Cudd_RecursiveDeref(dd, tt); + minD = dtt; + bound = ddMin(bound,minD); + + ee = cuddBddClosestCube(dd,fe,ge,bound); + if (ee == NULL) { + Cudd_RecursiveDeref(dd, ctt); + return(NULL); + } + cuddRef(ee); + cee = separateCube(dd,ee,&dee); + if (cee == NULL) { + Cudd_RecursiveDeref(dd, ctt); + Cudd_RecursiveDeref(dd, ee); + return(NULL); + } + cuddRef(cee); + Cudd_RecursiveDeref(dd, ee); + minD = ddMin(dtt, dee); + bound = ddMin(bound,minD-1); + + if (minD > 0 && topf == topg) { + DdNode *te = cuddBddClosestCube(dd,ft,ge,bound-1); + if (te == NULL) { + Cudd_RecursiveDeref(dd, ctt); + Cudd_RecursiveDeref(dd, cee); + return(NULL); + } + cuddRef(te); + cte = separateCube(dd,te,&dte); + if (cte == NULL) { + Cudd_RecursiveDeref(dd, ctt); + Cudd_RecursiveDeref(dd, cee); + Cudd_RecursiveDeref(dd, te); + return(NULL); + } + cuddRef(cte); + Cudd_RecursiveDeref(dd, te); + dte += 1.0; + minD = ddMin(minD, dte); + } else { + cte = azero; + cuddRef(cte); + dte = CUDD_CONST_INDEX + 1.0; + } + bound = ddMin(bound,minD-1); + + if (minD > 0 && topf == topg) { + DdNode *et = cuddBddClosestCube(dd,fe,gt,bound-1); + if (et == NULL) { + Cudd_RecursiveDeref(dd, ctt); + Cudd_RecursiveDeref(dd, cee); + Cudd_RecursiveDeref(dd, cte); + return(NULL); + } + cuddRef(et); + cet = separateCube(dd,et,&det); + if (cet == NULL) { + Cudd_RecursiveDeref(dd, ctt); + Cudd_RecursiveDeref(dd, cee); + Cudd_RecursiveDeref(dd, cte); + Cudd_RecursiveDeref(dd, et); + return(NULL); + } + cuddRef(cet); + Cudd_RecursiveDeref(dd, et); + det += 1.0; + minD = ddMin(minD, det); + } else { + cet = azero; + cuddRef(cet); + det = CUDD_CONST_INDEX + 1.0; + } + + if (minD == dtt) { + if (dtt == dee && ctt == cee) { + res = createResult(dd,CUDD_CONST_INDEX,1,ctt,dtt); + } else { + res = createResult(dd,index,1,ctt,dtt); + } + } else if (minD == dee) { + res = createResult(dd,index,0,cee,dee); + } else if (minD == dte) { + res = createResult(dd,index,(topf <= topg),cte,dte); + } else { + res = createResult(dd,index,(topf > topg),cet,det); + } + cuddRef(res); + Cudd_RecursiveDeref(dd, ctt); + Cudd_RecursiveDeref(dd, cee); + Cudd_RecursiveDeref(dd, cte); + Cudd_RecursiveDeref(dd, cet); + + if (F->ref != 1 || G->ref != 1) + cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, + DdNode *)) Cudd_bddClosestCube, f, g, res); + + cuddDeref(res); + return(res); + +} /* end of cuddBddClosestCube */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_MinHammingDist.] + + Description [Performs the recursive step of Cudd_MinHammingDist. + It is based on the following identity. Let H(f) be the + minimum Hamming distance of the minterms of f from the reference + minterm. Then: + + H(f) = min(H(f0)+h0,H(f1)+h1) + + where f0 and f1 are the two cofactors of f with respect to its top + variable; h0 is 1 if the minterm assigns 1 to the top variable of f; + h1 is 1 if the minterm assigns 0 to the top variable of f. + The upper bound on the distance is used to bound the depth of the + recursion. + Returns the minimum distance unless it exceeds the upper bound or + computation fails.] + + SideEffects [None] + + SeeAlso [Cudd_MinHammingDist] + +******************************************************************************/ +static int +cuddMinHammingDistRecur( + DdNode * f, + int *minterm, + DdHashTable * table, + int upperBound) +{ + DdNode *F, *Ft, *Fe; + double h, hT, hE; + DdNode *zero, *res; + DdManager *dd = table->manager; + + statLine(dd); + if (upperBound == 0) return(0); + + F = Cudd_Regular(f); + + if (cuddIsConstant(F)) { + zero = Cudd_Not(DD_ONE(dd)); + if (f == dd->background || f == zero) { + return(upperBound); + } else { + return(0); + } + } + if ((res = cuddHashTableLookup1(table,f)) != NULL) { + h = cuddV(res); + if (res->ref == 0) { + dd->dead++; + dd->constants.dead++; + } + return((int) h); + } + + Ft = cuddT(F); Fe = cuddE(F); + if (Cudd_IsComplement(f)) { + Ft = Cudd_Not(Ft); Fe = Cudd_Not(Fe); + } + if (minterm[F->index] == 0) { + DdNode *temp = Ft; + Ft = Fe; Fe = temp; + } + + hT = cuddMinHammingDistRecur(Ft,minterm,table,upperBound); + if (hT == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); + if (hT == 0) { + hE = upperBound; + } else { + hE = cuddMinHammingDistRecur(Fe,minterm,table,upperBound - 1); + if (hE == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); + } + h = ddMin(hT, hE + 1); + + if (F->ref != 1) { + ptrint fanout = (ptrint) F->ref; + cuddSatDec(fanout); + res = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) h); + if (!cuddHashTableInsert1(table,f,res,fanout)) { + cuddRef(res); Cudd_RecursiveDeref(dd, res); + return(CUDD_OUT_OF_MEM); + } + } + + return((int) h); + +} /* end of cuddMinHammingDistRecur */ + + +/**Function******************************************************************** + + Synopsis [Separates cube from distance.] + + Description [Separates cube from distance. Returns the cube if + successful; NULL otherwise.] + + SideEffects [The distance is returned as a side effect.] + + SeeAlso [cuddBddClosestCube createResult] + +******************************************************************************/ +static DdNode * +separateCube( + DdManager *dd, + DdNode *f, + CUDD_VALUE_TYPE *distance) +{ + DdNode *cube, *t; + + /* One and zero are special cases because the distance is implied. */ + if (Cudd_IsConstant(f)) { + *distance = (f == DD_ONE(dd)) ? 0.0 : + (1.0 + (CUDD_VALUE_TYPE) CUDD_CONST_INDEX); + return(f); + } + + /* Find out which branch points to the distance and replace the top + ** node with one pointing to zero instead. */ + t = cuddT(f); + if (Cudd_IsConstant(t) && cuddV(t) <= 0) { +#ifdef DD_DEBUG + assert(!Cudd_IsConstant(cuddE(f)) || cuddE(f) == DD_ONE(dd)); +#endif + *distance = -cuddV(t); + cube = cuddUniqueInter(dd, f->index, DD_ZERO(dd), cuddE(f)); + } else { +#ifdef DD_DEBUG + assert(!Cudd_IsConstant(t) || t == DD_ONE(dd)); +#endif + *distance = -cuddV(cuddE(f)); + cube = cuddUniqueInter(dd, f->index, t, DD_ZERO(dd)); + } + + return(cube); + +} /* end of separateCube */ + + +/**Function******************************************************************** + + Synopsis [Builds a result for cache storage.] + + Description [Builds a result for cache storage. Returns a pointer + to the resulting ADD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddBddClosestCube separateCube] + +******************************************************************************/ +static DdNode * +createResult( + DdManager *dd, + unsigned int index, + unsigned int phase, + DdNode *cube, + CUDD_VALUE_TYPE distance) +{ + DdNode *res, *constant; + + /* Special case. The cube is either one or zero, and we do not + ** add any variables. Hence, the result is also one or zero, + ** and the distance remains implied by teh value of the constant. */ + if (index == CUDD_CONST_INDEX && Cudd_IsConstant(cube)) return(cube); + + constant = cuddUniqueConst(dd,-distance); + if (constant == NULL) return(NULL); + cuddRef(constant); + + if (index == CUDD_CONST_INDEX) { + /* Replace the top node. */ + if (cuddT(cube) == DD_ZERO(dd)) { + res = cuddUniqueInter(dd,cube->index,constant,cuddE(cube)); + } else { + res = cuddUniqueInter(dd,cube->index,cuddT(cube),constant); + } + } else { + /* Add a new top node. */ +#ifdef DD_DEBUG + assert(cuddI(dd,index) < cuddI(dd,cube->index)); +#endif + if (phase) { + res = cuddUniqueInter(dd,index,cube,constant); + } else { + res = cuddUniqueInter(dd,index,constant,cube); + } + } + if (res == NULL) { + Cudd_RecursiveDeref(dd, constant); + return(NULL); + } + cuddDeref(constant); /* safe because constant is part of res */ + + return(res); + +} /* end of createResult */ diff --git a/abc70930/src/bdd/cudd/cuddRead.c b/abc70930/src/bdd/cudd/cuddRead.c new file mode 100644 index 00000000..2c4a86d8 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddRead.c @@ -0,0 +1,490 @@ +/**CFile*********************************************************************** + + FileName [cuddRead.c] + + PackageName [cudd] + + Synopsis [Functions to read in a matrix] + + Description [External procedures included in this module: +
        +
      • Cudd_addRead() +
      • Cudd_bddRead() +
      ] + + SeeAlso [cudd_addHarwell.c] + + Author [Fabio Somenzi] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddRead.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Reads in a sparse matrix.] + + Description [Reads in a sparse matrix specified in a simple format. + The first line of the input contains the numbers of rows and columns. + The remaining lines contain the elements of the matrix, one per line. + Given a background value + (specified by the background field of the manager), only the values + different from it are explicitly listed. Each foreground element is + described by two integers, i.e., the row and column number, and a + real number, i.e., the value.

      + Cudd_addRead produces an ADD that depends on two sets of variables: x + and y. The x variables (x\[0\] ... x\[nx-1\]) encode the row index and + the y variables (y\[0\] ... y\[ny-1\]) encode the column index. + x\[0\] and y\[0\] are the most significant bits in the indices. + The variables may already exist or may be created by the function. + The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.

      + On input, nx and ny hold the numbers + of row and column variables already in existence. On output, they + hold the numbers of row and column variables actually used by the + matrix. When Cudd_addRead creates the variable arrays, + the index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy. + When some variables already exist Cudd_addRead expects the indices + of the existing x variables to be bx+i*sx, and the indices of the + existing y variables to be by+i*sy.

      + m and n are set to the numbers of rows and columns of the + matrix. Their values on input are immaterial. + The ADD for the + sparse matrix is returned in E, and its reference count is > 0. + Cudd_addRead returns 1 in case of success; 0 otherwise.] + + SideEffects [nx and ny are set to the numbers of row and column + variables. m and n are set to the numbers of rows and columns. x and y + are possibly extended to represent the array of row and column + variables. Similarly for xn and yn_, which hold on return from + Cudd_addRead the complements of the row and column variables.] + + SeeAlso [Cudd_addHarwell Cudd_bddRead] + +******************************************************************************/ +int +Cudd_addRead( + FILE * fp /* input file pointer */, + DdManager * dd /* DD manager */, + DdNode ** E /* characteristic function of the graph */, + DdNode *** x /* array of row variables */, + DdNode *** y /* array of column variables */, + DdNode *** xn /* array of complemented row variables */, + DdNode *** yn_ /* array of complemented column variables */, + int * nx /* number or row variables */, + int * ny /* number or column variables */, + int * m /* number of rows */, + int * n /* number of columns */, + int bx /* first index of row variables */, + int sx /* step of row variables */, + int by /* first index of column variables */, + int sy /* step of column variables */) +{ + DdNode *one, *zero; + DdNode *w, *neW; + DdNode *minterm1; + int u, v, err, i, nv; + int lnx, lny; + CUDD_VALUE_TYPE val; + DdNode **lx, **ly, **lxn, **lyn; + + one = DD_ONE(dd); + zero = DD_ZERO(dd); + + err = fscanf(fp, "%d %d", &u, &v); + if (err == EOF) { + return(0); + } else if (err != 2) { + return(0); + } + + *m = u; + /* Compute the number of x variables. */ + lx = *x; lxn = *xn; + u--; /* row and column numbers start from 0 */ + for (lnx=0; u > 0; lnx++) { + u >>= 1; + } + /* Here we rely on the fact that REALLOC of a null pointer is + ** translates to an ALLOC. + */ + if (lnx > *nx) { + *x = lx = REALLOC(DdNode *, *x, lnx); + if (lx == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *xn = lxn = REALLOC(DdNode *, *xn, lnx); + if (lxn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } + + *n = v; + /* Compute the number of y variables. */ + ly = *y; lyn = *yn_; + v--; /* row and column numbers start from 0 */ + for (lny=0; v > 0; lny++) { + v >>= 1; + } + /* Here we rely on the fact that REALLOC of a null pointer is + ** translates to an ALLOC. + */ + if (lny > *ny) { + *y = ly = REALLOC(DdNode *, *y, lny); + if (ly == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + *yn_ = lyn = REALLOC(DdNode *, *yn_, lny); + if (lyn == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } + + /* Create all new variables. */ + for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) { + do { + dd->reordered = 0; + lx[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (lx[i] == NULL) return(0); + cuddRef(lx[i]); + do { + dd->reordered = 0; + lxn[i] = cuddUniqueInter(dd, nv, zero, one); + } while (dd->reordered == 1); + if (lxn[i] == NULL) return(0); + cuddRef(lxn[i]); + } + for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) { + do { + dd->reordered = 0; + ly[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (ly[i] == NULL) return(0); + cuddRef(ly[i]); + do { + dd->reordered = 0; + lyn[i] = cuddUniqueInter(dd, nv, zero, one); + } while (dd->reordered == 1); + if (lyn[i] == NULL) return(0); + cuddRef(lyn[i]); + } + *nx = lnx; + *ny = lny; + + *E = dd->background; /* this call will never cause reordering */ + cuddRef(*E); + + while (! feof(fp)) { + err = fscanf(fp, "%d %d %lf", &u, &v, &val); + if (err == EOF) { + break; + } else if (err != 3) { + return(0); + } else if (u >= *m || v >= *n || u < 0 || v < 0) { + return(0); + } + + minterm1 = one; cuddRef(minterm1); + + /* Build minterm1 corresponding to this arc */ + for (i = lnx - 1; i>=0; i--) { + if (u & 1) { + w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lx[i]); + } else { + w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lxn[i]); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + minterm1 = w; + u >>= 1; + } + for (i = lny - 1; i>=0; i--) { + if (v & 1) { + w = Cudd_addApply(dd, Cudd_addTimes, minterm1, ly[i]); + } else { + w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lyn[i]); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + minterm1 = w; + v >>= 1; + } + /* Create new constant node if necessary. + ** This call will never cause reordering. + */ + neW = cuddUniqueConst(dd, val); + if (neW == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + cuddRef(neW); + + w = Cudd_addIte(dd, minterm1, neW, *E); + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + Cudd_RecursiveDeref(dd, neW); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + Cudd_RecursiveDeref(dd, neW); + Cudd_RecursiveDeref(dd, *E); + *E = w; + } + return(1); + +} /* end of Cudd_addRead */ + + +/**Function******************************************************************** + + Synopsis [Reads in a graph (without labels) given as a list of arcs.] + + Description [Reads in a graph (without labels) given as an adjacency + matrix. The first line of the input contains the numbers of rows and + columns of the adjacency matrix. The remaining lines contain the arcs + of the graph, one per line. Each arc is described by two integers, + i.e., the row and column number, or the indices of the two endpoints. + Cudd_bddRead produces a BDD that depends on two sets of variables: x + and y. The x variables (x\[0\] ... x\[nx-1\]) encode + the row index and the y variables (y\[0\] ... y\[ny-1\]) encode the + column index. x\[0\] and y\[0\] are the most significant bits in the + indices. + The variables may already exist or may be created by the function. + The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.

      + On input, nx and ny hold the numbers of row and column variables already + in existence. On output, they hold the numbers of row and column + variables actually used by the matrix. When Cudd_bddRead creates the + variable arrays, the index of x\[i\] is bx+i*sx, and the index of + y\[i\] is by+i*sy. When some variables already exist, Cudd_bddRead + expects the indices of the existing x variables to be bx+i*sx, and the + indices of the existing y variables to be by+i*sy.

      + m and n are set to the numbers of rows and columns of the + matrix. Their values on input are immaterial. The BDD for the graph + is returned in E, and its reference count is > 0. Cudd_bddRead returns + 1 in case of success; 0 otherwise.] + + SideEffects [nx and ny are set to the numbers of row and column + variables. m and n are set to the numbers of rows and columns. x and y + are possibly extended to represent the array of row and column + variables.] + + SeeAlso [Cudd_addHarwell Cudd_addRead] + +******************************************************************************/ +int +Cudd_bddRead( + FILE * fp /* input file pointer */, + DdManager * dd /* DD manager */, + DdNode ** E /* characteristic function of the graph */, + DdNode *** x /* array of row variables */, + DdNode *** y /* array of column variables */, + int * nx /* number or row variables */, + int * ny /* number or column variables */, + int * m /* number of rows */, + int * n /* number of columns */, + int bx /* first index of row variables */, + int sx /* step of row variables */, + int by /* first index of column variables */, + int sy /* step of column variables */) +{ + DdNode *one, *zero; + DdNode *w; + DdNode *minterm1; + int u, v, err, i, nv; + int lnx, lny; + DdNode **lx, **ly; + + one = DD_ONE(dd); + zero = Cudd_Not(one); + + err = fscanf(fp, "%d %d", &u, &v); + if (err == EOF) { + return(0); + } else if (err != 2) { + return(0); + } + + *m = u; + /* Compute the number of x variables. */ + lx = *x; + u--; /* row and column numbers start from 0 */ + for (lnx=0; u > 0; lnx++) { + u >>= 1; + } + if (lnx > *nx) { + *x = lx = REALLOC(DdNode *, *x, lnx); + if (lx == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } + + *n = v; + /* Compute the number of y variables. */ + ly = *y; + v--; /* row and column numbers start from 0 */ + for (lny=0; v > 0; lny++) { + v >>= 1; + } + if (lny > *ny) { + *y = ly = REALLOC(DdNode *, *y, lny); + if (ly == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + } + + /* Create all new variables. */ + for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) { + do { + dd->reordered = 0; + lx[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (lx[i] == NULL) return(0); + cuddRef(lx[i]); + } + for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) { + do { + dd->reordered = 0; + ly[i] = cuddUniqueInter(dd, nv, one, zero); + } while (dd->reordered == 1); + if (ly[i] == NULL) return(0); + cuddRef(ly[i]); + } + *nx = lnx; + *ny = lny; + + *E = zero; /* this call will never cause reordering */ + cuddRef(*E); + + while (! feof(fp)) { + err = fscanf(fp, "%d %d", &u, &v); + if (err == EOF) { + break; + } else if (err != 2) { + return(0); + } else if (u >= *m || v >= *n || u < 0 || v < 0) { + return(0); + } + + minterm1 = one; cuddRef(minterm1); + + /* Build minterm1 corresponding to this arc. */ + for (i = lnx - 1; i>=0; i--) { + if (u & 1) { + w = Cudd_bddAnd(dd, minterm1, lx[i]); + } else { + w = Cudd_bddAnd(dd, minterm1, Cudd_Not(lx[i])); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd,minterm1); + minterm1 = w; + u >>= 1; + } + for (i = lny - 1; i>=0; i--) { + if (v & 1) { + w = Cudd_bddAnd(dd, minterm1, ly[i]); + } else { + w = Cudd_bddAnd(dd, minterm1, Cudd_Not(ly[i])); + } + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + minterm1 = w; + v >>= 1; + } + + w = Cudd_bddAnd(dd, Cudd_Not(minterm1), Cudd_Not(*E)); + if (w == NULL) { + Cudd_RecursiveDeref(dd, minterm1); + return(0); + } + w = Cudd_Not(w); + cuddRef(w); + Cudd_RecursiveDeref(dd, minterm1); + Cudd_RecursiveDeref(dd, *E); + *E = w; + } + return(1); + +} /* end of Cudd_bddRead */ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/cudd/cuddRef.c b/abc70930/src/bdd/cudd/cuddRef.c new file mode 100644 index 00000000..a9241f3d --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddRef.c @@ -0,0 +1,781 @@ +/**CFile*********************************************************************** + + FileName [cuddRef.c] + + PackageName [cudd] + + Synopsis [Functions that manipulate the reference counts.] + + Description [External procedures included in this module: +

        +
      • Cudd_Ref() +
      • Cudd_RecursiveDeref() +
      • Cudd_IterDerefBdd() +
      • Cudd_DelayedDerefBdd() +
      • Cudd_RecursiveDerefZdd() +
      • Cudd_Deref() +
      • Cudd_CheckZeroRef() +
      + Internal procedures included in this module: +
        +
      • cuddReclaim() +
      • cuddReclaimZdd() +
      • cuddClearDeathRow() +
      • cuddShrinkDeathRow() +
      • cuddIsInDeathRow() +
      • cuddTimesInDeathRow() +
      + ] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddRef.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Increases the reference count of a node, if it is not + saturated.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_RecursiveDeref Cudd_Deref] + +******************************************************************************/ +void +Cudd_Ref( + DdNode * n) +{ + + n = Cudd_Regular(n); + + cuddSatInc(n->ref); + +} /* end of Cudd_Ref */ + + +/**Function******************************************************************** + + Synopsis [Decreases the reference count of node n.] + + Description [Decreases the reference count of node n. If n dies, + recursively decreases the reference counts of its children. It is + used to dispose of a DD that is no longer needed.] + + SideEffects [None] + + SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDerefZdd] + +******************************************************************************/ +void +Cudd_RecursiveDeref( + DdManager * table, + DdNode * n) +{ + DdNode *N; + int ord; + DdNodePtr *stack = table->stack; + int SP = 1; + + unsigned int live = table->keys - table->dead; + if (live > table->peakLiveNodes) { + table->peakLiveNodes = live; + } + + N = Cudd_Regular(n); + + do { +#ifdef DD_DEBUG + assert(N->ref != 0); +#endif + + if (N->ref == 1) { + N->ref = 0; + table->dead++; +#ifdef DD_STATS + table->nodesDropped++; +#endif + if (cuddIsConstant(N)) { + table->constants.dead++; + N = stack[--SP]; + } else { + ord = table->perm[N->index]; + stack[SP++] = Cudd_Regular(cuddE(N)); + table->subtables[ord].dead++; + N = cuddT(N); + } + } else { + cuddSatDec(N->ref); + N = stack[--SP]; + } + } while (SP != 0); + +} /* end of Cudd_RecursiveDeref */ + + +/**Function******************************************************************** + + Synopsis [Decreases the reference count of BDD node n.] + + Description [Decreases the reference count of node n. If n dies, + recursively decreases the reference counts of its children. It is + used to dispose of a BDD that is no longer needed. It is more + efficient than Cudd_RecursiveDeref, but it cannot be used on + ADDs. The greater efficiency comes from being able to assume that no + constant node will ever die as a result of a call to this + procedure.] + + SideEffects [None] + + SeeAlso [Cudd_RecursiveDeref Cudd_DelayedDerefBdd] + +******************************************************************************/ +void +Cudd_IterDerefBdd( + DdManager * table, + DdNode * n) +{ + DdNode *N; + int ord; + DdNodePtr *stack = table->stack; + int SP = 1; + + unsigned int live = table->keys - table->dead; + if (live > table->peakLiveNodes) { + table->peakLiveNodes = live; + } + + N = Cudd_Regular(n); + + do { +#ifdef DD_DEBUG + assert(N->ref != 0); +#endif + + if (N->ref == 1) { + N->ref = 0; + table->dead++; +#ifdef DD_STATS + table->nodesDropped++; +#endif + ord = table->perm[N->index]; + stack[SP++] = Cudd_Regular(cuddE(N)); + table->subtables[ord].dead++; + N = cuddT(N); + } else { + cuddSatDec(N->ref); + N = stack[--SP]; + } + } while (SP != 0); + +} /* end of Cudd_IterDerefBdd */ + + +/**Function******************************************************************** + + Synopsis [Decreases the reference count of BDD node n.] + + Description [Enqueues node n for later dereferencing. If the queue + is full decreases the reference count of the oldest node N to make + room for n. If N dies, recursively decreases the reference counts of + its children. It is used to dispose of a BDD that is currently not + needed, but may be useful again in the near future. The dereferencing + proper is done as in Cudd_IterDerefBdd.] + + SideEffects [None] + + SeeAlso [Cudd_RecursiveDeref Cudd_IterDerefBdd] + +******************************************************************************/ +void +Cudd_DelayedDerefBdd( + DdManager * table, + DdNode * n) +{ + DdNode *N; + int ord; + DdNodePtr *stack; + int SP; + + unsigned int live = table->keys - table->dead; + if (live > table->peakLiveNodes) { + table->peakLiveNodes = live; + } + + n = Cudd_Regular(n); +#ifdef DD_DEBUG + assert(n->ref != 0); +#endif + +#ifdef DD_NO_DEATH_ROW + N = n; +#else + if (cuddIsConstant(n) || n->ref > 1) { +#ifdef DD_DEBUG + assert(n->ref != 1 && (!cuddIsConstant(n) || n == DD_ONE(table))); +#endif + cuddSatDec(n->ref); + return; + } + + N = table->deathRow[table->nextDead]; + + if (N != NULL) { +#endif +#ifdef DD_DEBUG + assert(!Cudd_IsComplement(N)); +#endif + stack = table->stack; + SP = 1; + do { +#ifdef DD_DEBUG + assert(N->ref != 0); +#endif + if (N->ref == 1) { + N->ref = 0; + table->dead++; +#ifdef DD_STATS + table->nodesDropped++; +#endif + ord = table->perm[N->index]; + stack[SP++] = Cudd_Regular(cuddE(N)); + table->subtables[ord].dead++; + N = cuddT(N); + } else { + cuddSatDec(N->ref); + N = stack[--SP]; + } + } while (SP != 0); +#ifndef DD_NO_DEATH_ROW + } + table->deathRow[table->nextDead] = n; + + /* Udate insertion point. */ + table->nextDead++; + table->nextDead &= table->deadMask; +#if 0 + if (table->nextDead == table->deathRowDepth) { + if (table->deathRowDepth < table->looseUpTo / 2) { + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long) = MMoutOfMemory; + DdNodePtr *newRow; + MMoutOfMemory = Cudd_OutOfMem; + newRow = REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth); + MMoutOfMemory = saveHandler; + if (newRow == NULL) { + table->nextDead = 0; + } else { + int i; + table->memused += table->deathRowDepth; + i = table->deathRowDepth; + table->deathRowDepth <<= 1; + for (; i < table->deathRowDepth; i++) { + newRow[i] = NULL; + } + table->deadMask = table->deathRowDepth - 1; + table->deathRow = newRow; + } + } else { + table->nextDead = 0; + } + } +#endif +#endif + +} /* end of Cudd_DelayedDerefBdd */ + + +/**Function******************************************************************** + + Synopsis [Decreases the reference count of ZDD node n.] + + Description [Decreases the reference count of ZDD node n. If n dies, + recursively decreases the reference counts of its children. It is + used to dispose of a ZDD that is no longer needed.] + + SideEffects [None] + + SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDeref] + +******************************************************************************/ +void +Cudd_RecursiveDerefZdd( + DdManager * table, + DdNode * n) +{ + DdNode *N; + int ord; + DdNodePtr *stack = table->stack; + int SP = 1; + + N = n; + + do { +#ifdef DD_DEBUG + assert(N->ref != 0); +#endif + + cuddSatDec(N->ref); + + if (N->ref == 0) { + table->deadZ++; +#ifdef DD_STATS + table->nodesDropped++; +#endif +#ifdef DD_DEBUG + assert(!cuddIsConstant(N)); +#endif + ord = table->permZ[N->index]; + stack[SP++] = cuddE(N); + table->subtableZ[ord].dead++; + N = cuddT(N); + } else { + N = stack[--SP]; + } + } while (SP != 0); + +} /* end of Cudd_RecursiveDerefZdd */ + + +/**Function******************************************************************** + + Synopsis [Decreases the reference count of node.] + + Description [Decreases the reference count of node. It is primarily + used in recursive procedures to decrease the ref count of a result + node before returning it. This accomplishes the goal of removing the + protection applied by a previous Cudd_Ref.] + + SideEffects [None] + + SeeAlso [Cudd_RecursiveDeref Cudd_RecursiveDerefZdd Cudd_Ref] + +******************************************************************************/ +void +Cudd_Deref( + DdNode * node) +{ + node = Cudd_Regular(node); + cuddSatDec(node->ref); + +} /* end of Cudd_Deref */ + + +/**Function******************************************************************** + + Synopsis [Checks the unique table for nodes with non-zero reference + counts.] + + Description [Checks the unique table for nodes with non-zero + reference counts. It is normally called before Cudd_Quit to make sure + that there are no memory leaks due to missing Cudd_RecursiveDeref's. + Takes into account that reference counts may saturate and that the + basic constants and the projection functions are referenced by the + manager. Returns the number of nodes with non-zero reference count. + (Except for the cases mentioned above.)] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_CheckZeroRef( + DdManager * manager) +{ + int size; + int i, j; + int remain; /* the expected number of remaining references to one */ + DdNodePtr *nodelist; + DdNode *node; + DdNode *sentinel = &(manager->sentinel); + DdSubtable *subtable; + int count = 0; + int index; + +#ifndef DD_NO_DEATH_ROW + cuddClearDeathRow(manager); +#endif + + /* First look at the BDD/ADD subtables. */ + remain = 1; /* reference from the manager */ + size = manager->size; + remain += 2 * size; /* reference from the BDD projection functions */ + + for (i = 0; i < size; i++) { + subtable = &(manager->subtables[i]); + nodelist = subtable->nodelist; + for (j = 0; (unsigned) j < subtable->slots; j++) { + node = nodelist[j]; + while (node != sentinel) { + if (node->ref != 0 && node->ref != DD_MAXREF) { + index = (int) node->index; + if (node != manager->vars[index]) { + count++; + } else { + if (node->ref != 1) { + count++; + } + } + } + node = node->next; + } + } + } + + /* Then look at the ZDD subtables. */ + size = manager->sizeZ; + if (size) /* references from ZDD universe */ + remain += 2; + + for (i = 0; i < size; i++) { + subtable = &(manager->subtableZ[i]); + nodelist = subtable->nodelist; + for (j = 0; (unsigned) j < subtable->slots; j++) { + node = nodelist[j]; + while (node != NULL) { + if (node->ref != 0 && node->ref != DD_MAXREF) { + index = (int) node->index; + if (node == manager->univ[manager->permZ[index]]) { + if (node->ref > 2) { + count++; + } + } else { + count++; + } + } + node = node->next; + } + } + } + + /* Now examine the constant table. Plusinfinity, minusinfinity, and + ** zero are referenced by the manager. One is referenced by the + ** manager, by the ZDD universe, and by all projection functions. + ** All other nodes should have no references. + */ + nodelist = manager->constants.nodelist; + for (j = 0; (unsigned) j < manager->constants.slots; j++) { + node = nodelist[j]; + while (node != NULL) { + if (node->ref != 0 && node->ref != DD_MAXREF) { + if (node == manager->one) { + if ((int) node->ref != remain) { + count++; + } + } else if (node == manager->zero || + node == manager->plusinfinity || + node == manager->minusinfinity) { + if (node->ref != 1) { + count++; + } + } else { + count++; + } + } + node = node->next; + } + } + return(count); + +} /* end of Cudd_CheckZeroRef */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Brings children of a dead node back.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddReclaimZdd] + +******************************************************************************/ +void +cuddReclaim( + DdManager * table, + DdNode * n) +{ + DdNode *N; + int ord; + DdNodePtr *stack = table->stack; + int SP = 1; + double initialDead = table->dead; + + N = Cudd_Regular(n); + +#ifdef DD_DEBUG + assert(N->ref == 0); +#endif + + do { + if (N->ref == 0) { + N->ref = 1; + table->dead--; + if (cuddIsConstant(N)) { + table->constants.dead--; + N = stack[--SP]; + } else { + ord = table->perm[N->index]; + stack[SP++] = Cudd_Regular(cuddE(N)); + table->subtables[ord].dead--; + N = cuddT(N); + } + } else { + cuddSatInc(N->ref); + N = stack[--SP]; + } + } while (SP != 0); + + N = Cudd_Regular(n); + cuddSatDec(N->ref); + table->reclaimed += initialDead - table->dead; + +} /* end of cuddReclaim */ + + +/**Function******************************************************************** + + Synopsis [Brings children of a dead ZDD node back.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddReclaim] + +******************************************************************************/ +void +cuddReclaimZdd( + DdManager * table, + DdNode * n) +{ + DdNode *N; + int ord; + DdNodePtr *stack = table->stack; + int SP = 1; + + N = n; + +#ifdef DD_DEBUG + assert(N->ref == 0); +#endif + + do { + cuddSatInc(N->ref); + + if (N->ref == 1) { + table->deadZ--; + table->reclaimed++; +#ifdef DD_DEBUG + assert(!cuddIsConstant(N)); +#endif + ord = table->permZ[N->index]; + stack[SP++] = cuddE(N); + table->subtableZ[ord].dead--; + N = cuddT(N); + } else { + N = stack[--SP]; + } + } while (SP != 0); + + cuddSatDec(n->ref); + +} /* end of cuddReclaimZdd */ + + +/**Function******************************************************************** + + Synopsis [Shrinks the death row.] + + Description [Shrinks the death row by a factor of four.] + + SideEffects [None] + + SeeAlso [cuddClearDeathRow] + +******************************************************************************/ +void +cuddShrinkDeathRow( + DdManager *table) +{ +#ifndef DD_NO_DEATH_ROW + int i; + + if (table->deathRowDepth > 3) { + for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) { + if (table->deathRow[i] == NULL) break; + Cudd_IterDerefBdd(table,table->deathRow[i]); + table->deathRow[i] = NULL; + } + table->deathRowDepth /= 4; + table->deadMask = table->deathRowDepth - 2; + if ((unsigned) table->nextDead > table->deadMask) { + table->nextDead = 0; + } + table->deathRow = REALLOC(DdNodePtr, table->deathRow, + table->deathRowDepth); + } +#endif + +} /* end of cuddShrinkDeathRow */ + + +/**Function******************************************************************** + + Synopsis [Clears the death row.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef + cuddGarbageCollect] + +******************************************************************************/ +void +cuddClearDeathRow( + DdManager *table) +{ +#ifndef DD_NO_DEATH_ROW + int i; + + for (i = 0; i < table->deathRowDepth; i++) { + if (table->deathRow[i] == NULL) break; + Cudd_IterDerefBdd(table,table->deathRow[i]); + table->deathRow[i] = NULL; + } +#ifdef DD_DEBUG + for (; i < table->deathRowDepth; i++) { + assert(table->deathRow[i] == NULL); + } +#endif + table->nextDead = 0; +#endif + +} /* end of cuddClearDeathRow */ + + +/**Function******************************************************************** + + Synopsis [Checks whether a node is in the death row.] + + Description [Checks whether a node is in the death row. Returns the + position of the first occurrence if the node is present; -1 + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow] + +******************************************************************************/ +int +cuddIsInDeathRow( + DdManager *dd, + DdNode *f) +{ +#ifndef DD_NO_DEATH_ROW + int i; + + for (i = 0; i < dd->deathRowDepth; i++) { + if (f == dd->deathRow[i]) { + return(i); + } + } +#endif + + return(-1); + +} /* end of cuddIsInDeathRow */ + + +/**Function******************************************************************** + + Synopsis [Counts how many times a node is in the death row.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow] + +******************************************************************************/ +int +cuddTimesInDeathRow( + DdManager *dd, + DdNode *f) +{ + int count = 0; +#ifndef DD_NO_DEATH_ROW + int i; + + for (i = 0; i < dd->deathRowDepth; i++) { + count += f == dd->deathRow[i]; + } +#endif + + return(count); + +} /* end of cuddTimesInDeathRow */ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ diff --git a/abc70930/src/bdd/cudd/cuddReorder.c b/abc70930/src/bdd/cudd/cuddReorder.c new file mode 100644 index 00000000..1387196f --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddReorder.c @@ -0,0 +1,2090 @@ +/**CFile*********************************************************************** + + FileName [cuddReorder.c] + + PackageName [cudd] + + Synopsis [Functions for dynamic variable reordering.] + + Description [External procedures included in this file: +
        +
      • Cudd_ReduceHeap() +
      • Cudd_ShuffleHeap() +
      + Internal procedures included in this module: +
        +
      • cuddDynamicAllocNode() +
      • cuddSifting() +
      • cuddSwapping() +
      • cuddNextHigh() +
      • cuddNextLow() +
      • cuddSwapInPlace() +
      • cuddBddAlignToZdd() +
      + Static procedures included in this module: +
        +
      • ddUniqueCompare() +
      • ddSwapAny() +
      • ddSiftingAux() +
      • ddSiftingUp() +
      • ddSiftingDown() +
      • ddSiftingBackward() +
      • ddReorderPreprocess() +
      • ddReorderPostprocess() +
      • ddShuffle() +
      • ddSiftUp() +
      • bddFixTree() +
      ] + + Author [Shipra Panda, Bernard Plessier, Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define DD_MAX_SUBTABLE_SPARSITY 8 +#define DD_SHRINK_FACTOR 2 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +static int *entry; + +int ddTotalNumberSwapping; +#ifdef DD_STATS +int ddTotalNISwaps; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int ddUniqueCompare ARGS((int *ptrX, int *ptrY)); +static Move * ddSwapAny ARGS((DdManager *table, int x, int y)); +static int ddSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); +static Move * ddSiftingUp ARGS((DdManager *table, int y, int xLow)); +static Move * ddSiftingDown ARGS((DdManager *table, int x, int xHigh)); +static int ddSiftingBackward ARGS((DdManager *table, int size, Move *moves)); +static int ddReorderPreprocess ARGS((DdManager *table)); +static int ddReorderPostprocess ARGS((DdManager *table)); +static int ddShuffle ARGS((DdManager *table, int *permutation)); +static int ddSiftUp ARGS((DdManager *table, int x, int xLow)); +static void bddFixTree ARGS((DdManager *table, MtrNode *treenode)); +static int ddUpdateMtrTree ARGS((DdManager *table, MtrNode *treenode, int *perm, int *invperm)); +static int ddCheckPermuation ARGS((DdManager *table, MtrNode *treenode, int *perm, int *invperm)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Main dynamic reordering routine.] + + Description [Main dynamic reordering routine. + Calls one of the possible reordering procedures: +
        +
      • Swapping +
      • Sifting +
      • Symmetric Sifting +
      • Group Sifting +
      • Window Permutation +
      • Simulated Annealing +
      • Genetic Algorithm +
      • Dynamic Programming (exact) +
      + + For sifting, symmetric sifting, group sifting, and window + permutation it is possible to request reordering to convergence.

      + + The core of all methods is the reordering procedure + cuddSwapInPlace() which swaps two adjacent variables and is based + on Rudell's paper. + Returns 1 in case of success; 0 otherwise. In the case of symmetric + sifting (with and without convergence) returns 1 plus the number of + symmetric variables, in case of success.] + + SideEffects [Changes the variable order for all diagrams and clears + the cache.] + +******************************************************************************/ +int +Cudd_ReduceHeap( + DdManager * table /* DD manager */, + Cudd_ReorderingType heuristic /* method used for reordering */, + int minsize /* bound below which no reordering occurs */) +{ + DdHook *hook; + int result; + unsigned int nextDyn; +#ifdef DD_STATS + unsigned int initialSize; + unsigned int finalSize; +#endif + long localTime; + + /* Don't reorder if there are too many dead nodes. */ + if (table->keys - table->dead < (unsigned) minsize) + return(1); + + if (heuristic == CUDD_REORDER_SAME) { + heuristic = table->autoMethod; + } + if (heuristic == CUDD_REORDER_NONE) { + return(1); + } + + /* This call to Cudd_ReduceHeap does initiate reordering. Therefore + ** we count it. + */ + table->reorderings++; + + localTime = util_cpu_time(); + + /* Run the hook functions. */ + hook = table->preReorderingHook; + while (hook != NULL) { + int res = (hook->f)(table, "BDD", (void *)heuristic); + if (res == 0) return(0); + hook = hook->next; + } + + if (!ddReorderPreprocess(table)) return(0); + ddTotalNumberSwapping = 0; + + if (table->keys > table->peakLiveNodes) { + table->peakLiveNodes = table->keys; + } +#ifdef DD_STATS + initialSize = table->keys - table->isolated; + ddTotalNISwaps = 0; + + switch(heuristic) { + case CUDD_REORDER_RANDOM: + case CUDD_REORDER_RANDOM_PIVOT: + (void) fprintf(table->out,"#:I_RANDOM "); + break; + case CUDD_REORDER_SIFT: + case CUDD_REORDER_SIFT_CONVERGE: + case CUDD_REORDER_SYMM_SIFT: + case CUDD_REORDER_SYMM_SIFT_CONV: + case CUDD_REORDER_GROUP_SIFT: + case CUDD_REORDER_GROUP_SIFT_CONV: + (void) fprintf(table->out,"#:I_SIFTING "); + break; + case CUDD_REORDER_WINDOW2: + case CUDD_REORDER_WINDOW3: + case CUDD_REORDER_WINDOW4: + case CUDD_REORDER_WINDOW2_CONV: + case CUDD_REORDER_WINDOW3_CONV: + case CUDD_REORDER_WINDOW4_CONV: + (void) fprintf(table->out,"#:I_WINDOW "); + break; + case CUDD_REORDER_ANNEALING: + (void) fprintf(table->out,"#:I_ANNEAL "); + break; + case CUDD_REORDER_GENETIC: + (void) fprintf(table->out,"#:I_GENETIC "); + break; + case CUDD_REORDER_LINEAR: + case CUDD_REORDER_LINEAR_CONVERGE: + (void) fprintf(table->out,"#:I_LINSIFT "); + break; + case CUDD_REORDER_EXACT: + (void) fprintf(table->out,"#:I_EXACT "); + break; + default: + return(0); + } + (void) fprintf(table->out,"%8d: initial size",initialSize); +#endif + + /* See if we should use alternate threshold for maximum growth. */ + if (table->reordCycle && table->reorderings % table->reordCycle == 0) { + double saveGrowth = table->maxGrowth; + table->maxGrowth = table->maxGrowthAlt; + result = cuddTreeSifting(table,heuristic); + table->maxGrowth = saveGrowth; + } else { + result = cuddTreeSifting(table,heuristic); + } + +#ifdef DD_STATS + (void) fprintf(table->out,"\n"); + finalSize = table->keys - table->isolated; + (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); + (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", + ((double)(util_cpu_time() - localTime)/1000.0)); + (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", + ddTotalNumberSwapping); + (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps); +#endif + + if (result == 0) + return(0); + + if (!ddReorderPostprocess(table)) + return(0); + + if (table->realign) { + if (!cuddZddAlignToBdd(table)) + return(0); + } + + nextDyn = (table->keys - table->constants.keys + 1) * + DD_DYN_RATIO + table->constants.keys; + if (table->reorderings < 20 || nextDyn > table->nextDyn) + table->nextDyn = nextDyn; + else + table->nextDyn += 20; + table->reordered = 1; + + /* Run hook functions. */ + hook = table->postReorderingHook; + while (hook != NULL) { + int res = (hook->f)(table, "BDD", (void *)localTime); + if (res == 0) return(0); + hook = hook->next; + } + /* Update cumulative reordering time. */ + table->reordTime += util_cpu_time() - localTime; + + return(result); + +} /* end of Cudd_ReduceHeap */ + + +/**Function******************************************************************** + + Synopsis [Reorders variables according to given permutation.] + + Description [Reorders variables according to given permutation. + The i-th entry of the permutation array contains the index of the variable + that should be brought to the i-th level. The size of the array should be + equal or greater to the number of variables currently in use. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [Changes the variable order for all diagrams and clears + the cache.] + + SeeAlso [Cudd_ReduceHeap] + +******************************************************************************/ +int +Cudd_ShuffleHeap( + DdManager * table /* DD manager */, + int * permutation /* required variable permutation */) +{ + + int result; + int i; + int identity = 1; + int *perm; + + /* Don't waste time in case of identity permutation. */ + for (i = 0; i < table->size; i++) { + if (permutation[i] != table->invperm[i]) { + identity = 0; + break; + } + } + if (identity == 1) { + return(1); + } + if (!ddReorderPreprocess(table)) return(0); + if (table->keys > table->peakLiveNodes) { + table->peakLiveNodes = table->keys; + } + + perm = ALLOC(int, table->size); + for (i = 0; i < table->size; i++) + perm[permutation[i]] = i; + if (!ddCheckPermuation(table,table->tree,perm,permutation)) { + FREE(perm); + return(0); + } + if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) { + FREE(perm); + return(0); + } + FREE(perm); + + result = ddShuffle(table,permutation); + + if (!ddReorderPostprocess(table)) return(0); + + return(result); + +} /* end of Cudd_ShuffleHeap */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Dynamically allocates a Node.] + + Description [Dynamically allocates a Node. This procedure is similar + to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage + collection, because during reordering there are no dead nodes. + Returns a pointer to a new node if successful; NULL is memory is + full.] + + SideEffects [None] + + SeeAlso [cuddAllocNode] + +******************************************************************************/ +DdNode * +cuddDynamicAllocNode( + DdManager * table) +{ + int i; + DdNodePtr *mem; + DdNode *list, *node; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); + + if (table->nextFree == NULL) { /* free list is empty */ + /* Try to allocate a new block. */ + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1); + MMoutOfMemory = saveHandler; + if (mem == NULL && table->stash != NULL) { + FREE(table->stash); + table->stash = NULL; + /* Inhibit resizing of tables. */ + table->maxCacheHard = table->cacheSlots - 1; + table->cacheSlack = -(table->cacheSlots + 1); + for (i = 0; i < table->size; i++) { + table->subtables[i].maxKeys <<= 2; + } + mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); + } + if (mem == NULL) { + /* Out of luck. Call the default handler to do + ** whatever it specifies for a failed malloc. If this + ** handler returns, then set error code, print + ** warning, and return. */ + (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); + table->errorCode = CUDD_MEMORY_OUT; +#ifdef DD_VERBOSE + (void) fprintf(table->err, + "cuddDynamicAllocNode: out of memory"); + (void) fprintf(table->err,"Memory in use = %ld\n", + table->memused); +#endif + return(NULL); + } else { /* successful allocation; slice memory */ + unsigned long offset; + table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); + mem[0] = (DdNode *) table->memoryList; + table->memoryList = mem; + + /* Here we rely on the fact that the size of a DdNode is a + ** power of 2 and a multiple of the size of a pointer. + ** If we align one node, all the others will be aligned + ** as well. */ + offset = (unsigned long) mem & (sizeof(DdNode) - 1); + mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); +#ifdef DD_DEBUG + assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0); +#endif + list = (DdNode *) mem; + + i = 1; + do { + list[i - 1].next = &list[i]; + } while (++i < DD_MEM_CHUNK); + + list[DD_MEM_CHUNK - 1].next = NULL; + + table->nextFree = &list[0]; + } + } /* if free list empty */ + + node = table->nextFree; + table->nextFree = node->next; + return (node); + +} /* end of cuddDynamicAllocNode */ + + +/**Function******************************************************************** + + Synopsis [Implementation of Rudell's sifting algorithm.] + + Description [Implementation of Rudell's sifting algorithm. + Assumes that no dead nodes are present. +

        +
      1. Order all the variables according to the number of entries + in each unique table. +
      2. Sift the variable up and down, remembering each time the + total size of the DD heap. +
      3. Select the best permutation. +
      4. Repeat 3 and 4 for all variables. +
      + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +int +cuddSifting( + DdManager * table, + int lower, + int upper) +{ + int i; + int *var; + int size; + int x; + int result; +#ifdef DD_STATS + int previousSize; +#endif + + size = table->size; + + /* Find order in which to sift variables. */ + var = NULL; + entry = ALLOC(int,size); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddSiftingOutOfMem; + } + var = ALLOC(int,size); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddSiftingOutOfMem; + } + + for (i = 0; i < size; i++) { + x = table->perm[i]; + entry[i] = table->subtables[x].keys; + var[i] = i; + } + + qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddUniqueCompare); + + /* Now sift. */ + for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { + if (ddTotalNumberSwapping >= table->siftMaxSwap) + break; + x = table->perm[var[i]]; + + if (x < lower || x > upper || table->subtables[x].bindVar == 1) + continue; +#ifdef DD_STATS + previousSize = table->keys - table->isolated; +#endif + result = ddSiftingAux(table, x, lower, upper); + if (!result) goto cuddSiftingOutOfMem; +#ifdef DD_STATS + if (table->keys < (unsigned) previousSize + table->isolated) { + (void) fprintf(table->out,"-"); + } else if (table->keys > (unsigned) previousSize + table->isolated) { + (void) fprintf(table->out,"+"); /* should never happen */ + (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + + FREE(var); + FREE(entry); + + return(1); + +cuddSiftingOutOfMem: + + if (entry != NULL) FREE(entry); + if (var != NULL) FREE(var); + + return(0); + +} /* end of cuddSifting */ + + +/**Function******************************************************************** + + Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.] + + Description [Implementation of Plessier's algorithm that reorders + variables by a sequence of (non-adjacent) swaps. +
        +
      1. Select two variables (RANDOM or HEURISTIC). +
      2. Permute these variables. +
      3. If the nodes have decreased accept the permutation. +
      4. Otherwise reconstruct the original heap. +
      5. Loop. +
      + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +int +cuddSwapping( + DdManager * table, + int lower, + int upper, + Cudd_ReorderingType heuristic) +{ + int i, j; + int max, keys; + int nvars; + int x, y; + int iterate; + int previousSize; + Move *moves, *move; + int pivot; + int modulo; + int result; + +#ifdef DD_DEBUG + /* Sanity check */ + assert(lower >= 0 && upper < table->size && lower <= upper); +#endif + + nvars = upper - lower + 1; + iterate = nvars; + + for (i = 0; i < iterate; i++) { + if (ddTotalNumberSwapping >= table->siftMaxSwap) + break; + if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { + max = -1; + for (j = lower; j <= upper; j++) { + if ((keys = table->subtables[j].keys) > max) { + max = keys; + pivot = j; + } + } + + modulo = upper - pivot; + if (modulo == 0) { + y = pivot; + } else{ + y = pivot + 1 + ((int) Cudd_Random() % modulo); + } + + modulo = pivot - lower - 1; + if (modulo < 1) { + x = lower; + } else{ + do { + x = (int) Cudd_Random() % modulo; + } while (x == y); + } + } else { + x = ((int) Cudd_Random() % nvars) + lower; + do { + y = ((int) Cudd_Random() % nvars) + lower; + } while (x == y); + } + previousSize = table->keys - table->isolated; + moves = ddSwapAny(table,x,y); + if (moves == NULL) goto cuddSwappingOutOfMem; + result = ddSiftingBackward(table,previousSize,moves); + if (!result) goto cuddSwappingOutOfMem; + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } +#ifdef DD_STATS + if (table->keys < (unsigned) previousSize + table->isolated) { + (void) fprintf(table->out,"-"); + } else if (table->keys > (unsigned) previousSize + table->isolated) { + (void) fprintf(table->out,"+"); /* should never happen */ + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif +#if 0 + (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n", + table->keys - table->isolated); +#endif + } + + return(1); + +cuddSwappingOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + + return(0); + +} /* end of cuddSwapping */ + + +/**Function******************************************************************** + + Synopsis [Finds the next subtable with a larger index.] + + Description [Finds the next subtable with a larger index. Returns the + index.] + + SideEffects [None] + + SeeAlso [cuddNextLow] + +******************************************************************************/ +int +cuddNextHigh( + DdManager * table, + int x) +{ + return(x+1); + +} /* end of cuddNextHigh */ + + +/**Function******************************************************************** + + Synopsis [Finds the next subtable with a smaller index.] + + Description [Finds the next subtable with a smaller index. Returns the + index.] + + SideEffects [None] + + SeeAlso [cuddNextHigh] + +******************************************************************************/ +int +cuddNextLow( + DdManager * table, + int x) +{ + return(x-1); + +} /* end of cuddNextLow */ + + +/**Function******************************************************************** + + Synopsis [Swaps two adjacent variables.] + + Description [Swaps two adjacent variables. It assumes that no dead + nodes are present on entry to this procedure. The procedure then + guarantees that no dead nodes will be present when it terminates. + cuddSwapInPlace assumes that x < y. Returns the number of keys in + the table if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +int +cuddSwapInPlace( + DdManager * table, + int x, + int y) +{ + DdNodePtr *xlist, *ylist; + int xindex, yindex; + int xslots, yslots; + int xshift, yshift; + int oldxkeys, oldykeys; + int newxkeys, newykeys; + int comple, newcomplement; + int i; + Cudd_VariableType varType; + Cudd_LazyGroupType groupType; + int posn; + int isolated; + DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; + DdNode *g,*next; + DdNodePtr *previousP; + DdNode *tmp; + DdNode *sentinel = &(table->sentinel); + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); + +#if DD_DEBUG + int count,idcheck; +#endif + +#ifdef DD_DEBUG + assert(x < y); + assert(cuddNextHigh(table,x) == y); + assert(table->subtables[x].keys != 0); + assert(table->subtables[y].keys != 0); + assert(table->subtables[x].dead == 0); + assert(table->subtables[y].dead == 0); +#endif + + ddTotalNumberSwapping++; + + /* Get parameters of x subtable. */ + xindex = table->invperm[x]; + xlist = table->subtables[x].nodelist; + oldxkeys = table->subtables[x].keys; + xslots = table->subtables[x].slots; + xshift = table->subtables[x].shift; + + /* Get parameters of y subtable. */ + yindex = table->invperm[y]; + ylist = table->subtables[y].nodelist; + oldykeys = table->subtables[y].keys; + yslots = table->subtables[y].slots; + yshift = table->subtables[y].shift; + + if (!cuddTestInteract(table,xindex,yindex)) { +#ifdef DD_STATS + ddTotalNISwaps++; +#endif + newxkeys = oldxkeys; + newykeys = oldykeys; + } else { + newxkeys = 0; + newykeys = oldykeys; + + /* Check whether the two projection functions involved in this + ** swap are isolated. At the end, we'll be able to tell how many + ** isolated projection functions are there by checking only these + ** two functions again. This is done to eliminate the isolated + ** projection functions from the node count. + */ + isolated = - ((table->vars[xindex]->ref == 1) + + (table->vars[yindex]->ref == 1)); + + /* The nodes in the x layer that do not depend on + ** y will stay there; the others are put in a chain. + ** The chain is handled as a LIFO; g points to the beginning. + */ + g = NULL; + if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) && + oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) { + for (i = 0; i < xslots; i++) { + previousP = &(xlist[i]); + f = *previousP; + while (f != sentinel) { + next = f->next; + f1 = cuddT(f); f0 = cuddE(f); + if (f1->index != (DdHalfWord) yindex && + Cudd_Regular(f0)->index != (DdHalfWord) yindex) { + /* stays */ + newxkeys++; + *previousP = f; + previousP = &(f->next); + } else { + f->index = yindex; + f->next = g; + g = f; + } + f = next; + } /* while there are elements in the collision chain */ + *previousP = sentinel; + } /* for each slot of the x subtable */ + } else { /* resize xlist */ + DdNode *h = NULL; + DdNodePtr *newxlist; + unsigned int newxslots; + int newxshift; + /* Empty current xlist. Nodes that stay go to list h; + ** nodes that move go to list g. */ + for (i = 0; i < xslots; i++) { + f = xlist[i]; + while (f != sentinel) { + next = f->next; + f1 = cuddT(f); f0 = cuddE(f); + if (f1->index != (DdHalfWord) yindex && + Cudd_Regular(f0)->index != (DdHalfWord) yindex) { + /* stays */ + f->next = h; + h = f; + newxkeys++; + } else { + f->index = yindex; + f->next = g; + g = f; + } + f = next; + } /* while there are elements in the collision chain */ + } /* for each slot of the x subtable */ + /* Decide size of new subtable. */ + if (oldxkeys > DD_MAX_SUBTABLE_DENSITY * xslots) { + newxshift = xshift - 1; + newxslots = xslots << 1; + } else { + newxshift = xshift + 1; + newxslots = xslots >> 1; + } + /* Try to allocate new table. Be ready to back off. */ + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + newxlist = ALLOC(DdNodePtr, newxslots); + MMoutOfMemory = saveHandler; + if (newxlist == NULL) { + (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i); + newxlist = xlist; + newxslots = xslots; + newxshift = xshift; + } else { + table->slots += (newxslots - xslots); + table->minDead = (unsigned) + (table->gcFrac * (double) table->slots); + table->cacheSlack = (int) + ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO + * table->slots) - 2 * (int) table->cacheSlots; + table->memused += (newxslots - xslots) * sizeof(DdNodePtr); + FREE(xlist); + xslots = newxslots; + xshift = newxshift; + xlist = newxlist; + } + /* Initialize new subtable. */ + for (i = 0; i < xslots; i++) { + xlist[i] = sentinel; + } + /* Move nodes that were parked in list h to their new home. */ + f = h; + while (f != NULL) { + next = f->next; + f1 = cuddT(f); + f0 = cuddE(f); + /* Check xlist for pair (f11,f01). */ + posn = ddHash(f1, f0, xshift); + /* For each element tmp in collision list xlist[posn]. */ + previousP = &(xlist[posn]); + tmp = *previousP; + while (f1 < cuddT(tmp)) { + previousP = &(tmp->next); + tmp = *previousP; + } + while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) { + previousP = &(tmp->next); + tmp = *previousP; + } + f->next = *previousP; + *previousP = f; + f = next; + } + } + +#ifdef DD_COUNT + table->swapSteps += oldxkeys - newxkeys; +#endif + /* Take care of the x nodes that must be re-expressed. + ** They form a linked list pointed by g. Their index has been + ** already changed to yindex. + */ + f = g; + while (f != NULL) { + next = f->next; + /* Find f1, f0, f11, f10, f01, f00. */ + f1 = cuddT(f); +#ifdef DD_DEBUG + assert(!(Cudd_IsComplement(f1))); +#endif + if ((int) f1->index == yindex) { + f11 = cuddT(f1); f10 = cuddE(f1); + } else { + f11 = f10 = f1; + } +#ifdef DD_DEBUG + assert(!(Cudd_IsComplement(f11))); +#endif + f0 = cuddE(f); + comple = Cudd_IsComplement(f0); + f0 = Cudd_Regular(f0); + if ((int) f0->index == yindex) { + f01 = cuddT(f0); f00 = cuddE(f0); + } else { + f01 = f00 = f0; + } + if (comple) { + f01 = Cudd_Not(f01); + f00 = Cudd_Not(f00); + } + /* Decrease ref count of f1. */ + cuddSatDec(f1->ref); + /* Create the new T child. */ + if (f11 == f01) { + newf1 = f11; + cuddSatInc(newf1->ref); + } else { + /* Check xlist for triple (xindex,f11,f01). */ + posn = ddHash(f11, f01, xshift); + /* For each element newf1 in collision list xlist[posn]. */ + previousP = &(xlist[posn]); + newf1 = *previousP; + while (f11 < cuddT(newf1)) { + previousP = &(newf1->next); + newf1 = *previousP; + } + while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) { + previousP = &(newf1->next); + newf1 = *previousP; + } + if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { + cuddSatInc(newf1->ref); + } else { /* no match */ + newf1 = cuddDynamicAllocNode(table); + if (newf1 == NULL) + goto cuddSwapOutOfMem; + newf1->index = xindex; newf1->ref = 1; + cuddT(newf1) = f11; + cuddE(newf1) = f01; + /* Insert newf1 in the collision list xlist[posn]; + ** increase the ref counts of f11 and f01. + */ + newxkeys++; + newf1->next = *previousP; + *previousP = newf1; + cuddSatInc(f11->ref); + tmp = Cudd_Regular(f01); + cuddSatInc(tmp->ref); + } + } + cuddT(f) = newf1; +#ifdef DD_DEBUG + assert(!(Cudd_IsComplement(newf1))); +#endif + + /* Do the same for f0, keeping complement dots into account. */ + /* Decrease ref count of f0. */ + tmp = Cudd_Regular(f0); + cuddSatDec(tmp->ref); + /* Create the new E child. */ + if (f10 == f00) { + newf0 = f00; + tmp = Cudd_Regular(newf0); + cuddSatInc(tmp->ref); + } else { + /* make sure f10 is regular */ + newcomplement = Cudd_IsComplement(f10); + if (newcomplement) { + f10 = Cudd_Not(f10); + f00 = Cudd_Not(f00); + } + /* Check xlist for triple (xindex,f10,f00). */ + posn = ddHash(f10, f00, xshift); + /* For each element newf0 in collision list xlist[posn]. */ + previousP = &(xlist[posn]); + newf0 = *previousP; + while (f10 < cuddT(newf0)) { + previousP = &(newf0->next); + newf0 = *previousP; + } + while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) { + previousP = &(newf0->next); + newf0 = *previousP; + } + if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { + cuddSatInc(newf0->ref); + } else { /* no match */ + newf0 = cuddDynamicAllocNode(table); + if (newf0 == NULL) + goto cuddSwapOutOfMem; + newf0->index = xindex; newf0->ref = 1; + cuddT(newf0) = f10; + cuddE(newf0) = f00; + /* Insert newf0 in the collision list xlist[posn]; + ** increase the ref counts of f10 and f00. + */ + newxkeys++; + newf0->next = *previousP; + *previousP = newf0; + cuddSatInc(f10->ref); + tmp = Cudd_Regular(f00); + cuddSatInc(tmp->ref); + } + if (newcomplement) { + newf0 = Cudd_Not(newf0); + } + } + cuddE(f) = newf0; + + /* Insert the modified f in ylist. + ** The modified f does not already exists in ylist. + ** (Because of the uniqueness of the cofactors.) + */ + posn = ddHash(newf1, newf0, yshift); + newykeys++; + previousP = &(ylist[posn]); + tmp = *previousP; + while (newf1 < cuddT(tmp)) { + previousP = &(tmp->next); + tmp = *previousP; + } + while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { + previousP = &(tmp->next); + tmp = *previousP; + } + f->next = *previousP; + *previousP = f; + f = next; + } /* while f != NULL */ + + /* GC the y layer. */ + + /* For each node f in ylist. */ + for (i = 0; i < yslots; i++) { + previousP = &(ylist[i]); + f = *previousP; + while (f != sentinel) { + next = f->next; + if (f->ref == 0) { + tmp = cuddT(f); + cuddSatDec(tmp->ref); + tmp = Cudd_Regular(cuddE(f)); + cuddSatDec(tmp->ref); + cuddDeallocNode(table,f); + newykeys--; + } else { + *previousP = f; + previousP = &(f->next); + } + f = next; + } /* while f */ + *previousP = sentinel; + } /* for i */ + +#if DD_DEBUG +#if 0 + (void) fprintf(table->out,"Swapping %d and %d\n",x,y); +#endif + count = 0; + idcheck = 0; + for (i = 0; i < yslots; i++) { + f = ylist[i]; + while (f != sentinel) { + count++; + if (f->index != (DdHalfWord) yindex) + idcheck++; + f = f->next; + } + } + if (count != newykeys) { + (void) fprintf(table->out, + "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n", + oldykeys,newykeys,count); + } + if (idcheck != 0) + (void) fprintf(table->out, + "Error in id's of ylist\twrong id's = %d\n", + idcheck); + count = 0; + idcheck = 0; + for (i = 0; i < xslots; i++) { + f = xlist[i]; + while (f != sentinel) { + count++; + if (f->index != (DdHalfWord) xindex) + idcheck++; + f = f->next; + } + } + if (count != newxkeys) { + (void) fprintf(table->out, + "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n", + oldxkeys,newxkeys,count); + } + if (idcheck != 0) + (void) fprintf(table->out, + "Error in id's of xlist\twrong id's = %d\n", + idcheck); +#endif + + isolated += (table->vars[xindex]->ref == 1) + + (table->vars[yindex]->ref == 1); + table->isolated += isolated; + } + + /* Set the appropriate fields in table. */ + table->subtables[x].nodelist = ylist; + table->subtables[x].slots = yslots; + table->subtables[x].shift = yshift; + table->subtables[x].keys = newykeys; + table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; + i = table->subtables[x].bindVar; + table->subtables[x].bindVar = table->subtables[y].bindVar; + table->subtables[y].bindVar = i; + /* Adjust filds for lazy sifting. */ + varType = table->subtables[x].varType; + table->subtables[x].varType = table->subtables[y].varType; + table->subtables[y].varType = varType; + i = table->subtables[x].pairIndex; + table->subtables[x].pairIndex = table->subtables[y].pairIndex; + table->subtables[y].pairIndex = i; + i = table->subtables[x].varHandled; + table->subtables[x].varHandled = table->subtables[y].varHandled; + table->subtables[y].varHandled = i; + groupType = table->subtables[x].varToBeGrouped; + table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped; + table->subtables[y].varToBeGrouped = groupType; + + table->subtables[y].nodelist = xlist; + table->subtables[y].slots = xslots; + table->subtables[y].shift = xshift; + table->subtables[y].keys = newxkeys; + table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; + + table->perm[xindex] = y; table->perm[yindex] = x; + table->invperm[x] = yindex; table->invperm[y] = xindex; + + table->keys += newxkeys + newykeys - oldxkeys - oldykeys; + + return(table->keys - table->isolated); + +cuddSwapOutOfMem: + (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n"); + + return (0); + +} /* end of cuddSwapInPlace */ + + +/**Function******************************************************************** + + Synopsis [Reorders BDD variables according to the order of the ZDD + variables.] + + Description [Reorders BDD variables according to the order of the + ZDD variables. This function can be called at the end of ZDD + reordering to insure that the order of the BDD variables is + consistent with the order of the ZDD variables. The number of ZDD + variables must be a multiple of the number of BDD variables. Let + M be the ratio of the two numbers. cuddBddAlignToZdd + then considers the ZDD variables from M*i to + (M+1)*i-1 as corresponding to BDD variable + i. This function should be normally called from + Cudd_zddReduceHeap, which clears the cache. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [Changes the BDD variable order for all diagrams and performs + garbage collection of the BDD unique table.] + + SeeAlso [Cudd_ShuffleHeap Cudd_zddReduceHeap] + +******************************************************************************/ +int +cuddBddAlignToZdd( + DdManager * table /* DD manager */) +{ + int *invperm; /* permutation array */ + int M; /* ratio of ZDD variables to BDD variables */ + int i; /* loop index */ + int result; /* return value */ + + /* We assume that a ratio of 0 is OK. */ + if (table->size == 0) + return(1); + + M = table->sizeZ / table->size; + /* Check whether the number of ZDD variables is a multiple of the + ** number of BDD variables. + */ + if (M * table->size != table->sizeZ) + return(0); + /* Create and initialize the inverse permutation array. */ + invperm = ALLOC(int,table->size); + if (invperm == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (i = 0; i < table->sizeZ; i += M) { + int indexZ = table->invpermZ[i]; + int index = indexZ / M; + invperm[i / M] = index; + } + /* Eliminate dead nodes. Do not scan the cache again, because we + ** assume that Cudd_zddReduceHeap has already cleared it. + */ + cuddGarbageCollect(table,0); + + /* Initialize number of isolated projection functions. */ + table->isolated = 0; + for (i = 0; i < table->size; i++) { + if (table->vars[i]->ref == 1) table->isolated++; + } + + /* Initialize the interaction matrix. */ + result = cuddInitInteract(table); + if (result == 0) return(0); + + result = ddShuffle(table, invperm); + FREE(invperm); + /* Free interaction matrix. */ + FREE(table->interact); + /* Fix the BDD variable group tree. */ + bddFixTree(table,table->tree); + return(result); + +} /* end of cuddBddAlignToZdd */ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Comparison function used by qsort.] + + Description [Comparison function used by qsort to order the + variables according to the number of keys in the subtables. + Returns the difference in number of keys between the two + variables being compared.] + + SideEffects [None] + +******************************************************************************/ +static int +ddUniqueCompare( + int * ptrX, + int * ptrY) +{ +#if 0 + if (entry[*ptrY] == entry[*ptrX]) { + return((*ptrX) - (*ptrY)); + } +#endif + return(entry[*ptrY] - entry[*ptrX]); + +} /* end of ddUniqueCompare */ + + +/**Function******************************************************************** + + Synopsis [Swaps any two variables.] + + Description [Swaps any two variables. Returns the set of moves.] + + SideEffects [None] + +******************************************************************************/ +static Move * +ddSwapAny( + DdManager * table, + int x, + int y) +{ + Move *move, *moves; + int xRef,yRef; + int xNext,yNext; + int size; + int limitSize; + int tmp; + + if (x >y) { + tmp = x; x = y; y = tmp; + } + + xRef = x; yRef = y; + + xNext = cuddNextHigh(table,x); + yNext = cuddNextLow(table,y); + moves = NULL; + limitSize = table->keys - table->isolated; + + for (;;) { + if ( xNext == yNext) { + size = cuddSwapInPlace(table,x,xNext); + if (size == 0) goto ddSwapAnyOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddSwapAnyOutOfMem; + move->x = x; + move->y = xNext; + move->size = size; + move->next = moves; + moves = move; + + size = cuddSwapInPlace(table,yNext,y); + if (size == 0) goto ddSwapAnyOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddSwapAnyOutOfMem; + move->x = yNext; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + + size = cuddSwapInPlace(table,x,xNext); + if (size == 0) goto ddSwapAnyOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddSwapAnyOutOfMem; + move->x = x; + move->y = xNext; + move->size = size; + move->next = moves; + moves = move; + + tmp = x; x = y; y = tmp; + + } else if (x == yNext) { + + size = cuddSwapInPlace(table,x,xNext); + if (size == 0) goto ddSwapAnyOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddSwapAnyOutOfMem; + move->x = x; + move->y = xNext; + move->size = size; + move->next = moves; + moves = move; + + tmp = x; x = y; y = tmp; + + } else { + size = cuddSwapInPlace(table,x,xNext); + if (size == 0) goto ddSwapAnyOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddSwapAnyOutOfMem; + move->x = x; + move->y = xNext; + move->size = size; + move->next = moves; + moves = move; + + size = cuddSwapInPlace(table,yNext,y); + if (size == 0) goto ddSwapAnyOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddSwapAnyOutOfMem; + move->x = yNext; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + + x = xNext; + y = yNext; + } + + xNext = cuddNextHigh(table,x); + yNext = cuddNextLow(table,y); + if (xNext > yRef) break; + + if ((double) size > table->maxGrowth * (double) limitSize) break; + if (size < limitSize) limitSize = size; + } + if (yNext>=xRef) { + size = cuddSwapInPlace(table,yNext,y); + if (size == 0) goto ddSwapAnyOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddSwapAnyOutOfMem; + move->x = yNext; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + } + + return(moves); + +ddSwapAnyOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return(NULL); + +} /* end of ddSwapAny */ + + +/**Function******************************************************************** + + Synopsis [Given xLow <= x <= xHigh moves x up and down between the + boundaries.] + + Description [Given xLow <= x <= xHigh moves x up and down between the + boundaries. Finds the best position and does the required changes. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddSiftingAux( + DdManager * table, + int x, + int xLow, + int xHigh) +{ + + Move *move; + Move *moveUp; /* list of up moves */ + Move *moveDown; /* list of down moves */ + int initialSize; + int result; + + initialSize = table->keys - table->isolated; + + moveDown = NULL; + moveUp = NULL; + + if (x == xLow) { + moveDown = ddSiftingDown(table,x,xHigh); + /* At this point x --> xHigh unless bounding occurred. */ + if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; + /* Move backward and stop at best position. */ + result = ddSiftingBackward(table,initialSize,moveDown); + if (!result) goto ddSiftingAuxOutOfMem; + + } else if (x == xHigh) { + moveUp = ddSiftingUp(table,x,xLow); + /* At this point x --> xLow unless bounding occurred. */ + if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; + /* Move backward and stop at best position. */ + result = ddSiftingBackward(table,initialSize,moveUp); + if (!result) goto ddSiftingAuxOutOfMem; + + } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ + moveDown = ddSiftingDown(table,x,xHigh); + /* At this point x --> xHigh unless bounding occurred. */ + if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; + if (moveDown != NULL) { + x = moveDown->y; + } + moveUp = ddSiftingUp(table,x,xLow); + if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; + /* Move backward and stop at best position */ + result = ddSiftingBackward(table,initialSize,moveUp); + if (!result) goto ddSiftingAuxOutOfMem; + + } else { /* must go up first: shorter */ + moveUp = ddSiftingUp(table,x,xLow); + /* At this point x --> xLow unless bounding occurred. */ + if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; + if (moveUp != NULL) { + x = moveUp->x; + } + moveDown = ddSiftingDown(table,x,xHigh); + if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; + /* Move backward and stop at best position. */ + result = ddSiftingBackward(table,initialSize,moveDown); + if (!result) goto ddSiftingAuxOutOfMem; + } + + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *) moveDown); + moveDown = move; + } + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *) moveUp); + moveUp = move; + } + + return(1); + +ddSiftingAuxOutOfMem: + if (moveDown != (Move *) CUDD_OUT_OF_MEM) { + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *) moveDown); + moveDown = move; + } + } + if (moveUp != (Move *) CUDD_OUT_OF_MEM) { + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *) moveUp); + moveUp = move; + } + } + + return(0); + +} /* end of ddSiftingAux */ + + +/**Function******************************************************************** + + Synopsis [Sifts a variable up.] + + Description [Sifts a variable up. Moves y up until either it reaches + the bound (xLow) or the size of the DD heap increases too much. + Returns the set of moves in case of success; NULL if memory is full.] + + SideEffects [None] + +******************************************************************************/ +static Move * +ddSiftingUp( + DdManager * table, + int y, + int xLow) +{ + Move *moves; + Move *move; + int x; + int size; + int limitSize; + int xindex, yindex; + int isolated; + int L; /* lower bound on DD size */ +#ifdef DD_DEBUG + int checkL; + int z; + int zindex; +#endif + + moves = NULL; + yindex = table->invperm[y]; + + /* Initialize the lower bound. + ** The part of the DD below y will not change. + ** The part of the DD above y that does not interact with y will not + ** change. The rest may vanish in the best case, except for + ** the nodes at level xLow, which will not vanish, regardless. + */ + limitSize = L = table->keys - table->isolated; + for (x = xLow + 1; x < y; x++) { + xindex = table->invperm[x]; + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[xindex]->ref == 1; + L -= table->subtables[x].keys - isolated; + } + } + isolated = table->vars[yindex]->ref == 1; + L -= table->subtables[y].keys - isolated; + + x = cuddNextLow(table,y); + while (x >= xLow && L <= limitSize) { + xindex = table->invperm[x]; +#ifdef DD_DEBUG + checkL = table->keys - table->isolated; + for (z = xLow + 1; z < y; z++) { + zindex = table->invperm[z]; + if (cuddTestInteract(table,zindex,yindex)) { + isolated = table->vars[zindex]->ref == 1; + checkL -= table->subtables[z].keys - isolated; + } + } + isolated = table->vars[yindex]->ref == 1; + checkL -= table->subtables[y].keys - isolated; + assert(L == checkL); +#endif + size = cuddSwapInPlace(table,x,y); + if (size == 0) goto ddSiftingUpOutOfMem; + /* Update the lower bound. */ + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[xindex]->ref == 1; + L += table->subtables[y].keys - isolated; + } + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddSiftingUpOutOfMem; + move->x = x; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + if ((double) size > (double) limitSize * table->maxGrowth) break; + if (size < limitSize) limitSize = size; + y = x; + x = cuddNextLow(table,y); + } + return(moves); + +ddSiftingUpOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return((Move *) CUDD_OUT_OF_MEM); + +} /* end of ddSiftingUp */ + + +/**Function******************************************************************** + + Synopsis [Sifts a variable down.] + + Description [Sifts a variable down. Moves x down until either it + reaches the bound (xHigh) or the size of the DD heap increases too + much. Returns the set of moves in case of success; NULL if memory is + full.] + + SideEffects [None] + +******************************************************************************/ +static Move * +ddSiftingDown( + DdManager * table, + int x, + int xHigh) +{ + Move *moves; + Move *move; + int y; + int size; + int R; /* upper bound on node decrease */ + int limitSize; + int xindex, yindex; + int isolated; +#ifdef DD_DEBUG + int checkR; + int z; + int zindex; +#endif + + moves = NULL; + /* Initialize R */ + xindex = table->invperm[x]; + limitSize = size = table->keys - table->isolated; + R = 0; + for (y = xHigh; y > x; y--) { + yindex = table->invperm[y]; + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[yindex]->ref == 1; + R += table->subtables[y].keys - isolated; + } + } + + y = cuddNextHigh(table,x); + while (y <= xHigh && size - R < limitSize) { +#ifdef DD_DEBUG + checkR = 0; + for (z = xHigh; z > x; z--) { + zindex = table->invperm[z]; + if (cuddTestInteract(table,xindex,zindex)) { + isolated = table->vars[zindex]->ref == 1; + checkR += table->subtables[z].keys - isolated; + } + } + assert(R == checkR); +#endif + /* Update upper bound on node decrease. */ + yindex = table->invperm[y]; + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[yindex]->ref == 1; + R -= table->subtables[y].keys - isolated; + } + size = cuddSwapInPlace(table,x,y); + if (size == 0) goto ddSiftingDownOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddSiftingDownOutOfMem; + move->x = x; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + if ((double) size > (double) limitSize * table->maxGrowth) break; + if (size < limitSize) limitSize = size; + x = y; + y = cuddNextHigh(table,x); + } + return(moves); + +ddSiftingDownOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return((Move *) CUDD_OUT_OF_MEM); + +} /* end of ddSiftingDown */ + + +/**Function******************************************************************** + + Synopsis [Given a set of moves, returns the DD heap to the position + giving the minimum size.] + + Description [Given a set of moves, returns the DD heap to the + position giving the minimum size. In case of ties, returns to the + closest position giving the minimum size. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddSiftingBackward( + DdManager * table, + int size, + Move * moves) +{ + Move *move; + int res; + + for (move = moves; move != NULL; move = move->next) { + if (move->size < size) { + size = move->size; + } + } + + for (move = moves; move != NULL; move = move->next) { + if (move->size == size) return(1); + res = cuddSwapInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); + } + + return(1); + +} /* end of ddSiftingBackward */ + + +/**Function******************************************************************** + + Synopsis [Prepares the DD heap for dynamic reordering.] + + Description [Prepares the DD heap for dynamic reordering. Does + garbage collection, to guarantee that there are no dead nodes; + clears the cache, which is invalidated by dynamic reordering; initializes + the number of isolated projection functions; and initializes the + interaction matrix. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddReorderPreprocess( + DdManager * table) +{ + int i; + int res; + + /* Clear the cache. */ + cuddCacheFlush(table); + cuddLocalCacheClearAll(table); + + /* Eliminate dead nodes. Do not scan the cache again. */ + cuddGarbageCollect(table,0); + + /* Initialize number of isolated projection functions. */ + table->isolated = 0; + for (i = 0; i < table->size; i++) { + if (table->vars[i]->ref == 1) table->isolated++; + } + + /* Initialize the interaction matrix. */ + res = cuddInitInteract(table); + if (res == 0) return(0); + + return(1); + +} /* end of ddReorderPreprocess */ + + +/**Function******************************************************************** + + Synopsis [Cleans up at the end of reordering.] + + Description [] + + SideEffects [None] + +******************************************************************************/ +static int +ddReorderPostprocess( + DdManager * table) +{ + +#ifdef DD_VERBOSE + (void) fflush(table->out); +#endif + + /* Free interaction matrix. */ + FREE(table->interact); + + return(1); + +} /* end of ddReorderPostprocess */ + + +/**Function******************************************************************** + + Synopsis [Reorders variables according to a given permutation.] + + Description [Reorders variables according to a given permutation. + The i-th permutation array contains the index of the variable that + should be brought to the i-th level. ddShuffle assumes that no + dead nodes are present and that the interaction matrix is properly + initialized. The reordering is achieved by a series of upward sifts. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ddShuffle( + DdManager * table, + int * permutation) +{ + int index; + int level; + int position; + int numvars; + int result; +#ifdef DD_STATS + long localTime; + int initialSize; + int finalSize; + int previousSize; +#endif + + ddTotalNumberSwapping = 0; +#ifdef DD_STATS + localTime = util_cpu_time(); + initialSize = table->keys - table->isolated; + (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", + initialSize); + ddTotalNISwaps = 0; +#endif + + numvars = table->size; + + for (level = 0; level < numvars; level++) { + index = permutation[level]; + position = table->perm[index]; +#ifdef DD_STATS + previousSize = table->keys - table->isolated; +#endif + result = ddSiftUp(table,position,level); + if (!result) return(0); +#ifdef DD_STATS + if (table->keys < (unsigned) previousSize + table->isolated) { + (void) fprintf(table->out,"-"); + } else if (table->keys > (unsigned) previousSize + table->isolated) { + (void) fprintf(table->out,"+"); /* should never happen */ + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + +#ifdef DD_STATS + (void) fprintf(table->out,"\n"); + finalSize = table->keys - table->isolated; + (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); + (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", + ((double)(util_cpu_time() - localTime)/1000.0)); + (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", + ddTotalNumberSwapping); + (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps); +#endif + + return(1); + +} /* end of ddShuffle */ + + +/**Function******************************************************************** + + Synopsis [Moves one variable up.] + + Description [Takes a variable from position x and sifts it up to + position xLow; xLow should be less than or equal to x. + Returns 1 if successful; 0 otherwise] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +ddSiftUp( + DdManager * table, + int x, + int xLow) +{ + int y; + int size; + + y = cuddNextLow(table,x); + while (y >= xLow) { + size = cuddSwapInPlace(table,y,x); + if (size == 0) { + return(0); + } + x = y; + y = cuddNextLow(table,x); + } + return(1); + +} /* end of ddSiftUp */ + + +/**Function******************************************************************** + + Synopsis [Fixes the BDD variable group tree after a shuffle.] + + Description [Fixes the BDD variable group tree after a + shuffle. Assumes that the order of the variables in a terminal node + has not been changed.] + + SideEffects [Changes the BDD variable group tree.] + + SeeAlso [] + +******************************************************************************/ +static void +bddFixTree( + DdManager * table, + MtrNode * treenode) +{ + if (treenode == NULL) return; + treenode->low = ((int) treenode->index < table->size) ? + table->perm[treenode->index] : treenode->index; + if (treenode->child != NULL) { + bddFixTree(table, treenode->child); + } + if (treenode->younger != NULL) + bddFixTree(table, treenode->younger); + if (treenode->parent != NULL && treenode->low < treenode->parent->low) { + treenode->parent->low = treenode->low; + treenode->parent->index = treenode->index; + } + return; + +} /* end of bddFixTree */ + + +/**Function******************************************************************** + + Synopsis [Updates the BDD variable group tree before a shuffle.] + + Description [Updates the BDD variable group tree before a shuffle. + Returns 1 if successful; 0 otherwise.] + + SideEffects [Changes the BDD variable group tree.] + + SeeAlso [] + +******************************************************************************/ +static int +ddUpdateMtrTree( + DdManager * table, + MtrNode * treenode, + int * perm, + int * invperm) +{ + int i, size, index, level; + int minLevel, maxLevel, minIndex; + + if (treenode == NULL) return(1); + + /* i : level */ + for (i = treenode->low; i < treenode->low + treenode->size; i++) { + index = table->invperm[i]; + level = perm[index]; + if (level < minLevel) { + minLevel = level; + minIndex = index; + } + if (level > maxLevel) + maxLevel = level; + } + size = maxLevel - minLevel + 1; + if (size == treenode->size) { + treenode->low = minLevel; + treenode->index = minIndex; + } else + return(0); + + if (treenode->child != NULL) { + if (!ddUpdateMtrTree(table, treenode->child, perm, invperm)) + return(0); + } + if (treenode->younger != NULL) { + if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm)) + return(0); + } + return(1); +} + + +/**Function******************************************************************** + + Synopsis [Checks the BDD variable group tree before a shuffle.] + + Description [Checks the BDD variable group tree before a shuffle. + Returns 1 if successful; 0 otherwise.] + + SideEffects [Changes the BDD variable group tree.] + + SeeAlso [] + +******************************************************************************/ +static int +ddCheckPermuation( + DdManager * table, + MtrNode * treenode, + int * perm, + int * invperm) +{ + int i, size, index, level; + int minLevel, maxLevel; + + if (treenode == NULL) return(1); + + minLevel = table->size; + maxLevel = 0; + /* i : level */ + for (i = treenode->low; i < treenode->low + treenode->size; i++) { + index = table->invperm[i]; + level = perm[index]; + if (level < minLevel) + minLevel = level; + if (level > maxLevel) + maxLevel = level; + } + size = maxLevel - minLevel + 1; + if (size != treenode->size) + return(0); + + if (treenode->child != NULL) { + if (!ddCheckPermuation(table, treenode->child, perm, invperm)) + return(0); + } + if (treenode->younger != NULL) { + if (!ddCheckPermuation(table, treenode->younger, perm, invperm)) + return(0); + } + return(1); +} diff --git a/abc70930/src/bdd/cudd/cuddSat.c b/abc70930/src/bdd/cudd/cuddSat.c new file mode 100644 index 00000000..1755a1c1 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddSat.c @@ -0,0 +1,1305 @@ +/**CFile*********************************************************************** + + FileName [cuddSat.c] + + PackageName [cudd] + + Synopsis [Functions for the solution of satisfiability related + problems.] + + Description [External procedures included in this file: +
        +
      • Cudd_Eval() +
      • Cudd_ShortestPath() +
      • Cudd_LargestCube() +
      • Cudd_ShortestLength() +
      • Cudd_Decreasing() +
      • Cudd_Increasing() +
      • Cudd_EquivDC() +
      • Cudd_bddLeqUnless() +
      • Cudd_EqualSupNorm() +
      • Cudd_bddMakePrime() +
      + Internal procedures included in this module: +
        +
      • cuddBddMakePrime() +
      + Static procedures included in this module: +
        +
      • freePathPair() +
      • getShortest() +
      • getPath() +
      • getLargest() +
      • getCube() +
      ] + + Author [Seh-Woong Jeong, Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define DD_BIGGY 1000000 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +typedef struct cuddPathPair { + int pos; + int neg; +} cuddPathPair; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +static DdNode *one, *zero; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define WEIGHT(weight, col) ((weight) == NULL ? 1 : weight[col]) + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static enum st_retval freePathPair ARGS((char *key, char *value, char *arg)); +static cuddPathPair getShortest ARGS((DdNode *root, int *cost, int *support, st_table *visited)); +static DdNode * getPath ARGS((DdManager *manager, st_table *visited, DdNode *f, int *weight, int cost)); +static cuddPathPair getLargest ARGS((DdNode *root, st_table *visited)); +static DdNode * getCube ARGS((DdManager *manager, st_table *visited, DdNode *f, int cost)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Returns the value of a DD for a given variable assignment.] + + Description [Finds the value of a DD for a given variable + assignment. The variable assignment is passed in an array of int's, + that should specify a zero or a one for each variable in the support + of the function. Returns a pointer to a constant node. No new nodes + are produced.] + + SideEffects [None] + + SeeAlso [Cudd_bddLeq Cudd_addEvalConst] + +******************************************************************************/ +DdNode * +Cudd_Eval( + DdManager * dd, + DdNode * f, + int * inputs) +{ + int comple; + DdNode *ptr; + + comple = Cudd_IsComplement(f); + ptr = Cudd_Regular(f); + + while (!cuddIsConstant(ptr)) { + if (inputs[ptr->index] == 1) { + ptr = cuddT(ptr); + } else { + comple ^= Cudd_IsComplement(cuddE(ptr)); + ptr = Cudd_Regular(cuddE(ptr)); + } + } + return(Cudd_NotCond(ptr,comple)); + +} /* end of Cudd_Eval */ + + +/**Function******************************************************************** + + Synopsis [Finds a shortest path in a DD.] + + Description [Finds a shortest path in a DD. f is the DD we want to + get the shortest path for; weight\[i\] is the weight of the THEN arc + coming from the node whose index is i. If weight is NULL, then unit + weights are assumed for all THEN arcs. All ELSE arcs have 0 weight. + If non-NULL, both weight and support should point to arrays with at + least as many entries as there are variables in the manager. + Returns the shortest path as the BDD of a cube.] + + SideEffects [support contains on return the true support of f. + If support is NULL on entry, then Cudd_ShortestPath does not compute + the true support info. length contains the length of the path.] + + SeeAlso [Cudd_ShortestLength Cudd_LargestCube] + +******************************************************************************/ +DdNode * +Cudd_ShortestPath( + DdManager * manager, + DdNode * f, + int * weight, + int * support, + int * length) +{ + register DdNode *F; + st_table *visited; + DdNode *sol; + cuddPathPair *rootPair; + int complement, cost; + int i; + + one = DD_ONE(manager); + zero = DD_ZERO(manager); + + /* Initialize support. */ + if (support) { + for (i = 0; i < manager->size; i++) { + support[i] = 0; + } + } + + if (f == Cudd_Not(one) || f == zero) { + *length = DD_BIGGY; + return(Cudd_Not(one)); + } + /* From this point on, a path exists. */ + + /* Initialize visited table. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + + /* Now get the length of the shortest path(s) from f to 1. */ + (void) getShortest(f, weight, support, visited); + + complement = Cudd_IsComplement(f); + + F = Cudd_Regular(f); + + st_lookup(visited, (char *)F, (char **)&rootPair); + + if (complement) { + cost = rootPair->neg; + } else { + cost = rootPair->pos; + } + + /* Recover an actual shortest path. */ + do { + manager->reordered = 0; + sol = getPath(manager,visited,f,weight,cost); + } while (manager->reordered == 1); + + st_foreach(visited, freePathPair, NULL); + st_free_table(visited); + + *length = cost; + return(sol); + +} /* end of Cudd_ShortestPath */ + + +/**Function******************************************************************** + + Synopsis [Finds a largest cube in a DD.] + + Description [Finds a largest cube in a DD. f is the DD we want to + get the largest cube for. The problem is translated into the one of + finding a shortest path in f, when both THEN and ELSE arcs are assumed to + have unit length. This yields a largest cube in the disjoint cover + corresponding to the DD. Therefore, it is not necessarily the largest + implicant of f. Returns the largest cube as a BDD.] + + SideEffects [The number of literals of the cube is returned in length.] + + SeeAlso [Cudd_ShortestPath] + +******************************************************************************/ +DdNode * +Cudd_LargestCube( + DdManager * manager, + DdNode * f, + int * length) +{ + register DdNode *F; + st_table *visited; + DdNode *sol; + cuddPathPair *rootPair; + int complement, cost; + + one = DD_ONE(manager); + zero = DD_ZERO(manager); + + if (f == Cudd_Not(one) || f == zero) { + *length = DD_BIGGY; + return(Cudd_Not(one)); + } + /* From this point on, a path exists. */ + + /* Initialize visited table. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + + /* Now get the length of the shortest path(s) from f to 1. */ + (void) getLargest(f, visited); + + complement = Cudd_IsComplement(f); + + F = Cudd_Regular(f); + + st_lookup(visited, (char *)F, (char **)&rootPair); + + if (complement) { + cost = rootPair->neg; + } else { + cost = rootPair->pos; + } + + /* Recover an actual shortest path. */ + do { + manager->reordered = 0; + sol = getCube(manager,visited,f,cost); + } while (manager->reordered == 1); + + st_foreach(visited, freePathPair, NULL); + st_free_table(visited); + + *length = cost; + return(sol); + +} /* end of Cudd_LargestCube */ + + +/**Function******************************************************************** + + Synopsis [Find the length of the shortest path(s) in a DD.] + + Description [Find the length of the shortest path(s) in a DD. f is + the DD we want to get the shortest path for; weight\[i\] is the + weight of the THEN edge coming from the node whose index is i. All + ELSE edges have 0 weight. Returns the length of the shortest + path(s) if successful; CUDD_OUT_OF_MEM otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_ShortestPath] + +******************************************************************************/ +int +Cudd_ShortestLength( + DdManager * manager, + DdNode * f, + int * weight) +{ + register DdNode *F; + st_table *visited; + cuddPathPair *my_pair; + int complement, cost; + + one = DD_ONE(manager); + zero = DD_ZERO(manager); + + if (f == Cudd_Not(one) || f == zero) { + return(DD_BIGGY); + } + + /* From this point on, a path exists. */ + /* Initialize visited table and support. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + + /* Now get the length of the shortest path(s) from f to 1. */ + (void) getShortest(f, weight, NULL, visited); + + complement = Cudd_IsComplement(f); + + F = Cudd_Regular(f); + + st_lookup(visited, (char *)F, (char **)&my_pair); + + if (complement) { + cost = my_pair->neg; + } else { + cost = my_pair->pos; + } + + st_foreach(visited, freePathPair, NULL); + st_free_table(visited); + + return(cost); + +} /* end of Cudd_ShortestLength */ + + +/**Function******************************************************************** + + Synopsis [Determines whether a BDD is negative unate in a + variable.] + + Description [Determines whether the function represented by BDD f is + negative unate (monotonic decreasing) in variable i. Returns the + constant one is f is unate and the (logical) constant zero if it is not. + This function does not generate any new nodes.] + + SideEffects [None] + + SeeAlso [Cudd_Increasing] + +******************************************************************************/ +DdNode * +Cudd_Decreasing( + DdManager * dd, + DdNode * f, + int i) +{ + unsigned int topf, level; + DdNode *F, *fv, *fvn, *res; + DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); + + statLine(dd); +#ifdef DD_DEBUG + assert(0 <= i && i < dd->size); +#endif + + F = Cudd_Regular(f); + topf = cuddI(dd,F->index); + + /* Check terminal case. If topf > i, f does not depend on var. + ** Therefore, f is unate in i. + */ + level = (unsigned) dd->perm[i]; + if (topf > level) { + return(DD_ONE(dd)); + } + + /* From now on, f is not constant. */ + + /* Check cache. */ + cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) Cudd_Decreasing; + res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]); + if (res != NULL) { + return(res); + } + + /* Compute cofactors. */ + fv = cuddT(F); fvn = cuddE(F); + if (F != f) { + fv = Cudd_Not(fv); + fvn = Cudd_Not(fvn); + } + + if (topf == (unsigned) level) { + /* Special case: if fv is regular, fv(1,...,1) = 1; + ** If in addition fvn is complemented, fvn(1,...,1) = 0. + ** But then f(1,1,...,1) > f(0,1,...,1). Hence f is not + ** monotonic decreasing in i. + */ + if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) { + return(Cudd_Not(DD_ONE(dd))); + } + res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd)); + } else { + res = Cudd_Decreasing(dd,fv,i); + if (res == DD_ONE(dd)) { + res = Cudd_Decreasing(dd,fvn,i); + } + } + + cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res); + return(res); + +} /* end of Cudd_Decreasing */ + + +/**Function******************************************************************** + + Synopsis [Determines whether a BDD is positive unate in a + variable.] + + Description [Determines whether the function represented by BDD f is + positive unate (monotonic decreasing) in variable i. It is based on + Cudd_Decreasing and the fact that f is monotonic increasing in i if + and only if its complement is monotonic decreasing in i.] + + SideEffects [None] + + SeeAlso [Cudd_Decreasing] + +******************************************************************************/ +DdNode * +Cudd_Increasing( + DdManager * dd, + DdNode * f, + int i) +{ + return(Cudd_Decreasing(dd,Cudd_Not(f),i)); + +} /* end of Cudd_Increasing */ + + +/**Function******************************************************************** + + Synopsis [Tells whether F and G are identical wherever D is 0.] + + Description [Tells whether F and G are identical wherever D is 0. F + and G are either two ADDs or two BDDs. D is either a 0-1 ADD or a + BDD. The function returns 1 if F and G are equivalent, and 0 + otherwise. No new nodes are created.] + + SideEffects [None] + + SeeAlso [Cudd_bddLeqUnless] + +******************************************************************************/ +int +Cudd_EquivDC( + DdManager * dd, + DdNode * F, + DdNode * G, + DdNode * D) +{ + DdNode *tmp, *One, *Gr, *Dr; + DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn; + int res; + unsigned int flevel, glevel, dlevel, top; + + One = DD_ONE(dd); + + statLine(dd); + /* Check terminal cases. */ + if (D == One || F == G) return(1); + if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0); + + /* From now on, D is non-constant. */ + + /* Normalize call to increase cache efficiency. */ + if (F > G) { + tmp = F; + F = G; + G = tmp; + } + if (Cudd_IsComplement(F)) { + F = Cudd_Not(F); + G = Cudd_Not(G); + } + + /* From now on, F is regular. */ + + /* Check cache. */ + tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D); + if (tmp != NULL) return(tmp == One); + + /* Find splitting variable. */ + flevel = cuddI(dd,F->index); + Gr = Cudd_Regular(G); + glevel = cuddI(dd,Gr->index); + top = ddMin(flevel,glevel); + Dr = Cudd_Regular(D); + dlevel = dd->perm[Dr->index]; + top = ddMin(top,dlevel); + + /* Compute cofactors. */ + if (top == flevel) { + Fv = cuddT(F); + Fvn = cuddE(F); + } else { + Fv = Fvn = F; + } + if (top == glevel) { + Gv = cuddT(Gr); + Gvn = cuddE(Gr); + if (G != Gr) { + Gv = Cudd_Not(Gv); + Gvn = Cudd_Not(Gvn); + } + } else { + Gv = Gvn = G; + } + if (top == dlevel) { + Dv = cuddT(Dr); + Dvn = cuddE(Dr); + if (D != Dr) { + Dv = Cudd_Not(Dv); + Dvn = Cudd_Not(Dvn); + } + } else { + Dv = Dvn = D; + } + + /* Solve recursively. */ + res = Cudd_EquivDC(dd,Fv,Gv,Dv); + if (res != 0) { + res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn); + } + cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One)); + + return(res); + +} /* end of Cudd_EquivDC */ + + +/**Function******************************************************************** + + Synopsis [Tells whether f is less than of equal to G unless D is 1.] + + Description [Tells whether f is less than of equal to G unless D is + 1. f, g, and D are BDDs. The function returns 1 if f is less than + of equal to G, and 0 otherwise. No new nodes are created.] + + SideEffects [None] + + SeeAlso [Cudd_EquivDC Cudd_bddLeq Cudd_bddIteConstant] + +******************************************************************************/ +int +Cudd_bddLeqUnless( + DdManager *dd, + DdNode *f, + DdNode *g, + DdNode *D) +{ + DdNode *tmp, *One, *F, *G; + DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De; + int res; + unsigned int flevel, glevel, dlevel, top; + + statLine(dd); + + One = DD_ONE(dd); + + /* Check terminal cases. */ + if (f == g || g == One || f == Cudd_Not(One) || D == One || + D == f || D == Cudd_Not(g)) return(1); + /* Check for two-operand cases. */ + if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f)) + return(Cudd_bddLeq(dd,f,g)); + if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D)); + if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D)); + + /* From now on, f, g, and D are non-constant, distinct, and + ** non-complementary. */ + + /* Normalize call to increase cache efficiency. We rely on the + ** fact that f <= g unless D is equivalent to not(g) <= not(f) + ** unless D and to f <= D unless g. We make sure that D is + ** regular, and that at most one of f and g is complemented. We also + ** ensure that when two operands can be swapped, the one with the + ** lowest address comes first. */ + + if (Cudd_IsComplement(D)) { + if (Cudd_IsComplement(g)) { + /* Special case: if f is regular and g is complemented, + ** f(1,...,1) = 1 > 0 = g(1,...,1). If D(1,...,1) = 0, return 0. + */ + if (!Cudd_IsComplement(f)) return(0); + /* !g <= D unless !f or !D <= g unless !f */ + tmp = D; + D = Cudd_Not(f); + if (g < tmp) { + f = Cudd_Not(g); + g = tmp; + } else { + f = Cudd_Not(tmp); + } + } else { + if (Cudd_IsComplement(f)) { + /* !D <= !f unless g or !D <= g unless !f */ + tmp = f; + f = Cudd_Not(D); + if (tmp < g) { + D = g; + g = Cudd_Not(tmp); + } else { + D = Cudd_Not(tmp); + } + } else { + /* f <= D unless g or !D <= !f unless g */ + tmp = D; + D = g; + if (tmp < f) { + g = Cudd_Not(f); + f = Cudd_Not(tmp); + } else { + g = tmp; + } + } + } + } else { + if (Cudd_IsComplement(g)) { + if (Cudd_IsComplement(f)) { + /* !g <= !f unless D or !g <= D unless !f */ + tmp = f; + f = Cudd_Not(g); + if (D < tmp) { + g = D; + D = Cudd_Not(tmp); + } else { + g = Cudd_Not(tmp); + } + } else { + /* f <= g unless D or !g <= !f unless D */ + if (g < f) { + tmp = g; + g = Cudd_Not(f); + f = Cudd_Not(tmp); + } + } + } else { + /* f <= g unless D or f <= D unless g */ + if (D < g) { + tmp = D; + D = g; + g = tmp; + } + } + } + + /* From now on, D is regular. */ + + /* Check cache. */ + tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D); + if (tmp != NULL) return(tmp == One); + + /* Find splitting variable. */ + F = Cudd_Regular(f); + flevel = dd->perm[F->index]; + G = Cudd_Regular(g); + glevel = dd->perm[G->index]; + top = ddMin(flevel,glevel); + dlevel = dd->perm[D->index]; + top = ddMin(top,dlevel); + + /* Compute cofactors. */ + if (top == flevel) { + Ft = cuddT(F); + Fe = cuddE(F); + if (F != f) { + Ft = Cudd_Not(Ft); + Fe = Cudd_Not(Fe); + } + } else { + Ft = Fe = f; + } + if (top == glevel) { + Gt = cuddT(G); + Ge = cuddE(G); + if (G != g) { + Gt = Cudd_Not(Gt); + Ge = Cudd_Not(Ge); + } + } else { + Gt = Ge = g; + } + if (top == dlevel) { + Dt = cuddT(D); + De = cuddE(D); + } else { + Dt = De = D; + } + + /* Solve recursively. */ + res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt); + if (res != 0) { + res = Cudd_bddLeqUnless(dd,Fe,Ge,De); + } + cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res)); + + return(res); + +} /* end of Cudd_bddLeqUnless */ + + +/**Function******************************************************************** + + Synopsis [Compares two ADDs for equality within tolerance.] + + Description [Compares two ADDs for equality within tolerance. Two + ADDs are reported to be equal if the maximum difference between them + (the sup norm of their difference) is less than or equal to the + tolerance parameter. Returns 1 if the two ADDs are equal (within + tolerance); 0 otherwise. If parameter pr is positive + the first failure is reported to the standard output.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_EqualSupNorm( + DdManager * dd /* manager */, + DdNode * f /* first ADD */, + DdNode * g /* second ADD */, + CUDD_VALUE_TYPE tolerance /* maximum allowed difference */, + int pr /* verbosity level */) +{ + DdNode *fv, *fvn, *gv, *gvn, *r; + unsigned int topf, topg; + + statLine(dd); + /* Check terminal cases. */ + if (f == g) return(1); + if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) { + if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) { + return(1); + } else { + if (pr>0) { + (void) fprintf(dd->out,"Offending nodes:\n"); +#if SIZEOF_VOID_P == 8 + (void) fprintf(dd->out, + "f: address = %lx\t value = %40.30f\n", + (unsigned long) f, cuddV(f)); + (void) fprintf(dd->out, + "g: address = %lx\t value = %40.30f\n", + (unsigned long) g, cuddV(g)); +#else + (void) fprintf(dd->out, + "f: address = %x\t value = %40.30f\n", + (unsigned) f, cuddV(f)); + (void) fprintf(dd->out, + "g: address = %x\t value = %40.30f\n", + (unsigned) g, cuddV(g)); +#endif + } + return(0); + } + } + + /* We only insert the result in the cache if the comparison is + ** successful. Therefore, if we hit we return 1. */ + r = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_EqualSupNorm,f,g); + if (r != NULL) { + return(1); + } + + /* Compute the cofactors and solve the recursive subproblems. */ + topf = cuddI(dd,f->index); + topg = cuddI(dd,g->index); + + if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;} + if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;} + + if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0); + if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0); + + cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_EqualSupNorm,f,g,DD_ONE(dd)); + + return(1); + +} /* end of Cudd_EqualSupNorm */ + + +/**Function******************************************************************** + + Synopsis [Expands cube to a prime implicant of f.] + + Description [Expands cube to a prime implicant of f. Returns the prime + if successful; NULL otherwise. In particular, NULL is returned if cube + is not a real cube or is not an implicant of f.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_bddMakePrime( + DdManager *dd /* manager */, + DdNode *cube /* cube to be expanded */, + DdNode *f /* function of which the cube is to be made a prime */) +{ + DdNode *res; + + if (!Cudd_bddLeq(dd,cube,f)) return(NULL); + + do { + dd->reordered = 0; + res = cuddBddMakePrime(dd,cube,f); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddMakePrime */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddMakePrime.] + + Description [Performs the recursive step of Cudd_bddMakePrime. + Returns the prime if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddBddMakePrime( + DdManager *dd /* manager */, + DdNode *cube /* cube to be expanded */, + DdNode *f /* function of which the cube is to be made a prime */) +{ + DdNode *scan; + DdNode *t, *e; + DdNode *res = cube; + DdNode *zero = Cudd_Not(DD_ONE(dd)); + + Cudd_Ref(res); + scan = cube; + while (!Cudd_IsConstant(scan)) { + DdNode *reg = Cudd_Regular(scan); + DdNode *var = dd->vars[reg->index]; + DdNode *expanded = Cudd_bddExistAbstract(dd,res,var); + if (expanded == NULL) { + return(NULL); + } + Cudd_Ref(expanded); + if (Cudd_bddLeq(dd,expanded,f)) { + Cudd_RecursiveDeref(dd,res); + res = expanded; + } else { + Cudd_RecursiveDeref(dd,expanded); + } + cuddGetBranches(scan,&t,&e); + if (t == zero) { + scan = e; + } else if (e == zero) { + scan = t; + } else { + Cudd_RecursiveDeref(dd,res); + return(NULL); /* cube is not a cube */ + } + } + + if (scan == DD_ONE(dd)) { + Cudd_Deref(res); + return(res); + } else { + Cudd_RecursiveDeref(dd,res); + return(NULL); + } + +} /* end of cuddBddMakePrime */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Frees the entries of the visited symbol table.] + + Description [Frees the entries of the visited symbol table. Returns + ST_CONTINUE.] + + SideEffects [None] + +******************************************************************************/ +static enum st_retval +freePathPair( + char * key, + char * value, + char * arg) +{ + cuddPathPair *pair; + + pair = (cuddPathPair *) value; + FREE(pair); + return(ST_CONTINUE); + +} /* end of freePathPair */ + + +/**Function******************************************************************** + + Synopsis [Finds the length of the shortest path(s) in a DD.] + + Description [Finds the length of the shortest path(s) in a DD. + Uses a local symbol table to store the lengths for each + node. Only the lengths for the regular nodes are entered in the table, + because those for the complement nodes are simply obtained by swapping + the two lenghts. + Returns a pair of lengths: the length of the shortest path to 1; + and the length of the shortest path to 0. This is done so as to take + complement arcs into account.] + + SideEffects [Accumulates the support of the DD in support.] + + SeeAlso [] + +******************************************************************************/ +static cuddPathPair +getShortest( + DdNode * root, + int * cost, + int * support, + st_table * visited) +{ + cuddPathPair *my_pair, res_pair, pair_T, pair_E; + DdNode *my_root, *T, *E; + int weight; + + my_root = Cudd_Regular(root); + + if (st_lookup(visited, (char *)my_root, (char **)&my_pair)) { + if (Cudd_IsComplement(root)) { + res_pair.pos = my_pair->neg; + res_pair.neg = my_pair->pos; + } else { + res_pair.pos = my_pair->pos; + res_pair.neg = my_pair->neg; + } + return(res_pair); + } + + /* In the case of a BDD the following test is equivalent to + ** testing whether the BDD is the constant 1. This formulation, + ** however, works for ADDs as well, by assuming the usual + ** dichotomy of 0 and != 0. + */ + if (cuddIsConstant(my_root)) { + if (my_root != zero) { + res_pair.pos = 0; + res_pair.neg = DD_BIGGY; + } else { + res_pair.pos = DD_BIGGY; + res_pair.neg = 0; + } + } else { + T = cuddT(my_root); + E = cuddE(my_root); + + pair_T = getShortest(T, cost, support, visited); + pair_E = getShortest(E, cost, support, visited); + weight = WEIGHT(cost, my_root->index); + res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos); + res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg); + + /* Update support. */ + if (support != NULL) { + support[my_root->index] = 1; + } + } + + my_pair = ALLOC(cuddPathPair, 1); + if (my_pair == NULL) { + if (Cudd_IsComplement(root)) { + int tmp = res_pair.pos; + res_pair.pos = res_pair.neg; + res_pair.neg = tmp; + } + return(res_pair); + } + my_pair->pos = res_pair.pos; + my_pair->neg = res_pair.neg; + + st_insert(visited, (char *)my_root, (char *)my_pair); + if (Cudd_IsComplement(root)) { + res_pair.pos = my_pair->neg; + res_pair.neg = my_pair->pos; + } else { + res_pair.pos = my_pair->pos; + res_pair.neg = my_pair->neg; + } + return(res_pair); + +} /* end of getShortest */ + + +/**Function******************************************************************** + + Synopsis [Build a BDD for a shortest path of f.] + + Description [Build a BDD for a shortest path of f. + Given the minimum length from the root, and the minimum + lengths for each node (in visited), apply triangulation at each node. + Of the two children of each node on a shortest path, at least one is + on a shortest path. In case of ties the procedure chooses the THEN + children. + Returns a pointer to the cube BDD representing the path if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +getPath( + DdManager * manager, + st_table * visited, + DdNode * f, + int * weight, + int cost) +{ + DdNode *sol, *tmp; + DdNode *my_dd, *T, *E; + cuddPathPair *T_pair, *E_pair; + int Tcost, Ecost; + int complement; + + my_dd = Cudd_Regular(f); + complement = Cudd_IsComplement(f); + + sol = one; + cuddRef(sol); + + while (!cuddIsConstant(my_dd)) { + Tcost = cost - WEIGHT(weight, my_dd->index); + Ecost = cost; + + T = cuddT(my_dd); + E = cuddE(my_dd); + + if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);} + + st_lookup(visited, (char *)Cudd_Regular(T), (char **)&T_pair); + if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) || + (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) { + tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol); + if (tmp == NULL) { + Cudd_RecursiveDeref(manager,sol); + return(NULL); + } + cuddRef(tmp); + Cudd_RecursiveDeref(manager,sol); + sol = tmp; + + complement = Cudd_IsComplement(T); + my_dd = Cudd_Regular(T); + cost = Tcost; + continue; + } + st_lookup(visited, (char *)Cudd_Regular(E), (char **)&E_pair); + if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) || + (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) { + tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol); + if (tmp == NULL) { + Cudd_RecursiveDeref(manager,sol); + return(NULL); + } + cuddRef(tmp); + Cudd_RecursiveDeref(manager,sol); + sol = tmp; + complement = Cudd_IsComplement(E); + my_dd = Cudd_Regular(E); + cost = Ecost; + continue; + } + (void) fprintf(manager->err,"We shouldn't be here!!\n"); + manager->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + + cuddDeref(sol); + return(sol); + +} /* end of getPath */ + + +/**Function******************************************************************** + + Synopsis [Finds the size of the largest cube(s) in a DD.] + + Description [Finds the size of the largest cube(s) in a DD. + This problem is translated into finding the shortest paths from a node + when both THEN and ELSE arcs have unit lengths. + Uses a local symbol table to store the lengths for each + node. Only the lengths for the regular nodes are entered in the table, + because those for the complement nodes are simply obtained by swapping + the two lenghts. + Returns a pair of lengths: the length of the shortest path to 1; + and the length of the shortest path to 0. This is done so as to take + complement arcs into account.] + + SideEffects [none] + + SeeAlso [] + +******************************************************************************/ +static cuddPathPair +getLargest( + DdNode * root, + st_table * visited) +{ + cuddPathPair *my_pair, res_pair, pair_T, pair_E; + DdNode *my_root, *T, *E; + + my_root = Cudd_Regular(root); + + if (st_lookup(visited, (char *)my_root, (char **)&my_pair)) { + if (Cudd_IsComplement(root)) { + res_pair.pos = my_pair->neg; + res_pair.neg = my_pair->pos; + } else { + res_pair.pos = my_pair->pos; + res_pair.neg = my_pair->neg; + } + return(res_pair); + } + + /* In the case of a BDD the following test is equivalent to + ** testing whether the BDD is the constant 1. This formulation, + ** however, works for ADDs as well, by assuming the usual + ** dichotomy of 0 and != 0. + */ + if (cuddIsConstant(my_root)) { + if (my_root != zero) { + res_pair.pos = 0; + res_pair.neg = DD_BIGGY; + } else { + res_pair.pos = DD_BIGGY; + res_pair.neg = 0; + } + } else { + T = cuddT(my_root); + E = cuddE(my_root); + + pair_T = getLargest(T, visited); + pair_E = getLargest(E, visited); + res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1; + res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1; + } + + my_pair = ALLOC(cuddPathPair, 1); + if (my_pair == NULL) { /* simlpy do not cache this result */ + if (Cudd_IsComplement(root)) { + int tmp = res_pair.pos; + res_pair.pos = res_pair.neg; + res_pair.neg = tmp; + } + return(res_pair); + } + my_pair->pos = res_pair.pos; + my_pair->neg = res_pair.neg; + + st_insert(visited, (char *)my_root, (char *)my_pair); + if (Cudd_IsComplement(root)) { + res_pair.pos = my_pair->neg; + res_pair.neg = my_pair->pos; + } else { + res_pair.pos = my_pair->pos; + res_pair.neg = my_pair->neg; + } + return(res_pair); + +} /* end of getLargest */ + + +/**Function******************************************************************** + + Synopsis [Build a BDD for a largest cube of f.] + + Description [Build a BDD for a largest cube of f. + Given the minimum length from the root, and the minimum + lengths for each node (in visited), apply triangulation at each node. + Of the two children of each node on a shortest path, at least one is + on a shortest path. In case of ties the procedure chooses the THEN + children. + Returns a pointer to the cube BDD representing the path if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +getCube( + DdManager * manager, + st_table * visited, + DdNode * f, + int cost) +{ + DdNode *sol, *tmp; + DdNode *my_dd, *T, *E; + cuddPathPair *T_pair, *E_pair; + int Tcost, Ecost; + int complement; + + my_dd = Cudd_Regular(f); + complement = Cudd_IsComplement(f); + + sol = one; + cuddRef(sol); + + while (!cuddIsConstant(my_dd)) { + Tcost = cost - 1; + Ecost = cost - 1; + + T = cuddT(my_dd); + E = cuddE(my_dd); + + if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);} + + st_lookup(visited, (char *)Cudd_Regular(T), (char **)&T_pair); + if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) || + (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) { + tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol); + if (tmp == NULL) { + Cudd_RecursiveDeref(manager,sol); + return(NULL); + } + cuddRef(tmp); + Cudd_RecursiveDeref(manager,sol); + sol = tmp; + + complement = Cudd_IsComplement(T); + my_dd = Cudd_Regular(T); + cost = Tcost; + continue; + } + st_lookup(visited, (char *)Cudd_Regular(E), (char **)&E_pair); + if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) || + (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) { + tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol); + if (tmp == NULL) { + Cudd_RecursiveDeref(manager,sol); + return(NULL); + } + cuddRef(tmp); + Cudd_RecursiveDeref(manager,sol); + sol = tmp; + complement = Cudd_IsComplement(E); + my_dd = Cudd_Regular(E); + cost = Ecost; + continue; + } + (void) fprintf(manager->err,"We shouldn't be here!\n"); + manager->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + + cuddDeref(sol); + return(sol); + +} /* end of getCube */ diff --git a/abc70930/src/bdd/cudd/cuddSign.c b/abc70930/src/bdd/cudd/cuddSign.c new file mode 100644 index 00000000..fcaa65c4 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddSign.c @@ -0,0 +1,292 @@ +/**CFile*********************************************************************** + + FileName [cuddSign.c] + + PackageName [cudd] + + Synopsis [Computation of signatures] + + Description [External procedures included in this module: +
        +
      • Cudd_CofMinterm(); +
      + Static procedures included in this module: +
        +
      • ddCofMintermAux() +
      + ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddSign.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +static int size; + +#ifdef DD_STATS +static int num_calls; /* should equal 2n-1 (n is the # of nodes) */ +static int table_mem; +#endif + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static double * ddCofMintermAux ARGS((DdManager *dd, DdNode *node, st_table *table)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes the fraction of minterms in the on-set of all the + positive cofactors of a BDD or ADD.] + + Description [Computes the fraction of minterms in the on-set of all + the positive cofactors of DD. Returns the pointer to an array of + doubles if successful; NULL otherwise. The array hs as many + positions as there are BDD variables in the manager plus one. The + last position of the array contains the fraction of the minterms in + the ON-set of the function represented by the BDD or ADD. The other + positions of the array hold the variable signatures.] + + SideEffects [None] + +******************************************************************************/ +double * +Cudd_CofMinterm( + DdManager * dd, + DdNode * node) +{ + st_table *table; + double *values; + double *result = NULL; + int i, firstLevel; + +#ifdef DD_STATS + long startTime; + startTime = util_cpu_time(); + num_calls = 0; + table_mem = sizeof(st_table); +#endif + + table = st_init_table(st_ptrcmp, st_ptrhash); + if (table == NULL) { + (void) fprintf(dd->err, + "out-of-memory, couldn't measure DD cofactors.\n"); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + size = dd->size; + values = ddCofMintermAux(dd, node, table); + if (values != NULL) { + result = ALLOC(double,size + 1); + if (result != NULL) { +#ifdef DD_STATS + table_mem += (size + 1) * sizeof(double); +#endif + if (Cudd_IsConstant(node)) + firstLevel = 1; + else + firstLevel = cuddI(dd,Cudd_Regular(node)->index); + for (i = 0; i < size; i++) { + if (i >= cuddI(dd,Cudd_Regular(node)->index)) { + result[dd->invperm[i]] = values[i - firstLevel]; + } else { + result[dd->invperm[i]] = values[size - firstLevel]; + } + } + result[size] = values[size - firstLevel]; + } else { + dd->errorCode = CUDD_MEMORY_OUT; + } + } + +#ifdef DD_STATS + table_mem += table->num_bins * sizeof(st_table_entry *); +#endif + if (Cudd_Regular(node)->ref == 1) FREE(values); + st_foreach(table, cuddStCountfree, NULL); + st_free_table(table); +#ifdef DD_STATS + (void) fprintf(dd->out,"Number of calls: %d\tTable memory: %d bytes\n", + num_calls, table_mem); + (void) fprintf(dd->out,"Time to compute measures: %s\n", + util_print_time(util_cpu_time() - startTime)); +#endif + if (result == NULL) { + (void) fprintf(dd->out, + "out-of-memory, couldn't measure DD cofactors.\n"); + dd->errorCode = CUDD_MEMORY_OUT; + } + return(result); + +} /* end of Cudd_CofMinterm */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Recursive Step for Cudd_CofMinterm function.] + + Description [Traverses the DD node and computes the fraction of + minterms in the on-set of all positive cofactors simultaneously. + It allocates an array with two more entries than there are + variables below the one labeling the node. One extra entry (the + first in the array) is for the variable labeling the node. The other + entry (the last one in the array) holds the fraction of minterms of + the function rooted at node. Each other entry holds the value for + one cofactor. The array is put in a symbol table, to avoid repeated + computation, and its address is returned by the procedure, for use + by the caller. Returns a pointer to the array of cofactor measures.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static double * +ddCofMintermAux( + DdManager * dd, + DdNode * node, + st_table * table) +{ + DdNode *N; /* regular version of node */ + DdNode *Nv, *Nnv; + double *values; + double *valuesT, *valuesE; + int i; + int localSize, localSizeT, localSizeE; + double vT, vE; + + statLine(dd); +#ifdef DD_STATS + num_calls++; +#endif + + if (st_lookup(table, (char *) node, (char **) &values)) { + return(values); + } + + N = Cudd_Regular(node); + if (cuddIsConstant(N)) { + localSize = 1; + } else { + localSize = size - cuddI(dd,N->index) + 1; + } + values = ALLOC(double, localSize); + if (values == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + if (cuddIsConstant(N)) { + if (node == DD_ZERO(dd) || node == Cudd_Not(DD_ONE(dd))) { + values[0] = 0.0; + } else { + values[0] = 1.0; + } + } else { + Nv = Cudd_NotCond(cuddT(N),N!=node); + Nnv = Cudd_NotCond(cuddE(N),N!=node); + + valuesT = ddCofMintermAux(dd, Nv, table); + if (valuesT == NULL) return(NULL); + valuesE = ddCofMintermAux(dd, Nnv, table); + if (valuesE == NULL) return(NULL); + + if (Cudd_IsConstant(Nv)) { + localSizeT = 1; + } else { + localSizeT = size - cuddI(dd,Cudd_Regular(Nv)->index) + 1; + } + if (Cudd_IsConstant(Nnv)) { + localSizeE = 1; + } else { + localSizeE = size - cuddI(dd,Cudd_Regular(Nnv)->index) + 1; + } + values[0] = valuesT[localSizeT - 1]; + for (i = 1; i < localSize; i++) { + if (i >= cuddI(dd,Cudd_Regular(Nv)->index) - cuddI(dd,N->index)) { + vT = valuesT[i - cuddI(dd,Cudd_Regular(Nv)->index) + + cuddI(dd,N->index)]; + } else { + vT = valuesT[localSizeT - 1]; + } + if (i >= cuddI(dd,Cudd_Regular(Nnv)->index) - cuddI(dd,N->index)) { + vE = valuesE[i - cuddI(dd,Cudd_Regular(Nnv)->index) + + cuddI(dd,N->index)]; + } else { + vE = valuesE[localSizeE - 1]; + } + values[i] = (vT + vE) / 2.0; + } + if (Cudd_Regular(Nv)->ref == 1) FREE(valuesT); + if (Cudd_Regular(Nnv)->ref == 1) FREE(valuesE); + } + + if (N->ref > 1) { + if (st_add_direct(table, (char *) node, (char *) values) == ST_OUT_OF_MEM) { + FREE(values); + return(NULL); + } +#ifdef DD_STATS + table_mem += localSize * sizeof(double) + sizeof(st_table_entry); +#endif + } + return(values); + +} /* end of ddCofMintermAux */ + diff --git a/abc70930/src/bdd/cudd/cuddSolve.c b/abc70930/src/bdd/cudd/cuddSolve.c new file mode 100644 index 00000000..d9c4a2e7 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddSolve.c @@ -0,0 +1,339 @@ +/**CFile*********************************************************************** + + FileName [cuddSolve.c] + + PackageName [cudd] + + Synopsis [Boolean equation solver and related functions.] + + Description [External functions included in this modoule: +
        +
      • Cudd_SolveEqn() +
      • Cudd_VerifySol() +
      + Internal functions included in this module: +
        +
      • cuddSolveEqnRecur() +
      • cuddVerifySol() +
      ] + + SeeAlso [] + + Author [Balakrishna Kumthekar] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Structure declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddSolve.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements the solution of F(x,y) = 0.] + + Description [Implements the solution for F(x,y) = 0. The return + value is the consistency condition. The y variables are the unknowns + and the remaining variables are the parameters. Returns the + consistency condition if successful; NULL otherwise. Cudd_SolveEqn + allocates an array and fills it with the indices of the + unknowns. This array is used by Cudd_VerifySol.] + + SideEffects [The solution is returned in G; the indices of the y + variables are returned in yIndex.] + + SeeAlso [Cudd_VerifySol] + +******************************************************************************/ +DdNode * +Cudd_SolveEqn( + DdManager * bdd, + DdNode * F /* the left-hand side of the equation */, + DdNode * Y /* the cube of the y variables */, + DdNode ** G /* the array of solutions (return parameter) */, + int ** yIndex /* index of y variables */, + int n /* numbers of unknowns */) +{ + DdNode *res; + int *temp; + + *yIndex = temp = ALLOC(int, n); + if (temp == NULL) { + bdd->errorCode = CUDD_MEMORY_OUT; + (void) fprintf(bdd->out, + "Cudd_SolveEqn: Out of memory for yIndex\n"); + return(NULL); + } + + do { + bdd->reordered = 0; + res = cuddSolveEqnRecur(bdd, F, Y, G, n, temp, 0); + } while (bdd->reordered == 1); + + return(res); + +} /* end of Cudd_SolveEqn */ + + +/**Function******************************************************************** + + Synopsis [Checks the solution of F(x,y) = 0.] + + Description [Checks the solution of F(x,y) = 0. This procedure + substitutes the solution components for the unknowns of F and returns + the resulting BDD for F.] + + SideEffects [Frees the memory pointed by yIndex.] + + SeeAlso [Cudd_SolveEqn] + +******************************************************************************/ +DdNode * +Cudd_VerifySol( + DdManager * bdd, + DdNode * F /* the left-hand side of the equation */, + DdNode ** G /* the array of solutions */, + int * yIndex /* index of y variables */, + int n /* numbers of unknowns */) +{ + DdNode *res; + + do { + bdd->reordered = 0; + res = cuddVerifySol(bdd, F, G, yIndex, n); + } while (bdd->reordered == 1); + + FREE(yIndex); + + return(res); + +} /* end of Cudd_VerifySol */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_SolveEqn.] + + Description [Implements the recursive step of Cudd_SolveEqn. + Returns NULL if the intermediate solution blows up + or reordering occurs. The parametric solutions are + stored in the array G.] + + SideEffects [none] + + SeeAlso [Cudd_SolveEqn, Cudd_VerifySol] + +******************************************************************************/ +DdNode * +cuddSolveEqnRecur( + DdManager * bdd, + DdNode * F /* the left-hand side of the equation */, + DdNode * Y /* the cube of remaining y variables */, + DdNode ** G /* the array of solutions */, + int n /* number of unknowns */, + int * yIndex /* array holding the y variable indices */, + int i /* level of recursion */) +{ + DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one; + DdNodePtr *variables; + + int j; + + statLine(bdd); + variables = bdd->vars; + one = DD_ONE(bdd); + + /* Base condition. */ + if (Y == one) { + return F; + } + + /* Cofactor of Y. */ + yIndex[i] = Y->index; + nextY = Cudd_T(Y); + + /* Universal abstraction of F with respect to the top variable index. */ + Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]); + if (Fm1) { + Fm1 = Cudd_Not(Fm1); + cuddRef(Fm1); + } else { + return(NULL); + } + + Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1); + if (Fn) { + cuddRef(Fn); + } else { + Cudd_RecursiveDeref(bdd, Fm1); + return(NULL); + } + + Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]); + if (Fv) { + cuddRef(Fv); + } else { + Cudd_RecursiveDeref(bdd, Fm1); + Cudd_RecursiveDeref(bdd, Fn); + return(NULL); + } + + Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]])); + if (Fvbar) { + cuddRef(Fvbar); + } else { + Cudd_RecursiveDeref(bdd, Fm1); + Cudd_RecursiveDeref(bdd, Fn); + Cudd_RecursiveDeref(bdd, Fv); + return(NULL); + } + + /* Build i-th component of the solution. */ + w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar); + if (w) { + cuddRef(w); + } else { + Cudd_RecursiveDeref(bdd, Fm1); + Cudd_RecursiveDeref(bdd, Fn); + Cudd_RecursiveDeref(bdd, Fv); + Cudd_RecursiveDeref(bdd, Fvbar); + return(NULL); + } + + T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1)); + if(T) { + cuddRef(T); + } else { + Cudd_RecursiveDeref(bdd, Fm1); + Cudd_RecursiveDeref(bdd, Fn); + Cudd_RecursiveDeref(bdd, Fv); + Cudd_RecursiveDeref(bdd, Fvbar); + Cudd_RecursiveDeref(bdd, w); + return(NULL); + } + + Cudd_RecursiveDeref(bdd,Fm1); + Cudd_RecursiveDeref(bdd,w); + Cudd_RecursiveDeref(bdd,Fv); + Cudd_RecursiveDeref(bdd,Fvbar); + + /* Substitute components of solution already found into solution. */ + for (j = n-1; j > i; j--) { + w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]); + if(w) { + cuddRef(w); + } else { + Cudd_RecursiveDeref(bdd, Fn); + Cudd_RecursiveDeref(bdd, T); + return(NULL); + } + Cudd_RecursiveDeref(bdd,T); + T = w; + } + G[i] = T; + + Cudd_Deref(Fn); + + return(Fn); + +} /* end of cuddSolveEqnRecur */ + + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_VerifySol. ] + + Description [] + + SideEffects [none] + + SeeAlso [Cudd_VerifySol] + +******************************************************************************/ +DdNode * +cuddVerifySol( + DdManager * bdd, + DdNode * F /* the left-hand side of the equation */, + DdNode ** G /* the array of solutions */, + int * yIndex /* array holding the y variable indices */, + int n /* number of unknowns */) +{ + DdNode *w, *R; + + int j; + + R = F; + cuddRef(R); + for(j = n - 1; j >= 0; j--) { + w = Cudd_bddCompose(bdd, R, G[j], yIndex[j]); + if (w) { + cuddRef(w); + } else { + return(NULL); + } + Cudd_RecursiveDeref(bdd,R); + R = w; + } + + cuddDeref(R); + + return(R); + +} /* end of cuddVerifySol */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/cudd/cuddSplit.c b/abc70930/src/bdd/cudd/cuddSplit.c new file mode 100644 index 00000000..e21ea7cb --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddSplit.c @@ -0,0 +1,657 @@ +/**CFile*********************************************************************** + + FileName [cuddSplit.c] + + PackageName [cudd] + + Synopsis [Returns a subset of minterms from a boolean function.] + + Description [External functions included in this modoule: +
        +
      • Cudd_SplitSet() +
      + Internal functions included in this module: +
        +
      • cuddSplitSetRecur() + + Static functions included in this module: +
          +
        • selectMintermsFromUniverse() +
        • mintermsFromUniverse() +
        • bddAnnotateMintermCount() +
        ] + + SeeAlso [] + + Author [Balakrishna Kumthekar] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Structure declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * selectMintermsFromUniverse ARGS((DdManager *manager, int *varSeen, double n)); +static DdNode * mintermsFromUniverse ARGS((DdManager *manager, DdNode **vars, int numVars, double n, int index)); +static double bddAnnotateMintermCount ARGS((DdManager *manager, DdNode *node, double max, st_table *table)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Returns m minterms from a BDD.] + + Description [Returns m minterms from a BDD whose + support has n variables at most. The procedure tries + to create as few extra nodes as possible. The function represented + by S depends on at most n of the variables + in xVars. Returns a BDD with m minterms + of the on-set of S if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_SplitSet( + DdManager * manager, + DdNode * S, + DdNode ** xVars, + int n, + double m) +{ + DdNode *result; + DdNode *zero, *one; + double max, num; + st_table *mtable; + int *varSeen; + int i,index, size; + + size = manager->size; + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Trivial cases. */ + if (m == 0.0) { + return(zero); + } + if (S == zero) { + return(NULL); + } + + max = pow(2.0,(double)n); + if (m > max) + return(NULL); + + do { + manager->reordered = 0; + /* varSeen is used to mark the variables that are encountered + ** while traversing the BDD S. + */ + varSeen = ALLOC(int, size); + if (varSeen == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < size; i++) { + varSeen[i] = -1; + } + for (i = 0; i < n; i++) { + index = (xVars[i])->index; + varSeen[manager->invperm[index]] = 0; + } + + if (S == one) { + if (m == max) + return(S); + result = selectMintermsFromUniverse(manager,varSeen,m); + if (result) + cuddRef(result); + FREE(varSeen); + } else { + mtable = st_init_table(st_ptrcmp,st_ptrhash); + if (mtable == NULL) { + (void) fprintf(manager->out, + "Cudd_SplitSet: out-of-memory.\n"); + FREE(varSeen); + manager->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + /* The nodes of BDD S are annotated by the number of minterms + ** in their onset. The node and the number of minterms in its + ** onset are stored in mtable. + */ + num = bddAnnotateMintermCount(manager,S,max,mtable); + if (m == num) { + st_foreach(mtable,cuddStCountfree,NIL(char)); + st_free_table(mtable); + FREE(varSeen); + return(S); + } + + result = cuddSplitSetRecur(manager,mtable,varSeen,S,m,max,0); + if (result) + cuddRef(result); + st_foreach(mtable,cuddStCountfree,NULL); + st_free_table(mtable); + FREE(varSeen); + } + } while (manager->reordered == 1); + + cuddDeref(result); + return(result); + +} /* end of Cudd_SplitSet */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_SplitSet.] + + Description [Implements the recursive step of Cudd_SplitSet. The + procedure recursively traverses the BDD and checks to see if any + node satisfies the minterm requirements as specified by 'n'. At any + node X, n is compared to the number of minterms in the onset of X's + children. If either of the child nodes have exactly n minterms, then + that node is returned; else, if n is greater than the onset of one + of the child nodes, that node is retained and the difference in the + number of minterms is extracted from the other child. In case n + minterms can be extracted from constant 1, the algorithm returns the + result with at most log(n) nodes.] + + SideEffects [The array 'varSeen' is updated at every recursive call + to set the variables traversed by the procedure.] + + SeeAlso [] + +******************************************************************************/ +DdNode* +cuddSplitSetRecur( + DdManager * manager, + st_table * mtable, + int * varSeen, + DdNode * p, + double n, + double max, + int index) +{ + DdNode *one, *zero, *N, *Nv; + DdNode *Nnv, *q, *r, *v; + DdNode *result; + double *dummy, numT, numE; + int variable, positive; + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* If p is constant, extract n minterms from constant 1. The procedure by + ** construction guarantees that minterms will not be extracted from + ** constant 0. + */ + if (Cudd_IsConstant(p)) { + q = selectMintermsFromUniverse(manager,varSeen,n); + return(q); + } + + N = Cudd_Regular(p); + + /* Set variable as seen. */ + variable = N->index; + varSeen[manager->invperm[variable]] = -1; + + Nv = cuddT(N); + Nnv = cuddE(N); + if (Cudd_IsComplement(p)) { + Nv = Cudd_Not(Nv); + Nnv = Cudd_Not(Nnv); + } + + /* If both the children of 'p' are constants, extract n minterms from a + ** constant node. + */ + if (Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) { + q = selectMintermsFromUniverse(manager,varSeen,n); + if (q == NULL) { + return(NULL); + } + cuddRef(q); + r = cuddBddAndRecur(manager,p,q); + if (r == NULL) { + Cudd_RecursiveDeref(manager,q); + return(NULL); + } + cuddRef(r); + Cudd_RecursiveDeref(manager,q); + cuddDeref(r); + return(r); + } + + /* Lookup the # of minterms in the onset of the node from the table. */ + if (!Cudd_IsConstant(Nv)) { + st_lookup(mtable,(char *)Nv, (char **)&dummy); + numT = *dummy/(2*(1<size; + one = DD_ONE(manager); + zero = Cudd_Not(one); + + /* Count the number of variables not encountered so far in procedure + ** cuddSplitSetRecur. + */ + for (i = size-1; i >= 0; i--) { + if(varSeen[i] == 0) + numVars++; + } + vars = ALLOC(DdNode *, numVars); + if (!vars) { + manager->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + j = 0; + for (i = size-1; i >= 0; i--) { + if(varSeen[i] == 0) { + vars[j] = cuddUniqueInter(manager,manager->perm[i],one,zero); + cuddRef(vars[j]); + j++; + } + } + + /* Compute a function which has n minterms and depends on at most + ** numVars variables. + */ + result = mintermsFromUniverse(manager,vars,numVars,n, 0); + if (result) + cuddRef(result); + + for (i = 0; i < numVars; i++) + Cudd_RecursiveDeref(manager,vars[i]); + FREE(vars); + + return(result); + +} /* end of selectMintermsFromUniverse */ + + +/**Function******************************************************************** + + Synopsis [Recursive procedure to extract n mintems from constant 1.] + + Description [Recursive procedure to extract n mintems from constant 1.] + + SideEffects [None] + +******************************************************************************/ +static DdNode * +mintermsFromUniverse( + DdManager * manager, + DdNode ** vars, + int numVars, + double n, + int index) +{ + DdNode *one, *zero; + DdNode *q, *result; + double max, max2; + + statLine(manager); + one = DD_ONE(manager); + zero = Cudd_Not(one); + + max = pow(2.0, (double)numVars); + max2 = max / 2.0; + + if (n == max) + return(one); + if (n == 0.0) + return(zero); + /* if n == 2^(numVars-1), return a single variable */ + if (n == max2) + return vars[index]; + else if (n > max2) { + /* When n > 2^(numVars-1), a single variable vars[index] + ** contains 2^(numVars-1) minterms. The rest are extracted + ** from a constant with 1 less variable. + */ + q = mintermsFromUniverse(manager,vars,numVars-1,(n-max2),index+1); + if (q == NULL) + return(NULL); + cuddRef(q); + result = cuddBddIteRecur(manager,vars[index],one,q); + } else { + /* When n < 2^(numVars-1), a literal of variable vars[index] + ** is selected. The required n minterms are extracted from a + ** constant with 1 less variable. + */ + q = mintermsFromUniverse(manager,vars,numVars-1,n,index+1); + if (q == NULL) + return(NULL); + cuddRef(q); + result = cuddBddAndRecur(manager,vars[index],q); + } + + if (result == NULL) { + Cudd_RecursiveDeref(manager,q); + return(NULL); + } + cuddRef(result); + Cudd_RecursiveDeref(manager,q); + cuddDeref(result); + return(result); + +} /* end of mintermsFromUniverse */ + + +/**Function******************************************************************** + + Synopsis [Annotates every node in the BDD node with its minterm count.] + + Description [Annotates every node in the BDD node with its minterm count. + In this function, every node and the minterm count represented by it are + stored in a hash table.] + + SideEffects [Fills up 'table' with the pair .] + +******************************************************************************/ +static double +bddAnnotateMintermCount( + DdManager * manager, + DdNode * node, + double max, + st_table * table) +{ + + DdNode *N,*Nv,*Nnv; + register double min_v,min_nv; + register double min_N; + double *pmin; + double *dummy; + + statLine(manager); + N = Cudd_Regular(node); + if (cuddIsConstant(N)) { + if (node == DD_ONE(manager)) { + return(max); + } else { + return(0.0); + } + } + + if (st_lookup(table,(char *)node,(char **)&dummy)) { + return(*dummy); + } + + Nv = cuddT(N); + Nnv = cuddE(N); + if (N != node) { + Nv = Cudd_Not(Nv); + Nnv = Cudd_Not(Nnv); + } + + /* Recur on the two branches. */ + min_v = bddAnnotateMintermCount(manager,Nv,max,table) / 2.0; + if (min_v == (double)CUDD_OUT_OF_MEM) + return ((double)CUDD_OUT_OF_MEM); + min_nv = bddAnnotateMintermCount(manager,Nnv,max,table) / 2.0; + if (min_nv == (double)CUDD_OUT_OF_MEM) + return ((double)CUDD_OUT_OF_MEM); + min_N = min_v + min_nv; + + pmin = ALLOC(double,1); + if (pmin == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + return((double)CUDD_OUT_OF_MEM); + } + *pmin = min_N; + + if (st_insert(table,(char *)node, (char *)pmin) == ST_OUT_OF_MEM) { + FREE(pmin); + return((double)CUDD_OUT_OF_MEM); + } + + return(min_N); + +} /* end of bddAnnotateMintermCount */ diff --git a/abc70930/src/bdd/cudd/cuddSubsetHB.c b/abc70930/src/bdd/cudd/cuddSubsetHB.c new file mode 100644 index 00000000..24d41ce5 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddSubsetHB.c @@ -0,0 +1,1311 @@ +/**CFile*********************************************************************** + + FileName [cuddSubsetHB.c] + + PackageName [cudd] + + Synopsis [Procedure to subset the given BDD by choosing the heavier + branches] + + + Description [External procedures provided by this module: +
          +
        • Cudd_SubsetHeavyBranch() +
        • Cudd_SupersetHeavyBranch() +
        + Internal procedures included in this module: +
          +
        • cuddSubsetHeavyBranch() +
        + Static procedures included in this module: +
          +
        • ResizeCountMintermPages(); +
        • ResizeNodeDataPages() +
        • ResizeCountNodePages() +
        • SubsetCountMintermAux() +
        • SubsetCountMinterm() +
        • SubsetCountNodesAux() +
        • SubsetCountNodes() +
        • BuildSubsetBdd() +
        + ] + + SeeAlso [cuddSubsetSP.c] + + Author [Kavita Ravi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no + warranty about the suitability of this software for any + purpose. It is presented on an AS IS basis.] + +******************************************************************************/ + +#ifdef __STDC__ +#include +#else +#define DBL_MAX_EXP 1024 +#endif +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define DEFAULT_PAGE_SIZE 2048 +#define DEFAULT_NODE_DATA_PAGE_SIZE 1024 +#define INITIAL_PAGES 128 + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/* data structure to store the information on each node. It keeps + * the number of minterms represented by the DAG rooted at this node + * in terms of the number of variables specified by the user, number + * of nodes in this DAG and the number of nodes of its child with + * lesser number of minterms that are not shared by the child with + * more minterms + */ +struct NodeData { + double *mintermPointer; + int *nodesPointer; + int *lightChildNodesPointer; +}; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +typedef struct NodeData NodeData_t; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +static int memOut; +#ifdef DEBUG +static int num_calls; +#endif + +static DdNode *zero, *one; /* constant functions */ +static double **mintermPages; /* pointers to the pages */ +static int **nodePages; /* pointers to the pages */ +static int **lightNodePages; /* pointers to the pages */ +static double *currentMintermPage; /* pointer to the current + page */ +static double max; /* to store the 2^n value of the number + * of variables */ + +static int *currentNodePage; /* pointer to the current + page */ +static int *currentLightNodePage; /* pointer to the + * current page */ +static int pageIndex; /* index to next element */ +static int page; /* index to current page */ +static int pageSize = DEFAULT_PAGE_SIZE; /* page size */ +static int maxPages; /* number of page pointers */ + +static NodeData_t *currentNodeDataPage; /* pointer to the current + page */ +static int nodeDataPage; /* index to next element */ +static int nodeDataPageIndex; /* index to next element */ +static NodeData_t **nodeDataPages; /* index to current page */ +static int nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE; + /* page size */ +static int maxNodeDataPages; /* number of page pointers */ + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void ResizeNodeDataPages ARGS(()); +static void ResizeCountMintermPages ARGS(()); +static void ResizeCountNodePages ARGS(()); +static double SubsetCountMintermAux ARGS((DdNode *node, double max, st_table *table)); +static st_table * SubsetCountMinterm ARGS((DdNode *node, int nvars)); +static int SubsetCountNodesAux ARGS((DdNode *node, st_table *table, double max)); +static int SubsetCountNodes ARGS((DdNode *node, st_table *table, int nvars)); +static void StoreNodes ARGS((st_table *storeTable, DdManager *dd, DdNode *node)); +static DdNode * BuildSubsetBdd ARGS((DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Extracts a dense subset from a BDD with the heavy branch + heuristic.] + + Description [Extracts a dense subset from a BDD. This procedure + builds a subset by throwing away one of the children of each node, + starting from the root, until the result is small enough. The child + that is eliminated from the result is the one that contributes the + fewer minterms. Returns a pointer to the BDD of the subset if + successful. NULL if the procedure runs out of memory. The parameter + numVars is the maximum number of variables to be used in minterm + calculation and node count calculation. The optimal number should + be as close as possible to the size of the support of f. However, + it is safe to pass the value returned by Cudd_ReadSize for numVars + when the number of variables is under 1023. If numVars is larger + than 1023, it will overflow. If a 0 parameter is passed then the + procedure will compute a value which will avoid overflow but will + cause underflow with 2046 variables or more.] + + SideEffects [None] + + SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize] + +******************************************************************************/ +DdNode * +Cudd_SubsetHeavyBranch( + DdManager * dd /* manager */, + DdNode * f /* function to be subset */, + int numVars /* number of variables in the support of f */, + int threshold /* maximum number of nodes in the subset */) +{ + DdNode *subset; + + memOut = 0; + do { + dd->reordered = 0; + subset = cuddSubsetHeavyBranch(dd, f, numVars, threshold); + } while ((dd->reordered == 1) && (!memOut)); + + return(subset); + +} /* end of Cudd_SubsetHeavyBranch */ + + +/**Function******************************************************************** + + Synopsis [Extracts a dense superset from a BDD with the heavy branch + heuristic.] + + Description [Extracts a dense superset from a BDD. The procedure is + identical to the subset procedure except for the fact that it + receives the complement of the given function. Extracting the subset + of the complement function is equivalent to extracting the superset + of the function. This procedure builds a superset by throwing away + one of the children of each node starting from the root of the + complement function, until the result is small enough. The child + that is eliminated from the result is the one that contributes the + fewer minterms. + Returns a pointer to the BDD of the superset if successful. NULL if + intermediate result causes the procedure to run out of memory. The + parameter numVars is the maximum number of variables to be used in + minterm calculation and node count calculation. The optimal number + should be as close as possible to the size of the support of f. + However, it is safe to pass the value returned by Cudd_ReadSize for + numVars when the number of variables is under 1023. If numVars is + larger than 1023, it will overflow. If a 0 parameter is passed then + the procedure will compute a value which will avoid overflow but + will cause underflow with 2046 variables or more.] + + SideEffects [None] + + SeeAlso [Cudd_SubsetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] + +******************************************************************************/ +DdNode * +Cudd_SupersetHeavyBranch( + DdManager * dd /* manager */, + DdNode * f /* function to be superset */, + int numVars /* number of variables in the support of f */, + int threshold /* maximum number of nodes in the superset */) +{ + DdNode *subset, *g; + + g = Cudd_Not(f); + memOut = 0; + do { + dd->reordered = 0; + subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold); + } while ((dd->reordered == 1) && (!memOut)); + + return(Cudd_NotCond(subset, (subset != NULL))); + +} /* end of Cudd_SupersetHeavyBranch */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [The main procedure that returns a subset by choosing the heavier + branch in the BDD.] + + Description [Here a subset BDD is built by throwing away one of the + children. Starting at root, annotate each node with the number of + minterms (in terms of the total number of variables specified - + numVars), number of nodes taken by the DAG rooted at this node and + number of additional nodes taken by the child that has the lesser + minterms. The child with the lower number of minterms is thrown away + and a dyanmic count of the nodes of the subset is kept. Once the + threshold is reached the subset is returned to the calling + procedure.] + + SideEffects [None] + + SeeAlso [Cudd_SubsetHeavyBranch] + +******************************************************************************/ +DdNode * +cuddSubsetHeavyBranch( + DdManager * dd /* DD manager */, + DdNode * f /* current DD */, + int numVars /* maximum number of variables */, + int threshold /* threshold size for the subset */) +{ + + int i, *size; + st_table *visitedTable; + int numNodes; + NodeData_t *currNodeQual; + DdNode *subset; + double minN; + st_table *storeTable, *approxTable; + char *key, *value; + st_generator *stGen; + + if (f == NULL) { + fprintf(dd->err, "Cannot subset, nil object\n"); + dd->errorCode = CUDD_INVALID_ARG; + return(NULL); + } + + one = Cudd_ReadOne(dd); + zero = Cudd_Not(one); + + /* If user does not know numVars value, set it to the maximum + * exponent that the pow function can take. The -1 is due to the + * discrepancy in the value that pow takes and the value that + * log gives. + */ + if (numVars == 0) { + /* set default value */ + numVars = DBL_MAX_EXP - 1; + } + + if (Cudd_IsConstant(f)) { + return(f); + } + + max = pow(2.0, (double)numVars); + + /* Create visited table where structures for node data are allocated and + stored in a st_table */ + visitedTable = SubsetCountMinterm(f, numVars); + if ((visitedTable == NULL) || memOut) { + (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + numNodes = SubsetCountNodes(f, visitedTable, numVars); + if (memOut) { + (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + + if (st_lookup(visitedTable, (char *)f, (char **)&currNodeQual)) { + minN = *(((NodeData_t *)currNodeQual)->mintermPointer); + } else { + fprintf(dd->err, + "Something is wrong, ought to be node quality table\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + } + + size = ALLOC(int, 1); + if (size == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + *size = numNodes; + +#ifdef DEBUG + num_calls = 0; +#endif + /* table to store nodes being created. */ + storeTable = st_init_table(st_ptrcmp, st_ptrhash); + /* insert the constant */ + cuddRef(one); + if (st_insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) == + ST_OUT_OF_MEM) { + fprintf(dd->out, "Something wrong, st_table insert failed\n"); + } + /* table to store approximations of nodes */ + approxTable = st_init_table(st_ptrcmp, st_ptrhash); + subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold, + storeTable, approxTable); + if (subset != NULL) { + cuddRef(subset); + } + + stGen = st_init_gen(approxTable); + if (stGen == NULL) { + st_free_table(approxTable); + return(NULL); + } + while(st_gen(stGen, (char **)&key, (char **)&value)) { + Cudd_RecursiveDeref(dd, (DdNode *)value); + } + st_free_gen(stGen); stGen = NULL; + st_free_table(approxTable); + + stGen = st_init_gen(storeTable); + if (stGen == NULL) { + st_free_table(storeTable); + return(NULL); + } + while(st_gen(stGen, (char **)&key, (char **)&value)) { + Cudd_RecursiveDeref(dd, (DdNode *)key); + } + st_free_gen(stGen); stGen = NULL; + st_free_table(storeTable); + + for (i = 0; i <= page; i++) { + FREE(mintermPages[i]); + } + FREE(mintermPages); + for (i = 0; i <= page; i++) { + FREE(nodePages[i]); + } + FREE(nodePages); + for (i = 0; i <= page; i++) { + FREE(lightNodePages[i]); + } + FREE(lightNodePages); + for (i = 0; i <= nodeDataPage; i++) { + FREE(nodeDataPages[i]); + } + FREE(nodeDataPages); + st_free_table(visitedTable); + FREE(size); +#if 0 + (void) Cudd_DebugCheck(dd); + (void) Cudd_CheckKeys(dd); +#endif + + if (subset != NULL) { +#ifdef DD_DEBUG + if (!Cudd_bddLeq(dd, subset, f)) { + fprintf(dd->err, "Wrong subset\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } +#endif + cuddDeref(subset); + return(subset); + } else { + return(NULL); + } +} /* end of cuddSubsetHeavyBranch */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Resize the number of pages allocated to store the node data.] + + Description [Resize the number of pages allocated to store the node data + The procedure moves the counter to the next page when the end of + the page is reached and allocates new pages when necessary.] + + SideEffects [Changes the size of pages, page, page index, maximum + number of pages freeing stuff in case of memory out. ] + + SeeAlso [] + +******************************************************************************/ +static void +ResizeNodeDataPages( + ) +{ + int i; + NodeData_t **newNodeDataPages; + + nodeDataPage++; + /* If the current page index is larger than the number of pages + * allocated, allocate a new page array. Page numbers are incremented by + * INITIAL_PAGES + */ + if (nodeDataPage == maxNodeDataPages) { + newNodeDataPages = ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES); + if (newNodeDataPages == NULL) { + for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + memOut = 1; + return; + } else { + for (i = 0; i < maxNodeDataPages; i++) { + newNodeDataPages[i] = nodeDataPages[i]; + } + /* Increase total page count */ + maxNodeDataPages += INITIAL_PAGES; + FREE(nodeDataPages); + nodeDataPages = newNodeDataPages; + } + } + /* Allocate a new page */ + currentNodeDataPage = nodeDataPages[nodeDataPage] = + ALLOC(NodeData_t ,nodeDataPageSize); + if (currentNodeDataPage == NULL) { + for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + memOut = 1; + return; + } + /* reset page index */ + nodeDataPageIndex = 0; + return; + +} /* end of ResizeNodeDataPages */ + + +/**Function******************************************************************** + + Synopsis [Resize the number of pages allocated to store the minterm + counts. ] + + Description [Resize the number of pages allocated to store the minterm + counts. The procedure moves the counter to the next page when the + end of the page is reached and allocates new pages when necessary.] + + SideEffects [Changes the size of minterm pages, page, page index, maximum + number of pages freeing stuff in case of memory out. ] + + SeeAlso [] + +******************************************************************************/ +static void +ResizeCountMintermPages( + ) +{ + int i; + double **newMintermPages; + + page++; + /* If the current page index is larger than the number of pages + * allocated, allocate a new page array. Page numbers are incremented by + * INITIAL_PAGES + */ + if (page == maxPages) { + newMintermPages = ALLOC(double *,maxPages + INITIAL_PAGES); + if (newMintermPages == NULL) { + for (i = 0; i < page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + memOut = 1; + return; + } else { + for (i = 0; i < maxPages; i++) { + newMintermPages[i] = mintermPages[i]; + } + /* Increase total page count */ + maxPages += INITIAL_PAGES; + FREE(mintermPages); + mintermPages = newMintermPages; + } + } + /* Allocate a new page */ + currentMintermPage = mintermPages[page] = ALLOC(double,pageSize); + if (currentMintermPage == NULL) { + for (i = 0; i < page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + memOut = 1; + return; + } + /* reset page index */ + pageIndex = 0; + return; + +} /* end of ResizeCountMintermPages */ + + +/**Function******************************************************************** + + Synopsis [Resize the number of pages allocated to store the node counts.] + + Description [Resize the number of pages allocated to store the node counts. + The procedure moves the counter to the next page when the end of + the page is reached and allocates new pages when necessary.] + + SideEffects [Changes the size of pages, page, page index, maximum + number of pages freeing stuff in case of memory out.] + + SeeAlso [] + +******************************************************************************/ +static void +ResizeCountNodePages( + ) +{ + int i; + int **newNodePages; + + page++; + + /* If the current page index is larger than the number of pages + * allocated, allocate a new page array. The number of pages is incremented + * by INITIAL_PAGES. + */ + if (page == maxPages) { + newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES); + if (newNodePages == NULL) { + for (i = 0; i < page; i++) FREE(nodePages[i]); + FREE(nodePages); + for (i = 0; i < page; i++) FREE(lightNodePages[i]); + FREE(lightNodePages); + memOut = 1; + return; + } else { + for (i = 0; i < maxPages; i++) { + newNodePages[i] = nodePages[i]; + } + FREE(nodePages); + nodePages = newNodePages; + } + + newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES); + if (newNodePages == NULL) { + for (i = 0; i < page; i++) FREE(nodePages[i]); + FREE(nodePages); + for (i = 0; i < page; i++) FREE(lightNodePages[i]); + FREE(lightNodePages); + memOut = 1; + return; + } else { + for (i = 0; i < maxPages; i++) { + newNodePages[i] = lightNodePages[i]; + } + FREE(lightNodePages); + lightNodePages = newNodePages; + } + /* Increase total page count */ + maxPages += INITIAL_PAGES; + } + /* Allocate a new page */ + currentNodePage = nodePages[page] = ALLOC(int,pageSize); + if (currentNodePage == NULL) { + for (i = 0; i < page; i++) FREE(nodePages[i]); + FREE(nodePages); + for (i = 0; i < page; i++) FREE(lightNodePages[i]); + FREE(lightNodePages); + memOut = 1; + return; + } + /* Allocate a new page */ + currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); + if (currentLightNodePage == NULL) { + for (i = 0; i <= page; i++) FREE(nodePages[i]); + FREE(nodePages); + for (i = 0; i < page; i++) FREE(lightNodePages[i]); + FREE(lightNodePages); + memOut = 1; + return; + } + /* reset page index */ + pageIndex = 0; + return; + +} /* end of ResizeCountNodePages */ + + +/**Function******************************************************************** + + Synopsis [Recursively counts minterms of each node in the DAG.] + + Description [Recursively counts minterms of each node in the DAG. + Similar to the cuddCountMintermAux which recursively counts the + number of minterms for the dag rooted at each node in terms of the + total number of variables (max). This procedure creates the node + data structure and stores the minterm count as part of the node + data structure. ] + + SideEffects [Creates structures of type node quality and fills the st_table] + + SeeAlso [SubsetCountMinterm] + +******************************************************************************/ +static double +SubsetCountMintermAux( + DdNode * node /* function to analyze */, + double max /* number of minterms of constant 1 */, + st_table * table /* visitedTable table */) +{ + + DdNode *N,*Nv,*Nnv; /* nodes to store cofactors */ + double min,*pmin; /* minterm count */ + double min1, min2; /* minterm count */ + NodeData_t *dummy; + NodeData_t *newEntry; + int i; + +#ifdef DEBUG + num_calls++; +#endif + + /* Constant case */ + if (Cudd_IsConstant(node)) { + if (node == zero) { + return(0.0); + } else { + return(max); + } + } else { + + /* check if entry for this node exists */ + if (st_lookup(table,(char *)node, (char **)&dummy)) { + min = *(dummy->mintermPointer); + return(min); + } + + /* Make the node regular to extract cofactors */ + N = Cudd_Regular(node); + + /* store the cofactors */ + Nv = Cudd_T(N); + Nnv = Cudd_E(N); + + Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); + Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); + + min1 = SubsetCountMintermAux(Nv, max,table)/2.0; + if (memOut) return(0.0); + min2 = SubsetCountMintermAux(Nnv,max,table)/2.0; + if (memOut) return(0.0); + min = (min1+min2); + + /* if page index is at the bottom, then create a new page */ + if (pageIndex == pageSize) ResizeCountMintermPages(); + if (memOut) { + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + st_free_table(table); + return(0.0); + } + + /* point to the correct location in the page */ + pmin = currentMintermPage+pageIndex; + pageIndex++; + + /* store the minterm count of this node in the page */ + *pmin = min; + + /* Note I allocate the struct here. Freeing taken care of later */ + if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages(); + if (memOut) { + for (i = 0; i <= page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + st_free_table(table); + return(0.0); + } + + newEntry = currentNodeDataPage + nodeDataPageIndex; + nodeDataPageIndex++; + + /* points to the correct location in the page */ + newEntry->mintermPointer = pmin; + /* initialize this field of the Node Quality structure */ + newEntry->nodesPointer = NULL; + + /* insert entry for the node in the table */ + if (st_insert(table,(char *)node, (char *)newEntry) == ST_OUT_OF_MEM) { + memOut = 1; + for (i = 0; i <= page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + st_free_table(table); + return(0.0); + } + return(min); + } + +} /* end of SubsetCountMintermAux */ + + +/**Function******************************************************************** + + Synopsis [Counts minterms of each node in the DAG] + + Description [Counts minterms of each node in the DAG. Similar to the + Cudd_CountMinterm procedure except this returns the minterm count for + all the nodes in the bdd in an st_table.] + + SideEffects [none] + + SeeAlso [SubsetCountMintermAux] + +******************************************************************************/ +static st_table * +SubsetCountMinterm( + DdNode * node /* function to be analyzed */, + int nvars /* number of variables node depends on */) +{ + st_table *table; + double num; + int i; + + +#ifdef DEBUG + num_calls = 0; +#endif + + max = pow(2.0,(double) nvars); + table = st_init_table(st_ptrcmp,st_ptrhash); + if (table == NULL) goto OUT_OF_MEM; + maxPages = INITIAL_PAGES; + mintermPages = ALLOC(double *,maxPages); + if (mintermPages == NULL) { + st_free_table(table); + goto OUT_OF_MEM; + } + page = 0; + currentMintermPage = ALLOC(double,pageSize); + mintermPages[page] = currentMintermPage; + if (currentMintermPage == NULL) { + FREE(mintermPages); + st_free_table(table); + goto OUT_OF_MEM; + } + pageIndex = 0; + maxNodeDataPages = INITIAL_PAGES; + nodeDataPages = ALLOC(NodeData_t *, maxNodeDataPages); + if (nodeDataPages == NULL) { + for (i = 0; i <= page ; i++) FREE(mintermPages[i]); + FREE(mintermPages); + st_free_table(table); + goto OUT_OF_MEM; + } + nodeDataPage = 0; + currentNodeDataPage = ALLOC(NodeData_t ,nodeDataPageSize); + nodeDataPages[nodeDataPage] = currentNodeDataPage; + if (currentNodeDataPage == NULL) { + for (i = 0; i <= page ; i++) FREE(mintermPages[i]); + FREE(mintermPages); + FREE(nodeDataPages); + st_free_table(table); + goto OUT_OF_MEM; + } + nodeDataPageIndex = 0; + + num = SubsetCountMintermAux(node,max,table); + if (memOut) goto OUT_OF_MEM; + return(table); + +OUT_OF_MEM: + memOut = 1; + return(NULL); + +} /* end of SubsetCountMinterm */ + + +/**Function******************************************************************** + + Synopsis [Recursively counts the number of nodes under the dag. + Also counts the number of nodes under the lighter child of + this node.] + + Description [Recursively counts the number of nodes under the dag. + Also counts the number of nodes under the lighter child of + this node. . Note that the same dag may be the lighter child of two + different nodes and have different counts. As with the minterm counts, + the node counts are stored in pages to be space efficient and the + address for these node counts are stored in an st_table associated + to each node. ] + + SideEffects [Updates the node data table with node counts] + + SeeAlso [SubsetCountNodes] + +******************************************************************************/ +static int +SubsetCountNodesAux( + DdNode * node /* current node */, + st_table * table /* table to update node count, also serves as visited table. */, + double max /* maximum number of variables */) +{ + int tval, eval, i; + DdNode *N, *Nv, *Nnv; + double minNv, minNnv; + NodeData_t *dummyN, *dummyNv, *dummyNnv, *dummyNBar; + int *pmin, *pminBar, *val; + + if ((node == NULL) || Cudd_IsConstant(node)) + return(0); + + /* if this node has been processed do nothing */ + if (st_lookup(table, (char *)node, (char **)&dummyN) == 1) { + val = dummyN->nodesPointer; + if (val != NULL) + return(0); + } else { + return(0); + } + + N = Cudd_Regular(node); + Nv = Cudd_T(N); + Nnv = Cudd_E(N); + + Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); + Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); + + /* find the minterm counts for the THEN and ELSE branches */ + if (Cudd_IsConstant(Nv)) { + if (Nv == zero) { + minNv = 0.0; + } else { + minNv = max; + } + } else { + if (st_lookup(table, (char *)Nv, (char **)&dummyNv) == 1) + minNv = *(dummyNv->mintermPointer); + else { + return(0); + } + } + if (Cudd_IsConstant(Nnv)) { + if (Nnv == zero) { + minNnv = 0.0; + } else { + minNnv = max; + } + } else { + if (st_lookup(table, (char *)Nnv, (char **)&dummyNnv) == 1) { + minNnv = *(dummyNnv->mintermPointer); + } + else { + return(0); + } + } + + + /* recur based on which has larger minterm, */ + if (minNv >= minNnv) { + tval = SubsetCountNodesAux(Nv, table, max); + if (memOut) return(0); + eval = SubsetCountNodesAux(Nnv, table, max); + if (memOut) return(0); + + /* store the node count of the lighter child. */ + if (pageIndex == pageSize) ResizeCountNodePages(); + if (memOut) { + for (i = 0; i <= page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + st_free_table(table); + return(0); + } + pmin = currentLightNodePage + pageIndex; + *pmin = eval; /* Here the ELSE child is lighter */ + dummyN->lightChildNodesPointer = pmin; + + } else { + eval = SubsetCountNodesAux(Nnv, table, max); + if (memOut) return(0); + tval = SubsetCountNodesAux(Nv, table, max); + if (memOut) return(0); + + /* store the node count of the lighter child. */ + if (pageIndex == pageSize) ResizeCountNodePages(); + if (memOut) { + for (i = 0; i <= page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + st_free_table(table); + return(0); + } + pmin = currentLightNodePage + pageIndex; + *pmin = tval; /* Here the THEN child is lighter */ + dummyN->lightChildNodesPointer = pmin; + + } + /* updating the page index for node count storage. */ + pmin = currentNodePage + pageIndex; + *pmin = tval + eval + 1; + dummyN->nodesPointer = pmin; + + /* pageIndex is parallel page index for count_nodes and count_lightNodes */ + pageIndex++; + + /* if this node has been reached first, it belongs to a heavier + branch. Its complement will be reached later on a lighter branch. + Hence the complement has zero node count. */ + + if (st_lookup(table, (char *)Cudd_Not(node), (char **)&dummyNBar) == 1) { + if (pageIndex == pageSize) ResizeCountNodePages(); + if (memOut) { + for (i = 0; i < page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + st_free_table(table); + return(0); + } + pminBar = currentLightNodePage + pageIndex; + *pminBar = 0; + dummyNBar->lightChildNodesPointer = pminBar; + /* The lighter child has less nodes than the parent. + * So if parent 0 then lighter child zero + */ + if (pageIndex == pageSize) ResizeCountNodePages(); + if (memOut) { + for (i = 0; i < page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + st_free_table(table); + return(0); + } + pminBar = currentNodePage + pageIndex; + *pminBar = 0; + dummyNBar->nodesPointer = pminBar ; /* maybe should point to zero */ + + pageIndex++; + } + return(*pmin); +} /*end of SubsetCountNodesAux */ + + +/**Function******************************************************************** + + Synopsis [Counts the nodes under the current node and its lighter child] + + Description [Counts the nodes under the current node and its lighter + child. Calls a recursive procedure to count the number of nodes of + a DAG rooted at a particular node and the number of nodes taken by its + lighter child.] + + SideEffects [None] + + SeeAlso [SubsetCountNodesAux] + +******************************************************************************/ +static int +SubsetCountNodes( + DdNode * node /* function to be analyzed */, + st_table * table /* node quality table */, + int nvars /* number of variables node depends on */) +{ + int num; + int i; + +#ifdef DEBUG + num_calls = 0; +#endif + + max = pow(2.0,(double) nvars); + maxPages = INITIAL_PAGES; + nodePages = ALLOC(int *,maxPages); + if (nodePages == NULL) { + goto OUT_OF_MEM; + } + + lightNodePages = ALLOC(int *,maxPages); + if (lightNodePages == NULL) { + for (i = 0; i <= page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + FREE(nodePages); + goto OUT_OF_MEM; + } + + page = 0; + currentNodePage = nodePages[page] = ALLOC(int,pageSize); + if (currentNodePage == NULL) { + for (i = 0; i <= page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + FREE(lightNodePages); + FREE(nodePages); + goto OUT_OF_MEM; + } + + currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); + if (currentLightNodePage == NULL) { + for (i = 0; i <= page; i++) FREE(mintermPages[i]); + FREE(mintermPages); + for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); + FREE(nodeDataPages); + FREE(currentNodePage); + FREE(lightNodePages); + FREE(nodePages); + goto OUT_OF_MEM; + } + + pageIndex = 0; + num = SubsetCountNodesAux(node,table,max); + if (memOut) goto OUT_OF_MEM; + return(num); + +OUT_OF_MEM: + memOut = 1; + return(0); + +} /* end of SubsetCountNodes */ + + +/**Function******************************************************************** + + Synopsis [Procedure to recursively store nodes that are retained in the subset.] + + Description [rocedure to recursively store nodes that are retained in the subset.] + + SideEffects [None] + + SeeAlso [StoreNodes] + +******************************************************************************/ +static void +StoreNodes( + st_table * storeTable, + DdManager * dd, + DdNode * node) +{ + char *dummy; + DdNode *N, *Nt, *Ne; + if (Cudd_IsConstant(dd)) { + return; + } + N = Cudd_Regular(node); + if (st_lookup(storeTable, (char *)N, (char **)&dummy)) { + return; + } + cuddRef(N); + if (st_insert(storeTable, (char *)N, NIL(char)) == ST_OUT_OF_MEM) { + fprintf(dd->err,"Something wrong, st_table insert failed\n"); + } + + Nt = Cudd_T(N); + Ne = Cudd_E(N); + + StoreNodes(storeTable, dd, Nt); + StoreNodes(storeTable, dd, Ne); + return; + +} + + +/**Function******************************************************************** + + Synopsis [Builds the subset BDD using the heavy branch method.] + + Description [The procedure carries out the building of the subset BDD + starting at the root. Using the three different counts labelling each node, + the procedure chooses the heavier branch starting from the root and keeps + track of the number of nodes it discards at each step, thus keeping count + of the size of the subset BDD dynamically. Once the threshold is satisfied, + the procedure then calls ITE to build the BDD.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +BuildSubsetBdd( + DdManager * dd /* DD manager */, + DdNode * node /* current node */, + int * size /* current size of the subset */, + st_table * visitedTable /* visited table storing all node data */, + int threshold, + st_table * storeTable, + st_table * approxTable) +{ + + DdNode *Nv, *Nnv, *N, *topv, *neW; + double minNv, minNnv; + NodeData_t *currNodeQual; + NodeData_t *currNodeQualT; + NodeData_t *currNodeQualE; + DdNode *ThenBranch, *ElseBranch; + unsigned int topid; + char *dummy; + +#ifdef DEBUG + num_calls++; +#endif + /*If the size of the subset is below the threshold, dont do + anything. */ + if ((*size) <= threshold) { + /* store nodes below this, so we can recombine if possible */ + StoreNodes(storeTable, dd, node); + return(node); + } + + if (Cudd_IsConstant(node)) + return(node); + + /* Look up minterm count for this node. */ + if (!st_lookup(visitedTable, (char *)node, (char **)&currNodeQual)) { + fprintf(dd->err, + "Something is wrong, ought to be in node quality table\n"); + } + + /* Get children. */ + N = Cudd_Regular(node); + Nv = Cudd_T(N); + Nnv = Cudd_E(N); + + /* complement if necessary */ + Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); + Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); + + if (!Cudd_IsConstant(Nv)) { + /* find out minterms and nodes contributed by then child */ + if (!st_lookup(visitedTable, (char *)Nv, + (char **)&currNodeQualT)) { + fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + else { + minNv = *(((NodeData_t *)currNodeQualT)->mintermPointer); + } + } else { + if (Nv == zero) { + minNv = 0; + } else { + minNv = max; + } + } + if (!Cudd_IsConstant(Nnv)) { + /* find out minterms and nodes contributed by else child */ + if (!st_lookup(visitedTable, (char *)Nnv, (char **)&currNodeQualE)) { + fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } else { + minNnv = *(((NodeData_t *)currNodeQualE)->mintermPointer); + } + } else { + if (Nnv == zero) { + minNnv = 0; + } else { + minNnv = max; + } + } + + /* keep track of size of subset by subtracting the number of + * differential nodes contributed by lighter child + */ + *size = (*(size)) - (int)*(currNodeQual->lightChildNodesPointer); + if (minNv >= minNnv) { /*SubsetCountNodesAux procedure takes + the Then branch in case of a tie */ + + /* recur with the Then branch */ + ThenBranch = (DdNode *)BuildSubsetBdd(dd, Nv, size, + visitedTable, threshold, storeTable, approxTable); + if (ThenBranch == NULL) { + return(NULL); + } + cuddRef(ThenBranch); + /* The Else branch is either a node that already exists in the + * subset, or one whose approximation has been computed, or + * Zero. + */ + if (st_lookup(storeTable, (char *)Cudd_Regular(Nnv), (char **)&dummy)) { + ElseBranch = Nnv; + cuddRef(ElseBranch); + } else { + if (st_lookup(approxTable, (char *)Nnv, (char **)&dummy)) { + ElseBranch = (DdNode *)dummy; + cuddRef(ElseBranch); + } else { + ElseBranch = zero; + cuddRef(ElseBranch); + } + } + + } + else { + /* recur with the Else branch */ + ElseBranch = (DdNode *)BuildSubsetBdd(dd, Nnv, size, + visitedTable, threshold, storeTable, approxTable); + if (ElseBranch == NULL) { + return(NULL); + } + cuddRef(ElseBranch); + /* The Then branch is either a node that already exists in the + * subset, or one whose approximation has been computed, or + * Zero. + */ + if (st_lookup(storeTable, (char *)Cudd_Regular(Nv), (char **)&dummy)) { + ThenBranch = Nv; + cuddRef(ThenBranch); + } else { + if (st_lookup(approxTable, (char *)Nv, (char **)&dummy)) { + ThenBranch = (DdNode *)dummy; + cuddRef(ThenBranch); + } else { + ThenBranch = zero; + cuddRef(ThenBranch); + } + } + } + + /* construct the Bdd with the top variable and the two children */ + topid = Cudd_NodeReadIndex(N); + topv = Cudd_ReadVars(dd, topid); + cuddRef(topv); + neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); + if (neW != NULL) { + cuddRef(neW); + } + Cudd_RecursiveDeref(dd, topv); + Cudd_RecursiveDeref(dd, ThenBranch); + Cudd_RecursiveDeref(dd, ElseBranch); + + + if (neW == NULL) + return(NULL); + else { + /* store this node in the store table */ + if (!st_lookup(storeTable, (char *)Cudd_Regular(neW), (char **)&dummy)) { + cuddRef(neW); + st_insert(storeTable, (char *)Cudd_Regular(neW), (char *)NIL(char)); + + } + /* store the approximation for this node */ + if (N != Cudd_Regular(neW)) { + if (st_lookup(approxTable, (char *)node, (char **)&dummy)) { + fprintf(dd->err, "This node should not be in the approximated table\n"); + } else { + cuddRef(neW); + st_insert(approxTable, (char *)node, (char *)neW); + } + } + cuddDeref(neW); + return(neW); + } +} /* end of BuildSubsetBdd */ + diff --git a/abc70930/src/bdd/cudd/cuddSubsetSP.c b/abc70930/src/bdd/cudd/cuddSubsetSP.c new file mode 100644 index 00000000..55ee3470 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddSubsetSP.c @@ -0,0 +1,1624 @@ +/**CFile*********************************************************************** + + FileName [cuddSubsetSP.c] + + PackageName [cudd] + + Synopsis [Procedure to subset the given BDD choosing the shortest paths + (largest cubes) in the BDD.] + + + Description [External procedures included in this module: +
          +
        • Cudd_SubsetShortPaths() +
        • Cudd_SupersetShortPaths() +
        + Internal procedures included in this module: +
          +
        • cuddSubsetShortPaths() +
        + Static procedures included in this module: +
          +
        • BuildSubsetBdd() +
        • CreatePathTable() +
        • AssessPathLength() +
        • CreateTopDist() +
        • CreateBotDist() +
        • ResizeNodeDistPages() +
        • ResizeQueuePages() +
        • stPathTableDdFree() +
        + ] + + SeeAlso [cuddSubsetHB.c] + + Author [Kavita Ravi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define DEFAULT_PAGE_SIZE 2048 /* page size to store the BFS queue element type */ +#define DEFAULT_NODE_DIST_PAGE_SIZE 2048 /* page sizesto store NodeDist_t type */ +#define MAXSHORTINT ((DdHalfWord) ~0) /* constant defined to store + * maximum distance of a node + * from the root or the + * constant + */ +#define INITIAL_PAGES 128 /* number of initial pages for the + * queue/NodeDist_t type */ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/* structure created to store subset results for each node and distances with + * odd and even parity of the node from the root and sink. Main data structure + * in this procedure. + */ +struct NodeDist{ + DdHalfWord oddTopDist; + DdHalfWord evenTopDist; + DdHalfWord oddBotDist; + DdHalfWord evenBotDist; + DdNode *regResult; + DdNode *compResult; +}; + +/* assorted information needed by the BuildSubsetBdd procedure. */ +struct AssortedInfo { + unsigned int maxpath; + int findShortestPath; + int thresholdReached; + st_table *maxpathTable; + int threshold; +}; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +typedef struct NodeDist NodeDist_t; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +#ifdef DD_DEBUG +static int numCalls; +static int hits; +static int thishit; +#endif + + +static int memOut; /* flag to indicate out of memory */ +static DdNode *zero, *one; /* constant functions */ + +static NodeDist_t **nodeDistPages; /* pointers to the pages */ +static int nodeDistPageIndex; /* index to next element */ +static int nodeDistPage; /* index to current page */ +static int nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE; /* page size */ +static int maxNodeDistPages; /* number of page pointers */ +static NodeDist_t *currentNodeDistPage; /* current page */ + +static DdNode ***queuePages; /* pointers to the pages */ +static int queuePageIndex; /* index to next element */ +static int queuePage; /* index to current page */ +static int queuePageSize = DEFAULT_PAGE_SIZE; /* page size */ +static int maxQueuePages; /* number of page pointers */ +static DdNode **currentQueuePage; /* current page */ + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void ResizeNodeDistPages ARGS(()); +static void ResizeQueuePages ARGS(()); +static void CreateTopDist ARGS((st_table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp)); +static int CreateBotDist ARGS((DdNode *node, st_table *pathTable, unsigned int *pathLengthArray, FILE *fp)); +static st_table * CreatePathTable ARGS((DdNode *node, unsigned int *pathLengthArray, FILE *fp)); +static unsigned int AssessPathLength ARGS((unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp)); +static DdNode * BuildSubsetBdd ARGS((DdManager *dd, st_table *pathTable, DdNode *node, struct AssortedInfo *info, st_table *subsetNodeTable)); +static enum st_retval stPathTableDdFree ARGS((char *key, char *value, char *arg)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of Exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Extracts a dense subset from a BDD with the shortest paths + heuristic.] + + Description [Extracts a dense subset from a BDD. This procedure + tries to preserve the shortest paths of the input BDD, because they + give many minterms and contribute few nodes. This procedure may + increase the number of nodes in trying to create the subset or + reduce the number of nodes due to recombination as compared to the + original BDD. Hence the threshold may not be strictly adhered to. In + practice, recombination overshadows the increase in the number of + nodes and results in small BDDs as compared to the threshold. The + hardlimit specifies whether threshold needs to be strictly adhered + to. If it is set to 1, the procedure ensures that result is never + larger than the specified limit but may be considerably less than + the threshold. Returns a pointer to the BDD for the subset if + successful; NULL otherwise. The value for numVars should be as + close as possible to the size of the support of f for better + efficiency. However, it is safe to pass the value returned by + Cudd_ReadSize for numVars. If 0 is passed, then the value returned + by Cudd_ReadSize is used.] + + SideEffects [None] + + SeeAlso [Cudd_SupersetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize] + +******************************************************************************/ +DdNode * +Cudd_SubsetShortPaths( + DdManager * dd /* manager */, + DdNode * f /* function to be subset */, + int numVars /* number of variables in the support of f */, + int threshold /* maximum number of nodes in the subset */, + int hardlimit /* flag: 1 if threshold is a hard limit */) +{ + DdNode *subset; + + memOut = 0; + do { + dd->reordered = 0; + subset = cuddSubsetShortPaths(dd, f, numVars, threshold, hardlimit); + } while((dd->reordered ==1) && (!memOut)); + + return(subset); + +} /* end of Cudd_SubsetShortPaths */ + + +/**Function******************************************************************** + + Synopsis [Extracts a dense superset from a BDD with the shortest paths + heuristic.] + + Description [Extracts a dense superset from a BDD. The procedure is + identical to the subset procedure except for the fact that it + receives the complement of the given function. Extracting the subset + of the complement function is equivalent to extracting the superset + of the function. This procedure tries to preserve the shortest + paths of the complement BDD, because they give many minterms and + contribute few nodes. This procedure may increase the number of + nodes in trying to create the superset or reduce the number of nodes + due to recombination as compared to the original BDD. Hence the + threshold may not be strictly adhered to. In practice, recombination + overshadows the increase in the number of nodes and results in small + BDDs as compared to the threshold. The hardlimit specifies whether + threshold needs to be strictly adhered to. If it is set to 1, the + procedure ensures that result is never larger than the specified + limit but may be considerably less than the threshold. Returns a + pointer to the BDD for the superset if successful; NULL + otherwise. The value for numVars should be as close as possible to + the size of the support of f for better efficiency. However, it is + safe to pass the value returned by Cudd_ReadSize for numVar. If 0 + is passed, then the value returned by Cudd_ReadSize is used.] + + SideEffects [None] + + SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize] + +******************************************************************************/ +DdNode * +Cudd_SupersetShortPaths( + DdManager * dd /* manager */, + DdNode * f /* function to be superset */, + int numVars /* number of variables in the support of f */, + int threshold /* maximum number of nodes in the subset */, + int hardlimit /* flag: 1 if threshold is a hard limit */) +{ + DdNode *subset, *g; + + g = Cudd_Not(f); + memOut = 0; + do { + dd->reordered = 0; + subset = cuddSubsetShortPaths(dd, g, numVars, threshold, hardlimit); + } while((dd->reordered ==1) && (!memOut)); + + return(Cudd_NotCond(subset, (subset != NULL))); + +} /* end of Cudd_SupersetShortPaths */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [The outermost procedure to return a subset of the given BDD + with the shortest path lengths.] + + Description [The outermost procedure to return a subset of the given + BDD with the largest cubes. The path lengths are calculated, the maximum + allowable path length is determined and the number of nodes of this + path length that can be used to build a subset. If the threshold is + larger than the size of the original BDD, the original BDD is + returned. ] + + SideEffects [None] + + SeeAlso [Cudd_SubsetShortPaths] + +******************************************************************************/ +DdNode * +cuddSubsetShortPaths( + DdManager * dd /* DD manager */, + DdNode * f /* function to be subset */, + int numVars /* total number of variables in consideration */, + int threshold /* maximum number of nodes allowed in the subset */, + int hardlimit /* flag determining whether thershold should be respected strictly */) +{ + st_table *pathTable; + DdNode *N, *subset; + + unsigned int *pathLengthArray; + unsigned int maxpath, oddLen, evenLen, pathLength, *excess; + int i; + NodeDist_t *nodeStat; + struct AssortedInfo *info; + st_table *subsetNodeTable; + + one = DD_ONE(dd); + zero = Cudd_Not(one); + + if (numVars == 0) { + /* set default value */ + numVars = Cudd_ReadSize(dd); + } + + if (threshold > numVars) { + threshold = threshold - numVars; + } + if (f == NULL) { + fprintf(dd->err, "Cannot partition, nil object\n"); + dd->errorCode = CUDD_INVALID_ARG; + return(NULL); + } + if (Cudd_IsConstant(f)) + return (f); + + pathLengthArray = ALLOC(unsigned int, numVars+1); + for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0; + + +#ifdef DD_DEBUG + numCalls = 0; +#endif + + pathTable = CreatePathTable(f, pathLengthArray, dd->err); + + if ((pathTable == NULL) || (memOut)) { + if (pathTable != NULL) + st_free_table(pathTable); + FREE(pathLengthArray); + return (NIL(DdNode)); + } + + excess = ALLOC(unsigned int, 1); + *excess = 0; + maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess, + dd->err); + + if (maxpath != (unsigned) (numVars + 1)) { + + info = ALLOC(struct AssortedInfo, 1); + info->maxpath = maxpath; + info->findShortestPath = 0; + info->thresholdReached = *excess; + info->maxpathTable = st_init_table(st_ptrcmp, st_ptrhash); + info->threshold = threshold; + +#ifdef DD_DEBUG + (void) fprintf(dd->out, "Path length array\n"); + for (i = 0; i < (numVars+1); i++) { + if (pathLengthArray[i]) + (void) fprintf(dd->out, "%d ",i); + } + (void) fprintf(dd->out, "\n"); + for (i = 0; i < (numVars+1); i++) { + if (pathLengthArray[i]) + (void) fprintf(dd->out, "%d ",pathLengthArray[i]); + } + (void) fprintf(dd->out, "\n"); + (void) fprintf(dd->out, "Maxpath = %d, Thresholdreached = %d\n", + maxpath, info->thresholdReached); +#endif + + N = Cudd_Regular(f); + if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { + fprintf(dd->err, "Something wrong, root node must be in table\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } else { + if ((nodeStat->oddTopDist != MAXSHORTINT) && + (nodeStat->oddBotDist != MAXSHORTINT)) + oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); + else + oddLen = MAXSHORTINT; + + if ((nodeStat->evenTopDist != MAXSHORTINT) && + (nodeStat->evenBotDist != MAXSHORTINT)) + evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); + else + evenLen = MAXSHORTINT; + + pathLength = (oddLen <= evenLen) ? oddLen : evenLen; + if (pathLength > maxpath) { + (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %d, %d\n", maxpath, pathLength); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + } + +#ifdef DD_DEBUG + numCalls = 0; + hits = 0; + thishit = 0; +#endif + /* initialize a table to store computed nodes */ + if (hardlimit) { + subsetNodeTable = st_init_table(st_ptrcmp, st_ptrhash); + } else { + subsetNodeTable = NIL(st_table); + } + subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable); + if (subset != NULL) { + cuddRef(subset); + } + /* record the number of times a computed result for a node is hit */ + +#ifdef DD_DEBUG + (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n", + hits, thishit, numCalls); +#endif + + if (subsetNodeTable != NIL(st_table)) { + st_free_table(subsetNodeTable); + } + st_free_table(info->maxpathTable); + st_foreach(pathTable, stPathTableDdFree, (char *)dd); + + FREE(info); + + } else {/* if threshold larger than size of dd */ + subset = f; + cuddRef(subset); + } + FREE(excess); + st_free_table(pathTable); + FREE(pathLengthArray); + for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); + FREE(nodeDistPages); + +#ifdef DD_DEBUG + /* check containment of subset in f */ + if (subset != NULL) { + DdNode *check; + check = Cudd_bddIteConstant(dd, subset, f, one); + if (check != one) { + (void) fprintf(dd->err, "Wrong partition\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + } +#endif + + if (subset != NULL) { + cuddDeref(subset); + return(subset); + } else { + return(NULL); + } + +} /* end of cuddSubsetShortPaths */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Resize the number of pages allocated to store the distances + related to each node.] + + Description [Resize the number of pages allocated to store the distances + related to each node. The procedure moves the counter to the + next page when the end of the page is reached and allocates new + pages when necessary. ] + + SideEffects [Changes the size of pages, page, page index, maximum + number of pages freeing stuff in case of memory out. ] + + SeeAlso [] + +******************************************************************************/ +static void +ResizeNodeDistPages( + ) +{ + int i; + NodeDist_t **newNodeDistPages; + + /* move to next page */ + nodeDistPage++; + + /* If the current page index is larger than the number of pages + * allocated, allocate a new page array. Page numbers are incremented by + * INITIAL_PAGES + */ + if (nodeDistPage == maxNodeDistPages) { + newNodeDistPages = ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES); + if (newNodeDistPages == NULL) { + for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); + FREE(nodeDistPages); + memOut = 1; + return; + } else { + for (i = 0; i < maxNodeDistPages; i++) { + newNodeDistPages[i] = nodeDistPages[i]; + } + /* Increase total page count */ + maxNodeDistPages += INITIAL_PAGES; + FREE(nodeDistPages); + nodeDistPages = newNodeDistPages; + } + } + /* Allocate a new page */ + currentNodeDistPage = nodeDistPages[nodeDistPage] = ALLOC(NodeDist_t, + nodeDistPageSize); + if (currentNodeDistPage == NULL) { + for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); + FREE(nodeDistPages); + memOut = 1; + return; + } + /* reset page index */ + nodeDistPageIndex = 0; + return; + +} /* end of ResizeNodeDistPages */ + + +/**Function******************************************************************** + + Synopsis [Resize the number of pages allocated to store nodes in the BFS + traversal of the Bdd .] + + Description [Resize the number of pages allocated to store nodes in the BFS + traversal of the Bdd. The procedure moves the counter to the + next page when the end of the page is reached and allocates new + pages when necessary.] + + SideEffects [Changes the size of pages, page, page index, maximum + number of pages freeing stuff in case of memory out. ] + + SeeAlso [] + +******************************************************************************/ +static void +ResizeQueuePages( + ) +{ + int i; + DdNode ***newQueuePages; + + queuePage++; + /* If the current page index is larger than the number of pages + * allocated, allocate a new page array. Page numbers are incremented by + * INITIAL_PAGES + */ + if (queuePage == maxQueuePages) { + newQueuePages = ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES); + if (newQueuePages == NULL) { + for (i = 0; i < queuePage; i++) FREE(queuePages[i]); + FREE(queuePages); + memOut = 1; + return; + } else { + for (i = 0; i < maxQueuePages; i++) { + newQueuePages[i] = queuePages[i]; + } + /* Increase total page count */ + maxQueuePages += INITIAL_PAGES; + FREE(queuePages); + queuePages = newQueuePages; + } + } + /* Allocate a new page */ + currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *,queuePageSize); + if (currentQueuePage == NULL) { + for (i = 0; i < queuePage; i++) FREE(queuePages[i]); + FREE(queuePages); + memOut = 1; + return; + } + /* reset page index */ + queuePageIndex = 0; + return; + +} /* end of ResizeQueuePages */ + + +/**Function******************************************************************** + + Synopsis [ Labels each node with its shortest distance from the root] + + Description [ Labels each node with its shortest distance from the root. + This is done in a BFS search of the BDD. The nodes are processed + in a queue implemented as pages(array) to reduce memory fragmentation. + An entry is created for each node visited. The distance from the root + to the node with the corresponding parity is updated. The procedure + is called recursively each recusion level handling nodes at a given + level from the root.] + + + SideEffects [Creates entries in the pathTable] + + SeeAlso [CreatePathTable CreateBotDist] + +******************************************************************************/ +static void +CreateTopDist( + st_table * pathTable /* hast table to store path lengths */, + int parentPage /* the pointer to the page on which the first parent in the queue is to be found. */, + int parentQueueIndex /* pointer to the first parent on the page */, + int topLen /* current distance from the root */, + DdNode ** childPage /* pointer to the page on which the first child is to be added. */, + int childQueueIndex /* pointer to the first child */, + int numParents /* number of parents to process in this recursive call */, + FILE *fp /* where to write messages */) +{ + NodeDist_t *nodeStat; + DdNode *N, *Nv, *Nnv, *node, *child, *regChild; + int i; + int processingDone, childrenCount; + +#ifdef DD_DEBUG + numCalls++; + + /* assume this procedure comes in with only the root node*/ + /* set queue index to the next available entry for addition */ + /* set queue page to page of addition */ + if ((queuePages[parentPage] == childPage) && (parentQueueIndex == + childQueueIndex)) { + fprintf(fp, "Should not happen that they are equal\n"); + } + assert(queuePageIndex == childQueueIndex); + assert(currentQueuePage == childPage); +#endif + /* number children added to queue is initialized , needed for + * numParents in the next call + */ + childrenCount = 0; + /* process all the nodes in this level */ + while (numParents) { + numParents--; + if (parentQueueIndex == queuePageSize) { + parentPage++; + parentQueueIndex = 0; + } + /* a parent to process */ + node = *(queuePages[parentPage] + parentQueueIndex); + parentQueueIndex++; + /* get its children */ + N = Cudd_Regular(node); + Nv = Cudd_T(N); + Nnv = Cudd_E(N); + + Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); + Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); + + processingDone = 2; + while (processingDone) { + /* processing the THEN and the ELSE children, the THEN + * child first + */ + if (processingDone == 2) { + child = Nv; + } else { + child = Nnv; + } + + regChild = Cudd_Regular(child); + /* dont process if the child is a constant */ + if (!Cudd_IsConstant(child)) { + /* check is already visited, if not add a new entry in + * the path Table + */ + if (!st_lookup(pathTable, (char *)regChild, (char **)&nodeStat)) { + /* if not in table, has never been visited */ + /* create entry for table */ + if (nodeDistPageIndex == nodeDistPageSize) + ResizeNodeDistPages(); + if (memOut) { + for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); + FREE(queuePages); + st_free_table(pathTable); + return; + } + /* New entry for child in path Table is created here */ + nodeStat = currentNodeDistPage + nodeDistPageIndex; + nodeDistPageIndex++; + + /* Initialize fields of the node data */ + nodeStat->oddTopDist = MAXSHORTINT; + nodeStat->evenTopDist = MAXSHORTINT; + nodeStat->evenBotDist = MAXSHORTINT; + nodeStat->oddBotDist = MAXSHORTINT; + nodeStat->regResult = NULL; + nodeStat->compResult = NULL; + /* update the table entry element, the distance keeps + * track of the parity of the path from the root + */ + if (Cudd_IsComplement(child)) { + nodeStat->oddTopDist = (DdHalfWord) topLen + 1; + } else { + nodeStat->evenTopDist = (DdHalfWord) topLen + 1; + } + + /* insert entry element for child in the table */ + if (st_insert(pathTable, (char *)regChild, + (char *)nodeStat) == ST_OUT_OF_MEM) { + memOut = 1; + for (i = 0; i <= nodeDistPage; i++) + FREE(nodeDistPages[i]); + FREE(nodeDistPages); + for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); + FREE(queuePages); + st_free_table(pathTable); + return; + } + + /* Create list element for this child to process its children. + * If this node has been processed already, then it appears + * in the path table and hence is never added to the list + * again. + */ + + if (queuePageIndex == queuePageSize) ResizeQueuePages(); + if (memOut) { + for (i = 0; i <= nodeDistPage; i++) + FREE(nodeDistPages[i]); + FREE(nodeDistPages); + st_free_table(pathTable); + return; + } + *(currentQueuePage + queuePageIndex) = child; + queuePageIndex++; + + childrenCount++; + } else { + /* if not been met in a path with this parity before */ + /* put in list */ + if (((Cudd_IsComplement(child)) && (nodeStat->oddTopDist == + MAXSHORTINT)) || ((!Cudd_IsComplement(child)) && + (nodeStat->evenTopDist == MAXSHORTINT))) { + + if (queuePageIndex == queuePageSize) ResizeQueuePages(); + if (memOut) { + for (i = 0; i <= nodeDistPage; i++) + FREE(nodeDistPages[i]); + FREE(nodeDistPages); + st_free_table(pathTable); + return; + + } + *(currentQueuePage + queuePageIndex) = child; + queuePageIndex++; + + /* update the distance with the appropriate parity */ + if (Cudd_IsComplement(child)) { + nodeStat->oddTopDist = (DdHalfWord) topLen + 1; + } else { + nodeStat->evenTopDist = (DdHalfWord) topLen + 1; + } + childrenCount++; + } + + } /* end of else (not found in st_table) */ + } /*end of if Not constant child */ + processingDone--; + } /*end of while processing Nv, Nnv */ + } /*end of while numParents */ + +#ifdef DD_DEBUG + assert(queuePages[parentPage] == childPage); + assert(parentQueueIndex == childQueueIndex); +#endif + + if (childrenCount != 0) { + topLen++; + childPage = currentQueuePage; + childQueueIndex = queuePageIndex; + CreateTopDist(pathTable, parentPage, parentQueueIndex, topLen, + childPage, childQueueIndex, childrenCount, fp); + } + + return; + +} /* end of CreateTopDist */ + + +/**Function******************************************************************** + + Synopsis [ Labels each node with the shortest distance from the constant.] + + Description [Labels each node with the shortest distance from the constant. + This is done in a DFS search of the BDD. Each node has an odd + and even parity distance from the sink (since there exists paths to both + zero and one) which is less than MAXSHORTINT. At each node these distances + are updated using the minimum distance of its children from the constant. + SInce now both the length from the root and child is known, the minimum path + length(length of the shortest path between the root and the constant that + this node lies on) of this node can be calculated and used to update the + pathLengthArray] + + SideEffects [Updates Path Table and path length array] + + SeeAlso [CreatePathTable CreateTopDist AssessPathLength] + +******************************************************************************/ +static int +CreateBotDist( + DdNode * node /* current node */, + st_table * pathTable /* path table with path lengths */, + unsigned int * pathLengthArray /* array that stores number of nodes belonging to a particular path length. */, + FILE *fp /* where to write messages */) +{ + DdNode *N, *Nv, *Nnv; + DdNode *realChild; + DdNode *child, *regChild; + NodeDist_t *nodeStat, *nodeStatChild; + unsigned int oddLen, evenLen, pathLength; + DdHalfWord botDist; + int processingDone; + + if (Cudd_IsConstant(node)) + return(1); + N = Cudd_Regular(node); + /* each node has one table entry */ + /* update as you go down the min dist of each node from + the root in each (odd and even) parity */ + if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { + fprintf(fp, "Something wrong, the entry doesn't exist\n"); + return(0); + } + + /* compute length of odd parity distances */ + if ((nodeStat->oddTopDist != MAXSHORTINT) && + (nodeStat->oddBotDist != MAXSHORTINT)) + oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); + else + oddLen = MAXSHORTINT; + + /* compute length of even parity distances */ + if (!((nodeStat->evenTopDist == MAXSHORTINT) || + (nodeStat->evenBotDist == MAXSHORTINT))) + evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); + else + evenLen = MAXSHORTINT; + + /* assign pathlength to minimum of the two */ + pathLength = (oddLen <= evenLen) ? oddLen : evenLen; + + Nv = Cudd_T(N); + Nnv = Cudd_E(N); + + /* process each child */ + processingDone = 0; + while (processingDone != 2) { + if (!processingDone) { + child = Nv; + } else { + child = Nnv; + } + + realChild = Cudd_NotCond(child, Cudd_IsComplement(node)); + regChild = Cudd_Regular(child); + if (Cudd_IsConstant(realChild)) { + /* Found a minterm; count parity and shortest distance + ** from the constant. + */ + if (Cudd_IsComplement(child)) + nodeStat->oddBotDist = 1; + else + nodeStat->evenBotDist = 1; + } else { + /* If node not in table, recur. */ + if (!st_lookup(pathTable, (char *) regChild, + (char **)&nodeStatChild)) { + fprintf(fp, "Something wrong, node in table should have been created in top dist proc.\n"); + return(0); + } + + if (nodeStatChild->oddBotDist == MAXSHORTINT) { + if (nodeStatChild->evenBotDist == MAXSHORTINT) { + if (!CreateBotDist(realChild, pathTable, pathLengthArray, fp)) + return(0); + } else { + fprintf(fp, "Something wrong, both bot nodeStats should be there\n"); + return(0); + } + } + + /* Update shortest distance from the constant depending on + ** parity. */ + + if (Cudd_IsComplement(child)) { + /* If parity on the edge then add 1 to even distance + ** of child to get odd parity distance and add 1 to + ** odd distance of child to get even parity + ** distance. Change distance of current node only if + ** the calculated distance is less than existing + ** distance. */ + if (nodeStatChild->oddBotDist != MAXSHORTINT) + botDist = nodeStatChild->oddBotDist + 1; + else + botDist = MAXSHORTINT; + if (nodeStat->evenBotDist > botDist ) + nodeStat->evenBotDist = botDist; + + if (nodeStatChild->evenBotDist != MAXSHORTINT) + botDist = nodeStatChild->evenBotDist + 1; + else + botDist = MAXSHORTINT; + if (nodeStat->oddBotDist > botDist) + nodeStat->oddBotDist = botDist; + + } else { + /* If parity on the edge then add 1 to even distance + ** of child to get even parity distance and add 1 to + ** odd distance of child to get odd parity distance. + ** Change distance of current node only if the + ** calculated distance is lesser than existing + ** distance. */ + if (nodeStatChild->evenBotDist != MAXSHORTINT) + botDist = nodeStatChild->evenBotDist + 1; + else + botDist = MAXSHORTINT; + if (nodeStat->evenBotDist > botDist) + nodeStat->evenBotDist = botDist; + + if (nodeStatChild->oddBotDist != MAXSHORTINT) + botDist = nodeStatChild->oddBotDist + 1; + else + botDist = MAXSHORTINT; + if (nodeStat->oddBotDist > botDist) + nodeStat->oddBotDist = botDist; + } + } /* end of else (if not constant child ) */ + processingDone++; + } /* end of while processing Nv, Nnv */ + + /* Compute shortest path length on the fly. */ + if ((nodeStat->oddTopDist != MAXSHORTINT) && + (nodeStat->oddBotDist != MAXSHORTINT)) + oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); + else + oddLen = MAXSHORTINT; + + if ((nodeStat->evenTopDist != MAXSHORTINT) && + (nodeStat->evenBotDist != MAXSHORTINT)) + evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); + else + evenLen = MAXSHORTINT; + + /* Update path length array that has number of nodes of a particular + ** path length. */ + if (oddLen < pathLength ) { + if (pathLength != MAXSHORTINT) + pathLengthArray[pathLength]--; + if (oddLen != MAXSHORTINT) + pathLengthArray[oddLen]++; + pathLength = oddLen; + } + if (evenLen < pathLength ) { + if (pathLength != MAXSHORTINT) + pathLengthArray[pathLength]--; + if (evenLen != MAXSHORTINT) + pathLengthArray[evenLen]++; + } + + return(1); + +} /*end of CreateBotDist */ + + +/**Function******************************************************************** + + Synopsis [ The outer procedure to label each node with its shortest + distance from the root and constant] + + Description [ The outer procedure to label each node with its shortest + distance from the root and constant. Calls CreateTopDist and CreateBotDist. + The basis for computing the distance between root and constant is that + the distance may be the sum of even distances from the node to the root + and constant or the sum of odd distances from the node to the root and + constant. Both CreateTopDist and CreateBotDist create the odd and + even parity distances from the root and constant respectively.] + + SideEffects [None] + + SeeAlso [CreateTopDist CreateBotDist] + +******************************************************************************/ +static st_table * +CreatePathTable( + DdNode * node /* root of function */, + unsigned int * pathLengthArray /* array of path lengths to store nodes labeled with the various path lengths */, + FILE *fp /* where to write messages */) +{ + + st_table *pathTable; + NodeDist_t *nodeStat; + DdHalfWord topLen; + DdNode *N; + int i, numParents; + int insertValue; + DdNode **childPage; + int parentPage; + int childQueueIndex, parentQueueIndex; + + /* Creating path Table for storing data about nodes */ + pathTable = st_init_table(st_ptrcmp,st_ptrhash); + + /* initializing pages for info about each node */ + maxNodeDistPages = INITIAL_PAGES; + nodeDistPages = ALLOC(NodeDist_t *, maxNodeDistPages); + if (nodeDistPages == NULL) { + goto OUT_OF_MEM; + } + nodeDistPage = 0; + currentNodeDistPage = nodeDistPages[nodeDistPage] = + ALLOC(NodeDist_t, nodeDistPageSize); + if (currentNodeDistPage == NULL) { + for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); + FREE(nodeDistPages); + goto OUT_OF_MEM; + } + nodeDistPageIndex = 0; + + /* Initializing pages for the BFS search queue, implemented as an array. */ + maxQueuePages = INITIAL_PAGES; + queuePages = ALLOC(DdNode **, maxQueuePages); + if (queuePages == NULL) { + goto OUT_OF_MEM; + } + queuePage = 0; + currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *, queuePageSize); + if (currentQueuePage == NULL) { + for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); + FREE(queuePages); + goto OUT_OF_MEM; + } + queuePageIndex = 0; + + /* Enter the root node into the queue to start with. */ + parentPage = queuePage; + parentQueueIndex = queuePageIndex; + topLen = 0; + *(currentQueuePage + queuePageIndex) = node; + queuePageIndex++; + childPage = currentQueuePage; + childQueueIndex = queuePageIndex; + + N = Cudd_Regular(node); + + if (nodeDistPageIndex == nodeDistPageSize) ResizeNodeDistPages(); + if (memOut) { + for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); + FREE(nodeDistPages); + for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); + FREE(queuePages); + st_free_table(pathTable); + goto OUT_OF_MEM; + } + + nodeStat = currentNodeDistPage + nodeDistPageIndex; + nodeDistPageIndex++; + + nodeStat->oddTopDist = MAXSHORTINT; + nodeStat->evenTopDist = MAXSHORTINT; + nodeStat->evenBotDist = MAXSHORTINT; + nodeStat->oddBotDist = MAXSHORTINT; + nodeStat->regResult = NULL; + nodeStat->compResult = NULL; + + insertValue = st_insert(pathTable, (char *)N, (char *)nodeStat); + if (insertValue == ST_OUT_OF_MEM) { + memOut = 1; + for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); + FREE(nodeDistPages); + for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); + FREE(queuePages); + st_free_table(pathTable); + goto OUT_OF_MEM; + } else if (insertValue == 1) { + fprintf(fp, "Something wrong, the entry exists but didnt show up in st_lookup\n"); + return(NULL); + } + + if (Cudd_IsComplement(node)) { + nodeStat->oddTopDist = 0; + } else { + nodeStat->evenTopDist = 0; + } + numParents = 1; + /* call the function that counts the distance of each node from the + * root + */ +#ifdef DD_DEBUG + numCalls = 0; +#endif + CreateTopDist(pathTable, parentPage, parentQueueIndex, (int) topLen, + childPage, childQueueIndex, numParents, fp); + if (memOut) { + fprintf(fp, "Out of Memory and cant count path lengths\n"); + goto OUT_OF_MEM; + } + +#ifdef DD_DEBUG + numCalls = 0; +#endif + /* call the function that counts the distance of each node from the + * constant + */ + if (!CreateBotDist(node, pathTable, pathLengthArray, fp)) return(NULL); + + /* free BFS queue pages as no longer required */ + for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); + FREE(queuePages); + return(pathTable); + +OUT_OF_MEM: + (void) fprintf(fp, "Out of Memory, cannot allocate pages\n"); + memOut = 1; + return(NULL); + +} /*end of CreatePathTable */ + + +/**Function******************************************************************** + + Synopsis [Chooses the maximum allowable path length of nodes under the + threshold.] + + Description [Chooses the maximum allowable path length under each node. + The corner cases are when the threshold is larger than the number + of nodes in the BDD iself, in which case 'numVars + 1' is returned. + If all nodes of a particular path length are needed, then the + maxpath returned is the next one with excess nodes = 0;] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static unsigned int +AssessPathLength( + unsigned int * pathLengthArray /* array determining number of nodes belonging to the different path lengths */, + int threshold /* threshold to determine maximum allowable nodes in the subset */, + int numVars /* maximum number of variables */, + unsigned int * excess /* number of nodes labeled maxpath required in the subset */, + FILE *fp /* where to write messages */) +{ + unsigned int i, maxpath; + int temp; + + temp = threshold; + i = 0; + maxpath = 0; + /* quit loop if i reaches max number of variables or if temp reaches + * below zero + */ + while ((i < (unsigned) numVars+1) && (temp > 0)) { + if (pathLengthArray[i] > 0) { + maxpath = i; + temp = temp - pathLengthArray[i]; + } + i++; + } + /* if all nodes of max path are needed */ + if (temp >= 0) { + maxpath++; /* now maxpath becomes the next maxppath or max number + of variables */ + *excess = 0; + } else { /* normal case when subset required is less than size of + original BDD */ + *excess = temp + pathLengthArray[maxpath]; + } + + if (maxpath == 0) { + fprintf(fp, "Path Length array seems to be all zeroes, check\n"); + } + return(maxpath); + +} /* end of AssessPathLength */ + + +/**Function******************************************************************** + + Synopsis [Builds the BDD with nodes labeled with path length less than or equal to maxpath] + + Description [Builds the BDD with nodes labeled with path length + under maxpath and as many nodes labeled maxpath as determined by the + threshold. The procedure uses the path table to determine which nodes + in the original bdd need to be retained. This procedure picks a + shortest path (tie break decided by taking the child with the shortest + distance to the constant) and recurs down the path till it reaches the + constant. the procedure then starts building the subset upward from + the constant. All nodes labeled by path lengths less than the given + maxpath are used to build the subset. However, in the case of nodes + that have label equal to maxpath, as many are chosen as required by + the threshold. This number is stored in the info structure in the + field thresholdReached. This field is decremented whenever a node + labeled maxpath is encountered and the nodes labeled maxpath are + aggregated in a maxpath table. As soon as the thresholdReached count + goes to 0, the shortest path from this node to the constant is found. + The extraction of nodes with the above labeling is based on the fact + that each node, labeled with a path length, P, has at least one child + labeled P or less. So extracting all nodes labeled a given path length + P ensures complete paths between the root and the constant. Extraction + of a partial number of nodes with a given path length may result in + incomplete paths and hence the additional number of nodes are grabbed + to complete the path. Since the Bdd is built bottom-up, other nodes + labeled maxpath do lie on complete paths. The procedure may cause the + subset to have a larger or smaller number of nodes than the specified + threshold. The increase in the number of nodes is caused by the + building of a subset and the reduction by recombination. However in + most cases, the recombination overshadows the increase and the + procedure returns a result with lower number of nodes than specified. + The subsetNodeTable is NIL when there is no hard limit on the number + of nodes. Further efforts towards keeping the subset closer to the + threshold number were abandoned in favour of keeping the procedure + simple and fast.] + + SideEffects [SubsetNodeTable is changed if it is not NIL.] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +BuildSubsetBdd( + DdManager * dd /* DD manager */, + st_table * pathTable /* path table with path lengths and computed results */, + DdNode * node /* current node */, + struct AssortedInfo * info /* assorted information structure */, + st_table * subsetNodeTable /* table storing computed results */) +{ + DdNode *N, *Nv, *Nnv; + DdNode *ThenBranch, *ElseBranch, *childBranch; + DdNode *child, *regChild, *regNnv, *regNv; + NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv; + DdNode *neW, *topv, *regNew; + char *entry; + unsigned int topid; + unsigned int childPathLength, oddLen, evenLen, NnvPathLength, NvPathLength; + unsigned int NvBotDist, NnvBotDist; + int tiebreakChild; + int processingDone, thenDone, elseDone; + + +#ifdef DD_DEBUG + numCalls++; +#endif + if (Cudd_IsConstant(node)) + return(node); + + N = Cudd_Regular(node); + /* Find node in table. */ + if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { + (void) fprintf(dd->err, "Something wrong, node must be in table \n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + /* If the node in the table has been visited, then return the corresponding + ** Dd. Since a node can become a subset of itself, its + ** complement (that is te same node reached by a different parity) will + ** become a superset of the original node and result in some minterms + ** that were not in the original set. Hence two different results are + ** maintained, corresponding to the odd and even parities. + */ + + /* If this node is reached with an odd parity, get odd parity results. */ + if (Cudd_IsComplement(node)) { + if (nodeStat->compResult != NULL) { +#ifdef DD_DEBUG + hits++; +#endif + return(nodeStat->compResult); + } + } else { + /* if this node is reached with an even parity, get even parity + * results + */ + if (nodeStat->regResult != NULL) { +#ifdef DD_DEBUG + hits++; +#endif + return(nodeStat->regResult); + } + } + + + /* get children */ + Nv = Cudd_T(N); + Nnv = Cudd_E(N); + + Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); + Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); + + /* no child processed */ + processingDone = 0; + /* then child not processed */ + thenDone = 0; + ThenBranch = NULL; + /* else child not processed */ + elseDone = 0; + ElseBranch = NULL; + /* if then child constant, branch is the child */ + if (Cudd_IsConstant(Nv)) { + /*shortest path found */ + if ((Nv == DD_ONE(dd)) && (info->findShortestPath)) { + info->findShortestPath = 0; + } + + ThenBranch = Nv; + cuddRef(ThenBranch); + if (ThenBranch == NULL) { + return(NULL); + } + + thenDone++; + processingDone++; + NvBotDist = MAXSHORTINT; + } else { + /* Derive regular child for table lookup. */ + regNv = Cudd_Regular(Nv); + /* Get node data for shortest path length. */ + if (!st_lookup(pathTable, (char *)regNv, (char **)&nodeStatNv) ) { + (void) fprintf(dd->err, "Something wrong, node must be in table\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + /* Derive shortest path length for child. */ + if ((nodeStatNv->oddTopDist != MAXSHORTINT) && + (nodeStatNv->oddBotDist != MAXSHORTINT)) { + oddLen = (nodeStatNv->oddTopDist + nodeStatNv->oddBotDist); + } else { + oddLen = MAXSHORTINT; + } + + if ((nodeStatNv->evenTopDist != MAXSHORTINT) && + (nodeStatNv->evenBotDist != MAXSHORTINT)) { + evenLen = (nodeStatNv->evenTopDist +nodeStatNv->evenBotDist); + } else { + evenLen = MAXSHORTINT; + } + + NvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; + NvBotDist = (oddLen <= evenLen) ? nodeStatNv->oddBotDist: + nodeStatNv->evenBotDist; + } + /* if else child constant, branch is the child */ + if (Cudd_IsConstant(Nnv)) { + /*shortest path found */ + if ((Nnv == DD_ONE(dd)) && (info->findShortestPath)) { + info->findShortestPath = 0; + } + + ElseBranch = Nnv; + cuddRef(ElseBranch); + if (ElseBranch == NULL) { + return(NULL); + } + + elseDone++; + processingDone++; + NnvBotDist = MAXSHORTINT; + } else { + /* Derive regular child for table lookup. */ + regNnv = Cudd_Regular(Nnv); + /* Get node data for shortest path length. */ + if (!st_lookup(pathTable, (char *)regNnv, (char **)&nodeStatNnv) ) { + (void) fprintf(dd->err, "Something wrong, node must be in table\n"); + dd->errorCode = CUDD_INTERNAL_ERROR; + return(NULL); + } + /* Derive shortest path length for child. */ + if ((nodeStatNnv->oddTopDist != MAXSHORTINT) && + (nodeStatNnv->oddBotDist != MAXSHORTINT)) { + oddLen = (nodeStatNnv->oddTopDist + nodeStatNnv->oddBotDist); + } else { + oddLen = MAXSHORTINT; + } + + if ((nodeStatNnv->evenTopDist != MAXSHORTINT) && + (nodeStatNnv->evenBotDist != MAXSHORTINT)) { + evenLen = (nodeStatNnv->evenTopDist +nodeStatNnv->evenBotDist); + } else { + evenLen = MAXSHORTINT; + } + + NnvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; + NnvBotDist = (oddLen <= evenLen) ? nodeStatNnv->oddBotDist : + nodeStatNnv->evenBotDist; + } + + tiebreakChild = (NvBotDist <= NnvBotDist) ? 1 : 0; + /* while both children not processed */ + while (processingDone != 2) { + if (!processingDone) { + /* if no child processed */ + /* pick the child with shortest path length and record which one + * picked + */ + if ((NvPathLength < NnvPathLength) || + ((NvPathLength == NnvPathLength) && (tiebreakChild == 1))) { + child = Nv; + regChild = regNv; + thenDone = 1; + childPathLength = NvPathLength; + } else { + child = Nnv; + regChild = regNnv; + elseDone = 1; + childPathLength = NnvPathLength; + } /* then path length less than else path length */ + } else { + /* if one child processed, process the other */ + if (thenDone) { + child = Nnv; + regChild = regNnv; + elseDone = 1; + childPathLength = NnvPathLength; + } else { + child = Nv; + regChild = regNv; + thenDone = 1; + childPathLength = NvPathLength; + } /* end of else pick the Then child if ELSE child processed */ + } /* end of else one child has been processed */ + + /* ignore (replace with constant 0) all nodes which lie on paths larger + * than the maximum length of the path required + */ + if (childPathLength > info->maxpath) { + /* record nodes visited */ + childBranch = zero; + } else { + if (childPathLength < info->maxpath) { + if (info->findShortestPath) { + info->findShortestPath = 0; + } + childBranch = BuildSubsetBdd(dd, pathTable, child, info, + subsetNodeTable); + + } else { /* Case: path length of node = maxpath */ + /* If the node labeled with maxpath is found in the + ** maxpathTable, use it to build the subset BDD. */ + if (st_lookup(info->maxpathTable, (char *)regChild, + (char **)&entry)) { + /* When a node that is already been chosen is hit, + ** the quest for a complete path is over. */ + if (info->findShortestPath) { + info->findShortestPath = 0; + } + childBranch = BuildSubsetBdd(dd, pathTable, child, info, + subsetNodeTable); + } else { + /* If node is not found in the maxpathTable and + ** the threshold has been reached, then if the + ** path needs to be completed, continue. Else + ** replace the node with a zero. */ + if (info->thresholdReached <= 0) { + if (info->findShortestPath) { + if (st_insert(info->maxpathTable, (char *)regChild, + (char *)NIL(char)) == ST_OUT_OF_MEM) { + memOut = 1; + (void) fprintf(dd->err, "OUT of memory\n"); + info->thresholdReached = 0; + childBranch = zero; + } else { + info->thresholdReached--; + childBranch = BuildSubsetBdd(dd, pathTable, + child, info,subsetNodeTable); + } + } else { /* not find shortest path, we dont need this + node */ + childBranch = zero; + } + } else { /* Threshold hasn't been reached, + ** need the node. */ + if (st_insert(info->maxpathTable, (char *)regChild, + (char *)NIL(char)) == ST_OUT_OF_MEM) { + memOut = 1; + (void) fprintf(dd->err, "OUT of memory\n"); + info->thresholdReached = 0; + childBranch = zero; + } else { + info->thresholdReached--; + if (info->thresholdReached <= 0) { + info->findShortestPath = 1; + } + childBranch = BuildSubsetBdd(dd, pathTable, + child, info, subsetNodeTable); + + } /* end of st_insert successful */ + } /* end of threshold hasnt been reached yet */ + } /* end of else node not found in maxpath table */ + } /* end of if (path length of node = maxpath) */ + } /* end if !(childPathLength > maxpath) */ + if (childBranch == NULL) { + /* deref other stuff incase reordering has taken place */ + if (ThenBranch != NULL) { + Cudd_RecursiveDeref(dd, ThenBranch); + ThenBranch = NULL; + } + if (ElseBranch != NULL) { + Cudd_RecursiveDeref(dd, ElseBranch); + ElseBranch = NULL; + } + return(NULL); + } + + cuddRef(childBranch); + + if (child == Nv) { + ThenBranch = childBranch; + } else { + ElseBranch = childBranch; + } + processingDone++; + + } /*end of while processing Nv, Nnv */ + + info->findShortestPath = 0; + topid = Cudd_NodeReadIndex(N); + topv = Cudd_ReadVars(dd, topid); + cuddRef(topv); + neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); + if (neW != NULL) { + cuddRef(neW); + } + Cudd_RecursiveDeref(dd, topv); + Cudd_RecursiveDeref(dd, ThenBranch); + Cudd_RecursiveDeref(dd, ElseBranch); + + + /* Hard Limit of threshold has been imposed */ + if (subsetNodeTable != NIL(st_table)) { + /* check if a new node is created */ + regNew = Cudd_Regular(neW); + /* subset node table keeps all new nodes that have been created to keep + * a running count of how many nodes have been built in the subset. + */ + if (!st_lookup(subsetNodeTable, (char *)regNew, (char **)&entry)) { + if (!Cudd_IsConstant(regNew)) { + if (st_insert(subsetNodeTable, (char *)regNew, + (char *)NULL) == ST_OUT_OF_MEM) { + (void) fprintf(dd->err, "Out of memory\n"); + return (NULL); + } + if (st_count(subsetNodeTable) > info->threshold) { + info->thresholdReached = 0; + } + } + } + } + + + if (neW == NULL) { + return(NULL); + } else { + /*store computed result in regular form*/ + if (Cudd_IsComplement(node)) { + nodeStat->compResult = neW; + cuddRef(nodeStat->compResult); + /* if the new node is the same as the corresponding node in the + * original bdd then its complement need not be computed as it + * cannot be larger than the node itself + */ + if (neW == node) { +#ifdef DD_DEBUG + thishit++; +#endif + /* if a result for the node has already been computed, then + * it can only be smaller than teh node itself. hence store + * the node result in order not to break recombination + */ + if (nodeStat->regResult != NULL) { + Cudd_RecursiveDeref(dd, nodeStat->regResult); + } + nodeStat->regResult = Cudd_Not(neW); + cuddRef(nodeStat->regResult); + } + + } else { + nodeStat->regResult = neW; + cuddRef(nodeStat->regResult); + if (neW == node) { +#ifdef DD_DEBUG + thishit++; +#endif + if (nodeStat->compResult != NULL) { + Cudd_RecursiveDeref(dd, nodeStat->compResult); + } + nodeStat->compResult = Cudd_Not(neW); + cuddRef(nodeStat->compResult); + } + } + + cuddDeref(neW); + return(neW); + } /* end of else i.e. Subset != NULL */ +} /* end of BuildSubsetBdd */ + + +/**Function******************************************************************** + + Synopsis [Procedure to free te result dds stored in the NodeDist pages.] + + Description [None] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static enum st_retval +stPathTableDdFree( + char * key, + char * value, + char * arg) +{ + NodeDist_t *nodeStat; + DdManager *dd; + + nodeStat = (NodeDist_t *)value; + dd = (DdManager *)arg; + if (nodeStat->regResult != NULL) { + Cudd_RecursiveDeref(dd, nodeStat->regResult); + } + if (nodeStat->compResult != NULL) { + Cudd_RecursiveDeref(dd, nodeStat->compResult); + } + return(ST_CONTINUE); + +} /* end of stPathTableFree */ diff --git a/abc70930/src/bdd/cudd/cuddSymmetry.c b/abc70930/src/bdd/cudd/cuddSymmetry.c new file mode 100644 index 00000000..e5488b17 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddSymmetry.c @@ -0,0 +1,1668 @@ +/**CFile*********************************************************************** + + FileName [cuddSymmetry.c] + + PackageName [cudd] + + Synopsis [Functions for symmetry-based variable reordering.] + + Description [External procedures included in this file: +
          +
        • Cudd_SymmProfile() +
        + Internal procedures included in this module: +
          +
        • cuddSymmCheck() +
        • cuddSymmSifting() +
        • cuddSymmSiftingConv() +
        + Static procedures included in this module: +
          +
        • ddSymmUniqueCompare() +
        • ddSymmSiftingAux() +
        • ddSymmSiftingConvAux() +
        • ddSymmSiftingUp() +
        • ddSymmSiftingDown() +
        • ddSymmGroupMove() +
        • ddSymmGroupMoveBackward() +
        • ddSymmSiftingBackward() +
        • ddSymmSummary() +
        ] + + Author [Shipra Panda, Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define MV_OOM (Move *)1 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +static int *entry; + +extern int ddTotalNumberSwapping; +#ifdef DD_STATS +extern int ddTotalNISwaps; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int ddSymmUniqueCompare ARGS((int *ptrX, int *ptrY)); +static int ddSymmSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); +static int ddSymmSiftingConvAux ARGS((DdManager *table, int x, int xLow, int xHigh)); +static Move * ddSymmSiftingUp ARGS((DdManager *table, int y, int xLow)); +static Move * ddSymmSiftingDown ARGS((DdManager *table, int x, int xHigh)); +static int ddSymmGroupMove ARGS((DdManager *table, int x, int y, Move **moves)); +static int ddSymmGroupMoveBackward ARGS((DdManager *table, int x, int y)); +static int ddSymmSiftingBackward ARGS((DdManager *table, Move *moves, int size)); +static void ddSymmSummary ARGS((DdManager *table, int lower, int upper, int *symvars, int *symgroups)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Prints statistics on symmetric variables.] + + Description [] + + SideEffects [None] + +******************************************************************************/ +void +Cudd_SymmProfile( + DdManager * table, + int lower, + int upper) +{ + int i,x,gbot; + int TotalSymm = 0; + int TotalSymmGroups = 0; + + for (i = lower; i <= upper; i++) { + if (table->subtables[i].next != (unsigned) i) { + x = i; + (void) fprintf(table->out,"Group:"); + do { + (void) fprintf(table->out," %d",table->invperm[x]); + TotalSymm++; + gbot = x; + x = table->subtables[x].next; + } while (x != i); + TotalSymmGroups++; +#ifdef DD_DEBUG + assert(table->subtables[gbot].next == (unsigned) i); +#endif + i = gbot; + (void) fprintf(table->out,"\n"); + } + } + (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm); + (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups); + +} /* end of Cudd_SymmProfile */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Checks for symmetry of x and y.] + + Description [Checks for symmetry of x and y. Ignores projection + functions, unless they are isolated. Returns 1 in case of symmetry; 0 + otherwise.] + + SideEffects [None] + +******************************************************************************/ +int +cuddSymmCheck( + DdManager * table, + int x, + int y) +{ + DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10; + int comple; /* f0 is complemented */ + int xsymmy; /* x and y may be positively symmetric */ + int xsymmyp; /* x and y may be negatively symmetric */ + int arccount; /* number of arcs from layer x to layer y */ + int TotalRefCount; /* total reference count of layer y minus 1 */ + int yindex; + int i; + DdNodePtr *list; + int slots; + DdNode *sentinel = &(table->sentinel); +#ifdef DD_DEBUG + int xindex; +#endif + + /* Checks that x and y are not the projection functions. + ** For x it is sufficient to check whether there is only one + ** node; indeed, if there is one node, it is the projection function + ** and it cannot point to y. Hence, if y isn't just the projection + ** function, it has one arc coming from a layer different from x. + */ + if (table->subtables[x].keys == 1) { + return(0); + } + yindex = table->invperm[y]; + if (table->subtables[y].keys == 1) { + if (table->vars[yindex]->ref == 1) + return(0); + } + + xsymmy = xsymmyp = 1; + arccount = 0; + slots = table->subtables[x].slots; + list = table->subtables[x].nodelist; + for (i = 0; i < slots; i++) { + f = list[i]; + while (f != sentinel) { + /* Find f1, f0, f11, f10, f01, f00. */ + f1 = cuddT(f); + f0 = Cudd_Regular(cuddE(f)); + comple = Cudd_IsComplement(cuddE(f)); + if ((int) f1->index == yindex) { + arccount++; + f11 = cuddT(f1); f10 = cuddE(f1); + } else { + if ((int) f0->index != yindex) { + /* If f is an isolated projection function it is + ** allowed to bypass layer y. + */ + if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) + return(0); /* f bypasses layer y */ + } + f11 = f10 = f1; + } + if ((int) f0->index == yindex) { + arccount++; + f01 = cuddT(f0); f00 = cuddE(f0); + } else { + f01 = f00 = f0; + } + if (comple) { + f01 = Cudd_Not(f01); + f00 = Cudd_Not(f00); + } + + if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) { + xsymmy &= f01 == f10; + xsymmyp &= f11 == f00; + if ((xsymmy == 0) && (xsymmyp == 0)) + return(0); + } + + f = f->next; + } /* while */ + } /* for */ + + /* Calculate the total reference counts of y */ + TotalRefCount = -1; /* -1 for projection function */ + slots = table->subtables[y].slots; + list = table->subtables[y].nodelist; + for (i = 0; i < slots; i++) { + f = list[i]; + while (f != sentinel) { + TotalRefCount += f->ref; + f = f->next; + } + } + +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + if (arccount == TotalRefCount) { + xindex = table->invperm[x]; + (void) fprintf(table->out, + "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", + xindex,yindex,x,y); + } +#endif + + return(arccount == TotalRefCount); + +} /* end of cuddSymmCheck */ + + +/**Function******************************************************************** + + Synopsis [Symmetric sifting algorithm.] + + Description [Symmetric sifting algorithm. + Assumes that no dead nodes are present. +
          +
        1. Order all the variables according to the number of entries in + each unique subtable. +
        2. Sift the variable up and down, remembering each time the total + size of the DD heap and grouping variables that are symmetric. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        + Returns 1 plus the number of symmetric variables if successful; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [cuddSymmSiftingConv] + +******************************************************************************/ +int +cuddSymmSifting( + DdManager * table, + int lower, + int upper) +{ + int i; + int *var; + int size; + int x; + int result; + int symvars; + int symgroups; +#ifdef DD_STATS + int previousSize; +#endif + + size = table->size; + + /* Find order in which to sift variables. */ + var = NULL; + entry = ALLOC(int,size); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto ddSymmSiftingOutOfMem; + } + var = ALLOC(int,size); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto ddSymmSiftingOutOfMem; + } + + for (i = 0; i < size; i++) { + x = table->perm[i]; + entry[i] = table->subtables[x].keys; + var[i] = i; + } + + qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare); + + /* Initialize the symmetry of each subtable to itself. */ + for (i = lower; i <= upper; i++) { + table->subtables[i].next = i; + } + + for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { + if (ddTotalNumberSwapping >= table->siftMaxSwap) + break; + x = table->perm[var[i]]; +#ifdef DD_STATS + previousSize = table->keys - table->isolated; +#endif + if (x < lower || x > upper) continue; + if (table->subtables[x].next == (unsigned) x) { + result = ddSymmSiftingAux(table,x,lower,upper); + if (!result) goto ddSymmSiftingOutOfMem; +#ifdef DD_STATS + if (table->keys < (unsigned) previousSize + table->isolated) { + (void) fprintf(table->out,"-"); + } else if (table->keys > (unsigned) previousSize + + table->isolated) { + (void) fprintf(table->out,"+"); /* should never happen */ + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + } + + FREE(var); + FREE(entry); + + ddSymmSummary(table, lower, upper, &symvars, &symgroups); + +#ifdef DD_STATS + (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", + symvars); + (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", + symgroups); +#endif + + return(1+symvars); + +ddSymmSiftingOutOfMem: + + if (entry != NULL) FREE(entry); + if (var != NULL) FREE(var); + + return(0); + +} /* end of cuddSymmSifting */ + + +/**Function******************************************************************** + + Synopsis [Symmetric sifting to convergence algorithm.] + + Description [Symmetric sifting to convergence algorithm. + Assumes that no dead nodes are present. +
          +
        1. Order all the variables according to the number of entries in + each unique subtable. +
        2. Sift the variable up and down, remembering each time the total + size of the DD heap and grouping variables that are symmetric. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        5. Repeat 1-4 until no further improvement. +
        + Returns 1 plus the number of symmetric variables if successful; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [cuddSymmSifting] + +******************************************************************************/ +int +cuddSymmSiftingConv( + DdManager * table, + int lower, + int upper) +{ + int i; + int *var; + int size; + int x; + int result; + int symvars; + int symgroups; + int classes; + int initialSize; +#ifdef DD_STATS + int previousSize; +#endif + + initialSize = table->keys - table->isolated; + + size = table->size; + + /* Find order in which to sift variables. */ + var = NULL; + entry = ALLOC(int,size); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto ddSymmSiftingConvOutOfMem; + } + var = ALLOC(int,size); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto ddSymmSiftingConvOutOfMem; + } + + for (i = 0; i < size; i++) { + x = table->perm[i]; + entry[i] = table->subtables[x].keys; + var[i] = i; + } + + qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare); + + /* Initialize the symmetry of each subtable to itself + ** for first pass of converging symmetric sifting. + */ + for (i = lower; i <= upper; i++) { + table->subtables[i].next = i; + } + + for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) { + if (ddTotalNumberSwapping >= table->siftMaxSwap) + break; + x = table->perm[var[i]]; + if (x < lower || x > upper) continue; + /* Only sift if not in symmetry group already. */ + if (table->subtables[x].next == (unsigned) x) { +#ifdef DD_STATS + previousSize = table->keys - table->isolated; +#endif + result = ddSymmSiftingAux(table,x,lower,upper); + if (!result) goto ddSymmSiftingConvOutOfMem; +#ifdef DD_STATS + if (table->keys < (unsigned) previousSize + table->isolated) { + (void) fprintf(table->out,"-"); + } else if (table->keys > (unsigned) previousSize + + table->isolated) { + (void) fprintf(table->out,"+"); + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + } + + /* Sifting now until convergence. */ + while ((unsigned) initialSize > table->keys - table->isolated) { + initialSize = table->keys - table->isolated; +#ifdef DD_STATS + (void) fprintf(table->out,"\n"); +#endif + /* Here we consider only one representative for each symmetry class. */ + for (x = lower, classes = 0; x <= upper; x++, classes++) { + while ((unsigned) x < table->subtables[x].next) { + x = table->subtables[x].next; + } + /* Here x is the largest index in a group. + ** Groups consist of adjacent variables. + ** Hence, the next increment of x will move it to a new group. + */ + i = table->invperm[x]; + entry[i] = table->subtables[x].keys; + var[classes] = i; + } + + qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare); + + /* Now sift. */ + for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { + if (ddTotalNumberSwapping >= table->siftMaxSwap) + break; + x = table->perm[var[i]]; + if ((unsigned) x >= table->subtables[x].next) { +#ifdef DD_STATS + previousSize = table->keys - table->isolated; +#endif + result = ddSymmSiftingConvAux(table,x,lower,upper); + if (!result ) goto ddSymmSiftingConvOutOfMem; +#ifdef DD_STATS + if (table->keys < (unsigned) previousSize + table->isolated) { + (void) fprintf(table->out,"-"); + } else if (table->keys > (unsigned) previousSize + + table->isolated) { + (void) fprintf(table->out,"+"); + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + } /* for */ + } + + ddSymmSummary(table, lower, upper, &symvars, &symgroups); + +#ifdef DD_STATS + (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", + symvars); + (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", + symgroups); +#endif + + FREE(var); + FREE(entry); + + return(1+symvars); + +ddSymmSiftingConvOutOfMem: + + if (entry != NULL) FREE(entry); + if (var != NULL) FREE(var); + + return(0); + +} /* end of cuddSymmSiftingConv */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Comparison function used by qsort.] + + Description [Comparison function used by qsort to order the variables + according to the number of keys in the subtables. + Returns the difference in number of keys between the two + variables being compared.] + + SideEffects [None] + +******************************************************************************/ +static int +ddSymmUniqueCompare( + int * ptrX, + int * ptrY) +{ +#if 0 + if (entry[*ptrY] == entry[*ptrX]) { + return((*ptrX) - (*ptrY)); + } +#endif + return(entry[*ptrY] - entry[*ptrX]); + +} /* end of ddSymmUniqueCompare */ + + +/**Function******************************************************************** + + Synopsis [Given xLow <= x <= xHigh moves x up and down between the + boundaries.] + + Description [Given xLow <= x <= xHigh moves x up and down between the + boundaries. Finds the best position and does the required changes. + Assumes that x is not part of a symmetry group. Returns 1 if + successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddSymmSiftingAux( + DdManager * table, + int x, + int xLow, + int xHigh) +{ + Move *move; + Move *moveUp; /* list of up moves */ + Move *moveDown; /* list of down moves */ + int initialSize; + int result; + int i; + int topbot; /* index to either top or bottom of symmetry group */ + int initGroupSize, finalGroupSize; + + +#ifdef DD_DEBUG + /* check for previously detected symmetry */ + assert(table->subtables[x].next == (unsigned) x); +#endif + + initialSize = table->keys - table->isolated; + + moveDown = NULL; + moveUp = NULL; + + if ((x - xLow) > (xHigh - x)) { + /* Will go down first, unless x == xHigh: + ** Look for consecutive symmetries above x. + */ + for (i = x; i > xLow; i--) { + if (!cuddSymmCheck(table,i-1,i)) + break; + topbot = table->subtables[i-1].next; /* find top of i-1's group */ + table->subtables[i-1].next = i; + table->subtables[x].next = topbot; /* x is bottom of group so its */ + /* next is top of i-1's group */ + i = topbot + 1; /* add 1 for i--; new i is top of symm group */ + } + } else { + /* Will go up first unless x == xlow: + ** Look for consecutive symmetries below x. + */ + for (i = x; i < xHigh; i++) { + if (!cuddSymmCheck(table,i,i+1)) + break; + /* find bottom of i+1's symm group */ + topbot = i + 1; + while ((unsigned) topbot < table->subtables[topbot].next) { + topbot = table->subtables[topbot].next; + } + table->subtables[topbot].next = table->subtables[i].next; + table->subtables[i].next = i + 1; + i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */ + } + } + + /* Now x may be in the middle of a symmetry group. + ** Find bottom of x's symm group. + */ + while ((unsigned) x < table->subtables[x].next) + x = table->subtables[x].next; + + if (x == xLow) { /* Sift down */ + +#ifdef DD_DEBUG + /* x must be a singleton */ + assert((unsigned) x == table->subtables[x].next); +#endif + if (x == xHigh) return(1); /* just one variable */ + + initGroupSize = 1; + + moveDown = ddSymmSiftingDown(table,x,xHigh); + /* after this point x --> xHigh, unless early term */ + if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; + if (moveDown == NULL) return(1); + + x = moveDown->y; + /* Find bottom of x's group */ + i = x; + while ((unsigned) i < table->subtables[i].next) { + i = table->subtables[i].next; + } +#ifdef DD_DEBUG + /* x should be the top of the symmetry group and i the bottom */ + assert((unsigned) i >= table->subtables[i].next); + assert((unsigned) x == table->subtables[i].next); +#endif + finalGroupSize = i - x + 1; + + if (initGroupSize == finalGroupSize) { + /* No new symmetry groups detected, return to best position */ + result = ddSymmSiftingBackward(table,moveDown,initialSize); + } else { + initialSize = table->keys - table->isolated; + moveUp = ddSymmSiftingUp(table,x,xLow); + result = ddSymmSiftingBackward(table,moveUp,initialSize); + } + if (!result) goto ddSymmSiftingAuxOutOfMem; + + } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ + /* Find top of x's symm group */ + i = x; /* bottom */ + x = table->subtables[x].next; /* top */ + + if (x == xLow) return(1); /* just one big group */ + + initGroupSize = i - x + 1; + + moveUp = ddSymmSiftingUp(table,x,xLow); + /* after this point x --> xLow, unless early term */ + if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; + if (moveUp == NULL) return(1); + + x = moveUp->x; + /* Find top of x's group */ + i = table->subtables[x].next; +#ifdef DD_DEBUG + /* x should be the bottom of the symmetry group and i the top */ + assert((unsigned) x >= table->subtables[x].next); + assert((unsigned) i == table->subtables[x].next); +#endif + finalGroupSize = x - i + 1; + + if (initGroupSize == finalGroupSize) { + /* No new symmetry groups detected, return to best position */ + result = ddSymmSiftingBackward(table,moveUp,initialSize); + } else { + initialSize = table->keys - table->isolated; + moveDown = ddSymmSiftingDown(table,x,xHigh); + result = ddSymmSiftingBackward(table,moveDown,initialSize); + } + if (!result) goto ddSymmSiftingAuxOutOfMem; + + } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ + + moveDown = ddSymmSiftingDown(table,x,xHigh); + /* at this point x == xHigh, unless early term */ + if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; + + if (moveDown != NULL) { + x = moveDown->y; /* x is top here */ + i = x; + while ((unsigned) i < table->subtables[i].next) { + i = table->subtables[i].next; + } + } else { + i = x; + while ((unsigned) i < table->subtables[i].next) { + i = table->subtables[i].next; + } + x = table->subtables[i].next; + } +#ifdef DD_DEBUG + /* x should be the top of the symmetry group and i the bottom */ + assert((unsigned) i >= table->subtables[i].next); + assert((unsigned) x == table->subtables[i].next); +#endif + initGroupSize = i - x + 1; + + moveUp = ddSymmSiftingUp(table,x,xLow); + if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; + + if (moveUp != NULL) { + x = moveUp->x; + i = table->subtables[x].next; + } else { + i = x; + while ((unsigned) x < table->subtables[x].next) + x = table->subtables[x].next; + } +#ifdef DD_DEBUG + /* x should be the bottom of the symmetry group and i the top */ + assert((unsigned) x >= table->subtables[x].next); + assert((unsigned) i == table->subtables[x].next); +#endif + finalGroupSize = x - i + 1; + + if (initGroupSize == finalGroupSize) { + /* No new symmetry groups detected, return to best position */ + result = ddSymmSiftingBackward(table,moveUp,initialSize); + } else { + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *) moveDown); + moveDown = move; + } + initialSize = table->keys - table->isolated; + moveDown = ddSymmSiftingDown(table,x,xHigh); + result = ddSymmSiftingBackward(table,moveDown,initialSize); + } + if (!result) goto ddSymmSiftingAuxOutOfMem; + + } else { /* moving up first: shorter */ + /* Find top of x's symmetry group */ + x = table->subtables[x].next; + + moveUp = ddSymmSiftingUp(table,x,xLow); + /* at this point x == xHigh, unless early term */ + if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; + + if (moveUp != NULL) { + x = moveUp->x; + i = table->subtables[x].next; + } else { + while ((unsigned) x < table->subtables[x].next) + x = table->subtables[x].next; + i = table->subtables[x].next; + } +#ifdef DD_DEBUG + /* x is bottom of the symmetry group and i is top */ + assert((unsigned) x >= table->subtables[x].next); + assert((unsigned) i == table->subtables[x].next); +#endif + initGroupSize = x - i + 1; + + moveDown = ddSymmSiftingDown(table,x,xHigh); + if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; + + if (moveDown != NULL) { + x = moveDown->y; + i = x; + while ((unsigned) i < table->subtables[i].next) { + i = table->subtables[i].next; + } + } else { + i = x; + x = table->subtables[x].next; + } +#ifdef DD_DEBUG + /* x should be the top of the symmetry group and i the bottom */ + assert((unsigned) i >= table->subtables[i].next); + assert((unsigned) x == table->subtables[i].next); +#endif + finalGroupSize = i - x + 1; + + if (initGroupSize == finalGroupSize) { + /* No new symmetries detected, go back to best position */ + result = ddSymmSiftingBackward(table,moveDown,initialSize); + } else { + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *) moveUp); + moveUp = move; + } + initialSize = table->keys - table->isolated; + moveUp = ddSymmSiftingUp(table,x,xLow); + result = ddSymmSiftingBackward(table,moveUp,initialSize); + } + if (!result) goto ddSymmSiftingAuxOutOfMem; + } + + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *) moveDown); + moveDown = move; + } + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *) moveUp); + moveUp = move; + } + + return(1); + +ddSymmSiftingAuxOutOfMem: + if (moveDown != MV_OOM) { + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *) moveDown); + moveDown = move; + } + } + if (moveUp != MV_OOM) { + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *) moveUp); + moveUp = move; + } + } + + return(0); + +} /* end of ddSymmSiftingAux */ + + +/**Function******************************************************************** + + Synopsis [Given xLow <= x <= xHigh moves x up and down between the + boundaries.] + + Description [Given xLow <= x <= xHigh moves x up and down between the + boundaries. Finds the best position and does the required changes. + Assumes that x is either an isolated variable, or it is the bottom of + a symmetry group. All symmetries may not have been found, because of + exceeded growth limit. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddSymmSiftingConvAux( + DdManager * table, + int x, + int xLow, + int xHigh) +{ + Move *move; + Move *moveUp; /* list of up moves */ + Move *moveDown; /* list of down moves */ + int initialSize; + int result; + int i; + int initGroupSize, finalGroupSize; + + + initialSize = table->keys - table->isolated; + + moveDown = NULL; + moveUp = NULL; + + if (x == xLow) { /* Sift down */ +#ifdef DD_DEBUG + /* x is bottom of symmetry group */ + assert((unsigned) x >= table->subtables[x].next); +#endif + i = table->subtables[x].next; + initGroupSize = x - i + 1; + + moveDown = ddSymmSiftingDown(table,x,xHigh); + /* at this point x == xHigh, unless early term */ + if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; + if (moveDown == NULL) return(1); + + x = moveDown->y; + i = x; + while ((unsigned) i < table->subtables[i].next) { + i = table->subtables[i].next; + } +#ifdef DD_DEBUG + /* x should be the top of the symmetric group and i the bottom */ + assert((unsigned) i >= table->subtables[i].next); + assert((unsigned) x == table->subtables[i].next); +#endif + finalGroupSize = i - x + 1; + + if (initGroupSize == finalGroupSize) { + /* No new symmetries detected, go back to best position */ + result = ddSymmSiftingBackward(table,moveDown,initialSize); + } else { + initialSize = table->keys - table->isolated; + moveUp = ddSymmSiftingUp(table,x,xLow); + result = ddSymmSiftingBackward(table,moveUp,initialSize); + } + if (!result) goto ddSymmSiftingConvAuxOutOfMem; + + } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ + /* Find top of x's symm group */ + while ((unsigned) x < table->subtables[x].next) + x = table->subtables[x].next; + i = x; /* bottom */ + x = table->subtables[x].next; /* top */ + + if (x == xLow) return(1); + + initGroupSize = i - x + 1; + + moveUp = ddSymmSiftingUp(table,x,xLow); + /* at this point x == xLow, unless early term */ + if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; + if (moveUp == NULL) return(1); + + x = moveUp->x; + i = table->subtables[x].next; +#ifdef DD_DEBUG + /* x should be the bottom of the symmetry group and i the top */ + assert((unsigned) x >= table->subtables[x].next); + assert((unsigned) i == table->subtables[x].next); +#endif + finalGroupSize = x - i + 1; + + if (initGroupSize == finalGroupSize) { + /* No new symmetry groups detected, return to best position */ + result = ddSymmSiftingBackward(table,moveUp,initialSize); + } else { + initialSize = table->keys - table->isolated; + moveDown = ddSymmSiftingDown(table,x,xHigh); + result = ddSymmSiftingBackward(table,moveDown,initialSize); + } + if (!result) + goto ddSymmSiftingConvAuxOutOfMem; + + } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ + moveDown = ddSymmSiftingDown(table,x,xHigh); + /* at this point x == xHigh, unless early term */ + if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; + + if (moveDown != NULL) { + x = moveDown->y; + i = x; + while ((unsigned) i < table->subtables[i].next) { + i = table->subtables[i].next; + } + } else { + while ((unsigned) x < table->subtables[x].next) + x = table->subtables[x].next; + i = x; + x = table->subtables[x].next; + } +#ifdef DD_DEBUG + /* x should be the top of the symmetry group and i the bottom */ + assert((unsigned) i >= table->subtables[i].next); + assert((unsigned) x == table->subtables[i].next); +#endif + initGroupSize = i - x + 1; + + moveUp = ddSymmSiftingUp(table,x,xLow); + if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; + + if (moveUp != NULL) { + x = moveUp->x; + i = table->subtables[x].next; + } else { + i = x; + while ((unsigned) x < table->subtables[x].next) + x = table->subtables[x].next; + } +#ifdef DD_DEBUG + /* x should be the bottom of the symmetry group and i the top */ + assert((unsigned) x >= table->subtables[x].next); + assert((unsigned) i == table->subtables[x].next); +#endif + finalGroupSize = x - i + 1; + + if (initGroupSize == finalGroupSize) { + /* No new symmetry groups detected, return to best position */ + result = ddSymmSiftingBackward(table,moveUp,initialSize); + } else { + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *) moveDown); + moveDown = move; + } + initialSize = table->keys - table->isolated; + moveDown = ddSymmSiftingDown(table,x,xHigh); + result = ddSymmSiftingBackward(table,moveDown,initialSize); + } + if (!result) goto ddSymmSiftingConvAuxOutOfMem; + + } else { /* moving up first: shorter */ + /* Find top of x's symmetry group */ + x = table->subtables[x].next; + + moveUp = ddSymmSiftingUp(table,x,xLow); + /* at this point x == xHigh, unless early term */ + if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; + + if (moveUp != NULL) { + x = moveUp->x; + i = table->subtables[x].next; + } else { + i = x; + while ((unsigned) x < table->subtables[x].next) + x = table->subtables[x].next; + } +#ifdef DD_DEBUG + /* x is bottom of the symmetry group and i is top */ + assert((unsigned) x >= table->subtables[x].next); + assert((unsigned) i == table->subtables[x].next); +#endif + initGroupSize = x - i + 1; + + moveDown = ddSymmSiftingDown(table,x,xHigh); + if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; + + if (moveDown != NULL) { + x = moveDown->y; + i = x; + while ((unsigned) i < table->subtables[i].next) { + i = table->subtables[i].next; + } + } else { + i = x; + x = table->subtables[x].next; + } +#ifdef DD_DEBUG + /* x should be the top of the symmetry group and i the bottom */ + assert((unsigned) i >= table->subtables[i].next); + assert((unsigned) x == table->subtables[i].next); +#endif + finalGroupSize = i - x + 1; + + if (initGroupSize == finalGroupSize) { + /* No new symmetries detected, go back to best position */ + result = ddSymmSiftingBackward(table,moveDown,initialSize); + } else { + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *) moveUp); + moveUp = move; + } + initialSize = table->keys - table->isolated; + moveUp = ddSymmSiftingUp(table,x,xLow); + result = ddSymmSiftingBackward(table,moveUp,initialSize); + } + if (!result) goto ddSymmSiftingConvAuxOutOfMem; + } + + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *) moveDown); + moveDown = move; + } + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *) moveUp); + moveUp = move; + } + + return(1); + +ddSymmSiftingConvAuxOutOfMem: + if (moveDown != MV_OOM) { + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *) moveDown); + moveDown = move; + } + } + if (moveUp != MV_OOM) { + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *) moveUp); + moveUp = move; + } + } + + return(0); + +} /* end of ddSymmSiftingConvAux */ + + +/**Function******************************************************************** + + Synopsis [Moves x up until either it reaches the bound (xLow) or + the size of the DD heap increases too much.] + + Description [Moves x up until either it reaches the bound (xLow) or + the size of the DD heap increases too much. Assumes that x is the top + of a symmetry group. Checks x for symmetry to the adjacent + variables. If symmetry is found, the symmetry group of x is merged + with the symmetry group of the other variable. Returns the set of + moves in case of success; MV_OOM if memory is full.] + + SideEffects [None] + +******************************************************************************/ +static Move * +ddSymmSiftingUp( + DdManager * table, + int y, + int xLow) +{ + Move *moves; + Move *move; + int x; + int size; + int i; + int gxtop,gybot; + int limitSize; + int xindex, yindex; + int zindex; + int z; + int isolated; + int L; /* lower bound on DD size */ +#ifdef DD_DEBUG + int checkL; +#endif + + + moves = NULL; + yindex = table->invperm[y]; + + /* Initialize the lower bound. + ** The part of the DD below the bottom of y' group will not change. + ** The part of the DD above y that does not interact with y will not + ** change. The rest may vanish in the best case, except for + ** the nodes at level xLow, which will not vanish, regardless. + */ + limitSize = L = table->keys - table->isolated; + gybot = y; + while ((unsigned) gybot < table->subtables[gybot].next) + gybot = table->subtables[gybot].next; + for (z = xLow + 1; z <= gybot; z++) { + zindex = table->invperm[z]; + if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { + isolated = table->vars[zindex]->ref == 1; + L -= table->subtables[z].keys - isolated; + } + } + + x = cuddNextLow(table,y); + while (x >= xLow && L <= limitSize) { +#ifdef DD_DEBUG + gybot = y; + while ((unsigned) gybot < table->subtables[gybot].next) + gybot = table->subtables[gybot].next; + checkL = table->keys - table->isolated; + for (z = xLow + 1; z <= gybot; z++) { + zindex = table->invperm[z]; + if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { + isolated = table->vars[zindex]->ref == 1; + checkL -= table->subtables[z].keys - isolated; + } + } + assert(L == checkL); +#endif + gxtop = table->subtables[x].next; + if (cuddSymmCheck(table,x,y)) { + /* Symmetry found, attach symm groups */ + table->subtables[x].next = y; + i = table->subtables[y].next; + while (table->subtables[i].next != (unsigned) y) + i = table->subtables[i].next; + table->subtables[i].next = gxtop; + } else if (table->subtables[x].next == (unsigned) x && + table->subtables[y].next == (unsigned) y) { + /* x and y have self symmetry */ + xindex = table->invperm[x]; + size = cuddSwapInPlace(table,x,y); +#ifdef DD_DEBUG + assert(table->subtables[x].next == (unsigned) x); + assert(table->subtables[y].next == (unsigned) y); +#endif + if (size == 0) goto ddSymmSiftingUpOutOfMem; + /* Update the lower bound. */ + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[xindex]->ref == 1; + L += table->subtables[y].keys - isolated; + } + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddSymmSiftingUpOutOfMem; + move->x = x; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + if ((double) size > (double) limitSize * table->maxGrowth) + return(moves); + if (size < limitSize) limitSize = size; + } else { /* Group move */ + size = ddSymmGroupMove(table,x,y,&moves); + if (size == 0) goto ddSymmSiftingUpOutOfMem; + /* Update the lower bound. */ + z = moves->y; + do { + zindex = table->invperm[z]; + if (cuddTestInteract(table,zindex,yindex)) { + isolated = table->vars[zindex]->ref == 1; + L += table->subtables[z].keys - isolated; + } + z = table->subtables[z].next; + } while (z != (int) moves->y); + if ((double) size > (double) limitSize * table->maxGrowth) + return(moves); + if (size < limitSize) limitSize = size; + } + y = gxtop; + x = cuddNextLow(table,y); + } + + return(moves); + +ddSymmSiftingUpOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return(MV_OOM); + +} /* end of ddSymmSiftingUp */ + + +/**Function******************************************************************** + + Synopsis [Moves x down until either it reaches the bound (xHigh) or + the size of the DD heap increases too much.] + + Description [Moves x down until either it reaches the bound (xHigh) + or the size of the DD heap increases too much. Assumes that x is the + bottom of a symmetry group. Checks x for symmetry to the adjacent + variables. If symmetry is found, the symmetry group of x is merged + with the symmetry group of the other variable. Returns the set of + moves in case of success; MV_OOM if memory is full.] + + SideEffects [None] + +******************************************************************************/ +static Move * +ddSymmSiftingDown( + DdManager * table, + int x, + int xHigh) +{ + Move *moves; + Move *move; + int y; + int size; + int limitSize; + int gxtop,gybot; + int R; /* upper bound on node decrease */ + int xindex, yindex; + int isolated; + int z; + int zindex; +#ifdef DD_DEBUG + int checkR; +#endif + + moves = NULL; + /* Initialize R */ + xindex = table->invperm[x]; + gxtop = table->subtables[x].next; + limitSize = size = table->keys - table->isolated; + R = 0; + for (z = xHigh; z > gxtop; z--) { + zindex = table->invperm[z]; + if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { + isolated = table->vars[zindex]->ref == 1; + R += table->subtables[z].keys - isolated; + } + } + + y = cuddNextHigh(table,x); + while (y <= xHigh && size - R < limitSize) { +#ifdef DD_DEBUG + gxtop = table->subtables[x].next; + checkR = 0; + for (z = xHigh; z > gxtop; z--) { + zindex = table->invperm[z]; + if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { + isolated = table->vars[zindex]->ref == 1; + checkR += table->subtables[z].keys - isolated; + } + } + assert(R == checkR); +#endif + gybot = table->subtables[y].next; + while (table->subtables[gybot].next != (unsigned) y) + gybot = table->subtables[gybot].next; + if (cuddSymmCheck(table,x,y)) { + /* Symmetry found, attach symm groups */ + gxtop = table->subtables[x].next; + table->subtables[x].next = y; + table->subtables[gybot].next = gxtop; + } else if (table->subtables[x].next == (unsigned) x && + table->subtables[y].next == (unsigned) y) { + /* x and y have self symmetry */ + /* Update upper bound on node decrease. */ + yindex = table->invperm[y]; + if (cuddTestInteract(table,xindex,yindex)) { + isolated = table->vars[yindex]->ref == 1; + R -= table->subtables[y].keys - isolated; + } + size = cuddSwapInPlace(table,x,y); +#ifdef DD_DEBUG + assert(table->subtables[x].next == (unsigned) x); + assert(table->subtables[y].next == (unsigned) y); +#endif + if (size == 0) goto ddSymmSiftingDownOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto ddSymmSiftingDownOutOfMem; + move->x = x; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + if ((double) size > (double) limitSize * table->maxGrowth) + return(moves); + if (size < limitSize) limitSize = size; + } else { /* Group move */ + /* Update upper bound on node decrease: first phase. */ + gxtop = table->subtables[x].next; + z = gxtop + 1; + do { + zindex = table->invperm[z]; + if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { + isolated = table->vars[zindex]->ref == 1; + R -= table->subtables[z].keys - isolated; + } + z++; + } while (z <= gybot); + size = ddSymmGroupMove(table,x,y,&moves); + if (size == 0) goto ddSymmSiftingDownOutOfMem; + if ((double) size > (double) limitSize * table->maxGrowth) + return(moves); + if (size < limitSize) limitSize = size; + /* Update upper bound on node decrease: second phase. */ + gxtop = table->subtables[gybot].next; + for (z = gxtop + 1; z <= gybot; z++) { + zindex = table->invperm[z]; + if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { + isolated = table->vars[zindex]->ref == 1; + R += table->subtables[z].keys - isolated; + } + } + } + x = gybot; + y = cuddNextHigh(table,x); + } + + return(moves); + +ddSymmSiftingDownOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return(MV_OOM); + +} /* end of ddSymmSiftingDown */ + + +/**Function******************************************************************** + + Synopsis [Swaps two groups.] + + Description [Swaps two groups. x is assumed to be the bottom variable + of the first group. y is assumed to be the top variable of the second + group. Updates the list of moves. Returns the number of keys in the + table if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddSymmGroupMove( + DdManager * table, + int x, + int y, + Move ** moves) +{ + Move *move; + int size; + int i,j; + int xtop,xbot,xsize,ytop,ybot,ysize,newxtop; + int swapx,swapy; + +#if DD_DEBUG + assert(x < y); /* we assume that x < y */ +#endif + /* Find top, bottom, and size for the two groups. */ + xbot = x; + xtop = table->subtables[x].next; + xsize = xbot - xtop + 1; + ybot = y; + while ((unsigned) ybot < table->subtables[ybot].next) + ybot = table->subtables[ybot].next; + ytop = y; + ysize = ybot - ytop + 1; + + /* Sift the variables of the second group up through the first group. */ + for (i = 1; i <= ysize; i++) { + for (j = 1; j <= xsize; j++) { + size = cuddSwapInPlace(table,x,y); + if (size == 0) return(0); + swapx = x; swapy = y; + y = x; + x = y - 1; + } + y = ytop + i; + x = y - 1; + } + + /* fix symmetries */ + y = xtop; /* ytop is now where xtop used to be */ + for (i = 0; i < ysize-1 ; i++) { + table->subtables[y].next = y + 1; + y = y + 1; + } + table->subtables[y].next = xtop; /* y is bottom of its group, join */ + /* its symmetry to top of its group */ + x = y + 1; + newxtop = x; + for (i = 0; i < xsize - 1 ; i++) { + table->subtables[x].next = x + 1; + x = x + 1; + } + table->subtables[x].next = newxtop; /* x is bottom of its group, join */ + /* its symmetry to top of its group */ + /* Store group move */ + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) return(0); + move->x = swapx; + move->y = swapy; + move->size = size; + move->next = *moves; + *moves = move; + + return(size); + +} /* end of ddSymmGroupMove */ + + +/**Function******************************************************************** + + Synopsis [Undoes the swap of two groups.] + + Description [Undoes the swap of two groups. x is assumed to be the + bottom variable of the first group. y is assumed to be the top + variable of the second group. Returns the number of keys in the table + if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddSymmGroupMoveBackward( + DdManager * table, + int x, + int y) +{ + int size; + int i,j; + int xtop,xbot,xsize,ytop,ybot,ysize,newxtop; + +#if DD_DEBUG + assert(x < y); /* We assume that x < y */ +#endif + + /* Find top, bottom, and size for the two groups. */ + xbot = x; + xtop = table->subtables[x].next; + xsize = xbot - xtop + 1; + ybot = y; + while ((unsigned) ybot < table->subtables[ybot].next) + ybot = table->subtables[ybot].next; + ytop = y; + ysize = ybot - ytop + 1; + + /* Sift the variables of the second group up through the first group. */ + for (i = 1; i <= ysize; i++) { + for (j = 1; j <= xsize; j++) { + size = cuddSwapInPlace(table,x,y); + if (size == 0) return(0); + y = x; + x = cuddNextLow(table,y); + } + y = ytop + i; + x = y - 1; + } + + /* Fix symmetries. */ + y = xtop; + for (i = 0; i < ysize-1 ; i++) { + table->subtables[y].next = y + 1; + y = y + 1; + } + table->subtables[y].next = xtop; /* y is bottom of its group, join */ + /* its symmetry to top of its group */ + x = y + 1; + newxtop = x; + for (i = 0; i < xsize-1 ; i++) { + table->subtables[x].next = x + 1; + x = x + 1; + } + table->subtables[x].next = newxtop; /* x is bottom of its group, join */ + /* its symmetry to top of its group */ + + return(size); + +} /* end of ddSymmGroupMoveBackward */ + + +/**Function******************************************************************** + + Synopsis [Given a set of moves, returns the DD heap to the position + giving the minimum size.] + + Description [Given a set of moves, returns the DD heap to the + position giving the minimum size. In case of ties, returns to the + closest position giving the minimum size. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddSymmSiftingBackward( + DdManager * table, + Move * moves, + int size) +{ + Move *move; + int res; + + for (move = moves; move != NULL; move = move->next) { + if (move->size < size) { + size = move->size; + } + } + + for (move = moves; move != NULL; move = move->next) { + if (move->size == size) return(1); + if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) { + res = cuddSwapInPlace(table,(int)move->x,(int)move->y); +#ifdef DD_DEBUG + assert(table->subtables[move->x].next == move->x); + assert(table->subtables[move->y].next == move->y); +#endif + } else { /* Group move necessary */ + res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y); + } + if (!res) return(0); + } + + return(1); + +} /* end of ddSymmSiftingBackward */ + + +/**Function******************************************************************** + + Synopsis [Counts numbers of symmetric variables and symmetry + groups.] + + Description [] + + SideEffects [None] + +******************************************************************************/ +static void +ddSymmSummary( + DdManager * table, + int lower, + int upper, + int * symvars, + int * symgroups) +{ + int i,x,gbot; + int TotalSymm = 0; + int TotalSymmGroups = 0; + + for (i = lower; i <= upper; i++) { + if (table->subtables[i].next != (unsigned) i) { + TotalSymmGroups++; + x = i; + do { + TotalSymm++; + gbot = x; + x = table->subtables[x].next; + } while (x != i); +#ifdef DD_DEBUG + assert(table->subtables[gbot].next == (unsigned) i); +#endif + i = gbot; + } + } + *symvars = TotalSymm; + *symgroups = TotalSymmGroups; + + return; + +} /* end of ddSymmSummary */ diff --git a/abc70930/src/bdd/cudd/cuddTable.c b/abc70930/src/bdd/cudd/cuddTable.c new file mode 100644 index 00000000..7f14aed1 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddTable.c @@ -0,0 +1,3141 @@ +/**CFile*********************************************************************** + + FileName [cuddTable.c] + + PackageName [cudd] + + Synopsis [Unique table management functions.] + + Description [External procedures included in this module: +
          +
        • Cudd_Prime() +
        + Internal procedures included in this module: +
          +
        • cuddAllocNode() +
        • cuddInitTable() +
        • cuddFreeTable() +
        • cuddGarbageCollect() +
        • cuddGarbageCollectZdd() +
        • cuddZddGetNode() +
        • cuddZddGetNodeIVO() +
        • cuddUniqueInter() +
        • cuddUniqueInterIVO() +
        • cuddUniqueInterZdd() +
        • cuddUniqueConst() +
        • cuddRehash() +
        • cuddShrinkSubtable() +
        • cuddInsertSubtables() +
        • cuddDestroySubtables() +
        • cuddResizeTableZdd() +
        • cuddSlowTableGrowth() +
        + Static procedures included in this module: +
          +
        • ddRehashZdd() +
        • ddResizeTable() +
        • cuddFindParent() +
        • cuddOrderedInsert() +
        • cuddOrderedThread() +
        • cuddRotateLeft() +
        • cuddRotateRight() +
        • cuddDoRebalance() +
        • cuddCheckCollisionOrdering() +
        ] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef DD_UNSORTED_FREE_LIST +/* Constants for red/black trees. */ +#define DD_STACK_SIZE 128 +#define DD_RED 0 +#define DD_BLACK 1 +#define DD_PAGE_SIZE 8192 +#define DD_PAGE_MASK ~(DD_PAGE_SIZE - 1) +#define DD_INSERT_COMPARE(x,y) \ + (((ptruint) (x) & DD_PAGE_MASK) - ((ptruint) (y) & DD_PAGE_MASK)) +#endif + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/* This is a hack for when CUDD_VALUE_TYPE is double */ +typedef union hack { + CUDD_VALUE_TYPE value; + unsigned int bits[2]; +} hack; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddTable.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +#ifndef DD_UNSORTED_FREE_LIST +/* Macros for red/black trees. */ +#define DD_COLOR(p) ((p)->index) +#define DD_IS_BLACK(p) ((p)->index == DD_BLACK) +#define DD_IS_RED(p) ((p)->index == DD_RED) +#define DD_LEFT(p) cuddT(p) +#define DD_RIGHT(p) cuddE(p) +#define DD_NEXT(p) ((p)->next) +#endif + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void ddRehashZdd ARGS((DdManager *unique, int i)); +static int ddResizeTable ARGS((DdManager *unique, int index)); +static int cuddFindParent ARGS((DdManager *table, DdNode *node)); +DD_INLINE static void ddFixLimits ARGS((DdManager *unique)); +static void cuddOrderedInsert ARGS((DdNodePtr *root, DdNodePtr node)); +static DdNode * cuddOrderedThread ARGS((DdNode *root, DdNode *list)); +static void cuddRotateLeft ARGS((DdNodePtr *nodeP)); +static void cuddRotateRight ARGS((DdNodePtr *nodeP)); +static void cuddDoRebalance ARGS((DdNodePtr **stack, int stackN)); +static void ddPatchTree ARGS((DdManager *dd, MtrNode *treenode)); +#ifdef DD_DEBUG +static int cuddCheckCollisionOrdering ARGS((DdManager *unique, int i, int j)); +#endif +static void ddReportRefMess ARGS((DdManager *unique, int i, char *caller)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Returns the next prime >= p.] + + Description [] + + SideEffects [None] + +******************************************************************************/ +unsigned int +Cudd_Prime( + unsigned int p) +{ + int i,pn; + + p--; + do { + p++; + if (p&1) { + pn = 1; + i = 3; + while ((unsigned) (i * i) <= p) { + if (p % i == 0) { + pn = 0; + break; + } + i += 2; + } + } else { + pn = 0; + } + } while (!pn); + return(p); + +} /* end of Cudd_Prime */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Fast storage allocation for DdNodes in the table.] + + Description [Fast storage allocation for DdNodes in the table. The + first 4 bytes of a chunk contain a pointer to the next block; the + rest contains DD_MEM_CHUNK spaces for DdNodes. Returns a pointer to + a new node if successful; NULL is memory is full.] + + SideEffects [None] + + SeeAlso [cuddDynamicAllocNode] + +******************************************************************************/ +DdNode * +cuddAllocNode( + DdManager * unique) +{ + int i; + DdNodePtr *mem; + DdNode *list, *node; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); + + if (unique->nextFree == NULL) { /* free list is empty */ + /* Check for exceeded limits. */ + if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) > + unique->maxLive) { + unique->errorCode = CUDD_TOO_MANY_NODES; + return(NULL); + } + if (unique->stash == NULL || unique->memused > unique->maxmemhard) { + (void) cuddGarbageCollect(unique,1); + mem = NULL; + } + if (unique->nextFree == NULL) { + if (unique->memused > unique->maxmemhard) { + unique->errorCode = CUDD_MAX_MEM_EXCEEDED; + return(NULL); + } + /* Try to allocate a new block. */ + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); + MMoutOfMemory = saveHandler; + if (mem == NULL) { + /* No more memory: Try collecting garbage. If this succeeds, + ** we end up with mem still NULL, but unique->nextFree != + ** NULL. */ + if (cuddGarbageCollect(unique,1) == 0) { + /* Last resort: Free the memory stashed away, if there + ** any. If this succeeeds, mem != NULL and + ** unique->nextFree still NULL. */ + if (unique->stash != NULL) { + FREE(unique->stash); + unique->stash = NULL; + /* Inhibit resizing of tables. */ + cuddSlowTableGrowth(unique); + /* Now try again. */ + mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); + } + if (mem == NULL) { + /* Out of luck. Call the default handler to do + ** whatever it specifies for a failed malloc. + ** If this handler returns, then set error code, + ** print warning, and return. */ + (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); + unique->errorCode = CUDD_MEMORY_OUT; +#ifdef DD_VERBOSE + (void) fprintf(unique->err, + "cuddAllocNode: out of memory"); + (void) fprintf(unique->err, "Memory in use = %ld\n", + unique->memused); +#endif + return(NULL); + } + } + } + if (mem != NULL) { /* successful allocation; slice memory */ + ptruint offset; + unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); + mem[0] = (DdNodePtr) unique->memoryList; + unique->memoryList = mem; + + /* Here we rely on the fact that a DdNode is as large + ** as 4 pointers. */ + offset = (ptruint) mem & (sizeof(DdNode) - 1); + mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); + assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0); + list = (DdNode *) mem; + + i = 1; + do { + list[i - 1].next = &list[i]; + } while (++i < DD_MEM_CHUNK); + + list[DD_MEM_CHUNK-1].next = NULL; + + unique->nextFree = &list[0]; + } + } + } + unique->allocated++; + node = unique->nextFree; + unique->nextFree = node->next; + return(node); + +} /* end of cuddAllocNode */ + + +/**Function******************************************************************** + + Synopsis [Creates and initializes the unique table.] + + Description [Creates and initializes the unique table. Returns a pointer + to the table if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_Init cuddFreeTable] + +******************************************************************************/ +DdManager * +cuddInitTable( + unsigned int numVars /* Initial number of BDD variables (and subtables) */, + unsigned int numVarsZ /* Initial number of ZDD variables (and subtables) */, + unsigned int numSlots /* Initial size of the BDD subtables */, + unsigned int looseUpTo /* Limit for fast table growth */) +{ + DdManager *unique = ALLOC(DdManager,1); + int i, j; + DdNodePtr *nodelist; + DdNode *sentinel; + unsigned int slots; + int shift; + + if (unique == NULL) { + return(NULL); + } + sentinel = &(unique->sentinel); + sentinel->ref = 0; + sentinel->index = 0; + cuddT(sentinel) = NULL; + cuddE(sentinel) = NULL; + sentinel->next = NULL; + unique->epsilon = DD_EPSILON; + unique->maxGrowth = DD_MAX_REORDER_GROWTH; + unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH; + unique->reordCycle = 0; /* do not use alternate threshold */ + unique->size = numVars; + unique->sizeZ = numVarsZ; + unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars); + unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ); + + /* Adjust the requested number of slots to a power of 2. */ + slots = 8; + while (slots < numSlots) { + slots <<= 1; + } + unique->initSlots = slots; + shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots); + + unique->slots = (numVars + numVarsZ + 1) * slots; + unique->keys = 0; + unique->maxLive = ~0; /* very large number */ + unique->keysZ = 0; + unique->dead = 0; + unique->deadZ = 0; + unique->gcFrac = DD_GC_FRAC_HI; + unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); + unique->looseUpTo = looseUpTo; + unique->gcEnabled = 1; + unique->allocated = 0; + unique->reclaimed = 0; + unique->subtables = ALLOC(DdSubtable,unique->maxSize); + if (unique->subtables == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->subtableZ = ALLOC(DdSubtable,unique->maxSizeZ); + if (unique->subtableZ == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->perm = ALLOC(int,unique->maxSize); + if (unique->perm == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->invperm = ALLOC(int,unique->maxSize); + if (unique->invperm == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->permZ = ALLOC(int,unique->maxSizeZ); + if (unique->permZ == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->invpermZ = ALLOC(int,unique->maxSizeZ); + if (unique->invpermZ == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->map = NULL; + unique->stack = ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1); + if (unique->stack == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->stack[0] = NULL; /* to suppress harmless UMR */ + +#ifndef DD_NO_DEATH_ROW + unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2); + unique->deathRow = ALLOC(DdNodePtr,unique->deathRowDepth); + if (unique->deathRow == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (i = 0; i < unique->deathRowDepth; i++) { + unique->deathRow[i] = NULL; + } + unique->nextDead = 0; + unique->deadMask = unique->deathRowDepth - 1; +#endif + + for (i = 0; (unsigned) i < numVars; i++) { + unique->subtables[i].slots = slots; + unique->subtables[i].shift = shift; + unique->subtables[i].keys = 0; + unique->subtables[i].dead = 0; + unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; + unique->subtables[i].bindVar = 0; + unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; + unique->subtables[i].pairIndex = 0; + unique->subtables[i].varHandled = 0; + unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; + + nodelist = unique->subtables[i].nodelist = ALLOC(DdNodePtr,slots); + if (nodelist == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (j = 0; (unsigned) j < slots; j++) { + nodelist[j] = sentinel; + } + unique->perm[i] = i; + unique->invperm[i] = i; + } + for (i = 0; (unsigned) i < numVarsZ; i++) { + unique->subtableZ[i].slots = slots; + unique->subtableZ[i].shift = shift; + unique->subtableZ[i].keys = 0; + unique->subtableZ[i].dead = 0; + unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; + nodelist = unique->subtableZ[i].nodelist = ALLOC(DdNodePtr,slots); + if (nodelist == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (j = 0; (unsigned) j < slots; j++) { + nodelist[j] = NULL; + } + unique->permZ[i] = i; + unique->invpermZ[i] = i; + } + unique->constants.slots = slots; + unique->constants.shift = shift; + unique->constants.keys = 0; + unique->constants.dead = 0; + unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; + nodelist = unique->constants.nodelist = ALLOC(DdNodePtr,slots); + if (nodelist == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (j = 0; (unsigned) j < slots; j++) { + nodelist[j] = NULL; + } + + unique->memoryList = NULL; + unique->nextFree = NULL; + + unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ) + * (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) * + slots * sizeof(DdNodePtr) + + (ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr); +#ifndef DD_NO_DEATH_ROW + unique->memused += unique->deathRowDepth * sizeof(DdNodePtr); +#endif + + /* Initialize fields concerned with automatic dynamic reordering */ + unique->reorderings = 0; + unique->autoDyn = 0; /* initially disabled */ + unique->autoDynZ = 0; /* initially disabled */ + unique->realign = 0; /* initially disabled */ + unique->realignZ = 0; /* initially disabled */ + unique->reordered = 0; + unique->autoMethod = CUDD_REORDER_SIFT; + unique->autoMethodZ = CUDD_REORDER_SIFT; + unique->nextDyn = DD_FIRST_REORDER; + unique->countDead = ~0; + unique->siftMaxVar = DD_SIFT_MAX_VAR; + unique->siftMaxSwap = DD_SIFT_MAX_SWAPS; + unique->tree = NULL; + unique->treeZ = NULL; + unique->groupcheck = CUDD_GROUP_CHECK7; + unique->recomb = DD_DEFAULT_RECOMB; + unique->symmviolation = 0; + unique->arcviolation = 0; + unique->populationSize = 0; + unique->numberXovers = 0; + unique->linear = NULL; + unique->linearSize = 0; + + /* Initialize ZDD universe. */ + unique->univ = (DdNodePtr *)NULL; + + /* Initialize auxiliary fields. */ + unique->localCaches = NULL; + unique->preGCHook = NULL; + unique->postGCHook = NULL; + unique->preReorderingHook = NULL; + unique->postReorderingHook = NULL; + unique->out = stdout; + unique->err = stderr; + unique->errorCode = CUDD_NO_ERROR; + + /* Initialize statistical counters. */ + unique->maxmemhard = (long) ((~ (unsigned long) 0) >> 1); + unique->garbageCollections = 0; + unique->GCTime = 0; + unique->reordTime = 0; +#ifdef DD_STATS + unique->nodesDropped = 0; + unique->nodesFreed = 0; +#endif + unique->peakLiveNodes = 0; +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLookUps = 0; + unique->uniqueLinks = 0; +#endif +#ifdef DD_COUNT + unique->recursiveCalls = 0; + unique->swapSteps = 0; +#ifdef DD_STATS + unique->nextSample = 250000; +#endif +#endif + + return(unique); + +} /* end of cuddInitTable */ + + +/**Function******************************************************************** + + Synopsis [Frees the resources associated to a unique table.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddInitTable] + +******************************************************************************/ +void +cuddFreeTable( + DdManager * unique) +{ + DdNodePtr *next; + DdNodePtr *memlist = unique->memoryList; + int i; + + if (unique->univ != NULL) cuddZddFreeUniv(unique); + while (memlist != NULL) { + next = (DdNodePtr *) memlist[0]; /* link to next block */ + FREE(memlist); + memlist = next; + } + unique->nextFree = NULL; + unique->memoryList = NULL; + + for (i = 0; i < unique->size; i++) { + FREE(unique->subtables[i].nodelist); + } + for (i = 0; i < unique->sizeZ; i++) { + FREE(unique->subtableZ[i].nodelist); + } + FREE(unique->constants.nodelist); + FREE(unique->subtables); + FREE(unique->subtableZ); + FREE(unique->acache); + FREE(unique->perm); + FREE(unique->permZ); + FREE(unique->invperm); + FREE(unique->invpermZ); + FREE(unique->vars); + if (unique->map != NULL) FREE(unique->map); + FREE(unique->stack); +#ifndef DD_NO_DEATH_ROW + FREE(unique->deathRow); +#endif + if (unique->tree != NULL) Mtr_FreeTree(unique->tree); + if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ); + if (unique->linear != NULL) FREE(unique->linear); + while (unique->preGCHook != NULL) + Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK); + while (unique->postGCHook != NULL) + Cudd_RemoveHook(unique,unique->postGCHook->f,CUDD_POST_GC_HOOK); + while (unique->preReorderingHook != NULL) + Cudd_RemoveHook(unique,unique->preReorderingHook->f, + CUDD_PRE_REORDERING_HOOK); + while (unique->postReorderingHook != NULL) + Cudd_RemoveHook(unique,unique->postReorderingHook->f, + CUDD_POST_REORDERING_HOOK); + FREE(unique); + +} /* end of cuddFreeTable */ + + +/**Function******************************************************************** + + Synopsis [Performs garbage collection on a unique table.] + + Description [Performs garbage collection on a unique table. + If clearCache is 0, the cache is not cleared. This should only be + specified if the cache has been cleared right before calling + cuddGarbageCollect. (As in the case of dynamic reordering.) + Returns the total number of deleted nodes.] + + SideEffects [None] + + SeeAlso [cuddGarbageCollectZdd] + +******************************************************************************/ +int +cuddGarbageCollect( + DdManager * unique, + int clearCache) +{ + DdHook *hook; + DdCache *cache = unique->cache; + DdNode *sentinel = &(unique->sentinel); + DdNodePtr *nodelist; + int i, j, deleted, totalDeleted; + DdCache *c; + DdNode *node,*next; + DdNodePtr *lastP; + int slots; + long localTime; +#ifndef DD_UNSORTED_FREE_LIST + DdNodePtr tree; +#endif + +#ifndef DD_NO_DEATH_ROW + cuddClearDeathRow(unique); +#endif + + hook = unique->preGCHook; + while (hook != NULL) { + int res = (hook->f)(unique,"BDD",NULL); + if (res == 0) return(0); + hook = hook->next; + } + + if (unique->dead == 0) { + hook = unique->postGCHook; + while (hook != NULL) { + int res = (hook->f)(unique,"BDD",NULL); + if (res == 0) return(0); + hook = hook->next; + } + return(0); + } + + /* If many nodes are being reclaimed, we want to resize the tables + ** more aggressively, to reduce the frequency of garbage collection. + */ + if (clearCache && unique->gcFrac == DD_GC_FRAC_LO && + unique->slots <= unique->looseUpTo && unique->stash != NULL) { + unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); +#ifdef DD_VERBOSE + (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI); + (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); +#endif + unique->gcFrac = DD_GC_FRAC_HI; + return(0); + } + + localTime = util_cpu_time(); + + unique->garbageCollections++; +#ifdef DD_VERBOSE + (void) fprintf(unique->err, + "garbage collecting (%d dead out of %d, min %d)...", + unique->dead, unique->keys, unique->minDead); +#endif + + /* Remove references to garbage collected nodes from the cache. */ + if (clearCache) { + slots = unique->cacheSlots; + for (i = 0; i < slots; i++) { + c = &cache[i]; + if (c->data != NULL) { + if (cuddClean(c->f)->ref == 0 || + cuddClean(c->g)->ref == 0 || + (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) || + (c->data != DD_NON_CONSTANT && + Cudd_Regular(c->data)->ref == 0)) { + c->data = NULL; + unique->cachedeletions++; + } + } + } + cuddLocalCacheClearDead(unique); + } + + /* Now return dead nodes to free list. Count them for sanity check. */ + totalDeleted = 0; +#ifndef DD_UNSORTED_FREE_LIST + tree = NULL; +#endif + + for (i = 0; i < unique->size; i++) { + if (unique->subtables[i].dead == 0) continue; + nodelist = unique->subtables[i].nodelist; + + deleted = 0; + slots = unique->subtables[i].slots; + for (j = 0; j < slots; j++) { + lastP = &(nodelist[j]); + node = *lastP; + while (node != sentinel) { + next = node->next; + if (node->ref == 0) { + deleted++; +#ifndef DD_UNSORTED_FREE_LIST +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + cuddOrderedInsert(&tree,node); +#ifdef __osf__ +#pragma pointer_size restore +#endif +#else + cuddDeallocNode(unique,node); +#endif + } else { + *lastP = node; + lastP = &(node->next); + } + node = next; + } + *lastP = sentinel; + } + if ((unsigned) deleted != unique->subtables[i].dead) { + ddReportRefMess(unique, i, "cuddGarbageCollect"); + } + totalDeleted += deleted; + unique->subtables[i].keys -= deleted; + unique->subtables[i].dead = 0; + } + if (unique->constants.dead != 0) { + nodelist = unique->constants.nodelist; + deleted = 0; + slots = unique->constants.slots; + for (j = 0; j < slots; j++) { + lastP = &(nodelist[j]); + node = *lastP; + while (node != NULL) { + next = node->next; + if (node->ref == 0) { + deleted++; +#ifndef DD_UNSORTED_FREE_LIST +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + cuddOrderedInsert(&tree,node); +#ifdef __osf__ +#pragma pointer_size restore +#endif +#else + cuddDeallocNode(unique,node); +#endif + } else { + *lastP = node; + lastP = &(node->next); + } + node = next; + } + *lastP = NULL; + } + if ((unsigned) deleted != unique->constants.dead) { + ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect"); + } + totalDeleted += deleted; + unique->constants.keys -= deleted; + unique->constants.dead = 0; + } + if ((unsigned) totalDeleted != unique->dead) { + ddReportRefMess(unique, -1, "cuddGarbageCollect"); + } + unique->keys -= totalDeleted; + unique->dead = 0; +#ifdef DD_STATS + unique->nodesFreed += (double) totalDeleted; +#endif + +#ifndef DD_UNSORTED_FREE_LIST + unique->nextFree = cuddOrderedThread(tree,unique->nextFree); +#endif + + unique->GCTime += util_cpu_time() - localTime; + + hook = unique->postGCHook; + while (hook != NULL) { + int res = (hook->f)(unique,"BDD",NULL); + if (res == 0) return(0); + hook = hook->next; + } + +#ifdef DD_VERBOSE + (void) fprintf(unique->err," done\n"); +#endif + + return(totalDeleted); + +} /* end of cuddGarbageCollect */ + + +/**Function******************************************************************** + + Synopsis [Performs garbage collection on a ZDD unique table.] + + Description [Performs garbage collection on a ZDD unique table. + If clearCache is 0, the cache is not cleared. This should only be + specified if the cache has been cleared right before calling + cuddGarbageCollectZdd. (As in the case of dynamic reordering.) + Returns the total number of deleted nodes.] + + SideEffects [None] + + SeeAlso [cuddGarbageCollect] + +******************************************************************************/ +int +cuddGarbageCollectZdd( + DdManager * unique, + int clearCache) +{ + DdHook *hook; + DdCache *cache = unique->cache; + DdNodePtr *nodelist; + int i, j, deleted, totalDeleted; + DdCache *c; + DdNode *node,*next; + DdNodePtr *lastP; + int slots; + long localTime; +#ifndef DD_UNSORTED_FREE_LIST + DdNodePtr tree; +#endif + + hook = unique->preGCHook; + while (hook != NULL) { + int res = (hook->f)(unique,"ZDD",NULL); + if (res == 0) return(0); + hook = hook->next; + } + + if (unique->deadZ == 0) { + hook = unique->postGCHook; + while (hook != NULL) { + int res = (hook->f)(unique,"ZDD",NULL); + if (res == 0) return(0); + hook = hook->next; + } + return(0); + } + + /* If many nodes are being reclaimed, we want to resize the tables + ** more aggressively, to reduce the frequency of garbage collection. + */ + if (clearCache && unique->slots <= unique->looseUpTo) { + unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); +#ifdef DD_VERBOSE + if (unique->gcFrac == DD_GC_FRAC_LO) { + (void) fprintf(unique->err,"GC fraction = %.2f\t", + DD_GC_FRAC_HI); + (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); + } +#endif + unique->gcFrac = DD_GC_FRAC_HI; + } + + localTime = util_cpu_time(); + + unique->garbageCollections++; +#ifdef DD_VERBOSE + (void) fprintf(unique->err,"garbage collecting (%d dead out of %d)...", + unique->deadZ,unique->keysZ); +#endif + + /* Remove references to garbage collected nodes from the cache. */ + if (clearCache) { + slots = unique->cacheSlots; + for (i = 0; i < slots; i++) { + c = &cache[i]; + if (c->data != NULL) { + if (cuddClean(c->f)->ref == 0 || + cuddClean(c->g)->ref == 0 || + (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) || + (c->data != DD_NON_CONSTANT && + Cudd_Regular(c->data)->ref == 0)) { + c->data = NULL; + unique->cachedeletions++; + } + } + } + } + + /* Now return dead nodes to free list. Count them for sanity check. */ + totalDeleted = 0; +#ifndef DD_UNSORTED_FREE_LIST + tree = NULL; +#endif + + for (i = 0; i < unique->sizeZ; i++) { + if (unique->subtableZ[i].dead == 0) continue; + nodelist = unique->subtableZ[i].nodelist; + + deleted = 0; + slots = unique->subtableZ[i].slots; + for (j = 0; j < slots; j++) { + lastP = &(nodelist[j]); + node = *lastP; + while (node != NULL) { + next = node->next; + if (node->ref == 0) { + deleted++; +#ifndef DD_UNSORTED_FREE_LIST +#ifdef __osf__ +#pragma pointer_size save +#pragma pointer_size short +#endif + cuddOrderedInsert(&tree,node); +#ifdef __osf__ +#pragma pointer_size restore +#endif +#else + cuddDeallocNode(unique,node); +#endif + } else { + *lastP = node; + lastP = &(node->next); + } + node = next; + } + *lastP = NULL; + } + if ((unsigned) deleted != unique->subtableZ[i].dead) { + ddReportRefMess(unique, i, "cuddGarbageCollectZdd"); + } + totalDeleted += deleted; + unique->subtableZ[i].keys -= deleted; + unique->subtableZ[i].dead = 0; + } + + /* No need to examine the constant table for ZDDs. + ** If we did we should be careful not to count whatever dead + ** nodes we found there among the dead ZDD nodes. */ + if ((unsigned) totalDeleted != unique->deadZ) { + ddReportRefMess(unique, -1, "cuddGarbageCollectZdd"); + } + unique->keysZ -= totalDeleted; + unique->deadZ = 0; +#ifdef DD_STATS + unique->nodesFreed += (double) totalDeleted; +#endif + +#ifndef DD_UNSORTED_FREE_LIST + unique->nextFree = cuddOrderedThread(tree,unique->nextFree); +#endif + + unique->GCTime += util_cpu_time() - localTime; + + hook = unique->postGCHook; + while (hook != NULL) { + int res = (hook->f)(unique,"ZDD",NULL); + if (res == 0) return(0); + hook = hook->next; + } + +#ifdef DD_VERBOSE + (void) fprintf(unique->err," done\n"); +#endif + + return(totalDeleted); + +} /* end of cuddGarbageCollectZdd */ + + +/**Function******************************************************************** + + Synopsis [Wrapper for cuddUniqueInterZdd.] + + Description [Wrapper for cuddUniqueInterZdd, which applies the ZDD + reduction rule. Returns a pointer to the result node under normal + conditions; NULL if reordering occurred or memory was exhausted.] + + SideEffects [None] + + SeeAlso [cuddUniqueInterZdd] + +******************************************************************************/ +DdNode * +cuddZddGetNode( + DdManager * zdd, + int id, + DdNode * T, + DdNode * E) +{ + DdNode *node; + + if (T == DD_ZERO(zdd)) + return(E); + node = cuddUniqueInterZdd(zdd, id, T, E); + return(node); + +} /* end of cuddZddGetNode */ + + +/**Function******************************************************************** + + Synopsis [Wrapper for cuddUniqueInterZdd that is independent of variable + ordering.] + + Description [Wrapper for cuddUniqueInterZdd that is independent of + variable ordering (IVO). This function does not require parameter + index to precede the indices of the top nodes of g and h in the + variable order. Returns a pointer to the result node under normal + conditions; NULL if reordering occurred or memory was exhausted.] + + SideEffects [None] + + SeeAlso [cuddZddGetNode cuddZddIsop] + +******************************************************************************/ +DdNode * +cuddZddGetNodeIVO( + DdManager * dd, + int index, + DdNode * g, + DdNode * h) +{ + DdNode *f, *r, *t; + DdNode *zdd_one = DD_ONE(dd); + DdNode *zdd_zero = DD_ZERO(dd); + + f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero); + if (f == NULL) { + return(NULL); + } + cuddRef(f); + t = cuddZddProduct(dd, f, g); + if (t == NULL) { + Cudd_RecursiveDerefZdd(dd, f); + return(NULL); + } + cuddRef(t); + Cudd_RecursiveDerefZdd(dd, f); + r = cuddZddUnion(dd, t, h); + if (r == NULL) { + Cudd_RecursiveDerefZdd(dd, t); + return(NULL); + } + cuddRef(r); + Cudd_RecursiveDerefZdd(dd, t); + + cuddDeref(r); + return(r); + +} /* end of cuddZddGetNodeIVO */ + + +/**Function******************************************************************** + + Synopsis [Checks the unique table for the existence of an internal node.] + + Description [Checks the unique table for the existence of an internal + node. If it does not exist, it creates a new one. Does not + modify the reference count of whatever is returned. A newly created + internal node comes back with a reference count 0. For a newly + created node, increments the reference counts of what T and E point + to. Returns a pointer to the new node if successful; NULL if memory + is exhausted or if reordering took place.] + + SideEffects [None] + + SeeAlso [cuddUniqueInterZdd] + +******************************************************************************/ +DdNode * +cuddUniqueInter( + DdManager * unique, + int index, + DdNode * T, + DdNode * E) +{ + int pos; + unsigned int level; + int retval; + DdNodePtr *nodelist; + DdNode *looking; + DdNodePtr *previousP; + DdSubtable *subtable; + int gcNumber; + +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLookUps++; +#endif + + if (index >= unique->size) { + if (!ddResizeTable(unique,index)) return(NULL); + } + + level = unique->perm[index]; + subtable = &(unique->subtables[level]); + +#ifdef DD_DEBUG + assert(level < (unsigned) cuddI(unique,T->index)); + assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index)); +#endif + + pos = ddHash(T, E, subtable->shift); + nodelist = subtable->nodelist; + previousP = &(nodelist[pos]); + looking = *previousP; + + while (T < cuddT(looking)) { + previousP = &(looking->next); + looking = *previousP; +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLinks++; +#endif + } + while (T == cuddT(looking) && E < cuddE(looking)) { + previousP = &(looking->next); + looking = *previousP; +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLinks++; +#endif + } + if (T == cuddT(looking) && E == cuddE(looking)) { + if (looking->ref == 0) { + cuddReclaim(unique,looking); + } + return(looking); + } + + /* countDead is 0 if deads should be counted and ~0 if they should not. */ + if (unique->autoDyn && + unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn) { +#ifdef DD_DEBUG + retval = Cudd_DebugCheck(unique); + if (retval != 0) return(NULL); + retval = Cudd_CheckKeys(unique); + if (retval != 0) return(NULL); +#endif + retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */ + if (retval == 0) unique->reordered = 2; +#ifdef DD_DEBUG + retval = Cudd_DebugCheck(unique); + if (retval != 0) unique->reordered = 2; + retval = Cudd_CheckKeys(unique); + if (retval != 0) unique->reordered = 2; +#endif + return(NULL); + } + + if (subtable->keys > subtable->maxKeys) { + if (unique->gcEnabled && + ((unique->dead > unique->minDead) || + ((unique->dead > unique->minDead / 2) && + (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */ + (void) cuddGarbageCollect(unique,1); + } else { + cuddRehash(unique,(int)level); + } + /* Update pointer to insertion point. In the case of rehashing, + ** the slot may have changed. In the case of garbage collection, + ** the predecessor may have been dead. */ + pos = ddHash(T, E, subtable->shift); + nodelist = subtable->nodelist; + previousP = &(nodelist[pos]); + looking = *previousP; + + while (T < cuddT(looking)) { + previousP = &(looking->next); + looking = *previousP; +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLinks++; +#endif + } + while (T == cuddT(looking) && E < cuddE(looking)) { + previousP = &(looking->next); + looking = *previousP; +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLinks++; +#endif + } + } + + gcNumber = unique->garbageCollections; + looking = cuddAllocNode(unique); + if (looking == NULL) { + return(NULL); + } + unique->keys++; + subtable->keys++; + + if (gcNumber != unique->garbageCollections) { + DdNode *looking2; + pos = ddHash(T, E, subtable->shift); + nodelist = subtable->nodelist; + previousP = &(nodelist[pos]); + looking2 = *previousP; + + while (T < cuddT(looking2)) { + previousP = &(looking2->next); + looking2 = *previousP; +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLinks++; +#endif + } + while (T == cuddT(looking2) && E < cuddE(looking2)) { + previousP = &(looking2->next); + looking2 = *previousP; +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLinks++; +#endif + } + } + looking->ref = 0; + looking->index = index; + cuddT(looking) = T; + cuddE(looking) = E; + looking->next = *previousP; + *previousP = looking; + cuddSatInc(T->ref); /* we know T is a regular pointer */ + cuddRef(E); + +#ifdef DD_DEBUG + cuddCheckCollisionOrdering(unique,level,pos); +#endif + + return(looking); + +} /* end of cuddUniqueInter */ + + +/**Function******************************************************************** + + Synopsis [Wrapper for cuddUniqueInter that is independent of variable + ordering.] + + Description [Wrapper for cuddUniqueInter that is independent of + variable ordering (IVO). This function does not require parameter + index to precede the indices of the top nodes of T and E in the + variable order. Returns a pointer to the result node under normal + conditions; NULL if reordering occurred or memory was exhausted.] + + SideEffects [None] + + SeeAlso [cuddUniqueInter Cudd_MakeBddFromZddCover] + +******************************************************************************/ +DdNode * +cuddUniqueInterIVO( + DdManager * unique, + int index, + DdNode * T, + DdNode * E) +{ + DdNode *result; + DdNode *v; + + v = cuddUniqueInter(unique, index, DD_ONE(unique), + Cudd_Not(DD_ONE(unique))); + if (v == NULL) + return(NULL); + cuddRef(v); + result = cuddBddIteRecur(unique, v, T, E); + Cudd_RecursiveDeref(unique, v); + return(result); +} + + +/**Function******************************************************************** + + Synopsis [Checks the unique table for the existence of an internal + ZDD node.] + + Description [Checks the unique table for the existence of an internal + ZDD node. If it does not exist, it creates a new one. Does not + modify the reference count of whatever is returned. A newly created + internal node comes back with a reference count 0. For a newly + created node, increments the reference counts of what T and E point + to. Returns a pointer to the new node if successful; NULL if memory + is exhausted or if reordering took place.] + + SideEffects [None] + + SeeAlso [cuddUniqueInter] + +******************************************************************************/ +DdNode * +cuddUniqueInterZdd( + DdManager * unique, + int index, + DdNode * T, + DdNode * E) +{ + int pos; + unsigned int level; + int retval; + DdNodePtr *nodelist; + DdNode *looking; + DdSubtable *subtable; + +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLookUps++; +#endif + + if (index >= unique->sizeZ) { + if (!cuddResizeTableZdd(unique,index)) return(NULL); + } + + level = unique->permZ[index]; + subtable = &(unique->subtableZ[level]); + +#ifdef DD_DEBUG + assert(level < (unsigned) cuddIZ(unique,T->index)); + assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index)); +#endif + + if (subtable->keys > subtable->maxKeys) { + if (unique->gcEnabled && ((unique->deadZ > unique->minDead) || + (10 * subtable->dead > 9 * subtable->keys))) { /* too many dead */ + (void) cuddGarbageCollectZdd(unique,1); + } else { + ddRehashZdd(unique,(int)level); + } + } + + pos = ddHash(T, E, subtable->shift); + nodelist = subtable->nodelist; + looking = nodelist[pos]; + + while (looking != NULL) { + if (cuddT(looking) == T && cuddE(looking) == E) { + if (looking->ref == 0) { + cuddReclaimZdd(unique,looking); + } + return(looking); + } + looking = looking->next; +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLinks++; +#endif + } + + /* countDead is 0 if deads should be counted and ~0 if they should not. */ + if (unique->autoDynZ && + unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) { +#ifdef DD_DEBUG + retval = Cudd_DebugCheck(unique); + if (retval != 0) return(NULL); + retval = Cudd_CheckKeys(unique); + if (retval != 0) return(NULL); +#endif + retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */ + if (retval == 0) unique->reordered = 2; +#ifdef DD_DEBUG + retval = Cudd_DebugCheck(unique); + if (retval != 0) unique->reordered = 2; + retval = Cudd_CheckKeys(unique); + if (retval != 0) unique->reordered = 2; +#endif + return(NULL); + } + + unique->keysZ++; + subtable->keys++; + + looking = cuddAllocNode(unique); + if (looking == NULL) return(NULL); + looking->ref = 0; + looking->index = index; + cuddT(looking) = T; + cuddE(looking) = E; + looking->next = nodelist[pos]; + nodelist[pos] = looking; + cuddRef(T); + cuddRef(E); + + return(looking); + +} /* end of cuddUniqueInterZdd */ + + +/**Function******************************************************************** + + Synopsis [Checks the unique table for the existence of a constant node.] + + Description [Checks the unique table for the existence of a constant node. + If it does not exist, it creates a new one. Does not + modify the reference count of whatever is returned. A newly created + internal node comes back with a reference count 0. Returns a + pointer to the new node.] + + SideEffects [None] + +******************************************************************************/ +DdNode * +cuddUniqueConst( + DdManager * unique, + CUDD_VALUE_TYPE value) +{ + int pos; + DdNodePtr *nodelist; + DdNode *looking; + hack split; + +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLookUps++; +#endif + + if (unique->constants.keys > unique->constants.maxKeys) { + if (unique->gcEnabled && ((unique->dead > unique->minDead) || + (10 * unique->constants.dead > 9 * unique->constants.keys))) { /* too many dead */ + (void) cuddGarbageCollect(unique,1); + } else { + cuddRehash(unique,CUDD_CONST_INDEX); + } + } + + cuddAdjust(value); /* for the case of crippled infinities */ + + if (ddAbs(value) < unique->epsilon) { + value = 0.0; + } + split.value = value; + + pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift); + nodelist = unique->constants.nodelist; + looking = nodelist[pos]; + + /* Here we compare values both for equality and for difference less + * than epsilon. The first comparison is required when values are + * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for + * every X. + */ + while (looking != NULL) { + if (looking->type.value == value || + ddEqualVal(looking->type.value,value,unique->epsilon)) { + if (looking->ref == 0) { + cuddReclaim(unique,looking); + } + return(looking); + } + looking = looking->next; +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLinks++; +#endif + } + + unique->keys++; + unique->constants.keys++; + + looking = cuddAllocNode(unique); + if (looking == NULL) return(NULL); + looking->ref = 0; + looking->index = CUDD_CONST_INDEX; + looking->type.value = value; + looking->next = nodelist[pos]; + nodelist[pos] = looking; + + return(looking); + +} /* end of cuddUniqueConst */ + + +/**Function******************************************************************** + + Synopsis [Rehashes a unique subtable.] + + Description [Doubles the size of a unique subtable and rehashes its + contents.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +cuddRehash( + DdManager * unique, + int i) +{ + unsigned int slots, oldslots; + int shift, oldshift; + int j, pos; + DdNodePtr *nodelist, *oldnodelist; + DdNode *node, *next; + DdNode *sentinel = &(unique->sentinel); + hack split; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); + + if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) { + unique->gcFrac = DD_GC_FRAC_LO; + unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); +#ifdef DD_VERBOSE + (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO); + (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); +#endif + } + + if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) { + unique->gcFrac = DD_GC_FRAC_MIN; + unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); +#ifdef DD_VERBOSE + (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN); + (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); +#endif + cuddShrinkDeathRow(unique); + if (cuddGarbageCollect(unique,1) > 0) return; + } + + if (i != CUDD_CONST_INDEX) { + oldslots = unique->subtables[i].slots; + oldshift = unique->subtables[i].shift; + oldnodelist = unique->subtables[i].nodelist; + + /* Compute the new size of the subtable. */ + slots = oldslots << 1; + shift = oldshift - 1; + + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + nodelist = ALLOC(DdNodePtr, slots); + MMoutOfMemory = saveHandler; + if (nodelist == NULL) { + (void) fprintf(unique->err, + "Unable to resize subtable %d for lack of memory\n", + i); + /* Prevent frequent resizing attempts. */ + (void) cuddGarbageCollect(unique,1); + if (unique->stash != NULL) { + FREE(unique->stash); + unique->stash = NULL; + /* Inhibit resizing of tables. */ + cuddSlowTableGrowth(unique); + } + return; + } + unique->subtables[i].nodelist = nodelist; + unique->subtables[i].slots = slots; + unique->subtables[i].shift = shift; + unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; + + /* Move the nodes from the old table to the new table. + ** This code depends on the type of hash function. + ** It assumes that the effect of doubling the size of the table + ** is to retain one more bit of the 32-bit hash value. + ** The additional bit is the LSB. */ + for (j = 0; (unsigned) j < oldslots; j++) { + DdNodePtr *evenP, *oddP; + node = oldnodelist[j]; + evenP = &(nodelist[j<<1]); + oddP = &(nodelist[(j<<1)+1]); + while (node != sentinel) { + next = node->next; + pos = ddHash(cuddT(node), cuddE(node), shift); + if (pos & 1) { + *oddP = node; + oddP = &(node->next); + } else { + *evenP = node; + evenP = &(node->next); + } + node = next; + } + *evenP = *oddP = sentinel; + } + FREE(oldnodelist); + +#ifdef DD_VERBOSE + (void) fprintf(unique->err, + "rehashing layer %d: keys %d dead %d new size %d\n", + i, unique->subtables[i].keys, + unique->subtables[i].dead, slots); +#endif + } else { + oldslots = unique->constants.slots; + oldshift = unique->constants.shift; + oldnodelist = unique->constants.nodelist; + + /* The constant subtable is never subjected to reordering. + ** Therefore, when it is resized, it is because it has just + ** reached the maximum load. We can safely just double the size, + ** with no need for the loop we use for the other tables. + */ + slots = oldslots << 1; + shift = oldshift - 1; + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + nodelist = ALLOC(DdNodePtr, slots); + MMoutOfMemory = saveHandler; + if (nodelist == NULL) { + int j; + (void) fprintf(unique->err, + "Unable to resize constant subtable for lack of memory\n"); + (void) cuddGarbageCollect(unique,1); + for (j = 0; j < unique->size; j++) { + unique->subtables[j].maxKeys <<= 1; + } + unique->constants.maxKeys <<= 1; + return; + } + unique->constants.slots = slots; + unique->constants.shift = shift; + unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; + unique->constants.nodelist = nodelist; + for (j = 0; (unsigned) j < slots; j++) { + nodelist[j] = NULL; + } + for (j = 0; (unsigned) j < oldslots; j++) { + node = oldnodelist[j]; + while (node != NULL) { + next = node->next; + split.value = cuddV(node); + pos = ddHash(split.bits[0], split.bits[1], shift); + node->next = nodelist[pos]; + nodelist[pos] = node; + node = next; + } + } + FREE(oldnodelist); + +#ifdef DD_VERBOSE + (void) fprintf(unique->err, + "rehashing constants: keys %d dead %d new size %d\n", + unique->constants.keys,unique->constants.dead,slots); +#endif + } + + /* Update global data */ + + unique->memused += (slots - oldslots) * sizeof(DdNodePtr); + unique->slots += (slots - oldslots); + ddFixLimits(unique); + +} /* end of cuddRehash */ + + +/**Function******************************************************************** + + Synopsis [Shrinks a subtable.] + + Description [Shrinks a subtable.] + + SideEffects [None] + + SeeAlso [cuddRehash] + +******************************************************************************/ +void +cuddShrinkSubtable( + DdManager *unique, + int i) +{ + int j; + int shift, posn; + DdNodePtr *nodelist, *oldnodelist; + DdNode *node, *next; + DdNode *sentinel = &(unique->sentinel); + unsigned int slots, oldslots; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); + + oldnodelist = unique->subtables[i].nodelist; + oldslots = unique->subtables[i].slots; + slots = oldslots >> 1; + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + nodelist = ALLOC(DdNodePtr, slots); + MMoutOfMemory = saveHandler; + if (nodelist == NULL) { + return; + } + unique->subtables[i].nodelist = nodelist; + unique->subtables[i].slots = slots; + unique->subtables[i].shift++; + unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; +#ifdef DD_VERBOSE + (void) fprintf(unique->err, + "shrunk layer %d (%d keys) from %d to %d slots\n", + i, unique->subtables[i].keys, oldslots, slots); +#endif + + for (j = 0; (unsigned) j < slots; j++) { + nodelist[j] = sentinel; + } + shift = unique->subtables[i].shift; + for (j = 0; (unsigned) j < oldslots; j++) { + node = oldnodelist[j]; + while (node != sentinel) { + DdNode *looking, *T, *E; + DdNodePtr *previousP; + next = node->next; + posn = ddHash(cuddT(node), cuddE(node), shift); + previousP = &(nodelist[posn]); + looking = *previousP; + T = cuddT(node); + E = cuddE(node); + while (T < cuddT(looking)) { + previousP = &(looking->next); + looking = *previousP; +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLinks++; +#endif + } + while (T == cuddT(looking) && E < cuddE(looking)) { + previousP = &(looking->next); + looking = *previousP; +#ifdef DD_UNIQUE_PROFILE + unique->uniqueLinks++; +#endif + } + node->next = *previousP; + *previousP = node; + node = next; + } + } + FREE(oldnodelist); + + unique->memused += ((long) slots - (long) oldslots) * sizeof(DdNode *); + unique->slots += slots - oldslots; + unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); + unique->cacheSlack = (int) + ddMin(unique->maxCacheHard,DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) + - 2 * (int) unique->cacheSlots; + +} /* end of cuddShrinkSubtable */ + + +/**Function******************************************************************** + + Synopsis [Inserts n new subtables in a unique table at level.] + + Description [Inserts n new subtables in a unique table at level. + The number n should be positive, and level should be an existing level. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [cuddDestroySubtables] + +******************************************************************************/ +int +cuddInsertSubtables( + DdManager * unique, + int n, + int level) +{ + DdSubtable *newsubtables; + DdNodePtr *newnodelist; + DdNodePtr *newvars; + DdNode *sentinel = &(unique->sentinel); + int oldsize,newsize; + int i,j,index,reorderSave; + unsigned int numSlots = unique->initSlots; + int *newperm, *newinvperm, *newmap; + DdNode *one, *zero; + +#ifdef DD_DEBUG + assert(n > 0 && level < unique->size); +#endif + + oldsize = unique->size; + /* Easy case: there is still room in the current table. */ + if (oldsize + n <= unique->maxSize) { + /* Shift the tables at and below level. */ + for (i = oldsize - 1; i >= level; i--) { + unique->subtables[i+n].slots = unique->subtables[i].slots; + unique->subtables[i+n].shift = unique->subtables[i].shift; + unique->subtables[i+n].keys = unique->subtables[i].keys; + unique->subtables[i+n].maxKeys = unique->subtables[i].maxKeys; + unique->subtables[i+n].dead = unique->subtables[i].dead; + unique->subtables[i+n].nodelist = unique->subtables[i].nodelist; + unique->subtables[i+n].bindVar = unique->subtables[i].bindVar; + unique->subtables[i+n].varType = unique->subtables[i].varType; + unique->subtables[i+n].pairIndex = unique->subtables[i].pairIndex; + unique->subtables[i+n].varHandled = unique->subtables[i].varHandled; + unique->subtables[i+n].varToBeGrouped = + unique->subtables[i].varToBeGrouped; + + index = unique->invperm[i]; + unique->invperm[i+n] = index; + unique->perm[index] += n; + } + /* Create new subtables. */ + for (i = 0; i < n; i++) { + unique->subtables[level+i].slots = numSlots; + unique->subtables[level+i].shift = sizeof(int) * 8 - + cuddComputeFloorLog2(numSlots); + unique->subtables[level+i].keys = 0; + unique->subtables[level+i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; + unique->subtables[level+i].dead = 0; + unique->subtables[level+i].bindVar = 0; + unique->subtables[level+i].varType = CUDD_VAR_PRIMARY_INPUT; + unique->subtables[level+i].pairIndex = 0; + unique->subtables[level+i].varHandled = 0; + unique->subtables[level+i].varToBeGrouped = CUDD_LAZY_NONE; + + unique->perm[oldsize+i] = level + i; + unique->invperm[level+i] = oldsize + i; + newnodelist = unique->subtables[level+i].nodelist = + ALLOC(DdNodePtr, numSlots); + if (newnodelist == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (j = 0; j < numSlots; j++) { + newnodelist[j] = sentinel; + } + } + if (unique->map != NULL) { + for (i = 0; i < n; i++) { + unique->map[oldsize+i] = oldsize + i; + } + } + } else { + /* The current table is too small: we need to allocate a new, + ** larger one; move all old subtables, and initialize the new + ** subtables. + */ + newsize = oldsize + n + DD_DEFAULT_RESIZE; +#ifdef DD_VERBOSE + (void) fprintf(unique->err, + "Increasing the table size from %d to %d\n", + unique->maxSize, newsize); +#endif + /* Allocate memory for new arrays (except nodelists). */ + newsubtables = ALLOC(DdSubtable,newsize); + if (newsubtables == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newvars = ALLOC(DdNodePtr,newsize); + if (newvars == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + FREE(newsubtables); + return(0); + } + newperm = ALLOC(int,newsize); + if (newperm == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + FREE(newsubtables); + FREE(newvars); + return(0); + } + newinvperm = ALLOC(int,newsize); + if (newinvperm == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + FREE(newsubtables); + FREE(newvars); + FREE(newperm); + return(0); + } + if (unique->map != NULL) { + newmap = ALLOC(int,newsize); + if (newmap == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + FREE(newsubtables); + FREE(newvars); + FREE(newperm); + FREE(newinvperm); + return(0); + } + unique->memused += (newsize - unique->maxSize) * sizeof(int); + } + unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * + sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); + /* Copy levels before insertion points from old tables. */ + for (i = 0; i < level; i++) { + newsubtables[i].slots = unique->subtables[i].slots; + newsubtables[i].shift = unique->subtables[i].shift; + newsubtables[i].keys = unique->subtables[i].keys; + newsubtables[i].maxKeys = unique->subtables[i].maxKeys; + newsubtables[i].dead = unique->subtables[i].dead; + newsubtables[i].nodelist = unique->subtables[i].nodelist; + newsubtables[i].bindVar = unique->subtables[i].bindVar; + newsubtables[i].varType = unique->subtables[i].varType; + newsubtables[i].pairIndex = unique->subtables[i].pairIndex; + newsubtables[i].varHandled = unique->subtables[i].varHandled; + newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; + + newvars[i] = unique->vars[i]; + newperm[i] = unique->perm[i]; + newinvperm[i] = unique->invperm[i]; + } + /* Finish initializing permutation for new table to old one. */ + for (i = level; i < oldsize; i++) { + newperm[i] = unique->perm[i]; + } + /* Initialize new levels. */ + for (i = level; i < level + n; i++) { + newsubtables[i].slots = numSlots; + newsubtables[i].shift = sizeof(int) * 8 - + cuddComputeFloorLog2(numSlots); + newsubtables[i].keys = 0; + newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; + newsubtables[i].dead = 0; + newsubtables[i].bindVar = 0; + newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; + newsubtables[i].pairIndex = 0; + newsubtables[i].varHandled = 0; + newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; + + newperm[oldsize + i - level] = i; + newinvperm[i] = oldsize + i - level; + newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); + if (newnodelist == NULL) { + /* We are going to leak some memory. We should clean up. */ + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (j = 0; j < numSlots; j++) { + newnodelist[j] = sentinel; + } + } + /* Copy the old tables for levels past the insertion point. */ + for (i = level; i < oldsize; i++) { + newsubtables[i+n].slots = unique->subtables[i].slots; + newsubtables[i+n].shift = unique->subtables[i].shift; + newsubtables[i+n].keys = unique->subtables[i].keys; + newsubtables[i+n].maxKeys = unique->subtables[i].maxKeys; + newsubtables[i+n].dead = unique->subtables[i].dead; + newsubtables[i+n].nodelist = unique->subtables[i].nodelist; + newsubtables[i+n].bindVar = unique->subtables[i].bindVar; + newsubtables[i+n].varType = unique->subtables[i].varType; + newsubtables[i+n].pairIndex = unique->subtables[i].pairIndex; + newsubtables[i+n].varHandled = unique->subtables[i].varHandled; + newsubtables[i+n].varToBeGrouped = + unique->subtables[i].varToBeGrouped; + + newvars[i] = unique->vars[i]; + index = unique->invperm[i]; + newinvperm[i+n] = index; + newperm[index] += n; + } + /* Update the map. */ + if (unique->map != NULL) { + for (i = 0; i < oldsize; i++) { + newmap[i] = unique->map[i]; + } + for (i = oldsize; i < oldsize + n; i++) { + newmap[i] = i; + } + FREE(unique->map); + unique->map = newmap; + } + /* Install the new tables and free the old ones. */ + FREE(unique->subtables); + unique->subtables = newsubtables; + unique->maxSize = newsize; + FREE(unique->vars); + unique->vars = newvars; + FREE(unique->perm); + unique->perm = newperm; + FREE(unique->invperm); + unique->invperm = newinvperm; + /* Update the stack for iterative procedures. */ + if (newsize > unique->maxSizeZ) { + FREE(unique->stack); + unique->stack = ALLOC(DdNodePtr,newsize + 1); + if (unique->stack == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->stack[0] = NULL; /* to suppress harmless UMR */ + unique->memused += + (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) + * sizeof(DdNode *); + } + } + /* Update manager parameters to account for the new subtables. */ + unique->slots += n * numSlots; + ddFixLimits(unique); + unique->size += n; + + /* Now that the table is in a coherent state, create the new + ** projection functions. We need to temporarily disable reordering, + ** because we cannot reorder without projection functions in place. + **/ + one = unique->one; + zero = Cudd_Not(one); + + reorderSave = unique->autoDyn; + unique->autoDyn = 0; + for (i = oldsize; i < oldsize + n; i++) { + unique->vars[i] = cuddUniqueInter(unique,i,one,zero); + if (unique->vars[i] == NULL) { + unique->autoDyn = reorderSave; + /* Shift everything back so table remains coherent. */ + for (j = oldsize; j < i; j++) { + Cudd_IterDerefBdd(unique,unique->vars[j]); + cuddDeallocNode(unique,unique->vars[j]); + unique->vars[j] = NULL; + } + for (j = level; j < oldsize; j++) { + unique->subtables[j].slots = unique->subtables[j+n].slots; + unique->subtables[j].slots = unique->subtables[j+n].slots; + unique->subtables[j].shift = unique->subtables[j+n].shift; + unique->subtables[j].keys = unique->subtables[j+n].keys; + unique->subtables[j].maxKeys = + unique->subtables[j+n].maxKeys; + unique->subtables[j].dead = unique->subtables[j+n].dead; + FREE(unique->subtables[j].nodelist); + unique->subtables[j].nodelist = + unique->subtables[j+n].nodelist; + unique->subtables[j+n].nodelist = NULL; + unique->subtables[j].bindVar = + unique->subtables[j+n].bindVar; + unique->subtables[j].varType = + unique->subtables[j+n].varType; + unique->subtables[j].pairIndex = + unique->subtables[j+n].pairIndex; + unique->subtables[j].varHandled = + unique->subtables[j+n].varHandled; + unique->subtables[j].varToBeGrouped = + unique->subtables[j+n].varToBeGrouped; + index = unique->invperm[j+n]; + unique->invperm[j] = index; + unique->perm[index] -= n; + } + unique->size = oldsize; + unique->slots -= n * numSlots; + ddFixLimits(unique); + (void) Cudd_DebugCheck(unique); + return(0); + } + cuddRef(unique->vars[i]); + } + if (unique->tree != NULL) { + unique->tree->size += n; + unique->tree->index = unique->invperm[0]; + ddPatchTree(unique,unique->tree); + } + unique->autoDyn = reorderSave; + + return(1); + +} /* end of cuddInsertSubtables */ + + +/**Function******************************************************************** + + Synopsis [Destroys the n most recently created subtables in a unique table.] + + Description [Destroys the n most recently created subtables in a unique + table. n should be positive. The subtables should not contain any live + nodes, except the (isolated) projection function. The projection + functions are freed. Returns 1 if successful; 0 otherwise.] + + SideEffects [The variable map used for fast variable substitution is + destroyed if it exists. In this case the cache is also cleared.] + + SeeAlso [cuddInsertSubtables Cudd_SetVarMap] + +******************************************************************************/ +int +cuddDestroySubtables( + DdManager * unique, + int n) +{ + DdSubtable *subtables; + DdNodePtr *nodelist; + DdNodePtr *vars; + int firstIndex, lastIndex; + int index, level, newlevel; + int lowestLevel; + int shift; + int found; + + /* Sanity check and set up. */ + if (n <= 0) return(0); + if (n > unique->size) n = unique->size; + + subtables = unique->subtables; + vars = unique->vars; + firstIndex = unique->size - n; + lastIndex = unique->size; + + /* Check for nodes labeled by the variables being destroyed + ** that may still be in use. It is allowed to destroy a variable + ** only if there are no such nodes. Also, find the lowest level + ** among the variables being destroyed. This will make further + ** processing more efficient. + */ + lowestLevel = unique->size; + for (index = firstIndex; index < lastIndex; index++) { + level = unique->perm[index]; + if (level < lowestLevel) lowestLevel = level; + nodelist = subtables[level].nodelist; + if (subtables[level].keys - subtables[level].dead != 1) return(0); + /* The projection function should be isolated. If the ref count + ** is 1, everything is OK. If the ref count is saturated, then + ** we need to make sure that there are no nodes pointing to it. + ** As for the external references, we assume the application is + ** responsible for them. + */ + if (vars[index]->ref != 1) { + if (vars[index]->ref != DD_MAXREF) return(0); + found = cuddFindParent(unique,vars[index]); + if (found) { + return(0); + } else { + vars[index]->ref = 1; + } + } + Cudd_RecursiveDeref(unique,vars[index]); + } + + /* Collect garbage, because we cannot afford having dead nodes pointing + ** to the dead nodes in the subtables being destroyed. + */ + (void) cuddGarbageCollect(unique,1); + + /* Here we know we can destroy our subtables. */ + for (index = firstIndex; index < lastIndex; index++) { + level = unique->perm[index]; + nodelist = subtables[level].nodelist; +#ifdef DD_DEBUG + assert(subtables[level].keys == 0); +#endif + FREE(nodelist); + unique->memused -= sizeof(DdNodePtr) * subtables[level].slots; + unique->slots -= subtables[level].slots; + unique->dead -= subtables[level].dead; + } + + /* Here all subtables to be destroyed have their keys field == 0 and + ** their hash tables have been freed. + ** We now scan the subtables from level lowestLevel + 1 to level size - 1, + ** shifting the subtables as required. We keep a running count of + ** how many subtables have been moved, so that we know by how many + ** positions each subtable should be shifted. + */ + shift = 1; + for (level = lowestLevel + 1; level < unique->size; level++) { + if (subtables[level].keys == 0) { + shift++; + continue; + } + newlevel = level - shift; + subtables[newlevel].slots = subtables[level].slots; + subtables[newlevel].shift = subtables[level].shift; + subtables[newlevel].keys = subtables[level].keys; + subtables[newlevel].maxKeys = subtables[level].maxKeys; + subtables[newlevel].dead = subtables[level].dead; + subtables[newlevel].nodelist = subtables[level].nodelist; + index = unique->invperm[level]; + unique->perm[index] = newlevel; + unique->invperm[newlevel] = index; + subtables[newlevel].bindVar = subtables[level].bindVar; + subtables[newlevel].varType = subtables[level].varType; + subtables[newlevel].pairIndex = subtables[level].pairIndex; + subtables[newlevel].varHandled = subtables[level].varHandled; + subtables[newlevel].varToBeGrouped = subtables[level].varToBeGrouped; + } + /* Destroy the map. If a surviving variable is + ** mapped to a dying variable, and the map were used again, + ** an out-of-bounds access to unique->vars would result. */ + if (unique->map != NULL) { + cuddCacheFlush(unique); + FREE(unique->map); + unique->map = NULL; + } + + unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); + unique->size -= n; + + return(1); + +} /* end of cuddDestroySubtables */ + + +/**Function******************************************************************** + + Synopsis [Increases the number of ZDD subtables in a unique table so + that it meets or exceeds index.] + + Description [Increases the number of ZDD subtables in a unique table so + that it meets or exceeds index. When new ZDD variables are created, it + is possible to preserve the functions unchanged, or it is possible to + preserve the covers unchanged, but not both. cuddResizeTableZdd preserves + the covers. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [ddResizeTable] + +******************************************************************************/ +int +cuddResizeTableZdd( + DdManager * unique, + int index) +{ + DdSubtable *newsubtables; + DdNodePtr *newnodelist; + int oldsize,newsize; + int i,j,reorderSave; + unsigned int numSlots = unique->initSlots; + int *newperm, *newinvperm; + DdNode *one, *zero; + + oldsize = unique->sizeZ; + /* Easy case: there is still room in the current table. */ + if (index < unique->maxSizeZ) { + for (i = oldsize; i <= index; i++) { + unique->subtableZ[i].slots = numSlots; + unique->subtableZ[i].shift = sizeof(int) * 8 - + cuddComputeFloorLog2(numSlots); + unique->subtableZ[i].keys = 0; + unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; + unique->subtableZ[i].dead = 0; + unique->permZ[i] = i; + unique->invpermZ[i] = i; + newnodelist = unique->subtableZ[i].nodelist = + ALLOC(DdNodePtr, numSlots); + if (newnodelist == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (j = 0; j < numSlots; j++) { + newnodelist[j] = NULL; + } + } + } else { + /* The current table is too small: we need to allocate a new, + ** larger one; move all old subtables, and initialize the new + ** subtables up to index included. + */ + newsize = index + DD_DEFAULT_RESIZE; +#ifdef DD_VERBOSE + (void) fprintf(unique->err, + "Increasing the ZDD table size from %d to %d\n", + unique->maxSizeZ, newsize); +#endif + newsubtables = ALLOC(DdSubtable,newsize); + if (newsubtables == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newperm = ALLOC(int,newsize); + if (newperm == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newinvperm = ALLOC(int,newsize); + if (newinvperm == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) * + sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); + if (newsize > unique->maxSize) { + FREE(unique->stack); + unique->stack = ALLOC(DdNodePtr,newsize + 1); + if (unique->stack == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->stack[0] = NULL; /* to suppress harmless UMR */ + unique->memused += + (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) + * sizeof(DdNode *); + } + for (i = 0; i < oldsize; i++) { + newsubtables[i].slots = unique->subtableZ[i].slots; + newsubtables[i].shift = unique->subtableZ[i].shift; + newsubtables[i].keys = unique->subtableZ[i].keys; + newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys; + newsubtables[i].dead = unique->subtableZ[i].dead; + newsubtables[i].nodelist = unique->subtableZ[i].nodelist; + newperm[i] = unique->permZ[i]; + newinvperm[i] = unique->invpermZ[i]; + } + for (i = oldsize; i <= index; i++) { + newsubtables[i].slots = numSlots; + newsubtables[i].shift = sizeof(int) * 8 - + cuddComputeFloorLog2(numSlots); + newsubtables[i].keys = 0; + newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; + newsubtables[i].dead = 0; + newperm[i] = i; + newinvperm[i] = i; + newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); + if (newnodelist == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (j = 0; j < numSlots; j++) { + newnodelist[j] = NULL; + } + } + FREE(unique->subtableZ); + unique->subtableZ = newsubtables; + unique->maxSizeZ = newsize; + FREE(unique->permZ); + unique->permZ = newperm; + FREE(unique->invpermZ); + unique->invpermZ = newinvperm; + } + unique->slots += (index + 1 - unique->sizeZ) * numSlots; + ddFixLimits(unique); + unique->sizeZ = index + 1; + + /* Now that the table is in a coherent state, update the ZDD + ** universe. We need to temporarily disable reordering, + ** because we cannot reorder without universe in place. + */ + one = unique->one; + zero = unique->zero; + + reorderSave = unique->autoDynZ; + unique->autoDynZ = 0; + cuddZddFreeUniv(unique); + if (!cuddZddInitUniv(unique)) { + unique->autoDynZ = reorderSave; + return(0); + } + unique->autoDynZ = reorderSave; + + return(1); + +} /* end of cuddResizeTableZdd */ + + +/**Function******************************************************************** + + Synopsis [Adjusts parameters of a table to slow down its growth.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +cuddSlowTableGrowth( + DdManager *unique) +{ + int i; + + unique->maxCacheHard = unique->cacheSlots - 1; + unique->cacheSlack = -(unique->cacheSlots + 1); + for (i = 0; i < unique->size; i++) { + unique->subtables[i].maxKeys <<= 2; + } + unique->gcFrac = DD_GC_FRAC_MIN; + unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); + cuddShrinkDeathRow(unique); + (void) fprintf(unique->err,"Slowing down table growth: "); + (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac); + (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); + +} /* end of cuddSlowTableGrowth */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Rehashes a ZDD unique subtable.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddRehash] + +******************************************************************************/ +static void +ddRehashZdd( + DdManager * unique, + int i) +{ + unsigned int slots, oldslots; + int shift, oldshift; + int j, pos; + DdNodePtr *nodelist, *oldnodelist; + DdNode *node, *next; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); + + if (unique->slots > unique->looseUpTo) { + unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); +#ifdef DD_VERBOSE + if (unique->gcFrac == DD_GC_FRAC_HI) { + (void) fprintf(unique->err,"GC fraction = %.2f\t", + DD_GC_FRAC_LO); + (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); + } +#endif + unique->gcFrac = DD_GC_FRAC_LO; + } + + assert(i != CUDD_MAXINDEX); + oldslots = unique->subtableZ[i].slots; + oldshift = unique->subtableZ[i].shift; + oldnodelist = unique->subtableZ[i].nodelist; + + /* Compute the new size of the subtable. Normally, we just + ** double. However, after reordering, a table may be severely + ** overloaded. Therefore, we iterate. */ + slots = oldslots; + shift = oldshift; + do { + slots <<= 1; + shift--; + } while (slots * DD_MAX_SUBTABLE_DENSITY < unique->subtableZ[i].keys); + + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + nodelist = ALLOC(DdNodePtr, slots); + MMoutOfMemory = saveHandler; + if (nodelist == NULL) { + int j; + (void) fprintf(unique->err, + "Unable to resize ZDD subtable %d for lack of memory.\n", + i); + (void) cuddGarbageCollectZdd(unique,1); + for (j = 0; j < unique->sizeZ; j++) { + unique->subtableZ[j].maxKeys <<= 1; + } + return; + } + unique->subtableZ[i].nodelist = nodelist; + unique->subtableZ[i].slots = slots; + unique->subtableZ[i].shift = shift; + unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; + for (j = 0; (unsigned) j < slots; j++) { + nodelist[j] = NULL; + } + for (j = 0; (unsigned) j < oldslots; j++) { + node = oldnodelist[j]; + while (node != NULL) { + next = node->next; + pos = ddHash(cuddT(node), cuddE(node), shift); + node->next = nodelist[pos]; + nodelist[pos] = node; + node = next; + } + } + FREE(oldnodelist); + +#ifdef DD_VERBOSE + (void) fprintf(unique->err, + "rehashing layer %d: keys %d dead %d new size %d\n", + i, unique->subtableZ[i].keys, + unique->subtableZ[i].dead, slots); +#endif + + /* Update global data. */ + unique->memused += (slots - oldslots) * sizeof(DdNode *); + unique->slots += (slots - oldslots); + ddFixLimits(unique); + +} /* end of ddRehashZdd */ + + +/**Function******************************************************************** + + Synopsis [Increases the number of subtables in a unique table so + that it meets or exceeds index.] + + Description [Increases the number of subtables in a unique table so + that it meets or exceeds index. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [cuddResizeTableZdd] + +******************************************************************************/ +static int +ddResizeTable( + DdManager * unique, + int index) +{ + DdSubtable *newsubtables; + DdNodePtr *newnodelist; + DdNodePtr *newvars; + DdNode *sentinel = &(unique->sentinel); + int oldsize,newsize; + int i,j,reorderSave; + int numSlots = unique->initSlots; + int *newperm, *newinvperm, *newmap; + DdNode *one, *zero; + + oldsize = unique->size; + /* Easy case: there is still room in the current table. */ + if (index < unique->maxSize) { + for (i = oldsize; i <= index; i++) { + unique->subtables[i].slots = numSlots; + unique->subtables[i].shift = sizeof(int) * 8 - + cuddComputeFloorLog2(numSlots); + unique->subtables[i].keys = 0; + unique->subtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; + unique->subtables[i].dead = 0; + unique->subtables[i].bindVar = 0; + unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; + unique->subtables[i].pairIndex = 0; + unique->subtables[i].varHandled = 0; + unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; + + unique->perm[i] = i; + unique->invperm[i] = i; + newnodelist = unique->subtables[i].nodelist = + ALLOC(DdNodePtr, numSlots); + if (newnodelist == NULL) { + for (j = oldsize; j < i; j++) { + FREE(unique->subtables[j].nodelist); + } + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (j = 0; j < numSlots; j++) { + newnodelist[j] = sentinel; + } + } + if (unique->map != NULL) { + for (i = oldsize; i <= index; i++) { + unique->map[i] = i; + } + } + } else { + /* The current table is too small: we need to allocate a new, + ** larger one; move all old subtables, and initialize the new + ** subtables up to index included. + */ + newsize = index + DD_DEFAULT_RESIZE; +#ifdef DD_VERBOSE + (void) fprintf(unique->err, + "Increasing the table size from %d to %d\n", + unique->maxSize, newsize); +#endif + newsubtables = ALLOC(DdSubtable,newsize); + if (newsubtables == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newvars = ALLOC(DdNodePtr,newsize); + if (newvars == NULL) { + FREE(newsubtables); + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newperm = ALLOC(int,newsize); + if (newperm == NULL) { + FREE(newsubtables); + FREE(newvars); + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + newinvperm = ALLOC(int,newsize); + if (newinvperm == NULL) { + FREE(newsubtables); + FREE(newvars); + FREE(newperm); + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + if (unique->map != NULL) { + newmap = ALLOC(int,newsize); + if (newmap == NULL) { + FREE(newsubtables); + FREE(newvars); + FREE(newperm); + FREE(newinvperm); + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->memused += (newsize - unique->maxSize) * sizeof(int); + } + unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * + sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); + if (newsize > unique->maxSizeZ) { + FREE(unique->stack); + unique->stack = ALLOC(DdNodePtr,newsize + 1); + if (unique->stack == NULL) { + FREE(newsubtables); + FREE(newvars); + FREE(newperm); + FREE(newinvperm); + if (unique->map != NULL) { + FREE(newmap); + } + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + unique->stack[0] = NULL; /* to suppress harmless UMR */ + unique->memused += + (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) + * sizeof(DdNode *); + } + for (i = 0; i < oldsize; i++) { + newsubtables[i].slots = unique->subtables[i].slots; + newsubtables[i].shift = unique->subtables[i].shift; + newsubtables[i].keys = unique->subtables[i].keys; + newsubtables[i].maxKeys = unique->subtables[i].maxKeys; + newsubtables[i].dead = unique->subtables[i].dead; + newsubtables[i].nodelist = unique->subtables[i].nodelist; + newsubtables[i].bindVar = unique->subtables[i].bindVar; + newsubtables[i].varType = unique->subtables[i].varType; + newsubtables[i].pairIndex = unique->subtables[i].pairIndex; + newsubtables[i].varHandled = unique->subtables[i].varHandled; + newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; + + newvars[i] = unique->vars[i]; + newperm[i] = unique->perm[i]; + newinvperm[i] = unique->invperm[i]; + } + for (i = oldsize; i <= index; i++) { + newsubtables[i].slots = numSlots; + newsubtables[i].shift = sizeof(int) * 8 - + cuddComputeFloorLog2(numSlots); + newsubtables[i].keys = 0; + newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; + newsubtables[i].dead = 0; + newsubtables[i].bindVar = 0; + newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; + newsubtables[i].pairIndex = 0; + newsubtables[i].varHandled = 0; + newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; + + newperm[i] = i; + newinvperm[i] = i; + newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); + if (newnodelist == NULL) { + unique->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (j = 0; j < numSlots; j++) { + newnodelist[j] = sentinel; + } + } + if (unique->map != NULL) { + for (i = 0; i < oldsize; i++) { + newmap[i] = unique->map[i]; + } + for (i = oldsize; i <= index; i++) { + newmap[i] = i; + } + FREE(unique->map); + unique->map = newmap; + } + FREE(unique->subtables); + unique->subtables = newsubtables; + unique->maxSize = newsize; + FREE(unique->vars); + unique->vars = newvars; + FREE(unique->perm); + unique->perm = newperm; + FREE(unique->invperm); + unique->invperm = newinvperm; + } + + /* Now that the table is in a coherent state, create the new + ** projection functions. We need to temporarily disable reordering, + ** because we cannot reorder without projection functions in place. + **/ + one = unique->one; + zero = Cudd_Not(one); + + unique->size = index + 1; + unique->slots += (index + 1 - oldsize) * numSlots; + ddFixLimits(unique); + + reorderSave = unique->autoDyn; + unique->autoDyn = 0; + for (i = oldsize; i <= index; i++) { + unique->vars[i] = cuddUniqueInter(unique,i,one,zero); + if (unique->vars[i] == NULL) { + unique->autoDyn = reorderSave; + for (j = oldsize; j < i; j++) { + Cudd_IterDerefBdd(unique,unique->vars[j]); + cuddDeallocNode(unique,unique->vars[j]); + unique->vars[j] = NULL; + } + for (j = oldsize; j <= index; j++) { + FREE(unique->subtables[j].nodelist); + unique->subtables[j].nodelist = NULL; + } + unique->size = oldsize; + unique->slots -= (index + 1 - oldsize) * numSlots; + ddFixLimits(unique); + return(0); + } + cuddRef(unique->vars[i]); + } + unique->autoDyn = reorderSave; + + return(1); + +} /* end of ddResizeTable */ + + +/**Function******************************************************************** + + Synopsis [Searches the subtables above node for a parent.] + + Description [Searches the subtables above node for a parent. Returns 1 + as soon as one parent is found. Returns 0 is the search is fruitless.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddFindParent( + DdManager * table, + DdNode * node) +{ + int i,j; + int slots; + DdNodePtr *nodelist; + DdNode *f; + + for (i = cuddI(table,node->index) - 1; i >= 0; i--) { + nodelist = table->subtables[i].nodelist; + slots = table->subtables[i].slots; + + for (j = 0; j < slots; j++) { + f = nodelist[j]; + while (cuddT(f) > node) { + f = f->next; + } + while (cuddT(f) == node && Cudd_Regular(cuddE(f)) > node) { + f = f->next; + } + if (cuddT(f) == node && Cudd_Regular(cuddE(f)) == node) { + return(1); + } + } + } + + return(0); + +} /* end of cuddFindParent */ + + +/**Function******************************************************************** + + Synopsis [Adjusts the values of table limits.] + + Description [Adjusts the values of table fields controlling the. + sizes of subtables and computed table. If the computed table is too small + according to the new values, it is resized.] + + SideEffects [Modifies manager fields. May resize computed table.] + + SeeAlso [] + +******************************************************************************/ +DD_INLINE +static void +ddFixLimits( + DdManager *unique) +{ + unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); + unique->cacheSlack = (int) ddMin(unique->maxCacheHard, + DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) - + 2 * (int) unique->cacheSlots; + if (unique->cacheSlots < unique->slots/2 && unique->cacheSlack >= 0) + cuddCacheResize(unique); + return; + +} /* end of ddFixLimits */ + + +#ifndef DD_UNSORTED_FREE_LIST +/**Function******************************************************************** + + Synopsis [Inserts a DdNode in a red/black search tree.] + + Description [Inserts a DdNode in a red/black search tree. Nodes from + the same "page" (defined by DD_PAGE_MASK) are linked in a LIFO list.] + + SideEffects [None] + + SeeAlso [cuddOrderedThread] + +******************************************************************************/ +static void +cuddOrderedInsert( + DdNodePtr * root, + DdNodePtr node) +{ + DdNode *scan; + DdNodePtr *scanP; + DdNodePtr *stack[DD_STACK_SIZE]; + int stackN = 0; + + scanP = root; + while ((scan = *scanP) != NULL) { + stack[stackN++] = scanP; + if (DD_INSERT_COMPARE(node, scan) == 0) { /* add to page list */ + DD_NEXT(node) = DD_NEXT(scan); + DD_NEXT(scan) = node; + return; + } + scanP = (node < scan) ? &DD_LEFT(scan) : &DD_RIGHT(scan); + } + DD_RIGHT(node) = DD_LEFT(node) = DD_NEXT(node) = NULL; + DD_COLOR(node) = DD_RED; + *scanP = node; + stack[stackN] = &node; + cuddDoRebalance(stack,stackN); + +} /* end of cuddOrderedInsert */ + + +/**Function******************************************************************** + + Synopsis [Threads all the nodes of a search tree into a linear list.] + + Description [Threads all the nodes of a search tree into a linear + list. For each node of the search tree, the "left" child, if non-null, has + a lower address than its parent, and the "right" child, if non-null, has a + higher address than its parent. + The list is sorted in order of increasing addresses. The search + tree is destroyed as a result of this operation. The last element of + the linear list is made to point to the address passed in list. Each + node if the search tree is a linearly-linked list of nodes from the + same memory page (as defined in DD_PAGE_MASK). When a node is added to + the linear list, all the elements of the linked list are added.] + + SideEffects [The search tree is destroyed as a result of this operation.] + + SeeAlso [cuddOrderedInsert] + +******************************************************************************/ +static DdNode * +cuddOrderedThread( + DdNode * root, + DdNode * list) +{ + DdNode *current, *next, *prev, *end; + + current = root; + /* The first word in the node is used to implement a stack that holds + ** the nodes from the root of the tree to the current node. Here we + ** put the root of the tree at the bottom of the stack. + */ + *((DdNodePtr *) current) = NULL; + + while (current != NULL) { + if (DD_RIGHT(current) != NULL) { + /* If possible, we follow the "right" link. Eventually we'll + ** find the node with the largest address in the current tree. + ** In this phase we use the first word of a node to implemen + ** a stack of the nodes on the path from the root to "current". + ** Also, we disconnect the "right" pointers to indicate that + ** we have already followed them. + */ + next = DD_RIGHT(current); + DD_RIGHT(current) = NULL; + *((DdNodePtr *)next) = current; + current = next; + } else { + /* We can't proceed along the "right" links any further. + ** Hence "current" is the largest element in the current tree. + ** We make this node the new head of "list". (Repeating this + ** operation until the tree is empty yields the desired linear + ** threading of all nodes.) + */ + prev = *((DdNodePtr *) current); /* save prev node on stack in prev */ + /* Traverse the linked list of current until the end. */ + for (end = current; DD_NEXT(end) != NULL; end = DD_NEXT(end)); + DD_NEXT(end) = list; /* attach "list" at end and make */ + list = current; /* "current" the new head of "list" */ + /* Now, if current has a "left" child, we push it on the stack. + ** Otherwise, we just continue with the parent of "current". + */ + if (DD_LEFT(current) != NULL) { + next = DD_LEFT(current); + *((DdNodePtr *) next) = prev; + current = next; + } else { + current = prev; + } + } + } + + return(list); + +} /* end of cuddOrderedThread */ + + +/**Function******************************************************************** + + Synopsis [Performs the left rotation for red/black trees.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddRotateRight] + +******************************************************************************/ +DD_INLINE +static void +cuddRotateLeft( + DdNodePtr * nodeP) +{ + DdNode *newRoot; + DdNode *oldRoot = *nodeP; + + *nodeP = newRoot = DD_RIGHT(oldRoot); + DD_RIGHT(oldRoot) = DD_LEFT(newRoot); + DD_LEFT(newRoot) = oldRoot; + +} /* end of cuddRotateLeft */ + + +/**Function******************************************************************** + + Synopsis [Performs the right rotation for red/black trees.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddRotateLeft] + +******************************************************************************/ +DD_INLINE +static void +cuddRotateRight( + DdNodePtr * nodeP) +{ + DdNode *newRoot; + DdNode *oldRoot = *nodeP; + + *nodeP = newRoot = DD_LEFT(oldRoot); + DD_LEFT(oldRoot) = DD_RIGHT(newRoot); + DD_RIGHT(newRoot) = oldRoot; + +} /* end of cuddRotateRight */ + + +/**Function******************************************************************** + + Synopsis [Rebalances a red/black tree.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +cuddDoRebalance( + DdNodePtr ** stack, + int stackN) +{ + DdNodePtr *xP, *parentP, *grandpaP; + DdNode *x, *y, *parent, *grandpa; + + xP = stack[stackN]; + x = *xP; + /* Work our way back up, re-balancing the tree. */ + while (--stackN >= 0) { + parentP = stack[stackN]; + parent = *parentP; + if (DD_IS_BLACK(parent)) break; + /* Since the root is black, here a non-null grandparent exists. */ + grandpaP = stack[stackN-1]; + grandpa = *grandpaP; + if (parent == DD_LEFT(grandpa)) { + y = DD_RIGHT(grandpa); + if (y != NULL && DD_IS_RED(y)) { + DD_COLOR(parent) = DD_BLACK; + DD_COLOR(y) = DD_BLACK; + DD_COLOR(grandpa) = DD_RED; + x = grandpa; + stackN--; + } else { + if (x == DD_RIGHT(parent)) { + cuddRotateLeft(parentP); + DD_COLOR(x) = DD_BLACK; + } else { + DD_COLOR(parent) = DD_BLACK; + } + DD_COLOR(grandpa) = DD_RED; + cuddRotateRight(grandpaP); + break; + } + } else { + y = DD_LEFT(grandpa); + if (y != NULL && DD_IS_RED(y)) { + DD_COLOR(parent) = DD_BLACK; + DD_COLOR(y) = DD_BLACK; + DD_COLOR(grandpa) = DD_RED; + x = grandpa; + stackN--; + } else { + if (x == DD_LEFT(parent)) { + cuddRotateRight(parentP); + DD_COLOR(x) = DD_BLACK; + } else { + DD_COLOR(parent) = DD_BLACK; + } + DD_COLOR(grandpa) = DD_RED; + cuddRotateLeft(grandpaP); + } + } + } + DD_COLOR(*(stack[0])) = DD_BLACK; + +} /* end of cuddDoRebalance */ +#endif + + +/**Function******************************************************************** + + Synopsis [Fixes a variable tree after the insertion of new subtables.] + + Description [Fixes a variable tree after the insertion of new subtables. + After such an insertion, the low fields of the tree below the insertion + point are inconsistent.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +ddPatchTree( + DdManager *dd, + MtrNode *treenode) +{ + MtrNode *auxnode = treenode; + + while (auxnode != NULL) { + auxnode->low = dd->perm[auxnode->index]; + if (auxnode->child != NULL) { + ddPatchTree(dd, auxnode->child); + } + auxnode = auxnode->younger; + } + + return; + +} /* end of ddPatchTree */ + + +#ifdef DD_DEBUG +/**Function******************************************************************** + + Synopsis [Checks whether a collision list is ordered.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddCheckCollisionOrdering( + DdManager *unique, + int i, + int j) +{ + int slots; + DdNode *node, *next; + DdNodePtr *nodelist; + DdNode *sentinel = &(unique->sentinel); + + nodelist = unique->subtables[i].nodelist; + slots = unique->subtables[i].slots; + node = nodelist[j]; + if (node == sentinel) return(1); + next = node->next; + while (next != sentinel) { + if (cuddT(node) < cuddT(next) || + (cuddT(node) == cuddT(next) && cuddE(node) < cuddE(next))) { + (void) fprintf(unique->err, + "Unordered list: index %u, position %d\n", i, j); + return(0); + } + node = next; + next = node->next; + } + return(1); + +} /* end of cuddCheckCollisionOrdering */ +#endif + + + + +/**Function******************************************************************** + + Synopsis [Reports problem in garbage collection.] + + Description [] + + SideEffects [None] + + SeeAlso [cuddGarbageCollect cuddGarbageCollectZdd] + +******************************************************************************/ +static void +ddReportRefMess( + DdManager *unique /* manager */, + int i /* table in which the problem occurred */, + char *caller /* procedure that detected the problem */) +{ + if (i == CUDD_CONST_INDEX) { + (void) fprintf(unique->err, + "%s: problem in constants\n", caller); + } else if (i != -1) { + (void) fprintf(unique->err, + "%s: problem in table %d\n", caller, i); + } + (void) fprintf(unique->err, " dead count != deleted\n"); + (void) fprintf(unique->err, " This problem is often due to a missing \ +call to Cudd_Ref\n or to an extra call to Cudd_RecursiveDeref.\n \ +See the CUDD Programmer's Guide for additional details."); + abort(); + +} /* end of ddReportRefMess */ diff --git a/abc70930/src/bdd/cudd/cuddUtil.c b/abc70930/src/bdd/cudd/cuddUtil.c new file mode 100644 index 00000000..d5fa18e2 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddUtil.c @@ -0,0 +1,3633 @@ +/**CFile*********************************************************************** + + FileName [cuddUtil.c] + + PackageName [cudd] + + Synopsis [Utility functions.] + + Description [External procedures included in this module: +
          +
        • Cudd_PrintMinterm() +
        • Cudd_PrintDebug() +
        • Cudd_DagSize() +
        • Cudd_EstimateCofactor() +
        • Cudd_EstimateCofactorSimple() +
        • Cudd_SharingSize() +
        • Cudd_CountMinterm() +
        • Cudd_EpdCountMinterm() +
        • Cudd_CountPath() +
        • Cudd_CountPathsToNonZero() +
        • Cudd_Support() +
        • Cudd_SupportIndex() +
        • Cudd_SupportSize() +
        • Cudd_VectorSupport() +
        • Cudd_VectorSupportIndex() +
        • Cudd_VectorSupportSize() +
        • Cudd_ClassifySupport() +
        • Cudd_CountLeaves() +
        • Cudd_bddPickOneCube() +
        • Cudd_bddPickOneMinterm() +
        • Cudd_bddPickArbitraryMinterms() +
        • Cudd_SubsetWithMaskVars() +
        • Cudd_FirstCube() +
        • Cudd_NextCube() +
        • Cudd_bddComputeCube() +
        • Cudd_addComputeCube() +
        • Cudd_FirstNode() +
        • Cudd_NextNode() +
        • Cudd_GenFree() +
        • Cudd_IsGenEmpty() +
        • Cudd_IndicesToCube() +
        • Cudd_PrintVersion() +
        • Cudd_AverageDistance() +
        • Cudd_Random() +
        • Cudd_Srandom() +
        • Cudd_Density() +
        + Internal procedures included in this module: +
          +
        • cuddP() +
        • cuddStCountfree() +
        • cuddCollectNodes() +
        + Static procedures included in this module: +
          +
        • dp2() +
        • ddPrintMintermAux() +
        • ddDagInt() +
        • ddCountMintermAux() +
        • ddEpdCountMintermAux() +
        • ddCountPathAux() +
        • ddSupportStep() +
        • ddClearFlag() +
        • ddLeavesInt() +
        • ddPickArbitraryMinterms() +
        • ddPickRepresentativeCube() +
        • ddEpdFree() +
        ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/* Random generator constants. */ +#define MODULUS1 2147483563 +#define LEQA1 40014 +#define LEQQ1 53668 +#define LEQR1 12211 +#define MODULUS2 2147483399 +#define LEQA2 40692 +#define LEQQ2 52774 +#define LEQR2 3791 +#define STAB_SIZE 64 +#define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE) + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddUtil.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +static DdNode *background, *zero; + +static long cuddRand = 0; +static long cuddRand2; +static long shuffleSelect; +static long shuffleTable[STAB_SIZE]; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define bang(f) ((Cudd_IsComplement(f)) ? '!' : ' ') + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int dp2 ARGS((DdManager *dd, DdNode *f, st_table *t)); +static void ddPrintMintermAux ARGS((DdManager *dd, DdNode *node, int *list)); +static int ddDagInt ARGS((DdNode *n)); +static int cuddEstimateCofactor ARGS((DdManager *dd, st_table *table, DdNode * node, int i, int phase, DdNode ** ptr)); +static DdNode * cuddUniqueLookup ARGS((DdManager * unique, int index, DdNode * T, DdNode * E)); +static int cuddEstimateCofactorSimple ARGS((DdNode * node, int i)); +static double ddCountMintermAux ARGS((DdNode *node, double max, DdHashTable *table)); +static int ddEpdCountMintermAux ARGS((DdNode *node, EpDouble *max, EpDouble *epd, st_table *table)); +static double ddCountPathAux ARGS((DdNode *node, st_table *table)); +static double ddCountPathsToNonZero ARGS((DdNode * N, st_table * table)); +static void ddSupportStep ARGS((DdNode *f, int *support)); +static void ddClearFlag ARGS((DdNode *f)); +static int ddLeavesInt ARGS((DdNode *n)); +static int ddPickArbitraryMinterms ARGS((DdManager *dd, DdNode *node, int nvars, int nminterms, char **string)); +static int ddPickRepresentativeCube ARGS((DdManager *dd, DdNode *node, int nvars, double *weight, char *string)); +static enum st_retval ddEpdFree ARGS((char * key, char * value, char * arg)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Prints a disjoint sum of products.] + + Description [Prints a disjoint sum of product cover for the function + rooted at node. Each product corresponds to a path from node to a + leaf node different from the logical zero, and different from the + background value. Uses the package default output file. Returns 1 + if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_PrintDebug Cudd_bddPrintCover] + +******************************************************************************/ +int +Cudd_PrintMinterm( + DdManager * manager, + DdNode * node) +{ + int i, *list; + + background = manager->background; + zero = Cudd_Not(manager->one); + list = ALLOC(int,manager->size); + if (list == NULL) { + manager->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (i = 0; i < manager->size; i++) list[i] = 2; + ddPrintMintermAux(manager,node,list); + FREE(list); + return(1); + +} /* end of Cudd_PrintMinterm */ + + +/**Function******************************************************************** + + Synopsis [Prints a sum of prime implicants of a BDD.] + + Description [Prints a sum of product cover for an incompletely + specified function given by a lower bound and an upper bound. Each + product is a prime implicant obtained by expanding the product + corresponding to a path from node to the constant one. Uses the + package default output file. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_PrintMinterm] + +******************************************************************************/ +int +Cudd_bddPrintCover( + DdManager *dd, + DdNode *l, + DdNode *u) +{ + int *array; + int q, result; + DdNode *lb; +#ifdef DD_DEBUG + DdNode *cover; +#endif + + array = ALLOC(int, Cudd_ReadSize(dd)); + if (array == NULL) return(0); + lb = l; + cuddRef(lb); +#ifdef DD_DEBUG + cover = Cudd_ReadLogicZero(dd); + cuddRef(cover); +#endif + while (lb != Cudd_ReadLogicZero(dd)) { + DdNode *implicant, *prime, *tmp; + int length; + implicant = Cudd_LargestCube(dd,lb,&length); + if (implicant == NULL) { + Cudd_RecursiveDeref(dd,lb); + FREE(array); + return(0); + } + cuddRef(implicant); + prime = Cudd_bddMakePrime(dd,implicant,u); + if (prime == NULL) { + Cudd_RecursiveDeref(dd,lb); + Cudd_RecursiveDeref(dd,implicant); + FREE(array); + return(0); + } + cuddRef(prime); + Cudd_RecursiveDeref(dd,implicant); + tmp = Cudd_bddAnd(dd,lb,Cudd_Not(prime)); + if (tmp == NULL) { + Cudd_RecursiveDeref(dd,lb); + Cudd_RecursiveDeref(dd,prime); + FREE(array); + return(0); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,lb); + lb = tmp; + result = Cudd_BddToCubeArray(dd,prime,array); + if (result == 0) { + Cudd_RecursiveDeref(dd,lb); + Cudd_RecursiveDeref(dd,prime); + FREE(array); + return(0); + } + for (q = 0; q < dd->size; q++) { + switch (array[q]) { + case 0: + (void) fprintf(dd->out, "0"); + break; + case 1: + (void) fprintf(dd->out, "1"); + break; + case 2: + (void) fprintf(dd->out, "-"); + break; + default: + (void) fprintf(dd->out, "?"); + } + } + (void) fprintf(dd->out, " 1\n"); +#ifdef DD_DEBUG + tmp = Cudd_bddOr(dd,prime,cover); + if (tmp == NULL) { + Cudd_RecursiveDeref(dd,cover); + Cudd_RecursiveDeref(dd,lb); + Cudd_RecursiveDeref(dd,prime); + FREE(array); + return(0); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,cover); + cover = tmp; +#endif + Cudd_RecursiveDeref(dd,prime); + } + (void) fprintf(dd->out, "\n"); + Cudd_RecursiveDeref(dd,lb); + FREE(array); +#ifdef DD_DEBUG + if (!Cudd_bddLeq(dd,cover,u) || !Cudd_bddLeq(dd,l,cover)) { + Cudd_RecursiveDeref(dd,cover); + return(0); + } + Cudd_RecursiveDeref(dd,cover); +#endif + return(1); + +} /* end of Cudd_bddPrintCover */ + + +/**Function******************************************************************** + + Synopsis [Prints to the standard output a DD and its statistics.] + + Description [Prints to the standard output a DD and its statistics. + The statistics include the number of nodes, the number of leaves, and + the number of minterms. (The number of minterms is the number of + assignments to the variables that cause the function to be different + from the logical zero (for BDDs) and from the background value (for + ADDs.) The statistics are printed if pr > 0. Specifically: +
          +
        • pr = 0 : prints nothing +
        • pr = 1 : prints counts of nodes and minterms +
        • pr = 2 : prints counts + disjoint sum of product +
        • pr = 3 : prints counts + list of nodes +
        • pr > 3 : prints counts + disjoint sum of product + list of nodes +
        + For the purpose of counting the number of minterms, the function is + supposed to depend on n variables. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_DagSize Cudd_CountLeaves Cudd_CountMinterm + Cudd_PrintMinterm] + +******************************************************************************/ +int +Cudd_PrintDebug( + DdManager * dd, + DdNode * f, + int n, + int pr) +{ + DdNode *azero, *bzero; + int nodes; + int leaves; + double minterms; + int retval = 1; + + if (f == NULL) { + (void) fprintf(dd->out,": is the NULL DD\n"); + (void) fflush(dd->out); + return(0); + } + azero = DD_ZERO(dd); + bzero = Cudd_Not(DD_ONE(dd)); + if ((f == azero || f == bzero) && pr > 0){ + (void) fprintf(dd->out,": is the zero DD\n"); + (void) fflush(dd->out); + return(1); + } + if (pr > 0) { + nodes = Cudd_DagSize(f); + if (nodes == CUDD_OUT_OF_MEM) retval = 0; + leaves = Cudd_CountLeaves(f); + if (leaves == CUDD_OUT_OF_MEM) retval = 0; + minterms = Cudd_CountMinterm(dd, f, n); + if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0; + (void) fprintf(dd->out,": %d nodes %d leaves %g minterms\n", + nodes, leaves, minterms); + if (pr > 2) { + if (!cuddP(dd, f)) retval = 0; + } + if (pr == 2 || pr > 3) { + if (!Cudd_PrintMinterm(dd,f)) retval = 0; + (void) fprintf(dd->out,"\n"); + } + (void) fflush(dd->out); + } + return(retval); + +} /* end of Cudd_PrintDebug */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of nodes in a DD.] + + Description [Counts the number of nodes in a DD. Returns the number + of nodes in the graph rooted at node.] + + SideEffects [None] + + SeeAlso [Cudd_SharingSize Cudd_PrintDebug] + +******************************************************************************/ +int +Cudd_DagSize( + DdNode * node) +{ + int i; + + i = ddDagInt(Cudd_Regular(node)); + ddClearFlag(Cudd_Regular(node)); + + return(i); + +} /* end of Cudd_DagSize */ + + +/**Function******************************************************************** + + Synopsis [Estimates the number of nodes in a cofactor of a DD.] + + Description [Estimates the number of nodes in a cofactor of a DD. + Returns an estimate of the number of nodes in a cofactor of + the graph rooted at node with respect to the variable whose index is i. + In case of failure, returns CUDD_OUT_OF_MEM. + This function uses a refinement of the algorithm of Cabodi et al. + (ICCAD96). The refinement allows the procedure to account for part + of the recombination that may occur in the part of the cofactor above + the cofactoring variable. This procedure does no create any new node. + It does keep a small table of results; therefore itmay run out of memory. + If this is a concern, one should use Cudd_EstimateCofactorSimple, which + is faster, does not allocate any memory, but is less accurate.] + + SideEffects [None] + + SeeAlso [Cudd_DagSize Cudd_EstimateCofactorSimple] + +******************************************************************************/ +int +Cudd_EstimateCofactor( + DdManager *dd /* manager */, + DdNode * f /* function */, + int i /* index of variable */, + int phase /* 1: positive; 0: negative */ + ) +{ + int val; + DdNode *ptr; + st_table *table; + + table = st_init_table(st_ptrcmp,st_ptrhash); + if (table == NULL) return(CUDD_OUT_OF_MEM); + val = cuddEstimateCofactor(dd,table,Cudd_Regular(f),i,phase,&ptr); + ddClearFlag(Cudd_Regular(f)); + st_free_table(table); + + return(val); + +} /* end of Cudd_EstimateCofactor */ + + +/**Function******************************************************************** + + Synopsis [Estimates the number of nodes in a cofactor of a DD.] + + Description [Estimates the number of nodes in a cofactor of a DD. + Returns an estimate of the number of nodes in the positive cofactor of + the graph rooted at node with respect to the variable whose index is i. + This procedure implements with minor changes the algorithm of Cabodi et al. + (ICCAD96). It does not allocate any memory, it does not change the + state of the manager, and it is fast. However, it has been observed to + overestimate the size of the cofactor by as much as a factor of 2.] + + SideEffects [None] + + SeeAlso [Cudd_DagSize] + +******************************************************************************/ +int +Cudd_EstimateCofactorSimple( + DdNode * node, + int i) +{ + int val; + + val = cuddEstimateCofactorSimple(Cudd_Regular(node),i); + ddClearFlag(Cudd_Regular(node)); + + return(val); + +} /* end of Cudd_EstimateCofactorSimple */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of nodes in an array of DDs.] + + Description [Counts the number of nodes in an array of DDs. Shared + nodes are counted only once. Returns the total number of nodes.] + + SideEffects [None] + + SeeAlso [Cudd_DagSize] + +******************************************************************************/ +int +Cudd_SharingSize( + DdNode ** nodeArray, + int n) +{ + int i,j; + + i = 0; + for (j = 0; j < n; j++) { + i += ddDagInt(Cudd_Regular(nodeArray[j])); + } + for (j = 0; j < n; j++) { + ddClearFlag(Cudd_Regular(nodeArray[j])); + } + return(i); + +} /* end of Cudd_SharingSize */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of minterms of a DD.] + + Description [Counts the number of minterms of a DD. The function is + assumed to depend on nvars variables. The minterm count is + represented as a double, to allow for a larger number of variables. + Returns the number of minterms of the function rooted at node if + successful; (double) CUDD_OUT_OF_MEM otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_PrintDebug Cudd_CountPath] + +******************************************************************************/ +double +Cudd_CountMinterm( + DdManager * manager, + DdNode * node, + int nvars) +{ + double max; + DdHashTable *table; + double res; + CUDD_VALUE_TYPE epsilon; + + background = manager->background; + zero = Cudd_Not(manager->one); + + max = pow(2.0,(double)nvars); + table = cuddHashTableInit(manager,1,2); + if (table == NULL) { + return((double)CUDD_OUT_OF_MEM); + } + epsilon = Cudd_ReadEpsilon(manager); + Cudd_SetEpsilon(manager,(CUDD_VALUE_TYPE)0.0); + res = ddCountMintermAux(node,max,table); + cuddHashTableQuit(table); + Cudd_SetEpsilon(manager,epsilon); + + return(res); + +} /* end of Cudd_CountMinterm */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of paths of a DD.] + + Description [Counts the number of paths of a DD. Paths to all + terminal nodes are counted. The path count is represented as a + double, to allow for a larger number of variables. Returns the + number of paths of the function rooted at node if successful; + (double) CUDD_OUT_OF_MEM otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_CountMinterm] + +******************************************************************************/ +double +Cudd_CountPath( + DdNode * node) +{ + + st_table *table; + double i; + + table = st_init_table(st_ptrcmp,st_ptrhash); + if (table == NULL) { + return((double)CUDD_OUT_OF_MEM); + } + i = ddCountPathAux(Cudd_Regular(node),table); + st_foreach(table, cuddStCountfree, NULL); + st_free_table(table); + return(i); + +} /* end of Cudd_CountPath */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of minterms of a DD with extended precision.] + + Description [Counts the number of minterms of a DD with extended precision. + The function is assumed to depend on nvars variables. The minterm count is + represented as an EpDouble, to allow any number of variables. + Returns 0 if successful; CUDD_OUT_OF_MEM otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_PrintDebug Cudd_CountPath] + +******************************************************************************/ +int +Cudd_EpdCountMinterm( + DdManager * manager, + DdNode * node, + int nvars, + EpDouble * epd) +{ + EpDouble max, tmp; + st_table *table; + int status; + + background = manager->background; + zero = Cudd_Not(manager->one); + + EpdPow2(nvars, &max); + table = st_init_table(EpdCmp, st_ptrhash); + if (table == NULL) { + EpdMakeZero(epd, 0); + return(CUDD_OUT_OF_MEM); + } + status = ddEpdCountMintermAux(Cudd_Regular(node),&max,epd,table); + st_foreach(table, ddEpdFree, NULL); + st_free_table(table); + if (status == CUDD_OUT_OF_MEM) { + EpdMakeZero(epd, 0); + return(CUDD_OUT_OF_MEM); + } + if (Cudd_IsComplement(node)) { + EpdSubtract3(&max, epd, &tmp); + EpdCopy(&tmp, epd); + } + return(0); + +} /* end of Cudd_EpdCountMinterm */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of paths to a non-zero terminal of a DD.] + + Description [Counts the number of paths to a non-zero terminal of a + DD. The path count is + represented as a double, to allow for a larger number of variables. + Returns the number of paths of the function rooted at node.] + + SideEffects [None] + + SeeAlso [Cudd_CountMinterm Cudd_CountPath] + +******************************************************************************/ +double +Cudd_CountPathsToNonZero( + DdNode * node) +{ + + st_table *table; + double i; + + table = st_init_table(st_ptrcmp,st_ptrhash); + if (table == NULL) { + return((double)CUDD_OUT_OF_MEM); + } + i = ddCountPathsToNonZero(node,table); + st_foreach(table, cuddStCountfree, NULL); + st_free_table(table); + return(i); + +} /* end of Cudd_CountPathsToNonZero */ + + +/**Function******************************************************************** + + Synopsis [Finds the variables on which a DD depends.] + + Description [Finds the variables on which a DD depends. + Returns a BDD consisting of the product of the variables if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_VectorSupport Cudd_ClassifySupport] + +******************************************************************************/ +DdNode * +Cudd_Support( + DdManager * dd /* manager */, + DdNode * f /* DD whose support is sought */) +{ + int *support; + DdNode *res, *tmp, *var; + int i,j; + int size; + + /* Allocate and initialize support array for ddSupportStep. */ + size = ddMax(dd->size, dd->sizeZ); + support = ALLOC(int,size); + if (support == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < size; i++) { + support[i] = 0; + } + + /* Compute support and clean up markers. */ + ddSupportStep(Cudd_Regular(f),support); + ddClearFlag(Cudd_Regular(f)); + + /* Transform support from array to cube. */ + do { + dd->reordered = 0; + res = DD_ONE(dd); + cuddRef(res); + for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */ + i = (j >= dd->size) ? j : dd->invperm[j]; + if (support[i] == 1) { + var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); + cuddRef(var); + tmp = cuddBddAndRecur(dd,res,var); + if (tmp == NULL) { + Cudd_RecursiveDeref(dd,res); + Cudd_RecursiveDeref(dd,var); + res = NULL; + break; + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,res); + Cudd_RecursiveDeref(dd,var); + res = tmp; + } + } + } while (dd->reordered == 1); + + FREE(support); + if (res != NULL) cuddDeref(res); + return(res); + +} /* end of Cudd_Support */ + + +/**Function******************************************************************** + + Synopsis [Finds the variables on which a DD depends.] + + Description [Finds the variables on which a DD depends. + Returns an index array of the variables if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport] + +******************************************************************************/ +int * +Cudd_SupportIndex( + DdManager * dd /* manager */, + DdNode * f /* DD whose support is sought */) +{ + int *support; + int i; + int size; + + /* Allocate and initialize support array for ddSupportStep. */ + size = ddMax(dd->size, dd->sizeZ); + support = ALLOC(int,size); + if (support == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < size; i++) { + support[i] = 0; + } + + /* Compute support and clean up markers. */ + ddSupportStep(Cudd_Regular(f),support); + ddClearFlag(Cudd_Regular(f)); + + return(support); + +} /* end of Cudd_SupportIndex */ + + +/**Function******************************************************************** + + Synopsis [Counts the variables on which a DD depends.] + + Description [Counts the variables on which a DD depends. + Returns the number of the variables if successful; CUDD_OUT_OF_MEM + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_Support] + +******************************************************************************/ +int +Cudd_SupportSize( + DdManager * dd /* manager */, + DdNode * f /* DD whose support size is sought */) +{ + int *support; + int i; + int size; + int count; + + /* Allocate and initialize support array for ddSupportStep. */ + size = ddMax(dd->size, dd->sizeZ); + support = ALLOC(int,size); + if (support == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(CUDD_OUT_OF_MEM); + } + for (i = 0; i < size; i++) { + support[i] = 0; + } + + /* Compute support and clean up markers. */ + ddSupportStep(Cudd_Regular(f),support); + ddClearFlag(Cudd_Regular(f)); + + /* Count support variables. */ + count = 0; + for (i = 0; i < size; i++) { + if (support[i] == 1) count++; + } + + FREE(support); + return(count); + +} /* end of Cudd_SupportSize */ + + +/**Function******************************************************************** + + Synopsis [Finds the variables on which a set of DDs depends.] + + Description [Finds the variables on which a set of DDs depends. + The set must contain either BDDs and ADDs, or ZDDs. + Returns a BDD consisting of the product of the variables if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_Support Cudd_ClassifySupport] + +******************************************************************************/ +DdNode * +Cudd_VectorSupport( + DdManager * dd /* manager */, + DdNode ** F /* array of DDs whose support is sought */, + int n /* size of the array */) +{ + int *support; + DdNode *res, *tmp, *var; + int i,j; + int size; + + /* Allocate and initialize support array for ddSupportStep. */ + size = ddMax(dd->size, dd->sizeZ); + support = ALLOC(int,size); + if (support == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < size; i++) { + support[i] = 0; + } + + /* Compute support and clean up markers. */ + for (i = 0; i < n; i++) { + ddSupportStep(Cudd_Regular(F[i]),support); + } + for (i = 0; i < n; i++) { + ddClearFlag(Cudd_Regular(F[i])); + } + + /* Transform support from array to cube. */ + res = DD_ONE(dd); + cuddRef(res); + for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */ + i = (j >= dd->size) ? j : dd->invperm[j]; + if (support[i] == 1) { + var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); + cuddRef(var); + tmp = Cudd_bddAnd(dd,res,var); + if (tmp == NULL) { + Cudd_RecursiveDeref(dd,res); + Cudd_RecursiveDeref(dd,var); + FREE(support); + return(NULL); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,res); + Cudd_RecursiveDeref(dd,var); + res = tmp; + } + } + + FREE(support); + cuddDeref(res); + return(res); + +} /* end of Cudd_VectorSupport */ + + +/**Function******************************************************************** + + Synopsis [Finds the variables on which a set of DDs depends.] + + Description [Finds the variables on which a set of DDs depends. + The set must contain either BDDs and ADDs, or ZDDs. + Returns an index array of the variables if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_SupportIndex Cudd_VectorSupport Cudd_ClassifySupport] + +******************************************************************************/ +int * +Cudd_VectorSupportIndex( + DdManager * dd /* manager */, + DdNode ** F /* array of DDs whose support is sought */, + int n /* size of the array */) +{ + int *support; + int i; + int size; + + /* Allocate and initialize support array for ddSupportStep. */ + size = ddMax(dd->size, dd->sizeZ); + support = ALLOC(int,size); + if (support == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < size; i++) { + support[i] = 0; + } + + /* Compute support and clean up markers. */ + for (i = 0; i < n; i++) { + ddSupportStep(Cudd_Regular(F[i]),support); + } + for (i = 0; i < n; i++) { + ddClearFlag(Cudd_Regular(F[i])); + } + + return(support); + +} /* end of Cudd_VectorSupportIndex */ + + +/**Function******************************************************************** + + Synopsis [Counts the variables on which a set of DDs depends.] + + Description [Counts the variables on which a set of DDs depends. + The set must contain either BDDs and ADDs, or ZDDs. + Returns the number of the variables if successful; CUDD_OUT_OF_MEM + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_VectorSupport Cudd_SupportSize] + +******************************************************************************/ +int +Cudd_VectorSupportSize( + DdManager * dd /* manager */, + DdNode ** F /* array of DDs whose support is sought */, + int n /* size of the array */) +{ + int *support; + int i; + int size; + int count; + + /* Allocate and initialize support array for ddSupportStep. */ + size = ddMax(dd->size, dd->sizeZ); + support = ALLOC(int,size); + if (support == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(CUDD_OUT_OF_MEM); + } + for (i = 0; i < size; i++) { + support[i] = 0; + } + + /* Compute support and clean up markers. */ + for (i = 0; i < n; i++) { + ddSupportStep(Cudd_Regular(F[i]),support); + } + for (i = 0; i < n; i++) { + ddClearFlag(Cudd_Regular(F[i])); + } + + /* Count vriables in support. */ + count = 0; + for (i = 0; i < size; i++) { + if (support[i] == 1) count++; + } + + FREE(support); + return(count); + +} /* end of Cudd_VectorSupportSize */ + + +/**Function******************************************************************** + + Synopsis [Classifies the variables in the support of two DDs.] + + Description [Classifies the variables in the support of two DDs + f and g, depending on whther they appear + in both DDs, only in f, or only in g. + Returns 1 if successful; 0 otherwise.] + + SideEffects [The cubes of the three classes of variables are + returned as side effects.] + + SeeAlso [Cudd_Support Cudd_VectorSupport] + +******************************************************************************/ +int +Cudd_ClassifySupport( + DdManager * dd /* manager */, + DdNode * f /* first DD */, + DdNode * g /* second DD */, + DdNode ** common /* cube of shared variables */, + DdNode ** onlyF /* cube of variables only in f */, + DdNode ** onlyG /* cube of variables only in g */) +{ + int *supportF, *supportG; + DdNode *tmp, *var; + int i,j; + int size; + + /* Allocate and initialize support arrays for ddSupportStep. */ + size = ddMax(dd->size, dd->sizeZ); + supportF = ALLOC(int,size); + if (supportF == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + supportG = ALLOC(int,size); + if (supportG == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(supportF); + return(0); + } + for (i = 0; i < size; i++) { + supportF[i] = 0; + supportG[i] = 0; + } + + /* Compute supports and clean up markers. */ + ddSupportStep(Cudd_Regular(f),supportF); + ddClearFlag(Cudd_Regular(f)); + ddSupportStep(Cudd_Regular(g),supportG); + ddClearFlag(Cudd_Regular(g)); + + /* Classify variables and create cubes. */ + *common = *onlyF = *onlyG = DD_ONE(dd); + cuddRef(*common); cuddRef(*onlyF); cuddRef(*onlyG); + for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */ + i = (j >= dd->size) ? j : dd->invperm[j]; + if (supportF[i] == 0 && supportG[i] == 0) continue; + var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); + cuddRef(var); + if (supportG[i] == 0) { + tmp = Cudd_bddAnd(dd,*onlyF,var); + if (tmp == NULL) { + Cudd_RecursiveDeref(dd,*common); + Cudd_RecursiveDeref(dd,*onlyF); + Cudd_RecursiveDeref(dd,*onlyG); + Cudd_RecursiveDeref(dd,var); + FREE(supportF); FREE(supportG); + return(0); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,*onlyF); + *onlyF = tmp; + } else if (supportF[i] == 0) { + tmp = Cudd_bddAnd(dd,*onlyG,var); + if (tmp == NULL) { + Cudd_RecursiveDeref(dd,*common); + Cudd_RecursiveDeref(dd,*onlyF); + Cudd_RecursiveDeref(dd,*onlyG); + Cudd_RecursiveDeref(dd,var); + FREE(supportF); FREE(supportG); + return(0); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,*onlyG); + *onlyG = tmp; + } else { + tmp = Cudd_bddAnd(dd,*common,var); + if (tmp == NULL) { + Cudd_RecursiveDeref(dd,*common); + Cudd_RecursiveDeref(dd,*onlyF); + Cudd_RecursiveDeref(dd,*onlyG); + Cudd_RecursiveDeref(dd,var); + FREE(supportF); FREE(supportG); + return(0); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,*common); + *common = tmp; + } + Cudd_RecursiveDeref(dd,var); + } + + FREE(supportF); FREE(supportG); + cuddDeref(*common); cuddDeref(*onlyF); cuddDeref(*onlyG); + return(1); + +} /* end of Cudd_ClassifySupport */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of leaves in a DD.] + + Description [Counts the number of leaves in a DD. Returns the number + of leaves in the DD rooted at node if successful; CUDD_OUT_OF_MEM + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_PrintDebug] + +******************************************************************************/ +int +Cudd_CountLeaves( + DdNode * node) +{ + int i; + + i = ddLeavesInt(Cudd_Regular(node)); + ddClearFlag(Cudd_Regular(node)); + return(i); + +} /* end of Cudd_CountLeaves */ + + +/**Function******************************************************************** + + Synopsis [Picks one on-set cube randomly from the given DD.] + + Description [Picks one on-set cube randomly from the given DD. The + cube is written into an array of characters. The array must have at + least as many entries as there are variables. Returns 1 if + successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddPickOneMinterm] + +******************************************************************************/ +int +Cudd_bddPickOneCube( + DdManager * ddm, + DdNode * node, + char * string) +{ + DdNode *N, *T, *E; + DdNode *one, *bzero; + char dir; + int i; + + if (string == NULL || node == NULL) return(0); + + /* The constant 0 function has no on-set cubes. */ + one = DD_ONE(ddm); + bzero = Cudd_Not(one); + if (node == bzero) return(0); + + for (i = 0; i < ddm->size; i++) string[i] = 2; + + for (;;) { + + if (node == one) break; + + N = Cudd_Regular(node); + + T = cuddT(N); E = cuddE(N); + if (Cudd_IsComplement(node)) { + T = Cudd_Not(T); E = Cudd_Not(E); + } + if (T == bzero) { + string[N->index] = 0; + node = E; + } else if (E == bzero) { + string[N->index] = 1; + node = T; + } else { + dir = (char) ((Cudd_Random() & 0x2000) >> 13); + string[N->index] = dir; + node = dir ? T : E; + } + } + return(1); + +} /* end of Cudd_bddPickOneCube */ + + +/**Function******************************************************************** + + Synopsis [Picks one on-set minterm randomly from the given DD.] + + Description [Picks one on-set minterm randomly from the given + DD. The minterm is in terms of vars. The array + vars should contain at least all variables in the + support of f; if this condition is not met the minterm + built by this procedure may not be contained in + f. Builds a BDD for the minterm and returns a pointer + to it if successful; NULL otherwise. There are three reasons why the + procedure may fail: +
          +
        • It may run out of memory; +
        • the function f may be the constant 0; +
        • the minterm may not be contained in f. +
        ] + + SideEffects [None] + + SeeAlso [Cudd_bddPickOneCube] + +******************************************************************************/ +DdNode * +Cudd_bddPickOneMinterm( + DdManager * dd /* manager */, + DdNode * f /* function from which to pick one minterm */, + DdNode ** vars /* array of variables */, + int n /* size of vars */) +{ + char *string; + int i, size; + int *indices; + int result; + DdNode *old, *neW; + + size = dd->size; + string = ALLOC(char, size); + if (string == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + indices = ALLOC(int,n); + if (indices == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(string); + return(NULL); + } + + for (i = 0; i < n; i++) { + indices[i] = vars[i]->index; + } + + result = Cudd_bddPickOneCube(dd,f,string); + if (result == 0) { + FREE(string); + FREE(indices); + return(NULL); + } + + /* Randomize choice for don't cares. */ + for (i = 0; i < n; i++) { + if (string[indices[i]] == 2) + string[indices[i]] = (char) ((Cudd_Random() & 0x20) >> 5); + } + + /* Build result BDD. */ + old = Cudd_ReadOne(dd); + cuddRef(old); + + for (i = n-1; i >= 0; i--) { + neW = Cudd_bddAnd(dd,old,Cudd_NotCond(vars[i],string[indices[i]]==0)); + if (neW == NULL) { + FREE(string); + FREE(indices); + Cudd_RecursiveDeref(dd,old); + return(NULL); + } + cuddRef(neW); + Cudd_RecursiveDeref(dd,old); + old = neW; + } + +#ifdef DD_DEBUG + /* Test. */ + if (Cudd_bddLeq(dd,old,f)) { + cuddDeref(old); + } else { + Cudd_RecursiveDeref(dd,old); + old = NULL; + } +#else + cuddDeref(old); +#endif + + FREE(string); + FREE(indices); + return(old); + +} /* end of Cudd_bddPickOneMinterm */ + + +/**Function******************************************************************** + + Synopsis [Picks k on-set minterms evenly distributed from given DD.] + + Description [Picks k on-set minterms evenly distributed from given DD. + The minterms are in terms of vars. The array + vars should contain at least all variables in the + support of f; if this condition is not met the minterms + built by this procedure may not be contained in + f. Builds an array of BDDs for the minterms and returns a + pointer to it if successful; NULL otherwise. There are three reasons + why the procedure may fail: +
          +
        • It may run out of memory; +
        • the function f may be the constant 0; +
        • the minterms may not be contained in f. +
        ] + + SideEffects [None] + + SeeAlso [Cudd_bddPickOneMinterm Cudd_bddPickOneCube] + +******************************************************************************/ +DdNode ** +Cudd_bddPickArbitraryMinterms( + DdManager * dd /* manager */, + DdNode * f /* function from which to pick k minterms */, + DdNode ** vars /* array of variables */, + int n /* size of vars */, + int k /* number of minterms to find */) +{ + char **string; + int i, j, l, size; + int *indices; + int result; + DdNode **old, *neW; + double minterms; + char *saveString; + int saveFlag, savePoint, isSame; + + minterms = Cudd_CountMinterm(dd,f,n); + if ((double)k > minterms) { + return(NULL); + } + + size = dd->size; + string = ALLOC(char *, k); + if (string == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < k; i++) { + string[i] = ALLOC(char, size + 1); + if (string[i] == NULL) { + for (j = 0; j < i; j++) + FREE(string[i]); + FREE(string); + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (j = 0; j < size; j++) string[i][j] = '2'; + string[i][size] = '\0'; + } + indices = ALLOC(int,n); + if (indices == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + for (i = 0; i < k; i++) + FREE(string[i]); + FREE(string); + return(NULL); + } + + for (i = 0; i < n; i++) { + indices[i] = vars[i]->index; + } + + result = ddPickArbitraryMinterms(dd,f,n,k,string); + if (result == 0) { + for (i = 0; i < k; i++) + FREE(string[i]); + FREE(string); + FREE(indices); + return(NULL); + } + + old = ALLOC(DdNode *, k); + if (old == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + for (i = 0; i < k; i++) + FREE(string[i]); + FREE(string); + FREE(indices); + return(NULL); + } + saveString = ALLOC(char, size + 1); + if (saveString == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + for (i = 0; i < k; i++) + FREE(string[i]); + FREE(string); + FREE(indices); + FREE(old); + return(NULL); + } + saveFlag = 0; + + /* Build result BDD array. */ + for (i = 0; i < k; i++) { + isSame = 0; + if (!saveFlag) { + for (j = i + 1; j < k; j++) { + if (strcmp(string[i], string[j]) == 0) { + savePoint = i; + strcpy(saveString, string[i]); + saveFlag = 1; + break; + } + } + } else { + if (strcmp(string[i], saveString) == 0) { + isSame = 1; + } else { + saveFlag = 0; + for (j = i + 1; j < k; j++) { + if (strcmp(string[i], string[j]) == 0) { + savePoint = i; + strcpy(saveString, string[i]); + saveFlag = 1; + break; + } + } + } + } + /* Randomize choice for don't cares. */ + for (j = 0; j < n; j++) { + if (string[i][indices[j]] == '2') + string[i][indices[j]] = (Cudd_Random() & 0x20) ? '1' : '0'; + } + + while (isSame) { + isSame = 0; + for (j = savePoint; j < i; j++) { + if (strcmp(string[i], string[j]) == 0) { + isSame = 1; + break; + } + } + if (isSame) { + strcpy(string[i], saveString); + /* Randomize choice for don't cares. */ + for (j = 0; j < n; j++) { + if (string[i][indices[j]] == '2') + string[i][indices[j]] = (Cudd_Random() & 0x20) ? + '1' : '0'; + } + } + } + + old[i] = Cudd_ReadOne(dd); + cuddRef(old[i]); + + for (j = 0; j < n; j++) { + if (string[i][indices[j]] == '0') { + neW = Cudd_bddAnd(dd,old[i],Cudd_Not(vars[j])); + } else { + neW = Cudd_bddAnd(dd,old[i],vars[j]); + } + if (neW == NULL) { + FREE(saveString); + for (l = 0; l < k; l++) + FREE(string[l]); + FREE(string); + FREE(indices); + for (l = 0; l <= i; l++) + Cudd_RecursiveDeref(dd,old[l]); + FREE(old); + return(NULL); + } + cuddRef(neW); + Cudd_RecursiveDeref(dd,old[i]); + old[i] = neW; + } + + /* Test. */ + if (!Cudd_bddLeq(dd,old[i],f)) { + FREE(saveString); + for (l = 0; l < k; l++) + FREE(string[l]); + FREE(string); + FREE(indices); + for (l = 0; l <= i; l++) + Cudd_RecursiveDeref(dd,old[l]); + FREE(old); + return(NULL); + } + } + + FREE(saveString); + for (i = 0; i < k; i++) { + cuddDeref(old[i]); + FREE(string[i]); + } + FREE(string); + FREE(indices); + return(old); + +} /* end of Cudd_bddPickArbitraryMinterms */ + + +/**Function******************************************************************** + + Synopsis [Extracts a subset from a BDD.] + + Description [Extracts a subset from a BDD in the following procedure. + 1. Compute the weight for each mask variable by counting the number of + minterms for both positive and negative cofactors of the BDD with + respect to each mask variable. (weight = #positive - #negative) + 2. Find a representative cube of the BDD by using the weight. From the + top variable of the BDD, for each variable, if the weight is greater + than 0.0, choose THEN branch, othereise ELSE branch, until meeting + the constant 1. + 3. Quantify out the variables not in maskVars from the representative + cube and if a variable in maskVars is don't care, replace the + variable with a constant(1 or 0) depending on the weight. + 4. Make a subset of the BDD by multiplying with the modified cube.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_SubsetWithMaskVars( + DdManager * dd /* manager */, + DdNode * f /* function from which to pick a cube */, + DdNode ** vars /* array of variables */, + int nvars /* size of vars */, + DdNode ** maskVars /* array of variables */, + int mvars /* size of maskVars */) +{ + double *weight; + char *string; + int i, size; + int *indices, *mask; + int result; + DdNode *zero, *cube, *newCube, *subset; + DdNode *cof; + + DdNode *support; + support = Cudd_Support(dd,f); + cuddRef(support); + Cudd_RecursiveDeref(dd,support); + + zero = Cudd_Not(dd->one); + size = dd->size; + + weight = ALLOC(double,size); + if (weight == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + for (i = 0; i < size; i++) { + weight[i] = 0.0; + } + for (i = 0; i < mvars; i++) { + cof = Cudd_Cofactor(dd, f, maskVars[i]); + cuddRef(cof); + weight[i] = Cudd_CountMinterm(dd, cof, nvars); + Cudd_RecursiveDeref(dd,cof); + + cof = Cudd_Cofactor(dd, f, Cudd_Not(maskVars[i])); + cuddRef(cof); + weight[i] -= Cudd_CountMinterm(dd, cof, nvars); + Cudd_RecursiveDeref(dd,cof); + } + + string = ALLOC(char, size + 1); + if (string == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + mask = ALLOC(int, size); + if (mask == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(string); + return(NULL); + } + for (i = 0; i < size; i++) { + string[i] = '2'; + mask[i] = 0; + } + string[size] = '\0'; + indices = ALLOC(int,nvars); + if (indices == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(string); + FREE(mask); + return(NULL); + } + for (i = 0; i < nvars; i++) { + indices[i] = vars[i]->index; + } + + result = ddPickRepresentativeCube(dd,f,nvars,weight,string); + if (result == 0) { + FREE(string); + FREE(mask); + FREE(indices); + return(NULL); + } + + cube = Cudd_ReadOne(dd); + cuddRef(cube); + zero = Cudd_Not(Cudd_ReadOne(dd)); + for (i = 0; i < nvars; i++) { + if (string[indices[i]] == '0') { + newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero); + } else if (string[indices[i]] == '1') { + newCube = Cudd_bddIte(dd,cube,vars[i],zero); + } else + continue; + if (newCube == NULL) { + FREE(string); + FREE(mask); + FREE(indices); + Cudd_RecursiveDeref(dd,cube); + return(NULL); + } + cuddRef(newCube); + Cudd_RecursiveDeref(dd,cube); + cube = newCube; + } + Cudd_RecursiveDeref(dd,cube); + + for (i = 0; i < mvars; i++) { + mask[maskVars[i]->index] = 1; + } + for (i = 0; i < nvars; i++) { + if (mask[indices[i]]) { + if (string[indices[i]] == '2') { + if (weight[indices[i]] >= 0.0) + string[indices[i]] = '1'; + else + string[indices[i]] = '0'; + } + } else { + string[indices[i]] = '2'; + } + } + + cube = Cudd_ReadOne(dd); + cuddRef(cube); + zero = Cudd_Not(Cudd_ReadOne(dd)); + + /* Build result BDD. */ + for (i = 0; i < nvars; i++) { + if (string[indices[i]] == '0') { + newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero); + } else if (string[indices[i]] == '1') { + newCube = Cudd_bddIte(dd,cube,vars[i],zero); + } else + continue; + if (newCube == NULL) { + FREE(string); + FREE(mask); + FREE(indices); + Cudd_RecursiveDeref(dd,cube); + return(NULL); + } + cuddRef(newCube); + Cudd_RecursiveDeref(dd,cube); + cube = newCube; + } + + subset = Cudd_bddAnd(dd,f,cube); + cuddRef(subset); + Cudd_RecursiveDeref(dd,cube); + + /* Test. */ + if (Cudd_bddLeq(dd,subset,f)) { + cuddDeref(subset); + } else { + Cudd_RecursiveDeref(dd,subset); + subset = NULL; + } + + FREE(string); + FREE(mask); + FREE(indices); + FREE(weight); + return(subset); + +} /* end of Cudd_SubsetWithMaskVars */ + + +/**Function******************************************************************** + + Synopsis [Finds the first cube of a decision diagram.] + + Description [Defines an iterator on the onset of a decision diagram + and finds its first cube. Returns a generator that contains the + information necessary to continue the enumeration if successful; NULL + otherwise.

        + A cube is represented as an array of literals, which are integers in + {0, 1, 2}; 0 represents a complemented literal, 1 represents an + uncomplemented literal, and 2 stands for don't care. The enumeration + produces a disjoint cover of the function associated with the diagram. + The size of the array equals the number of variables in the manager at + the time Cudd_FirstCube is called.

        + For each cube, a value is also returned. This value is always 1 for a + BDD, while it may be different from 1 for an ADD. + For BDDs, the offset is the set of cubes whose value is the logical zero. + For ADDs, the offset is the set of cubes whose value is the + background value. The cubes of the offset are not enumerated.] + + SideEffects [The first cube and its value are returned as side effects.] + + SeeAlso [Cudd_ForeachCube Cudd_NextCube Cudd_GenFree Cudd_IsGenEmpty + Cudd_FirstNode] + +******************************************************************************/ +DdGen * +Cudd_FirstCube( + DdManager * dd, + DdNode * f, + int ** cube, + CUDD_VALUE_TYPE * value) +{ + DdGen *gen; + DdNode *top, *treg, *next, *nreg, *prev, *preg; + int i; + int nvars; + + /* Sanity Check. */ + if (dd == NULL || f == NULL) return(NULL); + + /* Allocate generator an initialize it. */ + gen = ALLOC(DdGen,1); + if (gen == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + gen->manager = dd; + gen->type = CUDD_GEN_CUBES; + gen->status = CUDD_GEN_EMPTY; + gen->gen.cubes.cube = NULL; + gen->gen.cubes.value = DD_ZERO_VAL; + gen->stack.sp = 0; + gen->stack.stack = NULL; + gen->node = NULL; + + nvars = dd->size; + gen->gen.cubes.cube = ALLOC(int,nvars); + if (gen->gen.cubes.cube == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(gen); + return(NULL); + } + for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2; + + /* The maximum stack depth is one plus the number of variables. + ** because a path may have nodes at all levels, including the + ** constant level. + */ + gen->stack.stack = ALLOC(DdNode *, nvars+1); + if (gen->stack.stack == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + FREE(gen->gen.cubes.cube); + FREE(gen); + return(NULL); + } + for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL; + + /* Find the first cube of the onset. */ + gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++; + + while (1) { + top = gen->stack.stack[gen->stack.sp-1]; + treg = Cudd_Regular(top); + if (!cuddIsConstant(treg)) { + /* Take the else branch first. */ + gen->gen.cubes.cube[treg->index] = 0; + next = cuddE(treg); + if (top != treg) next = Cudd_Not(next); + gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; + } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) { + /* Backtrack */ + while (1) { + if (gen->stack.sp == 1) { + /* The current node has no predecessor. */ + gen->status = CUDD_GEN_EMPTY; + gen->stack.sp--; + goto done; + } + prev = gen->stack.stack[gen->stack.sp-2]; + preg = Cudd_Regular(prev); + nreg = cuddT(preg); + if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} + if (next != top) { /* follow the then branch next */ + gen->gen.cubes.cube[preg->index] = 1; + gen->stack.stack[gen->stack.sp-1] = next; + break; + } + /* Pop the stack and try again. */ + gen->gen.cubes.cube[preg->index] = 2; + gen->stack.sp--; + top = gen->stack.stack[gen->stack.sp-1]; + treg = Cudd_Regular(top); + } + } else { + gen->status = CUDD_GEN_NONEMPTY; + gen->gen.cubes.value = cuddV(top); + goto done; + } + } + +done: + *cube = gen->gen.cubes.cube; + *value = gen->gen.cubes.value; + return(gen); + +} /* end of Cudd_FirstCube */ + + +/**Function******************************************************************** + + Synopsis [Generates the next cube of a decision diagram onset.] + + Description [Generates the next cube of a decision diagram onset, + using generator gen. Returns 0 if the enumeration is completed; 1 + otherwise.] + + SideEffects [The cube and its value are returned as side effects. The + generator is modified.] + + SeeAlso [Cudd_ForeachCube Cudd_FirstCube Cudd_GenFree Cudd_IsGenEmpty + Cudd_NextNode] + +******************************************************************************/ +int +Cudd_NextCube( + DdGen * gen, + int ** cube, + CUDD_VALUE_TYPE * value) +{ + DdNode *top, *treg, *next, *nreg, *prev, *preg; + DdManager *dd = gen->manager; + + /* Backtrack from previously reached terminal node. */ + while (1) { + if (gen->stack.sp == 1) { + /* The current node has no predecessor. */ + gen->status = CUDD_GEN_EMPTY; + gen->stack.sp--; + goto done; + } + top = gen->stack.stack[gen->stack.sp-1]; + treg = Cudd_Regular(top); + prev = gen->stack.stack[gen->stack.sp-2]; + preg = Cudd_Regular(prev); + nreg = cuddT(preg); + if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} + if (next != top) { /* follow the then branch next */ + gen->gen.cubes.cube[preg->index] = 1; + gen->stack.stack[gen->stack.sp-1] = next; + break; + } + /* Pop the stack and try again. */ + gen->gen.cubes.cube[preg->index] = 2; + gen->stack.sp--; + } + + while (1) { + top = gen->stack.stack[gen->stack.sp-1]; + treg = Cudd_Regular(top); + if (!cuddIsConstant(treg)) { + /* Take the else branch first. */ + gen->gen.cubes.cube[treg->index] = 0; + next = cuddE(treg); + if (top != treg) next = Cudd_Not(next); + gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; + } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) { + /* Backtrack */ + while (1) { + if (gen->stack.sp == 1) { + /* The current node has no predecessor. */ + gen->status = CUDD_GEN_EMPTY; + gen->stack.sp--; + goto done; + } + prev = gen->stack.stack[gen->stack.sp-2]; + preg = Cudd_Regular(prev); + nreg = cuddT(preg); + if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} + if (next != top) { /* follow the then branch next */ + gen->gen.cubes.cube[preg->index] = 1; + gen->stack.stack[gen->stack.sp-1] = next; + break; + } + /* Pop the stack and try again. */ + gen->gen.cubes.cube[preg->index] = 2; + gen->stack.sp--; + top = gen->stack.stack[gen->stack.sp-1]; + treg = Cudd_Regular(top); + } + } else { + gen->status = CUDD_GEN_NONEMPTY; + gen->gen.cubes.value = cuddV(top); + goto done; + } + } + +done: + if (gen->status == CUDD_GEN_EMPTY) return(0); + *cube = gen->gen.cubes.cube; + *value = gen->gen.cubes.value; + return(1); + +} /* end of Cudd_NextCube */ + + +/**Function******************************************************************** + + Synopsis [Computes the cube of an array of BDD variables.] + + Description [Computes the cube of an array of BDD variables. If + non-null, the phase argument indicates which literal of each + variable should appear in the cube. If phase\[i\] is nonzero, then the + positive literal is used. If phase is NULL, the cube is positive unate. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_addComputeCube Cudd_IndicesToCube Cudd_CubeArrayToBdd] + +******************************************************************************/ +DdNode * +Cudd_bddComputeCube( + DdManager * dd, + DdNode ** vars, + int * phase, + int n) +{ + DdNode *cube; + DdNode *fn; + int i; + + cube = DD_ONE(dd); + cuddRef(cube); + + for (i = n - 1; i >= 0; i--) { + if (phase == NULL || phase[i] != 0) { + fn = Cudd_bddAnd(dd,vars[i],cube); + } else { + fn = Cudd_bddAnd(dd,Cudd_Not(vars[i]),cube); + } + if (fn == NULL) { + Cudd_RecursiveDeref(dd,cube); + return(NULL); + } + cuddRef(fn); + Cudd_RecursiveDeref(dd,cube); + cube = fn; + } + cuddDeref(cube); + + return(cube); + +} /* end of Cudd_bddComputeCube */ + + +/**Function******************************************************************** + + Synopsis [Computes the cube of an array of ADD variables.] + + Description [Computes the cube of an array of ADD variables. If + non-null, the phase argument indicates which literal of each + variable should appear in the cube. If phase\[i\] is nonzero, then the + positive literal is used. If phase is NULL, the cube is positive unate. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [none] + + SeeAlso [Cudd_bddComputeCube] + +******************************************************************************/ +DdNode * +Cudd_addComputeCube( + DdManager * dd, + DdNode ** vars, + int * phase, + int n) +{ + DdNode *cube, *zero; + DdNode *fn; + int i; + + cube = DD_ONE(dd); + cuddRef(cube); + zero = DD_ZERO(dd); + + for (i = n - 1; i >= 0; i--) { + if (phase == NULL || phase[i] != 0) { + fn = Cudd_addIte(dd,vars[i],cube,zero); + } else { + fn = Cudd_addIte(dd,vars[i],zero,cube); + } + if (fn == NULL) { + Cudd_RecursiveDeref(dd,cube); + return(NULL); + } + cuddRef(fn); + Cudd_RecursiveDeref(dd,cube); + cube = fn; + } + cuddDeref(cube); + + return(cube); + +} /* end of Cudd_addComputeCube */ + + +/**Function******************************************************************** + + Synopsis [Builds the BDD of a cube from a positional array.] + + Description [Builds a cube from a positional array. The array must + have one integer entry for each BDD variable. If the i-th entry is + 1, the variable of index i appears in true form in the cube; If the + i-th entry is 0, the variable of index i appears complemented in the + cube; otherwise the variable does not appear in the cube. Returns a + pointer to the BDD for the cube if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddComputeCube Cudd_IndicesToCube Cudd_BddToCubeArray] + +******************************************************************************/ +DdNode * +Cudd_CubeArrayToBdd( + DdManager *dd, + int *array) +{ + DdNode *cube, *var, *tmp; + int i; + int size = Cudd_ReadSize(dd); + + cube = DD_ONE(dd); + cuddRef(cube); + for (i = size - 1; i >= 0; i--) { + if ((array[i] & ~1) == 0) { + var = Cudd_bddIthVar(dd,i); + tmp = Cudd_bddAnd(dd,cube,Cudd_NotCond(var,array[i]==0)); + if (tmp == NULL) { + Cudd_RecursiveDeref(dd,cube); + return(NULL); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,cube); + cube = tmp; + } + } + cuddDeref(cube); + return(cube); + +} /* end of Cudd_CubeArrayToBdd */ + + +/**Function******************************************************************** + + Synopsis [Builds a positional array from the BDD of a cube.] + + Description [Builds a positional array from the BDD of a cube. + Array must have one entry for each BDD variable. The positional + array has 1 in i-th position if the variable of index i appears in + true form in the cube; it has 0 in i-th position if the variable of + index i appears in complemented form in the cube; finally, it has 2 + in i-th position if the variable of index i does not appear in the + cube. Returns 1 if successful (the BDD is indeed a cube); 0 + otherwise.] + + SideEffects [The result is in the array passed by reference.] + + SeeAlso [Cudd_CubeArrayToBdd] + +******************************************************************************/ +int +Cudd_BddToCubeArray( + DdManager *dd, + DdNode *cube, + int *array) +{ + DdNode *scan, *t, *e; + int i; + int size = Cudd_ReadSize(dd); + DdNode *zero = Cudd_Not(DD_ONE(dd)); + + for (i = size-1; i >= 0; i--) { + array[i] = 2; + } + scan = cube; + while (!Cudd_IsConstant(scan)) { + int index = Cudd_Regular(scan)->index; + cuddGetBranches(scan,&t,&e); + if (t == zero) { + array[index] = 0; + scan = e; + } else if (e == zero) { + array[index] = 1; + scan = t; + } else { + return(0); /* cube is not a cube */ + } + } + if (scan == zero) { + return(0); + } else { + return(1); + } + +} /* end of Cudd_BddToCubeArray */ + + +/**Function******************************************************************** + + Synopsis [Finds the first node of a decision diagram.] + + Description [Defines an iterator on the nodes of a decision diagram + and finds its first node. Returns a generator that contains the + information necessary to continue the enumeration if successful; NULL + otherwise.] + + SideEffects [The first node is returned as a side effect.] + + SeeAlso [Cudd_ForeachNode Cudd_NextNode Cudd_GenFree Cudd_IsGenEmpty + Cudd_FirstCube] + +******************************************************************************/ +DdGen * +Cudd_FirstNode( + DdManager * dd, + DdNode * f, + DdNode ** node) +{ + DdGen *gen; + int retval; + + /* Sanity Check. */ + if (dd == NULL || f == NULL) return(NULL); + + /* Allocate generator an initialize it. */ + gen = ALLOC(DdGen,1); + if (gen == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + gen->manager = dd; + gen->type = CUDD_GEN_NODES; + gen->status = CUDD_GEN_EMPTY; + gen->gen.nodes.visited = NULL; + gen->gen.nodes.stGen = NULL; + gen->stack.sp = 0; + gen->stack.stack = NULL; + gen->node = NULL; + + gen->gen.nodes.visited = st_init_table(st_ptrcmp,st_ptrhash); + if (gen->gen.nodes.visited == NULL) { + FREE(gen); + return(NULL); + } + + /* Collect all the nodes in a st table for later perusal. */ + retval = cuddCollectNodes(Cudd_Regular(f),gen->gen.nodes.visited); + if (retval == 0) { + st_free_table(gen->gen.nodes.visited); + FREE(gen); + return(NULL); + } + + /* Initialize the st table generator. */ + gen->gen.nodes.stGen = st_init_gen(gen->gen.nodes.visited); + if (gen->gen.nodes.stGen == NULL) { + st_free_table(gen->gen.nodes.visited); + FREE(gen); + return(NULL); + } + + /* Find the first node. */ + retval = st_gen(gen->gen.nodes.stGen, (char **) &(gen->node), NULL); + if (retval != 0) { + gen->status = CUDD_GEN_NONEMPTY; + *node = gen->node; + } + + return(gen); + +} /* end of Cudd_FirstNode */ + + +/**Function******************************************************************** + + Synopsis [Finds the next node of a decision diagram.] + + Description [Finds the node of a decision diagram, using generator + gen. Returns 0 if the enumeration is completed; 1 otherwise.] + + SideEffects [The next node is returned as a side effect.] + + SeeAlso [Cudd_ForeachNode Cudd_FirstNode Cudd_GenFree Cudd_IsGenEmpty + Cudd_NextCube] + +******************************************************************************/ +int +Cudd_NextNode( + DdGen * gen, + DdNode ** node) +{ + int retval; + + /* Find the next node. */ + retval = st_gen(gen->gen.nodes.stGen, (char **) &(gen->node), NULL); + if (retval == 0) { + gen->status = CUDD_GEN_EMPTY; + } else { + *node = gen->node; + } + + return(retval); + +} /* end of Cudd_NextNode */ + + +/**Function******************************************************************** + + Synopsis [Frees a CUDD generator.] + + Description [Frees a CUDD generator. Always returns 0, so that it can + be used in mis-like foreach constructs.] + + SideEffects [None] + + SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube + Cudd_FirstNode Cudd_NextNode Cudd_IsGenEmpty] + +******************************************************************************/ +int +Cudd_GenFree( + DdGen * gen) +{ + + if (gen == NULL) return(0); + switch (gen->type) { + case CUDD_GEN_CUBES: + case CUDD_GEN_ZDD_PATHS: + FREE(gen->gen.cubes.cube); + FREE(gen->stack.stack); + break; + case CUDD_GEN_NODES: + st_free_gen(gen->gen.nodes.stGen); + st_free_table(gen->gen.nodes.visited); + break; + default: + return(0); + } + FREE(gen); + return(0); + +} /* end of Cudd_GenFree */ + + +/**Function******************************************************************** + + Synopsis [Queries the status of a generator.] + + Description [Queries the status of a generator. Returns 1 if the + generator is empty or NULL; 0 otherswise.] + + SideEffects [None] + + SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube + Cudd_FirstNode Cudd_NextNode Cudd_GenFree] + +******************************************************************************/ +int +Cudd_IsGenEmpty( + DdGen * gen) +{ + if (gen == NULL) return(1); + return(gen->status == CUDD_GEN_EMPTY); + +} /* end of Cudd_IsGenEmpty */ + + +/**Function******************************************************************** + + Synopsis [Builds a cube of BDD variables from an array of indices.] + + Description [Builds a cube of BDD variables from an array of indices. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_bddComputeCube Cudd_CubeArrayToBdd] + +******************************************************************************/ +DdNode * +Cudd_IndicesToCube( + DdManager * dd, + int * array, + int n) +{ + DdNode *cube, *tmp; + int i; + + cube = DD_ONE(dd); + cuddRef(cube); + for (i = n - 1; i >= 0; i--) { + tmp = Cudd_bddAnd(dd,Cudd_bddIthVar(dd,array[i]),cube); + if (tmp == NULL) { + Cudd_RecursiveDeref(dd,cube); + return(NULL); + } + cuddRef(tmp); + Cudd_RecursiveDeref(dd,cube); + cube = tmp; + } + + cuddDeref(cube); + return(cube); + +} /* end of Cudd_IndicesToCube */ + + +/**Function******************************************************************** + + Synopsis [Prints the package version number.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +Cudd_PrintVersion( + FILE * fp) +{ + (void) fprintf(fp, "%s\n", CUDD_VERSION); + +} /* end of Cudd_PrintVersion */ + + +/**Function******************************************************************** + + Synopsis [Computes the average distance between adjacent nodes.] + + Description [Computes the average distance between adjacent nodes in + the manager. Adjacent nodes are node pairs such that the second node + is the then child, else child, or next node in the collision list.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +double +Cudd_AverageDistance( + DdManager * dd) +{ + double tetotal, nexttotal; + double tesubtotal, nextsubtotal; + double temeasured, nextmeasured; + int i, j; + int slots, nvars; + long diff; + DdNode *scan; + DdNodePtr *nodelist; + DdNode *sentinel = &(dd->sentinel); + + nvars = dd->size; + if (nvars == 0) return(0.0); + + /* Initialize totals. */ + tetotal = 0.0; + nexttotal = 0.0; + temeasured = 0.0; + nextmeasured = 0.0; + + /* Scan the variable subtables. */ + for (i = 0; i < nvars; i++) { + nodelist = dd->subtables[i].nodelist; + tesubtotal = 0.0; + nextsubtotal = 0.0; + slots = dd->subtables[i].slots; + for (j = 0; j < slots; j++) { + scan = nodelist[j]; + while (scan != sentinel) { + diff = (long) scan - (long) cuddT(scan); + tesubtotal += (double) ddAbs(diff); + diff = (long) scan - (long) Cudd_Regular(cuddE(scan)); + tesubtotal += (double) ddAbs(diff); + temeasured += 2.0; + if (scan->next != NULL) { + diff = (long) scan - (long) scan->next; + nextsubtotal += (double) ddAbs(diff); + nextmeasured += 1.0; + } + scan = scan->next; + } + } + tetotal += tesubtotal; + nexttotal += nextsubtotal; + } + + /* Scan the constant table. */ + nodelist = dd->constants.nodelist; + nextsubtotal = 0.0; + slots = dd->constants.slots; + for (j = 0; j < slots; j++) { + scan = nodelist[j]; + while (scan != NULL) { + if (scan->next != NULL) { + diff = (long) scan - (long) scan->next; + nextsubtotal += (double) ddAbs(diff); + nextmeasured += 1.0; + } + scan = scan->next; + } + } + nexttotal += nextsubtotal; + + return((tetotal + nexttotal) / (temeasured + nextmeasured)); + +} /* end of Cudd_AverageDistance */ + + +/**Function******************************************************************** + + Synopsis [Portable random number generator.] + + Description [Portable number generator based on ran2 from "Numerical + Recipes in C." It is a long period (> 2 * 10^18) random number generator + of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly + distributed between 0 and 2147483561 (inclusive of the endpoint values). + The random generator can be explicitly initialized by calling + Cudd_Srandom. If no explicit initialization is performed, then the + seed 1 is assumed.] + + SideEffects [None] + + SeeAlso [Cudd_Srandom] + +******************************************************************************/ +long +Cudd_Random( + ) +{ + int i; /* index in the shuffle table */ + long int w; /* work variable */ + + /* cuddRand == 0 if the geneartor has not been initialized yet. */ + if (cuddRand == 0) Cudd_Srandom(1); + + /* Compute cuddRand = (cuddRand * LEQA1) % MODULUS1 avoiding + ** overflows by Schrage's method. + */ + w = cuddRand / LEQQ1; + cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1; + cuddRand += (cuddRand < 0) * MODULUS1; + + /* Compute cuddRand2 = (cuddRand2 * LEQA2) % MODULUS2 avoiding + ** overflows by Schrage's method. + */ + w = cuddRand2 / LEQQ2; + cuddRand2 = LEQA2 * (cuddRand2 - w * LEQQ2) - w * LEQR2; + cuddRand2 += (cuddRand2 < 0) * MODULUS2; + + /* cuddRand is shuffled with the Bays-Durham algorithm. + ** shuffleSelect and cuddRand2 are combined to generate the output. + */ + + /* Pick one element from the shuffle table; "i" will be in the range + ** from 0 to STAB_SIZE-1. + */ + i = (int) (shuffleSelect / STAB_DIV); + /* Mix the element of the shuffle table with the current iterate of + ** the second sub-generator, and replace the chosen element of the + ** shuffle table with the current iterate of the first sub-generator. + */ + shuffleSelect = shuffleTable[i] - cuddRand2; + shuffleTable[i] = cuddRand; + shuffleSelect += (shuffleSelect < 1) * (MODULUS1 - 1); + /* Since shuffleSelect != 0, and we want to be able to return 0, + ** here we subtract 1 before returning. + */ + return(shuffleSelect - 1); + +} /* end of Cudd_Random */ + + +/**Function******************************************************************** + + Synopsis [Initializer for the portable random number generator.] + + Description [Initializer for the portable number generator based on + ran2 in "Numerical Recipes in C." The input is the seed for the + generator. If it is negative, its absolute value is taken as seed. + If it is 0, then 1 is taken as seed. The initialized sets up the two + recurrences used to generate a long-period stream, and sets up the + shuffle table.] + + SideEffects [None] + + SeeAlso [Cudd_Random] + +******************************************************************************/ +void +Cudd_Srandom( + long seed) +{ + int i; + + if (seed < 0) cuddRand = -seed; + else if (seed == 0) cuddRand = 1; + else cuddRand = seed; + cuddRand2 = cuddRand; + /* Load the shuffle table (after 11 warm-ups). */ + for (i = 0; i < STAB_SIZE + 11; i++) { + long int w; + w = cuddRand / LEQQ1; + cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1; + cuddRand += (cuddRand < 0) * MODULUS1; + shuffleTable[i % STAB_SIZE] = cuddRand; + } + shuffleSelect = shuffleTable[1 % STAB_SIZE]; + +} /* end of Cudd_Srandom */ + + +/**Function******************************************************************** + + Synopsis [Computes the density of a BDD or ADD.] + + Description [Computes the density of a BDD or ADD. The density is + the ratio of the number of minterms to the number of nodes. If 0 is + passed as number of variables, the number of variables existing in + the manager is used. Returns the density if successful; (double) + CUDD_OUT_OF_MEM otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_CountMinterm Cudd_DagSize] + +******************************************************************************/ +double +Cudd_Density( + DdManager * dd /* manager */, + DdNode * f /* function whose density is sought */, + int nvars /* size of the support of f */) +{ + double minterms; + int nodes; + double density; + + if (nvars == 0) nvars = dd->size; + minterms = Cudd_CountMinterm(dd,f,nvars); + if (minterms == (double) CUDD_OUT_OF_MEM) return(minterms); + nodes = Cudd_DagSize(f); + density = minterms / (double) nodes; + return(density); + +} /* end of Cudd_Density */ + + +/**Function******************************************************************** + + Synopsis [Warns that a memory allocation failed.] + + Description [Warns that a memory allocation failed. + This function can be used as replacement of MMout_of_memory to prevent + the safe_mem functions of the util package from exiting when malloc + returns NULL. One possible use is in case of discretionary allocations; + for instance, the allocation of memory to enlarge the computed table.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +Cudd_OutOfMem( + long size /* size of the allocation that failed */) +{ + (void) fflush(stdout); + (void) fprintf(stderr, "\nunable to allocate %ld bytes\n", size); + return; + +} /* end of Cudd_OutOfMem */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Prints a DD to the standard output. One line per node is + printed.] + + Description [Prints a DD to the standard output. One line per node is + printed. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_PrintDebug] + +******************************************************************************/ +int +cuddP( + DdManager * dd, + DdNode * f) +{ + int retval; + st_table *table = st_init_table(st_ptrcmp,st_ptrhash); + + if (table == NULL) return(0); + + retval = dp2(dd,f,table); + st_free_table(table); + (void) fputc('\n',dd->out); + return(retval); + +} /* end of cuddP */ + + +/**Function******************************************************************** + + Synopsis [Frees the memory used to store the minterm counts recorded + in the visited table.] + + Description [Frees the memory used to store the minterm counts + recorded in the visited table. Returns ST_CONTINUE.] + + SideEffects [None] + +******************************************************************************/ +enum st_retval +cuddStCountfree( + char * key, + char * value, + char * arg) +{ + double *d; + + d = (double *)value; + FREE(d); + return(ST_CONTINUE); + +} /* end of cuddStCountfree */ + + +/**Function******************************************************************** + + Synopsis [Recursively collects all the nodes of a DD in a symbol + table.] + + Description [Traverses the BDD f and collects all its nodes in a + symbol table. f is assumed to be a regular pointer and + cuddCollectNodes guarantees this assumption in the recursive calls. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddCollectNodes( + DdNode * f, + st_table * visited) +{ + DdNode *T, *E; + int retval; + +#ifdef DD_DEBUG + assert(!Cudd_IsComplement(f)); +#endif + + /* If already visited, nothing to do. */ + if (st_is_member(visited, (char *) f) == 1) + return(1); + + /* Check for abnormal condition that should never happen. */ + if (f == NULL) + return(0); + + /* Mark node as visited. */ + if (st_add_direct(visited, (char *) f, NULL) == ST_OUT_OF_MEM) + return(0); + + /* Check terminal case. */ + if (cuddIsConstant(f)) + return(1); + + /* Recursive calls. */ + T = cuddT(f); + retval = cuddCollectNodes(T,visited); + if (retval != 1) return(retval); + E = Cudd_Regular(cuddE(f)); + retval = cuddCollectNodes(E,visited); + return(retval); + +} /* end of cuddCollectNodes */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of cuddP.] + + Description [Performs the recursive step of cuddP. Returns 1 in case + of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +dp2( + DdManager *dd, + DdNode * f, + st_table * t) +{ + DdNode *g, *n, *N; + int T,E; + + if (f == NULL) { + return(0); + } + g = Cudd_Regular(f); + if (cuddIsConstant(g)) { +#if SIZEOF_VOID_P == 8 + (void) fprintf(dd->out,"ID = %c0x%lx\tvalue = %-9g\n", bang(f), + (unsigned long) g / (unsigned long) sizeof(DdNode),cuddV(g)); +#else + (void) fprintf(dd->out,"ID = %c0x%x\tvalue = %-9g\n", bang(f), + (unsigned) g / (unsigned) sizeof(DdNode),cuddV(g)); +#endif + return(1); + } + if (st_is_member(t,(char *) g) == 1) { + return(1); + } + if (st_add_direct(t,(char *) g,NULL) == ST_OUT_OF_MEM) + return(0); +#ifdef DD_STATS +#if SIZEOF_VOID_P == 8 + (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\tr = %d\t", bang(f), + (unsigned long) g / (unsigned long) sizeof(DdNode), g->index, g->ref); +#else + (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\tr = %d\t", bang(f), + (unsigned) g / (unsigned) sizeof(DdNode),g->index,g->ref); +#endif +#else +#if SIZEOF_VOID_P == 8 + (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\t", bang(f), + (unsigned long) g / (unsigned long) sizeof(DdNode),g->index); +#else + (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\t", bang(f), + (unsigned) g / (unsigned) sizeof(DdNode),g->index); +#endif +#endif + n = cuddT(g); + if (cuddIsConstant(n)) { + (void) fprintf(dd->out,"T = %-9g\t",cuddV(n)); + T = 1; + } else { +#if SIZEOF_VOID_P == 8 + (void) fprintf(dd->out,"T = 0x%lx\t",(unsigned long) n / (unsigned long) sizeof(DdNode)); +#else + (void) fprintf(dd->out,"T = 0x%x\t",(unsigned) n / (unsigned) sizeof(DdNode)); +#endif + T = 0; + } + + n = cuddE(g); + N = Cudd_Regular(n); + if (cuddIsConstant(N)) { + (void) fprintf(dd->out,"E = %c%-9g\n",bang(n),cuddV(N)); + E = 1; + } else { +#if SIZEOF_VOID_P == 8 + (void) fprintf(dd->out,"E = %c0x%lx\n", bang(n), (unsigned long) N/(unsigned long) sizeof(DdNode)); +#else + (void) fprintf(dd->out,"E = %c0x%x\n", bang(n), (unsigned) N/(unsigned) sizeof(DdNode)); +#endif + E = 0; + } + if (E == 0) { + if (dp2(dd,N,t) == 0) + return(0); + } + if (T == 0) { + if (dp2(dd,cuddT(g),t) == 0) + return(0); + } + return(1); + +} /* end of dp2 */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_PrintMinterm.] + + Description [] + + SideEffects [None] + +******************************************************************************/ +static void +ddPrintMintermAux( + DdManager * dd /* manager */, + DdNode * node /* current node */, + int * list /* current recursion path */) +{ + DdNode *N,*Nv,*Nnv; + int i,v,index; + + N = Cudd_Regular(node); + + if (cuddIsConstant(N)) { + /* Terminal case: Print one cube based on the current recursion + ** path, unless we have reached the background value (ADDs) or + ** the logical zero (BDDs). + */ + if (node != background && node != zero) { + for (i = 0; i < dd->size; i++) { + v = list[i]; + if (v == 0) (void) fprintf(dd->out,"0"); + else if (v == 1) (void) fprintf(dd->out,"1"); + else (void) fprintf(dd->out,"-"); + } + (void) fprintf(dd->out," % g\n", cuddV(node)); + } + } else { + Nv = cuddT(N); + Nnv = cuddE(N); + if (Cudd_IsComplement(node)) { + Nv = Cudd_Not(Nv); + Nnv = Cudd_Not(Nnv); + } + index = N->index; + list[index] = 0; + ddPrintMintermAux(dd,Nnv,list); + list[index] = 1; + ddPrintMintermAux(dd,Nv,list); + list[index] = 2; + } + return; + +} /* end of ddPrintMintermAux */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_DagSize.] + + Description [Performs the recursive step of Cudd_DagSize. Returns the + number of nodes in the graph rooted at n.] + + SideEffects [None] + +******************************************************************************/ +static int +ddDagInt( + DdNode * n) +{ + int tval, eval; + + if (Cudd_IsComplement(n->next)) { + return(0); + } + n->next = Cudd_Not(n->next); + if (cuddIsConstant(n)) { + return(1); + } + tval = ddDagInt(cuddT(n)); + eval = ddDagInt(Cudd_Regular(cuddE(n))); + return(1 + tval + eval); + +} /* end of ddDagInt */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_CofactorEstimate.] + + Description [Performs the recursive step of Cudd_CofactorEstimate. + Returns an estimate of the number of nodes in the DD of a + cofactor of node. Uses the least significant bit of the next field as + visited flag. node is supposed to be regular; the invariant is maintained + by this procedure.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddEstimateCofactor( + DdManager *dd, + st_table *table, + DdNode * node, + int i, + int phase, + DdNode ** ptr) +{ + int tval, eval, val; + DdNode *ptrT, *ptrE; + + if (Cudd_IsComplement(node->next)) { + if (!st_lookup(table,(char *)node,(char **)ptr)) { + st_add_direct(table,(char *)node,(char *)node); + *ptr = node; + } + return(0); + } + node->next = Cudd_Not(node->next); + if (cuddIsConstant(node)) { + *ptr = node; + if (st_add_direct(table,(char *)node,(char *)node) == ST_OUT_OF_MEM) + return(CUDD_OUT_OF_MEM); + return(1); + } + if ((int) node->index == i) { + if (phase == 1) { + *ptr = cuddT(node); + val = ddDagInt(cuddT(node)); + } else { + *ptr = cuddE(node); + val = ddDagInt(Cudd_Regular(cuddE(node))); + } + if (node->ref > 1) { + if (st_add_direct(table,(char *)node,(char *)*ptr) == + ST_OUT_OF_MEM) + return(CUDD_OUT_OF_MEM); + } + return(val); + } + if (dd->perm[node->index] > dd->perm[i]) { + *ptr = node; + tval = ddDagInt(cuddT(node)); + eval = ddDagInt(Cudd_Regular(cuddE(node))); + if (node->ref > 1) { + if (st_add_direct(table,(char *)node,(char *)node) == + ST_OUT_OF_MEM) + return(CUDD_OUT_OF_MEM); + } + val = 1 + tval + eval; + return(val); + } + tval = cuddEstimateCofactor(dd,table,cuddT(node),i,phase,&ptrT); + eval = cuddEstimateCofactor(dd,table,Cudd_Regular(cuddE(node)),i, + phase,&ptrE); + ptrE = Cudd_NotCond(ptrE,Cudd_IsComplement(cuddE(node))); + if (ptrT == ptrE) { /* recombination */ + *ptr = ptrT; + val = tval; + if (node->ref > 1) { + if (st_add_direct(table,(char *)node,(char *)*ptr) == + ST_OUT_OF_MEM) + return(CUDD_OUT_OF_MEM); + } + } else if ((ptrT != cuddT(node) || ptrE != cuddE(node)) && + (*ptr = cuddUniqueLookup(dd,node->index,ptrT,ptrE)) != NULL) { + if (Cudd_IsComplement((*ptr)->next)) { + val = 0; + } else { + val = 1 + tval + eval; + } + if (node->ref > 1) { + if (st_add_direct(table,(char *)node,(char *)*ptr) == + ST_OUT_OF_MEM) + return(CUDD_OUT_OF_MEM); + } + } else { + *ptr = node; + val = 1 + tval + eval; + } + return(val); + +} /* end of cuddEstimateCofactor */ + + +/**Function******************************************************************** + + Synopsis [Checks the unique table for the existence of an internal node.] + + Description [Checks the unique table for the existence of an internal + node. Returns a pointer to the node if it is in the table; NULL otherwise.] + + SideEffects [None] + + SeeAlso [cuddUniqueInter] + +******************************************************************************/ +static DdNode * +cuddUniqueLookup( + DdManager * unique, + int index, + DdNode * T, + DdNode * E) +{ + int posn; + unsigned int level; + DdNodePtr *nodelist; + DdNode *looking; + DdSubtable *subtable; + + if (index >= unique->size) { + return(NULL); + } + + level = unique->perm[index]; + subtable = &(unique->subtables[level]); + +#ifdef DD_DEBUG + assert(level < (unsigned) cuddI(unique,T->index)); + assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index)); +#endif + + posn = ddHash(T, E, subtable->shift); + nodelist = subtable->nodelist; + looking = nodelist[posn]; + + while (T < cuddT(looking)) { + looking = Cudd_Regular(looking->next); + } + while (T == cuddT(looking) && E < cuddE(looking)) { + looking = Cudd_Regular(looking->next); + } + if (cuddT(looking) == T && cuddE(looking) == E) { + return(looking); + } + + return(NULL); + +} /* end of cuddUniqueLookup */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_CofactorEstimateSimple.] + + Description [Performs the recursive step of Cudd_CofactorEstimateSimple. + Returns an estimate of the number of nodes in the DD of the positive + cofactor of node. Uses the least significant bit of the next field as + visited flag. node is supposed to be regular; the invariant is maintained + by this procedure.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddEstimateCofactorSimple( + DdNode * node, + int i) +{ + int tval, eval; + + if (Cudd_IsComplement(node->next)) { + return(0); + } + node->next = Cudd_Not(node->next); + if (cuddIsConstant(node)) { + return(1); + } + tval = cuddEstimateCofactorSimple(cuddT(node),i); + if ((int) node->index == i) return(tval); + eval = cuddEstimateCofactorSimple(Cudd_Regular(cuddE(node)),i); + return(1 + tval + eval); + +} /* end of cuddEstimateCofactorSimple */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_CountMinterm.] + + Description [Performs the recursive step of Cudd_CountMinterm. + It is based on the following identity. Let |f| be the + number of minterms of f. Then: +

        + |f| = (|f0|+|f1|)/2 + + where f0 and f1 are the two cofactors of f. Does not use the + identity |f'| = max - |f|, to minimize loss of accuracy due to + roundoff. Returns the number of minterms of the function rooted at + node.] + + SideEffects [None] + +******************************************************************************/ +static double +ddCountMintermAux( + DdNode * node, + double max, + DdHashTable * table) +{ + DdNode *N, *Nt, *Ne; + double min, minT, minE; + DdNode *res; + + N = Cudd_Regular(node); + + if (cuddIsConstant(N)) { + if (node == background || node == zero) { + return(0.0); + } else { + return(max); + } + } + if (N->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) { + min = cuddV(res); + if (res->ref == 0) { + table->manager->dead++; + table->manager->constants.dead++; + } + return(min); + } + + Nt = cuddT(N); Ne = cuddE(N); + if (Cudd_IsComplement(node)) { + Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne); + } + + minT = ddCountMintermAux(Nt,max,table); + if (minT == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); + minT *= 0.5; + minE = ddCountMintermAux(Ne,max,table); + if (minE == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); + minE *= 0.5; + min = minT + minE; + + if (N->ref != 1) { + ptrint fanout = (ptrint) N->ref; + cuddSatDec(fanout); + res = cuddUniqueConst(table->manager,min); + if (!cuddHashTableInsert1(table,node,res,fanout)) { + cuddRef(res); Cudd_RecursiveDeref(table->manager, res); + return((double)CUDD_OUT_OF_MEM); + } + } + + return(min); + +} /* end of ddCountMintermAux */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_CountPath.] + + Description [Performs the recursive step of Cudd_CountPath. + It is based on the following identity. Let |f| be the + number of paths of f. Then: + + |f| = |f0|+|f1| + + where f0 and f1 are the two cofactors of f. Uses the + identity |f'| = |f|, to improve the utilization of the (local) cache. + Returns the number of paths of the function rooted at node.] + + SideEffects [None] + +******************************************************************************/ +static double +ddCountPathAux( + DdNode * node, + st_table * table) +{ + + DdNode *Nv, *Nnv; + double paths, *ppaths, paths1, paths2; + double *dummy; + + + if (cuddIsConstant(node)) { + return(1.0); + } + if (st_lookup(table, (char *)node, (char **)&dummy)) { + paths = *dummy; + return(paths); + } + + Nv = cuddT(node); Nnv = cuddE(node); + + paths1 = ddCountPathAux(Nv,table); + if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); + paths2 = ddCountPathAux(Cudd_Regular(Nnv),table); + if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); + paths = paths1 + paths2; + + ppaths = ALLOC(double,1); + if (ppaths == NULL) { + return((double)CUDD_OUT_OF_MEM); + } + + *ppaths = paths; + + if (st_add_direct(table,(char *)node, (char *)ppaths) == ST_OUT_OF_MEM) { + FREE(ppaths); + return((double)CUDD_OUT_OF_MEM); + } + return(paths); + +} /* end of ddCountPathAux */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_CountMinterm.] + + Description [Performs the recursive step of Cudd_CountMinterm. + It is based on the following identity. Let |f| be the + number of minterms of f. Then: + + |f| = (|f0|+|f1|)/2 + + where f0 and f1 are the two cofactors of f. Does not use the + identity |f'| = max - |f|, to minimize loss of accuracy due to + roundoff. Returns the number of minterms of the function rooted at + node.] + + SideEffects [None] + +******************************************************************************/ +static int +ddEpdCountMintermAux( + DdNode * node, + EpDouble * max, + EpDouble * epd, + st_table * table) +{ + DdNode *Nt, *Ne; + EpDouble *min, minT, minE; + EpDouble *res; + int status; + + if (cuddIsConstant(node)) { + if (node == background || node == zero) { + EpdMakeZero(epd, 0); + } else { + EpdCopy(max, epd); + } + return(0); + } + if (node->ref != 1 && st_lookup(table, (char *)node, (char **)&res)) { + EpdCopy(res, epd); + return(0); + } + + Nt = cuddT(node); Ne = cuddE(node); + if (Cudd_IsComplement(node)) { + Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne); + } + + status = ddEpdCountMintermAux(Nt,max,&minT,table); + if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); + EpdMultiply(&minT, (double)0.5); + status = ddEpdCountMintermAux(Ne,max,&minE,table); + if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); + if (Cudd_IsComplement(Ne)) { + EpdSubtract3(max, &minE, epd); + EpdCopy(epd, &minE); + } + EpdMultiply(&minE, (double)0.5); + EpdAdd3(&minT, &minE, epd); + + if (node->ref > 1) { + min = EpdAlloc(); + if (!min) + return(CUDD_OUT_OF_MEM); + EpdCopy(epd, min); + if (st_insert(table, (char *)node, (char *)min) == ST_OUT_OF_MEM) { + EpdFree(min); + return(CUDD_OUT_OF_MEM); + } + } + + return(0); + +} /* end of ddEpdCountMintermAux */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_CountPathsToNonZero.] + + Description [Performs the recursive step of Cudd_CountPathsToNonZero. + It is based on the following identity. Let |f| be the + number of paths of f. Then: + + |f| = |f0|+|f1| + + where f0 and f1 are the two cofactors of f. Returns the number of + paths of the function rooted at node.] + + SideEffects [None] + +******************************************************************************/ +static double +ddCountPathsToNonZero( + DdNode * N, + st_table * table) +{ + + DdNode *node, *Nt, *Ne; + double paths, *ppaths, paths1, paths2; + double *dummy; + + node = Cudd_Regular(N); + if (cuddIsConstant(node)) { + return((double) !(Cudd_IsComplement(N) || cuddV(node)==DD_ZERO_VAL)); + } + if (st_lookup(table, (char *)N, (char **)&dummy)) { + paths = *dummy; + return(paths); + } + + Nt = cuddT(node); Ne = cuddE(node); + if (node != N) { + Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne); + } + + paths1 = ddCountPathsToNonZero(Nt,table); + if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); + paths2 = ddCountPathsToNonZero(Ne,table); + if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); + paths = paths1 + paths2; + + ppaths = ALLOC(double,1); + if (ppaths == NULL) { + return((double)CUDD_OUT_OF_MEM); + } + + *ppaths = paths; + + if (st_add_direct(table,(char *)N, (char *)ppaths) == ST_OUT_OF_MEM) { + FREE(ppaths); + return((double)CUDD_OUT_OF_MEM); + } + return(paths); + +} /* end of ddCountPathsToNonZero */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_Support.] + + Description [Performs the recursive step of Cudd_Support. Performs a + DFS from f. The support is accumulated in supp as a side effect. Uses + the LSB of the then pointer as visited flag.] + + SideEffects [None] + + SeeAlso [ddClearFlag] + +******************************************************************************/ +static void +ddSupportStep( + DdNode * f, + int * support) +{ + if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) { + return; + } + + support[f->index] = 1; + ddSupportStep(cuddT(f),support); + ddSupportStep(Cudd_Regular(cuddE(f)),support); + /* Mark as visited. */ + f->next = Cudd_Not(f->next); + return; + +} /* end of ddSupportStep */ + + +/**Function******************************************************************** + + Synopsis [Performs a DFS from f, clearing the LSB of the next + pointers.] + + Description [] + + SideEffects [None] + + SeeAlso [ddSupportStep ddDagInt] + +******************************************************************************/ +static void +ddClearFlag( + DdNode * f) +{ + if (!Cudd_IsComplement(f->next)) { + return; + } + /* Clear visited flag. */ + f->next = Cudd_Regular(f->next); + if (cuddIsConstant(f)) { + return; + } + ddClearFlag(cuddT(f)); + ddClearFlag(Cudd_Regular(cuddE(f))); + return; + +} /* end of ddClearFlag */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_CountLeaves.] + + Description [Performs the recursive step of Cudd_CountLeaves. Returns + the number of leaves in the DD rooted at n.] + + SideEffects [None] + + SeeAlso [Cudd_CountLeaves] + +******************************************************************************/ +static int +ddLeavesInt( + DdNode * n) +{ + int tval, eval; + + if (Cudd_IsComplement(n->next)) { + return(0); + } + n->next = Cudd_Not(n->next); + if (cuddIsConstant(n)) { + return(1); + } + tval = ddLeavesInt(cuddT(n)); + eval = ddLeavesInt(Cudd_Regular(cuddE(n))); + return(tval + eval); + +} /* end of ddLeavesInt */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddPickArbitraryMinterms.] + + Description [Performs the recursive step of Cudd_bddPickArbitraryMinterms. + Returns 1 if successful; 0 otherwise.] + + SideEffects [none] + + SeeAlso [Cudd_bddPickArbitraryMinterms] + +******************************************************************************/ +static int +ddPickArbitraryMinterms( + DdManager *dd, + DdNode *node, + int nvars, + int nminterms, + char **string) +{ + DdNode *N, *T, *E; + DdNode *one, *bzero; + int i, t, result; + double min1, min2; + + if (string == NULL || node == NULL) return(0); + + /* The constant 0 function has no on-set cubes. */ + one = DD_ONE(dd); + bzero = Cudd_Not(one); + if (nminterms == 0 || node == bzero) return(1); + if (node == one) { + return(1); + } + + N = Cudd_Regular(node); + T = cuddT(N); E = cuddE(N); + if (Cudd_IsComplement(node)) { + T = Cudd_Not(T); E = Cudd_Not(E); + } + + min1 = Cudd_CountMinterm(dd, T, nvars) / 2.0; + if (min1 == (double)CUDD_OUT_OF_MEM) return(0); + min2 = Cudd_CountMinterm(dd, E, nvars) / 2.0; + if (min2 == (double)CUDD_OUT_OF_MEM) return(0); + + t = (int)((double)nminterms * min1 / (min1 + min2) + 0.5); + for (i = 0; i < t; i++) + string[i][N->index] = '1'; + for (i = t; i < nminterms; i++) + string[i][N->index] = '0'; + + result = ddPickArbitraryMinterms(dd,T,nvars,t,&string[0]); + if (result == 0) + return(0); + result = ddPickArbitraryMinterms(dd,E,nvars,nminterms-t,&string[t]); + return(result); + +} /* end of ddPickArbitraryMinterms */ + + +/**Function******************************************************************** + + Synopsis [Finds a representative cube of a BDD.] + + Description [Finds a representative cube of a BDD with the weight of + each variable. From the top variable, if the weight is greater than or + equal to 0.0, choose THEN branch unless the child is the constant 0. + Otherwise, choose ELSE branch unless the child is the constant 0.] + + SideEffects [Cudd_SubsetWithMaskVars Cudd_bddPickOneCube] + +******************************************************************************/ +static int +ddPickRepresentativeCube( + DdManager *dd, + DdNode *node, + int nvars, + double *weight, + char *string) +{ + DdNode *N, *T, *E; + DdNode *one, *bzero; + + if (string == NULL || node == NULL) return(0); + + /* The constant 0 function has no on-set cubes. */ + one = DD_ONE(dd); + bzero = Cudd_Not(one); + if (node == bzero) return(0); + + if (node == DD_ONE(dd)) return(1); + + for (;;) { + N = Cudd_Regular(node); + if (N == one) + break; + T = cuddT(N); + E = cuddE(N); + if (Cudd_IsComplement(node)) { + T = Cudd_Not(T); + E = Cudd_Not(E); + } + if (weight[N->index] >= 0.0) { + if (T == bzero) { + node = E; + string[N->index] = '0'; + } else { + node = T; + string[N->index] = '1'; + } + } else { + if (E == bzero) { + node = T; + string[N->index] = '1'; + } else { + node = E; + string[N->index] = '0'; + } + } + } + return(1); + +} /* end of ddPickRepresentativeCube */ + + +/**Function******************************************************************** + + Synopsis [Frees the memory used to store the minterm counts recorded + in the visited table.] + + Description [Frees the memory used to store the minterm counts + recorded in the visited table. Returns ST_CONTINUE.] + + SideEffects [None] + +******************************************************************************/ +static enum st_retval +ddEpdFree( + char * key, + char * value, + char * arg) +{ + EpDouble *epd; + + epd = (EpDouble *) value; + EpdFree(epd); + return(ST_CONTINUE); + +} /* end of ddEpdFree */ diff --git a/abc70930/src/bdd/cudd/cuddWindow.c b/abc70930/src/bdd/cudd/cuddWindow.c new file mode 100644 index 00000000..9ceb79b2 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddWindow.c @@ -0,0 +1,997 @@ +/**CFile*********************************************************************** + + FileName [cuddWindow.c] + + PackageName [cudd] + + Synopsis [Functions for window permutation] + + Description [Internal procedures included in this module: +
          +
        • cuddWindowReorder() +
        + Static procedures included in this module: +
          +
        • ddWindow2() +
        • ddWindowConv2() +
        • ddPermuteWindow3() +
        • ddWindow3() +
        • ddWindowConv3() +
        • ddPermuteWindow4() +
        • ddWindow4() +
        • ddWindowConv4() +
        ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddWindow.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +#ifdef DD_STATS +extern int ddTotalNumberSwapping; +extern int ddTotalNISwaps; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int ddWindow2 ARGS((DdManager *table, int low, int high)); +static int ddWindowConv2 ARGS((DdManager *table, int low, int high)); +static int ddPermuteWindow3 ARGS((DdManager *table, int x)); +static int ddWindow3 ARGS((DdManager *table, int low, int high)); +static int ddWindowConv3 ARGS((DdManager *table, int low, int high)); +static int ddPermuteWindow4 ARGS((DdManager *table, int w)); +static int ddWindow4 ARGS((DdManager *table, int low, int high)); +static int ddWindowConv4 ARGS((DdManager *table, int low, int high)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Reorders by applying the method of the sliding window.] + + Description [Reorders by applying the method of the sliding window. + Tries all possible permutations to the variables in a window that + slides from low to high. The size of the window is determined by + submethod. Assumes that no dead nodes are present. Returns 1 in + case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +int +cuddWindowReorder( + DdManager * table /* DD table */, + int low /* lowest index to reorder */, + int high /* highest index to reorder */, + Cudd_ReorderingType submethod /* window reordering option */) +{ + + int res; +#ifdef DD_DEBUG + int supposedOpt; +#endif + + switch (submethod) { + case CUDD_REORDER_WINDOW2: + res = ddWindow2(table,low,high); + break; + case CUDD_REORDER_WINDOW3: + res = ddWindow3(table,low,high); + break; + case CUDD_REORDER_WINDOW4: + res = ddWindow4(table,low,high); + break; + case CUDD_REORDER_WINDOW2_CONV: + res = ddWindowConv2(table,low,high); + break; + case CUDD_REORDER_WINDOW3_CONV: + res = ddWindowConv3(table,low,high); +#ifdef DD_DEBUG + supposedOpt = table->keys - table->isolated; + res = ddWindow3(table,low,high); + if (table->keys - table->isolated != (unsigned) supposedOpt) { + (void) fprintf(table->err, "Convergence failed! (%d != %d)\n", + table->keys - table->isolated, supposedOpt); + } +#endif + break; + case CUDD_REORDER_WINDOW4_CONV: + res = ddWindowConv4(table,low,high); +#ifdef DD_DEBUG + supposedOpt = table->keys - table->isolated; + res = ddWindow4(table,low,high); + if (table->keys - table->isolated != (unsigned) supposedOpt) { + (void) fprintf(table->err,"Convergence failed! (%d != %d)\n", + table->keys - table->isolated, supposedOpt); + } +#endif + break; + default: return(0); + } + + return(res); + +} /* end of cuddWindowReorder */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Reorders by applying a sliding window of width 2.] + + Description [Reorders by applying a sliding window of width 2. + Tries both permutations of the variables in a window + that slides from low to high. Assumes that no dead nodes are + present. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddWindow2( + DdManager * table, + int low, + int high) +{ + + int x; + int res; + int size; + +#ifdef DD_DEBUG + assert(low >= 0 && high < table->size); +#endif + + if (high-low < 1) return(0); + + res = table->keys - table->isolated; + for (x = low; x < high; x++) { + size = res; + res = cuddSwapInPlace(table,x,x+1); + if (res == 0) return(0); + if (res >= size) { /* no improvement: undo permutation */ + res = cuddSwapInPlace(table,x,x+1); + if (res == 0) return(0); + } +#ifdef DD_STATS + if (res < size) { + (void) fprintf(table->out,"-"); + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + + return(1); + +} /* end of ddWindow2 */ + + +/**Function******************************************************************** + + Synopsis [Reorders by repeatedly applying a sliding window of width 2.] + + Description [Reorders by repeatedly applying a sliding window of width + 2. Tries both permutations of the variables in a window + that slides from low to high. Assumes that no dead nodes are + present. Uses an event-driven approach to determine convergence. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddWindowConv2( + DdManager * table, + int low, + int high) +{ + int x; + int res; + int nwin; + int newevent; + int *events; + int size; + +#ifdef DD_DEBUG + assert(low >= 0 && high < table->size); +#endif + + if (high-low < 1) return(ddWindowConv2(table,low,high)); + + nwin = high-low; + events = ALLOC(int,nwin); + if (events == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (x=0; xkeys - table->isolated; + do { + newevent = 0; + for (x=0; x= size) { /* no improvement: undo permutation */ + res = cuddSwapInPlace(table,x+low,x+low+1); + if (res == 0) { + FREE(events); + return(0); + } + } + if (res < size) { + if (x < nwin-1) events[x+1] = 1; + if (x > 0) events[x-1] = 1; + newevent = 1; + } + events[x] = 0; +#ifdef DD_STATS + if (res < size) { + (void) fprintf(table->out,"-"); + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + } +#ifdef DD_STATS + if (newevent) { + (void) fprintf(table->out,"|"); + fflush(table->out); + } +#endif + } while (newevent); + + FREE(events); + + return(1); + +} /* end of ddWindowConv3 */ + + +/**Function******************************************************************** + + Synopsis [Tries all the permutations of the three variables between + x and x+2 and retains the best.] + + Description [Tries all the permutations of the three variables between + x and x+2 and retains the best. Assumes that no dead nodes are + present. Returns the index of the best permutation (1-6) in case of + success; 0 otherwise.Assumes that no dead nodes are present. Returns + the index of the best permutation (1-6) in case of success; 0 + otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddPermuteWindow3( + DdManager * table, + int x) +{ + int y,z; + int size,sizeNew; + int best; + +#ifdef DD_DEBUG + assert(table->dead == 0); + assert(x+2 < table->size); +#endif + + size = table->keys - table->isolated; + y = x+1; z = y+1; + + /* The permutation pattern is: + ** (x,y)(y,z) + ** repeated three times to get all 3! = 6 permutations. + */ +#define ABC 1 + best = ABC; + +#define BAC 2 + sizeNew = cuddSwapInPlace(table,x,y); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = BAC; + size = sizeNew; + } +#define BCA 3 + sizeNew = cuddSwapInPlace(table,y,z); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = BCA; + size = sizeNew; + } +#define CBA 4 + sizeNew = cuddSwapInPlace(table,x,y); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = CBA; + size = sizeNew; + } +#define CAB 5 + sizeNew = cuddSwapInPlace(table,y,z); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = CAB; + size = sizeNew; + } +#define ACB 6 + sizeNew = cuddSwapInPlace(table,x,y); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = ACB; + size = sizeNew; + } + + /* Now take the shortest route to the best permuytation. + ** The initial permutation is ACB. + */ + switch(best) { + case BCA: if (!cuddSwapInPlace(table,y,z)) return(0); + case CBA: if (!cuddSwapInPlace(table,x,y)) return(0); + case ABC: if (!cuddSwapInPlace(table,y,z)) return(0); + case ACB: break; + case BAC: if (!cuddSwapInPlace(table,y,z)) return(0); + case CAB: if (!cuddSwapInPlace(table,x,y)) return(0); + break; + default: return(0); + } + +#ifdef DD_DEBUG + assert(table->keys - table->isolated == (unsigned) size); +#endif + + return(best); + +} /* end of ddPermuteWindow3 */ + + +/**Function******************************************************************** + + Synopsis [Reorders by applying a sliding window of width 3.] + + Description [Reorders by applying a sliding window of width 3. + Tries all possible permutations to the variables in a + window that slides from low to high. Assumes that no dead nodes are + present. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddWindow3( + DdManager * table, + int low, + int high) +{ + + int x; + int res; + +#ifdef DD_DEBUG + assert(low >= 0 && high < table->size); +#endif + + if (high-low < 2) return(ddWindow2(table,low,high)); + + for (x = low; x+1 < high; x++) { + res = ddPermuteWindow3(table,x); + if (res == 0) return(0); +#ifdef DD_STATS + if (res == ABC) { + (void) fprintf(table->out,"="); + } else { + (void) fprintf(table->out,"-"); + } + fflush(table->out); +#endif + } + + return(1); + +} /* end of ddWindow3 */ + + +/**Function******************************************************************** + + Synopsis [Reorders by repeatedly applying a sliding window of width 3.] + + Description [Reorders by repeatedly applying a sliding window of width + 3. Tries all possible permutations to the variables in a + window that slides from low to high. Assumes that no dead nodes are + present. Uses an event-driven approach to determine convergence. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddWindowConv3( + DdManager * table, + int low, + int high) +{ + int x; + int res; + int nwin; + int newevent; + int *events; + +#ifdef DD_DEBUG + assert(low >= 0 && high < table->size); +#endif + + if (high-low < 2) return(ddWindowConv2(table,low,high)); + + nwin = high-low-1; + events = ALLOC(int,nwin); + if (events == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (x=0; x 1) events[x-2] = 1; + newevent = 1; + break; + case BCA: + case CBA: + case CAB: + if (x < nwin-2) events[x+2] = 1; + if (x < nwin-1) events[x+1] = 1; + if (x > 0) events[x-1] = 1; + if (x > 1) events[x-2] = 1; + newevent = 1; + break; + case ACB: + if (x < nwin-2) events[x+2] = 1; + if (x > 0) events[x-1] = 1; + newevent = 1; + break; + default: + FREE(events); + return(0); + } + events[x] = 0; +#ifdef DD_STATS + if (res == ABC) { + (void) fprintf(table->out,"="); + } else { + (void) fprintf(table->out,"-"); + } + fflush(table->out); +#endif + } + } +#ifdef DD_STATS + if (newevent) { + (void) fprintf(table->out,"|"); + fflush(table->out); + } +#endif + } while (newevent); + + FREE(events); + + return(1); + +} /* end of ddWindowConv3 */ + + +/**Function******************************************************************** + + Synopsis [Tries all the permutations of the four variables between w + and w+3 and retains the best.] + + Description [Tries all the permutations of the four variables between + w and w+3 and retains the best. Assumes that no dead nodes are + present. Returns the index of the best permutation (1-24) in case of + success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddPermuteWindow4( + DdManager * table, + int w) +{ + int x,y,z; + int size,sizeNew; + int best; + +#ifdef DD_DEBUG + assert(table->dead == 0); + assert(w+3 < table->size); +#endif + + size = table->keys - table->isolated; + x = w+1; y = x+1; z = y+1; + + /* The permutation pattern is: + * (w,x)(y,z)(w,x)(x,y) + * (y,z)(w,x)(y,z)(x,y) + * repeated three times to get all 4! = 24 permutations. + * This gives a hamiltonian circuit of Cayley's graph. + * The codes to the permutation are assigned in topological order. + * The permutations at lower distance from the final permutation are + * assigned lower codes. This way we can choose, between + * permutations that give the same size, one that requires the minimum + * number of swaps from the final permutation of the hamiltonian circuit. + * There is an exception to this rule: ABCD is given Code 1, to + * avoid oscillation when convergence is sought. + */ +#define ABCD 1 + best = ABCD; + +#define BACD 7 + sizeNew = cuddSwapInPlace(table,w,x); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = BACD; + size = sizeNew; + } +#define BADC 13 + sizeNew = cuddSwapInPlace(table,y,z); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = BADC; + size = sizeNew; + } +#define ABDC 8 + sizeNew = cuddSwapInPlace(table,w,x); + if (sizeNew < size || (sizeNew == size && ABDC < best)) { + if (sizeNew == 0) return(0); + best = ABDC; + size = sizeNew; + } +#define ADBC 14 + sizeNew = cuddSwapInPlace(table,x,y); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = ADBC; + size = sizeNew; + } +#define ADCB 9 + sizeNew = cuddSwapInPlace(table,y,z); + if (sizeNew < size || (sizeNew == size && ADCB < best)) { + if (sizeNew == 0) return(0); + best = ADCB; + size = sizeNew; + } +#define DACB 15 + sizeNew = cuddSwapInPlace(table,w,x); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = DACB; + size = sizeNew; + } +#define DABC 20 + sizeNew = cuddSwapInPlace(table,y,z); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = DABC; + size = sizeNew; + } +#define DBAC 23 + sizeNew = cuddSwapInPlace(table,x,y); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = DBAC; + size = sizeNew; + } +#define BDAC 19 + sizeNew = cuddSwapInPlace(table,w,x); + if (sizeNew < size || (sizeNew == size && BDAC < best)) { + if (sizeNew == 0) return(0); + best = BDAC; + size = sizeNew; + } +#define BDCA 21 + sizeNew = cuddSwapInPlace(table,y,z); + if (sizeNew < size || (sizeNew == size && BDCA < best)) { + if (sizeNew == 0) return(0); + best = BDCA; + size = sizeNew; + } +#define DBCA 24 + sizeNew = cuddSwapInPlace(table,w,x); + if (sizeNew < size) { + if (sizeNew == 0) return(0); + best = DBCA; + size = sizeNew; + } +#define DCBA 22 + sizeNew = cuddSwapInPlace(table,x,y); + if (sizeNew < size || (sizeNew == size && DCBA < best)) { + if (sizeNew == 0) return(0); + best = DCBA; + size = sizeNew; + } +#define DCAB 18 + sizeNew = cuddSwapInPlace(table,y,z); + if (sizeNew < size || (sizeNew == size && DCAB < best)) { + if (sizeNew == 0) return(0); + best = DCAB; + size = sizeNew; + } +#define CDAB 12 + sizeNew = cuddSwapInPlace(table,w,x); + if (sizeNew < size || (sizeNew == size && CDAB < best)) { + if (sizeNew == 0) return(0); + best = CDAB; + size = sizeNew; + } +#define CDBA 17 + sizeNew = cuddSwapInPlace(table,y,z); + if (sizeNew < size || (sizeNew == size && CDBA < best)) { + if (sizeNew == 0) return(0); + best = CDBA; + size = sizeNew; + } +#define CBDA 11 + sizeNew = cuddSwapInPlace(table,x,y); + if (sizeNew < size || (sizeNew == size && CBDA < best)) { + if (sizeNew == 0) return(0); + best = CBDA; + size = sizeNew; + } +#define BCDA 16 + sizeNew = cuddSwapInPlace(table,w,x); + if (sizeNew < size || (sizeNew == size && BCDA < best)) { + if (sizeNew == 0) return(0); + best = BCDA; + size = sizeNew; + } +#define BCAD 10 + sizeNew = cuddSwapInPlace(table,y,z); + if (sizeNew < size || (sizeNew == size && BCAD < best)) { + if (sizeNew == 0) return(0); + best = BCAD; + size = sizeNew; + } +#define CBAD 5 + sizeNew = cuddSwapInPlace(table,w,x); + if (sizeNew < size || (sizeNew == size && CBAD < best)) { + if (sizeNew == 0) return(0); + best = CBAD; + size = sizeNew; + } +#define CABD 3 + sizeNew = cuddSwapInPlace(table,x,y); + if (sizeNew < size || (sizeNew == size && CABD < best)) { + if (sizeNew == 0) return(0); + best = CABD; + size = sizeNew; + } +#define CADB 6 + sizeNew = cuddSwapInPlace(table,y,z); + if (sizeNew < size || (sizeNew == size && CADB < best)) { + if (sizeNew == 0) return(0); + best = CADB; + size = sizeNew; + } +#define ACDB 4 + sizeNew = cuddSwapInPlace(table,w,x); + if (sizeNew < size || (sizeNew == size && ACDB < best)) { + if (sizeNew == 0) return(0); + best = ACDB; + size = sizeNew; + } +#define ACBD 2 + sizeNew = cuddSwapInPlace(table,y,z); + if (sizeNew < size || (sizeNew == size && ACBD < best)) { + if (sizeNew == 0) return(0); + best = ACBD; + size = sizeNew; + } + + /* Now take the shortest route to the best permutation. + ** The initial permutation is ACBD. + */ + switch(best) { + case DBCA: if (!cuddSwapInPlace(table,y,z)) return(0); + case BDCA: if (!cuddSwapInPlace(table,x,y)) return(0); + case CDBA: if (!cuddSwapInPlace(table,w,x)) return(0); + case ADBC: if (!cuddSwapInPlace(table,y,z)) return(0); + case ABDC: if (!cuddSwapInPlace(table,x,y)) return(0); + case ACDB: if (!cuddSwapInPlace(table,y,z)) return(0); + case ACBD: break; + case DCBA: if (!cuddSwapInPlace(table,y,z)) return(0); + case BCDA: if (!cuddSwapInPlace(table,x,y)) return(0); + case CBDA: if (!cuddSwapInPlace(table,w,x)) return(0); + if (!cuddSwapInPlace(table,x,y)) return(0); + if (!cuddSwapInPlace(table,y,z)) return(0); + break; + case DBAC: if (!cuddSwapInPlace(table,x,y)) return(0); + case DCAB: if (!cuddSwapInPlace(table,w,x)) return(0); + case DACB: if (!cuddSwapInPlace(table,y,z)) return(0); + case BACD: if (!cuddSwapInPlace(table,x,y)) return(0); + case CABD: if (!cuddSwapInPlace(table,w,x)) return(0); + break; + case DABC: if (!cuddSwapInPlace(table,y,z)) return(0); + case BADC: if (!cuddSwapInPlace(table,x,y)) return(0); + case CADB: if (!cuddSwapInPlace(table,w,x)) return(0); + if (!cuddSwapInPlace(table,y,z)) return(0); + break; + case BDAC: if (!cuddSwapInPlace(table,x,y)) return(0); + case CDAB: if (!cuddSwapInPlace(table,w,x)) return(0); + case ADCB: if (!cuddSwapInPlace(table,y,z)) return(0); + case ABCD: if (!cuddSwapInPlace(table,x,y)) return(0); + break; + case BCAD: if (!cuddSwapInPlace(table,x,y)) return(0); + case CBAD: if (!cuddSwapInPlace(table,w,x)) return(0); + if (!cuddSwapInPlace(table,x,y)) return(0); + break; + default: return(0); + } + +#ifdef DD_DEBUG + assert(table->keys - table->isolated == (unsigned) size); +#endif + + return(best); + +} /* end of ddPermuteWindow4 */ + + +/**Function******************************************************************** + + Synopsis [Reorders by applying a sliding window of width 4.] + + Description [Reorders by applying a sliding window of width 4. + Tries all possible permutations to the variables in a + window that slides from low to high. Assumes that no dead nodes are + present. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddWindow4( + DdManager * table, + int low, + int high) +{ + + int w; + int res; + +#ifdef DD_DEBUG + assert(low >= 0 && high < table->size); +#endif + + if (high-low < 3) return(ddWindow3(table,low,high)); + + for (w = low; w+2 < high; w++) { + res = ddPermuteWindow4(table,w); + if (res == 0) return(0); +#ifdef DD_STATS + if (res == ABCD) { + (void) fprintf(table->out,"="); + } else { + (void) fprintf(table->out,"-"); + } + fflush(table->out); +#endif + } + + return(1); + +} /* end of ddWindow4 */ + + +/**Function******************************************************************** + + Synopsis [Reorders by repeatedly applying a sliding window of width 4.] + + Description [Reorders by repeatedly applying a sliding window of width + 4. Tries all possible permutations to the variables in a + window that slides from low to high. Assumes that no dead nodes are + present. Uses an event-driven approach to determine convergence. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +ddWindowConv4( + DdManager * table, + int low, + int high) +{ + int x; + int res; + int nwin; + int newevent; + int *events; + +#ifdef DD_DEBUG + assert(low >= 0 && high < table->size); +#endif + + if (high-low < 3) return(ddWindowConv3(table,low,high)); + + nwin = high-low-2; + events = ALLOC(int,nwin); + if (events == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (x=0; x 2) events[x-3] = 1; + newevent = 1; + break; + case BADC: + if (x < nwin-3) events[x+3] = 1; + if (x < nwin-1) events[x+1] = 1; + if (x > 0) events[x-1] = 1; + if (x > 2) events[x-3] = 1; + newevent = 1; + break; + case ABDC: + if (x < nwin-3) events[x+3] = 1; + if (x > 0) events[x-1] = 1; + newevent = 1; + break; + case ADBC: + case ADCB: + case ACDB: + if (x < nwin-3) events[x+3] = 1; + if (x < nwin-2) events[x+2] = 1; + if (x > 0) events[x-1] = 1; + if (x > 1) events[x-2] = 1; + newevent = 1; + break; + case DACB: + case DABC: + case DBAC: + case BDAC: + case BDCA: + case DBCA: + case DCBA: + case DCAB: + case CDAB: + case CDBA: + case CBDA: + case BCDA: + case CADB: + if (x < nwin-3) events[x+3] = 1; + if (x < nwin-2) events[x+2] = 1; + if (x < nwin-1) events[x+1] = 1; + if (x > 0) events[x-1] = 1; + if (x > 1) events[x-2] = 1; + if (x > 2) events[x-3] = 1; + newevent = 1; + break; + case BCAD: + case CBAD: + case CABD: + if (x < nwin-2) events[x+2] = 1; + if (x < nwin-1) events[x+1] = 1; + if (x > 1) events[x-2] = 1; + if (x > 2) events[x-3] = 1; + newevent = 1; + break; + case ACBD: + if (x < nwin-2) events[x+2] = 1; + if (x > 1) events[x-2] = 1; + newevent = 1; + break; + default: + FREE(events); + return(0); + } + events[x] = 0; +#ifdef DD_STATS + if (res == ABCD) { + (void) fprintf(table->out,"="); + } else { + (void) fprintf(table->out,"-"); + } + fflush(table->out); +#endif + } + } +#ifdef DD_STATS + if (newevent) { + (void) fprintf(table->out,"|"); + fflush(table->out); + } +#endif + } while (newevent); + + FREE(events); + + return(1); + +} /* end of ddWindowConv4 */ + diff --git a/abc70930/src/bdd/cudd/cuddZddCount.c b/abc70930/src/bdd/cudd/cuddZddCount.c new file mode 100644 index 00000000..6c6ec1df --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddZddCount.c @@ -0,0 +1,324 @@ +/**CFile*********************************************************************** + + FileName [cuddZddCount.c] + + PackageName [cudd] + + Synopsis [Procedures to count the number of minterms of a ZDD.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddCount(); +
        • Cudd_zddCountDouble(); +
        + Internal procedures included in this module: +
          +
        + Static procedures included in this module: +
          +
        • cuddZddCountStep(); +
        • cuddZddCountDoubleStep(); +
        • st_zdd_count_dbl_free() +
        • st_zdd_countfree() +
        + ] + + SeeAlso [] + + Author [Hyong-Kyoon Shin, In-Ho Moon] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddCount.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int cuddZddCountStep ARGS((DdNode *P, st_table *table, DdNode *base, DdNode *empty)); +static double cuddZddCountDoubleStep ARGS((DdNode *P, st_table *table, DdNode *base, DdNode *empty)); +static enum st_retval st_zdd_countfree ARGS((char *key, char *value, char *arg)); +static enum st_retval st_zdd_count_dbl_free ARGS((char *key, char *value, char *arg)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Counts the number of minterms in a ZDD.] + + Description [Returns an integer representing the number of minterms + in a ZDD.] + + SideEffects [None] + + SeeAlso [Cudd_zddCountDouble] + +******************************************************************************/ +int +Cudd_zddCount( + DdManager * zdd, + DdNode * P) +{ + st_table *table; + int res; + DdNode *base, *empty; + + base = DD_ONE(zdd); + empty = DD_ZERO(zdd); + table = st_init_table(st_ptrcmp, st_ptrhash); + if (table == NULL) return(CUDD_OUT_OF_MEM); + res = cuddZddCountStep(P, table, base, empty); + if (res == CUDD_OUT_OF_MEM) { + zdd->errorCode = CUDD_MEMORY_OUT; + } + st_foreach(table, st_zdd_countfree, NIL(char)); + st_free_table(table); + + return(res); + +} /* end of Cudd_zddCount */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of minterms of a ZDD.] + + Description [Counts the number of minterms of a ZDD. The result is + returned as a double. If the procedure runs out of memory, it + returns (double) CUDD_OUT_OF_MEM. This procedure is used in + Cudd_zddCountMinterm.] + + SideEffects [None] + + SeeAlso [Cudd_zddCountMinterm Cudd_zddCount] + +******************************************************************************/ +double +Cudd_zddCountDouble( + DdManager * zdd, + DdNode * P) +{ + st_table *table; + double res; + DdNode *base, *empty; + + base = DD_ONE(zdd); + empty = DD_ZERO(zdd); + table = st_init_table(st_ptrcmp, st_ptrhash); + if (table == NULL) return((double)CUDD_OUT_OF_MEM); + res = cuddZddCountDoubleStep(P, table, base, empty); + if (res == (double)CUDD_OUT_OF_MEM) { + zdd->errorCode = CUDD_MEMORY_OUT; + } + st_foreach(table, st_zdd_count_dbl_free, NIL(char)); + st_free_table(table); + + return(res); + +} /* end of Cudd_zddCountDouble */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddCount.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddZddCountStep( + DdNode * P, + st_table * table, + DdNode * base, + DdNode * empty) +{ + int res; + int *dummy; + + if (P == empty) + return(0); + if (P == base) + return(1); + + /* Check cache. */ + if (st_lookup(table, (char *)P, (char **)(&dummy))) { + res = *dummy; + return(res); + } + + res = cuddZddCountStep(cuddE(P), table, base, empty) + + cuddZddCountStep(cuddT(P), table, base, empty); + + dummy = ALLOC(int, 1); + if (dummy == NULL) { + return(CUDD_OUT_OF_MEM); + } + *dummy = res; + if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) { + FREE(dummy); + return(CUDD_OUT_OF_MEM); + } + + return(res); + +} /* end of cuddZddCountStep */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddCountDouble.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static double +cuddZddCountDoubleStep( + DdNode * P, + st_table * table, + DdNode * base, + DdNode * empty) +{ + double res; + double *dummy; + + if (P == empty) + return((double)0.0); + if (P == base) + return((double)1.0); + + /* Check cache */ + if (st_lookup(table, (char *)P, (char **)(&dummy))) { + res = *dummy; + return(res); + } + + res = cuddZddCountDoubleStep(cuddE(P), table, base, empty) + + cuddZddCountDoubleStep(cuddT(P), table, base, empty); + + dummy = ALLOC(double, 1); + if (dummy == NULL) { + return((double)CUDD_OUT_OF_MEM); + } + *dummy = res; + if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) { + FREE(dummy); + return((double)CUDD_OUT_OF_MEM); + } + + return(res); + +} /* end of cuddZddCountDoubleStep */ + + +/**Function******************************************************************** + + Synopsis [Frees the memory associated with the computed table of + Cudd_zddCount.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static enum st_retval +st_zdd_countfree( + char * key, + char * value, + char * arg) +{ + int *d; + + d = (int *)value; + FREE(d); + return(ST_CONTINUE); + +} /* end of st_zdd_countfree */ + + +/**Function******************************************************************** + + Synopsis [Frees the memory associated with the computed table of + Cudd_zddCountDouble.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static enum st_retval +st_zdd_count_dbl_free( + char * key, + char * value, + char * arg) +{ + double *d; + + d = (double *)value; + FREE(d); + return(ST_CONTINUE); + +} /* end of st_zdd_count_dbl_free */ diff --git a/abc70930/src/bdd/cudd/cuddZddFuncs.c b/abc70930/src/bdd/cudd/cuddZddFuncs.c new file mode 100644 index 00000000..9dc27a95 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddZddFuncs.c @@ -0,0 +1,1603 @@ +/**CFile*********************************************************************** + + FileName [cuddZddFuncs.c] + + PackageName [cudd] + + Synopsis [Functions to manipulate covers represented as ZDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddProduct(); +
        • Cudd_zddUnateProduct(); +
        • Cudd_zddWeakDiv(); +
        • Cudd_zddWeakDivF(); +
        • Cudd_zddDivide(); +
        • Cudd_zddDivideF(); +
        • Cudd_zddComplement(); +
        + Internal procedures included in this module: +
          +
        • cuddZddProduct(); +
        • cuddZddUnateProduct(); +
        • cuddZddWeakDiv(); +
        • cuddZddWeakDivF(); +
        • cuddZddDivide(); +
        • cuddZddDivideF(); +
        • cuddZddGetCofactors3() +
        • cuddZddGetCofactors2() +
        • cuddZddComplement(); +
        • cuddZddGetPosVarIndex(); +
        • cuddZddGetNegVarIndex(); +
        • cuddZddGetPosVarLevel(); +
        • cuddZddGetNegVarLevel(); +
        + Static procedures included in this module: +
          +
        + ] + + SeeAlso [] + + Author [In-Ho Moon] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddFuncs.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes the product of two covers represented by ZDDs.] + + Description [Computes the product of two covers represented by + ZDDs. The result is also a ZDD. Returns a pointer to the result if + successful; NULL otherwise. The covers on which Cudd_zddProduct + operates use two ZDD variables for each function variable (one ZDD + variable for each literal of the variable). Those two ZDD variables + should be adjacent in the order.] + + SideEffects [None] + + SeeAlso [Cudd_zddUnateProduct] + +******************************************************************************/ +DdNode * +Cudd_zddProduct( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddZddProduct(dd, f, g); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_zddProduct */ + + +/**Function******************************************************************** + + Synopsis [Computes the product of two unate covers.] + + Description [Computes the product of two unate covers represented as + ZDDs. Unate covers use one ZDD variable for each BDD + variable. Returns a pointer to the result if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddProduct] + +******************************************************************************/ +DdNode * +Cudd_zddUnateProduct( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddZddUnateProduct(dd, f, g); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_zddUnateProduct */ + + +/**Function******************************************************************** + + Synopsis [Applies weak division to two covers.] + + Description [Applies weak division to two ZDDs representing two + covers. Returns a pointer to the ZDD representing the result if + successful; NULL otherwise. The result of weak division depends on + the variable order. The covers on which Cudd_zddWeakDiv operates use + two ZDD variables for each function variable (one ZDD variable for + each literal of the variable). Those two ZDD variables should be + adjacent in the order.] + + SideEffects [None] + + SeeAlso [Cudd_zddDivide] + +******************************************************************************/ +DdNode * +Cudd_zddWeakDiv( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddZddWeakDiv(dd, f, g); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_zddWeakDiv */ + + +/**Function******************************************************************** + + Synopsis [Computes the quotient of two unate covers.] + + Description [Computes the quotient of two unate covers represented + by ZDDs. Unate covers use one ZDD variable for each BDD + variable. Returns a pointer to the resulting ZDD if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddWeakDiv] + +******************************************************************************/ +DdNode * +Cudd_zddDivide( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddZddDivide(dd, f, g); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_zddDivide */ + + +/**Function******************************************************************** + + Synopsis [Modified version of Cudd_zddWeakDiv.] + + Description [Modified version of Cudd_zddWeakDiv. This function may + disappear in future releases.] + + SideEffects [None] + + SeeAlso [Cudd_zddWeakDiv] + +******************************************************************************/ +DdNode * +Cudd_zddWeakDivF( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddZddWeakDivF(dd, f, g); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_zddWeakDivF */ + + +/**Function******************************************************************** + + Synopsis [Modified version of Cudd_zddDivide.] + + Description [Modified version of Cudd_zddDivide. This function may + disappear in future releases.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_zddDivideF( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddZddDivideF(dd, f, g); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_zddDivideF */ + + +/**Function******************************************************************** + + Synopsis [Computes a complement cover for a ZDD node.] + + Description [Computes a complement cover for a ZDD node. For lack of a + better method, we first extract the function BDD from the ZDD cover, + then make the complement of the ZDD cover from the complement of the + BDD node by using ISOP. Returns a pointer to the resulting cover if + successful; NULL otherwise. The result depends on current variable + order.] + + SideEffects [The result depends on current variable order.] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_zddComplement( + DdManager *dd, + DdNode *node) +{ + DdNode *b, *isop, *zdd_I; + + /* Check cache */ + zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); + if (zdd_I) + return(zdd_I); + + b = Cudd_MakeBddFromZddCover(dd, node); + if (!b) + return(NULL); + Cudd_Ref(b); + isop = Cudd_zddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); + if (!isop) { + Cudd_RecursiveDeref(dd, b); + return(NULL); + } + Cudd_Ref(isop); + Cudd_Ref(zdd_I); + Cudd_RecursiveDeref(dd, b); + Cudd_RecursiveDeref(dd, isop); + + cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); + Cudd_Deref(zdd_I); + return(zdd_I); +} /* end of Cudd_zddComplement */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddProduct.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_zddProduct] + +******************************************************************************/ +DdNode * +cuddZddProduct( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + int v, top_f, top_g; + DdNode *tmp, *term1, *term2, *term3; + DdNode *f0, *f1, *fd, *g0, *g1, *gd; + DdNode *R0, *R1, *Rd, *N0, *N1; + DdNode *r; + DdNode *one = DD_ONE(dd); + DdNode *zero = DD_ZERO(dd); + int flag; + int pv, nv; + + statLine(dd); + if (f == zero || g == zero) + return(zero); + if (f == one) + return(g); + if (g == one) + return(f); + + top_f = dd->permZ[f->index]; + top_g = dd->permZ[g->index]; + + if (top_f > top_g) + return(cuddZddProduct(dd, g, f)); + + /* Check cache */ + r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g); + if (r) + return(r); + + v = f->index; /* either yi or zi */ + flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); + if (flag == 1) + return(NULL); + Cudd_Ref(f1); + Cudd_Ref(f0); + Cudd_Ref(fd); + flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); + if (flag == 1) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + return(NULL); + } + Cudd_Ref(g1); + Cudd_Ref(g0); + Cudd_Ref(gd); + pv = cuddZddGetPosVarIndex(dd, v); + nv = cuddZddGetNegVarIndex(dd, v); + + Rd = cuddZddProduct(dd, fd, gd); + if (Rd == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + Cudd_RecursiveDerefZdd(dd, gd); + return(NULL); + } + Cudd_Ref(Rd); + + term1 = cuddZddProduct(dd, f0, g0); + if (term1 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + Cudd_RecursiveDerefZdd(dd, gd); + Cudd_RecursiveDerefZdd(dd, Rd); + return(NULL); + } + Cudd_Ref(term1); + term2 = cuddZddProduct(dd, f0, gd); + if (term2 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + Cudd_RecursiveDerefZdd(dd, gd); + Cudd_RecursiveDerefZdd(dd, Rd); + Cudd_RecursiveDerefZdd(dd, term1); + return(NULL); + } + Cudd_Ref(term2); + term3 = cuddZddProduct(dd, fd, g0); + if (term3 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + Cudd_RecursiveDerefZdd(dd, gd); + Cudd_RecursiveDerefZdd(dd, Rd); + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term2); + return(NULL); + } + Cudd_Ref(term3); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g0); + tmp = cuddZddUnion(dd, term1, term2); + if (tmp == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, gd); + Cudd_RecursiveDerefZdd(dd, Rd); + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term2); + Cudd_RecursiveDerefZdd(dd, term3); + return(NULL); + } + Cudd_Ref(tmp); + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term2); + R0 = cuddZddUnion(dd, tmp, term3); + if (R0 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, gd); + Cudd_RecursiveDerefZdd(dd, Rd); + Cudd_RecursiveDerefZdd(dd, term3); + Cudd_RecursiveDerefZdd(dd, tmp); + return(NULL); + } + Cudd_Ref(R0); + Cudd_RecursiveDerefZdd(dd, tmp); + Cudd_RecursiveDerefZdd(dd, term3); + N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */ + if (N0 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, gd); + Cudd_RecursiveDerefZdd(dd, Rd); + Cudd_RecursiveDerefZdd(dd, R0); + return(NULL); + } + Cudd_Ref(N0); + Cudd_RecursiveDerefZdd(dd, R0); + Cudd_RecursiveDerefZdd(dd, Rd); + + term1 = cuddZddProduct(dd, f1, g1); + if (term1 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, gd); + Cudd_RecursiveDerefZdd(dd, N0); + return(NULL); + } + Cudd_Ref(term1); + term2 = cuddZddProduct(dd, f1, gd); + if (term2 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, gd); + Cudd_RecursiveDerefZdd(dd, N0); + Cudd_RecursiveDerefZdd(dd, term1); + return(NULL); + } + Cudd_Ref(term2); + term3 = cuddZddProduct(dd, fd, g1); + if (term3 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, gd); + Cudd_RecursiveDerefZdd(dd, N0); + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term2); + return(NULL); + } + Cudd_Ref(term3); + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + tmp = cuddZddUnion(dd, term1, term2); + if (tmp == NULL) { + Cudd_RecursiveDerefZdd(dd, N0); + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term2); + Cudd_RecursiveDerefZdd(dd, term3); + return(NULL); + } + Cudd_Ref(tmp); + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term2); + R1 = cuddZddUnion(dd, tmp, term3); + if (R1 == NULL) { + Cudd_RecursiveDerefZdd(dd, N0); + Cudd_RecursiveDerefZdd(dd, term3); + Cudd_RecursiveDerefZdd(dd, tmp); + return(NULL); + } + Cudd_Ref(R1); + Cudd_RecursiveDerefZdd(dd, tmp); + Cudd_RecursiveDerefZdd(dd, term3); + N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */ + if (N1 == NULL) { + Cudd_RecursiveDerefZdd(dd, N0); + Cudd_RecursiveDerefZdd(dd, R1); + return(NULL); + } + Cudd_Ref(N1); + Cudd_RecursiveDerefZdd(dd, R1); + Cudd_RecursiveDerefZdd(dd, N0); + + cuddCacheInsert2(dd, cuddZddProduct, f, g, N1); + Cudd_Deref(N1); + return(N1); + +} /* end of cuddZddProduct */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddUnateProduct.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_zddUnateProduct] + +******************************************************************************/ +DdNode * +cuddZddUnateProduct( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + int v, top_f, top_g; + DdNode *term1, *term2, *term3, *term4; + DdNode *sum1, *sum2; + DdNode *f0, *f1, *g0, *g1; + DdNode *r; + DdNode *one = DD_ONE(dd); + DdNode *zero = DD_ZERO(dd); + int flag; + + statLine(dd); + if (f == zero || g == zero) + return(zero); + if (f == one) + return(g); + if (g == one) + return(f); + + top_f = dd->permZ[f->index]; + top_g = dd->permZ[g->index]; + + if (top_f > top_g) + return(cuddZddUnateProduct(dd, g, f)); + + /* Check cache */ + r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g); + if (r) + return(r); + + v = f->index; /* either yi or zi */ + flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); + if (flag == 1) + return(NULL); + Cudd_Ref(f1); + Cudd_Ref(f0); + flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); + if (flag == 1) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + return(NULL); + } + Cudd_Ref(g1); + Cudd_Ref(g0); + + term1 = cuddZddUnateProduct(dd, f1, g1); + if (term1 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + return(NULL); + } + Cudd_Ref(term1); + term2 = cuddZddUnateProduct(dd, f1, g0); + if (term2 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + Cudd_RecursiveDerefZdd(dd, term1); + return(NULL); + } + Cudd_Ref(term2); + term3 = cuddZddUnateProduct(dd, f0, g1); + if (term3 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term2); + return(NULL); + } + Cudd_Ref(term3); + term4 = cuddZddUnateProduct(dd, f0, g0); + if (term4 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term2); + Cudd_RecursiveDerefZdd(dd, term3); + return(NULL); + } + Cudd_Ref(term4); + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + sum1 = cuddZddUnion(dd, term1, term2); + if (sum1 == NULL) { + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term2); + Cudd_RecursiveDerefZdd(dd, term3); + Cudd_RecursiveDerefZdd(dd, term4); + return(NULL); + } + Cudd_Ref(sum1); + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term2); + sum2 = cuddZddUnion(dd, sum1, term3); + if (sum2 == NULL) { + Cudd_RecursiveDerefZdd(dd, term3); + Cudd_RecursiveDerefZdd(dd, term4); + Cudd_RecursiveDerefZdd(dd, sum1); + return(NULL); + } + Cudd_Ref(sum2); + Cudd_RecursiveDerefZdd(dd, sum1); + Cudd_RecursiveDerefZdd(dd, term3); + r = cuddZddGetNode(dd, v, sum2, term4); + if (r == NULL) { + Cudd_RecursiveDerefZdd(dd, term4); + Cudd_RecursiveDerefZdd(dd, sum2); + return(NULL); + } + Cudd_Ref(r); + Cudd_RecursiveDerefZdd(dd, sum2); + Cudd_RecursiveDerefZdd(dd, term4); + + cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r); + Cudd_Deref(r); + return(r); + +} /* end of cuddZddUnateProduct */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddWeakDiv.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_zddWeakDiv] + +******************************************************************************/ +DdNode * +cuddZddWeakDiv( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + int v; + DdNode *one = DD_ONE(dd); + DdNode *zero = DD_ZERO(dd); + DdNode *f0, *f1, *fd, *g0, *g1, *gd; + DdNode *q, *tmp; + DdNode *r; + int flag; + + statLine(dd); + if (g == one) + return(f); + if (f == zero || f == one) + return(zero); + if (f == g) + return(one); + + /* Check cache. */ + r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g); + if (r) + return(r); + + v = g->index; + + flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); + if (flag == 1) + return(NULL); + Cudd_Ref(f1); + Cudd_Ref(f0); + Cudd_Ref(fd); + flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); + if (flag == 1) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + return(NULL); + } + Cudd_Ref(g1); + Cudd_Ref(g0); + Cudd_Ref(gd); + + q = g; + + if (g0 != zero) { + q = cuddZddWeakDiv(dd, f0, g0); + if (q == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + Cudd_RecursiveDerefZdd(dd, gd); + return(NULL); + } + Cudd_Ref(q); + } + else + Cudd_Ref(q); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g0); + + if (q == zero) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); + Cudd_Deref(q); + return(zero); + } + + if (g1 != zero) { + Cudd_RecursiveDerefZdd(dd, q); + tmp = cuddZddWeakDiv(dd, f1, g1); + if (tmp == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + return(NULL); + } + Cudd_Ref(tmp); + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, g1); + if (q == g) + q = tmp; + else { + q = cuddZddIntersect(dd, q, tmp); + if (q == NULL) { + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + return(NULL); + } + Cudd_Ref(q); + Cudd_RecursiveDerefZdd(dd, tmp); + } + } + else { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, g1); + } + + if (q == zero) { + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); + Cudd_Deref(q); + return(zero); + } + + if (gd != zero) { + Cudd_RecursiveDerefZdd(dd, q); + tmp = cuddZddWeakDiv(dd, fd, gd); + if (tmp == NULL) { + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + return(NULL); + } + Cudd_Ref(tmp); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + if (q == g) + q = tmp; + else { + q = cuddZddIntersect(dd, q, tmp); + if (q == NULL) { + Cudd_RecursiveDerefZdd(dd, tmp); + return(NULL); + } + Cudd_Ref(q); + Cudd_RecursiveDerefZdd(dd, tmp); + } + } + else { + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + } + + cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q); + Cudd_Deref(q); + return(q); + +} /* end of cuddZddWeakDiv */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddWeakDivF.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_zddWeakDivF] + +******************************************************************************/ +DdNode * +cuddZddWeakDivF( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + int v, top_f, top_g, vf, vg; + DdNode *one = DD_ONE(dd); + DdNode *zero = DD_ZERO(dd); + DdNode *f0, *f1, *fd, *g0, *g1, *gd; + DdNode *q, *tmp; + DdNode *r; + DdNode *term1, *term0, *termd; + int flag; + int pv, nv; + + statLine(dd); + if (g == one) + return(f); + if (f == zero || f == one) + return(zero); + if (f == g) + return(one); + + /* Check cache. */ + r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g); + if (r) + return(r); + + top_f = dd->permZ[f->index]; + top_g = dd->permZ[g->index]; + vf = top_f >> 1; + vg = top_g >> 1; + v = ddMin(top_f, top_g); + + if (v == top_f && vf < vg) { + v = f->index; + flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); + if (flag == 1) + return(NULL); + Cudd_Ref(f1); + Cudd_Ref(f0); + Cudd_Ref(fd); + + pv = cuddZddGetPosVarIndex(dd, v); + nv = cuddZddGetNegVarIndex(dd, v); + + term1 = cuddZddWeakDivF(dd, f1, g); + if (term1 == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + return(NULL); + } + Cudd_Ref(term1); + Cudd_RecursiveDerefZdd(dd, f1); + term0 = cuddZddWeakDivF(dd, f0, g); + if (term0 == NULL) { + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, term1); + return(NULL); + } + Cudd_Ref(term0); + Cudd_RecursiveDerefZdd(dd, f0); + termd = cuddZddWeakDivF(dd, fd, g); + if (termd == NULL) { + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term0); + return(NULL); + } + Cudd_Ref(termd); + Cudd_RecursiveDerefZdd(dd, fd); + + tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */ + if (tmp == NULL) { + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, term0); + Cudd_RecursiveDerefZdd(dd, termd); + return(NULL); + } + Cudd_Ref(tmp); + Cudd_RecursiveDerefZdd(dd, term0); + Cudd_RecursiveDerefZdd(dd, termd); + q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */ + if (q == NULL) { + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, tmp); + return(NULL); + } + Cudd_Ref(q); + Cudd_RecursiveDerefZdd(dd, term1); + Cudd_RecursiveDerefZdd(dd, tmp); + + cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); + Cudd_Deref(q); + return(q); + } + + if (v == top_f) + v = f->index; + else + v = g->index; + + flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); + if (flag == 1) + return(NULL); + Cudd_Ref(f1); + Cudd_Ref(f0); + Cudd_Ref(fd); + flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); + if (flag == 1) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + return(NULL); + } + Cudd_Ref(g1); + Cudd_Ref(g0); + Cudd_Ref(gd); + + q = g; + + if (g0 != zero) { + q = cuddZddWeakDivF(dd, f0, g0); + if (q == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + Cudd_RecursiveDerefZdd(dd, gd); + return(NULL); + } + Cudd_Ref(q); + } + else + Cudd_Ref(q); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g0); + + if (q == zero) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); + Cudd_Deref(q); + return(zero); + } + + if (g1 != zero) { + Cudd_RecursiveDerefZdd(dd, q); + tmp = cuddZddWeakDivF(dd, f1, g1); + if (tmp == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + return(NULL); + } + Cudd_Ref(tmp); + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, g1); + if (q == g) + q = tmp; + else { + q = cuddZddIntersect(dd, q, tmp); + if (q == NULL) { + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + return(NULL); + } + Cudd_Ref(q); + Cudd_RecursiveDerefZdd(dd, tmp); + } + } + else { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, g1); + } + + if (q == zero) { + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); + Cudd_Deref(q); + return(zero); + } + + if (gd != zero) { + Cudd_RecursiveDerefZdd(dd, q); + tmp = cuddZddWeakDivF(dd, fd, gd); + if (tmp == NULL) { + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + return(NULL); + } + Cudd_Ref(tmp); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + if (q == g) + q = tmp; + else { + q = cuddZddIntersect(dd, q, tmp); + if (q == NULL) { + Cudd_RecursiveDerefZdd(dd, tmp); + return(NULL); + } + Cudd_Ref(q); + Cudd_RecursiveDerefZdd(dd, tmp); + } + } + else { + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDerefZdd(dd, gd); + } + + cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); + Cudd_Deref(q); + return(q); + +} /* end of cuddZddWeakDivF */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddDivide.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_zddDivide] + +******************************************************************************/ +DdNode * +cuddZddDivide( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + int v; + DdNode *one = DD_ONE(dd); + DdNode *zero = DD_ZERO(dd); + DdNode *f0, *f1, *g0, *g1; + DdNode *q, *r, *tmp; + int flag; + + statLine(dd); + if (g == one) + return(f); + if (f == zero || f == one) + return(zero); + if (f == g) + return(one); + + /* Check cache. */ + r = cuddCacheLookup2Zdd(dd, cuddZddDivide, f, g); + if (r) + return(r); + + v = g->index; + + flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); + if (flag == 1) + return(NULL); + Cudd_Ref(f1); + Cudd_Ref(f0); + flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */ + if (flag == 1) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + return(NULL); + } + Cudd_Ref(g1); + Cudd_Ref(g0); + + r = cuddZddDivide(dd, f1, g1); + if (r == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + return(NULL); + } + Cudd_Ref(r); + + if (r != zero && g0 != zero) { + tmp = r; + q = cuddZddDivide(dd, f0, g0); + if (q == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + return(NULL); + } + Cudd_Ref(q); + r = cuddZddIntersect(dd, r, q); + if (r == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + Cudd_RecursiveDerefZdd(dd, q); + return(NULL); + } + Cudd_Ref(r); + Cudd_RecursiveDerefZdd(dd, q); + Cudd_RecursiveDerefZdd(dd, tmp); + } + + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + + cuddCacheInsert2(dd, cuddZddDivide, f, g, r); + Cudd_Deref(r); + return(r); + +} /* end of cuddZddDivide */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddDivideF.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_zddDivideF] + +******************************************************************************/ +DdNode * +cuddZddDivideF( + DdManager * dd, + DdNode * f, + DdNode * g) +{ + int v; + DdNode *one = DD_ONE(dd); + DdNode *zero = DD_ZERO(dd); + DdNode *f0, *f1, *g0, *g1; + DdNode *q, *r, *tmp; + int flag; + + statLine(dd); + if (g == one) + return(f); + if (f == zero || f == one) + return(zero); + if (f == g) + return(one); + + /* Check cache. */ + r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g); + if (r) + return(r); + + v = g->index; + + flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); + if (flag == 1) + return(NULL); + Cudd_Ref(f1); + Cudd_Ref(f0); + flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */ + if (flag == 1) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + return(NULL); + } + Cudd_Ref(g1); + Cudd_Ref(g0); + + r = cuddZddDivideF(dd, f1, g1); + if (r == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + return(NULL); + } + Cudd_Ref(r); + + if (r != zero && g0 != zero) { + tmp = r; + q = cuddZddDivideF(dd, f0, g0); + if (q == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + return(NULL); + } + Cudd_Ref(q); + r = cuddZddIntersect(dd, r, q); + if (r == NULL) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + Cudd_RecursiveDerefZdd(dd, q); + return(NULL); + } + Cudd_Ref(r); + Cudd_RecursiveDerefZdd(dd, q); + Cudd_RecursiveDerefZdd(dd, tmp); + } + + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, g1); + Cudd_RecursiveDerefZdd(dd, g0); + + cuddCacheInsert2(dd, cuddZddDivideF, f, g, r); + Cudd_Deref(r); + return(r); + +} /* end of cuddZddDivideF */ + + +/**Function******************************************************************** + + Synopsis [Computes the three-way decomposition of f w.r.t. v.] + + Description [Computes the three-way decomposition of function f (represented + by a ZDD) wit respect to variable v.] + + SideEffects [The results are returned in f1, f0, and fd.] + + SeeAlso [cuddZddGetCofactors2] + +******************************************************************************/ +int +cuddZddGetCofactors3( + DdManager * dd, + DdNode * f, + int v, + DdNode ** f1, + DdNode ** f0, + DdNode ** fd) +{ + DdNode *pc, *nc; + DdNode *zero = DD_ZERO(dd); + int top, hv, ht, pv, nv; + int level; + + top = dd->permZ[f->index]; + level = dd->permZ[v]; + hv = level >> 1; + ht = top >> 1; + + if (hv < ht) { + *f1 = zero; + *f0 = zero; + *fd = f; + } + else { + pv = cuddZddGetPosVarIndex(dd, v); + nv = cuddZddGetNegVarIndex(dd, v); + + /* not to create intermediate ZDD node */ + if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) { + pc = cuddZddSubset1(dd, f, pv); + if (pc == NULL) + return(1); + Cudd_Ref(pc); + nc = cuddZddSubset0(dd, f, pv); + if (nc == NULL) { + Cudd_RecursiveDerefZdd(dd, pc); + return(1); + } + Cudd_Ref(nc); + + *f1 = cuddZddSubset0(dd, pc, nv); + if (*f1 == NULL) { + Cudd_RecursiveDerefZdd(dd, pc); + Cudd_RecursiveDerefZdd(dd, nc); + return(1); + } + Cudd_Ref(*f1); + *f0 = cuddZddSubset1(dd, nc, nv); + if (*f0 == NULL) { + Cudd_RecursiveDerefZdd(dd, pc); + Cudd_RecursiveDerefZdd(dd, nc); + Cudd_RecursiveDerefZdd(dd, *f1); + return(1); + } + Cudd_Ref(*f0); + + *fd = cuddZddSubset0(dd, nc, nv); + if (*fd == NULL) { + Cudd_RecursiveDerefZdd(dd, pc); + Cudd_RecursiveDerefZdd(dd, nc); + Cudd_RecursiveDerefZdd(dd, *f1); + Cudd_RecursiveDerefZdd(dd, *f0); + return(1); + } + Cudd_Ref(*fd); + } else { + pc = cuddZddSubset1(dd, f, nv); + if (pc == NULL) + return(1); + Cudd_Ref(pc); + nc = cuddZddSubset0(dd, f, nv); + if (nc == NULL) { + Cudd_RecursiveDerefZdd(dd, pc); + return(1); + } + Cudd_Ref(nc); + + *f0 = cuddZddSubset0(dd, pc, pv); + if (*f0 == NULL) { + Cudd_RecursiveDerefZdd(dd, pc); + Cudd_RecursiveDerefZdd(dd, nc); + return(1); + } + Cudd_Ref(*f0); + *f1 = cuddZddSubset1(dd, nc, pv); + if (*f1 == NULL) { + Cudd_RecursiveDerefZdd(dd, pc); + Cudd_RecursiveDerefZdd(dd, nc); + Cudd_RecursiveDerefZdd(dd, *f1); + return(1); + } + Cudd_Ref(*f1); + + *fd = cuddZddSubset0(dd, nc, pv); + if (*fd == NULL) { + Cudd_RecursiveDerefZdd(dd, pc); + Cudd_RecursiveDerefZdd(dd, nc); + Cudd_RecursiveDerefZdd(dd, *f1); + Cudd_RecursiveDerefZdd(dd, *f0); + return(1); + } + Cudd_Ref(*fd); + } + + Cudd_RecursiveDerefZdd(dd, pc); + Cudd_RecursiveDerefZdd(dd, nc); + Cudd_Deref(*f1); + Cudd_Deref(*f0); + Cudd_Deref(*fd); + } + return(0); + +} /* end of cuddZddGetCofactors3 */ + + +/**Function******************************************************************** + + Synopsis [Computes the two-way decomposition of f w.r.t. v.] + + Description [] + + SideEffects [The results are returned in f1 and f0.] + + SeeAlso [cuddZddGetCofactors3] + +******************************************************************************/ +int +cuddZddGetCofactors2( + DdManager * dd, + DdNode * f, + int v, + DdNode ** f1, + DdNode ** f0) +{ + *f1 = cuddZddSubset1(dd, f, v); + if (*f1 == NULL) + return(1); + *f0 = cuddZddSubset0(dd, f, v); + if (*f0 == NULL) { + Cudd_RecursiveDerefZdd(dd, *f1); + return(1); + } + return(0); + +} /* end of cuddZddGetCofactors2 */ + + +/**Function******************************************************************** + + Synopsis [Computes a complement of a ZDD node.] + + Description [Computes the complement of a ZDD node. So far, since we + couldn't find a direct way to get the complement of a ZDD cover, we first + convert a ZDD cover to a BDD, then make the complement of the ZDD cover + from the complement of the BDD node by using ISOP.] + + SideEffects [The result depends on current variable order.] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddZddComplement( + DdManager * dd, + DdNode *node) +{ + DdNode *b, *isop, *zdd_I; + + /* Check cache */ + zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); + if (zdd_I) + return(zdd_I); + + b = cuddMakeBddFromZddCover(dd, node); + if (!b) + return(NULL); + cuddRef(b); + isop = cuddZddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); + if (!isop) { + Cudd_RecursiveDeref(dd, b); + return(NULL); + } + cuddRef(isop); + cuddRef(zdd_I); + Cudd_RecursiveDeref(dd, b); + Cudd_RecursiveDeref(dd, isop); + + cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); + cuddDeref(zdd_I); + return(zdd_I); +} /* end of cuddZddComplement */ + + +/**Function******************************************************************** + + Synopsis [Returns the index of positive ZDD variable.] + + Description [Returns the index of positive ZDD variable.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddGetPosVarIndex( + DdManager * dd, + int index) +{ + int pv = (index >> 1) << 1; + return(pv); +} /* end of cuddZddGetPosVarIndex */ + + +/**Function******************************************************************** + + Synopsis [Returns the index of negative ZDD variable.] + + Description [Returns the index of negative ZDD variable.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddGetNegVarIndex( + DdManager * dd, + int index) +{ + int nv = index | 0x1; + return(nv); +} /* end of cuddZddGetPosVarIndex */ + + +/**Function******************************************************************** + + Synopsis [Returns the level of positive ZDD variable.] + + Description [Returns the level of positive ZDD variable.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddGetPosVarLevel( + DdManager * dd, + int index) +{ + int pv = cuddZddGetPosVarIndex(dd, index); + return(dd->permZ[pv]); +} /* end of cuddZddGetPosVarLevel */ + + +/**Function******************************************************************** + + Synopsis [Returns the level of negative ZDD variable.] + + Description [Returns the level of negative ZDD variable.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddGetNegVarLevel( + DdManager * dd, + int index) +{ + int nv = cuddZddGetNegVarIndex(dd, index); + return(dd->permZ[nv]); +} /* end of cuddZddGetNegVarLevel */ diff --git a/abc70930/src/bdd/cudd/cuddZddGroup.c b/abc70930/src/bdd/cudd/cuddZddGroup.c new file mode 100644 index 00000000..621fa43f --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddZddGroup.c @@ -0,0 +1,1317 @@ +/**CFile*********************************************************************** + + FileName [cuddZddGroup.c] + + PackageName [cudd] + + Synopsis [Functions for ZDD group sifting.] + + Description [External procedures included in this file: +
          +
        • Cudd_MakeZddTreeNode() +
        + Internal procedures included in this file: +
          +
        • cuddZddTreeSifting() +
        + Static procedures included in this module: +
          +
        • zddTreeSiftingAux() +
        • zddCountInternalMtrNodes() +
        • zddReorderChildren() +
        • zddFindNodeHiLo() +
        • zddUniqueCompareGroup() +
        • zddGroupSifting() +
        • zddGroupSiftingAux() +
        • zddGroupSiftingUp() +
        • zddGroupSiftingDown() +
        • zddGroupMove() +
        • zddGroupMoveBackward() +
        • zddGroupSiftingBackward() +
        • zddMergeGroups() +
        ] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; +#endif + +static int *entry; +extern int zddTotalNumberSwapping; +#ifdef DD_STATS +static int extsymmcalls; +static int extsymm; +static int secdiffcalls; +static int secdiff; +static int secdiffmisfire; +#endif +#ifdef DD_DEBUG +static int pr = 0; /* flag to enable printing while debugging */ + /* by depositing a 1 into it */ +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int zddTreeSiftingAux ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); +#ifdef DD_STATS +static int zddCountInternalMtrNodes ARGS((DdManager *table, MtrNode *treenode)); +#endif +static int zddReorderChildren ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); +static void zddFindNodeHiLo ARGS((DdManager *table, MtrNode *treenode, int *lower, int *upper)); +static int zddUniqueCompareGroup ARGS((int *ptrX, int *ptrY)); +static int zddGroupSifting ARGS((DdManager *table, int lower, int upper)); +static int zddGroupSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); +static int zddGroupSiftingUp ARGS((DdManager *table, int y, int xLow, Move **moves)); +static int zddGroupSiftingDown ARGS((DdManager *table, int x, int xHigh, Move **moves)); +static int zddGroupMove ARGS((DdManager *table, int x, int y, Move **moves)); +static int zddGroupMoveBackward ARGS((DdManager *table, int x, int y)); +static int zddGroupSiftingBackward ARGS((DdManager *table, Move *moves, int size)); +static void zddMergeGroups ARGS((DdManager *table, MtrNode *treenode, int low, int high)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Creates a new ZDD variable group.] + + Description [Creates a new ZDD variable group. The group starts at + variable and contains size variables. The parameter low is the index + of the first variable. If the variable already exists, its current + position in the order is known to the manager. If the variable does + not exist yet, the position is assumed to be the same as the index. + The group tree is created if it does not exist yet. + Returns a pointer to the group if successful; NULL otherwise.] + + SideEffects [The ZDD variable tree is changed.] + + SeeAlso [Cudd_MakeTreeNode] + +******************************************************************************/ +MtrNode * +Cudd_MakeZddTreeNode( + DdManager * dd /* manager */, + unsigned int low /* index of the first group variable */, + unsigned int size /* number of variables in the group */, + unsigned int type /* MTR_DEFAULT or MTR_FIXED */) +{ + MtrNode *group; + MtrNode *tree; + unsigned int level; + + /* If the variable does not exist yet, the position is assumed to be + ** the same as the index. Therefore, applications that rely on + ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new + ** variables have to create the variables before they group them. + */ + level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low; + + if (level + size - 1> (int) MTR_MAXHIGH) + return(NULL); + + /* If the tree does not exist yet, create it. */ + tree = dd->treeZ; + if (tree == NULL) { + dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ); + if (tree == NULL) + return(NULL); + tree->index = dd->invpermZ[0]; + } + + /* Extend the upper bound of the tree if necessary. This allows the + ** application to create groups even before the variables are created. + */ + tree->size = ddMax(tree->size, level + size); + + /* Create the group. */ + group = Mtr_MakeGroup(tree, level, size, type); + if (group == NULL) + return(NULL); + + /* Initialize the index field to the index of the variable currently + ** in position low. This field will be updated by the reordering + ** procedure to provide a handle to the group once it has been moved. + */ + group->index = (MtrHalfWord) low; + + return(group); + +} /* end of Cudd_MakeZddTreeNode */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Tree sifting algorithm for ZDDs.] + + Description [Tree sifting algorithm for ZDDs. Assumes that a tree + representing a group hierarchy is passed as a parameter. It then + reorders each group in postorder fashion by calling + zddTreeSiftingAux. Assumes that no dead nodes are present. Returns + 1 if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +int +cuddZddTreeSifting( + DdManager * table /* DD table */, + Cudd_ReorderingType method /* reordering method for the groups of leaves */) +{ + int i; + int nvars; + int result; + int tempTree; + + /* If no tree is provided we create a temporary one in which all + ** variables are in a single group. After reordering this tree is + ** destroyed. + */ + tempTree = table->treeZ == NULL; + if (tempTree) { + table->treeZ = Mtr_InitGroupTree(0,table->sizeZ); + table->treeZ->index = table->invpermZ[0]; + } + nvars = table->sizeZ; + +#ifdef DD_DEBUG + if (pr > 0 && !tempTree) + (void) fprintf(table->out,"cuddZddTreeSifting:"); + Mtr_PrintGroups(table->treeZ,pr <= 0); +#endif +#if 0 + /* Debugging code. */ + if (table->tree && table->treeZ) { + (void) fprintf(table->out,"\n"); + Mtr_PrintGroups(table->tree, 0); + cuddPrintVarGroups(table,table->tree,0,0); + for (i = 0; i < table->size; i++) { + (void) fprintf(table->out,"%s%d", + (i == 0) ? "" : ",", table->invperm[i]); + } + (void) fprintf(table->out,"\n"); + for (i = 0; i < table->size; i++) { + (void) fprintf(table->out,"%s%d", + (i == 0) ? "" : ",", table->perm[i]); + } + (void) fprintf(table->out,"\n\n"); + Mtr_PrintGroups(table->treeZ,0); + cuddPrintVarGroups(table,table->treeZ,1,0); + for (i = 0; i < table->sizeZ; i++) { + (void) fprintf(table->out,"%s%d", + (i == 0) ? "" : ",", table->invpermZ[i]); + } + (void) fprintf(table->out,"\n"); + for (i = 0; i < table->sizeZ; i++) { + (void) fprintf(table->out,"%s%d", + (i == 0) ? "" : ",", table->permZ[i]); + } + (void) fprintf(table->out,"\n"); + } + /* End of debugging code. */ +#endif +#ifdef DD_STATS + extsymmcalls = 0; + extsymm = 0; + secdiffcalls = 0; + secdiff = 0; + secdiffmisfire = 0; + + (void) fprintf(table->out,"\n"); + if (!tempTree) + (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", + zddCountInternalMtrNodes(table,table->treeZ)); +#endif + + /* Initialize the group of each subtable to itself. Initially + ** there are no groups. Groups are created according to the tree + ** structure in postorder fashion. + */ + for (i = 0; i < nvars; i++) + table->subtableZ[i].next = i; + + /* Reorder. */ + result = zddTreeSiftingAux(table, table->treeZ, method); + +#ifdef DD_STATS /* print stats */ + if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && + (table->groupcheck == CUDD_GROUP_CHECK7 || + table->groupcheck == CUDD_GROUP_CHECK5)) { + (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); + (void) fprintf(table->out,"extsymm = %d",extsymm); + } + if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && + table->groupcheck == CUDD_GROUP_CHECK7) { + (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); + (void) fprintf(table->out,"secdiff = %d\n",secdiff); + (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); + } +#endif + + if (tempTree) + Cudd_FreeZddTree(table); + return(result); + +} /* end of cuddZddTreeSifting */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Visits the group tree and reorders each group.] + + Description [Recursively visits the group tree and reorders each + group in postorder fashion. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +zddTreeSiftingAux( + DdManager * table, + MtrNode * treenode, + Cudd_ReorderingType method) +{ + MtrNode *auxnode; + int res; + +#ifdef DD_DEBUG + Mtr_PrintGroups(treenode,1); +#endif + + auxnode = treenode; + while (auxnode != NULL) { + if (auxnode->child != NULL) { + if (!zddTreeSiftingAux(table, auxnode->child, method)) + return(0); + res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT); + if (res == 0) + return(0); + } else if (auxnode->size > 1) { + if (!zddReorderChildren(table, auxnode, method)) + return(0); + } + auxnode = auxnode->younger; + } + + return(1); + +} /* end of zddTreeSiftingAux */ + + +#ifdef DD_STATS +/**Function******************************************************************** + + Synopsis [Counts the number of internal nodes of the group tree.] + + Description [Counts the number of internal nodes of the group tree. + Returns the count.] + + SideEffects [None] + +******************************************************************************/ +static int +zddCountInternalMtrNodes( + DdManager * table, + MtrNode * treenode) +{ + MtrNode *auxnode; + int count,nodeCount; + + + nodeCount = 0; + auxnode = treenode; + while (auxnode != NULL) { + if (!(MTR_TEST(auxnode,MTR_TERMINAL))) { + nodeCount++; + count = zddCountInternalMtrNodes(table,auxnode->child); + nodeCount += count; + } + auxnode = auxnode->younger; + } + + return(nodeCount); + +} /* end of zddCountInternalMtrNodes */ +#endif + + +/**Function******************************************************************** + + Synopsis [Reorders the children of a group tree node according to + the options.] + + Description [Reorders the children of a group tree node according to + the options. After reordering puts all the variables in the group + and/or its descendents in a single group. This allows hierarchical + reordering. If the variables in the group do not exist yet, simply + does nothing. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +zddReorderChildren( + DdManager * table, + MtrNode * treenode, + Cudd_ReorderingType method) +{ + int lower; + int upper; + int result; + unsigned int initialSize; + + zddFindNodeHiLo(table,treenode,&lower,&upper); + /* If upper == -1 these variables do not exist yet. */ + if (upper == -1) + return(1); + + if (treenode->flags == MTR_FIXED) { + result = 1; + } else { +#ifdef DD_STATS + (void) fprintf(table->out," "); +#endif + switch (method) { + case CUDD_REORDER_RANDOM: + case CUDD_REORDER_RANDOM_PIVOT: + result = cuddZddSwapping(table,lower,upper,method); + break; + case CUDD_REORDER_SIFT: + result = cuddZddSifting(table,lower,upper); + break; + case CUDD_REORDER_SIFT_CONVERGE: + do { + initialSize = table->keysZ; + result = cuddZddSifting(table,lower,upper); + if (initialSize <= table->keysZ) + break; +#ifdef DD_STATS + else + (void) fprintf(table->out,"\n"); +#endif + } while (result != 0); + break; + case CUDD_REORDER_SYMM_SIFT: + result = cuddZddSymmSifting(table,lower,upper); + break; + case CUDD_REORDER_SYMM_SIFT_CONV: + result = cuddZddSymmSiftingConv(table,lower,upper); + break; + case CUDD_REORDER_GROUP_SIFT: + result = zddGroupSifting(table,lower,upper); + break; + case CUDD_REORDER_LINEAR: + result = cuddZddLinearSifting(table,lower,upper); + break; + case CUDD_REORDER_LINEAR_CONVERGE: + do { + initialSize = table->keysZ; + result = cuddZddLinearSifting(table,lower,upper); + if (initialSize <= table->keysZ) + break; +#ifdef DD_STATS + else + (void) fprintf(table->out,"\n"); +#endif + } while (result != 0); + break; + default: + return(0); + } + } + + /* Create a single group for all the variables that were sifted, + ** so that they will be treated as a single block by successive + ** invocations of zddGroupSifting. + */ + zddMergeGroups(table,treenode,lower,upper); + +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:"); +#endif + + return(result); + +} /* end of zddReorderChildren */ + + +/**Function******************************************************************** + + Synopsis [Finds the lower and upper bounds of the group represented + by treenode.] + + Description [Finds the lower and upper bounds of the group represented + by treenode. The high and low fields of treenode are indices. From + those we need to derive the current positions, and find maximum and + minimum.] + + SideEffects [The bounds are returned as side effects.] + + SeeAlso [] + +******************************************************************************/ +static void +zddFindNodeHiLo( + DdManager * table, + MtrNode * treenode, + int * lower, + int * upper) +{ + int low; + int high; + + /* Check whether no variables in this group already exist. + ** If so, return immediately. The calling procedure will know from + ** the values of upper that no reordering is needed. + */ + if ((int) treenode->low >= table->sizeZ) { + *lower = table->sizeZ; + *upper = -1; + return; + } + + *lower = low = (unsigned int) table->permZ[treenode->index]; + high = (int) (low + treenode->size - 1); + + if (high >= table->sizeZ) { + /* This is the case of a partially existing group. The aim is to + ** reorder as many variables as safely possible. If the tree + ** node is terminal, we just reorder the subset of the group + ** that is currently in existence. If the group has + ** subgroups, then we only reorder those subgroups that are + ** fully instantiated. This way we avoid breaking up a group. + */ + MtrNode *auxnode = treenode->child; + if (auxnode == NULL) { + *upper = (unsigned int) table->sizeZ - 1; + } else { + /* Search the subgroup that strands the table->sizeZ line. + ** If the first group starts at 0 and goes past table->sizeZ + ** upper will get -1, thus correctly signaling that no reordering + ** should take place. + */ + while (auxnode != NULL) { + int thisLower = table->permZ[auxnode->low]; + int thisUpper = thisLower + auxnode->size - 1; + if (thisUpper >= table->sizeZ && thisLower < table->sizeZ) + *upper = (unsigned int) thisLower - 1; + auxnode = auxnode->younger; + } + } + } else { + /* Normal case: All the variables of the group exist. */ + *upper = (unsigned int) high; + } + +#ifdef DD_DEBUG + /* Make sure that all variables in group are contiguous. */ + assert(treenode->size >= *upper - *lower + 1); +#endif + + return; + +} /* end of zddFindNodeHiLo */ + + +/**Function******************************************************************** + + Synopsis [Comparison function used by qsort.] + + Description [Comparison function used by qsort to order the variables + according to the number of keys in the subtables. Returns the + difference in number of keys between the two variables being + compared.] + + SideEffects [None] + +******************************************************************************/ +static int +zddUniqueCompareGroup( + int * ptrX, + int * ptrY) +{ +#if 0 + if (entry[*ptrY] == entry[*ptrX]) { + return((*ptrX) - (*ptrY)); + } +#endif + return(entry[*ptrY] - entry[*ptrX]); + +} /* end of zddUniqueCompareGroup */ + + +/**Function******************************************************************** + + Synopsis [Sifts from treenode->low to treenode->high.] + + Description [Sifts from treenode->low to treenode->high. If + croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the + end of the initial sifting. If a group is created, it is then sifted + again. After sifting one variable, the group that contains it is + dissolved. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +zddGroupSifting( + DdManager * table, + int lower, + int upper) +{ + int *var; + int i,j,x,xInit; + int nvars; + int classes; + int result; + int *sifted; +#ifdef DD_STATS + unsigned previousSize; +#endif + int xindex; + + nvars = table->sizeZ; + + /* Order variables to sift. */ + entry = NULL; + sifted = NULL; + var = ALLOC(int,nvars); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto zddGroupSiftingOutOfMem; + } + entry = ALLOC(int,nvars); + if (entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto zddGroupSiftingOutOfMem; + } + sifted = ALLOC(int,nvars); + if (sifted == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto zddGroupSiftingOutOfMem; + } + + /* Here we consider only one representative for each group. */ + for (i = 0, classes = 0; i < nvars; i++) { + sifted[i] = 0; + x = table->permZ[i]; + if ((unsigned) x >= table->subtableZ[x].next) { + entry[i] = table->subtableZ[x].keys; + var[classes] = i; + classes++; + } + } + + qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))zddUniqueCompareGroup); + + /* Now sift. */ + for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { + if (zddTotalNumberSwapping >= table->siftMaxSwap) + break; + xindex = var[i]; + if (sifted[xindex] == 1) /* variable already sifted as part of group */ + continue; + x = table->permZ[xindex]; /* find current level of this variable */ + if (x < lower || x > upper) + continue; +#ifdef DD_STATS + previousSize = table->keysZ; +#endif +#ifdef DD_DEBUG + /* x is bottom of group */ + assert((unsigned) x >= table->subtableZ[x].next); +#endif + result = zddGroupSiftingAux(table,x,lower,upper); + if (!result) goto zddGroupSiftingOutOfMem; + +#ifdef DD_STATS + if (table->keysZ < previousSize) { + (void) fprintf(table->out,"-"); + } else if (table->keysZ > previousSize) { + (void) fprintf(table->out,"+"); + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + + /* Mark variables in the group just sifted. */ + x = table->permZ[xindex]; + if ((unsigned) x != table->subtableZ[x].next) { + xInit = x; + do { + j = table->invpermZ[x]; + sifted[j] = 1; + x = table->subtableZ[x].next; + } while (x != xInit); + } + +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:"); +#endif + } /* for */ + + FREE(sifted); + FREE(var); + FREE(entry); + + return(1); + +zddGroupSiftingOutOfMem: + if (entry != NULL) FREE(entry); + if (var != NULL) FREE(var); + if (sifted != NULL) FREE(sifted); + + return(0); + +} /* end of zddGroupSifting */ + + +/**Function******************************************************************** + + Synopsis [Sifts one variable up and down until it has taken all + positions. Checks for aggregation.] + + Description [Sifts one variable up and down until it has taken all + positions. Checks for aggregation. There may be at most two sweeps, + even if the group grows. Assumes that x is either an isolated + variable, or it is the bottom of a group. All groups may not have + been found. The variable being moved is returned to the best position + seen during sifting. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +zddGroupSiftingAux( + DdManager * table, + int x, + int xLow, + int xHigh) +{ + Move *move; + Move *moves; /* list of moves */ + int initialSize; + int result; + + +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh); + assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */ +#endif + + initialSize = table->keysZ; + moves = NULL; + + if (x == xLow) { /* Sift down */ +#ifdef DD_DEBUG + /* x must be a singleton */ + assert((unsigned) x == table->subtableZ[x].next); +#endif + if (x == xHigh) return(1); /* just one variable */ + + if (!zddGroupSiftingDown(table,x,xHigh,&moves)) + goto zddGroupSiftingAuxOutOfMem; + /* at this point x == xHigh, unless early term */ + + /* move backward and stop at best position */ + result = zddGroupSiftingBackward(table,moves,initialSize); +#ifdef DD_DEBUG + assert(table->keysZ <= (unsigned) initialSize); +#endif + if (!result) goto zddGroupSiftingAuxOutOfMem; + + } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */ +#ifdef DD_DEBUG + /* x is bottom of group */ + assert((unsigned) x >= table->subtableZ[x].next); +#endif + /* Find top of x's group */ + x = table->subtableZ[x].next; + + if (!zddGroupSiftingUp(table,x,xLow,&moves)) + goto zddGroupSiftingAuxOutOfMem; + /* at this point x == xLow, unless early term */ + + /* move backward and stop at best position */ + result = zddGroupSiftingBackward(table,moves,initialSize); +#ifdef DD_DEBUG + assert(table->keysZ <= (unsigned) initialSize); +#endif + if (!result) goto zddGroupSiftingAuxOutOfMem; + + } else if (x - xLow > xHigh - x) { /* must go down first: shorter */ + if (!zddGroupSiftingDown(table,x,xHigh,&moves)) + goto zddGroupSiftingAuxOutOfMem; + /* at this point x == xHigh, unless early term */ + + /* Find top of group */ + if (moves) { + x = moves->y; + } + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + x = table->subtableZ[x].next; +#ifdef DD_DEBUG + /* x should be the top of a group */ + assert((unsigned) x <= table->subtableZ[x].next); +#endif + + if (!zddGroupSiftingUp(table,x,xLow,&moves)) + goto zddGroupSiftingAuxOutOfMem; + + /* move backward and stop at best position */ + result = zddGroupSiftingBackward(table,moves,initialSize); +#ifdef DD_DEBUG + assert(table->keysZ <= (unsigned) initialSize); +#endif + if (!result) goto zddGroupSiftingAuxOutOfMem; + + } else { /* moving up first: shorter */ + /* Find top of x's group */ + x = table->subtableZ[x].next; + + if (!zddGroupSiftingUp(table,x,xLow,&moves)) + goto zddGroupSiftingAuxOutOfMem; + /* at this point x == xHigh, unless early term */ + + if (moves) { + x = moves->x; + } + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; +#ifdef DD_DEBUG + /* x is bottom of a group */ + assert((unsigned) x >= table->subtableZ[x].next); +#endif + + if (!zddGroupSiftingDown(table,x,xHigh,&moves)) + goto zddGroupSiftingAuxOutOfMem; + + /* move backward and stop at best position */ + result = zddGroupSiftingBackward(table,moves,initialSize); +#ifdef DD_DEBUG + assert(table->keysZ <= (unsigned) initialSize); +#endif + if (!result) goto zddGroupSiftingAuxOutOfMem; + } + + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + + return(1); + +zddGroupSiftingAuxOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + + return(0); + +} /* end of zddGroupSiftingAux */ + + +/**Function******************************************************************** + + Synopsis [Sifts up a variable until either it reaches position xLow + or the size of the DD heap increases too much.] + + Description [Sifts up a variable until either it reaches position + xLow or the size of the DD heap increases too much. Assumes that y is + the top of a group (or a singleton). Checks y for aggregation to the + adjacent variables. Records all the moves that are appended to the + list of moves received as input and returned as a side effect. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +zddGroupSiftingUp( + DdManager * table, + int y, + int xLow, + Move ** moves) +{ + Move *move; + int x; + int size; + int gxtop; + int limitSize; + int xindex, yindex; + + yindex = table->invpermZ[y]; + + limitSize = table->keysZ; + + x = cuddZddNextLow(table,y); + while (x >= xLow) { + gxtop = table->subtableZ[x].next; + if (table->subtableZ[x].next == (unsigned) x && + table->subtableZ[y].next == (unsigned) y) { + /* x and y are self groups */ + xindex = table->invpermZ[x]; + size = cuddZddSwapInPlace(table,x,y); +#ifdef DD_DEBUG + assert(table->subtableZ[x].next == (unsigned) x); + assert(table->subtableZ[y].next == (unsigned) y); +#endif + if (size == 0) goto zddGroupSiftingUpOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) goto zddGroupSiftingUpOutOfMem; + move->x = x; + move->y = y; + move->flags = MTR_DEFAULT; + move->size = size; + move->next = *moves; + *moves = move; + +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n"); +#endif + if ((double) size > (double) limitSize * table->maxGrowth) + return(1); + if (size < limitSize) limitSize = size; + } else { /* group move */ + size = zddGroupMove(table,x,y,moves); + if (size == 0) goto zddGroupSiftingUpOutOfMem; + if ((double) size > (double) limitSize * table->maxGrowth) + return(1); + if (size < limitSize) limitSize = size; + } + y = gxtop; + x = cuddZddNextLow(table,y); + } + + return(1); + +zddGroupSiftingUpOutOfMem: + while (*moves != NULL) { + move = (*moves)->next; + cuddDeallocNode(table, (DdNode *) *moves); + *moves = move; + } + return(0); + +} /* end of zddGroupSiftingUp */ + + +/**Function******************************************************************** + + Synopsis [Sifts down a variable until it reaches position xHigh.] + + Description [Sifts down a variable until it reaches position xHigh. + Assumes that x is the bottom of a group (or a singleton). Records + all the moves. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +zddGroupSiftingDown( + DdManager * table, + int x, + int xHigh, + Move ** moves) +{ + Move *move; + int y; + int size; + int limitSize; + int gxtop,gybot; + int xindex; + + + /* Initialize R */ + xindex = table->invpermZ[x]; + gxtop = table->subtableZ[x].next; + limitSize = size = table->keysZ; + y = cuddZddNextHigh(table,x); + while (y <= xHigh) { + /* Find bottom of y group. */ + gybot = table->subtableZ[y].next; + while (table->subtableZ[gybot].next != (unsigned) y) + gybot = table->subtableZ[gybot].next; + + if (table->subtableZ[x].next == (unsigned) x && + table->subtableZ[y].next == (unsigned) y) { + /* x and y are self groups */ + size = cuddZddSwapInPlace(table,x,y); +#ifdef DD_DEBUG + assert(table->subtableZ[x].next == (unsigned) x); + assert(table->subtableZ[y].next == (unsigned) y); +#endif + if (size == 0) goto zddGroupSiftingDownOutOfMem; + + /* Record move. */ + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto zddGroupSiftingDownOutOfMem; + move->x = x; + move->y = y; + move->flags = MTR_DEFAULT; + move->size = size; + move->next = *moves; + *moves = move; + +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n"); +#endif + if ((double) size > (double) limitSize * table->maxGrowth) + return(1); + if (size < limitSize) limitSize = size; + x = y; + y = cuddZddNextHigh(table,x); + } else { /* Group move */ + size = zddGroupMove(table,x,y,moves); + if (size == 0) goto zddGroupSiftingDownOutOfMem; + if ((double) size > (double) limitSize * table->maxGrowth) + return(1); + if (size < limitSize) limitSize = size; + } + x = gybot; + y = cuddZddNextHigh(table,x); + } + + return(1); + +zddGroupSiftingDownOutOfMem: + while (*moves != NULL) { + move = (*moves)->next; + cuddDeallocNode(table, (DdNode *) *moves); + *moves = move; + } + + return(0); + +} /* end of zddGroupSiftingDown */ + + +/**Function******************************************************************** + + Synopsis [Swaps two groups and records the move.] + + Description [Swaps two groups and records the move. Returns the + number of keys in the DD table in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +zddGroupMove( + DdManager * table, + int x, + int y, + Move ** moves) +{ + Move *move; + int size; + int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; + int swapx,swapy; +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + int initialSize,bestSize; +#endif + +#if DD_DEBUG + /* We assume that x < y */ + assert(x < y); +#endif + /* Find top, bottom, and size for the two groups. */ + xbot = x; + xtop = table->subtableZ[x].next; + xsize = xbot - xtop + 1; + ybot = y; + while ((unsigned) ybot < table->subtableZ[ybot].next) + ybot = table->subtableZ[ybot].next; + ytop = y; + ysize = ybot - ytop + 1; + +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + initialSize = bestSize = table->keysZ; +#endif + /* Sift the variables of the second group up through the first group */ + for (i = 1; i <= ysize; i++) { + for (j = 1; j <= xsize; j++) { + size = cuddZddSwapInPlace(table,x,y); + if (size == 0) goto zddGroupMoveOutOfMem; +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + if (size < bestSize) + bestSize = size; +#endif + swapx = x; swapy = y; + y = x; + x = cuddZddNextLow(table,y); + } + y = ytop + i; + x = cuddZddNextLow(table,y); + } +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + if ((bestSize < initialSize) && (bestSize < size)) + (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size); +#endif + + /* fix groups */ + y = xtop; /* ytop is now where xtop used to be */ + for (i = 0; i < ysize - 1; i++) { + table->subtableZ[y].next = cuddZddNextHigh(table,y); + y = cuddZddNextHigh(table,y); + } + table->subtableZ[y].next = xtop; /* y is bottom of its group, join */ + /* it to top of its group */ + x = cuddZddNextHigh(table,y); + newxtop = x; + for (i = 0; i < xsize - 1; i++) { + table->subtableZ[x].next = cuddZddNextHigh(table,x); + x = cuddZddNextHigh(table,x); + } + table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */ + /* it to top of its group */ +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n"); +#endif + + /* Store group move */ + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) goto zddGroupMoveOutOfMem; + move->x = swapx; + move->y = swapy; + move->flags = MTR_DEFAULT; + move->size = table->keysZ; + move->next = *moves; + *moves = move; + + return(table->keysZ); + +zddGroupMoveOutOfMem: + while (*moves != NULL) { + move = (*moves)->next; + cuddDeallocNode(table, (DdNode *) *moves); + *moves = move; + } + return(0); + +} /* end of zddGroupMove */ + + +/**Function******************************************************************** + + Synopsis [Undoes the swap two groups.] + + Description [Undoes the swap two groups. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +zddGroupMoveBackward( + DdManager * table, + int x, + int y) +{ + int size; + int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; + + +#if DD_DEBUG + /* We assume that x < y */ + assert(x < y); +#endif + + /* Find top, bottom, and size for the two groups. */ + xbot = x; + xtop = table->subtableZ[x].next; + xsize = xbot - xtop + 1; + ybot = y; + while ((unsigned) ybot < table->subtableZ[ybot].next) + ybot = table->subtableZ[ybot].next; + ytop = y; + ysize = ybot - ytop + 1; + + /* Sift the variables of the second group up through the first group */ + for (i = 1; i <= ysize; i++) { + for (j = 1; j <= xsize; j++) { + size = cuddZddSwapInPlace(table,x,y); + if (size == 0) + return(0); + y = x; + x = cuddZddNextLow(table,y); + } + y = ytop + i; + x = cuddZddNextLow(table,y); + } + + /* fix groups */ + y = xtop; + for (i = 0; i < ysize - 1; i++) { + table->subtableZ[y].next = cuddZddNextHigh(table,y); + y = cuddZddNextHigh(table,y); + } + table->subtableZ[y].next = xtop; /* y is bottom of its group, join */ + /* to its top */ + x = cuddZddNextHigh(table,y); + newxtop = x; + for (i = 0; i < xsize - 1; i++) { + table->subtableZ[x].next = cuddZddNextHigh(table,x); + x = cuddZddNextHigh(table,x); + } + table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */ + /* to its top */ +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n"); +#endif + + return(1); + +} /* end of zddGroupMoveBackward */ + + +/**Function******************************************************************** + + Synopsis [Determines the best position for a variables and returns + it there.] + + Description [Determines the best position for a variables and returns + it there. Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +zddGroupSiftingBackward( + DdManager * table, + Move * moves, + int size) +{ + Move *move; + int res; + + + for (move = moves; move != NULL; move = move->next) { + if (move->size < size) { + size = move->size; + } + } + + for (move = moves; move != NULL; move = move->next) { + if (move->size == size) return(1); + if ((table->subtableZ[move->x].next == move->x) && + (table->subtableZ[move->y].next == move->y)) { + res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); +#ifdef DD_DEBUG + if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n"); + assert(table->subtableZ[move->x].next == move->x); + assert(table->subtableZ[move->y].next == move->y); +#endif + } else { /* Group move necessary */ + res = zddGroupMoveBackward(table,(int)move->x,(int)move->y); + if (!res) return(0); + } + } + + return(1); + +} /* end of zddGroupSiftingBackward */ + + +/**Function******************************************************************** + + Synopsis [Merges groups in the DD table.] + + Description [Creates a single group from low to high and adjusts the + idex field of the tree node.] + + SideEffects [None] + +******************************************************************************/ +static void +zddMergeGroups( + DdManager * table, + MtrNode * treenode, + int low, + int high) +{ + int i; + MtrNode *auxnode; + int saveindex; + int newindex; + + /* Merge all variables from low to high in one group, unless + ** this is the topmost group. In such a case we do not merge lest + ** we lose the symmetry information. */ + if (treenode != table->treeZ) { + for (i = low; i < high; i++) + table->subtableZ[i].next = i+1; + table->subtableZ[high].next = low; + } + + /* Adjust the index fields of the tree nodes. If a node is the + ** first child of its parent, then the parent may also need adjustment. */ + saveindex = treenode->index; + newindex = table->invpermZ[low]; + auxnode = treenode; + do { + auxnode->index = newindex; + if (auxnode->parent == NULL || + (int) auxnode->parent->index != saveindex) + break; + auxnode = auxnode->parent; + } while (1); + return; + +} /* end of zddMergeGroups */ + diff --git a/abc70930/src/bdd/cudd/cuddZddIsop.c b/abc70930/src/bdd/cudd/cuddZddIsop.c new file mode 100644 index 00000000..f4b057ea --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddZddIsop.c @@ -0,0 +1,885 @@ +/**CFile*********************************************************************** + + FileName [cuddZddIsop.c] + + PackageName [cudd] + + Synopsis [Functions to find irredundant SOP covers as ZDDs from BDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_bddIsop() +
        • Cudd_zddIsop() +
        • Cudd_MakeBddFromZddCover() +
        + Internal procedures included in this module: +
          +
        • cuddBddIsop() +
        • cuddZddIsop() +
        • cuddMakeBddFromZddCover() +
        + Static procedures included in this module: +
          +
        + ] + + SeeAlso [] + + Author [In-Ho Moon] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddIsop.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes an ISOP in ZDD form from BDDs.] + + Description [Computes an irredundant sum of products (ISOP) in ZDD + form from BDDs. The two BDDs L and U represent the lower bound and + the upper bound, respectively, of the function. The ISOP uses two + ZDD variables for each BDD variable: One for the positive literal, + and one for the negative literal. These two variables should be + adjacent in the ZDD order. The two ZDD variables corresponding to + BDD variable i should have indices 2i and + 2i+1. The result of this procedure depends on the + variable order. If successful, Cudd_zddIsop returns the BDD for + the function chosen from the interval. The ZDD representing the + irredundant cover is returned as a side effect in zdd_I. In case of + failure, NULL is returned.] + + SideEffects [zdd_I holds the pointer to the ZDD for the ISOP on + successful return.] + + SeeAlso [Cudd_bddIsop Cudd_zddVarsFromBddVars] + +******************************************************************************/ +DdNode * +Cudd_zddIsop( + DdManager * dd, + DdNode * L, + DdNode * U, + DdNode ** zdd_I) +{ + DdNode *res; + int autoDynZ; + + autoDynZ = dd->autoDynZ; + dd->autoDynZ = 0; + + do { + dd->reordered = 0; + res = cuddZddIsop(dd, L, U, zdd_I); + } while (dd->reordered == 1); + dd->autoDynZ = autoDynZ; + return(res); + +} /* end of Cudd_zddIsop */ + + +/**Function******************************************************************** + + Synopsis [Computes a BDD in the interval between L and U with a + simple sum-of-produuct cover.] + + Description [Computes a BDD in the interval between L and U with a + simple sum-of-produuct cover. This procedure is similar to + Cudd_zddIsop, but it does not return the ZDD for the cover. Returns + a pointer to the BDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddIsop] + +******************************************************************************/ +DdNode * +Cudd_bddIsop( + DdManager * dd, + DdNode * L, + DdNode * U) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddBddIsop(dd, L, U); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_bddIsop */ + + +/**Function******************************************************************** + + Synopsis [Converts a ZDD cover to a BDD graph.] + + Description [Converts a ZDD cover to a BDD graph. If successful, it + returns a BDD node, otherwise it returns NULL.] + + SideEffects [] + + SeeAlso [cuddMakeBddFromZddCover] + +******************************************************************************/ +DdNode * +Cudd_MakeBddFromZddCover( + DdManager * dd, + DdNode * node) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddMakeBddFromZddCover(dd, node); + } while (dd->reordered == 1); + return(res); +} /* end of Cudd_MakeBddFromZddCover */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddIsop.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_zddIsop] + +******************************************************************************/ +DdNode * +cuddZddIsop( + DdManager * dd, + DdNode * L, + DdNode * U, + DdNode ** zdd_I) +{ + DdNode *one = DD_ONE(dd); + DdNode *zero = Cudd_Not(one); + DdNode *zdd_one = DD_ONE(dd); + DdNode *zdd_zero = DD_ZERO(dd); + int v, top_l, top_u; + DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; + DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; + DdNode *Isub0, *Isub1, *Id; + DdNode *zdd_Isub0, *zdd_Isub1, *zdd_Id; + DdNode *x; + DdNode *term0, *term1, *sum; + DdNode *Lv, *Uv, *Lnv, *Unv; + DdNode *r, *y, *z; + int index; + DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); + + statLine(dd); + if (L == zero) { + *zdd_I = zdd_zero; + return(zero); + } + if (U == one) { + *zdd_I = zdd_one; + return(one); + } + + if (U == zero || L == one) { + printf("*** ERROR : illegal condition for ISOP (U < L).\n"); + exit(1); + } + + /* Check the cache. We store two results for each recursive call. + ** One is the BDD, and the other is the ZDD. Both are needed. + ** Hence we need a double hit in the cache to terminate the + ** recursion. Clearly, collisions may evict only one of the two + ** results. */ + cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) cuddZddIsop; + r = cuddCacheLookup2(dd, cuddBddIsop, L, U); + if (r) { + *zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U); + if (*zdd_I) + return(r); + else { + /* The BDD result may have been dead. In that case + ** cuddCacheLookup2 would have called cuddReclaim, + ** whose effects we now have to undo. */ + cuddRef(r); + Cudd_RecursiveDeref(dd, r); + } + } + + top_l = dd->perm[Cudd_Regular(L)->index]; + top_u = dd->perm[Cudd_Regular(U)->index]; + v = ddMin(top_l, top_u); + + /* Compute cofactors. */ + if (top_l == v) { + index = Cudd_Regular(L)->index; + Lv = Cudd_T(L); + Lnv = Cudd_E(L); + if (Cudd_IsComplement(L)) { + Lv = Cudd_Not(Lv); + Lnv = Cudd_Not(Lnv); + } + } + else { + index = Cudd_Regular(U)->index; + Lv = Lnv = L; + } + + if (top_u == v) { + Uv = Cudd_T(U); + Unv = Cudd_E(U); + if (Cudd_IsComplement(U)) { + Uv = Cudd_Not(Uv); + Unv = Cudd_Not(Unv); + } + } + else { + Uv = Unv = U; + } + + Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); + if (Lsub0 == NULL) + return(NULL); + Cudd_Ref(Lsub0); + Usub0 = Unv; + Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); + if (Lsub1 == NULL) { + Cudd_RecursiveDeref(dd, Lsub0); + return(NULL); + } + Cudd_Ref(Lsub1); + Usub1 = Uv; + + Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0); + if (Isub0 == NULL) { + Cudd_RecursiveDeref(dd, Lsub0); + Cudd_RecursiveDeref(dd, Lsub1); + return(NULL); + } + /* + if ((!cuddIsConstant(Cudd_Regular(Isub0))) && + (Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 || + dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) { + printf("*** ERROR : illegal permutation in ZDD. ***\n"); + } + */ + Cudd_Ref(Isub0); + Cudd_Ref(zdd_Isub0); + Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1); + if (Isub1 == NULL) { + Cudd_RecursiveDeref(dd, Lsub0); + Cudd_RecursiveDeref(dd, Lsub1); + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + return(NULL); + } + /* + if ((!cuddIsConstant(Cudd_Regular(Isub1))) && + (Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 || + dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) { + printf("*** ERROR : illegal permutation in ZDD. ***\n"); + } + */ + Cudd_Ref(Isub1); + Cudd_Ref(zdd_Isub1); + Cudd_RecursiveDeref(dd, Lsub0); + Cudd_RecursiveDeref(dd, Lsub1); + + Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); + if (Lsuper0 == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + return(NULL); + } + Cudd_Ref(Lsuper0); + Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); + if (Lsuper1 == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDeref(dd, Lsuper0); + return(NULL); + } + Cudd_Ref(Lsuper1); + Usuper0 = Unv; + Usuper1 = Uv; + + /* Ld = Lsuper0 + Lsuper1 */ + Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); + if (Ld == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDeref(dd, Lsuper0); + Cudd_RecursiveDeref(dd, Lsuper1); + return(NULL); + } + Ld = Cudd_Not(Ld); + Cudd_Ref(Ld); + /* Ud = Usuper0 * Usuper1 */ + Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); + if (Ud == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDeref(dd, Lsuper0); + Cudd_RecursiveDeref(dd, Lsuper1); + Cudd_RecursiveDeref(dd, Ld); + return(NULL); + } + Cudd_Ref(Ud); + Cudd_RecursiveDeref(dd, Lsuper0); + Cudd_RecursiveDeref(dd, Lsuper1); + + Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id); + if (Id == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDeref(dd, Ld); + Cudd_RecursiveDeref(dd, Ud); + return(NULL); + } + /* + if ((!cuddIsConstant(Cudd_Regular(Id))) && + (Cudd_Regular(Id)->index != zdd_Id->index / 2 || + dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) { + printf("*** ERROR : illegal permutation in ZDD. ***\n"); + } + */ + Cudd_Ref(Id); + Cudd_Ref(zdd_Id); + Cudd_RecursiveDeref(dd, Ld); + Cudd_RecursiveDeref(dd, Ud); + + x = cuddUniqueInter(dd, index, one, zero); + if (x == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDerefZdd(dd, zdd_Id); + return(NULL); + } + Cudd_Ref(x); + /* term0 = x * Isub0 */ + term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); + if (term0 == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDerefZdd(dd, zdd_Id); + Cudd_RecursiveDeref(dd, x); + return(NULL); + } + Cudd_Ref(term0); + Cudd_RecursiveDeref(dd, Isub0); + /* term1 = x * Isub1 */ + term1 = cuddBddAndRecur(dd, x, Isub1); + if (term1 == NULL) { + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDerefZdd(dd, zdd_Id); + Cudd_RecursiveDeref(dd, x); + Cudd_RecursiveDeref(dd, term0); + return(NULL); + } + Cudd_Ref(term1); + Cudd_RecursiveDeref(dd, x); + Cudd_RecursiveDeref(dd, Isub1); + /* sum = term0 + term1 */ + sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); + if (sum == NULL) { + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDerefZdd(dd, zdd_Id); + Cudd_RecursiveDeref(dd, term0); + Cudd_RecursiveDeref(dd, term1); + return(NULL); + } + sum = Cudd_Not(sum); + Cudd_Ref(sum); + Cudd_RecursiveDeref(dd, term0); + Cudd_RecursiveDeref(dd, term1); + /* r = sum + Id */ + r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); + r = Cudd_NotCond(r, r != NULL); + if (r == NULL) { + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDerefZdd(dd, zdd_Id); + Cudd_RecursiveDeref(dd, sum); + return(NULL); + } + Cudd_Ref(r); + Cudd_RecursiveDeref(dd, sum); + Cudd_RecursiveDeref(dd, Id); + + if (zdd_Isub0 != zdd_zero) { + z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id); + if (z == NULL) { + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDerefZdd(dd, zdd_Id); + Cudd_RecursiveDeref(dd, r); + return(NULL); + } + } + else { + z = zdd_Id; + } + Cudd_Ref(z); + if (zdd_Isub1 != zdd_zero) { + y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z); + if (y == NULL) { + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDerefZdd(dd, zdd_Id); + Cudd_RecursiveDeref(dd, r); + Cudd_RecursiveDerefZdd(dd, z); + return(NULL); + } + } + else + y = z; + Cudd_Ref(y); + + Cudd_RecursiveDerefZdd(dd, zdd_Isub0); + Cudd_RecursiveDerefZdd(dd, zdd_Isub1); + Cudd_RecursiveDerefZdd(dd, zdd_Id); + Cudd_RecursiveDerefZdd(dd, z); + + cuddCacheInsert2(dd, cuddBddIsop, L, U, r); + cuddCacheInsert2(dd, cacheOp, L, U, y); + + Cudd_Deref(r); + Cudd_Deref(y); + *zdd_I = y; + /* + if (Cudd_Regular(r)->index != y->index / 2) { + printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n"); + } + */ + return(r); + +} /* end of cuddZddIsop */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_bddIsop.] + + Description [] + + SideEffects [None] + + SeeAlso [Cudd_bddIsop] + +******************************************************************************/ +DdNode * +cuddBddIsop( + DdManager * dd, + DdNode * L, + DdNode * U) +{ + DdNode *one = DD_ONE(dd); + DdNode *zero = Cudd_Not(one); + int v, top_l, top_u; + DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; + DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; + DdNode *Isub0, *Isub1, *Id; + DdNode *x; + DdNode *term0, *term1, *sum; + DdNode *Lv, *Uv, *Lnv, *Unv; + DdNode *r; + int index; + + statLine(dd); + if (L == zero) + return(zero); + if (U == one) + return(one); + + /* Check cache */ + r = cuddCacheLookup2(dd, cuddBddIsop, L, U); + if (r) + return(r); + + top_l = dd->perm[Cudd_Regular(L)->index]; + top_u = dd->perm[Cudd_Regular(U)->index]; + v = ddMin(top_l, top_u); + + /* Compute cofactors */ + if (top_l == v) { + index = Cudd_Regular(L)->index; + Lv = Cudd_T(L); + Lnv = Cudd_E(L); + if (Cudd_IsComplement(L)) { + Lv = Cudd_Not(Lv); + Lnv = Cudd_Not(Lnv); + } + } + else { + index = Cudd_Regular(U)->index; + Lv = Lnv = L; + } + + if (top_u == v) { + Uv = Cudd_T(U); + Unv = Cudd_E(U); + if (Cudd_IsComplement(U)) { + Uv = Cudd_Not(Uv); + Unv = Cudd_Not(Unv); + } + } + else { + Uv = Unv = U; + } + + Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); + if (Lsub0 == NULL) + return(NULL); + Cudd_Ref(Lsub0); + Usub0 = Unv; + Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); + if (Lsub1 == NULL) { + Cudd_RecursiveDeref(dd, Lsub0); + return(NULL); + } + Cudd_Ref(Lsub1); + Usub1 = Uv; + + Isub0 = cuddBddIsop(dd, Lsub0, Usub0); + if (Isub0 == NULL) { + Cudd_RecursiveDeref(dd, Lsub0); + Cudd_RecursiveDeref(dd, Lsub1); + return(NULL); + } + Cudd_Ref(Isub0); + Isub1 = cuddBddIsop(dd, Lsub1, Usub1); + if (Isub1 == NULL) { + Cudd_RecursiveDeref(dd, Lsub0); + Cudd_RecursiveDeref(dd, Lsub1); + Cudd_RecursiveDeref(dd, Isub0); + return(NULL); + } + Cudd_Ref(Isub1); + Cudd_RecursiveDeref(dd, Lsub0); + Cudd_RecursiveDeref(dd, Lsub1); + + Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); + if (Lsuper0 == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + return(NULL); + } + Cudd_Ref(Lsuper0); + Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); + if (Lsuper1 == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Lsuper0); + return(NULL); + } + Cudd_Ref(Lsuper1); + Usuper0 = Unv; + Usuper1 = Uv; + + /* Ld = Lsuper0 + Lsuper1 */ + Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); + Ld = Cudd_NotCond(Ld, Ld != NULL); + if (Ld == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Lsuper0); + Cudd_RecursiveDeref(dd, Lsuper1); + return(NULL); + } + Cudd_Ref(Ld); + Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); + if (Ud == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Lsuper0); + Cudd_RecursiveDeref(dd, Lsuper1); + Cudd_RecursiveDeref(dd, Ld); + return(NULL); + } + Cudd_Ref(Ud); + Cudd_RecursiveDeref(dd, Lsuper0); + Cudd_RecursiveDeref(dd, Lsuper1); + + Id = cuddBddIsop(dd, Ld, Ud); + if (Id == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Ld); + Cudd_RecursiveDeref(dd, Ud); + return(NULL); + } + Cudd_Ref(Id); + Cudd_RecursiveDeref(dd, Ld); + Cudd_RecursiveDeref(dd, Ud); + + x = cuddUniqueInter(dd, index, one, zero); + if (x == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Id); + return(NULL); + } + Cudd_Ref(x); + term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); + if (term0 == NULL) { + Cudd_RecursiveDeref(dd, Isub0); + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDeref(dd, x); + return(NULL); + } + Cudd_Ref(term0); + Cudd_RecursiveDeref(dd, Isub0); + term1 = cuddBddAndRecur(dd, x, Isub1); + if (term1 == NULL) { + Cudd_RecursiveDeref(dd, Isub1); + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDeref(dd, x); + Cudd_RecursiveDeref(dd, term0); + return(NULL); + } + Cudd_Ref(term1); + Cudd_RecursiveDeref(dd, x); + Cudd_RecursiveDeref(dd, Isub1); + /* sum = term0 + term1 */ + sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); + sum = Cudd_NotCond(sum, sum != NULL); + if (sum == NULL) { + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDeref(dd, term0); + Cudd_RecursiveDeref(dd, term1); + return(NULL); + } + Cudd_Ref(sum); + Cudd_RecursiveDeref(dd, term0); + Cudd_RecursiveDeref(dd, term1); + /* r = sum + Id */ + r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); + r = Cudd_NotCond(r, r != NULL); + if (r == NULL) { + Cudd_RecursiveDeref(dd, Id); + Cudd_RecursiveDeref(dd, sum); + return(NULL); + } + Cudd_Ref(r); + Cudd_RecursiveDeref(dd, sum); + Cudd_RecursiveDeref(dd, Id); + + cuddCacheInsert2(dd, cuddBddIsop, L, U, r); + + Cudd_Deref(r); + return(r); + +} /* end of cuddBddIsop */ + + +/**Function******************************************************************** + + Synopsis [Converts a ZDD cover to a BDD graph.] + + Description [Converts a ZDD cover to a BDD graph. If successful, it + returns a BDD node, otherwise it returns NULL. It is a recursive + algorithm as the following. First computes 3 cofactors of a ZDD cover; + f1, f0 and fd. Second, compute BDDs(b1, b0 and bd) of f1, f0 and fd. + Third, compute T=b1+bd and E=b0+bd. Fourth, compute ITE(v,T,E) where v + is the variable which has the index of the top node of the ZDD cover. + In this case, since the index of v can be larger than either one of T or + one of E, cuddUniqueInterIVO is called, here IVO stands for + independent variable ordering.] + + SideEffects [] + + SeeAlso [Cudd_MakeBddFromZddCover] + +******************************************************************************/ +DdNode * +cuddMakeBddFromZddCover( + DdManager * dd, + DdNode * node) +{ + DdNode *neW; + int v; + DdNode *f1, *f0, *fd; + DdNode *b1, *b0, *bd; + DdNode *T, *E; + + statLine(dd); + if (node == dd->one) + return(dd->one); + if (node == dd->zero) + return(Cudd_Not(dd->one)); + + /* Check cache */ + neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node); + if (neW) + return(neW); + + v = Cudd_Regular(node)->index; /* either yi or zi */ + cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd); + Cudd_Ref(f1); + Cudd_Ref(f0); + Cudd_Ref(fd); + + b1 = cuddMakeBddFromZddCover(dd, f1); + if (!b1) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + return(NULL); + } + Cudd_Ref(b1); + b0 = cuddMakeBddFromZddCover(dd, f0); + if (!b1) { + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDeref(dd, b1); + return(NULL); + } + Cudd_Ref(b0); + Cudd_RecursiveDerefZdd(dd, f1); + Cudd_RecursiveDerefZdd(dd, f0); + if (fd != dd->zero) { + bd = cuddMakeBddFromZddCover(dd, fd); + if (!bd) { + Cudd_RecursiveDerefZdd(dd, fd); + Cudd_RecursiveDeref(dd, b1); + Cudd_RecursiveDeref(dd, b0); + return(NULL); + } + Cudd_Ref(bd); + Cudd_RecursiveDerefZdd(dd, fd); + + T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd)); + if (!T) { + Cudd_RecursiveDeref(dd, b1); + Cudd_RecursiveDeref(dd, b0); + Cudd_RecursiveDeref(dd, bd); + return(NULL); + } + T = Cudd_NotCond(T, T != NULL); + Cudd_Ref(T); + Cudd_RecursiveDeref(dd, b1); + E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd)); + if (!E) { + Cudd_RecursiveDeref(dd, b0); + Cudd_RecursiveDeref(dd, bd); + Cudd_RecursiveDeref(dd, T); + return(NULL); + } + E = Cudd_NotCond(E, E != NULL); + Cudd_Ref(E); + Cudd_RecursiveDeref(dd, b0); + Cudd_RecursiveDeref(dd, bd); + } + else { + Cudd_RecursiveDerefZdd(dd, fd); + T = b1; + E = b0; + } + + if (Cudd_IsComplement(T)) { + neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E)); + if (!neW) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + neW = Cudd_Not(neW); + } + else { + neW = cuddUniqueInterIVO(dd, v / 2, T, E); + if (!neW) { + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + return(NULL); + } + } + Cudd_Ref(neW); + Cudd_RecursiveDeref(dd, T); + Cudd_RecursiveDeref(dd, E); + + cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW); + Cudd_Deref(neW); + return(neW); + +} /* end of cuddMakeBddFromZddCover */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/cudd/cuddZddLin.c b/abc70930/src/bdd/cudd/cuddZddLin.c new file mode 100644 index 00000000..ef2cd298 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddZddLin.c @@ -0,0 +1,939 @@ +/**CFile*********************************************************************** + + FileName [cuddZddLin.c] + + PackageName [cudd] + + Synopsis [Procedures for dynamic variable ordering of ZDDs.] + + Description [Internal procedures included in this module: +
          +
        • cuddZddLinearSifting() +
        + Static procedures included in this module: +
          +
        • cuddZddLinearInPlace() +
        • cuddZddLinerAux() +
        • cuddZddLinearUp() +
        • cuddZddLinearDown() +
        • cuddZddLinearBackward() +
        • cuddZddUndoMoves() +
        + ] + + SeeAlso [cuddLinear.c cuddZddReord.c] + + Author [Fabio Somenzi] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define CUDD_SWAP_MOVE 0 +#define CUDD_LINEAR_TRANSFORM_MOVE 1 +#define CUDD_INVERSE_TRANSFORM_MOVE 2 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddLin.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; +#endif + +extern int *zdd_entry; +extern int zddTotalNumberSwapping; +static int zddTotalNumberLinearTr; +static DdNode *empty; + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int cuddZddLinearAux ARGS((DdManager *table, int x, int xLow, int xHigh)); +static Move * cuddZddLinearUp ARGS((DdManager *table, int y, int xLow, Move *prevMoves)); +static Move * cuddZddLinearDown ARGS((DdManager *table, int x, int xHigh, Move *prevMoves)); +static int cuddZddLinearBackward ARGS((DdManager *table, int size, Move *moves)); +static Move* cuddZddUndoMoves ARGS((DdManager *table, Move *moves)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + + + +/**Function******************************************************************** + + Synopsis [Implementation of the linear sifting algorithm for ZDDs.] + + Description [Implementation of the linear sifting algorithm for ZDDs. + Assumes that no dead nodes are present. +
          +
        1. Order all the variables according to the number of entries + in each unique table. +
        2. Sift the variable up and down and applies the XOR transformation, + remembering each time the total size of the DD heap. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddLinearSifting( + DdManager * table, + int lower, + int upper) +{ + int i; + int *var; + int size; + int x; + int result; +#ifdef DD_STATS + int previousSize; +#endif + + size = table->sizeZ; + empty = table->zero; + + /* Find order in which to sift variables. */ + var = NULL; + zdd_entry = ALLOC(int, size); + if (zdd_entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSiftingOutOfMem; + } + var = ALLOC(int, size); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSiftingOutOfMem; + } + + for (i = 0; i < size; i++) { + x = table->permZ[i]; + zdd_entry[i] = table->subtableZ[x].keys; + var[i] = i; + } + + qsort((void *)var, size, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); + + /* Now sift. */ + for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { + if (zddTotalNumberSwapping >= table->siftMaxSwap) + break; + x = table->permZ[var[i]]; + if (x < lower || x > upper) continue; +#ifdef DD_STATS + previousSize = table->keysZ; +#endif + result = cuddZddLinearAux(table, x, lower, upper); + if (!result) + goto cuddZddSiftingOutOfMem; +#ifdef DD_STATS + if (table->keysZ < (unsigned) previousSize) { + (void) fprintf(table->out,"-"); + } else if (table->keysZ > (unsigned) previousSize) { + (void) fprintf(table->out,"+"); /* should never happen */ + (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + + FREE(var); + FREE(zdd_entry); + + return(1); + +cuddZddSiftingOutOfMem: + + if (zdd_entry != NULL) FREE(zdd_entry); + if (var != NULL) FREE(var); + + return(0); + +} /* end of cuddZddLinearSifting */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Linearly combines two adjacent variables.] + + Description [Linearly combines two adjacent variables. It assumes + that no dead nodes are present on entry to this procedure. The + procedure then guarantees that no dead nodes will be present when it + terminates. cuddZddLinearInPlace assumes that x < y. Returns the + number of keys in the table if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [cuddZddSwapInPlace cuddLinearInPlace] + +******************************************************************************/ +int +cuddZddLinearInPlace( + DdManager * table, + int x, + int y) +{ + DdNodePtr *xlist, *ylist; + int xindex, yindex; + int xslots, yslots; + int xshift, yshift; + int oldxkeys, oldykeys; + int newxkeys, newykeys; + int i; + int posn; + DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; + DdNode *newf1, *newf0, *g, *next, *previous; + DdNode *special; + +#ifdef DD_DEBUG + assert(x < y); + assert(cuddZddNextHigh(table,x) == y); + assert(table->subtableZ[x].keys != 0); + assert(table->subtableZ[y].keys != 0); + assert(table->subtableZ[x].dead == 0); + assert(table->subtableZ[y].dead == 0); +#endif + + zddTotalNumberLinearTr++; + + /* Get parameters of x subtable. */ + xindex = table->invpermZ[x]; + xlist = table->subtableZ[x].nodelist; + oldxkeys = table->subtableZ[x].keys; + xslots = table->subtableZ[x].slots; + xshift = table->subtableZ[x].shift; + newxkeys = 0; + + /* Get parameters of y subtable. */ + yindex = table->invpermZ[y]; + ylist = table->subtableZ[y].nodelist; + oldykeys = table->subtableZ[y].keys; + yslots = table->subtableZ[y].slots; + yshift = table->subtableZ[y].shift; + newykeys = oldykeys; + + /* The nodes in the x layer are put in two chains. The chain + ** pointed by g holds the normal nodes. When re-expressed they stay + ** in the x list. The chain pointed by special holds the elements + ** that will move to the y list. + */ + g = special = NULL; + for (i = 0; i < xslots; i++) { + f = xlist[i]; + if (f == NULL) continue; + xlist[i] = NULL; + while (f != NULL) { + next = f->next; + f1 = cuddT(f); + /* if (f1->index == yindex) */ cuddSatDec(f1->ref); + f0 = cuddE(f); + /* if (f0->index == yindex) */ cuddSatDec(f0->ref); + if ((int) f1->index == yindex && cuddE(f1) == empty && + (int) f0->index != yindex) { + f->next = special; + special = f; + } else { + f->next = g; + g = f; + } + f = next; + } /* while there are elements in the collision chain */ + } /* for each slot of the x subtable */ + + /* Mark y nodes with pointers from above x. We mark them by + ** changing their index to x. + */ + for (i = 0; i < yslots; i++) { + f = ylist[i]; + while (f != NULL) { + if (f->ref != 0) { + f->index = xindex; + } + f = f->next; + } /* while there are elements in the collision chain */ + } /* for each slot of the y subtable */ + + /* Move special nodes to the y list. */ + f = special; + while (f != NULL) { + next = f->next; + f1 = cuddT(f); + f11 = cuddT(f1); + cuddT(f) = f11; + cuddSatInc(f11->ref); + f0 = cuddE(f); + cuddSatInc(f0->ref); + f->index = yindex; + /* Insert at the beginning of the list so that it will be + ** found first if there is a duplicate. The duplicate will + ** eventually be moved or garbage collected. No node + ** re-expression will add a pointer to it. + */ + posn = ddHash(f11, f0, yshift); + f->next = ylist[posn]; + ylist[posn] = f; + newykeys++; + f = next; + } + + /* Take care of the remaining x nodes that must be re-expressed. + ** They form a linked list pointed by g. + */ + f = g; + while (f != NULL) { +#ifdef DD_COUNT + table->swapSteps++; +#endif + next = f->next; + /* Find f1, f0, f11, f10, f01, f00. */ + f1 = cuddT(f); + if ((int) f1->index == yindex || (int) f1->index == xindex) { + f11 = cuddT(f1); f10 = cuddE(f1); + } else { + f11 = empty; f10 = f1; + } + f0 = cuddE(f); + if ((int) f0->index == yindex || (int) f0->index == xindex) { + f01 = cuddT(f0); f00 = cuddE(f0); + } else { + f01 = empty; f00 = f0; + } + /* Create the new T child. */ + if (f01 == empty) { + newf1 = f10; + cuddSatInc(newf1->ref); + } else { + /* Check ylist for triple (yindex, f01, f10). */ + posn = ddHash(f01, f10, yshift); + /* For each element newf1 in collision list ylist[posn]. */ + newf1 = ylist[posn]; + /* Search the collision chain skipping the marked nodes. */ + while (newf1 != NULL) { + if (cuddT(newf1) == f01 && cuddE(newf1) == f10 && + (int) newf1->index == yindex) { + cuddSatInc(newf1->ref); + break; /* match */ + } + newf1 = newf1->next; + } /* while newf1 */ + if (newf1 == NULL) { /* no match */ + newf1 = cuddDynamicAllocNode(table); + if (newf1 == NULL) + goto zddSwapOutOfMem; + newf1->index = yindex; newf1->ref = 1; + cuddT(newf1) = f01; + cuddE(newf1) = f10; + /* Insert newf1 in the collision list ylist[pos]; + ** increase the ref counts of f01 and f10 + */ + newykeys++; + newf1->next = ylist[posn]; + ylist[posn] = newf1; + cuddSatInc(f01->ref); + cuddSatInc(f10->ref); + } + } + cuddT(f) = newf1; + + /* Do the same for f0. */ + /* Create the new E child. */ + if (f11 == empty) { + newf0 = f00; + cuddSatInc(newf0->ref); + } else { + /* Check ylist for triple (yindex, f11, f00). */ + posn = ddHash(f11, f00, yshift); + /* For each element newf0 in collision list ylist[posn]. */ + newf0 = ylist[posn]; + while (newf0 != NULL) { + if (cuddT(newf0) == f11 && cuddE(newf0) == f00 && + (int) newf0->index == yindex) { + cuddSatInc(newf0->ref); + break; /* match */ + } + newf0 = newf0->next; + } /* while newf0 */ + if (newf0 == NULL) { /* no match */ + newf0 = cuddDynamicAllocNode(table); + if (newf0 == NULL) + goto zddSwapOutOfMem; + newf0->index = yindex; newf0->ref = 1; + cuddT(newf0) = f11; cuddE(newf0) = f00; + /* Insert newf0 in the collision list ylist[posn]; + ** increase the ref counts of f11 and f00. + */ + newykeys++; + newf0->next = ylist[posn]; + ylist[posn] = newf0; + cuddSatInc(f11->ref); + cuddSatInc(f00->ref); + } + } + cuddE(f) = newf0; + + /* Re-insert the modified f in xlist. + ** The modified f does not already exists in xlist. + ** (Because of the uniqueness of the cofactors.) + */ + posn = ddHash(newf1, newf0, xshift); + newxkeys++; + f->next = xlist[posn]; + xlist[posn] = f; + f = next; + } /* while f != NULL */ + + /* GC the y layer and move the marked nodes to the x list. */ + + /* For each node f in ylist. */ + for (i = 0; i < yslots; i++) { + previous = NULL; + f = ylist[i]; + while (f != NULL) { + next = f->next; + if (f->ref == 0) { + cuddSatDec(cuddT(f)->ref); + cuddSatDec(cuddE(f)->ref); + cuddDeallocNode(table, f); + newykeys--; + if (previous == NULL) + ylist[i] = next; + else + previous->next = next; + } else if ((int) f->index == xindex) { /* move marked node */ + if (previous == NULL) + ylist[i] = next; + else + previous->next = next; + f1 = cuddT(f); + cuddSatDec(f1->ref); + /* Check ylist for triple (yindex, f1, empty). */ + posn = ddHash(f1, empty, yshift); + /* For each element newf1 in collision list ylist[posn]. */ + newf1 = ylist[posn]; + while (newf1 != NULL) { + if (cuddT(newf1) == f1 && cuddE(newf1) == empty && + (int) newf1->index == yindex) { + cuddSatInc(newf1->ref); + break; /* match */ + } + newf1 = newf1->next; + } /* while newf1 */ + if (newf1 == NULL) { /* no match */ + newf1 = cuddDynamicAllocNode(table); + if (newf1 == NULL) + goto zddSwapOutOfMem; + newf1->index = yindex; newf1->ref = 1; + cuddT(newf1) = f1; cuddE(newf1) = empty; + /* Insert newf1 in the collision list ylist[posn]; + ** increase the ref counts of f1 and empty. + */ + newykeys++; + newf1->next = ylist[posn]; + ylist[posn] = newf1; + if (posn == i && previous == NULL) + previous = newf1; + cuddSatInc(f1->ref); + cuddSatInc(empty->ref); + } + cuddT(f) = newf1; + f0 = cuddE(f); + /* Insert f in x list. */ + posn = ddHash(newf1, f0, xshift); + newxkeys++; + newykeys--; + f->next = xlist[posn]; + xlist[posn] = f; + } else { + previous = f; + } + f = next; + } /* while f */ + } /* for i */ + + /* Set the appropriate fields in table. */ + table->subtableZ[x].keys = newxkeys; + table->subtableZ[y].keys = newykeys; + + table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; + + /* Update univ section; univ[x] remains the same. */ + table->univ[y] = cuddT(table->univ[x]); + +#if 0 + (void) fprintf(table->out,"x = %d y = %d\n", x, y); + (void) Cudd_DebugCheck(table); + (void) Cudd_CheckKeys(table); +#endif + + return (table->keysZ); + +zddSwapOutOfMem: + (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); + + return (0); + +} /* end of cuddZddLinearInPlace */ + + +/**Function******************************************************************** + + Synopsis [Given xLow <= x <= xHigh moves x up and down between the + boundaries.] + + Description [Given xLow <= x <= xHigh moves x up and down between the + boundaries. Finds the best position and does the required changes. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddZddLinearAux( + DdManager * table, + int x, + int xLow, + int xHigh) +{ + Move *move; + Move *moveUp; /* list of up move */ + Move *moveDown; /* list of down move */ + + int initial_size; + int result; + + initial_size = table->keysZ; + +#ifdef DD_DEBUG + assert(table->subtableZ[x].keys > 0); +#endif + + moveDown = NULL; + moveUp = NULL; + + if (x == xLow) { + moveDown = cuddZddLinearDown(table, x, xHigh, NULL); + /* At this point x --> xHigh. */ + if (moveDown == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + /* Move backward and stop at best position. */ + result = cuddZddLinearBackward(table, initial_size, moveDown); + if (!result) + goto cuddZddLinearAuxOutOfMem; + + } else if (x == xHigh) { + moveUp = cuddZddLinearUp(table, x, xLow, NULL); + /* At this point x --> xLow. */ + if (moveUp == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + /* Move backward and stop at best position. */ + result = cuddZddLinearBackward(table, initial_size, moveUp); + if (!result) + goto cuddZddLinearAuxOutOfMem; + + } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ + moveDown = cuddZddLinearDown(table, x, xHigh, NULL); + /* At this point x --> xHigh. */ + if (moveDown == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + moveUp = cuddZddUndoMoves(table,moveDown); +#ifdef DD_DEBUG + assert(moveUp == NULL || moveUp->x == x); +#endif + moveUp = cuddZddLinearUp(table, x, xLow, moveUp); + if (moveUp == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + /* Move backward and stop at best position. */ + result = cuddZddLinearBackward(table, initial_size, moveUp); + if (!result) + goto cuddZddLinearAuxOutOfMem; + + } else { + moveUp = cuddZddLinearUp(table, x, xLow, NULL); + /* At this point x --> xHigh. */ + if (moveUp == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + /* Then move up. */ + moveDown = cuddZddUndoMoves(table,moveUp); +#ifdef DD_DEBUG + assert(moveDown == NULL || moveDown->y == x); +#endif + moveDown = cuddZddLinearDown(table, x, xHigh, moveDown); + if (moveDown == (Move *) CUDD_OUT_OF_MEM) + goto cuddZddLinearAuxOutOfMem; + /* Move backward and stop at best position. */ + result = cuddZddLinearBackward(table, initial_size, moveDown); + if (!result) + goto cuddZddLinearAuxOutOfMem; + } + + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *)moveDown); + moveDown = move; + } + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *)moveUp); + moveUp = move; + } + + return(1); + +cuddZddLinearAuxOutOfMem: + if (moveDown != (Move *) CUDD_OUT_OF_MEM) { + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *)moveDown); + moveDown = move; + } + } + if (moveUp != (Move *) CUDD_OUT_OF_MEM) { + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *)moveUp); + moveUp = move; + } + } + + return(0); + +} /* end of cuddZddLinearAux */ + + +/**Function******************************************************************** + + Synopsis [Sifts a variable up applying the XOR transformation.] + + Description [Sifts a variable up applying the XOR + transformation. Moves y up until either it reaches the bound (xLow) + or the size of the ZDD heap increases too much. Returns the set of + moves in case of success; NULL if memory is full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +cuddZddLinearUp( + DdManager * table, + int y, + int xLow, + Move * prevMoves) +{ + Move *moves; + Move *move; + int x; + int size, newsize; + int limitSize; + + moves = prevMoves; + limitSize = table->keysZ; + + x = cuddZddNextLow(table, y); + while (x >= xLow) { + size = cuddZddSwapInPlace(table, x, y); + if (size == 0) + goto cuddZddLinearUpOutOfMem; + newsize = cuddZddLinearInPlace(table, x, y); + if (newsize == 0) + goto cuddZddLinearUpOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) + goto cuddZddLinearUpOutOfMem; + move->x = x; + move->y = y; + move->next = moves; + moves = move; + move->flags = CUDD_SWAP_MOVE; + if (newsize > size) { + /* Undo transformation. The transformation we apply is + ** its own inverse. Hence, we just apply the transformation + ** again. + */ + newsize = cuddZddLinearInPlace(table,x,y); + if (newsize == 0) goto cuddZddLinearUpOutOfMem; +#ifdef DD_DEBUG + if (newsize != size) { + (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize); + } +#endif + } else { + size = newsize; + move->flags = CUDD_LINEAR_TRANSFORM_MOVE; + } + move->size = size; + + if ((double)size > (double)limitSize * table->maxGrowth) + break; + if (size < limitSize) + limitSize = size; + + y = x; + x = cuddZddNextLow(table, y); + } + return(moves); + +cuddZddLinearUpOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *)moves); + moves = move; + } + return((Move *) CUDD_OUT_OF_MEM); + +} /* end of cuddZddLinearUp */ + + +/**Function******************************************************************** + + Synopsis [Sifts a variable down and applies the XOR transformation.] + + Description [Sifts a variable down. Moves x down until either it + reaches the bound (xHigh) or the size of the ZDD heap increases too + much. Returns the set of moves in case of success; NULL if memory is + full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +cuddZddLinearDown( + DdManager * table, + int x, + int xHigh, + Move * prevMoves) +{ + Move *moves; + Move *move; + int y; + int size, newsize; + int limitSize; + + moves = prevMoves; + limitSize = table->keysZ; + + y = cuddZddNextHigh(table, x); + while (y <= xHigh) { + size = cuddZddSwapInPlace(table, x, y); + if (size == 0) + goto cuddZddLinearDownOutOfMem; + newsize = cuddZddLinearInPlace(table, x, y); + if (newsize == 0) + goto cuddZddLinearDownOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) + goto cuddZddLinearDownOutOfMem; + move->x = x; + move->y = y; + move->next = moves; + moves = move; + move->flags = CUDD_SWAP_MOVE; + if (newsize > size) { + /* Undo transformation. The transformation we apply is + ** its own inverse. Hence, we just apply the transformation + ** again. + */ + newsize = cuddZddLinearInPlace(table,x,y); + if (newsize == 0) goto cuddZddLinearDownOutOfMem; + if (newsize != size) { + (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize); + } + } else { + size = newsize; + move->flags = CUDD_LINEAR_TRANSFORM_MOVE; + } + move->size = size; + + if ((double)size > (double)limitSize * table->maxGrowth) + break; + if (size < limitSize) + limitSize = size; + + x = y; + y = cuddZddNextHigh(table, x); + } + return(moves); + +cuddZddLinearDownOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *)moves); + moves = move; + } + return((Move *) CUDD_OUT_OF_MEM); + +} /* end of cuddZddLinearDown */ + + +/**Function******************************************************************** + + Synopsis [Given a set of moves, returns the ZDD heap to the position + giving the minimum size.] + + Description [Given a set of moves, returns the ZDD heap to the + position giving the minimum size. In case of ties, returns to the + closest position giving the minimum size. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddZddLinearBackward( + DdManager * table, + int size, + Move * moves) +{ + Move *move; + int res; + + /* Find the minimum size among moves. */ + for (move = moves; move != NULL; move = move->next) { + if (move->size < size) { + size = move->size; + } + } + + for (move = moves; move != NULL; move = move->next) { + if (move->size == size) return(1); + if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { + res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); + } + res = cuddZddSwapInPlace(table, move->x, move->y); + if (!res) + return(0); + if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) { + res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); + if (!res) return(0); + } + } + + return(1); + +} /* end of cuddZddLinearBackward */ + + +/**Function******************************************************************** + + Synopsis [Given a set of moves, returns the ZDD heap to the order + in effect before the moves.] + + Description [Given a set of moves, returns the ZDD heap to the + order in effect before the moves. Returns 1 in case of success; + 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static Move* +cuddZddUndoMoves( + DdManager * table, + Move * moves) +{ + Move *invmoves = NULL; + Move *move; + Move *invmove; + int size; + + for (move = moves; move != NULL; move = move->next) { + invmove = (Move *) cuddDynamicAllocNode(table); + if (invmove == NULL) goto cuddZddUndoMovesOutOfMem; + invmove->x = move->x; + invmove->y = move->y; + invmove->next = invmoves; + invmoves = invmove; + if (move->flags == CUDD_SWAP_MOVE) { + invmove->flags = CUDD_SWAP_MOVE; + size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); + if (!size) goto cuddZddUndoMovesOutOfMem; + } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { + invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE; + size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); + if (!size) goto cuddZddUndoMovesOutOfMem; + size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); + if (!size) goto cuddZddUndoMovesOutOfMem; + } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */ +#ifdef DD_DEBUG + (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n"); +#endif + invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE; + size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); + if (!size) goto cuddZddUndoMovesOutOfMem; + size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); + if (!size) goto cuddZddUndoMovesOutOfMem; + } + invmove->size = size; + } + + return(invmoves); + +cuddZddUndoMovesOutOfMem: + while (invmoves != NULL) { + move = invmoves->next; + cuddDeallocNode(table, (DdNode *) invmoves); + invmoves = move; + } + return((Move *) CUDD_OUT_OF_MEM); + +} /* end of cuddZddUndoMoves */ + diff --git a/abc70930/src/bdd/cudd/cuddZddMisc.c b/abc70930/src/bdd/cudd/cuddZddMisc.c new file mode 100644 index 00000000..6a4ddd09 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddZddMisc.c @@ -0,0 +1,252 @@ +/**CFile*********************************************************************** + + FileName [cuddZddMisc.c] + + PackageName [cudd] + + Synopsis [.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddDagSize() +
        • Cudd_zddCountMinterm() +
        • Cudd_zddPrintSubtable() +
        + Internal procedures included in this module: +
          +
        + Static procedures included in this module: +
          +
        • cuddZddDagInt() +
        + ] + + SeeAlso [] + + Author [Hyong-Kyoon Shin, In-Ho Moon] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddMisc.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int cuddZddDagInt ARGS((DdNode *n, st_table *tab)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Counts the number of nodes in a ZDD.] + + Description [Counts the number of nodes in a ZDD. This function + duplicates Cudd_DagSize and is only retained for compatibility.] + + SideEffects [None] + + SeeAlso [Cudd_DagSize] + +******************************************************************************/ +int +Cudd_zddDagSize( + DdNode * p_node) +{ + + int i; + st_table *table; + + table = st_init_table(st_ptrcmp, st_ptrhash); + i = cuddZddDagInt(p_node, table); + st_free_table(table); + return(i); + +} /* end of Cudd_zddDagSize */ + + +/**Function******************************************************************** + + Synopsis [Counts the number of minterms of a ZDD.] + + Description [Counts the number of minterms of the ZDD rooted at + node. This procedure takes a parameter + path that specifies how many variables are in the + support of the function. If the procedure runs out of memory, it + returns (double) CUDD_OUT_OF_MEM.] + + SideEffects [None] + + SeeAlso [Cudd_zddCountDouble] + +******************************************************************************/ +double +Cudd_zddCountMinterm( + DdManager * zdd, + DdNode * node, + int path) +{ + double dc_var, minterms; + + dc_var = (double)((double)(zdd->sizeZ) - (double)path); + minterms = Cudd_zddCountDouble(zdd, node) / pow(2.0, dc_var); + return(minterms); + +} /* end of Cudd_zddCountMinterm */ + + +/**Function******************************************************************** + + Synopsis [Prints the ZDD table.] + + Description [Prints the ZDD table for debugging purposes.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +Cudd_zddPrintSubtable( + DdManager * table) +{ + int i, j; + DdNode *z1, *z1_next, *base; + DdSubtable *ZSubTable; + + base = table->one; + for (i = table->sizeZ - 1; i >= 0; i--) { + ZSubTable = &(table->subtableZ[i]); + printf("subtable[%d]:\n", i); + for (j = ZSubTable->slots - 1; j >= 0; j--) { + z1 = ZSubTable->nodelist[j]; + while (z1 != NIL(DdNode)) { + (void) fprintf(table->out, +#if SIZEOF_VOID_P == 8 + "ID = 0x%lx\tindex = %d\tr = %d\t", + (unsigned long) z1 / (unsigned long) sizeof(DdNode), + z1->index, z1->ref); +#else + "ID = 0x%x\tindex = %d\tr = %d\t", + (unsigned) z1 / (unsigned) sizeof(DdNode), + z1->index, z1->ref); +#endif + z1_next = cuddT(z1); + if (Cudd_IsConstant(z1_next)) { + (void) fprintf(table->out, "T = %d\t\t", + (z1_next == base)); + } + else { +#if SIZEOF_VOID_P == 8 + (void) fprintf(table->out, "T = 0x%lx\t", + (unsigned long) z1_next / (unsigned long) sizeof(DdNode)); +#else + (void) fprintf(table->out, "T = 0x%x\t", + (unsigned) z1_next / (unsigned) sizeof(DdNode)); +#endif + } + z1_next = cuddE(z1); + if (Cudd_IsConstant(z1_next)) { + (void) fprintf(table->out, "E = %d\n", + (z1_next == base)); + } + else { +#if SIZEOF_VOID_P == 8 + (void) fprintf(table->out, "E = 0x%lx\n", + (unsigned long) z1_next / (unsigned long) sizeof(DdNode)); +#else + (void) fprintf(table->out, "E = 0x%x\n", + (unsigned) z1_next / (unsigned) sizeof(DdNode)); +#endif + } + + z1_next = z1->next; + z1 = z1_next; + } + } + } + putchar('\n'); + +} /* Cudd_zddPrintSubtable */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddDagSize.] + + Description [Performs the recursive step of Cudd_zddDagSize. Does + not check for out-of-memory conditions.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddZddDagInt( + DdNode * n, + st_table * tab) +{ + if (n == NIL(DdNode)) + return(0); + + if (st_is_member(tab, (char *)n) == 1) + return(0); + + if (Cudd_IsConstant(n)) + return(0); + + (void)st_insert(tab, (char *)n, NIL(char)); + return(1 + cuddZddDagInt(cuddT(n), tab) + + cuddZddDagInt(cuddE(n), tab)); + +} /* cuddZddDagInt */ + diff --git a/abc70930/src/bdd/cudd/cuddZddPort.c b/abc70930/src/bdd/cudd/cuddZddPort.c new file mode 100644 index 00000000..6d4a3236 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddZddPort.c @@ -0,0 +1,354 @@ +/**CFile*********************************************************************** + + FileName [cuddZddPort.c] + + PackageName [cudd] + + Synopsis [Functions that translate BDDs to ZDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddPortFromBdd() +
        • Cudd_zddPortToBdd() +
        + Internal procedures included in this module: +
          +
        + Static procedures included in this module: +
          +
        • zddPortFromBddStep() +
        • zddPortToBddStep() +
        + ] + + SeeAlso [] + + Author [Hyong-kyoon Shin, In-Ho Moon] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddPort.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * zddPortFromBddStep ARGS((DdManager *dd, DdNode *B, int expected)); +static DdNode * zddPortToBddStep ARGS((DdManager *dd, DdNode *f, int depth)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Converts a BDD into a ZDD.] + + Description [Converts a BDD into a ZDD. This function assumes that + there is a one-to-one correspondence between the BDD variables and the + ZDD variables, and that the variable order is the same for both types + of variables. These conditions are established if the ZDD variables + are created by one call to Cudd_zddVarsFromBddVars with multiplicity = + 1. Returns a pointer to the resulting ZDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddVarsFromBddVars] + +******************************************************************************/ +DdNode * +Cudd_zddPortFromBdd( + DdManager * dd, + DdNode * B) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = zddPortFromBddStep(dd,B,0); + } while (dd->reordered == 1); + + return(res); + +} /* end of Cudd_zddPortFromBdd */ + + +/**Function******************************************************************** + + Synopsis [Converts a ZDD into a BDD.] + + Description [Converts a ZDD into a BDD. Returns a pointer to the resulting + ZDD if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddPortFromBdd] + +******************************************************************************/ +DdNode * +Cudd_zddPortToBdd( + DdManager * dd, + DdNode * f) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = zddPortToBddStep(dd,f,0); + } while (dd->reordered == 1); + + return(res); + +} /* end of Cudd_zddPortToBdd */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddPortFromBdd.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +zddPortFromBddStep( + DdManager * dd, + DdNode * B, + int expected) +{ + DdNode *res, *prevZdd, *t, *e; + DdNode *Breg, *Bt, *Be; + int id, level; + + statLine(dd); + /* Terminal cases. */ + if (B == Cudd_Not(DD_ONE(dd))) + return(DD_ZERO(dd)); + if (B == DD_ONE(dd)) { + if (expected >= dd->sizeZ) { + return(DD_ONE(dd)); + } else { + return(dd->univ[expected]); + } + } + + Breg = Cudd_Regular(B); + + /* Computed table look-up. */ + res = cuddCacheLookup1Zdd(dd,Cudd_zddPortFromBdd,B); + if (res != NULL) { + level = cuddI(dd,Breg->index); + /* Adding DC vars. */ + if (expected < level) { + /* Add suppressed variables. */ + cuddRef(res); + for (level--; level >= expected; level--) { + prevZdd = res; + id = dd->invperm[level]; + res = cuddZddGetNode(dd, id, prevZdd, prevZdd); + if (res == NULL) { + Cudd_RecursiveDerefZdd(dd, prevZdd); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDerefZdd(dd, prevZdd); + } + cuddDeref(res); + } + return(res); + } /* end of cache look-up */ + + if (Cudd_IsComplement(B)) { + Bt = Cudd_Not(cuddT(Breg)); + Be = Cudd_Not(cuddE(Breg)); + } else { + Bt = cuddT(Breg); + Be = cuddE(Breg); + } + + id = Breg->index; + level = cuddI(dd,id); + t = zddPortFromBddStep(dd, Bt, level+1); + if (t == NULL) return(NULL); + cuddRef(t); + e = zddPortFromBddStep(dd, Be, level+1); + if (e == NULL) { + Cudd_RecursiveDerefZdd(dd, t); + return(NULL); + } + cuddRef(e); + res = cuddZddGetNode(dd, id, t, e); + if (res == NULL) { + Cudd_RecursiveDerefZdd(dd, t); + Cudd_RecursiveDerefZdd(dd, e); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDerefZdd(dd, t); + Cudd_RecursiveDerefZdd(dd, e); + + cuddCacheInsert1(dd,Cudd_zddPortFromBdd,B,res); + + for (level--; level >= expected; level--) { + prevZdd = res; + id = dd->invperm[level]; + res = cuddZddGetNode(dd, id, prevZdd, prevZdd); + if (res == NULL) { + Cudd_RecursiveDerefZdd(dd, prevZdd); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDerefZdd(dd, prevZdd); + } + + cuddDeref(res); + return(res); + +} /* end of zddPortFromBddStep */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddPortToBdd.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +zddPortToBddStep( + DdManager * dd /* manager */, + DdNode * f /* ZDD to be converted */, + int depth /* recursion depth */) +{ + DdNode *one, *zero, *T, *E, *res, *var; + unsigned int index; + unsigned int level; + + statLine(dd); + one = DD_ONE(dd); + zero = DD_ZERO(dd); + if (f == zero) return(Cudd_Not(one)); + + if (depth == dd->sizeZ) return(one); + + index = dd->invpermZ[depth]; + level = cuddIZ(dd,f->index); + var = cuddUniqueInter(dd,index,one,Cudd_Not(one)); + if (var == NULL) return(NULL); + cuddRef(var); + + if (level > (unsigned) depth) { + E = zddPortToBddStep(dd,f,depth+1); + if (E == NULL) { + Cudd_RecursiveDeref(dd,var); + return(NULL); + } + cuddRef(E); + res = cuddBddIteRecur(dd,var,Cudd_Not(one),E); + if (res == NULL) { + Cudd_RecursiveDeref(dd,var); + Cudd_RecursiveDeref(dd,E); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd,var); + Cudd_RecursiveDeref(dd,E); + cuddDeref(res); + return(res); + } + + res = cuddCacheLookup1(dd,Cudd_zddPortToBdd,f); + if (res != NULL) { + Cudd_RecursiveDeref(dd,var); + return(res); + } + + T = zddPortToBddStep(dd,cuddT(f),depth+1); + if (T == NULL) { + Cudd_RecursiveDeref(dd,var); + return(NULL); + } + cuddRef(T); + E = zddPortToBddStep(dd,cuddE(f),depth+1); + if (E == NULL) { + Cudd_RecursiveDeref(dd,var); + Cudd_RecursiveDeref(dd,T); + return(NULL); + } + cuddRef(E); + + res = cuddBddIteRecur(dd,var,T,E); + if (res == NULL) { + Cudd_RecursiveDeref(dd,var); + Cudd_RecursiveDeref(dd,T); + Cudd_RecursiveDeref(dd,E); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDeref(dd,var); + Cudd_RecursiveDeref(dd,T); + Cudd_RecursiveDeref(dd,E); + cuddDeref(res); + + cuddCacheInsert1(dd,Cudd_zddPortToBdd,f,res); + + return(res); + +} /* end of zddPortToBddStep */ + diff --git a/abc70930/src/bdd/cudd/cuddZddReord.c b/abc70930/src/bdd/cudd/cuddZddReord.c new file mode 100644 index 00000000..e2da37f2 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddZddReord.c @@ -0,0 +1,1633 @@ +/**CFile*********************************************************************** + + FileName [cuddZddReord.c] + + PackageName [cudd] + + Synopsis [Procedures for dynamic variable ordering of ZDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddReduceHeap() +
        • Cudd_zddShuffleHeap() +
        + Internal procedures included in this module: +
          +
        • cuddZddAlignToBdd() +
        • cuddZddNextHigh() +
        • cuddZddNextLow() +
        • cuddZddUniqueCompare() +
        • cuddZddSwapInPlace() +
        • cuddZddSwapping() +
        • cuddZddSifting() +
        + Static procedures included in this module: +
          +
        • zddSwapAny() +
        • cuddZddSiftingAux() +
        • cuddZddSiftingUp() +
        • cuddZddSiftingDown() +
        • cuddZddSiftingBackward() +
        • zddReorderPreprocess() +
        • zddReorderPostprocess() +
        • zddShuffle() +
        • zddSiftUp() +
        + ] + + SeeAlso [] + + Author [Hyong-Kyoon Shin, In-Ho Moon] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define DD_MAX_SUBTABLE_SPARSITY 8 +#define DD_SHRINK_FACTOR 2 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; +#endif + +int *zdd_entry; + +int zddTotalNumberSwapping; + +static DdNode *empty; + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static Move * zddSwapAny ARGS((DdManager *table, int x, int y)); +static int cuddZddSiftingAux ARGS((DdManager *table, int x, int x_low, int x_high)); +static Move * cuddZddSiftingUp ARGS((DdManager *table, int x, int x_low, int initial_size)); +static Move * cuddZddSiftingDown ARGS((DdManager *table, int x, int x_high, int initial_size)); +static int cuddZddSiftingBackward ARGS((DdManager *table, Move *moves, int size)); +static void zddReorderPreprocess ARGS((DdManager *table)); +static int zddReorderPostprocess ARGS((DdManager *table)); +static int zddShuffle ARGS((DdManager *table, int *permutation)); +static int zddSiftUp ARGS((DdManager *table, int x, int xLow)); +static void zddFixTree ARGS((DdManager *table, MtrNode *treenode)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Main dynamic reordering routine for ZDDs.] + + Description [Main dynamic reordering routine for ZDDs. + Calls one of the possible reordering procedures: +
          +
        • Swapping +
        • Sifting +
        • Symmetric Sifting +
        + + For sifting and symmetric sifting it is possible to request reordering + to convergence.

        + + The core of all methods is the reordering procedure + cuddZddSwapInPlace() which swaps two adjacent variables. + Returns 1 in case of success; 0 otherwise. In the case of symmetric + sifting (with and without convergence) returns 1 plus the number of + symmetric variables, in case of success.] + + SideEffects [Changes the variable order for all ZDDs and clears + the cache.] + +******************************************************************************/ +int +Cudd_zddReduceHeap( + DdManager * table /* DD manager */, + Cudd_ReorderingType heuristic /* method used for reordering */, + int minsize /* bound below which no reordering occurs */) +{ + DdHook *hook; + int result; + unsigned int nextDyn; +#ifdef DD_STATS + unsigned int initialSize; + unsigned int finalSize; +#endif + long localTime; + + /* Don't reorder if there are too many dead nodes. */ + if (table->keysZ - table->deadZ < (unsigned) minsize) + return(1); + + if (heuristic == CUDD_REORDER_SAME) { + heuristic = table->autoMethodZ; + } + if (heuristic == CUDD_REORDER_NONE) { + return(1); + } + + /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore + ** we count it. + */ + table->reorderings++; + empty = table->zero; + + localTime = util_cpu_time(); + + /* Run the hook functions. */ + hook = table->preReorderingHook; + while (hook != NULL) { + int res = (hook->f)(table, "ZDD", (void *)heuristic); + if (res == 0) return(0); + hook = hook->next; + } + + /* Clear the cache and collect garbage. */ + zddReorderPreprocess(table); + zddTotalNumberSwapping = 0; + +#ifdef DD_STATS + initialSize = table->keysZ; + + switch(heuristic) { + case CUDD_REORDER_RANDOM: + case CUDD_REORDER_RANDOM_PIVOT: + (void) fprintf(table->out,"#:I_RANDOM "); + break; + case CUDD_REORDER_SIFT: + case CUDD_REORDER_SIFT_CONVERGE: + case CUDD_REORDER_SYMM_SIFT: + case CUDD_REORDER_SYMM_SIFT_CONV: + (void) fprintf(table->out,"#:I_SIFTING "); + break; + case CUDD_REORDER_LINEAR: + case CUDD_REORDER_LINEAR_CONVERGE: + (void) fprintf(table->out,"#:I_LINSIFT "); + break; + default: + (void) fprintf(table->err,"Unsupported ZDD reordering method\n"); + return(0); + } + (void) fprintf(table->out,"%8d: initial size",initialSize); +#endif + + result = cuddZddTreeSifting(table,heuristic); + +#ifdef DD_STATS + (void) fprintf(table->out,"\n"); + finalSize = table->keysZ; + (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); + (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", + ((double)(util_cpu_time() - localTime)/1000.0)); + (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", + zddTotalNumberSwapping); +#endif + + if (result == 0) + return(0); + + if (!zddReorderPostprocess(table)) + return(0); + + if (table->realignZ) { + if (!cuddBddAlignToZdd(table)) + return(0); + } + + nextDyn = table->keysZ * DD_DYN_RATIO; + if (table->reorderings < 20 || nextDyn > table->nextDyn) + table->nextDyn = nextDyn; + else + table->nextDyn += 20; + + table->reordered = 1; + + /* Run hook functions. */ + hook = table->postReorderingHook; + while (hook != NULL) { + int res = (hook->f)(table, "ZDD", (void *)localTime); + if (res == 0) return(0); + hook = hook->next; + } + /* Update cumulative reordering time. */ + table->reordTime += util_cpu_time() - localTime; + + return(result); + +} /* end of Cudd_zddReduceHeap */ + + +/**Function******************************************************************** + + Synopsis [Reorders ZDD variables according to given permutation.] + + Description [Reorders ZDD variables according to given permutation. + The i-th entry of the permutation array contains the index of the variable + that should be brought to the i-th level. The size of the array should be + equal or greater to the number of variables currently in use. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [Changes the ZDD variable order for all diagrams and clears + the cache.] + + SeeAlso [Cudd_zddReduceHeap] + +******************************************************************************/ +int +Cudd_zddShuffleHeap( + DdManager * table /* DD manager */, + int * permutation /* required variable permutation */) +{ + + int result; + + empty = table->zero; + zddReorderPreprocess(table); + + result = zddShuffle(table,permutation); + + if (!zddReorderPostprocess(table)) return(0); + + return(result); + +} /* end of Cudd_zddShuffleHeap */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Reorders ZDD variables according to the order of the BDD + variables.] + + Description [Reorders ZDD variables according to the order of the + BDD variables. This function can be called at the end of BDD + reordering to insure that the order of the ZDD variables is + consistent with the order of the BDD variables. The number of ZDD + variables must be a multiple of the number of BDD variables. Let + M be the ratio of the two numbers. cuddZddAlignToBdd + then considers the ZDD variables from M*i to + (M+1)*i-1 as corresponding to BDD variable + i. This function should be normally called from + Cudd_ReduceHeap, which clears the cache. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [Changes the ZDD variable order for all diagrams and performs + garbage collection of the ZDD unique table.] + + SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap] + +******************************************************************************/ +int +cuddZddAlignToBdd( + DdManager * table /* DD manager */) +{ + int *invpermZ; /* permutation array */ + int M; /* ratio of ZDD variables to BDD variables */ + int i,j; /* loop indices */ + int result; /* return value */ + + /* We assume that a ratio of 0 is OK. */ + if (table->sizeZ == 0) + return(1); + + empty = table->zero; + M = table->sizeZ / table->size; + /* Check whether the number of ZDD variables is a multiple of the + ** number of BDD variables. + */ + if (M * table->size != table->sizeZ) + return(0); + /* Create and initialize the inverse permutation array. */ + invpermZ = ALLOC(int,table->sizeZ); + if (invpermZ == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (i = 0; i < table->size; i++) { + int index = table->invperm[i]; + int indexZ = index * M; + int levelZ = table->permZ[indexZ]; + levelZ = (levelZ / M) * M; + for (j = 0; j < M; j++) { + invpermZ[M * i + j] = table->invpermZ[levelZ + j]; + } + } + /* Eliminate dead nodes. Do not scan the cache again, because we + ** assume that Cudd_ReduceHeap has already cleared it. + */ + cuddGarbageCollectZdd(table,0); + + result = zddShuffle(table, invpermZ); + FREE(invpermZ); + /* Fix the ZDD variable group tree. */ + zddFixTree(table,table->treeZ); + return(result); + +} /* end of cuddZddAlignToBdd */ + + +/**Function******************************************************************** + + Synopsis [Finds the next subtable with a larger index.] + + Description [Finds the next subtable with a larger index. Returns the + index.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddNextHigh( + DdManager * table, + int x) +{ + return(x + 1); + +} /* end of cuddZddNextHigh */ + + +/**Function******************************************************************** + + Synopsis [Finds the next subtable with a smaller index.] + + Description [Finds the next subtable with a smaller index. Returns the + index.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddNextLow( + DdManager * table, + int x) +{ + return(x - 1); + +} /* end of cuddZddNextLow */ + + +/**Function******************************************************************** + + Synopsis [Comparison function used by qsort.] + + Description [Comparison function used by qsort to order the + variables according to the number of keys in the subtables. + Returns the difference in number of keys between the two + variables being compared.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddUniqueCompare( + int * ptr_x, + int * ptr_y) +{ + return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]); + +} /* end of cuddZddUniqueCompare */ + + +/**Function******************************************************************** + + Synopsis [Swaps two adjacent variables.] + + Description [Swaps two adjacent variables. It assumes that no dead + nodes are present on entry to this procedure. The procedure then + guarantees that no dead nodes will be present when it terminates. + cuddZddSwapInPlace assumes that x < y. Returns the number of keys in + the table if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddSwapInPlace( + DdManager * table, + int x, + int y) +{ + DdNodePtr *xlist, *ylist; + int xindex, yindex; + int xslots, yslots; + int xshift, yshift; + int oldxkeys, oldykeys; + int newxkeys, newykeys; + int i; + int posn; + DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; + DdNode *newf1, *newf0, *next; + DdNodePtr g, *lastP, *previousP; + +#ifdef DD_DEBUG + assert(x < y); + assert(cuddZddNextHigh(table,x) == y); + assert(table->subtableZ[x].keys != 0); + assert(table->subtableZ[y].keys != 0); + assert(table->subtableZ[x].dead == 0); + assert(table->subtableZ[y].dead == 0); +#endif + + zddTotalNumberSwapping++; + + /* Get parameters of x subtable. */ + xindex = table->invpermZ[x]; + xlist = table->subtableZ[x].nodelist; + oldxkeys = table->subtableZ[x].keys; + xslots = table->subtableZ[x].slots; + xshift = table->subtableZ[x].shift; + newxkeys = 0; + + yindex = table->invpermZ[y]; + ylist = table->subtableZ[y].nodelist; + oldykeys = table->subtableZ[y].keys; + yslots = table->subtableZ[y].slots; + yshift = table->subtableZ[y].shift; + newykeys = oldykeys; + + /* The nodes in the x layer that don't depend on y directly + ** will stay there; the others are put in a chain. + ** The chain is handled as a FIFO; g points to the beginning and + ** last points to the end. + */ + + g = NULL; + lastP = &g; + for (i = 0; i < xslots; i++) { + previousP = &(xlist[i]); + f = *previousP; + while (f != NULL) { + next = f->next; + f1 = cuddT(f); f0 = cuddE(f); + if ((f1->index != (DdHalfWord) yindex) && + (f0->index != (DdHalfWord) yindex)) { /* stays */ + newxkeys++; + *previousP = f; + previousP = &(f->next); + } else { + f->index = yindex; + *lastP = f; + lastP = &(f->next); + } + f = next; + } /* while there are elements in the collision chain */ + *previousP = NULL; + } /* for each slot of the x subtable */ + *lastP = NULL; + + +#ifdef DD_COUNT + table->swapSteps += oldxkeys - newxkeys; +#endif + /* Take care of the x nodes that must be re-expressed. + ** They form a linked list pointed by g. Their index has been + ** changed to yindex already. + */ + f = g; + while (f != NULL) { + next = f->next; + /* Find f1, f0, f11, f10, f01, f00. */ + f1 = cuddT(f); + if ((int) f1->index == yindex) { + f11 = cuddT(f1); f10 = cuddE(f1); + } else { + f11 = empty; f10 = f1; + } + f0 = cuddE(f); + if ((int) f0->index == yindex) { + f01 = cuddT(f0); f00 = cuddE(f0); + } else { + f01 = empty; f00 = f0; + } + + /* Decrease ref count of f1. */ + cuddSatDec(f1->ref); + /* Create the new T child. */ + if (f11 == empty) { + if (f01 != empty) { + newf1 = f01; + cuddSatInc(newf1->ref); + } + /* else case was already handled when finding nodes + ** with both children below level y + */ + } else { + /* Check xlist for triple (xindex, f11, f01). */ + posn = ddHash(f11, f01, xshift); + /* For each element newf1 in collision list xlist[posn]. */ + newf1 = xlist[posn]; + while (newf1 != NULL) { + if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { + cuddSatInc(newf1->ref); + break; /* match */ + } + newf1 = newf1->next; + } /* while newf1 */ + if (newf1 == NULL) { /* no match */ + newf1 = cuddDynamicAllocNode(table); + if (newf1 == NULL) + goto zddSwapOutOfMem; + newf1->index = xindex; newf1->ref = 1; + cuddT(newf1) = f11; + cuddE(newf1) = f01; + /* Insert newf1 in the collision list xlist[pos]; + ** increase the ref counts of f11 and f01 + */ + newxkeys++; + newf1->next = xlist[posn]; + xlist[posn] = newf1; + cuddSatInc(f11->ref); + cuddSatInc(f01->ref); + } + } + cuddT(f) = newf1; + + /* Do the same for f0. */ + /* Decrease ref count of f0. */ + cuddSatDec(f0->ref); + /* Create the new E child. */ + if (f10 == empty) { + newf0 = f00; + cuddSatInc(newf0->ref); + } else { + /* Check xlist for triple (xindex, f10, f00). */ + posn = ddHash(f10, f00, xshift); + /* For each element newf0 in collision list xlist[posn]. */ + newf0 = xlist[posn]; + while (newf0 != NULL) { + if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { + cuddSatInc(newf0->ref); + break; /* match */ + } + newf0 = newf0->next; + } /* while newf0 */ + if (newf0 == NULL) { /* no match */ + newf0 = cuddDynamicAllocNode(table); + if (newf0 == NULL) + goto zddSwapOutOfMem; + newf0->index = xindex; newf0->ref = 1; + cuddT(newf0) = f10; cuddE(newf0) = f00; + /* Insert newf0 in the collision list xlist[posn]; + ** increase the ref counts of f10 and f00. + */ + newxkeys++; + newf0->next = xlist[posn]; + xlist[posn] = newf0; + cuddSatInc(f10->ref); + cuddSatInc(f00->ref); + } + } + cuddE(f) = newf0; + + /* Insert the modified f in ylist. + ** The modified f does not already exists in ylist. + ** (Because of the uniqueness of the cofactors.) + */ + posn = ddHash(newf1, newf0, yshift); + newykeys++; + f->next = ylist[posn]; + ylist[posn] = f; + f = next; + } /* while f != NULL */ + + /* GC the y layer. */ + + /* For each node f in ylist. */ + for (i = 0; i < yslots; i++) { + previousP = &(ylist[i]); + f = *previousP; + while (f != NULL) { + next = f->next; + if (f->ref == 0) { + cuddSatDec(cuddT(f)->ref); + cuddSatDec(cuddE(f)->ref); + cuddDeallocNode(table, f); + newykeys--; + } else { + *previousP = f; + previousP = &(f->next); + } + f = next; + } /* while f */ + *previousP = NULL; + } /* for i */ + + /* Set the appropriate fields in table. */ + table->subtableZ[x].nodelist = ylist; + table->subtableZ[x].slots = yslots; + table->subtableZ[x].shift = yshift; + table->subtableZ[x].keys = newykeys; + table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; + + table->subtableZ[y].nodelist = xlist; + table->subtableZ[y].slots = xslots; + table->subtableZ[y].shift = xshift; + table->subtableZ[y].keys = newxkeys; + table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; + + table->permZ[xindex] = y; table->permZ[yindex] = x; + table->invpermZ[x] = yindex; table->invpermZ[y] = xindex; + + table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; + + /* Update univ section; univ[x] remains the same. */ + table->univ[y] = cuddT(table->univ[x]); + + return (table->keysZ); + +zddSwapOutOfMem: + (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); + + return (0); + +} /* end of cuddZddSwapInPlace */ + + +/**Function******************************************************************** + + Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.] + + Description [Implementation of Plessier's algorithm that reorders + variables by a sequence of (non-adjacent) swaps. +

          +
        1. Select two variables (RANDOM or HEURISTIC). +
        2. Permute these variables. +
        3. If the nodes have decreased accept the permutation. +
        4. Otherwise reconstruct the original heap. +
        5. Loop. +
        + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddSwapping( + DdManager * table, + int lower, + int upper, + Cudd_ReorderingType heuristic) +{ + int i, j; + int max, keys; + int nvars; + int x, y; + int iterate; + int previousSize; + Move *moves, *move; + int pivot; + int modulo; + int result; + +#ifdef DD_DEBUG + /* Sanity check */ + assert(lower >= 0 && upper < table->sizeZ && lower <= upper); +#endif + + nvars = upper - lower + 1; + iterate = nvars; + + for (i = 0; i < iterate; i++) { + if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { + /* Find pivot <= id with maximum keys. */ + for (max = -1, j = lower; j <= upper; j++) { + if ((keys = table->subtableZ[j].keys) > max) { + max = keys; + pivot = j; + } + } + + modulo = upper - pivot; + if (modulo == 0) { + y = pivot; /* y = nvars-1 */ + } else { + /* y = random # from {pivot+1 .. nvars-1} */ + y = pivot + 1 + (int) (Cudd_Random() % modulo); + } + + modulo = pivot - lower - 1; + if (modulo < 1) { /* if pivot = 1 or 0 */ + x = lower; + } else { + do { /* x = random # from {0 .. pivot-2} */ + x = (int) Cudd_Random() % modulo; + } while (x == y); + /* Is this condition really needed, since x and y + are in regions separated by pivot? */ + } + } else { + x = (int) (Cudd_Random() % nvars) + lower; + do { + y = (int) (Cudd_Random() % nvars) + lower; + } while (x == y); + } + + previousSize = table->keysZ; + moves = zddSwapAny(table, x, y); + if (moves == NULL) + goto cuddZddSwappingOutOfMem; + + result = cuddZddSiftingBackward(table, moves, previousSize); + if (!result) + goto cuddZddSwappingOutOfMem; + + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } +#ifdef DD_STATS + if (table->keysZ < (unsigned) previousSize) { + (void) fprintf(table->out,"-"); + } else if (table->keysZ > (unsigned) previousSize) { + (void) fprintf(table->out,"+"); /* should never happen */ + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + + return(1); + +cuddZddSwappingOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *) moves); + moves = move; + } + return(0); + +} /* end of cuddZddSwapping */ + + +/**Function******************************************************************** + + Synopsis [Implementation of Rudell's sifting algorithm.] + + Description [Implementation of Rudell's sifting algorithm. + Assumes that no dead nodes are present. +
          +
        1. Order all the variables according to the number of entries + in each unique table. +
        2. Sift the variable up and down, remembering each time the + total size of the DD heap. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddSifting( + DdManager * table, + int lower, + int upper) +{ + int i; + int *var; + int size; + int x; + int result; +#ifdef DD_STATS + int previousSize; +#endif + + size = table->sizeZ; + + /* Find order in which to sift variables. */ + var = NULL; + zdd_entry = ALLOC(int, size); + if (zdd_entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSiftingOutOfMem; + } + var = ALLOC(int, size); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSiftingOutOfMem; + } + + for (i = 0; i < size; i++) { + x = table->permZ[i]; + zdd_entry[i] = table->subtableZ[x].keys; + var[i] = i; + } + + qsort((void *)var, size, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); + + /* Now sift. */ + for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { + if (zddTotalNumberSwapping >= table->siftMaxSwap) + break; + x = table->permZ[var[i]]; + if (x < lower || x > upper) continue; +#ifdef DD_STATS + previousSize = table->keysZ; +#endif + result = cuddZddSiftingAux(table, x, lower, upper); + if (!result) + goto cuddZddSiftingOutOfMem; +#ifdef DD_STATS + if (table->keysZ < (unsigned) previousSize) { + (void) fprintf(table->out,"-"); + } else if (table->keysZ > (unsigned) previousSize) { + (void) fprintf(table->out,"+"); /* should never happen */ + (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + + FREE(var); + FREE(zdd_entry); + + return(1); + +cuddZddSiftingOutOfMem: + + if (zdd_entry != NULL) FREE(zdd_entry); + if (var != NULL) FREE(var); + + return(0); + +} /* end of cuddZddSifting */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Swaps any two variables.] + + Description [Swaps any two variables. Returns the set of moves.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +zddSwapAny( + DdManager * table, + int x, + int y) +{ + Move *move, *moves; + int tmp, size; + int x_ref, y_ref; + int x_next, y_next; + int limit_size; + + if (x > y) { /* make x precede y */ + tmp = x; x = y; y = tmp; + } + + x_ref = x; y_ref = y; + + x_next = cuddZddNextHigh(table, x); + y_next = cuddZddNextLow(table, y); + moves = NULL; + limit_size = table->keysZ; + + for (;;) { + if (x_next == y_next) { /* x < x_next = y_next < y */ + size = cuddZddSwapInPlace(table, x, x_next); + if (size == 0) + goto zddSwapAnyOutOfMem; + move = (Move *) cuddDynamicAllocNode(table); + if (move == NULL) + goto zddSwapAnyOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + + size = cuddZddSwapInPlace(table, y_next, y); + if (size == 0) + goto zddSwapAnyOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) + goto zddSwapAnyOutOfMem; + move->x = y_next; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + + size = cuddZddSwapInPlace(table, x, x_next); + if (size == 0) + goto zddSwapAnyOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) + goto zddSwapAnyOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + + tmp = x; x = y; y = tmp; + + } else if (x == y_next) { /* x = y_next < y = x_next */ + size = cuddZddSwapInPlace(table, x, x_next); + if (size == 0) + goto zddSwapAnyOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) + goto zddSwapAnyOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + + tmp = x; x = y; y = tmp; + } else { + size = cuddZddSwapInPlace(table, x, x_next); + if (size == 0) + goto zddSwapAnyOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) + goto zddSwapAnyOutOfMem; + move->x = x; + move->y = x_next; + move->size = size; + move->next = moves; + moves = move; + + size = cuddZddSwapInPlace(table, y_next, y); + if (size == 0) + goto zddSwapAnyOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) + goto zddSwapAnyOutOfMem; + move->x = y_next; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + + x = x_next; y = y_next; + } + + x_next = cuddZddNextHigh(table, x); + y_next = cuddZddNextLow(table, y); + if (x_next > y_ref) + break; /* if x == y_ref */ + + if ((double) size > table->maxGrowth * (double) limit_size) + break; + if (size < limit_size) + limit_size = size; + } + if (y_next >= x_ref) { + size = cuddZddSwapInPlace(table, y_next, y); + if (size == 0) + goto zddSwapAnyOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) + goto zddSwapAnyOutOfMem; + move->x = y_next; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + } + + return(moves); + +zddSwapAnyOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *)moves); + moves = move; + } + return(NULL); + +} /* end of zddSwapAny */ + + +/**Function******************************************************************** + + Synopsis [Given xLow <= x <= xHigh moves x up and down between the + boundaries.] + + Description [Given xLow <= x <= xHigh moves x up and down between the + boundaries. Finds the best position and does the required changes. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddZddSiftingAux( + DdManager * table, + int x, + int x_low, + int x_high) +{ + Move *move; + Move *moveUp; /* list of up move */ + Move *moveDown; /* list of down move */ + + int initial_size; + int result; + + initial_size = table->keysZ; + +#ifdef DD_DEBUG + assert(table->subtableZ[x].keys > 0); +#endif + + moveDown = NULL; + moveUp = NULL; + + if (x == x_low) { + moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); + /* after that point x --> x_high */ + if (moveDown == NULL) + goto cuddZddSiftingAuxOutOfMem; + result = cuddZddSiftingBackward(table, moveDown, + initial_size); + /* move backward and stop at best position */ + if (!result) + goto cuddZddSiftingAuxOutOfMem; + + } + else if (x == x_high) { + moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); + /* after that point x --> x_low */ + if (moveUp == NULL) + goto cuddZddSiftingAuxOutOfMem; + result = cuddZddSiftingBackward(table, moveUp, initial_size); + /* move backward and stop at best position */ + if (!result) + goto cuddZddSiftingAuxOutOfMem; + } + else if ((x - x_low) > (x_high - x)) { + /* must go down first:shorter */ + moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); + /* after that point x --> x_high */ + if (moveDown == NULL) + goto cuddZddSiftingAuxOutOfMem; + moveUp = cuddZddSiftingUp(table, moveDown->y, x_low, + initial_size); + if (moveUp == NULL) + goto cuddZddSiftingAuxOutOfMem; + result = cuddZddSiftingBackward(table, moveUp, initial_size); + /* move backward and stop at best position */ + if (!result) + goto cuddZddSiftingAuxOutOfMem; + } + else { + moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); + /* after that point x --> x_high */ + if (moveUp == NULL) + goto cuddZddSiftingAuxOutOfMem; + moveDown = cuddZddSiftingDown(table, moveUp->x, x_high, + initial_size); + /* then move up */ + if (moveDown == NULL) + goto cuddZddSiftingAuxOutOfMem; + result = cuddZddSiftingBackward(table, moveDown, + initial_size); + /* move backward and stop at best position */ + if (!result) + goto cuddZddSiftingAuxOutOfMem; + } + + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *)moveDown); + moveDown = move; + } + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *)moveUp); + moveUp = move; + } + + return(1); + +cuddZddSiftingAuxOutOfMem: + while (moveDown != NULL) { + move = moveDown->next; + cuddDeallocNode(table, (DdNode *)moveDown); + moveDown = move; + } + while (moveUp != NULL) { + move = moveUp->next; + cuddDeallocNode(table, (DdNode *)moveUp); + moveUp = move; + } + + return(0); + +} /* end of cuddZddSiftingAux */ + + +/**Function******************************************************************** + + Synopsis [Sifts a variable up.] + + Description [Sifts a variable up. Moves y up until either it reaches + the bound (x_low) or the size of the ZDD heap increases too much. + Returns the set of moves in case of success; NULL if memory is full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +cuddZddSiftingUp( + DdManager * table, + int x, + int x_low, + int initial_size) +{ + Move *moves; + Move *move; + int y; + int size; + int limit_size = initial_size; + + moves = NULL; + y = cuddZddNextLow(table, x); + while (y >= x_low) { + size = cuddZddSwapInPlace(table, y, x); + if (size == 0) + goto cuddZddSiftingUpOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) + goto cuddZddSiftingUpOutOfMem; + move->x = y; + move->y = x; + move->size = size; + move->next = moves; + moves = move; + + if ((double)size > (double)limit_size * table->maxGrowth) + break; + if (size < limit_size) + limit_size = size; + + x = y; + y = cuddZddNextLow(table, x); + } + return(moves); + +cuddZddSiftingUpOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *)moves); + moves = move; + } + return(NULL); + +} /* end of cuddZddSiftingUp */ + + +/**Function******************************************************************** + + Synopsis [Sifts a variable down.] + + Description [Sifts a variable down. Moves x down until either it + reaches the bound (x_high) or the size of the ZDD heap increases too + much. Returns the set of moves in case of success; NULL if memory is + full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +cuddZddSiftingDown( + DdManager * table, + int x, + int x_high, + int initial_size) +{ + Move *moves; + Move *move; + int y; + int size; + int limit_size = initial_size; + + moves = NULL; + y = cuddZddNextHigh(table, x); + while (y <= x_high) { + size = cuddZddSwapInPlace(table, x, y); + if (size == 0) + goto cuddZddSiftingDownOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) + goto cuddZddSiftingDownOutOfMem; + move->x = x; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + + if ((double)size > (double)limit_size * table->maxGrowth) + break; + if (size < limit_size) + limit_size = size; + + x = y; + y = cuddZddNextHigh(table, x); + } + return(moves); + +cuddZddSiftingDownOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *)moves); + moves = move; + } + return(NULL); + +} /* end of cuddZddSiftingDown */ + + +/**Function******************************************************************** + + Synopsis [Given a set of moves, returns the ZDD heap to the position + giving the minimum size.] + + Description [Given a set of moves, returns the ZDD heap to the + position giving the minimum size. In case of ties, returns to the + closest position giving the minimum size. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddZddSiftingBackward( + DdManager * table, + Move * moves, + int size) +{ + int i; + int i_best; + Move *move; + int res; + + /* Find the minimum size among moves. */ + i_best = -1; + for (move = moves, i = 0; move != NULL; move = move->next, i++) { + if (move->size < size) { + i_best = i; + size = move->size; + } + } + + for (move = moves, i = 0; move != NULL; move = move->next, i++) { + if (i == i_best) + break; + res = cuddZddSwapInPlace(table, move->x, move->y); + if (!res) + return(0); + if (i_best == -1 && res == size) + break; + } + + return(1); + +} /* end of cuddZddSiftingBackward */ + + +/**Function******************************************************************** + + Synopsis [Prepares the ZDD heap for dynamic reordering.] + + Description [Prepares the ZDD heap for dynamic reordering. Does + garbage collection, to guarantee that there are no dead nodes; + and clears the cache, which is invalidated by dynamic reordering.] + + SideEffects [None] + +******************************************************************************/ +static void +zddReorderPreprocess( + DdManager * table) +{ + + /* Clear the cache. */ + cuddCacheFlush(table); + + /* Eliminate dead nodes. Do not scan the cache again. */ + cuddGarbageCollectZdd(table,0); + + return; + +} /* end of ddReorderPreprocess */ + + +/**Function******************************************************************** + + Synopsis [Shrinks almost empty ZDD subtables at the end of reordering + to guarantee that they have a reasonable load factor.] + + Description [Shrinks almost empty subtables at the end of reordering to + guarantee that they have a reasonable load factor. However, if there many + nodes are being reclaimed, then no resizing occurs. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [None] + +******************************************************************************/ +static int +zddReorderPostprocess( + DdManager * table) +{ + int i, j, posn; + DdNodePtr *nodelist, *oldnodelist; + DdNode *node, *next; + unsigned int slots, oldslots; + extern void (*MMoutOfMemory)(long); + void (*saveHandler)(long); + +#ifdef DD_VERBOSE + (void) fflush(table->out); +#endif + + /* If we have very many reclaimed nodes, we do not want to shrink + ** the subtables, because this will lead to more garbage + ** collections. More garbage collections mean shorter mean life for + ** nodes with zero reference count; hence lower probability of finding + ** a result in the cache. + */ + if (table->reclaimed > table->allocated * 0.5) return(1); + + /* Resize subtables. */ + for (i = 0; i < table->sizeZ; i++) { + int shift; + oldslots = table->subtableZ[i].slots; + if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY || + oldslots <= table->initSlots) continue; + oldnodelist = table->subtableZ[i].nodelist; + slots = oldslots >> 1; + saveHandler = MMoutOfMemory; + MMoutOfMemory = Cudd_OutOfMem; + nodelist = ALLOC(DdNodePtr, slots); + MMoutOfMemory = saveHandler; + if (nodelist == NULL) { + return(1); + } + table->subtableZ[i].nodelist = nodelist; + table->subtableZ[i].slots = slots; + table->subtableZ[i].shift++; + table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; +#ifdef DD_VERBOSE + (void) fprintf(table->err, + "shrunk layer %d (%d keys) from %d to %d slots\n", + i, table->subtableZ[i].keys, oldslots, slots); +#endif + + for (j = 0; (unsigned) j < slots; j++) { + nodelist[j] = NULL; + } + shift = table->subtableZ[i].shift; + for (j = 0; (unsigned) j < oldslots; j++) { + node = oldnodelist[j]; + while (node != NULL) { + next = node->next; + posn = ddHash(cuddT(node), cuddE(node), shift); + node->next = nodelist[posn]; + nodelist[posn] = node; + node = next; + } + } + FREE(oldnodelist); + + table->memused += (slots - oldslots) * sizeof(DdNode *); + table->slots += slots - oldslots; + table->minDead = (unsigned) (table->gcFrac * (double) table->slots); + table->cacheSlack = (int) ddMin(table->maxCacheHard, + DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) - + 2 * (int) table->cacheSlots; + } + /* We don't look at the constant subtable, because it is not + ** affected by reordering. + */ + + return(1); + +} /* end of zddReorderPostprocess */ + + +/**Function******************************************************************** + + Synopsis [Reorders ZDD variables according to a given permutation.] + + Description [Reorders ZDD variables according to a given permutation. + The i-th permutation array contains the index of the variable that + should be brought to the i-th level. zddShuffle assumes that no + dead nodes are present. The reordering is achieved by a series of + upward sifts. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +zddShuffle( + DdManager * table, + int * permutation) +{ + int index; + int level; + int position; + int numvars; + int result; +#ifdef DD_STATS + long localTime; + int initialSize; + int finalSize; + int previousSize; +#endif + + zddTotalNumberSwapping = 0; +#ifdef DD_STATS + localTime = util_cpu_time(); + initialSize = table->keysZ; + (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", + initialSize); +#endif + + numvars = table->sizeZ; + + for (level = 0; level < numvars; level++) { + index = permutation[level]; + position = table->permZ[index]; +#ifdef DD_STATS + previousSize = table->keysZ; +#endif + result = zddSiftUp(table,position,level); + if (!result) return(0); +#ifdef DD_STATS + if (table->keysZ < (unsigned) previousSize) { + (void) fprintf(table->out,"-"); + } else if (table->keysZ > (unsigned) previousSize) { + (void) fprintf(table->out,"+"); /* should never happen */ + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + +#ifdef DD_STATS + (void) fprintf(table->out,"\n"); + finalSize = table->keysZ; + (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); + (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", + ((double)(util_cpu_time() - localTime)/1000.0)); + (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", + zddTotalNumberSwapping); +#endif + + return(1); + +} /* end of zddShuffle */ + + +/**Function******************************************************************** + + Synopsis [Moves one ZDD variable up.] + + Description [Takes a ZDD variable from position x and sifts it up to + position xLow; xLow should be less than or equal to x. + Returns 1 if successful; 0 otherwise] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +zddSiftUp( + DdManager * table, + int x, + int xLow) +{ + int y; + int size; + + y = cuddZddNextLow(table,x); + while (y >= xLow) { + size = cuddZddSwapInPlace(table,y,x); + if (size == 0) { + return(0); + } + x = y; + y = cuddZddNextLow(table,x); + } + return(1); + +} /* end of zddSiftUp */ + + +/**Function******************************************************************** + + Synopsis [Fixes the ZDD variable group tree after a shuffle.] + + Description [Fixes the ZDD variable group tree after a + shuffle. Assumes that the order of the variables in a terminal node + has not been changed.] + + SideEffects [Changes the ZDD variable group tree.] + + SeeAlso [] + +******************************************************************************/ +static void +zddFixTree( + DdManager * table, + MtrNode * treenode) +{ + if (treenode == NULL) return; + treenode->low = ((int) treenode->index < table->sizeZ) ? + table->permZ[treenode->index] : treenode->index; + if (treenode->child != NULL) { + zddFixTree(table, treenode->child); + } + if (treenode->younger != NULL) + zddFixTree(table, treenode->younger); + if (treenode->parent != NULL && treenode->low < treenode->parent->low) { + treenode->parent->low = treenode->low; + treenode->parent->index = treenode->index; + } + return; + +} /* end of zddFixTree */ + diff --git a/abc70930/src/bdd/cudd/cuddZddSetop.c b/abc70930/src/bdd/cudd/cuddZddSetop.c new file mode 100644 index 00000000..f1bd72f3 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddZddSetop.c @@ -0,0 +1,1137 @@ +/**CFile*********************************************************************** + + FileName [cuddZddSetop.c] + + PackageName [cudd] + + Synopsis [Set operations on ZDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddIte() +
        • Cudd_zddUnion() +
        • Cudd_zddIntersect() +
        • Cudd_zddDiff() +
        • Cudd_zddDiffConst() +
        • Cudd_zddSubset1() +
        • Cudd_zddSubset0() +
        • Cudd_zddChange() +
        + Internal procedures included in this module: +
          +
        • cuddZddIte() +
        • cuddZddUnion() +
        • cuddZddIntersect() +
        • cuddZddDiff() +
        • cuddZddChangeAux() +
        • cuddZddSubset1() +
        • cuddZddSubset0() +
        + Static procedures included in this module: +
          +
        • zdd_subset1_aux() +
        • zdd_subset0_aux() +
        • zddVarToConst() +
        + ] + + SeeAlso [] + + Author [Hyong-Kyoon Shin, In-Ho Moon] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddSetop.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * zdd_subset1_aux ARGS((DdManager *zdd, DdNode *P, DdNode *zvar)); +static DdNode * zdd_subset0_aux ARGS((DdManager *zdd, DdNode *P, DdNode *zvar)); +static void zddVarToConst ARGS((DdNode *f, DdNode **gp, DdNode **hp, DdNode *base, DdNode *empty)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes the ITE of three ZDDs.] + + Description [Computes the ITE of three ZDDs. Returns a pointer to the + result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_zddIte( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddZddIte(dd, f, g, h); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_zddIte */ + + +/**Function******************************************************************** + + Synopsis [Computes the union of two ZDDs.] + + Description [Computes the union of two ZDDs. Returns a pointer to the + result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_zddUnion( + DdManager * dd, + DdNode * P, + DdNode * Q) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddZddUnion(dd, P, Q); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_zddUnion */ + + +/**Function******************************************************************** + + Synopsis [Computes the intersection of two ZDDs.] + + Description [Computes the intersection of two ZDDs. Returns a pointer to + the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_zddIntersect( + DdManager * dd, + DdNode * P, + DdNode * Q) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddZddIntersect(dd, P, Q); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_zddIntersect */ + + +/**Function******************************************************************** + + Synopsis [Computes the difference of two ZDDs.] + + Description [Computes the difference of two ZDDs. Returns a pointer to the + result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddDiffConst] + +******************************************************************************/ +DdNode * +Cudd_zddDiff( + DdManager * dd, + DdNode * P, + DdNode * Q) +{ + DdNode *res; + + do { + dd->reordered = 0; + res = cuddZddDiff(dd, P, Q); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_zddDiff */ + + +/**Function******************************************************************** + + Synopsis [Performs the inclusion test for ZDDs (P implies Q).] + + Description [Inclusion test for ZDDs (P implies Q). No new nodes are + generated by this procedure. Returns empty if true; + a valid pointer different from empty or DD_NON_CONSTANT otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddDiff] + +******************************************************************************/ +DdNode * +Cudd_zddDiffConst( + DdManager * zdd, + DdNode * P, + DdNode * Q) +{ + int p_top, q_top; + DdNode *empty = DD_ZERO(zdd), *t, *res; + DdManager *table = zdd; + + statLine(zdd); + if (P == empty) + return(empty); + if (Q == empty) + return(P); + if (P == Q) + return(empty); + + /* Check cache. The cache is shared by cuddZddDiff(). */ + res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q); + if (res != NULL) + return(res); + + if (cuddIsConstant(P)) + p_top = P->index; + else + p_top = zdd->permZ[P->index]; + if (cuddIsConstant(Q)) + q_top = Q->index; + else + q_top = zdd->permZ[Q->index]; + if (p_top < q_top) { + res = DD_NON_CONSTANT; + } else if (p_top > q_top) { + res = Cudd_zddDiffConst(zdd, P, cuddE(Q)); + } else { + t = Cudd_zddDiffConst(zdd, cuddT(P), cuddT(Q)); + if (t != empty) + res = DD_NON_CONSTANT; + else + res = Cudd_zddDiffConst(zdd, cuddE(P), cuddE(Q)); + } + + cuddCacheInsert2(table, cuddZddDiff, P, Q, res); + + return(res); + +} /* end of Cudd_zddDiffConst */ + + +/**Function******************************************************************** + + Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.] + + Description [Computes the positive cofactor of a ZDD w.r.t. a + variable. In terms of combinations, the result is the set of all + combinations in which the variable is asserted. Returns a pointer to + the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddSubset0] + +******************************************************************************/ +DdNode * +Cudd_zddSubset1( + DdManager * dd, + DdNode * P, + int var) +{ + DdNode *r; + + do { + dd->reordered = 0; + r = cuddZddSubset1(dd, P, var); + } while (dd->reordered == 1); + + return(r); + +} /* end of Cudd_zddSubset1 */ + + +/**Function******************************************************************** + + Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.] + + Description [Computes the negative cofactor of a ZDD w.r.t. a + variable. In terms of combinations, the result is the set of all + combinations in which the variable is negated. Returns a pointer to + the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddSubset1] + +******************************************************************************/ +DdNode * +Cudd_zddSubset0( + DdManager * dd, + DdNode * P, + int var) +{ + DdNode *r; + + do { + dd->reordered = 0; + r = cuddZddSubset0(dd, P, var); + } while (dd->reordered == 1); + + return(r); + +} /* end of Cudd_zddSubset0 */ + + +/**Function******************************************************************** + + Synopsis [Substitutes a variable with its complement in a ZDD.] + + Description [Substitutes a variable with its complement in a ZDD. + returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Cudd_zddChange( + DdManager * dd, + DdNode * P, + int var) +{ + DdNode *res; + + if ((unsigned int) var >= CUDD_MAXINDEX - 1) return(NULL); + + do { + dd->reordered = 0; + res = cuddZddChange(dd, P, var); + } while (dd->reordered == 1); + return(res); + +} /* end of Cudd_zddChange */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddIte.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddZddIte( + DdManager * dd, + DdNode * f, + DdNode * g, + DdNode * h) +{ + DdNode *tautology, *empty; + DdNode *r,*Gv,*Gvn,*Hv,*Hvn,*t,*e; + unsigned int topf,topg,toph,v,top; + int index; + + statLine(dd); + /* Trivial cases. */ + /* One variable cases. */ + if (f == (empty = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ + return(h); + } + topf = cuddIZ(dd,f->index); + topg = cuddIZ(dd,g->index); + toph = cuddIZ(dd,h->index); + v = ddMin(topg,toph); + top = ddMin(topf,v); + + tautology = (top == CUDD_MAXINDEX) ? DD_ONE(dd) : dd->univ[top]; + if (f == tautology) { /* ITE(1,G,H) = G */ + return(g); + } + + /* From now on, f is known to not be a constant. */ + zddVarToConst(f,&g,&h,tautology,empty); + + /* Check remaining one variable cases. */ + if (g == h) { /* ITE(F,G,G) = G */ + return(g); + } + + if (g == tautology) { /* ITE(F,1,0) = F */ + if (h == empty) return(f); + } + + /* Check cache. */ + r = cuddCacheLookupZdd(dd,DD_ZDD_ITE_TAG,f,g,h); + if (r != NULL) { + return(r); + } + + /* Recompute these because they may have changed in zddVarToConst. */ + topg = cuddIZ(dd,g->index); + toph = cuddIZ(dd,h->index); + v = ddMin(topg,toph); + + if (topf < v) { + r = cuddZddIte(dd,cuddE(f),g,h); + if (r == NULL) return(NULL); + } else if (topf > v) { + if (topg > v) { + Gvn = g; + index = h->index; + } else { + Gvn = cuddE(g); + index = g->index; + } + if (toph > v) { + Hv = empty; Hvn = h; + } else { + Hv = cuddT(h); Hvn = cuddE(h); + } + e = cuddZddIte(dd,f,Gvn,Hvn); + if (e == NULL) return(NULL); + cuddRef(e); + r = cuddZddGetNode(dd,index,Hv,e); + if (r == NULL) { + Cudd_RecursiveDerefZdd(dd,e); + return(NULL); + } + cuddDeref(e); + } else { + index = f->index; + if (topg > v) { + Gv = empty; Gvn = g; + } else { + Gv = cuddT(g); Gvn = cuddE(g); + } + if (toph > v) { + Hv = empty; Hvn = h; + } else { + Hv = cuddT(h); Hvn = cuddE(h); + } + e = cuddZddIte(dd,cuddE(f),Gvn,Hvn); + if (e == NULL) return(NULL); + cuddRef(e); + t = cuddZddIte(dd,cuddT(f),Gv,Hv); + if (t == NULL) { + Cudd_RecursiveDerefZdd(dd,e); + return(NULL); + } + cuddRef(t); + r = cuddZddGetNode(dd,index,t,e); + if (r == NULL) { + Cudd_RecursiveDerefZdd(dd,e); + Cudd_RecursiveDerefZdd(dd,t); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + } + + cuddCacheInsert(dd,DD_ZDD_ITE_TAG,f,g,h,r); + + return(r); + +} /* end of cuddZddIte */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddUnion.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddZddUnion( + DdManager * zdd, + DdNode * P, + DdNode * Q) +{ + int p_top, q_top; + DdNode *empty = DD_ZERO(zdd), *t, *e, *res; + DdManager *table = zdd; + + statLine(zdd); + if (P == empty) + return(Q); + if (Q == empty) + return(P); + if (P == Q) + return(P); + + /* Check cache */ + res = cuddCacheLookup2Zdd(table, cuddZddUnion, P, Q); + if (res != NULL) + return(res); + + if (cuddIsConstant(P)) + p_top = P->index; + else + p_top = zdd->permZ[P->index]; + if (cuddIsConstant(Q)) + q_top = Q->index; + else + q_top = zdd->permZ[Q->index]; + if (p_top < q_top) { + e = cuddZddUnion(zdd, cuddE(P), Q); + if (e == NULL) return (NULL); + cuddRef(e); + res = cuddZddGetNode(zdd, P->index, cuddT(P), e); + if (res == NULL) { + Cudd_RecursiveDerefZdd(table, e); + return(NULL); + } + cuddDeref(e); + } else if (p_top > q_top) { + e = cuddZddUnion(zdd, P, cuddE(Q)); + if (e == NULL) return(NULL); + cuddRef(e); + res = cuddZddGetNode(zdd, Q->index, cuddT(Q), e); + if (res == NULL) { + Cudd_RecursiveDerefZdd(table, e); + return(NULL); + } + cuddDeref(e); + } else { + t = cuddZddUnion(zdd, cuddT(P), cuddT(Q)); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddZddUnion(zdd, cuddE(P), cuddE(Q)); + if (e == NULL) { + Cudd_RecursiveDerefZdd(table, t); + return(NULL); + } + cuddRef(e); + res = cuddZddGetNode(zdd, P->index, t, e); + if (res == NULL) { + Cudd_RecursiveDerefZdd(table, t); + Cudd_RecursiveDerefZdd(table, e); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + } + + cuddCacheInsert2(table, cuddZddUnion, P, Q, res); + + return(res); + +} /* end of cuddZddUnion */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddIntersect.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddZddIntersect( + DdManager * zdd, + DdNode * P, + DdNode * Q) +{ + int p_top, q_top; + DdNode *empty = DD_ZERO(zdd), *t, *e, *res; + DdManager *table = zdd; + + statLine(zdd); + if (P == empty) + return(empty); + if (Q == empty) + return(empty); + if (P == Q) + return(P); + + /* Check cache. */ + res = cuddCacheLookup2Zdd(table, cuddZddIntersect, P, Q); + if (res != NULL) + return(res); + + if (cuddIsConstant(P)) + p_top = P->index; + else + p_top = zdd->permZ[P->index]; + if (cuddIsConstant(Q)) + q_top = Q->index; + else + q_top = zdd->permZ[Q->index]; + if (p_top < q_top) { + res = cuddZddIntersect(zdd, cuddE(P), Q); + if (res == NULL) return(NULL); + } else if (p_top > q_top) { + res = cuddZddIntersect(zdd, P, cuddE(Q)); + if (res == NULL) return(NULL); + } else { + t = cuddZddIntersect(zdd, cuddT(P), cuddT(Q)); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddZddIntersect(zdd, cuddE(P), cuddE(Q)); + if (e == NULL) { + Cudd_RecursiveDerefZdd(table, t); + return(NULL); + } + cuddRef(e); + res = cuddZddGetNode(zdd, P->index, t, e); + if (res == NULL) { + Cudd_RecursiveDerefZdd(table, t); + Cudd_RecursiveDerefZdd(table, e); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + } + + cuddCacheInsert2(table, cuddZddIntersect, P, Q, res); + + return(res); + +} /* end of cuddZddIntersect */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddDiff.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddZddDiff( + DdManager * zdd, + DdNode * P, + DdNode * Q) +{ + int p_top, q_top; + DdNode *empty = DD_ZERO(zdd), *t, *e, *res; + DdManager *table = zdd; + + statLine(zdd); + if (P == empty) + return(empty); + if (Q == empty) + return(P); + if (P == Q) + return(empty); + + /* Check cache. The cache is shared by Cudd_zddDiffConst(). */ + res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q); + if (res != NULL && res != DD_NON_CONSTANT) + return(res); + + if (cuddIsConstant(P)) + p_top = P->index; + else + p_top = zdd->permZ[P->index]; + if (cuddIsConstant(Q)) + q_top = Q->index; + else + q_top = zdd->permZ[Q->index]; + if (p_top < q_top) { + e = cuddZddDiff(zdd, cuddE(P), Q); + if (e == NULL) return(NULL); + cuddRef(e); + res = cuddZddGetNode(zdd, P->index, cuddT(P), e); + if (res == NULL) { + Cudd_RecursiveDerefZdd(table, e); + return(NULL); + } + cuddDeref(e); + } else if (p_top > q_top) { + res = cuddZddDiff(zdd, P, cuddE(Q)); + if (res == NULL) return(NULL); + } else { + t = cuddZddDiff(zdd, cuddT(P), cuddT(Q)); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddZddDiff(zdd, cuddE(P), cuddE(Q)); + if (e == NULL) { + Cudd_RecursiveDerefZdd(table, t); + return(NULL); + } + cuddRef(e); + res = cuddZddGetNode(zdd, P->index, t, e); + if (res == NULL) { + Cudd_RecursiveDerefZdd(table, t); + Cudd_RecursiveDerefZdd(table, e); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + } + + cuddCacheInsert2(table, cuddZddDiff, P, Q, res); + + return(res); + +} /* end of cuddZddDiff */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddChange.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +cuddZddChangeAux( + DdManager * zdd, + DdNode * P, + DdNode * zvar) +{ + int top_var, level; + DdNode *res, *t, *e; + DdNode *base = DD_ONE(zdd); + DdNode *empty = DD_ZERO(zdd); + + statLine(zdd); + if (P == empty) + return(empty); + if (P == base) + return(zvar); + + /* Check cache. */ + res = cuddCacheLookup2Zdd(zdd, cuddZddChangeAux, P, zvar); + if (res != NULL) + return(res); + + top_var = zdd->permZ[P->index]; + level = zdd->permZ[zvar->index]; + + if (top_var > level) { + res = cuddZddGetNode(zdd, zvar->index, P, DD_ZERO(zdd)); + if (res == NULL) return(NULL); + } else if (top_var == level) { + res = cuddZddGetNode(zdd, zvar->index, cuddE(P), cuddT(P)); + if (res == NULL) return(NULL); + } else { + t = cuddZddChangeAux(zdd, cuddT(P), zvar); + if (t == NULL) return(NULL); + cuddRef(t); + e = cuddZddChangeAux(zdd, cuddE(P), zvar); + if (e == NULL) { + Cudd_RecursiveDerefZdd(zdd, t); + return(NULL); + } + cuddRef(e); + res = cuddZddGetNode(zdd, P->index, t, e); + if (res == NULL) { + Cudd_RecursiveDerefZdd(zdd, t); + Cudd_RecursiveDerefZdd(zdd, e); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + } + + cuddCacheInsert2(zdd, cuddZddChangeAux, P, zvar, res); + + return(res); + +} /* end of cuddZddChangeAux */ + + +/**Function******************************************************************** + + Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.] + + Description [Computes the positive cofactor of a ZDD w.r.t. a + variable. In terms of combinations, the result is the set of all + combinations in which the variable is asserted. Returns a pointer to + the result if successful; NULL otherwise. cuddZddSubset1 performs + the same function as Cudd_zddSubset1, but does not restart if + reordering has taken place. Therefore it can be called from within a + recursive procedure.] + + SideEffects [None] + + SeeAlso [cuddZddSubset0 Cudd_zddSubset1] + +******************************************************************************/ +DdNode * +cuddZddSubset1( + DdManager * dd, + DdNode * P, + int var) +{ + DdNode *zvar, *r; + DdNode *base, *empty; + + base = DD_ONE(dd); + empty = DD_ZERO(dd); + + zvar = cuddUniqueInterZdd(dd, var, base, empty); + if (zvar == NULL) { + return(NULL); + } else { + cuddRef(zvar); + r = zdd_subset1_aux(dd, P, zvar); + if (r == NULL) { + Cudd_RecursiveDerefZdd(dd, zvar); + return(NULL); + } + cuddRef(r); + Cudd_RecursiveDerefZdd(dd, zvar); + } + + cuddDeref(r); + return(r); + +} /* end of cuddZddSubset1 */ + + +/**Function******************************************************************** + + Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.] + + Description [Computes the negative cofactor of a ZDD w.r.t. a + variable. In terms of combinations, the result is the set of all + combinations in which the variable is negated. Returns a pointer to + the result if successful; NULL otherwise. cuddZddSubset0 performs + the same function as Cudd_zddSubset0, but does not restart if + reordering has taken place. Therefore it can be called from within a + recursive procedure.] + + SideEffects [None] + + SeeAlso [cuddZddSubset1 Cudd_zddSubset0] + +******************************************************************************/ +DdNode * +cuddZddSubset0( + DdManager * dd, + DdNode * P, + int var) +{ + DdNode *zvar, *r; + DdNode *base, *empty; + + base = DD_ONE(dd); + empty = DD_ZERO(dd); + + zvar = cuddUniqueInterZdd(dd, var, base, empty); + if (zvar == NULL) { + return(NULL); + } else { + cuddRef(zvar); + r = zdd_subset0_aux(dd, P, zvar); + if (r == NULL) { + Cudd_RecursiveDerefZdd(dd, zvar); + return(NULL); + } + cuddRef(r); + Cudd_RecursiveDerefZdd(dd, zvar); + } + + cuddDeref(r); + return(r); + +} /* end of cuddZddSubset0 */ + + +/**Function******************************************************************** + + Synopsis [Substitutes a variable with its complement in a ZDD.] + + Description [Substitutes a variable with its complement in a ZDD. + returns a pointer to the result if successful; NULL + otherwise. cuddZddChange performs the same function as + Cudd_zddChange, but does not restart if reordering has taken + place. Therefore it can be called from within a recursive + procedure.] + + SideEffects [None] + + SeeAlso [Cudd_zddChange] + +******************************************************************************/ +DdNode * +cuddZddChange( + DdManager * dd, + DdNode * P, + int var) +{ + DdNode *zvar, *res; + + zvar = cuddUniqueInterZdd(dd, var, DD_ONE(dd), DD_ZERO(dd)); + if (zvar == NULL) return(NULL); + cuddRef(zvar); + + res = cuddZddChangeAux(dd, P, zvar); + if (res == NULL) { + Cudd_RecursiveDerefZdd(dd,zvar); + return(NULL); + } + cuddRef(res); + Cudd_RecursiveDerefZdd(dd,zvar); + cuddDeref(res); + return(res); + +} /* end of cuddZddChange */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddSubset1.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +zdd_subset1_aux( + DdManager * zdd, + DdNode * P, + DdNode * zvar) +{ + int top_var, level; + DdNode *res, *t, *e; + DdNode *base, *empty; + + statLine(zdd); + base = DD_ONE(zdd); + empty = DD_ZERO(zdd); + + /* Check cache. */ + res = cuddCacheLookup2Zdd(zdd, zdd_subset1_aux, P, zvar); + if (res != NULL) + return(res); + + if (cuddIsConstant(P)) { + res = empty; + cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res); + return(res); + } + + top_var = zdd->permZ[P->index]; + level = zdd->permZ[zvar->index]; + + if (top_var > level) { + res = empty; + } else if (top_var == level) { + res = cuddT(P); + } else { + t = zdd_subset1_aux(zdd, cuddT(P), zvar); + if (t == NULL) return(NULL); + cuddRef(t); + e = zdd_subset1_aux(zdd, cuddE(P), zvar); + if (e == NULL) { + Cudd_RecursiveDerefZdd(zdd, t); + return(NULL); + } + cuddRef(e); + res = cuddZddGetNode(zdd, P->index, t, e); + if (res == NULL) { + Cudd_RecursiveDerefZdd(zdd, t); + Cudd_RecursiveDerefZdd(zdd, e); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + } + + cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res); + + return(res); + +} /* end of zdd_subset1_aux */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddSubset0.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static DdNode * +zdd_subset0_aux( + DdManager * zdd, + DdNode * P, + DdNode * zvar) +{ + int top_var, level; + DdNode *res, *t, *e; + DdNode *base, *empty; + + statLine(zdd); + base = DD_ONE(zdd); + empty = DD_ZERO(zdd); + + /* Check cache. */ + res = cuddCacheLookup2Zdd(zdd, zdd_subset0_aux, P, zvar); + if (res != NULL) + return(res); + + if (cuddIsConstant(P)) { + res = P; + cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res); + return(res); + } + + top_var = zdd->permZ[P->index]; + level = zdd->permZ[zvar->index]; + + if (top_var > level) { + res = P; + } + else if (top_var == level) { + res = cuddE(P); + } + else { + t = zdd_subset0_aux(zdd, cuddT(P), zvar); + if (t == NULL) return(NULL); + cuddRef(t); + e = zdd_subset0_aux(zdd, cuddE(P), zvar); + if (e == NULL) { + Cudd_RecursiveDerefZdd(zdd, t); + return(NULL); + } + cuddRef(e); + res = cuddZddGetNode(zdd, P->index, t, e); + if (res == NULL) { + Cudd_RecursiveDerefZdd(zdd, t); + Cudd_RecursiveDerefZdd(zdd, e); + return(NULL); + } + cuddDeref(t); + cuddDeref(e); + } + + cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res); + + return(res); + +} /* end of zdd_subset0_aux */ + + +/**Function******************************************************************** + + Synopsis [Replaces variables with constants if possible (part of + canonical form).] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +zddVarToConst( + DdNode * f, + DdNode ** gp, + DdNode ** hp, + DdNode * base, + DdNode * empty) +{ + DdNode *g = *gp; + DdNode *h = *hp; + + if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ + *gp = base; + } + + if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ + *hp = empty; + } + +} /* end of zddVarToConst */ + diff --git a/abc70930/src/bdd/cudd/cuddZddSymm.c b/abc70930/src/bdd/cudd/cuddZddSymm.c new file mode 100644 index 00000000..54019892 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddZddSymm.c @@ -0,0 +1,1677 @@ +/**CFile*********************************************************************** + + FileName [cuddZddSymm.c] + + PackageName [cudd] + + Synopsis [Functions for symmetry-based ZDD variable reordering.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddSymmProfile() +
        + Internal procedures included in this module: +
          +
        • cuddZddSymmCheck() +
        • cuddZddSymmSifting() +
        • cuddZddSymmSiftingConv() +
        + Static procedures included in this module: +
          +
        • cuddZddUniqueCompare() +
        • cuddZddSymmSiftingAux() +
        • cuddZddSymmSiftingConvAux() +
        • cuddZddSymmSifting_up() +
        • cuddZddSymmSifting_down() +
        • zdd_group_move() +
        • cuddZddSymmSiftingBackward() +
        • zdd_group_move_backward() +
        + ] + + SeeAlso [cuddSymmetry.c] + + Author [Hyong-Kyoon Shin, In-Ho Moon] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define ZDD_MV_OOM (Move *)1 + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; +#endif + +extern int *zdd_entry; + +extern int zddTotalNumberSwapping; + +static DdNode *empty; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int cuddZddSymmSiftingAux ARGS((DdManager *table, int x, int x_low, int x_high)); +static int cuddZddSymmSiftingConvAux ARGS((DdManager *table, int x, int x_low, int x_high)); +static Move * cuddZddSymmSifting_up ARGS((DdManager *table, int x, int x_low, int initial_size)); +static Move * cuddZddSymmSifting_down ARGS((DdManager *table, int x, int x_high, int initial_size)); +static int cuddZddSymmSiftingBackward ARGS((DdManager *table, Move *moves, int size)); +static int zdd_group_move ARGS((DdManager *table, int x, int y, Move **moves)); +static int zdd_group_move_backward ARGS((DdManager *table, int x, int y)); +static void cuddZddSymmSummary ARGS((DdManager *table, int lower, int upper, int *symvars, int *symgroups)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Prints statistics on symmetric ZDD variables.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +Cudd_zddSymmProfile( + DdManager * table, + int lower, + int upper) +{ + int i, x, gbot; + int TotalSymm = 0; + int TotalSymmGroups = 0; + int nvars; + + nvars = table->sizeZ; + + for (i = lower; i < upper; i++) { + if (table->subtableZ[i].next != (unsigned) i) { + x = i; + (void) fprintf(table->out,"Group:"); + do { + (void) fprintf(table->out," %d", table->invpermZ[x]); + TotalSymm++; + gbot = x; + x = table->subtableZ[x].next; + } while (x != i); + TotalSymmGroups++; +#ifdef DD_DEBUG + assert(table->subtableZ[gbot].next == (unsigned) i); +#endif + i = gbot; + (void) fprintf(table->out,"\n"); + } + } + (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm); + (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups); + +} /* end of Cudd_zddSymmProfile */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Checks for symmetry of x and y.] + + Description [Checks for symmetry of x and y. Ignores projection + functions, unless they are isolated. Returns 1 in case of + symmetry; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +cuddZddSymmCheck( + DdManager * table, + int x, + int y) +{ + int i; + DdNode *f, *f0, *f1, *f01, *f00, *f11, *f10; + int yindex; + int xsymmy = 1; + int xsymmyp = 1; + int arccount = 0; + int TotalRefCount = 0; + int symm_found; + + empty = table->zero; + + yindex = table->invpermZ[y]; + for (i = table->subtableZ[x].slots - 1; i >= 0; i--) { + f = table->subtableZ[x].nodelist[i]; + while (f != NULL) { + /* Find f1, f0, f11, f10, f01, f00 */ + f1 = cuddT(f); + f0 = cuddE(f); + if ((int) f1->index == yindex) { + f11 = cuddT(f1); + f10 = cuddE(f1); + if (f10 != empty) + arccount++; + } else { + if ((int) f0->index != yindex) { + return(0); /* f bypasses layer y */ + } + f11 = empty; + f10 = f1; + } + if ((int) f0->index == yindex) { + f01 = cuddT(f0); + f00 = cuddE(f0); + if (f00 != empty) + arccount++; + } else { + f01 = empty; + f00 = f0; + } + if (f01 != f10) + xsymmy = 0; + if (f11 != f00) + xsymmyp = 0; + if ((xsymmy == 0) && (xsymmyp == 0)) + return(0); + + f = f->next; + } /* for each element of the collision list */ + } /* for each slot of the subtable */ + + /* Calculate the total reference counts of y + ** whose else arc is not empty. + */ + for (i = table->subtableZ[y].slots - 1; i >= 0; i--) { + f = table->subtableZ[y].nodelist[i]; + while (f != NIL(DdNode)) { + if (cuddE(f) != empty) + TotalRefCount += f->ref; + f = f->next; + } + } + + symm_found = (arccount == TotalRefCount); +#if defined(DD_DEBUG) && defined(DD_VERBOSE) + if (symm_found) { + int xindex = table->invpermZ[x]; + (void) fprintf(table->out, + "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", + xindex,yindex,x,y); + } +#endif + + return(symm_found); + +} /* end cuddZddSymmCheck */ + + +/**Function******************************************************************** + + Synopsis [Symmetric sifting algorithm for ZDDs.] + + Description [Symmetric sifting algorithm. + Assumes that no dead nodes are present. +
          +
        1. Order all the variables according to the number of entries in + each unique subtable. +
        2. Sift the variable up and down, remembering each time the total + size of the ZDD heap and grouping variables that are symmetric. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        + Returns 1 plus the number of symmetric variables if successful; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [cuddZddSymmSiftingConv] + +******************************************************************************/ +int +cuddZddSymmSifting( + DdManager * table, + int lower, + int upper) +{ + int i; + int *var; + int nvars; + int x; + int result; + int symvars; + int symgroups; + int iteration; +#ifdef DD_STATS + int previousSize; +#endif + + nvars = table->sizeZ; + + /* Find order in which to sift variables. */ + var = NULL; + zdd_entry = ALLOC(int, nvars); + if (zdd_entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSymmSiftingOutOfMem; + } + var = ALLOC(int, nvars); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSymmSiftingOutOfMem; + } + + for (i = 0; i < nvars; i++) { + x = table->permZ[i]; + zdd_entry[i] = table->subtableZ[x].keys; + var[i] = i; + } + + qsort((void *)var, nvars, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); + + /* Initialize the symmetry of each subtable to itself. */ + for (i = lower; i <= upper; i++) + table->subtableZ[i].next = i; + + iteration = ddMin(table->siftMaxVar, nvars); + for (i = 0; i < iteration; i++) { + if (zddTotalNumberSwapping >= table->siftMaxSwap) + break; + x = table->permZ[var[i]]; +#ifdef DD_STATS + previousSize = table->keysZ; +#endif + if (x < lower || x > upper) continue; + if (table->subtableZ[x].next == (unsigned) x) { + result = cuddZddSymmSiftingAux(table, x, lower, upper); + if (!result) + goto cuddZddSymmSiftingOutOfMem; +#ifdef DD_STATS + if (table->keysZ < (unsigned) previousSize) { + (void) fprintf(table->out,"-"); + } else if (table->keysZ > (unsigned) previousSize) { + (void) fprintf(table->out,"+"); +#ifdef DD_VERBOSE + (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); +#endif + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + } + + FREE(var); + FREE(zdd_entry); + + cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); + +#ifdef DD_STATS + (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars); + (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups); +#endif + + return(1+symvars); + +cuddZddSymmSiftingOutOfMem: + + if (zdd_entry != NULL) + FREE(zdd_entry); + if (var != NULL) + FREE(var); + + return(0); + +} /* end of cuddZddSymmSifting */ + + +/**Function******************************************************************** + + Synopsis [Symmetric sifting to convergence algorithm for ZDDs.] + + Description [Symmetric sifting to convergence algorithm for ZDDs. + Assumes that no dead nodes are present. +
          +
        1. Order all the variables according to the number of entries in + each unique subtable. +
        2. Sift the variable up and down, remembering each time the total + size of the ZDD heap and grouping variables that are symmetric. +
        3. Select the best permutation. +
        4. Repeat 3 and 4 for all variables. +
        5. Repeat 1-4 until no further improvement. +
        + Returns 1 plus the number of symmetric variables if successful; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [cuddZddSymmSifting] + +******************************************************************************/ +int +cuddZddSymmSiftingConv( + DdManager * table, + int lower, + int upper) +{ + int i; + int *var; + int nvars; + int initialSize; + int x; + int result; + int symvars; + int symgroups; + int classes; + int iteration; +#ifdef DD_STATS + int previousSize; +#endif + + initialSize = table->keysZ; + + nvars = table->sizeZ; + + /* Find order in which to sift variables. */ + var = NULL; + zdd_entry = ALLOC(int, nvars); + if (zdd_entry == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSymmSiftingConvOutOfMem; + } + var = ALLOC(int, nvars); + if (var == NULL) { + table->errorCode = CUDD_MEMORY_OUT; + goto cuddZddSymmSiftingConvOutOfMem; + } + + for (i = 0; i < nvars; i++) { + x = table->permZ[i]; + zdd_entry[i] = table->subtableZ[x].keys; + var[i] = i; + } + + qsort((void *)var, nvars, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); + + /* Initialize the symmetry of each subtable to itself + ** for first pass of converging symmetric sifting. + */ + for (i = lower; i <= upper; i++) + table->subtableZ[i].next = i; + + iteration = ddMin(table->siftMaxVar, table->sizeZ); + for (i = 0; i < iteration; i++) { + if (zddTotalNumberSwapping >= table->siftMaxSwap) + break; + x = table->permZ[var[i]]; + if (x < lower || x > upper) continue; + /* Only sift if not in symmetry group already. */ + if (table->subtableZ[x].next == (unsigned) x) { +#ifdef DD_STATS + previousSize = table->keysZ; +#endif + result = cuddZddSymmSiftingAux(table, x, lower, upper); + if (!result) + goto cuddZddSymmSiftingConvOutOfMem; +#ifdef DD_STATS + if (table->keysZ < (unsigned) previousSize) { + (void) fprintf(table->out,"-"); + } else if (table->keysZ > (unsigned) previousSize) { + (void) fprintf(table->out,"+"); +#ifdef DD_VERBOSE + (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); +#endif + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + } + + /* Sifting now until convergence. */ + while ((unsigned) initialSize > table->keysZ) { + initialSize = table->keysZ; +#ifdef DD_STATS + (void) fprintf(table->out,"\n"); +#endif + /* Here we consider only one representative for each symmetry class. */ + for (x = lower, classes = 0; x <= upper; x++, classes++) { + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + /* Here x is the largest index in a group. + ** Groups consists of adjacent variables. + ** Hence, the next increment of x will move it to a new group. + */ + i = table->invpermZ[x]; + zdd_entry[i] = table->subtableZ[x].keys; + var[classes] = i; + } + + qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))cuddZddUniqueCompare); + + /* Now sift. */ + iteration = ddMin(table->siftMaxVar, nvars); + for (i = 0; i < iteration; i++) { + if (zddTotalNumberSwapping >= table->siftMaxSwap) + break; + x = table->permZ[var[i]]; + if ((unsigned) x >= table->subtableZ[x].next) { +#ifdef DD_STATS + previousSize = table->keysZ; +#endif + result = cuddZddSymmSiftingConvAux(table, x, lower, upper); + if (!result) + goto cuddZddSymmSiftingConvOutOfMem; +#ifdef DD_STATS + if (table->keysZ < (unsigned) previousSize) { + (void) fprintf(table->out,"-"); + } else if (table->keysZ > (unsigned) previousSize) { + (void) fprintf(table->out,"+"); +#ifdef DD_VERBOSE + (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); +#endif + } else { + (void) fprintf(table->out,"="); + } + fflush(table->out); +#endif + } + } /* for */ + } + + cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); + +#ifdef DD_STATS + (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n", + symvars); + (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n", + symgroups); +#endif + + FREE(var); + FREE(zdd_entry); + + return(1+symvars); + +cuddZddSymmSiftingConvOutOfMem: + + if (zdd_entry != NULL) + FREE(zdd_entry); + if (var != NULL) + FREE(var); + + return(0); + +} /* end of cuddZddSymmSiftingConv */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Given x_low <= x <= x_high moves x up and down between the + boundaries.] + + Description [Given x_low <= x <= x_high moves x up and down between the + boundaries. Finds the best position and does the required changes. + Assumes that x is not part of a symmetry group. Returns 1 if + successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddZddSymmSiftingAux( + DdManager * table, + int x, + int x_low, + int x_high) +{ + Move *move; + Move *move_up; /* list of up move */ + Move *move_down; /* list of down move */ + int initial_size; + int result; + int i; + int topbot; /* index to either top or bottom of symmetry group */ + int init_group_size, final_group_size; + + initial_size = table->keysZ; + + move_down = NULL; + move_up = NULL; + + /* Look for consecutive symmetries above x. */ + for (i = x; i > x_low; i--) { + if (!cuddZddSymmCheck(table, i - 1, i)) + break; + /* find top of i-1's symmetry */ + topbot = table->subtableZ[i - 1].next; + table->subtableZ[i - 1].next = i; + table->subtableZ[x].next = topbot; + /* x is bottom of group so its symmetry is top of i-1's + group */ + i = topbot + 1; /* add 1 for i--, new i is top of symm group */ + } + /* Look for consecutive symmetries below x. */ + for (i = x; i < x_high; i++) { + if (!cuddZddSymmCheck(table, i, i + 1)) + break; + /* find bottom of i+1's symm group */ + topbot = i + 1; + while ((unsigned) topbot < table->subtableZ[topbot].next) + topbot = table->subtableZ[topbot].next; + + table->subtableZ[topbot].next = table->subtableZ[i].next; + table->subtableZ[i].next = i + 1; + i = topbot - 1; /* add 1 for i++, + new i is bottom of symm group */ + } + + /* Now x maybe in the middle of a symmetry group. */ + if (x == x_low) { /* Sift down */ + /* Find bottom of x's symm group */ + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + + i = table->subtableZ[x].next; + init_group_size = x - i + 1; + + move_down = cuddZddSymmSifting_down(table, x, x_high, + initial_size); + /* after that point x --> x_high, unless early term */ + if (move_down == ZDD_MV_OOM) + goto cuddZddSymmSiftingAuxOutOfMem; + + if (move_down == NULL || + table->subtableZ[move_down->y].next != move_down->y) { + /* symmetry detected may have to make another complete + pass */ + if (move_down != NULL) + x = move_down->y; + else + x = table->subtableZ[x].next; + i = x; + while ((unsigned) i < table->subtableZ[i].next) { + i = table->subtableZ[i].next; + } + final_group_size = i - x + 1; + + if (init_group_size == final_group_size) { + /* No new symmetry groups detected, + return to best position */ + result = cuddZddSymmSiftingBackward(table, + move_down, initial_size); + } + else { + initial_size = table->keysZ; + move_up = cuddZddSymmSifting_up(table, x, x_low, + initial_size); + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + } + } + else { + result = cuddZddSymmSiftingBackward(table, move_down, + initial_size); + /* move backward and stop at best position */ + } + if (!result) + goto cuddZddSymmSiftingAuxOutOfMem; + } + else if (x == x_high) { /* Sift up */ + /* Find top of x's symm group */ + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + x = table->subtableZ[x].next; + + i = x; + while ((unsigned) i < table->subtableZ[i].next) { + i = table->subtableZ[i].next; + } + init_group_size = i - x + 1; + + move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); + /* after that point x --> x_low, unless early term */ + if (move_up == ZDD_MV_OOM) + goto cuddZddSymmSiftingAuxOutOfMem; + + if (move_up == NULL || + table->subtableZ[move_up->x].next != move_up->x) { + /* symmetry detected may have to make another complete + pass */ + if (move_up != NULL) + x = move_up->x; + else { + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + } + i = table->subtableZ[x].next; + final_group_size = x - i + 1; + + if (init_group_size == final_group_size) { + /* No new symmetry groups detected, + return to best position */ + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + } + else { + initial_size = table->keysZ; + move_down = cuddZddSymmSifting_down(table, x, x_high, + initial_size); + result = cuddZddSymmSiftingBackward(table, move_down, + initial_size); + } + } + else { + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + /* move backward and stop at best position */ + } + if (!result) + goto cuddZddSymmSiftingAuxOutOfMem; + } + else if ((x - x_low) > (x_high - x)) { /* must go down first: + shorter */ + /* Find bottom of x's symm group */ + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + + move_down = cuddZddSymmSifting_down(table, x, x_high, + initial_size); + /* after that point x --> x_high, unless early term */ + if (move_down == ZDD_MV_OOM) + goto cuddZddSymmSiftingAuxOutOfMem; + + if (move_down != NULL) { + x = move_down->y; + } + else { + x = table->subtableZ[x].next; + } + i = x; + while ((unsigned) i < table->subtableZ[i].next) { + i = table->subtableZ[i].next; + } + init_group_size = i - x + 1; + + move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); + if (move_up == ZDD_MV_OOM) + goto cuddZddSymmSiftingAuxOutOfMem; + + if (move_up == NULL || + table->subtableZ[move_up->x].next != move_up->x) { + /* symmetry detected may have to make another complete + pass */ + if (move_up != NULL) { + x = move_up->x; + } + else { + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + } + i = table->subtableZ[x].next; + final_group_size = x - i + 1; + + if (init_group_size == final_group_size) { + /* No new symmetry groups detected, + return to best position */ + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + } + else { + while (move_down != NULL) { + move = move_down->next; + cuddDeallocNode(table, (DdNode *)move_down); + move_down = move; + } + initial_size = table->keysZ; + move_down = cuddZddSymmSifting_down(table, x, x_high, + initial_size); + result = cuddZddSymmSiftingBackward(table, move_down, + initial_size); + } + } + else { + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + /* move backward and stop at best position */ + } + if (!result) + goto cuddZddSymmSiftingAuxOutOfMem; + } + else { /* moving up first:shorter */ + /* Find top of x's symmetry group */ + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + x = table->subtableZ[x].next; + + move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); + /* after that point x --> x_high, unless early term */ + if (move_up == ZDD_MV_OOM) + goto cuddZddSymmSiftingAuxOutOfMem; + + if (move_up != NULL) { + x = move_up->x; + } + else { + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + } + i = table->subtableZ[x].next; + init_group_size = x - i + 1; + + move_down = cuddZddSymmSifting_down(table, x, x_high, + initial_size); + if (move_down == ZDD_MV_OOM) + goto cuddZddSymmSiftingAuxOutOfMem; + + if (move_down == NULL || + table->subtableZ[move_down->y].next != move_down->y) { + /* symmetry detected may have to make another complete + pass */ + if (move_down != NULL) { + x = move_down->y; + } + else { + x = table->subtableZ[x].next; + } + i = x; + while ((unsigned) i < table->subtableZ[i].next) { + i = table->subtableZ[i].next; + } + final_group_size = i - x + 1; + + if (init_group_size == final_group_size) { + /* No new symmetries detected, + go back to best position */ + result = cuddZddSymmSiftingBackward(table, move_down, + initial_size); + } + else { + while (move_up != NULL) { + move = move_up->next; + cuddDeallocNode(table, (DdNode *)move_up); + move_up = move; + } + initial_size = table->keysZ; + move_up = cuddZddSymmSifting_up(table, x, x_low, + initial_size); + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + } + } + else { + result = cuddZddSymmSiftingBackward(table, move_down, + initial_size); + /* move backward and stop at best position */ + } + if (!result) + goto cuddZddSymmSiftingAuxOutOfMem; + } + + while (move_down != NULL) { + move = move_down->next; + cuddDeallocNode(table, (DdNode *)move_down); + move_down = move; + } + while (move_up != NULL) { + move = move_up->next; + cuddDeallocNode(table, (DdNode *)move_up); + move_up = move; + } + + return(1); + +cuddZddSymmSiftingAuxOutOfMem: + if (move_down != ZDD_MV_OOM) { + while (move_down != NULL) { + move = move_down->next; + cuddDeallocNode(table, (DdNode *)move_down); + move_down = move; + } + } + if (move_up != ZDD_MV_OOM) { + while (move_up != NULL) { + move = move_up->next; + cuddDeallocNode(table, (DdNode *)move_up); + move_up = move; + } + } + + return(0); + +} /* end of cuddZddSymmSiftingAux */ + + +/**Function******************************************************************** + + Synopsis [Given x_low <= x <= x_high moves x up and down between the + boundaries.] + + Description [Given x_low <= x <= x_high moves x up and down between the + boundaries. Finds the best position and does the required changes. + Assumes that x is either an isolated variable, or it is the bottom of + a symmetry group. All symmetries may not have been found, because of + exceeded growth limit. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddZddSymmSiftingConvAux( + DdManager * table, + int x, + int x_low, + int x_high) +{ + Move *move; + Move *move_up; /* list of up move */ + Move *move_down; /* list of down move */ + int initial_size; + int result; + int i; + int init_group_size, final_group_size; + + initial_size = table->keysZ; + + move_down = NULL; + move_up = NULL; + + if (x == x_low) { /* Sift down */ + i = table->subtableZ[x].next; + init_group_size = x - i + 1; + + move_down = cuddZddSymmSifting_down(table, x, x_high, + initial_size); + /* after that point x --> x_high, unless early term */ + if (move_down == ZDD_MV_OOM) + goto cuddZddSymmSiftingConvAuxOutOfMem; + + if (move_down == NULL || + table->subtableZ[move_down->y].next != move_down->y) { + /* symmetry detected may have to make another complete + pass */ + if (move_down != NULL) + x = move_down->y; + else { + while ((unsigned) x < table->subtableZ[x].next); + x = table->subtableZ[x].next; + x = table->subtableZ[x].next; + } + i = x; + while ((unsigned) i < table->subtableZ[i].next) { + i = table->subtableZ[i].next; + } + final_group_size = i - x + 1; + + if (init_group_size == final_group_size) { + /* No new symmetries detected, + go back to best position */ + result = cuddZddSymmSiftingBackward(table, move_down, + initial_size); + } + else { + initial_size = table->keysZ; + move_up = cuddZddSymmSifting_up(table, x, x_low, + initial_size); + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + } + } + else { + result = cuddZddSymmSiftingBackward(table, move_down, + initial_size); + /* move backward and stop at best position */ + } + if (!result) + goto cuddZddSymmSiftingConvAuxOutOfMem; + } + else if (x == x_high) { /* Sift up */ + /* Find top of x's symm group */ + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + x = table->subtableZ[x].next; + + i = x; + while ((unsigned) i < table->subtableZ[i].next) { + i = table->subtableZ[i].next; + } + init_group_size = i - x + 1; + + move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); + /* after that point x --> x_low, unless early term */ + if (move_up == ZDD_MV_OOM) + goto cuddZddSymmSiftingConvAuxOutOfMem; + + if (move_up == NULL || + table->subtableZ[move_up->x].next != move_up->x) { + /* symmetry detected may have to make another complete + pass */ + if (move_up != NULL) + x = move_up->x; + else { + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + } + i = table->subtableZ[x].next; + final_group_size = x - i + 1; + + if (init_group_size == final_group_size) { + /* No new symmetry groups detected, + return to best position */ + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + } + else { + initial_size = table->keysZ; + move_down = cuddZddSymmSifting_down(table, x, x_high, + initial_size); + result = cuddZddSymmSiftingBackward(table, move_down, + initial_size); + } + } + else { + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + /* move backward and stop at best position */ + } + if (!result) + goto cuddZddSymmSiftingConvAuxOutOfMem; + } + else if ((x - x_low) > (x_high - x)) { /* must go down first: + shorter */ + move_down = cuddZddSymmSifting_down(table, x, x_high, + initial_size); + /* after that point x --> x_high */ + if (move_down == ZDD_MV_OOM) + goto cuddZddSymmSiftingConvAuxOutOfMem; + + if (move_down != NULL) { + x = move_down->y; + } + else { + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + x = table->subtableZ[x].next; + } + i = x; + while ((unsigned) i < table->subtableZ[i].next) { + i = table->subtableZ[i].next; + } + init_group_size = i - x + 1; + + move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); + if (move_up == ZDD_MV_OOM) + goto cuddZddSymmSiftingConvAuxOutOfMem; + + if (move_up == NULL || + table->subtableZ[move_up->x].next != move_up->x) { + /* symmetry detected may have to make another complete + pass */ + if (move_up != NULL) { + x = move_up->x; + } + else { + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + } + i = table->subtableZ[x].next; + final_group_size = x - i + 1; + + if (init_group_size == final_group_size) { + /* No new symmetry groups detected, + return to best position */ + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + } + else { + while (move_down != NULL) { + move = move_down->next; + cuddDeallocNode(table, (DdNode *)move_down); + move_down = move; + } + initial_size = table->keysZ; + move_down = cuddZddSymmSifting_down(table, x, x_high, + initial_size); + result = cuddZddSymmSiftingBackward(table, move_down, + initial_size); + } + } + else { + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + /* move backward and stop at best position */ + } + if (!result) + goto cuddZddSymmSiftingConvAuxOutOfMem; + } + else { /* moving up first:shorter */ + /* Find top of x's symmetry group */ + x = table->subtableZ[x].next; + + move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); + /* after that point x --> x_high, unless early term */ + if (move_up == ZDD_MV_OOM) + goto cuddZddSymmSiftingConvAuxOutOfMem; + + if (move_up != NULL) { + x = move_up->x; + } + else { + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + } + i = table->subtableZ[x].next; + init_group_size = x - i + 1; + + move_down = cuddZddSymmSifting_down(table, x, x_high, + initial_size); + if (move_down == ZDD_MV_OOM) + goto cuddZddSymmSiftingConvAuxOutOfMem; + + if (move_down == NULL || + table->subtableZ[move_down->y].next != move_down->y) { + /* symmetry detected may have to make another complete + pass */ + if (move_down != NULL) { + x = move_down->y; + } + else { + while ((unsigned) x < table->subtableZ[x].next) + x = table->subtableZ[x].next; + x = table->subtableZ[x].next; + } + i = x; + while ((unsigned) i < table->subtableZ[i].next) { + i = table->subtableZ[i].next; + } + final_group_size = i - x + 1; + + if (init_group_size == final_group_size) { + /* No new symmetries detected, + go back to best position */ + result = cuddZddSymmSiftingBackward(table, move_down, + initial_size); + } + else { + while (move_up != NULL) { + move = move_up->next; + cuddDeallocNode(table, (DdNode *)move_up); + move_up = move; + } + initial_size = table->keysZ; + move_up = cuddZddSymmSifting_up(table, x, x_low, + initial_size); + result = cuddZddSymmSiftingBackward(table, move_up, + initial_size); + } + } + else { + result = cuddZddSymmSiftingBackward(table, move_down, + initial_size); + /* move backward and stop at best position */ + } + if (!result) + goto cuddZddSymmSiftingConvAuxOutOfMem; + } + + while (move_down != NULL) { + move = move_down->next; + cuddDeallocNode(table, (DdNode *)move_down); + move_down = move; + } + while (move_up != NULL) { + move = move_up->next; + cuddDeallocNode(table, (DdNode *)move_up); + move_up = move; + } + + return(1); + +cuddZddSymmSiftingConvAuxOutOfMem: + if (move_down != ZDD_MV_OOM) { + while (move_down != NULL) { + move = move_down->next; + cuddDeallocNode(table, (DdNode *)move_down); + move_down = move; + } + } + if (move_up != ZDD_MV_OOM) { + while (move_up != NULL) { + move = move_up->next; + cuddDeallocNode(table, (DdNode *)move_up); + move_up = move; + } + } + + return(0); + +} /* end of cuddZddSymmSiftingConvAux */ + + +/**Function******************************************************************** + + Synopsis [Moves x up until either it reaches the bound (x_low) or + the size of the ZDD heap increases too much.] + + Description [Moves x up until either it reaches the bound (x_low) or + the size of the ZDD heap increases too much. Assumes that x is the top + of a symmetry group. Checks x for symmetry to the adjacent + variables. If symmetry is found, the symmetry group of x is merged + with the symmetry group of the other variable. Returns the set of + moves in case of success; ZDD_MV_OOM if memory is full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +cuddZddSymmSifting_up( + DdManager * table, + int x, + int x_low, + int initial_size) +{ + Move *moves; + Move *move; + int y; + int size; + int limit_size = initial_size; + int i, gytop; + + moves = NULL; + y = cuddZddNextLow(table, x); + while (y >= x_low) { + gytop = table->subtableZ[y].next; + if (cuddZddSymmCheck(table, y, x)) { + /* Symmetry found, attach symm groups */ + table->subtableZ[y].next = x; + i = table->subtableZ[x].next; + while (table->subtableZ[i].next != (unsigned) x) + i = table->subtableZ[i].next; + table->subtableZ[i].next = gytop; + } + else if ((table->subtableZ[x].next == (unsigned) x) && + (table->subtableZ[y].next == (unsigned) y)) { + /* x and y have self symmetry */ + size = cuddZddSwapInPlace(table, y, x); + if (size == 0) + goto cuddZddSymmSifting_upOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) + goto cuddZddSymmSifting_upOutOfMem; + move->x = y; + move->y = x; + move->size = size; + move->next = moves; + moves = move; + if ((double)size > + (double)limit_size * table->maxGrowth) + return(moves); + if (size < limit_size) + limit_size = size; + } + else { /* Group move */ + size = zdd_group_move(table, y, x, &moves); + if ((double)size > + (double)limit_size * table->maxGrowth) + return(moves); + if (size < limit_size) + limit_size = size; + } + x = gytop; + y = cuddZddNextLow(table, x); + } + + return(moves); + +cuddZddSymmSifting_upOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *)moves); + moves = move; + } + return(ZDD_MV_OOM); + +} /* end of cuddZddSymmSifting_up */ + + +/**Function******************************************************************** + + Synopsis [Moves x down until either it reaches the bound (x_high) or + the size of the ZDD heap increases too much.] + + Description [Moves x down until either it reaches the bound (x_high) + or the size of the ZDD heap increases too much. Assumes that x is the + bottom of a symmetry group. Checks x for symmetry to the adjacent + variables. If symmetry is found, the symmetry group of x is merged + with the symmetry group of the other variable. Returns the set of + moves in case of success; ZDD_MV_OOM if memory is full.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static Move * +cuddZddSymmSifting_down( + DdManager * table, + int x, + int x_high, + int initial_size) +{ + Move *moves; + Move *move; + int y; + int size; + int limit_size = initial_size; + int i, gxtop, gybot; + + moves = NULL; + y = cuddZddNextHigh(table, x); + while (y <= x_high) { + gybot = table->subtableZ[y].next; + while (table->subtableZ[gybot].next != (unsigned) y) + gybot = table->subtableZ[gybot].next; + if (cuddZddSymmCheck(table, x, y)) { + /* Symmetry found, attach symm groups */ + gxtop = table->subtableZ[x].next; + table->subtableZ[x].next = y; + i = table->subtableZ[y].next; + while (table->subtableZ[i].next != (unsigned) y) + i = table->subtableZ[i].next; + table->subtableZ[i].next = gxtop; + } + else if ((table->subtableZ[x].next == (unsigned) x) && + (table->subtableZ[y].next == (unsigned) y)) { + /* x and y have self symmetry */ + size = cuddZddSwapInPlace(table, x, y); + if (size == 0) + goto cuddZddSymmSifting_downOutOfMem; + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) + goto cuddZddSymmSifting_downOutOfMem; + move->x = x; + move->y = y; + move->size = size; + move->next = moves; + moves = move; + if ((double)size > + (double)limit_size * table->maxGrowth) + return(moves); + if (size < limit_size) + limit_size = size; + x = y; + y = cuddZddNextHigh(table, x); + } + else { /* Group move */ + size = zdd_group_move(table, x, y, &moves); + if ((double)size > + (double)limit_size * table->maxGrowth) + return(moves); + if (size < limit_size) + limit_size = size; + } + x = gybot; + y = cuddZddNextHigh(table, x); + } + + return(moves); + +cuddZddSymmSifting_downOutOfMem: + while (moves != NULL) { + move = moves->next; + cuddDeallocNode(table, (DdNode *)moves); + moves = move; + } + return(ZDD_MV_OOM); + +} /* end of cuddZddSymmSifting_down */ + + +/**Function******************************************************************** + + Synopsis [Given a set of moves, returns the ZDD heap to the position + giving the minimum size.] + + Description [Given a set of moves, returns the ZDD heap to the + position giving the minimum size. In case of ties, returns to the + closest position giving the minimum size. Returns 1 in case of + success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +cuddZddSymmSiftingBackward( + DdManager * table, + Move * moves, + int size) +{ + int i; + int i_best; + Move *move; + int res; + + i_best = -1; + for (move = moves, i = 0; move != NULL; move = move->next, i++) { + if (move->size < size) { + i_best = i; + size = move->size; + } + } + + for (move = moves, i = 0; move != NULL; move = move->next, i++) { + if (i == i_best) break; + if ((table->subtableZ[move->x].next == move->x) && + (table->subtableZ[move->y].next == move->y)) { + res = cuddZddSwapInPlace(table, move->x, move->y); + if (!res) return(0); + } + else { /* Group move necessary */ + res = zdd_group_move_backward(table, move->x, move->y); + } + if (i_best == -1 && res == size) + break; + } + + return(1); + +} /* end of cuddZddSymmSiftingBackward */ + + +/**Function******************************************************************** + + Synopsis [Swaps two groups.] + + Description [Swaps two groups. x is assumed to be the bottom variable + of the first group. y is assumed to be the top variable of the second + group. Updates the list of moves. Returns the number of keys in the + table if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +zdd_group_move( + DdManager * table, + int x, + int y, + Move ** moves) +{ + Move *move; + int size; + int i, temp, gxtop, gxbot, gytop, gybot, yprev; + int swapx, swapy; + +#ifdef DD_DEBUG + assert(x < y); /* we assume that x < y */ +#endif + /* Find top and bottom for the two groups. */ + gxtop = table->subtableZ[x].next; + gytop = y; + gxbot = x; + gybot = table->subtableZ[y].next; + while (table->subtableZ[gybot].next != (unsigned) y) + gybot = table->subtableZ[gybot].next; + yprev = gybot; + + while (x <= y) { + while (y > gxtop) { + /* Set correct symmetries. */ + temp = table->subtableZ[x].next; + if (temp == x) + temp = y; + i = gxtop; + for (;;) { + if (table->subtableZ[i].next == (unsigned) x) { + table->subtableZ[i].next = y; + break; + } else { + i = table->subtableZ[i].next; + } + } + if (table->subtableZ[y].next != (unsigned) y) { + table->subtableZ[x].next = table->subtableZ[y].next; + } else { + table->subtableZ[x].next = x; + } + + if (yprev != y) { + table->subtableZ[yprev].next = x; + } else { + yprev = x; + } + table->subtableZ[y].next = temp; + + size = cuddZddSwapInPlace(table, x, y); + if (size == 0) + goto zdd_group_moveOutOfMem; + swapx = x; + swapy = y; + y = x; + x--; + } /* while y > gxtop */ + + /* Trying to find the next y. */ + if (table->subtableZ[y].next <= (unsigned) y) { + gybot = y; + } else { + y = table->subtableZ[y].next; + } + + yprev = gxtop; + gxtop++; + gxbot++; + x = gxbot; + } /* while x <= y, end of group movement */ + move = (Move *)cuddDynamicAllocNode(table); + if (move == NULL) + goto zdd_group_moveOutOfMem; + move->x = swapx; + move->y = swapy; + move->size = table->keysZ; + move->next = *moves; + *moves = move; + + return(table->keysZ); + +zdd_group_moveOutOfMem: + while (*moves != NULL) { + move = (*moves)->next; + cuddDeallocNode(table, (DdNode *)(*moves)); + *moves = move; + } + return(0); + +} /* end of zdd_group_move */ + + +/**Function******************************************************************** + + Synopsis [Undoes the swap of two groups.] + + Description [Undoes the swap of two groups. x is assumed to be the + bottom variable of the first group. y is assumed to be the top + variable of the second group. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +zdd_group_move_backward( + DdManager * table, + int x, + int y) +{ + int size; + int i, temp, gxtop, gxbot, gytop, gybot, yprev; + +#ifdef DD_DEBUG + assert(x < y); /* we assume that x < y */ +#endif + /* Find top and bottom of the two groups. */ + gxtop = table->subtableZ[x].next; + gytop = y; + gxbot = x; + gybot = table->subtableZ[y].next; + while (table->subtableZ[gybot].next != (unsigned) y) + gybot = table->subtableZ[gybot].next; + yprev = gybot; + + while (x <= y) { + while (y > gxtop) { + /* Set correct symmetries. */ + temp = table->subtableZ[x].next; + if (temp == x) + temp = y; + i = gxtop; + for (;;) { + if (table->subtableZ[i].next == (unsigned) x) { + table->subtableZ[i].next = y; + break; + } else { + i = table->subtableZ[i].next; + } + } + if (table->subtableZ[y].next != (unsigned) y) { + table->subtableZ[x].next = table->subtableZ[y].next; + } else { + table->subtableZ[x].next = x; + } + + if (yprev != y) { + table->subtableZ[yprev].next = x; + } else { + yprev = x; + } + table->subtableZ[y].next = temp; + + size = cuddZddSwapInPlace(table, x, y); + if (size == 0) + return(0); + y = x; + x--; + } /* while y > gxtop */ + + /* Trying to find the next y. */ + if (table->subtableZ[y].next <= (unsigned) y) { + gybot = y; + } else { + y = table->subtableZ[y].next; + } + + yprev = gxtop; + gxtop++; + gxbot++; + x = gxbot; + } /* while x <= y, end of group movement backward */ + + return(size); + +} /* end of zdd_group_move_backward */ + + +/**Function******************************************************************** + + Synopsis [Counts numbers of symmetric variables and symmetry + groups.] + + Description [] + + SideEffects [None] + +******************************************************************************/ +static void +cuddZddSymmSummary( + DdManager * table, + int lower, + int upper, + int * symvars, + int * symgroups) +{ + int i,x,gbot; + int TotalSymm = 0; + int TotalSymmGroups = 0; + + for (i = lower; i <= upper; i++) { + if (table->subtableZ[i].next != (unsigned) i) { + TotalSymmGroups++; + x = i; + do { + TotalSymm++; + gbot = x; + x = table->subtableZ[x].next; + } while (x != i); +#ifdef DD_DEBUG + assert(table->subtableZ[gbot].next == (unsigned) i); +#endif + i = gbot; + } + } + *symvars = TotalSymm; + *symgroups = TotalSymmGroups; + + return; + +} /* end of cuddZddSymmSummary */ + diff --git a/abc70930/src/bdd/cudd/cuddZddUtil.c b/abc70930/src/bdd/cudd/cuddZddUtil.c new file mode 100644 index 00000000..616d16d4 --- /dev/null +++ b/abc70930/src/bdd/cudd/cuddZddUtil.c @@ -0,0 +1,1021 @@ +/**CFile*********************************************************************** + + FileName [cuddZddUtil.c] + + PackageName [cudd] + + Synopsis [Utility functions for ZDDs.] + + Description [External procedures included in this module: +
          +
        • Cudd_zddPrintMinterm() +
        • Cudd_zddPrintCover() +
        • Cudd_zddPrintDebug() +
        • Cudd_zddDumpDot() +
        + Internal procedures included in this module: +
          +
        • cuddZddP() +
        + Static procedures included in this module: +
          +
        • zp2() +
        • zdd_print_minterm_aux() +
        + ] + + SeeAlso [] + + Author [Hyong-Kyoon Shin, In-Ho Moon] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: cuddZddUtil.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int zp2 ARGS((DdManager *zdd, DdNode *f, st_table *t)); +static void zdd_print_minterm_aux ARGS((DdManager *zdd, DdNode *node, int level, int *list)); +static void zddPrintCoverAux ARGS((DdManager *zdd, DdNode *node, int level, int *list)); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Prints a disjoint sum of product form for a ZDD.] + + Description [Prints a disjoint sum of product form for a ZDD. Returns 1 + if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddPrintDebug Cudd_zddPrintCover] + +******************************************************************************/ +int +Cudd_zddPrintMinterm( + DdManager * zdd, + DdNode * node) +{ + int i, size; + int *list; + + size = (int)zdd->sizeZ; + list = ALLOC(int, size); + if (list == NULL) { + zdd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */ + zdd_print_minterm_aux(zdd, node, 0, list); + FREE(list); + return(1); + +} /* end of Cudd_zddPrintMinterm */ + + +/**Function******************************************************************** + + Synopsis [Prints a sum of products from a ZDD representing a cover.] + + Description [Prints a sum of products from a ZDD representing a cover. + Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddPrintMinterm] + +******************************************************************************/ +int +Cudd_zddPrintCover( + DdManager * zdd, + DdNode * node) +{ + int i, size; + int *list; + + size = (int)zdd->sizeZ; + if (size % 2 != 0) return(0); /* number of variables should be even */ + list = ALLOC(int, size); + if (list == NULL) { + zdd->errorCode = CUDD_MEMORY_OUT; + return(0); + } + for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */ + zddPrintCoverAux(zdd, node, 0, list); + FREE(list); + return(1); + +} /* end of Cudd_zddPrintCover */ + + +/**Function******************************************************************** + + Synopsis [Prints to the standard output a ZDD and its statistics.] + + Description [Prints to the standard output a DD and its statistics. + The statistics include the number of nodes and the number of minterms. + (The number of minterms is also the number of combinations in the set.) + The statistics are printed if pr > 0. Specifically: +
          +
        • pr = 0 : prints nothing +
        • pr = 1 : prints counts of nodes and minterms +
        • pr = 2 : prints counts + disjoint sum of products +
        • pr = 3 : prints counts + list of nodes +
        • pr > 3 : prints counts + disjoint sum of products + list of nodes +
        + Returns 1 if successful; 0 otherwise. + ] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Cudd_zddPrintDebug( + DdManager * zdd, + DdNode * f, + int n, + int pr) +{ + DdNode *empty = DD_ZERO(zdd); + int nodes; + double minterms; + int retval = 1; + + if (f == empty && pr > 0) { + (void) fprintf(zdd->out,": is the empty ZDD\n"); + (void) fflush(zdd->out); + return(1); + } + + if (pr > 0) { + nodes = Cudd_zddDagSize(f); + if (nodes == CUDD_OUT_OF_MEM) retval = 0; + minterms = Cudd_zddCountMinterm(zdd, f, n); + if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0; + (void) fprintf(zdd->out,": %d nodes %g minterms\n", + nodes, minterms); + if (pr > 2) + if (!cuddZddP(zdd, f)) retval = 0; + if (pr == 2 || pr > 3) { + if (!Cudd_zddPrintMinterm(zdd, f)) retval = 0; + (void) fprintf(zdd->out,"\n"); + } + (void) fflush(zdd->out); + } + return(retval); + +} /* end of Cudd_zddPrintDebug */ + + + +/**Function******************************************************************** + + Synopsis [Finds the first path of a ZDD.] + + Description [Defines an iterator on the paths of a ZDD + and finds its first path. Returns a generator that contains the + information necessary to continue the enumeration if successful; NULL + otherwise.

        + A path is represented as an array of literals, which are integers in + {0, 1, 2}; 0 represents an else arc out of a node, 1 represents a then arc + out of a node, and 2 stands for the absence of a node. + The size of the array equals the number of variables in the manager at + the time Cudd_zddFirstCube is called.

        + The paths that end in the empty terminal are not enumerated.] + + SideEffects [The first path is returned as a side effect.] + + SeeAlso [Cudd_zddForeachPath Cudd_zddNextPath Cudd_GenFree + Cudd_IsGenEmpty] + +******************************************************************************/ +DdGen * +Cudd_zddFirstPath( + DdManager * zdd, + DdNode * f, + int ** path) +{ + DdGen *gen; + DdNode *top, *next, *prev; + int i; + int nvars; + + /* Sanity Check. */ + if (zdd == NULL || f == NULL) return(NULL); + + /* Allocate generator an initialize it. */ + gen = ALLOC(DdGen,1); + if (gen == NULL) { + zdd->errorCode = CUDD_MEMORY_OUT; + return(NULL); + } + + gen->manager = zdd; + gen->type = CUDD_GEN_ZDD_PATHS; + gen->status = CUDD_GEN_EMPTY; + gen->gen.cubes.cube = NULL; + gen->gen.cubes.value = DD_ZERO_VAL; + gen->stack.sp = 0; + gen->stack.stack = NULL; + gen->node = NULL; + + nvars = zdd->sizeZ; + gen->gen.cubes.cube = ALLOC(int,nvars); + if (gen->gen.cubes.cube == NULL) { + zdd->errorCode = CUDD_MEMORY_OUT; + FREE(gen); + return(NULL); + } + for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2; + + /* The maximum stack depth is one plus the number of variables. + ** because a path may have nodes at all levels, including the + ** constant level. + */ + gen->stack.stack = ALLOC(DdNode *, nvars+1); + if (gen->stack.stack == NULL) { + zdd->errorCode = CUDD_MEMORY_OUT; + FREE(gen->gen.cubes.cube); + FREE(gen); + return(NULL); + } + for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL; + + /* Find the first path of the ZDD. */ + gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++; + + while (1) { + top = gen->stack.stack[gen->stack.sp-1]; + if (!cuddIsConstant(top)) { + /* Take the else branch first. */ + gen->gen.cubes.cube[top->index] = 0; + next = cuddE(top); + gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; + } else if (top == DD_ZERO(zdd)) { + /* Backtrack. */ + while (1) { + if (gen->stack.sp == 1) { + /* The current node has no predecessor. */ + gen->status = CUDD_GEN_EMPTY; + gen->stack.sp--; + goto done; + } + prev = gen->stack.stack[gen->stack.sp-2]; + next = cuddT(prev); + if (next != top) { /* follow the then branch next */ + gen->gen.cubes.cube[prev->index] = 1; + gen->stack.stack[gen->stack.sp-1] = next; + break; + } + /* Pop the stack and try again. */ + gen->gen.cubes.cube[prev->index] = 2; + gen->stack.sp--; + top = gen->stack.stack[gen->stack.sp-1]; + } + } else { + gen->status = CUDD_GEN_NONEMPTY; + gen->gen.cubes.value = cuddV(top); + goto done; + } + } + +done: + *path = gen->gen.cubes.cube; + return(gen); + +} /* end of Cudd_zddFirstPath */ + + +/**Function******************************************************************** + + Synopsis [Generates the next path of a ZDD.] + + Description [Generates the next path of a ZDD onset, + using generator gen. Returns 0 if the enumeration is completed; 1 + otherwise.] + + SideEffects [The path is returned as a side effect. The + generator is modified.] + + SeeAlso [Cudd_zddForeachPath Cudd_zddFirstPath Cudd_GenFree + Cudd_IsGenEmpty] + +******************************************************************************/ +int +Cudd_zddNextPath( + DdGen * gen, + int ** path) +{ + DdNode *top, *next, *prev; + DdManager *zdd = gen->manager; + + /* Backtrack from previously reached terminal node. */ + while (1) { + if (gen->stack.sp == 1) { + /* The current node has no predecessor. */ + gen->status = CUDD_GEN_EMPTY; + gen->stack.sp--; + goto done; + } + top = gen->stack.stack[gen->stack.sp-1]; + prev = gen->stack.stack[gen->stack.sp-2]; + next = cuddT(prev); + if (next != top) { /* follow the then branch next */ + gen->gen.cubes.cube[prev->index] = 1; + gen->stack.stack[gen->stack.sp-1] = next; + break; + } + /* Pop the stack and try again. */ + gen->gen.cubes.cube[prev->index] = 2; + gen->stack.sp--; + } + + while (1) { + top = gen->stack.stack[gen->stack.sp-1]; + if (!cuddIsConstant(top)) { + /* Take the else branch first. */ + gen->gen.cubes.cube[top->index] = 0; + next = cuddE(top); + gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; + } else if (top == DD_ZERO(zdd)) { + /* Backtrack. */ + while (1) { + if (gen->stack.sp == 1) { + /* The current node has no predecessor. */ + gen->status = CUDD_GEN_EMPTY; + gen->stack.sp--; + goto done; + } + prev = gen->stack.stack[gen->stack.sp-2]; + next = cuddT(prev); + if (next != top) { /* follow the then branch next */ + gen->gen.cubes.cube[prev->index] = 1; + gen->stack.stack[gen->stack.sp-1] = next; + break; + } + /* Pop the stack and try again. */ + gen->gen.cubes.cube[prev->index] = 2; + gen->stack.sp--; + top = gen->stack.stack[gen->stack.sp-1]; + } + } else { + gen->status = CUDD_GEN_NONEMPTY; + gen->gen.cubes.value = cuddV(top); + goto done; + } + } + +done: + if (gen->status == CUDD_GEN_EMPTY) return(0); + *path = gen->gen.cubes.cube; + return(1); + +} /* end of Cudd_zddNextPath */ + + +/**Function******************************************************************** + + Synopsis [Converts a path of a ZDD representing a cover to a string.] + + Description [Converts a path of a ZDD representing a cover to a + string. The string represents an implicant of the cover. The path + is typically produced by Cudd_zddForeachPath. Returns a pointer to + the string if successful; NULL otherwise. If the str input is NULL, + it allocates a new string. The string passed to this function must + have enough room for all variables and for the terminator.] + + SideEffects [None] + + SeeAlso [Cudd_zddForeachPath] + +******************************************************************************/ +char * +Cudd_zddCoverPathToString( + DdManager *zdd /* DD manager */, + int *path /* path of ZDD representing a cover */, + char *str /* pointer to string to use if != NULL */ + ) +{ + int nvars = zdd->sizeZ; + int i; + char *res; + + if (nvars & 1) return(NULL); + nvars >>= 1; + if (str == NULL) { + res = ALLOC(char, nvars+1); + if (res == NULL) return(NULL); + } else { + res = str; + } + for (i = 0; i < nvars; i++) { + int v = (path[2*i] << 2) | path[2*i+1]; + switch (v) { + case 0: + case 2: + case 8: + case 10: + res[i] = '-'; + break; + case 1: + case 9: + res[i] = '0'; + break; + case 4: + case 6: + res[i] = '1'; + break; + default: + res[i] = '?'; + } + } + res[nvars] = 0; + + return(res); + +} /* end of Cudd_zddCoverPathToString */ + + +/**Function******************************************************************** + + Synopsis [Writes a dot file representing the argument ZDDs.] + + Description [Writes a file representing the argument ZDDs in a format + suitable for the graph drawing program dot. + It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, + file system full). + Cudd_zddDumpDot does not close the file: This is the caller + responsibility. Cudd_zddDumpDot uses a minimal unique subset of the + hexadecimal address of a node as name for it. + If the argument inames is non-null, it is assumed to hold the pointers + to the names of the inputs. Similarly for onames. + Cudd_zddDumpDot uses the following convention to draw arcs: +

          +
        • solid line: THEN arcs; +
        • dashed line: ELSE arcs. +
        + The dot options are chosen so that the drawing fits on a letter-size + sheet. + ] + + SideEffects [None] + + SeeAlso [Cudd_DumpDot Cudd_zddPrintDebug] + +******************************************************************************/ +int +Cudd_zddDumpDot( + DdManager * dd /* manager */, + int n /* number of output nodes to be dumped */, + DdNode ** f /* array of output nodes to be dumped */, + char ** inames /* array of input names (or NULL) */, + char ** onames /* array of output names (or NULL) */, + FILE * fp /* pointer to the dump file */) +{ + DdNode *support = NULL; + DdNode *scan; + int *sorted = NULL; + int nvars = dd->sizeZ; + st_table *visited = NULL; + st_generator *gen; + int retval; + int i, j; + int slots; + DdNodePtr *nodelist; + long refAddr, diff, mask; + + /* Build a bit array with the support of f. */ + sorted = ALLOC(int,nvars); + if (sorted == NULL) { + dd->errorCode = CUDD_MEMORY_OUT; + goto failure; + } + for (i = 0; i < nvars; i++) sorted[i] = 0; + + /* Take the union of the supports of each output function. */ + for (i = 0; i < n; i++) { + support = Cudd_Support(dd,f[i]); + if (support == NULL) goto failure; + cuddRef(support); + scan = support; + while (!cuddIsConstant(scan)) { + sorted[scan->index] = 1; + scan = cuddT(scan); + } + Cudd_RecursiveDeref(dd,support); + } + support = NULL; /* so that we do not try to free it in case of failure */ + + /* Initialize symbol table for visited nodes. */ + visited = st_init_table(st_ptrcmp, st_ptrhash); + if (visited == NULL) goto failure; + + /* Collect all the nodes of this DD in the symbol table. */ + for (i = 0; i < n; i++) { + retval = cuddCollectNodes(f[i],visited); + if (retval == 0) goto failure; + } + + /* Find how many most significant hex digits are identical + ** in the addresses of all the nodes. Build a mask based + ** on this knowledge, so that digits that carry no information + ** will not be printed. This is done in two steps. + ** 1. We scan the symbol table to find the bits that differ + ** in at least 2 addresses. + ** 2. We choose one of the possible masks. There are 8 possible + ** masks for 32-bit integer, and 16 possible masks for 64-bit + ** integers. + */ + + /* Find the bits that are different. */ + refAddr = (long) f[0]; + diff = 0; + gen = st_init_gen(visited); + while (st_gen(gen, (char **) &scan, NULL)) { + diff |= refAddr ^ (long) scan; + } + st_free_gen(gen); + + /* Choose the mask. */ + for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) { + mask = (1 << i) - 1; + if (diff <= mask) break; + } + + /* Write the header and the global attributes. */ + retval = fprintf(fp,"digraph \"ZDD\" {\n"); + if (retval == EOF) return(0); + retval = fprintf(fp, + "size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n"); + if (retval == EOF) return(0); + + /* Write the input name subgraph by scanning the support array. */ + retval = fprintf(fp,"{ node [shape = plaintext];\n"); + if (retval == EOF) goto failure; + retval = fprintf(fp," edge [style = invis];\n"); + if (retval == EOF) goto failure; + /* We use a name ("CONST NODES") with an embedded blank, because + ** it is unlikely to appear as an input name. + */ + retval = fprintf(fp," \"CONST NODES\" [style = invis];\n"); + if (retval == EOF) goto failure; + for (i = 0; i < nvars; i++) { + if (sorted[dd->invpermZ[i]]) { + if (inames == NULL) { + retval = fprintf(fp,"\" %d \" -> ", dd->invpermZ[i]); + } else { + retval = fprintf(fp,"\" %s \" -> ", inames[dd->invpermZ[i]]); + } + if (retval == EOF) goto failure; + } + } + retval = fprintf(fp,"\"CONST NODES\"; \n}\n"); + if (retval == EOF) goto failure; + + /* Write the output node subgraph. */ + retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n"); + if (retval == EOF) goto failure; + for (i = 0; i < n; i++) { + if (onames == NULL) { + retval = fprintf(fp,"\"F%d\"", i); + } else { + retval = fprintf(fp,"\" %s \"", onames[i]); + } + if (retval == EOF) goto failure; + if (i == n - 1) { + retval = fprintf(fp,"; }\n"); + } else { + retval = fprintf(fp," -> "); + } + if (retval == EOF) goto failure; + } + + /* Write rank info: All nodes with the same index have the same rank. */ + for (i = 0; i < nvars; i++) { + if (sorted[dd->invpermZ[i]]) { + retval = fprintf(fp,"{ rank = same; "); + if (retval == EOF) goto failure; + if (inames == NULL) { + retval = fprintf(fp,"\" %d \";\n", dd->invpermZ[i]); + } else { + retval = fprintf(fp,"\" %s \";\n", inames[dd->invpermZ[i]]); + } + if (retval == EOF) goto failure; + nodelist = dd->subtableZ[i].nodelist; + slots = dd->subtableZ[i].slots; + for (j = 0; j < slots; j++) { + scan = nodelist[j]; + while (scan != NULL) { + if (st_is_member(visited,(char *) scan)) { + retval = fprintf(fp,"\"%lx\";\n", (mask & (long) scan) / sizeof(DdNode)); + if (retval == EOF) goto failure; + } + scan = scan->next; + } + } + retval = fprintf(fp,"}\n"); + if (retval == EOF) goto failure; + } + } + + /* All constants have the same rank. */ + retval = fprintf(fp, + "{ rank = same; \"CONST NODES\";\n{ node [shape = box]; "); + if (retval == EOF) goto failure; + nodelist = dd->constants.nodelist; + slots = dd->constants.slots; + for (j = 0; j < slots; j++) { + scan = nodelist[j]; + while (scan != NULL) { + if (st_is_member(visited,(char *) scan)) { + retval = fprintf(fp,"\"%lx\";\n", (mask & (long) scan) / sizeof(DdNode)); + if (retval == EOF) goto failure; + } + scan = scan->next; + } + } + retval = fprintf(fp,"}\n}\n"); + if (retval == EOF) goto failure; + + /* Write edge info. */ + /* Edges from the output nodes. */ + for (i = 0; i < n; i++) { + if (onames == NULL) { + retval = fprintf(fp,"\"F%d\"", i); + } else { + retval = fprintf(fp,"\" %s \"", onames[i]); + } + if (retval == EOF) goto failure; + retval = fprintf(fp," -> \"%lx\" [style = solid];\n", + (mask & (long) f[i]) / sizeof(DdNode)); + if (retval == EOF) goto failure; + } + + /* Edges from internal nodes. */ + for (i = 0; i < nvars; i++) { + if (sorted[dd->invpermZ[i]]) { + nodelist = dd->subtableZ[i].nodelist; + slots = dd->subtableZ[i].slots; + for (j = 0; j < slots; j++) { + scan = nodelist[j]; + while (scan != NULL) { + if (st_is_member(visited,(char *) scan)) { + retval = fprintf(fp, + "\"%lx\" -> \"%lx\";\n", + (mask & (long) scan) / sizeof(DdNode), + (mask & (long) cuddT(scan)) / sizeof(DdNode)); + if (retval == EOF) goto failure; + retval = fprintf(fp, + "\"%lx\" -> \"%lx\" [style = dashed];\n", + (mask & (long) scan) / sizeof(DdNode), + (mask & (long) cuddE(scan)) / sizeof(DdNode)); + if (retval == EOF) goto failure; + } + scan = scan->next; + } + } + } + } + + /* Write constant labels. */ + nodelist = dd->constants.nodelist; + slots = dd->constants.slots; + for (j = 0; j < slots; j++) { + scan = nodelist[j]; + while (scan != NULL) { + if (st_is_member(visited,(char *) scan)) { + retval = fprintf(fp,"\"%lx\" [label = \"%g\"];\n", + (mask & (long) scan) / sizeof(DdNode), cuddV(scan)); + if (retval == EOF) goto failure; + } + scan = scan->next; + } + } + + /* Write trailer and return. */ + retval = fprintf(fp,"}\n"); + if (retval == EOF) goto failure; + + st_free_table(visited); + FREE(sorted); + return(1); + +failure: + if (sorted != NULL) FREE(sorted); + if (support != NULL) Cudd_RecursiveDeref(dd,support); + if (visited != NULL) st_free_table(visited); + return(0); + +} /* end of Cudd_zddDumpBlif */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Prints a ZDD to the standard output. One line per node is + printed.] + + Description [Prints a ZDD to the standard output. One line per node is + printed. Returns 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_zddPrintDebug] + +******************************************************************************/ +int +cuddZddP( + DdManager * zdd, + DdNode * f) +{ + int retval; + st_table *table = st_init_table(st_ptrcmp, st_ptrhash); + + if (table == NULL) return(0); + + retval = zp2(zdd, f, table); + st_free_table(table); + (void) fputc('\n', zdd->out); + return(retval); + +} /* end of cuddZddP */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of cuddZddP.] + + Description [Performs the recursive step of cuddZddP. Returns 1 in + case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +zp2( + DdManager * zdd, + DdNode * f, + st_table * t) +{ + DdNode *n; + int T, E; + DdNode *base = DD_ONE(zdd); + + if (f == NULL) + return(0); + + if (Cudd_IsConstant(f)) { + (void)fprintf(zdd->out, "ID = %d\n", (f == base)); + return(1); + } + if (st_is_member(t, (char *)f) == 1) + return(1); + + if (st_insert(t, (char *) f, NULL) == ST_OUT_OF_MEM) + return(0); + +#if SIZEOF_VOID_P == 8 + (void) fprintf(zdd->out, "ID = 0x%lx\tindex = %d\tr = %d\t", + (unsigned long)f / (unsigned long) sizeof(DdNode), f->index, f->ref); +#else + (void) fprintf(zdd->out, "ID = 0x%x\tindex = %d\tr = %d\t", + (unsigned)f / (unsigned) sizeof(DdNode), f->index, f->ref); +#endif + + n = cuddT(f); + if (Cudd_IsConstant(n)) { + (void) fprintf(zdd->out, "T = %d\t\t", (n == base)); + T = 1; + } else { +#if SIZEOF_VOID_P == 8 + (void) fprintf(zdd->out, "T = 0x%lx\t", (unsigned long) n / + (unsigned long) sizeof(DdNode)); +#else + (void) fprintf(zdd->out, "T = 0x%x\t", (unsigned) n / (unsigned) sizeof(DdNode)); +#endif + T = 0; + } + + n = cuddE(f); + if (Cudd_IsConstant(n)) { + (void) fprintf(zdd->out, "E = %d\n", (n == base)); + E = 1; + } else { +#if SIZEOF_VOID_P == 8 + (void) fprintf(zdd->out, "E = 0x%lx\n", (unsigned long) n / + (unsigned long) sizeof(DdNode)); +#else + (void) fprintf(zdd->out, "E = 0x%x\n", (unsigned) n / (unsigned) sizeof(DdNode)); +#endif + E = 0; + } + + if (E == 0) + if (zp2(zdd, cuddE(f), t) == 0) return(0); + if (T == 0) + if (zp2(zdd, cuddT(f), t) == 0) return(0); + return(1); + +} /* end of zp2 */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddPrintMinterm.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +zdd_print_minterm_aux( + DdManager * zdd /* manager */, + DdNode * node /* current node */, + int level /* depth in the recursion */, + int * list /* current recursion path */) +{ + DdNode *Nv, *Nnv; + int i, v; + DdNode *base = DD_ONE(zdd); + + if (Cudd_IsConstant(node)) { + if (node == base) { + /* Check for missing variable. */ + if (level != zdd->sizeZ) { + list[zdd->invpermZ[level]] = 0; + zdd_print_minterm_aux(zdd, node, level + 1, list); + return; + } + /* Terminal case: Print one cube based on the current recursion + ** path. + */ + for (i = 0; i < zdd->sizeZ; i++) { + v = list[i]; + if (v == 0) + (void) fprintf(zdd->out,"0"); + else if (v == 1) + (void) fprintf(zdd->out,"1"); + else if (v == 3) + (void) fprintf(zdd->out,"@"); /* should never happen */ + else + (void) fprintf(zdd->out,"-"); + } + (void) fprintf(zdd->out," 1\n"); + } + } else { + /* Check for missing variable. */ + if (level != cuddIZ(zdd,node->index)) { + list[zdd->invpermZ[level]] = 0; + zdd_print_minterm_aux(zdd, node, level + 1, list); + return; + } + + Nnv = cuddE(node); + Nv = cuddT(node); + if (Nv == Nnv) { + list[node->index] = 2; + zdd_print_minterm_aux(zdd, Nnv, level + 1, list); + return; + } + + list[node->index] = 1; + zdd_print_minterm_aux(zdd, Nv, level + 1, list); + list[node->index] = 0; + zdd_print_minterm_aux(zdd, Nnv, level + 1, list); + } + return; + +} /* end of zdd_print_minterm_aux */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_zddPrintCover.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +zddPrintCoverAux( + DdManager * zdd /* manager */, + DdNode * node /* current node */, + int level /* depth in the recursion */, + int * list /* current recursion path */) +{ + DdNode *Nv, *Nnv; + int i, v; + DdNode *base = DD_ONE(zdd); + + if (Cudd_IsConstant(node)) { + if (node == base) { + /* Check for missing variable. */ + if (level != zdd->sizeZ) { + list[zdd->invpermZ[level]] = 0; + zddPrintCoverAux(zdd, node, level + 1, list); + return; + } + /* Terminal case: Print one cube based on the current recursion + ** path. + */ + for (i = 0; i < zdd->sizeZ; i += 2) { + v = list[i] * 4 + list[i+1]; + if (v == 0) + (void) putc('-',zdd->out); + else if (v == 4) + (void) putc('1',zdd->out); + else if (v == 1) + (void) putc('0',zdd->out); + else + (void) putc('@',zdd->out); /* should never happen */ + } + (void) fprintf(zdd->out," 1\n"); + } + } else { + /* Check for missing variable. */ + if (level != cuddIZ(zdd,node->index)) { + list[zdd->invpermZ[level]] = 0; + zddPrintCoverAux(zdd, node, level + 1, list); + return; + } + + Nnv = cuddE(node); + Nv = cuddT(node); + if (Nv == Nnv) { + list[node->index] = 2; + zddPrintCoverAux(zdd, Nnv, level + 1, list); + return; + } + + list[node->index] = 1; + zddPrintCoverAux(zdd, Nv, level + 1, list); + list[node->index] = 0; + zddPrintCoverAux(zdd, Nnv, level + 1, list); + } + return; + +} /* end of zddPrintCoverAux */ diff --git a/abc70930/src/bdd/cudd/module.make b/abc70930/src/bdd/cudd/module.make new file mode 100644 index 00000000..c526a50e --- /dev/null +++ b/abc70930/src/bdd/cudd/module.make @@ -0,0 +1,61 @@ +SRC += src/bdd/cudd/cuddAPI.c \ + src/bdd/cudd/cuddAddAbs.c \ + src/bdd/cudd/cuddAddApply.c \ + src/bdd/cudd/cuddAddFind.c \ + src/bdd/cudd/cuddAddInv.c \ + src/bdd/cudd/cuddAddIte.c \ + src/bdd/cudd/cuddAddNeg.c \ + src/bdd/cudd/cuddAddWalsh.c \ + src/bdd/cudd/cuddAndAbs.c \ + src/bdd/cudd/cuddAnneal.c \ + src/bdd/cudd/cuddApa.c \ + src/bdd/cudd/cuddApprox.c \ + src/bdd/cudd/cuddBddAbs.c \ + src/bdd/cudd/cuddBddCorr.c \ + src/bdd/cudd/cuddBddIte.c \ + src/bdd/cudd/cuddBridge.c \ + src/bdd/cudd/cuddCache.c \ + src/bdd/cudd/cuddCheck.c \ + src/bdd/cudd/cuddClip.c \ + src/bdd/cudd/cuddCof.c \ + src/bdd/cudd/cuddCompose.c \ + src/bdd/cudd/cuddDecomp.c \ + src/bdd/cudd/cuddEssent.c \ + src/bdd/cudd/cuddExact.c \ + src/bdd/cudd/cuddExport.c \ + src/bdd/cudd/cuddGenCof.c \ + src/bdd/cudd/cuddGenetic.c \ + src/bdd/cudd/cuddGroup.c \ + src/bdd/cudd/cuddHarwell.c \ + src/bdd/cudd/cuddInit.c \ + src/bdd/cudd/cuddInteract.c \ + src/bdd/cudd/cuddLCache.c \ + src/bdd/cudd/cuddLevelQ.c \ + src/bdd/cudd/cuddLinear.c \ + src/bdd/cudd/cuddLiteral.c \ + src/bdd/cudd/cuddMatMult.c \ + src/bdd/cudd/cuddPriority.c \ + src/bdd/cudd/cuddRead.c \ + src/bdd/cudd/cuddRef.c \ + src/bdd/cudd/cuddReorder.c \ + src/bdd/cudd/cuddSat.c \ + src/bdd/cudd/cuddSign.c \ + src/bdd/cudd/cuddSolve.c \ + src/bdd/cudd/cuddSplit.c \ + src/bdd/cudd/cuddSubsetHB.c \ + src/bdd/cudd/cuddSubsetSP.c \ + src/bdd/cudd/cuddSymmetry.c \ + src/bdd/cudd/cuddTable.c \ + src/bdd/cudd/cuddUtil.c \ + src/bdd/cudd/cuddWindow.c \ + src/bdd/cudd/cuddZddCount.c \ + src/bdd/cudd/cuddZddFuncs.c \ + src/bdd/cudd/cuddZddGroup.c \ + src/bdd/cudd/cuddZddIsop.c \ + src/bdd/cudd/cuddZddLin.c \ + src/bdd/cudd/cuddZddMisc.c \ + src/bdd/cudd/cuddZddPort.c \ + src/bdd/cudd/cuddZddReord.c \ + src/bdd/cudd/cuddZddSetop.c \ + src/bdd/cudd/cuddZddSymm.c \ + src/bdd/cudd/cuddZddUtil.c diff --git a/abc70930/src/bdd/cudd/r7x8.1.mat b/abc70930/src/bdd/cudd/r7x8.1.mat new file mode 100644 index 00000000..b0dd0a0a --- /dev/null +++ b/abc70930/src/bdd/cudd/r7x8.1.mat @@ -0,0 +1,53 @@ +7 9 +0 0 1 +0 1 1 +0 2 1 +0 3 4 +0 4 3 +0 5 3 +0 6 3 +0 8 3 +1 0 4 +1 1 3 +1 2 2 +1 3 4 +1 4 1 +1 5 2 +1 6 4 +1 8 3 +2 0 1 +2 1 1 +2 2 4 +2 4 2 +2 5 3 +2 6 3 +2 8 3 +3 0 2 +3 1 1 +3 3 4 +3 4 4 +3 5 1 +3 8 1 +4 0 2 +4 1 3 +4 2 2 +4 3 4 +4 4 1 +4 5 1 +4 6 2 +4 8 2 +5 0 3 +5 1 3 +5 2 4 +5 3 4 +5 4 1 +5 5 3 +5 6 3 +5 8 4 +6 1 1 +6 2 1 +6 3 4 +6 4 2 +6 5 4 +6 6 4 +6 8 2 diff --git a/abc70930/src/bdd/cudd/testcudd.c b/abc70930/src/bdd/cudd/testcudd.c new file mode 100644 index 00000000..d8affadc --- /dev/null +++ b/abc70930/src/bdd/cudd/testcudd.c @@ -0,0 +1,988 @@ +/**CFile*********************************************************************** + + FileName [testcudd.c] + + PackageName [cudd] + + Synopsis [Sanity check tests for some CUDD functions.] + + Description [testcudd reads a matrix with real coefficients and + transforms it into an ADD. It then performs various operations on + the ADD and on the BDD corresponding to the ADD pattern. Finally, + testcudd tests functions relate to Walsh matrices and matrix + multiplication.] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "cuddInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define TESTCUDD_VERSION "TestCudd Version #1.0, Release date 3/17/01" + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] DD_UNUSED = "$Id: testcudd.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; +#endif + +static char *onames[] = { "C", "M" }; /* names of functions to be dumped */ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static void usage ARGS((char * prog)); +static FILE *open_file ARGS((char *filename, char *mode)); +static int testIterators ARGS((DdManager *dd, DdNode *M, DdNode *C, int pr)); +static int testXor ARGS((DdManager *dd, DdNode *f, int pr, int nvars)); +static int testHamming ARGS((DdManager *dd, DdNode *f, int pr, int nvars)); +static int testWalsh ARGS((DdManager *dd, int N, int cmu, int approach, int pr)); + +/**AutomaticEnd***************************************************************/ + + +/**Function******************************************************************** + + Synopsis [Main function for testcudd.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +main(int argc, char **argv) +{ + FILE *fp; /* pointer to input file */ + char *file = ""; /* input file name */ + FILE *dfp = NULL; /* pointer to dump file */ + char *dfile; /* file for DD dump */ + DdNode *dfunc[2]; /* addresses of the functions to be dumped */ + DdManager *dd; /* pointer to DD manager */ + DdNode *one, *zero; /* fast access to constant functions */ + DdNode *M; + DdNode **x; /* pointers to variables */ + DdNode **y; /* pointers to variables */ + DdNode **xn; /* complements of row variables */ + DdNode **yn_; /* complements of column variables */ + DdNode **xvars; + DdNode **yvars; + DdNode *C; /* result of converting from ADD to BDD */ + DdNode *ess; /* cube of essential variables */ + DdNode *shortP; /* BDD cube of shortest path */ + DdNode *largest; /* BDD of largest cube */ + DdNode *shortA; /* ADD cube of shortest path */ + DdNode *constN; /* value returned by evaluation of ADD */ + DdNode *ycube; /* cube of the negated y vars for c-proj */ + DdNode *CP; /* C-Projection of C */ + DdNode *CPr; /* C-Selection of C */ + int length; /* length of the shortest path */ + int nx; /* number of variables */ + int ny; + int maxnx; + int maxny; + int m; + int n; + int N; + int cmu; /* use CMU multiplication */ + int pr; /* verbose printout level */ + int harwell; + int multiple; /* read multiple matrices */ + int ok; + int c; /* variable to read in options */ + int approach; /* reordering approach */ + int autodyn; /* automatic reordering */ + int groupcheck; /* option for group sifting */ + int profile; /* print heap profile if != 0 */ + int keepperm; /* keep track of permutation */ + int clearcache; /* clear the cache after each matrix */ + int blifOrDot; /* dump format: 0 -> dot, 1 -> blif, ... */ + int retval; /* return value */ + int i; /* loop index */ + long startTime; /* initial time */ + long lapTime; + int size; + unsigned int cacheSize, maxMemory; + unsigned int nvars,nslots; + + startTime = util_cpu_time(); + + approach = CUDD_REORDER_NONE; + autodyn = 0; + pr = 0; + harwell = 0; + multiple = 0; + profile = 0; + keepperm = 0; + cmu = 0; + N = 4; + nvars = 4; + cacheSize = 127; + maxMemory = 0; + nslots = CUDD_UNIQUE_SLOTS; + clearcache = 0; + groupcheck = CUDD_GROUP_CHECK7; + dfile = NULL; + blifOrDot = 0; /* dot format */ + + /* Parse command line. */ + while ((c = util_getopt(argc, argv, "CDHMPS:a:bcd:g:hkmn:p:v:x:X:")) + != EOF) { + switch(c) { + case 'C': + cmu = 1; + break; + case 'D': + autodyn = 1; + break; + case 'H': + harwell = 1; + break; + case 'M': +#ifdef MNEMOSYNE + (void) mnem_setrecording(0); +#endif + break; + case 'P': + profile = 1; + break; + case 'S': + nslots = atoi(util_optarg); + break; + case 'X': + maxMemory = atoi(util_optarg); + break; + case 'a': + approach = atoi(util_optarg); + break; + case 'b': + blifOrDot = 1; /* blif format */ + break; + case 'c': + clearcache = 1; + break; + case 'd': + dfile = util_optarg; + break; + case 'g': + groupcheck = atoi(util_optarg); + break; + case 'k': + keepperm = 1; + break; + case 'm': + multiple = 1; + break; + case 'n': + N = atoi(util_optarg); + break; + case 'p': + pr = atoi(util_optarg); + break; + case 'v': + nvars = atoi(util_optarg); + break; + case 'x': + cacheSize = atoi(util_optarg); + break; + case 'h': + default: + usage(argv[0]); + break; + } + } + + if (argc - util_optind == 0) { + file = "-"; + } else if (argc - util_optind == 1) { + file = argv[util_optind]; + } else { + usage(argv[0]); + } + if ((approach<0) || (approach>17)) { + (void) fprintf(stderr,"Invalid approach: %d \n",approach); + usage(argv[0]); + } + + if (pr >= 0) { + (void) printf("# %s\n", TESTCUDD_VERSION); + /* Echo command line and arguments. */ + (void) printf("#"); + for (i = 0; i < argc; i++) { + (void) printf(" %s", argv[i]); + } + (void) printf("\n"); + (void) fflush(stdout); + } + + /* Initialize manager and provide easy reference to terminals. */ + dd = Cudd_Init(nvars,0,nslots,cacheSize,maxMemory); + one = DD_ONE(dd); + zero = DD_ZERO(dd); + dd->groupcheck = (Cudd_AggregationType) groupcheck; + if (autodyn) Cudd_AutodynEnable(dd,CUDD_REORDER_SAME); + + /* Open input file. */ + fp = open_file(file, "r"); + + /* Open dump file if requested */ + if (dfile != NULL) { + dfp = open_file(dfile, "w"); + } + + x = y = xn = yn_ = NULL; + do { + /* We want to start anew for every matrix. */ + maxnx = maxny = 0; + nx = maxnx; ny = maxny; + if (pr>0) lapTime = util_cpu_time(); + if (harwell) { + if (pr >= 0) (void) printf(":name: "); + ok = Cudd_addHarwell(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, + &m, &n, 0, 2, 1, 2, pr); + } else { + ok = Cudd_addRead(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, + &m, &n, 0, 2, 1, 2); + if (pr >= 0) + (void) printf(":name: %s: %d rows %d columns\n", file, m, n); + } + if (!ok) { + (void) fprintf(stderr, "Error reading matrix\n"); + exit(1); + } + + if (nx > maxnx) maxnx = nx; + if (ny > maxny) maxny = ny; + + /* Build cube of negated y's. */ + ycube = DD_ONE(dd); + Cudd_Ref(ycube); + for (i = maxny - 1; i >= 0; i--) { + DdNode *tmpp; + tmpp = Cudd_bddAnd(dd,Cudd_Not(dd->vars[y[i]->index]),ycube); + if (tmpp == NULL) exit(2); + Cudd_Ref(tmpp); + Cudd_RecursiveDeref(dd,ycube); + ycube = tmpp; + } + /* Initialize vectors of BDD variables used by priority func. */ + xvars = ALLOC(DdNode *, nx); + if (xvars == NULL) exit(2); + for (i = 0; i < nx; i++) { + xvars[i] = dd->vars[x[i]->index]; + } + yvars = ALLOC(DdNode *, ny); + if (yvars == NULL) exit(2); + for (i = 0; i < ny; i++) { + yvars[i] = dd->vars[y[i]->index]; + } + + /* Clean up */ + for (i=0; i < maxnx; i++) { + Cudd_RecursiveDeref(dd, x[i]); + Cudd_RecursiveDeref(dd, xn[i]); + } + FREE(x); + FREE(xn); + for (i=0; i < maxny; i++) { + Cudd_RecursiveDeref(dd, y[i]); + Cudd_RecursiveDeref(dd, yn_[i]); + } + FREE(y); + FREE(yn_); + + if (pr>0) {(void) printf(":1: M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} + + if (pr>0) (void) printf(":2: time to read the matrix = %s\n", + util_print_time(util_cpu_time() - lapTime)); + + C = Cudd_addBddPattern(dd, M); + if (C == 0) exit(2); + Cudd_Ref(C); + if (pr>0) {(void) printf(":3: C"); Cudd_PrintDebug(dd,C,nx+ny,pr);} + + /* Test iterators. */ + retval = testIterators(dd,M,C,pr); + if (retval == 0) exit(2); + + cuddCacheProfile(dd,stdout); + + /* Test XOR */ + retval = testXor(dd,C,pr,nx+ny); + if (retval == 0) exit(2); + + /* Test Hamming distance functions. */ + retval = testHamming(dd,C,pr,nx+ny); + if (retval == 0) exit(2); + + /* Test selection functions. */ + CP = Cudd_CProjection(dd,C,ycube); + if (CP == NULL) exit(2); + Cudd_Ref(CP); + if (pr>0) {(void) printf("ycube"); Cudd_PrintDebug(dd,ycube,nx+ny,pr);} + if (pr>0) {(void) printf("CP"); Cudd_PrintDebug(dd,CP,nx+ny,pr);} + + if (nx == ny) { + CPr = Cudd_PrioritySelect(dd,C,xvars,yvars,(DdNode **)NULL, + (DdNode *)NULL,ny,Cudd_Xgty); + if (CPr == NULL) exit(2); + Cudd_Ref(CPr); + if (pr>0) {(void) printf(":4: CPr"); Cudd_PrintDebug(dd,CPr,nx+ny,pr);} + if (CP != CPr) { + (void) printf("CP != CPr!\n"); + } + Cudd_RecursiveDeref(dd, CPr); + } + FREE(xvars); FREE(yvars); + + Cudd_RecursiveDeref(dd, CP); + Cudd_RecursiveDeref(dd, ycube); + + /* Test functions for essential variables. */ + ess = Cudd_FindEssential(dd,C); + if (ess == NULL) exit(2); + Cudd_Ref(ess); + if (pr>0) {(void) printf(":4: ess"); Cudd_PrintDebug(dd,ess,nx+ny,pr);} + Cudd_RecursiveDeref(dd, ess); + + /* Test functions for shortest paths. */ + shortP = Cudd_ShortestPath(dd, M, NULL, NULL, &length); + if (shortP == NULL) exit(2); + Cudd_Ref(shortP); + if (pr>0) { + (void) printf(":5: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); + } + /* Test functions for largest cubes. */ + largest = Cudd_LargestCube(dd, Cudd_Not(C), &length); + if (largest == NULL) exit(2); + Cudd_Ref(largest); + if (pr>0) { + (void) printf(":5b: largest"); + Cudd_PrintDebug(dd,largest,nx+ny,pr); + } + Cudd_RecursiveDeref(dd, largest); + + /* Test Cudd_addEvalConst and Cudd_addIteConstant. */ + shortA = Cudd_BddToAdd(dd,shortP); + if (shortA == NULL) exit(2); + Cudd_Ref(shortA); + Cudd_RecursiveDeref(dd, shortP); + constN = Cudd_addEvalConst(dd,shortA,M); + if (constN == DD_NON_CONSTANT) exit(2); + if (Cudd_addIteConstant(dd,shortA,M,constN) != constN) exit(2); + if (pr>0) {(void) printf("The value of M along the chosen shortest path is %g\n", cuddV(constN));} + Cudd_RecursiveDeref(dd, shortA); + + shortP = Cudd_ShortestPath(dd, C, NULL, NULL, &length); + if (shortP == NULL) exit(2); + Cudd_Ref(shortP); + if (pr>0) { + (void) printf(":6: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); + } + + /* Test Cudd_bddIteConstant and Cudd_bddLeq. */ + if (!Cudd_bddLeq(dd,shortP,C)) exit(2); + if (Cudd_bddIteConstant(dd,Cudd_Not(shortP),one,C) != one) exit(2); + Cudd_RecursiveDeref(dd, shortP); + + if (profile) { + retval = cuddHeapProfile(dd); + } + + size = dd->size; + + if (pr>0) { + (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); + } + + /* Reorder if so requested. */ + if (approach != CUDD_REORDER_NONE) { +#ifndef DD_STATS + retval = Cudd_EnableReorderingReporting(dd); + if (retval == 0) { + (void) fprintf(stderr,"Error reported by Cudd_EnableReorderingReporting\n"); + exit(3); + } +#endif +#ifdef DD_DEBUG + retval = Cudd_DebugCheck(dd); + if (retval != 0) { + (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); + exit(3); + } + retval = Cudd_CheckKeys(dd); + if (retval != 0) { + (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); + exit(3); + } +#endif + retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5); + if (retval == 0) { + (void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n"); + exit(3); + } +#ifndef DD_STATS + retval = Cudd_DisableReorderingReporting(dd); + if (retval == 0) { + (void) fprintf(stderr,"Error reported by Cudd_DisableReorderingReporting\n"); + exit(3); + } +#endif +#ifdef DD_DEBUG + retval = Cudd_DebugCheck(dd); + if (retval != 0) { + (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); + exit(3); + } + retval = Cudd_CheckKeys(dd); + if (retval != 0) { + (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); + exit(3); + } +#endif + if (approach == CUDD_REORDER_SYMM_SIFT || + approach == CUDD_REORDER_SYMM_SIFT_CONV) { + Cudd_SymmProfile(dd,0,dd->size-1); + } + + if (pr>0) { + (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); + } + + if (keepperm) { + /* Print variable permutation. */ + (void) printf("Variable Permutation:"); + for (i=0; iinvperm[i]); + } + (void) printf("\n"); + (void) printf("Inverse Permutation:"); + for (i=0; iperm[i]); + } + (void) printf("\n"); + } + + if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} + + if (profile) { + retval = cuddHeapProfile(dd); + } + + } + + /* Dump DDs of C and M if so requested. */ + if (dfile != NULL) { + dfunc[0] = C; + dfunc[1] = M; + if (blifOrDot == 1) { + /* Only dump C because blif cannot handle ADDs */ + retval = Cudd_DumpBlif(dd,1,dfunc,NULL,onames,NULL,dfp); + } else { + retval = Cudd_DumpDot(dd,2,dfunc,NULL,onames,dfp); + } + if (retval != 1) { + (void) fprintf(stderr,"abnormal termination\n"); + exit(2); + } + } + + Cudd_RecursiveDeref(dd, C); + Cudd_RecursiveDeref(dd, M); + + if (clearcache) { + if (pr>0) {(void) printf("Clearing the cache... ");} + for (i = dd->cacheSlots - 1; i>=0; i--) { + dd->cache[i].data = NIL(DdNode); + } + if (pr>0) {(void) printf("done\n");} + } + if (pr>0) { + (void) printf("Number of variables = %6d\t",dd->size); + (void) printf("Number of slots = %6d\n",dd->slots); + (void) printf("Number of keys = %6d\t",dd->keys); + (void) printf("Number of min dead = %6d\n",dd->minDead); + } + + } while (multiple && !feof(fp)); + + fclose(fp); + if (dfile != NULL) { + fclose(dfp); + } + + /* Second phase: experiment with Walsh matrices. */ + if (!testWalsh(dd,N,cmu,approach,pr)) { + exit(2); + } + + /* Check variable destruction. */ + assert(cuddDestroySubtables(dd,3)); + assert(Cudd_DebugCheck(dd) == 0); + assert(Cudd_CheckKeys(dd) == 0); + + retval = Cudd_CheckZeroRef(dd); + ok = retval != 0; /* ok == 0 means O.K. */ + if (retval != 0) { + (void) fprintf(stderr, + "%d non-zero DD reference counts after dereferencing\n", retval); + } + + if (pr >= 0) { + (void) Cudd_PrintInfo(dd,stdout); + } + + Cudd_Quit(dd); + +#ifdef MNEMOSYNE + mnem_writestats(); +#endif + + if (pr>0) (void) printf("total time = %s\n", + util_print_time(util_cpu_time() - startTime)); + + if (pr >= 0) util_print_cpu_stats(stdout); + exit(ok); + /* NOTREACHED */ + +} /* end of main */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Prints usage info for testcudd.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static void +usage(char *prog) +{ + (void) fprintf(stderr, "usage: %s [options] [file]\n", prog); + (void) fprintf(stderr, " -C\t\tuse CMU multiplication algorithm\n"); + (void) fprintf(stderr, " -D\t\tenable automatic dynamic reordering\n"); + (void) fprintf(stderr, " -H\t\tread matrix in Harwell format\n"); + (void) fprintf(stderr, " -M\t\tturns off memory allocation recording\n"); + (void) fprintf(stderr, " -P\t\tprint BDD heap profile\n"); + (void) fprintf(stderr, " -S n\t\tnumber of slots for each subtable\n"); + (void) fprintf(stderr, " -X n\t\ttarget maximum memory in bytes\n"); + (void) fprintf(stderr, " -a n\t\tchoose reordering approach (0-13)\n"); + (void) fprintf(stderr, " \t\t\t0: same as autoMethod\n"); + (void) fprintf(stderr, " \t\t\t1: no reordering (default)\n"); + (void) fprintf(stderr, " \t\t\t2: random\n"); + (void) fprintf(stderr, " \t\t\t3: pivot\n"); + (void) fprintf(stderr, " \t\t\t4: sifting\n"); + (void) fprintf(stderr, " \t\t\t5: sifting to convergence\n"); + (void) fprintf(stderr, " \t\t\t6: symmetric sifting\n"); + (void) fprintf(stderr, " \t\t\t7: symmetric sifting to convergence\n"); + (void) fprintf(stderr, " \t\t\t8-10: window of size 2-4\n"); + (void) fprintf(stderr, " \t\t\t11-13: window of size 2-4 to conv.\n"); + (void) fprintf(stderr, " \t\t\t14: group sifting\n"); + (void) fprintf(stderr, " \t\t\t15: group sifting to convergence\n"); + (void) fprintf(stderr, " \t\t\t16: simulated annealing\n"); + (void) fprintf(stderr, " \t\t\t17: genetic algorithm\n"); + (void) fprintf(stderr, " -b\t\tuse blif as format for dumps\n"); + (void) fprintf(stderr, " -c\t\tclear the cache after each matrix\n"); + (void) fprintf(stderr, " -d file\tdump DDs to file\n"); + (void) fprintf(stderr, " -g\t\tselect aggregation criterion (0,5,7)\n"); + (void) fprintf(stderr, " -h\t\tprints this message\n"); + (void) fprintf(stderr, " -k\t\tprint the variable permutation\n"); + (void) fprintf(stderr, " -m\t\tread multiple matrices (only with -H)\n"); + (void) fprintf(stderr, " -n n\t\tnumber of variables\n"); + (void) fprintf(stderr, " -p n\t\tcontrol verbosity\n"); + (void) fprintf(stderr, " -v n\t\tinitial variables in the unique table\n"); + (void) fprintf(stderr, " -x n\t\tinitial size of the cache\n"); + exit(2); +} /* end of usage */ + + +/**Function******************************************************************** + + Synopsis [Opens a file.] + + Description [Opens a file, or fails with an error message and exits. + Allows '-' as a synonym for standard input.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static FILE * +open_file(char *filename, char *mode) +{ + FILE *fp; + + if (strcmp(filename, "-") == 0) { + return mode[0] == 'r' ? stdin : stdout; + } else if ((fp = fopen(filename, mode)) == NULL) { + perror(filename); + exit(1); + } + return fp; + +} /* end of open_file */ + + +/**Function******************************************************************** + + Synopsis [Tests Walsh matrix multiplication.] + + Description [Tests Walsh matrix multiplication. Return 1 if successful; + 0 otherwise.] + + SideEffects [May create new variables in the manager.] + + SeeAlso [] + +******************************************************************************/ +static int +testWalsh( + DdManager *dd /* manager */, + int N /* number of variables */, + int cmu /* use CMU approach to matrix multiplication */, + int approach /* reordering approach */, + int pr /* verbosity level */) +{ + DdNode *walsh1, *walsh2, *wtw; + DdNode **x, **v, **z; + int i, retval; + DdNode *one = DD_ONE(dd); + DdNode *zero = DD_ZERO(dd); + + if (N > 3) { + x = ALLOC(DdNode *,N); + v = ALLOC(DdNode *,N); + z = ALLOC(DdNode *,N); + + for (i = N-1; i >= 0; i--) { + Cudd_Ref(x[i]=cuddUniqueInter(dd,3*i,one,zero)); + Cudd_Ref(v[i]=cuddUniqueInter(dd,3*i+1,one,zero)); + Cudd_Ref(z[i]=cuddUniqueInter(dd,3*i+2,one,zero)); + } + Cudd_Ref(walsh1 = Cudd_addWalsh(dd,v,z,N)); + if (pr>0) {(void) printf("walsh1"); Cudd_PrintDebug(dd,walsh1,2*N,pr);} + Cudd_Ref(walsh2 = Cudd_addWalsh(dd,x,v,N)); + if (cmu) { + Cudd_Ref(wtw = Cudd_addTimesPlus(dd,walsh2,walsh1,v,N)); + } else { + Cudd_Ref(wtw = Cudd_addMatrixMultiply(dd,walsh2,walsh1,v,N)); + } + if (pr>0) {(void) printf("wtw"); Cudd_PrintDebug(dd,wtw,2*N,pr);} + + if (approach != CUDD_REORDER_NONE) { +#ifdef DD_DEBUG + retval = Cudd_DebugCheck(dd); + if (retval != 0) { + (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); + return(0); + } +#endif + retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5); + if (retval == 0) { + (void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n"); + return(0); + } +#ifdef DD_DEBUG + retval = Cudd_DebugCheck(dd); + if (retval != 0) { + (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); + return(0); + } +#endif + if (approach == CUDD_REORDER_SYMM_SIFT || + approach == CUDD_REORDER_SYMM_SIFT_CONV) { + Cudd_SymmProfile(dd,0,dd->size-1); + } + } + /* Clean up. */ + Cudd_RecursiveDeref(dd, wtw); + Cudd_RecursiveDeref(dd, walsh1); + Cudd_RecursiveDeref(dd, walsh2); + for (i=0; i < N; i++) { + Cudd_RecursiveDeref(dd, x[i]); + Cudd_RecursiveDeref(dd, v[i]); + Cudd_RecursiveDeref(dd, z[i]); + } + FREE(x); + FREE(v); + FREE(z); + } + return(1); + +} /* end of testWalsh */ + +/**Function******************************************************************** + + Synopsis [Tests iterators.] + + Description [Tests iterators on cubes and nodes.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +testIterators( + DdManager *dd, + DdNode *M, + DdNode *C, + int pr) +{ + int *cube; + CUDD_VALUE_TYPE value; + DdGen *gen; + int q; + + /* Test iterator for cubes. */ + if (pr>1) { + (void) printf("Testing iterator on cubes:\n"); + Cudd_ForeachCube(dd,M,gen,cube,value) { + for (q = 0; q < dd->size; q++) { + switch (cube[q]) { + case 0: + (void) printf("0"); + break; + case 1: + (void) printf("1"); + break; + case 2: + (void) printf("-"); + break; + default: + (void) printf("?"); + } + } + (void) printf(" %g\n",value); + } + (void) printf("\n"); + } + + if (pr>1) { + (void) printf("Testing prime expansion of cubes:\n"); + if (!Cudd_bddPrintCover(dd,C,C)) return(0); + } + + /* Test iterator on nodes. */ + if (pr>2) { + DdGen *gen; + DdNode *node; + (void) printf("Testing iterator on nodes:\n"); + Cudd_ForeachNode(dd,M,gen,node) { + if (Cudd_IsConstant(node)) { +#if SIZEOF_VOID_P == 8 + (void) printf("ID = 0x%lx\tvalue = %-9g\n", + (unsigned long) node / + (unsigned long) sizeof(DdNode), + Cudd_V(node)); +#else + (void) printf("ID = 0x%x\tvalue = %-9g\n", + (unsigned int) node / + (unsigned int) sizeof(DdNode), + Cudd_V(node)); +#endif + } else { +#if SIZEOF_VOID_P == 8 + (void) printf("ID = 0x%lx\tindex = %d\tr = %d\n", + (unsigned long) node / + (unsigned long) sizeof(DdNode), + node->index, node->ref); +#else + (void) printf("ID = 0x%x\tindex = %d\tr = %d\n", + (unsigned int) node / + (unsigned int) sizeof(DdNode), + node->index, node->ref); +#endif + } + } + (void) printf("\n"); + } + return(1); + +} /* end of testIterators */ + + +/**Function******************************************************************** + + Synopsis [Tests the functions related to the exclusive OR.] + + Description [Tests the functions related to the exclusive OR. It + builds the boolean difference of the given function in three + different ways and checks that the results is the same. Returns 1 if + successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +testXor(DdManager *dd, DdNode *f, int pr, int nvars) +{ + DdNode *f1, *f0, *res1, *res2; + int x; + + /* Extract cofactors w.r.t. mid variable. */ + x = nvars / 2; + f1 = Cudd_Cofactor(dd,f,dd->vars[x]); + if (f1 == NULL) return(0); + Cudd_Ref(f1); + + f0 = Cudd_Cofactor(dd,f,Cudd_Not(dd->vars[x])); + if (f0 == NULL) { + Cudd_RecursiveDeref(dd,f1); + return(0); + } + Cudd_Ref(f0); + + /* Compute XOR of cofactors with ITE. */ + res1 = Cudd_bddIte(dd,f1,Cudd_Not(f0),f0); + if (res1 == NULL) return(0); + Cudd_Ref(res1); + + if (pr>0) {(void) printf("xor1"); Cudd_PrintDebug(dd,res1,nvars,pr);} + + /* Compute XOR of cofactors with XOR. */ + res2 = Cudd_bddXor(dd,f1,f0); + if (res2 == NULL) { + Cudd_RecursiveDeref(dd,res1); + return(0); + } + Cudd_Ref(res2); + + if (res1 != res2) { + if (pr>0) {(void) printf("xor2"); Cudd_PrintDebug(dd,res2,nvars,pr);} + Cudd_RecursiveDeref(dd,res1); + Cudd_RecursiveDeref(dd,res2); + return(0); + } + Cudd_RecursiveDeref(dd,res1); + Cudd_RecursiveDeref(dd,f1); + Cudd_RecursiveDeref(dd,f0); + + /* Compute boolean difference directly. */ + res1 = Cudd_bddBooleanDiff(dd,f,x); + if (res1 == NULL) { + Cudd_RecursiveDeref(dd,res2); + return(0); + } + Cudd_Ref(res1); + + if (res1 != res2) { + if (pr>0) {(void) printf("xor3"); Cudd_PrintDebug(dd,res1,nvars,pr);} + Cudd_RecursiveDeref(dd,res1); + Cudd_RecursiveDeref(dd,res2); + return(0); + } + Cudd_RecursiveDeref(dd,res1); + Cudd_RecursiveDeref(dd,res2); + return(1); + +} /* end of testXor */ + + +/**Function******************************************************************** + + Synopsis [Tests the Hamming distance functions.] + + Description [Tests the Hammming distance functions. Returns + 1 if successful; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +testHamming( + DdManager *dd, + DdNode *f, + int pr, + int nvars) +{ + DdNode **vars, *minBdd, *zero, *scan; + int i; + int d; + int *minterm; + int size = Cudd_ReadSize(dd); + + vars = ALLOC(DdNode *, size); + if (vars == NULL) return(0); + for (i = 0; i < size; i++) { + vars[i] = Cudd_bddIthVar(dd,i); + } + + minBdd = Cudd_bddPickOneMinterm(dd,Cudd_Not(f),vars,size); + Cudd_Ref(minBdd); + if (pr > 0) { + (void) printf("Chosen minterm for Hamming distance test: "); + Cudd_PrintDebug(dd,minBdd,size,pr); + } + + minterm = ALLOC(int,size); + if (minterm == NULL) { + FREE(vars); + Cudd_RecursiveDeref(dd,minBdd); + return(0); + } + scan = minBdd; + zero = Cudd_Not(DD_ONE(dd)); + while (!Cudd_IsConstant(scan)) { + DdNode *R = Cudd_Regular(scan); + DdNode *T = Cudd_T(R); + DdNode *E = Cudd_E(R); + if (R != scan) { + T = Cudd_Not(T); + E = Cudd_Not(E); + } + if (T == zero) { + minterm[R->index] = 0; + scan = E; + } else { + minterm[R->index] = 1; + scan = T; + } + } + Cudd_RecursiveDeref(dd,minBdd); + + d = Cudd_MinHammingDist(dd,f,minterm,size); + + (void) printf("Minimum Hamming distance = %d\n", d); + + FREE(vars); + FREE(minterm); + return(1); + +} /* end of testHamming */ diff --git a/abc70930/src/bdd/dsd/dsd.h b/abc70930/src/bdd/dsd/dsd.h new file mode 100644 index 00000000..b73b81ab --- /dev/null +++ b/abc70930/src/bdd/dsd/dsd.h @@ -0,0 +1,129 @@ +/**CFile**************************************************************** + + FileName [dsd.h] + + PackageName [DSD: Disjoint-support decomposition package.] + + Synopsis [External declarations of the package. + This fast BDD-based recursive algorithm for simple + (single-output) DSD is based on the following papers: + (1) V. Bertacco and M. Damiani, "Disjunctive decomposition of + logic functions," Proc. ICCAD '97, pp. 78-82. + (2) Y. Matsunaga, "An exact and efficient algorithm for disjunctive + decomposition", Proc. SASIMI '98, pp. 44-50. + The scope of detected decompositions is the same as in the paper: + T. Sasao and M. Matsuura, "DECOMPOS: An integrated system for + functional decomposition," Proc. IWLS '98, pp. 471-477.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 8.0. Started - September 22, 2003.] + + Revision [$Id: dsd.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __DSD_H__ +#define __DSD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// TYPEDEF DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Dsd_Manager_t_ Dsd_Manager_t; +typedef struct Dsd_Node_t_ Dsd_Node_t; +typedef enum Dsd_Type_t_ Dsd_Type_t; + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// types of DSD nodes +enum Dsd_Type_t_ { + DSD_NODE_NONE = 0, + DSD_NODE_CONST1 = 1, + DSD_NODE_BUF = 2, + DSD_NODE_OR = 3, + DSD_NODE_EXOR = 4, + DSD_NODE_PRIME = 5, +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// complementation and testing for pointers for decomposition entries +#define Dsd_IsComplement(p) (((int)((unsigned long) (p) & 01))) +#define Dsd_Regular(p) ((Dsd_Node_t *)((unsigned long)(p) & ~01)) +#define Dsd_Not(p) ((Dsd_Node_t *)((unsigned long)(p) ^ 01)) +#define Dsd_NotCond(p,c) ((Dsd_Node_t *)((unsigned long)(p) ^ (c))) + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator through the transitions +#define Dsd_NodeForEachChild( Node, Index, Child ) \ + for ( Index = 0; \ + Index < Dsd_NodeReadDecsNum(Node) && \ + ((Child = Dsd_NodeReadDec(Node,Index))>=0); \ + Index++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== dsdApi.c =======================================================*/ +extern Dsd_Type_t Dsd_NodeReadType( Dsd_Node_t * p ); +extern DdNode * Dsd_NodeReadFunc( Dsd_Node_t * p ); +extern DdNode * Dsd_NodeReadSupp( Dsd_Node_t * p ); +extern Dsd_Node_t ** Dsd_NodeReadDecs( Dsd_Node_t * p ); +extern Dsd_Node_t * Dsd_NodeReadDec ( Dsd_Node_t * p, int i ); +extern int Dsd_NodeReadDecsNum( Dsd_Node_t * p ); +extern int Dsd_NodeReadMark( Dsd_Node_t * p ); +extern void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ); +extern DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan ); +extern Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i ); +extern Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ); +extern Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan ); +/*=== dsdMan.c =======================================================*/ +extern Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose ); +extern void Dsd_ManagerStop( Dsd_Manager_t * dMan ); +/*=== dsdProc.c =======================================================*/ +extern void Dsd_Decompose( Dsd_Manager_t * dMan, DdNode ** pbFuncs, int nFuncs ); +extern Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc ); +/*=== dsdTree.c =======================================================*/ +extern void Dsd_TreeNodeGetInfo( Dsd_Manager_t * dMan, int * DepthMax, int * GateSizeMax ); +extern void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax ); +extern int Dsd_TreeGetAigCost( Dsd_Node_t * pNode ); +extern int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * dMan ); +extern int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot ); +extern int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan ); +extern int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot ); +extern int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * dMan, int * pVars ); +extern Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * dMan, int * pnNodes ); +extern Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes ); +extern void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ); +extern void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ); +/*=== dsdLocal.c =======================================================*/ +extern DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/bdd/dsd/dsdApi.c b/abc70930/src/bdd/dsd/dsdApi.c new file mode 100644 index 00000000..d1c90e23 --- /dev/null +++ b/abc70930/src/bdd/dsd/dsdApi.c @@ -0,0 +1,97 @@ +/**CFile**************************************************************** + + FileName [dsdApi.c] + + PackageName [DSD: Disjoint-support decomposition package.] + + Synopsis [Implementation of API functions.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 8.0. Started - September 22, 2003.] + + Revision [$Id: dsdApi.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dsdInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [APIs of the DSD node.] + + Description [The node's type can be retrieved by calling + Dsd_NodeReadType(). The type is one of the following: constant 1 node, + the buffer (or the elementary variable), OR gate, EXOR gate, or + PRIME function (a non-DSD-decomposable function with more than two + inputs). The return value of Dsd_NodeReadFunc() is the global function + of the DSD node. The return value of Dsd_NodeReadSupp() is the support + of the global function of the DSD node. The array of DSD nodes + returned by Dsd_NodeReadDecs() is the array of decomposition nodes for + the formal inputs of the given node. The number of decomposition entries + returned by Dsd_NodeReadDecsNum() is the number of formal inputs. + The mark is explained below.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dsd_Type_t Dsd_NodeReadType( Dsd_Node_t * p ) { return p->Type; } +DdNode * Dsd_NodeReadFunc( Dsd_Node_t * p ) { return p->G; } +DdNode * Dsd_NodeReadSupp( Dsd_Node_t * p ) { return p->S; } +Dsd_Node_t ** Dsd_NodeReadDecs( Dsd_Node_t * p ) { return p->pDecs; } +Dsd_Node_t * Dsd_NodeReadDec ( Dsd_Node_t * p, int i ) { return p->pDecs[i]; } +int Dsd_NodeReadDecsNum( Dsd_Node_t * p ) { return p->nDecs; } +int Dsd_NodeReadMark( Dsd_Node_t * p ) { return p->Mark; } + +/**Function************************************************************* + + Synopsis [APIs of the DSD node.] + + Description [This API allows the user to set the integer mark in the + given DSD node. The mark is guaranteed to persist as long as the + calls to the decomposition are not performed. In any case, the mark + is useful to associate the node with some temporary information, such + as its number in the DFS ordered list of the DSD nodes or its number in + the BLIF file that it being written.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ){ p->Mark = Mark; } + +/**Function************************************************************* + + Synopsis [APIs of the DSD manager.] + + Description [Allows the use to get hold of an individual leave of + the DSD tree (Dsd_ManagerReadInput) or an individual root of the + decomposition tree (Dsd_ManagerReadRoot). The root may have the + complemented attribute.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i ) { return pMan->pRoots[i]; } +Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ) { return pMan->pInputs[i]; } +Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan ) { return pMan->pConst1; } +DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan ) { return pMan->dd; } + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/bdd/dsd/dsdCheck.c b/abc70930/src/bdd/dsd/dsdCheck.c new file mode 100644 index 00000000..58b824d2 --- /dev/null +++ b/abc70930/src/bdd/dsd/dsdCheck.c @@ -0,0 +1,314 @@ +/**CFile**************************************************************** + + FileName [dsdCheck.c] + + PackageName [DSD: Disjoint-support decomposition package.] + + Synopsis [Procedures to check the identity of root functions.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 8.0. Started - September 22, 2003.] + + Revision [$Id: dsdCheck.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dsdInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Dsd_Cache_t_ Dds_Cache_t; +typedef struct Dsd_Entry_t_ Dsd_Entry_t; + +struct Dsd_Cache_t_ +{ + Dsd_Entry_t * pTable; + int nTableSize; + int nSuccess; + int nFailure; +}; + +struct Dsd_Entry_t_ +{ + DdNode * bX[5]; +}; + +static Dds_Cache_t * pCache; + +static int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function******************************************************************** + + Synopsis [(Re)allocates the local cache.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Dsd_CheckCacheAllocate( int nEntries ) +{ + int nRequested; + + pCache = ALLOC( Dds_Cache_t, 1 ); + memset( pCache, 0, sizeof(Dds_Cache_t) ); + + // check what is the size of the current cache + nRequested = Cudd_Prime( nEntries ); + if ( pCache->nTableSize != nRequested ) + { // the current size is different + // deallocate the old, allocate the new + if ( pCache->nTableSize ) + Dsd_CheckCacheDeallocate(); + // allocate memory for the hash table + pCache->nTableSize = nRequested; + pCache->pTable = ALLOC( Dsd_Entry_t, nRequested ); + } + // otherwise, there is no need to allocate, just clean + Dsd_CheckCacheClear(); +// printf( "\nThe number of allocated cache entries = %d.\n\n", pCache->nTableSize ); +} + +/**Function******************************************************************** + + Synopsis [Deallocates the local cache.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Dsd_CheckCacheDeallocate() +{ + free( pCache->pTable ); + free( pCache ); +} + +/**Function******************************************************************** + + Synopsis [Clears the local cache.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Dsd_CheckCacheClear() +{ + int i; + for ( i = 0; i < pCache->nTableSize; i++ ) + pCache->pTable[0].bX[0] = NULL; +} + + +/**Function******************************************************************** + + Synopsis [Checks whether it is true that bF1(bC1=0) == bF2(bC2=0).] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ) +{ + int RetValue; +// pCache->nSuccess = 0; +// pCache->nFailure = 0; + RetValue = Dsd_CheckRootFunctionIdentity_rec(dd, bF1, bF2, bC1, bC2); +// printf( "Cache success = %d. Cache failure = %d.\n", pCache->nSuccess, pCache->nFailure ); + return RetValue; +} + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Dsd_CheckRootFunctionIdentity().] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ) +{ + unsigned HKey; + + // if either bC1 or bC2 is zero, the test is true +// if ( bC1 == b0 || bC2 == b0 ) return 1; + assert( bC1 != b0 ); + assert( bC2 != b0 ); + + // if both bC1 and bC2 are one - perform comparison + if ( bC1 == b1 && bC2 == b1 ) return (int)( bF1 == bF2 ); + + if ( bF1 == b0 ) + return Cudd_bddLeq( dd, bC2, Cudd_Not(bF2) ); + + if ( bF1 == b1 ) + return Cudd_bddLeq( dd, bC2, bF2 ); + + if ( bF2 == b0 ) + return Cudd_bddLeq( dd, bC1, Cudd_Not(bF1) ); + + if ( bF2 == b1 ) + return Cudd_bddLeq( dd, bC1, bF1 ); + + // otherwise, keep expanding + + // check cache +// HKey = _Hash( ((unsigned)bF1), ((unsigned)bF2), ((unsigned)bC1), ((unsigned)bC2) ); + HKey = hashKey4( bF1, bF2, bC1, bC2, pCache->nTableSize ); + if ( pCache->pTable[HKey].bX[0] == bF1 && + pCache->pTable[HKey].bX[1] == bF2 && + pCache->pTable[HKey].bX[2] == bC1 && + pCache->pTable[HKey].bX[3] == bC2 ) + { + pCache->nSuccess++; + return (int)pCache->pTable[HKey].bX[4]; // the last bit records the result (yes/no) + } + else + { + + // determine the top variables + int RetValue; + DdNode * bA[4] = { bF1, bF2, bC1, bC2 }; // arguments + DdNode * bAR[4] = { Cudd_Regular(bF1), Cudd_Regular(bF2), Cudd_Regular(bC1), Cudd_Regular(bC2) }; // regular arguments + int CurLevel[4] = { cuddI(dd,bAR[0]->index), cuddI(dd,bAR[1]->index), cuddI(dd,bAR[2]->index), cuddI(dd,bAR[3]->index) }; + int TopLevel = CUDD_CONST_INDEX; + int i; + DdNode * bE[4], * bT[4]; + DdNode * bF1next, * bF2next, * bC1next, * bC2next; + + pCache->nFailure++; + + // determine the top level + for ( i = 0; i < 4; i++ ) + if ( TopLevel > CurLevel[i] ) + TopLevel = CurLevel[i]; + + // compute the cofactors + for ( i = 0; i < 4; i++ ) + if ( TopLevel == CurLevel[i] ) + { + if ( bA[i] != bAR[i] ) // complemented + { + bE[i] = Cudd_Not(cuddE(bAR[i])); + bT[i] = Cudd_Not(cuddT(bAR[i])); + } + else + { + bE[i] = cuddE(bAR[i]); + bT[i] = cuddT(bAR[i]); + } + } + else + bE[i] = bT[i] = bA[i]; + + // solve subproblems + // three cases are possible + + // (1) the top var belongs to both C1 and C2 + // in this case, any cofactor of F1 and F2 will do, + // as long as the corresponding cofactor of C1 and C2 is not equal to 0 + if ( TopLevel == CurLevel[2] && TopLevel == CurLevel[3] ) + { + if ( bE[2] != b0 ) // C1 + { + bF1next = bE[0]; + bC1next = bE[2]; + } + else + { + bF1next = bT[0]; + bC1next = bT[2]; + } + if ( bE[3] != b0 ) // C2 + { + bF2next = bE[1]; + bC2next = bE[3]; + } + else + { + bF2next = bT[1]; + bC2next = bT[3]; + } + RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bF2next, bC1next, bC2next ); + } + // (2) the top var belongs to either C1 or C2 + // in this case normal splitting of cofactors + else if ( TopLevel == CurLevel[2] && TopLevel != CurLevel[3] ) + { + if ( bE[2] != b0 ) // C1 + { + bF1next = bE[0]; + bC1next = bE[2]; + } + else + { + bF1next = bT[0]; + bC1next = bT[2]; + } + // split around this variable + RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bE[1], bC1next, bE[3] ); + if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test + RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bT[1], bC1next, bT[3] ); + } + else if ( TopLevel != CurLevel[2] && TopLevel == CurLevel[3] ) + { + if ( bE[3] != b0 ) // C2 + { + bF2next = bE[1]; + bC2next = bE[3]; + } + else + { + bF2next = bT[1]; + bC2next = bT[3]; + } + // split around this variable + RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bF2next, bE[2], bC2next ); + if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test + RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bF2next, bT[2], bC2next ); + } + // (3) the top var does not belong to C1 and C2 + // in this case normal splitting of cofactors + else // if ( TopLevel != CurLevel[2] && TopLevel != CurLevel[3] ) + { + // split around this variable + RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bE[1], bE[2], bE[3] ); + if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test + RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bT[1], bT[2], bT[3] ); + } + + // set cache + for ( i = 0; i < 4; i++ ) + pCache->pTable[HKey].bX[i] = bA[i]; + pCache->pTable[HKey].bX[4] = (DdNode*)RetValue; + + return RetValue; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/bdd/dsd/dsdInt.h b/abc70930/src/bdd/dsd/dsdInt.h new file mode 100644 index 00000000..62ce7e99 --- /dev/null +++ b/abc70930/src/bdd/dsd/dsdInt.h @@ -0,0 +1,91 @@ +/**CFile**************************************************************** + + FileName [dsdInt.h] + + PackageName [DSD: Disjoint-support decomposition package.] + + Synopsis [Internal declarations of the package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 8.0. Started - September 22, 2003.] + + Revision [$Id: dsdInt.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __DSD_INT_H__ +#define __DSD_INT_H__ + +#include "extra.h" +#include "dsd.h" + +//////////////////////////////////////////////////////////////////////// +/// TYPEDEF DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef unsigned char byte; + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// DSD manager +struct Dsd_Manager_t_ +{ + DdManager * dd; // the BDD manager + st_table * Table; // the mapping of BDDs into their DEs + int nInputs; // the number of primary inputs + int nRoots; // the number of primary outputs + int nRootsAlloc;// the number of primary outputs + Dsd_Node_t ** pInputs; // the primary input nodes + Dsd_Node_t ** pRoots; // the primary output nodes + Dsd_Node_t * pConst1; // the constant node + int fVerbose; // the verbosity level +}; + +// DSD node +struct Dsd_Node_t_ +{ + Dsd_Type_t Type; // decomposition type + DdNode * G; // function of the node + DdNode * S; // support of this function + Dsd_Node_t ** pDecs; // pointer to structures for formal inputs + int Mark; // the mark used by CASE 4 of disjoint decomposition + short nDecs; // the number of formal inputs + short nVisits; // the counter of visits +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define MAXINPUTS 1000 + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== dsdCheck.c =======================================================*/ +extern void Dsd_CheckCacheAllocate( int nEntries ); +extern void Dsd_CheckCacheDeallocate(); +extern void Dsd_CheckCacheClear(); +extern int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ); +/*=== dsdTree.c =======================================================*/ +extern Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum ); +extern void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode ); +extern void Dsd_TreeUnmark( Dsd_Manager_t * dMan ); +extern DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/bdd/dsd/dsdLocal.c b/abc70930/src/bdd/dsd/dsdLocal.c new file mode 100644 index 00000000..6dd6e7d1 --- /dev/null +++ b/abc70930/src/bdd/dsd/dsdLocal.c @@ -0,0 +1,337 @@ +/**CFile**************************************************************** + + FileName [dsdLocal.c] + + PackageName [DSD: Disjoint-support decomposition package.] + + Synopsis [Deriving the local function of the DSD node.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 8.0. Started - September 22, 2003.] + + Revision [$Id: dsdLocal.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dsdInt.h" + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STATIC VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +static DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bFunc, st_table * pCache, + int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ); +static DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the local function of the DSD node. ] + + Description [The local function is computed using the global function + of the node and the global functions of the formal inputs. The resulting + local function is mapped using the topmost N variables of the manager. + The number of variables N is equal to the number of formal inputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ) +{ + int * pForm2Var; // the mapping of each formal input into its first var + int * pVar2Form; // the mapping of each var into its formal inputs + int i, iVar, iLev, * pPermute; + DdNode ** pbCube0, ** pbCube1; + DdNode * bFunc, * bRes, * bTemp; + st_table * pCache; + + pPermute = ALLOC( int, dd->size ); + pVar2Form = ALLOC( int, dd->size ); + pForm2Var = ALLOC( int, dd->size ); + + pbCube0 = ALLOC( DdNode *, dd->size ); + pbCube1 = ALLOC( DdNode *, dd->size ); + + // remap the global function in such a way that + // the support variables of each formal input are adjacent + iLev = 0; + for ( i = 0; i < pNode->nDecs; i++ ) + { + pForm2Var[i] = dd->invperm[i]; + for ( bTemp = pNode->pDecs[i]->S; bTemp != b1; bTemp = cuddT(bTemp) ) + { + iVar = dd->invperm[iLev]; + pPermute[bTemp->index] = iVar; + pVar2Form[iVar] = i; + iLev++; + } + + // collect the cubes representing each assignment + pbCube0[i] = Extra_bddGetOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); + Cudd_Ref( pbCube0[i] ); + pbCube1[i] = Extra_bddGetOneCube( dd, pNode->pDecs[i]->G ); + Cudd_Ref( pbCube1[i] ); + } + + // remap the function + bFunc = Cudd_bddPermute( dd, pNode->G, pPermute ); Cudd_Ref( bFunc ); + // remap the cube + for ( i = 0; i < pNode->nDecs; i++ ) + { + pbCube0[i] = Cudd_bddPermute( dd, bTemp = pbCube0[i], pPermute ); Cudd_Ref( pbCube0[i] ); + Cudd_RecursiveDeref( dd, bTemp ); + pbCube1[i] = Cudd_bddPermute( dd, bTemp = pbCube1[i], pPermute ); Cudd_Ref( pbCube1[i] ); + Cudd_RecursiveDeref( dd, bTemp ); + } + + // remap the function + pCache = st_init_table(st_ptrcmp,st_ptrhash); + bRes = Extra_dsdRemap( dd, bFunc, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes ); + st_free_table( pCache ); + + Cudd_RecursiveDeref( dd, bFunc ); + for ( i = 0; i < pNode->nDecs; i++ ) + { + Cudd_RecursiveDeref( dd, pbCube0[i] ); + Cudd_RecursiveDeref( dd, pbCube1[i] ); + } +/* +//////////// + // permute the function once again + // in such a way that i-th var stood for i-th formal input + for ( i = 0; i < dd->size; i++ ) + pPermute[i] = -1; + for ( i = 0; i < pNode->nDecs; i++ ) + pPermute[dd->invperm[i]] = i; + bRes = Cudd_bddPermute( dd, bTemp = bRes, pPermute ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); +//////////// +*/ + FREE(pPermute); + FREE(pVar2Form); + FREE(pForm2Var); + FREE(pbCube0); + FREE(pbCube1); + + Cudd_Deref( bRes ); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bF, st_table * pCache, + int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ) +{ + DdNode * bFR, * bF0, * bF1; + DdNode * bRes0, * bRes1, * bRes; + int iForm; + + bFR = Cudd_Regular(bF); + if ( cuddIsConstant(bFR) ) + return bF; + + // check the hash-table + if ( bFR->ref != 1 ) + { + if ( st_lookup( pCache, (char *)bF, (char **)&bRes ) ) + return bRes; + } + + // get the formal input + iForm = pVar2Form[bFR->index]; + + // get the nodes pointed to by the cube + bF0 = Extra_bddNodePointedByCube( dd, bF, pbCube0[iForm] ); + bF1 = Extra_bddNodePointedByCube( dd, bF, pbCube1[iForm] ); + + // call recursively for these nodes + bRes0 = Extra_dsdRemap( dd, bF0, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes0 ); + bRes1 = Extra_dsdRemap( dd, bF1, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes1 ); + + // derive the result using ITE + bRes = Cudd_bddIte( dd, dd->vars[ pForm2Var[iForm] ], bRes1, bRes0 ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bRes1 ); + + // add to the hash table + if ( bFR->ref != 1 ) + st_insert( pCache, (char *)bF, (char *)bRes ); + Cudd_Deref( bRes ); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ) +{ + DdNode * bFR, * bCR; + DdNode * bF0, * bF1; + DdNode * bC0, * bC1; + int LevelF, LevelC; + + assert( bC != b0 ); + if ( bC == b1 ) + return bF; + +// bRes = cuddCacheLookup2( dd, Extra_bddNodePointedByCube, bF, bC ); +// if ( bRes ) +// return bRes; + // there is no need for caching because this operation is very fast + // there will no gain reusing the results of this operations + // instead, it will flush CUDD cache of other useful entries + + + bFR = Cudd_Regular( bF ); + bCR = Cudd_Regular( bC ); + assert( !cuddIsConstant( bFR ) ); + + LevelF = dd->perm[bFR->index]; + LevelC = dd->perm[bCR->index]; + + if ( LevelF <= LevelC ) + { + if ( bFR != bF ) + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + } + else + { + bF0 = bF1 = bF; + } + + if ( LevelC <= LevelF ) + { + if ( bCR != bC ) + { + bC0 = Cudd_Not( cuddE(bCR) ); + bC1 = Cudd_Not( cuddT(bCR) ); + } + else + { + bC0 = cuddE(bCR); + bC1 = cuddT(bCR); + } + } + else + { + bC0 = bC1 = bC; + } + + assert( bC0 == b0 || bC1 == b0 ); + if ( bC0 == b0 ) + return Extra_bddNodePointedByCube( dd, bF1, bC1 ); + return Extra_bddNodePointedByCube( dd, bF0, bC0 ); +} + +#if 0 + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * dsdTreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) +{ + DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; + int i; + int fAllBuffs = 1; + static int Permute[MAXINPUTS]; + + assert( pNode ); + assert( !Dsd_IsComplement( pNode ) ); + assert( pNode->Type == DT_PRIME ); + + // transform the function of this block to depend on inputs + // corresponding to the formal inputs + + // first, substitute those inputs that have some blocks associated with them + // second, remap the inputs to the top of the manager (then, it is easy to output them) + + // start the function + bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); + // go over all primary inputs + for ( i = 0; i < pNode->nDecs; i++ ) + if ( pNode->pDecs[i]->Type != DT_BUF ) // remap only if it is not the buffer + { + bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); + bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); + Cudd_RecursiveDeref( dd, bCube0 ); + + bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); + bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); + Cudd_RecursiveDeref( dd, bCube1 ); + + Cudd_RecursiveDeref( dd, bNewFunc ); + + // use the variable in the i-th level of the manager +// bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); + // use the first variale in the support of the component + bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); + } + + if ( fRemap ) + { + // remap the function to the top of the manager + // remap the function to the first variables of the manager + for ( i = 0; i < pNode->nDecs; i++ ) + // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; + Permute[ pNode->pDecs[i]->S->index ] = i; + + bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + } + + Cudd_Deref( bNewFunc ); + return bNewFunc; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/bdd/dsd/dsdMan.c b/abc70930/src/bdd/dsd/dsdMan.c new file mode 100644 index 00000000..6e43f0f4 --- /dev/null +++ b/abc70930/src/bdd/dsd/dsdMan.c @@ -0,0 +1,114 @@ +/**CFile**************************************************************** + + FileName [dsdMan.c] + + PackageName [DSD: Disjoint-support decomposition package.] + + Synopsis [APIs of the DSD manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 8.0. Started - September 22, 2003.] + + Revision [$Id: dsdMan.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dsdInt.h" + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// API OF DSD MANAGER /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the DSD manager.] + + Description [Takes the started BDD manager and the maximum support size + of the function to be DSD-decomposed. The manager should have at least as + many variables as there are variables in the support. The functions should + be expressed using the first nSuppSizeMax variables in the manager (these + may be ordered not necessarily on top of the manager).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose ) +{ + Dsd_Manager_t * dMan; + Dsd_Node_t * pNode; + int i; + + assert( nSuppMax <= dd->size ); + + dMan = ALLOC( Dsd_Manager_t, 1 ); + memset( dMan, 0, sizeof(Dsd_Manager_t) ); + dMan->dd = dd; + dMan->nInputs = nSuppMax; + dMan->fVerbose = fVerbose; + dMan->nRoots = 0; + dMan->nRootsAlloc = 50; + dMan->pRoots = (Dsd_Node_t **) malloc( dMan->nRootsAlloc * sizeof(Dsd_Node_t *) ); + dMan->pInputs = (Dsd_Node_t **) malloc( dMan->nInputs * sizeof(Dsd_Node_t *) ); + + // create the primary inputs and insert them into the table + dMan->Table = st_init_table(st_ptrcmp, st_ptrhash); + for ( i = 0; i < dMan->nInputs; i++ ) + { + pNode = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, 0 ); + pNode->G = dd->vars[i]; Cudd_Ref( pNode->G ); + pNode->S = dd->vars[i]; Cudd_Ref( pNode->S ); + st_insert( dMan->Table, (char*)dd->vars[i], (char*)pNode ); + dMan->pInputs[i] = pNode; + } + pNode = Dsd_TreeNodeCreate( DSD_NODE_CONST1, 0, 0 ); + pNode->G = b1; Cudd_Ref( pNode->G ); + pNode->S = b1; Cudd_Ref( pNode->S ); + st_insert( dMan->Table, (char*)b1, (char*)pNode ); + dMan->pConst1 = pNode; + + Dsd_CheckCacheAllocate( 5000 ); + return dMan; +} + +/**Function************************************************************* + + Synopsis [Stops the DSD manager.] + + Description [Stopping the DSD manager automatically derefereces and + deallocates all the DSD nodes that were created during the life time + of the DSD manager. As a result, the user does not need to deref or + deallocate any DSD nodes or trees that are derived and placed in + the manager while it exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_ManagerStop( Dsd_Manager_t * dMan ) +{ + st_generator * gen; + Dsd_Node_t * pNode; + DdNode * bFunc; + // delete the nodes + st_foreach_item( dMan->Table, gen, (char**)&bFunc, (char**)&pNode ) + Dsd_TreeNodeDelete( dMan->dd, Dsd_Regular(pNode) ); + st_free_table(dMan->Table); + free( dMan->pInputs ); + free( dMan->pRoots ); + free( dMan ); + Dsd_CheckCacheDeallocate(); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/bdd/dsd/dsdProc.c b/abc70930/src/bdd/dsd/dsdProc.c new file mode 100644 index 00000000..543ad387 --- /dev/null +++ b/abc70930/src/bdd/dsd/dsdProc.c @@ -0,0 +1,1617 @@ +/**CFile**************************************************************** + + FileName [dsdProc.c] + + PackageName [DSD: Disjoint-support decomposition package.] + + Synopsis [The core procedures of the package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 8.0. Started - September 22, 2003.] + + Revision [$Id: dsdProc.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dsdInt.h" + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the most important procedures +void dsdKernelDecompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs ); +static Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * F ); + +// additional procedures +static Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity ); +static int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH ); +static void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor ); +static int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall ); + +// list copying +static void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize ); +static void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int Skipped ); + +// debugging procedures +static int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE ); + +//////////////////////////////////////////////////////////////////////// +/// STATIC VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +// the counter of marks +static int s_Mark; + +// debugging flag +static int s_Show = 0; +// temporary var used for debugging +static int Depth = 0; + +static int s_Loops1; +static int s_Loops2; +static int s_Loops3; +static int s_Pivot; +static int s_PivotNo; +static int s_Common; +static int s_CommonNo; + +static int s_Case4Calls; +static int s_Case4CallsSpecial; + +static int s_Case5; +static int s_Loops2Useless; + + +static int s_DecNodesTotal; +static int s_DecNodesUsed; + +// statistical variables +static int s_nDecBlocks; +static int s_nLiterals; +static int s_nExorGates; +static int s_nReusedBlocks; +static int s_nCascades; +static float s_nArea; +static float s_MaxDelay; +static long s_Time; +static int s_nInvertors; +static int s_nPrimeBlocks; + +static int HashSuccess = 0; +static int HashFailure = 0; + +static int s_CacheEntries; + + +//////////////////////////////////////////////////////////////////////// +/// DECOMPOSITION FUNCTIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs DSD for the array of functions represented by BDDs.] + + Description [This function takes the DSD manager, which should be + previously allocated by the call to Dsd_ManagerStart(). The resulting + DSD tree is stored in the DSD manager (pDsdMan->pRoots, pDsdMan->nRoots). + Access to the tree is through the APIs of the manager. The resulting + tree is a shared DSD DAG for the functions given in the array. For one + function the resulting DAG is always a tree. The root node pointers can + be complemented, as discussed in the literature referred to in "dsd.h". + This procedure can be called repeatedly for different functions. There is + no need to remove the decomposition tree after it is returned, because + the next call to the DSD manager will "recycle" the tree. The user should + not modify or dereference any data associated with the nodes of the + DSD trees (the user can only change the contents of a temporary + mark associated with each node by the calling to Dsd_NodeSetMark()). + All the decomposition trees and intermediate nodes will be removed when + the DSD manager is deallocated at the end by calling Dsd_ManagerStop().] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_Decompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs ) +{ + DdManager * dd = pDsdMan->dd; + int i; + long clk; + Dsd_Node_t * pTemp; + int SumMaxGateSize = 0; + int nDecOutputs = 0; + int nCBFOutputs = 0; +/* +s_Loops1 = 0; +s_Loops2 = 0; +s_Loops3 = 0; +s_Case4Calls = 0; +s_Case4CallsSpecial = 0; +s_Case5 = 0; +s_Loops2Useless = 0; +*/ + // resize the number of roots in the manager + if ( pDsdMan->nRootsAlloc < nFuncs ) + { + if ( pDsdMan->nRootsAlloc > 0 ) + free( pDsdMan->pRoots ); + pDsdMan->nRootsAlloc = nFuncs; + pDsdMan->pRoots = (Dsd_Node_t **) malloc( pDsdMan->nRootsAlloc * sizeof(Dsd_Node_t *) ); + } + + if ( pDsdMan->fVerbose ) + printf( "\nDecomposability statistics for individual outputs:\n" ); + + // set the counter of decomposition nodes + s_nDecBlocks = 0; + + // perform decomposition for all outputs + clk = clock(); + pDsdMan->nRoots = 0; + s_nCascades = 0; + for ( i = 0; i < nFuncs; i++ ) + { + int nLiteralsPrev; + int nDecBlocksPrev; + int nExorGatesPrev; + int nReusedBlocksPres; + int nCascades; + int MaxBlock; + int nPrimeBlocks; + long clk; + + clk = clock(); + nLiteralsPrev = s_nLiterals; + nDecBlocksPrev = s_nDecBlocks; + nExorGatesPrev = s_nExorGates; + nReusedBlocksPres = s_nReusedBlocks; + nPrimeBlocks = s_nPrimeBlocks; + + pDsdMan->pRoots[ pDsdMan->nRoots++ ] = dsdKernelDecompose_rec( pDsdMan, pbFuncs[i] ); + + Dsd_TreeNodeGetInfoOne( pDsdMan->pRoots[i], &nCascades, &MaxBlock ); + s_nCascades = ddMax( s_nCascades, nCascades ); + pTemp = Dsd_Regular(pDsdMan->pRoots[i]); + if ( pTemp->Type != DSD_NODE_PRIME || pTemp->nDecs != Extra_bddSuppSize(dd,pTemp->S) ) + nDecOutputs++; + if ( MaxBlock < 3 ) + nCBFOutputs++; + SumMaxGateSize += MaxBlock; + + if ( pDsdMan->fVerbose ) + { + printf("#%02d: ", i ); + printf("Ins=%2d. ", Cudd_SupportSize(dd,pbFuncs[i]) ); + printf("Gts=%3d. ", Dsd_TreeCountNonTerminalNodesOne( pDsdMan->pRoots[i] ) ); + printf("Pri=%3d. ", Dsd_TreeCountPrimeNodesOne( pDsdMan->pRoots[i] ) ); + printf("Max=%3d. ", MaxBlock ); + printf("Reuse=%2d. ", s_nReusedBlocks-nReusedBlocksPres ); + printf("Csc=%2d. ", nCascades ); + printf("T= %.2f s. ", (float)(clock()-clk)/(float)(CLOCKS_PER_SEC) ) ; + printf("Bdd=%2d. ", Cudd_DagSize(pbFuncs[i]) ); + printf("\n"); + fflush( stdout ); + } + } + assert( pDsdMan->nRoots == nFuncs ); + + if ( pDsdMan->fVerbose ) + { + printf( "\n" ); + printf( "The cumulative decomposability statistics:\n" ); + printf( " Total outputs = %5d\n", nFuncs ); + printf( " Decomposable outputs = %5d\n", nDecOutputs ); + printf( " Completely decomposable outputs = %5d\n", nCBFOutputs ); + printf( " The sum of max gate sizes = %5d\n", SumMaxGateSize ); + printf( " Shared BDD size = %5d\n", Cudd_SharingSize( pbFuncs, nFuncs ) ); + printf( " Decomposition entries = %5d\n", st_count( pDsdMan->Table ) ); + printf( " Pure decomposition time = %.2f sec\n", (float)(clock() - clk)/(float)(CLOCKS_PER_SEC) ); + } +/* + printf( "s_Loops1 = %d.\n", s_Loops1 ); + printf( "s_Loops2 = %d.\n", s_Loops2 ); + printf( "s_Loops3 = %d.\n", s_Loops3 ); + printf( "s_Case4Calls = %d.\n", s_Case4Calls ); + printf( "s_Case4CallsSpecial = %d.\n", s_Case4CallsSpecial ); + printf( "s_Case5 = %d.\n", s_Case5 ); + printf( "s_Loops2Useless = %d.\n", s_Loops2Useless ); +*/ +} + +/**Function************************************************************* + + Synopsis [Performs decomposition for one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc ) +{ + return dsdKernelDecompose_rec( pDsdMan, bFunc ); +} + +/**Function************************************************************* + + Synopsis [The main function of this module. Recursive implementation of DSD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * bFunc0 ) +{ + DdManager * dd = pDsdMan->dd; + DdNode * bLow; + DdNode * bLowR; + DdNode * bHigh; + + int VarInt; + DdNode * bVarCur; + Dsd_Node_t * pVarCurDE; + // works only if var indices start from 0!!! + DdNode * bSuppNew = NULL, * bTemp; + + int fContained; + int nSuppLH; + int nSuppL; + int nSuppH; + + + + // various decomposition nodes + Dsd_Node_t * pThis, * pL, * pH, * pLR, * pHR; + + Dsd_Node_t * pSmallR, * pLargeR; + Dsd_Node_t * pTableEntry; + + + // treat the complemented case + DdNode * bF = Cudd_Regular(bFunc0); + int fCompF = (int)(bF != bFunc0); + + // check cache + if ( st_lookup( pDsdMan->Table, (char*)bF, (char**)&pTableEntry ) ) + { // the entry is present + HashSuccess++; + return Dsd_NotCond( pTableEntry, fCompF ); + } + HashFailure++; + Depth++; + + // proceed to consider "four cases" + ////////////////////////////////////////////////////////////////////// + // TERMINAL CASES - CASES 1 and 2 + ////////////////////////////////////////////////////////////////////// + bLow = cuddE(bF); + bLowR = Cudd_Regular(bLow); + bHigh = cuddT(bF); + VarInt = bF->index; + bVarCur = dd->vars[VarInt]; + pVarCurDE = pDsdMan->pInputs[VarInt]; + // works only if var indices start from 0!!! + bSuppNew = NULL; + + if ( bLowR->index == CUDD_CONST_INDEX || bHigh->index == CUDD_CONST_INDEX ) + { // one of the cofactors in the constant + if ( bHigh == b1 ) // bHigh cannot be equal to b0, because then it will be complemented + if ( bLow == b0 ) // bLow cannot be equal to b1, because then the node will have bLow == bHigh + ///////////////////////////////////////////////////////////////// + // bLow == 0, bHigh == 1, F = x'&0 + x&1 = x + ///////////////////////////////////////////////////////////////// + { // create the elementary variable node + assert(0); // should be already in the hash table + pThis = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, s_nDecBlocks++ ); + pThis->pDecs[0] = NULL; + } + else // if ( bLow != constant ) + ///////////////////////////////////////////////////////////////// + // bLow != const, bHigh == 1, F = x'&bLow + x&1 = bLow + x --- DSD_NODE_OR(x,bLow) + ///////////////////////////////////////////////////////////////// + { + pL = dsdKernelDecompose_rec( pDsdMan, bLow ); + pLR = Dsd_Regular( pL ); + bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew); + if ( pLR->Type == DSD_NODE_OR && pL == pLR ) // OR and no complement + { // add to the components + pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pL->nDecs+1, s_nDecBlocks++ ); + dsdKernelCopyListPlusOne( pThis, pVarCurDE, pL->pDecs, pL->nDecs ); + } + else // all other cases + { // create a new 2-input OR-gate + pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); + dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 ); + } + } + else // if ( bHigh != const ) // meaning that bLow should be a constant + { + pH = dsdKernelDecompose_rec( pDsdMan, bHigh ); + pHR = Dsd_Regular( pH ); + bSuppNew = Cudd_bddAnd( dd, bVarCur, pHR->S ); Cudd_Ref(bSuppNew); + if ( bLow == b0 ) + ///////////////////////////////////////////////////////////////// + // Low == 0, High != 1, F = x'&0+x&High = (x'+High')'--- NOR(x',High') + ///////////////////////////////////////////////////////////////// + if ( pHR->Type == DSD_NODE_OR && pH != pHR ) // DSD_NODE_OR and complement + { // add to the components + pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pHR->nDecs+1, s_nDecBlocks++ ); + dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pHR->pDecs, pHR->nDecs ); + pThis = Dsd_Not(pThis); + } + else // all other cases + { // create a new 2-input NOR gate + pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); + pH = Dsd_Not(pH); + dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 ); + pThis = Dsd_Not(pThis); + } + else // if ( bLow == b1 ) + ///////////////////////////////////////////////////////////////// + // Low == 1, High != 1, F = x'&1 + x&High = x' + High --- DSD_NODE_OR(x',High) + ///////////////////////////////////////////////////////////////// + if ( pHR->Type == DSD_NODE_OR && pH == pHR ) // OR and no complement + { // add to the components + pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pH->nDecs+1, s_nDecBlocks++ ); + dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pH->pDecs, pH->nDecs ); + } + else // all other cases + { // create a new 2-input OR-gate + pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); + dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 ); + } + } + goto EXIT; + } + // else if ( bLow != const && bHigh != const ) + + // the case of equal cofactors (up to complementation) + if ( bLowR == bHigh ) + ///////////////////////////////////////////////////////////////// + // Low == G, High == G', F = x'&G + x&G' = (x(+)G) --- EXOR(x,Low) + ///////////////////////////////////////////////////////////////// + { + pL = dsdKernelDecompose_rec( pDsdMan, bLow ); + pLR = Dsd_Regular( pL ); + bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew); + if ( pLR->Type == DSD_NODE_EXOR ) // complemented or not - does not matter! + { // add to the components + pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, pLR->nDecs+1, s_nDecBlocks++ ); + dsdKernelCopyListPlusOne( pThis, pVarCurDE, pLR->pDecs, pLR->nDecs ); + if ( pL != pLR ) + pThis = Dsd_Not( pThis ); + } + else // all other cases + { // create a new 2-input EXOR-gate + pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ ); + if ( pL != pLR ) // complemented + { + dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pLR, 1 ); + pThis = Dsd_Not( pThis ); + } + else // non-complemented + dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 ); + } + goto EXIT; + } + + ////////////////////////////////////////////////////////////////////// + // solve subproblems + ////////////////////////////////////////////////////////////////////// + pL = dsdKernelDecompose_rec( pDsdMan, bLow ); + pH = dsdKernelDecompose_rec( pDsdMan, bHigh ); + pLR = Dsd_Regular( pL ); + pHR = Dsd_Regular( pH ); + + assert( pLR->Type == DSD_NODE_BUF || pLR->Type == DSD_NODE_OR || pLR->Type == DSD_NODE_EXOR || pLR->Type == DSD_NODE_PRIME ); + assert( pHR->Type == DSD_NODE_BUF || pHR->Type == DSD_NODE_OR || pHR->Type == DSD_NODE_EXOR || pHR->Type == DSD_NODE_PRIME ); + +/* +if ( Depth == 1 ) +{ +// PRK(bLow,pDecTreeTotal->nInputs); +// PRK(bHigh,pDecTreeTotal->nInputs); +if ( s_Show ) +{ + PRD( pL ); + PRD( pH ); +} +} +*/ + // compute the new support + bTemp = Cudd_bddAnd( dd, pLR->S, pHR->S ); Cudd_Ref( bTemp ); + nSuppL = Extra_bddSuppSize( dd, pLR->S ); + nSuppH = Extra_bddSuppSize( dd, pHR->S ); + nSuppLH = Extra_bddSuppSize( dd, bTemp ); + bSuppNew = Cudd_bddAnd( dd, bTemp, bVarCur ); Cudd_Ref( bSuppNew ); + Cudd_RecursiveDeref( dd, bTemp ); + + + // several possibilities are possible + // (1) support of one component contains another + // (2) none of the supports is contained in another + fContained = dsdKernelCheckContainment( pDsdMan, pLR, pHR, &pLargeR, &pSmallR ); + + ////////////////////////////////////////////////////////////////////// + // CASE 3.b One of the cofactors in a constant (OR and EXOR) + ////////////////////////////////////////////////////////////////////// + // the support of the larger component should contain the support of the smaller + // it is possible to have PRIME function in this role + // for example: F = ITE( a+b, c(+)d, e+f ), F0 = ITE( b, c(+)d, e+f ), F1 = c(+)d + if ( fContained ) + { + Dsd_Node_t * pSmall, * pLarge; + int c, iCompLarge; // the number of the component is Large is equal to the whole of Small + int fLowIsLarge; + + DdNode * bFTemp; // the changed input function + Dsd_Node_t * pDETemp, * pDENew; + + Dsd_Node_t * pComp = NULL; + int nComp; + + if ( pSmallR == pLR ) + { // Low is Small => High is Large + pSmall = pL; + pLarge = pH; + fLowIsLarge = 0; + } + else + { // vice versa + pSmall = pH; + pLarge = pL; + fLowIsLarge = 1; + } + + // treat the situation when the larger is PRIME + if ( pLargeR->Type == DSD_NODE_PRIME ) //&& pLargeR->nDecs != pSmallR->nDecs ) + { + // QUESTION: Is it possible for pLargeR->nDecs > 3 + // and pSmall contained as one of input in pLarge? + // Yes, for example F = a'c + a & MUX(b,c',d) = a'c + abc' + ab'd is non-decomposable + // Consider the function H(a->xy) = F( xy, b, c, d ) + // H0 = H(x=0) = F(0,b,c,d) = c + // H1 = F(x=1) = F(y,b,c,d) - non-decomposable + // + // QUESTION: Is it possible that pLarge is PRIME(3) and pSmall is OR(2), + // which is not contained in PRIME as one input? + // Yes, for example F = abcd + b'c'd' + a'c'd' = PRIME(ab, c, d) + // F(a=0) = c'd' = NOT(OR(a,d)) F(a=1) = bcd + b'c'd' = PRIME(b,c,d) + // To find decomposition, we have to prove that F(a=1)|b=0 = F(a=0) + + // Is it possible that (pLargeR->nDecs == pSmallR->nDecs) and yet this case holds? + // Yes, consider the function such that F(a=0) = PRIME(a,b+c,d,e) and F(a=1) = OR(b,c,d,e) + // They have the same number of inputs and it is possible that they will be the cofactors + // as discribed in the previous example. + + // find the component, which when substituted for 0 or 1, produces the desired result + int g, fFoundComp; // {0,1} depending on whether setting cofactor to 0 or 1 worked out + + DdNode * bLarge, * bSmall; + if ( fLowIsLarge ) + { + bLarge = bLow; + bSmall = bHigh; + } + else + { + bLarge = bHigh; + bSmall = bLow; + } + + for ( g = 0; g < pLargeR->nDecs; g++ ) +// if ( g != c ) + { + pDETemp = pLargeR->pDecs[g]; // cannot be complemented + if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, pDETemp->G, b1 ) ) + { + fFoundComp = 1; + break; + } + + s_Loops1++; + + if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, Cudd_Not(pDETemp->G), b1 ) ) + { + fFoundComp = 0; + break; + } + + s_Loops1++; + } + + if ( g != pLargeR->nDecs ) + { // decomposition is found + if ( fFoundComp ) + if ( fLowIsLarge ) + bFTemp = Cudd_bddOr( dd, bVarCur, pLargeR->pDecs[g]->G ); + else + bFTemp = Cudd_bddOr( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G ); + else + if ( fLowIsLarge ) + bFTemp = Cudd_bddAnd( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G ); + else + bFTemp = Cudd_bddAnd( dd, bVarCur, pLargeR->pDecs[g]->G ); + Cudd_Ref( bFTemp ); + + pDENew = dsdKernelDecompose_rec( pDsdMan, bFTemp ); + pDENew = Dsd_Regular( pDENew ); + Cudd_RecursiveDeref( dd, bFTemp ); + + // get the new gate + pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLargeR->nDecs, s_nDecBlocks++ ); + dsdKernelCopyListPlusOneMinusOne( pThis, pDENew, pLargeR->pDecs, pLargeR->nDecs, g ); + goto EXIT; + } + } + + // try to find one component in the pLarger that is equal to the whole of pSmaller + for ( c = 0; c < pLargeR->nDecs; c++ ) + if ( pLargeR->pDecs[c] == pSmall || pLargeR->pDecs[c] == Dsd_Not(pSmall) ) + { + iCompLarge = c; + break; + } + + // assign the equal component + if ( c != pLargeR->nDecs ) // the decomposition is possible! + { + pComp = pLargeR->pDecs[iCompLarge]; + nComp = 1; + } + else // the decomposition is still possible + { // for example F = OR(ab,c,d), F(a=0) = OR(c,d), F(a=1) = OR(b,c,d) + // supp(F0) is contained in supp(F1), Polarity(F(a=0)) == Polarity(F(a=1)) + + // try to find a group of common components + if ( pLargeR->Type == pSmallR->Type && + (pLargeR->Type == DSD_NODE_EXOR || pSmallR->Type == DSD_NODE_OR&& ((pLarge==pLargeR) == (pSmall==pSmallR))) ) + { + Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; + int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLargeR, pSmallR, &pCommon, &pLastDiffL, &pLastDiffH ); + // if all the components of pSmall are contained in pLarge, + // then the decomposition exists + if ( nCommon == pSmallR->nDecs ) + { + pComp = pSmallR; + nComp = pSmallR->nDecs; + } + } + } + + if ( pComp ) // the decomposition is possible! + { +// Dsd_Node_t * pComp = pLargeR->pDecs[iCompLarge]; + Dsd_Node_t * pCompR = Dsd_Regular( pComp ); + int fComp1 = (int)( pLarge != pLargeR ); + int fComp2 = (int)( pComp != pCompR ); + int fComp3 = (int)( pSmall != pSmallR ); + + DdNode * bFuncComp; // the function of the given component + DdNode * bFuncNew; // the function of the input component + + if ( pLargeR->Type == DSD_NODE_OR ) // Figure 4 of Matsunaga's paper + { + // the decomposition exists only if the polarity assignment + // along the paths is the same + if ( (fComp1 ^ fComp2) == fComp3 ) + { // decomposition exists = consider 4 cases + // consideration of cases leads to the following conclusion + // fComp1 gives the polarity of the resulting DSD_NODE_OR gate + // fComp2 gives the polarity of the common component feeding into the DSD_NODE_OR gate + // + // | fComp1 pL/ |pS + // <> .........<=>....... <> | + // | / | + // [OR] [OR] | fComp3 + // / \ fComp2 / | \ | + // <> <> .......<=>... /..|..<> | + // / \ / | \| + // [OR] [C] S1 S2 C + // / \ + // <> \ + // / \ + // [OR] [x] + // / \ + // S1 S2 + // + + + // at this point we have the function F (bFTemp) and the common component C (bFuncComp) + // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0 + // we compute the following R = Exist( F - C, supp(C) ) + bFTemp = (fComp1)? Cudd_Not( bF ): bF; + bFuncComp = (fComp2)? Cudd_Not( pCompR->G ): pCompR->G; + bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bFuncComp), pCompR->S ); Cudd_Ref( bFuncNew ); + + // there is no need to copy the dec entry list first, because pComp is a component + // which will not be destroyed by the recursive call to decomposition + pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); + assert( Dsd_IsComplement(pDENew) ); // follows from the consideration of cases + Cudd_RecursiveDeref( dd, bFuncNew ); + + // get the new gate + if ( nComp == 1 ) + { + pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); + pThis->pDecs[0] = pDENew; + pThis->pDecs[1] = pComp; // takes the complement + } + else + { // pComp is not complemented + pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nComp+1, s_nDecBlocks++ ); + dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp ); + } + + if ( fComp1 ) + pThis = Dsd_Not( pThis ); + goto EXIT; + } + } + else if ( pLargeR->Type == DSD_NODE_EXOR ) // Figure 5 of Matsunaga's paper (with correction) + { // decomposition always exists = consider 4 cases + + // consideration of cases leads to the following conclusion + // fComp3 gives the COMPLEMENT of the polarity of the resulting EXOR gate + // (if fComp3 is 0, the EXOR gate is complemented, and vice versa) + // + // | fComp1 pL/ |pS + // <> .........<=>....... /....| fComp3 + // | / | + // [XOR] [XOR] | + // / \ fComp2==0 / | \ | + // / \ / | \ | + // / \ / | \| + // [OR] [C] S1 S2 C + // / \ + // <> \ + // / \ + // [XOR] [x] + // / \ + // S1 S2 + // + + assert( fComp2 == 0 ); + // find the functionality of the lower gates + bFTemp = (fComp3)? bF: Cudd_Not( bF ); + bFuncNew = Cudd_bddXor( dd, bFTemp, pComp->G ); Cudd_Ref( bFuncNew ); + + pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); + assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases + Cudd_RecursiveDeref( dd, bFuncNew ); + + // get the new gate + if ( nComp == 1 ) + { + pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ ); + pThis->pDecs[0] = pDENew; + pThis->pDecs[1] = pComp; + } + else + { // pComp is not complemented + pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nComp+1, s_nDecBlocks++ ); + dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp ); + } + + if ( !fComp3 ) + pThis = Dsd_Not( pThis ); + goto EXIT; + } + } + } + + // this case was added to fix the trivial bug found November 4, 2002 in Japan + // by running the example provided by T. Sasao + if ( nSuppLH == nSuppL + nSuppH ) // the supports of the components are disjoint + { + // create a new component of the type ITE( a, pH, pL ) + pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, 3, s_nDecBlocks++ ); + if ( dd->perm[pLR->S->index] < dd->perm[pHR->S->index] ) // pLR is higher in the varible order + { + pThis->pDecs[1] = pLR; + pThis->pDecs[2] = pHR; + } + else // pHR is higher in the varible order + { + pThis->pDecs[1] = pHR; + pThis->pDecs[2] = pLR; + } + // add the first component + pThis->pDecs[0] = pVarCurDE; + goto EXIT; + } + + + ////////////////////////////////////////////////////////////////////// + // CASE 3.a Neither of the cofactors is a constant (OR, EXOR, PRIME) + ////////////////////////////////////////////////////////////////////// + // the component types are identical + // and if they are OR, they are either both complemented or both not complemented + // and if they are PRIME, their dec numbers should be the same + if ( pLR->Type == pHR->Type && + pLR->Type != DSD_NODE_BUF && + (pLR->Type != DSD_NODE_OR || ( pL == pLR && pH == pHR || pL != pLR && pH != pHR ) ) && + (pLR->Type != DSD_NODE_PRIME || pLR->nDecs == pHR->nDecs) ) + { + // array to store common comps in pL and pH + Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; + int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLR, pHR, &pCommon, &pLastDiffL, &pLastDiffH ); + if ( nCommon ) + { + if ( pLR->Type == DSD_NODE_OR ) // Figure 2 of Matsunaga's paper + { // at this point we have the function F and the group of common components C + // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0 + // we compute the following R = Exist( F - C, supp(C) ) + + // compute the sum total of the common components and the union of their supports + DdNode * bCommF, * bCommS, * bFTemp, * bFuncNew; + Dsd_Node_t * pDENew; + + dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, &bCommS, 0 ); + Cudd_Ref( bCommF ); + Cudd_Ref( bCommS ); + bFTemp = ( pL != pLR )? Cudd_Not(bF): bF; + + bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bCommF), bCommS ); Cudd_Ref( bFuncNew ); + Cudd_RecursiveDeref( dd, bCommF ); + Cudd_RecursiveDeref( dd, bCommS ); + + // get the new gate + + // copy the components first, then call the decomposition + // because decomposition will distroy the list used for copying + pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nCommon + 1, s_nDecBlocks++ ); + dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); + + // call the decomposition recursively + pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); +// assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases + Cudd_RecursiveDeref( dd, bFuncNew ); + + // add the first component + pThis->pDecs[0] = pDENew; + + if ( pL != pLR ) + pThis = Dsd_Not( pThis ); + goto EXIT; + } + else + if ( pLR->Type == DSD_NODE_EXOR ) // Figure 3 of Matsunaga's paper + { + // compute the sum total of the common components and the union of their supports + DdNode * bCommF, * bFuncNew; + Dsd_Node_t * pDENew; + int fCompExor; + + dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, 1 ); + Cudd_Ref( bCommF ); + + bFuncNew = Cudd_bddXor( dd, bF, bCommF ); Cudd_Ref( bFuncNew ); + Cudd_RecursiveDeref( dd, bCommF ); + + // get the new gate + + // copy the components first, then call the decomposition + // because decomposition will distroy the list used for copying + pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nCommon + 1, s_nDecBlocks++ ); + dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); + + // call the decomposition recursively + pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); + Cudd_RecursiveDeref( dd, bFuncNew ); + + // remember the fact that it was complemented + fCompExor = Dsd_IsComplement(pDENew); + pDENew = Dsd_Regular(pDENew); + + // add the first component + pThis->pDecs[0] = pDENew; + + + if ( fCompExor ) + pThis = Dsd_Not( pThis ); + goto EXIT; + } + else + if ( pLR->Type == DSD_NODE_PRIME && (nCommon == pLR->nDecs-1 || nCommon == pLR->nDecs) ) + { + // for example the function F(a,b,c,d) = ITE(b,c,a(+)d) produces + // two cofactors F(a=0) = PRIME(b,c,d) and F(a=1) = PRIME(b,c,d) + // with exactly the same list of common components + + Dsd_Node_t * pDENew; + DdNode * bFuncNew; + int fCompComp = 0; // this flag can be {0,1,2} + // if it is 0 there is no identity + // if it is 1/2, the cofactored functions are equal in the direct/complemented polarity + + if ( nCommon == pLR->nDecs ) + { // all the components are the same + // find the formal input, in which pLow and pHigh differ (if such input exists) + int m; + Dsd_Node_t * pTempL, * pTempH; + + s_Common++; + for ( m = 0; m < pLR->nDecs; m++ ) + { + pTempL = pLR->pDecs[m]; // cannot be complemented + pTempH = pHR->pDecs[m]; // cannot be complemented + + if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pTempL->G, Cudd_Not(pTempH->G) ) && + Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pTempL->G), pTempH->G ) ) + { + pLastDiffL = pTempL; + pLastDiffH = pTempH; + assert( pLastDiffL == pLastDiffH ); + fCompComp = 2; + break; + } + + s_Loops2++; + s_Loops2++; +/* + if ( s_Loops2 % 10000 == 0 ) + { + int i; + for ( i = 0; i < pLR->nDecs; i++ ) + printf( " %d(s=%d)", pLR->pDecs[i]->Type, + Extra_bddSuppSize(dd, pLR->pDecs[i]->S) ); + printf( "\n" ); + } +*/ + + } +// if ( pLR->nDecs == Extra_bddSuppSize(dd, pLR->S) ) +// s_Loops2Useless += pLR->nDecs * 2; + + if ( fCompComp ) + { // put the equal components into pCommon, so that they could be copied into the new dec entry + nCommon = 0; + for ( m = 0; m < pLR->nDecs; m++ ) + if ( pLR->pDecs[m] != pLastDiffL ) + pCommon[nCommon++] = pLR->pDecs[m]; + assert( nCommon = pLR->nDecs-1 ); + } + } + else + { // the differing components are known - check that they have compatible PRIME function + + s_CommonNo++; + + // find the numbers of different components + assert( pLastDiffL ); + assert( pLastDiffH ); + // also, they cannot be complemented, because the decomposition type is PRIME + + if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), Cudd_Not(pLastDiffH->G) ) && + Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, pLastDiffH->G ) ) + fCompComp = 1; + else if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, Cudd_Not(pLastDiffH->G) ) && + Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), pLastDiffH->G ) ) + fCompComp = 2; + + s_Loops3 += 4; + } + + if ( fCompComp ) + { + if ( fCompComp == 1 ) // it is true that bLow(G=0) == bHigh(H=0) && bLow(G=1) == bHigh(H=1) + bFuncNew = Cudd_bddIte( dd, bVarCur, pLastDiffH->G, pLastDiffL->G ); + else // it is true that bLow(G=0) == bHigh(H=1) && bLow(G=1) == bHigh(H=0) + bFuncNew = Cudd_bddIte( dd, bVarCur, Cudd_Not(pLastDiffH->G), pLastDiffL->G ); + Cudd_Ref( bFuncNew ); + + // get the new gate + + // copy the components first, then call the decomposition + // because decomposition will distroy the list used for copying + pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLR->nDecs, s_nDecBlocks++ ); + dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); + + // create a new component + pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); + Cudd_RecursiveDeref( dd, bFuncNew ); + // the BDD of the argument function in PRIME decomposition, should be regular + pDENew = Dsd_Regular(pDENew); + + // add the first component + pThis->pDecs[0] = pDENew; + goto EXIT; + } + } // end of PRIME type + } // end of existing common components + } // end of CASE 3.a + +// if ( Depth != 1) +// { + +//CASE4: + ////////////////////////////////////////////////////////////////////// + // CASE 4 + ////////////////////////////////////////////////////////////////////// + { + // estimate the number of entries in the list + int nEntriesMax = pDsdMan->nInputs - dd->perm[VarInt]; + + // create the new decomposition entry + int nEntries = 0; + + DdNode * SuppL, * SuppH, * SuppL_init, * SuppH_init; + Dsd_Node_t *pHigher, *pLower, * pTemp, * pDENew; + + + int levTopSuppL; + int levTopSuppH; + int levTop; + + pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, nEntriesMax, s_nDecBlocks++ ); + pThis->pDecs[ nEntries++ ] = pVarCurDE; + // other entries will be added to this list one-by-one during analysis + + // count how many times does it happen that the decomposition entries are + s_Case4Calls++; + + // consider the simplest case: when the supports are equal + // and at least one of the components + // is the PRIME without decompositions, or + // when both of them are without decomposition + if ( (((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) || (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) && pLR->S == pHR->S) || + ((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) && (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) ) + { + + s_Case4CallsSpecial++; + // walk through both supports and create the decomposition list composed of simple entries + SuppL = pLR->S; + SuppH = pHR->S; + do + { + // determine levels + levTopSuppL = cuddI(dd,SuppL->index); + levTopSuppH = cuddI(dd,SuppH->index); + + // skip the topmost variable in both supports + if ( levTopSuppL <= levTopSuppH ) + { + levTop = levTopSuppL; + SuppL = cuddT(SuppL); + } + else + levTop = levTopSuppH; + + if ( levTopSuppH <= levTopSuppL ) + SuppH = cuddT(SuppH); + + // set the new decomposition entry + pThis->pDecs[ nEntries++ ] = pDsdMan->pInputs[ dd->invperm[levTop] ]; + } + while ( SuppL != b1 || SuppH != b1 ); + } + else + { + + // compare two different decomposition lists + SuppL_init = pLR->S; + SuppH_init = pHR->S; + // start references (because these supports will change) + SuppL = pLR->S; Cudd_Ref( SuppL ); + SuppH = pHR->S; Cudd_Ref( SuppH ); + while ( SuppL != b1 || SuppH != b1 ) + { + // determine the top level in cofactors and + // whether they have the same top level + int TopLevL = cuddI(dd,SuppL->index); + int TopLevH = cuddI(dd,SuppH->index); + int TopLevel = TopLevH; + int fEqualLevel = 0; + + DdNode * bVarTop; + DdNode * bSuppSubract; + + + if ( TopLevL < TopLevH ) + { + pHigher = pLR; + pLower = pHR; + TopLevel = TopLevL; + } + else if ( TopLevL > TopLevH ) + { + pHigher = pHR; + pLower = pLR; + } + else + fEqualLevel = 1; + assert( TopLevel != CUDD_CONST_INDEX ); + + + // find the currently top variable in the decomposition lists + bVarTop = dd->vars[dd->invperm[TopLevel]]; + + if ( !fEqualLevel ) + { + // find the lower support + DdNode * bSuppLower = (TopLevL < TopLevH)? SuppH_init: SuppL_init; + + // find the first component in pHigher + // whose support does not overlap with supp(Lower) + // and remember the previous component + int fPolarity; + Dsd_Node_t * pPrev = NULL; // the pointer to the component proceeding pCur + Dsd_Node_t * pCur = pHigher; // the first component not contained in supp(Lower) + while ( Extra_bddSuppOverlapping( dd, pCur->S, bSuppLower ) ) + { // get the next component + pPrev = pCur; + pCur = dsdKernelFindContainingComponent( pDsdMan, pCur, bVarTop, &fPolarity ); + }; + + // look for the possibility to subtract more than one component + if ( pPrev == NULL || pPrev->Type == DSD_NODE_PRIME ) + { // if there is no previous component, or if the previous component is PRIME + // there is no way to subtract more than one component + + // add the new decomposition entry (it is already regular) + pThis->pDecs[ nEntries++ ] = pCur; + // assign the support to be subtracted from both components + bSuppSubract = pCur->S; + } + else // all other types + { + // go through the decomposition list of pPrev and find components + // whose support does not overlap with supp(Lower) + + static Dsd_Node_t * pNonOverlap[MAXINPUTS]; + int i, nNonOverlap = 0; + for ( i = 0; i < pPrev->nDecs; i++ ) + { + pTemp = Dsd_Regular( pPrev->pDecs[i] ); + if ( !Extra_bddSuppOverlapping( dd, pTemp->S, bSuppLower ) ) + pNonOverlap[ nNonOverlap++ ] = pPrev->pDecs[i]; + } + assert( nNonOverlap > 0 ); + + if ( nNonOverlap == 1 ) + { // one one component was found, which is the original one + assert( Dsd_Regular(pNonOverlap[0]) == pCur); + // add the new decomposition entry + pThis->pDecs[ nEntries++ ] = pCur; + // assign the support to be subtracted from both components + bSuppSubract = pCur->S; + } + else // more than one components was found + { + // find the OR (EXOR) of the non-overlapping components + DdNode * bCommF; + dsdKernelComputeSumOfComponents( pDsdMan, pNonOverlap, nNonOverlap, &bCommF, NULL, (int)(pPrev->Type==DSD_NODE_EXOR) ); + Cudd_Ref( bCommF ); + + // create a new gated + pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF ); + Cudd_RecursiveDeref(dd, bCommF); + // make it regular... it must be regular already + assert( !Dsd_IsComplement(pDENew) ); + + // add the new decomposition entry + pThis->pDecs[ nEntries++ ] = pDENew; + // assign the support to be subtracted from both components + bSuppSubract = pDENew->S; + } + } + + // subtract its support from the support of upper component + if ( TopLevL < TopLevH ) + { + SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ); Cudd_Ref( SuppL ); + Cudd_RecursiveDeref(dd, bTemp); + } + else + { + SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ); Cudd_Ref( SuppH ); + Cudd_RecursiveDeref(dd, bTemp); + } + } // end of if ( !fEqualLevel ) + else // if ( fEqualLevel ) -- they have the same top level var + { + static Dsd_Node_t * pMarkedLeft[MAXINPUTS]; // the pointers to the marked blocks + static char pMarkedPols[MAXINPUTS]; // polarities of the marked blocks + int nMarkedLeft = 0; + + int fPolarity = 0; + Dsd_Node_t * pTempL = pLR; + + int fPolarityCurH = 0; + Dsd_Node_t * pPrevH = NULL, * pCurH = pHR; + + int fPolarityCurL = 0; + Dsd_Node_t * pPrevL = NULL, * pCurL = pLR; // = pMarkedLeft[0]; + int index = 1; + + // set the new mark + s_Mark++; + + // go over the dec list of pL, mark all components that contain the given variable + assert( Extra_bddSuppContainVar( dd, pLR->S, bVarTop ) ); + assert( Extra_bddSuppContainVar( dd, pHR->S, bVarTop ) ); + do { + pTempL->Mark = s_Mark; + pMarkedLeft[ nMarkedLeft ] = pTempL; + pMarkedPols[ nMarkedLeft ] = fPolarity; + nMarkedLeft++; + } while ( pTempL = dsdKernelFindContainingComponent( pDsdMan, pTempL, bVarTop, &fPolarity ) ); + + // go over the dec list of pH, and find the component that is marked and the previos one + // (such component always exists, because they have common variables) + while ( pCurH->Mark != s_Mark ) + { + pPrevH = pCurH; + pCurH = dsdKernelFindContainingComponent( pDsdMan, pCurH, bVarTop, &fPolarityCurH ); + assert( pCurH ); + } + + // go through the first list once again and find + // the component proceeding the one marked found in the second list + while ( pCurL != pCurH ) + { + pPrevL = pCurL; + pCurL = pMarkedLeft[index]; + fPolarityCurL = pMarkedPols[index]; + index++; + } + + // look for the possibility to subtract more than one component + if ( !pPrevL || !pPrevH || pPrevL->Type != pPrevH->Type || pPrevL->Type == DSD_NODE_PRIME || fPolarityCurL != fPolarityCurH ) + { // there is no way to extract more than one + pThis->pDecs[ nEntries++ ] = pCurH; + // assign the support to be subtracted from both components + bSuppSubract = pCurH->S; + } + else + { + // find the equal components in two decomposition lists + Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; + int nCommon = dsdKernelFindCommonComponents( pDsdMan, pPrevL, pPrevH, &pCommon, &pLastDiffL, &pLastDiffH ); + + if ( nCommon == 0 || nCommon == 1 ) + { // one one component was found, which is the original one + // assert( Dsd_Regular(pCommon[0]) == pCurL); + // add the new decomposition entry + pThis->pDecs[ nEntries++ ] = pCurL; + // assign the support to be subtracted from both components + bSuppSubract = pCurL->S; + } + else // more than one components was found + { + // find the OR (EXOR) of the non-overlapping components + DdNode * bCommF; + dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, (int)(pPrevL->Type==DSD_NODE_EXOR) ); + Cudd_Ref( bCommF ); + + pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF ); + assert( !Dsd_IsComplement(pDENew) ); // cannot be complemented because of construction + Cudd_RecursiveDeref( dd, bCommF ); + + // add the new decomposition entry + pThis->pDecs[ nEntries++ ] = pDENew; + + // assign the support to be subtracted from both components + bSuppSubract = pDENew->S; + } + } + + SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ), Cudd_Ref( SuppL ); + Cudd_RecursiveDeref(dd, bTemp); + + SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ), Cudd_Ref( SuppH ); + Cudd_RecursiveDeref(dd, bTemp); + + } // end of if ( fEqualLevel ) + + } // end of decomposition list comparison + Cudd_RecursiveDeref( dd, SuppL ); + Cudd_RecursiveDeref( dd, SuppH ); + + } + + // check that the estimation of the number of entries was okay + assert( nEntries <= nEntriesMax ); + +// if ( nEntries != Extra_bddSuppSize(dd, bSuppNew) ) +// s_Case5++; + + // update the number of entries in the new decomposition list + pThis->nDecs = nEntries; + } +//} +EXIT: + + { + // if the component created is complemented, it represents a function without complement + // therefore, as it is, without complement, it should recieve the complemented function + Dsd_Node_t * pThisR = Dsd_Regular( pThis ); + assert( pThisR->G == NULL ); + assert( pThisR->S == NULL ); + + if ( pThisR == pThis ) // set regular function + pThisR->G = bF; + else // set complemented function + pThisR->G = Cudd_Not(bF); + Cudd_Ref(bF); // reference the function in the component + + assert( bSuppNew ); + pThisR->S = bSuppNew; // takes the reference from the new support + if ( st_insert( pDsdMan->Table, (char*)bF, (char*)pThis ) ) + { + assert( 0 ); + } + s_CacheEntries++; + + +/* + if ( dsdKernelVerifyDecomposition(dd, pThis) == 0 ) + { + // write the function, for which verification does not work + cout << endl << "Internal verification failed!"" ); + + // create the variable mask + static int s_pVarMask[MAXINPUTS]; + int nInputCounter = 0; + + Cudd_SupportArray( dd, bF, s_pVarMask ); + int k; + for ( k = 0; k < dd->size; k++ ) + if ( s_pVarMask[k] ) + nInputCounter++; + + cout << endl << "The problem function is "" ); + + DdNode * zNewFunc = Cudd_zddIsopCover( dd, bF, bF ); Cudd_Ref( zNewFunc ); + cuddWriteFunctionSop( stdout, dd, zNewFunc, -1, dd->size, "1", s_pVarMask ); + Cudd_RecursiveDerefZdd( dd, zNewFunc ); + } +*/ + + } + + Depth--; + return Dsd_NotCond( pThis, fCompF ); +} + + +//////////////////////////////////////////////////////////////////////// +/// OTHER FUNCTIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Finds the corresponding decomposition entry.] + + Description [This function returns the non-complemented pointer to the + DecEntry of that component which contains the given variable in its + support, or NULL if no such component exists] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity ) + +{ + Dsd_Node_t * pTemp; + int i; + +// assert( !Dsd_IsComplement( pWhere ) ); +// assert( Extra_bddSuppContainVar( pDsdMan->dd, pWhere->S, Var ) ); + + if ( pWhere->nDecs == 1 ) + return NULL; + + for( i = 0; i < pWhere->nDecs; i++ ) + { + pTemp = Dsd_Regular( pWhere->pDecs[i] ); + if ( Extra_bddSuppContainVar( pDsdMan->dd, pTemp->S, Var ) ) + { + *fPolarity = (int)( pTemp != pWhere->pDecs[i] ); + return pTemp; + } + } + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Find the common decomposition components.] + + Description [This function determines the common components. It counts + the number of common components in the decomposition lists of pL and pH + and returns their number and the lists of common components. It assumes + that pL and pH are regular pointers. It retuns also the pointers to the + last different components encountered in pL and pH.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH ) +{ + static Dsd_Node_t * Common[MAXINPUTS]; + int nCommon = 0; + + // pointers to the current decomposition entries + Dsd_Node_t * pLcur; + Dsd_Node_t * pHcur; + + // the pointers to their supports + DdNode * bSLcur; + DdNode * bSHcur; + + // the top variable in the supports + int TopVar; + + // the indices running through the components + int iCurL = 0; + int iCurH = 0; + while ( iCurL < pL->nDecs && iCurH < pH->nDecs ) + { // both did not run out + + pLcur = Dsd_Regular(pL->pDecs[iCurL]); + pHcur = Dsd_Regular(pH->pDecs[iCurH]); + + bSLcur = pLcur->S; + bSHcur = pHcur->S; + + // find out what component is higher in the BDD + if ( pDsdMan->dd->perm[bSLcur->index] < pDsdMan->dd->perm[bSHcur->index] ) + TopVar = bSLcur->index; + else + TopVar = bSHcur->index; + + if ( TopVar == bSLcur->index && TopVar == bSHcur->index ) + { + // the components may be equal - should match exactly! + if ( pL->pDecs[iCurL] == pH->pDecs[iCurH] ) + Common[nCommon++] = pL->pDecs[iCurL]; + else + { + *pLastDiffL = pL->pDecs[iCurL]; + *pLastDiffH = pH->pDecs[iCurH]; + } + + // skip both + iCurL++; + iCurH++; + } + else if ( TopVar == bSLcur->index ) + { // the components cannot be equal + // skip the top-most one + *pLastDiffL = pL->pDecs[iCurL++]; + } + else // if ( TopVar == bSHcur->index ) + { // the components cannot be equal + // skip the top-most one + *pLastDiffH = pH->pDecs[iCurH++]; + } + } + + // if one of the lists still has components, write the first one down + if ( iCurL < pL->nDecs ) + *pLastDiffL = pL->pDecs[iCurL]; + + if ( iCurH < pH->nDecs ) + *pLastDiffH = pH->pDecs[iCurH]; + + // return the pointer to the array + *pCommon = Common; + // return the number of common components + return nCommon; +} + +/**Function************************************************************* + + Synopsis [Computes the sum (OR or EXOR) of the functions of the components.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor ) +{ + DdManager * dd = pDsdMan->dd; + DdNode * bF, * bS, * bFadd, * bTemp; + Dsd_Node_t * pDE, * pDER; + int i; + + // start the function + bF = b0; Cudd_Ref( bF ); + // start the support + if ( pCompS ) + bS = b1, Cudd_Ref( bS ); + + assert( nCommon > 0 ); + for ( i = 0; i < nCommon; i++ ) + { + pDE = pCommon[i]; + pDER = Dsd_Regular( pDE ); + bFadd = (pDE != pDER)? Cudd_Not(pDER->G): pDER->G; + // add to the function + if ( fExor ) + bF = Cudd_bddXor( dd, bTemp = bF, bFadd ); + else + bF = Cudd_bddOr( dd, bTemp = bF, bFadd ); + Cudd_Ref( bF ); + Cudd_RecursiveDeref( dd, bTemp ); + if ( pCompS ) + { + // add to the support + bS = Cudd_bddAnd( dd, bTemp = bS, pDER->S ); Cudd_Ref( bS ); + Cudd_RecursiveDeref( dd, bTemp ); + } + } + // return the function + Cudd_Deref( bF ); + *pCompF = bF; + + // return the support + if ( pCompS ) + Cudd_Deref( bS ), *pCompS = bS; +} + +/**Function************************************************************* + + Synopsis [Checks support containment of the decomposition components.] + + Description [This function returns 1 if support of one component is contained + in that of another. In this case, pLarge (pSmall) is assigned to point to the + larger (smaller) support. If the supports are identical return 0, and does not + assign the components.] +] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall ) +{ + DdManager * dd = pDsdMan->dd; + DdNode * bSuppLarge, * bSuppSmall; + int RetValue; + + RetValue = Extra_bddSuppCheckContainment( dd, pL->S, pH->S, &bSuppLarge, &bSuppSmall ); + + if ( RetValue == 0 ) + return 0; + + if ( pH->S == bSuppLarge ) + { + *pLarge = pH; + *pSmall = pL; + } + else // if ( pL->S == bSuppLarge ) + { + *pLarge = pL; + *pSmall = pH; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Copies the list of components plus one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize ) +{ + int i; + assert( nListSize+1 == p->nDecs ); + p->pDecs[0] = First; + for( i = 0; i < nListSize; i++ ) + p->pDecs[i+1] = ppList[i]; +} + +/**Function************************************************************* + + Synopsis [Copies the list of components plus one, and skips one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int iSkipped ) +{ + int i, Counter; + assert( nListSize == p->nDecs ); + p->pDecs[0] = First; + for( i = 0, Counter = 1; i < nListSize; i++ ) + if ( i != iSkipped ) + p->pDecs[Counter++] = ppList[i]; +} + +/**Function************************************************************* + + Synopsis [Debugging procedure to compute the functionality of the decomposed structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE ) +{ + DdManager * dd = pDsdMan->dd; + Dsd_Node_t * pR = Dsd_Regular(pDE); + int fCompP = (int)( pDE != pR ); + int RetValue; + + DdNode * bRes; + if ( pR->Type == DSD_NODE_CONST1 ) + bRes = b1; + else if ( pR->Type == DSD_NODE_BUF ) + bRes = pR->G; + else if ( pR->Type == DSD_NODE_OR || pR->Type == DSD_NODE_EXOR ) + dsdKernelComputeSumOfComponents( pDsdMan, pR->pDecs, pR->nDecs, &bRes, NULL, (int)(pR->Type == DSD_NODE_EXOR) ); + else if ( pR->Type == DSD_NODE_PRIME ) + { + int i; + static DdNode * bGVars[MAXINPUTS]; + // transform the function of this block, so that it depended on inputs + // corresponding to the formal inputs + DdNode * bNewFunc = Dsd_TreeGetPrimeFunctionOld( dd, pR, 1 ); Cudd_Ref( bNewFunc ); + + // compose this function with the inputs + // create the elementary permutation + for ( i = 0; i < dd->size; i++ ) + bGVars[i] = dd->vars[i]; + + // assign functions to be composed + for ( i = 0; i < pR->nDecs; i++ ) + bGVars[dd->invperm[i]] = pR->pDecs[i]->G; + + // perform the composition + bRes = Cudd_bddVectorCompose( dd, bNewFunc, bGVars ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bNewFunc ); + + ///////////////////////////////////////////////////////// + RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) ); + ///////////////////////////////////////////////////////// + Cudd_Deref( bRes ); + } + else + { + assert(0); + } + + Cudd_Ref( bRes ); + RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) ); + Cudd_RecursiveDeref( dd, bRes ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/bdd/dsd/dsdTree.c b/abc70930/src/bdd/dsd/dsdTree.c new file mode 100644 index 00000000..2855d68d --- /dev/null +++ b/abc70930/src/bdd/dsd/dsdTree.c @@ -0,0 +1,1068 @@ +/**CFile**************************************************************** + + FileName [dsdTree.c] + + PackageName [DSD: Disjoint-support decomposition package.] + + Synopsis [Managing the decomposition tree.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 8.0. Started - September 22, 2003.] + + Revision [$Id: dsdTree.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "dsdInt.h" + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode ); +static void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ); +static int Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode ); +static int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode ); +static int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars ); +static void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes ); +static void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fCcmp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames ); +static void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter ); + +//////////////////////////////////////////////////////////////////////// +/// STATIC VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +static int s_DepthMax; +static int s_GateSizeMax; + +static int s_CounterBlocks; +static int s_CounterPos; +static int s_CounterNeg; +static int s_CounterNo; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create the DSD node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum ) +{ + // allocate memory for this node + Dsd_Node_t * p = (Dsd_Node_t *) malloc( sizeof(Dsd_Node_t) ); + memset( p, 0, sizeof(Dsd_Node_t) ); + p->Type = Type; // the type of this block + p->nDecs = nDecs; // the number of decompositions + if ( p->nDecs ) + { + p->pDecs = (Dsd_Node_t **) malloc( p->nDecs * sizeof(Dsd_Node_t *) ); + p->pDecs[0] = NULL; + } + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the DSD node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode ) +{ + if ( pNode->G ) Cudd_RecursiveDeref( dd, pNode->G ); + if ( pNode->S ) Cudd_RecursiveDeref( dd, pNode->S ); + FREE( pNode->pDecs ); + FREE( pNode ); +} + +/**Function************************************************************* + + Synopsis [Unmarks the decomposition tree.] + + Description [This function assumes that originally pNode->nVisits are + set to zero!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_TreeUnmark( Dsd_Manager_t * pDsdMan ) +{ + int i; + for ( i = 0; i < pDsdMan->nRoots; i++ ) + Dsd_TreeUnmark_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); +} + + +/**Function************************************************************* + + Synopsis [Recursive unmarking.] + + Description [This function should be called with a non-complemented + pointer.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode ) +{ + int i; + + assert( pNode ); + assert( !Dsd_IsComplement( pNode ) ); + assert( pNode->nVisits > 0 ); + + if ( --pNode->nVisits ) // if this is not the last visit, return + return; + + // upon the last visit, go through the list of successors and call recursively + if ( pNode->Type != DSD_NODE_BUF && pNode->Type != DSD_NODE_CONST1 ) + for ( i = 0; i < pNode->nDecs; i++ ) + Dsd_TreeUnmark_rec( Dsd_Regular(pNode->pDecs[i]) ); +} + +/**Function************************************************************* + + Synopsis [Getting information about the node.] + + Description [This function computes the max depth and the max gate size + of the tree rooted at the node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_TreeNodeGetInfo( Dsd_Manager_t * pDsdMan, int * DepthMax, int * GateSizeMax ) +{ + int i; + s_DepthMax = 0; + s_GateSizeMax = 0; + + for ( i = 0; i < pDsdMan->nRoots; i++ ) + Dsd_TreeGetInfo_rec( Dsd_Regular( pDsdMan->pRoots[i] ), 0 ); + + if ( DepthMax ) + *DepthMax = s_DepthMax; + if ( GateSizeMax ) + *GateSizeMax = s_GateSizeMax; +} + +/**Function************************************************************* + + Synopsis [Getting information about the node.] + + Description [This function computes the max depth and the max gate size + of the tree rooted at the node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax ) +{ + s_DepthMax = 0; + s_GateSizeMax = 0; + + Dsd_TreeGetInfo_rec( Dsd_Regular(pNode), 0 ); + + if ( DepthMax ) + *DepthMax = s_DepthMax; + if ( GateSizeMax ) + *GateSizeMax = s_GateSizeMax; +} + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Dsd_TreeNodeGetInfo().] + + Description [pNode is the node, for the tree rooted in which we are + determining info. RankCur is the current rank to assign to the node. + fSetRank is the flag saying whether the rank will be written in the + node. s_DepthMax is the maximum depths of the tree. s_GateSizeMax is + the maximum gate size.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ) +{ + int i; + int GateSize; + + assert( pNode ); + assert( !Dsd_IsComplement( pNode ) ); + assert( pNode->nVisits >= 0 ); + + // we don't want the two-input gates to count for non-decomposable blocks + if ( pNode->Type == DSD_NODE_OR || + pNode->Type == DSD_NODE_EXOR ) + GateSize = 2; + else + GateSize = pNode->nDecs; + + // update the max size of the node + if ( s_GateSizeMax < GateSize ) + s_GateSizeMax = GateSize; + + if ( pNode->nDecs < 2 ) + return; + + // update the max rank + if ( s_DepthMax < RankCur+1 ) + s_DepthMax = RankCur+1; + + // call recursively + for ( i = 0; i < pNode->nDecs; i++ ) + Dsd_TreeGetInfo_rec( Dsd_Regular(pNode->pDecs[i]), RankCur+1 ); +} + +/**Function************************************************************* + + Synopsis [Counts AIG nodes needed to implement this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeGetAigCost_rec( Dsd_Node_t * pNode ) +{ + int i, Counter = 0; + + assert( pNode ); + assert( !Dsd_IsComplement( pNode ) ); + assert( pNode->nVisits >= 0 ); + + if ( pNode->nDecs < 2 ) + return 0; + + // we don't want the two-input gates to count for non-decomposable blocks + if ( pNode->Type == DSD_NODE_OR ) + Counter += pNode->nDecs - 1; + else if ( pNode->Type == DSD_NODE_EXOR ) + Counter += 3*(pNode->nDecs - 1); + else if ( pNode->Type == DSD_NODE_PRIME && pNode->nDecs == 3 ) + Counter += 3; + + // call recursively + for ( i = 0; i < pNode->nDecs; i++ ) + Counter += Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode->pDecs[i]) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts AIG nodes needed to implement this node.] + + Description [Assumes that the only primes of the DSD tree are MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeGetAigCost( Dsd_Node_t * pNode ) +{ + return Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Counts non-terminal nodes of the DSD tree.] + + Description [Nonterminal nodes include all the nodes with the + support more than 1. These are OR, EXOR, and PRIME nodes. They + do not include the elementary variable nodes and the constant 1 + node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * pDsdMan ) +{ + int Counter, i; + Counter = 0; + for ( i = 0; i < pDsdMan->nRoots; i++ ) + Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); + Dsd_TreeUnmark( pDsdMan ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot ) +{ + int Counter = 0; + + // go through the list of successors and call recursively + Counter = Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pRoot) ); + + Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) ); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Counts non-terminal nodes for one root.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode ) +{ + int i; + int Counter = 0; + + assert( pNode ); + assert( !Dsd_IsComplement( pNode ) ); + assert( pNode->nVisits >= 0 ); + + if ( pNode->nVisits++ ) // if this is not the first visit, return zero + return 0; + + if ( pNode->nDecs <= 1 ) + return 0; + + // upon the first visit, go through the list of successors and call recursively + for ( i = 0; i < pNode->nDecs; i++ ) + Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pNode->pDecs[i]) ); + + return Counter + 1; +} + + +/**Function************************************************************* + + Synopsis [Counts prime nodes of the DSD tree.] + + Description [Prime nodes are nodes with the support more than 2, + that is not an OR or EXOR gate.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan ) +{ + int Counter, i; + Counter = 0; + for ( i = 0; i < pDsdMan->nRoots; i++ ) + Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); + Dsd_TreeUnmark( pDsdMan ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts prime nodes for one root.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot ) +{ + int Counter = 0; + + // go through the list of successors and call recursively + Counter = Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pRoot) ); + + Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) ); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode ) +{ + int i; + int Counter = 0; + + assert( pNode ); + assert( !Dsd_IsComplement( pNode ) ); + assert( pNode->nVisits >= 0 ); + + if ( pNode->nVisits++ ) // if this is not the first visit, return zero + return 0; + + if ( pNode->nDecs <= 1 ) + return 0; + + // upon the first visit, go through the list of successors and call recursively + for ( i = 0; i < pNode->nDecs; i++ ) + Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pNode->pDecs[i]) ); + + if ( pNode->Type == DSD_NODE_PRIME ) + Counter++; + + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Collects the decomposable vars on the PI side.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * pDsdMan, int * pVars ) +{ + int nVars; + + // set the vars collected to 0 + nVars = 0; + Dsd_TreeCollectDecomposableVars_rec( pDsdMan->dd, Dsd_Regular(pDsdMan->pRoots[0]), pVars, &nVars ); + // return the number of collected vars + return nVars; +} + +/**Function************************************************************* + + Synopsis [Implements the recursive part of Dsd_TreeCollectDecomposableVars().] + + Description [Adds decomposable variables as they are found to pVars and increments + nVars. Returns 1 if a non-dec node with more than 4 inputs was encountered + in the processed subtree. Returns 0, otherwise. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars ) +{ + int fSkipThisNode, i; + Dsd_Node_t * pTemp; + int fVerbose = 0; + + assert( pNode ); + assert( !Dsd_IsComplement( pNode ) ); + + if ( pNode->nDecs <= 1 ) + return 0; + + // go through the list of successors and call recursively + fSkipThisNode = 0; + for ( i = 0; i < pNode->nDecs; i++ ) + if ( Dsd_TreeCollectDecomposableVars_rec(dd, Dsd_Regular(pNode->pDecs[i]), pVars, nVars) ) + fSkipThisNode = 1; + + if ( !fSkipThisNode && (pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR || pNode->nDecs <= 4) ) + { +if ( fVerbose ) +printf( "Node of type <%d> (OR=6,EXOR=8,RAND=1): ", pNode->Type ); + + for ( i = 0; i < pNode->nDecs; i++ ) + { + pTemp = Dsd_Regular(pNode->pDecs[i]); + if ( pTemp->Type == DSD_NODE_BUF ) + { + if ( pVars ) + pVars[ (*nVars)++ ] = pTemp->S->index; + else + (*nVars)++; + +if ( fVerbose ) +printf( "%d ", pTemp->S->index ); + } + } +if ( fVerbose ) +printf( "\n" ); + } + else + fSkipThisNode = 1; + + + return fSkipThisNode; +} + + +/**Function************************************************************* + + Synopsis [Creates the DFS ordered array of DSD nodes in the tree.] + + Description [The collected nodes do not include the terminal nodes + and the constant 1 node. The array of nodes is returned. The number + of entries in the array is returned in the variale pnNodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * pDsdMan, int * pnNodes ) +{ + Dsd_Node_t ** ppNodes; + int nNodes, nNodesAlloc; + int i; + + nNodesAlloc = Dsd_TreeCountNonTerminalNodes(pDsdMan); + nNodes = 0; + ppNodes = ALLOC( Dsd_Node_t *, nNodesAlloc ); + for ( i = 0; i < pDsdMan->nRoots; i++ ) + Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pDsdMan->pRoots[i]), ppNodes, &nNodes ); + Dsd_TreeUnmark( pDsdMan ); + assert( nNodesAlloc == nNodes ); + *pnNodes = nNodes; + return ppNodes; +} + +/**Function************************************************************* + + Synopsis [Creates the DFS ordered array of DSD nodes in the tree.] + + Description [The collected nodes do not include the terminal nodes + and the constant 1 node. The array of nodes is returned. The number + of entries in the array is returned in the variale pnNodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes ) +{ + Dsd_Node_t ** ppNodes; + int nNodes, nNodesAlloc; + nNodesAlloc = Dsd_TreeCountNonTerminalNodesOne(pNode); + nNodes = 0; + ppNodes = ALLOC( Dsd_Node_t *, nNodesAlloc ); + Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode), ppNodes, &nNodes ); + Dsd_TreeUnmark_rec(Dsd_Regular(pNode)); + assert( nNodesAlloc == nNodes ); + *pnNodes = nNodes; + return ppNodes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes ) +{ + int i; + assert( pNode ); + assert( !Dsd_IsComplement(pNode) ); + assert( pNode->nVisits >= 0 ); + + if ( pNode->nVisits++ ) // if this is not the first visit, return zero + return; + if ( pNode->nDecs <= 1 ) + return; + + // upon the first visit, go through the list of successors and call recursively + for ( i = 0; i < pNode->nDecs; i++ ) + Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode->pDecs[i]), ppNodes, pnNodes ); + + ppNodes[ (*pnNodes)++ ] = pNode; +} + +/**Function************************************************************* + + Synopsis [Prints the decompostion tree into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * pDsdMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ) +{ + Dsd_Node_t * pNode; + int SigCounter; + int i; + SigCounter = 1; + + if ( Output == -1 ) + { + for ( i = 0; i < pDsdMan->nRoots; i++ ) + { + pNode = Dsd_Regular( pDsdMan->pRoots[i] ); + Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[i]), pInputNames, pOutputNames[i], 0, &SigCounter, fShortNames ); + } + } + else + { + assert( Output >= 0 && Output < pDsdMan->nRoots ); + pNode = Dsd_Regular( pDsdMan->pRoots[Output] ); + Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[Output]), pInputNames, pOutputNames[Output], 0, &SigCounter, fShortNames ); + } +} + +/**Function************************************************************* + + Synopsis [Prints the decompostion tree into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames ) +{ + char Buffer[100]; + Dsd_Node_t * pInput; + int * pInputNums; + int fCompNew, i; + + assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || + pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); + + Extra_PrintSymbols( pFile, ' ', nOffset, 0 ); + if ( !fComp ) + fprintf( pFile, "%s = ", pOutputName ); + else + fprintf( pFile, "NOT(%s) = ", pOutputName ); + pInputNums = ALLOC( int, pNode->nDecs ); + if ( pNode->Type == DSD_NODE_CONST1 ) + { + fprintf( pFile, " Constant 1.\n" ); + } + else if ( pNode->Type == DSD_NODE_BUF ) + { + if ( fShortNames ) + fprintf( pFile, "%d", 'a' + pNode->S->index ); + else + fprintf( pFile, "%s", pInputNames[pNode->S->index] ); + fprintf( pFile, "\n" ); + } + else if ( pNode->Type == DSD_NODE_PRIME ) + { + // print the line + fprintf( pFile, "PRIME(" ); + for ( i = 0; i < pNode->nDecs; i++ ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + fCompNew = (int)( pInput != pNode->pDecs[i] ); + if ( i ) + fprintf( pFile, "," ); + if ( fCompNew ) + fprintf( pFile, " NOT(" ); + else + fprintf( pFile, " " ); + if ( pInput->Type == DSD_NODE_BUF ) + { + pInputNums[i] = 0; + if ( fShortNames ) + fprintf( pFile, "%d", pInput->S->index ); + else + fprintf( pFile, "%s", pInputNames[pInput->S->index] ); + } + else + { + pInputNums[i] = (*pSigCounter)++; + fprintf( pFile, "<%d>", pInputNums[i] ); + } + if ( fCompNew ) + fprintf( pFile, ")" ); + } + fprintf( pFile, " )\n" ); + // call recursively for the following blocks + for ( i = 0; i < pNode->nDecs; i++ ) + if ( pInputNums[i] ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + sprintf( Buffer, "<%d>", pInputNums[i] ); + Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); + } + } + else if ( pNode->Type == DSD_NODE_OR ) + { + // print the line + fprintf( pFile, "OR(" ); + for ( i = 0; i < pNode->nDecs; i++ ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + fCompNew = (int)( pInput != pNode->pDecs[i] ); + if ( i ) + fprintf( pFile, "," ); + if ( fCompNew ) + fprintf( pFile, " NOT(" ); + else + fprintf( pFile, " " ); + if ( pInput->Type == DSD_NODE_BUF ) + { + pInputNums[i] = 0; + if ( fShortNames ) + fprintf( pFile, "%c", 'a' + pInput->S->index ); + else + fprintf( pFile, "%s", pInputNames[pInput->S->index] ); + } + else + { + pInputNums[i] = (*pSigCounter)++; + fprintf( pFile, "<%d>", pInputNums[i] ); + } + if ( fCompNew ) + fprintf( pFile, ")" ); + } + fprintf( pFile, " )\n" ); + // call recursively for the following blocks + for ( i = 0; i < pNode->nDecs; i++ ) + if ( pInputNums[i] ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + sprintf( Buffer, "<%d>", pInputNums[i] ); + Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); + } + } + else if ( pNode->Type == DSD_NODE_EXOR ) + { + // print the line + fprintf( pFile, "EXOR(" ); + for ( i = 0; i < pNode->nDecs; i++ ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + fCompNew = (int)( pInput != pNode->pDecs[i] ); + if ( i ) + fprintf( pFile, "," ); + if ( fCompNew ) + fprintf( pFile, " NOT(" ); + else + fprintf( pFile, " " ); + if ( pInput->Type == DSD_NODE_BUF ) + { + pInputNums[i] = 0; + if ( fShortNames ) + fprintf( pFile, "%c", 'a' + pInput->S->index ); + else + fprintf( pFile, "%s", pInputNames[pInput->S->index] ); + } + else + { + pInputNums[i] = (*pSigCounter)++; + fprintf( pFile, "<%d>", pInputNums[i] ); + } + if ( fCompNew ) + fprintf( pFile, ")" ); + } + fprintf( pFile, " )\n" ); + // call recursively for the following blocks + for ( i = 0; i < pNode->nDecs; i++ ) + if ( pInputNums[i] ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + sprintf( Buffer, "<%d>", pInputNums[i] ); + Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); + } + } + free( pInputNums ); +} + +/**Function************************************************************* + + Synopsis [Prints the decompostion tree into file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ) +{ + Dsd_Node_t * pNodeR; + int SigCounter = 1; + pNodeR = Dsd_Regular(pNode); + Dsd_NodePrint_rec( pFile, pNodeR, pNodeR != pNode, "F", 0, &SigCounter ); +} + +/**Function************************************************************* + + Synopsis [Prints one node of the decomposition tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter ) +{ + char Buffer[100]; + Dsd_Node_t * pInput; + int * pInputNums; + int fCompNew, i; + + assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || + pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); + + Extra_PrintSymbols( pFile, ' ', nOffset, 0 ); + if ( !fComp ) + fprintf( pFile, "%s = ", pOutputName ); + else + fprintf( pFile, "NOT(%s) = ", pOutputName ); + pInputNums = ALLOC( int, pNode->nDecs ); + if ( pNode->Type == DSD_NODE_CONST1 ) + { + fprintf( pFile, " Constant 1.\n" ); + } + else if ( pNode->Type == DSD_NODE_BUF ) + { + fprintf( pFile, " " ); + fprintf( pFile, "%c", 'a' + pNode->S->index ); + fprintf( pFile, "\n" ); + } + else if ( pNode->Type == DSD_NODE_PRIME ) + { + // print the line + fprintf( pFile, "PRIME(" ); + for ( i = 0; i < pNode->nDecs; i++ ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + fCompNew = (int)( pInput != pNode->pDecs[i] ); + assert( fCompNew == 0 ); + if ( i ) + fprintf( pFile, "," ); + if ( pInput->Type == DSD_NODE_BUF ) + { + pInputNums[i] = 0; + fprintf( pFile, " %c", 'a' + pInput->S->index ); + } + else + { + pInputNums[i] = (*pSigCounter)++; + fprintf( pFile, " <%d>", pInputNums[i] ); + } + if ( fCompNew ) + fprintf( pFile, "\'" ); + } + fprintf( pFile, " )\n" ); +/* + fprintf( pFile, " ) " ); + { + DdNode * bLocal; + bLocal = Dsd_TreeGetPrimeFunction( dd, pNodeDsd ); Cudd_Ref( bLocal ); + Extra_bddPrint( dd, bLocal ); + Cudd_RecursiveDeref( dd, bLocal ); + } +*/ + // call recursively for the following blocks + for ( i = 0; i < pNode->nDecs; i++ ) + if ( pInputNums[i] ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + sprintf( Buffer, "<%d>", pInputNums[i] ); + Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); + } + } + else if ( pNode->Type == DSD_NODE_OR ) + { + // print the line + fprintf( pFile, "OR(" ); + for ( i = 0; i < pNode->nDecs; i++ ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + fCompNew = (int)( pInput != pNode->pDecs[i] ); + if ( i ) + fprintf( pFile, "," ); + if ( pInput->Type == DSD_NODE_BUF ) + { + pInputNums[i] = 0; + fprintf( pFile, " %c", 'a' + pInput->S->index ); + } + else + { + pInputNums[i] = (*pSigCounter)++; + fprintf( pFile, " <%d>", pInputNums[i] ); + } + if ( fCompNew ) + fprintf( pFile, "\'" ); + } + fprintf( pFile, " )\n" ); + // call recursively for the following blocks + for ( i = 0; i < pNode->nDecs; i++ ) + if ( pInputNums[i] ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + sprintf( Buffer, "<%d>", pInputNums[i] ); + Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); + } + } + else if ( pNode->Type == DSD_NODE_EXOR ) + { + // print the line + fprintf( pFile, "EXOR(" ); + for ( i = 0; i < pNode->nDecs; i++ ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + fCompNew = (int)( pInput != pNode->pDecs[i] ); + assert( fCompNew == 0 ); + if ( i ) + fprintf( pFile, "," ); + if ( pInput->Type == DSD_NODE_BUF ) + { + pInputNums[i] = 0; + fprintf( pFile, " %c", 'a' + pInput->S->index ); + } + else + { + pInputNums[i] = (*pSigCounter)++; + fprintf( pFile, " <%d>", pInputNums[i] ); + } + if ( fCompNew ) + fprintf( pFile, "\'" ); + } + fprintf( pFile, " )\n" ); + // call recursively for the following blocks + for ( i = 0; i < pNode->nDecs; i++ ) + if ( pInputNums[i] ) + { + pInput = Dsd_Regular( pNode->pDecs[i] ); + sprintf( Buffer, "<%d>", pInputNums[i] ); + Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); + } + } + free( pInputNums ); +} + + +/**Function************************************************************* + + Synopsis [Retuns the function of one node of the decomposition tree.] + + Description [This is the old procedure. It is now superceded by the + procedure Dsd_TreeGetPrimeFunction() found in "dsdLocal.c".] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) +{ + DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; + int i; + int fAllBuffs = 1; + static int Permute[MAXINPUTS]; + + assert( pNode ); + assert( !Dsd_IsComplement( pNode ) ); + assert( pNode->Type == DSD_NODE_PRIME ); + + // transform the function of this block to depend on inputs + // corresponding to the formal inputs + + // first, substitute those inputs that have some blocks associated with them + // second, remap the inputs to the top of the manager (then, it is easy to output them) + + // start the function + bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); + // go over all primary inputs + for ( i = 0; i < pNode->nDecs; i++ ) + if ( pNode->pDecs[i]->Type != DSD_NODE_BUF ) // remap only if it is not the buffer + { + bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); + bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); + Cudd_RecursiveDeref( dd, bCube0 ); + + bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); + bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); + Cudd_RecursiveDeref( dd, bCube1 ); + + Cudd_RecursiveDeref( dd, bNewFunc ); + + // use the variable in the i-th level of the manager +// bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); + // use the first variale in the support of the component + bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); + } + + if ( fRemap ) + { + // remap the function to the top of the manager + // remap the function to the first variables of the manager + for ( i = 0; i < pNode->nDecs; i++ ) + // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; + Permute[ pNode->pDecs[i]->S->index ] = i; + + bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + } + + Cudd_Deref( bNewFunc ); + return bNewFunc; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/bdd/dsd/module.make b/abc70930/src/bdd/dsd/module.make new file mode 100644 index 00000000..f5e6673d --- /dev/null +++ b/abc70930/src/bdd/dsd/module.make @@ -0,0 +1,6 @@ +SRC += src/bdd/dsd/dsdApi.c \ + src/bdd/dsd/dsdCheck.c \ + src/bdd/dsd/dsdLocal.c \ + src/bdd/dsd/dsdMan.c \ + src/bdd/dsd/dsdProc.c \ + src/bdd/dsd/dsdTree.c diff --git a/abc70930/src/bdd/epd/epd.c b/abc70930/src/bdd/epd/epd.c new file mode 100644 index 00000000..a80240bc --- /dev/null +++ b/abc70930/src/bdd/epd/epd.c @@ -0,0 +1,1314 @@ +/**CFile*********************************************************************** + + FileName [epd.c] + + PackageName [epd] + + Synopsis [Arithmetic functions with extended double precision.] + + Description [] + + SeeAlso [] + + Author [In-Ho Moon] + + Copyright [ This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + + Revision [$Id: epd.c,v 1.1.1.1 2003/02/24 22:23:57 wjiang Exp $] + +******************************************************************************/ + +#include +#include +#include +#include +#include "util_hack.h" +#include "epd.h" + + +/**Function******************************************************************** + + Synopsis [Allocates an EpDouble struct.] + + Description [Allocates an EpDouble struct.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +EpDouble * +EpdAlloc() +{ + EpDouble *epd; + + epd = ALLOC(EpDouble, 1); + return(epd); +} + + +/**Function******************************************************************** + + Synopsis [Compares two EpDouble struct.] + + Description [Compares two EpDouble struct.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +EpdCmp(const char *key1, const char *key2) +{ + EpDouble *epd1 = (EpDouble *) key1; + EpDouble *epd2 = (EpDouble *) key2; + if (epd1->type.value != epd2->type.value || + epd1->exponent != epd2->exponent) { + return(1); + } + return(0); +} + + +/**Function******************************************************************** + + Synopsis [Frees an EpDouble struct.] + + Description [Frees an EpDouble struct.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdFree(EpDouble *epd) +{ + FREE(epd); +} + + +/**Function******************************************************************** + + Synopsis [Multiplies two arbitrary precision double values.] + + Description [Multiplies two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdGetString(EpDouble *epd, char *str) +{ + double value; + int exponent; + char *pos; + + if (IsNanDouble(epd->type.value)) { + sprintf(str, "NaN"); + return; + } else if (IsInfDouble(epd->type.value)) { + if (epd->type.bits.sign == 1) + sprintf(str, "-Inf"); + else + sprintf(str, "Inf"); + return; + } + + assert(epd->type.bits.exponent == EPD_MAX_BIN || + epd->type.bits.exponent == 0); + + EpdGetValueAndDecimalExponent(epd, &value, &exponent); + sprintf(str, "%e", value); + pos = strstr(str, "e"); + if (exponent >= 0) { + if (exponent < 10) + sprintf(pos + 1, "+0%d", exponent); + else + sprintf(pos + 1, "+%d", exponent); + } else { + exponent *= -1; + if (exponent < 10) + sprintf(pos + 1, "-0%d", exponent); + else + sprintf(pos + 1, "-%d", exponent); + } +} + + +/**Function******************************************************************** + + Synopsis [Converts double to EpDouble struct.] + + Description [Converts double to EpDouble struct.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdConvert(double value, EpDouble *epd) +{ + epd->type.value = value; + epd->exponent = 0; + EpdNormalize(epd); +} + + +/**Function******************************************************************** + + Synopsis [Multiplies two arbitrary precision double values.] + + Description [Multiplies two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdMultiply(EpDouble *epd1, double value) +{ + EpDouble epd2; + double tmp; + int exponent; + + if (EpdIsNan(epd1) || IsNanDouble(value)) { + EpdMakeNan(epd1); + return; + } else if (EpdIsInf(epd1) || IsInfDouble(value)) { + int sign; + + EpdConvert(value, &epd2); + sign = epd1->type.bits.sign ^ epd2.type.bits.sign; + EpdMakeInf(epd1, sign); + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + + EpdConvert(value, &epd2); + tmp = epd1->type.value * epd2.type.value; + exponent = epd1->exponent + epd2.exponent; + epd1->type.value = tmp; + epd1->exponent = exponent; + EpdNormalize(epd1); +} + + +/**Function******************************************************************** + + Synopsis [Multiplies two arbitrary precision double values.] + + Description [Multiplies two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdMultiply2(EpDouble *epd1, EpDouble *epd2) +{ + double value; + int exponent; + + if (EpdIsNan(epd1) || EpdIsNan(epd2)) { + EpdMakeNan(epd1); + return; + } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { + int sign; + + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + EpdMakeInf(epd1, sign); + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + assert(epd2->type.bits.exponent == EPD_MAX_BIN); + + value = epd1->type.value * epd2->type.value; + exponent = epd1->exponent + epd2->exponent; + epd1->type.value = value; + epd1->exponent = exponent; + EpdNormalize(epd1); +} + + +/**Function******************************************************************** + + Synopsis [Multiplies two arbitrary precision double values.] + + Description [Multiplies two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2) +{ + double value; + int exponent; + + if (EpdIsNan(epd1) || EpdIsNan(epd2)) { + EpdMakeNan(epd1); + return; + } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { + int sign; + + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + EpdMakeInf(epd1, sign); + return; + } + + value = epd1->type.value * epd2->type.value; + exponent = epd1->exponent + epd2->exponent; + epd1->type.value = value; + epd1->exponent = exponent; + EpdNormalizeDecimal(epd1); +} + + +/**Function******************************************************************** + + Synopsis [Multiplies two arbitrary precision double values.] + + Description [Multiplies two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) +{ + if (EpdIsNan(epd1) || EpdIsNan(epd2)) { + EpdMakeNan(epd1); + return; + } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { + int sign; + + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + EpdMakeInf(epd3, sign); + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + assert(epd2->type.bits.exponent == EPD_MAX_BIN); + + epd3->type.value = epd1->type.value * epd2->type.value; + epd3->exponent = epd1->exponent + epd2->exponent; + EpdNormalize(epd3); +} + + +/**Function******************************************************************** + + Synopsis [Multiplies two arbitrary precision double values.] + + Description [Multiplies two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) +{ + if (EpdIsNan(epd1) || EpdIsNan(epd2)) { + EpdMakeNan(epd1); + return; + } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { + int sign; + + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + EpdMakeInf(epd3, sign); + return; + } + + epd3->type.value = epd1->type.value * epd2->type.value; + epd3->exponent = epd1->exponent + epd2->exponent; + EpdNormalizeDecimal(epd3); +} + + +/**Function******************************************************************** + + Synopsis [Divides two arbitrary precision double values.] + + Description [Divides two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdDivide(EpDouble *epd1, double value) +{ + EpDouble epd2; + double tmp; + int exponent; + + if (EpdIsNan(epd1) || IsNanDouble(value)) { + EpdMakeNan(epd1); + return; + } else if (EpdIsInf(epd1) || IsInfDouble(value)) { + int sign; + + EpdConvert(value, &epd2); + if (EpdIsInf(epd1) && IsInfDouble(value)) { + EpdMakeNan(epd1); + } else if (EpdIsInf(epd1)) { + sign = epd1->type.bits.sign ^ epd2.type.bits.sign; + EpdMakeInf(epd1, sign); + } else { + sign = epd1->type.bits.sign ^ epd2.type.bits.sign; + EpdMakeZero(epd1, sign); + } + return; + } + + if (value == 0.0) { + EpdMakeNan(epd1); + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + + EpdConvert(value, &epd2); + tmp = epd1->type.value / epd2.type.value; + exponent = epd1->exponent - epd2.exponent; + epd1->type.value = tmp; + epd1->exponent = exponent; + EpdNormalize(epd1); +} + + +/**Function******************************************************************** + + Synopsis [Divides two arbitrary precision double values.] + + Description [Divides two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdDivide2(EpDouble *epd1, EpDouble *epd2) +{ + double value; + int exponent; + + if (EpdIsNan(epd1) || EpdIsNan(epd2)) { + EpdMakeNan(epd1); + return; + } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { + int sign; + + if (EpdIsInf(epd1) && EpdIsInf(epd2)) { + EpdMakeNan(epd1); + } else if (EpdIsInf(epd1)) { + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + EpdMakeInf(epd1, sign); + } else { + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + EpdMakeZero(epd1, sign); + } + return; + } + + if (epd2->type.value == 0.0) { + EpdMakeNan(epd1); + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + assert(epd2->type.bits.exponent == EPD_MAX_BIN); + + value = epd1->type.value / epd2->type.value; + exponent = epd1->exponent - epd2->exponent; + epd1->type.value = value; + epd1->exponent = exponent; + EpdNormalize(epd1); +} + + +/**Function******************************************************************** + + Synopsis [Divides two arbitrary precision double values.] + + Description [Divides two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) +{ + if (EpdIsNan(epd1) || EpdIsNan(epd2)) { + EpdMakeNan(epd3); + return; + } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { + int sign; + + if (EpdIsInf(epd1) && EpdIsInf(epd2)) { + EpdMakeNan(epd3); + } else if (EpdIsInf(epd1)) { + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + EpdMakeInf(epd3, sign); + } else { + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + EpdMakeZero(epd3, sign); + } + return; + } + + if (epd2->type.value == 0.0) { + EpdMakeNan(epd3); + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + assert(epd2->type.bits.exponent == EPD_MAX_BIN); + + epd3->type.value = epd1->type.value / epd2->type.value; + epd3->exponent = epd1->exponent - epd2->exponent; + EpdNormalize(epd3); +} + + +/**Function******************************************************************** + + Synopsis [Adds two arbitrary precision double values.] + + Description [Adds two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdAdd(EpDouble *epd1, double value) +{ + EpDouble epd2; + double tmp; + int exponent, diff; + + if (EpdIsNan(epd1) || IsNanDouble(value)) { + EpdMakeNan(epd1); + return; + } else if (EpdIsInf(epd1) || IsInfDouble(value)) { + int sign; + + EpdConvert(value, &epd2); + if (EpdIsInf(epd1) && IsInfDouble(value)) { + sign = epd1->type.bits.sign ^ epd2.type.bits.sign; + if (sign == 1) + EpdMakeNan(epd1); + } else if (EpdIsInf(&epd2)) { + EpdCopy(&epd2, epd1); + } + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + + EpdConvert(value, &epd2); + if (epd1->exponent > epd2.exponent) { + diff = epd1->exponent - epd2.exponent; + if (diff <= EPD_MAX_BIN) + tmp = epd1->type.value + epd2.type.value / pow((double)2.0, (double)diff); + else + tmp = epd1->type.value; + exponent = epd1->exponent; + } else if (epd1->exponent < epd2.exponent) { + diff = epd2.exponent - epd1->exponent; + if (diff <= EPD_MAX_BIN) + tmp = epd1->type.value / pow((double)2.0, (double)diff) + epd2.type.value; + else + tmp = epd2.type.value; + exponent = epd2.exponent; + } else { + tmp = epd1->type.value + epd2.type.value; + exponent = epd1->exponent; + } + epd1->type.value = tmp; + epd1->exponent = exponent; + EpdNormalize(epd1); +} + + +/**Function******************************************************************** + + Synopsis [Adds two arbitrary precision double values.] + + Description [Adds two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdAdd2(EpDouble *epd1, EpDouble *epd2) +{ + double value; + int exponent, diff; + + if (EpdIsNan(epd1) || EpdIsNan(epd2)) { + EpdMakeNan(epd1); + return; + } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { + int sign; + + if (EpdIsInf(epd1) && EpdIsInf(epd2)) { + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + if (sign == 1) + EpdMakeNan(epd1); + } else if (EpdIsInf(epd2)) { + EpdCopy(epd2, epd1); + } + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + assert(epd2->type.bits.exponent == EPD_MAX_BIN); + + if (epd1->exponent > epd2->exponent) { + diff = epd1->exponent - epd2->exponent; + if (diff <= EPD_MAX_BIN) { + value = epd1->type.value + + epd2->type.value / pow((double)2.0, (double)diff); + } else + value = epd1->type.value; + exponent = epd1->exponent; + } else if (epd1->exponent < epd2->exponent) { + diff = epd2->exponent - epd1->exponent; + if (diff <= EPD_MAX_BIN) { + value = epd1->type.value / pow((double)2.0, (double)diff) + + epd2->type.value; + } else + value = epd2->type.value; + exponent = epd2->exponent; + } else { + value = epd1->type.value + epd2->type.value; + exponent = epd1->exponent; + } + epd1->type.value = value; + epd1->exponent = exponent; + EpdNormalize(epd1); +} + + +/**Function******************************************************************** + + Synopsis [Adds two arbitrary precision double values.] + + Description [Adds two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) +{ + double value; + int exponent, diff; + + if (EpdIsNan(epd1) || EpdIsNan(epd2)) { + EpdMakeNan(epd3); + return; + } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { + int sign; + + if (EpdIsInf(epd1) && EpdIsInf(epd2)) { + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + if (sign == 1) + EpdMakeNan(epd3); + else + EpdCopy(epd1, epd3); + } else if (EpdIsInf(epd1)) { + EpdCopy(epd1, epd3); + } else { + EpdCopy(epd2, epd3); + } + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + assert(epd2->type.bits.exponent == EPD_MAX_BIN); + + if (epd1->exponent > epd2->exponent) { + diff = epd1->exponent - epd2->exponent; + if (diff <= EPD_MAX_BIN) { + value = epd1->type.value + + epd2->type.value / pow((double)2.0, (double)diff); + } else + value = epd1->type.value; + exponent = epd1->exponent; + } else if (epd1->exponent < epd2->exponent) { + diff = epd2->exponent - epd1->exponent; + if (diff <= EPD_MAX_BIN) { + value = epd1->type.value / pow((double)2.0, (double)diff) + + epd2->type.value; + } else + value = epd2->type.value; + exponent = epd2->exponent; + } else { + value = epd1->type.value + epd2->type.value; + exponent = epd1->exponent; + } + epd3->type.value = value; + epd3->exponent = exponent; + EpdNormalize(epd3); +} + + +/**Function******************************************************************** + + Synopsis [Subtracts two arbitrary precision double values.] + + Description [Subtracts two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdSubtract(EpDouble *epd1, double value) +{ + EpDouble epd2; + double tmp; + int exponent, diff; + + if (EpdIsNan(epd1) || IsNanDouble(value)) { + EpdMakeNan(epd1); + return; + } else if (EpdIsInf(epd1) || IsInfDouble(value)) { + int sign; + + EpdConvert(value, &epd2); + if (EpdIsInf(epd1) && IsInfDouble(value)) { + sign = epd1->type.bits.sign ^ epd2.type.bits.sign; + if (sign == 0) + EpdMakeNan(epd1); + } else if (EpdIsInf(&epd2)) { + EpdCopy(&epd2, epd1); + } + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + + EpdConvert(value, &epd2); + if (epd1->exponent > epd2.exponent) { + diff = epd1->exponent - epd2.exponent; + if (diff <= EPD_MAX_BIN) + tmp = epd1->type.value - epd2.type.value / pow((double)2.0, (double)diff); + else + tmp = epd1->type.value; + exponent = epd1->exponent; + } else if (epd1->exponent < epd2.exponent) { + diff = epd2.exponent - epd1->exponent; + if (diff <= EPD_MAX_BIN) + tmp = epd1->type.value / pow((double)2.0, (double)diff) - epd2.type.value; + else + tmp = epd2.type.value * (double)(-1.0); + exponent = epd2.exponent; + } else { + tmp = epd1->type.value - epd2.type.value; + exponent = epd1->exponent; + } + epd1->type.value = tmp; + epd1->exponent = exponent; + EpdNormalize(epd1); +} + + +/**Function******************************************************************** + + Synopsis [Subtracts two arbitrary precision double values.] + + Description [Subtracts two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdSubtract2(EpDouble *epd1, EpDouble *epd2) +{ + double value; + int exponent, diff; + + if (EpdIsNan(epd1) || EpdIsNan(epd2)) { + EpdMakeNan(epd1); + return; + } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { + int sign; + + if (EpdIsInf(epd1) && EpdIsInf(epd2)) { + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + if (sign == 0) + EpdMakeNan(epd1); + } else if (EpdIsInf(epd2)) { + EpdCopy(epd2, epd1); + } + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + assert(epd2->type.bits.exponent == EPD_MAX_BIN); + + if (epd1->exponent > epd2->exponent) { + diff = epd1->exponent - epd2->exponent; + if (diff <= EPD_MAX_BIN) { + value = epd1->type.value - + epd2->type.value / pow((double)2.0, (double)diff); + } else + value = epd1->type.value; + exponent = epd1->exponent; + } else if (epd1->exponent < epd2->exponent) { + diff = epd2->exponent - epd1->exponent; + if (diff <= EPD_MAX_BIN) { + value = epd1->type.value / pow((double)2.0, (double)diff) - + epd2->type.value; + } else + value = epd2->type.value * (double)(-1.0); + exponent = epd2->exponent; + } else { + value = epd1->type.value - epd2->type.value; + exponent = epd1->exponent; + } + epd1->type.value = value; + epd1->exponent = exponent; + EpdNormalize(epd1); +} + + +/**Function******************************************************************** + + Synopsis [Subtracts two arbitrary precision double values.] + + Description [Subtracts two arbitrary precision double values.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) +{ + double value; + int exponent, diff; + + if (EpdIsNan(epd1) || EpdIsNan(epd2)) { + EpdMakeNan(epd3); + return; + } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { + int sign; + + if (EpdIsInf(epd1) && EpdIsInf(epd2)) { + sign = epd1->type.bits.sign ^ epd2->type.bits.sign; + if (sign == 0) + EpdCopy(epd1, epd3); + else + EpdMakeNan(epd3); + } else if (EpdIsInf(epd1)) { + EpdCopy(epd1, epd1); + } else { + sign = epd2->type.bits.sign ^ 0x1; + EpdMakeInf(epd3, sign); + } + return; + } + + assert(epd1->type.bits.exponent == EPD_MAX_BIN); + assert(epd2->type.bits.exponent == EPD_MAX_BIN); + + if (epd1->exponent > epd2->exponent) { + diff = epd1->exponent - epd2->exponent; + if (diff <= EPD_MAX_BIN) { + value = epd1->type.value - + epd2->type.value / pow((double)2.0, (double)diff); + } else + value = epd1->type.value; + exponent = epd1->exponent; + } else if (epd1->exponent < epd2->exponent) { + diff = epd2->exponent - epd1->exponent; + if (diff <= EPD_MAX_BIN) { + value = epd1->type.value / pow((double)2.0, (double)diff) - + epd2->type.value; + } else + value = epd2->type.value * (double)(-1.0); + exponent = epd2->exponent; + } else { + value = epd1->type.value - epd2->type.value; + exponent = epd1->exponent; + } + epd3->type.value = value; + epd3->exponent = exponent; + EpdNormalize(epd3); +} + + +/**Function******************************************************************** + + Synopsis [Computes arbitrary precision pow of base 2.] + + Description [Computes arbitrary precision pow of base 2.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdPow2(int n, EpDouble *epd) +{ + if (n <= EPD_MAX_BIN) { + EpdConvert(pow((double)2.0, (double)n), epd); + } else { + EpDouble epd1, epd2; + int n1, n2; + + n1 = n / 2; + n2 = n - n1; + EpdPow2(n1, &epd1); + EpdPow2(n2, &epd2); + EpdMultiply3(&epd1, &epd2, epd); + } +} + + +/**Function******************************************************************** + + Synopsis [Computes arbitrary precision pow of base 2.] + + Description [Computes arbitrary precision pow of base 2.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdPow2Decimal(int n, EpDouble *epd) +{ + if (n <= EPD_MAX_BIN) { + epd->type.value = pow((double)2.0, (double)n); + epd->exponent = 0; + EpdNormalizeDecimal(epd); + } else { + EpDouble epd1, epd2; + int n1, n2; + + n1 = n / 2; + n2 = n - n1; + EpdPow2Decimal(n1, &epd1); + EpdPow2Decimal(n2, &epd2); + EpdMultiply3Decimal(&epd1, &epd2, epd); + } +} + + +/**Function******************************************************************** + + Synopsis [Normalize an arbitrary precision double value.] + + Description [Normalize an arbitrary precision double value.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdNormalize(EpDouble *epd) +{ + int exponent; + + if (IsNanOrInfDouble(epd->type.value)) { + epd->exponent = 0; + return; + } + + exponent = EpdGetExponent(epd->type.value); + if (exponent == EPD_MAX_BIN) + return; + exponent -= EPD_MAX_BIN; + epd->type.bits.exponent = EPD_MAX_BIN; + epd->exponent += exponent; +} + + +/**Function******************************************************************** + + Synopsis [Normalize an arbitrary precision double value.] + + Description [Normalize an arbitrary precision double value.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdNormalizeDecimal(EpDouble *epd) +{ + int exponent; + + if (IsNanOrInfDouble(epd->type.value)) { + epd->exponent = 0; + return; + } + + exponent = EpdGetExponentDecimal(epd->type.value); + epd->type.value /= pow((double)10.0, (double)exponent); + epd->exponent += exponent; +} + + +/**Function******************************************************************** + + Synopsis [Returns value and decimal exponent of EpDouble.] + + Description [Returns value and decimal exponent of EpDouble.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent) +{ + EpDouble epd1, epd2; + + if (EpdIsNanOrInf(epd)) + return; + + if (EpdIsZero(epd)) { + *value = 0.0; + *exponent = 0; + return; + } + + epd1.type.value = epd->type.value; + epd1.exponent = 0; + EpdPow2Decimal(epd->exponent, &epd2); + EpdMultiply2Decimal(&epd1, &epd2); + + *value = epd1.type.value; + *exponent = epd1.exponent; +} + +/**Function******************************************************************** + + Synopsis [Returns the exponent value of a double.] + + Description [Returns the exponent value of a double.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +EpdGetExponent(double value) +{ + int exponent; + EpDouble epd; + + epd.type.value = value; + exponent = epd.type.bits.exponent; + return(exponent); +} + + +/**Function******************************************************************** + + Synopsis [Returns the decimal exponent value of a double.] + + Description [Returns the decimal exponent value of a double.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +EpdGetExponentDecimal(double value) +{ + char *pos, str[24]; + int exponent; + + sprintf(str, "%E", value); + pos = strstr(str, "E"); + sscanf(pos, "E%d", &exponent); + return(exponent); +} + + +/**Function******************************************************************** + + Synopsis [Makes EpDouble Inf.] + + Description [Makes EpDouble Inf.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdMakeInf(EpDouble *epd, int sign) +{ + epd->type.bits.mantissa1 = 0; + epd->type.bits.mantissa0 = 0; + epd->type.bits.exponent = EPD_EXP_INF; + epd->type.bits.sign = sign; + epd->exponent = 0; +} + + +/**Function******************************************************************** + + Synopsis [Makes EpDouble Zero.] + + Description [Makes EpDouble Zero.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdMakeZero(EpDouble *epd, int sign) +{ + epd->type.bits.mantissa1 = 0; + epd->type.bits.mantissa0 = 0; + epd->type.bits.exponent = 0; + epd->type.bits.sign = sign; + epd->exponent = 0; +} + + +/**Function******************************************************************** + + Synopsis [Makes EpDouble NaN.] + + Description [Makes EpDouble NaN.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdMakeNan(EpDouble *epd) +{ + epd->type.nan.mantissa1 = 0; + epd->type.nan.mantissa0 = 0; + epd->type.nan.quiet_bit = 1; + epd->type.nan.exponent = EPD_EXP_INF; + epd->type.nan.sign = 1; + epd->exponent = 0; +} + + +/**Function******************************************************************** + + Synopsis [Copies a EpDouble struct.] + + Description [Copies a EpDouble struct.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void +EpdCopy(EpDouble *from, EpDouble *to) +{ + to->type.value = from->type.value; + to->exponent = from->exponent; +} + + +/**Function******************************************************************** + + Synopsis [Checks whether the value is Inf.] + + Description [Checks whether the value is Inf.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +EpdIsInf(EpDouble *epd) +{ + return(IsInfDouble(epd->type.value)); +} + + +/**Function******************************************************************** + + Synopsis [Checks whether the value is Zero.] + + Description [Checks whether the value is Zero.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +EpdIsZero(EpDouble *epd) +{ + if (epd->type.value == 0.0) + return(1); + else + return(0); +} + + +/**Function******************************************************************** + + Synopsis [Checks whether the value is NaN.] + + Description [Checks whether the value is NaN.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +EpdIsNan(EpDouble *epd) +{ + return(IsNanDouble(epd->type.value)); +} + + +/**Function******************************************************************** + + Synopsis [Checks whether the value is NaN or Inf.] + + Description [Checks whether the value is NaN or Inf.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +EpdIsNanOrInf(EpDouble *epd) +{ + return(IsNanOrInfDouble(epd->type.value)); +} + + +/**Function******************************************************************** + + Synopsis [Checks whether the value is Inf.] + + Description [Checks whether the value is Inf.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +IsInfDouble(double value) +{ + IeeeDouble *ptr = (IeeeDouble *)(&value); + + if (ptr->exponent == EPD_EXP_INF && + ptr->mantissa0 == 0 && + ptr->mantissa1 == 0) { + if (ptr->sign == 0) + return(1); + else + return(-1); + } + return(0); +} + + +/**Function******************************************************************** + + Synopsis [Checks whether the value is NaN.] + + Description [Checks whether the value is NaN.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +IsNanDouble(double value) +{ + IeeeNan *ptr = (IeeeNan *)(&value); + + if (ptr->exponent == EPD_EXP_INF && + ptr->sign == 1 && + ptr->quiet_bit == 1 && + ptr->mantissa0 == 0 && + ptr->mantissa1 == 0) { + return(1); + } + return(0); +} + + +/**Function******************************************************************** + + Synopsis [Checks whether the value is NaN or Inf.] + + Description [Checks whether the value is NaN or Inf.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int +IsNanOrInfDouble(double value) +{ + IeeeNan *ptr = (IeeeNan *)(&value); + + if (ptr->exponent == EPD_EXP_INF && + ptr->mantissa0 == 0 && + ptr->mantissa1 == 0 && + (ptr->sign == 1 || ptr->quiet_bit == 0)) { + return(1); + } + return(0); +} diff --git a/abc70930/src/bdd/epd/epd.h b/abc70930/src/bdd/epd/epd.h new file mode 100644 index 00000000..66db80e3 --- /dev/null +++ b/abc70930/src/bdd/epd/epd.h @@ -0,0 +1,160 @@ +/**CHeaderFile***************************************************************** + + FileName [epd.h] + + PackageName [epd] + + Synopsis [The University of Colorado extended double precision package.] + + Description [arithmetic functions with extended double precision.] + + SeeAlso [] + + Author [In-Ho Moon] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + + Revision [$Id: epd.h,v 1.1.1.1 2003/02/24 22:23:57 wjiang Exp $] + +******************************************************************************/ + +#ifndef _EPD +#define _EPD + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#define EPD_MAX_BIN 1023 +#define EPD_MAX_DEC 308 +#define EPD_EXP_INF 0x7ff + +/*---------------------------------------------------------------------------*/ +/* Structure declarations */ +/*---------------------------------------------------------------------------*/ + +/**Struct********************************************************************** + + Synopsis [IEEE double struct.] + + Description [IEEE double struct.] + + SeeAlso [] + +******************************************************************************/ +#ifdef EPD_BIG_ENDIAN +struct IeeeDoubleStruct { /* BIG_ENDIAN */ + unsigned int sign: 1; + unsigned int exponent: 11; + unsigned int mantissa0: 20; + unsigned int mantissa1: 32; +}; +#else +struct IeeeDoubleStruct { /* LITTLE_ENDIAN */ + unsigned int mantissa1: 32; + unsigned int mantissa0: 20; + unsigned int exponent: 11; + unsigned int sign: 1; +}; +#endif + +/**Struct********************************************************************** + + Synopsis [IEEE double NaN struct.] + + Description [IEEE double NaN struct.] + + SeeAlso [] + +******************************************************************************/ +#ifdef EPD_BIG_ENDIAN +struct IeeeNanStruct { /* BIG_ENDIAN */ + unsigned int sign: 1; + unsigned int exponent: 11; + unsigned int quiet_bit: 1; + unsigned int mantissa0: 19; + unsigned int mantissa1: 32; +}; +#else +struct IeeeNanStruct { /* LITTLE_ENDIAN */ + unsigned int mantissa1: 32; + unsigned int mantissa0: 19; + unsigned int quiet_bit: 1; + unsigned int exponent: 11; + unsigned int sign: 1; +}; +#endif + +/**Struct********************************************************************** + + Synopsis [Extended precision double to keep very large value.] + + Description [Extended precision double to keep very large value.] + + SeeAlso [] + +******************************************************************************/ +struct EpDoubleStruct { + union { + double value; + struct IeeeDoubleStruct bits; + struct IeeeNanStruct nan; + } type; + int exponent; +}; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ +typedef struct EpDoubleStruct EpDouble; +typedef struct IeeeDoubleStruct IeeeDouble; +typedef struct IeeeNanStruct IeeeNan; + + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + +EpDouble *EpdAlloc(); +int EpdCmp(const char *key1, const char *key2); +void EpdFree(EpDouble *epd); +void EpdGetString(EpDouble *epd, char *str); +void EpdConvert(double value, EpDouble *epd); +void EpdMultiply(EpDouble *epd1, double value); +void EpdMultiply2(EpDouble *epd1, EpDouble *epd2); +void EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2); +void EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); +void EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); +void EpdDivide(EpDouble *epd1, double value); +void EpdDivide2(EpDouble *epd1, EpDouble *epd2); +void EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); +void EpdAdd(EpDouble *epd1, double value); +void EpdAdd2(EpDouble *epd1, EpDouble *epd2); +void EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); +void EpdSubtract(EpDouble *epd1, double value); +void EpdSubtract2(EpDouble *epd1, EpDouble *epd2); +void EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); +void EpdPow2(int n, EpDouble *epd); +void EpdPow2Decimal(int n, EpDouble *epd); +void EpdNormalize(EpDouble *epd); +void EpdNormalizeDecimal(EpDouble *epd); +void EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent); +int EpdGetExponent(double value); +int EpdGetExponentDecimal(double value); +void EpdMakeInf(EpDouble *epd, int sign); +void EpdMakeZero(EpDouble *epd, int sign); +void EpdMakeNan(EpDouble *epd); +void EpdCopy(EpDouble *from, EpDouble *to); +int EpdIsInf(EpDouble *epd); +int EpdIsZero(EpDouble *epd); +int EpdIsNan(EpDouble *epd); +int EpdIsNanOrInf(EpDouble *epd); +int IsInfDouble(double value); +int IsNanDouble(double value); +int IsNanOrInfDouble(double value); + +#endif /* _EPD */ diff --git a/abc70930/src/bdd/epd/module.make b/abc70930/src/bdd/epd/module.make new file mode 100644 index 00000000..a8084db1 --- /dev/null +++ b/abc70930/src/bdd/epd/module.make @@ -0,0 +1 @@ +SRC += src/bdd/epd/epd.c diff --git a/abc70930/src/bdd/mtr/module.make b/abc70930/src/bdd/mtr/module.make new file mode 100644 index 00000000..d7fa63d9 --- /dev/null +++ b/abc70930/src/bdd/mtr/module.make @@ -0,0 +1,2 @@ +SRC += src/bdd/mtr/mtrBasic.c \ + src/bdd/mtr/mtrGroup.c diff --git a/abc70930/src/bdd/mtr/mtr.h b/abc70930/src/bdd/mtr/mtr.h new file mode 100644 index 00000000..201329ae --- /dev/null +++ b/abc70930/src/bdd/mtr/mtr.h @@ -0,0 +1,173 @@ +/**CHeaderFile***************************************************************** + + FileName [mtr.h] + + PackageName [mtr] + + Synopsis [Multiway-branch tree manipulation] + + Description [This package provides two layers of functions. Functions + of the lower level manipulate multiway-branch trees, implemented + according to the classical scheme whereby each node points to its + first child and its previous and next siblings. These functions are + collected in mtrBasic.c.

        + Functions of the upper layer deal with group trees, that is the trees + used by group sifting to represent the grouping of variables. These + functions are collected in mtrGroup.c.] + + SeeAlso [The CUDD package documentation; specifically on group + sifting.] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + + Revision [$Id: mtr.h,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $] + +******************************************************************************/ + +#ifndef __MTR +#define __MTR + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef SIZEOF_VOID_P +#define SIZEOF_VOID_P 4 +#endif +#ifndef SIZEOF_INT +#define SIZEOF_INT 4 +#endif + +#undef CONST +#if defined(__STDC__) || defined(__cplusplus) +#define CONST const +#else /* !(__STDC__ || __cplusplus) */ +#define CONST +#endif /* !(__STDC__ || __cplusplus) */ + +/* These are potential duplicates. */ +#ifndef EXTERN +# ifdef __cplusplus +# define EXTERN extern "C" +# else +# define EXTERN extern +# endif +#endif +#ifndef ARGS +# if defined(__STDC__) || defined(__cplusplus) +# define ARGS(protos) protos /* ANSI C */ +# else /* !(__STDC__ || __cplusplus) */ +# define ARGS(protos) () /* K&R C */ +# endif /* !(__STDC__ || __cplusplus) */ +#endif + +#if defined(__GNUC__) +#define MTR_INLINE __inline__ +# if (__GNUC__ >2 || __GNUC_MINOR__ >=7) +# define MTR_UNUSED __attribute__ ((unused)) +# else +# define MTR_UNUSED +# endif +#else +#define MTR_INLINE +#define MTR_UNUSED +#endif + +/* Flag definitions */ +#define MTR_DEFAULT 0x00000000 +#define MTR_TERMINAL 0x00000001 +#define MTR_SOFT 0x00000002 +#define MTR_FIXED 0x00000004 +#define MTR_NEWNODE 0x00000008 + +/* MTR_MAXHIGH is defined in such a way that on 32-bit and 64-bit +** machines one can cast a value to (int) without generating a negative +** number. +*/ +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +#define MTR_MAXHIGH (((MtrHalfWord) ~0) >> 1) +#else +#define MTR_MAXHIGH ((MtrHalfWord) ~0) +#endif + + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 +typedef unsigned int MtrHalfWord; +#else +typedef unsigned short MtrHalfWord; +#endif + +typedef struct MtrNode { + MtrHalfWord flags; + MtrHalfWord low; + MtrHalfWord size; + MtrHalfWord index; + struct MtrNode *parent; + struct MtrNode *child; + struct MtrNode *elder; + struct MtrNode *younger; +} MtrNode; + + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/* Flag manipulation macros */ +#define MTR_SET(node, flag) (node->flags |= (flag)) +#define MTR_RESET(node, flag) (node->flags &= ~ (flag)) +#define MTR_TEST(node, flag) (node->flags & (flag)) + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + +EXTERN MtrNode * Mtr_AllocNode ARGS(()); +EXTERN void Mtr_DeallocNode ARGS((MtrNode *node)); +EXTERN MtrNode * Mtr_InitTree ARGS(()); +EXTERN void Mtr_FreeTree ARGS((MtrNode *node)); +EXTERN MtrNode * Mtr_CopyTree ARGS((MtrNode *node, int expansion)); +EXTERN void Mtr_MakeFirstChild ARGS((MtrNode *parent, MtrNode *child)); +EXTERN void Mtr_MakeLastChild ARGS((MtrNode *parent, MtrNode *child)); +EXTERN MtrNode * Mtr_CreateFirstChild ARGS((MtrNode *parent)); +EXTERN MtrNode * Mtr_CreateLastChild ARGS((MtrNode *parent)); +EXTERN void Mtr_MakeNextSibling ARGS((MtrNode *first, MtrNode *second)); +EXTERN void Mtr_PrintTree ARGS((MtrNode *node)); +EXTERN MtrNode * Mtr_InitGroupTree ARGS((int lower, int size)); +EXTERN MtrNode * Mtr_MakeGroup ARGS((MtrNode *root, unsigned int low, unsigned int high, unsigned int flags)); +EXTERN MtrNode * Mtr_DissolveGroup ARGS((MtrNode *group)); +EXTERN MtrNode * Mtr_FindGroup ARGS((MtrNode *root, unsigned int low, unsigned int high)); +EXTERN int Mtr_SwapGroups ARGS((MtrNode *first, MtrNode *second)); +EXTERN void Mtr_PrintGroups ARGS((MtrNode *root, int silent)); +EXTERN MtrNode * Mtr_ReadGroups ARGS((FILE *fp, int nleaves)); + +/**AutomaticEnd***************************************************************/ + +#endif /* __MTR */ diff --git a/abc70930/src/bdd/mtr/mtrBasic.c b/abc70930/src/bdd/mtr/mtrBasic.c new file mode 100644 index 00000000..94105282 --- /dev/null +++ b/abc70930/src/bdd/mtr/mtrBasic.c @@ -0,0 +1,426 @@ +/**CFile*********************************************************************** + + FileName [mtrBasic.c] + + PackageName [mtr] + + Synopsis [Basic manipulation of multiway branching trees.] + + Description [External procedures included in this module: +

          +
        • Mtr_AllocNode() +
        • Mtr_DeallocNode() +
        • Mtr_InitTree() +
        • Mtr_FreeTree() +
        • Mtr_CopyTree() +
        • Mtr_MakeFirstChild() +
        • Mtr_MakeLastChild() +
        • Mtr_CreateFirstChild() +
        • Mtr_CreateLastChild() +
        • Mtr_MakeNextSibling() +
        • Mtr_PrintTree() +
        + ] + + SeeAlso [cudd package] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "mtrInt.h" + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] MTR_UNUSED = "$Id: mtrBasic.c,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Allocates new tree node.] + + Description [Allocates new tree node. Returns pointer to node.] + + SideEffects [None] + + SeeAlso [Mtr_DeallocNode] + +******************************************************************************/ +MtrNode * +Mtr_AllocNode( + ) +{ + MtrNode *node; + + node = ALLOC(MtrNode,1); + return node; + +} /* Mtr_AllocNode */ + + +/**Function******************************************************************** + + Synopsis [Deallocates tree node.] + + Description [] + + SideEffects [None] + + SeeAlso [Mtr_AllocNode] + +******************************************************************************/ +void +Mtr_DeallocNode( + MtrNode * node /* node to be deallocated */) +{ + FREE(node); + return; + +} /* end of Mtr_DeallocNode */ + + +/**Function******************************************************************** + + Synopsis [Initializes tree with one node.] + + Description [Initializes tree with one node. Returns pointer to node.] + + SideEffects [None] + + SeeAlso [Mtr_FreeTree Mtr_InitGroupTree] + +******************************************************************************/ +MtrNode * +Mtr_InitTree( + ) +{ + MtrNode *node; + + node = Mtr_AllocNode(); + if (node == NULL) return(NULL); + + node->parent = node->child = node->elder = node->younger = NULL; + node->flags = 0; + + return(node); + +} /* end of Mtr_InitTree */ + + +/**Function******************************************************************** + + Synopsis [Disposes of tree rooted at node.] + + Description [] + + SideEffects [None] + + SeeAlso [Mtr_InitTree] + +******************************************************************************/ +void +Mtr_FreeTree( + MtrNode * node) +{ + if (node == NULL) return; + if (! MTR_TEST(node,MTR_TERMINAL)) Mtr_FreeTree(node->child); + Mtr_FreeTree(node->younger); + Mtr_DeallocNode(node); + return; + +} /* end of Mtr_FreeTree */ + + +/**Function******************************************************************** + + Synopsis [Makes a copy of tree.] + + Description [Makes a copy of tree. If parameter expansion is greater + than 1, it will expand the tree by that factor. It is an error for + expansion to be less than 1. Returns a pointer to the copy if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Mtr_InitTree] + +******************************************************************************/ +MtrNode * +Mtr_CopyTree( + MtrNode * node, + int expansion) +{ + MtrNode *copy; + + if (node == NULL) return(NULL); + if (expansion < 1) return(NULL); + copy = Mtr_AllocNode(); + if (copy == NULL) return(NULL); + copy->parent = copy->elder = copy->child = copy->younger = NULL; + if (node->child != NULL) { + copy->child = Mtr_CopyTree(node->child, expansion); + if (copy->child == NULL) { + Mtr_DeallocNode(copy); + return(NULL); + } + } + if (node->younger != NULL) { + copy->younger = Mtr_CopyTree(node->younger, expansion); + if (copy->younger == NULL) { + Mtr_FreeTree(copy); + return(NULL); + } + } + copy->flags = node->flags; + copy->low = node->low * expansion; + copy->size = node->size * expansion; + copy->index = node->index * expansion; + if (copy->younger) copy->younger->elder = copy; + if (copy->child) { + MtrNode *auxnode = copy->child; + while (auxnode != NULL) { + auxnode->parent = copy; + auxnode = auxnode->younger; + } + } + return(copy); + +} /* end of Mtr_CopyTree */ + + +/**Function******************************************************************** + + Synopsis [Makes child the first child of parent.] + + Description [] + + SideEffects [None] + + SeeAlso [Mtr_MakeLastChild Mtr_CreateFirstChild] + +******************************************************************************/ +void +Mtr_MakeFirstChild( + MtrNode * parent, + MtrNode * child) +{ + child->parent = parent; + child->younger = parent->child; + child->elder = NULL; + if (parent->child != NULL) { +#ifdef MTR_DEBUG + assert(parent->child->elder == NULL); +#endif + parent->child->elder = child; + } + parent->child = child; + return; + +} /* end of Mtr_MakeFirstChild */ + + +/**Function******************************************************************** + + Synopsis [Makes child the last child of parent.] + + Description [] + + SideEffects [None] + + SeeAlso [Mtr_MakeFirstChild Mtr_CreateLastChild] + +******************************************************************************/ +void +Mtr_MakeLastChild( + MtrNode * parent, + MtrNode * child) +{ + MtrNode *node; + + child->younger = NULL; + + if (parent->child == NULL) { + parent->child = child; + child->elder = NULL; + } else { + for (node = parent->child; + node->younger != NULL; + node = node->younger); + node->younger = child; + child->elder = node; + } + child->parent = parent; + return; + +} /* end of Mtr_MakeLastChild */ + + +/**Function******************************************************************** + + Synopsis [Creates a new node and makes it the first child of parent.] + + Description [Creates a new node and makes it the first child of + parent. Returns pointer to new child.] + + SideEffects [None] + + SeeAlso [Mtr_MakeFirstChild Mtr_CreateLastChild] + +******************************************************************************/ +MtrNode * +Mtr_CreateFirstChild( + MtrNode * parent) +{ + MtrNode *child; + + child = Mtr_AllocNode(); + if (child == NULL) return(NULL); + + child->child = child->younger = child-> elder = NULL; + child->flags = 0; + Mtr_MakeFirstChild(parent,child); + return(child); + +} /* end of Mtr_CreateFirstChild */ + + +/**Function******************************************************************** + + Synopsis [Creates a new node and makes it the last child of parent.] + + Description [Creates a new node and makes it the last child of parent. + Returns pointer to new child.] + + SideEffects [None] + + SeeAlso [Mtr_MakeLastChild Mtr_CreateFirstChild] + +******************************************************************************/ +MtrNode * +Mtr_CreateLastChild( + MtrNode * parent) +{ + MtrNode *child; + + child = Mtr_AllocNode(); + if (child == NULL) return(NULL); + + child->child = child->younger = child->elder = NULL; + child->flags = 0; + Mtr_MakeLastChild(parent,child); + return(child); + +} /* end of Mtr_CreateLastChild */ + + +/**Function******************************************************************** + + Synopsis [Makes second the next sibling of first.] + + Description [Makes second the next sibling of first. Second becomes a + child of the parent of first.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void +Mtr_MakeNextSibling( + MtrNode * first, + MtrNode * second) +{ + second->younger = first->younger; + if (first->younger != NULL) { + first->younger->elder = second; + } + second->parent = first->parent; + first->younger = second; + second->elder = first; + return; + +} /* end of Mtr_MakeNextSibling */ + + +/**Function******************************************************************** + + Synopsis [Prints a tree, one node per line.] + + Description [] + + SideEffects [None] + + SeeAlso [Mtr_PrintGroups] + +******************************************************************************/ +void +Mtr_PrintTree( + MtrNode * node) +{ + if (node == NULL) return; + (void) fprintf(stdout, +#if SIZEOF_VOID_P == 8 + "N=0x%-8lx C=0x%-8lx Y=0x%-8lx E=0x%-8lx P=0x%-8lx F=%x L=%d S=%d\n", + (unsigned long) node, (unsigned long) node->child, + (unsigned long) node->younger, (unsigned long) node->elder, + (unsigned long) node->parent, node->flags, node->low, node->size); +#else + "N=0x%-8x C=0x%-8x Y=0x%-8x E=0x%-8x P=0x%-8x F=%x L=%d S=%d\n", + (unsigned) node, (unsigned) node->child, + (unsigned) node->younger, (unsigned) node->elder, + (unsigned) node->parent, node->flags, node->low, node->size); +#endif + if (!MTR_TEST(node,MTR_TERMINAL)) Mtr_PrintTree(node->child); + Mtr_PrintTree(node->younger); + return; + +} /* end of Mtr_PrintTree */ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/bdd/mtr/mtrGroup.c b/abc70930/src/bdd/mtr/mtrGroup.c new file mode 100644 index 00000000..363b776b --- /dev/null +++ b/abc70930/src/bdd/mtr/mtrGroup.c @@ -0,0 +1,690 @@ +/**CFile*********************************************************************** + + FileName [mtrGroup.c] + + PackageName [mtr] + + Synopsis [Functions to support group specification for reordering.] + + Description [External procedures included in this module: +
          +
        • Mtr_InitGroupTree() +
        • Mtr_MakeGroup() +
        • Mtr_DissolveGroup() +
        • Mtr_FindGroup() +
        • Mtr_SwapGroups() +
        • Mtr_PrintGroups() +
        • Mtr_ReadGroups() +
        + Static procedures included in this module: +
          +
        • mtrShiftHL +
        + ] + + SeeAlso [cudd package] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + +******************************************************************************/ + +#include "util_hack.h" +#include "mtrInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +#ifndef lint +static char rcsid[] MTR_UNUSED = "$Id: mtrGroup.c,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $"; +#endif + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int mtrShiftHL ARGS((MtrNode *node, int shift)); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Allocate new tree.] + + Description [Allocate new tree with one node, whose low and size + fields are specified by the lower and size parameters. + Returns pointer to tree root.] + + SideEffects [None] + + SeeAlso [Mtr_InitTree Mtr_FreeTree] + +******************************************************************************/ +MtrNode * +Mtr_InitGroupTree( + int lower, + int size) +{ + MtrNode *root; + + root = Mtr_InitTree(); + if (root == NULL) return(NULL); + root->flags = MTR_DEFAULT; + root->low = lower; + root->size = size; + return(root); + +} /* end of Mtr_InitGroupTree */ + + +/**Function******************************************************************** + + Synopsis [Makes a new group with size leaves starting at low.] + + Description [Makes a new group with size leaves starting at low. + If the new group intersects an existing group, it must + either contain it or be contained by it. This procedure relies on + the low and size fields of each node. It also assumes that the + children of each node are sorted in order of increasing low. In + case of a valid request, the flags of the new group are set to the + value passed in `flags.' This can also be used to change the flags + of an existing group. Returns the pointer to the root of the new + group upon successful termination; NULL otherwise. If the group + already exists, the pointer to its root is returned.] + + SideEffects [None] + + SeeAlso [Mtr_DissolveGroup Mtr_ReadGroups Mtr_FindGroup] + +******************************************************************************/ +MtrNode * +Mtr_MakeGroup( + MtrNode * root /* root of the group tree */, + unsigned int low /* lower bound of the group */, + unsigned int size /* upper bound of the group */, + unsigned int flags /* flags for the new group */) +{ + MtrNode *node, + *first, + *last, + *previous, + *newn; + + /* Sanity check. */ + if (size == 0) + return(NULL); + + /* Check whether current group includes new group. This check is + ** necessary at the top-level call. In the subsequent calls it is + ** redundant. */ + if (low < (unsigned int) root->low || + low + size > (unsigned int) (root->low + root->size)) + return(NULL); + + /* Trying to create an existing group has the effect of updating + ** the flags. */ + if (root->size == size && root->low == low) { + root->flags = flags; + return(root); + } + + /* At this point we know that the new group is properly contained + ** in the group of root. We have two possible cases here: - root + ** is a terminal node; - root has children. */ + + /* Root has no children: create a new group. */ + if (root->child == NULL) { + newn = Mtr_AllocNode(); + if (newn == NULL) return(NULL); /* out of memory */ + newn->low = low; + newn->size = size; + newn->flags = flags; + newn->parent = root; + newn->elder = newn->younger = newn->child = NULL; + root->child = newn; + return(newn); + } + + /* Root has children: Find all chidren of root that are included + ** in the new group. If the group of any child entirely contains + ** the new group, call Mtr_MakeGroup recursively. */ + previous = NULL; + first = root->child; /* guaranteed to be non-NULL */ + while (first != NULL && low >= (unsigned int) (first->low + first->size)) { + previous = first; + first = first->younger; + } + if (first == NULL) { + /* We have scanned the entire list and we need to append a new + ** child at the end of it. Previous points to the last child + ** of root. */ + newn = Mtr_AllocNode(); + if (newn == NULL) return(NULL); /* out of memory */ + newn->low = low; + newn->size = size; + newn->flags = flags; + newn->parent = root; + newn->elder = previous; + previous->younger = newn; + newn->younger = newn->child = NULL; + return(newn); + } + /* Here first is non-NULL and low < first->low + first->size. */ + if (low >= (unsigned int) first->low && + low + size <= (unsigned int) (first->low + first->size)) { + /* The new group is contained in the group of first. */ + newn = Mtr_MakeGroup(first, low, size, flags); + return(newn); + } else if (low + size <= first->low) { + /* The new group is entirely contained in the gap between + ** previous and first. */ + newn = Mtr_AllocNode(); + if (newn == NULL) return(NULL); /* out of memory */ + newn->low = low; + newn->size = size; + newn->flags = flags; + newn->child = NULL; + newn->parent = root; + newn->elder = previous; + newn->younger = first; + first->elder = newn; + if (previous != NULL) { + previous->younger = newn; + } else { + root->child = newn; + } + return(newn); + } else if (low < (unsigned int) first->low && + low + size < (unsigned int) (first->low + first->size)) { + /* Trying to cut an existing group: not allowed. */ + return(NULL); + } else if (low > first->low) { + /* The new group neither is contained in the group of first + ** (this was tested above) nor contains it. It is therefore + ** trying to cut an existing group: not allowed. */ + return(NULL); + } + + /* First holds the pointer to the first child contained in the new + ** group. Here low <= first->low and low + size >= first->low + + ** first->size. One of the two inequalities is strict. */ + last = first->younger; + while (last != NULL && + (unsigned int) (last->low + last->size) < low + size) { + last = last->younger; + } + if (last == NULL) { + /* All the chilren of root from first onward become children + ** of the new group. */ + newn = Mtr_AllocNode(); + if (newn == NULL) return(NULL); /* out of memory */ + newn->low = low; + newn->size = size; + newn->flags = flags; + newn->child = first; + newn->parent = root; + newn->elder = previous; + newn->younger = NULL; + first->elder = NULL; + if (previous != NULL) { + previous->younger = newn; + } else { + root->child = newn; + } + last = first; + while (last != NULL) { + last->parent = newn; + last = last->younger; + } + return(newn); + } + + /* Here last != NULL and low + size <= last->low + last->size. */ + if (low + size - 1 >= (unsigned int) last->low && + low + size < (unsigned int) (last->low + last->size)) { + /* Trying to cut an existing group: not allowed. */ + return(NULL); + } + + /* First and last point to the first and last of the children of + ** root that are included in the new group. Allocate a new node + ** and make all children of root between first and last chidren of + ** the new node. Previous points to the child of root immediately + ** preceeding first. If it is NULL, then first is the first child + ** of root. */ + newn = Mtr_AllocNode(); + if (newn == NULL) return(NULL); /* out of memory */ + newn->low = low; + newn->size = size; + newn->flags = flags; + newn->child = first; + newn->parent = root; + if (previous == NULL) { + root->child = newn; + } else { + previous->younger = newn; + } + newn->elder = previous; + newn->younger = last->younger; + if (last->younger != NULL) { + last->younger->elder = newn; + } + last->younger = NULL; + first->elder = NULL; + for (node = first; node != NULL; node = node->younger) { + node->parent = newn; + } + + return(newn); + +} /* end of Mtr_MakeGroup */ + + +/**Function******************************************************************** + + Synopsis [Merges the children of `group' with the children of its + parent.] + + Description [Merges the children of `group' with the children of its + parent. Disposes of the node pointed by group. If group is the + root of the group tree, this procedure leaves the tree unchanged. + Returns the pointer to the parent of `group' upon successful + termination; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Mtr_MakeGroup] + +******************************************************************************/ +MtrNode * +Mtr_DissolveGroup( + MtrNode * group /* group to be dissolved */) +{ + MtrNode *parent; + MtrNode *last; + + parent = group->parent; + + if (parent == NULL) return(NULL); + if (MTR_TEST(group,MTR_TERMINAL) || group->child == NULL) return(NULL); + + /* Make all children of group children of its parent, and make + ** last point to the last child of group. */ + for (last = group->child; last->younger != NULL; last = last->younger) { + last->parent = parent; + } + last->parent = parent; + + last->younger = group->younger; + if (group->younger != NULL) { + group->younger->elder = last; + } + + group->child->elder = group->elder; + if (group == parent->child) { + parent->child = group->child; + } else { + group->elder->younger = group->child; + } + + Mtr_DeallocNode(group); + return(parent); + +} /* end of Mtr_DissolveGroup */ + + +/**Function******************************************************************** + + Synopsis [Finds a group with size leaves starting at low, if it exists.] + + Description [Finds a group with size leaves starting at low, if it + exists. This procedure relies on the low and size fields of each + node. It also assumes that the children of each node are sorted in + order of increasing low. Returns the pointer to the root of the + group upon successful termination; NULL otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +MtrNode * +Mtr_FindGroup( + MtrNode * root /* root of the group tree */, + unsigned int low /* lower bound of the group */, + unsigned int size /* upper bound of the group */) +{ + MtrNode *node; + +#ifdef MTR_DEBUG + /* We cannot have a non-empty proper subgroup of a singleton set. */ + assert(!MTR_TEST(root,MTR_TERMINAL)); +#endif + + /* Sanity check. */ + if (size < 1) return(NULL); + + /* Check whether current group includes the group sought. This + ** check is necessary at the top-level call. In the subsequent + ** calls it is redundant. */ + if (low < (unsigned int) root->low || + low + size > (unsigned int) (root->low + root->size)) + return(NULL); + + if (root->size == size && root->low == low) + return(root); + + if (root->child == NULL) + return(NULL); + + /* Find all chidren of root that are included in the new group. If + ** the group of any child entirely contains the new group, call + ** Mtr_MakeGroup recursively. */ + node = root->child; + while (low >= (unsigned int) (node->low + node->size)) { + node = node->younger; + } + if (low + size <= (unsigned int) (node->low + node->size)) { + /* The group is contained in the group of node. */ + node = Mtr_FindGroup(node, low, size); + return(node); + } else { + return(NULL); + } + +} /* end of Mtr_FindGroup */ + + +/**Function******************************************************************** + + Synopsis [Swaps two children of a tree node.] + + Description [Swaps two children of a tree node. Adjusts the high and + low fields of the two nodes and their descendants. The two children + must be adjacent. However, first may be the younger sibling of second. + Returns 1 in case of success; 0 otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +int +Mtr_SwapGroups( + MtrNode * first /* first node to be swapped */, + MtrNode * second /* second node to be swapped */) +{ + MtrNode *node; + MtrNode *parent; + int sizeFirst; + int sizeSecond; + + if (second->younger == first) { /* make first first */ + node = first; + first = second; + second = node; + } else if (first->younger != second) { /* non-adjacent */ + return(0); + } + + sizeFirst = first->size; + sizeSecond = second->size; + + /* Swap the two nodes. */ + parent = first->parent; + if (parent == NULL || second->parent != parent) return(0); + if (parent->child == first) { + parent->child = second; + } else { /* first->elder != NULL */ + first->elder->younger = second; + } + if (second->younger != NULL) { + second->younger->elder = first; + } + first->younger = second->younger; + second->elder = first->elder; + first->elder = second; + second->younger = first; + + /* Adjust the high and low fields. */ + if (!mtrShiftHL(first,sizeSecond)) return(0); + if (!mtrShiftHL(second,-sizeFirst)) return(0); + + return(1); + +} /* end of Mtr_SwapGroups */ + + +/**Function******************************************************************** + + Synopsis [Prints the groups as a parenthesized list.] + + Description [Prints the groups as a parenthesized list. After each + group, the group's flag are printed, preceded by a `|'. For each + flag (except MTR_TERMINAL) a character is printed. +
          +
        • F: MTR_FIXED +
        • N: MTR_NEWNODE +
        • S: MTR_SOFT +
        + The second argument, silent, if different from 0, causes + Mtr_PrintGroups to only check the syntax of the group tree. + ] + + SideEffects [None] + + SeeAlso [Mtr_PrintTree] + +******************************************************************************/ +void +Mtr_PrintGroups( + MtrNode * root /* root of the group tree */, + int silent /* flag to check tree syntax only */) +{ + MtrNode *node; + + assert(root != NULL); + assert(root->younger == NULL || root->younger->elder == root); + assert(root->elder == NULL || root->elder->younger == root); + if (!silent) (void) printf("(%d",root->low); + if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) { + if (!silent) (void) printf(","); + } else { + node = root->child; + while (node != NULL) { + assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size)); + assert(node->parent == root); + Mtr_PrintGroups(node,silent); + node = node->younger; + } + } + if (!silent) { + (void) printf("%d", root->low + root->size - 1); + if (root->flags != MTR_DEFAULT) { + (void) printf("|"); + if (MTR_TEST(root,MTR_FIXED)) (void) printf("F"); + if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N"); + if (MTR_TEST(root,MTR_SOFT)) (void) printf("S"); + } + (void) printf(")"); + if (root->parent == NULL) (void) printf("\n"); + } + assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0); + return; + +} /* end of Mtr_PrintGroups */ + + +/**Function******************************************************************** + + Synopsis [Reads groups from a file and creates a group tree.] + + Description [Reads groups from a file and creates a group tree. + Each group is specified by three fields: + + low size flags. + + Low and size are (short) integers. Flags is a string composed of the + following characters (with associated translation): +
          +
        • D: MTR_DEFAULT +
        • F: MTR_FIXED +
        • N: MTR_NEWNODE +
        • S: MTR_SOFT +
        • T: MTR_TERMINAL +
        + Normally, the only flags that are needed are D and F. Groups and + fields are separated by white space (spaces, tabs, and newlines). + Returns a pointer to the group tree if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Mtr_InitGroupTree Mtr_MakeGroup] + +******************************************************************************/ +MtrNode * +Mtr_ReadGroups( + FILE * fp /* file pointer */, + int nleaves /* number of leaves of the new tree */) +{ + int low; + int size; + int err; + unsigned int flags; + MtrNode *root; + MtrNode *node; + char attrib[8*sizeof(unsigned int)+1]; + char *c; + + root = Mtr_InitGroupTree(0,nleaves); + if (root == NULL) return NULL; + + while (! feof(fp)) { + /* Read a triple and check for consistency. */ + err = fscanf(fp, "%d %d %s", &low, &size, attrib); + if (err == EOF) { + break; + } else if (err != 3) { + return(NULL); + } else if (low < 0 || low+size > nleaves || size < 1) { + return(NULL); + } else if (strlen(attrib) > 8 * sizeof(MtrHalfWord)) { + /* Not enough bits in the flags word to store these many + ** attributes. */ + return(NULL); + } + + /* Parse the flag string. Currently all flags are permitted, + ** to make debugging easier. Normally, specifying NEWNODE + ** wouldn't be allowed. */ + flags = MTR_DEFAULT; + for (c=attrib; *c != 0; c++) { + switch (*c) { + case 'D': + break; + case 'F': + flags |= MTR_FIXED; + break; + case 'N': + flags |= MTR_NEWNODE; + break; + case 'S': + flags |= MTR_SOFT; + break; + case 'T': + flags |= MTR_TERMINAL; + break; + default: + return NULL; + } + } + node = Mtr_MakeGroup(root, (MtrHalfWord) low, (MtrHalfWord) size, + flags); + if (node == NULL) return(NULL); + } + + return(root); + +} /* end of Mtr_ReadGroups */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Adjusts the low fields of a node and its descendants.] + + Description [Adjusts the low fields of a node and its + descendants. Adds shift to low of each node. Checks that no + out-of-bounds values result. Returns 1 in case of success; 0 + otherwise.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +static int +mtrShiftHL( + MtrNode * node /* group tree node */, + int shift /* amount by which low should be changed */) +{ + MtrNode *auxnode; + int low; + + low = (int) node->low; + + + low += shift; + + if (low < 0 || low + (int) (node->size - 1) > (int) MTR_MAXHIGH) return(0); + + node->low = (MtrHalfWord) low; + + if (!MTR_TEST(node,MTR_TERMINAL) && node->child != NULL) { + auxnode = node->child; + do { + if (!mtrShiftHL(auxnode,shift)) return(0); + auxnode = auxnode->younger; + } while (auxnode != NULL); + } + + return(1); + +} /* end of mtrShiftHL */ + diff --git a/abc70930/src/bdd/mtr/mtrInt.h b/abc70930/src/bdd/mtr/mtrInt.h new file mode 100644 index 00000000..a8d5aa6c --- /dev/null +++ b/abc70930/src/bdd/mtr/mtrInt.h @@ -0,0 +1,65 @@ +/**CHeaderFile***************************************************************** + + FileName [mtrInt.h] + + PackageName [mtr] + + Synopsis [Internal data structures of the mtr package] + + Description [In this package all definitions are external.] + + SeeAlso [] + + Author [Fabio Somenzi] + + Copyright [This file was created at the University of Colorado at + Boulder. The University of Colorado at Boulder makes no warranty + about the suitability of this software for any purpose. It is + presented on an AS IS basis.] + + Revision [$Id: mtrInt.h,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $] + +******************************************************************************/ + +#ifndef _MTRINT +#define _MTRINT + +#include "mtr.h" + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Function prototypes */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticEnd***************************************************************/ + +#endif /* _MTRINT */ diff --git a/abc70930/src/bdd/parse/module.make b/abc70930/src/bdd/parse/module.make new file mode 100644 index 00000000..4f590f01 --- /dev/null +++ b/abc70930/src/bdd/parse/module.make @@ -0,0 +1,3 @@ +SRC += src/bdd/parse/parseCore.c \ + src/bdd/parse/parseEqn.c \ + src/bdd/parse/parseStack.c diff --git a/abc70930/src/bdd/parse/parse.h b/abc70930/src/bdd/parse/parse.h new file mode 100644 index 00000000..4923fbdd --- /dev/null +++ b/abc70930/src/bdd/parse/parse.h @@ -0,0 +1,54 @@ +/**CFile**************************************************************** + + FileName [parse.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Parsing symbolic Boolean formulas into BDDs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: parse.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __PARSE_H__ +#define __PARSE_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== parseCore.c =============================================================*/ +extern DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormula, int nVars, int nRanks, + char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/bdd/parse/parseCore.c b/abc70930/src/bdd/parse/parseCore.c new file mode 100644 index 00000000..21a37070 --- /dev/null +++ b/abc70930/src/bdd/parse/parseCore.c @@ -0,0 +1,504 @@ +/**CFile**************************************************************** + + FileNameIn [parseCore.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Boolean formula parser.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: parseCore.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +/* + Some aspects of Boolean Formula Parser: + + 1) The names in the boolean formulas can be any strings of symbols + that start with char or underscore and contain chars, digits + and underscores: For example: 1) a&b <+> c'&d => a + b; + 2) a1 b2 c3' dummy' + (a2+b2')c3 dummy + 2) Constant values 0 and 1 can be used just like normal variables + 3) Any boolean operator (listed below) and parantheses can be used + any number of times provided there are equal number of opening + and closing parantheses. + 4) By default, absence of an operator between vars and before and + after parantheses is taken for AND. + 5) Both complementation prefix and complementation suffix can be + used at the same time (but who needs this?) + 6) Spaces (tabs, end-of-lines) may be inserted anywhere, + except between characters of the operations: <=>, =>, <=, <+> + 7) The stack size is defined by macro STACKSIZE and is used by the + stack constructor. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#include "parseInt.h" + +// the list of operation symbols to be used in expressions +#define PARSE_SYM_OPEN '(' // opening paranthesis +#define PARSE_SYM_CLOSE ')' // closing paranthesis +#define PARSE_SYM_LOWER '[' // shifts one rank down +#define PARSE_SYM_RAISE ']' // shifts one rank up +#define PARSE_SYM_CONST0 '0' // constant 0 +#define PARSE_SYM_CONST1 '1' // constant 1 +#define PARSE_SYM_NEGBEF1 '!' // negation before the variable +#define PARSE_SYM_NEGBEF2 '~' // negation before the variable +#define PARSE_SYM_NEGAFT '\'' // negation after the variable +#define PARSE_SYM_AND1 '&' // logic AND +#define PARSE_SYM_AND2 '*' // logic AND +#define PARSE_SYM_XOR1 '<' // logic EXOR (the 1st symbol) +#define PARSE_SYM_XOR2 '+' // logic EXOR (the 2nd symbol) +#define PARSE_SYM_XOR3 '>' // logic EXOR (the 3rd symbol) +#define PARSE_SYM_OR '+' // logic OR +#define PARSE_SYM_EQU1 '<' // equvalence (the 1st symbol) +#define PARSE_SYM_EQU2 '=' // equvalence (the 2nd symbol) +#define PARSE_SYM_EQU3 '>' // equvalence (the 3rd symbol) +#define PARSE_SYM_FLR1 '=' // implication (the 1st symbol) +#define PARSE_SYM_FLR2 '>' // implication (the 2nd symbol) +#define PARSE_SYM_FLL1 '<' // backward imp (the 1st symbol) +#define PARSE_SYM_FLL2 '=' // backward imp (the 2nd symbol) +// PARSE_SYM_FLR1 and PARSE_SYM_FLR2 should be the same as PARSE_SYM_EQU2 and PARSE_SYM_EQU3! + +// the list of opcodes (also specifying operation precedence) +#define PARSE_OPER_NEG 10 // negation +#define PARSE_OPER_AND 9 // logic AND +#define PARSE_OPER_XOR 8 // logic EXOR (a'b | ab') +#define PARSE_OPER_OR 7 // logic OR +#define PARSE_OPER_EQU 6 // equvalence (a'b'| ab ) +#define PARSE_OPER_FLR 5 // implication ( a' | b ) +#define PARSE_OPER_FLL 4 // backward imp ( 'b | a ) +#define PARSE_OPER_MARK 1 // OpStack token standing for an opening paranthesis + +// these are values of the internal Flag +#define PARSE_FLAG_START 1 // after the opening parenthesis +#define PARSE_FLAG_VAR 2 // after operation is received +#define PARSE_FLAG_OPER 3 // after operation symbol is received +#define PARSE_FLAG_ERROR 4 // when error is detected + +#define STACKSIZE 1000 + +static DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the BDD corresponding to the formula in language L.] + + Description [Takes the stream to output messages, the formula, the number + variables and the rank in the formula. The array of variable names is also + given. The BDD manager and the elementary 0-rank variable are the last two + arguments. The manager should have at least as many variables as + nVars * (nRanks + 1). The 0-rank variables should have numbers larger + than the variables of other ranks.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormulaInit, int nVars, int nRanks, + char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ) +{ + char * pFormula; + Parse_StackFn_t * pStackFn; + Parse_StackOp_t * pStackOp; + DdNode * bFunc, * bTemp; + char * pTemp; + int nParans, fFound, Flag; + int Oper, Oper1, Oper2; + int i, v, fLower; + + // make sure that the number of vars and ranks is correct + if ( nVars * (nRanks + 1) > dd->size ) + { + printf( "Parse_FormulaParser(): The BDD manager does not have enough variables.\n" ); + return NULL; + } + + // make sure that the number of opening and closing parantheses is the same + nParans = 0; + for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) + if ( *pTemp == '(' ) + nParans++; + else if ( *pTemp == ')' ) + nParans--; + if ( nParans != 0 ) + { + fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing parantheses ().\n" ); + return NULL; + } + + nParans = 0; + for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) + if ( *pTemp == '[' ) + nParans++; + else if ( *pTemp == ']' ) + nParans--; + if ( nParans != 0 ) + { + fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing brackets [].\n" ); + return NULL; + } + + // copy the formula + pFormula = ALLOC( char, strlen(pFormulaInit) + 3 ); + sprintf( pFormula, "(%s)", pFormulaInit ); + + // start the stacks + pStackFn = Parse_StackFnStart( STACKSIZE ); + pStackOp = Parse_StackOpStart( STACKSIZE ); + + Flag = PARSE_FLAG_START; + fLower = 0; + for ( pTemp = pFormula; *pTemp; pTemp++ ) + { + switch ( *pTemp ) + { + // skip all spaces, tabs, and end-of-lines + case ' ': + case '\t': + case '\r': + case '\n': + continue; + + // treat Constant 0 as a variable + case PARSE_SYM_CONST0: + Parse_StackFnPush( pStackFn, b0 ); Cudd_Ref( b0 ); + if ( Flag == PARSE_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 0.\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + Flag = PARSE_FLAG_VAR; + break; + + // the same for Constant 1 + case PARSE_SYM_CONST1: + Parse_StackFnPush( pStackFn, b1 ); Cudd_Ref( b1 ); + if ( Flag == PARSE_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 1.\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + Flag = PARSE_FLAG_VAR; + break; + + case PARSE_SYM_NEGBEF1: + case PARSE_SYM_NEGBEF2: + if ( Flag == PARSE_FLAG_VAR ) + {// if NEGBEF follows a variable, AND is assumed + Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); + Flag = PARSE_FLAG_OPER; + } + Parse_StackOpPush( pStackOp, PARSE_OPER_NEG ); + break; + + case PARSE_SYM_NEGAFT: + if ( Flag != PARSE_FLAG_VAR ) + {// if there is no variable before NEGAFT, it is an error + fprintf( pOutput, "Parse_FormulaParser(): No variable is specified before the negation suffix.\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + else // if ( Flag == PARSE_FLAG_VAR ) + Parse_StackFnPush( pStackFn, Cudd_Not( Parse_StackFnPop(pStackFn) ) ); + break; + + case PARSE_SYM_AND1: + case PARSE_SYM_AND2: + case PARSE_SYM_OR: + if ( Flag != PARSE_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR.\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + if ( *pTemp == PARSE_SYM_AND1 || *pTemp == PARSE_SYM_AND2 ) + Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); + else //if ( Str[Pos] == PARSE_SYM_OR ) + Parse_StackOpPush( pStackOp, PARSE_OPER_OR ); + Flag = PARSE_FLAG_OPER; + break; + + case PARSE_SYM_EQU1: + if ( Flag != PARSE_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Equivalence or Implication\n" ); + Flag = PARSE_FLAG_ERROR; break; + } + if ( pTemp[1] == PARSE_SYM_EQU2 ) + { // check what is the next symbol in the string + pTemp++; + if ( pTemp[1] == PARSE_SYM_EQU3 ) + { + pTemp++; + Parse_StackOpPush( pStackOp, PARSE_OPER_EQU ); + } + else + { + Parse_StackOpPush( pStackOp, PARSE_OPER_FLL ); + } + } + else if ( pTemp[1] == PARSE_SYM_XOR2 ) + { + pTemp++; + if ( pTemp[1] == PARSE_SYM_XOR3 ) + { + pTemp++; + Parse_StackOpPush( pStackOp, PARSE_OPER_XOR ); + } + else + { + fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c%c\"\n", PARSE_SYM_EQU1, PARSE_SYM_XOR2 ); + Flag = PARSE_FLAG_ERROR; + break; + } + } + else + { + fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU1 ); + Flag = PARSE_FLAG_ERROR; + break; + } + Flag = PARSE_FLAG_OPER; + break; + + case PARSE_SYM_EQU2: + if ( Flag != PARSE_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Reverse Implication\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + if ( pTemp[1] == PARSE_SYM_EQU3 ) + { + pTemp++; + Parse_StackOpPush( pStackOp, PARSE_OPER_FLR ); + } + else + { + fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU2 ); + Flag = PARSE_FLAG_ERROR; + break; + } + Flag = PARSE_FLAG_OPER; + break; + + case PARSE_SYM_LOWER: + case PARSE_SYM_OPEN: + if ( Flag == PARSE_FLAG_VAR ) + Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); + Parse_StackOpPush( pStackOp, PARSE_OPER_MARK ); + // after an opening bracket, it feels like starting over again + Flag = PARSE_FLAG_START; + break; + + case PARSE_SYM_RAISE: + fLower = 1; + case PARSE_SYM_CLOSE: + if ( !Parse_StackOpIsEmpty( pStackOp ) ) + { + while ( 1 ) + { + if ( Parse_StackOpIsEmpty( pStackOp ) ) + { + fprintf( pOutput, "Parse_FormulaParser(): There is no opening paranthesis\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + Oper = Parse_StackOpPop( pStackOp ); + if ( Oper == PARSE_OPER_MARK ) + break; + + // perform the given operation + if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper ) == NULL ) + { + fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); + free( pFormula ); + return NULL; + } + } + + if ( fLower ) + { + bFunc = Parse_StackFnPop( pStackFn ); + bFunc = Extra_bddMove( dd, bTemp = bFunc, -nVars ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + Parse_StackFnPush( pStackFn, bFunc ); + } + } + else + { + fprintf( pOutput, "Parse_FormulaParser(): There is no opening paranthesis\n" ); + Flag = PARSE_FLAG_ERROR; + break; + } + if ( Flag != PARSE_FLAG_ERROR ) + Flag = PARSE_FLAG_VAR; + fLower = 0; + break; + + + default: + // scan the next name + fFound = 0; + for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n'; i++ ) + { + for ( v = 0; v < nVars; v++ ) + if ( strncmp( pTemp, ppVarNames[v], i+1 ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i+1) ) + { + pTemp += i; + fFound = 1; + break; + } + if ( fFound ) + break; + } + if ( !fFound ) + { + fprintf( pOutput, "Parse_FormulaParser(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); + Flag = PARSE_FLAG_ERROR; + break; + } + + // assume operation AND, if vars follow one another + if ( Flag == PARSE_FLAG_VAR ) + Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); + Parse_StackFnPush( pStackFn, pbVars[v] ); Cudd_Ref( pbVars[v] ); + Flag = PARSE_FLAG_VAR; + break; + } + + if ( Flag == PARSE_FLAG_ERROR ) + break; // error exit + else if ( Flag == PARSE_FLAG_START ) + continue; // go on parsing + else if ( Flag == PARSE_FLAG_VAR ) + while ( 1 ) + { // check if there are negations in the OpStack + if ( Parse_StackOpIsEmpty(pStackOp) ) + break; + Oper = Parse_StackOpPop( pStackOp ); + if ( Oper != PARSE_OPER_NEG ) + { + Parse_StackOpPush( pStackOp, Oper ); + break; + } + else + { + Parse_StackFnPush( pStackFn, Cudd_Not(Parse_StackFnPop(pStackFn)) ); + } + } + else // if ( Flag == PARSE_FLAG_OPER ) + while ( 1 ) + { // execute all the operations in the OpStack + // with precedence higher or equal than the last one + Oper1 = Parse_StackOpPop( pStackOp ); // the last operation + if ( Parse_StackOpIsEmpty(pStackOp) ) + { // if it is the only operation, push it back + Parse_StackOpPush( pStackOp, Oper1 ); + break; + } + Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one + if ( Oper2 >= Oper1 ) + { // if Oper2 precedence is higher or equal, execute it +// Parse_StackPush( pStackFn, Operation( FunStack.Pop(), FunStack.Pop(), Oper2 ) ); + if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper2 ) == NULL ) + { + fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); + free( pFormula ); + return NULL; + } + Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back + } + else + { // if Oper2 precedence is lower, push them back and done + Parse_StackOpPush( pStackOp, Oper2 ); + Parse_StackOpPush( pStackOp, Oper1 ); + break; + } + } + } + + if ( Flag != PARSE_FLAG_ERROR ) + { + if ( !Parse_StackFnIsEmpty(pStackFn) ) + { + bFunc = Parse_StackFnPop(pStackFn); + if ( Parse_StackFnIsEmpty(pStackFn) ) + if ( Parse_StackOpIsEmpty(pStackOp) ) + { + Parse_StackFnFree(pStackFn); + Parse_StackOpFree(pStackOp); + Cudd_Deref( bFunc ); + free( pFormula ); + return bFunc; + } + else + fprintf( pOutput, "Parse_FormulaParser(): Something is left in the operation stack\n" ); + else + fprintf( pOutput, "Parse_FormulaParser(): Something is left in the function stack\n" ); + } + else + fprintf( pOutput, "Parse_FormulaParser(): The input string is empty\n" ); + } + free( pFormula ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs the operation on the top entries in the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ) +{ + DdNode * bArg1, * bArg2, * bFunc; + // perform the given operation + bArg2 = Parse_StackFnPop( pStackFn ); + bArg1 = Parse_StackFnPop( pStackFn ); + if ( Oper == PARSE_OPER_AND ) + bFunc = Cudd_bddAnd( dd, bArg1, bArg2 ); + else if ( Oper == PARSE_OPER_XOR ) + bFunc = Cudd_bddXor( dd, bArg1, bArg2 ); + else if ( Oper == PARSE_OPER_OR ) + bFunc = Cudd_bddOr( dd, bArg1, bArg2 ); + else if ( Oper == PARSE_OPER_EQU ) + bFunc = Cudd_bddXnor( dd, bArg1, bArg2 ); + else if ( Oper == PARSE_OPER_FLR ) + bFunc = Cudd_bddOr( dd, Cudd_Not(bArg1), bArg2 ); + else if ( Oper == PARSE_OPER_FLL ) + bFunc = Cudd_bddOr( dd, Cudd_Not(bArg2), bArg1 ); + else + return NULL; + Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bArg1 ); + Cudd_RecursiveDeref( dd, bArg2 ); + Parse_StackFnPush( pStackFn, bFunc ); + return bFunc; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/bdd/parse/parseEqn.c b/abc70930/src/bdd/parse/parseEqn.c new file mode 100644 index 00000000..02d83966 --- /dev/null +++ b/abc70930/src/bdd/parse/parseEqn.c @@ -0,0 +1,349 @@ +/**CFile**************************************************************** + + FileNameIn [parseEqn.c] + + PackageName [ABC: Logic synthesis and verification system.] + + Synopsis [Boolean formula parser.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 18, 2006.] + + Revision [$Id: parseEqn.c,v 1.0 2006/12/18 00:00:00 alanmi Exp $] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#include "parseInt.h" +#include "vec.h" +#include "hop.h" + +// the list of operation symbols to be used in expressions +#define PARSE_EQN_SYM_OPEN '(' // opening paranthesis +#define PARSE_EQN_SYM_CLOSE ')' // closing paranthesis +#define PARSE_EQN_SYM_CONST0 '0' // constant 0 +#define PARSE_EQN_SYM_CONST1 '1' // constant 1 +#define PARSE_EQN_SYM_NEG '!' // negation before the variable +#define PARSE_EQN_SYM_AND '*' // logic AND +#define PARSE_EQN_SYM_OR '+' // logic OR + +// the list of opcodes (also specifying operation precedence) +#define PARSE_EQN_OPER_NEG 10 // negation +#define PARSE_EQN_OPER_AND 9 // logic AND +#define PARSE_EQN_OPER_OR 7 // logic OR +#define PARSE_EQN_OPER_MARK 1 // OpStack token standing for an opening paranthesis + +// these are values of the internal Flag +#define PARSE_EQN_FLAG_START 1 // after the opening parenthesis +#define PARSE_EQN_FLAG_VAR 2 // after operation is received +#define PARSE_EQN_FLAG_OPER 3 // after operation symbol is received +#define PARSE_EQN_FLAG_ERROR 4 // when error is detected + +#define PARSE_EQN_STACKSIZE 1000 + +static Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the AIG corresponding to the equation.] + + Description [Takes the stream to output messages, the formula, the vector + of variable names and the AIG manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ) +{ + char * pFormula; + Parse_StackFn_t * pStackFn; + Parse_StackOp_t * pStackOp; + Hop_Obj_t * gFunc; + char * pTemp, * pName; + int nParans, fFound, Flag; + int Oper, Oper1, Oper2; + int i, v; + + // make sure that the number of opening and closing parantheses is the same + nParans = 0; + for ( pTemp = pFormInit; *pTemp; pTemp++ ) + if ( *pTemp == '(' ) + nParans++; + else if ( *pTemp == ')' ) + nParans--; + if ( nParans != 0 ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): Different number of opening and closing parantheses ().\n" ); + return NULL; + } + + // copy the formula + pFormula = ALLOC( char, strlen(pFormInit) + 3 ); + sprintf( pFormula, "(%s)", pFormInit ); + + // start the stacks + pStackFn = Parse_StackFnStart( PARSE_EQN_STACKSIZE ); + pStackOp = Parse_StackOpStart( PARSE_EQN_STACKSIZE ); + + Flag = PARSE_EQN_FLAG_START; + for ( pTemp = pFormula; *pTemp; pTemp++ ) + { + switch ( *pTemp ) + { + // skip all spaces, tabs, and end-of-lines + case ' ': + case '\t': + case '\r': + case '\n': + continue; + case PARSE_EQN_SYM_CONST0: + Parse_StackFnPush( pStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( b0 ); + if ( Flag == PARSE_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 0.\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + Flag = PARSE_EQN_FLAG_VAR; + break; + case PARSE_EQN_SYM_CONST1: + Parse_StackFnPush( pStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( b1 ); + if ( Flag == PARSE_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 1.\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + Flag = PARSE_EQN_FLAG_VAR; + break; + case PARSE_EQN_SYM_NEG: + if ( Flag == PARSE_EQN_FLAG_VAR ) + {// if NEGBEF follows a variable, AND is assumed + Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); + Flag = PARSE_EQN_FLAG_OPER; + } + Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_NEG ); + break; + case PARSE_EQN_SYM_AND: + case PARSE_EQN_SYM_OR: + if ( Flag != PARSE_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): There is no variable before AND, EXOR, or OR.\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + if ( *pTemp == PARSE_EQN_SYM_AND ) + Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); + else //if ( *pTemp == PARSE_EQN_SYM_OR ) + Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_OR ); + Flag = PARSE_EQN_FLAG_OPER; + break; + case PARSE_EQN_SYM_OPEN: + if ( Flag == PARSE_EQN_FLAG_VAR ) + { +// Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); + fprintf( pOutput, "Parse_FormulaParserEqn(): An opening paranthesis follows a var without operation sign.\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_MARK ); + // after an opening bracket, it feels like starting over again + Flag = PARSE_EQN_FLAG_START; + break; + case PARSE_EQN_SYM_CLOSE: + if ( !Parse_StackOpIsEmpty( pStackOp ) ) + { + while ( 1 ) + { + if ( Parse_StackOpIsEmpty( pStackOp ) ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening paranthesis\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + Oper = Parse_StackOpPop( pStackOp ); + if ( Oper == PARSE_EQN_OPER_MARK ) + break; + + // perform the given operation + if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper ) == NULL ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); + free( pFormula ); + return NULL; + } + } + } + else + { + fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening paranthesis\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + if ( Flag != PARSE_EQN_FLAG_ERROR ) + Flag = PARSE_EQN_FLAG_VAR; + break; + + + default: + // scan the next name + for ( i = 0; pTemp[i] && + pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && + pTemp[i] != PARSE_EQN_SYM_AND && pTemp[i] != PARSE_EQN_SYM_OR && pTemp[i] != PARSE_EQN_SYM_CLOSE; i++ ) + { + if ( pTemp[i] == PARSE_EQN_SYM_NEG || pTemp[i] == PARSE_EQN_SYM_OPEN ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): The negation sign or an opening paranthesis inside the variable name.\n" ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + } + // variable name is found + fFound = 0; + Vec_PtrForEachEntry( vVarNames, pName, v ) + if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i ) + { + pTemp += i-1; + fFound = 1; + break; + } + if ( !fFound ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + if ( Flag == PARSE_EQN_FLAG_VAR ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); + Flag = PARSE_EQN_FLAG_ERROR; + break; + } + Parse_StackFnPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] ); + Flag = PARSE_EQN_FLAG_VAR; + break; + } + + if ( Flag == PARSE_EQN_FLAG_ERROR ) + break; // error exit + else if ( Flag == PARSE_EQN_FLAG_START ) + continue; // go on parsing + else if ( Flag == PARSE_EQN_FLAG_VAR ) + while ( 1 ) + { // check if there are negations in the OpStack + if ( Parse_StackOpIsEmpty(pStackOp) ) + break; + Oper = Parse_StackOpPop( pStackOp ); + if ( Oper != PARSE_EQN_OPER_NEG ) + { + Parse_StackOpPush( pStackOp, Oper ); + break; + } + else + { + Parse_StackFnPush( pStackFn, Hop_Not(Parse_StackFnPop(pStackFn)) ); + } + } + else // if ( Flag == PARSE_EQN_FLAG_OPER ) + while ( 1 ) + { // execute all the operations in the OpStack + // with precedence higher or equal than the last one + Oper1 = Parse_StackOpPop( pStackOp ); // the last operation + if ( Parse_StackOpIsEmpty(pStackOp) ) + { // if it is the only operation, push it back + Parse_StackOpPush( pStackOp, Oper1 ); + break; + } + Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one + if ( Oper2 >= Oper1 ) + { // if Oper2 precedence is higher or equal, execute it + if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper2 ) == NULL ) + { + fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); + free( pFormula ); + return NULL; + } + Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back + } + else + { // if Oper2 precedence is lower, push them back and done + Parse_StackOpPush( pStackOp, Oper2 ); + Parse_StackOpPush( pStackOp, Oper1 ); + break; + } + } + } + + if ( Flag != PARSE_EQN_FLAG_ERROR ) + { + if ( !Parse_StackFnIsEmpty(pStackFn) ) + { + gFunc = Parse_StackFnPop(pStackFn); + if ( Parse_StackFnIsEmpty(pStackFn) ) + if ( Parse_StackOpIsEmpty(pStackOp) ) + { + Parse_StackFnFree(pStackFn); + Parse_StackOpFree(pStackOp); +// Cudd_Deref( gFunc ); + free( pFormula ); + return gFunc; + } + else + fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the operation stack\n" ); + else + fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the function stack\n" ); + } + else + fprintf( pOutput, "Parse_FormulaParserEqn(): The input string is empty\n" ); + } + free( pFormula ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs the operation on the top entries in the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ) +{ + Hop_Obj_t * gArg1, * gArg2, * gFunc; + // perform the given operation + gArg2 = Parse_StackFnPop( pStackFn ); + gArg1 = Parse_StackFnPop( pStackFn ); + if ( Oper == PARSE_EQN_OPER_AND ) + gFunc = Hop_And( pMan, gArg1, gArg2 ); + else if ( Oper == PARSE_EQN_OPER_OR ) + gFunc = Hop_Or( pMan, gArg1, gArg2 ); + else + return NULL; +// Cudd_Ref( gFunc ); +// Cudd_RecursiveDeref( dd, gArg1 ); +// Cudd_RecursiveDeref( dd, gArg2 ); + Parse_StackFnPush( pStackFn, gFunc ); + return gFunc; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/bdd/parse/parseInt.h b/abc70930/src/bdd/parse/parseInt.h new file mode 100644 index 00000000..17f48375 --- /dev/null +++ b/abc70930/src/bdd/parse/parseInt.h @@ -0,0 +1,74 @@ +/**CFile**************************************************************** + + FileName [parseInt.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Parsing symbolic Boolean formulas into BDDs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: parseInt.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __PARSE_INT_H__ +#define __PARSE_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + + +#include +#include "cuddInt.h" +#include "extra.h" +#include "parse.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef int bool; + +typedef struct ParseStackFnStruct Parse_StackFn_t; // the function stack +typedef struct ParseStackOpStruct Parse_StackOp_t; // the operation stack + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== parseStack.c =============================================================*/ +extern Parse_StackFn_t * Parse_StackFnStart ( int nDepth ); +extern bool Parse_StackFnIsEmpty( Parse_StackFn_t * p ); +extern void Parse_StackFnPush ( Parse_StackFn_t * p, void * bFunc ); +extern void * Parse_StackFnPop ( Parse_StackFn_t * p ); +extern void Parse_StackFnFree ( Parse_StackFn_t * p ); + +extern Parse_StackOp_t * Parse_StackOpStart ( int nDepth ); +extern bool Parse_StackOpIsEmpty( Parse_StackOp_t * p ); +extern void Parse_StackOpPush ( Parse_StackOp_t * p, int Oper ); +extern int Parse_StackOpPop ( Parse_StackOp_t * p ); +extern void Parse_StackOpFree ( Parse_StackOp_t * p ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/bdd/parse/parseStack.c b/abc70930/src/bdd/parse/parseStack.c new file mode 100644 index 00000000..cd7cd7e3 --- /dev/null +++ b/abc70930/src/bdd/parse/parseStack.c @@ -0,0 +1,243 @@ +/**CFile**************************************************************** + + FileName [parseStack.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Stacks used by the formula parser.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 18, 2003.] + + Revision [$Id: parseStack.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "parseInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct ParseStackFnStruct +{ + void ** pData; // the array of elements + int Top; // the index + int Size; // the stack size +}; + +struct ParseStackOpStruct +{ + int * pData; // the array of elements + int Top; // the index + int Size; // the stack size +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Parse_StackFn_t * Parse_StackFnStart( int nDepth ) +{ + Parse_StackFn_t * p; + p = ALLOC( Parse_StackFn_t, 1 ); + memset( p, 0, sizeof(Parse_StackFn_t) ); + p->pData = ALLOC( void *, nDepth ); + p->Size = nDepth; + return p; +} + +/**Function************************************************************* + + Synopsis [Checks whether the stack is empty.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Parse_StackFnIsEmpty( Parse_StackFn_t * p ) +{ + return (bool)(p->Top == 0); +} + +/**Function************************************************************* + + Synopsis [Pushes an entry into the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Parse_StackFnPush( Parse_StackFn_t * p, void * bFunc ) +{ + if ( p->Top >= p->Size ) + { + printf( "Parse_StackFnPush(): Stack size is too small!\n" ); + return; + } + p->pData[ p->Top++ ] = bFunc; +} + +/**Function************************************************************* + + Synopsis [Pops an entry out of the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Parse_StackFnPop( Parse_StackFn_t * p ) +{ + if ( p->Top == 0 ) + { + printf( "Parse_StackFnPush(): Trying to extract data from the empty stack!\n" ); + return NULL; + } + return p->pData[ --p->Top ]; +} + +/**Function************************************************************* + + Synopsis [Deletes the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Parse_StackFnFree( Parse_StackFn_t * p ) +{ + FREE( p->pData ); + FREE( p ); +} + + + + +/**Function************************************************************* + + Synopsis [Starts the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Parse_StackOp_t * Parse_StackOpStart( int nDepth ) +{ + Parse_StackOp_t * p; + p = ALLOC( Parse_StackOp_t, 1 ); + memset( p, 0, sizeof(Parse_StackOp_t) ); + p->pData = ALLOC( int, nDepth ); + p->Size = nDepth; + return p; +} + +/**Function************************************************************* + + Synopsis [Checks whether the stack is empty.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Parse_StackOpIsEmpty( Parse_StackOp_t * p ) +{ + return (bool)(p->Top == 0); +} + +/**Function************************************************************* + + Synopsis [Pushes an entry into the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Parse_StackOpPush( Parse_StackOp_t * p, int Oper ) +{ + if ( p->Top >= p->Size ) + { + printf( "Parse_StackOpPush(): Stack size is too small!\n" ); + return; + } + p->pData[ p->Top++ ] = Oper; +} + +/**Function************************************************************* + + Synopsis [Pops an entry out of the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Parse_StackOpPop( Parse_StackOp_t * p ) +{ + if ( p->Top == 0 ) + { + printf( "Parse_StackOpPush(): Trying to extract data from the empty stack!\n" ); + return -1; + } + return p->pData[ --p->Top ]; +} + +/**Function************************************************************* + + Synopsis [Deletes the stack.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Parse_StackOpFree( Parse_StackOp_t * p ) +{ + FREE( p->pData ); + FREE( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/bdd/reo/module.make b/abc70930/src/bdd/reo/module.make new file mode 100644 index 00000000..7eb41e0e --- /dev/null +++ b/abc70930/src/bdd/reo/module.make @@ -0,0 +1,7 @@ +SRC += src/bdd/reo/reoApi.c \ + src/bdd/reo/reoCore.c \ + src/bdd/reo/reoProfile.c \ + src/bdd/reo/reoSift.c \ + src/bdd/reo/reoSwap.c \ + src/bdd/reo/reoTransfer.c \ + src/bdd/reo/reoUnits.c diff --git a/abc70930/src/bdd/reo/reo.h b/abc70930/src/bdd/reo/reo.h new file mode 100644 index 00000000..1a31242a --- /dev/null +++ b/abc70930/src/bdd/reo/reo.h @@ -0,0 +1,232 @@ +/**CFile**************************************************************** + + FileName [reo.h] + + PackageName [REO: A specialized DD reordering engine.] + + Synopsis [External and internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 15, 2002.] + + Revision [$Id: reo.h,v 1.0 2002/15/10 03:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __REO_H__ +#define __REO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "extra.h" + +//#pragma warning( disable : 4514 ) + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// reordering parameters +#define REO_REORDER_LIMIT 1.15 // determines the quality/runtime trade-off +#define REO_QUAL_PAR 3 // the quality [1 = simple lower bound, 2 = strict, larger = heuristic] +// internal parameters +#define REO_CONST_LEVEL 30000 // the number of the constant level +#define REO_TOPREF_UNDEF 30000 // the undefined top reference +#define REO_CHUNK_SIZE 5000 // the number of units allocated at one time +#define REO_COST_EPSILON 0.0000001 // difference in cost large enough so that it counted as an error +#define REO_HIGH_VALUE 10000000 // a large value used to initialize some variables +// interface parameters +#define REO_ENABLE 1 // the value of the enable flag +#define REO_DISABLE 0 // the value of the disable flag + +// the types of minimization currently supported +typedef enum { + REO_MINIMIZE_NODES, + REO_MINIMIZE_WIDTH, // may not work for BDDs with complemented edges + REO_MINIMIZE_APL +} reo_min_type; + +//////////////////////////////////////////////////////////////////////// +/// DATA STRUCTURES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct _reo_unit reo_unit; // the unit representing one DD node during reordering +typedef struct _reo_plane reo_plane; // the set of nodes on one level +typedef struct _reo_hash reo_hash; // the entry in the hash table +typedef struct _reo_man reo_man; // the reordering manager +typedef struct _reo_test reo_test; // + +struct _reo_unit +{ + short lev; // the level of this node at the beginning + short TopRef; // the top level from which this node is refed (used to update BDD width) + short TopRefNew; // the new top level from which this node is refed (used to update BDD width) + short n; // the number of incoming edges (similar to ref count in the BDD) + int Sign; // the signature + + reo_unit * pE; // the pointer to the "else" branch + reo_unit * pT; // the pointer to the "then" branch + reo_unit * Next; // the link to the next one in the list + double Weight; // the probability of traversing this node +}; + +struct _reo_plane +{ + int fSifted; // to mark the sifted variables + int statsNodes; // the number of nodes in the current level + int statsWidth; // the width on the current level + double statsApl; // the sum of node probabilities on this level + double statsCost; // the current cost is stored here + double statsCostAbove; // the current cost is stored here + double statsCostBelow; // the current cost is stored here + + reo_unit * pHead; // the pointer to the beginning of the unit list +}; + +struct _reo_hash +{ + int Sign; // signature of the current cache operation + reo_unit * Arg1; // the first argument + reo_unit * Arg2; // the second argument + reo_unit * Arg3; // the third argument +}; + +struct _reo_man +{ + // these paramaters can be set by the API functions + int fMinWidth; // the flag to enable reordering for minimum width + int fMinApl; // the flag to enable reordering for minimum APL + int fVerbose; // the verbosity level + int fVerify; // the flag toggling verification + int fRemapUp; // the flag to enable remapping + int nIters; // the number of interations of sifting to perform + + // parameters given by the user when reordering is called + DdManager * dd; // the CUDD BDD manager + int * pOrder; // the resulting variable order will be returned here + + // derived parameters + int fThisIsAdd; // this flag is one if the function is the ADD + int * pSupp; // the support of the given function + int nSuppAlloc; // the max allowed number of support variables + int nSupp; // the number of support variables + int * pOrderInt; // the array storing the internal variable permutation + double * pVarCosts; // other arrays + int * pLevelOrder; // other arrays + reo_unit ** pWidthCofs; // temporary storage for cofactors used during reordering for width + + // parameters related to cost + int nNodesBeg; + int nNodesCur; + int nNodesEnd; + int nWidthCur; + int nWidthBeg; + int nWidthEnd; + double nAplCur; + double nAplBeg; + double nAplEnd; + + // mapping of the function into planes and back + int * pMapToPlanes; // the mapping of var indexes into plane levels + int * pMapToDdVarsOrig;// the mapping of plane levels into the original indexes + int * pMapToDdVarsFinal;// the mapping of plane levels into the final indexes + + // the planes table + reo_plane * pPlanes; + int nPlanes; + reo_unit ** pTops; + int nTops; + int nTopsAlloc; + + // the hash table + reo_hash * HTable; // the table itself + int nTableSize; // the size of the hash table + int Signature; // the signature counter + + // the referenced node list + int nNodesMaxAlloc; // this parameters determins how much memory is allocated + DdNode ** pRefNodes; + int nRefNodes; + int nRefNodesAlloc; + + // unit memory management + reo_unit * pUnitFreeList; + reo_unit ** pMemChunks; + int nMemChunks; + int nMemChunksAlloc; + int nUnitsUsed; + + // statistic variables + int HashSuccess; + int HashFailure; + int nSwaps; // the number of swaps + int nNISwaps; // the number of swaps without interaction +}; + +// used to manipulate units +#define Unit_Regular(u) ((reo_unit *)((unsigned long)(u) & ~01)) +#define Unit_Not(u) ((reo_unit *)((unsigned long)(u) ^ 01)) +#define Unit_NotCond(u,c) ((reo_unit *)((unsigned long)(u) ^ (c))) +#define Unit_IsConstant(u) ((int)((u)->lev == REO_CONST_LEVEL)) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// ======================= reoApi.c ======================================== +extern reo_man * Extra_ReorderInit( int nDdVarsMax, int nNodesMax ); +extern void Extra_ReorderQuit( reo_man * p ); +extern void Extra_ReorderSetMinimizationType( reo_man * p, reo_min_type fMinType ); +extern void Extra_ReorderSetRemapping( reo_man * p, int fRemapUp ); +extern void Extra_ReorderSetIterations( reo_man * p, int nIters ); +extern void Extra_ReorderSetVerbosity( reo_man * p, int fVerbose ); +extern void Extra_ReorderSetVerification( reo_man * p, int fVerify ); +extern DdNode * Extra_Reorder( reo_man * p, DdManager * dd, DdNode * Func, int * pOrder ); +extern void Extra_ReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ); +// ======================= reoCore.c ======================================= +extern void reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ); +extern void reoResizeStructures( reo_man * p, int nDdVarsMax, int nNodesMax, int nFuncs ); +// ======================= reoProfile.c ====================================== +extern void reoProfileNodesStart( reo_man * p ); +extern void reoProfileAplStart( reo_man * p ); +extern void reoProfileWidthStart( reo_man * p ); +extern void reoProfileWidthStart2( reo_man * p ); +extern void reoProfileAplPrint( reo_man * p ); +extern void reoProfileNodesPrint( reo_man * p ); +extern void reoProfileWidthPrint( reo_man * p ); +extern void reoProfileWidthVerifyLevel( reo_plane * pPlane, int Level ); +// ======================= reoSift.c ======================================= +extern void reoReorderSift( reo_man * p ); +// ======================= reoSwap.c ======================================= +extern double reoReorderSwapAdjacentVars( reo_man * p, int Level, int fMovingUp ); +// ======================= reoTransfer.c =================================== +extern reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ); +extern DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ); +// ======================= reoUnits.c ====================================== +extern reo_unit * reoUnitsGetNextUnit(reo_man * p ); +extern void reoUnitsRecycleUnit( reo_man * p, reo_unit * pUnit ); +extern void reoUnitsRecycleUnitList( reo_man * p, reo_plane * pPlane ); +extern void reoUnitsAddUnitToPlane( reo_plane * pPlane, reo_unit * pUnit ); +extern void reoUnitsStopDispenser( reo_man * p ); +// ======================= reoTest.c ======================================= +extern void Extra_ReorderTest( DdManager * dd, DdNode * Func ); +extern DdNode * Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermuteReo[] ); +extern int Extra_bddReorderTest( DdManager * dd, DdNode * bF ); +extern int Extra_addReorderTest( DdManager * dd, DdNode * aF ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/bdd/reo/reoApi.c b/abc70930/src/bdd/reo/reoApi.c new file mode 100644 index 00000000..e833dabd --- /dev/null +++ b/abc70930/src/bdd/reo/reoApi.c @@ -0,0 +1,289 @@ +/**CFile**************************************************************** + + FileName [reoApi.c] + + PackageName [REO: A specialized DD reordering engine.] + + Synopsis [Implementation of API functions.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 15, 2002.] + + Revision [$Id: reoApi.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "reo.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Initializes the reordering engine.] + + Description [The first argument is the max number of variables in the + CUDD DD manager which will be used with the reordering engine + (this number of should be the maximum of BDD and ZDD parts). + The second argument is the maximum number of BDD nodes in the BDDs + to be reordered. These limits are soft. Setting lower limits will later + cause the reordering manager to resize internal data structures. + However, setting the exact values will make reordering more efficient + because resizing will be not necessary.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +reo_man * Extra_ReorderInit( int nDdVarsMax, int nNodesMax ) +{ + reo_man * p; + // allocate and clean the data structure + p = ALLOC( reo_man, 1 ); + memset( p, 0, sizeof(reo_man) ); + // resize the manager to meet user's needs + reoResizeStructures( p, nDdVarsMax, nNodesMax, 100 ); + // set the defaults + p->fMinApl = 0; + p->fMinWidth = 0; + p->fRemapUp = 0; + p->fVerbose = 0; + p->fVerify = 0; + p->nIters = 1; + return p; +} + +/**Function************************************************************* + + Synopsis [Disposes of the reordering engine.] + + Description [Removes all memory associated with the reordering engine.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ReorderQuit( reo_man * p ) +{ + free( p->pTops ); + free( p->pSupp ); + free( p->pOrderInt ); + free( p->pWidthCofs ); + free( p->pMapToPlanes ); + free( p->pMapToDdVarsOrig ); + free( p->pMapToDdVarsFinal ); + free( p->pPlanes ); + free( p->pVarCosts ); + free( p->pLevelOrder ); + free( p->HTable ); + free( p->pRefNodes ); + reoUnitsStopDispenser( p ); + free( p->pMemChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Sets the type of DD minimizationl that will be performed.] + + Description [Currently, three different types of minimization are supported. + It is possible to minimize the number of BDD nodes. This is a classical type + of minimization, which is attempting to reduce the total number of nodes in + the (shared) BDD of the given Boolean functions. It is also possible to + minimize the BDD width, defined as the sum total of the number of cofactors + on each level in the (shared) BDD (note that the number of cofactors on the + given level may be larger than the number of nodes appearing on the given level). + It is also possible to minimize the average path length in the (shared) BDD + defined as the sum of products, for all BDD paths from the top node to any + terminal node, of the number of minterms on the path by the number of nodes + on the path. The default reordering type is minimization for the number of + BDD nodes. Calling this function with REO_MINIMIZE_WIDTH or REO_MINIMIZE_APL + as the second argument, changes the default minimization option for all the + reorder calls performed afterwards.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ReorderSetMinimizationType( reo_man * p, reo_min_type fMinType ) +{ + if ( fMinType == REO_MINIMIZE_NODES ) + { + p->fMinWidth = 0; + p->fMinApl = 0; + } + else if ( fMinType == REO_MINIMIZE_WIDTH ) + { + p->fMinWidth = 1; + p->fMinApl = 0; + } + else if ( fMinType == REO_MINIMIZE_APL ) + { + p->fMinWidth = 0; + p->fMinApl = 1; + } + else + { + assert( 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Sets the type of remapping performed by the engine.] + + Description [The remapping refers to the way the resulting BDD + is expressed using the elementary variables of the CUDD BDD manager. + Currently, two types possibilities are supported: remapping and no + remapping. Remapping means that the function(s) after reordering + depend on the topmost variables in the manager. No remapping means + that the function(s) after reordering depend on the same variables + as before. Consider the following example. Suppose the initial four + variable function depends on variables 2,4,5, and 9 on the CUDD BDD + manager, which may be found anywhere in the current variable order. + If remapping is set, the function after ordering depends on the + topmost variables in the manager, which may or may not be the same + as the variables 2,4,5, and 9. If no remapping is set, then the + reordered function depend on the same variables 2,4,5, and 9, but + the meaning of each variale has changed according to the new ordering. + The resulting ordering is returned in the array "pOrder" filled out + by the reordering engine in the call to Extra_Reorder(). The default + is no remapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ReorderSetRemapping( reo_man * p, int fRemapUp ) +{ + p->fRemapUp = fRemapUp; +} + +/**Function************************************************************* + + Synopsis [Sets the number of iterations of sifting performed.] + + Description [The default is one iteration. But a higher minimization + quality is desired, it is possible to set the number of iterations + to any number larger than 1. Convergence is often reached after + several iterations, so typically it make no sense to set the number + of iterations higher than 3.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ReorderSetIterations( reo_man * p, int nIters ) +{ + p->nIters = nIters; +} + +/**Function************************************************************* + + Synopsis [Sets the verification mode.] + + Description [Setting the level to 1 results in verifying the results + of variable reordering. Verification is performed by remapping the + resulting functions into the original variable order and comparing + them with the original functions given by the user. Enabling verification + typically leads to 20-30% increase in the total runtime of REO.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ReorderSetVerification( reo_man * p, int fVerify ) +{ + p->fVerify = fVerify; +} + +/**Function************************************************************* + + Synopsis [Sets the verbosity level.] + + Description [Setting the level to 1 results in printing statistics + before and after the reordering.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ReorderSetVerbosity( reo_man * p, int fVerbose ) +{ + p->fVerbose = fVerbose; +} + +/**Function************************************************************* + + Synopsis [Performs reordering of the function.] + + Description [Returns the DD minimized by variable reordering in the REO + engine. Takes the CUDD decision diagram manager (dd) and the function (Func) + represented as a BDD or ADD (MTBDD). If the variable array (pOrder) is not NULL, + returns the resulting variable permutation. The permutation is such that if the resulting + function is permuted by Cudd_(add,bdd)Permute() using pOrder as the permutation + array, the initial function (Func) results. + Several flag set by other interface functions specify reordering options: + - Remappig can be set by Extra_ReorderSetRemapping(). Then the resulting DD after + reordering is remapped into the topmost levels of the DD manager. Otherwise, + the resulting DD after reordering is mapped using the same variables, on which it + originally depended, only (possibly) permuted as a result of reordering. + - Minimization type can be set by Extra_ReorderSetMinimizationType(). Note + that when the BDD is minimized for the total width of the total APL, the number + BDD nodes can increase. The total width is defines as sum total of widths on each + level. The width on one level is defined as the number of distinct BDD nodes + pointed by the nodes situated above the given level. + - The number of iterations of sifting can be set by Extra_ReorderSetIterations(). + The decision diagram returned by this procedure is not referenced.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_Reorder( reo_man * p, DdManager * dd, DdNode * Func, int * pOrder ) +{ + DdNode * FuncRes; + Extra_ReorderArray( p, dd, &Func, &FuncRes, 1, pOrder ); + Cudd_Deref( FuncRes ); + return FuncRes; +} + +/**Function************************************************************* + + Synopsis [Performs reordering of the array of functions.] + + Description [The options are similar to the procedure Extra_Reorder(), except that + the user should also provide storage for the resulting DDs, which are returned + referenced.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ) +{ + reoReorderArray( p, dd, Funcs, FuncsRes, nFuncs, pOrder ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/bdd/reo/reoCore.c b/abc70930/src/bdd/reo/reoCore.c new file mode 100644 index 00000000..3782631c --- /dev/null +++ b/abc70930/src/bdd/reo/reoCore.c @@ -0,0 +1,438 @@ +/**CFile**************************************************************** + + FileName [reoCore.c] + + PackageName [REO: A specialized DD reordering engine.] + + Synopsis [Implementation of the core reordering procedure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 15, 2002.] + + Revision [$Id: reoCore.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "reo.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define CALLOC(type, num) ((type *) calloc((long)(num), (long)sizeof(type))) + +static int reoRecursiveDeref( reo_unit * pUnit ); +static int reoCheckZeroRefs( reo_plane * pPlane ); +static int reoCheckLevels( reo_man * p ); + +double s_AplBefore; +double s_AplAfter; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ) +{ + int Counter, i; + + // set the initial parameters + p->dd = dd; + p->pOrder = pOrder; + p->nTops = nFuncs; + // get the initial number of nodes + p->nNodesBeg = Cudd_SharingSize( Funcs, nFuncs ); + // resize the internal data structures of the manager if necessary + reoResizeStructures( p, ddMax(dd->size,dd->sizeZ), p->nNodesBeg, nFuncs ); + // compute the support + p->pSupp = Extra_VectorSupportArray( dd, Funcs, nFuncs, p->pSupp ); + // get the number of support variables + p->nSupp = 0; + for ( i = 0; i < dd->size; i++ ) + p->nSupp += p->pSupp[i]; + + // if it is the constant function, no need to reorder + if ( p->nSupp == 0 ) + { + for ( i = 0; i < nFuncs; i++ ) + { + FuncsRes[i] = Funcs[i]; Cudd_Ref( FuncsRes[i] ); + } + return; + } + + // create the internal variable maps + // go through variable levels in the manager + Counter = 0; + for ( i = 0; i < dd->size; i++ ) + if ( p->pSupp[ dd->invperm[i] ] ) + { + p->pMapToPlanes[ dd->invperm[i] ] = Counter; + p->pMapToDdVarsOrig[Counter] = dd->invperm[i]; + if ( !p->fRemapUp ) + p->pMapToDdVarsFinal[Counter] = dd->invperm[i]; + else + p->pMapToDdVarsFinal[Counter] = dd->invperm[Counter]; + p->pOrderInt[Counter] = Counter; + Counter++; + } + + // set the initial parameters + p->nUnitsUsed = 0; + p->nNodesCur = 0; + p->fThisIsAdd = 0; + p->Signature++; + // transfer the function from the CUDD package into REO"s internal data structure + for ( i = 0; i < nFuncs; i++ ) + p->pTops[i] = reoTransferNodesToUnits_rec( p, Funcs[i] ); + assert( p->nNodesBeg == p->nNodesCur ); + + if ( !p->fThisIsAdd && p->fMinWidth ) + { + printf( "An important message from the REO reordering engine:\n" ); + printf( "The BDD given to the engine for reordering contains complemented edges.\n" ); + printf( "Currently, such BDDs cannot be reordered for the minimum width.\n" ); + printf( "Therefore, minimization for the number of BDD nodes is performed.\n" ); + fflush( stdout ); + p->fMinApl = 0; + p->fMinWidth = 0; + } + + if ( p->fMinWidth ) + reoProfileWidthStart(p); + else if ( p->fMinApl ) + reoProfileAplStart(p); + else + reoProfileNodesStart(p); + + if ( p->fVerbose ) + { + printf( "INITIAL: " ); + if ( p->fMinWidth ) + reoProfileWidthPrint(p); + else if ( p->fMinApl ) + reoProfileAplPrint(p); + else + reoProfileNodesPrint(p); + } + + /////////////////////////////////////////////////////////////////// + // performs the reordering + p->nSwaps = 0; + p->nNISwaps = 0; + for ( i = 0; i < p->nIters; i++ ) + { + reoReorderSift( p ); + // print statistics after each iteration + if ( p->fVerbose ) + { + printf( "ITER #%d: ", i+1 ); + if ( p->fMinWidth ) + reoProfileWidthPrint(p); + else if ( p->fMinApl ) + reoProfileAplPrint(p); + else + reoProfileNodesPrint(p); + } + // if the cost function did not change, stop iterating + if ( p->fMinWidth ) + { + p->nWidthEnd = p->nWidthCur; + assert( p->nWidthEnd <= p->nWidthBeg ); + if ( p->nWidthEnd == p->nWidthBeg ) + break; + } + else if ( p->fMinApl ) + { + p->nAplEnd = p->nAplCur; + assert( p->nAplEnd <= p->nAplBeg ); + if ( p->nAplEnd == p->nAplBeg ) + break; + } + else + { + p->nNodesEnd = p->nNodesCur; + assert( p->nNodesEnd <= p->nNodesBeg ); + if ( p->nNodesEnd == p->nNodesBeg ) + break; + } + } + assert( reoCheckLevels( p ) ); + /////////////////////////////////////////////////////////////////// + +s_AplBefore = p->nAplBeg; +s_AplAfter = p->nAplEnd; + + // set the initial parameters + p->nRefNodes = 0; + p->nNodesCur = 0; + p->Signature++; + // transfer the BDDs from REO's internal data structure to CUDD + for ( i = 0; i < nFuncs; i++ ) + { + FuncsRes[i] = reoTransferUnitsToNodes_rec( p, p->pTops[i] ); Cudd_Ref( FuncsRes[i] ); + } + // undo the DDs referenced for storing in the cache + for ( i = 0; i < p->nRefNodes; i++ ) + Cudd_RecursiveDeref( dd, p->pRefNodes[i] ); + // verify zero refs of the terminal nodes + for ( i = 0; i < nFuncs; i++ ) + { + assert( reoRecursiveDeref( p->pTops[i] ) ); + } + assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) ); + + // prepare the variable map to return to the user + if ( p->pOrder ) + { + // i is the current level in the planes data structure + // p->pOrderInt[i] is the original level in the planes data structure + // p->pMapToDdVarsOrig[i] is the variable, into which we remap when we construct the BDD from planes + // p->pMapToDdVarsOrig[ p->pOrderInt[i] ] is the original BDD variable corresponding to this level + // Therefore, p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ] + // creates the permutation, which remaps the resulting BDD variable into the original BDD variable + for ( i = 0; i < p->nSupp; i++ ) + p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; + } + + if ( p->fVerify ) + { + int fVerification; + DdNode * FuncRemapped; + int * pOrder; + + if ( p->pOrder == NULL ) + { + pOrder = ALLOC( int, p->nSupp ); + for ( i = 0; i < p->nSupp; i++ ) + pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; + } + else + pOrder = p->pOrder; + + fVerification = 1; + for ( i = 0; i < nFuncs; i++ ) + { + // verify the result + if ( p->fThisIsAdd ) + FuncRemapped = Cudd_addPermute( dd, FuncsRes[i], pOrder ); + else + FuncRemapped = Cudd_bddPermute( dd, FuncsRes[i], pOrder ); + Cudd_Ref( FuncRemapped ); + + if ( FuncRemapped != Funcs[i] ) + { + fVerification = 0; + printf( "REO: Internal verification has failed!\n" ); + fflush( stdout ); + } + Cudd_RecursiveDeref( dd, FuncRemapped ); + } + if ( fVerification ) + printf( "REO: Internal verification is okay!\n" ); + + if ( p->pOrder == NULL ) + free( pOrder ); + } + + // recycle the data structure + for ( i = 0; i <= p->nSupp; i++ ) + reoUnitsRecycleUnitList( p, p->pPlanes + i ); +} + +/**Function************************************************************* + + Synopsis [Resizes the internal manager data structures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void reoResizeStructures( reo_man * p, int nDdVarsMax, int nNodesMax, int nFuncs ) +{ + // resize data structures depending on the number of variables in the DD manager + if ( p->nSuppAlloc == 0 ) + { + p->pSupp = ALLOC( int, nDdVarsMax + 1 ); + p->pOrderInt = ALLOC( int, nDdVarsMax + 1 ); + p->pMapToPlanes = ALLOC( int, nDdVarsMax + 1 ); + p->pMapToDdVarsOrig = ALLOC( int, nDdVarsMax + 1 ); + p->pMapToDdVarsFinal = ALLOC( int, nDdVarsMax + 1 ); + p->pPlanes = CALLOC( reo_plane, nDdVarsMax + 1 ); + p->pVarCosts = ALLOC( double, nDdVarsMax + 1 ); + p->pLevelOrder = ALLOC( int, nDdVarsMax + 1 ); + p->nSuppAlloc = nDdVarsMax + 1; + } + else if ( p->nSuppAlloc < nDdVarsMax ) + { + free( p->pSupp ); + free( p->pOrderInt ); + free( p->pMapToPlanes ); + free( p->pMapToDdVarsOrig ); + free( p->pMapToDdVarsFinal ); + free( p->pPlanes ); + free( p->pVarCosts ); + free( p->pLevelOrder ); + + p->pSupp = ALLOC( int, nDdVarsMax + 1 ); + p->pOrderInt = ALLOC( int, nDdVarsMax + 1 ); + p->pMapToPlanes = ALLOC( int, nDdVarsMax + 1 ); + p->pMapToDdVarsOrig = ALLOC( int, nDdVarsMax + 1 ); + p->pMapToDdVarsFinal = ALLOC( int, nDdVarsMax + 1 ); + p->pPlanes = CALLOC( reo_plane, nDdVarsMax + 1 ); + p->pVarCosts = ALLOC( double, nDdVarsMax + 1 ); + p->pLevelOrder = ALLOC( int, nDdVarsMax + 1 ); + p->nSuppAlloc = nDdVarsMax + 1; + } + + // resize the data structures depending on the number of nodes + if ( p->nRefNodesAlloc == 0 ) + { + p->nNodesMaxAlloc = nNodesMax; + p->nTableSize = 3*nNodesMax + 1; + p->nRefNodesAlloc = 3*nNodesMax + 1; + p->nMemChunksAlloc = (10*nNodesMax + 1)/REO_CHUNK_SIZE + 1; + + p->HTable = CALLOC( reo_hash, p->nTableSize ); + p->pRefNodes = ALLOC( DdNode *, p->nRefNodesAlloc ); + p->pWidthCofs = ALLOC( reo_unit *, p->nRefNodesAlloc ); + p->pMemChunks = ALLOC( reo_unit *, p->nMemChunksAlloc ); + } + else if ( p->nNodesMaxAlloc < nNodesMax ) + { + void * pTemp; + int nMemChunksAllocPrev = p->nMemChunksAlloc; + + p->nNodesMaxAlloc = nNodesMax; + p->nTableSize = 3*nNodesMax + 1; + p->nRefNodesAlloc = 3*nNodesMax + 1; + p->nMemChunksAlloc = (10*nNodesMax + 1)/REO_CHUNK_SIZE + 1; + + free( p->HTable ); + free( p->pRefNodes ); + free( p->pWidthCofs ); + p->HTable = CALLOC( reo_hash, p->nTableSize ); + p->pRefNodes = ALLOC( DdNode *, p->nRefNodesAlloc ); + p->pWidthCofs = ALLOC( reo_unit *, p->nRefNodesAlloc ); + // p->pMemChunks should be reallocated because it contains pointers currently in use + pTemp = ALLOC( reo_unit *, p->nMemChunksAlloc ); + memmove( pTemp, p->pMemChunks, sizeof(reo_unit *) * nMemChunksAllocPrev ); + free( p->pMemChunks ); + p->pMemChunks = pTemp; + } + + // resize the data structures depending on the number of functions + if ( p->nTopsAlloc == 0 ) + { + p->pTops = ALLOC( reo_unit *, nFuncs ); + p->nTopsAlloc = nFuncs; + } + else if ( p->nTopsAlloc < nFuncs ) + { + free( p->pTops ); + p->pTops = ALLOC( reo_unit *, nFuncs ); + p->nTopsAlloc = nFuncs; + } +} + + +/**Function************************************************************* + + Synopsis [Dereferences units the data structure after reordering.] + + Description [This function is only useful for debugging.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int reoRecursiveDeref( reo_unit * pUnit ) +{ + reo_unit * pUnitR; + pUnitR = Unit_Regular(pUnit); + pUnitR->n--; + if ( Unit_IsConstant(pUnitR) ) + return 1; + if ( pUnitR->n == 0 ) + { + reoRecursiveDeref( pUnitR->pE ); + reoRecursiveDeref( pUnitR->pT ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the zero references for the given plane.] + + Description [This function is only useful for debugging.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int reoCheckZeroRefs( reo_plane * pPlane ) +{ + reo_unit * pUnit; + for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) + { + if ( pUnit->n != 0 ) + { + assert( 0 ); + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the zero references for the given plane.] + + Description [This function is only useful for debugging.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int reoCheckLevels( reo_man * p ) +{ + reo_unit * pUnit; + int i; + + for ( i = 0; i < p->nSupp; i++ ) + { + // there are some nodes left on each level + assert( p->pPlanes[i].statsNodes ); + for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) + { + // the level is properly set + assert( pUnit->lev == i ); + } + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/bdd/reo/reoProfile.c b/abc70930/src/bdd/reo/reoProfile.c new file mode 100644 index 00000000..84a0bc19 --- /dev/null +++ b/abc70930/src/bdd/reo/reoProfile.c @@ -0,0 +1,365 @@ +/**CFile**************************************************************** + + FileName [reoProfile.c] + + PackageName [REO: A specialized DD reordering engine.] + + Synopsis [Procudures that compute variables profiles (nodes, width, APL).] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 15, 2002.] + + Revision [$Id: reoProfile.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "reo.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function******************************************************************** + + Synopsis [Start the profile for the BDD nodes.] + + Description [TopRef is the first level, on this the given node counts towards + the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void reoProfileNodesStart( reo_man * p ) +{ + int Total, i; + Total = 0; + for ( i = 0; i <= p->nSupp; i++ ) + { + p->pPlanes[i].statsCost = p->pPlanes[i].statsNodes; + Total += p->pPlanes[i].statsNodes; + } + assert( Total == p->nNodesCur ); + p->nNodesBeg = p->nNodesCur; +} + +/**Function************************************************************* + + Synopsis [Start the profile for the APL.] + + Description [Computes the total path length. The path length is normalized + by dividing it by 2^|supp(f)|. To get the "real" APL, multiply by 2^|supp(f)|. + This procedure assumes that Weight field of all nodes has been set to 0.0 + before the call, except for the weight of the topmost node, which is set to 1.0 + (1.0 is the probability of traversing the topmost node). This procedure + assigns the edge weights. Because of the equal probability of selecting 0 and 1 + assignment at a node, the edge weights are the same for the node. + Instead of storing them, we store the weight of the node, which is the probability + of traversing the node (pUnit->Weight) during the top down evalation of the BDD. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void reoProfileAplStart( reo_man * p ) +{ + reo_unit * pER, * pTR; + reo_unit * pUnit; + double Res, Half; + int i; + + // clean the weights of all nodes + for ( i = 0; i < p->nSupp; i++ ) + for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) + pUnit->Weight = 0.0; + // to assign the node weights (the probability of visiting each node) + // we visit the node after visiting its predecessors + + // set the probability of visits to the top nodes + for ( i = 0; i < p->nTops; i++ ) + Unit_Regular(p->pTops[i])->Weight += 1.0; + + // to compute the path length (the sum of products of edge weight by edge length) + // we visit the nodes in any order (the above order will do) + Res = 0.0; + for ( i = 0; i < p->nSupp; i++ ) + { + p->pPlanes[i].statsCost = 0.0; + for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) + { + pER = Unit_Regular(pUnit->pE); + pTR = Unit_Regular(pUnit->pT); + Half = 0.5 * pUnit->Weight; + pER->Weight += Half; + pTR->Weight += Half; + // add to the path length + p->pPlanes[i].statsCost += pUnit->Weight; + } + Res += p->pPlanes[i].statsCost; + } + p->pPlanes[p->nSupp].statsCost = 0.0; + p->nAplBeg = p->nAplCur = Res; +} + +/**Function******************************************************************** + + Synopsis [Start the profile for the BDD width. Complexity of the algorithm is O(N + n).] + + Description [TopRef is the first level, on which the given node counts towards + the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void reoProfileWidthStart( reo_man * p ) +{ + reo_unit * pUnit; + int * pWidthStart; + int * pWidthStop; + int v; + + // allocate and clean the storage for starting and stopping levels + pWidthStart = ALLOC( int, p->nSupp + 1 ); + pWidthStop = ALLOC( int, p->nSupp + 1 ); + memset( pWidthStart, 0, sizeof(int) * (p->nSupp + 1) ); + memset( pWidthStop, 0, sizeof(int) * (p->nSupp + 1) ); + + // go through the non-constant nodes and set the topmost level of their cofactors + for ( v = 0; v <= p->nSupp; v++ ) + for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) + { + pUnit->TopRef = REO_TOPREF_UNDEF; + pUnit->Sign = 0; + } + + // add the topmost level of the width profile + for ( v = 0; v < p->nTops; v++ ) + { + pUnit = Unit_Regular(p->pTops[v]); + if ( pUnit->TopRef == REO_TOPREF_UNDEF ) + { + // set the starting level + pUnit->TopRef = 0; + pWidthStart[pUnit->TopRef]++; + // set the stopping level + if ( pUnit->lev != REO_CONST_LEVEL ) + pWidthStop[pUnit->lev+1]++; + } + } + + for ( v = 0; v < p->nSupp; v++ ) + for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) + { + if ( pUnit->pE->TopRef == REO_TOPREF_UNDEF ) + { + // set the starting level + pUnit->pE->TopRef = pUnit->lev + 1; + pWidthStart[pUnit->pE->TopRef]++; + // set the stopping level + if ( pUnit->pE->lev != REO_CONST_LEVEL ) + pWidthStop[pUnit->pE->lev+1]++; + } + if ( pUnit->pT->TopRef == REO_TOPREF_UNDEF ) + { + // set the starting level + pUnit->pT->TopRef = pUnit->lev + 1; + pWidthStart[pUnit->pT->TopRef]++; + // set the stopping level + if ( pUnit->pT->lev != REO_CONST_LEVEL ) + pWidthStop[pUnit->pT->lev+1]++; + } + } + + // verify the top reference + for ( v = 0; v < p->nSupp; v++ ) + reoProfileWidthVerifyLevel( p->pPlanes + v, v ); + + // derive the profile + p->nWidthCur = 0; + for ( v = 0; v <= p->nSupp; v++ ) + { + if ( v == 0 ) + p->pPlanes[v].statsWidth = pWidthStart[v] - pWidthStop[v]; + else + p->pPlanes[v].statsWidth = p->pPlanes[v-1].statsWidth + pWidthStart[v] - pWidthStop[v]; + p->pPlanes[v].statsCost = p->pPlanes[v].statsWidth; + p->nWidthCur += p->pPlanes[v].statsWidth; +// printf( "Level %2d: Width = %5d. Correct = %d.\n", v, Temp, p->pPlanes[v].statsWidth ); + } + p->nWidthBeg = p->nWidthCur; + free( pWidthStart ); + free( pWidthStop ); +} + +/**Function******************************************************************** + + Synopsis [Start the profile for the BDD width. Complexity of the algorithm is O(N * n).] + + Description [TopRef is the first level, on which the given node counts towards + the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void reoProfileWidthStart2( reo_man * p ) +{ + reo_unit * pUnit; + int i, v; + + // clean the profile + for ( i = 0; i <= p->nSupp; i++ ) + p->pPlanes[i].statsWidth = 0; + + // clean the node structures + for ( v = 0; v <= p->nSupp; v++ ) + for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) + { + pUnit->TopRef = REO_TOPREF_UNDEF; + pUnit->Sign = 0; + } + + // set the topref to the topmost nodes + for ( i = 0; i < p->nTops; i++ ) + Unit_Regular(p->pTops[i])->TopRef = 0; + + // go through the non-constant nodes and set the topmost level of their cofactors + for ( i = 0; i < p->nSupp; i++ ) + for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) + { + if ( pUnit->pE->TopRef > i+1 ) + pUnit->pE->TopRef = i+1; + if ( pUnit->pT->TopRef > i+1 ) + pUnit->pT->TopRef = i+1; + } + + // verify the top reference + for ( i = 0; i < p->nSupp; i++ ) + reoProfileWidthVerifyLevel( p->pPlanes + i, i ); + + // compute the profile for the internal nodes + for ( i = 0; i < p->nSupp; i++ ) + for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) + for ( v = pUnit->TopRef; v <= pUnit->lev; v++ ) + p->pPlanes[v].statsWidth++; + + // compute the profile for the constant nodes + for ( pUnit = p->pPlanes[p->nSupp].pHead; pUnit; pUnit = pUnit->Next ) + for ( v = pUnit->TopRef; v <= p->nSupp; v++ ) + p->pPlanes[v].statsWidth++; + + // get the width cost + p->nWidthCur = 0; + for ( i = 0; i <= p->nSupp; i++ ) + { + p->pPlanes[i].statsCost = p->pPlanes[i].statsWidth; + p->nWidthCur += p->pPlanes[i].statsWidth; + } + p->nWidthBeg = p->nWidthCur; +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void reoProfileNodesPrint( reo_man * p ) +{ + printf( "NODES: Total = %6d. Average = %6.2f.\n", p->nNodesCur, p->nNodesCur / (float)p->nSupp ); +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void reoProfileAplPrint( reo_man * p ) +{ + printf( "APL: Total = %8.2f. Average =%6.2f.\n", p->nAplCur, p->nAplCur / (float)p->nSupp ); +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void reoProfileWidthPrint( reo_man * p ) +{ + int WidthMax; + int TotalWidth; + int i; + + WidthMax = 0; + TotalWidth = 0; + for ( i = 0; i <= p->nSupp; i++ ) + { +// printf( "Level = %2d. Width = %3d.\n", i, p->pProfile[i] ); + if ( WidthMax < p->pPlanes[i].statsWidth ) + WidthMax = p->pPlanes[i].statsWidth; + TotalWidth += p->pPlanes[i].statsWidth; + } + assert( p->nWidthCur == TotalWidth ); + printf( "WIDTH: " ); + printf( "Maximum = %5d. ", WidthMax ); + printf( "Total = %7d. ", p->nWidthCur ); + printf( "Average = %6.2f.\n", TotalWidth / (float)p->nSupp ); +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void reoProfileWidthVerifyLevel( reo_plane * pPlane, int Level ) +{ + reo_unit * pUnit; + for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) + { + assert( pUnit->TopRef <= Level ); + assert( pUnit->pE->TopRef <= Level + 1 ); + assert( pUnit->pT->TopRef <= Level + 1 ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/bdd/reo/reoSift.c b/abc70930/src/bdd/reo/reoSift.c new file mode 100644 index 00000000..93d82f08 --- /dev/null +++ b/abc70930/src/bdd/reo/reoSift.c @@ -0,0 +1,341 @@ +/**CFile**************************************************************** + + FileName [reoSift.c] + + PackageName [REO: A specialized DD reordering engine.] + + Synopsis [Implementation of the sifting algorihtm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 15, 2002.] + + Revision [$Id: reoSift.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "reo.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Implements the variable sifting algorithm.] + + Description [Performs a sequence of adjacent variable swaps known as "sifting". + Uses the cost functions determined by the flag.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void reoReorderSift( reo_man * p ) +{ + double CostCurrent; // the cost of the current permutation + double CostLimit; // the maximum increase in cost that can be tolerated + double CostBest; // the best cost + int BestQ; // the best position + int VarCurrent; // the current variable to move + int q; // denotes the current position of the variable + int c; // performs the loops over variables until all of them are sifted + int v; // used for other purposes + + assert( p->nSupp > 0 ); + + // set the current cost depending on the minimization criteria + if ( p->fMinWidth ) + CostCurrent = p->nWidthCur; + else if ( p->fMinApl ) + CostCurrent = p->nAplCur; + else + CostCurrent = p->nNodesCur; + + // find the upper bound on tbe cost growth + CostLimit = 1 + (int)(REO_REORDER_LIMIT * CostCurrent); + + // perform sifting for each of p->nSupp variables + for ( c = 0; c < p->nSupp; c++ ) + { + // select the current variable to be the one with the largest number of nodes that is not sifted yet + VarCurrent = -1; + CostBest = -1.0; + for ( v = 0; v < p->nSupp; v++ ) + { + p->pVarCosts[v] = REO_HIGH_VALUE; + if ( !p->pPlanes[v].fSifted ) + { +// VarCurrent = v; +// if ( CostBest < p->pPlanes[v].statsCost ) + if ( CostBest < p->pPlanes[v].statsNodes ) + { +// CostBest = p->pPlanes[v].statsCost; + CostBest = p->pPlanes[v].statsNodes; + VarCurrent = v; + } + + } + } + assert( VarCurrent != -1 ); + // mark this variable as sifted + p->pPlanes[VarCurrent].fSifted = 1; + + // set the current value + p->pVarCosts[VarCurrent] = CostCurrent; + + // set the best cost + CostBest = CostCurrent; + BestQ = VarCurrent; + + // determine which way to move the variable first (up or down) + // the rationale is that if we move the shorter way first + // it is more likely that the best position will be found on the longer way + // and the reverse movement (to take the best position) will be faster + if ( VarCurrent < p->nSupp/2 ) // move up first, then down + { + // set the total cost on all levels above the current level + p->pPlanes[0].statsCostAbove = 0; + for ( v = 1; v <= VarCurrent; v++ ) + p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost; + // set the total cost on all levels below the current level + p->pPlanes[p->nSupp].statsCostBelow = 0; + for ( v = p->nSupp - 1; v >= VarCurrent; v-- ) + p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost; + + assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + + p->pPlanes[VarCurrent].statsCost + + p->pPlanes[VarCurrent].statsCostBelow ); + + // move up + for ( q = VarCurrent-1; q >= 0; q-- ) + { + CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 ); + // now q points to the position of this var in the order + p->pVarCosts[q] = CostCurrent; + // update the lower bound (assuming that for level q+1 it is set correctly) + p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost; + // check the upper bound + if ( CostCurrent >= CostLimit ) + break; + // check the lower bound + if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest ) + break; + // update the best cost + if ( CostBest > CostCurrent ) + { + CostBest = CostCurrent; + BestQ = q; + // adjust node limit + CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); + } + + // when we are reordering for width or APL, it may happen that + // the number of nodes has grown above certain limit, + // in which case we have to resize the data structures + if ( p->fMinWidth || p->fMinApl ) + { + if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) + { +// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); + reoResizeStructures( p, 0, p->nNodesCur, 0 ); + } + } + } + // fix the plane index + if ( q == -1 ) + q++; + // now p points to the position of this var in the order + + // move down + for ( ; q < p->nSupp-1; ) + { + CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); + q++; // change q to point to the position of this var in the order + // sanity check: the number of nodes on the back pass should be the same + if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON ) + printf("reoReorderSift(): Error! On the backward move, the costs are different.\n"); + p->pVarCosts[q] = CostCurrent; + // update the lower bound (assuming that for level q-1 it is set correctly) + p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost; + // check the bounds only if the variable already reached its previous position + if ( q >= BestQ ) + { + // check the upper bound + if ( CostCurrent >= CostLimit ) + break; + // check the lower bound + if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest ) + break; + } + // update the best cost + if ( CostBest >= CostCurrent ) + { + CostBest = CostCurrent; + BestQ = q; + // adjust node limit + CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); + } + + // when we are reordering for width or APL, it may happen that + // the number of nodes has grown above certain limit, + // in which case we have to resize the data structures + if ( p->fMinWidth || p->fMinApl ) + { + if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) + { +// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); + reoResizeStructures( p, 0, p->nNodesCur, 0 ); + } + } + } + // move the variable up from the given position (q) to the best position (BestQ) + assert( q >= BestQ ); + for ( ; q > BestQ; q-- ) + { + CostCurrent -= reoReorderSwapAdjacentVars( p, q-1, 1 ); + // sanity check: the number of nodes on the back pass should be the same + if ( fabs( p->pVarCosts[q-1] - CostCurrent ) > REO_COST_EPSILON ) + { + printf("reoReorderSift(): Error! On the return move, the costs are different.\n" ); + fflush(stdout); + } + } + } + else // move down first, then up + { + // set the current number of nodes on all levels above the given level + p->pPlanes[0].statsCostAbove = 0; + for ( v = 1; v <= VarCurrent; v++ ) + p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost; + // set the current number of nodes on all levels below the given level + p->pPlanes[p->nSupp].statsCostBelow = 0; + for ( v = p->nSupp - 1; v >= VarCurrent; v-- ) + p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost; + + assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + + p->pPlanes[VarCurrent].statsCost + + p->pPlanes[VarCurrent].statsCostBelow ); + + // move down + for ( q = VarCurrent; q < p->nSupp-1; ) + { + CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); + q++; // change q to point to the position of this var in the order + p->pVarCosts[q] = CostCurrent; + // update the lower bound (assuming that for level q-1 it is set correctly) + p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost; + // check the upper bound + if ( CostCurrent >= CostLimit ) + break; + // check the lower bound + if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest ) + break; + // update the best cost + if ( CostBest > CostCurrent ) + { + CostBest = CostCurrent; + BestQ = q; + // adjust node limit + CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); + } + + // when we are reordering for width or APL, it may happen that + // the number of nodes has grown above certain limit, + // in which case we have to resize the data structures + if ( p->fMinWidth || p->fMinApl ) + { + if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) + { +// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); + reoResizeStructures( p, 0, p->nNodesCur, 0 ); + } + } + } + + // move up + for ( --q; q >= 0; q-- ) + { + CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 ); + // now q points to the position of this var in the order + // sanity check: the number of nodes on the back pass should be the same + if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON ) + printf("reoReorderSift(): Error! On the backward move, the costs are different.\n"); + p->pVarCosts[q] = CostCurrent; + // update the lower bound (assuming that for level q+1 it is set correctly) + p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost; + // check the bounds only if the variable already reached its previous position + if ( q <= BestQ ) + { + // check the upper bound + if ( CostCurrent >= CostLimit ) + break; + // check the lower bound + if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest ) + break; + } + // update the best cost + if ( CostBest >= CostCurrent ) + { + CostBest = CostCurrent; + BestQ = q; + // adjust node limit + CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); + } + + // when we are reordering for width or APL, it may happen that + // the number of nodes has grown above certain limit, + // in which case we have to resize the data structures + if ( p->fMinWidth || p->fMinApl ) + { + if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) + { +// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); + reoResizeStructures( p, 0, p->nNodesCur, 0 ); + } + } + } + // fix the plane index + if ( q == -1 ) + q++; + // now q points to the position of this var in the order + // move the variable down from the given position (q) to the best position (BestQ) + assert( q <= BestQ ); + for ( ; q < BestQ; q++ ) + { + CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); + // sanity check: the number of nodes on the back pass should be the same + if ( fabs( p->pVarCosts[q+1] - CostCurrent ) > REO_COST_EPSILON ) + { + printf("reoReorderSift(): Error! On the return move, the costs are different.\n" ); + fflush(stdout); + } + } + } + assert( fabs( CostBest - CostCurrent ) < REO_COST_EPSILON ); + + // update the cost + if ( p->fMinWidth ) + p->nWidthCur = (int)CostBest; + else if ( p->fMinApl ) + p->nAplCur = CostCurrent; + else + p->nNodesCur = (int)CostBest; + } + + // remove the sifted attributes if any + for ( v = 0; v < p->nSupp; v++ ) + p->pPlanes[v].fSifted = 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/bdd/reo/reoSwap.c b/abc70930/src/bdd/reo/reoSwap.c new file mode 100644 index 00000000..4afa650c --- /dev/null +++ b/abc70930/src/bdd/reo/reoSwap.c @@ -0,0 +1,898 @@ +/**CFile**************************************************************** + + FileName [reoSwap.c] + + PackageName [REO: A specialized DD reordering engine.] + + Synopsis [Implementation of the two-variable swap.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 15, 2002.] + + Revision [$Id: reoSwap.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "reo.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define AddToLinkedList( ppList, pLink ) (((pLink)->Next = *(ppList)), (*(ppList) = (pLink))) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [Takes the level (lev0) of the plane, which should be swapped + with the next plane. Returns the gain using the current cost function.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) +{ + // the levels in the decision diagram + int lev1 = lev0 + 1, lev2 = lev0 + 2; + // the new nodes on lev0 + reo_unit * pLoop, * pUnit; + // the new nodes on lev1 + reo_unit * pNewPlane20, * pNewPlane21, * pNewPlane20R; + reo_unit * pUnitE, * pUnitER, * pUnitT; + // the nodes below lev1 + reo_unit * pNew1E, * pNew1T, * pNew2E, * pNew2T; + reo_unit * pNew1ER, * pNew2ER; + // the old linked lists + reo_unit * pListOld0 = p->pPlanes[lev0].pHead; + reo_unit * pListOld1 = p->pPlanes[lev1].pHead; + // working planes and one more temporary plane + reo_unit * pListNew0 = NULL, ** ppListNew0 = &pListNew0; + reo_unit * pListNew1 = NULL, ** ppListNew1 = &pListNew1; + reo_unit * pListTemp = NULL, ** ppListTemp = &pListTemp; + // various integer variables + int fComp, fCompT, fFound, nWidthCofs, HKey, fInteract, temp, c; + // statistical variables + int nNodesUpMovedDown = 0; + int nNodesDownMovedUp = 0; + int nNodesUnrefRemoved = 0; + int nNodesUnrefAdded = 0; + int nWidthReduction = 0; + double AplWeightTotalLev0; + double AplWeightTotalLev1; + double AplWeightHalf; + double AplWeightPrev; + double AplWeightAfter; + double nCostGain; + + // set the old lists + assert( lev0 >= 0 && lev1 < p->nSupp ); + pListOld0 = p->pPlanes[lev0].pHead; + pListOld1 = p->pPlanes[lev1].pHead; + + // make sure the planes have nodes + assert( p->pPlanes[lev0].statsNodes && p->pPlanes[lev1].statsNodes ); + assert( pListOld0 && pListOld1 ); + + if ( p->fMinWidth ) + { + // verify that the width parameters are set correctly + reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 ); + reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 ); + // start the storage for cofactors + nWidthCofs = 0; + } + else if ( p->fMinApl ) + { + AplWeightPrev = p->nAplCur; + AplWeightAfter = p->nAplCur; + AplWeightTotalLev0 = 0.0; + AplWeightTotalLev1 = 0.0; + } + + // check if the planes interact + fInteract = 0; // assume that they do not interact + for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) + { + if ( pUnit->pT->lev == lev1 || Unit_Regular(pUnit->pE)->lev == lev1 ) + { + fInteract = 1; + break; + } + // change the level now, this is done for efficiency reasons + pUnit->lev = lev1; + } + + // set the new signature for hashing + p->nSwaps++; + if ( !fInteract ) +// if ( 0 ) + { + // perform the swap without interaction + p->nNISwaps++; + + // change the levels + if ( p->fMinWidth ) + { + // go through the current lower level, which will become upper + for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next ) + { + pUnit->lev = lev0; + + pUnitER = Unit_Regular(pUnit->pE); + if ( pUnitER->TopRef > lev0 ) + { + if ( pUnitER->Sign != p->nSwaps ) + { + if ( pUnitER->TopRef == lev2 ) + { + pUnitER->TopRef = lev1; + nWidthReduction--; + } + else + { + assert( pUnitER->TopRef == lev1 ); + } + pUnitER->Sign = p->nSwaps; + } + } + + pUnitT = pUnit->pT; + if ( pUnitT->TopRef > lev0 ) + { + if ( pUnitT->Sign != p->nSwaps ) + { + if ( pUnitT->TopRef == lev2 ) + { + pUnitT->TopRef = lev1; + nWidthReduction--; + } + else + { + assert( pUnitT->TopRef == lev1 ); + } + pUnitT->Sign = p->nSwaps; + } + } + + } + + // go through the current upper level, which will become lower + for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) + { + pUnit->lev = lev1; + + pUnitER = Unit_Regular(pUnit->pE); + if ( pUnitER->TopRef > lev0 ) + { + if ( pUnitER->Sign != p->nSwaps ) + { + assert( pUnitER->TopRef == lev1 ); + pUnitER->TopRef = lev2; + pUnitER->Sign = p->nSwaps; + nWidthReduction++; + } + } + + pUnitT = pUnit->pT; + if ( pUnitT->TopRef > lev0 ) + { + if ( pUnitT->Sign != p->nSwaps ) + { + assert( pUnitT->TopRef == lev1 ); + pUnitT->TopRef = lev2; + pUnitT->Sign = p->nSwaps; + nWidthReduction++; + } + } + } + } + else + { +// for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) +// pUnit->lev = lev1; + for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next ) + pUnit->lev = lev0; + } + + // set the new linked lists, which will be attached to the planes + pListNew0 = pListOld1; + pListNew1 = pListOld0; + + if ( p->fMinApl ) + { + AplWeightTotalLev0 = p->pPlanes[lev1].statsCost; + AplWeightTotalLev1 = p->pPlanes[lev0].statsCost; + } + + // set the changes in terms of nodes + nNodesUpMovedDown = p->pPlanes[lev0].statsNodes; + nNodesDownMovedUp = p->pPlanes[lev1].statsNodes; + goto finish; + } + p->Signature++; + + + // two-variable swap is done in three easy steps + // previously I thought that steps (1) and (2) can be merged into one step + // now it is clear that this cannot be done without changing a lot of other stuff... + + // (1) walk through the upper level, find units without cofactors in the lower level + // and move them to the new lower level (while adding to the cache) + // (2) walk through the uppoer level, and tranform all the remaning nodes + // while employing cache for the new lower level + // (3) walk through the old lower level, find those nodes whose ref counters are not zero, + // and move them to the new uppoer level, free other nodes + + // (1) walk through the upper level, find units without cofactors in the lower level + // and move them to the new lower level (while adding to the cache) + for ( pLoop = pListOld0; pLoop; ) + { + pUnit = pLoop; + pLoop = pLoop->Next; + + pUnitE = pUnit->pE; + pUnitER = Unit_Regular(pUnitE); + pUnitT = pUnit->pT; + + if ( pUnitER->lev != lev1 && pUnitT->lev != lev1 ) + { + // before after + // + // + // 0 / \ 1 + // / \ + // / \ + // / \ + // / \ 0 / \ 1 + // / \ / \ + // / \ / \ + // F0 F1 F0 F1 + + // move to plane-2-new + // nothing changes in the process (cofactors, ref counter, APL weight) + pUnit->lev = lev1; + AddToLinkedList( ppListNew1, pUnit ); + if ( p->fMinApl ) + AplWeightTotalLev1 += pUnit->Weight; + + // add to cache - find the cell with different signature (not the current one!) + for ( HKey = hashKey3(p->Signature, pUnitE, pUnitT, p->nTableSize); + p->HTable[HKey].Sign == p->Signature; + HKey = (HKey+1) % p->nTableSize ); + assert( p->HTable[HKey].Sign != p->Signature ); + p->HTable[HKey].Sign = p->Signature; + p->HTable[HKey].Arg1 = pUnitE; + p->HTable[HKey].Arg2 = pUnitT; + p->HTable[HKey].Arg3 = pUnit; + + nNodesUpMovedDown++; + + if ( p->fMinWidth ) + { + // update the cofactors's top ref + if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels + { + assert( pUnitER->TopRef == lev1 ); + pUnitER->TopRefNew = lev2; + if ( pUnitER->Sign != p->nSwaps ) + { + pUnitER->Sign = p->nSwaps; // set the current signature + p->pWidthCofs[ nWidthCofs++ ] = pUnitER; + } + } + if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels + { + assert( pUnitT->TopRef == lev1 ); + pUnitT->TopRefNew = lev2; + if ( pUnitT->Sign != p->nSwaps ) + { + pUnitT->Sign = p->nSwaps; // set the current signature + p->pWidthCofs[ nWidthCofs++ ] = pUnitT; + } + } + } + } + else + { + // add to the temporary plane + AddToLinkedList( ppListTemp, pUnit ); + } + } + + + // (2) walk through the uppoer level, and tranform all the remaning nodes + // while employing cache for the new lower level + for ( pLoop = pListTemp; pLoop; ) + { + pUnit = pLoop; + pLoop = pLoop->Next; + + pUnitE = pUnit->pE; + pUnitER = Unit_Regular(pUnitE); + pUnitT = pUnit->pT; + fComp = (int)(pUnitER != pUnitE); + + // count the amount of weight to reduce the APL of the children of this node + if ( p->fMinApl ) + AplWeightHalf = 0.5 * pUnit->Weight; + + // determine what situation is this + if ( pUnitER->lev == lev1 && pUnitT->lev == lev1 ) + { + if ( fComp == 0 ) + { + // before after + // + // + // 0 / \ 1 0 / \ 1 + // / \ / \ + // / \ / \ + // + // 0 / \ 1 0 / \ 1 0 / \ 1 0 / \ 1 + // / \ / \ / \ / \ + // / \ / \ / \ / \ + // F0 F1 F2 F3 F0 F2 F1 F3 + // pNew1E pNew1T pNew2E pNew2T + // + pNew1E = pUnitE->pE; // F0 + pNew1T = pUnitT->pE; // F2 + + pNew2E = pUnitE->pT; // F1 + pNew2T = pUnitT->pT; // F3 + } + else + { + // before after + // + // + // 0 . \ 1 0 / \ 1 + // . \ / \ + // . \ / \ + // + // 0 / \ 1 0 / \ 1 0 . \ 1 0 . \ 1 + // / \ / \ . \ . \ + // / \ / \ . \ . \ + // F0 F1 F2 F3 F0 F2 F1 F3 + // pNew1E pNew1T pNew2E pNew2T + // + pNew1E = Unit_Not(pUnitER->pE); // F0 + pNew1T = pUnitT->pE; // F2 + + pNew2E = Unit_Not(pUnitER->pT); // F1 + pNew2T = pUnitT->pT; // F3 + } + // subtract ref counters - on the level P2 + pUnitER->n--; + pUnitT->n--; + + // mark the change in the APL weights + if ( p->fMinApl ) + { + pUnitER->Weight -= AplWeightHalf; + pUnitT->Weight -= AplWeightHalf; + AplWeightAfter -= pUnit->Weight; + } + } + else if ( pUnitER->lev == lev1 ) + { + if ( fComp == 0 ) + { + // before after + // + // + // 0 / \ 1 0 / \ 1 + // / \ / \ + // / \ / \ + // \ + // 0 / \ 1 \ 0 / \ 1 0 / \ 1 + // / \ \ / \ / \ + // / \ \ / \ / \ + // F0 F1 F3 F0 F3 F1 F3 + // pNew1E pNew1T pNew2E pNew2T + // + pNew1E = pUnitER->pE; // F0 + pNew1T = pUnitT; // F3 + + pNew2E = pUnitER->pT; // F1 + pNew2T = pUnitT; // F3 + } + else + { + // before after + // + // + // 0 . \ 1 0 / \ 1 + // . \ / \ + // . \ / \ + // \ + // 0 / \ 1 \ 0 . \ 1 0 . \ 1 + // / \ \ . \ . \ + // / \ \ . \ . \ + // F0 F1 F3 F0 F3 F1 F3 + // pNew1E pNew1T pNew2E pNew2T + // + pNew1E = Unit_Not(pUnitER->pE); // F0 + pNew1T = pUnitT; // F3 + + pNew2E = Unit_Not(pUnitER->pT); // F1 + pNew2T = pUnitT; // F3 + } + // subtract ref counter - on the level P2 + pUnitER->n--; + // subtract ref counter - on other levels + pUnitT->n--; /// + + // mark the change in the APL weights + if ( p->fMinApl ) + { + pUnitER->Weight -= AplWeightHalf; + AplWeightAfter -= AplWeightHalf; + } + } + else if ( pUnitT->lev == lev1 ) + { + // before after + // + // + // 0 / \ 1 0 / \ 1 + // / \ / \ + // / \ / \ + // / + // / 0 / \ 1 0 / \ 1 0 / \ 1 + // / / \ / \ / \ + // / / \ / \ / \ + // F0 F2 F3 F0 F2 F0 F3 + // pNew1E pNew1T pNew2E pNew2T + // + pNew1E = pUnitE; // F0 + pNew1T = pUnitT->pE; // F2 + + pNew2E = pUnitE; // F0 + pNew2T = pUnitT->pT; // F3 + + // subtract incoming edge counter - on the level P2 + pUnitT->n--; + // subtract ref counter - on other levels + pUnitER->n--; /// + + // mark the change in the APL weights + if ( p->fMinApl ) + { + pUnitT->Weight -= AplWeightHalf; + AplWeightAfter -= AplWeightHalf; + } + } + else + { + assert( 0 ); // should never happen + } + + + // consider all the cases except the last one + if ( pNew1E == pNew1T ) + { + pNewPlane20 = pNew1T; + + if ( p->fMinWidth ) + { + // update the cofactors's top ref + if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels + { + pNew1T->TopRefNew = lev1; + if ( pNew1T->Sign != p->nSwaps ) + { + pNew1T->Sign = p->nSwaps; // set the current signature + p->pWidthCofs[ nWidthCofs++ ] = pNew1T; + } + } + } + } + else + { + // pNew1T can be complemented + fCompT = Cudd_IsComplement(pNew1T); + if ( fCompT ) + { + pNew1E = Unit_Not(pNew1E); + pNew1T = Unit_Not(pNew1T); + } + + // check the hash-table + fFound = 0; + for ( HKey = hashKey3(p->Signature, pNew1E, pNew1T, p->nTableSize); + p->HTable[HKey].Sign == p->Signature; + HKey = (HKey+1) % p->nTableSize ) + if ( p->HTable[HKey].Arg1 == pNew1E && p->HTable[HKey].Arg2 == pNew1T ) + { // the entry is present + // assign this entry + pNewPlane20 = p->HTable[HKey].Arg3; + assert( pNewPlane20->lev == lev1 ); + fFound = 1; + p->HashSuccess++; + break; + } + + if ( !fFound ) + { // create the new entry + pNewPlane20 = reoUnitsGetNextUnit( p ); // increments the unit counter + pNewPlane20->pE = pNew1E; + pNewPlane20->pT = pNew1T; + pNewPlane20->n = 0; // ref will be added later + pNewPlane20->lev = lev1; + if ( p->fMinWidth ) + { + pNewPlane20->TopRef = lev1; + pNewPlane20->Sign = 0; + } + // set the weight of this node + if ( p->fMinApl ) + pNewPlane20->Weight = 0.0; + + // increment ref counters of children + pNew1ER = Unit_Regular(pNew1E); + pNew1ER->n++; // + pNew1T->n++; // + + // insert into the data structure + AddToLinkedList( ppListNew1, pNewPlane20 ); + + // add this entry to cache + assert( p->HTable[HKey].Sign != p->Signature ); + p->HTable[HKey].Sign = p->Signature; + p->HTable[HKey].Arg1 = pNew1E; + p->HTable[HKey].Arg2 = pNew1T; + p->HTable[HKey].Arg3 = pNewPlane20; + + nNodesUnrefAdded++; + + if ( p->fMinWidth ) + { + // update the cofactors's top ref + if ( pNew1ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels + { + if ( pNew1ER->Sign != p->nSwaps ) + { + pNew1ER->TopRefNew = lev2; + if ( pNew1ER->Sign != p->nSwaps ) + { + pNew1ER->Sign = p->nSwaps; // set the current signature + p->pWidthCofs[ nWidthCofs++ ] = pNew1ER; + } + } + // otherwise the level is already set correctly + else + { + assert( pNew1ER->TopRefNew == lev1 || pNew1ER->TopRefNew == lev2 ); + } + } + // update the cofactors's top ref + if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels + { + if ( pNew1T->Sign != p->nSwaps ) + { + pNew1T->TopRefNew = lev2; + if ( pNew1T->Sign != p->nSwaps ) + { + pNew1T->Sign = p->nSwaps; // set the current signature + p->pWidthCofs[ nWidthCofs++ ] = pNew1T; + } + } + // otherwise the level is already set correctly + else + { + assert( pNew1T->TopRefNew == lev1 || pNew1T->TopRefNew == lev2 ); + } + } + } + } + + if ( p->fMinApl ) + { + // increment the weight of this node + pNewPlane20->Weight += AplWeightHalf; + // mark the change in the APL weight + AplWeightAfter += AplWeightHalf; + // update the total weight of this level + AplWeightTotalLev1 += AplWeightHalf; + } + + if ( fCompT ) + pNewPlane20 = Unit_Not(pNewPlane20); + } + + if ( pNew2E == pNew2T ) + { + pNewPlane21 = pNew2T; + + if ( p->fMinWidth ) + { + // update the cofactors's top ref + if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels + { + pNew2T->TopRefNew = lev1; + if ( pNew2T->Sign != p->nSwaps ) + { + pNew2T->Sign = p->nSwaps; // set the current signature + p->pWidthCofs[ nWidthCofs++ ] = pNew2T; + } + } + } + } + else + { + assert( !Cudd_IsComplement(pNew2T) ); + + // check the hash-table + fFound = 0; + for ( HKey = hashKey3(p->Signature, pNew2E, pNew2T, p->nTableSize); + p->HTable[HKey].Sign == p->Signature; + HKey = (HKey+1) % p->nTableSize ) + if ( p->HTable[HKey].Arg1 == pNew2E && p->HTable[HKey].Arg2 == pNew2T ) + { // the entry is present + // assign this entry + pNewPlane21 = p->HTable[HKey].Arg3; + assert( pNewPlane21->lev == lev1 ); + fFound = 1; + p->HashSuccess++; + break; + } + + if ( !fFound ) + { // create the new entry + pNewPlane21 = reoUnitsGetNextUnit( p ); // increments the unit counter + pNewPlane21->pE = pNew2E; + pNewPlane21->pT = pNew2T; + pNewPlane21->n = 0; // ref will be added later + pNewPlane21->lev = lev1; + if ( p->fMinWidth ) + { + pNewPlane21->TopRef = lev1; + pNewPlane21->Sign = 0; + } + // set the weight of this node + if ( p->fMinApl ) + pNewPlane21->Weight = 0.0; + + // increment ref counters of children + pNew2ER = Unit_Regular(pNew2E); + pNew2ER->n++; // + pNew2T->n++; // + + // insert into the data structure +// reoUnitsAddUnitToPlane( &P2new, pNewPlane21 ); + AddToLinkedList( ppListNew1, pNewPlane21 ); + + // add this entry to cache + assert( p->HTable[HKey].Sign != p->Signature ); + p->HTable[HKey].Sign = p->Signature; + p->HTable[HKey].Arg1 = pNew2E; + p->HTable[HKey].Arg2 = pNew2T; + p->HTable[HKey].Arg3 = pNewPlane21; + + nNodesUnrefAdded++; + + + if ( p->fMinWidth ) + { + // update the cofactors's top ref + if ( pNew2ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels + { + if ( pNew2ER->Sign != p->nSwaps ) + { + pNew2ER->TopRefNew = lev2; + if ( pNew2ER->Sign != p->nSwaps ) + { + pNew2ER->Sign = p->nSwaps; // set the current signature + p->pWidthCofs[ nWidthCofs++ ] = pNew2ER; + } + } + // otherwise the level is already set correctly + else + { + assert( pNew2ER->TopRefNew == lev1 || pNew2ER->TopRefNew == lev2 ); + } + } + // update the cofactors's top ref + if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels + { + if ( pNew2T->Sign != p->nSwaps ) + { + pNew2T->TopRefNew = lev2; + if ( pNew2T->Sign != p->nSwaps ) + { + pNew2T->Sign = p->nSwaps; // set the current signature + p->pWidthCofs[ nWidthCofs++ ] = pNew2T; + } + } + // otherwise the level is already set correctly + else + { + assert( pNew2T->TopRefNew == lev1 || pNew2T->TopRefNew == lev2 ); + } + } + } + } + + if ( p->fMinApl ) + { + // increment the weight of this node + pNewPlane21->Weight += AplWeightHalf; + // mark the change in the APL weight + AplWeightAfter += AplWeightHalf; + // update the total weight of this level + AplWeightTotalLev1 += AplWeightHalf; + } + } + // in all cases, the node will be added to the plane-1 + // this should be the same node (pUnit) as was originally there + // because it is referenced by the above nodes + + assert( !Cudd_IsComplement(pNewPlane21) ); + // should be the case; otherwise reordering is not a local operation + + pUnit->pE = pNewPlane20; + pUnit->pT = pNewPlane21; + assert( pUnit->lev == lev0 ); + // reference counter remains the same; the APL weight remains the same + + // increment ref counters of children + pNewPlane20R = Unit_Regular(pNewPlane20); + pNewPlane20R->n++; /// + pNewPlane21->n++; /// + + // insert into the data structure + AddToLinkedList( ppListNew0, pUnit ); + if ( p->fMinApl ) + AplWeightTotalLev0 += pUnit->Weight; + } + + // (3) walk through the old lower level, find those nodes whose ref counters are not zero, + // and move them to the new uppoer level, free other nodes + for ( pLoop = pListOld1; pLoop; ) + { + pUnit = pLoop; + pLoop = pLoop->Next; + if ( pUnit->n ) + { + assert( !p->fMinApl || pUnit->Weight > 0.0 ); + // the node should be added to the new level + // no need to check the hash table + pUnit->lev = lev0; + AddToLinkedList( ppListNew0, pUnit ); + if ( p->fMinApl ) + AplWeightTotalLev0 += pUnit->Weight; + + nNodesDownMovedUp++; + + if ( p->fMinWidth ) + { + pUnitER = Unit_Regular(pUnit->pE); + pUnitT = pUnit->pT; + + // update the cofactors's top ref + if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels + { + pUnitER->TopRefNew = lev1; + if ( pUnitER->Sign != p->nSwaps ) + { + pUnitER->Sign = p->nSwaps; // set the current signature + p->pWidthCofs[ nWidthCofs++ ] = pUnitER; + } + } + if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels + { + pUnitT->TopRefNew = lev1; + if ( pUnitT->Sign != p->nSwaps ) + { + pUnitT->Sign = p->nSwaps; // set the current signature + p->pWidthCofs[ nWidthCofs++ ] = pUnitT; + } + } + } + } + else + { + assert( !p->fMinApl || pUnit->Weight == 0.0 ); + // decrement reference counters of children + pUnitER = Unit_Regular(pUnit->pE); + pUnitT = pUnit->pT; + pUnitER->n--; /// + pUnitT->n--; /// + // the node should be thrown away + reoUnitsRecycleUnit( p, pUnit ); + nNodesUnrefRemoved++; + } + } + +finish: + + // attach the new levels to the planes + p->pPlanes[lev0].pHead = pListNew0; + p->pPlanes[lev1].pHead = pListNew1; + + // swap the sift status + temp = p->pPlanes[lev0].fSifted; + p->pPlanes[lev0].fSifted = p->pPlanes[lev1].fSifted; + p->pPlanes[lev1].fSifted = temp; + + // swap variables in the variable map + if ( p->pOrderInt ) + { + temp = p->pOrderInt[lev0]; + p->pOrderInt[lev0] = p->pOrderInt[lev1]; + p->pOrderInt[lev1] = temp; + } + + // adjust the node profile + p->pPlanes[lev0].statsNodes -= (nNodesUpMovedDown - nNodesDownMovedUp); + p->pPlanes[lev1].statsNodes -= (nNodesDownMovedUp - nNodesUpMovedDown) + nNodesUnrefRemoved - nNodesUnrefAdded; + p->nNodesCur -= nNodesUnrefRemoved - nNodesUnrefAdded; + + // adjust the node profile on this level + if ( p->fMinWidth ) + { + for ( c = 0; c < nWidthCofs; c++ ) + { + if ( p->pWidthCofs[c]->TopRefNew < p->pWidthCofs[c]->TopRef ) + { + p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew; + nWidthReduction--; + } + else if ( p->pWidthCofs[c]->TopRefNew > p->pWidthCofs[c]->TopRef ) + { + p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew; + nWidthReduction++; + } + } + // verify that the profile is okay + reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 ); + reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 ); + + // compute the total gain in terms of width + nCostGain = (nNodesDownMovedUp - nNodesUpMovedDown + nNodesUnrefRemoved - nNodesUnrefAdded) + nWidthReduction; + // adjust the width on this level + p->pPlanes[lev1].statsWidth -= (int)nCostGain; + // set the cost + p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsWidth; + } + else if ( p->fMinApl ) + { + // compute the total gain in terms of APL + nCostGain = AplWeightPrev - AplWeightAfter; + // make sure that the ALP is updated correctly +// assert( p->pPlanes[lev0].statsCost + p->pPlanes[lev1].statsCost - nCostGain == +// AplWeightTotalLev0 + AplWeightTotalLev1 ); + // adjust the profile + p->pPlanes[lev0].statsApl = AplWeightTotalLev0; + p->pPlanes[lev1].statsApl = AplWeightTotalLev1; + // set the cost + p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsApl; + p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsApl; + } + else + { + // compute the total gain in terms of the number of nodes + nCostGain = nNodesUnrefRemoved - nNodesUnrefAdded; + // adjust the profile (adjusted above) + // set the cost + p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsNodes; + p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsNodes; + } + + return nCostGain; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/bdd/reo/reoTest.c b/abc70930/src/bdd/reo/reoTest.c new file mode 100644 index 00000000..82f3d5f5 --- /dev/null +++ b/abc70930/src/bdd/reo/reoTest.c @@ -0,0 +1,251 @@ +/**CFile**************************************************************** + + FileName [reoTest.c] + + PackageName [REO: A specialized DD reordering engine.] + + Synopsis [Various testing procedures (may be outdated).] + + Author [Alan Mishchenko ] + + Affiliation [ECE Department. Portland State University, Portland, Oregon.] + + Date [Ver. 1.0. Started - October 15, 2002.] + + Revision [$Id: reoTest.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "reo.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reorders the DD using REO and CUDD.] + + Description [This function can be used to test the performance of the reordering package.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ReorderTest( DdManager * dd, DdNode * Func ) +{ + reo_man * pReo; + DdNode * Temp, * Temp1; + int pOrder[1000]; + + pReo = Extra_ReorderInit( 100, 100 ); + +//Extra_DumpDot( dd, &Func, 1, "beforReo.dot", 0 ); + Temp = Extra_Reorder( pReo, dd, Func, pOrder ); Cudd_Ref( Temp ); +//Extra_DumpDot( dd, &Temp, 1, "afterReo.dot", 0 ); + + Temp1 = Extra_ReorderCudd(dd, Func, NULL ); Cudd_Ref( Temp1 ); +printf( "Initial = %d. Final = %d. Cudd = %d.\n", Cudd_DagSize(Func), Cudd_DagSize(Temp), Cudd_DagSize(Temp1) ); + Cudd_RecursiveDeref( dd, Temp1 ); + Cudd_RecursiveDeref( dd, Temp ); + + Extra_ReorderQuit( pReo ); +} + + +/**Function************************************************************* + + Synopsis [Reorders the DD using REO and CUDD.] + + Description [This function can be used to test the performance of the reordering package.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ReorderTestArray( DdManager * dd, DdNode * Funcs[], int nFuncs ) +{ + reo_man * pReo; + DdNode * FuncsRes[1000]; + int pOrder[1000]; + int i; + + pReo = Extra_ReorderInit( 100, 100 ); + Extra_ReorderArray( pReo, dd, Funcs, FuncsRes, nFuncs, pOrder ); + Extra_ReorderQuit( pReo ); + +printf( "Initial = %d. Final = %d.\n", Cudd_SharingSize(Funcs,nFuncs), Cudd_SharingSize(FuncsRes,nFuncs) ); + + for ( i = 0; i < nFuncs; i++ ) + Cudd_RecursiveDeref( dd, FuncsRes[i] ); + +} + +/**Function************************************************************* + + Synopsis [Reorders the DD using CUDD package.] + + Description [Transfers the DD into a temporary manager in such a way + that the level correspondence is preserved. Reorders the manager + and transfers the DD back into the original manager using the topmost + levels of the manager, in such a way that the ordering of levels is + preserved. The resulting permutation is returned in the array + given by the user.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermuteReo[] ) +{ + static DdManager * ddReorder = NULL; + static int * Permute = NULL; + static int * PermuteReo1 = NULL; + static int * PermuteReo2 = NULL; + DdNode * aFuncReorder, * aFuncNew; + int lev, var; + + // start the reordering manager + if ( ddReorder == NULL ) + { + Permute = ALLOC( int, dd->size ); + PermuteReo1 = ALLOC( int, dd->size ); + PermuteReo2 = ALLOC( int, dd->size ); + ddReorder = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynDisable(ddReorder); + } + + // determine the permutation of variable to make sure that var order in bFunc + // will not change when this function is transfered into the new manager + for ( lev = 0; lev < dd->size; lev++ ) + { + Permute[ dd->invperm[lev] ] = ddReorder->invperm[lev]; + PermuteReo1[ ddReorder->invperm[lev] ] = dd->invperm[lev]; + } + // transfer this function into the new manager in such a way that ordering of vars does not change + aFuncReorder = Extra_TransferPermute( dd, ddReorder, aFunc, Permute ); Cudd_Ref( aFuncReorder ); +// assert( Cudd_DagSize(aFunc) == Cudd_DagSize(aFuncReorder) ); + + // perform the reordering +printf( "Nodes before = %d.\n", Cudd_DagSize(aFuncReorder) ); + Cudd_ReduceHeap( ddReorder, CUDD_REORDER_SYMM_SIFT, 1 ); +printf( "Nodes before = %d.\n", Cudd_DagSize(aFuncReorder) ); + + // determine the reverse variable permutation + for ( lev = 0; lev < dd->size; lev++ ) + { + Permute[ ddReorder->invperm[lev] ] = dd->invperm[lev]; + PermuteReo2[ dd->invperm[lev] ] = ddReorder->invperm[lev]; + } + + // transfer this function into the new manager in such a way that ordering of vars does not change + aFuncNew = Extra_TransferPermute( ddReorder, dd, aFuncReorder, Permute ); Cudd_Ref( aFuncNew ); +// assert( Cudd_DagSize(aFuncNew) == Cudd_DagSize(aFuncReorder) ); + Cudd_RecursiveDeref( ddReorder, aFuncReorder ); + + // derive the resulting variable ordering + if ( pPermuteReo ) + for ( var = 0; var < dd->size; var++ ) + pPermuteReo[var] = PermuteReo1[ PermuteReo2[var] ]; + + Cudd_Deref( aFuncNew ); + return aFuncNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [Transfers the BDD into another manager minimizes it and + returns the min number of nodes; disposes of the BDD in the new manager. + Useful for debugging or comparing the performance of other reordering + procedures.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_bddReorderTest( DdManager * dd, DdNode * bF ) +{ + static DdManager * s_ddmin; + DdNode * bFmin; + int nNodes; +// int clk1; + + if ( s_ddmin == NULL ) + s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); + +// Cudd_ShuffleHeap( s_ddmin, dd->invperm ); + +// clk1 = clock(); + bFmin = Cudd_bddTransfer( dd, s_ddmin, bF ); Cudd_Ref( bFmin ); + Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SIFT,1); +// Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); + nNodes = Cudd_DagSize( bFmin ); + Cudd_RecursiveDeref( s_ddmin, bFmin ); + +// printf( "Classical variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); + return nNodes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Transfers the ADD into another manager minimizes it and + returns the min number of nodes; disposes of the BDD in the new manager. + Useful for debugging or comparing the performance of other reordering + procedures.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_addReorderTest( DdManager * dd, DdNode * aF ) +{ + static DdManager * s_ddmin; + DdNode * bF; + DdNode * bFmin; + DdNode * aFmin; + int nNodesBeg; + int nNodesEnd; + int clk1; + + if ( s_ddmin == NULL ) + s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); + +// Cudd_ShuffleHeap( s_ddmin, dd->invperm ); + + clk1 = clock(); + bF = Cudd_addBddPattern( dd, aF ); Cudd_Ref( bF ); + bFmin = Cudd_bddTransfer( dd, s_ddmin, bF ); Cudd_Ref( bFmin ); + Cudd_RecursiveDeref( dd, bF ); + aFmin = Cudd_BddToAdd( s_ddmin, bFmin ); Cudd_Ref( aFmin ); + Cudd_RecursiveDeref( s_ddmin, bFmin ); + + nNodesBeg = Cudd_DagSize( aFmin ); + Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SIFT,1); +// Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); + nNodesEnd = Cudd_DagSize( aFmin ); + Cudd_RecursiveDeref( s_ddmin, aFmin ); + + printf( "Classical reordering of ADDs: Before = %d. After = %d.\n", nNodesBeg, nNodesEnd ); + printf( "Classical variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); + return nNodesEnd; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/bdd/reo/reoTransfer.c b/abc70930/src/bdd/reo/reoTransfer.c new file mode 100644 index 00000000..65d31d01 --- /dev/null +++ b/abc70930/src/bdd/reo/reoTransfer.c @@ -0,0 +1,199 @@ +/**CFile**************************************************************** + + FileName [reoTransfer.c] + + PackageName [REO: A specialized DD reordering engine.] + + Synopsis [Transfering a DD from the CUDD manager into REO"s internal data structures and back.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 15, 2002.] + + Revision [$Id: reoTransfer.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "reo.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transfers the DD into the internal reordering data structure.] + + Description [It is important that the hash table is lossless.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ) +{ + DdManager * dd = p->dd; + reo_unit * pUnit; + int HKey, fComp; + + fComp = Cudd_IsComplement(F); + F = Cudd_Regular(F); + + // check the hash-table + if ( F->ref != 1 ) + { + // search cache - use linear probing + for ( HKey = hashKey2(p->Signature,F,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) + if ( p->HTable[HKey].Arg1 == (reo_unit *)F ) + { + pUnit = p->HTable[HKey].Arg2; + assert( pUnit ); + // increment the edge counter + pUnit->n++; + return Unit_NotCond( pUnit, fComp ); + } + } + // the entry in not found in the cache + + // create a new entry + pUnit = reoUnitsGetNextUnit( p ); + pUnit->n = 1; + if ( cuddIsConstant(F) ) + { + pUnit->lev = REO_CONST_LEVEL; + pUnit->pE = (reo_unit*)((int)(cuddV(F))); + pUnit->pT = NULL; + // check if the diagram that is being reordering has complement edges + if ( F != dd->one ) + p->fThisIsAdd = 1; + // insert the unit into the corresponding plane + reoUnitsAddUnitToPlane( &(p->pPlanes[p->nSupp]), pUnit ); // increments the unit counter + } + else + { + pUnit->lev = p->pMapToPlanes[F->index]; + pUnit->pE = reoTransferNodesToUnits_rec( p, cuddE(F) ); + pUnit->pT = reoTransferNodesToUnits_rec( p, cuddT(F) ); + // insert the unit into the corresponding plane + reoUnitsAddUnitToPlane( &(p->pPlanes[pUnit->lev]), pUnit ); // increments the unit counter + } + + // add to the hash table + if ( F->ref != 1 ) + { + // the next free entry is already found - it is pointed to by HKey + // while we traversed the diagram, the hash entry to which HKey points, + // might have been used. Make sure that its signature is different. + for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); + p->HTable[HKey].Sign = p->Signature; + p->HTable[HKey].Arg1 = (reo_unit *)F; + p->HTable[HKey].Arg2 = pUnit; + } + + // increment the counter of nodes + p->nNodesCur++; + return Unit_NotCond( pUnit, fComp ); +} + +/**Function************************************************************* + + Synopsis [Creates the DD from the internal reordering data structure.] + + Description [It is important that the hash table is lossless.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ) +{ + DdManager * dd = p->dd; + DdNode * bRes, * E, * T; + int HKey, fComp; + + fComp = Cudd_IsComplement(pUnit); + pUnit = Unit_Regular(pUnit); + + // check the hash-table + if ( pUnit->n != 1 ) + { + for ( HKey = hashKey2(p->Signature,pUnit,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) + if ( p->HTable[HKey].Arg1 == pUnit ) + { + bRes = (DdNode*) p->HTable[HKey].Arg2; + assert( bRes ); + return Cudd_NotCond( bRes, fComp ); + } + } + + // treat the case of constants + if ( Unit_IsConstant(pUnit) ) + { + bRes = cuddUniqueConst( dd, ((double)((int)(pUnit->pE))) ); + cuddRef( bRes ); + } + else + { + // split and recur on children of this node + E = reoTransferUnitsToNodes_rec( p, pUnit->pE ); + if ( E == NULL ) + return NULL; + cuddRef(E); + + T = reoTransferUnitsToNodes_rec( p, pUnit->pT ); + if ( T == NULL ) + { + Cudd_RecursiveDeref(dd, E); + return NULL; + } + cuddRef(T); + + // consider the case when Res0 and Res1 are the same node + assert( E != T ); + assert( !Cudd_IsComplement(T) ); + + bRes = cuddUniqueInter( dd, p->pMapToDdVarsFinal[pUnit->lev], T, E ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,E); + Cudd_RecursiveDeref(dd,T); + return NULL; + } + cuddRef( bRes ); + cuddDeref( E ); + cuddDeref( T ); + } + + // do not keep the result if the ref count is only 1, since it will not be visited again + if ( pUnit->n != 1 ) + { + // while we traversed the diagram, the hash entry to which HKey points, + // might have been used. Make sure that its signature is different. + for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); + p->HTable[HKey].Sign = p->Signature; + p->HTable[HKey].Arg1 = pUnit; + p->HTable[HKey].Arg2 = (reo_unit *)bRes; + + // add the DD to the referenced DD list in order to be able to store it in cache + p->pRefNodes[p->nRefNodes++] = bRes; Cudd_Ref( bRes ); + // no need to do this, because the garbage collection will not take bRes away + // it is held by the diagram in the making + } + // increment the counter of nodes + p->nNodesCur++; + cuddDeref( bRes ); + return Cudd_NotCond( bRes, fComp ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/bdd/reo/reoUnits.c b/abc70930/src/bdd/reo/reoUnits.c new file mode 100644 index 00000000..aa86516e --- /dev/null +++ b/abc70930/src/bdd/reo/reoUnits.c @@ -0,0 +1,184 @@ +/**CFile**************************************************************** + + FileName [reoUnits.c] + + PackageName [REO: A specialized DD reordering engine.] + + Synopsis [Procedures which support internal data structures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 15, 2002.] + + Revision [$Id: reoUnits.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "reo.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void reoUnitsAddToFreeUnitList( reo_man * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Extract the next unit from the free unit list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +reo_unit * reoUnitsGetNextUnit(reo_man * p ) +{ + reo_unit * pUnit; + // check there are stil units to extract + if ( p->pUnitFreeList == NULL ) + reoUnitsAddToFreeUnitList( p ); + // extract the next unit from the linked list + pUnit = p->pUnitFreeList; + p->pUnitFreeList = pUnit->Next; + p->nUnitsUsed++; + return pUnit; +} + +/**Function************************************************************* + + Synopsis [Returns the unit to the free unit list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void reoUnitsRecycleUnit( reo_man * p, reo_unit * pUnit ) +{ + pUnit->Next = p->pUnitFreeList; + p->pUnitFreeList = pUnit; + p->nUnitsUsed--; +} + +/**Function************************************************************* + + Synopsis [Returns the list of units to the free unit list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void reoUnitsRecycleUnitList( reo_man * p, reo_plane * pPlane ) +{ + reo_unit * pUnit; + reo_unit * pTail; + + if ( pPlane->pHead == NULL ) + return; + + // find the tail + for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) + pTail = pUnit; + pTail->Next = p->pUnitFreeList; + p->pUnitFreeList = pPlane->pHead; + memset( pPlane, 0, sizeof(reo_plane) ); +} + +/**Function************************************************************* + + Synopsis [Stops the unit dispenser.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void reoUnitsStopDispenser( reo_man * p ) +{ + int i; + for ( i = 0; i < p->nMemChunks; i++ ) + free( p->pMemChunks[i] ); +// printf("\nThe number of chunks used is %d, each of them %d units\n", p->nMemChunks, REO_CHUNK_SIZE ); + p->nMemChunks = 0; +} + +/**Function************************************************************* + + Synopsis [Adds one unit to the list of units which constitutes the plane.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void reoUnitsAddUnitToPlane( reo_plane * pPlane, reo_unit * pUnit ) +{ + if ( pPlane->pHead == NULL ) + { + pPlane->pHead = pUnit; + pUnit->Next = NULL; + } + else + { + pUnit->Next = pPlane->pHead; + pPlane->pHead = pUnit; + } + pPlane->statsNodes++; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void reoUnitsAddToFreeUnitList( reo_man * p ) +{ + int c; + // check that we still have chunks left + if ( p->nMemChunks == p->nMemChunksAlloc ) + { + printf( "reoUnitsAddToFreeUnitList(): Memory manager ran out of memory!\n" ); + fflush( stdout ); + return; + } + // allocate the next chunk + assert( p->pUnitFreeList == NULL ); + p->pUnitFreeList = ALLOC( reo_unit, REO_CHUNK_SIZE ); + // split chunks into list-connected units + for ( c = 0; c < REO_CHUNK_SIZE-1; c++ ) + (p->pUnitFreeList + c)->Next = p->pUnitFreeList + c + 1; + // set the last pointer to NULL + (p->pUnitFreeList + REO_CHUNK_SIZE-1)->Next = NULL; + // add the chunk to the array of chunks + p->pMemChunks[p->nMemChunks++] = p->pUnitFreeList; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/generic.c b/abc70930/src/generic.c new file mode 100644 index 00000000..f94c50e6 --- /dev/null +++ b/abc70930/src/generic.c @@ -0,0 +1,47 @@ +/**CFile**************************************************************** + + FileName [.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "__Int.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/generic.h b/abc70930/src/generic.h new file mode 100644 index 00000000..e17d2edf --- /dev/null +++ b/abc70930/src/generic.h @@ -0,0 +1,59 @@ +/**CFile**************************************************************** + + FileName [.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: .h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __zzz_H__ +#define __zzz_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== zzz.c ==========================================================*/ + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/map/fpga/fpga.c b/abc70930/src/map/fpga/fpga.c new file mode 100644 index 00000000..40423f4f --- /dev/null +++ b/abc70930/src/map/fpga/fpga.c @@ -0,0 +1,283 @@ +/**CFile**************************************************************** + + FileName [fpga.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Command file for the FPGA package.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpga.c,v 1.4 2004/10/28 17:36:07 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" +#include "main.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); +static int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); + +// the library file format should be as follows: +/* +# The area/delay of k-variable LUTs: +# k area delay +1 1 1 +2 2 2 +3 4 3 +4 8 4 +5 16 5 +6 32 6 +*/ + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Package initialization procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_Init( Abc_Frame_t * pAbc ) +{ + // set the default library + //Fpga_LutLib_t s_LutLib = { "lutlib", 6, 0, {0,1,2,4,8,16,32}, {{0},{1},{2},{3},{4},{5},{6}} }; +// Fpga_LutLib_t s_LutLib = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} }; + Fpga_LutLib_t s_LutLib = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} }; + //Fpga_LutLib_t s_LutLib = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} }; + + Abc_FrameSetLibLut( Fpga_LutLibDup(&s_LutLib) ); + + Cmd_CommandAdd( pAbc, "FPGA mapping", "read_lut", Fpga_CommandReadLibrary, 0 ); + Cmd_CommandAdd( pAbc, "FPGA mapping", "print_lut", Fpga_CommandPrintLibrary, 0 ); +} + +/**Function************************************************************* + + Synopsis [Package ending procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_End() +{ + Fpga_LutLibFree( Abc_FrameReadLibLut() ); +} + + +/**Function************************************************************* + + Synopsis [Command procedure to read LUT libraries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Fpga_LutLib_t * pLib; + Abc_Ntk_t * pNet; + char * FileName; + int fVerbose; + int c; + + pNet = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) + { + switch (c) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); + if ( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) ) + fprintf( pErr, "Did you mean \"%s\"?", FileName ); + fprintf( pErr, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pLib = Fpga_LutLibCreate( FileName, fVerbose ); + if ( pLib == NULL ) + { + fprintf( pErr, "Reading LUT library has failed.\n" ); + goto usage; + } + // replace the current library + Fpga_LutLibFree( Abc_FrameReadLibLut() ); + Abc_FrameSetLibLut( pLib ); + return 0; + +usage: + fprintf( pErr, "\nusage: read_lut [-vh]\n"); + fprintf( pErr, "\t read the LUT library from the file\n" ); + fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); + fprintf( pErr, "\t-h : print the command usage\n"); + fprintf( pErr, "\t \n"); + fprintf( pErr, "\t File format for a LUT library:\n"); + fprintf( pErr, "\t (the default library is shown)\n"); + fprintf( pErr, "\t \n"); + fprintf( pErr, "\t # The area/delay of k-variable LUTs:\n"); + fprintf( pErr, "\t # k area delay\n"); + fprintf( pErr, "\t 1 1 1\n"); + fprintf( pErr, "\t 2 2 2\n"); + fprintf( pErr, "\t 3 4 3\n"); + fprintf( pErr, "\t 4 8 4\n"); + fprintf( pErr, "\t 5 16 5\n"); + fprintf( pErr, "\t 6 32 6\n"); + return 1; /* error exit */ +} + +/**Function************************************************************* + + Synopsis [Command procedure to read LUT libraries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNet; + int fVerbose; + int c; + + pNet = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) + { + switch (c) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + + if ( argc != globalUtilOptind ) + { + goto usage; + } + + // set the new network + Fpga_LutLibPrint( Abc_FrameReadLibLut() ); + return 0; + +usage: + fprintf( pErr, "\nusage: read_print [-vh]\n"); + fprintf( pErr, "\t print the current LUT library\n" ); + fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; /* error exit */ +} + +/**Function************************************************************* + + Synopsis [Sets simple LUT library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_SetSimpleLutLib( int nLutSize ) +{ + Fpga_LutLib_t s_LutLib10= { "lutlib",10, 0, {0,1,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1},{1}} }; + Fpga_LutLib_t s_LutLib9 = { "lutlib", 9, 0, {0,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1}} }; + Fpga_LutLib_t s_LutLib8 = { "lutlib", 8, 0, {0,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1}} }; + Fpga_LutLib_t s_LutLib7 = { "lutlib", 7, 0, {0,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1}} }; + Fpga_LutLib_t s_LutLib6 = { "lutlib", 6, 0, {0,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1}} }; + Fpga_LutLib_t s_LutLib5 = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} }; + Fpga_LutLib_t s_LutLib4 = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} }; + Fpga_LutLib_t s_LutLib3 = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} }; + Fpga_LutLib_t * pLutLib; + assert( nLutSize >= 3 && nLutSize <= 10 ); + switch ( nLutSize ) + { + case 3: pLutLib = &s_LutLib3; break; + case 4: pLutLib = &s_LutLib4; break; + case 5: pLutLib = &s_LutLib5; break; + case 6: pLutLib = &s_LutLib6; break; + case 7: pLutLib = &s_LutLib7; break; + case 8: pLutLib = &s_LutLib8; break; + case 9: pLutLib = &s_LutLib9; break; + case 10: pLutLib = &s_LutLib10; break; + default: pLutLib = NULL; break; + } + if ( pLutLib == NULL ) + return; + Fpga_LutLibFree( Abc_FrameReadLibLut() ); + Abc_FrameSetLibLut( Fpga_LutLibDup(pLutLib) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/fpga/fpga.h b/abc70930/src/map/fpga/fpga.h new file mode 100644 index 00000000..188420b1 --- /dev/null +++ b/abc70930/src/map/fpga/fpga.h @@ -0,0 +1,172 @@ +/**CFile**************************************************************** + + FileName [fpga.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Technology mapping for variable-size-LUT FPGAs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpga.h,v 1.7 2004/09/30 21:18:09 satrajit Exp $] + +***********************************************************************/ + +#ifndef __FPGA_H__ +#define __FPGA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// the maximum size of LUTs used for mapping +#define FPGA_MAX_LUTSIZE 32 + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Fpga_ManStruct_t_ Fpga_Man_t; +typedef struct Fpga_NodeStruct_t_ Fpga_Node_t; +typedef struct Fpga_NodeVecStruct_t_ Fpga_NodeVec_t; +typedef struct Fpga_CutStruct_t_ Fpga_Cut_t; +typedef struct Fpga_LutLibStruct_t_ Fpga_LutLib_t; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Fpga_IsComplement(p) (((int)((unsigned long) (p) & 01))) +#define Fpga_Regular(p) ((Fpga_Node_t *)((unsigned long)(p) & ~01)) +#define Fpga_Not(p) ((Fpga_Node_t *)((unsigned long)(p) ^ 01)) +#define Fpga_NotCond(p,c) ((Fpga_Node_t *)((unsigned long)(p) ^ (c))) + +#define Fpga_Ref(p) +#define Fpga_Deref(p) +#define Fpga_RecursiveDeref(p,c) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== fpgaCreate.c =============================================================*/ +extern Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose ); +extern Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); +extern void Fpga_ManFree( Fpga_Man_t * pMan ); +extern void Fpga_ManPrintTimeStats( Fpga_Man_t * p ); + +extern int Fpga_ManReadInputNum( Fpga_Man_t * p ); +extern int Fpga_ManReadOutputNum( Fpga_Man_t * p ); +extern Fpga_Node_t ** Fpga_ManReadInputs ( Fpga_Man_t * p ); +extern Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p ); +extern Fpga_Node_t * Fpga_ManReadConst1 ( Fpga_Man_t * p ); +extern float * Fpga_ManReadInputArrivals( Fpga_Man_t * p ); +extern int Fpga_ManReadVerbose( Fpga_Man_t * p ); +extern float * Fpga_ManReadLutAreas( Fpga_Man_t * p ); +extern void Fpga_ManSetTimeToMap( Fpga_Man_t * p, int Time ); +extern void Fpga_ManSetTimeToNet( Fpga_Man_t * p, int Time ); +extern void Fpga_ManSetTimeTotal( Fpga_Man_t * p, int Time ); +extern void Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames ); +extern void Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals ); +extern void Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery ); +extern void Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit ); +extern void Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit ); +extern void Fpga_ManSetTimeLimit( Fpga_Man_t * p, float TimeLimit ); +extern void Fpga_ManSetObeyFanoutLimits( Fpga_Man_t * p, int fObeyFanoutLimits ); +extern void Fpga_ManSetNumIterations( Fpga_Man_t * p, int nNumIterations ); +extern int Fpga_ManReadFanoutViolations( Fpga_Man_t * p ); +extern void Fpga_ManSetFanoutViolations( Fpga_Man_t * p, int nVio ); +extern void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ); +extern void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices ); +extern void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose ); +extern void Fpga_ManSetSwitching( Fpga_Man_t * p, int fSwitching ); +extern void Fpga_ManSetLatchPaths( Fpga_Man_t * p, int fLatchPaths ); +extern void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches ); +extern void Fpga_ManSetDelayTarget( Fpga_Man_t * p, float DelayTarget ); +extern void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName ); + +extern int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib ); + +extern char * Fpga_NodeReadData0( Fpga_Node_t * p ); +extern Fpga_Node_t * Fpga_NodeReadData1( Fpga_Node_t * p ); +extern int Fpga_NodeReadRefs( Fpga_Node_t * p ); +extern int Fpga_NodeReadNum( Fpga_Node_t * p ); +extern int Fpga_NodeReadLevel( Fpga_Node_t * p ); +extern Fpga_Cut_t * Fpga_NodeReadCuts( Fpga_Node_t * p ); +extern Fpga_Cut_t * Fpga_NodeReadCutBest( Fpga_Node_t * p ); +extern Fpga_Node_t * Fpga_NodeReadOne( Fpga_Node_t * p ); +extern Fpga_Node_t * Fpga_NodeReadTwo( Fpga_Node_t * p ); +extern void Fpga_NodeSetLevel( Fpga_Node_t * p, Fpga_Node_t * pNode ); +extern void Fpga_NodeSetData0( Fpga_Node_t * p, char * pData ); +extern void Fpga_NodeSetData1( Fpga_Node_t * p, Fpga_Node_t * pNode ); +extern void Fpga_NodeSetArrival( Fpga_Node_t * p, float Time ); +extern void Fpga_NodeSetNextE( Fpga_Node_t * p, Fpga_Node_t * pNextE ); +extern void Fpga_NodeSetRepr( Fpga_Node_t * p, Fpga_Node_t * pRepr ); +extern void Fpga_NodeSetSwitching( Fpga_Node_t * p, float Switching ); + +extern int Fpga_NodeIsConst( Fpga_Node_t * p ); +extern int Fpga_NodeIsVar( Fpga_Node_t * p ); +extern int Fpga_NodeIsAnd( Fpga_Node_t * p ); +extern int Fpga_NodeComparePhase( Fpga_Node_t * p1, Fpga_Node_t * p2 ); + +extern int Fpga_CutReadLeavesNum( Fpga_Cut_t * p ); +extern Fpga_Node_t ** Fpga_CutReadLeaves( Fpga_Cut_t * p ); + +extern Fpga_Node_t * Fpga_NodeAnd( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); +extern Fpga_Node_t * Fpga_NodeOr( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); +extern Fpga_Node_t * Fpga_NodeExor( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); +extern Fpga_Node_t * Fpga_NodeMux( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Node_t * pNodeT, Fpga_Node_t * pNodeE ); +extern void Fpga_NodeSetChoice( Fpga_Man_t * pMan, Fpga_Node_t * pNodeOld, Fpga_Node_t * pNodeNew ); + +extern void Fpga_ManStats( Fpga_Man_t * p ); + +/*=== fpgaCore.c =============================================================*/ +extern int Fpga_Mapping( Fpga_Man_t * p ); +/*=== fpgaCut.c ===============================================================*/ +extern void Fpga_MappingCreatePiCuts( Fpga_Man_t * p ); +extern void Fpga_CutsCleanSign( Fpga_Man_t * pMan ); +/*=== fpgaCutUtils.c =============================================================*/ +extern void Fpga_CutCreateFromNode( Fpga_Man_t * p, int iRoot, int * pLeaves, int nLeaves ); +extern void Fpga_MappingSetUsedCuts( Fpga_Man_t * p ); +/*=== fpgaLib.c =============================================================*/ +extern Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p ); +extern int Fpga_LutLibReadVarMax( Fpga_LutLib_t * p ); +extern float * Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p ); +extern float * Fpga_LutLibReadLutDelays( Fpga_LutLib_t * p ); +extern float Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size ); +extern float Fpga_LutLibReadLutDelay( Fpga_LutLib_t * p, int Size ); +/*=== fpgaTruth.c =============================================================*/ +extern void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut ); +extern int Fpga_CutVolume( Fpga_Cut_t * pCut ); +/*=== fpgaUtil.c =============================================================*/ +extern int Fpga_ManCheckConsistency( Fpga_Man_t * p ); +extern void Fpga_ManCleanData0( Fpga_Man_t * pMan ); +extern Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode ); +/*=== fpga.c =============================================================*/ +extern void Fpga_SetSimpleLutLib( int nLutSize ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/map/fpga/fpgaCore.c b/abc70930/src/map/fpga/fpgaCore.c new file mode 100644 index 00000000..634a8eb1 --- /dev/null +++ b/abc70930/src/map/fpga/fpgaCore.c @@ -0,0 +1,188 @@ +/**CFile**************************************************************** + + FileName [fpgaCore.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Technology mapping for variable-size-LUT FPGAs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaCore.c,v 1.7 2004/10/01 23:41:04 satrajit Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Fpga_MappingPostProcess( Fpga_Man_t * p ); + +extern int s_MappingTime; +extern int s_MappingMem; + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs technology mapping for the given object graph.] + + Description [The object graph is stored in the mapping manager. + First, all the AND-nodes, which fanout into the POs, are collected + in the DFS fashion. Next, three steps are performed: the k-feasible + cuts are computed for each node, the truth tables are computed for + each cut, and the delay-optimal matches are assigned for each node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_Mapping( Fpga_Man_t * p ) +{ + int clk, clkTotal = clock(); + + // collect the nodes reachable from POs in the DFS order (including the choices) + p->vAnds = Fpga_MappingDfs( p, 1 ); + Fpga_ManReportChoices( p ); // recomputes levels + Fpga_MappingSetChoiceLevels( p ); + + // compute the cuts of nodes in the DFS order + clk = clock(); + Fpga_MappingCuts( p ); + p->timeCuts = clock() - clk; + + // match the truth tables to the supergates + clk = clock(); + if ( !Fpga_MappingMatches( p, 1 ) ) + return 0; + p->timeMatch = clock() - clk; + + // perform area recovery + clk = clock(); + if ( !Fpga_MappingPostProcess( p ) ) + return 0; + p->timeRecover = clock() - clk; +//PRT( "Total mapping time", clock() - clkTotal ); + + s_MappingTime = clock() - clkTotal; + s_MappingMem = Fpga_CutCountAll(p) * (sizeof(Fpga_Cut_t) - sizeof(int) * (FPGA_MAX_LEAVES - p->nVarsMax)); + + // print the AI-graph used for mapping + //Fpga_ManShow( p, "test" ); +// if ( p->fVerbose ) +// Fpga_MappingPrintOutputArrivals( p ); + if ( p->fVerbose ) + { + PRT( "Total time", clock() - clkTotal ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Postprocesses the mapped network for area recovery.] + + Description [This procedure assumes that the mapping is assigned. + It iterates the loop, in which the required times are computed and + the mapping is updated. It is conceptually similar to the paper: + V. Manohararajah, S. D. Brown, Z. G. Vranesic, Heuristics for area + minimization in LUT-based FPGA technology mapping. Proc. IWLS '04.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MappingPostProcess( Fpga_Man_t * p ) +{ + int fShowSwitching = 0; + int fRecoverAreaFlow = 1; + int fRecoverArea = 1; + float aAreaTotalCur, aAreaTotalCur2; + int Iter, clk; + +//if ( p->fVerbose ) +// printf( "Best clock period = %5.2f\n", Fpga_TimeComputeArrivalMax(p) ); + + // compute area, set references, and collect nodes used in the mapping + Iter = 1; + aAreaTotalCur = Fpga_MappingSetRefsAndArea( p ); +if ( p->fVerbose ) +{ +printf( "Iteration %dD : Area = %8.1f ", Iter++, aAreaTotalCur ); +if ( fShowSwitching ) +printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) ); +else +printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) ); + +PRT( "Time", p->timeMatch ); +} + + if ( !p->fAreaRecovery ) + return 1; + + if ( fRecoverAreaFlow ) + { +clk = clock(); + // compute the required times and the fanouts + Fpga_TimeComputeRequiredGlobal( p, 1 ); + // remap topologically + Fpga_MappingMatches( p, 0 ); + // get the resulting area +// aAreaTotalCur = Fpga_MappingSetRefsAndArea( p ); + aAreaTotalCur = Fpga_MappingAreaTrav( p ); + // note that here we do not update the reference counter + // for some reason, this works better on benchmarks +if ( p->fVerbose ) +{ +printf( "Iteration %dF : Area = %8.1f ", Iter++, aAreaTotalCur ); +if ( fShowSwitching ) +printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) ); +else +printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) ); +PRT( "Time", clock() - clk ); +} + } + + // update reference counters + aAreaTotalCur2 = Fpga_MappingSetRefsAndArea( p ); + assert( aAreaTotalCur == aAreaTotalCur2 ); + + if ( fRecoverArea ) + { +clk = clock(); + // compute the required times and the fanouts + Fpga_TimeComputeRequiredGlobal( p, 0 ); + // remap topologically + if ( p->fSwitching ) + Fpga_MappingMatchesSwitch( p ); + else + Fpga_MappingMatchesArea( p ); + // get the resulting area + aAreaTotalCur = Fpga_MappingSetRefsAndArea( p ); +if ( p->fVerbose ) +{ +printf( "Iteration %d%s : Area = %8.1f ", Iter++, (p->fSwitching?"S":"A"), aAreaTotalCur ); +if ( fShowSwitching ) +printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) ); +else +printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) ); +PRT( "Time", clock() - clk ); +} + } + + p->fAreaGlo = aAreaTotalCur; + return 1; +} + + diff --git a/abc70930/src/map/fpga/fpgaCreate.c b/abc70930/src/map/fpga/fpgaCreate.c new file mode 100644 index 00000000..fa0f80d1 --- /dev/null +++ b/abc70930/src/map/fpga/fpgaCreate.c @@ -0,0 +1,580 @@ +/**CFile**************************************************************** + + FileName [fpgaCreate.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Technology mapping for variable-size-LUT FPGAs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaCreate.c,v 1.8 2004/09/30 21:18:09 satrajit Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" +#include "main.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Fpga_TableCreate( Fpga_Man_t * p ); +static void Fpga_TableResize( Fpga_Man_t * p ); +static Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); + +// hash key for the structural hash table +static inline unsigned Fpga_HashKey2( Fpga_Node_t * p0, Fpga_Node_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads parameters of the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_ManReadInputNum( Fpga_Man_t * p ) { return p->nInputs; } +int Fpga_ManReadOutputNum( Fpga_Man_t * p ) { return p->nOutputs; } +Fpga_Node_t ** Fpga_ManReadInputs ( Fpga_Man_t * p ) { return p->pInputs; } +Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p ) { return p->pOutputs; } +Fpga_Node_t * Fpga_ManReadConst1 ( Fpga_Man_t * p ) { return p->pConst1; } +float * Fpga_ManReadInputArrivals( Fpga_Man_t * p ) { return p->pInputArrivals;} +int Fpga_ManReadVerbose( Fpga_Man_t * p ) { return p->fVerbose; } +float * Fpga_ManReadLutAreas( Fpga_Man_t * p ) { return p->pLutLib->pLutAreas; } +void Fpga_ManSetTimeToMap( Fpga_Man_t * p, int Time ) { p->timeToMap = Time; } +void Fpga_ManSetTimeToNet( Fpga_Man_t * p, int Time ) { p->timeToNet = Time; } +void Fpga_ManSetTimeTotal( Fpga_Man_t * p, int Time ) { p->timeTotal = Time; } +void Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; } +void Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals ) { p->pInputArrivals = pArrivals; } +void Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;} +void Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit ) { p->DelayLimit = DelayLimit; } +void Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit ) { p->AreaLimit = AreaLimit; } +void Fpga_ManSetTimeLimit( Fpga_Man_t * p, float TimeLimit ) { p->TimeLimit = TimeLimit; } +void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ) { p->nChoiceNodes = nChoiceNodes; } +void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices ) { p->nChoices = nChoices; } +void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; } +void Fpga_ManSetSwitching( Fpga_Man_t * p, int fSwitching ) { p->fSwitching = fSwitching; } +void Fpga_ManSetLatchPaths( Fpga_Man_t * p, int fLatchPaths ) { p->fLatchPaths = fLatchPaths; } +void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches ) { p->nLatches = nLatches; } +void Fpga_ManSetDelayTarget( Fpga_Man_t * p, float DelayTarget ) { p->DelayTarget = DelayTarget; } +void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName ) { p->pFileName = pFileName; } + +/**Function************************************************************* + + Synopsis [Reads the parameters of the LUT library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib ) { return pLib->LutMax; } + +/**Function************************************************************* + + Synopsis [Reads parameters of the mapping node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Fpga_NodeReadData0( Fpga_Node_t * p ) { return p->pData0; } +Fpga_Node_t * Fpga_NodeReadData1( Fpga_Node_t * p ) { return p->pLevel; } +int Fpga_NodeReadRefs( Fpga_Node_t * p ) { return p->nRefs; } +int Fpga_NodeReadNum( Fpga_Node_t * p ) { return p->Num; } +int Fpga_NodeReadLevel( Fpga_Node_t * p ) { return Fpga_Regular(p)->Level; } +Fpga_Cut_t * Fpga_NodeReadCuts( Fpga_Node_t * p ) { return p->pCuts; } +Fpga_Cut_t * Fpga_NodeReadCutBest( Fpga_Node_t * p ) { return p->pCutBest; } +Fpga_Node_t * Fpga_NodeReadOne( Fpga_Node_t * p ) { return p->p1; } +Fpga_Node_t * Fpga_NodeReadTwo( Fpga_Node_t * p ) { return p->p2; } +void Fpga_NodeSetData0( Fpga_Node_t * p, char * pData ) { p->pData0 = pData; } +void Fpga_NodeSetData1( Fpga_Node_t * p, Fpga_Node_t * pNode ) { p->pLevel = pNode; } +void Fpga_NodeSetNextE( Fpga_Node_t * p, Fpga_Node_t * pNextE ) { p->pNextE = pNextE; } +void Fpga_NodeSetRepr( Fpga_Node_t * p, Fpga_Node_t * pRepr ) { p->pRepr = pRepr; } +void Fpga_NodeSetSwitching( Fpga_Node_t * p, float Switching ) { p->Switching = Switching; } + +/**Function************************************************************* + + Synopsis [Checks the type of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_NodeIsConst( Fpga_Node_t * p ) { return (Fpga_Regular(p))->Num == -1; } +int Fpga_NodeIsVar( Fpga_Node_t * p ) { return (Fpga_Regular(p))->p1 == NULL && (Fpga_Regular(p))->Num >= 0; } +int Fpga_NodeIsAnd( Fpga_Node_t * p ) { return (Fpga_Regular(p))->p1 != NULL; } +int Fpga_NodeComparePhase( Fpga_Node_t * p1, Fpga_Node_t * p2 ) { assert( !Fpga_IsComplement(p1) ); assert( !Fpga_IsComplement(p2) ); return p1->fInv ^ p2->fInv; } + +/**Function************************************************************* + + Synopsis [Reads parameters from the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CutReadLeavesNum( Fpga_Cut_t * p ) { return p->nLeaves; } +Fpga_Node_t ** Fpga_CutReadLeaves( Fpga_Cut_t * p ) { return p->ppLeaves; } + + +/**Function************************************************************* + + Synopsis [Create the mapping manager.] + + Description [The number of inputs and outputs is assumed to be + known is advance. It is much simpler to have them fixed upfront. + When it comes to representing the object graph in the form of + AIG, the resulting manager is similar to the regular AIG manager, + except that it does not use reference counting (and therefore + does not have garbage collections). It does have table resizing. + The data structure is more flexible to represent additional + information needed for mapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose ) +{ + Fpga_Man_t * p; + int i; + + // start the manager + p = ALLOC( Fpga_Man_t, 1 ); + memset( p, 0, sizeof(Fpga_Man_t) ); + p->pLutLib = Abc_FrameReadLibLut(); + p->nVarsMax = p->pLutLib->LutMax; + p->fVerbose = fVerbose; + p->fAreaRecovery = 1; + p->fEpsilon = (float)0.001; + + Fpga_TableCreate( p ); +//if ( p->fVerbose ) +// printf( "Node = %d (%d) bytes. Cut = %d bytes.\n", sizeof(Fpga_Node_t), FPGA_NUM_BYTES(sizeof(Fpga_Node_t)), sizeof(Fpga_Cut_t) ); + p->mmNodes = Extra_MmFixedStart( FPGA_NUM_BYTES(sizeof(Fpga_Node_t)) ); + p->mmCuts = Extra_MmFixedStart( sizeof(Fpga_Cut_t) ); + + assert( p->nVarsMax > 0 ); +// Fpga_MappingSetupTruthTables( p->uTruths ); + + // make sure the constant node will get index -1 + p->nNodes = -1; + // create the constant node + p->pConst1 = Fpga_NodeCreate( p, NULL, NULL ); + p->vNodesAll = Fpga_NodeVecAlloc( 1000 ); + p->vMapping = Fpga_NodeVecAlloc( 1000 ); + + // create the PI nodes + p->nInputs = nInputs; + p->pInputs = ALLOC( Fpga_Node_t *, nInputs ); + for ( i = 0; i < nInputs; i++ ) + p->pInputs[i] = Fpga_NodeCreate( p, NULL, NULL ); + + // create the place for the output nodes + p->nOutputs = nOutputs; + p->pOutputs = ALLOC( Fpga_Node_t *, nOutputs ); + memset( p->pOutputs, 0, sizeof(Fpga_Node_t *) * nOutputs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_ManFree( Fpga_Man_t * p ) +{ +// Fpga_ManStats( p ); +// int i; +// for ( i = 0; i < p->vNodesAll->nSize; i++ ) +// Fpga_NodeVecFree( p->vNodesAll->pArray[i]->vFanouts ); +// Fpga_NodeVecFree( p->pConst1->vFanouts ); + if ( p->vMapping ) + Fpga_NodeVecFree( p->vMapping ); + if ( p->vAnds ) + Fpga_NodeVecFree( p->vAnds ); + if ( p->vNodesAll ) + Fpga_NodeVecFree( p->vNodesAll ); + Extra_MmFixedStop( p->mmNodes ); + Extra_MmFixedStop( p->mmCuts ); + FREE( p->ppOutputNames ); + FREE( p->pInputArrivals ); + FREE( p->pInputs ); + FREE( p->pOutputs ); + FREE( p->pBins ); + FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Prints runtime statistics of the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_ManPrintTimeStats( Fpga_Man_t * p ) +{ + extern char * pNetName; + extern int TotalLuts; +// FILE * pTable; + + +/* + pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%s ", pNetName ); + fprintf( pTable, "%.0f ", p->fRequiredGlo ); +// fprintf( pTable, "%.0f ", p->fAreaGlo );//+ (float)nOutputInvs ); + fprintf( pTable, "%.0f ", (float)TotalLuts ); + fprintf( pTable, "%4.2f\n", (float)(p->timeTotal-p->timeToMap)/(float)(CLOCKS_PER_SEC) ); + fclose( pTable ); +*/ + +// printf( "N-canonical = %d. Matchings = %d. ", p->nCanons, p->nMatches ); +// printf( "Choice nodes = %d. Choices = %d.\n", p->nChoiceNodes, p->nChoices ); + PRT( "ToMap", p->timeToMap ); + PRT( "Cuts ", p->timeCuts ); + PRT( "Match", p->timeMatch ); + PRT( "Area ", p->timeRecover ); + PRT( "ToNet", p->timeToNet ); + PRT( "TOTAL", p->timeTotal ); + if ( p->time1 ) { PRT( "time1", p->time1 ); } + if ( p->time2 ) { PRT( "time2", p->time2 ); } +} + +/**Function************************************************************* + + Synopsis [Creates a new node.] + + Description [This procedure should be called to create the constant + node and the PI nodes first.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) +{ + Fpga_Node_t * pNode; + // create the node + pNode = (Fpga_Node_t *)Extra_MmFixedEntryFetch( p->mmNodes ); + memset( pNode, 0, sizeof(Fpga_Node_t) ); + // set very large required time + pNode->tRequired = FPGA_FLOAT_LARGE; + pNode->aEstFanouts = -1; + pNode->p1 = p1; + pNode->p2 = p2; + // set the number of this node + pNode->Num = p->nNodes++; + // place to store the fanouts +// pNode->vFanouts = Fpga_NodeVecAlloc( 5 ); + // store this node in the internal array + if ( pNode->Num >= 0 ) + Fpga_NodeVecPush( p->vNodesAll, pNode ); + else + pNode->fInv = 1; + // set the level of this node + if ( p1 ) + { +#ifdef FPGA_ALLOCATE_FANOUT + // create the fanout info + Fpga_NodeAddFaninFanout( Fpga_Regular(p1), pNode ); + Fpga_NodeAddFaninFanout( Fpga_Regular(p2), pNode ); +#endif + // compute the level + pNode->Level = 1 + FPGA_MAX(Fpga_Regular(p1)->Level, Fpga_Regular(p2)->Level); + pNode->fInv = Fpga_NodeIsSimComplement(p1) & Fpga_NodeIsSimComplement(p2); + } + // reference the inputs + if ( p1 ) Fpga_NodeRef(p1); + if ( p2 ) Fpga_NodeRef(p2); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Create the unique table of AND gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_TableCreate( Fpga_Man_t * pMan ) +{ + assert( pMan->pBins == NULL ); + pMan->nBins = Cudd_Prime(50000); + pMan->pBins = ALLOC( Fpga_Node_t *, pMan->nBins ); + memset( pMan->pBins, 0, sizeof(Fpga_Node_t *) * pMan->nBins ); + pMan->nNodes = 0; +} + +/**Function************************************************************* + + Synopsis [Looks up the AND2 node in the unique table.] + + Description [This procedure implements one-level hashing. All the nodes + are hashed by their children. If the node with the same children was already + created, it is returned by the call to this procedure. If it does not exist, + this procedure creates a new node with these children. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * pMan, Fpga_Node_t * p1, Fpga_Node_t * p2 ) +{ + Fpga_Node_t * pEnt; + unsigned Key; + + if ( p1 == p2 ) + return p1; + if ( p1 == Fpga_Not(p2) ) + return Fpga_Not(pMan->pConst1); + if ( Fpga_NodeIsConst(p1) ) + { + if ( p1 == pMan->pConst1 ) + return p2; + return Fpga_Not(pMan->pConst1); + } + if ( Fpga_NodeIsConst(p2) ) + { + if ( p2 == pMan->pConst1 ) + return p1; + return Fpga_Not(pMan->pConst1); + } + + if ( Fpga_Regular(p1)->Num > Fpga_Regular(p2)->Num ) + pEnt = p1, p1 = p2, p2 = pEnt; + + Key = Fpga_HashKey2( p1, p2, pMan->nBins ); + for ( pEnt = pMan->pBins[Key]; pEnt; pEnt = pEnt->pNext ) + if ( pEnt->p1 == p1 && pEnt->p2 == p2 ) + return pEnt; + // resize the table + if ( pMan->nNodes >= 2 * pMan->nBins ) + { + Fpga_TableResize( pMan ); + Key = Fpga_HashKey2( p1, p2, pMan->nBins ); + } + // create the new node + pEnt = Fpga_NodeCreate( pMan, p1, p2 ); + // add the node to the corresponding linked list in the table + pEnt->pNext = pMan->pBins[Key]; + pMan->pBins[Key] = pEnt; + return pEnt; +} + + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_TableResize( Fpga_Man_t * pMan ) +{ + Fpga_Node_t ** pBinsNew; + Fpga_Node_t * pEnt, * pEnt2; + int nBinsNew, Counter, i, clk; + unsigned Key; + +clk = clock(); + // get the new table size + nBinsNew = Cudd_Prime(2 * pMan->nBins); + // allocate a new array + pBinsNew = ALLOC( Fpga_Node_t *, nBinsNew ); + memset( pBinsNew, 0, sizeof(Fpga_Node_t *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < pMan->nBins; i++ ) + for ( pEnt = pMan->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; + pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL ) + { + Key = Fpga_HashKey2( pEnt->p1, pEnt->p2, nBinsNew ); + pEnt->pNext = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == pMan->nNodes - pMan->nInputs ); + if ( pMan->fVerbose ) + { +// printf( "Increasing the unique table size from %6d to %6d. ", pMan->nBins, nBinsNew ); +// PRT( "Time", clock() - clk ); + } + // replace the table and the parameters + free( pMan->pBins ); + pMan->pBins = pBinsNew; + pMan->nBins = nBinsNew; +} + + + +/**Function************************************************************* + + Synopsis [Elementary AND operation on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Node_t * Fpga_NodeAnd( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) +{ + Fpga_Node_t * pNode; + pNode = Fpga_TableLookup( p, p1, p2 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Elementary OR operation on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Node_t * Fpga_NodeOr( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) +{ + Fpga_Node_t * pNode; + pNode = Fpga_Not( Fpga_TableLookup( p, Fpga_Not(p1), Fpga_Not(p2) ) ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Elementary EXOR operation on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Node_t * Fpga_NodeExor( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) +{ + return Fpga_NodeMux( p, p1, Fpga_Not(p2), p2 ); +} + +/**Function************************************************************* + + Synopsis [Elementary MUX operation on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Node_t * Fpga_NodeMux( Fpga_Man_t * p, Fpga_Node_t * pC, Fpga_Node_t * pT, Fpga_Node_t * pE ) +{ + Fpga_Node_t * pAnd1, * pAnd2, * pRes; + pAnd1 = Fpga_TableLookup( p, pC, pT ); + pAnd2 = Fpga_TableLookup( p, Fpga_Not(pC), pE ); + pRes = Fpga_NodeOr( p, pAnd1, pAnd2 ); + return pRes; +} + + +/**Function************************************************************* + + Synopsis [Sets the node to be equivalent to the given one.] + + Description [This procedure is a work-around for the equivalence check. + Does not verify the equivalence. Use at the user's risk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeSetChoice( Fpga_Man_t * pMan, Fpga_Node_t * pNodeOld, Fpga_Node_t * pNodeNew ) +{ + pNodeNew->pNextE = pNodeOld->pNextE; + pNodeOld->pNextE = pNodeNew; + pNodeNew->pRepr = pNodeOld; +} + + + +/**Function************************************************************* + + Synopsis [Prints some interesting stats.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_ManStats( Fpga_Man_t * p ) +{ + FILE * pTable; + pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%s ", p->pFileName ); + fprintf( pTable, "%4d ", p->nInputs - p->nLatches ); + fprintf( pTable, "%4d ", p->nOutputs - p->nLatches ); + fprintf( pTable, "%4d ", p->nLatches ); + fprintf( pTable, "%7d ", p->vAnds->nSize ); + fprintf( pTable, "%7d ", Fpga_CutCountAll(p) ); + fprintf( pTable, "%2d\n", (int)p->fRequiredGlo ); + fclose( pTable ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/map/fpga/fpgaCut.c b/abc70930/src/map/fpga/fpgaCut.c new file mode 100644 index 00000000..a5505e72 --- /dev/null +++ b/abc70930/src/map/fpga/fpgaCut.c @@ -0,0 +1,1159 @@ +/**CFile**************************************************************** + + FileName [fpgaCut.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaCut.c,v 1.3 2004/07/06 04:55:57 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Fpga_CutTableStrutct_t Fpga_CutTable_t; +struct Fpga_CutTableStrutct_t +{ + Fpga_Cut_t ** pBins; // the table used for linear probing + int nBins; // the size of the table + int * pCuts; // the array of cuts currently stored + int nCuts; // the number of cuts currently stored + Fpga_Cut_t ** pArray; // the temporary array of cuts + Fpga_Cut_t ** pCuts1; // the temporary array of cuts + Fpga_Cut_t ** pCuts2; // the temporary array of cuts +}; + +// the largest number of cuts considered +//#define FPGA_CUTS_MAX_COMPUTE 500 +#define FPGA_CUTS_MAX_COMPUTE 2000 +// the largest number of cuts used +//#define FPGA_CUTS_MAX_USE 200 +#define FPGA_CUTS_MAX_USE 1000 + +// primes used to compute the hash key +static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 }; + +static int bit_count[256] = { + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 +}; + +#define FPGA_COUNT_ONES(u) (bit_count[(u)&255]+bit_count[((u)>>8)&255]+bit_count[((u)>>16)&255]+bit_count[(u)>>24]) + +static Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode ); +static void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode ); +static Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ); +static int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax ); +static Fpga_Cut_t * Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 ); +static int Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes ); +extern Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p ); +extern int Fpga_CutCountAll( Fpga_Man_t * pMan ); + +static void Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ); +static void Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ); +static void Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot ); + +static Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan ); +static void Fpga_CutTableStop( Fpga_CutTable_t * p ); +static unsigned Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes ); +static int Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ); +static Fpga_Cut_t * Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ); +static void Fpga_CutTableRestart( Fpga_CutTable_t * p ); + +static int Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 ); +static Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList ); +static int Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList ); +static Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts ); + + +// iterator through all the cuts of the list +#define Fpga_ListForEachCut( pList, pCut ) \ + for ( pCut = pList; \ + pCut; \ + pCut = pCut->pNext ) +#define Fpga_ListForEachCutSafe( pList, pCut, pCut2 ) \ + for ( pCut = pList, \ + pCut2 = pCut? pCut->pNext: NULL; \ + pCut; \ + pCut = pCut2, \ + pCut2 = pCut? pCut->pNext: NULL ) + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the cuts for each node in the object graph.] + + Description [The cuts are computed in one sweep over the mapping graph. + First, the elementary cuts, which include the node itself, are assigned + to the PI nodes. The internal nodes are considered in the DFS order. + Each node is two-input AND-gate. So to compute the cuts at a node, we + need to merge the sets of cuts of its two predecessors. The merged set + contains only unique cuts with the number of inputs equal to k or less. + Finally, the elementary cut, composed of the node itself, is added to + the set of cuts for the node. + + This procedure is pretty fast for 5-feasible cuts, but it dramatically + slows down on some "dense" networks when computing 6-feasible cuts. + The problem is that there are too many cuts in this case. We should + think how to heuristically trim the number of cuts in such cases, + to have reasonable runtime.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingCuts( Fpga_Man_t * p ) +{ + ProgressBar * pProgress; + Fpga_CutTable_t * pTable; + Fpga_Node_t * pNode; + int nCuts, nNodes, i; + int clk = clock(); + + // set the elementary cuts for the PI variables + assert( p->nVarsMax > 1 && p->nVarsMax < 11 ); + Fpga_MappingCreatePiCuts( p ); + + // compute the cuts for the internal nodes + nNodes = p->vAnds->nSize; + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + pTable = Fpga_CutTableStart( p ); + for ( i = 0; i < nNodes; i++ ) + { + Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." ); + pNode = p->vAnds->pArray[i]; + if ( !Fpga_NodeIsAnd( pNode ) ) + continue; + Fpga_CutCompute( p, pTable, pNode ); + } + Extra_ProgressBarStop( pProgress ); + Fpga_CutTableStop( pTable ); + + // report the stats + if ( p->fVerbose ) + { + nCuts = Fpga_CutCountAll(p); + printf( "Nodes = %6d. Total %d-cuts = %d. Cuts per node = %.1f. ", + p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes ); + PRT( "Time", clock() - clk ); + } + + // print the cuts for the first primary output +// Fpga_CutListPrint( p, Fpga_Regular(p->pOutputs[0]) ); +} + +/**Function************************************************************* + + Synopsis [Performs technology mapping for variable-size-LUTs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingCreatePiCuts( Fpga_Man_t * p ) +{ + Fpga_Cut_t * pCut; + int i; + + // set the elementary cuts for the PI variables + for ( i = 0; i < p->nInputs; i++ ) + { + pCut = Fpga_CutAlloc( p ); + pCut->nLeaves = 1; + pCut->ppLeaves[0] = p->pInputs[i]; + pCut->uSign = (1 << (i%31)); + p->pInputs[i]->pCuts = pCut; + p->pInputs[i]->pCutBest = pCut; + // set the input arrival times +// p->pInputs[i]->pCut[1]->tArrival = p->pInputArrivals[i]; + } +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode ) +{ + Fpga_Node_t * pTemp; + Fpga_Cut_t * pList, * pList1, * pList2; + Fpga_Cut_t * pCut; + int fTree = 0; + int fPivot1 = fTree && (Fpga_NodeReadRef(pNode->p1)>2); + int fPivot2 = fTree && (Fpga_NodeReadRef(pNode->p2)>2); + + // if the cuts are computed return them + if ( pNode->pCuts ) + return pNode->pCuts; + + // compute the cuts for the children + pList1 = Fpga_Regular(pNode->p1)->pCuts; + pList2 = Fpga_Regular(pNode->p2)->pCuts; + // merge the lists + pList = Fpga_CutMergeLists( p, pTable, pList1, pList2, + Fpga_IsComplement(pNode->p1), Fpga_IsComplement(pNode->p2), + fPivot1, fPivot2 ); + // if there are functionally equivalent nodes, union them with this list + assert( pList ); + // only add to the list of cuts if the node is a representative one + if ( pNode->pRepr == NULL ) + { + for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) + { + assert( pTemp->pCuts ); + pList = Fpga_CutUnionLists( pList, pTemp->pCuts ); + assert( pTemp->pCuts ); + pList = Fpga_CutSortCuts( p, pTable, pList ); + } + } + // add the new cut + pCut = Fpga_CutAlloc( p ); + pCut->nLeaves = 1; + pCut->ppLeaves[0] = pNode; + pCut->uSign = (1 << (pNode->Num%31)); + pCut->fLevel = (float)pCut->ppLeaves[0]->Level; + // append (it is important that the elementary cut is appended first) + pCut->pNext = pList; + // set at the node + pNode->pCuts = pCut; + // remove the dominated cuts +// Fpga_CutFilter( p, pNode ); + // set the phase correctly + if ( pNode->pRepr && Fpga_NodeComparePhase(pNode, pNode->pRepr) ) + { + Fpga_ListForEachCut( pNode->pCuts, pCut ) + pCut->Phase = 1; + } + + +/* + { + Fpga_Cut_t * pPrev; + int i, Counter = 0; + for ( pCut = pNode->pCuts->pNext, pPrev = pNode->pCuts; pCut; pCut = pCut->pNext ) + { + for ( i = 0; i < pCut->nLeaves; i++ ) + if ( pCut->ppLeaves[i]->Level >= pNode->Level ) + break; + if ( i != pCut->nLeaves ) + pPrev->pNext = pCut->pNext; + else + pPrev = pCut; + } + } + { + int i, Counter = 0;; + for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) + for ( i = 0; i < pCut->nLeaves; i++ ) + Counter += (pCut->ppLeaves[i]->Level >= pNode->Level); + if ( Counter ) + printf( " %d", Counter ); + } +*/ + + return pCut; +} + +/**Function************************************************************* + + Synopsis [Filter the cuts using dominance.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode ) +{ + Fpga_Cut_t * pTemp, * pPrev, * pCut, * pCut2; + int i, k, Counter; + + Counter = 0; + pPrev = pNode->pCuts; + Fpga_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 ) + { + // go through all the previous cuts up to pCut + for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext ) + { + // check if every node in pTemp is contained in pCut + for ( i = 0; i < pTemp->nLeaves; i++ ) + { + for ( k = 0; k < pCut->nLeaves; k++ ) + if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] ) + break; + if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut + break; + } + if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut + { + Counter++; + break; + } + } + if ( pTemp != pCut ) // pTemp contain pCut + { + pPrev->pNext = pCut->pNext; // skip pCut + // recycle pCut + Fpga_CutFree( p, pCut ); + } + else + pPrev = pCut; + } +// printf( "Dominated = %3d. \n", Counter ); +} + + +/**Function************************************************************* + + Synopsis [Merges two lists of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable, + Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ) +{ + Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES]; + Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL }; + Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; + int nNodes, Counter, i; + Fpga_Cut_t ** ppArray1, ** ppArray2, ** ppArray3; + int nCuts1, nCuts2, nCuts3, k, fComp3; + + ppArray1 = pTable->pCuts1; + ppArray2 = pTable->pCuts2; + nCuts1 = Fpga_CutList2Array( ppArray1, pList1 ); + nCuts2 = Fpga_CutList2Array( ppArray2, pList2 ); + if ( fPivot1 ) + nCuts1 = 1; + if ( fPivot2 ) + nCuts2 = 1; + // swap the lists based on their length + if ( nCuts1 > nCuts2 ) + { + ppArray3 = ppArray1; + ppArray1 = ppArray2; + ppArray2 = ppArray3; + + nCuts3 = nCuts1; + nCuts1 = nCuts2; + nCuts2 = nCuts3; + + fComp3 = fComp1; + fComp1 = fComp2; + fComp2 = fComp3; + } + // pList1 is shorter or equal length compared to pList2 + + // prepare the manager for the cut computation + Fpga_CutTableRestart( pTable ); + // go through the cut pairs + Counter = 0; +// for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext ) +// for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext ) + for ( i = 0; i < nCuts1; i++ ) + { + for ( k = 0; k <= i; k++ ) + { + pTemp1 = ppArray1[i]; + pTemp2 = ppArray2[k]; + + if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) + { + if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) + continue; + if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) + continue; + } + + // check if k-feasible cut exists + nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); + if ( nNodes == 0 ) + continue; + // consider the cut for possible addition to the set of new cuts + pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); + if ( pCut == NULL ) + continue; + // add data to the cut + pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); + pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); + // create the signature + pCut->uSign = pTemp1->uSign | pTemp2->uSign; + // add it to the corresponding list + pCut->pNext = pLists[pCut->nLeaves]; + pLists[pCut->nLeaves] = pCut; + // count this cut and quit if limit is reached + Counter++; + if ( Counter == FPGA_CUTS_MAX_COMPUTE ) + goto QUITS; + } + for ( k = 0; k < i; k++ ) + { + pTemp1 = ppArray1[k]; + pTemp2 = ppArray2[i]; + + if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) + { + if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) + continue; + if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) + continue; + } + + + // check if k-feasible cut exists + nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); + if ( nNodes == 0 ) + continue; + // consider the cut for possible addition to the set of new cuts + pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); + if ( pCut == NULL ) + continue; + // add data to the cut + pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); + pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); + // create the signature + pCut->uSign = pTemp1->uSign | pTemp2->uSign; + // add it to the corresponding list + pCut->pNext = pLists[pCut->nLeaves]; + pLists[pCut->nLeaves] = pCut; + // count this cut and quit if limit is reached + Counter++; + if ( Counter == FPGA_CUTS_MAX_COMPUTE ) + goto QUITS; + } + } + // consider the rest of them + for ( i = nCuts1; i < nCuts2; i++ ) + for ( k = 0; k < nCuts1; k++ ) + { + pTemp1 = ppArray1[k]; + pTemp2 = ppArray2[i]; + + if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) + { + if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) + continue; + if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) + continue; + if ( pTemp1->ppLeaves[2] != pTemp2->ppLeaves[2] ) + continue; + } + + + // check if k-feasible cut exists + nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); + if ( nNodes == 0 ) + continue; + // consider the cut for possible addition to the set of new cuts + pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); + if ( pCut == NULL ) + continue; + // add data to the cut + pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); + pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); + // create the signature + pCut->uSign = pTemp1->uSign | pTemp2->uSign; + // add it to the corresponding list + pCut->pNext = pLists[pCut->nLeaves]; + pLists[pCut->nLeaves] = pCut; + // count this cut and quit if limit is reached + Counter++; + if ( Counter == FPGA_CUTS_MAX_COMPUTE ) + goto QUITS; + } +QUITS : + // combine all the lists into one + pListNew = NULL; + ppListNew = &pListNew; + for ( i = 1; i <= p->nVarsMax; i++ ) + { + if ( pLists[i] == NULL ) + continue; + // find the last entry + for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; + pPrev = pCut, pCut = pCut->pNext ); + // connect these lists + *ppListNew = pLists[i]; + ppListNew = &pPrev->pNext; + } + *ppListNew = NULL; + // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE + pListNew = Fpga_CutSortCuts( p, pTable, pListNew ); + return pListNew; +} + + +/**Function************************************************************* + + Synopsis [Merges two lists of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_CutMergeLists2( Fpga_Man_t * p, Fpga_CutTable_t * pTable, + Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ) +{ + Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES]; + Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL }; + Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; + int nNodes, Counter, i; + + // prepare the manager for the cut computation + Fpga_CutTableRestart( pTable ); + // go through the cut pairs + Counter = 0; + for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext ) + for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext ) + { + // check if k-feasible cut exists + nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); + if ( nNodes == 0 ) + continue; + // consider the cut for possible addition to the set of new cuts + pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); + if ( pCut == NULL ) + continue; + // add data to the cut + pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); + pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); + // add it to the corresponding list + pCut->pNext = pLists[pCut->nLeaves]; + pLists[pCut->nLeaves] = pCut; + // count this cut and quit if limit is reached + Counter++; + if ( Counter == FPGA_CUTS_MAX_COMPUTE ) + goto QUITS; + } +QUITS : + // combine all the lists into one + pListNew = NULL; + ppListNew = &pListNew; + for ( i = 1; i <= p->nVarsMax; i++ ) + { + if ( pLists[i] == NULL ) + continue; + // find the last entry + for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; + pPrev = pCut, pCut = pCut->pNext ); + // connect these lists + *ppListNew = pLists[i]; + ppListNew = &pPrev->pNext; + } + *ppListNew = NULL; + // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE + pListNew = Fpga_CutSortCuts( p, pTable, pListNew ); + return pListNew; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [Returns the number of nodes in the resulting cut, or 0 if the + cut is infeasible. Returns the resulting nodes in the array ppNodes[].] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax ) +{ + Fpga_Node_t * pNodeTemp; + int nTotal, i, k, min, Counter; + unsigned uSign; + + // use quick prefiltering + uSign = pCut1->uSign | pCut2->uSign; + Counter = FPGA_COUNT_ONES(uSign); + if ( Counter > nNodesMax ) + return 0; +/* + // check the special case when at least of the cuts is the largest + if ( pCut1->nLeaves == nNodesMax ) + { + if ( pCut2->nLeaves == nNodesMax ) + { + // return 0 if the cuts are different + for ( i = 0; i < nNodesMax; i++ ) + if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] ) + return 0; + // return nNodesMax if they are the same + for ( i = 0; i < nNodesMax; i++ ) + ppNodes[i] = pCut1->ppLeaves[i]; + return nNodesMax; + } + else if ( pCut2->nLeaves == nNodesMax - 1 ) + { + // return 0 if the cuts are different + fMismatch = 0; + for ( i = 0; i < nNodesMax; i++ ) + if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] ) + { + if ( fMismatch == 1 ) + return 0; + fMismatch = 1; + } + // return nNodesMax if they are the same + for ( i = 0; i < nNodesMax; i++ ) + ppNodes[i] = pCut1->ppLeaves[i]; + return nNodesMax; + } + } + else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax ) + { + // return 0 if the cuts are different + fMismatch = 0; + for ( i = 0; i < nNodesMax; i++ ) + if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] ) + { + if ( fMismatch == 1 ) + return 0; + fMismatch = 1; + } + // return nNodesMax if they are the same + for ( i = 0; i < nNodesMax; i++ ) + ppNodes[i] = pCut2->ppLeaves[i]; + return nNodesMax; + } +*/ + // count the number of unique entries in pCut2 + nTotal = pCut1->nLeaves; + for ( i = 0; i < pCut2->nLeaves; i++ ) + { + // try to find this entry among the leaves of pCut1 + for ( k = 0; k < pCut1->nLeaves; k++ ) + if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] ) + break; + if ( k < pCut1->nLeaves ) // found + continue; + // we found a new entry to add + if ( nTotal == nNodesMax ) + return 0; + ppNodes[nTotal++] = pCut2->ppLeaves[i]; + } + // we know that the feasible cut exists + + // add the starting entries + for ( k = 0; k < pCut1->nLeaves; k++ ) + ppNodes[k] = pCut1->ppLeaves[k]; + + // selection-sort the entries + for ( i = 0; i < nTotal - 1; i++ ) + { + min = i; + for ( k = i+1; k < nTotal; k++ ) +// if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!) + if ( ppNodes[k]->Num < ppNodes[min]->Num ) + min = k; + pNodeTemp = ppNodes[i]; + ppNodes[i] = ppNodes[min]; + ppNodes[min] = pNodeTemp; + } + + return nTotal; +} + +/**Function************************************************************* + + Synopsis [Computes the union of the two lists of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 ) +{ + Fpga_Cut_t * pTemp, * pRoot; + // find the last cut in the first list + pRoot = pList1; + Fpga_ListForEachCut( pList1, pTemp ) + pRoot = pTemp; + // attach the non-trival part of the second cut to the end of the first + assert( pRoot->pNext == NULL ); + pRoot->pNext = pList2->pNext; + pList2->pNext = NULL; + return pList1; +} + + +/**Function************************************************************* + + Synopsis [Checks whether the given cut belongs to the list.] + + Description [This procedure takes most of the runtime in the cut + computation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes ) +{ + Fpga_Cut_t * pTemp; + int i; + for ( pTemp = pList; pTemp; pTemp = pTemp->pNext ) + { + for ( i = 0; i < nNodes; i++ ) + if ( pTemp->ppLeaves[i] != ppNodes[i] ) + break; + if ( i == nNodes ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Counts all the cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CutCountAll( Fpga_Man_t * pMan ) +{ + Fpga_Node_t * pNode; + Fpga_Cut_t * pCut; + int i, nCuts; + // go through all the nodes in the unique table of the manager + nCuts = 0; + for ( i = 0; i < pMan->nBins; i++ ) + for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) + for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) + if ( pCut->nLeaves > 1 ) // skip the elementary cuts + { +// Fpga_CutVolume( pCut ); + nCuts++; + } + return nCuts; +} + + +/**Function************************************************************* + + Synopsis [Clean the signatures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutsCleanSign( Fpga_Man_t * pMan ) +{ + Fpga_Node_t * pNode; + Fpga_Cut_t * pCut; + int i; + for ( i = 0; i < pMan->nBins; i++ ) + for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) + for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) + pCut->uSign = 0; +} + + + +/**Function************************************************************* + + Synopsis [Prints the cuts in the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ) +{ + Fpga_Cut_t * pTemp; + int Counter; + for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) + { + printf( "%2d : ", Counter + 1 ); + Fpga_CutPrint_( pMan, pTemp, pRoot ); + } +} + +/**Function************************************************************* + + Synopsis [Prints the cuts in the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ) +{ + Fpga_Cut_t * pTemp; + int Counter; + for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) + { + printf( "%2d : ", Counter + 1 ); + Fpga_CutPrint_( pMan, pTemp, pRoot ); + } +} + +/**Function************************************************************* + + Synopsis [Prints the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot ) +{ + int i; + printf( "(%3d) {", pRoot->Num ); + for ( i = 0; i < pMan->nVarsMax; i++ ) + if ( pCut->ppLeaves[i] ) + printf( " %3d", pCut->ppLeaves[i]->Num ); + printf( " }\n" ); +} + + + + + + + + +/**Function************************************************************* + + Synopsis [Starts the hash table to canonicize cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan ) +{ + Fpga_CutTable_t * p; + // allocate the table + p = ALLOC( Fpga_CutTable_t, 1 ); + memset( p, 0, sizeof(Fpga_CutTable_t) ); + p->nBins = Cudd_Prime( 10 * FPGA_CUTS_MAX_COMPUTE ); + p->pBins = ALLOC( Fpga_Cut_t *, p->nBins ); + memset( p->pBins, 0, sizeof(Fpga_Cut_t *) * p->nBins ); + p->pCuts = ALLOC( int, 2 * FPGA_CUTS_MAX_COMPUTE ); + p->pArray = ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); + p->pCuts1 = ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); + p->pCuts2 = ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutTableStop( Fpga_CutTable_t * p ) +{ + free( p->pCuts1 ); + free( p->pCuts2 ); + free( p->pArray ); + free( p->pBins ); + free( p->pCuts ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Computes the hash value of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes ) +{ + unsigned uRes; + int i; + uRes = 0; + for ( i = 0; i < nNodes; i++ ) + uRes += s_HashPrimes[i] * ppNodes[i]->Num; + return uRes; +} + +/**Function************************************************************* + + Synopsis [Looks up the table for the available cut.] + + Description [Returns -1 if the same cut is found. Returns the index + of the cell where the cut should be added, if it does not exist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ) +{ + Fpga_Cut_t * pCut; + unsigned Key; + int b, i; + + Key = Fpga_CutTableHash(ppNodes, nNodes) % p->nBins; + for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins ) + { + pCut = p->pBins[b]; + if ( pCut->nLeaves != nNodes ) + continue; + for ( i = 0; i < nNodes; i++ ) + if ( pCut->ppLeaves[i] != ppNodes[i] ) + break; + if ( i == nNodes ) + return -1; + } + return b; +} + + +/**Function************************************************************* + + Synopsis [Starts the hash table to canonicize cuts.] + + Description [Considers addition of the cut to the hash table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ) +{ + Fpga_Cut_t * pCut; + int Place, i; + // check the cut + Place = Fpga_CutTableLookup( p, ppNodes, nNodes ); + if ( Place == -1 ) + return NULL; + assert( nNodes > 0 ); + // create the new cut + pCut = Fpga_CutAlloc( pMan ); + pCut->nLeaves = nNodes; + pCut->fLevel = 0.0; + for ( i = 0; i < nNodes; i++ ) + { + pCut->ppLeaves[i] = ppNodes[i]; + pCut->fLevel += ppNodes[i]->Level; + } + pCut->fLevel /= nNodes; + // add the cut to the table + assert( p->pBins[Place] == NULL ); + p->pBins[Place] = pCut; + // add the cut to the new list + p->pCuts[ p->nCuts++ ] = Place; + return pCut; +} + +/**Function************************************************************* + + Synopsis [Prepares the table to be used with other cuts.] + + Description [Restarts the table by cleaning the info about cuts stored + when the previous node was considered.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutTableRestart( Fpga_CutTable_t * p ) +{ + int i; + for ( i = 0; i < p->nCuts; i++ ) + { + assert( p->pBins[ p->pCuts[i] ] ); + p->pBins[ p->pCuts[i] ] = NULL; + } + p->nCuts = 0; +} + + + +/**Function************************************************************* + + Synopsis [Compares the cuts by the number of leaves and then by delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 ) +{ + if ( (*pC1)->nLeaves < (*pC2)->nLeaves ) + return -1; + if ( (*pC1)->nLeaves > (*pC2)->nLeaves ) + return 1; +/* + if ( (*pC1)->fLevel > (*pC2)->fLevel ) + return -1; + if ( (*pC1)->fLevel < (*pC2)->fLevel ) + return 1; +*/ + return 0; +} + +/**Function************************************************************* + + Synopsis [Sorts the cuts by average arrival time.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList ) +{ + Fpga_Cut_t * pListNew; + int nCuts, i; + // move the cuts from the list into the array + nCuts = Fpga_CutList2Array( p->pCuts1, pList ); + assert( nCuts <= FPGA_CUTS_MAX_COMPUTE ); + // sort the cuts + qsort( (void *)p->pCuts1, nCuts, sizeof(void *), + (int (*)(const void *, const void *)) Fpga_CutSortCutsCompare ); + // move them back into the list + if ( nCuts > FPGA_CUTS_MAX_USE - 1 ) + { +// printf( "*" ); + // free the remaining cuts + for ( i = FPGA_CUTS_MAX_USE - 1; i < nCuts; i++ ) + Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] ); + // update the number of cuts + nCuts = FPGA_CUTS_MAX_USE - 1; + } + pListNew = Fpga_CutArray2List( p->pCuts1, nCuts ); + return pListNew; +} + +/**Function************************************************************* + + Synopsis [Moves the nodes from the list into the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList ) +{ + int i; + for ( i = 0; pList; pList = pList->pNext, i++ ) + pArray[i] = pList; + return i; +} + +/**Function************************************************************* + + Synopsis [Moves the nodes from the array into the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts ) +{ + Fpga_Cut_t * pListNew, ** ppListNew; + int i; + pListNew = NULL; + ppListNew = &pListNew; + for ( i = 0; i < nCuts; i++ ) + { + // connect these lists + *ppListNew = pArray[i]; + ppListNew = &pArray[i]->pNext; +//printf( " %d(%.2f)", pArray[i]->nLeaves, pArray[i]->fLevel ); + } +//printf( "\n" ); + + *ppListNew = NULL; + return pListNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/map/fpga/fpgaCutUtils.c b/abc70930/src/map/fpga/fpgaCutUtils.c new file mode 100644 index 00000000..e60a1dee --- /dev/null +++ b/abc70930/src/map/fpga/fpgaCutUtils.c @@ -0,0 +1,470 @@ +/**CFile**************************************************************** + + FileName [fpgaCutUtils.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaCutUtils.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p ) +{ + Fpga_Cut_t * pCut; + pCut = (Fpga_Cut_t *)Extra_MmFixedEntryFetch( p->mmCuts ); + memset( pCut, 0, sizeof(Fpga_Cut_t) ); + return pCut; +} + +/**Function************************************************************* + + Synopsis [Duplicates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_CutDup( Fpga_Man_t * p, Fpga_Cut_t * pCutOld ) +{ + Fpga_Cut_t * pCutNew; + int i; + pCutNew = Fpga_CutAlloc( p ); + pCutNew->pRoot = pCutOld->pRoot; + pCutNew->nLeaves = pCutOld->nLeaves; + for ( i = 0; i < pCutOld->nLeaves; i++ ) + pCutNew->ppLeaves[i] = pCutOld->ppLeaves[i]; + return pCutNew; +} + +/**Function************************************************************* + + Synopsis [Deallocates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutFree( Fpga_Man_t * p, Fpga_Cut_t * pCut ) +{ + if ( pCut ) + Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pCut ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutPrint( Fpga_Man_t * p, Fpga_Node_t * pRoot, Fpga_Cut_t * pCut ) +{ + int i; + printf( "CUT: Delay = %4.2f. Area = %4.2f. Nodes = %d -> {", + pCut->tArrival, pCut->aFlow, pRoot->Num ); + for ( i = 0; i < pCut->nLeaves; i++ ) + printf( " %d", pCut->ppLeaves[i]->Num ); + printf( " } \n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_CutCreateSimple( Fpga_Man_t * p, Fpga_Node_t * pNode ) +{ + Fpga_Cut_t * pCut; + pCut = Fpga_CutAlloc( p ); + pCut->pRoot = pNode; + pCut->nLeaves = 1; + pCut->ppLeaves[0] = pNode; + pCut->uSign = FPGA_SEQ_SIGN(pCut->ppLeaves[0]); + return pCut; +} + + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Fpga_CutGetRootArea( Fpga_Man_t * p, Fpga_Cut_t * pCut ) +{ + return p->pLutLib->pLutAreas[pCut->nLeaves]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_CutListAppend( Fpga_Cut_t * pSetAll, Fpga_Cut_t * pSets ) +{ + Fpga_Cut_t * pPrev, * pTemp; + if ( pSetAll == NULL ) + return pSets; + if ( pSets == NULL ) + return pSetAll; + // find the last one + for ( pTemp = pSets; pTemp; pTemp = pTemp->pNext ) + pPrev = pTemp; + // append all the end of the current set + assert( pPrev->pNext == NULL ); + pPrev->pNext = pSetAll; + return pSets; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutListRecycle( Fpga_Man_t * p, Fpga_Cut_t * pSetList, Fpga_Cut_t * pSave ) +{ + Fpga_Cut_t * pNext, * pTemp; + for ( pTemp = pSetList, pNext = pTemp? pTemp->pNext : NULL; + pTemp; + pTemp = pNext, pNext = pNext? pNext->pNext : NULL ) + if ( pTemp != pSave ) + Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pTemp ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CutListCount( Fpga_Cut_t * pSets ) +{ + Fpga_Cut_t * pTemp; + int i; + for ( i = 0, pTemp = pSets; pTemp; pTemp = pTemp->pNext, i++ ); + return i; +} + +#if 0 + +/**function************************************************************* + + synopsis [Removes the fanouts of the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +void Fpga_CutRemoveFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ) +{ + Fpga_NodeVec_t * vFanouts; + int i, k; + for ( i = 0; i < pCut->nLeaves; i++ ) + { + vFanouts = pCut->ppLeaves[i]->vFanouts; + for ( k = 0; k < vFanouts->nSize; k++ ) + if ( vFanouts->pArray[k] == pNode ) + break; + assert( k != vFanouts->nSize ); + for ( k++; k < vFanouts->nSize; k++ ) + vFanouts->pArray[k-1] = vFanouts->pArray[k]; + vFanouts->nSize--; + } +} + +/**function************************************************************* + + synopsis [Removes the fanouts of the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +void Fpga_CutInsertFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ) +{ + int i; + for ( i = 0; i < pCut->nLeaves; i++ ) + Fpga_NodeVecPush( pCut->ppLeaves[i]->vFanouts, pNode ); +} +#endif + +/**Function************************************************************* + + Synopsis [Computes the arrival time and the area flow of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) +{ + Fpga_Cut_t * pFaninCut; + int i; + pCut->tArrival = -FPGA_FLOAT_LARGE; + pCut->aFlow = pMan->pLutLib->pLutAreas[pCut->nLeaves]; + for ( i = 0; i < pCut->nLeaves; i++ ) + { + pFaninCut = pCut->ppLeaves[i]->pCutBest; + if ( pCut->tArrival < pFaninCut->tArrival ) + pCut->tArrival = pFaninCut->tArrival; + // if the fanout count is not set, assume it to be 1 + if ( pCut->ppLeaves[i]->nRefs == 0 ) + pCut->aFlow += pFaninCut->aFlow; + else +// pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->nRefs; + pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->aEstFanouts; + } + // use the first pin to compute the delay of the LUT + // (this mapper does not support the variable pin delay model) + pCut->tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves][0]; +} + + +/**function************************************************************* + + synopsis [Computes the area flow of the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Fpga_CutGetAreaFlow( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) +{ + Fpga_Cut_t * pCutFanin; + int i; + pCut->aFlow = pMan->pLutLib->pLutAreas[pCut->nLeaves]; + for ( i = 0; i < pCut->nLeaves; i++ ) + { + // get the cut implementing this phase of the fanin + pCutFanin = pCut->ppLeaves[i]->pCutBest; + assert( pCutFanin ); + pCut->aFlow += pCutFanin->aFlow / pCut->ppLeaves[i]->nRefs; + } + return pCut->aFlow; +} + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) +{ + float aResult, aResult2; + if ( pCut->nLeaves == 1 ) + return 0; + aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 ); + aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 ); + assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) ); + return aResult; +} + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) +{ + float aResult, aResult2; + if ( pCut->nLeaves == 1 ) + return 0; + aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 ); + aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 ); + assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) ); + return aResult; +} + +/**function************************************************************* + + synopsis [References the cut.] + + description [This procedure is similar to the procedure NodeReclaim.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Fpga_CutRef( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) +{ + Fpga_Node_t * pNodeChild; + float aArea; + int i; + + // deref the fanouts +// if ( fFanouts ) +// Fpga_CutInsertFanouts( pMan, pNode, pCut ); + + // start the area of this cut + aArea = pMan->pLutLib->pLutAreas[pCut->nLeaves]; + // go through the children + for ( i = 0; i < pCut->nLeaves; i++ ) + { + pNodeChild = pCut->ppLeaves[i]; + assert( pNodeChild->nRefs >= 0 ); + if ( pNodeChild->nRefs++ > 0 ) + continue; + if ( !Fpga_NodeIsAnd(pNodeChild) ) + continue; + aArea += Fpga_CutRef( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); + } + return aArea; +} + +/**function************************************************************* + + synopsis [Dereferences the cut.] + + description [This procedure is similar to the procedure NodeRecusiveDeref.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Fpga_CutDeref( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) +{ + Fpga_Node_t * pNodeChild; + float aArea; + int i; + + // deref the fanouts +// if ( fFanouts ) +// Fpga_CutRemoveFanouts( pMan, pNode, pCut ); + + // start the area of this cut + aArea = pMan->pLutLib->pLutAreas[pCut->nLeaves]; + // go through the children + for ( i = 0; i < pCut->nLeaves; i++ ) + { + pNodeChild = pCut->ppLeaves[i]; + assert( pNodeChild->nRefs > 0 ); + if ( --pNodeChild->nRefs > 0 ) + continue; + if ( !Fpga_NodeIsAnd(pNodeChild) ) + continue; + aArea += Fpga_CutDeref( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); + } + return aArea; +} + + +/**Function************************************************************* + + Synopsis [Sets the used cuts to be the currently selected ones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingSetUsedCuts( Fpga_Man_t * pMan ) +{ + int i; + for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) + if ( pMan->vNodesAll->pArray[i]->pCutOld ) + { + pMan->vNodesAll->pArray[i]->pCutBest = pMan->vNodesAll->pArray[i]->pCutOld; + pMan->vNodesAll->pArray[i]->pCutOld = NULL; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/fpga/fpgaFanout.c b/abc70930/src/map/fpga/fpgaFanout.c new file mode 100644 index 00000000..c28a8799 --- /dev/null +++ b/abc70930/src/map/fpga/fpgaFanout.c @@ -0,0 +1,141 @@ +/**CFile**************************************************************** + + FileName [fpgaFanout.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaFanout.c,v 1.1 2005/01/23 06:59:41 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +#ifdef MAP_ALLOCATE_FANOUT + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Add the fanout to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeAddFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanout ) +{ + Fpga_Node_t * pPivot; + + // pFanins is a fanin of pFanout + assert( !Fpga_IsComplement(pFanin) ); + assert( !Fpga_IsComplement(pFanout) ); + assert( Fpga_Regular(pFanout->p1) == pFanin || Fpga_Regular(pFanout->p2) == pFanin ); + + pPivot = pFanin->pFanPivot; + if ( pPivot == NULL ) + { + pFanin->pFanPivot = pFanout; + return; + } + + if ( Fpga_Regular(pPivot->p1) == pFanin ) + { + if ( Fpga_Regular(pFanout->p1) == pFanin ) + { + pFanout->pFanFanin1 = pPivot->pFanFanin1; + pPivot->pFanFanin1 = pFanout; + } + else // if ( Fpga_Regular(pFanout->p2) == pFanin ) + { + pFanout->pFanFanin2 = pPivot->pFanFanin1; + pPivot->pFanFanin1 = pFanout; + } + } + else // if ( Fpga_Regular(pPivot->p2) == pFanin ) + { + assert( Fpga_Regular(pPivot->p2) == pFanin ); + if ( Fpga_Regular(pFanout->p1) == pFanin ) + { + pFanout->pFanFanin1 = pPivot->pFanFanin2; + pPivot->pFanFanin2 = pFanout; + } + else // if ( Fpga_Regular(pFanout->p2) == pFanin ) + { + pFanout->pFanFanin2 = pPivot->pFanFanin2; + pPivot->pFanFanin2 = pFanout; + } + } +} + +/**Function************************************************************* + + Synopsis [Add the fanout to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeRemoveFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanoutToRemove ) +{ + Fpga_Node_t * pFanout, * pFanout2, ** ppFanList; + // start the linked list of fanouts + ppFanList = &pFanin->pFanPivot; + // go through the fanouts + Fpga_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 ) + { + // skip the fanout-to-remove + if ( pFanout == pFanoutToRemove ) + continue; + // add useful fanouts to the list + *ppFanList = pFanout; + ppFanList = Fpga_NodeReadNextFanoutPlace( pFanin, pFanout ); + } + *ppFanList = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the number of fanouts of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_NodeGetFanoutNum( Fpga_Node_t * pNode ) +{ + Fpga_Node_t * pFanout; + int Counter = 0; + Fpga_NodeForEachFanout( pNode, pFanout ) + Counter++; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/abc70930/src/map/fpga/fpgaGENERIC.c b/abc70930/src/map/fpga/fpgaGENERIC.c new file mode 100644 index 00000000..4483c215 --- /dev/null +++ b/abc70930/src/map/fpga/fpgaGENERIC.c @@ -0,0 +1,46 @@ +/**CFile**************************************************************** + + FileName [fpga__.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: fpga__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/fpga/fpgaInt.h b/abc70930/src/map/fpga/fpgaInt.h new file mode 100644 index 00000000..b93eacab --- /dev/null +++ b/abc70930/src/map/fpga/fpgaInt.h @@ -0,0 +1,388 @@ +/**CFile**************************************************************** + + FileName [fpgaInt.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Technology mapping for variable-size-LUT FPGAs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaInt.h,v 1.8 2004/09/30 21:18:10 satrajit Exp $] + +***********************************************************************/ + +#ifndef __FPGA_INT_H__ +#define __FPGA_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//#include "leaks.h" +#include +#include +#include +#include "extra.h" +#include "fpga.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// uncomment to have fanouts represented in the mapping graph +//#define FPGA_ALLOCATE_FANOUT 1 + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +// the maximum number of cut leaves (currently does not work for 7) +#define FPGA_MAX_LEAVES 6 + +// the bit masks +#define FPGA_MASK(n) ((~((unsigned)0)) >> (32-(n))) +#define FPGA_FULL (~((unsigned)0)) +#define FPGA_NO_VAR (-9999.0) +#define FPGA_NUM_BYTES(n) (((n)/16 + (((n)%16) > 0))*16) + +// maximum/minimum operators +#define FPGA_MIN(a,b) (((a) < (b))? (a) : (b)) +#define FPGA_MAX(a,b) (((a) > (b))? (a) : (b)) + +// the small and large numbers (min/max float are 1.17e-38/3.40e+38) +#define FPGA_FLOAT_LARGE ((float)1.0e+20) +#define FPGA_FLOAT_SMALL ((float)1.0e-20) +#define FPGA_INT_LARGE (10000000) + +// the macro to compute the signature +#define FPGA_SEQ_SIGN(p) (1 << (((unsigned)p)%31)); + +// internal macros to work with cuts +#define Fpga_CutIsComplement(p) (((int)((unsigned long) (p) & 01))) +#define Fpga_CutRegular(p) ((Fpga_Cut_t *)((unsigned long)(p) & ~01)) +#define Fpga_CutNot(p) ((Fpga_Cut_t *)((unsigned long)(p) ^ 01)) +#define Fpga_CutNotCond(p,c) ((Fpga_Cut_t *)((unsigned long)(p) ^ (c))) + +// the cut nodes +#define Fpga_SeqIsComplement( p ) (((int)((unsigned long) (p) & 01))) +#define Fpga_SeqRegular( p ) ((Fpga_Node_t *)((unsigned long)(p) & ~015)) +#define Fpga_SeqIndex( p ) ((((unsigned long)(p)) >> 1) & 07) +#define Fpga_SeqIndexCreate( p, Ind ) (((unsigned long)(p)) | (1 << (((unsigned)(Ind)) & 07))) + +// internal macros for referencing of nodes +#define Fpga_NodeReadRef(p) ((Fpga_Regular(p))->nRefs) +#define Fpga_NodeRef(p) ((Fpga_Regular(p))->nRefs++) + +// returns the complemented attribute of the node +#define Fpga_NodeIsSimComplement(p) (Fpga_IsComplement(p)? !(Fpga_Regular(p)->fInv) : (p)->fInv) + +// generating random unsigned (#define RAND_MAX 0x7fff) +#define FPGA_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) + +// outputs the runtime in seconds +#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// the mapping manager +struct Fpga_ManStruct_t_ +{ + // the mapping graph + Fpga_Node_t ** pBins; // the table of nodes hashed by their children + int nBins; // the size of the table + Fpga_Node_t ** pInputs; // the array of inputs + int nInputs; // the number of inputs + Fpga_Node_t ** pOutputs; // the array of outputs + int nOutputs; // the number of outputs + int nNodes; // the total number of nodes + int nLatches; // the number of latches in the circuit + Fpga_Node_t * pConst1; // the constant 1 node + Fpga_NodeVec_t * vNodesAll; // the nodes by number + Fpga_NodeVec_t * vAnds; // the nodes reachable from COs + Fpga_NodeVec_t * vMapping; // the nodes used in the current mapping + + // info about the original circuit + char * pFileName; // the file name + char ** ppOutputNames; // the primary output names + float * pInputArrivals;// the PI arrival times + + // mapping parameters + int nVarsMax; // the max number of variables + int fAreaRecovery; // the flag to use area flow as the first parameter + int fVerbose; // the verbosiness flag + int fSwitching; // minimize the switching activity (instead of area) + int fLatchPaths; // optimize latch paths for delay, other paths for area + int nTravIds; // the counter of traversal IDs + float DelayTarget; // the target required times + + // support of choice nodes + int nChoiceNodes; // the number of choice nodes + int nChoices; // the number of all choices + + int nCanons; + int nMatches; + + // the supergate library + Fpga_LutLib_t * pLutLib; // the current LUT library + + // the memory managers + Extra_MmFixed_t * mmNodes; // the memory manager for nodes + Extra_MmFixed_t * mmCuts; // the memory manager for cuts + + // resynthesis parameters + int fResynthesis; // the resynthesis flag + float fRequiredGlo; // the global required times + float fRequiredShift;// the shift of the required times + float fRequiredStart;// the starting global required times + float fRequiredGain; // the reduction in delay + float fAreaGlo; // the total area + float fAreaGain; // the reduction in area + float fEpsilon; // the epsilon used to compare floats + float fDelayWindow; // the delay window for delay-oriented resynthesis + float DelayLimit; // for resynthesis + float AreaLimit; // for resynthesis + float TimeLimit; // for resynthesis + + // runtime statistics + int timeToMap; // time to transfer to the mapping structure + int timeCuts; // time to compute k-feasible cuts + int timeTruth; // time to compute the truth table for each cut + int timeMatch; // time to perform matching for each node + int timeRecover; // time to perform area recovery + int timeToNet; // time to transfer back to the network + int timeTotal; // the total mapping time + int time1; // time to transfer to the mapping structure + int time2; // time to transfer to the mapping structure +}; + +// the LUT library +struct Fpga_LutLibStruct_t_ +{ + char * pName; // the name of the LUT library + int LutMax; // the maximum LUT size + int fVarPinDelays; // set to 1 if variable pin delays are specified + float pLutAreas[FPGA_MAX_LUTSIZE+1]; // the areas of LUTs + float pLutDelays[FPGA_MAX_LUTSIZE+1][FPGA_MAX_LUTSIZE+1];// the delays of LUTs +}; + +// the mapping node +struct Fpga_NodeStruct_t_ +{ + // general information about the node + Fpga_Node_t * pNext; // the next node in the hash table + Fpga_Node_t * pLevel; // the next node in the linked list by level + int Num; // the unique number of this node + int NumA; // the unique number of this node + short Num2; // the temporary number of this node + short nRefs; // the number of references (fanouts) of the given node + unsigned fMark0 : 1; // the mark used for traversals + unsigned fMark1 : 1; // the mark used for traversals + unsigned fInv : 1; // the complemented attribute for the equivalent nodes + unsigned Value : 2; // the value of the nodes + unsigned fUsed : 1; // the flag indicating that the node is used in the mapping + unsigned fTemp : 1; // unused + unsigned Level :11; // the level of the given node + unsigned uData :14; // used to mark the fanins, for which resynthesis was tried + int TravId; + + // the successors of this node + Fpga_Node_t * p1; // the first child + Fpga_Node_t * p2; // the second child + Fpga_Node_t * pNextE; // the next functionally equivalent node + Fpga_Node_t * pRepr; // the representative of the functionally equivalent class + +#ifdef FPGA_ALLOCATE_FANOUT + // representation of node's fanouts + Fpga_Node_t * pFanPivot; // the first fanout of this node + Fpga_Node_t * pFanFanin1; // the next fanout of p1 + Fpga_Node_t * pFanFanin2; // the next fanout of p2 +// Fpga_NodeVec_t * vFanouts; // the array of fanouts of the gate +#endif + + // the delay information + float tRequired; // the best area flow + float aEstFanouts; // the fanout estimation + float Switching; // the probability of switching + int LValue; // the l-value of the node + short nLatches1; // the number of latches on the first edge + short nLatches2; // the number of latches on the second edge + + // cut information + Fpga_Cut_t * pCutBest; // the best mapping + Fpga_Cut_t * pCutOld; // the old mapping + Fpga_Cut_t * pCuts; // mapping choices for the node (elementary comes first) + Fpga_Cut_t * pCutsN; // mapping choices for the node (elementary comes first) + + // misc information + char * pData0; // temporary storage for the corresponding network node +}; + +// the cuts used for matching +struct Fpga_CutStruct_t_ +{ + Fpga_Cut_t * pOne; // the father of this cut + Fpga_Cut_t * pTwo; // the mother of this cut + Fpga_Node_t * pRoot; // the root of the cut + Fpga_Node_t * ppLeaves[FPGA_MAX_LEAVES+1]; // the leaves of this cut + float fLevel; // the average level of the fanins + unsigned uSign; // signature for quick comparison + char fMark; // the mark to denote visited cut + char Phase; // the mark to denote complemented cut + char nLeaves; // the number of leaves of this cut + char nVolume; // the volume of this cut + float tArrival; // the arrival time + float aFlow; // the area flow of the cut + Fpga_Cut_t * pNext; // the pointer to the next cut in the list +}; + +// the vector of nodes +struct Fpga_NodeVecStruct_t_ +{ + Fpga_Node_t ** pArray; // the array of nodes + int nSize; // the number of entries in the array + int nCap; // the number of allocated entries +}; + +// getting hold of the next fanout of the node +#define Fpga_NodeReadNextFanout( pNode, pFanout ) \ + ( ( pFanout == NULL )? NULL : \ + ((Fpga_Regular((pFanout)->p1) == (pNode))? \ + (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) ) + +// getting hold of the place where the next fanout will be attached +#define Fpga_NodeReadNextFanoutPlace( pNode, pFanout ) \ + ( (Fpga_Regular((pFanout)->p1) == (pNode))? \ + &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 ) + +// iterator through the fanouts of the node +#define Fpga_NodeForEachFanout( pNode, pFanout ) \ + for ( pFanout = (pNode)->pFanPivot; pFanout; \ + pFanout = Fpga_NodeReadNextFanout(pNode, pFanout) ) + +// safe iterator through the fanouts of the node +#define Fpga_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \ + for ( pFanout = (pNode)->pFanPivot, \ + pFanout2 = Fpga_NodeReadNextFanout(pNode, pFanout); \ + pFanout; \ + pFanout = pFanout2, \ + pFanout2 = Fpga_NodeReadNextFanout(pNode, pFanout) ) + +static inline Fpga_FloatMoreThan( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 > Arg2 + p->fEpsilon; } +static inline Fpga_FloatLessThan( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 < Arg2 - p->fEpsilon; } +static inline Fpga_FloatEqual( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 > Arg2 - p->fEpsilon && Arg1 < Arg2 + p->fEpsilon; } + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== fpgaCut.c ===============================================================*/ +extern void Fpga_MappingCuts( Fpga_Man_t * p ); +extern void Fpga_MappingCreatePiCuts( Fpga_Man_t * p ); +extern int Fpga_CutCountAll( Fpga_Man_t * pMan ); +/*=== fpgaCutUtils.c ===============================================================*/ +extern Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p ); +extern Fpga_Cut_t * Fpga_CutDup( Fpga_Man_t * p, Fpga_Cut_t * pCutOld ); +extern void Fpga_CutFree( Fpga_Man_t * p, Fpga_Cut_t * pCut ); +extern void Fpga_CutPrint( Fpga_Man_t * p, Fpga_Node_t * pRoot, Fpga_Cut_t * pCut ); +extern Fpga_Cut_t * Fpga_CutCreateSimple( Fpga_Man_t * p, Fpga_Node_t * pNode ); +extern float Fpga_CutGetRootArea( Fpga_Man_t * p, Fpga_Cut_t * pCut ); +extern Fpga_Cut_t * Fpga_CutListAppend( Fpga_Cut_t * pSetAll, Fpga_Cut_t * pSets ); +extern void Fpga_CutListRecycle( Fpga_Man_t * p, Fpga_Cut_t * pSetList, Fpga_Cut_t * pSave ); +extern int Fpga_CutListCount( Fpga_Cut_t * pSets ); +extern void Fpga_CutRemoveFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ); +extern void Fpga_CutInsertFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ); +extern float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); +extern float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); +extern float Fpga_CutRef( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); +extern float Fpga_CutDeref( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); +extern float Fpga_CutGetAreaFlow( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); +extern void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); +/*=== fraigFanout.c =============================================================*/ +extern void Fpga_NodeAddFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanout ); +extern void Fpga_NodeRemoveFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanoutToRemove ); +extern int Fpga_NodeGetFanoutNum( Fpga_Node_t * pNode ); +/*=== fpgaLib.c ============================================================*/ +extern Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose ); +extern void Fpga_LutLibFree( Fpga_LutLib_t * p ); +extern void Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib ); +extern int Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib ); +/*=== fpgaMatch.c ===============================================================*/ +extern int Fpga_MappingMatches( Fpga_Man_t * p, int fDelayOriented ); +extern int Fpga_MappingMatchesArea( Fpga_Man_t * p ); +extern int Fpga_MappingMatchesSwitch( Fpga_Man_t * p ); +/*=== fpgaShow.c =============================================================*/ +extern void Fpga_MappingShow( Fpga_Man_t * pMan, char * pFileName ); +extern void Fpga_MappingShowNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppRoots, int nRoots, char * pFileName ); +/*=== fpgaSwitch.c =============================================================*/ +extern float Fpga_CutGetSwitchDerefed( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ); +extern float Fpga_CutRefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); +extern float Fpga_CutDerefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); +extern float Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeVec_t * vMapping ); +/*=== fpgaTime.c ===============================================================*/ +extern float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); +extern float Fpga_TimeCutComputeArrival_rec( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); +extern float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p ); +extern void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p, int fFirstTime ); +extern void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired ); +extern void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ); +extern void Fpga_TimePropagateArrival( Fpga_Man_t * p ); +/*=== fpgaVec.c =============================================================*/ +extern Fpga_NodeVec_t * Fpga_NodeVecAlloc( int nCap ); +extern void Fpga_NodeVecFree( Fpga_NodeVec_t * p ); +extern Fpga_Node_t ** Fpga_NodeVecReadArray( Fpga_NodeVec_t * p ); +extern int Fpga_NodeVecReadSize( Fpga_NodeVec_t * p ); +extern void Fpga_NodeVecGrow( Fpga_NodeVec_t * p, int nCapMin ); +extern void Fpga_NodeVecShrink( Fpga_NodeVec_t * p, int nSizeNew ); +extern void Fpga_NodeVecClear( Fpga_NodeVec_t * p ); +extern void Fpga_NodeVecPush( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ); +extern int Fpga_NodeVecPushUnique( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ); +extern Fpga_Node_t * Fpga_NodeVecPop( Fpga_NodeVec_t * p ); +extern void Fpga_NodeVecWriteEntry( Fpga_NodeVec_t * p, int i, Fpga_Node_t * Entry ); +extern Fpga_Node_t * Fpga_NodeVecReadEntry( Fpga_NodeVec_t * p, int i ); +extern void Fpga_NodeVecSortByLevel( Fpga_NodeVec_t * p ); +extern void Fpga_SortNodesByArrivalTimes( Fpga_NodeVec_t * p ); +extern void Fpga_NodeVecUnion( Fpga_NodeVec_t * p, Fpga_NodeVec_t * p1, Fpga_NodeVec_t * p2 ); +extern void Fpga_NodeVecPushOrder( Fpga_NodeVec_t * vNodes, Fpga_Node_t * pNode, int fIncreasing ); +extern void Fpga_NodeVecReverse( Fpga_NodeVec_t * vNodes ); + +/*=== fpgaUtils.c ===============================================================*/ +extern Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv ); +extern Fpga_NodeVec_t * Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv ); +extern int Fpga_CountLevels( Fpga_Man_t * pMan ); +extern float Fpga_MappingGetAreaFlow( Fpga_Man_t * p ); +extern float Fpga_MappingArea( Fpga_Man_t * pMan ); +extern float Fpga_MappingAreaTrav( Fpga_Man_t * pMan ); +extern float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan ); +extern void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p ); +extern void Fpga_MappingSetupTruthTables( unsigned uTruths[][2] ); +extern void Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax ); +extern void Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes, int fIncreasing ); +extern Fpga_NodeVec_t * Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels ); +extern Fpga_NodeVec_t * Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes ); +extern int Fpga_MappingMaxLevel( Fpga_Man_t * pMan ); +extern void Fpga_ManReportChoices( Fpga_Man_t * pMan ); +extern void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan ); + +/*=== CUDD package.c ===============================================================*/ +extern unsigned int Cudd_Prime( unsigned int p ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/map/fpga/fpgaLib.c b/abc70930/src/map/fpga/fpgaLib.c new file mode 100644 index 00000000..e74def32 --- /dev/null +++ b/abc70930/src/map/fpga/fpgaLib.c @@ -0,0 +1,249 @@ +/**CFile**************************************************************** + + FileName [fpgaLib.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Technology mapping for variable-size-LUT FPGAs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaLib.c,v 1.4 2005/01/23 06:59:41 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [APIs to access LUT library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_LutLibReadVarMax( Fpga_LutLib_t * p ) { return p->LutMax; } +float * Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p ) { return p->pLutAreas; } +float Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size ) { assert( Size <= p->LutMax ); return p->pLutAreas[Size]; } + +/**Function************************************************************* + + Synopsis [Reads the description of LUTs from the LUT library file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose ) +{ + char pBuffer[1000], * pToken; + Fpga_LutLib_t * p; + FILE * pFile; + int i, k; + + pFile = fopen( FileName, "r" ); + if ( pFile == NULL ) + { + printf( "Cannot open LUT library file \"%s\".\n", FileName ); + return NULL; + } + + p = ALLOC( Fpga_LutLib_t, 1 ); + memset( p, 0, sizeof(Fpga_LutLib_t) ); + p->pName = Extra_UtilStrsav( FileName ); + + i = 1; + while ( fgets( pBuffer, 1000, pFile ) != NULL ) + { + pToken = strtok( pBuffer, " \t\n" ); + if ( pToken == NULL ) + continue; + if ( pToken[0] == '#' ) + continue; + if ( i != atoi(pToken) ) + { + printf( "Error in the LUT library file \"%s\".\n", FileName ); + free( p ); + return NULL; + } + + // read area + pToken = strtok( NULL, " \t\n" ); + p->pLutAreas[i] = (float)atof(pToken); + + // read delays + k = 0; + while ( pToken = strtok( NULL, " \t\n" ) ) + p->pLutDelays[i][k++] = (float)atof(pToken); + + // check for out-of-bound + if ( k > i ) + { + printf( "LUT %d has too many pins (%d). Max allowed is %d.\n", i, k, i ); + return NULL; + } + + // check if var delays are specifies + if ( k > 1 ) + p->fVarPinDelays = 1; + + if ( i == FPGA_MAX_LUTSIZE ) + { + printf( "Skipping LUTs of size more than %d.\n", i ); + return NULL; + } + i++; + } + p->LutMax = i-1; + if ( p->LutMax > FPGA_MAX_LEAVES ) + { + p->LutMax = FPGA_MAX_LEAVES; + printf( "Warning: LUTs with more than %d input will not be used.\n", FPGA_MAX_LEAVES ); + } + + // check the library + if ( p->fVarPinDelays ) + { + for ( i = 1; i <= p->LutMax; i++ ) + for ( k = 0; k < i; k++ ) + { + if ( p->pLutDelays[i][k] <= 0.0 ) + printf( "Warning: Pin %d of LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", + k, i, p->pLutDelays[i][k] ); + if ( k && p->pLutDelays[i][k-1] > p->pLutDelays[i][k] ) + printf( "Warning: Pin %d of LUT %d has delay %f. Pin %d of LUT %d has delay %f. Pin delays should be in non-decreasing order. Technology mapping may not work correctly.\n", + k-1, i, p->pLutDelays[i][k-1], + k, i, p->pLutDelays[i][k] ); + } + } + else + { + for ( i = 1; i <= p->LutMax; i++ ) + { + if ( p->pLutDelays[i][0] <= 0.0 ) + printf( "Warning: LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", + k, i, p->pLutDelays[i][0] ); + } + } + + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the LUT library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p ) +{ + Fpga_LutLib_t * pNew; + pNew = ALLOC( Fpga_LutLib_t, 1 ); + *pNew = *p; + pNew->pName = Extra_UtilStrsav( pNew->pName ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Frees the LUT library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_LutLibFree( Fpga_LutLib_t * pLutLib ) +{ + if ( pLutLib == NULL ) + return; + FREE( pLutLib->pName ); + FREE( pLutLib ); +} + + +/**Function************************************************************* + + Synopsis [Prints the LUT library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib ) +{ + int i, k; + printf( "# The area/delay of k-variable LUTs:\n" ); + printf( "# k area delay\n" ); + if ( pLutLib->fVarPinDelays ) + { + for ( i = 1; i <= pLutLib->LutMax; i++ ) + { + printf( "%d %7.2f ", i, pLutLib->pLutAreas[i] ); + for ( k = 0; k < i; k++ ) + printf( " %7.2f", pLutLib->pLutDelays[i][k] ); + printf( "\n" ); + } + } + else + for ( i = 1; i <= pLutLib->LutMax; i++ ) + printf( "%d %7.2f %7.2f\n", i, pLutLib->pLutAreas[i], pLutLib->pLutDelays[i][0] ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the delays are discrete.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib ) +{ + float Delay; + int i; + for ( i = 1; i <= pLutLib->LutMax; i++ ) + { + Delay = pLutLib->pLutDelays[i][0]; + if ( ((float)((int)Delay)) != Delay ) + return 0; + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/fpga/fpgaMatch.c b/abc70930/src/map/fpga/fpgaMatch.c new file mode 100644 index 00000000..73fa1258 --- /dev/null +++ b/abc70930/src/map/fpga/fpgaMatch.c @@ -0,0 +1,794 @@ +/**CFile**************************************************************** + + FileName [fpgaMatch.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Technology mapping for variable-size-LUT FPGAs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaMatch.c,v 1.7 2004/09/30 21:18:10 satrajit Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Fpga_MatchNode( Fpga_Man_t * p, Fpga_Node_t * pNode, int fDelayOriented ); +static int Fpga_MatchNodeArea( Fpga_Man_t * p, Fpga_Node_t * pNode ); +static int Fpga_MatchNodeSwitch( Fpga_Man_t * p, Fpga_Node_t * pNode ); + +static Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * pFanout, Fpga_Node_t * pNodeNo ); +static int Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Finds the best delay assignment of LUTs.] + + Description [This procedure iterates through all the nodes + of the object graph reachable from the POs and assigns the best + match to each of them. If the flag fDelayOriented is set to 1, it + tries to minimize the arrival time and uses the area flow as a + tie-breaker. If the flag is set to 0, it considers all the cuts, + whose arrival times matches the required time at the node, and + minimizes the area flow using the arrival time as a tie-breaker. + + Before this procedure is called, the required times should be set + and the fanout counts should be computed. In the first iteration, + the required times are set to very large number (by NodeCreate) + and the fanout counts are set to the number of fanouts in the AIG. + In the following iterations, the required times are set by the + backward traversal, while the fanouts are estimated approximately. + + If the arrival times of the PI nodes are given, they should be + assigned to the PIs after the cuts are computed and before this + procedure is called for the first time.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MappingMatches( Fpga_Man_t * p, int fDelayOriented ) +{ + ProgressBar * pProgress; + Fpga_Node_t * pNode; + int i, nNodes; + + // assign the arrival times of the PIs + for ( i = 0; i < p->nInputs; i++ ) + p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i]; + + // match LUTs with nodes in the topological order + nNodes = p->vAnds->nSize; + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + for ( i = 0; i < nNodes; i++ ) + { + pNode = p->vAnds->pArray[i]; + if ( !Fpga_NodeIsAnd( pNode ) ) + continue; + // skip a secondary node + if ( pNode->pRepr ) + continue; + // match the node + Fpga_MatchNode( p, pNode, fDelayOriented ); + Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); + } + Extra_ProgressBarStop( pProgress ); +/* + if ( !fDelayOriented ) + { + float Area = 0.0; + for ( i = 0; i < p->nOutputs; i++ ) + { + printf( "%5.2f ", Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow ); + Area += Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow; + } + printf( "\nTotal = %5.2f\n", Area ); + } +*/ + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the best matching for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MatchNode( Fpga_Man_t * p, Fpga_Node_t * pNode, int fDelayOriented ) +{ + Fpga_Cut_t * pCut, * pCutBestOld; + int clk; + // make sure that at least one cut other than the trivial is present + if ( pNode->pCuts->pNext == NULL ) + { + printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); + return 0; + } + + // estimate the fanouts of the node + if ( pNode->aEstFanouts < 0 ) + pNode->aEstFanouts = (float)pNode->nRefs; + else + pNode->aEstFanouts = (float)((2.0 * pNode->aEstFanouts + pNode->nRefs) / 3.0); +// pNode->aEstFanouts = (float)pNode->nRefs; + + pCutBestOld = pNode->pCutBest; + pNode->pCutBest = NULL; + for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) + { + // compute the arrival time of the cut and its area flow +clk = clock(); + Fpga_CutGetParameters( p, pCut ); +//p->time2 += clock() - clk; + // drop the cut if it does not meet the required times + if ( Fpga_FloatMoreThan(p, pCut->tArrival, pNode->tRequired) ) + continue; + // if no cut is assigned, use the current one + if ( pNode->pCutBest == NULL ) + { + pNode->pCutBest = pCut; + continue; + } + // choose the best cut using one of the two criteria: + // (1) delay oriented mapping (first traversal), delay first, area-flow as a tie-breaker + // (2) area recovery (subsequent traversals), area-flow first, delay as a tie-breaker + if ( (fDelayOriented && + (Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival) || + Fpga_FloatEqual(p, pNode->pCutBest->tArrival, pCut->tArrival) && Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) )) || + (!fDelayOriented && + (Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || + Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival))) ) + { + pNode->pCutBest = pCut; + } + } + + // make sure the match is found + if ( pNode->pCutBest == NULL ) + { + if ( pCutBestOld == NULL ) + { +// printf( "\nError: Could not match a node in the object graph.\n" ); + return 0; + } + pNode->pCutBest = pCutBestOld; + } + return 1; +} + + + + + +/**Function************************************************************* + + Synopsis [Finds the best area assignment of LUTs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MappingMatchesArea( Fpga_Man_t * p ) +{ + ProgressBar * pProgress; + Fpga_Node_t * pNode; + int i, nNodes; + + // assign the arrival times of the PIs + for ( i = 0; i < p->nInputs; i++ ) + p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i]; + + // match LUTs with nodes in the topological order + nNodes = p->vAnds->nSize; + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + for ( i = 0; i < nNodes; i++ ) + { + pNode = p->vAnds->pArray[i]; + if ( !Fpga_NodeIsAnd( pNode ) ) + continue; + // skip a secondary node + if ( pNode->pRepr ) + continue; + // match the node + Fpga_MatchNodeArea( p, pNode ); + Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); + } + Extra_ProgressBarStop( pProgress ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Finds the best area assignment of LUTs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ) +{ + Fpga_Node_t * pNode; + int i; + + // match LUTs with nodes in the topological order + for ( i = 0; i < vNodes->nSize; i++ ) + { + pNode = vNodes->pArray[i]; + if ( !Fpga_NodeIsAnd( pNode ) ) + continue; + // skip a secondary node + if ( pNode->pRepr ) + continue; + // match the node + if ( !Fpga_MatchNodeArea( p, pNode ) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the best matching for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MatchNodeArea( Fpga_Man_t * p, Fpga_Node_t * pNode ) +{ + Fpga_Cut_t * pCut, * pCutBestOld; + float aAreaCutBest; + int clk; + // make sure that at least one cut other than the trivial is present + if ( pNode->pCuts->pNext == NULL ) + { + printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); + return 0; + } + + // remember the old cut + pCutBestOld = pNode->pCutBest; + // deref the old cut + if ( pNode->nRefs ) + aAreaCutBest = Fpga_CutDeref( p, pNode, pNode->pCutBest, 0 ); + + // search for a better cut + pNode->pCutBest = NULL; + for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) + { + // compute the arrival time of the cut and its area flow +clk = clock(); + pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut ); +//p->time2 += clock() - clk; + // drop the cut if it does not meet the required times + if ( Fpga_FloatMoreThan( p, pCut->tArrival, pNode->tRequired ) ) + continue; + // get the area of this cut + pCut->aFlow = Fpga_CutGetAreaDerefed( p, pCut ); + // if no cut is assigned, use the current one + if ( pNode->pCutBest == NULL ) + { + pNode->pCutBest = pCut; + continue; + } + // choose the best cut as follows: exact area first, delay as a tie-breaker + if ( Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || + Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival) ) + { + pNode->pCutBest = pCut; + } + } + + // make sure the match is found + if ( pNode->pCutBest == NULL ) + { + pNode->pCutBest = pCutBestOld; + // insert the new cut + if ( pNode->nRefs ) + pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 ); +// printf( "\nError: Could not match a node in the object graph.\n" ); + return 0; + } + + // insert the new cut + // make sure the area selected is not worse then the original area + if ( pNode->nRefs ) + { + pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 ); +// assert( pNode->pCutBest->aFlow <= aAreaCutBest ); +// assert( pNode->tRequired < FPGA_FLOAT_LARGE ); + } + return 1; +} + + + + +/**Function************************************************************* + + Synopsis [Finds the best area assignment of LUTs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MappingMatchesSwitch( Fpga_Man_t * p ) +{ + ProgressBar * pProgress; + Fpga_Node_t * pNode; + int i, nNodes; + + // assign the arrival times of the PIs + for ( i = 0; i < p->nInputs; i++ ) + p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i]; + + // match LUTs with nodes in the topological order + nNodes = p->vAnds->nSize; + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + for ( i = 0; i < nNodes; i++ ) + { + pNode = p->vAnds->pArray[i]; + if ( !Fpga_NodeIsAnd( pNode ) ) + continue; + // skip a secondary node + if ( pNode->pRepr ) + continue; + // match the node + Fpga_MatchNodeSwitch( p, pNode ); + Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); + } + Extra_ProgressBarStop( pProgress ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the best matching for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MatchNodeSwitch( Fpga_Man_t * p, Fpga_Node_t * pNode ) +{ + Fpga_Cut_t * pCut, * pCutBestOld; + float aAreaCutBest; + int clk; + // make sure that at least one cut other than the trivial is present + if ( pNode->pCuts->pNext == NULL ) + { + printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); + return 0; + } + + // remember the old cut + pCutBestOld = pNode->pCutBest; + // deref the old cut + if ( pNode->nRefs ) + aAreaCutBest = Fpga_CutDerefSwitch( p, pNode, pNode->pCutBest, 0 ); + + // search for a better cut + pNode->pCutBest = NULL; + for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) + { + // compute the arrival time of the cut and its area flow +clk = clock(); + pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut ); +//p->time2 += clock() - clk; + // drop the cut if it does not meet the required times + if ( Fpga_FloatMoreThan( p, pCut->tArrival, pNode->tRequired ) ) + continue; + // get the area of this cut + pCut->aFlow = Fpga_CutGetSwitchDerefed( p, pNode, pCut ); + // if no cut is assigned, use the current one + if ( pNode->pCutBest == NULL ) + { + pNode->pCutBest = pCut; + continue; + } + // choose the best cut as follows: exact area first, delay as a tie-breaker + if ( Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || + Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival) ) + { + pNode->pCutBest = pCut; + } + } + + // make sure the match is found + if ( pNode->pCutBest == NULL ) + { + pNode->pCutBest = pCutBestOld; + // insert the new cut + if ( pNode->nRefs ) + pNode->pCutBest->aFlow = Fpga_CutRefSwitch( p, pNode, pNode->pCutBest, 0 ); +// printf( "\nError: Could not match a node in the object graph.\n" ); + return 0; + } + + // insert the new cut + // make sure the area selected is not worse then the original area + if ( pNode->nRefs ) + { + pNode->pCutBest->aFlow = Fpga_CutRefSwitch( p, pNode, pNode->pCutBest, 0 ); + assert( pNode->pCutBest->aFlow <= aAreaCutBest + 0.001 ); +// assert( pNode->tRequired < FPGA_FLOAT_LARGE ); + } + return 1; +} + + +#if 0 +/**function************************************************************* + + synopsis [References the cut.] + + description [This procedure is similar to the procedure NodeReclaim.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +void Fpga_Experiment( Fpga_Man_t * p ) +{ + int Counter[10] = {0}; + Fpga_Node_t * pNode; + int i; + + for ( i = 0; i < p->nOutputs; i++ ) + { + pNode = Fpga_Regular(p->pOutputs[i]); + pNode->vFanouts = NULL; + } + + for ( i = 0; i < p->vAnds->nSize; i++ ) + { + pNode = p->vAnds->pArray[i]; + if ( !Fpga_NodeIsAnd( pNode ) ) + continue; + if ( pNode->vFanouts == NULL ) + continue; + if ( pNode->vFanouts->nSize >= 10 ) + continue; + Counter[pNode->vFanouts->nSize]++; + } + + printf( "Fanout stats: " ); + for ( i = 0; i < 10; i++ ) + printf( " %d=%d", i, Counter[i] ); + printf( "\n" ); + printf( "Area before = %4.2f.\n", Fpga_MappingArea(p) ); + + for ( i = 0; i < p->vAnds->nSize; i++ ) + { + Fpga_NodeVec_t * vNodesTfo; + float AreaBefore; + + pNode = p->vAnds->pArray[i]; + if ( !Fpga_NodeIsAnd( pNode ) ) + continue; + if ( pNode->vFanouts == NULL ) + continue; + if ( pNode->vFanouts->nSize != 1 && pNode->vFanouts->nSize != 2 && pNode->vFanouts->nSize != 3 ) + continue; + +// assert( pNode->nRefs > 0 ); + if ( pNode->nRefs == 0 ) + continue; + + AreaBefore = pNode->pCutBest->aFlow; + pNode->pCutBest->aFlow = FPGA_FLOAT_LARGE; + + Fpga_TimeComputeRequiredGlobal( p, 0 ); + + vNodesTfo = Fpga_CollectNodeTfo( p, pNode ); + if ( Fpga_MappingMatchesAreaArray( p, vNodesTfo ) == 0 ) + printf( "attempt failed\n" ); + else + printf( "attempt succeeded\n" ); + Fpga_NodeVecFree( vNodesTfo ); + + pNode->pCutBest->aFlow = AreaBefore; +// break; + } + printf( "Area after = %4.2f.\n", Fpga_MappingArea(p) ); +// printf( "AREA GAIN = %4.2f (%.2f %%)\n", GainTotal, 100.0 * GainTotal / Fpga_MappingArea(p) ); +} + + + +/**function************************************************************* + + synopsis [References the cut.] + + description [This procedure is similar to the procedure NodeReclaim.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +void Fpga_Experiment2( Fpga_Man_t * p ) +{ + int Counter[10] = {0}; + Fpga_Cut_t * ppCutsNew[10]; + Fpga_Cut_t * ppCutsOld[10]; + Fpga_Node_t * pFanout, * pNode; + float Gain, Loss, GainTotal, Area1, Area2; + int i, k; + + for ( i = 0; i < p->nOutputs; i++ ) + { + pNode = Fpga_Regular(p->pOutputs[i]); + pNode->vFanouts = NULL; + } + + for ( i = 0; i < p->vAnds->nSize; i++ ) + { + pNode = p->vAnds->pArray[i]; + if ( !Fpga_NodeIsAnd( pNode ) ) + continue; + if ( pNode->vFanouts == NULL ) + continue; + if ( pNode->vFanouts->nSize >= 10 ) + continue; + Counter[pNode->vFanouts->nSize]++; + } + + printf( "Fanout stats: " ); + for ( i = 0; i < 10; i++ ) + printf( " %d=%d", i, Counter[i] ); + printf( "\n" ); + printf( "Area before = %4.2f.\n", Fpga_MappingArea(p) ); + + GainTotal = 0; + for ( i = 0; i < p->vAnds->nSize; i++ ) + { + pNode = p->vAnds->pArray[i]; + if ( !Fpga_NodeIsAnd( pNode ) ) + continue; + if ( pNode->vFanouts == NULL ) + continue; + if ( pNode->vFanouts->nSize != 2 )//&& pNode->vFanouts->nSize != 2 && pNode->vFanouts->nSize != 3 ) + continue; + + assert( pNode->nRefs > 0 ); + + // for all fanouts, find the best cut without this node + for ( k = 0; k < pNode->vFanouts->nSize; k++ ) + { + pFanout = pNode->vFanouts->pArray[k]; + ppCutsOld[k] = pFanout->pCutBest; + ppCutsNew[k] = Fpga_MappingAreaWithoutNode( p, pFanout, pNode ); + if ( ppCutsNew[k] == NULL ) + break; + } + if ( k != pNode->vFanouts->nSize ) + { + printf( "Node %4d: Skipped.\n", pNode->Num ); + continue; + } + + + // compute the area after replacing all the cuts + Gain = 0; + for ( k = 0; k < pNode->vFanouts->nSize; k++ ) + { + pFanout = pNode->vFanouts->pArray[k]; + // deref old cut + Area1 = Fpga_MatchAreaDeref( p, ppCutsOld[k] ); + // assign new cut + pFanout->pCutBest = ppCutsNew[k]; + // ref new cut + Area2 = Fpga_MatchAreaRef( p, ppCutsNew[k] ); + // compute the gain + Gain += Area1 - Area2; + } + + printf( "%d ", pNode->nRefs ); + + // undo the whole thing + Loss = 0; + for ( k = 0; k < pNode->vFanouts->nSize; k++ ) + { + pFanout = pNode->vFanouts->pArray[k]; + // deref old cut + Area1 = Fpga_MatchAreaDeref( p, ppCutsNew[k] ); + // assign new cut + pFanout->pCutBest = ppCutsOld[k]; + // ref new cut + Area2 = Fpga_MatchAreaRef( p, ppCutsOld[k] ); + // compute the gain + Loss += Area2 - Area1; + } + assert( Gain == Loss ); + + + printf( "Node %4d: Fanouts = %d. Cut area = %4.2f. Gain = %4.2f.\n", + pNode->Num, pNode->nRefs, pNode->pCutBest->aFlow, Gain ); + + if ( Gain > 0 ) + GainTotal += Gain; + } + printf( "Area after = %4.2f.\n", Fpga_MappingArea(p) ); + printf( "AREA GAIN = %4.2f (%.2f %%)\n", GainTotal, 100.0 * GainTotal / Fpga_MappingArea(p) ); +} + + +/**function************************************************************* + + synopsis [Computes the loss of area when node is not allowed.] + + description [Returning FPGA_FLOAT_LARGE means it does not exist.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Node_t * pNodeNo ) +{ + Fpga_Cut_t * pCut, * pCutBestOld, * pCutRes; + float aAreaCutBest; + int i, clk; + // make sure that at least one cut other than the trivial is present + if ( pNode->pCuts->pNext == NULL ) + { + printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); + return 0; + } + + assert( pNode->nRefs > 0 ); + + // remember the old cut + pCutBestOld = pNode->pCutBest; + // deref the old cut + aAreaCutBest = Fpga_MatchAreaDeref( p, pNode->pCutBest ); + + // search for a better cut + pNode->pCutBest = NULL; + for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) + { + // compute the arrival time of the cut and its area flow +clk = clock(); + Fpga_MatchCutGetArrTime( p, pCut ); +//p->time2 += clock() - clk; + // drop the cut if it does not meet the required times + if ( pCut->tArrival > pNode->tRequired ) + continue; + + // skip the cut if it contains the no-node + for ( i = 0; i < pCut->nLeaves; i++ ) + if ( pCut->ppLeaves[i] == pNodeNo ) + break; + if ( i != pCut->nLeaves ) + continue; + + // get the area of this cut + pCut->aFlow = Fpga_MatchAreaCount( p, pCut ); + // if no cut is assigned, use the current one + if ( pNode->pCutBest == NULL ) + { + pNode->pCutBest = pCut; + continue; + } + // choose the best cut as follows: exact area first, delay as a tie-breaker + if ( pNode->pCutBest->aFlow > pCut->aFlow || + pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival ) + { + pNode->pCutBest = pCut; + } + } + + // make sure the match is found + if ( pNode->pCutBest == NULL ) + { + pNode->pCutBest = pCutBestOld; + // insert the new cut + pNode->pCutBest->aFlow = Fpga_MatchAreaRef( p, pNode->pCutBest ); + return NULL; + } + + pCutRes = pNode->pCutBest; + pNode->pCutBest = pCutBestOld; + + // insert the new cut + pNode->pCutBest->aFlow = Fpga_MatchAreaRef( p, pNode->pCutBest ); + + // make sure the area selected is not worse then the original area + assert( pNode->pCutBest->aFlow == aAreaCutBest ); + assert( pNode->tRequired < FPGA_FLOAT_LARGE ); + return pCutRes; +} + +#endif + + +/**function************************************************************* + + synopsis [Performs area minimization using a heuristic algorithm.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Fpga_FindBestNode( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes, Fpga_Node_t ** ppNode, Fpga_Cut_t ** ppCutBest ) +{ + Fpga_Node_t * pNode; + Fpga_Cut_t * pCut; + float Gain, CutArea1, CutArea2, CutArea3; + int i; + + Gain = 0; + for ( i = 0; i < vNodes->nSize; i++ ) + { + pNode = vNodes->pArray[i]; + // deref the current cut + CutArea1 = Fpga_CutDeref( p, pNode, pNode->pCutBest, 0 ); + + // ref all the cuts + for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) + { + if ( pCut == pNode->pCutBest ) + continue; + if ( pCut->tArrival > pNode->tRequired ) + continue; + + CutArea2 = Fpga_CutGetAreaDerefed( p, pCut ); + if ( Gain < CutArea1 - CutArea2 ) + { + *ppNode = pNode; + *ppCutBest = pCut; + Gain = CutArea1 - CutArea2; + } + } + // ref the old cut + CutArea3 = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 ); + assert( CutArea1 == CutArea3 ); + } + if ( Gain == 0 ) + printf( "Returning no gain.\n" ); + + return Gain; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/map/fpga/fpgaSwitch.c b/abc70930/src/map/fpga/fpgaSwitch.c new file mode 100644 index 00000000..c93e0de4 --- /dev/null +++ b/abc70930/src/map/fpga/fpgaSwitch.c @@ -0,0 +1,151 @@ +/**CFile**************************************************************** + + FileName [fpgaSwitch.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: fpgaSwitch.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Fpga_CutGetSwitchDerefed( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ) +{ + float aResult, aResult2; + aResult2 = Fpga_CutRefSwitch( pMan, pNode, pCut, 0 ); + aResult = Fpga_CutDerefSwitch( pMan, pNode, pCut, 0 ); +// assert( aResult == aResult2 ); + return aResult; +} + +/**function************************************************************* + + synopsis [References the cut.] + + description [This procedure is similar to the procedure NodeReclaim.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Fpga_CutRefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) +{ + Fpga_Node_t * pNodeChild; + float aArea; + int i; + // start the area of this cut + aArea = pNode->Switching; + if ( pCut->nLeaves == 1 ) + return aArea; + // go through the children + for ( i = 0; i < pCut->nLeaves; i++ ) + { + pNodeChild = pCut->ppLeaves[i]; + assert( pNodeChild->nRefs >= 0 ); + if ( pNodeChild->nRefs++ > 0 ) + continue; + aArea += Fpga_CutRefSwitch( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); + } + return aArea; +} + +/**function************************************************************* + + synopsis [Dereferences the cut.] + + description [This procedure is similar to the procedure NodeRecusiveDeref.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Fpga_CutDerefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) +{ + Fpga_Node_t * pNodeChild; + float aArea; + int i; + // start the area of this cut + aArea = pNode->Switching; + if ( pCut->nLeaves == 1 ) + return aArea; + // go through the children + for ( i = 0; i < pCut->nLeaves; i++ ) + { + pNodeChild = pCut->ppLeaves[i]; + assert( pNodeChild->nRefs > 0 ); + if ( --pNodeChild->nRefs > 0 ) + continue; + aArea += Fpga_CutDerefSwitch( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); + } + return aArea; +} + +/**Function************************************************************* + + Synopsis [Computes the array of mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeVec_t * vMapping ) +{ + Fpga_Node_t * pNode; + float Switch; + int i; + Switch = 0.0; + for ( i = 0; i < vMapping->nSize; i++ ) + { + pNode = vMapping->pArray[i]; + // at least one phase has the best cut assigned + assert( !Fpga_NodeIsAnd(pNode) || pNode->pCutBest != NULL ); + // at least one phase is used in the mapping + assert( pNode->nRefs > 0 ); + // compute the array due to the supergate + Switch += pNode->Switching; + } + // add buffer for each CO driven by a CI + for ( i = 0; i < pMan->nOutputs; i++ ) + if ( Fpga_NodeIsVar(pMan->pOutputs[i]) && !Fpga_IsComplement(pMan->pOutputs[i]) ) + Switch += pMan->pOutputs[i]->Switching; + return Switch; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/fpga/fpgaTime.c b/abc70930/src/map/fpga/fpgaTime.c new file mode 100644 index 00000000..879cad4d --- /dev/null +++ b/abc70930/src/map/fpga/fpgaTime.c @@ -0,0 +1,262 @@ +/**CFile**************************************************************** + + FileName [fpgaTime.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Technology mapping for variable-size-LUT FPGAs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaTime.c,v 1.1 2005/01/23 06:59:42 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the arrival times of the cut.] + + Description [Computes the maximum arrival time of the cut leaves and + adds the delay of the LUT.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) +{ + int i; + float tArrival; + tArrival = -FPGA_FLOAT_LARGE; + for ( i = 0; i < pCut->nLeaves; i++ ) + if ( tArrival < pCut->ppLeaves[i]->pCutBest->tArrival ) + tArrival = pCut->ppLeaves[i]->pCutBest->tArrival; + tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves][0]; + return tArrival; +} + +/**Function************************************************************* + + Synopsis [Computes the arrival times of the cut recursively.] + + Description [When computing the arrival time for the previously unused + cuts, their arrival time may be incorrect because their fanins have + incorrect arrival time. This procedure is called to fix this problem.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_TimeCutComputeArrival_rec( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) +{ + int i; + for ( i = 0; i < pCut->nLeaves; i++ ) + if ( pCut->ppLeaves[i]->nRefs == 0 ) + Fpga_TimeCutComputeArrival_rec( pMan, pCut->ppLeaves[i]->pCutBest ); + return Fpga_TimeCutComputeArrival( pMan, pCut ); +} + +/**Function************************************************************* + + Synopsis [Computes the maximum arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p ) +{ + float fRequired; + int i; + if ( p->fLatchPaths && p->nLatches == 0 ) + { + printf( "Delay optimization of latch path is not performed because there is no latches.\n" ); + p->fLatchPaths = 0; + } + // get the critical PO arrival time + fRequired = -FPGA_FLOAT_LARGE; + if ( p->fLatchPaths ) + { + for ( i = p->nOutputs - p->nLatches; i < p->nOutputs; i++ ) + { + if ( Fpga_NodeIsConst(p->pOutputs[i]) ) + continue; + fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); +// printf( " %5.1f", Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); + } +// printf( "Required latches = %5.1f\n", fRequired ); + } + else + { + for ( i = 0; i < p->nOutputs; i++ ) + { + if ( Fpga_NodeIsConst(p->pOutputs[i]) ) + continue; + fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); +// printf( " %5.1f", Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); + } +// printf( "Required outputs = %5.1f\n", fRequired ); + } + return fRequired; +} + +/**Function************************************************************* + + Synopsis [Computes the required times of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p, int fFirstTime ) +{ + p->fRequiredGlo = Fpga_TimeComputeArrivalMax( p ); + // update the required times according to the target + if ( p->DelayTarget != -1 ) + { + if ( p->fRequiredGlo > p->DelayTarget + p->fEpsilon ) + { + if ( fFirstTime ) + printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->DelayTarget ); + } + else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon ) + { + if ( fFirstTime ) + printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget ); + p->fRequiredGlo = p->DelayTarget; + } + } + Fpga_TimeComputeRequired( p, p->fRequiredGlo ); +} + +/**Function************************************************************* + + Synopsis [Computes the required times of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired ) +{ + int i; + // clean the required times and the fanout counts for all nodes + for ( i = 0; i < p->vAnds->nSize; i++ ) + p->vAnds->pArray[i]->tRequired = FPGA_FLOAT_LARGE; + // set the required times for the POs + if ( p->fLatchPaths ) + for ( i = p->nOutputs - p->nLatches; i < p->nOutputs; i++ ) + Fpga_Regular(p->pOutputs[i])->tRequired = fRequired; + else + for ( i = 0; i < p->nOutputs; i++ ) + Fpga_Regular(p->pOutputs[i])->tRequired = fRequired; + // collect nodes reachable from POs in the DFS order through the best cuts + Fpga_TimePropagateRequired( p, p->vMapping ); +/* + { + int Counter = 0; + for ( i = 0; i < p->vAnds->nSize; i++ ) + if ( p->vAnds->pArray[i]->tRequired > FPGA_FLOAT_LARGE - 100 ) + Counter++; + printf( "The number of nodes with large required times = %d.\n", Counter ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Computes the required times of the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ) +{ + Fpga_Node_t * pNode, * pChild; + float fRequired; + int i, k; + + // sorts the nodes in the decreasing order of levels +// Fpga_MappingSortByLevel( p, vNodes, 0 ); + // the nodes area already sorted in Fpga_MappingSetRefsAndArea() + + // go through the nodes in the reverse topological order + for ( k = 0; k < vNodes->nSize; k++ ) + { + pNode = vNodes->pArray[k]; + if ( !Fpga_NodeIsAnd(pNode) ) + continue; + // get the required time for children + fRequired = pNode->tRequired - p->pLutLib->pLutDelays[pNode->pCutBest->nLeaves][0]; + // update the required time of the children + for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) + { + pChild = pNode->pCutBest->ppLeaves[i]; + pChild->tRequired = FPGA_MIN( pChild->tRequired, fRequired ); + } + } +} + + + +/**Function************************************************************* + + Synopsis [Computes the required times of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_TimePropagateArrival( Fpga_Man_t * p ) +{ + Fpga_Node_t * pNode; + Fpga_Cut_t * pCut; + int i; + + // clean the required times and the fanout counts for all nodes + for ( i = 0; i < p->vAnds->nSize; i++ ) + { + pNode = p->vAnds->pArray[i]; + for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) + pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut ); + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/fpga/fpgaTruth.c b/abc70930/src/map/fpga/fpgaTruth.c new file mode 100644 index 00000000..e3eb487f --- /dev/null +++ b/abc70930/src/map/fpga/fpgaTruth.c @@ -0,0 +1,166 @@ +/**CFile**************************************************************** + + FileName [fpgaTruth.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Technology mapping for variable-size-LUT FPGAs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaTruth.c,v 1.4 2005/01/23 06:59:42 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" +#include "cudd.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Recursively derives the truth table for the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Fpga_TruthsCutBdd_rec( DdManager * dd, Fpga_Cut_t * pCut, Fpga_NodeVec_t * vVisited ) +{ + DdNode * bFunc, * bFunc0, * bFunc1; + assert( !Fpga_IsComplement(pCut) ); + // if the cut is visited, return the result + if ( pCut->uSign ) + return (DdNode *)pCut->uSign; + // compute the functions of the children + bFunc0 = Fpga_TruthsCutBdd_rec( dd, Fpga_CutRegular(pCut->pOne), vVisited ); Cudd_Ref( bFunc0 ); + bFunc0 = Cudd_NotCond( bFunc0, Fpga_CutIsComplement(pCut->pOne) ); + bFunc1 = Fpga_TruthsCutBdd_rec( dd, Fpga_CutRegular(pCut->pTwo), vVisited ); Cudd_Ref( bFunc1 ); + bFunc1 = Cudd_NotCond( bFunc1, Fpga_CutIsComplement(pCut->pTwo) ); + // get the function of the cut + bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, pCut->Phase ); + Cudd_RecursiveDeref( dd, bFunc0 ); + Cudd_RecursiveDeref( dd, bFunc1 ); + assert( pCut->uSign == 0 ); + pCut->uSign = (unsigned)bFunc; + // add this cut to the visited list + Fpga_NodeVecPush( vVisited, (Fpga_Node_t *)pCut ); + return bFunc; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table for one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut ) +{ + Fpga_NodeVec_t * vVisited; + DdNode * bFunc; + int i; + assert( pCut->nLeaves > 1 ); + // set the leaf variables + for ( i = 0; i < pCut->nLeaves; i++ ) + pCut->ppLeaves[i]->pCuts->uSign = (unsigned)Cudd_bddIthVar( dd, i ); + // recursively compute the function + vVisited = Fpga_NodeVecAlloc( 10 ); + bFunc = Fpga_TruthsCutBdd_rec( dd, pCut, vVisited ); Cudd_Ref( bFunc ); + // clean the intermediate BDDs + for ( i = 0; i < pCut->nLeaves; i++ ) + pCut->ppLeaves[i]->pCuts->uSign = 0; + for ( i = 0; i < vVisited->nSize; i++ ) + { + pCut = (Fpga_Cut_t *)vVisited->pArray[i]; + Cudd_RecursiveDeref( dd, (DdNode*)pCut->uSign ); + pCut->uSign = 0; + } +// printf( "%d ", vVisited->nSize ); + Fpga_NodeVecFree( vVisited ); + Cudd_Deref( bFunc ); + return bFunc; +} + + +/**Function************************************************************* + + Synopsis [Recursively derives the truth table for the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_CutVolume_rec( Fpga_Cut_t * pCut, Fpga_NodeVec_t * vVisited ) +{ + assert( !Fpga_IsComplement(pCut) ); + if ( pCut->fMark ) + return; + pCut->fMark = 1; + Fpga_CutVolume_rec( Fpga_CutRegular(pCut->pOne), vVisited ); + Fpga_CutVolume_rec( Fpga_CutRegular(pCut->pTwo), vVisited ); + Fpga_NodeVecPush( vVisited, (Fpga_Node_t *)pCut ); +} + +/**Function************************************************************* + + Synopsis [Derives the truth table for one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CutVolume( Fpga_Cut_t * pCut ) +{ + Fpga_NodeVec_t * vVisited; + int Volume, i; + assert( pCut->nLeaves > 1 ); + // set the leaf variables + for ( i = 0; i < pCut->nLeaves; i++ ) + pCut->ppLeaves[i]->pCuts->fMark = 1; + // recursively compute the function + vVisited = Fpga_NodeVecAlloc( 10 ); + Fpga_CutVolume_rec( pCut, vVisited ); + // clean the marks + for ( i = 0; i < pCut->nLeaves; i++ ) + pCut->ppLeaves[i]->pCuts->fMark = 0; + for ( i = 0; i < vVisited->nSize; i++ ) + { + pCut = (Fpga_Cut_t *)vVisited->pArray[i]; + pCut->fMark = 0; + } + Volume = vVisited->nSize; + printf( "%d ", Volume ); + Fpga_NodeVecFree( vVisited ); + return Volume; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/fpga/fpgaUtils.c b/abc70930/src/map/fpga/fpgaUtils.c new file mode 100644 index 00000000..b951fd8f --- /dev/null +++ b/abc70930/src/map/fpga/fpgaUtils.c @@ -0,0 +1,986 @@ +/**CFile**************************************************************** + + FileName [fpgaUtils.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Technology mapping for variable-size-LUT FPGAs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaUtils.c,v 1.3 2004/07/06 04:55:58 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define FPGA_CO_LIST_SIZE 5 + +static void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv ); +static void Fpga_MappingDfsCuts_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes ); +static int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 ); +static void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax ); +static void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes ); +static int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo ); +static Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan ); +static Fpga_Man_t * s_pMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv ) +{ + Fpga_NodeVec_t * vNodes;//, * vNodesCo; + Fpga_Node_t * pNode; + int i; + // collect the CO nodes by level +// vNodesCo = Fpga_MappingOrderCosByLevel( pMan ); + // start the array + vNodes = Fpga_NodeVecAlloc( 100 ); + // collect the PIs + for ( i = 0; i < pMan->nInputs; i++ ) + { + pNode = pMan->pInputs[i]; + Fpga_NodeVecPush( vNodes, pNode ); + pNode->fMark0 = 1; + } + // perform the traversal + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_MappingDfs_rec( Fpga_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv ); +// for ( i = vNodesCo->nSize - 1; i >= 0 ; i-- ) +// for ( pNode = vNodesCo->pArray[i]; pNode; pNode = (Fpga_Node_t *)pNode->pData0 ) +// Fpga_MappingDfs_rec( pNode, vNodes, fCollectEquiv ); + // clean the node marks + for ( i = 0; i < vNodes->nSize; i++ ) + vNodes->pArray[i]->fMark0 = 0; +// for ( i = 0; i < pMan->nOutputs; i++ ) +// Fpga_MappingUnmark_rec( Fpga_Regular(pMan->pOutputs[i]) ); +// Fpga_NodeVecFree( vNodesCo ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv ) +{ + assert( !Fpga_IsComplement(pNode) ); + if ( pNode->fMark0 ) + return; + // visit the transitive fanin + if ( Fpga_NodeIsAnd(pNode) ) + { + Fpga_MappingDfs_rec( Fpga_Regular(pNode->p1), vNodes, fCollectEquiv ); + Fpga_MappingDfs_rec( Fpga_Regular(pNode->p2), vNodes, fCollectEquiv ); + } + // visit the equivalent nodes + if ( fCollectEquiv && pNode->pNextE ) + Fpga_MappingDfs_rec( pNode->pNextE, vNodes, fCollectEquiv ); + // make sure the node is not visited through the equivalent nodes + assert( pNode->fMark0 == 0 ); + // mark the node as visited + pNode->fMark0 = 1; + // add the node to the list + Fpga_NodeVecPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv ) +{ + Fpga_NodeVec_t * vNodes; + int i; + // perform the traversal + vNodes = Fpga_NodeVecAlloc( 200 ); + for ( i = 0; i < nNodes; i++ ) + Fpga_MappingDfs_rec( ppNodes[i], vNodes, fEquiv ); + for ( i = 0; i < vNodes->nSize; i++ ) + vNodes->pArray[i]->fMark0 = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingGetAreaFlow( Fpga_Man_t * p ) +{ + float aFlowFlowTotal = 0; + int i; + for ( i = 0; i < p->nOutputs; i++ ) + { + if ( Fpga_NodeIsConst(p->pOutputs[i]) ) + continue; + aFlowFlowTotal += Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow; + } + return aFlowFlowTotal; +} + +/**Function************************************************************* + + Synopsis [Computes the area of the current mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingArea( Fpga_Man_t * pMan ) +{ + Fpga_Node_t * pNode; + float aTotal; + int i; + // perform the traversal + aTotal = 0; + for ( i = 0; i < pMan->vMapping->nSize; i++ ) + { + pNode = pMan->vMapping->pArray[i]; + aTotal += pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves]; + } + return aTotal; +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes ) +{ + float aArea; + int i; + assert( !Fpga_IsComplement(pNode) ); + if ( !Fpga_NodeIsAnd(pNode) ) + return 0; + if ( pNode->fMark0 ) + return 0; + assert( pNode->pCutBest != NULL ); + // visit the transitive fanin of the selected cut + aArea = 0; + for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) + aArea += Fpga_MappingArea_rec( pMan, pNode->pCutBest->ppLeaves[i], vNodes ); + // make sure the node is not visited through the fanin nodes + assert( pNode->fMark0 == 0 ); + // mark the node as visited + pNode->fMark0 = 1; + // add the node to the list + aArea += pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves]; + // add the node to the list + Fpga_NodeVecPush( vNodes, pNode ); + return aArea; +} + +/**Function************************************************************* + + Synopsis [Computes the area of the current mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingAreaTrav( Fpga_Man_t * pMan ) +{ + Fpga_NodeVec_t * vNodes; + float aTotal; + int i; + // perform the traversal + aTotal = 0; + vNodes = Fpga_NodeVecAlloc( 100 ); + for ( i = 0; i < pMan->nOutputs; i++ ) + aTotal += Fpga_MappingArea_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), vNodes ); + for ( i = 0; i < vNodes->nSize; i++ ) + vNodes->pArray[i]->fMark0 = 0; + Fpga_NodeVecFree( vNodes ); + return aTotal; +} + + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingSetRefsAndArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Node_t ** ppStore ) +{ + float aArea; + int i; + assert( !Fpga_IsComplement(pNode) ); + if ( pNode->nRefs++ ) + return 0; + if ( !Fpga_NodeIsAnd(pNode) ) + return 0; + assert( pNode->pCutBest != NULL ); + // store the node in the structure by level + pNode->pData0 = (char *)ppStore[pNode->Level]; + ppStore[pNode->Level] = pNode; + // visit the transitive fanin of the selected cut + aArea = pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves]; + for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) + aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode->pCutBest->ppLeaves[i], ppStore ); + return aArea; +} + +/**Function************************************************************* + + Synopsis [Sets the correct reference counts for the mapping.] + + Description [Collects the nodes in reverse topological order + and places in them in array pMan->vMapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan ) +{ + Fpga_Node_t * pNode, ** ppStore; + float aArea; + int i, LevelMax; + + // clean all references + for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) + pMan->vNodesAll->pArray[i]->nRefs = 0; + + // allocate place to store the nodes + LevelMax = Fpga_MappingMaxLevel( pMan ); + ppStore = ALLOC( Fpga_Node_t *, LevelMax + 1 ); + memset( ppStore, 0, sizeof(Fpga_Node_t *) * (LevelMax + 1) ); + + // collect nodes reachable from POs in the DFS order through the best cuts + aArea = 0; + for ( i = 0; i < pMan->nOutputs; i++ ) + { + pNode = Fpga_Regular(pMan->pOutputs[i]); + if ( pNode == pMan->pConst1 ) + continue; + aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode, ppStore ); + pNode->nRefs++; + } + + // reconnect the nodes in reverse topological order + pMan->vMapping->nSize = 0; + for ( i = LevelMax; i >= 0; i-- ) + for ( pNode = ppStore[i]; pNode; pNode = (Fpga_Node_t *)pNode->pData0 ) + Fpga_NodeVecPush( pMan->vMapping, pNode ); + free( ppStore ); + return aArea; +} + + +/**Function************************************************************* + + Synopsis [Compares the outputs by their arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 ) +{ + Fpga_Node_t * pNode1 = Fpga_Regular(*ppNode1); + Fpga_Node_t * pNode2 = Fpga_Regular(*ppNode2); + float Arrival1 = pNode1->pCutBest? pNode1->pCutBest->tArrival : 0; + float Arrival2 = pNode2->pCutBest? pNode2->pCutBest->tArrival : 0; + if ( Arrival1 < Arrival2 ) + return -1; + if ( Arrival1 > Arrival2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Finds given number of latest arriving COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax ) +{ + int nNodes, i, k, v; + assert( p->nOutputs >= nNodesMax ); + pNodes[0] = 0; + nNodes = 1; + for ( i = 1; i < p->nOutputs; i++ ) + { + for ( k = nNodes - 1; k >= 0; k-- ) + if ( Fpga_MappingCompareOutputDelay( &p->pOutputs[pNodes[k]], &p->pOutputs[i] ) >= 0 ) + break; + if ( k == nNodesMax - 1 ) + continue; + if ( nNodes < nNodesMax ) + nNodes++; + for ( v = nNodes - 1; v > k+1; v-- ) + pNodes[v] = pNodes[v-1]; + pNodes[k+1] = i; + } +} + +/**Function************************************************************* + + Synopsis [Prints a bunch of latest arriving outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p ) +{ + Fpga_Node_t * pNode; + int pSorted[FPGA_CO_LIST_SIZE]; + int fCompl, Limit, MaxNameSize, i; + + // determine the number of nodes to print + Limit = (p->nOutputs > FPGA_CO_LIST_SIZE)? FPGA_CO_LIST_SIZE : p->nOutputs; + + // determine the order + Fpga_MappingFindLatest( p, pSorted, Limit ); + + // determine max size of the node's name + MaxNameSize = 0; + for ( i = 0; i < Limit; i++ ) + if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) ) + MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]); + + // print the latest outputs + for ( i = 0; i < Limit; i++ ) + { + // get the i-th latest output + pNode = Fpga_Regular(p->pOutputs[pSorted[i]]); + fCompl = Fpga_IsComplement(p->pOutputs[pSorted[i]]); + // print out the best arrival time + printf( "Output %-*s : ", MaxNameSize + 3, p->ppOutputNames[pSorted[i]] ); + printf( "Delay = %8.2f ", (double)pNode->pCutBest->tArrival ); + if ( fCompl ) + printf( "NEG" ); + else + printf( "POS" ); + printf( "\n" ); + } +} + + +/**Function************************************************************* + + Synopsis [Sets up the truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingSetupTruthTables( unsigned uTruths[][2] ) +{ + int m, v; + // set up the truth tables + for ( m = 0; m < 32; m++ ) + for ( v = 0; v < 5; v++ ) + if ( m & (1 << v) ) + uTruths[v][0] |= (1 << m); + // make adjustments for the case of 6 variables + for ( v = 0; v < 5; v++ ) + uTruths[v][1] = uTruths[v][0]; + uTruths[5][0] = 0; + uTruths[5][1] = FPGA_FULL; +} + +/**Function************************************************************* + + Synopsis [Sets up the mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax ) +{ + if ( nVarsMax == 6 ) + uMask[0] = uMask[1] = FPGA_FULL; + else + { + uMask[0] = FPGA_MASK(1 << nVarsMax); + uMask[1] = 0; + } +} + +/**Function************************************************************* + + Synopsis [Verify one useful property.] + + Description [This procedure verifies one useful property. After + the FRAIG construction with choice nodes is over, each primary node + should have fanins that are primary nodes. The primary nodes is the + one that does not have pNode->pRepr set to point to another node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_ManCheckConsistency( Fpga_Man_t * p ) +{ + Fpga_Node_t * pNode; + Fpga_NodeVec_t * pVec; + int i; + pVec = Fpga_MappingDfs( p, 0 ); + for ( i = 0; i < pVec->nSize; i++ ) + { + pNode = pVec->pArray[i]; + if ( Fpga_NodeIsVar(pNode) ) + { + if ( pNode->pRepr ) + printf( "Primary input %d is a secondary node.\n", pNode->Num ); + } + else if ( Fpga_NodeIsConst(pNode) ) + { + if ( pNode->pRepr ) + printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); + } + else + { + if ( pNode->pRepr ) + printf( "Internal node %d is a secondary node.\n", pNode->Num ); + if ( Fpga_Regular(pNode->p1)->pRepr ) + printf( "Internal node %d has first fanin that is a secondary node.\n", pNode->Num ); + if ( Fpga_Regular(pNode->p2)->pRepr ) + printf( "Internal node %d has second fanin that is a secondary node.\n", pNode->Num ); + } + } + Fpga_NodeVecFree( pVec ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares the supergates by their level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CompareNodesByLevelDecreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 ) +{ + if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level ) + return -1; + if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Compares the supergates by their level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CompareNodesByLevelIncreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 ) +{ + if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level ) + return -1; + if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Orders the nodes in the decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes, int fIncreasing ) +{ + if ( fIncreasing ) + qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *), + (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelIncreasing ); + else + qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *), + (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelDecreasing ); +// assert( Fpga_CompareNodesByLevel( vNodes->pArray, vNodes->pArray + vNodes->nSize - 1 ) <= 0 ); +} + +/**Function************************************************************* + + Synopsis [Computes the limited DFS ordering for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels ) +{ + Fpga_NodeVec_t * vNodes; + int i; + // perform the traversal + vNodes = Fpga_NodeVecAlloc( 100 ); + Fpga_DfsLim_rec( pNode, nLevels, vNodes ); + for ( i = 0; i < vNodes->nSize; i++ ) + vNodes->pArray[i]->fMark0 = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes ) +{ + assert( !Fpga_IsComplement(pNode) ); + if ( pNode->fMark0 ) + return; + pNode->fMark0 = 1; + // visit the transitive fanin + Level--; + if ( Level > 0 && Fpga_NodeIsAnd(pNode) ) + { + Fpga_DfsLim_rec( Fpga_Regular(pNode->p1), Level, vNodes ); + Fpga_DfsLim_rec( Fpga_Regular(pNode->p2), Level, vNodes ); + } + // add the node to the list + Fpga_NodeVecPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Computes the limited DFS ordering for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_ManCleanData0( Fpga_Man_t * pMan ) +{ + int i; + for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) + pMan->vNodesAll->pArray[i]->pData0 = 0; +} + +/**Function************************************************************* + + Synopsis [Collects the TFO of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode ) +{ + Fpga_NodeVec_t * vVisited, * vTfo; + int i; + // perform the traversal + vVisited = Fpga_NodeVecAlloc( 100 ); + vTfo = Fpga_NodeVecAlloc( 100 ); + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_CollectNodeTfo_rec( Fpga_Regular(pMan->pOutputs[i]), pNode, vVisited, vTfo ); + for ( i = 0; i < vVisited->nSize; i++ ) + vVisited->pArray[i]->fMark0 = vVisited->pArray[i]->fMark1 = 0; + Fpga_NodeVecFree( vVisited ); + return vTfo; +} + +/**Function************************************************************* + + Synopsis [Collects the TFO of the node.] + + Description [Returns 1 if the node should be collected.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo ) +{ + int Ret1, Ret2; + assert( !Fpga_IsComplement(pNode) ); + // skip visited nodes + if ( pNode->fMark0 ) + return pNode->fMark1; + pNode->fMark0 = 1; + Fpga_NodeVecPush( vVisited, pNode ); + + // return the pivot node + if ( pNode == pPivot ) + { + pNode->fMark1 = 1; + return 1; + } + if ( pNode->Level < pPivot->Level ) + { + pNode->fMark1 = 0; + return 0; + } + // visit the transitive fanin + assert( Fpga_NodeIsAnd(pNode) ); + Ret1 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p1), pPivot, vVisited, vTfo ); + Ret2 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p2), pPivot, vVisited, vTfo ); + if ( Ret1 || Ret2 ) + { + pNode->fMark1 = 1; + Fpga_NodeVecPush( vTfo, pNode ); + } + else + pNode->fMark1 = 0; + return pNode->fMark1; +} + +/**Function************************************************************* + + Synopsis [Levelizes the nodes accessible from the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes ) +{ + Fpga_NodeVec_t * vLevels; + Fpga_Node_t ** ppNodes; + Fpga_Node_t * pNode; + int nNodes, nLevelsMax, i; + + // reassign the levels (this may be necessary for networks which choices) + ppNodes = vNodes->pArray; + nNodes = vNodes->nSize; + for ( i = 0; i < nNodes; i++ ) + { + pNode = ppNodes[i]; + if ( !Fpga_NodeIsAnd(pNode) ) + { + pNode->Level = 0; + continue; + } + pNode->Level = 1 + FPGA_MAX( Fpga_Regular(pNode->p1)->Level, Fpga_Regular(pNode->p2)->Level ); + } + + // get the max levels + nLevelsMax = 0; + for ( i = 0; i < pMan->nOutputs; i++ ) + nLevelsMax = FPGA_MAX( nLevelsMax, (int)Fpga_Regular(pMan->pOutputs[i])->Level ); + nLevelsMax++; + + // allocate storage for levels + vLevels = Fpga_NodeVecAlloc( nLevelsMax ); + for ( i = 0; i < nLevelsMax; i++ ) + Fpga_NodeVecPush( vLevels, NULL ); + + // go through the nodes and add them to the levels + for ( i = 0; i < nNodes; i++ ) + { + pNode = ppNodes[i]; + pNode->pLevel = NULL; + if ( !Fpga_NodeIsAnd(pNode) ) + continue; + // attach the node to this level + pNode->pLevel = Fpga_NodeVecReadEntry( vLevels, pNode->Level ); + Fpga_NodeVecWriteEntry( vLevels, pNode->Level, pNode ); + } + return vLevels; +} + +/**Function************************************************************* + + Synopsis [Sets up the mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MappingMaxLevel( Fpga_Man_t * pMan ) +{ + int nLevelMax, i; + nLevelMax = 0; + for ( i = 0; i < pMan->nOutputs; i++ ) + nLevelMax = nLevelMax > (int)Fpga_Regular(pMan->pOutputs[i])->Level? + nLevelMax : (int)Fpga_Regular(pMan->pOutputs[i])->Level; + return nLevelMax; +} + + +/**Function************************************************************* + + Synopsis [Analyses choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MappingUpdateLevel_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int fMaximum ) +{ + Fpga_Node_t * pTemp; + int Level1, Level2, LevelE; + assert( !Fpga_IsComplement(pNode) ); + if ( !Fpga_NodeIsAnd(pNode) ) + return pNode->Level; + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return pNode->Level; + pNode->TravId = pMan->nTravIds; + // compute levels of the children nodes + Level1 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p1), fMaximum ); + Level2 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p2), fMaximum ); + pNode->Level = 1 + FPGA_MAX( Level1, Level2 ); + if ( pNode->pNextE ) + { + LevelE = Fpga_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); + if ( fMaximum ) + { + if ( pNode->Level < (unsigned)LevelE ) + pNode->Level = LevelE; + } + else + { + if ( pNode->Level > (unsigned)LevelE ) + pNode->Level = LevelE; + } + // set the level of all equivalent nodes to be the same minimum + if ( pNode->pRepr == NULL ) // the primary node + for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) + pTemp->Level = pNode->Level; + } + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Resets the levels of the nodes in the choice graph.] + + Description [Makes the level of the choice nodes to be equal to the + maximum of the level of the nodes in the equivalence class. This way + sorting by level leads to the reverse topological order, which is + needed for the required time computation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan ) +{ + int i; + pMan->nTravIds++; + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 1 ); +} + +/**Function************************************************************* + + Synopsis [Reports statistics on choice nodes.] + + Description [The number of choice nodes is the number of primary nodes, + which has pNextE set to a pointer. The number of choices is the number + of entries in the equivalent-node lists of the primary nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_ManReportChoices( Fpga_Man_t * pMan ) +{ + Fpga_Node_t * pNode, * pTemp; + int nChoiceNodes, nChoices; + int i, LevelMax1, LevelMax2; + + // report the number of levels + LevelMax1 = Fpga_MappingMaxLevel( pMan ); + pMan->nTravIds++; + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 0 ); + LevelMax2 = Fpga_MappingMaxLevel( pMan ); + + // report statistics about choices + nChoiceNodes = nChoices = 0; + for ( i = 0; i < pMan->vAnds->nSize; i++ ) + { + pNode = pMan->vAnds->pArray[i]; + if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) + { // this is a choice node = the primary node that has equivalent nodes + nChoiceNodes++; + for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) + nChoices++; + } + } + if ( pMan->fVerbose ) + { + printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); + printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); + } +/* + { + FILE * pTable; + pTable = fopen( "stats_choice.txt", "a+" ); + fprintf( pTable, "%s ", pMan->pFileName ); + fprintf( pTable, "%4d ", LevelMax1 ); + fprintf( pTable, "%4d ", pMan->vAnds->nSize - pMan->nInputs ); + fprintf( pTable, "%4d ", LevelMax2 ); + fprintf( pTable, "%7d ", nChoiceNodes ); + fprintf( pTable, "%7d ", nChoices + nChoiceNodes ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Returns the array of CO nodes sorted by level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan ) +{ + Fpga_Node_t * pNode; + Fpga_NodeVec_t * vNodes; + int i, nLevels; + // get the largest level of a CO + nLevels = Fpga_MappingMaxLevel( pMan ); + // allocate the array of nodes + vNodes = Fpga_NodeVecAlloc( nLevels + 1 ); + for ( i = 0; i <= nLevels; i++ ) + Fpga_NodeVecPush( vNodes, NULL ); + // clean the marks + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0; + // put the nodes into the structure + for ( i = 0; i < pMan->nOutputs; i++ ) + { + pNode = Fpga_Regular(pMan->pOutputs[i]); + if ( pNode->fMark0 ) + continue; + pNode->fMark0 = 1; + pNode->pData0 = (char *)Fpga_NodeVecReadEntry( vNodes, pNode->Level ); + Fpga_NodeVecWriteEntry( vNodes, pNode->Level, pNode ); + } + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0; + return vNodes; + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/fpga/fpgaVec.c b/abc70930/src/map/fpga/fpgaVec.c new file mode 100644 index 00000000..70a4a7ac --- /dev/null +++ b/abc70930/src/map/fpga/fpgaVec.c @@ -0,0 +1,408 @@ +/**CFile**************************************************************** + + FileName [fpgaVec.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Technology mapping for variable-size-LUT FPGAs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaVec.c,v 1.3 2005/01/23 06:59:42 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_NodeVecAlloc( int nCap ) +{ + Fpga_NodeVec_t * p; + p = ALLOC( Fpga_NodeVec_t, 1 ); + if ( nCap > 0 && nCap < 16 ) + nCap = 16; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? ALLOC( Fpga_Node_t *, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeVecFree( Fpga_NodeVec_t * p ) +{ + FREE( p->pArray ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Node_t ** Fpga_NodeVecReadArray( Fpga_NodeVec_t * p ) +{ + return p->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_NodeVecReadSize( Fpga_NodeVec_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeVecGrow( Fpga_NodeVec_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = REALLOC( Fpga_Node_t *, p->pArray, nCapMin ); + p->nCap = nCapMin; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeVecShrink( Fpga_NodeVec_t * p, int nSizeNew ) +{ + assert( p->nSize >= nSizeNew ); + p->nSize = nSizeNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeVecClear( Fpga_NodeVec_t * p ) +{ + p->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeVecPush( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ) +{ + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Fpga_NodeVecGrow( p, 16 ); + else + Fpga_NodeVecGrow( p, 2 * p->nCap ); + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [Add the element while ensuring uniqueness.] + + Description [Returns 1 if the element was found, and 0 if it was new. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_NodeVecPushUnique( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return 1; + Fpga_NodeVecPush( p, Entry ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Node_t * Fpga_NodeVecPop( Fpga_NodeVec_t * p ) +{ + return p->pArray[--p->nSize]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeVecWriteEntry( Fpga_NodeVec_t * p, int i, Fpga_Node_t * Entry ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_Node_t * Fpga_NodeVecReadEntry( Fpga_NodeVec_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 ) +{ + int Level1 = Fpga_Regular(*pp1)->Level; + int Level2 = Fpga_Regular(*pp2)->Level; + if ( Level1 < Level2 ) + return -1; + if ( Level1 > Level2 ) + return 1; + if ( Fpga_Regular(*pp1)->Num < Fpga_Regular(*pp2)->Num ) + return -1; + if ( Fpga_Regular(*pp1)->Num > Fpga_Regular(*pp2)->Num ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeVecSortByLevel( Fpga_NodeVec_t * p ) +{ + qsort( (void *)p->pArray, p->nSize, sizeof(Fpga_Node_t *), + (int (*)(const void *, const void *)) Fpga_NodeVecCompareLevels ); +} + +/**Function************************************************************* + + Synopsis [Compares the arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_NodeVecCompareArrivals( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 ) +{ + if ( (*ppS1)->pCutBest->tArrival < (*ppS2)->pCutBest->tArrival ) + return -1; + if ( (*ppS1)->pCutBest->tArrival > (*ppS2)->pCutBest->tArrival ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Orders the nodes in the increasing order of the arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_SortNodesByArrivalTimes( Fpga_NodeVec_t * p ) +{ + qsort( (void *)p->pArray, p->nSize, sizeof(Fpga_Node_t *), + (int (*)(const void *, const void *)) Fpga_NodeVecCompareArrivals ); +// assert( Fpga_CompareNodesByLevel( p->pArray, p->pArray + p->nSize - 1 ) <= 0 ); +} + + +/**Function************************************************************* + + Synopsis [Computes the union of nodes in two arrays.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeVecUnion( Fpga_NodeVec_t * p, Fpga_NodeVec_t * p1, Fpga_NodeVec_t * p2 ) +{ + int i; + Fpga_NodeVecClear( p ); + for ( i = 0; i < p1->nSize; i++ ) + Fpga_NodeVecPush( p, p1->pArray[i] ); + for ( i = 0; i < p2->nSize; i++ ) + Fpga_NodeVecPush( p, p2->pArray[i] ); +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeVecPushOrder( Fpga_NodeVec_t * vNodes, Fpga_Node_t * pNode, int fIncreasing ) +{ + Fpga_Node_t * pNode1, * pNode2; + int i; + Fpga_NodeVecPush( vNodes, pNode ); + // find the place of the node + for ( i = vNodes->nSize-1; i > 0; i-- ) + { + pNode1 = vNodes->pArray[i ]; + pNode2 = vNodes->pArray[i-1]; + if ( fIncreasing && pNode1->pCutBest->tArrival >= pNode2->pCutBest->tArrival || + !fIncreasing && pNode1->pCutBest->tArrival <= pNode2->pCutBest->tArrival ) + break; + vNodes->pArray[i ] = pNode2; + vNodes->pArray[i-1] = pNode1; + } +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_NodeVecReverse( Fpga_NodeVec_t * vNodes ) +{ + Fpga_Node_t * pNode1, * pNode2; + int i; + for ( i = 0; i < vNodes->nSize/2; i++ ) + { + pNode1 = vNodes->pArray[i]; + pNode2 = vNodes->pArray[vNodes->nSize-1-i]; + vNodes->pArray[i] = pNode2; + vNodes->pArray[vNodes->nSize-1-i] = pNode1; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/map/fpga/module.make b/abc70930/src/map/fpga/module.make new file mode 100644 index 00000000..cc3a6573 --- /dev/null +++ b/abc70930/src/map/fpga/module.make @@ -0,0 +1,13 @@ +SRC += src/map/fpga/fpga.c \ + src/map/fpga/fpgaCore.c \ + src/map/fpga/fpgaCreate.c \ + src/map/fpga/fpgaCut.c \ + src/map/fpga/fpgaCutUtils.c \ + src/map/fpga/fpgaFanout.c \ + src/map/fpga/fpgaLib.c \ + src/map/fpga/fpgaMatch.c \ + src/map/fpga/fpgaSwitch.c \ + src/map/fpga/fpgaTime.c \ + src/map/fpga/fpgaTruth.c \ + src/map/fpga/fpgaUtils.c \ + src/map/fpga/fpgaVec.c diff --git a/abc70930/src/map/if/if.h b/abc70930/src/map/if/if.h new file mode 100644 index 00000000..706f8552 --- /dev/null +++ b/abc70930/src/map/if/if.h @@ -0,0 +1,386 @@ +/**CFile**************************************************************** + + FileName [if.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: if.h,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __IF_H__ +#define __IF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include "vec.h" +#include "mem.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// the maximum size of LUTs used for mapping (should be the same as FPGA_MAX_LUTSIZE defined in "fpga.h"!!!) +#define IF_MAX_LUTSIZE 32 +// the largest possible number of LUT inputs when funtionality of the LUTs are computed +#define IF_MAX_FUNC_LUTSIZE 15 +// a very large number +#define IF_INFINITY 100000000 +// the largest possible user cut cost +#define IF_COST_MAX ((1<<14)-1) + +// object types +typedef enum { + IF_NONE, // 0: non-existent object + IF_CONST1, // 1: constant 1 + IF_CI, // 2: combinational input + IF_CO, // 3: combinational output + IF_AND, // 4: AND node + IF_VOID // 5: unused object +} If_Type_t; + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct If_Man_t_ If_Man_t; +typedef struct If_Par_t_ If_Par_t; +typedef struct If_Lib_t_ If_Lib_t; +typedef struct If_Obj_t_ If_Obj_t; +typedef struct If_Cut_t_ If_Cut_t; +typedef struct If_Set_t_ If_Set_t; + +// parameters +struct If_Par_t_ +{ + // user-controlable paramters + int nLutSize; // the LUT size + int nCutsMax; // the max number of cuts + int nFlowIters; // the number of iterations of area recovery + int nAreaIters; // the number of iterations of area recovery + float DelayTarget; // delay target + int fPreprocess; // preprossing + int fArea; // area-oriented mapping + int fFancy; // a fancy feature + int fExpRed; // expand/reduce of the best cuts + int fLatchPaths; // reset timing on latch paths + int fSeqMap; // sequential mapping + int fVerbose; // the verbosity flag + // internal parameters + int fAreaOnly; // area only mode + int fTruth; // truth table computation enabled + int fUsePerm; // use permutation (delay info) + int fUseBdds; // use local BDDs as a cost function + int fUseSops; // use local SOPs as a cost function + int fUseCnfs; // use local CNFs as a cost function + int fUseMv; // use local MV-SOPs as a cost function + int nLatches; // the number of latches in seq mapping + int fLiftLeaves; // shift the leaves for seq mapping + If_Lib_t * pLutLib; // the LUT library + float * pTimesArr; // arrival times + float * pTimesReq; // required times + int (* pFuncCost) (If_Cut_t *); // procedure to compute the user's cost of a cut + int (* pFuncUser) (If_Man_t *, If_Obj_t *, If_Cut_t *); // procedure called for each cut when cut computation is finished + void * pReoMan; // reordering manager +}; + +// the LUT library +struct If_Lib_t_ +{ + char * pName; // the name of the LUT library + int LutMax; // the maximum LUT size + int fVarPinDelays; // set to 1 if variable pin delays are specified + float pLutAreas[IF_MAX_LUTSIZE+1]; // the areas of LUTs + float pLutDelays[IF_MAX_LUTSIZE+1][IF_MAX_LUTSIZE+1];// the delays of LUTs +}; + +// manager +struct If_Man_t_ +{ + // mapping parameters + If_Par_t * pPars; + // mapping nodes + If_Obj_t * pConst1; // the constant 1 node + Vec_Ptr_t * vCis; // the primary inputs + Vec_Ptr_t * vCos; // the primary outputs + Vec_Ptr_t * vObjs; // all objects + Vec_Ptr_t * vMapped; // objects used in the mapping + Vec_Ptr_t * vTemp; // temporary array + int nObjs[IF_VOID];// the number of objects by type + // various data + int nLevelMax; // the max number of AIG levels + float fEpsilon; // epsilon used for comparison + float RequiredGlo; // global required times + float RequiredGlo2; // global required times + float AreaGlo; // global area + int nNets; // the sum total of fanins of all LUTs in the mapping + int nCutsUsed; // the number of cuts currently used + int nCutsMerged; // the total number of cuts merged + unsigned * puTemp[4]; // used for the truth table computation + int SortMode; // one of the three sorting modes + int fNextRound; // set to 1 after the first round + int nChoices; // the number of choice nodes + // sequential mapping + Vec_Ptr_t * vLatchOrder; // topological ordering of latches + Vec_Int_t * vLags; // sequentail lags of all nodes + int nAttempts; // the number of attempts in binary search + int nMaxIters; // the maximum number of iterations + int Period; // the current value of the clock period (for seq mapping) + // memory management + int nTruthWords; // the size of the truth table if allocated + int nPermWords; // the size of the permutation array (in words) + int nObjBytes; // the size of the object + int nCutBytes; // the size of the cut + int nSetBytes; // the size of the cut set + Mem_Fixed_t * pMemObj; // memory manager for objects (entrysize = nEntrySize) + Mem_Fixed_t * pMemSet; // memory manager for sets of cuts (entrysize = nCutSize*(nCutsMax+1)) + If_Set_t * pMemCi; // memory for CI cutsets + If_Set_t * pMemAnd; // memory for AND cutsets + If_Set_t * pFreeList; // the list of free cutsets +}; + +// priority cut +struct If_Cut_t_ +{ + float Delay; // delay of the cut + float Area; // area (or area-flow) of the cut + float AveRefs; // the average number of leaf references + unsigned uSign; // cut signature + unsigned Cost : 14; // the user's cost of the cut + unsigned fCompl : 1; // the complemented attribute + unsigned fUser : 1; // using the user's area and delay + unsigned nLimit : 8; // the maximum number of leaves + unsigned nLeaves : 8; // the number of leaves + int * pLeaves; // array of fanins + char * pPerm; // permutation + unsigned * pTruth; // the truth table +}; + +// set of priority cut +struct If_Set_t_ +{ + short nCutsMax; // the max number of cuts + short nCuts; // the current number of cuts + If_Set_t * pNext; // next cutset in the free list + If_Cut_t ** ppCuts; // the array of pointers to the cuts +}; + +// node extension +struct If_Obj_t_ +{ + unsigned Type : 4; // object + unsigned fCompl0 : 1; // complemented attribute + unsigned fCompl1 : 1; // complemented attribute + unsigned fPhase : 1; // phase of the node + unsigned fRepr : 1; // representative of the equivalence class + unsigned fMark : 1; // multipurpose mark + unsigned fVisit : 1; // multipurpose mark + unsigned Level : 22; // logic level of the node + int Id; // integer ID + int nRefs; // the number of references + int nVisits; // the number of visits to this node + int nVisitsCopy; // the number of visits to this node + If_Obj_t * pFanin0; // the first fanin + If_Obj_t * pFanin1; // the second fanin + If_Obj_t * pEquiv; // the choice node + float EstRefs; // estimated reference counter + float Required; // required time of the onde + float LValue; // sequential arrival time of the node + void * pCopy; // used for object duplication + If_Set_t * pCutSet; // the pointer to the cutset + If_Cut_t CutBest; // the best cut selected +}; + +static inline If_Obj_t * If_Regular( If_Obj_t * p ) { return (If_Obj_t *)((unsigned long)(p) & ~01); } +static inline If_Obj_t * If_Not( If_Obj_t * p ) { return (If_Obj_t *)((unsigned long)(p) ^ 01); } +static inline If_Obj_t * If_NotCond( If_Obj_t * p, int c ) { return (If_Obj_t *)((unsigned long)(p) ^ (c)); } +static inline int If_IsComplement( If_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } + +static inline int If_ManCiNum( If_Man_t * p ) { return p->nObjs[IF_CI]; } +static inline int If_ManCoNum( If_Man_t * p ) { return p->nObjs[IF_CO]; } +static inline int If_ManAndNum( If_Man_t * p ) { return p->nObjs[IF_AND]; } +static inline int If_ManObjNum( If_Man_t * p ) { return Vec_PtrSize(p->vObjs); } + +static inline If_Obj_t * If_ManConst1( If_Man_t * p ) { return p->pConst1; } +static inline If_Obj_t * If_ManCi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCis, i ); } +static inline If_Obj_t * If_ManCo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCos, i ); } +static inline If_Obj_t * If_ManLi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCos, If_ManCoNum(p) - p->pPars->nLatches + i ); } +static inline If_Obj_t * If_ManLo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCis, If_ManCiNum(p) - p->pPars->nLatches + i ); } +static inline If_Obj_t * If_ManObj( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vObjs, i ); } + +static inline int If_ObjIsConst1( If_Obj_t * pObj ) { return pObj->Type == IF_CONST1; } +static inline int If_ObjIsCi( If_Obj_t * pObj ) { return pObj->Type == IF_CI; } +static inline int If_ObjIsCo( If_Obj_t * pObj ) { return pObj->Type == IF_CO; } +static inline int If_ObjIsPi( If_Obj_t * pObj ) { return If_ObjIsCi(pObj) && pObj->pFanin0 == NULL; } +static inline int If_ObjIsLatch( If_Obj_t * pObj ) { return If_ObjIsCi(pObj) && pObj->pFanin0 != NULL; } +static inline int If_ObjIsAnd( If_Obj_t * pObj ) { return pObj->Type == IF_AND; } + +static inline If_Obj_t * If_ObjFanin0( If_Obj_t * pObj ) { return pObj->pFanin0; } +static inline If_Obj_t * If_ObjFanin1( If_Obj_t * pObj ) { return pObj->pFanin1; } +static inline int If_ObjFaninC0( If_Obj_t * pObj ) { return pObj->fCompl0; } +static inline int If_ObjFaninC1( If_Obj_t * pObj ) { return pObj->fCompl1; } +static inline void * If_ObjCopy( If_Obj_t * pObj ) { return pObj->pCopy; } +static inline void If_ObjSetCopy( If_Obj_t * pObj, void * pCopy ) { pObj->pCopy = pCopy; } +static inline void If_ObjSetChoice( If_Obj_t * pObj, If_Obj_t * pEqu ) { pObj->pEquiv = pEqu; } + +static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj ) { return &pObj->CutBest; } +static inline unsigned If_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId % 31)); } + +static inline float If_ObjArrTime( If_Obj_t * pObj ) { return If_ObjCutBest(pObj)->Delay; } +static inline void If_ObjSetArrTime( If_Obj_t * pObj, float ArrTime ) { If_ObjCutBest(pObj)->Delay = ArrTime; } + +static inline float If_ObjLValue( If_Obj_t * pObj ) { return pObj->LValue; } +static inline void If_ObjSetLValue( If_Obj_t * pObj, float LValue ) { pObj->LValue = LValue; } + +static inline void * If_CutData( If_Cut_t * pCut ) { return *(void **)pCut; } +static inline void If_CutSetData( If_Cut_t * pCut, void * pData ) { *(void **)pCut = pData; } + +static inline int If_CutLeaveNum( If_Cut_t * pCut ) { return pCut->nLeaves; } +static inline unsigned * If_CutTruth( If_Cut_t * pCut ) { return pCut->pTruth; } +static inline int If_CutTruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 1 : (1 << (nVarsMax - 5)); } +static inline int If_CutPermWords( int nVarsMax ) { return nVarsMax / sizeof(int) + ((nVarsMax % sizeof(int)) > 0); } + +static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { return pCut->fUser? (float)pCut->Cost : (p->pPars->pLutLib? p->pPars->pLutLib->pLutAreas[pCut->nLeaves] : (float)1.0); } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IF_MIN(a,b) (((a) < (b))? (a) : (b)) +#define IF_MAX(a,b) (((a) > (b))? (a) : (b)) + +// the small and large numbers (min/max float are 1.17e-38/3.40e+38) +#define IF_FLOAT_LARGE ((float)1.0e+20) +#define IF_FLOAT_SMALL ((float)1.0e-20) +#define IF_INT_LARGE (10000000) + +// iterator over the primary inputs +#define If_ManForEachCi( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vCis, pObj, i ) +// iterator over the primary outputs +#define If_ManForEachCo( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vCos, pObj, i ) +// iterator over the primary inputs +#define If_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntryStop( p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatches ) +// iterator over the primary outputs +#define If_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntryStop( p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatches ) +// iterator over the latches +#define If_ManForEachLatchInput( p, pObj, i ) \ + Vec_PtrForEachEntryStart( p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatches ) +#define If_ManForEachLatchOutput( p, pObj, i ) \ + Vec_PtrForEachEntryStart( p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatches ) +// iterator over all objects, including those currently not used +#define If_ManForEachObj( p, pObj, i ) \ + Vec_PtrForEachEntry( p->vObjs, pObj, i ) +// iterator over logic nodes +#define If_ManForEachNode( p, pObj, i ) \ + If_ManForEachObj( p, pObj, i ) if ( pObj->Type != IF_AND ) {} else +// iterator over cuts of the node +#define If_ObjForEachCut( pObj, pCut, i ) \ + for ( i = 0; (i < (pObj)->pCutSet->nCuts) && ((pCut) = (pObj)->pCutSet->ppCuts[i]); i++ ) +// iterator over the leaves of the cut +#define If_CutForEachLeaf( p, pCut, pLeaf, i ) \ + for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i++ ) +#define If_CutForEachLeafReverse( p, pCut, pLeaf, i ) \ + for ( i = (int)(pCut)->nLeaves - 1; (i >= 0) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i-- ) +//#define If_CutForEachLeaf( p, pCut, pLeaf, i ) \ +// for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, p->pPars->fLiftLeaves? (pCut)->pLeaves[i] >> 8 : (pCut)->pLeaves[i])); i++ ) +// iterator over the leaves of the sequential cut +#define If_CutForEachLeafSeq( p, pCut, pLeaf, Shift, i ) \ + for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i] >> 8)) && (((Shift) = ((pCut)->pLeaves[i] & 255)) >= 0); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== ifCore.c ===========================================================*/ +extern int If_ManPerformMapping( If_Man_t * p ); +extern int If_ManPerformMappingComb( If_Man_t * p ); +/*=== ifCut.c ============================================================*/ +extern float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut, int nLevels ); +extern float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut, int nLevels ); +extern float If_CutDeref( If_Man_t * p, If_Cut_t * pCut, int nLevels ); +extern float If_CutRef( If_Man_t * p, If_Cut_t * pCut, int nLevels ); +extern void If_CutPrint( If_Man_t * p, If_Cut_t * pCut ); +extern void If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut ); +extern float If_CutFlow( If_Man_t * p, If_Cut_t * pCut ); +extern float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut ); +extern int If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut ); +extern void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ); +extern int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut ); +extern void If_CutLift( If_Cut_t * pCut ); +extern void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc ); +extern void If_ManSortCuts( If_Man_t * p, int Mode ); +/*=== ifMan.c =============================================================*/ +extern If_Man_t * If_ManStart( If_Par_t * pPars ); +extern void If_ManRestart( If_Man_t * p ); +extern void If_ManStop( If_Man_t * p ); +extern If_Obj_t * If_ManCreateCi( If_Man_t * p ); +extern If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver ); +extern If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ); +extern If_Obj_t * If_ManCreateXor( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ); +extern If_Obj_t * If_ManCreateMux( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1, If_Obj_t * pCtrl ); +extern void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pRepr ); +extern void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId ); +extern void If_ManSetupCiCutSets( If_Man_t * p ); +extern If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj ); +extern void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj ); +extern void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj ); +extern void If_ManSetupSetAll( If_Man_t * p, int nCrossCut ); +/*=== ifMap.c =============================================================*/ +extern void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess ); +extern void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess ); +extern int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, char * pLabel ); +/*=== ifReduce.c ==========================================================*/ +extern void If_ManImproveMapping( If_Man_t * p ); +/*=== ifSeq.c =============================================================*/ +extern int If_ManPerformMappingSeq( If_Man_t * p ); +/*=== ifTime.c ============================================================*/ +extern float If_CutDelay( If_Man_t * p, If_Cut_t * pCut ); +extern void If_CutPropagateRequired( If_Man_t * p, If_Cut_t * pCut, float Required ); +/*=== ifTruth.c ===========================================================*/ +extern void If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ); +/*=== ifUtil.c ============================================================*/ +extern void If_ManCleanNodeCopy( If_Man_t * p ); +extern void If_ManCleanCutData( If_Man_t * p ); +extern void If_ManCleanMarkV( If_Man_t * p ); +extern float If_ManDelayMax( If_Man_t * p, int fSeq ); +extern void If_ManComputeRequired( If_Man_t * p ); +extern float If_ManScanMapping( If_Man_t * p ); +extern float If_ManScanMappingSeq( If_Man_t * p ); +extern void If_ManResetOriginalRefs( If_Man_t * p ); +extern int If_ManCrossCut( If_Man_t * p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/map/if/ifCore.c b/abc70930/src/map/if/ifCore.c new file mode 100644 index 00000000..59ad5a1c --- /dev/null +++ b/abc70930/src/map/if/ifCore.c @@ -0,0 +1,146 @@ +/**CFile**************************************************************** + + FileName [ifCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [The central part of the mapper.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifCore.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int s_MappingTime; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManPerformMapping( If_Man_t * p ) +{ + p->pPars->fAreaOnly = p->pPars->fArea; // temporary + + // create the CI cutsets + If_ManSetupCiCutSets( p ); + // allocate memory for other cutsets + If_ManSetupSetAll( p, If_ManCrossCut(p) ); + + // try sequential mapping + if ( p->pPars->fSeqMap ) + { + int RetValue; +// printf( "Currently sequential mapping is not performed.\n" ); + RetValue = If_ManPerformMappingSeq( p ); + return RetValue; +// return 1; + } + + return If_ManPerformMappingComb( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManPerformMappingComb( If_Man_t * p ) +{ + If_Obj_t * pObj; + int clkTotal = clock(); + int i; + + // set arrival times and fanout estimates + If_ManForEachCi( p, pObj, i ) + { + If_ObjSetArrTime( pObj, p->pPars->pTimesArr[i] ); + pObj->EstRefs = (float)1.0; + } + + // delay oriented mapping + if ( p->pPars->fPreprocess && !p->pPars->fArea ) + { + // map for delay + If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Delay" ); + // map for delay second option + p->pPars->fFancy = 1; + If_ManResetOriginalRefs( p ); + If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Delay-2" ); + p->pPars->fFancy = 0; + // map for area + p->pPars->fArea = 1; + If_ManResetOriginalRefs( p ); + If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Area" ); + p->pPars->fArea = 0; + } + else + If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 0, "Delay" ); + + // try to improve area by expanding and reducing the cuts + if ( p->pPars->fExpRed && !p->pPars->fTruth ) + If_ManImproveMapping( p ); + + // area flow oriented mapping + for ( i = 0; i < p->pPars->nFlowIters; i++ ) + { + If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 0, "Flow" ); + if ( p->pPars->fExpRed && !p->pPars->fTruth ) + If_ManImproveMapping( p ); + } + + // area oriented mapping + for ( i = 0; i < p->pPars->nAreaIters; i++ ) + { + If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 0, "Area" ); + if ( p->pPars->fExpRed && !p->pPars->fTruth ) + If_ManImproveMapping( p ); + } + + if ( p->pPars->fVerbose ) + { +// printf( "Total memory = %7.2f Mb. Peak cut memory = %7.2f Mb. ", +// 1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20), +// 1.0 * p->nSetBytes * Mem_FixedReadMaxEntriesUsed(p->pMemSet) / (1<<20) ); + PRT( "Total time", clock() - clkTotal ); + } +// printf( "Cross cut memory = %d.\n", Mem_FixedReadMaxEntriesUsed(p->pMemSet) ); + s_MappingTime = clock() - clkTotal; + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/if/ifCut.c b/abc70930/src/map/if/ifCut.c new file mode 100644 index 00000000..1a7ecc2c --- /dev/null +++ b/abc70930/src/map/if/ifCut.c @@ -0,0 +1,777 @@ +/**CFile**************************************************************** + + FileName [ifCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifCut.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int If_CutCheckDominance( If_Cut_t * pDom, If_Cut_t * pCut ) +{ + int i, k; + for ( i = 0; i < (int)pDom->nLeaves; i++ ) + { + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) + break; + if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is equal to pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int If_CutCheckEquality( If_Cut_t * pDom, If_Cut_t * pCut ) +{ + int i; + if ( (int)pDom->nLeaves != (int)pCut->nLeaves ) + return 0; + for ( i = 0; i < (int)pDom->nLeaves; i++ ) + if ( pDom->pLeaves[i] != pCut->pLeaves[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut is contained.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut ) +{ + If_Cut_t * pTemp; + int i, k; + assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut ); + for ( i = 0; i < pCutSet->nCuts; i++ ) + { + pTemp = pCutSet->ppCuts[i]; + if ( pTemp->nLeaves > pCut->nLeaves ) + { + // do not fiter the first cut + if ( i == 0 ) + continue; + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) + continue; + // check containment seriously + if ( If_CutCheckDominance( pCut, pTemp ) ) + { +// p->ppCuts[i] = p->ppCuts[p->nCuts-1]; +// p->ppCuts[p->nCuts-1] = pTemp; +// p->nCuts--; +// i--; + // remove contained cut + for ( k = i; k < pCutSet->nCuts; k++ ) + pCutSet->ppCuts[k] = pCutSet->ppCuts[k+1]; + pCutSet->ppCuts[pCutSet->nCuts] = pTemp; + pCutSet->nCuts--; + i--; + } + } + else + { + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) + continue; + // check containment seriously + if ( If_CutCheckDominance( pTemp, pCut ) ) + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int If_CutMergeOrdered( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC ) +{ + int i, k, c; + assert( pC0->nLeaves >= pC1->nLeaves ); + // the case of the largest cut sizes + if ( pC0->nLeaves == pC->nLimit && pC1->nLeaves == pC->nLimit ) + { + for ( i = 0; i < (int)pC0->nLeaves; i++ ) + if ( pC0->pLeaves[i] != pC1->pLeaves[i] ) + return 0; + for ( i = 0; i < (int)pC0->nLeaves; i++ ) + pC->pLeaves[i] = pC0->pLeaves[i]; + pC->nLeaves = pC0->nLeaves; + return 1; + } + // the case when one of the cuts is the largest + if ( pC0->nLeaves == pC->nLimit ) + { + for ( i = 0; i < (int)pC1->nLeaves; i++ ) + { + for ( k = (int)pC0->nLeaves - 1; k >= 0; k-- ) + if ( pC0->pLeaves[k] == pC1->pLeaves[i] ) + break; + if ( k == -1 ) // did not find + return 0; + } + for ( i = 0; i < (int)pC0->nLeaves; i++ ) + pC->pLeaves[i] = pC0->pLeaves[i]; + pC->nLeaves = pC0->nLeaves; + return 1; + } + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < (int)pC->nLimit; c++ ) + { + if ( k == (int)pC1->nLeaves ) + { + if ( i == (int)pC0->nLeaves ) + { + pC->nLeaves = c; + return 1; + } + pC->pLeaves[c] = pC0->pLeaves[i++]; + continue; + } + if ( i == (int)pC0->nLeaves ) + { + if ( k == (int)pC1->nLeaves ) + { + pC->nLeaves = c; + return 1; + } + pC->pLeaves[c] = pC1->pLeaves[k++]; + continue; + } + if ( pC0->pLeaves[i] < pC1->pLeaves[k] ) + { + pC->pLeaves[c] = pC0->pLeaves[i++]; + continue; + } + if ( pC0->pLeaves[i] > pC1->pLeaves[k] ) + { + pC->pLeaves[c] = pC1->pLeaves[k++]; + continue; + } + pC->pLeaves[c] = pC0->pLeaves[i++]; + k++; + } + if ( i < (int)pC0->nLeaves || k < (int)pC1->nLeaves ) + return 0; + pC->nLeaves = c; + return 1; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [Special case when the cut is known to exist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int If_CutMergeOrdered2( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC ) +{ + int i, k, c; + assert( pC0->nLeaves >= pC1->nLeaves ); + // copy the first cut + for ( i = 0; i < (int)pC0->nLeaves; i++ ) + pC->pLeaves[i] = pC0->pLeaves[i]; + pC->nLeaves = pC0->nLeaves; + // the case when one of the cuts is the largest + if ( pC0->nLeaves == pC->nLimit ) + return 1; + // add nodes of the second cut + k = 0; + for ( i = 0; i < (int)pC1->nLeaves; i++ ) + { + // find k-th node before which i-th node should be added + for ( ; k < (int)pC->nLeaves; k++ ) + if ( pC->pLeaves[k] >= pC1->pLeaves[i] ) + break; + // check the case when this should be the last node + if ( k == (int)pC->nLeaves ) + { + pC->pLeaves[k++] = pC1->pLeaves[i]; + pC->nLeaves++; + continue; + } + // check the case when equal node is found + if ( pC1->pLeaves[i] == pC->pLeaves[k] ) + continue; + // add the node + for ( c = (int)pC->nLeaves; c > k; c-- ) + pC->pLeaves[c] = pC->pLeaves[c-1]; + pC->pLeaves[k++] = pC1->pLeaves[i]; + pC->nLeaves++; + } +/* + assert( pC->nLeaves <= pC->nLimit ); + for ( i = 1; i < (int)pC->nLeaves; i++ ) + assert( pC->pLeaves[i-1] < pC->pLeaves[i] ); +*/ + return 1; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut ) +{ + assert( pCut->nLimit > 0 ); + // merge the nodes + if ( pCut0->nLeaves < pCut1->nLeaves ) + { + if ( !If_CutMergeOrdered( pCut1, pCut0, pCut ) ) + return 0; + } + else + { + if ( !If_CutMergeOrdered( pCut0, pCut1, pCut ) ) + return 0; + } + pCut->uSign = pCut0->uSign | pCut1->uSign; + return 1; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutCompareDelay( If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) +{ + If_Cut_t * pC0 = *ppC0; + If_Cut_t * pC1 = *ppC1; + if ( pC0->Delay < pC1->Delay - 0.0001 ) + return -1; + if ( pC0->Delay > pC1->Delay + 0.0001 ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + if ( pC0->Area < pC1->Area - 0.0001 ) + return -1; + if ( pC0->Area > pC1->Area + 0.0001 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutCompareDelayOld( If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) +{ + If_Cut_t * pC0 = *ppC0; + If_Cut_t * pC1 = *ppC1; + if ( pC0->Delay < pC1->Delay - 0.0001 ) + return -1; + if ( pC0->Delay > pC1->Delay + 0.0001 ) + return 1; + if ( pC0->Area < pC1->Area - 0.0001 ) + return -1; + if ( pC0->Area > pC1->Area + 0.0001 ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_CutCompareArea( If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) +{ + If_Cut_t * pC0 = *ppC0; + If_Cut_t * pC1 = *ppC1; + if ( pC0->Area < pC1->Area - 0.0001 ) + return -1; + if ( pC0->Area > pC1->Area + 0.0001 ) + return 1; + if ( pC0->AveRefs > pC1->AveRefs ) + return -1; + if ( pC0->AveRefs < pC1->AveRefs ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + if ( pC0->Delay < pC1->Delay - 0.0001 ) + return -1; + if ( pC0->Delay > pC1->Delay + 0.0001 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Sorts the cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManSortCuts( If_Man_t * p, int Mode ) +{ +/* + // sort the cuts + if ( Mode || p->pPars->fArea ) // area + qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareArea ); + else if ( p->pPars->fFancy ) + qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelayOld ); + else + qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelay ); +*/ +} + +/**Function************************************************************* + + Synopsis [Comparison function for two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 ) +{ + if ( p->SortMode == 1 ) // area + { + if ( pC0->Area < pC1->Area - 0.0001 ) + return -1; + if ( pC0->Area > pC1->Area + 0.0001 ) + return 1; + if ( pC0->AveRefs > pC1->AveRefs ) + return -1; + if ( pC0->AveRefs < pC1->AveRefs ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + if ( pC0->Delay < pC1->Delay - 0.0001 ) + return -1; + if ( pC0->Delay > pC1->Delay + 0.0001 ) + return 1; + return 0; + } + if ( p->SortMode == 0 ) // delay + { + if ( pC0->Delay < pC1->Delay - 0.0001 ) + return -1; + if ( pC0->Delay > pC1->Delay + 0.0001 ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + if ( pC0->Area < pC1->Area - 0.0001 ) + return -1; + if ( pC0->Area > pC1->Area + 0.0001 ) + return 1; + return 0; + } + assert( p->SortMode == 2 ); // delay old + if ( pC0->Delay < pC1->Delay - 0.0001 ) + return -1; + if ( pC0->Delay > pC1->Delay + 0.0001 ) + return 1; + if ( pC0->Area < pC1->Area - 0.0001 ) + return -1; + if ( pC0->Area > pC1->Area + 0.0001 ) + return 1; + if ( pC0->nLeaves < pC1->nLeaves ) + return -1; + if ( pC0->nLeaves > pC1->nLeaves ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs incremental sorting of cuts.] + + Description [Currently only the trivial sorting is implemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ) +{ +// int Counter = 0; + int i; + + // the new cut is the last one + assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut ); + assert( pCutSet->nCuts <= pCutSet->nCutsMax ); + + // cut structure is empty + if ( pCutSet->nCuts == 0 ) + { + pCutSet->nCuts++; + return; + } + + // the cut will be added - find its place + for ( i = pCutSet->nCuts-1; i >= 0; i-- ) + { +// Counter++; + if ( If_ManSortCompare( p, pCutSet->ppCuts[i], pCut ) <= 0 ) + break; + pCutSet->ppCuts[i+1] = pCutSet->ppCuts[i]; + pCutSet->ppCuts[i] = pCut; + } +// printf( "%d ", Counter ); + + // update the number of cuts + if ( pCutSet->nCuts < pCutSet->nCutsMax ) + pCutSet->nCuts++; +} + +/**Function************************************************************* + + Synopsis [Computes area flow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutFlow( If_Man_t * p, If_Cut_t * pCut ) +{ + If_Obj_t * pLeaf; + float Flow; + int i; + assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); + Flow = If_CutLutArea(p, pCut); + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + if ( pLeaf->nRefs == 0 ) + Flow += If_ObjCutBest(pLeaf)->Area; + else if ( p->pPars->fSeqMap ) // seq + Flow += If_ObjCutBest(pLeaf)->Area / pLeaf->nRefs; + else + { + assert( pLeaf->EstRefs > p->fEpsilon ); + Flow += If_ObjCutBest(pLeaf)->Area / pLeaf->EstRefs; + } + } + return Flow; +} + +/**Function************************************************************* + + Synopsis [Average number of references of the leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut ) +{ + If_Obj_t * pLeaf; + int nRefsTotal, i; + assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); + nRefsTotal = 0; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + nRefsTotal += pLeaf->nRefs; + return ((float)nRefsTotal)/pCut->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutDeref( If_Man_t * p, If_Cut_t * pCut, int nLevels ) +{ + If_Obj_t * pLeaf; + float Area; + int i; + Area = If_CutLutArea(p, pCut); + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + assert( pLeaf->nRefs > 0 ); + if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) || nLevels == 1 ) + continue; + Area += If_CutDeref( p, If_ObjCutBest(pLeaf), nLevels - 1 ); + } + return Area; +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutRef( If_Man_t * p, If_Cut_t * pCut, int nLevels ) +{ + If_Obj_t * pLeaf; + float Area; + int i; + Area = If_CutLutArea(p, pCut); + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + assert( pLeaf->nRefs >= 0 ); + if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) || nLevels == 1 ) + continue; + Area += If_CutRef( p, If_ObjCutBest(pLeaf), nLevels - 1 ); + } + return Area; +} + +/**Function************************************************************* + + Synopsis [Prints one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_CutPrint( If_Man_t * p, If_Cut_t * pCut ) +{ + unsigned i; + printf( "{" ); + for ( i = 0; i < pCut->nLeaves; i++ ) + printf( " %d", pCut->pLeaves[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut ) +{ + If_Obj_t * pLeaf; + unsigned i; + printf( "{" ); + If_CutForEachLeaf( p, pCut, pLeaf, i ) + printf( " %d(%.2f/%.2f)", pLeaf->Id, If_ObjCutBest(pLeaf)->Delay, pLeaf->Required ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut, int nLevels ) +{ + float aResult, aResult2; + assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); + aResult2 = If_CutRef( p, pCut, nLevels ); + aResult = If_CutDeref( p, pCut, nLevels ); + assert( aResult > aResult2 - p->fEpsilon ); + assert( aResult < aResult2 + p->fEpsilon ); + return aResult; +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut, int nLevels ) +{ + float aResult, aResult2; + assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); + aResult2 = If_CutDeref( p, pCut, nLevels ); + aResult = If_CutRef( p, pCut, nLevels ); + assert( aResult > aResult2 - p->fEpsilon ); + assert( aResult < aResult2 + p->fEpsilon ); + return aResult; +} + +/**Function************************************************************* + + Synopsis [Moves the cut over the latch.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_CutLift( If_Cut_t * pCut ) +{ + unsigned i; + for ( i = 0; i < pCut->nLeaves; i++ ) + { + assert( (pCut->pLeaves[i] & 255) < 255 ); + pCut->pLeaves[i]++; + } +} + +/**Function************************************************************* + + Synopsis [Computes area of the first level.] + + Description [The cut need to be derefed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc ) +{ + int * pLeaves; + char * pPerm; + unsigned * pTruth; + // save old arrays + pLeaves = pCutDest->pLeaves; + pPerm = pCutDest->pPerm; + pTruth = pCutDest->pTruth; + // copy the cut info + memcpy( pCutDest, pCutSrc, p->nCutBytes ); + // restore the arrays + pCutDest->pLeaves = pLeaves; + pCutDest->pPerm = pPerm; + pCutDest->pTruth = pTruth; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/if/ifMan.c b/abc70930/src/map/if/ifMan.c new file mode 100644 index 00000000..b713d80d --- /dev/null +++ b/abc70930/src/map/if/ifMan.c @@ -0,0 +1,570 @@ +/**CFile**************************************************************** + + FileName [ifMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Mapping manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifMan.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static If_Obj_t * If_ManSetupObj( If_Man_t * p ); + +static void If_ManCutSetRecycle( If_Man_t * p, If_Set_t * pSet ) { pSet->pNext = p->pFreeList; p->pFreeList = pSet; } +static If_Set_t * If_ManCutSetFetch( If_Man_t * p ) { If_Set_t * pTemp = p->pFreeList; p->pFreeList = p->pFreeList->pNext; return pTemp; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Man_t * If_ManStart( If_Par_t * pPars ) +{ + If_Man_t * p; + // start the manager + p = ALLOC( If_Man_t, 1 ); + memset( p, 0, sizeof(If_Man_t) ); + p->pPars = pPars; + p->fEpsilon = (float)0.001; + // allocate arrays for nodes + p->vCis = Vec_PtrAlloc( 100 ); + p->vCos = Vec_PtrAlloc( 100 ); + p->vObjs = Vec_PtrAlloc( 100 ); + p->vMapped = Vec_PtrAlloc( 100 ); + p->vTemp = Vec_PtrAlloc( 100 ); + // prepare the memory manager + p->nTruthWords = p->pPars->fTruth? If_CutTruthWords( p->pPars->nLutSize ) : 0; + p->nPermWords = p->pPars->fUsePerm? If_CutPermWords( p->pPars->nLutSize ) : 0; + p->nObjBytes = sizeof(If_Obj_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords); + p->nCutBytes = sizeof(If_Cut_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords); + p->nSetBytes = sizeof(If_Set_t) + (sizeof(If_Cut_t *) + p->nCutBytes) * (p->pPars->nCutsMax + 1); + p->pMemObj = Mem_FixedStart( p->nObjBytes ); +// p->pMemSet = Mem_FixedStart( p->nSetBytes ); + // report expected memory usage + if ( p->pPars->fVerbose ) + printf( "Memory (bytes): Truth = %4d. Cut = %4d. Obj = %4d. Set = %4d.\n", + 4 * p->nTruthWords, p->nCutBytes, p->nObjBytes, p->nSetBytes ); + // room for temporary truth tables + p->puTemp[0] = p->pPars->fTruth? ALLOC( unsigned, 4 * p->nTruthWords ) : NULL; + p->puTemp[1] = p->puTemp[0] + p->nTruthWords; + p->puTemp[2] = p->puTemp[1] + p->nTruthWords; + p->puTemp[3] = p->puTemp[2] + p->nTruthWords; + // create the constant node + p->pConst1 = If_ManSetupObj( p ); + p->pConst1->Type = IF_CONST1; + p->pConst1->fPhase = 1; + p->nObjs[IF_CONST1]++; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManRestart( If_Man_t * p ) +{ + FREE( p->pMemCi ); + Vec_PtrClear( p->vCis ); + Vec_PtrClear( p->vCos ); + Vec_PtrClear( p->vObjs ); + Vec_PtrClear( p->vMapped ); + Vec_PtrClear( p->vTemp ); + Mem_FixedRestart( p->pMemObj ); + // create the constant node + p->pConst1 = If_ManSetupObj( p ); + p->pConst1->Type = IF_CONST1; + p->pConst1->fPhase = 1; + // reset the counter of other nodes + p->nObjs[IF_CI] = p->nObjs[IF_CO] = p->nObjs[IF_AND] = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManStop( If_Man_t * p ) +{ + Vec_PtrFree( p->vCis ); + Vec_PtrFree( p->vCos ); + Vec_PtrFree( p->vObjs ); + Vec_PtrFree( p->vMapped ); + Vec_PtrFree( p->vTemp ); + if ( p->vLatchOrder ) Vec_PtrFree( p->vLatchOrder ); + if ( p->vLags ) Vec_IntFree( p->vLags ); + Mem_FixedStop( p->pMemObj, 0 ); + FREE( p->pMemCi ); + FREE( p->pMemAnd ); + FREE( p->puTemp[0] ); + // free pars memory + if ( p->pPars->pTimesArr ) + FREE( p->pPars->pTimesArr ); + if ( p->pPars->pTimesReq ) + FREE( p->pPars->pTimesReq ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Creates primary input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * If_ManCreateCi( If_Man_t * p ) +{ + If_Obj_t * pObj; + pObj = If_ManSetupObj( p ); + pObj->Type = IF_CI; + Vec_PtrPush( p->vCis, pObj ); + p->nObjs[IF_CI]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates primary output with the given driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver ) +{ + If_Obj_t * pObj; + pObj = If_ManSetupObj( p ); + Vec_PtrPush( p->vCos, pObj ); + pObj->Type = IF_CO; + pObj->fCompl0 = If_IsComplement(pDriver); pDriver = If_Regular(pDriver); + pObj->pFanin0 = pDriver; pDriver->nRefs++; + p->nObjs[IF_CO]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ) +{ + If_Obj_t * pObj; + // perform constant propagation + if ( pFan0 == pFan1 ) + return pFan0; + if ( pFan0 == If_Not(pFan1) ) + return If_Not(p->pConst1); + if ( If_Regular(pFan0) == p->pConst1 ) + return pFan0 == p->pConst1 ? pFan1 : If_Not(p->pConst1); + if ( If_Regular(pFan1) == p->pConst1 ) + return pFan1 == p->pConst1 ? pFan0 : If_Not(p->pConst1); + // get memory for the new object + pObj = If_ManSetupObj( p ); + pObj->Type = IF_AND; + pObj->fCompl0 = If_IsComplement(pFan0); pFan0 = If_Regular(pFan0); + pObj->fCompl1 = If_IsComplement(pFan1); pFan1 = If_Regular(pFan1); + pObj->pFanin0 = pFan0; pFan0->nRefs++; pFan0->nVisits++; pFan0->nVisitsCopy++; + pObj->pFanin1 = pFan1; pFan1->nRefs++; pFan1->nVisits++; pFan1->nVisitsCopy++; + pObj->fPhase = (pObj->fCompl0 ^ pFan0->fPhase) & (pObj->fCompl1 ^ pFan1->fPhase); + pObj->Level = 1 + IF_MAX( pFan0->Level, pFan1->Level ); + if ( p->nLevelMax < (int)pObj->Level ) + p->nLevelMax = (int)pObj->Level; + p->nObjs[IF_AND]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * If_ManCreateXor( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ) +{ + If_Obj_t * pRes1, * pRes2; + pRes1 = If_ManCreateAnd( p, If_Not(pFan0), pFan1 ); + pRes2 = If_ManCreateAnd( p, pFan0, If_Not(pFan1) ); + return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) ); +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * If_ManCreateMux( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1, If_Obj_t * pCtrl ) +{ + If_Obj_t * pRes1, * pRes2; + pRes1 = If_ManCreateAnd( p, pFan0, If_Not(pCtrl) ); + pRes2 = If_ManCreateAnd( p, pFan1, pCtrl ); + return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) ); +} + +/**Function************************************************************* + + Synopsis [Creates the choice node.] + + Description [Should be called after the equivalence class nodes are linked.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj ) +{ + If_Obj_t * pTemp; + // mark the node as a representative if its class + assert( pObj->fRepr == 0 ); + pObj->fRepr = 1; + // update the level of this node (needed for correct required time computation) + for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) + { + pObj->Level = IF_MAX( pObj->Level, pTemp->Level ); + pTemp->nVisits++; pTemp->nVisitsCopy++; + } + // mark the largest level + if ( p->nLevelMax < (int)pObj->Level ) + p->nLevelMax = (int)pObj->Level; +} + +/**Function************************************************************* + + Synopsis [Prepares memory for one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManSetupCut( If_Man_t * p, If_Cut_t * pCut ) +{ + memset( pCut, 0, sizeof(If_Cut_t) ); + pCut->nLimit = p->pPars->nLutSize; + pCut->pLeaves = (int *)(pCut + 1); + if ( p->pPars->fUsePerm ) + pCut->pPerm = (char *)(pCut->pLeaves + p->pPars->nLutSize); + if ( p->pPars->fTruth ) + pCut->pTruth = pCut->pLeaves + p->pPars->nLutSize + p->nPermWords; +} + +/**Function************************************************************* + + Synopsis [Prepares memory for one cutset.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManSetupSet( If_Man_t * p, If_Set_t * pSet ) +{ + char * pArray; + int i; + pSet->nCuts = 0; + pSet->nCutsMax = p->pPars->nCutsMax; + pSet->ppCuts = (If_Cut_t **)(pSet + 1); + pArray = (char *)pSet->ppCuts + sizeof(If_Cut_t *) * (pSet->nCutsMax+1); + for ( i = 0; i <= pSet->nCutsMax; i++ ) + { + pSet->ppCuts[i] = (If_Cut_t *)(pArray + i * p->nCutBytes); + If_ManSetupCut( p, pSet->ppCuts[i] ); + } +// pArray += (pSet->nCutsMax + 1) * p->nCutBytes; +// assert( ((char *)pArray) - ((char *)pSet) == p->nSetBytes ); +} + +/**Function************************************************************* + + Synopsis [Prepares memory for one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId ) +{ + pCut->fCompl = 0; + pCut->nLimit = p->pPars->nLutSize; + pCut->nLeaves = 1; + pCut->pLeaves[0] = p->pPars->fLiftLeaves? (ObjId << 8) : ObjId; + pCut->uSign = If_ObjCutSign( pCut->pLeaves[0] ); + // set up elementary truth table of the unit cut + if ( p->pPars->fTruth ) + { + int i, nTruthWords; + nTruthWords = pCut->nLimit <= 5 ? 1 : (1 << (pCut->nLimit - 5)); + for ( i = 0; i < nTruthWords; i++ ) + If_CutTruth(pCut)[i] = 0xAAAAAAAA; + } +} + +/**Function************************************************************* + + Synopsis [Prepares memory for the node with cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * If_ManSetupObj( If_Man_t * p ) +{ + If_Obj_t * pObj; + // get memory for the object + pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMemObj ); + memset( pObj, 0, sizeof(If_Obj_t) ); + If_ManSetupCut( p, &pObj->CutBest ); + // assign ID and save + pObj->Id = Vec_PtrSize(p->vObjs); + Vec_PtrPush( p->vObjs, pObj ); + // set the required times + pObj->Required = IF_FLOAT_LARGE; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Prepares memory for one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManSetupCiCutSets( If_Man_t * p ) +{ + If_Obj_t * pObj; + int i; + assert( p->pMemCi == NULL ); + // create elementary cuts for the CIs + If_ManForEachCi( p, pObj, i ) + If_ManSetupCutTriv( p, &pObj->CutBest, pObj->Id ); + // create elementary cutsets for the CIs + p->pMemCi = (If_Set_t *)malloc( If_ManCiNum(p) * (sizeof(If_Set_t) + sizeof(void *)) ); + If_ManForEachCi( p, pObj, i ) + { + pObj->pCutSet = (If_Set_t *)((char *)p->pMemCi + i * (sizeof(If_Set_t) + sizeof(void *))); + pObj->pCutSet->nCuts = 1; + pObj->pCutSet->nCutsMax = p->pPars->nCutsMax; + pObj->pCutSet->ppCuts = (If_Cut_t **)(pObj->pCutSet + 1); + pObj->pCutSet->ppCuts[0] = &pObj->CutBest; + } +} + +/**Function************************************************************* + + Synopsis [Prepares cutset of the node.] + + Description [Elementary cutset will be added last.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj ) +{ + assert( If_ObjIsAnd(pObj) ); + assert( pObj->pCutSet == NULL ); +// pObj->pCutSet = (If_Set_t *)Mem_FixedEntryFetch( p->pMemSet ); +// If_ManSetupSet( p, pObj->pCutSet ); + + pObj->pCutSet = If_ManCutSetFetch( p ); + pObj->pCutSet->nCuts = 0; + pObj->pCutSet->nCutsMax = p->pPars->nCutsMax; + + return pObj->pCutSet; +} + +/**Function************************************************************* + + Synopsis [Dereferences cutset of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj ) +{ + If_Obj_t * pFanin; + assert( If_ObjIsAnd(pObj) ); + // consider the node + assert( pObj->nVisits >= 0 ); + if ( pObj->nVisits == 0 ) + { +// Mem_FixedEntryRecycle( p->pMemSet, (char *)pObj->pCutSet ); + If_ManCutSetRecycle( p, pObj->pCutSet ); + pObj->pCutSet = NULL; + } + // consider the first fanin + pFanin = If_ObjFanin0(pObj); + assert( pFanin->nVisits > 0 ); + if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) + { +// Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet ); + If_ManCutSetRecycle( p, pFanin->pCutSet ); + pFanin->pCutSet = NULL; + } + // consider the second fanin + pFanin = If_ObjFanin1(pObj); + assert( pFanin->nVisits > 0 ); + if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) + { +// Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet ); + If_ManCutSetRecycle( p, pFanin->pCutSet ); + pFanin->pCutSet = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Dereferences cutset of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj ) +{ + If_Obj_t * pTemp; + assert( If_ObjIsAnd(pObj) ); + assert( pObj->fRepr ); + assert( pObj->nVisits > 0 ); + // consider the nodes in the choice class + for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) + { + assert( pTemp == pObj || pTemp->nVisits == 1 ); + if ( --pTemp->nVisits == 0 ) + { +// Mem_FixedEntryRecycle( p->pMemSet, (char *)pTemp->pCutSet ); + If_ManCutSetRecycle( p, pTemp->pCutSet ); + pTemp->pCutSet = NULL; + } + } +} + +/**Function************************************************************* + + Synopsis [Dereferences cutset of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManSetupSetAll( If_Man_t * p, int nCrossCut ) +{ + If_Set_t * pCutSet; + int i, nCutSets; + nCutSets = 128 + nCrossCut; + p->pFreeList = p->pMemAnd = pCutSet = (If_Set_t *)malloc( nCutSets * p->nSetBytes ); + for ( i = 0; i < nCutSets; i++ ) + { + If_ManSetupSet( p, pCutSet ); + if ( i == nCutSets - 1 ) + pCutSet->pNext = NULL; + else + pCutSet->pNext = (If_Set_t *)( (char *)pCutSet + p->nSetBytes ); + pCutSet = pCutSet->pNext; + } + assert( pCutSet == NULL ); + + if ( p->pPars->fVerbose ) + { + printf( "Node = %7d. Ch = %5d. Total mem = %7.2f Mb. Peak cut mem = %7.2f Mb.\n", + If_ManAndNum(p), p->nChoices, + 1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20), + 1.0 * p->nSetBytes * nCrossCut / (1<<20) ); + } +// printf( "Cross cut = %d.\n", nCrossCut ); + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/if/ifMap.c b/abc70930/src/map/if/ifMap.c new file mode 100644 index 00000000..06ed4d1e --- /dev/null +++ b/abc70930/src/map/if/ifMap.c @@ -0,0 +1,300 @@ +/**CFile**************************************************************** + + FileName [ifMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Mapping procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifMap.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Counts the number of 1s in the signature.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int If_WordCountOnes( unsigned uWord ) +{ + uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); + uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); + uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); + uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); + return (uWord & 0x0000FFFF) + (uWord>>16); +} + +/**Function************************************************************* + + Synopsis [Finds the best cut for the given node.] + + Description [Mapping modes: delay (0), area flow (1), area (2).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess ) +{ + If_Set_t * pCutSet; + If_Cut_t * pCut0, * pCut1, * pCut; + int i, k; + + assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 1 ); + assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin1) || pObj->pFanin1->pCutSet->nCuts > 1 ); + + // prepare + if ( !p->pPars->fSeqMap ) + { + if ( Mode == 0 ) + pObj->EstRefs = (float)pObj->nRefs; + else if ( Mode == 1 ) + pObj->EstRefs = (float)((2.0 * pObj->EstRefs + pObj->nRefs) / 3.0); + } + if ( Mode && pObj->nRefs > 0 ) + If_CutDeref( p, If_ObjCutBest(pObj), IF_INFINITY ); + + // prepare the cutset + pCutSet = If_ManSetupNodeCutSet( p, pObj ); + + // get the current assigned best cut + pCut = If_ObjCutBest(pObj); + if ( pCut->nLeaves > 0 ) + { + // recompute the parameters of the best cut + pCut->Delay = If_CutDelay( p, pCut ); + assert( pCut->Delay <= pObj->Required + p->fEpsilon ); + pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut ); + // save the best cut from the previous iteration + if ( !fPreprocess ) + If_CutCopy( p, pCutSet->ppCuts[pCutSet->nCuts++], pCut ); + } + + // generate cuts + If_ObjForEachCut( pObj->pFanin0, pCut0, i ) + If_ObjForEachCut( pObj->pFanin1, pCut1, k ) + { + // get the next free cut + assert( pCutSet->nCuts <= pCutSet->nCutsMax ); + pCut = pCutSet->ppCuts[pCutSet->nCuts]; + // make sure K-feasible cut exists + if ( If_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->pPars->nLutSize ) + continue; + // merge the nodes + if ( !If_CutMerge( pCut0, pCut1, pCut ) ) + continue; + assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); + p->nCutsMerged++; + // check if this cut is contained in any of the available cuts +// if ( p->pPars->pFuncCost == NULL && If_CutFilter( p, pCut ) ) // do not filter functionality cuts + if ( If_CutFilter( pCutSet, pCut ) ) + continue; + // compute the truth table + pCut->fCompl = 0; + if ( p->pPars->fTruth ) + If_CutComputeTruth( p, pCut, pCut0, pCut1, pObj->fCompl0, pObj->fCompl1 ); + // compute the application-specific cost and depth + pCut->fUser = (p->pPars->pFuncCost != NULL); + pCut->Cost = p->pPars->pFuncCost? p->pPars->pFuncCost(pCut) : 0; + if ( pCut->Cost == IF_COST_MAX ) + continue; + // check if the cut satisfies the required times + pCut->Delay = If_CutDelay( p, pCut ); +// printf( "%.2f ", pCut->Delay ); + if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon ) + continue; + // compute area of the cut (this area may depend on the application specific cost) + pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut ); + pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut ); + // insert the cut into storage + If_CutSort( p, pCutSet, pCut ); + } + assert( pCutSet->nCuts > 0 ); + + // add the trivial cut to the set + If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id ); + assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 ); + + // update the best cut + if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon ) + If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] ); + assert( p->pPars->fSeqMap || If_ObjCutBest(pObj)->nLeaves > 1 ); + + // ref the selected cut + if ( Mode && pObj->nRefs > 0 ) + If_CutRef( p, If_ObjCutBest(pObj), IF_INFINITY ); + + // call the user specified function for each cut + if ( p->pPars->pFuncUser ) + If_ObjForEachCut( pObj, pCut, i ) + p->pPars->pFuncUser( p, pObj, pCut ); + + // free the cuts + If_ManDerefNodeCutSet( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Finds the best cut for the choice node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess ) +{ + If_Set_t * pCutSet; + If_Obj_t * pTemp; + If_Cut_t * pCutTemp, * pCut; + int i; + assert( pObj->pEquiv != NULL ); + + // prepare + if ( Mode && pObj->nRefs > 0 ) + If_CutDeref( p, If_ObjCutBest(pObj), IF_INFINITY ); + + // remove elementary cuts + for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) + pTemp->pCutSet->nCuts--; + + // update the cutset of the node + pCutSet = pObj->pCutSet; + + // generate cuts + for ( pTemp = pObj->pEquiv; pTemp; pTemp = pTemp->pEquiv ) + { + assert( pTemp->nRefs == 0 ); + assert( p->pPars->fSeqMap || pTemp->pCutSet->nCuts > 0 ); + // go through the cuts of this node + If_ObjForEachCut( pTemp, pCutTemp, i ) + { + assert( p->pPars->fSeqMap || pCutTemp->nLeaves > 1 ); + // get the next free cut + assert( pCutSet->nCuts <= pCutSet->nCutsMax ); + pCut = pCutSet->ppCuts[pCutSet->nCuts]; + // copy the cut into storage + If_CutCopy( p, pCut, pCutTemp ); + // check if this cut is contained in any of the available cuts + if ( If_CutFilter( pCutSet, pCut ) ) + continue; + // check if the cut satisfies the required times + assert( pCut->Delay == If_CutDelay( p, pCut ) ); + if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon ) + continue; + // set the phase attribute + assert( pCut->fCompl == 0 ); + pCut->fCompl ^= (pObj->fPhase ^ pTemp->fPhase); // why ^= ? + // compute area of the cut (this area may depend on the application specific cost) + pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut ); + pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut ); + // insert the cut into storage + If_CutSort( p, pCutSet, pCut ); + } + } + assert( pCutSet->nCuts > 0 ); + + // add the trivial cut to the set + If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id ); + assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 ); + + // update the best cut + if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon ) + If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] ); + assert( p->pPars->fSeqMap || If_ObjCutBest(pObj)->nLeaves > 1 ); + + // ref the selected cut + if ( Mode && pObj->nRefs > 0 ) + If_CutRef( p, If_ObjCutBest(pObj), IF_INFINITY ); + + // free the cuts + If_ManDerefChoiceCutSet( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs one mapping pass over all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, char * pLabel ) +{ +// ProgressBar * pProgress; + If_Obj_t * pObj; + int i, clk = clock(); + assert( Mode >= 0 && Mode <= 2 ); + // set the sorting function + if ( Mode || p->pPars->fArea ) // area + p->SortMode = 1; + else if ( p->pPars->fFancy ) + p->SortMode = 2; + else + p->SortMode = 0; + // set the cut number + p->nCutsUsed = nCutsUsed; + p->nCutsMerged = 0; + // map the internal nodes +// pProgress = Extra_ProgressBarStart( stdout, If_ManObjNum(p) ); + If_ManForEachNode( p, pObj, i ) + { +// Extra_ProgressBarUpdate( pProgress, i, pLabel ); + If_ObjPerformMappingAnd( p, pObj, Mode, fPreprocess ); + if ( pObj->fRepr ) + If_ObjPerformMappingChoice( p, pObj, Mode, fPreprocess ); + } +// Extra_ProgressBarStop( pProgress ); + // make sure the visit counters are all zero + If_ManForEachNode( p, pObj, i ) + assert( pObj->nVisits == 0 ); + // compute required times and stats + If_ManComputeRequired( p ); + if ( p->pPars->fVerbose ) + { + char Symb = fPreprocess? 'P' : ((Mode == 0)? 'D' : ((Mode == 1)? 'F' : 'A')); + printf( "%c: Del = %7.2f. Ar = %9.1f. Edge = %8d. Cut = %8d. ", + Symb, p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged ); + PRT( "T", clock() - clk ); +// printf( "Max number of cuts = %d. Average number of cuts = %5.2f.\n", +// p->nCutsMax, 1.0 * p->nCutsMerged / If_ManAndNum(p) ); + } + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/if/ifReduce.c b/abc70930/src/map/if/ifReduce.c new file mode 100644 index 00000000..5dfda661 --- /dev/null +++ b/abc70930/src/map/if/ifReduce.c @@ -0,0 +1,574 @@ +/**CFile**************************************************************** + + FileName [ifExpand.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Incremental improvement of current mapping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifExpand.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void If_ManImproveReduce( If_Man_t * p, int nLimit ); +static void If_ManImproveExpand( If_Man_t * p, int nLimit ); +static void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ); +static void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ); +static void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront ); +static void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Improves current mapping using expand/Expand of one cut.] + + Description [Assumes current mapping assigned and required times computed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManImproveMapping( If_Man_t * p ) +{ + int clk; + + clk = clock(); + If_ManImproveExpand( p, p->pPars->nLutSize ); + If_ManComputeRequired( p ); + if ( p->pPars->fVerbose ) + { + printf( "E: Del = %7.2f. Ar = %9.1f. Edge = %8d. Cut = %8d. ", + p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged ); + PRT( "T", clock() - clk ); + } + +/* + clk = clock(); + If_ManImproveReduce( p, p->pPars->nLutSize ); + If_ManComputeRequired( p, 0 ); + if ( p->pPars->fVerbose ) + { + printf( "R: Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ", + p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) ); + PRT( "T", clock() - clk ); + } +*/ +/* + clk = clock(); + If_ManImproveExpand( p, p->pPars->nLutSize ); + If_ManComputeRequired( p, 0 ); + if ( p->pPars->fVerbose ) + { + printf( "E: Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ", + p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) ); + PRT( "T", clock() - clk ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManImproveExpand( If_Man_t * p, int nLimit ) +{ + Vec_Ptr_t * vFront, * vFrontOld, * vVisited; + If_Obj_t * pObj; + int i; + vFront = Vec_PtrAlloc( nLimit ); + vFrontOld = Vec_PtrAlloc( nLimit ); + vVisited = Vec_PtrAlloc( 100 ); + // iterate through all nodes in the topological order + If_ManForEachNode( p, pObj, i ) + If_ManImproveNodeExpand( p, pObj, nLimit, vFront, vFrontOld, vVisited ); + Vec_PtrFree( vFront ); + Vec_PtrFree( vFrontOld ); + Vec_PtrFree( vVisited ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of nodes with no external fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManImproveCutCost( If_Man_t * p, Vec_Ptr_t * vFront ) +{ + If_Obj_t * pFanin; + int i, Counter = 0; + Vec_PtrForEachEntry( vFront, pFanin, i ) + if ( pFanin->nRefs == 0 ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ) +{ + If_Obj_t * pFanin; + If_Cut_t * pCut; + int CostBef, CostAft, i; + float DelayOld, AreaBef, AreaAft; + pCut = If_ObjCutBest(pObj); + assert( pCut->Delay <= pObj->Required + p->fEpsilon ); + if ( pObj->nRefs == 0 ) + return; + // get the delay + DelayOld = pCut->Delay; + // get the area + AreaBef = If_CutAreaRefed( p, pCut, IF_INFINITY ); +// if ( AreaBef == 1 ) +// return; + // the cut is non-trivial + If_ManImproveNodePrepare( p, pObj, nLimit, vFront, vFrontOld, vVisited ); + // iteratively modify the cut + If_CutDeref( p, pCut, IF_INFINITY ); + CostBef = If_ManImproveCutCost( p, vFront ); + If_ManImproveNodeFaninCompact( p, pObj, nLimit, vFront, vVisited ); + CostAft = If_ManImproveCutCost( p, vFront ); + If_CutRef( p, pCut, IF_INFINITY ); + assert( CostBef >= CostAft ); + // clean up + Vec_PtrForEachEntry( vVisited, pFanin, i ) + pFanin->fMark = 0; + // update the node + If_ManImproveNodeUpdate( p, pObj, vFront ); + pCut->Delay = If_CutDelay( p, pCut ); + // get the new area + AreaAft = If_CutAreaRefed( p, pCut, IF_INFINITY ); + if ( AreaAft > AreaBef || pCut->Delay > pObj->Required + p->fEpsilon ) + { + If_ManImproveNodeUpdate( p, pObj, vFrontOld ); + AreaAft = If_CutAreaRefed( p, pCut, IF_INFINITY ); + assert( AreaAft == AreaBef ); + pCut->Delay = DelayOld; + } +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManImproveMark_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vVisited ) +{ + if ( pObj->fMark ) + return; + assert( If_ObjIsAnd(pObj) ); + If_ManImproveMark_rec( p, If_ObjFanin0(pObj), vVisited ); + If_ManImproveMark_rec( p, If_ObjFanin1(pObj), vVisited ); + Vec_PtrPush( vVisited, pObj ); + pObj->fMark = 1; +} + +/**Function************************************************************* + + Synopsis [Prepares node mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ) +{ + If_Cut_t * pCut; + If_Obj_t * pLeaf; + int i; + Vec_PtrClear( vFront ); + Vec_PtrClear( vFrontOld ); + Vec_PtrClear( vVisited ); + // expand the cut downwards from the given place + pCut = If_ObjCutBest(pObj); + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + Vec_PtrPush( vFront, pLeaf ); + Vec_PtrPush( vFrontOld, pLeaf ); + Vec_PtrPush( vVisited, pLeaf ); + pLeaf->fMark = 1; + } + // mark the nodes in the cone + If_ManImproveMark_rec( p, pObj, vVisited ); +} + +/**Function************************************************************* + + Synopsis [Updates the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront ) +{ + If_Cut_t * pCut; + If_Obj_t * pFanin; + int i; + pCut = If_ObjCutBest(pObj); + // deref node's cut + If_CutDeref( p, pCut, IF_INFINITY ); + // update the node's cut + pCut->nLeaves = Vec_PtrSize(vFront); + Vec_PtrForEachEntry( vFront, pFanin, i ) + pCut->pLeaves[i] = pFanin->Id; + // ref the new cut + If_CutRef( p, pCut, IF_INFINITY ); +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the number of fanins will grow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManImproveNodeWillGrow( If_Man_t * p, If_Obj_t * pObj ) +{ + If_Obj_t * pFanin0, * pFanin1; + assert( If_ObjIsAnd(pObj) ); + pFanin0 = If_ObjFanin0(pObj); + pFanin1 = If_ObjFanin1(pObj); + return !pFanin0->fMark && !pFanin1->fMark; +} + +/**Function************************************************************* + + Synopsis [Returns the increase in the number of fanins with no external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManImproveNodeFaninCost( If_Man_t * p, If_Obj_t * pObj ) +{ + int Counter = 0; + assert( If_ObjIsAnd(pObj) ); + // check if the node has external refs + if ( pObj->nRefs == 0 ) + Counter--; + // increment the number of fanins without external refs + if ( !If_ObjFanin0(pObj)->fMark && If_ObjFanin0(pObj)->nRefs == 0 ) + Counter++; + // increment the number of fanins without external refs + if ( !If_ObjFanin1(pObj)->fMark && If_ObjFanin1(pObj)->nRefs == 0 ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Updates the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManImproveNodeFaninUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) +{ + If_Obj_t * pFanin; + assert( If_ObjIsAnd(pObj) ); + Vec_PtrRemove( vFront, pObj ); + pFanin = If_ObjFanin0(pObj); + if ( !pFanin->fMark ) + { + Vec_PtrPush( vFront, pFanin ); + Vec_PtrPush( vVisited, pFanin ); + pFanin->fMark = 1; + } + pFanin = If_ObjFanin1(pObj); + if ( !pFanin->fMark ) + { + Vec_PtrPush( vFront, pFanin ); + Vec_PtrPush( vVisited, pFanin ); + pFanin->fMark = 1; + } +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManImproveNodeFaninCompact0( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) +{ + If_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( vFront, pFanin, i ) + { + if ( If_ObjIsCi(pFanin) ) + continue; + if ( If_ManImproveNodeWillGrow(p, pFanin) ) + continue; + if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 ) + { + If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManImproveNodeFaninCompact1( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) +{ + If_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( vFront, pFanin, i ) + { + if ( If_ObjIsCi(pFanin) ) + continue; + if ( If_ManImproveNodeFaninCost(p, pFanin) < 0 ) + { + If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManImproveNodeFaninCompact2( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) +{ + If_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( vFront, pFanin, i ) + { + if ( If_ObjIsCi(pFanin) ) + continue; + if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 ) + { + If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManImproveNodeFaninCompact_int( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) +{ + if ( If_ManImproveNodeFaninCompact0(p, pObj, nLimit, vFront, vVisited) ) + return 1; + if ( Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact1(p, pObj, nLimit, vFront, vVisited) ) + return 1; + if ( Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact2(p, pObj, nLimit, vFront, vVisited) ) + return 1; + assert( Vec_PtrSize(vFront) <= nLimit ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) +{ + while ( If_ManImproveNodeFaninCompact_int( p, pObj, nLimit, vFront, vVisited ) ); +} + + + + + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManImproveNodeReduce( If_Man_t * p, If_Obj_t * pObj, int nLimit ) +{ +/* + If_Cut_t * pCut, * pCut0, * pCut1, * pCutR; + If_Obj_t * pFanin0, * pFanin1; + float AreaBef, AreaAft; + int RetValue; + + assert( nLimit <= 32 ); + assert( If_ObjIsAnd(pObj) ); + // get the fanins + pFanin0 = If_ObjFanin0(pObj); + pFanin1 = If_ObjFanin1(pObj); + // get the cuts + pCut = If_ObjCutBest(pObj); + pCut0 = If_ObjIsCi(pFanin0) ? If_ObjCutTriv(pFanin0) : If_ObjCutBest(pFanin0); + pCut1 = If_ObjIsCi(pFanin1) ? If_ObjCutTriv(pFanin1) : If_ObjCutBest(pFanin1); + assert( pCut->Delay <= pObj->Required + p->fEpsilon ); + + // deref the cut if the node is refed + if ( pObj->nRefs > 0 ) + If_CutDeref( p, pCut, IF_INFINITY ); + // get the area + AreaBef = If_CutAreaDerefed( p, pCut, IF_INFINITY ); + // get the fanin support + if ( pFanin0->nRefs > 2 && pCut0->Delay < pObj->Required + p->fEpsilon ) +// if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results + { + pCut0 = If_ObjCutTriv(pFanin0); + } + // get the fanin support + if ( pFanin1->nRefs > 2 && pCut1->Delay < pObj->Required + p->fEpsilon ) +// if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR ) + { + pCut1 = If_ObjCutTriv(pFanin1); + } + + // merge the cuts + pCutR = p->ppCuts[0]; + RetValue = If_CutMerge( pCut0, pCut1, pCutR ); + // try very simple cut + if ( !RetValue ) + { + RetValue = If_CutMerge( If_ObjCutTriv(pFanin0), If_ObjCutTriv(pFanin1), pCutR ); + assert( RetValue == 1 ); + } + if ( RetValue ) + { + pCutR->Delay = If_CutDelay( p, pCutR ); + AreaAft = If_CutAreaDerefed( p, pCutR, IF_INFINITY ); + // update the best cut + if ( AreaAft < AreaBef - p->fEpsilon && pCutR->Delay < pObj->Required + p->fEpsilon ) + If_CutCopy( p, pCut, pCutR ); + } + // recompute the delay of the best cut + pCut->Delay = If_CutDelay( p, pCut ); + // ref the cut if the node is refed + if ( pObj->nRefs > 0 ) + If_CutRef( p, pCut, IF_INFINITY ); +*/ +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManImproveReduce( If_Man_t * p, int nLimit ) +{ + If_Obj_t * pObj; + int i; + If_ManForEachNode( p, pObj, i ) + If_ManImproveNodeReduce( p, pObj, nLimit ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/if/ifSeq.c b/abc70930/src/map/if/ifSeq.c new file mode 100644 index 00000000..8d1de8c1 --- /dev/null +++ b/abc70930/src/map/if/ifSeq.c @@ -0,0 +1,405 @@ +/**CFile**************************************************************** + + FileName [ifSeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Sequential mapping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifSeq.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int s_MappingTime; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Prepares for sequential mapping by linking the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManPrepareMappingSeq( If_Man_t * p ) +{ + If_Obj_t * pObjLi, * pObjLo; + int i; + + // link the latch outputs (CIs) directly to the drivers of latch inputs (COs) + for ( i = 0; i < p->pPars->nLatches; i++ ) + { + pObjLi = If_ManLi( p, i ); + pObjLo = If_ManLo( p, i ); + pObjLo->pFanin0 = If_ObjFanin0( pObjLi ); + pObjLo->fCompl0 = If_ObjFaninC0( pObjLi ); + } +} + +/**Function************************************************************* + + Synopsis [Collects latches in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManCollectLatches_rec( If_Obj_t * pObj, Vec_Ptr_t * vLatches ) +{ + if ( !If_ObjIsLatch(pObj) ) + return; + if ( pObj->fMark ) + return; + pObj->fMark = 1; + If_ManCollectLatches_rec( pObj->pFanin0, vLatches ); + Vec_PtrPush( vLatches, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects latches in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p ) +{ + Vec_Ptr_t * vLatches; + If_Obj_t * pObj; + int i; + // collect latches + vLatches = Vec_PtrAlloc( p->pPars->nLatches ); + If_ManForEachLatchOutput( p, pObj, i ) + If_ManCollectLatches_rec( pObj, vLatches ); + // clean marks + Vec_PtrForEachEntry( vLatches, pObj, i ) + pObj->fMark = 0; + assert( Vec_PtrSize(vLatches) == p->pPars->nLatches ); + return vLatches; +} + +/**Function************************************************************* + + Synopsis [Performs one pass of l-value computation over all nodes.] + + Description [Experimentally it was found that checking POs changes + is not enough to detect the convergence of l-values in the network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManPerformMappingRoundSeq( If_Man_t * p, int nIter ) +{ + If_Obj_t * pObj; + int i, clk = clock(); + int fVeryVerbose = 0; + int fChange = 0; + + // map the internal nodes + p->nCutsMerged = 0; + If_ManForEachNode( p, pObj, i ) + { + If_ObjPerformMappingAnd( p, pObj, 0, 0 ); + if ( pObj->fRepr ) + If_ObjPerformMappingChoice( p, pObj, 0, 0 ); + } + + // postprocess the mapping +//printf( "Itereation %d: \n", nIter ); + If_ManForEachNode( p, pObj, i ) + { + // update the LValues stored separately + if ( If_ObjLValue(pObj) < If_ObjCutBest(pObj)->Delay - p->fEpsilon ) + { + If_ObjSetLValue( pObj, If_ObjCutBest(pObj)->Delay ); + fChange = 1; + } +//printf( "%d ", (int)If_ObjLValue(pObj) ); + // reset the visit counters + assert( pObj->nVisits == 0 ); + pObj->nVisits = pObj->nVisitsCopy; + } +//printf( "\n" ); + + // propagate LValues over the registers + Vec_PtrForEachEntry( p->vLatchOrder, pObj, i ) + { + If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period ); + If_ObjSetArrTime( pObj, If_ObjLValue(pObj) ); + } + + // compute area and delay + if ( fVeryVerbose ) + { + p->RequiredGlo = If_ManDelayMax( p, 1 ); + p->AreaGlo = If_ManScanMapping(p); + printf( "S%d: Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. ", + nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged ); + PRT( "T", clock() - clk ); + } + return fChange; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if retiming with this clock period is feasible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManBinarySearchPeriod( If_Man_t * p ) +{ + If_Obj_t * pObj; + int i, c, fConverged; + int fResetRefs = 0; + + p->nAttempts++; + + // reset initial LValues (PIs to 0; others to -inf) + If_ManForEachObj( p, pObj, i ) + { + if ( If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) ) + { + If_ObjSetLValue( pObj, (float)0.0 ); + If_ObjSetArrTime( pObj, (float)0.0 ); + } + else + { + If_ObjSetLValue( pObj, (float)-IF_INFINITY ); + If_ObjSetArrTime( pObj, (float)-IF_INFINITY ); + } + // undo any previous mapping, except for CIs + if ( If_ObjIsAnd(pObj) ) + If_ObjCutBest(pObj)->nLeaves = 0; + } + + // update all values iteratively + fConverged = 0; + for ( c = 1; c <= p->nMaxIters; c++ ) + { + if ( !If_ManPerformMappingRoundSeq( p, c ) ) + { + p->RequiredGlo = If_ManDelayMax( p, 1 ); + fConverged = 1; + break; + } + p->RequiredGlo = If_ManDelayMax( p, 1 ); +//printf( "Global = %d \n", (int)p->RequiredGlo ); + if ( p->RequiredGlo > p->Period + p->fEpsilon ) + break; + } + + // report the results + if ( p->pPars->fVerbose ) + { + p->AreaGlo = If_ManScanMapping(p); + printf( "Attempt = %2d. Iters = %3d. Area = %10.2f. Fi = %6.2f. ", p->nAttempts, c, p->AreaGlo, (float)p->Period ); + if ( fConverged ) + printf( " Feasible" ); + else if ( c > p->nMaxIters ) + printf( "Infeasible (timeout)" ); + else + printf( "Infeasible" ); + printf( "\n" ); + } + return fConverged; +} + + +/**Function************************************************************* + + Synopsis [Performs binary search for the optimal clock period.] + + Description [Assumes that FiMin is infeasible while FiMax is feasible.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManBinarySearch_rec( If_Man_t * p, int FiMin, int FiMax ) +{ + assert( FiMin < FiMax ); + if ( FiMin + 1 == FiMax ) + return FiMax; + // compute the median + p->Period = FiMin + (FiMax - FiMin)/2; + if ( If_ManBinarySearchPeriod( p ) ) + return If_ManBinarySearch_rec( p, FiMin, p->Period ); // Median is feasible + else + return If_ManBinarySearch_rec( p, p->Period, FiMax ); // Median is infeasible +} + +/**Function************************************************************* + + Synopsis [Performs sequential mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManPerformMappingSeqPost( If_Man_t * p ) +{ + If_Obj_t * pObjLi, * pObjLo, * pObj; + int i; + + // link the latch outputs (CIs) directly to the drivers of latch inputs (COs) + for ( i = 0; i < p->pPars->nLatches; i++ ) + { + pObjLi = If_ManLi( p, i ); + pObjLo = If_ManLo( p, i ); +// printf( "%3d : %2d -> %2d \n", i, +// (int)If_ObjLValue(If_ObjFanin0(pObjLo)), (int)If_ObjLValue(pObjLo) ); + } + + // set arrival times + assert( p->pPars->pTimesArr != NULL ); + If_ManForEachLatchOutput( p, pObjLo, i ) + p->pPars->pTimesArr[i] = If_ObjLValue(pObjLo); + + // set the required times + assert( p->pPars->pTimesReq == NULL ); + p->pPars->pTimesReq = ALLOC( float, If_ManCoNum(p) ); + If_ManForEachPo( p, pObj, i ) + { + p->pPars->pTimesReq[i] = p->RequiredGlo2; +// printf( "Out %3d : %2d \n", i, (int)p->pPars->pTimesReq[i] ); + } + If_ManForEachLatchInput( p, pObjLi, i ) + { + p->pPars->pTimesReq[i] = If_ObjLValue(If_ObjFanin0(pObjLi)); +// printf( "Out %3d : %2d \n", i, (int)p->pPars->pTimesReq[i] ); + } + + // undo previous mapping + If_ManForEachObj( p, pObj, i ) + if ( If_ObjIsAnd(pObj) ) + If_ObjCutBest(pObj)->nLeaves = 0; + + // map again combinationally + p->pPars->fSeqMap = 0; + If_ManPerformMappingComb( p ); + p->pPars->fSeqMap = 1; +} + +/**Function************************************************************* + + Synopsis [Performs sequential mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManPerformMappingSeq( If_Man_t * p ) +{ + int clkTotal = clock(); + int PeriodBest; + + p->SortMode = 0; + + // perform combinational mapping to get the upper bound on the clock period + If_ManPerformMappingRound( p, 1, 0, 0, NULL ); + p->RequiredGlo = If_ManDelayMax( p, 0 ); + p->RequiredGlo2 = p->RequiredGlo; + + // set direct linking of latches with their inputs + If_ManPrepareMappingSeq( p ); + + // collect latches + p->vLatchOrder = If_ManCollectLatches( p ); + + // set parameters + p->nCutsUsed = p->pPars->nCutsMax; + p->nAttempts = 0; + p->nMaxIters = 50; + p->Period = (int)p->RequiredGlo; + + // make sure the clock period works + if ( !If_ManBinarySearchPeriod( p ) ) + { + printf( "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" ); + return 0; + } + + // perform binary search + PeriodBest = If_ManBinarySearch_rec( p, 0, p->Period ); + + // recompute the best l-values + if ( p->Period != PeriodBest ) + { + p->Period = PeriodBest; + if ( !If_ManBinarySearchPeriod( p ) ) + { + printf( "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" ); + return 0; + } + } + if ( p->pPars->fVerbose ) + { +/* + { + FILE * pTable; + pTable = fopen( "iscas/stats_new.txt", "a+" ); +// fprintf( pTable, "%s ", pNtk->pName ); + fprintf( pTable, "%d ", p->Period ); + // fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) ); +// fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) ); +// fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + printf( "The best clock period is %3d. ", p->Period ); + PRT( "Sequential time", clock() - clkTotal ); + } + p->RequiredGlo = (float)PeriodBest; + + // postprocess it using combinational mapping + If_ManPerformMappingSeqPost( p ); + s_MappingTime = clock() - clkTotal; + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/if/ifTime.c b/abc70930/src/map/if/ifTime.c new file mode 100644 index 00000000..60417c67 --- /dev/null +++ b/abc70930/src/map/if/ifTime.c @@ -0,0 +1,221 @@ +/**CFile**************************************************************** + + FileName [ifTime.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Computation of delay paramters depending on the library.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifTime.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void If_CutSortInputPins( If_Man_t * p, If_Cut_t * pCut, int * pPinPerm, float * pPinDelays ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_CutDelay( If_Man_t * p, If_Cut_t * pCut ) +{ + static int pPinPerm[IF_MAX_LUTSIZE]; + static float pPinDelays[IF_MAX_LUTSIZE]; + If_Obj_t * pLeaf; + float Delay, DelayCur; + float * pLutDelays; + int i, Shift; + assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); + Delay = -IF_FLOAT_LARGE; + if ( p->pPars->pLutLib ) + { + assert( !p->pPars->fLiftLeaves ); + pLutDelays = p->pPars->pLutLib->pLutDelays[pCut->nLeaves]; + if ( p->pPars->pLutLib->fVarPinDelays ) + { + // compute the delay using sorted pins + If_CutSortInputPins( p, pCut, pPinPerm, pPinDelays ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + DelayCur = pPinDelays[pPinPerm[i]] + pLutDelays[i]; + Delay = IF_MAX( Delay, DelayCur ); + } + } + else + { + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + DelayCur = If_ObjCutBest(pLeaf)->Delay + pLutDelays[0]; + Delay = IF_MAX( Delay, DelayCur ); + } + } + } + else + { + if ( pCut->fUser ) + { + assert( !p->pPars->fLiftLeaves ); + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + DelayCur = If_ObjCutBest(pLeaf)->Delay + (float)pCut->pPerm[i]; + Delay = IF_MAX( Delay, DelayCur ); + } + } + else + { + if ( p->pPars->fLiftLeaves ) + { + If_CutForEachLeafSeq( p, pCut, pLeaf, Shift, i ) + { + DelayCur = If_ObjCutBest(pLeaf)->Delay - Shift * p->Period; + Delay = IF_MAX( Delay, DelayCur ); + } + } + else + { + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + DelayCur = If_ObjCutBest(pLeaf)->Delay; + Delay = IF_MAX( Delay, DelayCur ); + } + } + Delay += 1.0; + } + } + return Delay; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_CutPropagateRequired( If_Man_t * p, If_Cut_t * pCut, float ObjRequired ) +{ + static int pPinPerm[IF_MAX_LUTSIZE]; + static float pPinDelays[IF_MAX_LUTSIZE]; + If_Obj_t * pLeaf; + float * pLutDelays; + float Required; + int i; + assert( !p->pPars->fLiftLeaves ); + // compute the pins + if ( p->pPars->pLutLib ) + { + pLutDelays = p->pPars->pLutLib->pLutDelays[pCut->nLeaves]; + if ( p->pPars->pLutLib->fVarPinDelays ) + { + // compute the delay using sorted pins + If_CutSortInputPins( p, pCut, pPinPerm, pPinDelays ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + Required = ObjRequired - pLutDelays[i]; + pLeaf = If_ManObj( p, pCut->pLeaves[pPinPerm[i]] ); + pLeaf->Required = IF_MIN( pLeaf->Required, Required ); + } + } + else + { + Required = ObjRequired - pLutDelays[0]; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + pLeaf->Required = IF_MIN( pLeaf->Required, Required ); + } + } + else + { + if ( pCut->fUser ) + { + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + Required = ObjRequired - (float)pCut->pPerm[i]; + pLeaf->Required = IF_MIN( pLeaf->Required, Required ); + } + } + else + { + Required = ObjRequired - (float)1.0; + If_CutForEachLeaf( p, pCut, pLeaf, i ) + pLeaf->Required = IF_MIN( pLeaf->Required, Required ); + } + } +} + +/**Function************************************************************* + + Synopsis [Sorts the pins in the decreasing order of delays.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_CutSortInputPins( If_Man_t * p, If_Cut_t * pCut, int * pPinPerm, float * pPinDelays ) +{ + If_Obj_t * pLeaf; + int i, j, best_i, temp; + // start the trivial permutation and collect pin delays + If_CutForEachLeaf( p, pCut, pLeaf, i ) + { + pPinPerm[i] = i; + pPinDelays[i] = If_ObjCutBest(pLeaf)->Delay; + } + // selection sort the pins in the decreasible order of delays + // this order will match the increasing order of LUT input pins + for ( i = 0; i < (int)pCut->nLeaves-1; i++ ) + { + best_i = i; + for ( j = i+1; j < (int)pCut->nLeaves; j++ ) + if ( pPinDelays[pPinPerm[j]] > pPinDelays[pPinPerm[best_i]] ) + best_i = j; + if ( best_i == i ) + continue; + temp = pPinPerm[i]; + pPinPerm[i] = pPinPerm[best_i]; + pPinPerm[best_i] = temp; + } + // verify + assert( pPinPerm[0] < (int)pCut->nLeaves ); + for ( i = 1; i < (int)pCut->nLeaves; i++ ) + { + assert( pPinPerm[i] < (int)pCut->nLeaves ); + assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/if/ifTruth.c b/abc70930/src/map/if/ifTruth.c new file mode 100644 index 00000000..5587e3ff --- /dev/null +++ b/abc70930/src/map/if/ifTruth.c @@ -0,0 +1,230 @@ +/**CFile**************************************************************** + + FileName [ifTruth.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Computation of truth tables of the cuts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifTruth.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Several simple procedures working with truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int If_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline void If_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~pIn[w]; +} +static inline void If_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn[w]; +} +static inline void If_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~(pIn0[w] & pIn1[w]); +} +static inline void If_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] & pIn1[w]; +} + +/**Function************************************************************* + + Synopsis [Swaps two adjacent variables in the truth table.] + + Description [Swaps var number Start and var number Start+1 (0-based numbers). + The input truth table is pIn. The output truth table is pOut.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) +{ + static unsigned PMasks[4][3] = { + { 0x99999999, 0x22222222, 0x44444444 }, + { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 }, + { 0xF00FF00F, 0x00F000F0, 0x0F000F00 }, + { 0xFF0000FF, 0x0000FF00, 0x00FF0000 } + }; + int nWords = If_TruthWordNum( nVars ); + int i, k, Step, Shift; + + assert( iVar < nVars - 1 ); + if ( iVar < 4 ) + { + Shift = (1 << iVar); + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift); + } + else if ( iVar > 4 ) + { + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 4*Step ) + { + for ( i = 0; i < Step; i++ ) + pOut[i] = pIn[i]; + for ( i = 0; i < Step; i++ ) + pOut[Step+i] = pIn[2*Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[2*Step+i] = pIn[Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[3*Step+i] = pIn[3*Step+i]; + pIn += 4*Step; + pOut += 4*Step; + } + } + else // if ( iVar == 4 ) + { + for ( i = 0; i < nWords; i += 2 ) + { + pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); + pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); + } + } +} + +/**Function************************************************************* + + Synopsis [Expands the truth table according to the phase.] + + Description [The input and output truth tables are in pIn/pOut. The current number + of variables is nVars. The total number of variables in nVarsAll. The last argument + (Phase) contains shows where the variables should go.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ) +{ + unsigned * pTemp; + int i, k, Var = nVars - 1, Counter = 0; + for ( i = nVarsAll - 1; i >= 0; i-- ) + if ( Phase & (1 << i) ) + { + for ( k = Var; k < i; k++ ) + { + If_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + Counter++; + } + Var--; + } + assert( Var == -1 ); + // swap if it was moved an even number of times + if ( !(Counter & 1) ) + If_TruthCopy( pOut, pIn, nVarsAll ); +} + +/**Function************************************************************* + + Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned If_CutTruthPhase( If_Cut_t * pCut, If_Cut_t * pCut1 ) +{ + unsigned uPhase = 0; + int i, k; + for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) + { + if ( k == (int)pCut1->nLeaves ) + break; + if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) + continue; + assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); + uPhase |= (1 << i); + k++; + } + return uPhase; +} + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ) +{ + extern void Kit_FactorTest( unsigned * pTruth, int nVars ); + + // permute the first table + if ( fCompl0 ^ pCut0->fCompl ) + If_TruthNot( p->puTemp[0], If_CutTruth(pCut0), pCut->nLimit ); + else + If_TruthCopy( p->puTemp[0], If_CutTruth(pCut0), pCut->nLimit ); + If_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nLimit, If_CutTruthPhase(pCut, pCut0) ); + // permute the second table + if ( fCompl1 ^ pCut1->fCompl ) + If_TruthNot( p->puTemp[1], If_CutTruth(pCut1), pCut->nLimit ); + else + If_TruthCopy( p->puTemp[1], If_CutTruth(pCut1), pCut->nLimit ); + If_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nLimit, If_CutTruthPhase(pCut, pCut1) ); + // produce the resulting table + assert( pCut->fCompl == 0 ); + if ( pCut->fCompl ) + If_TruthNand( If_CutTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nLimit ); + else + If_TruthAnd( If_CutTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nLimit ); + + // perform +// Kit_FactorTest( If_CutTruth(pCut), pCut->nLimit ); +// printf( "%d ", If_CutLeaveNum(pCut) - Kit_TruthSupportSize(If_CutTruth(pCut), If_CutLeaveNum(pCut)) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/if/ifUtil.c b/abc70930/src/map/if/ifUtil.c new file mode 100644 index 00000000..f3fa049e --- /dev/null +++ b/abc70930/src/map/if/ifUtil.c @@ -0,0 +1,454 @@ +/**CFile**************************************************************** + + FileName [ifUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: ifUtil.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets all the node copy to NULL.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManCleanNodeCopy( If_Man_t * p ) +{ + If_Obj_t * pObj; + int i; + If_ManForEachObj( p, pObj, i ) + If_ObjSetCopy( pObj, NULL ); +} + +/**Function************************************************************* + + Synopsis [Sets all the cut data to NULL.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManCleanCutData( If_Man_t * p ) +{ + If_Obj_t * pObj; + int i; + If_ManForEachObj( p, pObj, i ) + If_CutSetData( If_ObjCutBest(pObj), NULL ); +} + +/**Function************************************************************* + + Synopsis [Sets all visited marks to 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManCleanMarkV( If_Man_t * p ) +{ + If_Obj_t * pObj; + int i; + If_ManForEachObj( p, pObj, i ) + pObj->fVisit = 0; +} + +/**Function************************************************************* + + Synopsis [Returns the max delay of the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_ManDelayMax( If_Man_t * p, int fSeq ) +{ + If_Obj_t * pObj; + float DelayBest; + int i; + if ( p->pPars->fLatchPaths && p->pPars->nLatches == 0 ) + { + printf( "Delay optimization of latch path is not performed because there is no latches.\n" ); + p->pPars->fLatchPaths = 0; + } + DelayBest = -IF_FLOAT_LARGE; + if ( fSeq ) + { + assert( p->pPars->nLatches > 0 ); + If_ManForEachPo( p, pObj, i ) + if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) ) + DelayBest = If_ObjArrTime(If_ObjFanin0(pObj)); + } + else if ( p->pPars->fLatchPaths ) + { + If_ManForEachLatchInput( p, pObj, i ) + if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) ) + DelayBest = If_ObjArrTime(If_ObjFanin0(pObj)); + } + else + { + If_ManForEachCo( p, pObj, i ) + if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) ) + DelayBest = If_ObjArrTime(If_ObjFanin0(pObj)); + } + return DelayBest; +} + +/**Function************************************************************* + + Synopsis [Computes the required times of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManComputeRequired( If_Man_t * p ) +{ + If_Obj_t * pObj; + int i, Counter; + + // compute area, clean required times, collect nodes used in the mapping + p->nNets = 0; + p->AreaGlo = If_ManScanMapping( p ); + + // consider the case when the required times are given + if ( p->pPars->pTimesReq ) + { + assert( !p->pPars->fAreaOnly ); + // make sure that the required time hold + Counter = 0; + If_ManForEachCo( p, pObj, i ) + { + if ( If_ObjArrTime(If_ObjFanin0(pObj)) > p->pPars->pTimesReq[i] + p->fEpsilon ) + { + Counter++; +// printf( "Required times are violated for output %d (arr = %d; req = %d).\n", +// i, (int)If_ObjArrTime(If_ObjFanin0(pObj)), (int)p->pPars->pTimesReq[i] ); + } + If_ObjFanin0(pObj)->Required = p->pPars->pTimesReq[i]; + } + if ( Counter ) + printf( "Required times are violated for %d outputs.\n", Counter ); + } + else + { + // get the global required times + p->RequiredGlo = If_ManDelayMax( p, 0 ); + // update the required times according to the target + if ( p->pPars->DelayTarget != -1 ) + { + if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon ) + { + if ( p->fNextRound == 0 ) + { + p->fNextRound = 1; + printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget ); + } + } + else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon ) + { + if ( p->fNextRound == 0 ) + { + p->fNextRound = 1; + printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget ); + } + p->RequiredGlo = p->pPars->DelayTarget; + } + } + // do not propagate required times if area minimization is requested + if ( p->pPars->fAreaOnly ) + return; + // set the required times for the POs + if ( p->pPars->fLatchPaths ) + { + If_ManForEachLatchInput( p, pObj, i ) + If_ObjFanin0(pObj)->Required = p->RequiredGlo; + } + else + { + If_ManForEachCo( p, pObj, i ) + If_ObjFanin0(pObj)->Required = p->RequiredGlo; + } + } + // go through the nodes in the reverse topological order + Vec_PtrForEachEntry( p->vMapped, pObj, i ) + If_CutPropagateRequired( p, If_ObjCutBest(pObj), pObj->Required ); +} + +/**Function************************************************************* + + Synopsis [Computes area, references, and nodes used in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_ManScanMapping_rec( If_Man_t * p, If_Obj_t * pObj, If_Obj_t ** ppStore ) +{ + If_Obj_t * pLeaf; + If_Cut_t * pCutBest; + float aArea; + int i; + if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) ) + return 0.0; + // store the node in the structure by level + assert( If_ObjIsAnd(pObj) ); + pObj->pCopy = (char *)ppStore[pObj->Level]; + ppStore[pObj->Level] = pObj; + // visit the transitive fanin of the selected cut + pCutBest = If_ObjCutBest(pObj); + p->nNets += pCutBest->nLeaves; + aArea = If_CutLutArea( p, pCutBest ); + If_CutForEachLeaf( p, pCutBest, pLeaf, i ) + aArea += If_ManScanMapping_rec( p, pLeaf, ppStore ); + return aArea; +} + +/**Function************************************************************* + + Synopsis [Computes area, references, and nodes used in the mapping.] + + Description [Collects the nodes in reverse topological order in array + p->vMapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_ManScanMapping( If_Man_t * p ) +{ + If_Obj_t * pObj, ** ppStore; + float aArea; + int i; + assert( !p->pPars->fLiftLeaves ); + // clean all references + If_ManForEachObj( p, pObj, i ) + { + pObj->Required = IF_FLOAT_LARGE; + pObj->nVisits = pObj->nVisitsCopy; + pObj->nRefs = 0; + } + // allocate place to store the nodes + ppStore = ALLOC( If_Obj_t *, p->nLevelMax + 1 ); + memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) ); + // collect nodes reachable from POs in the DFS order through the best cuts + aArea = 0; + If_ManForEachCo( p, pObj, i ) + aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore ); + // reconnect the nodes in reverse topological order + Vec_PtrClear( p->vMapped ); + for ( i = p->nLevelMax; i >= 0; i-- ) + for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy ) + Vec_PtrPush( p->vMapped, pObj ); + free( ppStore ); + return aArea; +} + +/**Function************************************************************* + + Synopsis [Computes area, references, and nodes used in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_ManScanMappingSeq_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vMapped ) +{ + If_Obj_t * pLeaf; + If_Cut_t * pCutBest; + float aArea; + int i, Shift; + // treat latches transparently + if ( If_ObjIsLatch(pObj) ) + return If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), vMapped ); + // consider trivial cases + if ( pObj->nRefs++ || If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) ) + return 0.0; + // store the node in the structure by level + assert( If_ObjIsAnd(pObj) ); + // visit the transitive fanin of the selected cut + pCutBest = If_ObjCutBest(pObj); + aArea = If_ObjIsAnd(pObj)? If_CutLutArea(p, pCutBest) : (float)0.0; + If_CutForEachLeafSeq( p, pCutBest, pLeaf, Shift, i ) + aArea += If_ManScanMappingSeq_rec( p, pLeaf, vMapped ); + // add the node + Vec_PtrPush( vMapped, pObj ); + return aArea; +} + +/**Function************************************************************* + + Synopsis [Computes area, references, and nodes used in the mapping.] + + Description [Collects the nodes in reverse topological order in array + p->vMapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float If_ManScanMappingSeq( If_Man_t * p ) +{ + If_Obj_t * pObj; + float aArea; + int i; + assert( p->pPars->fLiftLeaves ); + // clean all references + If_ManForEachObj( p, pObj, i ) + pObj->nRefs = 0; + // collect nodes reachable from POs in the DFS order through the best cuts + aArea = 0; + Vec_PtrClear( p->vMapped ); + If_ManForEachPo( p, pObj, i ) + aArea += If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), p->vMapped ); + return aArea; +} + +/**Function************************************************************* + + Synopsis [Computes area, references, and nodes used in the mapping.] + + Description [Collects the nodes in reverse topological order in array + p->vMapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManResetOriginalRefs( If_Man_t * p ) +{ + If_Obj_t * pObj; + int i; + If_ManForEachObj( p, pObj, i ) + pObj->nRefs = 0; + If_ManForEachObj( p, pObj, i ) + { + if ( If_ObjIsAnd(pObj) ) + { + pObj->pFanin0->nRefs++; + pObj->pFanin1->nRefs++; + } + else if ( If_ObjIsCo(pObj) ) + pObj->pFanin0->nRefs++; + } +} + +/**Function************************************************************* + + Synopsis [Computes cross-cut of the circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManCrossCut( If_Man_t * p ) +{ + If_Obj_t * pObj, * pFanin; + int i, nCutSize = 0, nCutSizeMax = 0; + If_ManForEachObj( p, pObj, i ) + { + if ( !If_ObjIsAnd(pObj) ) + continue; + // consider the node + if ( nCutSizeMax < ++nCutSize ) + nCutSizeMax = nCutSize; + if ( pObj->nVisits == 0 ) + nCutSize--; + // consider the fanins + pFanin = If_ObjFanin0(pObj); + if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) + nCutSize--; + pFanin = If_ObjFanin1(pObj); + if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) + nCutSize--; + // consider the choice class + if ( pObj->fRepr ) + for ( pFanin = pObj; pFanin; pFanin = pFanin->pEquiv ) + if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) + nCutSize--; + } + If_ManForEachObj( p, pObj, i ) + { + assert( If_ObjIsCi(pObj) || pObj->fVisit == 0 ); + pObj->nVisits = pObj->nVisitsCopy; + } + assert( nCutSize == 0 ); +// printf( "Max cross cut size = %6d.\n", nCutSizeMax ); + return nCutSizeMax; +} + +/**Function************************************************************* + + Synopsis [Computes cross-cut of the circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int If_ManCountTrueArea( If_Man_t * p ) +{ + If_Obj_t * pObj; + int i, Area = 0; + Vec_PtrForEachEntry( p->vMapped, pObj, i ) + Area += 1 + (If_ObjCutBest(pObj)->nLeaves > (unsigned)p->pPars->nLutSize / 2); + return Area; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/if/if_.c b/abc70930/src/map/if/if_.c new file mode 100644 index 00000000..d2960077 --- /dev/null +++ b/abc70930/src/map/if/if_.c @@ -0,0 +1,47 @@ +/**CFile**************************************************************** + + FileName [if_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [FPGA mapping based on priority cuts.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - November 21, 2006.] + + Revision [$Id: if_.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "if.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/if/module.make b/abc70930/src/map/if/module.make new file mode 100644 index 00000000..f3d189be --- /dev/null +++ b/abc70930/src/map/if/module.make @@ -0,0 +1,9 @@ +SRC += src/map/if/ifCore.c \ + src/map/if/ifCut.c \ + src/map/if/ifMan.c \ + src/map/if/ifMap.c \ + src/map/if/ifReduce.c \ + src/map/if/ifSeq.c \ + src/map/if/ifTime.c \ + src/map/if/ifTruth.c \ + src/map/if/ifUtil.c diff --git a/abc70930/src/map/mapper/mapper.c b/abc70930/src/map/mapper/mapper.c new file mode 100644 index 00000000..b18b68c0 --- /dev/null +++ b/abc70930/src/map/mapper/mapper.c @@ -0,0 +1,176 @@ +/**CFile**************************************************************** + + FileName [mapper.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Command file for the mapper package.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapper.c,v 1.7 2005/01/23 06:59:42 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "mainInt.h" +#include "mio.h" +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Map_CommandReadLibrary ( Abc_Frame_t * pAbc, int argc, char **argv ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_Init( Abc_Frame_t * pAbc ) +{ + Cmd_CommandAdd( pAbc, "SC mapping", "read_super", Map_CommandReadLibrary, 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_End() +{ +// Map_SuperLibFree( s_pSuperLib ); + Map_SuperLibFree( Abc_FrameReadLibSuper() ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Map_SuperLib_t * pLib; + Abc_Ntk_t * pNet; + char * FileName, * ExcludeFile; + int fVerbose; + int fAlgorithm; + int c; + + pNet = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + fVerbose = 1; + fAlgorithm = 1; + ExcludeFile = 0; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "eovh")) != EOF ) + { + switch (c) + { + case 'e': + ExcludeFile = argv[globalUtilOptind]; + if ( ExcludeFile == 0 ) + goto usage; + globalUtilOptind++; + break; + case 'o': + fAlgorithm ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) +// if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); + if ( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) ) + fprintf( pErr, "Did you mean \"%s\"?", FileName ); + fprintf( pErr, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pLib = Map_SuperLibCreate( FileName, ExcludeFile, fAlgorithm, fVerbose ); + if ( pLib == NULL ) + { + fprintf( pErr, "Reading supergate library has failed.\n" ); + goto usage; + } + // replace the current library +// Map_SuperLibFree( s_pSuperLib ); +// s_pSuperLib = pLib; + Map_SuperLibFree( Abc_FrameReadLibSuper() ); + Abc_FrameSetLibSuper( pLib ); + // replace the current genlib library +// if ( s_pLib ) Mio_LibraryDelete( s_pLib ); +// s_pLib = s_pSuperLib->pGenlib; + Mio_LibraryDelete( Abc_FrameReadLibGen() ); + Abc_FrameSetLibGen( pLib->pGenlib ); + return 0; + +usage: + fprintf( pErr, "\nusage: read_super [-ovh]\n"); + fprintf( pErr, "\t read the supergate library from the file\n" ); + fprintf( pErr, "\t-e file : file contains list of genlib gates to exclude\n" ); + fprintf( pErr, "\t-o : toggles the use of old file format [default = %s]\n", (fAlgorithm? "new" : "old") ); + fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; /* error exit */ +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapper.h b/abc70930/src/map/mapper/mapper.h new file mode 100644 index 00000000..8eade761 --- /dev/null +++ b/abc70930/src/map/mapper/mapper.h @@ -0,0 +1,195 @@ +/**CFile**************************************************************** + + FileName [mapper.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapper.h,v 1.11 2005/02/28 05:34:26 alanmi Exp $] + +***********************************************************************/ + +#ifndef __MAPPER_H__ +#define __MAPPER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Map_ManStruct_t_ Map_Man_t; +typedef struct Map_NodeStruct_t_ Map_Node_t; +typedef struct Map_NodeVecStruct_t_ Map_NodeVec_t; +typedef struct Map_CutStruct_t_ Map_Cut_t; +typedef struct Map_MatchStruct_t_ Map_Match_t; +typedef struct Map_SuperStruct_t_ Map_Super_t; +typedef struct Map_SuperLibStruct_t_ Map_SuperLib_t; +typedef struct Map_HashTableStruct_t_ Map_HashTable_t; +typedef struct Map_HashEntryStruct_t_ Map_HashEntry_t; +typedef struct Map_TimeStruct_t_ Map_Time_t; + +// the pair of rise/fall time parameters +struct Map_TimeStruct_t_ +{ + float Rise; + float Fall; + float Worst; +}; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Map_IsComplement(p) (((int)((unsigned long) (p) & 01))) +#define Map_Regular(p) ((Map_Node_t *)((unsigned long)(p) & ~01)) +#define Map_Not(p) ((Map_Node_t *)((unsigned long)(p) ^ 01)) +#define Map_NotCond(p,c) ((Map_Node_t *)((unsigned long)(p) ^ (c))) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== mapperCreate.c =============================================================*/ +extern Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose ); +extern Map_Node_t * Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); +extern void Map_ManFree( Map_Man_t * pMan ); +extern void Map_ManPrintTimeStats( Map_Man_t * p ); +extern void Map_ManPrintStatsToFile( char * pName, float Area, float Delay, int Time ); +extern int Map_ManReadInputNum( Map_Man_t * p ); +extern int Map_ManReadOutputNum( Map_Man_t * p ); +extern Map_Node_t ** Map_ManReadInputs ( Map_Man_t * p ); +extern Map_Node_t ** Map_ManReadOutputs( Map_Man_t * p ); +extern Map_Node_t * Map_ManReadConst1 ( Map_Man_t * p ); +extern Map_Time_t * Map_ManReadInputArrivals( Map_Man_t * p ); +extern Mio_Library_t * Map_ManReadGenLib ( Map_Man_t * p ); +extern bool Map_ManReadVerbose( Map_Man_t * p ); +extern float Map_ManReadAreaFinal( Map_Man_t * p ); +extern float Map_ManReadRequiredGlo( Map_Man_t * p ); +extern void Map_ManSetTimeToMap( Map_Man_t * p, int Time ); +extern void Map_ManSetTimeToNet( Map_Man_t * p, int Time ); +extern void Map_ManSetTimeSweep( Map_Man_t * p, int Time ); +extern void Map_ManSetTimeTotal( Map_Man_t * p, int Time ); +extern void Map_ManSetOutputNames( Map_Man_t * p, char ** ppNames ); +extern void Map_ManSetAreaRecovery( Map_Man_t * p, int fAreaRecovery ); +extern void Map_ManSetDelayTarget( Map_Man_t * p, float DelayTarget ); +extern void Map_ManSetInputArrivals( Map_Man_t * p, Map_Time_t * pArrivals ); +extern void Map_ManSetObeyFanoutLimits( Map_Man_t * p, bool fObeyFanoutLimits ); +extern void Map_ManSetNumIterations( Map_Man_t * p, int nNumIterations ); +extern int Map_ManReadPass( Map_Man_t * p ); +extern void Map_ManSetPass( Map_Man_t * p, int nPass ); +extern int Map_ManReadFanoutViolations( Map_Man_t * p ); +extern void Map_ManSetFanoutViolations( Map_Man_t * p, int nVio ); +extern void Map_ManSetChoiceNodeNum( Map_Man_t * p, int nChoiceNodes ); +extern void Map_ManSetChoiceNum( Map_Man_t * p, int nChoices ); +extern void Map_ManSetVerbose( Map_Man_t * p, int fVerbose ); +extern void Map_ManSetSwitching( Map_Man_t * p, int fSwitching ); + +extern Map_Man_t * Map_NodeReadMan( Map_Node_t * p ); +extern char * Map_NodeReadData( Map_Node_t * p, int fPhase ); +extern int Map_NodeReadNum( Map_Node_t * p ); +extern int Map_NodeReadLevel( Map_Node_t * p ); +extern Map_Cut_t * Map_NodeReadCuts( Map_Node_t * p ); +extern Map_Cut_t * Map_NodeReadCutBest( Map_Node_t * p, int fPhase ); +extern Map_Node_t * Map_NodeReadOne( Map_Node_t * p ); +extern Map_Node_t * Map_NodeReadTwo( Map_Node_t * p ); +extern void Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData ); +extern void Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE ); +extern void Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr ); +extern void Map_NodeSetSwitching( Map_Node_t * p, float Switching ); + +extern int Map_NodeIsConst( Map_Node_t * p ); +extern int Map_NodeIsVar( Map_Node_t * p ); +extern int Map_NodeIsAnd( Map_Node_t * p ); +extern int Map_NodeComparePhase( Map_Node_t * p1, Map_Node_t * p2 ); + +extern Map_Super_t * Map_CutReadSuperBest( Map_Cut_t * p, int fPhase ); +extern Map_Super_t * Map_CutReadSuper0( Map_Cut_t * p ); +extern Map_Super_t * Map_CutReadSuper1( Map_Cut_t * p ); +extern int Map_CutReadLeavesNum( Map_Cut_t * p ); +extern Map_Node_t ** Map_CutReadLeaves( Map_Cut_t * p ); +extern unsigned Map_CutReadPhaseBest( Map_Cut_t * p, int fPhase ); +extern unsigned Map_CutReadPhase0( Map_Cut_t * p ); +extern unsigned Map_CutReadPhase1( Map_Cut_t * p ); +extern Map_Cut_t * Map_CutReadNext( Map_Cut_t * p ); + +extern char * Map_SuperReadFormula( Map_Super_t * p ); +extern Mio_Gate_t * Map_SuperReadRoot( Map_Super_t * p ); +extern int Map_SuperReadNum( Map_Super_t * p ); +extern Map_Super_t ** Map_SuperReadFanins( Map_Super_t * p ); +extern int Map_SuperReadFaninNum( Map_Super_t * p ); +extern Map_Super_t * Map_SuperReadNext( Map_Super_t * p ); +extern int Map_SuperReadNumPhases( Map_Super_t * p ); +extern unsigned char * Map_SuperReadPhases( Map_Super_t * p ); +extern int Map_SuperReadFanoutLimit( Map_Super_t * p ); + +extern Mio_Library_t * Map_SuperLibReadGenLib( Map_SuperLib_t * p ); +extern float Map_SuperLibReadAreaInv( Map_SuperLib_t * p ); +extern Map_Time_t Map_SuperLibReadDelayInv( Map_SuperLib_t * p ); +extern int Map_SuperLibReadVarsMax( Map_SuperLib_t * p ); + +extern Map_Node_t * Map_NodeAnd( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); +extern Map_Node_t * Map_NodeOr( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); +extern Map_Node_t * Map_NodeExor( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); +extern Map_Node_t * Map_NodeMux( Map_Man_t * p, Map_Node_t * pNode, Map_Node_t * pNodeT, Map_Node_t * pNodeE ); +extern void Map_NodeSetChoice( Map_Man_t * pMan, Map_Node_t * pNodeOld, Map_Node_t * pNodeNew ); + +/*=== resmCanon.c =============================================================*/ +extern int Map_CanonComputeSlow( unsigned uTruths[][2], int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ); +extern int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ); +/*=== mapperCut.c =============================================================*/ +extern Map_Cut_t * Map_CutAlloc( Map_Man_t * p ); +/*=== mapperCutUtils.c =============================================================*/ +extern void Map_CutCreateFromNode( Map_Man_t * p, Map_Super_t * pSuper, int iRoot, unsigned uPhaseRoot, + int * pLeaves, int nLeaves, unsigned uPhaseLeaves ); +/*=== mapperCore.c =============================================================*/ +extern int Map_Mapping( Map_Man_t * p ); +/*=== mapperLib.c =============================================================*/ +extern int Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib ); +/*=== mapperMntk.c =============================================================*/ +//extern Mntk_Man_t * Map_ConvertMappingToMntk( Map_Man_t * pMan ); +/*=== mapperSuper.c =============================================================*/ +extern char * Map_LibraryReadFormulaStep( char * pFormula, char * pStrings[], int * pnStrings ); +/*=== mapperSweep.c =============================================================*/ +extern void Map_NetworkSweep( Abc_Ntk_t * pNet ); +/*=== mapperTable.c =============================================================*/ +extern Map_Super_t * Map_SuperTableLookupC( Map_SuperLib_t * pLib, unsigned uTruth[] ); +/*=== mapperTime.c =============================================================*/ +/*=== mapperUtil.c =============================================================*/ +extern int Map_ManCheckConsistency( Map_Man_t * p ); +extern st_table * Map_CreateTableGate2Super( Map_Man_t * p ); +extern void Map_ManCleanData( Map_Man_t * p ); +extern void Map_MappingSetupTruthTables( unsigned uTruths[][2] ); +extern void Map_MappingSetupTruthTablesLarge( unsigned uTruths[][32] ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/map/mapper/mapperCanon.c b/abc70930/src/map/mapper/mapperCanon.c new file mode 100644 index 00000000..203c9142 --- /dev/null +++ b/abc70930/src/map/mapper/mapperCanon.c @@ -0,0 +1,271 @@ +/**CFile**************************************************************** + + FileName [mapperCanon.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperCanon.c,v 1.2 2005/01/23 06:59:42 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase ); +static void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the N-canonical form of the Boolean function.] + + Description [The N-canonical form is defined as the truth table with + the minimum integer value. This function exhaustively enumerates + through the complete set of 2^N phase assignments.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_CanonComputeSlow( unsigned uTruths[][2], int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ) +{ + unsigned uTruthPerm[2]; + int nMints, nPhases, m; + + nPhases = 0; + nMints = (1 << nVarsReal); + if ( nVarsMax < 6 ) + { + uTruthRes[0] = MAP_MASK(32); + for ( m = 0; m < nMints; m++ ) + { + uTruthPerm[0] = Map_CanonComputePhase( uTruths, nVarsMax, uTruth[0], m ); + if ( uTruthRes[0] > uTruthPerm[0] ) + { + uTruthRes[0] = uTruthPerm[0]; + nPhases = 0; + puPhases[nPhases++] = (unsigned char)m; + } + else if ( uTruthRes[0] == uTruthPerm[0] ) + { + if ( nPhases < 4 ) // the max number of phases in Map_Super_t + puPhases[nPhases++] = (unsigned char)m; + } + } + uTruthRes[1] = uTruthRes[0]; + } + else + { + uTruthRes[0] = MAP_MASK(32); + uTruthRes[1] = MAP_MASK(32); + for ( m = 0; m < nMints; m++ ) + { + Map_CanonComputePhase6( uTruths, nVarsMax, uTruth, m, uTruthPerm ); + if ( uTruthRes[1] > uTruthPerm[1] || uTruthRes[1] == uTruthPerm[1] && uTruthRes[0] > uTruthPerm[0] ) + { + uTruthRes[0] = uTruthPerm[0]; + uTruthRes[1] = uTruthPerm[1]; + nPhases = 0; + puPhases[nPhases++] = (unsigned char)m; + } + else if ( uTruthRes[1] == uTruthPerm[1] && uTruthRes[0] == uTruthPerm[0] ) + { + if ( nPhases < 4 ) // the max number of phases in Map_Super_t + puPhases[nPhases++] = (unsigned char)m; + } + } + } + assert( nPhases > 0 ); +// printf( "%d ", nPhases ); + return nPhases; +} + +/**Function************************************************************* + + Synopsis [Performs phase transformation for one function of less than 6 variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase ) +{ + int v, Shift; + for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) + if ( uPhase & Shift ) + uTruth = (((uTruth & ~uTruths[v][0]) << Shift) | ((uTruth & uTruths[v][0]) >> Shift)); + return uTruth; +} + +/**Function************************************************************* + + Synopsis [Performs phase transformation for one function of 6 variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] ) +{ + unsigned uTemp; + int v, Shift; + + // initialize the result + uTruthRes[0] = uTruth[0]; + uTruthRes[1] = uTruth[1]; + if ( uPhase == 0 ) + return; + // compute the phase + for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) + if ( uPhase & Shift ) + { + if ( Shift < 32 ) + { + uTruthRes[0] = (((uTruthRes[0] & ~uTruths[v][0]) << Shift) | ((uTruthRes[0] & uTruths[v][0]) >> Shift)); + uTruthRes[1] = (((uTruthRes[1] & ~uTruths[v][1]) << Shift) | ((uTruthRes[1] & uTruths[v][1]) >> Shift)); + } + else + { + uTemp = uTruthRes[0]; + uTruthRes[0] = uTruthRes[1]; + uTruthRes[1] = uTemp; + } + } +} + +/**Function************************************************************* + + Synopsis [Computes the N-canonical form of the Boolean function.] + + Description [The N-canonical form is defined as the truth table with + the minimum integer value. This function exhaustively enumerates + through the complete set of 2^N phase assignments.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ) +{ + unsigned uTruth0, uTruth1; + unsigned uCanon0, uCanon1, uCanonBest, uPhaseBest; + int i, Limit; + + if ( nVarsMax == 6 ) + return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes ); + + if ( nVarsReal < 5 ) + { +// return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes ); + + uTruth0 = uTruth[0] & 0xFFFF; + assert( p->pCounters[uTruth0] > 0 ); + uTruthRes[0] = (p->uCanons[uTruth0] << 16) | p->uCanons[uTruth0]; + uTruthRes[1] = uTruthRes[0]; + puPhases[0] = p->uPhases[uTruth0][0]; + return 1; + } + + assert( nVarsMax == 5 ); + assert( nVarsReal == 5 ); + uTruth0 = uTruth[0] & 0xFFFF; + uTruth1 = (uTruth[0] >> 16); + if ( uTruth1 == 0 ) + { + uTruthRes[0] = p->uCanons[uTruth0]; + uTruthRes[1] = uTruthRes[0]; + Limit = (p->pCounters[uTruth0] > 4)? 4 : p->pCounters[uTruth0]; + for ( i = 0; i < Limit; i++ ) + puPhases[i] = p->uPhases[uTruth0][i]; + return Limit; + } + else if ( uTruth0 == 0 ) + { + uTruthRes[0] = p->uCanons[uTruth1]; + uTruthRes[1] = uTruthRes[0]; + Limit = (p->pCounters[uTruth1] > 4)? 4 : p->pCounters[uTruth1]; + for ( i = 0; i < Limit; i++ ) + { + puPhases[i] = p->uPhases[uTruth1][i]; + puPhases[i] |= (1 << 4); + } + return Limit; + } + uCanon0 = p->uCanons[uTruth0]; + uCanon1 = p->uCanons[uTruth1]; + if ( uCanon0 >= uCanon1 ) // using nCanon1 as the main one + { + assert( p->pCounters[uTruth1] > 0 ); + uCanonBest = 0xFFFFFFFF; + for ( i = 0; i < p->pCounters[uTruth1]; i++ ) + { + uCanon0 = Extra_TruthPolarize( uTruth0, p->uPhases[uTruth1][i], 4 ); + if ( uCanonBest > uCanon0 ) + { + uCanonBest = uCanon0; + uPhaseBest = p->uPhases[uTruth1][i]; + assert( uPhaseBest < 16 ); + } + } + uTruthRes[0] = (uCanon1 << 16) | uCanonBest; + uTruthRes[1] = uTruthRes[0]; + puPhases[0] = uPhaseBest; + return 1; + } + else if ( uCanon0 < uCanon1 ) + { + assert( p->pCounters[uTruth0] > 0 ); + uCanonBest = 0xFFFFFFFF; + for ( i = 0; i < p->pCounters[uTruth0]; i++ ) + { + uCanon1 = Extra_TruthPolarize( uTruth1, p->uPhases[uTruth0][i], 4 ); + if ( uCanonBest > uCanon1 ) + { + uCanonBest = uCanon1; + uPhaseBest = p->uPhases[uTruth0][i]; + assert( uPhaseBest < 16 ); + } + } + uTruthRes[0] = (uCanon0 << 16) | uCanonBest; + uTruthRes[1] = uTruthRes[0]; + puPhases[0] = uPhaseBest | (1 << 4); + return 1; + } + else + { + assert( 0 ); + return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes ); + } +} + + + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperCore.c b/abc70930/src/map/mapper/mapperCore.c new file mode 100644 index 00000000..5d4854e6 --- /dev/null +++ b/abc70930/src/map/mapper/mapperCore.c @@ -0,0 +1,228 @@ +/**CFile**************************************************************** + + FileName [mapperCore.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperCore.c,v 1.7 2004/10/01 23:41:04 satrajit Exp $] + +***********************************************************************/ + +#include "mapperInt.h" +//#include "resm.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs technology mapping for the given object graph.] + + Description [The object graph is stored in the mapping manager. + First, the AND nodes that fanout into POs are collected in the DFS order. + Two preprocessing steps are performed: the k-feasible cuts are computed + for each node and the truth tables are computed for each cut. Next, the + delay-optimal matches are assigned for each node, followed by several + iterations of area recoveryd: using area flow (global optimization) + and using exact area at a node (local optimization).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_Mapping( Map_Man_t * p ) +{ + int fShowSwitching = 1; + int fUseAreaFlow = 1; + int fUseExactArea = !p->fSwitching; + int fUseExactAreaWithPhase = !p->fSwitching; + int clk; + + ////////////////////////////////////////////////////////////////////// + // perform pre-mapping computations + // collect the nodes reachable from POs in the DFS order (including the choices) + p->vAnds = Map_MappingDfs( p, 1 ); + if ( p->fVerbose ) + Map_MappingReportChoices( p ); + Map_MappingSetChoiceLevels( p ); // should always be called before mapping! +// return 1; + + // compute the cuts of nodes in the DFS order + clk = clock(); + Map_MappingCuts( p ); + p->timeCuts = clock() - clk; + // derive the truth tables + clk = clock(); + Map_MappingTruths( p ); + p->timeTruth = clock() - clk; + ////////////////////////////////////////////////////////////////////// +//PRT( "Truths", clock() - clk ); + + ////////////////////////////////////////////////////////////////////// + // compute the minimum-delay mapping + clk = clock(); + p->fMappingMode = 0; + if ( !Map_MappingMatches( p ) ) + return 0; + p->timeMatch = clock() - clk; + // compute the references and collect the nodes used in the mapping + Map_MappingSetRefs( p ); + p->AreaBase = Map_MappingGetArea( p, p->vMapping ); +if ( p->fVerbose ) +{ +printf( "Delay : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", + fShowSwitching? "Switch" : "Delay", + fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, + Map_MappingGetAreaFlow(p), p->AreaBase, 0.0 ); +PRT( "Time", p->timeMatch ); +} + ////////////////////////////////////////////////////////////////////// + + if ( !p->fAreaRecovery ) + { + if ( p->fVerbose ) + Map_MappingPrintOutputArrivals( p ); + return 1; + } + + ////////////////////////////////////////////////////////////////////// + // perform area recovery using area flow + clk = clock(); + if ( fUseAreaFlow ) + { + // compute the required times + Map_TimeComputeRequiredGlobal( p ); + // recover area flow + p->fMappingMode = 1; + Map_MappingMatches( p ); + // compute the references and collect the nodes used in the mapping + Map_MappingSetRefs( p ); + p->AreaFinal = Map_MappingGetArea( p, p->vMapping ); +if ( p->fVerbose ) +{ +printf( "AreaFlow : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", + fShowSwitching? "Switch" : "Delay", + fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, + Map_MappingGetAreaFlow(p), p->AreaFinal, + 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); +PRT( "Time", clock() - clk ); +} + } + p->timeArea += clock() - clk; + ////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + // perform area recovery using exact area + clk = clock(); + if ( fUseExactArea ) + { + // compute the required times + Map_TimeComputeRequiredGlobal( p ); + // recover area + p->fMappingMode = 2; + Map_MappingMatches( p ); + // compute the references and collect the nodes used in the mapping + Map_MappingSetRefs( p ); + p->AreaFinal = Map_MappingGetArea( p, p->vMapping ); +if ( p->fVerbose ) +{ +printf( "Area : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", + fShowSwitching? "Switch" : "Delay", + fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, + 0.0, p->AreaFinal, + 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); +PRT( "Time", clock() - clk ); +} + } + p->timeArea += clock() - clk; + ////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + // perform area recovery using exact area + clk = clock(); + if ( fUseExactAreaWithPhase ) + { + // compute the required times + Map_TimeComputeRequiredGlobal( p ); + // recover area + p->fMappingMode = 3; + Map_MappingMatches( p ); + // compute the references and collect the nodes used in the mapping + Map_MappingSetRefs( p ); + p->AreaFinal = Map_MappingGetArea( p, p->vMapping ); +if ( p->fVerbose ) +{ +printf( "Area : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", + fShowSwitching? "Switch" : "Delay", + fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, + 0.0, p->AreaFinal, + 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); +PRT( "Time", clock() - clk ); +} + } + p->timeArea += clock() - clk; + ////////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + // perform area recovery using exact area + clk = clock(); + if ( p->fSwitching ) + { + // compute the required times + Map_TimeComputeRequiredGlobal( p ); + // recover switching activity + p->fMappingMode = 4; + Map_MappingMatches( p ); + // compute the references and collect the nodes used in the mapping + Map_MappingSetRefs( p ); + p->AreaFinal = Map_MappingGetArea( p, p->vMapping ); +if ( p->fVerbose ) +{ +printf( "Switching: %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", + fShowSwitching? "Switch" : "Delay", + fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, + 0.0, p->AreaFinal, + 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); +PRT( "Time", clock() - clk ); +} + + // compute the required times + Map_TimeComputeRequiredGlobal( p ); + // recover switching activity + p->fMappingMode = 4; + Map_MappingMatches( p ); + // compute the references and collect the nodes used in the mapping + Map_MappingSetRefs( p ); + p->AreaFinal = Map_MappingGetArea( p, p->vMapping ); +if ( p->fVerbose ) +{ +printf( "Switching: %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", + fShowSwitching? "Switch" : "Delay", + fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, + 0.0, p->AreaFinal, + 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); +PRT( "Time", clock() - clk ); +} + } + p->timeArea += clock() - clk; + ////////////////////////////////////////////////////////////////////// + + // print the arrival times of the latest outputs + if ( p->fVerbose ) + Map_MappingPrintOutputArrivals( p ); + return 1; +} diff --git a/abc70930/src/map/mapper/mapperCreate.c b/abc70930/src/map/mapper/mapperCreate.c new file mode 100644 index 00000000..157d467b --- /dev/null +++ b/abc70930/src/map/mapper/mapperCreate.c @@ -0,0 +1,600 @@ +/**CFile**************************************************************** + + FileName [mapperCreate.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperCreate.c,v 1.15 2005/02/28 05:34:26 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Map_TableCreate( Map_Man_t * p ); +static void Map_TableResize( Map_Man_t * p ); +static Map_Node_t * Map_TableLookup( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); + +// hash key for the structural hash table +static inline unsigned Map_HashKey2( Map_Node_t * p0, Map_Node_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads parameters from the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_ManReadInputNum( Map_Man_t * p ) { return p->nInputs; } +int Map_ManReadOutputNum( Map_Man_t * p ) { return p->nOutputs; } +Map_Node_t ** Map_ManReadInputs ( Map_Man_t * p ) { return p->pInputs; } +Map_Node_t ** Map_ManReadOutputs( Map_Man_t * p ) { return p->pOutputs; } +Map_Node_t * Map_ManReadConst1 ( Map_Man_t * p ) { return p->pConst1; } +Map_Time_t * Map_ManReadInputArrivals( Map_Man_t * p ) { return p->pInputArrivals;} +Mio_Library_t * Map_ManReadGenLib ( Map_Man_t * p ) { return p->pSuperLib->pGenlib; } +bool Map_ManReadVerbose( Map_Man_t * p ) { return p->fVerbose; } +float Map_ManReadAreaFinal( Map_Man_t * p ) { return p->AreaFinal; } +float Map_ManReadRequiredGlo( Map_Man_t * p ) { return p->fRequiredGlo; } +void Map_ManSetTimeToMap( Map_Man_t * p, int Time ) { p->timeToMap = Time; } +void Map_ManSetTimeToNet( Map_Man_t * p, int Time ) { p->timeToNet = Time; } +void Map_ManSetTimeSweep( Map_Man_t * p, int Time ) { p->timeSweep = Time; } +void Map_ManSetTimeTotal( Map_Man_t * p, int Time ) { p->timeTotal = Time; } +void Map_ManSetOutputNames( Map_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; } +void Map_ManSetAreaRecovery( Map_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;} +void Map_ManSetDelayTarget( Map_Man_t * p, float DelayTarget ) { p->DelayTarget = DelayTarget;} +void Map_ManSetInputArrivals( Map_Man_t * p, Map_Time_t * pArrivals ) { p->pInputArrivals = pArrivals;} +void Map_ManSetObeyFanoutLimits( Map_Man_t * p, bool fObeyFanoutLimits ) { p->fObeyFanoutLimits = fObeyFanoutLimits; } +void Map_ManSetNumIterations( Map_Man_t * p, int nIterations ) { p->nIterations = nIterations; } +int Map_ManReadFanoutViolations( Map_Man_t * p ) { return p->nFanoutViolations; } +void Map_ManSetFanoutViolations( Map_Man_t * p, int nVio ) { p->nFanoutViolations = nVio; } +void Map_ManSetChoiceNodeNum( Map_Man_t * p, int nChoiceNodes ) { p->nChoiceNodes = nChoiceNodes; } +void Map_ManSetChoiceNum( Map_Man_t * p, int nChoices ) { p->nChoices = nChoices; } +void Map_ManSetVerbose( Map_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; } +void Map_ManSetSwitching( Map_Man_t * p, int fSwitching ) { p->fSwitching = fSwitching; } + +/**Function************************************************************* + + Synopsis [Reads parameters from the mapping node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Man_t * Map_NodeReadMan( Map_Node_t * p ) { return p->p; } +char * Map_NodeReadData( Map_Node_t * p, int fPhase ) { return fPhase? p->pData1 : p->pData0; } +int Map_NodeReadNum( Map_Node_t * p ) { return p->Num; } +int Map_NodeReadLevel( Map_Node_t * p ) { return Map_Regular(p)->Level; } +Map_Cut_t * Map_NodeReadCuts( Map_Node_t * p ) { return p->pCuts; } +Map_Cut_t * Map_NodeReadCutBest( Map_Node_t * p, int fPhase ) { return p->pCutBest[fPhase]; } +Map_Node_t * Map_NodeReadOne( Map_Node_t * p ) { return p->p1; } +Map_Node_t * Map_NodeReadTwo( Map_Node_t * p ) { return p->p2; } +void Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData ) { if (fPhase) p->pData1 = pData; else p->pData0 = pData; } +void Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE ) { p->pNextE = pNextE; } +void Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr ) { p->pRepr = pRepr; } +void Map_NodeSetSwitching( Map_Node_t * p, float Switching ) { p->Switching = Switching; } + +/**Function************************************************************* + + Synopsis [Checks the type of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_NodeIsConst( Map_Node_t * p ) { return (Map_Regular(p))->Num == -1; } +int Map_NodeIsVar( Map_Node_t * p ) { return (Map_Regular(p))->p1 == NULL && (Map_Regular(p))->Num >= 0; } +int Map_NodeIsAnd( Map_Node_t * p ) { return (Map_Regular(p))->p1 != NULL; } +int Map_NodeComparePhase( Map_Node_t * p1, Map_Node_t * p2 ) { assert( !Map_IsComplement(p1) ); assert( !Map_IsComplement(p2) ); return p1->fInv ^ p2->fInv; } + +/**Function************************************************************* + + Synopsis [Reads parameters from the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Super_t * Map_CutReadSuperBest( Map_Cut_t * p, int fPhase ) { return p->M[fPhase].pSuperBest;} +Map_Super_t * Map_CutReadSuper0( Map_Cut_t * p ) { return p->M[0].pSuperBest;} +Map_Super_t * Map_CutReadSuper1( Map_Cut_t * p ) { return p->M[1].pSuperBest;} +int Map_CutReadLeavesNum( Map_Cut_t * p ) { return p->nLeaves; } +Map_Node_t ** Map_CutReadLeaves( Map_Cut_t * p ) { return p->ppLeaves; } +unsigned Map_CutReadPhaseBest( Map_Cut_t * p, int fPhase ) { return p->M[fPhase].uPhaseBest;} +unsigned Map_CutReadPhase0( Map_Cut_t * p ) { return p->M[0].uPhaseBest;} +unsigned Map_CutReadPhase1( Map_Cut_t * p ) { return p->M[1].uPhaseBest;} +Map_Cut_t * Map_CutReadNext( Map_Cut_t * p ) { return p->pNext; } + +/**Function************************************************************* + + Synopsis [Reads parameters from the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Map_SuperReadFormula( Map_Super_t * p ) { return p->pFormula; } +Mio_Gate_t * Map_SuperReadRoot( Map_Super_t * p ) { return p->pRoot; } +int Map_SuperReadNum( Map_Super_t * p ) { return p->Num; } +Map_Super_t ** Map_SuperReadFanins( Map_Super_t * p ) { return p->pFanins; } +int Map_SuperReadFaninNum( Map_Super_t * p ) { return p->nFanins; } +Map_Super_t * Map_SuperReadNext( Map_Super_t * p ) { return p->pNext; } +int Map_SuperReadNumPhases( Map_Super_t * p ) { return p->nPhases; } +unsigned char * Map_SuperReadPhases( Map_Super_t * p ) { return p->uPhases; } +int Map_SuperReadFanoutLimit( Map_Super_t * p ) { return p->nFanLimit;} + +Mio_Library_t * Map_SuperLibReadGenLib( Map_SuperLib_t * p ) { return p->pGenlib; } +float Map_SuperLibReadAreaInv( Map_SuperLib_t * p ) { return p->AreaInv; } +Map_Time_t Map_SuperLibReadDelayInv( Map_SuperLib_t * p ) { return p->tDelayInv;} +int Map_SuperLibReadVarsMax( Map_SuperLib_t * p ) { return p->nVarsMax; } + + +/**Function************************************************************* + + Synopsis [Create the mapping manager.] + + Description [The number of inputs and outputs is assumed to be + known is advance. It is much simpler to have them fixed upfront. + When it comes to representing the object graph in the form of + AIG, the resulting manager is similar to the regular AIG manager, + except that it does not use reference counting (and therefore + does not have garbage collections). It does have table resizing. + The data structure is more flexible to represent additional + information needed for mapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose ) +{ + Map_Man_t * p; + int i; + + // derive the supergate library + if ( Abc_FrameReadLibSuper() == NULL ) + { + printf( "The supergate library is not specified. Use \"read_library\" or \"read_super\".\n" ); + return NULL; + } + + // start the manager + p = ALLOC( Map_Man_t, 1 ); + memset( p, 0, sizeof(Map_Man_t) ); + p->pSuperLib = Abc_FrameReadLibSuper(); + p->nVarsMax = p->pSuperLib->nVarsMax; + p->fVerbose = fVerbose; + p->fEpsilon = (float)0.001; + assert( p->nVarsMax > 0 ); + + if ( p->nVarsMax == 5 ) + Extra_Truth4VarN( &p->uCanons, &p->uPhases, &p->pCounters, 8 ); + + // start various data structures + Map_TableCreate( p ); + Map_MappingSetupTruthTables( p->uTruths ); + Map_MappingSetupTruthTablesLarge( p->uTruthsLarge ); +// printf( "Node = %d bytes. Cut = %d bytes. Super = %d bytes.\n", sizeof(Map_Node_t), sizeof(Map_Cut_t), sizeof(Map_Super_t) ); + p->mmNodes = Extra_MmFixedStart( sizeof(Map_Node_t) ); + p->mmCuts = Extra_MmFixedStart( sizeof(Map_Cut_t) ); + + // make sure the constant node will get index -1 + p->nNodes = -1; + // create the constant node + p->pConst1 = Map_NodeCreate( p, NULL, NULL ); + p->vNodesAll = Map_NodeVecAlloc( 100 ); + p->vNodesTemp = Map_NodeVecAlloc( 100 ); + p->vMapping = Map_NodeVecAlloc( 100 ); + p->vVisited = Map_NodeVecAlloc( 100 ); + + // create the PI nodes + p->nInputs = nInputs; + p->pInputs = ALLOC( Map_Node_t *, nInputs ); + for ( i = 0; i < nInputs; i++ ) + p->pInputs[i] = Map_NodeCreate( p, NULL, NULL ); + + // create the place for the output nodes + p->nOutputs = nOutputs; + p->pOutputs = ALLOC( Map_Node_t *, nOutputs ); + memset( p->pOutputs, 0, sizeof(Map_Node_t *) * nOutputs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_ManFree( Map_Man_t * p ) +{ +// int i; +// for ( i = 0; i < p->vNodesAll->nSize; i++ ) +// Map_NodeVecFree( p->vNodesAll->pArray[i]->vFanouts ); +// Map_NodeVecFree( p->pConst1->vFanouts ); + if ( p->vAnds ) + Map_NodeVecFree( p->vAnds ); + if ( p->vNodesAll ) + Map_NodeVecFree( p->vNodesAll ); + if ( p->vNodesTemp ) + Map_NodeVecFree( p->vNodesTemp ); + if ( p->vMapping ) + Map_NodeVecFree( p->vMapping ); + if ( p->vVisited ) + Map_NodeVecFree( p->vVisited ); + if ( p->uCanons ) free( p->uCanons ); + if ( p->uPhases ) free( p->uPhases ); + if ( p->pCounters ) free( p->pCounters ); + Extra_MmFixedStop( p->mmNodes ); + Extra_MmFixedStop( p->mmCuts ); + FREE( p->pInputArrivals ); + FREE( p->pInputs ); + FREE( p->pOutputs ); + FREE( p->pBins ); + FREE( p->ppOutputNames ); + FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Deallocates the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_ManPrintTimeStats( Map_Man_t * p ) +{ + printf( "N-canonical = %d. Matchings = %d. Phases = %d. ", p->nCanons, p->nMatches, p->nPhases ); + printf( "Choice nodes = %d. Choices = %d.\n", p->nChoiceNodes, p->nChoices ); + PRT( "ToMap", p->timeToMap ); + PRT( "Cuts ", p->timeCuts ); + PRT( "Truth", p->timeTruth ); + PRT( "Match", p->timeMatch ); + PRT( "Area ", p->timeArea ); + PRT( "Sweep", p->timeSweep ); + PRT( "ToNet", p->timeToNet ); + PRT( "TOTAL", p->timeTotal ); + if ( p->time1 ) { PRT( "time1", p->time1 ); } + if ( p->time2 ) { PRT( "time2", p->time2 ); } + if ( p->time3 ) { PRT( "time3", p->time3 ); } +} + +/**Function************************************************************* + + Synopsis [Prints the mapping stats.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_ManPrintStatsToFile( char * pName, float Area, float Delay, int Time ) +{ + FILE * pTable; + pTable = fopen( "map_stats.txt", "a+" ); + fprintf( pTable, "%s ", pName ); + fprintf( pTable, "%4.2f ", Area ); + fprintf( pTable, "%4.2f ", Delay ); + fprintf( pTable, "%4.2f\n", (float)(Time)/(float)(CLOCKS_PER_SEC) ); + fclose( pTable ); +} + +/**Function************************************************************* + + Synopsis [Creates a new node.] + + Description [This procedure should be called to create the constant + node and the PI nodes first.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Node_t * Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ) +{ + Map_Node_t * pNode; + // create the node + pNode = (Map_Node_t *)Extra_MmFixedEntryFetch( p->mmNodes ); + memset( pNode, 0, sizeof(Map_Node_t) ); + pNode->tRequired[0].Rise = pNode->tRequired[0].Fall = pNode->tRequired[0].Worst = MAP_FLOAT_LARGE; + pNode->tRequired[1].Rise = pNode->tRequired[1].Fall = pNode->tRequired[1].Worst = MAP_FLOAT_LARGE; + pNode->p1 = p1; + pNode->p2 = p2; + pNode->p = p; + // set the number of this node + pNode->Num = p->nNodes++; + // place to store the fanouts +// pNode->vFanouts = Map_NodeVecAlloc( 5 ); + // store this node in the internal array + if ( pNode->Num >= 0 ) + Map_NodeVecPush( p->vNodesAll, pNode ); + else + pNode->fInv = 1; + // set the level of this node + if ( p1 ) + { +#ifdef MAP_ALLOCATE_FANOUT + // create the fanout info + Map_NodeAddFaninFanout( Map_Regular(p1), pNode ); + Map_NodeAddFaninFanout( Map_Regular(p2), pNode ); +#endif + pNode->Level = 1 + MAP_MAX(Map_Regular(pNode->p1)->Level, Map_Regular(pNode->p2)->Level); + pNode->fInv = Map_NodeIsSimComplement(p1) & Map_NodeIsSimComplement(p2); + } + // reference the inputs (will be used to compute the number of fanouts) + if ( p1 ) Map_NodeRef(p1); + if ( p2 ) Map_NodeRef(p2); + + pNode->nRefEst[0] = pNode->nRefEst[1] = -1; + return pNode; +} + +/**Function************************************************************* + + Synopsis [Create the unique table of AND gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_TableCreate( Map_Man_t * pMan ) +{ + assert( pMan->pBins == NULL ); + pMan->nBins = Cudd_Prime(5000); + pMan->pBins = ALLOC( Map_Node_t *, pMan->nBins ); + memset( pMan->pBins, 0, sizeof(Map_Node_t *) * pMan->nBins ); + pMan->nNodes = 0; +} + +/**Function************************************************************* + + Synopsis [Looks up the AND2 node in the unique table.] + + Description [This procedure implements one-level hashing. All the nodes + are hashed by their children. If the node with the same children was already + created, it is returned by the call to this procedure. If it does not exist, + this procedure creates a new node with these children. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Node_t * Map_TableLookup( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 ) +{ + Map_Node_t * pEnt; + unsigned Key; + + if ( p1 == p2 ) + return p1; + if ( p1 == Map_Not(p2) ) + return Map_Not(pMan->pConst1); + if ( Map_NodeIsConst(p1) ) + { + if ( p1 == pMan->pConst1 ) + return p2; + return Map_Not(pMan->pConst1); + } + if ( Map_NodeIsConst(p2) ) + { + if ( p2 == pMan->pConst1 ) + return p1; + return Map_Not(pMan->pConst1); + } + + if ( Map_Regular(p1)->Num > Map_Regular(p2)->Num ) + pEnt = p1, p1 = p2, p2 = pEnt; + + Key = Map_HashKey2( p1, p2, pMan->nBins ); + for ( pEnt = pMan->pBins[Key]; pEnt; pEnt = pEnt->pNext ) + if ( pEnt->p1 == p1 && pEnt->p2 == p2 ) + return pEnt; + // resize the table + if ( pMan->nNodes >= 2 * pMan->nBins ) + { + Map_TableResize( pMan ); + Key = Map_HashKey2( p1, p2, pMan->nBins ); + } + // create the new node + pEnt = Map_NodeCreate( pMan, p1, p2 ); + // add the node to the corresponding linked list in the table + pEnt->pNext = pMan->pBins[Key]; + pMan->pBins[Key] = pEnt; + return pEnt; +} + + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_TableResize( Map_Man_t * pMan ) +{ + Map_Node_t ** pBinsNew; + Map_Node_t * pEnt, * pEnt2; + int nBinsNew, Counter, i, clk; + unsigned Key; + +clk = clock(); + // get the new table size + nBinsNew = Cudd_Prime(2 * pMan->nBins); + // allocate a new array + pBinsNew = ALLOC( Map_Node_t *, nBinsNew ); + memset( pBinsNew, 0, sizeof(Map_Node_t *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < pMan->nBins; i++ ) + for ( pEnt = pMan->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; + pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL ) + { + Key = Map_HashKey2( pEnt->p1, pEnt->p2, nBinsNew ); + pEnt->pNext = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == pMan->nNodes - pMan->nInputs ); + if ( pMan->fVerbose ) + { +// printf( "Increasing the unique table size from %6d to %6d. ", pMan->nBins, nBinsNew ); +// PRT( "Time", clock() - clk ); + } + // replace the table and the parameters + free( pMan->pBins ); + pMan->pBins = pBinsNew; + pMan->nBins = nBinsNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Node_t * Map_NodeAnd( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ) +{ + Map_Node_t * pNode; + pNode = Map_TableLookup( p, p1, p2 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Node_t * Map_NodeOr( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ) +{ + Map_Node_t * pNode; + pNode = Map_Not( Map_TableLookup( p, Map_Not(p1), Map_Not(p2) ) ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Node_t * Map_NodeExor( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ) +{ + return Map_NodeMux( p, p1, Map_Not(p2), p2 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Node_t * Map_NodeMux( Map_Man_t * p, Map_Node_t * pC, Map_Node_t * pT, Map_Node_t * pE ) +{ + Map_Node_t * pAnd1, * pAnd2, * pRes; + pAnd1 = Map_TableLookup( p, pC, pT ); + pAnd2 = Map_TableLookup( p, Map_Not(pC), pE ); + pRes = Map_NodeOr( p, pAnd1, pAnd2 ); + return pRes; +} + + +/**Function************************************************************* + + Synopsis [Sets the node to be equivalent to the given one.] + + Description [This procedure is a work-around for the equivalence check. + Does not verify the equivalence. Use at the user's risk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeSetChoice( Map_Man_t * pMan, Map_Node_t * pNodeOld, Map_Node_t * pNodeNew ) +{ + pNodeNew->pNextE = pNodeOld->pNextE; + pNodeOld->pNextE = pNodeNew; + pNodeNew->pRepr = pNodeOld; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/map/mapper/mapperCut.c b/abc70930/src/map/mapper/mapperCut.c new file mode 100644 index 00000000..b05e9d0c --- /dev/null +++ b/abc70930/src/map/mapper/mapperCut.c @@ -0,0 +1,1168 @@ +/**CFile**************************************************************** + + FileName [mapperCut.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperCut.c,v 1.12 2005/02/28 05:34:27 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the largest number of cuts considered +#define MAP_CUTS_MAX_COMPUTE 1000 +// the largest number of cuts used +#define MAP_CUTS_MAX_USE 250 + +// temporary hash table to store the cuts +typedef struct Map_CutTableStrutct_t Map_CutTable_t; +struct Map_CutTableStrutct_t +{ + Map_Cut_t ** pBins; // the table used for linear probing + int nBins; // the size of the table + int * pCuts; // the array of cuts currently stored + int nCuts; // the number of cuts currently stored + Map_Cut_t ** pArray; // the temporary array of cuts + Map_Cut_t ** pCuts1; // the temporary array of cuts + Map_Cut_t ** pCuts2; // the temporary array of cuts +}; + +// primes used to compute the hash key +static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 }; + +static Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode ); +static void Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode ); +static Map_Cut_t * Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable, Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 ); +static int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax ); +static Map_Cut_t * Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 ); +static int Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes ); + +static void Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot ); +static void Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot ); +static void Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot ); + +static Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan ); +static void Map_CutTableStop( Map_CutTable_t * p ); +static unsigned Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes ); +static int Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ); +static Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ); +static void Map_CutTableRestart( Map_CutTable_t * p ); + +static Map_Cut_t * Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList ); +static int Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList ); +static Map_Cut_t * Map_CutArray2List( Map_Cut_t ** pArray, int nCuts ); + +static unsigned Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Map_Cut_t * pTemp0, Map_Cut_t * pTemp1, int fComp0, int fComp1 ); + +// iterator through all the cuts of the list +#define Map_ListForEachCut( pList, pCut ) \ + for ( pCut = pList; \ + pCut; \ + pCut = pCut->pNext ) +#define Map_ListForEachCutSafe( pList, pCut, pCut2 ) \ + for ( pCut = pList, \ + pCut2 = pCut? pCut->pNext: NULL; \ + pCut; \ + pCut = pCut2, \ + pCut2 = pCut? pCut->pNext: NULL ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the cuts for each node in the object graph.] + + Description [The cuts are computed in one sweep over the mapping graph. + First, the elementary cuts, which include the node itself, are assigned + to the PI nodes. The internal nodes are considered in the DFS order. + Each node is two-input AND-gate. So to compute the cuts at a node, we + need to merge the sets of cuts of its two predecessors. The merged set + contains only unique cuts with the number of inputs equal to k or less. + Finally, the elementary cut, composed of the node itself, is added to + the set of cuts for the node. + + This procedure is pretty fast for 5-feasible cuts, but it dramatically + slows down on some "dense" networks when computing 6-feasible cuts. + The problem is that there are too many cuts in this case. We should + think how to heuristically trim the number of cuts in such cases, + to have reasonable runtime.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingCuts( Map_Man_t * p ) +{ + ProgressBar * pProgress; + Map_CutTable_t * pTable; + Map_Node_t * pNode; + Map_Cut_t * pCut; + int nCuts, nNodes, i; + int clk = clock(); + // set the elementary cuts for the PI variables + assert( p->nVarsMax > 1 && p->nVarsMax < 7 ); + for ( i = 0; i < p->nInputs; i++ ) + { + pCut = Map_CutAlloc( p ); + pCut->nLeaves = 1; + pCut->ppLeaves[0] = p->pInputs[i]; + p->pInputs[i]->pCuts = pCut; + p->pInputs[i]->pCutBest[0] = NULL; // negative polarity is not mapped + p->pInputs[i]->pCutBest[1] = pCut; // positive polarity is a trivial cut + pCut->uTruth = 0xAAAAAAAA; // the first variable "10101010" + pCut->M[0].AreaFlow = 0.0; + pCut->M[1].AreaFlow = 0.0; + } + + // compute the cuts for the internal nodes + nNodes = p->vAnds->nSize; + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + pTable = Map_CutTableStart( p ); + for ( i = 0; i < nNodes; i++ ) + { + pNode = p->vAnds->pArray[i]; + if ( !Map_NodeIsAnd( pNode ) ) + continue; + Map_CutCompute( p, pTable, pNode ); + Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." ); + } + Extra_ProgressBarStop( pProgress ); + Map_CutTableStop( pTable ); + + // report the stats + if ( p->fVerbose ) + { + nCuts = Map_MappingCountAllCuts(p); + printf( "Nodes = %6d. Total %d-feasible cuts = %10d. Per node = %.1f. ", + p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes ); + PRT( "Time", clock() - clk ); + } + + // print the cuts for the first primary output +// Map_CutListPrint( p, Map_Regular(p->pOutputs[0]) ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode ) +{ + Map_Node_t * pTemp; + Map_Cut_t * pList, * pList1, * pList2; + Map_Cut_t * pCut; + + // if the cuts are computed return them + if ( pNode->pCuts ) + return pNode->pCuts; + + // compute the cuts for the children + pList1 = Map_Regular(pNode->p1)->pCuts; + pList2 = Map_Regular(pNode->p2)->pCuts; + // merge the lists + pList = Map_CutMergeLists( p, pTable, pList1, pList2, + Map_IsComplement(pNode->p1), Map_IsComplement(pNode->p2) ); + // if there are functionally equivalent nodes, union them with this list + assert( pList ); + // only add to the list of cuts if the node is a representative one + if ( pNode->pRepr == NULL ) + { + for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) + { + assert( pTemp->pCuts ); + pList = Map_CutUnionLists( pList, pTemp->pCuts ); + assert( pTemp->pCuts ); + pList = Map_CutSortCuts( p, pTable, pList ); + } + } + // add the new cut + pCut = Map_CutAlloc( p ); + pCut->nLeaves = 1; + pCut->ppLeaves[0] = pNode; + pCut->uTruth = 0xAAAAAAAA; + // append (it is important that the elementary cut is appended first) + pCut->pNext = pList; + // set at the node + pNode->pCuts = pCut; + // remove the dominated cuts + Map_CutFilter( p, pNode ); + // set the phase correctly + if ( pNode->pRepr && Map_NodeComparePhase(pNode, pNode->pRepr) ) + { + Map_ListForEachCut( pNode->pCuts, pCut ) + pCut->Phase = 1; + } +/* + { + int i, Counter = 0;; + for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) + for ( i = 0; i < pCut->nLeaves; i++ ) + Counter += (pCut->ppLeaves[i]->Level >= pNode->Level); +// if ( Counter ) +// printf( " %d", Counter ); + } +*/ + return pCut; +} + +/**Function************************************************************* + + Synopsis [Filter the cuts using dominance.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode ) +{ + Map_Cut_t * pTemp, * pPrev, * pCut, * pCut2; + int i, k, Counter; + + Counter = 0; + pPrev = pNode->pCuts; + Map_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 ) + { + // go through all the previous cuts up to pCut + for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext ) + { + // check if every node in pTemp is contained in pCut + for ( i = 0; i < pTemp->nLeaves; i++ ) + { + for ( k = 0; k < pCut->nLeaves; k++ ) + if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] ) + break; + if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut + break; + } + if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut + { + Counter++; + break; + } + } + if ( pTemp != pCut ) // pTemp contain pCut + { + pPrev->pNext = pCut->pNext; // skip pCut + // recycle pCut + Map_CutFree( p, pCut ); + } + else + pPrev = pCut; + } +// printf( "Dominated = %3d. \n", Counter ); +} + +/**Function************************************************************* + + Synopsis [Merges two lists of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Cut_t * Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable, + Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 ) +{ + Map_Node_t * ppNodes[6]; + Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL }; + Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; + int nNodes, Counter, i; + Map_Cut_t ** ppArray1, ** ppArray2, ** ppArray3; + int nCuts1, nCuts2, nCuts3, k, fComp3; + + ppArray1 = pTable->pCuts1; + ppArray2 = pTable->pCuts2; + nCuts1 = Map_CutList2Array( ppArray1, pList1 ); + nCuts2 = Map_CutList2Array( ppArray2, pList2 ); + // swap the lists based on their length + if ( nCuts1 > nCuts2 ) + { + ppArray3 = ppArray1; + ppArray1 = ppArray2; + ppArray2 = ppArray3; + + nCuts3 = nCuts1; + nCuts1 = nCuts2; + nCuts2 = nCuts3; + + fComp3 = fComp1; + fComp1 = fComp2; + fComp2 = fComp3; + } + // pList1 is shorter or equal length compared to pList2 + + // prepare the manager for the cut computation + Map_CutTableRestart( pTable ); + // go through the cut pairs + Counter = 0; +// for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext ) +// for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext ) + for ( i = 0; i < nCuts1; i++ ) + { + for ( k = 0; k <= i; k++ ) + { + pTemp1 = ppArray1[i]; + pTemp2 = ppArray2[k]; + + if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) + { + if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) + continue; + if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) + continue; + } + + // check if k-feasible cut exists + nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); + if ( nNodes == 0 ) + continue; + // consider the cut for possible addition to the set of new cuts + pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); + if ( pCut == NULL ) + continue; + // add data to the cut + pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); + pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); +// if ( p->nVarsMax == 5 ) +// pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 ); + // add it to the corresponding list + pCut->pNext = pLists[pCut->nLeaves]; + pLists[pCut->nLeaves] = pCut; + // count this cut and quit if limit is reached + Counter++; + if ( Counter == MAP_CUTS_MAX_COMPUTE ) + goto QUITS; + } + for ( k = 0; k < i; k++ ) + { + pTemp1 = ppArray1[k]; + pTemp2 = ppArray2[i]; + + if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) + { + if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) + continue; + if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) + continue; + } + + // check if k-feasible cut exists + nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); + if ( nNodes == 0 ) + continue; + // consider the cut for possible addition to the set of new cuts + pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); + if ( pCut == NULL ) + continue; + // add data to the cut + pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); + pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); +// if ( p->nVarsMax == 5 ) +// pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 ); + // add it to the corresponding list + pCut->pNext = pLists[pCut->nLeaves]; + pLists[pCut->nLeaves] = pCut; + // count this cut and quit if limit is reached + Counter++; + if ( Counter == MAP_CUTS_MAX_COMPUTE ) + goto QUITS; + } + } + // consider the rest of them + for ( i = nCuts1; i < nCuts2; i++ ) + for ( k = 0; k < nCuts1; k++ ) + { + pTemp1 = ppArray1[k]; + pTemp2 = ppArray2[i]; + + if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) + { + if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) + continue; + if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) + continue; + } + + // check if k-feasible cut exists + nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); + if ( nNodes == 0 ) + continue; + // consider the cut for possible addition to the set of new cuts + pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); + if ( pCut == NULL ) + continue; + // add data to the cut + pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); + pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); +// if ( p->nVarsMax == 5 ) +// pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 ); + // add it to the corresponding list + pCut->pNext = pLists[pCut->nLeaves]; + pLists[pCut->nLeaves] = pCut; + // count this cut and quit if limit is reached + Counter++; + if ( Counter == MAP_CUTS_MAX_COMPUTE ) + goto QUITS; + } +QUITS : + // combine all the lists into one + pListNew = NULL; + ppListNew = &pListNew; + for ( i = 1; i <= p->nVarsMax; i++ ) + { + if ( pLists[i] == NULL ) + continue; + // find the last entry + for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; + pPrev = pCut, pCut = pCut->pNext ); + // connect these lists + *ppListNew = pLists[i]; + ppListNew = &pPrev->pNext; + } + *ppListNew = NULL; + // soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE + pListNew = Map_CutSortCuts( p, pTable, pListNew ); + return pListNew; +} + + +/**Function************************************************************* + + Synopsis [Merges two lists of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Cut_t * Map_CutMergeLists2( Map_Man_t * p, Map_CutTable_t * pTable, + Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 ) +{ + Map_Node_t * ppNodes[6]; + Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL }; + Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; + int nNodes, Counter, i; + + // prepare the manager for the cut computation + Map_CutTableRestart( pTable ); + // go through the cut pairs + Counter = 0; + for ( pTemp1 = pList1; pTemp1; pTemp1 = pTemp1->pNext ) + for ( pTemp2 = pList2; pTemp2; pTemp2 = pTemp2->pNext ) + { + // check if k-feasible cut exists + nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); + if ( nNodes == 0 ) + continue; + // consider the cut for possible addition to the set of new cuts + pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); + if ( pCut == NULL ) + continue; + // add data to the cut + pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); + pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); + // add it to the corresponding list + pCut->pNext = pLists[pCut->nLeaves]; + pLists[pCut->nLeaves] = pCut; + // count this cut and quit if limit is reached + Counter++; + if ( Counter == MAP_CUTS_MAX_COMPUTE ) + goto QUITS; + } +QUITS : + // combine all the lists into one + pListNew = NULL; + ppListNew = &pListNew; + for ( i = 1; i <= p->nVarsMax; i++ ) + { + if ( pLists[i] == NULL ) + continue; + // find the last entry + for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; + pPrev = pCut, pCut = pCut->pNext ); + // connect these lists + *ppListNew = pLists[i]; + ppListNew = &pPrev->pNext; + } + *ppListNew = NULL; + // soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE + pListNew = Map_CutSortCuts( p, pTable, pListNew ); + return pListNew; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [Returns the number of nodes in the resulting cut, or 0 if the + cut is infeasible. Returns the resulting nodes in the array ppNodes[].] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax ) +{ + Map_Node_t * pNodeTemp; + int nTotal, i, k, min, fMismatch; + + // check the special case when at least of the cuts is the largest + if ( pCut1->nLeaves == nNodesMax ) + { + if ( pCut2->nLeaves == nNodesMax ) + { + // return 0 if the cuts are different + for ( i = 0; i < nNodesMax; i++ ) + if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] ) + return 0; + // return nNodesMax if they are the same + for ( i = 0; i < nNodesMax; i++ ) + ppNodes[i] = pCut1->ppLeaves[i]; + return nNodesMax; + } + else if ( pCut2->nLeaves == nNodesMax - 1 ) + { + // return 0 if the cuts are different + fMismatch = 0; + for ( i = 0; i < nNodesMax; i++ ) + if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] ) + { + if ( fMismatch == 1 ) + return 0; + fMismatch = 1; + } + // return nNodesMax if they are the same + for ( i = 0; i < nNodesMax; i++ ) + ppNodes[i] = pCut1->ppLeaves[i]; + return nNodesMax; + } + } + else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax ) + { + // return 0 if the cuts are different + fMismatch = 0; + for ( i = 0; i < nNodesMax; i++ ) + if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] ) + { + if ( fMismatch == 1 ) + return 0; + fMismatch = 1; + } + // return nNodesMax if they are the same + for ( i = 0; i < nNodesMax; i++ ) + ppNodes[i] = pCut2->ppLeaves[i]; + return nNodesMax; + } + + // count the number of unique entries in pCut2 + nTotal = pCut1->nLeaves; + for ( i = 0; i < pCut2->nLeaves; i++ ) + { + // try to find this entry among the leaves of pCut1 + for ( k = 0; k < pCut1->nLeaves; k++ ) + if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] ) + break; + if ( k < pCut1->nLeaves ) // found + continue; + // we found a new entry to add + if ( nTotal == nNodesMax ) + return 0; + ppNodes[nTotal++] = pCut2->ppLeaves[i]; + } + // we know that the feasible cut exists + + // add the starting entries + for ( k = 0; k < pCut1->nLeaves; k++ ) + ppNodes[k] = pCut1->ppLeaves[k]; + + // selection-sort the entries + for ( i = 0; i < nTotal - 1; i++ ) + { + min = i; + for ( k = i+1; k < nTotal; k++ ) +// if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!) + if ( ppNodes[k]->Num < ppNodes[min]->Num ) + min = k; + pNodeTemp = ppNodes[i]; + ppNodes[i] = ppNodes[min]; + ppNodes[min] = pNodeTemp; + } + + return nTotal; +} + +/**Function************************************************************* + + Synopsis [Computes the union of the two lists of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Cut_t * Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 ) +{ + Map_Cut_t * pTemp, * pRoot; + // find the last cut in the first list + pRoot = pList1; + Map_ListForEachCut( pList1, pTemp ) + pRoot = pTemp; + // attach the non-trival part of the second cut to the end of the first + assert( pRoot->pNext == NULL ); + pRoot->pNext = pList2->pNext; + pList2->pNext = NULL; + return pList1; +} + + +/**Function************************************************************* + + Synopsis [Checks whether the given cut belongs to the list.] + + Description [This procedure takes most of the runtime in the cut + computation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes ) +{ + Map_Cut_t * pTemp; + int i; + for ( pTemp = pList; pTemp; pTemp = pTemp->pNext ) + { + for ( i = 0; i < nNodes; i++ ) + if ( pTemp->ppLeaves[i] != ppNodes[i] ) + break; + if ( i == nNodes ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Counts all the cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MappingCountAllCuts( Map_Man_t * pMan ) +{ + Map_Node_t * pNode; + Map_Cut_t * pCut; + int i, nCuts; +// int nCuts55 = 0, nCuts5x = 0, nCuts4x = 0, nCuts3x = 0; +// int pCounts[7] = {0}; + nCuts = 0; + for ( i = 0; i < pMan->nBins; i++ ) + for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) + for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) + if ( pCut->nLeaves > 1 ) // skip the elementary cuts + { + nCuts++; +/* + if ( Map_CutRegular(pCut->pOne)->nLeaves == 5 && Map_CutRegular(pCut->pTwo)->nLeaves == 5 ) + nCuts55++; + if ( Map_CutRegular(pCut->pOne)->nLeaves == 5 || Map_CutRegular(pCut->pTwo)->nLeaves == 5 ) + nCuts5x++; + else if ( Map_CutRegular(pCut->pOne)->nLeaves == 4 || Map_CutRegular(pCut->pTwo)->nLeaves == 4 ) + nCuts4x++; + else if ( Map_CutRegular(pCut->pOne)->nLeaves == 3 || Map_CutRegular(pCut->pTwo)->nLeaves == 3 ) + nCuts3x++; +*/ +// pCounts[ Map_CutRegular(pCut->pOne)->nLeaves ]++; +// pCounts[ Map_CutRegular(pCut->pTwo)->nLeaves ]++; + } +// printf( "Total cuts = %6d. 55 = %6d. 5x = %6d. 4x = %6d. 3x = %6d.\n", nCuts, nCuts55, nCuts5x, nCuts4x, nCuts3x ); + +// printf( "Total cuts = %6d. 6= %6d. 5= %6d. 4= %6d. 3= %6d. 2= %6d. 1= %6d.\n", +// nCuts, pCounts[6], pCounts[5], pCounts[4], pCounts[3], pCounts[2], pCounts[1] ); + return nCuts; +} + + +/**Function************************************************************* + + Synopsis [Prints the cuts in the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot ) +{ + Map_Cut_t * pTemp; + int Counter; + for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) + { + printf( "%2d : ", Counter + 1 ); + Map_CutPrint_( pMan, pTemp, pRoot ); + } +} + +/**Function************************************************************* + + Synopsis [Prints the cuts in the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot ) +{ + Map_Cut_t * pTemp; + int Counter; + for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) + { + printf( "%2d : ", Counter + 1 ); + Map_CutPrint_( pMan, pTemp, pRoot ); + } +} + +/**Function************************************************************* + + Synopsis [Prints the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot ) +{ + int i; + printf( "(%3d) {", pRoot->Num ); + for ( i = 0; i < pMan->nVarsMax; i++ ) + if ( pCut->ppLeaves[i] ) + printf( " %3d", pCut->ppLeaves[i]->Num ); + printf( " }\n" ); +} + + + + + + + + +/**Function************************************************************* + + Synopsis [Starts the hash table to canonicize cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan ) +{ + Map_CutTable_t * p; + // allocate the table + p = ALLOC( Map_CutTable_t, 1 ); + memset( p, 0, sizeof(Map_CutTable_t) ); + p->nBins = Cudd_Prime( 10 * MAP_CUTS_MAX_COMPUTE ); + p->pBins = ALLOC( Map_Cut_t *, p->nBins ); + memset( p->pBins, 0, sizeof(Map_Cut_t *) * p->nBins ); + p->pCuts = ALLOC( int, 2 * MAP_CUTS_MAX_COMPUTE ); + p->pArray = ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE ); + p->pCuts1 = ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE ); + p->pCuts2 = ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CutTableStop( Map_CutTable_t * p ) +{ + free( p->pCuts1 ); + free( p->pCuts2 ); + free( p->pArray ); + free( p->pBins ); + free( p->pCuts ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Computes the hash value of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes ) +{ + unsigned uRes; + int i; + uRes = 0; + for ( i = 0; i < nNodes; i++ ) + uRes += s_HashPrimes[i] * ppNodes[i]->Num; + return uRes; +} + +/**Function************************************************************* + + Synopsis [Looks up the table for the available cut.] + + Description [Returns -1 if the same cut is found. Returns the index + of the cell where the cut should be added, if it does not exist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ) +{ + Map_Cut_t * pCut; + unsigned Key; + int b, i; + + Key = Map_CutTableHash(ppNodes, nNodes) % p->nBins; + for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins ) + { + pCut = p->pBins[b]; + if ( pCut->nLeaves != nNodes ) + continue; + for ( i = 0; i < nNodes; i++ ) + if ( pCut->ppLeaves[i] != ppNodes[i] ) + break; + if ( i == nNodes ) + return -1; + } + return b; +} + + +/**Function************************************************************* + + Synopsis [Starts the hash table to canonicize cuts.] + + Description [Considers addition of the cut to the hash table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ) +{ + Map_Cut_t * pCut; + int Place, i; +// int clk; + // check the cut + Place = Map_CutTableLookup( p, ppNodes, nNodes ); + if ( Place == -1 ) + return NULL; + assert( nNodes > 0 ); + // create the new cut +//clk = clock(); + pCut = Map_CutAlloc( pMan ); +//pMan->time1 += clock() - clk; + pCut->nLeaves = nNodes; + for ( i = 0; i < nNodes; i++ ) + pCut->ppLeaves[i] = ppNodes[i]; + // add the cut to the table + assert( p->pBins[Place] == NULL ); + p->pBins[Place] = pCut; + // add the cut to the new list + p->pCuts[ p->nCuts++ ] = Place; + return pCut; +} + +/**Function************************************************************* + + Synopsis [Prepares the table to be used with other cuts.] + + Description [Restarts the table by cleaning the info about cuts stored + when the previous node was considered.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CutTableRestart( Map_CutTable_t * p ) +{ + int i; + for ( i = 0; i < p->nCuts; i++ ) + { + assert( p->pBins[ p->pCuts[i] ] ); + p->pBins[ p->pCuts[i] ] = NULL; + } + p->nCuts = 0; +} + + + +/**Function************************************************************* + + Synopsis [Compares the cuts by the number of leaves and then by delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_CutSortCutsCompare( Map_Cut_t ** pC1, Map_Cut_t ** pC2 ) +{ + if ( (*pC1)->nLeaves < (*pC2)->nLeaves ) + return -1; + if ( (*pC1)->nLeaves > (*pC2)->nLeaves ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Sorts the cuts by average arrival time.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Cut_t * Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList ) +{ + Map_Cut_t * pListNew; + int nCuts, i; +// int clk; + // move the cuts from the list into the array + nCuts = Map_CutList2Array( p->pCuts1, pList ); + assert( nCuts <= MAP_CUTS_MAX_COMPUTE ); + // sort the cuts +//clk = clock(); + qsort( (void *)p->pCuts1, nCuts, sizeof(Map_Cut_t *), + (int (*)(const void *, const void *)) Map_CutSortCutsCompare ); +//pMan->time2 += clock() - clk; + // move them back into the list + if ( nCuts > MAP_CUTS_MAX_USE - 1 ) + { + // free the remaining cuts + for ( i = MAP_CUTS_MAX_USE - 1; i < nCuts; i++ ) + Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] ); + // update the number of cuts + nCuts = MAP_CUTS_MAX_USE - 1; + } + pListNew = Map_CutArray2List( p->pCuts1, nCuts ); + return pListNew; +} + +/**Function************************************************************* + + Synopsis [Moves the nodes from the list into the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList ) +{ + int i; + for ( i = 0; pList; pList = pList->pNext, i++ ) + pArray[i] = pList; + return i; +} + +/**Function************************************************************* + + Synopsis [Moves the nodes from the array into the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Cut_t * Map_CutArray2List( Map_Cut_t ** pArray, int nCuts ) +{ + Map_Cut_t * pListNew, ** ppListNew; + int i; + pListNew = NULL; + ppListNew = &pListNew; + for ( i = 0; i < nCuts; i++ ) + { + // connect these lists + *ppListNew = pArray[i]; + ppListNew = &pArray[i]->pNext; + } +//printf( "\n" ); + + *ppListNew = NULL; + return pListNew; +} + + +/**Function************************************************************* + + Synopsis [Computes the truth table of the 5-input cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Map_Cut_t * pTemp0, Map_Cut_t * pTemp1, int fComp0, int fComp1 ) +{ + static unsigned ** pPerms53 = NULL; + static unsigned ** pPerms54 = NULL; + + unsigned uPhase, uTruth, uTruth0, uTruth1; + int i, k; + + if ( pPerms53 == NULL ) + { + pPerms53 = (unsigned **)Extra_TruthPerm53(); + pPerms54 = (unsigned **)Extra_TruthPerm54(); + } + + // find the mapping from the old nodes to the new + if ( pTemp0->nLeaves == pCut->nLeaves ) + uTruth0 = pTemp0->uTruth; + else + { + assert( pTemp0->nLeaves < pCut->nLeaves ); + uPhase = 0; + for ( i = 0; i < (int)pTemp0->nLeaves; i++ ) + { + for ( k = 0; k < pCut->nLeaves; k++ ) + if ( pTemp0->ppLeaves[i] == pCut->ppLeaves[k] ) + break; + uPhase |= (1 << k); + } + assert( uPhase < 32 ); + if ( pTemp0->nLeaves == 4 ) + { + if ( uPhase == 31-16 ) // 01111 + uTruth0 = pTemp0->uTruth; + else if ( uPhase == 31-8 ) // 10111 + uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][0]; + else if ( uPhase == 31-4 ) // 11011 + uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][1]; + else if ( uPhase == 31-2 ) // 11101 + uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][2]; + else if ( uPhase == 31-1 ) // 11110 + uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][3]; + else + assert( 0 ); + } + else + uTruth0 = pPerms53[pTemp0->uTruth & 0xFF][uPhase]; + } + uTruth0 = fComp0? ~uTruth0: uTruth0; + + // find the mapping from the old nodes to the new + if ( pTemp1->nLeaves == pCut->nLeaves ) + uTruth1 = pTemp1->uTruth; + else + { + assert( pTemp1->nLeaves < pCut->nLeaves ); + uPhase = 0; + for ( i = 0; i < (int)pTemp1->nLeaves; i++ ) + { + for ( k = 0; k < pCut->nLeaves; k++ ) + if ( pTemp1->ppLeaves[i] == pCut->ppLeaves[k] ) + break; + uPhase |= (1 << k); + } + assert( uPhase < 32 ); + if ( pTemp1->nLeaves == 4 ) + { + if ( uPhase == 31-16 ) // 01111 + uTruth1 = pTemp1->uTruth; + else if ( uPhase == 31-8 ) // 10111 + uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][0]; + else if ( uPhase == 31-4 ) // 11011 + uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][1]; + else if ( uPhase == 31-2 ) // 11101 + uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][2]; + else if ( uPhase == 31-1 ) // 11110 + uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][3]; + else + assert( 0 ); + } + else + uTruth1 = pPerms53[pTemp1->uTruth & 0xFF][uPhase]; + } + uTruth1 = fComp1? ~uTruth1: uTruth1; + uTruth = uTruth0 & uTruth1; + return uTruth; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/map/mapper/mapperCutUtils.c b/abc70930/src/map/mapper/mapperCutUtils.c new file mode 100644 index 00000000..4450cb04 --- /dev/null +++ b/abc70930/src/map/mapper/mapperCutUtils.c @@ -0,0 +1,273 @@ +/**CFile**************************************************************** + + FileName [mapperCutUtils.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperCutUtils.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Cut_t * Map_CutAlloc( Map_Man_t * p ) +{ + Map_Cut_t * pCut; + Map_Match_t * pMatch; + pCut = (Map_Cut_t *)Extra_MmFixedEntryFetch( p->mmCuts ); + memset( pCut, 0, sizeof(Map_Cut_t) ); + + pMatch = pCut->M; + pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned + pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned + pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned + pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned + + pMatch = pCut->M + 1; + pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned + pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned + pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned + pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned + return pCut; +} + +/**Function************************************************************* + + Synopsis [Deallocates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CutFree( Map_Man_t * p, Map_Cut_t * pCut ) +{ + if ( pCut ) + Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pCut ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CutPrint( Map_Man_t * p, Map_Node_t * pRoot, Map_Cut_t * pCut, int fPhase ) +{ + int i; + printf( "CUT: Delay = (%4.2f, %4.2f). Area = %4.2f. Nodes = %d -> {", + pCut->M[fPhase].tArrive.Rise, pCut->M[fPhase].tArrive.Fall, pCut->M[fPhase].AreaFlow, pRoot->Num ); + for ( i = 0; i < pCut->nLeaves; i++ ) + printf( " %d", pCut->ppLeaves[i]->Num ); + printf( " } \n" ); +} + + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_CutGetRootArea( Map_Cut_t * pCut, int fPhase ) +{ + assert( pCut->M[fPhase].pSuperBest ); + return pCut->M[fPhase].pSuperBest->Area; +} + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Map_CutGetLeafPhase( Map_Cut_t * pCut, int fPhase, int iLeaf ) +{ + assert( pCut->M[fPhase].pSuperBest ); + return (( pCut->M[fPhase].uPhaseBest & (1<pCutBest[fPhase]->M[fPhase].pSuperBest ); + return (( pNode->pCutBest[fPhase]->M[fPhase].uPhaseBest & (1<pNext ) + pPrev = pTemp; + // append all the end of the current set + assert( pPrev->pNext == NULL ); + pPrev->pNext = pSetAll; + return pSets; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CutListRecycle( Map_Man_t * p, Map_Cut_t * pSetList, Map_Cut_t * pSave ) +{ + Map_Cut_t * pNext, * pTemp; + for ( pTemp = pSetList, pNext = pTemp? pTemp->pNext : NULL; + pTemp; + pTemp = pNext, pNext = pNext? pNext->pNext : NULL ) + if ( pTemp != pSave ) + Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pTemp ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_CutListCount( Map_Cut_t * pSets ) +{ + Map_Cut_t * pTemp; + int i; + for ( i = 0, pTemp = pSets; pTemp; pTemp = pTemp->pNext, i++ ); + return i; +} + +#if 0 + +/**function************************************************************* + + synopsis [Removes the fanouts of the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +void Map_CutRemoveFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) +{ + Map_NodeVec_t * vFanouts; + int i, k; + for ( i = 0; i < pCut->nLeaves; i++ ) + { + vFanouts = pCut->ppLeaves[i]->vFanouts; + for ( k = 0; k < vFanouts->nSize; k++ ) + if ( vFanouts->pArray[k] == pNode ) + break; + assert( k != vFanouts->nSize ); + for ( k++; k < vFanouts->nSize; k++ ) + vFanouts->pArray[k-1] = vFanouts->pArray[k]; + vFanouts->nSize--; + } +} + +/**function************************************************************* + + synopsis [Removes the fanouts of the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +void Map_CutInsertFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) +{ + int i; + for ( i = 0; i < pCut->nLeaves; i++ ) + Map_NodeVecPush( pCut->ppLeaves[i]->vFanouts, pNode ); +} + +#endif + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperFanout.c b/abc70930/src/map/mapper/mapperFanout.c new file mode 100644 index 00000000..63cdbd2a --- /dev/null +++ b/abc70930/src/map/mapper/mapperFanout.c @@ -0,0 +1,141 @@ +/**CFile**************************************************************** + + FileName [mapperFanout.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperFanout.c,v 1.5 2005/01/23 06:59:43 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +#ifdef MAP_ALLOCATE_FANOUT + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Add the fanout to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeAddFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanout ) +{ + Map_Node_t * pPivot; + + // pFanins is a fanin of pFanout + assert( !Map_IsComplement(pFanin) ); + assert( !Map_IsComplement(pFanout) ); + assert( Map_Regular(pFanout->p1) == pFanin || Map_Regular(pFanout->p2) == pFanin ); + + pPivot = pFanin->pFanPivot; + if ( pPivot == NULL ) + { + pFanin->pFanPivot = pFanout; + return; + } + + if ( Map_Regular(pPivot->p1) == pFanin ) + { + if ( Map_Regular(pFanout->p1) == pFanin ) + { + pFanout->pFanFanin1 = pPivot->pFanFanin1; + pPivot->pFanFanin1 = pFanout; + } + else // if ( Map_Regular(pFanout->p2) == pFanin ) + { + pFanout->pFanFanin2 = pPivot->pFanFanin1; + pPivot->pFanFanin1 = pFanout; + } + } + else // if ( Map_Regular(pPivot->p2) == pFanin ) + { + assert( Map_Regular(pPivot->p2) == pFanin ); + if ( Map_Regular(pFanout->p1) == pFanin ) + { + pFanout->pFanFanin1 = pPivot->pFanFanin2; + pPivot->pFanFanin2 = pFanout; + } + else // if ( Map_Regular(pFanout->p2) == pFanin ) + { + pFanout->pFanFanin2 = pPivot->pFanFanin2; + pPivot->pFanFanin2 = pFanout; + } + } +} + +/**Function************************************************************* + + Synopsis [Add the fanout to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeRemoveFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanoutToRemove ) +{ + Map_Node_t * pFanout, * pFanout2, ** ppFanList; + // start the linked list of fanouts + ppFanList = &pFanin->pFanPivot; + // go through the fanouts + Map_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 ) + { + // skip the fanout-to-remove + if ( pFanout == pFanoutToRemove ) + continue; + // add useful fanouts to the list + *ppFanList = pFanout; + ppFanList = Map_NodeReadNextFanoutPlace( pFanin, pFanout ); + } + *ppFanList = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the number of fanouts of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_NodeGetFanoutNum( Map_Node_t * pNode ) +{ + Map_Node_t * pFanout; + int Counter = 0; + Map_NodeForEachFanout( pNode, pFanout ) + Counter++; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/abc70930/src/map/mapper/mapperGENERIC.c b/abc70930/src/map/mapper/mapperGENERIC.c new file mode 100644 index 00000000..823eb4f2 --- /dev/null +++ b/abc70930/src/map/mapper/mapperGENERIC.c @@ -0,0 +1,46 @@ +/**CFile**************************************************************** + + FileName [mapper__.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: mapper__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperInt.h b/abc70930/src/map/mapper/mapperInt.h new file mode 100644 index 00000000..37cca3d3 --- /dev/null +++ b/abc70930/src/map/mapper/mapperInt.h @@ -0,0 +1,477 @@ +/**CFile**************************************************************** + + FileName [mapperInt.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperInt.h,v 1.8 2004/09/30 21:18:10 satrajit Exp $] + +***********************************************************************/ + +#ifndef __MAPPER_INT_H__ +#define __MAPPER_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//#include "leaks.h" +#include +#include +#include +#include +#include "cuddInt.h" +#include "main.h" +#include "mio.h" +#include "mapper.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// uncomment to have fanouts represented in the mapping graph +//#define MAP_ALLOCATE_FANOUT 1 + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// the bit masks +#define MAP_MASK(n) ((~((unsigned)0)) >> (32-(n))) +#define MAP_FULL (~((unsigned)0)) +#define MAP_NO_VAR (-9999.0) + +// maximum/minimum operators +#define MAP_MIN(a,b) (((a) < (b))? (a) : (b)) +#define MAP_MAX(a,b) (((a) > (b))? (a) : (b)) + +// the small and large numbers (min/max float are 1.17e-38/3.40e+38) +#define MAP_FLOAT_LARGE ((float)(FLT_MAX/10)) +#define MAP_FLOAT_SMALL ((float)1.0e-03) + +// generating random unsigned (#define RAND_MAX 0x7fff) +#define MAP_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) + +// internal macros to work with cuts +#define Map_CutIsComplement(p) (((int)((unsigned long) (p) & 01))) +#define Map_CutRegular(p) ((Map_Cut_t *)((unsigned long)(p) & ~01)) +#define Map_CutNot(p) ((Map_Cut_t *)((unsigned long)(p) ^ 01)) +#define Map_CutNotCond(p,c) ((Map_Cut_t *)((unsigned long)(p) ^ (c))) + +// internal macros for referencing of nodes +#define Map_NodeReadRef(p) ((Map_Regular(p))->nRefs) +#define Map_NodeRef(p) ((Map_Regular(p))->nRefs++) + +// macros to get hold of the bits in the support info +#define Map_InfoSetVar(p,i) (p[(i)>>5] |= (1<<((i) & 31))) +#define Map_InfoRemVar(p,i) (p[(i)>>5] &= ~(1<<((i) & 31))) +#define Map_InfoFlipVar(p,i) (p[(i)>>5] ^= (1<<((i) & 31))) +#define Map_InfoReadVar(p,i) ((p[(i)>>5] & (1<<((i) & 31))) > 0) + +// returns the complemented attribute of the node +#define Map_NodeIsSimComplement(p) (Map_IsComplement(p)? !(Map_Regular(p)->fInv) : (p)->fInv) + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// the mapping manager +struct Map_ManStruct_t_ +{ + // the mapping graph + Map_Node_t ** pBins; // the table of nodes hashed by their children + int nBins; // the size of the table + Map_Node_t ** pInputs; // the array of inputs + int nInputs; // the number of inputs + Map_Node_t ** pOutputs; // the array of outputs + int nOutputs; // the number of outputs + int nNodes; // the total number of nodes + Map_Node_t * pConst1; // the constant 1 node + Map_NodeVec_t * vAnds; // the array of nodes in the DFS order + Map_NodeVec_t * vNodesAll; // the array of all nodes + Map_NodeVec_t * vNodesTemp; // the array of all nodes + Map_NodeVec_t * vMapping; // the array of internal nodes used in the mapping + + // info about the original circuit + char ** ppOutputNames; // the primary output names + Map_Time_t * pInputArrivals;// the PI arrival times + + // mapping parameters + int nVarsMax; // the max number of variables + int fAreaRecovery; // the flag to enable area recovery + int fVerbose; // the verbosiness flag + int fMappingMode; // set to 1 when doing area + float fRequiredGlo; // the global required times + float fEpsilon; // the epsilon used to compare floats + float AreaBase; // the area after delay-oriented mapping + float AreaFinal; // the area after delay-oriented mapping + int nIterations; // How many matching passes to do + bool fObeyFanoutLimits;// Should mapper try to obey fanout limits or not + float DelayTarget; // the required times set by the user + int nTravIds; // the traversal counter + bool fSwitching; // Should mapper try to obey fanout limits or not + + // the supergate library + Map_SuperLib_t * pSuperLib; // the current supergate library + unsigned uTruths[6][2]; // the elementary truth tables + unsigned uTruthsLarge[10][32]; // the elementary truth tables + int nCounts[32]; // the counter of minterms + int nCountsBest[32];// the counter of minterms + Map_NodeVec_t * vVisited; // the visited cuts during cut computation + + // the memory managers + Extra_MmFixed_t * mmNodes; // the memory manager for nodes + Extra_MmFixed_t * mmCuts; // the memory manager for cuts + + // precomputed N-canonical forms + unsigned short * uCanons; // N-canonical forms + char ** uPhases; // N-canonical phases + char * pCounters; // counters of phases + + // various statistical variables + int nChoiceNodes; // the number of choice nodes + int nChoices; // the number of all choices + int nCanons; // the number of times N-canonical form was computed + int nMatches; // the number of times supergate matching was performed + int nPhases; // the number of phases considered during matching + int nFanoutViolations; // the number of nodes in mapped circuit violating fanout + + // runtime statistics + int timeToMap; // time to transfer to the mapping structure + int timeCuts; // time to compute k-feasible cuts + int timeTruth; // time to compute the truth table for each cut + int timeMatch; // time to perform matching for each node + int timeArea; // time to recover area after delay oriented mapping + int timeSweep; // time to perform technology dependent sweep + int timeToNet; // time to transfer back to the network + int timeTotal; // the total mapping time + int time1; // time to transfer to the mapping structure + int time2; // time to transfer to the mapping structure + int time3; // time to transfer to the mapping structure +}; + +// the supergate library +struct Map_SuperLibStruct_t_ +{ + // general info + char * pName; // the name of the supergate library + Mio_Library_t * pGenlib; // the generic library + + // other info + int nVarsMax; // the max number of variables + int nSupersAll; // the total number of supergates + int nSupersReal; // the total number of supergates + int nLines; // the total number of lines in the supergate file + bool fVerbose; // the verbosity flag + + // hash tables + Map_Super_t ** ppSupers; // the array of supergates + Map_HashTable_t * tTableC; // the table mapping N-canonical forms into supergates + Map_HashTable_t * tTable; // the table mapping truth tables into supergates + + // data structures for N-canonical form computation + unsigned uTruths[6][2]; // the elementary truth tables + unsigned uMask[2]; // the mask for the truth table + + // the invertor + Mio_Gate_t * pGateInv; // the pointer to the intertor gate + Map_Time_t tDelayInv; // the delay of the inverter + float AreaInv; // the area of the inverter + float AreaBuf; // the area of the buffer + Map_Super_t * pSuperInv; // the supergate representing the inverter + + // the memory manager for the internal table + Extra_MmFixed_t * mmSupers; // the mamory manager for supergates + Extra_MmFixed_t * mmEntries; // the memory manager for the entries + Extra_MmFlex_t * mmForms; // the memory manager for formulas +}; + +// the mapping node +struct Map_NodeStruct_t_ +{ + // general information about the node + Map_Man_t * p; // the mapping manager + Map_Node_t * pNext; // the next node in the hash table + int Num; // the unique number of this node + int TravId; // the traversal ID (use to avoid cleaning marks) + int nRefs; // the number of references (fanouts) of the given node + unsigned fMark0 : 1; // the mark used for traversals + unsigned fMark1 : 1; // the mark used for traversals + unsigned fUsed : 1; // the mark to mark the node or its fanins + unsigned fInv : 1; // the complemented attribute for the equivalent nodes + unsigned fInvert: 1; // the flag to denote the use of interter + unsigned Level :16; // the level of the given node + unsigned NumTemp:10; // the level of the given node + int nRefAct[3]; // estimated fanout for current covering phase, neg and pos and sum + float nRefEst[3]; // actual fanout for previous covering phase, neg and pos and sum + float Switching; // the probability of switching + + // connectivity + Map_Node_t * p1; // the first child + Map_Node_t * p2; // the second child + Map_Node_t * pNextE; // the next functionally equivalent node + Map_Node_t * pRepr; // the representative of the functionally equivalent class + +#ifdef MAP_ALLOCATE_FANOUT + // representation of node's fanouts + Map_Node_t * pFanPivot; // the first fanout of this node + Map_Node_t * pFanFanin1; // the next fanout of p1 + Map_Node_t * pFanFanin2; // the next fanout of p2 +// Map_NodeVec_t * vFanouts; // the array of fanouts of the gate +#endif + + // the delay information + Map_Time_t tArrival[2]; // the best arrival time of the neg (0) and pos (1) phases + Map_Time_t tRequired[2]; // the required time of the neg (0) and pos (1) phases + + // misc information + Map_Cut_t * pCutBest[2]; // the best mapping for neg and pos phase + Map_Cut_t * pCuts; // mapping choices for the node (elementary comes first) + char * pData0; // temporary storage for the corresponding network node + char * pData1; // temporary storage for the corresponding network node +}; + +// the match of the cut +struct Map_MatchStruct_t_ +{ + // information used for matching + Map_Super_t * pSupers; + unsigned uPhase; + // information about the best selected match + unsigned uPhaseBest; // the best phase (the EXOR of match's phase and gate's phase) + Map_Super_t * pSuperBest; // the best supergate matched + // the parameters of the match + Map_Time_t tArrive; // the arrival time of this match + float AreaFlow; // the area flow or area of this match +}; + +// the cuts used for matching +struct Map_CutStruct_t_ +{ + Map_Cut_t * pNext; // the pointer to the next cut in the list + Map_Cut_t * pOne; // the father of this cut + Map_Cut_t * pTwo; // the mother of this cut + Map_Node_t * ppLeaves[6]; // the leaves of this cut + unsigned uTruth; // truth table for five-input cuts + char nLeaves; // the number of leaves + char nVolume; // the volume of this cut + char fMark; // the mark to denote visited cut + char Phase; // the mark to denote complemented cut + Map_Match_t M[2]; // the matches for positive/negative phase +}; + +// the supergate internally represented +struct Map_SuperStruct_t_ +{ + int Num; // the ID of the supergate + unsigned fSuper : 1; // the flag to distinquish a real super from a fake one + unsigned fExclude: 1; // the flag if set causes gate to be excluded from being used for mapping + unsigned nFanins : 3; // the number of inputs + unsigned nGates : 3; // the number of gates inside this supergate + unsigned nFanLimit: 4; // the max number of fanout count + unsigned nSupers : 16; // the number of supergates in the list + unsigned nPhases : 4; // the number of phases for matching with canonical form + unsigned char uPhases[4]; // the maximum of 4 phases for matching with canonical form + int nUsed; // the number of times the supergate is used + Map_Super_t * pFanins[6]; // the fanins of the gate + Mio_Gate_t * pRoot; // the root gate + unsigned uTruth[2]; // the truth table + Map_Time_t tDelaysR[6]; // the pin-to-pin delay constraints for the rise of the output + Map_Time_t tDelaysF[6]; // the pin-to-pin delay constraints for the rise of the output + Map_Time_t tDelayMax; // the maximum delay + float Area; // the area + char * pFormula; // the symbolic formula + Map_Super_t * pNext; // the pointer to the next super in the list +}; + +// the vector of nodes +struct Map_NodeVecStruct_t_ +{ + Map_Node_t ** pArray; // the array of nodes + int nSize; // the number of entries in the array + int nCap; // the number of allocated entries +}; + +// the hash table +struct Map_HashTableStruct_t_ +{ + Map_HashEntry_t ** pBins; // the table bins + int nBins; // the size of the table + int nEntries; // the total number of entries in the table + Extra_MmFixed_t * mmMan; // the memory manager for entries +}; + +// the entry in the hash table +struct Map_HashEntryStruct_t_ +{ + unsigned uTruth[2]; // the truth table for 6-var function + unsigned uPhase; // the phase to tranform it into the canonical form + Map_Super_t * pGates; // the linked list of matching supergates + Map_HashEntry_t * pNext; // the next entry in the hash table +}; + +// getting hold of the next fanout of the node +#define Map_NodeReadNextFanout( pNode, pFanout ) \ + ( ( pFanout == NULL )? NULL : \ + ((Map_Regular((pFanout)->p1) == (pNode))? \ + (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) ) + +// getting hold of the place where the next fanout will be attached +#define Map_NodeReadNextFanoutPlace( pNode, pFanout ) \ + ( (Map_Regular((pFanout)->p1) == (pNode))? \ + &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 ) + +// iterator through the fanouts of the node +#define Map_NodeForEachFanout( pNode, pFanout ) \ + for ( pFanout = (pNode)->pFanPivot; pFanout; \ + pFanout = Map_NodeReadNextFanout(pNode, pFanout) ) + +// safe iterator through the fanouts of the node +#define Map_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \ + for ( pFanout = (pNode)->pFanPivot, \ + pFanout2 = Map_NodeReadNextFanout(pNode, pFanout); \ + pFanout; \ + pFanout = pFanout2, \ + pFanout2 = Map_NodeReadNextFanout(pNode, pFanout) ) + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== mapperCanon.c =============================================================*/ +/*=== mapperCut.c ===============================================================*/ +extern void Map_MappingCuts( Map_Man_t * p ); +extern int Map_MappingCountAllCuts( Map_Man_t * p ); +/*=== mapperCutDcs.c ===============================================================*/ +extern void Map_ComputeDcs( Map_Man_t * p ); +extern unsigned Map_ComputeIsop_rec( Map_Man_t * p, unsigned uF, unsigned uFD, int iVar, int nVars, int fDir ); +/*=== mapperCutUtils.c ===============================================================*/ +extern Map_Cut_t * Map_CutAlloc( Map_Man_t * p ); +extern void Map_CutFree( Map_Man_t * p, Map_Cut_t * pCut ); +extern void Map_CutPrint( Map_Man_t * p, Map_Node_t * pRoot, Map_Cut_t * pCut, int fPhase ); +extern float Map_CutGetRootArea( Map_Cut_t * pCut, int fPhase ); +extern int Map_CutGetLeafPhase( Map_Cut_t * pCut, int fPhase, int iLeaf ); +extern int Map_NodeGetLeafPhase( Map_Node_t * pNode, int fPhase, int iLeaf ); +extern Map_Cut_t * Map_CutListAppend( Map_Cut_t * pSetAll, Map_Cut_t * pSets ); +extern void Map_CutListRecycle( Map_Man_t * p, Map_Cut_t * pSetList, Map_Cut_t * pSave ); +extern int Map_CutListCount( Map_Cut_t * pSets ); +extern void Map_CutRemoveFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); +extern void Map_CutInsertFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); +/*=== mapperFanout.c =============================================================*/ +extern void Map_NodeAddFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanout ); +extern void Map_NodeRemoveFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanoutToRemove ); +extern int Map_NodeGetFanoutNum( Map_Node_t * pNode ); +/*=== mapperLib.c ============================================================*/ +extern Map_SuperLib_t * Map_SuperLibCreate( char * pFileName, char * pExcludeFile, bool fAlgorithm, bool fVerbose ); +extern void Map_SuperLibFree( Map_SuperLib_t * p ); +/*=== mapperMatch.c ===============================================================*/ +extern int Map_MappingMatches( Map_Man_t * p ); +extern float Map_MappingCombinePhases( Map_Man_t * p ); +extern void Map_MatchClean( Map_Match_t * pMatch ); +extern int Map_MatchCompare( Map_Man_t * pMan, Map_Match_t * pM1, Map_Match_t * pM2, int fDoingArea ); +/*=== mapperPower.c =============================================================*/ +extern float Map_SwitchCutGetDerefed( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); +extern float Map_SwitchCutRef( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); +extern float Map_SwitchCutDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); +extern float Map_MappingGetSwitching( Map_Man_t * pMan, Map_NodeVec_t * vMapping ); +/*=== mapperRefs.c =============================================================*/ +extern int Map_NodeReadRefPhaseAct( Map_Node_t * pNode, int fPhase ); +extern float Map_NodeReadRefPhaseEst( Map_Node_t * pNode, int fPhase ); +extern void Map_MappingEstimateRefsInit( Map_Man_t * p ); +extern void Map_MappingEstimateRefs( Map_Man_t * p ); +extern float Map_CutGetAreaFlow( Map_Cut_t * pCut, int fPhase ); +extern float Map_CutGetAreaRefed( Map_Cut_t * pCut, int fPhase ); +extern float Map_CutGetAreaDerefed( Map_Cut_t * pCut, int fPhase ); +extern float Map_CutRef( Map_Cut_t * pCut, int fPhase ); +extern float Map_CutDeref( Map_Cut_t * pCut, int fPhase ); +extern void Map_MappingSetRefs( Map_Man_t * pMan ); +extern float Map_MappingGetArea( Map_Man_t * pMan, Map_NodeVec_t * vMapping ); +/*=== mapperShow.c =============================================================*/ +extern void Map_MappingShow( Map_Man_t * pMan, char * pFileName ); +/*=== mapperTree.c ===============================================================*/ +extern int Map_LibraryReadTree( Map_SuperLib_t * pLib, char * pFileName, char * pExcludeFile ); +extern void Map_LibraryPrintTree( Map_SuperLib_t * pLib ); +/*=== mapperSuper.c ===============================================================*/ +extern int Map_LibraryRead( Map_SuperLib_t * p, char * pFileName ); +extern void Map_LibraryPrintSupergate( Map_Super_t * pGate ); +/*=== mapperTable.c ============================================================*/ +extern Map_HashTable_t * Map_SuperTableCreate( Map_SuperLib_t * pLib ); +extern void Map_SuperTableFree( Map_HashTable_t * p ); +extern int Map_SuperTableInsertC( Map_HashTable_t * pLib, unsigned uTruthC[], Map_Super_t * pGate ); +extern int Map_SuperTableInsert( Map_HashTable_t * pLib, unsigned uTruth[], Map_Super_t * pGate, unsigned uPhase ); +extern Map_Super_t * Map_SuperTableLookup( Map_HashTable_t * p, unsigned uTruth[], unsigned * puPhase ); +extern void Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax ); +extern void Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax ); +/*=== mapperTime.c =============================================================*/ +extern float Map_TimeCutComputeArrival( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float tWorstCaseLimit ); +extern void Map_TimeCutComputeArrival_rec( Map_Cut_t * pCut, int fPhase ); +extern float Map_TimeComputeArrivalMax( Map_Man_t * p ); +extern void Map_TimeComputeRequiredGlobal( Map_Man_t * p ); +extern void Map_TimeComputeRequired( Map_Man_t * p, float fRequired ); +extern float Map_TimeNodeFanoutDelay( Map_Node_t * pNode, int fPhase ); +extern float Map_TimeCutFanoutDelay( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); +extern float Map_TimeMatchWithInverter( Map_Man_t * p, Map_Match_t * pMatch ); +/*=== mapperTruth.c ===============================================================*/ +extern void Map_MappingTruths( Map_Man_t * pMan ); +extern int Map_TruthsCutDontCare( Map_Man_t * pMan, Map_Cut_t * pCut, unsigned * uTruthDc ); +extern int Map_TruthCountOnes( unsigned * uTruth, int nLeaves ); +extern int Map_TruthDetectTwoFirst( unsigned * uTruth, int nLeaves ); +/*=== mapperUtils.c ===============================================================*/ +extern Map_NodeVec_t * Map_MappingDfs( Map_Man_t * pMan, int fCollectEquiv ); +extern Map_NodeVec_t * Map_MappingDfsNodes( Map_Man_t * pMan, Map_Node_t ** ppNodes, int nNodes, int fEquiv ); + +extern void Map_MappingDfsMarked1_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fFirst ); +extern void Map_MappingDfsMarked2_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, Map_NodeVec_t * vBoundary, int fFirst ); + +extern int Map_MappingCountLevels( Map_Man_t * pMan ); +extern void Map_MappingUnmark( Map_Man_t * pMan ); +extern void Map_MappingMark_rec( Map_Node_t * pNode ); +extern void Map_MappingUnmark_rec( Map_Node_t * pNode ); +extern void Map_MappingPrintOutputArrivals( Map_Man_t * p ); +extern void Map_MappingSetupMask( unsigned uMask[], int nVarsMax ); +extern int Map_MappingNodeIsViolator( Map_Node_t * pNode, Map_Cut_t * pCut, int fPosPol ); +extern float Map_MappingGetAreaFlow( Map_Man_t * p ); +extern void Map_MappingSortByLevel( Map_Man_t * pMan, Map_NodeVec_t * vNodes ); +extern int Map_MappingCountDoubles( Map_Man_t * pMan, Map_NodeVec_t * vNodes ); +extern void Map_MappingExpandTruth( unsigned uTruth[2], int nVars ); +extern float Map_MappingPrintSwitching( Map_Man_t * pMan ); +extern void Map_MappingSetPlacementInfo( Map_Man_t * p ); +extern float Map_MappingPrintWirelength( Map_Man_t * p ); +extern void Map_MappingWireReport( Map_Man_t * p ); +extern float Map_MappingComputeDelayWithFanouts( Map_Man_t * p ); +extern int Map_MappingGetMaxLevel( Map_Man_t * pMan ); +extern void Map_MappingSetChoiceLevels( Map_Man_t * pMan ); +extern void Map_MappingReportChoices( Map_Man_t * pMan ); +/*=== mapperVec.c =============================================================*/ +extern Map_NodeVec_t * Map_NodeVecAlloc( int nCap ); +extern void Map_NodeVecFree( Map_NodeVec_t * p ); +extern Map_Node_t ** Map_NodeVecReadArray( Map_NodeVec_t * p ); +extern int Map_NodeVecReadSize( Map_NodeVec_t * p ); +extern void Map_NodeVecGrow( Map_NodeVec_t * p, int nCapMin ); +extern void Map_NodeVecShrink( Map_NodeVec_t * p, int nSizeNew ); +extern void Map_NodeVecClear( Map_NodeVec_t * p ); +extern void Map_NodeVecPush( Map_NodeVec_t * p, Map_Node_t * Entry ); +extern int Map_NodeVecPushUnique( Map_NodeVec_t * p, Map_Node_t * Entry ); +extern Map_Node_t * Map_NodeVecPop( Map_NodeVec_t * p ); +extern void Map_NodeVecRemove( Map_NodeVec_t * p, Map_Node_t * Entry ); +extern void Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_Node_t * Entry ); +extern Map_Node_t * Map_NodeVecReadEntry( Map_NodeVec_t * p, int i ); +extern void Map_NodeVecSortByLevel( Map_NodeVec_t * p ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/map/mapper/mapperLib.c b/abc70930/src/map/mapper/mapperLib.c new file mode 100644 index 00000000..d916487e --- /dev/null +++ b/abc70930/src/map/mapper/mapperLib.c @@ -0,0 +1,231 @@ +/**CFile**************************************************************** + + FileName [mapperLib.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperLib.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads in the supergate library and prepares it for use.] + + Description [The supergates library comes in a .super file. This file + contains descriptions of supergates along with some relevant information. + This procedure reads the supergate file, canonicizes the supergates, + and constructs an additional lookup table, which can be used to map + truth tables of the cuts into the pair (phase, supergate). The phase + indicates how the current truth table should be phase assigned to + match the canonical form of the supergate. The resulting phase is the + bitwise EXOR of the phase needed to canonicize the supergate and the + phase needed to transform the truth table into its canonical form.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_SuperLib_t * Map_SuperLibCreate( char * pFileName, char * pExcludeFile, bool fAlgorithm, bool fVerbose ) +{ + Map_SuperLib_t * p; + int clk; + + // start the supergate library + p = ALLOC( Map_SuperLib_t, 1 ); + memset( p, 0, sizeof(Map_SuperLib_t) ); + p->pName = pFileName; + p->fVerbose = fVerbose; + p->mmSupers = Extra_MmFixedStart( sizeof(Map_Super_t) ); + p->mmEntries = Extra_MmFixedStart( sizeof(Map_HashEntry_t) ); + p->mmForms = Extra_MmFlexStart(); + Map_MappingSetupTruthTables( p->uTruths ); + + // start the hash table + p->tTableC = Map_SuperTableCreate( p ); + p->tTable = Map_SuperTableCreate( p ); + + // read the supergate library from file +clk = clock(); + if ( fAlgorithm ) + { + if ( !Map_LibraryReadTree( p, pFileName, pExcludeFile ) ) + { + Map_SuperLibFree( p ); + return NULL; + } + } + else + { + if ( pExcludeFile != 0 ) + { + printf ("Error: Exclude file support not present for old format. Stop.\n"); + return NULL; + } + if ( !Map_LibraryRead( p, pFileName ) ) + { + Map_SuperLibFree( p ); + return NULL; + } + } + assert( p->nVarsMax > 0 ); + + // report the stats +if ( fVerbose ) { + printf( "Loaded %d unique %d-input supergates from \"%s\". ", + p->nSupersReal, p->nVarsMax, pFileName ); + PRT( "Time", clock() - clk ); +} + + // assign the interver parameters + p->pGateInv = Mio_LibraryReadInv( p->pGenlib ); + p->tDelayInv.Rise = Mio_LibraryReadDelayInvRise( p->pGenlib ); + p->tDelayInv.Fall = Mio_LibraryReadDelayInvFall( p->pGenlib ); + p->tDelayInv.Worst = MAP_MAX( p->tDelayInv.Rise, p->tDelayInv.Fall ); + p->AreaInv = Mio_LibraryReadAreaInv( p->pGenlib ); + p->AreaBuf = Mio_LibraryReadAreaBuf( p->pGenlib ); + + // assign the interver supergate + p->pSuperInv = (Map_Super_t *)Extra_MmFixedEntryFetch( p->mmSupers ); + memset( p->pSuperInv, 0, sizeof(Map_Super_t) ); + p->pSuperInv->Num = -1; + p->pSuperInv->nGates = 1; + p->pSuperInv->nFanins = 1; + p->pSuperInv->nFanLimit = 10; + p->pSuperInv->pFanins[0] = p->ppSupers[0]; + p->pSuperInv->pRoot = p->pGateInv; + p->pSuperInv->Area = p->AreaInv; + p->pSuperInv->tDelayMax = p->tDelayInv; + p->pSuperInv->tDelaysR[0].Rise = MAP_NO_VAR; + p->pSuperInv->tDelaysR[0].Fall = p->tDelayInv.Rise; + p->pSuperInv->tDelaysF[0].Rise = p->tDelayInv.Fall; + p->pSuperInv->tDelaysF[0].Fall = MAP_NO_VAR; + return p; +} + + +/**Function************************************************************* + + Synopsis [Deallocates the supergate library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_SuperLibFree( Map_SuperLib_t * p ) +{ + if ( p == NULL ) return; + if ( p->pGenlib ) + { + assert( p->pGenlib == Abc_FrameReadLibGen() ); + Mio_LibraryDelete( p->pGenlib ); + Abc_FrameSetLibGen( NULL ); + } + if ( p->tTableC ) + Map_SuperTableFree( p->tTableC ); + if ( p->tTable ) + Map_SuperTableFree( p->tTable ); + Extra_MmFixedStop( p->mmSupers ); + Extra_MmFixedStop( p->mmEntries ); + Extra_MmFlexStop( p->mmForms ); + FREE( p->ppSupers ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Derives the library from the genlib library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib ) +{ + Abc_Frame_t * pAbc = Abc_FrameGetGlobalFrame(); + char * pNameGeneric; + char FileNameGenlib[100]; + char FileNameSuper[100]; + char CommandSuper[500]; + char CommandRead[500]; + FILE * pFile; + + if ( pLib == NULL ) + return 0; + + // write the current library into the file + sprintf( FileNameGenlib, "%s_temp", Mio_LibraryReadName(pLib) ); + pFile = fopen( FileNameGenlib, "w" ); + Mio_WriteLibrary( pFile, pLib, 0 ); + fclose( pFile ); + + // get the file name with the library + pNameGeneric = Extra_FileNameGeneric( Mio_LibraryReadName(pLib) ); + sprintf( FileNameSuper, "%s.super", pNameGeneric ); + free( pNameGeneric ); + + sprintf( CommandSuper, "super -l 1 -i 5 -d 10000000 -a 10000000 -t 100 %s", FileNameGenlib ); + if ( Cmd_CommandExecute( pAbc, CommandSuper ) ) + { + fprintf( stdout, "Cannot execute command \"%s\".\n", CommandSuper ); + return 0; + } +//#ifdef WIN32 +// _unlink( FileNameGenlib ); +//#else +// unlink( FileNameGenlib ); +//#endif + + sprintf( CommandRead, "read_super %s", FileNameSuper ); + if ( Cmd_CommandExecute( pAbc, CommandRead ) ) + { +#ifdef WIN32 + _unlink( FileNameSuper ); +#else + unlink( FileNameSuper ); +#endif + fprintf( stdout, "Cannot execute command \"%s\".\n", CommandRead ); + return 0; + } + +/* // don't remove the intermediate file +#ifdef WIN32 + _unlink( FileNameSuper ); +#else + unlink( FileNameSuper ); +#endif +*/ + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperMatch.c b/abc70930/src/map/mapper/mapperMatch.c new file mode 100644 index 00000000..bfa72601 --- /dev/null +++ b/abc70930/src/map/mapper/mapperMatch.c @@ -0,0 +1,596 @@ +/**CFile**************************************************************** + + FileName [mapperMatch.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperMatch.c,v 1.7 2004/09/30 21:18:10 satrajit Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +/* + A potential improvement: + When an internal node is not used in the mapping, its required times + are set to be +infinity. So when we recover area, we try to find the + best match for area and completely disregard the delay for the nodes + that are not currently used in the mapping because any match whose + arrival times are less than the required times (+infinity) can be used. + It may be possible to develop a better approach to recover area for + the nodes that are not currently used in the mapping... +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Map_MatchNodePhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase ); +static int Map_MatchNodeCut( Map_Man_t * p, Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float fWorstLimit ); + +static void Map_MappingSetPiArrivalTimes( Map_Man_t * p ); +static void Map_NodeTryDroppingOnePhase( Map_Man_t * p, Map_Node_t * pNode ); +static void Map_NodeTransferArrivalTimes( Map_Man_t * p, Map_Node_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the best matches of the nodes.] + + Description [Uses parameter p->fMappingMode to decide how to assign + the matches for both polarities of the node. While the matches are + being assigned, one of them may turn out to be better than the other + (in terms of delay, for example). In this case, the worse match can + be permanently dropped, and the corresponding pointer set to NULL.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MappingMatches( Map_Man_t * p ) +{ + ProgressBar * pProgress; + Map_Node_t * pNode; + int i; + + assert( p->fMappingMode >= 0 && p->fMappingMode <= 4 ); + + // use the externally given PI arrival times + if ( p->fMappingMode == 0 ) + Map_MappingSetPiArrivalTimes( p ); + + // estimate the fanouts + if ( p->fMappingMode == 0 ) + Map_MappingEstimateRefsInit( p ); + else if ( p->fMappingMode == 1 ) + Map_MappingEstimateRefs( p ); + + // the PI cuts are matched in the cut computation package + // in the loop below we match the internal nodes + pProgress = Extra_ProgressBarStart( stdout, p->vAnds->nSize ); + for ( i = 0; i < p->vAnds->nSize; i++ ) + { + // skip primary inputs and secondary nodes if mapping with choices + pNode = p->vAnds->pArray[i]; + if ( !Map_NodeIsAnd( pNode ) || pNode->pRepr ) + continue; + + // make sure that at least one non-trival cut is present + if ( pNode->pCuts->pNext == NULL ) + { + printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); + return 0; + } + + // match negative phase + if ( !Map_MatchNodePhase( p, pNode, 0 ) ) + return 0; + // match positive phase + if ( !Map_MatchNodePhase( p, pNode, 1 ) ) + return 0; + + // make sure that at least one phase is mapped + if ( pNode->pCutBest[0] == NULL && pNode->pCutBest[1] == NULL ) + { + printf( "\nError: Could not match both phases of AIG node %d.\n", pNode->Num ); + printf( "Please make sure that the supergate library has equivalents of AND2 or NAND2.\n" ); + printf( "If such supergates exist in the library, report a bug.\n" ); + return 0; + } + + // if both phases are assigned, check if one of them can be dropped + Map_NodeTryDroppingOnePhase( p, pNode ); + // set the arrival times of the node using the best cuts + Map_NodeTransferArrivalTimes( p, pNode ); + + // update the progress bar + Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); + } + Extra_ProgressBarStop( pProgress ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Find the matching of one polarity of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MatchNodePhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase ) +{ + Map_Match_t MatchBest, * pMatch; + Map_Cut_t * pCut, * pCutBest; + float Area1, Area2, fWorstLimit; + + // skip the cuts that have been unassigned during area recovery + pCutBest = pNode->pCutBest[fPhase]; + if ( p->fMappingMode != 0 && pCutBest == NULL ) + return 1; + + // recompute the arrival times of the current best match + // because the arrival times of the fanins may have changed + // as a result of remapping fanins in the topological order + if ( p->fMappingMode != 0 ) + { + Map_TimeCutComputeArrival( pNode, pCutBest, fPhase, MAP_FLOAT_LARGE ); + // make sure that the required times are met + assert( pCutBest->M[fPhase].tArrive.Rise < pNode->tRequired[fPhase].Rise + p->fEpsilon ); + assert( pCutBest->M[fPhase].tArrive.Fall < pNode->tRequired[fPhase].Fall + p->fEpsilon ); + } + + // recompute the exact area of the current best match + // because the exact area of the fanins may have changed + // as a result of remapping fanins in the topological order + if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) + { + pMatch = pCutBest->M + fPhase; + if ( pNode->nRefAct[fPhase] > 0 || + (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0) ) + pMatch->AreaFlow = Area1 = Map_CutDeref( pCutBest, fPhase ); + else + pMatch->AreaFlow = Area1 = Map_CutGetAreaDerefed( pCutBest, fPhase ); + } + else if ( p->fMappingMode == 4 ) + { + pMatch = pCutBest->M + fPhase; + if ( pNode->nRefAct[fPhase] > 0 || + (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0) ) + pMatch->AreaFlow = Area1 = Map_SwitchCutDeref( pNode, pCutBest, fPhase ); + else + pMatch->AreaFlow = Area1 = Map_SwitchCutGetDerefed( pNode, pCutBest, fPhase ); + } + + // save the old mapping + if ( pCutBest ) + MatchBest = pCutBest->M[fPhase]; + else + Map_MatchClean( &MatchBest ); + + // select the new best cut + fWorstLimit = pNode->tRequired[fPhase].Worst; + for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) + { + pMatch = pCut->M + fPhase; + if ( pMatch->pSupers == NULL ) + continue; + + // find the matches for the cut + Map_MatchNodeCut( p, pNode, pCut, fPhase, fWorstLimit ); + if ( pMatch->pSuperBest == NULL || pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon ) + continue; + + // if the cut can be matched compare the matchings + if ( Map_MatchCompare( p, &MatchBest, pMatch, p->fMappingMode ) ) + { + pCutBest = pCut; + MatchBest = *pMatch; + // if we are mapping for delay, the worst-case limit should be tightened + if ( p->fMappingMode == 0 ) + fWorstLimit = MatchBest.tArrive.Worst; + } + } + + if ( pCutBest == NULL ) + return 1; + + // set the new mapping + pNode->pCutBest[fPhase] = pCutBest; + pCutBest->M[fPhase] = MatchBest; + + // reference the new cut if it used + if ( p->fMappingMode >= 2 && + (pNode->nRefAct[fPhase] > 0 || + (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0)) ) + { + if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) + Area2 = Map_CutRef( pNode->pCutBest[fPhase], fPhase ); + else if ( p->fMappingMode == 4 ) + Area2 = Map_SwitchCutRef( pNode, pNode->pCutBest[fPhase], fPhase ); + else + assert( 0 ); + assert( Area2 < Area1 + p->fEpsilon ); + } + + // make sure that the requited times are met + assert( MatchBest.tArrive.Rise < pNode->tRequired[fPhase].Rise + p->fEpsilon ); + assert( MatchBest.tArrive.Fall < pNode->tRequired[fPhase].Fall + p->fEpsilon ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Find the best matching of the cut.] + + Description [The parameters: the node (pNode), the cut (pCut), the phase to be matched + (fPhase), and the upper bound on the arrival times of the cut (fWorstLimit). This + procedure goes through the matching supergates up to the phase assignment, and selects the + best supergate, which will be used to map the cut. As a result of calling this procedure + the matching information is written into pMatch.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MatchNodeCut( Map_Man_t * p, Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float fWorstLimit ) +{ + Map_Match_t MatchBest, * pMatch = pCut->M + fPhase; + Map_Super_t * pSuper; + int i, Counter; + + // save the current match of the cut + MatchBest = *pMatch; + // go through the supergates + for ( pSuper = pMatch->pSupers, Counter = 0; pSuper; pSuper = pSuper->pNext, Counter++ ) + { + p->nMatches++; + // this is an attempt to reduce the runtime of matching and area + // at the cost of rare and very minor increase in delay + // (the supergates are sorted by increasing area) + if ( Counter == 30 ) + break; + + // go through different phases of the given match and supergate + pMatch->pSuperBest = pSuper; + for ( i = 0; i < (int)pSuper->nPhases; i++ ) + { + p->nPhases++; + // find the overall phase of this match + pMatch->uPhaseBest = pMatch->uPhase ^ pSuper->uPhases[i]; + if ( p->fMappingMode == 0 ) + { + // get the arrival time + Map_TimeCutComputeArrival( pNode, pCut, fPhase, fWorstLimit ); + // skip the cut if the arrival times exceed the required times + if ( pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon ) + continue; + // get the area (area flow) + pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase ); + } + else + { + // get the area (area flow) + if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) + pMatch->AreaFlow = Map_CutGetAreaDerefed( pCut, fPhase ); + else if ( p->fMappingMode == 4 ) + pMatch->AreaFlow = Map_SwitchCutGetDerefed( pNode, pCut, fPhase ); + else + pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase ); + // skip if the cut is too large + if ( pMatch->AreaFlow > MatchBest.AreaFlow + p->fEpsilon ) + continue; + // get the arrival time + Map_TimeCutComputeArrival( pNode, pCut, fPhase, fWorstLimit ); + // skip the cut if the arrival times exceed the required times + if ( pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon ) + continue; + } + + // if the cut is non-trivial, compare it + if ( Map_MatchCompare( p, &MatchBest, pMatch, p->fMappingMode ) ) + { + MatchBest = *pMatch; + // if we are mapping for delay, the worst-case limit should be reduced + if ( p->fMappingMode == 0 ) + fWorstLimit = MatchBest.tArrive.Worst; + } + } + } + // set the best match + *pMatch = MatchBest; + + // recompute the arrival time and area (area flow) of this cut + if ( pMatch->pSuperBest ) + { + Map_TimeCutComputeArrival( pNode, pCut, fPhase, MAP_FLOAT_LARGE ); + if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) + pMatch->AreaFlow = Map_CutGetAreaDerefed( pCut, fPhase ); + else if ( p->fMappingMode == 4 ) + pMatch->AreaFlow = Map_SwitchCutGetDerefed( pNode, pCut, fPhase ); + else + pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Cleans the match.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MatchClean( Map_Match_t * pMatch ) +{ + memset( pMatch, 0, sizeof(Map_Match_t) ); + pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned + pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned + pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned + pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned +} + +/**Function************************************************************* + + Synopsis [Compares two matches.] + + Description [Returns 1 if the second match is better. Otherwise returns 0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MatchCompare( Map_Man_t * pMan, Map_Match_t * pM1, Map_Match_t * pM2, int fDoingArea ) +{ + if ( !fDoingArea ) + { + // compare the arrival times + if ( pM1->tArrive.Worst < pM2->tArrive.Worst - pMan->fEpsilon ) + return 0; + if ( pM1->tArrive.Worst > pM2->tArrive.Worst + pMan->fEpsilon ) + return 1; + // compare the areas or area flows + if ( pM1->AreaFlow < pM2->AreaFlow - pMan->fEpsilon ) + return 0; + if ( pM1->AreaFlow > pM2->AreaFlow + pMan->fEpsilon ) + return 1; + // compare the fanout limits + if ( pM1->pSuperBest->nFanLimit > pM2->pSuperBest->nFanLimit ) + return 0; + if ( pM1->pSuperBest->nFanLimit < pM2->pSuperBest->nFanLimit ) + return 1; + // compare the number of leaves + if ( pM1->pSuperBest->nFanins < pM2->pSuperBest->nFanins ) + return 0; + if ( pM1->pSuperBest->nFanins > pM2->pSuperBest->nFanins ) + return 1; + // otherwise prefer the old cut + return 0; + } + else + { + // compare the areas or area flows + if ( pM1->AreaFlow < pM2->AreaFlow - pMan->fEpsilon ) + return 0; + if ( pM1->AreaFlow > pM2->AreaFlow + pMan->fEpsilon ) + return 1; + // compare the arrival times + if ( pM1->tArrive.Worst < pM2->tArrive.Worst - pMan->fEpsilon ) + return 0; + if ( pM1->tArrive.Worst > pM2->tArrive.Worst + pMan->fEpsilon ) + return 1; + // compare the fanout limits + if ( pM1->pSuperBest->nFanLimit > pM2->pSuperBest->nFanLimit ) + return 0; + if ( pM1->pSuperBest->nFanLimit < pM2->pSuperBest->nFanLimit ) + return 1; + // compare the number of leaves + if ( pM1->pSuperBest->nFanins < pM2->pSuperBest->nFanins ) + return 0; + if ( pM1->pSuperBest->nFanins > pM2->pSuperBest->nFanins ) + return 1; + // otherwise prefer the old cut + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Sets the PI arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingSetPiArrivalTimes( Map_Man_t * p ) +{ + Map_Node_t * pNode; + int i; + for ( i = 0; i < p->nInputs; i++ ) + { + pNode = p->pInputs[i]; + // set the arrival time of the positive phase + pNode->tArrival[1] = p->pInputArrivals[i]; + // set the arrival time of the negative phase + pNode->tArrival[0].Rise = pNode->tArrival[1].Fall + p->pSuperLib->tDelayInv.Rise; + pNode->tArrival[0].Fall = pNode->tArrival[1].Rise + p->pSuperLib->tDelayInv.Fall; + pNode->tArrival[0].Worst = MAP_MAX(pNode->tArrival[0].Rise, pNode->tArrival[0].Fall); + } +} + + +/**Function************************************************************* + + Synopsis [Attempts dropping one phase of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeTryDroppingOnePhase( Map_Man_t * p, Map_Node_t * pNode ) +{ + Map_Match_t * pMatchBest0, * pMatchBest1; + float tWorst0Using1, tWorst1Using0; + int fUsePhase1, fUsePhase0; + + // nothing to do if one of the phases is already dropped + if ( pNode->pCutBest[0] == NULL || pNode->pCutBest[1] == NULL ) + return; + + // do not drop while recovering area flow + if ( p->fMappingMode == 1 )//|| p->fMappingMode == 2 ) + return; + + // get the pointers to the matches of the best cuts + pMatchBest0 = pNode->pCutBest[0]->M + 0; + pMatchBest1 = pNode->pCutBest[1]->M + 1; + + // get the worst arrival times of each phase + // implemented using the other phase with inverter added + tWorst0Using1 = Map_TimeMatchWithInverter( p, pMatchBest1 ); + tWorst1Using0 = Map_TimeMatchWithInverter( p, pMatchBest0 ); + + // consider the case of mapping for delay + if ( p->fMappingMode == 0 ) + { + // if the arrival time of a phase is larger than the arrival time + // of the opposite phase plus the inverter, drop this phase + if ( pMatchBest0->tArrive.Worst > tWorst0Using1 + p->fEpsilon ) + pNode->pCutBest[0] = NULL; + else if ( pMatchBest1->tArrive.Worst > tWorst1Using0 + p->fEpsilon ) + pNode->pCutBest[1] = NULL; + return; + } + + // do not perform replacement if one of the phases is unused + if ( pNode->nRefAct[0] == 0 || pNode->nRefAct[1] == 0 ) + return; + + // check if replacement of each phase is possible using required times + fUsePhase0 = fUsePhase1 = 0; + if ( p->fMappingMode == 2 ) + { + fUsePhase0 = (pNode->tRequired[1].Worst > tWorst1Using0 + 3*p->pSuperLib->tDelayInv.Worst + p->fEpsilon); + fUsePhase1 = (pNode->tRequired[0].Worst > tWorst0Using1 + 3*p->pSuperLib->tDelayInv.Worst + p->fEpsilon); + } + else if ( p->fMappingMode == 3 || p->fMappingMode == 4 ) + { + fUsePhase0 = (pNode->tRequired[1].Worst > tWorst1Using0 + p->fEpsilon); + fUsePhase1 = (pNode->tRequired[0].Worst > tWorst0Using1 + p->fEpsilon); + } + if ( !fUsePhase0 && !fUsePhase1 ) + return; + + // if replacement is possible both ways, use the one that works better + if ( fUsePhase0 && fUsePhase1 ) + { + if ( pMatchBest0->AreaFlow < pMatchBest1->AreaFlow ) + fUsePhase1 = 0; + else + fUsePhase0 = 0; + } + // only one phase should be used + assert( fUsePhase0 ^ fUsePhase1 ); + + // set the corresponding cut to NULL + if ( fUsePhase0 ) + { + // deref phase 1 cut if necessary + if ( p->fMappingMode >= 2 && pNode->nRefAct[1] > 0 ) + Map_CutDeref( pNode->pCutBest[1], 1 ); + // get rid of the cut + pNode->pCutBest[1] = NULL; + // ref phase 0 cut if necessary + if ( p->fMappingMode >= 2 && pNode->nRefAct[0] == 0 ) + Map_CutRef( pNode->pCutBest[0], 0 ); + } + else + { + // deref phase 0 cut if necessary + if ( p->fMappingMode >= 2 && pNode->nRefAct[0] > 0 ) + Map_CutDeref( pNode->pCutBest[0], 0 ); + // get rid of the cut + pNode->pCutBest[0] = NULL; + // ref phase 1 cut if necessary + if ( p->fMappingMode >= 2 && pNode->nRefAct[1] == 0 ) + Map_CutRef( pNode->pCutBest[1], 1 ); + } +} + + +/**Function************************************************************* + + Synopsis [Transfers the arrival times from the best cuts to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeTransferArrivalTimes( Map_Man_t * p, Map_Node_t * pNode ) +{ + // if both phases are available, set their arrival times + if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) + { + pNode->tArrival[0] = pNode->pCutBest[0]->M[0].tArrive; + pNode->tArrival[1] = pNode->pCutBest[1]->M[1].tArrive; + } + // if only one phase is available, compute the arrival time of other phase + else if ( pNode->pCutBest[0] ) + { + pNode->tArrival[0] = pNode->pCutBest[0]->M[0].tArrive; + pNode->tArrival[1].Rise = pNode->tArrival[0].Fall + p->pSuperLib->tDelayInv.Rise; + pNode->tArrival[1].Fall = pNode->tArrival[0].Rise + p->pSuperLib->tDelayInv.Fall; + pNode->tArrival[1].Worst = MAP_MAX(pNode->tArrival[1].Rise, pNode->tArrival[1].Fall); + } + else if ( pNode->pCutBest[1] ) + { + pNode->tArrival[1] = pNode->pCutBest[1]->M[1].tArrive; + pNode->tArrival[0].Rise = pNode->tArrival[1].Fall + p->pSuperLib->tDelayInv.Rise; + pNode->tArrival[0].Fall = pNode->tArrival[1].Rise + p->pSuperLib->tDelayInv.Fall; + pNode->tArrival[0].Worst = MAP_MAX(pNode->tArrival[0].Rise, pNode->tArrival[0].Fall); + } + else + { + assert( 0 ); + } + + assert( pNode->tArrival[0].Rise < pNode->tRequired[0].Rise + p->fEpsilon ); + assert( pNode->tArrival[0].Fall < pNode->tRequired[0].Fall + p->fEpsilon ); + + assert( pNode->tArrival[1].Rise < pNode->tRequired[1].Rise + p->fEpsilon ); + assert( pNode->tArrival[1].Fall < pNode->tRequired[1].Fall + p->fEpsilon ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/map/mapper/mapperRefs.c b/abc70930/src/map/mapper/mapperRefs.c new file mode 100644 index 00000000..a50b134a --- /dev/null +++ b/abc70930/src/map/mapper/mapperRefs.c @@ -0,0 +1,557 @@ +/**CFile**************************************************************** + + FileName [mapperRefs.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperRefs.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Map_NodeIncRefPhaseAct( Map_Node_t * pNode, int fPhase ); +static int Map_NodeDecRefPhaseAct( Map_Node_t * pNode, int fPhase ); +static float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference ); +static void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_Node_t ** ppStore ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the actual reference counter of a phase.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_NodeReadRefPhaseAct( Map_Node_t * pNode, int fPhase ) +{ + assert( !Map_IsComplement(pNode) ); + if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned + return pNode->nRefAct[fPhase]; + assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned + return pNode->nRefAct[2]; +} + +/**Function************************************************************* + + Synopsis [Reads the estimated reference counter of a phase.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Map_NodeReadRefPhaseEst( Map_Node_t * pNode, int fPhase ) +{ + assert( !Map_IsComplement(pNode) ); + if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned + return pNode->nRefEst[fPhase]; + assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned +// return pNode->nRefEst[0] + pNode->nRefEst[1]; + return pNode->nRefEst[2]; +} + + +/**Function************************************************************* + + Synopsis [Increments the actual reference counter of a phase.] + + Description [Returns the old reference counter.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_NodeIncRefPhaseAct( Map_Node_t * pNode, int fPhase ) +{ + assert( !Map_IsComplement(pNode) ); + if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned + return pNode->nRefAct[fPhase]++; + assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned + return pNode->nRefAct[2]++; +} + +/**Function************************************************************* + + Synopsis [Decrements the actual reference counter of a phase.] + + Description [Returns the new reference counter.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_NodeDecRefPhaseAct( Map_Node_t * pNode, int fPhase ) +{ + assert( !Map_IsComplement(pNode) ); + if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned + return --pNode->nRefAct[fPhase]; + assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned + return --pNode->nRefAct[2]; +} + + +/**Function************************************************************* + + Synopsis [Sets the estimated reference counter for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingEstimateRefsInit( Map_Man_t * p ) +{ + Map_Node_t * pNode; + int i; + for ( i = 0; i < p->vAnds->nSize; i++ ) + { + pNode = p->vAnds->pArray[i]; +// pNode->nRefEst[0] = pNode->nRefEst[1] = ((float)pNode->nRefs)*(float)2.0; + pNode->nRefEst[0] = pNode->nRefEst[1] = pNode->nRefEst[2] = ((float)pNode->nRefs); + } +} + +/**Function************************************************************* + + Synopsis [Sets the estimated reference counter.] + + Description [When this procedure is called for the first time, + the reference counter is estimated from the AIG. Otherwise, it is + a linear combination of reference counters in the last two iterations.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingEstimateRefs( Map_Man_t * p ) +{ + Map_Node_t * pNode; + int i; + for ( i = 0; i < p->vAnds->nSize; i++ ) + { + pNode = p->vAnds->pArray[i]; +// pNode->nRefEst[0] = (float)((2.0 * pNode->nRefEst[0] + 1.0 * pNode->nRefAct[0]) / 3.0); +// pNode->nRefEst[1] = (float)((2.0 * pNode->nRefEst[1] + 1.0 * pNode->nRefAct[1]) / 3.0); +// pNode->nRefEst[2] = (float)((2.0 * pNode->nRefEst[2] + 1.0 * pNode->nRefAct[2]) / 3.0); + pNode->nRefEst[0] = (float)((3.0 * pNode->nRefEst[0] + 1.0 * pNode->nRefAct[0]) / 4.0); + pNode->nRefEst[1] = (float)((3.0 * pNode->nRefEst[1] + 1.0 * pNode->nRefAct[1]) / 4.0); + pNode->nRefEst[2] = (float)((3.0 * pNode->nRefEst[2] + 1.0 * pNode->nRefAct[2]) / 4.0); + } +} + + + + + +/**function************************************************************* + + synopsis [Computes the area flow of the cut.] + + description [Computes the area flow of the cut if it is implemented using + the best supergate with the best phase.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_CutGetAreaFlow( Map_Cut_t * pCut, int fPhase ) +{ + Map_Match_t * pM = pCut->M + fPhase; + Map_Super_t * pSuper = pM->pSuperBest; + unsigned uPhaseTot = pM->uPhaseBest; + Map_Cut_t * pCutFanin; + float aFlowRes, aFlowFanin, nRefs; + int i, fPinPhasePos; + + // start the resulting area flow + aFlowRes = pSuper->Area; + // iterate through the leaves + for ( i = 0; i < pCut->nLeaves; i++ ) + { + // get the phase of this fanin + fPinPhasePos = ((uPhaseTot & (1 << i)) == 0); + // get the cut implementing this phase of the fanin + pCutFanin = pCut->ppLeaves[i]->pCutBest[fPinPhasePos]; + // if the cut is not available, we have to use the opposite phase + if ( pCutFanin == NULL ) + { + fPinPhasePos = !fPinPhasePos; + pCutFanin = pCut->ppLeaves[i]->pCutBest[fPinPhasePos]; + } + aFlowFanin = pCutFanin->M[fPinPhasePos].AreaFlow; // ignores the area of the interter + // get the fanout count of the cut in the given phase + nRefs = Map_NodeReadRefPhaseEst( pCut->ppLeaves[i], fPinPhasePos ); + // if the node does no fanout, assume fanout count equal to 1 + if ( nRefs == (float)0.0 ) + nRefs = (float)1.0; + // add the area flow due to the fanin + aFlowRes += aFlowFanin / nRefs; + } + pM->AreaFlow = aFlowRes; + return aFlowRes; +} + + + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [Assumes that the cut is referenced.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_CutGetAreaRefed( Map_Cut_t * pCut, int fPhase ) +{ + float aResult, aResult2; + aResult2 = Map_CutRefDeref( pCut, fPhase, 0 ); // dereference + aResult = Map_CutRefDeref( pCut, fPhase, 1 ); // reference +// assert( aResult == aResult2 ); + return aResult; +} + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_CutGetAreaDerefed( Map_Cut_t * pCut, int fPhase ) +{ + float aResult, aResult2; + aResult2 = Map_CutRefDeref( pCut, fPhase, 1 ); // reference + aResult = Map_CutRefDeref( pCut, fPhase, 0 ); // dereference +// assert( aResult == aResult2 ); + return aResult; +} + +/**function************************************************************* + + synopsis [References the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_CutRef( Map_Cut_t * pCut, int fPhase ) +{ + return Map_CutRefDeref( pCut, fPhase, 1 ); // reference +} + +/**function************************************************************* + + synopsis [Dereferences the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_CutDeref( Map_Cut_t * pCut, int fPhase ) +{ + return Map_CutRefDeref( pCut, fPhase, 0 ); // dereference +} + +/**function************************************************************* + + synopsis [References or dereferences the cut.] + + description [This reference part is similar to Cudd_NodeReclaim(). + The dereference part is similar to Cudd_RecursiveDeref().] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference ) +{ + Map_Node_t * pNodeChild; + Map_Cut_t * pCutChild; + float aArea; + int i, fPhaseChild; +// int nRefs; + + // consider the elementary variable + if ( pCut->nLeaves == 1 ) + return 0; + // start the area of this cut + aArea = Map_CutGetRootArea( pCut, fPhase ); + // go through the children + for ( i = 0; i < pCut->nLeaves; i++ ) + { + pNodeChild = pCut->ppLeaves[i]; + fPhaseChild = Map_CutGetLeafPhase( pCut, fPhase, i ); + // get the reference counter of the child +/* + // this code does not take inverters into account + // the quality of area recovery seems to always be a little worse + if ( fReference ) + nRefs = Map_NodeIncRefPhaseAct( pNodeChild, fPhaseChild ); + else + nRefs = Map_NodeDecRefPhaseAct( pNodeChild, fPhaseChild ); + assert( nRefs >= 0 ); + // skip if the child was already reference before + if ( nRefs > 0 ) + continue; +*/ + + if ( fReference ) + { + if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present + { + // if this phase of the node is referenced, there is no recursive call + pNodeChild->nRefAct[2]++; + if ( pNodeChild->nRefAct[fPhaseChild]++ > 0 ) + continue; + } + else // only one phase is present + { + // inverter should be added if the phase + // (a) has no reference and (b) is implemented using other phase + if ( pNodeChild->nRefAct[fPhaseChild]++ == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) + aArea += pNodeChild->p->pSuperLib->AreaInv; + // if the node is referenced, there is no recursive call + if ( pNodeChild->nRefAct[2]++ > 0 ) + continue; + } + } + else + { + if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present + { + // if this phase of the node is referenced, there is no recursive call + --pNodeChild->nRefAct[2]; + if ( --pNodeChild->nRefAct[fPhaseChild] > 0 ) + continue; + } + else // only one phase is present + { + // inverter should be added if the phase + // (a) has no reference and (b) is implemented using other phase + if ( --pNodeChild->nRefAct[fPhaseChild] == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) + aArea += pNodeChild->p->pSuperLib->AreaInv; + // if the node is referenced, there is no recursive call + if ( --pNodeChild->nRefAct[2] > 0 ) + continue; + } + assert( pNodeChild->nRefAct[fPhaseChild] >= 0 ); + } + + // get the child cut + pCutChild = pNodeChild->pCutBest[fPhaseChild]; + // if the child does not have this phase mapped, take the opposite phase + if ( pCutChild == NULL ) + { + fPhaseChild = !fPhaseChild; + pCutChild = pNodeChild->pCutBest[fPhaseChild]; + } + // reference and compute area recursively + aArea += Map_CutRefDeref( pCutChild, fPhaseChild, fReference ); + } + return aArea; +} + + + + +/**Function************************************************************* + + Synopsis [Computes actual reference counters.] + + Description [Collects the nodes used in the mapping in array pMan->vMapping. + Nodes are collected in reverse topological order to facilitate the + computation of required times.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingSetRefs( Map_Man_t * pMan ) +{ + Map_Node_t * pNode, ** ppStore; + int i, fPhase, LevelMax; + + // clean all references + for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) + { + pNode = pMan->vNodesAll->pArray[i]; + pNode->nRefAct[0] = 0; + pNode->nRefAct[1] = 0; + pNode->nRefAct[2] = 0; + } + + // find the largest level of a node + LevelMax = 0; + for ( i = 0; i < pMan->nOutputs; i++ ) + if ( LevelMax < (int)Map_Regular(pMan->pOutputs[i])->Level ) + LevelMax = Map_Regular(pMan->pOutputs[i])->Level; + + // allocate place to store the nodes + ppStore = ALLOC( Map_Node_t *, LevelMax + 1 ); + memset( ppStore, 0, sizeof(Map_Node_t *) * (LevelMax + 1) ); + + // visit nodes reachable from POs in the DFS order through the best cuts + for ( i = 0; i < pMan->nOutputs; i++ ) + { + pNode = pMan->pOutputs[i]; + fPhase = !Map_IsComplement(pNode); + if ( !Map_NodeIsConst(pNode) ) + Map_MappingSetRefs_rec( pMan, pNode, ppStore ); + } + + // reconnect the nodes in reverse topological order + pMan->vMapping->nSize = 0; + for ( i = LevelMax; i >= 0; i-- ) + for ( pNode = ppStore[i]; pNode; pNode = (Map_Node_t *)pNode->pData0 ) + Map_NodeVecPush( pMan->vMapping, pNode ); + free( ppStore ); +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_Node_t ** ppStore ) +{ + Map_Cut_t * pCut; + Map_Node_t * pNodeR; + unsigned uPhase; + int i, fPhase, fInvPin; + + // get the regular node and its phase + pNodeR = Map_Regular(pNode); + fPhase = !Map_IsComplement(pNode); + + // add the node to the list of all visited nodes + if ( pNodeR->nRefAct[2]++ == 0 ) +// Map_NodeVecPush( pMan->vMapping, pNodeR ); + pNodeR->pData0 = (char *)ppStore[pNodeR->Level], ppStore[pNodeR->Level] = pNodeR; + + // quit if the node was already visited in this phase + if ( pNodeR->nRefAct[fPhase]++ ) + return; + + // quit if this is a PI node + if ( Map_NodeIsVar(pNodeR) ) + return; + + // get the cut implementing this or opposite polarity + pCut = pNodeR->pCutBest[fPhase]; + if ( pCut == NULL ) + { + fPhase = !fPhase; + pCut = pNodeR->pCutBest[fPhase]; + } + + // visit the transitive fanin + uPhase = pCut->M[fPhase].uPhaseBest; + for ( i = 0; i < pCut->nLeaves; i++ ) + { + fInvPin = ((uPhase & (1 << i)) > 0); + Map_MappingSetRefs_rec( pMan, Map_NotCond(pCut->ppLeaves[i], fInvPin), ppStore ); + } +} + + +/**Function************************************************************* + + Synopsis [Computes the array of mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Map_MappingGetArea( Map_Man_t * pMan, Map_NodeVec_t * vMapping ) +{ + Map_Node_t * pNode; + float Area; + int i; + Area = 0.0; + for ( i = 0; i < vMapping->nSize; i++ ) + { + pNode = vMapping->pArray[i]; + // at least one phase has the best cut assigned + assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); + // at least one phase is used in the mapping + assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); + // compute the array due to the supergate + if ( Map_NodeIsAnd(pNode) ) + { + // count area of the negative phase + if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) + Area += pNode->pCutBest[0]->M[0].pSuperBest->Area; + // count area of the positive phase + if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) + Area += pNode->pCutBest[1]->M[1].pSuperBest->Area; + } + // count area of the interver if we need to implement one phase with another phase + if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) || + (pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) ) + Area += pMan->pSuperLib->AreaInv; + } + // add buffers for each CO driven by a CI + for ( i = 0; i < pMan->nOutputs; i++ ) + if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) ) + Area += pMan->pSuperLib->AreaBuf; + return Area; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperSuper.c b/abc70930/src/map/mapper/mapperSuper.c new file mode 100644 index 00000000..ce6a780f --- /dev/null +++ b/abc70930/src/map/mapper/mapperSuper.c @@ -0,0 +1,449 @@ +/**CFile**************************************************************** + + FileName [mapperSuper.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperSuper.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Map_LibraryReadFile( Map_SuperLib_t * pLib, FILE * pFile ); +static Map_Super_t * Map_LibraryReadGate( Map_SuperLib_t * pLib, char * pBuffer, int nVars ); +static int Map_LibraryTruthVerify( Map_SuperLib_t * pLib, Map_Super_t * pGate ); +static void Map_LibraryComputeTruth( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthRes[] ); +static void Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthsIn[][2], unsigned uTruthRes[] ); +static void Map_LibraryPrintClasses( Map_SuperLib_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the supergate library from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_LibraryRead( Map_SuperLib_t * pLib, char * pFileName ) +{ + FILE * pFile; + int Status; + // read the beginning of the file + assert( pLib->pGenlib == NULL ); + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Cannot open input file \"%s\".\n", pFileName ); + return 0; + } + Status = Map_LibraryReadFile( pLib, pFile ); + fclose( pFile ); +// Map_LibraryPrintClasses( pLib ); + return Status; +} + + +/**Function************************************************************* + + Synopsis [Reads the library file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_LibraryReadFile( Map_SuperLib_t * pLib, FILE * pFile ) +{ + ProgressBar * pProgress; + char pBuffer[2000]; + FILE * pFileGen; + Map_Super_t * pGate; + char * pTemp, * pLibName; + int nCounter, nGatesTotal; + unsigned uCanon[2]; + + // skip empty and comment lines + while ( fgets( pBuffer, 5000, pFile ) != NULL ) + { + // skip leading spaces + for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); + // skip comment lines and empty lines + if ( *pTemp != 0 && *pTemp != '#' ) + break; + } + + // get the genlib file name + pLibName = strtok( pTemp, " \t\r\n" ); + if ( strcmp( pLibName, "GATE" ) == 0 ) + { + printf( "The input file \"%s\" looks like a GENLIB file and not a supergate library file.\n", pLib->pName ); + return 0; + } + pFileGen = fopen( pLibName, "r" ); + if ( pFileGen == NULL ) + { + printf( "Cannot open the GENLIB file \"%s\".\n", pLibName ); + return 0; + } + fclose( pFileGen ); + + // read the genlib library + pLib->pGenlib = Mio_LibraryRead( Abc_FrameGetGlobalFrame(), pLibName, 0, 0 ); + if ( pLib->pGenlib == NULL ) + { + printf( "Cannot read GENLIB file \"%s\".\n", pLibName ); + return 0; + } + + // read the number of variables + fscanf( pFile, "%d\n", &pLib->nVarsMax ); + if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 ) + { + printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax ); + return 0; + } + + // read the number of gates + fscanf( pFile, "%d\n", &nGatesTotal ); + if ( nGatesTotal < 1 || nGatesTotal > 10000000 ) + { + printf( "Suspicious number of gates (%d).\n", nGatesTotal ); + return 0; + } + + // read the lines + nCounter = 0; + pProgress = Extra_ProgressBarStart( stdout, nGatesTotal ); + while ( fgets( pBuffer, 5000, pFile ) != NULL ) + { + for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); + if ( pTemp[0] == '\0' ) + continue; + // get the gate + pGate = Map_LibraryReadGate( pLib, pTemp, pLib->nVarsMax ); + assert( pGate->Num == nCounter + 1 ); + // count the number of parantheses in the formula - this is the number of gates + for ( pTemp = pGate->pFormula; *pTemp; pTemp++ ) + pGate->nGates += (*pTemp == '('); + // verify the truth table + assert( Map_LibraryTruthVerify(pLib, pGate) ); + + // find the N-canonical form of this supergate + pGate->nPhases = Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, pLib->nVarsMax, pGate->uTruth, pGate->uPhases, uCanon ); + // add the supergate into the table by its N-canonical table + Map_SuperTableInsertC( pLib->tTableC, uCanon, pGate ); + // update the progress bar + Extra_ProgressBarUpdate( pProgress, ++nCounter, NULL ); + } + Extra_ProgressBarStop( pProgress ); + pLib->nSupersAll = nCounter; + if ( nCounter != nGatesTotal ) + printf( "The number of gates read (%d) is different what the file says (%d).\n", nGatesTotal, nCounter ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Super_t * Map_LibraryReadGate( Map_SuperLib_t * pLib, char * pBuffer, int nVars ) +{ + Map_Super_t * pGate; + char * pTemp; + int i; + + // start and clean the gate + pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); + memset( pGate, 0, sizeof(Map_Super_t) ); + + // read the number + pTemp = strtok( pBuffer, " " ); + pGate->Num = atoi(pTemp); + + // read the signature + pTemp = strtok( NULL, " " ); + if ( pLib->nVarsMax < 6 ) + { + pGate->uTruth[0] = Extra_ReadBinary(pTemp); + pGate->uTruth[1] = 0; + } + else + { + pGate->uTruth[0] = Extra_ReadBinary(pTemp+32); + pTemp[32] = 0; + pGate->uTruth[1] = Extra_ReadBinary(pTemp); + } + + // read the max delay + pTemp = strtok( NULL, " " ); + pGate->tDelayMax.Rise = (float)atof(pTemp); + pGate->tDelayMax.Fall = pGate->tDelayMax.Rise; + + // read the pin-to-pin delay + for ( i = 0; i < nVars; i++ ) + { + pTemp = strtok( NULL, " " ); + pGate->tDelaysR[i].Rise = (float)atof(pTemp); + pGate->tDelaysF[i].Fall = pGate->tDelaysR[i].Rise; + } + + // read the area + pTemp = strtok( NULL, " " ); + pGate->Area = (float)atof(pTemp); + + // the rest is the gate name + pTemp = strtok( NULL, " \r\n" ); + if ( strlen(pTemp) == 0 ) + printf( "A gate name is empty.\n" ); + + // save the gate name + pGate->pFormula = Extra_MmFlexEntryFetch( pLib->mmForms, strlen(pTemp) + 1 ); + strcpy( pGate->pFormula, pTemp ); + + // the rest is the gate name + pTemp = strtok( NULL, " \n\0" ); + if ( pTemp != NULL ) + printf( "The following trailing symbols found \"%s\".\n", pTemp ); + return pGate; +} + +/**Function************************************************************* + + Synopsis [Performs one step of parsing the formula into parts.] + + Description [This function will eventually be replaced when the + tree-supergate library representation will become standard.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Map_LibraryReadFormulaStep( char * pFormula, char * pStrings[], int * pnStrings ) +{ + char * pName, * pPar1, * pPar2, * pCur; + int nStrings, CountPars; + + // skip leading spaces + for ( pName = pFormula; *pName && *pName == ' '; pName++ ); + assert( *pName ); + // find the first opening paranthesis + for ( pPar1 = pName; *pPar1 && *pPar1 != '('; pPar1++ ); + if ( *pPar1 == 0 ) + { + *pnStrings = 0; + return pName; + } + // overwrite it with space + assert( *pPar1 == '(' ); + *pPar1 = 0; + // find the corresponding closing paranthesis + for ( CountPars = 1, pPar2 = pPar1 + 1; *pPar2 && CountPars; pPar2++ ) + if ( *pPar2 == '(' ) + CountPars++; + else if ( *pPar2 == ')' ) + CountPars--; + pPar2--; + assert( CountPars == 0 ); + // overwrite it with space + assert( *pPar2 == ')' ); + *pPar2 = 0; + // save the intervals between the commas + nStrings = 0; + pCur = pPar1 + 1; + while ( 1 ) + { + // save the current string + pStrings[ nStrings++ ] = pCur; + // find the beginning of the next string + for ( CountPars = 0; *pCur && (CountPars || *pCur != ','); pCur++ ) + if ( *pCur == '(' ) + CountPars++; + else if ( *pCur == ')' ) + CountPars--; + if ( *pCur == 0 ) + break; + assert( *pCur == ',' ); + *pCur = 0; + pCur++; + } + // save the results and return + *pnStrings = nStrings; + return pName; +} + + +/**Function************************************************************* + + Synopsis [Verifies the truth table of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_LibraryTruthVerify( Map_SuperLib_t * pLib, Map_Super_t * pGate ) +{ + unsigned uTruthRes[2]; + Map_LibraryComputeTruth( pLib, pGate->pFormula, uTruthRes ); + if ( uTruthRes[0] != pGate->uTruth[0] || uTruthRes[1] != pGate->uTruth[1] ) + return 0; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Derives the functionality of the supergate.] + + Description [This procedure is useful for verification the supergate + library. The truth table derived by this procedure should be the same + as the one contained in the original supergate file.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_LibraryComputeTruth( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthRes[] ) +{ + char Buffer[1000]; + strcpy( Buffer, pFormula ); + Map_LibraryComputeTruth_rec( pLib, Buffer, pLib->uTruths, uTruthRes ); +} + +/**Function************************************************************* + + Synopsis [Derives the functionality of the supergate.] + + Description [This procedure is useful for verification the supergate + library. The truth table derived by this procedure should be the same + as the one contained in the original supergate file.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthsIn[][2], unsigned uTruthRes[] ) +{ + Mio_Gate_t * pMioGate; + char * pGateName, * pStrings[6]; + unsigned uTruthsFanins[6][2]; + int nStrings, i; + + // perform one step parsing of the formula + // detect the root gate name, the next-step strings, and their number + pGateName = Map_LibraryReadFormulaStep( pFormula, pStrings, &nStrings ); + if ( nStrings == 0 ) // elementary variable + { + assert( pGateName[0] - 'a' < pLib->nVarsMax ); + uTruthRes[0] = uTruthsIn[pGateName[0] - 'a'][0]; + uTruthRes[1] = uTruthsIn[pGateName[0] - 'a'][1]; + return; + } + // derive the functionality of the fanins + for ( i = 0; i < nStrings; i++ ) + Map_LibraryComputeTruth_rec( pLib, pStrings[i], uTruthsIn, uTruthsFanins[i] ); + // get the root supergate + pMioGate = Mio_LibraryReadGateByName( pLib->pGenlib, pGateName ); + if ( pMioGate == NULL ) + printf( "A supergate contains gate \"%s\" that is not in \"%s\".\n", pGateName, Mio_LibraryReadName(pLib->pGenlib) ); + // derive the functionality of the output of the supergate + Mio_DeriveTruthTable( pMioGate, uTruthsFanins, nStrings, pLib->nVarsMax, uTruthRes ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_LibraryPrintSupergate( Map_Super_t * pGate ) +{ + printf( "%5d : ", pGate->nUsed ); + printf( "%5d ", pGate->Num ); + printf( "A = %5.2f ", pGate->Area ); + printf( "D = %5.2f ", pGate->tDelayMax ); + printf( "%s", pGate->pFormula ); + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Prints N-classes of supergates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_LibraryPrintClasses( Map_SuperLib_t * p ) +{ +/* + st_generator * gen; + Map_Super_t * pSuper, * pSuper2; + unsigned Key, uTruth; + int Counter = 0; + // copy all the supergates into one array + st_foreach_item( p->tSuplib, gen, (char **)&Key, (char **)&pSuper ) + { + for ( pSuper2 = pSuper; pSuper2; pSuper2 = pSuper2->pNext ) + { + uTruth = pSuper2->Phase; + Extra_PrintBinary( stdout, &uTruth, 5 ); + printf( " %5d ", pSuper2->Num ); + printf( "%s", pSuper2->pFormula ); + printf( "\n" ); + } + printf( "\n" ); + if ( ++ Counter == 100 ) + break; + } +*/ +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperSwitch.c b/abc70930/src/map/mapper/mapperSwitch.c new file mode 100644 index 00000000..9dd6e42b --- /dev/null +++ b/abc70930/src/map/mapper/mapperSwitch.c @@ -0,0 +1,223 @@ +/**CFile**************************************************************** + + FileName [mapperSwitch.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: mapperSwitch.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_SwitchCutGetDerefed( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) +{ + float aResult, aResult2; +// assert( pNode->Switching > 0 ); + aResult2 = Map_SwitchCutRefDeref( pNode, pCut, fPhase, 1 ); // reference + aResult = Map_SwitchCutRefDeref( pNode, pCut, fPhase, 0 ); // dereference +// assert( aResult == aResult2 ); + return aResult; +} + +/**function************************************************************* + + synopsis [References the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_SwitchCutRef( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) +{ + return Map_SwitchCutRefDeref( pNode, pCut, fPhase, 1 ); // reference +} + +/**function************************************************************* + + synopsis [References the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_SwitchCutDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) +{ + return Map_SwitchCutRefDeref( pNode, pCut, fPhase, 0 ); // dereference +} + +/**function************************************************************* + + synopsis [References or dereferences the cut.] + + description [This reference part is similar to Cudd_NodeReclaim(). + The dereference part is similar to Cudd_RecursiveDeref().] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference ) +{ + Map_Node_t * pNodeChild; + Map_Cut_t * pCutChild; + float aSwitchActivity; + int i, fPhaseChild; + + // start switching activity for the node + aSwitchActivity = pNode->Switching; + // consider the elementary variable + if ( pCut->nLeaves == 1 ) + return aSwitchActivity; + + // go through the children + assert( pCut->M[fPhase].pSuperBest ); + for ( i = 0; i < pCut->nLeaves; i++ ) + { + pNodeChild = pCut->ppLeaves[i]; + fPhaseChild = Map_CutGetLeafPhase( pCut, fPhase, i ); + // get the reference counter of the child + + if ( fReference ) + { + if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present + { + // if this phase of the node is referenced, there is no recursive call + pNodeChild->nRefAct[2]++; + if ( pNodeChild->nRefAct[fPhaseChild]++ > 0 ) + continue; + } + else // only one phase is present + { + // inverter should be added if the phase + // (a) has no reference and (b) is implemented using other phase + if ( pNodeChild->nRefAct[fPhaseChild]++ == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) + aSwitchActivity += pNodeChild->Switching; // inverter switches the same as the node + // if the node is referenced, there is no recursive call + if ( pNodeChild->nRefAct[2]++ > 0 ) + continue; + } + } + else + { + if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present + { + // if this phase of the node is referenced, there is no recursive call + --pNodeChild->nRefAct[2]; + if ( --pNodeChild->nRefAct[fPhaseChild] > 0 ) + continue; + } + else // only one phase is present + { + // inverter should be added if the phase + // (a) has no reference and (b) is implemented using other phase + if ( --pNodeChild->nRefAct[fPhaseChild] == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) + aSwitchActivity += pNodeChild->Switching; // inverter switches the same as the node + // if the node is referenced, there is no recursive call + if ( --pNodeChild->nRefAct[2] > 0 ) + continue; + } + assert( pNodeChild->nRefAct[fPhaseChild] >= 0 ); + } + + // get the child cut + pCutChild = pNodeChild->pCutBest[fPhaseChild]; + // if the child does not have this phase mapped, take the opposite phase + if ( pCutChild == NULL ) + { + fPhaseChild = !fPhaseChild; + pCutChild = pNodeChild->pCutBest[fPhaseChild]; + } + // reference and compute area recursively + aSwitchActivity += Map_SwitchCutRefDeref( pNodeChild, pCutChild, fPhaseChild, fReference ); + } + return aSwitchActivity; +} + +/**Function************************************************************* + + Synopsis [Computes the array of mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Map_MappingGetSwitching( Map_Man_t * pMan, Map_NodeVec_t * vMapping ) +{ + Map_Node_t * pNode; + float Switch; + int i; + Switch = 0.0; + for ( i = 0; i < vMapping->nSize; i++ ) + { + pNode = vMapping->pArray[i]; + // at least one phase has the best cut assigned + assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); + // at least one phase is used in the mapping + assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); + // compute the array due to the supergate + if ( Map_NodeIsAnd(pNode) ) + { + // count switching of the negative phase + if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) + Switch += pNode->Switching; + // count switching of the positive phase + if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) + Switch += pNode->Switching; + } + // count switching of the interver if we need to implement one phase with another phase + if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) || + (pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) ) + Switch += pNode->Switching; // inverter switches the same as the node + } + // add buffers for each CO driven by a CI + for ( i = 0; i < pMan->nOutputs; i++ ) + if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) ) + Switch += pMan->pOutputs[i]->Switching; + return Switch; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperTable.c b/abc70930/src/map/mapper/mapperTable.c new file mode 100644 index 00000000..d0cb7a01 --- /dev/null +++ b/abc70930/src/map/mapper/mapperTable.c @@ -0,0 +1,402 @@ +/**CFile**************************************************************** + + FileName [mapperTable.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperTable.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the table function for the tables +#define MAP_TABLE_HASH(u1,u2,nSize) (((u1) + 2003 * (u2)) % nSize) + +static void Map_SuperTableResize( Map_HashTable_t * pLib ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the hash table for supergates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_HashTable_t * Map_SuperTableCreate( Map_SuperLib_t * pLib ) +{ + Map_HashTable_t * p; + // allocate the table + p = ALLOC( Map_HashTable_t, 1 ); + memset( p, 0, sizeof(Map_HashTable_t) ); + p->mmMan = pLib->mmEntries; + // allocate and clean the bins + p->nBins = Cudd_Prime(20000); + p->pBins = ALLOC( Map_HashEntry_t *, p->nBins ); + memset( p->pBins, 0, sizeof(Map_HashEntry_t *) * p->nBins ); + return p; +} + + +/**Function************************************************************* + + Synopsis [Deallocates the supergate hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_SuperTableFree( Map_HashTable_t * p ) +{ + FREE( p->pBins ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Inserts a new entry into the hash table.] + + Description [This function inserts the new gate (pGate), which will be + accessible through its canonical form (uTruthC).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_SuperTableInsertC( Map_HashTable_t * p, unsigned uTruthC[], Map_Super_t * pGate ) +{ + Map_HashEntry_t * pEnt; + unsigned Key; + // resize the table + if ( p->nEntries >= 2 * p->nBins ) + Map_SuperTableResize( p ); + // check if another supergate with the same canonical form exists + Key = MAP_TABLE_HASH( uTruthC[0], uTruthC[1], p->nBins ); + for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext ) + if ( pEnt->uTruth[0] == uTruthC[0] && pEnt->uTruth[1] == uTruthC[1] ) + break; + // create a new entry if it does not exist + if ( pEnt == NULL ) + { + // add the new entry to the table + pEnt = (Map_HashEntry_t *)Extra_MmFixedEntryFetch( p->mmMan ); + memset( pEnt, 0, sizeof(Map_HashEntry_t) ); + pEnt->uTruth[0] = uTruthC[0]; + pEnt->uTruth[1] = uTruthC[1]; + // add the hash table entry to the corresponding linked list in the table + pEnt->pNext = p->pBins[Key]; + p->pBins[Key] = pEnt; + p->nEntries++; + } + // add the supergate to the entry + pGate->pNext = pEnt->pGates; + pEnt->pGates = pGate; + return 0; +} + + + +/**Function************************************************************* + + Synopsis [Inserts a new entry into the library.] + + Description [This function inserts the new gate (pGate), which will be + accessible through its unfolded function (uTruth).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_SuperTableInsert( Map_HashTable_t * p, unsigned uTruth[], Map_Super_t * pGate, unsigned uPhase ) +{ + Map_HashEntry_t * pEnt; + unsigned Key; + // resize the table + if ( p->nEntries >= 2 * p->nBins ) + Map_SuperTableResize( p ); + // check if this entry already exists + Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->nBins ); + for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext ) + if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] ) + return 1; + // add the new hash table entry to the table + pEnt = (Map_HashEntry_t *)Extra_MmFixedEntryFetch( p->mmMan ); + memset( pEnt, 0, sizeof(Map_HashEntry_t) ); + pEnt->uTruth[0] = uTruth[0]; + pEnt->uTruth[1] = uTruth[1]; + pEnt->pGates = pGate; + pEnt->uPhase = uPhase; + // add the hash table to the corresponding linked list in the table + pEnt->pNext = p->pBins[Key]; + p->pBins[Key] = pEnt; + p->nEntries++; +/* +printf( "Adding gate: %10u ", Key ); +Map_LibraryPrintSupergate( pGate ); +Extra_PrintBinary( stdout, uTruth, 32 ); +printf( "\n" ); +*/ + return 0; +} + +/**Function************************************************************* + + Synopsis [Looks up an entry in the library.] + + Description [This function looks up the function, given by its truth table, + and return two things: (1) the linked list of supergates, which can implement + the functions of this N-class; (2) the phase, which should be applied to the + given function, in order to derive the canonical form of this N-class.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Super_t * Map_SuperTableLookupC( Map_SuperLib_t * p, unsigned uTruth[] ) +{ + Map_HashEntry_t * pEnt; + unsigned Key; + Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->tTableC->nBins ); + for ( pEnt = p->tTableC->pBins[Key]; pEnt; pEnt = pEnt->pNext ) + if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] ) + return pEnt->pGates; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Looks up an entry in the library.] + + Description [This function looks up the function, given by its truth table, + and return two things: (1) the linked list of supergates, which can implement + the functions of this N-class; (2) the phase, which should be applied to the + given function, in order to derive the canonical form of this N-class.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Super_t * Map_SuperTableLookup( Map_HashTable_t * p, unsigned uTruth[], unsigned * puPhase ) +{ + Map_HashEntry_t * pEnt; + unsigned Key; + Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->nBins ); + for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext ) + if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] ) + { + *puPhase = pEnt->uPhase; + return pEnt->pGates; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_SuperTableResize( Map_HashTable_t * p ) +{ + Map_HashEntry_t ** pBinsNew; + Map_HashEntry_t * pEnt, * pEnt2; + int nBinsNew, Counter, i, clk = clock(); + unsigned Key; + // get the new table size + nBinsNew = Cudd_Prime(2 * p->nBins); + // allocate a new array + pBinsNew = ALLOC( Map_HashEntry_t *, nBinsNew ); + memset( pBinsNew, 0, sizeof(Map_HashEntry_t *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < p->nBins; i++ ) + for ( pEnt = p->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; + pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL ) + { + Key = MAP_TABLE_HASH( pEnt->uTruth[0], pEnt->uTruth[1], nBinsNew ); + pEnt->pNext = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == p->nEntries ); + // replace the table and the parameters + free( p->pBins ); + p->pBins = pBinsNew; + p->nBins = nBinsNew; +} + +/**Function************************************************************* + + Synopsis [Compares the supergates by the number of times they are used.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_SuperTableCompareSupergates( Map_Super_t ** ppS1, Map_Super_t ** ppS2 ) +{ + if ( (*ppS1)->nUsed > (*ppS2)->nUsed ) + return -1; + if ( (*ppS1)->nUsed < (*ppS2)->nUsed ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Compares the supergates by the number of times they are used.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_SuperTableCompareGatesInList( Map_Super_t ** ppS1, Map_Super_t ** ppS2 ) +{ +// if ( (*ppS1)->tDelayMax.Rise > (*ppS2)->tDelayMax.Rise ) + if ( (*ppS1)->Area > (*ppS2)->Area ) + return -1; +// if ( (*ppS1)->tDelayMax.Rise < (*ppS2)->tDelayMax.Rise ) + if ( (*ppS1)->Area < (*ppS2)->Area ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Sorts supergates by usefulness and prints out most useful.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax ) +{ + Map_HashEntry_t * pEnt; + Map_Super_t ** ppSupers; + Map_Super_t * pSuper; + int nSupers, i; + + // copy all the supergates into one array + ppSupers = ALLOC( Map_Super_t *, nSupersMax ); + nSupers = 0; + for ( i = 0; i < p->nBins; i++ ) + for ( pEnt = p->pBins[i]; pEnt; pEnt = pEnt->pNext ) + for ( pSuper = pEnt->pGates; pSuper; pSuper = pSuper->pNext ) + ppSupers[nSupers++] = pSuper; + + // sort by usage + qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *), + (int (*)(const void *, const void *)) Map_SuperTableCompareSupergates ); + assert( Map_SuperTableCompareSupergates( ppSupers, ppSupers + nSupers - 1 ) <= 0 ); + + // print out the "top ten" +// for ( i = 0; i < nSupers; i++ ) + for ( i = 0; i < 10; i++ ) + { + if ( ppSupers[i]->nUsed == 0 ) + break; + printf( "%5d : ", ppSupers[i]->nUsed ); + printf( "%5d ", ppSupers[i]->Num ); + printf( "A = %5.2f ", ppSupers[i]->Area ); + printf( "D = %5.2f ", ppSupers[i]->tDelayMax.Rise ); + printf( "%s", ppSupers[i]->pFormula ); + printf( "\n" ); + } + free( ppSupers ); +} + +/**Function************************************************************* + + Synopsis [Sorts supergates by max delay for each truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax ) +{ + Map_HashEntry_t * pEnt; + Map_Super_t ** ppSupers; + Map_Super_t * pSuper; + int nSupers, i, k; + + ppSupers = ALLOC( Map_Super_t *, nSupersMax ); + for ( i = 0; i < p->nBins; i++ ) + for ( pEnt = p->pBins[i]; pEnt; pEnt = pEnt->pNext ) + { + // collect the gates in this entry + nSupers = 0; + for ( pSuper = pEnt->pGates; pSuper; pSuper = pSuper->pNext ) + { + // skip supergates, whose root is the AND gate +// if ( strcmp( Mio_GateReadName(pSuper->pRoot), "and" ) == 0 ) +// continue; + ppSupers[nSupers++] = pSuper; + } + pEnt->pGates = NULL; + if ( nSupers == 0 ) + continue; + // sort the gates by delay + qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *), + (int (*)(const void *, const void *)) Map_SuperTableCompareGatesInList ); + assert( Map_SuperTableCompareGatesInList( ppSupers, ppSupers + nSupers - 1 ) <= 0 ); + // link them in the reverse order + for ( k = 0; k < nSupers; k++ ) + { + ppSupers[k]->pNext = pEnt->pGates; + pEnt->pGates = ppSupers[k]; + } + // save the number of supergates in the list + pEnt->pGates->nSupers = nSupers; + } + FREE( ppSupers ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperTime.c b/abc70930/src/map/mapper/mapperTime.c new file mode 100644 index 00000000..cc4173cf --- /dev/null +++ b/abc70930/src/map/mapper/mapperTime.c @@ -0,0 +1,510 @@ +/**CFile**************************************************************** + + FileName [mapperTime.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperTime.c,v 1.3 2005/03/02 02:35:54 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Map_TimePropagateRequired( Map_Man_t * p, Map_NodeVec_t * vNodes ); +static void Map_TimePropagateRequiredPhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase ); +static float Map_MatchComputeReqTimes( Map_Cut_t * pCut, int fPhase, Map_Time_t * ptArrRes ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +float Map_TimeMatchWithInverter( Map_Man_t * p, Map_Match_t * pMatch ) +{ + Map_Time_t tArrInv; + tArrInv.Fall = pMatch->tArrive.Rise + p->pSuperLib->tDelayInv.Fall; + tArrInv.Rise = pMatch->tArrive.Fall + p->pSuperLib->tDelayInv.Rise; + tArrInv.Worst = MAP_MAX( tArrInv.Rise, tArrInv.Fall ); + return tArrInv.Worst; +} + +/**Function************************************************************* + + Synopsis [Computes the arrival times of the cut recursively.] + + Description [When computing the arrival time for the previously unused + cuts, their arrival time may be incorrect because their fanins have + incorrect arrival time. This procedure is called to fix this problem.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_TimeCutComputeArrival_rec( Map_Cut_t * pCut, int fPhase ) +{ + int i, fPhaseLeaf; + for ( i = 0; i < pCut->nLeaves; i++ ) + { + fPhaseLeaf = Map_CutGetLeafPhase( pCut, fPhase, i ); + if ( pCut->ppLeaves[i]->nRefAct[fPhaseLeaf] > 0 ) + continue; + Map_TimeCutComputeArrival_rec( pCut->ppLeaves[i]->pCutBest[fPhaseLeaf], fPhaseLeaf ); + } + Map_TimeCutComputeArrival( NULL, pCut, fPhase, MAP_FLOAT_LARGE ); +} + +/**Function************************************************************* + + Synopsis [Computes the arrival times of the cut.] + + Description [Computes the arrival times of the cut if it is implemented using + the given supergate with the given phase. Uses the constraint-type specification + of rise/fall arrival times.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Map_TimeCutComputeArrival( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float tWorstLimit ) +{ + Map_Match_t * pM = pCut->M + fPhase; + Map_Super_t * pSuper = pM->pSuperBest; + unsigned uPhaseTot = pM->uPhaseBest; + Map_Time_t * ptArrRes = &pM->tArrive; + Map_Time_t * ptArrIn; + bool fPinPhase; + float tDelay; + int i; + + ptArrRes->Rise = ptArrRes->Fall = 0.0; + ptArrRes->Worst = MAP_FLOAT_LARGE; + for ( i = pCut->nLeaves - 1; i >= 0; i-- ) + { + // get the phase of the given pin + fPinPhase = ((uPhaseTot & (1 << i)) == 0); + ptArrIn = pCut->ppLeaves[i]->tArrival + fPinPhase; + + // get the rise of the output due to rise of the inputs + if ( pSuper->tDelaysR[i].Rise > 0 ) + { + tDelay = ptArrIn->Rise + pSuper->tDelaysR[i].Rise; + if ( tDelay > tWorstLimit ) + return MAP_FLOAT_LARGE; + if ( ptArrRes->Rise < tDelay ) + ptArrRes->Rise = tDelay; + } + + // get the rise of the output due to fall of the inputs + if ( pSuper->tDelaysR[i].Fall > 0 ) + { + tDelay = ptArrIn->Fall + pSuper->tDelaysR[i].Fall; + if ( tDelay > tWorstLimit ) + return MAP_FLOAT_LARGE; + if ( ptArrRes->Rise < tDelay ) + ptArrRes->Rise = tDelay; + } + + // get the fall of the output due to rise of the inputs + if ( pSuper->tDelaysF[i].Rise > 0 ) + { + tDelay = ptArrIn->Rise + pSuper->tDelaysF[i].Rise; + if ( tDelay > tWorstLimit ) + return MAP_FLOAT_LARGE; + if ( ptArrRes->Fall < tDelay ) + ptArrRes->Fall = tDelay; + } + + // get the fall of the output due to fall of the inputs + if ( pSuper->tDelaysF[i].Fall > 0 ) + { + tDelay = ptArrIn->Fall + pSuper->tDelaysF[i].Fall; + if ( tDelay > tWorstLimit ) + return MAP_FLOAT_LARGE; + if ( ptArrRes->Fall < tDelay ) + ptArrRes->Fall = tDelay; + } + } + // return the worst-case of rise/fall arrival times + ptArrRes->Worst = MAP_MAX(ptArrRes->Rise, ptArrRes->Fall); + return ptArrRes->Worst; +} + + +/**Function************************************************************* + + Synopsis [Computes the maximum arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Map_TimeComputeArrivalMax( Map_Man_t * p ) +{ + float tReqMax, tReq; + int i, fPhase; + // get the critical PO arrival time + tReqMax = -MAP_FLOAT_LARGE; + for ( i = 0; i < p->nOutputs; i++ ) + { + if ( Map_NodeIsConst(p->pOutputs[i]) ) + continue; + fPhase = !Map_IsComplement(p->pOutputs[i]); + tReq = Map_Regular(p->pOutputs[i])->tArrival[fPhase].Worst; + tReqMax = MAP_MAX( tReqMax, tReq ); + } + return tReqMax; +} + +/**Function************************************************************* + + Synopsis [Computes the required times of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_TimeComputeRequiredGlobal( Map_Man_t * p ) +{ + p->fRequiredGlo = Map_TimeComputeArrivalMax( p ); + // update the required times according to the target + if ( p->DelayTarget != -1 ) + { + if ( p->fRequiredGlo > p->DelayTarget + p->fEpsilon ) + { + if ( p->fMappingMode == 1 ) + printf( "Cannot meet the target required times (%4.2f). Continue anyway.\n", p->DelayTarget ); + } + else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon ) + { + if ( p->fMappingMode == 1 ) + printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget ); + p->fRequiredGlo = p->DelayTarget; + } + } + Map_TimeComputeRequired( p, p->fRequiredGlo ); +} + +/**Function************************************************************* + + Synopsis [Computes the required times of all nodes.] + + Description [This procedure assumes that the nodes used in the mapping + are collected in p->vMapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_TimeComputeRequired( Map_Man_t * p, float fRequired ) +{ + Map_Time_t * ptTime; + int fPhase, i; + + // clean the required times + for ( i = 0; i < p->vAnds->nSize; i++ ) + { + p->vAnds->pArray[i]->tRequired[0].Rise = MAP_FLOAT_LARGE; + p->vAnds->pArray[i]->tRequired[0].Fall = MAP_FLOAT_LARGE; + p->vAnds->pArray[i]->tRequired[0].Worst = MAP_FLOAT_LARGE; + p->vAnds->pArray[i]->tRequired[1].Rise = MAP_FLOAT_LARGE; + p->vAnds->pArray[i]->tRequired[1].Fall = MAP_FLOAT_LARGE; + p->vAnds->pArray[i]->tRequired[1].Worst = MAP_FLOAT_LARGE; + } + + // set the required times for the POs + for ( i = 0; i < p->nOutputs; i++ ) + { + fPhase = !Map_IsComplement(p->pOutputs[i]); + ptTime = Map_Regular(p->pOutputs[i])->tRequired + fPhase; + ptTime->Rise = ptTime->Fall = ptTime->Worst = fRequired; + } + + // sorts the nodes in the decreasing order of levels + // this puts the nodes in reverse topological order +// Map_MappingSortByLevel( p, p->vMapping ); + // the array is already sorted by construction in Map_MappingSetRefs() + + Map_TimePropagateRequired( p, p->vMapping ); +} + +/**Function************************************************************* + + Synopsis [Computes the required times of the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_TimePropagateRequired( Map_Man_t * p, Map_NodeVec_t * vNodes ) +{ + Map_Node_t * pNode; + Map_Time_t tReqOutTest, * ptReqOutTest = &tReqOutTest; + Map_Time_t * ptReqIn, * ptReqOut; + int fPhase, k; + + // go through the nodes in the reverse topological order + for ( k = 0; k < vNodes->nSize; k++ ) + { + pNode = vNodes->pArray[k]; + + // this computation works for regular nodes only + assert( !Map_IsComplement(pNode) ); + // at least one phase should be mapped + assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); + // the node should be used in the currently assigned mapping + assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); + + // if one of the cuts is not given, project the required times from the other cut + if ( pNode->pCutBest[0] == NULL || pNode->pCutBest[1] == NULL ) + { +// assert( 0 ); + // get the missing phase + fPhase = (pNode->pCutBest[1] == NULL); + // check if the missing phase is needed in the mapping + if ( pNode->nRefAct[fPhase] > 0 ) + { + // get the pointers to the required times of the missing phase + ptReqOut = pNode->tRequired + fPhase; +// assert( ptReqOut->Fall < MAP_FLOAT_LARGE ); + // get the pointers to the required times of the present phase + ptReqIn = pNode->tRequired + !fPhase; + // propagate the required times from the missing phase to the present phase + // tArrInv.Fall = pMatch->tArrive.Rise + p->pSuperLib->tDelayInv.Fall; + // tArrInv.Rise = pMatch->tArrive.Fall + p->pSuperLib->tDelayInv.Rise; + ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, ptReqOut->Rise - p->pSuperLib->tDelayInv.Rise ); + ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, ptReqOut->Fall - p->pSuperLib->tDelayInv.Fall ); + } + } + + // finalize the worst case computation + pNode->tRequired[0].Worst = MAP_MIN( pNode->tRequired[0].Fall, pNode->tRequired[0].Rise ); + pNode->tRequired[1].Worst = MAP_MIN( pNode->tRequired[1].Fall, pNode->tRequired[1].Rise ); + + // skip the PIs + if ( !Map_NodeIsAnd(pNode) ) + continue; + + // propagate required times of different phases of the node + // the ordering of phases does not matter since they are mapped independently + if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE ) + Map_TimePropagateRequiredPhase( p, pNode, 0 ); + if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE ) + Map_TimePropagateRequiredPhase( p, pNode, 1 ); + } + + // in the end, we verify the required times + // for this, we compute the arrival times of the outputs of each phase + // of the supergates using the fanins' required times as the fanins' arrival times + // the resulting arrival time of the supergate should be less than the actual required time + for ( k = 0; k < vNodes->nSize; k++ ) + { + pNode = vNodes->pArray[k]; + if ( !Map_NodeIsAnd(pNode) ) + continue; + // verify that the required times are propagated correctly +// if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) + if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE ) + { + Map_MatchComputeReqTimes( pNode->pCutBest[0], 0, ptReqOutTest ); + assert( ptReqOutTest->Rise < pNode->tRequired[0].Rise + p->fEpsilon ); + assert( ptReqOutTest->Fall < pNode->tRequired[0].Fall + p->fEpsilon ); + } +// if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) + if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE ) + { + Map_MatchComputeReqTimes( pNode->pCutBest[1], 1, ptReqOutTest ); + assert( ptReqOutTest->Rise < pNode->tRequired[1].Rise + p->fEpsilon ); + assert( ptReqOutTest->Fall < pNode->tRequired[1].Fall + p->fEpsilon ); + } + } + +} + +/**Function************************************************************* + + Synopsis [Computes the required times of the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_TimePropagateRequiredPhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase ) +{ + Map_Time_t * ptReqIn, * ptReqOut; + Map_Cut_t * pCut; + Map_Super_t * pSuper; + float tNewReqTime; + unsigned uPhase; + int fPinPhase, i; + + // get the cut to be propagated + pCut = pNode->pCutBest[fPhase]; + assert( pCut != NULL ); + // get the supergate and its polarity + pSuper = pCut->M[fPhase].pSuperBest; + uPhase = pCut->M[fPhase].uPhaseBest; + // get the required time of the output of the supergate + ptReqOut = pNode->tRequired + fPhase; + // set the required time of the children + for ( i = 0; i < pCut->nLeaves; i++ ) + { + // get the phase of the given pin of the supergate + fPinPhase = ((uPhase & (1 << i)) == 0); + ptReqIn = pCut->ppLeaves[i]->tRequired + fPinPhase; + assert( pCut->ppLeaves[i]->nRefAct[2] > 0 ); + + // get the rise of the output due to rise of the inputs +// if ( ptArrOut->Rise < ptArrIn->Rise + pSuper->tDelaysR[i].Rise ) +// ptArrOut->Rise = ptArrIn->Rise + pSuper->tDelaysR[i].Rise; + if ( pSuper->tDelaysR[i].Rise > 0 ) + { + tNewReqTime = ptReqOut->Rise - pSuper->tDelaysR[i].Rise; + ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, tNewReqTime ); + } + + // get the rise of the output due to fall of the inputs +// if ( ptArrOut->Rise < ptArrIn->Fall + pSuper->tDelaysR[i].Fall ) +// ptArrOut->Rise = ptArrIn->Fall + pSuper->tDelaysR[i].Fall; + if ( pSuper->tDelaysR[i].Fall > 0 ) + { + tNewReqTime = ptReqOut->Rise - pSuper->tDelaysR[i].Fall; + ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, tNewReqTime ); + } + + // get the fall of the output due to rise of the inputs +// if ( ptArrOut->Fall < ptArrIn->Rise + pSuper->tDelaysF[i].Rise ) +// ptArrOut->Fall = ptArrIn->Rise + pSuper->tDelaysF[i].Rise; + if ( pSuper->tDelaysF[i].Rise > 0 ) + { + tNewReqTime = ptReqOut->Fall - pSuper->tDelaysF[i].Rise; + ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, tNewReqTime ); + } + + // get the fall of the output due to fall of the inputs +// if ( ptArrOut->Fall < ptArrIn->Fall + pSuper->tDelaysF[i].Fall ) +// ptArrOut->Fall = ptArrIn->Fall + pSuper->tDelaysF[i].Fall; + if ( pSuper->tDelaysF[i].Fall > 0 ) + { + tNewReqTime = ptReqOut->Fall - pSuper->tDelaysF[i].Fall; + ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, tNewReqTime ); + } + } + + // compare the required times with the arrival times + assert( pNode->tArrival[fPhase].Rise < ptReqOut->Rise + p->fEpsilon ); + assert( pNode->tArrival[fPhase].Fall < ptReqOut->Fall + p->fEpsilon ); +} + +/**Function************************************************************* + + Synopsis [Computes the arrival times of the cut.] + + Description [Computes the arrival times of the cut if it is implemented using + the given supergate with the given phase. Uses the constraint-type specification + of rise/fall arrival times.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Map_MatchComputeReqTimes( Map_Cut_t * pCut, int fPhase, Map_Time_t * ptArrRes ) +{ + Map_Time_t * ptArrIn; + Map_Super_t * pSuper; + unsigned uPhaseTot; + int fPinPhase, i; + float tDelay; + + // get the supergate and the phase + pSuper = pCut->M[fPhase].pSuperBest; + uPhaseTot = pCut->M[fPhase].uPhaseBest; + + // propagate the arrival times + ptArrRes->Rise = ptArrRes->Fall = -MAP_FLOAT_LARGE; + for ( i = 0; i < pCut->nLeaves; i++ ) + { + // get the phase of the given pin + fPinPhase = ((uPhaseTot & (1 << i)) == 0); + ptArrIn = pCut->ppLeaves[i]->tRequired + fPinPhase; +// assert( ptArrIn->Worst < MAP_FLOAT_LARGE ); + + // get the rise of the output due to rise of the inputs + if ( pSuper->tDelaysR[i].Rise > 0 ) + { + tDelay = ptArrIn->Rise + pSuper->tDelaysR[i].Rise; + if ( ptArrRes->Rise < tDelay ) + ptArrRes->Rise = tDelay; + } + + // get the rise of the output due to fall of the inputs + if ( pSuper->tDelaysR[i].Fall > 0 ) + { + tDelay = ptArrIn->Fall + pSuper->tDelaysR[i].Fall; + if ( ptArrRes->Rise < tDelay ) + ptArrRes->Rise = tDelay; + } + + // get the fall of the output due to rise of the inputs + if ( pSuper->tDelaysF[i].Rise > 0 ) + { + tDelay = ptArrIn->Rise + pSuper->tDelaysF[i].Rise; + if ( ptArrRes->Fall < tDelay ) + ptArrRes->Fall = tDelay; + } + + // get the fall of the output due to fall of the inputs + if ( pSuper->tDelaysF[i].Fall > 0 ) + { + tDelay = ptArrIn->Fall + pSuper->tDelaysF[i].Fall; + if ( ptArrRes->Fall < tDelay ) + ptArrRes->Fall = tDelay; + } + } + // return the worst-case of rise/fall arrival times + return MAP_MAX(ptArrRes->Rise, ptArrRes->Fall); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperTree.c b/abc70930/src/map/mapper/mapperTree.c new file mode 100644 index 00000000..ef66082d --- /dev/null +++ b/abc70930/src/map/mapper/mapperTree.c @@ -0,0 +1,818 @@ +/**CFile**************************************************************** + + FileName [mapperTree.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperTree.c,v 1.9 2005/01/23 06:59:45 alanmi Exp $] + +***********************************************************************/ + +#ifdef __linux__ +#include +#endif + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Map_LibraryReadFileTree( Map_SuperLib_t * pLib, FILE * pFile, char *pFileName ); +static Map_Super_t * Map_LibraryReadGateTree( Map_SuperLib_t * pLib, char * pBuffer, int Number, int nVars ); +static int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st_table * tExcludeGate ); +static void Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin ); +static int Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate ); +static unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate ); + +// fanout limits +extern const int s_MapFanoutLimits[10] = { 1/*0*/, 10/*1*/, 5/*2*/, 2/*3*/, 1/*4*/, 1/*5*/, 1/*6*/ }; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reads the supergate library from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_LibraryReadTree( Map_SuperLib_t * pLib, char * pFileName, char * pExcludeFile ) +{ + FILE * pFile; + int Status, num; + Abc_Frame_t * pAbc; + st_table * tExcludeGate = 0; + + // read the beginning of the file + assert( pLib->pGenlib == NULL ); + pFile = Io_FileOpen( pFileName, "open_path", "r", 1 ); +// pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Cannot open input file \"%s\".\n", pFileName ); + return 0; + } + + if ( pExcludeFile ) + { + pAbc = Abc_FrameGetGlobalFrame(); + + tExcludeGate = st_init_table(strcmp, st_strhash); + if ( (num = Mio_LibraryReadExclude( pAbc, pExcludeFile, tExcludeGate )) == -1 ) + { + st_free_table( tExcludeGate ); + tExcludeGate = 0; + return 0; + } + + fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num ); + } + + Status = Map_LibraryReadFileTree( pLib, pFile, pFileName ); + fclose( pFile ); + if ( Status == 0 ) + return 0; + // prepare the info about the library + return Map_LibraryDeriveGateInfo( pLib, tExcludeGate ); +} + + +/**Function************************************************************* + + Synopsis [Reads the library file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_LibraryReadFileTree( Map_SuperLib_t * pLib, FILE * pFile, char *pFileName ) +{ + ProgressBar * pProgress; + char pBuffer[5000], pLibFile[5000]; + FILE * pFileGen; + Map_Super_t * pGate; + char * pTemp = 0, * pLibName; + int nCounter, k, i; + + // skip empty and comment lines + while ( fgets( pBuffer, 5000, pFile ) != NULL ) + { + // skip leading spaces + for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); + // skip comment lines and empty lines + if ( *pTemp != 0 && *pTemp != '#' ) + break; + } + + // get the genlib file name (base) + pLibName = strtok( pTemp, " \t\r\n" ); + + if ( strcmp( pLibName, "GATE" ) == 0 ) + { + printf( "The input file \"%s\" looks like a GENLIB file and not a supergate library file.\n", pLib->pName ); + return 0; + } + + + // now figure out the directory if any in the pFileName +#ifdef __linux__ + snprintf( pLibFile, 5000, "%s/%s", dirname(strdup(pFileName)), pLibName ); +#else + { + char * pStr; + strcpy( pLibFile, pFileName ); + pStr = pLibFile + strlen(pBuffer) - 1; + while ( pStr > pLibFile && *pStr != '\\' && *pStr != '/' ) + pStr--; + if ( pStr == pLibFile ) + strcpy( pLibFile, pLibName ); + else + sprintf( pStr, "/%s", pLibName ); + } +#endif + + pFileGen = Io_FileOpen( pLibFile, "open_path", "r", 1 ); +// pFileGen = fopen( pLibFile, "r" ); + if ( pFileGen == NULL ) + { + printf( "Cannot open the GENLIB file \"%s\".\n", pLibFile ); + return 0; + } + fclose( pFileGen ); + + // read the genlib library + pLib->pGenlib = Mio_LibraryRead( Abc_FrameGetGlobalFrame(), pLibFile, 0, 0 ); + if ( pLib->pGenlib == NULL ) + { + printf( "Cannot read GENLIB file \"%s\".\n", pLibFile ); + return 0; + } + + // read the number of variables + fscanf( pFile, "%d\n", &pLib->nVarsMax ); + if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 ) + { + printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax ); + return 0; + } + + // read the number of gates + fscanf( pFile, "%d\n", &pLib->nSupersReal ); + if ( pLib->nSupersReal < 1 || pLib->nSupersReal > 10000000 ) + { + printf( "Suspicious number of gates (%d).\n", pLib->nSupersReal ); + return 0; + } + + // read the number of lines + fscanf( pFile, "%d\n", &pLib->nLines ); + if ( pLib->nLines < 1 || pLib->nLines > 10000000 ) + { + printf( "Suspicious number of lines (%d).\n", pLib->nLines ); + return 0; + } + + // allocate room for supergate pointers + pLib->ppSupers = ALLOC( Map_Super_t *, pLib->nLines + 10000 ); + + // create the elementary supergates + for ( i = 0; i < pLib->nVarsMax; i++ ) + { + // get a new gate + pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); + memset( pGate, 0, sizeof(Map_Super_t) ); + // assign the elementary variable, the truth table, and the delays + pGate->Num = i; + // set the truth table + pGate->uTruth[0] = pLib->uTruths[i][0]; + pGate->uTruth[1] = pLib->uTruths[i][1]; + // set the arrival times of all input to non-existent delay + for ( k = 0; k < pLib->nVarsMax; k++ ) + { + pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR; + pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR; + } + // set an existent arrival time for rise and fall + pGate->tDelaysR[i].Rise = 0.0; + pGate->tDelaysF[i].Fall = 0.0; + // set the gate + pLib->ppSupers[i] = pGate; + } + + // read the lines + nCounter = pLib->nVarsMax; + pProgress = Extra_ProgressBarStart( stdout, pLib->nLines ); + while ( fgets( pBuffer, 5000, pFile ) != NULL ) + { + for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); + if ( pTemp[0] == '\0' ) + continue; +// if ( pTemp[0] == 'a' || pTemp[2] == 'a' ) +// { +// pLib->nLines--; +// continue; +// } + + // get the gate + pGate = Map_LibraryReadGateTree( pLib, pTemp, nCounter, pLib->nVarsMax ); + if ( pGate == NULL ) + { + Extra_ProgressBarStop( pProgress ); + return 0; + } + pLib->ppSupers[nCounter++] = pGate; + // later we will derive: truth table, delays, area, number of component gates, etc + + // update the progress bar + Extra_ProgressBarUpdate( pProgress, nCounter, NULL ); + } + Extra_ProgressBarStop( pProgress ); + if ( nCounter != pLib->nLines ) + printf( "The number of lines read (%d) is different what the file says (%d).\n", nCounter, pLib->nLines ); + pLib->nSupersAll = nCounter; + // count the number of real supergates + nCounter = 0; + for ( k = 0; k < pLib->nLines; k++ ) + nCounter += pLib->ppSupers[k]->fSuper; + if ( nCounter != pLib->nSupersReal ) + printf( "The number of gates read (%d) is different what the file says (%d).\n", nCounter, pLib->nSupersReal ); + pLib->nSupersReal = nCounter; + return 1; +} + +/**Function************************************************************* + + Synopsis [Reads one gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Super_t * Map_LibraryReadGateTree( Map_SuperLib_t * pLib, char * pBuffer, int Number, int nVarsMax ) +{ + Map_Super_t * pGate; + char * pTemp; + int i, Num; + + // start and clean the gate + pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); + memset( pGate, 0, sizeof(Map_Super_t) ); + + // set the gate number + pGate->Num = Number; + + // read the mark + pTemp = strtok( pBuffer, " " ); + if ( pTemp[0] == '*' ) + { + pGate->fSuper = 1; + pTemp = strtok( NULL, " " ); + } + + // read the root gate + pGate->pRoot = Mio_LibraryReadGateByName( pLib->pGenlib, pTemp ); + if ( pGate->pRoot == NULL ) + { + printf( "Cannot read the root gate names %s.\n", pTemp ); + return NULL; + } + // set the max number of fanouts + pGate->nFanLimit = s_MapFanoutLimits[ Mio_GateReadInputs(pGate->pRoot) ]; + + // read the pin-to-pin delay + for ( i = 0; ( pTemp = strtok( NULL, " \n\0" ) ); i++ ) + { + if ( pTemp[0] == '#' ) + break; + if ( i == nVarsMax ) + { + printf( "There are too many entries on the line.\n" ); + return NULL; + } + Num = atoi(pTemp); + if ( Num < 0 ) + { + printf( "The number of a child supergate is negative.\n" ); + return NULL; + } + if ( Num > pLib->nLines ) + { + printf( "The number of a child supergate (%d) exceeded the number of lines (%d).\n", + Num, pLib->nLines ); + return NULL; + } + pGate->pFanins[i] = pLib->ppSupers[Num]; + } + pGate->nFanins = i; + if ( pGate->nFanins != (unsigned)Mio_GateReadInputs(pGate->pRoot) ) + { + printf( "The number of fanins of a root gate is wrong.\n" ); + return NULL; + } + + // save the gate name, just in case + if ( pTemp && pTemp[0] == '#' ) + { + if ( pTemp[1] == 0 ) + pTemp = strtok( NULL, " \n\0" ); + else // skip spaces + for ( pTemp++; *pTemp == ' '; pTemp++ ); + // save the formula + pGate->pFormula = Extra_MmFlexEntryFetch( pLib->mmForms, strlen(pTemp)+1 ); + strcpy( pGate->pFormula, pTemp ); + } + // check the rest of the string + pTemp = strtok( NULL, " \n\0" ); + if ( pTemp != NULL ) + printf( "The following trailing symbols found \"%s\".\n", pTemp ); + return pGate; +} + + +/**Function************************************************************* + + Synopsis [Derives information about the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st_table * tExcludeGate ) +{ + Map_Super_t * pGate, * pFanin; + Mio_Pin_t * pPin; + unsigned uCanon[2]; + unsigned uTruths[6][2]; + int i, k, nRealVars; + + // set all the derivable info related to the supergates + for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ ) + { + pGate = pLib->ppSupers[i]; + + if ( tExcludeGate ) + { + if ( st_is_member( tExcludeGate, Mio_GateReadName( pGate->pRoot ) ) ) + pGate->fExclude = 1; + for ( k = 0; k < (int)pGate->nFanins; k++ ) + { + pFanin = pGate->pFanins[k]; + if ( pFanin->fExclude ) + { + pGate->fExclude = 1; + continue; + } + } + } + + // collect the truth tables of the fanins + for ( k = 0; k < (int)pGate->nFanins; k++ ) + { + pFanin = pGate->pFanins[k]; + uTruths[k][0] = pFanin->uTruth[0]; + uTruths[k][1] = pFanin->uTruth[1]; + } + // derive the new truth table + Mio_DeriveTruthTable( pGate->pRoot, uTruths, pGate->nFanins, 6, pGate->uTruth ); + + // set the initial delays of the supergate + for ( k = 0; k < pLib->nVarsMax; k++ ) + { + pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR; + pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR; + } + // get the linked list of pins for the given root gate + pPin = Mio_GateReadPins( pGate->pRoot ); + // update the initial delay of the supergate using info from the corresponding pin + for ( k = 0; k < (int)pGate->nFanins; k++, pPin = Mio_PinReadNext(pPin) ) + { + // if there is no corresponding pin, this is a bug, return fail + if ( pPin == NULL ) + { + printf( "There are less pins than gate inputs.\n" ); + return 0; + } + // update the delay information of k-th fanins info from the corresponding pin + Map_LibraryAddFaninDelays( pLib, pGate, pGate->pFanins[k], pPin ); + } + // if there are some pins left, this is a bug, return fail + if ( pPin != NULL ) + { + printf( "There are more pins than gate inputs.\n" ); + return 0; + } + // find the max delay + pGate->tDelayMax.Rise = pGate->tDelayMax.Fall = MAP_NO_VAR; + for ( k = 0; k < pLib->nVarsMax; k++ ) + { + // the rise of the output depends on the rise and fall of the output + if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Rise ) + pGate->tDelayMax.Rise = pGate->tDelaysR[k].Rise; + if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Fall ) + pGate->tDelayMax.Rise = pGate->tDelaysR[k].Fall; + // the fall of the output depends on the rise and fall of the output + if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Rise ) + pGate->tDelayMax.Fall = pGate->tDelaysF[k].Rise; + if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Fall ) + pGate->tDelayMax.Fall = pGate->tDelaysF[k].Fall; + + pGate->tDelaysF[k].Worst = MAP_MAX( pGate->tDelaysF[k].Fall, pGate->tDelaysF[k].Rise ); + pGate->tDelaysR[k].Worst = MAP_MAX( pGate->tDelaysR[k].Fall, pGate->tDelaysR[k].Rise ); + } + + // count gates and area of the supergate + pGate->nGates = 1; + pGate->Area = (float)Mio_GateReadArea(pGate->pRoot); + for ( k = 0; k < (int)pGate->nFanins; k++ ) + { + pGate->nGates += pGate->pFanins[k]->nGates; + pGate->Area += pGate->pFanins[k]->Area; + } + // do not add the gate to the table, if this gate is an internal gate + // of some supegate and does not correspond to a supergate output + if ( ( !pGate->fSuper ) || pGate->fExclude ) + continue; + + // find the maximum index of a variable in the support of the supergates + // this is important for two reasons: + // (1) to limit the number of permutations considered for canonicization + // (2) to get rid of equivalence phases to speed-up matching + nRealVars = Map_LibraryGetMaxSuperPi_rec( pGate ) + 1; + assert( nRealVars > 0 && nRealVars <= pLib->nVarsMax ); + // if there are some problems with this code, try this instead +// nRealVars = pLib->nVarsMax; + + // find the N-canonical form of this supergate + pGate->nPhases = Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, nRealVars, pGate->uTruth, pGate->uPhases, uCanon ); + // add the supergate into the table by its N-canonical table + Map_SuperTableInsertC( pLib->tTableC, uCanon, pGate ); +/* + { + int uCanon1, uCanon2; + uCanon1 = uCanon[0]; + pGate->uTruth[0] = ~pGate->uTruth[0]; + pGate->uTruth[1] = ~pGate->uTruth[1]; + Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, nRealVars, pGate->uTruth, pGate->uPhases, uCanon ); + uCanon2 = uCanon[0]; +Rwt_Man5ExploreCount( uCanon1 < uCanon2 ? uCanon1 : uCanon2 ); + } +*/ + } + // sort the gates in each line + Map_SuperTableSortSupergatesByDelay( pLib->tTableC, pLib->nSupersAll ); + + // let the glory be manifest +// Map_LibraryPrintTree( pLib ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Finds the largest PI number in the support of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate ) +{ + int i, VarCur, VarMax = 0; + if ( pGate->pRoot == NULL ) + return pGate->Num; + for ( i = 0; i < (int)pGate->nFanins; i++ ) + { + VarCur = Map_LibraryGetMaxSuperPi_rec( pGate->pFanins[i] ); + if ( VarMax < VarCur ) + VarMax = VarCur; + } + return VarMax; +} + +/**Function************************************************************* + + Synopsis [Finds the largest PI number in the support of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate ) +{ + unsigned uSupport; + int i; + if ( pGate->pRoot == NULL ) + return (unsigned)(1 << (pGate->Num)); + uSupport = 0; + for ( i = 0; i < (int)pGate->nFanins; i++ ) + uSupport |= Map_LibraryGetGateSupp_rec( pGate->pFanins[i] ); + return uSupport; +} + +/**Function************************************************************* + + Synopsis [Derives the pin-to-pin delay constraints for the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin ) +{ + Mio_PinPhase_t PinPhase; + float tDelayBlockRise, tDelayBlockFall, tDelayPin; + bool fMaxDelay = 0; + int i; + + // use this node to enable max-delay model + if ( fMaxDelay ) + { + float tDelayBlockMax; + // get the maximum delay + tDelayBlockMax = (float)Mio_PinReadDelayBlockMax(pPin); + // go through the supergate inputs + for ( i = 0; i < pLib->nVarsMax; i++ ) + { + if ( pFanin->tDelaysR[i].Rise < 0 ) + continue; + tDelayPin = pFanin->tDelaysR[i].Rise + tDelayBlockMax; + if ( pGate->tDelaysR[i].Rise < tDelayPin ) + pGate->tDelaysR[i].Rise = tDelayPin; + } + // go through the supergate inputs + for ( i = 0; i < pLib->nVarsMax; i++ ) + { + if ( pFanin->tDelaysF[i].Fall < 0 ) + continue; + tDelayPin = pFanin->tDelaysF[i].Fall + tDelayBlockMax; + if ( pGate->tDelaysF[i].Fall < tDelayPin ) + pGate->tDelaysF[i].Fall = tDelayPin; + } + return; + } + + // get the interesting parameters of this pin + PinPhase = Mio_PinReadPhase(pPin); + tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); + tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); + + // update the rise and fall of the output depending on the phase of the pin + if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present + { + // the rise of the gate is determined by the rise of the fanin + // the fall of the gate is determined by the fall of the fanin + for ( i = 0; i < pLib->nVarsMax; i++ ) + { + //////////////////////////////////////////////////////// + // consider the rise of the gate + //////////////////////////////////////////////////////// + // check two types of constraints on the rise of the fanin: + // (1) the constraints related to the rise of the PIs + // (2) the constraints related to the fall of the PIs + if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1) + { // fanin's rise depends on the rise of i-th PI + // update the rise of the gate's output + if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockRise ) + pGate->tDelaysR[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockRise; + } + if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2) + { // fanin's rise depends on the fall of i-th PI + // update the rise of the gate's output + if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockRise ) + pGate->tDelaysR[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockRise; + } + //////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////// + // consider the fall of the gate (similar) + //////////////////////////////////////////////////////// + // check two types of constraints on the fall of the fanin: + // (1) the constraints related to the rise of the PIs + // (2) the constraints related to the fall of the PIs + if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1) + { + if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockFall ) + pGate->tDelaysF[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockFall; + } + if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2) + { + if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockFall ) + pGate->tDelaysF[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockFall; + } + //////////////////////////////////////////////////////// + } + } + if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present + { + // the rise of the gate is determined by the fall of the fanin + // the fall of the gate is determined by the rise of the fanin + for ( i = 0; i < pLib->nVarsMax; i++ ) + { + //////////////////////////////////////////////////////// + // consider the rise of the gate's output + //////////////////////////////////////////////////////// + // check two types of constraints on the fall of the fanin: + // (1) the constraints related to the rise of the PIs + // (2) the constraints related to the fall of the PIs + if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1) + { // fanin's rise depends on the rise of i-th PI + // update the rise of the gate + if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockRise ) + pGate->tDelaysR[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockRise; + } + if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2) + { // fanin's rise depends on the fall of i-th PI + // update the rise of the gate + if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockRise ) + pGate->tDelaysR[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockRise; + } + //////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////// + // consider the fall of the gate (similar) + //////////////////////////////////////////////////////// + // check two types of constraints on the rise of the fanin: + // (1) the constraints related to the rise of the PIs + // (2) the constraints related to the fall of the PIs + if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1) + { + if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockFall ) + pGate->tDelaysF[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockFall; + } + if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2) + { + if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockFall ) + pGate->tDelaysF[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockFall; + } + //////////////////////////////////////////////////////// + } + } +} + + +/**Function************************************************************* + + Synopsis [Performs phase transformation for one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Map_CalculatePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase ) +{ + int v, Shift; + for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) + if ( uPhase & Shift ) + uTruth = (((uTruth & ~uTruths[v][0]) << Shift) | ((uTruth & uTruths[v][0]) >> Shift)); + return uTruth; +} + +/**Function************************************************************* + + Synopsis [Performs phase transformation for one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CalculatePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] ) +{ + unsigned uTemp; + int v, Shift; + + // initialize the result + uTruthRes[0] = uTruth[0]; + uTruthRes[1] = uTruth[1]; + if ( uPhase == 0 ) + return; + // compute the phase + for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) + if ( uPhase & Shift ) + { + if ( Shift < 32 ) + { + uTruthRes[0] = (((uTruthRes[0] & ~uTruths[v][0]) << Shift) | ((uTruthRes[0] & uTruths[v][0]) >> Shift)); + uTruthRes[1] = (((uTruthRes[1] & ~uTruths[v][1]) << Shift) | ((uTruthRes[1] & uTruths[v][1]) >> Shift)); + } + else + { + uTemp = uTruthRes[0]; + uTruthRes[0] = uTruthRes[1]; + uTruthRes[1] = uTemp; + } + } +} + +/**Function************************************************************* + + Synopsis [Prints the supergate library after deriving parameters.] + + Description [This procedure is very useful to see the library after + it has been read into the mapper by "read_super" and all the information + about the supergates derived.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_LibraryPrintTree( Map_SuperLib_t * pLib ) +{ + Map_Super_t * pGate; + int i, k; + + // print all the info related to the supergates +// for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ ) + for ( i = pLib->nVarsMax; i < 20; i++ ) + { + pGate = pLib->ppSupers[i]; + + // write the gate's fanin info and formula + printf( "%6d ", pGate->Num ); + printf( "%c ", pGate->fSuper? '*' : ' ' ); + printf( "%6s", Mio_GateReadName(pGate->pRoot) ); + for ( k = 0; k < (int)pGate->nFanins; k++ ) + printf( " %6d", pGate->pFanins[k]->Num ); + printf( " %s", pGate->pFormula ); + printf( "\n" ); + + // write the gate's derived info + Extra_PrintBinary( stdout, pGate->uTruth, 64 ); + printf( " %3d", pGate->nGates ); + printf( " %6.2f", pGate->Area ); + printf( " (%4.2f, %4.2f)", pGate->tDelayMax.Rise, pGate->tDelayMax.Fall ); + printf( "\n" ); + for ( k = 0; k < pLib->nVarsMax; k++ ) + { + // print the constraint on the rise of the gate in the form (D1, D2), + // where D1 is the constraint related to the rise of the k-th PI + // where D2 is the constraint related to the fall of the k-th PI + if ( pGate->tDelaysR[k].Rise < 0 && pGate->tDelaysR[k].Fall < 0 ) + printf( " (----, ----)" ); + else if ( pGate->tDelaysR[k].Fall < 0 ) + printf( " (%4.2f, ----)", pGate->tDelaysR[k].Rise ); + else if ( pGate->tDelaysR[k].Rise < 0 ) + printf( " (----, %4.2f)", pGate->tDelaysR[k].Fall ); + else + printf( " (%4.2f, %4.2f)", pGate->tDelaysR[k].Rise, pGate->tDelaysR[k].Fall ); + + // print the constraint on the fall of the gate in the form (D1, D2), + // where D1 is the constraint related to the rise of the k-th PI + // where D2 is the constraint related to the fall of the k-th PI + if ( pGate->tDelaysF[k].Rise < 0 && pGate->tDelaysF[k].Fall < 0 ) + printf( " (----, ----)" ); + else if ( pGate->tDelaysF[k].Fall < 0 ) + printf( " (%4.2f, ----)", pGate->tDelaysF[k].Rise ); + else if ( pGate->tDelaysF[k].Rise < 0 ) + printf( " (----, %4.2f)", pGate->tDelaysF[k].Fall ); + else + printf( " (%4.2f, %4.2f)", pGate->tDelaysF[k].Rise, pGate->tDelaysF[k].Fall ); + printf( "\n" ); + } + printf( "\n" ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperTruth.c b/abc70930/src/map/mapper/mapperTruth.c new file mode 100644 index 00000000..388b6dd3 --- /dev/null +++ b/abc70930/src/map/mapper/mapperTruth.c @@ -0,0 +1,310 @@ +/**CFile**************************************************************** + + FileName [mapperTruth.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperTruth.c,v 1.8 2005/01/23 06:59:45 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Map_TruthsCut( Map_Man_t * pMan, Map_Cut_t * pCut ); +extern void Map_TruthsCutOne( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] ); +static void Map_CutsCollect_rec( Map_Cut_t * pCut, Map_NodeVec_t * vVisited ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives truth tables for each cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingTruths( Map_Man_t * pMan ) +{ + ProgressBar * pProgress; + Map_Node_t * pNode; + Map_Cut_t * pCut; + int nNodes, i; + // compute the cuts for the POs + nNodes = pMan->vAnds->nSize; + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + for ( i = 0; i < nNodes; i++ ) + { + pNode = pMan->vAnds->pArray[i]; + if ( !Map_NodeIsAnd( pNode ) ) + continue; + assert( pNode->pCuts ); + assert( pNode->pCuts->nLeaves == 1 ); + + // match the simple cut + pNode->pCuts->M[0].uPhase = 0; + pNode->pCuts->M[0].pSupers = pMan->pSuperLib->pSuperInv; + pNode->pCuts->M[0].uPhaseBest = 0; + pNode->pCuts->M[0].pSuperBest = pMan->pSuperLib->pSuperInv; + + pNode->pCuts->M[1].uPhase = 0; + pNode->pCuts->M[1].pSupers = pMan->pSuperLib->pSuperInv; + pNode->pCuts->M[1].uPhaseBest = 1; + pNode->pCuts->M[1].pSuperBest = pMan->pSuperLib->pSuperInv; + + // match the rest of the cuts + for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) + Map_TruthsCut( pMan, pCut ); + Extra_ProgressBarUpdate( pProgress, i, "Tables ..." ); + } + Extra_ProgressBarStop( pProgress ); +} + +/**Function************************************************************* + + Synopsis [Derives the truth table for one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut ) +{ +// unsigned uCanon1, uCanon2; + unsigned uTruth[2], uCanon[2]; + unsigned char uPhases[16]; + unsigned * uCanon2; + char * pPhases2; + int fUseFast = 1; + int fUseSlow = 0; + int fUseRec = 0; // this does not work for Solaris + + extern int Map_CanonCompute( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes ); + + // generally speaking, 1-input cut can be matched into a wire! + if ( pCut->nLeaves == 1 ) + return; +/* + if ( p->nVarsMax == 5 ) + { + uTruth[0] = pCut->uTruth; + uTruth[1] = pCut->uTruth; + } + else +*/ + Map_TruthsCutOne( p, pCut, uTruth ); + + + // compute the canonical form for the positive phase + if ( fUseFast ) + Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); + else if ( fUseSlow ) + Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); + else if ( fUseRec ) + { +// Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); + Extra_TruthCanonFastN( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); +/* + if ( uCanon[0] != uCanon2[0] || uPhases[0] != pPhases2[0] ) + { + int k = 0; + Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); + } +*/ + uCanon[0] = uCanon2[0]; + uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; + uPhases[0] = pPhases2[0]; + } + else + Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); + pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon ); + pCut->M[1].uPhase = uPhases[0]; + p->nCanons++; + +//uCanon1 = uCanon[0] & 0xFFFF; + + // compute the canonical form for the negative phase + uTruth[0] = ~uTruth[0]; + uTruth[1] = ~uTruth[1]; + if ( fUseFast ) + Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); + else if ( fUseSlow ) + Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); + else if ( fUseRec ) + { +// Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); + Extra_TruthCanonFastN( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); +/* + if ( uCanon[0] != uCanon2[0] || uPhases[0] != pPhases2[0] ) + { + int k = 0; + Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); + } +*/ + uCanon[0] = uCanon2[0]; + uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; + uPhases[0] = pPhases2[0]; + } + else + Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); + pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon ); + pCut->M[0].uPhase = uPhases[0]; + p->nCanons++; + +//uCanon2 = uCanon[0] & 0xFFFF; +//assert( p->nVarsMax == 4 ); +//Rwt_Man4ExploreCount( uCanon1 < uCanon2 ? uCanon1 : uCanon2 ); + + // restore the truth table + uTruth[0] = ~uTruth[0]; + uTruth[1] = ~uTruth[1]; +} + +/**Function************************************************************* + + Synopsis [Computes the truth table of one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_TruthsCutOne( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] ) +{ + unsigned uTruth1[2], uTruth2[2]; + Map_Cut_t * pTemp; + int i; + // mark the cut leaves + for ( i = 0; i < pCut->nLeaves; i++ ) + { + pTemp = pCut->ppLeaves[i]->pCuts; + pTemp->fMark = 1; + pTemp->M[0].uPhaseBest = p->uTruths[i][0]; + pTemp->M[1].uPhaseBest = p->uTruths[i][1]; + } + assert( pCut->fMark == 0 ); + + // collect the cuts in the cut cone + p->vVisited->nSize = 0; + Map_CutsCollect_rec( pCut, p->vVisited ); + assert( p->vVisited->nSize > 0 ); + pCut->nVolume = p->vVisited->nSize; + + // compute the tables and unmark + for ( i = 0; i < pCut->nLeaves; i++ ) + { + pTemp = pCut->ppLeaves[i]->pCuts; + pTemp->fMark = 0; + } + for ( i = 0; i < p->vVisited->nSize; i++ ) + { + // get the cut + pTemp = (Map_Cut_t *)p->vVisited->pArray[i]; + pTemp->fMark = 0; + // get truth table of the first branch + if ( Map_CutIsComplement(pTemp->pOne) ) + { + uTruth1[0] = ~Map_CutRegular(pTemp->pOne)->M[0].uPhaseBest; + uTruth1[1] = ~Map_CutRegular(pTemp->pOne)->M[1].uPhaseBest; + } + else + { + uTruth1[0] = Map_CutRegular(pTemp->pOne)->M[0].uPhaseBest; + uTruth1[1] = Map_CutRegular(pTemp->pOne)->M[1].uPhaseBest; + } + // get truth table of the second branch + if ( Map_CutIsComplement(pTemp->pTwo) ) + { + uTruth2[0] = ~Map_CutRegular(pTemp->pTwo)->M[0].uPhaseBest; + uTruth2[1] = ~Map_CutRegular(pTemp->pTwo)->M[1].uPhaseBest; + } + else + { + uTruth2[0] = Map_CutRegular(pTemp->pTwo)->M[0].uPhaseBest; + uTruth2[1] = Map_CutRegular(pTemp->pTwo)->M[1].uPhaseBest; + } + // get the truth table of the output + if ( !pTemp->Phase ) + { + pTemp->M[0].uPhaseBest = uTruth1[0] & uTruth2[0]; + pTemp->M[1].uPhaseBest = uTruth1[1] & uTruth2[1]; + } + else + { + pTemp->M[0].uPhaseBest = ~(uTruth1[0] & uTruth2[0]); + pTemp->M[1].uPhaseBest = ~(uTruth1[1] & uTruth2[1]); + } + } + uTruth[0] = pTemp->M[0].uPhaseBest; + uTruth[1] = pTemp->M[1].uPhaseBest; +} + +/**Function************************************************************* + + Synopsis [Recursively collect the cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_CutsCollect_rec( Map_Cut_t * pCut, Map_NodeVec_t * vVisited ) +{ + if ( pCut->fMark ) + return; + Map_CutsCollect_rec( Map_CutRegular(pCut->pOne), vVisited ); + Map_CutsCollect_rec( Map_CutRegular(pCut->pTwo), vVisited ); + assert( pCut->fMark == 0 ); + pCut->fMark = 1; + Map_NodeVecPush( vVisited, (Map_Node_t *)pCut ); +} + +/* + { + unsigned * uCanon2; + char * pPhases2; + + Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); + Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); + if ( uCanon2[0] != uCanon[0] ) + { + int v = 0; + Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); + Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); + } +// else +// { +// printf( "Correct.\n" ); +// } + } +*/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperUtils.c b/abc70930/src/map/mapper/mapperUtils.c new file mode 100644 index 00000000..11a3a683 --- /dev/null +++ b/abc70930/src/map/mapper/mapperUtils.c @@ -0,0 +1,1154 @@ +/**CFile**************************************************************** + + FileName [mapperUtils.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperUtils.c,v 1.8 2004/11/03 22:41:45 satrajit Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define MAP_CO_LIST_SIZE 5 + +static void Map_MappingDfs_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fCollectEquiv ); +static int Map_MappingCountLevels_rec( Map_Node_t * pNode ); +static float Map_MappingSetRefsAndArea_rec( Map_Man_t * pMan, Map_Node_t * pNode ); +static float Map_MappingSetRefsAndSwitch_rec( Map_Man_t * pMan, Map_Node_t * pNode ); +static float Map_MappingSetRefsAndWire_rec( Map_Man_t * pMan, Map_Node_t * pNode ); +static void Map_MappingDfsCuts_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes ); +static float Map_MappingArea_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_NodeVec_t * vNodes ); +static int Map_MappingCompareOutputDelay( Map_Node_t ** ppNode1, Map_Node_t ** ppNode2 ); +static void Map_MappingFindLatest( Map_Man_t * p, int * pNodes, int nNodesMax ); +static unsigned Map_MappingExpandTruth_rec( unsigned uTruth, int nVars ); +static void Map_MappingGetChoiceLevels( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2, int * pMin, int * pMax ); +static float Map_MappingGetChoiceVolumes( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 ); +static int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices ); +static Map_Man_t * s_pMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_NodeVec_t * Map_MappingDfs( Map_Man_t * pMan, int fCollectEquiv ) +{ + Map_NodeVec_t * vNodes; + int i; + // perform the traversal + vNodes = Map_NodeVecAlloc( 100 ); + for ( i = 0; i < pMan->nOutputs; i++ ) + Map_MappingDfs_rec( Map_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv ); + for ( i = 0; i < vNodes->nSize; i++ ) + vNodes->pArray[i]->fMark0 = 0; +// for ( i = 0; i < pMan->nOutputs; i++ ) +// Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_NodeVec_t * Map_MappingDfsNodes( Map_Man_t * pMan, Map_Node_t ** ppCuts, int nNodes, int fEquiv ) +{ + Map_NodeVec_t * vNodes; + int i; + // perform the traversal + vNodes = Map_NodeVecAlloc( 200 ); + for ( i = 0; i < nNodes; i++ ) + Map_MappingDfs_rec( ppCuts[i], vNodes, fEquiv ); + for ( i = 0; i < vNodes->nSize; i++ ) + vNodes->pArray[i]->fMark0 = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingDfs_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fCollectEquiv ) +{ + assert( !Map_IsComplement(pNode) ); + if ( pNode->fMark0 ) + return; + // visit the transitive fanin + if ( Map_NodeIsAnd(pNode) ) + { + Map_MappingDfs_rec( Map_Regular(pNode->p1), vNodes, fCollectEquiv ); + Map_MappingDfs_rec( Map_Regular(pNode->p2), vNodes, fCollectEquiv ); + } + // visit the equivalent nodes + if ( fCollectEquiv && pNode->pNextE ) + Map_MappingDfs_rec( pNode->pNextE, vNodes, fCollectEquiv ); + // make sure the node is not visited through the equivalent nodes + assert( pNode->fMark0 == 0 ); + // mark the node as visited + pNode->fMark0 = 1; + // add the node to the list + Map_NodeVecPush( vNodes, pNode ); +} + + + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingDfsMarked1_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fFirst ) +{ + assert( !Map_IsComplement(pNode) ); + if ( pNode->fMark0 ) + return; + // visit the transitive fanin + if ( Map_NodeIsAnd(pNode) ) + { + Map_MappingDfsMarked1_rec( Map_Regular(pNode->p1), vNodes, 0 ); + Map_MappingDfsMarked1_rec( Map_Regular(pNode->p2), vNodes, 0 ); + } + // visit the equivalent nodes + if ( !fFirst && pNode->pNextE ) + Map_MappingDfsMarked1_rec( pNode->pNextE, vNodes, 0 ); + // make sure the node is not visited through the equivalent nodes + assert( pNode->fMark0 == 0 ); + // mark the node as visited + pNode->fMark0 = 1; + // add the node to the list + Map_NodeVecPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingDfsMarked2_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, Map_NodeVec_t * vBoundary, int fFirst ) +{ + assert( !Map_IsComplement(pNode) ); + if ( pNode->fMark1 ) + return; + if ( pNode->fMark0 || Map_NodeIsVar(pNode) ) + { + pNode->fMark1 = 1; + Map_NodeVecPush(vBoundary, pNode); + return; + } + // visit the transitive fanin + if ( Map_NodeIsAnd(pNode) ) + { + Map_MappingDfsMarked2_rec( Map_Regular(pNode->p1), vNodes, vBoundary, 0 ); + Map_MappingDfsMarked2_rec( Map_Regular(pNode->p2), vNodes, vBoundary, 0 ); + } + // visit the equivalent nodes + if ( !fFirst && pNode->pNextE ) + Map_MappingDfsMarked2_rec( pNode->pNextE, vNodes, vBoundary, 0 ); + // make sure the node is not visited through the equivalent nodes + assert( pNode->fMark1 == 0 ); + // mark the node as visited + pNode->fMark1 = 1; + // add the node to the list + Map_NodeVecPush( vNodes, pNode ); +} + + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingDfsMarked3_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes ) +{ + assert( !Map_IsComplement(pNode) ); + if ( pNode->fMark0 ) + return; + // visit the transitive fanin + if ( Map_NodeIsAnd(pNode) ) + { + Map_MappingDfsMarked3_rec( Map_Regular(pNode->p1), vNodes ); + Map_MappingDfsMarked3_rec( Map_Regular(pNode->p2), vNodes ); + } + // make sure the node is not visited through the equivalent nodes + assert( pNode->fMark0 == 0 ); + // mark the node as visited + pNode->fMark0 = 1; + // add the node to the list + Map_NodeVecPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingDfsMarked4_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes ) +{ + assert( !Map_IsComplement(pNode) ); + if ( pNode->fMark1 ) + return; + // visit the transitive fanin + if ( Map_NodeIsAnd(pNode) ) + { + Map_MappingDfsMarked4_rec( Map_Regular(pNode->p1), vNodes ); + Map_MappingDfsMarked4_rec( Map_Regular(pNode->p2), vNodes ); + } + // make sure the node is not visited through the equivalent nodes + assert( pNode->fMark1 == 0 ); + // mark the node as visited + pNode->fMark1 = 1; + // add the node to the list + Map_NodeVecPush( vNodes, pNode ); +} + + + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [Note that this procedure will reassign the levels assigned + originally by NodeCreate() because it counts the number of levels with + choices differently!] + + SeeAlso [] + +***********************************************************************/ +int Map_MappingCountLevels( Map_Man_t * pMan ) +{ + int i, LevelsMax, LevelsCur; + // perform the traversal + LevelsMax = -1; + for ( i = 0; i < pMan->nOutputs; i++ ) + { + LevelsCur = Map_MappingCountLevels_rec( Map_Regular(pMan->pOutputs[i]) ); + if ( LevelsMax < LevelsCur ) + LevelsMax = LevelsCur; + } + for ( i = 0; i < pMan->nOutputs; i++ ) + Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) ); + return LevelsMax; +} + +/**Function************************************************************* + + Synopsis [Recursively computes the number of logic levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MappingCountLevels_rec( Map_Node_t * pNode ) +{ + int Level1, Level2; + assert( !Map_IsComplement(pNode) ); + if ( !Map_NodeIsAnd(pNode) ) + { + pNode->Level = 0; + return 0; + } + if ( pNode->fMark0 ) + return pNode->Level; + pNode->fMark0 = 1; + // visit the transitive fanin + Level1 = Map_MappingCountLevels_rec( Map_Regular(pNode->p1) ); + Level2 = Map_MappingCountLevels_rec( Map_Regular(pNode->p2) ); + // set the number of levels + pNode->Level = 1 + ((Level1>Level2)? Level1: Level2); + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Unmarks the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingUnmark( Map_Man_t * pMan ) +{ + int i; + for ( i = 0; i < pMan->nOutputs; i++ ) + Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) ); +} + +/**Function************************************************************* + + Synopsis [Recursively unmarks the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingUnmark_rec( Map_Node_t * pNode ) +{ + assert( !Map_IsComplement(pNode) ); + if ( pNode->fMark0 == 0 ) + return; + pNode->fMark0 = 0; + if ( !Map_NodeIsAnd(pNode) ) + return; + Map_MappingUnmark_rec( Map_Regular(pNode->p1) ); + Map_MappingUnmark_rec( Map_Regular(pNode->p2) ); + // visit the equivalent nodes + if ( pNode->pNextE ) + Map_MappingUnmark_rec( pNode->pNextE ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingMark_rec( Map_Node_t * pNode ) +{ + assert( !Map_IsComplement(pNode) ); + if ( pNode->fMark0 == 1 ) + return; + pNode->fMark0 = 1; + if ( !Map_NodeIsAnd(pNode) ) + return; + // visit the transitive fanin of the selected cut + Map_MappingMark_rec( Map_Regular(pNode->p1) ); + Map_MappingMark_rec( Map_Regular(pNode->p2) ); +} + +/**Function************************************************************* + + Synopsis [Compares the outputs by their arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MappingCompareOutputDelay( Map_Node_t ** ppNode1, Map_Node_t ** ppNode2 ) +{ + Map_Node_t * pNode1 = Map_Regular(*ppNode1); + Map_Node_t * pNode2 = Map_Regular(*ppNode2); + int fPhase1 = !Map_IsComplement(*ppNode1); + int fPhase2 = !Map_IsComplement(*ppNode2); + float Arrival1 = pNode1->tArrival[fPhase1].Worst; + float Arrival2 = pNode2->tArrival[fPhase2].Worst; + if ( Arrival1 < Arrival2 ) + return -1; + if ( Arrival1 > Arrival2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Finds given number of latest arriving COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingFindLatest( Map_Man_t * p, int * pNodes, int nNodesMax ) +{ + int nNodes, i, k, v; + assert( p->nOutputs >= nNodesMax ); + pNodes[0] = 0; + nNodes = 1; + for ( i = 1; i < p->nOutputs; i++ ) + { + for ( k = nNodes - 1; k >= 0; k-- ) + if ( Map_MappingCompareOutputDelay( &p->pOutputs[pNodes[k]], &p->pOutputs[i] ) >= 0 ) + break; + if ( k == nNodesMax - 1 ) + continue; + if ( nNodes < nNodesMax ) + nNodes++; + for ( v = nNodes - 1; v > k+1; v-- ) + pNodes[v] = pNodes[v-1]; + pNodes[k+1] = i; + } +} + +/**Function************************************************************* + + Synopsis [Prints a bunch of latest arriving outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingPrintOutputArrivals( Map_Man_t * p ) +{ + int pSorted[MAP_CO_LIST_SIZE]; + Map_Time_t * pTimes; + Map_Node_t * pNode; + int fPhase, Limit, i; + int MaxNameSize; + + // determine the number of nodes to print + Limit = (p->nOutputs > MAP_CO_LIST_SIZE)? MAP_CO_LIST_SIZE : p->nOutputs; + + // determine the order + Map_MappingFindLatest( p, pSorted, Limit ); + + // determine max size of the node's name + MaxNameSize = 0; + for ( i = 0; i < Limit; i++ ) + if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) ) + MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]); + + // print the latest outputs + for ( i = 0; i < Limit; i++ ) + { + // get the i-th latest output + pNode = Map_Regular(p->pOutputs[pSorted[i]]); + fPhase =!Map_IsComplement(p->pOutputs[pSorted[i]]); + pTimes = pNode->tArrival + fPhase; + // print out the best arrival time + printf( "Output %-*s : ", MaxNameSize + 3, p->ppOutputNames[pSorted[i]] ); + printf( "Delay = (%5.2f, %5.2f) ", (double)pTimes->Rise, (double)pTimes->Fall ); + printf( "%s", fPhase? "POS" : "NEG" ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Sets up the truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingSetupTruthTables( unsigned uTruths[][2] ) +{ + int m, v; + // set up the truth tables + for ( m = 0; m < 32; m++ ) + for ( v = 0; v < 5; v++ ) + if ( m & (1 << v) ) + uTruths[v][0] |= (1 << m); + // make adjustments for the case of 6 variables + for ( v = 0; v < 5; v++ ) + uTruths[v][1] = uTruths[v][0]; + uTruths[5][0] = 0; + uTruths[5][1] = MAP_FULL; +} + +/**Function************************************************************* + + Synopsis [Sets up the truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingSetupTruthTablesLarge( unsigned uTruths[][32] ) +{ + int m, v; + // clean everything + for ( m = 0; m < 32; m++ ) + for ( v = 0; v < 10; v++ ) + uTruths[v][m] = 0; + // set up the truth tables + for ( m = 0; m < 32; m++ ) + for ( v = 0; v < 5; v++ ) + if ( m & (1 << v) ) + { + uTruths[v][0] |= (1 << m); + uTruths[v+5][m] = MAP_FULL; + } + // extend this info for the rest of the first 5 variables + for ( m = 0; m < 32; m++ ) + for ( v = 0; v < 5; v++ ) + uTruths[v][m] = uTruths[v][0]; +/* + // verify + for ( m = 0; m < 1024; m++, printf("\n") ) + for ( v = 0; v < 10; v++ ) + if ( Map_InfoReadVar( uTruths[v], m ) ) + printf( "1" ); + else + printf( "0" ); +*/ +} + +/**Function************************************************************* + + Synopsis [Sets up the mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingSetupMask( unsigned uMask[], int nVarsMax ) +{ + if ( nVarsMax == 6 ) + uMask[0] = uMask[1] = MAP_FULL; + else + { + uMask[0] = MAP_MASK(1 << nVarsMax); + uMask[1] = 0; + } +} + +/**Function************************************************************* + + Synopsis [Verify one useful property.] + + Description [This procedure verifies one useful property. After + the FRAIG construction with choice nodes is over, each primary node + should have fanins that are primary nodes. The primary nodes is the + one that does not have pNode->pRepr set to point to another node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_ManCheckConsistency( Map_Man_t * p ) +{ + Map_Node_t * pNode; + Map_NodeVec_t * pVec; + int i; + pVec = Map_MappingDfs( p, 0 ); + for ( i = 0; i < pVec->nSize; i++ ) + { + pNode = pVec->pArray[i]; + if ( Map_NodeIsVar(pNode) ) + { + if ( pNode->pRepr ) + printf( "Primary input %d is a secondary node.\n", pNode->Num ); + } + else if ( Map_NodeIsConst(pNode) ) + { + if ( pNode->pRepr ) + printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); + } + else + { + if ( pNode->pRepr ) + printf( "Internal node %d is a secondary node.\n", pNode->Num ); + if ( Map_Regular(pNode->p1)->pRepr ) + printf( "Internal node %d has first fanin that is a secondary node.\n", pNode->Num ); + if ( Map_Regular(pNode->p2)->pRepr ) + printf( "Internal node %d has second fanin that is a secondary node.\n", pNode->Num ); + } + } + Map_NodeVecFree( pVec ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if current mapping of the node violates fanout limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MappingNodeIsViolator( Map_Node_t * pNode, Map_Cut_t * pCut, int fPosPol ) +{ + return pNode->nRefAct[fPosPol] > (int)pCut->M[fPosPol].pSuperBest->nFanLimit; +} + +/**Function************************************************************* + + Synopsis [Computes the total are flow of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Map_MappingGetAreaFlow( Map_Man_t * p ) +{ + Map_Node_t * pNode; + Map_Cut_t * pCut; + float aFlowFlowTotal = 0; + int fPosPol, i; + for ( i = 0; i < p->nOutputs; i++ ) + { + pNode = Map_Regular(p->pOutputs[i]); + if ( !Map_NodeIsAnd(pNode) ) + continue; + fPosPol = !Map_IsComplement(p->pOutputs[i]); + pCut = pNode->pCutBest[fPosPol]; + if ( pCut == NULL ) + { + fPosPol = !fPosPol; + pCut = pNode->pCutBest[fPosPol]; + } + aFlowFlowTotal += pNode->pCutBest[fPosPol]->M[fPosPol].AreaFlow; + } + return aFlowFlowTotal; +} + + +/**Function************************************************************* + + Synopsis [Compares the supergates by their level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_CompareNodesByLevel( Map_Node_t ** ppS1, Map_Node_t ** ppS2 ) +{ + Map_Node_t * pN1 = Map_Regular(*ppS1); + Map_Node_t * pN2 = Map_Regular(*ppS2); + if ( pN1->Level > pN2->Level ) + return -1; + if ( pN1->Level < pN2->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Orders the nodes in the decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingSortByLevel( Map_Man_t * pMan, Map_NodeVec_t * vNodes ) +{ + qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Map_Node_t *), + (int (*)(const void *, const void *)) Map_CompareNodesByLevel ); +// assert( Map_CompareNodesByLevel( vNodes->pArray, vNodes->pArray + vNodes->nSize - 1 ) <= 0 ); +} + + +/**Function************************************************************* + + Synopsis [Compares the supergates by their pointer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_CompareNodesByPointer( Map_Node_t ** ppS1, Map_Node_t ** ppS2 ) +{ + if ( *ppS1 < *ppS2 ) + return -1; + if ( *ppS1 > *ppS2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Counts how many AIG nodes are mapped in both polarities.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MappingCountDoubles( Map_Man_t * pMan, Map_NodeVec_t * vNodes ) +{ + Map_Node_t * pNode; + int Counter, i; + // count the number of equal adjacent nodes + Counter = 0; + for ( i = 0; i < vNodes->nSize; i++ ) + { + pNode = vNodes->pArray[i]; + if ( !Map_NodeIsAnd(pNode) ) + continue; + if ( (pNode->nRefAct[0] && pNode->pCutBest[0]) && + (pNode->nRefAct[1] && pNode->pCutBest[1]) ) + Counter++; + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +st_table * Map_CreateTableGate2Super( Map_Man_t * pMan ) +{ + Map_Super_t * pSuper; + st_table * tTable; + int i, nInputs, v; + tTable = st_init_table(strcmp, st_strhash); + for ( i = 0; i < pMan->pSuperLib->nSupersAll; i++ ) + { + pSuper = pMan->pSuperLib->ppSupers[i]; + if ( pSuper->nGates == 1 ) + { + // skip different versions of the same root gate + nInputs = Mio_GateReadInputs(pSuper->pRoot); + for ( v = 0; v < nInputs; v++ ) + if ( pSuper->pFanins[v]->Num != nInputs - 1 - v ) + break; + if ( v != nInputs ) + continue; +// printf( "%s\n", Mio_GateReadName(pSuper->pRoot) ); + if ( st_insert( tTable, (char *)pSuper->pRoot, (char *)pSuper ) ) + { + assert( 0 ); + } + } + } + return tTable; +} + +/**Function************************************************************* + + Synopsis [Get the FRAIG node with phase.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_ManCleanData( Map_Man_t * p ) +{ + int i; + for ( i = 0; i < p->vNodesAll->nSize; i++ ) + p->vNodesAll->pArray[i]->pData0 = p->vNodesAll->pArray[i]->pData1 = 0; +} + +/**Function************************************************************* + + Synopsis [Expand the truth table] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingExpandTruth( unsigned uTruth[2], int nVars ) +{ + assert( nVars < 7 ); + if ( nVars == 6 ) + return; + if ( nVars < 5 ) + { + uTruth[0] &= MAP_MASK( (1<vAnds->nSize; i++ ) + { + // skip primary inputs + pNode = p->vAnds->pArray[i]; + if ( !Map_NodeIsAnd( pNode ) ) + continue; + // skip a secondary node + if ( pNode->pRepr ) + continue; + // count the switching nodes + if ( pNode->nRefAct[0] > 0 ) + Map_TimeCutComputeArrival( pNode, pNode->pCutBest[0], 0, MAP_FLOAT_LARGE ); + if ( pNode->nRefAct[1] > 0 ) + Map_TimeCutComputeArrival( pNode, pNode->pCutBest[1], 1, MAP_FLOAT_LARGE ); + } + Result = Map_TimeComputeArrivalMax(p); + printf( "Max arrival times with fanouts = %10.2f.\n", Result ); + return Result; +} + + +/**Function************************************************************* + + Synopsis [Sets up the mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MappingGetMaxLevel( Map_Man_t * pMan ) +{ + int nLevelMax, i; + nLevelMax = 0; + for ( i = 0; i < pMan->nOutputs; i++ ) + nLevelMax = ((unsigned)nLevelMax) > Map_Regular(pMan->pOutputs[i])->Level? + nLevelMax : Map_Regular(pMan->pOutputs[i])->Level; + return nLevelMax; +} + +/**Function************************************************************* + + Synopsis [Analyses choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MappingUpdateLevel_rec( Map_Man_t * pMan, Map_Node_t * pNode, int fMaximum ) +{ + Map_Node_t * pTemp; + int Level1, Level2, LevelE; + assert( !Map_IsComplement(pNode) ); + if ( !Map_NodeIsAnd(pNode) ) + return pNode->Level; + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return pNode->Level; + pNode->TravId = pMan->nTravIds; + // compute levels of the children nodes + Level1 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p1), fMaximum ); + Level2 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p2), fMaximum ); + pNode->Level = 1 + MAP_MAX( Level1, Level2 ); + if ( pNode->pNextE ) + { + LevelE = Map_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); + if ( fMaximum ) + { + if ( pNode->Level < (unsigned)LevelE ) + pNode->Level = LevelE; + } + else + { + if ( pNode->Level > (unsigned)LevelE ) + pNode->Level = LevelE; + } + // set the level of all equivalent nodes to be the same minimum + if ( pNode->pRepr == NULL ) // the primary node + for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) + pTemp->Level = pNode->Level; + } + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Resets the levels of the nodes in the choice graph.] + + Description [Makes the level of the choice nodes to be equal to the + maximum of the level of the nodes in the equivalence class. This way + sorting by level leads to the reverse topological order, which is + needed for the required time computation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingSetChoiceLevels( Map_Man_t * pMan ) +{ + int i; + pMan->nTravIds++; + for ( i = 0; i < pMan->nOutputs; i++ ) + Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 1 ); +} + +/**Function************************************************************* + + Synopsis [Reports statistics on choice nodes.] + + Description [The number of choice nodes is the number of primary nodes, + which has pNextE set to a pointer. The number of choices is the number + of entries in the equivalent-node lists of the primary nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingReportChoices( Map_Man_t * pMan ) +{ + Map_Node_t * pNode, * pTemp; + int nChoiceNodes, nChoices; + int i, LevelMax1, LevelMax2; + + // report the number of levels + LevelMax1 = Map_MappingGetMaxLevel( pMan ); + pMan->nTravIds++; + for ( i = 0; i < pMan->nOutputs; i++ ) + Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 0 ); + LevelMax2 = Map_MappingGetMaxLevel( pMan ); + + // report statistics about choices + nChoiceNodes = nChoices = 0; + for ( i = 0; i < pMan->vAnds->nSize; i++ ) + { + pNode = pMan->vAnds->pArray[i]; + if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) + { // this is a choice node = the primary node that has equivalent nodes + nChoiceNodes++; + for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) + nChoices++; + } + } + printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); + printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); +} + +/**Function************************************************************* + + Synopsis [Computes the maximum and minimum levels of the choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_MappingGetChoiceLevels( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2, int * pMin, int * pMax ) +{ + Map_NodeVec_t * vNodes; + Map_NodeVec_t * vBoundary; + Map_Node_t * pNode; + int i, Min, Max; + + vNodes = Map_NodeVecAlloc( 100 ); + vBoundary = Map_NodeVecAlloc( 100 ); + Map_MappingDfsMarked1_rec( p1, vNodes, 1 ); + Map_MappingDfsMarked2_rec( p2, vNodes, vBoundary, 1 ); + // clean the marks + Min = 100000; + Max = -100000; + for ( i = 0; i < vBoundary->nSize; i++ ) + { + pNode = vBoundary->pArray[i]; + if ( Min > (int)pNode->Level ) + Min = pNode->Level; + if ( Max < (int)pNode->Level ) + Max = pNode->Level; + } + Map_NodeVecFree( vBoundary ); + for ( i = 0; i < vNodes->nSize; i++ ) + { + pNode = vNodes->pArray[i]; + pNode->fMark0 = pNode->fMark1 = 0; + } + Map_NodeVecFree( vNodes ); + *pMin = Min; + *pMax = Max; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Map_MappingGetChoiceVolumes( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 ) +{ + Map_NodeVec_t * vNodes; + Map_Node_t * pNode; + int i, nVolumeTotal, nVolumeUnique; + + vNodes = Map_NodeVecAlloc( 100 ); + Map_MappingDfsMarked3_rec( p1, vNodes ); + Map_MappingDfsMarked4_rec( p2, vNodes ); + // clean the marks + nVolumeTotal = nVolumeUnique = 0; + for ( i = 0; i < vNodes->nSize; i++ ) + { + pNode = vNodes->pArray[i]; + if ( !Map_NodeIsAnd(pNode) ) + continue; + nVolumeTotal++; + if ( pNode->fMark0 ^ pNode->fMark1 ) + nVolumeUnique++; + pNode->fMark0 = pNode->fMark1 = 0; + } + Map_NodeVecFree( vNodes ); +// return ((float)nVolumeUnique)/nVolumeTotal; + return (float)nVolumeUnique; +} + + +/**Function************************************************************* + + Synopsis [Computes the maximum and minimum levels of the choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices ) +{ + Map_NodeVec_t * vNodes; + int Result; + vNodes = Map_MappingDfs( pMan, fChoices ); + Result = vNodes->nSize; + Map_NodeVecFree( vNodes ); + return Result; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mapper/mapperVec.c b/abc70930/src/map/mapper/mapperVec.c new file mode 100644 index 00000000..f75138fb --- /dev/null +++ b/abc70930/src/map/mapper/mapperVec.c @@ -0,0 +1,318 @@ +/**CFile**************************************************************** + + FileName [mapperVec.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Generic technology mapping engine.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - June 1, 2004.] + + Revision [$Id: mapperVec.c,v 1.3 2005/01/23 06:59:45 alanmi Exp $] + +***********************************************************************/ + +#include "mapperInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_NodeVec_t * Map_NodeVecAlloc( int nCap ) +{ + Map_NodeVec_t * p; + p = ALLOC( Map_NodeVec_t, 1 ); + if ( nCap > 0 && nCap < 16 ) + nCap = 16; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? ALLOC( Map_Node_t *, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeVecFree( Map_NodeVec_t * p ) +{ + FREE( p->pArray ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Node_t ** Map_NodeVecReadArray( Map_NodeVec_t * p ) +{ + return p->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_NodeVecReadSize( Map_NodeVec_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeVecGrow( Map_NodeVec_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = REALLOC( Map_Node_t *, p->pArray, nCapMin ); + p->nCap = nCapMin; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeVecShrink( Map_NodeVec_t * p, int nSizeNew ) +{ + assert( p->nSize >= nSizeNew ); + p->nSize = nSizeNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeVecClear( Map_NodeVec_t * p ) +{ + p->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeVecPush( Map_NodeVec_t * p, Map_Node_t * Entry ) +{ + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Map_NodeVecGrow( p, 16 ); + else + Map_NodeVecGrow( p, 2 * p->nCap ); + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [Add the element while ensuring uniqueness.] + + Description [Returns 1 if the element was found, and 0 if it was new. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_NodeVecPushUnique( Map_NodeVec_t * p, Map_Node_t * Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return 1; + Map_NodeVecPush( p, Entry ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Node_t * Map_NodeVecPop( Map_NodeVec_t * p ) +{ + return p->pArray[--p->nSize]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeVecRemove( Map_NodeVec_t * p, Map_Node_t * Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + break; + assert( i < p->nSize ); + for ( i++; i < p->nSize; i++ ) + p->pArray[i-1] = p->pArray[i]; + p->nSize--; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_Node_t * Entry ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Map_Node_t * Map_NodeVecReadEntry( Map_NodeVec_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Map_NodeVecSortByLevel( Map_NodeVec_t * p ) +{ + qsort( (void *)p->pArray, p->nSize, sizeof(Map_Node_t *), + (int (*)(const void *, const void *)) Map_NodeVecCompareLevels ); +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 ) +{ + int Level1 = Map_Regular(*pp1)->Level; + int Level2 = Map_Regular(*pp2)->Level; + if ( Level1 < Level2 ) + return -1; + if ( Level1 > Level2 ) + return 1; + if ( Map_Regular(*pp1)->Num < Map_Regular(*pp2)->Num ) + return -1; + if ( Map_Regular(*pp1)->Num > Map_Regular(*pp2)->Num ) + return 1; + return 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/map/mapper/module.make b/abc70930/src/map/mapper/module.make new file mode 100644 index 00000000..bd6447d8 --- /dev/null +++ b/abc70930/src/map/mapper/module.make @@ -0,0 +1,18 @@ +SRC += src/map/mapper/mapper.c \ + src/map/mapper/mapperCanon.c \ + src/map/mapper/mapperCore.c \ + src/map/mapper/mapperCreate.c \ + src/map/mapper/mapperCut.c \ + src/map/mapper/mapperCutUtils.c \ + src/map/mapper/mapperFanout.c \ + src/map/mapper/mapperLib.c \ + src/map/mapper/mapperMatch.c \ + src/map/mapper/mapperRefs.c \ + src/map/mapper/mapperSuper.c \ + src/map/mapper/mapperSwitch.c \ + src/map/mapper/mapperTable.c \ + src/map/mapper/mapperTime.c \ + src/map/mapper/mapperTree.c \ + src/map/mapper/mapperTruth.c \ + src/map/mapper/mapperUtils.c \ + src/map/mapper/mapperVec.c diff --git a/abc70930/src/map/mio/mio.c b/abc70930/src/map/mio/mio.c new file mode 100644 index 00000000..10a5af9d --- /dev/null +++ b/abc70930/src/map/mio/mio.c @@ -0,0 +1,269 @@ +/**CFile**************************************************************** + + FileName [mio.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [File reading/writing for technology mapping.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 18, 2003.] + + Revision [$Id: mio.c,v 1.4 2004/08/05 18:34:51 satrajit Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "mvc.h" +#include "mainInt.h" +#include "mioInt.h" +#include "mapper.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); +static int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); + +// internal version of GENLIB library +static char * pMcncGenlib[25] = { + "GATE inv1 1 O=!a; PIN * INV 1 999 0.9 0.0 0.9 0.0\n", + "GATE inv2 2 O=!a; PIN * INV 2 999 1.0 0.0 1.0 0.0\n", + "GATE inv3 3 O=!a; PIN * INV 3 999 1.1 0.0 1.1 0.0\n", + "GATE inv4 4 O=!a; PIN * INV 4 999 1.2 0.0 1.2 0.0\n", + "GATE nand2 2 O=!(a*b); PIN * INV 1 999 1.0 0.0 1.0 0.0\n", + "GATE nand3 3 O=!(a*b*c); PIN * INV 1 999 1.1 0.0 1.1 0.0\n", + "GATE nand4 4 O=!(a*b*c*d); PIN * INV 1 999 1.4 0.0 1.4 0.0\n", + "GATE nor2 2 O=!(a+b); PIN * INV 1 999 1.4 0.0 1.4 0.0\n", + "GATE nor3 3 O=!(a+b+c); PIN * INV 1 999 2.4 0.0 2.4 0.0\n", + "GATE nor4 4 O=!(a+b+c+d); PIN * INV 1 999 3.8 0.0 3.8 0.0\n", + "GATE xora 5 O=a*!b+!a*b; PIN * UNKNOWN 2 999 1.9 0.0 1.9 0.0\n", + "GATE xorb 5 O=!(a*b+!a*!b); PIN * UNKNOWN 2 999 1.9 0.0 1.9 0.0\n", + "GATE xnora 5 O=a*b+!a*!b; PIN * UNKNOWN 2 999 2.1 0.0 2.1 0.0\n", + "GATE xnorb 5 O=!(!a*b+a*!b); PIN * UNKNOWN 2 999 2.1 0.0 2.1 0.0\n", + "GATE aoi21 3 O=!(a*b+c); PIN * INV 1 999 1.6 0.0 1.6 0.0\n", + "GATE aoi22 4 O=!(a*b+c*d); PIN * INV 1 999 2.0 0.0 2.0 0.0\n", + "GATE oai21 3 O=!((a+b)*c); PIN * INV 1 999 1.6 0.0 1.6 0.0\n", + "GATE oai22 4 O=!((a+b)*(c+d)); PIN * INV 1 999 2.0 0.0 2.0 0.0\n", + "GATE buf 1 O=a; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", + "GATE zero 0 O=CONST0;\n", + "GATE one 0 O=CONST1;\n" +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_Init( Abc_Frame_t * pAbc ) +{ + char * pFileTemp = "mcnc_temp.genlib"; + Mio_Library_t * pLibGen; + FILE * pFile; + int i; + + // write genlib into file + pFile = fopen( pFileTemp, "w" ); + for ( i = 0; pMcncGenlib[i]; i++ ) + fputs( pMcncGenlib[i], pFile ); + fclose( pFile ); + // read genlib from file + pLibGen = Mio_LibraryRead( pAbc, pFileTemp, NULL, 0 ); + Abc_FrameSetLibGen( pLibGen ); +#ifdef WIN32 + _unlink( pFileTemp ); +#else + unlink( pFileTemp ); +#endif + + Cmd_CommandAdd( pAbc, "SC mapping", "read_library", Mio_CommandReadLibrary, 0 ); + Cmd_CommandAdd( pAbc, "SC mapping", "print_library", Mio_CommandPrintLibrary, 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_End() +{ +// Mio_LibraryDelete( s_pLib ); + Mio_LibraryDelete( Abc_FrameReadLibGen() ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Mio_Library_t * pLib; + Abc_Ntk_t * pNet; + char * FileName; + int fVerbose; + int c; + + pNet = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) + { + switch (c) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) + { + fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) ) + fprintf( pErr, "Did you mean \"%s\"?", FileName ); + fprintf( pErr, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pLib = Mio_LibraryRead( pAbc, FileName, 0, fVerbose ); + if ( pLib == NULL ) + { + fprintf( pErr, "Reading GENLIB library has failed.\n" ); + return 1; + } + // free the current superlib because it depends on the old Mio library + if ( Abc_FrameReadLibSuper() ) + { + extern void Map_SuperLibFree( Map_SuperLib_t * p ); +// Map_SuperLibFree( s_pSuperLib ); +// s_pSuperLib = NULL; + Map_SuperLibFree( Abc_FrameReadLibSuper() ); + Abc_FrameSetLibSuper( NULL ); + } + + // replace the current library +// Mio_LibraryDelete( s_pLib ); +// s_pLib = pLib; + Mio_LibraryDelete( Abc_FrameReadLibGen() ); + Abc_FrameSetLibGen( pLib ); + return 0; + +usage: + fprintf( pErr, "usage: read_library [-vh]\n"); + fprintf( pErr, "\t read the library from a genlib file\n" ); + fprintf( pErr, "\t-h : enable verbose output\n"); + return 1; /* error exit */ +} + + +/**Function************************************************************* + + Synopsis [Command procedure to read LUT libraries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pOut, * pErr; + Abc_Ntk_t * pNet; + int fVerbose; + int c; + + pNet = Abc_FrameReadNtk(pAbc); + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) + { + switch (c) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + + if ( argc != globalUtilOptind ) + { + goto usage; + } + + // set the new network + Mio_WriteLibrary( stdout, Abc_FrameReadLibGen(), 0 ); + return 0; + +usage: + fprintf( pErr, "\nusage: print_library [-vh]\n"); + fprintf( pErr, "\t print the current genlib library\n" ); + fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); + fprintf( pErr, "\t-h : print the command usage\n"); + return 1; /* error exit */ +} +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mio/mio.h b/abc70930/src/map/mio/mio.h new file mode 100644 index 00000000..dbe2420b --- /dev/null +++ b/abc70930/src/map/mio/mio.h @@ -0,0 +1,150 @@ +/**CFile**************************************************************** + + FileName [mio.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [File reading/writing for technology mapping.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: mio.h,v 1.6 2004/08/09 22:16:31 satrajit Exp $] + +***********************************************************************/ + +#ifndef __MIO_H__ +#define __MIO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef enum { MIO_PHASE_UNKNOWN, MIO_PHASE_INV, MIO_PHASE_NONINV } Mio_PinPhase_t; + +typedef struct Mio_LibraryStruct_t_ Mio_Library_t; +typedef struct Mio_GateStruct_t_ Mio_Gate_t; +typedef struct Mio_PinStruct_t_ Mio_Pin_t; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Mio_LibraryForEachGate( Lib, Gate ) \ + for ( Gate = Mio_LibraryReadGates(Lib); \ + Gate; \ + Gate = Mio_GateReadNext(Gate) ) +#define Mio_LibraryForEachGateSafe( Lib, Gate, Gate2 ) \ + for ( Gate = Mio_LibraryReadGates(Lib), \ + Gate2 = (Gate? Mio_GateReadNext(Gate): NULL); \ + Gate; \ + Gate = Gate2, \ + Gate2 = (Gate? Mio_GateReadNext(Gate): NULL) ) + +#define Mio_GateForEachPin( Gate, Pin ) \ + for ( Pin = Mio_GateReadPins(Gate); \ + Pin; \ + Pin = Mio_PinReadNext(Pin) ) +#define Mio_GateForEachPinSafe( Gate, Pin, Pin2 ) \ + for ( Pin = Mio_GateReadPins(Gate), \ + Pin2 = (Pin? Mio_PinReadNext(Pin): NULL); \ + Pin; \ + Pin = Pin2, \ + Pin2 = (Pin? Mio_PinReadNext(Pin): NULL) ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== mioApi.c =============================================================*/ +extern char * Mio_LibraryReadName ( Mio_Library_t * pLib ); +extern int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ); +extern Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ); +extern DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib ); +extern Mio_Gate_t * Mio_LibraryReadGateByName ( Mio_Library_t * pLib, char * pName ); +extern char * Mio_LibraryReadSopByName ( Mio_Library_t * pLib, char * pName ); +extern Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib ); +extern Mio_Gate_t * Mio_LibraryReadConst1 ( Mio_Library_t * pLib ); +extern Mio_Gate_t * Mio_LibraryReadNand2 ( Mio_Library_t * pLib ); +extern Mio_Gate_t * Mio_LibraryReadAnd2 ( Mio_Library_t * pLib ); +extern Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib ); +extern Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib ); +extern float Mio_LibraryReadDelayInvRise( Mio_Library_t * pLib ); +extern float Mio_LibraryReadDelayInvFall( Mio_Library_t * pLib ); +extern float Mio_LibraryReadDelayInvMax( Mio_Library_t * pLib ); +extern float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib ); +extern float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib ); +extern float Mio_LibraryReadDelayNand2Max( Mio_Library_t * pLib ); +extern float Mio_LibraryReadDelayAnd2Max( Mio_Library_t * pLib ); +extern float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib ); +extern float Mio_LibraryReadAreaBuf ( Mio_Library_t * pLib ); +extern float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib ); +extern int Mio_LibraryReadGateNameMax( Mio_Library_t * pLib ); +extern char * Mio_GateReadName ( Mio_Gate_t * pGate ); +extern char * Mio_GateReadOutName ( Mio_Gate_t * pGate ); +extern double Mio_GateReadArea ( Mio_Gate_t * pGate ); +extern char * Mio_GateReadForm ( Mio_Gate_t * pGate ); +extern Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate ); +extern Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate ); +extern Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate ); +extern int Mio_GateReadInputs ( Mio_Gate_t * pGate ); +extern double Mio_GateReadDelayMax ( Mio_Gate_t * pGate ); +extern char * Mio_GateReadSop ( Mio_Gate_t * pGate ); +extern DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate ); +extern char * Mio_PinReadName ( Mio_Pin_t * pPin ); +extern Mio_PinPhase_t Mio_PinReadPhase ( Mio_Pin_t * pPin ); +extern double Mio_PinReadInputLoad ( Mio_Pin_t * pPin ); +extern double Mio_PinReadMaxLoad ( Mio_Pin_t * pPin ); +extern double Mio_PinReadDelayBlockRise ( Mio_Pin_t * pPin ); +extern double Mio_PinReadDelayFanoutRise( Mio_Pin_t * pPin ); +extern double Mio_PinReadDelayBlockFall ( Mio_Pin_t * pPin ); +extern double Mio_PinReadDelayFanoutFall( Mio_Pin_t * pPin ); +extern double Mio_PinReadDelayBlockMax ( Mio_Pin_t * pPin ); +extern Mio_Pin_t * Mio_PinReadNext ( Mio_Pin_t * pPin ); +/*=== mioRead.c =============================================================*/ +extern Mio_Library_t * Mio_LibraryRead( void * pAbc, char * FileName, char * ExcludeFile, int fVerbose ); +extern int Mio_LibraryReadExclude( void * pAbc, char * ExcludeFile, st_table * tExcludeGate ); +/*=== mioFunc.c =============================================================*/ +extern int Mio_LibraryParseFormulas( Mio_Library_t * pLib ); +/*=== mioUtils.c =============================================================*/ +extern void Mio_LibraryDelete( Mio_Library_t * pLib ); +extern void Mio_GateDelete( Mio_Gate_t * pGate ); +extern void Mio_PinDelete( Mio_Pin_t * pPin ); +extern Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin ); +extern void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops ); +extern Mio_Gate_t ** Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, bool fSkipInv, int * pnGates ); +extern void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] ); +extern void Mio_DeriveGateDelays( Mio_Gate_t * pGate, + float ** ptPinDelays, int nPins, int nInputs, float tDelayZero, + float * ptDelaysRes, float * ptPinDelayMax ); +extern Mio_Gate_t * Mio_GateCreatePseudo( int nInputs ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/map/mio/mioApi.c b/abc70930/src/map/mio/mioApi.c new file mode 100644 index 00000000..73473f8b --- /dev/null +++ b/abc70930/src/map/mio/mioApi.c @@ -0,0 +1,172 @@ +/**CFile**************************************************************** + + FileName [mioApi.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [File reading/writing for technology mapping.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: mioApi.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $] + +***********************************************************************/ + +#include "mioInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Mio_LibraryReadName ( Mio_Library_t * pLib ) { return pLib->pName; } +int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ) { return pLib->nGates; } +Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ) { return pLib->pGates; } +DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib ) { return pLib->dd; } +Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib ) { return pLib->pGateBuf; } +Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib ) { return pLib->pGateInv; } +Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib ) { return pLib->pGate0; } +Mio_Gate_t * Mio_LibraryReadConst1 ( Mio_Library_t * pLib ) { return pLib->pGate1; } +Mio_Gate_t * Mio_LibraryReadNand2 ( Mio_Library_t * pLib ) { return pLib->pGateNand2; } +Mio_Gate_t * Mio_LibraryReadAnd2 ( Mio_Library_t * pLib ) { return pLib->pGateAnd2; } +float Mio_LibraryReadDelayInvRise ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockRise : 0.0); } +float Mio_LibraryReadDelayInvFall ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockFall : 0.0); } +float Mio_LibraryReadDelayInvMax ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockMax : 0.0); } +float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockRise : 0.0); } +float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockFall : 0.0); } +float Mio_LibraryReadDelayNand2Max ( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockMax : 0.0); } +float Mio_LibraryReadDelayAnd2Max ( Mio_Library_t * pLib ) { return (float)(pLib->pGateAnd2? pLib->pGateAnd2->pPins->dDelayBlockMax : 0.0); } +float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->dArea : 0.0); } +float Mio_LibraryReadAreaBuf ( Mio_Library_t * pLib ) { return (float)(pLib->pGateBuf? pLib->pGateBuf->dArea : 0.0); } +float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->dArea : 0.0); } + +/**Function************************************************************* + + Synopsis [Returns the longest gate name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_LibraryReadGateNameMax( Mio_Library_t * pLib ) +{ + Mio_Gate_t * pGate; + int LenMax = 0, LenCur; + Mio_LibraryForEachGate( pLib, pGate ) + { + LenCur = strlen( Mio_GateReadName(pGate) ); + if ( LenMax < LenCur ) + LenMax = LenCur; + } + return LenMax; +} + +/**Function************************************************************* + + Synopsis [Read Mvc of the gate by name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mio_Gate_t * Mio_LibraryReadGateByName( Mio_Library_t * pLib, char * pName ) +{ + Mio_Gate_t * pGate; + if ( st_lookup( pLib->tName2Gate, pName, (char **)&pGate ) ) + return pGate; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Read Mvc of the gate by name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Mio_LibraryReadSopByName( Mio_Library_t * pLib, char * pName ) +{ + Mio_Gate_t * pGate; + if ( st_lookup( pLib->tName2Gate, pName, (char **)&pGate ) ) + return pGate->pSop; + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Mio_GateReadName ( Mio_Gate_t * pGate ) { return pGate->pName; } +char * Mio_GateReadOutName ( Mio_Gate_t * pGate ) { return pGate->pOutName; } +double Mio_GateReadArea ( Mio_Gate_t * pGate ) { return pGate->dArea; } +char * Mio_GateReadForm ( Mio_Gate_t * pGate ) { return pGate->pForm; } +Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate ) { return pGate->pPins; } +Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate ) { return pGate->pLib; } +Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate ) { return pGate->pNext; } +int Mio_GateReadInputs ( Mio_Gate_t * pGate ) { return pGate->nInputs; } +double Mio_GateReadDelayMax( Mio_Gate_t * pGate ) { return pGate->dDelayMax; } +char * Mio_GateReadSop ( Mio_Gate_t * pGate ) { return pGate->pSop; } +DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate ) { return pGate->bFunc; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Mio_PinReadName ( Mio_Pin_t * pPin ) { return pPin->pName; } +Mio_PinPhase_t Mio_PinReadPhase ( Mio_Pin_t * pPin ) { return pPin->Phase; } +double Mio_PinReadInputLoad ( Mio_Pin_t * pPin ) { return pPin->dLoadInput; } +double Mio_PinReadMaxLoad ( Mio_Pin_t * pPin ) { return pPin->dLoadMax; } +double Mio_PinReadDelayBlockRise ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockRise; } +double Mio_PinReadDelayFanoutRise( Mio_Pin_t * pPin ) { return pPin->dDelayFanoutRise;} +double Mio_PinReadDelayBlockFall ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockFall; } +double Mio_PinReadDelayFanoutFall( Mio_Pin_t * pPin ) { return pPin->dDelayFanoutFall;} +double Mio_PinReadDelayBlockMax ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockMax; } +Mio_Pin_t * Mio_PinReadNext ( Mio_Pin_t * pPin ) { return pPin->pNext; } + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mio/mioFunc.c b/abc70930/src/map/mio/mioFunc.c new file mode 100644 index 00000000..21a078f9 --- /dev/null +++ b/abc70930/src/map/mio/mioFunc.c @@ -0,0 +1,268 @@ +/**CFile**************************************************************** + + FileName [mioFunc.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [File reading/writing for technology mapping.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: mioFunc.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $] + +***********************************************************************/ + +#include "mioInt.h" +#include "parse.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// these symbols (and no other) can appear in the formulas +#define MIO_SYMB_AND '*' +#define MIO_SYMB_OR '+' +#define MIO_SYMB_NOT '!' +#define MIO_SYMB_AFTNOT '\'' +#define MIO_SYMB_OPEN '(' +#define MIO_SYMB_CLOSE ')' + +static int Mio_GateParseFormula( Mio_Gate_t * pGate ); +static int Mio_GateCollectNames( char * pFormula, char * pPinNames[] ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Deriving the functionality of the gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_LibraryParseFormulas( Mio_Library_t * pLib ) +{ + Mio_Gate_t * pGate; + + // count the gates + pLib->nGates = 0; + Mio_LibraryForEachGate( pLib, pGate ) + pLib->nGates++; + + // start a temporary BDD manager + pLib->dd = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + // introduce ZDD variables + Cudd_zddVarsFromBddVars( pLib->dd, 2 ); + + // for each gate, derive its function + Mio_LibraryForEachGate( pLib, pGate ) + if ( Mio_GateParseFormula( pGate ) ) + return 1; + return 0; +} + + +/**Function************************************************************* + + Synopsis [Deriving the functionality of the gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_GateParseFormula( Mio_Gate_t * pGate ) +{ + DdManager * dd = pGate->pLib->dd; + char * pPinNames[100]; + char * pPinNamesCopy[100]; + Mio_Pin_t * pPin, ** ppPin; + int nPins, iPin, i; + + // set the maximum delay of the gate; count pins + pGate->dDelayMax = 0.0; + nPins = 0; + Mio_GateForEachPin( pGate, pPin ) + { + // set the maximum delay of the gate + if ( pGate->dDelayMax < pPin->dDelayBlockMax ) + pGate->dDelayMax = pPin->dDelayBlockMax; + // count the pin + nPins++; + } + + // check for the gate with const function + if ( nPins == 0 ) + { + if ( strcmp( pGate->pForm, MIO_STRING_CONST0 ) == 0 ) + { + pGate->bFunc = b0; + pGate->pSop = Abc_SopRegister( pGate->pLib->pMmFlex, " 0\n" ); + pGate->pLib->pGate0 = pGate; + } + else if ( strcmp( pGate->pForm, MIO_STRING_CONST1 ) == 0 ) + { + pGate->bFunc = b1; + pGate->pSop = Abc_SopRegister( pGate->pLib->pMmFlex, " 1\n" ); + pGate->pLib->pGate1 = pGate; + } + else + { + printf( "Cannot parse formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName ); + return 1; + } + Cudd_Ref( pGate->bFunc ); + return 0; + } + + // collect the names as they appear in the formula + nPins = Mio_GateCollectNames( pGate->pForm, pPinNames ); + if ( nPins == 0 ) + { + printf( "Cannot read formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName ); + return 1; + } + + // set the number of inputs + pGate->nInputs = nPins; + + // consider the case when all the pins have identical pin info + if ( strcmp( pGate->pPins->pName, "*" ) == 0 ) + { + // get the topmost (generic) pin + pPin = pGate->pPins; + FREE( pPin->pName ); + + // create individual pins from the generic pin + ppPin = &pPin->pNext; + for ( i = 1; i < nPins; i++ ) + { + // get the new pin + *ppPin = Mio_PinDup( pPin ); + // set its name + (*ppPin)->pName = pPinNames[i]; + // prepare the next place in the list + ppPin = &((*ppPin)->pNext); + } + *ppPin = NULL; + + // set the name of the topmost pin + pPin->pName = pPinNames[0]; + } + else + { + // reorder the variable names to appear the save way as the pins + iPin = 0; + Mio_GateForEachPin( pGate, pPin ) + { + // find the pin with the name pPin->pName + for ( i = 0; i < nPins; i++ ) + { + if ( pPinNames[i] && strcmp( pPinNames[i], pPin->pName ) == 0 ) + { + // free pPinNames[i] because it is already available as pPin->pName + // setting pPinNames[i] to NULL is useful to make sure that + // this name is not assigned to two pins in the list + FREE( pPinNames[i] ); + pPinNamesCopy[iPin++] = pPin->pName; + break; + } + if ( i == nPins ) + { + printf( "Cannot find pin name \"%s\" in the formula \"%s\" of gate \"%s\".\n", + pPin->pName, pGate->pForm, pGate->pName ); + return 1; + } + } + } + + // check for the remaining names + for ( i = 0; i < nPins; i++ ) + if ( pPinNames[i] ) + { + printf( "Name \"%s\" appears in the formula \"%s\" of gate \"%s\" but there is no such pin.\n", + pPinNames[i], pGate->pForm, pGate->pName ); + return 1; + } + + // copy the names back + memcpy( pPinNames, pPinNamesCopy, nPins * sizeof(char *) ); + } + + // expand the manager if necessary + if ( dd->size < nPins ) + { + Cudd_Quit( dd ); + dd = Cudd_Init( nPins + 10, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_zddVarsFromBddVars( dd, 2 ); + } + + // derive the formula as the BDD + pGate->bFunc = Parse_FormulaParser( stdout, pGate->pForm, nPins, 0, pPinNames, dd, dd->vars ); + Cudd_Ref( pGate->bFunc ); + + // derive the cover (SOP) + pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, pGate->bFunc, nPins, 0, pGate->pLib->vCube, -1 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Collect the pin names in the formula.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_GateCollectNames( char * pFormula, char * pPinNames[] ) +{ + char Buffer[1000]; + char * pTemp; + int nPins, i; + + // save the formula as it was + strcpy( Buffer, pFormula ); + + // remove the non-name symbols + for ( pTemp = Buffer; *pTemp; pTemp++ ) + if ( *pTemp == MIO_SYMB_AND || *pTemp == MIO_SYMB_OR || *pTemp == MIO_SYMB_NOT + || *pTemp == MIO_SYMB_OPEN || *pTemp == MIO_SYMB_CLOSE || *pTemp == MIO_SYMB_AFTNOT ) + *pTemp = ' '; + + // save the names + nPins = 0; + pTemp = strtok( Buffer, " " ); + while ( pTemp ) + { + for ( i = 0; i < nPins; i++ ) + if ( strcmp( pTemp, pPinNames[i] ) == 0 ) + break; + if ( i == nPins ) + { // cannot find this name; save it + pPinNames[nPins++] = Extra_UtilStrsav(pTemp); + } + // get the next name + pTemp = strtok( NULL, " " ); + } + return nPins; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mio/mioGENERIC.c b/abc70930/src/map/mio/mioGENERIC.c new file mode 100644 index 00000000..972c4ffc --- /dev/null +++ b/abc70930/src/map/mio/mioGENERIC.c @@ -0,0 +1,46 @@ +/**CFile**************************************************************** + + FileName [mio___.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [File reading/writing for technology mapping.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: mio___.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "mioInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mio/mioInt.h b/abc70930/src/map/mio/mioInt.h new file mode 100644 index 00000000..3f90b625 --- /dev/null +++ b/abc70930/src/map/mio/mioInt.h @@ -0,0 +1,125 @@ +/**CFile**************************************************************** + + FileName [mioInt.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [File reading/writing for technology mapping.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: mioInt.h,v 1.4 2004/06/28 14:20:25 alanmi Exp $] + +***********************************************************************/ + +#ifndef __MIO_INT_H__ +#define __MIO_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "abc.h" +#include "mvc.h" +#include "main.h" +#include "mio.h" +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define MIO_STRING_GATE "GATE" +#define MIO_STRING_PIN "PIN" +#define MIO_STRING_NONINV "NONINV" +#define MIO_STRING_INV "INV" +#define MIO_STRING_UNKNOWN "UNKNOWN" + +#define MIO_STRING_CONST0 "CONST0" +#define MIO_STRING_CONST1 "CONST1" + +// the bit masks +#define MIO_MASK(n) ((~((unsigned)0)) >> (32-(n))) +#define MIO_FULL (~((unsigned)0)) + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Mio_LibraryStruct_t_ +{ + char * pName; // the name of the library + int nGates; // the number of the gates + Mio_Gate_t * pGates; // the linked list of all gates in no particular order + Mio_Gate_t * pGate0; // the constant zero gate + Mio_Gate_t * pGate1; // the constant one gate + Mio_Gate_t * pGateBuf; // the buffer + Mio_Gate_t * pGateInv; // the inverter + Mio_Gate_t * pGateNand2; // the NAND2 gate + Mio_Gate_t * pGateAnd2; // the AND2 gate + st_table * tName2Gate; // the mapping of gate names into their pointer + DdManager * dd; // the nanager storing functions of gates + Extra_MmFlex_t * pMmFlex; // the memory manaqer for SOPs + Vec_Str_t * vCube; // temporary cube +}; + +struct Mio_GateStruct_t_ +{ + // information derived from the genlib file + char * pName; // the name of the gate + double dArea; // the area of the gate + char * pForm; // the formula describing functionality of the gate + Mio_Pin_t * pPins; // the linked list of all pins (one pin if info is the same) + char * pOutName; // the name of the output pin + // the library to which this gate belongs + Mio_Library_t * pLib; + // the next gate in the list + Mio_Gate_t * pNext; + + // the derived information + int nInputs; // the number of inputs + double dDelayMax; // the maximum delay + DdNode * bFunc; // the functionality + char * pSop; +}; + +struct Mio_PinStruct_t_ +{ + char * pName; + Mio_PinPhase_t Phase; + double dLoadInput; + double dLoadMax; + double dDelayBlockRise; + double dDelayFanoutRise; + double dDelayBlockFall; + double dDelayFanoutFall; + double dDelayBlockMax; + Mio_Pin_t * pNext; +}; + + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== mio.c =============================================================*/ +/*=== mioRead.c =============================================================*/ +/*=== mioUtils.c =============================================================*/ + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/map/mio/mioRead.c b/abc70930/src/map/mio/mioRead.c new file mode 100644 index 00000000..13c2cdcd --- /dev/null +++ b/abc70930/src/map/mio/mioRead.c @@ -0,0 +1,582 @@ +/**CFile**************************************************************** + + FileName [mioRead.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [File reading/writing for technology mapping.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: mioRead.c,v 1.9 2004/10/19 06:40:16 satrajit Exp $] + +***********************************************************************/ + +#include "mioInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose ); +static int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose ); +static Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat ); +static Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, bool fExtendedFormat ); +static char * chomp( char *s ); +static void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib ); +static void Io_ReadFileRemoveComments( char * pBuffer, int * pnDots, int * pnLines ); + +#ifdef WIN32 +extern int isspace( int c ); // to silence the warning in VS +#endif + +/**Function************************************************************* + + Synopsis [Read the genlib type of library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mio_Library_t * Mio_LibraryRead( void * pAbc, char * FileName, char * ExcludeFile, int fVerbose ) +{ + Mio_Library_t * pLib; + int num; + + st_table * tExcludeGate = 0; + + if ( ExcludeFile ) + { + tExcludeGate = st_init_table(strcmp, st_strhash); + if ( (num = Mio_LibraryReadExclude( pAbc, ExcludeFile, tExcludeGate )) == -1 ) + { + st_free_table( tExcludeGate ); + tExcludeGate = 0; + return 0; + } + + fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num ); + } + + pLib = Mio_LibraryReadOne( pAbc, FileName, 0, tExcludeGate, fVerbose ); // try normal format first .. + if ( pLib == NULL ) + { + pLib = Mio_LibraryReadOne( pAbc, FileName, 1, tExcludeGate, fVerbose ); // .. otherwise try extended format + if ( pLib != NULL ) + printf ( "Warning: Read extended GENLIB format but ignoring extensions\n" ); + } + + return pLib; +} + +/**Function************************************************************* + + Synopsis [Read the genlib type of library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose ) +{ + Mio_Library_t * pLib; + char * pBuffer = 0; + + // allocate the genlib structure + pLib = ALLOC( Mio_Library_t, 1 ); + memset( pLib, 0, sizeof(Mio_Library_t) ); + pLib->pName = Extra_UtilStrsav( FileName ); + pLib->tName2Gate = st_init_table(strcmp, st_strhash); + pLib->pMmFlex = Extra_MmFlexStart(); + pLib->vCube = Vec_StrAlloc( 100 ); + + // read the file and clean comments + // pBuffer = Io_ReadFileFileContents( FileName, NULL ); + // we don't use above function but actually do the same thing explicitly + // to handle open_path expansion correctly + + { + FILE * pFile; + int nFileSize; + + // open the BLIF file for binary reading + pFile = Io_FileOpen( FileName, "open_path", "rb", 1 ); +// pFile = fopen( FileName, "rb" ); + // if we got this far, file should be okay otherwise would + // have been detected by caller + assert ( pFile != NULL ); + // get the file size, in bytes + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + // move the file current reading position to the beginning + rewind( pFile ); + // load the contents of the file into memory + pBuffer = ALLOC( char, nFileSize + 10 ); + fread( pBuffer, nFileSize, 1, pFile ); + // terminate the string with '\0' + pBuffer[ nFileSize ] = '\0'; + strcat( pBuffer, "\n.end\n" ); + // close file + fclose( pFile ); + } + + Io_ReadFileRemoveComments( pBuffer, NULL, NULL ); + + // parse the contents of the file + if ( Mio_LibraryReadInternal( pLib, pBuffer, fExtendedFormat, tExcludeGate, fVerbose ) ) + { + Mio_LibraryDelete( pLib ); + free( pBuffer ); + return NULL; + } + free( pBuffer ); + + // derive the functinality of gates + if ( Mio_LibraryParseFormulas( pLib ) ) + { + printf( "Mio_LibraryRead: Had problems parsing formulas.\n" ); + Mio_LibraryDelete( pLib ); + return NULL; + } + + // detect INV and NAND2 + Mio_LibraryDetectSpecialGates( pLib ); +//Mio_WriteLibrary( stdout, pLib ); + return pLib; +} + +/**Function************************************************************* + + Synopsis [Read the genlib type of library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose ) +{ + Mio_Gate_t * pGate, ** ppGate; + char * pToken; + int nGates = 0; + int nDel = 0; + + // start the linked list of gates + pLib->pGates = NULL; + ppGate = &pLib->pGates; + + // read gates one by one + pToken = strtok( pBuffer, " \t\r\n" ); + while ( pToken && strcmp( pToken, MIO_STRING_GATE ) == 0 ) + { + // derive the next gate + pGate = Mio_LibraryReadGate( &pToken, fExtendedFormat ); + if ( pGate == NULL ) + return 1; + + // set the library + pGate->pLib = pLib; + + // printf ("Processing: '%s'\n", pGate->pName); + + if ( tExcludeGate && st_is_member( tExcludeGate, pGate->pName ) ) + { + //printf ("Excluding: '%s'\n", pGate->pName); + Mio_GateDelete( pGate ); + nDel++; + } + else + { + // add this gate to the list + *ppGate = pGate; + ppGate = &pGate->pNext; + nGates++; + + // remember this gate by name + if ( !st_is_member( pLib->tName2Gate, pGate->pName ) ) + st_insert( pLib->tName2Gate, pGate->pName, (char *)pGate ); + else + printf( "The gate with name \"%s\" appears more than once.\n", pGate->pName ); + } + } + if ( fVerbose ) + printf( "The number of gates read = %d.\n", nGates ); + + // check what is the last word read + if ( pToken && strcmp( pToken, ".end" ) != 0 ) + return 1; + + if ( nDel != 0 ) + printf( "Actually excluded %d cells\n", nDel ); + + return 0; +} + +/**Function************************************************************* + + Synopsis [Read the genlib type of gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat ) +{ + Mio_Gate_t * pGate; + Mio_Pin_t * pPin, ** ppPin; + char * pToken = *ppToken; + + // allocate the gate structure + pGate = ALLOC( Mio_Gate_t, 1 ); + memset( pGate, 0, sizeof(Mio_Gate_t) ); + + // read the name + pToken = strtok( NULL, " \t\r\n" ); + pGate->pName = Extra_UtilStrsav( pToken ); + + // read the area + pToken = strtok( NULL, " \t\r\n" ); + pGate->dArea = atof( pToken ); + + // read the formula + + // first the output name + pToken = strtok( NULL, "=" ); + pGate->pOutName = chomp( pToken ); + + // then rest of the expression + pToken = strtok( NULL, ";" ); + pGate->pForm = Extra_UtilStrsav( pToken ); + + // read the pin info + // start the linked list of pins + pGate->pPins = NULL; + ppPin = &pGate->pPins; + + // read gates one by one + pToken = strtok( NULL, " \t\r\n" ); + while ( pToken && strcmp( pToken, MIO_STRING_PIN ) == 0 ) + { + // derive the next gate + pPin = Mio_LibraryReadPin( &pToken, fExtendedFormat ); + if ( pPin == NULL ) + { + Mio_GateDelete( pGate ); + *ppToken = pToken; + return NULL; + } + // add this pin to the list + *ppPin = pPin; + ppPin = &pPin->pNext; + // get the next token + pToken = strtok( NULL, " \t\r\n" ); + } + + *ppToken = pToken; + return pGate; +} + + + +/**Function************************************************************* + + Synopsis [Read the genlib type of pin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, bool fExtendedFormat ) +{ + Mio_Pin_t * pPin; + char * pToken = *ppToken; + + // allocate the gate structure + pPin = ALLOC( Mio_Pin_t, 1 ); + memset( pPin, 0, sizeof(Mio_Pin_t) ); + + // read the name + pToken = strtok( NULL, " \t\r\n" ); + pPin->pName = Extra_UtilStrsav( pToken ); + + // read the pin phase + pToken = strtok( NULL, " \t\r\n" ); + if ( strcmp( pToken, MIO_STRING_UNKNOWN ) == 0 ) + pPin->Phase = MIO_PHASE_UNKNOWN; + else if ( strcmp( pToken, MIO_STRING_INV ) == 0 ) + pPin->Phase = MIO_PHASE_INV; + else if ( strcmp( pToken, MIO_STRING_NONINV ) == 0 ) + pPin->Phase = MIO_PHASE_NONINV; + else + { + printf( "Cannot read pin phase specification\n" ); + Mio_PinDelete( pPin ); + *ppToken = pToken; + return NULL; + } + + pToken = strtok( NULL, " \t\r\n" ); + pPin->dLoadInput = atof( pToken ); + + pToken = strtok( NULL, " \t\r\n" ); + pPin->dLoadMax = atof( pToken ); + + pToken = strtok( NULL, " \t\r\n" ); + pPin->dDelayBlockRise = atof( pToken ); + + pToken = strtok( NULL, " \t\r\n" ); + pPin->dDelayFanoutRise = atof( pToken ); + + pToken = strtok( NULL, " \t\r\n" ); + pPin->dDelayBlockFall = atof( pToken ); + + pToken = strtok( NULL, " \t\r\n" ); + pPin->dDelayFanoutFall = atof( pToken ); + + if ( fExtendedFormat ) + { + /* In extended format, the field after dDelayFanoutRise + * is to be ignored + **/ + + pPin->dDelayBlockFall = pPin->dDelayFanoutFall; + + pToken = strtok( NULL, " \t" ); + pPin->dDelayFanoutFall = atof( pToken ); + + /* last field is ignored */ + pToken = strtok( NULL, " \t\r\n" ); + } + + if ( pPin->dDelayBlockRise > pPin->dDelayBlockFall ) + pPin->dDelayBlockMax = pPin->dDelayBlockRise; + else + pPin->dDelayBlockMax = pPin->dDelayBlockFall; + + *ppToken = pToken; + return pPin; +} + + +/**Function************************************************************* + + Synopsis [Duplicates string and returns it with leading and + trailing spaces removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char *chomp( char *s ) +{ + char *b = ALLOC(char, strlen(s)+1), *c = b; + while (*s && isspace(*s)) + ++s; + while (*s && !isspace(*s)) + *c++ = *s++; + *c = 0; + return b; +} + +/**Function************************************************************* + + Synopsis [Duplicates string and returns it with leading and + trailing spaces removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib ) +{ + Mio_Gate_t * pGate; + DdNode * bFuncBuf, * bFuncInv, * bFuncNand2, * bFuncAnd2; + + bFuncBuf = pLib->dd->vars[0]; Cudd_Ref( bFuncBuf ); + bFuncInv = Cudd_Not( pLib->dd->vars[0] ); Cudd_Ref( bFuncInv ); + bFuncNand2 = Cudd_bddNand( pLib->dd, pLib->dd->vars[0], pLib->dd->vars[1] ); Cudd_Ref( bFuncNand2 ); + bFuncAnd2 = Cudd_bddAnd( pLib->dd, pLib->dd->vars[0], pLib->dd->vars[1] ); Cudd_Ref( bFuncAnd2 ); + + // get buffer + Mio_LibraryForEachGate( pLib, pGate ) + if ( pLib->pGateBuf == NULL && pGate->bFunc == bFuncBuf ) + { + pLib->pGateBuf = pGate; + break; + } + if ( pLib->pGateBuf == NULL ) + { + printf( "Warnings: GENLIB library reader cannot detect the buffer gate.\n" ); + printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" ); + } + + // get inverter + Mio_LibraryForEachGate( pLib, pGate ) + if ( pLib->pGateInv == NULL && pGate->bFunc == bFuncInv ) + { + pLib->pGateInv = pGate; + break; + } + if ( pLib->pGateInv == NULL ) + { + printf( "Warnings: GENLIB library reader cannot detect the invertor gate.\n" ); + printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" ); + } + + // get the NAND2 and AND2 gates + Mio_LibraryForEachGate( pLib, pGate ) + if ( pLib->pGateNand2 == NULL && pGate->bFunc == bFuncNand2 ) + { + pLib->pGateNand2 = pGate; + break; + } + Mio_LibraryForEachGate( pLib, pGate ) + if ( pLib->pGateAnd2 == NULL && pGate->bFunc == bFuncAnd2 ) + { + pLib->pGateAnd2 = pGate; + break; + } + if ( pLib->pGateAnd2 == NULL && pLib->pGateNand2 == NULL ) + { + printf( "Warnings: GENLIB library reader cannot detect the AND2 or NAND2 gate.\n" ); + printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" ); + } + + Cudd_RecursiveDeref( pLib->dd, bFuncInv ); + Cudd_RecursiveDeref( pLib->dd, bFuncNand2 ); + Cudd_RecursiveDeref( pLib->dd, bFuncAnd2 ); +} + +/**Function************************************************************* + + Synopsis [populate hash table of gates to be exlcuded from genlib] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_LibraryReadExclude( void * pAbc, char * ExcludeFile, st_table * tExcludeGate ) +{ + int nDel = 0; + FILE *pEx; + char buffer[128]; + + assert ( tExcludeGate ); + + if ( ExcludeFile ) + { + pEx = fopen( ExcludeFile, "r" ); + + if ( pEx == NULL ) + { + fprintf ( Abc_FrameReadErr( pAbc ), "Error: Could not open exclude file %s. Stop.\n", ExcludeFile ); + return -1; + } + + while (1 == fscanf( pEx, "%127s", buffer )) + { + //printf ("Read: '%s'\n", buffer ); + st_insert( tExcludeGate, Extra_UtilStrsav( buffer ), (char *)0 ); + nDel++; + } + + fclose( pEx ); + } + + return nDel; +} + +/**Function************************************************************* + + Synopsis [Eliminates comments from the input file.] + + Description [As a byproduct, this procedure also counts the number + lines and dot-statements in the input file. This also joins non-comment + lines that are joined with a backspace '\'] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Io_ReadFileRemoveComments( char * pBuffer, int * pnDots, int * pnLines ) +{ + char * pCur; + int nDots, nLines; + // scan through the buffer and eliminate comments + // (in the BLIF file, comments are lines starting with "#") + nDots = nLines = 0; + for ( pCur = pBuffer; *pCur; pCur++ ) + { + // if this is the beginning of comment + // clean it with spaces until the new line statement + if ( *pCur == '#' ) + while ( *pCur != '\n' ) + *pCur++ = ' '; + + // count the number of new lines and dots + if ( *pCur == '\n' ) { + if (*(pCur-1)=='\r') { + // DOS(R) file support + if (*(pCur-2)!='\\') nLines++; + else { + // rewind to backslash and overwrite with a space + *(pCur-2) = ' '; + *(pCur-1) = ' '; + *pCur = ' '; + } + } else { + // UNIX(TM) file support + if (*(pCur-1)!='\\') nLines++; + else { + // rewind to backslash and overwrite with a space + *(pCur-1) = ' '; + *pCur = ' '; + } + } + } + else if ( *pCur == '.' ) + nDots++; + } + if ( pnDots ) + *pnDots = nDots; + if ( pnLines ) + *pnLines = nLines; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mio/mioUtils.c b/abc70930/src/map/mio/mioUtils.c new file mode 100644 index 00000000..bd3d01f7 --- /dev/null +++ b/abc70930/src/map/mio/mioUtils.c @@ -0,0 +1,531 @@ +/**CFile**************************************************************** + + FileName [mioUtils.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [File reading/writing for technology mapping.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: mioUtils.c,v 1.6 2004/09/03 18:02:20 satrajit Exp $] + +***********************************************************************/ + +#include "mioInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Mio_WriteGate( FILE * pFile, Mio_Gate_t * pGate, int fPrintSops ); +static void Mio_WritePin( FILE * pFile, Mio_Pin_t * pPin ); +static int Mio_DelayCompare( Mio_Gate_t ** ppG1, Mio_Gate_t ** ppG2 ); +static void Mio_DeriveTruthTable_rec( DdNode * bFunc, unsigned uTruthsIn[][2], unsigned uTruthRes[] ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_LibraryDelete( Mio_Library_t * pLib ) +{ + Mio_Gate_t * pGate, * pGate2; + if ( pLib == NULL ) + return; + // free the bindings of nodes to gates from this library for all networks + Abc_FrameUnmapAllNetworks( Abc_FrameGetGlobalFrame() ); + // free the library + FREE( pLib->pName ); + Mio_LibraryForEachGateSafe( pLib, pGate, pGate2 ) + Mio_GateDelete( pGate ); + Extra_MmFlexStop( pLib->pMmFlex ); + Vec_StrFree( pLib->vCube ); + if ( pLib->tName2Gate ) + st_free_table( pLib->tName2Gate ); + if ( pLib->dd ) + Cudd_Quit( pLib->dd ); + free( pLib ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_GateDelete( Mio_Gate_t * pGate ) +{ + Mio_Pin_t * pPin, * pPin2; + FREE( pGate->pOutName ); + FREE( pGate->pName ); + FREE( pGate->pForm ); + if ( pGate->bFunc ) + Cudd_RecursiveDeref( pGate->pLib->dd, pGate->bFunc ); + Mio_GateForEachPinSafe( pGate, pPin, pPin2 ) + Mio_PinDelete( pPin ); + free( pGate ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_PinDelete( Mio_Pin_t * pPin ) +{ + FREE( pPin->pName ); + free( pPin ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin ) +{ + Mio_Pin_t * pPinNew; + + pPinNew = ALLOC( Mio_Pin_t, 1 ); + *pPinNew = *pPin; + pPinNew->pName = (pPinNew->pName ? Extra_UtilStrsav(pPinNew->pName) : NULL); + pPinNew->pNext = NULL; + + return pPinNew; +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops ) +{ + Mio_Gate_t * pGate; + + fprintf( pFile, "# The genlib library \"%s\".\n", pLib->pName ); + Mio_LibraryForEachGate( pLib, pGate ) + Mio_WriteGate( pFile, pGate, fPrintSops ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_WriteGate( FILE * pFile, Mio_Gate_t * pGate, int fPrintSops ) +{ + Mio_Pin_t * pPin; + + fprintf( pFile, "GATE " ); + fprintf( pFile, "%12s ", pGate->pName ); + fprintf( pFile, "%10.2f ", pGate->dArea ); + fprintf( pFile, "%s=%s;\n", pGate->pOutName, pGate->pForm ); + // print the pins + if ( fPrintSops ) + fprintf( pFile, "%s", pGate->pSop? pGate->pSop : "unspecified\n" ); +// Extra_bddPrint( pGate->pLib->dd, pGate->bFunc ); +// fprintf( pFile, "\n" ); + Mio_GateForEachPin( pGate, pPin ) + Mio_WritePin( pFile, pPin ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_WritePin( FILE * pFile, Mio_Pin_t * pPin ) +{ + char * pPhaseNames[10] = { "UNKNOWN", "INV", "NONINV" }; + fprintf( pFile, " PIN " ); + fprintf( pFile, "%9s ", pPin->pName ); + fprintf( pFile, "%10s ", pPhaseNames[pPin->Phase] ); + fprintf( pFile, "%6d ", (int)pPin->dLoadInput ); + fprintf( pFile, "%6d ", (int)pPin->dLoadMax ); + fprintf( pFile, "%6.2f ", pPin->dDelayBlockRise ); + fprintf( pFile, "%6.2f ", pPin->dDelayFanoutRise ); + fprintf( pFile, "%6.2f ", pPin->dDelayBlockFall ); + fprintf( pFile, "%6.2f", pPin->dDelayFanoutFall ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Collects the set of root gates.] + + Description [Only collects the gates with unique functionality, + which have fewer inputs and shorter delay than the given limits.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mio_Gate_t ** Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, bool fSkipInv, int * pnGates ) +{ + Mio_Gate_t * pGate; + Mio_Gate_t ** ppGates; + /* st_table * tFuncs; */ + /* st_generator * gen; */ + DdNode * bFunc; + DdManager * dd; + int nGates, iGate; + + dd = Mio_LibraryReadDd( pLib ); + nGates = Mio_LibraryReadGateNum( pLib ); + + /* + + // for each functionality select one gate; skip constants and buffers + tFuncs = st_init_table( st_ptrcmp, st_ptrhash ); + Mio_LibraryForEachGate( pLib, pGate ) + { + bFunc = Mio_GateReadFunc(pGate); + if ( pGate->nInputs > nInputs ) + continue; + if ( pGate->dDelayMax > (double)tDelay ) + continue; + if ( bFunc == b0 || bFunc == b1 ) + continue; + if ( bFunc == dd->vars[0] ) + continue; + if ( bFunc == Cudd_Not(dd->vars[0]) && fSkipInv ) + continue; + if ( st_is_member( tFuncs, (char *)bFunc ) ) + continue; + st_insert( tFuncs, (char *)bFunc, (char *)pGate ); + } + + // collect the gates into the array + ppGates = ALLOC( Mio_Gate_t *, nGates ); + iGate = 0; + st_foreach_item( tFuncs, gen, (char **)&bFunc, (char **)&pGate ) + ppGates[ iGate++ ] = pGate; + assert( iGate <= nGates ); + st_free_table( tFuncs ); + + */ + + ppGates = ALLOC( Mio_Gate_t *, nGates ); + iGate = 0; + Mio_LibraryForEachGate( pLib, pGate ) + { + bFunc = Mio_GateReadFunc(pGate); + if ( pGate->nInputs > nInputs ) + continue; + if ( pGate->dDelayMax > (double)tDelay ) + continue; + if ( bFunc == b0 || bFunc == b1 ) + continue; + if ( bFunc == dd->vars[0] ) + continue; + if ( bFunc == Cudd_Not(dd->vars[0]) && fSkipInv ) + continue; + + assert( iGate < nGates ); + ppGates[ iGate++ ] = pGate; + } + + if ( iGate > 0 ) + { + // sort the gates by delay + qsort( (void *)ppGates, iGate, sizeof(Mio_Gate_t *), + (int (*)(const void *, const void *)) Mio_DelayCompare ); + assert( Mio_DelayCompare( ppGates, ppGates + iGate - 1 ) <= 0 ); + } + + if ( pnGates ) + *pnGates = iGate; + return ppGates; +} + +/**Function************************************************************* + + Synopsis [Compares the max delay of two gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mio_DelayCompare( Mio_Gate_t ** ppG1, Mio_Gate_t ** ppG2 ) +{ + if ( (*ppG1)->dDelayMax < (*ppG2)->dDelayMax ) + return -1; + if ( (*ppG1)->dDelayMax > (*ppG2)->dDelayMax ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Derives the truth table of the gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] ) +{ + Mio_DeriveTruthTable_rec( pGate->bFunc, uTruthsIn, uTruthRes ); +} + +/**Function************************************************************* + + Synopsis [Recursively derives the truth table of the gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_DeriveTruthTable_rec( DdNode * bFunc, unsigned uTruthsIn[][2], unsigned uTruthRes[] ) +{ + unsigned uTruthsCof0[2]; + unsigned uTruthsCof1[2]; + + // complement the resulting truth table, if the function is complemented + if ( Cudd_IsComplement(bFunc) ) + { + Mio_DeriveTruthTable_rec( Cudd_Not(bFunc), uTruthsIn, uTruthRes ); + uTruthRes[0] = ~uTruthRes[0]; + uTruthRes[1] = ~uTruthRes[1]; + return; + } + + // if the function is constant 1, return the constant 1 truth table + if ( bFunc->index == CUDD_CONST_INDEX ) + { + uTruthRes[0] = MIO_FULL; + uTruthRes[1] = MIO_FULL; + return; + } + + // solve the problem for both cofactors + Mio_DeriveTruthTable_rec( cuddE(bFunc), uTruthsIn, uTruthsCof0 ); + Mio_DeriveTruthTable_rec( cuddT(bFunc), uTruthsIn, uTruthsCof1 ); + + // derive the resulting truth table using the input truth tables + uTruthRes[0] = (uTruthsCof0[0] & ~uTruthsIn[bFunc->index][0]) | + (uTruthsCof1[0] & uTruthsIn[bFunc->index][0]); + uTruthRes[1] = (uTruthsCof0[1] & ~uTruthsIn[bFunc->index][1]) | + (uTruthsCof1[1] & uTruthsIn[bFunc->index][1]); +} + +/**Function************************************************************* + + Synopsis [Derives the truth table of the root of the gate.] + + Description [Given the truth tables of the leaves of the gate, + this procedure derives the truth table of the root.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_DeriveTruthTable2( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nTruths, int nInputs, unsigned uTruthRes[] ) +{ + unsigned uSignCube[2]; + int i, nFanins; + char * pCube; + + // make sure that the number of input truth tables in equal to the number of gate inputs + assert( pGate->nInputs == nTruths ); + assert( nInputs < 7 ); + + nFanins = Abc_SopGetVarNum( pGate->pSop ); + assert( nFanins == nInputs ); + + // clean the resulting truth table + uTruthRes[0] = 0; + uTruthRes[1] = 0; + if ( nInputs < 6 ) + { +// for ( c = 0; *(pCube = pGate->pSop + c * (nFanins + 3)); c++ ) + Abc_SopForEachCube( pGate->pSop, nFanins, pCube ) + { + // add the clause + uSignCube[0] = MIO_FULL; + for ( i = 0; i < nFanins; i++ ) + { + if ( pCube[i] == '0' ) + uSignCube[0] &= ~uTruthsIn[i][0]; + else if ( pCube[i] == '1' ) + uSignCube[0] &= uTruthsIn[i][0]; + } + } + if ( nInputs < 5 ) + uTruthRes[0] &= MIO_MASK(1<pSop + c * (nFanins + 3)); c++ ) + Abc_SopForEachCube( pGate->pSop, nFanins, pCube ) + { + uSignCube[0] = MIO_FULL; + uSignCube[1] = MIO_FULL; + for ( i = 0; i < nFanins; i++ ) + { + if ( pCube[i] == '0' ) + { + uSignCube[0] &= ~uTruthsIn[i][0]; + uSignCube[1] &= ~uTruthsIn[i][1]; + } + else if ( pCube[i] == '1' ) + { + uSignCube[0] &= uTruthsIn[i][0]; + uSignCube[1] &= uTruthsIn[i][1]; + } + } + uTruthRes[0] |= uSignCube[0]; + uTruthRes[1] |= uSignCube[1]; + } + } +} + +/**Function************************************************************* + + Synopsis [Derives the area and delay of the root of the gate.] + + Description [Array of the resulting delays should be initialized + to the (negative) SUPER_NO_VAR value.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mio_DeriveGateDelays( Mio_Gate_t * pGate, + float ** ptPinDelays, int nPins, int nInputs, float tDelayZero, + float * ptDelaysRes, float * ptPinDelayMax ) +{ + Mio_Pin_t * pPin; + float Delay, DelayMax; + int i, k; + assert( pGate->nInputs == nPins ); + // set all the delays to the unused delay + for ( i = 0; i < nInputs; i++ ) + ptDelaysRes[i] = tDelayZero; + // compute the delays for each input and the max delay at the same time + DelayMax = 0; + for ( i = 0; i < nInputs; i++ ) + { + for ( k = 0, pPin = pGate->pPins; pPin; pPin = pPin->pNext, k++ ) + { + if ( ptPinDelays[k][i] < 0 ) + continue; + Delay = ptPinDelays[k][i] + (float)pPin->dDelayBlockMax; + if ( ptDelaysRes[i] < Delay ) + ptDelaysRes[i] = Delay; + } + if ( k != nPins ) + { + printf ("DEBUG: problem gate is %s\n", Mio_GateReadName( pGate )); + } + assert( k == nPins ); + if ( DelayMax < ptDelaysRes[i] ) + DelayMax = ptDelaysRes[i]; + } + *ptPinDelayMax = DelayMax; +} + + +/**Function************************************************************* + + Synopsis [Creates a pseudo-gate.] + + Description [The pseudo-gate is a N-input gate with all info set to 0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mio_Gate_t * Mio_GateCreatePseudo( int nInputs ) +{ + Mio_Gate_t * pGate; + Mio_Pin_t * pPin; + int i; + // allocate the gate structure + pGate = ALLOC( Mio_Gate_t, 1 ); + memset( pGate, 0, sizeof(Mio_Gate_t) ); + pGate->nInputs = nInputs; + // create pins + for ( i = 0; i < nInputs; i++ ) + { + pPin = ALLOC( Mio_Pin_t, 1 ); + memset( pPin, 0, sizeof(Mio_Pin_t) ); + pPin->pNext = pGate->pPins; + pGate->pPins = pPin; + } + return pGate; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/mio/module.make b/abc70930/src/map/mio/module.make new file mode 100644 index 00000000..26a4561c --- /dev/null +++ b/abc70930/src/map/mio/module.make @@ -0,0 +1,5 @@ +SRC += src/map/mio/mio.c \ + src/map/mio/mioApi.c \ + src/map/mio/mioFunc.c \ + src/map/mio/mioRead.c \ + src/map/mio/mioUtils.c diff --git a/abc70930/src/map/super/module.make b/abc70930/src/map/super/module.make new file mode 100644 index 00000000..19ce8228 --- /dev/null +++ b/abc70930/src/map/super/module.make @@ -0,0 +1,4 @@ +SRC += src/map/super/super.c \ + src/map/super/superAnd.c \ + src/map/super/superGate.c \ + src/map/super/superWrite.c diff --git a/abc70930/src/map/super/super.c b/abc70930/src/map/super/super.c new file mode 100644 index 00000000..97420c5c --- /dev/null +++ b/abc70930/src/map/super/super.c @@ -0,0 +1,319 @@ +/**CFile**************************************************************** + + FileName [super.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Pre-computation of supergates.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 18, 2003.] + + Revision [$Id: super.c,v 1.6 2004/10/30 20:51:11 satrajit Exp $] + +***********************************************************************/ + +#include "superInt.h" +#include "mainInt.h" +#include "mio.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Super_CommandSupergates ( Abc_Frame_t * pAbc, int argc, char **argv ); +static int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_Init( Abc_Frame_t * pAbc ) +{ + Cmd_CommandAdd( pAbc, "SC mapping", "super", Super_CommandSupergates, 0 ); + Cmd_CommandAdd( pAbc, "SC mapping", "super2", Super_CommandSupergatesAnd, 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_End() +{ +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pOut, * pErr; + int nVarsMax, nLevels; + int fVerbose; + int c; + + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + nVarsMax = 4; + nLevels = 3; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "ilvh")) != EOF ) + { + switch (c) + { + case 'i': + nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVarsMax < 0 ) + goto usage; + break; + case 'l': + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + Super2_Precompute( nVarsMax, nLevels, fVerbose ); + + return 0; + +usage: + fprintf( pErr, "usage: super2 [-i num] [-l num] [-vh]\n"); + fprintf( pErr, "\t precomputes the supergates composed of AND2s and INVs\n" ); + fprintf( pErr, "\t-i num : the max number of inputs to the supergate [default = %d]\n", nVarsMax ); + fprintf( pErr, "\t-l num : the max number of logic levels of gates [default = %d]\n", nLevels ); + fprintf( pErr, "\t-v : enable verbose output\n"); + fprintf( pErr, "\t-h : print the help message\n"); + return 1; /* error exit */ +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv ) +{ + FILE * pFile; + FILE * pOut, * pErr; + Mio_Library_t * pLib; + char * FileName, * ExcludeFile; + float DelayLimit; + float AreaLimit; + bool fSkipInvs; + bool fWriteOldFormat; + int nVarsMax, nLevels, TimeLimit; + int fVerbose; + int c; + + pOut = Abc_FrameReadOut(pAbc); + pErr = Abc_FrameReadErr(pAbc); + + // set the defaults + nVarsMax = 5; + nLevels = 3; + DelayLimit = 3.5; + AreaLimit = 9; + TimeLimit = 10; + fSkipInvs = 1; + fVerbose = 0; + fWriteOldFormat = 0; + ExcludeFile = 0; + + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "eiltdasovh")) != EOF ) + { + switch (c) + { + case 'e': + ExcludeFile = argv[globalUtilOptind]; + if ( ExcludeFile == 0 ) + goto usage; + globalUtilOptind++; + break; + case 'i': + nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVarsMax < 0 ) + goto usage; + break; + case 'l': + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; + case 't': + TimeLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( TimeLimit < 0 ) + goto usage; + break; + case 'd': + DelayLimit = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( DelayLimit <= 0.0 ) + goto usage; + break; + case 'a': + AreaLimit = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( AreaLimit <= 0.0 ) + goto usage; + break; + case 's': + fSkipInvs ^= 1; + break; + case 'o': + fWriteOldFormat ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + + if ( argc != globalUtilOptind + 1 ) + { + fprintf( pErr, "The GENLIB library file should be given on the command line.\n" ); + goto usage; + } + + if ( nVarsMax < 2 || nVarsMax > 6 ) + { + fprintf( pErr, "The max number of variables (%d) should be more than 1 and less than 7.\n", nVarsMax ); + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) +// if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); + if (( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) )) + fprintf( pErr, "Did you mean \"%s\"?", FileName ); + fprintf( pErr, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pLib = Mio_LibraryRead( pAbc, FileName, ExcludeFile, fVerbose ); + if ( pLib == NULL ) + { + fprintf( pErr, "Reading library has failed.\n" ); + goto usage; + } + + // compute the gates + Super_Precompute( pLib, nVarsMax, nLevels, DelayLimit, AreaLimit, TimeLimit, fSkipInvs, fWriteOldFormat, fVerbose ); + + // delete the library + Mio_LibraryDelete( pLib ); + return 0; + +usage: + fprintf( pErr, "usage: super [-i num] [-l num] [-d float] [-a float] [-t num] [-sovh] \n"); + fprintf( pErr, "\t precomputes the supergates for the given GENLIB library\n" ); + fprintf( pErr, "\t-i num : the max number of supergate inputs [default = %d]\n", nVarsMax ); + fprintf( pErr, "\t-l num : the max number of levels of gates [default = %d]\n", nLevels ); + fprintf( pErr, "\t-d float : the max delay of the supergates [default = %.2f]\n", DelayLimit ); + fprintf( pErr, "\t-a float : the max area of the supergates [default = %.2f]\n", AreaLimit ); + fprintf( pErr, "\t-t num : the approximate runtime limit in seconds [default = %d]\n", TimeLimit ); + fprintf( pErr, "\t-s : toggle the use of inverters at the inputs [default = %s]\n", (fSkipInvs? "no": "yes") ); + fprintf( pErr, "\t-o : toggle dumping the supergate library in old format [default = %s]\n", (fWriteOldFormat? "yes": "no") ); + fprintf( pErr, "\t-e file : file contains list of genlib gates to exclude\n" ); + fprintf( pErr, "\t-v : enable verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); + fprintf( pErr, "\t-h : print the help message\n"); + fprintf( pErr, "\n"); + fprintf( pErr, "\tHere is a piece of advice on precomputing supergate libraries:\n"); + fprintf( pErr, "\t\n"); + fprintf( pErr, "\tStart with the number of inputs equal to 5 (-i 5), the number of \n"); + fprintf( pErr, "\tlevels equal to 3 (-l 3), the delay equal to 2-3 delays of inverter, \n"); + fprintf( pErr, "\tthe area equal to 3-4 areas of two input NAND, and runtime limit equal \n"); + fprintf( pErr, "\tto 10 seconds (-t 10). Run precomputation and learn from the result.\n"); + fprintf( pErr, "\tDetermine what parameter is most constraining and try to increase \n"); + fprintf( pErr, "\tthe value of that parameter. The goal is to have a well-balanced\n"); + fprintf( pErr, "\tset of constraints and the resulting supergate library containing\n"); + fprintf( pErr, "\tapproximately 100K-200K supergates. Typically, it is better to increase\n"); + fprintf( pErr, "\tdelay limit rather than area limit, because having large-area supergates\n"); + fprintf( pErr, "\tmay result in a considerable increase in area.\n"); + fprintf( pErr, "\t\n"); + fprintf( pErr, "\tNote that a good supergate library for experiments typically can be \n"); + fprintf( pErr, "\tprecomputed in 30 sec. Increasing the runtime limit makes sense when\n"); + fprintf( pErr, "\tother parameters are well-balanced and it is needed to enumerate more\n"); + fprintf( pErr, "\tchoices to have a good result. In the end, to compute the final library\n"); + fprintf( pErr, "\tthe runtime can be set to 300 sec to ensure the ultimate quality.\n"); + fprintf( pErr, "\tIn some cases, the runtime has to be reduced if the supergate library\n"); + fprintf( pErr, "\tcontains too many supergates (> 500K).\n"); + fprintf( pErr, "\t\n"); + fprintf( pErr, "\tWhen precomputing libraries of 6 inputs (-i 6), start with even more \n"); + fprintf( pErr, "\trestricted parameters and gradually increase them until the goal is met.\n"); + fprintf( pErr, "\t\n"); + return 1; /* error exit */ +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/super/super.h b/abc70930/src/map/super/super.h new file mode 100644 index 00000000..a7169924 --- /dev/null +++ b/abc70930/src/map/super/super.h @@ -0,0 +1,60 @@ +/**CFile**************************************************************** + + FileName [super.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Pre-computation of supergates (delay-limited gate combinations).] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: super.h,v 1.3 2004/06/28 14:20:25 alanmi Exp $] + +***********************************************************************/ + +#ifndef __SUPER_H__ +#define __SUPER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== superCore.c =============================================================*/ + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/map/super/superAnd.c b/abc70930/src/map/super/superAnd.c new file mode 100644 index 00000000..52473fba --- /dev/null +++ b/abc70930/src/map/super/superAnd.c @@ -0,0 +1,696 @@ +/**CFile**************************************************************** + + FileName [superAnd.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Pre-computation of supergates.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: superAnd.c,v 1.3 2004/06/28 14:20:25 alanmi Exp $] + +***********************************************************************/ + +#include "superInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the bit masks +#define SUPER_MASK(n) ((~((unsigned)0)) >> (32-n)) +#define SUPER_FULL (~((unsigned)0)) + +// data structure for AND2 subgraph precomputation +typedef struct Super2_ManStruct_t_ Super2_Man_t; // manager +typedef struct Super2_LibStruct_t_ Super2_Lib_t; // library +typedef struct Super2_GateStruct_t_ Super2_Gate_t; // supergate + +struct Super2_ManStruct_t_ +{ + Extra_MmFixed_t * pMem; // memory manager for all supergates + stmm_table * tTable; // mapping of truth tables into gates + int nTried; // the total number of tried +}; + +struct Super2_LibStruct_t_ +{ + int i; // used to iterate through the table + int k; // used to iterate through the table + int nInputs; // the number of inputs + int nMints; // the number of minterms + int nLevels; // the number of logic levels + int nGates; // the number of gates in the library + int nGatesAlloc; // the number of allocated places + Super2_Gate_t ** pGates; // the gates themselves + unsigned uMaskBit; // the mask used to determine the compl bit +}; + +struct Super2_GateStruct_t_ +{ + unsigned uTruth; // the truth table of this supergate + Super2_Gate_t * pOne; // the left wing + Super2_Gate_t * pTwo; // the right wing + Super2_Gate_t * pNext; // the next gate in the table +}; + + +// manipulation of complemented attributes +#define Super2_IsComplement(p) (((int)((unsigned long) (p) & 01))) +#define Super2_Regular(p) ((Super2_Gate_t *)((unsigned long)(p) & ~01)) +#define Super2_Not(p) ((Super2_Gate_t *)((unsigned long)(p) ^ 01)) +#define Super2_NotCond(p,c) ((Super2_Gate_t *)((unsigned long)(p) ^ (c))) + +// iterating through the gates in the library +#define Super2_LibForEachGate( Lib, Gate ) \ + for ( Lib->i = 0; \ + Lib->i < Lib->nGates && (Gate = Lib->pGates[Lib->i]); \ + Lib->i++ ) +#define Super2_LibForEachGate2( Lib, Gate2 ) \ + for ( Lib->k = 0; \ + Lib->k < Lib->i && (Gate2 = Lib->pGates[Lib->k]); \ + Lib->k++ ) + +// static functions +static Super2_Man_t * Super2_ManStart(); +static void Super2_ManStop( Super2_Man_t * pMan ); +static Super2_Lib_t * Super2_LibStart(); +static Super2_Lib_t * Super2_LibDup( Super2_Lib_t * pLib ); +static void Super2_LibStop( Super2_Lib_t * pLib ); +static void Super2_LibAddGate( Super2_Lib_t * pLib, Super2_Gate_t * pGate ); +static Super2_Lib_t * Super2_LibFirst( Super2_Man_t * pMan, int nInputs ); +static Super2_Lib_t * Super2_LibCompute( Super2_Man_t * pMan, Super2_Lib_t * pLib ); + +static void Super2_LibWrite( Super2_Lib_t * pLib ); +static void Super2_LibWriteGate( FILE * pFile, Super2_Lib_t * pLib, Super2_Gate_t * pGate ); +static char * Super2_LibWriteGate_rec( Super2_Gate_t * pGate, int fInv, int Level ); +static int Super2_LibWriteCompare( char * pStr1, char * pStr2 ); +static int Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Precomputes the library of AND2 gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super2_Precompute( int nInputs, int nLevels, int fVerbose ) +{ + Super2_Man_t * pMan; + Super2_Lib_t * pLibCur, * pLibNext; + int Level; + int clk; + + assert( nInputs < 6 ); + + // start the manager + pMan = Super2_ManStart(); + + // get the starting supergates + pLibCur = Super2_LibFirst( pMan, nInputs ); + + // perform the computation of supergates +printf( "Computing supergates for %d inputs and %d levels:\n", nInputs, nLevels ); + for ( Level = 1; Level <= nLevels; Level++ ) + { +clk = clock(); + pLibNext = Super2_LibCompute( pMan, pLibCur ); + pLibNext->nLevels = Level; + Super2_LibStop( pLibCur ); + pLibCur = pLibNext; +printf( "Level %d: Tried = %7d. Computed = %7d. ", Level, pMan->nTried, pLibCur->nGates ); +PRT( "Runtime", clock() - clk ); +fflush( stdout ); + } + +printf( "Writing the output file...\n" ); +fflush( stdout ); + // write them into a file + Super2_LibWrite( pLibCur ); + Super2_LibStop( pLibCur ); + + // stop the manager + Super2_ManStop( pMan ); +} + + + + +/**Function************************************************************* + + Synopsis [Starts the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Super2_Man_t * Super2_ManStart() +{ + Super2_Man_t * pMan; + pMan = ALLOC( Super2_Man_t, 1 ); + memset( pMan, 0, sizeof(Super2_Man_t) ); + pMan->pMem = Extra_MmFixedStart( sizeof(Super2_Gate_t) ); + pMan->tTable = stmm_init_table( st_ptrcmp, st_ptrhash ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Stops the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super2_ManStop( Super2_Man_t * pMan ) +{ + Extra_MmFixedStop( pMan->pMem ); + stmm_free_table( pMan->tTable ); + free( pMan ); +} + +/**Function************************************************************* + + Synopsis [Starts the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Super2_Lib_t * Super2_LibStart() +{ + Super2_Lib_t * pLib; + pLib = ALLOC( Super2_Lib_t, 1 ); + memset( pLib, 0, sizeof(Super2_Lib_t) ); + return pLib; +} + +/**Function************************************************************* + + Synopsis [Duplicates the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Super2_Lib_t * Super2_LibDup( Super2_Lib_t * pLib ) +{ + Super2_Lib_t * pLibNew; + pLibNew = Super2_LibStart(); + pLibNew->nInputs = pLib->nInputs; + pLibNew->nMints = pLib->nMints; + pLibNew->nLevels = pLib->nLevels; + pLibNew->nGates = pLib->nGates; + pLibNew->uMaskBit = pLib->uMaskBit; + pLibNew->nGatesAlloc = 1000 + pLib->nGatesAlloc; + pLibNew->pGates = ALLOC( Super2_Gate_t *, pLibNew->nGatesAlloc ); + memcpy( pLibNew->pGates, pLib->pGates, pLibNew->nGates * sizeof(Super2_Gate_t *) ); + return pLibNew; +} + +/**Function************************************************************* + + Synopsis [Add gate to the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super2_LibAddGate( Super2_Lib_t * pLib, Super2_Gate_t * pGate ) +{ + if ( pLib->nGates == pLib->nGatesAlloc ) + { + pLib->pGates = REALLOC( Super2_Gate_t *, pLib->pGates, 3 * pLib->nGatesAlloc ); + pLib->nGatesAlloc *= 3; + } + pLib->pGates[ pLib->nGates++ ] = pGate; +} + +/**Function************************************************************* + + Synopsis [Stops the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super2_LibStop( Super2_Lib_t * pLib ) +{ + free( pLib->pGates ); + free( pLib ); +} + +/**Function************************************************************* + + Synopsis [Derives the starting supergates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Super2_Lib_t * Super2_LibFirst( Super2_Man_t * pMan, int nInputs ) +{ + Super2_Lib_t * pLib; + int v, m; + + // start the library + pLib = Super2_LibStart(); + + // create the starting supergates + pLib->nInputs = nInputs; + pLib->nMints = (1 << nInputs); + pLib->nLevels = 0; + pLib->nGates = nInputs + 1; + pLib->nGatesAlloc = nInputs + 1; + pLib->uMaskBit = (1 << (pLib->nMints-1)); + pLib->pGates = ALLOC( Super2_Gate_t *, nInputs + 1 ); + // add the constant 0 + pLib->pGates[0] = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); + memset( pLib->pGates[0], 0, sizeof(Super2_Gate_t) ); + // add the elementary gates + for ( v = 0; v < nInputs; v++ ) + { + pLib->pGates[v+1] = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); + memset( pLib->pGates[v+1], 0, sizeof(Super2_Gate_t) ); + pLib->pGates[v+1]->pTwo = (Super2_Gate_t *)v; + } + + // set up their truth tables + for ( m = 0; m < pLib->nMints; m++ ) + for ( v = 0; v < nInputs; v++ ) + if ( m & (1 << v) ) + pLib->pGates[v+1]->uTruth |= (1 << m); + return pLib; +} + +/**Function************************************************************* + + Synopsis [Precomputes one level of supergates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Super2_Lib_t * Super2_LibCompute( Super2_Man_t * pMan, Super2_Lib_t * pLib ) +{ + Super2_Lib_t * pLibNew; + Super2_Gate_t * pGate1, * pGate2, * pGateNew; + Super2_Gate_t ** ppGate; + unsigned Mask = SUPER_MASK(pLib->nMints); + unsigned uTruth, uTruthR, uTruth1, uTruth2, uTruth1c, uTruth2c; + + // start the new library + pLibNew = Super2_LibDup( pLib ); + + // reset the hash table + stmm_free_table( pMan->tTable ); + pMan->tTable = stmm_init_table( st_ptrcmp, st_ptrhash ); + // set the starting things into the hash table + Super2_LibForEachGate( pLibNew, pGate1 ) + { + uTruthR = ((pGate1->uTruth & pLibNew->uMaskBit)? Mask & ~pGate1->uTruth : pGate1->uTruth); + + if ( stmm_lookup( pMan->tTable, (char *)uTruthR, (char **)&pGate2 ) ) + { + printf( "New gate:\n" ); + Super2_LibWriteGate( stdout, pLibNew, pGate1 ); + printf( "Gate in the table:\n" ); + Super2_LibWriteGate( stdout, pLibNew, pGate2 ); + assert( 0 ); + } + stmm_insert( pMan->tTable, (char *)uTruthR, (char *)pGate1 ); + } + + + // set the number of gates tried + pMan->nTried = pLibNew->nGates; + + // go through the gate pairs + Super2_LibForEachGate( pLib, pGate1 ) + { + if ( pLib->i && pLib->i % 300 == 0 ) + { + printf( "Tried %5d first gates...\n", pLib->i ); + fflush( stdout ); + } + + Super2_LibForEachGate2( pLib, pGate2 ) + { + uTruth1 = pGate1->uTruth; + uTruth2 = pGate2->uTruth; + uTruth1c = Mask & ~uTruth1; + uTruth2c = Mask & ~uTruth2; + + // none complemented + uTruth = uTruth1 & uTruth2; + uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); + + if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) ) + { + pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); + pGateNew->pOne = pGate1; + pGateNew->pTwo = pGate2; + pGateNew->uTruth = uTruth; + *ppGate = pGateNew; + Super2_LibAddGate( pLibNew, pGateNew ); + } + + // one complemented + uTruth = uTruth1c & uTruth2; + uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); + + if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) ) + { + pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); + pGateNew->pOne = Super2_Not(pGate1); + pGateNew->pTwo = pGate2; + pGateNew->uTruth = uTruth; + *ppGate = pGateNew; + Super2_LibAddGate( pLibNew, pGateNew ); + } + + // another complemented + uTruth = uTruth1 & uTruth2c; + uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); + + if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) ) + { + pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); + pGateNew->pOne = pGate1; + pGateNew->pTwo = Super2_Not(pGate2); + pGateNew->uTruth = uTruth; + *ppGate = pGateNew; + Super2_LibAddGate( pLibNew, pGateNew ); + } + + // both complemented + uTruth = uTruth1c & uTruth2c; + uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); + + if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) ) + { + pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); + pGateNew->pOne = Super2_Not(pGate1); + pGateNew->pTwo = Super2_Not(pGate2); + pGateNew->uTruth = uTruth; + *ppGate = pGateNew; + Super2_LibAddGate( pLibNew, pGateNew ); + } + + pMan->nTried += 4; + } + } + return pLibNew; +} + + +static unsigned s_uMaskBit; +static unsigned s_uMaskAll; + +/**Function************************************************************* + + Synopsis [Writes the library into the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super2_LibWrite( Super2_Lib_t * pLib ) +{ + Super2_Gate_t * pGate; + FILE * pFile; + char FileName[100]; + int clk; + + if ( pLib->nLevels > 5 ) + { + printf( "Cannot write file for %d levels.\n", pLib->nLevels ); + return; + } + +clk = clock(); + // sort the supergates by truth table + s_uMaskBit = pLib->uMaskBit; + s_uMaskAll = SUPER_MASK(pLib->nMints); + qsort( (void *)pLib->pGates, pLib->nGates, sizeof(Super2_Gate_t *), + (int (*)(const void *, const void *)) Super2_LibCompareGates ); + assert( Super2_LibCompareGates( pLib->pGates, pLib->pGates + pLib->nGates - 1 ) < 0 ); +PRT( "Sorting", clock() - clk ); + + + // start the file + sprintf( FileName, "superI%dL%d", pLib->nInputs, pLib->nLevels ); + pFile = fopen( FileName, "w" ); + fprintf( pFile, "# AND2/INV supergates derived on %s.\n", Extra_TimeStamp() ); + fprintf( pFile, "# Command line: \"super2 -i %d -l %d\".\n", pLib->nInputs, pLib->nLevels ); + fprintf( pFile, "# The number of inputs = %6d.\n", pLib->nInputs ); + fprintf( pFile, "# The number of levels = %6d.\n", pLib->nLevels ); + fprintf( pFile, "# The number of supergates = %6d.\n", pLib->nGates ); + fprintf( pFile, "# The total functions = %6d.\n", (1<<(pLib->nMints-1)) ); + fprintf( pFile, "\n" ); + fprintf( pFile, "%6d\n", pLib->nGates ); + + // print the gates + Super2_LibForEachGate( pLib, pGate ) + Super2_LibWriteGate( pFile, pLib, pGate ); + fclose( pFile ); + + printf( "The supergates are written into file \"%s\" ", FileName ); + printf( "(%0.2f Mb).\n", ((double)Extra_FileSize(FileName))/(1<<20) ); +} + +/**Function************************************************************* + + Synopsis [Writes the gate into the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 ) +{ + Super2_Gate_t * pG1 = *ppG1; + Super2_Gate_t * pG2 = *ppG2; + unsigned uTruth1, uTruth2; + + uTruth1 = (pG1->uTruth & s_uMaskBit)? s_uMaskAll & ~pG1->uTruth : pG1->uTruth; + uTruth2 = (pG2->uTruth & s_uMaskBit)? s_uMaskAll & ~pG2->uTruth : pG2->uTruth; + + if ( uTruth1 < uTruth2 ) + return -1; + return 1; +} + +/**Function************************************************************* + + Synopsis [Writes the gate into the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super2_LibWriteGate( FILE * pFile, Super2_Lib_t * pLib, Super2_Gate_t * pGate ) +{ +// unsigned uTruthR; + unsigned uTruth; + int fInv; + + // check whether the gate need complementation + fInv = (int)(pGate->uTruth & pLib->uMaskBit); + uTruth = (fInv? ~pGate->uTruth : pGate->uTruth); +/* + // reverse the truth table + uTruthR = 0; + for ( m = 0; m < pLib->nMints; m++ ) + if ( uTruth & (1 << m) ) + uTruthR |= (1 << (pLib->nMints-1-m)); +*/ + // write the truth table + Extra_PrintBinary( pFile, &uTruth, pLib->nMints ); + fprintf( pFile, " " ); + // write the symbolic expression + fprintf( pFile, "%s", Super2_LibWriteGate_rec( pGate, fInv, pLib->nLevels ) ); + fprintf( pFile, "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Recursively writes the gate into the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Super2_LibWriteGate_rec( Super2_Gate_t * pGate, int fInv, int Level ) +{ + static char Buff01[ 3], Buff02[ 3]; // Max0 = 1 + static char Buff11[ 6], Buff12[ 6]; // Max1 = 2*Max0 + 2 = 4 + static char Buff21[ 12], Buff22[ 12]; // Max2 = 2*Max1 + 2 = 10 + static char Buff31[ 25], Buff32[ 25]; // Max3 = 2*Max2 + 2 = 22 + static char Buff41[ 50], Buff42[ 50]; // Max4 = 2*Max3 + 2 = 46 + static char Buff51[100], Buff52[100]; // Max5 = 2*Max4 + 2 = 94 + static char * pBuffs1[6] = { Buff01, Buff11, Buff21, Buff31, Buff41, Buff51 }; + static char * pBuffs2[6] = { Buff02, Buff12, Buff22, Buff32, Buff42, Buff52 }; + char * pBranch; + char * pBuffer1 = pBuffs1[Level]; + char * pBuffer2 = pBuffs2[Level]; + Super2_Gate_t * pGateNext1, * pGateNext2; + int fInvNext1, fInvNext2; + int RetValue; + + // consider the last level + assert( Level >= 0 ); + if ( pGate->pOne == NULL ) + { + if ( pGate->uTruth == 0 ) + { + pBuffer1[0] = (fInv? '1': '0'); + pBuffer1[1] = '$'; + pBuffer1[2] = 0; + } + else + { + pBuffer1[0] = (fInv? 'A' + ((int)pGate->pTwo): 'a' + ((int)pGate->pTwo)); + pBuffer1[1] = 0; + } + return pBuffer1; + } + assert( Level > 0 ); + + + // get the left branch + pGateNext1 = Super2_Regular(pGate->pOne); + fInvNext1 = Super2_IsComplement(pGate->pOne); + pBranch = Super2_LibWriteGate_rec(pGateNext1, fInvNext1, Level - 1); + // copy into Buffer1 + strcpy( pBuffer1, pBranch ); + + // get the right branch + pGateNext2 = Super2_Regular(pGate->pTwo); + fInvNext2 = Super2_IsComplement(pGate->pTwo); + pBranch = Super2_LibWriteGate_rec(pGateNext2, fInvNext2, Level - 1); + + // consider the case when comparison is not necessary + if ( fInvNext1 ^ fInvNext2 ) + { + if ( fInvNext1 > fInvNext2 ) + sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBuffer1, pBranch, (fInv? '>': ')') ); + else + sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBranch, pBuffer1, (fInv? '>': ')') ); + } + else + { + // compare the two branches + RetValue = Super2_LibWriteCompare( pBuffer1, pBranch ); + if ( RetValue == 1 ) + sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBuffer1, pBranch, (fInv? '>': ')') ); + else // if ( RetValue == -1 ) + { + sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBranch, pBuffer1, (fInv? '>': ')') ); + if ( RetValue == 0 ) + printf( "Strange!\n" ); + } + } + return pBuffer2; +} + +/**Function************************************************************* + + Synopsis [Compares the two branches of the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Super2_LibWriteCompare( char * pStr1, char * pStr2 ) +{ + while ( 1 ) + { + // skip extra symbols + while ( *pStr1 && *pStr1 < 'A' ) + pStr1++; + while ( *pStr2 && *pStr2 < 'A' ) + pStr2++; + + // check if any one is finished + if ( *pStr1 == 0 || *pStr2 == 0 ) + { + if ( *pStr2 ) + return 1; + return -1; + } + + // compare + if ( *pStr1 == *pStr2 ) + { + pStr1++; + pStr2++; + } + else + { + if ( *pStr1 < *pStr2 ) + return 1; + return -1; + } + } + return 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/super/superGENERIC.c b/abc70930/src/map/super/superGENERIC.c new file mode 100644 index 00000000..1f2b7651 --- /dev/null +++ b/abc70930/src/map/super/superGENERIC.c @@ -0,0 +1,46 @@ +/**CFile**************************************************************** + + FileName [super__.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Pre-computation of supergates.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: super__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "superInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/map/super/superGate.c b/abc70930/src/map/super/superGate.c new file mode 100644 index 00000000..91a1e513 --- /dev/null +++ b/abc70930/src/map/super/superGate.c @@ -0,0 +1,1324 @@ +/**CFile**************************************************************** + + FileName [superGate.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Pre-computation of supergates.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: superGate.c,v 1.7 2004/08/03 00:11:40 satrajit Exp $] + +***********************************************************************/ + +#include "superInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the bit masks +#define SUPER_MASK(n) ((~((unsigned)0)) >> (32-(n))) +#define SUPER_FULL (~((unsigned)0)) +#define SUPER_NO_VAR (-9999.0) +#define SUPER_EPSILON (0.001) + +// data structure for supergate precomputation +typedef struct Super_ManStruct_t_ Super_Man_t; // manager +typedef struct Super_GateStruct_t_ Super_Gate_t; // supergate + +struct Super_ManStruct_t_ +{ + // parameters + char * pName; // the original genlib file name + int nVarsMax; // the number of inputs + int nMints; // the number of minterms + int nLevels; // the number of logic levels + float tDelayMax; // the max delay of the supergates in the library + float tAreaMax; // the max area of the supergates in the library + int fSkipInv; // the flag says about skipping inverters + int fWriteOldFormat; // in addition, writes the file in the old format + int fVerbose; + + // supergates + Super_Gate_t * pInputs[10]; // the input supergates + int nGates; // the number of gates in the library + Super_Gate_t ** pGates; // the gates themselves + stmm_table * tTable; // mapping of truth tables into gates + + // memory managers + Extra_MmFixed_t * pMem; // memory manager for the supergates + Extra_MmFlex_t * pMemFlex; // memory manager for the fanin arrays + + // statistics + int nTried; // the total number of tried + int nAdded; // the number of entries added + int nRemoved; // the number of entries removed + int nUnique; // the number of unique gates + int nLookups; // the number of hash table lookups + int nAliases; // the number of hash table lookups thrown away due to aliasing + + // runtime + int Time; // the runtime of the generation procedure + int TimeLimit; // the runtime limit (in seconds) + int TimeSec; // the time passed (in seconds) + int TimeStop; // the time to stop computation (in miliseconds) + int TimePrint; // the time to print message +}; + +struct Super_GateStruct_t_ +{ + Mio_Gate_t * pRoot; // the root gate for this supergate + unsigned fVar : 1; // the flag signaling the elementary variable + unsigned fSuper : 1; // the flag signaling the elementary variable + unsigned nFanins : 6; // the number of fanin gates + unsigned Number : 24; // the number assigned in the process + unsigned uTruth[2]; // the truth table of this supergate + Super_Gate_t * pFanins[6]; // the fanins of the gate + float Area; // the area of this gate + float ptDelays[6]; // the pin-to-pin delays for all inputs + float tDelayMax; // the maximum delay + Super_Gate_t * pNext; // the next gate in the table +}; + + +// iterating through the gates in the library +#define Super_ManForEachGate( GateArray, Limit, Index, Gate ) \ + for ( Index = 0; \ + Index < Limit && (Gate = GateArray[Index]); \ + Index++ ) + +// static functions +static Super_Man_t * Super_ManStart(); +static void Super_ManStop( Super_Man_t * pMan ); + +static void Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate ); +static void Super_First( Super_Man_t * pMan, int nVarsMax ); +static Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, bool fSkipInv ); +static Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers, unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins ); +static bool Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins ); +static int Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); +static int Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); +static void Super_TranferGatesToArray( Super_Man_t * pMan ); +static int Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan ); + +static void Super_Write( Super_Man_t * pMan ); +static int Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); +static void Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile ); + +static void Super_WriteLibrary( Super_Man_t * pMan ); +static void Super_WriteLibraryGate( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pGate, int Num ); +static char * Super_WriteLibraryGateName( Super_Gate_t * pGate ); +static void Super_WriteLibraryGateName_rec( Super_Gate_t * pGate, char * pBuffer ); + +static void Super_WriteLibraryTree( Super_Man_t * pMan ); +static void Super_WriteLibraryTree_rec( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Precomputes the library of supergates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_Precompute( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, float tDelayMax, float tAreaMax, int TimeLimit, bool fSkipInv, bool fWriteOldFormat, int fVerbose ) +{ + Super_Man_t * pMan; + Mio_Gate_t ** ppGates; + int nGates, Level, clk, clockStart; + + assert( nVarsMax < 7 ); + + // get the root gates + ppGates = Mio_CollectRoots( pLibGen, nVarsMax, tDelayMax, 0, &nGates ); + + // start the manager + pMan = Super_ManStart(); + pMan->pName = Mio_LibraryReadName(pLibGen); + pMan->fSkipInv = fSkipInv; + pMan->tDelayMax = tDelayMax; + pMan->tAreaMax = tAreaMax; + pMan->TimeLimit = TimeLimit; // in seconds + pMan->TimeStop = TimeLimit * CLOCKS_PER_SEC + clock(); // in CPU ticks + pMan->fWriteOldFormat = fWriteOldFormat; + pMan->fVerbose = fVerbose; + + if ( nGates == 0 ) + { + fprintf( stderr, "Error: No genlib gates satisfy the limits criteria. Stop.\n"); + fprintf( stderr, "Limits: max delay = %.2f, max area = %.2f, time limit = %d sec.\n", + pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit ); + + // stop the manager + Super_ManStop( pMan ); + free( ppGates ); + + return; + } + + // get the starting supergates + Super_First( pMan, nVarsMax ); + + // perform the computation of supergates + clockStart = clock(); +if ( fVerbose ) +{ + printf( "Computing supergates with %d inputs and %d levels.\n", + pMan->nVarsMax, nLevels ); + printf( "Limits: max delay = %.2f, max area = %.2f, time limit = %d sec.\n", + pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit ); +} + + for ( Level = 1; Level <= nLevels; Level++ ) + { + if ( clock() > pMan->TimeStop ) + break; +clk = clock(); + Super_Compute( pMan, ppGates, nGates, fSkipInv ); + pMan->nLevels = Level; +if ( fVerbose ) +{ + printf( "Lev %d: Try =%12d. Add =%6d. Rem =%5d. Save =%6d. Lookups =%12d. Aliases =%12d. ", + Level, pMan->nTried, pMan->nAdded, pMan->nRemoved, pMan->nAdded - pMan->nRemoved, pMan->nLookups, pMan->nAliases ); +PRT( "Time", clock() - clk ); +fflush( stdout ); +} + } + pMan->Time = clock() - clockStart; + +if ( fVerbose ) +{ +printf( "Writing the output file...\n" ); +fflush( stdout ); +} + // write them into a file + Super_Write( pMan ); + + // stop the manager + Super_ManStop( pMan ); + free( ppGates ); +} + + +/**Function************************************************************* + + Synopsis [Derives the starting supergates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_First( Super_Man_t * pMan, int nVarsMax ) +{ + Super_Gate_t * pSuper; + int nMintLimit, nVarLimit; + int v, m; + // set the parameters + pMan->nVarsMax = nVarsMax; + pMan->nMints = (1 << nVarsMax); + pMan->nLevels = 0; + // allocate room for the gates + pMan->nGates = nVarsMax; + pMan->pGates = ALLOC( Super_Gate_t *, nVarsMax + 2 ); + // create the gates corresponding to the elementary variables + for ( v = 0; v < nVarsMax; v++ ) + { + // get a new gate + pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); + memset( pSuper, 0, sizeof(Super_Gate_t) ); + // assign the elementary variable, the truth table, and the delays + pSuper->fVar = 1; + pSuper->Number = v; + for ( m = 0; m < nVarsMax; m++ ) + pSuper->ptDelays[m] = SUPER_NO_VAR; + pSuper->ptDelays[v] = 0.0; + // set the gate + pMan->pGates[v] = pSuper; + Super_AddGateToTable( pMan, pSuper ); + pMan->pInputs[v] = pSuper; + } + // set up their truth tables + nVarLimit = (nVarsMax >= 5)? 5 : nVarsMax; + nMintLimit = (1 << nVarLimit); + for ( m = 0; m < nMintLimit; m++ ) + for ( v = 0; v < nVarLimit; v++ ) + if ( m & (1 << v) ) + pMan->pGates[v]->uTruth[0] |= (1 << m); + // make adjustments for the case of 6 variables + if ( nVarsMax == 6 ) + { + for ( v = 0; v < 5; v++ ) + pMan->pGates[v]->uTruth[1] = pMan->pGates[v]->uTruth[0]; + pMan->pGates[5]->uTruth[0] = 0; + pMan->pGates[5]->uTruth[1] = ~((unsigned)0); + } + else + { + for ( v = 0; v < nVarsMax; v++ ) + pMan->pGates[v]->uTruth[1] = 0; + } +} + +/**Function************************************************************* + + Synopsis [Precomputes one level of supergates.] + + Description [This procedure computes the set of supergates that can be + derived from the given set of root gates (from GENLIB library) by composing + the root gates with the currently available supergates. This procedure is + smart in the sense that it tries to avoid useless emuration by imposing + tight bounds by area and delay. Only the supergates and are guaranteed to + have smaller area and delay are enumereated. See comments below for details.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, bool fSkipInv ) +{ + Super_Gate_t * pSupers[6], * pGate0, * pGate1, * pGate2, * pGate3, * pGate4, * pGate5, * pGateNew; + float tPinDelaysRes[6], * ptPinDelays[6], tPinDelayMax, tDelayMio; + float Area, Area0, Area1, Area2, Area3, Area4, AreaMio; + unsigned uTruth[2], uTruths[6][2]; + int i0, i1, i2, i3, i4, i5; + Super_Gate_t ** ppGatesLimit; + int nFanins, nGatesLimit, k, s, t; + ProgressBar * pProgress; + int fTimeOut; + int fPrune = 1; // Shall we prune? + int iPruneLimit = 3; // Each of the gates plugged into the root gate will have + // less than these many fanins + int iPruneLimitRoot = 4; // The root gate may have only less than these many fanins + + // put the gates from the unique table into the array + // the gates from the array will be used to compose other gates + // the gates in tbe table are used to check uniqueness of collected gates + Super_TranferGatesToArray( pMan ); + + // sort the gates in the increasing order of maximum delay + if ( pMan->nGates > 10000 ) + { + printf( "Sorting array of %d supergates...\r", pMan->nGates ); + fflush( stdout ); + } + qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *), + (int (*)(const void *, const void *)) Super_DelayCompare ); + assert( Super_DelayCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 ); + if ( pMan->nGates > 10000 ) + { + printf( " \r" ); + } + + pProgress = Extra_ProgressBarStart( stdout, pMan->TimeLimit ); + pMan->TimePrint = clock() + CLOCKS_PER_SEC; + ppGatesLimit = ALLOC( Super_Gate_t *, pMan->nGates ); + // go through the root gates + // the root gates are sorted in the increasing gelay + fTimeOut = 0; + for ( k = 0; k < nGates; k++ ) + { + if ( fTimeOut ) break; + + if ( fPrune ) + { + if ( pMan->nLevels >= 1 ) // First level gates have been computed + { + if ( Mio_GateReadInputs(ppGates[k]) >= iPruneLimitRoot ) + continue; + } + } + + // select the subset of gates to be considered with this root gate + // all the gates past this point will lead to delay larger than the limit + tDelayMio = (float)Mio_GateReadDelayMax(ppGates[k]); + for ( s = 0, t = 0; s < pMan->nGates; s++ ) + { + if ( fPrune && ( pMan->nLevels >= 1 ) && ( ((int)pMan->pGates[s]->nFanins) >= iPruneLimit )) + continue; + + ppGatesLimit[t] = pMan->pGates[s]; + if ( ppGatesLimit[t++]->tDelayMax + tDelayMio > pMan->tDelayMax ) + break; + } + nGatesLimit = t; + + if ( pMan->fVerbose ) + { + printf ("Trying %d choices for %d inputs\n", t, Mio_GateReadInputs(ppGates[k]) ); + } + + // resort part of this range by area + // now we can prune the search by going up in the list until we reach the limit on area + // all the gates beyond this point can be skipped because their area can be only larger + if ( nGatesLimit > 10000 ) + printf( "Sorting array of %d supergates...\r", nGatesLimit ); + qsort( (void *)ppGatesLimit, nGatesLimit, sizeof(Super_Gate_t *), + (int (*)(const void *, const void *)) Super_AreaCompare ); + assert( Super_AreaCompare( ppGatesLimit, ppGatesLimit + nGatesLimit - 1 ) <= 0 ); + if ( nGatesLimit > 10000 ) + printf( " \r" ); + + // consider the combinations of gates with the root gate on top + AreaMio = (float)Mio_GateReadArea(ppGates[k]); + nFanins = Mio_GateReadInputs(ppGates[k]); + switch ( nFanins ) + { + case 0: // should not happen + assert( 0 ); + break; + case 1: // interter root + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) + { + if ( fTimeOut ) break; + fTimeOut = Super_CheckTimeout( pProgress, pMan ); + // skip the inverter as the root gate before the elementary variable + // as a result, the supergates will not have inverters on the input side + // but inverters still may occur at the output of or inside complex supergates + if ( fSkipInv && pGate0->tDelayMax == 0 ) + continue; + // compute area + Area = AreaMio + pGate0->Area; + if ( Area > pMan->tAreaMax ) + break; + + pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; + Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); + Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); + if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) + continue; + // create a new gate + pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); + Super_AddGateToTable( pMan, pGateNew ); + } + break; + case 2: // two-input root gate + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) + { + Area0 = AreaMio + pGate0->Area; + if ( Area0 > pMan->tAreaMax ) + break; + pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) + if ( i1 != i0 ) + { + if ( fTimeOut ) goto done; + fTimeOut = Super_CheckTimeout( pProgress, pMan ); + // compute area + Area = Area0 + pGate1->Area; + if ( Area > pMan->tAreaMax ) + break; + + pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; + Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); + Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); + if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) + continue; + // create a new gate + pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); + Super_AddGateToTable( pMan, pGateNew ); + } + } + break; + case 3: // three-input root gate + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) + { + Area0 = AreaMio + pGate0->Area; + if ( Area0 > pMan->tAreaMax ) + break; + pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) + if ( i1 != i0 ) + { + Area1 = Area0 + pGate1->Area; + if ( Area1 > pMan->tAreaMax ) + break; + pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) + if ( i2 != i0 && i2 != i1 ) + { + if ( fTimeOut ) goto done; + fTimeOut = Super_CheckTimeout( pProgress, pMan ); + // compute area + Area = Area1 + pGate2->Area; + if ( Area > pMan->tAreaMax ) + break; + pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; + + Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); + Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); + if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) + continue; + // create a new gate + pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); + Super_AddGateToTable( pMan, pGateNew ); + } + } + } + break; + case 4: // four-input root gate + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) + { + Area0 = AreaMio + pGate0->Area; + if ( Area0 > pMan->tAreaMax ) + break; + pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) + if ( i1 != i0 ) + { + Area1 = Area0 + pGate1->Area; + if ( Area1 > pMan->tAreaMax ) + break; + pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) + if ( i2 != i0 && i2 != i1 ) + { + Area2 = Area1 + pGate2->Area; + if ( Area2 > pMan->tAreaMax ) + break; + pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) + if ( i3 != i0 && i3 != i1 && i3 != i2 ) + { + if ( fTimeOut ) goto done; + fTimeOut = Super_CheckTimeout( pProgress, pMan ); + // compute area + Area = Area2 + pGate3->Area; + if ( Area > pMan->tAreaMax ) + break; + pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; + + Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); + Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); + if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) + continue; + // create a new gate + pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); + Super_AddGateToTable( pMan, pGateNew ); + } + } + } + } + break; + case 5: // five-input root gate + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) + { + Area0 = AreaMio + pGate0->Area; + if ( Area0 > pMan->tAreaMax ) + break; + pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) + if ( i1 != i0 ) + { + Area1 = Area0 + pGate1->Area; + if ( Area1 > pMan->tAreaMax ) + break; + pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) + if ( i2 != i0 && i2 != i1 ) + { + Area2 = Area1 + pGate2->Area; + if ( Area2 > pMan->tAreaMax ) + break; + pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) + if ( i3 != i0 && i3 != i1 && i3 != i2 ) + { + Area3 = Area2 + pGate3->Area; + if ( Area3 > pMan->tAreaMax ) + break; + pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 ) + if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 ) + { + if ( fTimeOut ) goto done; + fTimeOut = Super_CheckTimeout( pProgress, pMan ); + // compute area + Area = Area3 + pGate4->Area; + if ( Area > pMan->tAreaMax ) + break; + pSupers[4] = pGate4; uTruths[4][0] = pGate4->uTruth[0]; uTruths[4][1] = pGate4->uTruth[1]; ptPinDelays[4] = pGate4->ptDelays; + + Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); + Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); + if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) + continue; + // create a new gate + pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); + Super_AddGateToTable( pMan, pGateNew ); + } + } + } + } + } + break; + case 6: // six-input root gate + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) + { + Area0 = AreaMio + pGate0->Area; + if ( Area0 > pMan->tAreaMax ) + break; + pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) + if ( i1 != i0 ) + { + Area1 = Area0 + pGate1->Area; + if ( Area1 > pMan->tAreaMax ) + break; + pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) + if ( i2 != i0 && i2 != i1 ) + { + Area2 = Area1 + pGate2->Area; + if ( Area2 > pMan->tAreaMax ) + break; + pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) + if ( i3 != i0 && i3 != i1 && i3 != i2 ) + { + Area3 = Area2 + pGate3->Area; + if ( Area3 > pMan->tAreaMax ) + break; + pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 ) + if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 ) + { + if ( fTimeOut ) break; + fTimeOut = Super_CheckTimeout( pProgress, pMan ); + // compute area + Area4 = Area3 + pGate4->Area; + if ( Area > pMan->tAreaMax ) + break; + pSupers[4] = pGate4; uTruths[4][0] = pGate4->uTruth[0]; uTruths[4][1] = pGate4->uTruth[1]; ptPinDelays[4] = pGate4->ptDelays; + + Super_ManForEachGate( ppGatesLimit, nGatesLimit, i5, pGate5 ) + if ( i5 != i0 && i5 != i1 && i5 != i2 && i5 != i3 && i5 != i4 ) + { + if ( fTimeOut ) goto done; + fTimeOut = Super_CheckTimeout( pProgress, pMan ); + // compute area + Area = Area4 + pGate5->Area; + if ( Area > pMan->tAreaMax ) + break; + pSupers[5] = pGate5; uTruths[5][0] = pGate5->uTruth[0]; uTruths[5][1] = pGate5->uTruth[1]; ptPinDelays[5] = pGate5->ptDelays; + + Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); + Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); + if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) + continue; + // create a new gate + pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); + Super_AddGateToTable( pMan, pGateNew ); + } + } + } + } + } + } + break; + default : + assert( 0 ); + break; + } + } +done: + Extra_ProgressBarStop( pProgress ); + free( ppGatesLimit ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Transfers gates from table into the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan ) +{ + int TimeNow = clock(); + if ( TimeNow > pMan->TimePrint ) + { + Extra_ProgressBarUpdate( pPro, ++pMan->TimeSec, NULL ); + pMan->TimePrint = clock() + CLOCKS_PER_SEC; + } + if ( TimeNow > pMan->TimeStop ) + { + printf ("Timeout!\n"); + return 1; + } + pMan->nTried++; + return 0; +} + + +/**Function************************************************************* + + Synopsis [Transfers gates from table into the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_TranferGatesToArray( Super_Man_t * pMan ) +{ + stmm_generator * gen; + Super_Gate_t * pGate, * pList; + unsigned Key; + + // put the gates fron the table into the array + free( pMan->pGates ); + pMan->pGates = ALLOC( Super_Gate_t *, pMan->nAdded ); + pMan->nGates = 0; + stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pList ) + { + for ( pGate = pList; pGate; pGate = pGate->pNext ) + pMan->pGates[ pMan->nGates++ ] = pGate; + } +// assert( pMan->nGates == pMan->nAdded - pMan->nRemoved ); +} + +/**Function************************************************************* + + Synopsis [Adds one supergate into the unique table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate ) +{ + Super_Gate_t ** ppList; + unsigned Key; +// Key = pGate->uTruth[0] + 2003 * pGate->uTruth[1]; + Key = pGate->uTruth[0] ^ pGate->uTruth[1]; + if ( !stmm_find_or_add( pMan->tTable, (char *)Key, (char ***)&ppList ) ) + *ppList = NULL; + pGate->pNext = *ppList; + *ppList = pGate; + pMan->nAdded++; +} + +/**Function************************************************************* + + Synopsis [Check the manager's unique table for comparable gates.] + + Description [Returns 0 if the gate is dominated by others. Returns 1 + if the gate is new or is better than the available ones. In this case, + cleans the table by removing the gates that are worse than the given one.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins ) +{ + Super_Gate_t ** ppList, * pPrev, * pGate, * pGate2; + int i, fNewIsBetter, fGateIsBetter; + unsigned Key; + + // skip constant functions + if ( pMan->nVarsMax < 6 ) + { + if ( uTruth[0] == 0 || ~uTruth[0] == 0 ) + return 0; + } + else + { + if ( ( uTruth[0] == 0 && uTruth[1] == 0 ) || ( ~uTruth[0] == 0 && ~uTruth[1] == 0 ) ) + return 0; + } + + // get hold of the place where the entry is stored +// Key = uTruth[0] + 2003 * uTruth[1]; + Key = uTruth[0] ^ uTruth[1]; + if ( !stmm_find( pMan->tTable, (char *)Key, (char ***)&ppList ) ) + return 1; + // the entry with this truth table is found + pPrev = NULL; + for ( pGate = *ppList, pGate2 = pGate? pGate->pNext: NULL; pGate; + pGate = pGate2, pGate2 = pGate? pGate->pNext: NULL ) + { + pMan->nLookups++; + if ( pGate->uTruth[0] != uTruth[0] || pGate->uTruth[1] != uTruth[1] ) + { + pMan->nAliases++; + continue; + } + fGateIsBetter = 0; + fNewIsBetter = 0; + if ( pGate->Area + SUPER_EPSILON < Area ) + fGateIsBetter = 1; + else if ( pGate->Area > Area + SUPER_EPSILON ) + fNewIsBetter = 1; + for ( i = 0; i < nPins; i++ ) + { + if ( pGate->ptDelays[i] == SUPER_NO_VAR || tPinDelaysRes[i] == SUPER_NO_VAR ) + continue; + if ( pGate->ptDelays[i] + SUPER_EPSILON < tPinDelaysRes[i] ) + fGateIsBetter = 1; + else if ( pGate->ptDelays[i] > tPinDelaysRes[i] + SUPER_EPSILON ) + fNewIsBetter = 1; + if ( fGateIsBetter && fNewIsBetter ) + break; + } + // consider 4 cases + if ( fGateIsBetter && fNewIsBetter ) // Pareto points; save both + pPrev = pGate; + else if ( fNewIsBetter ) // gate is worse; remove the gate + { + if ( pPrev == NULL ) + *ppList = pGate->pNext; + else + pPrev->pNext = pGate->pNext; + Extra_MmFixedEntryRecycle( pMan->pMem, (char *)pGate ); + pMan->nRemoved++; + } + else if ( fGateIsBetter ) // new is worse, already dominated no need to see others + return 0; + else // if ( !fGateIsBetter && !fNewIsBetter ) // they are identical, no need to see others + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Create a new supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers, + unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins ) +{ + Super_Gate_t * pSuper; + pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); + memset( pSuper, 0, sizeof(Super_Gate_t) ); + pSuper->pRoot = pRoot; + pSuper->uTruth[0] = uTruth[0]; + pSuper->uTruth[1] = uTruth[1]; + memcpy( pSuper->ptDelays, tPinDelaysRes, sizeof(float) * nPins ); + pSuper->Area = Area; + pSuper->nFanins = nSupers; + memcpy( pSuper->pFanins, pSupers, sizeof(Super_Gate_t *) * nSupers ); + pSuper->pNext = NULL; + pSuper->tDelayMax = tDelayMax; + return pSuper; +} + +/**Function************************************************************* + + Synopsis [Starts the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Super_Man_t * Super_ManStart() +{ + Super_Man_t * pMan; + pMan = ALLOC( Super_Man_t, 1 ); + memset( pMan, 0, sizeof(Super_Man_t) ); + pMan->pMem = Extra_MmFixedStart( sizeof(Super_Gate_t) ); + pMan->tTable = stmm_init_table( st_ptrcmp, st_ptrhash ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Stops the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_ManStop( Super_Man_t * pMan ) +{ + Extra_MmFixedStop( pMan->pMem ); + if ( pMan->tTable ) stmm_free_table( pMan->tTable ); + FREE( pMan->pGates ); + free( pMan ); +} + + + + + +/**Function************************************************************* + + Synopsis [Writes the supergate library into the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_Write( Super_Man_t * pMan ) +{ + Super_Gate_t * pGateRoot, * pGate; + stmm_generator * gen; + int fZeroFound, clk, v; + unsigned Key; + + if ( pMan->nGates < 1 ) + { + printf( "The generated library is empty. No output file written.\n" ); + return; + } + + // Filters the supergates by removing those that have fewer inputs than + // the given limit, provided that the inputs are not consequtive. + // For example, NAND2(a,c) is removed, but NAND2(a,b) is left, + // because a and b are consequtive. + FREE( pMan->pGates ); + pMan->pGates = ALLOC( Super_Gate_t *, pMan->nAdded ); + pMan->nGates = 0; + stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pGateRoot ) + { + for ( pGate = pGateRoot; pGate; pGate = pGate->pNext ) + { + // skip the elementary variables + if ( pGate->pRoot == NULL ) + continue; + // skip the non-consequtive gates + fZeroFound = 0; + for ( v = 0; v < pMan->nVarsMax; v++ ) + if ( pGate->ptDelays[v] < SUPER_NO_VAR + SUPER_EPSILON ) + fZeroFound = 1; + else if ( fZeroFound ) + break; + if ( v < pMan->nVarsMax ) + continue; + // save the unique gate + pMan->pGates[ pMan->nGates++ ] = pGate; + } + } + +clk = clock(); + // sort the supergates by truth table + qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *), + (int (*)(const void *, const void *)) Super_WriteCompare ); + assert( Super_WriteCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 ); +if ( pMan->fVerbose ) +{ +PRT( "Sorting", clock() - clk ); +} + + + // write library in the old format +clk = clock(); + if ( pMan->fWriteOldFormat ) + Super_WriteLibrary( pMan ); +if ( pMan->fVerbose ) +{ +PRT( "Writing old format", clock() - clk ); +} + + // write the tree-like structure of supergates +clk = clock(); + Super_WriteLibraryTree( pMan ); +if ( pMan->fVerbose ) +{ +PRT( "Writing new format", clock() - clk ); +} +} + + +/**Function************************************************************* + + Synopsis [Writes the file header.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile ) +{ + fprintf( pFile, "#\n" ); + fprintf( pFile, "# Supergate library derived for \"%s\" on %s.\n", pMan->pName, Extra_TimeStamp() ); + fprintf( pFile, "#\n" ); + fprintf( pFile, "# Command line: \"super -i %d -l %d -d %.2f -a %.2f -t %d %s %s\".\n", + pMan->nVarsMax, pMan->nLevels, pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit, (pMan->fSkipInv? "" : "-s"), pMan->pName ); + fprintf( pFile, "#\n" ); + fprintf( pFile, "# The number of inputs = %10d.\n", pMan->nVarsMax ); + fprintf( pFile, "# The number of levels = %10d.\n", pMan->nLevels ); + fprintf( pFile, "# The maximum delay = %10.2f.\n", pMan->tDelayMax ); + fprintf( pFile, "# The maximum area = %10.2f.\n", pMan->tAreaMax ); + fprintf( pFile, "# The maximum runtime (sec) = %10d.\n", pMan->TimeLimit ); + fprintf( pFile, "#\n" ); + fprintf( pFile, "# The number of attempts = %10d.\n", pMan->nTried ); + fprintf( pFile, "# The number of supergates = %10d.\n", pMan->nGates ); + fprintf( pFile, "# The number of functions = %10d.\n", pMan->nUnique ); + fprintf( pFile, "# The total functions = %.0f (2^%d).\n", pow(2,pMan->nMints), pMan->nMints ); + fprintf( pFile, "#\n" ); + fprintf( pFile, "# Generation time (sec) = %10.2f.\n", (float)(pMan->Time)/(float)(CLOCKS_PER_SEC) ); + fprintf( pFile, "#\n" ); + fprintf( pFile, "%s\n", pMan->pName ); + fprintf( pFile, "%d\n", pMan->nVarsMax ); + fprintf( pFile, "%d\n", pMan->nGates ); +} + +/**Function************************************************************* + + Synopsis [Compares the truth tables of two gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) +{ + unsigned * pTruth1 = (*ppG1)->uTruth; + unsigned * pTruth2 = (*ppG2)->uTruth; + if ( pTruth1[1] < pTruth2[1] ) + return -1; + if ( pTruth1[1] > pTruth2[1] ) + return 1; + if ( pTruth1[0] < pTruth2[0] ) + return -1; + if ( pTruth1[0] > pTruth2[0] ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Compares the max delay of two gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) +{ + if ( (*ppG1)->tDelayMax < (*ppG2)->tDelayMax ) + return -1; + if ( (*ppG1)->tDelayMax > (*ppG2)->tDelayMax ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Compares the area of two gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) +{ + if ( (*ppG1)->Area < (*ppG2)->Area ) + return -1; + if ( (*ppG1)->Area > (*ppG2)->Area ) + return 1; + return 0; +} + + + + + + +/**Function************************************************************* + + Synopsis [Writes the gates into the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_WriteLibrary( Super_Man_t * pMan ) +{ + Super_Gate_t * pGate, * pGateNext; + FILE * pFile; + char FileName[100]; + char * pNameGeneric; + int i, Counter; + + // get the file name + pNameGeneric = Extra_FileNameGeneric( pMan->pName ); + sprintf( FileName, "%s.super_old", pNameGeneric ); + free( pNameGeneric ); + + // count the number of unique functions + pMan->nUnique = 1; + Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate ) + { + if ( i == pMan->nGates - 1 ) + break; + // print the newline if this gate is different from the following one + pGateNext = pMan->pGates[i+1]; + if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] ) + pMan->nUnique++; + } + + // start the file + pFile = fopen( FileName, "w" ); + Super_WriteFileHeader( pMan, pFile ); + + // print the gates + Counter = 0; + Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate ) + { + Super_WriteLibraryGate( pFile, pMan, pGate, ++Counter ); + if ( i == pMan->nGates - 1 ) + break; + // print the newline if this gate is different from the following one + pGateNext = pMan->pGates[i+1]; + if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] ) + fprintf( pFile, "\n" ); + } + assert( Counter == pMan->nGates ); + fclose( pFile ); + +if ( pMan->fVerbose ) +{ + printf( "The supergates are written using old format \"%s\" ", FileName ); + printf( "(%0.3f Mb).\n", ((double)Extra_FileSize(FileName))/(1<<20) ); +} +} + +/**Function************************************************************* + + Synopsis [Writes the supergate into the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_WriteLibraryGate( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pGate, int Num ) +{ + int i; + fprintf( pFile, "%04d ", Num ); // the number + Extra_PrintBinary( pFile, pGate->uTruth, pMan->nMints ); // the truth table + fprintf( pFile, " %5.2f", pGate->tDelayMax ); // the max delay + fprintf( pFile, " " ); + for ( i = 0; i < pMan->nVarsMax; i++ ) // the pin-to-pin delays + fprintf( pFile, " %5.2f", pGate->ptDelays[i]==SUPER_NO_VAR? 0.0 : pGate->ptDelays[i] ); + fprintf( pFile, " %5.2f", pGate->Area ); // the area + fprintf( pFile, " " ); + fprintf( pFile, "%s", Super_WriteLibraryGateName(pGate) ); // the symbolic expression + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Recursively generates symbolic name of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Super_WriteLibraryGateName( Super_Gate_t * pGate ) +{ + static char Buffer[2000]; + Buffer[0] = 0; + Super_WriteLibraryGateName_rec( pGate, Buffer ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Recursively generates symbolic name of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_WriteLibraryGateName_rec( Super_Gate_t * pGate, char * pBuffer ) +{ + char Buffer[10]; + int i; + + if ( pGate->pRoot == NULL ) + { + sprintf( Buffer, "%c", 'a' + pGate->Number ); + strcat( pBuffer, Buffer ); + return; + } + strcat( pBuffer, Mio_GateReadName(pGate->pRoot) ); + strcat( pBuffer, "(" ); + for ( i = 0; i < (int)pGate->nFanins; i++ ) + { + if ( i ) + strcat( pBuffer, "," ); + Super_WriteLibraryGateName_rec( pGate->pFanins[i], pBuffer ); + } + strcat( pBuffer, ")" ); +} + + + + + +/**Function************************************************************* + + Synopsis [Recursively writes the gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_WriteLibraryTree( Super_Man_t * pMan ) +{ + Super_Gate_t * pSuper; + FILE * pFile; + char FileName[100]; + char * pNameGeneric; + int i, Counter; + int posStart; + + // get the file name + pNameGeneric = Extra_FileNameGeneric( pMan->pName ); + sprintf( FileName, "%s.super", pNameGeneric ); + free( pNameGeneric ); + + // write the elementary variables + pFile = fopen( FileName, "w" ); + Super_WriteFileHeader( pMan, pFile ); + // write the place holder for the number of lines + posStart = ftell( pFile ); + fprintf( pFile, " \n" ); + // mark the real supergates + Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) + pSuper->fSuper = 1; + // write the supergates + Counter = pMan->nVarsMax; + Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) + Super_WriteLibraryTree_rec( pFile, pMan, pSuper, &Counter ); + fclose( pFile ); + // write the number of lines + pFile = fopen( FileName, "rb+" ); + fseek( pFile, posStart, SEEK_SET ); + fprintf( pFile, "%d", Counter ); + fclose( pFile ); + +if ( pMan->fVerbose ) +{ + printf( "The supergates are written using new format \"%s\" ", FileName ); + printf( "(%0.3f Mb).\n", ((double)Extra_FileSize(FileName))/(1<<20) ); +} +} + +/**Function************************************************************* + + Synopsis [Recursively writes the gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Super_WriteLibraryTree_rec( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter ) +{ + int nFanins, i; + // skip an elementary variable and a gate that was already written + if ( pSuper->fVar || pSuper->Number > 0 ) + return; + // write the fanins + nFanins = Mio_GateReadInputs(pSuper->pRoot); + for ( i = 0; i < nFanins; i++ ) + Super_WriteLibraryTree_rec( pFile, pMan, pSuper->pFanins[i], pCounter ); + // finally write the gate + pSuper->Number = (*pCounter)++; + fprintf( pFile, "%s", pSuper->fSuper? "* " : "" ); + fprintf( pFile, "%s", Mio_GateReadName(pSuper->pRoot) ); + for ( i = 0; i < nFanins; i++ ) + fprintf( pFile, " %d", pSuper->pFanins[i]->Number ); + // write the formula + // this step is optional, the resulting library will work in any case + // however, it may be helpful to for debugging to compare the same library + // written in the old format and written in the new format with formulas +// fprintf( pFile, " # %s", Super_WriteLibraryGateName( pSuper ) ); + fprintf( pFile, "\n" ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/map/super/superInt.h b/abc70930/src/map/super/superInt.h new file mode 100644 index 00000000..ec6d0a38 --- /dev/null +++ b/abc70930/src/map/super/superInt.h @@ -0,0 +1,62 @@ +/**CFile**************************************************************** + + FileName [superInt.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Pre-computation of supergates.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: superInt.h,v 1.4 2004/07/06 04:55:59 alanmi Exp $] + +***********************************************************************/ + +#ifndef __super_INT_H__ +#define __super_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "abc.h" +#include "mainInt.h" +#include "mvc.h" +#include "mio.h" +#include "stmm.h" +#include "super.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== superAnd.c =============================================================*/ +extern void Super2_Precompute( int nInputs, int nLevels, int fVerbose ); +/*=== superGate.c =============================================================*/ +extern void Super_Precompute( Mio_Library_t * pLibGen, int nInputs, int nLevels, float tDelayMax, float tAreaMax, int TimeLimit, bool fSkipInv, bool fWriteOldFormat, int fVerbose ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/map/super/superWrite.c b/abc70930/src/map/super/superWrite.c new file mode 100644 index 00000000..395ef145 --- /dev/null +++ b/abc70930/src/map/super/superWrite.c @@ -0,0 +1,76 @@ +/**CFile**************************************************************** + + FileName [superWrite.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Pre-computation of supergates.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 8, 2003.] + + Revision [$Id: superWrite.c,v 1.1 2004/04/03 01:36:45 alanmi Exp $] + +***********************************************************************/ + +#include "superInt.h" + +/* + One record in the supergate library file consists of: + + + + is a zero-based integer + is a string of 2^n bits representing the value of the function for each minterm + is the maximum delay of the gate + is the array of n double values + is a floating point value + is the string representing the gate in the following format: + GATENAME1( GATENAME2( a, c ), GATENAME3( a, d ), ... ) + The gate names (GATENAME1, etc) are the names as they appear in the .genlib library. + The primary inputs of the gates are denoted by lowercase chars 'a', 'b', etc. + The parantheses are mandatory for each gate, except for the wire. + The wire name can be omitted, so that "a" can be used instead of "**wire**( a )". + The spaces are optional in any position of this string. + + + The supergates are generated exhaustively from all gate combinations that + have the max delay lower than the delay given by the user, or until the specified time + limit is reached. + + The supergates are stored in supergate classes by their functionality. + Among the gates with the equivalent functionaly only those are dropped, which are + dominated by at least one other gate in the class in terms of both delay and area. + For the definition of gate dominance see pliGenCheckDominance(). +*/ + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/espresso/cofactor.c b/abc70930/src/misc/espresso/cofactor.c new file mode 100644 index 00000000..b851a639 --- /dev/null +++ b/abc70930/src/misc/espresso/cofactor.c @@ -0,0 +1,382 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +/* + The cofactor of a cover against a cube "c" is a cover formed by the + cofactor of each cube in the cover against c. The cofactor of two + cubes is null if they are distance 1 or more apart. If they are + distance zero apart, the cofactor is the restriction of the cube + to the minterms of c. + + The cube list contains the following information: + + T[0] = pointer to a cube identifying the variables that have + been cofactored against + T[1] = pointer to just beyond the sentinel (i.e., T[n] in this case) + T[2] + . + . = pointers to cubes + . + T[n-2] + T[n-1] = NULL pointer (sentinel) + + + Cofactoring involves repeated application of "cdist0" to check if a + cube of the cover intersects the cofactored cube. This can be + slow, especially for the recursive descent of the espresso + routines. Therefore, a special cofactor routine "scofactor" is + provided which assumes the cofactor is only in a single variable. +*/ + + +/* cofactor -- compute the cofactor of a cover with respect to a cube */ +pcube *cofactor(T, c) +IN pcube *T; +IN register pcube c; +{ + pcube temp = cube.temp[0], *Tc_save, *Tc, *T1; + register pcube p; + int listlen; + + listlen = CUBELISTSIZE(T) + 5; + + /* Allocate a new list of cube pointers (max size is previous size) */ + Tc_save = Tc = ALLOC(pcube, listlen); + + /* pass on which variables have been cofactored against */ + *Tc++ = set_or(new_cube(), T[0], set_diff(temp, cube.fullset, c)); + Tc++; + + /* Loop for each cube in the list, determine suitability, and save */ + for(T1 = T+2; (p = *T1++) != NULL; ) { + if (p != c) { + +#ifdef NO_INLINE + if (! cdist0(p, c)) goto false; +#else + {register int w,last;register unsigned int x;if((last=cube.inword)!=-1) + {x=p[last]&c[last];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w>1)&DISJOINT)goto false;}}}{register int w,var,last; + register pcube mask;for(var=cube.num_binary_vars;var= 0; i--) + count[i] = 0; + } + + /* Count the number of zeros in each column */ + { register int i, *cnt; + register unsigned int val; + register pcube p, cof = T[0], full = cube.fullset; + for(T1 = T+2; (p = *T1++) != NULL; ) + for(i = LOOP(p); i > 0; i--) + if (val = full[i] & ~ (p[i] | cof[i])) { + cnt = count + ((i-1) << LOGBPI); +#if BPI == 32 + if (val & 0xFF000000) { + if (val & 0x80000000) cnt[31]++; + if (val & 0x40000000) cnt[30]++; + if (val & 0x20000000) cnt[29]++; + if (val & 0x10000000) cnt[28]++; + if (val & 0x08000000) cnt[27]++; + if (val & 0x04000000) cnt[26]++; + if (val & 0x02000000) cnt[25]++; + if (val & 0x01000000) cnt[24]++; + } + if (val & 0x00FF0000) { + if (val & 0x00800000) cnt[23]++; + if (val & 0x00400000) cnt[22]++; + if (val & 0x00200000) cnt[21]++; + if (val & 0x00100000) cnt[20]++; + if (val & 0x00080000) cnt[19]++; + if (val & 0x00040000) cnt[18]++; + if (val & 0x00020000) cnt[17]++; + if (val & 0x00010000) cnt[16]++; + } +#endif + if (val & 0xFF00) { + if (val & 0x8000) cnt[15]++; + if (val & 0x4000) cnt[14]++; + if (val & 0x2000) cnt[13]++; + if (val & 0x1000) cnt[12]++; + if (val & 0x0800) cnt[11]++; + if (val & 0x0400) cnt[10]++; + if (val & 0x0200) cnt[ 9]++; + if (val & 0x0100) cnt[ 8]++; + } + if (val & 0x00FF) { + if (val & 0x0080) cnt[ 7]++; + if (val & 0x0040) cnt[ 6]++; + if (val & 0x0020) cnt[ 5]++; + if (val & 0x0010) cnt[ 4]++; + if (val & 0x0008) cnt[ 3]++; + if (val & 0x0004) cnt[ 2]++; + if (val & 0x0002) cnt[ 1]++; + if (val & 0x0001) cnt[ 0]++; + } + } + } + + /* + * Perform counts for each variable: + * cdata.var_zeros[var] = number of zeros in the variable + * cdata.parts_active[var] = number of active parts for each variable + * cdata.vars_active = number of variables which are active + * cdata.vars_unate = number of variables which are active and unate + * + * best -- the variable which is best for splitting based on: + * mostactive -- most # active parts in any variable + * mostzero -- most # zeros in any variable + * mostbalanced -- minimum over the maximum # zeros / part / variable + */ + + { register int var, i, lastbit, active, maxactive; + int best = -1, mostactive = 0, mostzero = 0, mostbalanced = 32000; + cdata.vars_unate = cdata.vars_active = 0; + + for(var = 0; var < cube.num_vars; var++) { + if (var < cube.num_binary_vars) { /* special hack for binary vars */ + i = count[var*2]; + lastbit = count[var*2 + 1]; + active = (i > 0) + (lastbit > 0); + cdata.var_zeros[var] = i + lastbit; + maxactive = MAX(i, lastbit); + } else { + maxactive = active = cdata.var_zeros[var] = 0; + lastbit = cube.last_part[var]; + for(i = cube.first_part[var]; i <= lastbit; i++) { + cdata.var_zeros[var] += count[i]; + active += (count[i] > 0); + if (active > maxactive) maxactive = active; + } + } + + /* first priority is to maximize the number of active parts */ + /* for binary case, this will usually select the output first */ + if (active > mostactive) + best = var, mostactive = active, mostzero = cdata.var_zeros[best], + mostbalanced = maxactive; + else if (active == mostactive) + /* secondary condition is to maximize the number zeros */ + /* for binary variables, this is the same as minimum # of 2's */ + if (cdata.var_zeros[var] > mostzero) + best = var, mostzero = cdata.var_zeros[best], + mostbalanced = maxactive; + else if (cdata.var_zeros[var] == mostzero) + /* third condition is to pick a balanced variable */ + /* for binary vars, this means roughly equal # 0's and 1's */ + if (maxactive < mostbalanced) + best = var, mostbalanced = maxactive; + + cdata.parts_active[var] = active; + cdata.is_unate[var] = (active == 1); + cdata.vars_active += (active > 0); + cdata.vars_unate += (active == 1); + } + cdata.best = best; + } +} + +int binate_split_select(T, cleft, cright, debug_flag) +IN pcube *T; +IN register pcube cleft, cright; +IN int debug_flag; +{ + int best = cdata.best; + register int i, lastbit = cube.last_part[best], halfbit = 0; + register pcube cof=T[0]; + + /* Create the cubes to cofactor against */ + (void) set_diff(cleft, cube.fullset, cube.var_mask[best]); + (void) set_diff(cright, cube.fullset, cube.var_mask[best]); + for(i = cube.first_part[best]; i <= lastbit; i++) + if (! is_in_set(cof,i)) + halfbit++; + for(i = cube.first_part[best], halfbit = halfbit/2; halfbit > 0; i++) + if (! is_in_set(cof,i)) + halfbit--, set_insert(cleft, i); + for(; i <= lastbit; i++) + if (! is_in_set(cof,i)) + set_insert(cright, i); + + if (debug & debug_flag) { + (void) printf("BINATE_SPLIT_SELECT: split against %d\n", best); + if (verbose_debug) + (void) printf("cl=%s\ncr=%s\n", pc1(cleft), pc2(cright)); + } + return best; +} + + +pcube *cube1list(A) +pcover A; +{ + register pcube last, p, *plist, *list; + + list = plist = ALLOC(pcube, A->count + 3); + *plist++ = new_cube(); + plist++; + foreach_set(A, last, p) { + *plist++ = p; + } + *plist++ = NULL; /* sentinel */ + list[1] = (pcube) plist; + return list; +} + + +pcube *cube2list(A, B) +pcover A, B; +{ + register pcube last, p, *plist, *list; + + list = plist = ALLOC(pcube, A->count + B->count + 3); + *plist++ = new_cube(); + plist++; + foreach_set(A, last, p) { + *plist++ = p; + } + foreach_set(B, last, p) { + *plist++ = p; + } + *plist++ = NULL; + list[1] = (pcube) plist; + return list; +} + + +pcube *cube3list(A, B, C) +pcover A, B, C; +{ + register pcube last, p, *plist, *list; + + plist = ALLOC(pcube, A->count + B->count + C->count + 3); + list = plist; + *plist++ = new_cube(); + plist++; + foreach_set(A, last, p) { + *plist++ = p; + } + foreach_set(B, last, p) { + *plist++ = p; + } + foreach_set(C, last, p) { + *plist++ = p; + } + *plist++ = NULL; + list[1] = (pcube) plist; + return list; +} + + +pcover cubeunlist(A1) +pcube *A1; +{ + register int i; + register pcube p, pdest, cof = A1[0]; + register pcover A; + + A = new_cover(CUBELISTSIZE(A1)); + for(i = 2; (p = A1[i]) != NULL; i++) { + pdest = GETSET(A, i-2); + INLINEset_or(pdest, p, cof); + } + A->count = CUBELISTSIZE(A1); + return A; +} + +simplify_cubelist(T) +pcube *T; +{ + register pcube *Tdest; + register int i, ncubes; + + (void) set_copy(cube.temp[0], T[0]); /* retrieve cofactor */ + + ncubes = CUBELISTSIZE(T); + qsort((char *) (T+2), ncubes, sizeof(pset), (int (*)()) d1_order); + + Tdest = T+2; + /* *Tdest++ = T[2]; */ + for(i = 3; i < ncubes; i++) { + if (d1_order(&T[i-1], &T[i]) != 0) { + *Tdest++ = T[i]; + } + } + + *Tdest++ = NULL; /* sentinel */ + Tdest[1] = (pcube) Tdest; /* save pointer to last */ +} diff --git a/abc70930/src/misc/espresso/cols.c b/abc70930/src/misc/espresso/cols.c new file mode 100644 index 00000000..ec3797e6 --- /dev/null +++ b/abc70930/src/misc/espresso/cols.c @@ -0,0 +1,314 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +//#include "port.h" +#include "sparse_int.h" + + +/* + * allocate a new col vector + */ +sm_col * +sm_col_alloc() +{ + register sm_col *pcol; + +#ifdef FAST_AND_LOOSE + if (sm_col_freelist == NIL(sm_col)) { + pcol = ALLOC(sm_col, 1); + } else { + pcol = sm_col_freelist; + sm_col_freelist = pcol->next_col; + } +#else + pcol = ALLOC(sm_col, 1); +#endif + + pcol->col_num = 0; + pcol->length = 0; + pcol->first_row = pcol->last_row = NIL(sm_element); + pcol->next_col = pcol->prev_col = NIL(sm_col); + pcol->flag = 0; + pcol->user_word = NIL(char); /* for our user ... */ + return pcol; +} + + +/* + * free a col vector -- for FAST_AND_LOOSE, this is real cheap for cols; + * however, freeing a rowumn must still walk down the rowumn discarding + * the elements one-by-one; that is the only use for the extra '-DCOLS' + * compile flag ... + */ +void +sm_col_free(pcol) +register sm_col *pcol; +{ +#if defined(FAST_AND_LOOSE) && ! defined(COLS) + if (pcol->first_row != NIL(sm_element)) { + /* Add the linked list of col items to the free list */ + pcol->last_row->next_row = sm_element_freelist; + sm_element_freelist = pcol->first_row; + } + + /* Add the col to the free list of cols */ + pcol->next_col = sm_col_freelist; + sm_col_freelist = pcol; +#else + register sm_element *p, *pnext; + + for(p = pcol->first_row; p != 0; p = pnext) { + pnext = p->next_row; + sm_element_free(p); + } + FREE(pcol); +#endif +} + + +/* + * duplicate an existing col + */ +sm_col * +sm_col_dup(pcol) +register sm_col *pcol; +{ + register sm_col *pnew; + register sm_element *p; + + pnew = sm_col_alloc(); + for(p = pcol->first_row; p != 0; p = p->next_row) { + (void) sm_col_insert(pnew, p->row_num); + } + return pnew; +} + + +/* + * insert an element into a col vector + */ +sm_element * +sm_col_insert(pcol, row) +register sm_col *pcol; +register int row; +{ + register sm_element *test, *element; + + /* get a new item, save its address */ + sm_element_alloc(element); + test = element; + sorted_insert(sm_element, pcol->first_row, pcol->last_row, pcol->length, + next_row, prev_row, row_num, row, test); + + /* if item was not used, free it */ + if (element != test) { + sm_element_free(element); + } + + /* either way, return the current new value */ + return test; +} + + +/* + * remove an element from a col vector + */ +void +sm_col_remove(pcol, row) +register sm_col *pcol; +register int row; +{ + register sm_element *p; + + for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row) + ; + if (p != 0 && p->row_num == row) { + dll_unlink(p, pcol->first_row, pcol->last_row, + next_row, prev_row, pcol->length); + sm_element_free(p); + } +} + + +/* + * find an element (if it is in the col vector) + */ +sm_element * +sm_col_find(pcol, row) +sm_col *pcol; +int row; +{ + register sm_element *p; + + for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row) + ; + if (p != 0 && p->row_num == row) { + return p; + } else { + return NIL(sm_element); + } +} + +/* + * return 1 if col p2 contains col p1; 0 otherwise + */ +int +sm_col_contains(p1, p2) +sm_col *p1, *p2; +{ + register sm_element *q1, *q2; + + q1 = p1->first_row; + q2 = p2->first_row; + while (q1 != 0) { + if (q2 == 0 || q1->row_num < q2->row_num) { + return 0; + } else if (q1->row_num == q2->row_num) { + q1 = q1->next_row; + q2 = q2->next_row; + } else { + q2 = q2->next_row; + } + } + return 1; +} + + +/* + * return 1 if col p1 and col p2 share an element in common + */ +int +sm_col_intersects(p1, p2) +sm_col *p1, *p2; +{ + register sm_element *q1, *q2; + + q1 = p1->first_row; + q2 = p2->first_row; + if (q1 == 0 || q2 == 0) return 0; + for(;;) { + if (q1->row_num < q2->row_num) { + if ((q1 = q1->next_row) == 0) { + return 0; + } + } else if (q1->row_num > q2->row_num) { + if ((q2 = q2->next_row) == 0) { + return 0; + } + } else { + return 1; + } + } +} + + +/* + * compare two cols, lexical ordering + */ +int +sm_col_compare(p1, p2) +sm_col *p1, *p2; +{ + register sm_element *q1, *q2; + + q1 = p1->first_row; + q2 = p2->first_row; + while(q1 != 0 && q2 != 0) { + if (q1->row_num != q2->row_num) { + return q1->row_num - q2->row_num; + } + q1 = q1->next_row; + q2 = q2->next_row; + } + + if (q1 != 0) { + return 1; + } else if (q2 != 0) { + return -1; + } else { + return 0; + } +} + + +/* + * return the intersection + */ +sm_col * +sm_col_and(p1, p2) +sm_col *p1, *p2; +{ + register sm_element *q1, *q2; + register sm_col *result; + + result = sm_col_alloc(); + q1 = p1->first_row; + q2 = p2->first_row; + if (q1 == 0 || q2 == 0) return result; + for(;;) { + if (q1->row_num < q2->row_num) { + if ((q1 = q1->next_row) == 0) { + return result; + } + } else if (q1->row_num > q2->row_num) { + if ((q2 = q2->next_row) == 0) { + return result; + } + } else { + (void) sm_col_insert(result, q1->row_num); + if ((q1 = q1->next_row) == 0) { + return result; + } + if ((q2 = q2->next_row) == 0) { + return result; + } + } + } +} + +int +sm_col_hash(pcol, modulus) +sm_col *pcol; +int modulus; +{ + register int sum; + register sm_element *p; + + sum = 0; + for(p = pcol->first_row; p != 0; p = p->next_row) { + sum = (sum*17 + p->row_num) % modulus; + } + return sum; +} + +/* + * remove an element from a col vector (given a pointer to the element) + */ +void +sm_col_remove_element(pcol, p) +register sm_col *pcol; +register sm_element *p; +{ + dll_unlink(p, pcol->first_row, pcol->last_row, + next_row, prev_row, pcol->length); + sm_element_free(p); +} + + +void +sm_col_print(fp, pcol) +FILE *fp; +sm_col *pcol; +{ + sm_element *p; + + for(p = pcol->first_row; p != 0; p = p->next_row) { + (void) fprintf(fp, " %d", p->row_num); + } +} diff --git a/abc70930/src/misc/espresso/compl.c b/abc70930/src/misc/espresso/compl.c new file mode 100644 index 00000000..8f1c6606 --- /dev/null +++ b/abc70930/src/misc/espresso/compl.c @@ -0,0 +1,680 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + * module: compl.c + * purpose: compute the complement of a multiple-valued function + * + * The "unate recursive paradigm" is used. After a set of special + * cases are examined, the function is split on the "most active + * variable". These two halves are complemented recursively, and then + * the results are merged. + * + * Changes (from Version 2.1 to Version 2.2) + * 1. Minor bug in compl_lifting -- cubes in the left half were + * not marked as active, so that when merging a leaf from the left + * hand side, the active flags were essentially random. This led + * to minor impredictability problem, but never affected the + * accuracy of the results. + */ + +#include "espresso.h" + +#define USE_COMPL_LIFT 0 +#define USE_COMPL_LIFT_ONSET 1 +#define USE_COMPL_LIFT_ONSET_COMPLEX 2 +#define NO_LIFTING 3 + +static bool compl_special_cases(); +static pcover compl_merge(); +static void compl_d1merge(); +static pcover compl_cube(); +static void compl_lift(); +static void compl_lift_onset(); +static void compl_lift_onset_complex(); +static bool simp_comp_special_cases(); +static bool simplify_special_cases(); + + +/* complement -- compute the complement of T */ +pcover complement(T) +pcube *T; /* T will be disposed of */ +{ + register pcube cl, cr; + register int best; + pcover Tbar, Tl, Tr; + int lifting; + static int compl_level = 0; + + if (debug & COMPL) + debug_print(T, "COMPLEMENT", compl_level++); + + if (compl_special_cases(T, &Tbar) == MAYBE) { + + /* Allocate space for the partition cubes */ + cl = new_cube(); + cr = new_cube(); + best = binate_split_select(T, cl, cr, COMPL); + + /* Complement the left and right halves */ + Tl = complement(scofactor(T, cl, best)); + Tr = complement(scofactor(T, cr, best)); + + if (Tr->count*Tl->count > (Tr->count+Tl->count)*CUBELISTSIZE(T)) { + lifting = USE_COMPL_LIFT_ONSET; + } else { + lifting = USE_COMPL_LIFT; + } + Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting); + + free_cube(cl); + free_cube(cr); + free_cubelist(T); + } + + if (debug & COMPL) + debug1_print(Tbar, "exit COMPLEMENT", --compl_level); + return Tbar; +} + +static bool compl_special_cases(T, Tbar) +pcube *T; /* will be disposed if answer is determined */ +pcover *Tbar; /* returned only if answer determined */ +{ + register pcube *T1, p, ceil, cof=T[0]; + pcover A, ceil_compl; + + /* Check for no cubes in the cover */ + if (T[2] == NULL) { + *Tbar = sf_addset(new_cover(1), cube.fullset); + free_cubelist(T); + return TRUE; + } + + /* Check for only a single cube in the cover */ + if (T[3] == NULL) { + *Tbar = compl_cube(set_or(cof, cof, T[2])); + free_cubelist(T); + return TRUE; + } + + /* Check for a row of all 1's (implies complement is null) */ + for(T1 = T+2; (p = *T1++) != NULL; ) { + if (full_row(p, cof)) { + *Tbar = new_cover(0); + free_cubelist(T); + return TRUE; + } + } + + /* Check for a column of all 0's which can be factored out */ + ceil = set_save(cof); + for(T1 = T+2; (p = *T1++) != NULL; ) { + INLINEset_or(ceil, ceil, p); + } + if (! setp_equal(ceil, cube.fullset)) { + ceil_compl = compl_cube(ceil); + (void) set_or(cof, cof, set_diff(ceil, cube.fullset, ceil)); + set_free(ceil); + *Tbar = sf_append(complement(T), ceil_compl); + return TRUE; + } + set_free(ceil); + + /* Collect column counts, determine unate variables, etc. */ + massive_count(T); + + /* If single active variable not factored out above, then tautology ! */ + if (cdata.vars_active == 1) { + *Tbar = new_cover(0); + free_cubelist(T); + return TRUE; + + /* Check for unate cover */ + } else if (cdata.vars_unate == cdata.vars_active) { + A = map_cover_to_unate(T); + free_cubelist(T); + A = unate_compl(A); + *Tbar = map_unate_to_cover(A); + sf_free(A); + return TRUE; + + /* Not much we can do about it */ + } else { + return MAYBE; + } +} + +/* + * compl_merge -- merge the two cofactors around the splitting + * variable + * + * The merge operation involves intersecting each cube of the left + * cofactor with cl, and intersecting each cube of the right cofactor + * with cr. The union of these two covers is the merged result. + * + * In order to reduce the number of cubes, a distance-1 merge is + * performed (note that two cubes can only combine distance-1 in the + * splitting variable). Also, a simple expand is performed in the + * splitting variable (simple implies the covering check for the + * expansion is not full containment, but single-cube containment). + */ + +static pcover compl_merge(T1, L, R, cl, cr, var, lifting) +pcube *T1; /* Original ON-set */ +pcover L, R; /* Complement from each recursion branch */ +register pcube cl, cr; /* cubes used for cofactoring */ +int var; /* splitting variable */ +int lifting; /* whether to perform lifting or not */ +{ + register pcube p, last, pt; + pcover T, Tbar; + pcube *L1, *R1; + + if (debug & COMPL) { + (void) printf("compl_merge: left %d, right %d\n", L->count, R->count); + (void) printf("%s (cl)\n%s (cr)\nLeft is\n", pc1(cl), pc2(cr)); + cprint(L); + (void) printf("Right is\n"); + cprint(R); + } + + /* Intersect each cube with the cofactored cube */ + foreach_set(L, last, p) { + INLINEset_and(p, p, cl); + SET(p, ACTIVE); + } + foreach_set(R, last, p) { + INLINEset_and(p, p, cr); + SET(p, ACTIVE); + } + + /* Sort the arrays for a distance-1 merge */ + (void) set_copy(cube.temp[0], cube.var_mask[var]); + qsort((char *) (L1 = sf_list(L)), L->count, sizeof(pset), (int (*)()) d1_order); + qsort((char *) (R1 = sf_list(R)), R->count, sizeof(pset), (int (*)()) d1_order); + + /* Perform distance-1 merge */ + compl_d1merge(L1, R1); + + /* Perform lifting */ + switch(lifting) { + case USE_COMPL_LIFT_ONSET: + T = cubeunlist(T1); + compl_lift_onset(L1, T, cr, var); + compl_lift_onset(R1, T, cl, var); + free_cover(T); + break; + case USE_COMPL_LIFT_ONSET_COMPLEX: + T = cubeunlist(T1); + compl_lift_onset_complex(L1, T, var); + compl_lift_onset_complex(R1, T, var); + free_cover(T); + break; + case USE_COMPL_LIFT: + compl_lift(L1, R1, cr, var); + compl_lift(R1, L1, cl, var); + break; + case NO_LIFTING: + break; + default: + ; + } + FREE(L1); + FREE(R1); + + /* Re-create the merged cover */ + Tbar = new_cover(L->count + R->count); + pt = Tbar->data; + foreach_set(L, last, p) { + INLINEset_copy(pt, p); + Tbar->count++; + pt += Tbar->wsize; + } + foreach_active_set(R, last, p) { + INLINEset_copy(pt, p); + Tbar->count++; + pt += Tbar->wsize; + } + + if (debug & COMPL) { + (void) printf("Result %d\n", Tbar->count); + if (verbose_debug) + cprint(Tbar); + } + + free_cover(L); + free_cover(R); + return Tbar; +} + +/* + * compl_lift_simple -- expand in the splitting variable using single + * cube containment against the other recursion branch to check + * validity of the expansion, and expanding all (or none) of the + * splitting variable. + */ +static void compl_lift(A1, B1, bcube, var) +pcube *A1, *B1, bcube; +int var; +{ + register pcube a, b, *B2, lift=cube.temp[4], liftor=cube.temp[5]; + pcube mask = cube.var_mask[var]; + + (void) set_and(liftor, bcube, mask); + + /* for each cube in the first array ... */ + for(; (a = *A1++) != NULL; ) { + if (TESTP(a, ACTIVE)) { + + /* create a lift of this cube in the merging coord */ + (void) set_merge(lift, bcube, a, mask); + + /* for each cube in the second array */ + for(B2 = B1; (b = *B2++) != NULL; ) { + INLINEsetp_implies(lift, b, /* when_false => */ continue); + /* when_true => fall through to next statement */ + + /* cube of A1 was contained by some cube of B1, so raise */ + INLINEset_or(a, a, liftor); + break; + } + } + } +} + + + +/* + * compl_lift_onset -- expand in the splitting variable using a + * distance-1 check against the original on-set; expand all (or + * none) of the splitting variable. Each cube of A1 is expanded + * against the original on-set T. + */ +static void compl_lift_onset(A1, T, bcube, var) +pcube *A1; +pcover T; +pcube bcube; +int var; +{ + register pcube a, last, p, lift=cube.temp[4], mask=cube.var_mask[var]; + + /* for each active cube from one branch of the complement */ + for(; (a = *A1++) != NULL; ) { + if (TESTP(a, ACTIVE)) { + + /* create a lift of this cube in the merging coord */ + INLINEset_and(lift, bcube, mask); /* isolate parts to raise */ + INLINEset_or(lift, a, lift); /* raise these parts in a */ + + /* for each cube in the ON-set, check for intersection */ + foreach_set(T, last, p) { + if (cdist0(p, lift)) { + goto nolift; + } + } + INLINEset_copy(a, lift); /* save the raising */ + SET(a, ACTIVE); +nolift : ; + } + } +} + +/* + * compl_lift_complex -- expand in the splitting variable, but expand all + * parts which can possibly expand. + * T is the original ON-set + * A1 is either the left or right cofactor + */ +static void compl_lift_onset_complex(A1, T, var) +pcube *A1; /* array of pointers to new result */ +pcover T; /* original ON-set */ +int var; /* which variable we split on */ +{ + register int dist; + register pcube last, p, a, xlower; + + /* for each cube in the complement */ + xlower = new_cube(); + for(; (a = *A1++) != NULL; ) { + + if (TESTP(a, ACTIVE)) { + + /* Find which parts of the splitting variable are forced low */ + INLINEset_clear(xlower, cube.size); + foreach_set(T, last, p) { + if ((dist = cdist01(p, a)) < 2) { + if (dist == 0) { + fatal("compl: ON-set and OFF-set are not orthogonal"); + } else { + (void) force_lower(xlower, p, a); + } + } + } + + (void) set_diff(xlower, cube.var_mask[var], xlower); + (void) set_or(a, a, xlower); + free_cube(xlower); + } + } +} + + + +/* + * compl_d1merge -- distance-1 merge in the splitting variable + */ +static void compl_d1merge(L1, R1) +register pcube *L1, *R1; +{ + register pcube pl, pr; + + /* Find equal cubes between the two cofactors */ + for(pl = *L1, pr = *R1; (pl != NULL) && (pr != NULL); ) + switch (d1_order(L1, R1)) { + case 1: + pr = *(++R1); break; /* advance right pointer */ + case -1: + pl = *(++L1); break; /* advance left pointer */ + case 0: + RESET(pr, ACTIVE); + INLINEset_or(pl, pl, pr); + pr = *(++R1); + default: + ; + } +} + + + +/* compl_cube -- return the complement of a single cube (De Morgan's law) */ +static pcover compl_cube(p) +register pcube p; +{ + register pcube diff=cube.temp[7], pdest, mask, full=cube.fullset; + int var; + pcover R; + + /* Allocate worst-case size cover (to avoid checking overflow) */ + R = new_cover(cube.num_vars); + + /* Compute bit-wise complement of the cube */ + INLINEset_diff(diff, full, p); + + for(var = 0; var < cube.num_vars; var++) { + mask = cube.var_mask[var]; + /* If the bit-wise complement is not empty in var ... */ + if (! setp_disjoint(diff, mask)) { + pdest = GETSET(R, R->count++); + INLINEset_merge(pdest, diff, full, mask); + } + } + return R; +} + +/* simp_comp -- quick simplification of T */ +void simp_comp(T, Tnew, Tbar) +pcube *T; /* T will be disposed of */ +pcover *Tnew; +pcover *Tbar; +{ + register pcube cl, cr; + register int best; + pcover Tl, Tr, Tlbar, Trbar; + int lifting; + static int simplify_level = 0; + + if (debug & COMPL) + debug_print(T, "SIMPCOMP", simplify_level++); + + if (simp_comp_special_cases(T, Tnew, Tbar) == MAYBE) { + + /* Allocate space for the partition cubes */ + cl = new_cube(); + cr = new_cube(); + best = binate_split_select(T, cl, cr, COMPL); + + /* Complement the left and right halves */ + simp_comp(scofactor(T, cl, best), &Tl, &Tlbar); + simp_comp(scofactor(T, cr, best), &Tr, &Trbar); + + lifting = USE_COMPL_LIFT; + *Tnew = compl_merge(T, Tl, Tr, cl, cr, best, lifting); + + lifting = USE_COMPL_LIFT; + *Tbar = compl_merge(T, Tlbar, Trbar, cl, cr, best, lifting); + + /* All of this work for nothing ? Let's hope not ... */ + if ((*Tnew)->count > CUBELISTSIZE(T)) { + sf_free(*Tnew); + *Tnew = cubeunlist(T); + } + + free_cube(cl); + free_cube(cr); + free_cubelist(T); + } + + if (debug & COMPL) { + debug1_print(*Tnew, "exit SIMPCOMP (new)", simplify_level); + debug1_print(*Tbar, "exit SIMPCOMP (compl)", simplify_level); + simplify_level--; + } +} + +static bool simp_comp_special_cases(T, Tnew, Tbar) +pcube *T; /* will be disposed if answer is determined */ +pcover *Tnew; /* returned only if answer determined */ +pcover *Tbar; /* returned only if answer determined */ +{ + register pcube *T1, p, ceil, cof=T[0]; + pcube last; + pcover A; + + /* Check for no cubes in the cover (function is empty) */ + if (T[2] == NULL) { + *Tnew = new_cover(1); + *Tbar = sf_addset(new_cover(1), cube.fullset); + free_cubelist(T); + return TRUE; + } + + /* Check for only a single cube in the cover */ + if (T[3] == NULL) { + (void) set_or(cof, cof, T[2]); + *Tnew = sf_addset(new_cover(1), cof); + *Tbar = compl_cube(cof); + free_cubelist(T); + return TRUE; + } + + /* Check for a row of all 1's (function is a tautology) */ + for(T1 = T+2; (p = *T1++) != NULL; ) { + if (full_row(p, cof)) { + *Tnew = sf_addset(new_cover(1), cube.fullset); + *Tbar = new_cover(1); + free_cubelist(T); + return TRUE; + } + } + + /* Check for a column of all 0's which can be factored out */ + ceil = set_save(cof); + for(T1 = T+2; (p = *T1++) != NULL; ) { + INLINEset_or(ceil, ceil, p); + } + if (! setp_equal(ceil, cube.fullset)) { + p = new_cube(); + (void) set_diff(p, cube.fullset, ceil); + (void) set_or(cof, cof, p); + set_free(p); + simp_comp(T, Tnew, Tbar); + + /* Adjust the ON-set */ + A = *Tnew; + foreach_set(A, last, p) { + INLINEset_and(p, p, ceil); + } + + /* Compute the new complement */ + *Tbar = sf_append(*Tbar, compl_cube(ceil)); + set_free(ceil); + return TRUE; + } + set_free(ceil); + + /* Collect column counts, determine unate variables, etc. */ + massive_count(T); + + /* If single active variable not factored out above, then tautology ! */ + if (cdata.vars_active == 1) { + *Tnew = sf_addset(new_cover(1), cube.fullset); + *Tbar = new_cover(1); + free_cubelist(T); + return TRUE; + + /* Check for unate cover */ + } else if (cdata.vars_unate == cdata.vars_active) { + /* Make the cover minimum by single-cube containment */ + A = cubeunlist(T); + *Tnew = sf_contain(A); + + /* Now form a minimum representation of the complement */ + A = map_cover_to_unate(T); + A = unate_compl(A); + *Tbar = map_unate_to_cover(A); + sf_free(A); + free_cubelist(T); + return TRUE; + + /* Not much we can do about it */ + } else { + return MAYBE; + } +} + +/* simplify -- quick simplification of T */ +pcover simplify(T) +pcube *T; /* T will be disposed of */ +{ + register pcube cl, cr; + register int best; + pcover Tbar, Tl, Tr; + int lifting; + static int simplify_level = 0; + + if (debug & COMPL) { + debug_print(T, "SIMPLIFY", simplify_level++); + } + + if (simplify_special_cases(T, &Tbar) == MAYBE) { + + /* Allocate space for the partition cubes */ + cl = new_cube(); + cr = new_cube(); + + best = binate_split_select(T, cl, cr, COMPL); + + /* Complement the left and right halves */ + Tl = simplify(scofactor(T, cl, best)); + Tr = simplify(scofactor(T, cr, best)); + + lifting = USE_COMPL_LIFT; + Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting); + + /* All of this work for nothing ? Let's hope not ... */ + if (Tbar->count > CUBELISTSIZE(T)) { + sf_free(Tbar); + Tbar = cubeunlist(T); + } + + free_cube(cl); + free_cube(cr); + free_cubelist(T); + } + + if (debug & COMPL) { + debug1_print(Tbar, "exit SIMPLIFY", --simplify_level); + } + return Tbar; +} + +static bool simplify_special_cases(T, Tnew) +pcube *T; /* will be disposed if answer is determined */ +pcover *Tnew; /* returned only if answer determined */ +{ + register pcube *T1, p, ceil, cof=T[0]; + pcube last; + pcover A; + + /* Check for no cubes in the cover */ + if (T[2] == NULL) { + *Tnew = new_cover(0); + free_cubelist(T); + return TRUE; + } + + /* Check for only a single cube in the cover */ + if (T[3] == NULL) { + *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2])); + free_cubelist(T); + return TRUE; + } + + /* Check for a row of all 1's (implies function is a tautology) */ + for(T1 = T+2; (p = *T1++) != NULL; ) { + if (full_row(p, cof)) { + *Tnew = sf_addset(new_cover(1), cube.fullset); + free_cubelist(T); + return TRUE; + } + } + + /* Check for a column of all 0's which can be factored out */ + ceil = set_save(cof); + for(T1 = T+2; (p = *T1++) != NULL; ) { + INLINEset_or(ceil, ceil, p); + } + if (! setp_equal(ceil, cube.fullset)) { + p = new_cube(); + (void) set_diff(p, cube.fullset, ceil); + (void) set_or(cof, cof, p); + free_cube(p); + + A = simplify(T); + foreach_set(A, last, p) { + INLINEset_and(p, p, ceil); + } + *Tnew = A; + set_free(ceil); + return TRUE; + } + set_free(ceil); + + /* Collect column counts, determine unate variables, etc. */ + massive_count(T); + + /* If single active variable not factored out above, then tautology ! */ + if (cdata.vars_active == 1) { + *Tnew = sf_addset(new_cover(1), cube.fullset); + free_cubelist(T); + return TRUE; + + /* Check for unate cover */ + } else if (cdata.vars_unate == cdata.vars_active) { + A = cubeunlist(T); + *Tnew = sf_contain(A); + free_cubelist(T); + return TRUE; + + /* Not much we can do about it */ + } else { + return MAYBE; + } +} diff --git a/abc70930/src/misc/espresso/contain.c b/abc70930/src/misc/espresso/contain.c new file mode 100644 index 00000000..180dceb6 --- /dev/null +++ b/abc70930/src/misc/espresso/contain.c @@ -0,0 +1,441 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + contain.c -- set containment routines + + These are complex routines for performing containment over a + family of sets, but they have the advantage of being much faster + than a straightforward n*n routine. + + First the cubes are sorted by size, and as a secondary key they are + sorted so that if two cubes are equal they end up adjacent. We can + than quickly remove equal cubes from further consideration by + comparing each cube to its neighbor. Finally, because the cubes + are sorted by size, we need only check cubes which are larger (or + smaller) than a given cube for containment. +*/ + +#include "espresso.h" + + +/* + sf_contain -- perform containment on a set family (delete sets which + are contained by some larger set in the family). No assumptions are + made about A, and the result will be returned in decreasing order of + set size. +*/ +pset_family sf_contain(A) +INOUT pset_family A; /* disposes of A */ +{ + int cnt; + pset *A1; + pset_family R; + + A1 = sf_sort(A, descend); /* sort into descending order */ + cnt = rm_equal(A1, descend); /* remove duplicates */ + cnt = rm_contain(A1); /* remove contained sets */ + R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ + sf_free(A); + return R; +} + + +/* + sf_rev_contain -- perform containment on a set family (delete sets which + contain some smaller set in the family). No assumptions are made about + A, and the result will be returned in increasing order of set size +*/ +pset_family sf_rev_contain(A) +INOUT pset_family A; /* disposes of A */ +{ + int cnt; + pset *A1; + pset_family R; + + A1 = sf_sort(A, ascend); /* sort into ascending order */ + cnt = rm_equal(A1, ascend); /* remove duplicates */ + cnt = rm_rev_contain(A1); /* remove containing sets */ + R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ + sf_free(A); + return R; +} + + +/* + sf_ind_contain -- perform containment on a set family (delete sets which + are contained by some larger set in the family). No assumptions are + made about A, and the result will be returned in decreasing order of + set size. Also maintains a set of row_indices to track which rows + disappear and how the rows end up permuted. +*/ +pset_family sf_ind_contain(A, row_indices) +INOUT pset_family A; /* disposes of A */ +INOUT int *row_indices; /* updated with the new values */ +{ + int cnt; + pset *A1; + pset_family R; + + A1 = sf_sort(A, descend); /* sort into descending order */ + cnt = rm_equal(A1, descend); /* remove duplicates */ + cnt = rm_contain(A1); /* remove contained sets */ + R = sf_ind_unlist(A1, cnt, A->sf_size, row_indices, A->data); + sf_free(A); + return R; +} + + +/* sf_dupl -- delete duplicate sets in a set family */ +pset_family sf_dupl(A) +INOUT pset_family A; /* disposes of A */ +{ + register int cnt; + register pset *A1; + pset_family R; + + A1 = sf_sort(A, descend); /* sort the set family */ + cnt = rm_equal(A1, descend); /* remove duplicates */ + R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ + sf_free(A); + return R; +} + + +/* + sf_union -- form the contained union of two set families (delete + sets which are contained by some larger set in the family). A and + B are assumed already sorted in decreasing order of set size (and + the SIZE field is assumed to contain the set size), and the result + will be returned sorted likewise. +*/ +pset_family sf_union(A, B) +INOUT pset_family A, B; /* disposes of A and B */ +{ + int cnt; + pset_family R; + pset *A1 = sf_list(A), *B1 = sf_list(B), *E1; + + E1 = ALLOC(pset, MAX(A->count, B->count) + 1); + cnt = rm2_equal(A1, B1, E1, descend); + cnt += rm2_contain(A1, B1) + rm2_contain(B1, A1); + R = sf_merge(A1, B1, E1, cnt, A->sf_size); + sf_free(A); sf_free(B); + return R; +} + + +/* + dist_merge -- consider all sets to be "or"-ed with "mask" and then + delete duplicates from the set family. +*/ +pset_family dist_merge(A, mask) +INOUT pset_family A; /* disposes of A */ +IN pset mask; /* defines variables to mask out */ +{ + pset *A1; + int cnt; + pset_family R; + + (void) set_copy(cube.temp[0], mask); + A1 = sf_sort(A, d1_order); + cnt = d1_rm_equal(A1, d1_order); + R = sf_unlist(A1, cnt, A->sf_size); + sf_free(A); + return R; +} + + +/* + d1merge -- perform an efficient distance-1 merge of cubes of A +*/ +pset_family d1merge(A, var) +INOUT pset_family A; /* disposes of A */ +IN int var; +{ + return dist_merge(A, cube.var_mask[var]); +} + + + +/* d1_rm_equal -- distance-1 merge (merge cubes which are equal under a mask) */ +int d1_rm_equal(A1, compare) +register pset *A1; /* array of set pointers */ +int (*compare)(); /* comparison function */ +{ + register int i, j, dest; + + dest = 0; + if (A1[0] != (pcube) NULL) { + for(i = 0, j = 1; A1[j] != (pcube) NULL; j++) + if ( (*compare)(&A1[i], &A1[j]) == 0) { + /* if sets are equal (under the mask) merge them */ + (void) set_or(A1[i], A1[i], A1[j]); + } else { + /* sets are unequal, so save the set i */ + A1[dest++] = A1[i]; + i = j; + } + A1[dest++] = A1[i]; + } + A1[dest] = (pcube) NULL; + return dest; +} + + +/* rm_equal -- scan a sorted array of set pointers for duplicate sets */ +int rm_equal(A1, compare) +INOUT pset *A1; /* updated in place */ +IN int (*compare)(); +{ + register pset *p, *pdest = A1; + + if (*A1 != NULL) { /* If more than one set */ + for(p = A1+1; *p != NULL; p++) + if ((*compare)(p, p-1) != 0) + *pdest++ = *(p-1); + *pdest++ = *(p-1); + *pdest = NULL; + } + return pdest - A1; +} + + +/* rm_contain -- perform containment over a sorted array of set pointers */ +int rm_contain(A1) +INOUT pset *A1; /* updated in place */ +{ + register pset *pa, *pb, *pcheck, a, b; + pset *pdest = A1; + int last_size = -1; + + /* Loop for all cubes of A1 */ + for(pa = A1; (a = *pa++) != NULL; ) { + /* Update the check pointer if the size has changed */ + if (SIZE(a) != last_size) + last_size = SIZE(a), pcheck = pdest; + for(pb = A1; pb != pcheck; ) { + b = *pb++; + INLINEsetp_implies(a, b, /* when_false => */ continue); + goto lnext1; + } + /* set a was not contained by some larger set, so save it */ + *pdest++ = a; + lnext1: ; + } + + *pdest = NULL; + return pdest - A1; +} + + +/* rm_rev_contain -- perform rcontainment over a sorted array of set pointers */ +int rm_rev_contain(A1) +INOUT pset *A1; /* updated in place */ +{ + register pset *pa, *pb, *pcheck, a, b; + pset *pdest = A1; + int last_size = -1; + + /* Loop for all cubes of A1 */ + for(pa = A1; (a = *pa++) != NULL; ) { + /* Update the check pointer if the size has changed */ + if (SIZE(a) != last_size) + last_size = SIZE(a), pcheck = pdest; + for(pb = A1; pb != pcheck; ) { + b = *pb++; + INLINEsetp_implies(b, a, /* when_false => */ continue); + goto lnext1; + } + /* the set a did not contain some smaller set, so save it */ + *pdest++ = a; + lnext1: ; + } + + *pdest = NULL; + return pdest - A1; +} + + +/* rm2_equal -- check two sorted arrays of set pointers for equal cubes */ +int rm2_equal(A1, B1, E1, compare) +INOUT register pset *A1, *B1; /* updated in place */ +OUT pset *E1; +IN int (*compare)(); +{ + register pset *pda = A1, *pdb = B1, *pde = E1; + + /* Walk through the arrays advancing pointer to larger cube */ + for(; *A1 != NULL && *B1 != NULL; ) + switch((*compare)(A1, B1)) { + case -1: /* "a" comes before "b" */ + *pda++ = *A1++; break; + case 0: /* equal cubes */ + *pde++ = *A1++; B1++; break; + case 1: /* "a" is to follow "b" */ + *pdb++ = *B1++; break; + } + + /* Finish moving down the pointers of A and B */ + while (*A1 != NULL) + *pda++ = *A1++; + while (*B1 != NULL) + *pdb++ = *B1++; + *pda = *pdb = *pde = NULL; + + return pde - E1; +} + + +/* rm2_contain -- perform containment between two arrays of set pointers */ +int rm2_contain(A1, B1) +INOUT pset *A1; /* updated in place */ +IN pset *B1; /* unchanged */ +{ + register pset *pa, *pb, a, b, *pdest = A1; + + /* for each set in the first array ... */ + for(pa = A1; (a = *pa++) != NULL; ) { + /* for each set in the second array which is larger ... */ + for(pb = B1; (b = *pb++) != NULL && SIZE(b) > SIZE(a); ) { + INLINEsetp_implies(a, b, /* when_false => */ continue); + /* set was contained in some set of B, so don't save pointer */ + goto lnext1; + } + /* set wasn't contained in any set of B, so save the pointer */ + *pdest++ = a; + lnext1: ; + } + + *pdest = NULL; /* sentinel */ + return pdest - A1; /* # elements in A1 */ +} + + + +/* sf_sort -- sort the sets of A */ +pset *sf_sort(A, compare) +IN pset_family A; +IN int (*compare)(); +{ + register pset p, last, *pdest, *A1; + + /* Create a single array pointing to each cube of A */ + pdest = A1 = ALLOC(pset, A->count + 1); + foreach_set(A, last, p) { + PUTSIZE(p, set_ord(p)); /* compute the set size */ + *pdest++ = p; /* save the pointer */ + } + *pdest = NULL; /* Sentinel -- never seen by sort */ + + /* Sort cubes by size */ + qsort((char *) A1, A->count, sizeof(pset), compare); + return A1; +} + + +/* sf_list -- make a list of pointers to the sets in a set family */ +pset *sf_list(A) +IN register pset_family A; +{ + register pset p, last, *pdest, *A1; + + /* Create a single array pointing to each cube of A */ + pdest = A1 = ALLOC(pset, A->count + 1); + foreach_set(A, last, p) + *pdest++ = p; /* save the pointer */ + *pdest = NULL; /* Sentinel */ + return A1; +} + + +/* sf_unlist -- make a set family out of a list of pointers to sets */ +pset_family sf_unlist(A1, totcnt, size) +IN pset *A1; +IN int totcnt, size; +{ + register pset pr, p, *pa; + pset_family R = sf_new(totcnt, size); + + R->count = totcnt; + for(pr = R->data, pa = A1; (p = *pa++) != NULL; pr += R->wsize) + INLINEset_copy(pr, p); + FREE(A1); + return R; +} + + +/* sf_ind_unlist -- make a set family out of a list of pointers to sets */ +pset_family sf_ind_unlist(A1, totcnt, size, row_indices, pfirst) +IN pset *A1; +IN int totcnt, size; +INOUT int *row_indices; +IN register pset pfirst; +{ + register pset pr, p, *pa; + register int i, *new_row_indices; + pset_family R = sf_new(totcnt, size); + + R->count = totcnt; + new_row_indices = ALLOC(int, totcnt); + for(pr = R->data, pa = A1, i=0; (p = *pa++) != NULL; pr += R->wsize, i++) { + INLINEset_copy(pr, p); + new_row_indices[i] = row_indices[(p - pfirst)/R->wsize]; + } + for(i = 0; i < totcnt; i++) + row_indices[i] = new_row_indices[i]; + FREE(new_row_indices); + FREE(A1); + return R; +} + + +/* sf_merge -- merge three sorted lists of set pointers */ +pset_family sf_merge(A1, B1, E1, totcnt, size) +INOUT pset *A1, *B1, *E1; /* will be disposed of */ +IN int totcnt, size; +{ + register pset pr, ps, *pmin, *pmid, *pmax; + pset_family R; + pset *temp[3], *swap; + int i, j, n; + + /* Allocate the result set_family */ + R = sf_new(totcnt, size); + R->count = totcnt; + pr = R->data; + + /* Quick bubble sort to order the top member of the three arrays */ + n = 3; temp[0] = A1; temp[1] = B1; temp[2] = E1; + for(i = 0; i < n-1; i++) + for(j = i+1; j < n; j++) + if (desc1(*temp[i], *temp[j]) > 0) { + swap = temp[j]; + temp[j] = temp[i]; + temp[i] = swap; + } + pmin = temp[0]; pmid = temp[1]; pmax = temp[2]; + + /* Save the minimum element, then update pmin, pmid, pmax */ + while (*pmin != (pset) NULL) { + ps = *pmin++; + INLINEset_copy(pr, ps); + pr += R->wsize; + if (desc1(*pmin, *pmax) > 0) { + swap = pmax; pmax = pmin; pmin = pmid; pmid = swap; + } else if (desc1(*pmin, *pmid) > 0) { + swap = pmin; pmin = pmid; pmid = swap; + } + } + + FREE(A1); + FREE(B1); + FREE(E1); + return R; +} diff --git a/abc70930/src/misc/espresso/cubehack.c b/abc70930/src/misc/espresso/cubehack.c new file mode 100644 index 00000000..8e1724fc --- /dev/null +++ b/abc70930/src/misc/espresso/cubehack.c @@ -0,0 +1,138 @@ +/* + * Revision Control Information + * + * $Source: /vol/opua/opua2/sis/sis-1.1/common/src/sis/node/RCS/cubehack.c,v $ + * $Author: sis $ + * $Revision: 1.2 $ + * $Date: 1992/05/06 18:57:41 $ + * + */ +/* +#include "sis.h" +#include "node_int.h" + +#ifdef lint +struct cube_struct cube; +bool summary; +bool trace; +bool remove_essential; +bool force_irredundant; +bool unwrap_onset; +bool single_expand; +bool pos; +bool recompute_onset; +bool use_super_gasp; +bool use_random_order; +#endif +*/ +#include "espresso.h" + + +void +cautious_define_cube_size(n) +int n; +{ + if (cube.fullset != 0 && cube.num_binary_vars == n) + return; + if (cube.fullset != 0) { + setdown_cube(); + FREE(cube.part_size); + } + cube.num_binary_vars = cube.num_vars = n; + cube.part_size = ALLOC(int, n); + cube_setup(); +} + + +void +define_cube_size(n) +int n; +{ + register int q, i; + static int called_before = 0; + + /* check if the cube is already just the right size */ + if (cube.fullset != 0 && cube.num_binary_vars == n && cube.num_vars == n) + return; + + /* We can't handle more than 100 inputs */ + if (n > 100) { + cautious_define_cube_size(n); + called_before = 0; + return; + } + + if (cube.fullset == 0 || ! called_before) { + cautious_define_cube_size(100); + called_before = 1; + } + + cube.num_vars = n; + cube.num_binary_vars = n; + cube.num_mv_vars = 0; + cube.output = -1; + cube.size = n * 2; + + /* first_part, last_part, first_word, last_word, part_size OKAY */ + /* cube.sparse is OKAY */ + + /* need to completely re-make cube.fullset and cube.binary_mask */ + (void) set_fill(cube.fullset, n*2); + (void) set_fill(cube.binary_mask, n*2); + + /* need to resize each set in cube.var_mask and cube.temp */ + q = cube.fullset[0]; + for(i = 0; i < cube.num_vars; i++) + cube.var_mask[i][0] = q; + for(i = 0; i < CUBE_TEMP; i++) + cube.temp[i][0] = q; + + /* need to resize cube.emptyset and cube.mv_mask */ + cube.emptyset[0] = q; + cube.mv_mask[0] = q; + + /* need to reset the inword and inmask */ + if (cube.num_binary_vars != 0) { + cube.inword = cube.last_word[cube.num_binary_vars - 1]; + cube.inmask = cube.binary_mask[cube.inword] & DISJOINT; + } else { + cube.inword = -1; + cube.inmask = 0; + } + + /* cdata (entire structure) is OKAY */ +} + + +void +undefine_cube_size() +{ + if (cube.num_binary_vars > 100) { + if (cube.fullset != 0) { + setdown_cube(); + FREE(cube.part_size); + } + } else { + cube.num_vars = cube.num_binary_vars = 100; + if (cube.fullset != 0) { + setdown_cube(); + FREE(cube.part_size); + } + } +} + + +void +set_espresso_flags() +{ + summary = FALSE; + trace = FALSE; + remove_essential = TRUE; + force_irredundant = TRUE; + unwrap_onset = TRUE; + single_expand = FALSE; + pos = FALSE; + recompute_onset = FALSE; + use_super_gasp = FALSE; + use_random_order = FALSE; +} diff --git a/abc70930/src/misc/espresso/cubestr.c b/abc70930/src/misc/espresso/cubestr.c new file mode 100644 index 00000000..77389e73 --- /dev/null +++ b/abc70930/src/misc/espresso/cubestr.c @@ -0,0 +1,152 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + Module: cubestr.c -- routines for managing the global cube structure +*/ + +#include "espresso.h" + +/* + cube_setup -- assume that the fields "num_vars", "num_binary_vars", and + part_size[num_binary_vars .. num_vars-1] are setup, and initialize the + rest of cube and cdata. + + If a part_size is < 0, then the field size is abs(part_size) and the + field read from the input is symbolic. +*/ +void cube_setup() +{ + register int i, var; + register pcube p; + + if (cube.num_binary_vars < 0 || cube.num_vars < cube.num_binary_vars) + fatal("cube size is silly, error in .i/.o or .mv"); + + cube.num_mv_vars = cube.num_vars - cube.num_binary_vars; + cube.output = cube.num_mv_vars > 0 ? cube.num_vars - 1 : -1; + + cube.size = 0; + cube.first_part = ALLOC(int, cube.num_vars); + cube.last_part = ALLOC(int, cube.num_vars); + cube.first_word = ALLOC(int, cube.num_vars); + cube.last_word = ALLOC(int, cube.num_vars); + for(var = 0; var < cube.num_vars; var++) { + if (var < cube.num_binary_vars) + cube.part_size[var] = 2; + cube.first_part[var] = cube.size; + cube.first_word[var] = WHICH_WORD(cube.size); + cube.size += ABS(cube.part_size[var]); + cube.last_part[var] = cube.size - 1; + cube.last_word[var] = WHICH_WORD(cube.size - 1); + } + + cube.var_mask = ALLOC(pset, cube.num_vars); + cube.sparse = ALLOC(int, cube.num_vars); + cube.binary_mask = new_cube(); + cube.mv_mask = new_cube(); + for(var = 0; var < cube.num_vars; var++) { + p = cube.var_mask[var] = new_cube(); + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) + set_insert(p, i); + if (var < cube.num_binary_vars) { + INLINEset_or(cube.binary_mask, cube.binary_mask, p); + cube.sparse[var] = 0; + } else { + INLINEset_or(cube.mv_mask, cube.mv_mask, p); + cube.sparse[var] = 1; + } + } + if (cube.num_binary_vars == 0) + cube.inword = -1; + else { + cube.inword = cube.last_word[cube.num_binary_vars - 1]; + cube.inmask = cube.binary_mask[cube.inword] & DISJOINT; + } + + cube.temp = ALLOC(pset, CUBE_TEMP); + for(i = 0; i < CUBE_TEMP; i++) + cube.temp[i] = new_cube(); + cube.fullset = set_fill(new_cube(), cube.size); + cube.emptyset = new_cube(); + + cdata.part_zeros = ALLOC(int, cube.size); + cdata.var_zeros = ALLOC(int, cube.num_vars); + cdata.parts_active = ALLOC(int, cube.num_vars); + cdata.is_unate = ALLOC(int, cube.num_vars); +} + +/* + setdown_cube -- free memory allocated for the cube/cdata structs + (free's all but the part_size array) + + (I wanted to call this cube_setdown, but that violates the 8-character + external routine limit on the IBM !) +*/ +void setdown_cube() +{ + register int i, var; + + FREE(cube.first_part); + FREE(cube.last_part); + FREE(cube.first_word); + FREE(cube.last_word); + FREE(cube.sparse); + + free_cube(cube.binary_mask); + free_cube(cube.mv_mask); + free_cube(cube.fullset); + free_cube(cube.emptyset); + for(var = 0; var < cube.num_vars; var++) + free_cube(cube.var_mask[var]); + FREE(cube.var_mask); + + for(i = 0; i < CUBE_TEMP; i++) + free_cube(cube.temp[i]); + FREE(cube.temp); + + FREE(cdata.part_zeros); + FREE(cdata.var_zeros); + FREE(cdata.parts_active); + FREE(cdata.is_unate); + + cube.first_part = cube.last_part = (int *) NULL; + cube.first_word = cube.last_word = (int *) NULL; + cube.sparse = (int *) NULL; + cube.binary_mask = cube.mv_mask = (pcube) NULL; + cube.fullset = cube.emptyset = (pcube) NULL; + cube.var_mask = cube.temp = (pcube *) NULL; + + cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL; + cdata.is_unate = (bool *) NULL; +} + + +void save_cube_struct() +{ + temp_cube_save = cube; /* structure copy ! */ + temp_cdata_save = cdata; /* "" */ + + cube.first_part = cube.last_part = (int *) NULL; + cube.first_word = cube.last_word = (int *) NULL; + cube.part_size = (int *) NULL; + cube.binary_mask = cube.mv_mask = (pcube) NULL; + cube.fullset = cube.emptyset = (pcube) NULL; + cube.var_mask = cube.temp = (pcube *) NULL; + + cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL; + cdata.is_unate = (bool *) NULL; +} + + +void restore_cube_struct() +{ + cube = temp_cube_save; /* structure copy ! */ + cdata = temp_cdata_save; /* "" */ +} diff --git a/abc70930/src/misc/espresso/cvrin.c b/abc70930/src/misc/espresso/cvrin.c new file mode 100644 index 00000000..7790b38b --- /dev/null +++ b/abc70930/src/misc/espresso/cvrin.c @@ -0,0 +1,810 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + module: cvrin.c + purpose: cube and cover input routines +*/ + +#include "espresso.h" + +static bool line_length_error; +static int lineno; + +void skip_line(fpin, fpout, echo) +register FILE *fpin, *fpout; +register bool echo; +{ + register int ch; + while ((ch=getc(fpin)) != EOF && ch != '\n') + if (echo) + putc(ch, fpout); + if (echo) + putc('\n', fpout); + lineno++; +} + +char *get_word(fp, word) +register FILE *fp; +register char *word; +{ + register int ch, i = 0; + while ((ch = getc(fp)) != EOF && isspace(ch)) + ; + word[i++] = ch; + while ((ch = getc(fp)) != EOF && ! isspace(ch)) + word[i++] = ch; + word[i++] = '\0'; + return word; +} + +/* + * Yes, I know this routine is a mess + */ +void read_cube(fp, PLA) +register FILE *fp; +pPLA PLA; +{ + register int var, i; + pcube cf = cube.temp[0], cr = cube.temp[1], cd = cube.temp[2]; + bool savef = FALSE, saved = FALSE, saver = FALSE; + char token[256]; /* for kiss read hack */ + int varx, first, last, offset; /* for kiss read hack */ + + set_clear(cf, cube.size); + + /* Loop and read binary variables */ + for(var = 0; var < cube.num_binary_vars; var++) + switch(getc(fp)) { + case EOF: + goto bad_char; + case '\n': + if (! line_length_error) + (void) fprintf(stderr, "product term(s) %s\n", + "span more than one line (warning only)"); + line_length_error = TRUE; + lineno++; + var--; + break; + case ' ': case '|': case '\t': + var--; + break; + case '2': case '-': + set_insert(cf, var*2+1); + case '0': + set_insert(cf, var*2); + break; + case '1': + set_insert(cf, var*2+1); + break; + case '?': + break; + default: + goto bad_char; + } + + + /* Loop for the all but one of the multiple-valued variables */ + for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) + + /* Read a symbolic multiple-valued variable */ + if (cube.part_size[var] < 0) { + (void) fscanf(fp, "%s", token); + if (equal(token, "-") || equal(token, "ANY")) { + if (kiss && var == cube.num_vars - 2) { + /* leave it empty */ + } else { + /* make it full */ + set_or(cf, cf, cube.var_mask[var]); + } + } else if (equal(token, "~")) { + ; + /* leave it empty ... (?) */ + } else { + if (kiss && var == cube.num_vars - 2) + varx = var - 1, offset = ABS(cube.part_size[var-1]); + else + varx = var, offset = 0; + /* Find the symbolic label in the label table */ + first = cube.first_part[varx]; + last = cube.last_part[varx]; + for(i = first; i <= last; i++) + if (PLA->label[i] == (char *) NULL) { + PLA->label[i] = util_strsav(token); /* add new label */ + set_insert(cf, i+offset); + break; + } else if (equal(PLA->label[i], token)) { + set_insert(cf, i+offset); /* use column i */ + break; + } + if (i > last) { + (void) fprintf(stderr, +"declared size of variable %d (counting from variable 0) is too small\n", var); + exit(-1); + } + } + + } else for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) + switch (getc(fp)) { + case EOF: + goto bad_char; + case '\n': + if (! line_length_error) + (void) fprintf(stderr, "product term(s) %s\n", + "span more than one line (warning only)"); + line_length_error = TRUE; + lineno++; + i--; + break; + case ' ': case '|': case '\t': + i--; + break; + case '1': + set_insert(cf, i); + case '0': + break; + default: + goto bad_char; + } + + /* Loop for last multiple-valued variable */ + if (kiss) { + saver = savef = TRUE; + (void) set_xor(cr, cf, cube.var_mask[cube.num_vars - 2]); + } else + set_copy(cr, cf); + set_copy(cd, cf); + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) + switch (getc(fp)) { + case EOF: + goto bad_char; + case '\n': + if (! line_length_error) + (void) fprintf(stderr, "product term(s) %s\n", + "span more than one line (warning only)"); + line_length_error = TRUE; + lineno++; + i--; + break; + case ' ': case '|': case '\t': + i--; + break; + case '4': case '1': + if (PLA->pla_type & F_type) + set_insert(cf, i), savef = TRUE; + break; + case '3': case '0': + if (PLA->pla_type & R_type) + set_insert(cr, i), saver = TRUE; + break; + case '2': case '-': + if (PLA->pla_type & D_type) + set_insert(cd, i), saved = TRUE; + case '~': + break; + default: + goto bad_char; + } + if (savef) PLA->F = sf_addset(PLA->F, cf); + if (saved) PLA->D = sf_addset(PLA->D, cd); + if (saver) PLA->R = sf_addset(PLA->R, cr); + return; + +bad_char: + (void) fprintf(stderr, "(warning): input line #%d ignored\n", lineno); + skip_line(fp, stdout, TRUE); + return; +} +void parse_pla(fp, PLA) +IN FILE *fp; +INOUT pPLA PLA; +{ + int i, var, ch, np, last; + char word[256]; + + lineno = 1; + line_length_error = FALSE; + +loop: + switch(ch = getc(fp)) { + case EOF: + return; + + case '\n': + lineno++; + + case ' ': case '\t': case '\f': case '\r': + break; + + case '#': + (void) ungetc(ch, fp); + skip_line(fp, stdout, echo_comments); + break; + + case '.': + /* .i gives the cube input size (binary-functions only) */ + if (equal(get_word(fp, word), "i")) { + if (cube.fullset != NULL) { + (void) fprintf(stderr, "extra .i ignored\n"); + skip_line(fp, stdout, /* echo */ FALSE); + } else { + if (fscanf(fp, "%d", &cube.num_binary_vars) != 1) + fatal("error reading .i"); + cube.num_vars = cube.num_binary_vars + 1; + cube.part_size = ALLOC(int, cube.num_vars); + } + + /* .o gives the cube output size (binary-functions only) */ + } else if (equal(word, "o")) { + if (cube.fullset != NULL) { + (void) fprintf(stderr, "extra .o ignored\n"); + skip_line(fp, stdout, /* echo */ FALSE); + } else { + if (cube.part_size == NULL) + fatal(".o cannot appear before .i"); + if (fscanf(fp, "%d", &(cube.part_size[cube.num_vars-1]))!=1) + fatal("error reading .o"); + cube_setup(); + PLA_labels(PLA); + } + + /* .mv gives the cube size for a multiple-valued function */ + } else if (equal(word, "mv")) { + if (cube.fullset != NULL) { + (void) fprintf(stderr, "extra .mv ignored\n"); + skip_line(fp, stdout, /* echo */ FALSE); + } else { + if (cube.part_size != NULL) + fatal("cannot mix .i and .mv"); + if (fscanf(fp,"%d %d", + &cube.num_vars,&cube.num_binary_vars) != 2) + fatal("error reading .mv"); + if (cube.num_binary_vars < 0) +fatal("num_binary_vars (second field of .mv) cannot be negative"); + if (cube.num_vars < cube.num_binary_vars) + fatal( +"num_vars (1st field of .mv) must exceed num_binary_vars (2nd field of .mv)"); + cube.part_size = ALLOC(int, cube.num_vars); + for(var=cube.num_binary_vars; var < cube.num_vars; var++) + if (fscanf(fp, "%d", &(cube.part_size[var])) != 1) + fatal("error reading .mv"); + cube_setup(); + PLA_labels(PLA); + } + + /* .p gives the number of product terms -- we ignore it */ + } else if (equal(word, "p")) + (void) fscanf(fp, "%d", &np); + /* .e and .end specify the end of the file */ + else if (equal(word, "e") || equal(word,"end")) { + if (cube.fullset == NULL) { + /* fatal("unknown PLA size, need .i/.o or .mv");*/ + } else if (PLA->F == NULL) { + PLA->F = new_cover(10); + PLA->D = new_cover(10); + PLA->R = new_cover(10); + } + return; + } + /* .kiss turns on the kiss-hack option */ + else if (equal(word, "kiss")) + kiss = TRUE; + + /* .type specifies a logical type for the PLA */ + else if (equal(word, "type")) { + (void) get_word(fp, word); + for(i = 0; pla_types[i].key != 0; i++) + if (equal(pla_types[i].key + 1, word)) { + PLA->pla_type = pla_types[i].value; + break; + } + if (pla_types[i].key == 0) + fatal("unknown type in .type command"); + + /* parse the labels */ + } else if (equal(word, "ilb")) { + if (cube.fullset == NULL) + fatal("PLA size must be declared before .ilb or .ob"); + if (PLA->label == NULL) + PLA_labels(PLA); + for(var = 0; var < cube.num_binary_vars; var++) { + (void) get_word(fp, word); + i = cube.first_part[var]; + PLA->label[i+1] = util_strsav(word); + PLA->label[i] = ALLOC(char, strlen(word) + 6); + (void) sprintf(PLA->label[i], "%s.bar", word); + } + } else if (equal(word, "ob")) { + if (cube.fullset == NULL) + fatal("PLA size must be declared before .ilb or .ob"); + if (PLA->label == NULL) + PLA_labels(PLA); + var = cube.num_vars - 1; + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + (void) get_word(fp, word); + PLA->label[i] = util_strsav(word); + } + /* .label assigns labels to multiple-valued variables */ + } else if (equal(word, "label")) { + if (cube.fullset == NULL) + fatal("PLA size must be declared before .label"); + if (PLA->label == NULL) + PLA_labels(PLA); + if (fscanf(fp, "var=%d", &var) != 1) + fatal("Error reading labels"); + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + (void) get_word(fp, word); + PLA->label[i] = util_strsav(word); + } + + } else if (equal(word, "symbolic")) { + symbolic_t *newlist, *p1; + if (read_symbolic(fp, PLA, word, &newlist)) { + if (PLA->symbolic == NIL(symbolic_t)) { + PLA->symbolic = newlist; + } else { + for(p1=PLA->symbolic;p1->next!=NIL(symbolic_t); + p1=p1->next){ + } + p1->next = newlist; + } + } else { + fatal("error reading .symbolic"); + } + + } else if (equal(word, "symbolic-output")) { + symbolic_t *newlist, *p1; + if (read_symbolic(fp, PLA, word, &newlist)) { + if (PLA->symbolic_output == NIL(symbolic_t)) { + PLA->symbolic_output = newlist; + } else { + for(p1=PLA->symbolic_output;p1->next!=NIL(symbolic_t); + p1=p1->next){ + } + p1->next = newlist; + } + } else { + fatal("error reading .symbolic-output"); + } + + /* .phase allows a choice of output phases */ + } else if (equal(word, "phase")) { + if (cube.fullset == NULL) + fatal("PLA size must be declared before .phase"); + if (PLA->phase != NULL) { + (void) fprintf(stderr, "extra .phase ignored\n"); + skip_line(fp, stdout, /* echo */ FALSE); + } else { + do ch = getc(fp); while (ch == ' ' || ch == '\t'); + (void) ungetc(ch, fp); + PLA->phase = set_save(cube.fullset); + last = cube.last_part[cube.num_vars - 1]; + for(i=cube.first_part[cube.num_vars - 1]; i <= last; i++) + if ((ch = getc(fp)) == '0') + set_remove(PLA->phase, i); + else if (ch != '1') + fatal("only 0 or 1 allowed in phase description"); + } + + /* .pair allows for bit-pairing input variables */ + } else if (equal(word, "pair")) { + int j; + if (PLA->pair != NULL) { + (void) fprintf(stderr, "extra .pair ignored\n"); + } else { + ppair pair; + PLA->pair = pair = ALLOC(pair_t, 1); + if (fscanf(fp, "%d", &(pair->cnt)) != 1) + fatal("syntax error in .pair"); + pair->var1 = ALLOC(int, pair->cnt); + pair->var2 = ALLOC(int, pair->cnt); + for(i = 0; i < pair->cnt; i++) { + (void) get_word(fp, word); + if (word[0] == '(') (void) strcpy(word, word+1); + if (label_index(PLA, word, &var, &j)) { + pair->var1[i] = var+1; + } else { + fatal("syntax error in .pair"); + } + + (void) get_word(fp, word); + if (word[strlen(word)-1] == ')') { + word[strlen(word)-1]='\0'; + } + if (label_index(PLA, word, &var, &j)) { + pair->var2[i] = var+1; + } else { + fatal("syntax error in .pair"); + } + } + } + + } else { + if (echo_unknown_commands) + printf("%c%s ", ch, word); + skip_line(fp, stdout, echo_unknown_commands); + } + break; + default: + (void) ungetc(ch, fp); + if (cube.fullset == NULL) { +/* fatal("unknown PLA size, need .i/.o or .mv");*/ + if (echo_comments) + putchar('#'); + skip_line(fp, stdout, echo_comments); + break; + } + if (PLA->F == NULL) { + PLA->F = new_cover(10); + PLA->D = new_cover(10); + PLA->R = new_cover(10); + } + read_cube(fp, PLA); + } + goto loop; +} +/* + read_pla -- read a PLA from a file + + Input stops when ".e" is encountered in the input file, or upon reaching + end of file. + + Returns the PLA in the variable PLA after massaging the "symbolic" + representation into a positional cube notation of the ON-set, OFF-set, + and the DC-set. + + needs_dcset and needs_offset control the computation of the OFF-set + and DC-set (i.e., if either needs to be computed, then it will be + computed via complement only if the corresponding option is TRUE.) + pla_type specifies the interpretation to be used when reading the + PLA. + + The phase of the output functions is adjusted according to the + global option "pos" or according to an imbedded .phase option in + the input file. Note that either phase option implies that the + OFF-set be computed regardless of whether the caller needs it + explicitly or not. + + Bit pairing of the binary variables is performed according to an + imbedded .pair option in the input file. + + The global cube structure also reflects the sizes of the PLA which + was just read. If these fields have already been set, then any + subsequent PLA must conform to these sizes. + + The global flags trace and summary control the output produced + during the read. + + Returns a status code as a result: + EOF (-1) : End of file reached before any data was read + > 0 : Operation successful +*/ + +int read_pla(fp, needs_dcset, needs_offset, pla_type, PLA_return) +IN FILE *fp; +IN bool needs_dcset, needs_offset; +IN int pla_type; +OUT pPLA *PLA_return; +{ + pPLA PLA; + int i, second, third; + long time; + cost_t cost; + + /* Allocate and initialize the PLA structure */ + PLA = *PLA_return = new_PLA(); + PLA->pla_type = pla_type; + + /* Read the pla */ + time = ptime(); + parse_pla(fp, PLA); + + /* Check for nothing on the file -- implies reached EOF */ + if (PLA->F == NULL) { + return EOF; + } + + /* This hack merges the next-state field with the outputs */ + for(i = 0; i < cube.num_vars; i++) { + cube.part_size[i] = ABS(cube.part_size[i]); + } + if (kiss) { + third = cube.num_vars - 3; + second = cube.num_vars - 2; + if (cube.part_size[third] != cube.part_size[second]) { + (void) fprintf(stderr," with .kiss option, third to last and second\n"); + (void) fprintf(stderr, "to last variables must be the same size.\n"); + return EOF; + } + for(i = 0; i < cube.part_size[second]; i++) { + PLA->label[i + cube.first_part[second]] = + util_strsav(PLA->label[i + cube.first_part[third]]); + } + cube.part_size[second] += cube.part_size[cube.num_vars-1]; + cube.num_vars--; + setdown_cube(); + cube_setup(); + } + + if (trace) { + totals(time, READ_TIME, PLA->F, &cost); + } + + /* Decide how to break PLA into ON-set, OFF-set and DC-set */ + time = ptime(); + if (pos || PLA->phase != NULL || PLA->symbolic_output != NIL(symbolic_t)) { + needs_offset = TRUE; + } + if (needs_offset && (PLA->pla_type==F_type || PLA->pla_type==FD_type)) { + free_cover(PLA->R); + PLA->R = complement(cube2list(PLA->F, PLA->D)); + } else if (needs_dcset && PLA->pla_type == FR_type) { + pcover X; + free_cover(PLA->D); + /* hack, why not? */ + X = d1merge(sf_join(PLA->F, PLA->R), cube.num_vars - 1); + PLA->D = complement(cube1list(X)); + free_cover(X); + } else if (PLA->pla_type == R_type || PLA->pla_type == DR_type) { + free_cover(PLA->F); + PLA->F = complement(cube2list(PLA->D, PLA->R)); + } + + if (trace) { + totals(time, COMPL_TIME, PLA->R, &cost); + } + + /* Check for phase rearrangement of the functions */ + if (pos) { + pcover onset = PLA->F; + PLA->F = PLA->R; + PLA->R = onset; + PLA->phase = new_cube(); + set_diff(PLA->phase, cube.fullset, cube.var_mask[cube.num_vars-1]); + } else if (PLA->phase != NULL) { + (void) set_phase(PLA); + } + + /* Setup minimization for two-bit decoders */ + if (PLA->pair != (ppair) NULL) { + set_pair(PLA); + } + + if (PLA->symbolic != NIL(symbolic_t)) { + EXEC(map_symbolic(PLA), "MAP-INPUT ", PLA->F); + } + if (PLA->symbolic_output != NIL(symbolic_t)) { + EXEC(map_output_symbolic(PLA), "MAP-OUTPUT ", PLA->F); + if (needs_offset) { + free_cover(PLA->R); +EXECUTE(PLA->R=complement(cube2list(PLA->F,PLA->D)), COMPL_TIME, PLA->R, cost); + } + } + + return 1; +} + +void PLA_summary(PLA) +pPLA PLA; +{ + int var, i; + symbolic_list_t *p2; + symbolic_t *p1; + + printf("# PLA is %s", PLA->filename); + if (cube.num_binary_vars == cube.num_vars - 1) + printf(" with %d inputs and %d outputs\n", + cube.num_binary_vars, cube.part_size[cube.num_vars - 1]); + else { + printf(" with %d variables (%d binary, mv sizes", + cube.num_vars, cube.num_binary_vars); + for(var = cube.num_binary_vars; var < cube.num_vars; var++) + printf(" %d", cube.part_size[var]); + printf(")\n"); + } + printf("# ON-set cost is %s\n", print_cost(PLA->F)); + printf("# OFF-set cost is %s\n", print_cost(PLA->R)); + printf("# DC-set cost is %s\n", print_cost(PLA->D)); + if (PLA->phase != NULL) + printf("# phase is %s\n", pc1(PLA->phase)); + if (PLA->pair != NULL) { + printf("# two-bit decoders:"); + for(i = 0; i < PLA->pair->cnt; i++) + printf(" (%d %d)", PLA->pair->var1[i], PLA->pair->var2[i]); + printf("\n"); + } + if (PLA->symbolic != NIL(symbolic_t)) { + for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { + printf("# symbolic: "); + for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { + printf(" %d", p2->variable); + } + printf("\n"); + } + } + if (PLA->symbolic_output != NIL(symbolic_t)) { + for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1->next) { + printf("# output symbolic: "); + for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { + printf(" %d", p2->pos); + } + printf("\n"); + } + } + (void) fflush(stdout); +} + + +pPLA new_PLA() +{ + pPLA PLA; + + PLA = ALLOC(PLA_t, 1); + PLA->F = PLA->D = PLA->R = (pcover) NULL; + PLA->phase = (pcube) NULL; + PLA->pair = (ppair) NULL; + PLA->label = (char **) NULL; + PLA->filename = (char *) NULL; + PLA->pla_type = 0; + PLA->symbolic = NIL(symbolic_t); + PLA->symbolic_output = NIL(symbolic_t); + return PLA; +} + + +PLA_labels(PLA) +pPLA PLA; +{ + int i; + + PLA->label = ALLOC(char *, cube.size); + for(i = 0; i < cube.size; i++) + PLA->label[i] = (char *) NULL; +} + + +void free_PLA(PLA) +pPLA PLA; +{ + symbolic_list_t *p2, *p2next; + symbolic_t *p1, *p1next; + int i; + + if (PLA->F != (pcover) NULL) + free_cover(PLA->F); + if (PLA->R != (pcover) NULL) + free_cover(PLA->R); + if (PLA->D != (pcover) NULL) + free_cover(PLA->D); + if (PLA->phase != (pcube) NULL) + free_cube(PLA->phase); + if (PLA->pair != (ppair) NULL) { + FREE(PLA->pair->var1); + FREE(PLA->pair->var2); + FREE(PLA->pair); + } + if (PLA->label != NULL) { + for(i = 0; i < cube.size; i++) + if (PLA->label[i] != NULL) + FREE(PLA->label[i]); + FREE(PLA->label); + } + if (PLA->filename != NULL) { + FREE(PLA->filename); + } + for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1next) { + for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) { + p2next = p2->next; + FREE(p2); + } + p1next = p1->next; + FREE(p1); + } + PLA->symbolic = NIL(symbolic_t); + for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1next) { + for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) { + p2next = p2->next; + FREE(p2); + } + p1next = p1->next; + FREE(p1); + } + PLA->symbolic_output = NIL(symbolic_t); + FREE(PLA); +} + + +int read_symbolic(fp, PLA, word, retval) +FILE *fp; +pPLA PLA; +char *word; /* scratch string for words */ +symbolic_t **retval; +{ + symbolic_list_t *listp, *prev_listp; + symbolic_label_t *labelp, *prev_labelp; + symbolic_t *newlist; + int i, var; + + newlist = ALLOC(symbolic_t, 1); + newlist->next = NIL(symbolic_t); + newlist->symbolic_list = NIL(symbolic_list_t); + newlist->symbolic_list_length = 0; + newlist->symbolic_label = NIL(symbolic_label_t); + newlist->symbolic_label_length = 0; + prev_listp = NIL(symbolic_list_t); + prev_labelp = NIL(symbolic_label_t); + + for(;;) { + (void) get_word(fp, word); + if (equal(word, ";")) + break; + if (label_index(PLA, word, &var, &i)) { + listp = ALLOC(symbolic_list_t, 1); + listp->variable = var; + listp->pos = i; + listp->next = NIL(symbolic_list_t); + if (prev_listp == NIL(symbolic_list_t)) { + newlist->symbolic_list = listp; + } else { + prev_listp->next = listp; + } + prev_listp = listp; + newlist->symbolic_list_length++; + } else { + return FALSE; + } + } + + for(;;) { + (void) get_word(fp, word); + if (equal(word, ";")) + break; + labelp = ALLOC(symbolic_label_t, 1); + labelp->label = util_strsav(word); + labelp->next = NIL(symbolic_label_t); + if (prev_labelp == NIL(symbolic_label_t)) { + newlist->symbolic_label = labelp; + } else { + prev_labelp->next = labelp; + } + prev_labelp = labelp; + newlist->symbolic_label_length++; + } + + *retval = newlist; + return TRUE; +} + + +int label_index(PLA, word, varp, ip) +pPLA PLA; +char *word; +int *varp; +int *ip; +{ + int var, i; + + if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) { + if (sscanf(word, "%d", varp) == 1) { + *ip = *varp; + return TRUE; + } + } else { + for(var = 0; var < cube.num_vars; var++) { + for(i = 0; i < cube.part_size[var]; i++) { + if (equal(PLA->label[cube.first_part[var]+i], word)) { + *varp = var; + *ip = i; + return TRUE; + } + } + } + } + return FALSE; +} diff --git a/abc70930/src/misc/espresso/cvrm.c b/abc70930/src/misc/espresso/cvrm.c new file mode 100644 index 00000000..7d42d6e3 --- /dev/null +++ b/abc70930/src/misc/espresso/cvrm.c @@ -0,0 +1,539 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + module: cvrm.c + Purpose: miscellaneous cover manipulation + a) verify two covers are equal, check consistency of a cover + b) unravel a multiple-valued cover into minterms + c) sort covers +*/ + +#include "espresso.h" + + +static void cb_unravel(c, start, end, startbase, B1) +IN register pcube c; +IN int start, end; +IN pcube startbase; +INOUT pcover B1; +{ + pcube base = cube.temp[0], p, last; + int expansion, place, skip, var, size, offset; + register int i, j, k, n; + + /* Determine how many cubes it will blow up into, and create a mask + for those parts that have only a single coordinate + */ + expansion = 1; + (void) set_copy(base, startbase); + for(var = start; var <= end; var++) { + if ((size = set_dist(c, cube.var_mask[var])) < 2) { + (void) set_or(base, base, cube.var_mask[var]); + } else { + expansion *= size; + } + } + (void) set_and(base, c, base); + + /* Add the unravelled sets starting at the last element of B1 */ + offset = B1->count; + B1->count += expansion; + foreach_remaining_set(B1, last, GETSET(B1, offset-1), p) { + INLINEset_copy(p, base); + } + + place = expansion; + for(var = start; var <= end; var++) { + if ((size = set_dist(c, cube.var_mask[var])) > 1) { + skip = place; + place = place / size; + n = 0; + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + if (is_in_set(c, i)) { + for(j = n; j < expansion; j += skip) { + for(k = 0; k < place; k++) { + p = GETSET(B1, j+k+offset); + (void) set_insert(p, i); + } + } + n += place; + } + } + } + } +} + + +pcover unravel_range(B, start, end) +IN pcover B; +IN int start, end; +{ + pcover B1; + int var, total_size, expansion, size; + register pcube p, last, startbase = cube.temp[1]; + + /* Create the starting base for those variables not being unravelled */ + (void) set_copy(startbase, cube.emptyset); + for(var = 0; var < start; var++) + (void) set_or(startbase, startbase, cube.var_mask[var]); + for(var = end+1; var < cube.num_vars; var++) + (void) set_or(startbase, startbase, cube.var_mask[var]); + + /* Determine how many cubes it will blow up into */ + total_size = 0; + foreach_set(B, last, p) { + expansion = 1; + for(var = start; var <= end; var++) + if ((size = set_dist(p, cube.var_mask[var])) >= 2) + if ((expansion *= size) > 1000000) + fatal("unreasonable expansion in unravel"); + total_size += expansion; + } + + /* We can now allocate a cover of exactly the correct size */ + B1 = new_cover(total_size); + foreach_set(B, last, p) { + cb_unravel(p, start, end, startbase, B1); + } + free_cover(B); + return B1; +} + + +pcover unravel(B, start) +IN pcover B; +IN int start; +{ + return unravel_range(B, start, cube.num_vars-1); +} + +/* lex_sort -- sort cubes in a standard lexical fashion */ +pcover lex_sort(T) +pcover T; +{ + pcover T1 = sf_unlist(sf_sort(T, lex_order), T->count, T->sf_size); + free_cover(T); + return T1; +} + + +/* size_sort -- sort cubes by their size */ +pcover size_sort(T) +pcover T; +{ + pcover T1 = sf_unlist(sf_sort(T, descend), T->count, T->sf_size); + free_cover(T); + return T1; +} + + +/* mini_sort -- sort cubes according to the heuristics of mini */ +pcover mini_sort(F, compare) +pcover F; +int (*compare)(); +{ + register int *count, cnt, n = cube.size, i; + register pcube p, last; + pcover F_sorted; + pcube *F1; + + /* Perform a column sum over the set family */ + count = sf_count(F); + + /* weight is "inner product of the cube and the column sums" */ + foreach_set(F, last, p) { + cnt = 0; + for(i = 0; i < n; i++) + if (is_in_set(p, i)) + cnt += count[i]; + PUTSIZE(p, cnt); + } + FREE(count); + + /* use qsort to sort the array */ + qsort((char *) (F1 = sf_list(F)), F->count, sizeof(pcube), compare); + F_sorted = sf_unlist(F1, F->count, F->sf_size); + free_cover(F); + + return F_sorted; +} + + +/* sort_reduce -- Espresso strategy for ordering the cubes before reduction */ +pcover sort_reduce(T) +IN pcover T; +{ + register pcube p, last, largest = NULL; + register int bestsize = -1, size, n = cube.num_vars; + pcover T_sorted; + pcube *T1; + + if (T->count == 0) + return T; + + /* find largest cube */ + foreach_set(T, last, p) + if ((size = set_ord(p)) > bestsize) + largest = p, bestsize = size; + + foreach_set(T, last, p) + PUTSIZE(p, ((n - cdist(largest,p)) << 7) + MIN(set_ord(p),127)); + + qsort((char *) (T1 = sf_list(T)), T->count, sizeof(pcube), (int (*)()) descend); + T_sorted = sf_unlist(T1, T->count, T->sf_size); + free_cover(T); + + return T_sorted; +} + +pcover random_order(F) +register pcover F; +{ + pset temp; + register int i, k; +#ifdef RANDOM + long random(); +#endif + + temp = set_new(F->sf_size); + for(i = F->count - 1; i > 0; i--) { + /* Choose a random number between 0 and i */ +#ifdef RANDOM + k = random() % i; +#else + /* this is not meant to be really used; just provides an easy + "out" if random() and srandom() aren't around + */ + k = (i*23 + 997) % i; +#endif + /* swap sets i and k */ + (void) set_copy(temp, GETSET(F, k)); + (void) set_copy(GETSET(F, k), GETSET(F, i)); + (void) set_copy(GETSET(F, i), temp); + } + set_free(temp); + return F; +} + +/* + * cubelist_partition -- take a cubelist T and see if it has any components; + * if so, return cubelist's of the two partitions A and B; the return value + * is the size of the partition; if not, A and B + * are undefined and the return value is 0 + */ +int cubelist_partition(T, A, B, comp_debug) +pcube *T; /* a list of cubes */ +pcube **A, **B; /* cubelist of partition and remainder */ +unsigned int comp_debug; +{ + register pcube *T1, p, seed, cof; + pcube *A1, *B1; + bool change; + int count, numcube; + + numcube = CUBELISTSIZE(T); + + /* Mark all cubes -- covered cubes belong to the partition */ + for(T1 = T+2; (p = *T1++) != NULL; ) { + RESET(p, COVERED); + } + + /* + * Extract a partition from the cubelist T; start with the first cube as a + * seed, and then pull in all cubes which share a variable with the seed; + * iterate until no new cubes are brought into the partition. + */ + seed = set_save(T[2]); + cof = T[0]; + SET(T[2], COVERED); + count = 1; + + do { + change = FALSE; + for(T1 = T+2; (p = *T1++) != NULL; ) { + if (! TESTP(p, COVERED) && ccommon(p, seed, cof)) { + INLINEset_and(seed, seed, p); + SET(p, COVERED); + change = TRUE; + count++; + } + + } + } while (change); + + set_free(seed); + + if (comp_debug) { + (void) printf("COMPONENT_REDUCTION: split into %d %d\n", + count, numcube - count); + } + + if (count != numcube) { + /* Allocate and setup the cubelist's for the two partitions */ + *A = A1 = ALLOC(pcube, numcube+3); + *B = B1 = ALLOC(pcube, numcube+3); + (*A)[0] = set_save(T[0]); + (*B)[0] = set_save(T[0]); + A1 = *A + 2; + B1 = *B + 2; + + /* Loop over the cubes in T and distribute to A and B */ + for(T1 = T+2; (p = *T1++) != NULL; ) { + if (TESTP(p, COVERED)) { + *A1++ = p; + } else { + *B1++ = p; + } + } + + /* Stuff needed at the end of the cubelist's */ + *A1++ = NULL; + (*A)[1] = (pcube) A1; + *B1++ = NULL; + (*B)[1] = (pcube) B1; + } + + return numcube - count; +} + +/* + * quick cofactor against a single output function + */ +pcover cof_output(T, i) +pcover T; +register int i; +{ + pcover T1; + register pcube p, last, pdest, mask; + + mask = cube.var_mask[cube.output]; + T1 = new_cover(T->count); + foreach_set(T, last, p) { + if (is_in_set(p, i)) { + pdest = GETSET(T1, T1->count++); + INLINEset_or(pdest, p, mask); + RESET(pdest, PRIME); + } + } + return T1; +} + + +/* + * quick intersection against a single output function + */ +pcover uncof_output(T, i) +pcover T; +int i; +{ + register pcube p, last, mask; + + if (T == NULL) { + return T; + } + + mask = cube.var_mask[cube.output]; + foreach_set(T, last, p) { + INLINEset_diff(p, p, mask); + set_insert(p, i); + } + return T; +} + + +/* + * A generic routine to perform an operation for each output function + * + * func() is called with a PLA for each output function (with the output + * part effectively removed). + * func1() is called after reforming the equivalent output function + * + * Each function returns TRUE if process is to continue + */ +foreach_output_function(PLA, func, func1) +pPLA PLA; +int (*func)(); +int (*func1)(); +{ + pPLA PLA1; + int i; + + /* Loop for each output function */ + for(i = 0; i < cube.part_size[cube.output]; i++) { + + /* cofactor on the output part */ + PLA1 = new_PLA(); + PLA1->F = cof_output(PLA->F, i + cube.first_part[cube.output]); + PLA1->R = cof_output(PLA->R, i + cube.first_part[cube.output]); + PLA1->D = cof_output(PLA->D, i + cube.first_part[cube.output]); + + /* Call a routine to do something with the cover */ + if ((*func)(PLA1, i) == 0) { + free_PLA(PLA1); + return; + } + + /* intersect with the particular output part again */ + PLA1->F = uncof_output(PLA1->F, i + cube.first_part[cube.output]); + PLA1->R = uncof_output(PLA1->R, i + cube.first_part[cube.output]); + PLA1->D = uncof_output(PLA1->D, i + cube.first_part[cube.output]); + + /* Call a routine to do something with the final result */ + if ((*func1)(PLA1, i) == 0) { + free_PLA(PLA1); + return; + } + + /* Cleanup for next go-around */ + free_PLA(PLA1); + + + } +} + +static pcover Fmin; +static pcube phase; + +/* + * minimize each output function individually + */ +void so_espresso(PLA, strategy) +pPLA PLA; +int strategy; +{ + Fmin = new_cover(PLA->F->count); + if (strategy == 0) { + foreach_output_function(PLA, so_do_espresso, so_save); + } else { + foreach_output_function(PLA, so_do_exact, so_save); + } + sf_free(PLA->F); + PLA->F = Fmin; +} + + +/* + * minimize each output function, choose function or complement based on the + * one with the fewer number of terms + */ +void so_both_espresso(PLA, strategy) +pPLA PLA; +int strategy; +{ + phase = set_save(cube.fullset); + Fmin = new_cover(PLA->F->count); + if (strategy == 0) { + foreach_output_function(PLA, so_both_do_espresso, so_both_save); + } else { + foreach_output_function(PLA, so_both_do_exact, so_both_save); + } + sf_free(PLA->F); + PLA->F = Fmin; + PLA->phase = phase; +} + + +int so_do_espresso(PLA, i) +pPLA PLA; +int i; +{ + char word[32]; + + /* minimize the single-output function (on-set) */ + skip_make_sparse = 1; + (void) sprintf(word, "ESPRESSO-POS(%d)", i); + EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F); + return 1; +} + + +int so_do_exact(PLA, i) +pPLA PLA; +int i; +{ + char word[32]; + + /* minimize the single-output function (on-set) */ + skip_make_sparse = 1; + (void) sprintf(word, "EXACT-POS(%d)", i); + EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F); + return 1; +} + + +/*ARGSUSED*/ +int so_save(PLA, i) +pPLA PLA; +int i; +{ + Fmin = sf_append(Fmin, PLA->F); /* disposes of PLA->F */ + PLA->F = NULL; + return 1; +} + + +int so_both_do_espresso(PLA, i) +pPLA PLA; +int i; +{ + char word[32]; + + /* minimize the single-output function (on-set) */ + (void) sprintf(word, "ESPRESSO-POS(%d)", i); + skip_make_sparse = 1; + EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F); + + /* minimize the single-output function (off-set) */ + (void) sprintf(word, "ESPRESSO-NEG(%d)", i); + skip_make_sparse = 1; + EXEC_S(PLA->R = espresso(PLA->R, PLA->D, PLA->F), word, PLA->R); + + return 1; +} + + +int so_both_do_exact(PLA, i) +pPLA PLA; +int i; +{ + char word[32]; + + /* minimize the single-output function (on-set) */ + (void) sprintf(word, "EXACT-POS(%d)", i); + skip_make_sparse = 1; + EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F); + + /* minimize the single-output function (off-set) */ + (void) sprintf(word, "EXACT-NEG(%d)", i); + skip_make_sparse = 1; + EXEC_S(PLA->R = minimize_exact(PLA->R, PLA->D, PLA->F, 1), word, PLA->R); + + return 1; +} + + +int so_both_save(PLA, i) +pPLA PLA; +int i; +{ + if (PLA->F->count > PLA->R->count) { + sf_free(PLA->F); + PLA->F = PLA->R; + PLA->R = NULL; + i += cube.first_part[cube.output]; + set_remove(phase, i); + } else { + sf_free(PLA->R); + PLA->R = NULL; + } + Fmin = sf_append(Fmin, PLA->F); + PLA->F = NULL; + return 1; +} diff --git a/abc70930/src/misc/espresso/cvrmisc.c b/abc70930/src/misc/espresso/cvrmisc.c new file mode 100644 index 00000000..0f3de195 --- /dev/null +++ b/abc70930/src/misc/espresso/cvrmisc.c @@ -0,0 +1,142 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + + +/* cost -- compute the cost of a cover */ +void cover_cost(F, cost) +IN pcover F; +INOUT pcost cost; +{ + register pcube p, last; + pcube *T; + int var; + + /* use the routine used by cofactor to decide splitting variables */ + massive_count(T = cube1list(F)); + free_cubelist(T); + + cost->cubes = F->count; + cost->total = cost->in = cost->out = cost->mv = cost->primes = 0; + + /* Count transistors (zeros) for each binary variable (inputs) */ + for(var = 0; var < cube.num_binary_vars; var++) + cost->in += cdata.var_zeros[var]; + + /* Count transistors for each mv variable based on sparse/dense */ + for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) + if (cube.sparse[var]) + cost->mv += F->count * cube.part_size[var] - cdata.var_zeros[var]; + else + cost->mv += cdata.var_zeros[var]; + + /* Count the transistors (ones) for the output variable */ + if (cube.num_binary_vars != cube.num_vars) { + var = cube.num_vars - 1; + cost->out = F->count * cube.part_size[var] - cdata.var_zeros[var]; + } + + /* Count the number of nonprime cubes */ + foreach_set(F, last, p) + cost->primes += TESTP(p, PRIME) != 0; + + /* Count the total number of literals */ + cost->total = cost->in + cost->out + cost->mv; +} + + +/* fmt_cost -- return a string which reports the "cost" of a cover */ +char *fmt_cost(cost) +IN pcost cost; +{ + static char s[200]; + + if (cube.num_binary_vars == cube.num_vars - 1) + (void) sprintf(s, "c=%d(%d) in=%d out=%d tot=%d", + cost->cubes, cost->cubes - cost->primes, cost->in, + cost->out, cost->total); + else + (void) sprintf(s, "c=%d(%d) in=%d mv=%d out=%d", + cost->cubes, cost->cubes - cost->primes, cost->in, + cost->mv, cost->out); + return s; +} + + +char *print_cost(F) +IN pcover F; +{ + cost_t cost; + cover_cost(F, &cost); + return fmt_cost(&cost); +} + + +/* copy_cost -- copy a cost function from s to d */ +void copy_cost(s, d) +pcost s, d; +{ + d->cubes = s->cubes; + d->in = s->in; + d->out = s->out; + d->mv = s->mv; + d->total = s->total; + d->primes = s->primes; +} + + +/* size_stamp -- print single line giving the size of a cover */ +void size_stamp(T, name) +IN pcover T; +IN char *name; +{ + (void) printf("# %s\tCost is %s\n", name, print_cost(T)); + (void) fflush(stdout); +} + + +/* print_trace -- print a line reporting size and time after a function */ +void print_trace(T, name, time) +pcover T; +char *name; +long time; +{ + (void) printf("# %s\tTime was %s, cost is %s\n", + name, print_time(time), print_cost(T)); + (void) fflush(stdout); +} + + +/* totals -- add time spent in the function into the totals */ +void totals(time, i, T, cost) +long time; +int i; +pcover T; +pcost cost; +{ + time = ptime() - time; + total_time[i] += time; + total_calls[i]++; + cover_cost(T, cost); + if (trace) { + (void) printf("# %s\tTime was %s, cost is %s\n", + total_name[i], print_time(time), fmt_cost(cost)); + (void) fflush(stdout); + } +} + + +/* fatal -- report fatal error message and take a dive */ +void fatal(s) +char *s; +{ + (void) fprintf(stderr, "espresso: %s\n", s); + exit(1); +} diff --git a/abc70930/src/misc/espresso/cvrout.c b/abc70930/src/misc/espresso/cvrout.c new file mode 100644 index 00000000..4bd1c53b --- /dev/null +++ b/abc70930/src/misc/espresso/cvrout.c @@ -0,0 +1,609 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + module: cvrout.c + purpose: cube and cover output routines +*/ + +#include "espresso.h" + +void fprint_pla(fp, PLA, output_type) +INOUT FILE *fp; +IN pPLA PLA; +IN int output_type; +{ + int num; + register pcube last, p; + + if ((output_type & CONSTRAINTS_type) != 0) { + output_symbolic_constraints(fp, PLA, 0); + output_type &= ~ CONSTRAINTS_type; + if (output_type == 0) { + return; + } + } + + if ((output_type & SYMBOLIC_CONSTRAINTS_type) != 0) { + output_symbolic_constraints(fp, PLA, 1); + output_type &= ~ SYMBOLIC_CONSTRAINTS_type; + if (output_type == 0) { + return; + } + } + + if (output_type == PLEASURE_type) { + pls_output(PLA); + } else if (output_type == EQNTOTT_type) { + eqn_output(PLA); + } else if (output_type == KISS_type) { + kiss_output(fp, PLA); + } else { + fpr_header(fp, PLA, output_type); + + num = 0; + if (output_type & F_type) num += (PLA->F)->count; + if (output_type & D_type) num += (PLA->D)->count; + if (output_type & R_type) num += (PLA->R)->count; + (void) fprintf(fp, ".p %d\n", num); + + /* quick patch 01/17/85 to support TPLA ! */ + if (output_type == F_type) { + foreach_set(PLA->F, last, p) { + print_cube(fp, p, "01"); + } + (void) fprintf(fp, ".e\n"); + } else { + if (output_type & F_type) { + foreach_set(PLA->F, last, p) { + print_cube(fp, p, "~1"); + } + } + if (output_type & D_type) { + foreach_set(PLA->D, last, p) { + print_cube(fp, p, "~2"); + } + } + if (output_type & R_type) { + foreach_set(PLA->R, last, p) { + print_cube(fp, p, "~0"); + } + } + (void) fprintf(fp, ".end\n"); + } + } +} + +void fpr_header(fp, PLA, output_type) +FILE *fp; +pPLA PLA; +int output_type; +{ + register int i, var; + int first, last; + + /* .type keyword gives logical type */ + if (output_type != F_type) { + (void) fprintf(fp, ".type "); + if (output_type & F_type) putc('f', fp); + if (output_type & D_type) putc('d', fp); + if (output_type & R_type) putc('r', fp); + putc('\n', fp); + } + + /* Check for binary or multiple-valued labels */ + if (cube.num_mv_vars <= 1) { + (void) fprintf(fp, ".i %d\n", cube.num_binary_vars); + if (cube.output != -1) + (void) fprintf(fp, ".o %d\n", cube.part_size[cube.output]); + } else { + (void) fprintf(fp, ".mv %d %d", cube.num_vars, cube.num_binary_vars); + for(var = cube.num_binary_vars; var < cube.num_vars; var++) + (void) fprintf(fp, " %d", cube.part_size[var]); + (void) fprintf(fp, "\n"); + } + + /* binary valued labels */ + if (PLA->label != NIL(char *) && PLA->label[1] != NIL(char) + && cube.num_binary_vars > 0) { + (void) fprintf(fp, ".ilb"); + for(var = 0; var < cube.num_binary_vars; var++) + /* see (NIL) OUTLABELS comment below */ + if(INLABEL(var) == NIL(char)){ + (void) fprintf(fp, " (null)"); + } + else{ + (void) fprintf(fp, " %s", INLABEL(var)); + } + putc('\n', fp); + } + + /* output-part (last multiple-valued variable) labels */ + if (PLA->label != NIL(char *) && + PLA->label[cube.first_part[cube.output]] != NIL(char) + && cube.output != -1) { + (void) fprintf(fp, ".ob"); + for(i = 0; i < cube.part_size[cube.output]; i++) + /* (NIL) OUTLABELS caused espresso to segfault under solaris */ + if(OUTLABEL(i) == NIL(char)){ + (void) fprintf(fp, " (null)"); + } + else{ + (void) fprintf(fp, " %s", OUTLABEL(i)); + } + putc('\n', fp); + } + + /* multiple-valued labels */ + for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) { + first = cube.first_part[var]; + last = cube.last_part[var]; + if (PLA->label != NULL && PLA->label[first] != NULL) { + (void) fprintf(fp, ".label var=%d", var); + for(i = first; i <= last; i++) { + (void) fprintf(fp, " %s", PLA->label[i]); + } + putc('\n', fp); + } + } + + if (PLA->phase != (pcube) NULL) { + first = cube.first_part[cube.output]; + last = cube.last_part[cube.output]; + (void) fprintf(fp, "#.phase "); + for(i = first; i <= last; i++) + putc(is_in_set(PLA->phase,i) ? '1' : '0', fp); + (void) fprintf(fp, "\n"); + } +} + +void pls_output(PLA) +IN pPLA PLA; +{ + register pcube last, p; + + (void) printf(".option unmerged\n"); + makeup_labels(PLA); + pls_label(PLA, stdout); + pls_group(PLA, stdout); + (void) printf(".p %d\n", PLA->F->count); + foreach_set(PLA->F, last, p) { + print_expanded_cube(stdout, p, PLA->phase); + } + (void) printf(".end\n"); +} + + +void pls_group(PLA, fp) +pPLA PLA; +FILE *fp; +{ + int var, i, col, len; + + (void) fprintf(fp, "\n.group"); + col = 6; + for(var = 0; var < cube.num_vars-1; var++) { + (void) fprintf(fp, " ("), col += 2; + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + len = strlen(PLA->label[i]); + if (col + len > 75) + (void) fprintf(fp, " \\\n"), col = 0; + else if (i != 0) + putc(' ', fp), col += 1; + (void) fprintf(fp, "%s", PLA->label[i]), col += len; + } + (void) fprintf(fp, ")"), col += 1; + } + (void) fprintf(fp, "\n"); +} + + +void pls_label(PLA, fp) +pPLA PLA; +FILE *fp; +{ + int var, i, col, len; + + (void) fprintf(fp, ".label"); + col = 6; + for(var = 0; var < cube.num_vars; var++) + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + len = strlen(PLA->label[i]); + if (col + len > 75) + (void) fprintf(fp, " \\\n"), col = 0; + else + putc(' ', fp), col += 1; + (void) fprintf(fp, "%s", PLA->label[i]), col += len; + } +} + + + +/* + eqntott output mode -- output algebraic equations +*/ +void eqn_output(PLA) +pPLA PLA; +{ + register pcube p, last; + register int i, var, col, len; + int x; + bool firstand, firstor; + + if (cube.output == -1) + fatal("Cannot have no-output function for EQNTOTT output mode"); + if (cube.num_mv_vars != 1) + fatal("Must have binary-valued function for EQNTOTT output mode"); + makeup_labels(PLA); + + /* Write a single equation for each output */ + for(i = 0; i < cube.part_size[cube.output]; i++) { + (void) printf("%s = ", OUTLABEL(i)); + col = strlen(OUTLABEL(i)) + 3; + firstor = TRUE; + + /* Write product terms for each cube in this output */ + foreach_set(PLA->F, last, p) + if (is_in_set(p, i + cube.first_part[cube.output])) { + if (firstor) + (void) printf("("), col += 1; + else + (void) printf(" | ("), col += 4; + firstor = FALSE; + firstand = TRUE; + + /* print out a product term */ + for(var = 0; var < cube.num_binary_vars; var++) + if ((x=GETINPUT(p, var)) != DASH) { + len = strlen(INLABEL(var)); + if (col+len > 72) + (void) printf("\n "), col = 4; + if (! firstand) + (void) printf("&"), col += 1; + firstand = FALSE; + if (x == ZERO) + (void) printf("!"), col += 1; + (void) printf("%s", INLABEL(var)), col += len; + } + (void) printf(")"), col += 1; + } + (void) printf(";\n\n"); + } +} + + +char *fmt_cube(c, out_map, s) +register pcube c; +register char *out_map, *s; +{ + register int i, var, last, len = 0; + + for(var = 0; var < cube.num_binary_vars; var++) { + s[len++] = "?01-" [GETINPUT(c, var)]; + } + for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { + s[len++] = ' '; + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + s[len++] = "01" [is_in_set(c, i) != 0]; + } + } + if (cube.output != -1) { + last = cube.last_part[cube.output]; + s[len++] = ' '; + for(i = cube.first_part[cube.output]; i <= last; i++) { + s[len++] = out_map [is_in_set(c, i) != 0]; + } + } + s[len] = '\0'; + return s; +} + + +void print_cube(fp, c, out_map) +register FILE *fp; +register pcube c; +register char *out_map; +{ + register int i, var, ch; + int last; + + for(var = 0; var < cube.num_binary_vars; var++) { + ch = "?01-" [GETINPUT(c, var)]; + putc(ch, fp); + } + for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { + putc(' ', fp); + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + ch = "01" [is_in_set(c, i) != 0]; + putc(ch, fp); + } + } + if (cube.output != -1) { + last = cube.last_part[cube.output]; + putc(' ', fp); + for(i = cube.first_part[cube.output]; i <= last; i++) { + ch = out_map [is_in_set(c, i) != 0]; + putc(ch, fp); + } + } + putc('\n', fp); +} + + +void print_expanded_cube(fp, c, phase) +register FILE *fp; +register pcube c; +pcube phase; +{ + register int i, var, ch; + char *out_map; + + for(var = 0; var < cube.num_binary_vars; var++) { + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + ch = "~1" [is_in_set(c, i) != 0]; + putc(ch, fp); + } + } + for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + ch = "1~" [is_in_set(c, i) != 0]; + putc(ch, fp); + } + } + if (cube.output != -1) { + var = cube.num_vars - 1; + putc(' ', fp); + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + if (phase == (pcube) NULL || is_in_set(phase, i)) { + out_map = "~1"; + } else { + out_map = "~0"; + } + ch = out_map[is_in_set(c, i) != 0]; + putc(ch, fp); + } + } + putc('\n', fp); +} + + +char *pc1(c) pcube c; +{static char s1[256];return fmt_cube(c, "01", s1);} +char *pc2(c) pcube c; +{static char s2[256];return fmt_cube(c, "01", s2);} + + +void debug_print(T, name, level) +pcube *T; +char *name; +int level; +{ + register pcube *T1, p, temp; + register int cnt; + + cnt = CUBELISTSIZE(T); + temp = new_cube(); + if (verbose_debug && level == 0) + (void) printf("\n"); + (void) printf("%s[%d]: ord(T)=%d\n", name, level, cnt); + if (verbose_debug) { + (void) printf("cofactor=%s\n", pc1(T[0])); + for(T1 = T+2, cnt = 1; (p = *T1++) != (pcube) NULL; cnt++) + (void) printf("%4d. %s\n", cnt, pc1(set_or(temp, p, T[0]))); + } + free_cube(temp); +} + + +void debug1_print(T, name, num) +pcover T; +char *name; +int num; +{ + register int cnt = 1; + register pcube p, last; + + if (verbose_debug && num == 0) + (void) printf("\n"); + (void) printf("%s[%d]: ord(T)=%d\n", name, num, T->count); + if (verbose_debug) + foreach_set(T, last, p) + (void) printf("%4d. %s\n", cnt++, pc1(p)); +} + + +void cprint(T) +pcover T; +{ + register pcube p, last; + + foreach_set(T, last, p) + (void) printf("%s\n", pc1(p)); +} + + +int makeup_labels(PLA) +pPLA PLA; +{ + int var, i, ind; + + if (PLA->label == (char **) NULL) + PLA_labels(PLA); + + for(var = 0; var < cube.num_vars; var++) + for(i = 0; i < cube.part_size[var]; i++) { + ind = cube.first_part[var] + i; + if (PLA->label[ind] == (char *) NULL) { + PLA->label[ind] = ALLOC(char, 15); + if (var < cube.num_binary_vars) + if ((i % 2) == 0) + (void) sprintf(PLA->label[ind], "v%d.bar", var); + else + (void) sprintf(PLA->label[ind], "v%d", var); + else + (void) sprintf(PLA->label[ind], "v%d.%d", var, i); + } + } +} + + +kiss_output(fp, PLA) +FILE *fp; +pPLA PLA; +{ + register pset last, p; + + foreach_set(PLA->F, last, p) { + kiss_print_cube(fp, PLA, p, "~1"); + } + foreach_set(PLA->D, last, p) { + kiss_print_cube(fp, PLA, p, "~2"); + } +} + + +kiss_print_cube(fp, PLA, p, out_string) +FILE *fp; +pPLA PLA; +pcube p; +char *out_string; +{ + register int i, var; + int part, x; + + for(var = 0; var < cube.num_binary_vars; var++) { + x = "?01-" [GETINPUT(p, var)]; + putc(x, fp); + } + + for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { + putc(' ', fp); + if (setp_implies(cube.var_mask[var], p)) { + putc('-', fp); + } else { + part = -1; + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + if (is_in_set(p, i)) { + if (part != -1) { + fatal("more than 1 part in a symbolic variable\n"); + } + part = i; + } + } + if (part == -1) { + putc('~', fp); /* no parts, hope its an output ... */ + } else { + (void) fputs(PLA->label[part], fp); + } + } + } + + if ((var = cube.output) != -1) { + putc(' ', fp); + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + x = out_string [is_in_set(p, i) != 0]; + putc(x, fp); + } + } + + putc('\n', fp); +} + +output_symbolic_constraints(fp, PLA, output_symbolic) +FILE *fp; +pPLA PLA; +int output_symbolic; +{ + pset_family A; + register int i, j; + int size, var, npermute, *permute, *weight, noweight; + + if ((cube.num_vars - cube.num_binary_vars) <= 1) { + return; + } + makeup_labels(PLA); + + for(var=cube.num_binary_vars; var < cube.num_vars-1; var++) { + + /* pull out the columns for variable "var" */ + npermute = cube.part_size[var]; + permute = ALLOC(int, npermute); + for(i=0; i < npermute; i++) { + permute[i] = cube.first_part[var] + i; + } + A = sf_permute(sf_save(PLA->F), permute, npermute); + FREE(permute); + + + /* Delete the singletons and the full sets */ + noweight = 0; + for(i = 0; i < A->count; i++) { + size = set_ord(GETSET(A,i)); + if (size == 1 || size == A->sf_size) { + sf_delset(A, i--); + noweight++; + } + } + + + /* Count how many times each is duplicated */ + weight = ALLOC(int, A->count); + for(i = 0; i < A->count; i++) { + RESET(GETSET(A, i), COVERED); + } + for(i = 0; i < A->count; i++) { + weight[i] = 0; + if (! TESTP(GETSET(A,i), COVERED)) { + weight[i] = 1; + for(j = i+1; j < A->count; j++) { + if (setp_equal(GETSET(A,i), GETSET(A,j))) { + weight[i]++; + SET(GETSET(A,j), COVERED); + } + } + } + } + + + /* Print out the contraints */ + if (! output_symbolic) { + (void) fprintf(fp, + "# Symbolic constraints for variable %d (Numeric form)\n", var); + (void) fprintf(fp, "# unconstrained weight = %d\n", noweight); + (void) fprintf(fp, "num_codes=%d\n", cube.part_size[var]); + for(i = 0; i < A->count; i++) { + if (weight[i] > 0) { + (void) fprintf(fp, "weight=%d: ", weight[i]); + for(j = 0; j < A->sf_size; j++) { + if (is_in_set(GETSET(A,i), j)) { + (void) fprintf(fp, " %d", j); + } + } + (void) fprintf(fp, "\n"); + } + } + } else { + (void) fprintf(fp, + "# Symbolic constraints for variable %d (Symbolic form)\n", var); + for(i = 0; i < A->count; i++) { + if (weight[i] > 0) { + (void) fprintf(fp, "# w=%d: (", weight[i]); + for(j = 0; j < A->sf_size; j++) { + if (is_in_set(GETSET(A,i), j)) { + (void) fprintf(fp, " %s", + PLA->label[cube.first_part[var]+j]); + } + } + (void) fprintf(fp, " )\n"); + } + } + FREE(weight); + } + } +} diff --git a/abc70930/src/misc/espresso/dominate.c b/abc70930/src/misc/espresso/dominate.c new file mode 100644 index 00000000..a930d453 --- /dev/null +++ b/abc70930/src/misc/espresso/dominate.c @@ -0,0 +1,98 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + + +int +sm_row_dominance(A) +sm_matrix *A; +{ + register sm_row *prow, *prow1; + register sm_col *pcol, *least_col; + register sm_element *p, *pnext; + int rowcnt; + + rowcnt = A->nrows; + + /* Check each row against all other rows */ + for(prow = A->first_row; prow != 0; prow = prow->next_row) { + + /* Among all columns with a 1 in this row, choose smallest */ + least_col = sm_get_col(A, prow->first_col->col_num); + for(p = prow->first_col->next_col; p != 0; p = p->next_col) { + pcol = sm_get_col(A, p->col_num); + if (pcol->length < least_col->length) { + least_col = pcol; + } + } + + /* Only check for containment against rows in this column */ + for(p = least_col->first_row; p != 0; p = pnext) { + pnext = p->next_row; + + prow1 = sm_get_row(A, p->row_num); + if ((prow1->length > prow->length) || + (prow1->length == prow->length && + prow1->row_num > prow->row_num)) { + if (sm_row_contains(prow, prow1)) { + sm_delrow(A, prow1->row_num); + } + } + } + } + + return rowcnt - A->nrows; +} + +int +sm_col_dominance(A, weight) +sm_matrix *A; +int *weight; +{ + register sm_row *prow; + register sm_col *pcol, *pcol1; + register sm_element *p; + sm_row *least_row; + sm_col *next_col; + int colcnt; + + colcnt = A->ncols; + + /* Check each column against all other columns */ + for(pcol = A->first_col; pcol != 0; pcol = next_col) { + next_col = pcol->next_col; + + /* Check all rows to find the one with fewest elements */ + least_row = sm_get_row(A, pcol->first_row->row_num); + for(p = pcol->first_row->next_row; p != 0; p = p->next_row) { + prow = sm_get_row(A, p->row_num); + if (prow->length < least_row->length) { + least_row = prow; + } + } + + /* Only check for containment against columns in this row */ + for(p = least_row->first_col; p != 0; p = p->next_col) { + pcol1 = sm_get_col(A, p->col_num); + if (weight != 0 && weight[pcol1->col_num] > weight[pcol->col_num]) + continue; + if ((pcol1->length > pcol->length) || + (pcol1->length == pcol->length && + pcol1->col_num > pcol->col_num)) { + if (sm_col_contains(pcol, pcol1)) { + sm_delcol(A, pcol->col_num); + break; + } + } + } + } + + return colcnt - A->ncols; +} diff --git a/abc70930/src/misc/espresso/equiv.c b/abc70930/src/misc/espresso/equiv.c new file mode 100644 index 00000000..ba898a70 --- /dev/null +++ b/abc70930/src/misc/espresso/equiv.c @@ -0,0 +1,94 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + + +find_equiv_outputs(PLA) +pPLA PLA; +{ + int i, j, ipart, jpart, some_equiv; + pcover *R, *F; + + some_equiv = FALSE; + + makeup_labels(PLA); + + F = ALLOC(pcover, cube.part_size[cube.output]); + R = ALLOC(pcover, cube.part_size[cube.output]); + + for(i = 0; i < cube.part_size[cube.output]; i++) { + ipart = cube.first_part[cube.output] + i; + R[i] = cof_output(PLA->R, ipart); + F[i] = complement(cube1list(R[i])); + } + + for(i = 0; i < cube.part_size[cube.output]-1; i++) { + for(j = i+1; j < cube.part_size[cube.output]; j++) { + ipart = cube.first_part[cube.output] + i; + jpart = cube.first_part[cube.output] + j; + + if (check_equiv(F[i], F[j])) { + (void) printf("# Outputs %d and %d (%s and %s) are equivalent\n", + i, j, PLA->label[ipart], PLA->label[jpart]); + some_equiv = TRUE; + } else if (check_equiv(F[i], R[j])) { + (void) printf("# Outputs %d and NOT %d (%s and %s) are equivalent\n", + i, j, PLA->label[ipart], PLA->label[jpart]); + some_equiv = TRUE; + } else if (check_equiv(R[i], F[j])) { + (void) printf("# Outputs NOT %d and %d (%s and %s) are equivalent\n", + i, j, PLA->label[ipart], PLA->label[jpart]); + some_equiv = TRUE; + } else if (check_equiv(R[i], R[j])) { + (void) printf("# Outputs NOT %d and NOT %d (%s and %s) are equivalent\n", + i, j, PLA->label[ipart], PLA->label[jpart]); + some_equiv = TRUE; + } + } + } + + if (! some_equiv) { + (void) printf("# No outputs are equivalent\n"); + } + + for(i = 0; i < cube.part_size[cube.output]; i++) { + free_cover(F[i]); + free_cover(R[i]); + } + FREE(F); + FREE(R); +} + + + +int check_equiv(f1, f2) +pcover f1, f2; +{ + register pcube *f1list, *f2list; + register pcube p, last; + + f1list = cube1list(f1); + foreach_set(f2, last, p) { + if (! cube_is_covered(f1list, p)) { + return FALSE; + } + } + free_cubelist(f1list); + + f2list = cube1list(f2); + foreach_set(f1, last, p) { + if (! cube_is_covered(f2list, p)) { + return FALSE; + } + } + free_cubelist(f2list); + + return TRUE; +} diff --git a/abc70930/src/misc/espresso/espresso.c b/abc70930/src/misc/espresso/espresso.c new file mode 100644 index 00000000..8f05d43f --- /dev/null +++ b/abc70930/src/misc/espresso/espresso.c @@ -0,0 +1,139 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + * Module: espresso.c + * Purpose: The main espresso algorithm + * + * Returns a minimized version of the ON-set of a function + * + * The following global variables affect the operation of Espresso: + * + * MISCELLANEOUS: + * trace + * print trace information as the minimization progresses + * + * remove_essential + * remove essential primes + * + * single_expand + * if true, stop after first expand/irredundant + * + * LAST_GASP or SUPER_GASP strategy: + * use_super_gasp + * uses the super_gasp strategy rather than last_gasp + * + * SETUP strategy: + * recompute_onset + * recompute onset using the complement before starting + * + * unwrap_onset + * unwrap the function output part before first expand + * + * MAKE_SPARSE strategy: + * force_irredundant + * iterates make_sparse to force a minimal solution (used + * indirectly by make_sparse) + * + * skip_make_sparse + * skip the make_sparse step (used by opo only) + */ + +#include "espresso.h" + +pcover espresso(F, D1, R) +pcover F, D1, R; +{ + pcover E, D, Fsave; + pset last, p; + cost_t cost, best_cost; + +begin: + Fsave = sf_save(F); /* save original function */ + D = sf_save(D1); /* make a scratch copy of D */ + + /* Setup has always been a problem */ + if (recompute_onset) { + EXEC(E = simplify(cube1list(F)), "SIMPLIFY ", E); + free_cover(F); + F = E; + } + cover_cost(F, &cost); + if (unwrap_onset && (cube.part_size[cube.num_vars - 1] > 1) + && (cost.out != cost.cubes*cube.part_size[cube.num_vars-1]) + && (cost.out < 5000)) + EXEC(F = sf_contain(unravel(F, cube.num_vars - 1)), "SETUP ", F); + + /* Initial expand and irredundant */ + foreach_set(F, last, p) { + RESET(p, PRIME); + } + EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost); + EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost); + + if (! single_expand) { + if (remove_essential) { + EXECUTE(E = essential(&F, &D), ESSEN_TIME, E, cost); + } else { + E = new_cover(0); + } + + cover_cost(F, &cost); + do { + + /* Repeat inner loop until solution becomes "stable" */ + do { + copy_cost(&cost, &best_cost); + EXECUTE(F = reduce(F, D), REDUCE_TIME, F, cost); + EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost); + EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost); + } while (cost.cubes < best_cost.cubes); + + /* Perturb solution to see if we can continue to iterate */ + copy_cost(&cost, &best_cost); + if (use_super_gasp) { + F = super_gasp(F, D, R, &cost); + if (cost.cubes >= best_cost.cubes) + break; + } else { + F = last_gasp(F, D, R, &cost); + } + + } while (cost.cubes < best_cost.cubes || + (cost.cubes == best_cost.cubes && cost.total < best_cost.total)); + + /* Append the essential cubes to F */ + F = sf_append(F, E); /* disposes of E */ + if (trace) size_stamp(F, "ADJUST "); + } + + /* Free the D which we used */ + free_cover(D); + + /* Attempt to make the PLA matrix sparse */ + if (! skip_make_sparse) { + F = make_sparse(F, D1, R); + } + + /* + * Check to make sure function is actually smaller !! + * This can only happen because of the initial unravel. If we fail, + * then run the whole thing again without the unravel. + */ + if (Fsave->count < F->count) { + free_cover(F); + F = Fsave; + unwrap_onset = FALSE; + goto begin; + } else { + free_cover(Fsave); + } + + return F; +} diff --git a/abc70930/src/misc/espresso/espresso.h b/abc70930/src/misc/espresso/espresso.h new file mode 100644 index 00000000..1c7a8646 --- /dev/null +++ b/abc70930/src/misc/espresso/espresso.h @@ -0,0 +1,782 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + * espresso.h -- header file for Espresso-mv + */ + +//#include "port.h" +//#include "utility.h" +#include "sparse.h" +#include "mincov.h" + +#include "util_hack.h" // added + +#define ptime() util_cpu_time() +#define print_time(t) util_print_time(t) + +#ifdef IBM_WATC +#define void int +#include "short.h" +#endif + +#ifdef IBMPC /* set default options for IBM/PC */ +#define NO_INLINE +#define BPI 16 +#endif + +/*-----THIS USED TO BE set.h----- */ + +/* + * set.h -- definitions for packed arrays of bits + * + * This header file describes the data structures which comprise a + * facility for efficiently implementing packed arrays of bits + * (otherwise known as sets, cf. Pascal). + * + * A set is a vector of bits and is implemented here as an array of + * unsigned integers. The low order bits of set[0] give the index of + * the last word of set data. The higher order bits of set[0] are + * used to store data associated with the set. The set data is + * contained in elements set[1] ... set[LOOP(set)] as a packed bit + * array. + * + * A family of sets is a two-dimensional matrix of bits and is + * implemented with the data type "set_family". + * + * BPI == 32 and BPI == 16 have been tested and work. + */ + + +/* Define host machine characteristics of "unsigned int" */ +#ifndef BPI +#define BPI 32 /* # bits per integer */ +#endif + +#if BPI == 32 +#define LOGBPI 5 /* log(BPI)/log(2) */ +#else +#define LOGBPI 4 /* log(BPI)/log(2) */ +#endif + +/* Define the set type */ +typedef unsigned int *pset; + +/* Define the set family type -- an array of sets */ +typedef struct set_family { + int wsize; /* Size of each set in 'ints' */ + int sf_size; /* User declared set size */ + int capacity; /* Number of sets allocated */ + int count; /* The number of sets in the family */ + int active_count; /* Number of "active" sets */ + pset data; /* Pointer to the set data */ + struct set_family *next; /* For garbage collection */ +} set_family_t, *pset_family; + +/* Macros to set and test single elements */ +#define WHICH_WORD(element) (((element) >> LOGBPI) + 1) +#define WHICH_BIT(element) ((element) & (BPI-1)) + +/* # of ints needed to allocate a set with "size" elements */ +#if BPI == 32 +#define SET_SIZE(size) ((size) <= BPI ? 2 : (WHICH_WORD((size)-1) + 1)) +#else +#define SET_SIZE(size) ((size) <= BPI ? 3 : (WHICH_WORD((size)-1) + 2)) +#endif + +/* + * Three fields are maintained in the first word of the set + * LOOP is the index of the last word used for set data + * LOOPCOPY is the index of the last word in the set + * SIZE is available for general use (e.g., recording # elements in set) + * NELEM retrieves the number of elements in the set + */ +#define LOOP(set) (set[0] & 0x03ff) +#define PUTLOOP(set, i) (set[0] &= ~0x03ff, set[0] |= (i)) +#if BPI == 32 +#define LOOPCOPY(set) LOOP(set) +#define SIZE(set) (set[0] >> 16) +#define PUTSIZE(set, size) (set[0] &= 0xffff, set[0] |= ((size) << 16)) +#else +#define LOOPCOPY(set) (LOOP(set) + 1) +#define SIZE(set) (set[LOOP(set)+1]) +#define PUTSIZE(set, size) ((set[LOOP(set)+1]) = (size)) +#endif + +#define NELEM(set) (BPI * LOOP(set)) +#define LOOPINIT(size) ((size <= BPI) ? 1 : WHICH_WORD((size)-1)) + +/* + * FLAGS store general information about the set + */ +#define SET(set, flag) (set[0] |= (flag)) +#define RESET(set, flag) (set[0] &= ~ (flag)) +#define TESTP(set, flag) (set[0] & (flag)) + +/* Flag definitions are ... */ +#define PRIME 0x8000 /* cube is prime */ +#define NONESSEN 0x4000 /* cube cannot be essential prime */ +#define ACTIVE 0x2000 /* cube is still active */ +#define REDUND 0x1000 /* cube is redundant(at this point) */ +#define COVERED 0x0800 /* cube has been covered */ +#define RELESSEN 0x0400 /* cube is relatively essential */ + +/* Most efficient way to look at all members of a set family */ +#define foreach_set(R, last, p)\ + for(p=R->data,last=p+R->count*R->wsize;pwsize) +#define foreach_remaining_set(R, last, pfirst, p)\ + for(p=pfirst+R->wsize,last=R->data+R->count*R->wsize;pwsize) +#define foreach_active_set(R, last, p)\ + foreach_set(R,last,p) if (TESTP(p, ACTIVE)) + +/* Another way that also keeps the index of the current set member in i */ +#define foreachi_set(R, i, p)\ + for(p=R->data,i=0;icount;p+=R->wsize,i++) +#define foreachi_active_set(R, i, p)\ + foreachi_set(R,i,p) if (TESTP(p, ACTIVE)) + +/* Looping over all elements in a set: + * foreach_set_element(pset p, int i, unsigned val, int base) { + * . + * . + * . + * } + */ +#define foreach_set_element(p, i, val, base) \ + for(i = LOOP(p); i > 0; ) \ + for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) \ + if (val & 1) + +/* Return a pointer to a given member of a set family */ +#define GETSET(family, index) ((family)->data + (family)->wsize * (index)) + +/* Allocate and deallocate sets */ +#define set_new(size) set_clear(ALLOC(unsigned int, SET_SIZE(size)), size) +#define set_full(size) set_fill(ALLOC(unsigned int, SET_SIZE(size)), size) +#define set_save(r) set_copy(ALLOC(unsigned int, SET_SIZE(NELEM(r))), r) +#define set_free(r) FREE(r) + +/* Check for set membership, remove set element and insert set element */ +#define is_in_set(set, e) (set[WHICH_WORD(e)] & (1 << WHICH_BIT(e))) +#define set_remove(set, e) (set[WHICH_WORD(e)] &= ~ (1 << WHICH_BIT(e))) +#define set_insert(set, e) (set[WHICH_WORD(e)] |= 1 << WHICH_BIT(e)) + +/* Inline code substitution for those places that REALLY need it on a VAX */ +#ifdef NO_INLINE +#define INLINEset_copy(r, a) (void) set_copy(r,a) +#define INLINEset_clear(r, size) (void) set_clear(r, size) +#define INLINEset_fill(r, size) (void) set_fill(r, size) +#define INLINEset_and(r, a, b) (void) set_and(r, a, b) +#define INLINEset_or(r, a, b) (void) set_or(r, a, b) +#define INLINEset_diff(r, a, b) (void) set_diff(r, a, b) +#define INLINEset_ndiff(r, a, b, f) (void) set_ndiff(r, a, b, f) +#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b) +#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f) +#define INLINEset_merge(r, a, b, mask) (void) set_merge(r, a, b, mask) +#define INLINEsetp_implies(a, b, when_false) \ + if (! setp_implies(a,b)) when_false +#define INLINEsetp_disjoint(a, b, when_false) \ + if (! setp_disjoint(a,b)) when_false +#define INLINEsetp_equal(a, b, when_false) \ + if (! setp_equal(a,b)) when_false + +#else + +#define INLINEset_copy(r, a)\ + {register int i_=LOOPCOPY(a); do r[i_]=a[i_]; while (--i_>=0);} +#define INLINEset_clear(r, size)\ + {register int i_=LOOPINIT(size); *r=i_; do r[i_] = 0; while (--i_ > 0);} +#define INLINEset_fill(r, size)\ + {register int i_=LOOPINIT(size); *r=i_; \ + r[i_]=((unsigned int)(~0))>>(i_*BPI-size); while(--i_>0) r[i_]=~0;} +#define INLINEset_and(r, a, b)\ + {register int i_=LOOP(a); PUTLOOP(r,i_);\ + do r[i_] = a[i_] & b[i_]; while (--i_>0);} +#define INLINEset_or(r, a, b)\ + {register int i_=LOOP(a); PUTLOOP(r,i_);\ + do r[i_] = a[i_] | b[i_]; while (--i_>0);} +#define INLINEset_diff(r, a, b)\ + {register int i_=LOOP(a); PUTLOOP(r,i_);\ + do r[i_] = a[i_] & ~ b[i_]; while (--i_>0);} +#define INLINEset_ndiff(r, a, b, fullset)\ + {register int i_=LOOP(a); PUTLOOP(r,i_);\ + do r[i_] = fullset[i_] & (a[i_] | ~ b[i_]); while (--i_>0);} +#ifdef IBM_WATC +#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b) +#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f) +#else +#define INLINEset_xor(r, a, b)\ + {register int i_=LOOP(a); PUTLOOP(r,i_);\ + do r[i_] = a[i_] ^ b[i_]; while (--i_>0);} +#define INLINEset_xnor(r, a, b, fullset)\ + {register int i_=LOOP(a); PUTLOOP(r,i_);\ + do r[i_] = fullset[i_] & ~ (a[i_] ^ b[i_]); while (--i_>0);} +#endif +#define INLINEset_merge(r, a, b, mask)\ + {register int i_=LOOP(a); PUTLOOP(r,i_);\ + do r[i_] = (a[i_]&mask[i_]) | (b[i_]&~mask[i_]); while (--i_>0);} +#define INLINEsetp_implies(a, b, when_false)\ + {register int i_=LOOP(a); do if (a[i_]&~b[i_]) break; while (--i_>0);\ + if (i_ != 0) when_false;} +#define INLINEsetp_disjoint(a, b, when_false)\ + {register int i_=LOOP(a); do if (a[i_]&b[i_]) break; while (--i_>0);\ + if (i_ != 0) when_false;} +#define INLINEsetp_equal(a, b, when_false)\ + {register int i_=LOOP(a); do if (a[i_]!=b[i_]) break; while (--i_>0);\ + if (i_ != 0) when_false;} + +#endif + +#if BPI == 32 +#define count_ones(v)\ + (bit_count[v & 255] + bit_count[(v >> 8) & 255]\ + + bit_count[(v >> 16) & 255] + bit_count[(v >> 24) & 255]) +#else +#define count_ones(v) (bit_count[v & 255] + bit_count[(v >> 8) & 255]) +#endif + +/* Table for efficient bit counting */ +extern int bit_count[256]; +/*----- END OF set.h ----- */ + + +/* Define a boolean type */ +#define bool int +#define FALSE 0 +#define TRUE 1 +#define MAYBE 2 +#define print_bool(x) ((x) == 0 ? "FALSE" : ((x) == 1 ? "TRUE" : "MAYBE")) + +/* Map many cube/cover types/routines into equivalent set types/routines */ +#define pcube pset +#define new_cube() set_new(cube.size) +#define free_cube(r) set_free(r) +#define pcover pset_family +#define new_cover(i) sf_new(i, cube.size) +#define free_cover(r) sf_free(r) +#define free_cubelist(T) FREE(T[0]); FREE(T); + + +/* cost_t describes the cost of a cover */ +typedef struct cost_struct { + int cubes; /* number of cubes in the cover */ + int in; /* transistor count, binary-valued variables */ + int out; /* transistor count, output part */ + int mv; /* transistor count, multiple-valued vars */ + int total; /* total number of transistors */ + int primes; /* number of prime cubes */ +} cost_t, *pcost; + + +/* pair_t describes bit-paired variables */ +typedef struct pair_struct { + int cnt; + int *var1; + int *var2; +} pair_t, *ppair; + + +/* symbolic_list_t describes a single ".symbolic" line */ +typedef struct symbolic_list_struct { + int variable; + int pos; + struct symbolic_list_struct *next; +} symbolic_list_t; + + +/* symbolic_list_t describes a single ".symbolic" line */ +typedef struct symbolic_label_struct { + char *label; + struct symbolic_label_struct *next; +} symbolic_label_t; + + +/* symbolic_t describes a linked list of ".symbolic" lines */ +typedef struct symbolic_struct { + symbolic_list_t *symbolic_list; /* linked list of items */ + int symbolic_list_length; /* length of symbolic_list list */ + symbolic_label_t *symbolic_label; /* linked list of new names */ + int symbolic_label_length; /* length of symbolic_label list */ + struct symbolic_struct *next; +} symbolic_t; + + +/* PLA_t stores the logical representation of a PLA */ +typedef struct { + pcover F, D, R; /* on-set, off-set and dc-set */ + char *filename; /* filename */ + int pla_type; /* logical PLA format */ + pcube phase; /* phase to split into on-set and off-set */ + ppair pair; /* how to pair variables */ + char **label; /* labels for the columns */ + symbolic_t *symbolic; /* allow binary->symbolic mapping */ + symbolic_t *symbolic_output;/* allow symbolic output mapping */ +} PLA_t, *pPLA; + +#define equal(a,b) (strcmp(a,b) == 0) + +/* This is a hack which I wish I hadn't done, but too painful to change */ +#define CUBELISTSIZE(T) (((pcube *) T[1] - T) - 3) + +/* For documentation purposes */ +#define IN +#define OUT +#define INOUT + +/* The pla_type field describes the input and output format of the PLA */ +#define F_type 1 +#define D_type 2 +#define R_type 4 +#define PLEASURE_type 8 /* output format */ +#define EQNTOTT_type 16 /* output format algebraic eqns */ +#define KISS_type 128 /* output format kiss */ +#define CONSTRAINTS_type 256 /* output the constraints (numeric) */ +#define SYMBOLIC_CONSTRAINTS_type 512 /* output the constraints (symbolic) */ +#define FD_type (F_type | D_type) +#define FR_type (F_type | R_type) +#define DR_type (D_type | R_type) +#define FDR_type (F_type | D_type | R_type) + +/* Definitions for the debug variable */ +#define COMPL 0x0001 +#define ESSEN 0x0002 +#define EXPAND 0x0004 +#define EXPAND1 0x0008 +#define GASP 0x0010 +#define IRRED 0x0020 +#define REDUCE 0x0040 +#define REDUCE1 0x0080 +#define SPARSE 0x0100 +#define TAUT 0x0200 +#define EXACT 0x0400 +#define MINCOV 0x0800 +#define MINCOV1 0x1000 +#define SHARP 0x2000 +#define IRRED1 0x4000 + +#define VERSION\ + "UC Berkeley, Espresso Version #2.3, Release date 01/31/88" + +/* Define constants used for recording program statistics */ +#define TIME_COUNT 16 +#define READ_TIME 0 +#define COMPL_TIME 1 +#define ONSET_TIME 2 +#define ESSEN_TIME 3 +#define EXPAND_TIME 4 +#define IRRED_TIME 5 +#define REDUCE_TIME 6 +#define GEXPAND_TIME 7 +#define GIRRED_TIME 8 +#define GREDUCE_TIME 9 +#define PRIMES_TIME 10 +#define MINCOV_TIME 11 +#define MV_REDUCE_TIME 12 +#define RAISE_IN_TIME 13 +#define VERIFY_TIME 14 +#define WRITE_TIME 15 + + +/* For those who like to think about PLAs, macros to get at inputs/outputs */ +#define NUMINPUTS cube.num_binary_vars +#define NUMOUTPUTS cube.part_size[cube.num_vars - 1] + +#define POSITIVE_PHASE(pos)\ + (is_in_set(PLA->phase, cube.first_part[cube.output]+pos) != 0) + +#define INLABEL(var) PLA->label[cube.first_part[var] + 1] +#define OUTLABEL(pos) PLA->label[cube.first_part[cube.output] + pos] + +#define GETINPUT(c, pos)\ + ((c[WHICH_WORD(2*pos)] >> WHICH_BIT(2*pos)) & 3) +#define GETOUTPUT(c, pos)\ + (is_in_set(c, cube.first_part[cube.output] + pos) != 0) + +#define PUTINPUT(c, pos, value)\ + c[WHICH_WORD(2*pos)] = (c[WHICH_WORD(2*pos)] & ~(3 << WHICH_BIT(2*pos)))\ + | (value << WHICH_BIT(2*pos)) +#define PUTOUTPUT(c, pos, value)\ + c[WHICH_WORD(pos)] = (c[WHICH_WORD(pos)] & ~(1 << WHICH_BIT(pos)))\ + | (value << WHICH_BIT(pos)) + +#define TWO 3 +#define DASH 3 +#define ONE 2 +#define ZERO 1 + + +#define EXEC(fct, name, S)\ + {long t=ptime();fct;if(trace)print_trace(S,name,ptime()-t);} +#define EXEC_S(fct, name, S)\ + {long t=ptime();fct;if(summary)print_trace(S,name,ptime()-t);} +#define EXECUTE(fct,i,S,cost)\ + {long t=ptime();fct;totals(t,i,S,&(cost));} + +/* + * Global Variable Declarations + */ + +extern unsigned int debug; /* debug parameter */ +extern bool verbose_debug; /* -v: whether to print a lot */ +extern char *total_name[TIME_COUNT]; /* basic function names */ +extern long total_time[TIME_COUNT]; /* time spent in basic fcts */ +extern int total_calls[TIME_COUNT]; /* # calls to each fct */ + +extern bool echo_comments; /* turned off by -eat option */ +extern bool echo_unknown_commands; /* always true ?? */ +extern bool force_irredundant; /* -nirr command line option */ +extern bool skip_make_sparse; +extern bool kiss; /* -kiss command line option */ +extern bool pos; /* -pos command line option */ +extern bool print_solution; /* -x command line option */ +extern bool recompute_onset; /* -onset command line option */ +extern bool remove_essential; /* -ness command line option */ +extern bool single_expand; /* -fast command line option */ +extern bool summary; /* -s command line option */ +extern bool trace; /* -t command line option */ +extern bool unwrap_onset; /* -nunwrap command line option */ +extern bool use_random_order; /* -random command line option */ +extern bool use_super_gasp; /* -strong command line option */ +extern char *filename; /* filename PLA was read from */ +extern bool debug_exact_minimization; /* dumps info for -do exact */ + + +/* + * pla_types are the input and output types for reading/writing a PLA + */ +struct pla_types_struct { + char *key; + int value; +}; + + +/* + * The cube structure is a global structure which contains information + * on how a set maps into a cube -- i.e., number of parts per variable, + * number of variables, etc. Also, many fields are pre-computed to + * speed up various primitive operations. + */ +#define CUBE_TEMP 10 + +struct cube_struct { + int size; /* set size of a cube */ + int num_vars; /* number of variables in a cube */ + int num_binary_vars; /* number of binary variables */ + int *first_part; /* first element of each variable */ + int *last_part; /* first element of each variable */ + int *part_size; /* number of elements in each variable */ + int *first_word; /* first word for each variable */ + int *last_word; /* last word for each variable */ + pset binary_mask; /* Mask to extract binary variables */ + pset mv_mask; /* mask to get mv parts */ + pset *var_mask; /* mask to extract a variable */ + pset *temp; /* an array of temporary sets */ + pset fullset; /* a full cube */ + pset emptyset; /* an empty cube */ + unsigned int inmask; /* mask to get odd word of binary part */ + int inword; /* which word number for above */ + int *sparse; /* should this variable be sparse? */ + int num_mv_vars; /* number of multiple-valued variables */ + int output; /* which variable is "output" (-1 if none) */ +}; + +struct cdata_struct { + int *part_zeros; /* count of zeros for each element */ + int *var_zeros; /* count of zeros for each variable */ + int *parts_active; /* number of "active" parts for each var */ + bool *is_unate; /* indicates given var is unate */ + int vars_active; /* number of "active" variables */ + int vars_unate; /* number of unate variables */ + int best; /* best "binate" variable */ +}; + + +extern struct pla_types_struct pla_types[]; +extern struct cube_struct cube, temp_cube_save; +extern struct cdata_struct cdata, temp_cdata_save; + +#ifdef lint +#define DISJOINT 0x5555 +#else +#if BPI == 32 +#define DISJOINT 0x55555555 +#else +#define DISJOINT 0x5555 +#endif +#endif + +/* function declarations */ + +/* cofactor.c */ extern int binate_split_select(); +/* cofactor.c */ extern pcover cubeunlist(); +/* cofactor.c */ extern pcube *cofactor(); +/* cofactor.c */ extern pcube *cube1list(); +/* cofactor.c */ extern pcube *cube2list(); +/* cofactor.c */ extern pcube *cube3list(); +/* cofactor.c */ extern pcube *scofactor(); +/* cofactor.c */ extern void massive_count(); +/* compl.c */ extern pcover complement(); +/* compl.c */ extern pcover simplify(); +/* compl.c */ extern void simp_comp(); +/* contain.c */ extern int d1_rm_equal(); +/* contain.c */ extern int rm2_contain(); +/* contain.c */ extern int rm2_equal(); +/* contain.c */ extern int rm_contain(); +/* contain.c */ extern int rm_equal(); +/* contain.c */ extern int rm_rev_contain(); +/* contain.c */ extern pset *sf_list(); +/* contain.c */ extern pset *sf_sort(); +/* contain.c */ extern pset_family d1merge(); +/* contain.c */ extern pset_family dist_merge(); +/* contain.c */ extern pset_family sf_contain(); +/* contain.c */ extern pset_family sf_dupl(); +/* contain.c */ extern pset_family sf_ind_contain(); +/* contain.c */ extern pset_family sf_ind_unlist(); +/* contain.c */ extern pset_family sf_merge(); +/* contain.c */ extern pset_family sf_rev_contain(); +/* contain.c */ extern pset_family sf_union(); +/* contain.c */ extern pset_family sf_unlist(); +/* cubestr.c */ extern void cube_setup(); +/* cubestr.c */ extern void restore_cube_struct(); +/* cubestr.c */ extern void save_cube_struct(); +/* cubestr.c */ extern void setdown_cube(); +/* cvrin.c */ extern PLA_labels(); +/* cvrin.c */ extern char *get_word(); +/* cvrin.c */ extern int label_index(); +/* cvrin.c */ extern int read_pla(); +/* cvrin.c */ extern int read_symbolic(); +/* cvrin.c */ extern pPLA new_PLA(); +/* cvrin.c */ extern void PLA_summary(); +/* cvrin.c */ extern void free_PLA(); +/* cvrin.c */ extern void parse_pla(); +/* cvrin.c */ extern void read_cube(); +/* cvrin.c */ extern void skip_line(); +/* cvrm.c */ extern foreach_output_function(); +/* cvrm.c */ extern int cubelist_partition(); +/* cvrm.c */ extern int so_both_do_espresso(); +/* cvrm.c */ extern int so_both_do_exact(); +/* cvrm.c */ extern int so_both_save(); +/* cvrm.c */ extern int so_do_espresso(); +/* cvrm.c */ extern int so_do_exact(); +/* cvrm.c */ extern int so_save(); +/* cvrm.c */ extern pcover cof_output(); +/* cvrm.c */ extern pcover lex_sort(); +/* cvrm.c */ extern pcover mini_sort(); +/* cvrm.c */ extern pcover random_order(); +/* cvrm.c */ extern pcover size_sort(); +/* cvrm.c */ extern pcover sort_reduce(); +/* cvrm.c */ extern pcover uncof_output(); +/* cvrm.c */ extern pcover unravel(); +/* cvrm.c */ extern pcover unravel_range(); +/* cvrm.c */ extern void so_both_espresso(); +/* cvrm.c */ extern void so_espresso(); +/* cvrmisc.c */ extern char *fmt_cost(); +/* cvrmisc.c */ extern char *print_cost(); +/* cvrmisc.c */ extern char *strsav(); +/* cvrmisc.c */ extern void copy_cost(); +/* cvrmisc.c */ extern void cover_cost(); +/* cvrmisc.c */ extern void fatal(); +/* cvrmisc.c */ extern void print_trace(); +/* cvrmisc.c */ extern void size_stamp(); +/* cvrmisc.c */ extern void totals(); +/* cvrout.c */ extern char *fmt_cube(); +/* cvrout.c */ extern char *fmt_expanded_cube(); +/* cvrout.c */ extern char *pc1(); +/* cvrout.c */ extern char *pc2(); +/* cvrout.c */ extern char *pc3(); +/* cvrout.c */ extern int makeup_labels(); +/* cvrout.c */ extern kiss_output(); +/* cvrout.c */ extern kiss_print_cube(); +/* cvrout.c */ extern output_symbolic_constraints(); +/* cvrout.c */ extern void cprint(); +/* cvrout.c */ extern void debug1_print(); +/* cvrout.c */ extern void debug_print(); +/* cvrout.c */ extern void eqn_output(); +/* cvrout.c */ extern void fpr_header(); +/* cvrout.c */ extern void fprint_pla(); +/* cvrout.c */ extern void pls_group(); +/* cvrout.c */ extern void pls_label(); +/* cvrout.c */ extern void pls_output(); +/* cvrout.c */ extern void print_cube(); +/* cvrout.c */ extern void print_expanded_cube(); +/* cvrout.c */ extern void sf_debug_print(); +/* equiv.c */ extern find_equiv_outputs(); +/* equiv.c */ extern int check_equiv(); +/* espresso.c */ extern pcover espresso(); +/* essen.c */ extern bool essen_cube(); +/* essen.c */ extern pcover cb_consensus(); +/* essen.c */ extern pcover cb_consensus_dist0(); +/* essen.c */ extern pcover essential(); +/* exact.c */ extern pcover minimize_exact(); +/* exact.c */ extern pcover minimize_exact_literals(); +/* expand.c */ extern bool feasibly_covered(); +/* expand.c */ extern int most_frequent(); +/* expand.c */ extern pcover all_primes(); +/* expand.c */ extern pcover expand(); +/* expand.c */ extern pcover find_all_primes(); +/* expand.c */ extern void elim_lowering(); +/* expand.c */ extern void essen_parts(); +/* expand.c */ extern void essen_raising(); +/* expand.c */ extern void expand1(); +/* expand.c */ extern void mincov(); +/* expand.c */ extern void select_feasible(); +/* expand.c */ extern void setup_BB_CC(); +/* gasp.c */ extern pcover expand_gasp(); +/* gasp.c */ extern pcover irred_gasp(); +/* gasp.c */ extern pcover last_gasp(); +/* gasp.c */ extern pcover super_gasp(); +/* gasp.c */ extern void expand1_gasp(); +/* getopt.c */ extern int util_getopt(); +/* hack.c */ extern find_dc_inputs(); +/* hack.c */ extern find_inputs(); +/* hack.c */ extern form_bitvector(); +/* hack.c */ extern map_dcset(); +/* hack.c */ extern map_output_symbolic(); +/* hack.c */ extern map_symbolic(); +/* hack.c */ extern pcover map_symbolic_cover(); +/* hack.c */ extern symbolic_hack_labels(); +/* irred.c */ extern bool cube_is_covered(); +/* irred.c */ extern bool taut_special_cases(); +/* irred.c */ extern bool tautology(); +/* irred.c */ extern pcover irredundant(); +/* irred.c */ extern void mark_irredundant(); +/* irred.c */ extern void irred_split_cover(); +/* irred.c */ extern sm_matrix *irred_derive_table(); +/* map.c */ extern pset minterms(); +/* map.c */ extern void explode(); +/* map.c */ extern void map(); +/* opo.c */ extern output_phase_setup(); +/* opo.c */ extern pPLA set_phase(); +/* opo.c */ extern pcover opo(); +/* opo.c */ extern pcube find_phase(); +/* opo.c */ extern pset_family find_covers(); +/* opo.c */ extern pset_family form_cover_table(); +/* opo.c */ extern pset_family opo_leaf(); +/* opo.c */ extern pset_family opo_recur(); +/* opo.c */ extern void opoall(); +/* opo.c */ extern void phase_assignment(); +/* opo.c */ extern void repeated_phase_assignment(); +/* pair.c */ extern generate_all_pairs(); +/* pair.c */ extern int **find_pairing_cost(); +/* pair.c */ extern int find_best_cost(); +/* pair.c */ extern int greedy_best_cost(); +/* pair.c */ extern int minimize_pair(); +/* pair.c */ extern int pair_free(); +/* pair.c */ extern pair_all(); +/* pair.c */ extern pcover delvar(); +/* pair.c */ extern pcover pairvar(); +/* pair.c */ extern ppair pair_best_cost(); +/* pair.c */ extern ppair pair_new(); +/* pair.c */ extern ppair pair_save(); +/* pair.c */ extern print_pair(); +/* pair.c */ extern void find_optimal_pairing(); +/* pair.c */ extern void set_pair(); +/* pair.c */ extern void set_pair1(); +/* primes.c */ extern pcover primes_consensus(); +/* reduce.c */ extern bool sccc_special_cases(); +/* reduce.c */ extern pcover reduce(); +/* reduce.c */ extern pcube reduce_cube(); +/* reduce.c */ extern pcube sccc(); +/* reduce.c */ extern pcube sccc_cube(); +/* reduce.c */ extern pcube sccc_merge(); +/* set.c */ extern bool set_andp(); +/* set.c */ extern bool set_orp(); +/* set.c */ extern bool setp_disjoint(); +/* set.c */ extern bool setp_empty(); +/* set.c */ extern bool setp_equal(); +/* set.c */ extern bool setp_full(); +/* set.c */ extern bool setp_implies(); +/* set.c */ extern char *pbv1(); +/* set.c */ extern char *ps1(); +/* set.c */ extern int *sf_count(); +/* set.c */ extern int *sf_count_restricted(); +/* set.c */ extern int bit_index(); +/* set.c */ extern int set_dist(); +/* set.c */ extern int set_ord(); +/* set.c */ extern void set_adjcnt(); +/* set.c */ extern pset set_and(); +/* set.c */ extern pset set_clear(); +/* set.c */ extern pset set_copy(); +/* set.c */ extern pset set_diff(); +/* set.c */ extern pset set_fill(); +/* set.c */ extern pset set_merge(); +/* set.c */ extern pset set_or(); +/* set.c */ extern pset set_xor(); +/* set.c */ extern pset sf_and(); +/* set.c */ extern pset sf_or(); +/* set.c */ extern pset_family sf_active(); +/* set.c */ extern pset_family sf_addcol(); +/* set.c */ extern pset_family sf_addset(); +/* set.c */ extern pset_family sf_append(); +/* set.c */ extern pset_family sf_bm_read(); +/* set.c */ extern pset_family sf_compress(); +/* set.c */ extern pset_family sf_copy(); +/* set.c */ extern pset_family sf_copy_col(); +/* set.c */ extern pset_family sf_delc(); +/* set.c */ extern pset_family sf_delcol(); +/* set.c */ extern pset_family sf_inactive(); +/* set.c */ extern pset_family sf_join(); +/* set.c */ extern pset_family sf_new(); +/* set.c */ extern pset_family sf_permute(); +/* set.c */ extern pset_family sf_read(); +/* set.c */ extern pset_family sf_save(); +/* set.c */ extern pset_family sf_transpose(); +/* set.c */ extern void set_write(); +/* set.c */ extern void sf_bm_print(); +/* set.c */ extern void sf_cleanup(); +/* set.c */ extern void sf_delset(); +/* set.c */ extern void sf_free(); +/* set.c */ extern void sf_print(); +/* set.c */ extern void sf_write(); +/* setc.c */ extern bool ccommon(); +/* setc.c */ extern bool cdist0(); +/* setc.c */ extern bool full_row(); +/* setc.c */ extern int ascend(); +/* setc.c */ extern int cactive(); +/* setc.c */ extern int cdist(); +/* setc.c */ extern int cdist01(); +/* setc.c */ extern int cvolume(); +/* setc.c */ extern int d1_order(); +/* setc.c */ extern int d1_order_size(); +/* setc.c */ extern int desc1(); +/* setc.c */ extern int descend(); +/* setc.c */ extern int lex_order(); +/* setc.c */ extern int lex_order1(); +/* setc.c */ extern pset force_lower(); +/* setc.c */ extern void consensus(); +/* sharp.c */ extern pcover cb1_dsharp(); +/* sharp.c */ extern pcover cb_dsharp(); +/* sharp.c */ extern pcover cb_recur_dsharp(); +/* sharp.c */ extern pcover cb_recur_sharp(); +/* sharp.c */ extern pcover cb_sharp(); +/* sharp.c */ extern pcover cv_dsharp(); +/* sharp.c */ extern pcover cv_intersect(); +/* sharp.c */ extern pcover cv_sharp(); +/* sharp.c */ extern pcover dsharp(); +/* sharp.c */ extern pcover make_disjoint(); +/* sharp.c */ extern pcover sharp(); +/* sminterf.c */pset do_sm_minimum_cover(); +/* sparse.c */ extern pcover make_sparse(); +/* sparse.c */ extern pcover mv_reduce(); +#if !defined(__osf__) && !defined(__STDC__) && !defined(__hpux) +/* ucbqsort.c */ extern qsort(); +#endif +/* ucbqsort.c */ extern qst(); +/* unate.c */ extern pcover find_all_minimal_covers_petrick(); +/* unate.c */ extern pcover map_cover_to_unate(); +/* unate.c */ extern pcover map_unate_to_cover(); +/* unate.c */ extern pset_family exact_minimum_cover(); +/* unate.c */ extern pset_family gen_primes(); +/* unate.c */ extern pset_family unate_compl(); +/* unate.c */ extern pset_family unate_complement(); +/* unate.c */ extern pset_family unate_intersect(); +/* verify.c */ extern PLA_permute(); +/* verify.c */ extern bool PLA_verify(); +/* verify.c */ extern bool check_consistency(); +/* verify.c */ extern bool verify(); diff --git a/abc70930/src/misc/espresso/essen.c b/abc70930/src/misc/espresso/essen.c new file mode 100644 index 00000000..6a46295d --- /dev/null +++ b/abc70930/src/misc/espresso/essen.c @@ -0,0 +1,179 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + module: essen.c + purpose: Find essential primes in a multiple-valued function +*/ + +#include "espresso.h" + +/* + essential -- return a cover consisting of the cubes of F which are + essential prime implicants (with respect to F u D); Further, remove + these cubes from the ON-set F, and add them to the OFF-set D. + + Sometimes EXPAND can determine that a cube is not an essential prime. + If so, it will set the "NONESSEN" flag in the cube. + + We count on IRREDUNDANT to have set the flag RELESSEN to indicate + that a prime was relatively essential (i.e., covers some minterm + not contained in any other prime in the current cover), or to have + reset the flag to indicate that a prime was relatively redundant + (i.e., all minterms covered by other primes in the current cover). + Of course, after executing irredundant, all of the primes in the + cover are relatively essential, but we can mark the primes which + were redundant at the start of irredundant and avoid an extra check + on these primes for essentiality. +*/ + +pcover essential(Fp, Dp) +IN pcover *Fp, *Dp; +{ + register pcube last, p; + pcover E, F = *Fp, D = *Dp; + + /* set all cubes in F active */ + (void) sf_active(F); + + /* Might as well start out with some cubes in E */ + E = new_cover(10); + + foreach_set(F, last, p) { + /* don't test a prime which EXPAND says is nonessential */ + if (! TESTP(p, NONESSEN)) { + /* only test a prime which was relatively essential */ + if (TESTP(p, RELESSEN)) { + /* Check essentiality */ + if (essen_cube(F, D, p)) { + if (debug & ESSEN) + printf("ESSENTIAL: %s\n", pc1(p)); + E = sf_addset(E, p); + RESET(p, ACTIVE); + F->active_count--; + } + } + } + } + + *Fp = sf_inactive(F); /* delete the inactive cubes from F */ + *Dp = sf_join(D, E); /* add the essentials to D */ + sf_free(D); + return E; +} + +/* + essen_cube -- check if a single cube is essential or not + + The prime c is essential iff + + consensus((F u D) # c, c) u D + + does not contain c. +*/ +bool essen_cube(F, D, c) +IN pcover F, D; +IN pcube c; +{ + pcover H, FD; + pcube *H1; + bool essen; + + /* Append F and D together, and take the sharp-consensus with c */ + FD = sf_join(F, D); + H = cb_consensus(FD, c); + free_cover(FD); + + /* Add the don't care set, and see if this covers c */ + H1 = cube2list(H, D); + essen = ! cube_is_covered(H1, c); + free_cubelist(H1); + + free_cover(H); + return essen; +} + + +/* + * cb_consensus -- compute consensus(T # c, c) + */ +pcover cb_consensus(T, c) +register pcover T; +register pcube c; +{ + register pcube temp, last, p; + register pcover R; + + R = new_cover(T->count*2); + temp = new_cube(); + foreach_set(T, last, p) { + if (p != c) { + switch (cdist01(p, c)) { + case 0: + /* distance-0 needs special care */ + R = cb_consensus_dist0(R, p, c); + break; + + case 1: + /* distance-1 is easy because no sharping required */ + consensus(temp, p, c); + R = sf_addset(R, temp); + break; + } + } + } + set_free(temp); + return R; +} + + +/* + * form the sharp-consensus for p and c when they intersect + * What we are forming is consensus(p # c, c). + */ +pcover cb_consensus_dist0(R, p, c) +pcover R; +register pcube p, c; +{ + int var; + bool got_one; + register pcube temp, mask; + register pcube p_diff_c=cube.temp[0], p_and_c=cube.temp[1]; + + /* If c contains p, then this gives us no information for essential test */ + if (setp_implies(p, c)) { + return R; + } + + /* For the multiple-valued variables */ + temp = new_cube(); + got_one = FALSE; + INLINEset_diff(p_diff_c, p, c); + INLINEset_and(p_and_c, p, c); + + for(var = cube.num_binary_vars; var < cube.num_vars; var++) { + /* Check if c(var) is contained in p(var) -- if so, no news */ + mask = cube.var_mask[var]; + if (! setp_disjoint(p_diff_c, mask)) { + INLINEset_merge(temp, c, p_and_c, mask); + R = sf_addset(R, temp); + got_one = TRUE; + } + } + + /* if no cube so far, add one for the intersection */ + if (! got_one && cube.num_binary_vars > 0) { + /* Add a single cube for the intersection of p and c */ + INLINEset_and(temp, p, c); + R = sf_addset(R, temp); + } + + set_free(temp); + return R; +} diff --git a/abc70930/src/misc/espresso/exact.c b/abc70930/src/misc/espresso/exact.c new file mode 100644 index 00000000..b1943636 --- /dev/null +++ b/abc70930/src/misc/espresso/exact.c @@ -0,0 +1,181 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + + +static void dump_irredundant(); +static pcover do_minimize(); + + +/* + * minimize_exact -- main entry point for exact minimization + * + * Global flags which affect this routine are: + * + * debug + * skip_make_sparse + */ + +pcover +minimize_exact(F, D, R, exact_cover) +pcover F, D, R; +int exact_cover; +{ + return do_minimize(F, D, R, exact_cover, /*weighted*/ 0); +} + + +pcover +minimize_exact_literals(F, D, R, exact_cover) +pcover F, D, R; +int exact_cover; +{ + return do_minimize(F, D, R, exact_cover, /*weighted*/ 1); +} + + + +static pcover +do_minimize(F, D, R, exact_cover, weighted) +pcover F, D, R; +int exact_cover; +int weighted; +{ + pcover newF, E, Rt, Rp; + pset p, last; + int heur, level, *weights, i; + sm_matrix *table; + sm_row *cover; + sm_element *pe; + int debug_save = debug; + + if (debug & EXACT) { + debug |= (IRRED | MINCOV); + } +#if defined(sun) || defined(bsd4_2) /* hack ... */ + if (debug & MINCOV) { + setlinebuf(stdout); + } +#endif + level = (debug & MINCOV) ? 4 : 0; + heur = ! exact_cover; + + /* Generate all prime implicants */ + EXEC(F = primes_consensus(cube2list(F, D)), "PRIMES ", F); + + /* Setup the prime implicant table */ + EXEC(irred_split_cover(F, D, &E, &Rt, &Rp), "ESSENTIALS ", E); + EXEC(table = irred_derive_table(D, E, Rp), "PI-TABLE ", Rp); + + /* Solve either a weighted or nonweighted covering problem */ + if (weighted) { + /* correct only for all 2-valued variables */ + weights = ALLOC(int, F->count); + foreach_set(Rp, last, p) { + weights[SIZE(p)] = cube.size - set_ord(p); + /* We have added the 0's in the output part instead of the 1's. + This loop corrects the literal count. */ + for (i = cube.first_part[cube.output]; + i <= cube.last_part[cube.output]; i++) { + is_in_set(p, i) ? weights[SIZE(p)]++ : weights[SIZE(p)]--; + } + } + } else { + weights = NIL(int); + } + EXEC(cover=sm_minimum_cover(table,weights,heur,level), "MINCOV ", F); + if (weights != 0) { + FREE(weights); + } + + if (debug & EXACT) { + dump_irredundant(E, Rt, Rp, table); + } + + /* Form the result cover */ + newF = new_cover(100); + foreach_set(E, last, p) { + newF = sf_addset(newF, p); + } + sm_foreach_row_element(cover, pe) { + newF = sf_addset(newF, GETSET(F, pe->col_num)); + } + + free_cover(E); + free_cover(Rt); + free_cover(Rp); + sm_free(table); + sm_row_free(cover); + free_cover(F); + + /* Attempt to make the results more sparse */ + debug &= ~ (IRRED | SHARP | MINCOV); + if (! skip_make_sparse && R != 0) { + newF = make_sparse(newF, D, R); + } + + debug = debug_save; + return newF; +} + +static void +dump_irredundant(E, Rt, Rp, table) +pcover E, Rt, Rp; +sm_matrix *table; +{ + FILE *fp_pi_table, *fp_primes; + pPLA PLA; + pset last, p; + char *file; + + if (filename == 0 || strcmp(filename, "(stdin)") == 0) { + fp_pi_table = fp_primes = stdout; + } else { + file = ALLOC(char, strlen(filename)+20); + (void) sprintf(file, "%s.primes", filename); + if ((fp_primes = fopen(file, "w")) == NULL) { + (void) fprintf(stderr, "espresso: Unable to open %s\n", file); + fp_primes = stdout; + } + (void) sprintf(file, "%s.pi", filename); + if ((fp_pi_table = fopen(file, "w")) == NULL) { + (void) fprintf(stderr, "espresso: Unable to open %s\n", file); + fp_pi_table = stdout; + } + FREE(file); + } + + PLA = new_PLA(); + PLA_labels(PLA); + + fpr_header(fp_primes, PLA, F_type); + free_PLA(PLA); + + (void) fprintf(fp_primes, "# Essential primes are\n"); + foreach_set(E, last, p) { + (void) fprintf(fp_primes, "%s\n", pc1(p)); + } + (void) fprintf(fp_primes, "# Totally redundant primes are\n"); + foreach_set(Rt, last, p) { + (void) fprintf(fp_primes, "%s\n", pc1(p)); + } + (void) fprintf(fp_primes, "# Partially redundant primes are\n"); + foreach_set(Rp, last, p) { + (void) fprintf(fp_primes, "%s\n", pc1(p)); + } + if (fp_primes != stdout) { + (void) fclose(fp_primes); + } + + sm_write(fp_pi_table, table); + if (fp_pi_table != stdout) { + (void) fclose(fp_pi_table); + } +} diff --git a/abc70930/src/misc/espresso/expand.c b/abc70930/src/misc/espresso/expand.c new file mode 100644 index 00000000..2765d71c --- /dev/null +++ b/abc70930/src/misc/espresso/expand.c @@ -0,0 +1,693 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + module: expand.c + purpose: Perform the Espresso-II Expansion Step + + The idea is to take each nonprime cube of the on-set and expand it + into a prime implicant such that we can cover as many other cubes + of the on-set. If no cube of the on-set can be covered, then we + expand each cube into a large prime implicant by transforming the + problem into a minimum covering problem which is solved by the + heuristics of minimum_cover. + + These routines revolve around having a representation of the + OFF-set. (In contrast to the Espresso-II manuscript, we do NOT + require an "unwrapped" version of the OFF-set). + + Some conventions on variable names: + + SUPER_CUBE is the supercube of all cubes which can be covered + by an expansion of the cube being expanded + + OVEREXPANDED_CUBE is the cube which would result from expanding + all parts which can expand individually of the cube being expanded + + RAISE is the current expansion of the current cube + + FREESET is the set of parts which haven't been raised or lowered yet. + + INIT_LOWER is a set of parts to be removed from the free parts before + starting the expansion +*/ + +#include "espresso.h" + +/* + expand -- expand each nonprime cube of F into a prime implicant + + If nonsparse is true, only the non-sparse variables will be expanded; + this is done by forcing all of the sparse variables out of the free set. +*/ + +pcover expand(F, R, nonsparse) +INOUT pcover F; +IN pcover R; +IN bool nonsparse; /* expand non-sparse variables only */ +{ + register pcube last, p; + pcube RAISE, FREESET, INIT_LOWER, SUPER_CUBE, OVEREXPANDED_CUBE; + int var, num_covered; + bool change; + + /* Order the cubes according to "chewing-away from the edges" of mini */ + if (use_random_order) + F = random_order(F); + else + F = mini_sort(F, ascend); + + /* Allocate memory for variables needed by expand1() */ + RAISE = new_cube(); + FREESET = new_cube(); + INIT_LOWER = new_cube(); + SUPER_CUBE = new_cube(); + OVEREXPANDED_CUBE = new_cube(); + + /* Setup the initial lowering set (differs only for nonsparse) */ + if (nonsparse) + for(var = 0; var < cube.num_vars; var++) + if (cube.sparse[var]) + (void) set_or(INIT_LOWER, INIT_LOWER, cube.var_mask[var]); + + /* Mark all cubes as not covered, and maybe essential */ + foreach_set(F, last, p) { + RESET(p, COVERED); + RESET(p, NONESSEN); + } + + /* Try to expand each nonprime and noncovered cube */ + foreach_set(F, last, p) { + /* do not expand if PRIME or if covered by previous expansion */ + if (! TESTP(p, PRIME) && ! TESTP(p, COVERED)) { + + /* expand the cube p, result is RAISE */ + expand1(R, F, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE, + INIT_LOWER, &num_covered, p); + if (debug & EXPAND) + printf("EXPAND: %s (covered %d)\n", pc1(p), num_covered); + (void) set_copy(p, RAISE); + SET(p, PRIME); + RESET(p, COVERED); /* not really necessary */ + + /* See if we generated an inessential prime */ + if (num_covered == 0 && ! setp_equal(p, OVEREXPANDED_CUBE)) { + SET(p, NONESSEN); + } + } + } + + /* Delete any cubes of F which became covered during the expansion */ + F->active_count = 0; + change = FALSE; + foreach_set(F, last, p) { + if (TESTP(p, COVERED)) { + RESET(p, ACTIVE); + change = TRUE; + } else { + SET(p, ACTIVE); + F->active_count++; + } + } + if (change) + F = sf_inactive(F); + + free_cube(RAISE); + free_cube(FREESET); + free_cube(INIT_LOWER); + free_cube(SUPER_CUBE); + free_cube(OVEREXPANDED_CUBE); + return F; +} + +/* + expand1 -- Expand a single cube against the OFF-set +*/ +void expand1(BB, CC, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE, + INIT_LOWER, num_covered, c) +pcover BB; /* Blocking matrix (OFF-set) */ +pcover CC; /* Covering matrix (ON-set) */ +pcube RAISE; /* The current parts which have been raised */ +pcube FREESET; /* The current parts which are free */ +pcube OVEREXPANDED_CUBE; /* Overexpanded cube of c */ +pcube SUPER_CUBE; /* Supercube of all cubes of CC we cover */ +pcube INIT_LOWER; /* Parts to initially remove from FREESET */ +int *num_covered; /* Number of cubes of CC which are covered */ +pcube c; /* The cube to be expanded */ +{ + int bestindex; + + if (debug & EXPAND1) + printf("\nEXPAND1: \t%s\n", pc1(c)); + + /* initialize BB and CC */ + SET(c, PRIME); /* don't try to cover ourself */ + setup_BB_CC(BB, CC); + + /* initialize count of # cubes covered, and the supercube of them */ + *num_covered = 0; + (void) set_copy(SUPER_CUBE, c); + + /* Initialize the lowering, raising and unassigned sets */ + (void) set_copy(RAISE, c); + (void) set_diff(FREESET, cube.fullset, RAISE); + + /* If some parts are forced into lowering set, remove them */ + if (! setp_empty(INIT_LOWER)) { + (void) set_diff(FREESET, FREESET, INIT_LOWER); + elim_lowering(BB, CC, RAISE, FREESET); + } + + /* Determine what can be raised, and return the over-expanded cube */ + essen_parts(BB, CC, RAISE, FREESET); + (void) set_or(OVEREXPANDED_CUBE, RAISE, FREESET); + + /* While there are still cubes which can be covered, cover them ! */ + if (CC->active_count > 0) { + select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered); + } + + /* While there are still cubes covered by the overexpanded cube ... */ + while (CC->active_count > 0) { + bestindex = most_frequent(CC, FREESET); + set_insert(RAISE, bestindex); + set_remove(FREESET, bestindex); + essen_parts(BB, CC, RAISE, FREESET); + } + + /* Finally, when all else fails, choose the largest possible prime */ + /* We will loop only if we decide unravelling OFF-set is too expensive */ + while (BB->active_count > 0) { + mincov(BB, RAISE, FREESET); + } + + /* Raise any remaining free coordinates */ + (void) set_or(RAISE, RAISE, FREESET); +} + +/* + essen_parts -- determine which parts are forced into the lowering + set to insure that the cube be orthognal to the OFF-set. + + If any cube of the OFF-set is distance 1 from the raising cube, + then we must lower all parts of the conflicting variable. (If the + cube is distance 0, we detect this error here.) + + If there are essentially lowered parts, we can remove from consideration + any cubes of the OFF-set which are more than distance 1 from the + overexpanded cube of RAISE. +*/ + +void essen_parts(BB, CC, RAISE, FREESET) +pcover BB, CC; +pcube RAISE, FREESET; +{ + register pcube p, r = RAISE; + pcube lastp, xlower = cube.temp[0]; + int dist; + + (void) set_copy(xlower, cube.emptyset); + + foreach_active_set(BB, lastp, p) { +#ifdef NO_INLINE + if ((dist = cdist01(p, r)) > 1) goto exit_if; +#else + {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1) +{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto +exit_if;for(w=1;w>1)&DISJOINT)if(dist==1||( +dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube +mask;for(var=cube.num_binary_vars;var1)goto exit_if;nextvar:;}} +#endif + if (dist == 0) { + fatal("ON-set and OFF-set are not orthogonal"); + } else { + (void) force_lower(xlower, p, r); + BB->active_count--; + RESET(p, ACTIVE); + } +exit_if: ; + } + + if (! setp_empty(xlower)) { + (void) set_diff(FREESET, FREESET, xlower);/* remove from free set */ + elim_lowering(BB, CC, RAISE, FREESET); + } + + if (debug & EXPAND1) + printf("ESSEN_PARTS:\tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); +} + +/* + essen_raising -- determine which parts may always be added to + the raising set without restricting further expansions + + General rule: if some part is not blocked by any cube of BB, then + this part can always be raised. +*/ + +void essen_raising(BB, RAISE, FREESET) +register pcover BB; +pcube RAISE, FREESET; +{ + register pcube last, p, xraise = cube.temp[0]; + + /* Form union of all cubes of BB, and then take complement wrt FREESET */ + (void) set_copy(xraise, cube.emptyset); + foreach_active_set(BB, last, p) + INLINEset_or(xraise, xraise, p); + (void) set_diff(xraise, FREESET, xraise); + + (void) set_or(RAISE, RAISE, xraise); /* add to raising set */ + (void) set_diff(FREESET, FREESET, xraise); /* remove from free set */ + + if (debug & EXPAND1) + printf("ESSEN_RAISING:\tRAISE=%s FREESET=%s\n", + pc1(RAISE), pc2(FREESET)); +} + +/* + elim_lowering -- after removing parts from FREESET, we can reduce the + size of both BB and CC. + + We mark as inactive any cube of BB which does not intersect the + overexpanded cube (i.e., RAISE + FREESET). Likewise, we remove + from CC any cube which is not covered by the overexpanded cube. +*/ + +void elim_lowering(BB, CC, RAISE, FREESET) +pcover BB, CC; +pcube RAISE, FREESET; +{ + register pcube p, r = set_or(cube.temp[0], RAISE, FREESET); + pcube last; + + /* + * Remove sets of BB which are orthogonal to future expansions + */ + foreach_active_set(BB, last, p) { +#ifdef NO_INLINE + if (! cdist0(p, r)) +#else + {register int w,lastw;register unsigned int x;if((lastw=cube.inword)!=-1){x=p[ +lastw]&r[lastw];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w>1)&DISJOINT)goto false;}}}{register int w,var,lastw;register +pcube mask;for(var=cube.num_binary_vars;varactive_count--, RESET(p, ACTIVE); + } + + + /* + * Remove sets of CC which cannot be covered by future expansions + */ + if (CC != (pcover) NULL) { + foreach_active_set(CC, last, p) { +#ifdef NO_INLINE + if (! setp_implies(p, r)) +#else + INLINEsetp_implies(p, r, /* when false => */ goto false1); + /* when true => go to end of loop */ continue; + false1: +#endif + CC->active_count--, RESET(p, ACTIVE); + } + } +} + +/* + most_frequent -- When all else fails, select a reasonable part to raise + The active cubes of CC are the cubes which are covered by the + overexpanded cube of the original cube (however, we know that none + of them can actually be covered by a feasible expansion of the + original cube). We resort to the MINI strategy of selecting to + raise the part which will cover the same part in the most cubes of CC. +*/ +int most_frequent(CC, FREESET) +pcover CC; +pcube FREESET; +{ + register int i, best_part, best_count, *count; + register pset p, last; + + /* Count occurences of each variable */ + count = ALLOC(int, cube.size); + for(i = 0; i < cube.size; i++) + count[i] = 0; + if (CC != (pcover) NULL) + foreach_active_set(CC, last, p) + set_adjcnt(p, count, 1); + + /* Now find which free part occurs most often */ + best_count = best_part = -1; + for(i = 0; i < cube.size; i++) + if (is_in_set(FREESET,i) && count[i] > best_count) { + best_part = i; + best_count = count[i]; + } + FREE(count); + + if (debug & EXPAND1) + printf("MOST_FREQUENT:\tbest=%d FREESET=%s\n", best_part, pc2(FREESET)); + return best_part; +} + +/* + setup_BB_CC -- set up the blocking and covering set families; + + Note that the blocking family is merely the set of cubes of R, and + that CC is the set of cubes of F which might possibly be covered + (i.e., nonprime cubes, and cubes not already covered) +*/ + +void setup_BB_CC(BB, CC) +register pcover BB, CC; +{ + register pcube p, last; + + /* Create the block and cover set families */ + BB->active_count = BB->count; + foreach_set(BB, last, p) + SET(p, ACTIVE); + + if (CC != (pcover) NULL) { + CC->active_count = CC->count; + foreach_set(CC, last, p) + if (TESTP(p, COVERED) || TESTP(p, PRIME)) + CC->active_count--, RESET(p, ACTIVE); + else + SET(p, ACTIVE); + } +} + +/* + select_feasible -- Determine if there are cubes which can be covered, + and if so, raise those parts necessary to cover as many as possible. + + We really don't check to maximize the number that can be covered; + instead, we check, for each fcc, how many other fcc remain fcc + after expanding to cover the fcc. (Essentially one-level lookahead). +*/ + +void select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered) +pcover BB, CC; +pcube RAISE, FREESET, SUPER_CUBE; +int *num_covered; +{ + register pcube p, last, bestfeas, *feas; + register int i, j; + pcube *feas_new_lower; + int bestcount, bestsize, count, size, numfeas, lastfeas; + pcover new_lower; + + /* Start out with all cubes covered by the over-expanded cube as + * the "possibly" feasibly-covered cubes (pfcc) + */ + feas = ALLOC(pcube, CC->active_count); + numfeas = 0; + foreach_active_set(CC, last, p) + feas[numfeas++] = p; + + /* Setup extra cubes to record parts forced low after a covering */ + feas_new_lower = ALLOC(pcube, CC->active_count); + new_lower = new_cover(numfeas); + for(i = 0; i < numfeas; i++) + feas_new_lower[i] = GETSET(new_lower, i); + + +loop: + /* Find the essentially raised parts -- this might cover some cubes + for us, without having to find out if they are fcc or not + */ + essen_raising(BB, RAISE, FREESET); + + /* Now check all "possibly" feasibly covered cubes to check feasibility */ + lastfeas = numfeas; + numfeas = 0; + for(i = 0; i < lastfeas; i++) { + p = feas[i]; + + /* Check active because essen_parts might have removed it */ + if (TESTP(p, ACTIVE)) { + + /* See if the cube is already covered by RAISE -- + * this can happen because of essen_raising() or because of + * the previous "loop" + */ + if (setp_implies(p, RAISE)) { + (*num_covered) += 1; + (void) set_or(SUPER_CUBE, SUPER_CUBE, p); + CC->active_count--; + RESET(p, ACTIVE); + SET(p, COVERED); + /* otherwise, test if it is feasibly covered */ + } else if (feasibly_covered(BB,p,RAISE,feas_new_lower[numfeas])) { + feas[numfeas] = p; /* save the fcc */ + numfeas++; + } + } + } + if (debug & EXPAND1) + printf("SELECT_FEASIBLE: started with %d pfcc, ended with %d fcc\n", + lastfeas, numfeas); + + /* Exit here if there are no feasibly covered cubes */ + if (numfeas == 0) { + FREE(feas); + FREE(feas_new_lower); + free_cover(new_lower); + return; + } + + /* Now find which is the best feasibly covered cube */ + bestcount = 0; + bestsize = 9999; + for(i = 0; i < numfeas; i++) { + size = set_dist(feas[i], FREESET); /* # of newly raised parts */ + count = 0; /* # of other cubes which remain fcc after raising */ + +#define NEW +#ifdef NEW + for(j = 0; j < numfeas; j++) + if (setp_disjoint(feas_new_lower[i], feas[j])) + count++; +#else + for(j = 0; j < numfeas; j++) + if (setp_implies(feas[j], feas[i])) + count++; +#endif + if (count > bestcount) { + bestcount = count; + bestfeas = feas[i]; + bestsize = size; + } else if (count == bestcount && size < bestsize) { + bestfeas = feas[i]; + bestsize = size; + } + } + + /* Add the necessary parts to the raising set */ + (void) set_or(RAISE, RAISE, bestfeas); + (void) set_diff(FREESET, FREESET, RAISE); + if (debug & EXPAND1) + printf("FEASIBLE: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); + essen_parts(BB, CC, RAISE, FREESET); + goto loop; +/* NOTREACHED */ +} + +/* + feasibly_covered -- determine if the cube c is feasibly covered + (i.e., if it is possible to raise all of the necessary variables + while still insuring orthogonality with R). Also, if c is feasibly + covered, then compute the new set of parts which are forced into + the lowering set. +*/ + +bool feasibly_covered(BB, c, RAISE, new_lower) +pcover BB; +pcube c, RAISE, new_lower; +{ + register pcube p, r = set_or(cube.temp[0], RAISE, c); + int dist; + pcube lastp; + + set_copy(new_lower, cube.emptyset); + foreach_active_set(BB, lastp, p) { +#ifdef NO_INLINE + if ((dist = cdist01(p, r)) > 1) goto exit_if; +#else + {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1) +{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto +exit_if;for(w=1;w>1)&DISJOINT)if(dist==1||( +dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube +mask;for(var=cube.num_binary_vars;var1)goto exit_if;nextvar:;}} +#endif + if (dist == 0) + return FALSE; + else + (void) force_lower(new_lower, p, r); + exit_if: ; + } + return TRUE; +} + +/* + mincov -- transform the problem of expanding a cube to a maximally- + large prime implicant into the problem of selecting a minimum + cardinality cover over a family of sets. + + When we get to this point, we must unravel the remaining off-set. + This may be painful. +*/ + +void mincov(BB, RAISE, FREESET) +pcover BB; +pcube RAISE, FREESET; +{ + int expansion, nset, var, dist; + pset_family B; + register pcube xraise=cube.temp[0], xlower, p, last, plower; + +#ifdef RANDOM_MINCOV +#if defined(_POSIX_SOURCE) || defined(__SVR4) + dist = rand() % set_ord(FREESET); +#else + dist = random() % set_ord(FREESET); +#endif + for(var = 0; var < cube.size && dist >= 0; var++) { + if (is_in_set(FREESET, var)) { + dist--; + } + } + + set_insert(RAISE, var); + set_remove(FREESET, var); + (void) essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET); +#else + + /* Create B which are those cubes which we must avoid intersecting */ + B = new_cover(BB->active_count); + foreach_active_set(BB, last, p) { + plower = set_copy(GETSET(B, B->count++), cube.emptyset); + (void) force_lower(plower, p, RAISE); + } + + /* Determine how many sets it will blow up into after the unravel */ + nset = 0; + foreach_set(B, last, p) { + expansion = 1; + for(var = cube.num_binary_vars; var < cube.num_vars; var++) { + if ((dist=set_dist(p, cube.var_mask[var])) > 1) { + expansion *= dist; + if (expansion > 500) goto heuristic_mincov; + } + } + nset += expansion; + if (nset > 500) goto heuristic_mincov; + } + + B = unravel(B, cube.num_binary_vars); + xlower = do_sm_minimum_cover(B); + + /* Add any remaining free parts to the raising set */ + (void) set_or(RAISE, RAISE, set_diff(xraise, FREESET, xlower)); + (void) set_copy(FREESET, cube.emptyset); /* free set is empty */ + BB->active_count = 0; /* BB satisfied */ + if (debug & EXPAND1) { + printf("MINCOV: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); + } + sf_free(B); + set_free(xlower); + return; + +heuristic_mincov: + sf_free(B); + /* most_frequent will pick first free part */ + set_insert(RAISE, most_frequent(/*CC*/ (pcover) NULL, FREESET)); + (void) set_diff(FREESET, FREESET, RAISE); + essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET); + return; +#endif +} + +/* + find_all_primes -- find all of the primes which cover the + currently reduced BB +*/ +pcover find_all_primes(BB, RAISE, FREESET) +pcover BB; +register pcube RAISE, FREESET; +{ + register pset last, p, plower; + pset_family B, B1; + + if (BB->active_count == 0) { + B1 = new_cover(1); + p = GETSET(B1, B1->count++); + (void) set_copy(p, RAISE); + SET(p, PRIME); + } else { + B = new_cover(BB->active_count); + foreach_active_set(BB, last, p) { + plower = set_copy(GETSET(B, B->count++), cube.emptyset); + (void) force_lower(plower, p, RAISE); + } + B = sf_rev_contain(unravel(B, cube.num_binary_vars)); + B1 = exact_minimum_cover(B); + foreach_set(B1, last, p) { + INLINEset_diff(p, FREESET, p); + INLINEset_or(p, p, RAISE); + SET(p, PRIME); + } + free_cover(B); + } + return B1; +} + +/* + all_primes -- foreach cube in F, generate all of the primes + which cover the cube. +*/ + +pcover all_primes(F, R) +pcover F, R; +{ + register pcube last, p, RAISE, FREESET; + pcover Fall_primes, B1; + + FREESET = new_cube(); + RAISE = new_cube(); + Fall_primes = new_cover(F->count); + + foreach_set(F, last, p) { + if (TESTP(p, PRIME)) { + Fall_primes = sf_addset(Fall_primes, p); + } else { + /* Setup for call to essential parts */ + (void) set_copy(RAISE, p); + (void) set_diff(FREESET, cube.fullset, RAISE); + setup_BB_CC(R, /* CC */ (pcover) NULL); + essen_parts(R, /* CC */ (pcover) NULL, RAISE, FREESET); + + /* Find all of the primes, and add them to the prime set */ + B1 = find_all_primes(R, RAISE, FREESET); + Fall_primes = sf_append(Fall_primes, B1); + } + } + + set_free(RAISE); + set_free(FREESET); + return Fall_primes; +} diff --git a/abc70930/src/misc/espresso/gasp.c b/abc70930/src/misc/espresso/gasp.c new file mode 100644 index 00000000..aa3254d3 --- /dev/null +++ b/abc70930/src/misc/espresso/gasp.c @@ -0,0 +1,228 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + module: gasp.c + + The "last_gasp" heuristic computes the reduction of each cube in + the cover (without replacement) and then performs an expansion of + these cubes. The cubes which expand to cover some other cube are + added to the original cover and irredundant finds a minimal subset. + + If one of the reduced cubes expands to cover some other reduced + cube, then the new prime thus generated is a candidate for reducing + the size of the cover. + + super_gasp is a variation on this strategy which extracts a minimal + subset from the set of all prime implicants which cover all + maximally reduced cubes. +*/ + +#include "espresso.h" + + +/* + * reduce_gasp -- compute the maximal reduction of each cube of F + * + * If a cube does not reduce, it remains prime; otherwise, it is marked + * as nonprime. If the cube is redundant (should NEVER happen here) we + * just crap out ... + * + * A cover with all of the cubes of F is returned. Those that did + * reduce are marked "NONPRIME"; those that reduced are marked "PRIME". + * The cubes are in the same order as in F. + */ +static pcover reduce_gasp(F, D) +pcover F, D; +{ + pcube p, last, cunder, *FD; + pcover G; + + G = new_cover(F->count); + FD = cube2list(F, D); + + /* Reduce cubes of F without replacement */ + foreach_set(F, last, p) { + cunder = reduce_cube(FD, p); + if (setp_empty(cunder)) { + fatal("empty reduction in reduce_gasp, shouldn't happen"); + } else if (setp_equal(cunder, p)) { + SET(cunder, PRIME); /* just to make sure */ + G = sf_addset(G, p); /* it did not reduce ... */ + } else { + RESET(cunder, PRIME); /* it reduced ... */ + G = sf_addset(G, cunder); + } + if (debug & GASP) { + printf("REDUCE_GASP: %s reduced to %s\n", pc1(p), pc2(cunder)); + } + free_cube(cunder); + } + + free_cubelist(FD); + return G; +} + +/* + * expand_gasp -- expand each nonprime cube of F into a prime implicant + * + * The gasp strategy differs in that only those cubes which expand to + * cover some other cube are saved; also, all cubes are expanded + * regardless of whether they become covered or not. + */ + +pcover expand_gasp(F, D, R, Foriginal) +INOUT pcover F; +IN pcover D; +IN pcover R; +IN pcover Foriginal; +{ + int c1index; + pcover G; + + /* Try to expand each nonprime and noncovered cube */ + G = new_cover(10); + for(c1index = 0; c1index < F->count; c1index++) { + expand1_gasp(F, D, R, Foriginal, c1index, &G); + } + G = sf_dupl(G); + G = expand(G, R, /*nonsparse*/ FALSE); /* Make them prime ! */ + return G; +} + + + +/* + * expand1 -- Expand a single cube against the OFF-set, using the gasp strategy + */ +void expand1_gasp(F, D, R, Foriginal, c1index, G) +pcover F; /* reduced cubes of ON-set */ +pcover D; /* DC-set */ +pcover R; /* OFF-set */ +pcover Foriginal; /* ON-set before reduction (same order as F) */ +int c1index; /* which index of F (or Freduced) to be checked */ +pcover *G; +{ + register int c2index; + register pcube p, last, c2under; + pcube RAISE, FREESET, temp, *FD, c2essential; + pcover F1; + + if (debug & EXPAND1) { + printf("\nEXPAND1_GASP: \t%s\n", pc1(GETSET(F, c1index))); + } + + RAISE = new_cube(); + FREESET = new_cube(); + temp = new_cube(); + + /* Initialize the OFF-set */ + R->active_count = R->count; + foreach_set(R, last, p) { + SET(p, ACTIVE); + } + /* Initialize the reduced ON-set, all nonprime cubes become active */ + F->active_count = F->count; + foreachi_set(F, c2index, c2under) { + if (c1index == c2index || TESTP(c2under, PRIME)) { + F->active_count--; + RESET(c2under, ACTIVE); + } else { + SET(c2under, ACTIVE); + } + } + + /* Initialize the raising and unassigned sets */ + (void) set_copy(RAISE, GETSET(F, c1index)); + (void) set_diff(FREESET, cube.fullset, RAISE); + + /* Determine parts which must be lowered */ + essen_parts(R, F, RAISE, FREESET); + + /* Determine parts which can always be raised */ + essen_raising(R, RAISE, FREESET); + + /* See which, if any, of the reduced cubes we can cover */ + foreachi_set(F, c2index, c2under) { + if (TESTP(c2under, ACTIVE)) { + /* See if this cube can be covered by an expansion */ + if (setp_implies(c2under, RAISE) || + feasibly_covered(R, c2under, RAISE, temp)) { + + /* See if c1under can expanded to cover c2 reduced against + * (F - c1) u c1under; if so, c2 can definitely be removed ! + */ + + /* Copy F and replace c1 with c1under */ + F1 = sf_save(Foriginal); + (void) set_copy(GETSET(F1, c1index), GETSET(F, c1index)); + + /* Reduce c2 against ((F - c1) u c1under) */ + FD = cube2list(F1, D); + c2essential = reduce_cube(FD, GETSET(F1, c2index)); + free_cubelist(FD); + sf_free(F1); + + /* See if c2essential is covered by an expansion of c1under */ + if (feasibly_covered(R, c2essential, RAISE, temp)) { + (void) set_or(temp, RAISE, c2essential); + RESET(temp, PRIME); /* cube not prime */ + *G = sf_addset(*G, temp); + } + set_free(c2essential); + } + } + } + + free_cube(RAISE); + free_cube(FREESET); + free_cube(temp); +} + +/* irred_gasp -- Add new primes to F and find an irredundant subset */ +pcover irred_gasp(F, D, G) +pcover F, D, G; /* G is disposed of */ +{ + if (G->count != 0) + F = irredundant(sf_append(F, G), D); + else + free_cover(G); + return F; +} + + +/* last_gasp */ +pcover last_gasp(F, D, R, cost) +pcover F, D, R; +cost_t *cost; +{ + pcover G, G1; + + EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost); + EXECUTE(G1 = expand_gasp(G, D, R, F), GEXPAND_TIME, G1, *cost); + free_cover(G); + EXECUTE(F = irred_gasp(F, D, G1), GIRRED_TIME, F, *cost); + return F; +} + + +/* super_gasp */ +pcover super_gasp(F, D, R, cost) +pcover F, D, R; +cost_t *cost; +{ + pcover G, G1; + + EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost); + EXECUTE(G1 = all_primes(G, R), GEXPAND_TIME, G1, *cost); + free_cover(G); + EXEC(G = sf_dupl(sf_append(F, G1)), "NEWPRIMES", G); + EXECUTE(F = irredundant(G, D), IRRED_TIME, F, *cost); + return F; +} diff --git a/abc70930/src/misc/espresso/gimpel.c b/abc70930/src/misc/espresso/gimpel.c new file mode 100644 index 00000000..648bb64a --- /dev/null +++ b/abc70930/src/misc/espresso/gimpel.c @@ -0,0 +1,106 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + + +/* + * check for: + * + * c1 c2 rest + * -- -- --- + * 1 1 0 0 0 0 <-- primary row + * 1 0 S1 <-- secondary row + * 0 1 T1 + * 0 1 T2 + * 0 1 Tn + * 0 0 R + */ + +int +gimpel_reduce(A, select, weight, lb, bound, depth, stats, best) +sm_matrix *A; +solution_t *select; +int *weight; +int lb; +int bound; +int depth; +stats_t *stats; +solution_t **best; +{ + register sm_row *prow, *save_sec; + register sm_col *c1, *c2; + register sm_element *p, *p1; + int c1_col_num, c2_col_num, primary_row_num, secondary_row_num; + int reduce_it; + + reduce_it = 0; + for(prow = A->first_row; prow != 0; prow = prow->next_row) { + if (prow->length == 2) { + c1 = sm_get_col(A, prow->first_col->col_num); + c2 = sm_get_col(A, prow->last_col->col_num); + if (c1->length == 2) { + reduce_it = 1; + } else if (c2->length == 2) { + c1 = sm_get_col(A, prow->last_col->col_num); + c2 = sm_get_col(A, prow->first_col->col_num); + reduce_it = 1; + } + if (reduce_it) { + primary_row_num = prow->row_num; + secondary_row_num = c1->first_row->row_num; + if (secondary_row_num == primary_row_num) { + secondary_row_num = c1->last_row->row_num; + } + break; + } + } + } + + if (reduce_it) { + c1_col_num = c1->col_num; + c2_col_num = c2->col_num; + save_sec = sm_row_dup(sm_get_row(A, secondary_row_num)); + sm_row_remove(save_sec, c1_col_num); + + for(p = c2->first_row; p != 0; p = p->next_row) { + if (p->row_num != primary_row_num) { + /* merge rows S1 and T */ + for(p1 = save_sec->first_col; p1 != 0; p1 = p1->next_col) { + (void) sm_insert(A, p->row_num, p1->col_num); + } + } + } + + sm_delcol(A, c1_col_num); + sm_delcol(A, c2_col_num); + sm_delrow(A, primary_row_num); + sm_delrow(A, secondary_row_num); + + stats->gimpel_count++; + stats->gimpel++; + *best = sm_mincov(A, select, weight, lb-1, bound-1, depth, stats); + stats->gimpel--; + + if (*best != NIL(solution_t)) { + /* is secondary row covered ? */ + if (sm_row_intersects(save_sec, (*best)->row)) { + /* yes, actually select c2 */ + solution_add(*best, weight, c2_col_num); + } else { + solution_add(*best, weight, c1_col_num); + } + } + + sm_row_free(save_sec); + return 1; + } else { + return 0; + } +} diff --git a/abc70930/src/misc/espresso/globals.c b/abc70930/src/misc/espresso/globals.c new file mode 100644 index 00000000..d04771e9 --- /dev/null +++ b/abc70930/src/misc/espresso/globals.c @@ -0,0 +1,76 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +/* + * Global Variable Declarations + */ + +unsigned int debug; /* debug parameter */ +bool verbose_debug; /* -v: whether to print a lot */ +char *total_name[TIME_COUNT]; /* basic function names */ +long total_time[TIME_COUNT]; /* time spent in basic fcts */ +int total_calls[TIME_COUNT]; /* # calls to each fct */ + +bool echo_comments; /* turned off by -eat option */ +bool echo_unknown_commands; /* always true ?? */ +bool force_irredundant; /* -nirr command line option */ +bool skip_make_sparse; +bool kiss; /* -kiss command line option */ +bool pos; /* -pos command line option */ +bool print_solution; /* -x command line option */ +bool recompute_onset; /* -onset command line option */ +bool remove_essential; /* -ness command line option */ +bool single_expand; /* -fast command line option */ +bool summary; /* -s command line option */ +bool trace; /* -t command line option */ +bool unwrap_onset; /* -nunwrap command line option */ +bool use_random_order; /* -random command line option */ +bool use_super_gasp; /* -strong command line option */ +char *filename; /* filename PLA was read from */ + +struct pla_types_struct pla_types[] = { + "-f", F_type, + "-r", R_type, + "-d", D_type, + "-fd", FD_type, + "-fr", FR_type, + "-dr", DR_type, + "-fdr", FDR_type, + "-fc", F_type | CONSTRAINTS_type, + "-rc", R_type | CONSTRAINTS_type, + "-dc", D_type | CONSTRAINTS_type, + "-fdc", FD_type | CONSTRAINTS_type, + "-frc", FR_type | CONSTRAINTS_type, + "-drc", DR_type | CONSTRAINTS_type, + "-fdrc", FDR_type | CONSTRAINTS_type, + "-pleasure", PLEASURE_type, + "-eqn", EQNTOTT_type, + "-eqntott", EQNTOTT_type, + "-kiss", KISS_type, + "-cons", CONSTRAINTS_type, + "-scons", SYMBOLIC_CONSTRAINTS_type, + 0, 0 +}; + + +struct cube_struct cube, temp_cube_save; +struct cdata_struct cdata, temp_cdata_save; + +int bit_count[256] = { + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 +}; diff --git a/abc70930/src/misc/espresso/hack.c b/abc70930/src/misc/espresso/hack.c new file mode 100644 index 00000000..927f5341 --- /dev/null +++ b/abc70930/src/misc/espresso/hack.c @@ -0,0 +1,641 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +map_dcset(PLA) +pPLA PLA; +{ + int var, i; + pcover Tplus, Tminus, Tplusbar, Tminusbar; + pcover newf, term1, term2, dcset, dcsetbar; + pcube cplus, cminus, last, p; + + if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) + return; + + /* try to find a binary variable named "DONT_CARE" */ + var = -1; + for(i = 0; i < cube.num_binary_vars * 2; i++) { + if (strncmp(PLA->label[i], "DONT_CARE", 9) == 0 || + strncmp(PLA->label[i], "DONTCARE", 8) == 0 || + strncmp(PLA->label[i], "dont_care", 9) == 0 || + strncmp(PLA->label[i], "dontcare", 8) == 0) { + var = i/2; + break; + } + } + if (var == -1) { + return; + } + + /* form the cofactor cubes for the don't-care variable */ + cplus = set_save(cube.fullset); + cminus = set_save(cube.fullset); + set_remove(cplus, var*2); + set_remove(cminus, var*2 + 1); + + /* form the don't-care set */ + EXEC(simp_comp(cofactor(cube1list(PLA->F), cplus), &Tplus, &Tplusbar), + "simpcomp+", Tplus); + EXEC(simp_comp(cofactor(cube1list(PLA->F), cminus), &Tminus, &Tminusbar), + "simpcomp-", Tminus); + EXEC(term1 = cv_intersect(Tplus, Tminusbar), "term1 ", term1); + EXEC(term2 = cv_intersect(Tminus, Tplusbar), "term2 ", term2); + EXEC(dcset = sf_union(term1, term2), "union ", dcset); + EXEC(simp_comp(cube1list(dcset), &PLA->D, &dcsetbar), "simplify", PLA->D); + EXEC(newf = cv_intersect(PLA->F, dcsetbar), "separate ", PLA->F); + free_cover(PLA->F); + PLA->F = newf; + free_cover(Tplus); + free_cover(Tminus); + free_cover(Tplusbar); + free_cover(Tminusbar); + free_cover(dcsetbar); + + /* remove any cubes dependent on the DONT_CARE variable */ + (void) sf_active(PLA->F); + foreach_set(PLA->F, last, p) { + if (! is_in_set(p, var*2) || ! is_in_set(p, var*2+1)) { + RESET(p, ACTIVE); + } + } + PLA->F = sf_inactive(PLA->F); + + /* resize the cube and delete the don't-care variable */ + setdown_cube(); + for(i = 2*var+2; i < cube.size; i++) { + PLA->label[i-2] = PLA->label[i]; + } + for(i = var+1; i < cube.num_vars; i++) { + cube.part_size[i-1] = cube.part_size[i]; + } + cube.num_binary_vars--; + cube.num_vars--; + cube_setup(); + PLA->F = sf_delc(PLA->F, 2*var, 2*var+1); + PLA->D = sf_delc(PLA->D, 2*var, 2*var+1); +} + +map_output_symbolic(PLA) +pPLA PLA; +{ + pset_family newF, newD; + pset compress; + symbolic_t *p1; + symbolic_list_t *p2; + int i, bit, tot_size, base, old_size; + + /* Remove the DC-set from the ON-set (is this necessary ??) */ + if (PLA->D->count > 0) { + sf_free(PLA->F); + PLA->F = complement(cube2list(PLA->D, PLA->R)); + } + + /* tot_size = width added for all symbolic variables */ + tot_size = 0; + for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { + for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { + if (p2->pos<0 || p2->pos>=cube.part_size[cube.output]) { + fatal("symbolic-output index out of range"); +/* } else if (p2->variable != cube.output) { + fatal("symbolic-output label must be an output");*/ + } + } + tot_size += 1 << p1->symbolic_list_length; + } + + /* adjust the indices to skip over new outputs */ + for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { + for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { + p2->pos += tot_size; + } + } + + /* resize the cube structure -- add enough for the one-hot outputs */ + old_size = cube.size; + cube.part_size[cube.output] += tot_size; + setdown_cube(); + cube_setup(); + + /* insert space in the output part for the one-hot output */ + base = cube.first_part[cube.output]; + PLA->F = sf_addcol(PLA->F, base, tot_size); + PLA->D = sf_addcol(PLA->D, base, tot_size); + PLA->R = sf_addcol(PLA->R, base, tot_size); + + /* do the real work */ + for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { + newF = new_cover(100); + newD = new_cover(100); + find_inputs(NIL(set_family_t), PLA, p1->symbolic_list, base, 0, + &newF, &newD); +/* + * Not sure what this means + find_dc_inputs(PLA, p1->symbolic_list, + base, 1 << p1->symbolic_list_length, &newF, &newD); + */ + free_cover(PLA->F); + PLA->F = newF; +/* + * retain OLD DC-set -- but we've lost the don't-care arc information + * (it defaults to branch to the zero state) + free_cover(PLA->D); + PLA->D = newD; + */ + free_cover(newD); + base += 1 << p1->symbolic_list_length; + } + + /* delete the old outputs, and resize the cube */ + compress = set_full(newF->sf_size); + for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { + for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { + bit = cube.first_part[cube.output] + p2->pos; + set_remove(compress, bit); + } + } + cube.part_size[cube.output] -= newF->sf_size - set_ord(compress); + setdown_cube(); + cube_setup(); + PLA->F = sf_compress(PLA->F, compress); + PLA->D = sf_compress(PLA->D, compress); + if (cube.size != PLA->F->sf_size) fatal("error"); + + /* Quick minimization */ + PLA->F = sf_contain(PLA->F); + PLA->D = sf_contain(PLA->D); + for(i = 0; i < cube.num_vars; i++) { + PLA->F = d1merge(PLA->F, i); + PLA->D = d1merge(PLA->D, i); + } + PLA->F = sf_contain(PLA->F); + PLA->D = sf_contain(PLA->D); + + free_cover(PLA->R); + PLA->R = new_cover(0); + + symbolic_hack_labels(PLA, PLA->symbolic_output, + compress, cube.size, old_size, tot_size); + set_free(compress); +} + + +find_inputs(A, PLA, list, base, value, newF, newD) +pcover A; +pPLA PLA; +symbolic_list_t *list; +int base, value; +pcover *newF, *newD; +{ + pcover S, S1; + register pset last, p; + + /* + * A represents th 'input' values for which the outputs assume + * the integer value 'value + */ + if (list == NIL(symbolic_list_t)) { + /* + * Simulate these inputs against the on-set; then, insert into the + * new on-set a 1 in the proper position + */ + S = cv_intersect(A, PLA->F); + foreach_set(S, last, p) { + set_insert(p, base + value); + } + *newF = sf_append(*newF, S); + + /* + * 'simulate' these inputs against the don't-care set + S = cv_intersect(A, PLA->D); + *newD = sf_append(*newD, S); + */ + + } else { + /* intersect and recur with the OFF-set */ + S = cof_output(PLA->R, cube.first_part[cube.output] + list->pos); + if (A != NIL(set_family_t)) { + S1 = cv_intersect(A, S); + free_cover(S); + S = S1; + } + find_inputs(S, PLA, list->next, base, value*2, newF, newD); + free_cover(S); + + /* intersect and recur with the ON-set */ + S = cof_output(PLA->F, cube.first_part[cube.output] + list->pos); + if (A != NIL(set_family_t)) { + S1 = cv_intersect(A, S); + free_cover(S); + S = S1; + } + find_inputs(S, PLA, list->next, base, value*2 + 1, newF, newD); + free_cover(S); + } +} + + +#if 0 +find_dc_inputs(PLA, list, base, maxval, newF, newD) +pPLA PLA; +symbolic_list_t *list; +int base, maxval; +pcover *newF, *newD; +{ + pcover A, S, S1; + symbolic_list_t *p2; + register pset p, last; + register int i; + + /* painfully find the points for which the symbolic output is dc */ + A = NIL(set_family_t); + for(p2=list; p2!=NIL(symbolic_list_t); p2=p2->next) { + S = cof_output(PLA->D, cube.first_part[cube.output] + p2->pos); + if (A == NIL(set_family_t)) { + A = S; + } else { + S1 = cv_intersect(A, S); + free_cover(S); + free_cover(A); + A = S1; + } + } + + S = cv_intersect(A, PLA->F); + *newF = sf_append(*newF, S); + + S = cv_intersect(A, PLA->D); + foreach_set(S, last, p) { + for(i = base; i < base + maxval; i++) { + set_insert(p, i); + } + } + *newD = sf_append(*newD, S); + free_cover(A); +} +#endif + +map_symbolic(PLA) +pPLA PLA; +{ + symbolic_t *p1; + symbolic_list_t *p2; + int var, base, num_vars, num_binary_vars, *new_part_size; + int new_size, size_added, num_deleted_vars, num_added_vars, newvar; + pset compress; + + /* Verify legal values are in the symbolic lists */ + for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { + for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { + if (p2->variable < 0 || p2->variable >= cube.num_binary_vars) { + fatal(".symbolic requires binary variables"); + } + } + } + + /* + * size_added = width added for all symbolic variables + * num_deleted_vars = # binary variables to be deleted + * num_added_vars = # new mv variables + * compress = a cube which will be used to compress the set families + */ + size_added = 0; + num_added_vars = 0; + for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { + size_added += 1 << p1->symbolic_list_length; + num_added_vars++; + } + compress = set_full(PLA->F->sf_size + size_added); + for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { + for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { + set_remove(compress, p2->variable*2); + set_remove(compress, p2->variable*2+1); + } + } + num_deleted_vars = ((PLA->F->sf_size + size_added) - set_ord(compress))/2; + + /* compute the new cube constants */ + num_vars = cube.num_vars - num_deleted_vars + num_added_vars; + num_binary_vars = cube.num_binary_vars - num_deleted_vars; + new_size = cube.size - num_deleted_vars*2 + size_added; + new_part_size = ALLOC(int, num_vars); + new_part_size[num_vars-1] = cube.part_size[cube.num_vars-1]; + for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) { + new_part_size[var-num_deleted_vars] = cube.part_size[var]; + } + + /* re-size the covers, opening room for the new mv variables */ + base = cube.first_part[cube.output]; + PLA->F = sf_addcol(PLA->F, base, size_added); + PLA->D = sf_addcol(PLA->D, base, size_added); + PLA->R = sf_addcol(PLA->R, base, size_added); + + /* compute the values for the new mv variables */ + newvar = (cube.num_vars - 1) - num_deleted_vars; + for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { + PLA->F = map_symbolic_cover(PLA->F, p1->symbolic_list, base); + PLA->D = map_symbolic_cover(PLA->D, p1->symbolic_list, base); + PLA->R = map_symbolic_cover(PLA->R, p1->symbolic_list, base); + base += 1 << p1->symbolic_list_length; + new_part_size[newvar++] = 1 << p1->symbolic_list_length; + } + + /* delete the binary variables which disappear */ + PLA->F = sf_compress(PLA->F, compress); + PLA->D = sf_compress(PLA->D, compress); + PLA->R = sf_compress(PLA->R, compress); + + symbolic_hack_labels(PLA, PLA->symbolic, compress, + new_size, cube.size, size_added); + setdown_cube(); + FREE(cube.part_size); + cube.num_vars = num_vars; + cube.num_binary_vars = num_binary_vars; + cube.part_size = new_part_size; + cube_setup(); + set_free(compress); +} + + +pcover map_symbolic_cover(T, list, base) +pcover T; +symbolic_list_t *list; +int base; +{ + pset last, p; + foreach_set(T, last, p) { + form_bitvector(p, base, 0, list); + } + return T; +} + + +form_bitvector(p, base, value, list) +pset p; /* old cube, looking at binary variables */ +int base; /* where in mv cube the new variable starts */ +int value; /* current value for this recursion */ +symbolic_list_t *list; /* current place in the symbolic list */ +{ + if (list == NIL(symbolic_list_t)) { + set_insert(p, base + value); + } else { + switch(GETINPUT(p, list->variable)) { + case ZERO: + form_bitvector(p, base, value*2, list->next); + break; + case ONE: + form_bitvector(p, base, value*2+1, list->next); + break; + case TWO: + form_bitvector(p, base, value*2, list->next); + form_bitvector(p, base, value*2+1, list->next); + break; + default: + fatal("bad cube in form_bitvector"); + } + } +} + + +symbolic_hack_labels(PLA, list, compress, new_size, old_size, size_added) +pPLA PLA; +symbolic_t *list; +pset compress; +int new_size, old_size, size_added; +{ + int i, base; + char **oldlabel; + symbolic_t *p1; + symbolic_label_t *p3; + + /* hack with the labels */ + if ((oldlabel = PLA->label) == NIL(char *)) + return; + PLA->label = ALLOC(char *, new_size); + for(i = 0; i < new_size; i++) { + PLA->label[i] = NIL(char); + } + + /* copy the binary variable labels and unchanged mv variable labels */ + base = 0; + for(i = 0; i < cube.first_part[cube.output]; i++) { + if (is_in_set(compress, i)) { + PLA->label[base++] = oldlabel[i]; + } else { + if (oldlabel[i] != NIL(char)) { + FREE(oldlabel[i]); + } + } + } + + /* add the user-defined labels for the symbolic outputs */ + for(p1 = list; p1 != NIL(symbolic_t); p1 = p1->next) { + p3 = p1->symbolic_label; + for(i = 0; i < (1 << p1->symbolic_list_length); i++) { + if (p3 == NIL(symbolic_label_t)) { + PLA->label[base+i] = ALLOC(char, 10); + (void) sprintf(PLA->label[base+i], "X%d", i); + } else { + PLA->label[base+i] = p3->label; + p3 = p3->next; + } + } + base += 1 << p1->symbolic_list_length; + } + + /* copy the labels for the binary outputs which remain */ + for(i = cube.first_part[cube.output]; i < old_size; i++) { + if (is_in_set(compress, i + size_added)) { + PLA->label[base++] = oldlabel[i]; + } else { + if (oldlabel[i] != NIL(char)) { + FREE(oldlabel[i]); + } + } + } + FREE(oldlabel); +} + +static pcover fsm_simplify(F) +pcover F; +{ + pcover D, R; + D = new_cover(0); + R = complement(cube1list(F)); + F = espresso(F, D, R); + free_cover(D); + free_cover(R); + return F; +} + + +disassemble_fsm(PLA, verbose_mode) +pPLA PLA; +int verbose_mode; +{ + int nin, nstates, nout; + int before, after, present_state, next_state, i, j; + pcube next_state_mask, present_state_mask, state_mask, p, p1, last; + pcover go_nowhere, F, tF; + + /* We make the DISGUSTING assumption that the first 'n' outputs have + * been created by .symbolic-output, and represent a one-hot encoding + * of the next state. 'n' is the size of the second-to-last multiple- + * valued variable (i.e., before the outputs + */ + + if (cube.num_vars - cube.num_binary_vars != 2) { + (void) fprintf(stderr, + "use .symbolic and .symbolic-output to specify\n"); + (void) fprintf(stderr, + "the present state and next state field information\n"); + fatal("disassemble_pla: need two multiple-valued variables\n"); + } + + nin = cube.num_binary_vars; + nstates = cube.part_size[cube.num_binary_vars]; + nout = cube.part_size[cube.num_vars - 1]; + if (nout < nstates) { + (void) fprintf(stderr, + "use .symbolic and .symbolic-output to specify\n"); + (void) fprintf(stderr, + "the present state and next state field information\n"); + fatal("disassemble_pla: # outputs < # states\n"); + } + + + present_state = cube.first_part[cube.num_binary_vars]; + present_state_mask = new_cube(); + for(i = 0; i < nstates; i++) { + set_insert(present_state_mask, i + present_state); + } + + next_state = cube.first_part[cube.num_binary_vars+1]; + next_state_mask = new_cube(); + for(i = 0; i < nstates; i++) { + set_insert(next_state_mask, i + next_state); + } + + state_mask = set_or(new_cube(), next_state_mask, present_state_mask); + + F = new_cover(10); + + + /* + * check for arcs which go from ANY state to state #i + */ + for(i = 0; i < nstates; i++) { + tF = new_cover(10); + foreach_set(PLA->F, last, p) { + if (setp_implies(present_state_mask, p)) { /* from any state ! */ + if (is_in_set(p, next_state + i)) { + tF = sf_addset(tF, p); + } + } + } + before = tF->count; + if (before > 0) { + tF = fsm_simplify(tF); + /* don't allow the next state to disappear ... */ + foreach_set(tF, last, p) { + set_insert(p, next_state + i); + } + after = tF->count; + F = sf_append(F, tF); + if (verbose_mode) { + printf("# state EVERY to %d, before=%d after=%d\n", + i, before, after); + } + } + } + + + /* + * some 'arcs' may NOT have a next state -- handle these + * we must unravel the present state part + */ + go_nowhere = new_cover(10); + foreach_set(PLA->F, last, p) { + if (setp_disjoint(p, next_state_mask)) { /* no next state !! */ + go_nowhere = sf_addset(go_nowhere, p); + } + } + before = go_nowhere->count; + go_nowhere = unravel_range(go_nowhere, + cube.num_binary_vars, cube.num_binary_vars); + after = go_nowhere->count; + F = sf_append(F, go_nowhere); + if (verbose_mode) { + printf("# state ANY to NOWHERE, before=%d after=%d\n", before, after); + } + + + /* + * minimize cover for all arcs from state #i to state #j + */ + for(i = 0; i < nstates; i++) { + for(j = 0; j < nstates; j++) { + tF = new_cover(10); + foreach_set(PLA->F, last, p) { + /* not EVERY state */ + if (! setp_implies(present_state_mask, p)) { + if (is_in_set(p, present_state + i)) { + if (is_in_set(p, next_state + j)) { + p1 = set_save(p); + set_diff(p1, p1, state_mask); + set_insert(p1, present_state + i); + set_insert(p1, next_state + j); + tF = sf_addset(tF, p1); + set_free(p1); + } + } + } + } + before = tF->count; + if (before > 0) { + tF = fsm_simplify(tF); + /* don't allow the next state to disappear ... */ + foreach_set(tF, last, p) { + set_insert(p, next_state + j); + } + after = tF->count; + F = sf_append(F, tF); + if (verbose_mode) { + printf("# state %d to %d, before=%d after=%d\n", + i, j, before, after); + } + } + } + } + + + free_cube(state_mask); + free_cube(present_state_mask); + free_cube(next_state_mask); + + free_cover(PLA->F); + PLA->F = F; + free_cover(PLA->D); + PLA->D = new_cover(0); + + setdown_cube(); + FREE(cube.part_size); + cube.num_binary_vars = nin; + cube.num_vars = nin + 3; + cube.part_size = ALLOC(int, cube.num_vars); + cube.part_size[cube.num_binary_vars] = nstates; + cube.part_size[cube.num_binary_vars+1] = nstates; + cube.part_size[cube.num_binary_vars+2] = nout - nstates; + cube_setup(); + + foreach_set(PLA->F, last, p) { + kiss_print_cube(stdout, PLA, p, "~1"); + } +} diff --git a/abc70930/src/misc/espresso/indep.c b/abc70930/src/misc/espresso/indep.c new file mode 100644 index 00000000..10b363a0 --- /dev/null +++ b/abc70930/src/misc/espresso/indep.c @@ -0,0 +1,134 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + +static sm_matrix *build_intersection_matrix(); + + +#if 0 +/* + * verify that all rows in 'indep' are actually independent ! + */ +static int +verify_indep_set(A, indep) +sm_matrix *A; +sm_row *indep; +{ + register sm_row *prow, *prow1; + register sm_element *p, *p1; + + for(p = indep->first_col; p != 0; p = p->next_col) { + prow = sm_get_row(A, p->col_num); + for(p1 = p->next_col; p1 != 0; p1 = p1->next_col) { + prow1 = sm_get_row(A, p1->col_num); + if (sm_row_intersects(prow, prow1)) { + return 0; + } + } + } + return 1; +} +#endif + +solution_t * +sm_maximal_independent_set(A, weight) +sm_matrix *A; +int *weight; +{ + register sm_row *best_row, *prow; + register sm_element *p; + int least_weight; + sm_row *save; + sm_matrix *B; + solution_t *indep; + + indep = solution_alloc(); + B = build_intersection_matrix(A); + + while (B->nrows > 0) { + /* Find the row which is disjoint from a maximum number of rows */ + best_row = B->first_row; + for(prow = B->first_row->next_row; prow != 0; prow = prow->next_row) { + if (prow->length < best_row->length) { + best_row = prow; + } + } + + /* Find which element in this row has least weight */ + if (weight == NIL(int)) { + least_weight = 1; + } else { + prow = sm_get_row(A, best_row->row_num); + least_weight = weight[prow->first_col->col_num]; + for(p = prow->first_col->next_col; p != 0; p = p->next_col) { + if (weight[p->col_num] < least_weight) { + least_weight = weight[p->col_num]; + } + } + } + indep->cost += least_weight; + (void) sm_row_insert(indep->row, best_row->row_num); + + /* Discard the rows which intersect this row */ + save = sm_row_dup(best_row); + for(p = save->first_col; p != 0; p = p->next_col) { + sm_delrow(B, p->col_num); + sm_delcol(B, p->col_num); + } + sm_row_free(save); + } + + sm_free(B); + +/* + if (! verify_indep_set(A, indep->row)) { + fail("sm_maximal_independent_set: row set is not independent"); + } +*/ + return indep; +} + +static sm_matrix * +build_intersection_matrix(A) +sm_matrix *A; +{ + register sm_row *prow, *prow1; + register sm_element *p, *p1; + register sm_col *pcol; + sm_matrix *B; + + /* Build row-intersection matrix */ + B = sm_alloc(); + for(prow = A->first_row; prow != 0; prow = prow->next_row) { + + /* Clear flags on all rows we can reach from row 'prow' */ + for(p = prow->first_col; p != 0; p = p->next_col) { + pcol = sm_get_col(A, p->col_num); + for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) { + prow1 = sm_get_row(A, p1->row_num); + prow1->flag = 0; + } + } + + /* Now record which rows can be reached */ + for(p = prow->first_col; p != 0; p = p->next_col) { + pcol = sm_get_col(A, p->col_num); + for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) { + prow1 = sm_get_row(A, p1->row_num); + if (! prow1->flag) { + prow1->flag = 1; + (void) sm_insert(B, prow->row_num, prow1->row_num); + } + } + } + } + + return B; +} diff --git a/abc70930/src/misc/espresso/irred.c b/abc70930/src/misc/espresso/irred.c new file mode 100644 index 00000000..384e698f --- /dev/null +++ b/abc70930/src/misc/espresso/irred.c @@ -0,0 +1,440 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +static void fcube_is_covered(); +static void ftautology(); +static bool ftaut_special_cases(); + + +static int Rp_current; + +/* + * irredundant -- Return a minimal subset of F + */ + +pcover +irredundant(F, D) +pcover F, D; +{ + mark_irredundant(F, D); + return sf_inactive(F); +} + + +/* + * mark_irredundant -- find redundant cubes, and mark them "INACTIVE" + */ + +void +mark_irredundant(F, D) +pcover F, D; +{ + pcover E, Rt, Rp; + pset p, p1, last; + sm_matrix *table; + sm_row *cover; + sm_element *pe; + + /* extract a minimum cover */ + irred_split_cover(F, D, &E, &Rt, &Rp); + table = irred_derive_table(D, E, Rp); + cover = sm_minimum_cover(table, NIL(int), /* heuristic */ 1, /* debug */ 0); + + /* mark the cubes for the result */ + foreach_set(F, last, p) { + RESET(p, ACTIVE); + RESET(p, RELESSEN); + } + foreach_set(E, last, p) { + p1 = GETSET(F, SIZE(p)); + assert(setp_equal(p1, p)); + SET(p1, ACTIVE); + SET(p1, RELESSEN); /* for essen(), mark as rel. ess. */ + } + sm_foreach_row_element(cover, pe) { + p1 = GETSET(F, pe->col_num); + SET(p1, ACTIVE); + } + + if (debug & IRRED) { + printf("# IRRED: F=%d E=%d R=%d Rt=%d Rp=%d Rc=%d Final=%d Bound=%d\n", + F->count, E->count, Rt->count+Rp->count, Rt->count, Rp->count, + cover->length, E->count + cover->length, 0); + } + + free_cover(E); + free_cover(Rt); + free_cover(Rp); + sm_free(table); + sm_row_free(cover); +} + +/* + * irred_split_cover -- find E, Rt, and Rp from the cover F, D + * + * E -- relatively essential cubes + * Rt -- totally redundant cubes + * Rp -- partially redundant cubes + */ + +void +irred_split_cover(F, D, E, Rt, Rp) +pcover F, D; +pcover *E, *Rt, *Rp; +{ + register pcube p, last; + register int index; + pcover R; + pcube *FD, *ED; + + /* number the cubes of F -- these numbers track into E, Rp, Rt, etc. */ + index = 0; + foreach_set(F, last, p) { + PUTSIZE(p, index); + index++; + } + + *E = new_cover(10); + *Rt = new_cover(10); + *Rp = new_cover(10); + R = new_cover(10); + + /* Split F into E and R */ + FD = cube2list(F, D); + foreach_set(F, last, p) { + if (cube_is_covered(FD, p)) { + R = sf_addset(R, p); + } else { + *E = sf_addset(*E, p); + } + if (debug & IRRED1) { + (void) printf("IRRED1: zr=%d ze=%d to-go=%d time=%s\n", + R->count, (*E)->count, F->count - (R->count + (*E)->count), + print_time(ptime())); + } + } + free_cubelist(FD); + + /* Split R into Rt and Rp */ + ED = cube2list(*E, D); + foreach_set(R, last, p) { + if (cube_is_covered(ED, p)) { + *Rt = sf_addset(*Rt, p); + } else { + *Rp = sf_addset(*Rp, p); + } + if (debug & IRRED1) { + (void) printf("IRRED1: zr=%d zrt=%d to-go=%d time=%s\n", + (*Rp)->count, (*Rt)->count, + R->count - ((*Rp)->count +(*Rt)->count), print_time(ptime())); + } + } + free_cubelist(ED); + + free_cover(R); +} + +/* + * irred_derive_table -- given the covers D, E and the set of + * partially redundant primes Rp, build a covering table showing + * possible selections of primes to cover Rp. + */ + +sm_matrix * +irred_derive_table(D, E, Rp) +pcover D, E, Rp; +{ + register pcube last, p, *list; + sm_matrix *table; + int size_last_dominance, i; + + /* Mark each cube in DE as not part of the redundant set */ + foreach_set(D, last, p) { + RESET(p, REDUND); + } + foreach_set(E, last, p) { + RESET(p, REDUND); + } + + /* Mark each cube in Rp as partially redundant */ + foreach_set(Rp, last, p) { + SET(p, REDUND); /* belongs to redundant set */ + } + + /* For each cube in Rp, find ways to cover its minterms */ + list = cube3list(D, E, Rp); + table = sm_alloc(); + size_last_dominance = 0; + i = 0; + foreach_set(Rp, last, p) { + Rp_current = SIZE(p); + fcube_is_covered(list, p, table); + RESET(p, REDUND); /* can now consider this cube redundant */ + if (debug & IRRED1) { + (void) printf("IRRED1: %d of %d to-go=%d, table=%dx%d time=%s\n", + i, Rp->count, Rp->count - i, + table->nrows, table->ncols, print_time(ptime())); + } + /* try to keep memory limits down by reducing table as we go along */ + if (table->nrows - size_last_dominance > 1000) { + (void) sm_row_dominance(table); + size_last_dominance = table->nrows; + if (debug & IRRED1) { + (void) printf("IRRED1: delete redundant rows, now %dx%d\n", + table->nrows, table->ncols); + } + } + i++; + } + free_cubelist(list); + + return table; +} + +/* cube_is_covered -- determine if a cubelist "covers" a single cube */ +bool +cube_is_covered(T, c) +pcube *T, c; +{ + return tautology(cofactor(T,c)); +} + + + +/* tautology -- answer the tautology question for T */ +bool +tautology(T) +pcube *T; /* T will be disposed of */ +{ + register pcube cl, cr; + register int best, result; + static int taut_level = 0; + + if (debug & TAUT) { + debug_print(T, "TAUTOLOGY", taut_level++); + } + + if ((result = taut_special_cases(T)) == MAYBE) { + cl = new_cube(); + cr = new_cube(); + best = binate_split_select(T, cl, cr, TAUT); + result = tautology(scofactor(T, cl, best)) && + tautology(scofactor(T, cr, best)); + free_cubelist(T); + free_cube(cl); + free_cube(cr); + } + + if (debug & TAUT) { + printf("exit TAUTOLOGY[%d]: %s\n", --taut_level, print_bool(result)); + } + return result; +} + +/* + * taut_special_cases -- check special cases for tautology + */ + +bool +taut_special_cases(T) +pcube *T; /* will be disposed if answer is determined */ +{ + register pcube *T1, *Tsave, p, ceil=cube.temp[0], temp=cube.temp[1]; + pcube *A, *B; + int var; + + /* Check for a row of all 1's which implies tautology */ + for(T1 = T+2; (p = *T1++) != NULL; ) { + if (full_row(p, T[0])) { + free_cubelist(T); + return TRUE; + } + } + + /* Check for a column of all 0's which implies no tautology */ +start: + INLINEset_copy(ceil, T[0]); + for(T1 = T+2; (p = *T1++) != NULL; ) { + INLINEset_or(ceil, ceil, p); + } + if (! setp_equal(ceil, cube.fullset)) { + free_cubelist(T); + return FALSE; + } + + /* Collect column counts, determine unate variables, etc. */ + massive_count(T); + + /* If function is unate (and no row of all 1's), then no tautology */ + if (cdata.vars_unate == cdata.vars_active) { + free_cubelist(T); + return FALSE; + + /* If active in a single variable (and no column of 0's) then tautology */ + } else if (cdata.vars_active == 1) { + free_cubelist(T); + return TRUE; + + /* Check for unate variables, and reduce cover if there are any */ + } else if (cdata.vars_unate != 0) { + /* Form a cube "ceil" with full variables in the unate variables */ + (void) set_copy(ceil, cube.emptyset); + for(var = 0; var < cube.num_vars; var++) { + if (cdata.is_unate[var]) { + INLINEset_or(ceil, ceil, cube.var_mask[var]); + } + } + + /* Save only those cubes that are "full" in all unate variables */ + for(Tsave = T1 = T+2; (p = *T1++) != 0; ) { + if (setp_implies(ceil, set_or(temp, p, T[0]))) { + *Tsave++ = p; + } + } + *Tsave++ = NULL; + T[1] = (pcube) Tsave; + + if (debug & TAUT) { + printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n", + cdata.vars_unate, CUBELISTSIZE(T)); + } + goto start; + + /* Check for component reduction */ + } else if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T) / 2) { + if (cubelist_partition(T, &A, &B, debug & TAUT) == 0) { + return MAYBE; + } else { + free_cubelist(T); + if (tautology(A)) { + free_cubelist(B); + return TRUE; + } else { + return tautology(B); + } + } + } + + /* We tried as hard as we could, but must recurse from here on */ + return MAYBE; +} + +/* fcube_is_covered -- determine exactly how a cubelist "covers" a cube */ +static void +fcube_is_covered(T, c, table) +pcube *T, c; +sm_matrix *table; +{ + ftautology(cofactor(T,c), table); +} + + +/* ftautology -- find ways to make a tautology */ +static void +ftautology(T, table) +pcube *T; /* T will be disposed of */ +sm_matrix *table; +{ + register pcube cl, cr; + register int best; + static int ftaut_level = 0; + + if (debug & TAUT) { + debug_print(T, "FIND_TAUTOLOGY", ftaut_level++); + } + + if (ftaut_special_cases(T, table) == MAYBE) { + cl = new_cube(); + cr = new_cube(); + best = binate_split_select(T, cl, cr, TAUT); + + ftautology(scofactor(T, cl, best), table); + ftautology(scofactor(T, cr, best), table); + + free_cubelist(T); + free_cube(cl); + free_cube(cr); + } + + if (debug & TAUT) { + (void) printf("exit FIND_TAUTOLOGY[%d]: table is %d by %d\n", + --ftaut_level, table->nrows, table->ncols); + } +} + +static bool +ftaut_special_cases(T, table) +pcube *T; /* will be disposed if answer is determined */ +sm_matrix *table; +{ + register pcube *T1, *Tsave, p, temp = cube.temp[0], ceil = cube.temp[1]; + int var, rownum; + + /* Check for a row of all 1's in the essential cubes */ + for(T1 = T+2; (p = *T1++) != 0; ) { + if (! TESTP(p, REDUND)) { + if (full_row(p, T[0])) { + /* subspace is covered by essentials -- no new rows for table */ + free_cubelist(T); + return TRUE; + } + } + } + + /* Collect column counts, determine unate variables, etc. */ +start: + massive_count(T); + + /* If function is unate, find the rows of all 1's */ + if (cdata.vars_unate == cdata.vars_active) { + /* find which nonessentials cover this subspace */ + rownum = table->last_row ? table->last_row->row_num+1 : 0; + (void) sm_insert(table, rownum, Rp_current); + for(T1 = T+2; (p = *T1++) != 0; ) { + if (TESTP(p, REDUND)) { + /* See if a redundant cube covers this leaf */ + if (full_row(p, T[0])) { + (void) sm_insert(table, rownum, (int) SIZE(p)); + } + } + } + free_cubelist(T); + return TRUE; + + /* Perform unate reduction if there are any unate variables */ + } else if (cdata.vars_unate != 0) { + /* Form a cube "ceil" with full variables in the unate variables */ + (void) set_copy(ceil, cube.emptyset); + for(var = 0; var < cube.num_vars; var++) { + if (cdata.is_unate[var]) { + INLINEset_or(ceil, ceil, cube.var_mask[var]); + } + } + + /* Save only those cubes that are "full" in all unate variables */ + for(Tsave = T1 = T+2; (p = *T1++) != 0; ) { + if (setp_implies(ceil, set_or(temp, p, T[0]))) { + *Tsave++ = p; + } + } + *Tsave++ = 0; + T[1] = (pcube) Tsave; + + if (debug & TAUT) { + printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n", + cdata.vars_unate, CUBELISTSIZE(T)); + } + goto start; + } + + /* Not much we can do about it */ + return MAYBE; +} diff --git a/abc70930/src/misc/espresso/main.c b/abc70930/src/misc/espresso/main.c new file mode 100644 index 00000000..0a511c0e --- /dev/null +++ b/abc70930/src/misc/espresso/main.c @@ -0,0 +1,746 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + * Main driver for espresso + * + * Old style -do xxx, -out xxx, etc. are still supported. + */ + +#include "espresso.h" +#include "main.h" /* table definitions for options */ + +static FILE *last_fp; +static int input_type = FD_type; + + +main(argc, argv) +int argc; +char *argv[]; +{ + int i, j, first, last, strategy, out_type, option; + pPLA PLA, PLA1; + pcover F, Fold, Dold; + pset last1, p; + cost_t cost; + bool error, exact_cover; + long start; + extern char *util_optarg; + extern int util_optind; + + start = ptime(); + + error = FALSE; + init_runtime(); +#ifdef RANDOM + srandom(314973); +#endif + + option = 0; /* default -D: ESPRESSO */ + out_type = F_type; /* default -o: default is ON-set only */ + debug = 0; /* default -d: no debugging info */ + verbose_debug = FALSE; /* default -v: not verbose */ + print_solution = TRUE; /* default -x: print the solution (!) */ + summary = FALSE; /* default -s: no summary */ + trace = FALSE; /* default -t: no trace information */ + strategy = 0; /* default -S: strategy number */ + first = -1; /* default -R: select range */ + last = -1; + remove_essential = TRUE; /* default -e: */ + force_irredundant = TRUE; + unwrap_onset = TRUE; + single_expand = FALSE; + pos = FALSE; + recompute_onset = FALSE; + use_super_gasp = FALSE; + use_random_order = FALSE; + kiss = FALSE; + echo_comments = TRUE; + echo_unknown_commands = TRUE; + exact_cover = FALSE; /* for -qm option, the default */ + + backward_compatibility_hack(&argc, argv, &option, &out_type); + + + /* parse command line options*/ + while ((i = util_getopt(argc, argv, "D:S:de:o:r:stv:x")) != EOF) { + switch(i) { + case 'D': /* -Dcommand invokes a subcommand */ + for(j = 0; option_table[j].name != 0; j++) { + if (strcmp(util_optarg, option_table[j].name) == 0) { + option = j; + break; + } + } + if (option_table[j].name == 0) { + (void) fprintf(stderr, "%s: bad subcommand \"%s\"\n", + argv[0], util_optarg); + exit(1); + } + break; + + case 'o': /* -ooutput selects and output option */ + for(j = 0; pla_types[j].key != 0; j++) { + if (strcmp(util_optarg, pla_types[j].key+1) == 0) { + out_type = pla_types[j].value; + break; + } + } + if (pla_types[j].key == 0) { + (void) fprintf(stderr, "%s: bad output type \"%s\"\n", + argv[0], util_optarg); + exit(1); + } + break; + + case 'e': /* -eespresso selects an option for espresso */ + for(j = 0; esp_opt_table[j].name != 0; j++) { + if (strcmp(util_optarg, esp_opt_table[j].name) == 0) { + *(esp_opt_table[j].variable) = esp_opt_table[j].value; + break; + } + } + if (esp_opt_table[j].name == 0) { + (void) fprintf(stderr, "%s: bad espresso option \"%s\"\n", + argv[0], util_optarg); + exit(1); + } + break; + + case 'd': /* -d turns on (softly) all debug switches */ + debug = debug_table[0].value; + trace = TRUE; + summary = TRUE; + break; + + case 'v': /* -vdebug invokes a debug option */ + verbose_debug = TRUE; + for(j = 0; debug_table[j].name != 0; j++) { + if (strcmp(util_optarg, debug_table[j].name) == 0) { + debug |= debug_table[j].value; + break; + } + } + if (debug_table[j].name == 0) { + (void) fprintf(stderr, "%s: bad debug type \"%s\"\n", + argv[0], util_optarg); + exit(1); + } + break; + + case 't': + trace = TRUE; + break; + + case 's': + summary = TRUE; + break; + + case 'x': /* -x suppress printing of results */ + print_solution = FALSE; + break; + + case 'S': /* -S sets a strategy for several cmds */ + strategy = atoi(util_optarg); + break; + + case 'r': /* -r selects range (outputs or vars) */ + if (sscanf(util_optarg, "%d-%d", &first, &last) < 2) { + (void) fprintf(stderr, "%s: bad output range \"%s\"\n", + argv[0], util_optarg); + exit(1); + } + break; + + default: + usage(); + exit(1); + } + } + + /* provide version information and summaries */ + if (summary || trace) { + /* echo command line and arguments */ + printf("#"); + for(i = 0; i < argc; i++) { + printf(" %s", argv[i]); + } + printf("\n"); + printf("# %s\n", VERSION); + } + + /* the remaining arguments are argv[util_optind ... argc-1] */ + PLA = PLA1 = NIL(PLA_t); + switch(option_table[option].num_plas) { + case 2: + if (util_optind+2 < argc) fatal("trailing arguments on command line"); + getPLA(util_optind++, argc, argv, option, &PLA, out_type); + getPLA(util_optind++, argc, argv, option, &PLA1, out_type); + break; + case 1: + if (util_optind+1 < argc) fatal("trailing arguments on command line"); + getPLA(util_optind++, argc, argv, option, &PLA, out_type); + break; + } + if (util_optind < argc) fatal("trailing arguments on command line"); + + if (summary || trace) { + if (PLA != NIL(PLA_t)) PLA_summary(PLA); + if (PLA1 != NIL(PLA_t)) PLA_summary(PLA1); + } + +/* + * Now a case-statement to decide what to do + */ + + switch(option_table[option].key) { + + +/******************** Espresso operations ********************/ + + case KEY_ESPRESSO: + Fold = sf_save(PLA->F); + PLA->F = espresso(PLA->F, PLA->D, PLA->R); + EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost); + if (error) { + print_solution = FALSE; + PLA->F = Fold; + (void) check_consistency(PLA); + } else { + free_cover(Fold); + } + break; + + case KEY_MANY_ESPRESSO: { + int pla_type; + do { + EXEC(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F); + if (print_solution) { + fprint_pla(stdout, PLA, out_type); + (void) fflush(stdout); + } + pla_type = PLA->pla_type; + free_PLA(PLA); + setdown_cube(); + FREE(cube.part_size); + } while (read_pla(last_fp, TRUE, TRUE, pla_type, &PLA) != EOF); + exit(0); + } + + case KEY_simplify: + EXEC(PLA->F = simplify(cube1list(PLA->F)), "SIMPLIFY ", PLA->F); + break; + + case KEY_so: /* minimize all functions as single-output */ + if (strategy < 0 || strategy > 1) { + strategy = 0; + } + so_espresso(PLA, strategy); + break; + + case KEY_so_both: /* minimize all functions as single-output */ + if (strategy < 0 || strategy > 1) { + strategy = 0; + } + so_both_espresso(PLA, strategy); + break; + + case KEY_expand: /* execute expand */ + EXECUTE(PLA->F=expand(PLA->F,PLA->R,FALSE),EXPAND_TIME, PLA->F, cost); + break; + + case KEY_irred: /* extract minimal irredundant subset */ + EXECUTE(PLA->F = irredundant(PLA->F, PLA->D), IRRED_TIME, PLA->F, cost); + break; + + case KEY_reduce: /* perform reduction */ + EXECUTE(PLA->F = reduce(PLA->F, PLA->D), REDUCE_TIME, PLA->F, cost); + break; + + case KEY_essen: /* check for essential primes */ + foreach_set(PLA->F, last1, p) { + SET(p, RELESSEN); + RESET(p, NONESSEN); + } + EXECUTE(F = essential(&(PLA->F), &(PLA->D)), ESSEN_TIME, PLA->F, cost); + free_cover(F); + break; + + case KEY_super_gasp: + PLA->F = super_gasp(PLA->F, PLA->D, PLA->R, &cost); + break; + + case KEY_gasp: + PLA->F = last_gasp(PLA->F, PLA->D, PLA->R, &cost); + break; + + case KEY_make_sparse: /* make_sparse step of Espresso */ + PLA->F = make_sparse(PLA->F, PLA->D, PLA->R); + break; + + case KEY_exact: + exact_cover = TRUE; + + case KEY_qm: + Fold = sf_save(PLA->F); + PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, exact_cover); + EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost); + if (error) { + print_solution = FALSE; + PLA->F = Fold; + (void) check_consistency(PLA); + } + free_cover(Fold); + break; + + case KEY_primes: /* generate all prime implicants */ + EXEC(PLA->F = primes_consensus(cube2list(PLA->F, PLA->D)), + "PRIMES ", PLA->F); + break; + + case KEY_map: /* print out a Karnaugh map of function */ + map(PLA->F); + print_solution = FALSE; + break; + + + +/******************** Output phase and bit pairing ********************/ + + case KEY_opo: /* sasao output phase assignment */ + phase_assignment(PLA, strategy); + break; + + case KEY_opoall: /* try all phase assignments (!) */ + if (first < 0 || first >= cube.part_size[cube.output]) { + first = 0; + } + if (last < 0 || last >= cube.part_size[cube.output]) { + last = cube.part_size[cube.output] - 1; + } + opoall(PLA, first, last, strategy); + break; + + case KEY_pair: /* find an optimal pairing */ + find_optimal_pairing(PLA, strategy); + break; + + case KEY_pairall: /* try all pairings !! */ + pair_all(PLA, strategy); + break; + + + +/******************** Simple cover operations ********************/ + + case KEY_echo: /* echo the PLA */ + break; + + case KEY_taut: /* tautology check */ + printf("ON-set is%sa tautology\n", + tautology(cube1list(PLA->F)) ? " " : " not "); + print_solution = FALSE; + break; + + case KEY_contain: /* single cube containment */ + PLA->F = sf_contain(PLA->F); + break; + + case KEY_intersect: /* cover intersection */ + PLA->F = cv_intersect(PLA->F, PLA1->F); + break; + + case KEY_union: /* cover union */ + PLA->F = sf_union(PLA->F, PLA1->F); + break; + + case KEY_disjoint: /* make cover disjoint */ + PLA->F = make_disjoint(PLA->F); + break; + + case KEY_dsharp: /* cover disjoint-sharp */ + PLA->F = cv_dsharp(PLA->F, PLA1->F); + break; + + case KEY_sharp: /* cover sharp */ + PLA->F = cv_sharp(PLA->F, PLA1->F); + break; + + case KEY_lexsort: /* lexical sort order */ + PLA->F = lex_sort(PLA->F); + break; + + case KEY_stats: /* print info on size */ + if (! summary) PLA_summary(PLA); + print_solution = FALSE; + break; + + case KEY_minterms: /* explode into minterms */ + if (first < 0 || first >= cube.num_vars) { + first = 0; + } + if (last < 0 || last >= cube.num_vars) { + last = cube.num_vars - 1; + } + PLA->F = sf_dupl(unravel_range(PLA->F, first, last)); + break; + + case KEY_d1merge: /* distance-1 merge */ + if (first < 0 || first >= cube.num_vars) { + first = 0; + } + if (last < 0 || last >= cube.num_vars) { + last = cube.num_vars - 1; + } + for(i = first; i <= last; i++) { + PLA->F = d1merge(PLA->F, i); + } + break; + + case KEY_d1merge_in: /* distance-1 merge inputs only */ + for(i = 0; i < cube.num_binary_vars; i++) { + PLA->F = d1merge(PLA->F, i); + } + break; + + case KEY_PLA_verify: /* check two PLAs for equivalence */ + EXECUTE(error = PLA_verify(PLA, PLA1), VERIFY_TIME, PLA->F, cost); + if (error) { + printf("PLA comparison failed; the PLA's are not equivalent\n"); + exit(1); + } else { + printf("PLA's compared equal\n"); + exit(0); + } + break; /* silly */ + + case KEY_verify: /* check two covers for equivalence */ + Fold = PLA->F; Dold = PLA->D; F = PLA1->F; + EXECUTE(error=verify(F, Fold, Dold), VERIFY_TIME, PLA->F, cost); + if (error) { + printf("PLA comparison failed; the PLA's are not equivalent\n"); + exit(1); + } else { + printf("PLA's compared equal\n"); + exit(0); + } + break; /* silly */ + + case KEY_check: /* check consistency */ + (void) check_consistency(PLA); + print_solution = FALSE; + break; + + case KEY_mapdc: /* compute don't care set */ + map_dcset(PLA); + out_type = FD_type; + break; + + case KEY_equiv: + find_equiv_outputs(PLA); + print_solution = FALSE; + break; + + case KEY_separate: /* remove PLA->D from PLA->F */ + PLA->F = complement(cube2list(PLA->D, PLA->R)); + break; + + case KEY_xor: { + pcover T1 = cv_intersect(PLA->F, PLA1->R); + pcover T2 = cv_intersect(PLA1->F, PLA->R); + free_cover(PLA->F); + PLA->F = sf_contain(sf_join(T1, T2)); + free_cover(T1); + free_cover(T2); + break; + } + + case KEY_fsm: { + disassemble_fsm(PLA, summary); + print_solution = FALSE; + break; + } + + case KEY_test: { + pcover T, E; + T = sf_join(PLA->D, PLA->R); + E = new_cover(10); + sf_free(PLA->F); + EXECUTE(PLA->F = complement(cube1list(T)), COMPL_TIME, PLA->F, cost); + EXECUTE(PLA->F = expand(PLA->F, T, FALSE), EXPAND_TIME, PLA->F, cost); + EXECUTE(PLA->F = irredundant(PLA->F, E), IRRED_TIME, PLA->F, cost); + sf_free(T); + T = sf_join(PLA->F, PLA->R); + EXECUTE(PLA->D = expand(PLA->D, T, FALSE), EXPAND_TIME, PLA->D, cost); + EXECUTE(PLA->D = irredundant(PLA->D, E), IRRED_TIME, PLA->D, cost); + sf_free(T); + sf_free(E); + break; + } + + + } + + /* Print a runtime summary if trace mode enabled */ + if (trace) { + runtime(); + } + + /* Print total runtime */ + if (summary || trace) { + print_trace(PLA->F, option_table[option].name, ptime()-start); + } + + /* Output the solution */ + if (print_solution) { + EXECUTE(fprint_pla(stdout, PLA, out_type), WRITE_TIME, PLA->F, cost); + } + + /* Crash and burn if there was a verify error */ + if (error) { + fatal("cover verification failed"); + } + + /* cleanup all used memory */ + free_PLA(PLA); + FREE(cube.part_size); + setdown_cube(); /* free the cube/cdata structure data */ + sf_cleanup(); /* free unused set structures */ + sm_cleanup(); /* sparse matrix cleanup */ + + exit(0); +} + + +getPLA(opt, argc, argv, option, PLA, out_type) +int opt; +int argc; +char *argv[]; +int option; +pPLA *PLA; +int out_type; +{ + FILE *fp; + int needs_dcset, needs_offset; + char *fname; + + if (opt >= argc) { + fp = stdin; + fname = "(stdin)"; + } else { + fname = argv[opt]; + if (strcmp(fname, "-") == 0) { + fp = stdin; + } else if ((fp = fopen(argv[opt], "r")) == NULL) { + (void) fprintf(stderr, "%s: Unable to open %s\n", argv[0], fname); + exit(1); + } + } + if (option_table[option].key == KEY_echo) { + needs_dcset = (out_type & D_type) != 0; + needs_offset = (out_type & R_type) != 0; + } else { + needs_dcset = option_table[option].needs_dcset; + needs_offset = option_table[option].needs_offset; + } + + if (read_pla(fp, needs_dcset, needs_offset, input_type, PLA) == EOF) { + (void) fprintf(stderr, "%s: Unable to find PLA on file %s\n", argv[0], fname); + exit(1); + } + (*PLA)->filename = util_strsav(fname); + filename = (*PLA)->filename; +/* (void) fclose(fp);*/ +/* hackto support -Dmany */ + last_fp = fp; +} + + +runtime() +{ + int i; + long total = 1, temp; + + for(i = 0; i < TIME_COUNT; i++) { + total += total_time[i]; + } + for(i = 0; i < TIME_COUNT; i++) { + if (total_calls[i] != 0) { + temp = 100 * total_time[i]; + printf("# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n", + total_name[i], total_calls[i], print_time(total_time[i]), + temp/total, (10 * (temp%total)) / total); + } + } +} + + +init_runtime() +{ + total_name[READ_TIME] = "READ "; + total_name[WRITE_TIME] = "WRITE "; + total_name[COMPL_TIME] = "COMPL "; + total_name[REDUCE_TIME] = "REDUCE "; + total_name[EXPAND_TIME] = "EXPAND "; + total_name[ESSEN_TIME] = "ESSEN "; + total_name[IRRED_TIME] = "IRRED "; + total_name[GREDUCE_TIME] = "REDUCE_GASP"; + total_name[GEXPAND_TIME] = "EXPAND_GASP"; + total_name[GIRRED_TIME] = "IRRED_GASP "; + total_name[MV_REDUCE_TIME] ="MV_REDUCE "; + total_name[RAISE_IN_TIME] = "RAISE_IN "; + total_name[VERIFY_TIME] = "VERIFY "; + total_name[PRIMES_TIME] = "PRIMES "; + total_name[MINCOV_TIME] = "MINCOV "; +} + + +subcommands() +{ + int i, col; + printf(" "); + col = 16; + for(i = 0; option_table[i].name != 0; i++) { + if ((col + strlen(option_table[i].name) + 1) > 76) { + printf(",\n "); + col = 16; + } else if (i != 0) { + printf(", "); + } + printf("%s", option_table[i].name); + col += strlen(option_table[i].name) + 2; + } + printf("\n"); +} + + +usage() +{ + printf("%s\n\n", VERSION); + printf("SYNOPSIS: espresso [options] [file]\n\n"); + printf(" -d Enable debugging\n"); + printf(" -e[opt] Select espresso option:\n"); + printf(" fast, ness, nirr, nunwrap, onset, pos, strong,\n"); + printf(" eat, eatdots, kiss, random\n"); + printf(" -o[type] Select output format:\n"); + printf(" f, fd, fr, fdr, pleasure, eqntott, kiss, cons\n"); + printf(" -rn-m Select range for subcommands:\n"); + printf(" d1merge: first and last variables (0 ... m-1)\n"); + printf(" minterms: first and last variables (0 ... m-1)\n"); + printf(" opoall: first and last outputs (0 ... m-1)\n"); + printf(" -s Provide short execution summary\n"); + printf(" -t Provide longer execution trace\n"); + printf(" -x Suppress printing of solution\n"); + printf(" -v[type] Verbose debugging detail (-v '' for all)\n"); + printf(" -D[cmd] Execute subcommand 'cmd':\n"); + subcommands(); + printf(" -Sn Select strategy for subcommands:\n"); + printf(" opo: bit2=exact bit1=repeated bit0=skip sparse\n"); + printf(" opoall: 0=minimize, 1=exact\n"); + printf(" pair: 0=algebraic, 1=strongd, 2=espresso, 3=exact\n"); + printf(" pairall: 0=minimize, 1=exact, 2=opo\n"); + printf(" so_espresso: 0=minimize, 1=exact\n"); + printf(" so_both: 0=minimize, 1=exact\n"); +} + +/* + * Hack for backward compatibility (ACK! ) + */ + +backward_compatibility_hack(argc, argv, option, out_type) +int *argc; +char **argv; +int *option; +int *out_type; +{ + int i, j; + + /* Scan the argument list for something to do (default is ESPRESSO) */ + *option = 0; + for(i = 1; i < (*argc)-1; i++) { + if (strcmp(argv[i], "-do") == 0) { + for(j = 0; option_table[j].name != 0; j++) + if (strcmp(argv[i+1], option_table[j].name) == 0) { + *option = j; + delete_arg(argc, argv, i+1); + delete_arg(argc, argv, i); + break; + } + if (option_table[j].name == 0) { + (void) fprintf(stderr, + "espresso: bad keyword \"%s\" following -do\n",argv[i+1]); + exit(1); + } + break; + } + } + + for(i = 1; i < (*argc)-1; i++) { + if (strcmp(argv[i], "-out") == 0) { + for(j = 0; pla_types[j].key != 0; j++) + if (strcmp(pla_types[j].key+1, argv[i+1]) == 0) { + *out_type = pla_types[j].value; + delete_arg(argc, argv, i+1); + delete_arg(argc, argv, i); + break; + } + if (pla_types[j].key == 0) { + (void) fprintf(stderr, + "espresso: bad keyword \"%s\" following -out\n",argv[i+1]); + exit(1); + } + break; + } + } + + for(i = 1; i < (*argc); i++) { + if (argv[i][0] == '-') { + for(j = 0; esp_opt_table[j].name != 0; j++) { + if (strcmp(argv[i]+1, esp_opt_table[j].name) == 0) { + delete_arg(argc, argv, i); + *(esp_opt_table[j].variable) = esp_opt_table[j].value; + break; + } + } + } + } + + if (check_arg(argc, argv, "-fdr")) input_type = FDR_type; + if (check_arg(argc, argv, "-fr")) input_type = FR_type; + if (check_arg(argc, argv, "-f")) input_type = F_type; +} + + +/* delete_arg -- delete an argument from the argument list */ +delete_arg(argc, argv, num) +int *argc, num; +register char *argv[]; +{ + register int i; + (*argc)--; + for(i = num; i < *argc; i++) { + argv[i] = argv[i+1]; + } +} + + +/* check_arg -- scan argv for an argument, and return TRUE if found */ +bool check_arg(argc, argv, s) +int *argc; +register char *argv[], *s; +{ + register int i; + for(i = 1; i < *argc; i++) { + if (strcmp(argv[i], s) == 0) { + delete_arg(argc, argv, i); + return TRUE; + } + } + return FALSE; +} diff --git a/abc70930/src/misc/espresso/main.h b/abc70930/src/misc/espresso/main.h new file mode 100644 index 00000000..00657f39 --- /dev/null +++ b/abc70930/src/misc/espresso/main.h @@ -0,0 +1,122 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +enum keys { + KEY_ESPRESSO, KEY_PLA_verify, KEY_check, KEY_contain, KEY_d1merge, + KEY_disjoint, KEY_dsharp, KEY_echo, KEY_essen, KEY_exact, KEY_expand, + KEY_gasp, KEY_intersect, KEY_irred, KEY_lexsort, KEY_make_sparse, + KEY_map, KEY_mapdc, KEY_minterms, KEY_opo, KEY_opoall, + KEY_pair, KEY_pairall, KEY_primes, KEY_qm, KEY_reduce, KEY_sharp, + KEY_simplify, KEY_so, KEY_so_both, KEY_stats, KEY_super_gasp, KEY_taut, + KEY_test, KEY_equiv, KEY_union, KEY_verify, KEY_MANY_ESPRESSO, + KEY_separate, KEY_xor, KEY_d1merge_in, KEY_fsm, + KEY_unknown +}; + +/* Lookup table for program options */ +struct { + char *name; + enum keys key; + int num_plas; + bool needs_offset; + bool needs_dcset; +} option_table [] = { + /* ways to minimize functions */ + "ESPRESSO", KEY_ESPRESSO, 1, TRUE, TRUE, /* must be first */ + "many", KEY_MANY_ESPRESSO, 1, TRUE, TRUE, + "exact", KEY_exact, 1, TRUE, TRUE, + "qm", KEY_qm, 1, TRUE, TRUE, + "single_output", KEY_so, 1, TRUE, TRUE, + "so", KEY_so, 1, TRUE, TRUE, + "so_both", KEY_so_both, 1, TRUE, TRUE, + "simplify", KEY_simplify, 1, FALSE, FALSE, + "echo", KEY_echo, 1, FALSE, FALSE, + + /* output phase assignment and assignment of inputs to two-bit decoders */ + "opo", KEY_opo, 1, TRUE, TRUE, + "opoall", KEY_opoall, 1, TRUE, TRUE, + "pair", KEY_pair, 1, TRUE, TRUE, + "pairall", KEY_pairall, 1, TRUE, TRUE, + + /* Ways to check covers */ + "check", KEY_check, 1, TRUE, TRUE, + "stats", KEY_stats, 1, FALSE, FALSE, + "verify", KEY_verify, 2, FALSE, TRUE, + "PLAverify", KEY_PLA_verify, 2, FALSE, TRUE, + + /* hacks */ + "equiv", KEY_equiv, 1, TRUE, TRUE, + "map", KEY_map, 1, FALSE, FALSE, + "mapdc", KEY_mapdc, 1, FALSE, FALSE, + "fsm", KEY_fsm, 1, FALSE, TRUE, + + /* the basic boolean operations on covers */ + "contain", KEY_contain, 1, FALSE, FALSE, + "d1merge", KEY_d1merge, 1, FALSE, FALSE, + "d1merge_in", KEY_d1merge_in, 1, FALSE, FALSE, + "disjoint", KEY_disjoint, 1, TRUE, FALSE, + "dsharp", KEY_dsharp, 2, FALSE, FALSE, + "intersect", KEY_intersect, 2, FALSE, FALSE, + "minterms", KEY_minterms, 1, FALSE, FALSE, + "primes", KEY_primes, 1, FALSE, TRUE, + "separate", KEY_separate, 1, TRUE, TRUE, + "sharp", KEY_sharp, 2, FALSE, FALSE, + "union", KEY_union, 2, FALSE, FALSE, + "xor", KEY_xor, 2, TRUE, TRUE, + + /* debugging only -- call each step of the espresso algorithm */ + "essen", KEY_essen, 1, FALSE, TRUE, + "expand", KEY_expand, 1, TRUE, FALSE, + "gasp", KEY_gasp, 1, TRUE, TRUE, + "irred", KEY_irred, 1, FALSE, TRUE, + "make_sparse", KEY_make_sparse, 1, TRUE, TRUE, + "reduce", KEY_reduce, 1, FALSE, TRUE, + "taut", KEY_taut, 1, FALSE, FALSE, + "super_gasp", KEY_super_gasp, 1, TRUE, TRUE, + "lexsort", KEY_lexsort, 1, FALSE, FALSE, + "test", KEY_test, 1, TRUE, TRUE, + 0, KEY_unknown, 0, FALSE, FALSE /* must be last */ +}; + + +struct { + char *name; + int value; +} debug_table[] = { + "", EXPAND + ESSEN + IRRED + REDUCE + SPARSE + GASP + SHARP + MINCOV, + "compl", COMPL, "essen", ESSEN, + "expand", EXPAND, "expand1", EXPAND1|EXPAND, + "irred", IRRED, "irred1", IRRED1|IRRED, + "reduce", REDUCE, "reduce1", REDUCE1|REDUCE, + "mincov", MINCOV, "mincov1", MINCOV1|MINCOV, + "sparse", SPARSE, "sharp", SHARP, + "taut", TAUT, "gasp", GASP, + "exact", EXACT, + 0, +}; + + +struct { + char *name; + int *variable; + int value; +} esp_opt_table[] = { + "eat", &echo_comments, FALSE, + "eatdots", &echo_unknown_commands, FALSE, + "fast", &single_expand, TRUE, + "kiss", &kiss, TRUE, + "ness", &remove_essential, FALSE, + "nirr", &force_irredundant, FALSE, + "nunwrap", &unwrap_onset, FALSE, + "onset", &recompute_onset, TRUE, + "pos", &pos, TRUE, + "random", &use_random_order, TRUE, + "strong", &use_super_gasp, TRUE, + 0, +}; diff --git a/abc70930/src/misc/espresso/map.c b/abc70930/src/misc/espresso/map.c new file mode 100644 index 00000000..5ccf264c --- /dev/null +++ b/abc70930/src/misc/espresso/map.c @@ -0,0 +1,115 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +static pcube Gcube; +static pset Gminterm; + +pset minterms(T) +pcover T; +{ + int size, var; + register pcube last; + + size = 1; + for(var = 0; var < cube.num_vars; var++) + size *= cube.part_size[var]; + Gminterm = set_new(size); + + foreach_set(T, last, Gcube) + explode(cube.num_vars-1, 0); + + return Gminterm; +} + + +void explode(var, z) +int var, z; +{ + int i, last = cube.last_part[var]; + for(i=cube.first_part[var], z *= cube.part_size[var]; i<=last; i++, z++) + if (is_in_set(Gcube, i)) + if (var == 0) + set_insert(Gminterm, z); + else + explode(var-1, z); +} + + +static int mapindex[16][16] = { + 0, 1, 3, 2, 16, 17, 19, 18, 80, 81, 83, 82, 64, 65, 67, 66, + 4, 5, 7, 6, 20, 21, 23, 22, 84, 85, 87, 86, 68, 69, 71, 70, + 12, 13, 15, 14, 28, 29, 31, 30, 92, 93, 95, 94, 76, 77, 79, 78, + 8, 9, 11, 10, 24, 25, 27, 26, 88, 89, 91, 90, 72, 73, 75, 74, + + 32, 33, 35, 34, 48, 49, 51, 50, 112,113,115,114, 96, 97, 99, 98, + 36, 37, 39, 38, 52, 53, 55, 54, 116,117,119,118, 100,101,103,102, + 44, 45, 47, 46, 60, 61, 63, 62, 124,125,127,126, 108,109,111,110, + 40, 41, 43, 42, 56, 57, 59, 58, 120,121,123,122, 104,105,107,106, + + + 160,161,163,162, 176,177,179,178, 240,241,243,242, 224,225,227,226, + 164,165,167,166, 180,181,183,182, 244,245,247,246, 228,229,231,230, + 172,173,175,174, 188,189,191,190, 252,253,255,254, 236,237,239,238, + 168,169,171,170, 184,185,187,186, 248,249,251,250, 232,233,235,234, + + 128,129,131,130, 144,145,147,146, 208,209,211,210, 192,193,195,194, + 132,133,135,134, 148,149,151,150, 212,213,215,214, 196,197,199,198, + 140,141,143,142, 156,157,159,158, 220,221,223,222, 204,205,207,206, + 136,137,139,138, 152,153,155,154, 216,217,219,218, 200,201,203,202 +}; + +#define POWER2(n) (1 << n) +void map(T) +pcover T; +{ + int j, k, l, other_input_offset, output_offset, outnum, ind; + int largest_input_ind, numout; + char c; + pset m; + bool some_output; + + m = minterms(T); + largest_input_ind = POWER2(cube.num_binary_vars); + numout = cube.part_size[cube.num_vars-1]; + + for(outnum = 0; outnum < numout; outnum++) { + output_offset = outnum * largest_input_ind; + printf("\n\nOutput space # %d\n", outnum); + for(l = 0; l <= MAX(cube.num_binary_vars - 8, 0); l++) { + other_input_offset = l * 256; + for(k = 0; k < 16; k++) { + some_output = FALSE; + for(j = 0; j < 16; j++) { + ind = mapindex[k][j] + other_input_offset; + if (ind < largest_input_ind) { + c = is_in_set(m, ind+output_offset) ? '1' : '.'; + putchar(c); + some_output = TRUE; + } + if ((j+1)%4 == 0) + putchar(' '); + if ((j+1)%8 == 0) + printf(" "); + } + if (some_output) + putchar('\n'); + if ((k+1)%4 == 0) { + if (k != 15 && mapindex[k+1][0] >= largest_input_ind) + break; + putchar('\n'); + } + if ((k+1)%8 == 0) + putchar('\n'); + } + } + } + set_free(m); +} diff --git a/abc70930/src/misc/espresso/matrix.c b/abc70930/src/misc/espresso/matrix.c new file mode 100644 index 00000000..747fe54f --- /dev/null +++ b/abc70930/src/misc/espresso/matrix.c @@ -0,0 +1,574 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +//#include "port.h" +#include "sparse_int.h" + +/* + * free-lists are only used if 'FAST_AND_LOOSE' is set; this is because + * we lose the debugging capability of libmm_t which trashes objects when + * they are free'd. However, FAST_AND_LOOSE is much faster if matrices + * are created and freed frequently. + */ + +#ifdef FAST_AND_LOOSE +sm_element *sm_element_freelist; +sm_row *sm_row_freelist; +sm_col *sm_col_freelist; +#endif + + +sm_matrix * +sm_alloc() +{ + register sm_matrix *A; + + A = ALLOC(sm_matrix, 1); + A->rows = NIL(sm_row *); + A->cols = NIL(sm_col *); + A->nrows = A->ncols = 0; + A->rows_size = A->cols_size = 0; + A->first_row = A->last_row = NIL(sm_row); + A->first_col = A->last_col = NIL(sm_col); + A->user_word = NIL(char); /* for our user ... */ + return A; +} + + +sm_matrix * +sm_alloc_size(row, col) +int row, col; +{ + register sm_matrix *A; + + A = sm_alloc(); + sm_resize(A, row, col); + return A; +} + + +void +sm_free(A) +sm_matrix *A; +{ +#ifdef FAST_AND_LOOSE + register sm_row *prow; + + if (A->first_row != 0) { + for(prow = A->first_row; prow != 0; prow = prow->next_row) { + /* add the elements to the free list of elements */ + prow->last_col->next_col = sm_element_freelist; + sm_element_freelist = prow->first_col; + } + + /* Add the linked list of rows to the row-free-list */ + A->last_row->next_row = sm_row_freelist; + sm_row_freelist = A->first_row; + + /* Add the linked list of cols to the col-free-list */ + A->last_col->next_col = sm_col_freelist; + sm_col_freelist = A->first_col; + } +#else + register sm_row *prow, *pnext_row; + register sm_col *pcol, *pnext_col; + + for(prow = A->first_row; prow != 0; prow = pnext_row) { + pnext_row = prow->next_row; + sm_row_free(prow); + } + for(pcol = A->first_col; pcol != 0; pcol = pnext_col) { + pnext_col = pcol->next_col; + pcol->first_row = pcol->last_row = NIL(sm_element); + sm_col_free(pcol); + } +#endif + + /* Free the arrays to map row/col numbers into pointers */ + FREE(A->rows); + FREE(A->cols); + FREE(A); +} + + +sm_matrix * +sm_dup(A) +sm_matrix *A; +{ + register sm_row *prow; + register sm_element *p; + register sm_matrix *B; + + B = sm_alloc(); + if (A->last_row != 0) { + sm_resize(B, A->last_row->row_num, A->last_col->col_num); + for(prow = A->first_row; prow != 0; prow = prow->next_row) { + for(p = prow->first_col; p != 0; p = p->next_col) { + (void) sm_insert(B, p->row_num, p->col_num); + } + } + } + return B; +} + + +void +sm_resize(A, row, col) +register sm_matrix *A; +int row, col; +{ + register int i, new_size; + + if (row >= A->rows_size) { + new_size = MAX(A->rows_size*2, row+1); + A->rows = REALLOC(sm_row *, A->rows, new_size); + for(i = A->rows_size; i < new_size; i++) { + A->rows[i] = NIL(sm_row); + } + A->rows_size = new_size; + } + + if (col >= A->cols_size) { + new_size = MAX(A->cols_size*2, col+1); + A->cols = REALLOC(sm_col *, A->cols, new_size); + for(i = A->cols_size; i < new_size; i++) { + A->cols[i] = NIL(sm_col); + } + A->cols_size = new_size; + } +} + + +/* + * insert -- insert a value into the matrix + */ +sm_element * +sm_insert(A, row, col) +register sm_matrix *A; +register int row, col; +{ + register sm_row *prow; + register sm_col *pcol; + register sm_element *element; + sm_element *save_element; + + if (row >= A->rows_size || col >= A->cols_size) { + sm_resize(A, row, col); + } + + prow = A->rows[row]; + if (prow == NIL(sm_row)) { + prow = A->rows[row] = sm_row_alloc(); + prow->row_num = row; + sorted_insert(sm_row, A->first_row, A->last_row, A->nrows, + next_row, prev_row, row_num, row, prow); + } + + pcol = A->cols[col]; + if (pcol == NIL(sm_col)) { + pcol = A->cols[col] = sm_col_alloc(); + pcol->col_num = col; + sorted_insert(sm_col, A->first_col, A->last_col, A->ncols, + next_col, prev_col, col_num, col, pcol); + } + + /* get a new item, save its address */ + sm_element_alloc(element); + save_element = element; + + /* insert it into the row list */ + sorted_insert(sm_element, prow->first_col, prow->last_col, + prow->length, next_col, prev_col, col_num, col, element); + + /* if it was used, also insert it into the column list */ + if (element == save_element) { + sorted_insert(sm_element, pcol->first_row, pcol->last_row, + pcol->length, next_row, prev_row, row_num, row, element); + } else { + /* otherwise, it was already in matrix -- free element we allocated */ + sm_element_free(save_element); + } + return element; +} + + +sm_element * +sm_find(A, rownum, colnum) +sm_matrix *A; +int rownum, colnum; +{ + sm_row *prow; + sm_col *pcol; + + prow = sm_get_row(A, rownum); + if (prow == NIL(sm_row)) { + return NIL(sm_element); + } else { + pcol = sm_get_col(A, colnum); + if (pcol == NIL(sm_col)) { + return NIL(sm_element); + } + if (prow->length < pcol->length) { + return sm_row_find(prow, colnum); + } else { + return sm_col_find(pcol, rownum); + } + } +} + + +void +sm_remove(A, rownum, colnum) +sm_matrix *A; +int rownum, colnum; +{ + sm_remove_element(A, sm_find(A, rownum, colnum)); +} + + + +void +sm_remove_element(A, p) +register sm_matrix *A; +register sm_element *p; +{ + register sm_row *prow; + register sm_col *pcol; + + if (p == 0) return; + + /* Unlink the element from its row */ + prow = sm_get_row(A, p->row_num); + dll_unlink(p, prow->first_col, prow->last_col, + next_col, prev_col, prow->length); + + /* if no more elements in the row, discard the row header */ + if (prow->first_col == NIL(sm_element)) { + sm_delrow(A, p->row_num); + } + + /* Unlink the element from its column */ + pcol = sm_get_col(A, p->col_num); + dll_unlink(p, pcol->first_row, pcol->last_row, + next_row, prev_row, pcol->length); + + /* if no more elements in the column, discard the column header */ + if (pcol->first_row == NIL(sm_element)) { + sm_delcol(A, p->col_num); + } + + sm_element_free(p); +} + +void +sm_delrow(A, i) +sm_matrix *A; +int i; +{ + register sm_element *p, *pnext; + sm_col *pcol; + sm_row *prow; + + prow = sm_get_row(A, i); + if (prow != NIL(sm_row)) { + /* walk across the row */ + for(p = prow->first_col; p != 0; p = pnext) { + pnext = p->next_col; + + /* unlink the item from the column (and delete it) */ + pcol = sm_get_col(A, p->col_num); + sm_col_remove_element(pcol, p); + + /* discard the column if it is now empty */ + if (pcol->first_row == NIL(sm_element)) { + sm_delcol(A, pcol->col_num); + } + } + + /* discard the row -- we already threw away the elements */ + A->rows[i] = NIL(sm_row); + dll_unlink(prow, A->first_row, A->last_row, + next_row, prev_row, A->nrows); + prow->first_col = prow->last_col = NIL(sm_element); + sm_row_free(prow); + } +} + +void +sm_delcol(A, i) +sm_matrix *A; +int i; +{ + register sm_element *p, *pnext; + sm_row *prow; + sm_col *pcol; + + pcol = sm_get_col(A, i); + if (pcol != NIL(sm_col)) { + /* walk down the column */ + for(p = pcol->first_row; p != 0; p = pnext) { + pnext = p->next_row; + + /* unlink the element from the row (and delete it) */ + prow = sm_get_row(A, p->row_num); + sm_row_remove_element(prow, p); + + /* discard the row if it is now empty */ + if (prow->first_col == NIL(sm_element)) { + sm_delrow(A, prow->row_num); + } + } + + /* discard the column -- we already threw away the elements */ + A->cols[i] = NIL(sm_col); + dll_unlink(pcol, A->first_col, A->last_col, + next_col, prev_col, A->ncols); + pcol->first_row = pcol->last_row = NIL(sm_element); + sm_col_free(pcol); + } +} + +void +sm_copy_row(dest, dest_row, prow) +register sm_matrix *dest; +int dest_row; +sm_row *prow; +{ + register sm_element *p; + + for(p = prow->first_col; p != 0; p = p->next_col) { + (void) sm_insert(dest, dest_row, p->col_num); + } +} + + +void +sm_copy_col(dest, dest_col, pcol) +register sm_matrix *dest; +int dest_col; +sm_col *pcol; +{ + register sm_element *p; + + for(p = pcol->first_row; p != 0; p = p->next_row) { + (void) sm_insert(dest, dest_col, p->row_num); + } +} + + +sm_row * +sm_longest_row(A) +sm_matrix *A; +{ + register sm_row *large_row, *prow; + register int max_length; + + max_length = 0; + large_row = NIL(sm_row); + for(prow = A->first_row; prow != 0; prow = prow->next_row) { + if (prow->length > max_length) { + max_length = prow->length; + large_row = prow; + } + } + return large_row; +} + + +sm_col * +sm_longest_col(A) +sm_matrix *A; +{ + register sm_col *large_col, *pcol; + register int max_length; + + max_length = 0; + large_col = NIL(sm_col); + for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { + if (pcol->length > max_length) { + max_length = pcol->length; + large_col = pcol; + } + } + return large_col; +} + +int +sm_num_elements(A) +sm_matrix *A; +{ + register sm_row *prow; + register int num; + + num = 0; + sm_foreach_row(A, prow) { + num += prow->length; + } + return num; +} + +int +sm_read(fp, A) +FILE *fp; +sm_matrix **A; +{ + int i, j, err; + + *A = sm_alloc(); + while (! feof(fp)) { + err = fscanf(fp, "%d %d", &i, &j); + if (err == EOF) { + return 1; + } else if (err != 2) { + return 0; + } + (void) sm_insert(*A, i, j); + } + return 1; +} + + +int +sm_read_compressed(fp, A) +FILE *fp; +sm_matrix **A; +{ + int i, j, k, nrows, ncols; + unsigned long x; + + *A = sm_alloc(); + if (fscanf(fp, "%d %d", &nrows, &ncols) != 2) { + return 0; + } + sm_resize(*A, nrows, ncols); + + for(i = 0; i < nrows; i++) { + if (fscanf(fp, "%lx", &x) != 1) { + return 0; + } + for(j = 0; j < ncols; j += 32) { + if (fscanf(fp, "%lx", &x) != 1) { + return 0; + } + for(k = j; x != 0; x >>= 1, k++) { + if (x & 1) { + (void) sm_insert(*A, i, k); + } + } + } + } + return 1; +} + + +void +sm_write(fp, A) +FILE *fp; +sm_matrix *A; +{ + register sm_row *prow; + register sm_element *p; + + for(prow = A->first_row; prow != 0; prow = prow->next_row) { + for(p = prow->first_col; p != 0; p = p->next_col) { + (void) fprintf(fp, "%d %d\n", p->row_num, p->col_num); + } + } +} + +void +sm_print(fp, A) +FILE *fp; +sm_matrix *A; +{ + register sm_row *prow; + register sm_col *pcol; + int c; + + if (A->last_col->col_num >= 100) { + (void) fprintf(fp, " "); + for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { + (void) fprintf(fp, "%d", (pcol->col_num / 100)%10); + } + putc('\n', fp); + } + + if (A->last_col->col_num >= 10) { + (void) fprintf(fp, " "); + for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { + (void) fprintf(fp, "%d", (pcol->col_num / 10)%10); + } + putc('\n', fp); + } + + (void) fprintf(fp, " "); + for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { + (void) fprintf(fp, "%d", pcol->col_num % 10); + } + putc('\n', fp); + + (void) fprintf(fp, " "); + for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { + (void) fprintf(fp, "-"); + } + putc('\n', fp); + + for(prow = A->first_row; prow != 0; prow = prow->next_row) { + (void) fprintf(fp, "%3d:", prow->row_num); + + for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { + c = sm_row_find(prow, pcol->col_num) ? '1' : '.'; + putc(c, fp); + } + putc('\n', fp); + } +} + + +void +sm_dump(A, s, max) +sm_matrix *A; +char *s; +int max; +{ + FILE *fp = stdout; + + (void) fprintf(fp, "%s %d rows by %d cols\n", s, A->nrows, A->ncols); + if (A->nrows < max) { + sm_print(fp, A); + } +} + +void +sm_cleanup() +{ +#ifdef FAST_AND_LOOSE + register sm_element *p, *pnext; + register sm_row *prow, *pnextrow; + register sm_col *pcol, *pnextcol; + + for(p = sm_element_freelist; p != 0; p = pnext) { + pnext = p->next_col; + FREE(p); + } + sm_element_freelist = 0; + + for(prow = sm_row_freelist; prow != 0; prow = pnextrow) { + pnextrow = prow->next_row; + FREE(prow); + } + sm_row_freelist = 0; + + for(pcol = sm_col_freelist; pcol != 0; pcol = pnextcol) { + pnextcol = pcol->next_col; + FREE(pcol); + } + sm_col_freelist = 0; +#endif +} diff --git a/abc70930/src/misc/espresso/mincov.c b/abc70930/src/misc/espresso/mincov.c new file mode 100644 index 00000000..ee18a3f1 --- /dev/null +++ b/abc70930/src/misc/espresso/mincov.c @@ -0,0 +1,378 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + +/* + * mincov.c + */ + +#define USE_GIMPEL +#define USE_INDEP_SET + +static int select_column(); +static void select_essential(); +static int verify_cover(); + +#define fail(why) {\ + (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\ + __FILE__, __LINE__, why);\ + (void) fflush(stdout);\ + abort();\ +} + +sm_row * +sm_minimum_cover(A, weight, heuristic, debug_level) +sm_matrix *A; +int *weight; +int heuristic; /* set to 1 for a heuristic covering */ +int debug_level; /* how deep in the recursion to provide info */ +{ + stats_t stats; + solution_t *best, *select; + sm_row *prow, *sol; + sm_col *pcol; + sm_matrix *dup_A; + int nelem, bound; + double sparsity; + + /* Avoid sillyness */ + if (A->nrows <= 0) { + return sm_row_alloc(); /* easy to cover */ + } + + /* Initialize debugging structure */ + stats.start_time = util_cpu_time(); + stats.debug = debug_level > 0; + stats.max_print_depth = debug_level; + stats.max_depth = -1; + stats.nodes = 0; + stats.component = stats.comp_count = 0; + stats.gimpel = stats.gimpel_count = 0; + stats.no_branching = heuristic != 0; + stats.lower_bound = -1; + + /* Check the matrix sparsity */ + nelem = 0; + sm_foreach_row(A, prow) { + nelem += prow->length; + } + sparsity = (double) nelem / (double) (A->nrows * A->ncols); + + /* Determine an upper bound on the solution */ + bound = 1; + sm_foreach_col(A, pcol) { + bound += WEIGHT(weight, pcol->col_num); + } + + /* Perform the covering */ + select = solution_alloc(); + dup_A = sm_dup(A); + best = sm_mincov(dup_A, select, weight, 0, bound, 0, &stats); + sm_free(dup_A); + solution_free(select); + + if (stats.debug) { + if (stats.no_branching) { + (void) printf("**** heuristic covering ...\n"); + (void) printf("lower bound = %d\n", stats.lower_bound); + } + (void) printf("matrix = %d by %d with %d elements (%4.3f%%)\n", + A->nrows, A->ncols, nelem, sparsity * 100.0); + (void) printf("cover size = %d elements\n", best->row->length); + (void) printf("cover cost = %d\n", best->cost); + (void) printf("time = %s\n", + util_print_time(util_cpu_time() - stats.start_time)); + (void) printf("components = %d\n", stats.comp_count); + (void) printf("gimpel = %d\n", stats.gimpel_count); + (void) printf("nodes = %d\n", stats.nodes); + (void) printf("max_depth = %d\n", stats.max_depth); + } + + sol = sm_row_dup(best->row); + if (! verify_cover(A, sol)) { + fail("mincov: internal error -- cover verification failed\n"); + } + solution_free(best); + return sol; +} + +/* + * Find the best cover for 'A' (given that 'select' already selected); + * + * - abort search if a solution cannot be found which beats 'bound' + * + * - if any solution meets 'lower_bound', then it is the optimum solution + * and can be returned without further work. + */ + +solution_t * +sm_mincov(A, select, weight, lb, bound, depth, stats) +sm_matrix *A; +solution_t *select; +int *weight; +int lb; +int bound; +int depth; +stats_t *stats; +{ + sm_matrix *A1, *A2, *L, *R; + sm_element *p; + solution_t *select1, *select2, *best, *best1, *best2, *indep; + int pick, lb_new, debug; + + /* Start out with some debugging information */ + stats->nodes++; + if (depth > stats->max_depth) stats->max_depth = depth; + debug = stats->debug && (depth <= stats->max_print_depth); + + /* Apply row dominance, column dominance, and select essentials */ + select_essential(A, select, weight, bound); + if (select->cost >= bound) { + return NIL(solution_t); + } + + /* See if gimpel's reduction technique applies ... */ +#ifdef USE_GIMPEL + if ( weight == NIL(int)) { /* hack until we fix it */ + if (gimpel_reduce(A, select, weight, lb, bound, depth, stats, &best)) { + return best; + } + } +#endif + +#ifdef USE_INDEP_SET + /* Determine bound from here to final solution using independent-set */ + indep = sm_maximal_independent_set(A, weight); + + /* make sure the lower bound is monotonically increasing */ + lb_new = MAX(select->cost + indep->cost, lb); + pick = select_column(A, weight, indep); + solution_free(indep); +#else + lb_new = select->cost + (A->nrows > 0); + pick = select_column(A, weight, NIL(solution_t)); +#endif + + if (depth == 0) { + stats->lower_bound = lb_new + stats->gimpel; + } + + if (debug) { + (void) printf("ABSMIN[%2d]%s", depth, stats->component ? "*" : " "); + (void) printf(" %3dx%3d sel=%3d bnd=%3d lb=%3d %12s ", + A->nrows, A->ncols, select->cost + stats->gimpel, + bound + stats->gimpel, lb_new + stats->gimpel, + util_print_time(util_cpu_time()-stats->start_time)); + } + + /* Check for bounding based on no better solution possible */ + if (lb_new >= bound) { + if (debug) (void) printf("bounded\n"); + best = NIL(solution_t); + + + /* Check for new best solution */ + } else if (A->nrows == 0) { + best = solution_dup(select); + if (debug) (void) printf("BEST\n"); + if (stats->debug && stats->component == 0) { + (void) printf("new 'best' solution %d at level %d (time is %s)\n", + best->cost + stats->gimpel, depth, + util_print_time(util_cpu_time() - stats->start_time)); + } + + + /* Check for a partition of the problem */ + } else if (sm_block_partition(A, &L, &R)) { + /* Make L the smaller problem */ + if (L->ncols > R->ncols) { + A1 = L; + L = R; + R = A1; + } + if (debug) (void) printf("comp %d %d\n", L->nrows, R->nrows); + stats->comp_count++; + + /* Solve problem for L */ + select1 = solution_alloc(); + stats->component++; + best1 = sm_mincov(L, select1, weight, 0, + bound-select->cost, depth+1, stats); + stats->component--; + solution_free(select1); + sm_free(L); + + /* Add best solution to the selected set */ + if (best1 == NIL(solution_t)) { + best = NIL(solution_t); + } else { + for(p = best1->row->first_col; p != 0; p = p->next_col) { + solution_add(select, weight, p->col_num); + } + solution_free(best1); + + /* recur for the remaining block */ + best = sm_mincov(R, select, weight, lb_new, bound, depth+1, stats); + } + sm_free(R); + + /* We've tried as hard as possible, but now we must split and recur */ + } else { + if (debug) (void) printf("pick=%d\n", pick); + + /* Assume we choose this column to be in the covering set */ + A1 = sm_dup(A); + select1 = solution_dup(select); + solution_accept(select1, A1, weight, pick); + best1 = sm_mincov(A1, select1, weight, lb_new, bound, depth+1, stats); + solution_free(select1); + sm_free(A1); + + /* Update the upper bound if we found a better solution */ + if (best1 != NIL(solution_t) && bound > best1->cost) { + bound = best1->cost; + } + + /* See if this is a heuristic covering (no branching) */ + if (stats->no_branching) { + return best1; + } + + /* Check for reaching lower bound -- if so, don't actually branch */ + if (best1 != NIL(solution_t) && best1->cost == lb_new) { + return best1; + } + + /* Now assume we cannot have that column */ + A2 = sm_dup(A); + select2 = solution_dup(select); + solution_reject(select2, A2, weight, pick); + best2 = sm_mincov(A2, select2, weight, lb_new, bound, depth+1, stats); + solution_free(select2); + sm_free(A2); + + best = solution_choose_best(best1, best2); + } + + return best; +} + +static int +select_column(A, weight, indep) +sm_matrix *A; +int *weight; +solution_t *indep; +{ + register sm_col *pcol; + register sm_row *prow, *indep_cols; + register sm_element *p, *p1; + double w, best; + int best_col; + + indep_cols = sm_row_alloc(); + if (indep != NIL(solution_t)) { + /* Find which columns are in the independent sets */ + for(p = indep->row->first_col; p != 0; p = p->next_col) { + prow = sm_get_row(A, p->col_num); + for(p1 = prow->first_col; p1 != 0; p1 = p1->next_col) { + (void) sm_row_insert(indep_cols, p1->col_num); + } + } + } else { + /* select out of all columns */ + sm_foreach_col(A, pcol) { + (void) sm_row_insert(indep_cols, pcol->col_num); + } + } + + /* Find the best column */ + best_col = -1; + best = -1; + + /* Consider only columns which are in some independent row */ + sm_foreach_row_element(indep_cols, p1) { + pcol = sm_get_col(A, p1->col_num); + + /* Compute the total 'value' of all things covered by the column */ + w = 0.0; + for(p = pcol->first_row; p != 0; p = p->next_row) { + prow = sm_get_row(A, p->row_num); + w += 1.0 / ((double) prow->length - 1.0); + } + + /* divide this by the relative cost of choosing this column */ + w = w / (double) WEIGHT(weight, pcol->col_num); + + /* maximize this ratio */ + if (w > best) { + best_col = pcol->col_num; + best = w; + } + } + + sm_row_free(indep_cols); + return best_col; +} + +static void +select_essential(A, select, weight, bound) +sm_matrix *A; +solution_t *select; +int *weight; +int bound; /* must beat this solution */ +{ + register sm_element *p; + register sm_row *prow, *essen; + int delcols, delrows, essen_count; + + do { + /* Check for dominated columns */ + delcols = sm_col_dominance(A, weight); + + /* Find the rows with only 1 element (the essentials) */ + essen = sm_row_alloc(); + sm_foreach_row(A, prow) { + if (prow->length == 1) { + (void) sm_row_insert(essen, prow->first_col->col_num); + } + } + + /* Select all of the elements */ + sm_foreach_row_element(essen, p) { + solution_accept(select, A, weight, p->col_num); + /* Make sure solution still looks good */ + if (select->cost >= bound) { + sm_row_free(essen); + return; + } + } + essen_count = essen->length; + sm_row_free(essen); + + /* Check for dominated rows */ + delrows = sm_row_dominance(A); + + } while (delcols > 0 || delrows > 0 || essen_count > 0); +} + +static int +verify_cover(A, cover) +sm_matrix *A; +sm_row *cover; +{ + sm_row *prow; + + sm_foreach_row(A, prow) { + if (! sm_row_intersects(prow, cover)) { + return 0; + } + } + return 1; +} diff --git a/abc70930/src/misc/espresso/mincov.h b/abc70930/src/misc/espresso/mincov.h new file mode 100644 index 00000000..95310774 --- /dev/null +++ b/abc70930/src/misc/espresso/mincov.h @@ -0,0 +1,11 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* exported */ +extern sm_row *sm_minimum_cover(); diff --git a/abc70930/src/misc/espresso/mincov_int.h b/abc70930/src/misc/espresso/mincov_int.h new file mode 100644 index 00000000..e81850f2 --- /dev/null +++ b/abc70930/src/misc/espresso/mincov_int.h @@ -0,0 +1,55 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +//#include "port.h" +//#include "utility.h" +#include "sparse.h" +#include "mincov.h" + +#include "util_hack.h" // added + + +typedef struct stats_struct stats_t; +struct stats_struct { + int debug; /* 1 if debugging is enabled */ + int max_print_depth; /* dump stats for levels up to this level */ + int max_depth; /* deepest the recursion has gone */ + int nodes; /* total nodes visited */ + int component; /* currently solving a component */ + int comp_count; /* number of components detected */ + int gimpel_count; /* number of times Gimpel reduction applied */ + int gimpel; /* currently inside Gimpel reduction */ + long start_time; /* cpu time when the covering started */ + int no_branching; + int lower_bound; +}; + + + +typedef struct solution_struct solution_t; +struct solution_struct { + sm_row *row; + int cost; +}; + + +extern solution_t *solution_alloc(); +extern void solution_free(); +extern solution_t *solution_dup(); +extern void solution_accept(); +extern void solution_reject(); +extern void solution_add(); +extern solution_t *solution_choose_best(); + +extern solution_t *sm_maximal_independent_set(); +extern solution_t *sm_mincov(); +extern int gimpel_reduce(); + + +#define WEIGHT(weight, col) (weight == NIL(int) ? 1 : weight[col]) diff --git a/abc70930/src/misc/espresso/module.make b/abc70930/src/misc/espresso/module.make new file mode 100644 index 00000000..53ce982a --- /dev/null +++ b/abc70930/src/misc/espresso/module.make @@ -0,0 +1,39 @@ +SRC += src/misc/espresso/cofactor.c \ + src/misc/espresso/cols.c \ + src/misc/espresso/compl.c \ + src/misc/espresso/contain.c \ + src/misc/espresso/cubehack.c \ + src/misc/espresso/cubestr.c \ + src/misc/espresso/cvrin.c \ + src/misc/espresso/cvrm.c \ + src/misc/espresso/cvrmisc.c \ + src/misc/espresso/cvrout.c \ + src/misc/espresso/dominate.c \ + src/misc/espresso/equiv.c \ + src/misc/espresso/espresso.c \ + src/misc/espresso/essen.c \ + src/misc/espresso/exact.c \ + src/misc/espresso/expand.c \ + src/misc/espresso/gasp.c \ + src/misc/espresso/gimpel.c \ + src/misc/espresso/globals.c \ + src/misc/espresso/hack.c \ + src/misc/espresso/indep.c \ + src/misc/espresso/irred.c \ + src/misc/espresso/map.c \ + src/misc/espresso/matrix.c \ + src/misc/espresso/mincov.c \ + src/misc/espresso/opo.c \ + src/misc/espresso/pair.c \ + src/misc/espresso/part.c \ + src/misc/espresso/primes.c \ + src/misc/espresso/reduce.c \ + src/misc/espresso/rows.c \ + src/misc/espresso/set.c \ + src/misc/espresso/setc.c \ + src/misc/espresso/sharp.c \ + src/misc/espresso/sminterf.c \ + src/misc/espresso/solution.c \ + src/misc/espresso/sparse.c \ + src/misc/espresso/unate.c \ + src/misc/espresso/verify.c diff --git a/abc70930/src/misc/espresso/opo.c b/abc70930/src/misc/espresso/opo.c new file mode 100644 index 00000000..8daa0771 --- /dev/null +++ b/abc70930/src/misc/espresso/opo.c @@ -0,0 +1,624 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +/* + * Phase assignment technique (T. Sasao): + * + * 1. create a function with 2*m outputs which implements the + * original function and its complement for each output + * + * 2. minimize this function + * + * 3. choose the minimum number of prime implicants from the + * result of step 2 which are needed to realize either a function + * or its complement for each output + * + * Step 3 is performed in a rather crude way -- by simply multiplying + * out a large expression of the form: + * + * I = (ab + cdef)(acd + bgh) ... + * + * which is a product of m expressions where each expression has two + * product terms -- one representing which primes are needed for the + * function, and one representing which primes are needed for the + * complement. The largest product term resulting shows which primes + * to keep to implement one function or the other for each output. + * For problems with many outputs, this may grind to a + * halt. + * + * Untried: form complement of I and use unate_complement ... + * + * I have unsuccessfully tried several modifications to the basic + * algorithm. The first is quite simple: use Sasao's technique, but + * only commit to a single output at a time (rather than all + * outputs). The goal would be that the later minimizations can "take + * into account" the partial assignment at each step. This is + * expensive (m+1 minimizations rather than 2), and the results are + * discouraging. + * + * The second modification is rather complicated. The result from the + * minimization in step 2 is guaranteed to be minimal. Hence, for + * each output, the set of primes with a 1 in that output are both + * necessary and sufficient to implement the function. Espresso + * achieves the minimality using the routine MAKE_SPARSE. The + * modification is to prevent MAKE_SPARSE from running. Hence, there + * are potentially many subsets of the set of primes with a 1 in a + * column which can be used to implement that output. We use + * IRREDUNDANT to enumerate all possible subsets and then proceed as + * before. + */ + +static int opo_no_make_sparse; +static int opo_repeated; +static int opo_exact; +static void minimize(); + +void phase_assignment(PLA, opo_strategy) +pPLA PLA; +int opo_strategy; +{ + opo_no_make_sparse = opo_strategy % 2; + skip_make_sparse = opo_no_make_sparse; + opo_repeated = (opo_strategy / 2) % 2; + opo_exact = (opo_strategy / 4) % 2; + + /* Determine a phase assignment */ + if (PLA->phase != NULL) { + FREE(PLA->phase); + } + + if (opo_repeated) { + PLA->phase = set_save(cube.fullset); + repeated_phase_assignment(PLA); + } else { + PLA->phase = find_phase(PLA, 0, (pcube) NULL); + } + + /* Now minimize with this assignment */ + skip_make_sparse = FALSE; + (void) set_phase(PLA); + minimize(PLA); +} + +/* + * repeated_phase_assignment -- an alternate strategy which commits + * to a single phase assignment a step at a time. Performs m + 1 + * minimizations ! + */ +void repeated_phase_assignment(PLA) +pPLA PLA; +{ + int i; + pcube phase; + + for(i = 0; i < cube.part_size[cube.output]; i++) { + + /* Find best assignment for all undecided outputs */ + phase = find_phase(PLA, i, PLA->phase); + + /* Commit for only a single output ... */ + if (! is_in_set(phase, cube.first_part[cube.output] + i)) { + set_remove(PLA->phase, cube.first_part[cube.output] + i); + } + + if (trace || summary) { + printf("\nOPO loop for output #%d\n", i); + printf("PLA->phase is %s\n", pc1(PLA->phase)); + printf("phase is %s\n", pc1(phase)); + } + set_free(phase); + } +} + + +/* + * find_phase -- find a phase assignment for the PLA for all outputs starting + * with output number first_output. + */ +pcube find_phase(PLA, first_output, phase1) +pPLA PLA; +int first_output; +pcube phase1; +{ + pcube phase; + pPLA PLA1; + + phase = set_save(cube.fullset); + + /* setup the double-phase characteristic function, resize the cube */ + PLA1 = new_PLA(); + PLA1->F = sf_save(PLA->F); + PLA1->R = sf_save(PLA->R); + PLA1->D = sf_save(PLA->D); + if (phase1 != NULL) { + PLA1->phase = set_save(phase1); + (void) set_phase(PLA1); + } + EXEC_S(output_phase_setup(PLA1, first_output), "OPO-SETUP ", PLA1->F); + + /* minimize the double-phase function */ + minimize(PLA1); + + /* set the proper phases according to what gives a minimum solution */ + EXEC_S(PLA1->F = opo(phase, PLA1->F, PLA1->D, PLA1->R, first_output), + "OPO ", PLA1->F); + free_PLA(PLA1); + + /* set the cube structure to reflect the old size */ + setdown_cube(); + cube.part_size[cube.output] -= + (cube.part_size[cube.output] - first_output) / 2; + cube_setup(); + + return phase; +} + +/* + * opo -- multiply the expression out to determine a minimum subset of + * primes. + */ + +/*ARGSUSED*/ +pcover opo(phase, T, D, R, first_output) +pcube phase; +pcover T, D, R; +int first_output; +{ + int offset, output, i, last_output, ind; + pset pdest, select, p, p1, last, last1, not_covered, tmp; + pset_family temp, T1, T2; + + /* must select all primes for outputs [0 .. first_output-1] */ + select = set_full(T->count); + for(output = 0; output < first_output; output++) { + ind = cube.first_part[cube.output] + output; + foreachi_set(T, i, p) { + if (is_in_set(p, ind)) { + set_remove(select, i); + } + } + } + + /* Recursively perform the intersections */ + offset = (cube.part_size[cube.output] - first_output) / 2; + last_output = first_output + offset - 1; + temp = opo_recur(T, D, select, offset, first_output, last_output); + + /* largest set is on top -- select primes which are inferred from it */ + pdest = temp->data; + T1 = new_cover(T->count); + foreachi_set(T, i, p) { + if (! is_in_set(pdest, i)) { + T1 = sf_addset(T1, p); + } + } + + set_free(select); + sf_free(temp); + + /* finding phases is difficult -- see which functions are not covered */ + T2 = complement(cube1list(T1)); + not_covered = new_cube(); + tmp = new_cube(); + foreach_set(T, last, p) { + foreach_set(T2, last1, p1) { + if (cdist0(p, p1)) { + (void) set_or(not_covered, not_covered, set_and(tmp, p, p1)); + } + } + } + free_cover(T); + free_cover(T2); + set_free(tmp); + + /* Now reflect the phase choice in a single cube */ + for(output = first_output; output <= last_output; output++) { + ind = cube.first_part[cube.output] + output; + if (is_in_set(not_covered, ind)) { + if (is_in_set(not_covered, ind + offset)) { + fatal("error in output phase assignment"); + } else { + set_remove(phase, ind); + } + } + } + set_free(not_covered); + return T1; +} + +pset_family opo_recur(T, D, select, offset, first, last) +pcover T, D; +pcube select; +int offset, first, last; +{ + static int level = 0; + int middle; + pset_family sl, sr, temp; + + level++; + if (first == last) { +#if 0 + if (opo_no_make_sparse) { + temp = form_cover_table(T, D, select, first, first + offset); + } else { + temp = opo_leaf(T, select, first, first + offset); + } +#else + temp = opo_leaf(T, select, first, first + offset); +#endif + } else { + middle = (first + last) / 2; + sl = opo_recur(T, D, select, offset, first, middle); + sr = opo_recur(T, D, select, offset, middle+1, last); + temp = unate_intersect(sl, sr, level == 1); + if (trace) { + printf("# OPO[%d]: %4d = %4d x %4d, time = %s\n", level - 1, + temp->count, sl->count, sr->count, print_time(ptime())); + (void) fflush(stdout); + } + free_cover(sl); + free_cover(sr); + } + level--; + return temp; +} + + +pset_family opo_leaf(T, select, out1, out2) +register pcover T; +pset select; +int out1, out2; +{ + register pset_family temp; + register pset p, pdest; + register int i; + + out1 += cube.first_part[cube.output]; + out2 += cube.first_part[cube.output]; + + /* Allocate space for the result */ + temp = sf_new(2, T->count); + + /* Find which primes are needed for the ON-set of this fct */ + pdest = GETSET(temp, temp->count++); + (void) set_copy(pdest, select); + foreachi_set(T, i, p) { + if (is_in_set(p, out1)) { + set_remove(pdest, i); + } + } + + /* Find which primes are needed for the OFF-set of this fct */ + pdest = GETSET(temp, temp->count++); + (void) set_copy(pdest, select); + foreachi_set(T, i, p) { + if (is_in_set(p, out2)) { + set_remove(pdest, i); + } + } + + return temp; +} + +#if 0 +pset_family form_cover_table(F, D, select, f, fbar) +pcover F, D; +pset select; +int f, fbar; /* indices of f and fbar in the output part */ +{ + register int i; + register pcube p; + pset_family f_table, fbar_table; + + /* setup required for fcube_is_covered */ + Rp_size = F->count; + Rp_start = set_new(Rp_size); + foreachi_set(F, i, p) { + PUTSIZE(p, i); + } + foreachi_set(D, i, p) { + RESET(p, REDUND); + } + + f_table = find_covers(F, D, select, f); + fbar_table = find_covers(F, D, select, fbar); + f_table = sf_append(f_table, fbar_table); + + set_free(Rp_start); + return f_table; +} + + +pset_family find_covers(F, D, select, n) +pcover F, D; +register pset select; +int n; +{ + register pset p, last, new; + pcover F1; + pcube *Flist; + pset_family f_table, table; + int i; + + n += cube.first_part[cube.output]; + + /* save cubes in this output, and remove the output variable */ + F1 = new_cover(F->count); + foreach_set(F, last, p) + if (is_in_set(p, n)) { + new = GETSET(F1, F1->count++); + set_or(new, p, cube.var_mask[cube.output]); + PUTSIZE(new, SIZE(p)); + SET(new, REDUND); + } + + /* Find ways (sop form) to fail to cover output indexed by n */ + Flist = cube2list(F1, D); + table = sf_new(10, Rp_size); + foreach_set(F1, last, p) { + set_fill(Rp_start, Rp_size); + set_remove(Rp_start, SIZE(p)); + table = sf_append(table, fcube_is_covered(Flist, p)); + RESET(p, REDUND); + } + set_fill(Rp_start, Rp_size); + foreach_set(table, last, p) { + set_diff(p, Rp_start, p); + } + + /* complement this to get possible ways to cover the function */ + for(i = 0; i < Rp_size; i++) { + if (! is_in_set(select, i)) { + p = set_new(Rp_size); + set_insert(p, i); + table = sf_addset(table, p); + set_free(p); + } + } + f_table = unate_compl(table); + + /* what a pain, but we need bitwise complement of this */ + set_fill(Rp_start, Rp_size); + foreach_set(f_table, last, p) { + set_diff(p, Rp_start, p); + } + + free_cubelist(Flist); + sf_free(F1); + return f_table; +} +#endif + +/* + * Take a PLA (ON-set, OFF-set and DC-set) and create the + * "double-phase characteristic function" which is merely a new + * function which has twice as many outputs and realizes both the + * function and the complement. + * + * The cube structure is assumed to represent the PLA upon entering. + * It will be modified to represent the double-phase function upon + * exit. + * + * Only the outputs numbered starting with "first_output" are + * duplicated in the output part + */ + +output_phase_setup(PLA, first_output) +INOUT pPLA PLA; +int first_output; +{ + pcover F, R, D; + pcube mask, mask1, last; + int first_part, offset; + bool save; + register pcube p, pr, pf; + register int i, last_part; + + if (cube.output == -1) + fatal("output_phase_setup: must have an output"); + + F = PLA->F; + D = PLA->D; + R = PLA->R; + first_part = cube.first_part[cube.output] + first_output; + last_part = cube.last_part[cube.output]; + offset = cube.part_size[cube.output] - first_output; + + /* Change the output size, setup the cube structure */ + setdown_cube(); + cube.part_size[cube.output] += offset; + cube_setup(); + + /* Create a mask to select that part of the cube which isn't changing */ + mask = set_save(cube.fullset); + for(i = first_part; i < cube.size; i++) + set_remove(mask, i); + mask1 = set_save(mask); + for(i = cube.first_part[cube.output]; i < first_part; i++) { + set_remove(mask1, i); + } + + PLA->F = new_cover(F->count + R->count); + PLA->R = new_cover(F->count + R->count); + PLA->D = new_cover(D->count); + + foreach_set(F, last, p) { + pf = GETSET(PLA->F, (PLA->F)->count++); + pr = GETSET(PLA->R, (PLA->R)->count++); + INLINEset_and(pf, mask, p); + INLINEset_and(pr, mask1, p); + for(i = first_part; i <= last_part; i++) + if (is_in_set(p, i)) + set_insert(pf, i); + save = FALSE; + for(i = first_part; i <= last_part; i++) + if (is_in_set(p, i)) + save = TRUE, set_insert(pr, i+offset); + if (! save) PLA->R->count--; + } + + foreach_set(R, last, p) { + pf = GETSET(PLA->F, (PLA->F)->count++); + pr = GETSET(PLA->R, (PLA->R)->count++); + INLINEset_and(pf, mask1, p); + INLINEset_and(pr, mask, p); + save = FALSE; + for(i = first_part; i <= last_part; i++) + if (is_in_set(p, i)) + save = TRUE, set_insert(pf, i+offset); + if (! save) PLA->F->count--; + for(i = first_part; i <= last_part; i++) + if (is_in_set(p, i)) + set_insert(pr, i); + } + + foreach_set(D, last, p) { + pf = GETSET(PLA->D, (PLA->D)->count++); + INLINEset_and(pf, mask, p); + for(i = first_part; i <= last_part; i++) + if (is_in_set(p, i)) { + set_insert(pf, i); + set_insert(pf, i+offset); + } + } + + free_cover(F); + free_cover(D); + free_cover(R); + set_free(mask); + set_free(mask1); +} + +/* + * set_phase -- given a "cube" which describes which phases of the output + * are to be implemented, compute the appropriate on-set and off-set + */ +pPLA set_phase(PLA) +INOUT pPLA PLA; +{ + pcover F1, R1; + register pcube last, p, outmask; + register pcube temp=cube.temp[0], phase=PLA->phase, phase1=cube.temp[1]; + + outmask = cube.var_mask[cube.num_vars - 1]; + set_diff(phase1, outmask, phase); + set_or(phase1, set_diff(temp, cube.fullset, outmask), phase1); + F1 = new_cover((PLA->F)->count + (PLA->R)->count); + R1 = new_cover((PLA->F)->count + (PLA->R)->count); + + foreach_set(PLA->F, last, p) { + if (! setp_disjoint(set_and(temp, p, phase), outmask)) + set_copy(GETSET(F1, F1->count++), temp); + if (! setp_disjoint(set_and(temp, p, phase1), outmask)) + set_copy(GETSET(R1, R1->count++), temp); + } + foreach_set(PLA->R, last, p) { + if (! setp_disjoint(set_and(temp, p, phase), outmask)) + set_copy(GETSET(R1, R1->count++), temp); + if (! setp_disjoint(set_and(temp, p, phase1), outmask)) + set_copy(GETSET(F1, F1->count++), temp); + } + free_cover(PLA->F); + free_cover(PLA->R); + PLA->F = F1; + PLA->R = R1; + return PLA; +} + +#define POW2(x) (1 << (x)) + +void opoall(PLA, first_output, last_output, opo_strategy) +pPLA PLA; +int first_output, last_output; +int opo_strategy; +{ + pcover F, D, R, best_F, best_D, best_R; + int i, j, ind, num; + pcube bestphase; + + opo_exact = opo_strategy; + + if (PLA->phase != NULL) { + set_free(PLA->phase); + } + + bestphase = set_save(cube.fullset); + best_F = sf_save(PLA->F); + best_D = sf_save(PLA->D); + best_R = sf_save(PLA->R); + + for(i = 0; i < POW2(last_output - first_output + 1); i++) { + + /* save the initial PLA covers */ + F = sf_save(PLA->F); + D = sf_save(PLA->D); + R = sf_save(PLA->R); + + /* compute the phase cube for this iteration */ + PLA->phase = set_save(cube.fullset); + num = i; + for(j = last_output; j >= first_output; j--) { + if (num % 2 == 0) { + ind = cube.first_part[cube.output] + j; + set_remove(PLA->phase, ind); + } + num /= 2; + } + + /* set the phase and minimize */ + (void) set_phase(PLA); + printf("# phase is %s\n", pc1(PLA->phase)); + summary = TRUE; + minimize(PLA); + + /* see if this is the best so far */ + if (PLA->F->count < best_F->count) { + /* save new best solution */ + set_copy(bestphase, PLA->phase); + sf_free(best_F); + sf_free(best_D); + sf_free(best_R); + best_F = PLA->F; + best_D = PLA->D; + best_R = PLA->R; + } else { + /* throw away the solution */ + free_cover(PLA->F); + free_cover(PLA->D); + free_cover(PLA->R); + } + set_free(PLA->phase); + + /* restore the initial PLA covers */ + PLA->F = F; + PLA->D = D; + PLA->R = R; + } + + /* one more minimization to restore the best answer */ + PLA->phase = bestphase; + sf_free(PLA->F); + sf_free(PLA->D); + sf_free(PLA->R); + PLA->F = best_F; + PLA->D = best_D; + PLA->R = best_R; +} + +static void minimize(PLA) +pPLA PLA; +{ + if (opo_exact) { + EXEC_S(PLA->F = minimize_exact(PLA->F,PLA->D,PLA->R,1), "EXACT", PLA->F); + } else { + EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), "ESPRESSO ",PLA->F); + } +} diff --git a/abc70930/src/misc/espresso/pair.c b/abc70930/src/misc/espresso/pair.c new file mode 100644 index 00000000..a8077176 --- /dev/null +++ b/abc70930/src/misc/espresso/pair.c @@ -0,0 +1,675 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +void set_pair(PLA) +pPLA PLA; +{ + set_pair1(PLA, TRUE); +} + +void set_pair1(PLA, adjust_labels) +pPLA PLA; +bool adjust_labels; +{ + int i, var, *paired, newvar; + int old_num_vars, old_num_binary_vars, old_size, old_mv_start; + int *new_part_size, new_num_vars, new_num_binary_vars, new_mv_start; + ppair pair = PLA->pair; + char scratch[1000], **oldlabel, *var1, *var1bar, *var2, *var2bar; + + if (adjust_labels) + makeup_labels(PLA); + + /* Check the pair structure for valid entries and see which binary + variables are left unpaired + */ + paired = ALLOC(bool, cube.num_binary_vars); + for(var = 0; var < cube.num_binary_vars; var++) + paired[var] = FALSE; + for(i = 0; i < pair->cnt; i++) + if ((pair->var1[i] > 0 && pair->var1[i] <= cube.num_binary_vars) && + (pair->var2[i] > 0 && pair->var2[i] <= cube.num_binary_vars)) { + paired[pair->var1[i]-1] = TRUE; + paired[pair->var2[i]-1] = TRUE; + } else + fatal("can only pair binary-valued variables"); + + PLA->F = delvar(pairvar(PLA->F, pair), paired); + PLA->R = delvar(pairvar(PLA->R, pair), paired); + PLA->D = delvar(pairvar(PLA->D, pair), paired); + + /* Now painfully adjust the cube size */ + old_size = cube.size; + old_num_vars = cube.num_vars; + old_num_binary_vars = cube.num_binary_vars; + old_mv_start = cube.first_part[cube.num_binary_vars]; + /* Create the new cube.part_size vector and setup the cube structure */ + new_num_binary_vars = 0; + for(var = 0; var < old_num_binary_vars; var++) + new_num_binary_vars += (paired[var] == FALSE); + new_num_vars = new_num_binary_vars + pair->cnt; + new_num_vars += old_num_vars - old_num_binary_vars; + new_part_size = ALLOC(int, new_num_vars); + for(var = 0; var < pair->cnt; var++) + new_part_size[new_num_binary_vars + var] = 4; + for(var = 0; var < old_num_vars - old_num_binary_vars; var++) + new_part_size[new_num_binary_vars + pair->cnt + var] = + cube.part_size[old_num_binary_vars + var]; + setdown_cube(); + FREE(cube.part_size); + cube.num_vars = new_num_vars; + cube.num_binary_vars = new_num_binary_vars; + cube.part_size = new_part_size; + cube_setup(); + + /* hack with the labels to get them correct */ + if (adjust_labels) { + oldlabel = PLA->label; + PLA->label = ALLOC(char *, cube.size); + for(var = 0; var < pair->cnt; var++) { + newvar = cube.num_binary_vars*2 + var*4; + var1 = oldlabel[ (pair->var1[var]-1) * 2 + 1]; + var2 = oldlabel[ (pair->var2[var]-1) * 2 + 1]; + var1bar = oldlabel[ (pair->var1[var]-1) * 2]; + var2bar = oldlabel[ (pair->var2[var]-1) * 2]; + (void) sprintf(scratch, "%s+%s", var1bar, var2bar); + PLA->label[newvar] = util_strsav(scratch); + (void) sprintf(scratch, "%s+%s", var1bar, var2); + PLA->label[newvar+1] = util_strsav(scratch); + (void) sprintf(scratch, "%s+%s", var1, var2bar); + PLA->label[newvar+2] = util_strsav(scratch); + (void) sprintf(scratch, "%s+%s", var1, var2); + PLA->label[newvar+3] = util_strsav(scratch); + } + /* Copy the old labels for the unpaired binary vars */ + i = 0; + for(var = 0; var < old_num_binary_vars; var++) { + if (paired[var] == FALSE) { + PLA->label[2*i] = oldlabel[2*var]; + PLA->label[2*i+1] = oldlabel[2*var+1]; + oldlabel[2*var] = oldlabel[2*var+1] = (char *) NULL; + i++; + } + } + /* Copy the old labels for the remaining unpaired vars */ + new_mv_start = cube.num_binary_vars*2 + pair->cnt*4; + for(i = old_mv_start; i < old_size; i++) { + PLA->label[new_mv_start + i - old_mv_start] = oldlabel[i]; + oldlabel[i] = (char *) NULL; + } + /* free remaining entries in oldlabel */ + for(i = 0; i < old_size; i++) + if (oldlabel[i] != (char *) NULL) + FREE(oldlabel[i]); + FREE(oldlabel); + } + + /* the paired variables should not be sparse (cf. mv_reduce/raise_in)*/ + for(var = 0; var < pair->cnt; var++) + cube.sparse[cube.num_binary_vars + var] = 0; + FREE(paired); +} + +pcover pairvar(A, pair) +pcover A; +ppair pair; +{ + register pcube last, p; + register int val, p1, p2, b1, b0; + int insert_col, pairnum; + + insert_col = cube.first_part[cube.num_vars - 1]; + + /* stretch the cover matrix to make room for the paired variables */ + A = sf_delcol(A, insert_col, -4*pair->cnt); + + /* compute the paired values */ + foreach_set(A, last, p) { + for(pairnum = 0; pairnum < pair->cnt; pairnum++) { + p1 = cube.first_part[pair->var1[pairnum] - 1]; + p2 = cube.first_part[pair->var2[pairnum] - 1]; + b1 = is_in_set(p, p2+1); + b0 = is_in_set(p, p2); + val = insert_col + pairnum * 4; + if (/* a0 */ is_in_set(p, p1)) { + if (b0) + set_insert(p, val + 3); + if (b1) + set_insert(p, val + 2); + } + if (/* a1 */ is_in_set(p, p1+1)) { + if (b0) + set_insert(p, val + 1); + if (b1) + set_insert(p, val); + } + } + } + return A; +} + + +/* delvar -- delete variables from A, minimize the number of column shifts */ +pcover delvar(A, paired) +pcover A; +bool paired[]; +{ + bool run; + int first_run, run_length, var, offset = 0; + + run = FALSE; run_length = 0; + for(var = 0; var < cube.num_binary_vars; var++) + if (paired[var]) + if (run) + run_length += cube.part_size[var]; + else { + run = TRUE; + first_run = cube.first_part[var]; + run_length = cube.part_size[var]; + } + else + if (run) { + A = sf_delcol(A, first_run-offset, run_length); + run = FALSE; + offset += run_length; + } + if (run) + A = sf_delcol(A, first_run-offset, run_length); + return A; +} + +/* + find_optimal_pairing -- find which binary variables should be paired + to maximally reduce the number of terms + + This is essentially the technique outlined by T. Sasao in the + Trans. on Comp., Oct 1984. We estimate the cost of pairing each + pair individually using 1 of 4 strategies: (1) algebraic division + of F by the pair (exactly T. Sasao technique); (2) strong division + of F by the paired variables (using REDUCE/EXPAND/ IRREDUNDANT from + espresso); (3) full minimization using espresso; (4) exact + minimization. These are in order of both increasing accuracy and + increasing difficulty (!) + + Once the n squared pairs have been evaluated, T. Sasao proposes a + graph covering of nodes by disjoint edges. For now, I solve this + problem exhaustively (complexity = (n-1)*(n-3)*...*3*1 for n + variables when n is even). Note that solving this problem exactly + is the same as evaluating the cost function for all possible + pairings. + + n pairs + + 1, 2 1 + 3, 4 3 + 5, 6 15 + 7, 8 105 + 9,10 945 + 11,12 10,395 + 13,14 135,135 + 15,16 2,027,025 + 17,18 34,459,425 + 19,20 654,729,075 +*/ +void find_optimal_pairing(PLA, strategy) +pPLA PLA; +int strategy; +{ + int i, j, **cost_array; + + cost_array = find_pairing_cost(PLA, strategy); + + if (summary) { + printf(" "); + for(i = 0; i < cube.num_binary_vars; i++) + printf("%3d ", i+1); + printf("\n"); + for(i = 0; i < cube.num_binary_vars; i++) { + printf("%3d ", i+1); + for(j = 0; j < cube.num_binary_vars; j++) + printf("%3d ", cost_array[i][j]); + printf("\n"); + } + } + + if (cube.num_binary_vars <= 14) { + PLA->pair = pair_best_cost(cost_array); + } else { + (void) greedy_best_cost(cost_array, &(PLA->pair)); + } + printf("# "); + print_pair(PLA->pair); + + for(i = 0; i < cube.num_binary_vars; i++) + FREE(cost_array[i]); + FREE(cost_array); + + set_pair(PLA); + EXEC_S(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F); +} + +int **find_pairing_cost(PLA, strategy) +pPLA PLA; +int strategy; +{ + int var1, var2, **cost_array; + int i, j, xnum_binary_vars, xnum_vars, *xpart_size, cost; + pcover T, Fsave, Dsave, Rsave; + pset mask; +/* char *s;*/ + + /* data is returned in the cost array */ + cost_array = ALLOC(int *, cube.num_binary_vars); + for(i = 0; i < cube.num_binary_vars; i++) + cost_array[i] = ALLOC(int, cube.num_binary_vars); + for(i = 0; i < cube.num_binary_vars; i++) + for(j = 0; j < cube.num_binary_vars; j++) + cost_array[i][j] = 0; + + /* Setup the pair structure for pairing variables together */ + PLA->pair = pair_new(1); + PLA->pair->cnt = 1; + + for(var1 = 0; var1 < cube.num_binary_vars-1; var1++) { + for(var2 = var1+1; var2 < cube.num_binary_vars; var2++) { + /* if anything but simple strategy, perform setup */ + if (strategy > 0) { + /* save the original covers */ + Fsave = sf_save(PLA->F); + Dsave = sf_save(PLA->D); + Rsave = sf_save(PLA->R); + + /* save the original cube structure */ + xnum_binary_vars = cube.num_binary_vars; + xnum_vars = cube.num_vars; + xpart_size = ALLOC(int, cube.num_vars); + for(i = 0; i < cube.num_vars; i++) + xpart_size[i] = cube.part_size[i]; + + /* pair two variables together */ + PLA->pair->var1[0] = var1 + 1; + PLA->pair->var2[0] = var2 + 1; + set_pair1(PLA, /* adjust_labels */ FALSE); + } + + + /* decide how to best estimate worth of this pairing */ + switch(strategy) { + case 3: + /*s = "exact minimization";*/ + PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1); + cost = Fsave->count - PLA->F->count; + break; + case 2: + /*s = "full minimization";*/ + PLA->F = espresso(PLA->F, PLA->D, PLA->R); + cost = Fsave->count - PLA->F->count; + break; + case 1: + /*s = "strong division";*/ + PLA->F = reduce(PLA->F, PLA->D); + PLA->F = expand(PLA->F, PLA->R, FALSE); + PLA->F = irredundant(PLA->F, PLA->D); + cost = Fsave->count - PLA->F->count; + break; + case 0: + /*s = "weak division";*/ + mask = new_cube(); + set_or(mask, cube.var_mask[var1], cube.var_mask[var2]); + T = dist_merge(sf_save(PLA->F), mask); + cost = PLA->F->count - T->count; + sf_free(T); + set_free(mask); + } + + cost_array[var1][var2] = cost; + + if (strategy > 0) { + /* restore the original cube structure -- free the new ones */ + setdown_cube(); + FREE(cube.part_size); + cube.num_binary_vars = xnum_binary_vars; + cube.num_vars = xnum_vars; + cube.part_size = xpart_size; + cube_setup(); + + /* restore the original cover(s) -- free the new ones */ + sf_free(PLA->F); + sf_free(PLA->D); + sf_free(PLA->R); + PLA->F = Fsave; + PLA->D = Dsave; + PLA->R = Rsave; + } + } + } + + pair_free(PLA->pair); + PLA->pair = NULL; + return cost_array; +} + +static int best_cost; +static int **cost_array; +static ppair best_pair; +static pset best_phase; +static pPLA global_PLA; +static pcover best_F, best_D, best_R; +static int pair_minim_strategy; + + +print_pair(pair) +ppair pair; +{ + int i; + + printf("pair is"); + for(i = 0; i < pair->cnt; i++) + printf (" (%d %d)", pair->var1[i], pair->var2[i]); + printf("\n"); +} + + +int greedy_best_cost(cost_array_local, pair_p) +int **cost_array_local; +ppair *pair_p; +{ + int i, j, besti, bestj, maxcost, total_cost; + pset cand; + ppair pair; + + pair = pair_new(cube.num_binary_vars); + cand = set_full(cube.num_binary_vars); + total_cost = 0; + + while (set_ord(cand) >= 2) { + maxcost = -1; + for(i = 0; i < cube.num_binary_vars; i++) { + if (is_in_set(cand, i)) { + for(j = i+1; j < cube.num_binary_vars; j++) { + if (is_in_set(cand, j)) { + if (cost_array_local[i][j] > maxcost) { + maxcost = cost_array_local[i][j]; + besti = i; + bestj = j; + } + } + } + } + } + pair->var1[pair->cnt] = besti+1; + pair->var2[pair->cnt] = bestj+1; + pair->cnt++; + set_remove(cand, besti); + set_remove(cand, bestj); + total_cost += maxcost; + } + set_free(cand); + *pair_p = pair; + return total_cost; +} + + +ppair pair_best_cost(cost_array_local) +int **cost_array_local; +{ + ppair pair; + pset candidate; + + best_cost = -1; + best_pair = NULL; + cost_array = cost_array_local; + + pair = pair_new(cube.num_binary_vars); + candidate = set_full(cube.num_binary_vars); + generate_all_pairs(pair, cube.num_binary_vars, candidate, find_best_cost); + pair_free(pair); + set_free(candidate); + return best_pair; +} + + +int find_best_cost(pair) +register ppair pair; +{ + register int i, cost; + + cost = 0; + for(i = 0; i < pair->cnt; i++) + cost += cost_array[pair->var1[i]-1][pair->var2[i]-1]; + if (cost > best_cost) { + best_cost = cost; + best_pair = pair_save(pair, pair->cnt); + } + if ((debug & MINCOV) && trace) { + printf("cost is %d ", cost); + print_pair(pair); + } +} + +/* + pair_all: brute-force approach to try all possible pairings + + pair_strategy is: + 2) for espresso + 3) for minimize_exact + 4) for phase assignment +*/ + +pair_all(PLA, pair_strategy) +pPLA PLA; +int pair_strategy; +{ + ppair pair; + pset candidate; + + global_PLA = PLA; + pair_minim_strategy = pair_strategy; + best_cost = PLA->F->count + 1; + best_pair = NULL; + best_phase = NULL; + best_F = best_D = best_R = NULL; + pair = pair_new(cube.num_binary_vars); + candidate = set_fill(set_new(cube.num_binary_vars), cube.num_binary_vars); + + generate_all_pairs(pair, cube.num_binary_vars, candidate, minimize_pair); + + pair_free(pair); + set_free(candidate); + + PLA->pair = best_pair; + PLA->phase = best_phase; +/* not really necessary + if (phase != NULL) + (void) set_phase(PLA->phase); +*/ + set_pair(PLA); + printf("# "); + print_pair(PLA->pair); + + sf_free(PLA->F); + sf_free(PLA->D); + sf_free(PLA->R); + PLA->F = best_F; + PLA->D = best_D; + PLA->R = best_R; +} + + +/* + * minimize_pair -- called as each pair is generated + */ +int minimize_pair(pair) +ppair pair; +{ + pcover Fsave, Dsave, Rsave; + int i, xnum_binary_vars, xnum_vars, *xpart_size; + + /* save the original covers */ + Fsave = sf_save(global_PLA->F); + Dsave = sf_save(global_PLA->D); + Rsave = sf_save(global_PLA->R); + + /* save the original cube structure */ + xnum_binary_vars = cube.num_binary_vars; + xnum_vars = cube.num_vars; + xpart_size = ALLOC(int, cube.num_vars); + for(i = 0; i < cube.num_vars; i++) + xpart_size[i] = cube.part_size[i]; + + /* setup the paired variables */ + global_PLA->pair = pair; + set_pair1(global_PLA, /* adjust_labels */ FALSE); + + /* call the minimizer */ + if (summary) + print_pair(pair); + switch(pair_minim_strategy) { + case 2: + EXEC_S(phase_assignment(global_PLA,0), "OPO ", global_PLA->F); + if (summary) + printf("# phase is %s\n", pc1(global_PLA->phase)); + break; + case 1: + EXEC_S(global_PLA->F = minimize_exact(global_PLA->F, global_PLA->D, + global_PLA->R, 1), "EXACT ", global_PLA->F); + break; + case 0: + EXEC_S(global_PLA->F = espresso(global_PLA->F, global_PLA->D, + global_PLA->R), "ESPRESSO ", global_PLA->F); + break; + default: + break; + } + + /* see if we have a new best solution */ + if (global_PLA->F->count < best_cost) { + best_cost = global_PLA->F->count; + best_pair = pair_save(pair, pair->cnt); + best_phase = global_PLA->phase!=NULL?set_save(global_PLA->phase):NULL; + if (best_F != NULL) sf_free(best_F); + if (best_D != NULL) sf_free(best_D); + if (best_R != NULL) sf_free(best_R); + best_F = sf_save(global_PLA->F); + best_D = sf_save(global_PLA->D); + best_R = sf_save(global_PLA->R); + } + + /* restore the original cube structure -- free the new ones */ + setdown_cube(); + FREE(cube.part_size); + cube.num_binary_vars = xnum_binary_vars; + cube.num_vars = xnum_vars; + cube.part_size = xpart_size; + cube_setup(); + + /* restore the original cover(s) -- free the new ones */ + sf_free(global_PLA->F); + sf_free(global_PLA->D); + sf_free(global_PLA->R); + global_PLA->F = Fsave; + global_PLA->D = Dsave; + global_PLA->R = Rsave; + global_PLA->pair = NULL; + global_PLA->phase = NULL; +} + +generate_all_pairs(pair, n, candidate, action) +ppair pair; +int n; +pset candidate; +int (*action)(); +{ + int i, j; + pset recur_candidate; + ppair recur_pair; + + if (set_ord(candidate) < 2) { + (*action)(pair); + return; + } + + recur_pair = pair_save(pair, n); + recur_candidate = set_save(candidate); + + /* Find first variable still in the candidate set */ + for(i = 0; i < n; i++) + if (is_in_set(candidate, i)) + break; + + /* Try all pairs of i with other variables */ + for(j = i+1; j < n; j++) + if (is_in_set(candidate, j)) { + /* pair (i j) -- remove from candidate set for future pairings */ + set_remove(recur_candidate, i); + set_remove(recur_candidate, j); + + /* add to the pair array */ + recur_pair->var1[recur_pair->cnt] = i+1; + recur_pair->var2[recur_pair->cnt] = j+1; + recur_pair->cnt++; + + /* recur looking for the end ... */ + generate_all_pairs(recur_pair, n, recur_candidate, action); + + /* now break this pair, and restore candidate set */ + recur_pair->cnt--; + set_insert(recur_candidate, i); + set_insert(recur_candidate, j); + } + + /* if odd, generate all pairs which do NOT include i */ + if ((set_ord(candidate) % 2) == 1) { + set_remove(recur_candidate, i); + generate_all_pairs(recur_pair, n, recur_candidate, action); + } + + pair_free(recur_pair); + set_free(recur_candidate); +} + +ppair pair_new(n) +register int n; +{ + register ppair pair1; + + pair1 = ALLOC(pair_t, 1); + pair1->cnt = 0; + pair1->var1 = ALLOC(int, n); + pair1->var2 = ALLOC(int, n); + return pair1; +} + + +ppair pair_save(pair, n) +register ppair pair; +register int n; +{ + register int k; + register ppair pair1; + + pair1 = pair_new(n); + pair1->cnt = pair->cnt; + for(k = 0; k < pair->cnt; k++) { + pair1->var1[k] = pair->var1[k]; + pair1->var2[k] = pair->var2[k]; + } + return pair1; +} + + +int pair_free(pair) +register ppair pair; +{ + FREE(pair->var1); + FREE(pair->var2); + FREE(pair); +} diff --git a/abc70930/src/misc/espresso/part.c b/abc70930/src/misc/espresso/part.c new file mode 100644 index 00000000..42843aeb --- /dev/null +++ b/abc70930/src/misc/espresso/part.c @@ -0,0 +1,122 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + +static int visit_col(); + +static void +copy_row(A, prow) +register sm_matrix *A; +register sm_row *prow; +{ + register sm_element *p; + + for(p = prow->first_col; p != 0; p = p->next_col) { + (void) sm_insert(A, p->row_num, p->col_num); + } +} + + +static int +visit_row(A, prow, rows_visited, cols_visited) +sm_matrix *A; +sm_row *prow; +int *rows_visited; +int *cols_visited; +{ + sm_element *p; + sm_col *pcol; + + if (! prow->flag) { + prow->flag = 1; + (*rows_visited)++; + if (*rows_visited == A->nrows) { + return 1; + } + for(p = prow->first_col; p != 0; p = p->next_col) { + pcol = sm_get_col(A, p->col_num); + if (! pcol->flag) { + if (visit_col(A, pcol, rows_visited, cols_visited)) { + return 1; + } + } + } + } + return 0; +} + + +static int +visit_col(A, pcol, rows_visited, cols_visited) +sm_matrix *A; +sm_col *pcol; +int *rows_visited; +int *cols_visited; +{ + sm_element *p; + sm_row *prow; + + if (! pcol->flag) { + pcol->flag = 1; + (*cols_visited)++; + if (*cols_visited == A->ncols) { + return 1; + } + for(p = pcol->first_row; p != 0; p = p->next_row) { + prow = sm_get_row(A, p->row_num); + if (! prow->flag) { + if (visit_row(A, prow, rows_visited, cols_visited)) { + return 1; + } + } + } + } + return 0; +} + +int +sm_block_partition(A, L, R) +sm_matrix *A; +sm_matrix **L, **R; +{ + int cols_visited, rows_visited; + register sm_row *prow; + register sm_col *pcol; + + /* Avoid the trivial case */ + if (A->nrows == 0) { + return 0; + } + + /* Reset the visited flags for each row and column */ + for(prow = A->first_row; prow != 0; prow = prow->next_row) { + prow->flag = 0; + } + for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { + pcol->flag = 0; + } + + cols_visited = rows_visited = 0; + if (visit_row(A, A->first_row, &rows_visited, &cols_visited)) { + /* we found all of the rows */ + return 0; + } else { + *L = sm_alloc(); + *R = sm_alloc(); + for(prow = A->first_row; prow != 0; prow = prow->next_row) { + if (prow->flag) { + copy_row(*L, prow); + } else { + copy_row(*R, prow); + } + } + return 1; + } +} diff --git a/abc70930/src/misc/espresso/primes.c b/abc70930/src/misc/espresso/primes.c new file mode 100644 index 00000000..3e40da27 --- /dev/null +++ b/abc70930/src/misc/espresso/primes.c @@ -0,0 +1,170 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + +static bool primes_consensus_special_cases(); +static pcover primes_consensus_merge(); +static pcover and_with_cofactor(); + + +/* primes_consensus -- generate primes using consensus */ +pcover primes_consensus(T) +pcube *T; /* T will be disposed of */ +{ + register pcube cl, cr; + register int best; + pcover Tnew, Tl, Tr; + + if (primes_consensus_special_cases(T, &Tnew) == MAYBE) { + cl = new_cube(); + cr = new_cube(); + best = binate_split_select(T, cl, cr, COMPL); + + Tl = primes_consensus(scofactor(T, cl, best)); + Tr = primes_consensus(scofactor(T, cr, best)); + Tnew = primes_consensus_merge(Tl, Tr, cl, cr); + + free_cube(cl); + free_cube(cr); + free_cubelist(T); + } + + return Tnew; +} + +static bool +primes_consensus_special_cases(T, Tnew) +pcube *T; /* will be disposed if answer is determined */ +pcover *Tnew; /* returned only if answer determined */ +{ + register pcube *T1, p, ceil, cof=T[0]; + pcube last; + pcover A; + + /* Check for no cubes in the cover */ + if (T[2] == NULL) { + *Tnew = new_cover(0); + free_cubelist(T); + return TRUE; + } + + /* Check for only a single cube in the cover */ + if (T[3] == NULL) { + *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2])); + free_cubelist(T); + return TRUE; + } + + /* Check for a row of all 1's (implies function is a tautology) */ + for(T1 = T+2; (p = *T1++) != NULL; ) { + if (full_row(p, cof)) { + *Tnew = sf_addset(new_cover(1), cube.fullset); + free_cubelist(T); + return TRUE; + } + } + + /* Check for a column of all 0's which can be factored out */ + ceil = set_save(cof); + for(T1 = T+2; (p = *T1++) != NULL; ) { + INLINEset_or(ceil, ceil, p); + } + if (! setp_equal(ceil, cube.fullset)) { + p = new_cube(); + (void) set_diff(p, cube.fullset, ceil); + (void) set_or(cof, cof, p); + free_cube(p); + + A = primes_consensus(T); + foreach_set(A, last, p) { + INLINEset_and(p, p, ceil); + } + *Tnew = A; + set_free(ceil); + return TRUE; + } + set_free(ceil); + + /* Collect column counts, determine unate variables, etc. */ + massive_count(T); + + /* If single active variable not factored out above, then tautology ! */ + if (cdata.vars_active == 1) { + *Tnew = sf_addset(new_cover(1), cube.fullset); + free_cubelist(T); + return TRUE; + + /* Check for unate cover */ + } else if (cdata.vars_unate == cdata.vars_active) { + A = cubeunlist(T); + *Tnew = sf_contain(A); + free_cubelist(T); + return TRUE; + + /* Not much we can do about it */ + } else { + return MAYBE; + } +} + +static pcover +primes_consensus_merge(Tl, Tr, cl, cr) +pcover Tl, Tr; +pcube cl, cr; +{ + register pcube pl, pr, lastl, lastr, pt; + pcover T, Tsave; + + Tl = and_with_cofactor(Tl, cl); + Tr = and_with_cofactor(Tr, cr); + + T = sf_new(500, Tl->sf_size); + pt = T->data; + Tsave = sf_contain(sf_join(Tl, Tr)); + + foreach_set(Tl, lastl, pl) { + foreach_set(Tr, lastr, pr) { + if (cdist01(pl, pr) == 1) { + consensus(pt, pl, pr); + if (++T->count >= T->capacity) { + Tsave = sf_union(Tsave, sf_contain(T)); + T = sf_new(500, Tl->sf_size); + pt = T->data; + } else { + pt += T->wsize; + } + } + } + } + free_cover(Tl); + free_cover(Tr); + + Tsave = sf_union(Tsave, sf_contain(T)); + return Tsave; +} + + +static pcover +and_with_cofactor(A, cof) +pset_family A; +register pset cof; +{ + register pset last, p; + + foreach_set(A, last, p) { + INLINEset_and(p, p, cof); + if (cdist(p, cube.fullset) > 0) { + RESET(p, ACTIVE); + } else { + SET(p, ACTIVE); + } + } + return sf_inactive(A); +} diff --git a/abc70930/src/misc/espresso/reduce.c b/abc70930/src/misc/espresso/reduce.c new file mode 100644 index 00000000..00e4507f --- /dev/null +++ b/abc70930/src/misc/espresso/reduce.c @@ -0,0 +1,258 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + module: reduce.c + purpose: Perform the Espresso-II reduction step + + Reduction is a technique used to explore larger regions of the + optimization space. We replace each cube of F with a smaller + cube while still maintaining a cover of the same logic function. +*/ + +#include "espresso.h" + +static bool toggle = TRUE; + + +/* + reduce -- replace each cube in F with its reduction + + The reduction of a cube is the smallest cube contained in the cube + which can replace the cube in the original cover without changing + the cover. This is equivalent to the super cube of all of the + essential points in the cube. This can be computed directly. + + The problem is that the order in which the cubes are reduced can + greatly affect the final result. We alternate between two ordering + strategies: + + (1) Order the cubes in ascending order of distance from the + largest cube breaking ties by ordering cubes of equal distance + in descending order of size (sort_reduce) + + (2) Order the cubes in descending order of the inner-product of + the cube and the column sums (mini_sort) + + The real workhorse of this section is the routine SCCC which is + used to find the Smallest Cube Containing the Complement of a cover. + Reduction as proposed by Espresso-II takes a cube and computes its + maximal reduction as the intersection between the cube and the + smallest cube containing the complement of (F u D - {c}) cofactored + against c. + + As usual, the unate-recursive paradigm is used to compute SCCC. + The SCCC of a unate cover is trivial to compute, and thus we perform + Shannon Cofactor expansion attempting to drive the cover to be unate + as fast as possible. +*/ + +pcover reduce(F, D) +INOUT pcover F; +IN pcover D; +{ + register pcube last, p, cunder, *FD; + + /* Order the cubes */ + if (use_random_order) + F = random_order(F); + else { + F = toggle ? sort_reduce(F) : mini_sort(F, descend); + toggle = ! toggle; + } + + /* Try to reduce each cube */ + FD = cube2list(F, D); + foreach_set(F, last, p) { + cunder = reduce_cube(FD, p); /* reduce the cube */ + if (setp_equal(cunder, p)) { /* see if it actually did */ + SET(p, ACTIVE); /* cube remains active */ + SET(p, PRIME); /* cube remains prime ? */ + } else { + if (debug & REDUCE) { + printf("REDUCE: %s to %s %s\n", + pc1(p), pc2(cunder), print_time(ptime())); + } + set_copy(p, cunder); /* save reduced version */ + RESET(p, PRIME); /* cube is no longer prime */ + if (setp_empty(cunder)) + RESET(p, ACTIVE); /* if null, kill the cube */ + else + SET(p, ACTIVE); /* cube is active */ + } + free_cube(cunder); + } + free_cubelist(FD); + + /* Delete any cubes of F which reduced to the empty cube */ + return sf_inactive(F); +} + +/* reduce_cube -- find the maximal reduction of a cube */ +pcube reduce_cube(FD, p) +IN pcube *FD, p; +{ + pcube cunder; + + cunder = sccc(cofactor(FD, p)); + return set_and(cunder, cunder, p); +} + + +/* sccc -- find Smallest Cube Containing the Complement of a cover */ +pcube sccc(T) +INOUT pcube *T; /* T will be disposed of */ +{ + pcube r; + register pcube cl, cr; + register int best; + static int sccc_level = 0; + + if (debug & REDUCE1) { + debug_print(T, "SCCC", sccc_level++); + } + + if (sccc_special_cases(T, &r) == MAYBE) { + cl = new_cube(); + cr = new_cube(); + best = binate_split_select(T, cl, cr, REDUCE1); + r = sccc_merge(sccc(scofactor(T, cl, best)), + sccc(scofactor(T, cr, best)), cl, cr); + free_cubelist(T); + } + + if (debug & REDUCE1) + printf("SCCC[%d]: result is %s\n", --sccc_level, pc1(r)); + return r; +} + + +pcube sccc_merge(left, right, cl, cr) +INOUT register pcube left, right; /* will be disposed of ... */ +INOUT register pcube cl, cr; /* will be disposed of ... */ +{ + INLINEset_and(left, left, cl); + INLINEset_and(right, right, cr); + INLINEset_or(left, left, right); + free_cube(right); + free_cube(cl); + free_cube(cr); + return left; +} + + +/* + sccc_cube -- find the smallest cube containing the complement of a cube + + By DeMorgan's law and the fact that the smallest cube containing a + cover is the "or" of the positional cubes, it is simple to see that + the SCCC is the universe if the cube has more than two active + variables. If there is only a single active variable, then the + SCCC is merely the bitwise complement of the cube in that + variable. A last special case is no active variables, in which + case the SCCC is empty. + + This is "anded" with the incoming cube result. +*/ +pcube sccc_cube(result, p) +register pcube result, p; +{ + register pcube temp=cube.temp[0], mask; + int var; + + if ((var = cactive(p)) >= 0) { + mask = cube.var_mask[var]; + INLINEset_xor(temp, p, mask); + INLINEset_and(result, result, temp); + } + return result; +} + +/* + * sccc_special_cases -- check the special cases for sccc + */ + +bool sccc_special_cases(T, result) +INOUT pcube *T; /* will be disposed if answer is determined */ +OUT pcube *result; /* returned only if answer determined */ +{ + register pcube *T1, p, temp = cube.temp[1], ceil, cof = T[0]; + pcube *A, *B; + + /* empty cover => complement is universe => SCCC is universe */ + if (T[2] == NULL) { + *result = set_save(cube.fullset); + free_cubelist(T); + return TRUE; + } + + /* row of 1's => complement is empty => SCCC is empty */ + for(T1 = T+2; (p = *T1++) != NULL; ) { + if (full_row(p, cof)) { + *result = new_cube(); + free_cubelist(T); + return TRUE; + } + } + + /* Collect column counts, determine unate variables, etc. */ + massive_count(T); + + /* If cover is unate (or single cube), apply simple rules to find SCCCU */ + if (cdata.vars_unate == cdata.vars_active || T[3] == NULL) { + *result = set_save(cube.fullset); + for(T1 = T+2; (p = *T1++) != NULL; ) { + (void) sccc_cube(*result, set_or(temp, p, cof)); + } + free_cubelist(T); + return TRUE; + } + + /* Check for column of 0's (which can be easily factored( */ + ceil = set_save(cof); + for(T1 = T+2; (p = *T1++) != NULL; ) { + INLINEset_or(ceil, ceil, p); + } + if (! setp_equal(ceil, cube.fullset)) { + *result = sccc_cube(set_save(cube.fullset), ceil); + if (setp_equal(*result, cube.fullset)) { + free_cube(ceil); + } else { + *result = sccc_merge(sccc(cofactor(T,ceil)), + set_save(cube.fullset), ceil, *result); + } + free_cubelist(T); + return TRUE; + } + free_cube(ceil); + + /* Single active column at this point => tautology => SCCC is empty */ + if (cdata.vars_active == 1) { + *result = new_cube(); + free_cubelist(T); + return TRUE; + } + + /* Check for components */ + if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T)/2) { + if (cubelist_partition(T, &A, &B, debug & REDUCE1) == 0) { + return MAYBE; + } else { + free_cubelist(T); + *result = sccc(A); + ceil = sccc(B); + (void) set_and(*result, *result, ceil); + set_free(ceil); + return TRUE; + } + } + + /* Not much we can do about it */ + return MAYBE; +} diff --git a/abc70930/src/misc/espresso/rows.c b/abc70930/src/misc/espresso/rows.c new file mode 100644 index 00000000..bf0c0baa --- /dev/null +++ b/abc70930/src/misc/espresso/rows.c @@ -0,0 +1,314 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +//#include "port.h" +#include "sparse_int.h" + + +/* + * allocate a new row vector + */ +sm_row * +sm_row_alloc() +{ + register sm_row *prow; + +#ifdef FAST_AND_LOOSE + if (sm_row_freelist == NIL(sm_row)) { + prow = ALLOC(sm_row, 1); + } else { + prow = sm_row_freelist; + sm_row_freelist = prow->next_row; + } +#else + prow = ALLOC(sm_row, 1); +#endif + + prow->row_num = 0; + prow->length = 0; + prow->first_col = prow->last_col = NIL(sm_element); + prow->next_row = prow->prev_row = NIL(sm_row); + prow->flag = 0; + prow->user_word = NIL(char); /* for our user ... */ + return prow; +} + + +/* + * free a row vector -- for FAST_AND_LOOSE, this is real cheap for rows; + * however, freeing a column must still walk down the column discarding + * the elements one-by-one; that is the only use for the extra '-DCOLS' + * compile flag ... + */ +void +sm_row_free(prow) +register sm_row *prow; +{ +#if defined(FAST_AND_LOOSE) && ! defined(COLS) + if (prow->first_col != NIL(sm_element)) { + /* Add the linked list of row items to the free list */ + prow->last_col->next_col = sm_element_freelist; + sm_element_freelist = prow->first_col; + } + + /* Add the row to the free list of rows */ + prow->next_row = sm_row_freelist; + sm_row_freelist = prow; +#else + register sm_element *p, *pnext; + + for(p = prow->first_col; p != 0; p = pnext) { + pnext = p->next_col; + sm_element_free(p); + } + FREE(prow); +#endif +} + + +/* + * duplicate an existing row + */ +sm_row * +sm_row_dup(prow) +register sm_row *prow; +{ + register sm_row *pnew; + register sm_element *p; + + pnew = sm_row_alloc(); + for(p = prow->first_col; p != 0; p = p->next_col) { + (void) sm_row_insert(pnew, p->col_num); + } + return pnew; +} + + +/* + * insert an element into a row vector + */ +sm_element * +sm_row_insert(prow, col) +register sm_row *prow; +register int col; +{ + register sm_element *test, *element; + + /* get a new item, save its address */ + sm_element_alloc(element); + test = element; + sorted_insert(sm_element, prow->first_col, prow->last_col, prow->length, + next_col, prev_col, col_num, col, test); + + /* if item was not used, free it */ + if (element != test) { + sm_element_free(element); + } + + /* either way, return the current new value */ + return test; +} + + +/* + * remove an element from a row vector + */ +void +sm_row_remove(prow, col) +register sm_row *prow; +register int col; +{ + register sm_element *p; + + for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col) + ; + if (p != 0 && p->col_num == col) { + dll_unlink(p, prow->first_col, prow->last_col, + next_col, prev_col, prow->length); + sm_element_free(p); + } +} + + +/* + * find an element (if it is in the row vector) + */ +sm_element * +sm_row_find(prow, col) +sm_row *prow; +int col; +{ + register sm_element *p; + + for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col) + ; + if (p != 0 && p->col_num == col) { + return p; + } else { + return NIL(sm_element); + } +} + +/* + * return 1 if row p2 contains row p1; 0 otherwise + */ +int +sm_row_contains(p1, p2) +sm_row *p1, *p2; +{ + register sm_element *q1, *q2; + + q1 = p1->first_col; + q2 = p2->first_col; + while (q1 != 0) { + if (q2 == 0 || q1->col_num < q2->col_num) { + return 0; + } else if (q1->col_num == q2->col_num) { + q1 = q1->next_col; + q2 = q2->next_col; + } else { + q2 = q2->next_col; + } + } + return 1; +} + + +/* + * return 1 if row p1 and row p2 share an element in common + */ +int +sm_row_intersects(p1, p2) +sm_row *p1, *p2; +{ + register sm_element *q1, *q2; + + q1 = p1->first_col; + q2 = p2->first_col; + if (q1 == 0 || q2 == 0) return 0; + for(;;) { + if (q1->col_num < q2->col_num) { + if ((q1 = q1->next_col) == 0) { + return 0; + } + } else if (q1->col_num > q2->col_num) { + if ((q2 = q2->next_col) == 0) { + return 0; + } + } else { + return 1; + } + } +} + + +/* + * compare two rows, lexical ordering + */ +int +sm_row_compare(p1, p2) +sm_row *p1, *p2; +{ + register sm_element *q1, *q2; + + q1 = p1->first_col; + q2 = p2->first_col; + while(q1 != 0 && q2 != 0) { + if (q1->col_num != q2->col_num) { + return q1->col_num - q2->col_num; + } + q1 = q1->next_col; + q2 = q2->next_col; + } + + if (q1 != 0) { + return 1; + } else if (q2 != 0) { + return -1; + } else { + return 0; + } +} + + +/* + * return the intersection + */ +sm_row * +sm_row_and(p1, p2) +sm_row *p1, *p2; +{ + register sm_element *q1, *q2; + register sm_row *result; + + result = sm_row_alloc(); + q1 = p1->first_col; + q2 = p2->first_col; + if (q1 == 0 || q2 == 0) return result; + for(;;) { + if (q1->col_num < q2->col_num) { + if ((q1 = q1->next_col) == 0) { + return result; + } + } else if (q1->col_num > q2->col_num) { + if ((q2 = q2->next_col) == 0) { + return result; + } + } else { + (void) sm_row_insert(result, q1->col_num); + if ((q1 = q1->next_col) == 0) { + return result; + } + if ((q2 = q2->next_col) == 0) { + return result; + } + } + } +} + +int +sm_row_hash(prow, modulus) +sm_row *prow; +int modulus; +{ + register int sum; + register sm_element *p; + + sum = 0; + for(p = prow->first_col; p != 0; p = p->next_col) { + sum = (sum*17 + p->col_num) % modulus; + } + return sum; +} + +/* + * remove an element from a row vector (given a pointer to the element) + */ +void +sm_row_remove_element(prow, p) +register sm_row *prow; +register sm_element *p; +{ + dll_unlink(p, prow->first_col, prow->last_col, + next_col, prev_col, prow->length); + sm_element_free(p); +} + + +void +sm_row_print(fp, prow) +FILE *fp; +sm_row *prow; +{ + sm_element *p; + + for(p = prow->first_col; p != 0; p = p->next_col) { + (void) fprintf(fp, " %d", p->col_num); + } +} diff --git a/abc70930/src/misc/espresso/set.c b/abc70930/src/misc/espresso/set.c new file mode 100644 index 00000000..fce88288 --- /dev/null +++ b/abc70930/src/misc/espresso/set.c @@ -0,0 +1,820 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + * set.c -- routines for maniuplating sets and set families + */ + +/* LINTLIBRARY */ + +#include "espresso.h" +static pset_family set_family_garbage = NULL; + +static int intcpy(d, s, n) +register unsigned int *d, *s; +register long n; +{ + register int i; + for(i = 0; i < n; i++) { + *d++ = *s++; + } +} + + +/* bit_index -- find first bit (from LSB) in a word (MSB=bit n, LSB=bit 0) */ +int bit_index(a) +register unsigned int a; +{ + register int i; + if (a == 0) + return -1; + for(i = 0; (a & 1) == 0; a >>= 1, i++) + ; + return i; +} + + +/* set_ord -- count number of elements in a set */ +int set_ord(a) +register pset a; +{ + register int i, sum = 0; + register unsigned int val; + for(i = LOOP(a); i > 0; i--) + if ((val = a[i]) != 0) + sum += count_ones(val); + return sum; +} + +/* set_dist -- distance between two sets (# elements in common) */ +int set_dist(a, b) +register pset a, b; +{ + register int i, sum = 0; + register unsigned int val; + for(i = LOOP(a); i > 0; i--) + if ((val = a[i] & b[i]) != 0) + sum += count_ones(val); + return sum; +} + +/* set_clear -- make "r" the empty set of "size" elements */ +pset set_clear(r, size) +register pset r; +int size; +{ + register int i = LOOPINIT(size); + *r = i; do r[i] = 0; while (--i > 0); + return r; +} + +/* set_fill -- make "r" the universal set of "size" elements */ +pset set_fill(r, size) +register pset r; +register int size; +{ + register int i = LOOPINIT(size); + *r = i; + r[i] = ~ (unsigned) 0; + r[i] >>= i * BPI - size; + while (--i > 0) + r[i] = ~ (unsigned) 0; + return r; +} + +/* set_copy -- copy set a into set r */ +pset set_copy(r, a) +register pset r, a; +{ + register int i = LOOPCOPY(a); + do r[i] = a[i]; while (--i >= 0); + return r; +} + +/* set_and -- compute intersection of sets "a" and "b" */ +pset set_and(r, a, b) +register pset r, a, b; +{ + register int i = LOOP(a); + PUTLOOP(r,i); do r[i] = a[i] & b[i]; while (--i > 0); + return r; +} + +/* set_or -- compute union of sets "a" and "b" */ +pset set_or(r, a, b) +register pset r, a, b; +{ + register int i = LOOP(a); + PUTLOOP(r,i); do r[i] = a[i] | b[i]; while (--i > 0); + return r; +} + +/* set_diff -- compute difference of sets "a" and "b" */ +pset set_diff(r, a, b) +register pset r, a, b; +{ + register int i = LOOP(a); + PUTLOOP(r,i); do r[i] = a[i] & ~b[i]; while (--i > 0); + return r; +} + +/* set_xor -- compute exclusive-or of sets "a" and "b" */ +pset set_xor(r, a, b) +register pset r, a, b; +{ + register int i = LOOP(a); +#ifdef IBM_WATC + PUTLOOP(r,i); do r[i] = (a[i]&~b[i]) | (~a[i]&b[i]); while (--i > 0); +#else + PUTLOOP(r,i); do r[i] = a[i] ^ b[i]; while (--i > 0); +#endif + return r; +} + +/* set_merge -- compute "a" & "mask" | "b" & ~ "mask" */ +pset set_merge(r, a, b, mask) +register pset r, a, b, mask; +{ + register int i = LOOP(a); + PUTLOOP(r,i); do r[i] = (a[i]&mask[i]) | (b[i]&~mask[i]); while (--i > 0); + return r; +} + +/* set_andp -- compute intersection of sets "a" and "b" , TRUE if nonempty */ +bool set_andp(r, a, b) +register pset r, a, b; +{ + register int i = LOOP(a); + register unsigned int x = 0; + PUTLOOP(r,i); do {r[i] = a[i] & b[i]; x |= r[i];} while (--i > 0); + return x != 0; +} + +/* set_orp -- compute union of sets "a" and "b" , TRUE if nonempty */ +bool set_orp(r, a, b) +register pset r, a, b; +{ + register int i = LOOP(a); + register unsigned int x = 0; + PUTLOOP(r,i); do {r[i] = a[i] | b[i]; x |= r[i];} while (--i > 0); + return x != 0; +} + +/* setp_empty -- check if the set "a" is empty */ +bool setp_empty(a) +register pset a; +{ + register int i = LOOP(a); + do if (a[i]) return FALSE; while (--i > 0); + return TRUE; +} + +/* setp_full -- check if the set "a" is the full set of "size" elements */ +bool setp_full(a, size) +register pset a; +register int size; +{ + register int i = LOOP(a); + register unsigned int test; + test = ~ (unsigned) 0; + test >>= i * BPI - size; + if (a[i] != test) + return FALSE; + while (--i > 0) + if (a[i] != (~(unsigned) 0)) + return FALSE; + return TRUE; +} + +/* setp_equal -- check if the set "a" equals set "b" */ +bool setp_equal(a, b) +register pset a, b; +{ + register int i = LOOP(a); + do if (a[i] != b[i]) return FALSE; while (--i > 0); + return TRUE; +} + +/* setp_disjoint -- check if intersection of "a" and "b" is empty */ +bool setp_disjoint(a, b) +register pset a, b; +{ + register int i = LOOP(a); + do if (a[i] & b[i]) return FALSE; while (--i > 0); + return TRUE; +} + +/* setp_implies -- check if "a" implies "b" ("b" contains "a") */ +bool setp_implies(a, b) +register pset a, b; +{ + register int i = LOOP(a); + do if (a[i] & ~b[i]) return FALSE; while (--i > 0); + return TRUE; +} + +/* sf_or -- form the "or" of all sets in a set family */ +pset sf_or(A) +pset_family A; +{ + register pset or, last, p; + + or = set_new(A->sf_size); + foreach_set(A, last, p) + INLINEset_or(or, or, p); + return or; +} + +/* sf_and -- form the "and" of all sets in a set family */ +pset sf_and(A) +pset_family A; +{ + register pset and, last, p; + + and = set_fill(set_new(A->sf_size), A->sf_size); + foreach_set(A, last, p) + INLINEset_and(and, and, p); + return and; +} + +/* sf_active -- make all members of the set family active */ +pset_family sf_active(A) +pset_family A; +{ + register pset p, last; + foreach_set(A, last, p) { + SET(p, ACTIVE); + } + A->active_count = A->count; + return A; +} + + +/* sf_inactive -- remove all inactive cubes in a set family */ +pset_family sf_inactive(A) +pset_family A; +{ + register pset p, last, pdest; + + pdest = A->data; + foreach_set(A, last, p) { + if (TESTP(p, ACTIVE)) { + if (pdest != p) { + INLINEset_copy(pdest, p); + } + pdest += A->wsize; + } else { + A->count--; + } + } + return A; +} + + +/* sf_copy -- copy a set family */ +pset_family sf_copy(R, A) +pset_family R, A; +{ + R->sf_size = A->sf_size; + R->wsize = A->wsize; +/*R->capacity = A->count;*/ +/*R->data = REALLOC(unsigned int, R->data, (long) R->capacity * R->wsize);*/ + R->count = A->count; + R->active_count = A->active_count; + intcpy(R->data, A->data, (long) A->wsize * A->count); + return R; +} + + +/* sf_join -- join A and B into a single set_family */ +pset_family sf_join(A, B) +pset_family A, B; +{ + pset_family R; + long asize = A->count * A->wsize; + long bsize = B->count * B->wsize; + + if (A->sf_size != B->sf_size) fatal("sf_join: sf_size mismatch"); + R = sf_new(A->count + B->count, A->sf_size); + R->count = A->count + B->count; + R->active_count = A->active_count + B->active_count; + intcpy(R->data, A->data, asize); + intcpy(R->data + asize, B->data, bsize); + return R; +} + + +/* sf_append -- append the sets of B to the end of A, and dispose of B */ +pset_family sf_append(A, B) +pset_family A, B; +{ + long asize = A->count * A->wsize; + long bsize = B->count * B->wsize; + + if (A->sf_size != B->sf_size) fatal("sf_append: sf_size mismatch"); + A->capacity = A->count + B->count; + A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize); + intcpy(A->data + asize, B->data, bsize); + A->count += B->count; + A->active_count += B->active_count; + sf_free(B); + return A; +} + + +/* sf_new -- allocate "num" sets of "size" elements each */ +pset_family sf_new(num, size) +int num, size; +{ + pset_family A; + if (set_family_garbage == NULL) { + A = ALLOC(set_family_t, 1); + } else { + A = set_family_garbage; + set_family_garbage = A->next; + } + A->sf_size = size; + A->wsize = SET_SIZE(size); + A->capacity = num; + A->data = ALLOC(unsigned int, (long) A->capacity * A->wsize); + A->count = 0; + A->active_count = 0; + return A; +} + + +/* sf_save -- create a duplicate copy of a set family */ +pset_family sf_save(A) +register pset_family A; +{ + return sf_copy(sf_new(A->count, A->sf_size), A); +} + + +/* sf_free -- free the storage allocated for a set family */ +void sf_free(A) +pset_family A; +{ + FREE(A->data); + A->next = set_family_garbage; + set_family_garbage = A; +} + + +/* sf_cleanup -- free all of the set families from the garbage list */ +void sf_cleanup() +{ + register pset_family p, pnext; + for(p = set_family_garbage; p != (pset_family) NULL; p = pnext) { + pnext = p->next; + FREE(p); + } + set_family_garbage = (pset_family) NULL; +} + + +/* sf_addset -- add a set to the end of a set family */ +pset_family sf_addset(A, s) +pset_family A; +pset s; +{ + register pset p; + + if (A->count >= A->capacity) { + A->capacity = A->capacity + A->capacity/2 + 1; + A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize); + } + p = GETSET(A, A->count++); + INLINEset_copy(p, s); + return A; +} + +/* sf_delset -- delete a set from a set family */ +void sf_delset(A, i) +pset_family A; +int i; +{ (void) set_copy(GETSET(A,i), GETSET(A, --A->count));} + +/* sf_print -- print a set_family as a set (list the element numbers) */ +void sf_print(A) +pset_family A; +{ + char *ps1(); + register pset p; + register int i; + foreachi_set(A, i, p) + printf("A[%d] = %s\n", i, ps1(p)); +} + +/* sf_bm_print -- print a set_family as a bit-matrix */ +void sf_bm_print(A) +pset_family A; +{ + char *pbv1(); + register pset p; + register int i; + foreachi_set(A, i, p) + printf("[%4d] %s\n", i, pbv1(p, A->sf_size)); +} + + +/* sf_write -- output a set family in an unintelligable manner */ +void sf_write(fp, A) +FILE *fp; +pset_family A; +{ + register pset p, last; + (void) fprintf(fp, "%d %d\n", A->count, A->sf_size); + foreach_set(A, last, p) + set_write(fp, p); + (void) fflush(fp); +} + + +/* sf_read -- read a set family written by sf_write */ +pset_family sf_read(fp) +FILE *fp; +{ + int i, j; + register pset p, last; + pset_family A; + + (void) fscanf(fp, "%d %d\n", &i, &j); + A = sf_new(i, j); + A->count = i; + foreach_set(A, last, p) { + (void) fscanf(fp, "%x", p); + for(j = 1; j <= LOOP(p); j++) + (void) fscanf(fp, "%x", p+j); + } + return A; +} + + +/* set_write -- output a set in an unintelligable manner */ +void set_write(fp, a) +register FILE *fp; +register pset a; +{ + register int n = LOOP(a), j; + + for(j = 0; j <= n; j++) { + (void) fprintf(fp, "%x ", a[j]); + if ((j+1) % 8 == 0 && j != n) + (void) fprintf(fp, "\n\t"); + } + (void) fprintf(fp, "\n"); +} + + +/* sf_bm_read -- read a set family written by sf_bm_print (almost) */ +pset_family sf_bm_read(fp) +FILE *fp; +{ + int i, j, rows, cols; + register pset pdest; + pset_family A; + + (void) fscanf(fp, "%d %d\n", &rows, &cols); + A = sf_new(rows, cols); + for(i = 0; i < rows; i++) { + pdest = GETSET(A, A->count++); + (void) set_clear(pdest, A->sf_size); + for(j = 0; j < cols; j++) { + switch(getc(fp)) { + case '0': + break; + case '1': + set_insert(pdest, j); + break; + default: + fatal("Error reading set family"); + } + } + if (getc(fp) != '\n') { + fatal("Error reading set family (at end of line)"); + } + } + return A; +} + + + +/* ps1 -- convert a set into a printable string */ +#define largest_string 120 +static char s1[largest_string]; +char *ps1(a) +register pset a; +{ + register int i, num, l, len = 0, n = NELEM(a); + char temp[20]; + bool first = TRUE; + + s1[len++] = '['; + for(i = 0; i < n; i++) + if (is_in_set(a,i)) { + if (! first) + s1[len++] = ','; + first = FALSE; num = i; + /* Generate digits (reverse order) */ + l = 0; do temp[l++] = num % 10 + '0'; while ((num /= 10) > 0); + /* Copy them back in correct order */ + do s1[len++] = temp[--l]; while (l > 0); + if (len > largest_string-15) { + s1[len++] = '.'; s1[len++] = '.'; s1[len++] = '.'; + break; + } + } + + s1[len++] = ']'; + s1[len++] = '\0'; + return s1; +} + +/* pbv1 -- print bit-vector */ +char *pbv1(s, n) +pset s; +int n; +{ + register int i; + for(i = 0; i < n; i++) + s1[i] = is_in_set(s,i) ? '1' : '0'; + s1[n] = '\0'; + return s1; +} + + +/* set_adjcnt -- adjust the counts for a set by "weight" */ +void +set_adjcnt(a, count, weight) +register pset a; +register int *count, weight; +{ + register int i, base; + register unsigned int val; + + for(i = LOOP(a); i > 0; ) { + for(val = a[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) { + if (val & 1) { + count[base] += weight; + } + } + } +} + + + +/* sf_count -- perform a column sum over a set family */ +int *sf_count(A) +pset_family A; +{ + register pset p, last; + register int i, base, *count; + register unsigned int val; + + count = ALLOC(int, A->sf_size); + for(i = A->sf_size - 1; i >= 0; i--) { + count[i] = 0; + } + + foreach_set(A, last, p) { + for(i = LOOP(p); i > 0; ) { + for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) { + if (val & 1) { + count[base]++; + } + } + } + } + return count; +} + + +/* sf_count_restricted -- perform a column sum over a set family, restricting + * to only the columns which are in r; also, the columns are weighted by the + * number of elements which are in each row + */ +int *sf_count_restricted(A, r) +pset_family A; +register pset r; +{ + register pset p; + register int i, base, *count; + register unsigned int val; + int weight; + pset last; + + count = ALLOC(int, A->sf_size); + for(i = A->sf_size - 1; i >= 0; i--) { + count[i] = 0; + } + + /* Loop for each set */ + foreach_set(A, last, p) { + weight = 1024 / (set_ord(p) - 1); + for(i = LOOP(p); i > 0; ) { + for(val=p[i]&r[i], base= --i<>= 1) { + if (val & 1) { + count[base] += weight; + } + } + } + } + return count; +} + + +/* + * sf_delc -- delete columns first ... last of A + */ +pset_family sf_delc(A, first, last) +pset_family A; +int first, last; +{ + return sf_delcol(A, first, last-first + 1); +} + + +/* + * sf_addcol -- add columns to a set family; includes a quick check to see + * if there is already enough room (and hence, can avoid copying) + */ +pset_family sf_addcol(A, firstcol, n) +pset_family A; +int firstcol, n; +{ + int maxsize; + + /* Check if adding columns at the end ... */ + if (firstcol == A->sf_size) { + /* If so, check if there is already enough room */ + maxsize = BPI * LOOPINIT(A->sf_size); + if ((A->sf_size + n) <= maxsize) { + A->sf_size += n; + return A; + } + } + return sf_delcol(A, firstcol, -n); +} + +/* + * sf_delcol -- add/delete columns to/from a set family + * + * if n > 0 then n columns starting from firstcol are deleted if n < 0 + * then n blank columns are inserted starting at firstcol + * (i.e., the first new column number is firstcol) + * + * This is done by copying columns in the array which is a relatively + * slow operation. + */ +pset_family sf_delcol(A, firstcol, n) +pset_family A; +register int firstcol, n; +{ + register pset p, last, pdest; + register int i; + pset_family B; + + B = sf_new(A->count, A->sf_size - n); + foreach_set(A, last, p) { + pdest = GETSET(B, B->count++); + INLINEset_clear(pdest, B->sf_size); + for(i = 0; i < firstcol; i++) + if (is_in_set(p, i)) + set_insert(pdest, i); + for(i = n > 0 ? firstcol + n : firstcol; i < A->sf_size; i++) + if (is_in_set(p, i)) + set_insert(pdest, i - n); + } + sf_free(A); + return B; +} + + +/* + * sf_copy_col -- copy column "srccol" from "src" to column "dstcol" of "dst" + */ +pset_family sf_copy_col(dst, dstcol, src, srccol) +pset_family dst, src; +int dstcol, srccol; +{ + register pset last, p, pdest; + register int word_test, word_set; + unsigned int bit_set, bit_test; + + /* CHEAT! form these constants outside the loop */ + word_test = WHICH_WORD(srccol); + bit_test = 1 << WHICH_BIT(srccol); + word_set = WHICH_WORD(dstcol); + bit_set = 1 << WHICH_BIT(dstcol); + + pdest = dst->data; + foreach_set(src, last, p) { + if ((p[word_test] & bit_test) != 0) + pdest[word_set] |= bit_set; +/* + * equivalent code for this is ... + * if (is_in_set(p, srccol)) set_insert(pdest, destcol); + */ + pdest += dst->wsize; + } + return dst; +} + + + +/* + * sf_compress -- delete columns from a matrix + */ +pset_family sf_compress(A, c) +pset_family A; /* will be freed */ +register pset c; +{ + register pset p; + register int i, bcol; + pset_family B; + + /* create a clean set family for the result */ + B = sf_new(A->count, set_ord(c)); + for(i = 0; i < A->count; i++) { + p = GETSET(B, B->count++); + INLINEset_clear(p, B->sf_size); + } + + /* copy each column of A which has a 1 in c */ + bcol = 0; + for(i = 0; i < A->sf_size; i++) { + if (is_in_set(c, i)) { + (void) sf_copy_col(B, bcol++, A, i); + } + } + sf_free(A); + return B; +} + + + +/* + * sf_transpose -- transpose a bit matrix + * + * There are trickier ways of doing this, but this works. + */ +pset_family sf_transpose(A) +pset_family A; +{ + pset_family B; + register pset p; + register int i, j; + + B = sf_new(A->sf_size, A->count); + B->count = A->sf_size; + foreachi_set(B, i, p) { + INLINEset_clear(p, B->sf_size); + } + foreachi_set(A, i, p) { + for(j = 0; j < A->sf_size; j++) { + if (is_in_set(p, j)) { + set_insert(GETSET(B, j), i); + } + } + } + sf_free(A); + return B; +} + + +/* + * sf_permute -- permute the columns of a set_family + * + * permute is an array of integers containing column numbers of A which + * are to be retained. + */ +pset_family sf_permute(A, permute, npermute) +pset_family A; +register int *permute, npermute; +{ + pset_family B; + register pset p, last, pdest; + register int j; + + B = sf_new(A->count, npermute); + B->count = A->count; + foreach_set(B, last, p) + INLINEset_clear(p, npermute); + + pdest = B->data; + foreach_set(A, last, p) { + for(j = 0; j < npermute; j++) + if (is_in_set(p, permute[j])) + set_insert(pdest, j); + pdest += B->wsize; + } + sf_free(A); + return B; +} diff --git a/abc70930/src/misc/espresso/setc.c b/abc70930/src/misc/espresso/setc.c new file mode 100644 index 00000000..a6112ebc --- /dev/null +++ b/abc70930/src/misc/espresso/setc.c @@ -0,0 +1,483 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + setc.c -- massive bit-hacking for performing special "cube"-type + operations on a set + + The basic trick used for binary valued variables is the following: + + If a[w] and b[w] contain a full word of binary variables, then: + + 1) to get the full word of their intersection, we use + + x = a[w] & b[w]; + + + 2) to see if the intersection is null in any variables, we examine + + x = ~(x | x >> 1) & DISJOINT; + + this will have a single 1 in each binary variable for which + the intersection is null. In particular, if this is zero, + then there are no disjoint variables; or, if this is nonzero, + then there is at least one disjoint variable. A "count_ones" + over x will tell in how many variables they have an null + intersection. + + + 3) to get a mask which selects the disjoint variables, we use + + (x | x << 1) + + this provides a selector which can be used to see where + they have an null intersection + + + cdist return distance between two cubes + cdist0 return true if two cubes are distance 0 apart + cdist01 return distance, or 2 if distance exceeds 1 + consensus compute consensus of two cubes distance 1 apart + force_lower expand hack (for now), related to consensus +*/ + +#include "espresso.h" + +/* see if the cube has a full row of 1's (with respect to cof) */ +bool full_row(p, cof) +IN register pcube p, cof; +{ + register int i = LOOP(p); + do if ((p[i] | cof[i]) != cube.fullset[i]) return FALSE; while (--i > 0); + return TRUE; +} + +/* + cdist0 -- return TRUE if a and b are distance 0 apart +*/ + +bool cdist0(a, b) +register pcube a, b; +{ + { /* Check binary variables */ + register int w, last; register unsigned int x; + if ((last = cube.inword) != -1) { + + /* Check the partial word of binary variables */ + x = a[last] & b[last]; + if (~(x | x >> 1) & cube.inmask) + return FALSE; /* disjoint in some variable */ + + /* Check the full words of binary variables */ + for(w = 1; w < last; w++) { + x = a[w] & b[w]; + if (~(x | x >> 1) & DISJOINT) + return FALSE; /* disjoint in some variable */ + } + } + } + + { /* Check the multiple-valued variables */ + register int w, var, last; register pcube mask; + for(var = cube.num_binary_vars; var < cube.num_vars; var++) { + mask = cube.var_mask[var]; last = cube.last_word[var]; + for(w = cube.first_word[var]; w <= last; w++) + if (a[w] & b[w] & mask[w]) + goto nextvar; + return FALSE; /* disjoint in this variable */ + nextvar: ; + } + } + return TRUE; +} + +/* + cdist01 -- return the "distance" between two cubes (defined as the + number of null variables in their intersection). If the distance + exceeds 1, the value 2 is returned. +*/ + +int cdist01(a, b) +register pset a, b; +{ + int dist = 0; + + { /* Check binary variables */ + register int w, last; register unsigned int x; + if ((last = cube.inword) != -1) { + + /* Check the partial word of binary variables */ + x = a[last] & b[last]; + if (x = ~ (x | x >> 1) & cube.inmask) + if ((dist = count_ones(x)) > 1) + return 2; + + /* Check the full words of binary variables */ + for(w = 1; w < last; w++) { + x = a[w] & b[w]; + if (x = ~ (x | x >> 1) & DISJOINT) + if (dist == 1 || (dist += count_ones(x)) > 1) + return 2; + } + } + } + + { /* Check the multiple-valued variables */ + register int w, var, last; register pcube mask; + for(var = cube.num_binary_vars; var < cube.num_vars; var++) { + mask = cube.var_mask[var]; last = cube.last_word[var]; + for(w = cube.first_word[var]; w <= last; w++) + if (a[w] & b[w] & mask[w]) + goto nextvar; + if (++dist > 1) + return 2; + nextvar: ; + } + } + return dist; +} + +/* + cdist -- return the "distance" between two cubes (defined as the + number of null variables in their intersection). +*/ + +int cdist(a, b) +register pset a, b; +{ + int dist = 0; + + { /* Check binary variables */ + register int w, last; register unsigned int x; + if ((last = cube.inword) != -1) { + + /* Check the partial word of binary variables */ + x = a[last] & b[last]; + if (x = ~ (x | x >> 1) & cube.inmask) + dist = count_ones(x); + + /* Check the full words of binary variables */ + for(w = 1; w < last; w++) { + x = a[w] & b[w]; + if (x = ~ (x | x >> 1) & DISJOINT) + dist += count_ones(x); + } + } + } + + { /* Check the multiple-valued variables */ + register int w, var, last; register pcube mask; + for(var = cube.num_binary_vars; var < cube.num_vars; var++) { + mask = cube.var_mask[var]; last = cube.last_word[var]; + for(w = cube.first_word[var]; w <= last; w++) + if (a[w] & b[w] & mask[w]) + goto nextvar; + dist++; + nextvar: ; + } + } + return dist; +} + +/* + force_lower -- Determine which variables of a do not intersect b. +*/ + +pset force_lower(xlower, a, b) +INOUT pset xlower; +IN register pset a, b; +{ + + { /* Check binary variables (if any) */ + register int w, last; register unsigned int x; + if ((last = cube.inword) != -1) { + + /* Check the partial word of binary variables */ + x = a[last] & b[last]; + if (x = ~(x | x >> 1) & cube.inmask) + xlower[last] |= (x | (x << 1)) & a[last]; + + /* Check the full words of binary variables */ + for(w = 1; w < last; w++) { + x = a[w] & b[w]; + if (x = ~(x | x >> 1) & DISJOINT) + xlower[w] |= (x | (x << 1)) & a[w]; + } + } + } + + { /* Check the multiple-valued variables */ + register int w, var, last; register pcube mask; + for(var = cube.num_binary_vars; var < cube.num_vars; var++) { + mask = cube.var_mask[var]; last = cube.last_word[var]; + for(w = cube.first_word[var]; w <= last; w++) + if (a[w] & b[w] & mask[w]) + goto nextvar; + for(w = cube.first_word[var]; w <= last; w++) + xlower[w] |= a[w] & mask[w]; + nextvar: ; + } + } + return xlower; +} + +/* + consensus -- multiple-valued consensus + + Although this looks very messy, the idea is to compute for r the + "and" of the cubes a and b for each variable, unless the "and" is + null in a variable, in which case the "or" of a and b is computed + for this variable. + + Because we don't check how many variables are null in the + intersection of a and b, the returned value for r really only + represents the consensus when a and b are distance 1 apart. +*/ + +void consensus(r, a, b) +INOUT pcube r; +IN register pcube a, b; +{ + INLINEset_clear(r, cube.size); + + { /* Check binary variables (if any) */ + register int w, last; register unsigned int x; + if ((last = cube.inword) != -1) { + + /* Check the partial word of binary variables */ + r[last] = x = a[last] & b[last]; + if (x = ~(x | x >> 1) & cube.inmask) + r[last] |= (x | (x << 1)) & (a[last] | b[last]); + + /* Check the full words of binary variables */ + for(w = 1; w < last; w++) { + r[w] = x = a[w] & b[w]; + if (x = ~(x | x >> 1) & DISJOINT) + r[w] |= (x | (x << 1)) & (a[w] | b[w]); + } + } + } + + + { /* Check the multiple-valued variables */ + bool empty; int var; unsigned int x; + register int w, last; register pcube mask; + for(var = cube.num_binary_vars; var < cube.num_vars; var++) { + mask = cube.var_mask[var]; + last = cube.last_word[var]; + empty = TRUE; + for(w = cube.first_word[var]; w <= last; w++) + if (x = a[w] & b[w] & mask[w]) + empty = FALSE, r[w] |= x; + if (empty) + for(w = cube.first_word[var]; w <= last; w++) + r[w] |= mask[w] & (a[w] | b[w]); + } + } +} + +/* + cactive -- return the index of the single active variable in + the cube, or return -1 if there are none or more than 2. +*/ + +int cactive(a) +register pcube a; +{ + int active = -1, dist = 0, bit_index(); + + { /* Check binary variables */ + register int w, last; + register unsigned int x; + if ((last = cube.inword) != -1) { + + /* Check the partial word of binary variables */ + x = a[last]; + if (x = ~ (x & x >> 1) & cube.inmask) { + if ((dist = count_ones(x)) > 1) + return -1; /* more than 2 active variables */ + active = (last-1)*(BPI/2) + bit_index(x) / 2; + } + + /* Check the full words of binary variables */ + for(w = 1; w < last; w++) { + x = a[w]; + if (x = ~ (x & x >> 1) & DISJOINT) { + if ((dist += count_ones(x)) > 1) + return -1; /* more than 2 active variables */ + active = (w-1)*(BPI/2) + bit_index(x) / 2; + } + } + } + } + + { /* Check the multiple-valued variables */ + register int w, var, last; + register pcube mask; + for(var = cube.num_binary_vars; var < cube.num_vars; var++) { + mask = cube.var_mask[var]; + last = cube.last_word[var]; + for(w = cube.first_word[var]; w <= last; w++) + if (mask[w] & ~ a[w]) { + if (++dist > 1) + return -1; + active = var; + break; + } + } + } + return active; +} + +/* + ccommon -- return TRUE if a and b are share "active" variables + active variables include variables that are empty; +*/ + +bool ccommon(a, b, cof) +register pcube a, b, cof; +{ + { /* Check binary variables */ + int last; + register int w; + register unsigned int x, y; + if ((last = cube.inword) != -1) { + + /* Check the partial word of binary variables */ + x = a[last] | cof[last]; + y = b[last] | cof[last]; + if (~(x & x>>1) & ~(y & y>>1) & cube.inmask) + return TRUE; + + /* Check the full words of binary variables */ + for(w = 1; w < last; w++) { + x = a[w] | cof[w]; + y = b[w] | cof[w]; + if (~(x & x>>1) & ~(y & y>>1) & DISJOINT) + return TRUE; + } + } + } + + { /* Check the multiple-valued variables */ + int var; + register int w, last; + register pcube mask; + for(var = cube.num_binary_vars; var < cube.num_vars; var++) { + mask = cube.var_mask[var]; last = cube.last_word[var]; + /* Check for some part missing from a */ + for(w = cube.first_word[var]; w <= last; w++) + if (mask[w] & ~a[w] & ~cof[w]) { + + /* If so, check for some part missing from b */ + for(w = cube.first_word[var]; w <= last; w++) + if (mask[w] & ~b[w] & ~cof[w]) + return TRUE; /* both active */ + break; + } + } + } + return FALSE; +} + +/* + These routines compare two sets (cubes) for the qsort() routine and + return: + + -1 if set a is to precede set b + 0 if set a and set b are equal + 1 if set a is to follow set b + + Usually the SIZE field of the set is assumed to contain the size + of the set (which will save recomputing the set size during the + sort). For distance-1 merging, the global variable cube.temp[0] is + a mask which mask's-out the merging variable. +*/ + +/* descend -- comparison for descending sort on set size */ +int descend(a, b) +pset *a, *b; +{ + register pset a1 = *a, b1 = *b; + if (SIZE(a1) > SIZE(b1)) return -1; + else if (SIZE(a1) < SIZE(b1)) return 1; + else { + register int i = LOOP(a1); + do + if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1; + while (--i > 0); + } + return 0; +} + +/* ascend -- comparison for ascending sort on set size */ +int ascend(a, b) +pset *a, *b; +{ + register pset a1 = *a, b1 = *b; + if (SIZE(a1) > SIZE(b1)) return 1; + else if (SIZE(a1) < SIZE(b1)) return -1; + else { + register int i = LOOP(a1); + do + if (a1[i] > b1[i]) return 1; else if (a1[i] < b1[i]) return -1; + while (--i > 0); + } + return 0; +} + + +/* lex_order -- comparison for "lexical" ordering of cubes */ +int lex_order(a, b) +pset *a, *b; +{ + register pset a1 = *a, b1 = *b; + register int i = LOOP(a1); + do + if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1; + while (--i > 0); + return 0; +} + + +/* d1_order -- comparison for distance-1 merge routine */ +int d1_order(a, b) +pset *a, *b; +{ + register pset a1 = *a, b1 = *b, c1 = cube.temp[0]; + register int i = LOOP(a1); + register unsigned int x1, x2; + do + if ((x1 = a1[i] | c1[i]) > (x2 = b1[i] | c1[i])) return -1; + else if (x1 < x2) return 1; + while (--i > 0); + return 0; +} + + +/* desc1 -- comparison (without indirection) for descending sort */ +/* also has effect of handling NULL pointers,and a NULL pointer has smallest +order */ +int desc1(a, b) +register pset a, b; +{ + if (a == (pset) NULL) + return (b == (pset) NULL) ? 0 : 1; + else if (b == (pset) NULL) + return -1; + if (SIZE(a) > SIZE(b)) return -1; + else if (SIZE(a) < SIZE(b)) return 1; + else { + register int i = LOOP(a); + do + if (a[i] > b[i]) return -1; else if (a[i] < b[i]) return 1; + while (--i > 0); + } + return 0; +} diff --git a/abc70930/src/misc/espresso/sharp.c b/abc70930/src/misc/espresso/sharp.c new file mode 100644 index 00000000..53435078 --- /dev/null +++ b/abc70930/src/misc/espresso/sharp.c @@ -0,0 +1,247 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + sharp.c -- perform sharp, disjoint sharp, and intersection +*/ + +#include "espresso.h" + +long start_time; + + +/* cv_sharp -- form the sharp product between two covers */ +pcover cv_sharp(A, B) +pcover A, B; +{ + pcube last, p; + pcover T; + + T = new_cover(0); + foreach_set(A, last, p) + T = sf_union(T, cb_sharp(p, B)); + return T; +} + + +/* cb_sharp -- form the sharp product between a cube and a cover */ +pcover cb_sharp(c, T) +pcube c; +pcover T; +{ + if (T->count == 0) { + T = sf_addset(new_cover(1), c); + } else { + start_time = ptime(); + T = cb_recur_sharp(c, T, 0, T->count-1, 0); + } + return T; +} + + +/* recursive formulation to provide balanced merging */ +pcover cb_recur_sharp(c, T, first, last, level) +pcube c; +pcover T; +int first, last, level; +{ + pcover temp, left, right; + int middle; + + if (first == last) { + temp = sharp(c, GETSET(T, first)); + } else { + middle = (first + last) / 2; + left = cb_recur_sharp(c, T, first, middle, level+1); + right = cb_recur_sharp(c, T, middle+1, last, level+1); + temp = cv_intersect(left, right); + if ((debug & SHARP) && level < 4) { + printf("# SHARP[%d]: %4d = %4d x %4d, time = %s\n", + level, temp->count, left->count, right->count, + print_time(ptime() - start_time)); + (void) fflush(stdout); + } + free_cover(left); + free_cover(right); + } + return temp; +} + + +/* sharp -- form the sharp product between two cubes */ +pcover sharp(a, b) +pcube a, b; +{ + register int var; + register pcube d=cube.temp[0], temp=cube.temp[1], temp1=cube.temp[2]; + pcover r = new_cover(cube.num_vars); + + if (cdist0(a, b)) { + set_diff(d, a, b); + for(var = 0; var < cube.num_vars; var++) { + if (! setp_empty(set_and(temp, d, cube.var_mask[var]))) { + set_diff(temp1, a, cube.var_mask[var]); + set_or(GETSET(r, r->count++), temp, temp1); + } + } + } else { + r = sf_addset(r, a); + } + return r; +} + +pcover make_disjoint(A) +pcover A; +{ + pcover R, new; + register pset last, p; + + R = new_cover(0); + foreach_set(A, last, p) { + new = cb_dsharp(p, R); + R = sf_append(R, new); + } + return R; +} + + +/* cv_dsharp -- disjoint-sharp product between two covers */ +pcover cv_dsharp(A, B) +pcover A, B; +{ + register pcube last, p; + pcover T; + + T = new_cover(0); + foreach_set(A, last, p) { + T = sf_union(T, cb_dsharp(p, B)); + } + return T; +} + + +/* cb1_dsharp -- disjoint-sharp product between a cover and a cube */ +pcover cb1_dsharp(T, c) +pcover T; +pcube c; +{ + pcube last, p; + pcover R; + + R = new_cover(T->count); + foreach_set(T, last, p) { + R = sf_union(R, dsharp(p, c)); + } + return R; +} + + +/* cb_dsharp -- disjoint-sharp product between a cube and a cover */ +pcover cb_dsharp(c, T) +pcube c; +pcover T; +{ + pcube last, p; + pcover Y, Y1; + + if (T->count == 0) { + Y = sf_addset(new_cover(1), c); + } else { + Y = new_cover(T->count); + set_copy(GETSET(Y,Y->count++), c); + foreach_set(T, last, p) { + Y1 = cb1_dsharp(Y, p); + free_cover(Y); + Y = Y1; + } + } + return Y; +} + + +/* dsharp -- form the disjoint-sharp product between two cubes */ +pcover dsharp(a, b) +pcube a, b; +{ + register pcube mask, diff, and, temp, temp1 = cube.temp[0]; + int var; + pcover r; + + r = new_cover(cube.num_vars); + + if (cdist0(a, b)) { + diff = set_diff(new_cube(), a, b); + and = set_and(new_cube(), a, b); + mask = new_cube(); + for(var = 0; var < cube.num_vars; var++) { + /* check if position var of "a and not b" is not empty */ + if (! setp_disjoint(diff, cube.var_mask[var])) { + + /* coordinate var equals the difference between a and b */ + temp = GETSET(r, r->count++); + (void) set_and(temp, diff, cube.var_mask[var]); + + /* coordinates 0 ... var-1 equal the intersection */ + INLINEset_and(temp1, and, mask); + INLINEset_or(temp, temp, temp1); + + /* coordinates var+1 .. cube.num_vars equal a */ + set_or(mask, mask, cube.var_mask[var]); + INLINEset_diff(temp1, a, mask); + INLINEset_or(temp, temp, temp1); + } + } + free_cube(diff); + free_cube(and); + free_cube(mask); + } else { + r = sf_addset(r, a); + } + return r; +} + +/* cv_intersect -- form the intersection of two covers */ + +#define MAGIC 500 /* save 500 cubes before containment */ + +pcover cv_intersect(A, B) +pcover A, B; +{ + register pcube pi, pj, lasti, lastj, pt; + pcover T, Tsave = NULL; + + /* How large should each temporary result cover be ? */ + T = new_cover(MAGIC); + pt = T->data; + + /* Form pairwise intersection of each cube of A with each cube of B */ + foreach_set(A, lasti, pi) { + foreach_set(B, lastj, pj) { + if (cdist0(pi, pj)) { + (void) set_and(pt, pi, pj); + if (++T->count >= T->capacity) { + if (Tsave == NULL) + Tsave = sf_contain(T); + else + Tsave = sf_union(Tsave, sf_contain(T)); + T = new_cover(MAGIC); + pt = T->data; + } else + pt += T->wsize; + } + } + } + + + if (Tsave == NULL) + Tsave = sf_contain(T); + else + Tsave = sf_union(Tsave, sf_contain(T)); + return Tsave; +} diff --git a/abc70930/src/misc/espresso/sminterf.c b/abc70930/src/misc/espresso/sminterf.c new file mode 100644 index 00000000..50a6db4e --- /dev/null +++ b/abc70930/src/misc/espresso/sminterf.c @@ -0,0 +1,44 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "espresso.h" + + +pset +do_sm_minimum_cover(A) +pset_family A; +{ + sm_matrix *M; + sm_row *sparse_cover; + sm_element *pe; + pset cover; + register int i, base, rownum; + register unsigned val; + register pset last, p; + + M = sm_alloc(); + rownum = 0; + foreach_set(A, last, p) { + foreach_set_element(p, i, val, base) { + (void) sm_insert(M, rownum, base); + } + rownum++; + } + + sparse_cover = sm_minimum_cover(M, NIL(int), 1, 0); + sm_free(M); + + cover = set_new(A->sf_size); + sm_foreach_row_element(sparse_cover, pe) { + set_insert(cover, pe->col_num); + } + sm_row_free(sparse_cover); + + return cover; +} diff --git a/abc70930/src/misc/espresso/solution.c b/abc70930/src/misc/espresso/solution.c new file mode 100644 index 00000000..26119185 --- /dev/null +++ b/abc70930/src/misc/espresso/solution.c @@ -0,0 +1,114 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#include "mincov_int.h" + + +solution_t * +solution_alloc() +{ + solution_t *sol; + + sol = ALLOC(solution_t, 1); + sol->cost = 0; + sol->row = sm_row_alloc(); + return sol; +} + + +void +solution_free(sol) +solution_t *sol; +{ + sm_row_free(sol->row); + FREE(sol); +} + + +solution_t * +solution_dup(sol) +solution_t *sol; +{ + solution_t *new_sol; + + new_sol = ALLOC(solution_t, 1); + new_sol->cost = sol->cost; + new_sol->row = sm_row_dup(sol->row); + return new_sol; +} + + +void +solution_add(sol, weight, col) +solution_t *sol; +int *weight; +int col; +{ + (void) sm_row_insert(sol->row, col); + sol->cost += WEIGHT(weight, col); +} + + +void +solution_accept(sol, A, weight, col) +solution_t *sol; +sm_matrix *A; +int *weight; +int col; +{ + register sm_element *p, *pnext; + sm_col *pcol; + + solution_add(sol, weight, col); + + /* delete rows covered by this column */ + pcol = sm_get_col(A, col); + for(p = pcol->first_row; p != 0; p = pnext) { + pnext = p->next_row; /* grab it before it disappears */ + sm_delrow(A, p->row_num); + } +} + + +/* ARGSUSED */ +void +solution_reject(sol, A, weight, col) +solution_t *sol; +sm_matrix *A; +int *weight; +int col; +{ + sm_delcol(A, col); +} + + +solution_t * +solution_choose_best(best1, best2) +solution_t *best1, *best2; +{ + if (best1 != NIL(solution_t)) { + if (best2 != NIL(solution_t)) { + if (best1->cost <= best2->cost) { + solution_free(best2); + return best1; + } else { + solution_free(best1); + return best2; + } + } else { + return best1; + } + } else { + if (best2 != NIL(solution_t)) { + return best2; + } else { + return NIL(solution_t); + } + } +} diff --git a/abc70930/src/misc/espresso/sparse.c b/abc70930/src/misc/espresso/sparse.c new file mode 100644 index 00000000..137ce7c1 --- /dev/null +++ b/abc70930/src/misc/espresso/sparse.c @@ -0,0 +1,146 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + module: sparse.c + + make_sparse is a last-step cleanup to reduce the total number + of literals in the cover. + + This is done by reducing the "sparse" variables (using a modified + version of irredundant rather than reduce), followed by expanding + the "dense" variables (using modified version of expand). +*/ + +#include "espresso.h" + +pcover make_sparse(F, D, R) +pcover F, D, R; +{ + cost_t cost, best_cost; + + cover_cost(F, &best_cost); + + do { + EXECUTE(F = mv_reduce(F, D), MV_REDUCE_TIME, F, cost); + if (cost.total == best_cost.total) + break; + copy_cost(&cost, &best_cost); + + EXECUTE(F = expand(F, R, TRUE), RAISE_IN_TIME, F, cost); + if (cost.total == best_cost.total) + break; + copy_cost(&cost, &best_cost); + } while (force_irredundant); + + return F; +} + +/* + mv_reduce -- perform an "optimal" reduction of the variables which + we desire to be sparse + + This could be done using "reduce" and then saving just the desired + part of the reduction. Instead, this version uses IRRED to find + which cubes of an output are redundant. Note that this gets around + the cube-ordering problem. + + In normal use, it is expected that the cover is irredundant and + hence no cubes will be reduced to the empty cube (however, this is + checked for and such cubes will be deleted) +*/ + +pcover +mv_reduce(F, D) +pcover F, D; +{ + register int i, var; + register pcube p, p1, last; + int index; + pcover F1, D1; + pcube *F_cube_table; + + /* loop for each multiple-valued variable */ + for(var = 0; var < cube.num_vars; var++) { + + if (cube.sparse[var]) { + + /* loop for each part of the variable */ + for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { + + /* remember mapping of F1 cubes back to F cubes */ + F_cube_table = ALLOC(pcube, F->count); + + /* 'cofactor' against part #i of variable #var */ + F1 = new_cover(F->count); + foreach_set(F, last, p) { + if (is_in_set(p, i)) { + F_cube_table[F1->count] = p; + p1 = GETSET(F1, F1->count++); + (void) set_diff(p1, p, cube.var_mask[var]); + set_insert(p1, i); + } + } + + /* 'cofactor' against part #i of variable #var */ + /* not really necessary -- just more efficient ? */ + D1 = new_cover(D->count); + foreach_set(D, last, p) { + if (is_in_set(p, i)) { + p1 = GETSET(D1, D1->count++); + (void) set_diff(p1, p, cube.var_mask[var]); + set_insert(p1, i); + } + } + + mark_irredundant(F1, D1); + + /* now remove part i from cubes which are redundant */ + index = 0; + foreach_set(F1, last, p1) { + if (! TESTP(p1, ACTIVE)) { + p = F_cube_table[index]; + + /* don't reduce a variable which is full + * (unless it is the output variable) + */ + if (var == cube.num_vars-1 || + ! setp_implies(cube.var_mask[var], p)) { + set_remove(p, i); + } + RESET(p, PRIME); + } + index++; + } + + free_cover(F1); + free_cover(D1); + FREE(F_cube_table); + } + } + } + + /* Check if any cubes disappeared */ + (void) sf_active(F); + for(var = 0; var < cube.num_vars; var++) { + if (cube.sparse[var]) { + foreach_active_set(F, last, p) { + if (setp_disjoint(p, cube.var_mask[var])) { + RESET(p, ACTIVE); + F->active_count--; + } + } + } + } + + if (F->count != F->active_count) { + F = sf_inactive(F); + } + return F; +} diff --git a/abc70930/src/misc/espresso/sparse.h b/abc70930/src/misc/espresso/sparse.h new file mode 100644 index 00000000..212a32ed --- /dev/null +++ b/abc70930/src/misc/espresso/sparse.h @@ -0,0 +1,135 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +#ifndef SPARSE_H +#define SPARSE_H + +/* + * sparse.h -- sparse matrix package header file + */ + +typedef struct sm_element_struct sm_element; +typedef struct sm_row_struct sm_row; +typedef struct sm_col_struct sm_col; +typedef struct sm_matrix_struct sm_matrix; + + +/* + * sparse matrix element + */ +struct sm_element_struct { + int row_num; /* row number of this element */ + int col_num; /* column number of this element */ + sm_element *next_row; /* next row in this column */ + sm_element *prev_row; /* previous row in this column */ + sm_element *next_col; /* next column in this row */ + sm_element *prev_col; /* previous column in this row */ + char *user_word; /* user-defined word */ +}; + + +/* + * row header + */ +struct sm_row_struct { + int row_num; /* the row number */ + int length; /* number of elements in this row */ + int flag; /* user-defined word */ + sm_element *first_col; /* first element in this row */ + sm_element *last_col; /* last element in this row */ + sm_row *next_row; /* next row (in sm_matrix linked list) */ + sm_row *prev_row; /* previous row (in sm_matrix linked list) */ + char *user_word; /* user-defined word */ +}; + + +/* + * column header + */ +struct sm_col_struct { + int col_num; /* the column number */ + int length; /* number of elements in this column */ + int flag; /* user-defined word */ + sm_element *first_row; /* first element in this column */ + sm_element *last_row; /* last element in this column */ + sm_col *next_col; /* next column (in sm_matrix linked list) */ + sm_col *prev_col; /* prev column (in sm_matrix linked list) */ + char *user_word; /* user-defined word */ +}; + + +/* + * A sparse matrix + */ +struct sm_matrix_struct { + sm_row **rows; /* pointer to row headers (by row #) */ + int rows_size; /* alloc'ed size of above array */ + sm_col **cols; /* pointer to column headers (by col #) */ + int cols_size; /* alloc'ed size of above array */ + sm_row *first_row; /* first row (linked list of all rows) */ + sm_row *last_row; /* last row (linked list of all rows) */ + int nrows; /* number of rows */ + sm_col *first_col; /* first column (linked list of columns) */ + sm_col *last_col; /* last column (linked list of columns) */ + int ncols; /* number of columns */ + char *user_word; /* user-defined word */ +}; + + +#define sm_get_col(A, colnum) \ + (((colnum) >= 0 && (colnum) < (A)->cols_size) ? \ + (A)->cols[colnum] : (sm_col *) 0) + +#define sm_get_row(A, rownum) \ + (((rownum) >= 0 && (rownum) < (A)->rows_size) ? \ + (A)->rows[rownum] : (sm_row *) 0) + +#define sm_foreach_row(A, prow) \ + for(prow = A->first_row; prow != 0; prow = prow->next_row) + +#define sm_foreach_col(A, pcol) \ + for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) + +#define sm_foreach_row_element(prow, p) \ + for(p = prow->first_col; p != 0; p = p->next_col) + +#define sm_foreach_col_element(pcol, p) \ + for(p = pcol->first_row; p != 0; p = p->next_row) + +#define sm_put(x, val) \ + (x->user_word = (char *) val) + +#define sm_get(type, x) \ + ((type) (x->user_word)) + +extern sm_matrix *sm_alloc(), *sm_alloc_size(), *sm_dup(); +extern void sm_free(), sm_delrow(), sm_delcol(), sm_resize(); +extern void sm_write(), sm_print(), sm_dump(), sm_cleanup(); +extern void sm_copy_row(), sm_copy_col(); +extern void sm_remove(), sm_remove_element(); +extern sm_element *sm_insert(), *sm_find(); +extern sm_row *sm_longest_row(); +extern sm_col *sm_longest_col(); +extern int sm_read(), sm_read_compressed(); + +extern sm_row *sm_row_alloc(), *sm_row_dup(), *sm_row_and(); +extern void sm_row_free(), sm_row_remove(), sm_row_print(); +extern sm_element *sm_row_insert(), *sm_row_find(); +extern int sm_row_contains(), sm_row_intersects(); +extern int sm_row_compare(), sm_row_hash(); + +extern sm_col *sm_col_alloc(), *sm_col_dup(), *sm_col_and(); +extern void sm_col_free(), sm_col_remove(), sm_col_print(); +extern sm_element *sm_col_insert(), *sm_col_find(); +extern int sm_col_contains(), sm_col_intersects(); +extern int sm_col_compare(), sm_col_hash(); + +extern int sm_row_dominance(), sm_col_dominance(), sm_block_partition(); + +#endif diff --git a/abc70930/src/misc/espresso/sparse_int.h b/abc70930/src/misc/espresso/sparse_int.h new file mode 100644 index 00000000..49b2509a --- /dev/null +++ b/abc70930/src/misc/espresso/sparse_int.h @@ -0,0 +1,121 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +//#include "port.h" +//#include "utility.h" +#include "sparse.h" + +#include "util_hack.h" // added + + + +/* + * sorted, double-linked list insertion + * + * type: object type + * + * first, last: fields (in header) to head and tail of the list + * count: field (in header) of length of the list + * + * next, prev: fields (in object) to link next and previous objects + * value: field (in object) which controls the order + * + * newval: value field for new object + * e: an object to use if insertion needed (set to actual value used) + */ + +#define sorted_insert(type, first, last, count, next, prev, value, newval, e) \ + if (last == 0) { \ + e->value = newval; \ + first = e; \ + last = e; \ + e->next = 0; \ + e->prev = 0; \ + count++; \ + } else if (last->value < newval) { \ + e->value = newval; \ + last->next = e; \ + e->prev = last; \ + last = e; \ + e->next = 0; \ + count++; \ + } else if (first->value > newval) { \ + e->value = newval; \ + first->prev = e; \ + e->next = first; \ + first = e; \ + e->prev = 0; \ + count++; \ + } else { \ + type *p; \ + for(p = first; p->value < newval; p = p->next) \ + ; \ + if (p->value > newval) { \ + e->value = newval; \ + p = p->prev; \ + p->next->prev = e; \ + e->next = p->next; \ + p->next = e; \ + e->prev = p; \ + count++; \ + } else { \ + e = p; \ + } \ + } + + +/* + * double linked-list deletion + */ +#define dll_unlink(p, first, last, next, prev, count) { \ + if (p->prev == 0) { \ + first = p->next; \ + } else { \ + p->prev->next = p->next; \ + } \ + if (p->next == 0) { \ + last = p->prev; \ + } else { \ + p->next->prev = p->prev; \ + } \ + count--; \ +} + + +#ifdef FAST_AND_LOOSE +extern sm_element *sm_element_freelist; +extern sm_row *sm_row_freelist; +extern sm_col *sm_col_freelist; + +#define sm_element_alloc(newobj) \ + if (sm_element_freelist == NIL(sm_element)) { \ + newobj = ALLOC(sm_element, 1); \ + } else { \ + newobj = sm_element_freelist; \ + sm_element_freelist = sm_element_freelist->next_col; \ + } \ + newobj->user_word = NIL(char); \ + +#define sm_element_free(e) \ + (e->next_col = sm_element_freelist, sm_element_freelist = e) + +#else + +#define sm_element_alloc(newobj) \ + newobj = ALLOC(sm_element, 1); \ + newobj->user_word = NIL(char); +#define sm_element_free(e) \ + FREE(e) +#endif + + +extern void sm_row_remove_element(); +extern void sm_col_remove_element(); + +/* LINTLIBRARY */ diff --git a/abc70930/src/misc/espresso/unate.c b/abc70930/src/misc/espresso/unate.c new file mode 100644 index 00000000..7f6a1524 --- /dev/null +++ b/abc70930/src/misc/espresso/unate.c @@ -0,0 +1,441 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + * unate.c -- routines for dealing with unate functions + */ + +#include "espresso.h" + +static pset_family abs_covered(); +static pset_family abs_covered_many(); +static int abs_select_restricted(); + +pcover map_cover_to_unate(T) +pcube *T; +{ + register unsigned int word_test, word_set, bit_test, bit_set; + register pcube p, pA; + pset_family A; + pcube *T1; + int ncol, i; + + A = sf_new(CUBELISTSIZE(T), cdata.vars_unate); + A->count = CUBELISTSIZE(T); + foreachi_set(A, i, p) { + (void) set_clear(p, A->sf_size); + } + ncol = 0; + + for(i = 0; i < cube.size; i++) { + if (cdata.part_zeros[i] > 0) { + assert(ncol <= cdata.vars_unate); + + /* Copy a column from T to A */ + word_test = WHICH_WORD(i); + bit_test = 1 << WHICH_BIT(i); + word_set = WHICH_WORD(ncol); + bit_set = 1 << WHICH_BIT(ncol); + + pA = A->data; + for(T1 = T+2; (p = *T1++) != 0; ) { + if ((p[word_test] & bit_test) == 0) { + pA[word_set] |= bit_set; + } + pA += A->wsize; + } + + ncol++; + } + } + + return A; +} + +pcover map_unate_to_cover(A) +pset_family A; +{ + register int i, ncol, lp; + register pcube p, pB; + int var, nunate, *unate; + pcube last; + pset_family B; + + B = sf_new(A->count, cube.size); + B->count = A->count; + + /* Find the unate variables */ + unate = ALLOC(int, cube.num_vars); + nunate = 0; + for(var = 0; var < cube.num_vars; var++) { + if (cdata.is_unate[var]) { + unate[nunate++] = var; + } + } + + /* Loop for each set of A */ + pB = B->data; + foreach_set(A, last, p) { + + /* Initialize this set of B */ + INLINEset_fill(pB, cube.size); + + /* Now loop for the unate variables; if the part is in A, + * then this variable of B should be a single 1 in the unate + * part. + */ + for(ncol = 0; ncol < nunate; ncol++) { + if (is_in_set(p, ncol)) { + lp = cube.last_part[unate[ncol]]; + for(i = cube.first_part[unate[ncol]]; i <= lp; i++) { + if (cdata.part_zeros[i] == 0) { + set_remove(pB, i); + } + } + } + } + pB += B->wsize; + } + + FREE(unate); + return B; +} + +/* + * unate_compl + */ + +pset_family unate_compl(A) +pset_family A; +{ + register pset p, last; + + /* Make sure A is single-cube containment minimal */ +/* A = sf_rev_contain(A);*/ + + foreach_set(A, last, p) { + PUTSIZE(p, set_ord(p)); + } + + /* Recursively find the complement */ + A = unate_complement(A); + + /* Now, we can guarantee a minimal result by containing the result */ + A = sf_rev_contain(A); + return A; +} + + +/* + * Assume SIZE(p) records the size of each set + */ +pset_family unate_complement(A) +pset_family A; /* disposes of A */ +{ + pset_family Abar; + register pset p, p1, x_code_restrict; + register int i; + int max_i, min_set_ord, j; + + /* Check for no sets in the matrix -- complement is the universe */ + if (A->count == 0) { + sf_free(A); + Abar = sf_new(1, A->sf_size); + (void) set_clear(GETSET(Abar, Abar->count++), A->sf_size); + + /* Check for a single set in the maxtrix -- compute de Morgan complement */ + } else if (A->count == 1) { + p = A->data; + Abar = sf_new(A->sf_size, A->sf_size); + for(i = 0; i < A->sf_size; i++) { + if (is_in_set(p, i)) { + p1 = set_clear(GETSET(Abar, Abar->count++), A->sf_size); + set_insert(p1, i); + } + } + sf_free(A); + + } else { + + /* Select splitting variable as the variable which belongs to a set + * of the smallest size, and which has greatest column count + */ + x_code_restrict = set_new(A->sf_size); + min_set_ord = A->sf_size + 1; + foreachi_set(A, i, p) { + if (SIZE(p) < min_set_ord) { + set_copy(x_code_restrict, p); + min_set_ord = SIZE(p); + } else if (SIZE(p) == min_set_ord) { + set_or(x_code_restrict, x_code_restrict, p); + } + } + + /* Check for no data (shouldn't happen ?) */ + if (min_set_ord == 0) { + A->count = 0; + Abar = A; + + /* Check for "essential" columns */ + } else if (min_set_ord == 1) { + Abar = unate_complement(abs_covered_many(A, x_code_restrict)); + sf_free(A); + foreachi_set(Abar, i, p) { + set_or(p, p, x_code_restrict); + } + + /* else, recur as usual */ + } else { + max_i = abs_select_restricted(A, x_code_restrict); + + /* Select those rows of A which are not covered by max_i, + * recursively find all minimal covers of these rows, and + * then add back in max_i + */ + Abar = unate_complement(abs_covered(A, max_i)); + foreachi_set(Abar, i, p) { + set_insert(p, max_i); + } + + /* Now recur on A with all zero's on column max_i */ + foreachi_set(A, i, p) { + if (is_in_set(p, max_i)) { + set_remove(p, max_i); + j = SIZE(p) - 1; + PUTSIZE(p, j); + } + } + + Abar = sf_append(Abar, unate_complement(A)); + } + set_free(x_code_restrict); + } + + return Abar; +} + +pset_family exact_minimum_cover(T) +IN pset_family T; +{ + register pset p, last, p1; + register int i, n; + int lev, lvl; + pset nlast; + pset_family temp; + long start = ptime(); + struct { + pset_family sf; + int level; + } stack[32]; /* 32 suffices for 2 ** 32 cubes ! */ + + if (T->count <= 0) + return sf_new(1, T->sf_size); + for(n = T->count, lev = 0; n != 0; n >>= 1, lev++) ; + + /* A simple heuristic ordering */ + T = lex_sort(sf_save(T)); + + /* Push a full set on the stack to get things started */ + n = 1; + stack[0].sf = sf_new(1, T->sf_size); + stack[0].level = lev; + set_fill(GETSET(stack[0].sf, stack[0].sf->count++), T->sf_size); + + nlast = GETSET(T, T->count - 1); + foreach_set(T, last, p) { + + /* "unstack" the set into a family */ + temp = sf_new(set_ord(p), T->sf_size); + for(i = 0; i < T->sf_size; i++) + if (is_in_set(p, i)) { + p1 = set_fill(GETSET(temp, temp->count++), T->sf_size); + set_remove(p1, i); + } + stack[n].sf = temp; + stack[n++].level = lev; + + /* Pop the stack and perform (leveled) intersections */ + while (n > 1 && (stack[n-1].level==stack[n-2].level || p == nlast)) { + temp = unate_intersect(stack[n-1].sf, stack[n-2].sf, FALSE); + lvl = MIN(stack[n-1].level, stack[n-2].level) - 1; + if (debug & MINCOV && lvl < 10) { + printf("# EXACT_MINCOV[%d]: %4d = %4d x %4d, time = %s\n", + lvl, temp->count, stack[n-1].sf->count, + stack[n-2].sf->count, print_time(ptime() - start)); + (void) fflush(stdout); + } + sf_free(stack[n-2].sf); + sf_free(stack[n-1].sf); + stack[n-2].sf = temp; + stack[n-2].level = lvl; + n--; + } + } + + temp = stack[0].sf; + p1 = set_fill(set_new(T->sf_size), T->sf_size); + foreach_set(temp, last, p) + INLINEset_diff(p, p1, p); + set_free(p1); + if (debug & MINCOV1) { + printf("MINCOV: family of all minimal coverings is\n"); + sf_print(temp); + } + sf_free(T); /* this is the copy of T we made ... */ + return temp; +} + +/* + * unate_intersect -- intersect two unate covers + * + * If largest_only is TRUE, then only the largest cube(s) are returned + */ + +#define MAGIC 500 /* save 500 cubes before containment */ + +pset_family unate_intersect(A, B, largest_only) +pset_family A, B; +bool largest_only; +{ + register pset pi, pj, lasti, lastj, pt; + pset_family T, Tsave; + bool save; + int maxord, ord; + + /* How large should each temporary result cover be ? */ + T = sf_new(MAGIC, A->sf_size); + Tsave = NULL; + maxord = 0; + pt = T->data; + + /* Form pairwise intersection of each set of A with each cube of B */ + foreach_set(A, lasti, pi) { + + foreach_set(B, lastj, pj) { + + save = set_andp(pt, pi, pj); + + /* Check if we want the largest only */ + if (save && largest_only) { + if ((ord = set_ord(pt)) > maxord) { + /* discard Tsave and T */ + if (Tsave != NULL) { + sf_free(Tsave); + Tsave = NULL; + } + pt = T->data; + T->count = 0; + /* Re-create pt (which was just thrown away) */ + (void) set_and(pt, pi, pj); + maxord = ord; + } else if (ord < maxord) { + save = FALSE; + } + } + + if (save) { + if (++T->count >= T->capacity) { + T = sf_contain(T); + Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T); + T = sf_new(MAGIC, A->sf_size); + pt = T->data; + } else { + pt += T->wsize; + } + } + } + } + + + /* Contain the final result and merge it into Tsave */ + T = sf_contain(T); + Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T); + + return Tsave; +} + +/* + * abs_covered -- after selecting a new column for the selected set, + * create a new matrix which is only those rows which are still uncovered + */ +static pset_family +abs_covered(A, pick) +pset_family A; +register int pick; +{ + register pset last, p, pdest; + register pset_family Aprime; + + Aprime = sf_new(A->count, A->sf_size); + pdest = Aprime->data; + foreach_set(A, last, p) + if (! is_in_set(p, pick)) { + INLINEset_copy(pdest, p); + Aprime->count++; + pdest += Aprime->wsize; + } + return Aprime; +} + + +/* + * abs_covered_many -- after selecting many columns for ther selected set, + * create a new matrix which is only those rows which are still uncovered + */ +static pset_family +abs_covered_many(A, pick_set) +pset_family A; +register pset pick_set; +{ + register pset last, p, pdest; + register pset_family Aprime; + + Aprime = sf_new(A->count, A->sf_size); + pdest = Aprime->data; + foreach_set(A, last, p) + if (setp_disjoint(p, pick_set)) { + INLINEset_copy(pdest, p); + Aprime->count++; + pdest += Aprime->wsize; + } + return Aprime; +} + + +/* + * abs_select_restricted -- select the column of maximum column count which + * also belongs to the set "x_code_restrict"; weight each column of a set as + * 1 / (set_ord(p) - 1). + */ +static int +abs_select_restricted(A, x_code_restrict) +pset_family A; +pset x_code_restrict; +{ + register int i, best_var, best_count, *count; + + /* Sum the elements in these columns */ + count = sf_count_restricted(A, x_code_restrict); + + /* Find which variable has maximum weight */ + best_var = -1; + best_count = 0; + for(i = 0; i < A->sf_size; i++) { + if (count[i] > best_count) { + best_var = i; + best_count = count[i]; + } + } + FREE(count); + + if (best_var == -1) + fatal("abs_select_restricted: should not have best_var == -1"); + + return best_var; +} diff --git a/abc70930/src/misc/espresso/util_old.h b/abc70930/src/misc/espresso/util_old.h new file mode 100644 index 00000000..5451cbe9 --- /dev/null +++ b/abc70930/src/misc/espresso/util_old.h @@ -0,0 +1,301 @@ +/* + * Revision Control Information + * + * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/util/RCS/util.h,v $ + * $Author: sis $ + * $Revision: 1.9 $ + * $Date: 1993/06/07 21:04:07 $ + * + */ +#ifndef UTIL_H +#define UTIL_H + +#if defined(_IBMR2) +#ifndef _POSIX_SOURCE +#define _POSIX_SOURCE /* Argh! IBM strikes again */ +#endif +#ifndef _ALL_SOURCE +#define _ALL_SOURCE /* Argh! IBM strikes again */ +#endif +#ifndef _ANSI_C_SOURCE +#define _ANSI_C_SOURCE /* Argh! IBM strikes again */ +#endif +#endif + +#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__) +#include +#endif + +#if defined(_IBMR2) && !defined(__STDC__) +#define _BSD +#endif + +#include "ansi.h" /* since some files don't include sis.h */ + +/* This was taken out and defined at compile time in the SIS Makefile + that uses the OctTools. When the OctTools are used, USE_MM is defined, + because the OctTools contain libmm.a. Otherwise, USE_MM is not defined, + since the mm package is not distributed with SIS, only with Oct. */ + +/* #define USE_MM */ /* choose libmm.a as the memory allocator */ + +#define NIL(type) ((type *) 0) + +#ifdef USE_MM +/* + * assumes the memory manager is libmm.a + * - allows malloc(0) or realloc(obj, 0) + * - catches out of memory (and calls MMout_of_memory()) + * - catch free(0) and realloc(0, size) in the macros + */ +#define ALLOC(type, num) \ + ((type *) malloc(sizeof(type) * (num))) +#define REALLOC(type, obj, num) \ + (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num))) +#define FREE(obj) \ + ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#else +/* + * enforce strict semantics on the memory allocator + * - when in doubt, delete the '#define USE_MM' above + */ +#define ALLOC(type, num) \ + ((type *) MMalloc((long) sizeof(type) * (long) (num))) +#define REALLOC(type, obj, num) \ + ((type *) MMrealloc((char *) (obj), (long) sizeof(type) * (long) (num))) +#define FREE(obj) \ + ((obj) ? (free((void *) (obj)), (obj) = 0) : 0) +#endif + + +/* Ultrix (and SABER) have 'fixed' certain functions which used to be int */ +#if defined(ultrix) || defined(SABER) || defined(aiws) || defined(__hpux) || defined(__STDC__) || defined(apollo) +#define VOID_HACK void +#else +#define VOID_HACK int +#endif + + +/* No machines seem to have much of a problem with these */ +#include +#include + + +/* Some machines fail to define some functions in stdio.h */ +#if !defined(__STDC__) && !defined(sprite) && !defined(_IBMR2) && !defined(__osf__) +extern FILE *popen(), *tmpfile(); +extern int pclose(); +#ifndef clearerr /* is a macro on many machines, but not all */ +extern VOID_HACK clearerr(); +#endif +#ifndef rewind +extern VOID_HACK rewind(); +#endif +#endif + +#ifndef PORT_H +#include +#include +#if defined(ultrix) +#if defined(_SIZE_T_) +#define ultrix4 +#else +#if defined(SIGLOST) +#define ultrix3 +#else +#define ultrix2 +#endif +#endif +#endif +#endif + +/* most machines don't give us a header file for these */ +#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__) || defined(sunos4) || defined(__hpux) +#include +#if defined(__hpux) +#include /* For perror() defininition */ +#endif /* __hpux */ +#else +extern VOID_HACK abort(), free(), exit(), perror(); +extern char *getenv(); +#ifdef ultrix4 +extern void *malloc(), *realloc(), *calloc(); +#else +extern char *malloc(), *realloc(), *calloc(); +#endif +#if defined(aiws) +extern int sprintf(); +#else +#ifndef _IBMR2 +extern char *sprintf(); +#endif +#endif +extern int system(); +extern double atof(); +#endif + +#ifndef PORT_H +#if defined(ultrix3) || defined(sunos4) || defined(_IBMR2) || defined(__STDC__) +#define SIGNAL_FN void +#else +/* sequent, ultrix2, 4.3BSD (vax, hp), sunos3 */ +#define SIGNAL_FN int +#endif +#endif + +/* some call it strings.h, some call it string.h; others, also have memory.h */ +#if defined(__STDC__) || defined(sprite) +#include +#else +#if defined(ultrix4) || defined(__hpux) +#include +#else +#if defined(_IBMR2) || defined(__osf__) +#include +#include +#else +/* ANSI C string.h -- 1/11/88 Draft Standard */ +/* ugly, awful hack */ +#ifndef PORT_H +extern char *strcpy(), *strncpy(), *strcat(), *strncat(), *strerror(); +extern char *strpbrk(), *strtok(), *strchr(), *strrchr(), *strstr(); +extern int strcoll(), strxfrm(), strncmp(), strlen(), strspn(), strcspn(); +extern char *memmove(), *memccpy(), *memchr(), *memcpy(), *memset(); +extern int memcmp(), strcmp(); +#endif +#endif +#endif +#endif + +/* a few extras */ +#if defined(__hpux) +#define random() lrand48() +#define srandom(a) srand48(a) +#define bzero(a,b) memset(a, 0, b) +#else +#if !defined(__osf__) && !defined(linux) +/* these are defined as macros in stdlib.h */ +extern VOID_HACK srandom(); +extern long random(); +#endif +#endif + +/* code from sis-1.3 commented out below +#if defined(__STDC__) || defined(sprite) +#include +#else +#ifndef NDEBUG +#define assert(ex) {\ + if (! (ex)) {\ + (void) fprintf(stderr,\ + "Assertion failed: file %s, line %d\n\"%s\"\n",\ + __FILE__, __LINE__, "ex");\ + (void) fflush(stdout);\ + abort();\ + }\ +} +#else +#define assert(ex) {ex;} +#endif +#endif +*/ + + /* Sunil 5/3/97: + sis-1.4: dont let the assert call go to the OS, since + much of the code in SIS has actual computation done in + the assert function. %$#$@@#! The OS version of assert + will do nothing if NDEBUG is set. We cant let that happen... + */ +# ifdef NDEBUG +# define assert(ex) {ex;} +# else +# define assert(ex) {\ + if (! (ex)) {\ + (void) fprintf(stderr,\ + "Assertion failed: file %s, line %d\n\"%s\"\n",\ + __FILE__, __LINE__, "ex");\ + (void) fflush(stdout);\ + abort();\ + }\ +} +# endif + + +#define fail(why) {\ + (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\ + __FILE__, __LINE__, why);\ + (void) fflush(stdout);\ + abort();\ +} + + +#ifdef lint +#undef putc /* correct lint '_flsbuf' bug */ +#undef ALLOC /* allow for lint -h flag */ +#undef REALLOC +#define ALLOC(type, num) (((type *) 0) + (num)) +#define REALLOC(type, obj, num) ((obj) + (num)) +#endif + +/* +#if !defined(__osf__) +#define MAXPATHLEN 1024 +#endif +*/ + +/* These arguably do NOT belong in util.h */ +#ifndef ABS +#define ABS(a) ((a) < 0 ? -(a) : (a)) +#endif +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + + +#ifndef USE_MM +EXTERN void MMout_of_memory ARGS((long)); +EXTERN char *MMalloc ARGS((long)); +EXTERN char *MMrealloc ARGS((char *, long)); +EXTERN void MMfree ARGS((char *)); +#endif + +EXTERN void util_print_cpu_stats ARGS((FILE *)); +EXTERN long util_cpu_time ARGS((void)); +EXTERN void util_getopt_reset ARGS((void)); +EXTERN int util_getopt ARGS((int, char **, char *)); +EXTERN char *util_path_search ARGS((char *)); +EXTERN char *util_file_search ARGS((char *, char *, char *)); +EXTERN int util_pipefork ARGS((char **, FILE **, FILE **, int *)); +EXTERN char *util_print_time ARGS((long)); +EXTERN int util_save_image ARGS((char *, char *)); +EXTERN char *util_strsav ARGS((char *)); +EXTERN int util_do_nothing ARGS((void)); +EXTERN char *util_tilde_expand ARGS((char *)); +EXTERN char *util_tempnam ARGS((char *, char *)); +EXTERN FILE *util_tmpfile ARGS((void)); +EXTERN long getSoftDataLimit(); + +#define ptime() util_cpu_time() +#define print_time(t) util_print_time(t) + +/* util_getopt() global variables (ack !) */ +extern int util_optind; +extern char *util_optarg; + +#include +#ifndef HUGE_VAL +#ifndef HUGE +#define HUGE 8.9884656743115790e+307 +#endif +#define HUGE_VAL HUGE +#endif +#ifndef MAXINT +#define MAXINT (1 << 30) +#endif + +#include +#endif diff --git a/abc70930/src/misc/espresso/verify.c b/abc70930/src/misc/espresso/verify.c new file mode 100644 index 00000000..64342787 --- /dev/null +++ b/abc70930/src/misc/espresso/verify.c @@ -0,0 +1,193 @@ +/* + * Revision Control Information + * + * $Source$ + * $Author$ + * $Revision$ + * $Date$ + * + */ +/* + */ + +#include "espresso.h" + +/* + * verify -- check that all minterms of F are contained in (Fold u Dold) + * and that all minterms of Fold are contained in (F u Dold). + */ +bool verify(F, Fold, Dold) +pcover F, Fold, Dold; +{ + pcube p, last, *FD; + bool verify_error = FALSE; + + /* Make sure the function didn't grow too large */ + FD = cube2list(Fold, Dold); + foreach_set(F, last, p) + if (! cube_is_covered(FD, p)) { + printf("some minterm in F is not covered by Fold u Dold\n"); + verify_error = TRUE; + if (verbose_debug) printf("%s\n", pc1(p)); else break; + } + free_cubelist(FD); + + /* Make sure minimized function covers the original function */ + FD = cube2list(F, Dold); + foreach_set(Fold, last, p) + if (! cube_is_covered(FD, p)) { + printf("some minterm in Fold is not covered by F u Dold\n"); + verify_error = TRUE; + if (verbose_debug) printf("%s\n", pc1(p)); else break; + } + free_cubelist(FD); + + return verify_error; +} + + + +/* + * PLA_verify -- verify that two PLA's are identical + * + * If names are given, row and column permutations are done to make + * the comparison meaningful. + * + */ +bool PLA_verify(PLA1, PLA2) +pPLA PLA1, PLA2; +{ + /* Check if both have names given; if so, attempt to permute to + * match the names + */ + if (PLA1->label != NULL && PLA1->label[0] != NULL && + PLA2->label != NULL && PLA2->label[0] != NULL) { + PLA_permute(PLA1, PLA2); + } else { + (void) fprintf(stderr, "Warning: cannot permute columns without names\n"); + return TRUE; + } + + if (PLA1->F->sf_size != PLA2->F->sf_size) { + (void) fprintf(stderr, "PLA_verify: PLA's are not the same size\n"); + return TRUE; + } + + return verify(PLA2->F, PLA1->F, PLA1->D); +} + + + +/* + * Permute the columns of PLA1 so that they match the order of PLA2 + * Discard any columns of PLA1 which are not in PLA2 + * Association is strictly by the names of the columns of the cover. + */ +PLA_permute(PLA1, PLA2) +pPLA PLA1, PLA2; +{ + register int i, j, *permute, npermute; + register char *labi; + char **label; + + /* determine which columns of PLA1 to save, and place these in the list + * "permute"; the order in this list is the final output order + */ + npermute = 0; + permute = ALLOC(int, PLA2->F->sf_size); + for(i = 0; i < PLA2->F->sf_size; i++) { + labi = PLA2->label[i]; + for(j = 0; j < PLA1->F->sf_size; j++) { + if (strcmp(labi, PLA1->label[j]) == 0) { + permute[npermute++] = j; + break; + } + } + } + + /* permute columns */ + if (PLA1->F != NULL) { + PLA1->F = sf_permute(PLA1->F, permute, npermute); + } + if (PLA1->R != NULL) { + PLA1->R = sf_permute(PLA1->R, permute, npermute); + } + if (PLA1->D != NULL) { + PLA1->D = sf_permute(PLA1->D, permute, npermute); + } + + /* permute the labels */ + label = ALLOC(char *, cube.size); + for(i = 0; i < npermute; i++) { + label[i] = PLA1->label[permute[i]]; + } + for(i = npermute; i < cube.size; i++) { + label[i] = NULL; + } + FREE(PLA1->label); + PLA1->label = label; + + FREE(permute); +} + + + +/* + * check_consistency -- test that the ON-set, OFF-set and DC-set form + * a partition of the boolean space. + */ +bool check_consistency(PLA) +pPLA PLA; +{ + bool verify_error = FALSE; + pcover T; + + T = cv_intersect(PLA->F, PLA->D); + if (T->count == 0) + printf("ON-SET and DC-SET are disjoint\n"); + else { + printf("Some minterm(s) belong to both the ON-SET and DC-SET !\n"); + if (verbose_debug) + cprint(T); + verify_error = TRUE; + } + (void) fflush(stdout); + free_cover(T); + + T = cv_intersect(PLA->F, PLA->R); + if (T->count == 0) + printf("ON-SET and OFF-SET are disjoint\n"); + else { + printf("Some minterm(s) belong to both the ON-SET and OFF-SET !\n"); + if (verbose_debug) + cprint(T); + verify_error = TRUE; + } + (void) fflush(stdout); + free_cover(T); + + T = cv_intersect(PLA->D, PLA->R); + if (T->count == 0) + printf("DC-SET and OFF-SET are disjoint\n"); + else { + printf("Some minterm(s) belong to both the OFF-SET and DC-SET !\n"); + if (verbose_debug) + cprint(T); + verify_error = TRUE; + } + (void) fflush(stdout); + free_cover(T); + + if (tautology(cube3list(PLA->F, PLA->D, PLA->R))) + printf("Union of ON-SET, OFF-SET and DC-SET is the universe\n"); + else { + T = complement(cube3list(PLA->F, PLA->D, PLA->R)); + printf("There are minterms left unspecified !\n"); + if (verbose_debug) + cprint(T); + verify_error = TRUE; + free_cover(T); + } + (void) fflush(stdout); + return verify_error; +} diff --git a/abc70930/src/misc/extra/extra.h b/abc70930/src/misc/extra/extra.h new file mode 100644 index 00000000..314257a2 --- /dev/null +++ b/abc70930/src/misc/extra/extra.h @@ -0,0 +1,626 @@ +/**CFile**************************************************************** + + FileName [extra.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Various reusable software utilities.] + + Description [This library contains a number of operators and + traversal routines developed to extend the functionality of + CUDD v.2.3.x, by Fabio Somenzi (http://vlsi.colorado.edu/~fabio/) + To compile your code with the library, #include "extra.h" + in your source files and link your project to CUDD and this + library. Use the library at your own risk and with caution. + Note that debugging of some operators still continues.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extra.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __EXTRA_H__ +#define __EXTRA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +/*---------------------------------------------------------------------------*/ +/* Nested includes */ +/*---------------------------------------------------------------------------*/ + +// this include should be the first one in the list +// it is used to catch memory leaks on Windows +#include "leaks.h" + +#include +#include +#include +#include +#include +#include "st.h" +#include "cuddInt.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +typedef unsigned char uint8; +typedef unsigned short uint16; +typedef unsigned int uint32; +#ifdef WIN32 +typedef unsigned __int64 uint64; +#else +typedef unsigned long long uint64; +#endif + +/* constants of the manager */ +#define b0 Cudd_Not((dd)->one) +#define b1 (dd)->one +#define z0 (dd)->zero +#define z1 (dd)->one +#define a0 (dd)->zero +#define a1 (dd)->one + +// hash key macros +#define hashKey1(a,TSIZE) \ +((unsigned)(a) % TSIZE) + +#define hashKey2(a,b,TSIZE) \ +(((unsigned)(a) + (unsigned)(b) * DD_P1) % TSIZE) + +#define hashKey3(a,b,c,TSIZE) \ +(((((unsigned)(a) + (unsigned)(b)) * DD_P1 + (unsigned)(c)) * DD_P2 ) % TSIZE) + +#define hashKey4(a,b,c,d,TSIZE) \ +((((((unsigned)(a) + (unsigned)(b)) * DD_P1 + (unsigned)(c)) * DD_P2 + \ + (unsigned)(d)) * DD_P3) % TSIZE) + +#define hashKey5(a,b,c,d,e,TSIZE) \ +(((((((unsigned)(a) + (unsigned)(b)) * DD_P1 + (unsigned)(c)) * DD_P2 + \ + (unsigned)(d)) * DD_P3 + (unsigned)(e)) * DD_P1) % TSIZE) + +#ifndef PRT +#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) +#define PRTn(a,t) printf("%s = ", (a)); printf("%6.2f sec ", (float)(t)/(float)(CLOCKS_PER_SEC)) +#endif + +#ifndef PRTP +#define PRTP(a,t,T) printf("%s = ", (a)); printf("%6.2f sec (%6.2f %%)\n", (float)(t)/(float)(CLOCKS_PER_SEC), (T)? 100.0*(t)/(T) : 0.0) +#endif + +/*===========================================================================*/ +/* Various Utilities */ +/*===========================================================================*/ + +/*=== extraBddAuto.c ========================================================*/ + +extern DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ); +extern DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ); +extern DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ); +extern DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ); +extern DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ); +extern DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ); +extern DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ); + +extern DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace ); +extern DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bSpace ); + +extern DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace ); +extern DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ); +extern DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ); +extern DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ); +extern DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ); + +extern DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ); +extern DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ); +extern DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ); +extern DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ); + +extern DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars ); +extern DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations ); + +/*=== extraBddCas.c =============================================================*/ + +/* performs the binary encoding of the set of function using the given vars */ +extern DdNode * Extra_bddEncodingBinary( DdManager * dd, DdNode ** pbFuncs, int nFuncs, DdNode ** pbVars, int nVars ); +/* solves the column encoding problem using a sophisticated method */ +extern DdNode * Extra_bddEncodingNonStrict( DdManager * dd, DdNode ** pbColumns, int nColumns, DdNode * bVarsCol, DdNode ** pCVars, int nMulti, int * pSimple ); +/* collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root */ +extern st_table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel ); +/* collects the nodes under the cut starting from the given set of ADD nodes */ +extern int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel ); +/* find the profile of a DD (the number of edges crossing each level) */ +extern int Extra_ProfileWidth( DdManager * dd, DdNode * F, int * Profile, int CutLevel ); + +/*=== extraBddMisc.c ========================================================*/ + +extern DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); +extern DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ); +extern DdNode * Extra_bddRemapUp( DdManager * dd, DdNode * bF ); +extern DdNode * Extra_bddMove( DdManager * dd, DdNode * bF, int fShiftUp ); +extern DdNode * extraBddMove( DdManager * dd, DdNode * bF, DdNode * bFlag ); +extern void Extra_StopManager( DdManager * dd ); +extern void Extra_bddPrint( DdManager * dd, DdNode * F ); +extern void extraDecomposeCover( DdManager* dd, DdNode* zC, DdNode** zC0, DdNode** zC1, DdNode** zC2 ); +extern int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ); +extern int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ); +extern int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ); +extern int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ); +extern int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ); +extern int * Extra_SupportArray( DdManager * dd, DdNode * F, int * support ); +extern int * Extra_VectorSupportArray( DdManager * dd, DdNode ** F, int n, int * support ); +extern DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ); +extern DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ); +extern DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); +extern DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ); +extern DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ); +extern int Extra_bddIsVar( DdNode * bFunc ); +extern DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ); +extern DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ); +extern DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ); +extern DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ); +extern void Extra_bddPermuteArray( DdManager * dd, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ); + +/*=== extraBddKmap.c ================================================================*/ + +/* displays the Karnaugh Map of a function */ +extern void Extra_PrintKMap( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nVars, DdNode ** XVars, int fSuppType, char ** pVarNames ); +/* displays the Karnaugh Map of a relation */ +extern void Extra_PrintKMapRelation( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nXVars, int nYVars, DdNode ** XVars, DdNode ** YVars ); + +/*=== extraBddSymm.c =================================================================*/ + +typedef struct Extra_SymmInfo_t_ Extra_SymmInfo_t; +struct Extra_SymmInfo_t_ { + int nVars; // the number of variables in the support + int nVarsMax; // the number of variables in the DD manager + int nSymms; // the number of pair-wise symmetries + int nNodes; // the number of nodes in a ZDD (if applicable) + int * pVars; // the list of all variables present in the support + char ** pSymms; // the symmetry information +}; + +/* computes the classical symmetry information for the function - recursive */ +extern Extra_SymmInfo_t * Extra_SymmPairsCompute( DdManager * dd, DdNode * bFunc ); +/* computes the classical symmetry information for the function - using naive approach */ +extern Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ); +extern int Extra_bddCheckVarsSymmetricNaive( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); + +/* allocates the data structure */ +extern Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ); +/* deallocates the data structure */ +extern void Extra_SymmPairsDissolve( Extra_SymmInfo_t * ); +/* print the contents the data structure */ +extern void Extra_SymmPairsPrint( Extra_SymmInfo_t * ); +/* converts the ZDD into the Extra_SymmInfo_t structure */ +extern Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bVars ); + +/* computes the classical symmetry information as a ZDD */ +extern DdNode * Extra_zddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); +extern DdNode * extraZddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); +/* returns a singleton-set ZDD containing all variables that are symmetric with the given one */ +extern DdNode * Extra_zddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); +extern DdNode * extraZddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); +/* converts a set of variables into a set of singleton subsets */ +extern DdNode * Extra_zddGetSingletons( DdManager * dd, DdNode * bVars ); +extern DdNode * extraZddGetSingletons( DdManager * dd, DdNode * bVars ); +/* filters the set of variables using the support of the function */ +extern DdNode * Extra_bddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); +extern DdNode * extraBddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); + +/* checks the possibility that the two vars are symmetric */ +extern int Extra_bddCheckVarsSymmetric( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); +extern DdNode * extraBddCheckVarsSymmetric( DdManager * dd, DdNode * bF, DdNode * bVars ); + +/* build the set of all tuples of K variables out of N from the BDD cube */ +extern DdNode * Extra_zddTuplesFromBdd( DdManager * dd, int K, DdNode * bVarsN ); +extern DdNode * extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNode * bVarsN ); +/* selects one subset from a ZDD representing the set of subsets */ +extern DdNode * Extra_zddSelectOneSubset( DdManager * dd, DdNode * zS ); +extern DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS ); + +/*=== extraBddUnate.c =================================================================*/ + +typedef struct Extra_UnateVar_t_ Extra_UnateVar_t; +struct Extra_UnateVar_t_ { + unsigned iVar : 30; // index of the variable + unsigned Pos : 1; // 1 if positive unate + unsigned Neg : 1; // 1 if negative unate +}; + +typedef struct Extra_UnateInfo_t_ Extra_UnateInfo_t; +struct Extra_UnateInfo_t_ { + int nVars; // the number of variables in the support + int nVarsMax; // the number of variables in the DD manager + int nUnate; // the number of unate variables + Extra_UnateVar_t * pVars; // the array of variables present in the support +}; + +/* allocates the data structure */ +extern Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars ); +/* deallocates the data structure */ +extern void Extra_UnateInfoDissolve( Extra_UnateInfo_t * ); +/* print the contents the data structure */ +extern void Extra_UnateInfoPrint( Extra_UnateInfo_t * ); +/* converts the ZDD into the Extra_SymmInfo_t structure */ +extern Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zUnate, DdNode * bVars ); +/* naive check of unateness of one variable */ +extern int Extra_bddCheckUnateNaive( DdManager * dd, DdNode * bF, int iVar ); + +/* computes the unateness information for the function */ +extern Extra_UnateInfo_t * Extra_UnateComputeFast( DdManager * dd, DdNode * bFunc ); +extern Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc ); + +/* computes the classical symmetry information as a ZDD */ +extern DdNode * Extra_zddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); +extern DdNode * extraZddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); + +/* converts a set of variables into a set of singleton subsets */ +extern DdNode * Extra_zddGetSingletonsBoth( DdManager * dd, DdNode * bVars ); +extern DdNode * extraZddGetSingletonsBoth( DdManager * dd, DdNode * bVars ); + +/*=== extraUtilBitMatrix.c ================================================================*/ + +typedef struct Extra_BitMat_t_ Extra_BitMat_t; +extern Extra_BitMat_t * Extra_BitMatrixStart( int nSize ); +extern void Extra_BitMatrixClean( Extra_BitMat_t * p ); +extern void Extra_BitMatrixStop( Extra_BitMat_t * p ); +extern void Extra_BitMatrixPrint( Extra_BitMat_t * p ); +extern int Extra_BitMatrixReadSize( Extra_BitMat_t * p ); +extern void Extra_BitMatrixInsert1( Extra_BitMat_t * p, int i, int k ); +extern int Extra_BitMatrixLookup1( Extra_BitMat_t * p, int i, int k ); +extern void Extra_BitMatrixDelete1( Extra_BitMat_t * p, int i, int k ); +extern void Extra_BitMatrixInsert2( Extra_BitMat_t * p, int i, int k ); +extern int Extra_BitMatrixLookup2( Extra_BitMat_t * p, int i, int k ); +extern void Extra_BitMatrixDelete2( Extra_BitMat_t * p, int i, int k ); +extern void Extra_BitMatrixOr( Extra_BitMat_t * p, int i, unsigned * pInfo ); +extern void Extra_BitMatrixOrTwo( Extra_BitMat_t * p, int i, int j ); +extern int Extra_BitMatrixCountOnesUpper( Extra_BitMat_t * p ); +extern int Extra_BitMatrixIsDisjoint( Extra_BitMat_t * p1, Extra_BitMat_t * p2 ); +extern int Extra_BitMatrixIsClique( Extra_BitMat_t * p ); + +/*=== extraUtilFile.c ========================================================*/ + +extern char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2, char * pS3, char * pS4, char * pS5 ); +extern char * Extra_FileNameExtension( char * FileName ); +extern char * Extra_FileNameAppend( char * pBase, char * pSuffix ); +extern char * Extra_FileNameGeneric( char * FileName ); +extern int Extra_FileSize( char * pFileName ); +extern char * Extra_FileRead( FILE * pFile ); +extern char * Extra_TimeStamp(); +extern char * Extra_StringAppend( char * pStrGiven, char * pStrAdd ); +extern unsigned Extra_ReadBinary( char * Buffer ); +extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ); +extern int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars ); +extern void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ); +extern void Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars ); +extern void Extra_PrintHex( FILE * pFile, unsigned uTruth, int nVars ); +extern void Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine ); + +/*=== extraUtilReader.c ========================================================*/ + +typedef struct Extra_FileReader_t_ Extra_FileReader_t; +extern Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName, + char * pCharsComment, char * pCharsStop, char * pCharsClean ); +extern void Extra_FileReaderFree( Extra_FileReader_t * p ); +extern char * Extra_FileReaderGetFileName( Extra_FileReader_t * p ); +extern int Extra_FileReaderGetFileSize( Extra_FileReader_t * p ); +extern int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p ); +extern void * Extra_FileReaderGetTokens( Extra_FileReader_t * p ); +extern int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken ); + +/*=== extraUtilMemory.c ========================================================*/ + +typedef struct Extra_MmFixed_t_ Extra_MmFixed_t; +typedef struct Extra_MmFlex_t_ Extra_MmFlex_t; +typedef struct Extra_MmStep_t_ Extra_MmStep_t; + +// fixed-size-block memory manager +extern Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize ); +extern void Extra_MmFixedStop( Extra_MmFixed_t * p ); +extern char * Extra_MmFixedEntryFetch( Extra_MmFixed_t * p ); +extern void Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry ); +extern void Extra_MmFixedRestart( Extra_MmFixed_t * p ); +extern int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p ); +extern int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p ); +// flexible-size-block memory manager +extern Extra_MmFlex_t * Extra_MmFlexStart(); +extern void Extra_MmFlexStop( Extra_MmFlex_t * p ); +extern void Extra_MmFlexPrint( Extra_MmFlex_t * p ); +extern char * Extra_MmFlexEntryFetch( Extra_MmFlex_t * p, int nBytes ); +extern int Extra_MmFlexReadMemUsage( Extra_MmFlex_t * p ); +// hierarchical memory manager +extern Extra_MmStep_t * Extra_MmStepStart( int nSteps ); +extern void Extra_MmStepStop( Extra_MmStep_t * p ); +extern char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes ); +extern void Extra_MmStepEntryRecycle( Extra_MmStep_t * p, char * pEntry, int nBytes ); +extern int Extra_MmStepReadMemUsage( Extra_MmStep_t * p ); + +/*=== extraUtilMisc.c ========================================================*/ + +/* finds the smallest integer larger or equal than the logarithm */ +extern int Extra_Base2Log( unsigned Num ); +extern int Extra_Base2LogDouble( double Num ); +extern int Extra_Base10Log( unsigned Num ); +/* returns the power of two as a double */ +extern double Extra_Power2( int Num ); +extern int Extra_Power3( int Num ); +/* the number of combinations of k elements out of n */ +extern int Extra_NumCombinations( int k, int n ); +extern int * Extra_DeriveRadixCode( int Number, int Radix, int nDigits ); +/* counts the number of 1s in the bitstring */ +extern int Extra_CountOnes( unsigned char * pBytes, int nBytes ); +/* the factorial of number */ +extern int Extra_Factorial( int n ); +/* the permutation of the given number of elements */ +extern char ** Extra_Permutations( int n ); +/* permutation and complementation of a truth table */ +unsigned Extra_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse ); +unsigned Extra_TruthPolarize( unsigned uTruth, int Polarity, int nVars ); +/* canonical forms of a truth table */ +extern unsigned Extra_TruthCanonN( unsigned uTruth, int nVars ); +extern unsigned Extra_TruthCanonNN( unsigned uTruth, int nVars ); +extern unsigned Extra_TruthCanonP( unsigned uTruth, int nVars ); +extern unsigned Extra_TruthCanonNP( unsigned uTruth, int nVars ); +extern unsigned Extra_TruthCanonNPN( unsigned uTruth, int nVars ); +/* canonical forms of 4-variable functions */ +extern void Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ); +extern void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int nPhasesMax ); +/* permutation mapping */ +extern unsigned short Extra_TruthPerm4One( unsigned uTruth, int Phase ); +extern unsigned Extra_TruthPerm5One( unsigned uTruth, int Phase ); +extern void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes ); +extern void Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR ); +/* precomputing tables for permutation mapping */ +extern void ** Extra_ArrayAlloc( int nCols, int nRows, int Size ); +extern unsigned short ** Extra_TruthPerm43(); +extern unsigned ** Extra_TruthPerm53(); +extern unsigned ** Extra_TruthPerm54(); +/* bubble sort for small number of entries */ +extern void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing ); +/* for independence from CUDD */ +extern unsigned int Cudd_PrimeCopy( unsigned int p ); + +/*=== extraUtilCanon.c ========================================================*/ + +/* fast computation of N-canoninical form up to 6 inputs */ +extern int Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes ); + +/*=== extraUtilProgress.c ================================================================*/ + +typedef struct ProgressBarStruct ProgressBar; + +extern ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal ); +extern void Extra_ProgressBarStop( ProgressBar * p ); +extern void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString ); + +static inline void Extra_ProgressBarUpdate( ProgressBar * p, int nItemsCur, char * pString ) +{ if ( p && nItemsCur < *((int*)p) ) return; Extra_ProgressBarUpdate_int(p, nItemsCur, pString); } + +/*=== extraUtilTruth.c ================================================================*/ + +static inline int Extra_Float2Int( float Val ) { return *((int *)&Val); } +static inline float Extra_Int2Float( int Num ) { return *((float *)&Num); } +static inline int Extra_BitWordNum( int nBits ) { return nBits/(8*sizeof(unsigned)) + ((nBits%(8*sizeof(unsigned))) > 0); } +static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } + +static inline void Extra_TruthSetBit( unsigned * p, int Bit ) { p[Bit>>5] |= (1<<(Bit & 31)); } +static inline void Extra_TruthXorBit( unsigned * p, int Bit ) { p[Bit>>5] ^= (1<<(Bit & 31)); } +static inline int Extra_TruthHasBit( unsigned * p, int Bit ) { return (p[Bit>>5] & (1<<(Bit & 31))) > 0; } + +static inline int Extra_WordCountOnes( unsigned uWord ) +{ + uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); + uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); + uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); + uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); + return (uWord & 0x0000FFFF) + (uWord>>16); +} +static inline int Extra_TruthCountOnes( unsigned * pIn, int nVars ) +{ + int w, Counter = 0; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + Counter += Extra_WordCountOnes(pIn[w]); + return Counter; +} +static inline int Extra_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn0[w] != pIn1[w] ) + return 0; + return 1; +} +static inline int Extra_TruthIsConst0( unsigned * pIn, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn[w] ) + return 0; + return 1; +} +static inline int Extra_TruthIsConst1( unsigned * pIn, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn[w] != ~(unsigned)0 ) + return 0; + return 1; +} +static inline int Extra_TruthIsImply( unsigned * pIn1, unsigned * pIn2, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn1[w] & ~pIn2[w] ) + return 0; + return 1; +} +static inline void Extra_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn[w]; +} +static inline void Extra_TruthClear( unsigned * pOut, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = 0; +} +static inline void Extra_TruthFill( unsigned * pOut, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~(unsigned)0; +} +static inline void Extra_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~pIn[w]; +} +static inline void Extra_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] & pIn1[w]; +} +static inline void Extra_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] | pIn1[w]; +} +static inline void Extra_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] & ~pIn1[w]; +} +static inline void Extra_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) +{ + int w; + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~(pIn0[w] & pIn1[w]); +} +static inline void Extra_TruthAndPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 ) +{ + int w; + if ( fCompl0 && fCompl1 ) + { + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~(pIn0[w] | pIn1[w]); + } + else if ( fCompl0 && !fCompl1 ) + { + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~pIn0[w] & pIn1[w]; + } + else if ( !fCompl0 && fCompl1 ) + { + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] & ~pIn1[w]; + } + else // if ( !fCompl0 && !fCompl1 ) + { + for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn0[w] & pIn1[w]; + } +} + +extern unsigned ** Extra_TruthElementary( int nVars ); +extern void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start ); +extern void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ); +extern void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ); +extern int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ); +extern int Extra_TruthSupportSize( unsigned * pTruth, int nVars ); +extern int Extra_TruthSupport( unsigned * pTruth, int nVars ); +extern void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ); +extern void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ); +extern void Extra_TruthExist( unsigned * pTruth, int nVars, int iVar ); +extern void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar ); +extern void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ); +extern void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ); +extern int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ); +extern void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ); +extern unsigned Extra_TruthHash( unsigned * pIn, int nWords ); +extern unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ); + +/*=== extraUtilUtil.c ================================================================*/ + +#ifndef ABS +#define ABS(a) ((a) < 0 ? -(a) : (a)) +#endif + +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef ALLOC +#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#endif + +#ifndef FREE +#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#endif + +#ifndef REALLOC +#define REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) +#endif + + +extern long Extra_CpuTime(); +extern int Extra_GetSoftDataLimit(); +extern void Extra_UtilGetoptReset(); +extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring ); +extern char * Extra_UtilPrintTime( long t ); +extern char * Extra_UtilStrsav( char *s ); +extern char * Extra_UtilTildeExpand( char *fname ); +extern char * Extra_UtilFileSearch( char *file, char *path, char *mode ); +extern void (*Extra_UtilMMoutOfMemory)(); + +extern char * globalUtilOptarg; +extern int globalUtilOptind; + +/**AutomaticEnd***************************************************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* __EXTRA_H__ */ diff --git a/abc70930/src/misc/extra/extraBddAuto.c b/abc70930/src/misc/extra/extraBddAuto.c new file mode 100644 index 00000000..21a969ba --- /dev/null +++ b/abc70930/src/misc/extra/extraBddAuto.c @@ -0,0 +1,1558 @@ +/**CFile**************************************************************** + + FileName [extraBddAuto.c] + + PackageName [extra] + + Synopsis [Computation of autosymmetries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddAuto.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + + +/* + LinearSpace(f) = Space(f,f) + + Space(f,g) + { + if ( f = const ) + { + if ( f = g ) return 1; + else return 0; + } + if ( g = const ) return 0; + return x' * Space(fx',gx') * Space(fx,gx) + x * Space(fx',gx) * Space(fx,gx'); + } + + Equations(s) = Pos(s) + Neg(s); + + Pos(s) + { + if ( s = 0 ) return 1; + if ( s = 1 ) return 0; + if ( sx'= 0 ) return Pos(sx) + x; + if ( sx = 0 ) return Pos(sx'); + return 1 * [Pos(sx') & Pos(sx)] + x * [Pos(sx') & Neg(sx)]; + } + + Neg(s) + { + if ( s = 0 ) return 1; + if ( s = 1 ) return 0; + if ( sx'= 0 ) return Neg(sx); + if ( sx = 0 ) return Neg(sx') + x; + return 1 * [Neg(sx') & Neg(sx)] + x * [Neg(sx') & Pos(sx)]; + } + + + SpaceP(A) + { + if ( A = 0 ) return 1; + if ( A = 1 ) return 1; + return x' * SpaceP(Ax') * SpaceP(Ax) + x * SpaceP(Ax') * SpaceN(Ax); + } + + SpaceN(A) + { + if ( A = 0 ) return 1; + if ( A = 1 ) return 0; + return x' * SpaceN(Ax') * SpaceN(Ax) + x * SpaceN(Ax') * SpaceP(Ax); + } + + + LinInd(A) + { + if ( A = const ) return 1; + if ( !LinInd(Ax') ) return 0; + if ( !LinInd(Ax) ) return 0; + if ( LinSumOdd(Ax') & LinSumEven(Ax) != 0 ) return 0; + if ( LinSumEven(Ax') & LinSumEven(Ax) != 0 ) return 0; + return 1; + } + + LinSumOdd(A) + { + if ( A = 0 ) return 0; // Odd0 ---e-- Odd1 + if ( A = 1 ) return 1; // \ o + Odd0 = LinSumOdd(Ax'); // x is absent // \ + Even0 = LinSumEven(Ax'); // x is absent // / o + Odd1 = LinSumOdd(Ax); // x is present // Even0 ---e-- Even1 + Even1 = LinSumEven(Ax); // x is absent + return 1 * [Odd0 + ExorP(Odd0, Even1)] + x * [Odd1 + ExorP(Odd1, Even0)]; + } + + LinSumEven(A) + { + if ( A = 0 ) return 0; + if ( A = 1 ) return 0; + Odd0 = LinSumOdd(Ax'); // x is absent + Even0 = LinSumEven(Ax'); // x is absent + Odd1 = LinSumOdd(Ax); // x is present + Even1 = LinSumEven(Ax); // x is absent + return 1 * [Even0 + Even1 + ExorP(Even0, Even1)] + x * [ExorP(Odd0, Odd1)]; + } + +*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ) +{ + int * pSupport; + int * pPermute; + int * pPermuteBack; + DdNode ** pCompose; + DdNode * bCube, * bTemp; + DdNode * bSpace, * bFunc1, * bFunc2, * bSpaceShift; + int nSupp, Counter; + int i, lev; + + // get the support + pSupport = ALLOC( int, ddMax(dd->size,dd->sizeZ) ); + Extra_SupportArray( dd, bFunc, pSupport ); + nSupp = 0; + for ( i = 0; i < dd->size; i++ ) + if ( pSupport[i] ) + nSupp++; + + // make sure the manager has enough variables + if ( 2*nSupp > dd->size ) + { + printf( "Cannot derive linear space, because DD manager does not have enough variables.\n" ); + fflush( stdout ); + free( pSupport ); + return NULL; + } + + // create the permutation arrays + pPermute = ALLOC( int, dd->size ); + pPermuteBack = ALLOC( int, dd->size ); + pCompose = ALLOC( DdNode *, dd->size ); + for ( i = 0; i < dd->size; i++ ) + { + pPermute[i] = i; + pPermuteBack[i] = i; + pCompose[i] = dd->vars[i]; Cudd_Ref( pCompose[i] ); + } + + // remap the function in such a way that the variables are interleaved + Counter = 0; + bCube = b1; Cudd_Ref( bCube ); + for ( lev = 0; lev < dd->size; lev++ ) + if ( pSupport[ dd->invperm[lev] ] ) + { // var "dd->invperm[lev]" on level "lev" should go to level 2*Counter; + pPermute[ dd->invperm[lev] ] = dd->invperm[2*Counter]; + // var from level 2*Counter+1 should go back to the place of this var + pPermuteBack[ dd->invperm[2*Counter+1] ] = dd->invperm[lev]; + // the permutation should be defined in such a way that variable + // on level 2*Counter is replaced by an EXOR of itself and var on the next level + Cudd_Deref( pCompose[ dd->invperm[2*Counter] ] ); + pCompose[ dd->invperm[2*Counter] ] = + Cudd_bddXor( dd, dd->vars[ dd->invperm[2*Counter] ], dd->vars[ dd->invperm[2*Counter+1] ] ); + Cudd_Ref( pCompose[ dd->invperm[2*Counter] ] ); + // add this variable to the cube + bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[ dd->invperm[2*Counter] ] ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + // increment the counter + Counter ++; + } + + // permute the functions + bFunc1 = Cudd_bddPermute( dd, bFunc, pPermute ); Cudd_Ref( bFunc1 ); + // compose to gate the function depending on both vars + bFunc2 = Cudd_bddVectorCompose( dd, bFunc1, pCompose ); Cudd_Ref( bFunc2 ); + // gate the vector space + // L(a) = ForAll x [ F(x) = F(x+a) ] = Not( Exist x [ F(x) (+) F(x+a) ] ) + bSpaceShift = Cudd_bddXorExistAbstract( dd, bFunc1, bFunc2, bCube ); Cudd_Ref( bSpaceShift ); + bSpaceShift = Cudd_Not( bSpaceShift ); + // permute the space back into the original mapping + bSpace = Cudd_bddPermute( dd, bSpaceShift, pPermuteBack ); Cudd_Ref( bSpace ); + Cudd_RecursiveDeref( dd, bFunc1 ); + Cudd_RecursiveDeref( dd, bFunc2 ); + Cudd_RecursiveDeref( dd, bSpaceShift ); + Cudd_RecursiveDeref( dd, bCube ); + + for ( i = 0; i < dd->size; i++ ) + Cudd_RecursiveDeref( dd, pCompose[i] ); + free( pPermute ); + free( pPermuteBack ); + free( pCompose ); + free( pSupport ); + + Cudd_Deref( bSpace ); + return bSpace; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceFromFunction( dd, bF, bG ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceFromFunctionPos( dd, bFunc ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceFromFunctionNeg( dd, bFunc ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceCanonVars( dd, bSpace ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars ) +{ + DdNode * bNegCube; + DdNode * bResult; + bNegCube = Extra_bddSupportNegativeCube( dd, bCanonVars ); Cudd_Ref( bNegCube ); + bResult = Cudd_Cofactor( dd, bFunc, bNegCube ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bNegCube ); + Cudd_Deref( bResult ); + return bResult; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace ) +{ + DdNode * zRes; + DdNode * zEquPos; + DdNode * zEquNeg; + zEquPos = Extra_bddSpaceEquationsPos( dd, bSpace ); Cudd_Ref( zEquPos ); + zEquNeg = Extra_bddSpaceEquationsNeg( dd, bSpace ); Cudd_Ref( zEquNeg ); + zRes = Cudd_zddUnion( dd, zEquPos, zEquNeg ); Cudd_Ref( zRes ); + Cudd_RecursiveDerefZdd( dd, zEquPos ); + Cudd_RecursiveDerefZdd( dd, zEquNeg ); + Cudd_Deref( zRes ); + return zRes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ) +{ + DdNode * zRes; + do { + dd->reordered = 0; + zRes = extraBddSpaceEquationsPos( dd, bSpace ); + } while (dd->reordered == 1); + return zRes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ) +{ + DdNode * zRes; + do { + dd->reordered = 0; + zRes = extraBddSpaceEquationsNeg( dd, bSpace ); + } while (dd->reordered == 1); + return zRes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceFromMatrixPos( dd, zA ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ) +{ + DdNode * bRes; + do { + dd->reordered = 0; + bRes = extraBddSpaceFromMatrixNeg( dd, zA ); + } while (dd->reordered == 1); + return bRes; +} + +/**Function************************************************************* + + Synopsis [Counts the number of literals in one combination.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_zddLitCountComb( DdManager * dd, DdNode * zComb ) +{ + int Counter; + if ( zComb == z0 ) + return 0; + Counter = 0; + for ( ; zComb != z1; zComb = cuddT(zComb) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Returns the array of ZDDs with the number equal to the number of + vars in the DD manager. If the given var is non-canonical, this array contains + the referenced ZDD representing literals in the corresponding EXOR equation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations ) +{ + DdNode ** pzRes; + int * pVarsNonCan; + DdNode * zEquRem; + int iVarNonCan; + DdNode * zExor, * zTemp; + + // get the set of non-canonical variables + pVarsNonCan = ALLOC( int, ddMax(dd->size,dd->sizeZ) ); + Extra_SupportArray( dd, bFuncRed, pVarsNonCan ); + + // allocate storage for the EXOR sets + pzRes = ALLOC( DdNode *, dd->size ); + memset( pzRes, 0, sizeof(DdNode *) * dd->size ); + + // go through all the equations + zEquRem = zEquations; Cudd_Ref( zEquRem ); + while ( zEquRem != z0 ) + { + // extract one product + zExor = Extra_zddSelectOneSubset( dd, zEquRem ); Cudd_Ref( zExor ); + // remove it from the set + zEquRem = Cudd_zddDiff( dd, zTemp = zEquRem, zExor ); Cudd_Ref( zEquRem ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + + // locate the non-canonical variable + iVarNonCan = -1; + for ( zTemp = zExor; zTemp != z1; zTemp = cuddT(zTemp) ) + { + if ( pVarsNonCan[zTemp->index/2] == 1 ) + { + assert( iVarNonCan == -1 ); + iVarNonCan = zTemp->index/2; + } + } + assert( iVarNonCan != -1 ); + + if ( Extra_zddLitCountComb( dd, zExor ) > 1 ) + pzRes[ iVarNonCan ] = zExor; // takes ref + else + Cudd_RecursiveDerefZdd( dd, zExor ); + } + Cudd_RecursiveDerefZdd( dd, zEquRem ); + + free( pVarsNonCan ); + return pzRes; +} + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the recursive steps of Extra_bddSpaceFromFunction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ) +{ + DdNode * bRes; + DdNode * bFR, * bGR; + + bFR = Cudd_Regular( bF ); + bGR = Cudd_Regular( bG ); + if ( cuddIsConstant(bFR) ) + { + if ( bF == bG ) + return b1; + else + return b0; + } + if ( cuddIsConstant(bGR) ) + return b0; + // both bFunc and bCore are not constants + + // the operation is commutative - normalize the problem + if ( (unsigned)bF > (unsigned)bG ) + return extraBddSpaceFromFunction(dd, bG, bF); + + + if ( bRes = cuddCacheLookup2(dd, extraBddSpaceFromFunction, bF, bG) ) + return bRes; + else + { + DdNode * bF0, * bF1; + DdNode * bG0, * bG1; + DdNode * bTemp1, * bTemp2; + DdNode * bRes0, * bRes1; + int LevelF, LevelG; + int index; + + LevelF = dd->perm[bFR->index]; + LevelG = dd->perm[bGR->index]; + if ( LevelF <= LevelG ) + { + index = dd->invperm[LevelF]; + if ( bFR != bF ) + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + } + else + { + index = dd->invperm[LevelG]; + bF0 = bF1 = bF; + } + + if ( LevelG <= LevelF ) + { + if ( bGR != bG ) + { + bG0 = Cudd_Not( cuddE(bGR) ); + bG1 = Cudd_Not( cuddT(bGR) ); + } + else + { + bG0 = cuddE(bGR); + bG1 = cuddT(bGR); + } + } + else + bG0 = bG1 = bG; + + bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG0 ); + if ( bTemp1 == NULL ) + return NULL; + cuddRef( bTemp1 ); + + bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG1 ); + if ( bTemp2 == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp1 ); + return NULL; + } + cuddRef( bTemp2 ); + + + bRes0 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); + if ( bRes0 == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp1 ); + Cudd_RecursiveDeref( dd, bTemp2 ); + return NULL; + } + cuddRef( bRes0 ); + Cudd_RecursiveDeref( dd, bTemp1 ); + Cudd_RecursiveDeref( dd, bTemp2 ); + + + bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG1 ); + if ( bTemp1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bTemp1 ); + + bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG0 ); + if ( bTemp2 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bTemp1 ); + return NULL; + } + cuddRef( bTemp2 ); + + bRes1 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bTemp1 ); + Cudd_RecursiveDeref( dd, bTemp2 ); + return NULL; + } + cuddRef( bRes1 ); + Cudd_RecursiveDeref( dd, bTemp1 ); + Cudd_RecursiveDeref( dd, bTemp2 ); + + + + // consider the case when Res0 and Res1 are the same node + if ( bRes0 == bRes1 ) + bRes = bRes1; + // consider the case when Res1 is complemented + else if ( Cudd_IsComplement(bRes1) ) + { + bRes = cuddUniqueInter(dd, index, Cudd_Not(bRes1), Cudd_Not(bRes0)); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + bRes = Cudd_Not(bRes); + } + else + { + bRes = cuddUniqueInter( dd, index, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + } + cuddDeref( bRes0 ); + cuddDeref( bRes1 ); + + // insert the result into cache + cuddCacheInsert2(dd, extraBddSpaceFromFunction, bF, bG, bRes); + return bRes; + } +} /* end of extraBddSpaceFromFunction */ + + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bF ) +{ + DdNode * bRes, * bFR; + statLine( dd ); + + bFR = Cudd_Regular(bF); + if ( cuddIsConstant(bFR) ) + return b1; + + if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionPos, bF) ) + return bRes; + else + { + DdNode * bF0, * bF1; + DdNode * bPos0, * bPos1; + DdNode * bNeg0, * bNeg1; + DdNode * bRes0, * bRes1; + + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + + bPos0 = extraBddSpaceFromFunctionPos( dd, bF0 ); + if ( bPos0 == NULL ) + return NULL; + cuddRef( bPos0 ); + + bPos1 = extraBddSpaceFromFunctionPos( dd, bF1 ); + if ( bPos1 == NULL ) + { + Cudd_RecursiveDeref( dd, bPos0 ); + return NULL; + } + cuddRef( bPos1 ); + + bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 ); + if ( bRes0 == NULL ) + { + Cudd_RecursiveDeref( dd, bPos0 ); + Cudd_RecursiveDeref( dd, bPos1 ); + return NULL; + } + cuddRef( bRes0 ); + Cudd_RecursiveDeref( dd, bPos0 ); + Cudd_RecursiveDeref( dd, bPos1 ); + + + bNeg0 = extraBddSpaceFromFunctionNeg( dd, bF0 ); + if ( bNeg0 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bNeg0 ); + + bNeg1 = extraBddSpaceFromFunctionNeg( dd, bF1 ); + if ( bNeg1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + return NULL; + } + cuddRef( bNeg1 ); + + bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + Cudd_RecursiveDeref( dd, bNeg1 ); + return NULL; + } + cuddRef( bRes1 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + Cudd_RecursiveDeref( dd, bNeg1 ); + + + // consider the case when Res0 and Res1 are the same node + if ( bRes0 == bRes1 ) + bRes = bRes1; + // consider the case when Res1 is complemented + else if ( Cudd_IsComplement(bRes1) ) + { + bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + bRes = Cudd_Not(bRes); + } + else + { + bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + } + cuddDeref( bRes0 ); + cuddDeref( bRes1 ); + + cuddCacheInsert1( dd, extraBddSpaceFromFunctionPos, bF, bRes ); + return bRes; + } +} + + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bF ) +{ + DdNode * bRes, * bFR; + statLine( dd ); + + bFR = Cudd_Regular(bF); + if ( cuddIsConstant(bFR) ) + return b0; + + if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionNeg, bF) ) + return bRes; + else + { + DdNode * bF0, * bF1; + DdNode * bPos0, * bPos1; + DdNode * bNeg0, * bNeg1; + DdNode * bRes0, * bRes1; + + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + + bPos0 = extraBddSpaceFromFunctionNeg( dd, bF0 ); + if ( bPos0 == NULL ) + return NULL; + cuddRef( bPos0 ); + + bPos1 = extraBddSpaceFromFunctionNeg( dd, bF1 ); + if ( bPos1 == NULL ) + { + Cudd_RecursiveDeref( dd, bPos0 ); + return NULL; + } + cuddRef( bPos1 ); + + bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 ); + if ( bRes0 == NULL ) + { + Cudd_RecursiveDeref( dd, bPos0 ); + Cudd_RecursiveDeref( dd, bPos1 ); + return NULL; + } + cuddRef( bRes0 ); + Cudd_RecursiveDeref( dd, bPos0 ); + Cudd_RecursiveDeref( dd, bPos1 ); + + + bNeg0 = extraBddSpaceFromFunctionPos( dd, bF0 ); + if ( bNeg0 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bNeg0 ); + + bNeg1 = extraBddSpaceFromFunctionPos( dd, bF1 ); + if ( bNeg1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + return NULL; + } + cuddRef( bNeg1 ); + + bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + Cudd_RecursiveDeref( dd, bNeg1 ); + return NULL; + } + cuddRef( bRes1 ); + Cudd_RecursiveDeref( dd, bNeg0 ); + Cudd_RecursiveDeref( dd, bNeg1 ); + + + // consider the case when Res0 and Res1 are the same node + if ( bRes0 == bRes1 ) + bRes = bRes1; + // consider the case when Res1 is complemented + else if ( Cudd_IsComplement(bRes1) ) + { + bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + bRes = Cudd_Not(bRes); + } + else + { + bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + } + cuddDeref( bRes0 ); + cuddDeref( bRes1 ); + + cuddCacheInsert1( dd, extraBddSpaceFromFunctionNeg, bF, bRes ); + return bRes; + } +} + + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceCanonVars().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bF ) +{ + DdNode * bRes, * bFR; + statLine( dd ); + + bFR = Cudd_Regular(bF); + if ( cuddIsConstant(bFR) ) + return bF; + + if ( bRes = cuddCacheLookup1(dd, extraBddSpaceCanonVars, bF) ) + return bRes; + else + { + DdNode * bF0, * bF1; + DdNode * bRes, * bRes0; + + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + if ( bF0 == b0 ) + { + bRes = extraBddSpaceCanonVars( dd, bF1 ); + if ( bRes == NULL ) + return NULL; + } + else if ( bF1 == b0 ) + { + bRes = extraBddSpaceCanonVars( dd, bF0 ); + if ( bRes == NULL ) + return NULL; + } + else + { + bRes0 = extraBddSpaceCanonVars( dd, bF0 ); + if ( bRes0 == NULL ) + return NULL; + cuddRef( bRes0 ); + + bRes = cuddUniqueInter( dd, bFR->index, bRes0, b0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd,bRes0 ); + return NULL; + } + cuddDeref( bRes0 ); + } + + cuddCacheInsert1( dd, extraBddSpaceCanonVars, bF, bRes ); + return bRes; + } +} + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceEquationsPos().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bF ) +{ + DdNode * zRes; + statLine( dd ); + + if ( bF == b0 ) + return z1; + if ( bF == b1 ) + return z0; + + if ( zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsPos, bF) ) + return zRes; + else + { + DdNode * bFR, * bF0, * bF1; + DdNode * zPos0, * zPos1, * zNeg1; + DdNode * zRes, * zRes0, * zRes1; + + bFR = Cudd_Regular(bF); + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + if ( bF0 == b0 ) + { + zRes1 = extraBddSpaceEquationsPos( dd, bF1 ); + if ( zRes1 == NULL ) + return NULL; + cuddRef( zRes1 ); + + // add the current element to the set + zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes1 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddDeref( zRes1 ); + } + else if ( bF1 == b0 ) + { + zRes = extraBddSpaceEquationsPos( dd, bF0 ); + if ( zRes == NULL ) + return NULL; + } + else + { + zPos0 = extraBddSpaceEquationsPos( dd, bF0 ); + if ( zPos0 == NULL ) + return NULL; + cuddRef( zPos0 ); + + zPos1 = extraBddSpaceEquationsPos( dd, bF1 ); + if ( zPos1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zPos0); + return NULL; + } + cuddRef( zPos1 ); + + zNeg1 = extraBddSpaceEquationsNeg( dd, bF1 ); + if ( zNeg1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zNeg1 ); + + + zRes0 = cuddZddIntersect( dd, zPos0, zPos1 ); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zRes0 ); + + zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes0); + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zRes1 ); + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + // only zRes0 and zRes1 are refed at this point + + zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes0); + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + + cuddCacheInsert1( dd, extraBddSpaceEquationsPos, bF, zRes ); + return zRes; + } +} + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceEquationsNev().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bF ) +{ + DdNode * zRes; + statLine( dd ); + + if ( bF == b0 ) + return z1; + if ( bF == b1 ) + return z0; + + if ( zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsNeg, bF) ) + return zRes; + else + { + DdNode * bFR, * bF0, * bF1; + DdNode * zPos0, * zPos1, * zNeg1; + DdNode * zRes, * zRes0, * zRes1; + + bFR = Cudd_Regular(bF); + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + if ( bF0 == b0 ) + { + zRes = extraBddSpaceEquationsNeg( dd, bF1 ); + if ( zRes == NULL ) + return NULL; + } + else if ( bF1 == b0 ) + { + zRes0 = extraBddSpaceEquationsNeg( dd, bF0 ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + // add the current element to the set + zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes0); + return NULL; + } + cuddDeref( zRes0 ); + } + else + { + zPos0 = extraBddSpaceEquationsNeg( dd, bF0 ); + if ( zPos0 == NULL ) + return NULL; + cuddRef( zPos0 ); + + zPos1 = extraBddSpaceEquationsNeg( dd, bF1 ); + if ( zPos1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zPos0); + return NULL; + } + cuddRef( zPos1 ); + + zNeg1 = extraBddSpaceEquationsPos( dd, bF1 ); + if ( zNeg1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zNeg1 ); + + + zRes0 = cuddZddIntersect( dd, zPos0, zPos1 ); + if ( zRes0 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zRes0 ); + + zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes0); + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + return NULL; + } + cuddRef( zRes1 ); + Cudd_RecursiveDerefZdd(dd, zNeg1); + Cudd_RecursiveDerefZdd(dd, zPos0); + Cudd_RecursiveDerefZdd(dd, zPos1); + // only zRes0 and zRes1 are refed at this point + + zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zRes0); + Cudd_RecursiveDerefZdd(dd, zRes1); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + } + + cuddCacheInsert1( dd, extraBddSpaceEquationsNeg, bF, zRes ); + return zRes; + } +} + + + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ) +{ + DdNode * bRes; + statLine( dd ); + + if ( zA == z0 ) + return b1; + if ( zA == z1 ) + return b1; + + if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixPos, zA) ) + return bRes; + else + { + DdNode * bP0, * bP1; + DdNode * bN0, * bN1; + DdNode * bRes0, * bRes1; + + bP0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) ); + if ( bP0 == NULL ) + return NULL; + cuddRef( bP0 ); + + bP1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) ); + if ( bP1 == NULL ) + { + Cudd_RecursiveDeref( dd, bP0 ); + return NULL; + } + cuddRef( bP1 ); + + bRes0 = cuddBddAndRecur( dd, bP0, bP1 ); + if ( bRes0 == NULL ) + { + Cudd_RecursiveDeref( dd, bP0 ); + Cudd_RecursiveDeref( dd, bP1 ); + return NULL; + } + cuddRef( bRes0 ); + Cudd_RecursiveDeref( dd, bP0 ); + Cudd_RecursiveDeref( dd, bP1 ); + + + bN0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) ); + if ( bN0 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bN0 ); + + bN1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) ); + if ( bN1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bN0 ); + return NULL; + } + cuddRef( bN1 ); + + bRes1 = cuddBddAndRecur( dd, bN0, bN1 ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bN0 ); + Cudd_RecursiveDeref( dd, bN1 ); + return NULL; + } + cuddRef( bRes1 ); + Cudd_RecursiveDeref( dd, bN0 ); + Cudd_RecursiveDeref( dd, bN1 ); + + + // consider the case when Res0 and Res1 are the same node + if ( bRes0 == bRes1 ) + bRes = bRes1; + // consider the case when Res1 is complemented + else if ( Cudd_IsComplement(bRes1) ) + { + bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + bRes = Cudd_Not(bRes); + } + else + { + bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + } + cuddDeref( bRes0 ); + cuddDeref( bRes1 ); + + cuddCacheInsert1( dd, extraBddSpaceFromMatrixPos, zA, bRes ); + return bRes; + } +} + + +/**Function************************************************************* + + Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ) +{ + DdNode * bRes; + statLine( dd ); + + if ( zA == z0 ) + return b1; + if ( zA == z1 ) + return b0; + + if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixNeg, zA) ) + return bRes; + else + { + DdNode * bP0, * bP1; + DdNode * bN0, * bN1; + DdNode * bRes0, * bRes1; + + bP0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) ); + if ( bP0 == NULL ) + return NULL; + cuddRef( bP0 ); + + bP1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) ); + if ( bP1 == NULL ) + { + Cudd_RecursiveDeref( dd, bP0 ); + return NULL; + } + cuddRef( bP1 ); + + bRes0 = cuddBddAndRecur( dd, bP0, bP1 ); + if ( bRes0 == NULL ) + { + Cudd_RecursiveDeref( dd, bP0 ); + Cudd_RecursiveDeref( dd, bP1 ); + return NULL; + } + cuddRef( bRes0 ); + Cudd_RecursiveDeref( dd, bP0 ); + Cudd_RecursiveDeref( dd, bP1 ); + + + bN0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) ); + if ( bN0 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bN0 ); + + bN1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) ); + if ( bN1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bN0 ); + return NULL; + } + cuddRef( bN1 ); + + bRes1 = cuddBddAndRecur( dd, bN0, bN1 ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bN0 ); + Cudd_RecursiveDeref( dd, bN1 ); + return NULL; + } + cuddRef( bRes1 ); + Cudd_RecursiveDeref( dd, bN0 ); + Cudd_RecursiveDeref( dd, bN1 ); + + + // consider the case when Res0 and Res1 are the same node + if ( bRes0 == bRes1 ) + bRes = bRes1; + // consider the case when Res1 is complemented + else if ( Cudd_IsComplement(bRes1) ) + { + bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + bRes = Cudd_Not(bRes); + } + else + { + bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref(dd,bRes0); + Cudd_RecursiveDeref(dd,bRes1); + return NULL; + } + } + cuddDeref( bRes0 ); + cuddDeref( bRes1 ); + + cuddCacheInsert1( dd, extraBddSpaceFromMatrixNeg, zA, bRes ); + return bRes; + } +} + + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/misc/extra/extraBddCas.c b/abc70930/src/misc/extra/extraBddCas.c new file mode 100644 index 00000000..29382bfb --- /dev/null +++ b/abc70930/src/misc/extra/extraBddCas.c @@ -0,0 +1,1230 @@ +/**CFile**************************************************************** + + FileName [extraBddCas.c] + + PackageName [extra] + + Synopsis [Procedures related to LUT cascade synthesis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddCas.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +// the table to store cofactor operations +#define _TABLESIZE_COF 51113 +typedef struct +{ + unsigned Sign; + DdNode * Arg1; +} _HashEntry_cof; +_HashEntry_cof HHTable1[_TABLESIZE_COF]; + +// the table to store the result of computation of the number of minterms +#define _TABLESIZE_MINT 15113 +typedef struct +{ + DdNode * Arg1; + unsigned Arg2; + unsigned Res; +} _HashEntry_mint; +_HashEntry_mint HHTable2[_TABLESIZE_MINT]; + +typedef struct +{ + int nEdges; // the number of in-coming edges of the node + DdNode * bSum; // the sum of paths of the incoming edges +} traventry; + +// the signature used for hashing +static unsigned s_Signature = 1; + +static int s_CutLevel = 0; + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +// because the proposed solution to the optimal encoding problem has exponential complexity +// we limit the depth of the branch and bound procedure to 5 levels +static int s_MaxDepth = 5; + +static int s_nVarsBest; // the number of vars in the best ordering +static int s_VarOrderBest[32]; // storing the best ordering of vars in the "simple encoding" +static int s_VarOrderCur[32]; // storing the current ordering of vars + +// the place to store the supports of the encoded function +static DdNode * s_Field[8][256]; // the size should be K, 2^K, where K is no less than MaxDepth +static DdNode * s_Encoded; // this is the original function +static DdNode * s_VarAll; // the set of all column variables +static int s_MultiStart; // the total number of encoding variables used +// the array field now stores the supports + +static DdNode ** s_pbTemp; // the temporary storage for the columns + +static int s_BackTracks; +static int s_BackTrackLimit = 100; + +static DdNode * s_Terminal; // the terminal value for counting minterms + + +static int s_EncodingVarsLevel; + + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars ); +static void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level ); +// functions called from EvaluateEncodings_rec() +static DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ); +static DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ); +unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll ); +static unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max ); + +static void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st_table * Visited ); +static void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st_table * Visited, st_table * CutNodes ); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the binary encoding of the set of function using the given vars.] + + Description [Performs a straight binary encoding of the set of functions using + the variable cubes formed from the given set of variables. ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * +Extra_bddEncodingBinary( + DdManager * dd, + DdNode ** pbFuncs, // pbFuncs is the array of columns to be encoded + int nFuncs, // nFuncs is the number of columns in the array + DdNode ** pbVars, // pbVars is the array of variables to use for the codes + int nVars ) // nVars is the column multiplicity, [log2(nFuncs)] +{ + int i; + DdNode * bResult; + DdNode * bCube, * bTemp, * bProd; + + assert( nVars >= Extra_Base2Log(nFuncs) ); + + bResult = b0; Cudd_Ref( bResult ); + for ( i = 0; i < nFuncs; i++ ) + { + bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube ); + bProd = Cudd_bddAnd( dd, bCube, pbFuncs[i] ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bCube ); + + bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bProd ); + } + + Cudd_Deref( bResult ); + return bResult; +} /* end of Extra_bddEncodingBinary */ + + +/**Function******************************************************************** + + Synopsis [Solves the column encoding problem using a sophisticated method.] + + Description [The encoding is based on the idea of deriving functions which + depend on only one variable, which corresponds to the case of non-disjoint + decompostion. It is assumed that the variables pCVars are ordered below the variables + representing the solumns, and the first variable pCVars[0] is the topmost one.] + + SideEffects [] + + SeeAlso [Extra_bddEncodingBinary] + +******************************************************************************/ + +DdNode * +Extra_bddEncodingNonStrict( + DdManager * dd, + DdNode ** pbColumns, // pbColumns is the array of columns to be encoded; + int nColumns, // nColumns is the number of columns in the array + DdNode * bVarsCol, // bVarsCol is the cube of variables on which the columns depend + DdNode ** pCVars, // pCVars is the array of variables to use for the codes + int nMulti, // nMulti is the column multiplicity, [log2(nColumns)] + int * pSimple ) // pSimple gets the number of code variables taken from the input varibles without change +{ + DdNode * bEncoded, * bResult; + int nVarsCol = Cudd_SupportSize(dd,bVarsCol); + long clk; + + // cannot work with more that 32-bit codes + assert( nMulti < 32 ); + + // perform the preliminary encoding using the straight binary code + bEncoded = Extra_bddEncodingBinary( dd, pbColumns, nColumns, pCVars, nMulti ); Cudd_Ref( bEncoded ); + //printf( "Node count = %d", Cudd_DagSize(bEncoded) ); + + // set the backgroup value for counting minterms + s_Terminal = b0; + // set the level of the encoding variables + s_EncodingVarsLevel = dd->invperm[pCVars[0]->index]; + + // the current number of backtracks + s_BackTracks = 0; + // the variables that are cofactored on the topmost level where everything starts (no vars) + s_Field[0][0] = b1; + // the size of the best set of "simple" encoding variables found so far + s_nVarsBest = 0; + + // set the relation to be accessible to traversal procedures + s_Encoded = bEncoded; + // the set of all vars to be accessible to traversal procedures + s_VarAll = bVarsCol; + // the column multiplicity + s_MultiStart = nMulti; + + + clk = clock(); + // find the simplest encoding + if ( nColumns > 2 ) + EvaluateEncodings_rec( dd, bVarsCol, nVarsCol, nMulti, 1 ); +// printf( "The number of backtracks = %d\n", s_BackTracks ); +// s_EncSearchTime += clock() - clk; + + // allocate the temporary storage for the columns + s_pbTemp = (DdNode **) malloc( nColumns * sizeof(DdNode *) ); + +// clk = clock(); + bResult = CreateTheCodes_rec( dd, bEncoded, 0, pCVars ); Cudd_Ref( bResult ); +// s_EncComputeTime += clock() - clk; + + // delocate the preliminarily encoded set + Cudd_RecursiveDeref( dd, bEncoded ); +// Cudd_RecursiveDeref( dd, aEncoded ); + + free( s_pbTemp ); + + *pSimple = s_nVarsBest; + Cudd_Deref( bResult ); + return bResult; +} + +/**Function******************************************************************** + + Synopsis [Collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root.] + + Description [The table returned contains the set of BDD nodes pointed to under the cut + and, for each node, the BDD of the sum of paths leading to this node from the root + The sums of paths in the table are referenced. CutLevel is the first DD level + considered to be under the cut.] + + SideEffects [] + + SeeAlso [Extra_bddNodePaths] + +******************************************************************************/ +st_table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel ) +{ + st_table * Visited; // temporary table to remember the visited nodes + st_table * CutNodes; // the result goes here + st_table * Result; // the result goes here + DdNode * aFunc; + + s_CutLevel = CutLevel; + + Result = st_init_table(st_ptrcmp,st_ptrhash); + // the terminal cases + if ( Cudd_IsConstant( bFunc ) ) + { + if ( bFunc == b1 ) + { + st_insert( Result, (char*)b1, (char*)b1 ); + Cudd_Ref( b1 ); + Cudd_Ref( b1 ); + } + else + { + st_insert( Result, (char*)b0, (char*)b0 ); + Cudd_Ref( b0 ); + Cudd_Ref( b0 ); + } + return Result; + } + + // create the ADD to simplify processing (no complemented edges) + aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc ); + + // Step 1: Start the tables and collect information about the nodes above the cut + // this information tells how many edges point to each node + Visited = st_init_table(st_ptrcmp,st_ptrhash); + CutNodes = st_init_table(st_ptrcmp,st_ptrhash); + + CountNodeVisits_rec( dd, aFunc, Visited ); + + // Step 2: Traverse the BDD using the visited table and compute the sum of paths + CollectNodesAndComputePaths_rec( dd, aFunc, b1, Visited, CutNodes ); + + // at this point the table of cut nodes is ready and the table of visited is useless + { + st_generator * gen; + DdNode * aNode; + traventry * p; + st_foreach_item( Visited, gen, (char**)&aNode, (char**)&p ) + { + Cudd_RecursiveDeref( dd, p->bSum ); + free( p ); + } + st_free_table( Visited ); + } + + // go through the table CutNodes and create the BDD and the path to be returned + { + st_generator * gen; + DdNode * aNode, * bNode, * bSum; + st_foreach_item( CutNodes, gen, (char**)&aNode, (char**)&bSum) + { + // aNode is not referenced, because aFunc is holding it + bNode = Cudd_addBddPattern( dd, aNode ); Cudd_Ref( bNode ); + st_insert( Result, (char*)bNode, (char*)bSum ); + // the new table takes both refs + } + st_free_table( CutNodes ); + } + + // dereference the ADD + Cudd_RecursiveDeref( dd, aFunc ); + + // return the table + return Result; + +} /* end of Extra_bddNodePathsUnderCut */ + +/**Function******************************************************************** + + Synopsis [Collects the nodes under the cut in the ADD starting from the given set of ADD nodes.] + + Description [Takes the array, paNodes, of ADD nodes to start the traversal, + the array, pbCubes, of BDD cubes to start the traversal with in each node, + and the number, nNodes, of ADD nodes and BDD cubes in paNodes and pbCubes. + Returns the number of columns found. Fills in paNodesRes (pbCubesRes) + with the set of ADD columns (BDD paths). These arrays should be allocated + by the user.] + + SideEffects [] + + SeeAlso [Extra_bddNodePaths] + +******************************************************************************/ +int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel ) +{ + st_table * Visited; // temporary table to remember the visited nodes + st_table * CutNodes; // the nodes under the cut go here + int i, Counter; + + s_CutLevel = CutLevel; + + // there should be some nodes + assert( nNodes > 0 ); + if ( nNodes == 1 && Cudd_IsConstant( paNodes[0] ) ) + { + if ( paNodes[0] == a1 ) + { + paNodesRes[0] = a1; Cudd_Ref( a1 ); + pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] ); + } + else + { + paNodesRes[0] = a0; Cudd_Ref( a0 ); + pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] ); + } + return 1; + } + + // Step 1: Start the table and collect information about the nodes above the cut + // this information tells how many edges point to each node + CutNodes = st_init_table(st_ptrcmp,st_ptrhash); + Visited = st_init_table(st_ptrcmp,st_ptrhash); + + for ( i = 0; i < nNodes; i++ ) + CountNodeVisits_rec( dd, paNodes[i], Visited ); + + // Step 2: Traverse the BDD using the visited table and compute the sum of paths + for ( i = 0; i < nNodes; i++ ) + CollectNodesAndComputePaths_rec( dd, paNodes[i], pbCubes[i], Visited, CutNodes ); + + // at this point, the table of cut nodes is ready and the table of visited is useless + { + st_generator * gen; + DdNode * aNode; + traventry * p; + st_foreach_item( Visited, gen, (char**)&aNode, (char**)&p ) + { + Cudd_RecursiveDeref( dd, p->bSum ); + free( p ); + } + st_free_table( Visited ); + } + + // go through the table CutNodes and create the BDD and the path to be returned + { + st_generator * gen; + DdNode * aNode, * bSum; + Counter = 0; + st_foreach_item( CutNodes, gen, (char**)&aNode, (char**)&bSum) + { + paNodesRes[Counter] = aNode; Cudd_Ref( aNode ); + pbCubesRes[Counter] = bSum; + Counter++; + } + st_free_table( CutNodes ); + } + + // return the number of cofactors found + return Counter; + +} /* end of Extra_bddNodePathsUnderCutArray */ + +/**Function************************************************************* + + Synopsis [Collects all the BDD nodes into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void extraCollectNodes( DdNode * Func, st_table * tNodes ) +{ + DdNode * FuncR; + FuncR = Cudd_Regular(Func); + if ( st_find_or_add( tNodes, (char*)FuncR, NULL ) ) + return; + if ( cuddIsConstant(FuncR) ) + return; + extraCollectNodes( cuddE(FuncR), tNodes ); + extraCollectNodes( cuddT(FuncR), tNodes ); +} + +/**Function************************************************************* + + Synopsis [Collects all the nodes of one DD into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +st_table * Extra_CollectNodes( DdNode * Func ) +{ + st_table * tNodes; + tNodes = st_init_table( st_ptrcmp, st_ptrhash ); + extraCollectNodes( Func, tNodes ); + return tNodes; +} + +/**Function************************************************************* + + Synopsis [Updates the topmost level from which the given node is referenced.] + + Description [Takes the table which maps each BDD nodes (including the constants) + into the topmost level on which this node counts as a cofactor. Takes the topmost + level, on which this node counts as a cofactor (see Extra_ProfileWidthFast(). + Takes the node, for which the table entry should be updated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void extraProfileUpdateTopLevel( st_table * tNodeTopRef, int TopLevelNew, DdNode * node ) +{ + int * pTopLevel; + + if ( st_find_or_add( tNodeTopRef, (char*)node, (char***)&pTopLevel ) ) + { // the node is already referenced + // the current top level should be updated if it is larger than the new level + if ( *pTopLevel > TopLevelNew ) + *pTopLevel = TopLevelNew; + } + else + { // the node is not referenced + // its level should be set to the current new level + *pTopLevel = TopLevelNew; + } +} +/**Function************************************************************* + + Synopsis [Fast computation of the BDD profile.] + + Description [The array to store the profile is given by the user and should + contain at least as many entries as there is the maximum of the BDD/ZDD + size of the manager PLUS ONE. + When we say that the widths of the DD on level L is W, we mean the following. + Let us create the cut between the level L-1 and the level L and count the number + of different DD nodes pointed to across the cut. This number is the width W. + From this it follows the on level 0, the width is equal to the number of external + pointers to the considered DDs. If there is only one DD, then the profile on + level 0 is always 1. If this DD is rooted in the topmost variable, then the width + on level 1 is always 2, etc. The width at the level equal to dd->size is the + number of terminal nodes in the DD. (Because we consider the first level #0 + and the last level #dd->size, the profile array should contain dd->size+1 entries.) + ] + + SideEffects [This procedure will not work for BDDs w/ complement edges, only for ADDs and ZDDs] + + SeeAlso [] + +***********************************************************************/ +int Extra_ProfileWidth( DdManager * dd, DdNode * Func, int * pProfile, int CutLevel ) +{ + st_generator * gen; + st_table * tNodeTopRef; // this table stores the top level from which this node is pointed to + st_table * tNodes; + DdNode * node; + DdNode * nodeR; + int LevelStart, Limit; + int i, size; + int WidthMax; + + // start the mapping table + tNodeTopRef = st_init_table(st_ptrcmp,st_ptrhash); + // add the topmost node to the profile + extraProfileUpdateTopLevel( tNodeTopRef, 0, Func ); + + // collect all nodes + tNodes = Extra_CollectNodes( Func ); + // go though all the nodes and set the top level the cofactors are pointed from +// Cudd_ForeachNode( dd, Func, genDD, node ) + st_foreach_item( tNodes, gen, (char**)&node, NULL ) + { +// assert( Cudd_Regular(node) ); // this procedure works only with ADD/ZDD (not BDD w/ compl.edges) + nodeR = Cudd_Regular(node); + if ( cuddIsConstant(nodeR) ) + continue; + // this node is not a constant - consider its cofactors + extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddE(nodeR) ); + extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddT(nodeR) ); + } + st_free_table( tNodes ); + + // clean the profile + size = ddMax(dd->size, dd->sizeZ) + 1; + for ( i = 0; i < size; i++ ) + pProfile[i] = 0; + + // create the profile + st_foreach_item( tNodeTopRef, gen, (char**)&node, (char**)&LevelStart ) + { + nodeR = Cudd_Regular(node); + Limit = (cuddIsConstant(nodeR))? dd->size: dd->perm[nodeR->index]; + for ( i = LevelStart; i <= Limit; i++ ) + pProfile[i]++; + } + + if ( CutLevel != -1 && CutLevel != 0 ) + size = CutLevel; + + // get the max width + WidthMax = 0; + for ( i = 0; i < size; i++ ) + if ( WidthMax < pProfile[i] ) + WidthMax = pProfile[i]; + + // deref the table + st_free_table( tNodeTopRef ); + + return WidthMax; +} /* end of Extra_ProfileWidth */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes the non-strict codes when evaluation is finished.] + + Description [The information about the best code is stored in s_VarOrderBest, + which has s_nVarsBest entries.] + + SideEffects [None] + +******************************************************************************/ +DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars ) +// bEncoded is the preliminarily encoded set of columns +// Level is the current level in the recursion +// pCVars are the variables to be used for encoding +{ + DdNode * bRes; + if ( Level == s_nVarsBest ) + { // the terminal case, when we need to remap the encoded function + // from the preliminary encoded variables to the new ones + st_table * CutNodes; + int nCols; +// double nMints; +/* +#ifdef _DEBUG + + { + DdNode * bTemp; + // make sure that the given number of variables is enough + bTemp = Cudd_bddExistAbstract( dd, bEncoded, s_VarAll ); Cudd_Ref( bTemp ); +// nMints = Cudd_CountMinterm( dd, bTemp, s_MultiStart ); + nMints = Extra_CountMintermsSimple( bTemp, (1< Extra_Power2( s_MultiStart-Level ) ) + { // the number of minterms is too large to encode the columns + // using the given minimum number of encoding variables + assert( 0 ); + } + Cudd_RecursiveDeref( dd, bTemp ); + } +#endif +*/ + // get the columns to be re-encoded + CutNodes = Extra_bddNodePathsUnderCut( dd, bEncoded, s_EncodingVarsLevel ); + // LUT size is the cut level because because the temporary encoding variables + // are above the functional variables - this is not true!!! + // the temporary variables are below! + + // put the entries from the table into the temporary array + { + st_generator * gen; + DdNode * bColumn, * bCode; + nCols = 0; + st_foreach_item( CutNodes, gen, (char**)&bCode, (char**)&bColumn ) + { + if ( bCode == b0 ) + { // the unused part of the columns + Cudd_RecursiveDeref( dd, bColumn ); + Cudd_RecursiveDeref( dd, bCode ); + continue; + } + else + { + s_pbTemp[ nCols ] = bColumn; // takes ref + Cudd_RecursiveDeref( dd, bCode ); + nCols++; + } + } + st_free_table( CutNodes ); +// assert( nCols == (int)nMints ); + } + + // encode the columns + if ( s_MultiStart-Level == 0 ) // we reached the bottom level of recursion + { + assert( nCols == 1 ); +// assert( (int)nMints == 1 ); + bRes = s_pbTemp[0]; Cudd_Ref( bRes ); + } + else + { + bRes = Extra_bddEncodingBinary( dd, s_pbTemp, nCols, pCVars+Level, s_MultiStart-Level ); Cudd_Ref( bRes ); + } + + // deref the columns + { + int i; + for ( i = 0; i < nCols; i++ ) + Cudd_RecursiveDeref( dd, s_pbTemp[i] ); + } + } + else + { + // cofactor the problem as specified in the best solution + DdNode * bCof0, * bCof1; + DdNode * bRes0, * bRes1; + DdNode * bProd0, * bProd1; + DdNode * bTemp; + DdNode * bVarNext = dd->vars[ s_VarOrderBest[Level] ]; + + bCof0 = Cudd_Cofactor( dd, bEncoded, Cudd_Not( bVarNext ) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_Cofactor( dd, bEncoded, bVarNext ); Cudd_Ref( bCof1 ); + + // call recursively + bRes0 = CreateTheCodes_rec( dd, bCof0, Level+1, pCVars ); Cudd_Ref( bRes0 ); + bRes1 = CreateTheCodes_rec( dd, bCof1, Level+1, pCVars ); Cudd_Ref( bRes1 ); + + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); + + // compose the result using the identity (bVarNext <=> pCVars[Level]) - this is wrong! + // compose the result as follows: x'y'F0 + xyF1 + bProd0 = Cudd_bddAnd( dd, Cudd_Not(bVarNext), Cudd_Not(pCVars[Level]) ); Cudd_Ref( bProd0 ); + bProd1 = Cudd_bddAnd( dd, bVarNext , pCVars[Level] ); Cudd_Ref( bProd1 ); + + bProd0 = Cudd_bddAnd( dd, bTemp = bProd0, bRes0 ); Cudd_Ref( bProd0 ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bRes0 ); + + bProd1 = Cudd_bddAnd( dd, bTemp = bProd1, bRes1 ); Cudd_Ref( bProd1 ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bRes1 ); + + bRes = Cudd_bddOr( dd, bProd0, bProd1 ); Cudd_Ref( bRes ); + + Cudd_RecursiveDeref( dd, bProd0 ); + Cudd_RecursiveDeref( dd, bProd1 ); + } + Cudd_Deref( bRes ); + return bRes; +} + +/**Function******************************************************************** + + Synopsis [Computes the current set of variables and counts the number of minterms.] + + Description [Old implementation.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level ) +// bVarsCol is the set of remaining variables +// nVarsCol is the number of remaining variables +// nMulti is the number of encoding variables to be used +// Level is the level of recursion, from which this function is called +// if we successfully finish this procedure, Level also stands for how many encoding variabled we saved +{ + int i, k; + int nEntries = (1<<(Level-1)); // the number of entries in the field of the previous level + DdNode * bVars0, * bVars1; // the cofactors + unsigned nMint0, nMint1; // the number of minterms + DdNode * bTempV; + DdNode * bVarTop; + int fBreak; + + + // there is no need to search above this level + if ( Level > s_MaxDepth ) + return; + + // if there are no variables left, quit the research + if ( bVarsCol == b1 ) + return; + + if ( s_BackTracks > s_BackTrackLimit ) + return; + + s_BackTracks++; + + // otherwise, go through the remaining variables + for ( bTempV = bVarsCol; bTempV != b1; bTempV = cuddT(bTempV) ) + { + // the currently tested variable + bVarTop = dd->vars[bTempV->index]; + + // put it into the array + s_VarOrderCur[Level-1] = bTempV->index; + + // go through the entries and fill them out by cofactoring + fBreak = 0; + for ( i = 0; i < nEntries; i++ ) + { + bVars0 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], Cudd_Not(bVarTop), &nMint0 ); + Cudd_Ref( bVars0 ); + + if ( nMint0 > Extra_Power2( nMulti-1 ) ) + { + // there is no way to encode - dereference and return + Cudd_RecursiveDeref( dd, bVars0 ); + fBreak = 1; + break; + } + + bVars1 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], bVarTop, &nMint1 ); + Cudd_Ref( bVars1 ); + + if ( nMint1 > Extra_Power2( nMulti-1 ) ) + { + // there is no way to encode - dereference and return + Cudd_RecursiveDeref( dd, bVars0 ); + Cudd_RecursiveDeref( dd, bVars1 ); + fBreak = 1; + break; + } + + // otherwise, add these two cofactors + s_Field[Level][2*i + 0] = bVars0; // takes ref + s_Field[Level][2*i + 1] = bVars1; // takes ref + } + + if ( !fBreak ) + { + DdNode * bVarsRem; + // if we ended up here, it means that the cofactors w.r.t. variable bVarTop satisfy the condition + // save this situation + if ( s_nVarsBest < Level ) + { + s_nVarsBest = Level; + // copy the variable assignment + for ( k = 0; k < Level; k++ ) + s_VarOrderBest[k] = s_VarOrderCur[k]; + } + + // call recursively + // get the new variable set + if ( nMulti-1 > 0 ) + { + bVarsRem = Cudd_bddExistAbstract( dd, bVarsCol, bVarTop ); Cudd_Ref( bVarsRem ); + EvaluateEncodings_rec( dd, bVarsRem, nVarsCol-1, nMulti-1, Level+1 ); + Cudd_RecursiveDeref( dd, bVarsRem ); + } + } + + // deref the contents of the array + for ( k = 0; k < i; k++ ) + { + Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 0] ); + Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 1] ); + } + + // if the solution is found, there is no need to continue + if ( s_nVarsBest == s_MaxDepth ) + return; + + // if the solution is found, there is no need to continue + if ( s_nVarsBest == s_MultiStart ) + return; + } + // at this point, we have tried all possible directions in the space of variables +} + +/**Function******************************************************************** + + Synopsis [Computes the current set of variables and counts the number of minterms.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ) +// takes bVars - the variables cofactored so far (some of them may be in negative polarity) +// bVarTop - the topmost variable w.r.t. which to cofactor (may be in negative polarity) +// returns the cost and the new set of variables (bVars & bVarTop) +{ + DdNode * bVarsRes; + + // get the resulting set of variables + bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes ); + + // increment signature before calling Cudd_CountCofactorMinterms() + s_Signature++; + *Cost = Extra_CountCofactorMinterms( dd, s_Encoded, bVarsRes, s_VarAll ); + + Cudd_Deref( bVarsRes ); +// s_CountCalls++; + return bVarsRes; +} + +/**Function******************************************************************** + + Synopsis [Computes the current set of variables and counts the number of minterms.] + + Description [The old implementation, which is approximately 4 times slower.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ) +{ + DdNode * bVarsRes; + DdNode * bCof, * bFun; + + bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes ); + + bCof = Cudd_Cofactor( dd, s_Encoded, bVarsRes ); Cudd_Ref( bCof ); + bFun = Cudd_bddExistAbstract( dd, bCof, s_VarAll ); Cudd_Ref( bFun ); + *Cost = (unsigned)Cudd_CountMinterm( dd, bFun, s_MultiStart ); + Cudd_RecursiveDeref( dd, bFun ); + Cudd_RecursiveDeref( dd, bCof ); + + Cudd_Deref( bVarsRes ); +// s_CountCalls++; + return bVarsRes; +} + + +/**Function******************************************************************** + + Synopsis [Counts the number of encoding minterms pointed to by the cofactor of the function.] + + Description [] + + SideEffects [None] + +******************************************************************************/ +unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll ) +// this function computes how many minterms depending on the encoding variables +// are there in the cofactor of bFunc w.r.t. variables bVarsCof +// bFunc is assumed to depend on variables s_VarsAll +// the variables s_VarsAll should be ordered above the encoding variables +{ + unsigned HKey; + DdNode * bFuncR; + + // if the function is zero, there are no minterms +// if ( bFunc == b0 ) +// return 0; + +// if ( st_lookup(Visited, (char*)bFunc, NULL) ) +// return 0; + +// HKey = hashKey2c( s_Signature, bFuncR ); +// if ( HHTable1[HKey].Sign == s_Signature && HHTable1[HKey].Arg1 == bFuncR ) // this node is visited +// return 0; + + + // check the hash-table + bFuncR = Cudd_Regular(bFunc); +// HKey = hashKey2( s_Signature, bFuncR, _TABLESIZE_COF ); + HKey = hashKey2( s_Signature, bFunc, _TABLESIZE_COF ); + for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF ) +// if ( HHTable1[HKey].Arg1 == bFuncR ) // this node is visited + if ( HHTable1[HKey].Arg1 == bFunc ) // this node is visited + return 0; + + + // if the function is already the code + if ( dd->perm[bFuncR->index] >= s_EncodingVarsLevel ) + { +// st_insert(Visited, (char*)bFunc, NULL); + +// HHTable1[HKey].Sign = s_Signature; +// HHTable1[HKey].Arg1 = bFuncR; + + assert( HHTable1[HKey].Sign != s_Signature ); + HHTable1[HKey].Sign = s_Signature; +// HHTable1[HKey].Arg1 = bFuncR; + HHTable1[HKey].Arg1 = bFunc; + + return Extra_CountMintermsSimple( bFunc, (1<perm[bFuncR->index]; + int LevelC = cuddI(dd,bVarsCofR->index); + int LevelA = dd->perm[bVarsAll->index]; + + int LevelTop = LevelF; + + if ( LevelTop > LevelC ) + LevelTop = LevelC; + + if ( LevelTop > LevelA ) + LevelTop = LevelA; + + // the top var in the function or in cofactoring vars always belongs to the set of all vars + assert( !( LevelTop == LevelF || LevelTop == LevelC ) || LevelTop == LevelA ); + + // cofactor the function + if ( LevelTop == LevelF ) + { + if ( bFuncR != bFunc ) // bFunc is complemented + { + bFunc0 = Cudd_Not( cuddE(bFuncR) ); + bFunc1 = Cudd_Not( cuddT(bFuncR) ); + } + else + { + bFunc0 = cuddE(bFuncR); + bFunc1 = cuddT(bFuncR); + } + } + else // bVars is higher in the variable order + bFunc0 = bFunc1 = bFunc; + + // cofactor the cube + if ( LevelTop == LevelC ) + { + if ( bVarsCofR != bVarsCof ) // bFunc is complemented + { + bVarsCof0 = Cudd_Not( cuddE(bVarsCofR) ); + bVarsCof1 = Cudd_Not( cuddT(bVarsCofR) ); + } + else + { + bVarsCof0 = cuddE(bVarsCofR); + bVarsCof1 = cuddT(bVarsCofR); + } + } + else // bVars is higher in the variable order + bVarsCof0 = bVarsCof1 = bVarsCof; + + // there are two cases: + // (1) the top variable belongs to the cofactoring variables + // (2) the top variable does not belong to the cofactoring variables + + // (1) the top variable belongs to the cofactoring variables + Res = 0; + if ( LevelTop == LevelC ) + { + if ( bVarsCof1 == b0 ) // this is a negative cofactor + { + if ( bFunc0 != b0 ) + Res = Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) ); + } + else // this is a positive cofactor + { + if ( bFunc1 != b0 ) + Res = Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) ); + } + } + else + { + if ( bFunc0 != b0 ) + Res += Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) ); + + if ( bFunc1 != b0 ) + Res += Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) ); + } + +// st_insert(Visited, (char*)bFunc, NULL); + +// HHTable1[HKey].Sign = s_Signature; +// HHTable1[HKey].Arg1 = bFuncR; + + // skip through the entries with the same signatures + // (these might have been created at the time of recursive calls) + for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF ); + assert( HHTable1[HKey].Sign != s_Signature ); + HHTable1[HKey].Sign = s_Signature; +// HHTable1[HKey].Arg1 = bFuncR; + HHTable1[HKey].Arg1 = bFunc; + + return Res; + } +} + +/**Function******************************************************************** + + Synopsis [Counts the number of minterms.] + + Description [This function counts minterms for functions up to 32 variables + using a local cache. The terminal value (s_Termina) should be adjusted for + BDDs and ADDs.] + + SideEffects [None] + +******************************************************************************/ +unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max ) +{ + unsigned HKey; + + // normalize + if ( Cudd_IsComplement(bFunc) ) + return max - Extra_CountMintermsSimple( Cudd_Not(bFunc), max ); + + // now it is known that the function is not complemented + if ( cuddIsConstant(bFunc) ) + return ((bFunc==s_Terminal)? 0: max); + + // check cache + HKey = hashKey2( bFunc, max, _TABLESIZE_MINT ); + if ( HHTable2[HKey].Arg1 == bFunc && HHTable2[HKey].Arg2 == max ) + return HHTable2[HKey].Res; + else + { + // min = min0/2 + min1/2; + unsigned min = (Extra_CountMintermsSimple( cuddE(bFunc), max ) >> 1) + + (Extra_CountMintermsSimple( cuddT(bFunc), max ) >> 1); + + HHTable2[HKey].Arg1 = bFunc; + HHTable2[HKey].Arg2 = max; + HHTable2[HKey].Res = min; + + return min; + } +} /* end of Extra_CountMintermsSimple */ + + +/**Function******************************************************************** + + Synopsis [Visits the nodes.] + + Description [Visits the nodes above the cut and the nodes pointed to below the cut; + collects the visited nodes, counts how many times each node is visited, and sets + the path-sum to be the constant zero BDD.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st_table * Visited ) + +{ + traventry * p; + char **slot; + if ( st_find_or_add(Visited, (char*)aFunc, &slot) ) + { // the entry already exists + p = (traventry*) *slot; + // increment the counter of incoming edges + p->nEdges++; + return; + } + // this node has not been visited + assert( !Cudd_IsComplement(aFunc) ); + + // create the new traversal entry + p = (traventry *) malloc( sizeof(traventry) ); + // set the initial sum of edges to zero BDD + p->bSum = b0; Cudd_Ref( b0 ); + // set the starting number of incoming edges + p->nEdges = 1; + // set this entry into the slot + *slot = (char*)p; + + // recur if the node is above the cut + if ( cuddI(dd,aFunc->index) < s_CutLevel ) + { + CountNodeVisits_rec( dd, cuddE(aFunc), Visited ); + CountNodeVisits_rec( dd, cuddT(aFunc), Visited ); + } +} /* end of CountNodeVisits_rec */ + + +/**Function******************************************************************** + + Synopsis [Revisits the nodes and computes the paths.] + + Description [This function visits the nodes above the cut having the goal of + summing all the incomming BDD edges; when this function comes across the node + below the cut, it saves this node in the CutNode table.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st_table * Visited, st_table * CutNodes ) +{ + // find the node in the visited table + DdNode * bTemp; + traventry * p; + char **slot; + if ( st_find_or_add(Visited, (char*)aFunc, &slot) ) + { // the node is found + // get the pointer to the traversal entry + p = (traventry*) *slot; + + // make sure that the counter of incoming edges is positive + assert( p->nEdges > 0 ); + + // add the cube to the currently accumulated cubes + p->bSum = Cudd_bddOr( dd, bTemp = p->bSum, bCube ); Cudd_Ref( p->bSum ); + Cudd_RecursiveDeref( dd, bTemp ); + + // decrement the number of visits + p->nEdges--; + + // if more visits to this node are expected, return + if ( p->nEdges ) + return; + else // if ( p->nEdges == 0 ) + { // this is the last visit - propagate the cube + + // check where this node is + if ( cuddI(dd,aFunc->index) < s_CutLevel ) + { // the node is above the cut + DdNode * bCube0, * bCube1; + + // get the top-most variable + DdNode * bVarTop = dd->vars[aFunc->index]; + + // compute the propagated cubes + bCube0 = Cudd_bddAnd( dd, p->bSum, Cudd_Not( bVarTop ) ); Cudd_Ref( bCube0 ); + bCube1 = Cudd_bddAnd( dd, p->bSum, bVarTop ); Cudd_Ref( bCube1 ); + + // call recursively + CollectNodesAndComputePaths_rec( dd, cuddE(aFunc), bCube0, Visited, CutNodes ); + CollectNodesAndComputePaths_rec( dd, cuddT(aFunc), bCube1, Visited, CutNodes ); + + // dereference the cubes + Cudd_RecursiveDeref( dd, bCube0 ); + Cudd_RecursiveDeref( dd, bCube1 ); + return; + } + else + { // the node is below the cut + // add this node to the cut node table, if it is not yet there + +// DdNode * bNode; +// bNode = Cudd_addBddPattern( dd, aFunc ); Cudd_Ref( bNode ); + if ( st_find_or_add(CutNodes, (char*)aFunc, &slot) ) + { // the node exists - should never happen + assert( 0 ); + } + *slot = (char*) p->bSum; Cudd_Ref( p->bSum ); + // the table takes the reference of bNode + return; + } + } + } + + // the node does not exist in the visited table - should never happen + assert(0); + +} /* end of CollectNodesAndComputePaths_rec */ + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/misc/extra/extraBddKmap.c b/abc70930/src/misc/extra/extraBddKmap.c new file mode 100644 index 00000000..bb43db68 --- /dev/null +++ b/abc70930/src/misc/extra/extraBddKmap.c @@ -0,0 +1,783 @@ +/**CFile**************************************************************** + + FileName [extraBddKmap.c] + + PackageName [extra] + + Synopsis [Visualizing the K-map.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddKmap.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] + +***********************************************************************/ + +/// K-map visualization using pseudo graphics /// +/// Version 1.0. Started - August 20, 2000 /// +/// Version 2.0. Added to EXTRA - July 17, 2001 /// + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +// the maximum number of variables in the Karnaugh Map +#define MAXVARS 20 + +/* +// single line +#define SINGLE_VERTICAL (char)179 +#define SINGLE_HORIZONTAL (char)196 +#define SINGLE_TOP_LEFT (char)218 +#define SINGLE_TOP_RIGHT (char)191 +#define SINGLE_BOT_LEFT (char)192 +#define SINGLE_BOT_RIGHT (char)217 + +// double line +#define DOUBLE_VERTICAL (char)186 +#define DOUBLE_HORIZONTAL (char)205 +#define DOUBLE_TOP_LEFT (char)201 +#define DOUBLE_TOP_RIGHT (char)187 +#define DOUBLE_BOT_LEFT (char)200 +#define DOUBLE_BOT_RIGHT (char)188 + +// line intersections +#define SINGLES_CROSS (char)197 +#define DOUBLES_CROSS (char)206 +#define S_HOR_CROSS_D_VER (char)215 +#define S_VER_CROSS_D_HOR (char)216 + +// single line joining +#define S_JOINS_S_VER_LEFT (char)180 +#define S_JOINS_S_VER_RIGHT (char)195 +#define S_JOINS_S_HOR_TOP (char)193 +#define S_JOINS_S_HOR_BOT (char)194 + +// double line joining +#define D_JOINS_D_VER_LEFT (char)185 +#define D_JOINS_D_VER_RIGHT (char)204 +#define D_JOINS_D_HOR_TOP (char)202 +#define D_JOINS_D_HOR_BOT (char)203 + +// single line joining double line +#define S_JOINS_D_VER_LEFT (char)182 +#define S_JOINS_D_VER_RIGHT (char)199 +#define S_JOINS_D_HOR_TOP (char)207 +#define S_JOINS_D_HOR_BOT (char)209 +*/ + +// single line +#define SINGLE_VERTICAL (char)'|' +#define SINGLE_HORIZONTAL (char)'-' +#define SINGLE_TOP_LEFT (char)'+' +#define SINGLE_TOP_RIGHT (char)'+' +#define SINGLE_BOT_LEFT (char)'+' +#define SINGLE_BOT_RIGHT (char)'+' + +// double line +#define DOUBLE_VERTICAL (char)'|' +#define DOUBLE_HORIZONTAL (char)'-' +#define DOUBLE_TOP_LEFT (char)'+' +#define DOUBLE_TOP_RIGHT (char)'+' +#define DOUBLE_BOT_LEFT (char)'+' +#define DOUBLE_BOT_RIGHT (char)'+' + +// line intersections +#define SINGLES_CROSS (char)'+' +#define DOUBLES_CROSS (char)'+' +#define S_HOR_CROSS_D_VER (char)'+' +#define S_VER_CROSS_D_HOR (char)'+' + +// single line joining +#define S_JOINS_S_VER_LEFT (char)'+' +#define S_JOINS_S_VER_RIGHT (char)'+' +#define S_JOINS_S_HOR_TOP (char)'+' +#define S_JOINS_S_HOR_BOT (char)'+' + +// double line joining +#define D_JOINS_D_VER_LEFT (char)'+' +#define D_JOINS_D_VER_RIGHT (char)'+' +#define D_JOINS_D_HOR_TOP (char)'+' +#define D_JOINS_D_HOR_BOT (char)'+' + +// single line joining double line +#define S_JOINS_D_VER_LEFT (char)'+' +#define S_JOINS_D_VER_RIGHT (char)'+' +#define S_JOINS_D_HOR_TOP (char)'+' +#define S_JOINS_D_HOR_BOT (char)'+' + + +// other symbols +#define UNDERSCORE (char)95 +//#define SYMBOL_ZERO (char)248 // degree sign +//#define SYMBOL_ZERO (char)'o' +#define SYMBOL_ZERO (char)' ' +#define SYMBOL_ONE (char)'1' +#define SYMBOL_DC (char)'-' +#define SYMBOL_OVERLAP (char)'?' + +// full cells and half cells +#define CELL_FREE (char)32 +#define CELL_FULL (char)219 +#define HALF_UPPER (char)223 +#define HALF_LOWER (char)220 +#define HALF_LEFT (char)221 +#define HALF_RIGHT (char)222 + + +/*---------------------------------------------------------------------------*/ +/* Structure declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +// the array of BDD variables used internally +static DdNode * s_XVars[MAXVARS]; + +// flag which determines where the horizontal variable names are printed +static int fHorizontalVarNamesPrintedAbove = 1; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +// Oleg's way of generating the gray code +static int GrayCode( int BinCode ); +static int BinCode ( int GrayCode ); + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Prints the K-map of the function.] + + Description [If the pointer to the array of variables XVars is NULL, + fSuppType determines how the support will be determined. + fSuppType == 0 -- takes the first nVars of the manager + fSuppType == 1 -- takes the topmost nVars of the manager + fSuppType == 2 -- determines support from the on-set and the offset + ] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_PrintKMap( + FILE * Output, /* the output stream */ + DdManager * dd, + DdNode * OnSet, + DdNode * OffSet, + int nVars, + DdNode ** XVars, + int fSuppType, /* the flag which determines how support is computed */ + char ** pVarNames ) +{ + int d, p, n, s, v, h, w; + int nVarsVer; + int nVarsHor; + int nCellsVer; + int nCellsHor; + int nSkipSpaces; + + // make sure that on-set and off-set do not overlap + if ( !Cudd_bddLeq( dd, OnSet, Cudd_Not(OffSet) ) ) + { + fprintf( Output, "PrintKMap(): The on-set and the off-set overlap\n" ); + return; + } +/* + if ( OnSet == b1 ) + { + fprintf( Output, "PrintKMap(): Constant 1\n" ); + return; + } + if ( OffSet == b1 ) + { + fprintf( Output, "PrintKMap(): Constant 0\n" ); + return; + } +*/ + if ( nVars < 0 || nVars > MAXVARS ) + { + fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS ); + return; + } + + // determine the support if it is not given + if ( XVars == NULL ) + { + if ( fSuppType == 0 ) + { // assume that the support includes the first nVars of the manager + assert( nVars ); + for ( v = 0; v < nVars; v++ ) + s_XVars[v] = Cudd_bddIthVar( dd, v ); + } + else if ( fSuppType == 1 ) + { // assume that the support includes the topmost nVars of the manager + assert( nVars ); + for ( v = 0; v < nVars; v++ ) + s_XVars[v] = Cudd_bddIthVar( dd, dd->invperm[v] ); + } + else // determine the support + { + DdNode * SuppOn, * SuppOff, * Supp; + int cVars = 0; + DdNode * TempSupp; + + // determine support + SuppOn = Cudd_Support( dd, OnSet ); Cudd_Ref( SuppOn ); + SuppOff = Cudd_Support( dd, OffSet ); Cudd_Ref( SuppOff ); + Supp = Cudd_bddAnd( dd, SuppOn, SuppOff ); Cudd_Ref( Supp ); + Cudd_RecursiveDeref( dd, SuppOn ); + Cudd_RecursiveDeref( dd, SuppOff ); + + nVars = Cudd_SupportSize( dd, Supp ); + if ( nVars > MAXVARS ) + { + fprintf( Output, "PrintKMap(): The number of variables is more than %d\n", MAXVARS ); + Cudd_RecursiveDeref( dd, Supp ); + return; + } + + // assign variables + for ( TempSupp = Supp; TempSupp != dd->one; TempSupp = Cudd_T(TempSupp), cVars++ ) + s_XVars[cVars] = Cudd_bddIthVar( dd, TempSupp->index ); + + Cudd_RecursiveDeref( dd, TempSupp ); + } + } + else + { + // copy variables + assert( XVars ); + for ( v = 0; v < nVars; v++ ) + s_XVars[v] = XVars[v]; + } + + //////////////////////////////////////////////////////////////////// + // determine the Karnaugh map parameters + nVarsVer = nVars/2; + nVarsHor = nVars - nVarsVer; + nCellsVer = (1< MAXVARS ) + { + fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS ); + return; + } + + + //////////////////////////////////////////////////////////////////// + // determine the Karnaugh map parameters + nVarsVer = nXVars; + nVarsHor = nYVars; + nCellsVer = (1<> 1 ); +} + +/**Function******************************************************************** + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int BinCode ( int GrayCode ) +{ + int bc = GrayCode; + while( GrayCode >>= 1 ) bc ^= GrayCode; + return bc; +} + + diff --git a/abc70930/src/misc/extra/extraBddMisc.c b/abc70930/src/misc/extra/extraBddMisc.c new file mode 100644 index 00000000..a3320ad3 --- /dev/null +++ b/abc70930/src/misc/extra/extraBddMisc.c @@ -0,0 +1,1614 @@ +/**CFile**************************************************************** + + FileName [extraBddMisc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [DD-based utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraBddMisc.c,v 1.4 2005/10/04 00:19:54 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +// file "extraDdTransfer.c" +static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st_table * table, int * Permute ); +static DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ); +static DdNode * cuddBddPermuteRecur ARGS( ( DdManager * manager, DdHashTable * table, DdNode * node, int *permut ) ); + +// file "cuddUtils.c" +static void ddSupportStep(DdNode *f, int *support); +static void ddClearFlag(DdNode *f); + +static DdNode* extraZddPrimes( DdManager *dd, DdNode* F ); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Convert a {A,B}DD from a manager to another with variable remapping.] + + Description [Convert a {A,B}DD from a manager to another one. The orders of the + variables in the two managers may be different. Returns a + pointer to the {A,B}DD in the destination manager if successful; NULL + otherwise. The i-th entry in the array Permute tells what is the index + of the i-th variable from the old manager in the new manager.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ) +{ + DdNode * bRes; + do + { + ddDestination->reordered = 0; + bRes = extraTransferPermute( ddSource, ddDestination, f, Permute ); + } + while ( ddDestination->reordered == 1 ); + return ( bRes ); + +} /* end of Extra_TransferPermute */ + +/**Function******************************************************************** + + Synopsis [Transfers the BDD from one manager into another level by level.] + + Description [Transfers the BDD from one manager into another while + preserving the correspondence between variables level by level.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ) +{ + DdNode * bRes; + int * pPermute; + int nMin, nMax, i; + + nMin = ddMin(ddSource->size, ddDestination->size); + nMax = ddMax(ddSource->size, ddDestination->size); + pPermute = ALLOC( int, nMax ); + // set up the variable permutation + for ( i = 0; i < nMin; i++ ) + pPermute[ ddSource->invperm[i] ] = ddDestination->invperm[i]; + if ( ddSource->size > ddDestination->size ) + { + for ( ; i < nMax; i++ ) + pPermute[ ddSource->invperm[i] ] = -1; + } + bRes = Extra_TransferPermute( ddSource, ddDestination, f, pPermute ); + FREE( pPermute ); + return bRes; +} + +/**Function******************************************************************** + + Synopsis [Remaps the function to depend on the topmost variables on the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddRemapUp( + DdManager * dd, + DdNode * bF ) +{ + int * pPermute; + DdNode * bSupp, * bTemp, * bRes; + int Counter; + + pPermute = ALLOC( int, dd->size ); + + // get support + bSupp = Cudd_Support( dd, bF ); Cudd_Ref( bSupp ); + + // create the variable map + // to remap the DD into the upper part of the manager + Counter = 0; + for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) + pPermute[bTemp->index] = dd->invperm[Counter++]; + + // transfer the BDD and remap it + bRes = Cudd_bddPermute( dd, bF, pPermute ); Cudd_Ref( bRes ); + + // remove support + Cudd_RecursiveDeref( dd, bSupp ); + + // return + Cudd_Deref( bRes ); + free( pPermute ); + return bRes; +} + +/**Function******************************************************************** + + Synopsis [Moves the BDD by the given number of variables up or down.] + + Description [] + + SideEffects [] + + SeeAlso [Extra_bddShift] + +******************************************************************************/ +DdNode * Extra_bddMove( + DdManager * dd, /* the DD manager */ + DdNode * bF, + int nVars) +{ + DdNode * res; + DdNode * bVars; + if ( nVars == 0 ) + return bF; + if ( Cudd_IsConstant(bF) ) + return bF; + assert( nVars <= dd->size ); + if ( nVars > 0 ) + bVars = dd->vars[nVars]; + else + bVars = Cudd_Not(dd->vars[-nVars]); + + do { + dd->reordered = 0; + res = extraBddMove( dd, bF, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_bddMove */ + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_StopManager( DdManager * dd ) +{ + int RetValue; + // check for remaining references in the package + RetValue = Cudd_CheckZeroRef( dd ); + if ( RetValue > 0 ) + printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); +// Cudd_PrintInfo( dd, stdout ); + Cudd_Quit( dd ); +} + +/**Function******************************************************************** + + Synopsis [Outputs the BDD in a readable format.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +void Extra_bddPrint( DdManager * dd, DdNode * F ) +{ + DdGen * Gen; + int * Cube; + CUDD_VALUE_TYPE Value; + int nVars = dd->size; + int fFirstCube = 1; + int i; + + if ( F == NULL ) + { + printf("NULL"); + return; + } + if ( F == b0 ) + { + printf("Constant 0"); + return; + } + if ( F == b1 ) + { + printf("Constant 1"); + return; + } + + Cudd_ForeachCube( dd, F, Gen, Cube, Value ) + { + if ( fFirstCube ) + fFirstCube = 0; + else +// Output << " + "; + printf( " + " ); + + for ( i = 0; i < nVars; i++ ) + if ( Cube[i] == 0 ) + printf( "[%d]'", i ); +// printf( "%c'", (char)('a'+i) ); + else if ( Cube[i] == 1 ) + printf( "[%d]", i ); +// printf( "%c", (char)('a'+i) ); + } + +// printf("\n"); +} +/**Function******************************************************************** + + Synopsis [Returns the size of the support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ) +{ + int Counter = 0; + while ( bSupp != b1 ) + { + assert( !Cudd_IsComplement(bSupp) ); + assert( cuddE(bSupp) == b0 ); + + bSupp = cuddT(bSupp); + Counter++; + } + return Counter; +} + +/**Function******************************************************************** + + Synopsis [Returns 1 if the support contains the given BDD variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ) +{ + for( ; bS != b1; bS = cuddT(bS) ) + if ( bS->index == bVar->index ) + return 1; + return 0; +} + +/**Function******************************************************************** + + Synopsis [Returns 1 if two supports represented as BDD cubes are overlapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ) +{ + while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) + { + // if the top vars are the same, they intersect + if ( S1->index == S2->index ) + return 1; + // if the top vars are different, skip the one, which is higher + if ( dd->perm[S1->index] < dd->perm[S2->index] ) + S1 = cuddT(S1); + else + S2 = cuddT(S2); + } + return 0; +} + +/**Function******************************************************************** + + Synopsis [Returns the number of different vars in two supports.] + + Description [Counts the number of variables that appear in one support and + does not appear in other support. If the number exceeds DiffMax, returns DiffMax.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ) +{ + int Result = 0; + while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) + { + // if the top vars are the same, this var is the same + if ( S1->index == S2->index ) + { + S1 = cuddT(S1); + S2 = cuddT(S2); + continue; + } + // the top var is different + Result++; + + if ( Result >= DiffMax ) + return DiffMax; + + // if the top vars are different, skip the one, which is higher + if ( dd->perm[S1->index] < dd->perm[S2->index] ) + S1 = cuddT(S1); + else + S2 = cuddT(S2); + } + + // consider the remaining variables + if ( S1->index != CUDD_CONST_INDEX ) + Result += Extra_bddSuppSize(dd,S1); + else if ( S2->index != CUDD_CONST_INDEX ) + Result += Extra_bddSuppSize(dd,S2); + + if ( Result >= DiffMax ) + return DiffMax; + return Result; +} + + +/**Function******************************************************************** + + Synopsis [Checks the support containment.] + + Description [This function returns 1 if one support is contained in another. + In this case, bLarge (bSmall) is assigned to point to the larger (smaller) support. + If the supports are identical, return 0 and does not assign the supports!] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ) +{ + DdNode * bSL = bL; + DdNode * bSH = bH; + int fLcontainsH = 1; + int fHcontainsL = 1; + int TopVar; + + if ( bSL == bSH ) + return 0; + + while ( bSL != b1 || bSH != b1 ) + { + if ( bSL == b1 ) + { // Low component has no vars; High components has some vars + fLcontainsH = 0; + if ( fHcontainsL == 0 ) + return 0; + else + break; + } + + if ( bSH == b1 ) + { // similarly + fHcontainsL = 0; + if ( fLcontainsH == 0 ) + return 0; + else + break; + } + + // determine the topmost var of the supports by comparing their levels + if ( dd->perm[bSL->index] < dd->perm[bSH->index] ) + TopVar = bSL->index; + else + TopVar = bSH->index; + + if ( TopVar == bSL->index && TopVar == bSH->index ) + { // they are on the same level + // it does not tell us anything about their containment + // skip this var + bSL = cuddT(bSL); + bSH = cuddT(bSH); + } + else if ( TopVar == bSL->index ) // and TopVar != bSH->index + { // Low components is higher and contains more vars + // it is not possible that High component contains Low + fHcontainsL = 0; + // skip this var + bSL = cuddT(bSL); + } + else // if ( TopVar == bSH->index ) // and TopVar != bSL->index + { // similarly + fLcontainsH = 0; + // skip this var + bSH = cuddT(bSH); + } + + // check the stopping condition + if ( !fHcontainsL && !fLcontainsH ) + return 0; + } + // only one of them can be true at the same time + assert( !fHcontainsL || !fLcontainsH ); + if ( fHcontainsL ) + { + *bLarge = bH; + *bSmall = bL; + } + else // fLcontainsH + { + *bLarge = bL; + *bSmall = bH; + } + return 1; +} + + +/**Function******************************************************************** + + Synopsis [Finds variables on which the DD depends and returns them as am array.] + + Description [Finds the variables on which the DD depends. Returns an array + with entries set to 1 for those variables that belong to the support; + NULL otherwise. The array is allocated by the user and should have at least + as many entries as the maximum number of variables in BDD and ZDD parts of + the manager.] + + SideEffects [None] + + SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport] + +******************************************************************************/ +int * +Extra_SupportArray( + DdManager * dd, /* manager */ + DdNode * f, /* DD whose support is sought */ + int * support ) /* array allocated by the user */ +{ + int i, size; + + /* Initialize support array for ddSupportStep. */ + size = ddMax(dd->size, dd->sizeZ); + for (i = 0; i < size; i++) + support[i] = 0; + + /* Compute support and clean up markers. */ + ddSupportStep(Cudd_Regular(f),support); + ddClearFlag(Cudd_Regular(f)); + + return(support); + +} /* end of Extra_SupportArray */ + +/**Function******************************************************************** + + Synopsis [Finds the variables on which a set of DDs depends.] + + Description [Finds the variables on which a set of DDs depends. + The set must contain either BDDs and ADDs, or ZDDs. + Returns a BDD consisting of the product of the variables if + successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_Support Cudd_ClassifySupport] + +******************************************************************************/ +int * +Extra_VectorSupportArray( + DdManager * dd, /* manager */ + DdNode ** F, /* array of DDs whose support is sought */ + int n, /* size of the array */ + int * support ) /* array allocated by the user */ +{ + int i, size; + + /* Allocate and initialize support array for ddSupportStep. */ + size = ddMax( dd->size, dd->sizeZ ); + for ( i = 0; i < size; i++ ) + support[i] = 0; + + /* Compute support and clean up markers. */ + for ( i = 0; i < n; i++ ) + ddSupportStep( Cudd_Regular(F[i]), support ); + for ( i = 0; i < n; i++ ) + ddClearFlag( Cudd_Regular(F[i]) ); + + return support; +} + +/**Function******************************************************************** + + Synopsis [Find any cube belonging to the on-set of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ) +{ + char * s_Temp; + DdNode * bCube, * bTemp; + int v; + + // get the vector of variables in the cube + s_Temp = ALLOC( char, dd->size ); + Cudd_bddPickOneCube( dd, bF, s_Temp ); + + // start the cube + bCube = b1; Cudd_Ref( bCube ); + for ( v = 0; v < dd->size; v++ ) + if ( s_Temp[v] == 0 ) + { +// Cube &= !s_XVars[v]; + bCube = Cudd_bddAnd( dd, bTemp = bCube, Cudd_Not(dd->vars[v]) ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + else if ( s_Temp[v] == 1 ) + { +// Cube &= s_XVars[v]; + bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[v] ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref(bCube); + free( s_Temp ); + return bCube; +} + +/**Function******************************************************************** + + Synopsis [Returns one cube contained in the given BDD.] + + Description [This function returns the cube with the smallest + bits-to-integer value.] + + SideEffects [] + +******************************************************************************/ +DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bFuncR, * bFunc0, * bFunc1; + DdNode * bRes0, * bRes1, * bRes; + + bFuncR = Cudd_Regular(bFunc); + if ( cuddIsConstant(bFuncR) ) + return bFunc; + + // cofactor + if ( Cudd_IsComplement(bFunc) ) + { + bFunc0 = Cudd_Not( cuddE(bFuncR) ); + bFunc1 = Cudd_Not( cuddT(bFuncR) ); + } + else + { + bFunc0 = cuddE(bFuncR); + bFunc1 = cuddT(bFuncR); + } + + // try to find the cube with the negative literal + bRes0 = Extra_bddGetOneCube( dd, bFunc0 ); Cudd_Ref( bRes0 ); + + if ( bRes0 != b0 ) + { + bRes = Cudd_bddAnd( dd, bRes0, Cudd_Not(dd->vars[bFuncR->index]) ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bRes0 ); + } + else + { + Cudd_RecursiveDeref( dd, bRes0 ); + // try to find the cube with the positive literal + bRes1 = Extra_bddGetOneCube( dd, bFunc1 ); Cudd_Ref( bRes1 ); + assert( bRes1 != b0 ); + bRes = Cudd_bddAnd( dd, bRes1, dd->vars[bFuncR->index] ); Cudd_Ref( bRes ); + Cudd_RecursiveDeref( dd, bRes1 ); + } + + Cudd_Deref( bRes ); + return bRes; +} + +/**Function******************************************************************** + + Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) +{ + DdNode * bTemp, * bProd; + int i; + assert( iStart <= iStop ); + assert( iStart >= 0 && iStart <= dd->size ); + assert( iStop >= 0 && iStop <= dd->size ); + bProd = b1; Cudd_Ref( bProd ); + for ( i = iStart; i < iStop; i++ ) + { + bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bProd ); + return bProd; +} + +/**Function******************************************************************** + + Synopsis [Computes the cube of BDD variables corresponding to bits it the bit-code] + + Description [Returns a bdd composed of elementary bdds found in array BddVars[] such + that the bdd vars encode the number Value of bit length CodeWidth (if fMsbFirst is 1, + the most significant bit is encoded with the first bdd variable). If the variables + BddVars are not specified, takes the first CodeWidth variables of the manager] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ) +{ + int z; + DdNode * bTemp, * bVar, * bVarBdd, * bResult; + + bResult = b1; Cudd_Ref( bResult ); + for ( z = 0; z < CodeWidth; z++ ) + { + bVarBdd = (pbVars)? pbVars[z]: dd->vars[z]; + if ( fMsbFirst ) + bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (CodeWidth-1-z)))==0 ); + else + bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (z)))==0 ); + bResult = Cudd_bddAnd( dd, bTemp = bResult, bVar ); Cudd_Ref( bResult ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bResult ); + + return bResult; +} /* end of Extra_bddBitsToCube */ + +/**Function******************************************************************** + + Synopsis [Finds the support as a negative polarity cube.] + + Description [Finds the variables on which a DD depends. Returns a BDD + consisting of the product of the variables in the negative polarity + if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [Cudd_VectorSupport Cudd_Support] + +******************************************************************************/ +DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ) +{ + int *support; + DdNode *res, *tmp, *var; + int i, j; + int size; + + /* Allocate and initialize support array for ddSupportStep. */ + size = ddMax( dd->size, dd->sizeZ ); + support = ALLOC( int, size ); + if ( support == NULL ) + { + dd->errorCode = CUDD_MEMORY_OUT; + return ( NULL ); + } + for ( i = 0; i < size; i++ ) + { + support[i] = 0; + } + + /* Compute support and clean up markers. */ + ddSupportStep( Cudd_Regular( f ), support ); + ddClearFlag( Cudd_Regular( f ) ); + + /* Transform support from array to cube. */ + do + { + dd->reordered = 0; + res = DD_ONE( dd ); + cuddRef( res ); + for ( j = size - 1; j >= 0; j-- ) + { /* for each level bottom-up */ + i = ( j >= dd->size ) ? j : dd->invperm[j]; + if ( support[i] == 1 ) + { + var = cuddUniqueInter( dd, i, dd->one, Cudd_Not( dd->one ) ); + ////////////////////////////////////////////////////////////////// + var = Cudd_Not(var); + ////////////////////////////////////////////////////////////////// + cuddRef( var ); + tmp = cuddBddAndRecur( dd, res, var ); + if ( tmp == NULL ) + { + Cudd_RecursiveDeref( dd, res ); + Cudd_RecursiveDeref( dd, var ); + res = NULL; + break; + } + cuddRef( tmp ); + Cudd_RecursiveDeref( dd, res ); + Cudd_RecursiveDeref( dd, var ); + res = tmp; + } + } + } + while ( dd->reordered == 1 ); + + FREE( support ); + if ( res != NULL ) + cuddDeref( res ); + return ( res ); + +} /* end of Extra_SupportNeg */ + +/**Function******************************************************************** + + Synopsis [Returns 1 if the BDD is the BDD of elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddIsVar( DdNode * bFunc ) +{ + bFunc = Cudd_Regular( bFunc ); + if ( cuddIsConstant(bFunc) ) + return 0; + return cuddIsConstant( cuddT(bFunc) ) && cuddIsConstant( Cudd_Regular(cuddE(bFunc)) ); +} + +/**Function******************************************************************** + + Synopsis [Creates AND composed of the first nVars of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ) +{ + DdNode * bFunc, * bTemp; + int i; + bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); + for ( i = 0; i < nVars; i++ ) + { + bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function******************************************************************** + + Synopsis [Creates OR composed of the first nVars of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ) +{ + DdNode * bFunc, * bTemp; + int i; + bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); + for ( i = 0; i < nVars; i++ ) + { + bFunc = Cudd_bddOr( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function******************************************************************** + + Synopsis [Creates EXOR composed of the first nVars of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ) +{ + DdNode * bFunc, * bTemp; + int i; + bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); + for ( i = 0; i < nVars; i++ ) + { + bFunc = Cudd_bddXor( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Cudd_Deref( bFunc ); + return bFunc; +} + +/**Function******************************************************************** + + Synopsis [Computes the set of primes as a ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ) +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddPrimes(dd, F); + if ( dd->reordered == 1 ) + printf("\nReordering in Extra_zddPrimes()\n"); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddPrimes */ + +/**Function******************************************************************** + + Synopsis [Permutes the variables of the array of BDDs.] + + Description [Given a permutation in array permut, creates a new BDD + with permuted variables. There should be an entry in array permut + for each variable in the manager. The i-th entry of permut holds the + index of the variable that is to substitute the i-th variable. + The DDs in the resulting array are already referenced.] + + SideEffects [None] + + SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] + +******************************************************************************/ +void Extra_bddPermuteArray( DdManager * manager, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ) +{ + DdHashTable *table; + int i, k; + do + { + manager->reordered = 0; + table = cuddHashTableInit( manager, 1, 2 ); + + /* permute the output functions one-by-one */ + for ( i = 0; i < nNodes; i++ ) + { + bNodesOut[i] = cuddBddPermuteRecur( manager, table, bNodesIn[i], permut ); + if ( bNodesOut[i] == NULL ) + { + /* deref the array of the already computed outputs */ + for ( k = 0; k < i; k++ ) + Cudd_RecursiveDeref( manager, bNodesOut[k] ); + break; + } + cuddRef( bNodesOut[i] ); + } + /* Dispose of local cache. */ + cuddHashTableQuit( table ); + } + while ( manager->reordered == 1 ); +} /* end of Extra_bddPermuteArray */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraBddMove( + DdManager * dd, /* the DD manager */ + DdNode * bF, + DdNode * bDist) +{ + DdNode * bRes; + + if ( Cudd_IsConstant(bF) ) + return bF; + + if ( bRes = cuddCacheLookup2(dd, extraBddMove, bF, bDist) ) + return bRes; + else + { + DdNode * bRes0, * bRes1; + DdNode * bF0, * bF1; + DdNode * bFR = Cudd_Regular(bF); + int VarNew; + + if ( Cudd_IsComplement(bDist) ) + VarNew = bFR->index - Cudd_Not(bDist)->index; + else + VarNew = bFR->index + bDist->index; + assert( VarNew < dd->size ); + + // cofactor the functions + if ( bFR != bF ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + bRes0 = extraBddMove( dd, bF0, bDist ); + if ( bRes0 == NULL ) + return NULL; + cuddRef( bRes0 ); + + bRes1 = extraBddMove( dd, bF1, bDist ); + if ( bRes1 == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + return NULL; + } + cuddRef( bRes1 ); + + /* only bRes0 and bRes1 are referenced at this point */ + bRes = cuddBddIteRecur( dd, dd->vars[VarNew], bRes1, bRes0 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bRes1 ); + return NULL; + } + cuddRef( bRes ); + Cudd_RecursiveDeref( dd, bRes0 ); + Cudd_RecursiveDeref( dd, bRes1 ); + + /* insert the result into cache */ + cuddCacheInsert2( dd, extraBddMove, bF, bDist, bRes ); + cuddDeref( bRes ); + return bRes; + } +} /* end of extraBddMove */ + + +/**Function******************************************************************** + + Synopsis [Finds three cofactors of the cover w.r.t. to the topmost variable.] + + Description [Finds three cofactors of the cover w.r.t. to the topmost variable. + Does not check the cover for being a constant. Assumes that ZDD variables encoding + positive and negative polarities are adjacent in the variable order. Is different + from cuddZddGetCofactors3() in that it does not compute the cofactors w.r.t. the + given variable but takes the cofactors with respent to the topmost variable. + This function is more efficient when used in recursive procedures because it does + not require referencing of the resulting cofactors (compare cuddZddProduct() + and extraZddPrimeProduct()).] + + SideEffects [None] + + SeeAlso [cuddZddGetCofactors3] + +******************************************************************************/ +void +extraDecomposeCover( + DdManager* dd, /* the manager */ + DdNode* zC, /* the cover */ + DdNode** zC0, /* the pointer to the negative var cofactor */ + DdNode** zC1, /* the pointer to the positive var cofactor */ + DdNode** zC2 ) /* the pointer to the cofactor without var */ +{ + if ( (zC->index & 1) == 0 ) + { /* the top variable is present in positive polarity and maybe in negative */ + + DdNode *Temp = cuddE( zC ); + *zC1 = cuddT( zC ); + if ( cuddIZ(dd,Temp->index) == cuddIZ(dd,zC->index) + 1 ) + { /* Temp is not a terminal node + * top var is present in negative polarity */ + *zC2 = cuddE( Temp ); + *zC0 = cuddT( Temp ); + } + else + { /* top var is not present in negative polarity */ + *zC2 = Temp; + *zC0 = dd->zero; + } + } + else + { /* the top variable is present only in negative */ + *zC1 = dd->zero; + *zC2 = cuddE( zC ); + *zC0 = cuddT( zC ); + } +} /* extraDecomposeCover */ + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Convert a BDD from a manager to another one.] + + Description [Convert a BDD from a manager to another one. Returns a + pointer to the BDD in the destination manager if successful; NULL + otherwise.] + + SideEffects [None] + + SeeAlso [Extra_TransferPermute] + +******************************************************************************/ +DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ) +{ + DdNode *res; + st_table *table = NULL; + st_generator *gen = NULL; + DdNode *key, *value; + + table = st_init_table( st_ptrcmp, st_ptrhash ); + if ( table == NULL ) + goto failure; + res = extraTransferPermuteRecur( ddS, ddD, f, table, Permute ); + if ( res != NULL ) + cuddRef( res ); + + /* Dereference all elements in the table and dispose of the table. + ** This must be done also if res is NULL to avoid leaks in case of + ** reordering. */ + gen = st_init_gen( table ); + if ( gen == NULL ) + goto failure; + while ( st_gen( gen, ( char ** ) &key, ( char ** ) &value ) ) + { + Cudd_RecursiveDeref( ddD, value ); + } + st_free_gen( gen ); + gen = NULL; + st_free_table( table ); + table = NULL; + + if ( res != NULL ) + cuddDeref( res ); + return ( res ); + + failure: + if ( table != NULL ) + st_free_table( table ); + if ( gen != NULL ) + st_free_gen( gen ); + return ( NULL ); + +} /* end of extraTransferPermute */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_TransferPermute.] + + Description [Performs the recursive step of Extra_TransferPermute. + Returns a pointer to the result if successful; NULL otherwise.] + + SideEffects [None] + + SeeAlso [extraTransferPermute] + +******************************************************************************/ +static DdNode * +extraTransferPermuteRecur( + DdManager * ddS, + DdManager * ddD, + DdNode * f, + st_table * table, + int * Permute ) +{ + DdNode *ft, *fe, *t, *e, *var, *res; + DdNode *one, *zero; + int index; + int comple = 0; + + statLine( ddD ); + one = DD_ONE( ddD ); + comple = Cudd_IsComplement( f ); + + /* Trivial cases. */ + if ( Cudd_IsConstant( f ) ) + return ( Cudd_NotCond( one, comple ) ); + + + /* Make canonical to increase the utilization of the cache. */ + f = Cudd_NotCond( f, comple ); + /* Now f is a regular pointer to a non-constant node. */ + + /* Check the cache. */ + if ( st_lookup( table, ( char * ) f, ( char ** ) &res ) ) + return ( Cudd_NotCond( res, comple ) ); + + /* Recursive step. */ + if ( Permute ) + index = Permute[f->index]; + else + index = f->index; + + ft = cuddT( f ); + fe = cuddE( f ); + + t = extraTransferPermuteRecur( ddS, ddD, ft, table, Permute ); + if ( t == NULL ) + { + return ( NULL ); + } + cuddRef( t ); + + e = extraTransferPermuteRecur( ddS, ddD, fe, table, Permute ); + if ( e == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + return ( NULL ); + } + cuddRef( e ); + + zero = Cudd_Not(ddD->one); + var = cuddUniqueInter( ddD, index, one, zero ); + if ( var == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + return ( NULL ); + } + res = cuddBddIteRecur( ddD, var, t, e ); + + if ( res == NULL ) + { + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + return ( NULL ); + } + cuddRef( res ); + Cudd_RecursiveDeref( ddD, t ); + Cudd_RecursiveDeref( ddD, e ); + + if ( st_add_direct( table, ( char * ) f, ( char * ) res ) == + ST_OUT_OF_MEM ) + { + Cudd_RecursiveDeref( ddD, res ); + return ( NULL ); + } + return ( Cudd_NotCond( res, comple ) ); + +} /* end of extraTransferPermuteRecur */ + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Cudd_Support.] + + Description [Performs the recursive step of Cudd_Support. Performs a + DFS from f. The support is accumulated in supp as a side effect. Uses + the LSB of the then pointer as visited flag.] + + SideEffects [None] + + SeeAlso [ddClearFlag] + +******************************************************************************/ +static void +ddSupportStep( + DdNode * f, + int * support) +{ + if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) { + return; + } + + support[f->index] = 1; + ddSupportStep(cuddT(f),support); + ddSupportStep(Cudd_Regular(cuddE(f)),support); + /* Mark as visited. */ + f->next = Cudd_Not(f->next); + return; + +} /* end of ddSupportStep */ + + +/**Function******************************************************************** + + Synopsis [Performs a DFS from f, clearing the LSB of the next + pointers.] + + Description [] + + SideEffects [None] + + SeeAlso [ddSupportStep ddDagInt] + +******************************************************************************/ +static void +ddClearFlag( + DdNode * f) +{ + if (!Cudd_IsComplement(f->next)) { + return; + } + /* Clear visited flag. */ + f->next = Cudd_Regular(f->next); + if (cuddIsConstant(f)) { + return; + } + ddClearFlag(cuddT(f)); + ddClearFlag(Cudd_Regular(cuddE(f))); + return; + +} /* end of ddClearFlag */ + + +/**Function******************************************************************** + + Synopsis [Composed three subcovers into one ZDD.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraComposeCover( + DdManager* dd, /* the manager */ + DdNode* zC0, /* the pointer to the negative var cofactor */ + DdNode* zC1, /* the pointer to the positive var cofactor */ + DdNode* zC2, /* the pointer to the cofactor without var */ + int TopVar) /* the index of the positive ZDD var */ +{ + DdNode * zRes, * zTemp; + /* compose with-neg-var and without-var using the neg ZDD var */ + zTemp = cuddZddGetNode( dd, 2*TopVar + 1, zC0, zC2 ); + if ( zTemp == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zC0); + Cudd_RecursiveDerefZdd(dd, zC1); + Cudd_RecursiveDerefZdd(dd, zC2); + return NULL; + } + cuddRef( zTemp ); + cuddDeref( zC0 ); + cuddDeref( zC2 ); + + /* compose with-pos-var and previous result using the pos ZDD var */ + zRes = cuddZddGetNode( dd, 2*TopVar, zC1, zTemp ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd(dd, zC1); + Cudd_RecursiveDerefZdd(dd, zTemp); + return NULL; + } + cuddDeref( zC1 ); + cuddDeref( zTemp ); + return zRes; +} /* extraComposeCover */ + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of prime computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode* extraZddPrimes( DdManager *dd, DdNode* F ) +{ + DdNode *zRes; + + if ( F == Cudd_Not( dd->one ) ) + return dd->zero; + if ( F == dd->one ) + return dd->one; + + /* check cache */ + zRes = cuddCacheLookup1Zdd(dd, extraZddPrimes, F); + if (zRes) + return(zRes); + { + /* temporary variables */ + DdNode *bF01, *zP0, *zP1; + /* three components of the prime set */ + DdNode *zResE, *zResP, *zResN; + int fIsComp = Cudd_IsComplement( F ); + + /* find cofactors of F */ + DdNode * bF0 = Cudd_NotCond( Cudd_E( F ), fIsComp ); + DdNode * bF1 = Cudd_NotCond( Cudd_T( F ), fIsComp ); + + /* find the intersection of cofactors */ + bF01 = cuddBddAndRecur( dd, bF0, bF1 ); + if ( bF01 == NULL ) return NULL; + cuddRef( bF01 ); + + /* solve the problems for cofactors */ + zP0 = extraZddPrimes( dd, bF0 ); + if ( zP0 == NULL ) + { + Cudd_RecursiveDeref( dd, bF01 ); + return NULL; + } + cuddRef( zP0 ); + + zP1 = extraZddPrimes( dd, bF1 ); + if ( zP1 == NULL ) + { + Cudd_RecursiveDeref( dd, bF01 ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + return NULL; + } + cuddRef( zP1 ); + + /* check for local unateness */ + if ( bF01 == bF0 ) /* unate increasing */ + { + /* intersection is useless */ + cuddDeref( bF01 ); + /* the primes of intersection are the primes of F0 */ + zResE = zP0; + /* there are no primes with negative var */ + zResN = dd->zero; + cuddRef( zResN ); + /* primes with positive var are primes of F1 that are not primes of F01 */ + zResP = cuddZddDiff( dd, zP1, zP0 ); + if ( zResP == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zResE ); + Cudd_RecursiveDerefZdd( dd, zResN ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + return NULL; + } + cuddRef( zResP ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + } + else if ( bF01 == bF1 ) /* unate decreasing */ + { + /* intersection is useless */ + cuddDeref( bF01 ); + /* the primes of intersection are the primes of F1 */ + zResE = zP1; + /* there are no primes with positive var */ + zResP = dd->zero; + cuddRef( zResP ); + /* primes with negative var are primes of F0 that are not primes of F01 */ + zResN = cuddZddDiff( dd, zP0, zP1 ); + if ( zResN == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zResE ); + Cudd_RecursiveDerefZdd( dd, zResP ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + return NULL; + } + cuddRef( zResN ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + } + else /* not unate */ + { + /* primes without the top var are primes of F10 */ + zResE = extraZddPrimes( dd, bF01 ); + if ( zResE == NULL ) + { + Cudd_RecursiveDerefZdd( dd, bF01 ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + return NULL; + } + cuddRef( zResE ); + Cudd_RecursiveDeref( dd, bF01 ); + + /* primes with the negative top var are those of P0 that are not in F10 */ + zResN = cuddZddDiff( dd, zP0, zResE ); + if ( zResN == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zResE ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + return NULL; + } + cuddRef( zResN ); + Cudd_RecursiveDerefZdd( dd, zP0 ); + + /* primes with the positive top var are those of P1 that are not in F10 */ + zResP = cuddZddDiff( dd, zP1, zResE ); + if ( zResP == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zResE ); + Cudd_RecursiveDerefZdd( dd, zResN ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + return NULL; + } + cuddRef( zResP ); + Cudd_RecursiveDerefZdd( dd, zP1 ); + } + + zRes = extraComposeCover( dd, zResN, zResP, zResE, Cudd_Regular(F)->index ); + if ( zRes == NULL ) return NULL; + + /* insert the result into cache */ + cuddCacheInsert1(dd, extraZddPrimes, F, zRes); + return zRes; + } +} /* end of extraZddPrimes */ + +/**Function******************************************************************** + + Synopsis [Implements the recursive step of Cudd_bddPermute.] + + Description [ Recursively puts the BDD in the order given in the array permut. + Checks for trivial cases to terminate recursion, then splits on the + children of this node. Once the solutions for the children are + obtained, it puts into the current position the node from the rest of + the BDD that should be here. Then returns this BDD. + The key here is that the node being visited is NOT put in its proper + place by this instance, but rather is switched when its proper position + is reached in the recursion tree.

        + The DdNode * that is returned is the same BDD as passed in as node, + but in the new order.] + + SideEffects [None] + + SeeAlso [Cudd_bddPermute cuddAddPermuteRecur] + +******************************************************************************/ +static DdNode * +cuddBddPermuteRecur( DdManager * manager /* DD manager */ , + DdHashTable * table /* computed table */ , + DdNode * node /* BDD to be reordered */ , + int *permut /* permutation array */ ) +{ + DdNode *N, *T, *E; + DdNode *res; + int index; + + statLine( manager ); + N = Cudd_Regular( node ); + + /* Check for terminal case of constant node. */ + if ( cuddIsConstant( N ) ) + { + return ( node ); + } + + /* If problem already solved, look up answer and return. */ + if ( N->ref != 1 && ( res = cuddHashTableLookup1( table, N ) ) != NULL ) + { +#ifdef DD_DEBUG + bddPermuteRecurHits++; +#endif + return ( Cudd_NotCond( res, N != node ) ); + } + + /* Split and recur on children of this node. */ + T = cuddBddPermuteRecur( manager, table, cuddT( N ), permut ); + if ( T == NULL ) + return ( NULL ); + cuddRef( T ); + E = cuddBddPermuteRecur( manager, table, cuddE( N ), permut ); + if ( E == NULL ) + { + Cudd_IterDerefBdd( manager, T ); + return ( NULL ); + } + cuddRef( E ); + + /* Move variable that should be in this position to this position + ** by retrieving the single var BDD for that variable, and calling + ** cuddBddIteRecur with the T and E we just created. + */ + index = permut[N->index]; + res = cuddBddIteRecur( manager, manager->vars[index], T, E ); + if ( res == NULL ) + { + Cudd_IterDerefBdd( manager, T ); + Cudd_IterDerefBdd( manager, E ); + return ( NULL ); + } + cuddRef( res ); + Cudd_IterDerefBdd( manager, T ); + Cudd_IterDerefBdd( manager, E ); + + /* Do not keep the result if the reference count is only 1, since + ** it will not be visited again. + */ + if ( N->ref != 1 ) + { + ptrint fanout = ( ptrint ) N->ref; + cuddSatDec( fanout ); + if ( !cuddHashTableInsert1( table, N, res, fanout ) ) + { + Cudd_IterDerefBdd( manager, res ); + return ( NULL ); + } + } + cuddDeref( res ); + return ( Cudd_NotCond( res, N != node ) ); + +} /* end of cuddBddPermuteRecur */ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/extra/extraBddSymm.c b/abc70930/src/misc/extra/extraBddSymm.c new file mode 100644 index 00000000..358402b0 --- /dev/null +++ b/abc70930/src/misc/extra/extraBddSymm.c @@ -0,0 +1,1469 @@ +/**CFile**************************************************************** + + FileName [extraBddSymm.c] + + PackageName [extra] + + Synopsis [Efficient methods to compute the information about + symmetric variables using the algorithm presented in the paper: + A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. + Transactions on CAD, Nov. 2003.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddSymm.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +#define DD_GET_SYMM_VARS_TAG 0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information for the function.] + + Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.] + + SideEffects [If the ZDD variables are not derived from BDD variables with + multiplicity 2, this function may derive them in a wrong way.] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsCompute( + DdManager * dd, /* the manager */ + DdNode * bFunc) /* the function whose symmetries are computed */ +{ + DdNode * bSupp; + DdNode * zRes; + Extra_SymmInfo_t * p; + + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + zRes = Extra_zddSymmPairsCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); + + p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp ); + + Cudd_RecursiveDeref( dd, bSupp ); + Cudd_RecursiveDerefZdd( dd, zRes ); + + return p; + +} /* end of Extra_SymmPairsCompute */ + + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information as a ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddSymmPairsCompute( + DdManager * dd, /* the DD manager */ + DdNode * bF, + DdNode * bVars) +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddSymmPairsCompute( dd, bF, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddSymmPairsCompute */ + +/**Function******************************************************************** + + Synopsis [Returns a singleton-set ZDD containing all variables that are symmetric with the given one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddGetSymmetricVars( + DdManager * dd, /* the DD manager */ + DdNode * bF, /* the first function - originally, the positive cofactor */ + DdNode * bG, /* the second fucntion - originally, the negative cofactor */ + DdNode * bVars) /* the set of variables, on which F and G depend */ +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddGetSymmetricVars( dd, bF, bG, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddGetSymmetricVars */ + + +/**Function******************************************************************** + + Synopsis [Converts a set of variables into a set of singleton subsets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddGetSingletons( + DdManager * dd, /* the DD manager */ + DdNode * bVars) /* the set of variables */ +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddGetSingletons( dd, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddGetSingletons */ + +/**Function******************************************************************** + + Synopsis [Filters the set of variables using the support of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_bddReduceVarSet( + DdManager * dd, /* the DD manager */ + DdNode * bVars, /* the set of variables to be reduced */ + DdNode * bF) /* the function whose support is used for reduction */ +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraBddReduceVarSet( dd, bVars, bF ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_bddReduceVarSet */ + + +/**Function******************************************************************** + + Synopsis [Allocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ) +{ + int i; + Extra_SymmInfo_t * p; + + // allocate and clean the storage for symmetry info + p = ALLOC( Extra_SymmInfo_t, 1 ); + memset( p, 0, sizeof(Extra_SymmInfo_t) ); + p->nVars = nVars; + p->pVars = ALLOC( int, nVars ); + p->pSymms = ALLOC( char *, nVars ); + p->pSymms[0] = ALLOC( char , nVars * nVars ); + memset( p->pSymms[0], 0, nVars * nVars * sizeof(char) ); + + for ( i = 1; i < nVars; i++ ) + p->pSymms[i] = p->pSymms[i-1] + nVars; + + return p; +} /* end of Extra_SymmPairsAllocate */ + +/**Function******************************************************************** + + Synopsis [Deallocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_SymmPairsDissolve( Extra_SymmInfo_t * p ) +{ + free( p->pVars ); + free( p->pSymms[0] ); + free( p->pSymms ); + free( p ); +} /* end of Extra_SymmPairsDissolve */ + +/**Function******************************************************************** + + Synopsis [Allocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_SymmPairsPrint( Extra_SymmInfo_t * p ) +{ + int i, k; + printf( "\n" ); + for ( i = 0; i < p->nVars; i++ ) + { + for ( k = 0; k <= i; k++ ) + printf( " " ); + for ( k = i+1; k < p->nVars; k++ ) + if ( p->pSymms[i][k] ) + printf( "1" ); + else + printf( "." ); + printf( "\n" ); + } +} /* end of Extra_SymmPairsPrint */ + + +/**Function******************************************************************** + + Synopsis [Creates the symmetry information structure from ZDD.] + + Description [ZDD representation of symmetries is the set of cubes, each + of which has two variables in the positive polarity. These variables correspond + to the symmetric variable pair.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp ) +{ + int i; + int nSuppSize; + Extra_SymmInfo_t * p; + int * pMapVars2Nums; + DdNode * bTemp; + DdNode * zSet, * zCube, * zTemp; + int iVar1, iVar2; + + nSuppSize = Extra_bddSuppSize( dd, bSupp ); + + // allocate and clean the storage for symmetry info + p = Extra_SymmPairsAllocate( nSuppSize ); + + // allocate the storage for the temporary map + pMapVars2Nums = ALLOC( int, dd->size ); + memset( pMapVars2Nums, 0, dd->size * sizeof(int) ); + + // assign the variables + p->nVarsMax = dd->size; +// p->nNodes = Cudd_DagSize( zPairs ); + p->nNodes = 0; + for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) + { + p->pVars[i] = bTemp->index; + pMapVars2Nums[bTemp->index] = i; + } + + // write the symmetry info into the structure + zSet = zPairs; Cudd_Ref( zSet ); + while ( zSet != z0 ) + { + // get the next cube + zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube ); + + // add these two variables to the data structure + assert( cuddT( cuddT(zCube) ) == z1 ); + iVar1 = zCube->index/2; + iVar2 = cuddT(zCube)->index/2; + if ( pMapVars2Nums[iVar1] < pMapVars2Nums[iVar2] ) + p->pSymms[ pMapVars2Nums[iVar1] ][ pMapVars2Nums[iVar2] ] = 1; + else + p->pSymms[ pMapVars2Nums[iVar2] ][ pMapVars2Nums[iVar1] ] = 1; + // count the symmetric pairs + p->nSymms ++; + + // update the cuver and deref the cube + zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zCube ); + + } // for each cube + Cudd_RecursiveDerefZdd( dd, zSet ); + + FREE( pMapVars2Nums ); + return p; + +} /* end of Extra_SymmPairsCreateFromZdd */ + + +/**Function******************************************************************** + + Synopsis [Checks the possibility of two variables being symmetric.] + + Description [Returns 0 if vars are not symmetric. Return 1 if vars can be symmetric.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddCheckVarsSymmetric( + DdManager * dd, /* the DD manager */ + DdNode * bF, + int iVar1, + int iVar2) +{ + DdNode * bVars; + int Res; + +// return 1; + + assert( iVar1 != iVar2 ); + assert( iVar1 < dd->size ); + assert( iVar2 < dd->size ); + + bVars = Cudd_bddAnd( dd, dd->vars[iVar1], dd->vars[iVar2] ); Cudd_Ref( bVars ); + + Res = (int)( extraBddCheckVarsSymmetric( dd, bF, bVars ) == b1 ); + + Cudd_RecursiveDeref( dd, bVars ); + + return Res; +} /* end of Extra_bddCheckVarsSymmetric */ + + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information for the function.] + + Description [Uses the naive way of comparing cofactors.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ) +{ + DdNode * bSupp, * bTemp; + int nSuppSize; + Extra_SymmInfo_t * p; + int i, k; + + // compute the support + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + nSuppSize = Extra_bddSuppSize( dd, bSupp ); +//printf( "Support = %d. ", nSuppSize ); +//Extra_bddPrint( dd, bSupp ); +//printf( "%d ", nSuppSize ); + + // allocate the storage for symmetry info + p = Extra_SymmPairsAllocate( nSuppSize ); + + // assign the variables + p->nVarsMax = dd->size; + for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) + p->pVars[i] = bTemp->index; + + // go through the candidate pairs and check using Idea1 + for ( i = 0; i < nSuppSize; i++ ) + for ( k = i+1; k < nSuppSize; k++ ) + { + p->pSymms[k][i] = p->pSymms[i][k] = Extra_bddCheckVarsSymmetricNaive( dd, bFunc, p->pVars[i], p->pVars[k] ); + if ( p->pSymms[i][k] ) + p->nSymms++; + } + + Cudd_RecursiveDeref( dd, bSupp ); + return p; + +} /* end of Extra_SymmPairsComputeNaive */ + +/**Function******************************************************************** + + Synopsis [Checks if the two variables are symmetric.] + + Description [Returns 0 if vars are not symmetric. Return 1 if vars are symmetric.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddCheckVarsSymmetricNaive( + DdManager * dd, /* the DD manager */ + DdNode * bF, + int iVar1, + int iVar2) +{ + DdNode * bCube1, * bCube2; + DdNode * bCof01, * bCof10; + int Res; + + assert( iVar1 != iVar2 ); + assert( iVar1 < dd->size ); + assert( iVar2 < dd->size ); + + bCube1 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar1] ), dd->vars[iVar2] ); Cudd_Ref( bCube1 ); + bCube2 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar2] ), dd->vars[iVar1] ); Cudd_Ref( bCube2 ); + + bCof01 = Cudd_Cofactor( dd, bF, bCube1 ); Cudd_Ref( bCof01 ); + bCof10 = Cudd_Cofactor( dd, bF, bCube2 ); Cudd_Ref( bCof10 ); + + Res = (int)( bCof10 == bCof01 ); + + Cudd_RecursiveDeref( dd, bCof01 ); + Cudd_RecursiveDeref( dd, bCof10 ); + Cudd_RecursiveDeref( dd, bCube1 ); + Cudd_RecursiveDeref( dd, bCube2 ); + + return Res; +} /* end of Extra_bddCheckVarsSymmetricNaive */ + + +/**Function******************************************************************** + + Synopsis [Builds ZDD representing the set of fixed-size variable tuples.] + + Description [Creates ZDD of all combinations of variables in Support that + is represented by a BDD.] + + SideEffects [New ZDD variables are created if indices of the variables + present in the combination are larger than the currently + allocated number of ZDD variables.] + + SeeAlso [] + +******************************************************************************/ +DdNode* Extra_zddTuplesFromBdd( + DdManager * dd, /* the DD manager */ + int K, /* the number of variables in tuples */ + DdNode * bVarsN) /* the set of all variables represented as a BDD */ +{ + DdNode *zRes; + int autoDynZ; + + autoDynZ = dd->autoDynZ; + dd->autoDynZ = 0; + + do { + /* transform the numeric arguments (K) into a DdNode* argument; + * this allows us to use the standard internal CUDD cache */ + DdNode *bVarSet = bVarsN, *bVarsK = bVarsN; + int nVars = 0, i; + + /* determine the number of variables in VarSet */ + while ( bVarSet != b1 ) + { + nVars++; + /* make sure that the VarSet is a cube */ + if ( cuddE( bVarSet ) != b0 ) + return NULL; + bVarSet = cuddT( bVarSet ); + } + /* make sure that the number of variables in VarSet is less or equal + that the number of variables that should be present in the tuples + */ + if ( K > nVars ) + return NULL; + + /* the second argument in the recursive call stannds for ; + /* reate the first argument, which stands for + * as when we are talking about the tuple of out of */ + for ( i = 0; i < nVars-K; i++ ) + bVarsK = cuddT( bVarsK ); + + dd->reordered = 0; + zRes = extraZddTuplesFromBdd(dd, bVarsK, bVarsN ); + + } while (dd->reordered == 1); + dd->autoDynZ = autoDynZ; + return zRes; + +} /* end of Extra_zddTuplesFromBdd */ + +/**Function******************************************************************** + + Synopsis [Selects one subset from the set of subsets represented by a ZDD.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode* Extra_zddSelectOneSubset( + DdManager * dd, /* the DD manager */ + DdNode * zS) /* the ZDD */ +{ + DdNode *res; + do { + dd->reordered = 0; + res = extraZddSelectOneSubset(dd, zS); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddSelectOneSubset */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_SymmPairsCompute.] + + Description [Returns the set of symmetric variable pairs represented as a set + of two-literal ZDD cubes. Both variables always appear in the positive polarity + in the cubes. This function works without building new BDD nodes. Some relatively + small number of ZDD nodes may be built to ensure proper bookkeeping of the + symmetry information.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddSymmPairsCompute( + DdManager * dd, /* the manager */ + DdNode * bFunc, /* the function whose symmetries are computed */ + DdNode * bVars ) /* the set of variables on which this function depends */ +{ + DdNode * zRes; + DdNode * bFR = Cudd_Regular(bFunc); + + if ( cuddIsConstant(bFR) ) + { + int nVars, i; + + // determine how many vars are in the bVars + nVars = Extra_bddSuppSize( dd, bVars ); + if ( nVars < 2 ) + return z0; + else + { + DdNode * bVarsK; + + // create the BDD bVarsK corresponding to K = 2; + bVarsK = bVars; + for ( i = 0; i < nVars-2; i++ ) + bVarsK = cuddT( bVarsK ); + return extraZddTuplesFromBdd( dd, bVarsK, bVars ); + } + } + assert( bVars != b1 ); + + if ( zRes = cuddCacheLookup2Zdd(dd, extraZddSymmPairsCompute, bFunc, bVars) ) + return zRes; + else + { + DdNode * zRes0, * zRes1; + DdNode * zTemp, * zPlus, * zSymmVars; + DdNode * bF0, * bF1; + DdNode * bVarsNew; + int nVarsExtra; + int LevelF; + + // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV + // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F + // count how many extra vars are there in bVars + nVarsExtra = 0; + LevelF = dd->perm[bFR->index]; + for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) + nVarsExtra++; + // the indexes (level) of variables should be synchronized now + assert( bFR->index == bVarsNew->index ); + + // cofactor the function + if ( bFR != bFunc ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + // solve subproblems + zRes0 = extraZddSymmPairsCompute( dd, bF0, cuddT(bVarsNew) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + // if there is no symmetries in the negative cofactor + // there is no need to test the positive cofactor + if ( zRes0 == z0 ) + zRes = zRes0; // zRes takes reference + else + { + zRes1 = extraZddSymmPairsCompute( dd, bF1, cuddT(bVarsNew) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + // only those variables are pair-wise symmetric + // that are pair-wise symmetric in both cofactors + // therefore, intersect the solutions + zRes = cuddZddIntersect( dd, zRes0, zRes1 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + } + + // consider the current top-most variable and find all the vars + // that are pairwise symmetric with it + // these variables are returned as a set of ZDD singletons + zSymmVars = extraZddGetSymmetricVars( dd, bF1, bF0, cuddT(bVarsNew) ); + if ( zSymmVars == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zSymmVars ); + + // attach the topmost variable to the set, to get the variable pairs + // use the positive polarity ZDD variable for the purpose + + // there is no need to do so, if zSymmVars is empty + if ( zSymmVars == z0 ) + Cudd_RecursiveDerefZdd( dd, zSymmVars ); + else + { + zPlus = cuddZddGetNode( dd, 2*bFR->index, zSymmVars, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + Cudd_RecursiveDerefZdd( dd, zSymmVars ); + return NULL; + } + cuddRef( zPlus ); + cuddDeref( zSymmVars ); + + // add these variable pairs to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + + // only zRes is referenced at this point + + // if we skipped some variables, these variables cannot be symmetric with + // any variables that are currently in the support of bF, but they can be + // symmetric with the variables that are in bVars but not in the support of bF + if ( nVarsExtra ) + { + // it is possible to improve this step: + // (1) there is no need to enter here, if nVarsExtra < 2 + + // create the set of topmost nVarsExtra in bVars + DdNode * bVarsExtra; + int nVars; + + // remove from bVars all the variable that are in the support of bFunc + bVarsExtra = extraBddReduceVarSet( dd, bVars, bFunc ); + if ( bVarsExtra == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( bVarsExtra ); + + // determine how many vars are in the bVarsExtra + nVars = Extra_bddSuppSize( dd, bVarsExtra ); + if ( nVars < 2 ) + { + Cudd_RecursiveDeref( dd, bVarsExtra ); + } + else + { + int i; + DdNode * bVarsK; + + // create the BDD bVarsK corresponding to K = 2; + bVarsK = bVarsExtra; + for ( i = 0; i < nVars-2; i++ ) + bVarsK = cuddT( bVarsK ); + + // create the 2 variable tuples + zPlus = extraZddTuplesFromBdd( dd, bVarsK, bVarsExtra ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDeref( dd, bVarsExtra ); + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + } + cuddDeref( zRes ); + + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddSymmPairsCompute, bFunc, bVars, zRes); + return zRes; + } +} /* end of extraZddSymmPairsCompute */ + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_zddGetSymmetricVars.] + + Description [Returns the set of ZDD singletons, containing those positive + ZDD variables that correspond to BDD variables x, for which it is true + that bF(x=0) == bG(x=1).] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraZddGetSymmetricVars( + DdManager * dd, /* the DD manager */ + DdNode * bF, /* the first function - originally, the positive cofactor */ + DdNode * bG, /* the second function - originally, the negative cofactor */ + DdNode * bVars) /* the set of variables, on which F and G depend */ +{ + DdNode * zRes; + DdNode * bFR = Cudd_Regular(bF); + DdNode * bGR = Cudd_Regular(bG); + + if ( cuddIsConstant(bFR) && cuddIsConstant(bGR) ) + { + if ( bF == bG ) + return extraZddGetSingletons( dd, bVars ); + else + return z0; + } + assert( bVars != b1 ); + + if ( zRes = cuddCacheLookupZdd(dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars) ) + return zRes; + else + { + DdNode * zRes0, * zRes1; + DdNode * zPlus, * zTemp; + DdNode * bF0, * bF1; + DdNode * bG0, * bG1; + DdNode * bVarsNew; + + int LevelF = cuddI(dd,bFR->index); + int LevelG = cuddI(dd,bGR->index); + int LevelFG; + + if ( LevelF < LevelG ) + LevelFG = LevelF; + else + LevelFG = LevelG; + + // at least one of the arguments is not a constant + assert( LevelFG < dd->size ); + + // every variable in bF and bG should be also in bVars, therefore LevelFG cannot be above LevelV + // if LevelFG is below LevelV, scroll through the vars in bVars to the same level as LevelFG + for ( bVarsNew = bVars; LevelFG > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ); + assert( LevelFG == dd->perm[bVarsNew->index] ); + + // cofactor the functions + if ( LevelF == LevelFG ) + { + if ( bFR != bF ) // bF is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + } + else + bF0 = bF1 = bF; + + if ( LevelG == LevelFG ) + { + if ( bGR != bG ) // bG is complemented + { + bG0 = Cudd_Not( cuddE(bGR) ); + bG1 = Cudd_Not( cuddT(bGR) ); + } + else + { + bG0 = cuddE(bGR); + bG1 = cuddT(bGR); + } + } + else + bG0 = bG1 = bG; + + // solve subproblems + zRes0 = extraZddGetSymmetricVars( dd, bF0, bG0, cuddT(bVarsNew) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + // if there is not symmetries in the negative cofactor + // there is no need to test the positive cofactor + if ( zRes0 == z0 ) + zRes = zRes0; // zRes takes reference + else + { + zRes1 = extraZddGetSymmetricVars( dd, bF1, bG1, cuddT(bVarsNew) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + // only those variables should belong to the resulting set + // for which the property is true for both cofactors + zRes = cuddZddIntersect( dd, zRes0, zRes1 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + } + + // add one more singleton if the property is true for this variable + if ( bF0 == bG1 ) + { + zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these variable pairs to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + + if ( bF == bG && bVars != bVarsNew ) + { + // if the functions are equal, so are their cofactors + // add those variables from V that are above F and G + + DdNode * bVarsExtra; + + assert( LevelFG > dd->perm[bVars->index] ); + + // create the BDD of the extra variables + bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsNew ); + if ( bVarsExtra == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( bVarsExtra ); + + zPlus = extraZddGetSingletons( dd, bVarsExtra ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDeref( dd, bVarsExtra ); + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + cuddDeref( zRes ); + + cuddCacheInsert( dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars, zRes ); + return zRes; + } +} /* end of extraZddGetSymmetricVars */ + + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_zddGetSingletons.] + + Description [Returns the set of ZDD singletons, containing those positive + polarity ZDD variables that correspond to the BDD variables in bVars.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraZddGetSingletons( + DdManager * dd, /* the DD manager */ + DdNode * bVars) /* the set of variables */ +{ + DdNode * zRes; + + if ( bVars == b1 ) +// if ( bVars == b0 ) // bug fixed by Jin Zhang, Jan 23, 2004 + return z1; + + if ( zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars) ) + return zRes; + else + { + DdNode * zTemp, * zPlus; + + // solve subproblem + zRes = extraZddGetSingletons( dd, cuddT(bVars) ); + if ( zRes == NULL ) + return NULL; + cuddRef( zRes ); + + zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + cuddDeref( zRes ); + + cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes ); + return zRes; + } +} /* end of extraZddGetSingletons */ + + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_bddReduceVarSet.] + + Description [Returns the set of all variables in the given set that are not in the + support of the given function.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraBddReduceVarSet( + DdManager * dd, /* the DD manager */ + DdNode * bVars, /* the set of variables to be reduced */ + DdNode * bF) /* the function whose support is used for reduction */ +{ + DdNode * bRes; + DdNode * bFR = Cudd_Regular(bF); + + if ( cuddIsConstant(bFR) || bVars == b1 ) + return bVars; + + if ( bRes = cuddCacheLookup2(dd, extraBddReduceVarSet, bVars, bF) ) + return bRes; + else + { + DdNode * bF0, * bF1; + DdNode * bVarsThis, * bVarsLower, * bTemp; + int LevelF; + + // if LevelF is below LevelV, scroll through the vars in bVars + LevelF = dd->perm[bFR->index]; + for ( bVarsThis = bVars; LevelF > cuddI(dd,bVarsThis->index); bVarsThis = cuddT(bVarsThis) ); + // scroll also through the current var, because it should be not be added + if ( LevelF == cuddI(dd,bVarsThis->index) ) + bVarsLower = cuddT(bVarsThis); + else + bVarsLower = bVarsThis; + + // cofactor the function + if ( bFR != bF ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + // solve subproblems + bRes = extraBddReduceVarSet( dd, bVarsLower, bF0 ); + if ( bRes == NULL ) + return NULL; + cuddRef( bRes ); + + bRes = extraBddReduceVarSet( dd, bTemp = bRes, bF1 ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + return NULL; + } + cuddRef( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + + // the current var should not be added + // add the skipped vars + if ( bVarsThis != bVars ) + { + DdNode * bVarsExtra; + + // extract the skipped variables + bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsThis ); + if ( bVarsExtra == NULL ) + { + Cudd_RecursiveDeref( dd, bRes ); + return NULL; + } + cuddRef( bVarsExtra ); + + // add these variables + bRes = cuddBddAndRecur( dd, bTemp = bRes, bVarsExtra ); + if ( bRes == NULL ) + { + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + return NULL; + } + cuddRef( bRes ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bVarsExtra ); + } + cuddDeref( bRes ); + + cuddCacheInsert2( dd, extraBddReduceVarSet, bVars, bF, bRes ); + return bRes; + } +} /* end of extraBddReduceVarSet */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_bddCheckVarsSymmetric().] + + Description [Returns b0 if the variables are not symmetric. Returns b1 if the + variables can be symmetric. The variables are represented in the form of a + two-variable cube. In case the cube contains one variable (below Var1 level), + the cube's pointer is complemented if the variable Var1 occurred on the + current path; otherwise, the cube's pointer is regular. Uses additional + complemented bit (Hash_Not) to mark the result if in the BDD rooted that this + node there is a branch passing though the node labeled with Var2.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraBddCheckVarsSymmetric( + DdManager * dd, /* the DD manager */ + DdNode * bF, + DdNode * bVars) +{ + DdNode * bRes; + + if ( bF == b0 ) + return b1; + + assert( bVars != b1 ); + + if ( bRes = cuddCacheLookup2(dd, extraBddCheckVarsSymmetric, bF, bVars) ) + return bRes; + else + { + DdNode * bRes0, * bRes1; + DdNode * bF0, * bF1; + DdNode * bFR = Cudd_Regular(bF); + int LevelF = cuddI(dd,bFR->index); + + DdNode * bVarsR = Cudd_Regular(bVars); + int fVar1Pres; + int iLev1; + int iLev2; + + if ( bVarsR != bVars ) // cube's pointer is complemented + { + assert( cuddT(bVarsR) == b1 ); + fVar1Pres = 1; // the first var is present on the path + iLev1 = -1; // we are already below the first var level + iLev2 = dd->perm[bVarsR->index]; // the level of the second var + } + else // cube's pointer is NOT complemented + { + fVar1Pres = 0; // the first var is absent on the path + if ( cuddT(bVars) == b1 ) + { + iLev1 = -1; // we are already below the first var level + iLev2 = dd->perm[bVars->index]; // the level of the second var + } + else + { + assert( cuddT(cuddT(bVars)) == b1 ); + iLev1 = dd->perm[bVars->index]; // the level of the first var + iLev2 = dd->perm[cuddT(bVars)->index]; // the level of the second var + } + } + + // cofactor the function + // the cofactors are needed only if we are above the second level + if ( LevelF < iLev2 ) + { + if ( bFR != bF ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + } + else + bF0 = bF1 = NULL; + + // consider five cases: + // (1) F is above iLev1 + // (2) F is on the level iLev1 + // (3) F is between iLev1 and iLev2 + // (4) F is on the level iLev2 + // (5) F is below iLev2 + + // (1) F is above iLev1 + if ( LevelF < iLev1 ) + { + // the returned result cannot have the hash attribute + // because we still did not reach the level of Var1; + // the attribute never travels above the level of Var1 + bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); +// assert( !Hash_IsComplement( bRes0 ) ); + assert( bRes0 != z0 ); + if ( bRes0 == b0 ) + bRes = b0; + else + bRes = extraBddCheckVarsSymmetric( dd, bF1, bVars ); +// assert( !Hash_IsComplement( bRes ) ); + assert( bRes != z0 ); + } + // (2) F is on the level iLev1 + else if ( LevelF == iLev1 ) + { + bRes0 = extraBddCheckVarsSymmetric( dd, bF0, Cudd_Not( cuddT(bVars) ) ); + if ( bRes0 == b0 ) + bRes = b0; + else + { + bRes1 = extraBddCheckVarsSymmetric( dd, bF1, Cudd_Not( cuddT(bVars) ) ); + if ( bRes1 == b0 ) + bRes = b0; + else + { +// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) + if ( bRes0 == z0 || bRes1 == z0 ) + bRes = b1; + else + bRes = b0; + } + } + } + // (3) F is between iLev1 and iLev2 + else if ( LevelF < iLev2 ) + { + bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); + if ( bRes0 == b0 ) + bRes = b0; + else + { + bRes1 = extraBddCheckVarsSymmetric( dd, bF1, bVars ); + if ( bRes1 == b0 ) + bRes = b0; + else + { +// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) +// bRes = Hash_Not( b1 ); + if ( bRes0 == z0 || bRes1 == z0 ) + bRes = z0; + else + bRes = b1; + } + } + } + // (4) F is on the level iLev2 + else if ( LevelF == iLev2 ) + { + // this is the only place where the hash attribute (Hash_Not) can be added + // to the result; it can be added only if the path came through the node + // lebeled with Var1; therefore, the hash attribute cannot be returned + // to the caller function + if ( fVar1Pres ) +// bRes = Hash_Not( b1 ); + bRes = z0; + else + bRes = b0; + } + // (5) F is below iLev2 + else // if ( LevelF > iLev2 ) + { + // it is possible that the path goes through the node labeled by Var1 + // and still everything is okay; we do not label with Hash_Not here + // because the path does not go through node labeled by Var2 + bRes = b1; + } + + cuddCacheInsert2(dd, extraBddCheckVarsSymmetric, bF, bVars, bRes); + return bRes; + } +} /* end of extraBddCheckVarsSymmetric */ + +/**Function******************************************************************** + + Synopsis [Performs the reordering-sensitive step of Extra_zddTupleFromBdd().] + + Description [Generates in a bottom-up fashion ZDD for all combinations + composed of k variables out of variables belonging to Support.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode* extraZddTuplesFromBdd( + DdManager * dd, /* the DD manager */ + DdNode * bVarsK, /* the number of variables in tuples */ + DdNode * bVarsN) /* the set of all variables */ +{ + DdNode *zRes, *zRes0, *zRes1; + statLine(dd); + + /* terminal cases */ +/* if ( k < 0 || k > n ) + * return dd->zero; + * if ( n == 0 ) + * return dd->one; + */ + if ( cuddI( dd, bVarsK->index ) < cuddI( dd, bVarsN->index ) ) + return z0; + if ( bVarsN == b1 ) + return z1; + + /* check cache */ + zRes = cuddCacheLookup2Zdd(dd, extraZddTuplesFromBdd, bVarsK, bVarsN); + if (zRes) + return(zRes); + + /* ZDD in which this variable is 0 */ +/* zRes0 = extraZddTuplesFromBdd( dd, k, n-1 ); */ + zRes0 = extraZddTuplesFromBdd( dd, bVarsK, cuddT(bVarsN) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + /* ZDD in which this variable is 1 */ +/* zRes1 = extraZddTuplesFromBdd( dd, k-1, n-1 ); */ + if ( bVarsK == b1 ) + { + zRes1 = z0; + cuddRef( zRes1 ); + } + else + { + zRes1 = extraZddTuplesFromBdd( dd, cuddT(bVarsK), cuddT(bVarsN) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + } + + /* compose Res0 and Res1 with the given ZDD variable */ + zRes = cuddZddGetNode( dd, 2*bVarsN->index, zRes1, zRes0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddDeref( zRes0 ); + cuddDeref( zRes1 ); + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddTuplesFromBdd, bVarsK, bVarsN, zRes); + return zRes; + +} /* end of extraZddTuplesFromBdd */ + + +/**Function******************************************************************** + + Synopsis [Performs the recursive step of Extra_zddSelectOneSubset.] + + Description [] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraZddSelectOneSubset( + DdManager * dd, + DdNode * zS ) +// selects one subset from the ZDD zS +// returns z0 if and only if zS is an empty set of cubes +{ + DdNode * zRes; + + if ( zS == z0 ) return z0; + if ( zS == z1 ) return z1; + + // check cache + if ( zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS ) ) + return zRes; + else + { + DdNode * zS0, * zS1, * zTemp; + + zS0 = cuddE(zS); + zS1 = cuddT(zS); + + if ( zS0 != z0 ) + { + zRes = extraZddSelectOneSubset( dd, zS0 ); + if ( zRes == NULL ) + return NULL; + } + else // if ( zS0 == z0 ) + { + assert( zS1 != z0 ); + zRes = extraZddSelectOneSubset( dd, zS1 ); + if ( zRes == NULL ) + return NULL; + cuddRef( zRes ); + + zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + return NULL; + } + cuddDeref( zTemp ); + } + + // insert the result into cache + cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes ); + return zRes; + } +} /* end of extraZddSelectOneSubset */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ diff --git a/abc70930/src/misc/extra/extraBddUnate.c b/abc70930/src/misc/extra/extraBddUnate.c new file mode 100644 index 00000000..b0297c77 --- /dev/null +++ b/abc70930/src/misc/extra/extraBddUnate.c @@ -0,0 +1,641 @@ +/**CFile**************************************************************** + + FileName [extraBddUnate.c] + + PackageName [extra] + + Synopsis [Efficient methods to compute the information about + unate variables using an algorithm that is conceptually similar to + the algorithm for two-variable symmetry computation presented in: + A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. + Transactions on CAD, Nov. 2003.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - September 1, 2003.] + + Revision [$Id: extraBddUnate.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information for the function.] + + Description [Returns the symmetry information in the form of Extra_UnateInfo_t structure.] + + SideEffects [If the ZDD variables are not derived from BDD variables with + multiplicity 2, this function may derive them in a wrong way.] + + SeeAlso [] + +******************************************************************************/ +Extra_UnateInfo_t * Extra_UnateComputeFast( + DdManager * dd, /* the manager */ + DdNode * bFunc) /* the function whose symmetries are computed */ +{ + DdNode * bSupp; + DdNode * zRes; + Extra_UnateInfo_t * p; + + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + zRes = Extra_zddUnateInfoCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); + + p = Extra_UnateInfoCreateFromZdd( dd, zRes, bSupp ); + + Cudd_RecursiveDeref( dd, bSupp ); + Cudd_RecursiveDerefZdd( dd, zRes ); + + return p; + +} /* end of Extra_UnateInfoCompute */ + + +/**Function******************************************************************** + + Synopsis [Computes the classical symmetry information as a ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddUnateInfoCompute( + DdManager * dd, /* the DD manager */ + DdNode * bF, + DdNode * bVars) +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddUnateInfoCompute( dd, bF, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddUnateInfoCompute */ + + +/**Function******************************************************************** + + Synopsis [Converts a set of variables into a set of singleton subsets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * Extra_zddGetSingletonsBoth( + DdManager * dd, /* the DD manager */ + DdNode * bVars) /* the set of variables */ +{ + DdNode * res; + do { + dd->reordered = 0; + res = extraZddGetSingletonsBoth( dd, bVars ); + } while (dd->reordered == 1); + return(res); + +} /* end of Extra_zddGetSingletonsBoth */ + +/**Function******************************************************************** + + Synopsis [Allocates unateness information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars ) +{ + Extra_UnateInfo_t * p; + // allocate and clean the storage for unateness info + p = ALLOC( Extra_UnateInfo_t, 1 ); + memset( p, 0, sizeof(Extra_UnateInfo_t) ); + p->nVars = nVars; + p->pVars = ALLOC( Extra_UnateVar_t, nVars ); + memset( p->pVars, 0, nVars * sizeof(Extra_UnateVar_t) ); + return p; +} /* end of Extra_UnateInfoAllocate */ + +/**Function******************************************************************** + + Synopsis [Deallocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_UnateInfoDissolve( Extra_UnateInfo_t * p ) +{ + free( p->pVars ); + free( p ); +} /* end of Extra_UnateInfoDissolve */ + +/**Function******************************************************************** + + Synopsis [Allocates symmetry information structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Extra_UnateInfoPrint( Extra_UnateInfo_t * p ) +{ + char * pBuffer; + int i; + pBuffer = ALLOC( char, p->nVarsMax+1 ); + memset( pBuffer, ' ', p->nVarsMax ); + pBuffer[p->nVarsMax] = 0; + for ( i = 0; i < p->nVars; i++ ) + if ( p->pVars[i].Neg ) + pBuffer[ p->pVars[i].iVar ] = 'n'; + else if ( p->pVars[i].Pos ) + pBuffer[ p->pVars[i].iVar ] = 'p'; + else + pBuffer[ p->pVars[i].iVar ] = '.'; + printf( "%s\n", pBuffer ); + free( pBuffer ); +} /* end of Extra_UnateInfoPrint */ + + +/**Function******************************************************************** + + Synopsis [Creates the symmetry information structure from ZDD.] + + Description [ZDD representation of symmetries is the set of cubes, each + of which has two variables in the positive polarity. These variables correspond + to the symmetric variable pair.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp ) +{ + Extra_UnateInfo_t * p; + DdNode * bTemp, * zSet, * zCube, * zTemp; + int * pMapVars2Nums; + int i, nSuppSize; + + nSuppSize = Extra_bddSuppSize( dd, bSupp ); + + // allocate and clean the storage for symmetry info + p = Extra_UnateInfoAllocate( nSuppSize ); + + // allocate the storage for the temporary map + pMapVars2Nums = ALLOC( int, dd->size ); + memset( pMapVars2Nums, 0, dd->size * sizeof(int) ); + + // assign the variables + p->nVarsMax = dd->size; + for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) + { + p->pVars[i].iVar = bTemp->index; + pMapVars2Nums[bTemp->index] = i; + } + + // write the symmetry info into the structure + zSet = zPairs; Cudd_Ref( zSet ); +// Cudd_zddPrintCover( dd, zPairs ); printf( "\n" ); + while ( zSet != z0 ) + { + // get the next cube + zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube ); + + // add this var to the data structure + assert( cuddT(zCube) == z1 && cuddE(zCube) == z0 ); + if ( zCube->index & 1 ) // neg + p->pVars[ pMapVars2Nums[zCube->index/2] ].Neg = 1; + else + p->pVars[ pMapVars2Nums[zCube->index/2] ].Pos = 1; + // count the unate vars + p->nUnate++; + + // update the cuver and deref the cube + zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zCube ); + + } // for each cube + Cudd_RecursiveDerefZdd( dd, zSet ); + FREE( pMapVars2Nums ); + return p; + +} /* end of Extra_UnateInfoCreateFromZdd */ + + + +/**Function******************************************************************** + + Synopsis [Computes the classical unateness information for the function.] + + Description [Uses the naive way of comparing cofactors.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc ) +{ + int nSuppSize; + DdNode * bSupp, * bTemp; + Extra_UnateInfo_t * p; + int i, Res; + + // compute the support + bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); + nSuppSize = Extra_bddSuppSize( dd, bSupp ); +//printf( "Support = %d. ", nSuppSize ); +//Extra_bddPrint( dd, bSupp ); +//printf( "%d ", nSuppSize ); + + // allocate the storage for symmetry info + p = Extra_UnateInfoAllocate( nSuppSize ); + + // assign the variables + p->nVarsMax = dd->size; + for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) + { + Res = Extra_bddCheckUnateNaive( dd, bFunc, bTemp->index ); + p->pVars[i].iVar = bTemp->index; + if ( Res == -1 ) + p->pVars[i].Neg = 1; + else if ( Res == 1 ) + p->pVars[i].Pos = 1; + p->nUnate += (Res != 0); + } + Cudd_RecursiveDeref( dd, bSupp ); + return p; + +} /* end of Extra_UnateComputeSlow */ + +/**Function******************************************************************** + + Synopsis [Checks if the two variables are symmetric.] + + Description [Returns 0 if vars are not unate. Return -1/+1 if the var is neg/pos unate.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_bddCheckUnateNaive( + DdManager * dd, /* the DD manager */ + DdNode * bF, + int iVar) +{ + DdNode * bCof0, * bCof1; + int Res; + + assert( iVar < dd->size ); + + bCof0 = Cudd_Cofactor( dd, bF, Cudd_Not(Cudd_bddIthVar(dd,iVar)) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_Cofactor( dd, bF, Cudd_bddIthVar(dd,iVar) ); Cudd_Ref( bCof1 ); + + if ( Cudd_bddLeq( dd, bCof0, bCof1 ) ) + Res = 1; + else if ( Cudd_bddLeq( dd, bCof1, bCof0 ) ) + Res =-1; + else + Res = 0; + + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); + return Res; +} /* end of Extra_bddCheckUnateNaive */ + + + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_UnateInfoCompute.] + + Description [Returns the set of symmetric variable pairs represented as a set + of two-literal ZDD cubes. Both variables always appear in the positive polarity + in the cubes. This function works without building new BDD nodes. Some relatively + small number of ZDD nodes may be built to ensure proper bookkeeping of the + symmetry information.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * +extraZddUnateInfoCompute( + DdManager * dd, /* the manager */ + DdNode * bFunc, /* the function whose symmetries are computed */ + DdNode * bVars ) /* the set of variables on which this function depends */ +{ + DdNode * zRes; + DdNode * bFR = Cudd_Regular(bFunc); + + if ( cuddIsConstant(bFR) ) + { + if ( cuddIsConstant(bVars) ) + return z0; + return extraZddGetSingletonsBoth( dd, bVars ); + } + assert( bVars != b1 ); + + if ( zRes = cuddCacheLookup2Zdd(dd, extraZddUnateInfoCompute, bFunc, bVars) ) + return zRes; + else + { + DdNode * zRes0, * zRes1; + DdNode * zTemp, * zPlus; + DdNode * bF0, * bF1; + DdNode * bVarsNew; + int nVarsExtra; + int LevelF; + int AddVar; + + // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV + // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F + // count how many extra vars are there in bVars + nVarsExtra = 0; + LevelF = dd->perm[bFR->index]; + for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) + nVarsExtra++; + // the indexes (level) of variables should be synchronized now + assert( bFR->index == bVarsNew->index ); + + // cofactor the function + if ( bFR != bFunc ) // bFunc is complemented + { + bF0 = Cudd_Not( cuddE(bFR) ); + bF1 = Cudd_Not( cuddT(bFR) ); + } + else + { + bF0 = cuddE(bFR); + bF1 = cuddT(bFR); + } + + // solve subproblems + zRes0 = extraZddUnateInfoCompute( dd, bF0, cuddT(bVarsNew) ); + if ( zRes0 == NULL ) + return NULL; + cuddRef( zRes0 ); + + // if there is no symmetries in the negative cofactor + // there is no need to test the positive cofactor + if ( zRes0 == z0 ) + zRes = zRes0; // zRes takes reference + else + { + zRes1 = extraZddUnateInfoCompute( dd, bF1, cuddT(bVarsNew) ); + if ( zRes1 == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + return NULL; + } + cuddRef( zRes1 ); + + // only those variables are pair-wise symmetric + // that are pair-wise symmetric in both cofactors + // therefore, intersect the solutions + zRes = cuddZddIntersect( dd, zRes0, zRes1 ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zRes0 ); + Cudd_RecursiveDerefZdd( dd, zRes1 ); + } + + // consider the current top-most variable + AddVar = -1; + if ( Cudd_bddLeq( dd, bF0, bF1 ) ) // pos + AddVar = 0; + else if ( Cudd_bddLeq( dd, bF1, bF0 ) ) // neg + AddVar = 1; + if ( AddVar >= 0 ) + { + // create the singleton + zPlus = cuddZddGetNode( dd, 2*bFR->index + AddVar, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + // only zRes is referenced at this point + + // if we skipped some variables, these variables cannot be symmetric with + // any variables that are currently in the support of bF, but they can be + // symmetric with the variables that are in bVars but not in the support of bF + for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) + { + // create the negative singleton + zPlus = cuddZddGetNode( dd, 2*bVarsNew->index+1, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + + + // create the positive singleton + zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + } + cuddDeref( zRes ); + + /* insert the result into cache */ + cuddCacheInsert2(dd, extraZddUnateInfoCompute, bFunc, bVars, zRes); + return zRes; + } +} /* end of extraZddUnateInfoCompute */ + + +/**Function******************************************************************** + + Synopsis [Performs a recursive step of Extra_zddGetSingletons.] + + Description [Returns the set of ZDD singletons, containing those pos/neg + polarity ZDD variables that correspond to the BDD variables in bVars.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +DdNode * extraZddGetSingletonsBoth( + DdManager * dd, /* the DD manager */ + DdNode * bVars) /* the set of variables */ +{ + DdNode * zRes; + + if ( bVars == b1 ) + return z1; + + if ( zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletonsBoth, bVars) ) + return zRes; + else + { + DdNode * zTemp, * zPlus; + + // solve subproblem + zRes = extraZddGetSingletonsBoth( dd, cuddT(bVars) ); + if ( zRes == NULL ) + return NULL; + cuddRef( zRes ); + + + // create the negative singleton + zPlus = cuddZddGetNode( dd, 2*bVars->index+1, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + + + // create the positive singleton + zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); + if ( zPlus == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zRes ); + return NULL; + } + cuddRef( zPlus ); + + // add these to the result + zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); + if ( zRes == NULL ) + { + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + return NULL; + } + cuddRef( zRes ); + Cudd_RecursiveDerefZdd( dd, zTemp ); + Cudd_RecursiveDerefZdd( dd, zPlus ); + + cuddDeref( zRes ); + cuddCacheInsert1( dd, extraZddGetSingletonsBoth, bVars, zRes ); + return zRes; + } +} /* end of extraZddGetSingletonsBoth */ + + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ diff --git a/abc70930/src/misc/extra/extraUtilBitMatrix.c b/abc70930/src/misc/extra/extraUtilBitMatrix.c new file mode 100644 index 00000000..b860a538 --- /dev/null +++ b/abc70930/src/misc/extra/extraUtilBitMatrix.c @@ -0,0 +1,415 @@ +/**CFile**************************************************************** + + FileName [extraUtilBitMatrix.c] + + PackageName [extra] + + Synopsis [Various reusable software utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 1, 2003.] + + Revision [$Id: extraUtilBitMatrix.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +struct Extra_BitMat_t_ +{ + unsigned ** ppData; // bit data + int nSize; // the number of bits in one dimension + int nWords; // the number of words in one dimension + int nBitShift; // the number of bits to shift to get words + unsigned uMask; // the mask to get the number of bits in the word + int nLookups; // the number of lookups + int nInserts; // the number of inserts + int nDeletes; // the number of deletions +}; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [Starts the bit matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_BitMat_t * Extra_BitMatrixStart( int nSize ) +{ + Extra_BitMat_t * p; + int i; + p = ALLOC( Extra_BitMat_t, 1 ); + memset( p, 0, sizeof(Extra_BitMat_t) ); + p->nSize = nSize; + p->nBitShift = (sizeof(unsigned) == 4) ? 5: 6; + p->uMask = (sizeof(unsigned) == 4) ? 31: 63; + p->nWords = nSize / (8 * sizeof(unsigned)) + ((nSize % (8 * sizeof(unsigned))) > 0); + p->ppData = ALLOC( unsigned *, nSize ); + p->ppData[0] = ALLOC( unsigned, nSize * p->nWords ); + memset( p->ppData[0], 0, sizeof(unsigned) * nSize * p->nWords ); + for ( i = 1; i < nSize; i++ ) + p->ppData[i] = p->ppData[i-1] + p->nWords; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the bit matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_BitMatrixClean( Extra_BitMat_t * p ) +{ + memset( p->ppData[0], 0, sizeof(unsigned) * p->nSize * p->nWords ); +} + +/**Function************************************************************* + + Synopsis [Stops the bit matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_BitMatrixStop( Extra_BitMat_t * p ) +{ + FREE( p->ppData[0] ); + FREE( p->ppData ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Prints the bit-matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_BitMatrixPrint( Extra_BitMat_t * pMat ) +{ + int i, k, nVars; + printf( "\n" ); + nVars = Extra_BitMatrixReadSize( pMat ); + for ( i = 0; i < nVars; i++ ) + { + for ( k = 0; k <= i; k++ ) + printf( " " ); + for ( k = i+1; k < nVars; k++ ) + if ( Extra_BitMatrixLookup1( pMat, i, k ) ) + printf( "1" ); + else + printf( "." ); + printf( "\n" ); + } +} + + +/**Function************************************************************* + + Synopsis [Reads the matrix size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_BitMatrixReadSize( Extra_BitMat_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [Inserts the element into the upper part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_BitMatrixInsert1( Extra_BitMat_t * p, int i, int k ) +{ + p->nInserts++; + if ( i < k ) + p->ppData[i][k>>p->nBitShift] |= (1<<(k & p->uMask)); + else + p->ppData[k][i>>p->nBitShift] |= (1<<(i & p->uMask)); +} + +/**Function************************************************************* + + Synopsis [Inserts the element into the upper part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_BitMatrixLookup1( Extra_BitMat_t * p, int i, int k ) +{ + p->nLookups++; + if ( i < k ) + return ((p->ppData[i][k>>p->nBitShift] & (1<<(k & p->uMask))) > 0); + else + return ((p->ppData[k][i>>p->nBitShift] & (1<<(i & p->uMask))) > 0); +} + +/**Function************************************************************* + + Synopsis [Inserts the element into the upper part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_BitMatrixDelete1( Extra_BitMat_t * p, int i, int k ) +{ + p->nDeletes++; + if ( i < k ) + p->ppData[i][k>>p->nBitShift] &= ~(1<<(k & p->uMask)); + else + p->ppData[k][i>>p->nBitShift] &= ~(1<<(i & p->uMask)); +} + + + +/**Function************************************************************* + + Synopsis [Inserts the element into the upper part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_BitMatrixInsert2( Extra_BitMat_t * p, int i, int k ) +{ + p->nInserts++; + if ( i > k ) + p->ppData[i][k>>p->nBitShift] |= (1<<(k & p->uMask)); + else + p->ppData[k][i>>p->nBitShift] |= (1<<(i & p->uMask)); +} + +/**Function************************************************************* + + Synopsis [Inserts the element into the upper part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_BitMatrixLookup2( Extra_BitMat_t * p, int i, int k ) +{ + p->nLookups++; + if ( i > k ) + return ((p->ppData[i][k>>p->nBitShift] & (1<<(k & p->uMask))) > 0); + else + return ((p->ppData[k][i>>p->nBitShift] & (1<<(i & p->uMask))) > 0); +} + +/**Function************************************************************* + + Synopsis [Inserts the element into the upper part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_BitMatrixDelete2( Extra_BitMat_t * p, int i, int k ) +{ + p->nDeletes++; + if ( i > k ) + p->ppData[i][k>>p->nBitShift] &= ~(1<<(k & p->uMask)); + else + p->ppData[k][i>>p->nBitShift] &= ~(1<<(i & p->uMask)); +} + + +/**Function************************************************************* + + Synopsis [Inserts the element into the upper part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_BitMatrixOr( Extra_BitMat_t * p, int i, unsigned * pInfo ) +{ + int w; + for ( w = 0; w < p->nWords; w++ ) + p->ppData[i][w] |= pInfo[w]; +} + +/**Function************************************************************* + + Synopsis [Inserts the element into the upper part.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_BitMatrixOrTwo( Extra_BitMat_t * p, int i, int j ) +{ + int w; + for ( w = 0; w < p->nWords; w++ ) + p->ppData[i][w] = p->ppData[j][w] = (p->ppData[i][w] | p->ppData[j][w]); +} + +/**Function************************************************************* + + Synopsis [Counts the number of 1's in the upper rectangle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_BitMatrixCountOnesUpper( Extra_BitMat_t * p ) +{ + int i, k, nTotal = 0; + for ( i = 0; i < p->nSize; i++ ) + for ( k = i + 1; k < p->nSize; k++ ) + nTotal += ( (p->ppData[i][k>>5] & (1 << (k&31))) > 0 ); + return nTotal; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the matrices have no entries in common.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_BitMatrixIsDisjoint( Extra_BitMat_t * p1, Extra_BitMat_t * p2 ) +{ + int i, w; + assert( p1->nSize == p2->nSize ); + for ( i = 0; i < p1->nSize; i++ ) + for ( w = 0; w < p1->nWords; w++ ) + if ( p1->ppData[i][w] & p2->ppData[i][w] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the matrix is a set of cliques.] + + Description [For example pairwise symmetry info should satisfy this property.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_BitMatrixIsClique( Extra_BitMat_t * pMat ) +{ + int v, u, i; + for ( v = 0; v < pMat->nSize; v++ ) + for ( u = v+1; u < pMat->nSize; u++ ) + { + if ( !Extra_BitMatrixLookup1( pMat, v, u ) ) + continue; + // v and u are symmetric + for ( i = 0; i < pMat->nSize; i++ ) + { + if ( i == v || i == u ) + continue; + // i is neither v nor u + // the symmetry status of i is the same w.r.t. to v and u + if ( Extra_BitMatrixLookup1( pMat, i, v ) != Extra_BitMatrixLookup1( pMat, i, u ) ) + return 0; + } + } + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/extra/extraUtilCanon.c b/abc70930/src/misc/extra/extraUtilCanon.c new file mode 100644 index 00000000..fcc7d84d --- /dev/null +++ b/abc70930/src/misc/extra/extraUtilCanon.c @@ -0,0 +1,701 @@ +/**CFile**************************************************************** + + FileName [extraUtilMisc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Computing canonical forms of Boolean functions using truth tables.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +static unsigned s_Truths3[256]; +static char s_Phases3[256][9]; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +static int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, char ** ppfRes, int Flag ); + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function******************************************************************** + + Synopsis [Computes the N-canonical form of the Boolean function up to 6 inputs.] + + Description [The N-canonical form is defined as the truth table with + the minimum integer value. This function exhaustively enumerates + through the complete set of 2^N phase assignments. + Returns pointers to the static storage to the truth table and phases. + This data should be used before the function is called again.] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes ) +{ + static unsigned uTruthStore6[2]; + int RetValue; + assert( nVarsMax <= 6 ); + assert( nVarsReal <= nVarsMax ); + RetValue = Extra_TruthCanonN_rec( nVarsReal <= 3? 3: nVarsReal, (unsigned char *)pt, pptRes, ppfRes, 0 ); + if ( nVarsMax == 6 && nVarsReal < nVarsMax ) + { + uTruthStore6[0] = **pptRes; + uTruthStore6[1] = **pptRes; + *pptRes = uTruthStore6; + } + return RetValue; +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [Recursive implementation of the above.] + + Description [] + + SideEffects [This procedure has a bug, which shows on Solaris. + Most likely has something to do with the casts, i.g *((unsigned *)pt0)] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, char ** ppfRes, int Flag ) +{ + static unsigned uTruthStore[7][2][2]; + static char uPhaseStore[7][2][64]; + + unsigned char * pt0, * pt1; + unsigned * ptRes0, * ptRes1, * ptRes; + unsigned uInit0, uInit1, uTruth0, uTruth1, uTemp; + char * pfRes0, * pfRes1, * pfRes; + int nf0, nf1, nfRes, i, nVarsN; + + // table lookup for three vars + if ( nVars == 3 ) + { + *pptRes = &s_Truths3[*pt]; + *ppfRes = s_Phases3[*pt]+1; + return s_Phases3[*pt][0]; + } + + // number of vars for the next call + nVarsN = nVars-1; + // truth table for the next call + pt0 = pt; + pt1 = pt + (1 << nVarsN) / 8; + // 5-var truth tables for this call +// uInit0 = *((unsigned *)pt0); +// uInit1 = *((unsigned *)pt1); + if ( nVarsN == 3 ) + { + uInit0 = (pt0[0] << 24) | (pt0[0] << 16) | (pt0[0] << 8) | pt0[0]; + uInit1 = (pt1[0] << 24) | (pt1[0] << 16) | (pt1[0] << 8) | pt1[0]; + } + else if ( nVarsN == 4 ) + { + uInit0 = (pt0[1] << 24) | (pt0[0] << 16) | (pt0[1] << 8) | pt0[0]; + uInit1 = (pt1[1] << 24) | (pt1[0] << 16) | (pt1[1] << 8) | pt1[0]; + } + else + { + uInit0 = (pt0[3] << 24) | (pt0[2] << 16) | (pt0[1] << 8) | pt0[0]; + uInit1 = (pt1[3] << 24) | (pt1[2] << 16) | (pt1[1] << 8) | pt1[0]; + } + + // storage for truth tables and phases + ptRes = uTruthStore[nVars][Flag]; + pfRes = uPhaseStore[nVars][Flag]; + + // solve trivial cases + if ( uInit1 == 0 ) + { + nf0 = Extra_TruthCanonN_rec( nVarsN, pt0, &ptRes0, &pfRes0, 0 ); + uTruth1 = uInit1; + uTruth0 = *ptRes0; + nfRes = 0; + for ( i = 0; i < nf0; i++ ) + pfRes[nfRes++] = pfRes0[i]; + goto finish; + } + if ( uInit0 == 0 ) + { + nf1 = Extra_TruthCanonN_rec( nVarsN, pt1, &ptRes1, &pfRes1, 1 ); + uTruth1 = uInit0; + uTruth0 = *ptRes1; + nfRes = 0; + for ( i = 0; i < nf1; i++ ) + pfRes[nfRes++] = pfRes1[i] | (1< uTemp ) + { + nfRes = 0; + uTruth0 = uTemp; + pfRes[nfRes++] = pfRes1[i]; + } + else if ( uTruth0 == uTemp ) + pfRes[nfRes++] = pfRes1[i]; + } + uTruth1 = *ptRes1; + } + else if ( *ptRes1 > *ptRes0 ) + { + uTruth0 = 0xFFFFFFFF; + nfRes = 0; + for ( i = 0; i < nf0; i++ ) + { + uTemp = Extra_TruthPolarize( uInit1, pfRes0[i], nVarsN ); + if ( uTruth0 > uTemp ) + { + nfRes = 0; + uTruth0 = uTemp; + pfRes[nfRes++] = pfRes0[i] | (1<= FileName; pDot-- ) + if ( *pDot == '.' ) + return pDot + 1; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the composite name of the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_FileNameAppend( char * pBase, char * pSuffix ) +{ + static char Buffer[500]; + sprintf( Buffer, "%s%s", pBase, pSuffix ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_FileNameGeneric( char * FileName ) +{ + char * pDot; + char * pUnd; + char * pRes; + + // find the generic name of the file + pRes = Extra_UtilStrsav( FileName ); + // find the pointer to the "." symbol in the file name +// pUnd = strstr( FileName, "_" ); + pUnd = NULL; + pDot = strstr( FileName, "." ); + if ( pUnd ) + pRes[pUnd - FileName] = 0; + else if ( pDot ) + pRes[pDot - FileName] = 0; + return pRes; +} + +/**Function************************************************************* + + Synopsis [Returns the file size.] + + Description [The file should be closed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_FileSize( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Extra_FileSize(): The file is unavailable (absent or open).\n" ); + return 0; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + fclose( pFile ); + return nFileSize; +} + + +/**Function************************************************************* + + Synopsis [Read the file into the internal buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_FileRead( FILE * pFile ) +{ + int nFileSize; + char * pBuffer; + // get the file size, in bytes + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + // move the file current reading position to the beginning + rewind( pFile ); + // load the contents of the file into memory + pBuffer = ALLOC( char, nFileSize + 3 ); + fread( pBuffer, nFileSize, 1, pFile ); + // terminate the string with '\0' + pBuffer[ nFileSize + 0] = '\n'; + pBuffer[ nFileSize + 1] = '\0'; + return pBuffer; +} + +/**Function************************************************************* + + Synopsis [Returns the time stamp.] + + Description [The file should be closed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_TimeStamp() +{ + static char Buffer[100]; + char * TimeStamp; + time_t ltime; + // get the current time + time( <ime ); + TimeStamp = asctime( localtime( <ime ) ); + TimeStamp[ strlen(TimeStamp) - 1 ] = 0; + strcpy( Buffer, TimeStamp ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Extra_ReadBinary( char * Buffer ) +{ + unsigned Result; + int i; + + Result = 0; + for ( i = 0; Buffer[i]; i++ ) + if ( Buffer[i] == '0' || Buffer[i] == '1' ) + Result = Result * 2 + Buffer[i] - '0'; + else + { + assert( 0 ); + } + return Result; +} + +/**Function************************************************************* + + Synopsis [Prints the bit string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ) +{ + int Remainder, nWords; + int w, i; + + Remainder = (nBits%(sizeof(unsigned)*8)); + nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); + + for ( w = nWords-1; w >= 0; w-- ) + for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) + fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1< 0) ); + +// fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Reads the hex unsigned into the bit-string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars ) +{ + int nWords, nDigits, Digit, k, c; + nWords = Extra_TruthWordNum( nVars ); + for ( k = 0; k < nWords; k++ ) + Sign[k] = 0; + // read the number from the string + nDigits = (1 << nVars) / 4; + if ( nDigits == 0 ) + nDigits = 1; + for ( k = 0; k < nDigits; k++ ) + { + c = nDigits-1-k; + if ( pString[c] >= '0' && pString[c] <= '9' ) + Digit = pString[c] - '0'; + else if ( pString[c] >= 'A' && pString[c] <= 'F' ) + Digit = pString[c] - 'A' + 10; + else if ( pString[c] >= 'a' && pString[c] <= 'f' ) + Digit = pString[c] - 'a' + 10; + else { assert( 0 ); return 0; } + Sign[k/8] |= ( (Digit & 15) << ((k%8) * 4) ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Prints the hex unsigned into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ) +{ + int nDigits, Digit, k; + // write the number into the file + nDigits = (1 << nVars) / 4; + for ( k = nDigits - 1; k >= 0; k-- ) + { + Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15); + if ( Digit < 10 ) + fprintf( pFile, "%d", Digit ); + else + fprintf( pFile, "%c", 'a' + Digit-10 ); + } +// fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the hex unsigned into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars ) +{ + int nDigits, Digit, k; + // write the number into the file + nDigits = (1 << nVars) / 4; + for ( k = nDigits - 1; k >= 0; k-- ) + { + Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15); + if ( Digit < 10 ) + *pString++ = '0' + Digit; + else + *pString++ = 'a' + Digit-10; + } +// fprintf( pFile, "\n" ); + *pString = 0; +} + +/**Function************************************************************* + + Synopsis [Prints the hex unsigned into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_PrintHex( FILE * pFile, unsigned uTruth, int nVars ) +{ + int nMints, nDigits, Digit, k; + + // write the number into the file + fprintf( pFile, "0x" ); + nMints = (1 << nVars); + nDigits = nMints / 4; + for ( k = nDigits - 1; k >= 0; k-- ) + { + Digit = ((uTruth >> (k * 4)) & 15); + if ( Digit < 10 ) + fprintf( pFile, "%d", Digit ); + else + fprintf( pFile, "%c", 'a' + Digit-10 ); + } +// fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Returns the composite name of the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine ) +{ + int i; + for ( i = 0; i < nTimes; i++ ) + printf( "%c", Char ); + if ( fPrintNewLine ) + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Appends the string.] + + Description [Assumes that the given string (pStrGiven) has been allocated + before using malloc(). The additional string has not been allocated. + Allocs more root, appends the additional part, frees the old given string.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_StringAppend( char * pStrGiven, char * pStrAdd ) +{ + char * pTemp; + if ( pStrGiven ) + { + pTemp = ALLOC( char, strlen(pStrGiven) + strlen(pStrAdd) + 2 ); + sprintf( pTemp, "%s%s", pStrGiven, pStrAdd ); + free( pStrGiven ); + } + else + pTemp = Extra_UtilStrsav( pStrAdd ); + return pTemp; +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/extra/extraUtilMemory.c b/abc70930/src/misc/extra/extraUtilMemory.c new file mode 100644 index 00000000..6eccf015 --- /dev/null +++ b/abc70930/src/misc/extra/extraUtilMemory.c @@ -0,0 +1,625 @@ +/**CFile**************************************************************** + + FileName [extraUtilMemory.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Memory managers.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraUtilMemory.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +struct Extra_MmFixed_t_ +{ + // information about individual entries + int nEntrySize; // the size of one entry + int nEntriesAlloc; // the total number of entries allocated + int nEntriesUsed; // the number of entries in use + int nEntriesMax; // the max number of entries in use + char * pEntriesFree; // the linked list of free entries + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Extra_MmFlex_t_ +{ + // information about individual entries + int nEntriesUsed; // the number of entries allocated + char * pCurrent; // the current pointer to free memory + char * pEnd; // the first entry outside the free memory + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + + +struct Extra_MmStep_t_ +{ + int nMems; // the number of fixed memory managers employed + Extra_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc + int nMapSize; // the size of the memory array + Extra_MmFixed_t ** pMap; // maps the number of bytes into its memory manager + int nLargeChunksAlloc; // the maximum number of large memory chunks + int nLargeChunks; // the current number of large memory chunks + void ** pLargeChunks; // the allocated large memory chunks +}; + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [Allocates memory pieces of fixed size.] + + Description [The size of the chunk is computed as the minimum of + 1024 entries and 64K. Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize ) +{ + Extra_MmFixed_t * p; + + p = ALLOC( Extra_MmFixed_t, 1 ); + memset( p, 0, sizeof(Extra_MmFixed_t) ); + + p->nEntrySize = nEntrySize; + p->nEntriesAlloc = 0; + p->nEntriesUsed = 0; + p->pEntriesFree = NULL; + + if ( nEntrySize * (1 << 10) < (1<<16) ) + p->nChunkSize = (1 << 10); + else + p->nChunkSize = (1<<16) / nEntrySize; + if ( p->nChunkSize < 8 ) + p->nChunkSize = 8; + + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_MmFixedPrint( Extra_MmFixed_t * p ) +{ + printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", + p->nEntrySize, p->nChunkSize, p->nChunks ); + printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", + p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_MmFixedStop( Extra_MmFixed_t * p ) +{ + int i; + if ( p == NULL ) + return; + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_MmFixedEntryFetch( Extra_MmFixed_t * p ) +{ + char * pTemp; + int i; + + // check if there are still free entries + if ( p->nEntriesUsed == p->nEntriesAlloc ) + { // need to allocate more entries + assert( p->pEntriesFree == NULL ); + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); + p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; + // transform these entries into a linked list + pTemp = p->pEntriesFree; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pEntriesFree; + // add to the number of entries allocated + p->nEntriesAlloc += p->nChunkSize; + } + // incrememt the counter of used entries + p->nEntriesUsed++; + if ( p->nEntriesMax < p->nEntriesUsed ) + p->nEntriesMax = p->nEntriesUsed; + // return the first entry in the free entry list + pTemp = p->pEntriesFree; + p->pEntriesFree = *((char **)pTemp); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry ) +{ + // decrement the counter of used entries + p->nEntriesUsed--; + // add the entry to the linked list of free entries + *((char **)pEntry) = p->pEntriesFree; + p->pEntriesFree = pEntry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_MmFixedRestart( Extra_MmFixed_t * p ) +{ + int i; + char * pTemp; + + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + p->nChunks = 1; + // transform these entries into a linked list + pTemp = p->pChunks[0]; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // set the free entry list + p->pEntriesFree = p->pChunks[0]; + // set the correct statistics + p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; + p->nMemoryUsed = 0; + p->nEntriesAlloc = p->nChunkSize; + p->nEntriesUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p ) +{ + return p->nMemoryAlloc; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p ) +{ + return p->nEntriesMax; +} + + +/**Function************************************************************* + + Synopsis [Allocates entries of flexible size.] + + Description [Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_MmFlex_t * Extra_MmFlexStart() +{ + Extra_MmFlex_t * p; +//printf( "allocing flex\n" ); + p = ALLOC( Extra_MmFlex_t, 1 ); + memset( p, 0, sizeof(Extra_MmFlex_t) ); + + p->nEntriesUsed = 0; + p->pCurrent = NULL; + p->pEnd = NULL; + + p->nChunkSize = (1 << 10); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_MmFlexPrint( Extra_MmFlex_t * p ) +{ + printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", + p->nChunkSize, p->nChunks ); + printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", + p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_MmFlexStop( Extra_MmFlex_t * p ) +{ + int i; + if ( p == NULL ) + return; +//printf( "deleting flex\n" ); + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_MmFlexEntryFetch( Extra_MmFlex_t * p, int nBytes ) +{ + char * pTemp; + // check if there are still free entries + if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) + { // need to allocate more entries + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + if ( nBytes > p->nChunkSize ) + { + // resize the chunk size if more memory is requested than it can give + // (ideally, this should never happen) + p->nChunkSize = 2 * nBytes; + } + p->pCurrent = ALLOC( char, p->nChunkSize ); + p->pEnd = p->pCurrent + p->nChunkSize; + p->nMemoryAlloc += p->nChunkSize; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pCurrent; + } + assert( p->pCurrent + nBytes <= p->pEnd ); + // increment the counter of used entries + p->nEntriesUsed++; + // keep track of the memory used + p->nMemoryUsed += nBytes; + // return the next entry + pTemp = p->pCurrent; + p->pCurrent += nBytes; + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_MmFlexReadMemUsage( Extra_MmFlex_t * p ) +{ + return p->nMemoryAlloc; +} + + + + + +/**Function************************************************************* + + Synopsis [Starts the hierarchical memory manager.] + + Description [This manager can allocate entries of any size. + Iternally they are mapped into the entries with the number of bytes + equal to the power of 2. The smallest entry size is 8 bytes. The + next one is 16 bytes etc. So, if the user requests 6 bytes, he gets + 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. + The input parameters "nSteps" says how many fixed memory managers + are employed internally. Calling this procedure with nSteps equal + to 10 results in 10 hierarchically arranged internal memory managers, + which can allocate up to 4096 (1Kb) entries. Requests for larger + entries are handed over to malloc() and then free()ed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_MmStep_t * Extra_MmStepStart( int nSteps ) +{ + Extra_MmStep_t * p; + int i, k; + p = ALLOC( Extra_MmStep_t, 1 ); + memset( p, 0, sizeof(Extra_MmStep_t) ); + p->nMems = nSteps; + // start the fixed memory managers + p->pMems = ALLOC( Extra_MmFixed_t *, p->nMems ); + for ( i = 0; i < p->nMems; i++ ) + p->pMems[i] = Extra_MmFixedStart( (8<nMapSize = (4<nMems); + p->pMap = ALLOC( Extra_MmFixed_t *, p->nMapSize+1 ); + p->pMap[0] = NULL; + for ( k = 1; k <= 4; k++ ) + p->pMap[k] = p->pMems[0]; + for ( i = 0; i < p->nMems; i++ ) + for ( k = (4<pMap[k] = p->pMems[i]; +//for ( i = 1; i < 100; i ++ ) +//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_MmStepStop( Extra_MmStep_t * p ) +{ + int i; + for ( i = 0; i < p->nMems; i++ ) + Extra_MmFixedStop( p->pMems[i] ); +// if ( p->pLargeChunks ) +// { +// for ( i = 0; i < p->nLargeChunks; i++ ) +// free( p->pLargeChunks[i] ); +// free( p->pLargeChunks ); +// } + free( p->pMems ); + free( p->pMap ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Creates the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes ) +{ + if ( nBytes == 0 ) + return NULL; + if ( nBytes > p->nMapSize ) + { +// printf( "Allocating %d bytes.\n", nBytes ); +/* + if ( p->nLargeChunks == p->nLargeChunksAlloc ) + { + if ( p->nLargeChunksAlloc == 0 ) + p->nLargeChunksAlloc = 5; + p->nLargeChunksAlloc *= 2; + p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); + } + p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes ); + return p->pLargeChunks[ p->nLargeChunks - 1 ]; +*/ + return ALLOC( char, nBytes ); + } + return Extra_MmFixedEntryFetch( p->pMap[nBytes] ); +} + + +/**Function************************************************************* + + Synopsis [Recycles the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_MmStepEntryRecycle( Extra_MmStep_t * p, char * pEntry, int nBytes ) +{ + if ( nBytes == 0 ) + return; + if ( nBytes > p->nMapSize ) + { + free( pEntry ); + return; + } + Extra_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_MmStepReadMemUsage( Extra_MmStep_t * p ) +{ + int i, nMemTotal = 0; + for ( i = 0; i < p->nMems; i++ ) + nMemTotal += p->pMems[i]->nMemoryAlloc; + return nMemTotal; +} + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static functions */ +/*---------------------------------------------------------------------------*/ + diff --git a/abc70930/src/misc/extra/extraUtilMisc.c b/abc70930/src/misc/extra/extraUtilMisc.c new file mode 100644 index 00000000..dff774bc --- /dev/null +++ b/abc70930/src/misc/extra/extraUtilMisc.c @@ -0,0 +1,2235 @@ +/**CFile**************************************************************** + + FileName [extraUtilMisc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Misc procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + +static void Extra_Permutations_rec( char ** pRes, int nFact, int n, char Array[] ); + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function******************************************************************** + + Synopsis [Finds the smallest integer larger of equal than the logarithm.] + + Description [Returns [Log2(Num)].] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_Base2Log( unsigned Num ) +{ + int Res; + assert( Num >= 0 ); + if ( Num == 0 ) return 0; + if ( Num == 1 ) return 1; + for ( Res = 0, Num--; Num; Num >>= 1, Res++ ); + return Res; +} /* end of Extra_Base2Log */ + +/**Function******************************************************************** + + Synopsis [Finds the smallest integer larger of equal than the logarithm.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_Base2LogDouble( double Num ) +{ + double Res; + int ResInt; + + Res = log(Num)/log(2.0); + ResInt = (int)Res; + if ( ResInt == Res ) + return ResInt; + else + return ResInt+1; +} + +/**Function******************************************************************** + + Synopsis [Finds the smallest integer larger of equal than the logarithm.] + + Description [Returns [Log10(Num)].] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +int Extra_Base10Log( unsigned Num ) +{ + int Res; + assert( Num >= 0 ); + if ( Num == 0 ) return 0; + if ( Num == 1 ) return 1; + for ( Res = 0, Num--; Num; Num /= 10, Res++ ); + return Res; +} /* end of Extra_Base2Log */ + +/**Function******************************************************************** + + Synopsis [Returns the power of two as a double.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +double Extra_Power2( int Degree ) +{ + double Res; + assert( Degree >= 0 ); + if ( Degree < 32 ) + return (double)(01<>= Shift; + uTruth = uCof0 | uCof1; + } + return uTruth; +} + +/**Function************************************************************* + + Synopsis [Computes N-canonical form using brute-force methods.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Extra_TruthCanonN( unsigned uTruth, int nVars ) +{ + unsigned uTruthMin, uPhase; + int nMints, i; + nMints = (1 << nVars); + uTruthMin = 0xFFFFFFFF; + for ( i = 0; i < nMints; i++ ) + { + uPhase = Extra_TruthPolarize( uTruth, i, nVars ); + if ( uTruthMin > uPhase ) + uTruthMin = uPhase; + } + return uTruthMin; +} + +/**Function************************************************************* + + Synopsis [Computes NN-canonical form using brute-force methods.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Extra_TruthCanonNN( unsigned uTruth, int nVars ) +{ + unsigned uTruthMin, uTruthC, uPhase; + int nMints, i; + nMints = (1 << nVars); + uTruthC = (unsigned)( (~uTruth) & ((~((unsigned)0)) >> (32-nMints)) ); + uTruthMin = 0xFFFFFFFF; + for ( i = 0; i < nMints; i++ ) + { + uPhase = Extra_TruthPolarize( uTruth, i, nVars ); + if ( uTruthMin > uPhase ) + uTruthMin = uPhase; + uPhase = Extra_TruthPolarize( uTruthC, i, nVars ); + if ( uTruthMin > uPhase ) + uTruthMin = uPhase; + } + return uTruthMin; +} + +/**Function************************************************************* + + Synopsis [Computes P-canonical form using brute-force methods.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Extra_TruthCanonP( unsigned uTruth, int nVars ) +{ + static int nVarsOld, nPerms; + static char ** pPerms = NULL; + + unsigned uTruthMin, uPerm; + int k; + + if ( pPerms == NULL ) + { + nPerms = Extra_Factorial( nVars ); + pPerms = Extra_Permutations( nVars ); + nVarsOld = nVars; + } + else if ( nVarsOld != nVars ) + { + free( pPerms ); + nPerms = Extra_Factorial( nVars ); + pPerms = Extra_Permutations( nVars ); + nVarsOld = nVars; + } + + uTruthMin = 0xFFFFFFFF; + for ( k = 0; k < nPerms; k++ ) + { + uPerm = Extra_TruthPermute( uTruth, pPerms[k], nVars, 0 ); + if ( uTruthMin > uPerm ) + uTruthMin = uPerm; + } + return uTruthMin; +} + +/**Function************************************************************* + + Synopsis [Computes NP-canonical form using brute-force methods.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Extra_TruthCanonNP( unsigned uTruth, int nVars ) +{ + static int nVarsOld, nPerms; + static char ** pPerms = NULL; + + unsigned uTruthMin, uPhase, uPerm; + int nMints, k, i; + + if ( pPerms == NULL ) + { + nPerms = Extra_Factorial( nVars ); + pPerms = Extra_Permutations( nVars ); + nVarsOld = nVars; + } + else if ( nVarsOld != nVars ) + { + free( pPerms ); + nPerms = Extra_Factorial( nVars ); + pPerms = Extra_Permutations( nVars ); + nVarsOld = nVars; + } + + nMints = (1 << nVars); + uTruthMin = 0xFFFFFFFF; + for ( i = 0; i < nMints; i++ ) + { + uPhase = Extra_TruthPolarize( uTruth, i, nVars ); + for ( k = 0; k < nPerms; k++ ) + { + uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 ); + if ( uTruthMin > uPerm ) + uTruthMin = uPerm; + } + } + return uTruthMin; +} + +/**Function************************************************************* + + Synopsis [Computes NPN-canonical form using brute-force methods.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Extra_TruthCanonNPN( unsigned uTruth, int nVars ) +{ + static int nVarsOld, nPerms; + static char ** pPerms = NULL; + + unsigned uTruthMin, uTruthC, uPhase, uPerm; + int nMints, k, i; + + if ( pPerms == NULL ) + { + nPerms = Extra_Factorial( nVars ); + pPerms = Extra_Permutations( nVars ); + nVarsOld = nVars; + } + else if ( nVarsOld != nVars ) + { + free( pPerms ); + nPerms = Extra_Factorial( nVars ); + pPerms = Extra_Permutations( nVars ); + nVarsOld = nVars; + } + + nMints = (1 << nVars); + uTruthC = (unsigned)( (~uTruth) & ((~((unsigned)0)) >> (32-nMints)) ); + uTruthMin = 0xFFFFFFFF; + for ( i = 0; i < nMints; i++ ) + { + uPhase = Extra_TruthPolarize( uTruth, i, nVars ); + for ( k = 0; k < nPerms; k++ ) + { + uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 ); + if ( uTruthMin > uPerm ) + uTruthMin = uPerm; + } + uPhase = Extra_TruthPolarize( uTruthC, i, nVars ); + for ( k = 0; k < nPerms; k++ ) + { + uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 ); + if ( uTruthMin > uPerm ) + uTruthMin = uPerm; + } + } + return uTruthMin; +} + +/**Function************************************************************* + + Synopsis [Computes NPN canonical forms for 4-variable functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ) +{ + unsigned short * uCanons; + unsigned char * uMap; + unsigned uTruth, uPhase, uPerm; + char ** pPerms4, * uPhases, * uPerms; + int nFuncs, nClasses; + int i, k; + + nFuncs = (1 << 16); + uCanons = ALLOC( unsigned short, nFuncs ); + uPhases = ALLOC( char, nFuncs ); + uPerms = ALLOC( char, nFuncs ); + uMap = ALLOC( unsigned char, nFuncs ); + memset( uCanons, 0, sizeof(unsigned short) * nFuncs ); + memset( uPhases, 0, sizeof(char) * nFuncs ); + memset( uPerms, 0, sizeof(char) * nFuncs ); + memset( uMap, 0, sizeof(unsigned char) * nFuncs ); + pPerms4 = Extra_Permutations( 4 ); + + nClasses = 1; + nFuncs = (1 << 15); + for ( uTruth = 1; uTruth < (unsigned)nFuncs; uTruth++ ) + { + // skip already assigned + if ( uCanons[uTruth] ) + { + assert( uTruth > uCanons[uTruth] ); + uMap[~uTruth & 0xFFFF] = uMap[uTruth] = uMap[uCanons[uTruth]]; + continue; + } + uMap[uTruth] = nClasses++; + for ( i = 0; i < 16; i++ ) + { + uPhase = Extra_TruthPolarize( uTruth, i, 4 ); + for ( k = 0; k < 24; k++ ) + { + uPerm = Extra_TruthPermute( uPhase, pPerms4[k], 4, 0 ); + if ( uCanons[uPerm] == 0 ) + { + uCanons[uPerm] = uTruth; + uPhases[uPerm] = i; + uPerms[uPerm] = k; + + uPerm = ~uPerm & 0xFFFF; + uCanons[uPerm] = uTruth; + uPhases[uPerm] = i | 16; + uPerms[uPerm] = k; + } + else + assert( uCanons[uPerm] == uTruth ); + } + uPhase = Extra_TruthPolarize( ~uTruth & 0xFFFF, i, 4 ); + for ( k = 0; k < 24; k++ ) + { + uPerm = Extra_TruthPermute( uPhase, pPerms4[k], 4, 0 ); + if ( uCanons[uPerm] == 0 ) + { + uCanons[uPerm] = uTruth; + uPhases[uPerm] = i; + uPerms[uPerm] = k; + + uPerm = ~uPerm & 0xFFFF; + uCanons[uPerm] = uTruth; + uPhases[uPerm] = i | 16; + uPerms[uPerm] = k; + } + else + assert( uCanons[uPerm] == uTruth ); + } + } + } + uPhases[(1<<16)-1] = 16; + assert( nClasses == 222 ); + free( pPerms4 ); + if ( puCanons ) + *puCanons = uCanons; + else + free( uCanons ); + if ( puPhases ) + *puPhases = uPhases; + else + free( uPhases ); + if ( puPerms ) + *puPerms = uPerms; + else + free( uPerms ); + if ( puMap ) + *puMap = uMap; + else + free( uMap ); +} + +/**Function************************************************************* + + Synopsis [Computes NPN canonical forms for 4-variable functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_Truth3VarN( unsigned ** puCanons, char *** puPhases, char ** ppCounters ) +{ + int nPhasesMax = 8; + unsigned * uCanons; + unsigned uTruth, uPhase, uTruth32; + char ** uPhases, * pCounters; + int nFuncs, nClasses, i; + + nFuncs = (1 << 8); + uCanons = ALLOC( unsigned, nFuncs ); + memset( uCanons, 0, sizeof(unsigned) * nFuncs ); + pCounters = ALLOC( char, nFuncs ); + memset( pCounters, 0, sizeof(char) * nFuncs ); + uPhases = (char **)Extra_ArrayAlloc( nFuncs, nPhasesMax, sizeof(char) ); + nClasses = 0; + for ( uTruth = 0; uTruth < (unsigned)nFuncs; uTruth++ ) + { + // skip already assigned + uTruth32 = ((uTruth << 24) | (uTruth << 16) | (uTruth << 8) | uTruth); + if ( uCanons[uTruth] ) + { + assert( uTruth32 > uCanons[uTruth] ); + continue; + } + nClasses++; + for ( i = 0; i < 8; i++ ) + { + uPhase = Extra_TruthPolarize( uTruth, i, 3 ); + if ( uCanons[uPhase] == 0 && (uTruth || i==0) ) + { + uCanons[uPhase] = uTruth32; + uPhases[uPhase][0] = i; + pCounters[uPhase] = 1; + } + else + { + assert( uCanons[uPhase] == uTruth32 ); + if ( pCounters[uPhase] < nPhasesMax ) + uPhases[uPhase][ pCounters[uPhase]++ ] = i; + } + } + } + if ( puCanons ) + *puCanons = uCanons; + else + free( uCanons ); + if ( puPhases ) + *puPhases = uPhases; + else + free( uPhases ); + if ( ppCounters ) + *ppCounters = pCounters; + else + free( pCounters ); +// printf( "The number of 3N-classes = %d.\n", nClasses ); +} + +/**Function************************************************************* + + Synopsis [Computes NPN canonical forms for 4-variable functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int nPhasesMax ) +{ + unsigned short * uCanons; + unsigned uTruth, uPhase; + char ** uPhases, * pCounters; + int nFuncs, nClasses, i; + + nFuncs = (1 << 16); + uCanons = ALLOC( unsigned short, nFuncs ); + memset( uCanons, 0, sizeof(unsigned short) * nFuncs ); + pCounters = ALLOC( char, nFuncs ); + memset( pCounters, 0, sizeof(char) * nFuncs ); + uPhases = (char **)Extra_ArrayAlloc( nFuncs, nPhasesMax, sizeof(char) ); + nClasses = 0; + for ( uTruth = 0; uTruth < (unsigned)nFuncs; uTruth++ ) + { + // skip already assigned + if ( uCanons[uTruth] ) + { + assert( uTruth > uCanons[uTruth] ); + continue; + } + nClasses++; + for ( i = 0; i < 16; i++ ) + { + uPhase = Extra_TruthPolarize( uTruth, i, 4 ); + if ( uCanons[uPhase] == 0 && (uTruth || i==0) ) + { + uCanons[uPhase] = uTruth; + uPhases[uPhase][0] = i; + pCounters[uPhase] = 1; + } + else + { + assert( uCanons[uPhase] == uTruth ); + if ( pCounters[uPhase] < nPhasesMax ) + uPhases[uPhase][ pCounters[uPhase]++ ] = i; + } + } + } + if ( puCanons ) + *puCanons = uCanons; + else + free( uCanons ); + if ( puPhases ) + *puPhases = uPhases; + else + free( uPhases ); + if ( ppCounters ) + *ppCounters = pCounters; + else + free( pCounters ); +// printf( "The number of 4N-classes = %d.\n", nClasses ); +} + +/**Function************************************************************* + + Synopsis [Allocated one-memory-chunk array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ** Extra_ArrayAlloc( int nCols, int nRows, int Size ) +{ + char ** pRes; + char * pBuffer; + int i; + assert( nCols > 0 && nRows > 0 && Size > 0 ); + pBuffer = ALLOC( char, nCols * (sizeof(void *) + nRows * Size) ); + pRes = (char **)pBuffer; + pRes[0] = pBuffer + nCols * sizeof(void *); + for ( i = 1; i < nCols; i++ ) + pRes[i] = pRes[0] + i * nRows * Size; + return pRes; +} + +/**Function************************************************************* + + Synopsis [Computes a phase of the 3-var function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned short Extra_TruthPerm4One( unsigned uTruth, int Phase ) +{ + // cases + static unsigned short Cases[16] = { + 0, // 0000 - skip + 0, // 0001 - skip + 0xCCCC, // 0010 - single var + 0, // 0011 - skip + 0xF0F0, // 0100 - single var + 1, // 0101 + 1, // 0110 + 0, // 0111 - skip + 0xFF00, // 1000 - single var + 1, // 1001 + 1, // 1010 + 1, // 1011 + 1, // 1100 + 1, // 1101 + 1, // 1110 + 0 // 1111 - skip + }; + // permutations + static int Perms[16][4] = { + { 0, 0, 0, 0 }, // 0000 - skip + { 0, 0, 0, 0 }, // 0001 - skip + { 0, 0, 0, 0 }, // 0010 - single var + { 0, 0, 0, 0 }, // 0011 - skip + { 0, 0, 0, 0 }, // 0100 - single var + { 0, 2, 1, 3 }, // 0101 + { 2, 0, 1, 3 }, // 0110 + { 0, 0, 0, 0 }, // 0111 - skip + { 0, 0, 0, 0 }, // 1000 - single var + { 0, 2, 3, 1 }, // 1001 + { 2, 0, 3, 1 }, // 1010 + { 0, 1, 3, 2 }, // 1011 + { 2, 3, 0, 1 }, // 1100 + { 0, 3, 1, 2 }, // 1101 + { 3, 0, 1, 2 }, // 1110 + { 0, 0, 0, 0 } // 1111 - skip + }; + int i, k, iRes; + unsigned uTruthRes; + assert( Phase >= 0 && Phase < 16 ); + if ( Cases[Phase] == 0 ) + return uTruth; + if ( Cases[Phase] > 1 ) + return Cases[Phase]; + uTruthRes = 0; + for ( i = 0; i < 16; i++ ) + if ( uTruth & (1 << i) ) + { + for ( iRes = 0, k = 0; k < 4; k++ ) + if ( i & (1 << Perms[Phase][k]) ) + iRes |= (1 << k); + uTruthRes |= (1 << iRes); + } + return uTruthRes; +} + +/**Function************************************************************* + + Synopsis [Computes a phase of the 3-var function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Extra_TruthPerm5One( unsigned uTruth, int Phase ) +{ + // cases + static unsigned Cases[32] = { + 0, // 00000 - skip + 0, // 00001 - skip + 0xCCCCCCCC, // 00010 - single var + 0, // 00011 - skip + 0xF0F0F0F0, // 00100 - single var + 1, // 00101 + 1, // 00110 + 0, // 00111 - skip + 0xFF00FF00, // 01000 - single var + 1, // 01001 + 1, // 01010 + 1, // 01011 + 1, // 01100 + 1, // 01101 + 1, // 01110 + 0, // 01111 - skip + 0xFFFF0000, // 10000 - skip + 1, // 10001 + 1, // 10010 + 1, // 10011 + 1, // 10100 + 1, // 10101 + 1, // 10110 + 1, // 10111 - four var + 1, // 11000 + 1, // 11001 + 1, // 11010 + 1, // 11011 - four var + 1, // 11100 + 1, // 11101 - four var + 1, // 11110 - four var + 0 // 11111 - skip + }; + // permutations + static int Perms[32][5] = { + { 0, 0, 0, 0, 0 }, // 00000 - skip + { 0, 0, 0, 0, 0 }, // 00001 - skip + { 0, 0, 0, 0, 0 }, // 00010 - single var + { 0, 0, 0, 0, 0 }, // 00011 - skip + { 0, 0, 0, 0, 0 }, // 00100 - single var + { 0, 2, 1, 3, 4 }, // 00101 + { 2, 0, 1, 3, 4 }, // 00110 + { 0, 0, 0, 0, 0 }, // 00111 - skip + { 0, 0, 0, 0, 0 }, // 01000 - single var + { 0, 2, 3, 1, 4 }, // 01001 + { 2, 0, 3, 1, 4 }, // 01010 + { 0, 1, 3, 2, 4 }, // 01011 + { 2, 3, 0, 1, 4 }, // 01100 + { 0, 3, 1, 2, 4 }, // 01101 + { 3, 0, 1, 2, 4 }, // 01110 + { 0, 0, 0, 0, 0 }, // 01111 - skip + { 0, 0, 0, 0, 0 }, // 10000 - single var + { 0, 4, 2, 3, 1 }, // 10001 + { 4, 0, 2, 3, 1 }, // 10010 + { 0, 1, 3, 4, 2 }, // 10011 + { 2, 3, 0, 4, 1 }, // 10100 + { 0, 3, 1, 4, 2 }, // 10101 + { 3, 0, 1, 4, 2 }, // 10110 + { 0, 1, 2, 4, 3 }, // 10111 - four var + { 2, 3, 4, 0, 1 }, // 11000 + { 0, 3, 4, 1, 2 }, // 11001 + { 3, 0, 4, 1, 2 }, // 11010 + { 0, 1, 4, 2, 3 }, // 11011 - four var + { 3, 4, 0, 1, 2 }, // 11100 + { 0, 4, 1, 2, 3 }, // 11101 - four var + { 4, 0, 1, 2, 3 }, // 11110 - four var + { 0, 0, 0, 0, 0 } // 11111 - skip + }; + int i, k, iRes; + unsigned uTruthRes; + assert( Phase >= 0 && Phase < 32 ); + if ( Cases[Phase] == 0 ) + return uTruth; + if ( Cases[Phase] > 1 ) + return Cases[Phase]; + uTruthRes = 0; + for ( i = 0; i < 32; i++ ) + if ( uTruth & (1 << i) ) + { + for ( iRes = 0, k = 0; k < 5; k++ ) + if ( i & (1 << Perms[Phase][k]) ) + iRes |= (1 << k); + uTruthRes |= (1 << iRes); + } + return uTruthRes; +} + +/**Function************************************************************* + + Synopsis [Computes a phase of the 3-var function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes ) +{ + // cases + static unsigned Cases[64] = { + 0, // 000000 - skip + 0, // 000001 - skip + 0xCCCCCCCC, // 000010 - single var + 0, // 000011 - skip + 0xF0F0F0F0, // 000100 - single var + 1, // 000101 + 1, // 000110 + 0, // 000111 - skip + 0xFF00FF00, // 001000 - single var + 1, // 001001 + 1, // 001010 + 1, // 001011 + 1, // 001100 + 1, // 001101 + 1, // 001110 + 0, // 001111 - skip + 0xFFFF0000, // 010000 - skip + 1, // 010001 + 1, // 010010 + 1, // 010011 + 1, // 010100 + 1, // 010101 + 1, // 010110 + 1, // 010111 - four var + 1, // 011000 + 1, // 011001 + 1, // 011010 + 1, // 011011 - four var + 1, // 011100 + 1, // 011101 - four var + 1, // 011110 - four var + 0, // 011111 - skip + 0xFFFFFFFF, // 100000 - single var + 1, // 100001 + 1, // 100010 + 1, // 100011 + 1, // 100100 + 1, // 100101 + 1, // 100110 + 1, // 100111 + 1, // 101000 + 1, // 101001 + 1, // 101010 + 1, // 101011 + 1, // 101100 + 1, // 101101 + 1, // 101110 + 1, // 101111 + 1, // 110000 + 1, // 110001 + 1, // 110010 + 1, // 110011 + 1, // 110100 + 1, // 110101 + 1, // 110110 + 1, // 110111 + 1, // 111000 + 1, // 111001 + 1, // 111010 + 1, // 111011 + 1, // 111100 + 1, // 111101 + 1, // 111110 + 0 // 111111 - skip + }; + // permutations + static int Perms[64][6] = { + { 0, 0, 0, 0, 0, 0 }, // 000000 - skip + { 0, 0, 0, 0, 0, 0 }, // 000001 - skip + { 0, 0, 0, 0, 0, 0 }, // 000010 - single var + { 0, 0, 0, 0, 0, 0 }, // 000011 - skip + { 0, 0, 0, 0, 0, 0 }, // 000100 - single var + { 0, 2, 1, 3, 4, 5 }, // 000101 + { 2, 0, 1, 3, 4, 5 }, // 000110 + { 0, 0, 0, 0, 0, 0 }, // 000111 - skip + { 0, 0, 0, 0, 0, 0 }, // 001000 - single var + { 0, 2, 3, 1, 4, 5 }, // 001001 + { 2, 0, 3, 1, 4, 5 }, // 001010 + { 0, 1, 3, 2, 4, 5 }, // 001011 + { 2, 3, 0, 1, 4, 5 }, // 001100 + { 0, 3, 1, 2, 4, 5 }, // 001101 + { 3, 0, 1, 2, 4, 5 }, // 001110 + { 0, 0, 0, 0, 0, 0 }, // 001111 - skip + { 0, 0, 0, 0, 0, 0 }, // 010000 - skip + { 0, 4, 2, 3, 1, 5 }, // 010001 + { 4, 0, 2, 3, 1, 5 }, // 010010 + { 0, 1, 3, 4, 2, 5 }, // 010011 + { 2, 3, 0, 4, 1, 5 }, // 010100 + { 0, 3, 1, 4, 2, 5 }, // 010101 + { 3, 0, 1, 4, 2, 5 }, // 010110 + { 0, 1, 2, 4, 3, 5 }, // 010111 - four var + { 2, 3, 4, 0, 1, 5 }, // 011000 + { 0, 3, 4, 1, 2, 5 }, // 011001 + { 3, 0, 4, 1, 2, 5 }, // 011010 + { 0, 1, 4, 2, 3, 5 }, // 011011 - four var + { 3, 4, 0, 1, 2, 5 }, // 011100 + { 0, 4, 1, 2, 3, 5 }, // 011101 - four var + { 4, 0, 1, 2, 3, 5 }, // 011110 - four var + { 0, 0, 0, 0, 0, 0 }, // 011111 - skip + { 0, 0, 0, 0, 0, 0 }, // 100000 - single var + { 0, 2, 3, 4, 5, 1 }, // 100001 + { 2, 0, 3, 4, 5, 1 }, // 100010 + { 0, 1, 3, 4, 5, 2 }, // 100011 + { 2, 3, 0, 4, 5, 1 }, // 100100 + { 0, 3, 1, 4, 5, 2 }, // 100101 + { 3, 0, 1, 4, 5, 2 }, // 100110 + { 0, 1, 2, 4, 5, 3 }, // 100111 + { 2, 3, 4, 0, 5, 1 }, // 101000 + { 0, 3, 4, 1, 5, 2 }, // 101001 + { 3, 0, 4, 1, 5, 2 }, // 101010 + { 0, 1, 4, 2, 5, 3 }, // 101011 + { 3, 4, 0, 1, 5, 2 }, // 101100 + { 0, 4, 1, 2, 5, 3 }, // 101101 + { 4, 0, 1, 2, 5, 3 }, // 101110 + { 0, 1, 2, 3, 5, 4 }, // 101111 + { 2, 3, 4, 5, 0, 1 }, // 110000 + { 0, 3, 4, 5, 1, 2 }, // 110001 + { 3, 0, 4, 5, 1, 2 }, // 110010 + { 0, 1, 4, 5, 2, 3 }, // 110011 + { 3, 4, 0, 5, 1, 2 }, // 110100 + { 0, 4, 1, 5, 2, 3 }, // 110101 + { 4, 0, 1, 5, 2, 3 }, // 110110 + { 0, 1, 2, 5, 3, 4 }, // 110111 + { 3, 4, 5, 0, 1, 2 }, // 111000 + { 0, 4, 5, 1, 2, 3 }, // 111001 + { 4, 0, 5, 1, 2, 3 }, // 111010 + { 0, 1, 5, 2, 3, 4 }, // 111011 + { 4, 5, 0, 1, 2, 3 }, // 111100 + { 0, 5, 1, 2, 3, 4 }, // 111101 + { 5, 0, 1, 2, 3, 4 }, // 111110 + { 0, 0, 0, 0, 0, 0 } // 111111 - skip + }; + int i, k, iRes; + assert( Phase >= 0 && Phase < 64 ); + if ( Cases[Phase] == 0 ) + { + uTruthRes[0] = uTruth[0]; + uTruthRes[1] = uTruth[1]; + return; + } + if ( Cases[Phase] > 1 ) + { + if ( Phase == 32 ) + { + uTruthRes[0] = 0x00000000; + uTruthRes[1] = 0xFFFFFFFF; + } + else + { + uTruthRes[0] = Cases[Phase]; + uTruthRes[1] = Cases[Phase]; + } + return; + } + uTruthRes[0] = 0; + uTruthRes[1] = 0; + for ( i = 0; i < 64; i++ ) + { + if ( i < 32 ) + { + if ( uTruth[0] & (1 << i) ) + { + for ( iRes = 0, k = 0; k < 6; k++ ) + if ( i & (1 << Perms[Phase][k]) ) + iRes |= (1 << k); + if ( iRes < 32 ) + uTruthRes[0] |= (1 << iRes); + else + uTruthRes[1] |= (1 << (iRes-32)); + } + } + else + { + if ( uTruth[1] & (1 << (i-32)) ) + { + for ( iRes = 0, k = 0; k < 6; k++ ) + if ( i & (1 << Perms[Phase][k]) ) + iRes |= (1 << k); + if ( iRes < 32 ) + uTruthRes[0] |= (1 << iRes); + else + uTruthRes[1] |= (1 << (iRes-32)); + } + } + } +} + +/**Function************************************************************* + + Synopsis [Computes a phase of the 8-var function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR ) +{ + // elementary truth tables + static unsigned uTruths[8][8] = { + { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, + { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, + { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, + { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, + { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, + { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, + { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, + { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } + }; + static char Cases[256] = { + 0, // 00000000 + 0, // 00000001 + 1, // 00000010 + 0, // 00000011 + 2, // 00000100 + -1, // 00000101 + -1, // 00000110 + 0, // 00000111 + 3, // 00001000 + -1, // 00001001 + -1, // 00001010 + -1, // 00001011 + -1, // 00001100 + -1, // 00001101 + -1, // 00001110 + 0, // 00001111 + 4, // 00010000 + -1, // 00010001 + -1, // 00010010 + -1, // 00010011 + -1, // 00010100 + -1, // 00010101 + -1, // 00010110 + -1, // 00010111 + -1, // 00011000 + -1, // 00011001 + -1, // 00011010 + -1, // 00011011 + -1, // 00011100 + -1, // 00011101 + -1, // 00011110 + 0, // 00011111 + 5, // 00100000 + -1, // 00100001 + -1, // 00100010 + -1, // 00100011 + -1, // 00100100 + -1, // 00100101 + -1, // 00100110 + -1, // 00100111 + -1, // 00101000 + -1, // 00101001 + -1, // 00101010 + -1, // 00101011 + -1, // 00101100 + -1, // 00101101 + -1, // 00101110 + -1, // 00101111 + -1, // 00110000 + -1, // 00110001 + -1, // 00110010 + -1, // 00110011 + -1, // 00110100 + -1, // 00110101 + -1, // 00110110 + -1, // 00110111 + -1, // 00111000 + -1, // 00111001 + -1, // 00111010 + -1, // 00111011 + -1, // 00111100 + -1, // 00111101 + -1, // 00111110 + 0, // 00111111 + 6, // 01000000 + -1, // 01000001 + -1, // 01000010 + -1, // 01000011 + -1, // 01000100 + -1, // 01000101 + -1, // 01000110 + -1, // 01000111 + -1, // 01001000 + -1, // 01001001 + -1, // 01001010 + -1, // 01001011 + -1, // 01001100 + -1, // 01001101 + -1, // 01001110 + -1, // 01001111 + -1, // 01010000 + -1, // 01010001 + -1, // 01010010 + -1, // 01010011 + -1, // 01010100 + -1, // 01010101 + -1, // 01010110 + -1, // 01010111 + -1, // 01011000 + -1, // 01011001 + -1, // 01011010 + -1, // 01011011 + -1, // 01011100 + -1, // 01011101 + -1, // 01011110 + -1, // 01011111 + -1, // 01100000 + -1, // 01100001 + -1, // 01100010 + -1, // 01100011 + -1, // 01100100 + -1, // 01100101 + -1, // 01100110 + -1, // 01100111 + -1, // 01101000 + -1, // 01101001 + -1, // 01101010 + -1, // 01101011 + -1, // 01101100 + -1, // 01101101 + -1, // 01101110 + -1, // 01101111 + -1, // 01110000 + -1, // 01110001 + -1, // 01110010 + -1, // 01110011 + -1, // 01110100 + -1, // 01110101 + -1, // 01110110 + -1, // 01110111 + -1, // 01111000 + -1, // 01111001 + -1, // 01111010 + -1, // 01111011 + -1, // 01111100 + -1, // 01111101 + -1, // 01111110 + 0, // 01111111 + 7, // 10000000 + -1, // 10000001 + -1, // 10000010 + -1, // 10000011 + -1, // 10000100 + -1, // 10000101 + -1, // 10000110 + -1, // 10000111 + -1, // 10001000 + -1, // 10001001 + -1, // 10001010 + -1, // 10001011 + -1, // 10001100 + -1, // 10001101 + -1, // 10001110 + -1, // 10001111 + -1, // 10010000 + -1, // 10010001 + -1, // 10010010 + -1, // 10010011 + -1, // 10010100 + -1, // 10010101 + -1, // 10010110 + -1, // 10010111 + -1, // 10011000 + -1, // 10011001 + -1, // 10011010 + -1, // 10011011 + -1, // 10011100 + -1, // 10011101 + -1, // 10011110 + -1, // 10011111 + -1, // 10100000 + -1, // 10100001 + -1, // 10100010 + -1, // 10100011 + -1, // 10100100 + -1, // 10100101 + -1, // 10100110 + -1, // 10100111 + -1, // 10101000 + -1, // 10101001 + -1, // 10101010 + -1, // 10101011 + -1, // 10101100 + -1, // 10101101 + -1, // 10101110 + -1, // 10101111 + -1, // 10110000 + -1, // 10110001 + -1, // 10110010 + -1, // 10110011 + -1, // 10110100 + -1, // 10110101 + -1, // 10110110 + -1, // 10110111 + -1, // 10111000 + -1, // 10111001 + -1, // 10111010 + -1, // 10111011 + -1, // 10111100 + -1, // 10111101 + -1, // 10111110 + -1, // 10111111 + -1, // 11000000 + -1, // 11000001 + -1, // 11000010 + -1, // 11000011 + -1, // 11000100 + -1, // 11000101 + -1, // 11000110 + -1, // 11000111 + -1, // 11001000 + -1, // 11001001 + -1, // 11001010 + -1, // 11001011 + -1, // 11001100 + -1, // 11001101 + -1, // 11001110 + -1, // 11001111 + -1, // 11010000 + -1, // 11010001 + -1, // 11010010 + -1, // 11010011 + -1, // 11010100 + -1, // 11010101 + -1, // 11010110 + -1, // 11010111 + -1, // 11011000 + -1, // 11011001 + -1, // 11011010 + -1, // 11011011 + -1, // 11011100 + -1, // 11011101 + -1, // 11011110 + -1, // 11011111 + -1, // 11100000 + -1, // 11100001 + -1, // 11100010 + -1, // 11100011 + -1, // 11100100 + -1, // 11100101 + -1, // 11100110 + -1, // 11100111 + -1, // 11101000 + -1, // 11101001 + -1, // 11101010 + -1, // 11101011 + -1, // 11101100 + -1, // 11101101 + -1, // 11101110 + -1, // 11101111 + -1, // 11110000 + -1, // 11110001 + -1, // 11110010 + -1, // 11110011 + -1, // 11110100 + -1, // 11110101 + -1, // 11110110 + -1, // 11110111 + -1, // 11111000 + -1, // 11111001 + -1, // 11111010 + -1, // 11111011 + -1, // 11111100 + -1, // 11111101 + -1, // 11111110 + 0 // 11111111 + }; + static char Perms[256][8] = { + { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000000 + { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000001 + { 1, 0, 2, 3, 4, 5, 6, 7 }, // 00000010 + { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000011 + { 1, 2, 0, 3, 4, 5, 6, 7 }, // 00000100 + { 0, 2, 1, 3, 4, 5, 6, 7 }, // 00000101 + { 2, 0, 1, 3, 4, 5, 6, 7 }, // 00000110 + { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000111 + { 1, 2, 3, 0, 4, 5, 6, 7 }, // 00001000 + { 0, 2, 3, 1, 4, 5, 6, 7 }, // 00001001 + { 2, 0, 3, 1, 4, 5, 6, 7 }, // 00001010 + { 0, 1, 3, 2, 4, 5, 6, 7 }, // 00001011 + { 2, 3, 0, 1, 4, 5, 6, 7 }, // 00001100 + { 0, 3, 1, 2, 4, 5, 6, 7 }, // 00001101 + { 3, 0, 1, 2, 4, 5, 6, 7 }, // 00001110 + { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00001111 + { 1, 2, 3, 4, 0, 5, 6, 7 }, // 00010000 + { 0, 2, 3, 4, 1, 5, 6, 7 }, // 00010001 + { 2, 0, 3, 4, 1, 5, 6, 7 }, // 00010010 + { 0, 1, 3, 4, 2, 5, 6, 7 }, // 00010011 + { 2, 3, 0, 4, 1, 5, 6, 7 }, // 00010100 + { 0, 3, 1, 4, 2, 5, 6, 7 }, // 00010101 + { 3, 0, 1, 4, 2, 5, 6, 7 }, // 00010110 + { 0, 1, 2, 4, 3, 5, 6, 7 }, // 00010111 + { 2, 3, 4, 0, 1, 5, 6, 7 }, // 00011000 + { 0, 3, 4, 1, 2, 5, 6, 7 }, // 00011001 + { 3, 0, 4, 1, 2, 5, 6, 7 }, // 00011010 + { 0, 1, 4, 2, 3, 5, 6, 7 }, // 00011011 + { 3, 4, 0, 1, 2, 5, 6, 7 }, // 00011100 + { 0, 4, 1, 2, 3, 5, 6, 7 }, // 00011101 + { 4, 0, 1, 2, 3, 5, 6, 7 }, // 00011110 + { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00011111 + { 1, 2, 3, 4, 5, 0, 6, 7 }, // 00100000 + { 0, 2, 3, 4, 5, 1, 6, 7 }, // 00100001 + { 2, 0, 3, 4, 5, 1, 6, 7 }, // 00100010 + { 0, 1, 3, 4, 5, 2, 6, 7 }, // 00100011 + { 2, 3, 0, 4, 5, 1, 6, 7 }, // 00100100 + { 0, 3, 1, 4, 5, 2, 6, 7 }, // 00100101 + { 3, 0, 1, 4, 5, 2, 6, 7 }, // 00100110 + { 0, 1, 2, 4, 5, 3, 6, 7 }, // 00100111 + { 2, 3, 4, 0, 5, 1, 6, 7 }, // 00101000 + { 0, 3, 4, 1, 5, 2, 6, 7 }, // 00101001 + { 3, 0, 4, 1, 5, 2, 6, 7 }, // 00101010 + { 0, 1, 4, 2, 5, 3, 6, 7 }, // 00101011 + { 3, 4, 0, 1, 5, 2, 6, 7 }, // 00101100 + { 0, 4, 1, 2, 5, 3, 6, 7 }, // 00101101 + { 4, 0, 1, 2, 5, 3, 6, 7 }, // 00101110 + { 0, 1, 2, 3, 5, 4, 6, 7 }, // 00101111 + { 2, 3, 4, 5, 0, 1, 6, 7 }, // 00110000 + { 0, 3, 4, 5, 1, 2, 6, 7 }, // 00110001 + { 3, 0, 4, 5, 1, 2, 6, 7 }, // 00110010 + { 0, 1, 4, 5, 2, 3, 6, 7 }, // 00110011 + { 3, 4, 0, 5, 1, 2, 6, 7 }, // 00110100 + { 0, 4, 1, 5, 2, 3, 6, 7 }, // 00110101 + { 4, 0, 1, 5, 2, 3, 6, 7 }, // 00110110 + { 0, 1, 2, 5, 3, 4, 6, 7 }, // 00110111 + { 3, 4, 5, 0, 1, 2, 6, 7 }, // 00111000 + { 0, 4, 5, 1, 2, 3, 6, 7 }, // 00111001 + { 4, 0, 5, 1, 2, 3, 6, 7 }, // 00111010 + { 0, 1, 5, 2, 3, 4, 6, 7 }, // 00111011 + { 4, 5, 0, 1, 2, 3, 6, 7 }, // 00111100 + { 0, 5, 1, 2, 3, 4, 6, 7 }, // 00111101 + { 5, 0, 1, 2, 3, 4, 6, 7 }, // 00111110 + { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00111111 + { 1, 2, 3, 4, 5, 6, 0, 7 }, // 01000000 + { 0, 2, 3, 4, 5, 6, 1, 7 }, // 01000001 + { 2, 0, 3, 4, 5, 6, 1, 7 }, // 01000010 + { 0, 1, 3, 4, 5, 6, 2, 7 }, // 01000011 + { 2, 3, 0, 4, 5, 6, 1, 7 }, // 01000100 + { 0, 3, 1, 4, 5, 6, 2, 7 }, // 01000101 + { 3, 0, 1, 4, 5, 6, 2, 7 }, // 01000110 + { 0, 1, 2, 4, 5, 6, 3, 7 }, // 01000111 + { 2, 3, 4, 0, 5, 6, 1, 7 }, // 01001000 + { 0, 3, 4, 1, 5, 6, 2, 7 }, // 01001001 + { 3, 0, 4, 1, 5, 6, 2, 7 }, // 01001010 + { 0, 1, 4, 2, 5, 6, 3, 7 }, // 01001011 + { 3, 4, 0, 1, 5, 6, 2, 7 }, // 01001100 + { 0, 4, 1, 2, 5, 6, 3, 7 }, // 01001101 + { 4, 0, 1, 2, 5, 6, 3, 7 }, // 01001110 + { 0, 1, 2, 3, 5, 6, 4, 7 }, // 01001111 + { 2, 3, 4, 5, 0, 6, 1, 7 }, // 01010000 + { 0, 3, 4, 5, 1, 6, 2, 7 }, // 01010001 + { 3, 0, 4, 5, 1, 6, 2, 7 }, // 01010010 + { 0, 1, 4, 5, 2, 6, 3, 7 }, // 01010011 + { 3, 4, 0, 5, 1, 6, 2, 7 }, // 01010100 + { 0, 4, 1, 5, 2, 6, 3, 7 }, // 01010101 + { 4, 0, 1, 5, 2, 6, 3, 7 }, // 01010110 + { 0, 1, 2, 5, 3, 6, 4, 7 }, // 01010111 + { 3, 4, 5, 0, 1, 6, 2, 7 }, // 01011000 + { 0, 4, 5, 1, 2, 6, 3, 7 }, // 01011001 + { 4, 0, 5, 1, 2, 6, 3, 7 }, // 01011010 + { 0, 1, 5, 2, 3, 6, 4, 7 }, // 01011011 + { 4, 5, 0, 1, 2, 6, 3, 7 }, // 01011100 + { 0, 5, 1, 2, 3, 6, 4, 7 }, // 01011101 + { 5, 0, 1, 2, 3, 6, 4, 7 }, // 01011110 + { 0, 1, 2, 3, 4, 6, 5, 7 }, // 01011111 + { 2, 3, 4, 5, 6, 0, 1, 7 }, // 01100000 + { 0, 3, 4, 5, 6, 1, 2, 7 }, // 01100001 + { 3, 0, 4, 5, 6, 1, 2, 7 }, // 01100010 + { 0, 1, 4, 5, 6, 2, 3, 7 }, // 01100011 + { 3, 4, 0, 5, 6, 1, 2, 7 }, // 01100100 + { 0, 4, 1, 5, 6, 2, 3, 7 }, // 01100101 + { 4, 0, 1, 5, 6, 2, 3, 7 }, // 01100110 + { 0, 1, 2, 5, 6, 3, 4, 7 }, // 01100111 + { 3, 4, 5, 0, 6, 1, 2, 7 }, // 01101000 + { 0, 4, 5, 1, 6, 2, 3, 7 }, // 01101001 + { 4, 0, 5, 1, 6, 2, 3, 7 }, // 01101010 + { 0, 1, 5, 2, 6, 3, 4, 7 }, // 01101011 + { 4, 5, 0, 1, 6, 2, 3, 7 }, // 01101100 + { 0, 5, 1, 2, 6, 3, 4, 7 }, // 01101101 + { 5, 0, 1, 2, 6, 3, 4, 7 }, // 01101110 + { 0, 1, 2, 3, 6, 4, 5, 7 }, // 01101111 + { 3, 4, 5, 6, 0, 1, 2, 7 }, // 01110000 + { 0, 4, 5, 6, 1, 2, 3, 7 }, // 01110001 + { 4, 0, 5, 6, 1, 2, 3, 7 }, // 01110010 + { 0, 1, 5, 6, 2, 3, 4, 7 }, // 01110011 + { 4, 5, 0, 6, 1, 2, 3, 7 }, // 01110100 + { 0, 5, 1, 6, 2, 3, 4, 7 }, // 01110101 + { 5, 0, 1, 6, 2, 3, 4, 7 }, // 01110110 + { 0, 1, 2, 6, 3, 4, 5, 7 }, // 01110111 + { 4, 5, 6, 0, 1, 2, 3, 7 }, // 01111000 + { 0, 5, 6, 1, 2, 3, 4, 7 }, // 01111001 + { 5, 0, 6, 1, 2, 3, 4, 7 }, // 01111010 + { 0, 1, 6, 2, 3, 4, 5, 7 }, // 01111011 + { 5, 6, 0, 1, 2, 3, 4, 7 }, // 01111100 + { 0, 6, 1, 2, 3, 4, 5, 7 }, // 01111101 + { 6, 0, 1, 2, 3, 4, 5, 7 }, // 01111110 + { 0, 1, 2, 3, 4, 5, 6, 7 }, // 01111111 + { 1, 2, 3, 4, 5, 6, 7, 0 }, // 10000000 + { 0, 2, 3, 4, 5, 6, 7, 1 }, // 10000001 + { 2, 0, 3, 4, 5, 6, 7, 1 }, // 10000010 + { 0, 1, 3, 4, 5, 6, 7, 2 }, // 10000011 + { 2, 3, 0, 4, 5, 6, 7, 1 }, // 10000100 + { 0, 3, 1, 4, 5, 6, 7, 2 }, // 10000101 + { 3, 0, 1, 4, 5, 6, 7, 2 }, // 10000110 + { 0, 1, 2, 4, 5, 6, 7, 3 }, // 10000111 + { 2, 3, 4, 0, 5, 6, 7, 1 }, // 10001000 + { 0, 3, 4, 1, 5, 6, 7, 2 }, // 10001001 + { 3, 0, 4, 1, 5, 6, 7, 2 }, // 10001010 + { 0, 1, 4, 2, 5, 6, 7, 3 }, // 10001011 + { 3, 4, 0, 1, 5, 6, 7, 2 }, // 10001100 + { 0, 4, 1, 2, 5, 6, 7, 3 }, // 10001101 + { 4, 0, 1, 2, 5, 6, 7, 3 }, // 10001110 + { 0, 1, 2, 3, 5, 6, 7, 4 }, // 10001111 + { 2, 3, 4, 5, 0, 6, 7, 1 }, // 10010000 + { 0, 3, 4, 5, 1, 6, 7, 2 }, // 10010001 + { 3, 0, 4, 5, 1, 6, 7, 2 }, // 10010010 + { 0, 1, 4, 5, 2, 6, 7, 3 }, // 10010011 + { 3, 4, 0, 5, 1, 6, 7, 2 }, // 10010100 + { 0, 4, 1, 5, 2, 6, 7, 3 }, // 10010101 + { 4, 0, 1, 5, 2, 6, 7, 3 }, // 10010110 + { 0, 1, 2, 5, 3, 6, 7, 4 }, // 10010111 + { 3, 4, 5, 0, 1, 6, 7, 2 }, // 10011000 + { 0, 4, 5, 1, 2, 6, 7, 3 }, // 10011001 + { 4, 0, 5, 1, 2, 6, 7, 3 }, // 10011010 + { 0, 1, 5, 2, 3, 6, 7, 4 }, // 10011011 + { 4, 5, 0, 1, 2, 6, 7, 3 }, // 10011100 + { 0, 5, 1, 2, 3, 6, 7, 4 }, // 10011101 + { 5, 0, 1, 2, 3, 6, 7, 4 }, // 10011110 + { 0, 1, 2, 3, 4, 6, 7, 5 }, // 10011111 + { 2, 3, 4, 5, 6, 0, 7, 1 }, // 10100000 + { 0, 3, 4, 5, 6, 1, 7, 2 }, // 10100001 + { 3, 0, 4, 5, 6, 1, 7, 2 }, // 10100010 + { 0, 1, 4, 5, 6, 2, 7, 3 }, // 10100011 + { 3, 4, 0, 5, 6, 1, 7, 2 }, // 10100100 + { 0, 4, 1, 5, 6, 2, 7, 3 }, // 10100101 + { 4, 0, 1, 5, 6, 2, 7, 3 }, // 10100110 + { 0, 1, 2, 5, 6, 3, 7, 4 }, // 10100111 + { 3, 4, 5, 0, 6, 1, 7, 2 }, // 10101000 + { 0, 4, 5, 1, 6, 2, 7, 3 }, // 10101001 + { 4, 0, 5, 1, 6, 2, 7, 3 }, // 10101010 + { 0, 1, 5, 2, 6, 3, 7, 4 }, // 10101011 + { 4, 5, 0, 1, 6, 2, 7, 3 }, // 10101100 + { 0, 5, 1, 2, 6, 3, 7, 4 }, // 10101101 + { 5, 0, 1, 2, 6, 3, 7, 4 }, // 10101110 + { 0, 1, 2, 3, 6, 4, 7, 5 }, // 10101111 + { 3, 4, 5, 6, 0, 1, 7, 2 }, // 10110000 + { 0, 4, 5, 6, 1, 2, 7, 3 }, // 10110001 + { 4, 0, 5, 6, 1, 2, 7, 3 }, // 10110010 + { 0, 1, 5, 6, 2, 3, 7, 4 }, // 10110011 + { 4, 5, 0, 6, 1, 2, 7, 3 }, // 10110100 + { 0, 5, 1, 6, 2, 3, 7, 4 }, // 10110101 + { 5, 0, 1, 6, 2, 3, 7, 4 }, // 10110110 + { 0, 1, 2, 6, 3, 4, 7, 5 }, // 10110111 + { 4, 5, 6, 0, 1, 2, 7, 3 }, // 10111000 + { 0, 5, 6, 1, 2, 3, 7, 4 }, // 10111001 + { 5, 0, 6, 1, 2, 3, 7, 4 }, // 10111010 + { 0, 1, 6, 2, 3, 4, 7, 5 }, // 10111011 + { 5, 6, 0, 1, 2, 3, 7, 4 }, // 10111100 + { 0, 6, 1, 2, 3, 4, 7, 5 }, // 10111101 + { 6, 0, 1, 2, 3, 4, 7, 5 }, // 10111110 + { 0, 1, 2, 3, 4, 5, 7, 6 }, // 10111111 + { 2, 3, 4, 5, 6, 7, 0, 1 }, // 11000000 + { 0, 3, 4, 5, 6, 7, 1, 2 }, // 11000001 + { 3, 0, 4, 5, 6, 7, 1, 2 }, // 11000010 + { 0, 1, 4, 5, 6, 7, 2, 3 }, // 11000011 + { 3, 4, 0, 5, 6, 7, 1, 2 }, // 11000100 + { 0, 4, 1, 5, 6, 7, 2, 3 }, // 11000101 + { 4, 0, 1, 5, 6, 7, 2, 3 }, // 11000110 + { 0, 1, 2, 5, 6, 7, 3, 4 }, // 11000111 + { 3, 4, 5, 0, 6, 7, 1, 2 }, // 11001000 + { 0, 4, 5, 1, 6, 7, 2, 3 }, // 11001001 + { 4, 0, 5, 1, 6, 7, 2, 3 }, // 11001010 + { 0, 1, 5, 2, 6, 7, 3, 4 }, // 11001011 + { 4, 5, 0, 1, 6, 7, 2, 3 }, // 11001100 + { 0, 5, 1, 2, 6, 7, 3, 4 }, // 11001101 + { 5, 0, 1, 2, 6, 7, 3, 4 }, // 11001110 + { 0, 1, 2, 3, 6, 7, 4, 5 }, // 11001111 + { 3, 4, 5, 6, 0, 7, 1, 2 }, // 11010000 + { 0, 4, 5, 6, 1, 7, 2, 3 }, // 11010001 + { 4, 0, 5, 6, 1, 7, 2, 3 }, // 11010010 + { 0, 1, 5, 6, 2, 7, 3, 4 }, // 11010011 + { 4, 5, 0, 6, 1, 7, 2, 3 }, // 11010100 + { 0, 5, 1, 6, 2, 7, 3, 4 }, // 11010101 + { 5, 0, 1, 6, 2, 7, 3, 4 }, // 11010110 + { 0, 1, 2, 6, 3, 7, 4, 5 }, // 11010111 + { 4, 5, 6, 0, 1, 7, 2, 3 }, // 11011000 + { 0, 5, 6, 1, 2, 7, 3, 4 }, // 11011001 + { 5, 0, 6, 1, 2, 7, 3, 4 }, // 11011010 + { 0, 1, 6, 2, 3, 7, 4, 5 }, // 11011011 + { 5, 6, 0, 1, 2, 7, 3, 4 }, // 11011100 + { 0, 6, 1, 2, 3, 7, 4, 5 }, // 11011101 + { 6, 0, 1, 2, 3, 7, 4, 5 }, // 11011110 + { 0, 1, 2, 3, 4, 7, 5, 6 }, // 11011111 + { 3, 4, 5, 6, 7, 0, 1, 2 }, // 11100000 + { 0, 4, 5, 6, 7, 1, 2, 3 }, // 11100001 + { 4, 0, 5, 6, 7, 1, 2, 3 }, // 11100010 + { 0, 1, 5, 6, 7, 2, 3, 4 }, // 11100011 + { 4, 5, 0, 6, 7, 1, 2, 3 }, // 11100100 + { 0, 5, 1, 6, 7, 2, 3, 4 }, // 11100101 + { 5, 0, 1, 6, 7, 2, 3, 4 }, // 11100110 + { 0, 1, 2, 6, 7, 3, 4, 5 }, // 11100111 + { 4, 5, 6, 0, 7, 1, 2, 3 }, // 11101000 + { 0, 5, 6, 1, 7, 2, 3, 4 }, // 11101001 + { 5, 0, 6, 1, 7, 2, 3, 4 }, // 11101010 + { 0, 1, 6, 2, 7, 3, 4, 5 }, // 11101011 + { 5, 6, 0, 1, 7, 2, 3, 4 }, // 11101100 + { 0, 6, 1, 2, 7, 3, 4, 5 }, // 11101101 + { 6, 0, 1, 2, 7, 3, 4, 5 }, // 11101110 + { 0, 1, 2, 3, 7, 4, 5, 6 }, // 11101111 + { 4, 5, 6, 7, 0, 1, 2, 3 }, // 11110000 + { 0, 5, 6, 7, 1, 2, 3, 4 }, // 11110001 + { 5, 0, 6, 7, 1, 2, 3, 4 }, // 11110010 + { 0, 1, 6, 7, 2, 3, 4, 5 }, // 11110011 + { 5, 6, 0, 7, 1, 2, 3, 4 }, // 11110100 + { 0, 6, 1, 7, 2, 3, 4, 5 }, // 11110101 + { 6, 0, 1, 7, 2, 3, 4, 5 }, // 11110110 + { 0, 1, 2, 7, 3, 4, 5, 6 }, // 11110111 + { 5, 6, 7, 0, 1, 2, 3, 4 }, // 11111000 + { 0, 6, 7, 1, 2, 3, 4, 5 }, // 11111001 + { 6, 0, 7, 1, 2, 3, 4, 5 }, // 11111010 + { 0, 1, 7, 2, 3, 4, 5, 6 }, // 11111011 + { 6, 7, 0, 1, 2, 3, 4, 5 }, // 11111100 + { 0, 7, 1, 2, 3, 4, 5, 6 }, // 11111101 + { 7, 0, 1, 2, 3, 4, 5, 6 }, // 11111110 + { 0, 1, 2, 3, 4, 5, 6, 7 } // 11111111 + }; + + assert( uPhase > 0 && uPhase < (unsigned)(1 << nVars) ); + + // the same function + if ( Cases[uPhase] == 0 ) + { + int i; + for ( i = 0; i < nWords; i++ ) + puTruthR[i] = puTruth[i]; + return; + } + + // an elementary variable + if ( Cases[uPhase] > 0 ) + { + int i; + for ( i = 0; i < nWords; i++ ) + puTruthR[i] = uTruths[Cases[uPhase]][i]; + return; + } + + // truth table takes one word + if ( nWords == 1 ) + { + int i, k, nMints, iRes; + char * pPerm = Perms[uPhase]; + puTruthR[0] = 0; + nMints = (1 << nVars); + for ( i = 0; i < nMints; i++ ) + if ( puTruth[0] & (1 << i) ) + { + for ( iRes = 0, k = 0; k < nVars; k++ ) + if ( i & (1 << pPerm[k]) ) + iRes |= (1 << k); + puTruthR[0] |= (1 << iRes); + } + return; + } + else if ( nWords == 2 ) + { + int i, k, iRes; + char * pPerm = Perms[uPhase]; + puTruthR[0] = puTruthR[1] = 0; + for ( i = 0; i < 32; i++ ) + { + if ( puTruth[0] & (1 << i) ) + { + for ( iRes = 0, k = 0; k < 6; k++ ) + if ( i & (1 << pPerm[k]) ) + iRes |= (1 << k); + if ( iRes < 32 ) + puTruthR[0] |= (1 << iRes); + else + puTruthR[1] |= (1 << (iRes-32)); + } + } + for ( ; i < 64; i++ ) + { + if ( puTruth[1] & (1 << (i-32)) ) + { + for ( iRes = 0, k = 0; k < 6; k++ ) + if ( i & (1 << pPerm[k]) ) + iRes |= (1 << k); + if ( iRes < 32 ) + puTruthR[0] |= (1 << iRes); + else + puTruthR[1] |= (1 << (iRes-32)); + } + } + } + // truth table takes more than one word + else + { + int i, k, nMints, iRes; + char * pPerm = Perms[uPhase]; + for ( i = 0; i < nWords; i++ ) + puTruthR[i] = 0; + nMints = (1 << nVars); + for ( i = 0; i < nMints; i++ ) + if ( puTruth[i>>5] & (1 << (i&31)) ) + { + for ( iRes = 0, k = 0; k < 5; k++ ) + if ( i & (1 << pPerm[k]) ) + iRes |= (1 << k); + puTruthR[iRes>>5] |= (1 << (iRes&31)); + } + } +} + +/**Function************************************************************* + + Synopsis [Allocated lookup table for truth table permutation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned short ** Extra_TruthPerm43() +{ + unsigned short ** pTable; + unsigned uTruth; + int i, k; + pTable = (unsigned short **)Extra_ArrayAlloc( 256, 16, 2 ); + for ( i = 0; i < 256; i++ ) + { + uTruth = (i << 8) | i; + for ( k = 0; k < 16; k++ ) + pTable[i][k] = Extra_TruthPerm4One( uTruth, k ); + } + return pTable; +} + +/**Function************************************************************* + + Synopsis [Allocated lookup table for truth table permutation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned ** Extra_TruthPerm53() +{ + unsigned ** pTable; + unsigned uTruth; + int i, k; + pTable = (unsigned **)Extra_ArrayAlloc( 256, 32, 4 ); + for ( i = 0; i < 256; i++ ) + { + uTruth = (i << 24) | (i << 16) | (i << 8) | i; + for ( k = 0; k < 32; k++ ) + pTable[i][k] = Extra_TruthPerm5One( uTruth, k ); + } + return pTable; +} + +/**Function************************************************************* + + Synopsis [Allocated lookup table for truth table permutation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned ** Extra_TruthPerm54() +{ + unsigned ** pTable; + unsigned uTruth; + int i; + pTable = (unsigned **)Extra_ArrayAlloc( 256*256, 4, 4 ); + for ( i = 0; i < 256*256; i++ ) + { + uTruth = (i << 16) | i; + pTable[i][0] = Extra_TruthPerm5One( uTruth, 31-8 ); + pTable[i][1] = Extra_TruthPerm5One( uTruth, 31-4 ); + pTable[i][2] = Extra_TruthPerm5One( uTruth, 31-2 ); + pTable[i][3] = Extra_TruthPerm5One( uTruth, 31-1 ); + } + return pTable; +} + +/**Function************************************************************* + + Synopsis [Allocated lookup table for truth table permutation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned ** Extra_TruthPerm63() +{ + unsigned ** pTable; + unsigned uTruth[2]; + int i, k; + pTable = (unsigned **)Extra_ArrayAlloc( 256, 64, 8 ); + for ( i = 0; i < 256; i++ ) + { + uTruth[0] = (i << 24) | (i << 16) | (i << 8) | i; + uTruth[1] = uTruth[0]; + for ( k = 0; k < 64; k++ ) + Extra_TruthPerm6One( uTruth, k, &pTable[i][k] ); + } + return pTable; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the elementary truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned ** Extra_Truths8() +{ + static unsigned uTruths[8][8] = { + { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, + { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, + { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, + { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, + { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, + { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, + { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, + { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } + }; + static unsigned * puResult[8] = { + uTruths[0], uTruths[1], uTruths[2], uTruths[3], uTruths[4], uTruths[5], uTruths[6], uTruths[7] + }; + return (unsigned **)puResult; +} + +/**Function************************************************************* + + Synopsis [Bubble-sorts components by scores in increasing order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing ) +{ + int i, Temp, fChanges; + assert( nSize < 1000 ); + for ( i = 0; i < nSize; i++ ) + Order[i] = i; + if ( fIncreasing ) + { + do { + fChanges = 0; + for ( i = 0; i < nSize - 1; i++ ) + { + if ( Costs[Order[i]] <= Costs[Order[i+1]] ) + continue; + Temp = Order[i]; + Order[i] = Order[i+1]; + Order[i+1] = Temp; + fChanges = 1; + } + } while ( fChanges ); + } + else + { + do { + fChanges = 0; + for ( i = 0; i < nSize - 1; i++ ) + { + if ( Costs[Order[i]] >= Costs[Order[i+1]] ) + continue; + Temp = Order[i]; + Order[i] = Order[i+1]; + Order[i+1] = Temp; + fChanges = 1; + } + } while ( fChanges ); + } +} + +/**Function************************************************************* + + Synopsis [Returns the smallest prime larger than the number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned int Cudd_PrimeCopy( unsigned int p) +{ + int i,pn; + + p--; + do { + p++; + if (p&1) { + pn = 1; + i = 3; + while ((unsigned) (i * i) <= p) { + if (p % i == 0) { + pn = 0; + break; + } + i += 2; + } + } else { + pn = 0; + } + } while (!pn); + return(p); + +} /* end of Cudd_Prime */ + +/*---------------------------------------------------------------------------*/ +/* Definition of internal functions */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Definition of static Functions */ +/*---------------------------------------------------------------------------*/ + + +/**Function************************************************************* + + Synopsis [Computes the permutation table for 8 variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthExpandGeneratePermTable() +{ + int i, k, nOnes, Last1, First0; + int iOne, iZero; + + printf( "\nstatic char Cases[256] = {\n" ); + for ( i = 0; i < 256; i++ ) + { + nOnes = 0; + Last1 = First0 = -1; + for ( k = 0; k < 8; k++ ) + { + if ( i & (1 << k) ) + { + nOnes++; + Last1 = k; + } + else if ( First0 == -1 ) + First0 = k; + } + if ( Last1 + 1 == First0 || i == 255 ) + printf( " %d%s", 0, (i==255? " ":",") ); + else if ( nOnes == 1 ) + printf( " %d,", Last1 ); + else + printf( " -%d,", 1 ); + printf( " // " ); + Extra_PrintBinary( stdout, (unsigned*)&i, 8 ); + printf( "\n" ); + } + printf( "};\n" ); + + printf( "\nstatic char Perms[256][8] = {\n" ); + for ( i = 0; i < 256; i++ ) + { + printf( " {" ); + nOnes = 0; + for ( k = 0; k < 8; k++ ) + if ( i & (1 << k) ) + nOnes++; + iOne = 0; + iZero = nOnes; + for ( k = 0; k < 8; k++ ) + if ( i & (1 << k) ) + printf( "%s %d", (k==0? "":","), iOne++ ); + else + printf( "%s %d", (k==0? "":","), iZero++ ); + assert( iOne + iZero == 8 ); + printf( " }%s // ", (i==255? " ":",") ); + Extra_PrintBinary( stdout, (unsigned*)&i, 8 ); + printf( "\n" ); + } + printf( "};\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/extra/extraUtilProgress.c b/abc70930/src/misc/extra/extraUtilProgress.c new file mode 100644 index 00000000..6b6d5132 --- /dev/null +++ b/abc70930/src/misc/extra/extraUtilProgress.c @@ -0,0 +1,176 @@ +/**CFile**************************************************************** + + FileName [extraUtilProgress.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Progress bar.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraUtilProgress.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct ProgressBarStruct +{ + int nItemsNext; // the number of items for the next update of the progress bar + int nItemsTotal; // the total number of items + int posTotal; // the total number of positions + int posCur; // the current position + FILE * pFile; // the output stream +}; + +static void Extra_ProgressBarShow( ProgressBar * p, char * pString ); +static void Extra_ProgressBarClean( ProgressBar * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the progress bar.] + + Description [The first parameter is the output stream (pFile), where + the progress is printed. The current printing position should be the + first one on the given line. The second parameters is the total + number of items that correspond to 100% position of the progress bar.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal ) +{ + ProgressBar * p; + extern int Abc_FrameShowProgress( void * p ); + extern void * Abc_FrameGetGlobalFrame(); + + if ( !Abc_FrameShowProgress(Abc_FrameGetGlobalFrame()) ) return NULL; + p = ALLOC( ProgressBar, 1 ); + memset( p, 0, sizeof(ProgressBar) ); + p->pFile = pFile; + p->nItemsTotal = nItemsTotal; + p->posTotal = 78; + p->posCur = 1; + p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); + Extra_ProgressBarShow( p, NULL ); + return p; +} + +/**Function************************************************************* + + Synopsis [Updates the progress bar.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString ) +{ + if ( p == NULL ) return; + if ( nItemsCur < p->nItemsNext ) + return; + if ( nItemsCur >= p->nItemsTotal ) + { + p->posCur = 78; + p->nItemsNext = 0x7FFFFFFF; + } + else + { + p->posCur += 7; + p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); + } + Extra_ProgressBarShow( p, pString ); +} + + +/**Function************************************************************* + + Synopsis [Stops the progress bar.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ProgressBarStop( ProgressBar * p ) +{ + if ( p == NULL ) return; + Extra_ProgressBarClean( p ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Prints the progress bar of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ProgressBarShow( ProgressBar * p, char * pString ) +{ + int i; + if ( p == NULL ) return; + if ( pString ) + fprintf( p->pFile, "%s ", pString ); + for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ ) + fprintf( p->pFile, "-" ); + if ( i == p->posCur ) + fprintf( p->pFile, ">" ); + for ( i++ ; i <= p->posTotal; i++ ) + fprintf( p->pFile, " " ); + fprintf( p->pFile, "\r" ); + fflush( stdout ); +} + +/**Function************************************************************* + + Synopsis [Cleans the progress bar before quitting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_ProgressBarClean( ProgressBar * p ) +{ + int i; + if ( p == NULL ) return; + for ( i = 0; i <= p->posTotal; i++ ) + fprintf( p->pFile, " " ); + fprintf( p->pFile, "\r" ); + fflush( stdout ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/extra/extraUtilReader.c b/abc70930/src/misc/extra/extraUtilReader.c new file mode 100644 index 00000000..c165b989 --- /dev/null +++ b/abc70930/src/misc/extra/extraUtilReader.c @@ -0,0 +1,383 @@ +/**CFile**************************************************************** + + FileName [extraUtilReader.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [File reading utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraUtilReader.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "extra.h" +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define EXTRA_BUFFER_SIZE 4*1048576 // 1M - size of the data chunk stored in memory +#define EXTRA_OFFSET_SIZE 4096 // 4K - load new data when less than this is left + +#define EXTRA_MINIMUM(a,b) (((a) < (b))? (a) : (b)) + +struct Extra_FileReader_t_ +{ + // the input file + char * pFileName; // the input file name + FILE * pFile; // the input file pointer + int nFileSize; // the total number of bytes in the file + int nFileRead; // the number of bytes currently read from file + // info about processing different types of input chars + char pCharMap[256]; // the character map + // temporary storage for data + char * pBuffer; // the buffer + int nBufferSize; // the size of the buffer + char * pBufferCur; // the current reading position + char * pBufferEnd; // the first position not used by currently loaded data + char * pBufferStop; // the position where loading new data will be done + // tokens given to the user + Vec_Ptr_t * vTokens; // the vector of tokens returned to the user + Vec_Int_t * vLines; // the vector of line numbers for each token + int nLineCounter; // the counter of lines processed + // status of the parser + int fStop; // this flag goes high when the end of file is reached +}; + +// character types +typedef enum { + EXTRA_CHAR_COMMENT, // a character that begins the comment + EXTRA_CHAR_NORMAL, // a regular character + EXTRA_CHAR_STOP, // a character that delimits a series of tokens + EXTRA_CHAR_CLEAN // a character that should be cleaned +} Extra_CharType_t; + +// the static functions +static void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ); +static void Extra_FileReaderReload( Extra_FileReader_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the file reader.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName, + char * pCharsComment, char * pCharsStop, char * pCharsClean ) +{ + Extra_FileReader_t * p; + FILE * pFile; + char * pChar; + int nCharsToRead; + // check if the file can be opened + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Extra_FileReaderAlloc(): Cannot open input file \"%s\".\n", pFileName ); + return NULL; + } + // start the file reader + p = ALLOC( Extra_FileReader_t, 1 ); + memset( p, 0, sizeof(Extra_FileReader_t) ); + p->pFileName = pFileName; + p->pFile = pFile; + // set the character map + memset( p->pCharMap, EXTRA_CHAR_NORMAL, 256 ); + for ( pChar = pCharsComment; *pChar; pChar++ ) + p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_COMMENT; + for ( pChar = pCharsStop; *pChar; pChar++ ) + p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_STOP; + for ( pChar = pCharsClean; *pChar; pChar++ ) + p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_CLEAN; + // get the file size, in bytes + fseek( pFile, 0, SEEK_END ); + p->nFileSize = ftell( pFile ); + rewind( pFile ); + // allocate the buffer + p->pBuffer = ALLOC( char, EXTRA_BUFFER_SIZE+1 ); + p->nBufferSize = EXTRA_BUFFER_SIZE; + p->pBufferCur = p->pBuffer; + // determine how many chars to read + nCharsToRead = EXTRA_MINIMUM(p->nFileSize, EXTRA_BUFFER_SIZE); + // load the first part into the buffer + fread( p->pBuffer, nCharsToRead, 1, p->pFile ); + p->nFileRead = nCharsToRead; + // set the ponters to the end and the stopping point + p->pBufferEnd = p->pBuffer + nCharsToRead; + p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE; + // start the arrays + p->vTokens = Vec_PtrAlloc( 100 ); + p->vLines = Vec_IntAlloc( 100 ); + p->nLineCounter = 1; // 1-based line counting + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the file reader.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_FileReaderFree( Extra_FileReader_t * p ) +{ + if ( p->pFile ) + fclose( p->pFile ); + FREE( p->pBuffer ); + Vec_PtrFree( p->vTokens ); + Vec_IntFree( p->vLines ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the file size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_FileReaderGetFileName( Extra_FileReader_t * p ) +{ + return p->pFileName; +} + +/**Function************************************************************* + + Synopsis [Returns the file size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_FileReaderGetFileSize( Extra_FileReader_t * p ) +{ + return p->nFileSize; +} + +/**Function************************************************************* + + Synopsis [Returns the current reading position.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p ) +{ + return p->nFileRead - (p->pBufferEnd - p->pBufferCur); +} + +/**Function************************************************************* + + Synopsis [Returns the line number for the given token.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken ) +{ + assert( iToken >= 0 && iToken < p->vTokens->nSize ); + return p->vLines->pArray[iToken]; +} + + +/**Function************************************************************* + + Synopsis [Returns the next set of tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Extra_FileReaderGetTokens( Extra_FileReader_t * p ) +{ + Vec_Ptr_t * vTokens; + while ( vTokens = Extra_FileReaderGetTokens_int( p ) ) + if ( vTokens->nSize > 0 ) + break; + return vTokens; +} + +/**Function************************************************************* + + Synopsis [Returns the next set of tokens.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ) +{ + char * pChar; + int fTokenStarted, MapValue; + if ( p->fStop ) + return NULL; + // reset the token info + p->vTokens->nSize = 0; + p->vLines->nSize = 0; + fTokenStarted = 0; + // check if the new data should to be loaded + if ( p->pBufferCur > p->pBufferStop ) + Extra_FileReaderReload( p ); + +// printf( "%d\n", p->pBufferEnd - p->pBufferCur ); + + // process the string starting from the current position + for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) + { + // count the lines + if ( *pChar == '\n' ) + p->nLineCounter++; + // switch depending on the character + MapValue = p->pCharMap[*pChar]; + +// printf( "Char value = %d. Map value = %d.\n", *pChar, MapValue ); + + + switch ( MapValue ) + { + case EXTRA_CHAR_COMMENT: + if ( *pChar != '/' || *(pChar+1) == '/' ) + { // dealing with the need to have // as a comment + // if the token was being written, stop it + if ( fTokenStarted ) + fTokenStarted = 0; + // eraze the comment till the end of line + while ( *pChar != '\n' ) + { + *pChar++ = 0; + if ( pChar == p->pBufferEnd ) + { // this failure is due to the fact the comment continued + // through EXTRA_OFFSET_SIZE chars till the end of the buffer + printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName ); + return NULL; + } + } + pChar--; + break; + } + // otherwise it is a normal character + case EXTRA_CHAR_NORMAL: + if ( !fTokenStarted ) + { + Vec_PtrPush( p->vTokens, pChar ); + Vec_IntPush( p->vLines, p->nLineCounter ); + fTokenStarted = 1; + } + break; + case EXTRA_CHAR_STOP: + if ( fTokenStarted ) + fTokenStarted = 0; + *pChar = 0; + // prepare before leaving + p->pBufferCur = pChar + 1; + return p->vTokens; + case EXTRA_CHAR_CLEAN: + if ( fTokenStarted ) + fTokenStarted = 0; + *pChar = 0; + break; + default: + assert( 0 ); + } + } + // the file is finished or the last part continued + // through EXTRA_OFFSET_SIZE chars till the end of the buffer + if ( p->pBufferStop == p->pBufferEnd ) // end of file + { + *pChar = 0; + p->fStop = 1; + return p->vTokens; + } + printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName ); +/* + { + int i; + for ( i = 0; i < p->vTokens->nSize; i++ ) + printf( "%s ", p->vTokens->pArray[i] ); + printf( "\n" ); + } +*/ + return NULL; +} + +/**Function************************************************************* + + Synopsis [Loads new data into the file reader.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_FileReaderReload( Extra_FileReader_t * p ) +{ + int nCharsUsed, nCharsToRead; + assert( !p->fStop ); + assert( p->pBufferCur > p->pBufferStop ); + assert( p->pBufferCur < p->pBufferEnd ); + // figure out how many chars are still not processed + nCharsUsed = p->pBufferEnd - p->pBufferCur; + // move the remaining data to the beginning of the buffer + memmove( p->pBuffer, p->pBufferCur, nCharsUsed ); + p->pBufferCur = p->pBuffer; + // determine how many chars we will read + nCharsToRead = EXTRA_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead ); + // read the chars + fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile ); + p->nFileRead += nCharsToRead; + // set the ponters to the end and the stopping point + p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead; + p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/extra/extraUtilTruth.c b/abc70930/src/misc/extra/extraUtilTruth.c new file mode 100644 index 00000000..3b0b16eb --- /dev/null +++ b/abc70930/src/misc/extra/extraUtilTruth.c @@ -0,0 +1,1148 @@ +/**CFile**************************************************************** + + FileName [extraUtilMisc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Various procedures for truth table manipulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "extra.h" + +/*---------------------------------------------------------------------------*/ +/* Constant declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Stucture declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Type declarations */ +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* Variable declarations */ +/*---------------------------------------------------------------------------*/ + +static unsigned s_VarMasks[5][2] = { + { 0x33333333, 0xAAAAAAAA }, + { 0x55555555, 0xCCCCCCCC }, + { 0x0F0F0F0F, 0xF0F0F0F0 }, + { 0x00FF00FF, 0xFF00FF00 }, + { 0x0000FFFF, 0xFFFF0000 } +}; + +/*---------------------------------------------------------------------------*/ +/* Macro declarations */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticStart*************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Static function prototypes */ +/*---------------------------------------------------------------------------*/ + +/**AutomaticEnd***************************************************************/ + +/*---------------------------------------------------------------------------*/ +/* Definition of exported functions */ +/*---------------------------------------------------------------------------*/ + +/**Function************************************************************* + + Synopsis [Derive elementary truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned ** Extra_TruthElementary( int nVars ) +{ + unsigned ** pRes; + int i, k, nWords; + nWords = Extra_TruthWordNum(nVars); + pRes = (unsigned **)Extra_ArrayAlloc( nVars, nWords, 4 ); + for ( i = 0; i < nVars; i++ ) + { + if ( i < 5 ) + { + for ( k = 0; k < nWords; k++ ) + pRes[i][k] = s_VarMasks[i][1]; + } + else + { + for ( k = 0; k < nWords; k++ ) + if ( k & (1 << (i-5)) ) + pRes[i][k] = ~(unsigned)0; + else + pRes[i][k] = 0; + } + } + return pRes; +} + +/**Function************************************************************* + + Synopsis [Swaps two adjacent variables in the truth table.] + + Description [Swaps var number Start and var number Start+1 (0-based numbers). + The input truth table is pIn. The output truth table is pOut.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) +{ + static unsigned PMasks[4][3] = { + { 0x99999999, 0x22222222, 0x44444444 }, + { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 }, + { 0xF00FF00F, 0x00F000F0, 0x0F000F00 }, + { 0xFF0000FF, 0x0000FF00, 0x00FF0000 } + }; + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step, Shift; + + assert( iVar < nVars - 1 ); + if ( iVar < 4 ) + { + Shift = (1 << iVar); + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift); + } + else if ( iVar > 4 ) + { + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 4*Step ) + { + for ( i = 0; i < Step; i++ ) + pOut[i] = pIn[i]; + for ( i = 0; i < Step; i++ ) + pOut[Step+i] = pIn[2*Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[2*Step+i] = pIn[Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[3*Step+i] = pIn[3*Step+i]; + pIn += 4*Step; + pOut += 4*Step; + } + } + else // if ( iVar == 4 ) + { + for ( i = 0; i < nWords; i += 2 ) + { + pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); + pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); + } + } +} + +/**Function************************************************************* + + Synopsis [Swaps two adjacent variables in the truth table.] + + Description [Swaps var number Start and var number Start+1 (0-based numbers). + The input truth table is pIn. The output truth table is pOut.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int Start ) +{ + int nWords = (nVars <= 5)? 1 : (1 << (nVars-5)); + int i, k, Step; + + assert( Start < nVars - 1 ); + switch ( Start ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0x99999999) | ((pIn[i] & 0x22222222) << 1) | ((pIn[i] & 0x44444444) >> 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xC3C3C3C3) | ((pIn[i] & 0x0C0C0C0C) << 2) | ((pIn[i] & 0x30303030) >> 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xF00FF00F) | ((pIn[i] & 0x00F000F0) << 4) | ((pIn[i] & 0x0F000F00) >> 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pIn[i] & 0xFF0000FF) | ((pIn[i] & 0x0000FF00) << 8) | ((pIn[i] & 0x00FF0000) >> 8); + return; + case 4: + for ( i = 0; i < nWords; i += 2 ) + { + pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); + pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); + } + return; + default: + Step = (1 << (Start - 5)); + for ( k = 0; k < nWords; k += 4*Step ) + { + for ( i = 0; i < Step; i++ ) + pOut[i] = pIn[i]; + for ( i = 0; i < Step; i++ ) + pOut[Step+i] = pIn[2*Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[2*Step+i] = pIn[Step+i]; + for ( i = 0; i < Step; i++ ) + pOut[3*Step+i] = pIn[3*Step+i]; + pIn += 4*Step; + pOut += 4*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Expands the truth table according to the phase.] + + Description [The input and output truth tables are in pIn/pOut. The current number + of variables is nVars. The total number of variables in nVarsAll. The last argument + (Phase) contains shows where the variables should go.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ) +{ + unsigned * pTemp; + int i, k, Var = nVars - 1, Counter = 0; + for ( i = nVarsAll - 1; i >= 0; i-- ) + if ( Phase & (1 << i) ) + { + for ( k = Var; k < i; k++ ) + { + Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + Counter++; + } + Var--; + } + assert( Var == -1 ); + // swap if it was moved an even number of times + if ( !(Counter & 1) ) + Extra_TruthCopy( pOut, pIn, nVarsAll ); +} + +/**Function************************************************************* + + Synopsis [Shrinks the truth table according to the phase.] + + Description [The input and output truth tables are in pIn/pOut. The current number + of variables is nVars. The total number of variables in nVarsAll. The last argument + (Phase) contains shows what variables should remain.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ) +{ + unsigned * pTemp; + int i, k, Var = 0, Counter = 0; + for ( i = 0; i < nVarsAll; i++ ) + if ( Phase & (1 << i) ) + { + for ( k = i-1; k >= Var; k-- ) + { + Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + Counter++; + } + Var++; + } + assert( Var == nVars ); + // swap if it was moved an even number of times + if ( !(Counter & 1) ) + Extra_TruthCopy( pOut, pIn, nVarsAll ); +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if TT depends on the given variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) ) + return 1; + return 0; + case 1: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) ) + return 1; + return 0; + case 2: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) ) + return 1; + return 0; + case 3: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) ) + return 1; + return 0; + case 4: + for ( i = 0; i < nWords; i++ ) + if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) ) + return 1; + return 0; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + if ( pTruth[i] != pTruth[Step+i] ) + return 1; + pTruth += 2*Step; + } + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Returns the number of support vars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthSupportSize( unsigned * pTruth, int nVars ) +{ + int i, Counter = 0; + for ( i = 0; i < nVars; i++ ) + Counter += Extra_TruthVarInSupport( pTruth, nVars, i ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns support of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthSupport( unsigned * pTruth, int nVars ) +{ + int i, Support = 0; + for ( i = 0; i < nVars; i++ ) + if ( Extra_TruthVarInSupport( pTruth, nVars, i ) ) + Support |= (1 << i); + return Support; +} + + + +/**Function************************************************************* + + Synopsis [Computes positive cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xAAAAAAAA) | ((pTruth[i] & 0xAAAAAAAA) >> 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xCCCCCCCC) | ((pTruth[i] & 0xCCCCCCCC) >> 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xF0F0F0F0) | ((pTruth[i] & 0xF0F0F0F0) >> 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xFF00FF00) | ((pTruth[i] & 0xFF00FF00) >> 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0xFFFF0000) | ((pTruth[i] & 0xFFFF0000) >> 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + pTruth[i] = pTruth[Step+i]; + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Computes negative cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x55555555) | ((pTruth[i] & 0x55555555) << 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x33333333) | ((pTruth[i] & 0x33333333) << 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x0F0F0F0F) | ((pTruth[i] & 0x0F0F0F0F) << 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x00FF00FF) | ((pTruth[i] & 0x00FF00FF) << 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = (pTruth[i] & 0x0000FFFF) | ((pTruth[i] & 0x0000FFFF) << 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + pTruth[Step+i] = pTruth[i]; + pTruth += 2*Step; + } + return; + } +} + + +/**Function************************************************************* + + Synopsis [Existentially quantifies the variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthExist( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] |= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] |= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] |= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] |= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] |= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + pTruth[i] |= pTruth[Step+i]; + pTruth[Step+i] = pTruth[i]; + } + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Existentially quantifies the variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] &= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] &= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] &= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] &= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] &= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + pTruth[i] &= pTruth[Step+i]; + pTruth[Step+i] = pTruth[i]; + } + pTruth += 2*Step; + } + return; + } +} + + +/**Function************************************************************* + + Synopsis [Computes negative cofactor of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + pOut[i] = pCof0[i]; + pOut[Step+i] = pCof1[Step+i]; + } + pOut += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Checks symmetry of two variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) +{ + static unsigned uTemp0[16], uTemp1[16]; + assert( nVars <= 9 ); + // compute Cof01 + Extra_TruthCopy( uTemp0, pTruth, nVars ); + Extra_TruthCofactor0( uTemp0, nVars, iVar0 ); + Extra_TruthCofactor1( uTemp0, nVars, iVar1 ); + // compute Cof10 + Extra_TruthCopy( uTemp1, pTruth, nVars ); + Extra_TruthCofactor1( uTemp1, nVars, iVar0 ); + Extra_TruthCofactor0( uTemp1, nVars, iVar1 ); + // compare + return Extra_TruthIsEqual( uTemp0, uTemp1, nVars ); +} + +/**Function************************************************************* + + Synopsis [Checks antisymmetry of two variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) +{ + static unsigned uTemp0[16], uTemp1[16]; + assert( nVars <= 9 ); + // compute Cof00 + Extra_TruthCopy( uTemp0, pTruth, nVars ); + Extra_TruthCofactor0( uTemp0, nVars, iVar0 ); + Extra_TruthCofactor0( uTemp0, nVars, iVar1 ); + // compute Cof11 + Extra_TruthCopy( uTemp1, pTruth, nVars ); + Extra_TruthCofactor1( uTemp1, nVars, iVar0 ); + Extra_TruthCofactor1( uTemp1, nVars, iVar1 ); + // compare + return Extra_TruthIsEqual( uTemp0, uTemp1, nVars ); +} + +/**Function************************************************************* + + Synopsis [Changes phase of the function w.r.t. one variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Step; + unsigned Temp; + + assert( iVar < nVars ); + switch ( iVar ) + { + case 0: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x55555555) << 1) | ((pTruth[i] & 0xAAAAAAAA) >> 1); + return; + case 1: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x33333333) << 2) | ((pTruth[i] & 0xCCCCCCCC) >> 2); + return; + case 2: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x0F0F0F0F) << 4) | ((pTruth[i] & 0xF0F0F0F0) >> 4); + return; + case 3: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x00FF00FF) << 8) | ((pTruth[i] & 0xFF00FF00) >> 8); + return; + case 4: + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ((pTruth[i] & 0x0000FFFF) << 16) | ((pTruth[i] & 0xFFFF0000) >> 16); + return; + default: + Step = (1 << (iVar - 5)); + for ( k = 0; k < nWords; k += 2*Step ) + { + for ( i = 0; i < Step; i++ ) + { + Temp = pTruth[i]; + pTruth[i] = pTruth[Step+i]; + pTruth[Step+i] = Temp; + } + pTruth += 2*Step; + } + return; + } +} + +/**Function************************************************************* + + Synopsis [Computes minimum overlap in supports of cofactors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ) +{ + static unsigned uCofactor[16]; + int i, ValueCur, ValueMin, VarMin; + unsigned uSupp0, uSupp1; + int nVars0, nVars1; + assert( nVars <= 9 ); + ValueMin = 32; + VarMin = -1; + for ( i = 0; i < nVars; i++ ) + { + // get negative cofactor + Extra_TruthCopy( uCofactor, pTruth, nVars ); + Extra_TruthCofactor0( uCofactor, nVars, i ); + uSupp0 = Extra_TruthSupport( uCofactor, nVars ); + nVars0 = Extra_WordCountOnes( uSupp0 ); +//Extra_PrintBinary( stdout, &uSupp0, 8 ); printf( "\n" ); + // get positive cofactor + Extra_TruthCopy( uCofactor, pTruth, nVars ); + Extra_TruthCofactor1( uCofactor, nVars, i ); + uSupp1 = Extra_TruthSupport( uCofactor, nVars ); + nVars1 = Extra_WordCountOnes( uSupp1 ); +//Extra_PrintBinary( stdout, &uSupp1, 8 ); printf( "\n" ); + // get the number of common vars + ValueCur = Extra_WordCountOnes( uSupp0 & uSupp1 ); + if ( ValueMin > ValueCur && nVars0 <= 5 && nVars1 <= 5 ) + { + ValueMin = ValueCur; + VarMin = i; + } + if ( ValueMin == 0 ) + break; + } + if ( pVarMin ) + *pVarMin = VarMin; + return ValueMin; +} + + +/**Function************************************************************* + + Synopsis [Counts the number of 1's in each cofactor.] + + Description [The resulting numbers are stored in the array of shorts, + whose length is 2*nVars. The number of 1's is counted in a different + space than the original function. For example, if the function depends + on k variables, the cofactors are assumed to depend on k-1 variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i, k, Counter; + memset( pStore, 0, sizeof(short) * 2 * nVars ); + if ( nVars <= 5 ) + { + if ( nVars > 0 ) + { + pStore[2*0+0] = Extra_WordCountOnes( pTruth[0] & 0x55555555 ); + pStore[2*0+1] = Extra_WordCountOnes( pTruth[0] & 0xAAAAAAAA ); + } + if ( nVars > 1 ) + { + pStore[2*1+0] = Extra_WordCountOnes( pTruth[0] & 0x33333333 ); + pStore[2*1+1] = Extra_WordCountOnes( pTruth[0] & 0xCCCCCCCC ); + } + if ( nVars > 2 ) + { + pStore[2*2+0] = Extra_WordCountOnes( pTruth[0] & 0x0F0F0F0F ); + pStore[2*2+1] = Extra_WordCountOnes( pTruth[0] & 0xF0F0F0F0 ); + } + if ( nVars > 3 ) + { + pStore[2*3+0] = Extra_WordCountOnes( pTruth[0] & 0x00FF00FF ); + pStore[2*3+1] = Extra_WordCountOnes( pTruth[0] & 0xFF00FF00 ); + } + if ( nVars > 4 ) + { + pStore[2*4+0] = Extra_WordCountOnes( pTruth[0] & 0x0000FFFF ); + pStore[2*4+1] = Extra_WordCountOnes( pTruth[0] & 0xFFFF0000 ); + } + return; + } + // nVars >= 6 + // count 1's for all other variables + for ( k = 0; k < nWords; k++ ) + { + Counter = Extra_WordCountOnes( pTruth[k] ); + for ( i = 5; i < nVars; i++ ) + if ( k & (1 << (i-5)) ) + pStore[2*i+1] += Counter; + else + pStore[2*i+0] += Counter; + } + // count 1's for the first five variables + for ( k = 0; k < nWords/2; k++ ) + { + pStore[2*0+0] += Extra_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) ); + pStore[2*0+1] += Extra_WordCountOnes( (pTruth[0] & 0xAAAAAAAA) | ((pTruth[1] & 0xAAAAAAAA) >> 1) ); + pStore[2*1+0] += Extra_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) ); + pStore[2*1+1] += Extra_WordCountOnes( (pTruth[0] & 0xCCCCCCCC) | ((pTruth[1] & 0xCCCCCCCC) >> 2) ); + pStore[2*2+0] += Extra_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) ); + pStore[2*2+1] += Extra_WordCountOnes( (pTruth[0] & 0xF0F0F0F0) | ((pTruth[1] & 0xF0F0F0F0) >> 4) ); + pStore[2*3+0] += Extra_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) ); + pStore[2*3+1] += Extra_WordCountOnes( (pTruth[0] & 0xFF00FF00) | ((pTruth[1] & 0xFF00FF00) >> 8) ); + pStore[2*4+0] += Extra_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) ); + pStore[2*4+1] += Extra_WordCountOnes( (pTruth[0] & 0xFFFF0000) | ((pTruth[1] & 0xFFFF0000) >> 16) ); + pTruth += 2; + } +} + + +/**Function************************************************************* + + Synopsis [Canonicize the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Extra_TruthHash( unsigned * pIn, int nWords ) +{ + // The 1,024 smallest prime numbers used to compute the hash value + // http://www.math.utah.edu/~alfeld/math/primelist.html + static int HashPrimes[1024] = { 2, 3, 5, + 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, + 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, + 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, + 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, + 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, + 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, + 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, + 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, + 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, + 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, + 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, + 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, + 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, + 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, + 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, + 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, + 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, + 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, + 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, + 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, + 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, + 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, + 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, + 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, + 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, + 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, + 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, + 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, + 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, + 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, + 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, + 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, + 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, + 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, + 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, + 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, + 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, + 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, + 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, + 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, + 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, + 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, + 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, + 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, + 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, + 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, + 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, + 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, + 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, + 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, + 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, + 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, + 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, + 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, + 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, + 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, + 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, + 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, + 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, + 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, + 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, + 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, + 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, + 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, + 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, + 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, + 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, + 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, + 8147, 8161 }; + int i; + unsigned uHashKey; + assert( nWords <= 1024 ); + uHashKey = 0; + for ( i = 0; i < nWords; i++ ) + uHashKey ^= HashPrimes[i] * pIn[i]; + return uHashKey; +} + + +/**Function************************************************************* + + Synopsis [Canonicize the truth table.] + + Description [Returns the phase. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ) +{ + unsigned * pIn = pInOut, * pOut = pAux, * pTemp; + int nWords = Extra_TruthWordNum( nVars ); + int i, Temp, fChange, Counter, nOnes;//, k, j, w, Limit; + unsigned uCanonPhase; + + // canonicize output + uCanonPhase = 0; + nOnes = Extra_TruthCountOnes(pIn, nVars); + if ( (nOnes > nWords * 16) || ((nOnes == nWords * 16) && (pIn[0] & 1)) ) + { + uCanonPhase |= (1 << nVars); + Extra_TruthNot( pIn, pIn, nVars ); + } + + // collect the minterm counts + Extra_TruthCountOnesInCofs( pIn, nVars, pStore ); + + // canonicize phase + for ( i = 0; i < nVars; i++ ) + { + if ( pStore[2*i+0] <= pStore[2*i+1] ) + continue; + uCanonPhase |= (1 << i); + Temp = pStore[2*i+0]; + pStore[2*i+0] = pStore[2*i+1]; + pStore[2*i+1] = Temp; + Extra_TruthChangePhase( pIn, nVars, i ); + } + +// Extra_PrintHexadecimal( stdout, pIn, nVars ); +// printf( "\n" ); + + // permute + Counter = 0; + do { + fChange = 0; + for ( i = 0; i < nVars-1; i++ ) + { + if ( pStore[2*i] <= pStore[2*(i+1)] ) + continue; + Counter++; + fChange = 1; + + Temp = pCanonPerm[i]; + pCanonPerm[i] = pCanonPerm[i+1]; + pCanonPerm[i+1] = Temp; + + Temp = pStore[2*i]; + pStore[2*i] = pStore[2*(i+1)]; + pStore[2*(i+1)] = Temp; + + Temp = pStore[2*i+1]; + pStore[2*i+1] = pStore[2*(i+1)+1]; + pStore[2*(i+1)+1] = Temp; + + Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + } while ( fChange ); + +/* + Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " ); + for ( i = 0; i < nVars; i++ ) + printf( "%d=%d/%d ", pCanonPerm[i], pStore[2*i], pStore[2*i+1] ); + printf( " C = %d\n", Counter ); + Extra_PrintHexadecimal( stdout, pIn, nVars ); + printf( "\n" ); +*/ + +/* + // process symmetric variable groups + uSymms = 0; + for ( i = 0; i < nVars-1; i++ ) + { + if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric + continue; + if ( pStore[2*i] != pStore[2*i+1] ) + continue; + if ( Extra_TruthVarsSymm( pIn, nVars, i, i+1 ) ) + continue; + if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, i+1 ) ) + Extra_TruthChangePhase( pIn, nVars, i+1 ); + } +*/ + +/* + // process symmetric variable groups + uSymms = 0; + for ( i = 0; i < nVars-1; i++ ) + { + if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric + continue; + // i and i+1 can be symmetric + // find the end of this group + for ( k = i+1; k < nVars; k++ ) + if ( pStore[2*i] != pStore[2*k] ) + break; + Limit = k; + assert( i < Limit-1 ); + // go through the variables in this group + for ( j = i + 1; j < Limit; j++ ) + { + // check symmetry + if ( Extra_TruthVarsSymm( pIn, nVars, i, j ) ) + { + uSymms |= (1 << j); + continue; + } + // they are phase-unknown + if ( pStore[2*i] == pStore[2*i+1] ) + { + if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, j ) ) + { + Extra_TruthChangePhase( pIn, nVars, j ); + uCanonPhase ^= (1 << j); + uSymms |= (1 << j); + continue; + } + } + + // they are not symmetric - move j as far as it goes in the group + for ( k = j; k < Limit-1; k++ ) + { + Counter++; + + Temp = pCanonPerm[k]; + pCanonPerm[k] = pCanonPerm[k+1]; + pCanonPerm[k+1] = Temp; + + assert( pStore[2*k] == pStore[2*(k+1)] ); + Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, k ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + Limit--; + j--; + } + i = Limit - 1; + } +*/ + + // swap if it was moved an even number of times + if ( Counter & 1 ) + Extra_TruthCopy( pOut, pIn, nVars ); + return uCanonPhase; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/extra/extraUtilUtil.c b/abc70930/src/misc/extra/extraUtilUtil.c new file mode 100644 index 00000000..ee0c400a --- /dev/null +++ b/abc70930/src/misc/extra/extraUtilUtil.c @@ -0,0 +1,330 @@ +/**CFile**************************************************************** + + FileName [extraUtilUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [extra] + + Synopsis [Old SIS utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: extraUtilUtil.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define EXTRA_RLIMIT_DATA_DEFAULT 67108864 // assume 64MB by default + +/* File : getopt.c + * Author : Henry Spencer, University of Toronto + * Updated: 28 April 1984 + * + * Changes: (R Rudell) + * changed index() to strchr(); + * added getopt_reset() to reset the getopt argument parsing + * + * Purpose: get option letter from argv. + */ + +char * globalUtilOptarg; // Global argument pointer (util_optarg) +int globalUtilOptind = 0; // Global argv index (util_optind) + +static char *pScanStr; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [util_cpu_time()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +long Extra_CpuTime() +{ + return clock(); +} + +/**Function************************************************************* + + Synopsis [getSoftDataLimit()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_GetSoftDataLimit() +{ + return EXTRA_RLIMIT_DATA_DEFAULT; +} + +/**Function************************************************************* + + Synopsis [util_getopt_reset()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_UtilGetoptReset() +{ + globalUtilOptarg = 0; + globalUtilOptind = 0; + pScanStr = 0; +} + +/**Function************************************************************* + + Synopsis [util_getopt()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_UtilGetopt( int argc, char *argv[], char *optstring ) +{ + register int c; + register char *place; + + globalUtilOptarg = NULL; + + if (pScanStr == NULL || *pScanStr == '\0') { + if (globalUtilOptind == 0) globalUtilOptind++; + if (globalUtilOptind >= argc) return EOF; + place = argv[globalUtilOptind]; + if (place[0] != '-' || place[1] == '\0') return EOF; + globalUtilOptind++; + if (place[1] == '-' && place[2] == '\0') return EOF; + pScanStr = place+1; + } + + c = *pScanStr++; + place = strchr(optstring, c); + if (place == NULL || c == ':') { + (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c); + return '?'; + } + if (*++place == ':') { + if (*pScanStr != '\0') { + globalUtilOptarg = pScanStr; + pScanStr = NULL; + } else { + if (globalUtilOptind >= argc) { + (void) fprintf(stderr, "%s: %c requires an argument\n", + argv[0], c); + return '?'; + } + globalUtilOptarg = argv[globalUtilOptind]; + globalUtilOptind++; + } + } + return c; +} + +/**Function************************************************************* + + Synopsis [util_print_time()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_UtilPrintTime( long t ) +{ + static char s[40]; + + (void) sprintf(s, "%ld.%02ld sec", t/1000, (t%1000)/10); + return s; +} + + +/**Function************************************************************* + + Synopsis [Extra_UtilStrsav()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_UtilStrsav( char *s ) +{ + if(s == NULL) { /* added 7/95, for robustness */ + return s; + } + else { + return strcpy(ALLOC(char, strlen(s)+1), s); + } +} + +/**Function************************************************************* + + Synopsis [util_tilde_expand()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_UtilTildeExpand( char *fname ) +{ + return Extra_UtilStrsav( fname ); +} + +/**Function************************************************************* + + Synopsis [check_file()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Extra_UtilCheckFile(char *filename, char *mode) +{ + FILE *fp; + int got_file; + + if (strcmp(mode, "x") == 0) { + mode = "r"; + } + fp = fopen(filename, mode); + got_file = (fp != 0); + if (fp != 0) { + (void) fclose(fp); + } + return got_file; +} + +/**Function************************************************************* + + Synopsis [util_file_search()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Extra_UtilFileSearch(char *file, char *path, char *mode) +//char *file; // file we're looking for +//char *path; // search path, colon separated +//char *mode; // "r", "w", or "x" +{ + int quit; + char *buffer, *filename, *save_path, *cp; + + if (path == 0 || strcmp(path, "") == 0) { + path = "."; /* just look in the current directory */ + } + + save_path = path = Extra_UtilStrsav(path); + quit = 0; + do { + cp = strchr(path, ':'); + if (cp != 0) { + *cp = '\0'; + } else { + quit = 1; + } + + /* cons up the filename out of the path and file name */ + if (strcmp(path, ".") == 0) { + buffer = Extra_UtilStrsav(file); + } else { + buffer = ALLOC(char, strlen(path) + strlen(file) + 4); + (void) sprintf(buffer, "%s/%s", path, file); + } + filename = Extra_UtilTildeExpand(buffer); + FREE(buffer); + + /* see if we can access it */ + if (Extra_UtilCheckFile(filename, mode)) { + FREE(save_path); + return filename; + } + FREE(filename); + path = ++cp; + } while (! quit); + + FREE(save_path); + return 0; +} + +/**Function************************************************************* + + Synopsis [MMout_of_memory()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* MMout_of_memory -- out of memory for lazy people, flush and exit */ +void Extra_UtilMMout_Of_Memory( long size ) +{ + (void) fflush(stdout); + (void) fprintf(stderr, "\nout of memory allocating %u bytes\n", + (unsigned) size); + assert( 0 ); + exit(1); +} + +/**Function************************************************************* + + Synopsis [MMoutOfMemory()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void (*Extra_UtilMMoutOfMemory)() = Extra_UtilMMout_Of_Memory; + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/extra/module.make b/abc70930/src/misc/extra/module.make new file mode 100644 index 00000000..ec8bca4d --- /dev/null +++ b/abc70930/src/misc/extra/module.make @@ -0,0 +1,15 @@ +SRC += src/misc/extra/extraBddAuto.c \ + src/misc/extra/extraBddCas.c \ + src/misc/extra/extraBddKmap.c \ + src/misc/extra/extraBddMisc.c \ + src/misc/extra/extraBddSymm.c \ + src/misc/extra/extraBddUnate.c \ + src/misc/extra/extraUtilBitMatrix.c \ + src/misc/extra/extraUtilCanon.c \ + src/misc/extra/extraUtilFile.c \ + src/misc/extra/extraUtilMemory.c \ + src/misc/extra/extraUtilMisc.c \ + src/misc/extra/extraUtilProgress.c \ + src/misc/extra/extraUtilReader.c \ + src/misc/extra/extraUtilTruth.c \ + src/misc/extra/extraUtilUtil.c diff --git a/abc70930/src/misc/hash/hash.h b/abc70930/src/misc/hash/hash.h new file mode 100644 index 00000000..90e72868 --- /dev/null +++ b/abc70930/src/misc/hash/hash.h @@ -0,0 +1,65 @@ +/**CFile**************************************************************** + + FileName [hash.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Hash map.] + + Synopsis [External declarations.] + + Author [Aaron P. Hurst] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 16, 2005.] + + Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] + +***********************************************************************/ + +#ifndef __HASH_H__ +#define __HASH_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +#include "hashInt.h" +#include "hashFlt.h" +#include "hashPtr.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifndef ABS +#define ABS(a) ((a) < 0 ? -(a) : (a)) +#endif + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +int Hash_DefaultHashFunc(int key, int nBins) { + return ABS( ( (key+11)*(key)*7+3 ) % nBins ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/abc70930/src/misc/hash/hashFlt.h b/abc70930/src/misc/hash/hashFlt.h new file mode 100644 index 00000000..da20ee28 --- /dev/null +++ b/abc70930/src/misc/hash/hashFlt.h @@ -0,0 +1,330 @@ +/**CFile**************************************************************** + + FileName [hashFlt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Hash maps.] + + Synopsis [Hash maps.] + + Author [Aaron P. Hurst] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 16, 2006.] + + Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] + +***********************************************************************/ + +#ifndef __HASH_FLT_H__ +#define __HASH_FLT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "extra.h" + +extern int Hash_DefaultHashFunc(int key, int nBins); + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Hash_Flt_t_ Hash_Flt_t; +typedef struct Hash_Flt_Entry_t_ Hash_Flt_Entry_t; + +struct Hash_Flt_Entry_t_ +{ + int key; + float data; + struct Hash_Flt_Entry_t_ * pNext; +}; + +struct Hash_Flt_t_ +{ + int nSize; + int nBins; + int (* fHash)(int key, int nBins); + Hash_Flt_Entry_t ** pArray; +}; + + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Hash_FltForEachEntry( pHash, pEntry, bin) \ + for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \ + if (pEntry) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a hash map with the given number of bins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Hash_Flt_t * Hash_FltAlloc( int nBins ) +{ + Hash_Flt_t * p; + int i; + assert(nBins > 0); + p = ALLOC( Hash_Flt_t, 1); + p->nBins = nBins; + p->fHash = Hash_DefaultHashFunc; + p->nSize = 0; + p->pArray = ALLOC( Hash_Flt_Entry_t *, nBins ); + for(i=0; ipArray[i] = NULL; + + return p; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if a key already exists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Hash_FltExists( Hash_Flt_t *p, int key ) +{ + int bin; + Hash_Flt_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) { + return 1; + } + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + return 0; +} + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key and writes value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Hash_FltWriteEntry( Hash_Flt_t *p, int key, float data ) +{ + int bin; + Hash_Flt_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) { + pEntry->data = data; + return; + } + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = data; + + return; +} + + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key.] + + Description [fCreate specifies whether new entries should be created.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Hash_FltEntry( Hash_Flt_t *p, int key, int fCreate ) +{ + int bin; + Hash_Flt_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) + return pEntry->data; + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + if (fCreate) { + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = 0.0; + return pEntry->data; + } + + return 0.0; +} + + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key and returns the pointer to it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float* Hash_FltEntryPtr( Hash_Flt_t *p, int key ) +{ + int bin; + Hash_Flt_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) + return &(pEntry->data); + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = 0.0; + + return &(pEntry->data); +} + +/**Function************************************************************* + + Synopsis [Deletes an entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Hash_FltRemove( Hash_Flt_t *p, int key ) +{ + int bin; + Hash_Flt_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) { + p->nSize--; + *pLast = pEntry->pNext; + FREE( pEntry ); + return; + } + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // could not find key + return; +} + +/**Function************************************************************* + + Synopsis [Frees the hash.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Hash_FltFree( Hash_Flt_t *p ) { + int bin; + Hash_Flt_Entry_t *pEntry; + + // free bins + for(bin = 0; bin < p->nBins; bin++) { + pEntry = p->pArray[bin]; + while(pEntry) { + pEntry = pEntry->pNext; + FREE( pEntry ); + } + } + + // free hash + FREE( p->pArray ); + FREE( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif diff --git a/abc70930/src/misc/hash/hashInt.h b/abc70930/src/misc/hash/hashInt.h new file mode 100644 index 00000000..3b91f5df --- /dev/null +++ b/abc70930/src/misc/hash/hashInt.h @@ -0,0 +1,293 @@ +/**CFile**************************************************************** + + FileName [hashInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Hash maps.] + + Synopsis [Hash maps.] + + Author [Aaron P. Hurst] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 16, 2006.] + + Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] + +***********************************************************************/ + +#ifndef __HASH_INT_H__ +#define __HASH_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "extra.h" + +extern int Hash_DefaultHashFunc(int key, int nBins); + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Hash_Int_t_ Hash_Int_t; +typedef struct Hash_Int_Entry_t_ Hash_Int_Entry_t; + +struct Hash_Int_Entry_t_ +{ + int key; + int data; + struct Hash_Int_Entry_t_ * pNext; +}; + +struct Hash_Int_t_ +{ + int nSize; + int nBins; + int (* fHash)(int key, int nBins); + Hash_Int_Entry_t ** pArray; +}; + + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Hash_IntForEachEntry( pHash, pEntry, bin) \ + for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \ + if (pEntry) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a hash map with the given number of bins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Hash_Int_t * Hash_IntAlloc( int nBins ) +{ + Hash_Int_t * p; + int i; + assert(nBins > 0); + p = ALLOC( Hash_Int_t, 1); + p->nBins = nBins; + p->fHash = Hash_DefaultHashFunc; + p->nSize = 0; + p->pArray = ALLOC( Hash_Int_Entry_t *, nBins ); + for(i=0; ipArray[i] = NULL; + + return p; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if a key already exists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Hash_IntExists( Hash_Int_t *p, int key) +{ + int bin; + Hash_Int_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) { + return 1; + } + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + return 0; +} + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key and writes value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Hash_IntWriteEntry( Hash_Int_t *p, int key, int data ) +{ + int bin; + Hash_Int_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) { + pEntry->data = data; + return; + } + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = data; + + return; +} + + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key.] + + Description [fCreate specifies whether new entries will be created.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Hash_IntEntry( Hash_Int_t *p, int key, int fCreate ) +{ + int bin; + Hash_Int_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) + return pEntry->data; + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + if (fCreate) { + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = 0; + return pEntry->data; + } + + return 0; +} + + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key and returns the pointer to it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int* Hash_IntEntryPtr( Hash_Int_t *p, int key ) +{ + int bin; + Hash_Int_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) + return &(pEntry->data); + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = 0; + + return &(pEntry->data); +} + +/**Function************************************************************* + + Synopsis [Frees the hash.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Hash_IntFree( Hash_Int_t *p ) { + int bin; + Hash_Int_Entry_t *pEntry; + + // free bins + for(bin = 0; bin < p->nBins; bin++) { + pEntry = p->pArray[bin]; + while(pEntry) { + pEntry = pEntry->pNext; + FREE( pEntry ); + } + } + + // free hash + FREE( p->pArray ); + FREE( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif diff --git a/abc70930/src/misc/hash/hashPtr.h b/abc70930/src/misc/hash/hashPtr.h new file mode 100644 index 00000000..15398a8a --- /dev/null +++ b/abc70930/src/misc/hash/hashPtr.h @@ -0,0 +1,331 @@ +/**CFile**************************************************************** + + FileName [hashFlt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Hash maps.] + + Synopsis [Hash maps.] + + Author [Aaron P. Hurst] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 16, 2006.] + + Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] + +***********************************************************************/ + +#ifndef __HASH_PTR_H__ +#define __HASH_PTR_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "extra.h" + +extern int Hash_DefaultHashFunc(int key, int nBins); + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Hash_Ptr_t_ Hash_Ptr_t; +typedef struct Hash_Ptr_Entry_t_ Hash_Ptr_Entry_t; + +struct Hash_Ptr_Entry_t_ +{ + int key; + void * data; + struct Hash_Ptr_Entry_t_ * pNext; +}; + +struct Hash_Ptr_t_ +{ + int nSize; + int nBins; + int (* fHash)(int key, int nBins); + Hash_Ptr_Entry_t ** pArray; +}; + + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Hash_PtrForEachEntry( pHash, pEntry, bin ) \ + for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \ + if (pEntry) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a hash map with the given number of bins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Hash_Ptr_t * Hash_PtrAlloc( int nBins ) +{ + Hash_Ptr_t * p; + int i; + assert(nBins > 0); + p = ALLOC( Hash_Ptr_t, 1); + p->nBins = nBins; + p->fHash = Hash_DefaultHashFunc; + p->nSize = 0; + p->pArray = ALLOC( Hash_Ptr_Entry_t *, nBins ); + for(i=0; ipArray[i] = NULL; + + return p; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if a key already exists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Hash_PtrExists( Hash_Ptr_t *p, int key ) +{ + int bin; + Hash_Ptr_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) { + return 1; + } + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + return 0; +} + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key and writes value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Hash_PtrWriteEntry( Hash_Ptr_t *p, int key, void * data ) +{ + int bin; + Hash_Ptr_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) { + pEntry->data = data; + return; + } + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = data; + + return; +} + + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key.] + + Description [fCreate specifies whether a new entry should be created.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Hash_PtrEntry( Hash_Ptr_t *p, int key, int fCreate ) +{ + int bin; + Hash_Ptr_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) + return pEntry->data; + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + if (fCreate) { + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = NULL; + return pEntry->data; + } + + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Finds or creates an entry with a key and returns the pointer to it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void** Hash_PtrEntryPtr( Hash_Ptr_t *p, int key ) +{ + int bin; + Hash_Ptr_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) + return &(pEntry->data); + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // this key does not currently exist + // create a new entry and add to bin + p->nSize++; + (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 ); + pEntry->pNext = NULL; + pEntry->key = key; + pEntry->data = NULL; + + return &(pEntry->data); +} + +/**Function************************************************************* + + Synopsis [Deletes an entry.] + + Description [Returns data, if there was any.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void* Hash_PtrRemove( Hash_Ptr_t *p, int key ) +{ + int bin; + void * data; + Hash_Ptr_Entry_t *pEntry, **pLast; + + // find the bin where this key would live + bin = (*(p->fHash))(key, p->nBins); + + // search for key + pLast = &(p->pArray[bin]); + pEntry = p->pArray[bin]; + while(pEntry) { + if (pEntry->key == key) { + p->nSize--; + data = pEntry->data; + *pLast = pEntry->pNext; + return data; + } + pLast = &(pEntry->pNext); + pEntry = pEntry->pNext; + } + + // could not find key + return NULL; +} + +/**Function************************************************************* + + Synopsis [Frees the hash.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Hash_PtrFree( Hash_Ptr_t *p ) { + int bin; + Hash_Ptr_Entry_t *pEntry; + + // free bins + for(bin = 0; bin < p->nBins; bin++) { + pEntry = p->pArray[bin]; + while(pEntry) { + pEntry = pEntry->pNext; + FREE( pEntry ); + } + } + + // free hash + FREE( p->pArray ); + FREE( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif diff --git a/abc70930/src/misc/hash/module.make b/abc70930/src/misc/hash/module.make new file mode 100644 index 00000000..d6d908e7 --- /dev/null +++ b/abc70930/src/misc/hash/module.make @@ -0,0 +1 @@ +SRC += diff --git a/abc70930/src/misc/mvc/module.make b/abc70930/src/misc/mvc/module.make new file mode 100644 index 00000000..23735ca2 --- /dev/null +++ b/abc70930/src/misc/mvc/module.make @@ -0,0 +1,16 @@ +SRC += src/misc/mvc/mvc.c \ + src/misc/mvc/mvcApi.c \ + src/misc/mvc/mvcCompare.c \ + src/misc/mvc/mvcContain.c \ + src/misc/mvc/mvcCover.c \ + src/misc/mvc/mvcCube.c \ + src/misc/mvc/mvcDivide.c \ + src/misc/mvc/mvcDivisor.c \ + src/misc/mvc/mvcList.c \ + src/misc/mvc/mvcLits.c \ + src/misc/mvc/mvcMan.c \ + src/misc/mvc/mvcOpAlg.c \ + src/misc/mvc/mvcOpBool.c \ + src/misc/mvc/mvcPrint.c \ + src/misc/mvc/mvcSort.c \ + src/misc/mvc/mvcUtils.c diff --git a/abc70930/src/misc/mvc/mvc.c b/abc70930/src/misc/mvc/mvc.c new file mode 100644 index 00000000..001b1c63 --- /dev/null +++ b/abc70930/src/misc/mvc/mvc.c @@ -0,0 +1,46 @@ +/**CFile**************************************************************** + + FileName [mvc.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvc.c,v 1.3 2003/03/19 19:50:26 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvc.h b/abc70930/src/misc/mvc/mvc.h new file mode 100644 index 00000000..70834e0a --- /dev/null +++ b/abc70930/src/misc/mvc/mvc.h @@ -0,0 +1,732 @@ +/**CFile**************************************************************** + + FileName [mvc.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Data structure for MV cube/cover manipulation.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvc.h,v 1.10 2003/05/02 23:23:59 wjiang Exp $] + +***********************************************************************/ + +#ifndef __MVC_H__ +#define __MVC_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "extra.h" +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// this is the only part of Mvc package, which should be modified +// when compiling the package for other platforms + +// these parameters can be computed but setting them manually makes it faster +#define BITS_PER_WORD 32 // sizeof(Mvc_CubeWord_t) * 8 +#define BITS_PER_WORD_MINUS 31 // the same minus 1 +#define BITS_PER_WORD_LOG 5 // log2(sizeof(Mvc_CubeWord_t) * 8) +#define BITS_DISJOINT ((Mvc_CubeWord_t)0x55555555) // the mask of the type "01010101" +#define BITS_FULL ((Mvc_CubeWord_t)0xffffffff) // the mask of the type "11111111" + +// uncomment this macro to switch to standard memory management +//#define USE_SYSTEM_MEMORY_MANAGEMENT + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// cube/list/cover/data +typedef unsigned int Mvc_CubeWord_t; +typedef struct MvcCubeStruct Mvc_Cube_t; +typedef struct MvcListStruct Mvc_List_t; +typedef struct MvcCoverStruct Mvc_Cover_t; +typedef struct MvcDataStruct Mvc_Data_t; +typedef struct MvcManagerStruct Mvc_Manager_t; + +// the cube data structure +struct MvcCubeStruct +{ + Mvc_Cube_t * pNext; // the next cube in the linked list + unsigned iLast : 8; // the index of the last word + unsigned nUnused : 6; // the number of unused bits in the last word + unsigned fPrime : 1; // marks the prime cube + unsigned fEssen : 1; // marks the essential cube + unsigned nOnes : 16; // the number of 1's in the bit data + Mvc_CubeWord_t pData[1]; // the first Mvc_CubeWord_t filled with bit data +}; + +// the single-linked list of cubes in the cover +struct MvcListStruct +{ + Mvc_Cube_t * pHead; // the first cube in the list + Mvc_Cube_t * pTail; // the last cube in the list + int nItems; // the number of cubes in the list +}; + +// the cover data structure +struct MvcCoverStruct +{ + char nWords; // the number of machine words + char nUnused; // the number of unused bits in the last word + short nBits; // the number of used data bits in the cube + Mvc_List_t lCubes; // the single-linked list of cubes + Mvc_Cube_t ** pCubes; // the array of cubes (for sorting) + int nCubesAlloc; // the size of allocated storage + int * pLits; // the counter of lit occurrances in cubes + Mvc_Cube_t * pMask; // the multipurpose mask + Mvc_Manager_t * pMem; // the memory manager +}; + +// data structure to store information about MV variables +struct MvcDataStruct +{ + Mvc_Manager_t * pMan; // the memory manager +// Vm_VarMap_t * pVm; // the MV variable data + int nBinVars; // the number of binary variables + Mvc_Cube_t * pMaskBin; // the mask to select the binary bits only + Mvc_Cube_t ** ppMasks; // the mask to select each MV variable + Mvc_Cube_t * ppTemp[3]; // the temporary cubes +}; + +// the manager of covers and cubes (as of today, only managing memory) +struct MvcManagerStruct +{ + Extra_MmFixed_t * pManC; // the manager for covers + Extra_MmFixed_t * pMan1; // the manager for 1-word cubes + Extra_MmFixed_t * pMan2; // the manager for 2-word cubes + Extra_MmFixed_t * pMan4; // the manager for 3-word cubes +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// reading data from the header of the cube +#define Mvc_CubeReadNext(Cube) ((Cube)->pNext) +#define Mvc_CubeReadNextP(Cube) (&(Cube)->pNext) +#define Mvc_CubeReadLast(Cube) ((Cube)->iLast) +#define Mvc_CubeReadSize(Cube) ((Cube)->nOnes) +// setting data to the header of the cube +#define Mvc_CubeSetNext(Cube,Next) ((Cube)->pNext = (Next)) +#define Mvc_CubeSetLast(Cube,Last) ((Cube)->iLast = (Last)) +#define Mvc_CubeSetSize(Cube,Size) ((Cube)->nOnes = (Size)) +// checking the number of words + +#define Mvc_Cube1Words(Cube) ((Cube)->iLast == 0) +#define Mvc_Cube2Words(Cube) ((Cube)->iLast == 1) +#define Mvc_CubeNWords(Cube) ((Cube)->iLast > 1) +// getting one data bit +#define Mvc_CubeWhichWord(Bit) ((Bit) >> BITS_PER_WORD_LOG) +#define Mvc_CubeWhichBit(Bit) ((Bit) & BITS_PER_WORD_MINUS) +// accessing individual bits +#define Mvc_CubeBitValue(Cube, Bit) (((Cube)->pData[Mvc_CubeWhichWord(Bit)] & (((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit)))) > 0) +#define Mvc_CubeBitInsert(Cube, Bit) ((Cube)->pData[Mvc_CubeWhichWord(Bit)] |= (((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit)))) +#define Mvc_CubeBitRemove(Cube, Bit) ((Cube)->pData[Mvc_CubeWhichWord(Bit)] &= ~(((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit)))) +// accessing values of the binary variables +#define Mvc_CubeVarValue(Cube, Var) (((Cube)->pData[Mvc_CubeWhichWord(2*(Var))] >> (Mvc_CubeWhichBit(2*(Var)))) & ((Mvc_CubeWord_t)3)) + +// various macros + +// cleaning the data bits of the cube +#define Mvc_Cube1BitClean( Cube )\ + ((Cube)->pData[0] = 0) +#define Mvc_Cube2BitClean( Cube )\ + (((Cube)->pData[0] = 0),\ + ((Cube)->pData[1] = 0)) +#define Mvc_CubeNBitClean( Cube )\ +{\ + int _i_;\ + for( _i_ = (Cube)->iLast; _i_ >= 0; _i_--)\ + (Cube)->pData[_i_] = 0;\ +} + +// cleaning the unused part of the lat word +#define Mvc_CubeBitCleanUnused( Cube )\ + ((Cube)->pData[(Cube)->iLast] &= (BITS_FULL >> (Cube)->nUnused)) + +// filling the used data bits with 1's +#define Mvc_Cube1BitFill( Cube )\ + (Cube)->pData[0] = (BITS_FULL >> (Cube)->nUnused); +#define Mvc_Cube2BitFill( Cube )\ + (((Cube)->pData[0] = BITS_FULL),\ + ((Cube)->pData[1] = (BITS_FULL >> (Cube)->nUnused))) +#define Mvc_CubeNBitFill( Cube )\ +{\ + int _i_;\ + (Cube)->pData[(Cube)->iLast] = (BITS_FULL >> (Cube)->nUnused);\ + for( _i_ = (Cube)->iLast - 1; _i_ >= 0; _i_-- )\ + (Cube)->pData[_i_] = BITS_FULL;\ +} + +// complementing the data bits +#define Mvc_Cube1BitNot( Cube )\ + ((Cube)->pData[0] ^= (BITS_FULL >> (Cube)->nUnused)) +#define Mvc_Cube2BitNot( Cube )\ + (((Cube)->pData[0] ^= BITS_FULL),\ + ((Cube)->pData[1] ^= (BITS_FULL >> (Cube)->nUnused))) +#define Mvc_CubeNBitNot( Cube )\ +{\ + int _i_;\ + (Cube)->pData[(Cube)->iLast] ^= (BITS_FULL >> (Cube)->nUnused);\ + for( _i_ = (Cube)->iLast - 1; _i_ >= 0; _i_-- )\ + (Cube)->pData[_i_] ^= BITS_FULL;\ +} + +#define Mvc_Cube1BitCopy( Cube1, Cube2 )\ + (((Cube1)->pData[0]) = ((Cube2)->pData[0])) +#define Mvc_Cube2BitCopy( Cube1, Cube2 )\ + ((((Cube1)->pData[0]) = ((Cube2)->pData[0])),\ + (((Cube1)->pData[1])= ((Cube2)->pData[1]))) +#define Mvc_CubeNBitCopy( Cube1, Cube2 )\ +{\ + int _i_;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + ((Cube1)->pData[_i_]) = ((Cube2)->pData[_i_]);\ +} + +#define Mvc_Cube1BitOr( CubeR, Cube1, Cube2 )\ + (((CubeR)->pData[0]) = ((Cube1)->pData[0] | (Cube2)->pData[0])) +#define Mvc_Cube2BitOr( CubeR, Cube1, Cube2 )\ + ((((CubeR)->pData[0]) = ((Cube1)->pData[0] | (Cube2)->pData[0])),\ + (((CubeR)->pData[1]) = ((Cube1)->pData[1] | (Cube2)->pData[1]))) +#define Mvc_CubeNBitOr( CubeR, Cube1, Cube2 )\ +{\ + int _i_;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] | (Cube2)->pData[_i_]));\ +} + +#define Mvc_Cube1BitExor( CubeR, Cube1, Cube2 )\ + (((CubeR)->pData[0]) = ((Cube1)->pData[0] ^ (Cube2)->pData[0])) +#define Mvc_Cube2BitExor( CubeR, Cube1, Cube2 )\ + ((((CubeR)->pData[0]) = ((Cube1)->pData[0] ^ (Cube2)->pData[0])),\ + (((CubeR)->pData[1]) = ((Cube1)->pData[1] ^ (Cube2)->pData[1]))) +#define Mvc_CubeNBitExor( CubeR, Cube1, Cube2 )\ +{\ + int _i_;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] ^ (Cube2)->pData[_i_]));\ +} + +#define Mvc_Cube1BitAnd( CubeR, Cube1, Cube2 )\ + (((CubeR)->pData[0]) = ((Cube1)->pData[0] & (Cube2)->pData[0])) +#define Mvc_Cube2BitAnd( CubeR, Cube1, Cube2 )\ + ((((CubeR)->pData[0]) = ((Cube1)->pData[0] & (Cube2)->pData[0])),\ + (((CubeR)->pData[1]) = ((Cube1)->pData[1] & (Cube2)->pData[1]))) +#define Mvc_CubeNBitAnd( CubeR, Cube1, Cube2 )\ +{\ + int _i_;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] & (Cube2)->pData[_i_]));\ +} + +#define Mvc_Cube1BitSharp( CubeR, Cube1, Cube2 )\ + (((CubeR)->pData[0]) = ((Cube1)->pData[0] & ~((Cube2)->pData[0]))) +#define Mvc_Cube2BitSharp( CubeR, Cube1, Cube2 )\ + ((((CubeR)->pData[0]) = ((Cube1)->pData[0] & ~((Cube2)->pData[0]))),\ + (((CubeR)->pData[1]) = ((Cube1)->pData[1] & ~((Cube2)->pData[1])))) +#define Mvc_CubeNBitSharp( CubeR, Cube1, Cube2 )\ +{\ + int _i_;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] & ~(Cube2)->pData[_i_]));\ +} + +#define Mvc_Cube1BitEmpty( Res, Cube )\ + (Res = ((Cube)->pData[0] == 0)) +#define Mvc_Cube2BitEmpty( Res, Cube )\ + (Res = ((Cube)->pData[0] == 0 && (Cube)->pData[1] == 0)) +#define Mvc_CubeNBitEmpty( Res, Cube )\ +{\ + int _i_; Res = 1;\ + for (_i_ = (Cube)->iLast; _i_ >= 0; _i_--)\ + if ( (Cube)->pData[_i_] )\ + { Res = 0; break; }\ +} + +#define Mvc_Cube1BitEqual( Res, Cube1, Cube2 )\ + (Res = (((Cube1)->pData[0]) == ((Cube2)->pData[0]))) +#define Mvc_Cube2BitEqual( Res, Cube1, Cube2 )\ + (Res = ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) &&\ + (((Cube1)->pData[1]) == ((Cube2)->pData[1])))) +#define Mvc_CubeNBitEqual( Res, Cube1, Cube2 )\ +{\ + int _i_; Res = 1;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + if (((Cube1)->pData[_i_]) != ((Cube2)->pData[_i_]))\ + { Res = 0; break; }\ +} + +#define Mvc_Cube1BitLess( Res, Cube1, Cube2 )\ + (Res = (((Cube1)->pData[0]) < ((Cube2)->pData[0]))) +#define Mvc_Cube2BitLess( Res, Cube1, Cube2 )\ + (Res = ((((Cube1)->pData[0]) < ((Cube2)->pData[0])) ||\ + ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) && (((Cube1)->pData[1]) < ((Cube2)->pData[1]))))) +#define Mvc_CubeNBitLess( Res, Cube1, Cube2 )\ +{\ + int _i_; Res = 1;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + if (((Cube1)->pData[_i_]) >= ((Cube2)->pData[_i_]))\ + { Res = 0; break; }\ +} + +#define Mvc_Cube1BitMore( Res, Cube1, Cube2 )\ + (Res = (((Cube1)->pData[0]) > ((Cube2)->pData[0]))) +#define Mvc_Cube2BitMore( Res, Cube1, Cube2 )\ + (Res = ((((Cube1)->pData[0]) > ((Cube2)->pData[0])) ||\ + ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) && (((Cube1)->pData[1]) > ((Cube2)->pData[1]))))) +#define Mvc_CubeNBitMore( Res, Cube1, Cube2 )\ +{\ + int _i_; Res = 1;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + if (((Cube1)->pData[_i_]) <= ((Cube2)->pData[_i_]))\ + { Res = 0; break; }\ +} + +#define Mvc_Cube1BitNotImpl( Res, Cube1, Cube2 )\ + (Res = (((Cube1)->pData[0]) & ~((Cube2)->pData[0]))) +#define Mvc_Cube2BitNotImpl( Res, Cube1, Cube2 )\ + (Res = ((((Cube1)->pData[0]) & ~((Cube2)->pData[0])) ||\ + (((Cube1)->pData[1]) & ~((Cube2)->pData[1])))) +#define Mvc_CubeNBitNotImpl( Res, Cube1, Cube2 )\ +{\ + int _i_; Res = 0;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + if (((Cube1)->pData[_i_]) & ~((Cube2)->pData[_i_]))\ + { Res = 1; break; }\ +} + +#define Mvc_Cube1BitDisjoint( Res, Cube1, Cube2 )\ + (Res = ((((Cube1)->pData[0]) & ((Cube2)->pData[0])) == 0 )) +#define Mvc_Cube2BitDisjoint( Res, Cube1, Cube2 )\ + (Res = (((((Cube1)->pData[0]) & ((Cube2)->pData[0])) == 0 ) &&\ + ((((Cube1)->pData[1]) & ((Cube2)->pData[1])) == 0 ))) +#define Mvc_CubeNBitDisjoint( Res, Cube1, Cube2 )\ +{\ + int _i_; Res = 1;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + if (((Cube1)->pData[_i_]) & ((Cube2)->pData[_i_]))\ + { Res = 0; break; }\ +} + +#define Mvc_Cube1BitEqualUnderMask( Res, Cube1, Cube2, Mask )\ + (Res = ((((Cube1)->pData[0]) & ((Mask)->pData[0])) == (((Cube2)->pData[0]) & ((Mask)->pData[0])))) +#define Mvc_Cube2BitEqualUnderMask( Res, Cube1, Cube2, Mask )\ + (Res = (((((Cube1)->pData[0]) & ((Mask)->pData[0])) == (((Cube2)->pData[0]) & ((Mask)->pData[0]))) &&\ + ((((Cube1)->pData[1]) & ((Mask)->pData[1])) == (((Cube2)->pData[1]) & ((Mask)->pData[1]))))) +#define Mvc_CubeNBitEqualUnderMask( Res, Cube1, Cube2, Mask )\ +{\ + int _i_; Res = 1;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + if ((((Cube1)->pData[_i_]) & ((Mask)->pData[_i_])) != (((Cube2)->pData[_i_]) & ((Mask)->pData[_i_])))\ + { Res = 0; break; }\ +} + +#define Mvc_Cube1BitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ + (Res = ((((Cube1)->pData[0]) | ((Mask)->pData[0])) == (((Cube2)->pData[0]) | ((Mask)->pData[0])))) +#define Mvc_Cube2BitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ + (Res = (((((Cube1)->pData[0]) | ((Mask)->pData[0])) == (((Cube2)->pData[0]) | ((Mask)->pData[0]))) &&\ + ((((Cube1)->pData[1]) | ((Mask)->pData[1])) == (((Cube2)->pData[1]) | ((Mask)->pData[1]))))) +#define Mvc_CubeNBitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ +{\ + int _i_; Res = 1;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + if ((((Cube1)->pData[_i_]) | ((Mask)->pData[_i_])) != (((Cube2)->pData[_i_]) | ((Mask)->pData[_i_])))\ + { Res = 0; break; }\ +} + +#define Mvc_Cube1BitIntersectUnderMask( Res, Cube1, Cube2, Mask)\ + (Res = ((((Cube1)->pData[0]) & ((Cube2)->pData[0]) & ((Mask)->pData[0])) > 0)) +#define Mvc_Cube2BitIntersectUnderMask( Res, Cube1, Cube2, Mask)\ + (Res = (((((Cube1)->pData[0]) & ((Cube2)->pData[0]) & ((Mask)->pData[0])) > 0) ||\ + ((((Cube1)->pData[1]) & ((Cube2)->pData[1]) & ((Mask)->pData[1])) > 0))) +#define Mvc_CubeNBitIntersectUnderMask( Res, Cube1, Cube2, Mask)\ +{\ + int _i_; Res = 0;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + if (((Cube1)->pData[_i_]) & ((Cube2)->pData[_i_]) & ((Mask)->pData[_i_]))\ + { Res = 1; break; }\ +} + +#define Mvc_Cube1BitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ + (Res = (((Mask)->pData[0]) & ((Cube1)->pData[0]) & ~((Cube2)->pData[0]))) +#define Mvc_Cube2BitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ + (Res = ((((Mask)->pData[0]) & ((Cube1)->pData[0]) & ~((Cube2)->pData[0])) ||\ + (((Mask)->pData[1]) & ((Cube1)->pData[1]) & ~((Cube2)->pData[1])))) +#define Mvc_CubeNBitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ +{\ + int _i_; Res = 0;\ + for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ + if (((Mask)->pData[_i_]) & ((Cube1)->pData[_i_]) & ~((Cube2)->pData[_i_]))\ + { Res = 1; break; }\ +} + +// the following macros make no assumption about the cube's bitset size +#define Mvc_CubeBitClean( Cube )\ + if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitClean( Cube ); }\ + else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitClean( Cube ); }\ + else { Mvc_CubeNBitClean( Cube ); } +#define Mvc_CubeBitFill( Cube )\ + if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitFill( Cube ); }\ + else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitFill( Cube ); }\ + else { Mvc_CubeNBitFill( Cube ); } +#define Mvc_CubeBitNot( Cube )\ + if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitNot( Cube ); }\ + else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitNot( Cube ); }\ + else { Mvc_CubeNBitNot( Cube ); } +#define Mvc_CubeBitCopy( Cube1, Cube2 )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitCopy( Cube1, Cube2 ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitCopy( Cube1, Cube2 ); }\ + else { Mvc_CubeNBitCopy( Cube1, Cube2 ); } +#define Mvc_CubeBitOr( CubeR, Cube1, Cube2 )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitOr( CubeR, Cube1, Cube2 ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitOr( CubeR, Cube1, Cube2 ); }\ + else { Mvc_CubeNBitOr( CubeR, Cube1, Cube2 ); } +#define Mvc_CubeBitExor( CubeR, Cube1, Cube2 )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitExor( CubeR, Cube1, Cube2 ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitExor( CubeR, Cube1, Cube2 ); }\ + else { Mvc_CubeNBitExor( CubeR, Cube1, Cube2 ); } +#define Mvc_CubeBitAnd( CubeR, Cube1, Cube2 )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitAnd( CubeR, Cube1, Cube2 ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitAnd( CubeR, Cube1, Cube2 ); }\ + else { Mvc_CubeNBitAnd( CubeR, Cube1, Cube2 ); } +#define Mvc_CubeBitSharp( CubeR, Cube1, Cube2 )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitSharp( CubeR, Cube1, Cube2 ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitSharp( CubeR, Cube1, Cube2 ); }\ + else { Mvc_CubeNBitSharp( CubeR, Cube1, Cube2 ); } +#define Mvc_CubeBitEmpty( Res, Cube )\ + if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitEmpty( Res, Cube ); }\ + else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitEmpty( Res, Cube ); }\ + else { Mvc_CubeNBitEmpty( Res, Cube ); } +#define Mvc_CubeBitEqual( Res, Cube1, Cube2 )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqual( Res, Cube1, Cube2 ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqual( Res, Cube1, Cube2 ); }\ + else { Mvc_CubeNBitEqual( Res, Cube1, Cube2 ); } +#define Mvc_CubeBitLess( Res, Cube1, Cube2 )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitLess( Res, Cube1, Cube2 ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitLess( Res, Cube1, Cube2 ); }\ + else { Mvc_CubeNBitLess( Res, Cube1, Cube2 ); } +#define Mvc_CubeBitMore( Res, Cube1, Cube2 )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitMore( Res, Cube1, Cube2 ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitMore( Res, Cube1, Cube2 ); }\ + else { Mvc_CubeNBitMore( Res, Cube1, Cube2 ); } +#define Mvc_CubeBitNotImpl( Res, Cube1, Cube2 )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitNotImpl( Res, Cube1, Cube2 ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitNotImpl( Res, Cube1, Cube2 ); }\ + else { Mvc_CubeNBitNotImpl( Res, Cube1, Cube2 ); } +#define Mvc_CubeBitDisjoint( Res, Cube1, Cube2 )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitDisjoint( Res, Cube1, Cube2 ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitDisjoint( Res, Cube1, Cube2 ); }\ + else { Mvc_CubeNBitDisjoint( Res, Cube1, Cube2 ); } +#define Mvc_CubeBitEqualUnderMask( Res, Cube1, Cube2, Mask )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqualUnderMask( Res, Cube1, Cube2, Mask ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqualUnderMask( Res, Cube1, Cube2, Mask ); }\ + else { Mvc_CubeNBitEqualUnderMask( Res, Cube1, Cube2, Mask ); } +#define Mvc_CubeBitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }\ + else { Mvc_CubeNBitEqualOutsideMask( Res, Cube1, Cube2, Mask ); } +#define Mvc_CubeBitIntersectUnderMask( Res, Cube1, Cube2, Mask )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }\ + else { Mvc_CubeNBitIntersectUnderMask( Res, Cube1, Cube2, Mask ); } +#define Mvc_CubeBitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ + if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }\ + else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }\ + else { Mvc_CubeNBitNotImplUnderMask( Res, Cube1, Cube2, Mask ); } + + +// managing linked lists +#define Mvc_ListAddCubeHead( pList, pCube )\ + {\ + if ( pList->pHead == NULL )\ + {\ + Mvc_CubeSetNext( pCube, NULL );\ + pList->pHead = pCube;\ + pList->pTail = pCube;\ + }\ + else\ + {\ + Mvc_CubeSetNext( pCube, pList->pHead );\ + pList->pHead = pCube;\ + }\ + pList->nItems++;\ + } +#define Mvc_ListAddCubeTail( pList, pCube )\ + {\ + if ( pList->pHead == NULL )\ + pList->pHead = pCube;\ + else\ + Mvc_CubeSetNext( pList->pTail, pCube );\ + pList->pTail = pCube;\ + Mvc_CubeSetNext( pCube, NULL );\ + pList->nItems++;\ + } +#define Mvc_ListDeleteCube( pList, pPrev, pCube )\ +{\ + if ( pPrev == NULL )\ + pList->pHead = pCube->pNext;\ + else\ + pPrev->pNext = pCube->pNext;\ + if ( pList->pTail == pCube )\ + {\ + assert( pCube->pNext == NULL );\ + pList->pTail = pPrev;\ + }\ + pList->nItems--;\ +} + +// managing linked lists inside the cover +#define Mvc_CoverAddCubeHead( pCover, pCube )\ +{\ + Mvc_List_t * pList = &pCover->lCubes;\ + Mvc_ListAddCubeHead( pList, pCube );\ +} +#define Mvc_CoverAddCubeTail( pCover, pCube )\ +{\ + Mvc_List_t * pList = &pCover->lCubes;\ + Mvc_ListAddCubeTail( pList, pCube );\ +} +#define Mvc_CoverDeleteCube( pCover, pPrev, pCube )\ +{\ + Mvc_List_t * pList = &pCover->lCubes;\ + Mvc_ListDeleteCube( pList, pPrev, pCube );\ +} + + + + + + +// iterator through the cubes in the cube list +#define Mvc_ListForEachCube( List, Cube )\ + for ( Cube = List->pHead;\ + Cube;\ + Cube = Cube->pNext ) +#define Mvc_ListForEachCubeSafe( List, Cube, Cube2 )\ + for ( Cube = List->pHead, Cube2 = (Cube? Cube->pNext: NULL);\ + Cube;\ + Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) + +// iterator through cubes in the cover +#define Mvc_CoverForEachCube( Cover, Cube )\ + for ( Cube = (Cover)->lCubes.pHead;\ + Cube;\ + Cube = Cube->pNext ) +#define Mvc_CoverForEachCubeWithIndex( Cover, Cube, Index )\ + for ( Index = 0, Cube = (Cover)->lCubes.pHead;\ + Cube;\ + Index++, Cube = Cube->pNext ) +#define Mvc_CoverForEachCubeSafe( Cover, Cube, Cube2 )\ + for ( Cube = (Cover)->lCubes.pHead, Cube2 = (Cube? Cube->pNext: NULL);\ + Cube;\ + Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) + +// iterator which starts from the given cube +#define Mvc_CoverForEachCubeStart( Start, Cube )\ + for ( Cube = Start;\ + Cube;\ + Cube = Cube->pNext ) +#define Mvc_CoverForEachCubeStartSafe( Start, Cube, Cube2 )\ + for ( Cube = Start, Cube2 = (Cube? Cube->pNext: NULL);\ + Cube;\ + Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) + + +// iterator through literals of the cube +#define Mvc_CubeForEachBit( Cover, Cube, iBit, Value )\ + for ( iBit = 0;\ + iBit < Cover->nBits && ((Value = Mvc_CubeBitValue(Cube,iBit))>=0);\ + iBit++ ) +// iterator through values of binary variables +#define Mvc_CubeForEachVarValue( Cover, Cube, iVar, Value )\ + for ( iVar = 0;\ + iVar < Cover->nBits/2 && (Value = Mvc_CubeVarValue(Cube,iVar));\ + iVar++ ) + + +// macros which work with memory +// MEM_ALLOC: allocate the given number (Size) of items of type (Type) +// MEM_FREE: deallocate the pointer (Pointer) to the given number (Size) of items of type (Type) +#define MEM_ALLOC( Manager, Type, Size ) ((Type *)malloc( (Size) * sizeof(Type) )) +#define MEM_FREE( Manager, Type, Size, Pointer ) if ( Pointer ) { free(Pointer); Pointer = NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== mvcApi.c ====================================================*/ +extern int Mvc_CoverReadWordNum( Mvc_Cover_t * pCover ); +extern int Mvc_CoverReadBitNum( Mvc_Cover_t * pCover ); +extern int Mvc_CoverReadCubeNum( Mvc_Cover_t * pCover ); +extern Mvc_Cube_t * Mvc_CoverReadCubeHead( Mvc_Cover_t * pCover ); +extern Mvc_Cube_t * Mvc_CoverReadCubeTail( Mvc_Cover_t * pCover ); +extern Mvc_List_t * Mvc_CoverReadCubeList( Mvc_Cover_t * pCover ); +extern int Mvc_ListReadCubeNum( Mvc_List_t * pList ); +extern Mvc_Cube_t * Mvc_ListReadCubeHead( Mvc_List_t * pList ); +extern Mvc_Cube_t * Mvc_ListReadCubeTail( Mvc_List_t * pList ); +extern void Mvc_CoverSetCubeNum( Mvc_Cover_t * pCover,int nItems ); +extern void Mvc_CoverSetCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +extern void Mvc_CoverSetCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +extern void Mvc_CoverSetCubeList( Mvc_Cover_t * pCover, Mvc_List_t * pList ); +extern int Mvc_CoverIsEmpty( Mvc_Cover_t * pCover ); +extern int Mvc_CoverIsTautology( Mvc_Cover_t * pCover ); +extern int Mvc_CoverIsBinaryBuffer( Mvc_Cover_t * pCover ); +extern void Mvc_CoverMakeEmpty( Mvc_Cover_t * pCover ); +extern void Mvc_CoverMakeTautology( Mvc_Cover_t * pCover ); +extern Mvc_Cover_t * Mvc_CoverCreateEmpty( Mvc_Cover_t * pCover ); +extern Mvc_Cover_t * Mvc_CoverCreateTautology( Mvc_Cover_t * pCover ); +/*=== mvcCover.c ====================================================*/ +extern Mvc_Cover_t * Mvc_CoverAlloc( Mvc_Manager_t * pMem, int nBits ); +extern Mvc_Cover_t * Mvc_CoverCreateConst( Mvc_Manager_t * pMem, int nBits, int Phase ); +extern Mvc_Cover_t * Mvc_CoverClone( Mvc_Cover_t * pCover ); +extern Mvc_Cover_t * Mvc_CoverDup( Mvc_Cover_t * pCover ); +extern void Mvc_CoverFree( Mvc_Cover_t * pCover ); +extern void Mvc_CoverAllocateMask( Mvc_Cover_t * pCover ); +extern void Mvc_CoverAllocateArrayLits( Mvc_Cover_t * pCover ); +extern void Mvc_CoverAllocateArrayCubes( Mvc_Cover_t * pCover ); +extern void Mvc_CoverDeallocateMask( Mvc_Cover_t * pCover ); +extern void Mvc_CoverDeallocateArrayLits( Mvc_Cover_t * pCover ); +/*=== mvcCube.c ====================================================*/ +extern Mvc_Cube_t * Mvc_CubeAlloc( Mvc_Cover_t * pCover ); +extern Mvc_Cube_t * Mvc_CubeDup( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +extern void Mvc_CubeFree( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +extern void Mvc_CubeBitRemoveDcs( Mvc_Cube_t * pCube ); +/*=== mvcCompare.c ====================================================*/ +extern int Mvc_CubeCompareInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); +extern int Mvc_CubeCompareSizeAndInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); +extern int Mvc_CubeCompareIntUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); +extern int Mvc_CubeCompareIntOutsideMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); +extern int Mvc_CubeCompareIntOutsideAndUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); +/*=== mvcDd.c ====================================================*/ +/* +extern DdNode * Mvc_CoverConvertToBdd( DdManager * dd, Mvc_Cover_t * pCover ); +extern DdNode * Mvc_CoverConvertToZdd( DdManager * dd, Mvc_Cover_t * pCover ); +extern DdNode * Mvc_CoverConvertToZdd2( DdManager * dd, Mvc_Cover_t * pCover ); +extern DdNode * Mvc_CubeConvertToBdd( DdManager * dd, Mvc_Cube_t * pCube ); +extern DdNode * Mvc_CubeConvertToZdd( DdManager * dd, Mvc_Cube_t * pCube ); +extern DdNode * Mvc_CubeConvertToZdd2( DdManager * dd, Mvc_Cube_t * pCube ); +*/ +/*=== mvcDivisor.c ====================================================*/ +extern Mvc_Cover_t * Mvc_CoverDivisor( Mvc_Cover_t * pCover ); +/*=== mvcDivide.c ====================================================*/ +extern void Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); +extern void Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); +extern void Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); +extern void Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); +extern void Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit ); +/*=== mvcList.c ====================================================*/ +// these functions are available as macros +extern void Mvc_ListAddCubeHead_( Mvc_List_t * pList, Mvc_Cube_t * pCube ); +extern void Mvc_ListAddCubeTail_( Mvc_List_t * pList, Mvc_Cube_t * pCube ); +extern void Mvc_ListDeleteCube_( Mvc_List_t * pList, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ); +extern void Mvc_CoverAddCubeHead_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +extern void Mvc_CoverAddCubeTail_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +extern void Mvc_CoverDeleteCube_( Mvc_Cover_t * pCover, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ); +extern void Mvc_CoverAddDupCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +extern void Mvc_CoverAddDupCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +// other functions +extern void Mvc_CoverAddLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +extern void Mvc_CoverDeleteLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +extern void Mvc_CoverList2Array( Mvc_Cover_t * pCover ); +extern void Mvc_CoverArray2List( Mvc_Cover_t * pCover ); +extern Mvc_Cube_t * Mvc_ListGetTailFromHead( Mvc_Cube_t * pHead ); +/*=== mvcPrint.c ====================================================*/ +extern void Mvc_CoverPrint( Mvc_Cover_t * pCover ); +extern void Mvc_CubePrint( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +extern void Mvc_CoverPrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover ); +extern void Mvc_CubePrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); +/*=== mvcSort.c ====================================================*/ +extern void Mvc_CoverSort( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ); +/*=== mvcUtils.c ====================================================*/ +extern void Mvc_CoverSupport( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp ); +extern int Mvc_CoverSupportSizeBinary( Mvc_Cover_t * pCover ); +extern int Mvc_CoverSupportVarBelongs( Mvc_Cover_t * pCover, int iVar ); +extern void Mvc_CoverCommonCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pComCube ); +extern int Mvc_CoverIsCubeFree( Mvc_Cover_t * pCover ); +extern void Mvc_CoverMakeCubeFree( Mvc_Cover_t * pCover ); +extern Mvc_Cover_t * Mvc_CoverCommonCubeCover( Mvc_Cover_t * pCover ); +extern int Mvc_CoverCheckSuppContainment( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); +extern int Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover ); +extern int Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube ); +extern int Mvc_CoverCountCubePairDiffs( Mvc_Cover_t * pCover, unsigned char pDiffs[] ); +extern Mvc_Cover_t * Mvc_CoverRemap( Mvc_Cover_t * pCover, int * pVarsRem, int nVarsRem ); +extern void Mvc_CoverInverse( Mvc_Cover_t * pCover ); +extern Mvc_Cover_t * Mvc_CoverRemoveDontCareLits( Mvc_Cover_t * pCover ); +extern Mvc_Cover_t * Mvc_CoverCofactor( Mvc_Cover_t * pCover, int iValue, int iValueOther ); +extern Mvc_Cover_t * Mvc_CoverFlipVar( Mvc_Cover_t * pCover, int iValue0, int iValue1 ); +extern Mvc_Cover_t * Mvc_CoverUnivQuantify( Mvc_Cover_t * p, int iValueA0, int iValueA1, int iValueB0, int iValueB1 ); +extern Mvc_Cover_t ** Mvc_CoverCofactors( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar ); +extern int Mvr_CoverCountLitsWithValue( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar, int iValue ); +//extern Mvc_Cover_t * Mvc_CoverCreateExpanded( Mvc_Cover_t * pCover, Vm_VarMap_t * pVmNew ); +extern Mvc_Cover_t * Mvc_CoverTranspose( Mvc_Cover_t * pCover ); +extern int Mvc_UtilsCheckUnusedZeros( Mvc_Cover_t * pCover ); +/*=== mvcLits.c ====================================================*/ +extern int Mvc_CoverAnyLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ); +extern int Mvc_CoverBestLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ); +extern int Mvc_CoverWorstLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ); +extern Mvc_Cover_t * Mvc_CoverBestLiteralCover( Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ); +extern int Mvc_CoverFirstCubeFirstLit( Mvc_Cover_t * pCover ); +extern int Mvc_CoverCountLiterals( Mvc_Cover_t * pCover ); +extern int Mvc_CoverIsOneLiteral( Mvc_Cover_t * pCover ); +/*=== mvcOpAlg.c ====================================================*/ +extern Mvc_Cover_t * Mvc_CoverAlgebraicMultiply( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); +extern Mvc_Cover_t * Mvc_CoverAlgebraicSubtract( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); +extern int Mvc_CoverAlgebraicEqual( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); +/*=== mvcOpBool.c ====================================================*/ +extern Mvc_Cover_t * Mvc_CoverBooleanOr( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); +extern Mvc_Cover_t * Mvc_CoverBooleanAnd( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); +extern int Mvc_CoverBooleanEqual( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); + +/*=== mvcContain.c ====================================================*/ +extern int Mvc_CoverContain( Mvc_Cover_t * pCover ); +/*=== mvcTau.c ====================================================*/ +extern int Mvc_CoverTautology( Mvc_Data_t * p, Mvc_Cover_t * pCover ); +/*=== mvcCompl.c ====================================================*/ +extern Mvc_Cover_t * Mvc_CoverComplement( Mvc_Data_t * p, Mvc_Cover_t * pCover ); +/*=== mvcSharp.c ====================================================*/ +extern Mvc_Cover_t * Mvc_CoverSharp( Mvc_Data_t * p, Mvc_Cover_t * pA, Mvc_Cover_t * pB ); +extern int Mvc_CoverDist0Cubes( Mvc_Data_t * pData, Mvc_Cube_t * pA, Mvc_Cube_t * pB ); +extern void Mvc_CoverIntersectCubes( Mvc_Data_t * pData, Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); +extern int Mvc_CoverIsIntersecting( Mvc_Data_t * pData, Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); +extern void Mvc_CoverAppendCubes( Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); +extern void Mvc_CoverCopyAndAppendCubes( Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); +extern void Mvc_CoverRemoveCubes( Mvc_Cover_t * pC ); + +/*=== mvcReshape.c ====================================================*/ +extern void Mvc_CoverMinimizeByReshape( Mvc_Data_t * pData, Mvc_Cover_t * pCover ); + +/*=== mvcMerge.c ====================================================*/ +extern void Mvc_CoverDist1Merge( Mvc_Data_t * p, Mvc_Cover_t * pCover ); + +/*=== mvcData.c ====================================================*/ +//extern Mvc_Data_t * Mvc_CoverDataAlloc( Vm_VarMap_t * pVm, Mvc_Cover_t * pCover ); +//extern void Mvc_CoverDataFree( Mvc_Data_t * p, Mvc_Cover_t * pCover ); + +/*=== mvcMan.c ====================================================*/ +extern void Mvc_ManagerFree( Mvc_Manager_t * p ); +extern Mvc_Manager_t * Mvc_ManagerStart(); +extern Mvc_Manager_t * Mvc_ManagerAllocCover(); +extern Mvc_Manager_t * Mvc_ManagerAllocCube( int nWords ); +extern Mvc_Manager_t * Mvc_ManagerFreeCover( Mvc_Cover_t * pCover ); +extern Mvc_Manager_t * Mvc_ManagerFreeCube( Mvc_Cover_t * pCube, int nWords ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/misc/mvc/mvcApi.c b/abc70930/src/misc/mvc/mvcApi.c new file mode 100644 index 00000000..eb942f93 --- /dev/null +++ b/abc70930/src/misc/mvc/mvcApi.c @@ -0,0 +1,233 @@ +/**CFile**************************************************************** + + FileName [mvcApi.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcApi.c,v 1.4 2003/04/03 06:31:48 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverReadWordNum( Mvc_Cover_t * pCover ) { return pCover->nWords; } +int Mvc_CoverReadBitNum( Mvc_Cover_t * pCover ) { return pCover->nBits; } +int Mvc_CoverReadCubeNum( Mvc_Cover_t * pCover ) { return pCover->lCubes.nItems; } +Mvc_Cube_t * Mvc_CoverReadCubeHead( Mvc_Cover_t * pCover ) { return pCover->lCubes.pHead; } +Mvc_Cube_t * Mvc_CoverReadCubeTail( Mvc_Cover_t * pCover ) { return pCover->lCubes.pTail; } +Mvc_List_t * Mvc_CoverReadCubeList( Mvc_Cover_t * pCover ) { return &pCover->lCubes; } + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_ListReadCubeNum( Mvc_List_t * pList ) { return pList->nItems; } +Mvc_Cube_t * Mvc_ListReadCubeHead( Mvc_List_t * pList ) { return pList->pHead; } +Mvc_Cube_t * Mvc_ListReadCubeTail( Mvc_List_t * pList ) { return pList->pTail; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverSetCubeNum( Mvc_Cover_t * pCover,int nItems ) { pCover->lCubes.nItems = nItems; } +void Mvc_CoverSetCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { pCover->lCubes.pHead = pCube; } +void Mvc_CoverSetCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { pCover->lCubes.pTail = pCube; } +void Mvc_CoverSetCubeList( Mvc_Cover_t * pCover, Mvc_List_t * pList ) { pCover->lCubes = *pList; } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverIsEmpty( Mvc_Cover_t * pCover ) +{ + return Mvc_CoverReadCubeNum(pCover) == 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverIsTautology( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + int iBit, Value; + + if ( Mvc_CoverReadCubeNum(pCover) != 1 ) + return 0; + + pCube = Mvc_CoverReadCubeHead( pCover ); + Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) + if ( Value == 0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cover is a binary buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverIsBinaryBuffer( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + if ( pCover->nBits != 2 ) + return 0; + if ( Mvc_CoverReadCubeNum(pCover) != 1 ) + return 0; + pCube = pCover->lCubes.pHead; + if ( Mvc_CubeBitValue(pCube, 0) == 0 && Mvc_CubeBitValue(pCube, 1) == 1 ) + return 1; + return 0; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverMakeEmpty( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube, * pCube2; + Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 ) + Mvc_CubeFree( pCover, pCube ); + pCover->lCubes.nItems = 0; + pCover->lCubes.pHead = NULL; + pCover->lCubes.pTail = NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverMakeTautology( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCubeNew; + Mvc_CoverMakeEmpty( pCover ); + pCubeNew = Mvc_CubeAlloc( pCover ); + Mvc_CubeBitFill( pCubeNew ); + Mvc_CoverAddCubeTail( pCover, pCubeNew ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverCreateEmpty( Mvc_Cover_t * pCover ) +{ + Mvc_Cover_t * pCoverNew; + pCoverNew = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); + return pCoverNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverCreateTautology( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCubeNew; + Mvc_Cover_t * pCoverNew; + pCoverNew = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); + pCubeNew = Mvc_CubeAlloc( pCoverNew ); + Mvc_CubeBitFill( pCubeNew ); + Mvc_CoverAddCubeTail( pCoverNew, pCubeNew ); + return pCoverNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcCompare.c b/abc70930/src/misc/mvc/mvcCompare.c new file mode 100644 index 00000000..9cff99cd --- /dev/null +++ b/abc70930/src/misc/mvc/mvcCompare.c @@ -0,0 +1,369 @@ +/**CFile**************************************************************** + + FileName [mvcCompare.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Various cube comparison functions.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcCompare.c,v 1.5 2003/04/03 23:25:41 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Compares two cubes according to their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CubeCompareInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) +{ + if ( Mvc_Cube1Words(pC1) ) + { + if ( pC1->pData[0] < pC2->pData[0] ) + return -1; + if ( pC1->pData[0] > pC2->pData[0] ) + return 1; + return 0; + } + else if ( Mvc_Cube2Words(pC1) ) + { + if ( pC1->pData[1] < pC2->pData[1] ) + return -1; + if ( pC1->pData[1] > pC2->pData[1] ) + return 1; + if ( pC1->pData[0] < pC2->pData[0] ) + return -1; + if ( pC1->pData[0] > pC2->pData[0] ) + return 1; + return 0; + } + else + { + int i = Mvc_CubeReadLast(pC1); + for(; i >= 0; i--) + { + if ( pC1->pData[i] < pC2->pData[i] ) + return -1; + if ( pC1->pData[i] > pC2->pData[i] ) + return 1; + } + return 0; + } +} + + +/**Function************************************************************* + + Synopsis [Compares the cubes (1) by size, (2) by integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CubeCompareSizeAndInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) +{ + // compare the cubes by size + if ( Mvc_CubeReadSize( pC1 ) < Mvc_CubeReadSize( pC2 ) ) + return 1; + if ( Mvc_CubeReadSize( pC1 ) > Mvc_CubeReadSize( pC2 ) ) + return -1; + // the cubes have the same size + + // compare the cubes as integers + if ( Mvc_Cube1Words( pC1 ) ) + { + if ( pC1->pData[0] < pC2->pData[0] ) + return -1; + if ( pC1->pData[0] > pC2->pData[0] ) + return 1; + return 0; + } + else if ( Mvc_Cube2Words( pC1 ) ) + { + if ( pC1->pData[1] < pC2->pData[1] ) + return -1; + if ( pC1->pData[1] > pC2->pData[1] ) + return 1; + if ( pC1->pData[0] < pC2->pData[0] ) + return -1; + if ( pC1->pData[0] > pC2->pData[0] ) + return 1; + return 0; + } + else + { + int i = Mvc_CubeReadLast( pC1 ); + for(; i >= 0; i--) + { + if ( pC1->pData[i] < pC2->pData[i] ) + return -1; + if ( pC1->pData[i] > pC2->pData[i] ) + return 1; + } + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Compares two cubes under the mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CubeCompareIntUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) +{ + unsigned uBits1, uBits2; + + // compare the cubes under the mask + if ( Mvc_Cube1Words(pC1) ) + { + uBits1 = pC1->pData[0] & pMask->pData[0]; + uBits2 = pC2->pData[0] & pMask->pData[0]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + // cubes are equal + return 0; + } + else if ( Mvc_Cube2Words(pC1) ) + { + uBits1 = pC1->pData[1] & pMask->pData[1]; + uBits2 = pC2->pData[1] & pMask->pData[1]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + uBits1 = pC1->pData[0] & pMask->pData[0]; + uBits2 = pC2->pData[0] & pMask->pData[0]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + return 0; + } + else + { + int i = Mvc_CubeReadLast(pC1); + for(; i >= 0; i--) + { + uBits1 = pC1->pData[i] & pMask->pData[i]; + uBits2 = pC2->pData[i] & pMask->pData[i]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + } + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Compares two cubes under the mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CubeCompareIntOutsideMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) +{ + unsigned uBits1, uBits2; + + // compare the cubes under the mask + if ( Mvc_Cube1Words(pC1) ) + { + uBits1 = pC1->pData[0] | pMask->pData[0]; + uBits2 = pC2->pData[0] | pMask->pData[0]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + // cubes are equal + return 0; + } + else if ( Mvc_Cube2Words(pC1) ) + { + uBits1 = pC1->pData[1] | pMask->pData[1]; + uBits2 = pC2->pData[1] | pMask->pData[1]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + uBits1 = pC1->pData[0] | pMask->pData[0]; + uBits2 = pC2->pData[0] | pMask->pData[0]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + return 0; + } + else + { + int i = Mvc_CubeReadLast(pC1); + for(; i >= 0; i--) + { + uBits1 = pC1->pData[i] | pMask->pData[i]; + uBits2 = pC2->pData[i] | pMask->pData[i]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + } + return 0; + } +} + + +/**Function************************************************************* + + Synopsis [Compares the cubes (1) outside the mask, (2) under the mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CubeCompareIntOutsideAndUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) +{ + unsigned uBits1, uBits2; + + if ( Mvc_Cube1Words(pC1) ) + { + // compare the cubes outside the mask + uBits1 = pC1->pData[0] & ~(pMask->pData[0]); + uBits2 = pC2->pData[0] & ~(pMask->pData[0]); + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + + // compare the cubes under the mask + uBits1 = pC1->pData[0] & pMask->pData[0]; + uBits2 = pC2->pData[0] & pMask->pData[0]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + // cubes are equal + // should never happen + assert( 0 ); + return 0; + } + else if ( Mvc_Cube2Words(pC1) ) + { + // compare the cubes outside the mask + uBits1 = pC1->pData[1] & ~(pMask->pData[1]); + uBits2 = pC2->pData[1] & ~(pMask->pData[1]); + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + + uBits1 = pC1->pData[0] & ~(pMask->pData[0]); + uBits2 = pC2->pData[0] & ~(pMask->pData[0]); + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + + // compare the cubes under the mask + uBits1 = pC1->pData[1] & pMask->pData[1]; + uBits2 = pC2->pData[1] & pMask->pData[1]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + + uBits1 = pC1->pData[0] & pMask->pData[0]; + uBits2 = pC2->pData[0] & pMask->pData[0]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + + // cubes are equal + // should never happen + assert( 0 ); + return 0; + } + else + { + int i; + + // compare the cubes outside the mask + for( i = Mvc_CubeReadLast(pC1); i >= 0; i-- ) + { + uBits1 = pC1->pData[i] & ~(pMask->pData[i]); + uBits2 = pC2->pData[i] & ~(pMask->pData[i]); + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + } + // compare the cubes under the mask + for( i = Mvc_CubeReadLast(pC1); i >= 0; i-- ) + { + uBits1 = pC1->pData[i] & pMask->pData[i]; + uBits2 = pC2->pData[i] & pMask->pData[i]; + if ( uBits1 < uBits2 ) + return -1; + if ( uBits1 > uBits2 ) + return 1; + } +/* + { + Mvc_Cover_t * pCover; + pCover = Mvc_CoverAlloc( NULL, 96 ); + Mvc_CubePrint( pCover, pC1 ); + Mvc_CubePrint( pCover, pC2 ); + Mvc_CubePrint( pCover, pMask ); + } +*/ + // cubes are equal + // should never happen + assert( 0 ); + return 0; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcContain.c b/abc70930/src/misc/mvc/mvcContain.c new file mode 100644 index 00000000..a9eae06e --- /dev/null +++ b/abc70930/src/misc/mvc/mvcContain.c @@ -0,0 +1,173 @@ +/**CFile**************************************************************** + + FileName [mvcContain.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Making the cover single-cube containment free.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcContain.c,v 1.4 2003/04/03 23:25:42 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover ); +static void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Removes the contained cubes.] + + Description [Returns 1 if the cover has been changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverContain( Mvc_Cover_t * pCover ) +{ + int nCubes; + nCubes = Mvc_CoverReadCubeNum( pCover ); + if ( nCubes < 2 ) + return 0; + Mvc_CoverSetCubeSizes(pCover); + Mvc_CoverSort( pCover, NULL, Mvc_CubeCompareSizeAndInt ); + Mvc_CoverRemoveDuplicates( pCover ); + if ( nCubes > 1 ) + Mvc_CoverRemoveContained( pCover ); + return (nCubes != Mvc_CoverReadCubeNum(pCover)); +} + +/**Function************************************************************* + + Synopsis [Removes adjacent duplicated cubes from the cube list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pPrev, * pCube, * pCube2; + int fEqual; + + // set the first cube of the cover + pPrev = Mvc_CoverReadCubeHead(pCover); + // go through all the cubes after this one + Mvc_CoverForEachCubeStartSafe( Mvc_CubeReadNext(pPrev), pCube, pCube2 ) + { + // compare the current cube with the prev cube + Mvc_CubeBitEqual( fEqual, pPrev, pCube ); + if ( fEqual ) + { // they are equal - remove the current cube + Mvc_CoverDeleteCube( pCover, pPrev, pCube ); + Mvc_CubeFree( pCover, pCube ); + // don't change the previous cube cube + } + else + { // they are not equal - update the previous cube + pPrev = pCube; + } + } +} + +/**Function************************************************************* + + Synopsis [Removes contained cubes from the sorted cube list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCubeBeg, * pCubeEnd, * pCubeLarge; + Mvc_Cube_t * pCube, * pCube2, * pPrev; + unsigned sizeCur; + int Result; + + // since the cubes are sorted by size, it is sufficient + // to compare each cube with other cubes that have larger sizes + // if the given cube implies a larger cube, the larger cube is removed + pCubeBeg = Mvc_CoverReadCubeHead(pCover); + do + { + // get the current cube size + sizeCur = Mvc_CubeReadSize(pCubeBeg); + + // initialize the end of the given size group + pCubeEnd = pCubeBeg; + // find the beginning of the next size group + Mvc_CoverForEachCubeStart( Mvc_CubeReadNext(pCubeBeg), pCube ) + { + if ( sizeCur == Mvc_CubeReadSize(pCube) ) + pCubeEnd = pCube; + else // pCube is the first cube in the new size group + break; + } + // if we could not find the next size group + // the containment check is finished + if ( pCube == NULL ) + break; + // otherwise, pCubeBeg/pCubeEnd are the first/last cubes of the group + + // go through all the cubes between pCubeBeg and pCubeEnd, inclusive, + // and for each of them, try removing cubes after pCubeEnd + Mvc_CoverForEachCubeStart( pCubeBeg, pCubeLarge ) + { + pPrev = pCubeEnd; + Mvc_CoverForEachCubeStartSafe( Mvc_CubeReadNext(pCubeEnd), pCube, pCube2 ) + { + // check containment + Mvc_CubeBitNotImpl( Result, pCube, pCubeLarge ); + if ( !Result ) + { // pCubeLarge implies pCube - remove pCube + Mvc_CoverDeleteCube( pCover, pPrev, pCube ); + Mvc_CubeFree( pCover, pCube ); + // don't update the previous cube + } + else + { // update the previous cube + pPrev = pCube; + } + } + // quit, if the main cube was the last one of this size + if ( pCubeLarge == pCubeEnd ) + break; + } + + // set the beginning of the next group + pCubeBeg = Mvc_CubeReadNext(pCubeEnd); + } + while ( pCubeBeg ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcCover.c b/abc70930/src/misc/mvc/mvcCover.c new file mode 100644 index 00000000..d8584446 --- /dev/null +++ b/abc70930/src/misc/mvc/mvcCover.c @@ -0,0 +1,251 @@ +/**CFile**************************************************************** + + FileName [mvcCover.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Basic procedures to manipulate unate cube covers.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcCover.c,v 1.5 2003/04/09 18:02:05 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverAlloc( Mvc_Manager_t * pMem, int nBits ) +{ + Mvc_Cover_t * p; + int nBitsInUnsigned; + + nBitsInUnsigned = 8 * sizeof(Mvc_CubeWord_t); +#ifdef USE_SYSTEM_MEMORY_MANAGEMENT + p = (Mvc_Cover_t *)malloc( sizeof(Mvc_Cover_t) ); +#else + p = (Mvc_Cover_t *)Extra_MmFixedEntryFetch( pMem->pManC ); +#endif + p->pMem = pMem; + p->nBits = nBits; + p->nWords = nBits / nBitsInUnsigned + (int)(nBits % nBitsInUnsigned > 0); + p->nUnused = p->nWords * nBitsInUnsigned - p->nBits; + p->lCubes.nItems = 0; + p->lCubes.pHead = NULL; + p->lCubes.pTail = NULL; + p->nCubesAlloc = 0; + p->pCubes = NULL; + p->pMask = NULL; + p->pLits = NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverClone( Mvc_Cover_t * p ) +{ + Mvc_Cover_t * pCover; +#ifdef USE_SYSTEM_MEMORY_MANAGEMENT + pCover = (Mvc_Cover_t *)malloc( sizeof(Mvc_Cover_t) ); +#else + pCover = (Mvc_Cover_t *)Extra_MmFixedEntryFetch( p->pMem->pManC ); +#endif + pCover->pMem = p->pMem; + pCover->nBits = p->nBits; + pCover->nWords = p->nWords; + pCover->nUnused = p->nUnused; + pCover->lCubes.nItems = 0; + pCover->lCubes.pHead = NULL; + pCover->lCubes.pTail = NULL; + pCover->nCubesAlloc = 0; + pCover->pCubes = NULL; + pCover->pMask = NULL; + pCover->pLits = NULL; + return pCover; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverDup( Mvc_Cover_t * p ) +{ + Mvc_Cover_t * pCover; + Mvc_Cube_t * pCube, * pCubeCopy; + // clone the cover + pCover = Mvc_CoverClone( p ); + // copy the cube list + Mvc_CoverForEachCube( p, pCube ) + { + pCubeCopy = Mvc_CubeDup( p, pCube ); + Mvc_CoverAddCubeTail( pCover, pCubeCopy ); + } + return pCover; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverFree( Mvc_Cover_t * p ) +{ + Mvc_Cube_t * pCube, * pCube2; + // recycle cube list + Mvc_CoverForEachCubeSafe( p, pCube, pCube2 ) + Mvc_CubeFree( p, pCube ); + // recycle other pointers + Mvc_CubeFree( p, p->pMask ); + MEM_FREE( p->pMem, Mvc_Cube_t *, p->nCubesAlloc, p->pCubes ); + MEM_FREE( p->pMem, int, p->nBits, p->pLits ); + +#ifdef USE_SYSTEM_MEMORY_MANAGEMENT + free( p ); +#else + Extra_MmFixedEntryRecycle( p->pMem->pManC, (char *)p ); +#endif +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverAllocateMask( Mvc_Cover_t * pCover ) +{ + if ( pCover->pMask == NULL ) + pCover->pMask = Mvc_CubeAlloc( pCover ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverAllocateArrayLits( Mvc_Cover_t * pCover ) +{ + if ( pCover->pLits == NULL ) + pCover->pLits = MEM_ALLOC( pCover->pMem, int, pCover->nBits ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverAllocateArrayCubes( Mvc_Cover_t * pCover ) +{ + if ( pCover->nCubesAlloc < pCover->lCubes.nItems ) + { + if ( pCover->nCubesAlloc > 0 ) + MEM_FREE( pCover->pMem, Mvc_Cube_t *, pCover->nCubesAlloc, pCover->pCubes ); + pCover->nCubesAlloc = pCover->lCubes.nItems; + pCover->pCubes = MEM_ALLOC( pCover->pMem, Mvc_Cube_t *, pCover->nCubesAlloc ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverDeallocateMask( Mvc_Cover_t * pCover ) +{ + Mvc_CubeFree( pCover, pCover->pMask ); + pCover->pMask = NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverDeallocateArrayLits( Mvc_Cover_t * pCover ) +{ + if ( pCover->pLits ) + { + MEM_FREE( pCover->pMem, int, pCover->nBits, pCover->pLits ); + pCover->pLits = NULL; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcCube.c b/abc70930/src/misc/mvc/mvcCube.c new file mode 100644 index 00000000..e157879f --- /dev/null +++ b/abc70930/src/misc/mvc/mvcCube.c @@ -0,0 +1,175 @@ +/**CFile**************************************************************** + + FileName [mvcCube.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Manipulating unate cubes.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcCube.c,v 1.4 2003/04/03 06:31:49 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cube_t * Mvc_CubeAlloc( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + + assert( pCover->nWords >= 0 ); + // allocate the cube +#ifdef USE_SYSTEM_MEMORY_MANAGEMENT + if ( pCover->nWords == 0 ) + pCube = (Mvc_Cube_t *)malloc( sizeof(Mvc_Cube_t) ); + else + pCube = (Mvc_Cube_t *)malloc( sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) * (pCover->nWords - 1) ); +#else + switch( pCover->nWords ) + { + case 0: + case 1: + pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan1 ); + break; + case 2: + pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan2 ); + break; + case 3: + case 4: + pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan4 ); + break; + default: + pCube = (Mvc_Cube_t *)malloc( sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) * (pCover->nWords - 1) ); + break; + } +#endif + // set the parameters charactering this cube + if ( pCover->nWords == 0 ) + pCube->iLast = pCover->nWords; + else + pCube->iLast = pCover->nWords - 1; + pCube->nUnused = pCover->nUnused; + return pCube; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cube_t * Mvc_CubeDup( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) +{ + Mvc_Cube_t * pCubeCopy; + pCubeCopy = Mvc_CubeAlloc( pCover ); + Mvc_CubeBitCopy( pCubeCopy, pCube ); + return pCubeCopy; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CubeFree( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) +{ + if ( pCube == NULL ) + return; + + // verify the parameters charactering this cube + assert( pCube->iLast == 0 || ((int)pCube->iLast) == pCover->nWords - 1 ); + assert( ((int)pCube->nUnused) == pCover->nUnused ); + + // deallocate the cube +#ifdef USE_SYSTEM_MEMORY_MANAGEMENT + free( pCube ); +#else + switch( pCover->nWords ) + { + case 0: + case 1: + Extra_MmFixedEntryRecycle( pCover->pMem->pMan1, (char *)pCube ); + break; + case 2: + Extra_MmFixedEntryRecycle( pCover->pMem->pMan2, (char *)pCube ); + break; + case 3: + case 4: + Extra_MmFixedEntryRecycle( pCover->pMem->pMan4, (char *)pCube ); + break; + default: + free( pCube ); + break; + } +#endif +} + + +/**Function************************************************************* + + Synopsis [Removes the don't-care variable from the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CubeBitRemoveDcs( Mvc_Cube_t * pCube ) +{ + unsigned Mask; + int i; + for ( i = Mvc_CubeReadLast(pCube); i >= 0; i-- ) + { + // detect those variables that are different (not DCs) + Mask = (pCube->pData[i] ^ (pCube->pData[i] >> 1)) & BITS_DISJOINT; + // create the mask of all that are different + Mask |= (Mask << 1); + // remove other bits from the set + pCube->pData[i] &= Mask; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcDivide.c b/abc70930/src/misc/mvc/mvcDivide.c new file mode 100644 index 00000000..03643dcf --- /dev/null +++ b/abc70930/src/misc/mvc/mvcDivide.c @@ -0,0 +1,436 @@ +/**CFile**************************************************************** + + FileName [mvcDivide.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Procedures for algebraic division.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcDivide.c,v 1.5 2003/04/26 20:41:36 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem ); + +int s_fVerbose = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) +{ + // check the number of cubes + if ( Mvc_CoverReadCubeNum( pCover ) < Mvc_CoverReadCubeNum( pDiv ) ) + { + *ppQuo = NULL; + *ppRem = NULL; + return; + } + + // make sure that support of pCover contains that of pDiv + if ( !Mvc_CoverCheckSuppContainment( pCover, pDiv ) ) + { + *ppQuo = NULL; + *ppRem = NULL; + return; + } + + // perform the general division + Mvc_CoverDivideInternal( pCover, pDiv, ppQuo, ppRem ); +} + + +/**Function************************************************************* + + Synopsis [Merge the cubes inside the groups.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) +{ + Mvc_Cover_t * pQuo, * pRem; + Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy; + Mvc_Cube_t * pCube1, * pCube2; + int * pGroups, nGroups; // the cube groups + int nCubesC, nCubesD, nMerges, iCubeC, iCubeD, iMerge; + int fSkipG, GroupSize, g, c, RetValue; + int nCubes; + + // get cover sizes + nCubesD = Mvc_CoverReadCubeNum( pDiv ); + nCubesC = Mvc_CoverReadCubeNum( pCover ); + + // check trivial cases + if ( nCubesD == 1 ) + { + if ( Mvc_CoverIsOneLiteral( pDiv ) ) + Mvc_CoverDivideByLiteral( pCover, pDiv, ppQuo, ppRem ); + else + Mvc_CoverDivideByCube( pCover, pDiv, ppQuo, ppRem ); + return; + } + + // create the divisor and the remainder + pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); + pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); + + // get the support of the divisor + Mvc_CoverAllocateMask( pDiv ); + Mvc_CoverSupport( pDiv, pDiv->pMask ); + + // sort the cubes of the divisor + Mvc_CoverSort( pDiv, NULL, Mvc_CubeCompareInt ); + // sort the cubes of the cover + Mvc_CoverSort( pCover, pDiv->pMask, Mvc_CubeCompareIntOutsideAndUnderMask ); + + // allocate storage for cube groups + pGroups = MEM_ALLOC( pCover->pMem, int, nCubesC + 1 ); + + // mask contains variables in the support of Div + // split the cubes into groups using the mask + Mvc_CoverList2Array( pCover ); + Mvc_CoverList2Array( pDiv ); + pGroups[0] = 0; + nGroups = 1; + for ( c = 1; c < nCubesC; c++ ) + { + // get the cubes + pCube1 = pCover->pCubes[c-1]; + pCube2 = pCover->pCubes[c ]; + // compare the cubes + Mvc_CubeBitEqualOutsideMask( RetValue, pCube1, pCube2, pDiv->pMask ); + if ( !RetValue ) + pGroups[nGroups++] = c; + } + // finish off the last group + pGroups[nGroups] = nCubesC; + + // consider each group separately and decide + // whether it can produce a quotient cube + nCubes = 0; + for ( g = 0; g < nGroups; g++ ) + { + // if the group has less than nCubesD cubes, + // there is no way it can produce the quotient cube + // copy the cubes to the remainder + GroupSize = pGroups[g+1] - pGroups[g]; + if ( GroupSize < nCubesD ) + { + for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) + { + pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] ); + Mvc_CoverAddCubeTail( pRem, pCubeCopy ); + nCubes++; + } + continue; + } + + // mark the cubes as those that should be added to the remainder + for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) + Mvc_CubeSetSize( pCover->pCubes[c], 1 ); + + // go through the cubes in the group and at the same time + // go through the cubes in the divisor + iCubeD = 0; + iCubeC = 0; + pCubeD = pDiv->pCubes[iCubeD++]; + pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; + fSkipG = 0; + nMerges = 0; + + while ( 1 ) + { + // compare the topmost cubes in F and in D + RetValue = Mvc_CubeCompareIntUnderMask( pCubeC, pCubeD, pDiv->pMask ); + // cube are ordered in increasing order of their int value + if ( RetValue == -1 ) // pCubeC is above pCubeD + { // cube in C should be added to the remainder + // check that there is enough cubes in the group + if ( GroupSize - iCubeC < nCubesD - nMerges ) + { + fSkipG = 1; + break; + } + // get the next cube in the cover + pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; + continue; + } + if ( RetValue == 1 ) // pCubeD is above pCubeC + { // given cube in D does not have a corresponding cube in the cover + fSkipG = 1; + break; + } + // mark the cube as the one that should NOT be added to the remainder + Mvc_CubeSetSize( pCubeC, 0 ); + // remember this merged cube + iMerge = iCubeC-1; + nMerges++; + + // stop if we considered the last cube of the group + if ( iCubeD == nCubesD ) + break; + + // advance the cube of the divisor + assert( iCubeD < nCubesD ); + pCubeD = pDiv->pCubes[iCubeD++]; + + // advance the cube of the group + assert( pGroups[g]+iCubeC < nCubesC ); + pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; + } + + if ( fSkipG ) + { + // the group has failed, add all the cubes to the remainder + for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) + { + pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] ); + Mvc_CoverAddCubeTail( pRem, pCubeCopy ); + nCubes++; + } + continue; + } + + // the group has worked, add left-over cubes to the remainder + for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) + { + pCubeC = pCover->pCubes[c]; + if ( Mvc_CubeReadSize(pCubeC) ) + { + pCubeCopy = Mvc_CubeDup( pRem, pCubeC ); + Mvc_CoverAddCubeTail( pRem, pCubeCopy ); + nCubes++; + } + } + + // create the quotient cube + pCube1 = Mvc_CubeAlloc( pQuo ); + Mvc_CubeBitSharp( pCube1, pCover->pCubes[pGroups[g]+iMerge], pDiv->pMask ); + // add the cube to the quotient + Mvc_CoverAddCubeTail( pQuo, pCube1 ); + nCubes += nCubesD; + } + assert( nCubes == nCubesC ); + + // deallocate the memory + MEM_FREE( pCover->pMem, int, nCubesC + 1, pGroups ); + + // return the results + *ppRem = pRem; + *ppQuo = pQuo; +// Mvc_CoverVerifyDivision( pCover, pDiv, pQuo, pRem ); +} + + +/**Function************************************************************* + + Synopsis [Divides the cover by a cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) +{ + Mvc_Cover_t * pQuo, * pRem; + Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy; + int CompResult; + + // get the only cube of D + assert( Mvc_CoverReadCubeNum(pDiv) == 1 ); + + // start the quotient and the remainder + pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); + pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); + + // get the first and only cube of the divisor + pCubeD = Mvc_CoverReadCubeHead( pDiv ); + + // iterate through the cubes in the cover + Mvc_CoverForEachCube( pCover, pCubeC ) + { + // check the containment of literals from pCubeD in pCube + Mvc_Cube2BitNotImpl( CompResult, pCubeD, pCubeC ); + if ( !CompResult ) + { // this cube belongs to the quotient + // alloc the cube + pCubeCopy = Mvc_CubeAlloc( pQuo ); + // clean the support of D + Mvc_CubeBitSharp( pCubeCopy, pCubeC, pCubeD ); + // add the cube to the quotient + Mvc_CoverAddCubeTail( pQuo, pCubeCopy ); + } + else + { + // copy the cube + pCubeCopy = Mvc_CubeDup( pRem, pCubeC ); + // add the cube to the remainder + Mvc_CoverAddCubeTail( pRem, pCubeCopy ); + } + } + // return the results + *ppRem = pRem; + *ppQuo = pQuo; +} + +/**Function************************************************************* + + Synopsis [Divides the cover by a literal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) +{ + Mvc_Cover_t * pQuo, * pRem; + Mvc_Cube_t * pCubeC, * pCubeCopy; + int iLit; + + // get the only cube of D + assert( Mvc_CoverReadCubeNum(pDiv) == 1 ); + + // start the quotient and the remainder + pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); + pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); + + // get the first and only literal in the divisor cube + iLit = Mvc_CoverFirstCubeFirstLit( pDiv ); + + // iterate through the cubes in the cover + Mvc_CoverForEachCube( pCover, pCubeC ) + { + // copy the cube + pCubeCopy = Mvc_CubeDup( pCover, pCubeC ); + // add the cube to the quotient or to the remainder depending on the literal + if ( Mvc_CubeBitValue( pCubeCopy, iLit ) ) + { // remove the literal + Mvc_CubeBitRemove( pCubeCopy, iLit ); + // add the cube ot the quotient + Mvc_CoverAddCubeTail( pQuo, pCubeCopy ); + } + else + { // add the cube ot the remainder + Mvc_CoverAddCubeTail( pRem, pCubeCopy ); + } + } + // return the results + *ppRem = pRem; + *ppQuo = pQuo; +} + + +/**Function************************************************************* + + Synopsis [Derives the quotient of division by literal.] + + Description [Reduces the cover to be the equal to the result of + division of the given cover by the literal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit ) +{ + Mvc_Cube_t * pCube, * pCube2, * pPrev; + // delete those cubes that do not have this literal + // remove this literal from other cubes + pPrev = NULL; + Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 ) + { + if ( Mvc_CubeBitValue( pCube, iLit ) == 0 ) + { // delete the cube from the cover + Mvc_CoverDeleteCube( pCover, pPrev, pCube ); + Mvc_CubeFree( pCover, pCube ); + // don't update the previous cube + } + else + { // delete this literal from the cube + Mvc_CubeBitRemove( pCube, iLit ); + // update the previous cube + pPrev = pCube; + } + } +} + + +/**Function************************************************************* + + Synopsis [Verifies that the result of algebraic division is correct.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem ) +{ + Mvc_Cover_t * pProd; + Mvc_Cover_t * pDiff; + + pProd = Mvc_CoverAlgebraicMultiply( pDiv, pQuo ); + pDiff = Mvc_CoverAlgebraicSubtract( pCover, pProd ); + + if ( Mvc_CoverAlgebraicEqual( pDiff, pRem ) ) + printf( "Verification OKAY!\n" ); + else + { + printf( "Verification FAILED!\n" ); + printf( "pCover:\n" ); + Mvc_CoverPrint( pCover ); + printf( "pDiv:\n" ); + Mvc_CoverPrint( pDiv ); + printf( "pRem:\n" ); + Mvc_CoverPrint( pRem ); + printf( "pQuo:\n" ); + Mvc_CoverPrint( pQuo ); + } + + Mvc_CoverFree( pProd ); + Mvc_CoverFree( pDiff ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcDivisor.c b/abc70930/src/misc/mvc/mvcDivisor.c new file mode 100644 index 00000000..ecdea75b --- /dev/null +++ b/abc70930/src/misc/mvc/mvcDivisor.c @@ -0,0 +1,90 @@ +/**CFile**************************************************************** + + FileName [mvcDivisor.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Procedures for compute the quick divisor.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcDivisor.c,v 1.1 2003/04/03 15:34:08 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the quick divisor of the cover.] + + Description [Returns NULL, if there is not divisor other than + trivial.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverDivisor( Mvc_Cover_t * pCover ) +{ + Mvc_Cover_t * pKernel; + if ( Mvc_CoverReadCubeNum(pCover) <= 1 ) + return NULL; + // allocate the literal array and count literals + if ( Mvc_CoverAnyLiteral( pCover, NULL ) == -1 ) + return NULL; + // duplicate the cover + pKernel = Mvc_CoverDup(pCover); + // perform the kerneling + Mvc_CoverDivisorZeroKernel( pKernel ); + assert( Mvc_CoverReadCubeNum(pKernel) ); + return pKernel; +} + +/**Function************************************************************* + + Synopsis [Computes a level-zero kernel.] + + Description [Modifies the cover to contain one level-zero kernel.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover ) +{ + int iLit; + // find any literal that occurs at least two times +// iLit = Mvc_CoverAnyLiteral( pCover, NULL ); + iLit = Mvc_CoverWorstLiteral( pCover, NULL ); +// iLit = Mvc_CoverBestLiteral( pCover, NULL ); + if ( iLit == -1 ) + return; + // derive the cube-free quotient + Mvc_CoverDivideByLiteralQuo( pCover, iLit ); // the same cover + Mvc_CoverMakeCubeFree( pCover ); // the same cover + // call recursively + Mvc_CoverDivisorZeroKernel( pCover ); // the same cover +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcList.c b/abc70930/src/misc/mvc/mvcList.c new file mode 100644 index 00000000..8a82f911 --- /dev/null +++ b/abc70930/src/misc/mvc/mvcList.c @@ -0,0 +1,362 @@ +/**CFile**************************************************************** + + FileName [mvcList.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Manipulating list of cubes in the cover.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcList.c,v 1.4 2003/04/03 06:31:50 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_ListAddCubeHead_( Mvc_List_t * pList, Mvc_Cube_t * pCube ) +{ + if ( pList->pHead == NULL ) + { + Mvc_CubeSetNext( pCube, NULL ); + pList->pHead = pCube; + pList->pTail = pCube; + } + else + { + Mvc_CubeSetNext( pCube, pList->pHead ); + pList->pHead = pCube; + } + pList->nItems++; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_ListAddCubeTail_( Mvc_List_t * pList, Mvc_Cube_t * pCube ) +{ + if ( pList->pHead == NULL ) + pList->pHead = pCube; + else + Mvc_CubeSetNext( pList->pTail, pCube ); + pList->pTail = pCube; + Mvc_CubeSetNext( pCube, NULL ); + pList->nItems++; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_ListDeleteCube_( Mvc_List_t * pList, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ) +{ + if ( pPrev == NULL ) // deleting the head cube + pList->pHead = Mvc_CubeReadNext(pCube); + else + pPrev->pNext = pCube->pNext; + if ( pList->pTail == pCube ) // deleting the tail cube + { + assert( Mvc_CubeReadNext(pCube) == NULL ); + pList->pTail = pPrev; + } + pList->nItems--; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverAddCubeHead_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) +{ + Mvc_List_t * pList = &pCover->lCubes; + if ( pList->pHead == NULL ) + { + Mvc_CubeSetNext( pCube, NULL ); + pList->pHead = pCube; + pList->pTail = pCube; + } + else + { + Mvc_CubeSetNext( pCube, pList->pHead ); + pList->pHead = pCube; + } + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverAddCubeTail_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) +{ + Mvc_List_t * pList = &pCover->lCubes; + + if ( pList->pHead == NULL ) + pList->pHead = pCube; + else + Mvc_CubeSetNext( pList->pTail, pCube ); + pList->pTail = pCube; + Mvc_CubeSetNext( pCube, NULL ); + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverDeleteCube_( Mvc_Cover_t * pCover, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ) +{ + Mvc_List_t * pList = &pCover->lCubes; + + if ( pPrev == NULL ) // deleting the head cube + pList->pHead = Mvc_CubeReadNext(pCube); + else + pPrev->pNext = pCube->pNext; + if ( pList->pTail == pCube ) // deleting the tail cube + { + assert( Mvc_CubeReadNext(pCube) == NULL ); + pList->pTail = pPrev; + } + pList->nItems--; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverAddDupCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) +{ + Mvc_Cube_t * pCubeNew; + pCubeNew = Mvc_CubeAlloc( pCover ); + Mvc_CubeBitCopy( pCubeNew, pCube ); + Mvc_CoverAddCubeHead( pCover, pCubeNew ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverAddDupCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) +{ + Mvc_Cube_t * pCubeNew; + // copy the cube as part of this cover + pCubeNew = Mvc_CubeAlloc( pCover ); + Mvc_CubeBitCopy( pCubeNew, pCube ); + // clean the last bits of the new cube +// pCubeNew->pData[pCubeNew->iLast] &= (BITS_FULL >> pCubeNew->nUnused); + // add the cube at the end + Mvc_CoverAddCubeTail( pCover, pCubeNew ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverAddLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) +{ +// int iBit, Value; +// assert( pCover->pLits ); +// Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) +// if ( Value ) +// pCover->pLits[iBit] += Value; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverDeleteLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) +{ +// int iBit, Value; +// assert( pCover->pLits ); +// Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) +// if ( Value ) +// pCover->pLits[iBit] -= Value; +} + + +/**Function************************************************************* + + Synopsis [Transfers the cubes from the list into the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverList2Array( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + int Counter; + // resize storage if necessary + Mvc_CoverAllocateArrayCubes( pCover ); + // iterate through the cubes + Counter = 0; + Mvc_CoverForEachCube( pCover, pCube ) + pCover->pCubes[ Counter++ ] = pCube; + assert( Counter == Mvc_CoverReadCubeNum(pCover) ); +} + +/**Function************************************************************* + + Synopsis [Transfers the cubes from the array into list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverArray2List( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + int nCubes, i; + + assert( pCover->pCubes ); + + nCubes = Mvc_CoverReadCubeNum(pCover); + if ( nCubes == 0 ) + return; + if ( nCubes == 1 ) + { + pCube = pCover->pCubes[0]; + pCube->pNext = NULL; + pCover->lCubes.pHead = pCover->lCubes.pTail = pCube; + return; + } + // set up the first cube + pCube = pCover->pCubes[0]; + pCover->lCubes.pHead = pCube; + // set up the last cube + pCube = pCover->pCubes[nCubes-1]; + pCube->pNext = NULL; + pCover->lCubes.pTail = pCube; + + // link all cubes starting from the first one + for ( i = 0; i < nCubes - 1; i++ ) + pCover->pCubes[i]->pNext = pCover->pCubes[i+1]; +} + +/**Function************************************************************* + + Synopsis [Returns the tail of the linked list given by the head.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cube_t * Mvc_ListGetTailFromHead( Mvc_Cube_t * pHead ) +{ + Mvc_Cube_t * pCube, * pTail; + for ( pTail = pCube = pHead; + pCube; + pTail = pCube, pCube = Mvc_CubeReadNext(pCube) ); + return pTail; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcLits.c b/abc70930/src/misc/mvc/mvcLits.c new file mode 100644 index 00000000..910158e9 --- /dev/null +++ b/abc70930/src/misc/mvc/mvcLits.c @@ -0,0 +1,345 @@ +/**CFile**************************************************************** + + FileName [mvcLits.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Literal counting/updating procedures.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcLits.c,v 1.4 2003/04/03 06:31:50 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find the any literal that occurs more than once.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverAnyLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ) +{ + Mvc_Cube_t * pCube; + int nWord, nBit, i; + int nLitsCur; + int fUseFirst = 0; + + // go through each literal + if ( fUseFirst ) + { + for ( i = 0; i < pCover->nBits; i++ ) + if ( !pMask || Mvc_CubeBitValue(pMask,i) ) + { + // get the word and bit of this literal + nWord = Mvc_CubeWhichWord(i); + nBit = Mvc_CubeWhichBit(i); + // go through all the cubes + nLitsCur = 0; + Mvc_CoverForEachCube( pCover, pCube ) + if ( pCube->pData[nWord] & (1< 1 ) + return i; + } + } + } + else + { + for ( i = pCover->nBits - 1; i >=0; i-- ) + if ( !pMask || Mvc_CubeBitValue(pMask,i) ) + { + // get the word and bit of this literal + nWord = Mvc_CubeWhichWord(i); + nBit = Mvc_CubeWhichBit(i); + // go through all the cubes + nLitsCur = 0; + Mvc_CoverForEachCube( pCover, pCube ) + if ( pCube->pData[nWord] & (1< 1 ) + return i; + } + } + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Find the most often occurring literal.] + + Description [Find the most often occurring literal among those + that occur more than once.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverBestLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ) +{ + Mvc_Cube_t * pCube; + int nWord, nBit; + int i, iMax, nLitsMax, nLitsCur; + int fUseFirst = 1; + + // go through each literal + iMax = -1; + nLitsMax = -1; + for ( i = 0; i < pCover->nBits; i++ ) + if ( !pMask || Mvc_CubeBitValue(pMask,i) ) + { + // get the word and bit of this literal + nWord = Mvc_CubeWhichWord(i); + nBit = Mvc_CubeWhichBit(i); + // go through all the cubes + nLitsCur = 0; + Mvc_CoverForEachCube( pCover, pCube ) + if ( pCube->pData[nWord] & (1< 1 ) + return iMax; + return -1; +} + +/**Function************************************************************* + + Synopsis [Find the most often occurring literal.] + + Description [Find the most often occurring literal among those + that occur more than once.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverWorstLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ) +{ + Mvc_Cube_t * pCube; + int nWord, nBit; + int i, iMin, nLitsMin, nLitsCur; + int fUseFirst = 1; + + // go through each literal + iMin = -1; + nLitsMin = 1000000; + for ( i = 0; i < pCover->nBits; i++ ) + if ( !pMask || Mvc_CubeBitValue(pMask,i) ) + { + // get the word and bit of this literal + nWord = Mvc_CubeWhichWord(i); + nBit = Mvc_CubeWhichBit(i); + // go through all the cubes + nLitsCur = 0; + Mvc_CoverForEachCube( pCover, pCube ) + if ( pCube->pData[nWord] & (1< nLitsCur ) + { + nLitsMin = nLitsCur; + iMin = i; + } + } + else + { + if ( nLitsMin >= nLitsCur ) + { + nLitsMin = nLitsCur; + iMin = i; + } + } + } + + if ( nLitsMin < 1000000 ) + return iMin; + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverBestLiteralCover( Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ) +{ + Mvc_Cover_t * pCoverNew; + Mvc_Cube_t * pCubeNew; + Mvc_Cube_t * pCubeS; + int iLitBest; + + // create the new cover + pCoverNew = Mvc_CoverClone( pCover ); + // get the new cube + pCubeNew = Mvc_CubeAlloc( pCoverNew ); + // clean the cube + Mvc_CubeBitClean( pCubeNew ); + + // get the first cube of pSimple + assert( Mvc_CoverReadCubeNum(pSimple) == 1 ); + pCubeS = Mvc_CoverReadCubeHead( pSimple ); + // find the best literal among those of pCubeS + iLitBest = Mvc_CoverBestLiteral( pCover, pCubeS ); + + // insert this literal into the cube + Mvc_CubeBitInsert( pCubeNew, iLitBest ); + // add the cube to the cover + Mvc_CoverAddCubeTail( pCoverNew, pCubeNew ); + return pCoverNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverFirstCubeFirstLit( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + int iBit, Value; + + // get the first cube + pCube = Mvc_CoverReadCubeHead( pCover ); + // get the first literal + Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) + if ( Value ) + return iBit; + return -1; +} + +/**Function************************************************************* + + Synopsis [Returns the number of literals in the cover.] + + Description [Allocates storage for literal counters and fills it up + using the current information.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverCountLiterals( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + int nWord, nBit; + int i, CounterTot, CounterCur; + + // allocate/clean the storage for literals +// Mvc_CoverAllocateArrayLits( pCover ); +// memset( pCover->pLits, 0, pCover->nBits * sizeof(int) ); + // go through each literal + CounterTot = 0; + for ( i = 0; i < pCover->nBits; i++ ) + { + // get the word and bit of this literal + nWord = Mvc_CubeWhichWord(i); + nBit = Mvc_CubeWhichBit(i); + // go through all the cubes + CounterCur = 0; + Mvc_CoverForEachCube( pCover, pCube ) + if ( pCube->pData[nWord] & (1< +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Manager_t * Mvc_ManagerStart() +{ + Mvc_Manager_t * p; + p = ALLOC( Mvc_Manager_t, 1 ); + memset( p, 0, sizeof(Mvc_Manager_t) ); + p->pMan1 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) ); + p->pMan2 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) ); + p->pMan4 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) + 3 * sizeof(Mvc_CubeWord_t) ); + p->pManC = Extra_MmFixedStart( sizeof(Mvc_Cover_t) ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_ManagerFree( Mvc_Manager_t * p ) +{ + Extra_MmFixedStop( p->pMan1 ); + Extra_MmFixedStop( p->pMan2 ); + Extra_MmFixedStop( p->pMan4 ); + Extra_MmFixedStop( p->pManC ); + free( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcOpAlg.c b/abc70930/src/misc/mvc/mvcOpAlg.c new file mode 100644 index 00000000..65c02fa5 --- /dev/null +++ b/abc70930/src/misc/mvc/mvcOpAlg.c @@ -0,0 +1,163 @@ +/**CFile**************************************************************** + + FileName [mvcOperAlg.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Miscellaneous operations on covers.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcOpAlg.c,v 1.4 2003/04/26 20:41:36 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Multiplies two disjoint-support covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverAlgebraicMultiply( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) +{ + Mvc_Cover_t * pCover; + Mvc_Cube_t * pCube1, * pCube2, * pCube; + int CompResult; + + // covers should be the same base + assert( pCover1->nBits == pCover2->nBits ); + // make sure that supports do not overlap + Mvc_CoverAllocateMask( pCover1 ); + Mvc_CoverAllocateMask( pCover2 ); + Mvc_CoverSupport( pCover1, pCover1->pMask ); + Mvc_CoverSupport( pCover2, pCover2->pMask ); + // check if the cubes are bit-wise disjoint + Mvc_CubeBitDisjoint( CompResult, pCover1->pMask, pCover2->pMask ); + if ( !CompResult ) + printf( "Mvc_CoverMultiply(): Cover supports are not disjoint!\n" ); + + // iterate through the cubes + pCover = Mvc_CoverClone( pCover1 ); + Mvc_CoverForEachCube( pCover1, pCube1 ) + Mvc_CoverForEachCube( pCover2, pCube2 ) + { + // create the product cube + pCube = Mvc_CubeAlloc( pCover ); + // set the product cube equal to the product of the two cubes + Mvc_CubeBitOr( pCube, pCube1, pCube2 ); + // add the cube to the cover + Mvc_CoverAddCubeTail( pCover, pCube ); + } + return pCover; +} + + +/**Function************************************************************* + + Synopsis [Subtracts the second cover from the first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverAlgebraicSubtract( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) +{ + Mvc_Cover_t * pCover; + Mvc_Cube_t * pCube1, * pCube2, * pCube; + int fFound; + int CompResult; + + // covers should be the same base + assert( pCover1->nBits == pCover2->nBits ); + + // iterate through the cubes + pCover = Mvc_CoverClone( pCover1 ); + Mvc_CoverForEachCube( pCover1, pCube1 ) + { + fFound = 0; + Mvc_CoverForEachCube( pCover2, pCube2 ) + { + Mvc_CubeBitEqual( CompResult, pCube1, pCube2 ); + if ( CompResult ) + { + fFound = 1; + break; + } + } + if ( !fFound ) + { + // create the copy of the cube + pCube = Mvc_CubeDup( pCover, pCube1 ); + // add the cube copy to the cover + Mvc_CoverAddCubeTail( pCover, pCube ); + } + } + return pCover; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverAlgebraicEqual( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) +{ + Mvc_Cube_t * pCube1, * pCube2; + int fFound; + int CompResult; + + // covers should be the same base + assert( pCover1->nBits == pCover2->nBits ); + // iterate through the cubes + Mvc_CoverForEachCube( pCover1, pCube1 ) + { + fFound = 0; + Mvc_CoverForEachCube( pCover2, pCube2 ) + { + Mvc_CubeBitEqual( CompResult, pCube1, pCube2 ); + if ( CompResult ) + { + fFound = 1; + break; + } + } + if ( !fFound ) + return 0; + } + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcOpBool.c b/abc70930/src/misc/mvc/mvcOpBool.c new file mode 100644 index 00000000..0b34f1de --- /dev/null +++ b/abc70930/src/misc/mvc/mvcOpBool.c @@ -0,0 +1,151 @@ +/**CFile**************************************************************** + + FileName [mvcProc.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Various boolean procedures working with covers.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcOpBool.c,v 1.4 2003/04/16 01:55:37 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverBooleanOr( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) +{ + Mvc_Cover_t * pCover; + Mvc_Cube_t * pCube, * pCubeCopy; + // make sure the covers are compatible + assert( pCover1->nBits == pCover2->nBits ); + // clone the cover + pCover = Mvc_CoverClone( pCover1 ); + // create the cubes by making pair-wise products + // of cubes in pCover1 and pCover2 + Mvc_CoverForEachCube( pCover1, pCube ) + { + pCubeCopy = Mvc_CubeDup( pCover, pCube ); + Mvc_CoverAddCubeTail( pCover, pCubeCopy ); + } + Mvc_CoverForEachCube( pCover2, pCube ) + { + pCubeCopy = Mvc_CubeDup( pCover, pCube ); + Mvc_CoverAddCubeTail( pCover, pCubeCopy ); + } + return pCover; +} + +#if 0 + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverBooleanAnd( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) +{ + Mvc_Cover_t * pCover; + Mvc_Cube_t * pCube1, * pCube2, * pCubeCopy; + // make sure the covers are compatible + assert( pCover1->nBits == pCover2->nBits ); + // clone the cover + pCover = Mvc_CoverClone( pCover1 ); + // create the cubes by making pair-wise products + // of cubes in pCover1 and pCover2 + Mvc_CoverForEachCube( pCover1, pCube1 ) + { + Mvc_CoverForEachCube( pCover2, pCube2 ) + { + if ( Mvc_CoverDist0Cubes( p, pCube1, pCube2 ) ) + { + pCubeCopy = Mvc_CubeAlloc( pCover ); + Mvc_CubeBitAnd( pCubeCopy, pCube1, pCube2 ); + Mvc_CoverAddCubeTail( pCover, pCubeCopy ); + } + } + // if the number of cubes in the new cover is too large + // try compressing them + if ( Mvc_CoverReadCubeNum( pCover ) > 500 ) + Mvc_CoverContain( pCover ); + } + return pCover; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the two covers are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverBooleanEqual( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) +{ + Mvc_Cover_t * pSharp; + + pSharp = Mvc_CoverSharp( p, pCover1, pCover2 ); + if ( Mvc_CoverReadCubeNum( pSharp ) ) + { +Mvc_CoverContain( pSharp ); +printf( "Sharp \n" ); +Mvc_CoverPrint( pSharp ); + Mvc_CoverFree( pSharp ); + return 0; + } + Mvc_CoverFree( pSharp ); + + pSharp = Mvc_CoverSharp( p, pCover2, pCover1 ); + if ( Mvc_CoverReadCubeNum( pSharp ) ) + { +Mvc_CoverContain( pSharp ); +printf( "Sharp \n" ); +Mvc_CoverPrint( pSharp ); + Mvc_CoverFree( pSharp ); + return 0; + } + Mvc_CoverFree( pSharp ); + + return 1; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcPrint.c b/abc70930/src/misc/mvc/mvcPrint.c new file mode 100644 index 00000000..52ac76b3 --- /dev/null +++ b/abc70930/src/misc/mvc/mvcPrint.c @@ -0,0 +1,220 @@ +/**CFile**************************************************************** + + FileName [mvcPrint.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Printing cubes and covers.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcPrint.c,v 1.6 2003/04/09 18:02:06 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" +//#include "vm.h" +//#include "vmInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverPrint( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + int i; + // print general statistics + printf( "The cover contains %d cubes (%d bits and %d words)\n", + pCover->lCubes.nItems, pCover->nBits, pCover->nWords ); + // iterate through the cubes + Mvc_CoverForEachCube( pCover, pCube ) + Mvc_CubePrint( pCover, pCube ); + + if ( pCover->pLits ) + { + for ( i = 0; i < pCover->nBits; i++ ) + printf( " %d", pCover->pLits[i] ); + printf( "\n" ); + } + printf( "End of cover printout\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CubePrint( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) +{ + int iBit, Value; + // iterate through the literals +// printf( "Size = %2d ", Mvc_CubeReadSize(pCube) ); + Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) + printf( "%c", '0' + Value ); + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverPrintBinary( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + int i; + // print general statistics + printf( "The cover contains %d cubes (%d bits and %d words)\n", + pCover->lCubes.nItems, pCover->nBits, pCover->nWords ); + // iterate through the cubes + Mvc_CoverForEachCube( pCover, pCube ) + Mvc_CubePrintBinary( pCover, pCube ); + + if ( pCover->pLits ) + { + for ( i = 0; i < pCover->nBits; i++ ) + printf( " %d", pCover->pLits[i] ); + printf( "\n" ); + } + printf( "End of cover printout\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) +{ + int iVar, Value; + // iterate through the literals +// printf( "Size = %2d ", Mvc_CubeReadSize(pCube) ); + Mvc_CubeForEachVarValue( pCover, pCube, iVar, Value ) + { + assert( Value != 0 ); + if ( Value == 3 ) + printf( "-" ); + else if ( Value == 1 ) + printf( "0" ); + else + printf( "1" ); + } + printf( "\n" ); +} + +#if 0 + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverPrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + int i; + // print general statistics + printf( "The cover contains %d cubes (%d bits and %d words)\n", + pCover->lCubes.nItems, pCover->nBits, pCover->nWords ); + // iterate through the cubes + Mvc_CoverForEachCube( pCover, pCube ) + Mvc_CubePrintMv( pData, pCover, pCube ); + + if ( pCover->pLits ) + { + for ( i = 0; i < pCover->nBits; i++ ) + printf( " %d", pCover->pLits[i] ); + printf( "\n" ); + } + printf( "End of cover printout\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CubePrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) +{ + int iLit, iVar; + // iterate through the literals + printf( "Size = %2d ", Mvc_CubeReadSize(pCube) ); + iVar = 0; + for ( iLit = 0; iLit < pData->pVm->nValuesIn; iLit++ ) + { + if ( iLit == pData->pVm->pValuesFirst[iVar+1] ) + { + printf( " " ); + iVar++; + } + if ( Mvc_CubeBitValue( pCube, iLit ) ) + printf( "%c", '0' + iLit - pData->pVm->pValuesFirst[iVar] ); + else + printf( "-" ); + } + printf( "\n" ); +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcSort.c b/abc70930/src/misc/mvc/mvcSort.c new file mode 100644 index 00000000..3c975cb3 --- /dev/null +++ b/abc70930/src/misc/mvc/mvcSort.c @@ -0,0 +1,141 @@ +/**CFile**************************************************************** + + FileName [mvcSort.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Sorting cubes in the cover with the mask.] + + Author [MVSIS Group] + + Affiliation [uC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcSort.c,v 1.5 2003/04/27 01:03:45 wjiang Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ); +Mvc_Cube_t * Mvc_CoverSortMerge( Mvc_Cube_t * pList1, Mvc_Cube_t * pList2, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ); + +//////////////////////////////////////////////////////////////////////// +/// FuNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sorts cubes using the given cost function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverSort( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ) +{ + Mvc_Cube_t * pHead; + int nCubes; + // one cube does not need sorting + nCubes = Mvc_CoverReadCubeNum(pCover); + if ( nCubes <= 1 ) + return; + // sort the cubes + pHead = Mvc_CoverSort_rec( Mvc_CoverReadCubeHead(pCover), nCubes, pMask, pCompareFunc ); + // insert the sorted list into the cover + Mvc_CoverSetCubeHead( pCover, pHead ); + Mvc_CoverSetCubeTail( pCover, Mvc_ListGetTailFromHead(pHead) ); + // make sure that the list is sorted in the increasing order + assert( pCompareFunc( Mvc_CoverReadCubeHead(pCover), Mvc_CoverReadCubeTail(pCover), pMask ) <= 0 ); +} + +/**Function************************************************************* + + Synopsis [Recursive part of Mvc_CoverSort()] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ) +{ + Mvc_Cube_t * pList1, * pList2; + int nItems1, nItems2, i; + + // trivial case + if ( nItems == 1 ) + { + Mvc_CubeSetNext( pList, NULL ); + return pList; + } + + // select the new sizes + nItems1 = nItems/2; + nItems2 = nItems - nItems1; + + // set the new beginnings + pList1 = pList2 = pList; + for ( i = 0; i < nItems1; i++ ) + pList2 = Mvc_CubeReadNext( pList2 ); + + // solve recursively + pList1 = Mvc_CoverSort_rec( pList1, nItems1, pMask, pCompareFunc ); + pList2 = Mvc_CoverSort_rec( pList2, nItems2, pMask, pCompareFunc ); + + // merge + return Mvc_CoverSortMerge( pList1, pList2, pMask, pCompareFunc ); +} + + +/**Function************************************************************* + + Synopsis [Merges two NULL-terminated linked lists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cube_t * Mvc_CoverSortMerge( Mvc_Cube_t * pList1, Mvc_Cube_t * pList2, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ) +{ + Mvc_Cube_t * pList = NULL, ** ppTail = &pList; + Mvc_Cube_t * pCube; + while ( pList1 && pList2 ) + { + if ( pCompareFunc( pList1, pList2, pMask ) < 0 ) + { + pCube = pList1; + pList1 = Mvc_CubeReadNext(pList1); + } + else + { + pCube = pList2; + pList2 = Mvc_CubeReadNext(pList2); + } + *ppTail = pCube; + ppTail = Mvc_CubeReadNextP(pCube); + } + *ppTail = pList1? pList1: pList2; + return pList; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/mvc/mvcUtils.c b/abc70930/src/misc/mvc/mvcUtils.c new file mode 100644 index 00000000..4b13b23d --- /dev/null +++ b/abc70930/src/misc/mvc/mvcUtils.c @@ -0,0 +1,868 @@ +/**CFile**************************************************************** + + FileName [mvcUtils.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Various cover handling utilities.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: mvcUtils.c,v 1.7 2003/04/26 20:41:36 alanmi Exp $] + +***********************************************************************/ + +#include "mvc.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int bit_count[256] = { + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 +}; + + +static void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNew, int iColOld, int iColNew ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverSupport( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp ) +{ + Mvc_Cube_t * pCube; + // clean the support + Mvc_CubeBitClean( pSupp ); + // collect the support + Mvc_CoverForEachCube( pCover, pCube ) + Mvc_CubeBitOr( pSupp, pSupp, pCube ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverSupportAnd( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp ) +{ + Mvc_Cube_t * pCube; + // clean the support + Mvc_CubeBitFill( pSupp ); + // collect the support + Mvc_CoverForEachCube( pCover, pCube ) + Mvc_CubeBitAnd( pSupp, pSupp, pCube ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverSupportSizeBinary( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pSupp; + int Counter, i, v0, v1; + // compute the support + pSupp = Mvc_CubeAlloc( pCover ); + Mvc_CoverSupportAnd( pCover, pSupp ); + Counter = pCover->nBits/2; + for ( i = 0; i < pCover->nBits/2; i++ ) + { + v0 = Mvc_CubeBitValue( pSupp, 2*i ); + v1 = Mvc_CubeBitValue( pSupp, 2*i+1 ); + if ( v0 && v1 ) + Counter--; + } + Mvc_CubeFree( pCover, pSupp ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverSupportVarBelongs( Mvc_Cover_t * pCover, int iVar ) +{ + Mvc_Cube_t * pSupp; + int RetValue, v0, v1; + // compute the support + pSupp = Mvc_CubeAlloc( pCover ); + Mvc_CoverSupportAnd( pCover, pSupp ); + v0 = Mvc_CubeBitValue( pSupp, 2*iVar ); + v1 = Mvc_CubeBitValue( pSupp, 2*iVar+1 ); + RetValue = (int)( !v0 || !v1 ); + Mvc_CubeFree( pCover, pSupp ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverCommonCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pComCube ) +{ + Mvc_Cube_t * pCube; + // clean the support + Mvc_CubeBitFill( pComCube ); + // collect the support + Mvc_CoverForEachCube( pCover, pCube ) + Mvc_CubeBitAnd( pComCube, pComCube, pCube ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverIsCubeFree( Mvc_Cover_t * pCover ) +{ + int Result; + // get the common cube + Mvc_CoverAllocateMask( pCover ); + Mvc_CoverCommonCube( pCover, pCover->pMask ); + // check whether the common cube is empty + Mvc_CubeBitEmpty( Result, pCover->pMask ); + return Result; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverMakeCubeFree( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + // get the common cube + Mvc_CoverAllocateMask( pCover ); + Mvc_CoverCommonCube( pCover, pCover->pMask ); + // remove this cube from the cubes in the cover + Mvc_CoverForEachCube( pCover, pCube ) + Mvc_CubeBitSharp( pCube, pCube, pCover->pMask ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverCommonCubeCover( Mvc_Cover_t * pCover ) +{ + Mvc_Cover_t * pRes; + Mvc_Cube_t * pCube; + // create the new cover + pRes = Mvc_CoverClone( pCover ); + // get the new cube + pCube = Mvc_CubeAlloc( pRes ); + // get the common cube + Mvc_CoverCommonCube( pCover, pCube ); + // add the cube to the cover + Mvc_CoverAddCubeTail( pRes, pCube ); + return pRes; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the support of cover2 is contained in the support of cover1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverCheckSuppContainment( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) +{ + int Result; + assert( pCover1->nBits == pCover2->nBits ); + // set the supports + Mvc_CoverAllocateMask( pCover1 ); + Mvc_CoverSupport( pCover1, pCover1->pMask ); + Mvc_CoverAllocateMask( pCover2 ); + Mvc_CoverSupport( pCover2, pCover2->pMask ); + // check the containment + Mvc_CubeBitNotImpl( Result, pCover2->pMask, pCover1->pMask ); + return !Result; +} + +/**Function************************************************************* + + Synopsis [Counts the cube sizes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover ) +{ + Mvc_Cube_t * pCube; + unsigned char * pByte, * pByteStart, * pByteStop; + int nBytes, nOnes; + + // get the number of unsigned chars in the cube's bit strings + nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0); + // iterate through the cubes + Mvc_CoverForEachCube( pCover, pCube ) + { + // clean the counter of ones + nOnes = 0; + // set the starting and stopping positions + pByteStart = (unsigned char *)pCube->pData; + pByteStop = pByteStart + nBytes; + // iterate through the positions + for ( pByte = pByteStart; pByte < pByteStop; pByte++ ) + nOnes += bit_count[*pByte]; + // set the nOnes + Mvc_CubeSetSize( pCube, nOnes ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Counts the cube sizes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube ) +{ + unsigned char * pByte, * pByteStart, * pByteStop; + int nOnes, nBytes, nBits; + // get the number of unsigned chars in the cube's bit strings + nBits = (pCube->iLast + 1) * sizeof(Mvc_CubeWord_t) * 8 - pCube->nUnused; + nBytes = nBits / (8 * sizeof(unsigned char)) + (int)(nBits % (8 * sizeof(unsigned char)) > 0); + // clean the counter of ones + nOnes = 0; + // set the starting and stopping positions + pByteStart = (unsigned char *)pCube->pData; + pByteStop = pByteStart + nBytes; + // iterate through the positions + for ( pByte = pByteStart; pByte < pByteStop; pByte++ ) + nOnes += bit_count[*pByte]; + return nOnes; +} + +/**Function************************************************************* + + Synopsis [Counts the differences in each cube pair in the cover.] + + Description [Takes the cover (pCover) and the array where the + diff counters go (pDiffs). The array pDiffs should have as many + entries as there are different pairs of cubes in the cover: n(n-1)/2. + Fills out the array pDiffs with the following info: For each cube + pair, included in the array is the number of literals in both cubes + after they are made cube free.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvc_CoverCountCubePairDiffs( Mvc_Cover_t * pCover, unsigned char pDiffs[] ) +{ + Mvc_Cube_t * pCube1; + Mvc_Cube_t * pCube2; + Mvc_Cube_t * pMask; + unsigned char * pByte, * pByteStart, * pByteStop; + int nBytes, nOnes; + int nCubePairs; + + // allocate a temporary mask + pMask = Mvc_CubeAlloc( pCover ); + // get the number of unsigned chars in the cube's bit strings + nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0); + // iterate through the cubes + nCubePairs = 0; + Mvc_CoverForEachCube( pCover, pCube1 ) + { + Mvc_CoverForEachCubeStart( Mvc_CubeReadNext(pCube1), pCube2 ) + { + // find the bit-wise exor of cubes + Mvc_CubeBitExor( pMask, pCube1, pCube2 ); + // set the starting and stopping positions + pByteStart = (unsigned char *)pMask->pData; + pByteStop = pByteStart + nBytes; + // clean the counter of ones + nOnes = 0; + // iterate through the positions + for ( pByte = pByteStart; pByte < pByteStop; pByte++ ) + nOnes += bit_count[*pByte]; + // set the nOnes + pDiffs[nCubePairs++] = nOnes; + } + } + // deallocate the mask + Mvc_CubeFree( pCover, pMask ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Creates a new cover containing some literals of the old cover.] + + Description [Creates the new cover containing the given number (nVarsRem) + literals of the old cover. All the bits of the new cover are initialized + to "1". The selected bits from the old cover are copied on top. The numbers + of the selected bits to copy are given in the array pVarsRem. The i-set + entry in this array is the index of the bit in the old cover which goes + to the i-th place in the new cover. If the i-th entry in pVarsRem is -1, + it means that the i-th bit does not change (remains composed of all 1's). + This is a useful feature to speed up remapping covers, which are known + to depend only on a subset of input variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverRemap( Mvc_Cover_t * p, int * pVarsRem, int nVarsRem ) +{ + Mvc_Cover_t * pCover; + Mvc_Cube_t * pCube, * pCubeCopy; + int i; + // clone the cover + pCover = Mvc_CoverAlloc( p->pMem, nVarsRem ); + // copy the cube list + Mvc_CoverForEachCube( p, pCube ) + { + pCubeCopy = Mvc_CubeAlloc( pCover ); + //Mvc_CubeBitClean( pCubeCopy ); //changed by wjiang + Mvc_CubeBitFill( pCubeCopy ); //changed by wjiang + Mvc_CoverAddCubeTail( pCover, pCubeCopy ); + } + // copy the corresponding columns + for ( i = 0; i < nVarsRem; i++ ) + { + if (pVarsRem[i] < 0) + continue; //added by wjiang + assert( pVarsRem[i] >= 0 && pVarsRem[i] < p->nBits ); + Mvc_CoverCopyColumn( p, pCover, pVarsRem[i], i ); + } + return pCover; +} + +/**Function************************************************************* + + Synopsis [Copies a column from the old cover to the new cover.] + + Description [Copies the column (iColOld) of the old cover (pCoverOld) + into the column (iColNew) of the new cover (pCoverNew). Assumes that + the number of cubes is the same in both covers. Makes no assuptions + about the current contents of the column in the new cover.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNew, + int iColOld, int iColNew ) +{ + Mvc_Cube_t * pCubeOld, * pCubeNew; + int iWordOld, iWordNew, iBitOld, iBitNew; + + assert( Mvc_CoverReadCubeNum(pCoverOld) == Mvc_CoverReadCubeNum(pCoverNew) ); + + // get the place of the old and new columns + iWordOld = Mvc_CubeWhichWord(iColOld); + iBitOld = Mvc_CubeWhichBit(iColOld); + iWordNew = Mvc_CubeWhichWord(iColNew); + iBitNew = Mvc_CubeWhichBit(iColNew); + + // go through the cubes of both covers + pCubeNew = Mvc_CoverReadCubeHead(pCoverNew); + Mvc_CoverForEachCube( pCoverOld, pCubeOld ) + { + if ( pCubeOld->pData[iWordOld] & (1<pData[iWordNew] |= (1<pData[iWordNew] &= ~(1<pVm, iVar); + nValues = Vm_VarMapReadValues(pData->pVm, iVar); + ppCofs = ALLOC( Mvc_Cover_t *, nValues + 1 ); + for ( i = 0; i <= nValues; i++ ) + ppCofs[i] = Mvc_CoverClone( pCover ); + + // go through the cubes + Mvc_CoverForEachCube( pCover, pCube ) + { + // if the literal if a full literal, add it to last "cofactor" + Mvc_CubeBitEqualUnderMask( Res, pCube, pData->ppMasks[iVar], pData->ppMasks[iVar] ); + if ( Res ) + { + pCubeNew = Mvc_CubeDup(pCover, pCube); + Mvc_CoverAddCubeTail( ppCofs[nValues], pCubeNew ); + continue; + } + + // otherwise, add it to separate values + for ( i = 0; i < nValues; i++ ) + if ( Mvc_CubeBitValue( pCube, iValueFirst + i ) ) + { + pCubeNew = Mvc_CubeDup(pCover, pCube); + Mvc_CubeBitOr( pCubeNew, pCubeNew, pData->ppMasks[iVar] ); + Mvc_CoverAddCubeTail( ppCofs[i], pCubeNew ); + } + } + return ppCofs; +} + +/**Function************************************************************* + + Synopsis [Count the cubes with non-trivial literals with the given value.] + + Description [The data and the cover are given (pData, pCover). Also given + are the variable number and the number of a value of this variable. + This procedure returns the number of cubes having a non-trivial literal + of this variable that have the given value present.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mvr_CoverCountLitsWithValue( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar, int iValue ) +{ + Mvc_Cube_t * pCube; + int iValueFirst, Res, Counter; + + Counter = 0; + iValueFirst = Vm_VarMapReadValuesFirst( pData->pVm, iVar ); + Mvc_CoverForEachCube( pCover, pCube ) + { + // check if the given literal is the full literal + Mvc_CubeBitEqualUnderMask( Res, pCube, pData->ppMasks[iVar], pData->ppMasks[iVar] ); + if ( Res ) + continue; + // this literal is not a full literal; check if it has this value + Counter += Mvc_CubeBitValue( pCube, iValueFirst + iValue ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Creates the expanded cover.] + + Description [The original cover is expanded by adding some variables. + These variables are the additional variables in pVmNew, compared to + pCvr->pVm. The resulting cover is the same as the original one, except + that it contains the additional variables present as full literals + in every cube.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverCreateExpanded( Mvc_Cover_t * pCover, Vm_VarMap_t * pVmNew ) +{ + Mvc_Cover_t * pCoverNew; + Mvc_Cube_t * pCube, * pCubeNew; + int i, iLast, iLastNew; + + // create the new cover + pCoverNew = Mvc_CoverAlloc( pCover->pMem, Vm_VarMapReadValuesInNum(pVmNew) ); + + // get the cube composed of extra bits + Mvc_CoverAllocateMask( pCoverNew ); + Mvc_CubeBitClean( pCoverNew->pMask ); + for ( i = pCover->nBits; i < pCoverNew->nBits; i++ ) + Mvc_CubeBitInsert( pCoverNew->pMask, i ); + + // get the indexes of the last words in both covers + iLast = pCover->nWords? pCover->nWords - 1: 0; + iLastNew = pCoverNew->nWords? pCoverNew->nWords - 1: 0; + + // create the cubes of the new cover + Mvc_CoverForEachCube( pCover, pCube ) + { + pCubeNew = Mvc_CubeAlloc( pCoverNew ); + Mvc_CubeBitClean( pCubeNew ); + // copy the bits (cannot immediately use Mvc_CubeBitCopy, + // because covers have different numbers of bits) + Mvc_CubeSetLast( pCubeNew, iLast ); + Mvc_CubeBitCopy( pCubeNew, pCube ); + Mvc_CubeSetLast( pCubeNew, iLastNew ); + // add the extra bits + Mvc_CubeBitOr( pCubeNew, pCubeNew, pCoverNew->pMask ); + // add the cube to the new cover + Mvc_CoverAddCubeTail( pCoverNew, pCubeNew ); + } + return pCoverNew; +} + +#endif + +/**Function************************************************************* + + Synopsis [Transposes the cube cover.] + + Description [Returns the cube cover that looks like a transposed + matrix, compared to the matrix derived from the original cover.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Mvc_CoverTranspose( Mvc_Cover_t * pCover ) +{ + Mvc_Cover_t * pRes; + Mvc_Cube_t * pCubeRes, * pCube; + int nWord, nBit, i, iCube; + + pRes = Mvc_CoverAlloc( pCover->pMem, Mvc_CoverReadCubeNum(pCover) ); + for ( i = 0; i < pCover->nBits; i++ ) + { + // get the word and bit of this literal + nWord = Mvc_CubeWhichWord(i); + nBit = Mvc_CubeWhichBit(i); + // get the transposed cube + pCubeRes = Mvc_CubeAlloc( pRes ); + Mvc_CubeBitClean( pCubeRes ); + iCube = 0; + Mvc_CoverForEachCube( pCover, pCube ) + { + if ( pCube->pData[nWord] & (1<nUnused == 0 ) + continue; + + Unsigned = ( pCube->pData[pCube->iLast] & + (BITS_FULL << (32-pCube->nUnused)) ); + if( Unsigned ) + { + printf( "Cube %2d out of %2d contains dirty bits.\n", nCubes, + Mvc_CoverReadCubeNum(pCover) ); + } + nCubes++; + } + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/nm/module.make b/abc70930/src/misc/nm/module.make new file mode 100644 index 00000000..2a3820c7 --- /dev/null +++ b/abc70930/src/misc/nm/module.make @@ -0,0 +1,2 @@ +SRC += src/misc/nm/nmApi.c \ + src/misc/nm/nmTable.c diff --git a/abc70930/src/misc/nm/nm.h b/abc70930/src/misc/nm/nm.h new file mode 100644 index 00000000..c6344bbf --- /dev/null +++ b/abc70930/src/misc/nm/nm.h @@ -0,0 +1,92 @@ +/**CFilextern e**************************************************************** + + FileName [nm.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Name manager.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nm.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __NM_H__ +#define __NM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + This manager is designed to store ID-to-name and name-to-ID mapping + for Boolean networks and And-Inverter Graphs. + + In a netlist, net names are unique. In this case, there is a one-to-one + mapping between IDs and names. + + In a logic network, which do not have nets, several objects may have + the same name. For example, a latch output and a primary output. + Another example, a primary input and an input to a black box. + In this case, for each ID on an object there is only one name, + but for each name may be several IDs of objects having this name. + + The name manager maps ID-to-name uniquely but it allows one name to + be mapped into several IDs. When a query to find an ID of the object + by its name is submitted, it is possible to specify the object type, + which will help select one of several IDs. If the type is -1, and + there is more than one object with the given name, any object with + the given name is returned. +*/ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Nm_Man_t_ Nm_Man_t; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== nmApi.c ==========================================================*/ +extern Nm_Man_t * Nm_ManCreate( int nSize ); +extern void Nm_ManFree( Nm_Man_t * p ); +extern int Nm_ManNumEntries( Nm_Man_t * p ); +extern char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix ); +extern void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId ); +extern char * Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId ); +extern char * Nm_ManFindNameById( Nm_Man_t * p, int ObjId ); +extern int Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type ); +extern int Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 ); +extern Vec_Int_t * Nm_ManReturnNameIds( Nm_Man_t * p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/misc/nm/nmApi.c b/abc70930/src/misc/nm/nmApi.c new file mode 100644 index 00000000..9165922f --- /dev/null +++ b/abc70930/src/misc/nm/nmApi.c @@ -0,0 +1,272 @@ +/**CFile**************************************************************** + + FileName [nmApi.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Name manager.] + + Synopsis [APIs of the name manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nmApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nmInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the name manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nm_Man_t * Nm_ManCreate( int nSize ) +{ + Nm_Man_t * p; + // allocate the table + p = ALLOC( Nm_Man_t, 1 ); + memset( p, 0, sizeof(Nm_Man_t) ); + // set the parameters + p->nSizeFactor = 2; // determined the limit on the grow of data before the table resizes + p->nGrowthFactor = 3; // determined how much the table grows after resizing + // allocate and clean the bins + p->nBins = Cudd_PrimeNm(nSize); + p->pBinsI2N = ALLOC( Nm_Entry_t *, p->nBins ); + p->pBinsN2I = ALLOC( Nm_Entry_t *, p->nBins ); + memset( p->pBinsI2N, 0, sizeof(Nm_Entry_t *) * p->nBins ); + memset( p->pBinsN2I, 0, sizeof(Nm_Entry_t *) * p->nBins ); + // start the memory manager + p->pMem = Extra_MmFlexStart(); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the name manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nm_ManFree( Nm_Man_t * p ) +{ + Extra_MmFlexStop( p->pMem ); + FREE( p->pBinsI2N ); + FREE( p->pBinsN2I ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of objects with names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nm_ManNumEntries( Nm_Man_t * p ) +{ + return p->nEntries; +} + +/**Function************************************************************* + + Synopsis [Creates a new entry in the name manager.] + + Description [Returns 1 if the entry with the given object ID + already exists in the name manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix ) +{ + Nm_Entry_t * pEntry; + int RetValue, nEntrySize; + // check if the object with this ID is already stored + if ( pEntry = Nm_ManTableLookupId(p, ObjId) ) + { + printf( "Nm_ManStoreIdName(): Entry with the same ID already exists.\n" ); + return NULL; + } + // create a new entry + nEntrySize = sizeof(Nm_Entry_t) + strlen(pName) + (pSuffix?strlen(pSuffix):0) + 1; + nEntrySize = (nEntrySize / 4 + ((nEntrySize % 4) > 0)) * 4; + pEntry = (Nm_Entry_t *)Extra_MmFlexEntryFetch( p->pMem, nEntrySize ); + pEntry->pNextI2N = pEntry->pNextN2I = pEntry->pNameSake = NULL; + pEntry->ObjId = ObjId; + pEntry->Type = Type; + sprintf( pEntry->Name, "%s%s", pName, pSuffix? pSuffix : "" ); + // add the entry to the hash table + RetValue = Nm_ManTableAdd( p, pEntry ); + assert( RetValue == 1 ); + return pEntry->Name; +} + +/**Function************************************************************* + + Synopsis [Creates a new entry in the name manager.] + + Description [Returns 1 if the entry with the given object ID + already exists in the name manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId ) +{ + Nm_Entry_t * pEntry; + pEntry = Nm_ManTableLookupId(p, ObjId); + if ( pEntry == NULL ) + { + printf( "Nm_ManDeleteIdName(): This entry is not in the table.\n" ); + return; + } + // remove entry from the table + Nm_ManTableDelete( p, ObjId ); +} + + +/**Function************************************************************* + + Synopsis [Finds a unique name for the node.] + + Description [If the name exists, tries appending numbers to it until + it becomes unique. The name is not added to the table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId ) +{ + static char NameStr[1000]; + Nm_Entry_t * pEntry; + int i; + if ( pEntry = Nm_ManTableLookupId(p, ObjId) ) + return pEntry->Name; + sprintf( NameStr, "n%d", ObjId ); + for ( i = 1; Nm_ManTableLookupName(p, NameStr, -1); i++ ) + sprintf( NameStr, "n%d_%d", ObjId, i ); + return NameStr; +} + +/**Function************************************************************* + + Synopsis [Returns name of the object if the ID is known.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Nm_ManFindNameById( Nm_Man_t * p, int ObjId ) +{ + Nm_Entry_t * pEntry; + if ( pEntry = Nm_ManTableLookupId(p, ObjId) ) + return pEntry->Name; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns ID of the object if its name is known.] + + Description [This procedure may return two IDs because POs and latches + may have the same name (the only allowed case of name duplication).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type ) +{ + Nm_Entry_t * pEntry; + if ( pEntry = Nm_ManTableLookupName(p, pName, Type) ) + return pEntry->ObjId; + return -1; +} + +/**Function************************************************************* + + Synopsis [Returns ID of the object if its name is known.] + + Description [This procedure may return two IDs because POs and latches + may have the same name (the only allowed case of name duplication).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 ) +{ + int iNodeId; + iNodeId = Nm_ManFindIdByName( p, pName, Type1 ); + if ( iNodeId == -1 ) + iNodeId = Nm_ManFindIdByName( p, pName, Type2 ); + if ( iNodeId == -1 ) + return -1; + return iNodeId; +} + +/**Function************************************************************* + + Synopsis [Return the IDs of objects with names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Nm_ManReturnNameIds( Nm_Man_t * p ) +{ + Vec_Int_t * vNameIds; + int i; + vNameIds = Vec_IntAlloc( p->nEntries ); + for ( i = 0; i < p->nBins; i++ ) + if ( p->pBinsI2N[i] ) + Vec_IntPush( vNameIds, p->pBinsI2N[i]->ObjId ); + return vNameIds; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/nm/nmInt.h b/abc70930/src/misc/nm/nmInt.h new file mode 100644 index 00000000..028316e1 --- /dev/null +++ b/abc70930/src/misc/nm/nmInt.h @@ -0,0 +1,91 @@ +/**CFile**************************************************************** + + FileName [nmInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Name manager.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nmInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __NM_INT_H__ +#define __NM_INT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "extra.h" +#include "vec.h" +#include "nm.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Nm_Entry_t_ Nm_Entry_t; +struct Nm_Entry_t_ +{ + unsigned Type : 4; // object type + unsigned ObjId : 28; // object ID + Nm_Entry_t * pNextI2N; // the next entry in the ID hash table + Nm_Entry_t * pNextN2I; // the next entry in the name hash table + Nm_Entry_t * pNameSake; // the next entry with the same name + char Name[0]; // name of the object +}; + +struct Nm_Man_t_ +{ + Nm_Entry_t ** pBinsI2N; // mapping IDs into names + Nm_Entry_t ** pBinsN2I; // mapping names into IDs + int nBins; // the number of bins in tables + int nEntries; // the number of entries + int nSizeFactor; // determined how much larger the table should be + int nGrowthFactor; // determined how much the table grows after resizing + Extra_MmFlex_t * pMem; // memory manager for entries (and names) +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== nmTable.c ==========================================================*/ +extern int Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry ); +extern int Nm_ManTableDelete( Nm_Man_t * p, int ObjId ); +extern Nm_Entry_t * Nm_ManTableLookupId( Nm_Man_t * p, int ObjId ); +extern Nm_Entry_t * Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type ); +extern unsigned int Cudd_PrimeNm( unsigned int p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/nm/nmTable.c b/abc70930/src/misc/nm/nmTable.c new file mode 100644 index 00000000..f97a2f0b --- /dev/null +++ b/abc70930/src/misc/nm/nmTable.c @@ -0,0 +1,340 @@ +/**CFile**************************************************************** + + FileName [nmTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Name manager.] + + Synopsis [Hash table for the name manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: nmTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "nmInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// hashing for integers +static unsigned Nm_HashNumber( int Num, int TableSize ) +{ + unsigned Key = 0; + Key ^= ( Num & 0xFF) * 7937; + Key ^= ((Num >> 8) & 0xFF) * 2971; + Key ^= ((Num >> 16) & 0xFF) * 911; + Key ^= ((Num >> 24) & 0xFF) * 353; + return Key % TableSize; +} + +// hashing for strings +static unsigned Nm_HashString( char * pName, int TableSize ) +{ + static int s_Primes[10] = { + 1291, 1699, 2357, 4177, 5147, + 5647, 6343, 7103, 7873, 8147 + }; + unsigned i, Key = 0; + for ( i = 0; pName[i] != '\0'; i++ ) + Key ^= s_Primes[i%10]*pName[i]*pName[i]; + return Key % TableSize; +} + +static void Nm_ManResize( Nm_Man_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Adds an entry to two hash tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry ) +{ + Nm_Entry_t ** ppSpot, * pOther; + // resize the tables if needed + if ( p->nEntries > p->nBins * p->nSizeFactor ) + Nm_ManResize( p ); + // add the entry to the table Id->Name + assert( Nm_ManTableLookupId(p, pEntry->ObjId) == NULL ); + ppSpot = p->pBinsI2N + Nm_HashNumber(pEntry->ObjId, p->nBins); + pEntry->pNextI2N = *ppSpot; + *ppSpot = pEntry; + // check if an entry with the same name already exists + if ( pOther = Nm_ManTableLookupName(p, pEntry->Name, -1) ) + { + // entry with the same name already exists - add it to the ring + pEntry->pNameSake = pOther->pNameSake? pOther->pNameSake : pOther; + pOther->pNameSake = pEntry; + } + else + { + // entry with the same name does not exist - add it to the table + ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins); + pEntry->pNextN2I = *ppSpot; + *ppSpot = pEntry; + } + // report successfully added entry + p->nEntries++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Deletes the entry from two hash tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nm_ManTableDelete( Nm_Man_t * p, int ObjId ) +{ + Nm_Entry_t ** ppSpot, * pEntry, * pPrev; + int fRemoved; + p->nEntries--; + // remove the entry from the table Id->Name + assert( Nm_ManTableLookupId(p, ObjId) != NULL ); + ppSpot = p->pBinsI2N + Nm_HashNumber(ObjId, p->nBins); + while ( (*ppSpot)->ObjId != (unsigned)ObjId ) + ppSpot = &(*ppSpot)->pNextI2N; + pEntry = *ppSpot; + *ppSpot = (*ppSpot)->pNextI2N; + // remove the entry from the table Name->Id + ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins); + while ( *ppSpot && *ppSpot != pEntry ) + ppSpot = &(*ppSpot)->pNextN2I; + // remember if we found this one in the list + fRemoved = (*ppSpot != NULL); + if ( *ppSpot ) + { + assert( *ppSpot == pEntry ); + *ppSpot = (*ppSpot)->pNextN2I; + } + // quit if this entry has no namesakes + if ( pEntry->pNameSake == NULL ) + { + assert( fRemoved ); + return 1; + } + // remove entry from the ring of namesakes + assert( pEntry->pNameSake != pEntry ); + for ( pPrev = pEntry; pPrev->pNameSake != pEntry; pPrev = pPrev->pNameSake ); + assert( !strcmp(pPrev->Name, pEntry->Name) ); + assert( pPrev->pNameSake == pEntry ); + if ( pEntry->pNameSake == pPrev ) // two entries in the ring + pPrev->pNameSake = NULL; + else + pPrev->pNameSake = pEntry->pNameSake; + // reinsert the ring back if we removed its connection with the list in the table + if ( fRemoved ) + { + assert( pPrev->pNextN2I == NULL ); + pPrev->pNextN2I = *ppSpot; + *ppSpot = pPrev; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Looks up the entry by ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nm_Entry_t * Nm_ManTableLookupId( Nm_Man_t * p, int ObjId ) +{ + Nm_Entry_t * pEntry; + for ( pEntry = p->pBinsI2N[ Nm_HashNumber(ObjId, p->nBins) ]; pEntry; pEntry = pEntry->pNextI2N ) + if ( pEntry->ObjId == (unsigned)ObjId ) + return pEntry; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Looks up the entry by name and type.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nm_Entry_t * Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type ) +{ + Nm_Entry_t * pEntry, * pTemp; + int Counter = 0; + for ( pEntry = p->pBinsN2I[ Nm_HashString(pName, p->nBins) ]; pEntry; pEntry = pEntry->pNextN2I ) + { + // check the entry itself + if ( !strcmp(pEntry->Name, pName) && (Type == -1 || pEntry->Type == (unsigned)Type) ) + return pEntry; + // if there is no namesakes, continue + if ( pEntry->pNameSake == NULL ) + continue; + // check the list of namesakes + for ( pTemp = pEntry->pNameSake; pTemp != pEntry; pTemp = pTemp->pNameSake ) + if ( !strcmp(pTemp->Name, pName) && (Type == -1 || pTemp->Type == (unsigned)Type) ) + return pTemp; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Profiles hash tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nm_ManProfile( Nm_Man_t * p ) +{ + Nm_Entry_t * pEntry; + int Counter, e; + printf( "I2N table: " ); + for ( e = 0; e < p->nBins; e++ ) + { + Counter = 0; + for ( pEntry = p->pBinsI2N[e]; pEntry; pEntry = pEntry->pNextI2N ) + Counter++; + printf( "%d ", Counter ); + } + printf( "\n" ); + printf( "N2I table: " ); + for ( e = 0; e < p->nBins; e++ ) + { + Counter = 0; + for ( pEntry = p->pBinsN2I[e]; pEntry; pEntry = pEntry->pNextN2I ) + Counter++; + printf( "%d ", Counter ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nm_ManResize( Nm_Man_t * p ) +{ + Nm_Entry_t ** pBinsNewI2N, ** pBinsNewN2I, * pEntry, * pEntry2, ** ppSpot; + int nBinsNew, Counter, e, clk; + +clk = clock(); + // get the new table size + nBinsNew = Cudd_PrimeCopy( p->nGrowthFactor * p->nBins ); + // allocate a new array + pBinsNewI2N = ALLOC( Nm_Entry_t *, nBinsNew ); + pBinsNewN2I = ALLOC( Nm_Entry_t *, nBinsNew ); + memset( pBinsNewI2N, 0, sizeof(Nm_Entry_t *) * nBinsNew ); + memset( pBinsNewN2I, 0, sizeof(Nm_Entry_t *) * nBinsNew ); + // rehash entries in Id->Name table + Counter = 0; + for ( e = 0; e < p->nBins; e++ ) + for ( pEntry = p->pBinsI2N[e], pEntry2 = pEntry? pEntry->pNextI2N : NULL; + pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextI2N : NULL ) + { + ppSpot = pBinsNewI2N + Nm_HashNumber(pEntry->ObjId, nBinsNew); + pEntry->pNextI2N = *ppSpot; + *ppSpot = pEntry; + Counter++; + } + // rehash entries in Name->Id table + for ( e = 0; e < p->nBins; e++ ) + for ( pEntry = p->pBinsN2I[e], pEntry2 = pEntry? pEntry->pNextN2I : NULL; + pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextN2I : NULL ) + { + ppSpot = pBinsNewN2I + Nm_HashString(pEntry->Name, nBinsNew); + pEntry->pNextN2I = *ppSpot; + *ppSpot = pEntry; + } + assert( Counter == p->nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew ); +// PRT( "Time", clock() - clk ); + // replace the table and the parameters + free( p->pBinsI2N ); + free( p->pBinsN2I ); + p->pBinsI2N = pBinsNewI2N; + p->pBinsN2I = pBinsNewN2I; + p->nBins = nBinsNew; +// Nm_ManProfile( p ); +} + + +/**Function************************************************************* + + Synopsis [Returns the smallest prime larger than the number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned int Cudd_PrimeNm( unsigned int p) +{ + int i,pn; + + p--; + do { + p++; + if (p&1) { + pn = 1; + i = 3; + while ((unsigned) (i * i) <= p) { + if (p % i == 0) { + pn = 0; + break; + } + i += 2; + } + } else { + pn = 0; + } + } while (!pn); + return(p); + +} /* end of Cudd_Prime */ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/misc/st/module.make b/abc70930/src/misc/st/module.make new file mode 100644 index 00000000..33e442c0 --- /dev/null +++ b/abc70930/src/misc/st/module.make @@ -0,0 +1,2 @@ +SRC += src/misc/st/st.c \ + src/misc/st/stmm.c diff --git a/abc70930/src/misc/st/st.c b/abc70930/src/misc/st/st.c new file mode 100644 index 00000000..872fe51b --- /dev/null +++ b/abc70930/src/misc/st/st.c @@ -0,0 +1,625 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/st/st.c,v + * serdar + * 1.1 + * 1993/07/29 01:00:13 + * + */ +#include +#include +#include "st.h" + +#ifndef ABS +# define ABS(a) ((a) < 0 ? -(a) : (a)) +#endif + +#ifndef ALLOC +#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#endif + +#ifndef FREE +#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#endif + +#ifndef REALLOC +#define REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) +#endif + +#define ST_NUMCMP(x,y) ((x) != (y)) +#define ST_NUMHASH(x,size) (ABS((long)x)%(size)) +//#define ST_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size) // 64-bit bug fix 9/17/2007 +#define ST_PTRHASH(x,size) ((int)(((unsigned long)(x)>>2)%size)) +#define EQUAL(func, x, y) \ + ((((func) == st_numcmp) || ((func) == st_ptrcmp)) ?\ + (ST_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0)) + + +#define do_hash(key, table)\ + ((table->hash == st_ptrhash) ? ST_PTRHASH((key),(table)->num_bins) :\ + (table->hash == st_numhash) ? ST_NUMHASH((key), (table)->num_bins) :\ + (*table->hash)((key), (table)->num_bins)) + +static int rehash(); +int st_numhash(), st_ptrhash(), st_numcmp(), st_ptrcmp(); + +st_table * +st_init_table_with_params(compare, hash, size, density, grow_factor, + reorder_flag) +int (*compare)(); +int (*hash)(); +int size; +int density; +double grow_factor; +int reorder_flag; +{ + int i; + st_table *new; + + new = ALLOC(st_table, 1); + if (new == NULL) { + return NULL; + } + new->compare = compare; + new->hash = hash; + new->num_entries = 0; + new->max_density = density; + new->grow_factor = grow_factor; + new->reorder_flag = reorder_flag; + if (size <= 0) { + size = 1; + } + new->num_bins = size; + new->bins = ALLOC(st_table_entry *, size); + if (new->bins == NULL) { + FREE(new); + return NULL; + } + for(i = 0; i < size; i++) { + new->bins[i] = 0; + } + return new; +} + +st_table * +st_init_table(compare, hash) +int (*compare)(); +int (*hash)(); +{ + return st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE, + ST_DEFAULT_MAX_DENSITY, + ST_DEFAULT_GROW_FACTOR, + ST_DEFAULT_REORDER_FLAG); +} + +void +st_free_table(table) +st_table *table; +{ + register st_table_entry *ptr, *next; + int i; + + for(i = 0; i < table->num_bins ; i++) { + ptr = table->bins[i]; + while (ptr != NULL) { + next = ptr->next; + FREE(ptr); + ptr = next; + } + } + FREE(table->bins); + FREE(table); +} + +#define PTR_NOT_EQUAL(table, ptr, user_key)\ +(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) + +#define FIND_ENTRY(table, hash_val, key, ptr, last) \ + (last) = &(table)->bins[hash_val];\ + (ptr) = *(last);\ + while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ + (last) = &(ptr)->next; (ptr) = *(last);\ + }\ + if ((ptr) != NULL && (table)->reorder_flag) {\ + *(last) = (ptr)->next;\ + (ptr)->next = (table)->bins[hash_val];\ + (table)->bins[hash_val] = (ptr);\ + } + +int +st_lookup(table, key, value) +st_table *table; +register char *key; +char **value; +{ + int hash_val; + register st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr, last); + + if (ptr == NULL) { + return 0; + } else { + if (value != NULL) { + *value = ptr->record; + } + return 1; + } +} + +int +st_lookup_int(table, key, value) +st_table *table; +register char *key; +int *value; +{ + int hash_val; + register st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr, last); + + if (ptr == NULL) { + return 0; + } else { + if (value != 0) { + *value = (long) ptr->record; + } + return 1; + } +} + +/* This macro does not check if memory allocation fails. Use at you own risk */ +#define ADD_DIRECT(table, key, value, hash_val, new)\ +{\ + if (table->num_entries/table->num_bins >= table->max_density) {\ + rehash(table);\ + hash_val = do_hash(key,table);\ + }\ + \ + new = ALLOC(st_table_entry, 1);\ + \ + new->key = key;\ + new->record = value;\ + new->next = table->bins[hash_val];\ + table->bins[hash_val] = new;\ + table->num_entries++;\ +} + +int +st_insert(table, key, value) +register st_table *table; +register char *key; +char *value; +{ + int hash_val; + st_table_entry *new; + register st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr, last); + + if (ptr == NULL) { + if (table->num_entries/table->num_bins >= table->max_density) { + if (rehash(table) == ST_OUT_OF_MEM) { + return ST_OUT_OF_MEM; + } + hash_val = do_hash(key, table); + } + new = ALLOC(st_table_entry, 1); + if (new == NULL) { + return ST_OUT_OF_MEM; + } + new->key = key; + new->record = value; + new->next = table->bins[hash_val]; + table->bins[hash_val] = new; + table->num_entries++; + return 0; + } else { + ptr->record = value; + return 1; + } +} + +int +st_add_direct(table, key, value) +st_table *table; +char *key; +char *value; +{ + int hash_val; + st_table_entry *new; + + hash_val = do_hash(key, table); + if (table->num_entries / table->num_bins >= table->max_density) { + if (rehash(table) == ST_OUT_OF_MEM) { + return ST_OUT_OF_MEM; + } + } + hash_val = do_hash(key, table); + new = ALLOC(st_table_entry, 1); + if (new == NULL) { + return ST_OUT_OF_MEM; + } + new->key = key; + new->record = value; + new->next = table->bins[hash_val]; + table->bins[hash_val] = new; + table->num_entries++; + return 1; +} + +int +st_find_or_add(table, key, slot) +st_table *table; +char *key; +char ***slot; +{ + int hash_val; + st_table_entry *new, *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr, last); + + if (ptr == NULL) { + if (table->num_entries / table->num_bins >= table->max_density) { + if (rehash(table) == ST_OUT_OF_MEM) { + return ST_OUT_OF_MEM; + } + hash_val = do_hash(key, table); + } + new = ALLOC(st_table_entry, 1); + if (new == NULL) { + return ST_OUT_OF_MEM; + } + new->key = key; + new->record = (char *) 0; + new->next = table->bins[hash_val]; + table->bins[hash_val] = new; + table->num_entries++; + if (slot != NULL) *slot = &new->record; + return 0; + } else { + if (slot != NULL) *slot = &ptr->record; + return 1; + } +} + +int +st_find(table, key, slot) +st_table *table; +char *key; +char ***slot; +{ + int hash_val; + st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr, last); + + if (ptr == NULL) { + return 0; + } else { + if (slot != NULL) { + *slot = &ptr->record; + } + return 1; + } +} + +static int +rehash(table) +register st_table *table; +{ + register st_table_entry *ptr, *next, **old_bins; + int i, old_num_bins, hash_val, old_num_entries; + + /* save old values */ + old_bins = table->bins; + old_num_bins = table->num_bins; + old_num_entries = table->num_entries; + + /* rehash */ + table->num_bins = (int)(table->grow_factor * old_num_bins); + if (table->num_bins % 2 == 0) { + table->num_bins += 1; + } + table->num_entries = 0; + table->bins = ALLOC(st_table_entry *, table->num_bins); + if (table->bins == NULL) { + table->bins = old_bins; + table->num_bins = old_num_bins; + table->num_entries = old_num_entries; + return ST_OUT_OF_MEM; + } + /* initialize */ + for (i = 0; i < table->num_bins; i++) { + table->bins[i] = 0; + } + + /* copy data over */ + for (i = 0; i < old_num_bins; i++) { + ptr = old_bins[i]; + while (ptr != NULL) { + next = ptr->next; + hash_val = do_hash(ptr->key, table); + ptr->next = table->bins[hash_val]; + table->bins[hash_val] = ptr; + table->num_entries++; + ptr = next; + } + } + FREE(old_bins); + + return 1; +} + +st_table * +st_copy(old_table) +st_table *old_table; +{ + st_table *new_table; + st_table_entry *ptr, *newptr, *next, *new; + int i, j, num_bins = old_table->num_bins; + + new_table = ALLOC(st_table, 1); + if (new_table == NULL) { + return NULL; + } + + *new_table = *old_table; + new_table->bins = ALLOC(st_table_entry *, num_bins); + if (new_table->bins == NULL) { + FREE(new_table); + return NULL; + } + for(i = 0; i < num_bins ; i++) { + new_table->bins[i] = NULL; + ptr = old_table->bins[i]; + while (ptr != NULL) { + new = ALLOC(st_table_entry, 1); + if (new == NULL) { + for (j = 0; j <= i; j++) { + newptr = new_table->bins[j]; + while (newptr != NULL) { + next = newptr->next; + FREE(newptr); + newptr = next; + } + } + FREE(new_table->bins); + FREE(new_table); + return NULL; + } + *new = *ptr; + new->next = new_table->bins[i]; + new_table->bins[i] = new; + ptr = ptr->next; + } + } + return new_table; +} + +int +st_delete(table, keyp, value) +register st_table *table; +register char **keyp; +char **value; +{ + int hash_val; + char *key = *keyp; + register st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr ,last); + + if (ptr == NULL) { + return 0; + } + + *last = ptr->next; + if (value != NULL) *value = ptr->record; + *keyp = ptr->key; + FREE(ptr); + table->num_entries--; + return 1; +} + +int +st_delete_int(table, keyp, value) +register st_table *table; +register long *keyp; +char **value; +{ + int hash_val; + char *key = (char *) *keyp; + register st_table_entry *ptr, **last; + + hash_val = do_hash(key, table); + + FIND_ENTRY(table, hash_val, key, ptr ,last); + + if (ptr == NULL) { + return 0; + } + + *last = ptr->next; + if (value != NULL) *value = ptr->record; + *keyp = (long) ptr->key; + FREE(ptr); + table->num_entries--; + return 1; +} + +int +st_foreach(table, func, arg) +st_table *table; +enum st_retval (*func)(); +char *arg; +{ + st_table_entry *ptr, **last; + enum st_retval retval; + int i; + + for(i = 0; i < table->num_bins; i++) { + last = &table->bins[i]; ptr = *last; + while (ptr != NULL) { + retval = (*func)(ptr->key, ptr->record, arg); + switch (retval) { + case ST_CONTINUE: + last = &ptr->next; ptr = *last; + break; + case ST_STOP: + return 0; + case ST_DELETE: + *last = ptr->next; + table->num_entries--; /* cstevens@ic */ + FREE(ptr); + ptr = *last; + } + } + } + return 1; +} + +int +st_strhash(string, modulus) +register char *string; +int modulus; +{ + register int val = 0; + register int c; + + while ((c = *string++) != '\0') { + val = val*997 + c; + } + + return ((val < 0) ? -val : val)%modulus; +} + +int +st_numhash(x, size) +char *x; +int size; +{ + return ST_NUMHASH(x, size); +} + +int +st_ptrhash(x, size) +char *x; +int size; +{ + return ST_PTRHASH(x, size); +} + +int +st_numcmp(x, y) +char *x; +char *y; +{ + return ST_NUMCMP(x, y); +} + +int +st_ptrcmp(x, y) +char *x; +char *y; +{ + return ST_NUMCMP(x, y); +} + +st_generator * +st_init_gen(table) +st_table *table; +{ + st_generator *gen; + + gen = ALLOC(st_generator, 1); + if (gen == NULL) { + return NULL; + } + gen->table = table; + gen->entry = NULL; + gen->index = 0; + return gen; +} + + +int +st_gen(gen, key_p, value_p) +st_generator *gen; +char **key_p; +char **value_p; +{ + register int i; + + if (gen->entry == NULL) { + /* try to find next entry */ + for(i = gen->index; i < gen->table->num_bins; i++) { + if (gen->table->bins[i] != NULL) { + gen->index = i+1; + gen->entry = gen->table->bins[i]; + break; + } + } + if (gen->entry == NULL) { + return 0; /* that's all folks ! */ + } + } + *key_p = gen->entry->key; + if (value_p != 0) { + *value_p = gen->entry->record; + } + gen->entry = gen->entry->next; + return 1; +} + + +int +st_gen_int(gen, key_p, value_p) +st_generator *gen; +char **key_p; +long *value_p; +{ + register int i; + + if (gen->entry == NULL) { + /* try to find next entry */ + for(i = gen->index; i < gen->table->num_bins; i++) { + if (gen->table->bins[i] != NULL) { + gen->index = i+1; + gen->entry = gen->table->bins[i]; + break; + } + } + if (gen->entry == NULL) { + return 0; /* that's all folks ! */ + } + } + *key_p = gen->entry->key; + if (value_p != 0) { + *value_p = (long) gen->entry->record; + } + gen->entry = gen->entry->next; + return 1; +} + + +void +st_free_gen(gen) +st_generator *gen; +{ + FREE(gen); +} diff --git a/abc70930/src/misc/st/st.h b/abc70930/src/misc/st/st.h new file mode 100644 index 00000000..b15f3c83 --- /dev/null +++ b/abc70930/src/misc/st/st.h @@ -0,0 +1,96 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/st/st.h,v + * serdar + * 1.1 + * 1993/07/29 01:00:21 + * + */ +/* LINTLIBRARY */ + +/* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */ + +#ifndef ST_INCLUDED +#define ST_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct st_table_entry st_table_entry; +struct st_table_entry { + char *key; + char *record; + st_table_entry *next; +}; + +typedef struct st_table st_table; +struct st_table { + int (*compare)(); + int (*hash)(); + int num_bins; + int num_entries; + int max_density; + int reorder_flag; + double grow_factor; + st_table_entry **bins; +}; + +typedef struct st_generator st_generator; +struct st_generator { + st_table *table; + st_table_entry *entry; + int index; +}; + +#define st_is_member(table,key) st_lookup(table,key,(char **) 0) +#define st_count(table) ((table)->num_entries) + +enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE}; + +typedef enum st_retval (*ST_PFSR)(); +typedef int (*ST_PFI)(); + +extern st_table *st_init_table_with_params (ST_PFI, ST_PFI, int, int, double, int); +extern st_table *st_init_table (ST_PFI, ST_PFI); +extern void st_free_table (st_table *); +extern int st_lookup (st_table *, char *, char **); +extern int st_lookup_int (st_table *, char *, int *); +extern int st_insert (st_table *, char *, char *); +extern int st_add_direct (st_table *, char *, char *); +extern int st_find_or_add (st_table *, char *, char ***); +extern int st_find (st_table *, char *, char ***); +extern st_table *st_copy (st_table *); +extern int st_delete (st_table *, char **, char **); +extern int st_delete_int (st_table *, long *, char **); +extern int st_foreach (st_table *, ST_PFSR, char *); +extern int st_strhash (char *, int); +extern int st_numhash (char *, int); +extern int st_ptrhash (char *, int); +extern int st_numcmp (char *, char *); +extern int st_ptrcmp (char *, char *); +extern st_generator *st_init_gen (st_table *); +extern int st_gen (st_generator *, char **, char **); +extern int st_gen_int (st_generator *, char **, long *); +extern void st_free_gen (st_generator *); + + +#define ST_DEFAULT_MAX_DENSITY 5 +#define ST_DEFAULT_INIT_TABLE_SIZE 11 +#define ST_DEFAULT_GROW_FACTOR 2.0 +#define ST_DEFAULT_REORDER_FLAG 0 + +#define st_foreach_item(table, gen, key, value) \ + for(gen=st_init_gen(table); st_gen(gen,key,value) || (st_free_gen(gen),0);) + +#define st_foreach_item_int(table, gen, key, value) \ + for(gen=st_init_gen(table); st_gen_int(gen,key,value) || (st_free_gen(gen),0);) + +#define ST_OUT_OF_MEM -10000 + +#ifdef __cplusplus +} +#endif + +#endif /* ST_INCLUDED */ diff --git a/abc70930/src/misc/st/stmm.c b/abc70930/src/misc/st/stmm.c new file mode 100644 index 00000000..8dfacfe4 --- /dev/null +++ b/abc70930/src/misc/st/stmm.c @@ -0,0 +1,688 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/st/st.c,v + * serdar + * 1.1 + * 1993/07/29 01:00:13 + * + */ +#include +#include "extra.h" +#include "stmm.h" + +#ifndef ABS +# define ABS(a) ((a) < 0 ? -(a) : (a)) +#endif + +#define STMM_NUMCMP(x,y) ((x) != (y)) +#define STMM_NUMHASH(x,size) (ABS((long)x)%(size)) +//#define STMM_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size) // 64-bit bug fix 9/17/2007 +#define STMM_PTRHASH(x,size) ((int)(((unsigned long)(x)>>2)%size)) +#define EQUAL(func, x, y) \ + ((((func) == stmm_numcmp) || ((func) == stmm_ptrcmp)) ?\ + (STMM_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0)) + + +#define do_hash(key, table)\ + ((table->hash == stmm_ptrhash) ? STMM_PTRHASH((key),(table)->num_bins) :\ + (table->hash == stmm_numhash) ? STMM_NUMHASH((key), (table)->num_bins) :\ + (*table->hash)((key), (table)->num_bins)) + +static int rehash (); +int stmm_numhash (), stmm_ptrhash (), stmm_numcmp (), stmm_ptrcmp (); + +stmm_table * +stmm_init_table_with_params (compare, hash, size, density, grow_factor, + reorder_flag) + int (*compare) (); + int (*hash) (); + int size; + int density; + double grow_factor; + int reorder_flag; +{ + int i; + stmm_table *new; + + new = ALLOC (stmm_table, 1); + if (new == NULL) { + return NULL; + } + new->compare = compare; + new->hash = hash; + new->num_entries = 0; + new->max_density = density; + new->grow_factor = grow_factor; + new->reorder_flag = reorder_flag; + if (size <= 0) { + size = 1; + } + new->num_bins = size; + new->bins = ALLOC (stmm_table_entry *, size); + if (new->bins == NULL) { + FREE (new); + return NULL; + } + for (i = 0; i < size; i++) { + new->bins[i] = 0; + } + + // added by alanmi + new->pMemMan = Extra_MmFixedStart(sizeof (stmm_table_entry)); + return new; +} + +stmm_table * +stmm_init_table (compare, hash) + int (*compare) (); + int (*hash) (); +{ + return stmm_init_table_with_params (compare, hash, + STMM_DEFAULT_INIT_TABLE_SIZE, + STMM_DEFAULT_MAX_DENSITY, + STMM_DEFAULT_GROW_FACTOR, + STMM_DEFAULT_REORDER_FLAG); +} + +void +stmm_free_table (table) + stmm_table *table; +{ +/* + register stmm_table_entry *ptr, *next; + int i; + for ( i = 0; i < table->num_bins; i++ ) + { + ptr = table->bins[i]; + while ( ptr != NULL ) + { + next = ptr->next; + FREE( ptr ); + ptr = next; + } + } +*/ + // no need to deallocate entries because they are in the memory manager now + // added by alanmi + if ( table->pMemMan ) + Extra_MmFixedStop (table->pMemMan); + FREE (table->bins); + FREE (table); +} + +// this function recycles all the bins +void +stmm_clean (table) + stmm_table *table; +{ + int i; + // clean the bins + for (i = 0; i < table->num_bins; i++) + table->bins[i] = NULL; + // reset the parameters + table->num_entries = 0; + // restart the memory manager + Extra_MmFixedRestart (table->pMemMan); +} + + +#define PTR_NOT_EQUAL(table, ptr, user_key)\ +(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) + +#define FIND_ENTRY(table, hash_val, key, ptr, last) \ + (last) = &(table)->bins[hash_val];\ + (ptr) = *(last);\ + while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ + (last) = &(ptr)->next; (ptr) = *(last);\ + }\ + if ((ptr) != NULL && (table)->reorder_flag) {\ + *(last) = (ptr)->next;\ + (ptr)->next = (table)->bins[hash_val];\ + (table)->bins[hash_val] = (ptr);\ + } + +int +stmm_lookup (table, key, value) + stmm_table *table; + register char *key; + char **value; +{ + int hash_val; + register stmm_table_entry *ptr, **last; + + hash_val = do_hash (key, table); + + FIND_ENTRY (table, hash_val, key, ptr, last); + + if (ptr == NULL) { + return 0; + } + else { + if (value != NULL) + { + *value = ptr->record; + } + return 1; + } +} + +int +stmm_lookup_int (table, key, value) + stmm_table *table; + register char *key; + int *value; +{ + int hash_val; + register stmm_table_entry *ptr, **last; + + hash_val = do_hash (key, table); + + FIND_ENTRY (table, hash_val, key, ptr, last); + + if (ptr == NULL) { + return 0; + } + else { + if (value != 0) + { + *value = (long) ptr->record; + } + return 1; + } +} + +// This macro contained a line +// new = ALLOC(stmm_table_entry, 1); +// which was modified by alanmi + + +/* This macro does not check if memory allocation fails. Use at you own risk */ +#define ADD_DIRECT(table, key, value, hash_val, new)\ +{\ + if (table->num_entries/table->num_bins >= table->max_density) {\ + rehash(table);\ + hash_val = do_hash(key,table);\ + }\ + \ + new = (stmm_table_entry *)Extra_MmFixedEntryFetch( table->pMemMan );\ + \ + new->key = key;\ + new->record = value;\ + new->next = table->bins[hash_val];\ + table->bins[hash_val] = new;\ + table->num_entries++;\ +} + +int +stmm_insert (table, key, value) + register stmm_table *table; + register char *key; + char *value; +{ + int hash_val; + stmm_table_entry *new; + register stmm_table_entry *ptr, **last; + + hash_val = do_hash (key, table); + + FIND_ENTRY (table, hash_val, key, ptr, last); + + if (ptr == NULL) { + if (table->num_entries / table->num_bins >= table->max_density) { + if (rehash (table) == STMM_OUT_OF_MEM) { + return STMM_OUT_OF_MEM; + } + hash_val = do_hash (key, table); + } + +// new = ALLOC( stmm_table_entry, 1 ); + new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); + if (new == NULL) { + return STMM_OUT_OF_MEM; + } + + new->key = key; + new->record = value; + new->next = table->bins[hash_val]; + table->bins[hash_val] = new; + table->num_entries++; + return 0; + } + else { + ptr->record = value; + return 1; + } +} + +int +stmm_add_direct (table, key, value) + stmm_table *table; + char *key; + char *value; +{ + int hash_val; + stmm_table_entry *new; + + hash_val = do_hash (key, table); + if (table->num_entries / table->num_bins >= table->max_density) { + if (rehash (table) == STMM_OUT_OF_MEM) { + return STMM_OUT_OF_MEM; + } + } + hash_val = do_hash (key, table); + +// new = ALLOC( stmm_table_entry, 1 ); + new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); + if (new == NULL) { + return STMM_OUT_OF_MEM; + } + + new->key = key; + new->record = value; + new->next = table->bins[hash_val]; + table->bins[hash_val] = new; + table->num_entries++; + return 1; +} + +int +stmm_find_or_add (table, key, slot) + stmm_table *table; + char *key; + char ***slot; +{ + int hash_val; + stmm_table_entry *new, *ptr, **last; + + hash_val = do_hash (key, table); + + FIND_ENTRY (table, hash_val, key, ptr, last); + + if (ptr == NULL) { + if (table->num_entries / table->num_bins >= table->max_density) { + if (rehash (table) == STMM_OUT_OF_MEM) { + return STMM_OUT_OF_MEM; + } + hash_val = do_hash (key, table); + } + + // new = ALLOC( stmm_table_entry, 1 ); + new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); + if (new == NULL) { + return STMM_OUT_OF_MEM; + } + + new->key = key; + new->record = (char *) 0; + new->next = table->bins[hash_val]; + table->bins[hash_val] = new; + table->num_entries++; + if (slot != NULL) + *slot = &new->record; + return 0; + } + else { + if (slot != NULL) + *slot = &ptr->record; + return 1; + } +} + +int +stmm_find (table, key, slot) + stmm_table *table; + char *key; + char ***slot; +{ + int hash_val; + stmm_table_entry *ptr, **last; + + hash_val = do_hash (key, table); + + FIND_ENTRY (table, hash_val, key, ptr, last); + + if (ptr == NULL) { + return 0; + } + else { + if (slot != NULL) + { + *slot = &ptr->record; + } + return 1; + } +} + +static int +rehash (table) + register stmm_table *table; +{ + register stmm_table_entry *ptr, *next, **old_bins; + int i, old_num_bins, hash_val, old_num_entries; + + /* save old values */ + old_bins = table->bins; + old_num_bins = table->num_bins; + old_num_entries = table->num_entries; + + /* rehash */ + table->num_bins = (int) (table->grow_factor * old_num_bins); + if (table->num_bins % 2 == 0) { + table->num_bins += 1; + } + table->num_entries = 0; + table->bins = ALLOC (stmm_table_entry *, table->num_bins); + if (table->bins == NULL) { + table->bins = old_bins; + table->num_bins = old_num_bins; + table->num_entries = old_num_entries; + return STMM_OUT_OF_MEM; + } + /* initialize */ + for (i = 0; i < table->num_bins; i++) { + table->bins[i] = 0; + } + + /* copy data over */ + for (i = 0; i < old_num_bins; i++) { + ptr = old_bins[i]; + while (ptr != NULL) { + next = ptr->next; + hash_val = do_hash (ptr->key, table); + ptr->next = table->bins[hash_val]; + table->bins[hash_val] = ptr; + table->num_entries++; + ptr = next; + } + } + FREE (old_bins); + + return 1; +} + +stmm_table * +stmm_copy (old_table) + stmm_table *old_table; +{ + stmm_table *new_table; + stmm_table_entry *ptr, /* *newptr, *next, */ *new; + int i, /*j, */ num_bins = old_table->num_bins; + + new_table = ALLOC (stmm_table, 1); + if (new_table == NULL) { + return NULL; + } + + *new_table = *old_table; + new_table->bins = ALLOC (stmm_table_entry *, num_bins); + if (new_table->bins == NULL) { + FREE (new_table); + return NULL; + } + + // allocate the memory manager for the new table + new_table->pMemMan = + Extra_MmFixedStart (sizeof (stmm_table_entry)); + + for (i = 0; i < num_bins; i++) { + new_table->bins[i] = NULL; + ptr = old_table->bins[i]; + while (ptr != NULL) { +// new = ALLOC( stmm_table_entry, 1 ); + new = + (stmm_table_entry *) Extra_MmFixedEntryFetch (new_table-> + pMemMan); + + if (new == NULL) { +/* + for ( j = 0; j <= i; j++ ) + { + newptr = new_table->bins[j]; + while ( newptr != NULL ) + { + next = newptr->next; + FREE( newptr ); + newptr = next; + } + } +*/ + Extra_MmFixedStop (new_table->pMemMan); + + FREE (new_table->bins); + FREE (new_table); + return NULL; + } + *new = *ptr; + new->next = new_table->bins[i]; + new_table->bins[i] = new; + ptr = ptr->next; + } + } + return new_table; +} + +int +stmm_delete (table, keyp, value) + register stmm_table *table; + register char **keyp; + char **value; +{ + int hash_val; + char *key = *keyp; + register stmm_table_entry *ptr, **last; + + hash_val = do_hash (key, table); + + FIND_ENTRY (table, hash_val, key, ptr, last); + + if (ptr == NULL) { + return 0; + } + + *last = ptr->next; + if (value != NULL) + *value = ptr->record; + *keyp = ptr->key; +// FREE( ptr ); + Extra_MmFixedEntryRecycle (table->pMemMan, (char *) ptr); + + table->num_entries--; + return 1; +} + +int +stmm_delete_int (table, keyp, value) + register stmm_table *table; + register long *keyp; + char **value; +{ + int hash_val; + char *key = (char *) *keyp; + register stmm_table_entry *ptr, **last; + + hash_val = do_hash (key, table); + + FIND_ENTRY (table, hash_val, key, ptr, last); + + if (ptr == NULL) { + return 0; + } + + *last = ptr->next; + if (value != NULL) + *value = ptr->record; + *keyp = (long) ptr->key; +// FREE( ptr ); + Extra_MmFixedEntryRecycle (table->pMemMan, (char *) ptr); + + table->num_entries--; + return 1; +} + +int +stmm_foreach (table, func, arg) + stmm_table *table; + enum stmm_retval (*func) (); + char *arg; +{ + stmm_table_entry *ptr, **last; + enum stmm_retval retval; + int i; + + for (i = 0; i < table->num_bins; i++) { + last = &table->bins[i]; + ptr = *last; + while (ptr != NULL) { + retval = (*func) (ptr->key, ptr->record, arg); + switch (retval) { + case STMM_CONTINUE: + last = &ptr->next; + ptr = *last; + break; + case STMM_STOP: + return 0; + case STMM_DELETE: + *last = ptr->next; + table->num_entries--; /* cstevens@ic */ +// FREE( ptr ); + Extra_MmFixedEntryRecycle (table->pMemMan, (char *) ptr); + + ptr = *last; + } + } + } + return 1; +} + +int +stmm_strhash (string, modulus) + register char *string; + int modulus; +{ + register int val = 0; + register int c; + + while ((c = *string++) != '\0') { + val = val * 997 + c; + } + + return ((val < 0) ? -val : val) % modulus; +} + +int +stmm_numhash (x, size) + char *x; + int size; +{ + return STMM_NUMHASH (x, size); +} + +int +stmm_ptrhash (x, size) + char *x; + int size; +{ + return STMM_PTRHASH (x, size); +} + +int +stmm_numcmp (x, y) + char *x; + char *y; +{ + return STMM_NUMCMP (x, y); +} + +int +stmm_ptrcmp (x, y) + char *x; + char *y; +{ + return STMM_NUMCMP (x, y); +} + +stmm_generator * +stmm_init_gen (table) + stmm_table *table; +{ + stmm_generator *gen; + + gen = ALLOC (stmm_generator, 1); + if (gen == NULL) { + return NULL; + } + gen->table = table; + gen->entry = NULL; + gen->index = 0; + return gen; +} + + +int +stmm_gen (gen, key_p, value_p) + stmm_generator *gen; + char **key_p; + char **value_p; +{ + register int i; + + if (gen->entry == NULL) { + /* try to find next entry */ + for (i = gen->index; i < gen->table->num_bins; i++) { + if (gen->table->bins[i] != NULL) { + gen->index = i + 1; + gen->entry = gen->table->bins[i]; + break; + } + } + if (gen->entry == NULL) { + return 0; /* that's all folks ! */ + } + } + *key_p = gen->entry->key; + if (value_p != 0) { + *value_p = gen->entry->record; + } + gen->entry = gen->entry->next; + return 1; +} + + +int +stmm_gen_int (gen, key_p, value_p) + stmm_generator *gen; + char **key_p; + long *value_p; +{ + register int i; + + if (gen->entry == NULL) { + /* try to find next entry */ + for (i = gen->index; i < gen->table->num_bins; i++) { + if (gen->table->bins[i] != NULL) { + gen->index = i + 1; + gen->entry = gen->table->bins[i]; + break; + } + } + if (gen->entry == NULL) { + return 0; /* that's all folks ! */ + } + } + *key_p = gen->entry->key; + if (value_p != 0) + { + *value_p = (long) gen->entry->record; + } + gen->entry = gen->entry->next; + return 1; +} + + +void +stmm_free_gen (gen) + stmm_generator *gen; +{ + FREE (gen); +} diff --git a/abc70930/src/misc/st/stmm.h b/abc70930/src/misc/st/stmm.h new file mode 100644 index 00000000..4330416e --- /dev/null +++ b/abc70930/src/misc/st/stmm.h @@ -0,0 +1,127 @@ +/* + * Revision Control Information + * + * /projects/hsis/CVS/utilities/st/st.h,v + * serdar + * 1.1 + * 1993/07/29 01:00:21 + * + */ +/* LINTLIBRARY */ + +/* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */ + +#ifndef STMM_INCLUDED +#define STMM_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "extra.h" + +typedef struct stmm_table_entry stmm_table_entry; +typedef struct stmm_table stmm_table; +typedef struct stmm_generator stmm_generator; + +struct stmm_table_entry +{ + char *key; + char *record; + stmm_table_entry *next; +}; + +struct stmm_table +{ + int (*compare) (); + int (*hash) (); + int num_bins; + int num_entries; + int max_density; + int reorder_flag; + double grow_factor; + stmm_table_entry **bins; + // memory manager to improve runtime and prevent memory fragmentation + // added by alanmi - January 16, 2003 + Extra_MmFixed_t *pMemMan; +}; + +struct stmm_generator +{ + stmm_table *table; + stmm_table_entry *entry; + int index; +}; + +#define stmm_is_member(table,key) stmm_lookup(table,key,(char **) 0) +#define stmm_count(table) ((table)->num_entries) + +enum stmm_retval +{ STMM_CONTINUE, STMM_STOP, STMM_DELETE }; + +typedef enum stmm_retval (*STMM_PFSR) (); +typedef int (*STMM_PFI) (); + +EXTERN stmm_table *stmm_init_table_with_params +ARGS ((STMM_PFI, STMM_PFI, int, int, double, int)); +EXTERN stmm_table *stmm_init_table ARGS ((STMM_PFI, STMM_PFI)); +EXTERN void stmm_free_table ARGS ((stmm_table *)); +EXTERN int stmm_lookup ARGS ((stmm_table *, char *, char **)); +EXTERN int stmm_lookup_int ARGS ((stmm_table *, char *, int *)); +EXTERN int stmm_insert ARGS ((stmm_table *, char *, char *)); +EXTERN int stmm_add_direct ARGS ((stmm_table *, char *, char *)); +EXTERN int stmm_find_or_add ARGS ((stmm_table *, char *, char ***)); +EXTERN int stmm_find ARGS ((stmm_table *, char *, char ***)); +EXTERN stmm_table *stmm_copy ARGS ((stmm_table *)); +EXTERN int stmm_delete ARGS ((stmm_table *, char **, char **)); +EXTERN int stmm_delete_int ARGS ((stmm_table *, long *, char **)); +EXTERN int stmm_foreach ARGS ((stmm_table *, STMM_PFSR, char *)); +EXTERN int stmm_strhash ARGS ((char *, int)); +EXTERN int stmm_numhash ARGS ((char *, int)); +EXTERN int stmm_ptrhash ARGS ((char *, int)); +EXTERN int stmm_numcmp ARGS ((char *, char *)); +EXTERN int stmm_ptrcmp ARGS ((char *, char *)); +EXTERN stmm_generator *stmm_init_gen ARGS ((stmm_table *)); +EXTERN int stmm_gen ARGS ((stmm_generator *, char **, char **)); +EXTERN int stmm_gen_int ARGS ((stmm_generator *, char **, long *)); +EXTERN void stmm_free_gen ARGS ((stmm_generator *)); +// additional functions +EXTERN void stmm_clean ARGS ((stmm_table *)); + + + +#define STMM_DEFAULT_MAX_DENSITY 5 +#define STMM_DEFAULT_INIT_TABLE_SIZE 11 +#define STMM_DEFAULT_GROW_FACTOR 2.0 +#define STMM_DEFAULT_REORDER_FLAG 0 + +// added by Zhihong: no need for memory allocation +#define stmm_foreach_item2(tb, /* stmm_generator */gen, key, value) \ + for(gen.table=(tb), gen.entry=NULL, gen.index=0; \ + stmm_gen(&(gen),key,value);) + +#define stmm_foreach_item(table, gen, key, value) \ + for(gen=stmm_init_gen(table); stmm_gen(gen,key,value) || (stmm_free_gen(gen),0);) + +#define stmm_foreach_item_int(table, gen, key, value) \ + for(gen=stmm_init_gen(table); stmm_gen_int(gen,key,value) || (stmm_free_gen(gen),0);) + +#define STMM_OUT_OF_MEM -10000 + +/* + +// consider adding these other other similar definitions +#define st_table stmm_table +#define st_insert stmm_insert +#define st_delete stmm_delete +#define st_lookup stmm_lookup +#define st_init_table stmm_init_table +#define st_free_table stmm_free_table + +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* STMM_INCLUDED */ diff --git a/abc70930/src/misc/util/leaks.h b/abc70930/src/misc/util/leaks.h new file mode 100644 index 00000000..1a32062a --- /dev/null +++ b/abc70930/src/misc/util/leaks.h @@ -0,0 +1,30 @@ +////////////////////////////////////////////////////////////////////////// +// This file is used to detect memory leaks using Visual Studio 6.0 +// The idea comes from this page: http://www.michaelmoser.org/memory.htm +// In addition to this file, it required the presence of "stdlib_hack.h" +////////////////////////////////////////////////////////////////////////// + +#ifndef __LEAKS_H__ +#define __LEAKS_H__ + +#ifdef _DEBUG +#define _CRTDBG_MAP_ALLOC // include Microsoft memory leak detection procedures +//#define _INC_MALLOC // exclude standard memory alloc procedures + +#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) +#define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__) +#define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) +//#define _expand(p, s) _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) +//#define free(p) _free_dbg(p, _NORMAL_BLOCK) +//#define _msize(p) _msize_dbg(p, _NORMAL_BLOCK) + +//#include +#include +#include +#endif + +#endif + +////////////////////////////////////// + + diff --git a/abc70930/src/misc/util/module.make b/abc70930/src/misc/util/module.make new file mode 100644 index 00000000..d6d908e7 --- /dev/null +++ b/abc70930/src/misc/util/module.make @@ -0,0 +1 @@ +SRC += diff --git a/abc70930/src/misc/util/stdlib_hack.h b/abc70930/src/misc/util/stdlib_hack.h new file mode 100644 index 00000000..e3190edd --- /dev/null +++ b/abc70930/src/misc/util/stdlib_hack.h @@ -0,0 +1,471 @@ +/*** +*stdlib.h - declarations/definitions for commonly used library functions +* +* Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved. +* +*Purpose: +* This include file contains the function declarations for commonly +* used library functions which either don't fit somewhere else, or, +* cannot be declared in the normal place for other reasons. +* +* [ANSI] +* +* [Public] +* +****/ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#ifndef _INC_STDLIB +#define _INC_STDLIB + +#if !defined(_WIN32) && !defined(_MAC) +#error ERROR: Only Mac or Win32 targets supported! +#endif + + +#ifdef _MSC_VER +/* + * Currently, all MS C compilers for Win32 platforms default to 8 byte + * alignment. + */ +#pragma pack(push,8) +#endif /* _MSC_VER */ + +#ifdef __cplusplus +extern "C" { +#endif + + + +/* Define _CRTIMP */ + +#ifndef _CRTIMP +#ifdef _DLL +#define _CRTIMP __declspec(dllimport) +#else /* ndef _DLL */ +#define _CRTIMP +#endif /* _DLL */ +#endif /* _CRTIMP */ + + +/* Define __cdecl for non-Microsoft compilers */ + +#if ( !defined(_MSC_VER) && !defined(__cdecl) ) +#define __cdecl +#endif + +/* Define _CRTAPI1 (for compatibility with the NT SDK) */ + +#ifndef _CRTAPI1 +#if _MSC_VER >= 800 && _M_IX86 >= 300 +#define _CRTAPI1 __cdecl +#else +#define _CRTAPI1 +#endif +#endif + + +#ifndef _SIZE_T_DEFINED +typedef unsigned int size_t; +#define _SIZE_T_DEFINED +#endif + + +#ifndef _WCHAR_T_DEFINED +typedef unsigned short wchar_t; +#define _WCHAR_T_DEFINED +#endif + + +/* Define NULL pointer value */ + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + + +/* Definition of the argument values for the exit() function */ + +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 + + +#ifndef _ONEXIT_T_DEFINED +typedef int (__cdecl * _onexit_t)(void); +#if !__STDC__ +/* Non-ANSI name for compatibility */ +#define onexit_t _onexit_t +#endif +#define _ONEXIT_T_DEFINED +#endif + + +/* Data structure definitions for div and ldiv runtimes. */ + +#ifndef _DIV_T_DEFINED + +typedef struct _div_t { + int quot; + int rem; +} div_t; + +typedef struct _ldiv_t { + long quot; + long rem; +} ldiv_t; + +#define _DIV_T_DEFINED +#endif + + +/* Maximum value that can be returned by the rand function. */ + +#define RAND_MAX 0x7fff + +/* + * Maximum number of bytes in multi-byte character in the current locale + * (also defined in ctype.h). + */ +#ifndef MB_CUR_MAX +#define MB_CUR_MAX __mb_cur_max +_CRTIMP extern int __mb_cur_max; +#endif /* MB_CUR_MAX */ + + +/* Minimum and maximum macros */ + +#define __max(a,b) (((a) > (b)) ? (a) : (b)) +#define __min(a,b) (((a) < (b)) ? (a) : (b)) + +/* + * Sizes for buffers used by the _makepath() and _splitpath() functions. + * note that the sizes include space for 0-terminator + */ +#ifndef _MAC +#define _MAX_PATH 260 /* max. length of full pathname */ +#define _MAX_DRIVE 3 /* max. length of drive component */ +#define _MAX_DIR 256 /* max. length of path component */ +#define _MAX_FNAME 256 /* max. length of file name component */ +#define _MAX_EXT 256 /* max. length of extension component */ +#else /* def _MAC */ +#define _MAX_PATH 256 /* max. length of full pathname */ +#define _MAX_DIR 32 /* max. length of path component */ +#define _MAX_FNAME 64 /* max. length of file name component */ +#endif /* _MAC */ + +/* + * Argument values for _set_error_mode(). + */ +#define _OUT_TO_DEFAULT 0 +#define _OUT_TO_STDERR 1 +#define _OUT_TO_MSGBOX 2 +#define _REPORT_ERRMODE 3 + + +/* External variable declarations */ + +#if (defined(_MT) || defined(_DLL)) && !defined(_MAC) +_CRTIMP int * __cdecl _errno(void); +_CRTIMP unsigned long * __cdecl __doserrno(void); +#define errno (*_errno()) +#define _doserrno (*__doserrno()) +#else /* ndef _MT && ndef _DLL */ +_CRTIMP extern int errno; /* XENIX style error number */ +_CRTIMP extern unsigned long _doserrno; /* OS system error value */ +#endif /* _MT || _DLL */ + + +#ifdef _MAC +_CRTIMP extern int _macerrno; /* OS system error value */ +#endif + + +_CRTIMP extern char * _sys_errlist[]; /* perror error message table */ +_CRTIMP extern int _sys_nerr; /* # of entries in sys_errlist table */ + + +#if defined(_DLL) && defined(_M_IX86) + +#define __argc (*__p___argc()) /* count of cmd line args */ +#define __argv (*__p___argv()) /* pointer to table of cmd line args */ +#define __wargv (*__p___wargv()) /* pointer to table of wide cmd line args */ +#define _environ (*__p__environ()) /* pointer to environment table */ +#ifdef _POSIX_ +extern char ** environ; /* pointer to environment table */ +#else +#ifndef _MAC +#define _wenviron (*__p__wenviron()) /* pointer to wide environment table */ +#endif /* ndef _MAC */ +#endif /* _POSIX_ */ +#define _pgmptr (*__p__pgmptr()) /* points to the module (EXE) name */ +#ifndef _MAC +#define _wpgmptr (*__p__wpgmptr()) /* points to the module (EXE) wide name */ +#endif /* ndef _MAC */ + +_CRTIMP int * __cdecl __p___argc(void); +_CRTIMP char *** __cdecl __p___argv(void); +_CRTIMP wchar_t *** __cdecl __p___wargv(void); +_CRTIMP char *** __cdecl __p__environ(void); +_CRTIMP wchar_t *** __cdecl __p__wenviron(void); +_CRTIMP char ** __cdecl __p__pgmptr(void); +_CRTIMP wchar_t ** __cdecl __p__wpgmptr(void); + + +#else + +_CRTIMP extern int __argc; /* count of cmd line args */ +_CRTIMP extern char ** __argv; /* pointer to table of cmd line args */ +#ifndef _MAC +_CRTIMP extern wchar_t ** __wargv; /* pointer to table of wide cmd line args */ +#endif /* ndef _MAC */ + +#ifdef _POSIX_ +extern char ** environ; /* pointer to environment table */ +#else +_CRTIMP extern char ** _environ; /* pointer to environment table */ +#ifndef _MAC +_CRTIMP extern wchar_t ** _wenviron; /* pointer to wide environment table */ +#endif /* ndef _MAC */ +#endif /* _POSIX_ */ + +_CRTIMP extern char * _pgmptr; /* points to the module (EXE) name */ +#ifndef _MAC +_CRTIMP extern wchar_t * _wpgmptr; /* points to the module (EXE) wide name */ +#endif /* ndef _MAC */ + +#endif + + +_CRTIMP extern int _fmode; /* default file translation mode */ +_CRTIMP extern int _fileinfo; /* open file info mode (for spawn) */ + + +/* Windows major/minor and O.S. version numbers */ + +_CRTIMP extern unsigned int _osver; +_CRTIMP extern unsigned int _winver; +_CRTIMP extern unsigned int _winmajor; +_CRTIMP extern unsigned int _winminor; + + +/* function prototypes */ + +#if _MSC_VER >= 1200 +_CRTIMP __declspec(noreturn) void __cdecl abort(void); +_CRTIMP __declspec(noreturn) void __cdecl exit(int); +#else +_CRTIMP void __cdecl abort(void); +_CRTIMP void __cdecl exit(int); +#endif + +#if defined(_M_MRX000) +_CRTIMP int __cdecl abs(int); +#else + int __cdecl abs(int); +#endif + int __cdecl atexit(void (__cdecl *)(void)); +_CRTIMP double __cdecl atof(const char *); +_CRTIMP int __cdecl atoi(const char *); +_CRTIMP long __cdecl atol(const char *); +#ifdef _M_M68K +_CRTIMP long double __cdecl _atold(const char *); +#endif +_CRTIMP void * __cdecl bsearch(const void *, const void *, size_t, size_t, + int (__cdecl *)(const void *, const void *)); + +#ifndef _CRTDBG_MAP_ALLOC +_CRTIMP void * __cdecl calloc(size_t, size_t); +#endif + +_CRTIMP div_t __cdecl div(int, int); +_CRTIMP void __cdecl free(void *); +_CRTIMP char * __cdecl getenv(const char *); +_CRTIMP char * __cdecl _itoa(int, char *, int); +#if _INTEGRAL_MAX_BITS >= 64 +_CRTIMP char * __cdecl _i64toa(__int64, char *, int); +_CRTIMP char * __cdecl _ui64toa(unsigned __int64, char *, int); +_CRTIMP __int64 __cdecl _atoi64(const char *); +#endif +#if defined(_M_MRX000) +_CRTIMP long __cdecl labs(long); +#else + long __cdecl labs(long); +#endif +_CRTIMP ldiv_t __cdecl ldiv(long, long); +_CRTIMP char * __cdecl _ltoa(long, char *, int); + +#ifndef _CRTDBG_MAP_ALLOC +_CRTIMP void * __cdecl malloc(size_t); +#endif + +_CRTIMP int __cdecl mblen(const char *, size_t); +_CRTIMP size_t __cdecl _mbstrlen(const char *s); +_CRTIMP int __cdecl mbtowc(wchar_t *, const char *, size_t); +_CRTIMP size_t __cdecl mbstowcs(wchar_t *, const char *, size_t); +_CRTIMP void __cdecl qsort(void *, size_t, size_t, int (__cdecl *) + (const void *, const void *)); +_CRTIMP int __cdecl rand(void); + +#ifndef _CRTDBG_MAP_ALLOC +_CRTIMP void * __cdecl realloc(void *, size_t); +#endif + +_CRTIMP int __cdecl _set_error_mode(int); +_CRTIMP void __cdecl srand(unsigned int); +_CRTIMP double __cdecl strtod(const char *, char **); +_CRTIMP long __cdecl strtol(const char *, char **, int); +#ifdef _M_M68K +_CRTIMP long double __cdecl _strtold(const char *, char **); +#endif +_CRTIMP unsigned long __cdecl strtoul(const char *, char **, int); +#ifndef _MAC +_CRTIMP int __cdecl system(const char *); +#endif +_CRTIMP char * __cdecl _ultoa(unsigned long, char *, int); +_CRTIMP int __cdecl wctomb(char *, wchar_t); +_CRTIMP size_t __cdecl wcstombs(char *, const wchar_t *, size_t); + + +#ifndef _MAC +#ifndef _WSTDLIB_DEFINED + +/* wide function prototypes, also declared in wchar.h */ + +_CRTIMP wchar_t * __cdecl _itow (int, wchar_t *, int); +_CRTIMP wchar_t * __cdecl _ltow (long, wchar_t *, int); +_CRTIMP wchar_t * __cdecl _ultow (unsigned long, wchar_t *, int); +_CRTIMP double __cdecl wcstod(const wchar_t *, wchar_t **); +_CRTIMP long __cdecl wcstol(const wchar_t *, wchar_t **, int); +_CRTIMP unsigned long __cdecl wcstoul(const wchar_t *, wchar_t **, int); +_CRTIMP wchar_t * __cdecl _wgetenv(const wchar_t *); +_CRTIMP int __cdecl _wsystem(const wchar_t *); +_CRTIMP int __cdecl _wtoi(const wchar_t *); +_CRTIMP long __cdecl _wtol(const wchar_t *); +#if _INTEGRAL_MAX_BITS >= 64 +_CRTIMP wchar_t * __cdecl _i64tow(__int64, wchar_t *, int); +_CRTIMP wchar_t * __cdecl _ui64tow(unsigned __int64, wchar_t *, int); +_CRTIMP __int64 __cdecl _wtoi64(const wchar_t *); +#endif + +#define _WSTDLIB_DEFINED +#endif +#endif /* ndef _MAC */ + + +#ifndef _POSIX_ + +_CRTIMP char * __cdecl _ecvt(double, int, int *, int *); +#if _MSC_VER >= 1200 +_CRTIMP __declspec(noreturn) void __cdecl _exit(int); +#else +_CRTIMP void __cdecl _exit(int); +#endif +_CRTIMP char * __cdecl _fcvt(double, int, int *, int *); +_CRTIMP char * __cdecl _fullpath(char *, const char *, size_t); +_CRTIMP char * __cdecl _gcvt(double, int, char *); + unsigned long __cdecl _lrotl(unsigned long, int); + unsigned long __cdecl _lrotr(unsigned long, int); +#ifndef _MAC +_CRTIMP void __cdecl _makepath(char *, const char *, const char *, const char *, + const char *); +#endif + _onexit_t __cdecl _onexit(_onexit_t); +_CRTIMP void __cdecl perror(const char *); +_CRTIMP int __cdecl _putenv(const char *); + unsigned int __cdecl _rotl(unsigned int, int); + unsigned int __cdecl _rotr(unsigned int, int); +_CRTIMP void __cdecl _searchenv(const char *, const char *, char *); +#ifndef _MAC +_CRTIMP void __cdecl _splitpath(const char *, char *, char *, char *, char *); +#endif +_CRTIMP void __cdecl _swab(char *, char *, int); + +#ifndef _MAC +#ifndef _WSTDLIBP_DEFINED + +/* wide function prototypes, also declared in wchar.h */ + +_CRTIMP wchar_t * __cdecl _wfullpath(wchar_t *, const wchar_t *, size_t); +_CRTIMP void __cdecl _wmakepath(wchar_t *, const wchar_t *, const wchar_t *, const wchar_t *, + const wchar_t *); +_CRTIMP void __cdecl _wperror(const wchar_t *); +_CRTIMP int __cdecl _wputenv(const wchar_t *); +_CRTIMP void __cdecl _wsearchenv(const wchar_t *, const wchar_t *, wchar_t *); +_CRTIMP void __cdecl _wsplitpath(const wchar_t *, wchar_t *, wchar_t *, wchar_t *, wchar_t *); + +#define _WSTDLIBP_DEFINED +#endif +#endif /* ndef _MAC */ + +/* --------- The following functions are OBSOLETE --------- */ +/* The Win32 API SetErrorMode, Beep and Sleep should be used instead. */ +#ifndef _MAC +_CRTIMP void __cdecl _seterrormode(int); +_CRTIMP void __cdecl _beep(unsigned, unsigned); +_CRTIMP void __cdecl _sleep(unsigned long); +#endif /* ndef _MAC */ +/* --------- The preceding functions are OBSOLETE --------- */ + +#endif /* _POSIX_ */ + + +#if !__STDC__ +/* --------- The declarations below should not be in stdlib.h --------- */ +/* --------- and will be removed in a future release. Include --------- */ +/* --------- ctype.h to obtain these declarations. --------- */ +#ifndef tolower /* tolower has been undefined - use function */ +_CRTIMP int __cdecl tolower(int); +#endif /* tolower */ +#ifndef toupper /* toupper has been undefined - use function */ +_CRTIMP int __cdecl toupper(int); +#endif /* toupper */ +/* --------- The declarations above will be removed. --------- */ +#endif + + +#if !__STDC__ + +#ifndef _POSIX_ + +/* Non-ANSI names for compatibility */ + +#ifndef __cplusplus +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#define sys_errlist _sys_errlist +#define sys_nerr _sys_nerr +#define environ _environ + +_CRTIMP char * __cdecl ecvt(double, int, int *, int *); +_CRTIMP char * __cdecl fcvt(double, int, int *, int *); +_CRTIMP char * __cdecl gcvt(double, int, char *); +_CRTIMP char * __cdecl itoa(int, char *, int); +_CRTIMP char * __cdecl ltoa(long, char *, int); + onexit_t __cdecl onexit(onexit_t); +_CRTIMP int __cdecl putenv(const char *); +_CRTIMP void __cdecl swab(char *, char *, int); +_CRTIMP char * __cdecl ultoa(unsigned long, char *, int); + +#endif /* _POSIX_ */ + +#endif /* __STDC__ */ + +#ifdef __cplusplus +} + +#endif + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ + +#endif /* _INC_STDLIB */ diff --git a/abc70930/src/misc/util/util_hack.h b/abc70930/src/misc/util/util_hack.h new file mode 100644 index 00000000..71c77321 --- /dev/null +++ b/abc70930/src/misc/util/util_hack.h @@ -0,0 +1,95 @@ +/**CFile**************************************************************** + + FileName [util_hack.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [This file is used to simulate the presence of "util.h".] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: util_hack.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __UTIL_HACK_H__ +#define __UTIL_HACK_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include +#include + +#define EXTERN extern +#define NIL(type) ((type *) 0) +#define random rand +#define srandom srand + +#define util_cpu_time Extra_CpuTime +#define getSoftDataLimit Extra_GetSoftDataLimit +#define util_getopt_reset Extra_UtilGetoptReset +#define util_getopt Extra_UtilGetopt +#define util_print_time Extra_UtilPrintTime +#define util_strsav Extra_UtilStrsav +#define util_tilde_expand Extra_UtilTildeExpand +#define util_file_search Extra_UtilFileSearch +#define MMoutOfMemory Extra_UtilMMoutOfMemory + +#define util_optarg globalUtilOptarg +#define util_optind globalUtilOptind + +#ifndef ARGS +# ifdef __STDC__ +# define ARGS(args) args +# else +# define ARGS(args) () +# endif +#endif + +#ifndef ABS +# define ABS(a) ((a) < 0 ? -(a) : (a)) +#endif + +#ifndef MAX +# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#define REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) + +extern long Extra_CpuTime(); +extern int Extra_GetSoftDataLimit(); +extern void Extra_UtilGetoptReset(); +extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring ); +extern char * Extra_UtilPrintTime( long t ); +extern char * Extra_UtilStrsav( char *s ); +extern char * Extra_UtilTildeExpand( char *fname ); +extern char * Extra_UtilFileSearch( char *file, char *path, char *mode ); + +extern char * globalUtilOptarg; +extern int globalUtilOptind; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/abc70930/src/misc/vec/module.make b/abc70930/src/misc/vec/module.make new file mode 100644 index 00000000..d6d908e7 --- /dev/null +++ b/abc70930/src/misc/vec/module.make @@ -0,0 +1 @@ +SRC += diff --git a/abc70930/src/misc/vec/vec.h b/abc70930/src/misc/vec/vec.h new file mode 100644 index 00000000..6a97fcaa --- /dev/null +++ b/abc70930/src/misc/vec/vec.h @@ -0,0 +1,110 @@ +/**CFile**************************************************************** + + FileName [vec.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resizable arrays.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __VEC_H__ +#define __VEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#pragma warning(disable : 4152) // warning C4152: nonstandard extension, function/data pointer conversion in expression +#pragma warning(disable : 4244) // warning C4244: '+=' : conversion from 'int ' to 'unsigned short ', possible loss of data +#pragma warning(disable : 4514) // warning C4514: 'Vec_StrPop' : unreferenced inline function has been removed +#pragma warning(disable : 4710) // warning C4710: function 'Vec_PtrGrow' not inlined +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +// this include should be the first one in the list +// it is used to catch memory leaks on Windows +#include "leaks.h" + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifndef ABS +#define ABS(a) ((a) < 0 ? -(a) : (a)) +#endif + +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef ALLOC +#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#endif + +#ifndef FREE +#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#endif + +#ifndef REALLOC +#define REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) +#endif + +#ifndef PRT +#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) +#endif + +#ifndef PRTP +#define PRTP(a,t,T) printf("%s = ", (a)); printf("%6.2f sec (%6.2f %%)\n", (float)(t)/(float)(CLOCKS_PER_SEC), (T)? 100.0*(t)/(T) : 0.0) +#endif + +#include "vecInt.h" +#include "vecFlt.h" +#include "vecStr.h" +#include "vecPtr.h" +#include "vecVec.h" +#include "vecAtt.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/misc/vec/vecAtt.h b/abc70930/src/misc/vec/vecAtt.h new file mode 100644 index 00000000..da7a8445 --- /dev/null +++ b/abc70930/src/misc/vec/vecAtt.h @@ -0,0 +1,391 @@ +/**CFile**************************************************************** + + FileName [vecAtt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resizable arrays.] + + Synopsis [Array of user-specified attiributes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: vecAtt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __Vec_Att_H__ +#define __Vec_Att_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// various attributes +typedef enum { + VEC_ATTR_NONE = 0, // 0 + VEC_ATTR_COPY, // 1 + VEC_ATTR_LOCAL_AIG, // 2 + VEC_ATTR_LOCAL_SOP, // 3 + VEC_ATTR_LOCAL_BDD, // 4 + VEC_ATTR_GLOBAL_AIG, // 5 + VEC_ATTR_GLOBAL_SOP, // 6 + VEC_ATTR_GLOBAL_BDD, // 7 + VEC_ATTR_LEVEL, // 8 + VEC_ATTR_LEVEL_REV, // 9 + VEC_ATTR_RETIME_LAG, // 10 + VEC_ATTR_FRAIG, // 11 + VEC_ATTR_MVVAR, // 12 + VEC_ATTR_DATA1, // 13 + VEC_ATTR_DATA2, // 14 + VEC_ATTR_TOTAL_NUM // 15 +} Vec_AttrType_t; + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Vec_Att_t_ Vec_Att_t; +struct Vec_Att_t_ +{ + // storage for attributes + int nCap; // the size of array allocated + int * pArrayInt; // the integer attribute array + void ** pArrayPtr; // the pointer attribute array + // attribute specific info + void * pMan; // the manager for this attribute + void (*pFuncFreeMan) (void *); // the procedure to free the manager + void*(*pFuncStartObj)(void *); // the procedure to start one attribute + void (*pFuncFreeObj) (void *, void *); // the procedure to free one attribute +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Att_t * Vec_AttAlloc( + int fInteger, int nSize, void * pMan, + void (*pFuncFreeMan) (void *), + void*(*pFuncStartObj)(void *), + void (*pFuncFreeObj) (void *, void *) ) +{ + Vec_Att_t * p; + p = ALLOC( Vec_Att_t, 1 ); + memset( p, 0, sizeof(Vec_Att_t) ); + p->pMan = pMan; + p->pFuncFreeMan = pFuncFreeMan; + p->pFuncStartObj = pFuncStartObj; + p->pFuncFreeObj = pFuncFreeObj; + p->nCap = nSize? nSize : 16; + if ( fInteger ) + { + p->pArrayInt = ALLOC( int, p->nCap ); + memset( p->pArrayInt, 0xff, sizeof(int) * p->nCap ); + } + else + { + p->pArrayPtr = ALLOC( void *, p->nCap ); + memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Vec_AttFree( Vec_Att_t * p, int fFreeMan ) +{ + void * pMan; + if ( p == NULL ) + return NULL; + // free the attributes of objects + if ( p->pFuncFreeObj ) + { + int i; + if ( p->pArrayInt ) + { + for ( i = 0; i < p->nCap; i++ ) + if ( p->pArrayInt[i] ) + p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] ); + } + else + { + for ( i = 0; i < p->nCap; i++ ) + if ( p->pArrayPtr[i] ) + p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] ); + } + } + // free the memory manager + pMan = fFreeMan? NULL : p->pMan; + if ( p->pMan && fFreeMan ) + p->pFuncFreeMan( p->pMan ); + FREE( p->pArrayInt ); + FREE( p->pArrayPtr ); + FREE( p ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Clears the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_AttClear( Vec_Att_t * p ) +{ + // free the attributes of objects + if ( p->pFuncFreeObj ) + { + int i; + if ( p->pArrayInt ) + { + if ( p->pFuncFreeObj ) + for ( i = 0; i < p->nCap; i++ ) + if ( p->pArrayInt[i] ) + p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] ); + } + else + { + if ( p->pFuncFreeObj ) + for ( i = 0; i < p->nCap; i++ ) + if ( p->pArrayPtr[i] ) + p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] ); + } + } + if ( p->pArrayInt ) + memset( p->pArrayInt, 0xff, sizeof(int) * p->nCap ); + else + memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap ); + +} + +/**Function************************************************************* + + Synopsis [Deletes one entry from the attribute manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_AttFreeEntry( Vec_Att_t * p, int i ) +{ + if ( i >= p->nCap ) + return; + if ( p->pMan ) + { + if ( p->pArrayInt[i] && p->pFuncFreeObj ) + p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] ); + if ( p->pArrayPtr[i] && p->pFuncFreeObj ) + p->pFuncFreeObj( p->pMan, (void *)p->pArrayPtr[i] ); + } + if ( p->pArrayInt ) + p->pArrayInt[i] = ~(unsigned)0; + else + p->pArrayPtr[i] = NULL; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_AttGrow( Vec_Att_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + if ( p->pArrayInt ) + { + p->pArrayInt = REALLOC( int, p->pArrayInt, nCapMin ); + memset( p->pArrayInt + p->nCap, 0xff, sizeof(int) * (nCapMin - p->nCap) ); + } + else + { + p->pArrayPtr = REALLOC( void *, p->pArrayPtr, nCapMin ); + memset( p->pArrayPtr + p->nCap, 0, sizeof(void *) * (nCapMin - p->nCap) ); + } + p->nCap = nCapMin; +} + +/**Function************************************************************* + + Synopsis [Writes the entry into its place.] + + Description [Only works if the manager is not defined.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_AttWriteEntry( Vec_Att_t * p, int i, void * pEntry ) +{ + assert( p->pArrayPtr ); + assert( p->pFuncStartObj == NULL ); + if ( i >= p->nCap ) + Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 ); + p->pArrayPtr[i] = pEntry; +} + +/**Function************************************************************* + + Synopsis [Writes the entry into its place.] + + Description [Only works if the manager is not defined.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_AttWriteEntryInt( Vec_Att_t * p, int i, int Entry ) +{ + assert( p->pArrayInt ); + assert( p->pFuncStartObj == NULL ); + if ( i >= p->nCap ) + Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 ); + p->pArrayInt[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [Returns the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Vec_AttEntry( Vec_Att_t * p, int i ) +{ + assert( p->pArrayPtr ); + if ( i >= p->nCap ) + Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 ); + if ( p->pArrayPtr[i] == NULL && p->pFuncStartObj ) + p->pArrayPtr[i] = p->pFuncStartObj( p->pMan ); + return p->pArrayPtr[i]; +} + +/**Function************************************************************* + + Synopsis [Returns the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_AttEntryInt( Vec_Att_t * p, int i ) +{ + assert( p->pArrayInt ); + assert( p->pMan == NULL ); + if ( i >= p->nCap ) + Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 ); + return p->pArrayInt[i]; +} + +/**Function************************************************************* + + Synopsis [Returns the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Vec_AttMan( Vec_Att_t * p ) +{ + return p->pMan; +} + +/**Function************************************************************* + + Synopsis [Returns the array of attributes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void ** Vec_AttArray( Vec_Att_t * p ) +{ + return p->pArrayPtr; +} + +/**Function************************************************************* + + Synopsis [Returns the array of attributes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int * Vec_AttArrayInt( Vec_Att_t * p ) +{ + return p->pArrayInt; +} + +#endif + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/misc/vec/vecFlt.h b/abc70930/src/misc/vec/vecFlt.h new file mode 100644 index 00000000..6b36ce84 --- /dev/null +++ b/abc70930/src/misc/vec/vecFlt.h @@ -0,0 +1,630 @@ +/**CFile**************************************************************** + + FileName [vecFlt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resizable arrays.] + + Synopsis [Resizable arrays of floats.] + + Author [Aaron P. Hurst] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __VEC_FLT_H__ +#define __VEC_FLT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Vec_Flt_t_ Vec_Flt_t; +struct Vec_Flt_t_ +{ + int nCap; + int nSize; + float * pArray; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Vec_FltForEachEntry( vVec, Entry, i ) \ + for ( i = 0; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) +#define Vec_FltForEachEntryStart( vVec, Entry, i, Start ) \ + for ( i = Start; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) +#define Vec_FltForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \ + for ( i = Start; (i < Stop) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) +#define Vec_FltForEachEntryReverse( vVec, pEntry, i ) \ + for ( i = Vec_FltSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_FltEntry(vVec, i)), 1); i-- ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Flt_t * Vec_FltAlloc( int nCap ) +{ + Vec_Flt_t * p; + p = ALLOC( Vec_Flt_t, 1 ); + if ( nCap > 0 && nCap < 16 ) + nCap = 16; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? ALLOC( float, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given size and cleans it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Flt_t * Vec_FltStart( int nSize ) +{ + Vec_Flt_t * p; + p = Vec_FltAlloc( nSize ); + p->nSize = nSize; + memset( p->pArray, 0, sizeof(float) * nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the vector from a float array of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Flt_t * Vec_FltAllocArray( float * pArray, int nSize ) +{ + Vec_Flt_t * p; + p = ALLOC( Vec_Flt_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = pArray; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the vector from a float array of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Flt_t * Vec_FltAllocArrayCopy( float * pArray, int nSize ) +{ + Vec_Flt_t * p; + p = ALLOC( Vec_Flt_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = ALLOC( float, nSize ); + memcpy( p->pArray, pArray, sizeof(float) * nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the float array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Flt_t * Vec_FltDup( Vec_Flt_t * pVec ) +{ + Vec_Flt_t * p; + p = ALLOC( Vec_Flt_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nCap; + p->pArray = p->nCap? ALLOC( float, p->nCap ) : NULL; + memcpy( p->pArray, pVec->pArray, sizeof(float) * pVec->nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Transfers the array into another vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Flt_t * Vec_FltDupArray( Vec_Flt_t * pVec ) +{ + Vec_Flt_t * p; + p = ALLOC( Vec_Flt_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nCap; + p->pArray = pVec->pArray; + pVec->nSize = 0; + pVec->nCap = 0; + pVec->pArray = NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FltFree( Vec_Flt_t * p ) +{ + FREE( p->pArray ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float * Vec_FltReleaseArray( Vec_Flt_t * p ) +{ + float * pArray = p->pArray; + p->nCap = 0; + p->nSize = 0; + p->pArray = NULL; + return pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float * Vec_FltArray( Vec_Flt_t * p ) +{ + return p->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_FltSize( Vec_Flt_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Vec_FltEntry( Vec_Flt_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FltWriteEntry( Vec_Flt_t * p, int i, float Entry ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FltAddToEntry( Vec_Flt_t * p, int i, float Addition ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] += Addition; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Vec_FltEntryLast( Vec_Flt_t * p ) +{ + return p->pArray[p->nSize-1]; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FltGrow( Vec_Flt_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = REALLOC( float, p->pArray, nCapMin ); + p->nCap = nCapMin; +} + +/**Function************************************************************* + + Synopsis [Fills the vector with given number of entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FltFill( Vec_Flt_t * p, int nSize, float Entry ) +{ + int i; + Vec_FltGrow( p, nSize ); + for ( i = 0; i < nSize; i++ ) + p->pArray[i] = Entry; + p->nSize = nSize; +} + +/**Function************************************************************* + + Synopsis [Fills the vector with given number of entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FltFillExtra( Vec_Flt_t * p, int nSize, float Entry ) +{ + int i; + if ( p->nSize >= nSize ) + return; + Vec_FltGrow( p, nSize ); + for ( i = p->nSize; i < nSize; i++ ) + p->pArray[i] = Entry; + p->nSize = nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FltShrink( Vec_Flt_t * p, int nSizeNew ) +{ + assert( p->nSize >= nSizeNew ); + p->nSize = nSizeNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FltClear( Vec_Flt_t * p ) +{ + p->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FltPush( Vec_Flt_t * p, float Entry ) +{ + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Vec_FltGrow( p, 16 ); + else + Vec_FltGrow( p, 2 * p->nCap ); + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FltPushOrder( Vec_Flt_t * p, float Entry ) +{ + int i; + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Vec_FltGrow( p, 16 ); + else + Vec_FltGrow( p, 2 * p->nCap ); + } + p->nSize++; + for ( i = p->nSize-2; i >= 0; i-- ) + if ( p->pArray[i] > Entry ) + p->pArray[i+1] = p->pArray[i]; + else + break; + p->pArray[i+1] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_FltPushUnique( Vec_Flt_t * p, float Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return 1; + Vec_FltPush( p, Entry ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the last entry and removes it from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Vec_FltPop( Vec_Flt_t * p ) +{ + assert( p->nSize > 0 ); + return p->pArray[--p->nSize]; +} + +/**Function************************************************************* + + Synopsis [Find entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_FltFind( Vec_Flt_t * p, float Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_FltRemove( Vec_Flt_t * p, float Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + break; + if ( i == p->nSize ) + return 0; + assert( i < p->nSize ); + for ( i++; i < p->nSize; i++ ) + p->pArray[i-1] = p->pArray[i]; + p->nSize--; + return 1; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two floats.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_FltSortCompare1( float * pp1, float * pp2 ) +{ + // for some reason commenting out lines (as shown) led to crashing of the release version + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) // + return 1; + return 0; // +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two floats.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_FltSortCompare2( float * pp1, float * pp2 ) +{ + // for some reason commenting out lines (as shown) led to crashing of the release version + if ( *pp1 > *pp2 ) + return -1; + if ( *pp1 < *pp2 ) // + return 1; + return 0; // +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_FltSort( Vec_Flt_t * p, int fReverse ) +{ + if ( fReverse ) + qsort( (void *)p->pArray, p->nSize, sizeof(float), + (int (*)(const void *, const void *)) Vec_FltSortCompare2 ); + else + qsort( (void *)p->pArray, p->nSize, sizeof(float), + (int (*)(const void *, const void *)) Vec_FltSortCompare1 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/abc70930/src/misc/vec/vecInt.h b/abc70930/src/misc/vec/vecInt.h new file mode 100644 index 00000000..082ebe70 --- /dev/null +++ b/abc70930/src/misc/vec/vecInt.h @@ -0,0 +1,834 @@ +/**CFile**************************************************************** + + FileName [vecInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resizable arrays.] + + Synopsis [Resizable arrays of integers.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __VEC_INT_H__ +#define __VEC_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Vec_Int_t_ Vec_Int_t; +struct Vec_Int_t_ +{ + int nCap; + int nSize; + int * pArray; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Vec_IntForEachEntry( vVec, Entry, i ) \ + for ( i = 0; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) +#define Vec_IntForEachEntryStart( vVec, Entry, i, Start ) \ + for ( i = Start; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) +#define Vec_IntForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \ + for ( i = Start; (i < Stop) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) +#define Vec_IntForEachEntryReverse( vVec, pEntry, i ) \ + for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_IntEntry(vVec, i)), 1); i-- ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Int_t * Vec_IntAlloc( int nCap ) +{ + Vec_Int_t * p; + p = ALLOC( Vec_Int_t, 1 ); + if ( nCap > 0 && nCap < 16 ) + nCap = 16; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given size and cleans it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Int_t * Vec_IntStart( int nSize ) +{ + Vec_Int_t * p; + p = Vec_IntAlloc( nSize ); + p->nSize = nSize; + memset( p->pArray, 0, sizeof(int) * nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given size and cleans it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Int_t * Vec_IntStartNatural( int nSize ) +{ + Vec_Int_t * p; + int i; + p = Vec_IntAlloc( nSize ); + p->nSize = nSize; + for ( i = 0; i < nSize; i++ ) + p->pArray[i] = i; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the vector from an integer array of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Int_t * Vec_IntAllocArray( int * pArray, int nSize ) +{ + Vec_Int_t * p; + p = ALLOC( Vec_Int_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = pArray; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the vector from an integer array of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Int_t * Vec_IntAllocArrayCopy( int * pArray, int nSize ) +{ + Vec_Int_t * p; + p = ALLOC( Vec_Int_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = ALLOC( int, nSize ); + memcpy( p->pArray, pArray, sizeof(int) * nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the integer array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Int_t * Vec_IntDup( Vec_Int_t * pVec ) +{ + Vec_Int_t * p; + p = ALLOC( Vec_Int_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nSize; + p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL; + memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Transfers the array into another vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Int_t * Vec_IntDupArray( Vec_Int_t * pVec ) +{ + Vec_Int_t * p; + p = ALLOC( Vec_Int_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nCap; + p->pArray = pVec->pArray; + pVec->nSize = 0; + pVec->nCap = 0; + pVec->pArray = NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntFree( Vec_Int_t * p ) +{ + FREE( p->pArray ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int * Vec_IntReleaseArray( Vec_Int_t * p ) +{ + int * pArray = p->pArray; + p->nCap = 0; + p->nSize = 0; + p->pArray = NULL; + return pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int * Vec_IntArray( Vec_Int_t * p ) +{ + return p->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntSize( Vec_Int_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntEntry( Vec_Int_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] += Addition; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntEntryLast( Vec_Int_t * p ) +{ + assert( p->nSize > 0 ); + return p->pArray[p->nSize-1]; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = REALLOC( int, p->pArray, nCapMin ); + assert( p->pArray ); + p->nCap = nCapMin; +} + +/**Function************************************************************* + + Synopsis [Fills the vector with given number of entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntFill( Vec_Int_t * p, int nSize, int Entry ) +{ + int i; + Vec_IntGrow( p, nSize ); + for ( i = 0; i < nSize; i++ ) + p->pArray[i] = Entry; + p->nSize = nSize; +} + +/**Function************************************************************* + + Synopsis [Fills the vector with given number of entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntFillExtra( Vec_Int_t * p, int nSize, int Entry ) +{ + int i; + if ( p->nSize >= nSize ) + return; + Vec_IntGrow( p, nSize ); + for ( i = p->nSize; i < nSize; i++ ) + p->pArray[i] = Entry; + p->nSize = nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntShrink( Vec_Int_t * p, int nSizeNew ) +{ + assert( p->nSize >= nSizeNew ); + p->nSize = nSizeNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntClear( Vec_Int_t * p ) +{ + p->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntPush( Vec_Int_t * p, int Entry ) +{ + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Vec_IntGrow( p, 16 ); + else + Vec_IntGrow( p, 2 * p->nCap ); + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntPushFirst( Vec_Int_t * p, int Entry ) +{ + int i; + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Vec_IntGrow( p, 16 ); + else + Vec_IntGrow( p, 2 * p->nCap ); + } + p->nSize++; + for ( i = p->nSize - 1; i >= 1; i-- ) + p->pArray[i] = p->pArray[i-1]; + p->pArray[0] = Entry; +} + +/**Function************************************************************* + + Synopsis [Inserts the entry while preserving the increasing order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry ) +{ + int i; + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Vec_IntGrow( p, 16 ); + else + Vec_IntGrow( p, 2 * p->nCap ); + } + p->nSize++; + for ( i = p->nSize-2; i >= 0; i-- ) + if ( p->pArray[i] > Entry ) + p->pArray[i+1] = p->pArray[i]; + else + break; + p->pArray[i+1] = Entry; +} + +/**Function************************************************************* + + Synopsis [Inserts the entry while preserving the increasing order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntPushUniqueOrder( Vec_Int_t * p, int Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return 1; + Vec_IntPushOrder( p, Entry ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntPushUnique( Vec_Int_t * p, int Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return 1; + Vec_IntPush( p, Entry ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the next nWords entries in the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned * Vec_IntFetch( Vec_Int_t * p, int nWords ) +{ + if ( nWords == 0 ) + return NULL; + assert( nWords > 0 ); + p->nSize += nWords; + if ( p->nSize > p->nCap ) + { +// Vec_IntGrow( p, 2 * p->nSize ); + return NULL; + } + return ((unsigned *)p->pArray) + p->nSize - nWords; +} + +/**Function************************************************************* + + Synopsis [Returns the last entry and removes it from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntPop( Vec_Int_t * p ) +{ + assert( p->nSize > 0 ); + return p->pArray[--p->nSize]; +} + +/**Function************************************************************* + + Synopsis [Find entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntFind( Vec_Int_t * p, int Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntRemove( Vec_Int_t * p, int Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + break; + if ( i == p->nSize ) + return 0; + assert( i < p->nSize ); + for ( i++; i < p->nSize; i++ ) + p->pArray[i-1] = p->pArray[i]; + p->nSize--; + return 1; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two integers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntSortCompare1( int * pp1, int * pp2 ) +{ + // for some reason commenting out lines (as shown) led to crashing of the release version + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) // + return 1; + return 0; // +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two integers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntSortCompare2( int * pp1, int * pp2 ) +{ + // for some reason commenting out lines (as shown) led to crashing of the release version + if ( *pp1 > *pp2 ) + return -1; + if ( *pp1 < *pp2 ) // + return 1; + return 0; // +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntSort( Vec_Int_t * p, int fReverse ) +{ + if ( fReverse ) + qsort( (void *)p->pArray, p->nSize, sizeof(int), + (int (*)(const void *, const void *)) Vec_IntSortCompare2 ); + else + qsort( (void *)p->pArray, p->nSize, sizeof(int), + (int (*)(const void *, const void *)) Vec_IntSortCompare1 ); +} + + +/**Function************************************************************* + + Synopsis [Comparison procedure for two integers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntSortCompareUnsigned( unsigned * pp1, unsigned * pp2 ) +{ + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntSortUnsigned( Vec_Int_t * p ) +{ + qsort( (void *)p->pArray, p->nSize, sizeof(int), + (int (*)(const void *, const void *)) Vec_IntSortCompareUnsigned ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of common entries.] + + Description [Assumes that the vectors are sorted in the increasing order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntTwoCountCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) +{ + int * pBeg1 = vArr1->pArray; + int * pBeg2 = vArr2->pArray; + int * pEnd1 = vArr1->pArray + vArr1->nSize; + int * pEnd2 = vArr2->pArray + vArr2->nSize; + int Counter = 0; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( *pBeg1 == *pBeg2 ) + pBeg1++, pBeg2++, Counter++; + else if ( *pBeg1 < *pBeg2 ) + pBeg1++; + else + pBeg2++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the result of merging the two vectors.] + + Description [Assumes that the vectors are sorted in the increasing order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) +{ + Vec_Int_t * vArr = Vec_IntAlloc( vArr1->nSize + vArr2->nSize ); + int * pBeg = vArr->pArray; + int * pBeg1 = vArr1->pArray; + int * pBeg2 = vArr2->pArray; + int * pEnd1 = vArr1->pArray + vArr1->nSize; + int * pEnd2 = vArr2->pArray + vArr2->nSize; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( *pBeg1 == *pBeg2 ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( *pBeg1 < *pBeg2 ) + *pBeg++ = *pBeg1++; + else + *pBeg++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pBeg++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pBeg++ = *pBeg2++; + vArr->nSize = pBeg - vArr->pArray; + assert( vArr->nSize <= vArr->nCap ); + assert( vArr->nSize >= vArr1->nSize ); + assert( vArr->nSize >= vArr2->nSize ); + return vArr; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/misc/vec/vecPtr.h b/abc70930/src/misc/vec/vecPtr.h new file mode 100644 index 00000000..1862bc7c --- /dev/null +++ b/abc70930/src/misc/vec/vecPtr.h @@ -0,0 +1,762 @@ +/**CFile**************************************************************** + + FileName [vecPtr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resizable arrays.] + + Synopsis [Resizable arrays of generic pointers.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: vecPtr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __VEC_PTR_H__ +#define __VEC_PTR_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Vec_Ptr_t_ Vec_Ptr_t; +struct Vec_Ptr_t_ +{ + int nCap; + int nSize; + void ** pArray; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// iterators through entries +#define Vec_PtrForEachEntry( vVec, pEntry, i ) \ + for ( i = 0; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) +#define Vec_PtrForEachEntryStart( vVec, pEntry, i, Start ) \ + for ( i = Start; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) +#define Vec_PtrForEachEntryStop( vVec, pEntry, i, Stop ) \ + for ( i = 0; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) +#define Vec_PtrForEachEntryStartStop( vVec, pEntry, i, Start, Stop ) \ + for ( i = Start; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) +#define Vec_PtrForEachEntryReverse( vVec, pEntry, i ) \ + for ( i = Vec_PtrSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i-- ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Ptr_t * Vec_PtrAlloc( int nCap ) +{ + Vec_Ptr_t * p; + p = ALLOC( Vec_Ptr_t, 1 ); + if ( nCap > 0 && nCap < 8 ) + nCap = 8; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given size and cleans it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Ptr_t * Vec_PtrStart( int nSize ) +{ + Vec_Ptr_t * p; + p = Vec_PtrAlloc( nSize ); + p->nSize = nSize; + memset( p->pArray, 0, sizeof(void *) * nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the vector from an integer array of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Ptr_t * Vec_PtrAllocArray( void ** pArray, int nSize ) +{ + Vec_Ptr_t * p; + p = ALLOC( Vec_Ptr_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = pArray; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the vector from an integer array of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Ptr_t * Vec_PtrAllocArrayCopy( void ** pArray, int nSize ) +{ + Vec_Ptr_t * p; + p = ALLOC( Vec_Ptr_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = ALLOC( void *, nSize ); + memcpy( p->pArray, pArray, sizeof(void *) * nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates the array of simulation info.] + + Description [Allocates the array containing given number of entries, + each of which contains given number of unsigned words of simulation data. + The resulting array can be freed using regular procedure Vec_PtrFree(). + It is the responsibility of the user to ensure this array is never grown.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Ptr_t * Vec_PtrAllocSimInfo( int nEntries, int nWords ) +{ + void ** pMemory; + unsigned * pInfo; + int i; + pMemory = (void **)ALLOC( char, (sizeof(void *) + sizeof(unsigned) * nWords) * nEntries ); + pInfo = (unsigned *)(pMemory + nEntries); + for ( i = 0; i < nEntries; i++ ) + pMemory[i] = pInfo + i * nWords; + return Vec_PtrAllocArray( pMemory, nEntries ); +} + +/**Function************************************************************* + + Synopsis [Allocates the array of truth tables for the given number of vars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Ptr_t * Vec_PtrAllocTruthTables( int nVars ) +{ + Vec_Ptr_t * p; + unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + unsigned * pTruth; + int i, k, nWords; + nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5))); + p = Vec_PtrAllocSimInfo( nVars, nWords ); + for ( i = 0; i < nVars; i++ ) + { + pTruth = (unsigned *)p->pArray[i]; + if ( i < 5 ) + { + for ( k = 0; k < nWords; k++ ) + pTruth[k] = Masks[i]; + } + else + { + for ( k = 0; k < nWords; k++ ) + if ( k & (1 << (i-5)) ) + pTruth[k] = ~(unsigned)0; + else + pTruth[k] = 0; + } + } + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the integer array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Ptr_t * Vec_PtrDup( Vec_Ptr_t * pVec ) +{ + Vec_Ptr_t * p; + p = ALLOC( Vec_Ptr_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nCap; + p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL; + memcpy( p->pArray, pVec->pArray, sizeof(void *) * pVec->nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Transfers the array into another vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Ptr_t * Vec_PtrDupArray( Vec_Ptr_t * pVec ) +{ + Vec_Ptr_t * p; + p = ALLOC( Vec_Ptr_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nCap; + p->pArray = pVec->pArray; + pVec->nSize = 0; + pVec->nCap = 0; + pVec->pArray = NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrFree( Vec_Ptr_t * p ) +{ + FREE( p->pArray ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void ** Vec_PtrReleaseArray( Vec_Ptr_t * p ) +{ + void ** pArray = p->pArray; + p->nCap = 0; + p->nSize = 0; + p->pArray = NULL; + return pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void ** Vec_PtrArray( Vec_Ptr_t * p ) +{ + return p->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_PtrSize( Vec_Ptr_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Vec_PtrEntry( Vec_Ptr_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [Resizes the array of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrDoubleSimInfo( Vec_Ptr_t * vInfo ) +{ + Vec_Ptr_t * vInfoNew; + int nWords; + assert( Vec_PtrSize(vInfo) > 2 ); + // get the new array + nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0); + vInfoNew = Vec_PtrAllocSimInfo( 2*Vec_PtrSize(vInfo), nWords ); + // copy the simulation info + memcpy( Vec_PtrEntry(vInfoNew,0), Vec_PtrEntry(vInfo,0), Vec_PtrSize(vInfo) * nWords * 4 ); + // replace the array + free( vInfo->pArray ); + vInfo->pArray = vInfoNew->pArray; + vInfo->nSize *= 2; + vInfo->nCap *= 2; + // free the old array + vInfoNew->pArray = NULL; + free( vInfoNew ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void ** Vec_PtrEntryP( Vec_Ptr_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray + i; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Vec_PtrEntryLast( Vec_Ptr_t * p ) +{ + assert( p->nSize > 0 ); + return p->pArray[p->nSize-1]; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrGrow( Vec_Ptr_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = REALLOC( void *, p->pArray, nCapMin ); + p->nCap = nCapMin; +} + +/**Function************************************************************* + + Synopsis [Fills the vector with given number of entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrFill( Vec_Ptr_t * p, int nSize, void * Entry ) +{ + int i; + Vec_PtrGrow( p, nSize ); + for ( i = 0; i < nSize; i++ ) + p->pArray[i] = Entry; + p->nSize = nSize; +} + +/**Function************************************************************* + + Synopsis [Fills the vector with given number of entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrFillExtra( Vec_Ptr_t * p, int nSize, void * Entry ) +{ + int i; + if ( p->nSize >= nSize ) + return; + assert( p->nSize < nSize ); + if ( 2 * p->nSize > nSize ) + Vec_PtrGrow( p, 2 * nSize ); + else + Vec_PtrGrow( p, nSize ); + for ( i = p->nSize; i < nSize; i++ ) + p->pArray[i] = Entry; + p->nSize = nSize; +} + +/**Function************************************************************* + + Synopsis [Returns the entry even if the place not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Vec_PtrGetEntry( Vec_Ptr_t * p, int i ) +{ + Vec_PtrFillExtra( p, i + 1, NULL ); + return Vec_PtrEntry( p, i ); +} + +/**Function************************************************************* + + Synopsis [Inserts the entry even if the place does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrSetEntry( Vec_Ptr_t * p, int i, void * Entry ) +{ + Vec_PtrFillExtra( p, i + 1, NULL ); + Vec_PtrWriteEntry( p, i, Entry ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrShrink( Vec_Ptr_t * p, int nSizeNew ) +{ + assert( p->nSize >= nSizeNew ); + p->nSize = nSizeNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrClear( Vec_Ptr_t * p ) +{ + p->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [Copies the interger array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrCopy( Vec_Ptr_t * pDest, Vec_Ptr_t * pSour ) +{ + pDest->nSize = 0; + Vec_PtrGrow( pDest, pSour->nSize ); + memcpy( pDest->pArray, pSour->pArray, sizeof(void *) * pSour->nSize ); + pDest->nSize = pSour->nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrPush( Vec_Ptr_t * p, void * Entry ) +{ + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Vec_PtrGrow( p, 16 ); + else + Vec_PtrGrow( p, 2 * p->nCap ); + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_PtrPushUnique( Vec_Ptr_t * p, void * Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return 1; + Vec_PtrPush( p, Entry ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the last entry and removes it from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Vec_PtrPop( Vec_Ptr_t * p ) +{ + assert( p->nSize > 0 ); + return p->pArray[--p->nSize]; +} + +/**Function************************************************************* + + Synopsis [Find entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_PtrFind( Vec_Ptr_t * p, void * Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrRemove( Vec_Ptr_t * p, void * Entry ) +{ + int i; + // delete assuming that it is closer to the end + for ( i = p->nSize - 1; i >= 0; i-- ) + if ( p->pArray[i] == Entry ) + break; + assert( i >= 0 ); +/* + // delete assuming that it is closer to the beginning + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + break; + assert( i < p->nSize ); +*/ + for ( i++; i < p->nSize; i++ ) + p->pArray[i-1] = p->pArray[i]; + p->nSize--; +} + +/**Function************************************************************* + + Synopsis [Moves the first nItems to the end.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrReorder( Vec_Ptr_t * p, int nItems ) +{ + assert( nItems < p->nSize ); + Vec_PtrGrow( p, nItems + p->nSize ); + memmove( (char **)p->pArray + p->nSize, p->pArray, nItems * sizeof(void*) ); + memmove( p->pArray, (char **)p->pArray + nItems, p->nSize * sizeof(void*) ); +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) +{ + if ( p->nSize < 2 ) + return; + qsort( (void *)p->pArray, p->nSize, sizeof(void *), + (int (*)(const void *, const void *)) Vec_PtrSortCompare ); +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) +{ + int i, k; + if ( p->nSize < 2 ) + return; + qsort( (void *)p->pArray, p->nSize, sizeof(void *), + (int (*)(const void *, const void *)) Vec_PtrSortCompare ); + for ( i = k = 1; i < p->nSize; i++ ) + if ( p->pArray[i] != p->pArray[i-1] ) + p->pArray[k++] = p->pArray[i]; + p->nSize = k; +} + +#endif + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/misc/vec/vecStr.h b/abc70930/src/misc/vec/vecStr.h new file mode 100644 index 00000000..47367bc6 --- /dev/null +++ b/abc70930/src/misc/vec/vecStr.h @@ -0,0 +1,583 @@ +/**CFile**************************************************************** + + FileName [vecStr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resizable arrays.] + + Synopsis [Resizable arrays of characters.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: vecStr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __VEC_STR_H__ +#define __VEC_STR_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Vec_Str_t_ Vec_Str_t; +struct Vec_Str_t_ +{ + int nCap; + int nSize; + char * pArray; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Vec_StrForEachEntry( vVec, Entry, i ) \ + for ( i = 0; (i < Vec_StrSize(vVec)) && (((Entry) = Vec_StrEntry(vVec, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Str_t * Vec_StrAlloc( int nCap ) +{ + Vec_Str_t * p; + p = ALLOC( Vec_Str_t, 1 ); + if ( nCap > 0 && nCap < 16 ) + nCap = 16; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given size and cleans it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Str_t * Vec_StrStart( int nSize ) +{ + Vec_Str_t * p; + p = Vec_StrAlloc( nSize ); + p->nSize = nSize; + memset( p->pArray, 0, sizeof(char) * nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the vector from an integer array of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize ) +{ + Vec_Str_t * p; + p = ALLOC( Vec_Str_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = pArray; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the vector from an integer array of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Str_t * Vec_StrAllocArrayCopy( char * pArray, int nSize ) +{ + Vec_Str_t * p; + p = ALLOC( Vec_Str_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = ALLOC( char, nSize ); + memcpy( p->pArray, pArray, sizeof(char) * nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the integer array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Str_t * Vec_StrDup( Vec_Str_t * pVec ) +{ + Vec_Str_t * p; + p = ALLOC( Vec_Str_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nCap; + p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL; + memcpy( p->pArray, pVec->pArray, sizeof(char) * pVec->nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Transfers the array into another vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Str_t * Vec_StrDupArray( Vec_Str_t * pVec ) +{ + Vec_Str_t * p; + p = ALLOC( Vec_Str_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nCap; + p->pArray = pVec->pArray; + pVec->nSize = 0; + pVec->nCap = 0; + pVec->pArray = NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrFree( Vec_Str_t * p ) +{ + FREE( p->pArray ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline char * Vec_StrReleaseArray( Vec_Str_t * p ) +{ + char * pArray = p->pArray; + p->nCap = 0; + p->nSize = 0; + p->pArray = NULL; + return pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline char * Vec_StrArray( Vec_Str_t * p ) +{ + return p->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_StrSize( Vec_Str_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline char Vec_StrEntry( Vec_Str_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrWriteEntry( Vec_Str_t * p, int i, char Entry ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline char Vec_StrEntryLast( Vec_Str_t * p ) +{ + assert( p->nSize > 0 ); + return p->pArray[p->nSize-1]; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrGrow( Vec_Str_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = REALLOC( char, p->pArray, 2 * nCapMin ); + p->nCap = 2 * nCapMin; +} + +/**Function************************************************************* + + Synopsis [Fills the vector with given number of entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrFill( Vec_Str_t * p, int nSize, char Entry ) +{ + int i; + Vec_StrGrow( p, nSize ); + p->nSize = nSize; + for ( i = 0; i < p->nSize; i++ ) + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrShrink( Vec_Str_t * p, int nSizeNew ) +{ + assert( p->nSize >= nSizeNew ); + p->nSize = nSizeNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrClear( Vec_Str_t * p ) +{ + p->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrPush( Vec_Str_t * p, char Entry ) +{ + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Vec_StrGrow( p, 16 ); + else + Vec_StrGrow( p, 2 * p->nCap ); + } + p->pArray[p->nSize++] = Entry; +} + +/**Function******************************************************************** + + Synopsis [Finds the smallest integer larger of equal than the logarithm.] + + Description [Returns [Log10(Num)].] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +static inline int Vec_StrBase10Log( unsigned Num ) +{ + int Res; + assert( Num >= 0 ); + if ( Num == 0 ) return 0; + if ( Num == 1 ) return 1; + for ( Res = 0, Num--; Num; Num /= 10, Res++ ); + return Res; +} /* end of Extra_Base2Log */ + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrPrintNum( Vec_Str_t * p, int Num ) +{ + int i, nDigits; + if ( Num < 0 ) + { + Vec_StrPush( p, '-' ); + Num = -Num; + } + if ( Num < 10 ) + { + Vec_StrPush( p, (char)('0' + Num) ); + return; + } + nDigits = Vec_StrBase10Log( Num ); + Vec_StrGrow( p, p->nSize + nDigits ); + for ( i = nDigits - 1; i >= 0; i-- ) + { + Vec_StrWriteEntry( p, p->nSize + i, (char)('0' + Num % 10) ); + Num /= 10; + } + assert( Num == 0 ); + p->nSize += nDigits; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrPrintStr( Vec_Str_t * p, char * pStr ) +{ + int i, Length = strlen(pStr); + for ( i = 0; i < Length; i++ ) + Vec_StrPush( p, pStr[i] ); +} + +/**Function************************************************************* + + Synopsis [Appends the string to the char vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrAppend( Vec_Str_t * p, char * pString ) +{ + int i, nLength = strlen(pString); + Vec_StrGrow( p, p->nSize + nLength ); + for ( i = 0; i < nLength; i++ ) + p->pArray[p->nSize + i] = pString[i]; + p->nSize += nLength; +} + +/**Function************************************************************* + + Synopsis [Returns the last entry and removes it from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline char Vec_StrPop( Vec_Str_t * p ) +{ + assert( p->nSize > 0 ); + return p->pArray[--p->nSize]; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_StrSortCompare1( char * pp1, char * pp2 ) +{ + // for some reason commenting out lines (as shown) led to crashing of the release version + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) // + return 1; + return 0; // +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_StrSortCompare2( char * pp1, char * pp2 ) +{ + // for some reason commenting out lines (as shown) led to crashing of the release version + if ( *pp1 > *pp2 ) + return -1; + if ( *pp1 < *pp2 ) // + return 1; + return 0; // +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrSort( Vec_Str_t * p, int fReverse ) +{ + if ( fReverse ) + qsort( (void *)p->pArray, p->nSize, sizeof(char), + (int (*)(const void *, const void *)) Vec_StrSortCompare2 ); + else + qsort( (void *)p->pArray, p->nSize, sizeof(char), + (int (*)(const void *, const void *)) Vec_StrSortCompare1 ); +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/misc/vec/vecVec.h b/abc70930/src/misc/vec/vecVec.h new file mode 100644 index 00000000..55ffdf4f --- /dev/null +++ b/abc70930/src/misc/vec/vecVec.h @@ -0,0 +1,356 @@ +/**CFile**************************************************************** + + FileName [vecVec.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resizable arrays.] + + Synopsis [Resizable vector of resizable vectors.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: vecVec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __VEC_VEC_H__ +#define __VEC_VEC_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Vec_Vec_t_ Vec_Vec_t; +struct Vec_Vec_t_ +{ + int nCap; + int nSize; + void ** pArray; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// iterators through levels +#define Vec_VecForEachLevel( vGlob, vVec, i ) \ + for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ ) +#define Vec_VecForEachLevelStart( vGlob, vVec, i, LevelStart ) \ + for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ ) +#define Vec_VecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ + for ( i = LevelStart; (i <= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ ) +#define Vec_VecForEachLevelReverse( vGlob, vVec, i ) \ + for ( i = Vec_VecSize(vGlob) - 1; (i >= 0) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- ) +#define Vec_VecForEachLevelReverseStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ + for ( i = LevelStart; (i >= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- ) + +// iteratores through entries +#define Vec_VecForEachEntry( vGlob, pEntry, i, k ) \ + for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \ + Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k ) +#define Vec_VecForEachEntryLevel( vGlob, pEntry, i, Level ) \ + Vec_PtrForEachEntry( Vec_VecEntry(vGlob, Level), pEntry, i ) +#define Vec_VecForEachEntryStart( vGlob, pEntry, i, k, LevelStart ) \ + for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ ) \ + Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k ) +#define Vec_VecForEachEntryStartStop( vGlob, pEntry, i, k, LevelStart, LevelStop ) \ + for ( i = LevelStart; i <= LevelStop; i++ ) \ + Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k ) +#define Vec_VecForEachEntryReverse( vGlob, pEntry, i, k ) \ + for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \ + Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k ) +#define Vec_VecForEachEntryReverseReverse( vGlob, pEntry, i, k ) \ + for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- ) \ + Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k ) +#define Vec_VecForEachEntryReverseStart( vGlob, pEntry, i, k, LevelStart ) \ + for ( i = LevelStart; i >= 0; i-- ) \ + Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Vec_t * Vec_VecAlloc( int nCap ) +{ + Vec_Vec_t * p; + p = ALLOC( Vec_Vec_t, 1 ); + if ( nCap > 0 && nCap < 8 ) + nCap = 8; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Vec_t * Vec_VecStart( int nSize ) +{ + Vec_Vec_t * p; + int i; + p = Vec_VecAlloc( nSize ); + for ( i = 0; i < nSize; i++ ) + p->pArray[i] = Vec_PtrAlloc( 0 ); + p->nSize = nSize; + return p; +} + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_VecExpand( Vec_Vec_t * p, int Level ) +{ + int i; + if ( p->nSize >= Level + 1 ) + return; + Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 ); + for ( i = p->nSize; i <= Level; i++ ) + p->pArray[i] = Vec_PtrAlloc( 0 ); + p->nSize = Level + 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_VecSize( Vec_Vec_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Vec_VecEntry( Vec_Vec_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [Frees the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_VecFree( Vec_Vec_t * p ) +{ + Vec_Ptr_t * vVec; + int i; + Vec_VecForEachLevel( p, vVec, i ) + Vec_PtrFree( vVec ); + Vec_PtrFree( (Vec_Ptr_t *)p ); +} + +/**Function************************************************************* + + Synopsis [Frees the vector of vectors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_VecSizeSize( Vec_Vec_t * p ) +{ + Vec_Ptr_t * vVec; + int i, Counter = 0; + Vec_VecForEachLevel( p, vVec, i ) + Counter += vVec->nSize; + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_VecClear( Vec_Vec_t * p ) +{ + Vec_Ptr_t * vVec; + int i; + Vec_VecForEachLevel( p, vVec, i ) + Vec_PtrClear( vVec ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry ) +{ + if ( p->nSize < Level + 1 ) + { + int i; + Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 ); + for ( i = p->nSize; i < Level + 1; i++ ) + p->pArray[i] = Vec_PtrAlloc( 0 ); + p->nSize = Level + 1; + } + Vec_PtrPush( (Vec_Ptr_t*)p->pArray[Level], Entry ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_VecPushUnique( Vec_Vec_t * p, int Level, void * Entry ) +{ + if ( p->nSize < Level + 1 ) + Vec_VecPush( p, Level, Entry ); + else + Vec_PtrPushUnique( (Vec_Ptr_t*)p->pArray[Level], Entry ); +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two arrays.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 ) +{ + if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) ) + return -1; + if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two integers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 ) +{ + if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) ) + return -1; + if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse ) +{ + if ( fReverse ) + qsort( (void *)p->pArray, p->nSize, sizeof(void *), + (int (*)(const void *, const void *)) Vec_VecSortCompare2 ); + else + qsort( (void *)p->pArray, p->nSize, sizeof(void *), + (int (*)(const void *, const void *)) Vec_VecSortCompare1 ); +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/cut/abcCut.c b/abc70930/src/opt/cut/abcCut.c new file mode 100644 index 00000000..9bbd5790 --- /dev/null +++ b/abc70930/src/opt/cut/abcCut.c @@ -0,0 +1,492 @@ +/**CFile**************************************************************** + + FileName [abcCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Interface to cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "cut.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ); +static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ); + + +extern int nTotal, nGood, nEqual; + +// temporary +//Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) { return NULL; } +Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); + int i; + Abc_Obj_t * pObj; + +// Abc_NtkForEachCi( pNtk, pObj, i ) +// Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); + + Abc_NtkForEachObj( pNtk, pObj, i ) + { +// if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) ) + if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) ) + Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); + } + return vAttrs; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) +{ + ProgressBar * pProgress; + Cut_Man_t * p; + Abc_Obj_t * pObj, * pNode; + Vec_Ptr_t * vNodes; + Vec_Int_t * vChoices; + int i; + int clk = clock(); + + extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ); + extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); + + nTotal = nGood = nEqual = 0; + + assert( Abc_NtkIsStrash(pNtk) ); + // start the manager + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + p = Cut_ManStart( pParams ); + // compute node attributes if local or global cuts are requested + if ( pParams->fGlobal || pParams->fLocal ) + { + extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); + Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) ); + } + // prepare for cut dropping + if ( pParams->fDrop ) + Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( p, pObj->Id ); + // compute cuts for internal nodes + vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs + vChoices = Vec_IntAlloc( 100 ); + pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // when we reached a CO, it is time to deallocate the cuts + if ( Abc_ObjIsCo(pObj) ) + { + if ( pParams->fDrop ) + Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + continue; + } + // skip constant node, it has no cuts +// if ( Abc_NodeIsConst(pObj) ) +// continue; + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // compute the cuts to the internal node + Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree ); + // consider dropping the fanins cuts + if ( pParams->fDrop ) + { + Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); + } + // add cuts due to choices + if ( Abc_AigNodeIsChoice(pObj) ) + { + Vec_IntClear( vChoices ); + for ( pNode = pObj; pNode; pNode = pNode->pData ) + Vec_IntPush( vChoices, pNode->Id ); + Cut_NodeUnionCuts( p, vChoices ); + } + } + Extra_ProgressBarStop( pProgress ); + Vec_PtrFree( vNodes ); + Vec_IntFree( vChoices ); +PRT( "Total", clock() - clk ); +//Abc_NtkPrintCuts( p, pNtk, 0 ); +// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk ); + + // temporary printout of stats + if ( nTotal ) + printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal ); + return p; +} + +/**Function************************************************************* + + Synopsis [Cut computation using the oracle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p ) +{ + Abc_Obj_t * pObj; + Vec_Ptr_t * vNodes; + int i, clk = clock(); + int fDrop = Cut_OracleReadDrop(p); + + assert( Abc_NtkIsStrash(pNtk) ); + + // prepare cut droppping + if ( fDrop ) + Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); + + // set cuts for PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_OracleNodeSetTriv( p, pObj->Id ); + + // compute cuts for internal nodes + vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + // when we reached a CO, it is time to deallocate the cuts + if ( Abc_ObjIsCo(pObj) ) + { + if ( fDrop ) + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + continue; + } + // skip constant node, it has no cuts +// if ( Abc_NodeIsConst(pObj) ) +// continue; + // compute the cuts to the internal node + Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + // consider dropping the fanins cuts + if ( fDrop ) + { + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); + Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); + } + } + Vec_PtrFree( vNodes ); +//PRT( "Total", clock() - clk ); +//Abc_NtkPrintCuts_( p, pNtk, 0 ); +} + + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) +{ +/* + Cut_Man_t * p; + Abc_Obj_t * pObj, * pNode; + int i, nIters, fStatus; + Vec_Int_t * vChoices; + int clk = clock(); + + assert( Abc_NtkIsSeq(pNtk) ); + assert( pParams->fSeq ); +// assert( Abc_NtkIsDfsOrdered(pNtk) ); + + // start the manager + pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); + pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk ); + p = Cut_ManStart( pParams ); + + // set cuts for the constant node and the PIs + pObj = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Cut_NodeSetTriv( p, pObj->Id ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { +//printf( "Setting trivial cut %d.\n", pObj->Id ); + Cut_NodeSetTriv( p, pObj->Id ); + } + // label the cutset nodes and set their number in the array + // assign the elementary cuts to the cutset nodes + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + { + assert( pObj->fMarkC == 0 ); + pObj->fMarkC = 1; + pObj->pCopy = (Abc_Obj_t *)i; + Cut_NodeSetTriv( p, pObj->Id ); +//printf( "Setting trivial cut %d.\n", pObj->Id ); + } + + // process the nodes + vChoices = Vec_IntAlloc( 100 ); + for ( nIters = 0; nIters < 10; nIters++ ) + { +//printf( "ITERATION %d:\n", nIters ); + // compute the cuts for the internal nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + { + Abc_NodeGetCutsSeq( p, pObj, nIters==0 ); + // add cuts due to choices + if ( Abc_AigNodeIsChoice(pObj) ) + { + Vec_IntClear( vChoices ); + for ( pNode = pObj; pNode; pNode = pNode->pData ) + Vec_IntPush( vChoices, pNode->Id ); + Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 ); + } + } + // merge the new cuts with the old cuts + Abc_NtkForEachPi( pNtk, pObj, i ) + Cut_NodeNewMergeWithOld( p, pObj->Id ); + Abc_AigForEachAnd( pNtk, pObj, i ) + Cut_NodeNewMergeWithOld( p, pObj->Id ); + // for the cutset, transfer temp cuts to new cuts + fStatus = 0; + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i ); + if ( fStatus == 0 ) + break; + } + Vec_IntFree( vChoices ); + + // if the status is not finished, transfer new to old for the cutset + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + Cut_NodeNewMergeWithOld( p, pObj->Id ); + + // transfer the old cuts to the new positions + Abc_NtkForEachObj( pNtk, pObj, i ) + Cut_NodeOldTransferToNew( p, pObj->Id ); + + // unlabel the cutset nodes + Abc_SeqForEachCutsetNode( pNtk, pObj, i ) + pObj->fMarkC = 0; +if ( pParams->fVerbose ) +{ +PRT( "Total", clock() - clk ); +printf( "Converged after %d iterations.\n", nIters ); +} +//Abc_NtkPrintCuts( p, pNtk, 1 ); + return p; +*/ +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) +{ + void * pList; + if ( pList = Abc_NodeReadCuts( p, pObj ) ) + return pList; + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree ); + Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree ); + return Abc_NodeGetCuts( p, pObj, fDag, fTree ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) +{ + Abc_Obj_t * pFanin; + int fDagNode, fTriv, TreeCode = 0; +// assert( Abc_NtkIsStrash(pObj->pNtk) ); + assert( Abc_ObjFaninNum(pObj) == 2 ); + + + // check if the node is a DAG node + fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)); + // increment the counter of DAG nodes + if ( fDagNode ) Cut_ManIncrementDagNodes( p ); + // add the trivial cut if the node is a DAG node, or if we compute all cuts + fTriv = fDagNode || !fDag; + // check if fanins are DAG nodes + if ( fTree ) + { + pFanin = Abc_ObjFanin0(pObj); + TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)); + pFanin = Abc_ObjFanin1(pObj); + TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1); + } + + + // changes due to the global/local cut computation + { + Cut_Params_t * pParams = Cut_ManReadParams(p); + if ( pParams->fLocal ) + { + Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p); + fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id ); + if ( fDagNode ) Cut_ManIncrementDagNodes( p ); +// fTriv = fDagNode || !pParams->fGlobal; + fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id ); + TreeCode = 0; + pFanin = Abc_ObjFanin0(pObj); + TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id ); + pFanin = Abc_ObjFanin1(pObj); + TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1); + } + } + return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv ) +{ + int CutSetNum; + assert( Abc_NtkIsSeq(pObj->pNtk) ); + assert( Abc_ObjFaninNum(pObj) == 2 ); + fTriv = pObj->fMarkC ? 0 : fTriv; + CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1; + Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), + Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ) +{ + return Cut_NodeReadCutsNew( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ) +{ + Cut_NodeFreeCuts( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ) +{ + Cut_Man_t * pMan = p; + Cut_Cut_t * pList; + Abc_Obj_t * pObj; + int i; + printf( "Cuts of the network:\n" ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + pList = Abc_NodeReadCuts( p, pObj ); + printf( "Node %s:\n", Abc_ObjName(pObj) ); + Cut_CutPrintList( pList, fSeq ); + } +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ) +{ + Cut_Man_t * pMan = p; + Cut_Cut_t * pList; + Abc_Obj_t * pObj; + pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 ); + pList = Abc_NodeReadCuts( p, pObj ); + printf( "Node %s:\n", Abc_ObjName(pObj) ); + Cut_CutPrintList( pList, fSeq ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/cut/cut.h b/abc70930/src/opt/cut/cut.h new file mode 100644 index 00000000..dee05dfc --- /dev/null +++ b/abc70930/src/opt/cut/cut.h @@ -0,0 +1,165 @@ +/**CFile**************************************************************** + + FileName [cut.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: .h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CUT_H__ +#define __CUT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define CUT_SIZE_MIN 3 // the min K of the K-feasible cut computation +#define CUT_SIZE_MAX 12 // the max K of the K-feasible cut computation + +#define CUT_SHIFT 8 // the number of bits for storing latch number in the cut leaves +#define CUT_MASK 0xFF // the mask to get the stored latch number + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cut_ManStruct_t_ Cut_Man_t; +typedef struct Cut_OracleStruct_t_ Cut_Oracle_t; +typedef struct Cut_CutStruct_t_ Cut_Cut_t; +typedef struct Cut_ParamsStruct_t_ Cut_Params_t; + +struct Cut_ParamsStruct_t_ +{ + int nVarsMax; // the max cut size ("k" of the k-feasible cuts) + int nKeepMax; // the max number of cuts kept at a node + int nIdsMax; // the max number of IDs of cut objects + int nBitShift; // the number of bits used for the latch counter of an edge + int nCutSet; // the number of nodes in the cut set + int fTruth; // compute truth tables + int fFilter; // filter dominated cuts + int fSeq; // compute sequential cuts + int fDrop; // drop cuts on the fly + int fDag; // compute only DAG cuts + int fTree; // compute only tree cuts + int fGlobal; // compute only global cuts + int fLocal; // compute only local cuts + int fRecord; // record the cut computation flow + int fFancy; // perform fancy computations + int fMap; // computes delay of FPGA mapping with cuts + int fVerbose; // the verbosiness flag +}; + +struct Cut_CutStruct_t_ +{ + unsigned Num0 : 11; // temporary number + unsigned Num1 : 11; // temporary number + unsigned fSimul : 1; // the value of cut's output at 000.. pattern + unsigned fCompl : 1; // the cut is complemented + unsigned nVarsMax : 4; // the max number of vars [4-6] + unsigned nLeaves : 4; // the number of leaves [4-6] + unsigned uSign; // the signature + unsigned uCanon0; // the canonical form + unsigned uCanon1; // the canonical form + Cut_Cut_t * pNext; // the next cut in the list + int pLeaves[0]; // the array of leaves +}; + +static inline int Cut_CutReadLeaveNum( Cut_Cut_t * p ) { return p->nLeaves; } +static inline int * Cut_CutReadLeaves( Cut_Cut_t * p ) { return p->pLeaves; } +static inline unsigned * Cut_CutReadTruth( Cut_Cut_t * p ) { return (unsigned *)(p->pLeaves + p->nVarsMax); } +static inline void Cut_CutWriteTruth( Cut_Cut_t * p, unsigned * puTruth ) { + int i; + for ( i = (p->nVarsMax <= 5) ? 0 : ((1 << (p->nVarsMax - 5)) - 1); i >= 0; i-- ) + p->pLeaves[p->nVarsMax + i] = (int)puTruth[i]; +} + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cutApi.c ==========================================================*/ +extern Cut_Cut_t * Cut_NodeReadCutsNew( Cut_Man_t * p, int Node ); +extern Cut_Cut_t * Cut_NodeReadCutsOld( Cut_Man_t * p, int Node ); +extern Cut_Cut_t * Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node ); +extern void Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList ); +extern void Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList ); +extern void Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList ); +extern void Cut_NodeSetTriv( Cut_Man_t * p, int Node ); +extern void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node ); +extern void Cut_NodeFreeCuts( Cut_Man_t * p, int Node ); +/*=== cutCut.c ==========================================================*/ +extern void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq ); +extern void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq ); +extern int Cut_CutCountList( Cut_Cut_t * pList ); +/*=== cutMan.c ==========================================================*/ +extern Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams ); +extern void Cut_ManStop( Cut_Man_t * p ); +extern void Cut_ManPrintStats( Cut_Man_t * p ); +extern void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, int TimeTotal ); +extern void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts ); +extern void Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vFanCounts ); +extern int Cut_ManReadVarsMax( Cut_Man_t * p ); +extern Cut_Params_t * Cut_ManReadParams( Cut_Man_t * p ); +extern Vec_Int_t * Cut_ManReadNodeAttrs( Cut_Man_t * p ); +extern void Cut_ManIncrementDagNodes( Cut_Man_t * p ); +/*=== cutNode.c ==========================================================*/ +extern Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode ); +extern Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ); +extern Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst ); +extern int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node ); +/*=== cutSeq.c ==========================================================*/ +extern void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum ); +extern void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node ); +extern int Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum ); +extern void Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node ); +/*=== cutOracle.c ==========================================================*/ +extern Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan ); +extern void Cut_OracleStop( Cut_Oracle_t * p ); +extern void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts ); +extern int Cut_OracleReadDrop( Cut_Oracle_t * p ); +extern void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node ); +extern Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 ); +extern void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node ); +/*=== cutTruth.c ==========================================================*/ +extern void Cut_TruthNCanonicize( Cut_Cut_t * pCut ); +/*=== cutPre22.c ==========================================================*/ +extern void Cut_CellPrecompute(); +extern void Cut_CellLoad(); +extern int Cut_CellIsRunning(); +extern void Cut_CellDumpToFile(); +extern int Cut_CellTruthLookup( unsigned * pTruth, int nVars ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/cut/cutApi.c b/abc70930/src/opt/cut/cutApi.c new file mode 100644 index 00000000..980c6b12 --- /dev/null +++ b/abc70930/src/opt/cut/cutApi.c @@ -0,0 +1,197 @@ +/**CFile**************************************************************** + + FileName [cutNode.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [Procedures to compute cuts for a node.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the pointer to the linked list of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_NodeReadCutsNew( Cut_Man_t * p, int Node ) +{ + if ( Node >= p->vCutsNew->nSize ) + return NULL; + return Vec_PtrEntry( p->vCutsNew, Node ); +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the linked list of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_NodeReadCutsOld( Cut_Man_t * p, int Node ) +{ + assert( Node < p->vCutsOld->nSize ); + return Vec_PtrEntry( p->vCutsOld, Node ); +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the linked list of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node ) +{ + assert( Node < p->vCutsTemp->nSize ); + return Vec_PtrEntry( p->vCutsTemp, Node ); +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the linked list of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList ) +{ + Vec_PtrWriteEntry( p->vCutsNew, Node, pList ); +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the linked list of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList ) +{ + Vec_PtrWriteEntry( p->vCutsOld, Node, pList ); +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the linked list of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList ) +{ + Vec_PtrWriteEntry( p->vCutsTemp, Node, pList ); +} + +/**Function************************************************************* + + Synopsis [Sets the trivial cut for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_NodeSetTriv( Cut_Man_t * p, int Node ) +{ + assert( Cut_NodeReadCutsNew(p, Node) == NULL ); + Cut_NodeWriteCutsNew( p, Node, Cut_CutCreateTriv(p, Node) ); +} + +/**Function************************************************************* + + Synopsis [Consider dropping cuts if they are useless by now.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node ) +{ + int nFanouts; + assert( p->vFanCounts ); + nFanouts = Vec_IntEntry( p->vFanCounts, Node ); + assert( nFanouts > 0 ); + if ( --nFanouts == 0 ) + Cut_NodeFreeCuts( p, Node ); + Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts ); +} + +/**Function************************************************************* + + Synopsis [Deallocates the cuts at the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_NodeFreeCuts( Cut_Man_t * p, int Node ) +{ + Cut_Cut_t * pList, * pCut, * pCut2; + pList = Cut_NodeReadCutsNew( p, Node ); + if ( pList == NULL ) + return; + Cut_ListForEachCutSafe( pList, pCut, pCut2 ) + Cut_CutRecycle( p, pCut ); + Cut_NodeWriteCutsNew( p, Node, NULL ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/cut/cutCut.c b/abc70930/src/opt/cut/cutCut.c new file mode 100644 index 00000000..94147278 --- /dev/null +++ b/abc70930/src/opt/cut/cutCut.c @@ -0,0 +1,359 @@ +/**CFile**************************************************************** + + FileName [cutNode.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [Procedures to compute cuts for a node.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p ) +{ + Cut_Cut_t * pCut; + // cut allocation + pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts ); + memset( pCut, 0, sizeof(Cut_Cut_t) ); + pCut->nVarsMax = p->pParams->nVarsMax; + pCut->fSimul = p->fSimul; + // statistics + p->nCutsAlloc++; + p->nCutsCur++; + if ( p->nCutsPeak < p->nCutsAlloc - p->nCutsDealloc ) + p->nCutsPeak = p->nCutsAlloc - p->nCutsDealloc; + return pCut; +} + +/**Function************************************************************* + + Synopsis [Recybles the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut ) +{ + p->nCutsDealloc++; + p->nCutsCur--; + if ( pCut->nLeaves == 1 ) + p->nCutsTriv--; + Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut ); +} + +/**Function************************************************************* + + Synopsis [Compares two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 ) +{ + int i; + if ( pCut1->nLeaves < pCut2->nLeaves ) + return -1; + if ( pCut1->nLeaves > pCut2->nLeaves ) + return 1; + for ( i = 0; i < (int)pCut1->nLeaves; i++ ) + { + if ( pCut1->pLeaves[i] < pCut2->pLeaves[i] ) + return -1; + if ( pCut1->pLeaves[i] > pCut2->pLeaves[i] ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Duplicates the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList ) +{ + Cut_Cut_t * pHead = NULL, ** ppTail = &pHead; + Cut_Cut_t * pTemp, * pCopy; + if ( pList == NULL ) + return NULL; + Cut_ListForEachCut( pList, pTemp ) + { + pCopy = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts ); + memcpy( pCopy, pTemp, p->EntrySize ); + *ppTail = pCopy; + ppTail = &pCopy->pNext; + } + *ppTail = NULL; + return pHead; +} + +/**Function************************************************************* + + Synopsis [Recycles the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList ) +{ + Cut_Cut_t * pCut, * pCut2; + Cut_ListForEachCutSafe( pList, pCut, pCut2 ) + Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of cuts in the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_CutCountList( Cut_Cut_t * pList ) +{ + int Counter = 0; + Cut_ListForEachCut( pList, pList ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Merges two NULL-terminated linked lists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 ) +{ + Cut_Cut_t * pList = NULL, ** ppTail = &pList; + Cut_Cut_t * pCut; + while ( pList1 && pList2 ) + { + if ( Cut_CutCompare(pList1, pList2) < 0 ) + { + pCut = pList1; + pList1 = pList1->pNext; + } + else + { + pCut = pList2; + pList2 = pList2->pNext; + } + *ppTail = pCut; + ppTail = &pCut->pNext; + } + *ppTail = pList1? pList1: pList2; + return pList; +} + +/**Function************************************************************* + + Synopsis [Sets the number of the cuts in the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CutNumberList( Cut_Cut_t * pList ) +{ + Cut_Cut_t * pCut; + int i = 0; + Cut_ListForEachCut( pList, pCut ) + pCut->Num0 = i++; +} + +/**Function************************************************************* + + Synopsis [Creates the trivial cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node ) +{ + Cut_Cut_t * pCut; + if ( p->pParams->fSeq ) + Node <<= CUT_SHIFT; + pCut = Cut_CutAlloc( p ); + pCut->nLeaves = 1; + pCut->pLeaves[0] = Node; + pCut->uSign = Cut_NodeSign( Node ); + if ( p->pParams->fTruth ) + { +/* + if ( pCut->nVarsMax == 4 ) + Cut_CutWriteTruth( pCut, p->uTruthVars[0] ); + else + Extra_BitCopy( pCut->nLeaves, p->uTruths[0], (uint8*)Cut_CutReadTruth(pCut) ); +*/ + unsigned * pTruth = Cut_CutReadTruth(pCut); + int i; + for ( i = 0; i < p->nTruthWords; i++ ) + pTruth[i] = 0xAAAAAAAA; + } + p->nCutsTriv++; + return pCut; +} + + +/**Function************************************************************* + + Synopsis [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq ) +{ + int i; + assert( pCut->nLeaves > 0 ); + printf( "%d : {", pCut->nLeaves ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + if ( fSeq ) + { + printf( " %d", pCut->pLeaves[i] >> CUT_SHIFT ); + if ( pCut->pLeaves[i] & CUT_MASK ) + printf( "(%d)", pCut->pLeaves[i] & CUT_MASK ); + } + else + printf( " %d", pCut->pLeaves[i] ); + } + printf( " }" ); +// printf( "\nSign = " ); +// Extra_PrintBinary( stdout, &pCut->uSign, 32 ); +} + +/**Function************************************************************* + + Synopsis [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq ) +{ + Cut_Cut_t * pCut; + for ( pCut = pList; pCut; pCut = pCut->pNext ) + Cut_CutPrint( pCut, fSeq ), printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Consider dropping cuts if they are useless by now.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) +{ + printf( "\n" ); + printf( "%d : %5d %5d %5d %5d %5d\n", + pCut0->nLeaves, + pCut0->nLeaves > 0 ? pCut0->pLeaves[0] : -1, + pCut0->nLeaves > 1 ? pCut0->pLeaves[1] : -1, + pCut0->nLeaves > 2 ? pCut0->pLeaves[2] : -1, + pCut0->nLeaves > 3 ? pCut0->pLeaves[3] : -1, + pCut0->nLeaves > 4 ? pCut0->pLeaves[4] : -1 + ); + printf( "%d : %5d %5d %5d %5d %5d\n", + pCut1->nLeaves, + pCut1->nLeaves > 0 ? pCut1->pLeaves[0] : -1, + pCut1->nLeaves > 1 ? pCut1->pLeaves[1] : -1, + pCut1->nLeaves > 2 ? pCut1->pLeaves[2] : -1, + pCut1->nLeaves > 3 ? pCut1->pLeaves[3] : -1, + pCut1->nLeaves > 4 ? pCut1->pLeaves[4] : -1 + ); + if ( pCut == NULL ) + printf( "Cannot merge\n" ); + else + printf( "%d : %5d %5d %5d %5d %5d\n", + pCut->nLeaves, + pCut->nLeaves > 0 ? pCut->pLeaves[0] : -1, + pCut->nLeaves > 1 ? pCut->pLeaves[1] : -1, + pCut->nLeaves > 2 ? pCut->pLeaves[2] : -1, + pCut->nLeaves > 3 ? pCut->pLeaves[3] : -1, + pCut->nLeaves > 4 ? pCut->pLeaves[4] : -1 + ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/cut/cutExpand.c b/abc70930/src/opt/cut/cutExpand.c new file mode 100644 index 00000000..d389ef7a --- /dev/null +++ b/abc70930/src/opt/cut/cutExpand.c @@ -0,0 +1,184 @@ +/**CFile**************************************************************** + + FileName [cutExpand.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [Computes the truth table of the cut after expansion.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutExpand.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define CUT_CELL_MVAR 9 + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 ) +{ + unsigned uPhase = 0; + int i, k; + for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) + { + if ( k == (int)pCut1->nLeaves ) + break; + if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) + continue; + assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); + uPhase |= (1 << i); + k++; + } + return uPhase; +} + +/**Function************************************************************* + + Synopsis [Computes the truth table of the composition of cuts.] + + Description [Inputs are: + - a factor cut (truth table is stored inside) + - a node in the factor cut + - a tree cut to be substituted (truth table is stored inside) + - the resulting cut (truth table will be filled in). + Note that all cuts, including the resulting one, should be already + computed and the nodes should be stored in the ascending order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_TruthCompose( Cut_Cut_t * pCutF, int Node, Cut_Cut_t * pCutT, Cut_Cut_t * pCutRes ) +{ + static unsigned uCof0[1<<(CUT_CELL_MVAR-5)]; + static unsigned uCof1[1<<(CUT_CELL_MVAR-5)]; + static unsigned uTemp[1<<(CUT_CELL_MVAR-5)]; + unsigned * pIn, * pOut, * pTemp; + unsigned uPhase; + int NodeIndex, i, k; + + // sanity checks + assert( pCutF->nVarsMax == pCutT->nVarsMax ); + assert( pCutF->nVarsMax == pCutRes->nVarsMax ); + assert( pCutF->nVarsMax <= CUT_CELL_MVAR ); + // the factor cut (pCutF) should have its nodes sorted in the ascending order + assert( pCutF->nLeaves <= pCutF->nVarsMax ); + for ( i = 0; i < (int)pCutF->nLeaves - 1; i++ ) + assert( pCutF->pLeaves[i] < pCutF->pLeaves[i+1] ); + // the tree cut (pCutT) should have its nodes sorted in the ascending order + assert( pCutT->nLeaves <= pCutT->nVarsMax ); + for ( i = 0; i < (int)pCutT->nLeaves - 1; i++ ) + assert( pCutT->pLeaves[i] < pCutT->pLeaves[i+1] ); + // the resulting cut (pCutRes) should have its nodes sorted in the ascending order + assert( pCutRes->nLeaves <= pCutRes->nVarsMax ); + for ( i = 0; i < (int)pCutRes->nLeaves - 1; i++ ) + assert( pCutRes->pLeaves[i] < pCutRes->pLeaves[i+1] ); + // make sure that every node in pCutF (except Node) appears in pCutRes + for ( i = 0; i < (int)pCutF->nLeaves; i++ ) + { + if ( pCutF->pLeaves[i] == Node ) + continue; + for ( k = 0; k < (int)pCutRes->nLeaves; k++ ) + if ( pCutF->pLeaves[i] == pCutRes->pLeaves[k] ) + break; + assert( k < (int)pCutRes->nLeaves ); // node i from pCutF is not found in pCutRes!!! + } + // make sure that every node in pCutT appears in pCutRes + for ( i = 0; i < (int)pCutT->nLeaves; i++ ) + { + for ( k = 0; k < (int)pCutRes->nLeaves; k++ ) + if ( pCutT->pLeaves[i] == pCutRes->pLeaves[k] ) + break; + assert( k < (int)pCutRes->nLeaves ); // node i from pCutT is not found in pCutRes!!! + } + + + // find the index of the given node in the factor cut + NodeIndex = -1; + for ( NodeIndex = 0; NodeIndex < (int)pCutF->nLeaves; NodeIndex++ ) + if ( pCutF->pLeaves[NodeIndex] == Node ) + break; + assert( NodeIndex >= 0 ); // Node should be in pCutF + + // copy the truth table + Extra_TruthCopy( uTemp, Cut_CutReadTruth(pCutF), pCutF->nLeaves ); + + // bubble-move the NodeIndex variable to be the last one (the most significant one) + pIn = uTemp; pOut = uCof0; // uCof0 is used for temporary storage here + for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ ) + { + Extra_TruthSwapAdjacentVars( pOut, pIn, pCutF->nLeaves, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + if ( (pCutF->nLeaves - 1 - NodeIndex) & 1 ) + Extra_TruthCopy( pOut, pIn, pCutF->nLeaves ); + // the result of stretching is in uTemp + + // cofactor the factor cut with respect to the node + Extra_TruthCopy( uCof0, uTemp, pCutF->nLeaves ); + Extra_TruthCofactor0( uCof0, pCutF->nLeaves, pCutF->nLeaves-1 ); + Extra_TruthCopy( uCof1, uTemp, pCutF->nLeaves ); + Extra_TruthCofactor1( uCof1, pCutF->nLeaves, pCutF->nLeaves-1 ); + + // temporarily shrink the factor cut's variables by removing Node + for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ ) + pCutF->pLeaves[i] = pCutF->pLeaves[i+1]; + pCutF->nLeaves--; + + // spread out the cofactors' truth tables to the same var order as the resulting cut + uPhase = Cut_TruthPhase(pCutRes, pCutF); + assert( Extra_WordCountOnes(uPhase) == (int)pCutF->nLeaves ); + Extra_TruthStretch( uTemp, uCof0, pCutF->nLeaves, pCutF->nVarsMax, uPhase ); + Extra_TruthCopy( uCof0, uTemp, pCutF->nVarsMax ); + Extra_TruthStretch( uTemp, uCof1, pCutF->nLeaves, pCutF->nVarsMax, uPhase ); + Extra_TruthCopy( uCof1, uTemp, pCutF->nVarsMax ); + + // spread out the tree cut's truth table to the same var order as the resulting cut + uPhase = Cut_TruthPhase(pCutRes, pCutT); + assert( Extra_WordCountOnes(uPhase) == (int)pCutT->nLeaves ); + Extra_TruthStretch( uTemp, Cut_CutReadTruth(pCutT), pCutT->nLeaves, pCutT->nVarsMax, uPhase ); + + // create the resulting truth table + pTemp = Cut_CutReadTruth(pCutRes); + for ( i = Extra_TruthWordNum(pCutRes->nLeaves)-1; i >= 0; i-- ) + pTemp[i] = (uCof0[i] & ~uTemp[i]) | (uCof1[i] & uTemp[i]); + + // undo the removal of the node from the cut + for ( i = (int)pCutF->nLeaves - 1; i >= NodeIndex; --i ) + pCutF->pLeaves[i+1] = pCutF->pLeaves[i]; + pCutF->pLeaves[NodeIndex] = Node; + pCutF->nLeaves++; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/cut/cutInt.h b/abc70930/src/opt/cut/cutInt.h new file mode 100644 index 00000000..17f268c7 --- /dev/null +++ b/abc70930/src/opt/cut/cutInt.h @@ -0,0 +1,157 @@ +/**CFile**************************************************************** + + FileName [cutInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CUT_INT_H__ +#define __CUT_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "extra.h" +#include "vec.h" +#include "cut.h" +#include "cutList.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cut_HashTableStruct_t_ Cut_HashTable_t; + +struct Cut_ManStruct_t_ +{ + // user preferences + Cut_Params_t * pParams; // computation parameters + Vec_Int_t * vFanCounts; // the array of fanout counters + Vec_Int_t * vNodeAttrs; // node attributes (1 = global; 0 = local) + // storage for cuts + Vec_Ptr_t * vCutsNew; // new cuts by node ID + Vec_Ptr_t * vCutsOld; // old cuts by node ID + Vec_Ptr_t * vCutsTemp; // temp cuts for cutset nodes by cutset node number + // memory management + Extra_MmFixed_t * pMmCuts; + int EntrySize; + int nTruthWords; + // temporary variables + Cut_Cut_t * pReady; + Vec_Ptr_t * vTemp; + int fCompl0; + int fCompl1; + int fSimul; + int nNodeCuts; + Cut_Cut_t * pStore0[2]; + Cut_Cut_t * pStore1[2]; + Cut_Cut_t * pCompareOld; + Cut_Cut_t * pCompareNew; + unsigned * puTemp[4]; + // record of the cut computation + Vec_Int_t * vNodeCuts; // the number of cuts for each node + Vec_Int_t * vNodeStarts; // the number of the starting cut of each node + Vec_Int_t * vCutPairs; // the pairs of parent cuts for each cut + // minimum delay mapping with the given cuts + Vec_Ptr_t * vCutsMax; + Vec_Int_t * vDelays; + Vec_Int_t * vDelays2; + int nDelayMin; + // statistics + int nCutsCur; + int nCutsAlloc; + int nCutsDealloc; + int nCutsPeak; + int nCutsTriv; + int nCutsFilter; + int nCutsLimit; + int nNodes; + int nNodesDag; + int nNodesNoCuts; + // runtime + int timeMerge; + int timeUnion; + int timeTruth; + int timeFilter; + int timeHash; + int timeMap; +}; + +// iterator through all the cuts of the list +#define Cut_ListForEachCut( pList, pCut ) \ + for ( pCut = pList; \ + pCut; \ + pCut = pCut->pNext ) +#define Cut_ListForEachCutStop( pList, pCut, pStop ) \ + for ( pCut = pList; \ + pCut != pStop; \ + pCut = pCut->pNext ) +#define Cut_ListForEachCutSafe( pList, pCut, pCut2 ) \ + for ( pCut = pList, \ + pCut2 = pCut? pCut->pNext: NULL; \ + pCut; \ + pCut = pCut2, \ + pCut2 = pCut? pCut->pNext: NULL ) + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// computes signature of the node +static inline unsigned Cut_NodeSign( int Node ) { return (1 << (Node % 31)); } +static inline int Cut_TruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 1 : (1 << (nVarsMax - 5)); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== cutCut.c ==========================================================*/ +extern Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p ); +extern void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut ); +extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 ); +extern Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList ); +extern void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList ); +extern Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 ); +extern void Cut_CutNumberList( Cut_Cut_t * pList ); +extern Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node ); +extern void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); +/*=== cutMerge.c ==========================================================*/ +extern Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); +/*=== cutNode.c ==========================================================*/ +extern void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode ); +extern int Cut_CutListVerify( Cut_Cut_t * pList ); +/*=== cutTable.c ==========================================================*/ +extern Cut_HashTable_t * Cut_TableStart( int Size ); +extern void Cut_TableStop( Cut_HashTable_t * pTable ); +extern int Cut_TableLookup( Cut_HashTable_t * pTable, Cut_Cut_t * pCut, int fStore ); +extern void Cut_TableClear( Cut_HashTable_t * pTable ); +extern int Cut_TableReadTime( Cut_HashTable_t * pTable ); +/*=== cutTruth.c ==========================================================*/ +extern void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ); +extern void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/cut/cutList.h b/abc70930/src/opt/cut/cutList.h new file mode 100644 index 00000000..a03ec9d5 --- /dev/null +++ b/abc70930/src/opt/cut/cutList.h @@ -0,0 +1,207 @@ +/**CFile**************************************************************** + + FileName [cutList.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Implementation of layered listed list of cuts.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutList.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __CUT_LIST_H__ +#define __CUT_LIST_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cut_ListStruct_t_ Cut_List_t; +struct Cut_ListStruct_t_ +{ + Cut_Cut_t * pHead[CUT_SIZE_MAX+1]; + Cut_Cut_t ** ppTail[CUT_SIZE_MAX+1]; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start the cut list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cut_ListStart( Cut_List_t * p ) +{ + int i; + for ( i = 1; i <= CUT_SIZE_MAX; i++ ) + { + p->pHead[i] = 0; + p->ppTail[i] = &p->pHead[i]; + } +} + +/**Function************************************************************* + + Synopsis [Adds one cut to the cut list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cut_ListAdd( Cut_List_t * p, Cut_Cut_t * pCut ) +{ + assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX ); + *p->ppTail[pCut->nLeaves] = pCut; + p->ppTail[pCut->nLeaves] = &pCut->pNext; +} + +/**Function************************************************************* + + Synopsis [Adds one cut to the cut list while preserving order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cut_ListAdd2( Cut_List_t * p, Cut_Cut_t * pCut ) +{ + extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 ); + Cut_Cut_t * pTemp, ** ppSpot; + assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX ); + if ( p->pHead[pCut->nLeaves] != NULL ) + { + ppSpot = &p->pHead[pCut->nLeaves]; + for ( pTemp = p->pHead[pCut->nLeaves]; pTemp; pTemp = pTemp->pNext ) + { + if ( Cut_CutCompare(pCut, pTemp) < 0 ) + { + *ppSpot = pCut; + pCut->pNext = pTemp; + return; + } + else + ppSpot = &pTemp->pNext; + } + } + *p->ppTail[pCut->nLeaves] = pCut; + p->ppTail[pCut->nLeaves] = &pCut->pNext; +} + +/**Function************************************************************* + + Synopsis [Derive the super list from the linked list of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cut_ListDerive( Cut_List_t * p, Cut_Cut_t * pList ) +{ + Cut_Cut_t * pPrev; + int nLeaves; + Cut_ListStart( p ); + while ( pList != NULL ) + { + nLeaves = pList->nLeaves; + p->pHead[nLeaves] = pList; + for ( pPrev = pList, pList = pList->pNext; pList; pPrev = pList, pList = pList->pNext ) + if ( nLeaves < (int)pList->nLeaves ) + break; + p->ppTail[nLeaves] = &pPrev->pNext; + pPrev->pNext = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Adds the second list to the first list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cut_ListAddList( Cut_List_t * pOld, Cut_List_t * pNew ) +{ + int i; + for ( i = 1; i <= CUT_SIZE_MAX; i++ ) + { + if ( pNew->pHead[i] == NULL ) + continue; + *pOld->ppTail[i] = pNew->pHead[i]; + pOld->ppTail[i] = pNew->ppTail[i]; + } +} + +/**Function************************************************************* + + Synopsis [Returns the cut list linked into one sequence of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Cut_Cut_t * Cut_ListFinish( Cut_List_t * p ) +{ + Cut_Cut_t * pHead = NULL, ** ppTail = &pHead; + int i; + for ( i = 1; i <= CUT_SIZE_MAX; i++ ) + { + if ( p->pHead[i] == NULL ) + continue; + *ppTail = p->pHead[i]; + ppTail = p->ppTail[i]; + } + *ppTail = NULL; + return pHead; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/cut/cutMan.c b/abc70930/src/opt/cut/cutMan.c new file mode 100644 index 00000000..8593ef93 --- /dev/null +++ b/abc70930/src/opt/cut/cutMan.c @@ -0,0 +1,326 @@ +/**CFile**************************************************************** + + FileName [cutMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [Cut manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Npn_StartTruth8( uint8 uTruths[][32] ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the cut manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams ) +{ + Cut_Man_t * p; + int clk = clock(); +// extern int nTruthDsd; +// nTruthDsd = 0; + assert( pParams->nVarsMax >= 3 && pParams->nVarsMax <= CUT_SIZE_MAX ); + p = ALLOC( Cut_Man_t, 1 ); + memset( p, 0, sizeof(Cut_Man_t) ); + // set and correct parameters + p->pParams = pParams; + // prepare storage for cuts + p->vCutsNew = Vec_PtrAlloc( pParams->nIdsMax ); + Vec_PtrFill( p->vCutsNew, pParams->nIdsMax, NULL ); + // prepare storage for sequential cuts + if ( pParams->fSeq ) + { + p->pParams->fFilter = 1; + p->vCutsOld = Vec_PtrAlloc( pParams->nIdsMax ); + Vec_PtrFill( p->vCutsOld, pParams->nIdsMax, NULL ); + p->vCutsTemp = Vec_PtrAlloc( pParams->nCutSet ); + Vec_PtrFill( p->vCutsTemp, pParams->nCutSet, NULL ); + if ( pParams->fTruth && pParams->nVarsMax > 5 ) + { + pParams->fTruth = 0; + printf( "Skipping computation of truth tables for sequential cuts with more than 5 inputs.\n" ); + } + } + // entry size + p->EntrySize = sizeof(Cut_Cut_t) + pParams->nVarsMax * sizeof(int); + if ( pParams->fTruth ) + { + if ( pParams->nVarsMax > 14 ) + { + pParams->fTruth = 0; + printf( "Skipping computation of truth table for more than %d inputs.\n", 14 ); + } + else + { + p->nTruthWords = Cut_TruthWords( pParams->nVarsMax ); + p->EntrySize += p->nTruthWords * sizeof(unsigned); + } + p->puTemp[0] = ALLOC( unsigned, 4 * p->nTruthWords ); + p->puTemp[1] = p->puTemp[0] + p->nTruthWords; + p->puTemp[2] = p->puTemp[1] + p->nTruthWords; + p->puTemp[3] = p->puTemp[2] + p->nTruthWords; + } + // enable cut computation recording + if ( pParams->fRecord ) + { + p->vNodeCuts = Vec_IntStart( pParams->nIdsMax ); + p->vNodeStarts = Vec_IntStart( pParams->nIdsMax ); + p->vCutPairs = Vec_IntAlloc( 0 ); + } + // allocate storage for delays + if ( pParams->fMap && !p->pParams->fSeq ) + { + p->vDelays = Vec_IntStart( pParams->nIdsMax ); + p->vDelays2 = Vec_IntStart( pParams->nIdsMax ); + p->vCutsMax = Vec_PtrStart( pParams->nIdsMax ); + } + // memory for cuts + p->pMmCuts = Extra_MmFixedStart( p->EntrySize ); + p->vTemp = Vec_PtrAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the cut manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_ManStop( Cut_Man_t * p ) +{ + Cut_Cut_t * pCut; + int i; +// extern int nTruthDsd; +// printf( "Decomposable cuts = %d.\n", nTruthDsd ); + + Vec_PtrForEachEntry( p->vCutsNew, pCut, i ) + if ( pCut != NULL ) + { + int k = 0; + } + if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew ); + if ( p->vCutsOld ) Vec_PtrFree( p->vCutsOld ); + if ( p->vCutsTemp ) Vec_PtrFree( p->vCutsTemp ); + if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts ); + if ( p->vTemp ) Vec_PtrFree( p->vTemp ); + + if ( p->vCutsMax ) Vec_PtrFree( p->vCutsMax ); + if ( p->vDelays ) Vec_IntFree( p->vDelays ); + if ( p->vDelays2 ) Vec_IntFree( p->vDelays2 ); + if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts ); + if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts ); + if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs ); + if ( p->puTemp[0] ) free( p->puTemp[0] ); + + Extra_MmFixedStop( p->pMmCuts ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_ManPrintStats( Cut_Man_t * p ) +{ + if ( p->pReady ) + { + Cut_CutRecycle( p, p->pReady ); + p->pReady = NULL; + } + printf( "Cut computation statistics:\n" ); + printf( "Current cuts = %8d. (Trivial = %d.)\n", p->nCutsCur-p->nCutsTriv, p->nCutsTriv ); + printf( "Peak cuts = %8d.\n", p->nCutsPeak ); + printf( "Total allocated = %8d.\n", p->nCutsAlloc ); + printf( "Total deallocated = %8d.\n", p->nCutsDealloc ); + printf( "Cuts filtered = %8d.\n", p->nCutsFilter ); + printf( "Nodes saturated = %8d. (Max cuts = %d.)\n", p->nCutsLimit, p->pParams->nKeepMax ); + printf( "Cuts per node = %8.1f\n", ((float)(p->nCutsCur-p->nCutsTriv))/p->nNodes ); + printf( "The cut size = %8d bytes.\n", p->EntrySize ); + printf( "Peak memory = %8.2f Mb.\n", (float)p->nCutsPeak * p->EntrySize / (1<<20) ); + printf( "Total nodes = %8d.\n", p->nNodes ); + if ( p->pParams->fDag || p->pParams->fTree ) + { + printf( "DAG nodes = %8d.\n", p->nNodesDag ); + printf( "Tree nodes = %8d.\n", p->nNodes - p->nNodesDag ); + } + printf( "Nodes w/o cuts = %8d.\n", p->nNodesNoCuts ); + if ( p->pParams->fMap && !p->pParams->fSeq ) + printf( "Mapping delay = %8d.\n", p->nDelayMin ); + + PRT( "Merge ", p->timeMerge ); + PRT( "Union ", p->timeUnion ); + PRT( "Filter", p->timeFilter ); + PRT( "Truth ", p->timeTruth ); + PRT( "Map ", p->timeMap ); +// printf( "Nodes = %d. Multi = %d. Cuts = %d. Multi = %d.\n", +// p->nNodes, p->nNodesMulti, p->nCutsCur-p->nCutsTriv, p->nCutsMulti ); +// printf( "Count0 = %d. Count1 = %d. Count2 = %d.\n\n", p->Count0, p->Count1, p->Count2 ); +} + + +/**Function************************************************************* + + Synopsis [Prints some interesting stats.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, int TimeTotal ) +{ + FILE * pTable; + pTable = fopen( "cut_stats.txt", "a+" ); + fprintf( pTable, "%-20s ", pFileName ); + fprintf( pTable, "%8d ", p->nNodes ); + fprintf( pTable, "%6.1f ", ((float)(p->nCutsCur))/p->nNodes ); + fprintf( pTable, "%6.2f ", ((float)(100.0 * p->nCutsLimit))/p->nNodes ); + fprintf( pTable, "%6.2f ", (float)p->nCutsPeak * p->EntrySize / (1<<20) ); + fprintf( pTable, "%6.2f ", (float)(TimeTotal)/(float)(CLOCKS_PER_SEC) ); + fprintf( pTable, "\n" ); + fclose( pTable ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts ) +{ + p->vFanCounts = vFanCounts; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vNodeAttrs ) +{ + p->vNodeAttrs = vNodeAttrs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_ManReadVarsMax( Cut_Man_t * p ) +{ + return p->pParams->nVarsMax; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Params_t * Cut_ManReadParams( Cut_Man_t * p ) +{ + return p->pParams; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cut_ManReadNodeAttrs( Cut_Man_t * p ) +{ + return p->vNodeAttrs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_ManIncrementDagNodes( Cut_Man_t * p ) +{ + p->nNodesDag++; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/cut/cutMerge.c b/abc70930/src/opt/cut/cutMerge.c new file mode 100644 index 00000000..d8a9989c --- /dev/null +++ b/abc70930/src/opt/cut/cutMerge.c @@ -0,0 +1,657 @@ +/**CFile**************************************************************** + + FileName [cutMerge.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [Procedure to merge two cuts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [This procedure works.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) +{ + static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}}; + Cut_Cut_t * pRes; + int * pRow; + int nLeaves0, nLeaves1, Limit; + int i, k, Count, nNodes; + + assert( pCut0->nLeaves >= pCut1->nLeaves ); + + // the case of the largest cut sizes + Limit = p->pParams->nVarsMax; + nLeaves0 = pCut0->nLeaves; + nLeaves1 = pCut1->nLeaves; + if ( nLeaves0 == Limit && nLeaves1 == Limit ) + { + for ( i = 0; i < nLeaves0; i++ ) + if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] ) + return NULL; + pRes = Cut_CutAlloc( p ); + for ( i = 0; i < nLeaves0; i++ ) + pRes->pLeaves[i] = pCut0->pLeaves[i]; + pRes->nLeaves = nLeaves0; + return pRes; + } + // the case when one of the cuts is the largest + if ( nLeaves0 == Limit ) + { + for ( i = 0; i < nLeaves1; i++ ) + { + for ( k = nLeaves0 - 1; k >= 0; k-- ) + if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) + break; + if ( k == -1 ) // did not find + return NULL; + } + pRes = Cut_CutAlloc( p ); + for ( i = 0; i < nLeaves0; i++ ) + pRes->pLeaves[i] = pCut0->pLeaves[i]; + pRes->nLeaves = nLeaves0; + return pRes; + } + // other cases + nNodes = nLeaves0; + for ( i = 0; i < nLeaves1; i++ ) + { + for ( k = nLeaves0 - 1; k >= 0; k-- ) + { + if ( pCut0->pLeaves[k] > pCut1->pLeaves[i] ) + continue; + if ( pCut0->pLeaves[k] < pCut1->pLeaves[i] ) + { + pRow = M[k+1]; + if ( pRow[0] == 0 ) + pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; + else if ( pRow[1] == 0 ) + pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; + else if ( pRow[2] == 0 ) + pRow[2] = pCut1->pLeaves[i]; + else + assert( 0 ); + if ( ++nNodes > Limit ) + { + for ( i = 0; i <= nLeaves0; i++ ) + M[i][0] = 0; + return NULL; + } + } + break; + } + if ( k == -1 ) + { + pRow = M[0]; + if ( pRow[0] == 0 ) + pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; + else if ( pRow[1] == 0 ) + pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; + else if ( pRow[2] == 0 ) + pRow[2] = pCut1->pLeaves[i]; + else + assert( 0 ); + if ( ++nNodes > Limit ) + { + for ( i = 0; i <= nLeaves0; i++ ) + M[i][0] = 0; + return NULL; + } + continue; + } + } + + pRes = Cut_CutAlloc( p ); + for ( Count = 0, i = 0; i <= nLeaves0; i++ ) + { + if ( i > 0 ) + pRes->pLeaves[Count++] = pCut0->pLeaves[i-1]; + pRow = M[i]; + if ( pRow[0] ) + { + pRes->pLeaves[Count++] = pRow[0]; + if ( pRow[1] ) + { + pRes->pLeaves[Count++] = pRow[1]; + if ( pRow[2] ) + pRes->pLeaves[Count++] = pRow[2]; + } + pRow[0] = 0; + } + } + assert( Count == nNodes ); + pRes->nLeaves = nNodes; + return pRes; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) +{ + Cut_Cut_t * pRes; + int * pLeaves; + int Limit, nLeaves0, nLeaves1; + int i, k, c; + + assert( pCut0->nLeaves >= pCut1->nLeaves ); + + // consider two cuts + nLeaves0 = pCut0->nLeaves; + nLeaves1 = pCut1->nLeaves; + + // the case of the largest cut sizes + Limit = p->pParams->nVarsMax; + if ( nLeaves0 == Limit && nLeaves1 == Limit ) + { + for ( i = 0; i < nLeaves0; i++ ) + if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] ) + return NULL; + pRes = Cut_CutAlloc( p ); + for ( i = 0; i < nLeaves0; i++ ) + pRes->pLeaves[i] = pCut0->pLeaves[i]; + pRes->nLeaves = pCut0->nLeaves; + return pRes; + } + // the case when one of the cuts is the largest + if ( nLeaves0 == Limit ) + { + for ( i = 0; i < nLeaves1; i++ ) + { + for ( k = nLeaves0 - 1; k >= 0; k-- ) + if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) + break; + if ( k == -1 ) // did not find + return NULL; + } + pRes = Cut_CutAlloc( p ); + for ( i = 0; i < nLeaves0; i++ ) + pRes->pLeaves[i] = pCut0->pLeaves[i]; + pRes->nLeaves = pCut0->nLeaves; + return pRes; + } + + // prepare the cut + if ( p->pReady == NULL ) + p->pReady = Cut_CutAlloc( p ); + pLeaves = p->pReady->pLeaves; + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < Limit; c++ ) + { + if ( k == nLeaves1 ) + { + if ( i == nLeaves0 ) + { + p->pReady->nLeaves = c; + pRes = p->pReady; p->pReady = NULL; + return pRes; + } + pLeaves[c] = pCut0->pLeaves[i++]; + continue; + } + if ( i == nLeaves0 ) + { + if ( k == nLeaves1 ) + { + p->pReady->nLeaves = c; + pRes = p->pReady; p->pReady = NULL; + return pRes; + } + pLeaves[c] = pCut1->pLeaves[k++]; + continue; + } + if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] ) + { + pLeaves[c] = pCut0->pLeaves[i++]; + continue; + } + if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] ) + { + pLeaves[c] = pCut1->pLeaves[k++]; + continue; + } + pLeaves[c] = pCut0->pLeaves[i++]; + k++; + } + if ( i < nLeaves0 || k < nLeaves1 ) + return NULL; + p->pReady->nLeaves = c; + pRes = p->pReady; p->pReady = NULL; + return pRes; +} + + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutMergeTwo3( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) +{ + Cut_Cut_t * pRes; + int * pLeaves; + int Limit, nLeaves0, nLeaves1; + int i, k, c; + + assert( pCut0->nLeaves >= pCut1->nLeaves ); + + // prepare the cut + if ( p->pReady == NULL ) + p->pReady = Cut_CutAlloc( p ); + pLeaves = p->pReady->pLeaves; + + // consider two cuts + Limit = p->pParams->nVarsMax; + nLeaves0 = pCut0->nLeaves; + nLeaves1 = pCut1->nLeaves; + if ( nLeaves0 == Limit ) + { // the case when one of the cuts is the largest + if ( nLeaves1 == Limit ) + { // the case when both cuts are the largest + for ( i = 0; i < nLeaves0; i++ ) + { + pLeaves[i] = pCut0->pLeaves[i]; + if ( pLeaves[i] != pCut1->pLeaves[i] ) + return NULL; + } + } + else + { + for ( i = k = 0; i < nLeaves0; i++ ) + { + pLeaves[i] = pCut0->pLeaves[i]; + if ( k == (int)nLeaves1 ) + continue; + if ( pLeaves[i] < pCut1->pLeaves[k] ) + continue; + if ( pLeaves[i] == pCut1->pLeaves[k++] ) + continue; + return NULL; + } + if ( k < nLeaves1 ) + return NULL; + } + p->pReady->nLeaves = nLeaves0; + pRes = p->pReady; p->pReady = NULL; + return pRes; + } + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < Limit; c++ ) + { + if ( k == nLeaves1 ) + { + if ( i == nLeaves0 ) + { + p->pReady->nLeaves = c; + pRes = p->pReady; p->pReady = NULL; + return pRes; + } + pLeaves[c] = pCut0->pLeaves[i++]; + continue; + } + if ( i == nLeaves0 ) + { + if ( k == nLeaves1 ) + { + p->pReady->nLeaves = c; + pRes = p->pReady; p->pReady = NULL; + return pRes; + } + pLeaves[c] = pCut1->pLeaves[k++]; + continue; + } + if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] ) + { + pLeaves[c] = pCut0->pLeaves[i++]; + continue; + } + if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] ) + { + pLeaves[c] = pCut1->pLeaves[k++]; + continue; + } + pLeaves[c] = pCut0->pLeaves[i++]; + k++; + } + if ( i < nLeaves0 || k < nLeaves1 ) + return NULL; + p->pReady->nLeaves = c; + pRes = p->pReady; p->pReady = NULL; + return pRes; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutMergeTwo4( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) +{ + Cut_Cut_t * pRes; + int * pLeaves; + int i, k, min, NodeTemp, Limit, nTotal; + + assert( pCut0->nLeaves >= pCut1->nLeaves ); + + // prepare the cut + if ( p->pReady == NULL ) + p->pReady = Cut_CutAlloc( p ); + pLeaves = p->pReady->pLeaves; + + // consider two cuts + Limit = p->pParams->nVarsMax; + if ( pCut0->nLeaves == (unsigned)Limit ) + { // the case when one of the cuts is the largest + if ( pCut1->nLeaves == (unsigned)Limit ) + { // the case when both cuts are the largest + for ( i = 0; i < (int)pCut0->nLeaves; i++ ) + { + pLeaves[i] = pCut0->pLeaves[i]; + if ( pLeaves[i] != pCut1->pLeaves[i] ) + return NULL; + } + } + else + { + for ( i = k = 0; i < (int)pCut0->nLeaves; i++ ) + { + pLeaves[i] = pCut0->pLeaves[i]; + if ( k == (int)pCut1->nLeaves ) + continue; + if ( pLeaves[i] < pCut1->pLeaves[k] ) + continue; + if ( pLeaves[i] == pCut1->pLeaves[k++] ) + continue; + return NULL; + } + if ( k < (int)pCut1->nLeaves ) + return NULL; + } + p->pReady->nLeaves = pCut0->nLeaves; + pRes = p->pReady; p->pReady = NULL; + return pRes; + } + + // count the number of unique entries in pCut1 + nTotal = pCut0->nLeaves; + for ( i = 0; i < (int)pCut1->nLeaves; i++ ) + { + // try to find this entry among the leaves of pCut0 + for ( k = 0; k < (int)pCut0->nLeaves; k++ ) + if ( pCut1->pLeaves[i] == pCut0->pLeaves[k] ) + break; + if ( k < (int)pCut0->nLeaves ) // found + continue; + // we found a new entry to add + if ( nTotal == Limit ) + return NULL; + pLeaves[nTotal++] = pCut1->pLeaves[i]; + } + // we know that the feasible cut exists + + // add the starting entries + for ( k = 0; k < (int)pCut0->nLeaves; k++ ) + pLeaves[k] = pCut0->pLeaves[k]; + + // selection-sort the entries + for ( i = 0; i < nTotal - 1; i++ ) + { + min = i; + for ( k = i+1; k < nTotal; k++ ) + if ( pLeaves[k] < pLeaves[min] ) + min = k; + NodeTemp = pLeaves[i]; + pLeaves[i] = pLeaves[min]; + pLeaves[min] = NodeTemp; + } + p->pReady->nLeaves = nTotal; + pRes = p->pReady; p->pReady = NULL; + return pRes; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [This procedure works.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutMergeTwo5( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) +{ + static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}}; + Cut_Cut_t * pRes; + int * pRow; + unsigned uSign0, uSign1; + int i, k, nNodes, Count; + unsigned Limit = p->pParams->nVarsMax; + + assert( pCut0->nLeaves >= pCut1->nLeaves ); + + // the case of the largest cut sizes + if ( pCut0->nLeaves == Limit && pCut1->nLeaves == Limit ) + { + for ( i = 0; i < (int)pCut0->nLeaves; i++ ) + if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] ) + return NULL; + pRes = Cut_CutAlloc( p ); + for ( i = 0; i < (int)pCut0->nLeaves; i++ ) + pRes->pLeaves[i] = pCut0->pLeaves[i]; + pRes->nLeaves = pCut0->nLeaves; + return pRes; + } + // the case when one of the cuts is the largest + if ( pCut0->nLeaves == Limit ) + { + if ( !p->pParams->fTruth ) + { + for ( i = 0; i < (int)pCut1->nLeaves; i++ ) + { + for ( k = pCut0->nLeaves - 1; k >= 0; k-- ) + if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) + break; + if ( k == -1 ) // did not find + return NULL; + } + pRes = Cut_CutAlloc( p ); + } + else + { + uSign1 = 0; + for ( i = 0; i < (int)pCut1->nLeaves; i++ ) + { + for ( k = pCut0->nLeaves - 1; k >= 0; k-- ) + if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) + { + uSign1 |= (1 << i); + break; + } + if ( k == -1 ) // did not find + return NULL; + } + pRes = Cut_CutAlloc( p ); + pRes->Num1 = uSign1; + } + for ( i = 0; i < (int)pCut0->nLeaves; i++ ) + pRes->pLeaves[i] = pCut0->pLeaves[i]; + pRes->nLeaves = pCut0->nLeaves; + return pRes; + } + // other cases + nNodes = pCut0->nLeaves; + for ( i = 0; i < (int)pCut1->nLeaves; i++ ) + { + for ( k = pCut0->nLeaves - 1; k >= 0; k-- ) + { + if ( pCut0->pLeaves[k] > pCut1->pLeaves[i] ) + continue; + if ( pCut0->pLeaves[k] < pCut1->pLeaves[i] ) + { + pRow = M[k+1]; + if ( pRow[0] == 0 ) + pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; + else if ( pRow[1] == 0 ) + pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; + else if ( pRow[2] == 0 ) + pRow[2] = pCut1->pLeaves[i]; + else + assert( 0 ); + if ( ++nNodes > (int)Limit ) + { + for ( i = 0; i <= (int)pCut0->nLeaves; i++ ) + M[i][0] = 0; + return NULL; + } + } + break; + } + if ( k == -1 ) + { + pRow = M[0]; + if ( pRow[0] == 0 ) + pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; + else if ( pRow[1] == 0 ) + pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; + else if ( pRow[2] == 0 ) + pRow[2] = pCut1->pLeaves[i]; + else + assert( 0 ); + if ( ++nNodes > (int)Limit ) + { + for ( i = 0; i <= (int)pCut0->nLeaves; i++ ) + M[i][0] = 0; + return NULL; + } + continue; + } + } + + pRes = Cut_CutAlloc( p ); + if ( !p->pParams->fTruth ) + { + for ( Count = 0, i = 0; i <= (int)pCut0->nLeaves; i++ ) + { + if ( i > 0 ) + pRes->pLeaves[Count++] = pCut0->pLeaves[i-1]; + pRow = M[i]; + if ( pRow[0] ) + { + pRes->pLeaves[Count++] = pRow[0]; + if ( pRow[1] ) + { + pRes->pLeaves[Count++] = pRow[1]; + if ( pRow[2] ) + pRes->pLeaves[Count++] = pRow[2]; + } + pRow[0] = 0; + } + } + assert( Count == nNodes ); + pRes->nLeaves = nNodes; +/* + // make sure that the cut is correct + { + for ( i = 1; i < (int)pRes->nLeaves; i++ ) + if ( pRes->pLeaves[i-1] >= pRes->pLeaves[i] ) + { + int v = 0; + } + } +*/ + return pRes; + } + + uSign0 = uSign1 = 0; + for ( Count = 0, i = 0; i <= (int)pCut0->nLeaves; i++ ) + { + if ( i > 0 ) + { + uSign0 |= (1 << Count); + pRes->pLeaves[Count++] = pCut1->pLeaves[i-1]; + } + pRow = M[i]; + if ( pRow[0] ) + { + uSign1 |= (1 << Count); + pRes->pLeaves[Count++] = pRow[0]; + if ( pRow[1] ) + { + uSign1 |= (1 << Count); + pRes->pLeaves[Count++] = pRow[1]; + if ( pRow[2] ) + { + uSign1 |= (1 << Count); + pRes->pLeaves[Count++] = pRow[2]; + } + } + pRow[0] = 0; + } + } + assert( Count == nNodes ); + pRes->nLeaves = nNodes; + pRes->Num1 = uSign1; + pRes->Num0 = uSign0; + return pRes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/cut/cutNode.c b/abc70930/src/opt/cut/cutNode.c new file mode 100644 index 00000000..1f93b14b --- /dev/null +++ b/abc70930/src/opt/cut/cutNode.c @@ -0,0 +1,992 @@ +/**CFile**************************************************************** + + FileName [cutNode.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [Procedures to compute cuts for a node.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ); +static int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cut_CutCheckDominance( Cut_Cut_t * pDom, Cut_Cut_t * pCut ) +{ + int i, k; + for ( i = 0; i < (int)pDom->nLeaves; i++ ) + { + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) + break; + if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Filters cuts using dominance.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList ) +{ + Cut_Cut_t * pListR, ** ppListR = &pListR; + Cut_Cut_t * pCut, * pCut2, * pDom, * pPrev; + // save the first cut + *ppListR = pList, ppListR = &pList->pNext; + // try to filter out other cuts + pPrev = pList; + Cut_ListForEachCutSafe( pList->pNext, pCut, pCut2 ) + { + assert( pCut->nLeaves > 1 ); + // go through all the previous cuts up to pCut + Cut_ListForEachCutStop( pList->pNext, pDom, pCut ) + { + if ( pDom->nLeaves > pCut->nLeaves ) + continue; + if ( (pDom->uSign & pCut->uSign) != pDom->uSign ) + continue; + if ( Cut_CutCheckDominance( pDom, pCut ) ) + break; + } + if ( pDom != pCut ) // pDom is contained in pCut - recycle pCut + { + // make sure cuts are connected after removing + pPrev->pNext = pCut->pNext; + // recycle the cut + Cut_CutRecycle( p, pCut ); + } + else // pDom is NOT contained in pCut - save pCut + { + *ppListR = pCut, ppListR = &pCut->pNext; + pPrev = pCut; + } + } + *ppListR = NULL; +} + +/**Function************************************************************* + + Synopsis [Checks equality of one cut.] + + Description [Returns 1 if the cut is removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cut_CutFilterOneEqual( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut ) +{ + Cut_Cut_t * pTemp; + Cut_ListForEachCut( pSuperList->pHead[pCut->nLeaves], pTemp ) + { + // skip the non-contained cuts + if ( pCut->uSign != pTemp->uSign ) + continue; + // check containment seriously + if ( Cut_CutCheckDominance( pTemp, pCut ) ) + { + p->nCutsFilter++; + Cut_CutRecycle( p, pCut ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks containment for one cut.] + + Description [Returns 1 if the cut is removed.] + + SideEffects [May remove other cuts in the set.] + + SeeAlso [] + +***********************************************************************/ +static inline int Cut_CutFilterOne( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut ) +{ + Cut_Cut_t * pTemp, * pTemp2, ** ppTail; + int a; + + // check if this cut is filtered out by smaller cuts + for ( a = 2; a <= (int)pCut->nLeaves; a++ ) + { + Cut_ListForEachCut( pSuperList->pHead[a], pTemp ) + { + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) + continue; + // check containment seriously + if ( Cut_CutCheckDominance( pTemp, pCut ) ) + { + p->nCutsFilter++; + Cut_CutRecycle( p, pCut ); + return 1; + } + } + } + + // filter out other cuts using this one + for ( a = pCut->nLeaves + 1; a <= (int)pCut->nVarsMax; a++ ) + { + ppTail = pSuperList->pHead + a; + Cut_ListForEachCutSafe( pSuperList->pHead[a], pTemp, pTemp2 ) + { + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) + { + ppTail = &pTemp->pNext; + continue; + } + // check containment seriously + if ( Cut_CutCheckDominance( pCut, pTemp ) ) + { + p->nCutsFilter++; + p->nNodeCuts--; + // move the head + if ( pSuperList->pHead[a] == pTemp ) + pSuperList->pHead[a] = pTemp->pNext; + // move the tail + if ( pSuperList->ppTail[a] == &pTemp->pNext ) + pSuperList->ppTail[a] = ppTail; + // skip the given cut in the list + *ppTail = pTemp->pNext; + // recycle pTemp + Cut_CutRecycle( p, pTemp ); + } + else + ppTail = &pTemp->pNext; + } + assert( ppTail == pSuperList->ppTail[a] ); + assert( *ppTail == NULL ); + } + + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the cut is local and can be removed.] + + Description [Returns 1 if the cut is removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cut_CutFilterGlobal( Cut_Man_t * p, Cut_Cut_t * pCut ) +{ + int a; + if ( pCut->nLeaves == 1 ) + return 0; + for ( a = 0; a < (int)pCut->nLeaves; a++ ) + if ( Vec_IntEntry( p->vNodeAttrs, pCut->pLeaves[a] ) ) // global + return 0; + // there is no global nodes, the cut should be removed + p->nCutsFilter++; + Cut_CutRecycle( p, pCut ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Checks containment for one cut.] + + Description [Returns 1 if the cut is removed.] + + SideEffects [May remove other cuts in the set.] + + SeeAlso [] + +***********************************************************************/ +static inline int Cut_CutFilterOld( Cut_Man_t * p, Cut_Cut_t * pList, Cut_Cut_t * pCut ) +{ + Cut_Cut_t * pPrev, * pTemp, * pTemp2, ** ppTail; + + // check if this cut is filtered out by smaller cuts + pPrev = NULL; + Cut_ListForEachCut( pList, pTemp ) + { + if ( pTemp->nLeaves > pCut->nLeaves ) + break; + pPrev = pTemp; + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) + continue; + // check containment seriously + if ( Cut_CutCheckDominance( pTemp, pCut ) ) + { + p->nCutsFilter++; + Cut_CutRecycle( p, pCut ); + return 1; + } + } + assert( pPrev->pNext == pTemp ); + + // filter out other cuts using this one + ppTail = &pPrev->pNext; + Cut_ListForEachCutSafe( pTemp, pTemp, pTemp2 ) + { + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) + { + ppTail = &pTemp->pNext; + continue; + } + // check containment seriously + if ( Cut_CutCheckDominance( pCut, pTemp ) ) + { + p->nCutsFilter++; + p->nNodeCuts--; + // skip the given cut in the list + *ppTail = pTemp->pNext; + // recycle pTemp + Cut_CutRecycle( p, pTemp ); + } + else + ppTail = &pTemp->pNext; + } + assert( *ppTail == NULL ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Processes two cuts.] + + Description [Returns 1 if the limit has been reached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cut_CutProcessTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList ) +{ + Cut_Cut_t * pCut; + // merge the cuts + if ( pCut0->nLeaves >= pCut1->nLeaves ) + pCut = Cut_CutMergeTwo( p, pCut0, pCut1 ); + else + pCut = Cut_CutMergeTwo( p, pCut1, pCut0 ); + if ( pCut == NULL ) + return 0; + assert( p->pParams->fSeq || pCut->nLeaves > 1 ); + // set the signature + pCut->uSign = pCut0->uSign | pCut1->uSign; + if ( p->pParams->fRecord ) + pCut->Num0 = pCut0->Num0, pCut->Num1 = pCut1->Num0; + // check containment + if ( p->pParams->fFilter ) + { + if ( Cut_CutFilterOne(p, pSuperList, pCut) ) +// if ( Cut_CutFilterOneEqual(p, pSuperList, pCut) ) + return 0; + if ( p->pParams->fSeq ) + { + if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) + return 0; + if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) + return 0; + } + } + + if ( p->pParams->fGlobal ) + { + assert( p->vNodeAttrs != NULL ); + if ( Cut_CutFilterGlobal( p, pCut ) ) + return 0; + } + + // compute the truth table + if ( p->pParams->fTruth ) + Cut_TruthCompute( p, pCut, pCut0, pCut1, p->fCompl0, p->fCompl1 ); + // add to the list + Cut_ListAdd( pSuperList, pCut ); + // return status (0 if okay; 1 if exceeded the limit) + return ++p->nNodeCuts == p->pParams->nKeepMax; +} + +/**Function************************************************************* + + Synopsis [Computes the cuts by merging cuts at two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode ) +{ + Cut_List_t Super, * pSuper = &Super; + Cut_Cut_t * pList, * pCut; + int clk; + // start the number of cuts at the node + p->nNodes++; + p->nNodeCuts = 0; + // prepare information for recording + if ( p->pParams->fRecord ) + { + Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node0) ); + Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node1) ); + } + // compute the cuts +clk = clock(); + Cut_ListStart( pSuper ); + Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, Cut_NodeReadCutsNew(p, Node0), Cut_NodeReadCutsNew(p, Node1), fTriv, TreeCode ); + pList = Cut_ListFinish( pSuper ); +p->timeMerge += clock() - clk; + // verify the result of cut computation +// Cut_CutListVerify( pList ); + // performing the recording + if ( p->pParams->fRecord ) + { + Vec_IntWriteEntry( p->vNodeStarts, Node, Vec_IntSize(p->vCutPairs) ); + Cut_ListForEachCut( pList, pCut ) + Vec_IntPush( p->vCutPairs, ((pCut->Num1 << 16) | pCut->Num0) ); + Vec_IntWriteEntry( p->vNodeCuts, Node, Vec_IntSize(p->vCutPairs) - Vec_IntEntry(p->vNodeStarts, Node) ); + } + // check if the node is over the list + if ( p->nNodeCuts == p->pParams->nKeepMax ) + p->nCutsLimit++; + // set the list at the node + Vec_PtrFillExtra( p->vCutsNew, Node + 1, NULL ); + assert( Cut_NodeReadCutsNew(p, Node) == NULL ); + ///// +// pList->pNext = NULL; + ///// + Cut_NodeWriteCutsNew( p, Node, pList ); + // filter the cuts +//clk = clock(); +// if ( p->pParams->fFilter ) +// Cut_CutFilter( p, pList0 ); +//p->timeFilter += clock() - clk; + // perform mapping of this node with these cuts +clk = clock(); + if ( p->pParams->fMap && !p->pParams->fSeq ) + { +// int Delay1, Delay2; +// Delay1 = Cut_NodeMapping( p, pList, Node, Node0, Node1 ); +// Delay2 = Cut_NodeMapping2( p, pList, Node, Node0, Node1 ); +// assert( Delay1 >= Delay2 ); + Cut_NodeMapping( p, pList, Node, Node0, Node1 ); + } +p->timeMap += clock() - clk; + return pList; +} + +/**Function************************************************************* + + Synopsis [Returns optimum delay mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ) +{ + Cut_Cut_t * pCut; + int DelayMin, DelayCur, i; + if ( pCuts == NULL ) + p->nDelayMin = -1; + if ( p->nDelayMin == -1 ) + return -1; + DelayMin = 1000000; + Cut_ListForEachCut( pCuts, pCut ) + { + if ( pCut->nLeaves == 1 ) + continue; + DelayCur = 0; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + if ( DelayCur < Vec_IntEntry(p->vDelays, pCut->pLeaves[i]) ) + DelayCur = Vec_IntEntry(p->vDelays, pCut->pLeaves[i]); + if ( DelayMin > DelayCur ) + DelayMin = DelayCur; + } + if ( DelayMin == 1000000 ) + { + p->nDelayMin = -1; + return -1; + } + DelayMin++; + Vec_IntWriteEntry( p->vDelays, Node, DelayMin ); + if ( p->nDelayMin < DelayMin ) + p->nDelayMin = DelayMin; + return DelayMin; +} + +/**Function************************************************************* + + Synopsis [Returns optimum delay mapping using the largest cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ) +{ + Cut_Cut_t * pCut0, * pCut1, * pCut; + int Delay0, Delay1, Delay; + // get the fanin cuts + Delay0 = Vec_IntEntry( p->vDelays2, Node0 ); + Delay1 = Vec_IntEntry( p->vDelays2, Node1 ); + pCut0 = (Delay0 == 0) ? Vec_PtrEntry( p->vCutsNew, Node0 ) : Vec_PtrEntry( p->vCutsMax, Node0 ); + pCut1 = (Delay1 == 0) ? Vec_PtrEntry( p->vCutsNew, Node1 ) : Vec_PtrEntry( p->vCutsMax, Node1 ); + if ( Delay0 == Delay1 ) + Delay = (Delay0 == 0) ? Delay0 + 1: Delay0; + else if ( Delay0 > Delay1 ) + { + Delay = Delay0; + pCut1 = Vec_PtrEntry( p->vCutsNew, Node1 ); + assert( pCut1->nLeaves == 1 ); + } + else // if ( Delay0 < Delay1 ) + { + Delay = Delay1; + pCut0 = Vec_PtrEntry( p->vCutsNew, Node0 ); + assert( pCut0->nLeaves == 1 ); + } + // merge the cuts + if ( pCut0->nLeaves < pCut1->nLeaves ) + pCut = Cut_CutMergeTwo( p, pCut1, pCut0 ); + else + pCut = Cut_CutMergeTwo( p, pCut0, pCut1 ); + if ( pCut == NULL ) + { + Delay++; + pCut = Cut_CutAlloc( p ); + pCut->nLeaves = 2; + pCut->pLeaves[0] = Node0 < Node1 ? Node0 : Node1; + pCut->pLeaves[1] = Node0 < Node1 ? Node1 : Node0; + } + assert( Delay > 0 ); + Vec_IntWriteEntry( p->vDelays2, Node, Delay ); + Vec_PtrWriteEntry( p->vCutsMax, Node, pCut ); + if ( p->nDelayMin < Delay ) + p->nDelayMin = Delay; + return Delay; +} + +/**Function************************************************************* + + Synopsis [Computes area after mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node ) +{ + Cut_Cut_t * pCut; + int i, Counter; + if ( p->vCutsMax == NULL ) + return 0; + pCut = Vec_PtrEntry( p->vCutsMax, Node ); + if ( pCut == NULL || pCut->nLeaves == 1 ) + return 0; + Counter = 0; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + Counter += Cut_ManMappingArea_rec( p, pCut->pLeaves[i] ); + Vec_PtrWriteEntry( p->vCutsMax, Node, NULL ); + return 1 + Counter; +} + + +/**Function************************************************************* + + Synopsis [Computes the cuts by merging cuts at two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode ) +{ + Cut_Cut_t * pStop0, * pStop1, * pTemp0, * pTemp1, * pStore0, * pStore1; + int i, nCutsOld, Limit; + // start with the elementary cut + if ( fTriv ) + { +// printf( "Creating trivial cut %d.\n", Node ); + pTemp0 = Cut_CutCreateTriv( p, Node ); + Cut_ListAdd( pSuper, pTemp0 ); + p->nNodeCuts++; + } + // get the cut lists of children + if ( pList0 == NULL || pList1 == NULL || (p->pParams->fLocal && TreeCode) ) + return; + + // remember the old number of cuts + nCutsOld = p->nCutsCur; + Limit = p->pParams->nVarsMax; + // get the simultation bit of the node + p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul); + // set temporary variables + p->fCompl0 = fCompl0; + p->fCompl1 = fCompl1; + // if tree cuts are computed, make sure only the unit cuts propagate over the DAG nodes + if ( TreeCode & 1 ) + { + assert( pList0->nLeaves == 1 ); + pStore0 = pList0->pNext; + pList0->pNext = NULL; + } + if ( TreeCode & 2 ) + { + assert( pList1->nLeaves == 1 ); + pStore1 = pList1->pNext; + pList1->pNext = NULL; + } + // find the point in the list where the max-var cuts begin + Cut_ListForEachCut( pList0, pStop0 ) + if ( pStop0->nLeaves == (unsigned)Limit ) + break; + Cut_ListForEachCut( pList1, pStop1 ) + if ( pStop1->nLeaves == (unsigned)Limit ) + break; + + // small by small + Cut_ListForEachCutStop( pList0, pTemp0, pStop0 ) + Cut_ListForEachCutStop( pList1, pTemp1, pStop1 ) + { + if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) + goto Quits; + } + // small by large + Cut_ListForEachCutStop( pList0, pTemp0, pStop0 ) + Cut_ListForEachCut( pStop1, pTemp1 ) + { + if ( (pTemp0->uSign & pTemp1->uSign) != pTemp0->uSign ) + continue; + if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) + goto Quits; + } + // small by large + Cut_ListForEachCutStop( pList1, pTemp1, pStop1 ) + Cut_ListForEachCut( pStop0, pTemp0 ) + { + if ( (pTemp0->uSign & pTemp1->uSign) != pTemp1->uSign ) + continue; + if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) + goto Quits; + } + // large by large + Cut_ListForEachCut( pStop0, pTemp0 ) + Cut_ListForEachCut( pStop1, pTemp1 ) + { + assert( pTemp0->nLeaves == (unsigned)Limit && pTemp1->nLeaves == (unsigned)Limit ); + if ( pTemp0->uSign != pTemp1->uSign ) + continue; + for ( i = 0; i < Limit; i++ ) + if ( pTemp0->pLeaves[i] != pTemp1->pLeaves[i] ) + break; + if ( i < Limit ) + continue; + if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) + goto Quits; + } + if ( p->nNodeCuts == 0 ) + p->nNodesNoCuts++; +Quits: + if ( TreeCode & 1 ) + pList0->pNext = pStore0; + if ( TreeCode & 2 ) + pList1->pNext = pStore1; +} + +/**Function************************************************************* + + Synopsis [Computes the cuts by unioning cuts at a choice node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ) +{ + Cut_List_t Super, * pSuper = &Super; + Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop; + int i, k, Node, Root, Limit = p->pParams->nVarsMax; + int clk = clock(); + + // start the new list + Cut_ListStart( pSuper ); + + // remember the root node to save the resulting cuts + Root = Vec_IntEntry( vNodes, 0 ); + p->nNodeCuts = 1; + + // collect small cuts first + Vec_PtrClear( p->vTemp ); + Vec_IntForEachEntry( vNodes, Node, i ) + { + // get the cuts of this node + pList = Cut_NodeReadCutsNew( p, Node ); + Cut_NodeWriteCutsNew( p, Node, NULL ); + assert( pList ); + // remember the starting point + pListStart = pList->pNext; + pList->pNext = NULL; + // save or recycle the elementary cut + if ( i == 0 ) + Cut_ListAdd( pSuper, pList ), pTop = pList; + else + Cut_CutRecycle( p, pList ); + // save all the cuts that are smaller than the limit + Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) + { + if ( pCut->nLeaves == (unsigned)Limit ) + { + Vec_PtrPush( p->vTemp, pCut ); + break; + } + // check containment + if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) + continue; + // set the complemented bit by comparing the first cut with the current cut + pCut->fCompl = pTop->fSimul ^ pCut->fSimul; + pListStart = pCut->pNext; + pCut->pNext = NULL; + // add to the list + Cut_ListAdd( pSuper, pCut ); + if ( ++p->nNodeCuts == p->pParams->nKeepMax ) + { + // recycle the rest of the cuts of this node + Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) + Cut_CutRecycle( p, pCut ); + // recycle all cuts of other nodes + Vec_IntForEachEntryStart( vNodes, Node, k, i+1 ) + Cut_NodeFreeCuts( p, Node ); + // recycle the saved cuts of other nodes + Vec_PtrForEachEntry( p->vTemp, pList, k ) + Cut_ListForEachCutSafe( pList, pCut, pCut2 ) + Cut_CutRecycle( p, pCut ); + goto finish; + } + } + } + // collect larger cuts next + Vec_PtrForEachEntry( p->vTemp, pList, i ) + { + Cut_ListForEachCutSafe( pList, pCut, pCut2 ) + { + // check containment + if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) + continue; + // set the complemented bit + pCut->fCompl = pTop->fSimul ^ pCut->fSimul; + pListStart = pCut->pNext; + pCut->pNext = NULL; + // add to the list + Cut_ListAdd( pSuper, pCut ); + if ( ++p->nNodeCuts == p->pParams->nKeepMax ) + { + // recycle the rest of the cuts + Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) + Cut_CutRecycle( p, pCut ); + // recycle the saved cuts of other nodes + Vec_PtrForEachEntryStart( p->vTemp, pList, k, i+1 ) + Cut_ListForEachCutSafe( pList, pCut, pCut2 ) + Cut_CutRecycle( p, pCut ); + goto finish; + } + } + } +finish : + // set the cuts at the node + assert( Cut_NodeReadCutsNew(p, Root) == NULL ); + pList = Cut_ListFinish( pSuper ); + Cut_NodeWriteCutsNew( p, Root, pList ); +p->timeUnion += clock() - clk; + // filter the cuts +//clk = clock(); +// if ( p->pParams->fFilter ) +// Cut_CutFilter( p, pList ); +//p->timeFilter += clock() - clk; + p->nNodes -= vNodes->nSize - 1; + return pList; +} + +/**Function************************************************************* + + Synopsis [Computes the cuts by unioning cuts at a choice node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst ) +{ + Cut_List_t Super, * pSuper = &Super; + Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop; + int i, k, Node, Root, Limit = p->pParams->nVarsMax; + int clk = clock(); + + // start the new list + Cut_ListStart( pSuper ); + + // remember the root node to save the resulting cuts + Root = Vec_IntEntry( vNodes, 0 ); + p->nNodeCuts = 1; + + // store the original lists for comparison + p->pCompareOld = Cut_NodeReadCutsOld( p, Root ); + p->pCompareNew = (CutSetNum >= 0)? Cut_NodeReadCutsNew( p, Root ) : NULL; + + // get the topmost cut + pTop = NULL; + if ( (pTop = Cut_NodeReadCutsOld( p, Root )) == NULL ) + pTop = Cut_NodeReadCutsNew( p, Root ); + assert( pTop != NULL ); + + // collect small cuts first + Vec_PtrClear( p->vTemp ); + Vec_IntForEachEntry( vNodes, Node, i ) + { + // get the cuts of this node + if ( i == 0 && CutSetNum >= 0 ) + { + pList = Cut_NodeReadCutsTemp( p, CutSetNum ); + Cut_NodeWriteCutsTemp( p, CutSetNum, NULL ); + } + else + { + pList = Cut_NodeReadCutsNew( p, Node ); + Cut_NodeWriteCutsNew( p, Node, NULL ); + } + if ( pList == NULL ) + continue; + + // process the cuts + if ( fFirst ) + { + // remember the starting point + pListStart = pList->pNext; + pList->pNext = NULL; + // save or recycle the elementary cut + if ( i == 0 ) + Cut_ListAdd( pSuper, pList ); + else + Cut_CutRecycle( p, pList ); + } + else + pListStart = pList; + + // save all the cuts that are smaller than the limit + Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) + { + if ( pCut->nLeaves == (unsigned)Limit ) + { + Vec_PtrPush( p->vTemp, pCut ); + break; + } + // check containment +// if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) +// continue; + if ( p->pParams->fFilter ) + { + if ( Cut_CutFilterOne(p, pSuper, pCut) ) + continue; + if ( p->pParams->fSeq ) + { + if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) + continue; + if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) + continue; + } + } + + // set the complemented bit by comparing the first cut with the current cut + pCut->fCompl = pTop->fSimul ^ pCut->fSimul; + pListStart = pCut->pNext; + pCut->pNext = NULL; + // add to the list + Cut_ListAdd( pSuper, pCut ); + if ( ++p->nNodeCuts == p->pParams->nKeepMax ) + { + // recycle the rest of the cuts of this node + Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) + Cut_CutRecycle( p, pCut ); + // recycle all cuts of other nodes + Vec_IntForEachEntryStart( vNodes, Node, k, i+1 ) + Cut_NodeFreeCuts( p, Node ); + // recycle the saved cuts of other nodes + Vec_PtrForEachEntry( p->vTemp, pList, k ) + Cut_ListForEachCutSafe( pList, pCut, pCut2 ) + Cut_CutRecycle( p, pCut ); + goto finish; + } + } + } + // collect larger cuts next + Vec_PtrForEachEntry( p->vTemp, pList, i ) + { + Cut_ListForEachCutSafe( pList, pCut, pCut2 ) + { + // check containment +// if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) +// continue; + if ( p->pParams->fFilter ) + { + if ( Cut_CutFilterOne(p, pSuper, pCut) ) + continue; + if ( p->pParams->fSeq ) + { + if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) + continue; + if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) + continue; + } + } + + // set the complemented bit + pCut->fCompl = pTop->fSimul ^ pCut->fSimul; + pListStart = pCut->pNext; + pCut->pNext = NULL; + // add to the list + Cut_ListAdd( pSuper, pCut ); + if ( ++p->nNodeCuts == p->pParams->nKeepMax ) + { + // recycle the rest of the cuts + Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) + Cut_CutRecycle( p, pCut ); + // recycle the saved cuts of other nodes + Vec_PtrForEachEntryStart( p->vTemp, pList, k, i+1 ) + Cut_ListForEachCutSafe( pList, pCut, pCut2 ) + Cut_CutRecycle( p, pCut ); + goto finish; + } + } + } +finish : + // set the cuts at the node + pList = Cut_ListFinish( pSuper ); + + // set the lists at the node +// assert( Cut_NodeReadCutsNew(p, Root) == NULL ); +// Cut_NodeWriteCutsNew( p, Root, pList ); + if ( CutSetNum >= 0 ) + { + assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL ); + Cut_NodeWriteCutsTemp( p, CutSetNum, pList ); + } + else + { + assert( Cut_NodeReadCutsNew(p, Root) == NULL ); + Cut_NodeWriteCutsNew( p, Root, pList ); + } + +p->timeUnion += clock() - clk; + // filter the cuts +//clk = clock(); +// if ( p->pParams->fFilter ) +// Cut_CutFilter( p, pList ); +//p->timeFilter += clock() - clk; +// if ( fFirst ) +// p->nNodes -= vNodes->nSize - 1; + return pList; +} + + +/**Function************************************************************* + + Synopsis [Verifies that the list contains only non-dominated cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_CutListVerify( Cut_Cut_t * pList ) +{ + Cut_Cut_t * pCut, * pDom; + Cut_ListForEachCut( pList, pCut ) + { + Cut_ListForEachCutStop( pList, pDom, pCut ) + { + if ( Cut_CutCheckDominance( pDom, pCut ) ) + { + int x = 0; + printf( "******************* These are contained cuts:\n" ); + Cut_CutPrint( pDom, 1 ); + Cut_CutPrint( pDom, 1 ); + + return 0; + } + } + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/cut/cutOracle.c b/abc70930/src/opt/cut/cutOracle.c new file mode 100644 index 00000000..3eb4462b --- /dev/null +++ b/abc70930/src/opt/cut/cutOracle.c @@ -0,0 +1,428 @@ +/**CFile**************************************************************** + + FileName [cutOracle.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [Procedures to compute cuts for a node using the oracle.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutOracle.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Cut_OracleStruct_t_ +{ + // cut comptupatation parameters + Cut_Params_t * pParams; + Vec_Int_t * vFanCounts; + int fSimul; + // storage for cuts + Vec_Ptr_t * vCutsNew; + Vec_Ptr_t * vCuts0; + Vec_Ptr_t * vCuts1; + // oracle info + Vec_Int_t * vNodeCuts; + Vec_Int_t * vNodeStarts; + Vec_Int_t * vCutPairs; + // memory management + Extra_MmFixed_t * pMmCuts; + int EntrySize; + int nTruthWords; + // stats + int timeTotal; + int nCuts; + int nCutsTriv; +}; + +static Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p ); +static Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node ); +static Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the cut oracle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan ) +{ + Cut_Oracle_t * p; + int clk = clock(); + + assert( pMan->pParams->nVarsMax >= 3 && pMan->pParams->nVarsMax <= CUT_SIZE_MAX ); + assert( pMan->pParams->fRecord ); + + p = ALLOC( Cut_Oracle_t, 1 ); + memset( p, 0, sizeof(Cut_Oracle_t) ); + + // set and correct parameters + p->pParams = pMan->pParams; + + // transfer the recording info + p->vNodeCuts = pMan->vNodeCuts; pMan->vNodeCuts = NULL; + p->vNodeStarts = pMan->vNodeStarts; pMan->vNodeStarts = NULL; + p->vCutPairs = pMan->vCutPairs; pMan->vCutPairs = NULL; + + // prepare storage for cuts + p->vCutsNew = Vec_PtrAlloc( p->pParams->nIdsMax ); + Vec_PtrFill( p->vCutsNew, p->pParams->nIdsMax, NULL ); + p->vCuts0 = Vec_PtrAlloc( 100 ); + p->vCuts1 = Vec_PtrAlloc( 100 ); + + // entry size + p->EntrySize = sizeof(Cut_Cut_t) + p->pParams->nVarsMax * sizeof(int); + if ( p->pParams->fTruth ) + { + if ( p->pParams->nVarsMax > 8 ) + { + p->pParams->fTruth = 0; + printf( "Skipping computation of truth table for more than 8 inputs.\n" ); + } + else + { + p->nTruthWords = Cut_TruthWords( p->pParams->nVarsMax ); + p->EntrySize += p->nTruthWords * sizeof(unsigned); + } + } + // memory for cuts + p->pMmCuts = Extra_MmFixedStart( p->EntrySize ); + return p; +} +/**Function************************************************************* + + Synopsis [Stop the cut oracle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_OracleStop( Cut_Oracle_t * p ) +{ + Cut_Cut_t * pCut; + int i; + +// if ( p->pParams->fVerbose ) + { + printf( "Cut computation statistics with oracle:\n" ); + printf( "Current cuts = %8d. (Trivial = %d.)\n", p->nCuts-p->nCutsTriv, p->nCutsTriv ); + PRT( "Total time ", p->timeTotal ); + } + + Vec_PtrForEachEntry( p->vCutsNew, pCut, i ) + if ( pCut != NULL ) + { + int k = 0; + } + if ( p->vCuts0 ) Vec_PtrFree( p->vCuts0 ); + if ( p->vCuts1 ) Vec_PtrFree( p->vCuts1 ); + if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew ); + if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts ); + + if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts ); + if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts ); + if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs ); + + Extra_MmFixedStop( p->pMmCuts ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts ) +{ + p->vFanCounts = vFanCounts; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_OracleReadDrop( Cut_Oracle_t * p ) +{ + return p->pParams->fDrop; +} + +/**Function************************************************************* + + Synopsis [Sets the trivial cut for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node ) +{ + assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL ); + Vec_PtrWriteEntry( p->vCutsNew, Node, Cut_CutTriv(p, Node) ); +} + + + +/**Function************************************************************* + + Synopsis [Allocates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p ) +{ + Cut_Cut_t * pCut; + // cut allocation + pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts ); + memset( pCut, 0, sizeof(Cut_Cut_t) ); + pCut->nVarsMax = p->pParams->nVarsMax; + pCut->fSimul = p->fSimul; + p->nCuts++; + return pCut; +} + +/**Function************************************************************* + + Synopsis [Creates the trivial cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node ) +{ + Cut_Cut_t * pCut; + pCut = Cut_CutStart( p ); + pCut->nLeaves = 1; + pCut->pLeaves[0] = Node; + if ( p->pParams->fTruth ) + { + unsigned * pTruth = Cut_CutReadTruth(pCut); + int i; + for ( i = 0; i < p->nTruthWords; i++ ) + pTruth[i] = 0xAAAAAAAA; + } + p->nCutsTriv++; + return pCut; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) +{ + Cut_Cut_t * pCut; + int Limit, i, k, c; + // create the leaves of the new cut + pCut = Cut_CutStart( p ); + Limit = p->pParams->nVarsMax; + for ( i = k = c = 0; c < Limit; c++ ) + { + if ( k == (int)pCut1->nLeaves ) + { + if ( i == (int)pCut0->nLeaves ) + { + pCut->nLeaves = c; + return pCut; + } + pCut->pLeaves[c] = pCut0->pLeaves[i++]; + continue; + } + if ( i == (int)pCut0->nLeaves ) + { + if ( k == (int)pCut1->nLeaves ) + { + pCut->nLeaves = c; + return pCut; + } + pCut->pLeaves[c] = pCut1->pLeaves[k++]; + continue; + } + if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] ) + { + pCut->pLeaves[c] = pCut0->pLeaves[i++]; + continue; + } + if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] ) + { + pCut->pLeaves[c] = pCut1->pLeaves[k++]; + continue; + } + pCut->pLeaves[c] = pCut0->pLeaves[i++]; + k++; + } + assert( i == (int)pCut0->nLeaves && k == (int)pCut1->nLeaves ); + pCut->nLeaves = c; + return pCut; +} + +/**Function************************************************************* + + Synopsis [Reconstruct the cuts of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 ) +{ + Cut_Cut_t * pList = NULL, ** ppTail = &pList; + Cut_Cut_t * pCut, * pCut0, * pCut1, * pList0, * pList1; + int iCutStart, nCuts, i, Entry; + int clk = clock(); + + // get the cuts of the children + pList0 = Vec_PtrEntry( p->vCutsNew, Node0 ); + pList1 = Vec_PtrEntry( p->vCutsNew, Node1 ); + assert( pList0 && pList1 ); + + // get the complemented attribute of the cut + p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul); + + // collect the cuts + Vec_PtrClear( p->vCuts0 ); + Cut_ListForEachCut( pList0, pCut ) + Vec_PtrPush( p->vCuts0, pCut ); + Vec_PtrClear( p->vCuts1 ); + Cut_ListForEachCut( pList1, pCut ) + Vec_PtrPush( p->vCuts1, pCut ); + + // get the first and last cuts of this node + nCuts = Vec_IntEntry(p->vNodeCuts, Node); + iCutStart = Vec_IntEntry(p->vNodeStarts, Node); + + // create trivial cut + assert( Vec_IntEntry(p->vCutPairs, iCutStart) == 0 ); + pCut = Cut_CutTriv( p, Node ); + *ppTail = pCut; + ppTail = &pCut->pNext; + // create other cuts + for ( i = 1; i < nCuts; i++ ) + { + Entry = Vec_IntEntry( p->vCutPairs, iCutStart + i ); + pCut0 = Vec_PtrEntry( p->vCuts0, Entry & 0xFFFF ); + pCut1 = Vec_PtrEntry( p->vCuts1, Entry >> 16 ); + pCut = Cut_CutMerge( p, pCut0, pCut1 ); + *ppTail = pCut; + ppTail = &pCut->pNext; + // compute the truth table + if ( p->pParams->fTruth ) + Cut_TruthComputeOld( pCut, pCut0, pCut1, fCompl0, fCompl1 ); + } + *ppTail = NULL; + + // write the new cut + assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL ); + Vec_PtrWriteEntry( p->vCutsNew, Node, pList ); +p->timeTotal += clock() - clk; + return pList; +} + +/**Function************************************************************* + + Synopsis [Deallocates the cuts at the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_OracleFreeCuts( Cut_Oracle_t * p, int Node ) +{ + Cut_Cut_t * pList, * pCut, * pCut2; + pList = Vec_PtrEntry( p->vCutsNew, Node ); + if ( pList == NULL ) + return; + Cut_ListForEachCutSafe( pList, pCut, pCut2 ) + Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut ); + Vec_PtrWriteEntry( p->vCutsNew, Node, pList ); +} + +/**Function************************************************************* + + Synopsis [Consider dropping cuts if they are useless by now.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node ) +{ + int nFanouts; + assert( p->vFanCounts ); + nFanouts = Vec_IntEntry( p->vFanCounts, Node ); + assert( nFanouts > 0 ); + if ( --nFanouts == 0 ) + Cut_OracleFreeCuts( p, Node ); + Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/cut/cutPre22.c b/abc70930/src/opt/cut/cutPre22.c new file mode 100644 index 00000000..5cb87a9c --- /dev/null +++ b/abc70930/src/opt/cut/cutPre22.c @@ -0,0 +1,988 @@ +/**CFile**************************************************************** + + FileName [cutPre22.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Precomputes truth tables for the 2x2 macro cell.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutPre22.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define CUT_CELL_MVAR 9 + +typedef struct Cut_Cell_t_ Cut_Cell_t; +typedef struct Cut_CMan_t_ Cut_CMan_t; + +struct Cut_Cell_t_ +{ + Cut_Cell_t * pNext; // pointer to the next cell in the table + Cut_Cell_t * pNextVar; // pointer to the next cell of this support size + Cut_Cell_t * pParent; // pointer to the cell used to derive this one + int nUsed; // the number of times the cell is used + char Box[4]; // functions in the boxes + unsigned nVars : 4; // the number of variables + unsigned CrossBar0 : 4; // the variable set equal + unsigned CrossBar1 : 4; // the variable set equal + unsigned CrossBarPhase : 2; // the phase of the cross bar (0, 1, or 2) + unsigned CanonPhase : 18; // the canonical phase + char CanonPerm[CUT_CELL_MVAR+3]; // semicanonical permutation + short Store[2*CUT_CELL_MVAR]; // minterm counts in the cofactors + unsigned uTruth[1<<(CUT_CELL_MVAR-5)]; // the current truth table +}; + +struct Cut_CMan_t_ +{ + // storage for canonical cells + Extra_MmFixed_t * pMem; + st_table * tTable; + Cut_Cell_t * pSameVar[CUT_CELL_MVAR+1]; + // elementary truth tables + unsigned uInputs[CUT_CELL_MVAR][1<<(CUT_CELL_MVAR-5)]; + // temporary truth tables + unsigned uTemp1[22][1<<(CUT_CELL_MVAR-5)]; + unsigned uTemp2[22][1<<(CUT_CELL_MVAR-5)]; + unsigned uTemp3[22][1<<(CUT_CELL_MVAR-5)]; + unsigned uFinal[1<<(CUT_CELL_MVAR-5)]; + unsigned puAux[1<<(CUT_CELL_MVAR-5)]; + // statistical variables + int nTotal; + int nGood; + int nVarCounts[CUT_CELL_MVAR+1]; + int nSymGroups[CUT_CELL_MVAR+1]; + int nSymGroupsE[CUT_CELL_MVAR+1]; + int timeCanon; + int timeSupp; + int timeTable; + int nCellFound; + int nCellNotFound; +}; + +// NP-classes of functions of 3 variables (22) +static char * s_NP3[22] = { + " 0\n", // 00 const 0 // 0 vars + " 1\n", // 01 const 1 // 0 vars + "1 1\n", // 02 a // 1 vars + "11 1\n", // 03 ab // 2 vars + "11 0\n", // 04 (ab)' // 2 vars + "10 1\n01 1\n", // 05 a<+>b // 2 vars + "111 1\n", // 06 0s abc // 3 vars + "111 0\n", // 07 (abc)' // + "11- 1\n1-1 1\n", // 08 1p a(b+c) // + "11- 0\n1-1 0\n", // 09 (a(b+c))' // + "111 1\n100 1\n010 1\n001 1\n", // 10 2s a<+>b<+>c // + "10- 0\n1-0 0\n011 0\n", // 11 3p a<+>bc // + "101 1\n110 1\n", // 12 4p a(b<+>c) // + "101 0\n110 0\n", // 13 (a(b<+>c))' // + "11- 1\n1-1 1\n-11 1\n", // 14 5s ab+bc+ac // + "111 1\n000 1\n", // 15 6s abc+a'b'c' // + "111 0\n000 0\n", // 16 (abc+a'b'c')' // + "11- 1\n-11 1\n0-1 1\n", // 17 7 ab+bc+a'c // + "011 1\n101 1\n110 1\n", // 18 8s a'bc+ab'c+abc' // + "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' // + "100 1\n-11 1\n", // 20 9p ab'c'+bc // + "100 0\n-11 0\n" // 21 (ab'c'+bc)' // +}; + +// NP-classes of functions of 3 variables (22) +static char * s_NP3Names[22] = { + " const 0 ", + " const 1 ", + " a ", + " ab ", + " (ab)' ", + " a<+>b ", + "0s abc ", + " (abc)' ", + "1p a(b+c) ", + " (a(b+c))' ", + "2s a<+>b<+>c ", + "3p a<+>bc ", + "4p a(b<+>c) ", + " (a(b<+>c))' ", + "5s ab+bc+ac ", + "6s abc+a'b'c' ", + " (abc+a'b'c')' ", + "7 ab+bc+a'c ", + "8s a'bc+ab'c+abc' ", + " (a'bc+ab'c+abc')' ", + "9p ab'c'+bc ", + " (ab'c'+bc)' " +}; + +// the number of variables in each function +static int s_NP3VarNums[22] = { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; + +// NPN classes of functions of exactly 3 inputs (10) +static int s_NPNe3[10] = { 6, 8, 10, 11, 12, 14, 15, 17, 18, 20 }; + +// NPN classes of functions of exactly 3 inputs that are symmetric (5) +static int s_NPNe3s[10] = { 6, 10, 14, 15, 18 }; + +// NPN classes of functions of exactly 3 inputs (4) +static int s_NPNe3p[10] = { 8, 11, 12, 20 }; + +static Cut_CMan_t * Cut_CManStart(); +static void Cut_CManStop( Cut_CMan_t * p ); +static void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type ); +static void Cut_CellCanonicize( Cut_CMan_t * p, Cut_Cell_t * pCell ); +static int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell ); +static void Cut_CellSuppMin( Cut_Cell_t * pCell ); +static void Cut_CellCrossBar( Cut_Cell_t * pCell ); + + +static Cut_CMan_t * s_pCMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start the precomputation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellLoad() +{ + FILE * pFile; + char * pFileName = "cells22_daomap_iwls.txt"; + char pString[1000]; + Cut_CMan_t * p; + Cut_Cell_t * pCell; + int Length; //, i; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\".\n", pFileName ); + return; + } + // start the manager + p = Cut_CManStart(); + // load truth tables + while ( fgets(pString, 1000, pFile) ) + { + Length = strlen(pString); + pString[Length--] = 0; + if ( Length == 0 ) + continue; + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = Extra_Base2Log(Length*4); + pCell->nUsed = 1; +// Extra_TruthCopy( pCell->uTruth, pTruth, nVars ); + Extra_ReadHexadecimal( pCell->uTruth, pString, pCell->nVars ); + Cut_CellSuppMin( pCell ); +/* + // set the elementary permutation + for ( i = 0; i < (int)pCell->nVars; i++ ) + pCell->CanonPerm[i] = i; + // canonicize + pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); +*/ + // add to the table + p->nTotal++; + +// Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); printf( "\n" ); +// if ( p->nTotal == 500 ) +// break; + + if ( !Cut_CellTableLookup( p, pCell ) ) // new cell + p->nGood++; + } + printf( "Read %d cells from file \"%s\". Added %d cells to the table.\n", p->nTotal, pFileName, p->nGood ); + fclose( pFile ); +// return p; +} + +/**Function************************************************************* + + Synopsis [Precomputes truth tables for the 2x2 macro cell.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellPrecompute() +{ + Cut_CMan_t * p; + Cut_Cell_t * pCell, * pTemp; + int i1, i2, i3, i, j, k, c, clk = clock(), clk2 = clock(); + + p = Cut_CManStart(); + + // precompute truth tables + for ( i = 0; i < 22; i++ ) + Cut_CellTruthElem( p->uInputs[0], p->uInputs[1], p->uInputs[2], p->uTemp1[i], 9, i ); + for ( i = 0; i < 22; i++ ) + Cut_CellTruthElem( p->uInputs[3], p->uInputs[4], p->uInputs[5], p->uTemp2[i], 9, i ); + for ( i = 0; i < 22; i++ ) + Cut_CellTruthElem( p->uInputs[6], p->uInputs[7], p->uInputs[8], p->uTemp3[i], 9, i ); +/* + if ( k == 8 && ((i1 == 6 && i2 == 14 && i3 == 20) || (i1 == 20 && i2 == 6 && i3 == 14)) ) + { + Extra_PrintBinary( stdout, &pCell->CanonPhase, pCell->nVars+1 ); printf( " : " ); + for ( i = 0; i < pCell->nVars; i++ ) + printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); + Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); + printf( "\n" ); + } +*/ +/* + // go through symmetric roots + for ( k = 0; k < 5; k++ ) + for ( i1 = 0; i1 < 22; i1++ ) + for ( i2 = i1; i2 < 22; i2++ ) + for ( i3 = i2; i3 < 22; i3++ ) + { + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = 9; + pCell->Box[0] = s_NPNe3s[k]; + pCell->Box[1] = i1; + pCell->Box[2] = i2; + pCell->Box[3] = i3; + // fill in the truth table + Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3s[k] ); + // canonicize + Cut_CellCanonicize( pCell ); + + // add to the table + p->nTotal++; + if ( Cut_CellTableLookup( p, pCell ) ) // already exists + Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); + else + p->nGood++; + } + + // go through partially symmetric roots + for ( k = 0; k < 4; k++ ) + for ( i1 = 0; i1 < 22; i1++ ) + for ( i2 = 0; i2 < 22; i2++ ) + for ( i3 = i2; i3 < 22; i3++ ) + { + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = 9; + pCell->Box[0] = s_NPNe3p[k]; + pCell->Box[1] = i1; + pCell->Box[2] = i2; + pCell->Box[3] = i3; + // fill in the truth table + Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3p[k] ); + // canonicize + Cut_CellCanonicize( pCell ); + + // add to the table + p->nTotal++; + if ( Cut_CellTableLookup( p, pCell ) ) // already exists + Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); + else + p->nGood++; + } + + // go through non-symmetric functions + for ( i1 = 0; i1 < 22; i1++ ) + for ( i2 = 0; i2 < 22; i2++ ) + for ( i3 = 0; i3 < 22; i3++ ) + { + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = 9; + pCell->Box[0] = 17; + pCell->Box[1] = i1; + pCell->Box[2] = i2; + pCell->Box[3] = i3; + // fill in the truth table + Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, 17 ); + // canonicize + Cut_CellCanonicize( pCell ); + + // add to the table + p->nTotal++; + if ( Cut_CellTableLookup( p, pCell ) ) // already exists + Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); + else + p->nGood++; + } +*/ + + // go through non-symmetric functions + for ( k = 0; k < 10; k++ ) + for ( i1 = 0; i1 < 22; i1++ ) + for ( i2 = 0; i2 < 22; i2++ ) + for ( i3 = 0; i3 < 22; i3++ ) + { + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = 9; + pCell->Box[0] = s_NPNe3[k]; + pCell->Box[1] = i1; + pCell->Box[2] = i2; + pCell->Box[3] = i3; + // set the elementary permutation + for ( i = 0; i < (int)pCell->nVars; i++ ) + pCell->CanonPerm[i] = i; + // fill in the truth table + Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3[k] ); + // minimize the support + Cut_CellSuppMin( pCell ); + + // canonicize + pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); + + // add to the table + p->nTotal++; + if ( Cut_CellTableLookup( p, pCell ) ) // already exists + Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); + else + { + p->nGood++; + p->nVarCounts[pCell->nVars]++; + + if ( pCell->nVars ) + for ( i = 0; i < (int)pCell->nVars-1; i++ ) + { + if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric + continue; + // i and i+1 can be symmetric + // find the end of this group + for ( j = i+1; j < (int)pCell->nVars; j++ ) + if ( pCell->Store[2*i] != pCell->Store[2*j] ) + break; + + if ( pCell->Store[2*i] == pCell->Store[2*i+1] ) + p->nSymGroupsE[j-i]++; + else + p->nSymGroups[j-i]++; + i = j - 1; + } +/* + if ( pCell->nVars == 3 ) + { + Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" ); + for ( i = 0; i < (int)pCell->nVars; i++ ) + printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); + printf( "\n" ); + } +*/ + } + } + + printf( "BASIC: Total = %d. Good = %d. Entry = %d. ", p->nTotal, p->nGood, sizeof(Cut_Cell_t) ); + PRT( "Time", clock() - clk ); + printf( "Cells: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nVarCounts[i] ); + printf( "\nDiffs: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nSymGroups[i] ); + printf( "\nEquals: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nSymGroupsE[i] ); + printf( "\n" ); + + // continue adding new cells using support + for ( k = CUT_CELL_MVAR; k > 3; k-- ) + { + for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) + for ( i1 = 0; i1 < k; i1++ ) + for ( i2 = i1+1; i2 < k; i2++ ) + for ( c = 0; c < 3; c++ ) + { + // derive the cell + pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = pTemp->nVars; + pCell->pParent = pTemp; + // set the elementary permutation + for ( i = 0; i < (int)pCell->nVars; i++ ) + pCell->CanonPerm[i] = i; + // fill in the truth table + Extra_TruthCopy( pCell->uTruth, pTemp->uTruth, pTemp->nVars ); + // create the cross-bar + pCell->CrossBar0 = i1; + pCell->CrossBar1 = i2; + pCell->CrossBarPhase = c; + Cut_CellCrossBar( pCell ); + // minimize the support +//clk2 = clock(); + Cut_CellSuppMin( pCell ); +//p->timeSupp += clock() - clk2; + // canonicize +//clk2 = clock(); + pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); +//p->timeCanon += clock() - clk2; + + // add to the table +//clk2 = clock(); + p->nTotal++; + if ( Cut_CellTableLookup( p, pCell ) ) // already exists + Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); + else + { + p->nGood++; + p->nVarCounts[pCell->nVars]++; + + for ( i = 0; i < (int)pCell->nVars-1; i++ ) + { + if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric + continue; + // i and i+1 can be symmetric + // find the end of this group + for ( j = i+1; j < (int)pCell->nVars; j++ ) + if ( pCell->Store[2*i] != pCell->Store[2*j] ) + break; + + if ( pCell->Store[2*i] == pCell->Store[2*i+1] ) + p->nSymGroupsE[j-i]++; + else + p->nSymGroups[j-i]++; + i = j - 1; + } +/* + if ( pCell->nVars == 3 ) + { + Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" ); + for ( i = 0; i < (int)pCell->nVars; i++ ) + printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); + printf( "\n" ); + } +*/ + } +//p->timeTable += clock() - clk2; + } + + printf( "VAR %d: Total = %d. Good = %d. Entry = %d. ", k, p->nTotal, p->nGood, sizeof(Cut_Cell_t) ); + PRT( "Time", clock() - clk ); + printf( "Cells: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nVarCounts[i] ); + printf( "\nDiffs: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nSymGroups[i] ); + printf( "\nEquals: " ); + for ( i = 0; i <= 9; i++ ) + printf( "%d=%d ", i, p->nSymGroupsE[i] ); + printf( "\n" ); + } +// printf( "\n" ); + PRT( "Supp ", p->timeSupp ); + PRT( "Canon", p->timeCanon ); + PRT( "Table", p->timeTable ); +// Cut_CManStop( p ); +} + +/**Function************************************************************* + + Synopsis [Check the table.] + + Description [Returns 1 if such a truth table already exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell ) +{ + Cut_Cell_t ** pSlot, * pTemp; + unsigned Hash; + Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum( pCell->nVars ) ); + if ( !st_find_or_add( p->tTable, (char *)Hash, (char ***)&pSlot ) ) + *pSlot = NULL; + for ( pTemp = *pSlot; pTemp; pTemp = pTemp->pNext ) + { + if ( pTemp->nVars != pCell->nVars ) + continue; + if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) ) + return 1; + } + // the entry is new + pCell->pNext = *pSlot; + *pSlot = pCell; + // add it to the variable support list + pCell->pNextVar = p->pSameVar[pCell->nVars]; + p->pSameVar[pCell->nVars] = pCell; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellSuppMin( Cut_Cell_t * pCell ) +{ + static unsigned uTemp[1<<(CUT_CELL_MVAR-5)]; + unsigned * pIn, * pOut, * pTemp; + int i, k, Counter, Temp; + + // go backward through the support variables and remove redundant + for ( k = pCell->nVars - 1; k >= 0; k-- ) + if ( !Extra_TruthVarInSupport(pCell->uTruth, pCell->nVars, k) ) + { + // shift all the variables above this one + Counter = 0; + pIn = pCell->uTruth; pOut = uTemp; + for ( i = k; i < (int)pCell->nVars - 1; i++ ) + { + Extra_TruthSwapAdjacentVars( pOut, pIn, pCell->nVars, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + // swap the support vars + Temp = pCell->CanonPerm[i]; + pCell->CanonPerm[i] = pCell->CanonPerm[i+1]; + pCell->CanonPerm[i+1] = Temp; + Counter++; + } + // return the function back into its place + if ( Counter & 1 ) + Extra_TruthCopy( pOut, pIn, pCell->nVars ); + // remove one variable + pCell->nVars--; +// Extra_PrintBinary( stdout, pCell->uTruth, (1<nVars) ); printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellCrossBar( Cut_Cell_t * pCell ) +{ + static unsigned uTemp0[1<<(CUT_CELL_MVAR-5)]; + static unsigned uTemp1[1<<(CUT_CELL_MVAR-5)]; + Extra_TruthCopy( uTemp0, pCell->uTruth, pCell->nVars ); + Extra_TruthCopy( uTemp1, pCell->uTruth, pCell->nVars ); + if ( pCell->CanonPhase == 0 ) + { + Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 ); + Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 ); + } + else if ( pCell->CanonPhase == 1 ) + { + Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 ); + Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 ); + } + else if ( pCell->CanonPhase == 2 ) + { + Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar1 ); + Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 ); + Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar1 ); + } + else assert( 0 ); + Extra_TruthMux( pCell->uTruth, uTemp0, uTemp1, pCell->nVars, pCell->CrossBar0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type ) +{ + int nWords = Extra_TruthWordNum( nVars ); + int i; + + assert( Type < 22 ); + switch ( Type ) + { + // " 0\n", // 00 const 0 + case 0: + for ( i = 0; i < nWords; i++ ) + pOut[i] = 0; + return; + // " 1\n", // 01 const 1 + case 1: + for ( i = 0; i < nWords; i++ ) + pOut[i] = 0xFFFFFFFF; + return; + // "1 1\n", // 02 a + case 2: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i]; + return; + // "11 1\n", // 03 ab + case 3: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] & InB[i]; + return; + // "11 0\n", // 04 (ab)' + case 4: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~(InA[i] & InB[i]); + return; + // "10 1\n01 1\n", // 05 a<+>b + case 5: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] ^ InB[i]; + return; + // "111 1\n", // 06 + abc + case 6: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] & InB[i] & InC[i]; + return; + // "111 0\n", // 07 (abc)' + case 7: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~(InA[i] & InB[i] & InC[i]); + return; + // "11- 1\n1-1 1\n", // 08 + a(b+c) + case 8: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] & (InB[i] | InC[i]); + return; + // "11- 0\n1-1 0\n", // 09 (a(b+c))' + case 9: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~(InA[i] & (InB[i] | InC[i])); + return; + // "111 1\n100 1\n010 1\n001 1\n", // 10 + a<+>b<+>c + case 10: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] ^ InB[i] ^ InC[i]; + return; + // "10- 0\n1-0 0\n011 0\n", // 11 + a<+>bc + case 11: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] ^ (InB[i] & InC[i]); + return; + // "101 1\n110 1\n", // 12 + a(b<+>c) + case 12: + for ( i = 0; i < nWords; i++ ) + pOut[i] = InA[i] & (InB[i] ^ InC[i]); + return; + // "101 0\n110 0\n", // 13 (a(b<+>c))' + case 13: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~(InA[i] & (InB[i] ^ InC[i])); + return; + // "11- 1\n1-1 1\n-11 1\n", // 14 + ab+bc+ac + case 14: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (InA[i] & InC[i]); + return; + // "111 1\n000 1\n", // 15 + abc+a'b'c' + case 15: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]); + return; + // "111 0\n000 0\n", // 16 (abc+a'b'c')' + case 16: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~((InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i])); + return; + // "11- 1\n-11 1\n0-1 1\n", // 17 + ab+bc+a'c + case 17: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (~InA[i] & InC[i]); + return; + // "011 1\n101 1\n110 1\n", // 18 + a'bc+ab'c+abc' + case 18: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]); + return; + // "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' + case 19: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~((~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i])); + return; + // "100 1\n-11 1\n", // 20 + ab'c'+bc + case 20: + for ( i = 0; i < nWords; i++ ) + pOut[i] = (InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]); + return; + // "100 0\n-11 0\n" // 21 (ab'c'+bc)' + case 21: + for ( i = 0; i < nWords; i++ ) + pOut[i] = ~((InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i])); + return; + } +} + + +/**Function************************************************************* + + Synopsis [Start the precomputation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cut_CMan_t * Cut_CManStart() +{ + Cut_CMan_t * p; + int i, k; + // start the manager + assert( sizeof(unsigned) == 4 ); + p = ALLOC( Cut_CMan_t, 1 ); + memset( p, 0, sizeof(Cut_CMan_t) ); + // start the table and the memory manager + p->tTable = st_init_table(st_ptrcmp,st_ptrhash); + p->pMem = Extra_MmFixedStart( sizeof(Cut_Cell_t) ); + // set elementary truth tables + for ( k = 0; k < CUT_CELL_MVAR; k++ ) + for ( i = 0; i < (1<uInputs[k][i>>5] |= (1 << (i&31)); + s_pCMan = p; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CManStop( Cut_CMan_t * p ) +{ + st_free_table( p->tTable ); + Extra_MmFixedStop( p->pMem ); + free( p ); +} +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_CellIsRunning() +{ + return s_pCMan != NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_CellDumpToFile() +{ + FILE * pFile; + Cut_CMan_t * p = s_pCMan; + Cut_Cell_t * pTemp; + char * pFileName = "celllib22.txt"; + int NumUsed[10][5] = {{0}}; + int BoxUsed[22][5] = {{0}}; + int i, k, Counter; + int clk = clock(); + + if ( p == NULL ) + { + printf( "Cut_CellDumpToFile: Cell manager is not defined.\n" ); + return; + } + + // count the number of cells used + for ( k = CUT_CELL_MVAR; k >= 0; k-- ) + { + for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) + { + if ( pTemp->nUsed == 0 ) + NumUsed[k][0]++; + else if ( pTemp->nUsed < 10 ) + NumUsed[k][1]++; + else if ( pTemp->nUsed < 100 ) + NumUsed[k][2]++; + else if ( pTemp->nUsed < 1000 ) + NumUsed[k][3]++; + else + NumUsed[k][4]++; + + for ( i = 0; i < 4; i++ ) + if ( pTemp->nUsed == 0 ) + BoxUsed[ pTemp->Box[i] ][0]++; + else if ( pTemp->nUsed < 10 ) + BoxUsed[ pTemp->Box[i] ][1]++; + else if ( pTemp->nUsed < 100 ) + BoxUsed[ pTemp->Box[i] ][2]++; + else if ( pTemp->nUsed < 1000 ) + BoxUsed[ pTemp->Box[i] ][3]++; + else + BoxUsed[ pTemp->Box[i] ][4]++; + } + } + + printf( "Functions found = %10d. Functions not found = %10d.\n", p->nCellFound, p->nCellNotFound ); + for ( k = 0; k <= CUT_CELL_MVAR; k++ ) + { + printf( "%3d : ", k ); + for ( i = 0; i < 5; i++ ) + printf( "%8d ", NumUsed[k][i] ); + printf( "\n" ); + } + printf( "Box usage:\n" ); + for ( k = 0; k < 22; k++ ) + { + printf( "%3d : ", k ); + for ( i = 0; i < 5; i++ ) + printf( "%8d ", BoxUsed[k][i] ); + printf( " %s", s_NP3Names[k] ); + printf( "\n" ); + } + + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + printf( "Cut_CellDumpToFile: Cannout open output file.\n" ); + return; + } + + Counter = 0; + for ( k = 0; k <= CUT_CELL_MVAR; k++ ) + { + for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) + if ( pTemp->nUsed > 0 ) + { + Extra_PrintHexadecimal( pFile, pTemp->uTruth, (k <= 5? 5 : k) ); + fprintf( pFile, "\n" ); + Counter++; + } + fprintf( pFile, "\n" ); + } + fclose( pFile ); + + printf( "Library composed of %d functions is written into file \"%s\". ", Counter, pFileName ); + + PRT( "Time", clock() - clk ); +} + + +/**Function************************************************************* + + Synopsis [Looks up if the given function exists in the hash table.] + + Description [If the function exists, returns 1, meaning that it can be + implemented using two levels of 3-input LUTs. If the function does not + exist, return 0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_CellTruthLookup( unsigned * pTruth, int nVars ) +{ + Cut_CMan_t * p = s_pCMan; + Cut_Cell_t * pTemp; + Cut_Cell_t Cell, * pCell = &Cell; + unsigned Hash; + int i; + + // cell manager is not defined + if ( p == NULL ) + { + printf( "Cut_CellTruthLookup: Cell manager is not defined.\n" ); + return 0; + } + + // canonicize + memset( pCell, 0, sizeof(Cut_Cell_t) ); + pCell->nVars = nVars; + Extra_TruthCopy( pCell->uTruth, pTruth, nVars ); + Cut_CellSuppMin( pCell ); + // set the elementary permutation + for ( i = 0; i < (int)pCell->nVars; i++ ) + pCell->CanonPerm[i] = i; + // canonicize + pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); + + + // check if the cell exists + Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum(pCell->nVars) ); + if ( st_lookup( p->tTable, (char *)Hash, (char **)&pTemp ) ) + { + for ( ; pTemp; pTemp = pTemp->pNext ) + { + if ( pTemp->nVars != pCell->nVars ) + continue; + if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) ) + { + pTemp->nUsed++; + p->nCellFound++; + return 1; + } + } + } + p->nCellNotFound++; + return 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/cut/cutSeq.c b/abc70930/src/opt/cut/cutSeq.c new file mode 100644 index 00000000..d36f94f7 --- /dev/null +++ b/abc70930/src/opt/cut/cutSeq.c @@ -0,0 +1,227 @@ +/**CFile**************************************************************** + + FileName [cutSeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [Sequential cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Shifts all cut leaves of the node by the given number of latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cut_NodeShiftCutLeaves( Cut_Cut_t * pList, int nLat ) +{ + Cut_Cut_t * pTemp; + int i; + // shift the cuts by as many latches + Cut_ListForEachCut( pList, pTemp ) + { + pTemp->uSign = 0; + for ( i = 0; i < (int)pTemp->nLeaves; i++ ) + { + pTemp->pLeaves[i] += nLat; + pTemp->uSign |= Cut_NodeSign( pTemp->pLeaves[i] ); + } + } +} + +/**Function************************************************************* + + Synopsis [Computes sequential cuts for the node from its fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum ) +{ + Cut_List_t Super, * pSuper = &Super; + Cut_Cut_t * pListNew; + int clk; + + // get the number of cuts at the node + p->nNodeCuts = Cut_CutCountList( Cut_NodeReadCutsOld(p, Node) ); + if ( p->nNodeCuts >= p->pParams->nKeepMax ) + return; + + // count only the first visit + if ( p->nNodeCuts == 0 ) + p->nNodes++; + + // store the fanin lists + p->pStore0[0] = Cut_NodeReadCutsOld( p, Node0 ); + p->pStore0[1] = Cut_NodeReadCutsNew( p, Node0 ); + p->pStore1[0] = Cut_NodeReadCutsOld( p, Node1 ); + p->pStore1[1] = Cut_NodeReadCutsNew( p, Node1 ); + + // duplicate the cut lists if fanin nodes are non-standard + if ( Node == Node0 || Node == Node1 || Node0 == Node1 ) + { + p->pStore0[0] = Cut_CutDupList( p, p->pStore0[0] ); + p->pStore0[1] = Cut_CutDupList( p, p->pStore0[1] ); + p->pStore1[0] = Cut_CutDupList( p, p->pStore1[0] ); + p->pStore1[1] = Cut_CutDupList( p, p->pStore1[1] ); + } + + // shift the cuts by as many latches and recompute signatures + if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], nLat0 ); + if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], nLat0 ); + if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], nLat1 ); + if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], nLat1 ); + + // store the original lists for comparison + p->pCompareOld = Cut_NodeReadCutsOld( p, Node ); + p->pCompareNew = Cut_NodeReadCutsNew( p, Node ); + + // merge the old and the new +clk = clock(); + Cut_ListStart( pSuper ); + Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[0], p->pStore1[1], 0, 0 ); + Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[0], 0, 0 ); + Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[1], fTriv, 0 ); + pListNew = Cut_ListFinish( pSuper ); +p->timeMerge += clock() - clk; + + // shift the cuts by as many latches and recompute signatures + if ( Node == Node0 || Node == Node1 || Node0 == Node1 ) + { + Cut_CutRecycleList( p, p->pStore0[0] ); + Cut_CutRecycleList( p, p->pStore0[1] ); + Cut_CutRecycleList( p, p->pStore1[0] ); + Cut_CutRecycleList( p, p->pStore1[1] ); + } + else + { + if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], -nLat0 ); + if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], -nLat0 ); + if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], -nLat1 ); + if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], -nLat1 ); + } + + // set the lists at the node + if ( CutSetNum >= 0 ) + { + assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL ); + Cut_NodeWriteCutsTemp( p, CutSetNum, pListNew ); + } + else + { + assert( Cut_NodeReadCutsNew(p, Node) == NULL ); + Cut_NodeWriteCutsNew( p, Node, pListNew ); + } + + // mark the node if we exceeded the number of cuts + if ( p->nNodeCuts >= p->pParams->nKeepMax ) + p->nCutsLimit++; +} + +/**Function************************************************************* + + Synopsis [Merges the new cuts with the old cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node ) +{ + Cut_Cut_t * pListOld, * pListNew, * pList; + // get the new cuts + pListNew = Cut_NodeReadCutsNew( p, Node ); + if ( pListNew == NULL ) + return; + Cut_NodeWriteCutsNew( p, Node, NULL ); + // get the old cuts + pListOld = Cut_NodeReadCutsOld( p, Node ); + if ( pListOld == NULL ) + { + Cut_NodeWriteCutsOld( p, Node, pListNew ); + return; + } + // merge the lists + pList = Cut_CutMergeLists( pListOld, pListNew ); + Cut_NodeWriteCutsOld( p, Node, pList ); +} + + +/**Function************************************************************* + + Synopsis [Transfers the temporary cuts to be the new cuts.] + + Description [Returns 1 if something was transferred.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum ) +{ + Cut_Cut_t * pList; + pList = Cut_NodeReadCutsTemp( p, CutSetNum ); + Cut_NodeWriteCutsTemp( p, CutSetNum, NULL ); + Cut_NodeWriteCutsNew( p, Node, pList ); + return pList != NULL; +} + +/**Function************************************************************* + + Synopsis [Transfers the old cuts to be the new cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node ) +{ + Cut_Cut_t * pList; + pList = Cut_NodeReadCutsOld( p, Node ); + Cut_NodeWriteCutsOld( p, Node, NULL ); + Cut_NodeWriteCutsNew( p, Node, pList ); +// Cut_CutListVerify( pList ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/cut/cutTruth.c b/abc70930/src/opt/cut/cutTruth.c new file mode 100644 index 00000000..c3514ad7 --- /dev/null +++ b/abc70930/src/opt/cut/cutTruth.c @@ -0,0 +1,226 @@ +/**CFile**************************************************************** + + FileName [cutTruth.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [K-feasible cut computation package.] + + Synopsis [Incremental truth table computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: cutTruth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "cutInt.h" + +/* + Truth tables computed in this package are represented as bit-strings + stored in the cut data structure. Cuts of any number of inputs have + the truth table with 2^k bits, where k is the max number of cut inputs. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int nTotal = 0; +extern int nGood = 0; +extern int nEqual = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 ) +{ + unsigned uPhase = 0; + int i, k; + for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) + { + if ( k == (int)pCut1->nLeaves ) + break; + if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) + continue; + assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); + uPhase |= (1 << i); + k++; + } + return uPhase; +} + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + + Description [This procedure cannot be used while recording oracle + because it will overwrite Num0 and Num1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_TruthNCanonicize( Cut_Cut_t * pCut ) +{ + unsigned uTruth; + unsigned * uCanon2; + char * pPhases2; + assert( pCut->nVarsMax < 6 ); + + // get the direct truth table + uTruth = *Cut_CutReadTruth(pCut); + + // compute the direct truth table + Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); +// uCanon[0] = uCanon2[0]; +// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; +// uPhases[0] = pPhases2[0]; + pCut->uCanon0 = uCanon2[0]; + pCut->Num0 = pPhases2[0]; + + // get the complemented truth table + uTruth = ~*Cut_CutReadTruth(pCut); + + // compute the direct truth table + Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); +// uCanon[0] = uCanon2[0]; +// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; +// uPhases[0] = pPhases2[0]; + pCut->uCanon1 = uCanon2[0]; + pCut->Num1 = pPhases2[0]; +} + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) +{ + static unsigned uTruth0[8], uTruth1[8]; + int nTruthWords = Cut_TruthWords( pCut->nVarsMax ); + unsigned * pTruthRes; + int i, uPhase; + + // permute the first table + uPhase = Cut_TruthPhase( pCut, pCut0 ); + Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut0), uPhase, uTruth0 ); + if ( fCompl0 ) + { + for ( i = 0; i < nTruthWords; i++ ) + uTruth0[i] = ~uTruth0[i]; + } + + // permute the second table + uPhase = Cut_TruthPhase( pCut, pCut1 ); + Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut1), uPhase, uTruth1 ); + if ( fCompl1 ) + { + for ( i = 0; i < nTruthWords; i++ ) + uTruth1[i] = ~uTruth1[i]; + } + + // write the resulting table + pTruthRes = Cut_CutReadTruth(pCut); + + if ( pCut->fCompl ) + { + for ( i = 0; i < nTruthWords; i++ ) + pTruthRes[i] = ~(uTruth0[i] & uTruth1[i]); + } + else + { + for ( i = 0; i < nTruthWords; i++ ) + pTruthRes[i] = uTruth0[i] & uTruth1[i]; + } +} + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) +{ + // permute the first table + if ( fCompl0 ) + Extra_TruthNot( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax ); + else + Extra_TruthCopy( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax ); + Extra_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut0) ); + // permute the second table + if ( fCompl1 ) + Extra_TruthNot( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax ); + else + Extra_TruthCopy( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax ); + Extra_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut1) ); + // produce the resulting table + if ( pCut->fCompl ) + Extra_TruthNand( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax ); + else + Extra_TruthAnd( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax ); + +// Ivy_TruthTestOne( *Cut_CutReadTruth(pCut) ); + + // quit if no fancy computation is needed + if ( !p->pParams->fFancy ) + return; + + if ( pCut->nLeaves != 7 ) + return; + + // count the total number of truth tables computed + nTotal++; + + // MAPPING INTO ALTERA 6-2 LOGIC BLOCKS + // call this procedure to find the minimum number of common variables in the cofactors + // if this number is less or equal than 3, the cut can be implemented using the 6-2 logic block + if ( Extra_TruthMinCofSuppOverlap( Cut_CutReadTruth(pCut), pCut->nVarsMax, NULL ) <= 4 ) + nGood++; + + // MAPPING INTO ACTEL 2x2 CELLS + // call this procedure to see if a semi-canonical form can be found in the lookup table + // (if it exists, then a two-level 3-input LUT implementation of the cut exists) + // Before this procedure is called, cell manager should be defined by calling + // Cut_CellLoad (make sure file "cells22_daomap_iwls.txt" is available in the working dir) +// if ( Cut_CellIsRunning() && pCut->nVarsMax <= 9 ) +// nGood += Cut_CellTruthLookup( Cut_CutReadTruth(pCut), pCut->nVarsMax ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/cut/module.make b/abc70930/src/opt/cut/module.make new file mode 100644 index 00000000..132e730b --- /dev/null +++ b/abc70930/src/opt/cut/module.make @@ -0,0 +1,9 @@ +SRC += src/opt/cut/cutApi.c \ + src/opt/cut/cutCut.c \ + src/opt/cut/cutMan.c \ + src/opt/cut/cutMerge.c \ + src/opt/cut/cutNode.c \ + src/opt/cut/cutOracle.c \ + src/opt/cut/cutPre22.c \ + src/opt/cut/cutSeq.c \ + src/opt/cut/cutTruth.c diff --git a/abc70930/src/opt/dec/dec.h b/abc70930/src/opt/dec/dec.h new file mode 100644 index 00000000..41d22649 --- /dev/null +++ b/abc70930/src/opt/dec/dec.h @@ -0,0 +1,719 @@ +/**CFile**************************************************************** + + FileName [dec.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [A simple decomposition tree/node data structure and its APIs.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: dec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __DEC_H__ +#define __DEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Dec_Edge_t_ Dec_Edge_t; +struct Dec_Edge_t_ +{ + unsigned fCompl : 1; // the complemented bit + unsigned Node : 30; // the decomposition node pointed by the edge +}; + +typedef struct Dec_Node_t_ Dec_Node_t; +struct Dec_Node_t_ +{ + Dec_Edge_t eEdge0; // the left child of the node + Dec_Edge_t eEdge1; // the right child of the node + // other info + void * pFunc; // the function of the node (BDD or AIG) + unsigned Level : 14; // the level of this node in the global AIG + // printing info + unsigned fNodeOr : 1; // marks the original OR node + unsigned fCompl0 : 1; // marks the original complemented edge + unsigned fCompl1 : 1; // marks the original complemented edge + // latch info + unsigned nLat0 : 5; // the number of latches on the first edge + unsigned nLat1 : 5; // the number of latches on the second edge + unsigned nLat2 : 5; // the number of latches on the output edge +}; + +typedef struct Dec_Graph_t_ Dec_Graph_t; +struct Dec_Graph_t_ +{ + int fConst; // marks the constant 1 graph + int nLeaves; // the number of leaves + int nSize; // the number of nodes (including the leaves) + int nCap; // the number of allocated nodes + Dec_Node_t * pNodes; // the array of leaves and internal nodes + Dec_Edge_t eRoot; // the pointer to the topmost node +}; + +typedef struct Dec_Man_t_ Dec_Man_t; +struct Dec_Man_t_ +{ + void * pMvcMem; // memory manager for MVC cover (used for factoring) + Vec_Int_t * vCubes; // storage for cubes + Vec_Int_t * vLits; // storage for literals + // precomputation information about 4-variable functions + unsigned short * puCanons; // canonical forms + char * pPhases; // canonical phases + char * pPerms; // canonical permutations + unsigned char * pMap; // mapping of functions into class numbers +}; + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// interator throught the leaves +#define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \ + for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ ) +// interator throught the internal nodes +#define Dec_GraphForEachNode( pGraph, pAnd, i ) \ + for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== decAbc.c ========================================================*/ +extern Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ); +extern Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ); +extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); +extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain ); +/*=== decFactor.c ========================================================*/ +extern Dec_Graph_t * Dec_Factor( char * pSop ); +/*=== decMan.c ========================================================*/ +extern Dec_Man_t * Dec_ManStart(); +extern void Dec_ManStop( Dec_Man_t * p ); +/*=== decPrint.c ========================================================*/ +extern void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut ); +/*=== decUtil.c ========================================================*/ +extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ); +extern unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates an edge pointing to the node in the given polarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl ) +{ + Dec_Edge_t eEdge = { fCompl, Node }; + return eEdge; +} + +/**Function************************************************************* + + Synopsis [Converts the edge into unsigned integer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge ) +{ + return (eEdge.Node << 1) | eEdge.fCompl; +} + +/**Function************************************************************* + + Synopsis [Converts unsigned integer into the edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge ) +{ + return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); +} + +/**Function************************************************************* + + Synopsis [Converts the edge into unsigned integer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge ) +{ + return *(unsigned *)&eEdge; +} + +/**Function************************************************************* + + Synopsis [Converts unsigned integer into the edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge ) +{ + return *(Dec_Edge_t *)&Edge; +} + +/**Function************************************************************* + + Synopsis [Creates a graph with the given number of leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves ) +{ + Dec_Graph_t * pGraph; + pGraph = ALLOC( Dec_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Dec_Graph_t) ); + pGraph->nLeaves = nLeaves; + pGraph->nSize = nLeaves; + pGraph->nCap = 2 * nLeaves + 50; + pGraph->pNodes = ALLOC( Dec_Node_t, pGraph->nCap ); + memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates constant 0 graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreateConst0() +{ + Dec_Graph_t * pGraph; + pGraph = ALLOC( Dec_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Dec_Graph_t) ); + pGraph->fConst = 1; + pGraph->eRoot.fCompl = 1; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates constant 1 graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreateConst1() +{ + Dec_Graph_t * pGraph; + pGraph = ALLOC( Dec_Graph_t, 1 ); + memset( pGraph, 0, sizeof(Dec_Graph_t) ); + pGraph->fConst = 1; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates the literal graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ) +{ + Dec_Graph_t * pGraph; + assert( 0 <= iLeaf && iLeaf < nLeaves ); + pGraph = Dec_GraphCreate( nLeaves ); + pGraph->eRoot.Node = iLeaf; + pGraph->eRoot.fCompl = fCompl; + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Creates a graph with the given number of leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Dec_GraphFree( Dec_Graph_t * pGraph ) +{ + FREE( pGraph->pNodes ); + free( pGraph ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline bool Dec_GraphIsConst( Dec_Graph_t * pGraph ) +{ + return pGraph->fConst; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline bool Dec_GraphIsConst0( Dec_Graph_t * pGraph ) +{ + return pGraph->fConst && pGraph->eRoot.fCompl; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline bool Dec_GraphIsConst1( Dec_Graph_t * pGraph ) +{ + return pGraph->fConst && !pGraph->eRoot.fCompl; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the graph is complemented.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline bool Dec_GraphIsComplement( Dec_Graph_t * pGraph ) +{ + return pGraph->eRoot.fCompl; +} + +/**Function************************************************************* + + Synopsis [Checks if the graph is complemented.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Dec_GraphComplement( Dec_Graph_t * pGraph ) +{ + pGraph->eRoot.fCompl ^= 1; +} + + +/**Function************************************************************* + + Synopsis [Returns the number of leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph ) +{ + return pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the number of internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph ) +{ + return pGraph->nSize - pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i ) +{ + return pGraph->pNodes + i; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph ) +{ + return pGraph->pNodes + pGraph->nSize - 1; +} + +/**Function************************************************************* + + Synopsis [Returns the number of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) +{ + return pNode - pGraph->pNodes; +} + +/**Function************************************************************* + + Synopsis [Check if the graph represents elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline bool Dec_GraphIsVar( Dec_Graph_t * pGraph ) +{ + return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Check if the graph represents elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline bool Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) +{ + return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; +} + +/**Function************************************************************* + + Synopsis [Returns the elementary variable elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph ) +{ + assert( Dec_GraphIsVar( pGraph ) ); + return Dec_GraphNode( pGraph, pGraph->eRoot.Node ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of the elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph ) +{ + assert( Dec_GraphIsVar( pGraph ) ); + return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Sets the root of the graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot ) +{ + pGraph->eRoot = eRoot; +} + +/**Function************************************************************* + + Synopsis [Appends a new node to the graph.] + + Description [This procedure is meant for internal use.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph ) +{ + Dec_Node_t * pNode; + if ( pGraph->nSize == pGraph->nCap ) + { + pGraph->pNodes = REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); + pGraph->nCap = 2 * pGraph->nCap; + } + pNode = pGraph->pNodes + pGraph->nSize++; + memset( pNode, 0, sizeof(Dec_Node_t) ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates an AND node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) +{ + Dec_Node_t * pNode; + // get the new node + pNode = Dec_GraphAppendNode( pGraph ); + // set the inputs and other info + pNode->eEdge0 = eEdge0; + pNode->eEdge1 = eEdge1; + pNode->fCompl0 = eEdge0.fCompl; + pNode->fCompl1 = eEdge1.fCompl; + return Dec_EdgeCreate( pGraph->nSize - 1, 0 ); +} + +/**Function************************************************************* + + Synopsis [Creates an OR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) +{ + Dec_Node_t * pNode; + // get the new node + pNode = Dec_GraphAppendNode( pGraph ); + // set the inputs and other info + pNode->eEdge0 = eEdge0; + pNode->eEdge1 = eEdge1; + pNode->fCompl0 = eEdge0.fCompl; + pNode->fCompl1 = eEdge1.fCompl; + // make adjustments for the OR gate + pNode->fNodeOr = 1; + pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl; + pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl; + return Dec_EdgeCreate( pGraph->nSize - 1, 1 ); +} + +/**Function************************************************************* + + Synopsis [Creates an XOR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type ) +{ + Dec_Edge_t eNode0, eNode1, eNode; + if ( Type == 0 ) + { + // derive the first AND + eEdge0.fCompl ^= 1; + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + eEdge0.fCompl ^= 1; + // derive the second AND + eEdge1.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + } + else + { + // derive the first AND + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the second AND + eEdge0.fCompl ^= 1; + eEdge1.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + eNode.fCompl ^= 1; + } + return eNode; +} + +/**Function************************************************************* + + Synopsis [Creates an XOR node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type ) +{ + Dec_Edge_t eNode0, eNode1, eNode; + if ( Type == 0 ) + { + // derive the first AND + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); + // derive the second AND + eEdgeC.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + } + else + { + // complement the arguments + eEdgeT.fCompl ^= 1; + eEdgeE.fCompl ^= 1; + // derive the first AND + eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); + // derive the second AND + eEdgeC.fCompl ^= 1; + eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); + // derive the final OR + eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); + eNode.fCompl ^= 1; + } + return eNode; +} + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/dec/decAbc.c b/abc70930/src/opt/dec/decAbc.c new file mode 100644 index 00000000..bd960c14 --- /dev/null +++ b/abc70930/src/opt/dec/decAbc.c @@ -0,0 +1,305 @@ +/**CFile**************************************************************** + + FileName [decAbc.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Interface between the decomposition package and ABC network.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: decAbc.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" +#include "ivy.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ) +{ + Abc_Obj_t * pAnd0, * pAnd1; + Dec_Node_t * pNode; + int i; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Abc_ObjNotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Abc_AigAnd( pNtk->pManFunc, pAnd0, pAnd1 ); + } + // complement the result if necessary + return Abc_ObjNotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ) +{ + Abc_Obj_t * pAnd, * pAnd0, * pAnd1; + Dec_Node_t * pNode; + int i; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Abc_ObjNotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); +// pNode->pFunc = Abc_AigAnd( pNtk->pManFunc, pAnd0, pAnd1 ); + pAnd = Abc_NtkCreateNode( pNtk ); + Abc_ObjAddFanin( pAnd, pAnd0 ); + Abc_ObjAddFanin( pAnd, pAnd1 ); + pNode->pFunc = pAnd; + } + // complement the result if necessary + return Abc_ObjNotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of new nodes added when using this graph.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure. + Returns -1 if the number of nodes and levels exceeded the given limit or + the number of levels exceeded the maximum allowed level.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ) +{ + Abc_Aig_t * pMan = pRoot->pNtk->pManFunc; + Dec_Node_t * pNode, * pNode0, * pNode1; + Abc_Obj_t * pAnd, * pAnd0, * pAnd1; + int i, Counter, LevelNew, LevelOld; + // check for constant function or a literal + if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) + return 0; + // set the levels of the leaves + Dec_GraphForEachLeaf( pGraph, pNode, i ) + pNode->Level = Abc_ObjRegular(pNode->pFunc)->Level; + // compute the AIG size after adding the internal nodes + Counter = 0; + Dec_GraphForEachNode( pGraph, pNode, i ) + { + // get the children of this node + pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); + pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); + // get the AIG nodes corresponding to the children + pAnd0 = pNode0->pFunc; + pAnd1 = pNode1->pFunc; + if ( pAnd0 && pAnd1 ) + { + // if they are both present, find the resulting node + pAnd0 = Abc_ObjNotCond( pAnd0, pNode->eEdge0.fCompl ); + pAnd1 = Abc_ObjNotCond( pAnd1, pNode->eEdge1.fCompl ); + pAnd = Abc_AigAndLookup( pMan, pAnd0, pAnd1 ); + // return -1 if the node is the same as the original root + if ( Abc_ObjRegular(pAnd) == pRoot ) + return -1; + } + else + pAnd = NULL; + // count the number of added nodes + if ( pAnd == NULL || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pAnd)) ) + { + if ( ++Counter > NodeMax ) + return -1; + } + // count the number of new levels + LevelNew = 1 + ABC_MAX( pNode0->Level, pNode1->Level ); + if ( pAnd ) + { + if ( Abc_ObjRegular(pAnd) == Abc_AigConst1(pRoot->pNtk) ) + LevelNew = 0; + else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd0) ) + LevelNew = (int)Abc_ObjRegular(pAnd0)->Level; + else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd1) ) + LevelNew = (int)Abc_ObjRegular(pAnd1)->Level; + LevelOld = (int)Abc_ObjRegular(pAnd)->Level; +// assert( LevelNew == LevelOld ); + } + if ( LevelNew > LevelMax ) + return -1; + pNode->pFunc = pAnd; + pNode->Level = LevelNew; + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Replaces MFFC of the node by the new factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain ) +{ + Abc_Obj_t * pRootNew; + Abc_Ntk_t * pNtk = pRoot->pNtk; + int nNodesNew, nNodesOld; + nNodesOld = Abc_NtkNodeNum(pNtk); + // create the new structure of nodes + pRootNew = Dec_GraphToNetwork( pNtk, pGraph ); + // remove the old nodes + Abc_AigReplace( pNtk->pManFunc, pRoot, pRootNew, fUpdateLevel ); + // compare the gains + nNodesNew = Abc_NtkNodeNum(pNtk); + assert( nGain <= nNodesOld - nNodesNew ); +} + + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Dec_GraphToNetworkAig( Hop_Man_t * pMan, Dec_Graph_t * pGraph ) +{ + Dec_Node_t * pNode; + Hop_Obj_t * pAnd0, * pAnd1; + int i; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Hop_NotCond( Hop_ManConst1(pMan), Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Hop_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Hop_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Hop_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 ); + } + // complement the result if necessary + return Hop_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop ) +{ + Hop_Obj_t * pFunc; + Dec_Graph_t * pFForm; + Dec_Node_t * pNode; + int i; + // perform factoring + pFForm = Dec_Factor( pSop ); + // collect the fanins + Dec_GraphForEachLeaf( pFForm, pNode, i ) + pNode->pFunc = Hop_IthVar( pMan, i ); + // perform strashing + pFunc = Dec_GraphToNetworkAig( pMan, pFForm ); + Dec_GraphFree( pFForm ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph ) +{ + Dec_Node_t * pNode; + Ivy_Obj_t * pAnd0, * pAnd1; + int i; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Ivy_NotCond( Ivy_ManConst1(pMan), Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Ivy_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Ivy_And( pMan, pAnd0, pAnd1 ); + } + // complement the result if necessary + return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/dec/decFactor.c b/abc70930/src/opt/dec/decFactor.c new file mode 100644 index 00000000..dca422ea --- /dev/null +++ b/abc70930/src/opt/dec/decFactor.c @@ -0,0 +1,392 @@ +/**CFile**************************************************************** + + FileName [ftFactor.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Procedures for algebraic factoring.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: ftFactor.c,v 1.3 2003/09/01 04:56:43 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "main.h" +#include "mvc.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ); +static Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ); +static Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ); +static Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits ); +static Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr ); +static int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ); +static Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Factors the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Dec_Factor( char * pSop ) +{ + Mvc_Cover_t * pCover; + Dec_Graph_t * pFForm; + Dec_Edge_t eRoot; + + // derive the cover from the SOP representation + pCover = Dec_ConvertSopToMvc( pSop ); + + // make sure the cover is CCS free (should be done before CST) + Mvc_CoverContain( pCover ); + // check for trivial functions + if ( Mvc_CoverIsEmpty(pCover) ) + { + Mvc_CoverFree( pCover ); + return Dec_GraphCreateConst0(); + } + if ( Mvc_CoverIsTautology(pCover) ) + { + Mvc_CoverFree( pCover ); + return Dec_GraphCreateConst1(); + } + + // perform CST + Mvc_CoverInverse( pCover ); // CST + // start the factored form + pFForm = Dec_GraphCreate( Abc_SopGetVarNum(pSop) ); + // factor the cover + eRoot = Dec_Factor_rec( pFForm, pCover ); + // finalize the factored form + Dec_GraphSetRoot( pFForm, eRoot ); + // complement the factored form if SOP is complemented + if ( Abc_SopIsComplement(pSop) ) + Dec_GraphComplement( pFForm ); + // verify the factored form +// if ( !Dec_FactorVerify( pSop, pFForm ) ) +// printf( "Verification has failed.\n" ); +// Mvc_CoverInverse( pCover ); // undo CST + Mvc_CoverFree( pCover ); + return pFForm; +} + +/**Function************************************************************* + + Synopsis [Internal recursive factoring procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) +{ + Mvc_Cover_t * pDiv, * pQuo, * pRem, * pCom; + Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem; + Dec_Edge_t eNodeAnd, eNode; + + // make sure the cover contains some cubes + assert( Mvc_CoverReadCubeNum(pCover) ); + + // get the divisor + pDiv = Mvc_CoverDivisor( pCover ); + if ( pDiv == NULL ) + return Dec_FactorTrivial( pFForm, pCover ); + + // divide the cover by the divisor + Mvc_CoverDivideInternal( pCover, pDiv, &pQuo, &pRem ); + assert( Mvc_CoverReadCubeNum(pQuo) ); + + Mvc_CoverFree( pDiv ); + Mvc_CoverFree( pRem ); + + // check the trivial case + if ( Mvc_CoverReadCubeNum(pQuo) == 1 ) + { + eNode = Dec_FactorLF_rec( pFForm, pCover, pQuo ); + Mvc_CoverFree( pQuo ); + return eNode; + } + + // make the quotient cube free + Mvc_CoverMakeCubeFree( pQuo ); + + // divide the cover by the quotient + Mvc_CoverDivideInternal( pCover, pQuo, &pDiv, &pRem ); + + // check the trivial case + if ( Mvc_CoverIsCubeFree( pDiv ) ) + { + eNodeDiv = Dec_Factor_rec( pFForm, pDiv ); + eNodeQuo = Dec_Factor_rec( pFForm, pQuo ); + Mvc_CoverFree( pDiv ); + Mvc_CoverFree( pQuo ); + eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); + if ( Mvc_CoverReadCubeNum(pRem) == 0 ) + { + Mvc_CoverFree( pRem ); + return eNodeAnd; + } + else + { + eNodeRem = Dec_Factor_rec( pFForm, pRem ); + Mvc_CoverFree( pRem ); + return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); + } + } + + // get the common cube + pCom = Mvc_CoverCommonCubeCover( pDiv ); + Mvc_CoverFree( pDiv ); + Mvc_CoverFree( pQuo ); + Mvc_CoverFree( pRem ); + + // solve the simple problem + eNode = Dec_FactorLF_rec( pFForm, pCover, pCom ); + Mvc_CoverFree( pCom ); + return eNode; +} + + +/**Function************************************************************* + + Synopsis [Internal recursive factoring procedure for the leaf case.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ) +{ + Dec_Man_t * pManDec = Abc_FrameReadManDec(); + Vec_Int_t * vEdgeLits = pManDec->vLits; + Mvc_Cover_t * pDiv, * pQuo, * pRem; + Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem; + Dec_Edge_t eNodeAnd; + + // get the most often occurring literal + pDiv = Mvc_CoverBestLiteralCover( pCover, pSimple ); + // divide the cover by the literal + Mvc_CoverDivideByLiteral( pCover, pDiv, &pQuo, &pRem ); + // get the node pointer for the literal + eNodeDiv = Dec_FactorTrivialCube( pFForm, pDiv, Mvc_CoverReadCubeHead(pDiv), vEdgeLits ); + Mvc_CoverFree( pDiv ); + // factor the quotient and remainder + eNodeQuo = Dec_Factor_rec( pFForm, pQuo ); + Mvc_CoverFree( pQuo ); + eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); + if ( Mvc_CoverReadCubeNum(pRem) == 0 ) + { + Mvc_CoverFree( pRem ); + return eNodeAnd; + } + else + { + eNodeRem = Dec_Factor_rec( pFForm, pRem ); + Mvc_CoverFree( pRem ); + return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); + } +} + + + +/**Function************************************************************* + + Synopsis [Factoring the cover, which has no algebraic divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) +{ + Dec_Man_t * pManDec = Abc_FrameReadManDec(); + Vec_Int_t * vEdgeCubes = pManDec->vCubes; + Vec_Int_t * vEdgeLits = pManDec->vLits; + Mvc_Manager_t * pMem = pManDec->pMvcMem; + Dec_Edge_t eNode; + Mvc_Cube_t * pCube; + // create the factored form for each cube + Vec_IntClear( vEdgeCubes ); + Mvc_CoverForEachCube( pCover, pCube ) + { + eNode = Dec_FactorTrivialCube( pFForm, pCover, pCube, vEdgeLits ); + Vec_IntPush( vEdgeCubes, Dec_EdgeToInt_(eNode) ); + } + // balance the factored forms + return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeCubes->pArray, vEdgeCubes->nSize, 1 ); +} + +/**Function************************************************************* + + Synopsis [Factoring the cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits ) +{ + Dec_Edge_t eNode; + int iBit, Value; + // create the factored form for each literal + Vec_IntClear( vEdgeLits ); + Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) + if ( Value ) + { + eNode = Dec_EdgeCreate( iBit/2, iBit%2 ); // CST + Vec_IntPush( vEdgeLits, Dec_EdgeToInt_(eNode) ); + } + // balance the factored forms + return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeLits->pArray, vEdgeLits->nSize, 0 ); +} + +/**Function************************************************************* + + Synopsis [Create the well-balanced tree of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr ) +{ + Dec_Edge_t eNode1, eNode2; + int nNodes1, nNodes2; + + if ( nNodes == 1 ) + return peNodes[0]; + + // split the nodes into two parts + nNodes1 = nNodes/2; + nNodes2 = nNodes - nNodes1; +// nNodes2 = nNodes/2; +// nNodes1 = nNodes - nNodes2; + + // recursively construct the tree for the parts + eNode1 = Dec_FactorTrivialTree_rec( pFForm, peNodes, nNodes1, fNodeOr ); + eNode2 = Dec_FactorTrivialTree_rec( pFForm, peNodes + nNodes1, nNodes2, fNodeOr ); + + if ( fNodeOr ) + return Dec_GraphAddNodeOr( pFForm, eNode1, eNode2 ); + else + return Dec_GraphAddNodeAnd( pFForm, eNode1, eNode2 ); +} + + + +/**Function************************************************************* + + Synopsis [Converts SOP into MVC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ) +{ + Dec_Man_t * pManDec = Abc_FrameReadManDec(); + Mvc_Manager_t * pMem = pManDec->pMvcMem; + Mvc_Cover_t * pMvc; + Mvc_Cube_t * pMvcCube; + char * pCube; + int nVars, Value, v; + + // start the cover + nVars = Abc_SopGetVarNum(pSop); + pMvc = Mvc_CoverAlloc( pMem, nVars * 2 ); + // check the logic function of the node + Abc_SopForEachCube( pSop, nVars, pCube ) + { + // create and add the cube + pMvcCube = Mvc_CubeAlloc( pMvc ); + Mvc_CoverAddCubeTail( pMvc, pMvcCube ); + // fill in the literals + Mvc_CubeBitFill( pMvcCube ); + Abc_CubeForEachVar( pCube, Value, v ) + { + if ( Value == '0' ) + Mvc_CubeBitRemove( pMvcCube, v * 2 + 1 ); + else if ( Value == '1' ) + Mvc_CubeBitRemove( pMvcCube, v * 2 ); + } + } + return pMvc; +} + +/**Function************************************************************* + + Synopsis [Verifies that the factoring is correct.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ) +{ + DdManager * dd = Abc_FrameReadManDd(); + DdNode * bFunc1, * bFunc2; + int RetValue; + bFunc1 = Abc_ConvertSopToBdd( dd, pSop ); Cudd_Ref( bFunc1 ); + bFunc2 = Dec_GraphDeriveBdd( dd, pFForm ); Cudd_Ref( bFunc2 ); +//Extra_bddPrint( dd, bFunc1 ); printf("\n"); +//Extra_bddPrint( dd, bFunc2 ); printf("\n"); + RetValue = (bFunc1 == bFunc2); + if ( bFunc1 != bFunc2 ) + { + int s; + Extra_bddPrint( dd, bFunc1 ); printf("\n"); + Extra_bddPrint( dd, bFunc2 ); printf("\n"); + s = 0; + } + Cudd_RecursiveDeref( dd, bFunc1 ); + Cudd_RecursiveDeref( dd, bFunc2 ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/dec/decMan.c b/abc70930/src/opt/dec/decMan.c new file mode 100644 index 00000000..65857461 --- /dev/null +++ b/abc70930/src/opt/dec/decMan.c @@ -0,0 +1,83 @@ +/**CFile**************************************************************** + + FileName [decMan.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Decomposition manager.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: decMan.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "mvc.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start the MVC manager used in the factoring package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Man_t * Dec_ManStart() +{ + Dec_Man_t * p; + int clk = clock(); + p = ALLOC( Dec_Man_t, 1 ); + p->pMvcMem = Mvc_ManagerStart(); + p->vCubes = Vec_IntAlloc( 8 ); + p->vLits = Vec_IntAlloc( 8 ); + // canonical forms, phases, perms + Extra_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap ); +//PRT( "NPN classes precomputation time", clock() - clk ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the MVC maanager used in the factoring package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_ManStop( Dec_Man_t * p ) +{ + Mvc_ManagerFree( p->pMvcMem ); + Vec_IntFree( p->vCubes ); + Vec_IntFree( p->vLits ); + free( p->puCanons ); + free( p->pPhases ); + free( p->pPerms ); + free( p->pMap ); + free( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/dec/decPrint.c b/abc70930/src/opt/dec/decPrint.c new file mode 100644 index 00000000..2d8f09b3 --- /dev/null +++ b/abc70930/src/opt/dec/decPrint.c @@ -0,0 +1,284 @@ +/**CFile**************************************************************** + + FileName [decPrint.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Procedures to print the decomposition graphs (factored forms).] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: decPrint.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ); +static int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] ); +static void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax ); +static int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut, int fCompl ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Prints the decomposition graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut ) +{ + Vec_Ptr_t * vNamesIn = NULL; + int LitSizeMax, LitSizeCur, Pos, i; + + // create the names if not given by the user + if ( pNamesIn == NULL ) + { + vNamesIn = Abc_NodeGetFakeNames( Dec_GraphLeaveNum(pGraph) ); + pNamesIn = (char **)vNamesIn->pArray; + } + if ( pNameOut == NULL ) + pNameOut = "F"; + + // get the size of the longest literal + LitSizeMax = 0; + for ( i = 0; i < Dec_GraphLeaveNum(pGraph); i++ ) + { + LitSizeCur = strlen(pNamesIn[i]); + if ( LitSizeMax < LitSizeCur ) + LitSizeMax = LitSizeCur; + } + if ( LitSizeMax > 50 ) + LitSizeMax = 20; + + // write the decomposition graph (factored form) + if ( Dec_GraphIsConst(pGraph) ) // constant + { + Pos = Dec_GraphPrintOutputName( pFile, pNameOut, 0 ); + fprintf( pFile, "Constant %d", !Dec_GraphIsComplement(pGraph) ); + } + else if ( Dec_GraphIsVar(pGraph) ) // literal + { + Pos = Dec_GraphPrintOutputName( pFile, pNameOut, 0 ); + Dec_GraphPrintGetLeafName( pFile, Dec_GraphVarInt(pGraph), Dec_GraphIsComplement(pGraph), pNamesIn ); + } + else + { + Pos = Dec_GraphPrintOutputName( pFile, pNameOut, Dec_GraphIsComplement(pGraph) ); + Dec_GraphPrint_rec( pFile, pGraph, Dec_GraphNodeLast(pGraph), 0, pNamesIn, &Pos, LitSizeMax ); + } + fprintf( pFile, "\n" ); + + if ( vNamesIn ) + Abc_NodeFreeNames( vNamesIn ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_GraphPrint2_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ) +{ + Dec_Node_t * pNode0, * pNode1; + pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node); + pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node); + if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF ) + { + (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn ); + return; + } + if ( !pNode->fNodeOr ) // FT_NODE_AND ) + { + if ( !pNode0->fNodeOr ) // != FT_NODE_OR ) + Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); + else + { + fprintf( pFile, "(" ); + (*pPos)++; + Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, ")" ); + (*pPos)++; + } + fprintf( pFile, " " ); + (*pPos)++; + + Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax ); + + if ( !pNode1->fNodeOr ) // != FT_NODE_OR ) + Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); + else + { + fprintf( pFile, "(" ); + (*pPos)++; + Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, ")" ); + (*pPos)++; + } + return; + } + if ( pNode->fNodeOr ) // FT_NODE_OR ) + { + Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, " + " ); + (*pPos) += 3; + + Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax ); + + Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); + return; + } + assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ) +{ + Dec_Node_t * pNode0, * pNode1; + Dec_Node_t * pNode00, * pNode01, * pNode10, * pNode11; + pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node); + pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node); + if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF ) + { + (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn ); + return; + } + if ( !Dec_GraphNodeIsVar(pGraph, pNode0) && !Dec_GraphNodeIsVar(pGraph, pNode1) ) + { + pNode00 = Dec_GraphNode(pGraph, pNode0->eEdge0.Node); + pNode01 = Dec_GraphNode(pGraph, pNode0->eEdge1.Node); + pNode10 = Dec_GraphNode(pGraph, pNode1->eEdge0.Node); + pNode11 = Dec_GraphNode(pGraph, pNode1->eEdge1.Node); + if ( (pNode00 == pNode10 || pNode00 == pNode11) && (pNode01 == pNode10 || pNode01 == pNode11) ) + { + fprintf( pFile, "(" ); + (*pPos)++; + Dec_GraphPrint_rec( pFile, pGraph, pNode00, pNode00->fCompl0, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, " # " ); + (*pPos) += 3; + Dec_GraphPrint_rec( pFile, pGraph, pNode01, pNode01->fCompl1, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, ")" ); + (*pPos)++; + return; + } + } + if ( fCompl ) + { + fprintf( pFile, "(" ); + (*pPos)++; + Dec_GraphPrint_rec( pFile, pGraph, pNode0, !pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, " + " ); + (*pPos) += 3; + Dec_GraphPrint_rec( pFile, pGraph, pNode1, !pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, ")" ); + (*pPos)++; + } + else + { + fprintf( pFile, "(" ); + (*pPos)++; + Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); + Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); + fprintf( pFile, ")" ); + (*pPos)++; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] ) +{ + static char Buffer[100]; + sprintf( Buffer, "%s%s", pNamesIn[iLeaf], fCompl? "\'" : "" ); + fprintf( pFile, "%s", Buffer ); + return strlen( Buffer ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax ) +{ + int i; + if ( *pPos + LitSizeMax < 77 ) + return; + fprintf( pFile, "\n" ); + for ( i = 0; i < 10; i++ ) + fprintf( pFile, " " ); + *pPos = 10; +} + +/**Function************************************************************* + + Synopsis [Starts the printout for a decomposition graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut, int fCompl ) +{ + if ( pNameOut == NULL ) + return 0; + fprintf( pFile, "%6s%s = ", pNameOut, fCompl? "\'" : " " ); + return 10; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/dec/decUtil.c b/abc70930/src/opt/dec/decUtil.c new file mode 100644 index 00000000..463bc7e2 --- /dev/null +++ b/abc70930/src/opt/dec/decUtil.c @@ -0,0 +1,134 @@ +/**CFile**************************************************************** + + FileName [decUtil.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Decomposition unitilies.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: decUtil.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts graph to BDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ) +{ + DdNode * bFunc, * bFunc0, * bFunc1; + Dec_Node_t * pNode; + int i; + + // sanity checks + assert( Dec_GraphLeaveNum(pGraph) >= 0 ); + assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); + + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Cudd_NotCond( b1, Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Cudd_NotCond( Cudd_bddIthVar(dd, Dec_GraphVarInt(pGraph)), Dec_GraphIsComplement(pGraph) ); + + // assign the elementary variables + Dec_GraphForEachLeaf( pGraph, pNode, i ) + pNode->pFunc = Cudd_bddIthVar( dd, i ); + + // compute the function for each internal node + Dec_GraphForEachNode( pGraph, pNode, i ) + { + bFunc0 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + bFunc1 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( pNode->pFunc ); + } + + // deref the intermediate results + bFunc = pNode->pFunc; Cudd_Ref( bFunc ); + Dec_GraphForEachNode( pGraph, pNode, i ) + Cudd_RecursiveDeref( dd, pNode->pFunc ); + Cudd_Deref( bFunc ); + + // complement the result if necessary + return Cudd_NotCond( bFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Derives the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph ) +{ + unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + unsigned uTruth, uTruth0, uTruth1; + Dec_Node_t * pNode; + int i; + + // sanity checks + assert( Dec_GraphLeaveNum(pGraph) >= 0 ); + assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); + assert( Dec_GraphLeaveNum(pGraph) <= 5 ); + + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Dec_GraphIsComplement(pGraph)? 0 : ~((unsigned)0); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Dec_GraphIsComplement(pGraph)? ~uTruths[Dec_GraphVarInt(pGraph)] : uTruths[Dec_GraphVarInt(pGraph)]; + + // assign the elementary variables + Dec_GraphForEachLeaf( pGraph, pNode, i ) + pNode->pFunc = (void *)uTruths[i]; + + // compute the function for each internal node + Dec_GraphForEachNode( pGraph, pNode, i ) + { + uTruth0 = (unsigned)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; + uTruth1 = (unsigned)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; + uTruth0 = pNode->eEdge0.fCompl? ~uTruth0 : uTruth0; + uTruth1 = pNode->eEdge1.fCompl? ~uTruth1 : uTruth1; + uTruth = uTruth0 & uTruth1; + pNode->pFunc = (void *)uTruth; + } + + // complement the result if necessary + return Dec_GraphIsComplement(pGraph)? ~uTruth : uTruth; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/dec/module.make b/abc70930/src/opt/dec/module.make new file mode 100644 index 00000000..1e0722d5 --- /dev/null +++ b/abc70930/src/opt/dec/module.make @@ -0,0 +1,5 @@ +SRC += src/opt/dec/decAbc.c \ + src/opt/dec/decFactor.c \ + src/opt/dec/decMan.c \ + src/opt/dec/decPrint.c \ + src/opt/dec/decUtil.c diff --git a/abc70930/src/opt/fxu/fxu.c b/abc70930/src/opt/fxu/fxu.c new file mode 100644 index 00000000..d11fd793 --- /dev/null +++ b/abc70930/src/opt/fxu/fxu.c @@ -0,0 +1,254 @@ +/**CFile**************************************************************** + + FileName [fxu.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [The entrance into the fast extract module.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxu.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fxuInt.h" +#include "fxu.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*===== fxuCreate.c ====================================================*/ +extern Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ); +extern void Fxu_CreateCovers( Fxu_Matrix * p, Fxu_Data_t * pData ); + +static int s_MemoryTotal; +static int s_MemoryPeak; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs fast_extract on a set of covers.] + + Description [All the covers are given in the array p->vSops. + The resulting covers are returned in the array p->vSopsNew. + The entries in these arrays correspond to objects in the network. + The entries corresponding to the PI and objects with trivial covers are NULL. + The number of extracted covers (not exceeding p->nNodesExt) is returned. + Two other things are important for the correct operation of this procedure: + (1) The input covers do not have duplicated fanins and are SCC-free. + (2) The fanins array contains the numbers of the fanin objects.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_FastExtract( Fxu_Data_t * pData ) +{ + Fxu_Matrix * p; + Fxu_Single * pSingle; + Fxu_Double * pDouble; + int Weight1, Weight2, Weight3; + int Counter = 0; + + s_MemoryTotal = 0; + s_MemoryPeak = 0; + + // create the matrix + p = Fxu_CreateMatrix( pData ); + if ( p == NULL ) + return -1; +// if ( pData->fVerbose ) +// printf( "Memory usage after construction: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak ); +//Fxu_MatrixPrint( NULL, p ); + + if ( pData->fOnlyS ) + { + pData->nNodesNew = 0; + do + { + Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ); + if ( pData->fVerbose ) + printf( "Div %5d : Best single = %5d.\r", Counter++, Weight1 ); + if ( Weight1 > 0 || Weight1 == 0 && pData->fUse0 ) + Fxu_UpdateSingle( p ); + else + break; + } + while ( ++pData->nNodesNew < pData->nNodesExt ); + } + else if ( pData->fOnlyD ) + { + pData->nNodesNew = 0; + do + { + Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); + if ( pData->fVerbose ) + printf( "Div %5d : Best double = %5d.\r", Counter++, Weight2 ); + if ( Weight2 > 0 || Weight2 == 0 && pData->fUse0 ) + Fxu_UpdateDouble( p ); + else + break; + } + while ( ++pData->nNodesNew < pData->nNodesExt ); + } + else if ( !pData->fUseCompl ) + { + pData->nNodesNew = 0; + do + { + Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ); + Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); + + if ( pData->fVerbose ) + printf( "Div %5d : Best double = %5d. Best single = %5d.\r", Counter++, Weight2, Weight1 ); +//Fxu_Select( p, &pSingle, &pDouble ); + + if ( Weight1 >= Weight2 ) + { + if ( Weight1 > 0 || Weight1 == 0 && pData->fUse0 ) + Fxu_UpdateSingle( p ); + else + break; + } + else + { + if ( Weight2 > 0 || Weight2 == 0 && pData->fUse0 ) + Fxu_UpdateDouble( p ); + else + break; + } + } + while ( ++pData->nNodesNew < pData->nNodesExt ); + } + else + { // use the complement + pData->nNodesNew = 0; + do + { + Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ); + Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); + + // select the best single and double + Weight3 = Fxu_Select( p, &pSingle, &pDouble ); + if ( pData->fVerbose ) + printf( "Div %5d : Best double = %5d. Best single = %5d. Best complement = %5d.\r", + Counter++, Weight2, Weight1, Weight3 ); + + if ( Weight3 > 0 || Weight3 == 0 && pData->fUse0 ) + Fxu_Update( p, pSingle, pDouble ); + else + break; + } + while ( ++pData->nNodesNew < pData->nNodesExt ); + } + + if ( pData->fVerbose ) + printf( "Total single = %3d. Total double = %3d. Total compl = %3d. \n", + p->nDivs1, p->nDivs2, p->nDivs3 ); + + // create the new covers + if ( pData->nNodesNew ) + Fxu_CreateCovers( p, pData ); + Fxu_MatrixDelete( p ); +// printf( "Memory usage after deallocation: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak ); + if ( pData->nNodesNew == pData->nNodesExt ) + printf( "Warning: The limit on the number of extracted divisors has been reached.\n" ); + return pData->nNodesNew; +} + + +/**Function************************************************************* + + Synopsis [Unmarks the cubes in the ring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixRingCubesUnmark( Fxu_Matrix * p ) +{ + Fxu_Cube * pCube, * pCube2; + // unmark the cubes + Fxu_MatrixForEachCubeInRingSafe( p, pCube, pCube2 ) + pCube->pOrder = NULL; + Fxu_MatrixRingCubesReset( p ); +} + + +/**Function************************************************************* + + Synopsis [Unmarks the vars in the ring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p ) +{ + Fxu_Var * pVar, * pVar2; + // unmark the vars + Fxu_MatrixForEachVarInRingSafe( p, pVar, pVar2 ) + pVar->pOrder = NULL; + Fxu_MatrixRingVarsReset( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Fxu_MemFetch( Fxu_Matrix * p, int nBytes ) +{ + s_MemoryTotal += nBytes; + if ( s_MemoryPeak < s_MemoryTotal ) + s_MemoryPeak = s_MemoryTotal; +// return malloc( nBytes ); + return Extra_MmFixedEntryFetch( p->pMemMan ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MemRecycle( Fxu_Matrix * p, char * pItem, int nBytes ) +{ + s_MemoryTotal -= nBytes; +// free( pItem ); + Extra_MmFixedEntryRecycle( p->pMemMan, pItem ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/fxu/fxu.h b/abc70930/src/opt/fxu/fxu.h new file mode 100644 index 00000000..e6d0b69e --- /dev/null +++ b/abc70930/src/opt/fxu/fxu.h @@ -0,0 +1,93 @@ +/**CFile**************************************************************** + + FileName [fxu.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [External declarations of fast extract for unate covers.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxu.h,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __FXU_H__ +#define __FXU_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifndef __cplusplus +#ifndef bool +#define bool int +#endif +#endif + +typedef struct FxuDataStruct Fxu_Data_t; + +// structure for the FX input/output data +struct FxuDataStruct +{ + // user specified parameters + bool fOnlyS; // set to 1 to have only single-cube divs + bool fOnlyD; // set to 1 to have only double-cube divs + bool fUse0; // set to 1 to have 0-weight also extracted + bool fUseCompl; // set to 1 to have complement taken into account + bool fVerbose; // set to 1 to have verbose output + int nNodesExt; // the number of divisors to extract + int nSingleMax; // the max number of single-cube divisors to consider + int nPairsMax; // the max number of double-cube divisors to consider + // the input information + Vec_Ptr_t * vSops; // the SOPs for each node in the network + Vec_Ptr_t * vFanins; // the fanins of each node in the network + // output information + Vec_Ptr_t * vSopsNew; // the SOPs for each node in the network after extraction + Vec_Ptr_t * vFaninsNew; // the fanins of each node in the network after extraction + // the SOP manager + Extra_MmFlex_t * pManSop; + // statistics + int nNodesOld; // the old number of nodes + int nNodesNew; // the number of divisors actually extracted +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*===== fxu.c ==========================================================*/ +extern int Fxu_FastExtract( Fxu_Data_t * pData ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/fxu/fxuCreate.c b/abc70930/src/opt/fxu/fxuCreate.c new file mode 100644 index 00000000..55026b27 --- /dev/null +++ b/abc70930/src/opt/fxu/fxuCreate.c @@ -0,0 +1,431 @@ +/**CFile**************************************************************** + + FileName [fxuCreate.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Create matrix from covers and covers from matrix.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuCreate.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fxuInt.h" +#include "fxu.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder ); +static int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY ); +static void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext ); +static Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode ); +static int * s_pLits; + +extern int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the sparse matrix from the array of SOPs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ) +{ + Fxu_Matrix * p; + Fxu_Var * pVar; + Fxu_Cube * pCubeFirst, * pCubeNew; + Fxu_Cube * pCube1, * pCube2; + Vec_Int_t * vFanins; + char * pSopCover; + char * pSopCube; + int * pOrder, nBitsMax; + int i, v, c; + int nCubesTotal; + int nPairsTotal; + int nPairsStore; + int nCubes; + int iCube, iPair; + int nFanins; + + // collect all sorts of statistics + nCubesTotal = 0; + nPairsTotal = 0; + nPairsStore = 0; + nBitsMax = -1; + for ( i = 0; i < pData->nNodesOld; i++ ) + if ( pSopCover = pData->vSops->pArray[i] ) + { + nCubes = Abc_SopGetCubeNum( pSopCover ); + nFanins = Abc_SopGetVarNum( pSopCover ); + assert( nFanins > 1 && nCubes > 0 ); + + nCubesTotal += nCubes; + nPairsTotal += nCubes * (nCubes - 1) / 2; + nPairsStore += nCubes * nCubes; + if ( nBitsMax < nFanins ) + nBitsMax = nFanins; + } + if ( nBitsMax <= 0 ) + { + printf( "The current network does not have SOPs to perform extraction.\n" ); + return NULL; + } + + if ( nPairsStore > 50000000 ) + { + printf( "The problem is too large to be solved by \"fxu\" (%d cubes and %d cube pairs)\n", nCubesTotal, nPairsStore ); + return NULL; + } + + // start the matrix + p = Fxu_MatrixAllocate(); + // create the column labels + p->ppVars = ALLOC( Fxu_Var *, 2 * (pData->nNodesOld + pData->nNodesExt) ); + for ( i = 0; i < 2 * pData->nNodesOld; i++ ) + p->ppVars[i] = Fxu_MatrixAddVar( p ); + + // allocate storage for all cube pairs at once + p->pppPairs = ALLOC( Fxu_Pair **, nCubesTotal + 100 ); + p->ppPairs = ALLOC( Fxu_Pair *, nPairsStore + 100 ); + memset( p->ppPairs, 0, sizeof(Fxu_Pair *) * nPairsStore ); + iCube = 0; + iPair = 0; + for ( i = 0; i < pData->nNodesOld; i++ ) + if ( pSopCover = pData->vSops->pArray[i] ) + { + // get the number of cubes + nCubes = Abc_SopGetCubeNum( pSopCover ); + // get the new var in the matrix + pVar = p->ppVars[2*i+1]; + // assign the pair storage + pVar->nCubes = nCubes; + if ( nCubes > 0 ) + { + pVar->ppPairs = p->pppPairs + iCube; + pVar->ppPairs[0] = p->ppPairs + iPair; + for ( v = 1; v < nCubes; v++ ) + pVar->ppPairs[v] = pVar->ppPairs[v-1] + nCubes; + } + // update + iCube += nCubes; + iPair += nCubes * nCubes; + } + assert( iCube == nCubesTotal ); + assert( iPair == nPairsStore ); + + + // allocate room for the reordered literals + pOrder = ALLOC( int, nBitsMax ); + // create the rows + for ( i = 0; i < pData->nNodesOld; i++ ) + if ( pSopCover = pData->vSops->pArray[i] ) + { + // get the new var in the matrix + pVar = p->ppVars[2*i+1]; + // here we sort the literals of the cover + // in the increasing order of the numbers of the corresponding nodes + // because literals should be added to the matrix in this order + vFanins = pData->vFanins->pArray[i]; + s_pLits = vFanins->pArray; + // start the variable order + nFanins = Abc_SopGetVarNum( pSopCover ); + for ( v = 0; v < nFanins; v++ ) + pOrder[v] = v; + // reorder the fanins + qsort( (void *)pOrder, nFanins, sizeof(int),(int (*)(const void *, const void *))Fxu_CreateMatrixLitCompare); + assert( s_pLits[ pOrder[0] ] < s_pLits[ pOrder[nFanins-1] ] ); + // create the corresponding cubes in the matrix + pCubeFirst = NULL; + c = 0; + Abc_SopForEachCube( pSopCover, nFanins, pSopCube ) + { + // create the cube + pCubeNew = Fxu_MatrixAddCube( p, pVar, c++ ); + Fxu_CreateMatrixAddCube( p, pCubeNew, pSopCube, vFanins, pOrder ); + if ( pCubeFirst == NULL ) + pCubeFirst = pCubeNew; + pCubeNew->pFirst = pCubeFirst; + } + // set the first cube of this var + pVar->pFirst = pCubeFirst; + // create the divisors without preprocessing + if ( nPairsTotal <= pData->nPairsMax ) + { + for ( pCube1 = pCubeFirst; pCube1; pCube1 = pCube1->pNext ) + for ( pCube2 = pCube1? pCube1->pNext: NULL; pCube2; pCube2 = pCube2->pNext ) + Fxu_MatrixAddDivisor( p, pCube1, pCube2 ); + } + } + FREE( pOrder ); + + // consider the case when cube pairs should be preprocessed + // before adding them to the set of divisors +// if ( pData->fVerbose ) +// printf( "The total number of cube pairs is %d.\n", nPairsTotal ); + if ( nPairsTotal > 10000000 ) + { + printf( "The total number of cube pairs of the network is more than 10,000,000.\n" ); + printf( "Command \"fx\" takes a long time to run in such cases. It is suggested\n" ); + printf( "that the user changes the network by reducing the size of logic node and\n" ); + printf( "consequently the number of cube pairs to be processed by this command.\n" ); + printf( "One way to achieve this is to run the commands \"st; multi -m -F \"\n" ); + printf( "as a proprocessing step, while selecting as approapriate.\n" ); + return NULL; + } + if ( nPairsTotal > pData->nPairsMax ) + if ( !Fxu_PreprocessCubePairs( p, pData->vSops, nPairsTotal, pData->nPairsMax ) ) + return NULL; +// if ( pData->fVerbose ) +// printf( "Only %d best cube pairs will be used by the fast extract command.\n", pData->nPairsMax ); + + // add the var pairs to the heap + Fxu_MatrixComputeSingles( p, pData->fUse0, pData->nSingleMax ); + + // print stats + if ( pData->fVerbose ) + { + double Density; + Density = ((double)p->nEntries) / p->lVars.nItems / p->lCubes.nItems; + fprintf( stdout, "Matrix: [vars x cubes] = [%d x %d] ", + p->lVars.nItems, p->lCubes.nItems ); + fprintf( stdout, "Lits = %d Density = %.5f%%\n", + p->nEntries, Density ); + fprintf( stdout, "1-cube divs = %6d. (Total = %6d) ", p->lSingles.nItems, p->nSingleTotal ); + fprintf( stdout, "2-cube divs = %6d. (Total = %6d)", p->nDivsTotal, nPairsTotal ); + fprintf( stdout, "\n" ); + } +// Fxu_MatrixPrint( stdout, p ); + return p; +} + +/**Function************************************************************* + + Synopsis [Adds one cube with literals to the matrix.] + + Description [Create the cube and literals in the matrix corresponding + to the given cube in the SOP cover. Co-singleton transform is performed here.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder ) +{ + Fxu_Var * pVar; + int Value, i; + // add literals to the matrix + Abc_CubeForEachVar( pSopCube, Value, i ) + { + Value = pSopCube[pOrder[i]]; + if ( Value == '0' ) + { + pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] + 1 ]; // CST + Fxu_MatrixAddLiteral( p, pCube, pVar ); + } + else if ( Value == '1' ) + { + pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] ]; // CST + Fxu_MatrixAddLiteral( p, pCube, pVar ); + } + } +} + + +/**Function************************************************************* + + Synopsis [Creates the new array of Sop covers from the sparse matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_CreateCovers( Fxu_Matrix * p, Fxu_Data_t * pData ) +{ + Fxu_Cube * pCube, * pCubeFirst, * pCubeNext; + char * pSopCover; + int iNode, n; + + // get the first cube of the first internal node + pCubeFirst = Fxu_CreateCoversFirstCube( p, pData, 0 ); + + // go through the internal nodes + for ( n = 0; n < pData->nNodesOld; n++ ) + if ( pSopCover = pData->vSops->pArray[n] ) + { + // get the number of this node + iNode = n; + // get the next first cube + pCubeNext = Fxu_CreateCoversFirstCube( p, pData, iNode + 1 ); + // check if there any new variables in these cubes + for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) + if ( pCube->lLits.pTail && pCube->lLits.pTail->iVar >= 2 * pData->nNodesOld ) + break; + if ( pCube != pCubeNext ) + Fxu_CreateCoversNode( p, pData, iNode, pCubeFirst, pCubeNext ); + // update the first cube + pCubeFirst = pCubeNext; + } + + // add the covers for the extracted nodes + for ( n = 0; n < pData->nNodesNew; n++ ) + { + // get the number of this node + iNode = pData->nNodesOld + n; + // get the next first cube + pCubeNext = Fxu_CreateCoversFirstCube( p, pData, iNode + 1 ); + // the node should be added + Fxu_CreateCoversNode( p, pData, iNode, pCubeFirst, pCubeNext ); + // update the first cube + pCubeFirst = pCubeNext; + } +} + +/**Function************************************************************* + + Synopsis [Create Sop covers for one node that has changed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext ) +{ + Vec_Int_t * vInputsNew; + char * pSopCover, * pSopCube; + Fxu_Var * pVar; + Fxu_Cube * pCube; + Fxu_Lit * pLit; + int iNum, nCubes, v; + + // collect positive polarity variable in the cubes between pCubeFirst and pCubeNext + Fxu_MatrixRingVarsStart( p ); + for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) + for ( pLit = pCube->lLits.pHead; pLit; pLit = pLit->pHNext ) + { + pVar = p->ppVars[ 2 * (pLit->pVar->iVar/2) + 1 ]; + if ( pVar->pOrder == NULL ) + Fxu_MatrixRingVarsAdd( p, pVar ); + } + Fxu_MatrixRingVarsStop( p ); + + // collect the variable numbers + vInputsNew = Vec_IntAlloc( 4 ); + Fxu_MatrixForEachVarInRing( p, pVar ) + Vec_IntPush( vInputsNew, pVar->iVar / 2 ); + Fxu_MatrixRingVarsUnmark( p ); + + // sort the vars by their number + Vec_IntSort( vInputsNew, 0 ); + + // mark the vars with their numbers in the sorted array + for ( v = 0; v < vInputsNew->nSize; v++ ) + { + p->ppVars[ 2 * vInputsNew->pArray[v] + 0 ]->lLits.nItems = v; // hack - reuse lLits.nItems + p->ppVars[ 2 * vInputsNew->pArray[v] + 1 ]->lLits.nItems = v; // hack - reuse lLits.nItems + } + + // count the number of cubes + nCubes = 0; + for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) + if ( pCube->lLits.nItems ) + nCubes++; + + // allocate room for the new cover + pSopCover = Abc_SopStart( pData->pManSop, nCubes, vInputsNew->nSize ); + // set the correct polarity of the cover + if ( iNode < pData->nNodesOld && Abc_SopGetPhase( pData->vSops->pArray[iNode] ) == 0 ) + Abc_SopComplement( pSopCover ); + + // add the cubes + nCubes = 0; + for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) + { + if ( pCube->lLits.nItems == 0 ) + continue; + // get hold of the SOP cube + pSopCube = pSopCover + nCubes * (vInputsNew->nSize + 3); + // insert literals + for ( pLit = pCube->lLits.pHead; pLit; pLit = pLit->pHNext ) + { + iNum = pLit->pVar->lLits.nItems; // hack - reuse lLits.nItems + assert( iNum < vInputsNew->nSize ); + if ( pLit->pVar->iVar / 2 < pData->nNodesOld ) + pSopCube[iNum] = (pLit->pVar->iVar & 1)? '0' : '1'; // reverse CST + else + pSopCube[iNum] = (pLit->pVar->iVar & 1)? '1' : '0'; // no CST + } + // count the cube + nCubes++; + } + assert( nCubes == Abc_SopGetCubeNum(pSopCover) ); + + // set the new cover and the array of fanins + pData->vSopsNew->pArray[iNode] = pSopCover; + pData->vFaninsNew->pArray[iNode] = vInputsNew; +} + + +/**Function************************************************************* + + Synopsis [Adds the var to storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iVar ) +{ + int v; + for ( v = iVar; v < pData->nNodesOld + pData->nNodesNew; v++ ) + if ( p->ppVars[ 2*v + 1 ]->pFirst ) + return p->ppVars[ 2*v + 1 ]->pFirst; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Compares the vars by their number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY ) +{ + return s_pLits[*ptrX] - s_pLits[*ptrY]; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/opt/fxu/fxuHeapD.c b/abc70930/src/opt/fxu/fxuHeapD.c new file mode 100644 index 00000000..c81ad818 --- /dev/null +++ b/abc70930/src/opt/fxu/fxuHeapD.c @@ -0,0 +1,445 @@ +/**CFile**************************************************************** + + FileName [fxuHeapD.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [The priority queue for double cube divisors.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuHeapD.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fxuInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define FXU_HEAP_DOUBLE_WEIGHT(pDiv) ((pDiv)->Weight) +#define FXU_HEAP_DOUBLE_CURRENT(p, pDiv) ((p)->pTree[(pDiv)->HNum]) +#define FXU_HEAP_DOUBLE_PARENT_EXISTS(p, pDiv) ((pDiv)->HNum > 1) +#define FXU_HEAP_DOUBLE_CHILD1_EXISTS(p, pDiv) (((pDiv)->HNum << 1) <= p->nItems) +#define FXU_HEAP_DOUBLE_CHILD2_EXISTS(p, pDiv) ((((pDiv)->HNum << 1)+1) <= p->nItems) +#define FXU_HEAP_DOUBLE_PARENT(p, pDiv) ((p)->pTree[(pDiv)->HNum >> 1]) +#define FXU_HEAP_DOUBLE_CHILD1(p, pDiv) ((p)->pTree[(pDiv)->HNum << 1]) +#define FXU_HEAP_DOUBLE_CHILD2(p, pDiv) ((p)->pTree[((pDiv)->HNum << 1)+1]) +#define FXU_HEAP_DOUBLE_ASSERT(p, pDiv) assert( (pDiv)->HNum >= 1 && (pDiv)->HNum <= p->nItemsAlloc ) + +static void Fxu_HeapDoubleResize( Fxu_HeapDouble * p ); +static void Fxu_HeapDoubleSwap( Fxu_Double ** pDiv1, Fxu_Double ** pDiv2 ); +static void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv ); +static void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_HeapDouble * Fxu_HeapDoubleStart() +{ + Fxu_HeapDouble * p; + p = ALLOC( Fxu_HeapDouble, 1 ); + memset( p, 0, sizeof(Fxu_HeapDouble) ); + p->nItems = 0; + p->nItemsAlloc = 10000; + p->pTree = ALLOC( Fxu_Double *, p->nItemsAlloc + 1 ); + p->pTree[0] = NULL; + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapDoubleResize( Fxu_HeapDouble * p ) +{ + p->nItemsAlloc *= 2; + p->pTree = REALLOC( Fxu_Double *, p->pTree, p->nItemsAlloc + 1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapDoubleStop( Fxu_HeapDouble * p ) +{ + free( p->pTree ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapDoublePrint( FILE * pFile, Fxu_HeapDouble * p ) +{ + Fxu_Double * pDiv; + int Counter = 1; + int Degree = 1; + + Fxu_HeapDoubleCheck( p ); + fprintf( pFile, "The contents of the heap:\n" ); + fprintf( pFile, "Level %d: ", Degree ); + Fxu_HeapDoubleForEachItem( p, pDiv ) + { + assert( Counter == p->pTree[Counter]->HNum ); + fprintf( pFile, "%2d=%3d ", Counter, FXU_HEAP_DOUBLE_WEIGHT(p->pTree[Counter]) ); + if ( ++Counter == (1 << Degree) ) + { + fprintf( pFile, "\n" ); + Degree++; + fprintf( pFile, "Level %d: ", Degree ); + } + } + fprintf( pFile, "\n" ); + fprintf( pFile, "End of the heap printout.\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapDoubleCheck( Fxu_HeapDouble * p ) +{ + Fxu_Double * pDiv; + Fxu_HeapDoubleForEachItem( p, pDiv ) + { + assert( pDiv->HNum == p->i ); + Fxu_HeapDoubleCheckOne( p, pDiv ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapDoubleCheckOne( Fxu_HeapDouble * p, Fxu_Double * pDiv ) +{ + int Weight1, Weight2; + if ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,pDiv) ) + { + Weight1 = FXU_HEAP_DOUBLE_WEIGHT(pDiv); + Weight2 = FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD1(p,pDiv) ); + assert( Weight1 >= Weight2 ); + } + if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,pDiv) ) + { + Weight1 = FXU_HEAP_DOUBLE_WEIGHT(pDiv); + Weight2 = FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD2(p,pDiv) ); + assert( Weight1 >= Weight2 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapDoubleInsert( Fxu_HeapDouble * p, Fxu_Double * pDiv ) +{ + if ( p->nItems == p->nItemsAlloc ) + Fxu_HeapDoubleResize( p ); + // put the last entry to the last place and move up + p->pTree[++p->nItems] = pDiv; + pDiv->HNum = p->nItems; + // move the last entry up if necessary + Fxu_HeapDoubleMoveUp( p, pDiv ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapDoubleUpdate( Fxu_HeapDouble * p, Fxu_Double * pDiv ) +{ +//printf( "Updating divisor %d.\n", pDiv->Num ); + + FXU_HEAP_DOUBLE_ASSERT(p,pDiv); + if ( FXU_HEAP_DOUBLE_PARENT_EXISTS(p,pDiv) && + FXU_HEAP_DOUBLE_WEIGHT(pDiv) > FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_PARENT(p,pDiv) ) ) + Fxu_HeapDoubleMoveUp( p, pDiv ); + else if ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,pDiv) && + FXU_HEAP_DOUBLE_WEIGHT(pDiv) < FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD1(p,pDiv) ) ) + Fxu_HeapDoubleMoveDn( p, pDiv ); + else if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,pDiv) && + FXU_HEAP_DOUBLE_WEIGHT(pDiv) < FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD2(p,pDiv) ) ) + Fxu_HeapDoubleMoveDn( p, pDiv ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapDoubleDelete( Fxu_HeapDouble * p, Fxu_Double * pDiv ) +{ + FXU_HEAP_DOUBLE_ASSERT(p,pDiv); + // put the last entry to the deleted place + // decrement the number of entries + p->pTree[pDiv->HNum] = p->pTree[p->nItems--]; + p->pTree[pDiv->HNum]->HNum = pDiv->HNum; + // move the top entry down if necessary + Fxu_HeapDoubleUpdate( p, p->pTree[pDiv->HNum] ); + pDiv->HNum = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Double * Fxu_HeapDoubleReadMax( Fxu_HeapDouble * p ) +{ + if ( p->nItems == 0 ) + return NULL; + return p->pTree[1]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Double * Fxu_HeapDoubleGetMax( Fxu_HeapDouble * p ) +{ + Fxu_Double * pDiv; + if ( p->nItems == 0 ) + return NULL; + // prepare the return value + pDiv = p->pTree[1]; + pDiv->HNum = 0; + // put the last entry on top + // decrement the number of entries + p->pTree[1] = p->pTree[p->nItems--]; + p->pTree[1]->HNum = 1; + // move the top entry down if necessary + Fxu_HeapDoubleMoveDn( p, p->pTree[1] ); + return pDiv; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_HeapDoubleReadMaxWeight( Fxu_HeapDouble * p ) +{ + if ( p->nItems == 0 ) + return -1; + else + return FXU_HEAP_DOUBLE_WEIGHT(p->pTree[1]); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapDoubleSwap( Fxu_Double ** pDiv1, Fxu_Double ** pDiv2 ) +{ + Fxu_Double * pDiv; + int Temp; + pDiv = *pDiv1; + *pDiv1 = *pDiv2; + *pDiv2 = pDiv; + Temp = (*pDiv1)->HNum; + (*pDiv1)->HNum = (*pDiv2)->HNum; + (*pDiv2)->HNum = Temp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv ) +{ + Fxu_Double ** ppDiv, ** ppPar; + ppDiv = &FXU_HEAP_DOUBLE_CURRENT(p, pDiv); + while ( FXU_HEAP_DOUBLE_PARENT_EXISTS(p,*ppDiv) ) + { + ppPar = &FXU_HEAP_DOUBLE_PARENT(p,*ppDiv); + if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) > FXU_HEAP_DOUBLE_WEIGHT(*ppPar) ) + { + Fxu_HeapDoubleSwap( ppDiv, ppPar ); + ppDiv = ppPar; + } + else + break; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv ) +{ + Fxu_Double ** ppChild1, ** ppChild2, ** ppDiv; + ppDiv = &FXU_HEAP_DOUBLE_CURRENT(p, pDiv); + while ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,*ppDiv) ) + { // if Child1 does not exist, Child2 also does not exists + + // get the children + ppChild1 = &FXU_HEAP_DOUBLE_CHILD1(p,*ppDiv); + if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,*ppDiv) ) + { + ppChild2 = &FXU_HEAP_DOUBLE_CHILD2(p,*ppDiv); + + // consider two cases + if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) && + FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild2) ) + { // Div is larger than both, skip + break; + } + else + { // Div is smaller than one of them, then swap it with larger + if ( FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild2) ) + { + Fxu_HeapDoubleSwap( ppDiv, ppChild1 ); + // update the pointer + ppDiv = ppChild1; + } + else + { + Fxu_HeapDoubleSwap( ppDiv, ppChild2 ); + // update the pointer + ppDiv = ppChild2; + } + } + } + else // Child2 does not exist + { + // consider two cases + if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) ) + { // Div is larger than Child1, skip + break; + } + else + { // Div is smaller than Child1, then swap them + Fxu_HeapDoubleSwap( ppDiv, ppChild1 ); + // update the pointer + ppDiv = ppChild1; + } + } + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/fxu/fxuHeapS.c b/abc70930/src/opt/fxu/fxuHeapS.c new file mode 100644 index 00000000..eaca8363 --- /dev/null +++ b/abc70930/src/opt/fxu/fxuHeapS.c @@ -0,0 +1,444 @@ +/**CFile**************************************************************** + + FileName [fxuHeapS.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [The priority queue for variables.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuHeapS.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fxuInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define FXU_HEAP_SINGLE_WEIGHT(pSingle) ((pSingle)->Weight) +#define FXU_HEAP_SINGLE_CURRENT(p, pSingle) ((p)->pTree[(pSingle)->HNum]) +#define FXU_HEAP_SINGLE_PARENT_EXISTS(p, pSingle) ((pSingle)->HNum > 1) +#define FXU_HEAP_SINGLE_CHILD1_EXISTS(p, pSingle) (((pSingle)->HNum << 1) <= p->nItems) +#define FXU_HEAP_SINGLE_CHILD2_EXISTS(p, pSingle) ((((pSingle)->HNum << 1)+1) <= p->nItems) +#define FXU_HEAP_SINGLE_PARENT(p, pSingle) ((p)->pTree[(pSingle)->HNum >> 1]) +#define FXU_HEAP_SINGLE_CHILD1(p, pSingle) ((p)->pTree[(pSingle)->HNum << 1]) +#define FXU_HEAP_SINGLE_CHILD2(p, pSingle) ((p)->pTree[((pSingle)->HNum << 1)+1]) +#define FXU_HEAP_SINGLE_ASSERT(p, pSingle) assert( (pSingle)->HNum >= 1 && (pSingle)->HNum <= p->nItemsAlloc ) + +static void Fxu_HeapSingleResize( Fxu_HeapSingle * p ); +static void Fxu_HeapSingleSwap( Fxu_Single ** pSingle1, Fxu_Single ** pSingle2 ); +static void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle ); +static void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_HeapSingle * Fxu_HeapSingleStart() +{ + Fxu_HeapSingle * p; + p = ALLOC( Fxu_HeapSingle, 1 ); + memset( p, 0, sizeof(Fxu_HeapSingle) ); + p->nItems = 0; + p->nItemsAlloc = 2000; + p->pTree = ALLOC( Fxu_Single *, p->nItemsAlloc + 10 ); + p->pTree[0] = NULL; + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapSingleResize( Fxu_HeapSingle * p ) +{ + p->nItemsAlloc *= 2; + p->pTree = REALLOC( Fxu_Single *, p->pTree, p->nItemsAlloc + 10 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapSingleStop( Fxu_HeapSingle * p ) +{ + int i; + i = 0; + free( p->pTree ); + i = 1; + free( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapSinglePrint( FILE * pFile, Fxu_HeapSingle * p ) +{ + Fxu_Single * pSingle; + int Counter = 1; + int Degree = 1; + + Fxu_HeapSingleCheck( p ); + fprintf( pFile, "The contents of the heap:\n" ); + fprintf( pFile, "Level %d: ", Degree ); + Fxu_HeapSingleForEachItem( p, pSingle ) + { + assert( Counter == p->pTree[Counter]->HNum ); + fprintf( pFile, "%2d=%3d ", Counter, FXU_HEAP_SINGLE_WEIGHT(p->pTree[Counter]) ); + if ( ++Counter == (1 << Degree) ) + { + fprintf( pFile, "\n" ); + Degree++; + fprintf( pFile, "Level %d: ", Degree ); + } + } + fprintf( pFile, "\n" ); + fprintf( pFile, "End of the heap printout.\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapSingleCheck( Fxu_HeapSingle * p ) +{ + Fxu_Single * pSingle; + Fxu_HeapSingleForEachItem( p, pSingle ) + { + assert( pSingle->HNum == p->i ); + Fxu_HeapSingleCheckOne( p, pSingle ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapSingleCheckOne( Fxu_HeapSingle * p, Fxu_Single * pSingle ) +{ + int Weight1, Weight2; + if ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,pSingle) ) + { + Weight1 = FXU_HEAP_SINGLE_WEIGHT(pSingle); + Weight2 = FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD1(p,pSingle) ); + assert( Weight1 >= Weight2 ); + } + if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,pSingle) ) + { + Weight1 = FXU_HEAP_SINGLE_WEIGHT(pSingle); + Weight2 = FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD2(p,pSingle) ); + assert( Weight1 >= Weight2 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapSingleInsert( Fxu_HeapSingle * p, Fxu_Single * pSingle ) +{ + if ( p->nItems == p->nItemsAlloc ) + Fxu_HeapSingleResize( p ); + // put the last entry to the last place and move up + p->pTree[++p->nItems] = pSingle; + pSingle->HNum = p->nItems; + // move the last entry up if necessary + Fxu_HeapSingleMoveUp( p, pSingle ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapSingleUpdate( Fxu_HeapSingle * p, Fxu_Single * pSingle ) +{ + FXU_HEAP_SINGLE_ASSERT(p,pSingle); + if ( FXU_HEAP_SINGLE_PARENT_EXISTS(p,pSingle) && + FXU_HEAP_SINGLE_WEIGHT(pSingle) > FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_PARENT(p,pSingle) ) ) + Fxu_HeapSingleMoveUp( p, pSingle ); + else if ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,pSingle) && + FXU_HEAP_SINGLE_WEIGHT(pSingle) < FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD1(p,pSingle) ) ) + Fxu_HeapSingleMoveDn( p, pSingle ); + else if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,pSingle) && + FXU_HEAP_SINGLE_WEIGHT(pSingle) < FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD2(p,pSingle) ) ) + Fxu_HeapSingleMoveDn( p, pSingle ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapSingleDelete( Fxu_HeapSingle * p, Fxu_Single * pSingle ) +{ + int Place = pSingle->HNum; + FXU_HEAP_SINGLE_ASSERT(p,pSingle); + // put the last entry to the deleted place + // decrement the number of entries + p->pTree[Place] = p->pTree[p->nItems--]; + p->pTree[Place]->HNum = Place; + // move the top entry down if necessary + Fxu_HeapSingleUpdate( p, p->pTree[Place] ); + pSingle->HNum = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p ) +{ + if ( p->nItems == 0 ) + return NULL; + return p->pTree[1]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p ) +{ + Fxu_Single * pSingle; + if ( p->nItems == 0 ) + return NULL; + // prepare the return value + pSingle = p->pTree[1]; + pSingle->HNum = 0; + // put the last entry on top + // decrement the number of entries + p->pTree[1] = p->pTree[p->nItems--]; + p->pTree[1]->HNum = 1; + // move the top entry down if necessary + Fxu_HeapSingleMoveDn( p, p->pTree[1] ); + return pSingle; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p ) +{ + if ( p->nItems == 0 ) + return -1; + return FXU_HEAP_SINGLE_WEIGHT(p->pTree[1]); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapSingleSwap( Fxu_Single ** pSingle1, Fxu_Single ** pSingle2 ) +{ + Fxu_Single * pSingle; + int Temp; + pSingle = *pSingle1; + *pSingle1 = *pSingle2; + *pSingle2 = pSingle; + Temp = (*pSingle1)->HNum; + (*pSingle1)->HNum = (*pSingle2)->HNum; + (*pSingle2)->HNum = Temp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle ) +{ + Fxu_Single ** ppSingle, ** ppPar; + ppSingle = &FXU_HEAP_SINGLE_CURRENT(p, pSingle); + while ( FXU_HEAP_SINGLE_PARENT_EXISTS(p,*ppSingle) ) + { + ppPar = &FXU_HEAP_SINGLE_PARENT(p,*ppSingle); + if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) > FXU_HEAP_SINGLE_WEIGHT(*ppPar) ) + { + Fxu_HeapSingleSwap( ppSingle, ppPar ); + ppSingle = ppPar; + } + else + break; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle ) +{ + Fxu_Single ** ppChild1, ** ppChild2, ** ppSingle; + ppSingle = &FXU_HEAP_SINGLE_CURRENT(p, pSingle); + while ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,*ppSingle) ) + { // if Child1 does not exist, Child2 also does not exists + + // get the children + ppChild1 = &FXU_HEAP_SINGLE_CHILD1(p,*ppSingle); + if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,*ppSingle) ) + { + ppChild2 = &FXU_HEAP_SINGLE_CHILD2(p,*ppSingle); + + // consider two cases + if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild1) && + FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild2) ) + { // Var is larger than both, skip + break; + } + else + { // Var is smaller than one of them, then swap it with larger + if ( FXU_HEAP_SINGLE_WEIGHT(*ppChild1) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild2) ) + { + Fxu_HeapSingleSwap( ppSingle, ppChild1 ); + // update the pointer + ppSingle = ppChild1; + } + else + { + Fxu_HeapSingleSwap( ppSingle, ppChild2 ); + // update the pointer + ppSingle = ppChild2; + } + } + } + else // Child2 does not exist + { + // consider two cases + if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild1) ) + { // Var is larger than Child1, skip + break; + } + else + { // Var is smaller than Child1, then swap them + Fxu_HeapSingleSwap( ppSingle, ppChild1 ); + // update the pointer + ppSingle = ppChild1; + } + } + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/opt/fxu/fxuInt.h b/abc70930/src/opt/fxu/fxuInt.h new file mode 100644 index 00000000..ea85cb79 --- /dev/null +++ b/abc70930/src/opt/fxu/fxuInt.h @@ -0,0 +1,539 @@ +/**CFile**************************************************************** + + FileName [fxuInt.h] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Internal declarations of fast extract for unate covers.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuInt.h,v 1.3 2003/04/10 05:42:44 donald Exp $] + +***********************************************************************/ + +#ifndef __FXU_INT_H__ +#define __FXU_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "extra.h" +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// uncomment this macro to switch to standard memory management +//#define USE_SYSTEM_MEMORY_MANAGEMENT + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + Here is an informal description of the FX data structure. + (1) The sparse matrix is filled with literals, associated with + cubes (row) and variables (columns). The matrix contains + all the cubes of all the nodes in the network. + (2) A cube is associated with + (a) its literals in the matrix, + (b) the output variable of the node, to which this cube belongs, + (3) A variable is associated with + (a) its literals in the matrix and + (b) the list of cube pairs in the cover, for which it is the output + (4) A cube pair is associated with two cubes and contains the counters + of literals in the base and in the cubes without the base + (5) A double-cube divisor is associated with list of all cube pairs + that produce it and its current weight (which is updated automatically + each time a new pair is added or an old pair is removed). + (6) A single-cube divisor is associated the pair of variables. +*/ + +// sparse matrix +typedef struct FxuMatrix Fxu_Matrix; // the sparse matrix + +// sparse matrix contents: cubes (rows), vars (columns), literals (entries) +typedef struct FxuCube Fxu_Cube; // one cube in the sparse matrix +typedef struct FxuVar Fxu_Var; // one literal in the sparse matrix +typedef struct FxuLit Fxu_Lit; // one entry in the sparse matrix + +// double cube divisors +typedef struct FxuPair Fxu_Pair; // the pair of cubes +typedef struct FxuDouble Fxu_Double; // the double-cube divisor +typedef struct FxuSingle Fxu_Single; // the two-literal single-cube divisor + +// various lists +typedef struct FxuListCube Fxu_ListCube; // the list of cubes +typedef struct FxuListVar Fxu_ListVar; // the list of literals +typedef struct FxuListLit Fxu_ListLit; // the list of entries +typedef struct FxuListPair Fxu_ListPair; // the list of pairs +typedef struct FxuListDouble Fxu_ListDouble; // the list of divisors +typedef struct FxuListSingle Fxu_ListSingle; // the list of single-cube divisors + +// various heaps +typedef struct FxuHeapDouble Fxu_HeapDouble; // the heap of divisors +typedef struct FxuHeapSingle Fxu_HeapSingle; // the heap of variables + + +// various lists + +// the list of cubes in the sparse matrix +struct FxuListCube +{ + Fxu_Cube * pHead; + Fxu_Cube * pTail; + int nItems; +}; + +// the list of literals in the sparse matrix +struct FxuListVar +{ + Fxu_Var * pHead; + Fxu_Var * pTail; + int nItems; +}; + +// the list of entries in the sparse matrix +struct FxuListLit +{ + Fxu_Lit * pHead; + Fxu_Lit * pTail; + int nItems; +}; + +// the list of cube pair in the sparse matrix +struct FxuListPair +{ + Fxu_Pair * pHead; + Fxu_Pair * pTail; + int nItems; +}; + +// the list of divisors in the sparse matrix +struct FxuListDouble +{ + Fxu_Double * pHead; + Fxu_Double * pTail; + int nItems; +}; + +// the list of divisors in the sparse matrix +struct FxuListSingle +{ + Fxu_Single * pHead; + Fxu_Single * pTail; + int nItems; +}; + + +// various heaps + +// the heap of double cube divisors by weight +struct FxuHeapDouble +{ + Fxu_Double ** pTree; + int nItems; + int nItemsAlloc; + int i; +}; + +// the heap of variable by their occurrence in the cubes +struct FxuHeapSingle +{ + Fxu_Single ** pTree; + int nItems; + int nItemsAlloc; + int i; +}; + + + +// sparse matrix +struct FxuMatrix // ~ 30 words +{ + // the cubes + Fxu_ListCube lCubes; // the double linked list of cubes + // the values (binary literals) + Fxu_ListVar lVars; // the double linked list of variables + Fxu_Var ** ppVars; // the array of variables + // the double cube divisors + Fxu_ListDouble * pTable; // the hash table of divisors + int nTableSize; // the hash table size + int nDivs; // the number of divisors in the table + int nDivsTotal; // the number of divisors in the table + Fxu_HeapDouble * pHeapDouble; // the heap of divisors by weight + // the single cube divisors + Fxu_ListSingle lSingles; // the linked list of single cube divisors + Fxu_HeapSingle * pHeapSingle; // the heap of variables by the number of literals in the matrix + int nWeightLimit;// the limit on weight of single cube divisors collected + int nSingleTotal;// the total number of single cube divisors + // storage for cube pairs + Fxu_Pair *** pppPairs; + Fxu_Pair ** ppPairs; + // temporary storage for cubes + Fxu_Cube * pOrderCubes; + Fxu_Cube ** ppTailCubes; + // temporary storage for variables + Fxu_Var * pOrderVars; + Fxu_Var ** ppTailVars; + // temporary storage for pairs + Vec_Ptr_t * vPairs; + // statistics + int nEntries; // the total number of entries in the sparse matrix + int nDivs1; // the single cube divisors taken + int nDivs2; // the double cube divisors taken + int nDivs3; // the double cube divisors with complement + // memory manager + Extra_MmFixed_t * pMemMan; // the memory manager for all small sized entries +}; + +// the cube in the sparse matrix +struct FxuCube // 9 words +{ + int iCube; // the number of this cube in the cover + Fxu_Cube * pFirst; // the pointer to the first cube of this cover + Fxu_Var * pVar; // the variable representing the output of the cover + Fxu_ListLit lLits; // the row in the table + Fxu_Cube * pPrev; // the previous cube + Fxu_Cube * pNext; // the next cube + Fxu_Cube * pOrder; // the specialized linked list of cubes +}; + +// the variable in the sparse matrix +struct FxuVar // 10 words +{ + int iVar; // the number of this variable + int nCubes; // the number of cubes assoc with this var + Fxu_Cube * pFirst; // the first cube assoc with this var + Fxu_Pair *** ppPairs; // the pairs of cubes assoc with this var + Fxu_ListLit lLits; // the column in the table + Fxu_Var * pPrev; // the previous variable + Fxu_Var * pNext; // the next variable + Fxu_Var * pOrder; // the specialized linked list of variables +}; + +// the literal entry in the sparse matrix +struct FxuLit // 8 words +{ + int iVar; // the number of this variable + int iCube; // the number of this cube + Fxu_Cube * pCube; // the cube of this literal + Fxu_Var * pVar; // the variable of this literal + Fxu_Lit * pHPrev; // prev lit in the cube + Fxu_Lit * pHNext; // next lit in the cube + Fxu_Lit * pVPrev; // prev lit of the var + Fxu_Lit * pVNext; // next lit of the var +}; + +// the cube pair +struct FxuPair // 10 words +{ + int nLits1; // the number of literals in the two cubes + int nLits2; // the number of literals in the two cubes + int nBase; // the number of literals in the base + Fxu_Double * pDiv; // the divisor of this pair + Fxu_Cube * pCube1; // the first cube of the pair + Fxu_Cube * pCube2; // the second cube of the pair + int iCube1; // the first cube of the pair + int iCube2; // the second cube of the pair + Fxu_Pair * pDPrev; // the previous pair in the divisor + Fxu_Pair * pDNext; // the next pair in the divisor +}; + +// the double cube divisor +struct FxuDouble // 10 words +{ + int Num; // the unique number of this divisor + int HNum; // the heap number of this divisor + int Weight; // the weight of this divisor + unsigned Key; // the hash key of this divisor + Fxu_ListPair lPairs; // the pairs of cubes, which produce this divisor + Fxu_Double * pPrev; // the previous divisor in the table + Fxu_Double * pNext; // the next divisor in the table + Fxu_Double * pOrder; // the specialized linked list of divisors +}; + +// the single cube divisor +struct FxuSingle // 7 words +{ + int Num; // the unique number of this divisor + int HNum; // the heap number of this divisor + int Weight; // the weight of this divisor + Fxu_Var * pVar1; // the first variable of the single-cube divisor + Fxu_Var * pVar2; // the second variable of the single-cube divisor + Fxu_Single * pPrev; // the previous divisor in the list + Fxu_Single * pNext; // the next divisor in the list +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// minimum/maximum +#define Fxu_Min( a, b ) ( ((a)<(b))? (a):(b) ) +#define Fxu_Max( a, b ) ( ((a)>(b))? (a):(b) ) + +// selection of the minimum/maximum cube in the pair +#define Fxu_PairMinCube( pPair ) (((pPair)->iCube1 < (pPair)->iCube2)? (pPair)->pCube1: (pPair)->pCube2) +#define Fxu_PairMaxCube( pPair ) (((pPair)->iCube1 > (pPair)->iCube2)? (pPair)->pCube1: (pPair)->pCube2) +#define Fxu_PairMinCubeInt( pPair ) (((pPair)->iCube1 < (pPair)->iCube2)? (pPair)->iCube1: (pPair)->iCube2) +#define Fxu_PairMaxCubeInt( pPair ) (((pPair)->iCube1 > (pPair)->iCube2)? (pPair)->iCube1: (pPair)->iCube2) + +// iterators + +#define Fxu_MatrixForEachCube( Matrix, Cube )\ + for ( Cube = (Matrix)->lCubes.pHead;\ + Cube;\ + Cube = Cube->pNext ) +#define Fxu_MatrixForEachCubeSafe( Matrix, Cube, Cube2 )\ + for ( Cube = (Matrix)->lCubes.pHead, Cube2 = (Cube? Cube->pNext: NULL);\ + Cube;\ + Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) + +#define Fxu_MatrixForEachVariable( Matrix, Var )\ + for ( Var = (Matrix)->lVars.pHead;\ + Var;\ + Var = Var->pNext ) +#define Fxu_MatrixForEachVariableSafe( Matrix, Var, Var2 )\ + for ( Var = (Matrix)->lVars.pHead, Var2 = (Var? Var->pNext: NULL);\ + Var;\ + Var = Var2, Var2 = (Var? Var->pNext: NULL) ) + +#define Fxu_MatrixForEachSingle( Matrix, Single )\ + for ( Single = (Matrix)->lSingles.pHead;\ + Single;\ + Single = Single->pNext ) +#define Fxu_MatrixForEachSingleSafe( Matrix, Single, Single2 )\ + for ( Single = (Matrix)->lSingles.pHead, Single2 = (Single? Single->pNext: NULL);\ + Single;\ + Single = Single2, Single2 = (Single? Single->pNext: NULL) ) + +#define Fxu_TableForEachDouble( Matrix, Key, Div )\ + for ( Div = (Matrix)->pTable[Key].pHead;\ + Div;\ + Div = Div->pNext ) +#define Fxu_TableForEachDoubleSafe( Matrix, Key, Div, Div2 )\ + for ( Div = (Matrix)->pTable[Key].pHead, Div2 = (Div? Div->pNext: NULL);\ + Div;\ + Div = Div2, Div2 = (Div? Div->pNext: NULL) ) + +#define Fxu_MatrixForEachDouble( Matrix, Div, Index )\ + for ( Index = 0; Index < (Matrix)->nTableSize; Index++ )\ + Fxu_TableForEachDouble( Matrix, Index, Div ) +#define Fxu_MatrixForEachDoubleSafe( Matrix, Div, Div2, Index )\ + for ( Index = 0; Index < (Matrix)->nTableSize; Index++ )\ + Fxu_TableForEachDoubleSafe( Matrix, Index, Div, Div2 ) + + +#define Fxu_CubeForEachLiteral( Cube, Lit )\ + for ( Lit = (Cube)->lLits.pHead;\ + Lit;\ + Lit = Lit->pHNext ) +#define Fxu_CubeForEachLiteralSafe( Cube, Lit, Lit2 )\ + for ( Lit = (Cube)->lLits.pHead, Lit2 = (Lit? Lit->pHNext: NULL);\ + Lit;\ + Lit = Lit2, Lit2 = (Lit? Lit->pHNext: NULL) ) + +#define Fxu_VarForEachLiteral( Var, Lit )\ + for ( Lit = (Var)->lLits.pHead;\ + Lit;\ + Lit = Lit->pVNext ) + +#define Fxu_CubeForEachDivisor( Cube, Div )\ + for ( Div = (Cube)->lDivs.pHead;\ + Div;\ + Div = Div->pCNext ) + +#define Fxu_DoubleForEachPair( Div, Pair )\ + for ( Pair = (Div)->lPairs.pHead;\ + Pair;\ + Pair = Pair->pDNext ) +#define Fxu_DoubleForEachPairSafe( Div, Pair, Pair2 )\ + for ( Pair = (Div)->lPairs.pHead, Pair2 = (Pair? Pair->pDNext: NULL);\ + Pair;\ + Pair = Pair2, Pair2 = (Pair? Pair->pDNext: NULL) ) + + +// iterator through the cube pairs belonging to the given cube +#define Fxu_CubeForEachPair( pCube, pPair, i )\ + for ( i = 0;\ + i < pCube->pVar->nCubes &&\ + (((unsigned)(pPair = pCube->pVar->ppPairs[pCube->iCube][i])) >= 0);\ + i++ )\ + if ( pPair ) + +// iterator through all the items in the heap +#define Fxu_HeapDoubleForEachItem( Heap, Div )\ + for ( Heap->i = 1;\ + Heap->i <= Heap->nItems && (Div = Heap->pTree[Heap->i]);\ + Heap->i++ ) +#define Fxu_HeapSingleForEachItem( Heap, Single )\ + for ( Heap->i = 1;\ + Heap->i <= Heap->nItems && (Single = Heap->pTree[Heap->i]);\ + Heap->i++ ) + +// starting the rings +#define Fxu_MatrixRingCubesStart( Matrix ) (((Matrix)->ppTailCubes = &((Matrix)->pOrderCubes)), ((Matrix)->pOrderCubes = NULL)) +#define Fxu_MatrixRingVarsStart( Matrix ) (((Matrix)->ppTailVars = &((Matrix)->pOrderVars)), ((Matrix)->pOrderVars = NULL)) +// stopping the rings +#define Fxu_MatrixRingCubesStop( Matrix ) +#define Fxu_MatrixRingVarsStop( Matrix ) +// resetting the rings +#define Fxu_MatrixRingCubesReset( Matrix ) (((Matrix)->pOrderCubes = NULL), ((Matrix)->ppTailCubes = NULL)) +#define Fxu_MatrixRingVarsReset( Matrix ) (((Matrix)->pOrderVars = NULL), ((Matrix)->ppTailVars = NULL)) +// adding to the rings +#define Fxu_MatrixRingCubesAdd( Matrix, Cube) ((*((Matrix)->ppTailCubes) = Cube), ((Matrix)->ppTailCubes = &(Cube)->pOrder), ((Cube)->pOrder = (Fxu_Cube *)1)) +#define Fxu_MatrixRingVarsAdd( Matrix, Var ) ((*((Matrix)->ppTailVars ) = Var ), ((Matrix)->ppTailVars = &(Var)->pOrder ), ((Var)->pOrder = (Fxu_Var *)1)) +// iterating through the rings +#define Fxu_MatrixForEachCubeInRing( Matrix, Cube )\ + if ( (Matrix)->pOrderCubes )\ + for ( Cube = (Matrix)->pOrderCubes;\ + Cube != (Fxu_Cube *)1;\ + Cube = Cube->pOrder ) +#define Fxu_MatrixForEachCubeInRingSafe( Matrix, Cube, Cube2 )\ + if ( (Matrix)->pOrderCubes )\ + for ( Cube = (Matrix)->pOrderCubes, Cube2 = ((Cube != (Fxu_Cube *)1)? Cube->pOrder: (Fxu_Cube *)1);\ + Cube != (Fxu_Cube *)1;\ + Cube = Cube2, Cube2 = ((Cube != (Fxu_Cube *)1)? Cube->pOrder: (Fxu_Cube *)1) ) +#define Fxu_MatrixForEachVarInRing( Matrix, Var )\ + if ( (Matrix)->pOrderVars )\ + for ( Var = (Matrix)->pOrderVars;\ + Var != (Fxu_Var *)1;\ + Var = Var->pOrder ) +#define Fxu_MatrixForEachVarInRingSafe( Matrix, Var, Var2 )\ + if ( (Matrix)->pOrderVars )\ + for ( Var = (Matrix)->pOrderVars, Var2 = ((Var != (Fxu_Var *)1)? Var->pOrder: (Fxu_Var *)1);\ + Var != (Fxu_Var *)1;\ + Var = Var2, Var2 = ((Var != (Fxu_Var *)1)? Var->pOrder: (Fxu_Var *)1) ) +// the procedures are related to the above macros +extern void Fxu_MatrixRingCubesUnmark( Fxu_Matrix * p ); +extern void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p ); + + +// macros working with memory +// MEM_ALLOC: allocate the given number (Size) of items of type (Type) +// MEM_FREE: deallocate the pointer (Pointer) to the given number (Size) of items of type (Type) +#ifdef USE_SYSTEM_MEMORY_MANAGEMENT +#define MEM_ALLOC_FXU( Manager, Type, Size ) ((Type *)malloc( (Size) * sizeof(Type) )) +#define MEM_FREE_FXU( Manager, Type, Size, Pointer ) if ( Pointer ) { free(Pointer); Pointer = NULL; } +#else +#define MEM_ALLOC_FXU( Manager, Type, Size )\ + ((Type *)Fxu_MemFetch( Manager, (Size) * sizeof(Type) )) +#define MEM_FREE_FXU( Manager, Type, Size, Pointer )\ + if ( Pointer ) { Fxu_MemRecycle( Manager, (char *)(Pointer), (Size) * sizeof(Type) ); Pointer = NULL; } +#endif + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*===== fxu.c ====================================================*/ +extern char * Fxu_MemFetch( Fxu_Matrix * p, int nBytes ); +extern void Fxu_MemRecycle( Fxu_Matrix * p, char * pItem, int nBytes ); +/*===== fxuCreate.c ====================================================*/ +/*===== fxuReduce.c ====================================================*/ +/*===== fxuPrint.c ====================================================*/ +extern void Fxu_MatrixPrint( FILE * pFile, Fxu_Matrix * p ); +extern void Fxu_MatrixPrintDivisorProfile( FILE * pFile, Fxu_Matrix * p ); +/*===== fxuSelect.c ====================================================*/ +extern int Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble ); +extern int Fxu_SelectSCD( Fxu_Matrix * p, int Weight, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 ); +/*===== fxuUpdate.c ====================================================*/ +extern void Fxu_Update( Fxu_Matrix * p, Fxu_Single * pSingle, Fxu_Double * pDouble ); +extern void Fxu_UpdateDouble( Fxu_Matrix * p ); +extern void Fxu_UpdateSingle( Fxu_Matrix * p ); +/*===== fxuPair.c ====================================================*/ +extern void Fxu_PairCanonicize( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 ); +extern unsigned Fxu_PairHashKeyArray( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ); +extern unsigned Fxu_PairHashKey( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, int * pnBase, int * pnLits1, int * pnLits2 ); +extern unsigned Fxu_PairHashKeyMv( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, int * pnBase, int * pnLits1, int * pnLits2 ); +extern int Fxu_PairCompare( Fxu_Pair * pPair1, Fxu_Pair * pPair2 ); +extern void Fxu_PairAllocStorage( Fxu_Var * pVar, int nCubes ); +extern void Fxu_PairFreeStorage( Fxu_Var * pVar ); +extern void Fxu_PairClearStorage( Fxu_Cube * pCube ); +extern Fxu_Pair * Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ); +extern void Fxu_PairAdd( Fxu_Pair * pPair ); +/*===== fxuSingle.c ====================================================*/ +extern void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax ); +extern void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar ); +extern int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 ); +/*===== fxuMatrix.c ====================================================*/ +// matrix +extern Fxu_Matrix * Fxu_MatrixAllocate(); +extern void Fxu_MatrixDelete( Fxu_Matrix * p ); +// double-cube divisor +extern void Fxu_MatrixAddDivisor( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ); +extern void Fxu_MatrixDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ); +// single-cube divisor +extern void Fxu_MatrixAddSingle( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, int Weight ); +// variable +extern Fxu_Var * Fxu_MatrixAddVar( Fxu_Matrix * p ); +// cube +extern Fxu_Cube * Fxu_MatrixAddCube( Fxu_Matrix * p, Fxu_Var * pVar, int iCube ); +// literal +extern void Fxu_MatrixAddLiteral( Fxu_Matrix * p, Fxu_Cube * pCube, Fxu_Var * pVar ); +extern void Fxu_MatrixDelLiteral( Fxu_Matrix * p, Fxu_Lit * pLit ); +/*===== fxuList.c ====================================================*/ +// matrix -> variable +extern void Fxu_ListMatrixAddVariable( Fxu_Matrix * p, Fxu_Var * pVar ); +extern void Fxu_ListMatrixDelVariable( Fxu_Matrix * p, Fxu_Var * pVar ); +// matrix -> cube +extern void Fxu_ListMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube ); +extern void Fxu_ListMatrixDelCube( Fxu_Matrix * p, Fxu_Cube * pCube ); +// matrix -> single +extern void Fxu_ListMatrixAddSingle( Fxu_Matrix * p, Fxu_Single * pSingle ); +extern void Fxu_ListMatrixDelSingle( Fxu_Matrix * p, Fxu_Single * pSingle ); +// table -> divisor +extern void Fxu_ListTableAddDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ); +extern void Fxu_ListTableDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ); +// cube -> literal +extern void Fxu_ListCubeAddLiteral( Fxu_Cube * pCube, Fxu_Lit * pLit ); +extern void Fxu_ListCubeDelLiteral( Fxu_Cube * pCube, Fxu_Lit * pLit ); +// var -> literal +extern void Fxu_ListVarAddLiteral( Fxu_Var * pVar, Fxu_Lit * pLit ); +extern void Fxu_ListVarDelLiteral( Fxu_Var * pVar, Fxu_Lit * pLit ); +// divisor -> pair +extern void Fxu_ListDoubleAddPairLast( Fxu_Double * pDiv, Fxu_Pair * pLink ); +extern void Fxu_ListDoubleAddPairFirst( Fxu_Double * pDiv, Fxu_Pair * pLink ); +extern void Fxu_ListDoubleAddPairMiddle( Fxu_Double * pDiv, Fxu_Pair * pSpot, Fxu_Pair * pLink ); +extern void Fxu_ListDoubleDelPair( Fxu_Double * pDiv, Fxu_Pair * pPair ); +/*===== fxuHeapDouble.c ====================================================*/ +extern Fxu_HeapDouble * Fxu_HeapDoubleStart(); +extern void Fxu_HeapDoubleStop( Fxu_HeapDouble * p ); +extern void Fxu_HeapDoublePrint( FILE * pFile, Fxu_HeapDouble * p ); +extern void Fxu_HeapDoubleCheck( Fxu_HeapDouble * p ); +extern void Fxu_HeapDoubleCheckOne( Fxu_HeapDouble * p, Fxu_Double * pDiv ); + +extern void Fxu_HeapDoubleInsert( Fxu_HeapDouble * p, Fxu_Double * pDiv ); +extern void Fxu_HeapDoubleUpdate( Fxu_HeapDouble * p, Fxu_Double * pDiv ); +extern void Fxu_HeapDoubleDelete( Fxu_HeapDouble * p, Fxu_Double * pDiv ); +extern int Fxu_HeapDoubleReadMaxWeight( Fxu_HeapDouble * p ); +extern Fxu_Double * Fxu_HeapDoubleReadMax( Fxu_HeapDouble * p ); +extern Fxu_Double * Fxu_HeapDoubleGetMax( Fxu_HeapDouble * p ); +/*===== fxuHeapSingle.c ====================================================*/ +extern Fxu_HeapSingle * Fxu_HeapSingleStart(); +extern void Fxu_HeapSingleStop( Fxu_HeapSingle * p ); +extern void Fxu_HeapSinglePrint( FILE * pFile, Fxu_HeapSingle * p ); +extern void Fxu_HeapSingleCheck( Fxu_HeapSingle * p ); +extern void Fxu_HeapSingleCheckOne( Fxu_HeapSingle * p, Fxu_Single * pSingle ); + +extern void Fxu_HeapSingleInsert( Fxu_HeapSingle * p, Fxu_Single * pSingle ); +extern void Fxu_HeapSingleUpdate( Fxu_HeapSingle * p, Fxu_Single * pSingle ); +extern void Fxu_HeapSingleDelete( Fxu_HeapSingle * p, Fxu_Single * pSingle ); +extern int Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p ); +extern Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p ); +extern Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/fxu/fxuList.c b/abc70930/src/opt/fxu/fxuList.c new file mode 100644 index 00000000..52995804 --- /dev/null +++ b/abc70930/src/opt/fxu/fxuList.c @@ -0,0 +1,522 @@ +/**CFile**************************************************************** + + FileName [fxuList.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Operations on lists.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuList.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fxuInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// matrix -> var + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListMatrixAddVariable( Fxu_Matrix * p, Fxu_Var * pLink ) +{ + Fxu_ListVar * pList = &p->lVars; + if ( pList->pHead == NULL ) + { + pList->pHead = pLink; + pList->pTail = pLink; + pLink->pPrev = NULL; + pLink->pNext = NULL; + } + else + { + pLink->pNext = NULL; + pList->pTail->pNext = pLink; + pLink->pPrev = pList->pTail; + pList->pTail = pLink; + } + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListMatrixDelVariable( Fxu_Matrix * p, Fxu_Var * pLink ) +{ + Fxu_ListVar * pList = &p->lVars; + if ( pList->pHead == pLink ) + pList->pHead = pLink->pNext; + if ( pList->pTail == pLink ) + pList->pTail = pLink->pPrev; + if ( pLink->pPrev ) + pLink->pPrev->pNext = pLink->pNext; + if ( pLink->pNext ) + pLink->pNext->pPrev = pLink->pPrev; + pList->nItems--; +} + + +// matrix -> cube + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pLink ) +{ + Fxu_ListCube * pList = &p->lCubes; + if ( pList->pHead == NULL ) + { + pList->pHead = pLink; + pList->pTail = pLink; + pLink->pPrev = NULL; + pLink->pNext = NULL; + } + else + { + pLink->pNext = NULL; + pList->pTail->pNext = pLink; + pLink->pPrev = pList->pTail; + pList->pTail = pLink; + } + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListMatrixDelCube( Fxu_Matrix * p, Fxu_Cube * pLink ) +{ + Fxu_ListCube * pList = &p->lCubes; + if ( pList->pHead == pLink ) + pList->pHead = pLink->pNext; + if ( pList->pTail == pLink ) + pList->pTail = pLink->pPrev; + if ( pLink->pPrev ) + pLink->pPrev->pNext = pLink->pNext; + if ( pLink->pNext ) + pLink->pNext->pPrev = pLink->pPrev; + pList->nItems--; +} + + +// matrix -> single + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListMatrixAddSingle( Fxu_Matrix * p, Fxu_Single * pLink ) +{ + Fxu_ListSingle * pList = &p->lSingles; + if ( pList->pHead == NULL ) + { + pList->pHead = pLink; + pList->pTail = pLink; + pLink->pPrev = NULL; + pLink->pNext = NULL; + } + else + { + pLink->pNext = NULL; + pList->pTail->pNext = pLink; + pLink->pPrev = pList->pTail; + pList->pTail = pLink; + } + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListMatrixDelSingle( Fxu_Matrix * p, Fxu_Single * pLink ) +{ + Fxu_ListSingle * pList = &p->lSingles; + if ( pList->pHead == pLink ) + pList->pHead = pLink->pNext; + if ( pList->pTail == pLink ) + pList->pTail = pLink->pPrev; + if ( pLink->pPrev ) + pLink->pPrev->pNext = pLink->pNext; + if ( pLink->pNext ) + pLink->pNext->pPrev = pLink->pPrev; + pList->nItems--; +} + + +// table -> divisor + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListTableAddDivisor( Fxu_Matrix * p, Fxu_Double * pLink ) +{ + Fxu_ListDouble * pList = &(p->pTable[pLink->Key]); + if ( pList->pHead == NULL ) + { + pList->pHead = pLink; + pList->pTail = pLink; + pLink->pPrev = NULL; + pLink->pNext = NULL; + } + else + { + pLink->pNext = NULL; + pList->pTail->pNext = pLink; + pLink->pPrev = pList->pTail; + pList->pTail = pLink; + } + pList->nItems++; + p->nDivs++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListTableDelDivisor( Fxu_Matrix * p, Fxu_Double * pLink ) +{ + Fxu_ListDouble * pList = &(p->pTable[pLink->Key]); + if ( pList->pHead == pLink ) + pList->pHead = pLink->pNext; + if ( pList->pTail == pLink ) + pList->pTail = pLink->pPrev; + if ( pLink->pPrev ) + pLink->pPrev->pNext = pLink->pNext; + if ( pLink->pNext ) + pLink->pNext->pPrev = pLink->pPrev; + pList->nItems--; + p->nDivs--; +} + + +// cube -> literal + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListCubeAddLiteral( Fxu_Cube * pCube, Fxu_Lit * pLink ) +{ + Fxu_ListLit * pList = &(pCube->lLits); + if ( pList->pHead == NULL ) + { + pList->pHead = pLink; + pList->pTail = pLink; + pLink->pHPrev = NULL; + pLink->pHNext = NULL; + } + else + { + pLink->pHNext = NULL; + pList->pTail->pHNext = pLink; + pLink->pHPrev = pList->pTail; + pList->pTail = pLink; + } + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListCubeDelLiteral( Fxu_Cube * pCube, Fxu_Lit * pLink ) +{ + Fxu_ListLit * pList = &(pCube->lLits); + if ( pList->pHead == pLink ) + pList->pHead = pLink->pHNext; + if ( pList->pTail == pLink ) + pList->pTail = pLink->pHPrev; + if ( pLink->pHPrev ) + pLink->pHPrev->pHNext = pLink->pHNext; + if ( pLink->pHNext ) + pLink->pHNext->pHPrev = pLink->pHPrev; + pList->nItems--; +} + + +// var -> literal + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListVarAddLiteral( Fxu_Var * pVar, Fxu_Lit * pLink ) +{ + Fxu_ListLit * pList = &(pVar->lLits); + if ( pList->pHead == NULL ) + { + pList->pHead = pLink; + pList->pTail = pLink; + pLink->pVPrev = NULL; + pLink->pVNext = NULL; + } + else + { + pLink->pVNext = NULL; + pList->pTail->pVNext = pLink; + pLink->pVPrev = pList->pTail; + pList->pTail = pLink; + } + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListVarDelLiteral( Fxu_Var * pVar, Fxu_Lit * pLink ) +{ + Fxu_ListLit * pList = &(pVar->lLits); + if ( pList->pHead == pLink ) + pList->pHead = pLink->pVNext; + if ( pList->pTail == pLink ) + pList->pTail = pLink->pVPrev; + if ( pLink->pVPrev ) + pLink->pVPrev->pVNext = pLink->pVNext; + if ( pLink->pVNext ) + pLink->pVNext->pVPrev = pLink->pVPrev; + pList->nItems--; +} + + + +// divisor -> pair + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListDoubleAddPairLast( Fxu_Double * pDiv, Fxu_Pair * pLink ) +{ + Fxu_ListPair * pList = &pDiv->lPairs; + if ( pList->pHead == NULL ) + { + pList->pHead = pLink; + pList->pTail = pLink; + pLink->pDPrev = NULL; + pLink->pDNext = NULL; + } + else + { + pLink->pDNext = NULL; + pList->pTail->pDNext = pLink; + pLink->pDPrev = pList->pTail; + pList->pTail = pLink; + } + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListDoubleAddPairFirst( Fxu_Double * pDiv, Fxu_Pair * pLink ) +{ + Fxu_ListPair * pList = &pDiv->lPairs; + if ( pList->pHead == NULL ) + { + pList->pHead = pLink; + pList->pTail = pLink; + pLink->pDPrev = NULL; + pLink->pDNext = NULL; + } + else + { + pLink->pDPrev = NULL; + pList->pHead->pDPrev = pLink; + pLink->pDNext = pList->pHead; + pList->pHead = pLink; + } + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [Adds the entry in the middle of the list after the spot.] + + Description [Assumes that spot points to the link, after which the given + link should be added. Spot cannot be NULL or the tail of the list. + Therefore, the head and the tail of the list are not changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListDoubleAddPairMiddle( Fxu_Double * pDiv, Fxu_Pair * pSpot, Fxu_Pair * pLink ) +{ + Fxu_ListPair * pList = &pDiv->lPairs; + assert( pSpot ); + assert( pSpot != pList->pTail ); + pLink->pDPrev = pSpot; + pLink->pDNext = pSpot->pDNext; + pLink->pDPrev->pDNext = pLink; + pLink->pDNext->pDPrev = pLink; + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListDoubleDelPair( Fxu_Double * pDiv, Fxu_Pair * pLink ) +{ + Fxu_ListPair * pList = &pDiv->lPairs; + if ( pList->pHead == pLink ) + pList->pHead = pLink->pDNext; + if ( pList->pTail == pLink ) + pList->pTail = pLink->pDPrev; + if ( pLink->pDPrev ) + pLink->pDPrev->pDNext = pLink->pDNext; + if ( pLink->pDNext ) + pLink->pDNext->pDPrev = pLink->pDPrev; + pList->nItems--; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_ListDoubleAddPairPlace( Fxu_Double * pDiv, Fxu_Pair * pPair, Fxu_Pair * pPairSpot ) +{ + printf( "Fxu_ListDoubleAddPairPlace() is called!\n" ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/fxu/fxuMatrix.c b/abc70930/src/opt/fxu/fxuMatrix.c new file mode 100644 index 00000000..93ec7b90 --- /dev/null +++ b/abc70930/src/opt/fxu/fxuMatrix.c @@ -0,0 +1,374 @@ +/**CFile**************************************************************** + + FileName [fxuMatrix.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Procedures to manipulate the sparse matrix.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuMatrix.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fxuInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern unsigned int Cudd_Prime( unsigned int p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Matrix * Fxu_MatrixAllocate() +{ + Fxu_Matrix * p; + p = ALLOC( Fxu_Matrix, 1 ); + memset( p, 0, sizeof(Fxu_Matrix) ); + p->nTableSize = Cudd_Prime(10000); + p->pTable = ALLOC( Fxu_ListDouble, p->nTableSize ); + memset( p->pTable, 0, sizeof(Fxu_ListDouble) * p->nTableSize ); +#ifndef USE_SYSTEM_MEMORY_MANAGEMENT + { + // get the largest size in bytes for the following structures: + // Fxu_Cube, Fxu_Var, Fxu_Lit, Fxu_Pair, Fxu_Double, Fxu_Single + // (currently, Fxu_Var, Fxu_Pair, Fxu_Double take 10 machine words) + int nSizeMax, nSizeCur; + nSizeMax = -1; + nSizeCur = sizeof(Fxu_Cube); + if ( nSizeMax < nSizeCur ) + nSizeMax = nSizeCur; + nSizeCur = sizeof(Fxu_Var); + if ( nSizeMax < nSizeCur ) + nSizeMax = nSizeCur; + nSizeCur = sizeof(Fxu_Lit); + if ( nSizeMax < nSizeCur ) + nSizeMax = nSizeCur; + nSizeCur = sizeof(Fxu_Pair); + if ( nSizeMax < nSizeCur ) + nSizeMax = nSizeCur; + nSizeCur = sizeof(Fxu_Double); + if ( nSizeMax < nSizeCur ) + nSizeMax = nSizeCur; + nSizeCur = sizeof(Fxu_Single); + if ( nSizeMax < nSizeCur ) + nSizeMax = nSizeCur; + p->pMemMan = Extra_MmFixedStart( nSizeMax ); + } +#endif + p->pHeapDouble = Fxu_HeapDoubleStart(); + p->pHeapSingle = Fxu_HeapSingleStart(); + p->vPairs = Vec_PtrAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixDelete( Fxu_Matrix * p ) +{ + Fxu_HeapDoubleCheck( p->pHeapDouble ); + Fxu_HeapDoubleStop( p->pHeapDouble ); + Fxu_HeapSingleStop( p->pHeapSingle ); + + // delete other things +#ifdef USE_SYSTEM_MEMORY_MANAGEMENT + // this code is not needed when the custom memory manager is used + { + Fxu_Cube * pCube, * pCube2; + Fxu_Var * pVar, * pVar2; + Fxu_Lit * pLit, * pLit2; + Fxu_Double * pDiv, * pDiv2; + Fxu_Single * pSingle, * pSingle2; + Fxu_Pair * pPair, * pPair2; + int i; + // delete the divisors + Fxu_MatrixForEachDoubleSafe( p, pDiv, pDiv2, i ) + { + Fxu_DoubleForEachPairSafe( pDiv, pPair, pPair2 ) + MEM_FREE_FXU( p, Fxu_Pair, 1, pPair ); + MEM_FREE_FXU( p, Fxu_Double, 1, pDiv ); + } + Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 ) + MEM_FREE_FXU( p, Fxu_Single, 1, pSingle ); + // delete the entries + Fxu_MatrixForEachCube( p, pCube ) + Fxu_CubeForEachLiteralSafe( pCube, pLit, pLit2 ) + MEM_FREE_FXU( p, Fxu_Lit, 1, pLit ); + // delete the cubes + Fxu_MatrixForEachCubeSafe( p, pCube, pCube2 ) + MEM_FREE_FXU( p, Fxu_Cube, 1, pCube ); + // delete the vars + Fxu_MatrixForEachVariableSafe( p, pVar, pVar2 ) + MEM_FREE_FXU( p, Fxu_Var, 1, pVar ); + } +#else + Extra_MmFixedStop( p->pMemMan ); +#endif + + Vec_PtrFree( p->vPairs ); + FREE( p->pppPairs ); + FREE( p->ppPairs ); +// FREE( p->pPairsTemp ); + FREE( p->pTable ); + FREE( p->ppVars ); + FREE( p ); +} + + + +/**Function************************************************************* + + Synopsis [Adds a variable to the matrix.] + + Description [This procedure always adds variables at the end of the matrix. + It assigns the var's node and number. It adds the var to the linked list of + all variables and to the table of all nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Var * Fxu_MatrixAddVar( Fxu_Matrix * p ) +{ + Fxu_Var * pVar; + pVar = MEM_ALLOC_FXU( p, Fxu_Var, 1 ); + memset( pVar, 0, sizeof(Fxu_Var) ); + pVar->iVar = p->lVars.nItems; + p->ppVars[pVar->iVar] = pVar; + Fxu_ListMatrixAddVariable( p, pVar ); + return pVar; +} + +/**Function************************************************************* + + Synopsis [Adds a literal to the matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Cube * Fxu_MatrixAddCube( Fxu_Matrix * p, Fxu_Var * pVar, int iCube ) +{ + Fxu_Cube * pCube; + pCube = MEM_ALLOC_FXU( p, Fxu_Cube, 1 ); + memset( pCube, 0, sizeof(Fxu_Cube) ); + pCube->pVar = pVar; + pCube->iCube = iCube; + Fxu_ListMatrixAddCube( p, pCube ); + return pCube; +} + +/**Function************************************************************* + + Synopsis [Adds a literal to the matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixAddLiteral( Fxu_Matrix * p, Fxu_Cube * pCube, Fxu_Var * pVar ) +{ + Fxu_Lit * pLit; + pLit = MEM_ALLOC_FXU( p, Fxu_Lit, 1 ); + memset( pLit, 0, sizeof(Fxu_Lit) ); + // insert the literal into two linked lists + Fxu_ListCubeAddLiteral( pCube, pLit ); + Fxu_ListVarAddLiteral( pVar, pLit ); + // set the back pointers + pLit->pCube = pCube; + pLit->pVar = pVar; + pLit->iCube = pCube->iCube; + pLit->iVar = pVar->iVar; + // increment the literal counter + p->nEntries++; +} + +/**Function************************************************************* + + Synopsis [Deletes the divisor from the matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ) +{ + // delete divisor from the table + Fxu_ListTableDelDivisor( p, pDiv ); + // recycle the divisor + MEM_FREE_FXU( p, Fxu_Double, 1, pDiv ); +} + +/**Function************************************************************* + + Synopsis [Deletes the literal fromthe matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixDelLiteral( Fxu_Matrix * p, Fxu_Lit * pLit ) +{ + // delete the literal + Fxu_ListCubeDelLiteral( pLit->pCube, pLit ); + Fxu_ListVarDelLiteral( pLit->pVar, pLit ); + MEM_FREE_FXU( p, Fxu_Lit, 1, pLit ); + // increment the literal counter + p->nEntries--; +} + + +/**Function************************************************************* + + Synopsis [Creates and adds a single cube divisor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixAddSingle( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, int Weight ) +{ + Fxu_Single * pSingle; + assert( pVar1->iVar < pVar2->iVar ); + pSingle = MEM_ALLOC_FXU( p, Fxu_Single, 1 ); + memset( pSingle, 0, sizeof(Fxu_Single) ); + pSingle->Num = p->lSingles.nItems; + pSingle->Weight = Weight; + pSingle->HNum = 0; + pSingle->pVar1 = pVar1; + pSingle->pVar2 = pVar2; + Fxu_ListMatrixAddSingle( p, pSingle ); + // add to the heap + Fxu_HeapSingleInsert( p->pHeapSingle, pSingle ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixAddDivisor( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ) +{ + Fxu_Pair * pPair; + Fxu_Double * pDiv; + int nBase, nLits1, nLits2; + int fFound; + unsigned Key; + + // canonicize the pair + Fxu_PairCanonicize( &pCube1, &pCube2 ); + // compute the hash key + Key = Fxu_PairHashKey( p, pCube1, pCube2, &nBase, &nLits1, &nLits2 ); + + // create the cube pair + pPair = Fxu_PairAlloc( p, pCube1, pCube2 ); + pPair->nBase = nBase; + pPair->nLits1 = nLits1; + pPair->nLits2 = nLits2; + + // check if the divisor for this pair already exists + fFound = 0; + Key %= p->nTableSize; + Fxu_TableForEachDouble( p, Key, pDiv ) + { + if ( Fxu_PairCompare( pPair, pDiv->lPairs.pTail ) ) // they are equal + { + fFound = 1; + break; + } + } + + if ( !fFound ) + { // create the new divisor + pDiv = MEM_ALLOC_FXU( p, Fxu_Double, 1 ); + memset( pDiv, 0, sizeof(Fxu_Double) ); + pDiv->Key = Key; + // set the number of this divisor + pDiv->Num = p->nDivsTotal++; // p->nDivs; + // insert the divisor in the table + Fxu_ListTableAddDivisor( p, pDiv ); + // set the initial cost of the divisor + pDiv->Weight -= pPair->nLits1 + pPair->nLits2; + } + + // link the pair to the cubes + Fxu_PairAdd( pPair ); + // connect the pair and the divisor + pPair->pDiv = pDiv; + Fxu_ListDoubleAddPairLast( pDiv, pPair ); + // update the max number of pairs in a divisor +// if ( p->nPairsMax < pDiv->lPairs.nItems ) +// p->nPairsMax = pDiv->lPairs.nItems; + // update the divisor's weight + pDiv->Weight += pPair->nLits1 + pPair->nLits2 - 1 + pPair->nBase; + if ( fFound ) // update the divisor in the heap + Fxu_HeapDoubleUpdate( p->pHeapDouble, pDiv ); + else // add the new divisor to the heap + Fxu_HeapDoubleInsert( p->pHeapDouble, pDiv ); +} + +/* + { + int piVarsC1[100], piVarsC2[100], nVarsC1, nVarsC2; + Fxu_Double * pDivCur; + Fxu_MatrixGetDoubleVars( p, pDiv, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 ); + pDivCur = Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 ); + assert( pDivCur == pDiv ); + } +*/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/fxu/fxuPair.c b/abc70930/src/opt/fxu/fxuPair.c new file mode 100644 index 00000000..3c031ce8 --- /dev/null +++ b/abc70930/src/opt/fxu/fxuPair.c @@ -0,0 +1,555 @@ +/**CFile**************************************************************** + + FileName [fxuPair.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Operations on cube pairs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuPair.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fxuInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define MAX_PRIMES 304 + +static s_Primes[MAX_PRIMES] = +{ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, + 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, + 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, + 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, + 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, + 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, + 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, + 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, + 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, + 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, + 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, + 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, + 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, + 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, + 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, + 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, + 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, + 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, + 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, + 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, + 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, + 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, + 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, + 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, + 1993, 1997, 1999, 2003 +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find the canonical permutation of two cubes in the pair.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_PairCanonicize( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 ) +{ + Fxu_Lit * pLit1, * pLit2; + Fxu_Cube * pCubeTemp; + + // walk through the cubes to determine + // the one that has higher first variable + pLit1 = (*ppCube1)->lLits.pHead; + pLit2 = (*ppCube2)->lLits.pHead; + while ( 1 ) + { + if ( pLit1->iVar == pLit2->iVar ) + { + pLit1 = pLit1->pHNext; + pLit2 = pLit2->pHNext; + continue; + } + assert( pLit1 && pLit2 ); // this is true if the covers are SCC-free + if ( pLit1->iVar > pLit2->iVar ) + { // swap the cubes + pCubeTemp = *ppCube1; + *ppCube1 = *ppCube2; + *ppCube2 = pCubeTemp; + } + break; + } +} + +/**Function************************************************************* + + Synopsis [Find the canonical permutation of two cubes in the pair.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_PairCanonicize2( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 ) +{ + Fxu_Cube * pCubeTemp; + // canonicize the pair by ordering the cubes + if ( (*ppCube1)->iCube > (*ppCube2)->iCube ) + { // swap the cubes + pCubeTemp = *ppCube1; + *ppCube1 = *ppCube2; + *ppCube2 = pCubeTemp; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Fxu_PairHashKeyArray( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ) +{ + int Offset1 = 100, Offset2 = 200, i; + unsigned Key; + // compute the hash key + Key = 0; + for ( i = 0; i < nVarsC1; i++ ) + Key ^= s_Primes[Offset1+i] * piVarsC1[i]; + for ( i = 0; i < nVarsC2; i++ ) + Key ^= s_Primes[Offset2+i] * piVarsC2[i]; + return Key; +} + +/**Function************************************************************* + + Synopsis [Computes the hash key of the divisor represented by the pair of cubes.] + + Description [Goes through the variables in both cubes. Skips the identical + ones (this corresponds to making the cubes cube-free). Computes the hash + value of the cubes. Assigns the number of literals in the base and in the + cubes without base.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Fxu_PairHashKey( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, + int * pnBase, int * pnLits1, int * pnLits2 ) +{ + int Offset1 = 100, Offset2 = 200; + int nBase, nLits1, nLits2; + Fxu_Lit * pLit1, * pLit2; + unsigned Key; + + // compute the hash key + Key = 0; + nLits1 = 0; + nLits2 = 0; + nBase = 0; + pLit1 = pCube1->lLits.pHead; + pLit2 = pCube2->lLits.pHead; + while ( 1 ) + { + if ( pLit1 && pLit2 ) + { + if ( pLit1->iVar == pLit2->iVar ) + { // ensure cube-free + pLit1 = pLit1->pHNext; + pLit2 = pLit2->pHNext; + // add this literal to the base + nBase++; + } + else if ( pLit1->iVar < pLit2->iVar ) + { + Key ^= s_Primes[Offset1+nLits1] * pLit1->iVar; + pLit1 = pLit1->pHNext; + nLits1++; + } + else + { + Key ^= s_Primes[Offset2+nLits2] * pLit2->iVar; + pLit2 = pLit2->pHNext; + nLits2++; + } + } + else if ( pLit1 && !pLit2 ) + { + Key ^= s_Primes[Offset1+nLits1] * pLit1->iVar; + pLit1 = pLit1->pHNext; + nLits1++; + } + else if ( !pLit1 && pLit2 ) + { + Key ^= s_Primes[Offset2+nLits2] * pLit2->iVar; + pLit2 = pLit2->pHNext; + nLits2++; + } + else + break; + } + *pnBase = nBase; + *pnLits1 = nLits1; + *pnLits2 = nLits2; + return Key; +} + +/**Function************************************************************* + + Synopsis [Compares the two pairs.] + + Description [Returns 1 if the divisors represented by these pairs + are equal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_PairCompare( Fxu_Pair * pPair1, Fxu_Pair * pPair2 ) +{ + Fxu_Lit * pD1C1, * pD1C2; + Fxu_Lit * pD2C1, * pD2C2; + int TopVar1, TopVar2; + int Code; + + if ( pPair1->nLits1 != pPair2->nLits1 ) + return 0; + if ( pPair1->nLits2 != pPair2->nLits2 ) + return 0; + + pD1C1 = pPair1->pCube1->lLits.pHead; + pD1C2 = pPair1->pCube2->lLits.pHead; + + pD2C1 = pPair2->pCube1->lLits.pHead; + pD2C2 = pPair2->pCube2->lLits.pHead; + + Code = pD1C1? 8: 0; + Code |= pD1C2? 4: 0; + Code |= pD2C1? 2: 0; + Code |= pD2C2? 1: 0; + assert( Code == 15 ); + + while ( 1 ) + { + switch ( Code ) + { + case 0: // -- -- NULL NULL NULL NULL + return 1; + case 1: // -- -1 NULL NULL NULL pD2C2 + return 0; + case 2: // -- 1- NULL NULL pD2C1 NULL + return 0; + case 3: // -- 11 NULL NULL pD2C1 pD2C2 + if ( pD2C1->iVar != pD2C2->iVar ) + return 0; + pD2C1 = pD2C1->pHNext; + pD2C2 = pD2C2->pHNext; + break; + case 4: // -1 -- NULL pD1C2 NULL NULL + return 0; + case 5: // -1 -1 NULL pD1C2 NULL pD2C2 + if ( pD1C2->iVar != pD2C2->iVar ) + return 0; + pD1C2 = pD1C2->pHNext; + pD2C2 = pD2C2->pHNext; + break; + case 6: // -1 1- NULL pD1C2 pD2C1 NULL + return 0; + case 7: // -1 11 NULL pD1C2 pD2C1 pD2C2 + TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar ); + if ( TopVar2 == pD1C2->iVar ) + { + if ( pD2C1->iVar <= pD2C2->iVar ) + return 0; + pD1C2 = pD1C2->pHNext; + pD2C2 = pD2C2->pHNext; + } + else if ( TopVar2 < pD1C2->iVar ) + { + if ( pD2C1->iVar != pD2C2->iVar ) + return 0; + pD2C1 = pD2C1->pHNext; + pD2C2 = pD2C2->pHNext; + } + else + return 0; + break; + case 8: // 1- -- pD1C1 NULL NULL NULL + return 0; + case 9: // 1- -1 pD1C1 NULL NULL pD2C2 + return 0; + case 10: // 1- 1- pD1C1 NULL pD2C1 NULL + if ( pD1C1->iVar != pD2C1->iVar ) + return 0; + pD1C1 = pD1C1->pHNext; + pD2C1 = pD2C1->pHNext; + break; + case 11: // 1- 11 pD1C1 NULL pD2C1 pD2C2 + TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar ); + if ( TopVar2 == pD1C1->iVar ) + { + if ( pD2C1->iVar >= pD2C2->iVar ) + return 0; + pD1C1 = pD1C1->pHNext; + pD2C1 = pD2C1->pHNext; + } + else if ( TopVar2 < pD1C1->iVar ) + { + if ( pD2C1->iVar != pD2C2->iVar ) + return 0; + pD2C1 = pD2C1->pHNext; + pD2C2 = pD2C2->pHNext; + } + else + return 0; + break; + case 12: // 11 -- pD1C1 pD1C2 NULL NULL + if ( pD1C1->iVar != pD1C2->iVar ) + return 0; + pD1C1 = pD1C1->pHNext; + pD1C2 = pD1C2->pHNext; + break; + case 13: // 11 -1 pD1C1 pD1C2 NULL pD2C2 + TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar ); + if ( TopVar1 == pD2C2->iVar ) + { + if ( pD1C1->iVar <= pD1C2->iVar ) + return 0; + pD1C2 = pD1C2->pHNext; + pD2C2 = pD2C2->pHNext; + } + else if ( TopVar1 < pD2C2->iVar ) + { + if ( pD1C1->iVar != pD1C2->iVar ) + return 0; + pD1C1 = pD1C1->pHNext; + pD1C2 = pD1C2->pHNext; + } + else + return 0; + break; + case 14: // 11 1- pD1C1 pD1C2 pD2C1 NULL + TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar ); + if ( TopVar1 == pD2C1->iVar ) + { + if ( pD1C1->iVar >= pD1C2->iVar ) + return 0; + pD1C1 = pD1C1->pHNext; + pD2C1 = pD2C1->pHNext; + } + else if ( TopVar1 < pD2C1->iVar ) + { + if ( pD1C1->iVar != pD1C2->iVar ) + return 0; + pD1C1 = pD1C1->pHNext; + pD1C2 = pD1C2->pHNext; + } + else + return 0; + break; + case 15: // 11 11 pD1C1 pD1C2 pD2C1 pD2C2 + TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar ); + TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar ); + if ( TopVar1 == TopVar2 ) + { + if ( pD1C1->iVar == pD1C2->iVar ) + { + if ( pD2C1->iVar != pD2C2->iVar ) + return 0; + pD1C1 = pD1C1->pHNext; + pD1C2 = pD1C2->pHNext; + pD2C1 = pD2C1->pHNext; + pD2C2 = pD2C2->pHNext; + } + else + { + if ( pD2C1->iVar == pD2C2->iVar ) + return 0; + if ( pD1C1->iVar < pD1C2->iVar ) + { + if ( pD2C1->iVar > pD2C2->iVar ) + return 0; + pD1C1 = pD1C1->pHNext; + pD2C1 = pD2C1->pHNext; + } + else + { + if ( pD2C1->iVar < pD2C2->iVar ) + return 0; + pD1C2 = pD1C2->pHNext; + pD2C2 = pD2C2->pHNext; + } + } + } + else if ( TopVar1 < TopVar2 ) + { + if ( pD1C1->iVar != pD1C2->iVar ) + return 0; + pD1C1 = pD1C1->pHNext; + pD1C2 = pD1C2->pHNext; + } + else + { + if ( pD2C1->iVar != pD2C2->iVar ) + return 0; + pD2C1 = pD2C1->pHNext; + pD2C2 = pD2C2->pHNext; + } + break; + default: + assert( 0 ); + break; + } + + Code = pD1C1? 8: 0; + Code |= pD1C2? 4: 0; + Code |= pD2C1? 2: 0; + Code |= pD2C2? 1: 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Allocates the storage for cubes pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_PairAllocStorage( Fxu_Var * pVar, int nCubes ) +{ + int k; +// assert( pVar->nCubes == 0 ); + pVar->nCubes = nCubes; + // allocate memory for all the pairs + pVar->ppPairs = ALLOC( Fxu_Pair **, nCubes ); + pVar->ppPairs[0] = ALLOC( Fxu_Pair *, nCubes * nCubes ); + memset( pVar->ppPairs[0], 0, sizeof(Fxu_Pair *) * nCubes * nCubes ); + for ( k = 1; k < nCubes; k++ ) + pVar->ppPairs[k] = pVar->ppPairs[k-1] + nCubes; +} + +/**Function************************************************************* + + Synopsis [Clears all pairs associated with this cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_PairClearStorage( Fxu_Cube * pCube ) +{ + Fxu_Var * pVar; + int i; + pVar = pCube->pVar; + for ( i = 0; i < pVar->nCubes; i++ ) + { + pVar->ppPairs[pCube->iCube][i] = NULL; + pVar->ppPairs[i][pCube->iCube] = NULL; + } +} + +/**Function************************************************************* + + Synopsis [Clears all pairs associated with this cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_PairFreeStorage( Fxu_Var * pVar ) +{ + if ( pVar->ppPairs ) + { + FREE( pVar->ppPairs[0] ); + FREE( pVar->ppPairs ); + } +} + +/**Function************************************************************* + + Synopsis [Adds the pair to storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Pair * Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ) +{ + Fxu_Pair * pPair; + assert( pCube1->pVar == pCube2->pVar ); + pPair = MEM_ALLOC_FXU( p, Fxu_Pair, 1 ); + memset( pPair, 0, sizeof(Fxu_Pair) ); + pPair->pCube1 = pCube1; + pPair->pCube2 = pCube2; + pPair->iCube1 = pCube1->iCube; + pPair->iCube2 = pCube2->iCube; + return pPair; +} + +/**Function************************************************************* + + Synopsis [Adds the pair to storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_PairAdd( Fxu_Pair * pPair ) +{ + Fxu_Var * pVar; + + pVar = pPair->pCube1->pVar; + assert( pVar == pPair->pCube2->pVar ); + + pVar->ppPairs[pPair->iCube1][pPair->iCube2] = pPair; + pVar->ppPairs[pPair->iCube2][pPair->iCube1] = pPair; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/fxu/fxuPrint.c b/abc70930/src/opt/fxu/fxuPrint.c new file mode 100644 index 00000000..232b109a --- /dev/null +++ b/abc70930/src/opt/fxu/fxuPrint.c @@ -0,0 +1,195 @@ +/**CFile**************************************************************** + + FileName [fxuPrint.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Various printing procedures.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuPrint.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fxuInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixPrint( FILE * pFile, Fxu_Matrix * p ) +{ + Fxu_Var * pVar; + Fxu_Cube * pCube; + Fxu_Double * pDiv; + Fxu_Single * pSingle; + Fxu_Lit * pLit; + Fxu_Pair * pPair; + int i, LastNum; + int fStdout; + + fStdout = 1; + if ( pFile == NULL ) + { + pFile = fopen( "matrix.txt", "w" ); + fStdout = 0; + } + + fprintf( pFile, "Matrix has %d vars, %d cubes, %d literals, %d divisors.\n", + p->lVars.nItems, p->lCubes.nItems, p->nEntries, p->nDivs ); + fprintf( pFile, "Divisors selected so far: single = %d, double = %d.\n", + p->nDivs1, p->nDivs2 ); + fprintf( pFile, "\n" ); + + // print the numbers on top of the matrix + for ( i = 0; i < 12; i++ ) + fprintf( pFile, " " ); + Fxu_MatrixForEachVariable( p, pVar ) + fprintf( pFile, "%d", pVar->iVar % 10 ); + fprintf( pFile, "\n" ); + + // print the rows + Fxu_MatrixForEachCube( p, pCube ) + { + fprintf( pFile, "%4d", pCube->iCube ); + fprintf( pFile, " " ); + fprintf( pFile, "%4d", pCube->pVar->iVar ); + fprintf( pFile, " " ); + + // print the literals + LastNum = -1; + Fxu_CubeForEachLiteral( pCube, pLit ) + { + for ( i = LastNum + 1; i < pLit->pVar->iVar; i++ ) + fprintf( pFile, "." ); + fprintf( pFile, "1" ); + LastNum = i; + } + for ( i = LastNum + 1; i < p->lVars.nItems; i++ ) + fprintf( pFile, "." ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, "\n" ); + + // print the double-cube divisors + fprintf( pFile, "The double divisors are:\n" ); + Fxu_MatrixForEachDouble( p, pDiv, i ) + { + fprintf( pFile, "Divisor #%3d (lit=%d,%d) (w=%2d): ", + pDiv->Num, pDiv->lPairs.pHead->nLits1, + pDiv->lPairs.pHead->nLits2, pDiv->Weight ); + Fxu_DoubleForEachPair( pDiv, pPair ) + fprintf( pFile, " <%d, %d> (b=%d)", + pPair->pCube1->iCube, pPair->pCube2->iCube, pPair->nBase ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, "\n" ); + + // print the divisors associated with each cube + fprintf( pFile, "The cubes are:\n" ); + Fxu_MatrixForEachCube( p, pCube ) + { + fprintf( pFile, "Cube #%3d: ", pCube->iCube ); + if ( pCube->pVar->ppPairs ) + Fxu_CubeForEachPair( pCube, pPair, i ) + fprintf( pFile, " <%d %d> (d=%d) (b=%d)", + pPair->iCube1, pPair->iCube2, pPair->pDiv->Num, pPair->nBase ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, "\n" ); + + // print the single-cube divisors + fprintf( pFile, "The single divisors are:\n" ); + Fxu_MatrixForEachSingle( p, pSingle ) + { + fprintf( pFile, "Single-cube divisor #%5d: Var1 = %4d. Var2 = %4d. Weight = %2d\n", + pSingle->Num, pSingle->pVar1->iVar, pSingle->pVar2->iVar, pSingle->Weight ); + } + fprintf( pFile, "\n" ); + +/* + { + int Index; + fprintf( pFile, "Distribution of divisors in the hash table:\n" ); + for ( Index = 0; Index < p->nTableSize; Index++ ) + fprintf( pFile, " %d", p->pTable[Index].nItems ); + fprintf( pFile, "\n" ); + } +*/ + if ( !fStdout ) + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixPrintDivisorProfile( FILE * pFile, Fxu_Matrix * p ) +{ + Fxu_Double * pDiv; + int WeightMax; + int * pProfile; + int Counter1; // the number of -1 weight + int CounterL; // the number of less than -1 weight + int i; + + WeightMax = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); + pProfile = ALLOC( int, (WeightMax + 1) ); + memset( pProfile, 0, sizeof(int) * (WeightMax + 1) ); + + Counter1 = 0; + CounterL = 0; + Fxu_MatrixForEachDouble( p, pDiv, i ) + { + assert( pDiv->Weight <= WeightMax ); + if ( pDiv->Weight == -1 ) + Counter1++; + else if ( pDiv->Weight < 0 ) + CounterL++; + else + pProfile[ pDiv->Weight ]++; + } + + fprintf( pFile, "The double divisors profile:\n" ); + fprintf( pFile, "Weight < -1 divisors = %6d\n", CounterL ); + fprintf( pFile, "Weight -1 divisors = %6d\n", Counter1 ); + for ( i = 0; i <= WeightMax; i++ ) + if ( pProfile[i] ) + fprintf( pFile, "Weight %3d divisors = %6d\n", i, pProfile[i] ); + fprintf( pFile, "End of divisor profile printout\n" ); + FREE( pProfile ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/fxu/fxuReduce.c b/abc70930/src/opt/fxu/fxuReduce.c new file mode 100644 index 00000000..0ab8a157 --- /dev/null +++ b/abc70930/src/opt/fxu/fxuReduce.c @@ -0,0 +1,204 @@ +/**CFile**************************************************************** + + FileName [fxuReduce.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Procedures to reduce the number of considered cube pairs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuReduce.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fxuInt.h" +#include "fxu.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Precomputes the pairs to use for creating two-cube divisors.] + + Description [This procedure takes the matrix with variables and cubes + allocated (p), the original covers of the nodes (i-sets) and their number + (ppCovers,nCovers). The maximum number of pairs to compute and the total + number of pairs in existence. This procedure adds to the storage of + divisors exactly the given number of pairs (nPairsMax) while taking + first those pairs that have the smallest number of literals in their + cube-free form.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax ) +{ + unsigned char * pnLitsDiff; // storage for the counters of diff literals + int * pnPairCounters; // the counters of pairs for each number of diff literals + Fxu_Cube * pCubeFirst, * pCubeLast; + Fxu_Cube * pCube1, * pCube2; + Fxu_Var * pVar; + int nCubes, nBitsMax, nSum; + int CutOffNum, CutOffQuant; + int iPair, iQuant, k, c; + int clk = clock(); + char * pSopCover; + int nFanins; + + assert( nPairsMax < nPairsTotal ); + + // allocate storage for counter of diffs + pnLitsDiff = ALLOC( unsigned char, nPairsTotal ); + // go through the covers and precompute the distances between the pairs + iPair = 0; + nBitsMax = -1; + for ( c = 0; c < vCovers->nSize; c++ ) + if ( pSopCover = vCovers->pArray[c] ) + { + nFanins = Abc_SopGetVarNum(pSopCover); + // precompute the differences + Fxu_CountPairDiffs( pSopCover, pnLitsDiff + iPair ); + // update the counter + nCubes = Abc_SopGetCubeNum( pSopCover ); + iPair += nCubes * (nCubes - 1) / 2; + if ( nBitsMax < nFanins ) + nBitsMax = nFanins; + } + assert( iPair == nPairsTotal ); + + // allocate storage for counters of cube pairs by difference + pnPairCounters = ALLOC( int, 2 * nBitsMax ); + memset( pnPairCounters, 0, sizeof(int) * 2 * nBitsMax ); + // count the number of different pairs + for ( k = 0; k < nPairsTotal; k++ ) + pnPairCounters[ pnLitsDiff[k] ]++; + // determine what pairs to take starting from the lower + // so that there would be exactly pPairsMax pairs + if ( pnPairCounters[0] != 0 ) + { + printf( "The SOPs of the nodes are not cube-free. Run \"bdd; sop\" before \"fx\".\n" ); + return 0; + } + if ( pnPairCounters[1] != 0 ) + { + printf( "The SOPs of the nodes are not SCC-free. Run \"bdd; sop\" before \"fx\".\n" ); + return 0; + } + assert( pnPairCounters[0] == 0 ); // otherwise, covers are not dup-free + assert( pnPairCounters[1] == 0 ); // otherwise, covers are not SCC-free + nSum = 0; + for ( k = 0; k < 2 * nBitsMax; k++ ) + { + nSum += pnPairCounters[k]; + if ( nSum >= nPairsMax ) + { + CutOffNum = k; + CutOffQuant = pnPairCounters[k] - (nSum - nPairsMax); + break; + } + } + FREE( pnPairCounters ); + + // set to 0 all the pairs above the cut-off number and quantity + iQuant = 0; + iPair = 0; + for ( k = 0; k < nPairsTotal; k++ ) + if ( pnLitsDiff[k] > CutOffNum ) + pnLitsDiff[k] = 0; + else if ( pnLitsDiff[k] == CutOffNum ) + { + if ( iQuant++ >= CutOffQuant ) + pnLitsDiff[k] = 0; + else + iPair++; + } + else + iPair++; + assert( iPair == nPairsMax ); + + // collect the corresponding pairs and add the divisors + iPair = 0; + for ( c = 0; c < vCovers->nSize; c++ ) + if ( pSopCover = vCovers->pArray[c] ) + { + // get the var + pVar = p->ppVars[2*c+1]; + // get the first cube + pCubeFirst = pVar->pFirst; + // get the last cube + pCubeLast = pCubeFirst; + for ( k = 0; k < pVar->nCubes; k++ ) + pCubeLast = pCubeLast->pNext; + assert( pCubeLast == NULL || pCubeLast->pVar != pVar ); + + // go through the cube pairs + for ( pCube1 = pCubeFirst; pCube1 != pCubeLast; pCube1 = pCube1->pNext ) + for ( pCube2 = pCube1->pNext; pCube2 != pCubeLast; pCube2 = pCube2->pNext ) + if ( pnLitsDiff[iPair++] ) + { // create the divisors for this pair + Fxu_MatrixAddDivisor( p, pCube1, pCube2 ); + } + } + assert( iPair == nPairsTotal ); + FREE( pnLitsDiff ); +//PRT( "Preprocess", clock() - clk ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Counts the differences in each cube pair in the cover.] + + Description [Takes the cover (pCover) and the array where the + diff counters go (pDiffs). The array pDiffs should have as many + entries as there are different pairs of cubes in the cover: n(n-1)/2. + Fills out the array pDiffs with the following info: For each cube + pair, included in the array is the number of literals in both cubes + after they are made cube free.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] ) +{ + char * pCube1, * pCube2; + int nOnes, nCubePairs, nFanins, v; + nCubePairs = 0; + nFanins = Abc_SopGetVarNum(pCover); + Abc_SopForEachCube( pCover, nFanins, pCube1 ) + Abc_SopForEachCube( pCube1, nFanins, pCube2 ) + { + if ( pCube1 == pCube2 ) + continue; + nOnes = 0; + for ( v = 0; v < nFanins; v++ ) + nOnes += (pCube1[v] != pCube2[v]); + pDiffs[nCubePairs++] = nOnes; + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/fxu/fxuSelect.c b/abc70930/src/opt/fxu/fxuSelect.c new file mode 100644 index 00000000..b9265487 --- /dev/null +++ b/abc70930/src/opt/fxu/fxuSelect.c @@ -0,0 +1,603 @@ +/**CFile**************************************************************** + + FileName [fxuSelect.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Procedures to select the best divisor/complement pair.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuSelect.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fxuInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define MAX_SIZE_LOOKAHEAD 20 + +static int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar ); + +static Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle ); +static Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble ); +static Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble ); + +Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p, + int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ); +void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble, + int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Selects the best pair (Single,Double) and returns their weight.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble ) +{ + // the top entries + Fxu_Single * pSingles[MAX_SIZE_LOOKAHEAD]; + Fxu_Double * pDoubles[MAX_SIZE_LOOKAHEAD]; + // the complements + Fxu_Double * pSCompl[MAX_SIZE_LOOKAHEAD]; + Fxu_Single * pDComplS[MAX_SIZE_LOOKAHEAD]; + Fxu_Double * pDComplD[MAX_SIZE_LOOKAHEAD]; + Fxu_Pair * pPair; + int nSingles; + int nDoubles; + int i; + int WeightBest; + int WeightCur; + int iNum, fBestS; + + // collect the top entries from the queues + for ( nSingles = 0; nSingles < MAX_SIZE_LOOKAHEAD; nSingles++ ) + { + pSingles[nSingles] = Fxu_HeapSingleGetMax( p->pHeapSingle ); + if ( pSingles[nSingles] == NULL ) + break; + } + // put them back into the queue + for ( i = 0; i < nSingles; i++ ) + if ( pSingles[i] ) + Fxu_HeapSingleInsert( p->pHeapSingle, pSingles[i] ); + + // the same for doubles + // collect the top entries from the queues + for ( nDoubles = 0; nDoubles < MAX_SIZE_LOOKAHEAD; nDoubles++ ) + { + pDoubles[nDoubles] = Fxu_HeapDoubleGetMax( p->pHeapDouble ); + if ( pDoubles[nDoubles] == NULL ) + break; + } + // put them back into the queue + for ( i = 0; i < nDoubles; i++ ) + if ( pDoubles[i] ) + Fxu_HeapDoubleInsert( p->pHeapDouble, pDoubles[i] ); + + // for each single, find the complement double (if any) + for ( i = 0; i < nSingles; i++ ) + if ( pSingles[i] ) + pSCompl[i] = Fxu_MatrixFindComplementSingle( p, pSingles[i] ); + + // for each double, find the complement single or double (if any) + for ( i = 0; i < nDoubles; i++ ) + if ( pDoubles[i] ) + { + pPair = pDoubles[i]->lPairs.pHead; + if ( pPair->nLits1 == 1 && pPair->nLits2 == 1 ) + { + pDComplS[i] = Fxu_MatrixFindComplementDouble2( p, pDoubles[i] ); + pDComplD[i] = NULL; + } +// else if ( pPair->nLits1 == 2 && pPair->nLits2 == 2 ) +// { +// pDComplS[i] = NULL; +// pDComplD[i] = Fxu_MatrixFindComplementDouble4( p, pDoubles[i] ); +// } + else + { + pDComplS[i] = NULL; + pDComplD[i] = NULL; + } + } + + // select the best pair + WeightBest = -1; + for ( i = 0; i < nSingles; i++ ) + { + WeightCur = pSingles[i]->Weight; + if ( pSCompl[i] ) + { + // add the weight of the double + WeightCur += pSCompl[i]->Weight; + // there is no need to implement this double, so... + pPair = pSCompl[i]->lPairs.pHead; + WeightCur += pPair->nLits1 + pPair->nLits2; + } + if ( WeightBest < WeightCur ) + { + WeightBest = WeightCur; + *ppSingle = pSingles[i]; + *ppDouble = pSCompl[i]; + fBestS = 1; + iNum = i; + } + } + for ( i = 0; i < nDoubles; i++ ) + { + WeightCur = pDoubles[i]->Weight; + if ( pDComplS[i] ) + { + // add the weight of the single + WeightCur += pDComplS[i]->Weight; + // there is no need to implement this double, so... + pPair = pDoubles[i]->lPairs.pHead; + WeightCur += pPair->nLits1 + pPair->nLits2; + } + if ( WeightBest < WeightCur ) + { + WeightBest = WeightCur; + *ppSingle = pDComplS[i]; + *ppDouble = pDoubles[i]; + fBestS = 0; + iNum = i; + } + } +/* + // print the statistics + printf( "\n" ); + for ( i = 0; i < nSingles; i++ ) + { + printf( "Single #%d: Weight = %3d. ", i, pSingles[i]->Weight ); + printf( "Compl: " ); + if ( pSCompl[i] == NULL ) + printf( "None." ); + else + printf( "D Weight = %3d Sum = %3d", + pSCompl[i]->Weight, pSCompl[i]->Weight + pSingles[i]->Weight ); + printf( "\n" ); + } + printf( "\n" ); + for ( i = 0; i < nDoubles; i++ ) + { + printf( "Double #%d: Weight = %3d. ", i, pDoubles[i]->Weight ); + printf( "Compl: " ); + if ( pDComplS[i] == NULL && pDComplD[i] == NULL ) + printf( "None." ); + else if ( pDComplS[i] ) + printf( "S Weight = %3d Sum = %3d", + pDComplS[i]->Weight, pDComplS[i]->Weight + pDoubles[i]->Weight ); + else if ( pDComplD[i] ) + printf( "D Weight = %3d Sum = %3d", + pDComplD[i]->Weight, pDComplD[i]->Weight + pDoubles[i]->Weight ); + printf( "\n" ); + } + if ( WeightBest == -1 ) + printf( "Selected NONE\n" ); + else + { + printf( "Selected = %s. ", fBestS? "S": "D" ); + printf( "Number = %d. ", iNum ); + printf( "Weight = %d.\n", WeightBest ); + } + printf( "\n" ); +*/ + return WeightBest; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle ) +{ +// int * pValue2Node = p->pValue2Node; + int iVar1, iVar2; + int iVar1C, iVar2C; + // get the variables of this single div + iVar1 = pSingle->pVar1->iVar; + iVar2 = pSingle->pVar2->iVar; + iVar1C = Fxu_MatrixFindComplement( p, iVar1 ); + iVar2C = Fxu_MatrixFindComplement( p, iVar2 ); + if ( iVar1C == -1 || iVar2C == -1 ) + return NULL; + assert( iVar1C < iVar2C ); + return Fxu_MatrixFindDouble( p, &iVar1C, &iVar2C, 1, 1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble ) +{ +// int * pValue2Node = p->pValue2Node; + int piVarsC1[10], piVarsC2[10]; + int nVarsC1, nVarsC2; + int iVar1, iVar2, iVarTemp; + int iVar1C, iVar2C; + Fxu_Single * pSingle; + + // get the variables of this double div + Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 ); + assert( nVarsC1 == 1 ); + assert( nVarsC2 == 1 ); + iVar1 = piVarsC1[0]; + iVar2 = piVarsC2[0]; + assert( iVar1 < iVar2 ); + + iVar1C = Fxu_MatrixFindComplement( p, iVar1 ); + iVar2C = Fxu_MatrixFindComplement( p, iVar2 ); + if ( iVar1C == -1 || iVar2C == -1 ) + return NULL; + + // go through the queque and find this one +// assert( iVar1C < iVar2C ); + if ( iVar1C > iVar2C ) + { + iVarTemp = iVar1C; + iVar1C = iVar2C; + iVar2C = iVarTemp; + } + + Fxu_MatrixForEachSingle( p, pSingle ) + if ( pSingle->pVar1->iVar == iVar1C && pSingle->pVar2->iVar == iVar2C ) + return pSingle; + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble ) +{ +// int * pValue2Node = p->pValue2Node; + int piVarsC1[10], piVarsC2[10]; + int nVarsC1, nVarsC2; + int iVar11, iVar12, iVar21, iVar22; + int iVar11C, iVar12C, iVar21C, iVar22C; + int RetValue; + + // get the variables of this double div + Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 ); + assert( nVarsC1 == 2 && nVarsC2 == 2 ); + + iVar11 = piVarsC1[0]; + iVar12 = piVarsC1[1]; + iVar21 = piVarsC2[0]; + iVar22 = piVarsC2[1]; + assert( iVar11 < iVar21 ); + + iVar11C = Fxu_MatrixFindComplement( p, iVar11 ); + iVar12C = Fxu_MatrixFindComplement( p, iVar12 ); + iVar21C = Fxu_MatrixFindComplement( p, iVar21 ); + iVar22C = Fxu_MatrixFindComplement( p, iVar22 ); + if ( iVar11C == -1 || iVar12C == -1 || iVar21C == -1 || iVar22C == -1 ) + return NULL; + if ( iVar11C != iVar21 || iVar12C != iVar22 || + iVar21C != iVar11 || iVar22C != iVar12 ) + return NULL; + + // a'b' + ab => a'b + ab' + // a'b + ab' => a'b' + ab + // swap the second pair in each cube + RetValue = piVarsC1[1]; + piVarsC1[1] = piVarsC2[1]; + piVarsC2[1] = RetValue; + + return Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, 2, 2 ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar ) +{ + return iVar ^ 1; +/* +// int * pValue2Node = p->pValue2Node; + int iVarC; + int iNode; + int Beg, End; + + // get the nodes + iNode = pValue2Node[iVar]; + // get the first node with the same var + for ( Beg = iVar; Beg >= 0; Beg-- ) + if ( pValue2Node[Beg] != iNode ) + { + Beg++; + break; + } + // get the last node with the same var + for ( End = iVar; ; End++ ) + if ( pValue2Node[End] != iNode ) + { + End--; + break; + } + + // if one of the vars is not binary, quit + if ( End - Beg > 1 ) + return -1; + + // get the complements + if ( iVar == Beg ) + iVarC = End; + else if ( iVar == End ) + iVarC = Beg; + else + { + assert( 0 ); + } + return iVarC; +*/ +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble, + int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 ) +{ + Fxu_Pair * pPair; + Fxu_Lit * pLit1, * pLit2; + int nLits1, nLits2; + + // get the first pair + pPair = pDouble->lPairs.pHead; + // init the parameters + nLits1 = 0; + nLits2 = 0; + pLit1 = pPair->pCube1->lLits.pHead; + pLit2 = pPair->pCube2->lLits.pHead; + while ( 1 ) + { + if ( pLit1 && pLit2 ) + { + if ( pLit1->iVar == pLit2->iVar ) + { // ensure cube-free + pLit1 = pLit1->pHNext; + pLit2 = pLit2->pHNext; + } + else if ( pLit1->iVar < pLit2->iVar ) + { + piVarsC1[nLits1++] = pLit1->iVar; + pLit1 = pLit1->pHNext; + } + else + { + piVarsC2[nLits2++] = pLit2->iVar; + pLit2 = pLit2->pHNext; + } + } + else if ( pLit1 && !pLit2 ) + { + piVarsC1[nLits1++] = pLit1->iVar; + pLit1 = pLit1->pHNext; + } + else if ( !pLit1 && pLit2 ) + { + piVarsC2[nLits2++] = pLit2->iVar; + pLit2 = pLit2->pHNext; + } + else + break; + } + *pnVarsC1 = nLits1; + *pnVarsC2 = nLits2; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p, + int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ) +{ + int piVarsC1_[100], piVarsC2_[100]; + int nVarsC1_, nVarsC2_, i; + Fxu_Double * pDouble; + Fxu_Pair * pPair; + unsigned Key; + + assert( nVarsC1 > 0 ); + assert( nVarsC2 > 0 ); + assert( piVarsC1[0] < piVarsC2[0] ); + + // get the hash key + Key = Fxu_PairHashKeyArray( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 ); + + // check if the divisor for this pair already exists + Key %= p->nTableSize; + Fxu_TableForEachDouble( p, Key, pDouble ) + { + pPair = pDouble->lPairs.pHead; + if ( pPair->nLits1 != nVarsC1 ) + continue; + if ( pPair->nLits2 != nVarsC2 ) + continue; + // get the cubes of this divisor + Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1_, piVarsC2_, &nVarsC1_, &nVarsC2_ ); + // compare lits of the first cube + for ( i = 0; i < nVarsC1; i++ ) + if ( piVarsC1[i] != piVarsC1_[i] ) + break; + if ( i != nVarsC1 ) + continue; + // compare lits of the second cube + for ( i = 0; i < nVarsC2; i++ ) + if ( piVarsC2[i] != piVarsC2_[i] ) + break; + if ( i != nVarsC2 ) + continue; + return pDouble; + } + return NULL; +} + + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_SelectSCD( Fxu_Matrix * p, int WeightLimit, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 ) +{ +// int * pValue2Node = p->pValue2Node; + Fxu_Var * pVar1; + Fxu_Var * pVar2, * pVarTemp; + Fxu_Lit * pLitV, * pLitH; + int Coin; + int CounterAll; + int CounterTest; + int WeightCur; + int WeightBest; + + CounterAll = 0; + CounterTest = 0; + + WeightBest = -10; + + // iterate through the columns in the matrix + Fxu_MatrixForEachVariable( p, pVar1 ) + { + // start collecting the affected vars + Fxu_MatrixRingVarsStart( p ); + + // go through all the literals of this variable + for ( pLitV = pVar1->lLits.pHead; pLitV; pLitV = pLitV->pVNext ) + { + // for this literal, go through all the horizontal literals + for ( pLitH = pLitV->pHNext; pLitH; pLitH = pLitH->pHNext ) + { + // get another variable + pVar2 = pLitH->pVar; + CounterAll++; + // skip the var if it is already used + if ( pVar2->pOrder ) + continue; + // skip the var if it belongs to the same node +// if ( pValue2Node[pVar1->iVar] == pValue2Node[pVar2->iVar] ) +// continue; + // collect the var + Fxu_MatrixRingVarsAdd( p, pVar2 ); + } + } + // stop collecting the selected vars + Fxu_MatrixRingVarsStop( p ); + + // iterate through the selected vars + Fxu_MatrixForEachVarInRing( p, pVar2 ) + { + CounterTest++; + + // count the coincidence + Coin = Fxu_SingleCountCoincidence( p, pVar1, pVar2 ); + assert( Coin > 0 ); + + // get the new weight + WeightCur = Coin - 2; + + // compare the weights + if ( WeightBest < WeightCur ) + { + WeightBest = WeightCur; + *ppVar1 = pVar1; + *ppVar2 = pVar2; + } + } + // unmark the vars + Fxu_MatrixForEachVarInRingSafe( p, pVar2, pVarTemp ) + pVar2->pOrder = NULL; + Fxu_MatrixRingVarsReset( p ); + } + +// if ( WeightBest == WeightLimit ) +// return -1; + return WeightBest; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/fxu/fxuSingle.c b/abc70930/src/opt/fxu/fxuSingle.c new file mode 100644 index 00000000..73d9a76c --- /dev/null +++ b/abc70930/src/opt/fxu/fxuSingle.c @@ -0,0 +1,284 @@ +/**CFile**************************************************************** + + FileName [fxuSingle.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Procedures to compute the set of single-cube divisors.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuSingle.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fxuInt.h" +#include "vec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes and adds all single-cube divisors to storage.] + + Description [This procedure should be called once when the matrix is + already contructed before the process of logic extraction begins..] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax ) +{ + Fxu_Var * pVar; + Vec_Ptr_t * vSingles; + int i, k; + // set the weight limit + p->nWeightLimit = 1 - fUse0; + // iterate through columns in the matrix and collect single-cube divisors + vSingles = Vec_PtrAlloc( 10000 ); + Fxu_MatrixForEachVariable( p, pVar ) + Fxu_MatrixComputeSinglesOneCollect( p, pVar, vSingles ); + p->nSingleTotal = Vec_PtrSize(vSingles) / 3; + // check if divisors should be filtered + if ( Vec_PtrSize(vSingles) > nSingleMax ) + { + int * pWeigtCounts, nDivCount, Weight, i, c;; + assert( Vec_PtrSize(vSingles) % 3 == 0 ); + // count how many divisors have the given weight + pWeigtCounts = ALLOC( int, 1000 ); + memset( pWeigtCounts, 0, sizeof(int) * 1000 ); + for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 ) + { + Weight = (int)Vec_PtrEntry(vSingles, i); + if ( Weight >= 999 ) + pWeigtCounts[999]++; + else + pWeigtCounts[Weight]++; + } + // select the bound on the weight (above this bound, singles will be included) + nDivCount = 0; + for ( c = 999; c >= 0; c-- ) + { + nDivCount += pWeigtCounts[c]; + if ( nDivCount >= nSingleMax ) + break; + } + free( pWeigtCounts ); + // collect singles with the given costs + k = 0; + for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 ) + { + Weight = (int)Vec_PtrEntry(vSingles, i); + if ( Weight < c ) + continue; + Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-2) ); + Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-1) ); + Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i) ); + if ( k/3 == nSingleMax ) + break; + } + Vec_PtrShrink( vSingles, k ); + // adjust the weight limit + p->nWeightLimit = c; + } + // collect the selected divisors + assert( Vec_PtrSize(vSingles) % 3 == 0 ); + for ( i = 0; i < Vec_PtrSize(vSingles); i += 3 ) + { + Fxu_MatrixAddSingle( p, + Vec_PtrEntry(vSingles,i), + Vec_PtrEntry(vSingles,i+1), + (int)Vec_PtrEntry(vSingles,i+2) ); + } + Vec_PtrFree( vSingles ); +} + +/**Function************************************************************* + + Synopsis [Adds the single-cube divisors associated with a new column.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles ) +{ + Fxu_Lit * pLitV, * pLitH; + Fxu_Var * pVar2; + int Coin; + int WeightCur; + + // start collecting the affected vars + Fxu_MatrixRingVarsStart( p ); + // go through all the literals of this variable + for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext ) + // for this literal, go through all the horizontal literals + for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev ) + { + // get another variable + pVar2 = pLitH->pVar; + // skip the var if it is already used + if ( pVar2->pOrder ) + continue; + // skip the var if it belongs to the same node +// if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] ) +// continue; + // collect the var + Fxu_MatrixRingVarsAdd( p, pVar2 ); + } + // stop collecting the selected vars + Fxu_MatrixRingVarsStop( p ); + + // iterate through the selected vars + Fxu_MatrixForEachVarInRing( p, pVar2 ) + { + // count the coincidence + Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar ); + assert( Coin > 0 ); + // get the new weight + WeightCur = Coin - 2; + // peformance fix (August 24, 2007) + if ( WeightCur >= p->nWeightLimit ) + { + Vec_PtrPush( vSingles, pVar2 ); + Vec_PtrPush( vSingles, pVar ); + Vec_PtrPush( vSingles, (void *)WeightCur ); + } + } + + // unmark the vars + Fxu_MatrixRingVarsUnmark( p ); +} + +/**Function************************************************************* + + Synopsis [Adds the single-cube divisors associated with a new column.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar ) +{ + Fxu_Lit * pLitV, * pLitH; + Fxu_Var * pVar2; + int Coin; + int WeightCur; + + // start collecting the affected vars + Fxu_MatrixRingVarsStart( p ); + // go through all the literals of this variable + for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext ) + // for this literal, go through all the horizontal literals + for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev ) + { + // get another variable + pVar2 = pLitH->pVar; + // skip the var if it is already used + if ( pVar2->pOrder ) + continue; + // skip the var if it belongs to the same node +// if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] ) +// continue; + // collect the var + Fxu_MatrixRingVarsAdd( p, pVar2 ); + } + // stop collecting the selected vars + Fxu_MatrixRingVarsStop( p ); + + // iterate through the selected vars + Fxu_MatrixForEachVarInRing( p, pVar2 ) + { + // count the coincidence + Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar ); + assert( Coin > 0 ); + // get the new weight + WeightCur = Coin - 2; + // peformance fix (August 24, 2007) +// if ( WeightCur >= 0 ) +// Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur ); + if ( WeightCur >= p->nWeightLimit ) + Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur ); + } + // unmark the vars + Fxu_MatrixRingVarsUnmark( p ); +} + +/**Function************************************************************* + + Synopsis [Computes the coincidence count of two columns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 ) +{ + Fxu_Lit * pLit1, * pLit2; + int Result; + + // compute the coincidence count + Result = 0; + pLit1 = pVar1->lLits.pHead; + pLit2 = pVar2->lLits.pHead; + while ( 1 ) + { + if ( pLit1 && pLit2 ) + { + if ( pLit1->pCube->pVar->iVar == pLit2->pCube->pVar->iVar ) + { // the variables are the same + if ( pLit1->iCube == pLit2->iCube ) + { // the literals are the same + pLit1 = pLit1->pVNext; + pLit2 = pLit2->pVNext; + // add this literal to the coincidence + Result++; + } + else if ( pLit1->iCube < pLit2->iCube ) + pLit1 = pLit1->pVNext; + else + pLit2 = pLit2->pVNext; + } + else if ( pLit1->pCube->pVar->iVar < pLit2->pCube->pVar->iVar ) + pLit1 = pLit1->pVNext; + else + pLit2 = pLit2->pVNext; + } + else if ( pLit1 && !pLit2 ) + pLit1 = pLit1->pVNext; + else if ( !pLit1 && pLit2 ) + pLit2 = pLit2->pVNext; + else + break; + } + return Result; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/fxu/fxuUpdate.c b/abc70930/src/opt/fxu/fxuUpdate.c new file mode 100644 index 00000000..274f79f6 --- /dev/null +++ b/abc70930/src/opt/fxu/fxuUpdate.c @@ -0,0 +1,806 @@ +/**CFile**************************************************************** + + FileName [fxuUpdate.c] + + PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] + + Synopsis [Updating the sparse matrix when divisors are accepted.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fxuUpdate.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "fxuInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Fxu_UpdateDoublePairs( Fxu_Matrix * p, Fxu_Double * pDouble, Fxu_Var * pVar ); +static void Fxu_UpdateMatrixDoubleCreateCubes( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, Fxu_Double * pDiv ); +static void Fxu_UpdateMatrixDoubleClean( Fxu_Matrix * p, Fxu_Cube * pCubeUse, Fxu_Cube * pCubeRem ); +static void Fxu_UpdateMatrixSingleClean( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, Fxu_Var * pVarNew ); + +static void Fxu_UpdateCreateNewVars( Fxu_Matrix * p, Fxu_Var ** ppVarC, Fxu_Var ** ppVarD, int nCubes ); +static int Fxu_UpdatePairCompare( Fxu_Pair ** ppP1, Fxu_Pair ** ppP2 ); +static void Fxu_UpdatePairsSort( Fxu_Matrix * p, Fxu_Double * pDouble ); + +static void Fxu_UpdateCleanOldDoubles( Fxu_Matrix * p, Fxu_Double * pDiv, Fxu_Cube * pCube ); +static void Fxu_UpdateAddNewDoubles( Fxu_Matrix * p, Fxu_Cube * pCube ); +static void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p ); +static void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Updates the matrix after selecting two divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_Update( Fxu_Matrix * p, Fxu_Single * pSingle, Fxu_Double * pDouble ) +{ + Fxu_Cube * pCube, * pCubeNew; + Fxu_Var * pVarC, * pVarD; + Fxu_Var * pVar1, * pVar2; + + // consider trivial cases + if ( pSingle == NULL ) + { + assert( pDouble->Weight == Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ) ); + Fxu_UpdateDouble( p ); + return; + } + if ( pDouble == NULL ) + { + assert( pSingle->Weight == Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ) ); + Fxu_UpdateSingle( p ); + return; + } + + // get the variables of the single + pVar1 = pSingle->pVar1; + pVar2 = pSingle->pVar2; + + // remove the best double from the heap + Fxu_HeapDoubleDelete( p->pHeapDouble, pDouble ); + // remove the best divisor from the table + Fxu_ListTableDelDivisor( p, pDouble ); + + // create two new columns (vars) + Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 1 ); + // create one new row (cube) + pCubeNew = Fxu_MatrixAddCube( p, pVarD, 0 ); + pCubeNew->pFirst = pCubeNew; + // set the first cube of the positive var + pVarD->pFirst = pCubeNew; + + // start collecting the affected vars and cubes + Fxu_MatrixRingCubesStart( p ); + Fxu_MatrixRingVarsStart( p ); + // add the vars + Fxu_MatrixRingVarsAdd( p, pVar1 ); + Fxu_MatrixRingVarsAdd( p, pVar2 ); + // remove the literals and collect the affected cubes + // remove the divisors associated with this cube + // add to the affected cube the literal corresponding to the new column + Fxu_UpdateMatrixSingleClean( p, pVar1, pVar2, pVarD ); + // replace each two cubes of the pair by one new cube + // the new cube contains the base and the new literal + Fxu_UpdateDoublePairs( p, pDouble, pVarC ); + // stop collecting the affected vars and cubes + Fxu_MatrixRingCubesStop( p ); + Fxu_MatrixRingVarsStop( p ); + + // add the literals to the new cube + assert( pVar1->iVar < pVar2->iVar ); + assert( Fxu_SingleCountCoincidence( p, pVar1, pVar2 ) == 0 ); + Fxu_MatrixAddLiteral( p, pCubeNew, pVar1 ); + Fxu_MatrixAddLiteral( p, pCubeNew, pVar2 ); + + // create new doubles; we cannot add them in the same loop + // because we first have to create *all* new cubes for each node + Fxu_MatrixForEachCubeInRing( p, pCube ) + Fxu_UpdateAddNewDoubles( p, pCube ); + // update the singles after removing some literals + Fxu_UpdateCleanOldSingles( p ); + + // undo the temporary rings with cubes and vars + Fxu_MatrixRingCubesUnmark( p ); + Fxu_MatrixRingVarsUnmark( p ); + // we should undo the rings before creating new singles + + // create new singles + Fxu_UpdateAddNewSingles( p, pVarC ); + Fxu_UpdateAddNewSingles( p, pVarD ); + + // recycle the divisor + MEM_FREE_FXU( p, Fxu_Double, 1, pDouble ); + p->nDivs3++; +} + +/**Function************************************************************* + + Synopsis [Updates after accepting single cube divisor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdateSingle( Fxu_Matrix * p ) +{ + Fxu_Single * pSingle; + Fxu_Cube * pCube, * pCubeNew; + Fxu_Var * pVarC, * pVarD; + Fxu_Var * pVar1, * pVar2; + + // read the best divisor from the heap + pSingle = Fxu_HeapSingleReadMax( p->pHeapSingle ); + // get the variables of this single-cube divisor + pVar1 = pSingle->pVar1; + pVar2 = pSingle->pVar2; + + // create two new columns (vars) + Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 1 ); + // create one new row (cube) + pCubeNew = Fxu_MatrixAddCube( p, pVarD, 0 ); + pCubeNew->pFirst = pCubeNew; + // set the first cube + pVarD->pFirst = pCubeNew; + + // start collecting the affected vars and cubes + Fxu_MatrixRingCubesStart( p ); + Fxu_MatrixRingVarsStart( p ); + // add the vars + Fxu_MatrixRingVarsAdd( p, pVar1 ); + Fxu_MatrixRingVarsAdd( p, pVar2 ); + // remove the literals and collect the affected cubes + // remove the divisors associated with this cube + // add to the affected cube the literal corresponding to the new column + Fxu_UpdateMatrixSingleClean( p, pVar1, pVar2, pVarD ); + // stop collecting the affected vars and cubes + Fxu_MatrixRingCubesStop( p ); + Fxu_MatrixRingVarsStop( p ); + + // add the literals to the new cube + assert( pVar1->iVar < pVar2->iVar ); + assert( Fxu_SingleCountCoincidence( p, pVar1, pVar2 ) == 0 ); + Fxu_MatrixAddLiteral( p, pCubeNew, pVar1 ); + Fxu_MatrixAddLiteral( p, pCubeNew, pVar2 ); + + // create new doubles; we cannot add them in the same loop + // because we first have to create *all* new cubes for each node + Fxu_MatrixForEachCubeInRing( p, pCube ) + Fxu_UpdateAddNewDoubles( p, pCube ); + // update the singles after removing some literals + Fxu_UpdateCleanOldSingles( p ); + // we should undo the rings before creating new singles + + // unmark the cubes + Fxu_MatrixRingCubesUnmark( p ); + Fxu_MatrixRingVarsUnmark( p ); + + // create new singles + Fxu_UpdateAddNewSingles( p, pVarC ); + Fxu_UpdateAddNewSingles( p, pVarD ); + p->nDivs1++; +} + +/**Function************************************************************* + + Synopsis [Updates the matrix after accepting a double cube divisor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdateDouble( Fxu_Matrix * p ) +{ + Fxu_Double * pDiv; + Fxu_Cube * pCube, * pCubeNew1, * pCubeNew2; + Fxu_Var * pVarC, * pVarD; + + // remove the best divisor from the heap + pDiv = Fxu_HeapDoubleGetMax( p->pHeapDouble ); + // remove the best divisor from the table + Fxu_ListTableDelDivisor( p, pDiv ); + + // create two new columns (vars) + Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 2 ); + // create two new rows (cubes) + pCubeNew1 = Fxu_MatrixAddCube( p, pVarD, 0 ); + pCubeNew1->pFirst = pCubeNew1; + pCubeNew2 = Fxu_MatrixAddCube( p, pVarD, 1 ); + pCubeNew2->pFirst = pCubeNew1; + // set the first cube + pVarD->pFirst = pCubeNew1; + + // add the literals to the new cubes + Fxu_UpdateMatrixDoubleCreateCubes( p, pCubeNew1, pCubeNew2, pDiv ); + + // start collecting the affected cubes and vars + Fxu_MatrixRingCubesStart( p ); + Fxu_MatrixRingVarsStart( p ); + // replace each two cubes of the pair by one new cube + // the new cube contains the base and the new literal + Fxu_UpdateDoublePairs( p, pDiv, pVarD ); + // stop collecting the affected cubes and vars + Fxu_MatrixRingCubesStop( p ); + Fxu_MatrixRingVarsStop( p ); + + // create new doubles; we cannot add them in the same loop + // because we first have to create *all* new cubes for each node + Fxu_MatrixForEachCubeInRing( p, pCube ) + Fxu_UpdateAddNewDoubles( p, pCube ); + // update the singles after removing some literals + Fxu_UpdateCleanOldSingles( p ); + + // undo the temporary rings with cubes and vars + Fxu_MatrixRingCubesUnmark( p ); + Fxu_MatrixRingVarsUnmark( p ); + // we should undo the rings before creating new singles + + // create new singles + Fxu_UpdateAddNewSingles( p, pVarC ); + Fxu_UpdateAddNewSingles( p, pVarD ); + + // recycle the divisor + MEM_FREE_FXU( p, Fxu_Double, 1, pDiv ); + p->nDivs2++; +} + +/**Function************************************************************* + + Synopsis [Update the pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdateDoublePairs( Fxu_Matrix * p, Fxu_Double * pDouble, Fxu_Var * pVar ) +{ + Fxu_Pair * pPair; + Fxu_Cube * pCubeUse, * pCubeRem; + int i; + + // collect and sort the pairs + Fxu_UpdatePairsSort( p, pDouble ); +// for ( i = 0; i < p->nPairsTemp; i++ ) + for ( i = 0; i < p->vPairs->nSize; i++ ) + { + // get the pair +// pPair = p->pPairsTemp[i]; + pPair = p->vPairs->pArray[i]; + // out of the two cubes, select the one which comes earlier + pCubeUse = Fxu_PairMinCube( pPair ); + pCubeRem = Fxu_PairMaxCube( pPair ); + // collect the affected cube + assert( pCubeUse->pOrder == NULL ); + Fxu_MatrixRingCubesAdd( p, pCubeUse ); + + // remove some literals from pCubeUse and all literals from pCubeRem + Fxu_UpdateMatrixDoubleClean( p, pCubeUse, pCubeRem ); + // add a literal that depends on the new variable + Fxu_MatrixAddLiteral( p, pCubeUse, pVar ); + // check the literal count + assert( pCubeUse->lLits.nItems == pPair->nBase + 1 ); + assert( pCubeRem->lLits.nItems == 0 ); + + // update the divisors by removing useless pairs + Fxu_UpdateCleanOldDoubles( p, pDouble, pCubeUse ); + Fxu_UpdateCleanOldDoubles( p, pDouble, pCubeRem ); + // remove the pair + MEM_FREE_FXU( p, Fxu_Pair, 1, pPair ); + } + p->vPairs->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [Add two cubes corresponding to the given double-cube divisor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdateMatrixDoubleCreateCubes( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, Fxu_Double * pDiv ) +{ + Fxu_Lit * pLit1, * pLit2; + Fxu_Pair * pPair; + int nBase, nLits1, nLits2; + + // fill in the SOP and copy the fanins + nBase = nLits1 = nLits2 = 0; + pPair = pDiv->lPairs.pHead; + pLit1 = pPair->pCube1->lLits.pHead; + pLit2 = pPair->pCube2->lLits.pHead; + while ( 1 ) + { + if ( pLit1 && pLit2 ) + { + if ( pLit1->iVar == pLit2->iVar ) + { // skip the cube free part + pLit1 = pLit1->pHNext; + pLit2 = pLit2->pHNext; + nBase++; + } + else if ( pLit1->iVar < pLit2->iVar ) + { // add literal to the first cube + Fxu_MatrixAddLiteral( p, pCube1, pLit1->pVar ); + // move to the next literal in this cube + pLit1 = pLit1->pHNext; + nLits1++; + } + else + { // add literal to the second cube + Fxu_MatrixAddLiteral( p, pCube2, pLit2->pVar ); + // move to the next literal in this cube + pLit2 = pLit2->pHNext; + nLits2++; + } + } + else if ( pLit1 && !pLit2 ) + { // add literal to the first cube + Fxu_MatrixAddLiteral( p, pCube1, pLit1->pVar ); + // move to the next literal in this cube + pLit1 = pLit1->pHNext; + nLits1++; + } + else if ( !pLit1 && pLit2 ) + { // add literal to the second cube + Fxu_MatrixAddLiteral( p, pCube2, pLit2->pVar ); + // move to the next literal in this cube + pLit2 = pLit2->pHNext; + nLits2++; + } + else + break; + } + assert( pPair->nLits1 == nLits1 ); + assert( pPair->nLits2 == nLits2 ); + assert( pPair->nBase == nBase ); +} + + +/**Function************************************************************* + + Synopsis [Create the node equal to double-cube divisor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdateMatrixDoubleClean( Fxu_Matrix * p, Fxu_Cube * pCubeUse, Fxu_Cube * pCubeRem ) +{ + Fxu_Lit * pLit1, * bLit1Next; + Fxu_Lit * pLit2, * bLit2Next; + + // initialize the starting literals + pLit1 = pCubeUse->lLits.pHead; + pLit2 = pCubeRem->lLits.pHead; + bLit1Next = pLit1? pLit1->pHNext: NULL; + bLit2Next = pLit2? pLit2->pHNext: NULL; + // go through the pair and remove the literals in the base + // from the first cube and all literals from the second cube + while ( 1 ) + { + if ( pLit1 && pLit2 ) + { + if ( pLit1->iVar == pLit2->iVar ) + { // this literal is present in both cubes - it belongs to the base + // mark the affected var + if ( pLit1->pVar->pOrder == NULL ) + Fxu_MatrixRingVarsAdd( p, pLit1->pVar ); + // leave the base in pCubeUse; delete it from pCubeRem + Fxu_MatrixDelLiteral( p, pLit2 ); + // step to the next literals + pLit1 = bLit1Next; + pLit2 = bLit2Next; + bLit1Next = pLit1? pLit1->pHNext: NULL; + bLit2Next = pLit2? pLit2->pHNext: NULL; + } + else if ( pLit1->iVar < pLit2->iVar ) + { // this literal is present in pCubeUse - remove it + // mark the affected var + if ( pLit1->pVar->pOrder == NULL ) + Fxu_MatrixRingVarsAdd( p, pLit1->pVar ); + // delete this literal + Fxu_MatrixDelLiteral( p, pLit1 ); + // step to the next literals + pLit1 = bLit1Next; + bLit1Next = pLit1? pLit1->pHNext: NULL; + } + else + { // this literal is present in pCubeRem - remove it + // mark the affected var + if ( pLit2->pVar->pOrder == NULL ) + Fxu_MatrixRingVarsAdd( p, pLit2->pVar ); + // delete this literal + Fxu_MatrixDelLiteral( p, pLit2 ); + // step to the next literals + pLit2 = bLit2Next; + bLit2Next = pLit2? pLit2->pHNext: NULL; + } + } + else if ( pLit1 && !pLit2 ) + { // this literal is present in pCubeUse - leave it + // mark the affected var + if ( pLit1->pVar->pOrder == NULL ) + Fxu_MatrixRingVarsAdd( p, pLit1->pVar ); + // delete this literal + Fxu_MatrixDelLiteral( p, pLit1 ); + // step to the next literals + pLit1 = bLit1Next; + bLit1Next = pLit1? pLit1->pHNext: NULL; + } + else if ( !pLit1 && pLit2 ) + { // this literal is present in pCubeRem - remove it + // mark the affected var + if ( pLit2->pVar->pOrder == NULL ) + Fxu_MatrixRingVarsAdd( p, pLit2->pVar ); + // delete this literal + Fxu_MatrixDelLiteral( p, pLit2 ); + // step to the next literals + pLit2 = bLit2Next; + bLit2Next = pLit2? pLit2->pHNext: NULL; + } + else + break; + } +} + +/**Function************************************************************* + + Synopsis [Updates the matrix after selecting a single cube divisor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdateMatrixSingleClean( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, Fxu_Var * pVarNew ) +{ + Fxu_Lit * pLit1, * bLit1Next; + Fxu_Lit * pLit2, * bLit2Next; + + // initialize the starting literals + pLit1 = pVar1->lLits.pHead; + pLit2 = pVar2->lLits.pHead; + bLit1Next = pLit1? pLit1->pVNext: NULL; + bLit2Next = pLit2? pLit2->pVNext: NULL; + while ( 1 ) + { + if ( pLit1 && pLit2 ) + { + if ( pLit1->pCube->pVar->iVar == pLit2->pCube->pVar->iVar ) + { // these literals coincide + if ( pLit1->iCube == pLit2->iCube ) + { // these literals coincide + + // collect the affected cube + assert( pLit1->pCube->pOrder == NULL ); + Fxu_MatrixRingCubesAdd( p, pLit1->pCube ); + + // add the literal to this cube corresponding to the new column + Fxu_MatrixAddLiteral( p, pLit1->pCube, pVarNew ); + // clean the old cubes + Fxu_UpdateCleanOldDoubles( p, NULL, pLit1->pCube ); + + // remove the literals + Fxu_MatrixDelLiteral( p, pLit1 ); + Fxu_MatrixDelLiteral( p, pLit2 ); + + // go to the next literals + pLit1 = bLit1Next; + pLit2 = bLit2Next; + bLit1Next = pLit1? pLit1->pVNext: NULL; + bLit2Next = pLit2? pLit2->pVNext: NULL; + } + else if ( pLit1->iCube < pLit2->iCube ) + { + pLit1 = bLit1Next; + bLit1Next = pLit1? pLit1->pVNext: NULL; + } + else + { + pLit2 = bLit2Next; + bLit2Next = pLit2? pLit2->pVNext: NULL; + } + } + else if ( pLit1->pCube->pVar->iVar < pLit2->pCube->pVar->iVar ) + { + pLit1 = bLit1Next; + bLit1Next = pLit1? pLit1->pVNext: NULL; + } + else + { + pLit2 = bLit2Next; + bLit2Next = pLit2? pLit2->pVNext: NULL; + } + } + else if ( pLit1 && !pLit2 ) + { + pLit1 = bLit1Next; + bLit1Next = pLit1? pLit1->pVNext: NULL; + } + else if ( !pLit1 && pLit2 ) + { + pLit2 = bLit2Next; + bLit2Next = pLit2? pLit2->pVNext: NULL; + } + else + break; + } +} + +/**Function************************************************************* + + Synopsis [Sort the pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdatePairsSort( Fxu_Matrix * p, Fxu_Double * pDouble ) +{ + Fxu_Pair * pPair; + // order the pairs by the first cube to ensure that new literals are added + // to the matrix from top to bottom - collect pairs into the array + p->vPairs->nSize = 0; + Fxu_DoubleForEachPair( pDouble, pPair ) + Vec_PtrPush( p->vPairs, pPair ); + if ( p->vPairs->nSize < 2 ) + return; + // sort + qsort( (void *)p->vPairs->pArray, p->vPairs->nSize, sizeof(Fxu_Pair *), + (int (*)(const void *, const void *)) Fxu_UpdatePairCompare ); + assert( Fxu_UpdatePairCompare( (Fxu_Pair**)p->vPairs->pArray, (Fxu_Pair**)p->vPairs->pArray + p->vPairs->nSize - 1 ) < 0 ); +} + +/**Function************************************************************* + + Synopsis [Compares the vars by their number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fxu_UpdatePairCompare( Fxu_Pair ** ppP1, Fxu_Pair ** ppP2 ) +{ + Fxu_Cube * pC1 = (*ppP1)->pCube1; + Fxu_Cube * pC2 = (*ppP2)->pCube1; + int iP1CubeMin, iP2CubeMin; + if ( pC1->pVar->iVar < pC2->pVar->iVar ) + return -1; + if ( pC1->pVar->iVar > pC2->pVar->iVar ) + return 1; + iP1CubeMin = Fxu_PairMinCubeInt( *ppP1 ); + iP2CubeMin = Fxu_PairMinCubeInt( *ppP2 ); + if ( iP1CubeMin < iP2CubeMin ) + return -1; + if ( iP1CubeMin > iP2CubeMin ) + return 1; + assert( 0 ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Create new variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdateCreateNewVars( Fxu_Matrix * p, Fxu_Var ** ppVarC, Fxu_Var ** ppVarD, int nCubes ) +{ + Fxu_Var * pVarC, * pVarD; + + // add a new column for the complement + pVarC = Fxu_MatrixAddVar( p ); + pVarC->nCubes = 0; + // add a new column for the divisor + pVarD = Fxu_MatrixAddVar( p ); + pVarD->nCubes = nCubes; + + // mark this entry in the Value2Node array +// assert( p->pValue2Node[pVarC->iVar] > 0 ); +// p->pValue2Node[pVarD->iVar ] = p->pValue2Node[pVarC->iVar]; +// p->pValue2Node[pVarD->iVar+1] = p->pValue2Node[pVarC->iVar]+1; + + *ppVarC = pVarC; + *ppVarD = pVarD; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdateCleanOldDoubles( Fxu_Matrix * p, Fxu_Double * pDiv, Fxu_Cube * pCube ) +{ + Fxu_Double * pDivCur; + Fxu_Pair * pPair; + int i; + + // if the cube is a recently introduced one + // it does not have pairs allocated + // in this case, there is nothing to update + if ( pCube->pVar->ppPairs == NULL ) + return; + + // go through all the pairs of this cube + Fxu_CubeForEachPair( pCube, pPair, i ) + { + // get the divisor of this pair + pDivCur = pPair->pDiv; + // skip the current divisor + if ( pDivCur == pDiv ) + continue; + // remove this pair + Fxu_ListDoubleDelPair( pDivCur, pPair ); + // the divisor may have become useless by now + if ( pDivCur->lPairs.nItems == 0 ) + { + assert( pDivCur->Weight == pPair->nBase - 1 ); + Fxu_HeapDoubleDelete( p->pHeapDouble, pDivCur ); + Fxu_MatrixDelDivisor( p, pDivCur ); + } + else + { + // update the divisor's weight + pDivCur->Weight -= pPair->nLits1 + pPair->nLits2 - 1 + pPair->nBase; + Fxu_HeapDoubleUpdate( p->pHeapDouble, pDivCur ); + } + MEM_FREE_FXU( p, Fxu_Pair, 1, pPair ); + } + // finally erase all the pair info associated with this cube + Fxu_PairClearStorage( pCube ); +} + +/**Function************************************************************* + + Synopsis [Adds the new divisors that depend on the cube.] + + Description [Go through all the non-empty cubes of this cover + (except the given cube) and, for each of them, add the new divisor + with the given cube.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdateAddNewDoubles( Fxu_Matrix * p, Fxu_Cube * pCube ) +{ + Fxu_Cube * pTemp; + assert( pCube->pOrder ); + + // if the cube is a recently introduced one + // it does not have pairs allocated + // in this case, there is nothing to update + if ( pCube->pVar->ppPairs == NULL ) + return; + + for ( pTemp = pCube->pFirst; pTemp->pVar == pCube->pVar; pTemp = pTemp->pNext ) + { + // do not add pairs with the empty cubes + if ( pTemp->lLits.nItems == 0 ) + continue; + // to prevent adding duplicated pairs of the new cubes + // do not add the pair, if the current cube is marked + if ( pTemp->pOrder && pTemp >= pCube ) + continue; + Fxu_MatrixAddDivisor( p, pTemp, pCube ); + } +} + +/**Function************************************************************* + + Synopsis [Removes old single cube divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p ) +{ + Fxu_Single * pSingle, * pSingle2; + int WeightNew; + int Counter = 0; + + Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 ) + { + // if at least one of the variables is marked, recalculate + if ( pSingle->pVar1->pOrder || pSingle->pVar2->pOrder ) + { + Counter++; + // get the new weight + WeightNew = -2 + Fxu_SingleCountCoincidence( p, pSingle->pVar1, pSingle->pVar2 ); + if ( WeightNew >= 0 ) + { + pSingle->Weight = WeightNew; + Fxu_HeapSingleUpdate( p->pHeapSingle, pSingle ); + } + else + { + Fxu_HeapSingleDelete( p->pHeapSingle, pSingle ); + Fxu_ListMatrixDelSingle( p, pSingle ); + MEM_FREE_FXU( p, Fxu_Single, 1, pSingle ); + } + } + } +// printf( "Called procedure %d times.\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [Updates the single cube divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar ) +{ + Fxu_MatrixComputeSinglesOne( p, pVar ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/fxu/module.make b/abc70930/src/opt/fxu/module.make new file mode 100644 index 00000000..dd8acd40 --- /dev/null +++ b/abc70930/src/opt/fxu/module.make @@ -0,0 +1,12 @@ +SRC += src/opt/fxu/fxu.c \ + src/opt/fxu/fxuCreate.c \ + src/opt/fxu/fxuHeapD.c \ + src/opt/fxu/fxuHeapS.c \ + src/opt/fxu/fxuList.c \ + src/opt/fxu/fxuMatrix.c \ + src/opt/fxu/fxuPair.c \ + src/opt/fxu/fxuPrint.c \ + src/opt/fxu/fxuReduce.c \ + src/opt/fxu/fxuSelect.c \ + src/opt/fxu/fxuSingle.c \ + src/opt/fxu/fxuUpdate.c diff --git a/abc70930/src/opt/lpk/lpk.h b/abc70930/src/opt/lpk/lpk.h new file mode 100644 index 00000000..2a642db2 --- /dev/null +++ b/abc70930/src/opt/lpk/lpk.h @@ -0,0 +1,84 @@ +/**CFile**************************************************************** + + FileName [lpk.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpk.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __LPK_H__ +#define __LPK_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Lpk_Par_t_ Lpk_Par_t; +struct Lpk_Par_t_ +{ + // user-controlled parameters + int nLutsMax; // (N) the maximum number of LUTs in the structure + int nLutsOver; // (Q) the maximum number of LUTs not in the MFFC + int nVarsShared; // (S) the maximum number of shared variables (crossbars) + int nGrowthLevel; // (L) the maximum increase in the node level after resynthesis + int fSatur; // iterate till saturation + int fZeroCost; // accept zero-cost replacements + int fFirst; // use root node and first cut only + int fOldAlgo; // use old algorithm + int fVerbose; // the verbosiness flag + int fVeryVerbose; // additional verbose info printout + // internal parameters + int nLutSize; // (K) the LUT size (determined by the input network) + int nVarsMax; // (V) the largest number of variables: V = N * (K-1) + 1 +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== lpkCore.c ========================================================*/ +extern int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars ); + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/lpk/lpkAbcDec.c b/abc70930/src/opt/lpk/lpkAbcDec.c new file mode 100644 index 00000000..aa2d4bc0 --- /dev/null +++ b/abc70930/src/opt/lpk/lpkAbcDec.c @@ -0,0 +1,290 @@ +/**CFile**************************************************************** + + FileName [lpkAbcDec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [The new core procedure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpkAbcDec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "lpkInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Implements the function.] + + Description [Returns the node implementing this function.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Lpk_ImplementFun( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * p ) +{ + extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); + unsigned * pTruth; + Abc_Obj_t * pObjNew; + int i; + if ( p->fMark ) + pMan->nMuxes++; + else + pMan->nDsds++; + // create the new node + pObjNew = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < (int)p->nVars; i++ ) + Abc_ObjAddFanin( pObjNew, Abc_ObjRegular(Vec_PtrEntry(vLeaves, p->pFanins[i])) ); + Abc_ObjSetLevel( pObjNew, Abc_ObjLevelNew(pObjNew) ); + // assign the node's function + pTruth = Lpk_FunTruth(p, 0); + if ( p->nVars == 0 ) + { + pObjNew->pData = Hop_NotCond( Hop_ManConst1(pNtk->pManFunc), !(pTruth[0] & 1) ); + return pObjNew; + } + if ( p->nVars == 1 ) + { + pObjNew->pData = Hop_NotCond( Hop_ManPi(pNtk->pManFunc, 0), (pTruth[0] & 1) ); + return pObjNew; + } + // create the logic function + pObjNew->pData = Kit_TruthToHop( pNtk->pManFunc, pTruth, p->nVars, NULL ); + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Implements the function.] + + Description [Returns the node implementing this function.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Lpk_Implement_rec( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * pFun ) +{ + Abc_Obj_t * pFanin, * pRes; + int i; + // prepare the leaves of the function + for ( i = 0; i < (int)pFun->nVars; i++ ) + { + pFanin = Vec_PtrEntry( vLeaves, pFun->pFanins[i] ); + if ( !Abc_ObjIsComplement(pFanin) ) + Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)pFanin ); + pFanin = Vec_PtrEntry( vLeaves, pFun->pFanins[i] ); + assert( Abc_ObjIsComplement(pFanin) ); + } + // construct the function + pRes = Lpk_ImplementFun( pMan, pNtk, vLeaves, pFun ); + // replace the function + Vec_PtrWriteEntry( vLeaves, pFun->Id, Abc_ObjNot(pRes) ); + Lpk_FunFree( pFun ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Implements the function.] + + Description [Returns the node implementing this function.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Lpk_Implement( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, int nLeavesOld ) +{ + Abc_Obj_t * pFanin, * pRes; + int i; + assert( nLeavesOld < Vec_PtrSize(vLeaves) ); + // mark implemented nodes + Vec_PtrForEachEntryStop( vLeaves, pFanin, i, nLeavesOld ) + Vec_PtrWriteEntry( vLeaves, i, Abc_ObjNot(pFanin) ); + // recursively construct starting from the first entry + pRes = Lpk_Implement_rec( pMan, pNtk, vLeaves, Vec_PtrEntry( vLeaves, nLeavesOld ) ); + Vec_PtrShrink( vLeaves, nLeavesOld ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Decomposes the function using recursive MUX decomposition.] + + Description [Returns the ID of the top-most decomposition node + implementing this function, or 0 if there is no decomposition satisfying + the constraints on area and delay.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_Decompose_rec( Lpk_Man_t * pMan, Lpk_Fun_t * p ) +{ + static Lpk_Res_t Res0, * pRes0 = &Res0; + Lpk_Res_t * pResMux, * pResDsd; + Lpk_Fun_t * p2; + int clk; + + // is only called for non-trivial blocks + assert( p->nLutK >= 3 && p->nLutK <= 6 ); + assert( p->nVars > p->nLutK ); + // skip if area bound is exceeded + if ( Lpk_LutNumLuts(p->nVars, p->nLutK) > (int)p->nAreaLim ) + return 0; + // skip if delay bound is exceeded + if ( Lpk_SuppDelay(p->uSupp, p->pDelays) > (int)p->nDelayLim ) + return 0; + + // compute supports if needed + if ( !p->fSupports ) + Lpk_FunComputeCofSupps( p ); + + // check DSD decomposition +clk = clock(); + pResDsd = Lpk_DsdAnalize( pMan, p, pMan->pPars->nVarsShared ); +pMan->timeEvalDsdAn += clock() - clk; + if ( pResDsd && (pResDsd->nBSVars == (int)p->nLutK || pResDsd->nBSVars == (int)p->nLutK - 1) && + pResDsd->AreaEst <= (int)p->nAreaLim && pResDsd->DelayEst <= (int)p->nDelayLim ) + { +clk = clock(); + p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars ); +pMan->timeEvalDsdSp += clock() - clk; + assert( p2->nVars <= (int)p->nLutK ); + if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) + return 0; + return 1; + } + + // check MUX decomposition +clk = clock(); + pResMux = Lpk_MuxAnalize( pMan, p ); +pMan->timeEvalMuxAn += clock() - clk; +// pResMux = NULL; + assert( !pResMux || (pResMux->DelayEst <= (int)p->nDelayLim && pResMux->AreaEst <= (int)p->nAreaLim) ); + // accept MUX decomposition if it is "good" + if ( pResMux && pResMux->nSuppSizeS <= (int)p->nLutK && pResMux->nSuppSizeL <= (int)p->nLutK ) + pResDsd = NULL; + else if ( pResMux && pResDsd ) + { + // compare two decompositions + if ( pResMux->AreaEst < pResDsd->AreaEst || + (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL < pResDsd->nSuppSizeL) || + (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL == pResDsd->nSuppSizeL && pResMux->DelayEst < pResDsd->DelayEst) ) + pResDsd = NULL; + else + pResMux = NULL; + } + assert( pResMux == NULL || pResDsd == NULL ); + if ( pResMux ) + { +clk = clock(); + p2 = Lpk_MuxSplit( pMan, p, pResMux->Variable, pResMux->Polarity ); +pMan->timeEvalMuxSp += clock() - clk; + if ( p2->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p2 ) ) + return 0; + if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) + return 0; + return 1; + } + if ( pResDsd ) + { +clk = clock(); + p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars ); +pMan->timeEvalDsdSp += clock() - clk; + assert( p2->nVars <= (int)p->nLutK ); + if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) + return 0; + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Removes decomposed nodes from the array of fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_DecomposeClean( Vec_Ptr_t * vLeaves, int nLeavesOld ) +{ + Lpk_Fun_t * pFunc; + int i; + Vec_PtrForEachEntryStart( vLeaves, pFunc, i, nLeavesOld ) + Lpk_FunFree( pFunc ); + Vec_PtrShrink( vLeaves, nLeavesOld ); +} + +/**Function************************************************************* + + Synopsis [Decomposes the function using recursive MUX decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Lpk_Decompose( Lpk_Man_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, unsigned * puSupps, int nLutK, int AreaLim, int DelayLim ) +{ + Lpk_Fun_t * pFun; + Abc_Obj_t * pObjNew = NULL; + int nLeaves = Vec_PtrSize( vLeaves ); + pFun = Lpk_FunCreate( pNtk, vLeaves, pTruth, nLutK, AreaLim, DelayLim ); + if ( puSupps[0] || puSupps[1] ) + { +/* + int i; + Lpk_FunComputeCofSupps( pFun ); + for ( i = 0; i < nLeaves; i++ ) + { + assert( pFun->puSupps[2*i+0] == puSupps[2*i+0] ); + assert( pFun->puSupps[2*i+1] == puSupps[2*i+1] ); + } +*/ + memcpy( pFun->puSupps, puSupps, sizeof(unsigned) * 2 * nLeaves ); + pFun->fSupports = 1; + } + Lpk_FunSuppMinimize( pFun ); + if ( pFun->nVars <= pFun->nLutK ) + pObjNew = Lpk_ImplementFun( p, pNtk, vLeaves, pFun ); + else if ( Lpk_Decompose_rec(p, pFun) ) + pObjNew = Lpk_Implement( p, pNtk, vLeaves, nLeaves ); + Lpk_DecomposeClean( vLeaves, nLeaves ); + return pObjNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/lpkAbcDsd.c b/abc70930/src/opt/lpk/lpkAbcDsd.c new file mode 100644 index 00000000..f4095914 --- /dev/null +++ b/abc70930/src/opt/lpk/lpkAbcDsd.c @@ -0,0 +1,603 @@ +/**CFile**************************************************************** + + FileName [lpkAbcDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [LUT-decomposition based on recursive DSD.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpkAbcDsd.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "lpkInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Cofactors TTs w.r.t. all vars and finds the best var.] + + Description [The best variable is the variable with the minimum + sum total of the support sizes of all truth tables. This procedure + computes and returns cofactors w.r.t. the best variable.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_FunComputeMinSuppSizeVar( Lpk_Fun_t * p, unsigned ** ppTruths, int nTruths, unsigned ** ppCofs, unsigned uNonDecSupp ) +{ + int i, Var, VarBest, nSuppSize0, nSuppSize1, nSuppTotalMin, nSuppTotalCur, nSuppMaxMin, nSuppMaxCur; + assert( nTruths > 0 ); + VarBest = -1; + Lpk_SuppForEachVar( p->uSupp, Var ) + { + if ( (uNonDecSupp & (1 << Var)) == 0 ) + continue; + nSuppMaxCur = 0; + nSuppTotalCur = 0; + for ( i = 0; i < nTruths; i++ ) + { + if ( nTruths == 1 ) + { + nSuppSize0 = Kit_WordCountOnes( p->puSupps[2*Var+0] ); + nSuppSize1 = Kit_WordCountOnes( p->puSupps[2*Var+1] ); + } + else + { + Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, Var ); + Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, Var ); + nSuppSize0 = Kit_TruthSupportSize( ppCofs[2*i+0], p->nVars ); + nSuppSize1 = Kit_TruthSupportSize( ppCofs[2*i+1], p->nVars ); + } + nSuppMaxCur = ABC_MAX( nSuppMaxCur, nSuppSize0 ); + nSuppMaxCur = ABC_MAX( nSuppMaxCur, nSuppSize1 ); + nSuppTotalCur += nSuppSize0 + nSuppSize1; + } + if ( VarBest == -1 || nSuppMaxMin > nSuppMaxCur || + (nSuppMaxMin == nSuppMaxCur && nSuppTotalMin > nSuppTotalCur) ) + { + VarBest = Var; + nSuppMaxMin = nSuppMaxCur; + nSuppTotalMin = nSuppTotalCur; + } + } + // recompute cofactors for the best var + for ( i = 0; i < nTruths; i++ ) + { + Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, VarBest ); + Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, VarBest ); + } + return VarBest; +} + +/**Function************************************************************* + + Synopsis [Recursively computes decomposable subsets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Lpk_ComputeBoundSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets, int nSizeMax ) +{ + unsigned i, iLitFanin, uSupport, uSuppCur; + Kit_DsdObj_t * pObj; + // consider the case of simple gate + pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); + if ( pObj == NULL ) + return (1 << Kit_DsdLit2Var(iLit)); + if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) + { + unsigned uSupps[16], Limit, s; + uSupport = 0; + Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) + { + uSupps[i] = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax ); + uSupport |= uSupps[i]; + } + // create all subsets, except empty and full + Limit = (1 << pObj->nFans) - 1; + for ( s = 1; s < Limit; s++ ) + { + uSuppCur = 0; + for ( i = 0; i < pObj->nFans; i++ ) + if ( s & (1 << i) ) + uSuppCur |= uSupps[i]; + if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax ) + Vec_IntPush( vSets, uSuppCur ); + } + return uSupport; + } + assert( pObj->Type == KIT_DSD_PRIME ); + // get the cumulative support of all fanins + uSupport = 0; + Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) + { + uSuppCur = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax ); + uSupport |= uSuppCur; + if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax ) + Vec_IntPush( vSets, uSuppCur ); + } + return uSupport; +} + +/**Function************************************************************* + + Synopsis [Computes the set of subsets of decomposable variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Lpk_ComputeBoundSets( Kit_DsdNtk_t * p, int nSizeMax ) +{ + Vec_Int_t * vSets; + unsigned uSupport, Entry; + int Number, i; + assert( p->nVars <= 16 ); + vSets = Vec_IntAlloc( 100 ); + Vec_IntPush( vSets, 0 ); + if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) + return vSets; + if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) + { + uSupport = ( 1 << Kit_DsdLit2Var(Kit_DsdNtkRoot(p)->pFans[0]) ); + if ( Kit_WordCountOnes(uSupport) <= nSizeMax ) + Vec_IntPush( vSets, uSupport ); + return vSets; + } + uSupport = Lpk_ComputeBoundSets_rec( p, p->Root, vSets, nSizeMax ); + assert( (uSupport & 0xFFFF0000) == 0 ); + // add the total support of the network + if ( Kit_WordCountOnes(uSupport) <= nSizeMax ) + Vec_IntPush( vSets, uSupport ); + // set the remaining variables + Vec_IntForEachEntry( vSets, Number, i ) + { + Entry = Number; + Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) ); + } + return vSets; +} + +/**Function************************************************************* + + Synopsis [Prints the sets of subsets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Lpk_PrintSetOne( int uSupport ) +{ + unsigned k; + for ( k = 0; k < 16; k++ ) + if ( uSupport & (1<> 16)) ) + continue; + if ( Kit_WordCountOnes(Entry & 0xffff) <= nSizeMax ) + Vec_IntPush( vSets, Entry ); + } + return vSets; +} + +/**Function************************************************************* + + Synopsis [Performs DSD-based decomposition of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_FunCompareBoundSets( Lpk_Fun_t * p, Vec_Int_t * vBSets, int nCofDepth, unsigned uNonDecSupp, unsigned uLateArrSupp, Lpk_Res_t * pRes ) +{ + int fVerbose = 0; + unsigned uBoundSet; + int i, nVarsBS, nVarsRem, Delay, Area; + + // compare the resulting boundsets + memset( pRes, 0, sizeof(Lpk_Res_t) ); + Vec_IntForEachEntry( vBSets, uBoundSet, i ) + { + if ( (uBoundSet & 0xFFFF) == 0 ) // skip empty boundset + continue; + if ( (uBoundSet & uNonDecSupp) == 0 ) // skip those boundsets that are not in the domain of interest + continue; + if ( (uBoundSet & uLateArrSupp) ) // skip those boundsets that are late arriving + continue; +if ( fVerbose ) +Lpk_PrintSetOne( uBoundSet ); + assert( (uBoundSet & (uBoundSet >> 16)) == 0 ); + nVarsBS = Kit_WordCountOnes( uBoundSet & 0xFFFF ); + if ( nVarsBS == 1 ) + continue; + assert( nVarsBS <= (int)p->nLutK - nCofDepth ); + nVarsRem = p->nVars - nVarsBS + 1; + Area = 1 + Lpk_LutNumLuts( nVarsRem, p->nLutK ); + Delay = 1 + Lpk_SuppDelay( uBoundSet & 0xFFFF, p->pDelays ); +if ( fVerbose ) +printf( "area = %d limit = %d delay = %d limit = %d\n", Area, (int)p->nAreaLim, Delay, (int)p->nDelayLim ); + if ( Area > (int)p->nAreaLim || Delay > (int)p->nDelayLim ) + continue; + if ( pRes->BSVars == 0 || pRes->nSuppSizeL > nVarsRem || (pRes->nSuppSizeL == nVarsRem && pRes->DelayEst > Delay) ) + { + pRes->nBSVars = nVarsBS; + pRes->BSVars = (uBoundSet & 0xFFFF); + pRes->nSuppSizeS = nVarsBS + nCofDepth; + pRes->nSuppSizeL = nVarsRem; + pRes->DelayEst = Delay; + pRes->AreaEst = Area; + } + } +if ( fVerbose ) +{ +if ( pRes->BSVars ) +{ +printf( "Found bound set " ); +Lpk_PrintSetOne( pRes->BSVars ); +printf( "\n" ); +} +else +printf( "Did not find boundsets.\n" ); +printf( "\n" ); +} + if ( pRes->BSVars ) + { + assert( pRes->DelayEst <= (int)p->nDelayLim ); + assert( pRes->AreaEst <= (int)p->nAreaLim ); + } +} + + +/**Function************************************************************* + + Synopsis [Finds late arriving inputs, which cannot be in the bound set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Lpk_DsdLateArriving( Lpk_Fun_t * p ) +{ + unsigned i, uLateArrSupp = 0; + Lpk_SuppForEachVar( p->uSupp, i ) + if ( p->pDelays[i] > (int)p->nDelayLim - 2 ) + uLateArrSupp |= (1 << i); + return uLateArrSupp; +} + +/**Function************************************************************* + + Synopsis [Performs DSD-based decomposition of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_DsdAnalizeOne( Lpk_Fun_t * p, unsigned * ppTruths[5][16], Kit_DsdNtk_t * pNtks[], char pCofVars[], int nCofDepth, Lpk_Res_t * pRes ) +{ + int fVerbose = 0; + Vec_Int_t * pvBSets[4][8]; + unsigned uNonDecSupp, uLateArrSupp; + int i, k, nNonDecSize, nNonDecSizeMax; + assert( nCofDepth >= 1 && nCofDepth <= 3 ); + assert( nCofDepth < (int)p->nLutK - 1 ); + assert( p->fSupports ); + + // find the support of the largest non-DSD block + nNonDecSizeMax = 0; + uNonDecSupp = p->uSupp; + for ( i = 0; i < (1<<(nCofDepth-1)); i++ ) + { + nNonDecSize = Kit_DsdNonDsdSizeMax( pNtks[i] ); + if ( nNonDecSizeMax < nNonDecSize ) + { + nNonDecSizeMax = nNonDecSize; + uNonDecSupp = Kit_DsdNonDsdSupports( pNtks[i] ); + } + else if ( nNonDecSizeMax == nNonDecSize ) + uNonDecSupp |= Kit_DsdNonDsdSupports( pNtks[i] ); + } + + // remove those variables that cannot be used because of delay constraints + // if variables arrival time is more than p->DelayLim - 2, it cannot be used + uLateArrSupp = Lpk_DsdLateArriving( p ); + if ( (uNonDecSupp & ~uLateArrSupp) == 0 ) + { + memset( pRes, 0, sizeof(Lpk_Res_t) ); + return 0; + } + + // find the next cofactoring variable + pCofVars[nCofDepth-1] = Lpk_FunComputeMinSuppSizeVar( p, ppTruths[nCofDepth-1], 1<<(nCofDepth-1), ppTruths[nCofDepth], uNonDecSupp & ~uLateArrSupp ); + + // derive decomposed networks + for ( i = 0; i < (1<nVars ); +if ( fVerbose ) +Kit_DsdPrint( stdout, pNtks[i] ); + pvBSets[nCofDepth][i] = Lpk_ComputeBoundSets( pNtks[i], p->nLutK - nCofDepth ); // try restricting to those in uNonDecSupp!!! + } + + // derive the set of feasible boundsets + for ( i = nCofDepth - 1; i >= 0; i-- ) + for ( k = 0; k < (1<nLutK - nCofDepth ); + // compare bound-sets + Lpk_FunCompareBoundSets( p, pvBSets[0][0], nCofDepth, uNonDecSupp, uLateArrSupp, pRes ); + // free the bound sets + for ( i = nCofDepth; i >= 0; i-- ) + for ( k = 0; k < (1<BSVars ) + { + pRes->nCofVars = nCofDepth; + for ( i = 0; i < nCofDepth; i++ ) + pRes->pCofVars[i] = pCofVars[i]; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs DSD-based decomposition of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Lpk_Res_t * Lpk_DsdAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p, int nShared ) +{ + static Lpk_Res_t Res0, * pRes0 = &Res0; + static Lpk_Res_t Res1, * pRes1 = &Res1; + static Lpk_Res_t Res2, * pRes2 = &Res2; + static Lpk_Res_t Res3, * pRes3 = &Res3; + int fUseBackLooking = 1; + Lpk_Res_t * pRes = NULL; + Vec_Int_t * vBSets; + Kit_DsdNtk_t * pNtks[8] = {NULL}; + char pCofVars[5]; + int i; + + assert( p->nLutK >= 3 ); + assert( nShared >= 0 && nShared <= 3 ); + assert( p->uSupp == Kit_BitMask(p->nVars) ); + + // try decomposition without cofactoring + pNtks[0] = Kit_DsdDecomposeExpand( Lpk_FunTruth( p, 0 ), p->nVars ); + if ( pMan->pPars->fVerbose ) + pMan->nBlocks[ Kit_DsdNonDsdSizeMax(pNtks[0]) ]++; + vBSets = Lpk_ComputeBoundSets( pNtks[0], p->nLutK ); + Lpk_FunCompareBoundSets( p, vBSets, 0, 0xFFFF, Lpk_DsdLateArriving(p), pRes0 ); + Vec_IntFree( vBSets ); + + // check the result + if ( pRes0->nBSVars == (int)p->nLutK ) + { pRes = pRes0; goto finish; } + if ( pRes0->nBSVars == (int)p->nLutK - 1 ) + { pRes = pRes0; goto finish; } + if ( nShared == 0 ) + goto finish; + + // prepare storage + Kit_TruthCopy( pMan->ppTruths[0][0], Lpk_FunTruth( p, 0 ), p->nVars ); + + // cofactor 1 time + if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 1, pRes1 ) ) + goto finish; + assert( pRes1->nBSVars <= (int)p->nLutK - 1 ); + if ( pRes1->nBSVars == (int)p->nLutK - 1 ) + { pRes = pRes1; goto finish; } + if ( pRes0->nBSVars == (int)p->nLutK - 2 ) + { pRes = pRes0; goto finish; } + if ( pRes1->nBSVars == (int)p->nLutK - 2 ) + { pRes = pRes1; goto finish; } + if ( nShared == 1 ) + goto finish; + + // cofactor 2 times + if ( p->nLutK >= 4 ) + { + if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 2, pRes2 ) ) + goto finish; + assert( pRes2->nBSVars <= (int)p->nLutK - 2 ); + if ( pRes2->nBSVars == (int)p->nLutK - 2 ) + { pRes = pRes2; goto finish; } + if ( fUseBackLooking ) + { + if ( pRes0->nBSVars == (int)p->nLutK - 3 ) + { pRes = pRes0; goto finish; } + if ( pRes1->nBSVars == (int)p->nLutK - 3 ) + { pRes = pRes1; goto finish; } + } + if ( pRes2->nBSVars == (int)p->nLutK - 3 ) + { pRes = pRes2; goto finish; } + if ( nShared == 2 ) + goto finish; + assert( nShared == 3 ); + } + + // cofactor 3 times + if ( p->nLutK >= 5 ) + { + if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 3, pRes3 ) ) + goto finish; + assert( pRes3->nBSVars <= (int)p->nLutK - 3 ); + if ( pRes3->nBSVars == (int)p->nLutK - 3 ) + { pRes = pRes3; goto finish; } + if ( fUseBackLooking ) + { + if ( pRes0->nBSVars == (int)p->nLutK - 4 ) + { pRes = pRes0; goto finish; } + if ( pRes1->nBSVars == (int)p->nLutK - 4 ) + { pRes = pRes1; goto finish; } + if ( pRes2->nBSVars == (int)p->nLutK - 4 ) + { pRes = pRes2; goto finish; } + } + if ( pRes3->nBSVars == (int)p->nLutK - 4 ) + { pRes = pRes3; goto finish; } + } + +finish: + // free the networks + for ( i = 0; i < (1<ppTruths[0][0], Lpk_FunTruth(p, 0), p->nVars ); + // get the vacuous variable + iVacVar = Kit_WordFindFirstBit( uBoundSet ); + // compute the cofactors + for ( i = 0; i < nCofVars; i++ ) + for ( k = 0; k < (1<ppTruths[i+1][2*k+0], pMan->ppTruths[i][k], p->nVars, pCofVars[i] ); + Kit_TruthCofactor1New( pMan->ppTruths[i+1][2*k+1], pMan->ppTruths[i][k], p->nVars, pCofVars[i] ); + } + // decompose each cofactor w.r.t. the bound set + nCofs = (1<ppTruths[nCofVars][k], p->nVars ); + Kit_DsdTruthPartialTwo( pMan->pDsdMan, pNtkDec, uBoundSet, iVacVar, pMan->ppTruths[nCofVars+1][k], pMan->ppTruths[nCofVars+1][nCofs+k] ); + Kit_DsdNtkFree( pNtkDec ); + } + // compute the composition/decomposition functions (they will be in pMan->ppTruths[1][0]/pMan->ppTruths[1][1]) + for ( i = nCofVars; i >= 1; i-- ) + for ( k = 0; k < (1<ppTruths[i][k], pMan->ppTruths[i+1][2*k+0], pMan->ppTruths[i+1][2*k+1], p->nVars, pCofVars[i-1] ); + + // derive the new component (decomposition function) + pNew = Lpk_FunDup( p, pMan->ppTruths[1][1] ); + // update the old component (composition function) + Kit_TruthCopy( Lpk_FunTruth(p, 0), pMan->ppTruths[1][0], p->nVars ); + p->uSupp = Kit_TruthSupport( Lpk_FunTruth(p, 0), p->nVars ); + p->pFanins[iVacVar] = pNew->Id; + p->pDelays[iVacVar] = Lpk_SuppDelay( pNew->uSupp, pNew->pDelays ); + // support minimize both + p->fSupports = 0; + Lpk_FunSuppMinimize( p ); + Lpk_FunSuppMinimize( pNew ); + // update delay and area requirements + pNew->nDelayLim = p->pDelays[iVacVar]; + pNew->nAreaLim = 1; + p->nAreaLim = p->nAreaLim - 1; + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/lpkAbcMux.c b/abc70930/src/opt/lpk/lpkAbcMux.c new file mode 100644 index 00000000..d6f579ee --- /dev/null +++ b/abc70930/src/opt/lpk/lpkAbcMux.c @@ -0,0 +1,235 @@ +/**CFile**************************************************************** + + FileName [lpkAbcMux.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [LUT-decomposition based on recursive MUX decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpkAbcMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "lpkInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the possibility of MUX decomposition.] + + Description [Returns the best variable to use for MUX decomposition.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p ) +{ + static Lpk_Res_t Res, * pRes = &Res; + int nSuppSize0, nSuppSize1, nSuppSizeS, nSuppSizeL; + int Var, Area, Polarity, Delay, Delay0, Delay1, DelayA, DelayB; + memset( pRes, 0, sizeof(Lpk_Res_t) ); + assert( p->uSupp == Kit_BitMask(p->nVars) ); + assert( p->fSupports ); + // derive the delay and area after MUX-decomp with each var - and find the best var + pRes->Variable = -1; + Lpk_SuppForEachVar( p->uSupp, Var ) + { + nSuppSize0 = Kit_WordCountOnes(p->puSupps[2*Var+0]); + nSuppSize1 = Kit_WordCountOnes(p->puSupps[2*Var+1]); + assert( nSuppSize0 < (int)p->nVars ); + assert( nSuppSize1 < (int)p->nVars ); + if ( nSuppSize0 < 1 || nSuppSize1 < 1 ) + continue; +//printf( "%d %d ", nSuppSize0, nSuppSize1 ); + if ( nSuppSize0 <= (int)p->nLutK - 2 && nSuppSize1 <= (int)p->nLutK - 2 ) + { + // include cof var into 0-block + DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); + DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); + Delay0 = ABC_MAX( DelayA, DelayB + 1 ); + // include cof var into 1-block + DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); + DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); + Delay1 = ABC_MAX( DelayA, DelayB + 1 ); + // get the best delay + Delay = ABC_MIN( Delay0, Delay1 ); + Area = 2; + Polarity = (int)(Delay == Delay1); + } + else if ( nSuppSize0 <= (int)p->nLutK - 2 ) + { + DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); + DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); + Delay = ABC_MAX( DelayA, DelayB + 1 ); + Area = 1 + Lpk_LutNumLuts( nSuppSize1, p->nLutK ); + Polarity = 0; + } + else if ( nSuppSize1 <= (int)p->nLutK - 2 ) + { + DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); + DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); + Delay = ABC_MAX( DelayA, DelayB + 1 ); + Area = 1 + Lpk_LutNumLuts( nSuppSize0, p->nLutK ); + Polarity = 1; + } + else if ( nSuppSize0 <= (int)p->nLutK ) + { + DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); + DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); + Delay = ABC_MAX( DelayA, DelayB + 1 ); + Area = 1 + Lpk_LutNumLuts( nSuppSize1+2, p->nLutK ); + Polarity = 1; + } + else if ( nSuppSize1 <= (int)p->nLutK ) + { + DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); + DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); + Delay = ABC_MAX( DelayA, DelayB + 1 ); + Area = 1 + Lpk_LutNumLuts( nSuppSize0+2, p->nLutK ); + Polarity = 0; + } + else + { + // include cof var into 0-block + DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); + DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); + Delay0 = ABC_MAX( DelayA, DelayB + 1 ); + // include cof var into 1-block + DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); + DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); + Delay1 = ABC_MAX( DelayA, DelayB + 1 ); + // get the best delay + Delay = ABC_MIN( Delay0, Delay1 ); + if ( Delay == Delay0 ) + Area = Lpk_LutNumLuts( nSuppSize0+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize1, p->nLutK ); + else + Area = Lpk_LutNumLuts( nSuppSize1+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize0, p->nLutK ); + Polarity = (int)(Delay == Delay1); + } + // find the best variable + if ( Delay > (int)p->nDelayLim ) + continue; + if ( Area > (int)p->nAreaLim ) + continue; + nSuppSizeS = ABC_MIN( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity ); + nSuppSizeL = ABC_MAX( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity ); + if ( nSuppSizeL > (int)p->nVars ) + continue; + if ( pRes->Variable == -1 || pRes->AreaEst > Area || + (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL > nSuppSizeS + nSuppSizeL) || + (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL == nSuppSizeS + nSuppSizeL && pRes->DelayEst > Delay) ) + { + pRes->Variable = Var; + pRes->Polarity = Polarity; + pRes->AreaEst = Area; + pRes->DelayEst = Delay; + pRes->nSuppSizeS = nSuppSizeS; + pRes->nSuppSizeL = nSuppSizeL; + } + } + return pRes->Variable == -1 ? NULL : pRes; +} + +/**Function************************************************************* + + Synopsis [Transforms the function decomposed by the MUX decomposition.] + + Description [Returns the best variable to use for MUX decomposition.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Lpk_Fun_t * Lpk_MuxSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, int Var, int Pol ) +{ + Lpk_Fun_t * pNew; + unsigned * pTruth = Lpk_FunTruth( p, 0 ); + unsigned * pTruth0 = Lpk_FunTruth( p, 1 ); + unsigned * pTruth1 = Lpk_FunTruth( p, 2 ); +// unsigned uSupp; + int iVarVac; + assert( Var >= 0 && Var < (int)p->nVars ); + assert( p->nAreaLim >= 2 ); + assert( p->uSupp == Kit_BitMask(p->nVars) ); + Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var ); + Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var ); +/* +uSupp = Kit_TruthSupport( pTruth, p->nVars ); +Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" ); +uSupp = Kit_TruthSupport( pTruth0, p->nVars ); +Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" ); +uSupp = Kit_TruthSupport( pTruth1, p->nVars ); +Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n\n" ); +*/ + // derive the new component + pNew = Lpk_FunDup( p, Pol ? pTruth0 : pTruth1 ); + // update the support of the old component + p->uSupp = Kit_TruthSupport( Pol ? pTruth1 : pTruth0, p->nVars ); + p->uSupp |= (1 << Var); + // update the truth table of the old component + iVarVac = Kit_WordFindFirstBit( ~p->uSupp ); + assert( iVarVac < (int)p->nVars ); + p->uSupp |= (1 << iVarVac); + Kit_TruthIthVar( pTruth, p->nVars, iVarVac ); + if ( Pol ) + Kit_TruthMuxVar( pTruth, pTruth, pTruth1, p->nVars, Var ); + else + Kit_TruthMuxVar( pTruth, pTruth0, pTruth, p->nVars, Var ); + assert( p->uSupp == Kit_TruthSupport(pTruth, p->nVars) ); + // set the decomposed variable + p->pFanins[iVarVac] = pNew->Id; + p->pDelays[iVarVac] = p->nDelayLim - 1; + // support minimize both + p->fSupports = 0; + Lpk_FunSuppMinimize( p ); + Lpk_FunSuppMinimize( pNew ); + // update delay and area requirements + pNew->nDelayLim = p->nDelayLim - 1; + if ( pNew->nVars <= pNew->nLutK ) + { + pNew->nAreaLim = 1; + p->nAreaLim = p->nAreaLim - 1; + } + else if ( p->nVars <= p->nLutK ) + { + pNew->nAreaLim = p->nAreaLim - 1; + p->nAreaLim = 1; + } + else if ( p->nVars < pNew->nVars ) + { + pNew->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2; + p->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2; + } + else // if ( pNew->nVars < p->nVars ) + { + pNew->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2; + p->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2; + } + pNew->fMark = 1; + return pNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/lpkAbcUtil.c b/abc70930/src/opt/lpk/lpkAbcUtil.c new file mode 100644 index 00000000..3f917ce2 --- /dev/null +++ b/abc70930/src/opt/lpk/lpkAbcUtil.c @@ -0,0 +1,244 @@ +/**CFile**************************************************************** + + FileName [lpkAbcUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [Procedures working on decomposed functions.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpkAbcUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "lpkInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Lpk_Fun_t * Lpk_FunAlloc( int nVars ) +{ + Lpk_Fun_t * p; + p = (Lpk_Fun_t *)malloc( sizeof(Lpk_Fun_t) + sizeof(unsigned) * Kit_TruthWordNum(nVars) * 3 ); + memset( p, 0, sizeof(Lpk_Fun_t) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deletes the function] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_FunFree( Lpk_Fun_t * p ) +{ + free( p ); +} + +/**Function************************************************************* + + Synopsis [Creates the starting function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Lpk_Fun_t * Lpk_FunCreate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, int nLutK, int AreaLim, int DelayLim ) +{ + Lpk_Fun_t * p; + Abc_Obj_t * pNode; + int i; + p = Lpk_FunAlloc( Vec_PtrSize(vLeaves) ); + p->Id = Vec_PtrSize(vLeaves); + p->vNodes = vLeaves; + p->nVars = Vec_PtrSize(vLeaves); + p->nLutK = nLutK; + p->nAreaLim = AreaLim; + p->nDelayLim = DelayLim; + p->uSupp = Kit_TruthSupport( pTruth, p->nVars ); + Kit_TruthCopy( Lpk_FunTruth(p,0), pTruth, p->nVars ); + Vec_PtrForEachEntry( vLeaves, pNode, i ) + { + p->pFanins[i] = i; + p->pDelays[i] = pNode->Level; + } + Vec_PtrPush( p->vNodes, p ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the new function with the given truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Lpk_Fun_t * Lpk_FunDup( Lpk_Fun_t * p, unsigned * pTruth ) +{ + Lpk_Fun_t * pNew; + pNew = Lpk_FunAlloc( p->nVars ); + pNew->Id = Vec_PtrSize(p->vNodes); + pNew->vNodes = p->vNodes; + pNew->nVars = p->nVars; + pNew->nLutK = p->nLutK; + pNew->nAreaLim = p->nAreaLim; + pNew->nDelayLim = p->nDelayLim; + pNew->uSupp = Kit_TruthSupport( pTruth, p->nVars ); + Kit_TruthCopy( Lpk_FunTruth(pNew,0), pTruth, p->nVars ); + memcpy( pNew->pFanins, p->pFanins, 16 ); + memcpy( pNew->pDelays, p->pDelays, 16 ); + Vec_PtrPush( p->vNodes, pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Minimizes support of the function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_FunSuppMinimize( Lpk_Fun_t * p ) +{ + int i, k, nVarsNew; + // compress the truth table + if ( p->uSupp == Kit_BitMask(p->nVars) ) + return 0; + // invalidate support info + p->fSupports = 0; +//Extra_PrintBinary( stdout, &p->uSupp, p->nVars ); printf( "\n" ); + // minimize support + nVarsNew = Kit_WordCountOnes(p->uSupp); + Kit_TruthShrink( Lpk_FunTruth(p, 1), Lpk_FunTruth(p, 0), nVarsNew, p->nVars, p->uSupp, 1 ); + k = 0; + Lpk_SuppForEachVar( p->uSupp, i ) + { + p->pFanins[k] = p->pFanins[i]; + p->pDelays[k] = p->pDelays[i]; +/* + if ( p->fSupports ) + { + p->puSupps[2*k+0] = p->puSupps[2*i+0]; + p->puSupps[2*k+1] = p->puSupps[2*i+1]; + } +*/ + k++; + } + assert( k == nVarsNew ); + p->nVars = k; + p->uSupp = Kit_BitMask(p->nVars); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes cofactors w.r.t. each variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_FunComputeCofSupps( Lpk_Fun_t * p ) +{ + unsigned * pTruth = Lpk_FunTruth( p, 0 ); + unsigned * pTruth0 = Lpk_FunTruth( p, 1 ); + unsigned * pTruth1 = Lpk_FunTruth( p, 2 ); + int Var; + assert( p->fSupports == 0 ); +// Lpk_SuppForEachVar( p->uSupp, Var ) + for ( Var = 0; Var < (int)p->nVars; Var++ ) + { + Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var ); + Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var ); + p->puSupps[2*Var+0] = Kit_TruthSupport( pTruth0, p->nVars ); + p->puSupps[2*Var+1] = Kit_TruthSupport( pTruth1, p->nVars ); + } + p->fSupports = 1; +} + +/**Function************************************************************* + + Synopsis [Get the delay of the bound set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_SuppDelay( unsigned uSupp, char * pDelays ) +{ + int Delay, Var; + Delay = 0; + Lpk_SuppForEachVar( uSupp, Var ) + Delay = ABC_MAX( Delay, pDelays[Var] ); + return Delay + 1; +} + +/**Function************************************************************* + + Synopsis [Converts support into variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_SuppToVars( unsigned uBoundSet, char * pVars ) +{ + int i, nVars = 0; + Lpk_SuppForEachVar( uBoundSet, i ) + pVars[nVars++] = i; + return nVars; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/lpkCore.c b/abc70930/src/opt/lpk/lpkCore.c new file mode 100644 index 00000000..8b8028e3 --- /dev/null +++ b/abc70930/src/opt/lpk/lpkCore.c @@ -0,0 +1,659 @@ +/**CFile**************************************************************** + + FileName [lpkCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpkCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "lpkInt.h" +#include "cloud.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Prepares the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_IfManStart( Lpk_Man_t * p ) +{ + If_Par_t * pPars; + assert( p->pIfMan == NULL ); + // set defaults + pPars = ALLOC( If_Par_t, 1 ); + memset( pPars, 0, sizeof(If_Par_t) ); + // user-controlable paramters + pPars->nLutSize = p->pPars->nLutSize; + pPars->nCutsMax = 16; + pPars->nFlowIters = 0; // 1 + pPars->nAreaIters = 0; // 1 + pPars->DelayTarget = -1; + pPars->fPreprocess = 0; + pPars->fArea = 1; + pPars->fFancy = 0; + pPars->fExpRed = 0; // + pPars->fLatchPaths = 0; + pPars->fSeqMap = 0; + pPars->fVerbose = 0; + // internal parameters + pPars->fTruth = 1; + pPars->fUsePerm = 0; + pPars->nLatches = 0; + pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); + pPars->pTimesArr = NULL; + pPars->pTimesArr = NULL; + pPars->fUseBdds = 0; + pPars->fUseSops = 0; + pPars->fUseCnfs = 0; + pPars->fUseMv = 0; + // start the mapping manager and set its parameters + p->pIfMan = If_ManStart( pPars ); + If_ManSetupSetAll( p->pIfMan, 1000 ); + p->pIfMan->pPars->pTimesArr = ALLOC( float, 32 ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if at least one entry has changed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_NodeHasChanged( Lpk_Man_t * p, int iNode ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pTemp; + int i; + vNodes = Vec_VecEntry( p->vVisited, iNode ); + if ( Vec_PtrSize(vNodes) == 0 ) + return 1; + Vec_PtrForEachEntry( vNodes, pTemp, i ) + { + // check if the node has changed + pTemp = Abc_NtkObj( p->pNtk, (int)pTemp ); + if ( pTemp == NULL ) + return 1; + // check if the number of fanouts has changed +// if ( Abc_ObjFanoutNum(pTemp) != (int)Vec_PtrEntry(vNodes, i+1) ) +// return 1; + i++; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Prepares the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_ExploreCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, Kit_DsdNtk_t * pNtk ) +{ + extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ); + Kit_DsdObj_t * pRoot; + If_Obj_t * pDriver, * ppLeaves[16]; + Abc_Obj_t * pLeaf, * pObjNew; + int nGain, i, clk; + int nNodesBef; +// int nOldShared; + + // check special cases + pRoot = Kit_DsdNtkRoot( pNtk ); + if ( pRoot->Type == KIT_DSD_CONST1 ) + { + if ( Kit_DsdLitIsCompl(pNtk->Root) ) + pObjNew = Abc_NtkCreateNodeConst0( p->pNtk ); + else + pObjNew = Abc_NtkCreateNodeConst1( p->pNtk ); + Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); + p->nGainTotal += pCut->nNodes - pCut->nNodesDup; + return 1; + } + if ( pRoot->Type == KIT_DSD_VAR ) + { + pObjNew = Abc_NtkObj( p->pNtk, pCut->pLeaves[ Kit_DsdLit2Var(pRoot->pFans[0]) ] ); + if ( Kit_DsdLitIsCompl(pNtk->Root) ^ Kit_DsdLitIsCompl(pRoot->pFans[0]) ) + pObjNew = Abc_NtkCreateNodeInv( p->pNtk, pObjNew ); + Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); + p->nGainTotal += pCut->nNodes - pCut->nNodesDup; + return 1; + } + assert( pRoot->Type == KIT_DSD_AND || pRoot->Type == KIT_DSD_XOR || pRoot->Type == KIT_DSD_PRIME ); + + // start the mapping manager + if ( p->pIfMan == NULL ) + Lpk_IfManStart( p ); + + // prepare the mapping manager + If_ManRestart( p->pIfMan ); + // create the PI variables + for ( i = 0; i < p->pPars->nVarsMax; i++ ) + ppLeaves[i] = If_ManCreateCi( p->pIfMan ); + // set the arrival times + Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i ) + p->pIfMan->pPars->pTimesArr[i] = (float)pLeaf->Level; + // prepare the PI cuts + If_ManSetupCiCutSets( p->pIfMan ); + // create the internal nodes + p->fCalledOnce = 0; + p->nCalledSRed = 0; + pDriver = Lpk_MapTree_rec( p, pNtk, ppLeaves, pNtk->Root, NULL ); + if ( pDriver == NULL ) + return 0; + // create the PO node + If_ManCreateCo( p->pIfMan, If_Regular(pDriver) ); + + // perform mapping + p->pIfMan->pPars->fAreaOnly = 1; +clk = clock(); + If_ManPerformMappingComb( p->pIfMan ); +p->timeMap += clock() - clk; + + // compute the gain in area + nGain = pCut->nNodes - pCut->nNodesDup - (int)p->pIfMan->AreaGlo; + if ( p->pPars->fVeryVerbose ) + printf( " Mffc = %2d. Mapped = %2d. Gain = %3d. Depth increase = %d. SReds = %d.\n", + pCut->nNodes - pCut->nNodesDup, (int)p->pIfMan->AreaGlo, nGain, (int)p->pIfMan->RequiredGlo - (int)p->pObj->Level, p->nCalledSRed ); + + // quit if there is no gain + if ( !(nGain > 0 || (p->pPars->fZeroCost && nGain == 0)) ) + return 0; + + // quit if depth increases too much + if ( (int)p->pIfMan->RequiredGlo > Abc_ObjRequiredLevel(p->pObj) ) + return 0; + + // perform replacement + p->nGainTotal += nGain; + p->nChanges++; + if ( p->nCalledSRed ) + p->nBenefited++; + + nNodesBef = Abc_NtkNodeNum(p->pNtk); + // prepare the mapping manager + If_ManCleanNodeCopy( p->pIfMan ); + If_ManCleanCutData( p->pIfMan ); + // set the PIs of the cut + Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i ) + If_ObjSetCopy( If_ManCi(p->pIfMan, i), pLeaf ); + // get the area of mapping + pObjNew = Abc_NodeFromIf_rec( p->pNtk, p->pIfMan, If_Regular(pDriver), p->vCover ); + pObjNew->pData = Hop_NotCond( pObjNew->pData, If_IsComplement(pDriver) ); + // perform replacement + Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); +//printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs resynthesis for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_ResynthesizeNode( Lpk_Man_t * p ) +{ + static int Count = 0; + Kit_DsdNtk_t * pDsdNtk; + Lpk_Cut_t * pCut; + unsigned * pTruth; + int i, k, nSuppSize, nCutNodes, RetValue, clk; + + // compute the cuts +clk = clock(); + if ( !Lpk_NodeCuts( p ) ) + { +p->timeCuts += clock() - clk; + return 0; + } +p->timeCuts += clock() - clk; + +//return 0; + + if ( p->pPars->fVeryVerbose ) + printf( "Node %5d : Mffc size = %5d. Cuts = %5d.\n", p->pObj->Id, p->nMffc, p->nEvals ); + // try the good cuts + p->nCutsTotal += p->nCuts; + p->nCutsUseful += p->nEvals; + for ( i = 0; i < p->nEvals; i++ ) + { + // get the cut + pCut = p->pCuts + p->pEvals[i]; + if ( p->pPars->fFirst && i == 1 ) + break; + + // skip bad cuts +// printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) ); + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++; + nCutNodes = Abc_NodeMffcLabel(p->pObj); +// printf( "Mffc with cut = %d. ", nCutNodes ); + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--; +// printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup ); +// printf( "\n" ); + if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup ) + continue; + + // compute the truth table +clk = clock(); + pTruth = Lpk_CutTruth( p, pCut, 0 ); + nSuppSize = Extra_TruthSupportSize(pTruth, pCut->nLeaves); +p->timeTruth += clock() - clk; + + pDsdNtk = Kit_DsdDecompose( pTruth, pCut->nLeaves ); +// Kit_DsdVerify( pDsdNtk, pTruth, pCut->nLeaves ); + // skip 16-input non-DSD because ISOP will not work + if ( Kit_DsdNtkRoot(pDsdNtk)->nFans == 16 ) + { + Kit_DsdNtkFree( pDsdNtk ); + continue; + } + + // if DSD has nodes that require splitting to fit them into LUTs + // we can skip those cuts that cannot lead to improvement + // (a full DSD network requires V = Nmin * (K-1) + 1 for improvement) + if ( Kit_DsdNonDsdSizeMax(pDsdNtk) > p->pPars->nLutSize && + nSuppSize >= ((int)pCut->nNodes - (int)pCut->nNodesDup - 1) * (p->pPars->nLutSize - 1) + 1 ) + { + Kit_DsdNtkFree( pDsdNtk ); + continue; + } + + if ( p->pPars->fVeryVerbose ) + { +// char * pFileName; + printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ", + i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight ); + Kit_DsdPrint( stdout, pDsdNtk ); + Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); +// pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ ); +// printf( "Saved truth table in file \"%s\".\n", pFileName ); + } + + // update the network +clk = clock(); + RetValue = Lpk_ExploreCut( p, pCut, pDsdNtk ); +p->timeEval += clock() - clk; + Kit_DsdNtkFree( pDsdNtk ); + if ( RetValue ) + break; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Computes supports of the cofactors of the function.] + + Description [This procedure should be called after Lpk_CutTruth(p,pCut,0)] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_ComputeSupports( Lpk_Man_t * p, Lpk_Cut_t * pCut, unsigned * pTruth ) +{ + unsigned * pTruthInv; + int RetValue1, RetValue2; + pTruthInv = Lpk_CutTruth( p, pCut, 1 ); + RetValue1 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruth, pCut->nLeaves, p->vBddDir ); + RetValue2 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruthInv, pCut->nLeaves, p->vBddInv ); + if ( RetValue1 && RetValue2 ) + Kit_TruthCofSupports( p->vBddDir, p->vBddInv, pCut->nLeaves, p->vMemory, p->puSupps ); + else + p->puSupps[0] = p->puSupps[1] = 0; +} + + +/**Function************************************************************* + + Synopsis [Performs resynthesis for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_ResynthesizeNodeNew( Lpk_Man_t * p ) +{ + static int Count = 0; + Abc_Obj_t * pObjNew, * pLeaf; + Lpk_Cut_t * pCut; + unsigned * pTruth; + int nNodesBef, nNodesAft, nCutNodes; + int i, k, clk; + int Required = Abc_ObjRequiredLevel(p->pObj); +// CloudNode * pFun2;//, * pFun1; + + // compute the cuts +clk = clock(); + if ( !Lpk_NodeCuts( p ) ) + { +p->timeCuts += clock() - clk; + return 0; + } +p->timeCuts += clock() - clk; + + if ( p->pPars->fVeryVerbose ) + printf( "Node %5d : Mffc size = %5d. Cuts = %5d. Level = %2d. Req = %2d.\n", + p->pObj->Id, p->nMffc, p->nEvals, p->pObj->Level, Required ); + // try the good cuts + p->nCutsTotal += p->nCuts; + p->nCutsUseful += p->nEvals; + for ( i = 0; i < p->nEvals; i++ ) + { + // get the cut + pCut = p->pCuts + p->pEvals[i]; + if ( p->pPars->fFirst && i == 1 ) + break; +// if ( pCut->Weight < 1.05 ) +// continue; + + // skip bad cuts +// printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) ); + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++; + nCutNodes = Abc_NodeMffcLabel(p->pObj); +// printf( "Mffc with cut = %d. ", nCutNodes ); + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--; +// printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup ); +// printf( "\n" ); + if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup ) + continue; + + // collect nodes into the array + Vec_PtrClear( p->vLeaves ); + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + Vec_PtrPush( p->vLeaves, Abc_NtkObj(p->pNtk, pCut->pLeaves[k]) ); + + // compute the truth table +clk = clock(); + pTruth = Lpk_CutTruth( p, pCut, 0 ); +p->timeTruth += clock() - clk; +clk = clock(); + Lpk_ComputeSupports( p, pCut, pTruth ); +p->timeSupps += clock() - clk; +//clk = clock(); +// pFun1 = Lpk_CutTruthBdd( p, pCut ); +//p->timeTruth2 += clock() - clk; +/* +clk = clock(); + Cloud_Restart( p->pDsdMan->dd ); + pFun2 = Kit_TruthToCloud( p->pDsdMan->dd, pTruth, pCut->nLeaves ); + RetValue = Kit_CreateCloud( p->pDsdMan->dd, pFun2, p->vBddNodes ); +p->timeTruth3 += clock() - clk; +*/ +// if ( pFun1 != pFun2 ) +// printf( "Truth tables do not agree!\n" ); +// else +// printf( "Fine!\n" ); + + if ( p->pPars->fVeryVerbose ) + { +// char * pFileName; + int nSuppSize = Extra_TruthSupportSize( pTruth, pCut->nLeaves ); + printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ", + i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight ); + Vec_PtrForEachEntry( p->vLeaves, pLeaf, k ) + printf( "%c=%d ", 'a'+k, Abc_ObjLevel(pLeaf) ); + printf( "\n" ); + Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); +// pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ ); +// printf( "Saved truth table in file \"%s\".\n", pFileName ); + } + if ( p->pObj->Id == 33 && i == 0 ) + { + int x = 0; + } + + // update the network + nNodesBef = Abc_NtkNodeNum(p->pNtk); +clk = clock(); + pObjNew = Lpk_Decompose( p, p->pNtk, p->vLeaves, pTruth, p->puSupps, p->pPars->nLutSize, + (int)pCut->nNodes - (int)pCut->nNodesDup - 1 + (int)(p->pPars->fZeroCost > 0), Required ); +p->timeEval += clock() - clk; + nNodesAft = Abc_NtkNodeNum(p->pNtk); + + // perform replacement + if ( pObjNew ) + { + int nGain = (int)pCut->nNodes - (int)pCut->nNodesDup - (nNodesAft - nNodesBef); + assert( nGain >= 1 - p->pPars->fZeroCost ); + assert( Abc_ObjLevel(pObjNew) <= Required ); +/* + if ( nGain <= 0 ) + { + int x = 0; + } + if ( Abc_ObjLevel(pObjNew) > Required ) + { + int x = 0; + } +*/ + p->nGainTotal += nGain; + p->nChanges++; + if ( p->pPars->fVeryVerbose ) + printf( "Performed resynthesis: Gain = %2d. Level = %2d. Req = %2d.\n", nGain, Abc_ObjLevel(pObjNew), Required ); + Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); +//printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain ); + break; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs resynthesis for one network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars ) +{ + ProgressBar * pProgress; + Lpk_Man_t * p; + Abc_Obj_t * pObj; + double Delta; + int i, Iter, nNodes, nNodesPrev, clk = clock(); + assert( Abc_NtkIsLogic(pNtk) ); + + // sweep dangling nodes as a preprocessing step + Abc_NtkSweep( pNtk, 0 ); + + // get the number of inputs + pPars->nLutSize = Abc_NtkGetFaninMax( pNtk ); + // adjust the number of crossbars based on LUT size + if ( pPars->nVarsShared > pPars->nLutSize - 2 ) + pPars->nVarsShared = pPars->nLutSize - 2; + // get the max number of LUTs tried + pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1; // V = N * (K-1) + 1 + while ( pPars->nVarsMax > 16 ) + { + pPars->nLutsMax--; + pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1; + + } + if ( pPars->fVerbose ) + { + printf( "Resynthesis for %d %d-LUTs with %d non-MFFC LUTs, %d crossbars, and %d-input cuts.\n", + pPars->nLutsMax, pPars->nLutSize, pPars->nLutsOver, pPars->nVarsShared, pPars->nVarsMax ); + } + + + // convert into the AIG + if ( !Abc_NtkToAig(pNtk) ) + { + fprintf( stdout, "Converting to BDD has failed.\n" ); + return 0; + } + assert( Abc_NtkHasAig(pNtk) ); + + // set the number of levels + Abc_NtkLevel( pNtk ); + Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); + + // start the manager + p = Lpk_ManStart( pPars ); + p->pNtk = pNtk; + p->nNodesTotal = Abc_NtkNodeNum(pNtk); + p->vLevels = Vec_VecStart( pNtk->LevelMax ); + if ( p->pPars->fSatur ) + p->vVisited = Vec_VecStart( 0 ); + if ( pPars->fVerbose ) + { + p->nTotalNets = Abc_NtkGetTotalFanins(pNtk); + p->nTotalNodes = Abc_NtkNodeNum(pNtk); + } + + // iterate over the network + nNodesPrev = p->nNodesTotal; + for ( Iter = 1; ; Iter++ ) + { + // expand storage for changed nodes + if ( p->pPars->fSatur ) + Vec_VecExpand( p->vVisited, Abc_NtkObjNumMax(pNtk) + 1 ); + + // consider all nodes + nNodes = Abc_NtkObjNumMax(pNtk); + if ( !pPars->fVeryVerbose ) + pProgress = Extra_ProgressBarStart( stdout, nNodes ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + // skip all except the final node + if ( pPars->fFirst ) + { + if ( !Abc_ObjIsCo(Abc_ObjFanout0(pObj)) ) + continue; + } + if ( i >= nNodes ) + break; + if ( !pPars->fVeryVerbose ) + Extra_ProgressBarUpdate( pProgress, i, NULL ); + // skip the nodes that did not change + if ( p->pPars->fSatur && !Lpk_NodeHasChanged(p, pObj->Id) ) + continue; + // resynthesize + p->pObj = pObj; + if ( p->pPars->fOldAlgo ) + Lpk_ResynthesizeNode( p ); + else + Lpk_ResynthesizeNodeNew( p ); + } + if ( !pPars->fVeryVerbose ) + Extra_ProgressBarStop( pProgress ); + + // check the increase + Delta = 100.00 * (nNodesPrev - Abc_NtkNodeNum(pNtk)) / p->nNodesTotal; + if ( Delta < 0.05 ) + break; + nNodesPrev = Abc_NtkNodeNum(pNtk); + if ( !p->pPars->fSatur ) + break; + + if ( pPars->fFirst ) + break; + } + Abc_NtkStopReverseLevels( pNtk ); + + if ( pPars->fVerbose ) + { +// Cloud_PrintInfo( p->pDsdMan->dd ); + p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk); + p->nTotalNodes2 = Abc_NtkNodeNum(pNtk); + printf( "Node gain = %5d. (%.2f %%) ", + p->nTotalNodes-p->nTotalNodes2, 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes ); + printf( "Edge gain = %5d. (%.2f %%) ", + p->nTotalNets-p->nTotalNets2, 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets ); + printf( "Muxes = %4d. Dsds = %4d.", p->nMuxes, p->nDsds ); + printf( "\n" ); + printf( "Nodes = %5d (%3d) Cuts = %5d (%4d) Changes = %5d Iter = %2d Benefit = %d.\n", + p->nNodesTotal, p->nNodesOver, p->nCutsTotal, p->nCutsUseful, p->nChanges, Iter, p->nBenefited ); + + printf( "Non-DSD:" ); + for ( i = 3; i <= pPars->nVarsMax; i++ ) + if ( p->nBlocks[i] ) + printf( " %d=%d", i, p->nBlocks[i] ); + printf( "\n" ); + + p->timeTotal = clock() - clk; + p->timeEval = p->timeEval - p->timeMap; + p->timeOther = p->timeTotal - p->timeCuts - p->timeTruth - p->timeEval - p->timeMap; + PRTP( "Cuts ", p->timeCuts, p->timeTotal ); + PRTP( "Truth ", p->timeTruth, p->timeTotal ); + PRTP( "CSupps", p->timeSupps, p->timeTotal ); + PRTP( "Eval ", p->timeEval, p->timeTotal ); + PRTP( " MuxAn", p->timeEvalMuxAn, p->timeEval ); + PRTP( " MuxSp", p->timeEvalMuxSp, p->timeEval ); + PRTP( " DsdAn", p->timeEvalDsdAn, p->timeEval ); + PRTP( " DsdSp", p->timeEvalDsdSp, p->timeEval ); + PRTP( " Other", p->timeEval-p->timeEvalMuxAn-p->timeEvalMuxSp-p->timeEvalDsdAn-p->timeEvalDsdSp, p->timeEval ); + PRTP( "Map ", p->timeMap, p->timeTotal ); + PRTP( "Other ", p->timeOther, p->timeTotal ); + PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + } + + Lpk_ManStop( p ); + // check the resulting network + if ( !Abc_NtkCheck( pNtk ) ) + { + printf( "Lpk_Resynthesize: The network check has failed.\n" ); + return 0; + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/lpkCut.c b/abc70930/src/opt/lpk/lpkCut.c new file mode 100644 index 00000000..b2a743bd --- /dev/null +++ b/abc70930/src/opt/lpk/lpkCut.c @@ -0,0 +1,683 @@ +/**CFile**************************************************************** + + FileName [lpkCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpkCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "lpkInt.h" +#include "cloud.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the truth table of one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +CloudNode * Lpk_CutTruthBdd_rec( CloudManager * dd, Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars ) +{ + CloudNode * pTruth, * pTruth0, * pTruth1; + assert( !Hop_IsComplement(pObj) ); + if ( pObj->pData ) + { + assert( ((unsigned)pObj->pData) & 0xffff0000 ); + return pObj->pData; + } + // get the plan for a new truth table + if ( Hop_ObjIsConst1(pObj) ) + pTruth = dd->one; + else + { + assert( Hop_ObjIsAnd(pObj) ); + // compute the truth tables of the fanins + pTruth0 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin0(pObj), nVars ); + pTruth1 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin1(pObj), nVars ); + pTruth0 = Cloud_NotCond( pTruth0, Hop_ObjFaninC0(pObj) ); + pTruth1 = Cloud_NotCond( pTruth1, Hop_ObjFaninC1(pObj) ); + // creat the truth table of the node + pTruth = Cloud_bddAnd( dd, pTruth0, pTruth1 ); + } + pObj->pData = pTruth; + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Verifies that the factoring is correct.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +CloudNode * Lpk_CutTruthBdd( Lpk_Man_t * p, Lpk_Cut_t * pCut ) +{ + CloudManager * dd = p->pDsdMan->dd; + Hop_Man_t * pManHop = p->pNtk->pManFunc; + Hop_Obj_t * pObjHop; + Abc_Obj_t * pObj, * pFanin; + CloudNode * pTruth; + int i, k, iCount = 0; + +// return NULL; +// Lpk_NodePrintCut( p, pCut ); + // initialize the leaves + Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)dd->vars[pCut->nLeaves-1-i]; + + // construct truth table in the topological order + Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i ) + { + // get the local AIG + pObjHop = Hop_Regular(pObj->pData); + // clean the data field of the nodes in the AIG subgraph + Hop_ObjCleanData_rec( pObjHop ); + // set the initial truth tables at the fanins + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + assert( ((unsigned)pFanin->pCopy) & 0xffff0000 ); + Hop_ManPi( pManHop, k )->pData = pFanin->pCopy; + } + // compute the truth table of internal nodes + pTruth = Lpk_CutTruthBdd_rec( dd, pManHop, pObjHop, pCut->nLeaves ); + if ( Hop_IsComplement(pObj->pData) ) + pTruth = Cloud_Not(pTruth); + // set the truth table at the node + pObj->pCopy = (Abc_Obj_t *)pTruth; + + } + +// Cloud_bddPrint( dd, pTruth ); +// printf( "Bdd size = %d. Total nodes = %d.\n", Cloud_DagSize( dd, pTruth ), dd->nNodesCur-dd->nVars-1 ); + return pTruth; +} + + +/**Function************************************************************* + + Synopsis [Computes the truth table of one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Lpk_CutTruth_rec( Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars, Vec_Ptr_t * vTtNodes, int * piCount ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + assert( !Hop_IsComplement(pObj) ); + if ( pObj->pData ) + { + assert( ((unsigned)pObj->pData) & 0xffff0000 ); + return pObj->pData; + } + // get the plan for a new truth table + pTruth = Vec_PtrEntry( vTtNodes, (*piCount)++ ); + if ( Hop_ObjIsConst1(pObj) ) + Kit_TruthFill( pTruth, nVars ); + else + { + assert( Hop_ObjIsAnd(pObj) ); + // compute the truth tables of the fanins + pTruth0 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin0(pObj), nVars, vTtNodes, piCount ); + pTruth1 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin1(pObj), nVars, vTtNodes, piCount ); + // creat the truth table of the node + Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Hop_ObjFaninC0(pObj), Hop_ObjFaninC1(pObj) ); + } + pObj->pData = pTruth; + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Computes the truth able of one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Lpk_CutTruth( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fInv ) +{ + Hop_Man_t * pManHop = p->pNtk->pManFunc; + Hop_Obj_t * pObjHop; + Abc_Obj_t * pObj, * pFanin; + unsigned * pTruth; + int i, k, iCount = 0; +// Lpk_NodePrintCut( p, pCut ); + assert( pCut->nNodes > 0 ); + + // initialize the leaves + Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) + pObj->pCopy = Vec_PtrEntry( p->vTtElems, fInv? pCut->nLeaves-1-i : i ); + + // construct truth table in the topological order + Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i ) + { + // get the local AIG + pObjHop = Hop_Regular(pObj->pData); + // clean the data field of the nodes in the AIG subgraph + Hop_ObjCleanData_rec( pObjHop ); + // set the initial truth tables at the fanins + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + assert( ((unsigned)pFanin->pCopy) & 0xffff0000 ); + Hop_ManPi( pManHop, k )->pData = pFanin->pCopy; + } + // compute the truth table of internal nodes + pTruth = Lpk_CutTruth_rec( pManHop, pObjHop, pCut->nLeaves, p->vTtNodes, &iCount ); + if ( Hop_IsComplement(pObj->pData) ) + Kit_TruthNot( pTruth, pTruth, pCut->nLeaves ); + // set the truth table at the node + pObj->pCopy = (Abc_Obj_t *)pTruth; + } + + // make sure direct truth table is stored elsewhere (assuming the first call for direct truth!!!) + if ( fInv == 0 ) + { + pTruth = Vec_PtrEntry( p->vTtNodes, iCount++ ); + Kit_TruthCopy( pTruth, (unsigned *)pObj->pCopy, pCut->nLeaves ); + } + assert( iCount <= Vec_PtrSize(p->vTtNodes) ); + return pTruth; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if at least one entry has changed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_NodeRecordImpact( Lpk_Man_t * p ) +{ + Lpk_Cut_t * pCut; + Vec_Ptr_t * vNodes = Vec_VecEntry( p->vVisited, p->pObj->Id ); + Abc_Obj_t * pNode; + int i, k; + // collect the nodes that impact the given node + Vec_PtrClear( vNodes ); + for ( i = 0; i < p->nCuts; i++ ) + { + pCut = p->pCuts + i; + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + { + pNode = Abc_NtkObj( p->pNtk, pCut->pLeaves[k] ); + if ( pNode->fMarkC ) + continue; + pNode->fMarkC = 1; + Vec_PtrPush( vNodes, (void *)pNode->Id ); + Vec_PtrPush( vNodes, (void *)Abc_ObjFanoutNum(pNode) ); + } + } + // clear the marks + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + pNode = Abc_NtkObj( p->pNtk, (int)pNode ); + pNode->fMarkC = 0; + i++; + } +//printf( "%d ", Vec_PtrSize(vNodes) ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut has structural DSD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_NodeCutsCheckDsd( Lpk_Man_t * p, Lpk_Cut_t * pCut ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k, nCands, fLeavesOnly, RetValue; + assert( pCut->nLeaves > 0 ); + // clear ref counters + memset( p->pRefs, 0, sizeof(int) * pCut->nLeaves ); + // mark cut leaves + Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) + { + assert( pObj->fMarkA == 0 ); + pObj->fMarkA = 1; + pObj->pCopy = (void *)i; + } + // ref leaves pointed from the internal nodes + nCands = 0; + Lpk_CutForEachNode( p->pNtk, pCut, pObj, i ) + { + fLeavesOnly = 1; + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( pFanin->fMarkA ) + p->pRefs[(int)pFanin->pCopy]++; + else + fLeavesOnly = 0; + if ( fLeavesOnly ) + p->pCands[nCands++] = pObj->Id; + } + // look at the nodes that only point to the leaves + RetValue = 0; + for ( i = 0; i < nCands; i++ ) + { + pObj = Abc_NtkObj( p->pNtk, p->pCands[i] ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + assert( pFanin->fMarkA == 1 ); + if ( p->pRefs[(int)pFanin->pCopy] > 1 ) + break; + } + if ( k == Abc_ObjFaninNum(pObj) ) + { + RetValue = 1; + break; + } + } + // unmark cut leaves + Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) + pObj->fMarkA = 0; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Lpk_NodeCutsOneDominance( Lpk_Cut_t * pDom, Lpk_Cut_t * pCut ) +{ + int i, k; + for ( i = 0; i < (int)pDom->nLeaves; i++ ) + { + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) + break; + if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Check if the cut exists.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_NodeCutsOneFilter( Lpk_Cut_t * pCuts, int nCuts, Lpk_Cut_t * pCutNew ) +{ + Lpk_Cut_t * pCut; + int i, k; + assert( pCutNew->uSign[0] || pCutNew->uSign[1] ); + // try to find the cut + for ( i = 0; i < nCuts; i++ ) + { + pCut = pCuts + i; + if ( pCut->nLeaves == 0 ) + continue; + if ( pCut->nLeaves == pCutNew->nLeaves ) + { + if ( pCut->uSign[0] == pCutNew->uSign[0] && pCut->uSign[1] == pCutNew->uSign[1] ) + { + for ( k = 0; k < (int)pCutNew->nLeaves; k++ ) + if ( pCut->pLeaves[k] != pCutNew->pLeaves[k] ) + break; + if ( k == (int)pCutNew->nLeaves ) + return 1; + } + continue; + } + if ( pCut->nLeaves < pCutNew->nLeaves ) + { + // skip the non-contained cuts + if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCut->uSign[0] ) + continue; + if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCut->uSign[1] ) + continue; + // check containment seriously + if ( Lpk_NodeCutsOneDominance( pCut, pCutNew ) ) + return 1; + continue; + } + // check potential containment of other cut + + // skip the non-contained cuts + if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCutNew->uSign[0] ) + continue; + if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCutNew->uSign[1] ) + continue; + // check containment seriously + if ( Lpk_NodeCutsOneDominance( pCutNew, pCut ) ) + pCut->nLeaves = 0; // removed + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Prints the given cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_NodePrintCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fLeavesOnly ) +{ + Abc_Obj_t * pObj; + int i; + if ( !fLeavesOnly ) + printf( "LEAVES:\n" ); + Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) + printf( "%d,", pObj->Id ); + if ( !fLeavesOnly ) + { + printf( "\nNODES:\n" ); + Lpk_CutForEachNode( p->pNtk, pCut, pObj, i ) + { + printf( "%d,", pObj->Id ); + assert( Abc_ObjIsNode(pObj) ); + } + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Set the cut signature.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_NodeCutSignature( Lpk_Cut_t * pCut ) +{ + unsigned i; + pCut->uSign[0] = pCut->uSign[1] = 0; + for ( i = 0; i < pCut->nLeaves; i++ ) + { + pCut->uSign[(pCut->pLeaves[i] & 32) > 0] |= (1 << (pCut->pLeaves[i] & 31)); + if ( i != pCut->nLeaves - 1 ) + assert( pCut->pLeaves[i] < pCut->pLeaves[i+1] ); + } +} + + +/**Function************************************************************* + + Synopsis [Computes the set of all cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_NodeCutsOne( Lpk_Man_t * p, Lpk_Cut_t * pCut, int Node ) +{ + Lpk_Cut_t * pCutNew; + Abc_Obj_t * pObj, * pFanin; + int i, k, j, nLeavesNew; +/* + printf( "Exploring cut " ); + Lpk_NodePrintCut( p, pCut, 1 ); + printf( "with node %d\n", Node ); +*/ + // check if the cut can stand adding one more internal node + if ( pCut->nNodes == LPK_SIZE_MAX ) + return; + + // if the node is a PI, quit + pObj = Abc_NtkObj( p->pNtk, Node ); + if ( Abc_ObjIsCi(pObj) ) + return; + assert( Abc_ObjIsNode(pObj) ); + assert( Abc_ObjFaninNum(pObj) <= p->pPars->nLutSize ); + + // if the node is not in the MFFC, check the limit + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + { + if ( (int)pCut->nNodesDup == p->pPars->nLutsOver ) + return; + assert( (int)pCut->nNodesDup < p->pPars->nLutsOver ); + } + + // check the possibility of adding this node using the signature + nLeavesNew = pCut->nLeaves - 1; + Abc_ObjForEachFanin( pObj, pFanin, i ) + { + if ( (pCut->uSign[(pFanin->Id & 32) > 0] & (1 << (pFanin->Id & 31))) ) + continue; + if ( ++nLeavesNew > p->pPars->nVarsMax ) + return; + } + + // initialize the set of leaves to the nodes in the cut + assert( p->nCuts < LPK_CUTS_MAX ); + pCutNew = p->pCuts + p->nCuts; + pCutNew->nLeaves = 0; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + if ( pCut->pLeaves[i] != Node ) + pCutNew->pLeaves[pCutNew->nLeaves++] = pCut->pLeaves[i]; + + // add new nodes + Abc_ObjForEachFanin( pObj, pFanin, i ) + { + // find the place where this node belongs + for ( k = 0; k < (int)pCutNew->nLeaves; k++ ) + if ( pCutNew->pLeaves[k] >= pFanin->Id ) + break; + if ( k < (int)pCutNew->nLeaves && pCutNew->pLeaves[k] == pFanin->Id ) + continue; + // check if there is room + if ( (int)pCutNew->nLeaves == p->pPars->nVarsMax ) + return; + // move all the nodes + for ( j = pCutNew->nLeaves; j > k; j-- ) + pCutNew->pLeaves[j] = pCutNew->pLeaves[j-1]; + pCutNew->pLeaves[k] = pFanin->Id; + pCutNew->nLeaves++; + assert( pCutNew->nLeaves <= LPK_SIZE_MAX ); + + } + // skip the contained cuts + Lpk_NodeCutSignature( pCutNew ); + if ( Lpk_NodeCutsOneFilter( p->pCuts, p->nCuts, pCutNew ) ) + return; + + // update the set of internal nodes + assert( pCut->nNodes < LPK_SIZE_MAX ); + memcpy( pCutNew->pNodes, pCut->pNodes, pCut->nNodes * sizeof(int) ); + pCutNew->nNodes = pCut->nNodes; + pCutNew->nNodesDup = pCut->nNodesDup; + + // check if the node is already there + // if so, move the node to be the last + for ( i = 0; i < (int)pCutNew->nNodes; i++ ) + if ( pCutNew->pNodes[i] == Node ) + { + for ( k = i; k < (int)pCutNew->nNodes - 1; k++ ) + pCutNew->pNodes[k] = pCutNew->pNodes[k+1]; + pCutNew->pNodes[k] = Node; + break; + } + if ( i == (int)pCutNew->nNodes ) // new node + { + pCutNew->pNodes[ pCutNew->nNodes++ ] = Node; + pCutNew->nNodesDup += !Abc_NodeIsTravIdCurrent(pObj); + } + // the number of nodes does not exceed MFFC plus duplications + assert( pCutNew->nNodes <= p->nMffc + pCutNew->nNodesDup ); + // add the cut to storage + assert( p->nCuts < LPK_CUTS_MAX ); + p->nCuts++; +} + +/**Function************************************************************* + + Synopsis [Computes the set of all cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_NodeCuts( Lpk_Man_t * p ) +{ + Lpk_Cut_t * pCut, * pCut2; + int i, k, Temp, nMffc, fChanges; + + // mark the MFFC of the node with the current trav ID + nMffc = p->nMffc = Abc_NodeMffcLabel( p->pObj ); + assert( nMffc > 0 ); + if ( nMffc == 1 ) + return 0; + + // initialize the first cut + pCut = p->pCuts; p->nCuts = 1; + pCut->nNodes = 0; + pCut->nNodesDup = 0; + pCut->nLeaves = 1; + pCut->pLeaves[0] = p->pObj->Id; + // assign the signature + Lpk_NodeCutSignature( pCut ); + + // perform the cut computation + for ( i = 0; i < p->nCuts; i++ ) + { + pCut = p->pCuts + i; + if ( pCut->nLeaves == 0 ) + continue; + + // try to expand the fanins of this cut + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + { + // create a new cut + Lpk_NodeCutsOne( p, pCut, pCut->pLeaves[k] ); + // quit if the number of cuts has exceeded the limit + if ( p->nCuts == LPK_CUTS_MAX ) + break; + } + if ( p->nCuts == LPK_CUTS_MAX ) + break; + } + if ( p->nCuts == LPK_CUTS_MAX ) + p->nNodesOver++; + + // record the impact of this node + if ( p->pPars->fSatur ) + Lpk_NodeRecordImpact( p ); + + // compress the cuts by removing empty ones, those with negative Weight, and decomposable ones + p->nEvals = 0; + for ( i = 0; i < p->nCuts; i++ ) + { + pCut = p->pCuts + i; + if ( pCut->nLeaves < 2 ) + continue; + // compute the minimum number of LUTs needed to implement this cut + // V = N * (K-1) + 1 ~~~~~ N = Ceiling[(V-1)/(K-1)] = (V-1)/(K-1) + [(V-1)%(K-1) > 0] + pCut->nLuts = Lpk_LutNumLuts( pCut->nLeaves, p->pPars->nLutSize ); +// pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup - 1) / pCut->nLuts; //p->pPars->nLutsMax; + pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup) / pCut->nLuts; //p->pPars->nLutsMax; + if ( pCut->Weight <= 1.001 ) +// if ( pCut->Weight <= 0.999 ) + continue; + pCut->fHasDsd = Lpk_NodeCutsCheckDsd( p, pCut ); + if ( pCut->fHasDsd ) + continue; + p->pEvals[p->nEvals++] = i; + } + if ( p->nEvals == 0 ) + return 0; + + // sort the cuts by Weight + do { + fChanges = 0; + for ( i = 0; i < p->nEvals - 1; i++ ) + { + pCut = p->pCuts + p->pEvals[i]; + pCut2 = p->pCuts + p->pEvals[i+1]; + if ( pCut->Weight >= pCut2->Weight - 0.001 ) + continue; + Temp = p->pEvals[i]; + p->pEvals[i] = p->pEvals[i+1]; + p->pEvals[i+1] = Temp; + fChanges = 1; + } + } while ( fChanges ); +/* + for ( i = 0; i < p->nEvals; i++ ) + { + pCut = p->pCuts + p->pEvals[i]; + printf( "Cut %3d : W = %5.2f.\n", i, pCut->Weight ); + } + printf( "\n" ); +*/ + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/lpkInt.h b/abc70930/src/opt/lpk/lpkInt.h new file mode 100644 index 00000000..960599e4 --- /dev/null +++ b/abc70930/src/opt/lpk/lpkInt.h @@ -0,0 +1,246 @@ +/**CFile**************************************************************** + + FileName [lpkInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpkInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __LPK_INT_H__ +#define __LPK_INT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "abc.h" +#include "kit.h" +#include "if.h" +#include "lpk.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +#define LPK_SIZE_MAX 24 // the largest size of the function +#define LPK_CUTS_MAX 512 // the largest number of cuts considered + +typedef struct Lpk_Man_t_ Lpk_Man_t; +typedef struct Lpk_Cut_t_ Lpk_Cut_t; + +struct Lpk_Cut_t_ +{ + unsigned nLeaves : 6; // (L) the number of leaves + unsigned nNodes : 6; // (M) the number of nodes + unsigned nNodesDup : 6; // (Q) nodes outside of MFFC + unsigned nLuts : 6; // (N) the number of LUTs to try + unsigned unused : 6; // unused + unsigned fHasDsd : 1; // set to 1 if the cut has structural DSD (and so cannot be used) + unsigned fMark : 1; // multipurpose mark + unsigned uSign[2]; // the signature + float Weight; // the weight of the cut: (M - Q)/N(V) (the larger the better) + int Gain; // the gain achieved using this cut + int pLeaves[LPK_SIZE_MAX]; // the leaves of the cut + int pNodes[LPK_SIZE_MAX]; // the nodes of the cut +}; + +struct Lpk_Man_t_ +{ + // parameters + Lpk_Par_t * pPars; // the set of parameters + // current representation + Abc_Ntk_t * pNtk; // the network + Abc_Obj_t * pObj; // the node to resynthesize + // cut representation + int nMffc; // the size of MFFC of the node + int nCuts; // the total number of cuts + int nCutsMax; // the largest possible number of cuts + int nEvals; // the number of good cuts + Lpk_Cut_t pCuts[LPK_CUTS_MAX]; // the storage for cuts + int pEvals[LPK_CUTS_MAX]; // the good cuts + // visited nodes + Vec_Vec_t * vVisited; + // mapping manager + If_Man_t * pIfMan; + Vec_Int_t * vCover; + Vec_Vec_t * vLevels; + // temporary variables + int fCofactoring; // working in the cofactoring mode + int fCalledOnce; // limits the depth of MUX cofactoring + int nCalledSRed; // the number of called to SRed + int pRefs[LPK_SIZE_MAX]; // fanin reference counters + int pCands[LPK_SIZE_MAX]; // internal nodes pointing only to the leaves + Vec_Ptr_t * vLeaves; + // truth table representation + Vec_Ptr_t * vTtElems; // elementary truth tables + Vec_Ptr_t * vTtNodes; // storage for temporary truth tables of the nodes + Vec_Int_t * vMemory; + Vec_Int_t * vBddDir; + Vec_Int_t * vBddInv; + unsigned puSupps[32]; // the supports of the cofactors + unsigned * ppTruths[5][16]; + // variable sets + Vec_Int_t * vSets[8]; + Kit_DsdMan_t* pDsdMan; + // statistics + int nNodesTotal; // total number of nodes + int nNodesOver; // nodes with cuts over the limit + int nCutsTotal; // total number of cuts + int nCutsUseful; // useful cuts + int nGainTotal; // the gain in LUTs + int nChanges; // the number of changed nodes + int nBenefited; // the number of gainful that benefited from decomposition + int nMuxes; + int nDsds; + int nTotalNets; + int nTotalNets2; + int nTotalNodes; + int nTotalNodes2; + // counter of non-DSD blocks + int nBlocks[17]; + // runtime + int timeCuts; + int timeTruth; + int timeSupps; + int timeTruth2; + int timeTruth3; + int timeEval; + int timeMap; + int timeOther; + int timeTotal; + // runtime of eval + int timeEvalMuxAn; + int timeEvalMuxSp; + int timeEvalDsdAn; + int timeEvalDsdSp; + +}; + + +// internal representation of the function to be decomposed +typedef struct Lpk_Fun_t_ Lpk_Fun_t; +struct Lpk_Fun_t_ +{ + Vec_Ptr_t * vNodes; // the array of leaves and decomposition nodes + unsigned Id : 7; // the ID of this node + unsigned nVars : 5; // the number of variables + unsigned nLutK : 4; // the number of LUT inputs + unsigned nAreaLim : 5; // the area limit (the largest allowed) + unsigned nDelayLim : 9; // the delay limit (the largest allowed) + unsigned fSupports : 1; // supports of cofactors were precomputed + unsigned fMark : 1; // marks the MUX-based dec + unsigned uSupp; // the support of this component + unsigned puSupps[32]; // the supports of the cofactors + char pDelays[16]; // the delays of the inputs + char pFanins[16]; // the fanins of this function + unsigned pTruth[0]; // the truth table (contains room for three truth tables) +}; + +// preliminary decomposition result +typedef struct Lpk_Res_t_ Lpk_Res_t; +struct Lpk_Res_t_ +{ + int nBSVars; // the number of bound set variables + unsigned BSVars; // the bound set + int nCofVars; // the number of cofactoring variables + char pCofVars[4]; // the cofactoring variables + int nSuppSizeS; // support size of the smaller (decomposed) function + int nSuppSizeL; // support size of the larger (composition) function + int DelayEst; // estimated delay of the decomposition + int AreaEst; // estimated area of the decomposition + int Variable; // variable in MUX decomposition + int Polarity; // polarity in MUX decomposition +}; + +static inline int Lpk_LutNumVars( int nLutsLim, int nLutK ) { return nLutsLim * (nLutK - 1) + 1; } +static inline int Lpk_LutNumLuts( int nVarsMax, int nLutK ) { return (nVarsMax - 1) / (nLutK - 1) + (int)((nVarsMax - 1) % (nLutK - 1) > 0); } +static inline unsigned * Lpk_FunTruth( Lpk_Fun_t * p, int Num ) { assert( Num < 3 ); return p->pTruth + Kit_TruthWordNum(p->nVars) * Num; } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +#define Lpk_CutForEachLeaf( pNtk, pCut, pObj, i ) \ + for ( i = 0; (i < (int)(pCut)->nLeaves) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pLeaves[i])), 1); i++ ) +#define Lpk_CutForEachNode( pNtk, pCut, pObj, i ) \ + for ( i = 0; (i < (int)(pCut)->nNodes) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i++ ) +#define Lpk_CutForEachNodeReverse( pNtk, pCut, pObj, i ) \ + for ( i = (int)(pCut)->nNodes - 1; (i >= 0) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i-- ) +#define Lpk_SuppForEachVar( Supp, Var )\ + for ( Var = 0; Var < 16; Var++ )\ + if ( !(Supp & (1<nLutsMax <= 16 ); + assert( pPars->nVarsMax > 0 && pPars->nVarsMax <= 16 ); + p = ALLOC( Lpk_Man_t, 1 ); + memset( p, 0, sizeof(Lpk_Man_t) ); + p->pPars = pPars; + p->nCutsMax = LPK_CUTS_MAX; + p->vTtElems = Vec_PtrAllocTruthTables( pPars->nVarsMax ); + p->vTtNodes = Vec_PtrAllocSimInfo( 1024, Abc_TruthWordNum(pPars->nVarsMax) ); + p->vCover = Vec_IntAlloc( 1 << 12 ); + p->vLeaves = Vec_PtrAlloc( 32 ); + for ( i = 0; i < 8; i++ ) + p->vSets[i] = Vec_IntAlloc(100); + p->pDsdMan = Kit_DsdManAlloc( pPars->nVarsMax, 64 ); + p->vMemory = Vec_IntAlloc( 1024 * 32 ); + p->vBddDir = Vec_IntAlloc( 256 ); + p->vBddInv = Vec_IntAlloc( 256 ); + // allocate temporary storage for truth tables + nWords = Kit_TruthWordNum(pPars->nVarsMax); + p->ppTruths[0][0] = ALLOC( unsigned, 32 * nWords ); + p->ppTruths[1][0] = p->ppTruths[0][0] + 1 * nWords; + for ( i = 1; i < 2; i++ ) + p->ppTruths[1][i] = p->ppTruths[1][0] + i * nWords; + p->ppTruths[2][0] = p->ppTruths[1][0] + 2 * nWords; + for ( i = 1; i < 4; i++ ) + p->ppTruths[2][i] = p->ppTruths[2][0] + i * nWords; + p->ppTruths[3][0] = p->ppTruths[2][0] + 4 * nWords; + for ( i = 1; i < 8; i++ ) + p->ppTruths[3][i] = p->ppTruths[3][0] + i * nWords; + p->ppTruths[4][0] = p->ppTruths[3][0] + 8 * nWords; + for ( i = 1; i < 16; i++ ) + p->ppTruths[4][i] = p->ppTruths[4][0] + i * nWords; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_ManStop( Lpk_Man_t * p ) +{ + int i; + free( p->ppTruths[0][0] ); + Vec_IntFree( p->vBddDir ); + Vec_IntFree( p->vBddInv ); + Vec_IntFree( p->vMemory ); + Kit_DsdManFree( p->pDsdMan ); + for ( i = 0; i < 8; i++ ) + Vec_IntFree(p->vSets[i]); + if ( p->pIfMan ) + { + void * pPars = p->pIfMan->pPars; + If_ManStop( p->pIfMan ); + free( pPars ); + } + if ( p->vLevels ) + Vec_VecFree( p->vLevels ); + if ( p->vVisited ) + Vec_VecFree( p->vVisited ); + Vec_PtrFree( p->vLeaves ); + Vec_IntFree( p->vCover ); + Vec_PtrFree( p->vTtElems ); + Vec_PtrFree( p->vTtNodes ); + free( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/lpkMap.c b/abc70930/src/opt/lpk/lpkMap.c new file mode 100644 index 00000000..698aeea1 --- /dev/null +++ b/abc70930/src/opt/lpk/lpkMap.c @@ -0,0 +1,205 @@ +/**CFile**************************************************************** + + FileName [lpkMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpkMap.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "lpkInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * Lpk_MapPrimeInternal( If_Man_t * pIfMan, Kit_Graph_t * pGraph ) +{ + Kit_Node_t * pNode; + If_Obj_t * pAnd0, * pAnd1; + int i; + // check for constant function + if ( Kit_GraphIsConst(pGraph) ) + return If_ManConst1(pIfMan); + // check for a literal + if ( Kit_GraphIsVar(pGraph) ) + return Kit_GraphVar(pGraph)->pFunc; + // build the AIG nodes corresponding to the AND gates of the graph + Kit_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; + pAnd1 = Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; + pNode->pFunc = If_ManCreateAnd( pIfMan, + If_NotCond( If_Regular(pAnd0), If_IsComplement(pAnd0) ^ pNode->eEdge0.fCompl ), + If_NotCond( If_Regular(pAnd1), If_IsComplement(pAnd1) ^ pNode->eEdge1.fCompl ) ); + } + return pNode->pFunc; +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * Lpk_MapPrime( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) +{ + Kit_Graph_t * pGraph; + Kit_Node_t * pNode; + If_Obj_t * pRes; + int i; + // derive the factored form + pGraph = Kit_TruthToGraph( pTruth, nVars, p->vCover ); + if ( pGraph == NULL ) + return NULL; + // collect the fanins + Kit_GraphForEachLeaf( pGraph, pNode, i ) + pNode->pFunc = ppLeaves[i]; + // perform strashing + pRes = Lpk_MapPrimeInternal( p->pIfMan, pGraph ); + pRes = If_NotCond( pRes, Kit_GraphIsComplement(pGraph) ); + Kit_GraphFree( pGraph ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Prepares the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLeaves, int iLit, If_Obj_t * pResult ) +{ + Kit_DsdObj_t * pObj; + If_Obj_t * pObjNew = NULL, * pObjNew2 = NULL, * pFansNew[16]; + unsigned i, iLitFanin; + + assert( iLit >= 0 ); + + // consider the case of a gate + pObj = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iLit) ); + if ( pObj == NULL ) + { + pObjNew = ppLeaves[Kit_DsdLit2Var(iLit)]; + return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ); + } + if ( pObj->Type == KIT_DSD_CONST1 ) + { + return If_NotCond( If_ManConst1(p->pIfMan), Kit_DsdLitIsCompl(iLit) ); + } + if ( pObj->Type == KIT_DSD_VAR ) + { + pObjNew = ppLeaves[Kit_DsdLit2Var(pObj->pFans[0])]; + return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ^ Kit_DsdLitIsCompl(pObj->pFans[0]) ); + } + if ( pObj->Type == KIT_DSD_AND ) + { + assert( pObj->nFans == 2 ); + pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL ); + pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL ); + if ( pFansNew[0] == NULL || pFansNew[1] == NULL ) + return NULL; + pObjNew = If_ManCreateAnd( p->pIfMan, pFansNew[0], pFansNew[1] ); + return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ); + } + if ( pObj->Type == KIT_DSD_XOR ) + { + int fCompl = Kit_DsdLitIsCompl(iLit); + assert( pObj->nFans == 2 ); + pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL ); + pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL ); + if ( pFansNew[0] == NULL || pFansNew[1] == NULL ) + return NULL; + fCompl ^= If_IsComplement(pFansNew[0]) ^ If_IsComplement(pFansNew[1]); + pObjNew = If_ManCreateXor( p->pIfMan, If_Regular(pFansNew[0]), If_Regular(pFansNew[1]) ); + return If_NotCond( pObjNew, fCompl ); + } + assert( pObj->Type == KIT_DSD_PRIME ); + p->nBlocks[pObj->nFans]++; + + // solve for the inputs + Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i ) + { + if ( i == 0 ) + pFansNew[i] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL ); + else + pFansNew[i] = Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL ); + if ( pFansNew[i] == NULL ) + return NULL; + } +/* + if ( !p->fCofactoring && p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize ) + { + pObjNew = Lpk_MapTreeMulti( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); + return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ); + } +*/ +/* + if ( (int)pObj->nFans > p->pPars->nLutSize ) + { + pObjNew2 = Lpk_MapTreeMux_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); +// if ( pObjNew2 ) +// return If_NotCond( pObjNew2, Kit_DsdLitIsCompl(iLit) ); + } +*/ + + // find best cofactoring variable + if ( p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize ) + { + pObjNew2 = Lpk_MapSuppRedDec_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); + if ( pObjNew2 ) + return If_NotCond( pObjNew2, Kit_DsdLitIsCompl(iLit) ); + } + + pObjNew = Lpk_MapPrime( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); + + // add choice + if ( pObjNew && pObjNew2 ) + { + If_ObjSetChoice( If_Regular(pObjNew), If_Regular(pObjNew2) ); + If_ManCreateChoice( p->pIfMan, If_Regular(pObjNew) ); + } + return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/lpkMulti.c b/abc70930/src/opt/lpk/lpkMulti.c new file mode 100644 index 00000000..82cf3578 --- /dev/null +++ b/abc70930/src/opt/lpk/lpkMulti.c @@ -0,0 +1,495 @@ +/**CFile**************************************************************** + + FileName [lpkMulti.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpkMulti.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "lpkInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Records variable order.] + + Description [Increaments Order[x][y] by 1 if x should be above y in the DSD.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_CreateVarOrder( Kit_DsdNtk_t * pNtk, char pTable[][16] ) +{ + Kit_DsdObj_t * pObj; + unsigned uSuppFanins, k; + int Above[16], Below[16]; + int nAbove, nBelow, iFaninLit, i, x, y; + // iterate through the nodes + Kit_DsdNtkForEachObj( pNtk, pObj, i ) + { + // collect fanin support of this node + nAbove = 0; + uSuppFanins = 0; + Kit_DsdObjForEachFanin( pNtk, pObj, iFaninLit, k ) + { + if ( Kit_DsdLitIsLeaf( pNtk, iFaninLit ) ) + Above[nAbove++] = Kit_DsdLit2Var(iFaninLit); + else + uSuppFanins |= Kit_DsdLitSupport( pNtk, iFaninLit ); + } + // find the below variables + nBelow = 0; + for ( y = 0; y < 16; y++ ) + if ( uSuppFanins & (1 << y) ) + Below[nBelow++] = y; + // create all pairs + for ( x = 0; x < nAbove; x++ ) + for ( y = 0; y < nBelow; y++ ) + pTable[Above[x]][Below[y]]++; + } +} + +/**Function************************************************************* + + Synopsis [Creates commmon variable order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_CreateCommonOrder( char pTable[][16], int piCofVar[], int nCBars, int pPrios[], int nVars, int fVerbose ) +{ + int Score[16] = {0}, pPres[16]; + int i, y, x, iVarBest, ScoreMax, PrioCount; + + // mark the present variables + for ( i = 0; i < nVars; i++ ) + pPres[i] = 1; + // remove cofactored variables + for ( i = 0; i < nCBars; i++ ) + pPres[piCofVar[i]] = 0; + + // compute scores for each leaf + for ( i = 0; i < nVars; i++ ) + { + if ( pPres[i] == 0 ) + continue; + for ( y = 0; y < nVars; y++ ) + Score[i] += pTable[i][y]; + for ( x = 0; x < nVars; x++ ) + Score[i] -= pTable[x][i]; + } + + // print the scores + if ( fVerbose ) + { + printf( "Scores: " ); + for ( i = 0; i < nVars; i++ ) + printf( "%c=%d ", 'a'+i, Score[i] ); + printf( " " ); + printf( "Prios: " ); + } + + // derive variable priority + // variables with equal score receive the same priority + for ( i = 0; i < nVars; i++ ) + pPrios[i] = 16; + + // iterate until variables remain + for ( PrioCount = 1; ; PrioCount++ ) + { + // find the present variable with the highest score + iVarBest = -1; + ScoreMax = -100000; + for ( i = 0; i < nVars; i++ ) + { + if ( pPres[i] == 0 ) + continue; + if ( ScoreMax < Score[i] ) + { + ScoreMax = Score[i]; + iVarBest = i; + } + } + if ( iVarBest == -1 ) + break; + // give the next priority to all vars having this score + if ( fVerbose ) + printf( "%d=", PrioCount ); + for ( i = 0; i < nVars; i++ ) + { + if ( pPres[i] == 0 ) + continue; + if ( Score[i] == ScoreMax ) + { + pPrios[i] = PrioCount; + pPres[i] = 0; + if ( fVerbose ) + printf( "%c", 'a'+i ); + } + } + if ( fVerbose ) + printf( " " ); + } + if ( fVerbose ) + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Finds components with the highest priority.] + + Description [Returns the number of components selected.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_FindHighest( Kit_DsdNtk_t ** ppNtks, int * piLits, int nSize, int * pPrio, int * pDecision ) +{ + Kit_DsdObj_t * pObj; + unsigned uSupps[8], uSuppFanin, uSuppTotal, uSuppLarge; + int i, pTriv[8], PrioMin, iVarMax, nComps, fOneNonTriv; + + // find individual support and total support + uSuppTotal = 0; + for ( i = 0; i < nSize; i++ ) + { + pTriv[i] = 1; + if ( piLits[i] < 0 ) + uSupps[i] = 0; + else if ( Kit_DsdLitIsLeaf(ppNtks[i], piLits[i]) ) + uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ); + else + { + pObj = Kit_DsdNtkObj( ppNtks[i], Kit_DsdLit2Var(piLits[i]) ); + if ( pObj->Type == KIT_DSD_PRIME ) + { + pTriv[i] = 0; + uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[0] ); + } + else + { + assert( pObj->nFans == 2 ); + if ( !Kit_DsdLitIsLeaf(ppNtks[i], pObj->pFans[0]) ) + pTriv[i] = 0; + uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[1] ); + } + uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ) & ~uSuppFanin; + } + assert( uSupps[i] <= 0xFFFF ); + uSuppTotal |= uSupps[i]; + } + if ( uSuppTotal == 0 ) + return 0; + + // find one support variable with the highest priority + PrioMin = ABC_INFINITY; + iVarMax = -1; + for ( i = 0; i < 16; i++ ) + if ( uSuppTotal & (1 << i) ) + if ( PrioMin > pPrio[i] ) + { + PrioMin = pPrio[i]; + iVarMax = i; + } + assert( iVarMax != -1 ); + + // select components, which have this variable + nComps = 0; + fOneNonTriv = 0; + uSuppLarge = 0; + for ( i = 0; i < nSize; i++ ) + if ( uSupps[i] & (1<pIfMan) ); + + // iterate over the nodes + if ( p->pPars->fVeryVerbose ) + printf( "Decision: " ); + for ( i = 0; i < nSize; i++ ) + { + if ( pDecision[i] ) + { + if ( p->pPars->fVeryVerbose ) + printf( "%d ", i ); + assert( piLits[i] >= 0 ); + pObj = Kit_DsdNtkObj( ppNtks[i], Kit_DsdLit2Var(piLits[i]) ); + if ( pObj == NULL ) + piLitsNew[i] = -2; + else if ( pObj->Type == KIT_DSD_PRIME ) + piLitsNew[i] = pObj->pFans[0]; + else + piLitsNew[i] = pObj->pFans[1]; + } + else + piLitsNew[i] = piLits[i]; + } + if ( p->pPars->fVeryVerbose ) + printf( "\n" ); + + // call again + pResPrev = Lpk_MapTreeMulti_rec( p, ppNtks, piLitsNew, piCofVar, nCBars, ppLeaves, nLeaves, pPrio ); + + // create new set of nodes + for ( i = 0; i < nSize; i++ ) + { + if ( pDecision[i] ) + pObjsNew[nCBars][i] = Lpk_MapTree_rec( p, ppNtks[i], ppLeaves, piLits[i], pResPrev ); + else if ( piLits[i] == -1 ) + pObjsNew[nCBars][i] = If_ManConst1(p->pIfMan); + else if ( piLits[i] == -2 ) + pObjsNew[nCBars][i] = If_Not( If_ManConst1(p->pIfMan) ); + else + pObjsNew[nCBars][i] = pResPrev; + } + + // create MUX using these outputs + for ( k = nCBars; k > 0; k-- ) + { + nSize /= 2; + for ( i = 0; i < nSize; i++ ) + pObjsNew[k-1][i] = If_ManCreateMux( p->pIfMan, pObjsNew[k][2*i+0], pObjsNew[k][2*i+1], ppLeaves[piCofVar[k-1]] ); + } + assert( nSize == 1 ); + return pObjsNew[0][0]; +} + +/**Function************************************************************* + + Synopsis [Prepares the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * Lpk_MapTreeMulti( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) +{ + static Counter = 0; + If_Obj_t * pResult; + Kit_DsdNtk_t * ppNtks[8] = {0}, * pTemp; + Kit_DsdObj_t * pRoot; + int piCofVar[4], pPrios[16], pFreqs[16] = {0}, piLits[16]; + int i, k, nCBars, nSize, nMemSize; + unsigned * ppCofs[4][8], uSupport; + char pTable[16][16] = {0}; + int fVerbose = p->pPars->fVeryVerbose; + + Counter++; +// printf( "Run %d.\n", Counter ); + + // allocate storage for cofactors + nMemSize = Kit_TruthWordNum(nVars); + ppCofs[0][0] = ALLOC( unsigned, 32 * nMemSize ); + nSize = 0; + for ( i = 0; i < 4; i++ ) + for ( k = 0; k < 8; k++ ) + ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++; + assert( nSize == 32 ); + + // find the best cofactoring variables + nCBars = Kit_DsdCofactoring( pTruth, nVars, piCofVar, p->pPars->nVarsShared, 0 ); +// nCBars = 2; +// piCofVar[0] = 0; +// piCofVar[1] = 1; + + + // copy the function + Kit_TruthCopy( ppCofs[0][0], pTruth, nVars ); + + // decompose w.r.t. these variables + for ( k = 0; k < nCBars; k++ ) + { + nSize = (1 << k); + for ( i = 0; i < nSize; i++ ) + { + Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); + Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); + } + } + nSize = (1 << nCBars); + // compute DSD networks + for ( i = 0; i < nSize; i++ ) + { + ppNtks[i] = Kit_DsdDecompose( ppCofs[nCBars][i], nVars ); + ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); + Kit_DsdNtkFree( pTemp ); + if ( fVerbose ) + { + printf( "Cof%d%d: ", nCBars, i ); + Kit_DsdPrint( stdout, ppNtks[i] ); + } + } + + // compute variable frequences + for ( i = 0; i < nSize; i++ ) + { + uSupport = Kit_TruthSupport( ppCofs[nCBars][i], nVars ); + for ( k = 0; k < nVars; k++ ) + if ( uSupport & (1<pSupps[0] <= 0xFFFF ); + // undec nodes should be rotated in such a way that the first input has as many shared inputs as possible + Kit_DsdRotate( ppNtks[i], pFreqs ); + // print the resulting networks + if ( fVerbose ) + { + printf( "Cof%d%d: ", nCBars, i ); + Kit_DsdPrint( stdout, ppNtks[i] ); + } + } + + for ( i = 0; i < nSize; i++ ) + { + // collect the roots + pRoot = Kit_DsdNtkRoot(ppNtks[i]); + if ( pRoot->Type == KIT_DSD_CONST1 ) + piLits[i] = Kit_DsdLitIsCompl(ppNtks[i]->Root)? -2: -1; + else if ( pRoot->Type == KIT_DSD_VAR ) + piLits[i] = Kit_DsdLitNotCond( pRoot->pFans[0], Kit_DsdLitIsCompl(ppNtks[i]->Root) ); + else + piLits[i] = ppNtks[i]->Root; + } + + + // recursively construct AIG for mapping + p->fCofactoring = 1; + pResult = Lpk_MapTreeMulti_rec( p, ppNtks, piLits, piCofVar, nCBars, ppLeaves, nVars, pPrios ); + p->fCofactoring = 0; + + if ( fVerbose ) + printf( "\n" ); + + // verify the transformations + nSize = (1 << nCBars); + for ( i = 0; i < nSize; i++ ) + Kit_DsdTruth( ppNtks[i], ppCofs[nCBars][i] ); + // mux the truth tables + for ( k = nCBars-1; k >= 0; k-- ) + { + nSize = (1 << k); + for ( i = 0; i < nSize; i++ ) + Kit_TruthMuxVar( ppCofs[k][i], ppCofs[k+1][2*i+0], ppCofs[k+1][2*i+1], nVars, piCofVar[k] ); + } + if ( !Extra_TruthIsEqual( pTruth, ppCofs[0][0], nVars ) ) + printf( "Verification failed.\n" ); + + + // free the networks + for ( i = 0; i < 8; i++ ) + if ( ppNtks[i] ) + Kit_DsdNtkFree( ppNtks[i] ); + free( ppCofs[0][0] ); + + return pResult; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/lpkMux.c b/abc70930/src/opt/lpk/lpkMux.c new file mode 100644 index 00000000..ed046ad7 --- /dev/null +++ b/abc70930/src/opt/lpk/lpkMux.c @@ -0,0 +1,247 @@ +/**CFile**************************************************************** + + FileName [lpkMux.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpkMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "lpkInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find the best cofactoring variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lpk_MapTreeBestCofVar( Lpk_Man_t * p, unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 ) +{ + int i, iBestVar, nSuppSizeCur0, nSuppSizeCur1, nSuppSizeCur, nSuppSizeMin; + // iterate through variables + iBestVar = -1; + nSuppSizeMin = KIT_INFINITY; + for ( i = 0; i < nVars; i++ ) + { + // cofactor the functiona and get support sizes + Kit_TruthCofactor0New( pCof0, pTruth, nVars, i ); + Kit_TruthCofactor1New( pCof1, pTruth, nVars, i ); + nSuppSizeCur0 = Kit_TruthSupportSize( pCof0, nVars ); + nSuppSizeCur1 = Kit_TruthSupportSize( pCof1, nVars ); + nSuppSizeCur = nSuppSizeCur0 + nSuppSizeCur1; + // skip cofactoring that goes above the limit + if ( nSuppSizeCur0 > p->pPars->nLutSize || nSuppSizeCur1 > p->pPars->nLutSize ) + continue; + // compare this variable with other variables + if ( nSuppSizeMin > nSuppSizeCur ) + { + nSuppSizeMin = nSuppSizeCur; + iBestVar = i; + } + } + // cofactor w.r.t. this variable + if ( iBestVar != -1 ) + { + Kit_TruthCofactor0New( pCof0, pTruth, nVars, iBestVar ); + Kit_TruthCofactor1New( pCof1, pTruth, nVars, iBestVar ); + } + return iBestVar; +} + +/**Function************************************************************* + + Synopsis [Maps the function by the best cofactoring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * Lpk_MapTreeMux_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) +{ + unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 ); + unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 ); + If_Obj_t * pObj0, * pObj1; + Kit_DsdNtk_t * ppNtks[2]; + int iBestVar; + assert( nVars > 3 ); + p->fCalledOnce = 1; + // cofactor w.r.t. the best variable + iBestVar = Lpk_MapTreeBestCofVar( p, pTruth, nVars, pCof0, pCof1 ); + if ( iBestVar == -1 ) + return NULL; + // decompose the functions + ppNtks[0] = Kit_DsdDecompose( pCof0, nVars ); + ppNtks[1] = Kit_DsdDecompose( pCof1, nVars ); + if ( p->pPars->fVeryVerbose ) + { + printf( "Cofactoring w.r.t. var %c (%d -> %d+%d supp vars):\n", + 'a'+iBestVar, nVars, Kit_TruthSupportSize(pCof0, nVars), Kit_TruthSupportSize(pCof1, nVars) ); + Kit_DsdPrintExpanded( ppNtks[0] ); + Kit_DsdPrintExpanded( ppNtks[1] ); + } + // map the DSD structures + pObj0 = Lpk_MapTree_rec( p, ppNtks[0], ppLeaves, ppNtks[0]->Root, NULL ); + pObj1 = Lpk_MapTree_rec( p, ppNtks[1], ppLeaves, ppNtks[1]->Root, NULL ); + Kit_DsdNtkFree( ppNtks[0] ); + Kit_DsdNtkFree( ppNtks[1] ); + return If_ManCreateMux( p->pIfMan, pObj0, pObj1, ppLeaves[iBestVar] ); +} + + + +/**Function************************************************************* + + Synopsis [Implements support-reducing decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +If_Obj_t * Lpk_MapSuppRedDec_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) +{ + Kit_DsdNtk_t * pNtkDec, * pNtkComp, * ppNtks[2], * pTemp; + If_Obj_t * pObjNew; + unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 ); + unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 ); + unsigned * pDec0 = Vec_PtrEntry( p->vTtNodes, 2 ); + unsigned * pDec1 = Vec_PtrEntry( p->vTtNodes, 3 ); + unsigned * pDec = Vec_PtrEntry( p->vTtNodes, 4 ); + unsigned * pCo00 = Vec_PtrEntry( p->vTtNodes, 5 ); + unsigned * pCo01 = Vec_PtrEntry( p->vTtNodes, 6 ); + unsigned * pCo10 = Vec_PtrEntry( p->vTtNodes, 7 ); + unsigned * pCo11 = Vec_PtrEntry( p->vTtNodes, 8 ); + unsigned * pCo0 = Vec_PtrEntry( p->vTtNodes, 9 ); + unsigned * pCo1 = Vec_PtrEntry( p->vTtNodes, 10 ); + unsigned * pCo = Vec_PtrEntry( p->vTtNodes, 11 ); + int TrueMint0, TrueMint1, FalseMint0, FalseMint1; + int uSubsets, uSubset0, uSubset1, iVar, iVarReused, i; + + // determine if supp-red decomposition exists + uSubsets = Lpk_MapSuppRedDecSelect( p, pTruth, nVars, &iVar, &iVarReused ); + if ( uSubsets == 0 ) + return NULL; + p->nCalledSRed++; + + // get the cofactors + Kit_TruthCofactor0New( pCof0, pTruth, nVars, iVar ); + Kit_TruthCofactor1New( pCof1, pTruth, nVars, iVar ); + + // get the bound sets + uSubset0 = uSubsets & 0xFFFF; + uSubset1 = uSubsets >> 16; + + // compute the decomposed functions + ppNtks[0] = Kit_DsdDecompose( pCof0, nVars ); + ppNtks[1] = Kit_DsdDecompose( pCof1, nVars ); + ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp ); + ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] ); Kit_DsdNtkFree( pTemp ); + Kit_DsdTruthPartial( p->pDsdMan, ppNtks[0], pDec0, uSubset0 ); + Kit_DsdTruthPartial( p->pDsdMan, ppNtks[1], pDec1, uSubset1 ); +// Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[0], uSubset0, iVarReused, pCo0, pDec0 ); +// Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[1], uSubset1, iVarReused, pCo1, pDec1 ); + Kit_DsdNtkFree( ppNtks[0] ); + Kit_DsdNtkFree( ppNtks[1] ); +//Kit_DsdPrintFromTruth( pDec0, nVars ); +//Kit_DsdPrintFromTruth( pDec1, nVars ); + // get the decomposed function + Kit_TruthMuxVar( pDec, pDec0, pDec1, nVars, iVar ); + + // find any true assignments of the decomposed functions + TrueMint0 = Kit_TruthFindFirstBit( pDec0, nVars ); + TrueMint1 = Kit_TruthFindFirstBit( pDec1, nVars ); + assert( TrueMint0 >= 0 && TrueMint1 >= 0 ); + // find any false assignments of the decomposed functions + FalseMint0 = Kit_TruthFindFirstZero( pDec0, nVars ); + FalseMint1 = Kit_TruthFindFirstZero( pDec1, nVars ); + assert( FalseMint0 >= 0 && FalseMint1 >= 0 ); + + // cofactor the cofactors according to these minterms + Kit_TruthCopy( pCo00, pCof0, nVars ); + Kit_TruthCopy( pCo01, pCof0, nVars ); + for ( i = 0; i < nVars; i++ ) + if ( uSubset0 & (1 << i) ) + { + if ( FalseMint0 & (1 << i) ) + Kit_TruthCofactor1( pCo00, nVars, i ); + else + Kit_TruthCofactor0( pCo00, nVars, i ); + if ( TrueMint0 & (1 << i) ) + Kit_TruthCofactor1( pCo01, nVars, i ); + else + Kit_TruthCofactor0( pCo01, nVars, i ); + } + Kit_TruthCopy( pCo10, pCof1, nVars ); + Kit_TruthCopy( pCo11, pCof1, nVars ); + for ( i = 0; i < nVars; i++ ) + if ( uSubset1 & (1 << i) ) + { + if ( FalseMint1 & (1 << i) ) + Kit_TruthCofactor1( pCo10, nVars, i ); + else + Kit_TruthCofactor0( pCo10, nVars, i ); + if ( TrueMint1 & (1 << i) ) + Kit_TruthCofactor1( pCo11, nVars, i ); + else + Kit_TruthCofactor0( pCo11, nVars, i ); + } + + // derive the functions by composing them with the new variable (iVarReused) + Kit_TruthMuxVar( pCo0, pCo00, pCo01, nVars, iVarReused ); + Kit_TruthMuxVar( pCo1, pCo10, pCo11, nVars, iVarReused ); +//Kit_DsdPrintFromTruth( pCo0, nVars ); +//Kit_DsdPrintFromTruth( pCo1, nVars ); + + // derive the composition function + Kit_TruthMuxVar( pCo , pCo0 , pCo1 , nVars, iVar ); + + // process the decomposed function + pNtkDec = Kit_DsdDecompose( pDec, nVars ); + pNtkComp = Kit_DsdDecompose( pCo, nVars ); +//Kit_DsdPrint( stdout, pNtkDec ); +//Kit_DsdPrint( stdout, pNtkComp ); +//printf( "cofactored variable %c\n", 'a' + iVar ); +//printf( "reused variable %c\n", 'a' + iVarReused ); + + ppLeaves[iVarReused] = Lpk_MapTree_rec( p, pNtkDec, ppLeaves, pNtkDec->Root, NULL ); + pObjNew = Lpk_MapTree_rec( p, pNtkComp, ppLeaves, pNtkComp->Root, NULL ); + + Kit_DsdNtkFree( pNtkDec ); + Kit_DsdNtkFree( pNtkComp ); + return pObjNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/lpkSets.c b/abc70930/src/opt/lpk/lpkSets.c new file mode 100644 index 00000000..90e46863 --- /dev/null +++ b/abc70930/src/opt/lpk/lpkSets.c @@ -0,0 +1,440 @@ +/**CFile**************************************************************** + + FileName [lpkSets.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpkSets.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "lpkInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Lpk_Set_t_ Lpk_Set_t; +struct Lpk_Set_t_ +{ + char iVar; // the cofactoring variable + char Over; // the overlap in supports + char SRed; // the support reduction + char Size; // the size of the boundset + unsigned uSubset0; // the first subset (with removed) + unsigned uSubset1; // the second subset (with removed) +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Recursively computes decomposable subsets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Lpk_ComputeSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets ) +{ + unsigned i, iLitFanin, uSupport, uSuppCur; + Kit_DsdObj_t * pObj; + // consider the case of simple gate + pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); + if ( pObj == NULL ) + return (1 << Kit_DsdLit2Var(iLit)); + if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) + { + unsigned uSupps[16], Limit, s; + uSupport = 0; + Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) + { + uSupps[i] = Lpk_ComputeSets_rec( p, iLitFanin, vSets ); + uSupport |= uSupps[i]; + } + // create all subsets, except empty and full + Limit = (1 << pObj->nFans) - 1; + for ( s = 1; s < Limit; s++ ) + { + uSuppCur = 0; + for ( i = 0; i < pObj->nFans; i++ ) + if ( s & (1 << i) ) + uSuppCur |= uSupps[i]; + Vec_IntPush( vSets, uSuppCur ); + } + return uSupport; + } + assert( pObj->Type == KIT_DSD_PRIME ); + // get the cumulative support of all fanins + uSupport = 0; + Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) + { + uSuppCur = Lpk_ComputeSets_rec( p, iLitFanin, vSets ); + uSupport |= uSuppCur; + Vec_IntPush( vSets, uSuppCur ); + } + return uSupport; +} + +/**Function************************************************************* + + Synopsis [Computes the set of subsets of decomposable variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Lpk_ComputeSets( Kit_DsdNtk_t * p, Vec_Int_t * vSets ) +{ + unsigned uSupport, Entry; + int Number, i; + assert( p->nVars <= 16 ); + Vec_IntClear( vSets ); + Vec_IntPush( vSets, 0 ); + if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) + return 0; + if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) + { + uSupport = ( 1 << Kit_DsdLit2Var(Kit_DsdNtkRoot(p)->pFans[0]) ); + Vec_IntPush( vSets, uSupport ); + return uSupport; + } + uSupport = Lpk_ComputeSets_rec( p, p->Root, vSets ); + assert( (uSupport & 0xFFFF0000) == 0 ); + Vec_IntPush( vSets, uSupport ); + // set the remaining variables + Vec_IntForEachEntry( vSets, Number, i ) + { + Entry = Number; + Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) ); + } + return uSupport; +} + +/**Function************************************************************* + + Synopsis [Prints the sets of subsets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Lpk_PrintSetOne( int uSupport ) +{ + unsigned k; + for ( k = 0; k < 16; k++ ) + if ( uSupport & (1<> 16) ); + // get the support reduction + nSuppRed = nSuppSize - 1 - nSuppOver; + // only consider support-reducing subsets + if ( nSuppRed <= 0 ) + continue; + // check if this support is already used + if ( TravId[uSupp] < nTravId ) + { + Used[nUsed++] = uSupp; + + TravId[uSupp] = nTravId; + SRed[uSupp] = nSuppRed; + Over[uSupp] = nSuppOver; + Parents[uSupp] = (k << 16) | i; + } + else if ( TravId[uSupp] == nTravId && SRed[uSupp] < nSuppRed ) + { + TravId[uSupp] = nTravId; + SRed[uSupp] = nSuppRed; + Over[uSupp] = nSuppOver; + Parents[uSupp] = (k << 16) | i; + } + } + + // find the minimum overlap + nMinOver = 1000; + for ( s = 0; s < nUsed; s++ ) + if ( nMinOver > Over[Used[s]] ) + nMinOver = Over[Used[s]]; + + + // collect the accumulated ones + for ( s = 0; s < nUsed; s++ ) + if ( Over[Used[s]] == nMinOver ) + { + // save the entry + if ( *pSize == nSizeLimit ) + return; + pEntry = pStore + (*pSize)++; + + i = Parents[Used[s]] & 0xFFFF; + k = Parents[Used[s]] >> 16; + + pEntry->uSubset0 = Vec_IntEntry(vSets0, i); + pEntry->uSubset1 = Vec_IntEntry(vSets1, k); + Entry = pEntry->uSubset0 | pEntry->uSubset1; + + // record the cofactoring variable + pEntry->iVar = iCofVar; + // set the bound set size + pEntry->Size = Kit_WordCountOnes( Entry & 0xFFFF ); + // get the number of overlapping vars + pEntry->Over = Kit_WordCountOnes( Entry & (Entry >> 16) ); + // get the support reduction + pEntry->SRed = pEntry->Size - 1 - pEntry->Over; + assert( pEntry->SRed > 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Prints one set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lpk_MapSuppPrintSet( Lpk_Set_t * pSet, int i ) +{ + unsigned Entry; + Entry = pSet->uSubset0 | pSet->uSubset1; + printf( "%2d : ", i ); + printf( "Var = %c ", 'a' + pSet->iVar ); + printf( "Size = %2d ", pSet->Size ); + printf( "Over = %2d ", pSet->Over ); + printf( "SRed = %2d ", pSet->SRed ); + Lpk_PrintSetOne( Entry ); + printf( " " ); + Lpk_PrintSetOne( Entry >> 16 ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Evaluates the cofactors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Lpk_MapSuppRedDecSelect( Lpk_Man_t * p, unsigned * pTruth, int nVars, int * piVar, int * piVarReused ) +{ + static int nStoreSize = 256; + static Lpk_Set_t pStore[256], * pSet, * pSetBest; + Kit_DsdNtk_t * ppNtks[2], * pTemp; + Vec_Int_t * vSets0 = p->vSets[0]; + Vec_Int_t * vSets1 = p->vSets[1]; + unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 ); + unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 ); + int nSets, i, SizeMax;//, SRedMax; + unsigned Entry; + int fVerbose = p->pPars->fVeryVerbose; +// int fVerbose = 0; + + // collect decomposable subsets for each pair of cofactors + if ( fVerbose ) + { + printf( "\nExploring support-reducing bound-sets of function:\n" ); + Kit_DsdPrintFromTruth( pTruth, nVars ); + } + nSets = 0; + for ( i = 0; i < nVars; i++ ) + { + if ( fVerbose ) + printf( "Evaluating variable %c:\n", 'a'+i ); + // evaluate the cofactor pair + Kit_TruthCofactor0New( pCof0, pTruth, nVars, i ); + Kit_TruthCofactor1New( pCof1, pTruth, nVars, i ); + // decompose and expand + ppNtks[0] = Kit_DsdDecompose( pCof0, nVars ); + ppNtks[1] = Kit_DsdDecompose( pCof1, nVars ); + ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp ); + ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] ); Kit_DsdNtkFree( pTemp ); + if ( fVerbose ) + Kit_DsdPrint( stdout, ppNtks[0] ); + if ( fVerbose ) + Kit_DsdPrint( stdout, ppNtks[1] ); + // compute subsets + Lpk_ComputeSets( ppNtks[0], vSets0 ); + Lpk_ComputeSets( ppNtks[1], vSets1 ); + // print subsets + if ( fVerbose ) + Lpk_PrintSets( vSets0 ); + if ( fVerbose ) + Lpk_PrintSets( vSets1 ); + // free the networks + Kit_DsdNtkFree( ppNtks[0] ); + Kit_DsdNtkFree( ppNtks[1] ); + // evaluate the pair + Lpk_ComposeSets( vSets0, vSets1, nVars, i, pStore, &nSets, nStoreSize ); + } + + // print the results + if ( fVerbose ) + printf( "\n" ); + if ( fVerbose ) + for ( i = 0; i < nSets; i++ ) + Lpk_MapSuppPrintSet( pStore + i, i ); + + // choose the best subset + SizeMax = 0; + pSetBest = NULL; + for ( i = 0; i < nSets; i++ ) + { + pSet = pStore + i; + if ( pSet->Size > p->pPars->nLutSize - 1 ) + continue; + if ( SizeMax < pSet->Size ) + { + pSetBest = pSet; + SizeMax = pSet->Size; + } + } +/* + // if the best is not choosen, select the one with largest reduction + SRedMax = 0; + if ( pSetBest == NULL ) + { + for ( i = 0; i < nSets; i++ ) + { + pSet = pStore + i; + if ( SRedMax < pSet->SRed ) + { + pSetBest = pSet; + SRedMax = pSet->SRed; + } + } + } +*/ + if ( pSetBest == NULL ) + { + if ( fVerbose ) + printf( "Could not select a subset.\n" ); + return 0; + } + else + { + if ( fVerbose ) + printf( "Selected the following subset:\n" ); + if ( fVerbose ) + Lpk_MapSuppPrintSet( pSetBest, pSetBest - pStore ); + } + + // prepare the return result + // get the remaining variables + Entry = ((pSetBest->uSubset0 >> 16) | (pSetBest->uSubset1 >> 16)); + // get the variables to be removed + Entry = Kit_BitMask(nVars) & ~(1<iVar) & ~Entry; + // make sure there are some - otherwise it is not supp-red + assert( Entry ); + // remember the first such variable + *piVarReused = Kit_WordFindFirstBit( Entry ); + *piVar = pSetBest->iVar; + return (pSetBest->uSubset1 << 16) | (pSetBest->uSubset0 & 0xFFFF); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/lpk_.c b/abc70930/src/opt/lpk/lpk_.c new file mode 100644 index 00000000..d8555e08 --- /dev/null +++ b/abc70930/src/opt/lpk/lpk_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [lpk_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Fast Boolean matching for LUT structures.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: lpk_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "lpkInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/lpk/module.make b/abc70930/src/opt/lpk/module.make new file mode 100644 index 00000000..26a54894 --- /dev/null +++ b/abc70930/src/opt/lpk/module.make @@ -0,0 +1,11 @@ +SRC += src/opt/lpk/lpkCore.c \ + src/opt/lpk/lpkAbcDec.c \ + src/opt/lpk/lpkAbcMux.c \ + src/opt/lpk/lpkAbcDsd.c \ + src/opt/lpk/lpkAbcUtil.c \ + src/opt/lpk/lpkCut.c \ + src/opt/lpk/lpkMan.c \ + src/opt/lpk/lpkMap.c \ + src/opt/lpk/lpkMulti.c \ + src/opt/lpk/lpkMux.c \ + src/opt/lpk/lpkSets.c diff --git a/abc70930/src/opt/res/module.make b/abc70930/src/opt/res/module.make new file mode 100644 index 00000000..52d8a315 --- /dev/null +++ b/abc70930/src/opt/res/module.make @@ -0,0 +1,7 @@ +SRC += src/opt/res/resCore.c \ + src/opt/res/resDivs.c \ + src/opt/res/resFilter.c \ + src/opt/res/resSat.c \ + src/opt/res/resSim.c \ + src/opt/res/resStrash.c \ + src/opt/res/resWin.c diff --git a/abc70930/src/opt/res/res.h b/abc70930/src/opt/res/res.h new file mode 100644 index 00000000..3c3431bf --- /dev/null +++ b/abc70930/src/opt/res/res.h @@ -0,0 +1,75 @@ +/**CFile**************************************************************** + + FileName [res.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resynthesis package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: res.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __RES_H__ +#define __RES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Res_Par_t_ Res_Par_t; +struct Res_Par_t_ +{ + // general parameters + int nWindow; // window size + int nGrowthLevel; // the maximum allowed growth in level after one iteration of resynthesis + int nSimWords; // the number of simulation words + int nCands; // the number of candidates to try + int fArea; // performs optimization for area + int fDelay; // performs optimization for delay + int fVerbose; // enable basic stats + int fVeryVerbose; // enable detailed stats +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== resCore.c ==========================================================*/ +extern int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars ); + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/res/resCore.c b/abc70930/src/opt/res/resCore.c new file mode 100644 index 00000000..27e9b3ea --- /dev/null +++ b/abc70930/src/opt/res/resCore.c @@ -0,0 +1,415 @@ +/**CFile**************************************************************** + + FileName [resCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resynthesis package.] + + Synopsis [Top-level resynthesis procedure.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: resCore.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "resInt.h" +#include "kit.h" +#include "satStore.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Res_Man_t_ Res_Man_t; +struct Res_Man_t_ +{ + // general parameters + Res_Par_t * pPars; + // specialized manager + Res_Win_t * pWin; // windowing manager + Abc_Ntk_t * pAig; // the strashed window + Res_Sim_t * pSim; // simulation manager + Sto_Man_t * pCnf; // the CNF of the SAT problem + Int_Man_t * pMan; // interpolation manager; + Vec_Int_t * vMem; // memory for intermediate SOPs + Vec_Vec_t * vResubs; // resubstitution candidates of the AIG + Vec_Vec_t * vResubsW; // resubstitution candidates of the window + Vec_Vec_t * vLevels; // levelized structure for updating + // statistics + int nWins; // the number of windows tried + int nWinNodes; // the total number of window nodes + int nDivNodes; // the total number of divisors + int nWinsTriv; // the total number of trivial windows + int nWinsUsed; // the total number of useful windows (with at least one candidate) + int nConstsUsed; // the total number of constant nodes under ODC + int nCandSets; // the total number of candidates + int nProvedSets; // the total number of proved groups + int nSimEmpty; // the empty simulation info + int nTotalNets; // the total number of nets + int nTotalNodes; // the total number of nodess + int nTotalNets2; // the total number of nets + int nTotalNodes2; // the total number of nodess + // runtime + int timeWin; // windowing + int timeDiv; // divisors + int timeAig; // strashing + int timeSim; // simulation + int timeCand; // resubstitution candidates + int timeSatTotal; // SAT solving total + int timeSatSat; // SAT solving (sat calls) + int timeSatUnsat; // SAT solving (unsat calls) + int timeSatSim; // SAT solving (simulation) + int timeInt; // interpolation + int timeUpd; // updating + int timeTotal; // total runtime +}; + +extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); + +extern int s_ResynTime; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocate resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Res_Man_t * Res_ManAlloc( Res_Par_t * pPars ) +{ + Res_Man_t * p; + p = ALLOC( Res_Man_t, 1 ); + memset( p, 0, sizeof(Res_Man_t) ); + assert( pPars->nWindow > 0 && pPars->nWindow < 100 ); + assert( pPars->nCands > 0 && pPars->nCands < 100 ); + p->pPars = pPars; + p->pWin = Res_WinAlloc(); + p->pSim = Res_SimAlloc( pPars->nSimWords ); + p->pMan = Int_ManAlloc( 512 ); + p->vMem = Vec_IntAlloc( 0 ); + p->vResubs = Vec_VecStart( pPars->nCands ); + p->vResubsW = Vec_VecStart( pPars->nCands ); + p->vLevels = Vec_VecStart( 32 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocate resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_ManFree( Res_Man_t * p ) +{ + if ( p->pPars->fVerbose ) + { + printf( "Reduction in nodes = %5d. (%.2f %%) ", + p->nTotalNodes-p->nTotalNodes2, + 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes ); + printf( "Reduction in edges = %5d. (%.2f %%) ", + p->nTotalNets-p->nTotalNets2, + 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets ); + printf( "\n" ); + + printf( "Winds = %d. ", p->nWins ); + printf( "Nodes = %d. (Ave = %5.1f) ", p->nWinNodes, 1.0*p->nWinNodes/p->nWins ); + printf( "Divs = %d. (Ave = %5.1f) ", p->nDivNodes, 1.0*p->nDivNodes/p->nWins ); + printf( "\n" ); + printf( "WinsTriv = %d. ", p->nWinsTriv ); + printf( "SimsEmpt = %d. ", p->nSimEmpty ); + printf( "Const = %d. ", p->nConstsUsed ); + printf( "WindUsed = %d. ", p->nWinsUsed ); + printf( "Cands = %d. ", p->nCandSets ); + printf( "Proved = %d.", p->nProvedSets ); + printf( "\n" ); + + PRTP( "Windowing ", p->timeWin, p->timeTotal ); + PRTP( "Divisors ", p->timeDiv, p->timeTotal ); + PRTP( "Strashing ", p->timeAig, p->timeTotal ); + PRTP( "Simulation ", p->timeSim, p->timeTotal ); + PRTP( "Candidates ", p->timeCand, p->timeTotal ); + PRTP( "SAT solver ", p->timeSatTotal, p->timeTotal ); + PRTP( " sat ", p->timeSatSat, p->timeTotal ); + PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); + PRTP( " simul ", p->timeSatSim, p->timeTotal ); + PRTP( "Interpol ", p->timeInt, p->timeTotal ); + PRTP( "Undating ", p->timeUpd, p->timeTotal ); + PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + } + Res_WinFree( p->pWin ); + if ( p->pAig ) Abc_NtkDelete( p->pAig ); + Res_SimFree( p->pSim ); + if ( p->pCnf ) Sto_ManFree( p->pCnf ); + Int_ManFree( p->pMan ); + Vec_IntFree( p->vMem ); + Vec_VecFree( p->vResubs ); + Vec_VecFree( p->vResubsW ); + Vec_VecFree( p->vLevels ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels ) +{ + Abc_Obj_t * pObjNew, * pFanin; + int k; + // create the new node + pObjNew = Abc_NtkCreateNode( pObj->pNtk ); + pObjNew->pData = pFunc; + Vec_PtrForEachEntry( vFanins, pFanin, k ) + Abc_ObjAddFanin( pObjNew, pFanin ); + // replace the old node by the new node + // update the level of the node + Abc_NtkUpdate( pObj, pObjNew, vLevels ); +} + +/**Function************************************************************* + + Synopsis [Entrace into the resynthesis package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars ) +{ + ProgressBar * pProgress; + Res_Man_t * p; + Abc_Obj_t * pObj; + Hop_Obj_t * pFunc; + Kit_Graph_t * pGraph; + Vec_Ptr_t * vFanins; + unsigned * puTruth; + int i, k, RetValue, nNodesOld, nFanins, nFaninsMax; + int clk, clkTotal = clock(); + + // start the manager + p = Res_ManAlloc( pPars ); + p->nTotalNets = Abc_NtkGetTotalFanins(pNtk); + p->nTotalNodes = Abc_NtkNodeNum(pNtk); + nFaninsMax = Abc_NtkGetFaninMax(pNtk); + + // perform the network sweep + Abc_NtkSweep( pNtk, 0 ); + + // convert into the AIG + if ( !Abc_NtkToAig(pNtk) ) + { + fprintf( stdout, "Converting to BDD has failed.\n" ); + Res_ManFree( p ); + return 0; + } + assert( Abc_NtkHasAig(pNtk) ); + + // set the number of levels + Abc_NtkLevel( pNtk ); + Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); + + // try resynthesizing nodes in the topological order + nNodesOld = Abc_NtkObjNumMax(pNtk); + pProgress = Extra_ProgressBarStart( stdout, nNodesOld ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + Extra_ProgressBarUpdate( pProgress, i, NULL ); + if ( !Abc_ObjIsNode(pObj) ) + continue; + if ( pObj->Id > nNodesOld ) + break; + + // create the window for this node +clk = clock(); + RetValue = Res_WinCompute( pObj, p->pPars->nWindow/10, p->pPars->nWindow%10, p->pWin ); +p->timeWin += clock() - clk; + if ( !RetValue ) + continue; + p->nWinsTriv += Res_WinIsTrivial( p->pWin ); + + if ( p->pPars->fVeryVerbose ) + { + printf( "%5d (lev=%2d) : ", pObj->Id, pObj->Level ); + printf( "Win = %3d/%3d/%4d/%3d ", + Vec_PtrSize(p->pWin->vLeaves), + Vec_PtrSize(p->pWin->vBranches), + Vec_PtrSize(p->pWin->vNodes), + Vec_PtrSize(p->pWin->vRoots) ); + } + + // collect the divisors +clk = clock(); + Res_WinDivisors( p->pWin, Abc_ObjRequiredLevel(pObj) - 1 ); +p->timeDiv += clock() - clk; + + p->nWins++; + p->nWinNodes += Vec_PtrSize(p->pWin->vNodes); + p->nDivNodes += Vec_PtrSize( p->pWin->vDivs); + + if ( p->pPars->fVeryVerbose ) + { + printf( "D = %3d ", Vec_PtrSize(p->pWin->vDivs) ); + printf( "D+ = %3d ", p->pWin->nDivsPlus ); + } + + // create the AIG for the window +clk = clock(); + if ( p->pAig ) Abc_NtkDelete( p->pAig ); + p->pAig = Res_WndStrash( p->pWin ); +p->timeAig += clock() - clk; + + if ( p->pPars->fVeryVerbose ) + { + printf( "AIG = %4d ", Abc_NtkNodeNum(p->pAig) ); + printf( "\n" ); + } + + // prepare simulation info +clk = clock(); + RetValue = Res_SimPrepare( p->pSim, p->pAig, Vec_PtrSize(p->pWin->vLeaves), 0 ); //p->pPars->fVerbose ); +p->timeSim += clock() - clk; + if ( !RetValue ) + { + p->nSimEmpty++; + continue; + } + + // consider the case of constant node + if ( p->pSim->fConst0 || p->pSim->fConst1 ) + { + p->nConstsUsed++; + + pFunc = p->pSim->fConst1? Hop_ManConst1(pNtk->pManFunc) : Hop_ManConst0(pNtk->pManFunc); + vFanins = Vec_VecEntry( p->vResubsW, 0 ); + Vec_PtrClear( vFanins ); + Res_UpdateNetwork( pObj, vFanins, pFunc, p->vLevels ); + continue; + } + +// printf( " " ); + + // find resub candidates for the node +clk = clock(); + if ( p->pPars->fArea ) + RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 1 ); + else + RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 0 ); +p->timeCand += clock() - clk; + p->nCandSets += RetValue; + if ( RetValue == 0 ) + continue; + +// printf( "%d(%d) ", Vec_PtrSize(p->pWin->vDivs), RetValue ); + + p->nWinsUsed++; + + // iterate through candidate resubstitutions + Vec_VecForEachLevel( p->vResubs, vFanins, k ) + { + if ( Vec_PtrSize(vFanins) == 0 ) + break; + + // solve the SAT problem and get clauses +clk = clock(); + if ( p->pCnf ) Sto_ManFree( p->pCnf ); + p->pCnf = Res_SatProveUnsat( p->pAig, vFanins ); + if ( p->pCnf == NULL ) + { +p->timeSatSat += clock() - clk; +// printf( " Sat\n" ); +// printf( "-" ); + continue; + } +p->timeSatUnsat += clock() - clk; +// printf( "+" ); + + p->nProvedSets++; +// printf( " Unsat\n" ); +// continue; +// printf( "Proved %d.\n", k ); + + // write it into a file +// Sto_ManDumpClauses( p->pCnf, "trace.cnf" ); + + // interpolate the problem if it was UNSAT +clk = clock(); + nFanins = Int_ManInterpolate( p->pMan, p->pCnf, 0, &puTruth ); +p->timeInt += clock() - clk; + if ( nFanins != Vec_PtrSize(vFanins) - 2 ) + continue; + assert( puTruth ); +// Extra_PrintBinary( stdout, puTruth, 1 << nFanins ); printf( "\n" ); + + // transform interpolant into the AIG + pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem ); + + // derive the AIG for the decomposition tree + pFunc = Kit_GraphToHop( pNtk->pManFunc, pGraph ); + Kit_GraphFree( pGraph ); + + // update the network +clk = clock(); + Res_UpdateNetwork( pObj, Vec_VecEntry(p->vResubsW, k), pFunc, p->vLevels ); +p->timeUpd += clock() - clk; + break; + } +// printf( "\n" ); + } + Extra_ProgressBarStop( pProgress ); + Abc_NtkStopReverseLevels( pNtk ); + +p->timeSatSim += p->pSim->timeSat; +p->timeSatTotal = p->timeSatSat + p->timeSatUnsat + p->timeSatSim; + + p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk); + p->nTotalNodes2 = Abc_NtkNodeNum(pNtk); + + // quit resubstitution manager +p->timeTotal = clock() - clkTotal; + Res_ManFree( p ); + +s_ResynTime += clock() - clkTotal; + // check the resulting network + if ( !Abc_NtkCheck( pNtk ) ) + { + fprintf( stdout, "Abc_NtkResynthesize(): Network check has failed.\n" ); + return 0; + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/res/resDivs.c b/abc70930/src/opt/res/resDivs.c new file mode 100644 index 00000000..cc75b90f --- /dev/null +++ b/abc70930/src/opt/res/resDivs.c @@ -0,0 +1,285 @@ +/**CFile**************************************************************** + + FileName [resDivs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resynthesis package.] + + Synopsis [Collect divisors for the given window.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: resDivs.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "resInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Res_WinMarkTfi( Res_Win_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Adds candidate divisors of the node to its window.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_WinDivisors( Res_Win_t * p, int nLevDivMax ) +{ + Abc_Obj_t * pObj, * pFanout, * pFanin; + int k, f, m; + + // set the maximum level of the divisors + p->nLevDivMax = nLevDivMax; + + // mark the TFI with the current trav ID + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Res_WinMarkTfi( p ); + + // mark with the current trav ID those nodes that should not be divisors: + // (1) the node and its TFO + // (2) the MFFC of the node + // (3) the node's fanins (these are treated as a special case) + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Res_WinSweepLeafTfo_rec( p->pNode, p->nLevDivMax ); + Res_WinVisitMffc( p->pNode ); + Abc_ObjForEachFanin( p->pNode, pObj, k ) + Abc_NodeSetTravIdCurrent( pObj ); + + // at this point the nodes are marked with two trav IDs: + // nodes to be collected as divisors are marked with previous trav ID + // nodes to be avoided as divisors are marked with current trav ID + + // start collecting the divisors + Vec_PtrClear( p->vDivs ); + Vec_PtrForEachEntry( p->vLeaves, pObj, k ) + { + assert( (int)pObj->Level >= p->nLevLeafMin ); + if ( !Abc_NodeIsTravIdPrevious(pObj) ) + continue; + if ( (int)pObj->Level > p->nLevDivMax ) + continue; + Vec_PtrPush( p->vDivs, pObj ); + } + // add the internal nodes to the data structure + Vec_PtrForEachEntry( p->vNodes, pObj, k ) + { + if ( !Abc_NodeIsTravIdPrevious(pObj) ) + continue; + if ( (int)pObj->Level > p->nLevDivMax ) + continue; + Vec_PtrPush( p->vDivs, pObj ); + } + + // explore the fanouts of already collected divisors + p->nDivsPlus = 0; + Vec_PtrForEachEntry( p->vDivs, pObj, k ) + { + // consider fanouts of this node + Abc_ObjForEachFanout( pObj, pFanout, f ) + { + // stop if there are too many fanouts + if ( f > 20 ) + break; + // skip nodes that are already added + if ( Abc_NodeIsTravIdPrevious(pFanout) ) + continue; + // skip nodes in the TFO or in the MFFC of node + if ( Abc_NodeIsTravIdCurrent(pFanout) ) + continue; + // skip COs + if ( !Abc_ObjIsNode(pFanout) ) + continue; + // skip nodes with large level + if ( (int)pFanout->Level >= p->nLevDivMax ) + continue; + // skip nodes whose fanins are not divisors + Abc_ObjForEachFanin( pFanout, pFanin, m ) + if ( !Abc_NodeIsTravIdPrevious(pFanin) ) + break; + if ( m < Abc_ObjFaninNum(pFanout) ) + continue; + // add the node to the divisors + Vec_PtrPush( p->vDivs, pFanout ); + Vec_PtrPush( p->vNodes, pFanout ); + Abc_NodeSetTravIdPrevious( pFanout ); + p->nDivsPlus++; + } + } +/* + printf( "Node level = %d. ", Abc_ObjLevel(p->pNode) ); + Vec_PtrForEachEntryStart( p->vDivs, pObj, k, Vec_PtrSize(p->vDivs)-p->nDivsPlus ) + printf( "%d ", Abc_ObjLevel(pObj) ); + printf( "\n" ); +*/ +//printf( "%d ", p->nDivsPlus ); +} + +/**Function************************************************************* + + Synopsis [Marks the TFI cone of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_WinMarkTfi_rec( Res_Win_t * p, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return; + Abc_NodeSetTravIdCurrent( pObj ); + assert( Abc_ObjIsNode(pObj) ); + // visit the fanins of the node + Abc_ObjForEachFanin( pObj, pFanin, i ) + Res_WinMarkTfi_rec( p, pFanin ); +} + +/**Function************************************************************* + + Synopsis [Marks the TFI cone of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_WinMarkTfi( Res_Win_t * p ) +{ + Abc_Obj_t * pObj; + int i; + // mark the leaves + Vec_PtrForEachEntry( p->vLeaves, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // start from the node + Res_WinMarkTfi_rec( p, p->pNode ); +} + +/**Function************************************************************* + + Synopsis [Marks the TFO of the collected nodes up to the given level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit ) +{ + Abc_Obj_t * pFanout; + int i; + if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit ) + return; + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return; + Abc_NodeSetTravIdCurrent( pObj ); + Abc_ObjForEachFanout( pObj, pFanout, i ) + Res_WinSweepLeafTfo_rec( pFanout, nLevelLimit ); +} + +/**Function************************************************************* + + Synopsis [Dereferences the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_NodeDeref_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i, Counter = 1; + if ( Abc_ObjIsCi(pNode) ) + return 0; + Abc_NodeSetTravIdCurrent( pNode ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + assert( pFanin->vFanouts.nSize > 0 ); + if ( --pFanin->vFanouts.nSize == 0 ) + Counter += Res_NodeDeref_rec( pFanin ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_NodeRef_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i, Counter = 1; + if ( Abc_ObjIsCi(pNode) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pFanin->vFanouts.nSize++ == 0 ) + Counter += Res_NodeRef_rec( pFanin ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Labels MFFC of the node with the current trav ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_WinVisitMffc( Abc_Obj_t * pNode ) +{ + int Count1, Count2; + assert( Abc_ObjIsNode(pNode) ); + // dereference the node (mark with the current trav ID) + Count1 = Res_NodeDeref_rec( pNode ); + // reference it back + Count2 = Res_NodeRef_rec( pNode ); + assert( Count1 == Count2 ); + return Count1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/res/resFilter.c b/abc70930/src/opt/res/resFilter.c new file mode 100644 index 00000000..f2ca41d3 --- /dev/null +++ b/abc70930/src/opt/res/resFilter.c @@ -0,0 +1,434 @@ +/**CFile**************************************************************** + + FileName [resFilter.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resynthesis package.] + + Synopsis [Filtering resubstitution candidates.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: resFilter.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "resInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask ); +static int Res_FilterCriticalFanin( Abc_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Finds sets of feasible candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea ) +{ + Abc_Obj_t * pFanin, * pFanin2, * pFaninTemp; + unsigned * pInfo, * pInfoDiv, * pInfoDiv2; + int Counter, RetValue, i, i2, d, d2, iDiv, iDiv2, k; + + // check that the info the node is one + pInfo = Vec_PtrEntry( pSim->vOuts, 1 ); + RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); + if ( RetValue == 0 ) + { +// printf( "Failed 1!\n" ); + return 0; + } + + // collect the fanin info + pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 ); + RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); + if ( RetValue == 0 ) + { +// printf( "Failed 2!\n" ); + return 0; + } + + // try removing each fanin +// printf( "Fanins: " ); + Counter = 0; + Vec_VecClear( vResubs ); + Vec_VecClear( vResubsW ); + Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) + { + if ( fArea && Abc_ObjFanoutNum(pFanin) > 1 ) + continue; + // get simulation info without this fanin + pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) ); + RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); + if ( RetValue ) + { +// printf( "Node %4d. Candidate fanin %4d.\n", pWin->pNode->Id, pFanin->Id ); + // collect the nodes + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); + Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) + { + if ( k != i ) + { + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); + Vec_VecPush( vResubsW, Counter, pFaninTemp ); + } + } + Counter++; + if ( Counter == Vec_VecSize(vResubs) ) + return Counter; + } + } + + // try replacing each critical fanin by a non-critical fanin + Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) + { + if ( Abc_ObjFanoutNum(pFanin) > 1 ) + continue; + // get simulation info without this fanin + pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) ); + // go over the set of divisors + for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) + { + pInfoDiv = Vec_PtrEntry( pSim->vOuts, d ); + iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); + if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) ) + continue; + // collect the nodes + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); + // collect the remaning fanins and the divisor + Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) + { + if ( k != i ) + { + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); + Vec_VecPush( vResubsW, Counter, pFaninTemp ); + } + } + // collect the divisor + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); + Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); + Counter++; + if ( Counter == Vec_VecSize(vResubs) ) + return Counter; + } + } + + // consider the case when two fanins can be added instead of one + if ( Abc_ObjFaninNum(pWin->pNode) < nFaninsMax ) + { + // try to replace each critical fanin by two non-critical fanins + Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) + { + if ( Abc_ObjFanoutNum(pFanin) > 1 ) + continue; + // get simulation info without this fanin + pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) ); + // go over the set of divisors + for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) + { + pInfoDiv = Vec_PtrEntry( pSim->vOuts, d ); + iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); + // go through the second divisor + for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ ) + { + pInfoDiv2 = Vec_PtrEntry( pSim->vOuts, d2 ); + iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2); + if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) ) + continue; + // collect the nodes + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); + // collect the remaning fanins and the divisor + Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) + { + if ( k != i ) + { + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); + Vec_VecPush( vResubsW, Counter, pFaninTemp ); + } + } + // collect the divisor + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) ); + Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); + Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) ); + Counter++; + if ( Counter == Vec_VecSize(vResubs) ) + return Counter; + } + } + } + } + + // try to replace two nets by one + if ( !fArea ) + { + Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) + { + for ( i2 = i + 1; i2 < Abc_ObjFaninNum(pWin->pNode); i2++ ) + { + pFanin2 = Abc_ObjFanin(pWin->pNode, i2); + // get simulation info without these fanins + pInfo = Res_FilterCollectFaninInfo( pWin, pSim, (~(1 << i)) & (~(1 << i2)) ); + // go over the set of divisors + for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) + { + pInfoDiv = Vec_PtrEntry( pSim->vOuts, d ); + iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); + if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) ) + continue; + // collect the nodes + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); + // collect the remaning fanins and the divisor + Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) + { + if ( k != i && k != i2 ) + { + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); + Vec_VecPush( vResubsW, Counter, pFaninTemp ); + } + } + // collect the divisor + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); + Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); + Counter++; + if ( Counter == Vec_VecSize(vResubs) ) + return Counter; + } + } + } + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Finds sets of feasible candidates.] + + Description [This procedure is a special case of the above.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax ) +{ + Abc_Obj_t * pFanin; + unsigned * pInfo, * pInfoDiv, * pInfoDiv2; + int Counter, RetValue, d, d2, k, iDiv, iDiv2, iBest; + + // check that the info the node is one + pInfo = Vec_PtrEntry( pSim->vOuts, 1 ); + RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); + if ( RetValue == 0 ) + { +// printf( "Failed 1!\n" ); + return 0; + } + + // collect the fanin info + pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 ); + RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); + if ( RetValue == 0 ) + { +// printf( "Failed 2!\n" ); + return 0; + } + + // try removing fanins +// printf( "Fanins: " ); + Counter = 0; + Vec_VecClear( vResubs ); + Vec_VecClear( vResubsW ); + // get the best fanins + iBest = Res_FilterCriticalFanin( pWin->pNode ); + if ( iBest == -1 ) + return 0; + + // get the info without the critical fanin + pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << iBest) ); + RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); + if ( RetValue ) + { +// printf( "Can be done without one!\n" ); + // collect the nodes + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); + Abc_ObjForEachFanin( pWin->pNode, pFanin, k ) + { + if ( k != iBest ) + { + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); + Vec_VecPush( vResubsW, Counter, pFanin ); + } + } + Counter++; +// printf( "*" ); + return Counter; + } + + // go through the divisors + for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) + { + pInfoDiv = Vec_PtrEntry( pSim->vOuts, d ); + iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); + if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) ) + continue; +//if ( Abc_ObjLevel(pWin->pNode) <= Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) ) +// printf( "Node level = %d. Divisor level = %d.\n", Abc_ObjLevel(pWin->pNode), Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) ); + // collect the nodes + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); + // collect the remaning fanins and the divisor + Abc_ObjForEachFanin( pWin->pNode, pFanin, k ) + { + if ( k != iBest ) + { + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); + Vec_VecPush( vResubsW, Counter, pFanin ); + } + } + // collect the divisor + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); + Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); + Counter++; + + if ( Counter == Vec_VecSize(vResubs) ) + break; + } + + if ( Counter > 0 || Abc_ObjFaninNum(pWin->pNode) >= nFaninsMax ) + return Counter; + + // try to find the node pairs + for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) + { + pInfoDiv = Vec_PtrEntry( pSim->vOuts, d ); + iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); + // go through the second divisor + for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ ) + { + pInfoDiv2 = Vec_PtrEntry( pSim->vOuts, d2 ); + iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2); + + if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) ) + continue; + // collect the nodes + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); + // collect the remaning fanins and the divisor + Abc_ObjForEachFanin( pWin->pNode, pFanin, k ) + { + if ( k != iBest ) + { + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); + Vec_VecPush( vResubsW, Counter, pFanin ); + } + } + // collect the divisor + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); + Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) ); + Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); + Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) ); + Counter++; + + if ( Counter == Vec_VecSize(vResubs) ) + break; + } + if ( Counter == Vec_VecSize(vResubs) ) + break; + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Finds sets of feasible candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask ) +{ + Abc_Obj_t * pFanin; + unsigned * pInfo; + int i; + pInfo = Vec_PtrEntry( pSim->vOuts, 0 ); + Abc_InfoClear( pInfo, pSim->nWordsOut ); + Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) + { + if ( uMask & (1 << i) ) + Abc_InfoOr( pInfo, Vec_PtrEntry(pSim->vOuts, 2+i), pSim->nWordsOut ); + } + return pInfo; +} + + +/**Function************************************************************* + + Synopsis [Returns the index of the most critical fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_FilterCriticalFanin( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i, iBest = -1, CostMax = 0, CostCur; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( !Abc_ObjIsNode(pFanin) ) + continue; + if ( Abc_ObjFanoutNum(pFanin) > 1 ) + continue; + CostCur = Res_WinVisitMffc( pFanin ); + if ( CostMax < CostCur ) + { + CostMax = CostCur; + iBest = i; + } + } +// if ( CostMax > 0 ) +// printf( "<%d>", CostMax ); + return iBest; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/res/resInt.h b/abc70930/src/opt/res/resInt.h new file mode 100644 index 00000000..5aae46cc --- /dev/null +++ b/abc70930/src/opt/res/resInt.h @@ -0,0 +1,137 @@ +/**CFile**************************************************************** + + FileName [resInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resynthesis package.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __RES_INT_H__ +#define __RES_INT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "res.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Res_Win_t_ Res_Win_t; +struct Res_Win_t_ +{ + // windowing parameters + Abc_Obj_t * pNode; // the node in the center + int nWinTfiMax; // the fanin levels + int nWinTfoMax; // the fanout levels + int nLevDivMax; // the maximum divisor level + // internal windowing parameters + int nFanoutLimit; // the limit on the fanout count of a TFO node (if more, the node is treated as a root) + int nLevTfiMinus; // the number of additional levels to search from TFO below the level of leaves + // derived windowing parameters + int nLevLeafMin; // the minimum level of a leaf + int nLevTravMin; // the minimum level to search from TFO + int nDivsPlus; // the number of additional divisors + // the window data + Vec_Ptr_t * vRoots; // outputs of the window + Vec_Ptr_t * vLeaves; // inputs of the window + Vec_Ptr_t * vBranches; // side nodes of the window + Vec_Ptr_t * vNodes; // internal nodes of the window + Vec_Ptr_t * vDivs; // candidate divisors of the node + // temporary data + Vec_Vec_t * vMatrix; // TFI nodes below the given node +}; + +typedef struct Res_Sim_t_ Res_Sim_t; +struct Res_Sim_t_ +{ + Abc_Ntk_t * pAig; // AIG for simulation + int nTruePis; // the number of true PIs of the window + int fConst0; // the node can be replaced by constant 0 + int fConst1; // the node can be replaced by constant 0 + // simulation parameters + int nWords; // the number of simulation words + int nPats; // the number of patterns + int nWordsIn; // the number of simulation words in the input patterns + int nPatsIn; // the number of patterns in the input patterns + int nBytesIn; // the number of bytes in the input patterns + int nWordsOut; // the number of simulation words in the output patterns + int nPatsOut; // the number of patterns in the output patterns + // simulation info + Vec_Ptr_t * vPats; // input simulation patterns + Vec_Ptr_t * vPats0; // input simulation patterns + Vec_Ptr_t * vPats1; // input simulation patterns + Vec_Ptr_t * vOuts; // output simulation info + int nPats0; // the number of 0-patterns accumulated + int nPats1; // the number of 1-patterns accumulated + // resub candidates + Vec_Vec_t * vCands; // resubstitution candidates + // statistics + int timeSat; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== resDivs.c ==========================================================*/ +extern void Res_WinDivisors( Res_Win_t * p, int nLevDivMax ); +extern void Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit ); +extern int Res_WinVisitMffc( Abc_Obj_t * pNode ); +/*=== resFilter.c ==========================================================*/ +extern int Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea ); +extern int Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax ); +/*=== resSat.c ==========================================================*/ +extern void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins ); +extern int Res_SatSimulate( Res_Sim_t * p, int nPats, int fOnSet ); +/*=== resSim.c ==========================================================*/ +extern Res_Sim_t * Res_SimAlloc( int nWords ); +extern void Res_SimFree( Res_Sim_t * p ); +extern int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose ); +/*=== resStrash.c ==========================================================*/ +extern Abc_Ntk_t * Res_WndStrash( Res_Win_t * p ); +/*=== resWnd.c ==========================================================*/ +extern void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels ); +/*=== resWnd.c ==========================================================*/ +extern Res_Win_t * Res_WinAlloc(); +extern void Res_WinFree( Res_Win_t * p ); +extern int Res_WinIsTrivial( Res_Win_t * p ); +extern int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p ); + + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/res/resSat.c b/abc70930/src/opt/res/resSat.c new file mode 100644 index 00000000..dd0e7a23 --- /dev/null +++ b/abc70930/src/opt/res/resSat.c @@ -0,0 +1,407 @@ +/**CFile**************************************************************** + + FileName [resSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resynthesis package.] + + Synopsis [Interface with the SAT solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: resSat.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "resInt.h" +#include "hop.h" +#include "satSolver.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl ); +extern int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl ); +extern int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Loads AIG into the SAT solver for checking resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins ) +{ + void * pCnf = NULL; + sat_solver * pSat; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i, nNodes, status; + + // make sure fanins contain POs of the AIG + pObj = Vec_PtrEntry( vFanins, 0 ); + assert( pObj->pNtk == pAig && Abc_ObjIsPo(pObj) ); + + // collect reachable nodes + vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize ); + + // assign unique numbers to each node + nNodes = 0; + Abc_AigConst1(pAig)->pCopy = (void *)nNodes++; + Abc_NtkForEachPi( pAig, pObj, i ) + pObj->pCopy = (void *)nNodes++; + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pCopy = (void *)nNodes++; + Vec_PtrForEachEntry( vFanins, pObj, i ) // useful POs + pObj->pCopy = (void *)nNodes++; + + // start the solver + pSat = sat_solver_new(); + sat_solver_store_alloc( pSat ); + + // add clause for the constant node + Res_SatAddConst1( pSat, (int)Abc_AigConst1(pAig)->pCopy, 0 ); + // add clauses for AND gates + Vec_PtrForEachEntry( vNodes, pObj, i ) + Res_SatAddAnd( pSat, (int)pObj->pCopy, + (int)Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + Vec_PtrFree( vNodes ); + // add clauses for POs + Vec_PtrForEachEntry( vFanins, pObj, i ) + Res_SatAddEqual( pSat, (int)pObj->pCopy, + (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); + // add trivial clauses + pObj = Vec_PtrEntry(vFanins, 0); + Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // care-set + pObj = Vec_PtrEntry(vFanins, 1); + Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // on-set + + // bookmark the clauses of A + sat_solver_store_mark_clauses_a( pSat ); + + // duplicate the clauses + pObj = Vec_PtrEntry(vFanins, 1); + Sat_SolverDoubleClauses( pSat, (int)pObj->pCopy ); + // add the equality constraints + Vec_PtrForEachEntryStart( vFanins, pObj, i, 2 ) + Res_SatAddEqual( pSat, (int)pObj->pCopy, ((int)pObj->pCopy) + nNodes, 0 ); + + // bookmark the roots + sat_solver_store_mark_roots( pSat ); + + // solve the problem + status = sat_solver_solve( pSat, NULL, NULL, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 ); + if ( status == l_False ) + { + pCnf = sat_solver_store_release( pSat ); +// printf( "unsat\n" ); + } + else if ( status == l_True ) + { +// printf( "sat\n" ); + } + else + { +// printf( "undef\n" ); + } + sat_solver_delete( pSat ); + return pCnf; +} + +/**Function************************************************************* + + Synopsis [Loads AIG into the SAT solver for constrained simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Res_SatSimulateConstr( Abc_Ntk_t * pAig, int fOnSet ) +{ + sat_solver * pSat; + Vec_Ptr_t * vFanins; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i, nNodes; + + // start the array + vFanins = Vec_PtrAlloc( 2 ); + pObj = Abc_NtkPo( pAig, 0 ); + Vec_PtrPush( vFanins, pObj ); + pObj = Abc_NtkPo( pAig, 1 ); + Vec_PtrPush( vFanins, pObj ); + + // collect reachable nodes + vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize ); + + // assign unique numbers to each node + nNodes = 0; + Abc_AigConst1(pAig)->pCopy = (void *)nNodes++; + Abc_NtkForEachPi( pAig, pObj, i ) + pObj->pCopy = (void *)nNodes++; + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pCopy = (void *)nNodes++; + Vec_PtrForEachEntry( vFanins, pObj, i ) // useful POs + pObj->pCopy = (void *)nNodes++; + + // start the solver + pSat = sat_solver_new(); + + // add clause for the constant node + Res_SatAddConst1( pSat, (int)Abc_AigConst1(pAig)->pCopy, 0 ); + // add clauses for AND gates + Vec_PtrForEachEntry( vNodes, pObj, i ) + Res_SatAddAnd( pSat, (int)pObj->pCopy, + (int)Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + Vec_PtrFree( vNodes ); + // add clauses for the first PO + pObj = Abc_NtkPo( pAig, 0 ); + Res_SatAddEqual( pSat, (int)pObj->pCopy, + (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); + // add clauses for the second PO + pObj = Abc_NtkPo( pAig, 1 ); + Res_SatAddEqual( pSat, (int)pObj->pCopy, + (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); + + // add trivial clauses + pObj = Abc_NtkPo( pAig, 0 ); + Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // care-set + + pObj = Abc_NtkPo( pAig, 1 ); + Res_SatAddConst1( pSat, (int)pObj->pCopy, !fOnSet ); // on-set + + Vec_PtrFree( vFanins ); + return pSat; +} + +/**Function************************************************************* + + Synopsis [Loads AIG into the SAT solver for constrained simulation.] + + Description [Returns 1 if the required number of patterns are found. + Returns 0 if the solver ran out of time or proved a constant. + In the latter, case one of the flags, fConst0 or fConst1, are set to 1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_SatSimulate( Res_Sim_t * p, int nPatsLimit, int fOnSet ) +{ + Vec_Int_t * vLits; + Vec_Ptr_t * vPats; + sat_solver * pSat; + int RetValue, i, k, value, status, Lit, Var, iPat; + int clk = clock(); + +//printf( "Looking for %s: ", fOnSet? "onset " : "offset" ); + + // decide what problem should be solved + Lit = toLitCond( (int)Abc_NtkPo(p->pAig,1)->pCopy, !fOnSet ); + if ( fOnSet ) + { + iPat = p->nPats1; + vPats = p->vPats1; + } + else + { + iPat = p->nPats0; + vPats = p->vPats0; + } + assert( iPat < nPatsLimit ); + + // derive the SAT solver + pSat = Res_SatSimulateConstr( p->pAig, fOnSet ); + pSat->fSkipSimplify = 1; + status = sat_solver_simplify( pSat ); + if ( status == 0 ) + { + if ( iPat == 0 ) + { +// if ( fOnSet ) +// p->fConst0 = 1; +// else +// p->fConst1 = 1; + RetValue = 0; + } + goto finish; + } + + // enumerate through the SAT assignments + RetValue = 1; + vLits = Vec_IntAlloc( 32 ); + for ( k = iPat; k < nPatsLimit; k++ ) + { + // solve with the assumption +// status = sat_solver_solve( pSat, &Lit, &Lit + 1, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 ); + status = sat_solver_solve( pSat, NULL, NULL, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 ); + if ( status == l_False ) + { +//printf( "Const %d\n", !fOnSet ); + if ( k == 0 ) + { + if ( fOnSet ) + p->fConst0 = 1; + else + p->fConst1 = 1; + RetValue = 0; + } + break; + } + else if ( status == l_True ) + { + // save the pattern + Vec_IntClear( vLits ); + for ( i = 0; i < p->nTruePis; i++ ) + { + Var = (int)Abc_NtkPi(p->pAig,i)->pCopy; + value = (int)(pSat->model.ptr[Var] == l_True); + if ( value ) + Abc_InfoSetBit( Vec_PtrEntry(vPats, i), k ); + Lit = toLitCond( Var, value ); + Vec_IntPush( vLits, Lit ); +// printf( "%d", value ); + } +// printf( "\n" ); + + status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); + if ( status == 0 ) + { + k++; + RetValue = 1; + break; + } + } + else + { +//printf( "Undecided\n" ); + if ( k == 0 ) + RetValue = 0; + else + RetValue = 1; + break; + } + } + Vec_IntFree( vLits ); +//printf( "Found %d patterns\n", k - iPat ); + + // set the new number of patterns + if ( fOnSet ) + p->nPats1 = k; + else + p->nPats0 = k; + +finish: + + sat_solver_delete( pSat ); +p->timeSat += clock() - clk; + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Asserts equality of the variable to a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl ) +{ + lit Lit = toLitCond( iVar, fCompl ); + if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Asserts equality of two variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl ) +{ + lit Lits[2]; + + Lits[0] = toLitCond( iVar0, 0 ); + Lits[1] = toLitCond( iVar1, !fCompl ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + Lits[0] = toLitCond( iVar0, 1 ); + Lits[1] = toLitCond( iVar1, fCompl ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds constraints for the two-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ) +{ + lit Lits[3]; + + Lits[0] = toLitCond( iVar, 1 ); + Lits[1] = toLitCond( iVar0, fCompl0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + Lits[0] = toLitCond( iVar, 1 ); + Lits[1] = toLitCond( iVar1, fCompl1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + Lits[0] = toLitCond( iVar, 0 ); + Lits[1] = toLitCond( iVar0, !fCompl0 ); + Lits[2] = toLitCond( iVar1, !fCompl1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) + return 0; + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/res/resSim.c b/abc70930/src/opt/res/resSim.c new file mode 100644 index 00000000..5c1dd2b6 --- /dev/null +++ b/abc70930/src/opt/res/resSim.c @@ -0,0 +1,790 @@ +/**CFile**************************************************************** + + FileName [resSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resynthesis package.] + + Synopsis [Simulation engine.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "resInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocate simulation engine.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Res_Sim_t * Res_SimAlloc( int nWords ) +{ + Res_Sim_t * p; + p = ALLOC( Res_Sim_t, 1 ); + memset( p, 0, sizeof(Res_Sim_t) ); + // simulation parameters + p->nWords = nWords; + p->nPats = p->nWords * 8 * sizeof(unsigned); + p->nWordsIn = p->nPats; + p->nBytesIn = p->nPats * sizeof(unsigned); + p->nPatsIn = p->nPats * 8 * sizeof(unsigned); + p->nWordsOut = p->nPats * p->nWords; + p->nPatsOut = p->nPats * p->nPats; + // simulation info + p->vPats = Vec_PtrAllocSimInfo( 1024, p->nWordsIn ); + p->vPats0 = Vec_PtrAllocSimInfo( 128, p->nWords ); + p->vPats1 = Vec_PtrAllocSimInfo( 128, p->nWords ); + p->vOuts = Vec_PtrAllocSimInfo( 128, p->nWordsOut ); + // resub candidates + p->vCands = Vec_VecStart( 16 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Allocate simulation engine.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis ) +{ + srand( 0xABC ); + + assert( Abc_NtkIsStrash(pAig) ); + p->pAig = pAig; + p->nTruePis = nTruePis; + if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 ) + { + Vec_PtrFree( p->vPats ); + p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWordsIn ); + } + if ( Vec_PtrSize(p->vPats0) < nTruePis ) + { + Vec_PtrFree( p->vPats0 ); + p->vPats0 = Vec_PtrAllocSimInfo( nTruePis, p->nWords ); + } + if ( Vec_PtrSize(p->vPats1) < nTruePis ) + { + Vec_PtrFree( p->vPats1 ); + p->vPats1 = Vec_PtrAllocSimInfo( nTruePis, p->nWords ); + } + if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) ) + { + Vec_PtrFree( p->vOuts ); + p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut ); + } + // clean storage info for patterns + Abc_InfoClear( Vec_PtrEntry(p->vPats0,0), p->nWords * nTruePis ); + Abc_InfoClear( Vec_PtrEntry(p->vPats1,0), p->nWords * nTruePis ); + p->nPats0 = 0; + p->nPats1 = 0; + p->fConst0 = 0; + p->fConst1 = 0; +} + +/**Function************************************************************* + + Synopsis [Free simulation engine.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimFree( Res_Sim_t * p ) +{ + Vec_PtrFree( p->vPats ); + Vec_PtrFree( p->vPats0 ); + Vec_PtrFree( p->vPats1 ); + Vec_PtrFree( p->vOuts ); + Vec_VecFree( p->vCands ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Sets random PI simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_InfoRandomBytes( unsigned * p, int nWords ) +{ + int i, Num; + for ( i = nWords - 1; i >= 0; i-- ) + { + Num = rand(); + p[i] = (Num & 1)? 0xff : 0; + p[i] = (p[i] << 8) | ((Num & 2)? 0xff : 0); + p[i] = (p[i] << 8) | ((Num & 4)? 0xff : 0); + p[i] = (p[i] << 8) | ((Num & 8)? 0xff : 0); + } +// Extra_PrintBinary( stdout, p, 32 ); printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Sets random PI simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimSetRandomBytes( Res_Sim_t * p ) +{ + Abc_Obj_t * pObj; + unsigned * pInfo; + int i; + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); + if ( i < p->nTruePis ) + Abc_InfoRandomBytes( pInfo, p->nWordsIn ); + else + Abc_InfoRandom( pInfo, p->nWordsIn ); + } +/* + // double-check that all are byte-patterns + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + if ( i == p->nTruePis ) + break; + pInfoC = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); + for ( k = 0; k < p->nBytesIn; k++ ) + assert( pInfoC[k] == 0 || pInfoC[k] == 0xff ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Sets random PI simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimSetDerivedBytes( Res_Sim_t * p, int fUseWalk ) +{ + Vec_Ptr_t * vPatsSource[2]; + int nPatsSource[2]; + Abc_Obj_t * pObj; + unsigned char * pInfo; + int i, k, z, s, nPats; + + // set several random patterns + assert( p->nBytesIn % 32 == 0 ); + nPats = p->nBytesIn/8; + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + if ( i == p->nTruePis ) + break; + Abc_InfoRandomBytes( Vec_PtrEntry(p->vPats, pObj->Id), nPats/4 ); + } + + // set special patterns + if ( fUseWalk ) + { + for ( z = 0; z < 2; z++ ) + { + // set the zero pattern + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + if ( i == p->nTruePis ) + break; + pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); + pInfo[nPats] = z ? 0xff : 0; + } + if ( ++nPats == p->nBytesIn ) + return; + // set the walking zero pattern + for ( k = 0; k < p->nTruePis; k++ ) + { + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + if ( i == p->nTruePis ) + break; + pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); + pInfo[nPats] = ((i == k) ^ z) ? 0xff : 0; + } + if ( ++nPats == p->nBytesIn ) + return; + } + } + } + + // decide what patterns to set first + if ( p->nPats0 < p->nPats1 ) + { + nPatsSource[0] = p->nPats0; + vPatsSource[0] = p->vPats0; + nPatsSource[1] = p->nPats1; + vPatsSource[1] = p->vPats1; + } + else + { + nPatsSource[0] = p->nPats1; + vPatsSource[0] = p->vPats1; + nPatsSource[1] = p->nPats0; + vPatsSource[1] = p->vPats0; + } + for ( z = 0; z < 2; z++ ) + { + for ( s = nPatsSource[z] - 1; s >= 0; s-- ) + { +// if ( s == 0 ) +// printf( "Patterns:\n" ); + // set the given source pattern + for ( k = 0; k < p->nTruePis; k++ ) + { + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + if ( i == p->nTruePis ) + break; + pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); + if ( (i == k) ^ Abc_InfoHasBit( Vec_PtrEntry(vPatsSource[z], i), s ) ) + { + pInfo[nPats] = 0xff; +// if ( s == 0 ) +// printf( "1" ); + } + else + { + pInfo[nPats] = 0; +// if ( s == 0 ) +// printf( "0" ); + } + } +// if ( s == 0 ) +// printf( "\n" ); + if ( ++nPats == p->nBytesIn ) + return; + } + } + } + // clean the rest + for ( z = nPats; z < p->nBytesIn; z++ ) + { + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + if ( i == p->nTruePis ) + break; + pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); + memset( pInfo + nPats, 0, p->nBytesIn - nPats ); + } + } +/* + // double-check that all are byte-patterns + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + if ( i == p->nTruePis ) + break; + pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); + for ( k = 0; k < p->nBytesIn; k++ ) + assert( pInfo[k] == 0 || pInfo[k] == 0xff ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Sets given PI simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo ) +{ + Abc_Obj_t * pObj; + unsigned * pInfo, * pInfo2; + int i, w; + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + if ( i == p->nTruePis ) + break; + pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); + pInfo2 = Vec_PtrEntry( vInfo, i ); + for ( w = 0; w < p->nWords; w++ ) + pInfo[w] = pInfo2[w]; + } +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) +{ + unsigned * pInfo, * pInfo1, * pInfo2; + int k, fComp1, fComp2; + // simulate the internal nodes + assert( Abc_ObjIsNode(pNode) ); + pInfo = Vec_PtrEntry(vSimInfo, pNode->Id); + pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); + pInfo2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode)); + fComp1 = Abc_ObjFaninC0(pNode); + fComp2 = Abc_ObjFaninC1(pNode); + if ( fComp1 && fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = ~pInfo1[k] & ~pInfo2[k]; + else if ( fComp1 && !fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = ~pInfo1[k] & pInfo2[k]; + else if ( !fComp1 && fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = pInfo1[k] & ~pInfo2[k]; + else // if ( fComp1 && fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = pInfo1[k] & pInfo2[k]; +} + +/**Function************************************************************* + + Synopsis [Simulates one CO node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) +{ + unsigned * pInfo, * pInfo1; + int k, fComp1; + // simulate the internal nodes + assert( Abc_ObjIsCo(pNode) ); + pInfo = Vec_PtrEntry(vSimInfo, pNode->Id); + pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); + fComp1 = Abc_ObjFaninC0(pNode); + if ( fComp1 ) + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = ~pInfo1[k]; + else + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = pInfo1[k]; +} + +/**Function************************************************************* + + Synopsis [Performs one round of simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimPerformRound( Res_Sim_t * p, int nWords ) +{ + Abc_Obj_t * pObj; + int i; + Abc_InfoFill( Vec_PtrEntry(p->vPats,0), nWords ); + Abc_AigForEachAnd( p->pAig, pObj, i ) + Res_SimPerformOne( pObj, p->vPats, nWords ); + Abc_NtkForEachPo( p->pAig, pObj, i ) + Res_SimTransferOne( pObj, p->vPats, nWords ); +} + + +/**Function************************************************************* + + Synopsis [Pads the extra space with duplicated simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords ) +{ + unsigned * pInfo; + int i, w, iWords; + assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) ); + // pad the first word + if ( nPats < 8 * sizeof(unsigned) ) + { + Vec_PtrForEachEntry( vPats, pInfo, i ) + if ( pInfo[0] & 1 ) + pInfo[0] |= ((~0) << nPats); + nPats = 8 * sizeof(unsigned); + } + // pad the empty words + iWords = nPats / (8 * sizeof(unsigned)); + Vec_PtrForEachEntry( vPats, pInfo, i ) + { + for ( w = iWords; w < nWords; w++ ) + pInfo[w] = pInfo[0]; + } +} + +/**Function************************************************************* + + Synopsis [Duplicates the simulation info to fill the space.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimDeriveInfoReplicate( Res_Sim_t * p ) +{ + unsigned * pInfo, * pInfo2; + Abc_Obj_t * pObj; + int i, j, w; + Abc_NtkForEachPo( p->pAig, pObj, i ) + { + pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); + pInfo2 = Vec_PtrEntry( p->vOuts, i ); + for ( j = 0; j < p->nPats; j++ ) + for ( w = 0; w < p->nWords; w++ ) + *pInfo2++ = pInfo[w]; + } +} + +/**Function************************************************************* + + Synopsis [Complement the simulation info if necessary.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimDeriveInfoComplement( Res_Sim_t * p ) +{ + unsigned * pInfo, * pInfo2; + Abc_Obj_t * pObj; + int i, j, w; + Abc_NtkForEachPo( p->pAig, pObj, i ) + { + pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); + pInfo2 = Vec_PtrEntry( p->vOuts, i ); + for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords ) + if ( Abc_InfoHasBit( pInfo, j ) ) + for ( w = 0; w < p->nWords; w++ ) + pInfo2[w] = ~pInfo2[w]; + } +} + +/**Function************************************************************* + + Synopsis [Prints output patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig ) +{ + Abc_Obj_t * pObj; + unsigned * pInfo2; + int i; + Abc_NtkForEachPo( pAig, pObj, i ) + { + pInfo2 = Vec_PtrEntry( p->vOuts, i ); + Extra_PrintBinary( stdout, pInfo2, p->nPatsOut ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Prints output patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimPrintNodePatterns( Res_Sim_t * p, Abc_Ntk_t * pAig ) +{ + unsigned * pInfo; + pInfo = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); + Extra_PrintBinary( stdout, pInfo, p->nPats ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of patters of different type.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimCountResults( Res_Sim_t * p, int * pnDcs, int * pnOnes, int * pnZeros, int fVerbose ) +{ + unsigned char * pInfoCare, * pInfoNode; + int i, nTotal = 0; + pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); + pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); + for ( i = 0; i < p->nBytesIn; i++ ) + { + if ( !pInfoCare[i] ) + (*pnDcs)++; + else if ( !pInfoNode[i] ) + (*pnZeros)++; + else + (*pnOnes)++; + } + nTotal += *pnDcs; + nTotal += *pnZeros; + nTotal += *pnOnes; + if ( fVerbose ) + { + printf( "Dc = %7.2f %% ", 100.0*(*pnDcs) /nTotal ); + printf( "On = %7.2f %% ", 100.0*(*pnOnes) /nTotal ); + printf( "Off = %7.2f %% ", 100.0*(*pnZeros)/nTotal ); + } +} + +/**Function************************************************************* + + Synopsis [Counts the number of patters of different type.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimCollectPatterns( Res_Sim_t * p, int fVerbose ) +{ + Abc_Obj_t * pObj; + unsigned char * pInfoCare, * pInfoNode, * pInfo; + int i, j; + pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); + pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); + for ( i = 0; i < p->nBytesIn; i++ ) + { + // skip don't-care patterns + if ( !pInfoCare[i] ) + continue; + // separate offset and onset patterns + assert( pInfoNode[i] == 0 || pInfoNode[i] == 0xff ); + if ( !pInfoNode[i] ) + { + if ( p->nPats0 >= p->nPats ) + continue; + Abc_NtkForEachPi( p->pAig, pObj, j ) + { + if ( j == p->nTruePis ) + break; + pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); + assert( pInfo[i] == 0 || pInfo[i] == 0xff ); + if ( pInfo[i] ) + Abc_InfoSetBit( Vec_PtrEntry(p->vPats0, j), p->nPats0 ); + } + p->nPats0++; + } + else + { + if ( p->nPats1 >= p->nPats ) + continue; + Abc_NtkForEachPi( p->pAig, pObj, j ) + { + if ( j == p->nTruePis ) + break; + pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); + assert( pInfo[i] == 0 || pInfo[i] == 0xff ); + if ( pInfo[i] ) + Abc_InfoSetBit( Vec_PtrEntry(p->vPats1, j), p->nPats1 ); + } + p->nPats1++; + } + if ( p->nPats0 >= p->nPats && p->nPats1 >= p->nPats ) + break; + } + if ( fVerbose ) + { + printf( "| " ); + printf( "On = %3d ", p->nPats1 ); + printf( "Off = %3d ", p->nPats0 ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Verifies the last pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_SimVerifyValue( Res_Sim_t * p, int fOnSet ) +{ + Abc_Obj_t * pObj; + unsigned * pInfo, * pInfo2; + int i, value; + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + if ( i == p->nTruePis ) + break; + if ( fOnSet ) + { + pInfo2 = Vec_PtrEntry( p->vPats1, i ); + value = Abc_InfoHasBit( pInfo2, p->nPats1 - 1 ); + } + else + { + pInfo2 = Vec_PtrEntry( p->vPats0, i ); + value = Abc_InfoHasBit( pInfo2, p->nPats0 - 1 ); + } + pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); + pInfo[0] = value ? ~0 : 0; + } + Res_SimPerformRound( p, 1 ); + pObj = Abc_NtkPo( p->pAig, 1 ); + pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); + assert( pInfo[0] == 0 || pInfo[0] == ~0 ); + return pInfo[0] > 0; +} + +/**Function************************************************************* + + Synopsis [Prepares simulation info for candidate filtering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose ) +{ + int i, nOnes = 0, nZeros = 0, nDcs = 0; + if ( fVerbose ) + printf( "\n" ); + // prepare the manager + Res_SimAdjust( p, pAig, nTruePis ); + // estimate the number of patterns + Res_SimSetRandomBytes( p ); + Res_SimPerformRound( p, p->nWordsIn ); + Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose ); + // collect the patterns + Res_SimCollectPatterns( p, fVerbose ); + // add more patterns using constraint simulation + if ( p->nPats0 < 8 ) + { + if ( !Res_SatSimulate( p, 16, 0 ) ) + return p->fConst0 || p->fConst1; +// return 0; +// printf( "Value0 = %d\n", Res_SimVerifyValue( p, 0 ) ); + } + if ( p->nPats1 < 8 ) + { + if ( !Res_SatSimulate( p, 16, 1 ) ) + return p->fConst0 || p->fConst1; +// return 0; +// printf( "Value1 = %d\n", Res_SimVerifyValue( p, 1 ) ); + } + // generate additional patterns + for ( i = 0; i < 2; i++ ) + { + if ( p->nPats0 > p->nPats*7/8 && p->nPats1 > p->nPats*7/8 ) + break; + Res_SimSetDerivedBytes( p, i==0 ); + Res_SimPerformRound( p, p->nWordsIn ); + Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose ); + Res_SimCollectPatterns( p, fVerbose ); + } + // create bit-matrix info + if ( p->nPats0 < p->nPats ) + Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords ); + if ( p->nPats1 < p->nPats ) + Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords ); + // resimulate 0-patterns + Res_SimSetGiven( p, p->vPats0 ); + Res_SimPerformRound( p, p->nWords ); +//Res_SimPrintNodePatterns( p, pAig ); + Res_SimDeriveInfoReplicate( p ); + // resimulate 1-patterns + Res_SimSetGiven( p, p->vPats1 ); + Res_SimPerformRound( p, p->nWords ); +//Res_SimPrintNodePatterns( p, pAig ); + Res_SimDeriveInfoComplement( p ); + // print output patterns +// Res_SimPrintOutPatterns( p, pAig ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/res/resSim_old.c b/abc70930/src/opt/res/resSim_old.c new file mode 100644 index 00000000..23ce29e4 --- /dev/null +++ b/abc70930/src/opt/res/resSim_old.c @@ -0,0 +1,521 @@ +/**CFile**************************************************************** + + FileName [resSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resynthesis package.] + + Synopsis [Simulation engine.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "resInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocate simulation engine.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Res_Sim_t * Res_SimAlloc( int nWords ) +{ + Res_Sim_t * p; + p = ALLOC( Res_Sim_t, 1 ); + memset( p, 0, sizeof(Res_Sim_t) ); + // simulation parameters + p->nWords = nWords; + p->nPats = 8 * sizeof(unsigned) * p->nWords; + p->nWordsOut = p->nPats * p->nWords; + p->nPatsOut = p->nPats * p->nPats; + // simulation info + p->vPats = Vec_PtrAllocSimInfo( 1024, p->nWords ); + p->vPats0 = Vec_PtrAllocSimInfo( 128, p->nWords ); + p->vPats1 = Vec_PtrAllocSimInfo( 128, p->nWords ); + p->vOuts = Vec_PtrAllocSimInfo( 128, p->nWordsOut ); + // resub candidates + p->vCands = Vec_VecStart( 16 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Allocate simulation engine.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig ) +{ + srand( 0xABC ); + + assert( Abc_NtkIsStrash(pAig) ); + p->pAig = pAig; + if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 ) + { + Vec_PtrFree( p->vPats ); + p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWords ); + } + if ( Vec_PtrSize(p->vPats0) < Abc_NtkPiNum(pAig) ) + { + Vec_PtrFree( p->vPats0 ); + p->vPats0 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords ); + } + if ( Vec_PtrSize(p->vPats1) < Abc_NtkPiNum(pAig) ) + { + Vec_PtrFree( p->vPats1 ); + p->vPats1 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords ); + } + if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) ) + { + Vec_PtrFree( p->vOuts ); + p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut ); + } + // clean storage info for patterns + Abc_InfoClear( Vec_PtrEntry(p->vPats0,0), p->nWords * Abc_NtkPiNum(pAig) ); + Abc_InfoClear( Vec_PtrEntry(p->vPats1,0), p->nWords * Abc_NtkPiNum(pAig) ); + p->nPats0 = 0; + p->nPats1 = 0; +} + +/**Function************************************************************* + + Synopsis [Free simulation engine.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimFree( Res_Sim_t * p ) +{ + Vec_PtrFree( p->vPats ); + Vec_PtrFree( p->vPats0 ); + Vec_PtrFree( p->vPats1 ); + Vec_PtrFree( p->vOuts ); + Vec_VecFree( p->vCands ); + free( p ); +} + + +/**Function************************************************************* + + Synopsis [Sets random PI simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimSetRandom( Res_Sim_t * p ) +{ + Abc_Obj_t * pObj; + unsigned * pInfo; + int i; + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); + Abc_InfoRandom( pInfo, p->nWords ); + } +} + +/**Function************************************************************* + + Synopsis [Sets given PI simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo ) +{ + Abc_Obj_t * pObj; + unsigned * pInfo, * pInfo2; + int i, w; + Abc_NtkForEachPi( p->pAig, pObj, i ) + { + pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); + pInfo2 = Vec_PtrEntry( vInfo, i ); + for ( w = 0; w < p->nWords; w++ ) + pInfo[w] = pInfo2[w]; + } +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) +{ + unsigned * pInfo, * pInfo1, * pInfo2; + int k, fComp1, fComp2; + // simulate the internal nodes + assert( Abc_ObjIsNode(pNode) ); + pInfo = Vec_PtrEntry(vSimInfo, pNode->Id); + pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); + pInfo2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode)); + fComp1 = Abc_ObjFaninC0(pNode); + fComp2 = Abc_ObjFaninC1(pNode); + if ( fComp1 && fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = ~pInfo1[k] & ~pInfo2[k]; + else if ( fComp1 && !fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = ~pInfo1[k] & pInfo2[k]; + else if ( !fComp1 && fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = pInfo1[k] & ~pInfo2[k]; + else // if ( fComp1 && fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = pInfo1[k] & pInfo2[k]; +} + +/**Function************************************************************* + + Synopsis [Simulates one CO node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) +{ + unsigned * pInfo, * pInfo1; + int k, fComp1; + // simulate the internal nodes + assert( Abc_ObjIsCo(pNode) ); + pInfo = Vec_PtrEntry(vSimInfo, pNode->Id); + pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); + fComp1 = Abc_ObjFaninC0(pNode); + if ( fComp1 ) + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = ~pInfo1[k]; + else + for ( k = 0; k < nSimWords; k++ ) + pInfo[k] = pInfo1[k]; +} + +/**Function************************************************************* + + Synopsis [Performs one round of simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimPerformRound( Res_Sim_t * p ) +{ + Abc_Obj_t * pObj; + int i; + Abc_InfoFill( Vec_PtrEntry(p->vPats,0), p->nWords ); + Abc_AigForEachAnd( p->pAig, pObj, i ) + Res_SimPerformOne( pObj, p->vPats, p->nWords ); + Abc_NtkForEachPo( p->pAig, pObj, i ) + Res_SimTransferOne( pObj, p->vPats, p->nWords ); +} + +/**Function************************************************************* + + Synopsis [Processes simulation patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimProcessPats( Res_Sim_t * p ) +{ + Abc_Obj_t * pObj; + unsigned * pInfoCare, * pInfoNode; + int i, j, nDcs = 0; + pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); + pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); + for ( i = 0; i < p->nPats; i++ ) + { + // skip don't-care patterns + if ( !Abc_InfoHasBit(pInfoCare, i) ) + { + nDcs++; + continue; + } + // separate offset and onset patterns + if ( !Abc_InfoHasBit(pInfoNode, i) ) + { + if ( p->nPats0 >= p->nPats ) + continue; + Abc_NtkForEachPi( p->pAig, pObj, j ) + if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) ) + Abc_InfoSetBit( Vec_PtrEntry(p->vPats0, j), p->nPats0 ); + p->nPats0++; + } + else + { + if ( p->nPats1 >= p->nPats ) + continue; + Abc_NtkForEachPi( p->pAig, pObj, j ) + if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) ) + Abc_InfoSetBit( Vec_PtrEntry(p->vPats1, j), p->nPats1 ); + p->nPats1++; + } + } +} + +/**Function************************************************************* + + Synopsis [Pads the extra space with duplicated simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords ) +{ + unsigned * pInfo; + int i, w, iWords; + assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) ); + // pad the first word + if ( nPats < 8 * sizeof(unsigned) ) + { + Vec_PtrForEachEntry( vPats, pInfo, i ) + if ( pInfo[0] & 1 ) + pInfo[0] |= ((~0) << nPats); + nPats = 8 * sizeof(unsigned); + } + // pad the empty words + iWords = nPats / (8 * sizeof(unsigned)); + Vec_PtrForEachEntry( vPats, pInfo, i ) + { + for ( w = iWords; w < nWords; w++ ) + pInfo[w] = pInfo[0]; + } +} + +/**Function************************************************************* + + Synopsis [Duplicates the simulation info to fill the space.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimDeriveInfoReplicate( Res_Sim_t * p ) +{ + unsigned * pInfo, * pInfo2; + Abc_Obj_t * pObj; + int i, j, w; + Abc_NtkForEachPo( p->pAig, pObj, i ) + { + pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); + pInfo2 = Vec_PtrEntry( p->vOuts, i ); + for ( j = 0; j < p->nPats; j++ ) + for ( w = 0; w < p->nWords; w++ ) + *pInfo2++ = pInfo[w]; + } +} + +/**Function************************************************************* + + Synopsis [Complement the simulation info if necessary.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimDeriveInfoComplement( Res_Sim_t * p ) +{ + unsigned * pInfo, * pInfo2; + Abc_Obj_t * pObj; + int i, j, w; + Abc_NtkForEachPo( p->pAig, pObj, i ) + { + pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); + pInfo2 = Vec_PtrEntry( p->vOuts, i ); + for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords ) + if ( Abc_InfoHasBit( pInfo, j ) ) + for ( w = 0; w < p->nWords; w++ ) + pInfo2[w] = ~pInfo2[w]; + } +} + +/**Function************************************************************* + + Synopsis [Free simulation engine.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimReportOne( Res_Sim_t * p ) +{ + unsigned * pInfoCare, * pInfoNode; + int i, nDcs, nOnes, nZeros; + pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); + pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); + nDcs = nOnes = nZeros = 0; + for ( i = 0; i < p->nPats; i++ ) + { + // skip don't-care patterns + if ( !Abc_InfoHasBit(pInfoCare, i) ) + { + nDcs++; + continue; + } + // separate offset and onset patterns + if ( !Abc_InfoHasBit(pInfoNode, i) ) + nZeros++; + else + nOnes++; + } + printf( "On = %3d (%7.2f %%) ", nOnes, 100.0*nOnes/p->nPats ); + printf( "Off = %3d (%7.2f %%) ", nZeros, 100.0*nZeros/p->nPats ); + printf( "Dc = %3d (%7.2f %%) ", nDcs, 100.0*nDcs/p->nPats ); + printf( "P0 = %3d ", p->nPats0 ); + printf( "P1 = %3d ", p->nPats1 ); + if ( p->nPats0 < 4 || p->nPats1 < 4 ) + printf( "*" ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints output patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig ) +{ + Abc_Obj_t * pObj; + unsigned * pInfo2; + int i; + Abc_NtkForEachPo( pAig, pObj, i ) + { + pInfo2 = Vec_PtrEntry( p->vOuts, i ); + Extra_PrintBinary( stdout, pInfo2, p->nPatsOut ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Prepares simulation info for candidate filtering.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose ) +{ + int Limit; + // prepare the manager + Res_SimAdjust( p, pAig ); + // collect 0/1 simulation info + for ( Limit = 0; Limit < 10; Limit++ ) + { + Res_SimSetRandom( p ); + Res_SimPerformRound( p ); + Res_SimProcessPats( p ); + if ( !(p->nPats0 < p->nPats || p->nPats1 < p->nPats) ) + break; + } +// printf( "%d ", Limit ); + // report the last set of patterns +// Res_SimReportOne( p ); +// printf( "\n" ); + // quit if there is not enough +// if ( p->nPats0 < 4 || p->nPats1 < 4 ) + if ( p->nPats0 < 4 || p->nPats1 < 4 ) + { +// Res_SimReportOne( p ); + return 0; + } + // create bit-matrix info + if ( p->nPats0 < p->nPats ) + Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords ); + if ( p->nPats1 < p->nPats ) + Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords ); + // resimulate 0-patterns + Res_SimSetGiven( p, p->vPats0 ); + Res_SimPerformRound( p ); + Res_SimDeriveInfoReplicate( p ); + // resimulate 1-patterns + Res_SimSetGiven( p, p->vPats1 ); + Res_SimPerformRound( p ); + Res_SimDeriveInfoComplement( p ); + // print output patterns +// Res_SimPrintOutPatterns( p, pAig ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/res/resStrash.c b/abc70930/src/opt/res/resStrash.c new file mode 100644 index 00000000..fde842a4 --- /dev/null +++ b/abc70930/src/opt/res/resStrash.c @@ -0,0 +1,117 @@ +/**CFile**************************************************************** + + FileName [resStrash.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resynthesis package.] + + Synopsis [Structural hashing of the nodes in the window.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: resStrash.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "resInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pAig, Abc_Obj_t * pObjOld ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Structurally hashes the given window.] + + Description [The first PO is the observability condition. The second + is the node's function. The remaining POs are the candidate divisors.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Res_WndStrash( Res_Win_t * p ) +{ + Vec_Ptr_t * vPairs; + Abc_Ntk_t * pAig; + Abc_Obj_t * pObj, * pMiter; + int i; + assert( Abc_NtkHasAig(p->pNode->pNtk) ); +// Abc_NtkCleanCopy( p->pNode->pNtk ); + // create the network + pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pAig->pName = Extra_UtilStrsav( "window" ); + // create the inputs + Vec_PtrForEachEntry( p->vLeaves, pObj, i ) + pObj->pCopy = Abc_NtkCreatePi( pAig ); + Vec_PtrForEachEntry( p->vBranches, pObj, i ) + pObj->pCopy = Abc_NtkCreatePi( pAig ); + // go through the nodes in the topological order + Vec_PtrForEachEntry( p->vNodes, pObj, i ) + { + pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj ); + if ( pObj == p->pNode ) + pObj->pCopy = Abc_ObjNot( pObj->pCopy ); + } + // collect the POs + vPairs = Vec_PtrAlloc( 2 * Vec_PtrSize(p->vRoots) ); + Vec_PtrForEachEntry( p->vRoots, pObj, i ) + { + Vec_PtrPush( vPairs, pObj->pCopy ); + Vec_PtrPush( vPairs, NULL ); + } + // mark the TFO of the node + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Res_WinSweepLeafTfo_rec( p->pNode, (int)p->pNode->Level + p->nWinTfoMax ); + // update strashing of the node + p->pNode->pCopy = Abc_ObjNot( p->pNode->pCopy ); + Abc_NodeSetTravIdPrevious( p->pNode ); + // redo strashing in the TFO + Vec_PtrForEachEntry( p->vNodes, pObj, i ) + { + if ( Abc_NodeIsTravIdCurrent(pObj) ) + pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj ); + } + // collect the POs + Vec_PtrForEachEntry( p->vRoots, pObj, i ) + Vec_PtrWriteEntry( vPairs, 2 * i + 1, pObj->pCopy ); + // add the miter + pMiter = Abc_AigMiter( pAig->pManFunc, vPairs ); + Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pMiter ); + Vec_PtrFree( vPairs ); + // add the node + Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), p->pNode->pCopy ); + // add the fanins + Abc_ObjForEachFanin( p->pNode, pObj, i ) + Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy ); + // add the divisors + Vec_PtrForEachEntry( p->vDivs, pObj, i ) + Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy ); + // add the names + Abc_NtkAddDummyPiNames( pAig ); + Abc_NtkAddDummyPoNames( pAig ); + // check the resulting network + if ( !Abc_NtkCheck( pAig ) ) + fprintf( stdout, "Res_WndStrash(): Network check has failed.\n" ); + return pAig; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/res/resWin.c b/abc70930/src/opt/res/resWin.c new file mode 100644 index 00000000..a3648925 --- /dev/null +++ b/abc70930/src/opt/res/resWin.c @@ -0,0 +1,485 @@ +/**CFile**************************************************************** + + FileName [resWin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resynthesis package.] + + Synopsis [Windowing algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: resWin.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "resInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the window.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Res_Win_t * Res_WinAlloc() +{ + Res_Win_t * p; + // start the manager + p = ALLOC( Res_Win_t, 1 ); + memset( p, 0, sizeof(Res_Win_t) ); + // set internal parameters + p->nFanoutLimit = 10; + p->nLevTfiMinus = 3; + // allocate storage + p->vRoots = Vec_PtrAlloc( 256 ); + p->vLeaves = Vec_PtrAlloc( 256 ); + p->vBranches = Vec_PtrAlloc( 256 ); + p->vNodes = Vec_PtrAlloc( 256 ); + p->vDivs = Vec_PtrAlloc( 256 ); + p->vMatrix = Vec_VecStart( 128 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Frees the window.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_WinFree( Res_Win_t * p ) +{ + Vec_PtrFree( p->vRoots ); + Vec_PtrFree( p->vLeaves ); + Vec_PtrFree( p->vBranches ); + Vec_PtrFree( p->vNodes ); + Vec_PtrFree( p->vDivs ); + Vec_VecFree( p->vMatrix ); + free( p ); +} + + + +/**Function************************************************************* + + Synopsis [Collect the limited TFI cone of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_WinCollectLeavesAndNodes( Res_Win_t * p ) +{ + Vec_Ptr_t * vFront; + Abc_Obj_t * pObj, * pTemp; + int i, k, m; + + assert( p->nWinTfiMax > 0 ); + assert( Vec_VecSize(p->vMatrix) > p->nWinTfiMax ); + + // start matrix with the node + Vec_VecClear( p->vMatrix ); + Vec_VecPush( p->vMatrix, 0, p->pNode ); + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Abc_NodeSetTravIdCurrent( p->pNode ); + + // collect the leaves (nodes pTemp such that "p->pNode->Level - pTemp->Level > p->nWinTfiMax") + Vec_PtrClear( p->vLeaves ); + Vec_VecForEachLevelStartStop( p->vMatrix, vFront, i, 0, p->nWinTfiMax ) + { + Vec_PtrForEachEntry( vFront, pObj, k ) + { + Abc_ObjForEachFanin( pObj, pTemp, m ) + { + if ( Abc_NodeIsTravIdCurrent( pTemp ) ) + continue; + Abc_NodeSetTravIdCurrent( pTemp ); + if ( Abc_ObjIsCi(pTemp) || (int)(p->pNode->Level - pTemp->Level) > p->nWinTfiMax ) + Vec_PtrPush( p->vLeaves, pTemp ); + else + Vec_VecPush( p->vMatrix, p->pNode->Level - pTemp->Level, pTemp ); + } + } + } + if ( Vec_PtrSize(p->vLeaves) == 0 ) + return 0; + + // collect the nodes in the reverse order + Vec_PtrClear( p->vNodes ); + Vec_VecForEachLevelReverseStartStop( p->vMatrix, vFront, i, p->nWinTfiMax, 0 ) + { + Vec_PtrForEachEntry( vFront, pObj, k ) + Vec_PtrPush( p->vNodes, pObj ); + Vec_PtrClear( vFront ); + } + + // get the lowest leaf level + p->nLevLeafMin = ABC_INFINITY; + Vec_PtrForEachEntry( p->vLeaves, pObj, k ) + p->nLevLeafMin = ABC_MIN( p->nLevLeafMin, (int)pObj->Level ); + + // set minimum traversal level + p->nLevTravMin = ABC_MAX( ((int)p->pNode->Level) - p->nWinTfiMax - p->nLevTfiMinus, p->nLevLeafMin ); + assert( p->nLevTravMin >= 0 ); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the node should be a root.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Res_WinComputeRootsCheck( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit ) +{ + Abc_Obj_t * pFanout; + int i; + // the node is the root if one of the following is true: + // (1) the node has more than fanouts than the limit + if ( Abc_ObjFanoutNum(pNode) > nFanoutLimit ) + return 1; + // (2) the node has CO fanouts + // (3) the node has fanouts above the cutoff level + Abc_ObjForEachFanout( pNode, pFanout, i ) + if ( Abc_ObjIsCo(pFanout) || (int)pFanout->Level > nLevelMax ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Recursively collects the root candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_WinComputeRoots_rec( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit, Vec_Ptr_t * vRoots ) +{ + Abc_Obj_t * pFanout; + int i; + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + Abc_NodeSetTravIdCurrent( pNode ); + // check if the node should be the root + if ( Res_WinComputeRootsCheck( pNode, nLevelMax, nFanoutLimit ) ) + Vec_PtrPush( vRoots, pNode ); + else // if not, explore its fanouts + Abc_ObjForEachFanout( pNode, pFanout, i ) + Res_WinComputeRoots_rec( pFanout, nLevelMax, nFanoutLimit, vRoots ); +} + +/**Function************************************************************* + + Synopsis [Recursively collects the root candidates.] + + Description [Returns 1 if the only root is this node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_WinComputeRoots( Res_Win_t * p ) +{ + Vec_PtrClear( p->vRoots ); + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Res_WinComputeRoots_rec( p->pNode, p->pNode->Level + p->nWinTfoMax, p->nFanoutLimit, p->vRoots ); + assert( Vec_PtrSize(p->vRoots) > 0 ); + if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode ) + return 0; + return 1; +} + + + +/**Function************************************************************* + + Synopsis [Marks the paths from the roots to the leaves.] + + Description [Returns 1 if the the node can reach a leaf.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_WinMarkPaths_rec( Abc_Obj_t * pNode, Abc_Obj_t * pPivot, int nLevelMin ) +{ + Abc_Obj_t * pFanin; + int i, RetValue; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return 1; + if ( Abc_NodeIsTravIdPrevious(pNode) ) + return 0; + // assume that the node does not have access to the leaves + Abc_NodeSetTravIdPrevious( pNode ); + // skip nodes below the given level + if ( pNode == pPivot || (int)pNode->Level <= nLevelMin ) + return 0; + assert( Abc_ObjIsNode(pNode) ); + // check if the fanins have access to the leaves + RetValue = 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + RetValue |= Res_WinMarkPaths_rec( pFanin, pPivot, nLevelMin ); + // relabel the node if it has access to the leaves + if ( RetValue ) + Abc_NodeSetTravIdCurrent( pNode ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Marks the paths from the roots to the leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_WinMarkPaths( Res_Win_t * p ) +{ + Abc_Obj_t * pObj; + int i; + // mark the leaves + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Vec_PtrForEachEntry( p->vLeaves, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // traverse from the roots and mark the nodes that can reach leaves + // the nodes that do not reach leaves have previous trav ID + // the nodes that reach leaves have current trav ID + Vec_PtrForEachEntry( p->vRoots, pObj, i ) + Res_WinMarkPaths_rec( pObj, p->pNode, p->nLevTravMin ); +} + + + + +/**Function************************************************************* + + Synopsis [Recursively collects the roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_WinFinalizeRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots ) +{ + Abc_Obj_t * pFanout; + int i; + assert( Abc_ObjIsNode(pObj) ); + assert( Abc_NodeIsTravIdCurrent(pObj) ); + // check if the node has all fanouts marked + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( !Abc_NodeIsTravIdCurrent(pFanout) ) + break; + // if some of the fanouts are unmarked, add the node to the roots + if ( i < Abc_ObjFanoutNum(pObj) ) + Vec_PtrPushUnique( vRoots, pObj ); + else // otherwise, call recursively + Abc_ObjForEachFanout( pObj, pFanout, i ) + Res_WinFinalizeRoots_rec( pFanout, vRoots ); +} + +/**Function************************************************************* + + Synopsis [Finalizes the roots of the window.] + + Description [Roots of the window are the nodes that have at least + one fanout that it not in the TFO of the leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_WinFinalizeRoots( Res_Win_t * p ) +{ + assert( !Abc_NodeIsTravIdCurrent(p->pNode) ); + // mark the node with the old traversal ID + Abc_NodeSetTravIdCurrent( p->pNode ); + // recollect the roots + Vec_PtrClear( p->vRoots ); + Res_WinFinalizeRoots_rec( p->pNode, p->vRoots ); + assert( Vec_PtrSize(p->vRoots) > 0 ); + if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode ) + return 0; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Recursively adds missing nodes and leaves.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_WinAddMissing_rec( Res_Win_t * p, Abc_Obj_t * pObj, int nLevTravMin ) +{ + Abc_Obj_t * pFanin; + int i; + // skip the already collected leaves, nodes, and branches + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return; + // if this is not an internal node - make it a new branch + if ( !Abc_NodeIsTravIdPrevious(pObj) ) + { + assert( Vec_PtrFind(p->vLeaves, pObj) == -1 ); + Abc_NodeSetTravIdCurrent( pObj ); + Vec_PtrPush( p->vBranches, pObj ); + return; + } + assert( Abc_ObjIsNode(pObj) ); // if this is a CI, then the window is incorrect! + Abc_NodeSetTravIdCurrent( pObj ); + // visit the fanins of the node + Abc_ObjForEachFanin( pObj, pFanin, i ) + Res_WinAddMissing_rec( p, pFanin, nLevTravMin ); + // collect the node + Vec_PtrPush( p->vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Adds to the window nodes and leaves in the TFI of the roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res_WinAddMissing( Res_Win_t * p ) +{ + Abc_Obj_t * pObj; + int i; + // mark the leaves + Abc_NtkIncrementTravId( p->pNode->pNtk ); + Vec_PtrForEachEntry( p->vLeaves, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // mark the already collected nodes + Vec_PtrForEachEntry( p->vNodes, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // explore from the roots + Vec_PtrClear( p->vBranches ); + Vec_PtrForEachEntry( p->vRoots, pObj, i ) + Res_WinAddMissing_rec( p, pObj, p->nLevTravMin ); +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the window is trivial (without TFO).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_WinIsTrivial( Res_Win_t * p ) +{ + return Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode; +} + +/**Function************************************************************* + + Synopsis [Computes the window.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p ) +{ + assert( Abc_ObjIsNode(pNode) ); + assert( nWinTfiMax > 0 && nWinTfiMax < 10 ); + assert( nWinTfoMax >= 0 && nWinTfoMax < 10 ); + + // initialize the window + p->pNode = pNode; + p->nWinTfiMax = nWinTfiMax; + p->nWinTfoMax = nWinTfoMax; + + Vec_PtrClear( p->vBranches ); + Vec_PtrClear( p->vDivs ); + Vec_PtrClear( p->vRoots ); + Vec_PtrPush( p->vRoots, pNode ); + + // compute the leaves + if ( !Res_WinCollectLeavesAndNodes( p ) ) + return 0; + + // compute the candidate roots + if ( p->nWinTfoMax > 0 && Res_WinComputeRoots(p) ) + { + // mark the paths from the roots to the leaves + Res_WinMarkPaths( p ); + // refine the roots and add branches and missing nodes + if ( Res_WinFinalizeRoots( p ) ) + Res_WinAddMissing( p ); + } + + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/res/res_.c b/abc70930/src/opt/res/res_.c new file mode 100644 index 00000000..a50affd7 --- /dev/null +++ b/abc70930/src/opt/res/res_.c @@ -0,0 +1,50 @@ +/**CFile**************************************************************** + + FileName [res_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Resynthesis package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 15, 2007.] + + Revision [$Id: res_.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "res.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/ret/module.make b/abc70930/src/opt/ret/module.make new file mode 100644 index 00000000..4b14365e --- /dev/null +++ b/abc70930/src/opt/ret/module.make @@ -0,0 +1,8 @@ +SRC += src/opt/ret/retArea.c \ + src/opt/ret/retCore.c \ + src/opt/ret/retDelay.c \ + src/opt/ret/retFlow.c \ + src/opt/ret/retIncrem.c \ + src/opt/ret/retInit.c \ + src/opt/ret/retLvalue.c + diff --git a/abc70930/src/opt/ret/retArea.c b/abc70930/src/opt/ret/retArea.c new file mode 100644 index 00000000..5eec8e80 --- /dev/null +++ b/abc70930/src/opt/ret/retArea.c @@ -0,0 +1,540 @@ +/**CFile**************************************************************** + + FileName [retArea.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Retiming package.] + + Synopsis [Min-area retiming.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Oct 31, 2006.] + + Revision [$Id: retArea.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "retInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose ); +static void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward ); +static void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); +static Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); +static void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ); + +extern Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs min-area retiming.] + + Description [Returns the number of latches reduced.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fVerbose ) +{ + Abc_Ntk_t * pNtkTotal = NULL, * pNtkBottom; + Vec_Int_t * vValuesNew = NULL, * vValues; + int nLatches = Abc_NtkLatchNum(pNtk); + int fOneFrame = 0; + assert( !fForwardOnly || !fBackwardOnly ); + // there should not be black boxes + assert( Abc_NtkIsSopLogic(pNtk) ); + assert( Abc_NtkLatchNum(pNtk) == Vec_PtrSize(pNtk->vBoxes) ); + // reorder CI/CO/latch inputs + Abc_NtkOrderCisCos( pNtk ); + // perform forward retiming + if ( !fBackwardOnly ) + { + if ( fOneFrame ) + Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose ); + else + while ( Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose ) ); + } + // remember initial values + vValues = Abc_NtkCollectLatchValues( pNtk ); + // perform backward retiming + if ( !fForwardOnly ) + { + if ( fOneFrame ) + pNtkTotal = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose ); + else + while ( pNtkBottom = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose ) ) + pNtkTotal = Abc_NtkAttachBottom( pNtkTotal, pNtkBottom ); + } + // compute initial values + vValuesNew = Abc_NtkRetimeInitialValues( pNtkTotal, vValues, fVerbose ); + if ( pNtkTotal ) Abc_NtkDelete( pNtkTotal ); + // insert new initial values + Abc_NtkInsertLatchValues( pNtk, vValuesNew ); + if ( vValuesNew ) Vec_IntFree( vValuesNew ); + if ( vValues ) Vec_IntFree( vValues ); + // fix the COs (this changes the circuit structure) +// Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); + // check for correctness + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkRetimeMinArea(): Network check has failed.\n" ); + // return the number of latches saved + return nLatches - Abc_NtkLatchNum(pNtk); +} + +/**Function************************************************************* + + Synopsis [Performs min-area retiming backward.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew = NULL; + Vec_Ptr_t * vMinCut; + int nLatches = Abc_NtkLatchNum(pNtk); + // mark current latches and TFI(POs) + Abc_NtkRetimeMinAreaPrepare( pNtk, fForward ); + // run the maximum forward flow + vMinCut = Abc_NtkMaxFlow( pNtk, fForward, fVerbose ); +// assert( Vec_PtrSize(vMinCut) <= Abc_NtkLatchNum(pNtk) ); + // create new latch boundary if there is improvement + if ( Vec_PtrSize(vMinCut) < Abc_NtkLatchNum(pNtk) ) + { + pNtkNew = (Abc_Ntk_t *)1; + if ( fForward ) + Abc_NtkRetimeMinAreaInitValues( pNtk, vMinCut ); + else + pNtkNew = Abc_NtkRetimeMinAreaConstructNtk( pNtk, vMinCut ); + Abc_NtkRetimeMinAreaUpdateLatches( pNtk, vMinCut, fForward ); + } + // clean up + Vec_PtrFree( vMinCut ); + Abc_NtkCleanMarkA( pNtk ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Marks the cone with MarkA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ) +{ + Abc_Obj_t * pNext; + int i; + if ( pObj->fMarkA ) + return; + pObj->fMarkA = 1; + if ( fForward ) + { + Abc_ObjForEachFanout( pObj, pNext, i ) + Abc_NtkMarkCone_rec( pNext, fForward ); + } + else + { + Abc_ObjForEachFanin( pObj, pNext, i ) + Abc_NtkMarkCone_rec( pNext, fForward ); + } +} + +/**Function************************************************************* + + Synopsis [Marks the cone with MarkA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUnmarkCone_rec( Abc_Obj_t * pObj, int fForward ) +{ + Abc_Obj_t * pNext; + int i; + if ( !pObj->fMarkA || Abc_ObjIsLatch(pObj) ) + return; + pObj->fMarkA = 0; + if ( fForward ) + { + Abc_ObjForEachFanout( pObj, pNext, i ) + Abc_NtkUnmarkCone_rec( pNext, fForward ); + } + else + { + Abc_ObjForEachFanin( pObj, pNext, i ) + Abc_NtkUnmarkCone_rec( pNext, fForward ); + } +} + +/**Function************************************************************* + + Synopsis [Prepares the network for running MaxFlow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanin; + int i, k; + if ( fForward ) + { + // mark the frontier + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->fMarkA = 1; + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + pObj->fMarkA = 1; + Abc_ObjFanin0(pObj)->fMarkA = 1; + } + // mark the nodes reachable from the PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkMarkCone_rec( pObj, fForward ); + // collect the unmarked fanins of the marked nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->fMarkA ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( !pFanin->fMarkA ) + Vec_PtrPush( vNodes, pFanin ); + // mark these nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->fMarkA = 1; + Vec_PtrFree( vNodes ); + } + else + { + // mark the frontier + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->fMarkA = 1; + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + pObj->fMarkA = 1; + Abc_ObjFanout0(pObj)->fMarkA = 1; + } + // mark the nodes reachable from the POs + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkMarkCone_rec( pObj, fForward ); + } +} + +/**Function************************************************************* + + Synopsis [Compute initial values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeMinAreaInitValues_rec( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return (int)pObj->pCopy; + Abc_NodeSetTravIdCurrent(pObj); + // consider the case of a latch output + if ( Abc_ObjIsBo(pObj) ) + { + assert( Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ); + pObj->pCopy = (void *)Abc_NtkRetimeMinAreaInitValues_rec( Abc_ObjFanin0(pObj) ); + return (int)pObj->pCopy; + } + assert( Abc_ObjIsNode(pObj) ); + // visit the fanins + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NtkRetimeMinAreaInitValues_rec( pFanin ); + // compute the value of the node + pObj->pCopy = (void *)Abc_ObjSopSimulate(pObj); + return (int)pObj->pCopy; +} + +/**Function************************************************************* + + Synopsis [Compute initial values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) +{ + Abc_Obj_t * pObj; + int i; + // transfer initial values to pCopy and mark the latches + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + pObj->pCopy = (void *)Abc_LatchIsInit1(pObj); + Abc_NodeSetTravIdCurrent( pObj ); + } + // propagate initial values + Vec_PtrForEachEntry( vMinCut, pObj, i ) + Abc_NtkRetimeMinAreaInitValues_rec( pObj ); + // unmark the latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_NodeSetTravIdPrevious( pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs min-area retiming backward.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkRetimeMinAreaConstructNtk_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return pObj->pCopy; + Abc_NodeSetTravIdCurrent(pObj); + // consider the case of a latch output + if ( Abc_ObjIsBi(pObj) ) + { + pObj->pCopy = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) ); + return pObj->pCopy; + } + assert( Abc_ObjIsNode(pObj) ); + // visit the fanins + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, pFanin ); + // compute the value of the node + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + return pObj->pCopy; +} + +/**Function************************************************************* + + Synopsis [Creates the network from computing initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pObjNew; + int i; + // create new network + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + // map new latches into PIs of the new network + Abc_NtkIncrementTravId(pNtk); + Vec_PtrForEachEntry( vMinCut, pObj, i ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_NodeSetTravIdCurrent( pObj ); + } + // construct the network recursively + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + pObjNew = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) ); + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObjNew ); + } + // unmark the nodes in the cut + Vec_PtrForEachEntry( vMinCut, pObj, i ) + Abc_NodeSetTravIdPrevious( pObj ); + // unmark the latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_NodeSetTravIdPrevious( pObj ); + // assign dummy node names + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkRetimeMinAreaConstructNtk(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Updates the network after backward retiming.] + + Description [Assumes that fMarkA denotes all nodes reachabe from + the latches toward the cut.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ) +{ + Vec_Ptr_t * vCis, * vCos, * vBoxes, * vBoxesNew, * vNodes, * vBuffers; + Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut, * pNext, * pBuffer; + int i, k; + // create new latches + Vec_PtrShrink( pNtk->vCis, Abc_NtkCiNum(pNtk) - Abc_NtkLatchNum(pNtk) ); + Vec_PtrShrink( pNtk->vCos, Abc_NtkCoNum(pNtk) - Abc_NtkLatchNum(pNtk) ); + vCis = pNtk->vCis; pNtk->vCis = NULL; + vCos = pNtk->vCos; pNtk->vCos = NULL; + vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL; + // transfer boxes + vBoxesNew = Vec_PtrAlloc(100); + Vec_PtrForEachEntry( vBoxes, pObj, i ) + if ( !Abc_ObjIsLatch(pObj) ) + Vec_PtrPush( vBoxesNew, pObj ); + // create or reuse latches + vNodes = Vec_PtrAlloc( 100 ); + vBuffers = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( vMinCut, pObj, i ) + { + if ( Abc_ObjIsCi(pObj) && fForward ) + { + pLatchOut = pObj; + pLatch = Abc_ObjFanin0(pLatchOut); + pLatchIn = Abc_ObjFanin0(pLatch); + assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) ); + // mark the latch as reused + Abc_NodeSetTravIdCurrent( pLatch ); + + // check if there are marked fanouts + // (these are fanouts to be connected to the latch input) + Abc_ObjForEachFanout( pObj, pNext, k ) + if ( pNext->fMarkA ) + break; + if ( k < Abc_ObjFanoutNum(pObj) ) + { + // add the buffer + pBuffer = Abc_NtkCreateNodeBuf( pNtk, Abc_ObjFanin0(pLatchIn) ); + Abc_ObjPatchFanin( pLatchIn, Abc_ObjFanin0(pLatchIn), pBuffer ); + Vec_PtrPush( vBuffers, pBuffer ); + // redirect edges to the unvisited fanouts of the node + Abc_NodeCollectFanouts( pObj, vNodes ); + Vec_PtrForEachEntry( vNodes, pNext, k ) + if ( pNext->fMarkA ) + Abc_ObjPatchFanin( pNext, pObj, pBuffer ); + } + assert( Abc_ObjFanoutNum(pObj) > 0 ); +// if ( Abc_ObjFanoutNum(pObj) == 0 ) +// Abc_NtkDeleteObj_rec( pObj, 0 ); + } + else if ( Abc_ObjIsCo(pObj) && !fForward ) + { + pLatchIn = pObj; + pLatch = Abc_ObjFanout0(pLatchIn); + pLatchOut = Abc_ObjFanout0(pLatch); + assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) ); + // mark the latch as reused + Abc_NodeSetTravIdCurrent( pLatch ); + assert( !Abc_ObjFanin0(pLatchIn)->fMarkA ); + } + else + { + pLatchOut = Abc_NtkCreateBo(pNtk); + pLatch = Abc_NtkCreateLatch(pNtk); + pLatchIn = Abc_NtkCreateBi(pNtk); + Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" ); + Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" ); + // connect + Abc_ObjAddFanin( pLatchOut, pLatch ); + Abc_ObjAddFanin( pLatch, pLatchIn ); + if ( fForward ) + { + pLatch->pData = (void *)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO); + // redirect edges to the unvisited fanouts of the node + Abc_NodeCollectFanouts( pObj, vNodes ); + Vec_PtrForEachEntry( vNodes, pNext, k ) + if ( !pNext->fMarkA ) + Abc_ObjPatchFanin( pNext, pObj, pLatchOut ); + } + else + { + // redirect edges to the visited fanouts of the node + Abc_NodeCollectFanouts( pObj, vNodes ); + Vec_PtrForEachEntry( vNodes, pNext, k ) + if ( pNext->fMarkA ) + Abc_ObjPatchFanin( pNext, pObj, pLatchOut ); + } + // connect latch to the node + Abc_ObjAddFanin( pLatchIn, pObj ); + } + Vec_PtrPush( vCis, pLatchOut ); + Vec_PtrPush( vBoxesNew, pLatch ); + Vec_PtrPush( vCos, pLatchIn ); + } + Vec_PtrFree( vNodes ); + // remove buffers + Vec_PtrForEachEntry( vBuffers, pObj, i ) + { + Abc_ObjTransferFanout( pObj, Abc_ObjFanin0(pObj) ); + Abc_NtkDeleteObj( pObj ); + } + Vec_PtrFree( vBuffers ); + // remove useless latches + Vec_PtrForEachEntry( vBoxes, pObj, i ) + { + if ( !Abc_ObjIsLatch(pObj) ) + continue; + if ( Abc_NodeIsTravIdCurrent(pObj) ) + continue; + pLatchOut = Abc_ObjFanout0(pObj); + pLatch = pObj; + pLatchIn = Abc_ObjFanin0(pObj); + if ( Abc_ObjFanoutNum(pLatchOut) > 0 ) + Abc_ObjTransferFanout( pLatchOut, Abc_ObjFanin0(pLatchIn) ); + Abc_NtkDeleteObj( pLatchOut ); + Abc_NtkDeleteObj( pObj ); + Abc_NtkDeleteObj( pLatchIn ); + } + // set the arrays + pNtk->vCis = vCis; + pNtk->vCos = vCos; + pNtk->vBoxes = vBoxesNew; + Vec_PtrFree( vBoxes ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/ret/retCore.c b/abc70930/src/opt/ret/retCore.c new file mode 100644 index 00000000..47b2cbbc --- /dev/null +++ b/abc70930/src/opt/ret/retCore.c @@ -0,0 +1,132 @@ +/**CFile**************************************************************** + + FileName [retCore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Retiming package.] + + Synopsis [The core retiming procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Oct 31, 2006.] + + Revision [$Id: retCore.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "retInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +int timeRetime = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Implementation of retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose ) +{ + int nLatches = Abc_NtkLatchNum(pNtk); + int nLevels = Abc_NtkLevel(pNtk); + int RetValue = 0, clkTotal = clock(); + int nNodesOld, nLatchesOld; + assert( Mode > 0 && Mode < 7 ); + assert( !fForwardOnly || !fBackwardOnly ); + + // cleanup the network + nNodesOld = Abc_NtkNodeNum(pNtk); + nLatchesOld = Abc_NtkLatchNum(pNtk); + Abc_NtkCleanupSeq(pNtk, 0, 0, 0); + if ( nNodesOld > Abc_NtkNodeNum(pNtk) || nLatchesOld > Abc_NtkLatchNum(pNtk) ) + printf( "Cleanup before retiming removed %d dangling nodes and %d dangling latches.\n", + nNodesOld - Abc_NtkNodeNum(pNtk), nLatchesOld - Abc_NtkLatchNum(pNtk) ); + + // perform retiming + switch ( Mode ) + { + case 1: // forward + RetValue = Abc_NtkRetimeIncremental( pNtk, 1, 0, 0, fVerbose ); + break; + case 2: // backward + RetValue = Abc_NtkRetimeIncremental( pNtk, 0, 0, 0, fVerbose ); + break; + case 3: // min-area + RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose ); + break; + case 4: // min-delay + if ( !fBackwardOnly ) + RetValue += Abc_NtkRetimeIncremental( pNtk, 1, 1, fOneStep, fVerbose ); + if ( !fForwardOnly ) + RetValue += Abc_NtkRetimeIncremental( pNtk, 0, 1, fOneStep, fVerbose ); + break; + case 5: // min-area + min-delay + RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose ); + if ( !fBackwardOnly ) + RetValue += Abc_NtkRetimeIncremental( pNtk, 1, 1, 0, fVerbose ); + if ( !fForwardOnly ) + RetValue += Abc_NtkRetimeIncremental( pNtk, 0, 1, 0, fVerbose ); + break; + case 6: // Pan's algorithm + RetValue = Abc_NtkRetimeLValue( pNtk, 500, fVerbose ); + break; + default: + printf( "Unknown retiming option.\n" ); + break; + } + if ( fVerbose ) + { + printf( "Reduction in area = %3d. Reduction in delay = %3d. ", + nLatches - Abc_NtkLatchNum(pNtk), nLevels - Abc_NtkLevel(pNtk) ); + PRT( "Total runtime", clock() - clkTotal ); + } + timeRetime = clock() - clkTotal; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Used for automated debugging.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk ) +{ + extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ); + Abc_Ntk_t * pNtkRet; + assert( Abc_NtkIsLogic(pNtk) ); + Abc_NtkToSop( pNtk, 0 ); +// if ( !Abc_NtkCheck( pNtk ) ) +// fprintf( stdout, "Abc_NtkRetimeDebug(): Network check has failed.\n" ); +// Io_WriteBlifLogic( pNtk, "debug_temp.blif", 1 ); + pNtkRet = Abc_NtkDup( pNtk ); + Abc_NtkRetime( pNtkRet, 3, 0, 1, 0, 0 ); // debugging backward flow + return !Abc_NtkSecFraig( pNtk, pNtkRet, 10000, 3, 0 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/ret/retDelay.c b/abc70930/src/opt/ret/retDelay.c new file mode 100644 index 00000000..bcfe3a2e --- /dev/null +++ b/abc70930/src/opt/ret/retDelay.c @@ -0,0 +1,305 @@ +/**CFile**************************************************************** + + FileName [retDelay.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Retiming package.] + + Synopsis [Incremental retiming for optimum delay.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Oct 31, 2006.] + + Revision [$Id: retDelay.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "retInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose ); +static int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical ); +static int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Retimes incrementally for minimum delay.] + + Description [This procedure cannot be called in the application code + because it assumes that the network is preprocessed by removing LIs/LOs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nIterLimit, int fForward, int fVerbose ) +{ + int IterBest, DelayBest; + int IterBest2, DelayBest2; + // try to find the best delay iteration on a copy + DelayBest = Abc_NtkRetimeMinDelayTry( pNtkCopy, fForward, 0, nIterLimit, &IterBest, fVerbose ); + if ( IterBest == 0 ) + return 1; + // perform the given number of iterations on the original network + DelayBest2 = Abc_NtkRetimeMinDelayTry( pNtk, fForward, 1, IterBest, &IterBest2, fVerbose ); + assert( DelayBest == DelayBest2 ); + assert( IterBest == IterBest2 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns the best delay and the number of best iteration.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew = NULL; + Vec_Ptr_t * vCritical; + Vec_Int_t * vValues; + Abc_Obj_t * pObj; + int i, k, IterBest, DelayCur, DelayBest, DelayStart, LatchesBest; + // transfer intitial values + if ( fInitial ) + { + if ( fForward ) + Abc_NtkRetimeTranferToCopy( pNtk ); + else + { + // save initial value of the latches + vValues = Abc_NtkRetimeCollectLatchValues( pNtk ); + // start the network for initial value computation + pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk ); + } + } + +if ( fVerbose && !fInitial ) + printf( "Performing analysis:\n" ); + // find the best iteration + DelayBest = ABC_INFINITY; IterBest = 0; LatchesBest = Abc_NtkLatchNum(pNtk); + vCritical = Vec_PtrAlloc( 100 ); + for ( i = 0; ; i++ ) + { + // perform moves for the timing-critical nodes + DelayCur = Abc_NtkRetimeTiming( pNtk, fForward, vCritical ); + if ( i == 0 ) + DelayStart = DelayCur; + // record this position if it has the best delay + if ( DelayBest > DelayCur ) + { +if ( fVerbose && !fInitial ) + printf( "%s Iter = %3d. Delay = %3d. Latches = %5d. Delta = %6.2f. Ratio = %4.2f %%\n", + fForward ? "Fwd": "Bwd", i, DelayCur, Abc_NtkLatchNum(pNtk), + 1.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/(DelayBest-DelayCur), + 100.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/Abc_NtkLatchNum(pNtk)/(DelayBest-DelayCur) ); + + DelayBest = DelayCur; + IterBest = i; + LatchesBest = Abc_NtkLatchNum(pNtk); + } + // quit after timing analysis + if ( i == nIterLimit ) + break; + // skip if 10 interations did not give improvement + if ( i - IterBest > 20 ) + break; + // try retiming to improve the delay + Vec_PtrForEachEntry( vCritical, pObj, k ) + if ( Abc_NtkRetimeNodeIsEnabled(pObj, fForward) ) + Abc_NtkRetimeNode( pObj, fForward, fInitial ); + // share latches + if ( !fForward ) + Abc_NtkRetimeShareLatches( pNtk, fInitial ); + } + Vec_PtrFree( vCritical ); + // transfer the initial state back to the latches + if ( fInitial ) + { + if ( fForward ) + Abc_NtkRetimeTranferFromCopy( pNtk ); + else + { + Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose ); + Abc_NtkDelete( pNtkNew ); + Vec_IntFree( vValues ); + } + } +if ( fVerbose && !fInitial ) + printf( "%s : Starting delay = %3d. Final delay = %3d. IterBest = %2d (out of %2d).\n", + fForward? "Forward " : "Backward", DelayStart, DelayBest, IterBest, nIterLimit ); + *pIterBest = (nIterLimit == 1) ? 1 : IterBest; + return DelayBest; +} + +/**Function************************************************************* + + Synopsis [Returns the set of timing-critical nodes.] + + Description [Performs static timing analysis on the network. Uses + unit-delay model.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical ) +{ + Vec_Ptr_t * vLatches; + Abc_Obj_t * pObj, * pNext; + int i, k, LevelCur, LevelMax = 0; + // mark all objects except nodes + Abc_NtkIncrementTravId(pNtk); + vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + Vec_PtrPush( vLatches, pObj ); + if ( Abc_ObjIsNode(pObj) ) + continue; + pObj->Level = 0; + Abc_NodeSetTravIdCurrent( pObj ); + } + // perform analysis from CIs/COs + if ( fForward ) + { + Vec_PtrForEachEntry( vLatches, pObj, i ) + { + Abc_ObjForEachFanout( pObj, pNext, k ) + { + LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + } + Abc_NtkForEachPi( pNtk, pObj, i ) + { + Abc_ObjForEachFanout( pObj, pNext, k ) + { + LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + } + } + else + { + Vec_PtrForEachEntry( vLatches, pObj, i ) + { + LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + } + // collect timing critical nodes, which should be retimed forward/backward + Vec_PtrClear( vCritical ); + Abc_NtkIncrementTravId(pNtk); + if ( fForward ) + { + Vec_PtrForEachEntry( vLatches, pObj, i ) + { + Abc_ObjForEachFanout( pObj, pNext, k ) + { + if ( Abc_NodeIsTravIdCurrent(pNext) ) + continue; + if ( LevelMax != (int)pNext->Level ) + continue; + // new critical node + Vec_PtrPush( vCritical, pNext ); + Abc_NodeSetTravIdCurrent( pNext ); + } + } + } + else + { + Vec_PtrForEachEntry( vLatches, pObj, i ) + { + Abc_ObjForEachFanin( pObj, pNext, k ) + { + if ( Abc_NodeIsTravIdCurrent(pNext) ) + continue; + if ( LevelMax != (int)pNext->Level ) + continue; + // new critical node + Vec_PtrPush( vCritical, pNext ); + Abc_NodeSetTravIdCurrent( pNext ); + } + } + } + Vec_PtrFree( vLatches ); + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Recursively performs timing analysis.] + + Description [Performs static timing analysis on the network. Uses + unit-delay model.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward ) +{ + Abc_Obj_t * pNext; + int i, LevelCur, LevelMax = 0; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return pObj->Level; + Abc_NodeSetTravIdCurrent(pObj); + // visit the next nodes + if ( fForward ) + { + Abc_ObjForEachFanout( pObj, pNext, i ) + { + LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + } + else + { + Abc_ObjForEachFanin( pObj, pNext, i ) + { + LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + } +// printf( "Node %3d -> Level %3d.\n", pObj->Id, LevelMax + 1 ); + pObj->Level = LevelMax + 1; + return pObj->Level; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/ret/retFlow.c b/abc70930/src/opt/ret/retFlow.c new file mode 100644 index 00000000..47ee8516 --- /dev/null +++ b/abc70930/src/opt/ret/retFlow.c @@ -0,0 +1,783 @@ +/**CFile**************************************************************** + + FileName [retFlow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Implementation of maximum flow (min-area retiming).] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Oct 31, 2006.] + + Revision [$Id: retFlow.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "retInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Abc_ObjSetPath( Abc_Obj_t * pObj, Abc_Obj_t * pNext ) { pObj->pCopy = pNext; return 1; } +static inline Abc_Obj_t * Abc_ObjGetPath( Abc_Obj_t * pObj ) { return pObj->pCopy; } +static inline Abc_Obj_t * Abc_ObjGetFanoutPath( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i; + assert( Abc_ObjGetPath(pObj) ); + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( Abc_ObjGetPath(pFanout) == pObj ) + return pFanout; + return NULL; +} +static inline Abc_Obj_t * Abc_ObjGetFaninPath( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + assert( Abc_ObjGetPath(pObj) ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + if ( Abc_ObjGetPath(pFanin) == pObj ) + return pFanin; + return NULL; +} +static inline Abc_Obj_t * Abc_ObjGetPredecessorBwd( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext; + int i; + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( Abc_ObjGetPath(pNext) == pObj ) + return pNext; + Abc_ObjForEachFanin( pObj, pNext, i ) + if ( Abc_ObjGetPath(pNext) == pObj ) + return pNext; + return NULL; +} +static inline Abc_Obj_t * Abc_ObjGetPredecessorFwd( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext; + int i; + Abc_ObjForEachFanin( pObj, pNext, i ) + if ( Abc_ObjGetPath(pNext) == pObj ) + return pNext; + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( Abc_ObjGetPath(pNext) == pObj ) + return pNext; + return NULL; +} + +static int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ); +static int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ); +static int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj ); +static int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj ); +//static int Abc_NtkMaxFlowBwdPath3_rec( Abc_Obj_t * pObj ); +static int Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin ); +static Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward ); +static void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ); +static int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ); +static void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); +static void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Test-bench for the max-flow computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vMinCut; + Abc_Obj_t * pObj; + int i; + + // forward flow + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->fMarkA = 1; + Abc_NtkForEachLatch( pNtk, pObj, i ) + pObj->fMarkA = Abc_ObjFanin0(pObj)->fMarkA = 1; +// Abc_ObjFanin0(pObj)->fMarkA = 1; + vMinCut = Abc_NtkMaxFlow( pNtk, 1, 1 ); + Vec_PtrFree( vMinCut ); + Abc_NtkCleanMarkA( pNtk ); + + // backward flow + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->fMarkA = 1; + Abc_NtkForEachLatch( pNtk, pObj, i ) + pObj->fMarkA = Abc_ObjFanout0(pObj)->fMarkA = 1; +// Abc_ObjFanout0(pObj)->fMarkA = 1; + vMinCut = Abc_NtkMaxFlow( pNtk, 0, 1 ); + Vec_PtrFree( vMinCut ); + Abc_NtkCleanMarkA( pNtk ); + +} + +/**Function************************************************************* + + Synopsis [Implementation of max-flow/min-cut computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) +{ + Vec_Ptr_t * vMinCut; + Abc_Obj_t * pLatch; + int Flow, FlowCur, RetValue, i; + int clk = clock(); + int fUseDirectedFlow = 1; + + // find the max-flow + Abc_NtkCleanCopy( pNtk ); + Flow = 0; + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( fForward ) + { +// assert( !Abc_ObjFanout0(pLatch)->fMarkA ); + FlowCur = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) ); +// FlowCur = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 ); + Flow += FlowCur; + } + else + { + assert( !Abc_ObjFanin0(pLatch)->fMarkA ); + FlowCur = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) ); + Flow += FlowCur; + } + if ( FlowCur ) + Abc_NtkIncrementTravId(pNtk); + } + + if ( !fUseDirectedFlow ) + { + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( fForward ) + { + // assert( !Abc_ObjFanout0(pLatch)->fMarkA ); + FlowCur = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) ); + Flow += FlowCur; + } + else + { + assert( !Abc_ObjFanin0(pLatch)->fMarkA ); + FlowCur = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) ); + Flow += FlowCur; + } + if ( FlowCur ) + Abc_NtkIncrementTravId(pNtk); + } + } +// Abc_NtkMaxFlowPrintFlow( pNtk, fForward ); + + // mark the nodes reachable from the latches + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( fForward ) + { +// assert( !Abc_ObjFanout0(pLatch)->fMarkA ); + if ( fUseDirectedFlow ) + RetValue = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) ); +// RetValue = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 ); + else + RetValue = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) ); + } + else + { + assert( !Abc_ObjFanin0(pLatch)->fMarkA ); + if ( fUseDirectedFlow ) + RetValue = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) ); + else + RetValue = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) ); + } + assert( RetValue == 0 ); + } + + // find the min-cut with the smallest volume + vMinCut = Abc_NtkMaxFlowMinCut( pNtk, fForward ); + // verify the cut + if ( !Abc_NtkMaxFlowVerifyCut(pNtk, vMinCut, fForward) ) + printf( "Abc_NtkMaxFlow() error! The computed min-cut is not a cut!\n" ); + // make the cut retimable + Abc_NtkMaxFlowMinCutUpdate( pNtk, vMinCut, fForward ); + + // report the results + if ( fVerbose ) + { + printf( "L = %6d. %s max-flow = %6d. Min-cut = %6d. ", + Abc_NtkLatchNum(pNtk), fForward? "Forward " : "Backward", Flow, Vec_PtrSize(vMinCut) ); +PRT( "Time", clock() - clk ); + } + +// Abc_NtkMaxFlowPrintCut( pNtk, vMinCut ); + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Tries to find an augmenting path originating in this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext, * pPred; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + // get the predecessor + pPred = Abc_ObjGetPredecessorBwd( pObj ); + // process node without flow + if ( !Abc_ObjGetPath(pObj) ) + { + // start the path if we reached a terminal node + if ( pObj->fMarkA ) + return Abc_ObjSetPath( pObj, (void *)1 ); + // explore the fanins + Abc_ObjForEachFanin( pObj, pNext, i ) + if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) ) + return Abc_ObjSetPath( pObj, pNext ); + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) ) + return Abc_ObjSetPath( pObj, pNext ); + return 0; + } + // pObj has flow - find the fanout with flow + if ( pPred == NULL ) + return 0; + // go through the successors of the predecessor + Abc_ObjForEachFanin( pPred, pNext, i ) + if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) ) + return Abc_ObjSetPath( pPred, pNext ); + Abc_ObjForEachFanout( pPred, pNext, i ) + if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) ) + return Abc_ObjSetPath( pPred, pNext ); + // try the fanout + if ( Abc_NtkMaxFlowBwdPath_rec( pPred ) ) + return Abc_ObjSetPath( pPred, NULL ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Tries to find an augmenting path originating in this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext, * pPred; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + // get the predecessor + pPred = Abc_ObjGetPredecessorFwd( pObj ); + // process node without flow + if ( !Abc_ObjGetPath(pObj) ) + { + // start the path if we reached a terminal node + if ( pObj->fMarkA ) + return Abc_ObjSetPath( pObj, (void *)1 ); + // explore the fanins + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) ) + return Abc_ObjSetPath( pObj, pNext ); + Abc_ObjForEachFanin( pObj, pNext, i ) + if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) ) + return Abc_ObjSetPath( pObj, pNext ); + return 0; + } + // pObj has flow - find the fanout with flow + if ( pPred == NULL ) + return 0; + // go through the successors of the predecessor + Abc_ObjForEachFanout( pPred, pNext, i ) + if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) ) + return Abc_ObjSetPath( pPred, pNext ); + Abc_ObjForEachFanin( pPred, pNext, i ) + if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) ) + return Abc_ObjSetPath( pPred, pNext ); + // try the fanout + if ( Abc_NtkMaxFlowFwdPath_rec( pPred ) ) + return Abc_ObjSetPath( pPred, NULL ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Tries to find an augmenting path originating in this edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin ) +{ + Abc_Obj_t * pFanin, * pFanout; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + // skip the fanin which already has flow + if ( fFanin && Abc_ObjGetPath(pPrev) ) + return 0; + // if the node has no flow, try to push through the fanouts + if ( !Abc_ObjGetPath(pObj) ) + { + // start the path if we reached a terminal node + if ( pObj->fMarkA ) + return Abc_ObjSetPath( pObj, (void *)1 ); + // try to push flow through the fanouts + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( Abc_NtkMaxFlowFwdPath3_rec(pFanout, pObj, 1) ) + return fFanin? Abc_ObjSetPath(pPrev, pObj) : 1; + } + // try to push through the fanins + Abc_ObjForEachFanin( pObj, pFanin, i ) + if ( !Abc_ObjIsLatch(pFanin) && Abc_NtkMaxFlowFwdPath3_rec(pFanin, pObj, 0) ) + return Abc_ObjSetPath( pFanin, NULL ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Tries to find an augmenting path originating in this node.] + + Description [This procedure works for directed graphs only!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout, * pFanin; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + // process node without flow + if ( !Abc_ObjGetPath(pObj) ) + { + // start the path if we reached a terminal node + if ( pObj->fMarkA ) + return Abc_ObjSetPath( pObj, (void *)1 ); + // explore the fanins + Abc_ObjForEachFanin( pObj, pFanin, i ) + if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) ) + return Abc_ObjSetPath( pObj, pFanin ); + return 0; + } + // pObj has flow - find the fanout with flow + pFanout = Abc_ObjGetFanoutPath( pObj ); + if ( pFanout == NULL ) + return 0; + // go through the fanins of the fanout with flow + Abc_ObjForEachFanin( pFanout, pFanin, i ) + if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) ) + return Abc_ObjSetPath( pFanout, pFanin ); + // try the fanout + if ( Abc_NtkMaxFlowBwdPath2_rec( pFanout ) ) + return Abc_ObjSetPath( pFanout, NULL ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Tries to find an augmenting path originating in this node.] + + Description [This procedure works for directed graphs only!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout, * pFanin; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + // process node without flow + if ( !Abc_ObjGetPath(pObj) ) + { + // start the path if we reached a terminal node + if ( pObj->fMarkA ) + return Abc_ObjSetPath( pObj, (void *)1 ); + // explore the fanins + Abc_ObjForEachFanout( pObj, pFanout, i ) + if ( Abc_NtkMaxFlowFwdPath2_rec(pFanout) ) + return Abc_ObjSetPath( pObj, pFanout ); + return 0; + } + // pObj has flow - find the fanout with flow + pFanin = Abc_ObjGetFaninPath( pObj ); + if ( pFanin == NULL ) + return 0; + // go through the fanins of the fanout with flow + Abc_ObjForEachFanout( pFanin, pFanout, i ) + if ( Abc_NtkMaxFlowFwdPath2_rec( pFanout ) ) + return Abc_ObjSetPath( pFanin, pFanout ); + // try the fanout + if ( Abc_NtkMaxFlowFwdPath2_rec( pFanin ) ) + return Abc_ObjSetPath( pFanin, NULL ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Find minimum-volume minumum cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward ) +{ + Vec_Ptr_t * vMinCut; + Abc_Obj_t * pObj; + int i; + // collect the cut nodes + vMinCut = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + // node without flow is not a cut node + if ( !Abc_ObjGetPath(pObj) ) + continue; + // unvisited node is below the cut + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + continue; + // add terminal with flow or node whose path is not visited + if ( pObj->fMarkA || !Abc_NodeIsTravIdCurrent( Abc_ObjGetPath(pObj) ) ) + Vec_PtrPush( vMinCut, pObj ); + } + return vMinCut; +} + +/**Function************************************************************* + + Synopsis [Marks the TFI cone with MarkA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMaxFlowMarkCut_rec( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pNext; + int i; + if ( pObj->fMarkA ) + return; + pObj->fMarkA = 1; + Abc_ObjForEachFanin( pObj, pNext, i ) + Abc_NtkMaxFlowMarkCut_rec( pNext ); +} + +/**Function************************************************************* + + Synopsis [Visits the TFI up to marked nodes and collects marked nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMaxFlowCollectCut_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pNext; + int i; + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return; + Abc_NodeSetTravIdCurrent(pObj); + if ( pObj->fMarkA ) + { + Vec_PtrPush( vNodes, pObj ); + return; + } + Abc_ObjForEachFanin( pObj, pNext, i ) + Abc_NtkMaxFlowCollectCut_rec( pNext, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Updates the minimum cut to be retimable.] + + Description [This procedure also labels the nodes reachable from + the latches to the cut with fMarkA.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ) +{ + Abc_Obj_t * pObj, * pNext; + int i, k; + // clean marks + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->fMarkA = 0; + // set latch outputs + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjFanout0(pObj)->fMarkA = 1; + // traverse from cut nodes + Vec_PtrForEachEntry( vMinCut, pObj, i ) + Abc_NtkMaxFlowMarkCut_rec( pObj ); + if ( fForward ) + { + // change mincut to be nodes with unmarked fanouts + Vec_PtrClear( vMinCut ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( !pObj->fMarkA ) + continue; + Abc_ObjForEachFanout( pObj, pNext, k ) + { + if ( pNext->fMarkA ) + continue; + Vec_PtrPush( vMinCut, pObj ); + break; + } + } + } + else + { + // change mincut to be marked fanins of the unmarked nodes + Vec_PtrClear( vMinCut ); + Abc_NtkIncrementTravId(pNtk); + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_NtkMaxFlowCollectCut_rec( Abc_ObjFanin0(pObj), vMinCut ); + // transfer the attribute + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->fMarkA = Abc_NodeIsTravIdCurrent(pObj); + // unmark the cut nodes + Vec_PtrForEachEntry( vMinCut, pObj, i ) + pObj->fMarkA = 0; + } +} + +/**Function************************************************************* + + Synopsis [Verifies the min-cut is indeed a cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMaxFlowVerifyCut_rec( Abc_Obj_t * pObj, int fForward ) +{ + Abc_Obj_t * pNext; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 1; + Abc_NodeSetTravIdCurrent(pObj); + // visit the node + if ( fForward ) + { + if ( Abc_ObjIsCo(pObj) ) + return 0; + // explore the fanouts + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) ) + return 0; + } + else + { + if ( Abc_ObjIsCi(pObj) ) + return 0; + // explore the fanins + Abc_ObjForEachFanin( pObj, pNext, i ) + if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies the min-cut is indeed a cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ) +{ + Abc_Obj_t * pObj; + int i; + // mark the cut with the current traversal ID + Abc_NtkIncrementTravId(pNtk); + Vec_PtrForEachEntry( vMinCut, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + // search from the latches for a path to the COs/CIs + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + if ( fForward ) + { + if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanout0(pObj), fForward ) ) + return 0; + } + else + { + if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanin0(pObj), fForward ) ) + return 0; + } + } +/* + { + // count the volume of the cut + int Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + Counter += Abc_NodeIsTravIdCurrent( pObj ); + printf( "Volume = %d.\n", Counter ); + } +*/ + return 1; +} + +/**Function************************************************************* + + Synopsis [Prints the flows.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward ) +{ + Abc_Obj_t * pLatch, * pNext, * pPrev; + int i; + if ( fForward ) + { + Vec_PtrForEachEntry( pNtk->vBoxes, pLatch, i ) + { + assert( !Abc_ObjFanout0(pLatch)->fMarkA ); + if ( Abc_ObjGetPath(Abc_ObjFanout0(pLatch)) == NULL ) // no flow through this latch + continue; + printf( "Path = " ); + for ( pNext = Abc_ObjFanout0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) ) + { + printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id ); + pPrev = pNext; + } + if ( !Abc_ObjIsPo(pPrev) ) + printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanout0(pPrev)), Abc_ObjFanout0(pPrev)->Id ); + printf( "\n" ); + } + } + else + { + Vec_PtrForEachEntry( pNtk->vBoxes, pLatch, i ) + { + assert( !Abc_ObjFanin0(pLatch)->fMarkA ); + if ( Abc_ObjGetPath(Abc_ObjFanin0(pLatch)) == NULL ) // no flow through this latch + continue; + printf( "Path = " ); + for ( pNext = Abc_ObjFanin0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) ) + { + printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id ); + pPrev = pNext; + } + if ( !Abc_ObjIsPi(pPrev) ) + printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanin0(pPrev)), Abc_ObjFanin0(pPrev)->Id ); + printf( "\n" ); + } + } +} + +/**Function************************************************************* + + Synopsis [Prints the min-cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) +{ + Abc_Obj_t * pObj; + int i; + printf( "Min-cut: " ); + Vec_PtrForEachEntry( vMinCut, pObj, i ) + printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id ); + printf( "\n" ); + printf( "Marked nodes: " ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->fMarkA ) + printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id ); + printf( "\n" ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/ret/retIncrem.c b/abc70930/src/opt/ret/retIncrem.c new file mode 100644 index 00000000..ba8104be --- /dev/null +++ b/abc70930/src/opt/ret/retIncrem.c @@ -0,0 +1,464 @@ +/**CFile**************************************************************** + + FileName [retIncrem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Retiming package.] + + Synopsis [Incremental retiming in one direction.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Oct 31, 2006.] + + Revision [$Id: retIncrem.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "retInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs retiming in one direction.] + + Description [Currently does not retime over black boxes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int fOneStep, int fVerbose ) +{ + Abc_Ntk_t * pNtkCopy = NULL; + Vec_Ptr_t * vBoxes; + st_table * tLatches; + int nLatches = Abc_NtkLatchNum(pNtk); + int nIdMaxStart = Abc_NtkObjNumMax(pNtk); + int RetValue, nIterLimit; + if ( Abc_NtkNodeNum(pNtk) == 0 ) + return 0; + // reorder CI/CO/latch inputs + Abc_NtkOrderCisCos( pNtk ); + if ( fMinDelay ) + { + nIterLimit = fOneStep? 1 : 2 * Abc_NtkLevel(pNtk); + pNtkCopy = Abc_NtkDup( pNtk ); + tLatches = Abc_NtkRetimePrepareLatches( pNtkCopy ); + st_free_table( tLatches ); + } + // collect latches and remove CIs/COs + tLatches = Abc_NtkRetimePrepareLatches( pNtk ); + // share the latches + Abc_NtkRetimeShareLatches( pNtk, 0 ); + // save boxes + vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL; + // perform the retiming + if ( fMinDelay ) + Abc_NtkRetimeMinDelay( pNtk, pNtkCopy, nIterLimit, fForward, fVerbose ); + else + Abc_NtkRetimeOneWay( pNtk, fForward, fVerbose ); + if ( fMinDelay ) + Abc_NtkDelete( pNtkCopy ); + // share the latches + Abc_NtkRetimeShareLatches( pNtk, 0 ); + // restore boxes + pNtk->vBoxes = vBoxes; + // finalize the latches + RetValue = Abc_NtkRetimeFinalizeLatches( pNtk, tLatches, nIdMaxStart ); + st_free_table( tLatches ); + if ( RetValue == 0 ) + return 0; + // fix the COs +// Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); + // check for correctness + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkRetimeForward(): Network check has failed.\n" ); + // return the number of latches saved + return nLatches - Abc_NtkLatchNum(pNtk); +} + +/**Function************************************************************* + + Synopsis [Prepares the network for retiming.] + + Description [Hash latches into their number in the original network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +st_table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk ) +{ + st_table * tLatches; + Abc_Obj_t * pLatch, * pLatchIn, * pLatchOut, * pFanin; + int i, nOffSet = Abc_NtkBoxNum(pNtk) - Abc_NtkLatchNum(pNtk); + // collect latches and remove CIs/COs + tLatches = st_init_table( st_ptrcmp, st_ptrhash ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + // map latch into its true number + st_insert( tLatches, (void *)pLatch, (void *)(i-nOffSet) ); + // disconnect LI + pLatchIn = Abc_ObjFanin0(pLatch); + pFanin = Abc_ObjFanin0(pLatchIn); + Abc_ObjTransferFanout( pLatchIn, pFanin ); + Abc_ObjDeleteFanin( pLatchIn, pFanin ); + // disconnect LO + pLatchOut = Abc_ObjFanout0(pLatch); + pFanin = Abc_ObjFanin0(pLatchOut); + if ( Abc_ObjFanoutNum(pLatchOut) > 0 ) + Abc_ObjTransferFanout( pLatchOut, pFanin ); + Abc_ObjDeleteFanin( pLatchOut, pFanin ); + } + return tLatches; +} + +/**Function************************************************************* + + Synopsis [Finalizes the latches after retiming.] + + Description [Reuses the LIs/LOs for old latches.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nIdMaxStart ) +{ + Vec_Ptr_t * vCisOld, * vCosOld, * vBoxesOld, * vCisNew, * vCosNew, * vBoxesNew; + Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut; + int i, Index; + // create new arrays + vCisOld = pNtk->vCis; pNtk->vCis = NULL; vCisNew = Vec_PtrAlloc( 100 ); + vCosOld = pNtk->vCos; pNtk->vCos = NULL; vCosNew = Vec_PtrAlloc( 100 ); + vBoxesOld = pNtk->vBoxes; pNtk->vBoxes = NULL; vBoxesNew = Vec_PtrAlloc( 100 ); + // copy boxes and their CIs/COs + Vec_PtrForEachEntryStop( vCisOld, pObj, i, Vec_PtrSize(vCisOld) - st_count(tLatches) ) + Vec_PtrPush( vCisNew, pObj ); + Vec_PtrForEachEntryStop( vCosOld, pObj, i, Vec_PtrSize(vCosOld) - st_count(tLatches) ) + Vec_PtrPush( vCosNew, pObj ); + Vec_PtrForEachEntryStop( vBoxesOld, pObj, i, Vec_PtrSize(vBoxesOld) - st_count(tLatches) ) + Vec_PtrPush( vBoxesNew, pObj ); + // go through the latches + Abc_NtkForEachObj( pNtk, pLatch, i ) + { + if ( !Abc_ObjIsLatch(pLatch) ) + continue; + if ( Abc_ObjId(pLatch) >= (unsigned)nIdMaxStart ) + { + // this is a new latch + pLatchIn = Abc_NtkCreateBi(pNtk); + pLatchOut = Abc_NtkCreateBo(pNtk); + Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" ); + Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" ); + } + else + { + // this is an old latch + // get its number in the original order + if ( !st_lookup( tLatches, (char *)pLatch, (char **)&Index ) ) + { + printf( "Abc_NtkRetimeFinalizeLatches(): Internal error.\n" ); + return 0; + } + assert( pLatch == Vec_PtrEntry(vBoxesOld, Vec_PtrSize(vBoxesOld) - st_count(tLatches) + Index) ); + // reconnect with the old LIs/LOs + pLatchIn = Vec_PtrEntry( vCosOld, Vec_PtrSize(vCosOld) - st_count(tLatches) + Index ); + pLatchOut = Vec_PtrEntry( vCisOld, Vec_PtrSize(vCisOld) - st_count(tLatches) + Index ); + } + // connect + Abc_ObjAddFanin( pLatchIn, Abc_ObjFanin0(pLatch) ); + Abc_ObjPatchFanin( pLatch, Abc_ObjFanin0(pLatch), pLatchIn ); + if ( Abc_ObjFanoutNum(pLatch) > 0 ) + Abc_ObjTransferFanout( pLatch, pLatchOut ); + Abc_ObjAddFanin( pLatchOut, pLatch ); + // add to the arrays + Vec_PtrPush( vCisNew, pLatchOut ); + Vec_PtrPush( vCosNew, pLatchIn ); + Vec_PtrPush( vBoxesNew, pLatch ); + } + // free useless Cis/Cos + Vec_PtrForEachEntry( vCisOld, pObj, i ) + if ( !Abc_ObjIsPi(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 ) + Abc_NtkDeleteObj(pObj); + Vec_PtrForEachEntry( vCosOld, pObj, i ) + if ( !Abc_ObjIsPo(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 ) + Abc_NtkDeleteObj(pObj); + // set the new arrays + pNtk->vCis = vCisNew; Vec_PtrFree( vCisOld ); + pNtk->vCos = vCosNew; Vec_PtrFree( vCosOld ); + pNtk->vBoxes = vBoxesNew; Vec_PtrFree( vBoxesOld ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs retiming one way, forward or backward.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew; + Vec_Int_t * vValues; + Abc_Obj_t * pObj; + int i, fChanges, nTotalMoves = 0, nTotalMovesLimit = 10000; + if ( fForward ) + Abc_NtkRetimeTranferToCopy( pNtk ); + else + { + // save initial values of the latches + vValues = Abc_NtkRetimeCollectLatchValues( pNtk ); + // start the network for initial value computation + pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk ); + } + // try to move latches forward whenever possible + do { + fChanges = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( !Abc_ObjIsNode(pObj) ) + continue; + if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) ) + { + Abc_NtkRetimeNode( pObj, fForward, 1 ); + fChanges = 1; + nTotalMoves++; + if ( nTotalMoves >= nTotalMovesLimit ) + { + printf( "Stopped after %d latch moves.\n", nTotalMoves ); + break; + } + } + } + } while ( fChanges && nTotalMoves < nTotalMovesLimit ); + // transfer the initial state back to the latches + if ( fForward ) + Abc_NtkRetimeTranferFromCopy( pNtk ); + else + { + Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose ); + Abc_NtkDelete( pNtkNew ); + Vec_IntFree( vValues ); + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if retiming forward/backward is possible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward ) +{ + Abc_Obj_t * pNext; + int i; + assert( Abc_ObjIsNode(pObj) ); + if ( fForward ) + { + Abc_ObjForEachFanin( pObj, pNext, i ) + if ( !Abc_ObjIsLatch(pNext) ) + return 0; + } + else + { + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( !Abc_ObjIsLatch(pNext) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Retimes the node backward or forward.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial ) +{ + Abc_Ntk_t * pNtkNew = NULL; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNext, * pLatch; + int i; + vNodes = Vec_PtrAlloc( 10 ); + if ( fForward ) + { + // compute the initial value + if ( fInitial ) + pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj ); + // collect fanins + Abc_NodeCollectFanins( pObj, vNodes ); + // make the node point to the fanins fanins + Vec_PtrForEachEntry( vNodes, pNext, i ) + { + assert( Abc_ObjIsLatch(pNext) ); + Abc_ObjPatchFanin( pObj, pNext, Abc_ObjFanin0(pNext) ); + if ( Abc_ObjFanoutNum(pNext) == 0 ) + Abc_NtkDeleteObj(pNext); + } + // add a new latch on top + pNext = Abc_NtkCreateLatch(pObj->pNtk); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + Abc_ObjTransferFanout( pObj, pNext ); + Abc_ObjAddFanin( pNext, pObj ); + // set the initial value + if ( fInitial ) + pNext->pCopy = pObj->pCopy; + } + else + { + // compute the initial value + if ( fInitial ) + { + pNtkNew = Abc_ObjFanout0(pObj)->pCopy->pNtk; + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanout( pObj, pNext, i ) + { + assert( Abc_ObjFaninNum(pNext->pCopy) == 0 ); + Abc_ObjAddFanin( pNext->pCopy, pObj->pCopy ); + } + } + // collect fanouts + Abc_NodeCollectFanouts( pObj, vNodes ); + // make the fanouts fanouts point to the node + Vec_PtrForEachEntry( vNodes, pNext, i ) + { + assert( Abc_ObjIsLatch(pNext) ); + Abc_ObjTransferFanout( pNext, pObj ); + Abc_NtkDeleteObj( pNext ); + } + // add new latches to the fanins + Abc_ObjForEachFanin( pObj, pNext, i ) + { + pLatch = Abc_NtkCreateLatch(pObj->pNtk); + Abc_ObjPatchFanin( pObj, pNext, pLatch ); + Abc_ObjAddFanin( pLatch, pNext ); + // create buffer isomorphic to this latch + if ( fInitial ) + { + pLatch->pCopy = Abc_NtkCreateNodeBuf( pNtkNew, NULL ); + Abc_ObjAddFanin( pObj->pCopy, pLatch->pCopy ); + } + } + } + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of compatible fanout latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeCheckCompatibleLatchFanouts( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanout; + int i, nLatches = 0, Init = -1; + Abc_ObjForEachFanout( pObj, pFanout, i ) + { + if ( !Abc_ObjIsLatch(pFanout) ) + continue; + if ( Init == -1 ) + { + Init = (int)pObj->pData; + nLatches++; + } + else if ( Init == (int)pObj->pData ) + nLatches++; + } + return nLatches; +} + +/**Function************************************************************* + + Synopsis [Retimes the node backward or forward.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pFanin, * pLatchTop, * pLatchCur; + int i, k; + vNodes = Vec_PtrAlloc( 10 ); + // consider latch fanins + Abc_NtkForEachObj( pNtk, pFanin, i ) + { + if ( Abc_NtkRetimeCheckCompatibleLatchFanouts(pFanin) <= 1 ) + continue; + // get the first latch + pLatchTop = NULL; + Abc_ObjForEachFanout( pFanin, pLatchTop, k ) + if ( Abc_ObjIsLatch(pLatchTop) ) + break; + assert( pLatchTop && Abc_ObjIsLatch(pLatchTop) ); + // redirect compatible fanout latches to the first latch + Abc_NodeCollectFanouts( pFanin, vNodes ); + Vec_PtrForEachEntry( vNodes, pLatchCur, k ) + { + if ( !Abc_ObjIsLatch(pLatchCur) ) + continue; + if ( pLatchCur == pLatchTop ) + continue; + if ( pLatchCur->pData != pLatchTop->pData ) + continue; + // connect the initial state + if ( fInitial ) + Abc_ObjAddFanin( pLatchCur->pCopy, pLatchTop->pCopy ); + // redirect the fanouts + Abc_ObjTransferFanout( pLatchCur, pLatchTop ); + Abc_NtkDeleteObj(pLatchCur); + } + } + Vec_PtrFree( vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/ret/retInit.c b/abc70930/src/opt/ret/retInit.c new file mode 100644 index 00000000..dcb71c60 --- /dev/null +++ b/abc70930/src/opt/ret/retInit.c @@ -0,0 +1,349 @@ +/**CFile**************************************************************** + + FileName [retInit.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Retiming package.] + + Synopsis [Initial state computation for backward retiming.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Oct 31, 2006.] + + Revision [$Id: retInit.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "retInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes initial values of the new latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int fVerbose ) +{ + Vec_Int_t * vSolution; + Abc_Ntk_t * pNtkMiter, * pNtkLogic; + int RetValue, clk; + if ( pNtkCone == NULL ) + return Vec_IntDup( vValues ); + // convert the target network to AIG + pNtkLogic = Abc_NtkDup( pNtkCone ); + Abc_NtkToAig( pNtkLogic ); + // get the miter + pNtkMiter = Abc_NtkCreateTarget( pNtkLogic, pNtkLogic->vCos, vValues ); + if ( fVerbose ) + printf( "The miter for initial state computation has %d AIG nodes. ", Abc_NtkNodeNum(pNtkMiter) ); + // solve the miter + clk = clock(); + RetValue = Abc_NtkMiterSat( pNtkMiter, (sint64)500000, (sint64)50000000, 0, NULL, NULL ); + if ( fVerbose ) + { PRT( "SAT solving time", clock() - clk ); } + // analyze the result + if ( RetValue == 1 ) + printf( "Abc_NtkRetimeInitialValues(): The problem is unsatisfiable. DC latch values are used.\n" ); + else if ( RetValue == -1 ) + printf( "Abc_NtkRetimeInitialValues(): The SAT problem timed out. DC latch values are used.\n" ); + else if ( !Abc_NtkRetimeVerifyModel( pNtkCone, vValues, pNtkMiter->pModel ) ) + printf( "Abc_NtkRetimeInitialValues(): The computed counter-example is incorrect.\n" ); + // set the values of the latches + vSolution = RetValue? NULL : Vec_IntAllocArray( pNtkMiter->pModel, Abc_NtkPiNum(pNtkLogic) ); + pNtkMiter->pModel = NULL; + Abc_NtkDelete( pNtkMiter ); + Abc_NtkDelete( pNtkLogic ); + return vSolution; +} + +/**Function************************************************************* + + Synopsis [Computes the results of simulating one node.] + + Description [Assumes that fanins have pCopy set to the input values.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjSopSimulate( Abc_Obj_t * pObj ) +{ + char * pCube, * pSop = pObj->pData; + int nVars, Value, v, ResOr, ResAnd, ResVar; + assert( pSop && !Abc_SopIsExorType(pSop) ); + // simulate the SOP of the node + ResOr = 0; + nVars = Abc_SopGetVarNum(pSop); + Abc_SopForEachCube( pSop, nVars, pCube ) + { + ResAnd = 1; + Abc_CubeForEachVar( pCube, Value, v ) + { + if ( Value == '0' ) + ResVar = 1 ^ ((int)Abc_ObjFanin(pObj, v)->pCopy); + else if ( Value == '1' ) + ResVar = (int)Abc_ObjFanin(pObj, v)->pCopy; + else + continue; + ResAnd &= ResVar; + } + ResOr |= ResAnd; + } + // complement the result if necessary + if ( !Abc_SopGetPhase(pSop) ) + ResOr ^= 1; + return ResOr; +} + +/**Function************************************************************* + + Synopsis [Verifies the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i, Counter = 0; + assert( Abc_NtkIsSopLogic(pNtkCone) ); + // set the PIs + Abc_NtkForEachPi( pNtkCone, pObj, i ) + pObj->pCopy = (void *)pModel[i]; + // simulate the internal nodes + vNodes = Abc_NtkDfs( pNtkCone, 0 ); + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj ); + Vec_PtrFree( vNodes ); + // compare the outputs + Abc_NtkForEachPo( pNtkCone, pObj, i ) + pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; + Abc_NtkForEachPo( pNtkCone, pObj, i ) + Counter += (Vec_IntEntry(vValues, i) != (int)pObj->pCopy); + if ( Counter > 0 ) + printf( "%d outputs (out of %d) have a value mismatch.\n", Counter, Abc_NtkPoNum(pNtkCone) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Transfer latch initial values to pCopy.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjIsLatch(pObj) ) + pObj->pCopy = (void *)Abc_LatchIsInit1(pObj); +} + +/**Function************************************************************* + + Synopsis [Transfer latch initial values from pCopy.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjIsLatch(pObj) ) + pObj->pData = (void *)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO); +} + +/**Function************************************************************* + + Synopsis [Transfer latch initial values to pCopy.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vValues; + Abc_Obj_t * pObj; + int i; + vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjIsLatch(pObj) ) + Vec_IntPush( vValues, Abc_LatchIsInit1(pObj) ); + return vValues; +} + +/**Function************************************************************* + + Synopsis [Transfer latch initial values from pCopy.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ) +{ + Abc_Obj_t * pObj; + int i, Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjIsLatch(pObj) ) + pObj->pCopy = (void *)Counter++; + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjIsLatch(pObj) ) + pObj->pData = (void *)(vValues? (Vec_IntEntry(vValues,(int)pObj->pCopy)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC); +} + +/**Function************************************************************* + + Synopsis [Transfer latch initial values to pCopy.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + int i; + // create the network used for the initial state computation + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + // create POs corresponding to the initial values + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjIsLatch(pObj) ) + pObj->pCopy = Abc_NtkCreatePo(pNtkNew); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transfer latch initial values to pCopy.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose ) +{ + Vec_Int_t * vValuesNew; + Abc_Obj_t * pObj; + int i; + // create PIs corresponding to the initial values + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjIsLatch(pObj) ) + Abc_ObjAddFanin( pObj->pCopy, Abc_NtkCreatePi(pNtkNew) ); + // assign dummy node names + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + // check the network + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkRetimeBackwardInitialFinish(): Network check has failed.\n" ); + // derive new initial values + vValuesNew = Abc_NtkRetimeInitialValues( pNtkNew, vValuesOld, fVerbose ); + // insert new initial values + Abc_NtkRetimeInsertLatchValues( pNtk, vValuesNew ); + if ( vValuesNew ) Vec_IntFree( vValuesNew ); +} + + +/**Function************************************************************* + + Synopsis [Cycles the circuit to create a new initial state.] + + Description [Simulates the circuit with random input for the given + number of timeframes to get a better initial state.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i, f; + assert( Abc_NtkIsSopLogic(pNtk) ); + srand( 0x12341234 ); + // initialize the values + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = (void *)(rand() & 1); + Abc_NtkForEachLatch( pNtk, pObj, i ) + pObj->pCopy = (void *)Abc_LatchIsInit1(pObj); + // simulate for the given number of timeframes + vNodes = Abc_NtkDfs( pNtk, 0 ); + for ( f = 0; f < nFrames; f++ ) + { + // simulate internal nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj ); + // bring the results to the COs + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; + // assign PI values + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = (void *)(rand() & 1); + // transfer the latch values + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjFanout0(pObj)->pCopy = Abc_ObjFanin0(pObj)->pCopy; + } + Vec_PtrFree( vNodes ); + // set the final values + Abc_NtkForEachLatch( pNtk, pObj, i ) + pObj->pData = (void *)(Abc_ObjFanout0(pObj)->pCopy ? ABC_INIT_ONE : ABC_INIT_ZERO); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/ret/retInt.h b/abc70930/src/opt/ret/retInt.h new file mode 100644 index 00000000..51428bce --- /dev/null +++ b/abc70930/src/opt/ret/retInt.h @@ -0,0 +1,80 @@ +/**CFile**************************************************************** + + FileName [retInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Retiming package.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Oct 31, 2006.] + + Revision [$Id: retInt.h,v 1.00 2006/10/31 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __RET_INT_H__ +#define __RET_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "abc.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== retArea.c ========================================================*/ +extern int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fVerbose ); +/*=== retCore.c ========================================================*/ +extern int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose ); +/*=== retDelay.c ========================================================*/ +extern int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nIterLimit, int fForward, int fVerbose ); +/*=== retDirect.c ========================================================*/ +extern int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int fOneStep, int fVerbose ); +extern void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial ); +extern int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward ); +extern void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial ); +extern st_table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk ); +extern int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nIdMaxStart ); +/*=== retFlow.c ========================================================*/ +extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose ); +/*=== retInit.c ========================================================*/ +extern Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkSat, Vec_Int_t * vValues, int fVerbose ); +extern int Abc_ObjSopSimulate( Abc_Obj_t * pObj ); +extern void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk ); +extern void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk ); +extern Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk ); +extern void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ); +extern Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk ); +extern void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose ); +/*=== retLvalue.c ========================================================*/ +extern int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/ret/retLvalue.c b/abc70930/src/opt/ret/retLvalue.c new file mode 100644 index 00000000..b4d9e946 --- /dev/null +++ b/abc70930/src/opt/ret/retLvalue.c @@ -0,0 +1,395 @@ +/**CFile**************************************************************** + + FileName [retLvalue.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Retiming package.] + + Synopsis [Implementation of Pan's retiming algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Oct 31, 2006.] + + Revision [$Id: retLvalue.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "retInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// node status after updating its arrival time +enum { ABC_RET_UPDATE_FAIL, ABC_RET_UPDATE_NO, ABC_RET_UPDATE_YES }; + +// the internal procedures +static Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ); +static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose ); +static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose ); +static int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi ); +static int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi ); +static Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk ); +static int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose ); + +static inline int Abc_NodeComputeLag( int LValue, int Fi ) { return (LValue + (1<<16)*Fi)/Fi - (1<<16) - (int)(LValue % Fi == 0); } +static inline int Abc_NodeGetLValue( Abc_Obj_t * pNode ) { return (int)pNode->pCopy; } +static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { pNode->pCopy = (void *)Value; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Implements Pan's retiming algorithm.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ) +{ + Vec_Int_t * vLags; + int nLatches = Abc_NtkLatchNum(pNtk); + assert( Abc_NtkIsLogic( pNtk ) ); + // get the lags + vLags = Abc_NtkRetimeGetLags( pNtk, nIterLimit, fVerbose ); + // compute the retiming +// Abc_NtkRetimeUsingLags( pNtk, vLags, fVerbose ); + Vec_IntFree( vLags ); + // fix the COs +// Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); + // check for correctness + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkRetimeLValue(): Network check has failed.\n" ); + // return the number of latches saved + return nLatches - Abc_NtkLatchNum(pNtk); +} + +/**Function************************************************************* + + Synopsis [Computes the retiming lags.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ) +{ + Vec_Int_t * vLags; + Vec_Ptr_t * vNodes, * vLatches; + Abc_Obj_t * pNode; + int i, FiMax, FiBest, RetValue, clk, clkIter; + char NodeLag; + + // get the upper bound on the clock period + FiMax = Abc_NtkLevel(pNtk); + + // make sure this clock period is feasible + vNodes = Abc_NtkDfs( pNtk, 0 ); + vLatches = Abc_ManCollectLatches( pNtk ); + if ( !Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiMax, nIterLimit, fVerbose ) ) + { + Vec_PtrFree( vNodes ); + printf( "Abc_NtkRetimeGetLags() error: The upper bound on the clock period cannot be computed.\n" ); + return Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); + } + + // search for the optimal clock period between 0 and nLevelMax +clk = clock(); + FiBest = Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, 0, FiMax, nIterLimit, fVerbose ); +clkIter = clock() - clk; + + // recompute the best l-values + RetValue = Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiBest, nIterLimit, fVerbose ); + assert( RetValue ); + + // fix the problem with non-converged delays + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( Abc_NodeGetLValue(pNode) < -ABC_INFINITY/2 ) + Abc_NodeSetLValue( pNode, 0 ); + + // write the retiming lags + vLags = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + NodeLag = Abc_NodeComputeLag( Abc_NodeGetLValue(pNode), FiBest ); + Vec_IntWriteEntry( vLags, pNode->Id, NodeLag ); + } +/* + Abc_NtkForEachPo( pNtk, pNode, i ) + printf( "%d ", Abc_NodeGetLValue(Abc_ObjFanin0(pNode)) ); + printf( "\n" ); + Abc_NtkForEachLatch( pNtk, pNode, i ) + printf( "%d/%d ", Abc_NodeGetLValue(Abc_ObjFanout0(pNode)), Abc_NodeGetLValue(Abc_ObjFanout0(pNode)) + FiBest ); + printf( "\n" ); +*/ + + // print the result +// if ( fVerbose ) + printf( "The best clock period is %3d. (Currently, network is not modified.)\n", FiBest ); +/* + { + FILE * pTable; + pTable = fopen( "iscas/seqmap__stats2.txt", "a+" ); + fprintf( pTable, "%d ", FiBest ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ + Vec_PtrFree( vNodes ); + Vec_PtrFree( vLatches ); + return vLags; +} + +/**Function************************************************************* + + Synopsis [Performs binary search for the optimal clock period.] + + Description [Assumes that FiMin is infeasible while FiMax is feasible.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose ) +{ + int Median; + assert( FiMin < FiMax ); + if ( FiMin + 1 == FiMax ) + return FiMax; + Median = FiMin + (FiMax - FiMin)/2; + if ( Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, Median, nMaxIters, fVerbose ) ) + return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, FiMin, Median, nMaxIters, fVerbose ); // Median is feasible + else + return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, Median, FiMax, nMaxIters, fVerbose ); // Median is infeasible +} + +/**Function************************************************************* + + Synopsis [Returns 1 if retiming with this clock period is feasible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose ) +{ + Abc_Obj_t * pObj; + int c, i, fConverged; + // set l-values of all nodes to be minus infinity, except PIs and constants + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjFaninNum(pObj) == 0 ) + Abc_NodeSetLValue( pObj, 0 ); + else + Abc_NodeSetLValue( pObj, -ABC_INFINITY ); + // update all values iteratively + fConverged = 0; + for ( c = 1; c <= nMaxIters; c++ ) + { + if ( !Abc_NtkRetimeUpdateLValue( pNtk, vNodes, vLatches, Fi ) ) + { + fConverged = 1; + break; + } + if ( Abc_NtkRetimePosOverLimit(pNtk, Fi) ) + break; + } + // report the results + if ( fVerbose ) + { + if ( !fConverged ) + printf( "Period = %3d. Iterations = %3d. Infeasible %s\n", Fi, c, (c > nMaxIters)? "(timeout)" : "" ); + else + printf( "Period = %3d. Iterations = %3d. Feasible\n", Fi, c ); + } +/* + // check if any AND gates have infinite delay + Counter = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + Counter += (Abc_NodeGetLValue(pObj) < -ABC_INFINITY/2); + if ( Counter > 0 ) + printf( "Warning: %d internal nodes have wrong l-values!\n", Counter ); +*/ + return fConverged; +} + +/**Function************************************************************* + + Synopsis [Performs one iteration of l-value computation for the nodes.] + + Description [Experimentally it was found that checking POs changes + is not enough to detect the convergence of l-values in the network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k, lValueNew, fChange; + // go through the nodes and detect change + fChange = 0; + Vec_PtrForEachEntry( vNodes, pObj, i ) + { + assert( Abc_ObjIsNode(pObj) ); + lValueNew = -ABC_INFINITY; + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( lValueNew < Abc_NodeGetLValue(pFanin) ) + lValueNew = Abc_NodeGetLValue(pFanin); + } + lValueNew++; + if ( Abc_NodeGetLValue(pObj) < lValueNew ) + { + Abc_NodeSetLValue( pObj, lValueNew ); + fChange = 1; + } + } + // propagate values through the latches + Vec_PtrForEachEntry( vLatches, pObj, i ) + Abc_NodeSetLValue( Abc_ObjFanout0(pObj), Abc_NodeGetLValue(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) - Fi ); + return fChange; +} + +/**Function************************************************************* + + Synopsis [Detects the case when l-values exceeded the limit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachPo( pNtk, pObj, i ) + if ( Abc_NodeGetLValue(Abc_ObjFanin0(pObj)) > Fi ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Collects latches in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ManCollectLatches_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLatches ) +{ + Abc_Obj_t * pDriver; + if ( !Abc_ObjIsLatch(pObj) ) + return; + // skip already collected latches + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return; + Abc_NodeSetTravIdCurrent(pObj); + // get the driver node feeding into the latch + pDriver = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); + // call recursively if the driver looks like a latch output + if ( Abc_ObjIsBo(pDriver) ) + Abc_ManCollectLatches_rec( Abc_ObjFanin0(pDriver), vLatches ); + // collect the latch + Vec_PtrPush( vLatches, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects latches in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vLatches; + Abc_Obj_t * pObj; + int i; + vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ManCollectLatches_rec( pObj, vLatches ); + assert( Vec_PtrSize(vLatches) == Abc_NtkLatchNum(pNtk) ); + return vLatches; +} + +/**Function************************************************************* + + Synopsis [Implements the retiming given as the array of retiming lags.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose ) +{ + Abc_Obj_t * pObj; + int fChanges, fForward, nTotalMoves, Lag, Counter, i; + // iterate over the nodes + nTotalMoves = 0; + do { + fChanges = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Lag = Vec_IntEntry( vLags, pObj->Id ); + if ( !Lag ) + continue; + fForward = (Lag < 0); + if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) ) + { + Abc_NtkRetimeNode( pObj, fForward, 0 ); + fChanges = 1; + nTotalMoves++; + Vec_IntAddToEntry( vLags, pObj->Id, fForward? 1 : -1 ); + } + } + } while ( fChanges ); + if ( fVerbose ) + printf( "Total latch moves = %d.\n", nTotalMoves ); + // check if there are remaining lags + Counter = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + Counter += (Vec_IntEntry( vLags, pObj->Id ) != 0); + if ( Counter ) + printf( "Warning! The number of nodes with unrealized lag = %d.\n", Counter ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/ret/ret_.c b/abc70930/src/opt/ret/ret_.c new file mode 100644 index 00000000..89625e17 --- /dev/null +++ b/abc70930/src/opt/ret/ret_.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [ret_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Retiming package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - Oct 31, 2006.] + + Revision [$Id: ret_.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "retInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/rwr/module.make b/abc70930/src/opt/rwr/module.make new file mode 100644 index 00000000..077a3c01 --- /dev/null +++ b/abc70930/src/opt/rwr/module.make @@ -0,0 +1,7 @@ +SRC += src/opt/rwr/rwrDec.c \ + src/opt/rwr/rwrEva.c \ + src/opt/rwr/rwrExp.c \ + src/opt/rwr/rwrLib.c \ + src/opt/rwr/rwrMan.c \ + src/opt/rwr/rwrPrint.c \ + src/opt/rwr/rwrUtil.c diff --git a/abc70930/src/opt/rwr/rwr.h b/abc70930/src/opt/rwr/rwr.h new file mode 100644 index 00000000..f24f9535 --- /dev/null +++ b/abc70930/src/opt/rwr/rwr.h @@ -0,0 +1,169 @@ +/**CFile**************************************************************** + + FileName [rwr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __RWR_H__ +#define __RWR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "abc.h" +#include "cut.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +#define RWR_LIMIT 1048576/4 // ((1 << 20) + +typedef struct Rwr_Man_t_ Rwr_Man_t; +typedef struct Rwr_Node_t_ Rwr_Node_t; + +struct Rwr_Man_t_ +{ + // internal lookups + int nFuncs; // number of four var functions + unsigned short * puCanons; // canonical forms + char * pPhases; // canonical phases + char * pPerms; // canonical permutations + unsigned char * pMap; // mapping of functions into class numbers + unsigned short * pMapInv; // mapping of classes into functions + char * pPractical; // practical NPN classes + char ** pPerms4; // four-var permutations + // node space + Vec_Ptr_t * vForest; // all the nodes + Rwr_Node_t ** pTable; // the hash table of nodes by their canonical form + Vec_Vec_t * vClasses; // the nodes of the equivalence classes + Extra_MmFixed_t * pMmNode; // memory for nodes and cuts + // statistical variables + int nTravIds; // the counter of traversal IDs + int nConsidered; // the number of nodes considered + int nAdded; // the number of nodes added to lists + int nClasses; // the number of NN classes + // the result of resynthesis + int fCompl; // indicates if the output of FF should be complemented + void * pGraph; // the decomposition tree (temporary) + Vec_Ptr_t * vFanins; // the fanins array (temporary) + Vec_Ptr_t * vFaninsCur; // the fanins array (temporary) + Vec_Int_t * vLevNums; // the array of levels (temporary) + Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary) + // node statistics + int nNodesConsidered; + int nNodesRewritten; + int nNodesGained; + int nNodesBeg; + int nNodesEnd; + int nScores[222]; + int nCutsGood; + int nCutsBad; + int nSubgraphs; + // runtime statistics + int timeStart; + int timeCut; + int timeRes; + int timeEval; + int timeMffc; + int timeUpdate; + int timeTotal; +}; + +struct Rwr_Node_t_ // 24 bytes +{ + int Id; // ID + int TravId; // traversal ID + short nScore; + short nGain; + short nAdded; + unsigned uTruth : 16; // truth table + unsigned Volume : 8; // volume + unsigned Level : 6; // level + unsigned fUsed : 1; // mark + unsigned fExor : 1; // mark + Rwr_Node_t * p0; // first child + Rwr_Node_t * p1; // second child + Rwr_Node_t * pNext; // next in the table +}; + +// manipulation of complemented attributes +static inline bool Rwr_IsComplement( Rwr_Node_t * p ) { return (bool)(((unsigned long)p) & 01); } +static inline Rwr_Node_t * Rwr_Regular( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned long)(p) & ~01); } +static inline Rwr_Node_t * Rwr_Not( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned long)(p) ^ 01); } +static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_Node_t *)((unsigned long)(p) ^ (c)); } + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== rwrDec.c ========================================================*/ +extern void Rwr_ManPreprocess( Rwr_Man_t * p ); +/*=== rwrEva.c ========================================================*/ +extern int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable ); +extern void Rwr_ScoresClean( Rwr_Man_t * p ); +extern void Rwr_ScoresReport( Rwr_Man_t * p ); +/*=== rwrLib.c ========================================================*/ +extern void Rwr_ManPrecompute( Rwr_Man_t * p ); +extern Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute ); +extern Rwr_Node_t * Rwr_ManAddNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ); +extern int Rwr_ManNodeVolume( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 ); +extern void Rwr_ManIncTravId( Rwr_Man_t * p ); +/*=== rwrMan.c ========================================================*/ +extern Rwr_Man_t * Rwr_ManStart( bool fPrecompute ); +extern void Rwr_ManStop( Rwr_Man_t * p ); +extern void Rwr_ManPrintStats( Rwr_Man_t * p ); +extern void Rwr_ManPrintStatsFile( Rwr_Man_t * p ); +extern void * Rwr_ManReadDecs( Rwr_Man_t * p ); +extern Vec_Ptr_t * Rwr_ManReadLeaves( Rwr_Man_t * p ); +extern int Rwr_ManReadCompl( Rwr_Man_t * p ); +extern void Rwr_ManAddTimeCuts( Rwr_Man_t * p, int Time ); +extern void Rwr_ManAddTimeUpdate( Rwr_Man_t * p, int Time ); +extern void Rwr_ManAddTimeTotal( Rwr_Man_t * p, int Time ); +/*=== rwrPrint.c ========================================================*/ +extern void Rwr_ManPrint( Rwr_Man_t * p ); +/*=== rwrUtil.c ========================================================*/ +extern void Rwr_ManWriteToArray( Rwr_Man_t * p ); +extern void Rwr_ManLoadFromArray( Rwr_Man_t * p, int fVerbose ); +extern void Rwr_ManWriteToFile( Rwr_Man_t * p, char * pFileName ); +extern void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName ); +extern void Rwr_ListAddToTail( Rwr_Node_t ** ppList, Rwr_Node_t * pNode ); +extern char * Rwr_ManGetPractical( Rwr_Man_t * p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/rwr/rwrDec.c b/abc70930/src/opt/rwr/rwrDec.c new file mode 100644 index 00000000..ef7af34f --- /dev/null +++ b/abc70930/src/opt/rwr/rwrDec.c @@ -0,0 +1,150 @@ +/**CFile**************************************************************** + + FileName [rwrDec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Evaluation and decomposition procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwrDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwr.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Dec_Graph_t * Rwr_NodePreprocess( Rwr_Man_t * p, Rwr_Node_t * pNode ); +static Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * pGraph ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Preprocesses computed library of subgraphs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManPreprocess( Rwr_Man_t * p ) +{ + Dec_Graph_t * pGraph; + Rwr_Node_t * pNode; + int i, k; + // put the nodes into the structure + p->pMapInv = ALLOC( unsigned short, 222 ); + memset( p->pMapInv, 0, sizeof(unsigned short) * 222 ); + p->vClasses = Vec_VecStart( 222 ); + for ( i = 0; i < p->nFuncs; i++ ) + { + if ( p->pTable[i] == NULL ) + continue; + // consider all implementations of this function + for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext ) + { + assert( pNode->uTruth == p->pTable[i]->uTruth ); + assert( p->pMap[pNode->uTruth] >= 0 && p->pMap[pNode->uTruth] < 222 ); + Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode ); + p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth]; + } + } + // compute decomposition forms for each node and verify them + Vec_VecForEachEntry( p->vClasses, pNode, i, k ) + { + pGraph = Rwr_NodePreprocess( p, pNode ); + pNode->pNext = (Rwr_Node_t *)pGraph; + assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) ); + } +} + +/**Function************************************************************* + + Synopsis [Preprocesses subgraphs rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Rwr_NodePreprocess( Rwr_Man_t * p, Rwr_Node_t * pNode ) +{ + Dec_Graph_t * pGraph; + Dec_Edge_t eRoot; + assert( !Rwr_IsComplement(pNode) ); + // consider constant + if ( pNode->uTruth == 0 ) + return Dec_GraphCreateConst0(); + // consider the case of elementary var + if ( pNode->uTruth == 0x00FF ) + return Dec_GraphCreateLeaf( 3, 4, 1 ); + // start the subgraphs + pGraph = Dec_GraphCreate( 4 ); + // collect the nodes + Rwr_ManIncTravId( p ); + eRoot = Rwr_TravCollect_rec( p, pNode, pGraph ); + Dec_GraphSetRoot( pGraph, eRoot ); + return pGraph; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * pGraph ) +{ + Dec_Edge_t eNode0, eNode1, eNode; + // elementary variable + if ( pNode->fUsed ) + return Dec_EdgeCreate( pNode->Id - 1, 0 ); + // previously visited node + if ( pNode->TravId == p->nTravIds ) + return Dec_IntToEdge( pNode->Volume ); + pNode->TravId = p->nTravIds; + // solve for children + eNode0 = Rwr_TravCollect_rec( p, Rwr_Regular(pNode->p0), pGraph ); + if ( Rwr_IsComplement(pNode->p0) ) + eNode0.fCompl = !eNode0.fCompl; + eNode1 = Rwr_TravCollect_rec( p, Rwr_Regular(pNode->p1), pGraph ); + if ( Rwr_IsComplement(pNode->p1) ) + eNode1.fCompl = !eNode1.fCompl; + // create the decomposition node(s) + if ( pNode->fExor ) + eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 ); + else + eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); + // save the result + pNode->Volume = Dec_EdgeToInt( eNode ); + return eNode; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/rwr/rwrEva.c b/abc70930/src/opt/rwr/rwrEva.c new file mode 100644 index 00000000..0eb547f2 --- /dev/null +++ b/abc70930/src/opt/rwr/rwrEva.c @@ -0,0 +1,588 @@ +/**CFile**************************************************************** + + FileName [rwrDec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Evaluation and decomposition procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwrDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwr.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable ); +static int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ); +static int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut ); +static int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs rewriting for one node.] + + Description [This procedure considers all the cuts computed for the node + and tries to rewrite each of them using the "forest" of different AIG + structures precomputed and stored in the RWR manager. + Determines the best rewriting and computes the gain in the number of AIG + nodes in the final network. In the end, p->vFanins contains information + about the best cut that can be used for rewriting, while p->pGraph gives + the decomposition dag (represented using decomposition graph data structure). + Returns gain in the number of nodes or -1 if node cannot be rewritten.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable ) +{ + int fVeryVerbose = 0; + Dec_Graph_t * pGraph; + Cut_Cut_t * pCut;//, * pTemp; + Abc_Obj_t * pFanin; + unsigned uPhase, uTruthBest, uTruth; + char * pPerm; + int Required, nNodesSaved, nNodesSaveCur; + int i, GainCur, GainBest = -1; + int clk, clk2;//, Counter; + + p->nNodesConsidered++; + // get the required times + Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; + + // get the node's cuts +clk = clock(); + pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 ); + assert( pCut != NULL ); +p->timeCut += clock() - clk; + +//printf( " %d", Rwr_CutCountNumNodes(pNode, pCut) ); +/* + Counter = 0; + for ( pTemp = pCut->pNext; pTemp; pTemp = pTemp->pNext ) + Counter++; + printf( "%d ", Counter ); +*/ + // go through the cuts +clk = clock(); + for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) + { + // consider only 4-input cuts + if ( pCut->nLeaves < 4 ) + continue; +// Cut_CutPrint( pCut, 0 ), printf( "\n" ); + + // get the fanin permutation + uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); + pPerm = p->pPerms4[ p->pPerms[uTruth] ]; + uPhase = p->pPhases[uTruth]; + // collect fanins with the corresponding permutation/phase + Vec_PtrClear( p->vFaninsCur ); + Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + pFanin = Abc_NtkObj( pNode->pNtk, pCut->pLeaves[pPerm[i]] ); + if ( pFanin == NULL ) + break; + pFanin = Abc_ObjNotCond(pFanin, ((uPhase & (1< 0) ); + Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); + } + if ( i != (int)pCut->nLeaves ) + { + p->nCutsBad++; + continue; + } + p->nCutsGood++; + + { + int Counter = 0; + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + if ( Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) == 1 ) + Counter++; + if ( Counter > 2 ) + continue; + } + +clk2 = clock(); +/* + printf( "Considering: (" ); + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + printf( "%d ", Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) ); + printf( ")\n" ); +*/ + // mark the fanin boundary + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Abc_ObjRegular(pFanin)->vFanouts.nSize++; + + // label MFFC with current ID + Abc_NtkIncrementTravId( pNode->pNtk ); + nNodesSaved = Abc_NodeMffcLabelAig( pNode ); + // unmark the fanin boundary + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Abc_ObjRegular(pFanin)->vFanouts.nSize--; +p->timeMffc += clock() - clk2; + + // evaluate the cut +clk2 = clock(); + pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur, fPlaceEnable ); +p->timeEval += clock() - clk2; + + // check if the cut is better than the current best one + if ( pGraph != NULL && GainBest < GainCur ) + { + // save this form + nNodesSaveCur = nNodesSaved; + GainBest = GainCur; + p->pGraph = pGraph; + p->fCompl = ((uPhase & (1<<4)) > 0); + uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut); + // collect fanins in the + Vec_PtrClear( p->vFanins ); + Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) + Vec_PtrPush( p->vFanins, pFanin ); + } + } +p->timeRes += clock() - clk; + + if ( GainBest == -1 ) + return -1; +/* + if ( GainBest > 0 ) + { + printf( "Class %d ", p->pMap[uTruthBest] ); + printf( "Gain = %d. Node %d : ", GainBest, pNode->Id ); + Vec_PtrForEachEntry( p->vFanins, pFanin, i ) + printf( "%d ", Abc_ObjRegular(pFanin)->Id ); + Dec_GraphPrint( stdout, p->pGraph, NULL, NULL ); + printf( "\n" ); + } +*/ + +// printf( "%d", nNodesSaveCur - GainBest ); +/* + if ( GainBest > 0 ) + { + if ( Rwr_CutIsBoolean( pNode, p->vFanins ) ) + printf( "b" ); + else + { + printf( "Node %d : ", pNode->Id ); + Vec_PtrForEachEntry( p->vFanins, pFanin, i ) + printf( "%d ", Abc_ObjRegular(pFanin)->Id ); + printf( "a" ); + } + } +*/ +/* + if ( GainBest > 0 ) + if ( p->fCompl ) + printf( "c" ); + else + printf( "." ); +*/ + + // copy the leaves + Vec_PtrForEachEntry( p->vFanins, pFanin, i ) + Dec_GraphNode(p->pGraph, i)->pFunc = pFanin; +/* + printf( "(" ); + Vec_PtrForEachEntry( p->vFanins, pFanin, i ) + printf( " %d", Abc_ObjRegular(pFanin)->vFanouts.nSize - 1 ); + printf( " ) " ); +*/ +// printf( "%d ", Rwr_NodeGetDepth_rec( pNode, p->vFanins ) ); + + p->nScores[p->pMap[uTruthBest]]++; + p->nNodesGained += GainBest; + if ( fUseZeros || GainBest > 0 ) + { + p->nNodesRewritten++; + } + + // report the progress + if ( fVeryVerbose && GainBest > 0 ) + { + printf( "Node %6s : ", Abc_ObjName(pNode) ); + printf( "Fanins = %d. ", p->vFanins->nSize ); + printf( "Save = %d. ", nNodesSaveCur ); + printf( "Add = %d. ", nNodesSaveCur-GainBest ); + printf( "GAIN = %d. ", GainBest ); + printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); + printf( "Class = %d. ", p->pMap[uTruthBest] ); + printf( "\n" ); + } + return GainBest; +} + +/**Function************************************************************* + + Synopsis [Evaluates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable ) +{ + Vec_Ptr_t * vSubgraphs; + Dec_Graph_t * pGraphBest, * pGraphCur; + Rwr_Node_t * pNode, * pFanin; + int nNodesAdded, GainBest, i, k; + unsigned uTruth; + float CostBest;//, CostCur; + // find the matching class of subgraphs + uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); + vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); + p->nSubgraphs += vSubgraphs->nSize; + // determine the best subgraph + GainBest = -1; + CostBest = ABC_INFINITY; + Vec_PtrForEachEntry( vSubgraphs, pNode, i ) + { + // get the current graph + pGraphCur = (Dec_Graph_t *)pNode->pNext; + // copy the leaves + Vec_PtrForEachEntry( vFaninsCur, pFanin, k ) + Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; + // detect how many unlabeled nodes will be reused + nNodesAdded = Dec_GraphToNetworkCount( pRoot, pGraphCur, nNodesSaved, LevelMax ); + if ( nNodesAdded == -1 ) + continue; + assert( nNodesSaved >= nNodesAdded ); +/* + // evaluate the cut + if ( fPlaceEnable ) + { + extern float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins ); + + float Alpha = 0.5; // ??? + float PlaceCost; + + // get the placement cost of the cut + PlaceCost = Abc_PlaceEvaluateCut( pRoot, vFaninsCur ); + + // get the weigted cost of the cut + CostCur = nNodesSaved - nNodesAdded + Alpha * PlaceCost; + + // do not allow uphill moves + if ( nNodesSaved - nNodesAdded < 0 ) + continue; + + // decide what cut to use + if ( CostBest > CostCur ) + { + GainBest = nNodesSaved - nNodesAdded; // pure node cost + CostBest = CostCur; // cost with placement + pGraphBest = pGraphCur; // subgraph to be used for rewriting + + // score the graph + if ( nNodesSaved - nNodesAdded > 0 ) + { + pNode->nScore++; + pNode->nGain += GainBest; + pNode->nAdded += nNodesAdded; + } + } + } + else +*/ + { + // count the gain at this node + if ( GainBest < nNodesSaved - nNodesAdded ) + { + GainBest = nNodesSaved - nNodesAdded; + pGraphBest = pGraphCur; + + // score the graph + if ( nNodesSaved - nNodesAdded > 0 ) + { + pNode->nScore++; + pNode->nGain += GainBest; + pNode->nAdded += nNodesAdded; + } + } + } + } + if ( GainBest == -1 ) + return NULL; + *pGainBest = GainBest; + return pGraphBest; +} + +/**Function************************************************************* + + Synopsis [Checks the type of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_CutIsBoolean_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, int fMarkA ) +{ + if ( Vec_PtrFind(vLeaves, pObj) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pObj)) >= 0 ) + { + if ( fMarkA ) + pObj->fMarkA = 1; + else + pObj->fMarkB = 1; + return; + } + assert( !Abc_ObjIsCi(pObj) ); + Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, fMarkA ); + Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, fMarkA ); +} + +/**Function************************************************************* + + Synopsis [Checks the type of the cut.] + + Description [Returns 1(0) if the cut is Boolean (algebraic).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ) +{ + Abc_Obj_t * pTemp; + int i, RetValue; + Vec_PtrForEachEntry( vLeaves, pTemp, i ) + { + pTemp = Abc_ObjRegular(pTemp); + assert( !pTemp->fMarkA && !pTemp->fMarkB ); + } + Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, 1 ); + Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, 0 ); + RetValue = 0; + Vec_PtrForEachEntry( vLeaves, pTemp, i ) + { + pTemp = Abc_ObjRegular(pTemp); + RetValue |= pTemp->fMarkA && pTemp->fMarkB; + pTemp->fMarkA = pTemp->fMarkB = 0; + } + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Count the nodes in the cut space of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_CutCountNumNodes_rec( Abc_Obj_t * pObj, Cut_Cut_t * pCut, Vec_Ptr_t * vNodes ) +{ + int i; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + if ( pCut->pLeaves[i] == pObj->Id ) + { + // check if the node is collected + if ( pObj->fMarkC == 0 ) + { + pObj->fMarkC = 1; + Vec_PtrPush( vNodes, pObj ); + } + return; + } + assert( Abc_ObjIsNode(pObj) ); + // check if the node is collected + if ( pObj->fMarkC == 0 ) + { + pObj->fMarkC = 1; + Vec_PtrPush( vNodes, pObj ); + } + // traverse the fanins + Rwr_CutCountNumNodes_rec( Abc_ObjFanin0(pObj), pCut, vNodes ); + Rwr_CutCountNumNodes_rec( Abc_ObjFanin1(pObj), pCut, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Count the nodes in the cut space of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut ) +{ + Vec_Ptr_t * vNodes; + int i, Counter; + // collect all nodes + vNodes = Vec_PtrAlloc( 100 ); + for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) + Rwr_CutCountNumNodes_rec( pObj, pCut, vNodes ); + // clean all nodes + Vec_PtrForEachEntry( vNodes, pObj, i ) + pObj->fMarkC = 0; + // delete and return + Counter = Vec_PtrSize(vNodes); + Vec_PtrFree( vNodes ); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Returns depth of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ) +{ + Abc_Obj_t * pLeaf; + int i, Depth0, Depth1; + if ( Abc_ObjIsCi(pObj) ) + return 0; + Vec_PtrForEachEntry( vLeaves, pLeaf, i ) + if ( pObj == Abc_ObjRegular(pLeaf) ) + return 0; + Depth0 = Rwr_NodeGetDepth_rec( Abc_ObjFanin0(pObj), vLeaves ); + Depth1 = Rwr_NodeGetDepth_rec( Abc_ObjFanin1(pObj), vLeaves ); + return 1 + ABC_MAX( Depth0, Depth1 ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ScoresClean( Rwr_Man_t * p ) +{ + Vec_Ptr_t * vSubgraphs; + Rwr_Node_t * pNode; + int i, k; + for ( i = 0; i < p->vClasses->nSize; i++ ) + { + vSubgraphs = Vec_VecEntry( p->vClasses, i ); + Vec_PtrForEachEntry( vSubgraphs, pNode, k ) + pNode->nScore = pNode->nGain = pNode->nAdded = 0; + } +} + +static int Gains[222]; + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwr_ScoresCompare( int * pNum1, int * pNum2 ) +{ + if ( Gains[*pNum1] > Gains[*pNum2] ) + return -1; + if ( Gains[*pNum1] < Gains[*pNum2] ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ScoresReport( Rwr_Man_t * p ) +{ + extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); + int Perm[222]; + Vec_Ptr_t * vSubgraphs; + Rwr_Node_t * pNode; + int i, iNew, k; + unsigned uTruth; + // collect total gains + assert( p->vClasses->nSize == 222 ); + for ( i = 0; i < p->vClasses->nSize; i++ ) + { + Perm[i] = i; + Gains[i] = 0; + vSubgraphs = Vec_VecEntry( p->vClasses, i ); + Vec_PtrForEachEntry( vSubgraphs, pNode, k ) + Gains[i] += pNode->nGain; + } + // sort the gains + qsort( Perm, 222, sizeof(int), (int (*)(const void *, const void *))Rwr_ScoresCompare ); + + // print classes + for ( i = 0; i < p->vClasses->nSize; i++ ) + { + iNew = Perm[i]; + if ( Gains[iNew] == 0 ) + break; + vSubgraphs = Vec_VecEntry( p->vClasses, iNew ); + printf( "CLASS %3d: Subgr = %3d. Total gain = %6d. ", iNew, Vec_PtrSize(vSubgraphs), Gains[iNew] ); + uTruth = (unsigned)p->pMapInv[iNew]; + Extra_PrintBinary( stdout, &uTruth, 16 ); + printf( " " ); + Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[iNew] | ((unsigned)p->pMapInv[iNew] << 16) ); + Vec_PtrForEachEntry( vSubgraphs, pNode, k ) + { + if ( pNode->nScore == 0 ) + continue; + printf( " %2d: S=%5d. A=%5d. G=%6d. ", k, pNode->nScore, pNode->nAdded, pNode->nGain ); + Dec_GraphPrint( stdout, (Dec_Graph_t *)pNode->pNext, NULL, NULL ); + } + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/rwr/rwrExp.c b/abc70930/src/opt/rwr/rwrExp.c new file mode 100644 index 00000000..2d00bb1c --- /dev/null +++ b/abc70930/src/opt/rwr/rwrExp.c @@ -0,0 +1,333 @@ +/**CFile**************************************************************** + + FileName [rwrExp.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Computation of practically used NN-classes of 4-input cuts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwrExp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwr.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Rwr_Man4_t_ Rwr_Man4_t; +struct Rwr_Man4_t_ +{ + // internal lookups + int nFuncs; // the number of four-var functions + unsigned short * puCanons; // canonical forms + int * pnCounts; // the counters of functions in each class + int nConsidered; // the number of nodes considered + int nClasses; // the number of NN classes +}; + +typedef struct Rwr_Man5_t_ Rwr_Man5_t; +struct Rwr_Man5_t_ +{ + // internal lookups + stmm_table * tTableNN; // the NN canonical forms + stmm_table * tTableNPN; // the NPN canonical forms +}; + +static Rwr_Man4_t * s_pManRwrExp4 = NULL; +static Rwr_Man5_t * s_pManRwrExp5 = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects stats about 4-var functions appearing in netlists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_Man4ExploreStart() +{ + Rwr_Man4_t * p; + p = ALLOC( Rwr_Man4_t, 1 ); + memset( p, 0, sizeof(Rwr_Man4_t) ); + // canonical forms + p->nFuncs = (1<<16); + // canonical forms, phases, perms + Extra_Truth4VarNPN( &p->puCanons, NULL, NULL, NULL ); + // counters + p->pnCounts = ALLOC( int, p->nFuncs ); + memset( p->pnCounts, 0, sizeof(int) * p->nFuncs ); + s_pManRwrExp4 = p; +} + +/**Function************************************************************* + + Synopsis [Collects stats about 4-var functions appearing in netlists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_Man4ExploreCount( unsigned uTruth ) +{ + assert( uTruth < (1<<16) ); + s_pManRwrExp4->pnCounts[ s_pManRwrExp4->puCanons[uTruth] ]++; +} + +/**Function************************************************************* + + Synopsis [Collects stats about 4-var functions appearing in netlists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_Man4ExplorePrint() +{ + FILE * pFile; + int i, CountMax, CountWrite, nCuts, nClasses; + int * pDistrib; + int * pReprs; + // find the max number of occurences + nCuts = nClasses = 0; + CountMax = 0; + for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ ) + { + if ( CountMax < s_pManRwrExp4->pnCounts[i] ) + CountMax = s_pManRwrExp4->pnCounts[i]; + nCuts += s_pManRwrExp4->pnCounts[i]; + if ( s_pManRwrExp4->pnCounts[i] > 0 ) + nClasses++; + } + printf( "Number of cuts considered = %8d.\n", nCuts ); + printf( "Classes occurring at least once = %8d.\n", nClasses ); + // print the distribution of classes + pDistrib = ALLOC( int, CountMax + 1 ); + pReprs = ALLOC( int, CountMax + 1 ); + memset( pDistrib, 0, sizeof(int)*(CountMax + 1) ); + for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ ) + { + pDistrib[ s_pManRwrExp4->pnCounts[i] ]++; + pReprs[ s_pManRwrExp4->pnCounts[i] ] = i; + } + + printf( "Occurence = %6d. Num classes = %4d. \n", 0, 2288-nClasses ); + for ( i = 1; i <= CountMax; i++ ) + if ( pDistrib[i] ) + { + printf( "Occurence = %6d. Num classes = %4d. Repr = ", i, pDistrib[i] ); + Extra_PrintBinary( stdout, (unsigned*)&(pReprs[i]), 16 ); + printf( "\n" ); + } + free( pDistrib ); + free( pReprs ); + // write into a file all classes above limit (5) + CountWrite = 0; + pFile = fopen( "npnclass_stats4.txt", "w" ); + for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ ) + if ( s_pManRwrExp4->pnCounts[i] > 0 ) + { + Extra_PrintHex( pFile, i, 4 ); + fprintf( pFile, " %10d\n", s_pManRwrExp4->pnCounts[i] ); +// fprintf( pFile, "%d ", i ); + CountWrite++; + } + fclose( pFile ); + printf( "%d classes written into file \"%s\".\n", CountWrite, "npnclass_stats4.txt" ); +} + + + + +/**Function************************************************************* + + Synopsis [Collects stats about 4-var functions appearing in netlists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_Man5ExploreStart() +{ + Rwr_Man5_t * p; + p = ALLOC( Rwr_Man5_t, 1 ); + memset( p, 0, sizeof(Rwr_Man5_t) ); + p->tTableNN = stmm_init_table( st_numcmp, st_numhash ); + p->tTableNPN = stmm_init_table( st_numcmp, st_numhash ); + s_pManRwrExp5 = p; + +//Extra_PrintHex( stdout, Extra_TruthCanonNPN( 0x0000FFFF, 5 ), 5 ); +//printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Collects stats about 4-var functions appearing in netlists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_Man5ExploreCount( unsigned uTruth ) +{ + int * pCounter; + if ( !stmm_find_or_add( s_pManRwrExp5->tTableNN, (char *)uTruth, (char***)&pCounter ) ) + *pCounter = 0; + (*pCounter)++; +} + +/**Function************************************************************* + + Synopsis [Collects stats about 4-var functions appearing in netlists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwt_Man5ExplorePrint() +{ + FILE * pFile; + stmm_generator * gen; + int i, CountMax, nCuts, Counter; + int * pDistrib; + unsigned * pReprs; + unsigned uTruth, uTruthC; + int clk = clock(); + Vec_Int_t * vClassesNN, * vClassesNPN; + + // find the max number of occurences + nCuts = 0; + CountMax = 0; + stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, (char **)&Counter ) + { + nCuts += Counter; + if ( CountMax < Counter ) + CountMax = Counter; + } + printf( "Number of cuts considered = %8d.\n", nCuts ); + printf( "Classes occurring at least once = %8d.\n", stmm_count(s_pManRwrExp5->tTableNN) ); + printf( "The largest number of occurence = %8d.\n", CountMax ); + + // print the distribution of classes + pDistrib = ALLOC( int, CountMax + 1 ); + pReprs = ALLOC( unsigned, CountMax + 1 ); + memset( pDistrib, 0, sizeof(int)*(CountMax + 1) ); + stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, (char **)&Counter ) + { + assert( Counter <= CountMax ); + pDistrib[ Counter ]++; + pReprs[ Counter ] = uTruth; + } + + for ( i = 1; i <= CountMax; i++ ) + if ( pDistrib[i] ) + { + printf( "Occurence = %6d. Num classes = %4d. Repr = ", i, pDistrib[i] ); + Extra_PrintBinary( stdout, pReprs + i, 32 ); + printf( "\n" ); + } + free( pDistrib ); + free( pReprs ); + + + // put them into an array + vClassesNN = Vec_IntAlloc( stmm_count(s_pManRwrExp5->tTableNN) ); + stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, NULL ) + Vec_IntPush( vClassesNN, (int)uTruth ); + Vec_IntSortUnsigned( vClassesNN ); + + // write into a file all classes + pFile = fopen( "nnclass_stats5.txt", "w" ); + Vec_IntForEachEntry( vClassesNN, uTruth, i ) + { + if ( !stmm_lookup( s_pManRwrExp5->tTableNN, (char *)uTruth, (char **)&Counter ) ) + { + assert( 0 ); + } + Extra_PrintHex( pFile, uTruth, 5 ); + fprintf( pFile, " %10d\n", Counter ); + } + fclose( pFile ); + printf( "%d classes written into file \"%s\".\n", vClassesNN->nSize, "nnclass_stats5.txt" ); + + +clk = clock(); + // how many NPN classes exist? + Vec_IntForEachEntry( vClassesNN, uTruth, i ) + { + int * pCounter; + uTruthC = Extra_TruthCanonNPN( uTruth, 5 ); + if ( !stmm_find_or_add( s_pManRwrExp5->tTableNPN, (char *)uTruthC, (char***)&pCounter ) ) + *pCounter = 0; + if ( !stmm_lookup( s_pManRwrExp5->tTableNN, (char *)uTruth, (char **)&Counter ) ) + { + assert( 0 ); + } + (*pCounter) += Counter; + } + printf( "The numbe of NPN classes = %d.\n", stmm_count(s_pManRwrExp5->tTableNPN) ); +PRT( "Computing NPN classes", clock() - clk ); + + // put them into an array + vClassesNPN = Vec_IntAlloc( stmm_count(s_pManRwrExp5->tTableNPN) ); + stmm_foreach_item( s_pManRwrExp5->tTableNPN, gen, (char **)&uTruth, NULL ) + Vec_IntPush( vClassesNPN, (int)uTruth ); + Vec_IntSortUnsigned( vClassesNPN ); + + // write into a file all classes + pFile = fopen( "npnclass_stats5.txt", "w" ); + Vec_IntForEachEntry( vClassesNPN, uTruth, i ) + { + if ( !stmm_lookup( s_pManRwrExp5->tTableNPN, (char *)uTruth, (char **)&Counter ) ) + { + assert( 0 ); + } + Extra_PrintHex( pFile, uTruth, 5 ); + fprintf( pFile, " %10d\n", Counter ); + } + fclose( pFile ); + printf( "%d classes written into file \"%s\".\n", vClassesNPN->nSize, "npnclass_stats5.txt" ); + + + // can they be uniquely characterized? + +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/rwr/rwrLib.c b/abc70930/src/opt/rwr/rwrLib.c new file mode 100644 index 00000000..1cdf350e --- /dev/null +++ b/abc70930/src/opt/rwr/rwrLib.c @@ -0,0 +1,362 @@ +/**CFile**************************************************************** + + FileName [rwrLib.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwrLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwr.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ); +static void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Precomputes the forest in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManPrecompute( Rwr_Man_t * p ) +{ + Rwr_Node_t * p0, * p1; + int i, k, Level, Volume; + int LevelOld = -1; + int nNodes; + + Vec_PtrForEachEntryStart( p->vForest, p0, i, 1 ) + Vec_PtrForEachEntryStart( p->vForest, p1, k, 1 ) + { + if ( LevelOld < (int)p0->Level ) + { + LevelOld = p0->Level; + printf( "Starting level %d (at %d nodes).\n", LevelOld+1, i ); + printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", + p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); + } + + if ( k == i ) + break; +// if ( p0->Level + p1->Level > 6 ) // hard +// break; + + if ( p0->Level + p1->Level > 5 ) // easy + break; + +// if ( p0->Level + p1->Level > 6 || (p0->Level == 3 && p1->Level == 3) ) +// break; + + // compute the level and volume of the new nodes + Level = 1 + ABC_MAX( p0->Level, p1->Level ); + Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); + // try four different AND nodes + Rwr_ManTryNode( p, p0 , p1 , 0, Level, Volume ); + Rwr_ManTryNode( p, Rwr_Not(p0), p1 , 0, Level, Volume ); + Rwr_ManTryNode( p, p0 , Rwr_Not(p1), 0, Level, Volume ); + Rwr_ManTryNode( p, Rwr_Not(p0), Rwr_Not(p1), 0, Level, Volume ); + // try EXOR + Rwr_ManTryNode( p, p0 , p1 , 1, Level, Volume + 1 ); + // report the progress + if ( p->nConsidered % 50000000 == 0 ) + printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", + p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); + // quit after some time + if ( p->vForest->nSize == RWR_LIMIT + 5 ) + { + printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", + p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); + goto save; + } + } +save : + + // mark the relevant ones + Rwr_ManIncTravId( p ); + k = 5; + nNodes = 0; + Vec_PtrForEachEntryStart( p->vForest, p0, i, 5 ) + if ( p0->uTruth == p->puCanons[p0->uTruth] ) + { + Rwr_MarkUsed_rec( p, p0 ); + nNodes++; + } + + // compact the array by throwing away non-canonical + k = 5; + Vec_PtrForEachEntryStart( p->vForest, p0, i, 5 ) + if ( p0->fUsed ) + { + p->vForest->pArray[k] = p0; + p0->Id = k++; + } + p->vForest->nSize = k; + printf( "Total canonical = %4d. Total used = %5d.\n", nNodes, p->vForest->nSize ); +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ) +{ + Rwr_Node_t * pOld, * pNew, ** ppPlace; + unsigned uTruth; + // compute truth table, level, volume + p->nConsidered++; + if ( fExor ) + { +// printf( "Considering EXOR of %d and %d.\n", p0->Id, p1->Id ); + uTruth = (p0->uTruth ^ p1->uTruth); + } + else + uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & + (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF; + // skip non-practical classes + if ( Level > 2 && !p->pPractical[p->puCanons[uTruth]] ) + return NULL; + // enumerate through the nodes with the same canonical form + ppPlace = p->pTable + uTruth; + for ( pOld = *ppPlace; pOld; ppPlace = &pOld->pNext, pOld = pOld->pNext ) + { + if ( pOld->Level < (unsigned)Level && pOld->Volume < (unsigned)Volume ) + return NULL; + if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume ) + return NULL; +// if ( pOld->Level < (unsigned)Level && pOld->Volume == (unsigned)Volume ) +// return NULL; + } +/* + // enumerate through the nodes with the opposite polarity + for ( pOld = p->pTable[~uTruth & 0xFFFF]; pOld; pOld = pOld->pNext ) + { + if ( pOld->Level < (unsigned)Level && pOld->Volume < (unsigned)Volume ) + return NULL; + if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume ) + return NULL; +// if ( pOld->Level < (unsigned)Level && pOld->Volume == (unsigned)Volume ) +// return NULL; + } +*/ + // count the classes + if ( p->pTable[uTruth] == NULL && p->puCanons[uTruth] == uTruth ) + p->nClasses++; + // create the new node + pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); + pNew->Id = p->vForest->nSize; + pNew->TravId = 0; + pNew->uTruth = uTruth; + pNew->Level = Level; + pNew->Volume = Volume; + pNew->fUsed = 0; + pNew->fExor = fExor; + pNew->p0 = p0; + pNew->p1 = p1; + pNew->pNext = NULL; + Vec_PtrPush( p->vForest, pNew ); + *ppPlace = pNew; + return pNew; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rwr_Node_t * Rwr_ManAddNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ) +{ + Rwr_Node_t * pNew; + unsigned uTruth; + // compute truth table, leve, volume + p->nConsidered++; + if ( fExor ) + uTruth = (p0->uTruth ^ p1->uTruth); + else + uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & + (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF; + // create the new node + pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); + pNew->Id = p->vForest->nSize; + pNew->TravId = 0; + pNew->uTruth = uTruth; + pNew->Level = Level; + pNew->Volume = Volume; + pNew->fUsed = 0; + pNew->fExor = fExor; + pNew->p0 = p0; + pNew->p1 = p1; + pNew->pNext = NULL; + Vec_PtrPush( p->vForest, pNew ); + // do not add if the node is not essential + if ( uTruth != p->puCanons[uTruth] ) + return pNew; + + // add to the list + p->nAdded++; + if ( p->pTable[uTruth] == NULL ) + p->nClasses++; + Rwr_ListAddToTail( p->pTable + uTruth, pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute ) +{ + Rwr_Node_t * pNew; + pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); + pNew->Id = p->vForest->nSize; + pNew->TravId = 0; + pNew->uTruth = uTruth; + pNew->Level = 0; + pNew->Volume = 0; + pNew->fUsed = 1; + pNew->fExor = 0; + pNew->p0 = NULL; + pNew->p1 = NULL; + pNew->pNext = NULL; + Vec_PtrPush( p->vForest, pNew ); + if ( fPrecompute ) + Rwr_ListAddToTail( p->pTable + uTruth, pNew ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode ) +{ + if ( pNode->fUsed || pNode->TravId == p->nTravIds ) + return; + pNode->TravId = p->nTravIds; + pNode->fUsed = 1; + Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p0) ); + Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p1) ); +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_Trav_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, int * pVolume ) +{ + if ( pNode->fUsed || pNode->TravId == p->nTravIds ) + return; + pNode->TravId = p->nTravIds; + (*pVolume)++; + if ( pNode->fExor ) + (*pVolume)++; + Rwr_Trav_rec( p, Rwr_Regular(pNode->p0), pVolume ); + Rwr_Trav_rec( p, Rwr_Regular(pNode->p1), pVolume ); +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwr_ManNodeVolume( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 ) +{ + int Volume = 0; + Rwr_ManIncTravId( p ); + Rwr_Trav_rec( p, p0, &Volume ); + Rwr_Trav_rec( p, p1, &Volume ); + return Volume; +} + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManIncTravId( Rwr_Man_t * p ) +{ + Rwr_Node_t * pNode; + int i; + if ( p->nTravIds++ < 0x8FFFFFFF ) + return; + Vec_PtrForEachEntry( p->vForest, pNode, i ) + pNode->TravId = 0; + p->nTravIds = 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/rwr/rwrMan.c b/abc70930/src/opt/rwr/rwrMan.c new file mode 100644 index 00000000..87a080c7 --- /dev/null +++ b/abc70930/src/opt/rwr/rwrMan.c @@ -0,0 +1,318 @@ +/**CFile**************************************************************** + + FileName [rwrMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Rewriting manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwrMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwr.h" +#include "main.h" +#include "dec.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rwr_Man_t * Rwr_ManStart( bool fPrecompute ) +{ + Dec_Man_t * pManDec; + Rwr_Man_t * p; + int clk = clock(); +clk = clock(); + p = ALLOC( Rwr_Man_t, 1 ); + memset( p, 0, sizeof(Rwr_Man_t) ); + p->nFuncs = (1<<16); + pManDec = Abc_FrameReadManDec(); + p->puCanons = pManDec->puCanons; + p->pPhases = pManDec->pPhases; + p->pPerms = pManDec->pPerms; + p->pMap = pManDec->pMap; + // initialize practical NPN classes + p->pPractical = Rwr_ManGetPractical( p ); + // create the table + p->pTable = ALLOC( Rwr_Node_t *, p->nFuncs ); + memset( p->pTable, 0, sizeof(Rwr_Node_t *) * p->nFuncs ); + // create the elementary nodes + p->pMmNode = Extra_MmFixedStart( sizeof(Rwr_Node_t) ); + p->vForest = Vec_PtrAlloc( 100 ); + Rwr_ManAddVar( p, 0x0000, fPrecompute ); // constant 0 + Rwr_ManAddVar( p, 0xAAAA, fPrecompute ); // var A + Rwr_ManAddVar( p, 0xCCCC, fPrecompute ); // var B + Rwr_ManAddVar( p, 0xF0F0, fPrecompute ); // var C + Rwr_ManAddVar( p, 0xFF00, fPrecompute ); // var D + p->nClasses = 5; + // other stuff + p->nTravIds = 1; + p->pPerms4 = Extra_Permutations( 4 ); + p->vLevNums = Vec_IntAlloc( 50 ); + p->vFanins = Vec_PtrAlloc( 50 ); + p->vFaninsCur = Vec_PtrAlloc( 50 ); + p->vNodesTemp = Vec_PtrAlloc( 50 ); + if ( fPrecompute ) + { // precompute subgraphs + Rwr_ManPrecompute( p ); +// Rwr_ManPrint( p ); + Rwr_ManWriteToArray( p ); + } + else + { // load saved subgraphs + Rwr_ManLoadFromArray( p, 0 ); +// Rwr_ManPrint( p ); + Rwr_ManPreprocess( p ); + } +p->timeStart = clock() - clk; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops rewriting manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManStop( Rwr_Man_t * p ) +{ + if ( p->vClasses ) + { + Rwr_Node_t * pNode; + int i, k; + Vec_VecForEachEntry( p->vClasses, pNode, i, k ) + Dec_GraphFree( (Dec_Graph_t *)pNode->pNext ); + } + if ( p->vClasses ) Vec_VecFree( p->vClasses ); + Vec_PtrFree( p->vNodesTemp ); + Vec_PtrFree( p->vForest ); + Vec_IntFree( p->vLevNums ); + Vec_PtrFree( p->vFanins ); + Vec_PtrFree( p->vFaninsCur ); + Extra_MmFixedStop( p->pMmNode ); + FREE( p->pMapInv ); + free( p->pTable ); + free( p->pPractical ); + free( p->pPerms4 ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManPrintStats( Rwr_Man_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < 222; i++ ) + Counter += (p->nScores[i] > 0); + + printf( "Rewriting statistics:\n" ); + printf( "Total cuts tries = %8d.\n", p->nCutsGood ); + printf( "Bad cuts found = %8d.\n", p->nCutsBad ); + printf( "Total subgraphs = %8d.\n", p->nSubgraphs ); + printf( "Used NPN classes = %8d.\n", Counter ); + printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); + printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten ); + printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg ); + PRT( "Start ", p->timeStart ); + PRT( "Cuts ", p->timeCut ); + PRT( "Resynthesis ", p->timeRes ); + PRT( " Mffc ", p->timeMffc ); + PRT( " Eval ", p->timeEval ); + PRT( "Update ", p->timeUpdate ); + PRT( "TOTAL ", p->timeTotal ); + +/* + printf( "The scores are:\n" ); + for ( i = 0; i < 222; i++ ) + if ( p->nScores[i] > 0 ) + { + extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); + printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] ); + Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) ); + } +*/ + printf( "\n" ); + +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManPrintStatsFile( Rwr_Man_t * p ) +{ + FILE * pTable; + pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%d ", p->nCutsGood ); + fprintf( pTable, "%d ", p->nSubgraphs ); + fprintf( pTable, "%d ", p->nNodesRewritten ); + fprintf( pTable, "%d", p->nNodesGained ); + fprintf( pTable, "\n" ); + fclose( pTable ); +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Rwr_ManReadDecs( Rwr_Man_t * p ) +{ + return p->pGraph; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Rwr_ManReadLeaves( Rwr_Man_t * p ) +{ + return p->vFanins; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwr_ManReadCompl( Rwr_Man_t * p ) +{ + return p->fCompl; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManAddTimeCuts( Rwr_Man_t * p, int Time ) +{ + p->timeCut += Time; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManAddTimeUpdate( Rwr_Man_t * p, int Time ) +{ + p->timeUpdate += Time; +} + +/**Function************************************************************* + + Synopsis [Stops the resynthesis manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManAddTimeTotal( Rwr_Man_t * p, int Time ) +{ + p->timeTotal += Time; +} + + +/**Function************************************************************* + + Synopsis [Precomputes AIG subgraphs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_Precompute() +{ + Rwr_Man_t * p; + p = Rwr_ManStart( 1 ); + Rwr_ManStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/rwr/rwrPrint.c b/abc70930/src/opt/rwr/rwrPrint.c new file mode 100644 index 00000000..82ad2a90 --- /dev/null +++ b/abc70930/src/opt/rwr/rwrPrint.c @@ -0,0 +1,266 @@ +/**CFile**************************************************************** + + FileName [rwrCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwr.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Adds one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_Trav2_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, int * pVolume ) +{ + if ( pNode->fUsed || pNode->TravId == p->nTravIds ) + return; + pNode->TravId = p->nTravIds; + (*pVolume)++; + Rwr_Trav2_rec( p, Rwr_Regular(pNode->p0), pVolume ); + Rwr_Trav2_rec( p, Rwr_Regular(pNode->p1), pVolume ); +} + +/**Function************************************************************* + + Synopsis [Adds the node to the end of the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_GetBushVolume( Rwr_Man_t * p, int Entry, int * pVolume, int * pnFuncs ) +{ + Rwr_Node_t * pNode; + int Volume = 0; + int nFuncs = 0; + Rwr_ManIncTravId( p ); + for ( pNode = p->pTable[Entry]; pNode; pNode = pNode->pNext ) + { + if ( pNode->uTruth != p->puCanons[pNode->uTruth] ) + continue; + nFuncs++; + Rwr_Trav2_rec( p, pNode, &Volume ); + } + *pVolume = Volume; + *pnFuncs = nFuncs; +} + +/**Function************************************************************* + + Synopsis [Adds the node to the end of the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwr_GetBushSumOfVolumes( Rwr_Man_t * p, int Entry ) +{ + Rwr_Node_t * pNode; + int Volume, VolumeTotal = 0; + for ( pNode = p->pTable[Entry]; pNode; pNode = pNode->pNext ) + { + if ( pNode->uTruth != p->puCanons[pNode->uTruth] ) + continue; + Volume = 0; + Rwr_ManIncTravId( p ); + Rwr_Trav2_rec( p, pNode, &Volume ); + VolumeTotal += Volume; + } + return VolumeTotal; +} + +/**Function************************************************************* + + Synopsis [Prints one rwr node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_NodePrint_rec( FILE * pFile, Rwr_Node_t * pNode ) +{ + assert( !Rwr_IsComplement(pNode) ); + + if ( pNode->Id == 0 ) + { + fprintf( pFile, "Const1" ); + return; + } + + if ( pNode->Id < 5 ) + { + fprintf( pFile, "%c", 'a' + pNode->Id - 1 ); + return; + } + + if ( Rwr_IsComplement(pNode->p0) ) + { + if ( Rwr_Regular(pNode->p0)->Id < 5 ) + { + Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); + fprintf( pFile, "\'" ); + } + else + { + fprintf( pFile, "(" ); + Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); + fprintf( pFile, ")\'" ); + } + } + else + { + if ( Rwr_Regular(pNode->p0)->Id < 5 ) + { + Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); + } + else + { + fprintf( pFile, "(" ); + Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); + fprintf( pFile, ")" ); + } + } + + if ( pNode->fExor ) + fprintf( pFile, "+" ); + + if ( Rwr_IsComplement(pNode->p1) ) + { + if ( Rwr_Regular(pNode->p1)->Id < 5 ) + { + Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); + fprintf( pFile, "\'" ); + } + else + { + fprintf( pFile, "(" ); + Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); + fprintf( pFile, ")\'" ); + } + } + else + { + if ( Rwr_Regular(pNode->p1)->Id < 5 ) + { + Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); + } + else + { + fprintf( pFile, "(" ); + Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); + fprintf( pFile, ")" ); + } + } +} + +/**Function************************************************************* + + Synopsis [Prints one rwr node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_NodePrint( FILE * pFile, Rwr_Man_t * p, Rwr_Node_t * pNode ) +{ + unsigned uTruth; + fprintf( pFile, "%5d : ", pNode->Id ); + Extra_PrintHex( pFile, pNode->uTruth, 4 ); + fprintf( pFile, " tt=" ); + uTruth = pNode->uTruth; + Extra_PrintBinary( pFile, &uTruth, 16 ); +// fprintf( pFile, " cn=", pNode->Id ); +// uTruth = p->puCanons[pNode->uTruth]; +// Extra_PrintBinary( pFile, &uTruth, 16 ); + fprintf( pFile, " lev=%d", pNode->Level ); + fprintf( pFile, " vol=%d", pNode->Volume ); + fprintf( pFile, " " ); + Rwr_NodePrint_rec( pFile, pNode ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints one rwr node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManPrint( Rwr_Man_t * p ) +{ + FILE * pFile; + Rwr_Node_t * pNode; + unsigned uTruth; + int Limit, Counter, Volume, nFuncs, i; + pFile = fopen( "graph_lib.txt", "w" ); + Counter = 0; + Limit = (1 << 16); + for ( i = 0; i < Limit; i++ ) + { + if ( p->pTable[i] == NULL ) + continue; + if ( i != p->puCanons[i] ) + continue; + fprintf( pFile, "\nClass %3d. Func %6d. ", p->pMap[i], Counter++ ); + Rwr_GetBushVolume( p, i, &Volume, &nFuncs ); + fprintf( pFile, "Roots = %3d. Vol = %3d. Sum = %3d. ", nFuncs, Volume, Rwr_GetBushSumOfVolumes(p, i) ); + uTruth = i; + Extra_PrintBinary( pFile, &uTruth, 16 ); + fprintf( pFile, "\n" ); + for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext ) + if ( pNode->uTruth == p->puCanons[pNode->uTruth] ) + Rwr_NodePrint( pFile, p, pNode ); + } + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/rwr/rwrTemp.c b/abc70930/src/opt/rwr/rwrTemp.c new file mode 100644 index 00000000..3ffbd408 --- /dev/null +++ b/abc70930/src/opt/rwr/rwrTemp.c @@ -0,0 +1,121 @@ +/**CFile**************************************************************** + + FileName [rwrCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwr.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int pTruths[13719]; +static int pFreqs[13719]; +static int pPerm[13719]; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rwr_TempCompare( int * pNum1, int * pNum2 ) +{ + int Freq1 = pFreqs[*pNum1]; + int Freq2 = pFreqs[*pNum2]; + if ( Freq1 < Freq2 ) + return 1; + if ( Freq1 > Freq2 ) + return -1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_Temp() +{ + char Buffer[32]; + int nFuncs = 13719; + int nEntries = 100; + unsigned uTruth; + int i, k; + FILE * pFile; + + pFile = fopen( "nnclass_stats5.txt", "r" ); + for ( i = 0; i < 13719; i++ ) + { + fscanf( pFile, "%s%d", Buffer, &pFreqs[i] ); + Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); + pTruths[i] = uTruth; + } + fclose( pFile ); + + for ( i = 0; i < 13719; i++ ) + pPerm[i] = i; + + qsort( (void *)pPerm, 13719, sizeof(int), + (int (*)(const void *, const void *)) Rwr_TempCompare ); + + + pFile = fopen( "5npn_100.blif", "w" ); + fprintf( pFile, "# Most frequent NPN classes of 5 vars.\n" ); + fprintf( pFile, ".model 5npn\n" ); + fprintf( pFile, ".inputs a b c d e\n" ); + fprintf( pFile, ".outputs" ); + for ( i = 0; i < nEntries; i++ ) + fprintf( pFile, " %02d", i ); + fprintf( pFile, "\n" ); + + for ( i = 0; i < nEntries; i++ ) + { + fprintf( pFile, ".names a b c d e %02d\n", i ); + uTruth = pTruths[pPerm[i]]; + for ( k = 0; k < 32; k++ ) + if ( uTruth & (1 << k) ) + { + Extra_PrintBinary( pFile, &k, 5 ); + fprintf( pFile, " 1\n" ); + } + } + fprintf( pFile, ".end\n" ); + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/rwr/rwrUtil.c b/abc70930/src/opt/rwr/rwrUtil.c new file mode 100644 index 00000000..b2add2bf --- /dev/null +++ b/abc70930/src/opt/rwr/rwrUtil.c @@ -0,0 +1,659 @@ +/**CFile**************************************************************** + + FileName [rwrUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [DAG-aware AIG rewriting package.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: rwrUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "rwr.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// precomputed data +#ifdef _WIN32 +unsigned short s_RwrPracticalClasses[]; +unsigned short s_RwtAigSubgraphs[]; +#else +static unsigned short s_RwrPracticalClasses[]; +static unsigned short s_RwtAigSubgraphs[]; +#endif + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManWriteToArray( Rwr_Man_t * p ) +{ + FILE * pFile; + Rwr_Node_t * pNode; + unsigned Entry0, Entry1; + int i, nEntries, clk = clock(); + // prepare the buffer + nEntries = p->vForest->nSize - 5; + pFile = fopen( "npn4_aig_array.txt", "w" ); + fprintf( pFile, "static unsigned short s_RwtAigSubgraphs[] = \n{" ); + for ( i = 0; i < nEntries; i++ ) + { + if ( i % 5 == 0 ) + fprintf( pFile, "\n " ); + pNode = p->vForest->pArray[i+5]; + Entry0 = (Rwr_Regular(pNode->p0)->Id << 1) | Rwr_IsComplement(pNode->p0); + Entry1 = (Rwr_Regular(pNode->p1)->Id << 1) | Rwr_IsComplement(pNode->p1); + Entry0 = (Entry0 << 1) | pNode->fExor; + Extra_PrintHex( pFile, Entry0, 4 ); + fprintf( pFile, "," ); + Extra_PrintHex( pFile, Entry1, 4 ); + fprintf( pFile, ", " ); + } + if ( i % 5 == 0 ) + fprintf( pFile, "\n " ); + Extra_PrintHex( pFile, 0, 4 ); + fprintf( pFile, "," ); + Extra_PrintHex( pFile, 0, 4 ); + fprintf( pFile, " \n};\n" ); + fclose( pFile ); + printf( "The number of nodes saved = %d. ", nEntries ); PRT( "Saving", clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Loads data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManLoadFromArray( Rwr_Man_t * p, int fVerbose ) +{ + unsigned short * pArray = s_RwtAigSubgraphs; + Rwr_Node_t * p0, * p1; + unsigned Entry0, Entry1; + int Level, Volume, nEntries, fExor; + int i, clk = clock(); + + // reconstruct the forest + for ( i = 0; ; i++ ) + { + Entry0 = pArray[2*i + 0]; + Entry1 = pArray[2*i + 1]; + if ( Entry0 == 0 && Entry1 == 0 ) + break; + // get EXOR flag + fExor = (Entry0 & 1); + Entry0 >>= 1; + // get the nodes + p0 = p->vForest->pArray[Entry0 >> 1]; + p1 = p->vForest->pArray[Entry1 >> 1]; + // compute the level and volume of the new nodes + Level = 1 + ABC_MAX( p0->Level, p1->Level ); + Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); + // set the complemented attributes + p0 = Rwr_NotCond( p0, (Entry0 & 1) ); + p1 = Rwr_NotCond( p1, (Entry1 & 1) ); + // add the node +// Rwr_ManTryNode( p, p0, p1, Level, Volume ); + Rwr_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor ); + } + nEntries = i - 1; + if ( fVerbose ) + { + printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded ); + printf( "The number of nodes loaded = %d. ", nEntries ); PRT( "Loading", clock() - clk ); + } +} + + +/**Function************************************************************* + + Synopsis [Writes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManWriteToFile( Rwr_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Rwr_Node_t * pNode; + unsigned * pBuffer; + int i, nEntries, clk = clock(); + // prepare the buffer + nEntries = p->vForest->nSize - 5; + pBuffer = ALLOC( unsigned, nEntries * 2 ); + for ( i = 0; i < nEntries; i++ ) + { + pNode = p->vForest->pArray[i+5]; + pBuffer[2*i + 0] = (Rwr_Regular(pNode->p0)->Id << 1) | Rwr_IsComplement(pNode->p0); + pBuffer[2*i + 1] = (Rwr_Regular(pNode->p1)->Id << 1) | Rwr_IsComplement(pNode->p1); + // save EXOR flag + pBuffer[2*i + 0] = (pBuffer[2*i + 0] << 1) | pNode->fExor; + + } + pFile = fopen( pFileName, "wb" ); + fwrite( &nEntries, sizeof(int), 1, pFile ); + fwrite( pBuffer, sizeof(unsigned), nEntries * 2, pFile ); + free( pBuffer ); + fclose( pFile ); + printf( "The number of nodes saved = %d. ", nEntries ); PRT( "Saving", clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Loads data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Rwr_Node_t * p0, * p1; + unsigned * pBuffer; + int Level, Volume, nEntries, fExor; + int i, clk = clock(); + + // load the data + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Rwr_ManLoadFromFile: Cannot open file \"%s\".\n", pFileName ); + return; + } + fread( &nEntries, sizeof(int), 1, pFile ); + pBuffer = ALLOC( unsigned, nEntries * 2 ); + fread( pBuffer, sizeof(unsigned), nEntries * 2, pFile ); + fclose( pFile ); + // reconstruct the forest + for ( i = 0; i < nEntries; i++ ) + { + // get EXOR flag + fExor = (pBuffer[2*i + 0] & 1); + pBuffer[2*i + 0] = (pBuffer[2*i + 0] >> 1); + // get the nodes + p0 = p->vForest->pArray[pBuffer[2*i + 0] >> 1]; + p1 = p->vForest->pArray[pBuffer[2*i + 1] >> 1]; + // compute the level and volume of the new nodes + Level = 1 + ABC_MAX( p0->Level, p1->Level ); + Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); + // set the complemented attributes + p0 = Rwr_NotCond( p0, (pBuffer[2*i + 0] & 1) ); + p1 = Rwr_NotCond( p1, (pBuffer[2*i + 1] & 1) ); + // add the node +// Rwr_ManTryNode( p, p0, p1, Level, Volume ); + Rwr_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor ); + } + free( pBuffer ); + printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded ); + printf( "The number of nodes loaded = %d. ", nEntries ); PRT( "Loading", clock() - clk ); +} + + +/**Function************************************************************* + + Synopsis [Adds the node to the end of the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rwr_ListAddToTail( Rwr_Node_t ** ppList, Rwr_Node_t * pNode ) +{ + Rwr_Node_t * pTemp; + // find the last one + for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext ) + ppList = &pTemp->pNext; + // attach at the end + *ppList = pNode; +} + +/**Function************************************************************* + + Synopsis [Create practical classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Rwr_ManGetPractical( Rwr_Man_t * p ) +{ + char * pPractical; + int i; + pPractical = ALLOC( char, p->nFuncs ); + memset( pPractical, 0, sizeof(char) * p->nFuncs ); + pPractical[0] = 1; + for ( i = 1; ; i++ ) + { + if ( s_RwrPracticalClasses[i] == 0 ) + break; + pPractical[ s_RwrPracticalClasses[i] ] = 1; + } + return pPractical; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +// the following 135 practical NPN classes of 4-variable functions were computed +// by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks +static unsigned short s_RwrPracticalClasses[] = +{ + 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b, + 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff, + 0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c, + 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, + 0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab, + 0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe, + 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368, + 0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5, + 0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669, + 0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2, + 0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8, + 0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4, + 0x1ee1, 0x3cc3, 0x6996, 0x0000 +}; + +static unsigned short s_RwtAigSubgraphs[] = +{ + 0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002, + 0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002, + 0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004, + 0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002, + 0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004, + 0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006, + 0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007, + 0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009, + 0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007, + 0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005, + 0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006, + 0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008, + 0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006, + 0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008, + 0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006, + 0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004, + 0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009, + 0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e, + 0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005, + 0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f, + 0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009, + 0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e, + 0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005, + 0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008, + 0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013, + 0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008, + 0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012, + 0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003, + 0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009, + 0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013, + 0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002, + 0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d, + 0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c, + 0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007, + 0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012, + 0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002, + 0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008, + 0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f, + 0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019, + 0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002, + 0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008, + 0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011, + 0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017, + 0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d, + 0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009, + 0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019, + 0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024, + 0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004, + 0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b, + 0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021, + 0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024, + 0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009, + 0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024, + 0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004, + 0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d, + 0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020, + 0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024, + 0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027, + 0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f, + 0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d, + 0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024, + 0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006, + 0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015, + 0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f, + 0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002, + 0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016, + 0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025, + 0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b, + 0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a, + 0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003, + 0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f, + 0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018, + 0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b, + 0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003, + 0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006, + 0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019, + 0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022, + 0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f, + 0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004, + 0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f, + 0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017, + 0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f, + 0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002, + 0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011, + 0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037, + 0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010, + 0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b, + 0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002, + 0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005, + 0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d, + 0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011, + 0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012, + 0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039, + 0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005, + 0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011, + 0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017, + 0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b, + 0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009, + 0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037, + 0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010, + 0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030, + 0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009, + 0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d, + 0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008, + 0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010, + 0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030, + 0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044, + 0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011, + 0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043, + 0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017, + 0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a, + 0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f, + 0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f, + 0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023, + 0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007, + 0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033, + 0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b, + 0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037, + 0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d, + 0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067, + 0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038, + 0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d, + 0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006, + 0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025, + 0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014, + 0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f, + 0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008, + 0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d, + 0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058, + 0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008, + 0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d, + 0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059, + 0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b, + 0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b, + 0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019, + 0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043, + 0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061, + 0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007, + 0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004, + 0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045, + 0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d, + 0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009, + 0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044, + 0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044, + 0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097, + 0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f, + 0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048, + 0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a, + 0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009, + 0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044, + 0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a, + 0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029, + 0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a, + 0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013, + 0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5, + 0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f, + 0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095, + 0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009, + 0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f, + 0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013, + 0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095, + 0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030, + 0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6, + 0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e, + 0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061, + 0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc, + 0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044, + 0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a, + 0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008, + 0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8, + 0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095, + 0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004, + 0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029, + 0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068, + 0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c, + 0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029, + 0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c, + 0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013, + 0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067, + 0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf, + 0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d, + 0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003, + 0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f, + 0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099, + 0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf, + 0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f, + 0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176, + 0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3, + 0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b, + 0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f, + 0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008, + 0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095, + 0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b, + 0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec, + 0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3, + 0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009, + 0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009, + 0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a, + 0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030, + 0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009, + 0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033, + 0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e, + 0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158, + 0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a, + 0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d, + 0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168, + 0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e, + 0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133, + 0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b, + 0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f, + 0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da, + 0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d, + 0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef, + 0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181, + 0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027, + 0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a, + 0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f, + 0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181, + 0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205, + 0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033, + 0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225, + 0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0, + 0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1, + 0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d, + 0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006, + 0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a, + 0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b, + 0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033, + 0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231, + 0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4, + 0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e, + 0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec, + 0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e, + 0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3, + 0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a, + 0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef, + 0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175, + 0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0, + 0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f, + 0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3, + 0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e, + 0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086, + 0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5, + 0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e, + 0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181, + 0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0, + 0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095, + 0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b, + 0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276, + 0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4, + 0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006, + 0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3, + 0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d, + 0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103, + 0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234, + 0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d, + 0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106, + 0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8, + 0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044, + 0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0, + 0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a, + 0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6, + 0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238, + 0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e, + 0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067, + 0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020, + 0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021, + 0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183, + 0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268, + 0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc, + 0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213, + 0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023, + 0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b, + 0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da, + 0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287, + 0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce, + 0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf, + 0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338, + 0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328, + 0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003, + 0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330, + 0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282, + 0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a, + 0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9, + 0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247, + 0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d, + 0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce, + 0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0, + 0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004, + 0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315, + 0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d, + 0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd, + 0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb, + 0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f, + 0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173, + 0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029, + 0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3, + 0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053, + 0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030, + 0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021, + 0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2, + 0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9, + 0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285, + 0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b, + 0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a, + 0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315, + 0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f, + 0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c, + 0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e, + 0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089, + 0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021, + 0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354, + 0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f, + 0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095, + 0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3, + 0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e, + 0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009, + 0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009, + 0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b, + 0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381, + 0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008, + 0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb, + 0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5, + 0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027, + 0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030, + 0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb, + 0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a, + 0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009, + 0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027, + 0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d, + 0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271, + 0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f, + 0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009, + 0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009, + 0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f, + 0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9, + 0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235, + 0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d, + 0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085, + 0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3, + 0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043, + 0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7, + 0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f, + 0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059, + 0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d, + 0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009, + 0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b, + 0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061, + 0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9, + 0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027, + 0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019, + 0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1, + 0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b, + 0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7, + 0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb, + 0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d, + 0x0000,0x0000 +}; + + diff --git a/abc70930/src/opt/sim/module.make b/abc70930/src/opt/sim/module.make new file mode 100644 index 00000000..54058402 --- /dev/null +++ b/abc70930/src/opt/sim/module.make @@ -0,0 +1,10 @@ +SRC += src/opt/sim/simMan.c \ + src/opt/sim/simSat.c \ + src/opt/sim/simSeq.c \ + src/opt/sim/simSupp.c \ + src/opt/sim/simSwitch.c \ + src/opt/sim/simSym.c \ + src/opt/sim/simSymSat.c \ + src/opt/sim/simSymSim.c \ + src/opt/sim/simSymStr.c \ + src/opt/sim/simUtils.c diff --git a/abc70930/src/opt/sim/sim.h b/abc70930/src/opt/sim/sim.h new file mode 100644 index 00000000..7fcf5ae6 --- /dev/null +++ b/abc70930/src/opt/sim/sim.h @@ -0,0 +1,233 @@ +/**CFile**************************************************************** + + FileName [sim.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Simulation package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: sim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __SIM_H__ +#define __SIM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + The ideas realized in this package are described in the paper: + "Detecting Symmetries in Boolean Functions using Circuit Representation, + Simulation, and Satisfiability". +*/ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Sym_Man_t_ Sym_Man_t; +struct Sym_Man_t_ +{ + // info about the network + Abc_Ntk_t * pNtk; // the network + Vec_Ptr_t * vNodes; // internal nodes in topological order + int nInputs; + int nOutputs; + // internal simulation information + int nSimWords; // the number of bits in simulation info + Vec_Ptr_t * vSim; // simulation info + // support information + Vec_Ptr_t * vSuppFun; // bit representation + Vec_Vec_t * vSupports; // integer representation + // symmetry info for each output + Vec_Ptr_t * vMatrSymms; // symmetric pairs + Vec_Ptr_t * vMatrNonSymms; // non-symmetric pairs + Vec_Int_t * vPairsTotal; // total pairs + Vec_Int_t * vPairsSym; // symmetric pairs + Vec_Int_t * vPairsNonSym; // non-symmetric pairs + // temporary simulation info + unsigned * uPatRand; + unsigned * uPatCol; + unsigned * uPatRow; + // temporary + Vec_Int_t * vVarsU; + Vec_Int_t * vVarsV; + int iOutput; + int iVar1; + int iVar2; + int iVar1Old; + int iVar2Old; + // internal data structures + int nSatRuns; + int nSatRunsSat; + int nSatRunsUnsat; + // pairs + int nPairsSymm; + int nPairsSymmStr; + int nPairsNonSymm; + int nPairsRem; + int nPairsTotal; + // runtime statistics + int timeStruct; + int timeCount; + int timeMatr; + int timeSim; + int timeFraig; + int timeSat; + int timeTotal; +}; + +typedef struct Sim_Man_t_ Sim_Man_t; +struct Sim_Man_t_ +{ + // info about the network + Abc_Ntk_t * pNtk; + int nInputs; + int nOutputs; + int fLightweight; + // internal simulation information + int nSimBits; // the number of bits in simulation info + int nSimWords; // the number of words in simulation info + Vec_Ptr_t * vSim0; // simulation info 1 + Vec_Ptr_t * vSim1; // simulation info 2 + // support information + int nSuppBits; // the number of bits in support info + int nSuppWords; // the number of words in support info + Vec_Ptr_t * vSuppStr; // structural supports + Vec_Ptr_t * vSuppFun; // functional supports + // simulation targets + Vec_Vec_t * vSuppTargs; // support targets + int iInput; // the input current processed + // internal data structures + Extra_MmFixed_t * pMmPat; + Vec_Ptr_t * vFifo; + Vec_Int_t * vDiffs; + int nSatRuns; + int nSatRunsSat; + int nSatRunsUnsat; + // runtime statistics + int timeSim; + int timeTrav; + int timeFraig; + int timeSat; + int timeTotal; +}; + +typedef struct Sim_Pat_t_ Sim_Pat_t; +struct Sim_Pat_t_ +{ + int Input; // the input which it has detected + int Output; // the output for which it was collected + unsigned * pData; // the simulation data +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define SIM_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0)) +#define SIM_LAST_BITS(n) ((((n)&31) > 0)? (n)&31 : 32) + +#define SIM_MASK_FULL (0xFFFFFFFF) +#define SIM_MASK_BEG(n) (SIM_MASK_FULL >> (32-n)) +#define SIM_MASK_END(n) (SIM_MASK_FULL << (n)) +#define SIM_SET_0_FROM(m,n) ((m) & ~SIM_MASK_BEG(n)) +#define SIM_SET_1_FROM(m,n) ((m) | SIM_MASK_END(n)) + +// generating random unsigned (#define RAND_MAX 0x7fff) +#define SIM_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) + +// macros to get hold of bits in a bit string +#define Sim_SetBit(p,i) ((p)[(i)>>5] |= (1<<((i) & 31))) +#define Sim_XorBit(p,i) ((p)[(i)>>5] ^= (1<<((i) & 31))) +#define Sim_HasBit(p,i) (((p)[(i)>>5] & (1<<((i) & 31))) > 0) + +// macros to get hold of the support info +#define Sim_SuppStrSetVar(vSupps,pNode,v) Sim_SetBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) +#define Sim_SuppStrHasVar(vSupps,pNode,v) Sim_HasBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) +#define Sim_SuppFunSetVar(vSupps,Output,v) Sim_SetBit((unsigned*)(vSupps)->pArray[Output],(v)) +#define Sim_SuppFunHasVar(vSupps,Output,v) Sim_HasBit((unsigned*)(vSupps)->pArray[Output],(v)) +#define Sim_SimInfoSetVar(vSupps,pNode,v) Sim_SetBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) +#define Sim_SimInfoHasVar(vSupps,pNode,v) Sim_HasBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) +#define Sim_SimInfoGet(vInfo,pNode) ((unsigned *)((vInfo)->pArray[(pNode)->Id])) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== simMan.c ==========================================================*/ +extern Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose ); +extern void Sym_ManStop( Sym_Man_t * p ); +extern void Sym_ManPrintStats( Sym_Man_t * p ); +extern Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight ); +extern void Sim_ManStop( Sim_Man_t * p ); +extern void Sim_ManPrintStats( Sim_Man_t * p ); +extern Sim_Pat_t * Sim_ManPatAlloc( Sim_Man_t * p ); +extern void Sim_ManPatFree( Sim_Man_t * p, Sim_Pat_t * pPat ); +/*=== simSeq.c ==========================================================*/ +extern Vec_Ptr_t * Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords ); +extern Vec_Ptr_t * Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel ); +/*=== simSupp.c ==========================================================*/ +extern Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ); +/*=== simSym.c ==========================================================*/ +extern int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose ); +/*=== simSymSat.c ==========================================================*/ +extern int Sim_SymmsGetPatternUsingSat( Sym_Man_t * p, unsigned * pPattern ); +/*=== simSymStr.c ==========================================================*/ +extern void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * vSuppFun ); +/*=== simSymSim.c ==========================================================*/ +extern void Sim_SymmsSimulate( Sym_Man_t * p, unsigned * pPatRand, Vec_Ptr_t * vMatrsNonSym ); +/*=== simUtil.c ==========================================================*/ +extern Vec_Ptr_t * Sim_UtilInfoAlloc( int nSize, int nWords, bool fClean ); +extern void Sim_UtilInfoFree( Vec_Ptr_t * p ); +extern void Sim_UtilInfoAdd( unsigned * pInfo1, unsigned * pInfo2, int nWords ); +extern void Sim_UtilInfoDetectDiffs( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ); +extern void Sim_UtilInfoDetectNews( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ); +extern void Sim_UtilInfoFlip( Sim_Man_t * p, Abc_Obj_t * pNode ); +extern bool Sim_UtilInfoCompare( Sim_Man_t * p, Abc_Obj_t * pNode ); +extern void Sim_UtilSimulate( Sim_Man_t * p, bool fFirst ); +extern void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fType1, bool fType2 ); +extern void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset ); +extern void Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift ); +extern int Sim_UtilCountSuppSizes( Sim_Man_t * p, int fStruct ); +extern int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords ); +extern Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords ); +extern void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords ); +extern void Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords ); +extern void Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 ); +extern int Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords ); +extern int Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords ); +extern int Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords ); +extern int Sim_UtilCountAllPairs( Vec_Ptr_t * vSuppFun, int nSimWords, Vec_Int_t * vCounters ); +extern void Sim_UtilCountPairsAll( Sym_Man_t * p ); +extern int Sim_UtilMatrsAreDisjoint( Sym_Man_t * p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/opt/sim/simMan.c b/abc70930/src/opt/sim/simMan.c new file mode 100644 index 00000000..3b50ad84 --- /dev/null +++ b/abc70930/src/opt/sim/simMan.c @@ -0,0 +1,288 @@ +/**CFile**************************************************************** + + FileName [simMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Simulation manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: simMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Sym_Man_t * p; + int i, v; + // start the manager + p = ALLOC( Sym_Man_t, 1 ); + memset( p, 0, sizeof(Sym_Man_t) ); + p->pNtk = pNtk; + p->vNodes = Abc_NtkDfs( pNtk, 0 ); + p->nInputs = Abc_NtkCiNum(p->pNtk); + p->nOutputs = Abc_NtkCoNum(p->pNtk); + // internal simulation information + p->nSimWords = SIM_NUM_WORDS(p->nInputs); + p->vSim = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 ); + // symmetry info for each output + p->vMatrSymms = Vec_PtrStart( p->nOutputs ); + p->vMatrNonSymms = Vec_PtrStart( p->nOutputs ); + p->vPairsTotal = Vec_IntStart( p->nOutputs ); + p->vPairsSym = Vec_IntStart( p->nOutputs ); + p->vPairsNonSym = Vec_IntStart( p->nOutputs ); + for ( i = 0; i < p->nOutputs; i++ ) + { + p->vMatrSymms->pArray[i] = Extra_BitMatrixStart( p->nInputs ); + p->vMatrNonSymms->pArray[i] = Extra_BitMatrixStart( p->nInputs ); + } + // temporary patterns + p->uPatRand = ALLOC( unsigned, p->nSimWords ); + p->uPatCol = ALLOC( unsigned, p->nSimWords ); + p->uPatRow = ALLOC( unsigned, p->nSimWords ); + p->vVarsU = Vec_IntStart( 100 ); + p->vVarsV = Vec_IntStart( 100 ); + // compute supports + p->vSuppFun = Sim_ComputeFunSupp( pNtk, fVerbose ); + p->vSupports = Vec_VecStart( p->nOutputs ); + for ( i = 0; i < p->nOutputs; i++ ) + for ( v = 0; v < p->nInputs; v++ ) + if ( Sim_SuppFunHasVar( p->vSuppFun, i, v ) ) + Vec_VecPush( p->vSupports, i, (void *)v ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sym_ManStop( Sym_Man_t * p ) +{ + int i; + Sym_ManPrintStats( p ); + if ( p->vSuppFun ) Sim_UtilInfoFree( p->vSuppFun ); + if ( p->vSim ) Sim_UtilInfoFree( p->vSim ); + if ( p->vNodes ) Vec_PtrFree( p->vNodes ); + if ( p->vSupports ) Vec_VecFree( p->vSupports ); + for ( i = 0; i < p->nOutputs; i++ ) + { + Extra_BitMatrixStop( p->vMatrSymms->pArray[i] ); + Extra_BitMatrixStop( p->vMatrNonSymms->pArray[i] ); + } + Vec_IntFree( p->vVarsU ); + Vec_IntFree( p->vVarsV ); + Vec_PtrFree( p->vMatrSymms ); + Vec_PtrFree( p->vMatrNonSymms ); + Vec_IntFree( p->vPairsTotal ); + Vec_IntFree( p->vPairsSym ); + Vec_IntFree( p->vPairsNonSym ); + FREE( p->uPatRand ); + FREE( p->uPatCol ); + FREE( p->uPatRow ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Prints the manager statisticis.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sym_ManPrintStats( Sym_Man_t * p ) +{ +// printf( "Inputs = %5d. Outputs = %5d. Sim words = %5d.\n", +// Abc_NtkCiNum(p->pNtk), Abc_NtkCoNum(p->pNtk), p->nSimWords ); + printf( "Total symm = %8d.\n", p->nPairsSymm ); + printf( "Structural symm = %8d.\n", p->nPairsSymmStr ); + printf( "Total non-sym = %8d.\n", p->nPairsNonSymm ); + printf( "Total var pairs = %8d.\n", p->nPairsTotal ); + printf( "Sat runs SAT = %8d.\n", p->nSatRunsSat ); + printf( "Sat runs UNSAT = %8d.\n", p->nSatRunsUnsat ); + PRT( "Structural ", p->timeStruct ); + PRT( "Simulation ", p->timeSim ); + PRT( "Matrix ", p->timeMatr ); + PRT( "Counting ", p->timeCount ); + PRT( "Fraiging ", p->timeFraig ); + PRT( "SAT ", p->timeSat ); + PRT( "TOTAL ", p->timeTotal ); +} + + +/**Function************************************************************* + + Synopsis [Starts the simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight ) +{ + Sim_Man_t * p; + // start the manager + p = ALLOC( Sim_Man_t, 1 ); + memset( p, 0, sizeof(Sim_Man_t) ); + p->pNtk = pNtk; + p->nInputs = Abc_NtkCiNum(p->pNtk); + p->nOutputs = Abc_NtkCoNum(p->pNtk); + // internal simulation information + p->nSimBits = 2048; + p->nSimWords = SIM_NUM_WORDS(p->nSimBits); + p->vSim0 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 ); + p->fLightweight = fLightweight; + if (!p->fLightweight) { + p->vSim1 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 ); + // support information + p->nSuppBits = Abc_NtkCiNum(pNtk); + p->nSuppWords = SIM_NUM_WORDS(p->nSuppBits); + p->vSuppStr = Sim_ComputeStrSupp( pNtk ); + p->vSuppFun = Sim_UtilInfoAlloc( Abc_NtkCoNum(p->pNtk), p->nSuppWords, 1 ); + // other data + p->pMmPat = Extra_MmFixedStart( sizeof(Sim_Pat_t) + p->nSuppWords * sizeof(unsigned) ); + p->vFifo = Vec_PtrAlloc( 100 ); + p->vDiffs = Vec_IntAlloc( 100 ); + // allocate support targets (array of unresolved outputs for each input) + p->vSuppTargs = Vec_VecStart( p->nInputs ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_ManStop( Sim_Man_t * p ) +{ + Sim_ManPrintStats( p ); + if ( p->vSim0 ) Sim_UtilInfoFree( p->vSim0 ); + if ( p->vSim1 ) Sim_UtilInfoFree( p->vSim1 ); + if ( p->vSuppStr ) Sim_UtilInfoFree( p->vSuppStr ); +// if ( p->vSuppFun ) Sim_UtilInfoFree( p->vSuppFun ); + if ( p->vSuppTargs ) Vec_VecFree( p->vSuppTargs ); + if ( p->pMmPat ) Extra_MmFixedStop( p->pMmPat ); + if ( p->vFifo ) Vec_PtrFree( p->vFifo ); + if ( p->vDiffs ) Vec_IntFree( p->vDiffs ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Prints the manager statisticis.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_ManPrintStats( Sim_Man_t * p ) +{ +// printf( "Inputs = %5d. Outputs = %5d. Sim words = %5d.\n", +// Abc_NtkCiNum(p->pNtk), Abc_NtkCoNum(p->pNtk), p->nSimWords ); + printf( "Total func supps = %8d.\n", Sim_UtilCountSuppSizes(p, 0) ); + printf( "Total struct supps = %8d.\n", Sim_UtilCountSuppSizes(p, 1) ); + printf( "Sat runs SAT = %8d.\n", p->nSatRunsSat ); + printf( "Sat runs UNSAT = %8d.\n", p->nSatRunsUnsat ); + PRT( "Simulation ", p->timeSim ); + PRT( "Traversal ", p->timeTrav ); + PRT( "Fraiging ", p->timeFraig ); + PRT( "SAT ", p->timeSat ); + PRT( "TOTAL ", p->timeTotal ); +} + + + +/**Function************************************************************* + + Synopsis [Returns one simulation pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sim_Pat_t * Sim_ManPatAlloc( Sim_Man_t * p ) +{ + Sim_Pat_t * pPat; + pPat = (Sim_Pat_t *)Extra_MmFixedEntryFetch( p->pMmPat ); + pPat->Output = -1; + pPat->pData = (unsigned *)((char *)pPat + sizeof(Sim_Pat_t)); + memset( pPat->pData, 0, p->nSuppWords * sizeof(unsigned) ); + return pPat; +} + +/**Function************************************************************* + + Synopsis [Returns one simulation pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_ManPatFree( Sim_Man_t * p, Sim_Pat_t * pPat ) +{ + Extra_MmFixedEntryRecycle( p->pMmPat, (char *)pPat ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/sim/simSat.c b/abc70930/src/opt/sim/simSat.c new file mode 100644 index 00000000..d514f7f2 --- /dev/null +++ b/abc70930/src/opt/sim/simSat.c @@ -0,0 +1,48 @@ +/**CFile**************************************************************** + + FileName [simSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Simulation to determine functional support.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: simSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/sim/simSeq.c b/abc70930/src/opt/sim/simSeq.c new file mode 100644 index 00000000..49fb939f --- /dev/null +++ b/abc70930/src/opt/sim/simSeq.c @@ -0,0 +1,171 @@ +/**CFile**************************************************************** + + FileName [simSeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Simulation for sequential circuits.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: simUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Simulates sequential circuit.] + + Description [Takes sequential circuit (pNtk). Simulates the given number + (nFrames) of the circuit with the given number of machine words (nWords) + of random simulation data, starting from the initial state. If the initial + state of some latches is a don't-care, uses random input for that latch.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords ) +{ + Vec_Ptr_t * vInfo; + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nWords * nFrames, 0 ); + // set the constant data + pNode = Abc_AigConst1(pNtk); + Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames, 1 ); + // set the random PI data + Abc_NtkForEachPi( pNtk, pNode, i ) + Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames ); + // set the initial state data + Abc_NtkForEachLatch( pNtk, pNode, i ) + if ( Abc_LatchIsInit0(pNode) ) + Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 0 ); + else if ( Abc_LatchIsInit1(pNode) ) + Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 1 ); + else + Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords ); + // simulate the nodes for the given number of timeframes + for ( i = 0; i < nFrames; i++ ) + Sim_SimulateSeqFrame( vInfo, pNtk, i, nWords, (int)(i < nFrames-1) ); + return vInfo; +} + +/**Function************************************************************* + + Synopsis [Simulates sequential circuit.] + + Description [Takes sequential circuit (pNtk). Simulates the given number + (nFrames) of the circuit with the given model. The model is assumed to + contain values of PIs for each frame. The latches are initialized to + the initial state. One word of data is simulated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel ) +{ + Vec_Ptr_t * vInfo; + Abc_Obj_t * pNode; + unsigned * pUnsigned; + int i, k; + vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nFrames, 0 ); + // set the constant data + pNode = Abc_AigConst1(pNtk); + Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nFrames, 1 ); + // set the random PI data + Abc_NtkForEachPi( pNtk, pNode, i ) + { + pUnsigned = Sim_SimInfoGet(vInfo,pNode); + for ( k = 0; k < nFrames; k++ ) + pUnsigned[k] = pModel[k * Abc_NtkPiNum(pNtk) + i] ? ~((unsigned)0) : 0; + } + // set the initial state data + Abc_NtkForEachLatch( pNtk, pNode, i ) + { + pUnsigned = Sim_SimInfoGet(vInfo,pNode); + if ( Abc_LatchIsInit0(pNode) ) + pUnsigned[0] = 0; + else if ( Abc_LatchIsInit1(pNode) ) + pUnsigned[0] = ~((unsigned)0); + else + pUnsigned[0] = SIM_RANDOM_UNSIGNED; + } + // simulate the nodes for the given number of timeframes + for ( i = 0; i < nFrames; i++ ) + Sim_SimulateSeqFrame( vInfo, pNtk, i, 1, (int)(i < nFrames-1) ); +/* + // print the simulated values + for ( i = 0; i < nFrames; i++ ) + { + printf( "Frame %d : ", i+1 ); + Abc_NtkForEachPi( pNtk, pNode, k ) + printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 ); + printf( " " ); + Abc_NtkForEachLatch( pNtk, pNode, k ) + printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 ); + printf( " " ); + Abc_NtkForEachPo( pNtk, pNode, k ) + printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 ); + printf( "\n" ); + } + printf( "\n" ); +*/ + return vInfo; +} + +/**Function************************************************************* + + Synopsis [Simulates one frame of sequential circuit.] + + Description [Assumes that the latches and POs are already initialized. + In the end transfers the data to the latches of the next frame.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer ) +{ + Abc_Obj_t * pNode; + int i; + Abc_NtkForEachNode( pNtk, pNode, i ) + Sim_UtilSimulateNodeOne( pNode, vInfo, nWords, iFrames * nWords ); + Abc_NtkForEachPo( pNtk, pNode, i ) + Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 0 ); + if ( !fTransfer ) + return; + Abc_NtkForEachLatch( pNtk, pNode, i ) + Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 1 ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/sim/simSupp.c b/abc70930/src/opt/sim/simSupp.c new file mode 100644 index 00000000..f7048f4a --- /dev/null +++ b/abc70930/src/opt/sim/simSupp.c @@ -0,0 +1,597 @@ +/**CFile**************************************************************** + + FileName [simSupp.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Simulation to determine functional support.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: simSupp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Sim_ComputeSuppRound( Sim_Man_t * p, bool fUseTargets ); +static int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, bool fUseTargets ); +static void Sim_ComputeSuppSetTargets( Sim_Man_t * p ); + +static void Sim_UtilAssignRandom( Sim_Man_t * p ); +static void Sim_UtilAssignFromFifo( Sim_Man_t * p ); +static void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int nCounters ); +static int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes structural supports.] + + Description [Supports are returned as an array of bit strings, one + for each CO.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSuppStr; + Abc_Obj_t * pNode; + unsigned * pSimmNode, * pSimmNode1, * pSimmNode2; + int nSuppWords, i, k; + // allocate room for structural supports + nSuppWords = SIM_NUM_WORDS( Abc_NtkCiNum(pNtk) ); + vSuppStr = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nSuppWords, 1 ); + // assign the structural support to the PIs + Abc_NtkForEachCi( pNtk, pNode, i ) + Sim_SuppStrSetVar( vSuppStr, pNode, i ); + // derive the structural supports of the internal nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + { +// if ( Abc_NodeIsConst(pNode) ) +// continue; + pSimmNode = vSuppStr->pArray[ pNode->Id ]; + pSimmNode1 = vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ]; + pSimmNode2 = vSuppStr->pArray[ Abc_ObjFaninId1(pNode) ]; + for ( k = 0; k < nSuppWords; k++ ) + pSimmNode[k] = pSimmNode1[k] | pSimmNode2[k]; + } + // set the structural supports of the PO nodes + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pSimmNode = vSuppStr->pArray[ pNode->Id ]; + pSimmNode1 = vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ]; + for ( k = 0; k < nSuppWords; k++ ) + pSimmNode[k] = pSimmNode1[k]; + } + return vSuppStr; +} + +/**Function************************************************************* + + Synopsis [Compute functional supports.] + + Description [Supports are returned as an array of bit strings, one + for each CO.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Sim_Man_t * p; + Vec_Ptr_t * vResult; + int nSolved, i, clk = clock(); + + srand( 0xABC ); + + // start the simulation manager + p = Sim_ManStart( pNtk, 0 ); + + // compute functional support using one round of random simulation + Sim_UtilAssignRandom( p ); + Sim_ComputeSuppRound( p, 0 ); + + // set the support targets + Sim_ComputeSuppSetTargets( p ); +if ( fVerbose ) + printf( "Number of support targets after simulation = %5d.\n", Vec_VecSizeSize(p->vSuppTargs) ); + if ( Vec_VecSizeSize(p->vSuppTargs) == 0 ) + goto exit; + + for ( i = 0; i < 1; i++ ) + { + // compute patterns using one round of random simulation + Sim_UtilAssignRandom( p ); + nSolved = Sim_ComputeSuppRound( p, 1 ); + if ( Vec_VecSizeSize(p->vSuppTargs) == 0 ) + goto exit; + +if ( fVerbose ) + printf( "Targets = %5d. Solved = %5d. Fifo = %5d.\n", + Vec_VecSizeSize(p->vSuppTargs), nSolved, Vec_PtrSize(p->vFifo) ); + } + + // try to solve the support targets + while ( Vec_VecSizeSize(p->vSuppTargs) > 0 ) + { + // solve targets until the first disproved one (which gives counter-example) + Sim_SolveTargetsUsingSat( p, p->nSimWords/p->nSuppWords ); + // compute additional functional support + Sim_UtilAssignFromFifo( p ); + nSolved = Sim_ComputeSuppRound( p, 1 ); + +if ( fVerbose ) + printf( "Targets = %5d. Solved = %5d. Fifo = %5d. SAT runs = %3d.\n", + Vec_VecSizeSize(p->vSuppTargs), nSolved, Vec_PtrSize(p->vFifo), p->nSatRuns ); + } + +exit: +p->timeTotal = clock() - clk; + vResult = p->vSuppFun; + // p->vSuppFun = NULL; + Sim_ManStop( p ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Computes functional support using one round of simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_ComputeSuppRound( Sim_Man_t * p, bool fUseTargets ) +{ + Vec_Int_t * vTargets; + int i, Counter = 0; + int clk; + // perform one round of random simulation +clk = clock(); + Sim_UtilSimulate( p, 0 ); +p->timeSim += clock() - clk; + // iterate through the CIs and detect COs that depend on them + for ( i = p->iInput; i < p->nInputs; i++ ) + { + vTargets = p->vSuppTargs->pArray[i]; + if ( fUseTargets && vTargets->nSize == 0 ) + continue; + Counter += Sim_ComputeSuppRoundNode( p, i, fUseTargets ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Computes functional support for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, bool fUseTargets ) +{ + int fVerbose = 0; + Sim_Pat_t * pPat; + Vec_Int_t * vTargets; + Vec_Vec_t * vNodesByLevel; + Abc_Obj_t * pNodeCi, * pNode; + int i, k, v, Output, LuckyPat, fType0, fType1; + int Counter = 0; + int fFirst = 1; + int clk; + // collect nodes by level in the TFO of the CI + // this proceduredoes not collect the CIs and COs + // but it increments TravId of the collected nodes and CIs/COs +clk = clock(); + pNodeCi = Abc_NtkCi( p->pNtk, iNumCi ); + vNodesByLevel = Abc_DfsLevelized( pNodeCi, 0 ); +p->timeTrav += clock() - clk; + // complement the simulation info of the selected CI + Sim_UtilInfoFlip( p, pNodeCi ); + // simulate the levelized structure of nodes + Vec_VecForEachEntry( vNodesByLevel, pNode, i, k ) + { + fType0 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin0(pNode) ); + fType1 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin1(pNode) ); +clk = clock(); + Sim_UtilSimulateNode( p, pNode, 1, fType0, fType1 ); +p->timeSim += clock() - clk; + } + // set the simulation info of the affected COs + if ( fUseTargets ) + { + vTargets = p->vSuppTargs->pArray[iNumCi]; + for ( i = vTargets->nSize - 1; i >= 0; i-- ) + { + // get the target output + Output = vTargets->pArray[i]; + // get the target node + pNode = Abc_ObjFanin0( Abc_NtkCo(p->pNtk, Output) ); + // the output should be in the cone + assert( Abc_NodeIsTravIdCurrent(pNode) ); + + // skip if the simulation info is equal + if ( Sim_UtilInfoCompare( p, pNode ) ) + continue; + + // otherwise, we solved a new target + Vec_IntRemove( vTargets, Output ); +if ( fVerbose ) + printf( "(%d,%d) ", iNumCi, Output ); + Counter++; + // make sure this variable is not yet detected + assert( !Sim_SuppFunHasVar(p->vSuppFun, Output, iNumCi) ); + // set this variable + Sim_SuppFunSetVar( p->vSuppFun, Output, iNumCi ); + + // detect the differences in the simulation info + Sim_UtilInfoDetectDiffs( p->vSim0->pArray[pNode->Id], p->vSim1->pArray[pNode->Id], p->nSimWords, p->vDiffs ); + // create new patterns + if ( !fFirst && p->vFifo->nSize > 1000 ) + continue; + + Vec_IntForEachEntry( p->vDiffs, LuckyPat, k ) + { + // set the new pattern + pPat = Sim_ManPatAlloc( p ); + pPat->Input = iNumCi; + pPat->Output = Output; + Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) + if ( Sim_SimInfoHasVar( p->vSim0, pNodeCi, LuckyPat ) ) + Sim_SetBit( pPat->pData, v ); + Vec_PtrPush( p->vFifo, pPat ); + + fFirst = 0; + break; + } + } +if ( fVerbose && Counter ) +printf( "\n" ); + } + else + { + Abc_NtkForEachCo( p->pNtk, pNode, Output ) + { + if ( !Abc_NodeIsTravIdCurrent( pNode ) ) + continue; + if ( !Sim_UtilInfoCompare( p, Abc_ObjFanin0(pNode) ) ) + { + if ( !Sim_SuppFunHasVar(p->vSuppFun, Output, iNumCi) ) + { + Counter++; + Sim_SuppFunSetVar( p->vSuppFun, Output, iNumCi ); + } + } + } + } + Vec_VecFree( vNodesByLevel ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Sets the simulation targets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_ComputeSuppSetTargets( Sim_Man_t * p ) +{ + Abc_Obj_t * pNode; + unsigned * pSuppStr, * pSuppFun; + int i, k, Num; + Abc_NtkForEachCo( p->pNtk, pNode, i ) + { + pSuppStr = p->vSuppStr->pArray[pNode->Id]; + pSuppFun = p->vSuppFun->pArray[i]; + // find vars in the structural support that are not in the functional support + Sim_UtilInfoDetectNews( pSuppFun, pSuppStr, p->nSuppWords, p->vDiffs ); + Vec_IntForEachEntry( p->vDiffs, Num, k ) + Vec_VecPush( p->vSuppTargs, Num, (void *)i ); + } +} + +/**Function************************************************************* + + Synopsis [Assigns random simulation info to the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilAssignRandom( Sim_Man_t * p ) +{ + Abc_Obj_t * pNode; + unsigned * pSimInfo; + int i, k; + // assign the random/systematic simulation info to the PIs + Abc_NtkForEachCi( p->pNtk, pNode, i ) + { + pSimInfo = p->vSim0->pArray[pNode->Id]; + for ( k = 0; k < p->nSimWords; k++ ) + pSimInfo[k] = SIM_RANDOM_UNSIGNED; + } +} + +/**Function************************************************************* + + Synopsis [Sets the new patterns from fifo.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilAssignFromFifo( Sim_Man_t * p ) +{ + int fUseOneWord = 0; + Abc_Obj_t * pNode; + Sim_Pat_t * pPat; + unsigned * pSimInfo; + int nWordsNew, iWord, iWordLim, i, w; + int iBeg, iEnd; + int Counter = 0; + // go through the patterns and fill in the dist-1 minterms for each + for ( iWord = 0; p->vFifo->nSize > 0; iWord = iWordLim ) + { + ++Counter; + // get the pattern + pPat = Vec_PtrPop( p->vFifo ); + if ( fUseOneWord ) + { + // get the first word of the next series + iWordLim = iWord + 1; + // set the pattern for all PIs from iBit to iWord + p->nInputs + iBeg = p->iInput; + iEnd = ABC_MIN( iBeg + 32, p->nInputs ); +// for ( i = iBeg; i < iEnd; i++ ) + Abc_NtkForEachCi( p->pNtk, pNode, i ) + { + pNode = Abc_NtkCi(p->pNtk,i); + pSimInfo = p->vSim0->pArray[pNode->Id]; + if ( Sim_HasBit(pPat->pData, i) ) + pSimInfo[iWord] = SIM_MASK_FULL; + else + pSimInfo[iWord] = 0; + // flip one bit + if ( i >= iBeg && i < iEnd ) + Sim_XorBit( pSimInfo + iWord, i-iBeg ); + } + } + else + { + // get the number of words for the remaining inputs + nWordsNew = p->nSuppWords; +// nWordsNew = SIM_NUM_WORDS( p->nInputs - p->iInput ); + // get the first word of the next series + iWordLim = (iWord + nWordsNew < p->nSimWords)? iWord + nWordsNew : p->nSimWords; + // set the pattern for all CIs from iWord to iWord + nWordsNew + Abc_NtkForEachCi( p->pNtk, pNode, i ) + { + pSimInfo = p->vSim0->pArray[pNode->Id]; + if ( Sim_HasBit(pPat->pData, i) ) + { + for ( w = iWord; w < iWordLim; w++ ) + pSimInfo[w] = SIM_MASK_FULL; + } + else + { + for ( w = iWord; w < iWordLim; w++ ) + pSimInfo[w] = 0; + } + Sim_XorBit( pSimInfo + iWord, i ); + // flip one bit +// if ( i >= p->iInput ) +// Sim_XorBit( pSimInfo + iWord, i-p->iInput ); + } + } + Sim_ManPatFree( p, pPat ); + // stop if we ran out of room for patterns + if ( iWordLim == p->nSimWords ) + break; +// if ( Counter == 1 ) +// break; + } +} + +/**Function************************************************************* + + Synopsis [Get the given number of counter-examples using SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int Limit ) +{ + Fraig_Params_t Params; + Fraig_Man_t * pMan; + Abc_Obj_t * pNodeCi; + Abc_Ntk_t * pMiter; + Sim_Pat_t * pPat; + void * pEntry; + int * pModel; + int RetValue, Output, Input, k, v; + int Counter = 0; + int clk; + + p->nSatRuns = 0; + // put targets into one array + Vec_VecForEachEntryReverse( p->vSuppTargs, pEntry, Input, k ) + { + p->nSatRuns++; + Output = (int)pEntry; + + // set up the miter for the two cofactors of this output w.r.t. this input + pMiter = Abc_NtkMiterForCofactors( p->pNtk, Output, Input, -1 ); + + // transform the miter into a fraig + Fraig_ParamsSetDefault( &Params ); + Params.nSeconds = ABC_INFINITY; + Params.fInternal = 1; +clk = clock(); + pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 ); +p->timeFraig += clock() - clk; +clk = clock(); + Fraig_ManProveMiter( pMan ); +p->timeSat += clock() - clk; + + // analyze the result + RetValue = Fraig_ManCheckMiter( pMan ); + assert( RetValue >= 0 ); + if ( RetValue == 1 ) // unsat + { + p->nSatRunsUnsat++; + pModel = NULL; + Vec_PtrRemove( p->vSuppTargs->pArray[Input], pEntry ); + } + else // sat + { + p->nSatRunsSat++; + pModel = Fraig_ManReadModel( pMan ); + assert( pModel != NULL ); + assert( Sim_SolveSuppModelVerify( p->pNtk, pModel, Input, Output ) ); + +//printf( "Solved by SAT (%d,%d).\n", Input, Output ); + // set the new pattern + pPat = Sim_ManPatAlloc( p ); + pPat->Input = Input; + pPat->Output = Output; + Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) + if ( pModel[v] ) + Sim_SetBit( pPat->pData, v ); + Vec_PtrPush( p->vFifo, pPat ); +/* + // set the new pattern + pPat = Sim_ManPatAlloc( p ); + pPat->Input = Input; + pPat->Output = Output; + Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) + if ( pModel[v] ) + Sim_SetBit( pPat->pData, v ); + Sim_XorBit( pPat->pData, Input ); // add this bit in the opposite polarity + Vec_PtrPush( p->vFifo, pPat ); +*/ + Counter++; + } + // delete the fraig manager + Fraig_ManFree( pMan ); + // delete the miter + Abc_NtkDelete( pMiter ); + + // makr the input, which we are processing + p->iInput = Input; + + // stop when we found enough patterns +// if ( Counter == Limit ) + if ( Counter == 1 ) + return; + } +} + + +/**Function************************************************************* + + Synopsis [Saves the counter example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_NtkSimTwoPats_rec( Abc_Obj_t * pNode ) +{ + int Value0, Value1; + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return (int)pNode->pCopy; + Abc_NodeSetTravIdCurrent( pNode ); + Value0 = Sim_NtkSimTwoPats_rec( Abc_ObjFanin0(pNode) ); + Value1 = Sim_NtkSimTwoPats_rec( Abc_ObjFanin1(pNode) ); + if ( Abc_ObjFaninC0(pNode) ) + Value0 = ~Value0; + if ( Abc_ObjFaninC1(pNode) ) + Value1 = ~Value1; + pNode->pCopy = (Abc_Obj_t *)(Value0 & Value1); + return Value0 & Value1; +} + +/**Function************************************************************* + + Synopsis [Verifies that pModel proves the presence of Input in the support of Output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output ) +{ + Abc_Obj_t * pNode; + int RetValue, i; + // set the PI values + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCi( pNtk, pNode, i ) + { + Abc_NodeSetTravIdCurrent( pNode ); + if ( pNode == Abc_NtkCi(pNtk,Input) ) + pNode->pCopy = (Abc_Obj_t *)1; + else if ( pModel[i] == 1 ) + pNode->pCopy = (Abc_Obj_t *)3; + else + pNode->pCopy = NULL; + } + // perform the traversal + RetValue = 3 & Sim_NtkSimTwoPats_rec( Abc_ObjFanin0( Abc_NtkCo(pNtk,Output) ) ); +// assert( RetValue == 1 || RetValue == 2 ); + return RetValue == 1 || RetValue == 2; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/sim/simSwitch.c b/abc70930/src/opt/sim/simSwitch.c new file mode 100644 index 00000000..218d4d59 --- /dev/null +++ b/abc70930/src/opt/sim/simSwitch.c @@ -0,0 +1,107 @@ +/**CFile**************************************************************** + + FileName [simSwitch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Computes switching activity of nodes in the ABC network.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: simSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Sim_NodeSimulate( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ); +static float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes switching activity using simulation.] + + Description [Computes switching activity, which is understood as the + probability of switching under random simulation. Assigns the + random simulation information at the CI and propagates it through + the internal nodes of the AIG.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ) +{ + Vec_Int_t * vSwitching; + float * pSwitching; + Vec_Ptr_t * vNodes; + Vec_Ptr_t * vSimInfo; + Abc_Obj_t * pNode; + unsigned * pSimInfo; + int nSimWords, i; + + // allocate space for simulation info of all nodes + nSimWords = SIM_NUM_WORDS(nPatterns); + vSimInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nSimWords, 0 ); + // assign the random simulation to the CIs + vSwitching = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); + pSwitching = (float *)vSwitching->pArray; + Abc_NtkForEachCi( pNtk, pNode, i ) + { + pSimInfo = Vec_PtrEntry(vSimInfo, pNode->Id); + Sim_UtilSetRandom( pSimInfo, nSimWords ); + pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords ); + } + // simulate the internal nodes + vNodes = Abc_AigDfs( pNtk, 1, 0 ); + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + pSimInfo = Vec_PtrEntry(vSimInfo, pNode->Id); + Sim_UtilSimulateNodeOne( pNode, vSimInfo, nSimWords, 0 ); + pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords ); + } + Vec_PtrFree( vNodes ); + Sim_UtilInfoFree( vSimInfo ); + return vSwitching; +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords ) +{ + int nOnes, nTotal; + nTotal = 32 * nSimWords; + nOnes = Sim_UtilCountOnes( pSimInfo, nSimWords ); + return (float)2.0 * nOnes * (nTotal - nOnes) / nTotal / nTotal; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/sim/simSym.c b/abc70930/src/opt/sim/simSym.c new file mode 100644 index 00000000..71de5b05 --- /dev/null +++ b/abc70930/src/opt/sim/simSym.c @@ -0,0 +1,142 @@ +/**CFile**************************************************************** + + FileName [simSym.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Simulation to determine two-variable symmetries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: simSym.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes two variable symmetries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Sym_Man_t * p; + Vec_Ptr_t * vResult; + int Result; + int i, clk, clkTotal = clock(); + + srand( 0xABC ); + + // start the simulation manager + p = Sym_ManStart( pNtk, fVerbose ); + p->nPairsTotal = p->nPairsRem = Sim_UtilCountAllPairs( p->vSuppFun, p->nSimWords, p->vPairsTotal ); + if ( fVerbose ) + printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", + p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); + + // detect symmetries using circuit structure +clk = clock(); + Sim_SymmsStructCompute( pNtk, p->vMatrSymms, p->vSuppFun ); +p->timeStruct = clock() - clk; + + Sim_UtilCountPairsAll( p ); + p->nPairsSymmStr = p->nPairsSymm; + if ( fVerbose ) + printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", + p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); + + // detect symmetries using simulation + for ( i = 1; i <= 1000; i++ ) + { + // simulate this pattern + Sim_UtilSetRandom( p->uPatRand, p->nSimWords ); + Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); + if ( i % 50 != 0 ) + continue; + // check disjointness + assert( Sim_UtilMatrsAreDisjoint( p ) ); + // count the number of pairs + Sim_UtilCountPairsAll( p ); + if ( i % 500 != 0 ) + continue; + if ( fVerbose ) + printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", + p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); + } + + // detect symmetries using SAT + for ( i = 1; Sim_SymmsGetPatternUsingSat( p, p->uPatRand ); i++ ) + { + // simulate this pattern in four polarities + Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); + Sim_XorBit( p->uPatRand, p->iVar1 ); + Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); + Sim_XorBit( p->uPatRand, p->iVar2 ); + Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); + Sim_XorBit( p->uPatRand, p->iVar1 ); + Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); + Sim_XorBit( p->uPatRand, p->iVar2 ); +/* + // try the previuos pair + Sim_XorBit( p->uPatRand, p->iVar1Old ); + Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); + Sim_XorBit( p->uPatRand, p->iVar2Old ); + Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); + Sim_XorBit( p->uPatRand, p->iVar1Old ); + Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); +*/ + if ( i % 10 != 0 ) + continue; + // check disjointness + assert( Sim_UtilMatrsAreDisjoint( p ) ); + // count the number of pairs + Sim_UtilCountPairsAll( p ); + if ( i % 50 != 0 ) + continue; + if ( fVerbose ) + printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", + p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); + } + + // count the number of pairs + Sim_UtilCountPairsAll( p ); + if ( fVerbose ) + printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", + p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); +// Sim_UtilCountPairsAllPrint( p ); + + Result = p->nPairsSymm; + vResult = p->vMatrSymms; +p->timeTotal = clock() - clkTotal; + // p->vMatrSymms = NULL; + Sym_ManStop( p ); + return Result; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/sim/simSymSat.c b/abc70930/src/opt/sim/simSymSat.c new file mode 100644 index 00000000..7690a891 --- /dev/null +++ b/abc70930/src/opt/sim/simSymSat.c @@ -0,0 +1,199 @@ +/**CFile**************************************************************** + + FileName [simSymSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Satisfiability to determine two variable symmetries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: simSymSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "sim.h" +#include "fraig.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Tries to prove the remaining pairs using SAT.] + + Description [Continues to prove as long as it encounters symmetric pairs. + Returns 1 if a non-symmetric pair is found (which gives a counter-example). + Returns 0 if it finishes considering all pairs for all outputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_SymmsGetPatternUsingSat( Sym_Man_t * p, unsigned * pPattern ) +{ + Vec_Int_t * vSupport; + Extra_BitMat_t * pMatSym, * pMatNonSym; + int Index1, Index2, Index3, IndexU, IndexV; + int v, u, i, k, b, out; + + // iterate through outputs + for ( out = p->iOutput; out < p->nOutputs; out++ ) + { + pMatSym = Vec_PtrEntry( p->vMatrSymms, out ); + pMatNonSym = Vec_PtrEntry( p->vMatrNonSymms, out ); + + // go through the remaining variable pairs + vSupport = Vec_VecEntry( p->vSupports, out ); + Vec_IntForEachEntry( vSupport, v, Index1 ) + Vec_IntForEachEntryStart( vSupport, u, Index2, Index1+1 ) + { + if ( Extra_BitMatrixLookup1( pMatSym, v, u ) || Extra_BitMatrixLookup1( pMatNonSym, v, u ) ) + continue; + p->nSatRuns++; + + // collect the support variables that are symmetric with u and v + Vec_IntClear( p->vVarsU ); + Vec_IntClear( p->vVarsV ); + Vec_IntForEachEntry( vSupport, b, Index3 ) + { + if ( Extra_BitMatrixLookup1( pMatSym, u, b ) ) + Vec_IntPush( p->vVarsU, b ); + if ( Extra_BitMatrixLookup1( pMatSym, v, b ) ) + Vec_IntPush( p->vVarsV, b ); + } + + if ( Sim_SymmsSatProveOne( p, out, v, u, pPattern ) ) + { // update the symmetric variable info + p->nSatRunsUnsat++; + Vec_IntForEachEntry( p->vVarsU, i, IndexU ) + Vec_IntForEachEntry( p->vVarsV, k, IndexV ) + { + Extra_BitMatrixInsert1( pMatSym, i, k ); // Theorem 1 + Extra_BitMatrixInsert2( pMatSym, i, k ); // Theorem 1 + Extra_BitMatrixOrTwo( pMatNonSym, i, k ); // Theorem 2 + } + } + else + { // update the assymmetric variable info + p->nSatRunsSat++; + Vec_IntForEachEntry( p->vVarsU, i, IndexU ) + Vec_IntForEachEntry( p->vVarsV, k, IndexV ) + { + Extra_BitMatrixInsert1( pMatNonSym, i, k ); // Theorem 3 + Extra_BitMatrixInsert2( pMatNonSym, i, k ); // Theorem 3 + } + + // remember the out + p->iOutput = out; + p->iVar1Old = p->iVar1; + p->iVar2Old = p->iVar2; + p->iVar1 = v; + p->iVar2 = u; + return 1; + + } + } + // make sure that the symmetry matrix contains only cliques + assert( Extra_BitMatrixIsClique( pMatSym ) ); + } + + // mark that we finished all outputs + p->iOutput = p->nOutputs; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the variables are symmetric; 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern ) +{ + Fraig_Params_t Params; + Fraig_Man_t * pMan; + Abc_Ntk_t * pMiter; + int RetValue, i, clk; + int * pModel; + + // get the miter for this problem + pMiter = Abc_NtkMiterForCofactors( p->pNtk, Out, Var1, Var2 ); + // transform the miter into a fraig + Fraig_ParamsSetDefault( &Params ); + Params.fInternal = 1; + Params.nPatsRand = 512; + Params.nPatsDyna = 512; + Params.nSeconds = ABC_INFINITY; + +clk = clock(); + pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 ); +p->timeFraig += clock() - clk; +clk = clock(); + Fraig_ManProveMiter( pMan ); +p->timeSat += clock() - clk; + + // analyze the result + RetValue = Fraig_ManCheckMiter( pMan ); +// assert( RetValue >= 0 ); + // save the pattern + if ( RetValue == 0 ) + { + // get the pattern + pModel = Fraig_ManReadModel( pMan ); + assert( pModel != NULL ); +//printf( "Disproved by SAT: out = %d pair = (%d, %d)\n", Out, Var1, Var2 ); + // transfer the model into the pattern + for ( i = 0; i < p->nSimWords; i++ ) + pPattern[i] = 0; + for ( i = 0; i < p->nInputs; i++ ) + if ( pModel[i] ) + Sim_SetBit( pPattern, i ); + // make sure these variables have the same value (1) + Sim_SetBit( pPattern, Var1 ); + Sim_SetBit( pPattern, Var2 ); + } + else if ( RetValue == -1 ) + { + // this should never happen; if it happens, such is life + // we are conservative and assume that there is no symmetry +//printf( "STRANGE THING: out = %d %s pair = (%d %s, %d %s)\n", +// Out, Abc_ObjName(Abc_NtkCo(p->pNtk,Out)), +// Var1, Abc_ObjName(Abc_NtkCi(p->pNtk,Var1)), +// Var2, Abc_ObjName(Abc_NtkCi(p->pNtk,Var2)) ); + memset( pPattern, 0, sizeof(unsigned) * p->nSimWords ); + RetValue = 0; + } + // delete the fraig manager + Fraig_ManFree( pMan ); + // delete the miter + Abc_NtkDelete( pMiter ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/sim/simSymSim.c b/abc70930/src/opt/sim/simSymSim.c new file mode 100644 index 00000000..2282825b --- /dev/null +++ b/abc70930/src/opt/sim/simSymSim.c @@ -0,0 +1,173 @@ +/**CFile**************************************************************** + + FileName [simSymSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Simulation to determine two-variable symmetries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: simSymSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Sim_SymmsCreateSquare( Sym_Man_t * p, unsigned * pPat ); +static void Sim_SymmsDeriveInfo( Sym_Man_t * p, unsigned * pPat, Abc_Obj_t * pNode, Vec_Ptr_t * vMatrsNonSym, int Output ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Detects non-symmetric pairs using one pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SymmsSimulate( Sym_Man_t * p, unsigned * pPat, Vec_Ptr_t * vMatrsNonSym ) +{ + Abc_Obj_t * pNode; + int i, nPairsTotal, nPairsSym, nPairsNonSym; + int clk; + + // create the simulation matrix + Sim_SymmsCreateSquare( p, pPat ); + // simulate each node in the DFS order +clk = clock(); + Vec_PtrForEachEntry( p->vNodes, pNode, i ) + { +// if ( Abc_NodeIsConst(pNode) ) +// continue; + Sim_UtilSimulateNodeOne( pNode, p->vSim, p->nSimWords, 0 ); + } +p->timeSim += clock() - clk; + // collect info into the CO matrices +clk = clock(); + Abc_NtkForEachCo( p->pNtk, pNode, i ) + { + pNode = Abc_ObjFanin0(pNode); +// if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) ) +// continue; + nPairsTotal = Vec_IntEntry(p->vPairsTotal, i); + nPairsSym = Vec_IntEntry(p->vPairsSym, i); + nPairsNonSym = Vec_IntEntry(p->vPairsNonSym,i); + assert( nPairsTotal >= nPairsSym + nPairsNonSym ); + if ( nPairsTotal == nPairsSym + nPairsNonSym ) + continue; + Sim_SymmsDeriveInfo( p, pPat, pNode, vMatrsNonSym, i ); + } +p->timeMatr += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [Creates the square matrix of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SymmsCreateSquare( Sym_Man_t * p, unsigned * pPat ) +{ + unsigned * pSimInfo; + Abc_Obj_t * pNode; + int i, w; + // for each PI var copy the pattern + Abc_NtkForEachCi( p->pNtk, pNode, i ) + { + pSimInfo = Vec_PtrEntry( p->vSim, pNode->Id ); + if ( Sim_HasBit(pPat, i) ) + { + for ( w = 0; w < p->nSimWords; w++ ) + pSimInfo[w] = SIM_MASK_FULL; + } + else + { + for ( w = 0; w < p->nSimWords; w++ ) + pSimInfo[w] = 0; + } + // flip one bit + Sim_XorBit( pSimInfo, i ); + } +} + +/**Function************************************************************* + + Synopsis [Transfers the info to the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SymmsDeriveInfo( Sym_Man_t * p, unsigned * pPat, Abc_Obj_t * pNode, Vec_Ptr_t * vMatrsNonSym, int Output ) +{ + Extra_BitMat_t * pMat; + Vec_Int_t * vSupport; + unsigned * pSupport; + unsigned * pSimInfo; + int i, w, Index; + // get the matrix, the support, and the simulation info + pMat = Vec_PtrEntry( vMatrsNonSym, Output ); + vSupport = Vec_VecEntry( p->vSupports, Output ); + pSupport = Vec_PtrEntry( p->vSuppFun, Output ); + pSimInfo = Vec_PtrEntry( p->vSim, pNode->Id ); + // generate vectors A1 and A2 + for ( w = 0; w < p->nSimWords; w++ ) + { + p->uPatCol[w] = pSupport[w] & pPat[w] & pSimInfo[w]; + p->uPatRow[w] = pSupport[w] & pPat[w] & ~pSimInfo[w]; + } + // add two dimensions + Vec_IntForEachEntry( vSupport, i, Index ) + if ( Sim_HasBit( p->uPatCol, i ) ) + Extra_BitMatrixOr( pMat, i, p->uPatRow ); + // add two dimensions + Vec_IntForEachEntry( vSupport, i, Index ) + if ( Sim_HasBit( p->uPatRow, i ) ) + Extra_BitMatrixOr( pMat, i, p->uPatCol ); + // generate vectors B1 and B2 + for ( w = 0; w < p->nSimWords; w++ ) + { + p->uPatCol[w] = pSupport[w] & ~pPat[w] & pSimInfo[w]; + p->uPatRow[w] = pSupport[w] & ~pPat[w] & ~pSimInfo[w]; + } + // add two dimensions + Vec_IntForEachEntry( vSupport, i, Index ) + if ( Sim_HasBit( p->uPatCol, i ) ) + Extra_BitMatrixOr( pMat, i, p->uPatRow ); + // add two dimensions + Vec_IntForEachEntry( vSupport, i, Index ) + if ( Sim_HasBit( p->uPatRow, i ) ) + Extra_BitMatrixOr( pMat, i, p->uPatCol ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/sim/simSymStr.c b/abc70930/src/opt/sim/simSymStr.c new file mode 100644 index 00000000..d52c4328 --- /dev/null +++ b/abc70930/src/opt/sim/simSymStr.c @@ -0,0 +1,488 @@ +/**CFile**************************************************************** + + FileName [simSymStr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Structural detection of symmetries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: simSymStr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define SIM_READ_SYMMS(pNode) ((Vec_Int_t *)pNode->pCopy) +#define SIM_SET_SYMMS(pNode,vVect) (pNode->pCopy = (Abc_Obj_t *)(vVect)) + +static void Sim_SymmsStructComputeOne( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int * pMap ); +static void Sim_SymmsBalanceCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); +static void Sim_SymmsPartitionNodes( Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesPis0, Vec_Ptr_t * vNodesPis1, Vec_Ptr_t * vNodesOther ); +static void Sim_SymmsAppendFromGroup( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodesPi, Vec_Ptr_t * vNodesOther, Vec_Int_t * vSymms, int * pMap ); +static void Sim_SymmsAppendFromNode( Abc_Ntk_t * pNtk, Vec_Int_t * vSymms0, Vec_Ptr_t * vNodesOther, Vec_Ptr_t * vNodesPi0, Vec_Ptr_t * vNodesPi1, Vec_Int_t * vSymms, int * pMap ); +static int Sim_SymmsIsCompatibleWithNodes( Abc_Ntk_t * pNtk, unsigned uSymm, Vec_Ptr_t * vNodesOther, int * pMap ); +static int Sim_SymmsIsCompatibleWithGroup( unsigned uSymm, Vec_Ptr_t * vNodesPi, int * pMap ); +static void Sim_SymmsPrint( Vec_Int_t * vSymms ); +static void Sim_SymmsTrans( Vec_Int_t * vSymms ); +static void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * vSymms, unsigned * pSupport ); +static int * Sim_SymmsCreateMap( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes symmetries for a single output function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * vSuppFun ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pTemp; + int * pMap, i; + + assert( Abc_NtkCiNum(pNtk) + 10 < (1<<16) ); + + // get the structural support + pNtk->vSupps = Sim_ComputeStrSupp( pNtk ); + // set elementary info for the CIs + Abc_NtkForEachCi( pNtk, pTemp, i ) + SIM_SET_SYMMS( pTemp, Vec_IntAlloc(0) ); + // create the map of CI ids into their numbers + pMap = Sim_SymmsCreateMap( pNtk ); + // collect the nodes in the TFI cone of this output + vNodes = Abc_NtkDfs( pNtk, 0 ); + Vec_PtrForEachEntry( vNodes, pTemp, i ) + { +// if ( Abc_NodeIsConst(pTemp) ) +// continue; + Sim_SymmsStructComputeOne( pNtk, pTemp, pMap ); + } + // collect the results for the COs; + Abc_NtkForEachCo( pNtk, pTemp, i ) + { +//printf( "Output %d:\n", i ); + pTemp = Abc_ObjFanin0(pTemp); + if ( Abc_ObjIsCi(pTemp) || Abc_AigNodeIsConst(pTemp) ) + continue; + Sim_SymmsTransferToMatrix( Vec_PtrEntry(vMatrs, i), SIM_READ_SYMMS(pTemp), Vec_PtrEntry(vSuppFun, i) ); + } + // clean the intermediate results + Sim_UtilInfoFree( pNtk->vSupps ); + pNtk->vSupps = NULL; + Abc_NtkForEachCi( pNtk, pTemp, i ) + Vec_IntFree( SIM_READ_SYMMS(pTemp) ); + Vec_PtrForEachEntry( vNodes, pTemp, i ) +// if ( !Abc_NodeIsConst(pTemp) ) + Vec_IntFree( SIM_READ_SYMMS(pTemp) ); + Vec_PtrFree( vNodes ); + free( pMap ); +} + +/**Function************************************************************* + + Synopsis [Recursively computes symmetries. ] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SymmsStructComputeOne( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int * pMap ) +{ + Vec_Ptr_t * vNodes, * vNodesPi0, * vNodesPi1, * vNodesOther; + Vec_Int_t * vSymms; + Abc_Obj_t * pTemp; + int i; + + // allocate the temporary arrays + vNodes = Vec_PtrAlloc( 10 ); + vNodesPi0 = Vec_PtrAlloc( 10 ); + vNodesPi1 = Vec_PtrAlloc( 10 ); + vNodesOther = Vec_PtrAlloc( 10 ); + + // collect the fanins of the implication supergate + Sim_SymmsBalanceCollect_rec( pNode, vNodes ); + + // sort the nodes in the implication supergate + Sim_SymmsPartitionNodes( vNodes, vNodesPi0, vNodesPi1, vNodesOther ); + + // start the resulting set + vSymms = Vec_IntAlloc( 10 ); + // generate symmetries from the groups + Sim_SymmsAppendFromGroup( pNtk, vNodesPi0, vNodesOther, vSymms, pMap ); + Sim_SymmsAppendFromGroup( pNtk, vNodesPi1, vNodesOther, vSymms, pMap ); + // add symmetries from other inputs + for ( i = 0; i < vNodesOther->nSize; i++ ) + { + pTemp = Abc_ObjRegular(vNodesOther->pArray[i]); + Sim_SymmsAppendFromNode( pNtk, SIM_READ_SYMMS(pTemp), vNodesOther, vNodesPi0, vNodesPi1, vSymms, pMap ); + } + Vec_PtrFree( vNodes ); + Vec_PtrFree( vNodesPi0 ); + Vec_PtrFree( vNodesPi1 ); + Vec_PtrFree( vNodesOther ); + + // set the symmetry at the node + SIM_SET_SYMMS( pNode, vSymms ); +} + + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SymmsBalanceCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + // if the new node is complemented, another gate begins + if ( Abc_ObjIsComplement(pNode) ) + { + Vec_PtrPushUnique( vNodes, pNode ); + return; + } + // if pNew is the PI node, return + if ( Abc_ObjIsCi(pNode) ) + { + Vec_PtrPushUnique( vNodes, pNode ); + return; + } + // go through the branches + Sim_SymmsBalanceCollect_rec( Abc_ObjChild0(pNode), vNodes ); + Sim_SymmsBalanceCollect_rec( Abc_ObjChild1(pNode), vNodes ); +} + +/**Function************************************************************* + + Synopsis [Divides PI variables into groups.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SymmsPartitionNodes( Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesPis0, + Vec_Ptr_t * vNodesPis1, Vec_Ptr_t * vNodesOther ) +{ + Abc_Obj_t * pNode; + int i; + Vec_PtrForEachEntry( vNodes, pNode, i ) + { + if ( !Abc_ObjIsCi(Abc_ObjRegular(pNode)) ) + Vec_PtrPush( vNodesOther, pNode ); + else if ( Abc_ObjIsComplement(pNode) ) + Vec_PtrPush( vNodesPis0, pNode ); + else + Vec_PtrPush( vNodesPis1, pNode ); + } +} + +/**Function************************************************************* + + Synopsis [Makes the product of two partitions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SymmsAppendFromGroup( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodesPi, Vec_Ptr_t * vNodesOther, Vec_Int_t * vSymms, int * pMap ) +{ + Abc_Obj_t * pNode1, * pNode2; + unsigned uSymm; + int i, k; + + if ( vNodesPi->nSize == 0 ) + return; + + // go through the pairs + for ( i = 0; i < vNodesPi->nSize; i++ ) + for ( k = i+1; k < vNodesPi->nSize; k++ ) + { + // get the two PI nodes + pNode1 = Abc_ObjRegular(vNodesPi->pArray[i]); + pNode2 = Abc_ObjRegular(vNodesPi->pArray[k]); + assert( pMap[pNode1->Id] != pMap[pNode2->Id] ); + assert( pMap[pNode1->Id] >= 0 ); + assert( pMap[pNode2->Id] >= 0 ); + // generate symmetry + if ( pMap[pNode1->Id] < pMap[pNode2->Id] ) + uSymm = ((pMap[pNode1->Id] << 16) | pMap[pNode2->Id]); + else + uSymm = ((pMap[pNode2->Id] << 16) | pMap[pNode1->Id]); + // check if symmetry belongs + if ( Sim_SymmsIsCompatibleWithNodes( pNtk, uSymm, vNodesOther, pMap ) ) + Vec_IntPushUnique( vSymms, (int)uSymm ); + } +} + +/**Function************************************************************* + + Synopsis [Add the filters symmetries from the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SymmsAppendFromNode( Abc_Ntk_t * pNtk, Vec_Int_t * vSymms0, Vec_Ptr_t * vNodesOther, + Vec_Ptr_t * vNodesPi0, Vec_Ptr_t * vNodesPi1, Vec_Int_t * vSymms, int * pMap ) +{ + unsigned uSymm; + int i; + + if ( vSymms0->nSize == 0 ) + return; + + // go through the pairs + for ( i = 0; i < vSymms0->nSize; i++ ) + { + uSymm = (unsigned)vSymms0->pArray[i]; + // check if symmetry belongs + if ( Sim_SymmsIsCompatibleWithNodes( pNtk, uSymm, vNodesOther, pMap ) && + Sim_SymmsIsCompatibleWithGroup( uSymm, vNodesPi0, pMap ) && + Sim_SymmsIsCompatibleWithGroup( uSymm, vNodesPi1, pMap ) ) + Vec_IntPushUnique( vSymms, (int)uSymm ); + } +} + +/**Function************************************************************* + + Synopsis [Returns 1 if symmetry is compatible with the group of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_SymmsIsCompatibleWithNodes( Abc_Ntk_t * pNtk, unsigned uSymm, Vec_Ptr_t * vNodesOther, int * pMap ) +{ + Vec_Int_t * vSymmsNode; + Abc_Obj_t * pNode; + int i, s, Ind1, Ind2, fIsVar1, fIsVar2; + + if ( vNodesOther->nSize == 0 ) + return 1; + + // get the indices of the PI variables + Ind1 = (uSymm & 0xffff); + Ind2 = (uSymm >> 16); + + // go through the nodes + // if they do not belong to a support, it is okay + // if one belongs, the other does not belong, quit + // if they belong, but are not part of symmetry, quit + for ( i = 0; i < vNodesOther->nSize; i++ ) + { + pNode = Abc_ObjRegular(vNodesOther->pArray[i]); + fIsVar1 = Sim_SuppStrHasVar( pNtk->vSupps, pNode, Ind1 ); + fIsVar2 = Sim_SuppStrHasVar( pNtk->vSupps, pNode, Ind2 ); + + if ( !fIsVar1 && !fIsVar2 ) + continue; + if ( fIsVar1 ^ fIsVar2 ) + return 0; + // both belong + // check if there is a symmetry + vSymmsNode = SIM_READ_SYMMS( pNode ); + for ( s = 0; s < vSymmsNode->nSize; s++ ) + if ( uSymm == (unsigned)vSymmsNode->pArray[s] ) + break; + if ( s == vSymmsNode->nSize ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if symmetry is compatible with the group of PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_SymmsIsCompatibleWithGroup( unsigned uSymm, Vec_Ptr_t * vNodesPi, int * pMap ) +{ + Abc_Obj_t * pNode; + int i, Ind1, Ind2, fHasVar1, fHasVar2; + + if ( vNodesPi->nSize == 0 ) + return 1; + + // get the indices of the PI variables + Ind1 = (uSymm & 0xffff); + Ind2 = (uSymm >> 16); + + // go through the PI nodes + fHasVar1 = fHasVar2 = 0; + for ( i = 0; i < vNodesPi->nSize; i++ ) + { + pNode = Abc_ObjRegular(vNodesPi->pArray[i]); + if ( pMap[pNode->Id] == Ind1 ) + fHasVar1 = 1; + else if ( pMap[pNode->Id] == Ind2 ) + fHasVar2 = 1; + } + return fHasVar1 == fHasVar2; +} + + + +/**Function************************************************************* + + Synopsis [Improvements due to transitivity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SymmsTrans( Vec_Int_t * vSymms ) +{ + unsigned uSymm, uSymma, uSymmr; + int i, Ind1, Ind2; + int k, Ind1a, Ind2a; + int j; + int nTrans = 0; + + for ( i = 0; i < vSymms->nSize; i++ ) + { + uSymm = (unsigned)vSymms->pArray[i]; + Ind1 = (uSymm & 0xffff); + Ind2 = (uSymm >> 16); + // find other symmetries that have Ind1 + for ( k = i+1; k < vSymms->nSize; k++ ) + { + uSymma = (unsigned)vSymms->pArray[k]; + if ( uSymma == uSymm ) + continue; + Ind1a = (uSymma & 0xffff); + Ind2a = (uSymma >> 16); + if ( Ind1a == Ind1 ) + { + // find the symmetry (Ind2,Ind2a) + if ( Ind2 < Ind2a ) + uSymmr = ((Ind2 << 16) | Ind2a); + else + uSymmr = ((Ind2a << 16) | Ind2); + for ( j = 0; j < vSymms->nSize; j++ ) + if ( uSymmr == (unsigned)vSymms->pArray[j] ) + break; + if ( j == vSymms->nSize ) + nTrans++; + } + } + + } + printf( "Trans = %d.\n", nTrans ); +} + + +/**Function************************************************************* + + Synopsis [Transfers from the vector to the matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * vSymms, unsigned * pSupport ) +{ + int i, Ind1, Ind2, nInputs; + unsigned uSymm; + // add diagonal elements + nInputs = Extra_BitMatrixReadSize( pMatSymm ); + for ( i = 0; i < nInputs; i++ ) + Extra_BitMatrixInsert1( pMatSymm, i, i ); + // add non-diagonal elements + for ( i = 0; i < vSymms->nSize; i++ ) + { + uSymm = (unsigned)vSymms->pArray[i]; + Ind1 = (uSymm & 0xffff); + Ind2 = (uSymm >> 16); +//printf( "%d,%d ", Ind1, Ind2 ); + // skip variables that are not in the true support + assert( Sim_HasBit(pSupport, Ind1) == Sim_HasBit(pSupport, Ind2) ); + if ( !Sim_HasBit(pSupport, Ind1) || !Sim_HasBit(pSupport, Ind2) ) + continue; + Extra_BitMatrixInsert1( pMatSymm, Ind1, Ind2 ); + Extra_BitMatrixInsert2( pMatSymm, Ind1, Ind2 ); + } +} + +/**Function************************************************************* + + Synopsis [Mapping of indices into numbers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Sim_SymmsCreateMap( Abc_Ntk_t * pNtk ) +{ + int * pMap; + Abc_Obj_t * pNode; + int i; + pMap = ALLOC( int, Abc_NtkObjNumMax(pNtk) ); + for ( i = 0; i < Abc_NtkObjNumMax(pNtk); i++ ) + pMap[i] = -1; + Abc_NtkForEachCi( pNtk, pNode, i ) + pMap[pNode->Id] = i; + return pMap; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/opt/sim/simUtils.c b/abc70930/src/opt/sim/simUtils.c new file mode 100644 index 00000000..b0660001 --- /dev/null +++ b/abc70930/src/opt/sim/simUtils.c @@ -0,0 +1,711 @@ +/**CFile**************************************************************** + + FileName [simUtils.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Various simulation utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: simUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "sim.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int bit_count[256] = { + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates simulation information for all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Sim_UtilInfoAlloc( int nSize, int nWords, bool fClean ) +{ + Vec_Ptr_t * vInfo; + int i; + assert( nSize > 0 && nWords > 0 ); + vInfo = Vec_PtrAlloc( nSize ); + vInfo->pArray[0] = ALLOC( unsigned, nSize * nWords ); + if ( fClean ) + memset( vInfo->pArray[0], 0, sizeof(unsigned) * nSize * nWords ); + for ( i = 1; i < nSize; i++ ) + vInfo->pArray[i] = ((unsigned *)vInfo->pArray[i-1]) + nWords; + vInfo->nSize = nSize; + return vInfo; +} + +/**Function************************************************************* + + Synopsis [Allocates simulation information for all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilInfoFree( Vec_Ptr_t * p ) +{ + free( p->pArray[0] ); + Vec_PtrFree( p ); +} + +/**Function************************************************************* + + Synopsis [Adds the second supp-info the first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilInfoAdd( unsigned * pInfo1, unsigned * pInfo2, int nWords ) +{ + int w; + for ( w = 0; w < nWords; w++ ) + pInfo1[w] |= pInfo2[w]; +} + +/**Function************************************************************* + + Synopsis [Returns the positions where pInfo2 is 1 while pInfo1 is 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilInfoDetectDiffs( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ) +{ + int w, b; + unsigned uMask; + vDiffs->nSize = 0; + for ( w = 0; w < nWords; w++ ) + if ( uMask = (pInfo2[w] ^ pInfo1[w]) ) + for ( b = 0; b < 32; b++ ) + if ( uMask & (1 << b) ) + Vec_IntPush( vDiffs, 32*w + b ); +} + +/**Function************************************************************* + + Synopsis [Returns the positions where pInfo2 is 1 while pInfo1 is 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilInfoDetectNews( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ) +{ + int w, b; + unsigned uMask; + vDiffs->nSize = 0; + for ( w = 0; w < nWords; w++ ) + if ( uMask = (pInfo2[w] & ~pInfo1[w]) ) + for ( b = 0; b < 32; b++ ) + if ( uMask & (1 << b) ) + Vec_IntPush( vDiffs, 32*w + b ); +} + +/**Function************************************************************* + + Synopsis [Flips the simulation info of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilInfoFlip( Sim_Man_t * p, Abc_Obj_t * pNode ) +{ + unsigned * pSimInfo1, * pSimInfo2; + int k; + pSimInfo1 = p->vSim0->pArray[pNode->Id]; + pSimInfo2 = p->vSim1->pArray[pNode->Id]; + for ( k = 0; k < p->nSimWords; k++ ) + pSimInfo2[k] = ~pSimInfo1[k]; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the simulation infos are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Sim_UtilInfoCompare( Sim_Man_t * p, Abc_Obj_t * pNode ) +{ + unsigned * pSimInfo1, * pSimInfo2; + int k; + pSimInfo1 = p->vSim0->pArray[pNode->Id]; + pSimInfo2 = p->vSim1->pArray[pNode->Id]; + for ( k = 0; k < p->nSimWords; k++ ) + if ( pSimInfo2[k] != pSimInfo1[k] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Simulates the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilSimulate( Sim_Man_t * p, bool fType ) +{ + Abc_Obj_t * pNode; + int i; + // simulate the internal nodes + Abc_NtkForEachNode( p->pNtk, pNode, i ) + Sim_UtilSimulateNode( p, pNode, fType, fType, fType ); + // assign simulation info of the CO nodes + Abc_NtkForEachCo( p->pNtk, pNode, i ) + Sim_UtilSimulateNode( p, pNode, fType, fType, fType ); +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fType1, bool fType2 ) +{ + unsigned * pSimmNode, * pSimmNode1, * pSimmNode2; + int k, fComp1, fComp2; + // simulate the internal nodes + if ( Abc_ObjIsNode(pNode) ) + { + if ( fType ) + pSimmNode = p->vSim1->pArray[ pNode->Id ]; + else + pSimmNode = p->vSim0->pArray[ pNode->Id ]; + + if ( fType1 ) + pSimmNode1 = p->vSim1->pArray[ Abc_ObjFaninId0(pNode) ]; + else + pSimmNode1 = p->vSim0->pArray[ Abc_ObjFaninId0(pNode) ]; + + if ( fType2 ) + pSimmNode2 = p->vSim1->pArray[ Abc_ObjFaninId1(pNode) ]; + else + pSimmNode2 = p->vSim0->pArray[ Abc_ObjFaninId1(pNode) ]; + + fComp1 = Abc_ObjFaninC0(pNode); + fComp2 = Abc_ObjFaninC1(pNode); + if ( fComp1 && fComp2 ) + for ( k = 0; k < p->nSimWords; k++ ) + pSimmNode[k] = ~pSimmNode1[k] & ~pSimmNode2[k]; + else if ( fComp1 && !fComp2 ) + for ( k = 0; k < p->nSimWords; k++ ) + pSimmNode[k] = ~pSimmNode1[k] & pSimmNode2[k]; + else if ( !fComp1 && fComp2 ) + for ( k = 0; k < p->nSimWords; k++ ) + pSimmNode[k] = pSimmNode1[k] & ~pSimmNode2[k]; + else // if ( fComp1 && fComp2 ) + for ( k = 0; k < p->nSimWords; k++ ) + pSimmNode[k] = pSimmNode1[k] & pSimmNode2[k]; + } + else + { + assert( Abc_ObjFaninNum(pNode) == 1 ); + if ( fType ) + pSimmNode = p->vSim1->pArray[ pNode->Id ]; + else + pSimmNode = p->vSim0->pArray[ pNode->Id ]; + + if ( fType1 ) + pSimmNode1 = p->vSim1->pArray[ Abc_ObjFaninId0(pNode) ]; + else + pSimmNode1 = p->vSim0->pArray[ Abc_ObjFaninId0(pNode) ]; + + fComp1 = Abc_ObjFaninC0(pNode); + if ( fComp1 ) + for ( k = 0; k < p->nSimWords; k++ ) + pSimmNode[k] = ~pSimmNode1[k]; + else + for ( k = 0; k < p->nSimWords; k++ ) + pSimmNode[k] = pSimmNode1[k]; + } +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset ) +{ + unsigned * pSimmNode, * pSimmNode1, * pSimmNode2; + int k, fComp1, fComp2; + // simulate the internal nodes + assert( Abc_ObjIsNode(pNode) ); + pSimmNode = Vec_PtrEntry(vSimInfo, pNode->Id); + pSimmNode1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); + pSimmNode2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode)); + pSimmNode += nOffset; + pSimmNode1 += nOffset; + pSimmNode2 += nOffset; + fComp1 = Abc_ObjFaninC0(pNode); + fComp2 = Abc_ObjFaninC1(pNode); + if ( fComp1 && fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pSimmNode[k] = ~pSimmNode1[k] & ~pSimmNode2[k]; + else if ( fComp1 && !fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pSimmNode[k] = ~pSimmNode1[k] & pSimmNode2[k]; + else if ( !fComp1 && fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pSimmNode[k] = pSimmNode1[k] & ~pSimmNode2[k]; + else // if ( fComp1 && fComp2 ) + for ( k = 0; k < nSimWords; k++ ) + pSimmNode[k] = pSimmNode1[k] & pSimmNode2[k]; +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift ) +{ + unsigned * pSimmNode, * pSimmNode1; + int k, fComp1; + // simulate the internal nodes + assert( Abc_ObjIsCo(pNode) ); + pSimmNode = Vec_PtrEntry(vSimInfo, pNode->Id); + pSimmNode1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); + pSimmNode += nOffset + (fShift > 0)*nSimWords; + pSimmNode1 += nOffset; + fComp1 = Abc_ObjFaninC0(pNode); + if ( fComp1 ) + for ( k = 0; k < nSimWords; k++ ) + pSimmNode[k] = ~pSimmNode1[k]; + else + for ( k = 0; k < nSimWords; k++ ) + pSimmNode[k] = pSimmNode1[k]; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the simulation infos are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_UtilCountSuppSizes( Sim_Man_t * p, int fStruct ) +{ + Abc_Obj_t * pNode, * pNodeCi; + int i, v, Counter; + Counter = 0; + if ( fStruct ) + { + Abc_NtkForEachCo( p->pNtk, pNode, i ) + Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) + Counter += Sim_SuppStrHasVar( p->vSuppStr, pNode, v ); + } + else + { + Abc_NtkForEachCo( p->pNtk, pNode, i ) + Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) + Counter += Sim_SuppFunHasVar( p->vSuppFun, i, v ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of 1's in the bitstring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords ) +{ + unsigned char * pBytes; + int nOnes, nBytes, i; + pBytes = (unsigned char *)pSimInfo; + nBytes = 4 * nSimWords; + nOnes = 0; + for ( i = 0; i < nBytes; i++ ) + nOnes += bit_count[ pBytes[i] ]; + return nOnes; +} + +/**Function************************************************************* + + Synopsis [Counts the number of 1's in the bitstring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords ) +{ + Vec_Int_t * vCounters; + unsigned * pSimInfo; + int i; + vCounters = Vec_IntStart( Vec_PtrSize(vInfo) ); + Vec_PtrForEachEntry( vInfo, pSimInfo, i ) + Vec_IntWriteEntry( vCounters, i, Sim_UtilCountOnes(pSimInfo, nSimWords) ); + return vCounters; +} + +/**Function************************************************************* + + Synopsis [Returns random patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords ) +{ + int k; + for ( k = 0; k < nSimWords; k++ ) + pPatRand[k] = SIM_RANDOM_UNSIGNED; +} + +/**Function************************************************************* + + Synopsis [Returns complemented patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords ) +{ + int k; + for ( k = 0; k < nSimWords; k++ ) + pPatRand[k] = ~pPatRand[k]; +} + +/**Function************************************************************* + + Synopsis [Returns constant patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 ) +{ + int k; + for ( k = 0; k < nSimWords; k++ ) + pPatRand[k] = 0; + if ( fConst1 ) + Sim_UtilSetCompl( pPatRand, nSimWords ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords ) +{ + int k; + for ( k = 0; k < nSimWords; k++ ) + if ( pPats1[k] != pPats2[k] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if Node1 implies Node2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords ) +{ + int k; + for ( k = 0; k < nSimWords; k++ ) + if ( pPats1[k] & ~pPats2[k] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if Node1 v Node2 is always true.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords ) +{ + int k; + for ( k = 0; k < nSimWords; k++ ) + if ( ~pPats1[k] & ~pPats2[k] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Counts the total number of pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_UtilCountAllPairs( Vec_Ptr_t * vSuppFun, int nSimWords, Vec_Int_t * vCounters ) +{ + unsigned * pSupp; + int Counter, nOnes, nPairs, i; + Counter = 0; + Vec_PtrForEachEntry( vSuppFun, pSupp, i ) + { + nOnes = Sim_UtilCountOnes( pSupp, nSimWords ); + nPairs = nOnes * (nOnes - 1) / 2; + Vec_IntWriteEntry( vCounters, i, nPairs ); + Counter += nPairs; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of entries in the array of matrices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_UtilCountPairsOne( Extra_BitMat_t * pMat, Vec_Int_t * vSupport ) +{ + int i, k, Index1, Index2; + int Counter = 0; +// int Counter2; + Vec_IntForEachEntry( vSupport, i, Index1 ) + Vec_IntForEachEntryStart( vSupport, k, Index2, Index1+1 ) + Counter += Extra_BitMatrixLookup1( pMat, i, k ); +// Counter2 = Extra_BitMatrixCountOnesUpper(pMat); +// assert( Counter == Counter2 ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of entries in the array of matrices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_UtilCountPairsOnePrint( Extra_BitMat_t * pMat, Vec_Int_t * vSupport ) +{ + int i, k, Index1, Index2; + Vec_IntForEachEntry( vSupport, i, Index1 ) + Vec_IntForEachEntryStart( vSupport, k, Index2, Index1+1 ) + if ( Extra_BitMatrixLookup1( pMat, i, k ) ) + printf( "(%d,%d) ", i, k ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Counts the number of entries in the array of matrices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilCountPairsAllPrint( Sym_Man_t * p ) +{ + int i, clk; +clk = clock(); + for ( i = 0; i < p->nOutputs; i++ ) + { + printf( "Output %2d :", i ); + Sim_UtilCountPairsOnePrint( Vec_PtrEntry(p->vMatrSymms, i), Vec_VecEntry(p->vSupports, i) ); + printf( "\n" ); + } +p->timeCount += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [Counts the number of entries in the array of matrices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sim_UtilCountPairsAll( Sym_Man_t * p ) +{ + int nPairsTotal, nPairsSym, nPairsNonSym, i, clk; +clk = clock(); + p->nPairsSymm = 0; + p->nPairsNonSymm = 0; + for ( i = 0; i < p->nOutputs; i++ ) + { + nPairsTotal = Vec_IntEntry(p->vPairsTotal, i); + nPairsSym = Vec_IntEntry(p->vPairsSym, i); + nPairsNonSym = Vec_IntEntry(p->vPairsNonSym,i); + assert( nPairsTotal >= nPairsSym + nPairsNonSym ); + if ( nPairsTotal == nPairsSym + nPairsNonSym ) + { + p->nPairsSymm += nPairsSym; + p->nPairsNonSymm += nPairsNonSym; + continue; + } + nPairsSym = Sim_UtilCountPairsOne( Vec_PtrEntry(p->vMatrSymms, i), Vec_VecEntry(p->vSupports, i) ); + nPairsNonSym = Sim_UtilCountPairsOne( Vec_PtrEntry(p->vMatrNonSymms,i), Vec_VecEntry(p->vSupports, i) ); + assert( nPairsTotal >= nPairsSym + nPairsNonSym ); + Vec_IntWriteEntry( p->vPairsSym, i, nPairsSym ); + Vec_IntWriteEntry( p->vPairsNonSym, i, nPairsNonSym ); + p->nPairsSymm += nPairsSym; + p->nPairsNonSymm += nPairsNonSym; +// printf( "%d ", nPairsTotal - nPairsSym - nPairsNonSym ); + } +//printf( "\n" ); + p->nPairsRem = p->nPairsTotal-p->nPairsSymm-p->nPairsNonSymm; +p->timeCount += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sim_UtilMatrsAreDisjoint( Sym_Man_t * p ) +{ + int i; + for ( i = 0; i < p->nOutputs; i++ ) + if ( !Extra_BitMatrixIsDisjoint( Vec_PtrEntry(p->vMatrSymms,i), Vec_PtrEntry(p->vMatrNonSymms,i) ) ) + return 0; + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/bsat/module.make b/abc70930/src/sat/bsat/module.make new file mode 100644 index 00000000..563c8dfc --- /dev/null +++ b/abc70930/src/sat/bsat/module.make @@ -0,0 +1,6 @@ +SRC += src/sat/bsat/satMem.c \ + src/sat/bsat/satInter.c \ + src/sat/bsat/satSolver.c \ + src/sat/bsat/satStore.c \ + src/sat/bsat/satTrace.c \ + src/sat/bsat/satUtil.c diff --git a/abc70930/src/sat/bsat/satInter.c b/abc70930/src/sat/bsat/satInter.c new file mode 100644 index 00000000..b52cd6c7 --- /dev/null +++ b/abc70930/src/sat/bsat/satInter.c @@ -0,0 +1,991 @@ +/**CFile**************************************************************** + + FileName [satInter.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT sat_solver.] + + Synopsis [Interpolation package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include +#include "satStore.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// variable assignments +static const lit LIT_UNDEF = 0xffffffff; + +// interpolation manager +struct Int_Man_t_ +{ + // clauses of the problems + Sto_Man_t * pCnf; // the set of CNF clauses for A and B + // various parameters + int fVerbose; // verbosiness flag + int fProofVerif; // verifies the proof + int fProofWrite; // writes the proof file + int nVarsAlloc; // the allocated size of var arrays + int nClosAlloc; // the allocated size of clause arrays + // internal BCP + int nRootSize; // the number of root level assignments + int nTrailSize; // the number of assignments made + lit * pTrail; // chronological order of assignments (size nVars) + lit * pAssigns; // assignments by variable (size nVars) + char * pSeens; // temporary mark (size nVars) + Sto_Cls_t ** pReasons; // reasons for each assignment (size nVars) + Sto_Cls_t ** pWatches; // watched clauses for each literal (size 2*nVars) + // interpolation data + int nVarsAB; // the number of global variables + char * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB] + unsigned * pInters; // storage for interpolants as truth tables (size nClauses) + int nIntersAlloc; // the allocated size of truth table array + int nWords; // the number of words in the truth table + // proof recording + int Counter; // counter of resolved clauses + int * pProofNums; // the proof numbers for each clause (size nClauses) + FILE * pFile; // the file for proof recording + // internal verification + lit * pResLits; // the literals of the resolvent + int nResLits; // the number of literals of the resolvent + int nResLitsAlloc;// the number of literals of the resolvent + // runtime stats + int timeBcp; // the runtime for BCP + int timeTrace; // the runtime of trace construction + int timeTotal; // the total runtime of interpolation +}; + +// procedure to get hold of the clauses' truth table +static inline unsigned * Int_ManTruthRead( Int_Man_t * p, Sto_Cls_t * pCls ) { return p->pInters + pCls->Id * p->nWords; } +static inline void Int_ManTruthClear( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = 0; } +static inline void Int_ManTruthFill( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = ~0; } +static inline void Int_ManTruthCopy( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = q[i]; } +static inline void Int_ManTruthAnd( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] &= q[i]; } +static inline void Int_ManTruthOr( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= q[i]; } +static inline void Int_ManTruthOrNot( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= ~q[i]; } + +// reading/writing the proof for a clause +static inline int Int_ManProofGet( Int_Man_t * p, Sto_Cls_t * pCls ) { return p->pProofNums[pCls->Id]; } +static inline void Int_ManProofSet( Int_Man_t * p, Sto_Cls_t * pCls, int n ) { p->pProofNums[pCls->Id] = n; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Int_Man_t * Int_ManAlloc( int nVarsAlloc ) +{ + Int_Man_t * p; + // allocate the manager + p = (Int_Man_t *)malloc( sizeof(Int_Man_t) ); + memset( p, 0, sizeof(Int_Man_t) ); + // verification + p->nResLitsAlloc = (1<<16); + p->pResLits = malloc( sizeof(lit) * p->nResLitsAlloc ); + // parameters + p->fProofWrite = 0; + p->fProofVerif = 1; + return p; +} + +/**Function************************************************************* + + Synopsis [Count common variables in the clauses of A and B.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Int_ManGlobalVars( Int_Man_t * p ) +{ + Sto_Cls_t * pClause; + int Var, nVarsAB, v; + + // mark the variable encountered in the clauses of A + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + if ( !pClause->fA ) + break; + for ( v = 0; v < (int)pClause->nLits; v++ ) + p->pVarTypes[lit_var(pClause->pLits[v])] = 1; + } + + // check variables that appear in clauses of B + nVarsAB = 0; + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + if ( pClause->fA ) + continue; + for ( v = 0; v < (int)pClause->nLits; v++ ) + { + Var = lit_var(pClause->pLits[v]); + if ( p->pVarTypes[Var] == 1 ) // var of A + { + // change it into a global variable + nVarsAB++; + p->pVarTypes[Var] = -1; + } + } + } + + // order global variables + nVarsAB = 0; + for ( v = 0; v < p->pCnf->nVars; v++ ) + if ( p->pVarTypes[v] == -1 ) + p->pVarTypes[v] -= nVarsAB++; +//printf( "There are %d global variables.\n", nVarsAB ); + return nVarsAB; +} + +/**Function************************************************************* + + Synopsis [Resize proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Int_ManResize( Int_Man_t * p ) +{ + // check if resizing is needed + if ( p->nVarsAlloc < p->pCnf->nVars ) + { + // find the new size + if ( p->nVarsAlloc == 0 ) + p->nVarsAlloc = 1; + while ( p->nVarsAlloc < p->pCnf->nVars ) + p->nVarsAlloc *= 2; + // resize the arrays + p->pTrail = (lit *) realloc( p->pTrail, sizeof(lit) * p->nVarsAlloc ); + p->pAssigns = (lit *) realloc( p->pAssigns, sizeof(lit) * p->nVarsAlloc ); + p->pSeens = (char *) realloc( p->pSeens, sizeof(char) * p->nVarsAlloc ); + p->pVarTypes = (char *) realloc( p->pVarTypes, sizeof(char) * p->nVarsAlloc ); + p->pReasons = (Sto_Cls_t **)realloc( p->pReasons, sizeof(Sto_Cls_t *) * p->nVarsAlloc ); + p->pWatches = (Sto_Cls_t **)realloc( p->pWatches, sizeof(Sto_Cls_t *) * p->nVarsAlloc*2 ); + } + + // clean the free space + memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars ); + memset( p->pSeens , 0, sizeof(char) * p->pCnf->nVars ); + memset( p->pVarTypes, 0, sizeof(char) * p->pCnf->nVars ); + memset( p->pReasons , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars ); + memset( p->pWatches , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 ); + + // compute the number of common variables + p->nVarsAB = Int_ManGlobalVars( p ); + // compute the number of words in the truth table + p->nWords = (p->nVarsAB <= 5 ? 1 : (1 << (p->nVarsAB - 5))); + + // check if resizing of clauses is needed + if ( p->nClosAlloc < p->pCnf->nClauses ) + { + // find the new size + if ( p->nClosAlloc == 0 ) + p->nClosAlloc = 1; + while ( p->nClosAlloc < p->pCnf->nClauses ) + p->nClosAlloc *= 2; + // resize the arrays + p->pProofNums = (int *) realloc( p->pProofNums, sizeof(int) * p->nClosAlloc ); + } + memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses ); + + // check if resizing of truth tables is needed + if ( p->nIntersAlloc < p->nWords * p->pCnf->nClauses ) + { + p->nIntersAlloc = p->nWords * p->pCnf->nClauses; + p->pInters = (unsigned *) realloc( p->pInters, sizeof(unsigned) * p->nIntersAlloc ); + } +// memset( p->pInters, 0, sizeof(unsigned) * p->nWords * p->pCnf->nClauses ); +} + +/**Function************************************************************* + + Synopsis [Deallocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Int_ManFree( Int_Man_t * p ) +{ +/* + printf( "Runtime stats:\n" ); +PRT( "BCP ", p->timeBcp ); +PRT( "Trace ", p->timeTrace ); +PRT( "TOTAL ", p->timeTotal ); +*/ + free( p->pInters ); + free( p->pProofNums ); + free( p->pTrail ); + free( p->pAssigns ); + free( p->pSeens ); + free( p->pVarTypes ); + free( p->pReasons ); + free( p->pWatches ); + free( p->pResLits ); + free( p ); +} + + + + +/**Function************************************************************* + + Synopsis [Prints the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Int_ManPrintClause( Int_Man_t * p, Sto_Cls_t * pClause ) +{ + int i; + printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Int_ManProofGet(p, pClause) ); + for ( i = 0; i < (int)pClause->nLits; i++ ) + printf( " %d", pClause->pLits[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the resolvent.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Int_ManPrintResolvent( lit * pResLits, int nResLits ) +{ + int i; + printf( "Resolvent: {" ); + for ( i = 0; i < nResLits; i++ ) + printf( " %d", pResLits[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Records the proof.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_PrintBinary__( FILE * pFile, unsigned Sign[], int nBits ) +{ + int Remainder, nWords; + int w, i; + + Remainder = (nBits%(sizeof(unsigned)*8)); + nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); + + for ( w = nWords-1; w >= 0; w-- ) + for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) + fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1< 0) ); +} + +/**Function************************************************************* + + Synopsis [Prints the interpolant for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Int_ManPrintInterOne( Int_Man_t * p, Sto_Cls_t * pClause ) +{ + printf( "Clause %2d : ", pClause->Id ); + Extra_PrintBinary__( stdout, Int_ManTruthRead(p, pClause), (1 << p->nVarsAB) ); + printf( "\n" ); +} + + + +/**Function************************************************************* + + Synopsis [Adds one clause to the watcher list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Int_ManWatchClause( Int_Man_t * p, Sto_Cls_t * pClause, lit Lit ) +{ + assert( lit_check(Lit, p->pCnf->nVars) ); + if ( pClause->pLits[0] == Lit ) + pClause->pNext0 = p->pWatches[lit_neg(Lit)]; + else + { + assert( pClause->pLits[1] == Lit ); + pClause->pNext1 = p->pWatches[lit_neg(Lit)]; + } + p->pWatches[lit_neg(Lit)] = pClause; +} + + +/**Function************************************************************* + + Synopsis [Records implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Int_ManEnqueue( Int_Man_t * p, lit Lit, Sto_Cls_t * pReason ) +{ + int Var = lit_var(Lit); + if ( p->pAssigns[Var] != LIT_UNDEF ) + return p->pAssigns[Var] == Lit; + p->pAssigns[Var] = Lit; + p->pReasons[Var] = pReason; + p->pTrail[p->nTrailSize++] = Lit; +//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Records implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Int_ManCancelUntil( Int_Man_t * p, int Level ) +{ + lit Lit; + int i, Var; + for ( i = p->nTrailSize - 1; i >= Level; i-- ) + { + Lit = p->pTrail[i]; + Var = lit_var( Lit ); + p->pReasons[Var] = NULL; + p->pAssigns[Var] = LIT_UNDEF; +//printf( "cancelling var %d\n", Var ); + } + p->nTrailSize = Level; +} + +/**Function************************************************************* + + Synopsis [Propagate one assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Sto_Cls_t * Int_ManPropagateOne( Int_Man_t * p, lit Lit ) +{ + Sto_Cls_t ** ppPrev, * pCur, * pTemp; + lit LitF = lit_neg(Lit); + int i; + // iterate through the literals + ppPrev = p->pWatches + Lit; + for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) + { + // make sure the false literal is in the second literal of the clause + if ( pCur->pLits[0] == LitF ) + { + pCur->pLits[0] = pCur->pLits[1]; + pCur->pLits[1] = LitF; + pTemp = pCur->pNext0; + pCur->pNext0 = pCur->pNext1; + pCur->pNext1 = pTemp; + } + assert( pCur->pLits[1] == LitF ); + + // if the first literal is true, the clause is satisfied + if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) + { + ppPrev = &pCur->pNext1; + continue; + } + + // look for a new literal to watch + for ( i = 2; i < (int)pCur->nLits; i++ ) + { + // skip the case when the literal is false + if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] ) + continue; + // the literal is either true or unassigned - watch it + pCur->pLits[1] = pCur->pLits[i]; + pCur->pLits[i] = LitF; + // remove this clause from the watch list of Lit + *ppPrev = pCur->pNext1; + // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) + Int_ManWatchClause( p, pCur, pCur->pLits[1] ); + break; + } + if ( i < (int)pCur->nLits ) // found new watch + continue; + + // clause is unit - enqueue new implication + if ( Int_ManEnqueue(p, pCur->pLits[0], pCur) ) + { + ppPrev = &pCur->pNext1; + continue; + } + + // conflict detected - return the conflict clause + return pCur; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Propagate the current assignments.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sto_Cls_t * Int_ManPropagate( Int_Man_t * p, int Start ) +{ + Sto_Cls_t * pClause; + int i; + int clk = clock(); + for ( i = Start; i < p->nTrailSize; i++ ) + { + pClause = Int_ManPropagateOne( p, p->pTrail[i] ); + if ( pClause ) + { +p->timeBcp += clock() - clk; + return pClause; + } + } +p->timeBcp += clock() - clk; + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Writes one root clause into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Int_ManProofWriteOne( Int_Man_t * p, Sto_Cls_t * pClause ) +{ + Int_ManProofSet( p, pClause, ++p->Counter ); + + if ( p->fProofWrite ) + { + int v; + fprintf( p->pFile, "%d", Int_ManProofGet(p, pClause) ); + for ( v = 0; v < (int)pClause->nLits; v++ ) + fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) ); + fprintf( p->pFile, " 0 0\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Traces the proof for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Int_ManProofTraceOne( Int_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal ) +{ + Sto_Cls_t * pReason; + int i, v, Var, PrevId; + int fPrint = 0; + int clk = clock(); + + // collect resolvent literals + if ( p->fProofVerif ) + { + assert( (int)pConflict->nLits <= p->nResLitsAlloc ); + memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits ); + p->nResLits = pConflict->nLits; + } + + // mark all the variables in the conflict as seen + for ( v = 0; v < (int)pConflict->nLits; v++ ) + p->pSeens[lit_var(pConflict->pLits[v])] = 1; + + // start the anticedents +// pFinal->pAntis = Vec_PtrAlloc( 32 ); +// Vec_PtrPush( pFinal->pAntis, pConflict ); + + if ( p->pCnf->nClausesA ) + Int_ManTruthCopy( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pConflict), p->nWords ); + + // follow the trail backwards + PrevId = Int_ManProofGet(p, pConflict); + for ( i = p->nTrailSize - 1; i >= 0; i-- ) + { + // skip literals that are not involved + Var = lit_var(p->pTrail[i]); + if ( !p->pSeens[Var] ) + continue; + p->pSeens[Var] = 0; + + // skip literals of the resulting clause + pReason = p->pReasons[Var]; + if ( pReason == NULL ) + continue; + assert( p->pTrail[i] == pReason->pLits[0] ); + + // add the variables to seen + for ( v = 1; v < (int)pReason->nLits; v++ ) + p->pSeens[lit_var(pReason->pLits[v])] = 1; + + + // record the reason clause + assert( Int_ManProofGet(p, pReason) > 0 ); + p->Counter++; + if ( p->fProofWrite ) + fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Int_ManProofGet(p, pReason) ); + PrevId = p->Counter; + + if ( p->pCnf->nClausesA ) + { + if ( p->pVarTypes[Var] == 1 ) // var of A + Int_ManTruthOr( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pReason), p->nWords ); + else + Int_ManTruthAnd( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pReason), p->nWords ); + } + + // resolve the temporary resolvent with the reason clause + if ( p->fProofVerif ) + { + int v1, v2; + if ( fPrint ) + Int_ManPrintResolvent( p->pResLits, p->nResLits ); + // check that the var is present in the resolvent + for ( v1 = 0; v1 < p->nResLits; v1++ ) + if ( lit_var(p->pResLits[v1]) == Var ) + break; + if ( v1 == p->nResLits ) + printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var ); + if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) ) + printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var ); + // remove this variable from the resolvent + assert( lit_var(p->pResLits[v1]) == Var ); + p->nResLits--; + for ( ; v1 < p->nResLits; v1++ ) + p->pResLits[v1] = p->pResLits[v1+1]; + // add variables of the reason clause + for ( v2 = 1; v2 < (int)pReason->nLits; v2++ ) + { + for ( v1 = 0; v1 < p->nResLits; v1++ ) + if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) ) + break; + // if it is a new variable, add it to the resolvent + if ( v1 == p->nResLits ) + { + if ( p->nResLits == p->nResLitsAlloc ) + printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n, pFinal->Id" ); + p->pResLits[ p->nResLits++ ] = pReason->pLits[v2]; + continue; + } + // if the variable is the same, the literal should be the same too + if ( p->pResLits[v1] == pReason->pLits[v2] ) + continue; + // the literal is different + printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id ); + } + } + +// Vec_PtrPush( pFinal->pAntis, pReason ); + } + + // unmark all seen variables +// for ( i = p->nTrailSize - 1; i >= 0; i-- ) +// p->pSeens[lit_var(p->pTrail[i])] = 0; + // check that the literals are unmarked +// for ( i = p->nTrailSize - 1; i >= 0; i-- ) +// assert( p->pSeens[lit_var(p->pTrail[i])] == 0 ); + + // use the resulting clause to check the correctness of resolution + if ( p->fProofVerif ) + { + int v1, v2; + if ( fPrint ) + Int_ManPrintResolvent( p->pResLits, p->nResLits ); + for ( v1 = 0; v1 < p->nResLits; v1++ ) + { + for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) + if ( pFinal->pLits[v2] == p->pResLits[v1] ) + break; + if ( v2 < (int)pFinal->nLits ) + continue; + break; + } + if ( v1 < p->nResLits ) + { + printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id ); + Int_ManPrintClause( p, pConflict ); + Int_ManPrintResolvent( p->pResLits, p->nResLits ); + Int_ManPrintClause( p, pFinal ); + } + } +p->timeTrace += clock() - clk; + + // return the proof pointer + if ( p->pCnf->nClausesA ) + { +// Int_ManPrintInterOne( p, pFinal ); + } + Int_ManProofSet( p, pFinal, p->Counter ); + return p->Counter; +} + +/**Function************************************************************* + + Synopsis [Records the proof for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Int_ManProofRecordOne( Int_Man_t * p, Sto_Cls_t * pClause ) +{ + Sto_Cls_t * pConflict; + int i; + + // empty clause never ends up there + assert( pClause->nLits > 0 ); + if ( pClause->nLits == 0 ) + printf( "Error: Empty clause is attempted.\n" ); + + // add assumptions to the trail + assert( !pClause->fRoot ); + assert( p->nTrailSize == p->nRootSize ); + for ( i = 0; i < (int)pClause->nLits; i++ ) + if ( !Int_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) + { + assert( 0 ); // impossible + return 0; + } + + // propagate the assumptions + pConflict = Int_ManPropagate( p, p->nRootSize ); + if ( pConflict == NULL ) + { + assert( 0 ); // cannot prove + return 0; + } + + // construct the proof + Int_ManProofTraceOne( p, pConflict, pClause ); + + // undo to the root level + Int_ManCancelUntil( p, p->nRootSize ); + + // add large clauses to the watched lists + if ( pClause->nLits > 1 ) + { + Int_ManWatchClause( p, pClause, pClause->pLits[0] ); + Int_ManWatchClause( p, pClause, pClause->pLits[1] ); + return 1; + } + assert( pClause->nLits == 1 ); + + // if the clause proved is unit, add it and propagate + if ( !Int_ManEnqueue( p, pClause->pLits[0], pClause ) ) + { + assert( 0 ); // impossible + return 0; + } + + // propagate the assumption + pConflict = Int_ManPropagate( p, p->nRootSize ); + if ( pConflict ) + { + // construct the proof + Int_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty ); + if ( p->fVerbose ) + printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id ); + return 0; + } + + // update the root level + p->nRootSize = p->nTrailSize; + return 1; +} + +/**Function************************************************************* + + Synopsis [Propagate the root clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Int_ManProcessRoots( Int_Man_t * p ) +{ + Sto_Cls_t * pClause; + int Counter; + + // make sure the root clauses are preceeding the learnt clauses + Counter = 0; + Sto_ManForEachClause( p->pCnf, pClause ) + { + assert( (int)pClause->fA == (Counter < (int)p->pCnf->nClausesA) ); + assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots) ); + Counter++; + } + assert( p->pCnf->nClauses == Counter ); + + // make sure the last clause if empty + assert( p->pCnf->pTail->nLits == 0 ); + + // go through the root unit clauses + p->nTrailSize = 0; + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + // create watcher lists for the root clauses + if ( pClause->nLits > 1 ) + { + Int_ManWatchClause( p, pClause, pClause->pLits[0] ); + Int_ManWatchClause( p, pClause, pClause->pLits[1] ); + } + // empty clause and large clauses + if ( pClause->nLits != 1 ) + continue; + // unit clause + assert( lit_check(pClause->pLits[0], p->pCnf->nVars) ); + if ( !Int_ManEnqueue( p, pClause->pLits[0], pClause ) ) + { + // detected root level conflict + printf( "Error in Int_ManProcessRoots(): Detected a root-level conflict too early!\n" ); + assert( 0 ); + return 0; + } + } + + // propagate the root unit clauses + pClause = Int_ManPropagate( p, 0 ); + if ( pClause ) + { + // detected root level conflict + Int_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); + if ( p->fVerbose ) + printf( "Found root level conflict!\n" ); + return 0; + } + + // set the root level + p->nRootSize = p->nTrailSize; + return 1; +} + +/**Function************************************************************* + + Synopsis [Records the proof.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Int_ManPrepareInter( Int_Man_t * p ) +{ + // elementary truth tables + unsigned uTruths[8][8] = { + { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, + { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, + { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, + { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, + { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, + { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, + { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, + { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } + }; + Sto_Cls_t * pClause; + int Var, VarAB, v; + assert( p->nVarsAB <= 8 ); + + // set interpolants for root clauses + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + { + if ( !pClause->fA ) // clause of B + { + Int_ManTruthFill( Int_ManTruthRead(p, pClause), p->nWords ); +// Int_ManPrintInterOne( p, pClause ); + continue; + } + // clause of A + Int_ManTruthClear( Int_ManTruthRead(p, pClause), p->nWords ); + for ( v = 0; v < (int)pClause->nLits; v++ ) + { + Var = lit_var(pClause->pLits[v]); + if ( p->pVarTypes[Var] < 0 ) // global var + { + VarAB = -p->pVarTypes[Var]-1; + assert( VarAB >= 0 && VarAB < p->nVarsAB ); + if ( lit_sign(pClause->pLits[v]) ) // negative var + Int_ManTruthOrNot( Int_ManTruthRead(p, pClause), uTruths[VarAB], p->nWords ); + else + Int_ManTruthOr( Int_ManTruthRead(p, pClause), uTruths[VarAB], p->nWords ); + } + } +// Int_ManPrintInterOne( p, pClause ); + } +} + +/**Function************************************************************* + + Synopsis [Computes interpolant for the given CNF.] + + Description [Returns the number of common variable found and interpolant. + Returns 0, if something did not work.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Int_ManInterpolate( Int_Man_t * p, Sto_Man_t * pCnf, int fVerbose, unsigned ** ppResult ) +{ + Sto_Cls_t * pClause; + int RetValue = 1; + int clkTotal = clock(); + + // check that the CNF makes sense + assert( pCnf->nVars > 0 && pCnf->nClauses > 0 ); + p->pCnf = pCnf; + p->fVerbose = fVerbose; + *ppResult = NULL; + + // adjust the manager + Int_ManResize( p ); + + // prepare the interpolant computation + Int_ManPrepareInter( p ); + + // construct proof for each clause + // start the proof + if ( p->fProofWrite ) + { + p->pFile = fopen( "proof.cnf_", "w" ); + p->Counter = 0; + } + + // write the root clauses + Sto_ManForEachClauseRoot( p->pCnf, pClause ) + Int_ManProofWriteOne( p, pClause ); + + // propagate root level assignments + if ( Int_ManProcessRoots( p ) ) + { + // if there is no conflict, consider learned clauses + Sto_ManForEachClause( p->pCnf, pClause ) + { + if ( pClause->fRoot ) + continue; + if ( !Int_ManProofRecordOne( p, pClause ) ) + { + RetValue = 0; + break; + } + } + } + + // stop the proof + if ( p->fProofWrite ) + { + fclose( p->pFile ); + p->pFile = NULL; + } + + if ( fVerbose ) + { + printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d. Ave = %.2f. Mem = %.2f Mb\n", + p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter, + 1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), + 1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) ); +p->timeTotal += clock() - clkTotal; + } + + *ppResult = Int_ManTruthRead( p, p->pCnf->pTail ); + return p->nVarsAB; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/bsat/satMem.c b/abc70930/src/sat/bsat/satMem.c new file mode 100644 index 00000000..bb234f66 --- /dev/null +++ b/abc70930/src/sat/bsat/satMem.c @@ -0,0 +1,527 @@ +/**CFile**************************************************************** + + FileName [satMem.c] + + PackageName [SAT solver.] + + Synopsis [Memory management.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: satMem.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "satMem.h" +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Sat_MmFixed_t_ +{ + // information about individual entries + int nEntrySize; // the size of one entry + int nEntriesAlloc; // the total number of entries allocated + int nEntriesUsed; // the number of entries in use + int nEntriesMax; // the max number of entries in use + char * pEntriesFree; // the linked list of free entries + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Sat_MmFlex_t_ +{ + // information about individual entries + int nEntriesUsed; // the number of entries allocated + char * pCurrent; // the current pointer to free memory + char * pEnd; // the first entry outside the free memory + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Sat_MmStep_t_ +{ + int nMems; // the number of fixed memory managers employed + Sat_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc + int nMapSize; // the size of the memory array + Sat_MmFixed_t ** pMap; // maps the number of bytes into its memory manager +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates memory pieces of fixed size.] + + Description [The size of the chunk is computed as the minimum of + 1024 entries and 64K. Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sat_MmFixed_t * Sat_MmFixedStart( int nEntrySize ) +{ + Sat_MmFixed_t * p; + + p = ALLOC( Sat_MmFixed_t, 1 ); + memset( p, 0, sizeof(Sat_MmFixed_t) ); + + p->nEntrySize = nEntrySize; + p->nEntriesAlloc = 0; + p->nEntriesUsed = 0; + p->pEntriesFree = NULL; + + if ( nEntrySize * (1 << 10) < (1<<16) ) + p->nChunkSize = (1 << 10); + else + p->nChunkSize = (1<<16) / nEntrySize; + if ( p->nChunkSize < 8 ) + p->nChunkSize = 8; + + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_MmFixedStop( Sat_MmFixed_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", + p->nEntrySize, p->nChunkSize, p->nChunks ); + printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", + p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Sat_MmFixedEntryFetch( Sat_MmFixed_t * p ) +{ + char * pTemp; + int i; + + // check if there are still free entries + if ( p->nEntriesUsed == p->nEntriesAlloc ) + { // need to allocate more entries + assert( p->pEntriesFree == NULL ); + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); + p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; + // transform these entries into a linked list + pTemp = p->pEntriesFree; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pEntriesFree; + // add to the number of entries allocated + p->nEntriesAlloc += p->nChunkSize; + } + // incrememt the counter of used entries + p->nEntriesUsed++; + if ( p->nEntriesMax < p->nEntriesUsed ) + p->nEntriesMax = p->nEntriesUsed; + // return the first entry in the free entry list + pTemp = p->pEntriesFree; + p->pEntriesFree = *((char **)pTemp); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_MmFixedEntryRecycle( Sat_MmFixed_t * p, char * pEntry ) +{ + // decrement the counter of used entries + p->nEntriesUsed--; + // add the entry to the linked list of free entries + *((char **)pEntry) = p->pEntriesFree; + p->pEntriesFree = pEntry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_MmFixedRestart( Sat_MmFixed_t * p ) +{ + int i; + char * pTemp; + + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + p->nChunks = 1; + // transform these entries into a linked list + pTemp = p->pChunks[0]; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // set the free entry list + p->pEntriesFree = p->pChunks[0]; + // set the correct statistics + p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; + p->nMemoryUsed = 0; + p->nEntriesAlloc = p->nChunkSize; + p->nEntriesUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sat_MmFixedReadMemUsage( Sat_MmFixed_t * p ) +{ + return p->nMemoryAlloc; +} + + + +/**Function************************************************************* + + Synopsis [Allocates entries of flexible size.] + + Description [Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sat_MmFlex_t * Sat_MmFlexStart() +{ + Sat_MmFlex_t * p; + + p = ALLOC( Sat_MmFlex_t, 1 ); + memset( p, 0, sizeof(Sat_MmFlex_t) ); + + p->nEntriesUsed = 0; + p->pCurrent = NULL; + p->pEnd = NULL; + + p->nChunkSize = (1 << 12); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_MmFlexStop( Sat_MmFlex_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", + p->nChunkSize, p->nChunks ); + printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", + p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Sat_MmFlexEntryFetch( Sat_MmFlex_t * p, int nBytes ) +{ + char * pTemp; + // check if there are still free entries + if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) + { // need to allocate more entries + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + if ( nBytes > p->nChunkSize ) + { + // resize the chunk size if more memory is requested than it can give + // (ideally, this should never happen) + p->nChunkSize = 2 * nBytes; + } + p->pCurrent = ALLOC( char, p->nChunkSize ); + p->pEnd = p->pCurrent + p->nChunkSize; + p->nMemoryAlloc += p->nChunkSize; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pCurrent; + } + assert( p->pCurrent + nBytes <= p->pEnd ); + // increment the counter of used entries + p->nEntriesUsed++; + // keep track of the memory used + p->nMemoryUsed += nBytes; + // return the next entry + pTemp = p->pCurrent; + p->pCurrent += nBytes; + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sat_MmFlexReadMemUsage( Sat_MmFlex_t * p ) +{ + return p->nMemoryAlloc; +} + + + + + +/**Function************************************************************* + + Synopsis [Starts the hierarchical memory manager.] + + Description [This manager can allocate entries of any size. + Iternally they are mapped into the entries with the number of bytes + equal to the power of 2. The smallest entry size is 8 bytes. The + next one is 16 bytes etc. So, if the user requests 6 bytes, he gets + 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. + The input parameters "nSteps" says how many fixed memory managers + are employed internally. Calling this procedure with nSteps equal + to 10 results in 10 hierarchically arranged internal memory managers, + which can allocate up to 4096 (1Kb) entries. Requests for larger + entries are handed over to malloc() and then free()ed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sat_MmStep_t * Sat_MmStepStart( int nSteps ) +{ + Sat_MmStep_t * p; + int i, k; + p = ALLOC( Sat_MmStep_t, 1 ); + p->nMems = nSteps; + // start the fixed memory managers + p->pMems = ALLOC( Sat_MmFixed_t *, p->nMems ); + for ( i = 0; i < p->nMems; i++ ) + p->pMems[i] = Sat_MmFixedStart( (8<nMapSize = (4<nMems); + p->pMap = ALLOC( Sat_MmFixed_t *, p->nMapSize+1 ); + p->pMap[0] = NULL; + for ( k = 1; k <= 4; k++ ) + p->pMap[k] = p->pMems[0]; + for ( i = 0; i < p->nMems; i++ ) + for ( k = (4<pMap[k] = p->pMems[i]; +//for ( i = 1; i < 100; i ++ ) +//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_MmStepStop( Sat_MmStep_t * p, int fVerbose ) +{ + int i; + for ( i = 0; i < p->nMems; i++ ) + Sat_MmFixedStop( p->pMems[i], fVerbose ); + free( p->pMems ); + free( p->pMap ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Creates the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Sat_MmStepEntryFetch( Sat_MmStep_t * p, int nBytes ) +{ + if ( nBytes == 0 ) + return NULL; + if ( nBytes > p->nMapSize ) + { +// printf( "Allocating %d bytes.\n", nBytes ); + return ALLOC( char, nBytes ); + } + return Sat_MmFixedEntryFetch( p->pMap[nBytes] ); +} + + +/**Function************************************************************* + + Synopsis [Recycles the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_MmStepEntryRecycle( Sat_MmStep_t * p, char * pEntry, int nBytes ) +{ + if ( nBytes == 0 ) + return; + if ( nBytes > p->nMapSize ) + { + free( pEntry ); + return; + } + Sat_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sat_MmStepReadMemUsage( Sat_MmStep_t * p ) +{ + int i, nMemTotal = 0; + for ( i = 0; i < p->nMems; i++ ) + nMemTotal += p->pMems[i]->nMemoryAlloc; + return nMemTotal; +} diff --git a/abc70930/src/sat/bsat/satMem.h b/abc70930/src/sat/bsat/satMem.h new file mode 100644 index 00000000..5c5ddd9c --- /dev/null +++ b/abc70930/src/sat/bsat/satMem.h @@ -0,0 +1,78 @@ +/**CFile**************************************************************** + + FileName [satMem.h] + + PackageName [SAT solver.] + + Synopsis [Memory management.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: satMem.h,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __SAT_MEM_H__ +#define __SAT_MEM_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//#include "leaks.h" +#include +#include + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Sat_MmFixed_t_ Sat_MmFixed_t; +typedef struct Sat_MmFlex_t_ Sat_MmFlex_t; +typedef struct Sat_MmStep_t_ Sat_MmStep_t; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// fixed-size-block memory manager +extern Sat_MmFixed_t * Sat_MmFixedStart( int nEntrySize ); +extern void Sat_MmFixedStop( Sat_MmFixed_t * p, int fVerbose ); +extern char * Sat_MmFixedEntryFetch( Sat_MmFixed_t * p ); +extern void Sat_MmFixedEntryRecycle( Sat_MmFixed_t * p, char * pEntry ); +extern void Sat_MmFixedRestart( Sat_MmFixed_t * p ); +extern int Sat_MmFixedReadMemUsage( Sat_MmFixed_t * p ); +// flexible-size-block memory manager +extern Sat_MmFlex_t * Sat_MmFlexStart(); +extern void Sat_MmFlexStop( Sat_MmFlex_t * p, int fVerbose ); +extern char * Sat_MmFlexEntryFetch( Sat_MmFlex_t * p, int nBytes ); +extern int Sat_MmFlexReadMemUsage( Sat_MmFlex_t * p ); +// hierarchical memory manager +extern Sat_MmStep_t * Sat_MmStepStart( int nSteps ); +extern void Sat_MmStepStop( Sat_MmStep_t * p, int fVerbose ); +extern char * Sat_MmStepEntryFetch( Sat_MmStep_t * p, int nBytes ); +extern void Sat_MmStepEntryRecycle( Sat_MmStep_t * p, char * pEntry, int nBytes ); +extern int Sat_MmStepReadMemUsage( Sat_MmStep_t * p ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/sat/bsat/satSolver.c b/abc70930/src/sat/bsat/satSolver.c new file mode 100644 index 00000000..439d9e76 --- /dev/null +++ b/abc70930/src/sat/bsat/satSolver.c @@ -0,0 +1,1358 @@ +/************************************************************************************************** +MiniSat -- Copyright (c) 2005, Niklas Sorensson +http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ +// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko + +#include +#include +#include +#include + +#include "satSolver.h" + +//#define SAT_USE_SYSTEM_MEMORY_MANAGEMENT + +//================================================================================================= +// Debug: + +//#define VERBOSEDEBUG + +// For derivation output (verbosity level 2) +#define L_IND "%-*d" +#define L_ind sat_solver_dlevel(s)*3+3,sat_solver_dlevel(s) +#define L_LIT "%sx%d" +#define L_lit(p) lit_sign(p)?"~":"", (lit_var(p)) + +// Just like 'assert()' but expression will be evaluated in the release version as well. +static inline void check(int expr) { assert(expr); } + +static void printlits(lit* begin, lit* end) +{ + int i; + for (i = 0; i < end - begin; i++) + printf(L_LIT" ",L_lit(begin[i])); +} + +//================================================================================================= +// Random numbers: + + +// Returns a random float 0 <= x < 1. Seed must never be 0. +static inline double drand(double* seed) { + int q; + *seed *= 1389796; + q = (int)(*seed / 2147483647); + *seed -= (double)q * 2147483647; + return *seed / 2147483647; } + + +// Returns a random integer 0 <= x < size. Seed must never be 0. +static inline int irand(double* seed, int size) { + return (int)(drand(seed) * size); } + + +//================================================================================================= +// Predeclarations: + +static void sat_solver_sort(void** array, int size, int(*comp)(const void *, const void *)); + +//================================================================================================= +// Clause datatype + minor functions: + +struct clause_t +{ + int size_learnt; + lit lits[0]; +}; + +static inline int clause_size (clause* c) { return c->size_learnt >> 1; } +static inline lit* clause_begin (clause* c) { return c->lits; } +static inline int clause_learnt (clause* c) { return c->size_learnt & 1; } +static inline float clause_activity (clause* c) { return *((float*)&c->lits[c->size_learnt>>1]); } +static inline void clause_setactivity(clause* c, float a) { *((float*)&c->lits[c->size_learnt>>1]) = a; } + +//================================================================================================= +// Encode literals in clause pointers: + +static inline clause* clause_from_lit (lit l) { return (clause*)((unsigned long)l + (unsigned long)l + 1); } +static inline bool clause_is_lit (clause* c) { return ((unsigned long)c & 1); } +static inline lit clause_read_lit (clause* c) { return (lit)((unsigned long)c >> 1); } + +//================================================================================================= +// Simple helpers: + +static inline int sat_solver_dlevel(sat_solver* s) { return veci_size(&s->trail_lim); } +static inline vecp* sat_solver_read_wlist(sat_solver* s, lit l) { return &s->wlists[l]; } +static inline void vecp_remove(vecp* v, void* e) +{ + void** ws = vecp_begin(v); + int j = 0; + for (; ws[j] != e ; j++); + assert(j < vecp_size(v)); + for (; j < vecp_size(v)-1; j++) ws[j] = ws[j+1]; + vecp_resize(v,vecp_size(v)-1); +} + +//================================================================================================= +// Variable order functions: + +static inline void order_update(sat_solver* s, int v) // updateorder +{ + int* orderpos = s->orderpos; + double* activity = s->activity; + int* heap = veci_begin(&s->order); + int i = orderpos[v]; + int x = heap[i]; + int parent = (i - 1) / 2; + + assert(s->orderpos[v] != -1); + + while (i != 0 && activity[x] > activity[heap[parent]]){ + heap[i] = heap[parent]; + orderpos[heap[i]] = i; + i = parent; + parent = (i - 1) / 2; + } + heap[i] = x; + orderpos[x] = i; +} + +static inline void order_assigned(sat_solver* s, int v) +{ +} + +static inline void order_unassigned(sat_solver* s, int v) // undoorder +{ + int* orderpos = s->orderpos; + if (orderpos[v] == -1){ + orderpos[v] = veci_size(&s->order); + veci_push(&s->order,v); + order_update(s,v); +//printf( "+%d ", v ); + } +} + +static inline int order_select(sat_solver* s, float random_var_freq) // selectvar +{ + int* heap; + double* activity; + int* orderpos; + + lbool* values = s->assigns; + + // Random decision: + if (drand(&s->random_seed) < random_var_freq){ + int next = irand(&s->random_seed,s->size); + assert(next >= 0 && next < s->size); + if (values[next] == l_Undef) + return next; + } + + // Activity based decision: + + heap = veci_begin(&s->order); + activity = s->activity; + orderpos = s->orderpos; + + + while (veci_size(&s->order) > 0){ + int next = heap[0]; + int size = veci_size(&s->order)-1; + int x = heap[size]; + + veci_resize(&s->order,size); + + orderpos[next] = -1; + + if (size > 0){ + double act = activity[x]; + + int i = 0; + int child = 1; + + + while (child < size){ + if (child+1 < size && activity[heap[child]] < activity[heap[child+1]]) + child++; + + assert(child < size); + + if (act >= activity[heap[child]]) + break; + + heap[i] = heap[child]; + orderpos[heap[i]] = i; + i = child; + child = 2 * child + 1; + } + heap[i] = x; + orderpos[heap[i]] = i; + } + +//printf( "-%d ", next ); + if (values[next] == l_Undef) + return next; + } + + return var_Undef; +} + +//================================================================================================= +// Activity functions: + +static inline void act_var_rescale(sat_solver* s) { + double* activity = s->activity; + int i; + for (i = 0; i < s->size; i++) + activity[i] *= 1e-100; + s->var_inc *= 1e-100; +} + +static inline void act_var_bump(sat_solver* s, int v) { + s->activity[v] += s->var_inc; + if (s->activity[v] > 1e100) + act_var_rescale(s); + //printf("bump %d %f\n", v-1, activity[v]); + if (s->orderpos[v] != -1) + order_update(s,v); +} + +static inline void act_var_bump_factor(sat_solver* s, int v) { + s->activity[v] += (s->var_inc * s->factors[v]); + if (s->activity[v] > 1e100) + act_var_rescale(s); + //printf("bump %d %f\n", v-1, activity[v]); + if (s->orderpos[v] != -1) + order_update(s,v); +} + +static inline void act_var_decay(sat_solver* s) { s->var_inc *= s->var_decay; } + +static inline void act_clause_rescale(sat_solver* s) { + clause** cs = (clause**)vecp_begin(&s->learnts); + int i; + for (i = 0; i < vecp_size(&s->learnts); i++){ + float a = clause_activity(cs[i]); + clause_setactivity(cs[i], a * (float)1e-20); + } + s->cla_inc *= (float)1e-20; +} + + +static inline void act_clause_bump(sat_solver* s, clause *c) { + float a = clause_activity(c) + s->cla_inc; + clause_setactivity(c,a); + if (a > 1e20) act_clause_rescale(s); +} + +static inline void act_clause_decay(sat_solver* s) { s->cla_inc *= s->cla_decay; } + +//================================================================================================= +// Clause functions: + +/* pre: size > 1 && no variable occurs twice + */ +static clause* clause_new(sat_solver* s, lit* begin, lit* end, int learnt) +{ + int size; + clause* c; + int i; + + assert(end - begin > 1); + assert(learnt >= 0 && learnt < 2); + size = end - begin; +// c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float)); +#ifdef SAT_USE_SYSTEM_MEMORY_MANAGEMENT + c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float)); +#else + c = (clause*)Sat_MmStepEntryFetch( s->pMem, sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float) ); +#endif + + c->size_learnt = (size << 1) | learnt; + assert(((unsigned int)c & 1) == 0); + + for (i = 0; i < size; i++) + c->lits[i] = begin[i]; + + if (learnt) + *((float*)&c->lits[size]) = 0.0; + + assert(begin[0] >= 0); + assert(begin[0] < s->size*2); + assert(begin[1] >= 0); + assert(begin[1] < s->size*2); + + assert(lit_neg(begin[0]) < s->size*2); + assert(lit_neg(begin[1]) < s->size*2); + + //vecp_push(sat_solver_read_wlist(s,lit_neg(begin[0])),(void*)c); + //vecp_push(sat_solver_read_wlist(s,lit_neg(begin[1])),(void*)c); + + vecp_push(sat_solver_read_wlist(s,lit_neg(begin[0])),(void*)(size > 2 ? c : clause_from_lit(begin[1]))); + vecp_push(sat_solver_read_wlist(s,lit_neg(begin[1])),(void*)(size > 2 ? c : clause_from_lit(begin[0]))); + + return c; +} + + +static void clause_remove(sat_solver* s, clause* c) +{ + lit* lits = clause_begin(c); + assert(lit_neg(lits[0]) < s->size*2); + assert(lit_neg(lits[1]) < s->size*2); + + //vecp_remove(sat_solver_read_wlist(s,lit_neg(lits[0])),(void*)c); + //vecp_remove(sat_solver_read_wlist(s,lit_neg(lits[1])),(void*)c); + + assert(lits[0] < s->size*2); + vecp_remove(sat_solver_read_wlist(s,lit_neg(lits[0])),(void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[1]))); + vecp_remove(sat_solver_read_wlist(s,lit_neg(lits[1])),(void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[0]))); + + if (clause_learnt(c)){ + s->stats.learnts--; + s->stats.learnts_literals -= clause_size(c); + }else{ + s->stats.clauses--; + s->stats.clauses_literals -= clause_size(c); + } + +#ifdef SAT_USE_SYSTEM_MEMORY_MANAGEMENT + free(c); +#else + Sat_MmStepEntryRecycle( s->pMem, (char *)c, sizeof(clause) + sizeof(lit) * clause_size(c) + clause_learnt(c) * sizeof(float) ); +#endif +} + + +static lbool clause_simplify(sat_solver* s, clause* c) +{ + lit* lits = clause_begin(c); + lbool* values = s->assigns; + int i; + + assert(sat_solver_dlevel(s) == 0); + + for (i = 0; i < clause_size(c); i++){ + lbool sig = !lit_sign(lits[i]); sig += sig - 1; + if (values[lit_var(lits[i])] == sig) + return l_True; + } + return l_False; +} + +//================================================================================================= +// Minor (solver) functions: + +void sat_solver_setnvars(sat_solver* s,int n) +{ + int var; + + if (s->cap < n){ + + while (s->cap < n) s->cap = s->cap*2+1; + + s->wlists = (vecp*) realloc(s->wlists, sizeof(vecp)*s->cap*2); + s->activity = (double*) realloc(s->activity, sizeof(double)*s->cap); + s->factors = (double*) realloc(s->factors, sizeof(double)*s->cap); + s->assigns = (lbool*) realloc(s->assigns, sizeof(lbool)*s->cap); + s->orderpos = (int*) realloc(s->orderpos, sizeof(int)*s->cap); + s->reasons = (clause**)realloc(s->reasons, sizeof(clause*)*s->cap); + s->levels = (int*) realloc(s->levels, sizeof(int)*s->cap); + s->tags = (lbool*) realloc(s->tags, sizeof(lbool)*s->cap); + s->trail = (lit*) realloc(s->trail, sizeof(lit)*s->cap); + } + + for (var = s->size; var < n; var++){ + vecp_new(&s->wlists[2*var]); + vecp_new(&s->wlists[2*var+1]); + s->activity [var] = 0; + s->factors [var] = 0; + s->assigns [var] = l_Undef; + s->orderpos [var] = veci_size(&s->order); + s->reasons [var] = (clause*)0; + s->levels [var] = 0; + s->tags [var] = l_Undef; + + /* does not hold because variables enqueued at top level will not be reinserted in the heap + assert(veci_size(&s->order) == var); + */ + veci_push(&s->order,var); + order_update(s, var); + } + + s->size = n > s->size ? n : s->size; +} + + +static inline bool enqueue(sat_solver* s, lit l, clause* from) +{ + lbool* values = s->assigns; + int v = lit_var(l); + lbool val = values[v]; +#ifdef VERBOSEDEBUG + printf(L_IND"enqueue("L_LIT")\n", L_ind, L_lit(l)); +#endif + + lbool sig = !lit_sign(l); sig += sig - 1; + if (val != l_Undef){ + return val == sig; + }else{ + // New fact -- store it. +#ifdef VERBOSEDEBUG + printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(l)); +#endif + int* levels = s->levels; + clause** reasons = s->reasons; + + values [v] = sig; + levels [v] = sat_solver_dlevel(s); + reasons[v] = from; + s->trail[s->qtail++] = l; + + order_assigned(s, v); + return true; + } +} + + +static inline void assume(sat_solver* s, lit l){ + assert(s->qtail == s->qhead); + assert(s->assigns[lit_var(l)] == l_Undef); +#ifdef VERBOSEDEBUG + printf(L_IND"assume("L_LIT")\n", L_ind, L_lit(l)); +#endif + veci_push(&s->trail_lim,s->qtail); + enqueue(s,l,(clause*)0); +} + + +static void sat_solver_canceluntil(sat_solver* s, int level) { + lit* trail; + lbool* values; + clause** reasons; + int bound; + int c; + + if (sat_solver_dlevel(s) <= level) + return; + + trail = s->trail; + values = s->assigns; + reasons = s->reasons; + bound = (veci_begin(&s->trail_lim))[level]; + + //////////////////////////////////////// + // added to cancel all assignments +// if ( level == -1 ) +// bound = 0; + //////////////////////////////////////// + + for (c = s->qtail-1; c >= bound; c--) { + int x = lit_var(trail[c]); + values [x] = l_Undef; + reasons[x] = (clause*)0; + } + + for (c = s->qhead-1; c >= bound; c--) + order_unassigned(s,lit_var(trail[c])); + + s->qhead = s->qtail = bound; + veci_resize(&s->trail_lim,level); +} + +static void sat_solver_record(sat_solver* s, veci* cls) +{ + lit* begin = veci_begin(cls); + lit* end = begin + veci_size(cls); + clause* c = (veci_size(cls) > 1) ? clause_new(s,begin,end,1) : (clause*)0; + enqueue(s,*begin,c); + + /////////////////////////////////// + // add clause to internal storage + if ( s->pStore ) + { + extern int Sto_ManAddClause( void * p, lit * pBeg, lit * pEnd ); + int RetValue = Sto_ManAddClause( s->pStore, begin, end ); + assert( RetValue ); + } + /////////////////////////////////// + + assert(veci_size(cls) > 0); + + if (c != 0) { + vecp_push(&s->learnts,c); + act_clause_bump(s,c); + s->stats.learnts++; + s->stats.learnts_literals += veci_size(cls); + } +} + + +static double sat_solver_progress(sat_solver* s) +{ + lbool* values = s->assigns; + int* levels = s->levels; + int i; + + double progress = 0; + double F = 1.0 / s->size; + for (i = 0; i < s->size; i++) + if (values[i] != l_Undef) + progress += pow(F, levels[i]); + return progress / s->size; +} + +//================================================================================================= +// Major methods: + +static bool sat_solver_lit_removable(sat_solver* s, lit l, int minl) +{ + lbool* tags = s->tags; + clause** reasons = s->reasons; + int* levels = s->levels; + int top = veci_size(&s->tagged); + + assert(lit_var(l) >= 0 && lit_var(l) < s->size); + assert(reasons[lit_var(l)] != 0); + veci_resize(&s->stack,0); + veci_push(&s->stack,lit_var(l)); + + while (veci_size(&s->stack) > 0){ + clause* c; + int v = veci_begin(&s->stack)[veci_size(&s->stack)-1]; + assert(v >= 0 && v < s->size); + veci_resize(&s->stack,veci_size(&s->stack)-1); + assert(reasons[v] != 0); + c = reasons[v]; + + if (clause_is_lit(c)){ + int v = lit_var(clause_read_lit(c)); + if (tags[v] == l_Undef && levels[v] != 0){ + if (reasons[v] != 0 && ((1 << (levels[v] & 31)) & minl)){ + veci_push(&s->stack,v); + tags[v] = l_True; + veci_push(&s->tagged,v); + }else{ + int* tagged = veci_begin(&s->tagged); + int j; + for (j = top; j < veci_size(&s->tagged); j++) + tags[tagged[j]] = l_Undef; + veci_resize(&s->tagged,top); + return false; + } + } + }else{ + lit* lits = clause_begin(c); + int i, j; + + for (i = 1; i < clause_size(c); i++){ + int v = lit_var(lits[i]); + if (tags[v] == l_Undef && levels[v] != 0){ + if (reasons[v] != 0 && ((1 << (levels[v] & 31)) & minl)){ + + veci_push(&s->stack,lit_var(lits[i])); + tags[v] = l_True; + veci_push(&s->tagged,v); + }else{ + int* tagged = veci_begin(&s->tagged); + for (j = top; j < veci_size(&s->tagged); j++) + tags[tagged[j]] = l_Undef; + veci_resize(&s->tagged,top); + return false; + } + } + } + } + } + + return true; +} + +static void sat_solver_analyze(sat_solver* s, clause* c, veci* learnt) +{ + lit* trail = s->trail; + lbool* tags = s->tags; + clause** reasons = s->reasons; + int* levels = s->levels; + int cnt = 0; + lit p = lit_Undef; + int ind = s->qtail-1; + lit* lits; + int i, j, minl; + int* tagged; + + veci_push(learnt,lit_Undef); + + do{ + assert(c != 0); + + if (clause_is_lit(c)){ + lit q = clause_read_lit(c); + assert(lit_var(q) >= 0 && lit_var(q) < s->size); + if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){ + tags[lit_var(q)] = l_True; + veci_push(&s->tagged,lit_var(q)); + act_var_bump(s,lit_var(q)); + if (levels[lit_var(q)] == sat_solver_dlevel(s)) + cnt++; + else + veci_push(learnt,q); + } + }else{ + + if (clause_learnt(c)) + act_clause_bump(s,c); + + lits = clause_begin(c); + //printlits(lits,lits+clause_size(c)); printf("\n"); + for (j = (p == lit_Undef ? 0 : 1); j < clause_size(c); j++){ + lit q = lits[j]; + assert(lit_var(q) >= 0 && lit_var(q) < s->size); + if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){ + tags[lit_var(q)] = l_True; + veci_push(&s->tagged,lit_var(q)); + act_var_bump(s,lit_var(q)); + if (levels[lit_var(q)] == sat_solver_dlevel(s)) + cnt++; + else + veci_push(learnt,q); + } + } + } + + while (tags[lit_var(trail[ind--])] == l_Undef); + + p = trail[ind+1]; + c = reasons[lit_var(p)]; + cnt--; + + }while (cnt > 0); + + *veci_begin(learnt) = lit_neg(p); + + lits = veci_begin(learnt); + minl = 0; + for (i = 1; i < veci_size(learnt); i++){ + int lev = levels[lit_var(lits[i])]; + minl |= 1 << (lev & 31); + } + + // simplify (full) + for (i = j = 1; i < veci_size(learnt); i++){ + if (reasons[lit_var(lits[i])] == 0 || !sat_solver_lit_removable(s,lits[i],minl)) + lits[j++] = lits[i]; + } + + // update size of learnt + statistics + s->stats.max_literals += veci_size(learnt); + veci_resize(learnt,j); + s->stats.tot_literals += j; + + // clear tags + tagged = veci_begin(&s->tagged); + for (i = 0; i < veci_size(&s->tagged); i++) + tags[tagged[i]] = l_Undef; + veci_resize(&s->tagged,0); + +#ifdef DEBUG + for (i = 0; i < s->size; i++) + assert(tags[i] == l_Undef); +#endif + +#ifdef VERBOSEDEBUG + printf(L_IND"Learnt {", L_ind); + for (i = 0; i < veci_size(learnt); i++) printf(" "L_LIT, L_lit(lits[i])); +#endif + if (veci_size(learnt) > 1){ + int max_i = 1; + int max = levels[lit_var(lits[1])]; + lit tmp; + + for (i = 2; i < veci_size(learnt); i++) + if (levels[lit_var(lits[i])] > max){ + max = levels[lit_var(lits[i])]; + max_i = i; + } + + tmp = lits[1]; + lits[1] = lits[max_i]; + lits[max_i] = tmp; + } +#ifdef VERBOSEDEBUG + { + int lev = veci_size(learnt) > 1 ? levels[lit_var(lits[1])] : 0; + printf(" } at level %d\n", lev); + } +#endif +} + + +clause* sat_solver_propagate(sat_solver* s) +{ + lbool* values = s->assigns; + clause* confl = (clause*)0; + lit* lits; + + //printf("sat_solver_propagate\n"); + while (confl == 0 && s->qtail - s->qhead > 0){ + lit p = s->trail[s->qhead++]; + vecp* ws = sat_solver_read_wlist(s,p); + clause **begin = (clause**)vecp_begin(ws); + clause **end = begin + vecp_size(ws); + clause **i, **j; + + s->stats.propagations++; + s->simpdb_props--; + + //printf("checking lit %d: "L_LIT"\n", veci_size(ws), L_lit(p)); + for (i = j = begin; i < end; ){ + if (clause_is_lit(*i)){ +// s->stats.inspects2++; + *j++ = *i; + if (!enqueue(s,clause_read_lit(*i),clause_from_lit(p))){ + confl = s->binary; + (clause_begin(confl))[1] = lit_neg(p); + (clause_begin(confl))[0] = clause_read_lit(*i++); + // Copy the remaining watches: +// s->stats.inspects2 += end - i; + while (i < end) + *j++ = *i++; + } + }else{ + lit false_lit; + lbool sig; + + lits = clause_begin(*i); + + // Make sure the false literal is data[1]: + false_lit = lit_neg(p); + if (lits[0] == false_lit){ + lits[0] = lits[1]; + lits[1] = false_lit; + } + assert(lits[1] == false_lit); + //printf("checking clause: "); printlits(lits, lits+clause_size(*i)); printf("\n"); + + // If 0th watch is true, then clause is already satisfied. + sig = !lit_sign(lits[0]); sig += sig - 1; + if (values[lit_var(lits[0])] == sig){ + *j++ = *i; + }else{ + // Look for new watch: + lit* stop = lits + clause_size(*i); + lit* k; + for (k = lits + 2; k < stop; k++){ + lbool sig = lit_sign(*k); sig += sig - 1; + if (values[lit_var(*k)] != sig){ + lits[1] = *k; + *k = false_lit; + vecp_push(sat_solver_read_wlist(s,lit_neg(lits[1])),*i); + goto next; } + } + + *j++ = *i; + // Clause is unit under assignment: + if (!enqueue(s,lits[0], *i)){ + confl = *i++; + // Copy the remaining watches: +// s->stats.inspects2 += end - i; + while (i < end) + *j++ = *i++; + } + } + } + next: + i++; + } + + s->stats.inspects += j - (clause**)vecp_begin(ws); + vecp_resize(ws,j - (clause**)vecp_begin(ws)); + } + + return confl; +} + +static inline int clause_cmp (const void* x, const void* y) { + return clause_size((clause*)x) > 2 && (clause_size((clause*)y) == 2 || clause_activity((clause*)x) < clause_activity((clause*)y)) ? -1 : 1; } + +void sat_solver_reducedb(sat_solver* s) +{ + int i, j; + double extra_lim = s->cla_inc / vecp_size(&s->learnts); // Remove any clause below this activity + clause** learnts = (clause**)vecp_begin(&s->learnts); + clause** reasons = s->reasons; + + sat_solver_sort(vecp_begin(&s->learnts), vecp_size(&s->learnts), &clause_cmp); + + for (i = j = 0; i < vecp_size(&s->learnts) / 2; i++){ + if (clause_size(learnts[i]) > 2 && reasons[lit_var(*clause_begin(learnts[i]))] != learnts[i]) + clause_remove(s,learnts[i]); + else + learnts[j++] = learnts[i]; + } + for (; i < vecp_size(&s->learnts); i++){ + if (clause_size(learnts[i]) > 2 && reasons[lit_var(*clause_begin(learnts[i]))] != learnts[i] && clause_activity(learnts[i]) < extra_lim) + clause_remove(s,learnts[i]); + else + learnts[j++] = learnts[i]; + } + + //printf("reducedb deleted %d\n", vecp_size(&s->learnts) - j); + + + vecp_resize(&s->learnts,j); +} + +static lbool sat_solver_search(sat_solver* s, sint64 nof_conflicts, sint64 nof_learnts) +{ + int* levels = s->levels; + double var_decay = 0.95; + double clause_decay = 0.999; + double random_var_freq = 0.02; + + sint64 conflictC = 0; + veci learnt_clause; + int i; + + assert(s->root_level == sat_solver_dlevel(s)); + + s->nRestarts++; + s->stats.starts++; + s->var_decay = (float)(1 / var_decay ); + s->cla_decay = (float)(1 / clause_decay); + veci_resize(&s->model,0); + veci_new(&learnt_clause); + + // use activity factors in every even restart + if ( (s->nRestarts & 1) && veci_size(&s->act_vars) > 0 ) + for ( i = 0; i < s->act_vars.size; i++ ) + act_var_bump_factor(s, s->act_vars.ptr[i]); + + for (;;){ + clause* confl = sat_solver_propagate(s); + if (confl != 0){ + // CONFLICT + int blevel; + +#ifdef VERBOSEDEBUG + printf(L_IND"**CONFLICT**\n", L_ind); +#endif + s->stats.conflicts++; conflictC++; + if (sat_solver_dlevel(s) == s->root_level){ + veci_delete(&learnt_clause); + return l_False; + } + + veci_resize(&learnt_clause,0); + sat_solver_analyze(s, confl, &learnt_clause); + blevel = veci_size(&learnt_clause) > 1 ? levels[lit_var(veci_begin(&learnt_clause)[1])] : s->root_level; + blevel = s->root_level > blevel ? s->root_level : blevel; + sat_solver_canceluntil(s,blevel); + sat_solver_record(s,&learnt_clause); + act_var_decay(s); + act_clause_decay(s); + + }else{ + // NO CONFLICT + int next; + + if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ + // Reached bound on number of conflicts: + s->progress_estimate = sat_solver_progress(s); + sat_solver_canceluntil(s,s->root_level); + veci_delete(&learnt_clause); + return l_Undef; } + + if ( s->nConfLimit && s->stats.conflicts > s->nConfLimit || + s->nInsLimit && s->stats.inspects > s->nInsLimit ) + { + // Reached bound on number of conflicts: + s->progress_estimate = sat_solver_progress(s); + sat_solver_canceluntil(s,s->root_level); + veci_delete(&learnt_clause); + return l_Undef; + } + + if (sat_solver_dlevel(s) == 0 && !s->fSkipSimplify) + // Simplify the set of problem clauses: + sat_solver_simplify(s); + + if (nof_learnts >= 0 && vecp_size(&s->learnts) - s->qtail >= nof_learnts) + // Reduce the set of learnt clauses: + sat_solver_reducedb(s); + + // New variable decision: + s->stats.decisions++; + next = order_select(s,(float)random_var_freq); + + if (next == var_Undef){ + // Model found: + lbool* values = s->assigns; + int i; + veci_resize(&s->model, 0); + for (i = 0; i < s->size; i++) + veci_push(&s->model,(int)values[i]); + sat_solver_canceluntil(s,s->root_level); + veci_delete(&learnt_clause); + + /* + veci apa; veci_new(&apa); + for (i = 0; i < s->size; i++) + veci_push(&apa,(int)(s->model.ptr[i] == l_True ? toLit(i) : lit_neg(toLit(i)))); + printf("model: "); printlits((lit*)apa.ptr, (lit*)apa.ptr + veci_size(&apa)); printf("\n"); + veci_delete(&apa); + */ + + return l_True; + } + + assume(s,lit_neg(toLit(next))); + } + } + + return l_Undef; // cannot happen +} + +//================================================================================================= +// External solver functions: + +sat_solver* sat_solver_new(void) +{ + sat_solver* s = (sat_solver*)malloc(sizeof(sat_solver)); + memset( s, 0, sizeof(sat_solver) ); + + // initialize vectors + vecp_new(&s->clauses); + vecp_new(&s->learnts); + veci_new(&s->order); + veci_new(&s->trail_lim); + veci_new(&s->tagged); + veci_new(&s->stack); + veci_new(&s->model); + veci_new(&s->act_vars); + + // initialize arrays + s->wlists = 0; + s->activity = 0; + s->factors = 0; + s->assigns = 0; + s->orderpos = 0; + s->reasons = 0; + s->levels = 0; + s->tags = 0; + s->trail = 0; + + + // initialize other vars + s->size = 0; + s->cap = 0; + s->qhead = 0; + s->qtail = 0; + s->cla_inc = 1; + s->cla_decay = 1; + s->var_inc = 1; + s->var_decay = 1; + s->root_level = 0; + s->simpdb_assigns = 0; + s->simpdb_props = 0; + s->random_seed = 91648253; + s->progress_estimate = 0; + s->binary = (clause*)malloc(sizeof(clause) + sizeof(lit)*2); + s->binary->size_learnt = (2 << 1); + s->verbosity = 0; + + s->stats.starts = 0; + s->stats.decisions = 0; + s->stats.propagations = 0; + s->stats.inspects = 0; + s->stats.conflicts = 0; + s->stats.clauses = 0; + s->stats.clauses_literals = 0; + s->stats.learnts = 0; + s->stats.learnts_literals = 0; + s->stats.max_literals = 0; + s->stats.tot_literals = 0; + +#ifdef SAT_USE_SYSTEM_MEMORY_MANAGEMENT + s->pMem = NULL; +#else + s->pMem = Sat_MmStepStart( 10 ); +#endif + return s; +} + + +void sat_solver_delete(sat_solver* s) +{ + +#ifdef SAT_USE_SYSTEM_MEMORY_MANAGEMENT + int i; + for (i = 0; i < vecp_size(&s->clauses); i++) + free(vecp_begin(&s->clauses)[i]); + for (i = 0; i < vecp_size(&s->learnts); i++) + free(vecp_begin(&s->learnts)[i]); +#else + Sat_MmStepStop( s->pMem, 0 ); +#endif + + // delete vectors + vecp_delete(&s->clauses); + vecp_delete(&s->learnts); + veci_delete(&s->order); + veci_delete(&s->trail_lim); + veci_delete(&s->tagged); + veci_delete(&s->stack); + veci_delete(&s->model); + veci_delete(&s->act_vars); + free(s->binary); + + // delete arrays + if (s->wlists != 0){ + int i; + for (i = 0; i < s->size*2; i++) + vecp_delete(&s->wlists[i]); + + // if one is different from null, all are + free(s->wlists ); + free(s->activity ); + free(s->factors ); + free(s->assigns ); + free(s->orderpos ); + free(s->reasons ); + free(s->levels ); + free(s->trail ); + free(s->tags ); + } + + sat_solver_store_free(s); + free(s); +} + + +bool sat_solver_addclause(sat_solver* s, lit* begin, lit* end) +{ + lit *i,*j; + int maxvar; + lbool* values; + lit last; + + if (begin == end) return false; + + //printlits(begin,end); printf("\n"); + // insertion sort + maxvar = lit_var(*begin); + for (i = begin + 1; i < end; i++){ + lit l = *i; + maxvar = lit_var(l) > maxvar ? lit_var(l) : maxvar; + for (j = i; j > begin && *(j-1) > l; j--) + *j = *(j-1); + *j = l; + } + sat_solver_setnvars(s,maxvar+1); +// sat_solver_setnvars(s, lit_var(*(end-1))+1 ); + + //printlits(begin,end); printf("\n"); + values = s->assigns; + + // delete duplicates + last = lit_Undef; + for (i = j = begin; i < end; i++){ + //printf("lit: "L_LIT", value = %d\n", L_lit(*i), (lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)])); + lbool sig = !lit_sign(*i); sig += sig - 1; + if (*i == lit_neg(last) || sig == values[lit_var(*i)]) + return true; // tautology + else if (*i != last && values[lit_var(*i)] == l_Undef) + last = *j++ = *i; + } + + //printf("final: "); printlits(begin,j); printf("\n"); + + if (j == begin) // empty clause + return false; + + /////////////////////////////////// + // add clause to internal storage + if ( s->pStore ) + { + extern int Sto_ManAddClause( void * p, lit * pBeg, lit * pEnd ); + int RetValue = Sto_ManAddClause( s->pStore, begin, j ); + assert( RetValue ); + } + /////////////////////////////////// + + if (j - begin == 1) // unit clause + return enqueue(s,*begin,(clause*)0); + + // create new clause + vecp_push(&s->clauses,clause_new(s,begin,j,0)); + + + s->stats.clauses++; + s->stats.clauses_literals += j - begin; + + return true; +} + + +bool sat_solver_simplify(sat_solver* s) +{ + clause** reasons; + int type; + + assert(sat_solver_dlevel(s) == 0); + + if (sat_solver_propagate(s) != 0) + return false; + + if (s->qhead == s->simpdb_assigns || s->simpdb_props > 0) + return true; + + reasons = s->reasons; + for (type = 0; type < 2; type++){ + vecp* cs = type ? &s->learnts : &s->clauses; + clause** cls = (clause**)vecp_begin(cs); + + int i, j; + for (j = i = 0; i < vecp_size(cs); i++){ + if (reasons[lit_var(*clause_begin(cls[i]))] != cls[i] && + clause_simplify(s,cls[i]) == l_True) + clause_remove(s,cls[i]); + else + cls[j++] = cls[i]; + } + vecp_resize(cs,j); + } + + s->simpdb_assigns = s->qhead; + // (shouldn't depend on 'stats' really, but it will do for now) + s->simpdb_props = (int)(s->stats.clauses_literals + s->stats.learnts_literals); + + return true; +} + + +int sat_solver_solve(sat_solver* s, lit* begin, lit* end, sint64 nConfLimit, sint64 nInsLimit, sint64 nConfLimitGlobal, sint64 nInsLimitGlobal) +{ + sint64 nof_conflicts = 100; + sint64 nof_learnts = sat_solver_nclauses(s) / 3; + lbool status = l_Undef; + lbool* values = s->assigns; + lit* i; + + // set the external limits + s->nCalls++; + s->nRestarts = 0; + s->nConfLimit = 0; + s->nInsLimit = 0; + if ( nConfLimit ) + s->nConfLimit = s->stats.conflicts + nConfLimit; + if ( nInsLimit ) + s->nInsLimit = s->stats.inspects + nInsLimit; + if ( nConfLimitGlobal && (s->nConfLimit == 0 || s->nConfLimit > nConfLimitGlobal) ) + s->nConfLimit = nConfLimitGlobal; + if ( nInsLimitGlobal && (s->nInsLimit == 0 || s->nInsLimit > nInsLimitGlobal) ) + s->nInsLimit = nInsLimitGlobal; + + //printf("solve: "); printlits(begin, end); printf("\n"); + for (i = begin; i < end; i++){ + switch (lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)]){ + case 1: /* l_True: */ + break; + case 0: /* l_Undef */ + assume(s, *i); + if (sat_solver_propagate(s) == NULL) + break; + // fallthrough + case -1: /* l_False */ + sat_solver_canceluntil(s, 0); + return l_False; + } + } + s->nCalls2++; + + s->root_level = sat_solver_dlevel(s); + + if (s->verbosity >= 1){ + printf("==================================[MINISAT]===================================\n"); + printf("| Conflicts | ORIGINAL | LEARNT | Progress |\n"); + printf("| | Clauses Literals | Limit Clauses Literals Lit/Cl | |\n"); + printf("==============================================================================\n"); + } + + while (status == l_Undef){ + double Ratio = (s->stats.learnts == 0)? 0.0 : + s->stats.learnts_literals / (double)s->stats.learnts; + + if (s->verbosity >= 1) + { + printf("| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %6.3f %% |\n", + (double)s->stats.conflicts, + (double)s->stats.clauses, + (double)s->stats.clauses_literals, + (double)nof_learnts, + (double)s->stats.learnts, + (double)s->stats.learnts_literals, + Ratio, + s->progress_estimate*100); + fflush(stdout); + } + status = sat_solver_search(s, nof_conflicts, nof_learnts); + nof_conflicts = nof_conflicts * 3 / 2; //*= 1.5; + nof_learnts = nof_learnts * 11 / 10; //*= 1.1; + + // quit the loop if reached an external limit + if ( s->nConfLimit && s->stats.conflicts > s->nConfLimit ) + { +// printf( "Reached the limit on the number of conflicts (%d).\n", s->nConfLimit ); + break; + } + if ( s->nInsLimit && s->stats.inspects > s->nInsLimit ) + { +// printf( "Reached the limit on the number of implications (%d).\n", s->nInsLimit ); + break; + } + } + if (s->verbosity >= 1) + printf("==============================================================================\n"); + + sat_solver_canceluntil(s,0); + + //////////////////////////////////////////////// + if ( status == l_False && s->pStore ) + { + extern int Sto_ManAddClause( void * p, lit * pBeg, lit * pEnd ); + int RetValue = Sto_ManAddClause( s->pStore, NULL, NULL ); + assert( RetValue ); + } + //////////////////////////////////////////////// + return status; +} + + +int sat_solver_nvars(sat_solver* s) +{ + return s->size; +} + + +int sat_solver_nclauses(sat_solver* s) +{ + return vecp_size(&s->clauses); +} + + +int sat_solver_nconflicts(sat_solver* s) +{ + return (int)s->stats.conflicts; +} + +//================================================================================================= +// Clause storage functions: + +void sat_solver_store_alloc( sat_solver * s ) +{ + extern void * Sto_ManAlloc(); + assert( s->pStore == NULL ); + s->pStore = Sto_ManAlloc(); +} + +void sat_solver_store_write( sat_solver * s, char * pFileName ) +{ + extern void Sto_ManDumpClauses( void * p, char * pFileName ); + if ( s->pStore ) Sto_ManDumpClauses( s->pStore, pFileName ); +} + +void sat_solver_store_free( sat_solver * s ) +{ + extern void Sto_ManFree( void * p ); + if ( s->pStore ) Sto_ManFree( s->pStore ); + s->pStore = NULL; +} + +void sat_solver_store_mark_roots( sat_solver * s ) +{ + extern void Sto_ManMarkRoots( void * p ); + if ( s->pStore ) Sto_ManMarkRoots( s->pStore ); +} + +void sat_solver_store_mark_clauses_a( sat_solver * s ) +{ + extern void Sto_ManMarkClausesA( void * p ); + if ( s->pStore ) Sto_ManMarkClausesA( s->pStore ); +} + +void * sat_solver_store_release( sat_solver * s ) +{ + void * pTemp; + if ( s->pStore == NULL ) + return NULL; + pTemp = s->pStore; + s->pStore = NULL; + return pTemp; +} + +//================================================================================================= +// Sorting functions (sigh): + +static inline void selectionsort(void** array, int size, int(*comp)(const void *, const void *)) +{ + int i, j, best_i; + void* tmp; + + for (i = 0; i < size-1; i++){ + best_i = i; + for (j = i+1; j < size; j++){ + if (comp(array[j], array[best_i]) < 0) + best_i = j; + } + tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; + } +} + + +static void sortrnd(void** array, int size, int(*comp)(const void *, const void *), double* seed) +{ + if (size <= 15) + selectionsort(array, size, comp); + + else{ + void* pivot = array[irand(seed, size)]; + void* tmp; + int i = -1; + int j = size; + + for(;;){ + do i++; while(comp(array[i], pivot)<0); + do j--; while(comp(pivot, array[j])<0); + + if (i >= j) break; + + tmp = array[i]; array[i] = array[j]; array[j] = tmp; + } + + sortrnd(array , i , comp, seed); + sortrnd(&array[i], size-i, comp, seed); + } +} + +void sat_solver_sort(void** array, int size, int(*comp)(const void *, const void *)) +{ + double seed = 91648253; + sortrnd(array,size,comp,&seed); +} diff --git a/abc70930/src/sat/bsat/satSolver.h b/abc70930/src/sat/bsat/satSolver.h new file mode 100644 index 00000000..542b9895 --- /dev/null +++ b/abc70930/src/sat/bsat/satSolver.h @@ -0,0 +1,191 @@ +/************************************************************************************************** +MiniSat -- Copyright (c) 2005, Niklas Sorensson +http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ +// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko + +#ifndef satSolver_h +#define satSolver_h + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +#include "satVec.h" +#include "satMem.h" + +//================================================================================================= +// Simple types: + +// does not work for c++ +//typedef int bool; +#ifndef __cplusplus +#ifndef bool +#define bool int +#endif +#endif + +static const bool true = 1; +static const bool false = 0; + +typedef int lit; +typedef char lbool; + +#ifndef SINT64 +#define SINT64 + +#ifdef _WIN32 +typedef signed __int64 sint64; // compatible with MS VS 6.0 +#else +typedef long long sint64; +#endif + +#endif + +static const int var_Undef = -1; +static const lit lit_Undef = -2; + +static const lbool l_Undef = 0; +static const lbool l_True = 1; +static const lbool l_False = -1; + +static inline lit toLit (int v) { return v + v; } +static inline lit toLitCond(int v, int c) { return v + v + (c != 0); } +static inline lit lit_neg (lit l) { return l ^ 1; } +static inline int lit_var (lit l) { return l >> 1; } +static inline int lit_sign (lit l) { return l & 1; } +static inline int lit_print(lit l) { return lit_sign(l)? -lit_var(l)-1 : lit_var(l)+1; } +static inline lit lit_read (int s) { return s > 0 ? toLit(s-1) : lit_neg(toLit(-s-1)); } + + +//================================================================================================= +// Public interface: + +struct sat_solver_t; +typedef struct sat_solver_t sat_solver; + +extern sat_solver* sat_solver_new(void); +extern void sat_solver_delete(sat_solver* s); + +extern bool sat_solver_addclause(sat_solver* s, lit* begin, lit* end); +extern bool sat_solver_simplify(sat_solver* s); +extern int sat_solver_solve(sat_solver* s, lit* begin, lit* end, sint64 nConfLimit, sint64 nInsLimit, sint64 nConfLimitGlobal, sint64 nInsLimitGlobal); + +extern int sat_solver_nvars(sat_solver* s); +extern int sat_solver_nclauses(sat_solver* s); +extern int sat_solver_nconflicts(sat_solver* s); + +extern void sat_solver_setnvars(sat_solver* s,int n); + +struct stats_t +{ + sint64 starts, decisions, propagations, inspects, conflicts; + sint64 clauses, clauses_literals, learnts, learnts_literals, max_literals, tot_literals; +}; +typedef struct stats_t stats; + +extern void Sat_SolverWriteDimacs( sat_solver * p, char * pFileName, lit* assumptionsBegin, lit* assumptionsEnd, int incrementVars ); +extern void Sat_SolverPrintStats( FILE * pFile, sat_solver * p ); +extern int * Sat_SolverGetModel( sat_solver * p, int * pVars, int nVars ); +extern void Sat_SolverDoubleClauses( sat_solver * p, int iVar ); + +// trace recording +extern void Sat_SolverTraceStart( sat_solver * pSat, char * pName ); +extern void Sat_SolverTraceStop( sat_solver * pSat ); +extern void Sat_SolverTraceWrite( sat_solver * pSat, int * pBeg, int * pEnd, int fRoot ); + +// clause storage +extern void sat_solver_store_alloc( sat_solver * s ); +extern void sat_solver_store_write( sat_solver * s, char * pFileName ); +extern void sat_solver_store_free( sat_solver * s ); +extern void sat_solver_store_mark_roots( sat_solver * s ); +extern void sat_solver_store_mark_clauses_a( sat_solver * s ); +extern void * sat_solver_store_release( sat_solver * s ); + +//================================================================================================= +// Solver representation: + +struct clause_t; +typedef struct clause_t clause; + +struct sat_solver_t +{ + int size; // nof variables + int cap; // size of varmaps + int qhead; // Head index of queue. + int qtail; // Tail index of queue. + + // clauses + vecp clauses; // List of problem constraints. (contains: clause*) + vecp learnts; // List of learnt clauses. (contains: clause*) + + // activities + double var_inc; // Amount to bump next variable with. + double var_decay; // INVERSE decay factor for variable activity: stores 1/decay. + float cla_inc; // Amount to bump next clause with. + float cla_decay; // INVERSE decay factor for clause activity: stores 1/decay. + + vecp* wlists; // + double* activity; // A heuristic measurement of the activity of a variable. + lbool* assigns; // Current values of variables. + int* orderpos; // Index in variable order. + clause** reasons; // + int* levels; // + lit* trail; + + clause* binary; // A temporary binary clause + lbool* tags; // + veci tagged; // (contains: var) + veci stack; // (contains: var) + + veci order; // Variable order. (heap) (contains: var) + veci trail_lim; // Separator indices for different decision levels in 'trail'. (contains: int) + veci model; // If problem is solved, this vector contains the model (contains: lbool). + + int root_level; // Level of first proper decision. + int simpdb_assigns;// Number of top-level assignments at last 'simplifyDB()'. + int simpdb_props; // Number of propagations before next 'simplifyDB()'. + double random_seed; + double progress_estimate; + int verbosity; // Verbosity level. 0=silent, 1=some progress report, 2=everything + + stats stats; + + sint64 nConfLimit; // external limit on the number of conflicts + sint64 nInsLimit; // external limit on the number of implications + + veci act_vars; // variables whose activity has changed + double* factors; // the activity factors + int nRestarts; // the number of local restarts + int nCalls; // the number of local restarts + int nCalls2; // the number of local restarts + + Sat_MmStep_t * pMem; + + int fSkipSimplify; // set to one to skip simplification of the clause database + + // clause store + void * pStore; + + // trace recording + FILE * pFile; + int nClauses; + int nRoots; +}; + +#endif diff --git a/abc70930/src/sat/bsat/satStore.c b/abc70930/src/sat/bsat/satStore.c new file mode 100644 index 00000000..7c1d7132 --- /dev/null +++ b/abc70930/src/sat/bsat/satStore.c @@ -0,0 +1,437 @@ +/**CFile**************************************************************** + + FileName [satStore.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT solver.] + + Synopsis [Records the trace of SAT solving in the CNF form.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: satStore.c,v 1.4 2005/09/16 22:55:03 casem Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include +#include "satStore.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Fetches memory.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Sto_ManMemoryFetch( Sto_Man_t * p, int nBytes ) +{ + char * pMem; + if ( p->pChunkLast == NULL || nBytes > p->nChunkSize - p->nChunkUsed ) + { + pMem = (char *)malloc( p->nChunkSize ); + *(char **)pMem = p->pChunkLast; + p->pChunkLast = pMem; + p->nChunkUsed = sizeof(char *); + } + pMem = p->pChunkLast + p->nChunkUsed; + p->nChunkUsed += nBytes; + return pMem; +} + +/**Function************************************************************* + + Synopsis [Frees memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sto_ManMemoryStop( Sto_Man_t * p ) +{ + char * pMem, * pNext; + if ( p->pChunkLast == NULL ) + return; + for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext ) + free( pMem ); + free( pMem ); +} + +/**Function************************************************************* + + Synopsis [Reports memory usage in bytes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sto_ManMemoryReport( Sto_Man_t * p ) +{ + int Total; + char * pMem, * pNext; + if ( p->pChunkLast == NULL ) + return 0; + Total = p->nChunkUsed; + for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext ) + Total += p->nChunkSize; + return Total; +} + + +/**Function************************************************************* + + Synopsis [Allocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sto_Man_t * Sto_ManAlloc() +{ + Sto_Man_t * p; + // allocate the manager + p = (Sto_Man_t *)malloc( sizeof(Sto_Man_t) ); + memset( p, 0, sizeof(Sto_Man_t) ); + // memory management + p->nChunkSize = (1<<16); // use 64K chunks + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sto_ManFree( Sto_Man_t * p ) +{ + Sto_ManMemoryStop( p ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Adds one clause to the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sto_ManAddClause( Sto_Man_t * p, lit * pBeg, lit * pEnd ) +{ + Sto_Cls_t * pClause; + lit Lit, * i, * j; + int nSize; + + // process the literals + if ( pBeg < pEnd ) + { + // insertion sort + for ( i = pBeg + 1; i < pEnd; i++ ) + { + Lit = *i; + for ( j = i; j > pBeg && *(j-1) > Lit; j-- ) + *j = *(j-1); + *j = Lit; + } + // make sure there is no duplicated variables + for ( i = pBeg + 1; i < pEnd; i++ ) + if ( lit_var(*(i-1)) == lit_var(*i) ) + { + printf( "The clause contains two literals of the same variable: %d and %d.\n", *(i-1), *i ); + return 0; + } + // check the largest var size + p->nVars = STO_MAX( p->nVars, lit_var(*(pEnd-1)) + 1 ); + } + + // get memory for the clause + nSize = sizeof(Sto_Cls_t) + sizeof(lit) * (pEnd - pBeg); + pClause = (Sto_Cls_t *)Sto_ManMemoryFetch( p, nSize ); + memset( pClause, 0, sizeof(Sto_Cls_t) ); + + // assign the clause + pClause->Id = p->nClauses++; + pClause->nLits = pEnd - pBeg; + memcpy( pClause->pLits, pBeg, sizeof(lit) * (pEnd - pBeg) ); + + // add the clause to the list + if ( p->pHead == NULL ) + p->pHead = pClause; + if ( p->pTail == NULL ) + p->pTail = pClause; + else + { + p->pTail->pNext = pClause; + p->pTail = pClause; + } + + // add the empty clause + if ( pClause->nLits == 0 ) + { + if ( p->pEmpty ) + { + printf( "More than one empty clause!\n" ); + return 0; + } + p->pEmpty = pClause; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Mark all clauses added so far as root clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sto_ManMarkRoots( Sto_Man_t * p ) +{ + Sto_Cls_t * pClause; + p->nRoots = 0; + Sto_ManForEachClause( p, pClause ) + { + pClause->fRoot = 1; + p->nRoots++; + } +} + +/**Function************************************************************* + + Synopsis [Mark all clauses added so far as clause of A.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sto_ManMarkClausesA( Sto_Man_t * p ) +{ + Sto_Cls_t * pClause; + p->nClausesA = 0; + Sto_ManForEachClause( p, pClause ) + { + pClause->fA = 1; + p->nClausesA++; + } +} + + +/**Function************************************************************* + + Synopsis [Writes the stored clauses into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sto_ManDumpClauses( Sto_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Sto_Cls_t * pClause; + int i; + // start the file + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + printf( "Error: Cannot open output file (%s).\n", pFileName ); + return; + } + // write the data + fprintf( pFile, "p %d %d %d %d\n", p->nVars, p->nClauses, p->nRoots, p->nClausesA ); + Sto_ManForEachClause( p, pClause ) + { + for ( i = 0; i < (int)pClause->nLits; i++ ) + fprintf( pFile, " %d", lit_print(pClause->pLits[i]) ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, " 0\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Reads one literal from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sto_ManLoadNumber( FILE * pFile, int * pNumber ) +{ + int Char, Number = 0, Sign = 0; + // skip space-like chars + do { + Char = fgetc( pFile ); + if ( Char == EOF ) + return 0; + } while ( Char == ' ' || Char == '\t' || Char == '\r' || Char == '\n' ); + // read the literal + while ( 1 ) + { + // get the next character + Char = fgetc( pFile ); + if ( Char == ' ' || Char == '\t' || Char == '\r' || Char == '\n' ) + break; + // check that the char is a digit + if ( (Char < '0' || Char > '9') && Char != '-' ) + { + printf( "Error: Wrong char (%c) in the input file.\n", Char ); + return 0; + } + // check if this is a minus + if ( Char == '-' ) + Sign = 1; + else + Number = 10 * Number + Char; + } + // return the number + *pNumber = Sign? -Number : Number; + return 1; +} + +/**Function************************************************************* + + Synopsis [Reads CNF from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sto_Man_t * Sto_ManLoadClauses( char * pFileName ) +{ + FILE * pFile; + Sto_Man_t * p; + Sto_Cls_t * pClause; + char pBuffer[1024]; + int nLits, nLitsAlloc, Counter, Number; + lit * pLits; + + // start the file + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Error: Cannot open input file (%s).\n", pFileName ); + return NULL; + } + + // create the manager + p = Sto_ManAlloc(); + + // alloc the array of literals + nLitsAlloc = 1024; + pLits = (lit *)malloc( sizeof(lit) * nLitsAlloc ); + + // read file header + p->nVars = p->nClauses = p->nRoots = p->nClausesA = 0; + while ( fgets( pBuffer, 1024, pFile ) ) + { + if ( pBuffer[0] == 'c' ) + continue; + if ( pBuffer[0] == 'p' ) + { + sscanf( pBuffer + 1, "%d %d %d %d", p->nVars, p->nClauses, p->nRoots, p->nClausesA ); + break; + } + printf( "Warning: Skipping line: \"%s\"\n", pBuffer ); + } + + // read the clauses + nLits = 0; + while ( Sto_ManLoadNumber(pFile, &Number) ) + { + if ( Number == 0 ) + { + int RetValue; + RetValue = Sto_ManAddClause( p, pLits, pLits + nLits ); + assert( RetValue ); + nLits = 0; + continue; + } + if ( nLits == nLitsAlloc ) + { + nLitsAlloc *= 2; + pLits = (lit *)realloc( pLits, sizeof(lit) * nLitsAlloc ); + } + pLits[ nLits++ ] = lit_read(Number); + } + if ( nLits > 0 ) + printf( "Error: The last clause was not saved.\n" ); + + // count clauses + Counter = 0; + Sto_ManForEachClause( p, pClause ) + Counter++; + + // check the number of clauses + if ( p->nClauses != Counter ) + { + printf( "Error: The actual number of clauses (%d) is different than declared (%d).\n", Counter, p->nClauses ); + Sto_ManFree( p ); + return NULL; + } + + free( pLits ); + fclose( pFile ); + return p; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/bsat/satStore.h b/abc70930/src/sat/bsat/satStore.h new file mode 100644 index 00000000..346b59df --- /dev/null +++ b/abc70930/src/sat/bsat/satStore.h @@ -0,0 +1,137 @@ +/**CFile**************************************************************** + + FileName [pr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Proof recording.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: pr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __PR_H__ +#define __PR_H__ + +/* + The trace of SAT solving contains the original clause of the problem + along with the learned clauses derived during SAT solving. + The first line of the resulting file contains 3 numbers instead of 2: + c +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +#ifndef PRT +#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) +#endif + +#define STO_MAX(a,b) ((a) > (b) ? (a) : (b)) + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef unsigned lit; + +typedef struct Sto_Cls_t_ Sto_Cls_t; +struct Sto_Cls_t_ +{ + Sto_Cls_t * pNext; // the next clause + Sto_Cls_t * pNext0; // the next 0-watch + Sto_Cls_t * pNext1; // the next 0-watch + int Id; // the clause ID + unsigned fA : 1; // belongs to A + unsigned fRoot : 1; // original clause + unsigned fVisit : 1; // visited clause + unsigned nLits : 24; // the number of literals + lit pLits[0]; // literals of this clause +}; + +typedef struct Sto_Man_t_ Sto_Man_t; +struct Sto_Man_t_ +{ + // general data + int nVars; // the number of variables + int nRoots; // the number of root clauses + int nClauses; // the number of all clauses + int nClausesA; // the number of clauses of A + Sto_Cls_t * pHead; // the head clause + Sto_Cls_t * pTail; // the tail clause + Sto_Cls_t * pEmpty; // the empty clause + // memory management + int nChunkSize; // the number of bytes in a chunk + int nChunkUsed; // the number of bytes used in the last chunk + char * pChunkLast; // the last memory chunk +}; + +// variable/literal conversions (taken from MiniSat) +static inline lit toLit (int v) { return v + v; } +static inline lit toLitCond(int v, int c) { return v + v + (c != 0); } +static inline lit lit_neg (lit l) { return l ^ 1; } +static inline int lit_var (lit l) { return l >> 1; } +static inline int lit_sign (lit l) { return l & 1; } +static inline int lit_print(lit l) { return lit_sign(l)? -lit_var(l)-1 : lit_var(l)+1; } +static inline lit lit_read (int s) { return s > 0 ? toLit(s-1) : lit_neg(toLit(-s-1)); } +static inline int lit_check(lit l, int n) { return l >= 0 && lit_var(l) < n; } + +// iterators through the clauses +#define Sto_ManForEachClause( p, pCls ) for( pCls = p->pHead; pCls; pCls = pCls->pNext ) +#define Sto_ManForEachClauseRoot( p, pCls ) for( pCls = p->pHead; pCls && pCls->fRoot; pCls = pCls->pNext ) + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== satStore.c ==========================================================*/ +extern Sto_Man_t * Sto_ManAlloc(); +extern void Sto_ManFree( Sto_Man_t * p ); +extern int Sto_ManAddClause( Sto_Man_t * p, lit * pBeg, lit * pEnd ); +extern int Sto_ManMemoryReport( Sto_Man_t * p ); +extern void Sto_ManMarkRoots( Sto_Man_t * p ); +extern void Sto_ManMarkClausesA( Sto_Man_t * p ); +extern void Sto_ManDumpClauses( Sto_Man_t * p, char * pFileName ); +extern Sto_Man_t * Sto_ManLoadClauses( char * pFileName ); + +/*=== satInter.c ==========================================================*/ +typedef struct Int_Man_t_ Int_Man_t; +extern Int_Man_t * Int_ManAlloc( int nVarsAlloc ); +extern void Int_ManFree( Int_Man_t * p ); +extern int Int_ManInterpolate( Int_Man_t * p, Sto_Man_t * pCnf, int fVerbose, unsigned ** ppResult ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/sat/bsat/satTrace.c b/abc70930/src/sat/bsat/satTrace.c new file mode 100644 index 00000000..111e8dfb --- /dev/null +++ b/abc70930/src/sat/bsat/satTrace.c @@ -0,0 +1,109 @@ +/**CFile**************************************************************** + + FileName [satTrace.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [SAT sat_solver.] + + Synopsis [Records the trace of SAT solving in the CNF form.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: satTrace.c,v 1.4 2005/09/16 22:55:03 casem Exp $] + +***********************************************************************/ + +#include +#include +#include "satSolver.h" + +/* + The trace of SAT solving contains the original clause of the problem + along with the learned clauses derived during SAT solving. + The first line of the resulting file contains 3 numbers instead of 2: + c +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start the trace recording.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_SolverTraceStart( sat_solver * pSat, char * pName ) +{ + assert( pSat->pFile == NULL ); + pSat->pFile = fopen( pName, "w" ); + fprintf( pSat->pFile, " \n" ); + pSat->nClauses = 0; + pSat->nRoots = 0; +} + +/**Function************************************************************* + + Synopsis [Stops the trace recording.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_SolverTraceStop( sat_solver * pSat ) +{ + if ( pSat->pFile == NULL ) + return; + rewind( pSat->pFile ); + fprintf( pSat->pFile, "p %d %d %d", sat_solver_nvars(pSat), pSat->nClauses, pSat->nRoots ); + fclose( pSat->pFile ); + pSat->pFile = NULL; +} + + +/**Function************************************************************* + + Synopsis [Writes one clause into the trace file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_SolverTraceWrite( sat_solver * pSat, int * pBeg, int * pEnd, int fRoot ) +{ + if ( pSat->pFile == NULL ) + return; + pSat->nClauses++; + pSat->nRoots += fRoot; + for ( ; pBeg < pEnd ; pBeg++ ) + fprintf( pSat->pFile, " %d", lit_print(*pBeg) ); + fprintf( pSat->pFile, " 0\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/bsat/satUtil.c b/abc70930/src/sat/bsat/satUtil.c new file mode 100644 index 00000000..62f3c208 --- /dev/null +++ b/abc70930/src/sat/bsat/satUtil.c @@ -0,0 +1,234 @@ +/**CFile**************************************************************** + + FileName [satUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [C-language MiniSat solver.] + + Synopsis [Additional SAT solver procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: satUtil.c,v 1.4 2005/09/16 22:55:03 casem Exp $] + +***********************************************************************/ + +#include +#include +#include "satSolver.h" +#include "extra.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct clause_t +{ + int size_learnt; + lit lits[0]; +}; + +static inline int clause_size( clause* c ) { return c->size_learnt >> 1; } +static inline lit* clause_begin( clause* c ) { return c->lits; } + +static void Sat_SolverClauseWriteDimacs( FILE * pFile, clause * pC, bool fIncrement ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Write the clauses in the solver into a file in DIMACS format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_SolverWriteDimacs( sat_solver * p, char * pFileName, lit* assumptionsBegin, lit* assumptionsEnd, int incrementVars ) +{ + FILE * pFile; + void ** pClauses; + int nClauses, i; + + // count the number of clauses + nClauses = p->clauses.size + p->learnts.size; + for ( i = 0; i < p->size; i++ ) + if ( p->levels[i] == 0 && p->assigns[i] != l_Undef ) + nClauses++; + + // start the file + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Sat_SolverWriteDimacs(): Cannot open the ouput file.\n" ); + return; + } + fprintf( pFile, "c CNF generated by ABC on %s\n", Extra_TimeStamp() ); + fprintf( pFile, "p cnf %d %d\n", p->size, nClauses ); + + // write the original clauses + nClauses = p->clauses.size; + pClauses = p->clauses.ptr; + for ( i = 0; i < nClauses; i++ ) + Sat_SolverClauseWriteDimacs( pFile, pClauses[i], incrementVars ); + + // write the learned clauses + nClauses = p->learnts.size; + pClauses = p->learnts.ptr; + for ( i = 0; i < nClauses; i++ ) + Sat_SolverClauseWriteDimacs( pFile, pClauses[i], incrementVars ); + + // write zero-level assertions + for ( i = 0; i < p->size; i++ ) + if ( p->levels[i] == 0 && p->assigns[i] != l_Undef ) + fprintf( pFile, "%s%d%s\n", + (p->assigns[i] == l_False)? "-": "", + i + (int)(incrementVars>0), + (incrementVars) ? " 0" : ""); + + // write the assumptions + if (assumptionsBegin) { + for (; assumptionsBegin != assumptionsEnd; assumptionsBegin++) { + fprintf( pFile, "%s%d%s\n", + lit_sign(*assumptionsBegin)? "-": "", + lit_var(*assumptionsBegin) + (int)(incrementVars>0), + (incrementVars) ? " 0" : ""); + } + } + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes the given clause in a file in DIMACS format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_SolverClauseWriteDimacs( FILE * pFile, clause * pC, bool fIncrement ) +{ + lit * pLits = clause_begin(pC); + int nLits = clause_size(pC); + int i; + + for ( i = 0; i < nLits; i++ ) + fprintf( pFile, "%s%d ", (lit_sign(pLits[i])? "-": ""), lit_var(pLits[i]) + (int)(fIncrement>0) ); + if ( fIncrement ) + fprintf( pFile, "0" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the given clause in a file in DIMACS format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_SolverPrintStats( FILE * pFile, sat_solver * p ) +{ +// printf( "calls : %8d (%d)\n", (int)p->nCalls, (int)p->nCalls2 ); + printf( "starts : %8d\n", (int)p->stats.starts ); + printf( "conflicts : %8d\n", (int)p->stats.conflicts ); + printf( "decisions : %8d\n", (int)p->stats.decisions ); + printf( "propagations : %8d\n", (int)p->stats.propagations ); + printf( "inspects : %8d\n", (int)p->stats.inspects ); +// printf( "inspects2 : %8d\n", (int)p->stats.inspects2 ); +} + +/**Function************************************************************* + + Synopsis [Returns a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Sat_SolverGetModel( sat_solver * p, int * pVars, int nVars ) +{ + int * pModel; + int i; + pModel = ALLOC( int, nVars ); + for ( i = 0; i < nVars; i++ ) + { + assert( pVars[i] >= 0 && pVars[i] < p->size ); + pModel[i] = (int)(p->model.ptr[pVars[i]] == l_True); + } + return pModel; +} + +/**Function************************************************************* + + Synopsis [Duplicates all clauses, complements unit clause of the given var.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sat_SolverDoubleClauses( sat_solver * p, int iVar ) +{ + clause * pClause; + lit Lit, * pLits; + int RetValue, nClauses, nVarsOld, nLitsOld, nLits, c, v; + // get the number of variables + nVarsOld = p->size; + nLitsOld = 2 * p->size; + // extend the solver to depend on two sets of variables + sat_solver_setnvars( p, 2 * p->size ); + // duplicate implications + for ( v = 0; v < nVarsOld; v++ ) + if ( p->assigns[v] != l_Undef ) + { + Lit = nLitsOld + toLitCond( v, p->assigns[v]==l_False ); + if ( v == iVar ) + Lit = lit_neg(Lit); + RetValue = sat_solver_addclause( p, &Lit, &Lit + 1 ); + assert( RetValue ); + } + // duplicate clauses + nClauses = vecp_size(&p->clauses); + for ( c = 0; c < nClauses; c++ ) + { + pClause = p->clauses.ptr[c]; + nLits = clause_size(pClause); + pLits = clause_begin(pClause); + for ( v = 0; v < nLits; v++ ) + pLits[v] += nLitsOld; + RetValue = sat_solver_addclause( p, pLits, pLits + nLits ); + assert( RetValue ); + for ( v = 0; v < nLits; v++ ) + pLits[v] -= nLitsOld; + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/bsat/satVec.h b/abc70930/src/sat/bsat/satVec.h new file mode 100644 index 00000000..d7fce5c0 --- /dev/null +++ b/abc70930/src/sat/bsat/satVec.h @@ -0,0 +1,83 @@ +/************************************************************************************************** +MiniSat -- Copyright (c) 2005, Niklas Sorensson +http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and +associated documentation files (the "Software"), to deal in the Software without restriction, +including without limitation the rights to use, copy, modify, merge, publish, distribute, +sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT +NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT +OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +**************************************************************************************************/ +// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko + +#ifndef satVec_h +#define satVec_h + +#include + +// vector of 32-bit intergers (added for 64-bit portability) +struct veci_t { + int size; + int cap; + int* ptr; +}; +typedef struct veci_t veci; + +static inline void veci_new (veci* v) { + v->size = 0; + v->cap = 4; + v->ptr = (int*)malloc(sizeof(int)*v->cap); +} + +static inline void veci_delete (veci* v) { free(v->ptr); } +static inline int* veci_begin (veci* v) { return v->ptr; } +static inline int veci_size (veci* v) { return v->size; } +static inline void veci_resize (veci* v, int k) { v->size = k; } // only safe to shrink !! +static inline void veci_push (veci* v, int e) +{ + if (v->size == v->cap) { + int newsize = v->cap * 2;//+1; + v->ptr = (int*)realloc(v->ptr,sizeof(int)*newsize); + v->cap = newsize; } + v->ptr[v->size++] = e; +} + + +// vector of 32- or 64-bit pointers +struct vecp_t { + int size; + int cap; + void** ptr; +}; +typedef struct vecp_t vecp; + +static inline void vecp_new (vecp* v) { + v->size = 0; + v->cap = 4; + v->ptr = (void**)malloc(sizeof(void*)*v->cap); +} + +static inline void vecp_delete (vecp* v) { free(v->ptr); } +static inline void** vecp_begin (vecp* v) { return v->ptr; } +static inline int vecp_size (vecp* v) { return v->size; } +static inline void vecp_resize (vecp* v, int k) { v->size = k; } // only safe to shrink !! +static inline void vecp_push (vecp* v, void* e) +{ + if (v->size == v->cap) { + int newsize = v->cap * 2;//+1; + v->ptr = (void**)realloc(v->ptr,sizeof(void*)*newsize); + v->cap = newsize; } + v->ptr[v->size++] = e; +} + + +#endif diff --git a/abc70930/src/sat/csat/csat_apis.c b/abc70930/src/sat/csat/csat_apis.c new file mode 100644 index 00000000..5872f5bc --- /dev/null +++ b/abc70930/src/sat/csat/csat_apis.c @@ -0,0 +1,769 @@ +/**CFile**************************************************************** + + FileName [csat_apis.h] + + PackageName [Interface to CSAT.] + + Synopsis [APIs, enums, and data structures expected from the use of CSAT.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 28, 2005] + + Revision [$Id: csat_apis.h,v 1.00 2005/08/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "fraig.h" +#include "csat_apis.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_DEFAULT_CONF_LIMIT 0 // limit on conflicts +#define ABC_DEFAULT_IMP_LIMIT 0 // limit on implications + + +struct ABC_ManagerStruct_t +{ + // information about the problem + stmm_table * tName2Node; // the hash table mapping names to nodes + stmm_table * tNode2Name; // the hash table mapping nodes to names + Abc_Ntk_t * pNtk; // the starting ABC network + Abc_Ntk_t * pTarget; // the AIG representing the target + char * pDumpFileName; // the name of the file to dump the target network + Extra_MmFlex_t * pMmNames; // memory manager for signal names + // solving parameters + int mode; // 0 = resource-aware integration; 1 = brute-force SAT + Prove_Params_t Params; // integrated CEC parameters + // information about the target + int nog; // the numbers of gates in the target + Vec_Ptr_t * vNodes; // the gates in the target + Vec_Int_t * vValues; // the values of gate's outputs in the target + // solution + CSAT_Target_ResultT * pResult; // the result of solving the target +}; + +static CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars ); +static char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode ); + +// procedures to start and stop the ABC framework +extern void Abc_Start(); +extern void Abc_Stop(); + +// some external procedures +extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a new manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +ABC_Manager ABC_InitManager() +{ + ABC_Manager_t * mng; + Abc_Start(); + mng = ALLOC( ABC_Manager_t, 1 ); + memset( mng, 0, sizeof(ABC_Manager_t) ); + mng->pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + mng->pNtk->pName = Extra_UtilStrsav("csat_network"); + mng->tName2Node = stmm_init_table(strcmp, stmm_strhash); + mng->tNode2Name = stmm_init_table(stmm_ptrcmp, stmm_ptrhash); + mng->pMmNames = Extra_MmFlexStart(); + mng->vNodes = Vec_PtrAlloc( 100 ); + mng->vValues = Vec_IntAlloc( 100 ); + mng->mode = 0; // set "resource-aware integration" as the default mode + // set default parameters for CEC + Prove_ParamsSetDefault( &mng->Params ); + // set infinite resource limit for the final mitering +// mng->Params.nMiteringLimitLast = ABC_INFINITY; + return mng; +} + +/**Function************************************************************* + + Synopsis [Deletes the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_ReleaseManager( ABC_Manager mng ) +{ + CSAT_Target_ResultT * p_res = ABC_Get_Target_Result( mng,0 ); + ABC_TargetResFree(p_res); + if ( mng->tNode2Name ) stmm_free_table( mng->tNode2Name ); + if ( mng->tName2Node ) stmm_free_table( mng->tName2Node ); + if ( mng->pMmNames ) Extra_MmFlexStop( mng->pMmNames ); + if ( mng->pNtk ) Abc_NtkDelete( mng->pNtk ); + if ( mng->pTarget ) Abc_NtkDelete( mng->pTarget ); + if ( mng->vNodes ) Vec_PtrFree( mng->vNodes ); + if ( mng->vValues ) Vec_IntFree( mng->vValues ); + FREE( mng->pDumpFileName ); + free( mng ); + Abc_Stop(); +} + +/**Function************************************************************* + + Synopsis [Sets solver options for learning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_SetSolveOption( ABC_Manager mng, enum CSAT_OptionT option ) +{ +} + +/**Function************************************************************* + + Synopsis [Sets solving mode by brute-force SAT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_UseOnlyCoreSatSolver( ABC_Manager mng ) +{ + mng->mode = 1; // switch to "brute-force SAT" as the solving option +} + +/**Function************************************************************* + + Synopsis [Adds a gate to the circuit.] + + Description [The meaning of the parameters are: + type: the type of the gate to be added + name: the name of the gate to be added, name should be unique in a circuit. + nofi: number of fanins of the gate to be added; + fanins: the name array of fanins of the gate to be added.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, char ** fanins, int dc_attr ) +{ + Abc_Obj_t * pObj, * pFanin; + char * pSop, * pNewName; + int i; + + // save the name in the local memory manager + pNewName = Extra_MmFlexEntryFetch( mng->pMmNames, strlen(name) + 1 ); + strcpy( pNewName, name ); + name = pNewName; + + // consider different cases, create the node, and map the node into the name + switch( type ) + { + case CSAT_BPI: + case CSAT_BPPI: + if ( nofi != 0 ) + { printf( "ABC_AddGate: The PI/PPI gate \"%s\" has fanins.\n", name ); return 0; } + // create the PI + pObj = Abc_NtkCreatePi( mng->pNtk ); + stmm_insert( mng->tNode2Name, (char *)pObj, name ); + break; + case CSAT_CONST: + case CSAT_BAND: + case CSAT_BNAND: + case CSAT_BOR: + case CSAT_BNOR: + case CSAT_BXOR: + case CSAT_BXNOR: + case CSAT_BINV: + case CSAT_BBUF: + // create the node + pObj = Abc_NtkCreateNode( mng->pNtk ); + // create the fanins + for ( i = 0; i < nofi; i++ ) + { + if ( !stmm_lookup( mng->tName2Node, fanins[i], (char **)&pFanin ) ) + { printf( "ABC_AddGate: The fanin gate \"%s\" is not in the network.\n", fanins[i] ); return 0; } + Abc_ObjAddFanin( pObj, pFanin ); + } + // create the node function + switch( type ) + { + case CSAT_CONST: + if ( nofi != 0 ) + { printf( "ABC_AddGate: The constant gate \"%s\" has fanins.\n", name ); return 0; } + pSop = Abc_SopCreateConst1( mng->pNtk->pManFunc ); + break; + case CSAT_BAND: + if ( nofi < 1 ) + { printf( "ABC_AddGate: The AND gate \"%s\" no fanins.\n", name ); return 0; } + pSop = Abc_SopCreateAnd( mng->pNtk->pManFunc, nofi, NULL ); + break; + case CSAT_BNAND: + if ( nofi < 1 ) + { printf( "ABC_AddGate: The NAND gate \"%s\" no fanins.\n", name ); return 0; } + pSop = Abc_SopCreateNand( mng->pNtk->pManFunc, nofi ); + break; + case CSAT_BOR: + if ( nofi < 1 ) + { printf( "ABC_AddGate: The OR gate \"%s\" no fanins.\n", name ); return 0; } + pSop = Abc_SopCreateOr( mng->pNtk->pManFunc, nofi, NULL ); + break; + case CSAT_BNOR: + if ( nofi < 1 ) + { printf( "ABC_AddGate: The NOR gate \"%s\" no fanins.\n", name ); return 0; } + pSop = Abc_SopCreateNor( mng->pNtk->pManFunc, nofi ); + break; + case CSAT_BXOR: + if ( nofi < 1 ) + { printf( "ABC_AddGate: The XOR gate \"%s\" no fanins.\n", name ); return 0; } + if ( nofi > 2 ) + { printf( "ABC_AddGate: The XOR gate \"%s\" has more than two fanins.\n", name ); return 0; } + pSop = Abc_SopCreateXor( mng->pNtk->pManFunc, nofi ); + break; + case CSAT_BXNOR: + if ( nofi < 1 ) + { printf( "ABC_AddGate: The XNOR gate \"%s\" no fanins.\n", name ); return 0; } + if ( nofi > 2 ) + { printf( "ABC_AddGate: The XNOR gate \"%s\" has more than two fanins.\n", name ); return 0; } + pSop = Abc_SopCreateNxor( mng->pNtk->pManFunc, nofi ); + break; + case CSAT_BINV: + if ( nofi != 1 ) + { printf( "ABC_AddGate: The inverter gate \"%s\" does not have exactly one fanin.\n", name ); return 0; } + pSop = Abc_SopCreateInv( mng->pNtk->pManFunc ); + break; + case CSAT_BBUF: + if ( nofi != 1 ) + { printf( "ABC_AddGate: The buffer gate \"%s\" does not have exactly one fanin.\n", name ); return 0; } + pSop = Abc_SopCreateBuf( mng->pNtk->pManFunc ); + break; + default : + break; + } + Abc_ObjSetData( pObj, pSop ); + break; + case CSAT_BPPO: + case CSAT_BPO: + if ( nofi != 1 ) + { printf( "ABC_AddGate: The PO/PPO gate \"%s\" does not have exactly one fanin.\n", name ); return 0; } + // create the PO + pObj = Abc_NtkCreatePo( mng->pNtk ); + stmm_insert( mng->tNode2Name, (char *)pObj, name ); + // connect to the PO fanin + if ( !stmm_lookup( mng->tName2Node, fanins[0], (char **)&pFanin ) ) + { printf( "ABC_AddGate: The fanin gate \"%s\" is not in the network.\n", fanins[0] ); return 0; } + Abc_ObjAddFanin( pObj, pFanin ); + break; + default: + printf( "ABC_AddGate: Unknown gate type.\n" ); + break; + } + + // map the name into the node + if ( stmm_insert( mng->tName2Node, name, (char *)pObj ) ) + { printf( "ABC_AddGate: The same gate \"%s\" is added twice.\n", name ); return 0; } + return 1; +} + +/**Function************************************************************* + + Synopsis [This procedure also finalizes construction of the ABC network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_Network_Finalize( ABC_Manager mng ) +{ + Abc_Ntk_t * pNtk = mng->pNtk; + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, ABC_GetNodeName(mng, pObj), NULL ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, ABC_GetNodeName(mng, pObj), NULL ); + assert( Abc_NtkLatchNum(pNtk) == 0 ); +} + +/**Function************************************************************* + + Synopsis [Checks integraty of the manager.] + + Description [Checks if there are gates that are not used by any primary output. + If no such gates exist, return 1 else return 0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int ABC_Check_Integrity( ABC_Manager mng ) +{ + Abc_Ntk_t * pNtk = mng->pNtk; + Abc_Obj_t * pObj; + int i; + + // check that there are no dangling nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( i == 0 ) + continue; + if ( Abc_ObjFanoutNum(pObj) == 0 ) + { +// printf( "ABC_Check_Integrity: The network has dangling nodes.\n" ); + return 0; + } + } + + // make sure everything is okay with the network structure + if ( !Abc_NtkDoCheck( pNtk ) ) + { + printf( "ABC_Check_Integrity: The internal network check has failed.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Sets time limit for solving a target.] + + Description [Runtime: time limit (in second).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_SetTimeLimit( ABC_Manager mng, int runtime ) +{ +// printf( "ABC_SetTimeLimit: The resource limit is not implemented (warning).\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_SetLearnLimit( ABC_Manager mng, int num ) +{ +// printf( "ABC_SetLearnLimit: The resource limit is not implemented (warning).\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num ) +{ +// printf( "ABC_SetLearnBacktrackLimit: The resource limit is not implemented (warning).\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_SetSolveBacktrackLimit( ABC_Manager mng, int num ) +{ + mng->Params.nMiteringLimitLast = num; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_SetSolveImplicationLimit( ABC_Manager mng, int num ) +{ +// printf( "ABC_SetSolveImplicationLimit: The resource limit is not implemented (warning).\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_SetTotalBacktrackLimit( ABC_Manager mng, uint64 num ) +{ + mng->Params.nTotalBacktrackLimit = num; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_SetTotalInspectLimit( ABC_Manager mng, uint64 num ) +{ + mng->Params.nTotalInspectLimit = num; +} +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +uint64 ABC_GetTotalBacktracksMade( ABC_Manager mng ) +{ + return mng->Params.nTotalBacktracksMade; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +uint64 ABC_GetTotalInspectsMade( ABC_Manager mng ) +{ + return mng->Params.nTotalInspectsMade; +} + +/**Function************************************************************* + + Synopsis [Sets the file name to dump the structurally hashed network used for solving.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_EnableDump( ABC_Manager mng, char * dump_file ) +{ + FREE( mng->pDumpFileName ); + mng->pDumpFileName = Extra_UtilStrsav( dump_file ); +} + +/**Function************************************************************* + + Synopsis [Adds a new target to the manager.] + + Description [The meaning of the parameters are: + nog: number of gates that are in the targets, + names: name array of gates, + values: value array of the corresponding gates given in "names" to be solved. + The relation of them is AND.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int ABC_AddTarget( ABC_Manager mng, int nog, char ** names, int * values ) +{ + Abc_Obj_t * pObj; + int i; + if ( nog < 1 ) + { printf( "ABC_AddTarget: The target has no gates.\n" ); return 0; } + // clear storage for the target + mng->nog = 0; + Vec_PtrClear( mng->vNodes ); + Vec_IntClear( mng->vValues ); + // save the target + for ( i = 0; i < nog; i++ ) + { + if ( !stmm_lookup( mng->tName2Node, names[i], (char **)&pObj ) ) + { printf( "ABC_AddTarget: The target gate \"%s\" is not in the network.\n", names[i] ); return 0; } + Vec_PtrPush( mng->vNodes, pObj ); + if ( values[i] < 0 || values[i] > 1 ) + { printf( "ABC_AddTarget: The value of gate \"%s\" is not 0 or 1.\n", names[i] ); return 0; } + Vec_IntPush( mng->vValues, values[i] ); + } + mng->nog = nog; + return 1; +} + +/**Function************************************************************* + + Synopsis [Initialize the solver internal data structure.] + + Description [Prepares the solver to work on one specific target + set by calling ABC_AddTarget before.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_SolveInit( ABC_Manager mng ) +{ + // check if the target is available + assert( mng->nog == Vec_PtrSize(mng->vNodes) ); + if ( mng->nog == 0 ) + { printf( "ABC_SolveInit: Target is not specified by ABC_AddTarget().\n" ); return; } + + // free the previous target network if present + if ( mng->pTarget ) Abc_NtkDelete( mng->pTarget ); + + // set the new target network +// mng->pTarget = Abc_NtkCreateTarget( mng->pNtk, mng->vNodes, mng->vValues ); + mng->pTarget = Abc_NtkStrash( mng->pNtk, 0, 1, 0 ); +} + +/**Function************************************************************* + + Synopsis [Currently not implemented.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_AnalyzeTargets( ABC_Manager mng ) +{ +} + +/**Function************************************************************* + + Synopsis [Solves the targets added by ABC_AddTarget().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +enum CSAT_StatusT ABC_Solve( ABC_Manager mng ) +{ + Prove_Params_t * pParams = &mng->Params; + int RetValue, i; + + // check if the target network is available + if ( mng->pTarget == NULL ) + { printf( "ABC_Solve: Target network is not derived by ABC_SolveInit().\n" ); return UNDETERMINED; } + + // try to prove the miter using a number of techniques + if ( mng->mode ) + RetValue = Abc_NtkMiterSat( mng->pTarget, (sint64)pParams->nMiteringLimitLast, (sint64)0, 0, NULL, NULL ); + else +// RetValue = Abc_NtkMiterProve( &mng->pTarget, pParams ); // old CEC engine + RetValue = Abc_NtkIvyProve( &mng->pTarget, pParams ); // new CEC engine + + // analyze the result + mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) ); + if ( RetValue == -1 ) + mng->pResult->status = UNDETERMINED; + else if ( RetValue == 1 ) + mng->pResult->status = UNSATISFIABLE; + else if ( RetValue == 0 ) + { + mng->pResult->status = SATISFIABLE; + // create the array of PI names and values + for ( i = 0; i < mng->pResult->no_sig; i++ ) + { + mng->pResult->names[i] = Extra_UtilStrsav( ABC_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)) ); + mng->pResult->values[i] = mng->pTarget->pModel[i]; + } + FREE( mng->pTarget->pModel ); + } + else assert( 0 ); + + // delete the target + Abc_NtkDelete( mng->pTarget ); + mng->pTarget = NULL; + // return the status + return mng->pResult->status; +} + +/**Function************************************************************* + + Synopsis [Gets the solve status of a target.] + + Description [TargetID: the target id returned by ABC_AddTarget().] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +CSAT_Target_ResultT * ABC_Get_Target_Result( ABC_Manager mng, int TargetID ) +{ + return mng->pResult; +} + +/**Function************************************************************* + + Synopsis [Dumps the original network into the BENCH file.] + + Description [This procedure should be modified to dump the target.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_Dump_Bench_File( ABC_Manager mng ) +{ + Abc_Ntk_t * pNtkTemp, * pNtkAig; + char * pFileName; + + // derive the netlist + pNtkAig = Abc_NtkStrash( mng->pNtk, 0, 0, 0 ); + pNtkTemp = Abc_NtkToNetlistBench( pNtkAig ); + Abc_NtkDelete( pNtkAig ); + if ( pNtkTemp == NULL ) + { printf( "ABC_Dump_Bench_File: Dumping BENCH has failed.\n" ); return; } + pFileName = mng->pDumpFileName? mng->pDumpFileName: "abc_test.bench"; + Io_WriteBench( pNtkTemp, pFileName ); + Abc_NtkDelete( pNtkTemp ); +} + + + +/**Function************************************************************* + + Synopsis [Allocates the target result.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars ) +{ + CSAT_Target_ResultT * p; + p = ALLOC( CSAT_Target_ResultT, 1 ); + memset( p, 0, sizeof(CSAT_Target_ResultT) ); + p->no_sig = nVars; + p->names = ALLOC( char *, nVars ); + p->values = ALLOC( int, nVars ); + memset( p->names, 0, sizeof(char *) * nVars ); + memset( p->values, 0, sizeof(int) * nVars ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the target result.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void ABC_TargetResFree( CSAT_Target_ResultT * p ) +{ + if ( p == NULL ) + return; + if( p->names ) + { + int i = 0; + for ( i = 0; i < p->no_sig; i++ ) + { + FREE(p->names[i]); + } + } + FREE( p->names ); + FREE( p->values ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Dumps the target AIG into the BENCH file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode ) +{ + char * pName = NULL; + if ( !stmm_lookup( mng->tNode2Name, (char *)pNode, (char **)&pName ) ) + { + assert( 0 ); + } + return pName; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/csat/csat_apis.h b/abc70930/src/sat/csat/csat_apis.h new file mode 100644 index 00000000..b80eddbf --- /dev/null +++ b/abc70930/src/sat/csat/csat_apis.h @@ -0,0 +1,222 @@ +/**CFile**************************************************************** + + FileName [csat_apis.h] + + PackageName [Interface to CSAT.] + + Synopsis [APIs, enums, and data structures expected from the use of CSAT.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 28, 2005] + + Revision [$Id: csat_apis.h,v 1.5 2005/12/30 10:54:40 rmukherj Exp $] + +***********************************************************************/ + +#ifndef __ABC_APIS_H__ +#define __ABC_APIS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +typedef struct ABC_ManagerStruct_t ABC_Manager_t; +typedef struct ABC_ManagerStruct_t * ABC_Manager; + + +// GateType defines the gate type that can be added to circuit by +// ABC_AddGate(); +#ifndef _ABC_GATE_TYPE_ +#define _ABC_GATE_TYPE_ +enum GateType +{ + CSAT_CONST = 0, // constant gate + CSAT_BPI, // boolean PI + CSAT_BPPI, // bit level PSEUDO PRIMARY INPUT + CSAT_BAND, // bit level AND + CSAT_BNAND, // bit level NAND + CSAT_BOR, // bit level OR + CSAT_BNOR, // bit level NOR + CSAT_BXOR, // bit level XOR + CSAT_BXNOR, // bit level XNOR + CSAT_BINV, // bit level INVERTER + CSAT_BBUF, // bit level BUFFER + CSAT_BMUX, // bit level MUX --not supported + CSAT_BDFF, // bit level D-type FF + CSAT_BSDFF, // bit level scan FF --not supported + CSAT_BTRIH, // bit level TRISTATE gate with active high control --not supported + CSAT_BTRIL, // bit level TRISTATE gate with active low control --not supported + CSAT_BBUS, // bit level BUS --not supported + CSAT_BPPO, // bit level PSEUDO PRIMARY OUTPUT + CSAT_BPO, // boolean PO + CSAT_BCNF, // boolean constraint + CSAT_BDC, // boolean don't care gate (2 input) +}; +#endif + + +//CSAT_StatusT defines the return value by ABC_Solve(); +#ifndef _ABC_STATUS_ +#define _ABC_STATUS_ +enum CSAT_StatusT +{ + UNDETERMINED = 0, + UNSATISFIABLE, + SATISFIABLE, + TIME_OUT, + FRAME_OUT, + NO_TARGET, + ABORTED, + SEQ_SATISFIABLE +}; +#endif + + +// to identify who called the CSAT solver +#ifndef _ABC_CALLER_ +#define _ABC_CALLER_ +enum CSAT_CallerT +{ + BLS = 0, + SATORI, + NONE +}; +#endif + + +// CSAT_OptionT defines the solver option about learning +// which is used by ABC_SetSolveOption(); +#ifndef _ABC_OPTION_ +#define _ABC_OPTION_ +enum CSAT_OptionT +{ + BASE_LINE = 0, + IMPLICT_LEARNING, //default + EXPLICT_LEARNING +}; +#endif + + +#ifndef _ABC_Target_Result +#define _ABC_Target_Result +typedef struct _CSAT_Target_ResultT CSAT_Target_ResultT; +struct _CSAT_Target_ResultT +{ + enum CSAT_StatusT status; // solve status of the target + int num_dec; // num of decisions to solve the target + int num_imp; // num of implications to solve the target + int num_cftg; // num of conflict gates learned + int num_cfts; // num of conflict signals in conflict gates + double time; // time(in second) used to solve the target + int no_sig; // if "status" is SATISFIABLE, "no_sig" is the number of + // primary inputs, if the "status" is TIME_OUT, "no_sig" is the + // number of constant signals found. + char** names; // if the "status" is SATISFIABLE, "names" is the name array of + // primary inputs, "values" is the value array of primary + // inputs that satisfy the target. + // if the "status" is TIME_OUT, "names" is the name array of + // constant signals found (signals at the root of decision + // tree), "values" is the value array of constant signals found. + int* values; +}; +#endif + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// create a new manager +extern ABC_Manager ABC_InitManager(void); + +// release a manager +extern void ABC_ReleaseManager(ABC_Manager mng); + +// set solver options for learning +extern void ABC_SetSolveOption(ABC_Manager mng, enum CSAT_OptionT option); + +// enable checking by brute-force SAT solver (MiniSat-1.14) +extern void ABC_UseOnlyCoreSatSolver(ABC_Manager mng); + + +// add a gate to the circuit +// the meaning of the parameters are: +// type: the type of the gate to be added +// name: the name of the gate to be added, name should be unique in a circuit. +// nofi: number of fanins of the gate to be added; +// fanins: the name array of fanins of the gate to be added +extern int ABC_AddGate(ABC_Manager mng, + enum GateType type, + char* name, + int nofi, + char** fanins, + int dc_attr); + +// check if there are gates that are not used by any primary ouput. +// if no such gates exist, return 1 else return 0; +extern int ABC_Check_Integrity(ABC_Manager mng); + +// THIS PROCEDURE SHOULD BE CALLED AFTER THE NETWORK IS CONSTRUCTED!!! +extern void ABC_Network_Finalize( ABC_Manager mng ); + +// set time limit for solving a target. +// runtime: time limit (in second). +extern void ABC_SetTimeLimit(ABC_Manager mng, int runtime); +extern void ABC_SetLearnLimit(ABC_Manager mng, int num); +extern void ABC_SetSolveBacktrackLimit(ABC_Manager mng, int num); +extern void ABC_SetLearnBacktrackLimit(ABC_Manager mng, int num); +extern void ABC_EnableDump(ABC_Manager mng, char* dump_file); + +extern void ABC_SetTotalBacktrackLimit( ABC_Manager mng, uint64 num ); +extern void ABC_SetTotalInspectLimit( ABC_Manager mng, uint64 num ); +extern uint64 ABC_GetTotalBacktracksMade( ABC_Manager mng ); +extern uint64 ABC_GetTotalInspectsMade( ABC_Manager mng ); + +// the meaning of the parameters are: +// nog: number of gates that are in the targets +// names: name array of gates +// values: value array of the corresponding gates given in "names" to be +// solved. the relation of them is AND. +extern int ABC_AddTarget(ABC_Manager mng, int nog, char**names, int* values); + +// initialize the solver internal data structure. +extern void ABC_SolveInit(ABC_Manager mng); +extern void ABC_AnalyzeTargets(ABC_Manager mng); + +// solve the targets added by ABC_AddTarget() +extern enum CSAT_StatusT ABC_Solve(ABC_Manager mng); + +// get the solve status of a target +// TargetID: the target id returned by ABC_AddTarget(). +extern CSAT_Target_ResultT * ABC_Get_Target_Result(ABC_Manager mng, int TargetID); +extern void ABC_Dump_Bench_File(ABC_Manager mng); + +// ADDED PROCEDURES: +extern void ABC_TargetResFree( CSAT_Target_ResultT * p ); + +extern void CSAT_SetCaller(ABC_Manager mng, enum CSAT_CallerT caller); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/sat/csat/module.make b/abc70930/src/sat/csat/module.make new file mode 100644 index 00000000..5b71a03c --- /dev/null +++ b/abc70930/src/sat/csat/module.make @@ -0,0 +1 @@ +SRC += src/sat/csat/csat_apis.c diff --git a/abc70930/src/sat/fraig/fraig.h b/abc70930/src/sat/fraig/fraig.h new file mode 100644 index 00000000..1dad21e2 --- /dev/null +++ b/abc70930/src/sat/fraig/fraig.h @@ -0,0 +1,267 @@ +/**CFile**************************************************************** + + FileName [fraig.h] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [External declarations of the FRAIG package.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraig.h,v 1.18 2005/07/08 01:01:30 alanmi Exp $] + +***********************************************************************/ + +#ifndef __FRAIG_H__ +#define __FRAIG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#ifndef SINT64 +#define SINT64 + +#ifdef _WIN32 +typedef signed __int64 sint64; // compatible with MS VS 6.0 +#else +typedef long long sint64; +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Fraig_ManStruct_t_ Fraig_Man_t; +typedef struct Fraig_NodeStruct_t_ Fraig_Node_t; +typedef struct Fraig_NodeVecStruct_t_ Fraig_NodeVec_t; +typedef struct Fraig_HashTableStruct_t_ Fraig_HashTable_t; +typedef struct Fraig_ParamsStruct_t_ Fraig_Params_t; +typedef struct Fraig_PatternsStruct_t_ Fraig_Patterns_t; +typedef struct Prove_ParamsStruct_t_ Prove_Params_t; + +struct Fraig_ParamsStruct_t_ +{ + int nPatsRand; // the number of words of random simulation info + int nPatsDyna; // the number of words of dynamic simulation info + int nBTLimit; // the max number of backtracks to perform + int nSeconds; // the timeout for the final proof + int fFuncRed; // performs only one level hashing + int fFeedBack; // enables solver feedback + int fDist1Pats; // enables distance-1 patterns + int fDoSparse; // performs equiv tests for sparse functions + int fChoicing; // enables recording structural choices + int fTryProve; // tries to solve the final miter + int fVerbose; // the verbosiness flag + int fVerboseP; // the verbosiness flag (for proof reporting) + int fInternal; // is set to 1 for internal fraig calls + int nConfLimit; // the limit on the number of conflicts + sint64 nInspLimit; // the limit on the number of inspections +}; + +struct Prove_ParamsStruct_t_ +{ + // general parameters + int fUseFraiging; // enables fraiging + int fUseRewriting; // enables rewriting + int fUseBdds; // enables BDD construction when other methods fail + int fVerbose; // prints verbose stats + // iterations + int nItersMax; // the number of iterations + // mitering + int nMiteringLimitStart; // starting mitering limit + float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // rewriting + int nRewritingLimitStart; // the number of rewriting iterations + float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // fraiging + int nFraigingLimitStart; // starting backtrack(conflict) limit + float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // last-gasp BDD construction + int nBddSizeLimit; // the number of BDD nodes when construction is aborted + int fBddReorder; // enables dynamic BDD variable reordering + // last-gasp mitering + int nMiteringLimitLast; // final mitering limit + // global SAT solver limits + sint64 nTotalBacktrackLimit; // global limit on the number of backtracks + sint64 nTotalInspectLimit; // global limit on the number of clause inspects + // global resources applied + sint64 nTotalBacktracksMade; // the total number of backtracks made + sint64 nTotalInspectsMade; // the total number of inspects made +}; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// macros working with complemented attributes of the nodes +#define Fraig_IsComplement(p) (((int)((unsigned long) (p) & 01))) +#define Fraig_Regular(p) ((Fraig_Node_t *)((unsigned long)(p) & ~01)) +#define Fraig_Not(p) ((Fraig_Node_t *)((unsigned long)(p) ^ 01)) +#define Fraig_NotCond(p,c) ((Fraig_Node_t *)((unsigned long)(p) ^ (c))) + +// these are currently not used +#define Fraig_Ref(p) +#define Fraig_Deref(p) +#define Fraig_RecursiveDeref(p,c) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== fraigApi.c =============================================================*/ +extern Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p ); +extern Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p ); +extern Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p ); +extern Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p ); +extern Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p ); +extern Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p ); +extern int Fraig_ManReadInputNum ( Fraig_Man_t * p ); +extern int Fraig_ManReadOutputNum( Fraig_Man_t * p ); +extern int Fraig_ManReadNodeNum( Fraig_Man_t * p ); +extern Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p ); +extern Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i ); +extern Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i ); +extern char ** Fraig_ManReadInputNames( Fraig_Man_t * p ); +extern char ** Fraig_ManReadOutputNames( Fraig_Man_t * p ); +extern char * Fraig_ManReadVarsInt( Fraig_Man_t * p ); +extern char * Fraig_ManReadSat( Fraig_Man_t * p ); +extern int Fraig_ManReadFuncRed( Fraig_Man_t * p ); +extern int Fraig_ManReadFeedBack( Fraig_Man_t * p ); +extern int Fraig_ManReadDoSparse( Fraig_Man_t * p ); +extern int Fraig_ManReadChoicing( Fraig_Man_t * p ); +extern int Fraig_ManReadVerbose( Fraig_Man_t * p ); +extern int * Fraig_ManReadModel( Fraig_Man_t * p ); +extern int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ); +extern int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ); +extern int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ); +extern int Fraig_ManReadSatFails( Fraig_Man_t * p ); +extern int Fraig_ManReadConflicts( Fraig_Man_t * p ); +extern int Fraig_ManReadInspects( Fraig_Man_t * p ); + +extern void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed ); +extern void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack ); +extern void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse ); +extern void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ); +extern void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve ); +extern void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose ); +extern void Fraig_ManSetTimeToGraph( Fraig_Man_t * p, int Time ); +extern void Fraig_ManSetTimeToNet( Fraig_Man_t * p, int Time ); +extern void Fraig_ManSetTimeTotal( Fraig_Man_t * p, int Time ); +extern void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ); +extern void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames ); +extern void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode ); + +extern Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p ); +extern Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p ); +extern int Fraig_NodeReadNum( Fraig_Node_t * p ); +extern Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p ); +extern Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p ); +extern Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p ); +extern Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p ); +extern int Fraig_NodeReadNumRefs( Fraig_Node_t * p ); +extern int Fraig_NodeReadNumFanouts( Fraig_Node_t * p ); +extern int Fraig_NodeReadSimInv( Fraig_Node_t * p ); +extern int Fraig_NodeReadNumOnes( Fraig_Node_t * p ); +extern unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p ); +extern unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p ); + +extern void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData ); +extern void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData ); + +extern int Fraig_NodeIsConst( Fraig_Node_t * p ); +extern int Fraig_NodeIsVar( Fraig_Node_t * p ); +extern int Fraig_NodeIsAnd( Fraig_Node_t * p ); +extern int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ); + +extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +extern Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +extern Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +extern Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_Node_t * pNodeT, Fraig_Node_t * pNodeE ); +extern void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew ); + +/*=== fraigMan.c =============================================================*/ +extern void Prove_ParamsSetDefault( Prove_Params_t * pParams ); +extern void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ); +extern void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams ); +extern Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ); +extern void Fraig_ManFree( Fraig_Man_t * pMan ); +extern void Fraig_ManPrintStats( Fraig_Man_t * p ); +extern Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p ); +extern int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ); +extern void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes ); + +/*=== fraigDfs.c =============================================================*/ +extern Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv ); +extern Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv ); +extern Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv ); +extern Fraig_NodeVec_t * Fraig_DfsReverse( Fraig_Man_t * pMan ); +extern int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv ); +extern int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +extern int Fraig_CountLevels( Fraig_Man_t * pMan ); + +/*=== fraigSat.c =============================================================*/ +extern int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit ); +extern int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit ); +extern void Fraig_ManProveMiter( Fraig_Man_t * p ); +extern int Fraig_ManCheckMiter( Fraig_Man_t * p ); +extern int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ); + +/*=== fraigVec.c ===============================================================*/ +extern Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap ); +extern void Fraig_NodeVecFree( Fraig_NodeVec_t * p ); +extern Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * p ); +extern Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p ); +extern int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p ); +extern void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin ); +extern void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew ); +extern void Fraig_NodeVecClear( Fraig_NodeVec_t * p ); +extern void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); +extern int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); +extern void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); +extern int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); +extern void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); +extern int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); +extern Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p ); +extern void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); +extern void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry ); +extern Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i ); +extern void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing ); +extern void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p ); + +/*=== fraigUtil.c ===============================================================*/ +extern void Fraig_ManMarkRealFanouts( Fraig_Man_t * p ); +extern int Fraig_ManCheckConsistency( Fraig_Man_t * p ); +extern int Fraig_GetMaxLevel( Fraig_Man_t * pMan ); +extern void Fraig_ManReportChoices( Fraig_Man_t * pMan ); +extern void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum ); +extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ); + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/abc70930/src/sat/fraig/fraigApi.c b/abc70930/src/sat/fraig/fraigApi.c new file mode 100644 index 00000000..79a7c224 --- /dev/null +++ b/abc70930/src/sat/fraig/fraigApi.c @@ -0,0 +1,297 @@ +/**CFile**************************************************************** + + FileName [fraigApi.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Access APIs for the FRAIG manager and node.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigApi.c,v 1.2 2005/07/08 01:01:30 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Access functions to read the data members of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p ) { return p->vInputs; } +Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p ) { return p->vOutputs; } +Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p ) { return p->vNodes; } +Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p ) { return p->vInputs->pArray; } +Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p ) { return p->vOutputs->pArray; } +Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p ) { return p->vNodes->pArray; } +int Fraig_ManReadInputNum ( Fraig_Man_t * p ) { return p->vInputs->nSize; } +int Fraig_ManReadOutputNum( Fraig_Man_t * p ) { return p->vOutputs->nSize; } +int Fraig_ManReadNodeNum( Fraig_Man_t * p ) { return p->vNodes->nSize; } +Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p ) { return p->pConst1; } +Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i ) { assert ( i < p->vNodes->nSize ); return p->vNodes->pArray[i]; } +char ** Fraig_ManReadInputNames( Fraig_Man_t * p ) { return p->ppInputNames; } +char ** Fraig_ManReadOutputNames( Fraig_Man_t * p ) { return p->ppOutputNames; } +char * Fraig_ManReadVarsInt( Fraig_Man_t * p ) { return (char *)p->vVarsInt; } +char * Fraig_ManReadSat( Fraig_Man_t * p ) { return (char *)p->pSat; } +int Fraig_ManReadFuncRed( Fraig_Man_t * p ) { return p->fFuncRed; } +int Fraig_ManReadFeedBack( Fraig_Man_t * p ) { return p->fFeedBack; } +int Fraig_ManReadDoSparse( Fraig_Man_t * p ) { return p->fDoSparse; } +int Fraig_ManReadChoicing( Fraig_Man_t * p ) { return p->fChoicing; } +int Fraig_ManReadVerbose( Fraig_Man_t * p ) { return p->fVerbose; } +int * Fraig_ManReadModel( Fraig_Man_t * p ) { return p->pModel; } +// returns the number of patterns used for random simulation (this number is fixed for the FRAIG run) +int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ) { return p->nWordsRand * 32; } +// returns the number of dynamic patterns accumulated at runtime (include SAT solver counter-examples and distance-1 patterns derived from them) +int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ) { return p->iWordStart * 32; } +// returns the number of dynamic patterns proved useful to distinquish some FRAIG nodes (this number is more than 0 after the first garbage collection of patterns) +int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ) { return p->iPatsPerm; } +// returns the number of times FRAIG package timed out +int Fraig_ManReadSatFails( Fraig_Man_t * p ) { return p->nSatFailsReal; } +// returns the number of conflicts in the SAT solver +int Fraig_ManReadConflicts( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadBackTracks(p->pSat) : 0; } +// returns the number of inspections in the SAT solver +int Fraig_ManReadInspects( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadInspects(p->pSat) : 0; } + +/**Function************************************************************* + + Synopsis [Access functions to set the data members of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed ) { p->fFuncRed = fFuncRed; } +void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack ) { p->fFeedBack = fFeedBack; } +void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse ) { p->fDoSparse = fDoSparse; } +void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ) { p->fChoicing = fChoicing; } +void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve ) { p->fTryProve = fTryProve; } +void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; } +void Fraig_ManSetTimeToGraph( Fraig_Man_t * p, int Time ) { p->timeToAig = Time; } +void Fraig_ManSetTimeToNet( Fraig_Man_t * p, int Time ) { p->timeToNet = Time; } +void Fraig_ManSetTimeTotal( Fraig_Man_t * p, int Time ) { p->timeTotal = Time; } +void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; } +void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppInputNames = ppNames; } + +/**Function************************************************************* + + Synopsis [Access functions to read the data members of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p ) { return p->pData0; } +Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p ) { return p->pData1; } +int Fraig_NodeReadNum( Fraig_Node_t * p ) { return p->Num; } +Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p1; } +Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p2; } +Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p ) { return p->pNextE; } +Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p ) { return p->pRepr; } +int Fraig_NodeReadNumRefs( Fraig_Node_t * p ) { return p->nRefs; } +int Fraig_NodeReadNumFanouts( Fraig_Node_t * p ) { return p->nFanouts; } +int Fraig_NodeReadSimInv( Fraig_Node_t * p ) { return p->fInv; } +int Fraig_NodeReadNumOnes( Fraig_Node_t * p ) { return p->nOnes; } +// returns the pointer to the random simulation patterns (their number is returned by Fraig_ManReadPatternNumRandom) +// memory pointed to by this and the following procedure is maintained by the FRAIG package and exists as long as the package runs +unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p ) { return p->puSimR; } +// returns the pointer to the dynamic simulation patterns (their number is returned by Fraig_ManReadPatternNumDynamic or Fraig_ManReadPatternNumDynamicFiltered) +// if the number of patterns is not evenly divisible by 32, the patterns beyond the given number contain garbage +unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p ) { return p->puSimD; } + +/**Function************************************************************* + + Synopsis [Access functions to set the data members of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData0 = pData; } +void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData1 = pData; } + +/**Function************************************************************* + + Synopsis [Checks the type of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsConst( Fraig_Node_t * p ) { return (Fraig_Regular(p))->Num == 0; } +int Fraig_NodeIsVar( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi >= 0; } +int Fraig_NodeIsAnd( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi < 0 && (Fraig_Regular(p))->Num > 0; } +int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ) { assert( !Fraig_IsComplement(p1) ); assert( !Fraig_IsComplement(p2) ); return p1->fInv ^ p2->fInv; } + +/**Function************************************************************* + + Synopsis [Returns a new primary input node.] + + Description [If the node with this number does not exist, + create a new PI node with this number.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i ) +{ + int k; + if ( i < 0 ) + { + printf( "Requesting a PI with a negative number\n" ); + return NULL; + } + // create the PIs to fill in the interval + if ( i >= p->vInputs->nSize ) + for ( k = p->vInputs->nSize; k <= i; k++ ) + Fraig_NodeCreatePi( p ); + return p->vInputs->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [Creates a new PO node.] + + Description [This procedure may take a complemented node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + // internal node may be a PO two times + Fraig_Regular(pNode)->fNodePo = 1; + Fraig_NodeVecPush( p->vOutputs, pNode ); +} + +/**Function************************************************************* + + Synopsis [Perfoms the AND operation with functional hashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) +{ + return Fraig_NodeAndCanon( p, p1, p2 ); +} + +/**Function************************************************************* + + Synopsis [Perfoms the OR operation with functional hashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) +{ + return Fraig_Not( Fraig_NodeAndCanon( p, Fraig_Not(p1), Fraig_Not(p2) ) ); +} + +/**Function************************************************************* + + Synopsis [Perfoms the EXOR operation with functional hashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) +{ + return Fraig_NodeMux( p, p1, Fraig_Not(p2), p2 ); +} + +/**Function************************************************************* + + Synopsis [Perfoms the MUX operation with functional hashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pC, Fraig_Node_t * pT, Fraig_Node_t * pE ) +{ + Fraig_Node_t * pAnd1, * pAnd2, * pRes; + pAnd1 = Fraig_NodeAndCanon( p, pC, pT ); Fraig_Ref( pAnd1 ); + pAnd2 = Fraig_NodeAndCanon( p, Fraig_Not(pC), pE ); Fraig_Ref( pAnd2 ); + pRes = Fraig_NodeOr( p, pAnd1, pAnd2 ); + Fraig_RecursiveDeref( p, pAnd1 ); + Fraig_RecursiveDeref( p, pAnd2 ); + Fraig_Deref( pRes ); + return pRes; +} + + +/**Function************************************************************* + + Synopsis [Sets the node to be equivalent to the given one.] + + Description [This procedure is a work-around for the equivalence check. + Does not verify the equivalence. Use at the user's risk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew ) +{ +// assert( pMan->fChoicing ); + pNodeNew->pNextE = pNodeOld->pNextE; + pNodeOld->pNextE = pNodeNew; + pNodeNew->pRepr = pNodeOld; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/fraig/fraigCanon.c b/abc70930/src/sat/fraig/fraigCanon.c new file mode 100644 index 00000000..89bc924f --- /dev/null +++ b/abc70930/src/sat/fraig/fraigCanon.c @@ -0,0 +1,218 @@ +/**CFile**************************************************************** + + FileName [fraigCanon.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [AND-node creation and elementary AND-operation.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigCanon.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#include +#include "fraigInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [The internal AND operation for the two FRAIG nodes.] + + Description [This procedure is the core of the FRAIG package, because + it performs the two-step canonicization of FRAIG nodes. The first step + involves the lookup in the structural hash table (which hashes two ANDs + into a node that has them as fanins, if such a node exists). If the node + is not found in the structural hash table, an attempt is made to find a + functionally equivalent node in another hash table (which hashes the + simulation info into the nodes, which has this simulation info). Some + tricks used on the way are described in the comments to the code and + in the paper "FRAIGs: Functionally reduced AND-INV graphs".] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 ) +{ + Fraig_Node_t * pNodeNew, * pNodeOld, * pNodeRepr; + int fUseSatCheck; +// int RetValue; + + // check for trivial cases + if ( p1 == p2 ) + return p1; + if ( p1 == Fraig_Not(p2) ) + return Fraig_Not(pMan->pConst1); + if ( Fraig_NodeIsConst(p1) ) + { + if ( p1 == pMan->pConst1 ) + return p2; + return Fraig_Not(pMan->pConst1); + } + if ( Fraig_NodeIsConst(p2) ) + { + if ( p2 == pMan->pConst1 ) + return p1; + return Fraig_Not(pMan->pConst1); + } +/* + // check for less trivial cases + if ( Fraig_IsComplement(p1) ) + { + if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p1), p2 ) ) + { + if ( RetValue == -1 ) + pMan->nImplies0++; + else + pMan->nImplies1++; + + if ( RetValue == -1 ) + return p2; + } + } + else + { + if ( RetValue = Fraig_NodeIsInSupergate( p1, p2 ) ) + { + if ( RetValue == 1 ) + pMan->nSimplifies1++; + else + pMan->nSimplifies0++; + + if ( RetValue == 1 ) + return p1; + return Fraig_Not(pMan->pConst1); + } + } + + if ( Fraig_IsComplement(p2) ) + { + if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p2), p1 ) ) + { + if ( RetValue == -1 ) + pMan->nImplies0++; + else + pMan->nImplies1++; + + if ( RetValue == -1 ) + return p1; + } + } + else + { + if ( RetValue = Fraig_NodeIsInSupergate( p2, p1 ) ) + { + if ( RetValue == 1 ) + pMan->nSimplifies1++; + else + pMan->nSimplifies0++; + + if ( RetValue == 1 ) + return p2; + return Fraig_Not(pMan->pConst1); + } + } +*/ + // perform level-one structural hashing + if ( Fraig_HashTableLookupS( pMan, p1, p2, &pNodeNew ) ) // the node with these children is found + { + // if the existent node is part of the cone of unused logic + // (that is logic feeding the node which is equivalent to the given node) + // return the canonical representative of this node + // determine the phase of the given node, with respect to its canonical form + pNodeRepr = Fraig_Regular(pNodeNew)->pRepr; + if ( pMan->fFuncRed && pNodeRepr ) + return Fraig_NotCond( pNodeRepr, Fraig_IsComplement(pNodeNew) ^ Fraig_NodeComparePhase(Fraig_Regular(pNodeNew), pNodeRepr) ); + // otherwise, the node is itself a canonical representative, return it + return pNodeNew; + } + // the same node is not found, but the new one is created + + // if one level hashing is requested (without functionality hashing), return + if ( !pMan->fFuncRed ) + return pNodeNew; + + // check if the new node is unique using the simulation info + if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 ) + { + pMan->nSatZeros++; + if ( !pMan->fDoSparse ) // if we do not do sparse functions, skip + return pNodeNew; + // check the sparse function simulation hash table + pNodeOld = Fraig_HashTableLookupF0( pMan, pNodeNew ); + if ( pNodeOld == NULL ) // the node is unique (it is added to the table) + return pNodeNew; + } + else + { + // check the simulation hash table + pNodeOld = Fraig_HashTableLookupF( pMan, pNodeNew ); + if ( pNodeOld == NULL ) // the node is unique + return pNodeNew; + } + assert( pNodeOld->pRepr == 0 ); + // there is another node which looks the same according to simulation + + // use SAT to resolve the ambiguity + fUseSatCheck = (pMan->nInspLimit == 0 || Fraig_ManReadInspects(pMan) < pMan->nInspLimit); + if ( fUseSatCheck && Fraig_NodeIsEquivalent( pMan, pNodeOld, pNodeNew, pMan->nBTLimit, 1000000 ) ) + { + // set the node to be equivalent with this node + // to prevent loops, only set if the old node is not in the TFI of the new node + // the loop may happen in the following case: suppose + // NodeC = AND(NodeA, NodeB) and at the same time NodeA => NodeB + // in this case, NodeA and NodeC are functionally equivalent + // however, NodeA is a fanin of node NodeC (this leads to the loop) + // add the node to the list of equivalent nodes or dereference it + if ( pMan->fChoicing && !Fraig_CheckTfi( pMan, pNodeOld, pNodeNew ) ) + { + // if the old node is not in the TFI of the new node and choicing + // is enabled, add the new node to the list of equivalent ones + pNodeNew->pNextE = pNodeOld->pNextE; + pNodeOld->pNextE = pNodeNew; + } + // set the canonical representative of this node + pNodeNew->pRepr = pNodeOld; + // return the equivalent node + return Fraig_NotCond( pNodeOld, Fraig_NodeComparePhase(pNodeOld, pNodeNew) ); + } + + // now we add another member to this simulation class + if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 ) + { + Fraig_Node_t * pNodeTemp; + assert( pMan->fDoSparse ); + pNodeTemp = Fraig_HashTableLookupF0( pMan, pNodeNew ); +// assert( pNodeTemp == NULL ); +// Fraig_HashTableInsertF0( pMan, pNodeNew ); + } + else + { + pNodeNew->pNextD = pNodeOld->pNextD; + pNodeOld->pNextD = pNodeNew; + } + // return the new node + assert( pNodeNew->pRepr == 0 ); + return pNodeNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/fraig/fraigChoice.c b/abc70930/src/sat/fraig/fraigChoice.c new file mode 100644 index 00000000..896e5d2d --- /dev/null +++ b/abc70930/src/sat/fraig/fraigChoice.c @@ -0,0 +1,241 @@ +/**CFile**************************************************************** + + FileName [fraigTrans.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Adds the additive and distributive choices to the AIG.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - February 1, 2003.] + + Revision [$Id: fraigTrans.c,v 1.1 2005/02/28 05:34:34 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Adds choice nodes based on associativity.] + + Description [Make nLimit big AND gates and add all decompositions + to the Fraig.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManAddChoices( Fraig_Man_t * pMan, int fVerbose, int nLimit ) +{ +// ProgressBar * pProgress; + char Buffer[100]; + int clkTotal = clock(); + int i, nNodesBefore, nNodesAfter, nInputs, nMaxNodes; + int /*nMaxLevel,*/ nDistributive; + Fraig_Node_t *pNode, *pRepr; + Fraig_Node_t *pX, *pA, *pB, *pC, /* *pD,*/ *pN, /* *pQ, *pR,*/ *pT; + int fShortCut = 0; + + nDistributive = 0; + +// Fraig_ManSetApprox( pMan, 1 ); + + // NO functional reduction + if (fShortCut) Fraig_ManSetFuncRed( pMan, 0 ); + + // First we mark critical functions i.e. compute those + // nodes which lie on the critical path. Note that this + // doesn't update the required times on any choice nodes + // which are not the representatives +/* + nMaxLevel = Fraig_GetMaxLevel( pMan ); + for ( i = 0; i < pMan->nOutputs; i++ ) + { + Fraig_SetNodeRequired( pMan, pMan->pOutputs[i], nMaxLevel ); + } +*/ + nNodesBefore = Fraig_ManReadNodeNum( pMan ); + nInputs = Fraig_ManReadInputNum( pMan ); + nMaxNodes = nInputs + nLimit * ( nNodesBefore - nInputs ); + + printf ("Limit = %d, Before = %d\n", nMaxNodes, nNodesBefore ); + + if (0) + { + char buffer[128]; + sprintf (buffer, "test" ); +// Fraig_MappingShow( pMan, buffer ); + } + +// pProgress = Extra_ProgressBarStart( stdout, nMaxNodes ); +Fraig_ManCheckConsistency( pMan ); + + for ( i = nInputs+1; (i < Fraig_ManReadNodeNum( pMan )) + && (nMaxNodes > Fraig_ManReadNodeNum( pMan )); ++i ) + { +// if ( i == nNodesBefore ) +// break; + + pNode = Fraig_ManReadIthNode( pMan, i ); + assert ( pNode ); + + pRepr = pNode->pRepr ? pNode->pRepr : pNode; + //printf ("Slack: %d\n", Fraig_NodeReadSlack( pRepr )); + + // All the new associative choices we add will have huge slack + // since we do not redo timing, and timing doesnt handle choices + // well anyway. However every newly added node is a choice of an + // existing critical node, so they are considered critical. +// if ( (Fraig_NodeReadSlack( pRepr ) > 3) && (i < nNodesBefore) ) +// continue; + +// if ( pNode->pRepr ) +// continue; + + // Try ((ab)c), x = ab -> (a(bc)) and (b(ac)) + pX = Fraig_NodeReadOne(pNode); + pC = Fraig_NodeReadTwo(pNode); + if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX)) + { + pA = Fraig_NodeReadOne(Fraig_Regular(pX)); + pB = Fraig_NodeReadTwo(Fraig_Regular(pX)); + +// pA = Fraig_NodeGetRepr( pA ); +// pB = Fraig_NodeGetRepr( pB ); +// pC = Fraig_NodeGetRepr( pC ); + + if (fShortCut) + { + pT = Fraig_NodeAnd(pMan, pB, pC); + if ( !pT->pRepr ) + { + pN = Fraig_NodeAnd(pMan, pA, pT); +// Fraig_NodeAddChoice( pMan, pNode, pN ); + } + } + else + pN = Fraig_NodeAnd(pMan, pA, Fraig_NodeAnd(pMan, pB, pC)); + // assert ( Fraig_NodesEqual(pN, pNode) ); + + + if (fShortCut) + { + pT = Fraig_NodeAnd(pMan, pA, pC); + if ( !pT->pRepr ) + { + pN = Fraig_NodeAnd(pMan, pB, pT); +// Fraig_NodeAddChoice( pMan, pNode, pN ); + } + } + else + pN = Fraig_NodeAnd(pMan, pB, Fraig_NodeAnd(pMan, pA, pC)); + // assert ( Fraig_NodesEqual(pN, pNode) ); + } + + + // Try (a(bc)), x = bc -> ((ab)c) and ((ac)b) + pA = Fraig_NodeReadOne(pNode); + pX = Fraig_NodeReadTwo(pNode); + if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX)) + { + pB = Fraig_NodeReadOne(Fraig_Regular(pX)); + pC = Fraig_NodeReadTwo(Fraig_Regular(pX)); + +// pA = Fraig_NodeGetRepr( pA ); +// pB = Fraig_NodeGetRepr( pB ); +// pC = Fraig_NodeGetRepr( pC ); + + if (fShortCut) + { + pT = Fraig_NodeAnd(pMan, pA, pB); + if ( !pT->pRepr ) + { + pN = Fraig_NodeAnd(pMan, pC, pT); +// Fraig_NodeAddChoice( pMan, pNode, pN ); + } + } + else + pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pB), pC); + // assert ( Fraig_NodesEqual(pN, pNode) ); + + if (fShortCut) + { + pT = Fraig_NodeAnd(pMan, pA, pC); + if ( !pT->pRepr ) + { + pN = Fraig_NodeAnd(pMan, pB, pT); +// Fraig_NodeAddChoice( pMan, pNode, pN ); + } + } + else + pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pC), pB); + // assert ( Fraig_NodesEqual(pN, pNode) ); + } + + +/* + // Try distributive transform + pQ = Fraig_NodeReadOne(pNode); + pR = Fraig_NodeReadTwo(pNode); + if ( (Fraig_IsComplement(pQ) && Fraig_NodeIsAnd(pQ)) + && (Fraig_IsComplement(pR) && Fraig_NodeIsAnd(pR)) ) + { + pA = Fraig_NodeReadOne(Fraig_Regular(pQ)); + pB = Fraig_NodeReadTwo(Fraig_Regular(pQ)); + pC = Fraig_NodeReadOne(Fraig_Regular(pR)); + pD = Fraig_NodeReadTwo(Fraig_Regular(pR)); + + // Now detect the !(xy + xz) pattern, store + // x in pA, y in pB and z in pC and set pD = 0 to indicate + // pattern was found + assert (pD != 0); + if (pA == pC) { pC = pD; pD = 0; } + if (pA == pD) { pD = 0; } + if (pB == pC) { pB = pA; pA = pC; pC = pD; pD = 0; } + if (pB == pD) { pB = pA; pA = pD; pD = 0; } + if (pD == 0) + { + nDistributive++; + pN = Fraig_Not(Fraig_NodeAnd(pMan, pA, + Fraig_NodeOr(pMan, pB, pC))); + if (fShortCut) Fraig_NodeAddChoice( pMan, pNode, pN ); + // assert ( Fraig_NodesEqual(pN, pNode) ); + } + } +*/ + if ( i % 1000 == 0 ) + { + sprintf( Buffer, "Adding choice %6d...", i - nNodesBefore ); +// Extra_ProgressBarUpdate( pProgress, i, Buffer ); + } + } + +// Extra_ProgressBarStop( pProgress ); + +Fraig_ManCheckConsistency( pMan ); + + nNodesAfter = Fraig_ManReadNodeNum( pMan ); + printf ( "Nodes before = %6d. Nodes with associative choices = %6d. Increase = %4.2f %%.\n", + nNodesBefore, nNodesAfter, ((float)(nNodesAfter - nNodesBefore)) * 100.0/(nNodesBefore - nInputs) ); + printf ( "Distributive = %d\n", nDistributive ); + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/fraig/fraigFanout.c b/abc70930/src/sat/fraig/fraigFanout.c new file mode 100644 index 00000000..789bffca --- /dev/null +++ b/abc70930/src/sat/fraig/fraigFanout.c @@ -0,0 +1,175 @@ +/**CFile**************************************************************** + + FileName [fraigFanout.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigFanout.c,v 1.5 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +#ifdef FRAIG_ENABLE_FANOUTS + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Add the fanout to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout ) +{ + Fraig_Node_t * pPivot; + + // pFanins is a fanin of pFanout + assert( !Fraig_IsComplement(pFanin) ); + assert( !Fraig_IsComplement(pFanout) ); + assert( Fraig_Regular(pFanout->p1) == pFanin || Fraig_Regular(pFanout->p2) == pFanin ); + + pPivot = pFanin->pFanPivot; + if ( pPivot == NULL ) + { + pFanin->pFanPivot = pFanout; + return; + } + + if ( Fraig_Regular(pPivot->p1) == pFanin ) + { + if ( Fraig_Regular(pFanout->p1) == pFanin ) + { + pFanout->pFanFanin1 = pPivot->pFanFanin1; + pPivot->pFanFanin1 = pFanout; + } + else // if ( Fraig_Regular(pFanout->p2) == pFanin ) + { + pFanout->pFanFanin2 = pPivot->pFanFanin1; + pPivot->pFanFanin1 = pFanout; + } + } + else // if ( Fraig_Regular(pPivot->p2) == pFanin ) + { + assert( Fraig_Regular(pPivot->p2) == pFanin ); + if ( Fraig_Regular(pFanout->p1) == pFanin ) + { + pFanout->pFanFanin1 = pPivot->pFanFanin2; + pPivot->pFanFanin2 = pFanout; + } + else // if ( Fraig_Regular(pFanout->p2) == pFanin ) + { + pFanout->pFanFanin2 = pPivot->pFanFanin2; + pPivot->pFanFanin2 = pFanout; + } + } +} + +/**Function************************************************************* + + Synopsis [Add the fanout to the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove ) +{ + Fraig_Node_t * pFanout, * pFanout2, ** ppFanList; + // start the linked list of fanouts + ppFanList = &pFanin->pFanPivot; + // go through the fanouts + Fraig_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 ) + { + // skip the fanout-to-remove + if ( pFanout == pFanoutToRemove ) + continue; + // add useful fanouts to the list + *ppFanList = pFanout; + ppFanList = Fraig_NodeReadNextFanoutPlace( pFanin, pFanout ); + } + *ppFanList = NULL; +} + +/**Function************************************************************* + + Synopsis [Transfers fanout to a different node.] + + Description [Assumes that the other node currently has no fanouts.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeTransferFanout( Fraig_Node_t * pNodeFrom, Fraig_Node_t * pNodeTo ) +{ + Fraig_Node_t * pFanout; + assert( pNodeTo->pFanPivot == NULL ); + assert( pNodeTo->pFanFanin1 == NULL ); + assert( pNodeTo->pFanFanin2 == NULL ); + // go through the fanouts and update their fanins + Fraig_NodeForEachFanout( pNodeFrom, pFanout ) + { + if ( Fraig_Regular(pFanout->p1) == pNodeFrom ) + pFanout->p1 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p1) ); + else if ( Fraig_Regular(pFanout->p2) == pNodeFrom ) + pFanout->p2 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p2) ); + } + // move the pointers + pNodeTo->pFanPivot = pNodeFrom->pFanPivot; + pNodeTo->pFanFanin1 = pNodeFrom->pFanFanin1; + pNodeTo->pFanFanin2 = pNodeFrom->pFanFanin2; + pNodeFrom->pFanPivot = NULL; + pNodeFrom->pFanFanin1 = NULL; + pNodeFrom->pFanFanin2 = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the number of fanouts of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pFanout; + int Counter = 0; + Fraig_NodeForEachFanout( pNode, pFanout ) + Counter++; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/abc70930/src/sat/fraig/fraigFeed.c b/abc70930/src/sat/fraig/fraigFeed.c new file mode 100644 index 00000000..8a3cc6c7 --- /dev/null +++ b/abc70930/src/sat/fraig/fraigFeed.c @@ -0,0 +1,909 @@ +/**CFile**************************************************************** + + FileName [fraigFeed.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Procedures to support the solver feedback.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigFeed.c,v 1.8 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ); +static int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ); +static void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); + +static void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ); +static Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * pMan ); +static int Fraig_GetSmallestColumn( int * pHits, int nHits ); +static int Fraig_GetHittingPattern( unsigned * pSims, int nWords ); +static void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ); +static void Fraig_FeedBackCheckTable( Fraig_Man_t * p ); +static void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ); +static void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Initializes the feedback information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBackInit( Fraig_Man_t * p ) +{ + p->vCones = Fraig_NodeVecAlloc( 500 ); + p->vPatsReal = Msat_IntVecAlloc( 1000 ); + p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); + p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); +} + +/**Function************************************************************* + + Synopsis [Processes the feedback from teh solver.] + + Description [Array pModel gives the value of each variable in the SAT + solver. Array vVars is the array of integer numbers of variables + involves in this conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + int nVarsPi, nWords; + int i, clk = clock(); + + // get the number of PI vars in the feedback (also sets the PI values) + nVarsPi = Fraig_FeedBackPrepare( p, pModel, vVars ); + + // set the PI values + nWords = Fraig_FeedBackInsert( p, nVarsPi ); + assert( p->iWordStart + nWords <= p->nWordsDyna ); + + // resimulates the words from p->iWordStart to iWordStop + for ( i = 1; i < p->vNodes->nSize; i++ ) + if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) + Fraig_NodeSimulate( p->vNodes->pArray[i], p->iWordStart, p->iWordStart + nWords, 0 ); + + if ( p->fDoSparse ) + Fraig_TableRehashF0( p, 0 ); + + if ( !p->fChoicing ) + Fraig_FeedBackVerify( p, pOld, pNew ); + + // if there is no room left, compress the patterns + if ( p->iWordStart + nWords == p->nWordsDyna ) + p->iWordStart = Fraig_FeedBackCompress( p ); + else // otherwise, update the starting word + p->iWordStart += nWords; + +p->timeFeed += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [Get the number and values of the PI variables.] + + Description [Returns the number of PI variables involved in this feedback. + Fills in the internal presence and value data for the primary inputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ) +{ + Fraig_Node_t * pNode; + int i, nVars, nVarsPis, * pVars; + + // clean the presence flag for all PIs + for ( i = 0; i < p->vInputs->nSize; i++ ) + { + pNode = p->vInputs->pArray[i]; + pNode->fFeedUse = 0; + } + + // get the variables involved in the feedback + nVars = Msat_IntVecReadSize(vVars); + pVars = Msat_IntVecReadArray(vVars); + + // set the values for the present variables + nVarsPis = 0; + for ( i = 0; i < nVars; i++ ) + { + pNode = p->vNodes->pArray[ pVars[i] ]; + if ( !Fraig_NodeIsVar(pNode) ) + continue; + // set its value + pNode->fFeedUse = 1; + pNode->fFeedVal = !MSAT_LITSIGN(pModel[pVars[i]]); + nVarsPis++; + } + return nVarsPis; +} + +/**Function************************************************************* + + Synopsis [Inserts the new simulation patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ) +{ + Fraig_Node_t * pNode; + int nWords, iPatFlip, nPatFlipLimit, i, w; + int fUseNoPats = 0; + int fUse2Pats = 0; + + // get the number of words + if ( fUse2Pats ) + nWords = FRAIG_NUM_WORDS( 2 * nVarsPi + 1 ); + else if ( fUseNoPats ) + nWords = 1; + else + nWords = FRAIG_NUM_WORDS( nVarsPi + 1 ); + // update the number of words if they do not fit into the simulation info + if ( nWords > p->nWordsDyna - p->iWordStart ) + nWords = p->nWordsDyna - p->iWordStart; + // determine the bound on the flipping bit + nPatFlipLimit = nWords * 32 - 2; + + // mark the real pattern + Msat_IntVecPush( p->vPatsReal, p->iWordStart * 32 ); + // record the real pattern + Fraig_BitStringSetBit( p->pSimsReal, p->iWordStart * 32 ); + + // set the values at the PIs + iPatFlip = 1; + for ( i = 0; i < p->vInputs->nSize; i++ ) + { + pNode = p->vInputs->pArray[i]; + for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) + if ( !pNode->fFeedUse ) + pNode->puSimD[w] = FRAIG_RANDOM_UNSIGNED; + else if ( pNode->fFeedVal ) + pNode->puSimD[w] = FRAIG_FULL; + else // if ( !pNode->fFeedVal ) + pNode->puSimD[w] = 0; + + if ( fUse2Pats ) + { + // flip two patterns + if ( pNode->fFeedUse && 2 * iPatFlip < nPatFlipLimit ) + { + Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip - 1 ); + Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip ); + Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip + 1 ); + iPatFlip++; + } + } + else if ( fUseNoPats ) + { + } + else + { + // flip the diagonal + if ( pNode->fFeedUse && iPatFlip < nPatFlipLimit ) + { + Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, iPatFlip ); + iPatFlip++; + // Extra_PrintBinary( stdout, &pNode->puSimD, 45 ); printf( "\n" ); + } + } + // clean the use mask + pNode->fFeedUse = 0; + + // add the info to the D hash value of the PIs + for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) + pNode->uHashD ^= pNode->puSimD[w] * s_FraigPrimes[w]; + + } + return nWords; +} + + +/**Function************************************************************* + + Synopsis [Checks that the SAT solver pattern indeed distinquishes the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + int fValue1, fValue2, iPat; + iPat = Msat_IntVecReadEntry( p->vPatsReal, Msat_IntVecReadSize(p->vPatsReal)-1 ); + fValue1 = (Fraig_BitStringHasBit( pOld->puSimD, iPat )); + fValue2 = (Fraig_BitStringHasBit( pNew->puSimD, iPat )); +/* +Fraig_PrintNode( p, pOld ); +printf( "\n" ); +Fraig_PrintNode( p, pNew ); +printf( "\n" ); +*/ +// assert( fValue1 != fValue2 ); +} + +/**Function************************************************************* + + Synopsis [Compress the simulation patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_FeedBackCompress( Fraig_Man_t * p ) +{ + unsigned * pSims; + unsigned uHash; + int i, w, t, nPats, * pPats; + int fPerformChecks = (p->nBTLimit == -1); + + // solve the covering problem + if ( fPerformChecks ) + { + Fraig_FeedBackCheckTable( p ); + if ( p->fDoSparse ) + Fraig_FeedBackCheckTableF0( p ); + } + + // solve the covering problem + Fraig_FeedBackCovering( p, p->vPatsReal ); + + + // get the number of additional patterns + nPats = Msat_IntVecReadSize( p->vPatsReal ); + pPats = Msat_IntVecReadArray( p->vPatsReal ); + // get the new starting word + p->iWordStart = FRAIG_NUM_WORDS( p->iPatsPerm + nPats ); + + // set the simulation info for the PIs + for ( i = 0; i < p->vInputs->nSize; i++ ) + { + // get hold of the simulation info for this PI + pSims = p->vInputs->pArray[i]->puSimD; + // clean the storage for the new patterns + for ( w = p->iWordPerm; w < p->iWordStart; w++ ) + p->pSimsTemp[w] = 0; + // set the patterns + for ( t = 0; t < nPats; t++ ) + if ( Fraig_BitStringHasBit( pSims, pPats[t] ) ) + { + // check if this pattern falls into temporary storage + if ( p->iPatsPerm + t < p->iWordPerm * 32 ) + Fraig_BitStringSetBit( pSims, p->iPatsPerm + t ); + else + Fraig_BitStringSetBit( p->pSimsTemp, p->iPatsPerm + t ); + } + // copy the pattern + for ( w = p->iWordPerm; w < p->iWordStart; w++ ) + pSims[w] = p->pSimsTemp[w]; + // recompute the hashing info + uHash = 0; + for ( w = 0; w < p->iWordStart; w++ ) + uHash ^= pSims[w] * s_FraigPrimes[w]; + p->vInputs->pArray[i]->uHashD = uHash; + } + + // update info about the permanently stored patterns + p->iWordPerm = p->iWordStart; + p->iPatsPerm += nPats; + assert( p->iWordPerm == FRAIG_NUM_WORDS( p->iPatsPerm ) ); + + // resimulate and recompute the hash values + for ( i = 1; i < p->vNodes->nSize; i++ ) + if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) + { + p->vNodes->pArray[i]->uHashD = 0; + Fraig_NodeSimulate( p->vNodes->pArray[i], 0, p->iWordPerm, 0 ); + } + + // double-check that the nodes are still distinguished + if ( fPerformChecks ) + Fraig_FeedBackCheckTable( p ); + + // rehash the values in the F0 table + if ( p->fDoSparse ) + { + Fraig_TableRehashF0( p, 0 ); + if ( fPerformChecks ) + Fraig_FeedBackCheckTableF0( p ); + } + + // check if we need to resize the simulation info + // if less than FRAIG_WORDS_STORE words are left, reallocate simulation info + if ( p->iWordPerm + FRAIG_WORDS_STORE > p->nWordsDyna ) + Fraig_ReallocateSimulationInfo( p ); + + // set the real patterns + Msat_IntVecClear( p->vPatsReal ); + memset( p->pSimsReal, 0, sizeof(unsigned)*p->nWordsDyna ); + for ( w = 0; w < p->iWordPerm; w++ ) + p->pSimsReal[w] = FRAIG_FULL; + if ( p->iPatsPerm % 32 > 0 ) + p->pSimsReal[p->iWordPerm-1] = FRAIG_MASK( p->iPatsPerm % 32 ); +// printf( "The number of permanent words = %d.\n", p->iWordPerm ); + return p->iWordStart; +} + + + + +/**Function************************************************************* + + Synopsis [Checks the correctness of the functional simulation table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ) +{ + Fraig_NodeVec_t * vColumns; + unsigned * pSims; + int * pHits, iPat, iCol, i; + int nOnesTotal, nSolStarting; + int fVeryVerbose = 0; + + // collect the pairs to be distinguished + vColumns = Fraig_FeedBackCoveringStart( p ); + // collect the number of 1s in each simulation vector + nOnesTotal = 0; + pHits = ALLOC( int, vColumns->nSize ); + for ( i = 0; i < vColumns->nSize; i++ ) + { + pSims = (unsigned *)vColumns->pArray[i]; + pHits[i] = Fraig_BitStringCountOnes( pSims, p->iWordStart ); + nOnesTotal += pHits[i]; +// assert( pHits[i] > 0 ); + } + + // go through the patterns + nSolStarting = Msat_IntVecReadSize(vPats); + while ( (iCol = Fraig_GetSmallestColumn( pHits, vColumns->nSize )) != -1 ) + { + // find the pattern, which hits this column + iPat = Fraig_GetHittingPattern( (unsigned *)vColumns->pArray[iCol], p->iWordStart ); + // cancel the columns covered by this pattern + Fraig_CancelCoveredColumns( vColumns, pHits, iPat ); + // save the pattern + Msat_IntVecPush( vPats, iPat ); + } + + // free the set of columns + for ( i = 0; i < vColumns->nSize; i++ ) + Fraig_MemFixedEntryRecycle( p->mmSims, (char *)vColumns->pArray[i] ); + + // print stats related to the covering problem + if ( p->fVerbose && fVeryVerbose ) + { + printf( "%3d\\%3d\\%3d ", p->nWordsRand, p->nWordsDyna, p->iWordPerm ); + printf( "Col (pairs) = %5d. ", vColumns->nSize ); + printf( "Row (pats) = %5d. ", p->iWordStart * 32 ); + printf( "Dns = %6.2f %%. ", vColumns->nSize==0? 0.0 : 100.0 * nOnesTotal / vColumns->nSize / p->iWordStart / 32 ); + printf( "Sol = %3d (%3d). ", Msat_IntVecReadSize(vPats), nSolStarting ); + printf( "\n" ); + } + Fraig_NodeVecFree( vColumns ); + free( pHits ); +} + + +/**Function************************************************************* + + Synopsis [Checks the correctness of the functional simulation table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * p ) +{ + Fraig_NodeVec_t * vColumns; + Fraig_HashTable_t * pT = p->pTableF; + Fraig_Node_t * pEntF, * pEntD; + unsigned * pSims; + unsigned * pUnsigned1, * pUnsigned2; + int i, k, m, w;//, nOnes; + + // start the set of columns + vColumns = Fraig_NodeVecAlloc( 100 ); + + // go through the pairs of nodes to be distinguished + for ( i = 0; i < pT->nBins; i++ ) + Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) + { + p->vCones->nSize = 0; + Fraig_TableBinForEachEntryD( pEntF, pEntD ) + Fraig_NodeVecPush( p->vCones, pEntD ); + if ( p->vCones->nSize == 1 ) + continue; + //////////////////////////////// bug fix by alanmi, September 14, 2006 + if ( p->vCones->nSize > 20 ) + continue; + //////////////////////////////// + + for ( k = 0; k < p->vCones->nSize; k++ ) + for ( m = k+1; m < p->vCones->nSize; m++ ) + { + if ( !Fraig_CompareSimInfoUnderMask( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0, p->pSimsReal ) ) + continue; + + // primary simulation patterns (counter-examples) cannot distinguish this pair + // get memory to store the feasible simulation patterns + pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + // find the pattern that distinguish this column, exept the primary ones + pUnsigned1 = p->vCones->pArray[k]->puSimD; + pUnsigned2 = p->vCones->pArray[m]->puSimD; + for ( w = 0; w < p->iWordStart; w++ ) + pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; + // store the pattern + Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); +// nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); +// assert( nOnes > 0 ); + } + } + + // if the flag is not set, do not consider sparse nodes in p->pTableF0 + if ( !p->fDoSparse ) + return vColumns; + + // recalculate their hash values based on p->pSimsReal + pT = p->pTableF0; + for ( i = 0; i < pT->nBins; i++ ) + Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) + { + pSims = pEntF->puSimD; + pEntF->uHashD = 0; + for ( w = 0; w < p->iWordStart; w++ ) + pEntF->uHashD ^= (pSims[w] & p->pSimsReal[w]) * s_FraigPrimes[w]; + } + + // rehash the table using these values + Fraig_TableRehashF0( p, 1 ); + + // collect the classes of equivalent node pairs + for ( i = 0; i < pT->nBins; i++ ) + Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) + { + p->vCones->nSize = 0; + Fraig_TableBinForEachEntryD( pEntF, pEntD ) + Fraig_NodeVecPush( p->vCones, pEntD ); + if ( p->vCones->nSize == 1 ) + continue; + + // primary simulation patterns (counter-examples) cannot distinguish all these pairs + for ( k = 0; k < p->vCones->nSize; k++ ) + for ( m = k+1; m < p->vCones->nSize; m++ ) + { + // get memory to store the feasible simulation patterns + pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + // find the patterns that are not distinquished + pUnsigned1 = p->vCones->pArray[k]->puSimD; + pUnsigned2 = p->vCones->pArray[m]->puSimD; + for ( w = 0; w < p->iWordStart; w++ ) + pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; + // store the pattern + Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); +// nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); +// assert( nOnes > 0 ); + } + } + return vColumns; +} + +/**Function************************************************************* + + Synopsis [Selects the column, which has the smallest number of hits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_GetSmallestColumn( int * pHits, int nHits ) +{ + int i, iColMin = -1, nHitsMin = 1000000; + for ( i = 0; i < nHits; i++ ) + { + // skip covered columns + if ( pHits[i] == 0 ) + continue; + // take the column if it can only be covered by one pattern + if ( pHits[i] == 1 ) + return i; + // find the column, which requires the smallest number of patterns + if ( nHitsMin > pHits[i] ) + { + nHitsMin = pHits[i]; + iColMin = i; + } + } + return iColMin; +} + +/**Function************************************************************* + + Synopsis [Select the pattern, which hits this column.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_GetHittingPattern( unsigned * pSims, int nWords ) +{ + int i, b; + for ( i = 0; i < nWords; i++ ) + { + if ( pSims[i] == 0 ) + continue; + for ( b = 0; b < 32; b++ ) + if ( pSims[i] & (1 << b) ) + return i * 32 + b; + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Cancel covered patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ) +{ + unsigned * pSims; + int i; + for ( i = 0; i < vColumns->nSize; i++ ) + { + pSims = (unsigned *)vColumns->pArray[i]; + if ( Fraig_BitStringHasBit( pSims, iPat ) ) + pHits[i] = 0; + } +} + + +/**Function************************************************************* + + Synopsis [Checks the correctness of the functional simulation table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBackCheckTable( Fraig_Man_t * p ) +{ + Fraig_HashTable_t * pT = p->pTableF; + Fraig_Node_t * pEntF, * pEntD; + int i, k, m, nPairs; + int clk = clock(); + + nPairs = 0; + for ( i = 0; i < pT->nBins; i++ ) + Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) + { + p->vCones->nSize = 0; + Fraig_TableBinForEachEntryD( pEntF, pEntD ) + Fraig_NodeVecPush( p->vCones, pEntD ); + if ( p->vCones->nSize == 1 ) + continue; + for ( k = 0; k < p->vCones->nSize; k++ ) + for ( m = k+1; m < p->vCones->nSize; m++ ) + { + if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) + printf( "Nodes %d and %d have the same D simulation info.\n", + p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); + nPairs++; + } + } +// printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); +} + +/**Function************************************************************* + + Synopsis [Checks the correctness of the functional simulation table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ) +{ + Fraig_HashTable_t * pT = p->pTableF0; + Fraig_Node_t * pEntF; + int i, k, m, nPairs; + + nPairs = 0; + for ( i = 0; i < pT->nBins; i++ ) + { + p->vCones->nSize = 0; + Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) + Fraig_NodeVecPush( p->vCones, pEntF ); + if ( p->vCones->nSize == 1 ) + continue; + for ( k = 0; k < p->vCones->nSize; k++ ) + for ( m = k+1; m < p->vCones->nSize; m++ ) + { + if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) + printf( "Nodes %d and %d have the same D simulation info.\n", + p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); + nPairs++; + } + } +// printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); +} + +/**Function************************************************************* + + Synopsis [Doubles the size of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ) +{ + Fraig_MemFixed_t * mmSimsNew; // new memory manager for simulation info + Fraig_Node_t * pNode; + unsigned * pSimsNew; + unsigned uSignOld; + int i; + + // allocate a new memory manager + p->nWordsDyna *= 2; + mmSimsNew = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); + + // set the new data for the constant node + pNode = p->pConst1; + pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); + pNode->puSimD = pNode->puSimR + p->nWordsRand; + memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); + memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); + + // copy the simulation info of the PIs + for ( i = 0; i < p->vInputs->nSize; i++ ) + { + pNode = p->vInputs->pArray[i]; + // copy the simulation info + pSimsNew = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); + memmove( pSimsNew, pNode->puSimR, sizeof(unsigned) * (p->nWordsRand + p->iWordStart) ); + // attach the new info + pNode->puSimR = pSimsNew; + pNode->puSimD = pNode->puSimR + p->nWordsRand; + // signatures remain without changes + } + + // replace the manager to free up some memory + Fraig_MemFixedStop( p->mmSims, 0 ); + p->mmSims = mmSimsNew; + + // resimulate the internal nodes (this should lead to the same signatures) + for ( i = 1; i < p->vNodes->nSize; i++ ) + { + pNode = p->vNodes->pArray[i]; + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + // allocate memory for the simulation info + pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); + pNode->puSimD = pNode->puSimR + p->nWordsRand; + // derive random simulation info + uSignOld = pNode->uHashR; + pNode->uHashR = 0; + Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); + assert( uSignOld == pNode->uHashR ); + // derive dynamic simulation info + uSignOld = pNode->uHashD; + pNode->uHashD = 0; + Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); + assert( uSignOld == pNode->uHashD ); + } + + // realloc temporary storage + p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); + memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); + p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); + p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); +} + + +/**Function************************************************************* + + Synopsis [Generated trivial counter example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Fraig_ManAllocCounterExample( Fraig_Man_t * p ) +{ + int * pModel; + pModel = ALLOC( int, p->vInputs->nSize ); + memset( pModel, 0, sizeof(int) * p->vInputs->nSize ); + return pModel; +} + + +/**Function************************************************************* + + Synopsis [Saves the counter example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManSimulateBitNode_rec( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + int Value0, Value1; + if ( Fraig_NodeIsTravIdCurrent( p, pNode ) ) + return pNode->fMark3; + Fraig_NodeSetTravIdCurrent( p, pNode ); + Value0 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p1) ); + Value1 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p2) ); + Value0 ^= Fraig_IsComplement(pNode->p1); + Value1 ^= Fraig_IsComplement(pNode->p2); + pNode->fMark3 = Value0 & Value1; + return pNode->fMark3; +} + +/**Function************************************************************* + + Synopsis [Simulates one bit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManSimulateBitNode( Fraig_Man_t * p, Fraig_Node_t * pNode, int * pModel ) +{ + int fCompl, RetValue, i; + // set the PI values + Fraig_ManIncrementTravId( p ); + for ( i = 0; i < p->vInputs->nSize; i++ ) + { + Fraig_NodeSetTravIdCurrent( p, p->vInputs->pArray[i] ); + p->vInputs->pArray[i]->fMark3 = pModel[i]; + } + // perform the traversal + fCompl = Fraig_IsComplement(pNode); + RetValue = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode) ); + return fCompl ^ RetValue; +} + + +/**Function************************************************************* + + Synopsis [Saves the counter example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + int * pModel; + int iPattern; + int i, fCompl; + + // the node can be complemented + fCompl = Fraig_IsComplement(pNode); + // because we compare with constant 0, p->pConst1 should also be complemented + fCompl = !fCompl; + + // derive the model + pModel = Fraig_ManAllocCounterExample( p ); + iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->nWordsRand, 1 ); + if ( iPattern >= 0 ) + { + for ( i = 0; i < p->vInputs->nSize; i++ ) + if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimR, iPattern ) ) + pModel[i] = 1; +/* +printf( "SAT solver's pattern:\n" ); +for ( i = 0; i < p->vInputs->nSize; i++ ) + printf( "%d", pModel[i] ); +printf( "\n" ); +*/ + assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); + return pModel; + } + iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->iWordStart, 0 ); + if ( iPattern >= 0 ) + { + for ( i = 0; i < p->vInputs->nSize; i++ ) + if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimD, iPattern ) ) + pModel[i] = 1; +/* +printf( "SAT solver's pattern:\n" ); +for ( i = 0; i < p->vInputs->nSize; i++ ) + printf( "%d", pModel[i] ); +printf( "\n" ); +*/ + assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); + return pModel; + } + FREE( pModel ); + return NULL; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/fraig/fraigInt.h b/abc70930/src/sat/fraig/fraigInt.h new file mode 100644 index 00000000..9c6e0d47 --- /dev/null +++ b/abc70930/src/sat/fraig/fraigInt.h @@ -0,0 +1,451 @@ +/**CFile**************************************************************** + + FileName [fraigInt.h] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Internal declarations of the FRAIG package.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigInt.h,v 1.15 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#ifndef __FRAIG_INT_H__ +#define __FRAIG_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//#include "leaks.h" +#include +#include +#include +#include +#include + +#include "fraig.h" +#include "msat.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +/* + The AIG node policy: + - Each node has its main number (pNode->Num) + This is the number of this node in the array of all nodes and its SAT variable number + - The PI nodes are stored along with other nodes + Additionally, PI nodes have a PI number, by which they are stored in the PI node array + - The constant node is has number 0 and is also stored in the array +*/ + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// enable this macro to support the fanouts +#define FRAIG_ENABLE_FANOUTS +#define FRAIG_PATTERNS_RANDOM 2048 // should not be less than 128 and more than 32768 (2^15) +#define FRAIG_PATTERNS_DYNAMIC 2048 // should not be less than 256 and more than 32768 (2^15) +#define FRAIG_MAX_PRIMES 1024 // the maximum number of primes used for hashing + +// this parameter determines when simulation info is extended +// it will be extended when the free storage in the dynamic simulation +// info is less or equal to this number of words (FRAIG_WORDS_STORE) +// this is done because if the free storage for dynamic simulation info +// is not sufficient, computation becomes inefficient +#define FRAIG_WORDS_STORE 5 + +// the bit masks +#define FRAIG_MASK(n) ((~((unsigned)0)) >> (32-(n))) +#define FRAIG_FULL (~((unsigned)0)) +#define FRAIG_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0)) + +// maximum/minimum operators +#define FRAIG_MIN(a,b) (((a) < (b))? (a) : (b)) +#define FRAIG_MAX(a,b) (((a) > (b))? (a) : (b)) + +// generating random unsigned (#define RAND_MAX 0x7fff) +#define FRAIG_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) + +// macros to get hold of the bits in a bit string +#define Fraig_BitStringSetBit(p,i) ((p)[(i)>>5] |= (1<<((i) & 31))) +#define Fraig_BitStringXorBit(p,i) ((p)[(i)>>5] ^= (1<<((i) & 31))) +#define Fraig_BitStringHasBit(p,i) (((p)[(i)>>5] & (1<<((i) & 31))) > 0) + +// macros to get hold of the bits in the support info +//#define Fraig_NodeSetVarStr(p,i) (Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] |= (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) +//#define Fraig_NodeHasVarStr(p,i) ((Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] & (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) > 0) +#define Fraig_NodeSetVarStr(p,i) Fraig_BitStringSetBit(Fraig_Regular(p)->pSuppStr,i) +#define Fraig_NodeHasVarStr(p,i) Fraig_BitStringHasBit(Fraig_Regular(p)->pSuppStr,i) + +// copied from "util.h" for standaloneness +#ifndef ALLOC +# define ALLOC(type, num) \ + ((type *) malloc(sizeof(type) * (num))) +#endif + +#ifndef REALLOC +# define REALLOC(type, obj, num) \ + (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num))) +#endif + +#ifndef FREE +# define FREE(obj) \ + ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#endif + +// copied from "extra.h" for stand-aloneness +#define Fraig_PrintTime(a,t) printf( "%s = ", (a) ); printf( "%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) ) + +#define Fraig_HashKey2(a,b,TSIZE) (((unsigned)(a) + (unsigned)(b) * 12582917) % TSIZE) +//#define Fraig_HashKey2(a,b,TSIZE) (( ((unsigned)(a)->Num * 19) ^ ((unsigned)(b)->Num * 1999) ) % TSIZE) +//#define Fraig_HashKey2(a,b,TSIZE) ( ((unsigned)((a)->Num + (b)->Num) * ((a)->Num + (b)->Num + 1) / 2) % TSIZE) +// the other two hash functions give bad distribution of hash chain lengths (not clear why) + +#ifndef PRT +#define PRT(a,t) printf( "%s = ", (a) ); printf( "%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) ) +#endif + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Fraig_MemFixed_t_ Fraig_MemFixed_t; + +// the mapping manager +struct Fraig_ManStruct_t_ +{ + // the AIG nodes + Fraig_NodeVec_t * vInputs; // the array of primary inputs + Fraig_NodeVec_t * vNodes; // the array of all nodes, including primary inputs + Fraig_NodeVec_t * vOutputs; // the array of primary outputs (some internal nodes) + Fraig_Node_t * pConst1; // the pointer to the constant node (vNodes->pArray[0]) + + // info about the original circuit + char ** ppInputNames; // the primary input names + char ** ppOutputNames; // the primary output names + + // various hash-tables + Fraig_HashTable_t * pTableS; // hashing by structure + Fraig_HashTable_t * pTableF; // hashing by simulation info + Fraig_HashTable_t * pTableF0; // hashing by simulation info (sparse functions) + + // parameters + int nWordsRand; // the number of words of random simulation info + int nWordsDyna; // the number of words of dynamic simulation info + int nBTLimit; // the max number of backtracks to perform + int nSeconds; // the runtime limit for the miter proof + int fFuncRed; // performs only one level hashing + int fFeedBack; // enables solver feedback + int fDist1Pats; // enables solver feedback + int fDoSparse; // performs equiv tests for sparse functions + int fChoicing; // enables recording structural choices + int fTryProve; // tries to solve the final miter + int fVerbose; // the verbosiness flag + int fVerboseP; // the verbosiness flag + sint64 nInspLimit; // the inspection limit + + int nTravIds; // the traversal counter + int nTravIds2; // the traversal counter + + // info related to the solver feedback + int iWordStart; // the first word to use for simulation + int iWordPerm; // the number of words stored permanently + int iPatsPerm; // the number of patterns stored permanently + Fraig_NodeVec_t * vCones; // the temporary array of internal variables + Msat_IntVec_t * vPatsReal; // the array of real pattern numbers + unsigned * pSimsReal; // used for simulation patterns + unsigned * pSimsDiff; // used for simulation patterns + unsigned * pSimsTemp; // used for simulation patterns + + // the support information + int nSuppWords; + unsigned ** pSuppS; + unsigned ** pSuppF; + + // the memory managers + Fraig_MemFixed_t * mmNodes; // the memory manager for nodes + Fraig_MemFixed_t * mmSims; // the memory manager for simulation info + + // solving the SAT problem + Msat_Solver_t * pSat; // the SAT solver + Msat_IntVec_t * vProj; // the temporary array of projection vars + int nSatNums; // the counter of SAT variables + int * pModel; // the assignment, which satisfies the miter + // these arrays belong to the solver + Msat_IntVec_t * vVarsInt; // the temporary array of variables + Msat_ClauseVec_t * vAdjacents; // the temporary storage for connectivity + Msat_IntVec_t * vVarsUsed; // the array marking vars appearing in the cone + + // various statistic variables + int nSatCalls; // the number of times equivalence checking was called + int nSatProof; // the number of times a proof was found + int nSatCounter; // the number of times a counter example was found + int nSatFails; // the number of times the SAT solver failed to complete due to resource limit or prediction + int nSatFailsReal; // the number of times the SAT solver failed to complete due to resource limit + + int nSatCallsImp; // the number of times equivalence checking was called + int nSatProofImp; // the number of times a proof was found + int nSatCounterImp;// the number of times a counter example was found + int nSatFailsImp; // the number of times the SAT solver failed to complete + + int nSatZeros; // the number of times the simulation vector is zero + int nSatSupps; // the number of times the support info was useful + int nRefErrors; // the number of ref counting errors + int nImplies; // the number of implication cases + int nSatImpls; // the number of implication SAT calls + int nVarsClauses; // the number of variables with clauses + int nSimplifies0; + int nSimplifies1; + int nImplies0; + int nImplies1; + + // runtime statistics + int timeToAig; // time to transfer to the mapping structure + int timeSims; // time to compute k-feasible cuts + int timeTrav; // time to traverse the network + int timeFeed; // time for solver feedback (recording and resimulating) + int timeImply; // time to analyze implications + int timeSat; // time to compute the truth table for each cut + int timeToNet; // time to transfer back to the network + int timeTotal; // the total mapping time + int time1; // time to perform one task + int time2; // time to perform another task + int time3; // time to perform another task + int time4; // time to perform another task +}; + +// the mapping node +struct Fraig_NodeStruct_t_ +{ + // various numbers associated with the node + int Num; // the unique number (SAT var number) of this node + int NumPi; // if the node is a PI, this is its variable number + int Level; // the level of the node + int nRefs; // the number of references of the node + int TravId; // the traversal ID (use to avoid cleaning marks) + int TravId2; // the traversal ID (use to avoid cleaning marks) + + // general information about the node + unsigned fInv : 1; // the mark to show that simulation info is complemented + unsigned fNodePo : 1; // the mark used for primary outputs + unsigned fClauses : 1; // the clauses for this node are loaded + unsigned fMark0 : 1; // the mark used for traversals + unsigned fMark1 : 1; // the mark used for traversals + unsigned fMark2 : 1; // the mark used for traversals + unsigned fMark3 : 1; // the mark used for traversals + unsigned fFeedUse : 1; // the presence of the variable in the feedback + unsigned fFeedVal : 1; // the value of the variable in the feedback + unsigned fFailTfo : 1; // the node is in the TFO of the failed SAT run + unsigned nFanouts : 2; // the indicator of fanouts (none, one, or many) + unsigned nOnes : 20; // the number of 1's in the random sim info + + // the children of the node + Fraig_Node_t * p1; // the first child + Fraig_Node_t * p2; // the second child + Fraig_NodeVec_t * vFanins; // the fanins of the supergate rooted at this node +// Fraig_NodeVec_t * vFanouts; // the fanouts of the supergate rooted at this node + + // various linked lists + Fraig_Node_t * pNextS; // the next node in the structural hash table + Fraig_Node_t * pNextF; // the next node in the functional (simulation) hash table + Fraig_Node_t * pNextD; // the next node in the list of nodes based on dynamic simulation + Fraig_Node_t * pNextE; // the next structural choice (functionally-equivalent node) + Fraig_Node_t * pRepr; // the canonical functional representative of the node + + // simulation data + unsigned uHashR; // the hash value for random information + unsigned uHashD; // the hash value for dynamic information + unsigned * puSimR; // the simulation information (random) + unsigned * puSimD; // the simulation information (dynamic) + + // misc information + Fraig_Node_t * pData0; // temporary storage for the corresponding network node + Fraig_Node_t * pData1; // temporary storage for the corresponding network node + +#ifdef FRAIG_ENABLE_FANOUTS + // representation of node's fanouts + Fraig_Node_t * pFanPivot; // the first fanout of this node + Fraig_Node_t * pFanFanin1; // the next fanout of p1 + Fraig_Node_t * pFanFanin2; // the next fanout of p2 +#endif +}; + +// the vector of nodes +struct Fraig_NodeVecStruct_t_ +{ + int nCap; // the number of allocated entries + int nSize; // the number of entries in the array + Fraig_Node_t ** pArray; // the array of nodes +}; + +// the hash table +struct Fraig_HashTableStruct_t_ +{ + Fraig_Node_t ** pBins; // the table bins + int nBins; // the size of the table + int nEntries; // the total number of entries in the table +}; + +// getting hold of the next fanout of the node +#define Fraig_NodeReadNextFanout( pNode, pFanout ) \ + ( ( pFanout == NULL )? NULL : \ + ((Fraig_Regular((pFanout)->p1) == (pNode))? \ + (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) ) +// getting hold of the place where the next fanout will be attached +#define Fraig_NodeReadNextFanoutPlace( pNode, pFanout ) \ + ( (Fraig_Regular((pFanout)->p1) == (pNode))? \ + &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 ) +// iterator through the fanouts of the node +#define Fraig_NodeForEachFanout( pNode, pFanout ) \ + for ( pFanout = (pNode)->pFanPivot; pFanout; \ + pFanout = Fraig_NodeReadNextFanout(pNode, pFanout) ) +// safe iterator through the fanouts of the node +#define Fraig_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \ + for ( pFanout = (pNode)->pFanPivot, \ + pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout); \ + pFanout; \ + pFanout = pFanout2, \ + pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout) ) + +// iterators through the entries in the linked lists of nodes +// the list of nodes in the structural hash table +#define Fraig_TableBinForEachEntryS( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = pEnt->pNextS ) +#define Fraig_TableBinForEachEntrySafeS( pBin, pEnt, pEnt2 ) \ + for ( pEnt = pBin, \ + pEnt2 = pEnt? pEnt->pNextS: NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? pEnt->pNextS: NULL ) +// the list of nodes in the functional (simulation) hash table +#define Fraig_TableBinForEachEntryF( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = pEnt->pNextF ) +#define Fraig_TableBinForEachEntrySafeF( pBin, pEnt, pEnt2 ) \ + for ( pEnt = pBin, \ + pEnt2 = pEnt? pEnt->pNextF: NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? pEnt->pNextF: NULL ) +// the list of nodes with the same simulation and different functionality +#define Fraig_TableBinForEachEntryD( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = pEnt->pNextD ) +#define Fraig_TableBinForEachEntrySafeD( pBin, pEnt, pEnt2 ) \ + for ( pEnt = pBin, \ + pEnt2 = pEnt? pEnt->pNextD: NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? pEnt->pNextD: NULL ) +// the list of nodes with the same functionality +#define Fraig_TableBinForEachEntryE( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = pEnt->pNextE ) +#define Fraig_TableBinForEachEntrySafeE( pBin, pEnt, pEnt2 ) \ + for ( pEnt = pBin, \ + pEnt2 = pEnt? pEnt->pNextE: NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? pEnt->pNextE: NULL ) + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== fraigCanon.c =============================================================*/ +extern Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +/*=== fraigFanout.c =============================================================*/ +extern void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout ); +extern void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove ); +extern int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode ); +/*=== fraigFeed.c =============================================================*/ +extern void Fraig_FeedBackInit( Fraig_Man_t * p ); +extern void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +extern void Fraig_FeedBackTest( Fraig_Man_t * p ); +extern int Fraig_FeedBackCompress( Fraig_Man_t * p ); +extern int * Fraig_ManAllocCounterExample( Fraig_Man_t * p ); +extern int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode ); +/*=== fraigMan.c =============================================================*/ +extern void Fraig_ManCreateSolver( Fraig_Man_t * p ); +/*=== fraigMem.c =============================================================*/ +extern Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize ); +extern void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose ); +extern char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p ); +extern void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry ); +extern void Fraig_MemFixedRestart( Fraig_MemFixed_t * p ); +extern int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p ); +/*=== fraigNode.c =============================================================*/ +extern Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p ); +extern Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ); +extern Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); +extern void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand ); +/*=== fraigPrime.c =============================================================*/ +extern int s_FraigPrimes[FRAIG_MAX_PRIMES]; +extern unsigned int Cudd_PrimeFraig( unsigned int p ); +/*=== fraigSat.c ===============================================================*/ +extern int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ); +/*=== fraigTable.c =============================================================*/ +extern Fraig_HashTable_t * Fraig_HashTableCreate( int nSize ); +extern void Fraig_HashTableFree( Fraig_HashTable_t * p ); +extern int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes ); +extern Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +extern Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +extern void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +extern int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand ); +extern int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ); +extern int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand ); +extern void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ); +extern void Fraig_TablePrintStatsS( Fraig_Man_t * pMan ); +extern void Fraig_TablePrintStatsF( Fraig_Man_t * pMan ); +extern void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan ); +extern int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv ); +/*=== fraigUtil.c ===============================================================*/ +extern int Fraig_NodeCountPis( Msat_IntVec_t * vVars, int nVarsPi ); +extern int Fraig_NodeCountSuppVars( Fraig_Man_t * p, Fraig_Node_t * pNode, int fSuppStr ); +extern int Fraig_NodesCompareSupps( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +extern int Fraig_NodeAndSimpleCase_rec( Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode ); +extern void Fraig_ManSelectBestChoice( Fraig_Man_t * p ); +extern int Fraig_BitStringCountOnes( unsigned * pString, int nWords ); +extern void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits ); +extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode ); +extern int Fraig_NodeIsExor( Fraig_Node_t * pNode ); +extern int Fraig_NodeIsMuxType( Fraig_Node_t * pNode ); +extern Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE ); +extern int Fraig_ManCountExors( Fraig_Man_t * pMan ); +extern int Fraig_ManCountMuxes( Fraig_Man_t * pMan ); +extern int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ); +extern int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ); +extern int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums ); +extern void Fraig_ManIncrementTravId( Fraig_Man_t * pMan ); +extern void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +extern int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +extern int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +/*=== fraigVec.c ===============================================================*/ +extern void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p ); + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/sat/fraig/fraigMan.c b/abc70930/src/sat/fraig/fraigMan.c new file mode 100644 index 00000000..7fd937d5 --- /dev/null +++ b/abc70930/src/sat/fraig/fraigMan.c @@ -0,0 +1,540 @@ +/**CFile**************************************************************** + + FileName [fraigMan.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Implementation of the FRAIG manager.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigMan.c,v 1.11 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +int timeSelect; +int timeAssign; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets the default parameters of the package.] + + Description [This set of parameters is tuned for equivalence checking.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Prove_ParamsSetDefault( Prove_Params_t * pParams ) +{ + // clean the parameter structure + memset( pParams, 0, sizeof(Prove_Params_t) ); + // general parameters + pParams->fUseFraiging = 1; // enables fraiging + pParams->fUseRewriting = 1; // enables rewriting + pParams->fUseBdds = 0; // enables BDD construction when other methods fail + pParams->fVerbose = 0; // prints verbose stats + // iterations + pParams->nItersMax = 6; // the number of iterations + // mitering + pParams->nMiteringLimitStart = 300; // starting mitering limit + pParams->nMiteringLimitMulti = 2.0; // multiplicative coefficient to increase the limit in each iteration + // rewriting (currently not used) + pParams->nRewritingLimitStart = 3; // the number of rewriting iterations + pParams->nRewritingLimitMulti = 1.0; // multiplicative coefficient to increase the limit in each iteration + // fraiging + pParams->nFraigingLimitStart = 2; // starting backtrack(conflict) limit + pParams->nFraigingLimitMulti = 8.0; // multiplicative coefficient to increase the limit in each iteration + // last-gasp BDD construction + pParams->nBddSizeLimit = 1000000; // the number of BDD nodes when construction is aborted + pParams->fBddReorder = 1; // enables dynamic BDD variable reordering + // last-gasp mitering +// pParams->nMiteringLimitLast = 1000000; // final mitering limit + pParams->nMiteringLimitLast = 0; // final mitering limit + // global SAT solver limits + pParams->nTotalBacktrackLimit = 0; // global limit on the number of backtracks + pParams->nTotalInspectLimit = 0; // global limit on the number of clause inspects +// pParams->nTotalInspectLimit = 100000000; // global limit on the number of clause inspects +} + +/**Function************************************************************* + + Synopsis [Prints out the current values of CEC engine parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Prove_ParamsPrint( Prove_Params_t * pParams ) +{ + printf( "CEC enging parameters:\n" ); + printf( "Fraiging enabled: %s\n", pParams->fUseFraiging? "yes":"no" ); + printf( "Rewriting enabled: %s\n", pParams->fUseRewriting? "yes":"no" ); + printf( "BDD construction enabled: %s\n", pParams->fUseBdds? "yes":"no" ); + printf( "Verbose output enabled: %s\n", pParams->fVerbose? "yes":"no" ); + printf( "Solver iterations: %d\n", pParams->nItersMax ); + printf( "Starting mitering limit: %d\n", pParams->nMiteringLimitStart ); + printf( "Multiplicative coeficient for mitering: %.2f\n", pParams->nMiteringLimitMulti ); + printf( "Starting number of rewriting iterations: %d\n", pParams->nRewritingLimitStart ); + printf( "Multiplicative coeficient for rewriting: %.2f\n", pParams->nRewritingLimitMulti ); + printf( "Starting number of conflicts in fraiging: %d\n", pParams->nFraigingLimitMulti ); + printf( "Multiplicative coeficient for fraiging: %.2f\n", pParams->nRewritingLimitMulti ); + printf( "BDD size limit for bailing out: %.2f\n", pParams->nBddSizeLimit ); + printf( "BDD reordering enabled: %s\n", pParams->fBddReorder? "yes":"no" ); + printf( "Last-gasp mitering limit: %d\n", pParams->nMiteringLimitLast ); + printf( "Total conflict limit: %d\n", pParams->nTotalBacktrackLimit ); + printf( "Total inspection limit: %d\n", pParams->nTotalInspectLimit ); + printf( "Parameter dump complete.\n" ); +} + +/**Function************************************************************* + + Synopsis [Sets the default parameters of the package.] + + Description [This set of parameters is tuned for equivalence checking.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ) +{ + memset( pParams, 0, sizeof(Fraig_Params_t) ); + pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info + pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info + pParams->nBTLimit = 99; // the max number of backtracks to perform + pParams->nSeconds = 20; // the max number of seconds to solve the miter + pParams->fFuncRed = 1; // performs only one level hashing + pParams->fFeedBack = 1; // enables solver feedback + pParams->fDist1Pats = 1; // enables distance-1 patterns + pParams->fDoSparse = 0; // performs equiv tests for sparse functions + pParams->fChoicing = 0; // enables recording structural choices + pParams->fTryProve = 1; // tries to solve the final miter + pParams->fVerbose = 0; // the verbosiness flag + pParams->fVerboseP = 0; // the verbose flag for reporting the proof + pParams->fInternal = 0; // the flag indicates the internal run + pParams->nConfLimit = 0; // the limit on the number of conflicts + pParams->nInspLimit = 0; // the limit on the number of inspections +} + +/**Function************************************************************* + + Synopsis [Sets the default parameters of the package.] + + Description [This set of parameters is tuned for complete FRAIGing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams ) +{ + memset( pParams, 0, sizeof(Fraig_Params_t) ); + pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info + pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info + pParams->nBTLimit = -1; // the max number of backtracks to perform + pParams->nSeconds = 20; // the max number of seconds to solve the miter + pParams->fFuncRed = 1; // performs only one level hashing + pParams->fFeedBack = 1; // enables solver feedback + pParams->fDist1Pats = 1; // enables distance-1 patterns + pParams->fDoSparse = 1; // performs equiv tests for sparse functions + pParams->fChoicing = 0; // enables recording structural choices + pParams->fTryProve = 0; // tries to solve the final miter + pParams->fVerbose = 0; // the verbosiness flag + pParams->fVerboseP = 0; // the verbose flag for reporting the proof + pParams->fInternal = 0; // the flag indicates the internal run + pParams->nConfLimit = 0; // the limit on the number of conflicts + pParams->nInspLimit = 0; // the limit on the number of inspections +} + +/**Function************************************************************* + + Synopsis [Creates the new FRAIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ) +{ + Fraig_Params_t Params; + Fraig_Man_t * p; + + // set the random seed for simulation +// srand( 0xFEEDDEAF ); + srand( 0xDEADCAFE ); + + // set parameters for equivalence checking + if ( pParams == NULL ) + Fraig_ParamsSetDefault( pParams = &Params ); + // adjust the amount of simulation info + if ( pParams->nPatsRand < 128 ) + pParams->nPatsRand = 128; + if ( pParams->nPatsRand > 32768 ) + pParams->nPatsRand = 32768; + if ( pParams->nPatsDyna < 128 ) + pParams->nPatsDyna = 128; + if ( pParams->nPatsDyna > 32768 ) + pParams->nPatsDyna = 32768; + // if reduction is not performed, allocate minimum simulation info + if ( !pParams->fFuncRed ) + pParams->nPatsRand = pParams->nPatsDyna = 128; + + // start the manager + p = ALLOC( Fraig_Man_t, 1 ); + memset( p, 0, sizeof(Fraig_Man_t) ); + + // set the default parameters + p->nWordsRand = FRAIG_NUM_WORDS( pParams->nPatsRand ); // the number of words of random simulation info + p->nWordsDyna = FRAIG_NUM_WORDS( pParams->nPatsDyna ); // the number of patterns for dynamic simulation info + p->nBTLimit = pParams->nBTLimit; // -1 means infinite backtrack limit + p->nSeconds = pParams->nSeconds; // the timeout for the final miter + p->fFuncRed = pParams->fFuncRed; // enables functional reduction (otherwise, only one-level hashing is performed) + p->fFeedBack = pParams->fFeedBack; // enables solver feedback (the use of counter-examples in simulation) + p->fDist1Pats = pParams->fDist1Pats; // enables solver feedback (the use of counter-examples in simulation) + p->fDoSparse = pParams->fDoSparse; // performs equivalence checking for sparse functions (whose sim-info is 0) + p->fChoicing = pParams->fChoicing; // disable accumulation of structural choices (keeps only the first choice) + p->fTryProve = pParams->fTryProve; // disable accumulation of structural choices (keeps only the first choice) + p->fVerbose = pParams->fVerbose; // disable verbose output + p->fVerboseP = pParams->fVerboseP; // disable verbose output + p->nInspLimit = pParams->nInspLimit; // the limit on the number of inspections + + // start memory managers + p->mmNodes = Fraig_MemFixedStart( sizeof(Fraig_Node_t) ); + p->mmSims = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); + // allocate node arrays + p->vInputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary inputs + p->vOutputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary outputs + p->vNodes = Fraig_NodeVecAlloc( 1000 ); // the array of internal nodes + // start the tables + p->pTableS = Fraig_HashTableCreate( 1000 ); // hashing by structure + p->pTableF = Fraig_HashTableCreate( 1000 ); // hashing by function + p->pTableF0 = Fraig_HashTableCreate( 1000 ); // hashing by function (for sparse functions) + // create the constant node + p->pConst1 = Fraig_NodeCreateConst( p ); + // initialize SAT solver feedback data structures + Fraig_FeedBackInit( p ); + // initialize other variables + p->vProj = Msat_IntVecAlloc( 10 ); + p->nTravIds = 1; + p->nTravIds2 = 1; + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManFree( Fraig_Man_t * p ) +{ + int i; + if ( p->fVerbose ) + { + if ( p->fChoicing ) Fraig_ManReportChoices( p ); + Fraig_ManPrintStats( p ); +// Fraig_TablePrintStatsS( p ); +// Fraig_TablePrintStatsF( p ); +// Fraig_TablePrintStatsF0( p ); + } + + for ( i = 0; i < p->vNodes->nSize; i++ ) + if ( p->vNodes->pArray[i]->vFanins ) + { + Fraig_NodeVecFree( p->vNodes->pArray[i]->vFanins ); + p->vNodes->pArray[i]->vFanins = NULL; + } + + if ( p->vInputs ) Fraig_NodeVecFree( p->vInputs ); + if ( p->vNodes ) Fraig_NodeVecFree( p->vNodes ); + if ( p->vOutputs ) Fraig_NodeVecFree( p->vOutputs ); + + if ( p->pTableS ) Fraig_HashTableFree( p->pTableS ); + if ( p->pTableF ) Fraig_HashTableFree( p->pTableF ); + if ( p->pTableF0 ) Fraig_HashTableFree( p->pTableF0 ); + + if ( p->pSat ) Msat_SolverFree( p->pSat ); + if ( p->vProj ) Msat_IntVecFree( p->vProj ); + if ( p->vCones ) Fraig_NodeVecFree( p->vCones ); + if ( p->vPatsReal ) Msat_IntVecFree( p->vPatsReal ); + if ( p->pModel ) free( p->pModel ); + + Fraig_MemFixedStop( p->mmNodes, 0 ); + Fraig_MemFixedStop( p->mmSims, 0 ); + + if ( p->pSuppS ) + { + FREE( p->pSuppS[0] ); + FREE( p->pSuppS ); + } + if ( p->pSuppF ) + { + FREE( p->pSuppF[0] ); + FREE( p->pSuppF ); + } + + FREE( p->ppOutputNames ); + FREE( p->ppInputNames ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Prepares the SAT solver to run on the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManCreateSolver( Fraig_Man_t * p ) +{ + extern int timeSelect; + extern int timeAssign; + assert( p->pSat == NULL ); + // allocate data for SAT solving + p->pSat = Msat_SolverAlloc( 500, 1, 1, 1, 1, 0 ); + p->vVarsInt = Msat_SolverReadConeVars( p->pSat ); + p->vAdjacents = Msat_SolverReadAdjacents( p->pSat ); + p->vVarsUsed = Msat_SolverReadVarsUsed( p->pSat ); + timeSelect = 0; + timeAssign = 0; +} + + +/**Function************************************************************* + + Synopsis [Deallocates the mapping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManPrintStats( Fraig_Man_t * p ) +{ + double nMemory; + int clk = clock(); + nMemory = ((double)(p->vInputs->nSize + p->vNodes->nSize) * + (sizeof(Fraig_Node_t) + sizeof(unsigned)*(p->nWordsRand + p->nWordsDyna) /*+ p->nSuppWords*sizeof(unsigned)*/))/(1<<20); + printf( "Words: Random = %d. Dynamic = %d. Used = %d. Memory = %0.2f Mb.\n", + p->nWordsRand, p->nWordsDyna, p->iWordPerm, nMemory ); + printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", + p->nSatProof, p->nSatCounter, p->nSatFails, p->nSatFailsReal, p->nSatZeros ); + printf( "Nodes: Final = %d. Total = %d. Mux = %d. (Exor = %d.) ClaVars = %d.\n", + Fraig_CountNodes(p,0), p->vNodes->nSize, Fraig_ManCountMuxes(p), Fraig_ManCountExors(p), p->nVarsClauses ); + if ( p->pSat ) Msat_SolverPrintStats( p->pSat ); + Fraig_PrintTime( "AIG simulation ", p->timeSims ); + Fraig_PrintTime( "AIG traversal ", p->timeTrav ); + Fraig_PrintTime( "Solver feedback ", p->timeFeed ); + Fraig_PrintTime( "SAT solving ", p->timeSat ); + Fraig_PrintTime( "Network update ", p->timeToNet ); + Fraig_PrintTime( "TOTAL RUNTIME ", p->timeTotal ); + if ( p->time1 > 0 ) { Fraig_PrintTime( "time1", p->time1 ); } + if ( p->time2 > 0 ) { Fraig_PrintTime( "time2", p->time2 ); } + if ( p->time3 > 0 ) { Fraig_PrintTime( "time3", p->time3 ); } + if ( p->time4 > 0 ) { Fraig_PrintTime( "time4", p->time4 ); } +// PRT( "Selection ", timeSelect ); +// PRT( "Assignment", timeAssign ); +} + +/**Function************************************************************* + + Synopsis [Allocates simulation information for all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_UtilInfoAlloc( int nSize, int nWords, bool fClean ) +{ + Fraig_NodeVec_t * vInfo; + unsigned * pUnsigned; + int i; + assert( nSize > 0 && nWords > 0 ); + vInfo = Fraig_NodeVecAlloc( nSize ); + pUnsigned = ALLOC( unsigned, nSize * nWords ); + vInfo->pArray[0] = (Fraig_Node_t *)pUnsigned; + if ( fClean ) + memset( pUnsigned, 0, sizeof(unsigned) * nSize * nWords ); + for ( i = 1; i < nSize; i++ ) + vInfo->pArray[i] = (Fraig_Node_t *)(((unsigned *)vInfo->pArray[i-1]) + nWords); + vInfo->nSize = nSize; + return vInfo; +} + +/**Function************************************************************* + + Synopsis [Returns simulation info of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p ) +{ + Fraig_NodeVec_t * vInfo; + Fraig_Node_t * pNode; + unsigned * pUnsigned; + int nRandom, nDynamic; + int i, k, nWords; + + nRandom = Fraig_ManReadPatternNumRandom( p ); + nDynamic = Fraig_ManReadPatternNumDynamic( p ); + nWords = nRandom / 32 + nDynamic / 32; + + vInfo = Fraig_UtilInfoAlloc( p->vNodes->nSize, nWords, 0 ); + for ( i = 0; i < p->vNodes->nSize; i++ ) + { + pNode = p->vNodes->pArray[i]; + assert( i == pNode->Num ); + pUnsigned = (unsigned *)vInfo->pArray[i]; + for ( k = 0; k < nRandom / 32; k++ ) + pUnsigned[k] = pNode->puSimR[k]; + for ( k = 0; k < nDynamic / 32; k++ ) + pUnsigned[nRandom / 32 + k] = pNode->puSimD[k]; + } + return vInfo; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if A v B is always true based on the siminfo.] + + Description [A v B is always true iff A' * B' is always false.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ) +{ + int fCompl1, fCompl2, i; + + fCompl1 = 1 ^ Fraig_IsComplement(pNode1) ^ Fraig_Regular(pNode1)->fInv; + fCompl2 = 1 ^ Fraig_IsComplement(pNode2) ^ Fraig_Regular(pNode2)->fInv; + + pNode1 = Fraig_Regular(pNode1); + pNode2 = Fraig_Regular(pNode2); + assert( pNode1 != pNode2 ); + + // check the simulation info + if ( fCompl1 && fCompl2 ) + { + for ( i = 0; i < p->nWordsRand; i++ ) + if ( ~pNode1->puSimR[i] & ~pNode2->puSimR[i] ) + return 0; + for ( i = 0; i < p->iWordStart; i++ ) + if ( ~pNode1->puSimD[i] & ~pNode2->puSimD[i] ) + return 0; + return 1; + } + if ( !fCompl1 && fCompl2 ) + { + for ( i = 0; i < p->nWordsRand; i++ ) + if ( pNode1->puSimR[i] & ~pNode2->puSimR[i] ) + return 0; + for ( i = 0; i < p->iWordStart; i++ ) + if ( pNode1->puSimD[i] & ~pNode2->puSimD[i] ) + return 0; + return 1; + } + if ( fCompl1 && !fCompl2 ) + { + for ( i = 0; i < p->nWordsRand; i++ ) + if ( ~pNode1->puSimR[i] & pNode2->puSimR[i] ) + return 0; + for ( i = 0; i < p->iWordStart; i++ ) + if ( ~pNode1->puSimD[i] & pNode2->puSimD[i] ) + return 0; + return 1; + } +// if ( fCompl1 && fCompl2 ) + { + for ( i = 0; i < p->nWordsRand; i++ ) + if ( pNode1->puSimR[i] & pNode2->puSimR[i] ) + return 0; + for ( i = 0; i < p->iWordStart; i++ ) + if ( pNode1->puSimD[i] & pNode2->puSimD[i] ) + return 0; + return 1; + } +} + +/**Function************************************************************* + + Synopsis [Adds clauses to the solver.] + + Description [This procedure is used to add external clauses to the solver. + The clauses are given by sets of nodes. Each node stands for one literal. + If the node is complemented, the literal is negated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes ) +{ + Fraig_Node_t * pNode; + int i, fComp, RetValue; + if ( p->pSat == NULL ) + Fraig_ManCreateSolver( p ); + // create four clauses + Msat_IntVecClear( p->vProj ); + for ( i = 0; i < nNodes; i++ ) + { + pNode = Fraig_Regular(ppNodes[i]); + fComp = Fraig_IsComplement(ppNodes[i]); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); +// printf( "%d(%d) ", pNode->Num, fComp ); + } +// printf( "\n" ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/sat/fraig/fraigMem.c b/abc70930/src/sat/fraig/fraigMem.c new file mode 100644 index 00000000..500431c6 --- /dev/null +++ b/abc70930/src/sat/fraig/fraigMem.c @@ -0,0 +1,246 @@ +/**CFile**************************************************************** + + FileName [fraigMem.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Fixed-size-entry memory manager for the FRAIG package.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigMem.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Fraig_MemFixed_t_ +{ + // information about individual entries + int nEntrySize; // the size of one entry + int nEntriesAlloc; // the total number of entries allocated + int nEntriesUsed; // the number of entries in use + int nEntriesMax; // the max number of entries in use + char * pEntriesFree; // the linked list of free entries + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the internal memory manager.] + + Description [Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize ) +{ + Fraig_MemFixed_t * p; + + p = ALLOC( Fraig_MemFixed_t, 1 ); + memset( p, 0, sizeof(Fraig_MemFixed_t) ); + + p->nEntrySize = nEntrySize; + p->nEntriesAlloc = 0; + p->nEntriesUsed = 0; + p->pEntriesFree = NULL; + + if ( nEntrySize * (1 << 10) < (1<<16) ) + p->nChunkSize = (1 << 10); + else + p->nChunkSize = (1<<16) / nEntrySize; + if ( p->nChunkSize < 8 ) + p->nChunkSize = 8; + + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", + p->nEntrySize, p->nChunkSize, p->nChunks ); + printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", + p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Extracts one entry from the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p ) +{ + char * pTemp; + int i; + + // check if there are still free entries + if ( p->nEntriesUsed == p->nEntriesAlloc ) + { // need to allocate more entries + assert( p->pEntriesFree == NULL ); + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); + p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; + // transform these entries into a linked list + pTemp = p->pEntriesFree; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pEntriesFree; + // add to the number of entries allocated + p->nEntriesAlloc += p->nChunkSize; + } + // incrememt the counter of used entries + p->nEntriesUsed++; + if ( p->nEntriesMax < p->nEntriesUsed ) + p->nEntriesMax = p->nEntriesUsed; + // return the first entry in the free entry list + pTemp = p->pEntriesFree; + p->pEntriesFree = *((char **)pTemp); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [Returns one entry into the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry ) +{ + // decrement the counter of used entries + p->nEntriesUsed--; + // add the entry to the linked list of free entries + *((char **)pEntry) = p->pEntriesFree; + p->pEntriesFree = pEntry; +} + +/**Function************************************************************* + + Synopsis [Frees all associated memory and resets the manager.] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_MemFixedRestart( Fraig_MemFixed_t * p ) +{ + int i; + char * pTemp; + + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + p->nChunks = 1; + // transform these entries into a linked list + pTemp = p->pChunks[0]; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // set the free entry list + p->pEntriesFree = p->pChunks[0]; + // set the correct statistics + p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; + p->nMemoryUsed = 0; + p->nEntriesAlloc = p->nChunkSize; + p->nEntriesUsed = 0; +} + +/**Function************************************************************* + + Synopsis [Reports the memory usage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p ) +{ + return p->nMemoryAlloc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/fraig/fraigNode.c b/abc70930/src/sat/fraig/fraigNode.c new file mode 100644 index 00000000..6e3d3c7d --- /dev/null +++ b/abc70930/src/sat/fraig/fraigNode.c @@ -0,0 +1,313 @@ +/**CFile**************************************************************** + + FileName [fraigNode.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Implementation of the FRAIG node.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigNode.c,v 1.3 2005/07/08 01:01:32 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// returns the complemented attribute of the node +#define Fraig_NodeIsSimComplement(p) (Fraig_IsComplement(p)? !(Fraig_Regular(p)->fInv) : (p)->fInv) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p ) +{ + Fraig_Node_t * pNode; + + // create the node + pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); + memset( pNode, 0, sizeof(Fraig_Node_t) ); + + // assign the number and add to the array of nodes + pNode->Num = p->vNodes->nSize; + Fraig_NodeVecPush( p->vNodes, pNode ); + pNode->NumPi = -1; // this is not a PI, so its number is -1 + pNode->Level = 0; // just like a PI, it has 0 level + pNode->nRefs = 1; // it is a persistent node, which comes referenced + pNode->fInv = 1; // the simulation info is complemented + + // create the simulation info + pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + pNode->puSimD = pNode->puSimR + p->nWordsRand; + memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); + memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); + + // count the number of ones in the simulation vector + pNode->nOnes = p->nWordsRand * sizeof(unsigned) * 8; + + // insert it into the hash table + Fraig_HashTableLookupF0( p, pNode ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates a primary input node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ) +{ + Fraig_Node_t * pNode, * pNodeRes; + int i, clk; + + // create the node + pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); + memset( pNode, 0, sizeof(Fraig_Node_t) ); + pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + pNode->puSimD = pNode->puSimR + p->nWordsRand; + memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); + + // assign the number and add to the array of nodes + pNode->Num = p->vNodes->nSize; + Fraig_NodeVecPush( p->vNodes, pNode ); + + // assign the PI number and add to the array of primary inputs + pNode->NumPi = p->vInputs->nSize; + Fraig_NodeVecPush( p->vInputs, pNode ); + + pNode->Level = 0; // PI has 0 level + pNode->nRefs = 1; // it is a persistent node, which comes referenced + pNode->fInv = 0; // the simulation info of the PI is not complemented + + // derive the simulation info for the new node +clk = clock(); + // set the random simulation info for the primary input + pNode->uHashR = 0; + for ( i = 0; i < p->nWordsRand; i++ ) + { + // generate the simulation info + pNode->puSimR[i] = FRAIG_RANDOM_UNSIGNED; + // for reasons that take very long to explain, it makes sense to have (0000000...) + // pattern in the set (this helps if we need to return the counter-examples) + if ( i == 0 ) + pNode->puSimR[i] <<= 1; + // compute the hash key + pNode->uHashR ^= pNode->puSimR[i] * s_FraigPrimes[i]; + } + // count the number of ones in the simulation vector + pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); + + // set the systematic simulation info for the primary input + pNode->uHashD = 0; + for ( i = 0; i < p->iWordStart; i++ ) + { + // generate the simulation info + pNode->puSimD[i] = FRAIG_RANDOM_UNSIGNED; + // compute the hash key + pNode->uHashD ^= pNode->puSimD[i] * s_FraigPrimes[i]; + } +p->timeSims += clock() - clk; + + // insert it into the hash table + pNodeRes = Fraig_HashTableLookupF( p, pNode ); + assert( pNodeRes == NULL ); + // add to the runtime of simulation + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates a new node.] + + Description [This procedure should be called to create the constant + node and the PI nodes first.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) +{ + Fraig_Node_t * pNode; + int clk; + + // create the node + pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); + memset( pNode, 0, sizeof(Fraig_Node_t) ); + + // assign the children + pNode->p1 = p1; Fraig_Ref(p1); Fraig_Regular(p1)->nRefs++; + pNode->p2 = p2; Fraig_Ref(p2); Fraig_Regular(p2)->nRefs++; + + // assign the number and add to the array of nodes + pNode->Num = p->vNodes->nSize; + Fraig_NodeVecPush( p->vNodes, pNode ); + + // assign the PI number + pNode->NumPi = -1; + + // compute the level of this node + pNode->Level = 1 + FRAIG_MAX(Fraig_Regular(p1)->Level, Fraig_Regular(p2)->Level); + pNode->fInv = Fraig_NodeIsSimComplement(p1) & Fraig_NodeIsSimComplement(p2); + pNode->fFailTfo = Fraig_Regular(p1)->fFailTfo | Fraig_Regular(p2)->fFailTfo; + + // derive the simulation info +clk = clock(); + // allocate memory for the simulation info + pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); + pNode->puSimD = pNode->puSimR + p->nWordsRand; + // derive random simulation info + pNode->uHashR = 0; + Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); + // derive dynamic simulation info + pNode->uHashD = 0; + Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); + // count the number of ones in the random simulation info + pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); + if ( pNode->fInv ) + pNode->nOnes = p->nWordsRand * 32 - pNode->nOnes; + // add to the runtime of simulation +p->timeSims += clock() - clk; + +#ifdef FRAIG_ENABLE_FANOUTS + // create the fanout info + Fraig_NodeAddFaninFanout( Fraig_Regular(p1), pNode ); + Fraig_NodeAddFaninFanout( Fraig_Regular(p2), pNode ); +#endif + return pNode; +} + + +/**Function************************************************************* + + Synopsis [Simulates the node.] + + Description [Simulates the random or dynamic simulation info through + the node. Uses phases of the children to determine their real simulation + info. Uses phase of the node to determine the way its simulation info + is stored. The resulting info is guaranteed to be 0 for the first pattern.] + + SideEffects [This procedure modified the hash value of the simulation info.] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand ) +{ + unsigned * pSims, * pSims1, * pSims2; + unsigned uHash; + int fCompl, fCompl1, fCompl2, i; + + assert( !Fraig_IsComplement(pNode) ); + + // get hold of the simulation information + pSims = fUseRand? pNode->puSimR : pNode->puSimD; + pSims1 = fUseRand? Fraig_Regular(pNode->p1)->puSimR : Fraig_Regular(pNode->p1)->puSimD; + pSims2 = fUseRand? Fraig_Regular(pNode->p2)->puSimR : Fraig_Regular(pNode->p2)->puSimD; + + // get complemented attributes of the children using their random info + fCompl = pNode->fInv; + fCompl1 = Fraig_NodeIsSimComplement(pNode->p1); + fCompl2 = Fraig_NodeIsSimComplement(pNode->p2); + + // simulate + uHash = 0; + if ( fCompl1 && fCompl2 ) + { + if ( fCompl ) + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (pSims1[i] | pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + else + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = ~(pSims1[i] | pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + } + else if ( fCompl1 && !fCompl2 ) + { + if ( fCompl ) + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (pSims1[i] | ~pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + else + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (~pSims1[i] & pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + } + else if ( !fCompl1 && fCompl2 ) + { + if ( fCompl ) + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (~pSims1[i] | pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + else + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (pSims1[i] & ~pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + } + else // if ( !fCompl1 && !fCompl2 ) + { + if ( fCompl ) + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = ~(pSims1[i] & pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + else + for ( i = iWordStart; i < iWordStop; i++ ) + { + pSims[i] = (pSims1[i] & pSims2[i]); + uHash ^= pSims[i] * s_FraigPrimes[i]; + } + } + + if ( fUseRand ) + pNode->uHashR ^= uHash; + else + pNode->uHashD ^= uHash; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/sat/fraig/fraigPrime.c b/abc70930/src/sat/fraig/fraigPrime.c new file mode 100644 index 00000000..127ad478 --- /dev/null +++ b/abc70930/src/sat/fraig/fraigPrime.c @@ -0,0 +1,144 @@ +/**CFile**************************************************************** + + FileName [fraigPrime.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [The table of the first 1000 primes.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigPrime.c,v 1.4 2005/07/08 01:01:32 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// The 1,024 smallest prime numbers used to compute the hash value +// http://www.math.utah.edu/~alfeld/math/primelist.html +int s_FraigPrimes[FRAIG_MAX_PRIMES] = { 2, 3, 5, +7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, +101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, +193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, +293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, +409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, +521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, +641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, +757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, +881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, +1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, +1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, +1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, +1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, +1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, +1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, +1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, +1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, +1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, +1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, +2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, +2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, +2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, +2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, +2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, +2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, +2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, +2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, +2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, +3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, +3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, +3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, +3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, +3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, +3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, +3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, +3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, +3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, +4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, +4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, +4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, +4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, +4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, +4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, +4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, +4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, +5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, +5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, +5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, +5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, +5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, +5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, +5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, +5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, +6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, +6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, +6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, +6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, +6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, +6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, +6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, +6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, +6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, +7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, +7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, +7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, +7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, +7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, +7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, +7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, +8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, +8147, 8161 }; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function******************************************************************** + + Synopsis [Returns the next prime >= p.] + + Description [Copied from CUDD, for stand-aloneness.] + + SideEffects [None] + + SeeAlso [] + +******************************************************************************/ +unsigned int Cudd_PrimeFraig( unsigned int p) +{ + int i,pn; + + p--; + do { + p++; + if (p&1) { + pn = 1; + i = 3; + while ((unsigned) (i * i) <= p) { + if (p % i == 0) { + pn = 0; + break; + } + i += 2; + } + } else { + pn = 0; + } + } while (!pn); + return(p); + +} /* end of Cudd_Prime */ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/fraig/fraigSat.c b/abc70930/src/sat/fraig/fraigSat.c new file mode 100644 index 00000000..53057fc3 --- /dev/null +++ b/abc70930/src/sat/fraig/fraigSat.c @@ -0,0 +1,1455 @@ +/**CFile**************************************************************** + + FileName [fraigSat.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Proving functional equivalence using SAT.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigSat.c,v 1.10 2005/07/08 01:01:32 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" +#include "math.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +static void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ); +static void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ); +static void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); +static void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); + +static void Fraig_SupergateAddClauses( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper ); +static void Fraig_SupergateAddClausesExor( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +static void Fraig_SupergateAddClausesMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +//static void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +static void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); +static void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); + +extern void * Msat_ClauseVecReadEntry( void * p, int i ); + +// The lesson learned seems to be that variable should be in reverse topological order +// from the output of the miter. The ordering of adjacency lists is very important. +// The best way seems to be fanins followed by fanouts. Slight changes to this order +// leads to big degradation in quality. + +static int nMuxes; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks equivalence of two nodes.] + + Description [Returns 1 iff the nodes are equivalent.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit ) +{ + if ( pNode1 == pNode2 ) + return 1; + if ( pNode1 == Fraig_Not(pNode2) ) + return 0; + return Fraig_NodeIsEquivalent( p, Fraig_Regular(pNode1), Fraig_Regular(pNode2), nBTLimit, nTimeLimit ); +} + +/**Function************************************************************* + + Synopsis [Tries to prove the final miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManProveMiter( Fraig_Man_t * p ) +{ + Fraig_Node_t * pNode; + int i, clk; + + if ( !p->fTryProve ) + return; + + clk = clock(); + // consider all outputs of the multi-output miter + for ( i = 0; i < p->vOutputs->nSize; i++ ) + { + pNode = Fraig_Regular(p->vOutputs->pArray[i]); + // skip already constant nodes + if ( pNode == p->pConst1 ) + continue; + // skip nodes that are different according to simulation + if ( !Fraig_CompareSimInfo( pNode, p->pConst1, p->nWordsRand, 1 ) ) + continue; + if ( Fraig_NodeIsEquivalent( p, p->pConst1, pNode, -1, p->nSeconds ) ) + { + if ( Fraig_IsComplement(p->vOutputs->pArray[i]) ^ Fraig_NodeComparePhase(p->pConst1, pNode) ) + p->vOutputs->pArray[i] = Fraig_Not(p->pConst1); + else + p->vOutputs->pArray[i] = p->pConst1; + } + } + if ( p->fVerboseP ) + { +// PRT( "Final miter proof time", clock() - clk ); + } +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the miter is unsat; 0 if sat; -1 if undecided.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManCheckMiter( Fraig_Man_t * p ) +{ + Fraig_Node_t * pNode; + int i; + FREE( p->pModel ); + for ( i = 0; i < p->vOutputs->nSize; i++ ) + { + // get the output node (it can be complemented!) + pNode = p->vOutputs->pArray[i]; + // if the miter is constant 0, the problem is UNSAT + if ( pNode == Fraig_Not(p->pConst1) ) + continue; + // consider the special case when the miter is constant 1 + if ( pNode == p->pConst1 ) + { + // in this case, any counter example will do to distinquish it from constant 0 + // here we pick the counter example composed of all zeros + p->pModel = Fraig_ManAllocCounterExample( p ); + return 0; + } + // save the counter example + p->pModel = Fraig_ManSaveCounterExample( p, pNode ); + // if the model is not found, return undecided + if ( p->pModel == NULL ) + return -1; + else + return 0; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_MarkTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return 0; + pNode->TravId = pMan->nTravIds; + // skip the PI node + if ( pNode->NumPi >= 0 ) + return 1; + // check the children + return Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p1) ) + + Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p2) ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_MarkTfi2_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return 0; + // skip the boundary node + if ( pNode->TravId == pMan->nTravIds-1 ) + { + pNode->TravId = pMan->nTravIds; + return 1; + } + pNode->TravId = pMan->nTravIds; + // skip the PI node + if ( pNode->NumPi >= 0 ) + return 1; + // check the children + return Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p1) ) + + Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p2) ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_MarkTfi3_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return 1; + // skip the boundary node + if ( pNode->TravId == pMan->nTravIds-1 ) + { + pNode->TravId = pMan->nTravIds; + return 1; + } + pNode->TravId = pMan->nTravIds; + // skip the PI node + if ( pNode->NumPi >= 0 ) + return 0; + // check the children + return Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p1) ) * + Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p2) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_VarsStudy( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + int NumPis, NumCut, fContain; + + // mark the TFI of pNew + p->nTravIds++; + NumPis = Fraig_MarkTfi_rec( p, pNew ); + printf( "(%d)(%d,%d):", NumPis, pOld->Level, pNew->Level ); + + // check if the old is in the TFI + if ( pOld->TravId == p->nTravIds ) + { + printf( "* " ); + return; + } + + // count the boundary of nodes in pOld + p->nTravIds++; + NumCut = Fraig_MarkTfi2_rec( p, pOld ); + printf( "%d", NumCut ); + + // check if the new is contained in the old's support + p->nTravIds++; + fContain = Fraig_MarkTfi3_rec( p, pNew ); + printf( "%c ", fContain? '+':'-' ); +} + + +/**Function************************************************************* + + Synopsis [Checks whether two nodes are functinally equivalent.] + + Description [The flag (fComp) tells whether the nodes to be checked + are in the opposite polarity. The second flag (fSkipZeros) tells whether + the checking should be performed if the simulation vectors are zeros. + Returns 1 if the nodes are equivalent; 0 othewise.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit ) +{ + int RetValue, RetValue1, i, fComp, clk; + int fVerbose = 0; + int fSwitch = 0; + + // make sure the nodes are not complemented + assert( !Fraig_IsComplement(pNew) ); + assert( !Fraig_IsComplement(pOld) ); + assert( pNew != pOld ); + + // if at least one of the nodes is a failed node, perform adjustments: + // if the backtrack limit is small, simply skip this node + // if the backtrack limit is > 10, take the quare root of the limit + if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) + { + p->nSatFails++; +// return 0; +// if ( nBTLimit > 10 ) +// nBTLimit /= 10; + if ( nBTLimit <= 10 ) + return 0; + nBTLimit = (int)sqrt(nBTLimit); +// fSwitch = 1; + } + + p->nSatCalls++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + Fraig_ManCreateSolver( p ); + // make sure the SAT solver has enough variables + for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) + Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); + + + +/* + { + Fraig_Node_t * ppNodes[2] = { pOld, pNew }; + extern void Fraig_MappingShowNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppRoots, int nRoots, char * pFileName ); + Fraig_MappingShowNodes( p, ppNodes, 2, "temp_aig" ); + } +*/ + + nMuxes = 0; + + + // get the logic cone +clk = clock(); +// Fraig_VarsStudy( p, pOld, pNew ); + Fraig_OrderVariables( p, pOld, pNew ); +// Fraig_PrepareCones( p, pOld, pNew ); +p->timeTrav += clock() - clk; + +// printf( "The number of MUXes detected = %d (%5.2f %% of logic). ", nMuxes, 300.0*nMuxes/(p->vNodes->nSize - p->vInputs->nSize) ); +// PRT( "Time", clock() - clk ); + +if ( fVerbose ) + printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) ); + + + // prepare variable activity + Fraig_SetActivity( p, pOld, pNew ); + + // get the complemented attribute + fComp = Fraig_NodeComparePhase( pOld, pNew ); +//Msat_SolverPrintClauses( p->pSat ); + + //////////////////////////////////////////// + // prepare the solver to run incrementally on these variables +//clk = clock(); + Msat_SolverPrepare( p->pSat, p->vVarsInt ); +//p->time3 += clock() - clk; + + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); + +//Msat_SolverWriteDimacs( p->pSat, "temp_fraig.cnf" ); + + // run the solver +clk = clock(); + RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit ); +p->timeSat += clock() - clk; + + if ( RetValue1 == MSAT_FALSE ) + { +//p->time1 += clock() - clk; + +if ( fVerbose ) +{ + printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); +PRT( "time", clock() - clk ); +} + + // add the clause + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + // continue solving the other implication + } + else if ( RetValue1 == MSAT_TRUE ) + { +//p->time2 += clock() - clk; + +if ( fVerbose ) +{ + printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); +PRT( "time", clock() - clk ); +} + + // record the counter example + Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "s(%d)", pNew->Level ); + if ( fSwitch ) + printf( "s(%d)", pNew->Level ); + p->nSatCounter++; + return 0; + } + else // if ( RetValue1 == MSAT_UNKNOWN ) + { +p->time3 += clock() - clk; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "T(%d)", pNew->Level ); + + // mark the node as the failed node + if ( pOld != p->pConst1 ) + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; +// p->nSatFails++; + if ( fSwitch ) + printf( "T(%d)", pNew->Level ); + p->nSatFailsReal++; + return 0; + } + + // if the old node was constant 0, we already know the answer + if ( pOld == p->pConst1 ) + return 1; + + //////////////////////////////////////////// + // prepare the solver to run incrementally +//clk = clock(); + Msat_SolverPrepare( p->pSat, p->vVarsInt ); +//p->time3 += clock() - clk; + // solve under assumptions + // A = 0; B = 1 OR A = 0; B = 0 + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); + // run the solver +clk = clock(); + RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit ); +p->timeSat += clock() - clk; + + if ( RetValue1 == MSAT_FALSE ) + { +//p->time1 += clock() - clk; + +if ( fVerbose ) +{ + printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); +PRT( "time", clock() - clk ); +} + + // add the clause + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + // continue solving the other implication + } + else if ( RetValue1 == MSAT_TRUE ) + { +//p->time2 += clock() - clk; + +if ( fVerbose ) +{ + printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); +PRT( "time", clock() - clk ); +} + + // record the counter example + Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); + p->nSatCounter++; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "s(%d)", pNew->Level ); + if ( fSwitch ) + printf( "s(%d)", pNew->Level ); + return 0; + } + else // if ( RetValue1 == MSAT_UNKNOWN ) + { +p->time3 += clock() - clk; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "T(%d)", pNew->Level ); + if ( fSwitch ) + printf( "T(%d)", pNew->Level ); + + // mark the node as the failed node + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; +// p->nSatFails++; + p->nSatFailsReal++; + return 0; + } + + // return SAT proof + p->nSatProof++; + +// if ( pOld->fFailTfo || pNew->fFailTfo ) +// printf( "*" ); +// printf( "u(%d)", pNew->Level ); + + if ( fSwitch ) + printf( "u(%d)", pNew->Level ); + + return 1; +} + + +/**Function************************************************************* + + Synopsis [Checks whether pOld => pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ) +{ + int RetValue, RetValue1, i, fComp, clk; + int fVerbose = 0; + + // make sure the nodes are not complemented + assert( !Fraig_IsComplement(pNew) ); + assert( !Fraig_IsComplement(pOld) ); + assert( pNew != pOld ); + + p->nSatCallsImp++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + Fraig_ManCreateSolver( p ); + // make sure the SAT solver has enough variables + for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) + Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); + + // get the logic cone +clk = clock(); + Fraig_OrderVariables( p, pOld, pNew ); +// Fraig_PrepareCones( p, pOld, pNew ); +p->timeTrav += clock() - clk; + +if ( fVerbose ) + printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) ); + + + // get the complemented attribute + fComp = Fraig_NodeComparePhase( pOld, pNew ); +//Msat_SolverPrintClauses( p->pSat ); + + //////////////////////////////////////////// + // prepare the solver to run incrementally on these variables +//clk = clock(); + Msat_SolverPrepare( p->pSat, p->vVarsInt ); +//p->time3 += clock() - clk; + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); + // run the solver +clk = clock(); + RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 ); +p->timeSat += clock() - clk; + + if ( RetValue1 == MSAT_FALSE ) + { +//p->time1 += clock() - clk; + +if ( fVerbose ) +{ + printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); +PRT( "time", clock() - clk ); +} + + // add the clause + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); +// p->nSatProofImp++; + return 1; + } + else if ( RetValue1 == MSAT_TRUE ) + { +//p->time2 += clock() - clk; + +if ( fVerbose ) +{ + printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); +PRT( "time", clock() - clk ); +} + // record the counter example + Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); + p->nSatCounterImp++; + return 0; + } + else // if ( RetValue1 == MSAT_UNKNOWN ) + { +p->time3 += clock() - clk; + p->nSatFailsImp++; + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Prepares the SAT solver to run on the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ) +{ + Fraig_Node_t * pNode1R, * pNode2R; + int RetValue, RetValue1, i, clk; + int fVerbose = 0; + + pNode1R = Fraig_Regular(pNode1); + pNode2R = Fraig_Regular(pNode2); + assert( pNode1R != pNode2R ); + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + Fraig_ManCreateSolver( p ); + // make sure the SAT solver has enough variables + for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) + Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); + + // get the logic cone +clk = clock(); + Fraig_OrderVariables( p, pNode1R, pNode2R ); +// Fraig_PrepareCones( p, pNode1R, pNode2R ); +p->timeTrav += clock() - clk; + + //////////////////////////////////////////// + // prepare the solver to run incrementally on these variables +//clk = clock(); + Msat_SolverPrepare( p->pSat, p->vVarsInt ); +//p->time3 += clock() - clk; + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, !Fraig_IsComplement(pNode1)) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, !Fraig_IsComplement(pNode2)) ); + // run the solver +clk = clock(); + RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 ); +p->timeSat += clock() - clk; + + if ( RetValue1 == MSAT_FALSE ) + { +//p->time1 += clock() - clk; + +if ( fVerbose ) +{ + printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); +PRT( "time", clock() - clk ); +} + + // add the clause + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, Fraig_IsComplement(pNode1)) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, Fraig_IsComplement(pNode2)) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); +// p->nSatProofImp++; + return 1; + } + else if ( RetValue1 == MSAT_TRUE ) + { +//p->time2 += clock() - clk; + +if ( fVerbose ) +{ + printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); +PRT( "time", clock() - clk ); +} + // record the counter example +// Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pNode1R, pNode2R ); + p->nSatCounterImp++; + return 0; + } + else // if ( RetValue1 == MSAT_UNKNOWN ) + { +p->time3 += clock() - clk; + p->nSatFailsImp++; + return 0; + } +} + + +/**Function************************************************************* + + Synopsis [Prepares the SAT solver to run on the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ +// Msat_IntVec_t * vAdjs; +// int * pVars, nVars, i, k; + int nVarsAlloc; + + assert( pOld != pNew ); + assert( !Fraig_IsComplement(pOld) ); + assert( !Fraig_IsComplement(pNew) ); + // clean the variables + nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); + Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); + Msat_IntVecClear( pMan->vVarsInt ); + + pMan->nTravIds++; + Fraig_PrepareCones_rec( pMan, pNew ); + Fraig_PrepareCones_rec( pMan, pOld ); + + +/* + nVars = Msat_IntVecReadSize( pMan->vVarsInt ); + pVars = Msat_IntVecReadArray( pMan->vVarsInt ); + for ( i = 0; i < nVars; i++ ) + { + // process its connections + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); + printf( "%d=%d { ", pVars[i], Msat_IntVecReadSize(vAdjs) ); + for ( k = 0; k < Msat_IntVecReadSize(vAdjs); k++ ) + printf( "%d ", Msat_IntVecReadEntry(vAdjs,k) ); + printf( "}\n" ); + + } + i = 0; +*/ +} + +/**Function************************************************************* + + Synopsis [Traverses the cone, collects the numbers and adds the clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pFanin; + Msat_IntVec_t * vAdjs; + int fUseMuxes = 1, i; + int fItIsTime; + + // skip if the node is aleady visited + assert( !Fraig_IsComplement(pNode) ); + if ( pNode->TravId == pMan->nTravIds ) + return; + pNode->TravId = pMan->nTravIds; + + // collect the node's number (closer to reverse topological order) + Msat_IntVecPush( pMan->vVarsInt, pNode->Num ); + Msat_IntVecWriteEntry( pMan->vVarsUsed, pNode->Num, 1 ); + if ( !Fraig_NodeIsAnd( pNode ) ) + return; + + // if the node does not have fanins, create them + fItIsTime = 0; + if ( pNode->vFanins == NULL ) + { + fItIsTime = 1; + // create the fanins of the supergate + assert( pNode->fClauses == 0 ); + if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) + { + pNode->vFanins = Fraig_NodeVecAlloc( 4 ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); + Fraig_SupergateAddClausesMux( pMan, pNode ); + } + else + { + pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); + Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); + } + assert( pNode->vFanins->nSize > 1 ); + pNode->fClauses = 1; + pMan->nVarsClauses++; + + // add fanins + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pNode->Num ); + assert( Msat_IntVecReadSize( vAdjs ) == 0 ); + for ( i = 0; i < pNode->vFanins->nSize; i++ ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); + Msat_IntVecPush( vAdjs, pFanin->Num ); + } + } + + // recursively visit the fanins + for ( i = 0; i < pNode->vFanins->nSize; i++ ) + Fraig_PrepareCones_rec( pMan, Fraig_Regular(pNode->vFanins->pArray[i]) ); + + if ( fItIsTime ) + { + // recursively visit the fanins + for ( i = 0; i < pNode->vFanins->nSize; i++ ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); + Msat_IntVecPush( vAdjs, pNode->Num ); + } + } +} + +/**Function************************************************************* + + Synopsis [Collect variables using their proximity from the nodes.] + + Description [This procedure creates a variable order based on collecting + first the nodes that are the closest to the given two target nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + Fraig_Node_t * pNode, * pFanin; + int i, k, Number, fUseMuxes = 1; + int nVarsAlloc; + + assert( pOld != pNew ); + assert( !Fraig_IsComplement(pOld) ); + assert( !Fraig_IsComplement(pNew) ); + + pMan->nTravIds++; + + // clean the variables + nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); + Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); + Msat_IntVecClear( pMan->vVarsInt ); + + // add the first node + Msat_IntVecPush( pMan->vVarsInt, pOld->Num ); + Msat_IntVecWriteEntry( pMan->vVarsUsed, pOld->Num, 1 ); + pOld->TravId = pMan->nTravIds; + + // add the second node + Msat_IntVecPush( pMan->vVarsInt, pNew->Num ); + Msat_IntVecWriteEntry( pMan->vVarsUsed, pNew->Num, 1 ); + pNew->TravId = pMan->nTravIds; + + // create the variable order + for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ ) + { + // get the new node on the frontier + Number = Msat_IntVecReadEntry(pMan->vVarsInt, i); + pNode = pMan->vNodes->pArray[Number]; + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + + // if the node does not have fanins, create them + if ( pNode->vFanins == NULL ) + { + // create the fanins of the supergate + assert( pNode->fClauses == 0 ); + // detecting a fanout-free cone (experiment only) +// Fraig_DetectFanoutFreeCone( pMan, pNode ); + + if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) + { + pNode->vFanins = Fraig_NodeVecAlloc( 4 ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); + Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); + Fraig_SupergateAddClausesMux( pMan, pNode ); +// Fraig_DetectFanoutFreeConeMux( pMan, pNode ); + + nMuxes++; + } + else + { + pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); + Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); + } + assert( pNode->vFanins->nSize > 1 ); + pNode->fClauses = 1; + pMan->nVarsClauses++; + + pNode->fMark2 = 1; // goes together with Fraig_SetupAdjacentMark() + } + + // explore the implication fanins of pNode + for ( k = 0; k < pNode->vFanins->nSize; k++ ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); + if ( pFanin->TravId == pMan->nTravIds ) // already collected + continue; + // collect and mark + Msat_IntVecPush( pMan->vVarsInt, pFanin->Num ); + Msat_IntVecWriteEntry( pMan->vVarsUsed, pFanin->Num, 1 ); + pFanin->TravId = pMan->nTravIds; + } + } + + // set up the adjacent variable information +// Fraig_SetupAdjacent( pMan, pMan->vVarsInt ); + Fraig_SetupAdjacentMark( pMan, pMan->vVarsInt ); +} + + + +/**Function************************************************************* + + Synopsis [Set up the adjacent variable information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ) +{ + Fraig_Node_t * pNode, * pFanin; + Msat_IntVec_t * vAdjs; + int * pVars, nVars, i, k; + + // clean the adjacents for the variables + nVars = Msat_IntVecReadSize( vConeVars ); + pVars = Msat_IntVecReadArray( vConeVars ); + for ( i = 0; i < nVars; i++ ) + { + // process its connections + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); + Msat_IntVecClear( vAdjs ); + + pNode = pMan->vNodes->pArray[pVars[i]]; + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + + // add fanins + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); + for ( k = 0; k < pNode->vFanins->nSize; k++ ) +// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); + Msat_IntVecPush( vAdjs, pFanin->Num ); +// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); + } + } + // add the fanouts + for ( i = 0; i < nVars; i++ ) + { + pNode = pMan->vNodes->pArray[pVars[i]]; + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + + // add the edges + for ( k = 0; k < pNode->vFanins->nSize; k++ ) +// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); + Msat_IntVecPush( vAdjs, pNode->Num ); +// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); + } + } +} + + +/**Function************************************************************* + + Synopsis [Set up the adjacent variable information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ) +{ + Fraig_Node_t * pNode, * pFanin; + Msat_IntVec_t * vAdjs; + int * pVars, nVars, i, k; + + // clean the adjacents for the variables + nVars = Msat_IntVecReadSize( vConeVars ); + pVars = Msat_IntVecReadArray( vConeVars ); + for ( i = 0; i < nVars; i++ ) + { + pNode = pMan->vNodes->pArray[pVars[i]]; + if ( pNode->fMark2 == 0 ) + continue; +// pNode->fMark2 = 0; + + // process its connections +// vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); +// Msat_IntVecClear( vAdjs ); + + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + + // add fanins + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); + for ( k = 0; k < pNode->vFanins->nSize; k++ ) +// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); + Msat_IntVecPush( vAdjs, pFanin->Num ); +// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); + } + } + // add the fanouts + for ( i = 0; i < nVars; i++ ) + { + pNode = pMan->vNodes->pArray[pVars[i]]; + if ( pNode->fMark2 == 0 ) + continue; + pNode->fMark2 = 0; + + if ( !Fraig_NodeIsAnd(pNode) ) + continue; + + // add the edges + for ( k = 0; k < pNode->vFanins->nSize; k++ ) +// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) + { + pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); + vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); + Msat_IntVecPush( vAdjs, pNode->Num ); +// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); + } + } +} + + + + +/**Function************************************************************* + + Synopsis [Adds clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SupergateAddClauses( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper ) +{ + int fComp1, RetValue, nVars, Var, Var1, i; + + assert( Fraig_NodeIsAnd( pNode ) ); + nVars = Msat_SolverReadVarNum(p->pSat); + + Var = pNode->Num; + assert( Var < nVars ); + for ( i = 0; i < vSuper->nSize; i++ ) + { + // get the predecessor nodes + // get the complemented attributes of the nodes + fComp1 = Fraig_IsComplement(vSuper->pArray[i]); + // determine the variable numbers + Var1 = Fraig_Regular(vSuper->pArray[i])->Num; + // check that the variables are in the SAT manager + assert( Var1 < nVars ); + + // suppose the AND-gate is A * B = C + // add !A => !C or A + !C + // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, fComp1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 1) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + } + + // add A & B => C or !A + !B + C +// fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 ); + Msat_IntVecClear( p->vProj ); + for ( i = 0; i < vSuper->nSize; i++ ) + { + // get the predecessor nodes + // get the complemented attributes of the nodes + fComp1 = Fraig_IsComplement(vSuper->pArray[i]); + // determine the variable numbers + Var1 = Fraig_Regular(vSuper->pArray[i])->Num; + + // add this variable to the array + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, !fComp1) ); + } + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 0) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Adds clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SupergateAddClausesExor( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1, * pNode2; + int fComp, RetValue; + + assert( !Fraig_IsComplement( pNode ) ); + assert( Fraig_NodeIsExorType( pNode ) ); + // get nodes + pNode1 = Fraig_Regular(Fraig_Regular(pNode->p1)->p1); + pNode2 = Fraig_Regular(Fraig_Regular(pNode->p1)->p2); + // get the complemented attribute of the EXOR/NEXOR gate + fComp = Fraig_NodeIsExor( pNode ); // 1 if EXOR, 0 if NEXOR + + // create four clauses + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Adds clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SupergateAddClausesMux( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNodeI, * pNodeT, * pNodeE; + int RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; + + assert( !Fraig_IsComplement( pNode ) ); + assert( Fraig_NodeIsMuxType( pNode ) ); + // get nodes (I = if, T = then, E = else) + pNodeI = Fraig_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the variable numbers + VarF = pNode->Num; + VarI = pNodeI->Num; + VarT = Fraig_Regular(pNodeT)->Num; + VarE = Fraig_Regular(pNodeE)->Num; + // get the complementation flags + fCompT = Fraig_IsComplement(pNodeT); + fCompE = Fraig_IsComplement(pNodeE); + + // f = ITE(i, t, e) + + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + + // create four clauses + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + + // two additional clauses + // t' & e' -> f' + // t & e -> f + + // t + e + f' + // t' + e' + f + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return; + } + + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + Msat_IntVecClear( p->vProj ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) ); + Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); + RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); + assert( RetValue ); + +} + + + + + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_DetectFanoutFreeCone_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst ) +{ + // make the pointer regular + pNode = Fraig_Regular(pNode); + // if the new node is complemented or a PI, another gate begins + if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) ) + { + Fraig_NodeVecPushUnique( vSuper, pNode ); + return; + } + // go through the branches + Fraig_DetectFanoutFreeCone_rec( pNode->p1, vSuper, vInside, 0 ); + Fraig_DetectFanoutFreeCone_rec( pNode->p2, vSuper, vInside, 0 ); + // add the node + Fraig_NodeVecPushUnique( vInside, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_NodeVec_t * vFanins; + Fraig_NodeVec_t * vInside; + int nCubes; + extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside ); + + vFanins = Fraig_NodeVecAlloc( 8 ); + vInside = Fraig_NodeVecAlloc( 8 ); + + Fraig_DetectFanoutFreeCone_rec( pNode, vFanins, vInside, 1 ); + assert( vInside->pArray[vInside->nSize-1] == pNode ); + + nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside ); + +printf( "%d(%d)", vFanins->nSize, nCubes ); + Fraig_NodeVecFree( vFanins ); + Fraig_NodeVecFree( vInside ); +} +*/ + + + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_DetectFanoutFreeConeMux_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst ) +{ + // make the pointer regular + pNode = Fraig_Regular(pNode); + // if the new node is complemented or a PI, another gate begins + if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) || !Fraig_NodeIsMuxType(pNode) ) + { + Fraig_NodeVecPushUnique( vSuper, pNode ); + return; + } + // go through the branches + Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p1, vSuper, vInside, 0 ); + Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p2, vSuper, vInside, 0 ); + Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p1, vSuper, vInside, 0 ); + Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p2, vSuper, vInside, 0 ); + // add the node + Fraig_NodeVecPushUnique( vInside, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_NodeVec_t * vFanins; + Fraig_NodeVec_t * vInside; + int nCubes; + extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside ); + + vFanins = Fraig_NodeVecAlloc( 8 ); + vInside = Fraig_NodeVecAlloc( 8 ); + + Fraig_DetectFanoutFreeConeMux_rec( pNode, vFanins, vInside, 1 ); + assert( vInside->pArray[vInside->nSize-1] == pNode ); + +// nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside ); + nCubes = 0; + +printf( "%d(%d)", vFanins->nSize, nCubes ); + Fraig_NodeVecFree( vFanins ); + Fraig_NodeVecFree( vInside ); +} + + + +/**Function************************************************************* + + Synopsis [Collect variables using their proximity from the nodes.] + + Description [This procedure creates a variable order based on collecting + first the nodes that are the closest to the given two target nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + Fraig_Node_t * pNode; + int i, Number, MaxLevel; + float * pFactors = Msat_SolverReadFactors(pMan->pSat); + if ( pFactors == NULL ) + return; + MaxLevel = FRAIG_MAX( pOld->Level, pNew->Level ); + // create the variable order + for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ ) + { + // get the new node on the frontier + Number = Msat_IntVecReadEntry(pMan->vVarsInt, i); + pNode = pMan->vNodes->pArray[Number]; + pFactors[pNode->Num] = (float)pow( 0.97, MaxLevel - pNode->Level ); +// if ( pNode->Num % 50 == 0 ) +// printf( "(%d) %.2f ", MaxLevel - pNode->Level, pFactors[pNode->Num] ); + } +// printf( "\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/fraig/fraigTable.c b/abc70930/src/sat/fraig/fraigTable.c new file mode 100644 index 00000000..b68bbe0e --- /dev/null +++ b/abc70930/src/sat/fraig/fraigTable.c @@ -0,0 +1,657 @@ +/**CFile**************************************************************** + + FileName [fraigTable.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Structural and functional hash tables.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigTable.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Fraig_TableResizeS( Fraig_HashTable_t * p ); +static void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_HashTable_t * Fraig_HashTableCreate( int nSize ) +{ + Fraig_HashTable_t * p; + // allocate the table + p = ALLOC( Fraig_HashTable_t, 1 ); + memset( p, 0, sizeof(Fraig_HashTable_t) ); + // allocate and clean the bins + p->nBins = Cudd_PrimeFraig(nSize); + p->pBins = ALLOC( Fraig_Node_t *, p->nBins ); + memset( p->pBins, 0, sizeof(Fraig_Node_t *) * p->nBins ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates the supergate hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_HashTableFree( Fraig_HashTable_t * p ) +{ + FREE( p->pBins ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Looks up an entry in the structural hash table.] + + Description [If the entry with the same children does not exists, + creates it, inserts it into the table, and returns 0. If the entry + with the same children exists, finds it, and return 1. In both cases, + the new/old entry is returned in ppNodeRes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes ) +{ + Fraig_HashTable_t * p = pMan->pTableS; + Fraig_Node_t * pEnt; + unsigned Key; + + // order the arguments + if ( Fraig_Regular(p1)->Num > Fraig_Regular(p2)->Num ) + pEnt = p1, p1 = p2, p2 = pEnt; + + Key = Fraig_HashKey2( p1, p2, p->nBins ); + Fraig_TableBinForEachEntryS( p->pBins[Key], pEnt ) + if ( pEnt->p1 == p1 && pEnt->p2 == p2 ) + { + *ppNodeRes = pEnt; + return 1; + } + // check if it is a good time for table resizing + if ( p->nEntries >= 2 * p->nBins ) + { + Fraig_TableResizeS( p ); + Key = Fraig_HashKey2( p1, p2, p->nBins ); + } + // create the new node + pEnt = Fraig_NodeCreate( pMan, p1, p2 ); + // add the node to the corresponding linked list in the table + pEnt->pNextS = p->pBins[Key]; + p->pBins[Key] = pEnt; + *ppNodeRes = pEnt; + p->nEntries++; + return 0; +} + + +/**Function************************************************************* + + Synopsis [Insert the entry in the functional hash table.] + + Description [If the entry with the same key exists, return it right away. + If the entry with the same key does not exists, inserts it and returns NULL. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_HashTable_t * p = pMan->pTableF; + Fraig_Node_t * pEnt, * pEntD; + unsigned Key; + + // go through the hash table entries + Key = pNode->uHashR % p->nBins; + Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt ) + { + // if their simulation info differs, skip + if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->nWordsRand, 1 ) ) + continue; + // equivalent up to the complement + Fraig_TableBinForEachEntryD( pEnt, pEntD ) + { + // if their simulation info differs, skip + if ( !Fraig_CompareSimInfo( pNode, pEntD, pMan->iWordStart, 0 ) ) + continue; + // found a simulation-equivalent node + return pEntD; + } + // did not find a simulation equivalent node + // add the node to the corresponding linked list + pNode->pNextD = pEnt->pNextD; + pEnt->pNextD = pNode; + // return NULL, because there is no functional equivalence in this case + return NULL; + } + + // check if it is a good time for table resizing + if ( p->nEntries >= 2 * p->nBins ) + { + Fraig_TableResizeF( p, 1 ); + Key = pNode->uHashR % p->nBins; + } + + // add the node to the corresponding linked list in the table + pNode->pNextF = p->pBins[Key]; + p->pBins[Key] = pNode; + p->nEntries++; + // return NULL, because there is no functional equivalence in this case + return NULL; +} + +/**Function************************************************************* + + Synopsis [Insert the entry in the functional hash table.] + + Description [If the entry with the same key exists, return it right away. + If the entry with the same key does not exists, inserts it and returns NULL. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_HashTable_t * p = pMan->pTableF0; + Fraig_Node_t * pEnt; + unsigned Key; + + // go through the hash table entries + Key = pNode->uHashD % p->nBins; + Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt ) + { + // if their simulation info differs, skip + if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->iWordStart, 0 ) ) + continue; + // found a simulation-equivalent node + return pEnt; + } + + // check if it is a good time for table resizing + if ( p->nEntries >= 2 * p->nBins ) + { + Fraig_TableResizeF( p, 0 ); + Key = pNode->uHashD % p->nBins; + } + + // add the node to the corresponding linked list in the table + pNode->pNextF = p->pBins[Key]; + p->pBins[Key] = pNode; + p->nEntries++; + // return NULL, because there is no functional equivalence in this case + return NULL; +} + +/**Function************************************************************* + + Synopsis [Insert the entry in the functional hash table.] + + Description [Unconditionally add the node to the corresponding + linked list in the table.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + Fraig_HashTable_t * p = pMan->pTableF0; + unsigned Key = pNode->uHashD % p->nBins; + + pNode->pNextF = p->pBins[Key]; + p->pBins[Key] = pNode; + p->nEntries++; +} + + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_TableResizeS( Fraig_HashTable_t * p ) +{ + Fraig_Node_t ** pBinsNew; + Fraig_Node_t * pEnt, * pEnt2; + int nBinsNew, Counter, i, clk; + unsigned Key; + +clk = clock(); + // get the new table size + nBinsNew = Cudd_PrimeFraig(2 * p->nBins); + // allocate a new array + pBinsNew = ALLOC( Fraig_Node_t *, nBinsNew ); + memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < p->nBins; i++ ) + Fraig_TableBinForEachEntrySafeS( p->pBins[i], pEnt, pEnt2 ) + { + Key = Fraig_HashKey2( pEnt->p1, pEnt->p2, nBinsNew ); + pEnt->pNextS = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == p->nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew ); +// PRT( "Time", clock() - clk ); + // replace the table and the parameters + free( p->pBins ); + p->pBins = pBinsNew; + p->nBins = nBinsNew; +} + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR ) +{ + Fraig_Node_t ** pBinsNew; + Fraig_Node_t * pEnt, * pEnt2; + int nBinsNew, Counter, i, clk; + unsigned Key; + +clk = clock(); + // get the new table size + nBinsNew = Cudd_PrimeFraig(2 * p->nBins); + // allocate a new array + pBinsNew = ALLOC( Fraig_Node_t *, nBinsNew ); + memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < p->nBins; i++ ) + Fraig_TableBinForEachEntrySafeF( p->pBins[i], pEnt, pEnt2 ) + { + if ( fUseSimR ) + Key = pEnt->uHashR % nBinsNew; + else + Key = pEnt->uHashD % nBinsNew; + pEnt->pNextF = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == p->nEntries ); +// printf( "Increasing the functional table size from %6d to %6d. ", p->nBins, nBinsNew ); +// PRT( "Time", clock() - clk ); + // replace the table and the parameters + free( p->pBins ); + p->pBins = pBinsNew; + p->nBins = nBinsNew; +} + + +/**Function************************************************************* + + Synopsis [Compares two pieces of simulation info.] + + Description [Returns 1 if they are equal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand ) +{ + int i; + assert( !Fraig_IsComplement(pNode1) ); + assert( !Fraig_IsComplement(pNode2) ); + if ( fUseRand ) + { + // if their signatures differ, skip + if ( pNode1->uHashR != pNode2->uHashR ) + return 0; + // check the simulation info + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimR[i] != pNode2->puSimR[i] ) + return 0; + } + else + { + // if their signatures differ, skip + if ( pNode1->uHashD != pNode2->uHashD ) + return 0; + // check the simulation info + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimD[i] != pNode2->puSimD[i] ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Find the number of the different pattern.] + + Description [Returns -1 if there is no such pattern] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand ) +{ + int i, v; + assert( !Fraig_IsComplement(pNode1) ); + assert( !Fraig_IsComplement(pNode2) ); + // take into account possible internal complementation + fCompl ^= pNode1->fInv; + fCompl ^= pNode2->fInv; + // find the pattern + if ( fCompl ) + { + if ( fUseRand ) + { + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimR[i] != ~pNode2->puSimR[i] ) + for ( v = 0; v < 32; v++ ) + if ( (pNode1->puSimR[i] ^ ~pNode2->puSimR[i]) & (1 << v) ) + return i * 32 + v; + } + else + { + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimD[i] != ~pNode2->puSimD[i] ) + for ( v = 0; v < 32; v++ ) + if ( (pNode1->puSimD[i] ^ ~pNode2->puSimD[i]) & (1 << v) ) + return i * 32 + v; + } + } + else + { + if ( fUseRand ) + { + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimR[i] != pNode2->puSimR[i] ) + for ( v = 0; v < 32; v++ ) + if ( (pNode1->puSimR[i] ^ pNode2->puSimR[i]) & (1 << v) ) + return i * 32 + v; + } + else + { + for ( i = 0; i < iWordLast; i++ ) + if ( pNode1->puSimD[i] != pNode2->puSimD[i] ) + for ( v = 0; v < 32; v++ ) + if ( (pNode1->puSimD[i] ^ pNode2->puSimD[i]) & (1 << v) ) + return i * 32 + v; + } + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Compares two pieces of simulation info.] + + Description [Returns 1 if they are equal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ) +{ + unsigned * pSims1, * pSims2; + int i; + assert( !Fraig_IsComplement(pNode1) ); + assert( !Fraig_IsComplement(pNode2) ); + // get hold of simulation info + pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD; + pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD; + // check the simulation info + for ( i = 0; i < iWordLast; i++ ) + if ( (pSims1[i] & puMask[i]) != (pSims2[i] & puMask[i]) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares two pieces of simulation info.] + + Description [Returns 1 if they are equal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ) +{ + unsigned * pSims1, * pSims2; + int i; + assert( !Fraig_IsComplement(pNode1) ); + assert( !Fraig_IsComplement(pNode2) ); + // get hold of simulation info + pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD; + pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD; + // check the simulation info + for ( i = 0; i < iWordLast; i++ ) + puMask[i] = ( pSims1[i] ^ pSims2[i] ); +} + + +/**Function************************************************************* + + Synopsis [Prints stats of the structural table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_TablePrintStatsS( Fraig_Man_t * pMan ) +{ + Fraig_HashTable_t * pT = pMan->pTableS; + Fraig_Node_t * pNode; + int i, Counter; + + printf( "Structural table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); + for ( i = 0; i < pT->nBins; i++ ) + { + Counter = 0; + Fraig_TableBinForEachEntryS( pT->pBins[i], pNode ) + Counter++; + if ( Counter > 1 ) + { + printf( "%d ", Counter ); + if ( Counter > 50 ) + printf( "{%d} ", i ); + } + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints stats of the structural table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_TablePrintStatsF( Fraig_Man_t * pMan ) +{ + Fraig_HashTable_t * pT = pMan->pTableF; + Fraig_Node_t * pNode; + int i, Counter; + + printf( "Functional table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); + for ( i = 0; i < pT->nBins; i++ ) + { + Counter = 0; + Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) + Counter++; + if ( Counter > 1 ) + printf( "{%d} ", Counter ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints stats of the structural table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan ) +{ + Fraig_HashTable_t * pT = pMan->pTableF0; + Fraig_Node_t * pNode; + int i, Counter; + + printf( "Zero-node table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); + for ( i = 0; i < pT->nBins; i++ ) + { + Counter = 0; + Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) + Counter++; + if ( Counter == 0 ) + continue; +/* + printf( "\nBin = %4d : Number of entries = %4d\n", i, Counter ); + Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) + printf( "Node %5d. Hash = %10d.\n", pNode->Num, pNode->uHashD ); +*/ + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Rehashes the table after the simulation info has changed.] + + Description [Assumes that the hash values have been updated after performing + additional simulation. Rehashes the table using the new hash values. + Uses pNextF to link the entries in the bins. Uses pNextD to link the entries + with identical hash values. Returns 1 if the identical entries have been found. + Note that identical hash values may mean that the simulation data is different.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv ) +{ + Fraig_HashTable_t * pT = pMan->pTableF0; + Fraig_Node_t ** pBinsNew; + Fraig_Node_t * pEntF, * pEntF2, * pEnt, * pEntD2, * pEntN; + int ReturnValue, Counter, i; + unsigned Key; + + // allocate a new array of bins + pBinsNew = ALLOC( Fraig_Node_t *, pT->nBins ); + memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * pT->nBins ); + + // rehash the entries in the table + // go through all the nodes in the F-lists (and possible in D-lists, if used) + Counter = 0; + ReturnValue = 0; + for ( i = 0; i < pT->nBins; i++ ) + Fraig_TableBinForEachEntrySafeF( pT->pBins[i], pEntF, pEntF2 ) + Fraig_TableBinForEachEntrySafeD( pEntF, pEnt, pEntD2 ) + { + // decide where to put entry pEnt + Key = pEnt->uHashD % pT->nBins; + if ( fLinkEquiv ) + { + // go through the entries in the new bin + Fraig_TableBinForEachEntryF( pBinsNew[Key], pEntN ) + { + // if they have different values skip + if ( pEnt->uHashD != pEntN->uHashD ) + continue; + // they have the same hash value, add pEnt to the D-list pEnt3 + pEnt->pNextD = pEntN->pNextD; + pEntN->pNextD = pEnt; + ReturnValue = 1; + Counter++; + break; + } + if ( pEntN != NULL ) // already linked + continue; + // we did not find equal entry + } + // link the new entry + pEnt->pNextF = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + pEnt->pNextD = NULL; + Counter++; + } + assert( Counter == pT->nEntries ); + // replace the table and the parameters + free( pT->pBins ); + pT->pBins = pBinsNew; + return ReturnValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/fraig/fraigUtil.c b/abc70930/src/sat/fraig/fraigUtil.c new file mode 100644 index 00000000..342a7111 --- /dev/null +++ b/abc70930/src/sat/fraig/fraigUtil.c @@ -0,0 +1,1034 @@ +/**CFile**************************************************************** + + FileName [fraigUtil.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigUtil.c,v 1.15 2005/07/08 01:01:34 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" +#include + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int bit_count[256] = { + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 +}; + +static void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv ); +static int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv ) +{ + Fraig_NodeVec_t * vNodes; + int i; + pMan->nTravIds++; + vNodes = Fraig_NodeVecAlloc( 100 ); + for ( i = 0; i < pMan->vOutputs->nSize; i++ ) + Fraig_Dfs_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), vNodes, fEquiv ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv ) +{ + Fraig_NodeVec_t * vNodes; + pMan->nTravIds++; + vNodes = Fraig_NodeVecAlloc( 100 ); + Fraig_Dfs_rec( pMan, Fraig_Regular(pNode), vNodes, fEquiv ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv ) +{ + Fraig_NodeVec_t * vNodes; + int i; + pMan->nTravIds++; + vNodes = Fraig_NodeVecAlloc( 100 ); + for ( i = 0; i < nNodes; i++ ) + Fraig_Dfs_rec( pMan, Fraig_Regular(ppNodes[i]), vNodes, fEquiv ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv ) +{ + assert( !Fraig_IsComplement(pNode) ); + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return; + pNode->TravId = pMan->nTravIds; + // visit the transitive fanin + if ( Fraig_NodeIsAnd(pNode) ) + { + Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p1), vNodes, fEquiv ); + Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p2), vNodes, fEquiv ); + } + if ( fEquiv && pNode->pNextE ) + Fraig_Dfs_rec( pMan, pNode->pNextE, vNodes, fEquiv ); + // save the node + Fraig_NodeVecPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv ) +{ + Fraig_NodeVec_t * vNodes; + int RetValue; + vNodes = Fraig_Dfs( pMan, fEquiv ); + RetValue = vNodes->nSize; + Fraig_NodeVecFree( vNodes ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + assert( !Fraig_IsComplement(pOld) ); + assert( !Fraig_IsComplement(pNew) ); + pMan->nTravIds++; + return Fraig_CheckTfi_rec( pMan, pNew, pOld ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld ) +{ + // check the trivial cases + if ( pNode == NULL ) + return 0; + if ( pNode->Num < pOld->Num && !pMan->fChoicing ) + return 0; + if ( pNode == pOld ) + return 1; + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return 0; + pNode->TravId = pMan->nTravIds; + // check the children + if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p1), pOld ) ) + return 1; + if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p2), pOld ) ) + return 1; + // check equivalent nodes + return Fraig_CheckTfi_rec( pMan, pNode->pNextE, pOld ); +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CheckTfi2( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + Fraig_NodeVec_t * vNodes; + int RetValue; + vNodes = Fraig_DfsOne( pMan, pNew, 1 ); + RetValue = (pOld->TravId == pMan->nTravIds); + Fraig_NodeVecFree( vNodes ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Sets the number of fanouts (none, one, or many).] + + Description [This procedure collects the nodes reachable from + the POs of the AIG and sets the type of fanout counter (none, one, + or many) for each node. This procedure is useful to determine + fanout-free cones of AND-nodes, which is helpful for rebalancing + the AIG (see procedure Fraig_ManRebalance, or something like that).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManMarkRealFanouts( Fraig_Man_t * p ) +{ + Fraig_NodeVec_t * vNodes; + Fraig_Node_t * pNodeR; + int i; + // collect the nodes reachable + vNodes = Fraig_Dfs( p, 0 ); + // clean the fanouts field + for ( i = 0; i < vNodes->nSize; i++ ) + { + vNodes->pArray[i]->nFanouts = 0; + vNodes->pArray[i]->pData0 = NULL; + } + // mark reachable nodes by setting the two-bit counter pNode->nFans + for ( i = 0; i < vNodes->nSize; i++ ) + { + pNodeR = Fraig_Regular(vNodes->pArray[i]->p1); + if ( pNodeR && ++pNodeR->nFanouts == 3 ) + pNodeR->nFanouts = 2; + pNodeR = Fraig_Regular(vNodes->pArray[i]->p2); + if ( pNodeR && ++pNodeR->nFanouts == 3 ) + pNodeR->nFanouts = 2; + } + Fraig_NodeVecFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Creates the constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_BitStringCountOnes( unsigned * pString, int nWords ) +{ + unsigned char * pSuppBytes = (unsigned char *)pString; + int i, nOnes, nBytes = sizeof(unsigned) * nWords; + // count the number of ones in the simulation vector + for ( i = nOnes = 0; i < nBytes; i++ ) + nOnes += bit_count[pSuppBytes[i]]; + return nOnes; +} + +/**Function************************************************************* + + Synopsis [Verify one useful property.] + + Description [This procedure verifies one useful property. After + the FRAIG construction with choice nodes is over, each primary node + should have fanins that are primary nodes. The primary nodes is the + one that does not have pNode->pRepr set to point to another node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManCheckConsistency( Fraig_Man_t * p ) +{ + Fraig_Node_t * pNode; + Fraig_NodeVec_t * pVec; + int i; + pVec = Fraig_Dfs( p, 0 ); + for ( i = 0; i < pVec->nSize; i++ ) + { + pNode = pVec->pArray[i]; + if ( Fraig_NodeIsVar(pNode) ) + { + if ( pNode->pRepr ) + printf( "Primary input %d is a secondary node.\n", pNode->Num ); + } + else if ( Fraig_NodeIsConst(pNode) ) + { + if ( pNode->pRepr ) + printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); + } + else + { + if ( pNode->pRepr ) + printf( "Internal node %d is a secondary node.\n", pNode->Num ); + if ( Fraig_Regular(pNode->p1)->pRepr ) + printf( "Internal node %d has first fanin %d that is a secondary node.\n", + pNode->Num, Fraig_Regular(pNode->p1)->Num ); + if ( Fraig_Regular(pNode->p2)->pRepr ) + printf( "Internal node %d has second fanin %d that is a secondary node.\n", + pNode->Num, Fraig_Regular(pNode->p2)->Num ); + } + } + Fraig_NodeVecFree( pVec ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Prints the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_PrintNode( Fraig_Man_t * p, Fraig_Node_t * pNode ) +{ + Fraig_NodeVec_t * vNodes; + Fraig_Node_t * pTemp; + int fCompl1, fCompl2, i; + + vNodes = Fraig_DfsOne( p, pNode, 0 ); + for ( i = 0; i < vNodes->nSize; i++ ) + { + pTemp = vNodes->pArray[i]; + if ( Fraig_NodeIsVar(pTemp) ) + { + printf( "%3d : PI ", pTemp->Num ); + Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 ); + printf( " " ); + Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 ); + printf( " %d\n", pTemp->fInv ); + continue; + } + + fCompl1 = Fraig_IsComplement(pTemp->p1); + fCompl2 = Fraig_IsComplement(pTemp->p2); + printf( "%3d : %c%3d %c%3d ", pTemp->Num, + (fCompl1? '-':'+'), Fraig_Regular(pTemp->p1)->Num, + (fCompl2? '-':'+'), Fraig_Regular(pTemp->p2)->Num ); + Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 ); + printf( " " ); + Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 ); + printf( " %d\n", pTemp->fInv ); + } + Fraig_NodeVecFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Prints the bit string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits ) +{ + int Remainder, nWords; + int w, i; + + Remainder = (nBits%(sizeof(unsigned)*8)); + nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); + + for ( w = nWords-1; w >= 0; w-- ) + for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) + fprintf( pFile, "%c", '0' + (int)((pSign[w] & (1< 0) ); + +// fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Sets up the mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_GetMaxLevel( Fraig_Man_t * pMan ) +{ + int nLevelMax, i; + nLevelMax = 0; + for ( i = 0; i < pMan->vOutputs->nSize; i++ ) + nLevelMax = nLevelMax > Fraig_Regular(pMan->vOutputs->pArray[i])->Level? + nLevelMax : Fraig_Regular(pMan->vOutputs->pArray[i])->Level; + return nLevelMax; +} + +/**Function************************************************************* + + Synopsis [Analyses choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_MappingUpdateLevel_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fMaximum ) +{ + Fraig_Node_t * pTemp; + int Level1, Level2, LevelE; + assert( !Fraig_IsComplement(pNode) ); + if ( !Fraig_NodeIsAnd(pNode) ) + return pNode->Level; + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return pNode->Level; + pNode->TravId = pMan->nTravIds; + // compute levels of the children nodes + Level1 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p1), fMaximum ); + Level2 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p2), fMaximum ); + pNode->Level = 1 + FRAIG_MAX( Level1, Level2 ); + if ( pNode->pNextE ) + { + LevelE = Fraig_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); + if ( fMaximum ) + { + if ( pNode->Level < LevelE ) + pNode->Level = LevelE; + } + else + { + if ( pNode->Level > LevelE ) + pNode->Level = LevelE; + } + // set the level of all equivalent nodes to be the same minimum + if ( pNode->pRepr == NULL ) // the primary node + for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) + pTemp->Level = pNode->Level; + } + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Resets the levels of the nodes in the choice graph.] + + Description [Makes the level of the choice nodes to be equal to the + maximum of the level of the nodes in the equivalence class. This way + sorting by level leads to the reverse topological order, which is + needed for the required time computation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum ) +{ + int i; + pMan->nTravIds++; + for ( i = 0; i < pMan->vOutputs->nSize; i++ ) + Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), fMaximum ); +} + +/**Function************************************************************* + + Synopsis [Reports statistics on choice nodes.] + + Description [The number of choice nodes is the number of primary nodes, + which has pNextE set to a pointer. The number of choices is the number + of entries in the equivalent-node lists of the primary nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManReportChoices( Fraig_Man_t * pMan ) +{ + Fraig_Node_t * pNode, * pTemp; + int nChoiceNodes, nChoices; + int i, LevelMax1, LevelMax2; + + // report the number of levels + LevelMax1 = Fraig_GetMaxLevel( pMan ); + Fraig_MappingSetChoiceLevels( pMan, 0 ); + LevelMax2 = Fraig_GetMaxLevel( pMan ); + + // report statistics about choices + nChoiceNodes = nChoices = 0; + for ( i = 0; i < pMan->vNodes->nSize; i++ ) + { + pNode = pMan->vNodes->pArray[i]; + if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) + { // this is a choice node = the primary node that has equivalent nodes + nChoiceNodes++; + for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) + nChoices++; + } + } + printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); + printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of EXOR/NEXOR gate.] + + Description [The node can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsExorType( Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1, * pNode2; + // make the node regular (it does not matter for EXOR/NEXOR) + pNode = Fraig_Regular(pNode); + // if the node or its children are not ANDs or not compl, this cannot be EXOR type + if ( !Fraig_NodeIsAnd(pNode) ) + return 0; + if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) ) + return 0; + if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) ) + return 0; + + // get children + pNode1 = Fraig_Regular(pNode->p1); + pNode2 = Fraig_Regular(pNode->p2); + assert( pNode1->Num < pNode2->Num ); + + // compare grandchildren + return pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [The node can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsMuxType( Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1, * pNode2; + + // make the node regular (it does not matter for EXOR/NEXOR) + pNode = Fraig_Regular(pNode); + // if the node or its children are not ANDs or not compl, this cannot be EXOR type + if ( !Fraig_NodeIsAnd(pNode) ) + return 0; + if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) ) + return 0; + if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) ) + return 0; + + // get children + pNode1 = Fraig_Regular(pNode->p1); + pNode2 = Fraig_Regular(pNode->p2); + assert( pNode1->Num < pNode2->Num ); + + // compare grandchildren + // node is an EXOR/NEXOR + if ( pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2) ) + return 1; + + // otherwise the node is MUX iff it has a pair of equal grandchildren + return pNode1->p1 == Fraig_Not(pNode2->p1) || + pNode1->p1 == Fraig_Not(pNode2->p2) || + pNode1->p2 == Fraig_Not(pNode2->p1) || + pNode1->p2 == Fraig_Not(pNode2->p2); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is EXOR, 0 if it is NEXOR.] + + Description [The node should be EXOR type and not complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsExor( Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1; + assert( !Fraig_IsComplement(pNode) ); + assert( Fraig_NodeIsExorType(pNode) ); + assert( Fraig_IsComplement(pNode->p1) ); + // get children + pNode1 = Fraig_Regular(pNode->p1); + return Fraig_IsComplement(pNode1->p1) == Fraig_IsComplement(pNode1->p2); +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE ) +{ + Fraig_Node_t * pNode1, * pNode2; + assert( !Fraig_IsComplement(pNode) ); + assert( Fraig_NodeIsMuxType(pNode) ); + // get children + pNode1 = Fraig_Regular(pNode->p1); + pNode2 = Fraig_Regular(pNode->p2); + // find the control variable + if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) + { + if ( Fraig_IsComplement(pNode1->p1) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Fraig_Not(pNode2->p2); + *ppNodeE = Fraig_Not(pNode1->p2); + return pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Fraig_Not(pNode1->p2); + *ppNodeE = Fraig_Not(pNode2->p2); + return pNode1->p1; + } + } + else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) + { + if ( Fraig_IsComplement(pNode1->p1) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Fraig_Not(pNode2->p1); + *ppNodeE = Fraig_Not(pNode1->p2); + return pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Fraig_Not(pNode1->p2); + *ppNodeE = Fraig_Not(pNode2->p1); + return pNode1->p1; + } + } + else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) + { + if ( Fraig_IsComplement(pNode1->p2) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Fraig_Not(pNode2->p2); + *ppNodeE = Fraig_Not(pNode1->p1); + return pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Fraig_Not(pNode1->p1); + *ppNodeE = Fraig_Not(pNode2->p2); + return pNode1->p2; + } + } + else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) + { + if ( Fraig_IsComplement(pNode1->p2) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Fraig_Not(pNode2->p1); + *ppNodeE = Fraig_Not(pNode1->p1); + return pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Fraig_Not(pNode1->p1); + *ppNodeE = Fraig_Not(pNode2->p1); + return pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + +/**Function************************************************************* + + Synopsis [Counts the number of EXOR type nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManCountExors( Fraig_Man_t * pMan ) +{ + int i, nExors; + nExors = 0; + for ( i = 0; i < pMan->vNodes->nSize; i++ ) + nExors += Fraig_NodeIsExorType( pMan->vNodes->pArray[i] ); + return nExors; + +} + +/**Function************************************************************* + + Synopsis [Counts the number of EXOR type nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManCountMuxes( Fraig_Man_t * pMan ) +{ + int i, nMuxes; + nMuxes = 0; + for ( i = 0; i < pMan->vNodes->nSize; i++ ) + nMuxes += Fraig_NodeIsMuxType( pMan->vNodes->pArray[i] ); + return nMuxes; + +} + +/**Function************************************************************* + + Synopsis [Returns 1 if siminfo of Node1 is contained in siminfo of Node2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ) +{ + unsigned * pUnsigned1, * pUnsigned2; + int i; + + // compare random siminfo + pUnsigned1 = pNode1->puSimR; + pUnsigned2 = pNode2->puSimR; + for ( i = 0; i < pMan->nWordsRand; i++ ) + if ( pUnsigned1[i] & ~pUnsigned2[i] ) + return 0; + + // compare systematic siminfo + pUnsigned1 = pNode1->puSimD; + pUnsigned2 = pNode2->puSimD; + for ( i = 0; i < pMan->iWordStart; i++ ) + if ( pUnsigned1[i] & ~pUnsigned2[i] ) + return 0; + + return 1; +} + +/**Function************************************************************* + + Synopsis [Count the number of PI variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums ) +{ + int * pVars, nVars, i, Counter; + + nVars = Msat_IntVecReadSize(vVarNums); + pVars = Msat_IntVecReadArray(vVarNums); + Counter = 0; + for ( i = 0; i < nVars; i++ ) + Counter += Fraig_NodeIsVar( p->vNodes->pArray[pVars[i]] ); + return Counter; +} + + + +/**Function************************************************************* + + Synopsis [Counts the number of EXOR type nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_ManPrintRefs( Fraig_Man_t * pMan ) +{ + Fraig_NodeVec_t * vPivots; + Fraig_Node_t * pNode, * pNode2; + int i, k, Counter, nProved; + int clk; + + vPivots = Fraig_NodeVecAlloc( 1000 ); + for ( i = 0; i < pMan->vNodes->nSize; i++ ) + { + pNode = pMan->vNodes->pArray[i]; + + if ( pNode->nOnes == 0 || pNode->nOnes == (unsigned)pMan->nWordsRand * 32 ) + continue; + + if ( pNode->nRefs > 5 ) + { + Fraig_NodeVecPush( vPivots, pNode ); +// printf( "Node %6d : nRefs = %2d Level = %3d.\n", pNode->Num, pNode->nRefs, pNode->Level ); + } + } + printf( "Total nodes = %d. Referenced nodes = %d.\n", pMan->vNodes->nSize, vPivots->nSize ); + +clk = clock(); + // count implications + Counter = nProved = 0; + for ( i = 0; i < vPivots->nSize; i++ ) + for ( k = i+1; k < vPivots->nSize; k++ ) + { + pNode = vPivots->pArray[i]; + pNode2 = vPivots->pArray[k]; + if ( Fraig_NodeSimsContained( pMan, pNode, pNode2 ) ) + { + if ( Fraig_NodeIsImplication( pMan, pNode, pNode2, -1 ) ) + nProved++; + Counter++; + } + else if ( Fraig_NodeSimsContained( pMan, pNode2, pNode ) ) + { + if ( Fraig_NodeIsImplication( pMan, pNode2, pNode, -1 ) ) + nProved++; + Counter++; + } + } + printf( "Number of candidate pairs = %d. Proved = %d.\n", Counter, nProved ); +PRT( "Time", clock() - clk ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Checks if pNew exists among the implication fanins of pOld.] + + Description [If pNew is an implication fanin of pOld, returns 1. + If Fraig_Not(pNew) is an implication fanin of pOld, return -1. + Otherwise returns 0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew ) +{ + int RetValue1, RetValue2; + if ( Fraig_Regular(pOld) == Fraig_Regular(pNew) ) + return (pOld == pNew)? 1 : -1; + if ( Fraig_IsComplement(pOld) || Fraig_NodeIsVar(pOld) ) + return 0; + RetValue1 = Fraig_NodeIsInSupergate( pOld->p1, pNew ); + RetValue2 = Fraig_NodeIsInSupergate( pOld->p2, pNew ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + if ( RetValue1 == 1 || RetValue2 == 1 ) + return 1; + return 0; +} + + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_CollectSupergate_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, int fFirst, int fStopAtMux ) +{ + // if the new node is complemented or a PI, another gate begins +// if ( Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || Fraig_NodeIsMuxType(pNode) ) + if ( (!fFirst && Fraig_Regular(pNode)->nRefs > 1) || + Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || + (fStopAtMux && Fraig_NodeIsMuxType(pNode)) ) + { + Fraig_NodeVecPushUnique( vSuper, pNode ); + return; + } + // go through the branches + Fraig_CollectSupergate_rec( pNode->p1, vSuper, 0, fStopAtMux ); + Fraig_CollectSupergate_rec( pNode->p2, vSuper, 0, fStopAtMux ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ) +{ + Fraig_NodeVec_t * vSuper; + vSuper = Fraig_NodeVecAlloc( 8 ); + Fraig_CollectSupergate_rec( pNode, vSuper, 1, fStopAtMux ); + return vSuper; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_ManIncrementTravId( Fraig_Man_t * pMan ) +{ + pMan->nTravIds2++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + pNode->TravId2 = pMan->nTravIds2; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + return pNode->TravId2 == pMan->nTravIds2; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) +{ + return pNode->TravId2 == pMan->nTravIds2 - 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/fraig/fraigVec.c b/abc70930/src/sat/fraig/fraigVec.c new file mode 100644 index 00000000..ba3feecd --- /dev/null +++ b/abc70930/src/sat/fraig/fraigVec.c @@ -0,0 +1,545 @@ +/**CFile**************************************************************** + + FileName [fraigVec.c] + + PackageName [FRAIG: Functionally reduced AND-INV graphs.] + + Synopsis [Vector of FRAIG nodes.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - October 1, 2004] + + Revision [$Id: fraigVec.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $] + +***********************************************************************/ + +#include "fraigInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap ) +{ + Fraig_NodeVec_t * p; + p = ALLOC( Fraig_NodeVec_t, 1 ); + if ( nCap > 0 && nCap < 8 ) + nCap = 8; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? ALLOC( Fraig_Node_t *, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecFree( Fraig_NodeVec_t * p ) +{ + FREE( p->pArray ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the integer array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * pVec ) +{ + Fraig_NodeVec_t * p; + p = ALLOC( Fraig_NodeVec_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nCap; + p->pArray = p->nCap? ALLOC( Fraig_Node_t *, p->nCap ) : NULL; + memcpy( p->pArray, pVec->pArray, sizeof(Fraig_Node_t *) * pVec->nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p ) +{ + return p->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = REALLOC( Fraig_Node_t *, p->pArray, nCapMin ); + p->nCap = nCapMin; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew ) +{ + assert( p->nSize >= nSizeNew ); + p->nSize = nSizeNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecClear( Fraig_NodeVec_t * p ) +{ + p->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) +{ + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Fraig_NodeVecGrow( p, 16 ); + else + Fraig_NodeVecGrow( p, 2 * p->nCap ); + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [Add the element while ensuring uniqueness.] + + Description [Returns 1 if the element was found, and 0 if it was new. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return 1; + Fraig_NodeVecPush( p, Entry ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1, * pNode2; + int i; + Fraig_NodeVecPush( p, pNode ); + // find the p of the node + for ( i = p->nSize-1; i > 0; i-- ) + { + pNode1 = p->pArray[i ]; + pNode2 = p->pArray[i-1]; + if ( pNode1 >= pNode2 ) + break; + p->pArray[i ] = pNode2; + p->pArray[i-1] = pNode1; + } +} + +/**Function************************************************************* + + Synopsis [Add the element while ensuring uniqueness in the order.] + + Description [Returns 1 if the element was found, and 0 if it was new. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == pNode ) + return 1; + Fraig_NodeVecPushOrder( p, pNode ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) +{ + Fraig_Node_t * pNode1, * pNode2; + int i; + Fraig_NodeVecPush( p, pNode ); + // find the p of the node + for ( i = p->nSize-1; i > 0; i-- ) + { + pNode1 = p->pArray[i ]; + pNode2 = p->pArray[i-1]; + if ( Fraig_Regular(pNode1)->Level <= Fraig_Regular(pNode2)->Level ) + break; + p->pArray[i ] = pNode2; + p->pArray[i-1] = pNode1; + } +} + +/**Function************************************************************* + + Synopsis [Add the element while ensuring uniqueness in the order.] + + Description [Returns 1 if the element was found, and 0 if it was new. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == pNode ) + return 1; + Fraig_NodeVecPushOrderByLevel( p, pNode ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p ) +{ + return p->pArray[--p->nSize]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + break; + assert( i < p->nSize ); + for ( i++; i < p->nSize; i++ ) + p->pArray[i-1] = p->pArray[i]; + p->nSize--; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecCompareLevelsIncreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) +{ + int Level1 = Fraig_Regular(*pp1)->Level; + int Level2 = Fraig_Regular(*pp2)->Level; + if ( Level1 < Level2 ) + return -1; + if ( Level1 > Level2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecCompareLevelsDecreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) +{ + int Level1 = Fraig_Regular(*pp1)->Level; + int Level2 = Fraig_Regular(*pp2)->Level; + if ( Level1 > Level2 ) + return -1; + if ( Level1 < Level2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecCompareNumbers( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) +{ + int Num1 = Fraig_Regular(*pp1)->Num; + int Num2 = Fraig_Regular(*pp2)->Num; + if ( Num1 < Num2 ) + return -1; + if ( Num1 > Num2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fraig_NodeVecCompareRefCounts( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) +{ + int nRefs1 = Fraig_Regular(*pp1)->nRefs; + int nRefs2 = Fraig_Regular(*pp2)->nRefs; + + if ( nRefs1 < nRefs2 ) + return -1; + if ( nRefs1 > nRefs2 ) + return 1; + + nRefs1 = Fraig_Regular(*pp1)->Level; + nRefs2 = Fraig_Regular(*pp2)->Level; + + if ( nRefs1 < nRefs2 ) + return -1; + if ( nRefs1 > nRefs2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing ) +{ + if ( fIncreasing ) + qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), + (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsIncreasing ); + else + qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), + (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsDecreasing ); +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p ) +{ + qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), + (int (*)(const void *, const void *)) Fraig_NodeVecCompareNumbers ); +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p ) +{ + qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), + (int (*)(const void *, const void *)) Fraig_NodeVecCompareRefCounts ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/sat/fraig/module.make b/abc70930/src/sat/fraig/module.make new file mode 100644 index 00000000..cc6eb9d3 --- /dev/null +++ b/abc70930/src/sat/fraig/module.make @@ -0,0 +1,12 @@ +SRC += src/sat/fraig/fraigApi.c \ + src/sat/fraig/fraigCanon.c \ + src/sat/fraig/fraigFanout.c \ + src/sat/fraig/fraigFeed.c \ + src/sat/fraig/fraigMan.c \ + src/sat/fraig/fraigMem.c \ + src/sat/fraig/fraigNode.c \ + src/sat/fraig/fraigPrime.c \ + src/sat/fraig/fraigSat.c \ + src/sat/fraig/fraigTable.c \ + src/sat/fraig/fraigUtil.c \ + src/sat/fraig/fraigVec.c diff --git a/abc70930/src/sat/msat/module.make b/abc70930/src/sat/msat/module.make new file mode 100644 index 00000000..0dadfbe1 --- /dev/null +++ b/abc70930/src/sat/msat/module.make @@ -0,0 +1,13 @@ +SRC += src/sat/msat/msatActivity.c \ + src/sat/msat/msatClause.c \ + src/sat/msat/msatClauseVec.c \ + src/sat/msat/msatMem.c \ + src/sat/msat/msatOrderJ.c \ + src/sat/msat/msatQueue.c \ + src/sat/msat/msatRead.c \ + src/sat/msat/msatSolverApi.c \ + src/sat/msat/msatSolverCore.c \ + src/sat/msat/msatSolverIo.c \ + src/sat/msat/msatSolverSearch.c \ + src/sat/msat/msatSort.c \ + src/sat/msat/msatVec.c diff --git a/abc70930/src/sat/msat/msat.h b/abc70930/src/sat/msat/msat.h new file mode 100644 index 00000000..53353ba6 --- /dev/null +++ b/abc70930/src/sat/msat/msat.h @@ -0,0 +1,172 @@ +/**CFile**************************************************************** + + FileName [msat.h] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [External definitions of the solver.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msat.h,v 1.6 2004/05/12 06:30:20 satrajit Exp $] + +***********************************************************************/ + +#ifndef __MSAT_H__ +#define __MSAT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifdef bool +#undef bool +#endif + +#ifndef __MVTYPES_H__ +typedef int bool; +#endif + +typedef struct Msat_Solver_t_ Msat_Solver_t; + +// the vector of intergers and of clauses +typedef struct Msat_IntVec_t_ Msat_IntVec_t; +typedef struct Msat_ClauseVec_t_ Msat_ClauseVec_t; +typedef struct Msat_VarHeap_t_ Msat_VarHeap_t; + +// the return value of the solver +typedef enum { MSAT_FALSE = -1, MSAT_UNKNOWN = 0, MSAT_TRUE = 1 } Msat_Type_t; + +// representation of variables and literals +// the literal (l) is the variable (v) and the sign (s) +// s = 0 the variable is positive +// s = 1 the variable is negative +#define MSAT_VAR2LIT(v,s) (2*(v)+(s)) +#define MSAT_LITNOT(l) ((l)^1) +#define MSAT_LITSIGN(l) ((l)&1) +#define MSAT_LIT2VAR(l) ((l)>>1) + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== satRead.c ============================================================*/ +extern bool Msat_SolverParseDimacs( FILE * pFile, Msat_Solver_t ** p, int fVerbose ); +/*=== satSolver.c ===========================================================*/ +// adding vars, clauses, simplifying the database, and solving +extern bool Msat_SolverAddVar( Msat_Solver_t * p, int Level ); +extern bool Msat_SolverAddClause( Msat_Solver_t * p, Msat_IntVec_t * pLits ); +extern bool Msat_SolverSimplifyDB( Msat_Solver_t * p ); +extern bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * pVecAssumps, int nBackTrackLimit, int nTimeLimit ); +// printing stats, assignments, and clauses +extern void Msat_SolverPrintStats( Msat_Solver_t * p ); +extern void Msat_SolverPrintAssignment( Msat_Solver_t * p ); +extern void Msat_SolverPrintClauses( Msat_Solver_t * p ); +extern void Msat_SolverWriteDimacs( Msat_Solver_t * p, char * pFileName ); +// access to the solver internal data +extern int Msat_SolverReadVarNum( Msat_Solver_t * p ); +extern int Msat_SolverReadClauseNum( Msat_Solver_t * p ); +extern int Msat_SolverReadVarAllocNum( Msat_Solver_t * p ); +extern int * Msat_SolverReadAssignsArray( Msat_Solver_t * p ); +extern int * Msat_SolverReadModelArray( Msat_Solver_t * p ); +extern unsigned Msat_SolverReadTruth( Msat_Solver_t * p ); +extern int Msat_SolverReadBackTracks( Msat_Solver_t * p ); +extern int Msat_SolverReadInspects( Msat_Solver_t * p ); +extern void Msat_SolverSetVerbosity( Msat_Solver_t * p, int fVerbose ); +extern void Msat_SolverSetProofWriting( Msat_Solver_t * p, int fProof ); +extern void Msat_SolverSetVarTypeA( Msat_Solver_t * p, int Var ); +extern void Msat_SolverSetVarMap( Msat_Solver_t * p, Msat_IntVec_t * vVarMap ); +extern void Msat_SolverMarkLastClauseTypeA( Msat_Solver_t * p ); +extern void Msat_SolverMarkClausesStart( Msat_Solver_t * p ); +extern float * Msat_SolverReadFactors( Msat_Solver_t * p ); +// returns the solution after incremental solving +extern int Msat_SolverReadSolutions( Msat_Solver_t * p ); +extern int * Msat_SolverReadSolutionsArray( Msat_Solver_t * p ); +extern Msat_ClauseVec_t * Msat_SolverReadAdjacents( Msat_Solver_t * p ); +extern Msat_IntVec_t * Msat_SolverReadConeVars( Msat_Solver_t * p ); +extern Msat_IntVec_t * Msat_SolverReadVarsUsed( Msat_Solver_t * p ); +/*=== satSolverSearch.c ===========================================================*/ +extern void Msat_SolverRemoveLearned( Msat_Solver_t * p ); +extern void Msat_SolverRemoveMarked( Msat_Solver_t * p ); +/*=== satSolverApi.c ===========================================================*/ +// allocation, cleaning, and freeing the solver +extern Msat_Solver_t * Msat_SolverAlloc( int nVars, double dClaInc, double dClaDecay, double dVarInc, double dVarDecay, bool fVerbose ); +extern void Msat_SolverResize( Msat_Solver_t * pMan, int nVarsAlloc ); +extern void Msat_SolverClean( Msat_Solver_t * p, int nVars ); +extern void Msat_SolverPrepare( Msat_Solver_t * pSat, Msat_IntVec_t * vVars ); +extern void Msat_SolverFree( Msat_Solver_t * p ); +/*=== satVec.c ===========================================================*/ +extern Msat_IntVec_t * Msat_IntVecAlloc( int nCap ); +extern Msat_IntVec_t * Msat_IntVecAllocArray( int * pArray, int nSize ); +extern Msat_IntVec_t * Msat_IntVecAllocArrayCopy( int * pArray, int nSize ); +extern Msat_IntVec_t * Msat_IntVecDup( Msat_IntVec_t * pVec ); +extern Msat_IntVec_t * Msat_IntVecDupArray( Msat_IntVec_t * pVec ); +extern void Msat_IntVecFree( Msat_IntVec_t * p ); +extern void Msat_IntVecFill( Msat_IntVec_t * p, int nSize, int Entry ); +extern int * Msat_IntVecReleaseArray( Msat_IntVec_t * p ); +extern int * Msat_IntVecReadArray( Msat_IntVec_t * p ); +extern int Msat_IntVecReadSize( Msat_IntVec_t * p ); +extern int Msat_IntVecReadEntry( Msat_IntVec_t * p, int i ); +extern int Msat_IntVecReadEntryLast( Msat_IntVec_t * p ); +extern void Msat_IntVecWriteEntry( Msat_IntVec_t * p, int i, int Entry ); +extern void Msat_IntVecGrow( Msat_IntVec_t * p, int nCapMin ); +extern void Msat_IntVecShrink( Msat_IntVec_t * p, int nSizeNew ); +extern void Msat_IntVecClear( Msat_IntVec_t * p ); +extern void Msat_IntVecPush( Msat_IntVec_t * p, int Entry ); +extern int Msat_IntVecPushUnique( Msat_IntVec_t * p, int Entry ); +extern void Msat_IntVecPushUniqueOrder( Msat_IntVec_t * p, int Entry, int fIncrease ); +extern int Msat_IntVecPop( Msat_IntVec_t * p ); +extern void Msat_IntVecSort( Msat_IntVec_t * p, int fReverse ); +/*=== satHeap.c ===========================================================*/ +extern Msat_VarHeap_t * Msat_VarHeapAlloc(); +extern void Msat_VarHeapSetActivity( Msat_VarHeap_t * p, double * pActivity ); +extern void Msat_VarHeapStart( Msat_VarHeap_t * p, int * pVars, int nVars, int nVarsAlloc ); +extern void Msat_VarHeapGrow( Msat_VarHeap_t * p, int nSize ); +extern void Msat_VarHeapStop( Msat_VarHeap_t * p ); +extern void Msat_VarHeapPrint( FILE * pFile, Msat_VarHeap_t * p ); +extern void Msat_VarHeapCheck( Msat_VarHeap_t * p ); +extern void Msat_VarHeapCheckOne( Msat_VarHeap_t * p, int iVar ); +extern int Msat_VarHeapContainsVar( Msat_VarHeap_t * p, int iVar ); +extern void Msat_VarHeapInsert( Msat_VarHeap_t * p, int iVar ); +extern void Msat_VarHeapUpdate( Msat_VarHeap_t * p, int iVar ); +extern void Msat_VarHeapDelete( Msat_VarHeap_t * p, int iVar ); +extern double Msat_VarHeapReadMaxWeight( Msat_VarHeap_t * p ); +extern int Msat_VarHeapCountNodes( Msat_VarHeap_t * p, double WeightLimit ); +extern int Msat_VarHeapReadMax( Msat_VarHeap_t * p ); +extern int Msat_VarHeapGetMax( Msat_VarHeap_t * p ); + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/abc70930/src/sat/msat/msatActivity.c b/abc70930/src/sat/msat/msatActivity.c new file mode 100644 index 00000000..1cd795bd --- /dev/null +++ b/abc70930/src/sat/msat/msatActivity.c @@ -0,0 +1,160 @@ +/**CFile**************************************************************** + + FileName [msatActivity.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [Procedures controlling activity of variables and clauses.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatActivity.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverVarBumpActivity( Msat_Solver_t * p, Msat_Lit_t Lit ) +{ + Msat_Var_t Var; + if ( p->dVarDecay < 0 ) // (negative decay means static variable order -- don't bump) + return; + Var = MSAT_LIT2VAR(Lit); + p->pdActivity[Var] += p->dVarInc; +// p->pdActivity[Var] += p->dVarInc * p->pFactors[Var]; + if ( p->pdActivity[Var] > 1e100 ) + Msat_SolverVarRescaleActivity( p ); + Msat_OrderUpdate( p->pOrder, Var ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverVarDecayActivity( Msat_Solver_t * p ) +{ + if ( p->dVarDecay >= 0 ) + p->dVarInc *= p->dVarDecay; +} + +/**Function************************************************************* + + Synopsis [Divide all variable activities by 1e100.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverVarRescaleActivity( Msat_Solver_t * p ) +{ + int i; + for ( i = 0; i < p->nVars; i++ ) + p->pdActivity[i] *= 1e-100; + p->dVarInc *= 1e-100; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverClaBumpActivity( Msat_Solver_t * p, Msat_Clause_t * pC ) +{ + float Activ; + Activ = Msat_ClauseReadActivity(pC); + if ( Activ + p->dClaInc > 1e20 ) + { + Msat_SolverClaRescaleActivity( p ); + Activ = Msat_ClauseReadActivity( pC ); + } + Msat_ClauseWriteActivity( pC, Activ + (float)p->dClaInc ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverClaDecayActivity( Msat_Solver_t * p ) +{ + p->dClaInc *= p->dClaDecay; +} + +/**Function************************************************************* + + Synopsis [Divide all constraint activities by 1e20.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverClaRescaleActivity( Msat_Solver_t * p ) +{ + Msat_Clause_t ** pLearned; + int nLearned, i; + float Activ; + nLearned = Msat_ClauseVecReadSize( p->vLearned ); + pLearned = Msat_ClauseVecReadArray( p->vLearned ); + for ( i = 0; i < nLearned; i++ ) + { + Activ = Msat_ClauseReadActivity( pLearned[i] ); + Msat_ClauseWriteActivity( pLearned[i], Activ * (float)1e-20 ); + } + p->dClaInc *= 1e-20; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatClause.c b/abc70930/src/sat/msat/msatClause.c new file mode 100644 index 00000000..2ba8cd32 --- /dev/null +++ b/abc70930/src/sat/msat/msatClause.c @@ -0,0 +1,529 @@ +/**CFile**************************************************************** + + FileName [msatClause.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [Procedures working with SAT clauses.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatClause.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Msat_Clause_t_ +{ + int Num; // unique number of the clause + unsigned fLearned : 1; // 1 if the clause is learned + unsigned fMark : 1; // used to mark visited clauses during proof recording + unsigned fTypeA : 1; // used to mark clauses belonging to A for interpolant computation + unsigned nSize : 14; // the number of literals in the clause + unsigned nSizeAlloc : 15; // the number of bytes allocated for the clause + Msat_Lit_t pData[0]; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a new clause.] + + Description [Returns FALSE if top-level conflict detected (must be handled); + TRUE otherwise. 'pClause_out' may be set to NULL if clause is already + satisfied by the top-level assignment.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_ClauseCreate( Msat_Solver_t * p, Msat_IntVec_t * vLits, bool fLearned, Msat_Clause_t ** pClause_out ) +{ + int * pAssigns = Msat_SolverReadAssignsArray(p); + Msat_ClauseVec_t ** pvWatched; + Msat_Clause_t * pC; + int * pLits; + int nLits, i, j; + int nBytes; + Msat_Var_t Var; + bool Sign; + + *pClause_out = NULL; + + nLits = Msat_IntVecReadSize(vLits); + pLits = Msat_IntVecReadArray(vLits); + + if ( !fLearned ) + { + int * pSeen = Msat_SolverReadSeenArray( p ); + int nSeenId; + assert( Msat_SolverReadDecisionLevel(p) == 0 ); + // sorting literals makes the code trace-equivalent + // with to the original C++ solver + Msat_IntVecSort( vLits, 0 ); + // increment the counter of seen twice + nSeenId = Msat_SolverIncrementSeenId( p ); + nSeenId = Msat_SolverIncrementSeenId( p ); + // nSeenId - 1 stands for negative + // nSeenId stands for positive + // Remove false literals + + // there is a bug here!!!! + // when the same var in opposite polarities is given, it drops one polarity!!! + + for ( i = j = 0; i < nLits; i++ ) { + // get the corresponding variable + Var = MSAT_LIT2VAR(pLits[i]); + Sign = MSAT_LITSIGN(pLits[i]); // Sign=0 for positive + // check if we already saw this variable in the this clause + if ( pSeen[Var] >= nSeenId - 1 ) + { + if ( (pSeen[Var] != nSeenId) == Sign ) // the same lit + continue; + return 1; // two opposite polarity lits -- don't add the clause + } + // mark the variable as seen + pSeen[Var] = nSeenId - !Sign; + + // analize the value of this literal + if ( pAssigns[Var] != MSAT_VAR_UNASSIGNED ) + { + if ( pAssigns[Var] == pLits[i] ) + return 1; // the clause is always true -- don't add anything + // the literal has no impact - skip it + continue; + } + // otherwise, add this literal to the clause + pLits[j++] = pLits[i]; + } + Msat_IntVecShrink( vLits, j ); + nLits = j; +/* + // the problem with this code is that performance is very + // sensitive to the ordering of adjacency lits + // the best ordering requires fanins first, next fanouts + // this ordering is more convenient to make from FRAIG + + // create the adjacency information + if ( nLits > 2 ) + { + Msat_Var_t VarI, VarJ; + Msat_IntVec_t * pAdjI, * pAdjJ; + + for ( i = 0; i < nLits; i++ ) + { + VarI = MSAT_LIT2VAR(pLits[i]); + pAdjI = (Msat_IntVec_t *)p->vAdjacents->pArray[VarI]; + + for ( j = i+1; j < nLits; j++ ) + { + VarJ = MSAT_LIT2VAR(pLits[j]); + pAdjJ = (Msat_IntVec_t *)p->vAdjacents->pArray[VarJ]; + + Msat_IntVecPushUniqueOrder( pAdjI, VarJ, 1 ); + Msat_IntVecPushUniqueOrder( pAdjJ, VarI, 1 ); + } + } + } +*/ + } + // 'vLits' is now the (possibly) reduced vector of literals. + if ( nLits == 0 ) + return 0; + if ( nLits == 1 ) + return Msat_SolverEnqueue( p, pLits[0], NULL ); + + // Allocate clause: +// nBytes = sizeof(unsigned)*(nLits + 1 + (int)fLearned); + nBytes = sizeof(unsigned)*(nLits + 2 + (int)fLearned); +#ifdef USE_SYSTEM_MEMORY_MANAGEMENT + pC = (Msat_Clause_t *)ALLOC( char, nBytes ); +#else + pC = (Msat_Clause_t *)Msat_MmStepEntryFetch( Msat_SolverReadMem(p), nBytes ); +#endif + pC->Num = p->nClauses++; + pC->fTypeA = 0; + pC->fMark = 0; + pC->fLearned = fLearned; + pC->nSize = nLits; + pC->nSizeAlloc = nBytes; + memcpy( pC->pData, pLits, sizeof(int)*nLits ); + + // For learnt clauses only: + if ( fLearned ) + { + int * pLevel = Msat_SolverReadDecisionLevelArray( p ); + int iLevelMax, iLevelCur, iLitMax; + + // Put the second watch on the literal with highest decision level: + iLitMax = 1; + iLevelMax = pLevel[ MSAT_LIT2VAR(pLits[1]) ]; + for ( i = 2; i < nLits; i++ ) + { + iLevelCur = pLevel[ MSAT_LIT2VAR(pLits[i]) ]; + assert( iLevelCur != -1 ); + if ( iLevelMax < iLevelCur ) + // this is very strange - shouldn't it be??? + // if ( iLevelMax > iLevelCur ) + iLevelMax = iLevelCur, iLitMax = i; + } + pC->pData[1] = pLits[iLitMax]; + pC->pData[iLitMax] = pLits[1]; + + // Bumping: + // (newly learnt clauses should be considered active) + Msat_ClauseWriteActivity( pC, 0.0 ); + Msat_SolverClaBumpActivity( p, pC ); +// if ( nLits < 20 ) + for ( i = 0; i < nLits; i++ ) + { + Msat_SolverVarBumpActivity( p, pLits[i] ); +// Msat_SolverVarBumpActivity( p, pLits[i] ); +// p->pFreq[ MSAT_LIT2VAR(pLits[i]) ]++; + } + } + + // Store clause: + pvWatched = Msat_SolverReadWatchedArray( p ); + Msat_ClauseVecPush( pvWatched[ MSAT_LITNOT(pC->pData[0]) ], pC ); + Msat_ClauseVecPush( pvWatched[ MSAT_LITNOT(pC->pData[1]) ], pC ); + *pClause_out = pC; + return 1; +} + +/**Function************************************************************* + + Synopsis [Deallocates the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClauseFree( Msat_Solver_t * p, Msat_Clause_t * pC, bool fRemoveWatched ) +{ + if ( fRemoveWatched ) + { + Msat_Lit_t Lit; + Msat_ClauseVec_t ** pvWatched; + pvWatched = Msat_SolverReadWatchedArray( p ); + Lit = MSAT_LITNOT( pC->pData[0] ); + Msat_ClauseRemoveWatch( pvWatched[Lit], pC ); + Lit = MSAT_LITNOT( pC->pData[1] ); + Msat_ClauseRemoveWatch( pvWatched[Lit], pC ); + } + +#ifdef USE_SYSTEM_MEMORY_MANAGEMENT + free( pC ); +#else + Msat_MmStepEntryRecycle( Msat_SolverReadMem(p), (char *)pC, pC->nSizeAlloc ); +#endif + +} + +/**Function************************************************************* + + Synopsis [Access the data field of the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_ClauseReadLearned( Msat_Clause_t * pC ) { return pC->fLearned; } +int Msat_ClauseReadSize( Msat_Clause_t * pC ) { return pC->nSize; } +int * Msat_ClauseReadLits( Msat_Clause_t * pC ) { return pC->pData; } +bool Msat_ClauseReadMark( Msat_Clause_t * pC ) { return pC->fMark; } +int Msat_ClauseReadNum( Msat_Clause_t * pC ) { return pC->Num; } +bool Msat_ClauseReadTypeA( Msat_Clause_t * pC ) { return pC->fTypeA; } + +void Msat_ClauseSetMark( Msat_Clause_t * pC, bool fMark ) { pC->fMark = fMark; } +void Msat_ClauseSetNum( Msat_Clause_t * pC, int Num ) { pC->Num = Num; } +void Msat_ClauseSetTypeA( Msat_Clause_t * pC, bool fTypeA ) { pC->fTypeA = fTypeA; } + +/**Function************************************************************* + + Synopsis [Checks whether the learned clause is locked.] + + Description [The clause may be locked if it is the reason of a + recent conflict. Such clause cannot be removed from the database.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_ClauseIsLocked( Msat_Solver_t * p, Msat_Clause_t * pC ) +{ + Msat_Clause_t ** pReasons = Msat_SolverReadReasonArray( p ); + return (bool)(pReasons[MSAT_LIT2VAR(pC->pData[0])] == pC); +} + +/**Function************************************************************* + + Synopsis [Reads the activity of the given clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Msat_ClauseReadActivity( Msat_Clause_t * pC ) +{ + return *((float *)(pC->pData + pC->nSize)); +} + +/**Function************************************************************* + + Synopsis [Sets the activity of the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClauseWriteActivity( Msat_Clause_t * pC, float Num ) +{ + *((float *)(pC->pData + pC->nSize)) = Num; +} + +/**Function************************************************************* + + Synopsis [Propages the assignment.] + + Description [The literal that has become true (Lit) is given to this + procedure. The array of current variable assignments is given for + efficiency. The output literal (pLit_out) can be the second watched + literal (if TRUE is returned) or the conflict literal (if FALSE is + returned). This messy interface is used to improve performance. + This procedure accounts for ~50% of the runtime of the solver.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_ClausePropagate( Msat_Clause_t * pC, Msat_Lit_t Lit, int * pAssigns, Msat_Lit_t * pLit_out ) +{ + // make sure the false literal is pC->pData[1] + Msat_Lit_t LitF = MSAT_LITNOT(Lit); + if ( pC->pData[0] == LitF ) + pC->pData[0] = pC->pData[1], pC->pData[1] = LitF; + assert( pC->pData[1] == LitF ); + // if the 0-th watch is true, clause is already satisfied + if ( pAssigns[MSAT_LIT2VAR(pC->pData[0])] == pC->pData[0] ) + return 1; + // look for a new watch + if ( pC->nSize > 2 ) + { + int i; + for ( i = 2; i < (int)pC->nSize; i++ ) + if ( pAssigns[MSAT_LIT2VAR(pC->pData[i])] != MSAT_LITNOT(pC->pData[i]) ) + { + pC->pData[1] = pC->pData[i], pC->pData[i] = LitF; + *pLit_out = MSAT_LITNOT(pC->pData[1]); + return 1; + } + } + // clause is unit under assignment + *pLit_out = pC->pData[0]; + return 0; +} + +/**Function************************************************************* + + Synopsis [Simplifies the clause.] + + Description [Assumes everything has been propagated! (esp. watches + in clauses are NOT unsatisfied)] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_ClauseSimplify( Msat_Clause_t * pC, int * pAssigns ) +{ + Msat_Var_t Var; + int i, j; + for ( i = j = 0; i < (int)pC->nSize; i++ ) + { + Var = MSAT_LIT2VAR(pC->pData[i]); + if ( pAssigns[Var] == MSAT_VAR_UNASSIGNED ) + { + pC->pData[j++] = pC->pData[i]; + continue; + } + if ( pAssigns[Var] == pC->pData[i] ) + return 1; + // otherwise, the value of the literal is false + // make sure, this literal is not watched + assert( i >= 2 ); + } + // if the size has changed, update it and move activity + if ( j < (int)pC->nSize ) + { + float Activ = Msat_ClauseReadActivity(pC); + pC->nSize = j; + Msat_ClauseWriteActivity(pC, Activ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Computes reason of conflict in the given clause.] + + Description [If the literal is unassigned, finds the reason by + complementing literals in the given cluase (pC). If the literal is + assigned, makes sure that this literal is the first one in the clause + and computes the complement of all other literals in the clause. + Returns the reason in the given array (vLits_out). If the clause is + learned, bumps its activity.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClauseCalcReason( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_Lit_t Lit, Msat_IntVec_t * vLits_out ) +{ + int i; + // clear the reason + Msat_IntVecClear( vLits_out ); + assert( Lit == MSAT_LIT_UNASSIGNED || Lit == pC->pData[0] ); + for ( i = (Lit != MSAT_LIT_UNASSIGNED); i < (int)pC->nSize; i++ ) + { + assert( Msat_SolverReadAssignsArray(p)[MSAT_LIT2VAR(pC->pData[i])] == MSAT_LITNOT(pC->pData[i]) ); + Msat_IntVecPush( vLits_out, MSAT_LITNOT(pC->pData[i]) ); + } + if ( pC->fLearned ) + Msat_SolverClaBumpActivity( p, pC ); +} + +/**Function************************************************************* + + Synopsis [Removes the given clause from the watched list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClauseRemoveWatch( Msat_ClauseVec_t * vClauses, Msat_Clause_t * pC ) +{ + Msat_Clause_t ** pClauses; + int nClauses, i; + nClauses = Msat_ClauseVecReadSize( vClauses ); + pClauses = Msat_ClauseVecReadArray( vClauses ); + for ( i = 0; pClauses[i] != pC; i++ ) + assert( i < nClauses ); + for ( ; i < nClauses - 1; i++ ) + pClauses[i] = pClauses[i+1]; + Msat_ClauseVecPop( vClauses ); +} + +/**Function************************************************************* + + Synopsis [Prints the given clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClausePrint( Msat_Clause_t * pC ) +{ + int i; + if ( pC == NULL ) + printf( "NULL pointer" ); + else + { + if ( pC->fLearned ) + printf( "Act = %.4f ", Msat_ClauseReadActivity(pC) ); + for ( i = 0; i < (int)pC->nSize; i++ ) + printf( " %s%d", ((pC->pData[i]&1)? "-": ""), pC->pData[i]/2 + 1 ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes the given clause in a file in DIMACS format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClauseWriteDimacs( FILE * pFile, Msat_Clause_t * pC, bool fIncrement ) +{ + int i; + for ( i = 0; i < (int)pC->nSize; i++ ) + fprintf( pFile, "%s%d ", ((pC->pData[i]&1)? "-": ""), pC->pData[i]/2 + (int)(fIncrement>0) ); + if ( fIncrement ) + fprintf( pFile, "0" ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the given clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClausePrintSymbols( Msat_Clause_t * pC ) +{ + int i; + if ( pC == NULL ) + printf( "NULL pointer" ); + else + { +// if ( pC->fLearned ) +// printf( "Act = %.4f ", Msat_ClauseReadActivity(pC) ); + for ( i = 0; i < (int)pC->nSize; i++ ) + printf(" "L_LIT, L_lit(pC->pData[i])); + } + printf( "\n" ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatClauseVec.c b/abc70930/src/sat/msat/msatClauseVec.c new file mode 100644 index 00000000..04691cf2 --- /dev/null +++ b/abc70930/src/sat/msat/msatClauseVec.c @@ -0,0 +1,232 @@ +/**CFile**************************************************************** + + FileName [msatClauseVec.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [Procedures working with arrays of SAT clauses.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatClauseVec.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_ClauseVec_t * Msat_ClauseVecAlloc( int nCap ) +{ + Msat_ClauseVec_t * p; + p = ALLOC( Msat_ClauseVec_t, 1 ); + if ( nCap > 0 && nCap < 16 ) + nCap = 16; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? ALLOC( Msat_Clause_t *, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClauseVecFree( Msat_ClauseVec_t * p ) +{ + FREE( p->pArray ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_Clause_t ** Msat_ClauseVecReadArray( Msat_ClauseVec_t * p ) +{ + return p->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_ClauseVecReadSize( Msat_ClauseVec_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClauseVecGrow( Msat_ClauseVec_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = REALLOC( Msat_Clause_t *, p->pArray, nCapMin ); + p->nCap = nCapMin; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClauseVecShrink( Msat_ClauseVec_t * p, int nSizeNew ) +{ + assert( p->nSize >= nSizeNew ); + p->nSize = nSizeNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClauseVecClear( Msat_ClauseVec_t * p ) +{ + p->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClauseVecPush( Msat_ClauseVec_t * p, Msat_Clause_t * Entry ) +{ + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Msat_ClauseVecGrow( p, 16 ); + else + Msat_ClauseVecGrow( p, 2 * p->nCap ); + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_Clause_t * Msat_ClauseVecPop( Msat_ClauseVec_t * p ) +{ + return p->pArray[--p->nSize]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_ClauseVecWriteEntry( Msat_ClauseVec_t * p, int i, Msat_Clause_t * Entry ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_Clause_t * Msat_ClauseVecReadEntry( Msat_ClauseVec_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatInt.h b/abc70930/src/sat/msat/msatInt.h new file mode 100644 index 00000000..03903abe --- /dev/null +++ b/abc70930/src/sat/msat/msatInt.h @@ -0,0 +1,306 @@ +/**CFile**************************************************************** + + FileName [msatInt.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [Internal definitions of the solver.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatInt.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __MSAT_INT_H__ +#define __MSAT_INT_H__ + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//#include "leaks.h" +#include +#include +#include +#include +#include +#include +#include "msat.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +typedef __int64 int64; +#else +typedef long long int64; +#endif + +// outputs the runtime in seconds +#define PRT(a,t) \ + printf( "%s = ", (a) ); printf( "%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) ) + +// memory management macros +#define ALLOC(type, num) \ + ((type *) malloc(sizeof(type) * (num))) +#define REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) +#define FREE(obj) \ + ((obj) ? (free((char *)(obj)), (obj) = 0) : 0) + +// By default, custom memory management is used +// which guarantees constant time allocation/deallocation +// for SAT clauses and other frequently modified objects. +// For debugging, it is possible use system memory management +// directly. In which case, uncomment the macro below. +//#define USE_SYSTEM_MEMORY_MANAGEMENT + +// internal data structures +typedef struct Msat_Clause_t_ Msat_Clause_t; +typedef struct Msat_Queue_t_ Msat_Queue_t; +typedef struct Msat_Order_t_ Msat_Order_t; +// memory managers (duplicated from Extra for stand-aloneness) +typedef struct Msat_MmFixed_t_ Msat_MmFixed_t; +typedef struct Msat_MmFlex_t_ Msat_MmFlex_t; +typedef struct Msat_MmStep_t_ Msat_MmStep_t; +// variables and literals +typedef int Msat_Lit_t; +typedef int Msat_Var_t; +// the type of return value +#define MSAT_VAR_UNASSIGNED (-1) +#define MSAT_LIT_UNASSIGNED (-2) +#define MSAT_ORDER_UNKNOWN (-3) + +// printing the search tree +#define L_IND "%-*d" +#define L_ind Msat_SolverReadDecisionLevel(p)*3+3,Msat_SolverReadDecisionLevel(p) +#define L_LIT "%s%d" +#define L_lit(Lit) MSAT_LITSIGN(Lit)?"-":"", MSAT_LIT2VAR(Lit)+1 + +typedef struct Msat_SolverStats_t_ Msat_SolverStats_t; +struct Msat_SolverStats_t_ +{ + int64 nStarts; // the number of restarts + int64 nDecisions; // the number of decisions + int64 nPropagations; // the number of implications + int64 nInspects; // the number of times clauses are vising while watching them + int64 nConflicts; // the number of conflicts + int64 nSuccesses; // the number of sat assignments found +}; + +typedef struct Msat_SearchParams_t_ Msat_SearchParams_t; +struct Msat_SearchParams_t_ +{ + double dVarDecay; + double dClaDecay; +}; + +// sat solver data structure visible through all the internal files +struct Msat_Solver_t_ +{ + int nClauses; // the total number of clauses + int nClausesStart; // the number of clauses before adding + Msat_ClauseVec_t * vClauses; // problem clauses + Msat_ClauseVec_t * vLearned; // learned clauses + double dClaInc; // Amount to bump next clause with. + double dClaDecay; // INVERSE decay factor for clause activity: stores 1/decay. + + double * pdActivity; // A heuristic measurement of the activity of a variable. + float * pFactors; // the multiplicative factors of variable activity + double dVarInc; // Amount to bump next variable with. + double dVarDecay; // INVERSE decay factor for variable activity: stores 1/decay. Use negative value for static variable order. + Msat_Order_t * pOrder; // Keeps track of the decision variable order. + + Msat_ClauseVec_t ** pvWatched; // 'pvWatched[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). + Msat_Queue_t * pQueue; // Propagation queue. + + int nVars; // the current number of variables + int nVarsAlloc; // the maximum allowed number of variables + int * pAssigns; // The current assignments (literals or MSAT_VAR_UNKOWN) + int * pModel; // The satisfying assignment + Msat_IntVec_t * vTrail; // List of assignments made. + Msat_IntVec_t * vTrailLim; // Separator indices for different decision levels in 'trail'. + Msat_Clause_t ** pReasons; // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none. + int * pLevel; // 'level[var]' is the decision level at which assignment was made. + int nLevelRoot; // Level of first proper decision. + + double dRandSeed; // For the internal random number generator (makes solver deterministic over different platforms). + + bool fVerbose; // the verbosity flag + double dProgress; // Set by 'search()'. + + // the variable cone and variable connectivity + Msat_IntVec_t * vConeVars; + Msat_IntVec_t * vVarsUsed; + Msat_ClauseVec_t * vAdjacents; + + // internal data used during conflict analysis + int * pSeen; // time when a lit was seen for the last time + int nSeenId; // the id of current seeing + Msat_IntVec_t * vReason; // the temporary array of literals + Msat_IntVec_t * vTemp; // the temporary array of literals + int * pFreq; // the number of times each var participated in conflicts + + // the memory manager + Msat_MmStep_t * pMem; + + // statistics + Msat_SolverStats_t Stats; + int nTwoLits; + int nTwoLitsL; + int nClausesInit; + int nClausesAlloc; + int nClausesAllocL; + int nBackTracks; +}; + +struct Msat_ClauseVec_t_ +{ + Msat_Clause_t ** pArray; + int nSize; + int nCap; +}; + +struct Msat_IntVec_t_ +{ + int * pArray; + int nSize; + int nCap; +}; + +//////////////////////////////////////////////////////////////////////// +/// GLOBAL VARIABLES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== satActivity.c ===========================================================*/ +extern void Msat_SolverVarDecayActivity( Msat_Solver_t * p ); +extern void Msat_SolverVarRescaleActivity( Msat_Solver_t * p ); +extern void Msat_SolverClaDecayActivity( Msat_Solver_t * p ); +extern void Msat_SolverClaRescaleActivity( Msat_Solver_t * p ); +/*=== satSolverApi.c ===========================================================*/ +extern Msat_Clause_t * Msat_SolverReadClause( Msat_Solver_t * p, int Num ); +/*=== satSolver.c ===========================================================*/ +extern int Msat_SolverReadDecisionLevel( Msat_Solver_t * p ); +extern int * Msat_SolverReadDecisionLevelArray( Msat_Solver_t * p ); +extern Msat_Clause_t ** Msat_SolverReadReasonArray( Msat_Solver_t * p ); +extern Msat_Type_t Msat_SolverReadVarValue( Msat_Solver_t * p, Msat_Var_t Var ); +extern Msat_ClauseVec_t * Msat_SolverReadLearned( Msat_Solver_t * p ); +extern Msat_ClauseVec_t ** Msat_SolverReadWatchedArray( Msat_Solver_t * p ); +extern int * Msat_SolverReadSeenArray( Msat_Solver_t * p ); +extern int Msat_SolverIncrementSeenId( Msat_Solver_t * p ); +extern Msat_MmStep_t * Msat_SolverReadMem( Msat_Solver_t * p ); +extern void Msat_SolverClausesIncrement( Msat_Solver_t * p ); +extern void Msat_SolverClausesDecrement( Msat_Solver_t * p ); +extern void Msat_SolverClausesIncrementL( Msat_Solver_t * p ); +extern void Msat_SolverClausesDecrementL( Msat_Solver_t * p ); +extern void Msat_SolverVarBumpActivity( Msat_Solver_t * p, Msat_Lit_t Lit ); +extern void Msat_SolverClaBumpActivity( Msat_Solver_t * p, Msat_Clause_t * pC ); +extern bool Msat_SolverEnqueue( Msat_Solver_t * p, Msat_Lit_t Lit, Msat_Clause_t * pC ); +extern double Msat_SolverProgressEstimate( Msat_Solver_t * p ); +/*=== satSolverSearch.c ===========================================================*/ +extern bool Msat_SolverAssume( Msat_Solver_t * p, Msat_Lit_t Lit ); +extern Msat_Clause_t * Msat_SolverPropagate( Msat_Solver_t * p ); +extern void Msat_SolverCancelUntil( Msat_Solver_t * p, int Level ); +extern Msat_Type_t Msat_SolverSearch( Msat_Solver_t * p, int nConfLimit, int nLearnedLimit, int nBackTrackLimit, Msat_SearchParams_t * pPars ); +/*=== satQueue.c ===========================================================*/ +extern Msat_Queue_t * Msat_QueueAlloc( int nVars ); +extern void Msat_QueueFree( Msat_Queue_t * p ); +extern int Msat_QueueReadSize( Msat_Queue_t * p ); +extern void Msat_QueueInsert( Msat_Queue_t * p, int Lit ); +extern int Msat_QueueExtract( Msat_Queue_t * p ); +extern void Msat_QueueClear( Msat_Queue_t * p ); +/*=== satOrder.c ===========================================================*/ +extern Msat_Order_t * Msat_OrderAlloc( Msat_Solver_t * pSat ); +extern void Msat_OrderSetBounds( Msat_Order_t * p, int nVarsMax ); +extern void Msat_OrderClean( Msat_Order_t * p, Msat_IntVec_t * vCone ); +extern int Msat_OrderCheck( Msat_Order_t * p ); +extern void Msat_OrderFree( Msat_Order_t * p ); +extern int Msat_OrderVarSelect( Msat_Order_t * p ); +extern void Msat_OrderVarAssigned( Msat_Order_t * p, int Var ); +extern void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var ); +extern void Msat_OrderUpdate( Msat_Order_t * p, int Var ); +/*=== satClause.c ===========================================================*/ +extern bool Msat_ClauseCreate( Msat_Solver_t * p, Msat_IntVec_t * vLits, bool fLearnt, Msat_Clause_t ** pClause_out ); +extern Msat_Clause_t * Msat_ClauseCreateFake( Msat_Solver_t * p, Msat_IntVec_t * vLits ); +extern Msat_Clause_t * Msat_ClauseCreateFakeLit( Msat_Solver_t * p, Msat_Lit_t Lit ); +extern bool Msat_ClauseReadLearned( Msat_Clause_t * pC ); +extern int Msat_ClauseReadSize( Msat_Clause_t * pC ); +extern int * Msat_ClauseReadLits( Msat_Clause_t * pC ); +extern bool Msat_ClauseReadMark( Msat_Clause_t * pC ); +extern void Msat_ClauseSetMark( Msat_Clause_t * pC, bool fMark ); +extern int Msat_ClauseReadNum( Msat_Clause_t * pC ); +extern void Msat_ClauseSetNum( Msat_Clause_t * pC, int Num ); +extern bool Msat_ClauseReadTypeA( Msat_Clause_t * pC ); +extern void Msat_ClauseSetTypeA( Msat_Clause_t * pC, bool fTypeA ); +extern bool Msat_ClauseIsLocked( Msat_Solver_t * p, Msat_Clause_t * pC ); +extern float Msat_ClauseReadActivity( Msat_Clause_t * pC ); +extern void Msat_ClauseWriteActivity( Msat_Clause_t * pC, float Num ); +extern void Msat_ClauseFree( Msat_Solver_t * p, Msat_Clause_t * pC, bool fRemoveWatched ); +extern bool Msat_ClausePropagate( Msat_Clause_t * pC, Msat_Lit_t Lit, int * pAssigns, Msat_Lit_t * pLit_out ); +extern bool Msat_ClauseSimplify( Msat_Clause_t * pC, int * pAssigns ); +extern void Msat_ClauseCalcReason( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_Lit_t Lit, Msat_IntVec_t * vLits_out ); +extern void Msat_ClauseRemoveWatch( Msat_ClauseVec_t * vClauses, Msat_Clause_t * pC ); +extern void Msat_ClausePrint( Msat_Clause_t * pC ); +extern void Msat_ClausePrintSymbols( Msat_Clause_t * pC ); +extern void Msat_ClauseWriteDimacs( FILE * pFile, Msat_Clause_t * pC, bool fIncrement ); +extern unsigned Msat_ClauseComputeTruth( Msat_Solver_t * p, Msat_Clause_t * pC ); +/*=== satSort.c ===========================================================*/ +extern void Msat_SolverSortDB( Msat_Solver_t * p ); +/*=== satClauseVec.c ===========================================================*/ +extern Msat_ClauseVec_t * Msat_ClauseVecAlloc( int nCap ); +extern void Msat_ClauseVecFree( Msat_ClauseVec_t * p ); +extern Msat_Clause_t ** Msat_ClauseVecReadArray( Msat_ClauseVec_t * p ); +extern int Msat_ClauseVecReadSize( Msat_ClauseVec_t * p ); +extern void Msat_ClauseVecGrow( Msat_ClauseVec_t * p, int nCapMin ); +extern void Msat_ClauseVecShrink( Msat_ClauseVec_t * p, int nSizeNew ); +extern void Msat_ClauseVecClear( Msat_ClauseVec_t * p ); +extern void Msat_ClauseVecPush( Msat_ClauseVec_t * p, Msat_Clause_t * Entry ); +extern Msat_Clause_t * Msat_ClauseVecPop( Msat_ClauseVec_t * p ); +extern void Msat_ClauseVecWriteEntry( Msat_ClauseVec_t * p, int i, Msat_Clause_t * Entry ); +extern Msat_Clause_t * Msat_ClauseVecReadEntry( Msat_ClauseVec_t * p, int i ); + +/*=== satMem.c ===========================================================*/ +// fixed-size-block memory manager +extern Msat_MmFixed_t * Msat_MmFixedStart( int nEntrySize ); +extern void Msat_MmFixedStop( Msat_MmFixed_t * p, int fVerbose ); +extern char * Msat_MmFixedEntryFetch( Msat_MmFixed_t * p ); +extern void Msat_MmFixedEntryRecycle( Msat_MmFixed_t * p, char * pEntry ); +extern void Msat_MmFixedRestart( Msat_MmFixed_t * p ); +extern int Msat_MmFixedReadMemUsage( Msat_MmFixed_t * p ); +// flexible-size-block memory manager +extern Msat_MmFlex_t * Msat_MmFlexStart(); +extern void Msat_MmFlexStop( Msat_MmFlex_t * p, int fVerbose ); +extern char * Msat_MmFlexEntryFetch( Msat_MmFlex_t * p, int nBytes ); +extern int Msat_MmFlexReadMemUsage( Msat_MmFlex_t * p ); +// hierarchical memory manager +extern Msat_MmStep_t * Msat_MmStepStart( int nSteps ); +extern void Msat_MmStepStop( Msat_MmStep_t * p, int fVerbose ); +extern char * Msat_MmStepEntryFetch( Msat_MmStep_t * p, int nBytes ); +extern void Msat_MmStepEntryRecycle( Msat_MmStep_t * p, char * pEntry, int nBytes ); +extern int Msat_MmStepReadMemUsage( Msat_MmStep_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// +#endif diff --git a/abc70930/src/sat/msat/msatMem.c b/abc70930/src/sat/msat/msatMem.c new file mode 100644 index 00000000..30bf4a96 --- /dev/null +++ b/abc70930/src/sat/msat/msatMem.c @@ -0,0 +1,529 @@ +/**CFile**************************************************************** + + FileName [msatMem.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [Memory managers borrowed from Extra.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatMem.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Msat_MmFixed_t_ +{ + // information about individual entries + int nEntrySize; // the size of one entry + int nEntriesAlloc; // the total number of entries allocated + int nEntriesUsed; // the number of entries in use + int nEntriesMax; // the max number of entries in use + char * pEntriesFree; // the linked list of free entries + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Msat_MmFlex_t_ +{ + // information about individual entries + int nEntriesUsed; // the number of entries allocated + char * pCurrent; // the current pointer to free memory + char * pEnd; // the first entry outside the free memory + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + + +struct Msat_MmStep_t_ +{ + int nMems; // the number of fixed memory managers employed + Msat_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc + int nMapSize; // the size of the memory array + Msat_MmFixed_t ** pMap; // maps the number of bytes into its memory manager +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates memory pieces of fixed size.] + + Description [The size of the chunk is computed as the minimum of + 1024 entries and 64K. Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_MmFixed_t * Msat_MmFixedStart( int nEntrySize ) +{ + Msat_MmFixed_t * p; + + p = ALLOC( Msat_MmFixed_t, 1 ); + memset( p, 0, sizeof(Msat_MmFixed_t) ); + + p->nEntrySize = nEntrySize; + p->nEntriesAlloc = 0; + p->nEntriesUsed = 0; + p->pEntriesFree = NULL; + + if ( nEntrySize * (1 << 10) < (1<<16) ) + p->nChunkSize = (1 << 10); + else + p->nChunkSize = (1<<16) / nEntrySize; + if ( p->nChunkSize < 8 ) + p->nChunkSize = 8; + + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_MmFixedStop( Msat_MmFixed_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", + p->nEntrySize, p->nChunkSize, p->nChunks ); + printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", + p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Msat_MmFixedEntryFetch( Msat_MmFixed_t * p ) +{ + char * pTemp; + int i; + + // check if there are still free entries + if ( p->nEntriesUsed == p->nEntriesAlloc ) + { // need to allocate more entries + assert( p->pEntriesFree == NULL ); + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); + p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; + // transform these entries into a linked list + pTemp = p->pEntriesFree; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pEntriesFree; + // add to the number of entries allocated + p->nEntriesAlloc += p->nChunkSize; + } + // incrememt the counter of used entries + p->nEntriesUsed++; + if ( p->nEntriesMax < p->nEntriesUsed ) + p->nEntriesMax = p->nEntriesUsed; + // return the first entry in the free entry list + pTemp = p->pEntriesFree; + p->pEntriesFree = *((char **)pTemp); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_MmFixedEntryRecycle( Msat_MmFixed_t * p, char * pEntry ) +{ + // decrement the counter of used entries + p->nEntriesUsed--; + // add the entry to the linked list of free entries + *((char **)pEntry) = p->pEntriesFree; + p->pEntriesFree = pEntry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_MmFixedRestart( Msat_MmFixed_t * p ) +{ + int i; + char * pTemp; + + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + p->nChunks = 1; + // transform these entries into a linked list + pTemp = p->pChunks[0]; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // set the free entry list + p->pEntriesFree = p->pChunks[0]; + // set the correct statistics + p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; + p->nMemoryUsed = 0; + p->nEntriesAlloc = p->nChunkSize; + p->nEntriesUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_MmFixedReadMemUsage( Msat_MmFixed_t * p ) +{ + return p->nMemoryAlloc; +} + + + +/**Function************************************************************* + + Synopsis [Allocates entries of flexible size.] + + Description [Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_MmFlex_t * Msat_MmFlexStart() +{ + Msat_MmFlex_t * p; + + p = ALLOC( Msat_MmFlex_t, 1 ); + memset( p, 0, sizeof(Msat_MmFlex_t) ); + + p->nEntriesUsed = 0; + p->pCurrent = NULL; + p->pEnd = NULL; + + p->nChunkSize = (1 << 12); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_MmFlexStop( Msat_MmFlex_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", + p->nChunkSize, p->nChunks ); + printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", + p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + free( p->pChunks[i] ); + free( p->pChunks ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Msat_MmFlexEntryFetch( Msat_MmFlex_t * p, int nBytes ) +{ + char * pTemp; + // check if there are still free entries + if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) + { // need to allocate more entries + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + if ( nBytes > p->nChunkSize ) + { + // resize the chunk size if more memory is requested than it can give + // (ideally, this should never happen) + p->nChunkSize = 2 * nBytes; + } + p->pCurrent = ALLOC( char, p->nChunkSize ); + p->pEnd = p->pCurrent + p->nChunkSize; + p->nMemoryAlloc += p->nChunkSize; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pCurrent; + } + assert( p->pCurrent + nBytes <= p->pEnd ); + // increment the counter of used entries + p->nEntriesUsed++; + // keep track of the memory used + p->nMemoryUsed += nBytes; + // return the next entry + pTemp = p->pCurrent; + p->pCurrent += nBytes; + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_MmFlexReadMemUsage( Msat_MmFlex_t * p ) +{ + return p->nMemoryAlloc; +} + + + + + +/**Function************************************************************* + + Synopsis [Starts the hierarchical memory manager.] + + Description [This manager can allocate entries of any size. + Iternally they are mapped into the entries with the number of bytes + equal to the power of 2. The smallest entry size is 8 bytes. The + next one is 16 bytes etc. So, if the user requests 6 bytes, he gets + 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. + The input parameters "nSteps" says how many fixed memory managers + are employed internally. Calling this procedure with nSteps equal + to 10 results in 10 hierarchically arranged internal memory managers, + which can allocate up to 4096 (1Kb) entries. Requests for larger + entries are handed over to malloc() and then free()ed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_MmStep_t * Msat_MmStepStart( int nSteps ) +{ + Msat_MmStep_t * p; + int i, k; + p = ALLOC( Msat_MmStep_t, 1 ); + p->nMems = nSteps; + // start the fixed memory managers + p->pMems = ALLOC( Msat_MmFixed_t *, p->nMems ); + for ( i = 0; i < p->nMems; i++ ) + p->pMems[i] = Msat_MmFixedStart( (8<nMapSize = (4<nMems); + p->pMap = ALLOC( Msat_MmFixed_t *, p->nMapSize+1 ); + p->pMap[0] = NULL; + for ( k = 1; k <= 4; k++ ) + p->pMap[k] = p->pMems[0]; + for ( i = 0; i < p->nMems; i++ ) + for ( k = (4<pMap[k] = p->pMems[i]; +//for ( i = 1; i < 100; i ++ ) +//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_MmStepStop( Msat_MmStep_t * p, int fVerbose ) +{ + int i; + for ( i = 0; i < p->nMems; i++ ) + Msat_MmFixedStop( p->pMems[i], fVerbose ); + free( p->pMems ); + free( p->pMap ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Creates the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Msat_MmStepEntryFetch( Msat_MmStep_t * p, int nBytes ) +{ + if ( nBytes == 0 ) + return NULL; + if ( nBytes > p->nMapSize ) + { +// printf( "Allocating %d bytes.\n", nBytes ); + return ALLOC( char, nBytes ); + } + return Msat_MmFixedEntryFetch( p->pMap[nBytes] ); +} + + +/**Function************************************************************* + + Synopsis [Recycles the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_MmStepEntryRecycle( Msat_MmStep_t * p, char * pEntry, int nBytes ) +{ + if ( nBytes == 0 ) + return; + if ( nBytes > p->nMapSize ) + { + free( pEntry ); + return; + } + Msat_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_MmStepReadMemUsage( Msat_MmStep_t * p ) +{ + int i, nMemTotal = 0; + for ( i = 0; i < p->nMems; i++ ) + nMemTotal += p->pMems[i]->nMemoryAlloc; + return nMemTotal; +} diff --git a/abc70930/src/sat/msat/msatOrderH.c b/abc70930/src/sat/msat/msatOrderH.c new file mode 100644 index 00000000..956e7fc6 --- /dev/null +++ b/abc70930/src/sat/msat/msatOrderH.c @@ -0,0 +1,405 @@ +/**CFile**************************************************************** + + FileName [msatOrder.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [The manager of variable assignment.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatOrder.c,v 1.0 2005/05/30 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the variable package data structure +struct Msat_Order_t_ +{ + Msat_Solver_t * pSat; // the SAT solver + Msat_IntVec_t * vIndex; // the heap + Msat_IntVec_t * vHeap; // the mapping of var num into its heap num +}; + +//The solver can communicate to the variable order the following parts: +//- the array of current assignments (pSat->pAssigns) +//- the array of variable activities (pSat->pdActivity) +//- the array of variables currently in the cone (pSat->vConeVars) +//- the array of arrays of variables adjucent to each(pSat->vAdjacents) + +#define HLEFT(i) ((i)<<1) +#define HRIGHT(i) (((i)<<1)+1) +#define HPARENT(i) ((i)>>1) +#define HCOMPARE(p, i, j) ((p)->pSat->pdActivity[i] > (p)->pSat->pdActivity[j]) +#define HHEAP(p, i) ((p)->vHeap->pArray[i]) +#define HSIZE(p) ((p)->vHeap->nSize) +#define HOKAY(p, i) ((i) >= 0 && (i) < (p)->vIndex->nSize) +#define HINHEAP(p, i) (HOKAY(p, i) && (p)->vIndex->pArray[i] != 0) +#define HEMPTY(p) (HSIZE(p) == 1) + +static int Msat_HeapCheck_rec( Msat_Order_t * p, int i ); +static int Msat_HeapGetTop( Msat_Order_t * p ); +static void Msat_HeapInsert( Msat_Order_t * p, int n ); +static void Msat_HeapIncrease( Msat_Order_t * p, int n ); +static void Msat_HeapPercolateUp( Msat_Order_t * p, int i ); +static void Msat_HeapPercolateDown( Msat_Order_t * p, int i ); + +extern int timeSelect; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the ordering structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_Order_t * Msat_OrderAlloc( Msat_Solver_t * pSat ) +{ + Msat_Order_t * p; + p = ALLOC( Msat_Order_t, 1 ); + memset( p, 0, sizeof(Msat_Order_t) ); + p->pSat = pSat; + p->vIndex = Msat_IntVecAlloc( 0 ); + p->vHeap = Msat_IntVecAlloc( 0 ); + Msat_OrderSetBounds( p, pSat->nVarsAlloc ); + return p; +} + +/**Function************************************************************* + + Synopsis [Sets the bound of the ordering structure.] + + Description [Should be called whenever the SAT solver is resized.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderSetBounds( Msat_Order_t * p, int nVarsMax ) +{ + Msat_IntVecGrow( p->vIndex, nVarsMax ); + Msat_IntVecGrow( p->vHeap, nVarsMax + 1 ); + p->vIndex->nSize = nVarsMax; + p->vHeap->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans the ordering structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderClean( Msat_Order_t * p, Msat_IntVec_t * vCone ) +{ + int i; + for ( i = 0; i < p->vIndex->nSize; i++ ) + p->vIndex->pArray[i] = 0; + for ( i = 0; i < vCone->nSize; i++ ) + { + assert( i+1 < p->vHeap->nCap ); + p->vHeap->pArray[i+1] = vCone->pArray[i]; + + assert( vCone->pArray[i] < p->vIndex->nSize ); + p->vIndex->pArray[vCone->pArray[i]] = i+1; + } + p->vHeap->nSize = vCone->nSize + 1; +} + +/**Function************************************************************* + + Synopsis [Checks that the J-boundary is okay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_OrderCheck( Msat_Order_t * p ) +{ + return Msat_HeapCheck_rec( p, 1 ); +} + +/**Function************************************************************* + + Synopsis [Frees the ordering structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderFree( Msat_Order_t * p ) +{ + Msat_IntVecFree( p->vHeap ); + Msat_IntVecFree( p->vIndex ); + free( p ); +} + + + +/**Function************************************************************* + + Synopsis [Selects the next variable to assign.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_OrderVarSelect( Msat_Order_t * p ) +{ + // Activity based decision: +// while (!heap.empty()){ +// Var next = heap.getmin(); +// if (toLbool(assigns[next]) == l_Undef) +// return next; +// } +// return var_Undef; + + int Var; + int clk = clock(); + + while ( !HEMPTY(p) ) + { + Var = Msat_HeapGetTop(p); + if ( (p)->pSat->pAssigns[Var] == MSAT_VAR_UNASSIGNED ) + { +//assert( Msat_OrderCheck(p) ); +timeSelect += clock() - clk; + return Var; + } + } + return MSAT_ORDER_UNKNOWN; +} + +/**Function************************************************************* + + Synopsis [Updates J-boundary when the variable is assigned.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderVarAssigned( Msat_Order_t * p, int Var ) +{ +} + +/**Function************************************************************* + + Synopsis [Updates the order after a variable is unassigned.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var ) +{ +// if (!heap.inHeap(x)) +// heap.insert(x); + + int clk = clock(); + if ( !HINHEAP(p,Var) ) + Msat_HeapInsert( p, Var ); +timeSelect += clock() - clk; +} + +/**Function************************************************************* + + Synopsis [Updates the order after a variable changed weight.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderUpdate( Msat_Order_t * p, int Var ) +{ +// if (heap.inHeap(x)) +// heap.increase(x); + + int clk = clock(); + if ( HINHEAP(p,Var) ) + Msat_HeapIncrease( p, Var ); +timeSelect += clock() - clk; +} + + + + +/**Function************************************************************* + + Synopsis [Checks the heap property recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_HeapCheck_rec( Msat_Order_t * p, int i ) +{ + return i >= HSIZE(p) || + ( HPARENT(i) == 0 || !HCOMPARE(p, HHEAP(p, i), HHEAP(p, HPARENT(i))) ) && + Msat_HeapCheck_rec( p, HLEFT(i) ) && Msat_HeapCheck_rec( p, HRIGHT(i) ); +} + +/**Function************************************************************* + + Synopsis [Retrieves the minimum element.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_HeapGetTop( Msat_Order_t * p ) +{ + int Result, NewTop; + Result = HHEAP(p, 1); + NewTop = Msat_IntVecPop( p->vHeap ); + p->vHeap->pArray[1] = NewTop; + p->vIndex->pArray[NewTop] = 1; + p->vIndex->pArray[Result] = 0; + if ( p->vHeap->nSize > 1 ) + Msat_HeapPercolateDown( p, 1 ); + return Result; +} + +/**Function************************************************************* + + Synopsis [Inserts the new element.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_HeapInsert( Msat_Order_t * p, int n ) +{ + assert( HOKAY(p, n) ); + p->vIndex->pArray[n] = HSIZE(p); + Msat_IntVecPush( p->vHeap, n ); + Msat_HeapPercolateUp( p, p->vIndex->pArray[n] ); +} + +/**Function************************************************************* + + Synopsis [Inserts the new element.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_HeapIncrease( Msat_Order_t * p, int n ) +{ + Msat_HeapPercolateUp( p, p->vIndex->pArray[n] ); +} + +/**Function************************************************************* + + Synopsis [Moves the entry up.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_HeapPercolateUp( Msat_Order_t * p, int i ) +{ + int x = HHEAP(p, i); + while ( HPARENT(i) != 0 && HCOMPARE(p, x, HHEAP(p, HPARENT(i))) ) + { + p->vHeap->pArray[i] = HHEAP(p, HPARENT(i)); + p->vIndex->pArray[HHEAP(p, i)] = i; + i = HPARENT(i); + } + p->vHeap->pArray[i] = x; + p->vIndex->pArray[x] = i; +} + +/**Function************************************************************* + + Synopsis [Moves the entry down.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_HeapPercolateDown( Msat_Order_t * p, int i ) +{ + int x = HHEAP(p, i); + int Child; + while ( HLEFT(i) < HSIZE(p) ) + { + if ( HRIGHT(i) < HSIZE(p) && HCOMPARE(p, HHEAP(p, HRIGHT(i)), HHEAP(p, HLEFT(i))) ) + Child = HRIGHT(i); + else + Child = HLEFT(i); + if ( !HCOMPARE(p, HHEAP(p, Child), x) ) + break; + p->vHeap->pArray[i] = HHEAP(p, Child); + p->vIndex->pArray[HHEAP(p, i)] = i; + i = Child; + } + p->vHeap->pArray[i] = x; + p->vIndex->pArray[x] = i; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatOrderJ.c b/abc70930/src/sat/msat/msatOrderJ.c new file mode 100644 index 00000000..4db7ff7b --- /dev/null +++ b/abc70930/src/sat/msat/msatOrderJ.c @@ -0,0 +1,472 @@ +/**CFile**************************************************************** + + FileName [msatOrder.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [The manager of variable assignment.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatOrder.c,v 1.0 2005/05/30 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +/* +The J-boundary (justification boundary) is defined as a set of unassigned +variables belonging to the cone of interest, such that for each of them, +there exist an adjacent assigned variable in the cone of interest. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Msat_OrderVar_t_ Msat_OrderVar_t; +typedef struct Msat_OrderRing_t_ Msat_OrderRing_t; + +// the variable data structure +struct Msat_OrderVar_t_ +{ + Msat_OrderVar_t * pNext; + Msat_OrderVar_t * pPrev; + int Num; +}; + +// the ring of variables data structure (J-boundary) +struct Msat_OrderRing_t_ +{ + Msat_OrderVar_t * pRoot; + int nItems; +}; + +// the variable package data structure +struct Msat_Order_t_ +{ + Msat_Solver_t * pSat; // the SAT solver + Msat_OrderVar_t * pVars; // the storage for variables + int nVarsAlloc; // the number of variables allocated + Msat_OrderRing_t rVars; // the J-boundary as a ring of variables +}; + +//The solver can communicate to the variable order the following parts: +//- the array of current assignments (pSat->pAssigns) +//- the array of variable activities (pSat->pdActivity) +//- the array of variables currently in the cone (pSat->vConeVars) +//- the array of arrays of variables adjucent to each(pSat->vAdjacents) + +#define Msat_OrderVarIsInBoundary( p, i ) ((p)->pVars[i].pNext) +#define Msat_OrderVarIsAssigned( p, i ) ((p)->pSat->pAssigns[i] != MSAT_VAR_UNASSIGNED) +#define Msat_OrderVarIsUsedInCone( p, i ) ((p)->pSat->vVarsUsed->pArray[i]) + +// iterator through the entries in J-boundary +#define Msat_OrderRingForEachEntry( pRing, pVar, pNext ) \ + for ( pVar = pRing, \ + pNext = pVar? pVar->pNext : NULL; \ + pVar; \ + pVar = (pNext != pRing)? pNext : NULL, \ + pNext = pVar? pVar->pNext : NULL ) + +static void Msat_OrderRingAddLast( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar ); +static void Msat_OrderRingRemove( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar ); + +extern int timeSelect; +extern int timeAssign; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the ordering structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_Order_t * Msat_OrderAlloc( Msat_Solver_t * pSat ) +{ + Msat_Order_t * p; + p = ALLOC( Msat_Order_t, 1 ); + memset( p, 0, sizeof(Msat_Order_t) ); + p->pSat = pSat; + Msat_OrderSetBounds( p, pSat->nVarsAlloc ); + return p; +} + +/**Function************************************************************* + + Synopsis [Sets the bound of the ordering structure.] + + Description [Should be called whenever the SAT solver is resized.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderSetBounds( Msat_Order_t * p, int nVarsMax ) +{ + int i; + // add variables if they are missing + if ( p->nVarsAlloc < nVarsMax ) + { + p->pVars = REALLOC( Msat_OrderVar_t, p->pVars, nVarsMax ); + for ( i = p->nVarsAlloc; i < nVarsMax; i++ ) + { + p->pVars[i].pNext = p->pVars[i].pPrev = NULL; + p->pVars[i].Num = i; + } + p->nVarsAlloc = nVarsMax; + } +} + +/**Function************************************************************* + + Synopsis [Cleans the ordering structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderClean( Msat_Order_t * p, Msat_IntVec_t * vCone ) +{ + Msat_OrderVar_t * pVar, * pNext; + // quickly undo the ring + Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext ) + pVar->pNext = pVar->pPrev = NULL; + p->rVars.pRoot = NULL; + p->rVars.nItems = 0; +} + +/**Function************************************************************* + + Synopsis [Checks that the J-boundary is okay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_OrderCheck( Msat_Order_t * p ) +{ + Msat_OrderVar_t * pVar, * pNext; + Msat_IntVec_t * vRound; + int * pRound, nRound; + int * pVars, nVars, i, k; + int Counter = 0; + + // go through all the variables in the boundary + Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext ) + { + assert( !Msat_OrderVarIsAssigned(p, pVar->Num) ); + // go though all the variables in the neighborhood + // and check that it is true that there is least one assigned + vRound = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( p->pSat->vAdjacents, pVar->Num ); + nRound = Msat_IntVecReadSize( vRound ); + pRound = Msat_IntVecReadArray( vRound ); + for ( i = 0; i < nRound; i++ ) + { + if ( !Msat_OrderVarIsUsedInCone(p, pRound[i]) ) + continue; + if ( Msat_OrderVarIsAssigned(p, pRound[i]) ) + break; + } +// assert( i != nRound ); +// if ( i == nRound ) +// return 0; + if ( i == nRound ) + Counter++; + } + if ( Counter > 0 ) + printf( "%d(%d) ", Counter, p->rVars.nItems ); + + // we may also check other unassigned variables in the cone + // to make sure that if they are not in J-boundary, + // then they do not have an assigned neighbor + nVars = Msat_IntVecReadSize( p->pSat->vConeVars ); + pVars = Msat_IntVecReadArray( p->pSat->vConeVars ); + for ( i = 0; i < nVars; i++ ) + { + assert( Msat_OrderVarIsUsedInCone(p, pVars[i]) ); + // skip assigned vars, vars in the boundary, and vars not used in the cone + if ( Msat_OrderVarIsAssigned(p, pVars[i]) || + Msat_OrderVarIsInBoundary(p, pVars[i]) ) + continue; + // make sure, it does not have assigned neighbors + vRound = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( p->pSat->vAdjacents, pVars[i] ); + nRound = Msat_IntVecReadSize( vRound ); + pRound = Msat_IntVecReadArray( vRound ); + for ( k = 0; k < nRound; k++ ) + { + if ( !Msat_OrderVarIsUsedInCone(p, pRound[k]) ) + continue; + if ( Msat_OrderVarIsAssigned(p, pRound[k]) ) + break; + } +// assert( k == nRound ); +// if ( k != nRound ) +// return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Frees the ordering structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderFree( Msat_Order_t * p ) +{ + free( p->pVars ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Selects the next variable to assign.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_OrderVarSelect( Msat_Order_t * p ) +{ + Msat_OrderVar_t * pVar, * pNext, * pVarBest; + double * pdActs = p->pSat->pdActivity; + double dfActBest; +// int clk = clock(); + + pVarBest = NULL; + dfActBest = -1.0; + Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext ) + { + if ( dfActBest < pdActs[pVar->Num] ) + { + dfActBest = pdActs[pVar->Num]; + pVarBest = pVar; + } + } +//timeSelect += clock() - clk; +//timeAssign += clock() - clk; + +//if ( pVarBest && pVarBest->Num % 1000 == 0 ) +//printf( "%d ", p->rVars.nItems ); + +// Msat_OrderCheck( p ); + if ( pVarBest ) + { + assert( Msat_OrderVarIsUsedInCone(p, pVarBest->Num) ); + return pVarBest->Num; + } + return MSAT_ORDER_UNKNOWN; +} + +/**Function************************************************************* + + Synopsis [Updates J-boundary when the variable is assigned.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderVarAssigned( Msat_Order_t * p, int Var ) +{ + Msat_IntVec_t * vRound; + int i;//, clk = clock(); + + // make sure the variable is in the boundary + assert( Var < p->nVarsAlloc ); + // if it is not in the boundary (initial decision, random decision), do not remove + if ( Msat_OrderVarIsInBoundary( p, Var ) ) + Msat_OrderRingRemove( &p->rVars, &p->pVars[Var] ); + // add to the boundary those neighbors that are (1) unassigned, (2) not in boundary + // because for them we know that there is a variable (Var) which is assigned + vRound = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[Var]; + for ( i = 0; i < vRound->nSize; i++ ) + { + if ( !Msat_OrderVarIsUsedInCone(p, vRound->pArray[i]) ) + continue; + if ( Msat_OrderVarIsAssigned(p, vRound->pArray[i]) ) + continue; + if ( Msat_OrderVarIsInBoundary(p, vRound->pArray[i]) ) + continue; + Msat_OrderRingAddLast( &p->rVars, &p->pVars[vRound->pArray[i]] ); + } +//timeSelect += clock() - clk; +// Msat_OrderCheck( p ); +} + +/**Function************************************************************* + + Synopsis [Updates the order after a variable is unassigned.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var ) +{ + Msat_IntVec_t * vRound, * vRound2; + int i, k;//, clk = clock(); + + // make sure the variable is not in the boundary + assert( Var < p->nVarsAlloc ); + assert( !Msat_OrderVarIsInBoundary( p, Var ) ); + // go through its neigbors - if one of them is assigned add this var + // add to the boundary those neighbors that are not there already + // this will also get rid of variable outside of the current cone + // because they are unassigned in Msat_SolverPrepare() + vRound = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[Var]; + for ( i = 0; i < vRound->nSize; i++ ) + if ( Msat_OrderVarIsAssigned(p, vRound->pArray[i]) ) + break; + if ( i != vRound->nSize ) + Msat_OrderRingAddLast( &p->rVars, &p->pVars[Var] ); + + // unassigning a variable may lead to its adjacents dropping from the boundary + for ( i = 0; i < vRound->nSize; i++ ) + if ( Msat_OrderVarIsInBoundary(p, vRound->pArray[i]) ) + { // the neighbor is in the J-boundary (and unassigned) + assert( !Msat_OrderVarIsAssigned(p, vRound->pArray[i]) ); + vRound2 = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[vRound->pArray[i]]; + // go through its neighbors and determine if there is at least one assigned + for ( k = 0; k < vRound2->nSize; k++ ) + if ( Msat_OrderVarIsAssigned(p, vRound2->pArray[k]) ) + break; + if ( k == vRound2->nSize ) // there is no assigned vars, delete this one + Msat_OrderRingRemove( &p->rVars, &p->pVars[vRound->pArray[i]] ); + } +//timeSelect += clock() - clk; +// Msat_OrderCheck( p ); +} + +/**Function************************************************************* + + Synopsis [Updates the order after a variable changed weight.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderUpdate( Msat_Order_t * p, int Var ) +{ +} + + +/**Function************************************************************* + + Synopsis [Adds node to the end of the ring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderRingAddLast( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar ) +{ +//printf( "adding %d\n", pVar->Num ); + // check that the node is not in a ring + assert( pVar->pPrev == NULL ); + assert( pVar->pNext == NULL ); + // if the ring is empty, make the node point to itself + pRing->nItems++; + if ( pRing->pRoot == NULL ) + { + pRing->pRoot = pVar; + pVar->pPrev = pVar; + pVar->pNext = pVar; + return; + } + // if the ring is not empty, add it as the last entry + pVar->pPrev = pRing->pRoot->pPrev; + pVar->pNext = pRing->pRoot; + pVar->pPrev->pNext = pVar; + pVar->pNext->pPrev = pVar; + + // move the root so that it points to the new entry +// pRing->pRoot = pRing->pRoot->pPrev; +} + +/**Function************************************************************* + + Synopsis [Removes the node from the ring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_OrderRingRemove( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar ) +{ +//printf( "removing %d\n", pVar->Num ); + // check that the var is in a ring + assert( pVar->pPrev ); + assert( pVar->pNext ); + pRing->nItems--; + if ( pRing->nItems == 0 ) + { + assert( pRing->pRoot == pVar ); + pVar->pPrev = NULL; + pVar->pNext = NULL; + pRing->pRoot = NULL; + return; + } + // move the root if needed + if ( pRing->pRoot == pVar ) + pRing->pRoot = pVar->pNext; + // move the root to the next entry after pVar + // this way all the additions to the list will be traversed first +// pRing->pRoot = pVar->pPrev; + // delete the node + pVar->pPrev->pNext = pVar->pNext; + pVar->pNext->pPrev = pVar->pPrev; + pVar->pPrev = NULL; + pVar->pNext = NULL; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatQueue.c b/abc70930/src/sat/msat/msatQueue.c new file mode 100644 index 00000000..5938e042 --- /dev/null +++ b/abc70930/src/sat/msat/msatQueue.c @@ -0,0 +1,157 @@ +/**CFile**************************************************************** + + FileName [msatQueue.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [The manager of the assignment propagation queue.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatQueue.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Msat_Queue_t_ +{ + int nVars; + int * pVars; + int iFirst; + int iLast; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the variable propagation queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_Queue_t * Msat_QueueAlloc( int nVars ) +{ + Msat_Queue_t * p; + p = ALLOC( Msat_Queue_t, 1 ); + memset( p, 0, sizeof(Msat_Queue_t) ); + p->nVars = nVars; + p->pVars = ALLOC( int, nVars ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocate the variable propagation queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_QueueFree( Msat_Queue_t * p ) +{ + free( p->pVars ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Reads the queue size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_QueueReadSize( Msat_Queue_t * p ) +{ + return p->iLast - p->iFirst; +} + +/**Function************************************************************* + + Synopsis [Insert an entry into the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_QueueInsert( Msat_Queue_t * p, int Lit ) +{ + if ( p->iLast == p->nVars ) + { + int i; + assert( 0 ); + for ( i = 0; i < p->iLast; i++ ) + printf( "entry = %2d lit = %2d var = %2d \n", i, p->pVars[i], p->pVars[i]/2 ); + } + assert( p->iLast < p->nVars ); + p->pVars[p->iLast++] = Lit; +} + +/**Function************************************************************* + + Synopsis [Extracts an entry from the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_QueueExtract( Msat_Queue_t * p ) +{ + if ( p->iFirst == p->iLast ) + return -1; + return p->pVars[p->iFirst++]; +} + +/**Function************************************************************* + + Synopsis [Resets the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_QueueClear( Msat_Queue_t * p ) +{ + p->iFirst = 0; + p->iLast = 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatRead.c b/abc70930/src/sat/msat/msatRead.c new file mode 100644 index 00000000..738562ef --- /dev/null +++ b/abc70930/src/sat/msat/msatRead.c @@ -0,0 +1,268 @@ +/**CFile**************************************************************** + + FileName [msatRead.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [The reader of the CNF formula in DIMACS format.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatRead.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static char * Msat_FileRead( FILE * pFile ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Read the file into the internal buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Msat_FileRead( FILE * pFile ) +{ + int nFileSize; + char * pBuffer; + // get the file size, in bytes + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + // move the file current reading position to the beginning + rewind( pFile ); + // load the contents of the file into memory + pBuffer = ALLOC( char, nFileSize + 3 ); + fread( pBuffer, nFileSize, 1, pFile ); + // terminate the string with '\0' + pBuffer[ nFileSize + 0] = '\n'; + pBuffer[ nFileSize + 1] = '\0'; + return pBuffer; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Msat_ReadWhitespace( char ** pIn ) +{ + while ((**pIn >= 9 && **pIn <= 13) || **pIn == 32) + (*pIn)++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Msat_ReadNotWhitespace( char ** pIn ) +{ + while ( !((**pIn >= 9 && **pIn <= 13) || **pIn == 32) ) + (*pIn)++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void skipLine( char ** pIn ) +{ + while ( 1 ) + { + if (**pIn == 0) + return; + if (**pIn == '\n') + { + (*pIn)++; + return; + } + (*pIn)++; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Msat_ReadInt( char ** pIn ) +{ + int val = 0; + bool neg = 0; + + Msat_ReadWhitespace( pIn ); + if ( **pIn == '-' ) + neg = 1, + (*pIn)++; + else if ( **pIn == '+' ) + (*pIn)++; + if ( **pIn < '0' || **pIn > '9' ) + fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", **pIn), + exit(1); + while ( **pIn >= '0' && **pIn <= '9' ) + val = val*10 + (**pIn - '0'), + (*pIn)++; + return neg ? -val : val; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Msat_ReadClause( char ** pIn, Msat_Solver_t * p, Msat_IntVec_t * pLits ) +{ + int nVars = Msat_SolverReadVarNum( p ); + int parsed_lit, var, sign; + + Msat_IntVecClear( pLits ); + while ( 1 ) + { + parsed_lit = Msat_ReadInt(pIn); + if ( parsed_lit == 0 ) + break; + var = abs(parsed_lit) - 1; + sign = (parsed_lit > 0); + if ( var >= nVars ) + { + printf( "Variable %d is larger than the number of allocated variables (%d).\n", var+1, nVars ); + exit(1); + } + Msat_IntVecPush( pLits, MSAT_VAR2LIT(var, !sign) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static bool Msat_ReadDimacs( char * pText, Msat_Solver_t ** pS, bool fVerbose ) +{ + Msat_Solver_t * p; + Msat_IntVec_t * pLits; + char * pIn = pText; + int nVars, nClas; + while ( 1 ) + { + Msat_ReadWhitespace( &pIn ); + if ( *pIn == 0 ) + break; + else if ( *pIn == 'c' ) + skipLine( &pIn ); + else if ( *pIn == 'p' ) + { + pIn++; + Msat_ReadWhitespace( &pIn ); + Msat_ReadNotWhitespace( &pIn ); + + nVars = Msat_ReadInt( &pIn ); + nClas = Msat_ReadInt( &pIn ); + skipLine( &pIn ); + // start the solver + p = Msat_SolverAlloc( nVars, 1, 1, 1, 1, 0 ); + Msat_SolverClean( p, nVars ); + Msat_SolverSetVerbosity( p, fVerbose ); + // allocate the vector + pLits = Msat_IntVecAlloc( nVars ); + } + else + { + if ( p == NULL ) + { + printf( "There is no parameter line.\n" ); + exit(1); + } + Msat_ReadClause( &pIn, p, pLits ); + if ( !Msat_SolverAddClause( p, pLits ) ) + return 0; + } + } + Msat_IntVecFree( pLits ); + *pS = p; + return Msat_SolverSimplifyDB( p ); +} + +/**Function************************************************************* + + Synopsis [Starts the solver and reads the DIMAC file.] + + Description [Returns FALSE upon immediate conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_SolverParseDimacs( FILE * pFile, Msat_Solver_t ** p, int fVerbose ) +{ + char * pText; + bool Value; + pText = Msat_FileRead( pFile ); + Value = Msat_ReadDimacs( pText, p, fVerbose ); + free( pText ); + return Value; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatSolverApi.c b/abc70930/src/sat/msat/msatSolverApi.c new file mode 100644 index 00000000..ee3507a6 --- /dev/null +++ b/abc70930/src/sat/msat/msatSolverApi.c @@ -0,0 +1,500 @@ +/**CFile**************************************************************** + + FileName [msatSolverApi.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [APIs of the SAT solver.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatSolverApi.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Msat_SolverSetupTruthTables( unsigned uTruths[][2] ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Simple SAT solver APIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_SolverReadVarNum( Msat_Solver_t * p ) { return p->nVars; } +int Msat_SolverReadClauseNum( Msat_Solver_t * p ) { return p->nClauses; } +int Msat_SolverReadVarAllocNum( Msat_Solver_t * p ) { return p->nVarsAlloc; } +int Msat_SolverReadDecisionLevel( Msat_Solver_t * p ) { return Msat_IntVecReadSize(p->vTrailLim); } +int * Msat_SolverReadDecisionLevelArray( Msat_Solver_t * p ) { return p->pLevel; } +Msat_Clause_t ** Msat_SolverReadReasonArray( Msat_Solver_t * p ) { return p->pReasons; } +Msat_Lit_t Msat_SolverReadVarValue( Msat_Solver_t * p, Msat_Var_t Var ) { return p->pAssigns[Var]; } +Msat_ClauseVec_t * Msat_SolverReadLearned( Msat_Solver_t * p ) { return p->vLearned; } +Msat_ClauseVec_t ** Msat_SolverReadWatchedArray( Msat_Solver_t * p ) { return p->pvWatched; } +int * Msat_SolverReadAssignsArray( Msat_Solver_t * p ) { return p->pAssigns; } +int * Msat_SolverReadModelArray( Msat_Solver_t * p ) { return p->pModel; } +int Msat_SolverReadBackTracks( Msat_Solver_t * p ) { return (int)p->Stats.nConflicts; } +int Msat_SolverReadInspects( Msat_Solver_t * p ) { return (int)p->Stats.nInspects; } +Msat_MmStep_t * Msat_SolverReadMem( Msat_Solver_t * p ) { return p->pMem; } +int * Msat_SolverReadSeenArray( Msat_Solver_t * p ) { return p->pSeen; } +int Msat_SolverIncrementSeenId( Msat_Solver_t * p ) { return ++p->nSeenId; } +void Msat_SolverSetVerbosity( Msat_Solver_t * p, int fVerbose ) { p->fVerbose = fVerbose; } +void Msat_SolverClausesIncrement( Msat_Solver_t * p ) { p->nClausesAlloc++; } +void Msat_SolverClausesDecrement( Msat_Solver_t * p ) { p->nClausesAlloc--; } +void Msat_SolverClausesIncrementL( Msat_Solver_t * p ) { p->nClausesAllocL++; } +void Msat_SolverClausesDecrementL( Msat_Solver_t * p ) { p->nClausesAllocL--; } +void Msat_SolverMarkLastClauseTypeA( Msat_Solver_t * p ) { Msat_ClauseSetTypeA( Msat_ClauseVecReadEntry( p->vClauses, Msat_ClauseVecReadSize(p->vClauses)-1 ), 1 ); } +void Msat_SolverMarkClausesStart( Msat_Solver_t * p ) { p->nClausesStart = Msat_ClauseVecReadSize(p->vClauses); } +float * Msat_SolverReadFactors( Msat_Solver_t * p ) { return p->pFactors; } + +/**Function************************************************************* + + Synopsis [Reads the clause with the given number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_Clause_t * Msat_SolverReadClause( Msat_Solver_t * p, int Num ) +{ + int nClausesP; + assert( Num < p->nClauses ); + nClausesP = Msat_ClauseVecReadSize( p->vClauses ); + if ( Num < nClausesP ) + return Msat_ClauseVecReadEntry( p->vClauses, Num ); + return Msat_ClauseVecReadEntry( p->vLearned, Num - nClausesP ); +} + +/**Function************************************************************* + + Synopsis [Reads the clause with the given number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_ClauseVec_t * Msat_SolverReadAdjacents( Msat_Solver_t * p ) +{ + return p->vAdjacents; +} + +/**Function************************************************************* + + Synopsis [Reads the clause with the given number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_IntVec_t * Msat_SolverReadConeVars( Msat_Solver_t * p ) +{ + return p->vConeVars; +} + +/**Function************************************************************* + + Synopsis [Reads the clause with the given number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_IntVec_t * Msat_SolverReadVarsUsed( Msat_Solver_t * p ) +{ + return p->vVarsUsed; +} + + +/**Function************************************************************* + + Synopsis [Allocates the solver.] + + Description [After the solver is allocated, the procedure + Msat_SolverClean() should be called to set the number of variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_Solver_t * Msat_SolverAlloc( int nVarsAlloc, + double dClaInc, double dClaDecay, + double dVarInc, double dVarDecay, + bool fVerbose ) +{ + Msat_Solver_t * p; + int i; + + assert(sizeof(Msat_Lit_t) == sizeof(unsigned)); + assert(sizeof(float) == sizeof(unsigned)); + + p = ALLOC( Msat_Solver_t, 1 ); + memset( p, 0, sizeof(Msat_Solver_t) ); + + p->nVarsAlloc = nVarsAlloc; + p->nVars = 0; + + p->nClauses = 0; + p->vClauses = Msat_ClauseVecAlloc( 512 ); + p->vLearned = Msat_ClauseVecAlloc( 512 ); + + p->dClaInc = dClaInc; + p->dClaDecay = dClaDecay; + p->dVarInc = dVarInc; + p->dVarDecay = dVarDecay; + + p->pdActivity = ALLOC( double, p->nVarsAlloc ); + p->pFactors = ALLOC( float, p->nVarsAlloc ); + for ( i = 0; i < p->nVarsAlloc; i++ ) + { + p->pdActivity[i] = 0.0; + p->pFactors[i] = 1.0; + } + + p->pAssigns = ALLOC( int, p->nVarsAlloc ); + p->pModel = ALLOC( int, p->nVarsAlloc ); + for ( i = 0; i < p->nVarsAlloc; i++ ) + p->pAssigns[i] = MSAT_VAR_UNASSIGNED; +// p->pOrder = Msat_OrderAlloc( p->pAssigns, p->pdActivity, p->nVarsAlloc ); + p->pOrder = Msat_OrderAlloc( p ); + + p->pvWatched = ALLOC( Msat_ClauseVec_t *, 2 * p->nVarsAlloc ); + for ( i = 0; i < 2 * p->nVarsAlloc; i++ ) + p->pvWatched[i] = Msat_ClauseVecAlloc( 16 ); + p->pQueue = Msat_QueueAlloc( p->nVarsAlloc ); + + p->vTrail = Msat_IntVecAlloc( p->nVarsAlloc ); + p->vTrailLim = Msat_IntVecAlloc( p->nVarsAlloc ); + p->pReasons = ALLOC( Msat_Clause_t *, p->nVarsAlloc ); + memset( p->pReasons, 0, sizeof(Msat_Clause_t *) * p->nVarsAlloc ); + p->pLevel = ALLOC( int, p->nVarsAlloc ); + for ( i = 0; i < p->nVarsAlloc; i++ ) + p->pLevel[i] = -1; + p->dRandSeed = 91648253; + p->fVerbose = fVerbose; + p->dProgress = 0.0; +// p->pModel = Msat_IntVecAlloc( p->nVarsAlloc ); + p->pMem = Msat_MmStepStart( 10 ); + + p->vConeVars = Msat_IntVecAlloc( p->nVarsAlloc ); + p->vAdjacents = Msat_ClauseVecAlloc( p->nVarsAlloc ); + for ( i = 0; i < p->nVarsAlloc; i++ ) + Msat_ClauseVecPush( p->vAdjacents, (Msat_Clause_t *)Msat_IntVecAlloc(5) ); + p->vVarsUsed = Msat_IntVecAlloc( p->nVarsAlloc ); + Msat_IntVecFill( p->vVarsUsed, p->nVarsAlloc, 1 ); + + + p->pSeen = ALLOC( int, p->nVarsAlloc ); + memset( p->pSeen, 0, sizeof(int) * p->nVarsAlloc ); + p->nSeenId = 1; + p->vReason = Msat_IntVecAlloc( p->nVarsAlloc ); + p->vTemp = Msat_IntVecAlloc( p->nVarsAlloc ); + return p; +} + +/**Function************************************************************* + + Synopsis [Resizes the solver.] + + Description [Assumes that the solver contains some clauses, and that + it is currently between the calls. Resizes the solver to accomodate + more variables.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverResize( Msat_Solver_t * p, int nVarsAlloc ) +{ + int nVarsAllocOld, i; + + nVarsAllocOld = p->nVarsAlloc; + p->nVarsAlloc = nVarsAlloc; + + p->pdActivity = REALLOC( double, p->pdActivity, p->nVarsAlloc ); + p->pFactors = REALLOC( float, p->pFactors, p->nVarsAlloc ); + for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ ) + { + p->pdActivity[i] = 0.0; + p->pFactors[i] = 1.0; + } + + p->pAssigns = REALLOC( int, p->pAssigns, p->nVarsAlloc ); + p->pModel = REALLOC( int, p->pModel, p->nVarsAlloc ); + for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ ) + p->pAssigns[i] = MSAT_VAR_UNASSIGNED; + +// Msat_OrderRealloc( p->pOrder, p->pAssigns, p->pdActivity, p->nVarsAlloc ); + Msat_OrderSetBounds( p->pOrder, p->nVarsAlloc ); + + p->pvWatched = REALLOC( Msat_ClauseVec_t *, p->pvWatched, 2 * p->nVarsAlloc ); + for ( i = 2 * nVarsAllocOld; i < 2 * p->nVarsAlloc; i++ ) + p->pvWatched[i] = Msat_ClauseVecAlloc( 16 ); + + Msat_QueueFree( p->pQueue ); + p->pQueue = Msat_QueueAlloc( p->nVarsAlloc ); + + p->pReasons = REALLOC( Msat_Clause_t *, p->pReasons, p->nVarsAlloc ); + p->pLevel = REALLOC( int, p->pLevel, p->nVarsAlloc ); + for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ ) + { + p->pReasons[i] = NULL; + p->pLevel[i] = -1; + } + + p->pSeen = REALLOC( int, p->pSeen, p->nVarsAlloc ); + for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ ) + p->pSeen[i] = 0; + + Msat_IntVecGrow( p->vTrail, p->nVarsAlloc ); + Msat_IntVecGrow( p->vTrailLim, p->nVarsAlloc ); + + // make sure the array of adjucents has room to store the variable numbers + for ( i = Msat_ClauseVecReadSize(p->vAdjacents); i < p->nVarsAlloc; i++ ) + Msat_ClauseVecPush( p->vAdjacents, (Msat_Clause_t *)Msat_IntVecAlloc(5) ); + Msat_IntVecFill( p->vVarsUsed, p->nVarsAlloc, 1 ); +} + +/**Function************************************************************* + + Synopsis [Prepares the solver.] + + Description [Cleans the solver assuming that the problem will involve + the given number of variables (nVars). This procedure is useful + for many small (incremental) SAT problems, to prevent the solver + from being reallocated each time.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverClean( Msat_Solver_t * p, int nVars ) +{ + int i; + // free the clauses + int nClauses; + Msat_Clause_t ** pClauses; + + assert( p->nVarsAlloc >= nVars ); + p->nVars = nVars; + p->nClauses = 0; + + nClauses = Msat_ClauseVecReadSize( p->vClauses ); + pClauses = Msat_ClauseVecReadArray( p->vClauses ); + for ( i = 0; i < nClauses; i++ ) + Msat_ClauseFree( p, pClauses[i], 0 ); +// Msat_ClauseVecFree( p->vClauses ); + Msat_ClauseVecClear( p->vClauses ); + + nClauses = Msat_ClauseVecReadSize( p->vLearned ); + pClauses = Msat_ClauseVecReadArray( p->vLearned ); + for ( i = 0; i < nClauses; i++ ) + Msat_ClauseFree( p, pClauses[i], 0 ); +// Msat_ClauseVecFree( p->vLearned ); + Msat_ClauseVecClear( p->vLearned ); + +// FREE( p->pdActivity ); + for ( i = 0; i < p->nVars; i++ ) + p->pdActivity[i] = 0; + +// Msat_OrderFree( p->pOrder ); +// Msat_OrderClean( p->pOrder, p->nVars, NULL ); + Msat_OrderSetBounds( p->pOrder, p->nVars ); + + for ( i = 0; i < 2 * p->nVars; i++ ) +// Msat_ClauseVecFree( p->pvWatched[i] ); + Msat_ClauseVecClear( p->pvWatched[i] ); +// FREE( p->pvWatched ); +// Msat_QueueFree( p->pQueue ); + Msat_QueueClear( p->pQueue ); + +// FREE( p->pAssigns ); + for ( i = 0; i < p->nVars; i++ ) + p->pAssigns[i] = MSAT_VAR_UNASSIGNED; +// Msat_IntVecFree( p->vTrail ); + Msat_IntVecClear( p->vTrail ); +// Msat_IntVecFree( p->vTrailLim ); + Msat_IntVecClear( p->vTrailLim ); +// FREE( p->pReasons ); + memset( p->pReasons, 0, sizeof(Msat_Clause_t *) * p->nVars ); +// FREE( p->pLevel ); + for ( i = 0; i < p->nVars; i++ ) + p->pLevel[i] = -1; +// Msat_IntVecFree( p->pModel ); +// Msat_MmStepStop( p->pMem, 0 ); + p->dRandSeed = 91648253; + p->dProgress = 0.0; + +// FREE( p->pSeen ); + memset( p->pSeen, 0, sizeof(int) * p->nVars ); + p->nSeenId = 1; +// Msat_IntVecFree( p->vReason ); + Msat_IntVecClear( p->vReason ); +// Msat_IntVecFree( p->vTemp ); + Msat_IntVecClear( p->vTemp ); +// printf(" The number of clauses remaining = %d (%d).\n", p->nClausesAlloc, p->nClausesAllocL ); +// FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Frees the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverFree( Msat_Solver_t * p ) +{ + int i; + + // free the clauses + int nClauses; + Msat_Clause_t ** pClauses; +//printf( "clauses = %d. learned = %d.\n", Msat_ClauseVecReadSize( p->vClauses ), +// Msat_ClauseVecReadSize( p->vLearned ) ); + + nClauses = Msat_ClauseVecReadSize( p->vClauses ); + pClauses = Msat_ClauseVecReadArray( p->vClauses ); + for ( i = 0; i < nClauses; i++ ) + Msat_ClauseFree( p, pClauses[i], 0 ); + Msat_ClauseVecFree( p->vClauses ); + + nClauses = Msat_ClauseVecReadSize( p->vLearned ); + pClauses = Msat_ClauseVecReadArray( p->vLearned ); + for ( i = 0; i < nClauses; i++ ) + Msat_ClauseFree( p, pClauses[i], 0 ); + Msat_ClauseVecFree( p->vLearned ); + + FREE( p->pdActivity ); + FREE( p->pFactors ); + Msat_OrderFree( p->pOrder ); + + for ( i = 0; i < 2 * p->nVarsAlloc; i++ ) + Msat_ClauseVecFree( p->pvWatched[i] ); + FREE( p->pvWatched ); + Msat_QueueFree( p->pQueue ); + + FREE( p->pAssigns ); + FREE( p->pModel ); + Msat_IntVecFree( p->vTrail ); + Msat_IntVecFree( p->vTrailLim ); + FREE( p->pReasons ); + FREE( p->pLevel ); + + Msat_MmStepStop( p->pMem, 0 ); + + nClauses = Msat_ClauseVecReadSize( p->vAdjacents ); + pClauses = Msat_ClauseVecReadArray( p->vAdjacents ); + for ( i = 0; i < nClauses; i++ ) + Msat_IntVecFree( (Msat_IntVec_t *)pClauses[i] ); + Msat_ClauseVecFree( p->vAdjacents ); + Msat_IntVecFree( p->vConeVars ); + Msat_IntVecFree( p->vVarsUsed ); + + FREE( p->pSeen ); + Msat_IntVecFree( p->vReason ); + Msat_IntVecFree( p->vTemp ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Prepares the solver to run on a subset of variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverPrepare( Msat_Solver_t * p, Msat_IntVec_t * vVars ) +{ + + int i; + // undo the previous data + for ( i = 0; i < p->nVarsAlloc; i++ ) + { + p->pAssigns[i] = MSAT_VAR_UNASSIGNED; + p->pReasons[i] = NULL; + p->pLevel[i] = -1; + p->pdActivity[i] = 0.0; + } + + // set the new variable order + Msat_OrderClean( p->pOrder, vVars ); + + Msat_QueueClear( p->pQueue ); + Msat_IntVecClear( p->vTrail ); + Msat_IntVecClear( p->vTrailLim ); + p->dProgress = 0.0; +} + +/**Function************************************************************* + + Synopsis [Sets up the truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverSetupTruthTables( unsigned uTruths[][2] ) +{ + int m, v; + // set up the truth tables + for ( m = 0; m < 32; m++ ) + for ( v = 0; v < 5; v++ ) + if ( m & (1 << v) ) + uTruths[v][0] |= (1 << m); + // make adjustments for the case of 6 variables + for ( v = 0; v < 5; v++ ) + uTruths[v][1] = uTruths[v][0]; + uTruths[5][0] = 0; + uTruths[5][1] = ~((unsigned)0); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatSolverCore.c b/abc70930/src/sat/msat/msatSolverCore.c new file mode 100644 index 00000000..f9fee73c --- /dev/null +++ b/abc70930/src/sat/msat/msatSolverCore.c @@ -0,0 +1,212 @@ +/**CFile**************************************************************** + + FileName [msatSolverCore.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [The SAT solver core procedures.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatSolverCore.c,v 1.2 2004/05/12 03:37:40 satrajit Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Adds one variable to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_SolverAddVar( Msat_Solver_t * p, int Level ) +{ + if ( p->nVars == p->nVarsAlloc ) + Msat_SolverResize( p, 2 * p->nVarsAlloc ); + p->pLevel[p->nVars] = Level; + p->nVars++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds one clause to the solver's clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_SolverAddClause( Msat_Solver_t * p, Msat_IntVec_t * vLits ) +{ + Msat_Clause_t * pC; + bool Value; + Value = Msat_ClauseCreate( p, vLits, 0, &pC ); + if ( pC != NULL ) + Msat_ClauseVecPush( p->vClauses, pC ); +// else if ( p->fProof ) +// Msat_ClauseCreateFake( p, vLits ); + return Value; +} + +/**Function************************************************************* + + Synopsis [Returns search-space coverage. Not extremely reliable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +double Msat_SolverProgressEstimate( Msat_Solver_t * p ) +{ + double dProgress = 0.0; + double dF = 1.0 / p->nVars; + int i; + for ( i = 0; i < p->nVars; i++ ) + if ( p->pAssigns[i] != MSAT_VAR_UNASSIGNED ) + dProgress += pow( dF, p->pLevel[i] ); + return dProgress / p->nVars; +} + +/**Function************************************************************* + + Synopsis [Prints statistics about the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverPrintStats( Msat_Solver_t * p ) +{ + printf("C solver (%d vars; %d clauses; %d learned):\n", + p->nVars, Msat_ClauseVecReadSize(p->vClauses), Msat_ClauseVecReadSize(p->vLearned) ); + printf("starts : %lld\n", p->Stats.nStarts); + printf("conflicts : %lld\n", p->Stats.nConflicts); + printf("decisions : %lld\n", p->Stats.nDecisions); + printf("propagations : %lld\n", p->Stats.nPropagations); + printf("inspects : %lld\n", p->Stats.nInspects); +} + +/**Function************************************************************* + + Synopsis [Top-level solve.] + + Description [If using assumptions (non-empty 'assumps' vector), you must + call 'simplifyDB()' first to see that no top-level conflict is present + (which would put the solver in an undefined state. If the last argument + is given (vProj), the solver enumerates through the satisfying solutions, + which are projected on the variables listed in this array. Note that the + variables in the array may be complemented, in which case the derived + assignment for the variable is complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * vAssumps, int nBackTrackLimit, int nTimeLimit ) +{ + Msat_SearchParams_t Params = { 0.95, 0.999 }; + double nConflictsLimit, nLearnedLimit; + Msat_Type_t Status; + int timeStart = clock(); + int64 nConflictsOld = p->Stats.nConflicts; + int64 nDecisionsOld = p->Stats.nDecisions; + +// p->pFreq = ALLOC( int, p->nVarsAlloc ); +// memset( p->pFreq, 0, sizeof(int) * p->nVarsAlloc ); + + if ( vAssumps ) + { + int * pAssumps, nAssumps, i; + + assert( Msat_IntVecReadSize(p->vTrailLim) == 0 ); + + nAssumps = Msat_IntVecReadSize( vAssumps ); + pAssumps = Msat_IntVecReadArray( vAssumps ); + for ( i = 0; i < nAssumps; i++ ) + { + if ( !Msat_SolverAssume(p, pAssumps[i]) || Msat_SolverPropagate(p) ) + { + Msat_QueueClear( p->pQueue ); + Msat_SolverCancelUntil( p, 0 ); + return MSAT_FALSE; + } + } + } + p->nLevelRoot = Msat_SolverReadDecisionLevel(p); + p->nClausesInit = Msat_ClauseVecReadSize( p->vClauses ); + nConflictsLimit = 100; + nLearnedLimit = Msat_ClauseVecReadSize(p->vClauses) / 3; + Status = MSAT_UNKNOWN; + p->nBackTracks = (int)p->Stats.nConflicts; + while ( Status == MSAT_UNKNOWN ) + { + if ( p->fVerbose ) + printf("Solving -- conflicts=%d learnts=%d progress=%.4f %%\n", + (int)nConflictsLimit, (int)nLearnedLimit, p->dProgress*100); + Status = Msat_SolverSearch( p, (int)nConflictsLimit, (int)nLearnedLimit, nBackTrackLimit, &Params ); + nConflictsLimit *= 1.5; + nLearnedLimit *= 1.1; + // if the limit on the number of backtracks is given, quit the restart loop + if ( nBackTrackLimit > 0 && (int)p->Stats.nConflicts - p->nBackTracks > nBackTrackLimit ) + break; + // if the runtime limit is exceeded, quit the restart loop + if ( nTimeLimit > 0 && clock() - timeStart >= nTimeLimit * CLOCKS_PER_SEC ) + break; + } + Msat_SolverCancelUntil( p, 0 ); + p->nBackTracks = (int)p->Stats.nConflicts - p->nBackTracks; +/* + PRT( "True solver runtime", clock() - timeStart ); + // print the statistics + { + int i, Counter = 0; + for ( i = 0; i < p->nVars; i++ ) + if ( p->pFreq[i] > 0 ) + { + printf( "%d ", p->pFreq[i] ); + Counter++; + } + if ( Counter ) + printf( "\n" ); + printf( "Total = %d. Used = %d. Decisions = %d. Imps = %d. Conflicts = %d. ", p->nVars, Counter, (int)p->Stats.nDecisions, (int)p->Stats.nPropagations, (int)p->Stats.nConflicts ); + PRT( "Time", clock() - timeStart ); + } +*/ + return Status; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatSolverIo.c b/abc70930/src/sat/msat/msatSolverIo.c new file mode 100644 index 00000000..05b7f6a9 --- /dev/null +++ b/abc70930/src/sat/msat/msatSolverIo.c @@ -0,0 +1,177 @@ +/**CFile**************************************************************** + + FileName [msatSolverIo.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [Input/output of CNFs.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatSolverIo.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static char * Msat_TimeStamp(); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverPrintAssignment( Msat_Solver_t * p ) +{ + int i; + printf( "Current assignments are: \n" ); + for ( i = 0; i < p->nVars; i++ ) + printf( "%d", i % 10 ); + printf( "\n" ); + for ( i = 0; i < p->nVars; i++ ) + if ( p->pAssigns[i] == MSAT_VAR_UNASSIGNED ) + printf( "." ); + else + { + assert( i == MSAT_LIT2VAR(p->pAssigns[i]) ); + if ( MSAT_LITSIGN(p->pAssigns[i]) ) + printf( "0" ); + else + printf( "1" ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverPrintClauses( Msat_Solver_t * p ) +{ + Msat_Clause_t ** pClauses; + int nClauses, i; + + printf( "Original clauses: \n" ); + nClauses = Msat_ClauseVecReadSize( p->vClauses ); + pClauses = Msat_ClauseVecReadArray( p->vClauses ); + for ( i = 0; i < nClauses; i++ ) + { + printf( "%3d: ", i ); + Msat_ClausePrint( pClauses[i] ); + } + + printf( "Learned clauses: \n" ); + nClauses = Msat_ClauseVecReadSize( p->vLearned ); + pClauses = Msat_ClauseVecReadArray( p->vLearned ); + for ( i = 0; i < nClauses; i++ ) + { + printf( "%3d: ", i ); + Msat_ClausePrint( pClauses[i] ); + } + + printf( "Variable activity: \n" ); + for ( i = 0; i < p->nVars; i++ ) + printf( "%3d : %.4f\n", i, p->pdActivity[i] ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverWriteDimacs( Msat_Solver_t * p, char * pFileName ) +{ + FILE * pFile; + Msat_Clause_t ** pClauses; + int nClauses, i; + + nClauses = Msat_ClauseVecReadSize(p->vClauses) + Msat_ClauseVecReadSize(p->vLearned); + for ( i = 0; i < p->nVars; i++ ) + nClauses += ( p->pLevel[i] == 0 ); + + pFile = fopen( pFileName, "wb" ); + fprintf( pFile, "c Produced by Msat_SolverWriteDimacs() on %s\n", Msat_TimeStamp() ); + fprintf( pFile, "p cnf %d %d\n", p->nVars, nClauses ); + + nClauses = Msat_ClauseVecReadSize( p->vClauses ); + pClauses = Msat_ClauseVecReadArray( p->vClauses ); + for ( i = 0; i < nClauses; i++ ) + Msat_ClauseWriteDimacs( pFile, pClauses[i], 1 ); + + nClauses = Msat_ClauseVecReadSize( p->vLearned ); + pClauses = Msat_ClauseVecReadArray( p->vLearned ); + for ( i = 0; i < nClauses; i++ ) + Msat_ClauseWriteDimacs( pFile, pClauses[i], 1 ); + + // write zero-level assertions + for ( i = 0; i < p->nVars; i++ ) + if ( p->pLevel[i] == 0 ) + fprintf( pFile, "%s%d 0\n", ((p->pAssigns[i]&1)? "-": ""), i + 1 ); + + fprintf( pFile, "\n" ); + fclose( pFile ); +} + + +/**Function************************************************************* + + Synopsis [Returns the time stamp.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Msat_TimeStamp() +{ + static char Buffer[100]; + time_t ltime; + char * TimeStamp; + // get the current time + time( <ime ); + TimeStamp = asctime( localtime( <ime ) ); + TimeStamp[ strlen(TimeStamp) - 1 ] = 0; + strcpy( Buffer, TimeStamp ); + return Buffer; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatSolverSearch.c b/abc70930/src/sat/msat/msatSolverSearch.c new file mode 100644 index 00000000..11a6540c --- /dev/null +++ b/abc70930/src/sat/msat/msatSolverSearch.c @@ -0,0 +1,629 @@ +/**CFile**************************************************************** + + FileName [msatSolverSearch.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [The search part of the solver.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatSolverSearch.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Msat_SolverUndoOne( Msat_Solver_t * p ); +static void Msat_SolverCancel( Msat_Solver_t * p ); +static Msat_Clause_t * Msat_SolverRecord( Msat_Solver_t * p, Msat_IntVec_t * vLits ); +static void Msat_SolverAnalyze( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_IntVec_t * vLits_out, int * pLevel_out ); +static void Msat_SolverReduceDB( Msat_Solver_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Makes the next assumption (Lit).] + + Description [Returns FALSE if immediate conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_SolverAssume( Msat_Solver_t * p, Msat_Lit_t Lit ) +{ + assert( Msat_QueueReadSize(p->pQueue) == 0 ); + if ( p->fVerbose ) + printf(L_IND"assume("L_LIT")\n", L_ind, L_lit(Lit)); + Msat_IntVecPush( p->vTrailLim, Msat_IntVecReadSize(p->vTrail) ); +// assert( Msat_IntVecReadSize(p->vTrailLim) <= Msat_IntVecReadSize(p->vTrail) + 1 ); +// assert( Msat_IntVecReadSize( p->vTrailLim ) < p->nVars ); + return Msat_SolverEnqueue( p, Lit, NULL ); +} + +/**Function************************************************************* + + Synopsis [Reverts one variable binding on the trail.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverUndoOne( Msat_Solver_t * p ) +{ + Msat_Lit_t Lit; + Msat_Var_t Var; + Lit = Msat_IntVecPop( p->vTrail ); + Var = MSAT_LIT2VAR(Lit); + p->pAssigns[Var] = MSAT_VAR_UNASSIGNED; + p->pReasons[Var] = NULL; + p->pLevel[Var] = -1; +// Msat_OrderUndo( p->pOrder, Var ); + Msat_OrderVarUnassigned( p->pOrder, Var ); + + if ( p->fVerbose ) + printf(L_IND"unbind("L_LIT")\n", L_ind, L_lit(Lit)); +} + +/**Function************************************************************* + + Synopsis [Reverts to the state before last Msat_SolverAssume().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverCancel( Msat_Solver_t * p ) +{ + int c; + assert( Msat_QueueReadSize(p->pQueue) == 0 ); + if ( p->fVerbose ) + { + if ( Msat_IntVecReadSize(p->vTrail) != Msat_IntVecReadEntryLast(p->vTrailLim) ) + { + Msat_Lit_t Lit; + Lit = Msat_IntVecReadEntry( p->vTrail, Msat_IntVecReadEntryLast(p->vTrailLim) ); + printf(L_IND"cancel("L_LIT")\n", L_ind, L_lit(Lit)); + } + } + for ( c = Msat_IntVecReadSize(p->vTrail) - Msat_IntVecPop( p->vTrailLim ); c != 0; c-- ) + Msat_SolverUndoOne( p ); +} + +/**Function************************************************************* + + Synopsis [Reverts to the state at given level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverCancelUntil( Msat_Solver_t * p, int Level ) +{ + while ( Msat_IntVecReadSize(p->vTrailLim) > Level ) + Msat_SolverCancel(p); +} + + +/**Function************************************************************* + + Synopsis [Record a clause and drive backtracking.] + + Description [vLits[0] must contain the asserting literal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_Clause_t * Msat_SolverRecord( Msat_Solver_t * p, Msat_IntVec_t * vLits ) +{ + Msat_Clause_t * pC; + int Value; + assert( Msat_IntVecReadSize(vLits) != 0 ); + Value = Msat_ClauseCreate( p, vLits, 1, &pC ); + assert( Value ); + Value = Msat_SolverEnqueue( p, Msat_IntVecReadEntry(vLits,0), pC ); + assert( Value ); + if ( pC ) + Msat_ClauseVecPush( p->vLearned, pC ); + return pC; +} + +/**Function************************************************************* + + Synopsis [Enqueues one variable assignment.] + + Description [Puts a new fact on the propagation queue and immediately + updates the variable value. Should a conflict arise, FALSE is returned. + Otherwise returns TRUE.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_SolverEnqueue( Msat_Solver_t * p, Msat_Lit_t Lit, Msat_Clause_t * pC ) +{ + Msat_Var_t Var = MSAT_LIT2VAR(Lit); + + // skip literals that are not in the current cone + if ( !Msat_IntVecReadEntry( p->vVarsUsed, Var ) ) + return 1; + +// assert( Msat_QueueReadSize(p->pQueue) == Msat_IntVecReadSize(p->vTrail) ); + // if the literal is assigned + // return 1 if the assignment is consistent + // return 0 if the assignment is inconsistent (conflict) + if ( p->pAssigns[Var] != MSAT_VAR_UNASSIGNED ) + return p->pAssigns[Var] == Lit; + // new fact - store it + if ( p->fVerbose ) + { +// printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(Lit)); + printf(L_IND"bind("L_LIT") ", L_ind, L_lit(Lit)); + Msat_ClausePrintSymbols( pC ); + } + p->pAssigns[Var] = Lit; + p->pLevel[Var] = Msat_IntVecReadSize(p->vTrailLim); +// p->pReasons[Var] = p->pLevel[Var]? pC: NULL; + p->pReasons[Var] = pC; + Msat_IntVecPush( p->vTrail, Lit ); + Msat_QueueInsert( p->pQueue, Lit ); + + Msat_OrderVarAssigned( p->pOrder, Var ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Propagates the assignments in the queue.] + + Description [Propagates all enqueued facts. If a conflict arises, + the conflicting clause is returned, otherwise NULL.] + + SideEffects [The propagation queue is empty, even if there was a conflict.] + + SeeAlso [] + +***********************************************************************/ +Msat_Clause_t * Msat_SolverPropagate( Msat_Solver_t * p ) +{ + Msat_ClauseVec_t ** pvWatched = p->pvWatched; + Msat_Clause_t ** pClauses; + Msat_Clause_t * pConflict; + Msat_Lit_t Lit, Lit_out; + int i, j, nClauses; + + // propagate all the literals in the queue + while ( (Lit = Msat_QueueExtract( p->pQueue )) >= 0 ) + { + p->Stats.nPropagations++; + // get the clauses watched by this literal + nClauses = Msat_ClauseVecReadSize( pvWatched[Lit] ); + pClauses = Msat_ClauseVecReadArray( pvWatched[Lit] ); + // go through the watched clauses and decide what to do with them + for ( i = j = 0; i < nClauses; i++ ) + { + p->Stats.nInspects++; + // clear the returned literal + Lit_out = -1; + // propagate the clause + if ( !Msat_ClausePropagate( pClauses[i], Lit, p->pAssigns, &Lit_out ) ) + { // the clause is unit + // "Lit_out" contains the new assignment to be enqueued + if ( Msat_SolverEnqueue( p, Lit_out, pClauses[i] ) ) + { // consistent assignment + // no changes to the implication queue; the watch is the same too + pClauses[j++] = pClauses[i]; + continue; + } + // remember the reason of conflict (will be returned) + pConflict = pClauses[i]; + // leave the remaning clauses in the same watched list + for ( ; i < nClauses; i++ ) + pClauses[j++] = pClauses[i]; + Msat_ClauseVecShrink( pvWatched[Lit], j ); + // clear the propagation queue + Msat_QueueClear( p->pQueue ); + return pConflict; + } + // the clause is not unit + // in this case "Lit_out" contains the new watch if it has changed + if ( Lit_out >= 0 ) + Msat_ClauseVecPush( pvWatched[Lit_out], pClauses[i] ); + else // the watch did not change + pClauses[j++] = pClauses[i]; + } + Msat_ClauseVecShrink( pvWatched[Lit], j ); + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Simplifies the data base.] + + Description [Simplify all constraints according to the current top-level + assigment (redundant constraints may be removed altogether).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +bool Msat_SolverSimplifyDB( Msat_Solver_t * p ) +{ + Msat_ClauseVec_t * vClauses; + Msat_Clause_t ** pClauses; + int nClauses, Type, i, j; + int * pAssigns; + int Counter; + + assert( Msat_SolverReadDecisionLevel(p) == 0 ); + if ( Msat_SolverPropagate(p) != NULL ) + return 0; +//Msat_SolverPrintClauses( p ); +//Msat_SolverPrintAssignment( p ); +//printf( "Simplification\n" ); + + // simplify and reassign clause numbers + Counter = 0; + pAssigns = Msat_SolverReadAssignsArray( p ); + for ( Type = 0; Type < 2; Type++ ) + { + vClauses = Type? p->vLearned : p->vClauses; + nClauses = Msat_ClauseVecReadSize( vClauses ); + pClauses = Msat_ClauseVecReadArray( vClauses ); + for ( i = j = 0; i < nClauses; i++ ) + if ( Msat_ClauseSimplify( pClauses[i], pAssigns ) ) + Msat_ClauseFree( p, pClauses[i], 1 ); + else + { + pClauses[j++] = pClauses[i]; + Msat_ClauseSetNum( pClauses[i], Counter++ ); + } + Msat_ClauseVecShrink( vClauses, j ); + } + p->nClauses = Counter; + return 1; +} + +/**Function************************************************************* + + Synopsis [Cleans the clause databased from the useless learnt clauses.] + + Description [Removes half of the learnt clauses, minus the clauses locked + by the current assignment. Locked clauses are clauses that are reason + to a some assignment.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverReduceDB( Msat_Solver_t * p ) +{ + Msat_Clause_t ** pLearned; + int nLearned, i, j; + double dExtraLim = p->dClaInc / Msat_ClauseVecReadSize(p->vLearned); + // Remove any clause below this activity + + // sort the learned clauses in the increasing order of activity + Msat_SolverSortDB( p ); + + // discard the first half the clauses (the less active ones) + nLearned = Msat_ClauseVecReadSize( p->vLearned ); + pLearned = Msat_ClauseVecReadArray( p->vLearned ); + for ( i = j = 0; i < nLearned / 2; i++ ) + if ( !Msat_ClauseIsLocked( p, pLearned[i]) ) + Msat_ClauseFree( p, pLearned[i], 1 ); + else + pLearned[j++] = pLearned[i]; + // filter the more active clauses and leave those above the limit + for ( ; i < nLearned; i++ ) + if ( !Msat_ClauseIsLocked( p, pLearned[i] ) && + Msat_ClauseReadActivity(pLearned[i]) < dExtraLim ) + Msat_ClauseFree( p, pLearned[i], 1 ); + else + pLearned[j++] = pLearned[i]; + Msat_ClauseVecShrink( p->vLearned, j ); +} + +/**Function************************************************************* + + Synopsis [Removes the learned clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverRemoveLearned( Msat_Solver_t * p ) +{ + Msat_Clause_t ** pLearned; + int nLearned, i; + + // discard the learned clauses + nLearned = Msat_ClauseVecReadSize( p->vLearned ); + pLearned = Msat_ClauseVecReadArray( p->vLearned ); + for ( i = 0; i < nLearned; i++ ) + { + assert( !Msat_ClauseIsLocked( p, pLearned[i]) ); + + Msat_ClauseFree( p, pLearned[i], 1 ); + } + Msat_ClauseVecShrink( p->vLearned, 0 ); + p->nClauses = Msat_ClauseVecReadSize(p->vClauses); + + for ( i = 0; i < p->nVarsAlloc; i++ ) + p->pReasons[i] = NULL; +} + +/**Function************************************************************* + + Synopsis [Removes the recently added clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverRemoveMarked( Msat_Solver_t * p ) +{ + Msat_Clause_t ** pLearned, ** pClauses; + int nLearned, nClauses, i; + + // discard the learned clauses + nClauses = Msat_ClauseVecReadSize( p->vClauses ); + pClauses = Msat_ClauseVecReadArray( p->vClauses ); + for ( i = p->nClausesStart; i < nClauses; i++ ) + { +// assert( !Msat_ClauseIsLocked( p, pClauses[i]) ); + Msat_ClauseFree( p, pClauses[i], 1 ); + } + Msat_ClauseVecShrink( p->vClauses, p->nClausesStart ); + + // discard the learned clauses + nLearned = Msat_ClauseVecReadSize( p->vLearned ); + pLearned = Msat_ClauseVecReadArray( p->vLearned ); + for ( i = 0; i < nLearned; i++ ) + { +// assert( !Msat_ClauseIsLocked( p, pLearned[i]) ); + Msat_ClauseFree( p, pLearned[i], 1 ); + } + Msat_ClauseVecShrink( p->vLearned, 0 ); + p->nClauses = Msat_ClauseVecReadSize(p->vClauses); +/* + // undo the previous data + for ( i = 0; i < p->nVarsAlloc; i++ ) + { + p->pAssigns[i] = MSAT_VAR_UNASSIGNED; + p->pReasons[i] = NULL; + p->pLevel[i] = -1; + p->pdActivity[i] = 0.0; + } + Msat_OrderClean( p->pOrder, p->nVars, NULL ); + Msat_QueueClear( p->pQueue ); +*/ +} + + + +/**Function************************************************************* + + Synopsis [Analyze conflict and produce a reason clause.] + + Description [Current decision level must be greater than root level.] + + SideEffects [vLits_out[0] is the asserting literal at level pLevel_out.] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverAnalyze( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_IntVec_t * vLits_out, int * pLevel_out ) +{ + Msat_Lit_t LitQ, Lit = MSAT_LIT_UNASSIGNED; + Msat_Var_t VarQ, Var; + int * pReasonArray, nReasonSize; + int j, pathC = 0, nLevelCur = Msat_IntVecReadSize(p->vTrailLim); + int iStep = Msat_IntVecReadSize(p->vTrail) - 1; + + // increment the seen counter + p->nSeenId++; + // empty the vector array + Msat_IntVecClear( vLits_out ); + Msat_IntVecPush( vLits_out, -1 ); // (leave room for the asserting literal) + *pLevel_out = 0; + do { + assert( pC != NULL ); // (otherwise should be UIP) + // get the reason of conflict + Msat_ClauseCalcReason( p, pC, Lit, p->vReason ); + nReasonSize = Msat_IntVecReadSize( p->vReason ); + pReasonArray = Msat_IntVecReadArray( p->vReason ); + for ( j = 0; j < nReasonSize; j++ ) { + LitQ = pReasonArray[j]; + VarQ = MSAT_LIT2VAR(LitQ); + if ( p->pSeen[VarQ] != p->nSeenId ) { + p->pSeen[VarQ] = p->nSeenId; + + // added to better fine-tune the search + Msat_SolverVarBumpActivity( p, LitQ ); + + // skip all the literals on this decision level + if ( p->pLevel[VarQ] == nLevelCur ) + pathC++; + else if ( p->pLevel[VarQ] > 0 ) { + // add the literals on other decision levels but + // exclude variables from decision level 0 + Msat_IntVecPush( vLits_out, MSAT_LITNOT(LitQ) ); + if ( *pLevel_out < p->pLevel[VarQ] ) + *pLevel_out = p->pLevel[VarQ]; + } + } + } + // Select next clause to look at: + do { +// Lit = Msat_IntVecReadEntryLast(p->vTrail); + Lit = Msat_IntVecReadEntry( p->vTrail, iStep-- ); + Var = MSAT_LIT2VAR(Lit); + pC = p->pReasons[Var]; +// Msat_SolverUndoOne( p ); + } while ( p->pSeen[Var] != p->nSeenId ); + pathC--; + } while ( pathC > 0 ); + // we do not unbind the variables above + // this will be done after conflict analysis + + Msat_IntVecWriteEntry( vLits_out, 0, MSAT_LITNOT(Lit) ); + if ( p->fVerbose ) + { + printf( L_IND"Learnt {", L_ind ); + nReasonSize = Msat_IntVecReadSize( vLits_out ); + pReasonArray = Msat_IntVecReadArray( vLits_out ); + for ( j = 0; j < nReasonSize; j++ ) + printf(" "L_LIT, L_lit(pReasonArray[j])); + printf(" } at level %d\n", *pLevel_out); + } +} + +/**Function************************************************************* + + Synopsis [The search procedure called between the restarts.] + + Description [Search for a satisfying solution as long as the number of + conflicts does not exceed the limit (nConfLimit) while keeping the number + of learnt clauses below the provided limit (nLearnedLimit). NOTE! Use + negative value for nConfLimit or nLearnedLimit to indicate infinity.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_Type_t Msat_SolverSearch( Msat_Solver_t * p, int nConfLimit, int nLearnedLimit, int nBackTrackLimit, Msat_SearchParams_t * pPars ) +{ + Msat_Clause_t * pConf; + Msat_Var_t Var; + int nLevelBack, nConfs, nAssigns, Value; + int i; + + assert( Msat_SolverReadDecisionLevel(p) == p->nLevelRoot ); + p->Stats.nStarts++; + p->dVarDecay = 1 / pPars->dVarDecay; + p->dClaDecay = 1 / pPars->dClaDecay; + + // reset the activities + for ( i = 0; i < p->nVars; i++ ) + p->pdActivity[i] = (double)p->pFactors[i]; +// p->pdActivity[i] = 0.0; + + nConfs = 0; + while ( 1 ) + { + pConf = Msat_SolverPropagate( p ); + if ( pConf != NULL ){ + // CONFLICT + if ( p->fVerbose ) + { +// printf(L_IND"**CONFLICT**\n", L_ind); + printf(L_IND"**CONFLICT** ", L_ind); + Msat_ClausePrintSymbols( pConf ); + } + // count conflicts + p->Stats.nConflicts++; + nConfs++; + + // if top level, return UNSAT + if ( Msat_SolverReadDecisionLevel(p) == p->nLevelRoot ) + return MSAT_FALSE; + + // perform conflict analysis + Msat_SolverAnalyze( p, pConf, p->vTemp, &nLevelBack ); + Msat_SolverCancelUntil( p, (p->nLevelRoot > nLevelBack)? p->nLevelRoot : nLevelBack ); + Msat_SolverRecord( p, p->vTemp ); + + // it is important that recording is done after cancelling + // because canceling cleans the queue while recording adds to it + Msat_SolverVarDecayActivity( p ); + Msat_SolverClaDecayActivity( p ); + + } + else{ + // NO CONFLICT + if ( Msat_IntVecReadSize(p->vTrailLim) == 0 ) { + // Simplify the set of problem clauses: +// Value = Msat_SolverSimplifyDB(p); +// assert( Value ); + } + nAssigns = Msat_IntVecReadSize( p->vTrail ); + if ( nLearnedLimit >= 0 && Msat_ClauseVecReadSize(p->vLearned) >= nLearnedLimit + nAssigns ) { + // Reduce the set of learnt clauses: + Msat_SolverReduceDB(p); + } + + Var = Msat_OrderVarSelect( p->pOrder ); + if ( Var == MSAT_ORDER_UNKNOWN ) { + // Model found and stored in p->pAssigns + memcpy( p->pModel, p->pAssigns, sizeof(int) * p->nVars ); + Msat_QueueClear( p->pQueue ); + Msat_SolverCancelUntil( p, p->nLevelRoot ); + return MSAT_TRUE; + } + if ( nConfLimit > 0 && nConfs > nConfLimit ) { + // Reached bound on number of conflicts: + p->dProgress = Msat_SolverProgressEstimate( p ); + Msat_QueueClear( p->pQueue ); + Msat_SolverCancelUntil( p, p->nLevelRoot ); + return MSAT_UNKNOWN; + } + else if ( nBackTrackLimit > 0 && (int)p->Stats.nConflicts - p->nBackTracks > nBackTrackLimit ) { + // Reached bound on number of conflicts: + Msat_QueueClear( p->pQueue ); + Msat_SolverCancelUntil( p, p->nLevelRoot ); + return MSAT_UNKNOWN; + } + else{ + // New variable decision: + p->Stats.nDecisions++; + assert( Var != MSAT_ORDER_UNKNOWN && Var >= 0 && Var < p->nVars ); + Value = Msat_SolverAssume(p, MSAT_VAR2LIT(Var,0) ); + assert( Value ); + } + } + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatSort.c b/abc70930/src/sat/msat/msatSort.c new file mode 100644 index 00000000..3b89d102 --- /dev/null +++ b/abc70930/src/sat/msat/msatSort.c @@ -0,0 +1,173 @@ +/**CFile**************************************************************** + + FileName [msatSort.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [Sorting clauses.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatSort.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Msat_SolverSortCompare( Msat_Clause_t ** ppC1, Msat_Clause_t ** ppC2 ); + +// Returns a random float 0 <= x < 1. Seed must never be 0. +static double drand(double seed) { + int q; + seed *= 1389796; + q = (int)(seed / 2147483647); + seed -= (double)q * 2147483647; + return seed / 2147483647; } + +// Returns a random integer 0 <= x < size. Seed must never be 0. +static int irand(double seed, int size) { + return (int)(drand(seed) * size); } + +static void Msat_SolverSort( Msat_Clause_t ** array, int size, double seed ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Msat_SolverSort the learned clauses in the increasing order of activity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverSortDB( Msat_Solver_t * p ) +{ + Msat_ClauseVec_t * pVecClauses; + Msat_Clause_t ** pLearned; + int nLearned; + // read the parameters + pVecClauses = Msat_SolverReadLearned( p ); + nLearned = Msat_ClauseVecReadSize( pVecClauses ); + pLearned = Msat_ClauseVecReadArray( pVecClauses ); + // Msat_SolverSort the array +// qMsat_SolverSort( (void *)pLearned, nLearned, sizeof(Msat_Clause_t *), +// (int (*)(const void *, const void *)) Msat_SolverSortCompare ); +// printf( "Msat_SolverSorting.\n" ); + Msat_SolverSort( pLearned, nLearned, 91648253 ); +/* + if ( nLearned > 2 ) + { + printf( "Clause 1: %0.20f\n", Msat_ClauseReadActivity(pLearned[0]) ); + printf( "Clause 2: %0.20f\n", Msat_ClauseReadActivity(pLearned[1]) ); + printf( "Clause 3: %0.20f\n", Msat_ClauseReadActivity(pLearned[2]) ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_SolverSortCompare( Msat_Clause_t ** ppC1, Msat_Clause_t ** ppC2 ) +{ + float Value1 = Msat_ClauseReadActivity( *ppC1 ); + float Value2 = Msat_ClauseReadActivity( *ppC2 ); + if ( Value1 < Value2 ) + return -1; + if ( Value1 > Value2 ) + return 1; + return 0; +} + + +/**Function************************************************************* + + Synopsis [Selection sort for small array size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverSortSelection( Msat_Clause_t ** array, int size ) +{ + Msat_Clause_t * tmp; + int i, j, best_i; + for ( i = 0; i < size-1; i++ ) + { + best_i = i; + for (j = i+1; j < size; j++) + { + if ( Msat_ClauseReadActivity(array[j]) < Msat_ClauseReadActivity(array[best_i]) ) + best_i = j; + } + tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; + } +} + +/**Function************************************************************* + + Synopsis [The original MiniSat sorting procedure.] + + Description [This procedure is used to preserve trace-equivalence + with the orignal C++ implemenation of the solver.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_SolverSort( Msat_Clause_t ** array, int size, double seed ) +{ + if (size <= 15) + Msat_SolverSortSelection( array, size ); + else + { + Msat_Clause_t * pivot = array[irand(seed, size)]; + Msat_Clause_t * tmp; + int i = -1; + int j = size; + + for(;;) + { + do i++; while( Msat_ClauseReadActivity(array[i]) < Msat_ClauseReadActivity(pivot) ); + do j--; while( Msat_ClauseReadActivity(pivot) < Msat_ClauseReadActivity(array[j]) ); + + if ( i >= j ) break; + + tmp = array[i]; array[i] = array[j]; array[j] = tmp; + } + Msat_SolverSort(array , i , seed); + Msat_SolverSort(&array[i], size-i, seed); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/msat/msatVec.c b/abc70930/src/sat/msat/msatVec.c new file mode 100644 index 00000000..75f53047 --- /dev/null +++ b/abc70930/src/sat/msat/msatVec.c @@ -0,0 +1,495 @@ +/**CFile**************************************************************** + + FileName [msatVec.c] + + PackageName [A C version of SAT solver MINISAT, originally developed + in C++ by Niklas Een and Niklas Sorensson, Chalmers University of + Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] + + Synopsis [Integer vector borrowed from Extra.] + + Author [Alan Mishchenko ] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - January 1, 2004.] + + Revision [$Id: msatVec.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "msatInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Msat_IntVecSortCompare1( int * pp1, int * pp2 ); +static int Msat_IntVecSortCompare2( int * pp1, int * pp2 ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates a vector with the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_IntVec_t * Msat_IntVecAlloc( int nCap ) +{ + Msat_IntVec_t * p; + p = ALLOC( Msat_IntVec_t, 1 ); + if ( nCap > 0 && nCap < 16 ) + nCap = 16; + p->nSize = 0; + p->nCap = nCap; + p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the vector from an integer array of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_IntVec_t * Msat_IntVecAllocArray( int * pArray, int nSize ) +{ + Msat_IntVec_t * p; + p = ALLOC( Msat_IntVec_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = pArray; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates the vector from an integer array of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_IntVec_t * Msat_IntVecAllocArrayCopy( int * pArray, int nSize ) +{ + Msat_IntVec_t * p; + p = ALLOC( Msat_IntVec_t, 1 ); + p->nSize = nSize; + p->nCap = nSize; + p->pArray = ALLOC( int, nSize ); + memcpy( p->pArray, pArray, sizeof(int) * nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the integer array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_IntVec_t * Msat_IntVecDup( Msat_IntVec_t * pVec ) +{ + Msat_IntVec_t * p; + p = ALLOC( Msat_IntVec_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nCap; + p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL; + memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Transfers the array into another vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Msat_IntVec_t * Msat_IntVecDupArray( Msat_IntVec_t * pVec ) +{ + Msat_IntVec_t * p; + p = ALLOC( Msat_IntVec_t, 1 ); + p->nSize = pVec->nSize; + p->nCap = pVec->nCap; + p->pArray = pVec->pArray; + pVec->nSize = 0; + pVec->nCap = 0; + pVec->pArray = NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_IntVecFree( Msat_IntVec_t * p ) +{ + FREE( p->pArray ); + FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Fills the vector with given number of entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_IntVecFill( Msat_IntVec_t * p, int nSize, int Entry ) +{ + int i; + Msat_IntVecGrow( p, nSize ); + p->nSize = nSize; + for ( i = 0; i < p->nSize; i++ ) + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Msat_IntVecReleaseArray( Msat_IntVec_t * p ) +{ + int * pArray = p->pArray; + p->nCap = 0; + p->nSize = 0; + p->pArray = NULL; + return pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Msat_IntVecReadArray( Msat_IntVec_t * p ) +{ + return p->pArray; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_IntVecReadSize( Msat_IntVec_t * p ) +{ + return p->nSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_IntVecReadEntry( Msat_IntVec_t * p, int i ) +{ + assert( i >= 0 && i < p->nSize ); + return p->pArray[i]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_IntVecWriteEntry( Msat_IntVec_t * p, int i, int Entry ) +{ + assert( i >= 0 && i < p->nSize ); + p->pArray[i] = Entry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_IntVecReadEntryLast( Msat_IntVec_t * p ) +{ + return p->pArray[p->nSize-1]; +} + +/**Function************************************************************* + + Synopsis [Resizes the vector to the given capacity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_IntVecGrow( Msat_IntVec_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = REALLOC( int, p->pArray, nCapMin ); + p->nCap = nCapMin; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_IntVecShrink( Msat_IntVec_t * p, int nSizeNew ) +{ + assert( p->nSize >= nSizeNew ); + p->nSize = nSizeNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_IntVecClear( Msat_IntVec_t * p ) +{ + p->nSize = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_IntVecPush( Msat_IntVec_t * p, int Entry ) +{ + if ( p->nSize == p->nCap ) + { + if ( p->nCap < 16 ) + Msat_IntVecGrow( p, 16 ); + else + Msat_IntVecGrow( p, 2 * p->nCap ); + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [Add the element while ensuring uniqueness.] + + Description [Returns 1 if the element was found, and 0 if it was new. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_IntVecPushUnique( Msat_IntVec_t * p, int Entry ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + if ( p->pArray[i] == Entry ) + return 1; + Msat_IntVecPush( p, Entry ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Inserts the element while sorting in the increasing order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_IntVecPushUniqueOrder( Msat_IntVec_t * p, int Entry, int fIncrease ) +{ + int Entry1, Entry2; + int i; + Msat_IntVecPushUnique( p, Entry ); + // find the p of the node + for ( i = p->nSize-1; i > 0; i-- ) + { + Entry1 = p->pArray[i ]; + Entry2 = p->pArray[i-1]; + if ( fIncrease && Entry1 >= Entry2 || + !fIncrease && Entry1 <= Entry2 ) + break; + p->pArray[i ] = Entry2; + p->pArray[i-1] = Entry1; + } +} + + +/**Function************************************************************* + + Synopsis [Returns the last entry and removes it from the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_IntVecPop( Msat_IntVec_t * p ) +{ + assert( p->nSize > 0 ); + return p->pArray[--p->nSize]; +} + +/**Function************************************************************* + + Synopsis [Sorting the entries by their integer value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Msat_IntVecSort( Msat_IntVec_t * p, int fReverse ) +{ + if ( fReverse ) + qsort( (void *)p->pArray, p->nSize, sizeof(int), + (int (*)(const void *, const void *)) Msat_IntVecSortCompare2 ); + else + qsort( (void *)p->pArray, p->nSize, sizeof(int), + (int (*)(const void *, const void *)) Msat_IntVecSortCompare1 ); +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_IntVecSortCompare1( int * pp1, int * pp2 ) +{ + // for some reason commenting out lines (as shown) led to crashing of the release version + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) // + return 1; + return 0; // +} + +/**Function************************************************************* + + Synopsis [Comparison procedure for two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Msat_IntVecSortCompare2( int * pp1, int * pp2 ) +{ + // for some reason commenting out lines (as shown) led to crashing of the release version + if ( *pp1 > *pp2 ) + return -1; + if ( *pp1 < *pp2 ) // + return 1; + return 0; // +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/proof/pr.c b/abc70930/src/sat/proof/pr.c new file mode 100644 index 00000000..2d1ab2d1 --- /dev/null +++ b/abc70930/src/sat/proof/pr.c @@ -0,0 +1,1263 @@ +/**CFile**************************************************************** + + FileName [pr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Proof recording.] + + Synopsis [Core procedures of the package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: pr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include +//#include "vec.h" +#include "pr.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef unsigned lit; + +typedef struct Pr_Cls_t_ Pr_Cls_t; +struct Pr_Cls_t_ +{ + unsigned uTruth; // interpolant + void * pProof; // the proof node +// void * pAntis; // the anticedents + Pr_Cls_t * pNext; // the next clause + Pr_Cls_t * pNext0; // the next 0-watch + Pr_Cls_t * pNext1; // the next 0-watch + int Id; // the clause ID + unsigned fA : 1; // belongs to A + unsigned fRoot : 1; // original clause + unsigned fVisit : 1; // visited clause + unsigned nLits : 24; // the number of literals + lit pLits[0]; // literals of this clause +}; + +struct Pr_Man_t_ +{ + // general data + int fProofWrite; // writes the proof file + int fProofVerif; // verifies the proof + int nVars; // the number of variables + int nVarsAB; // the number of global variables + int nRoots; // the number of root clauses + int nClauses; // the number of all clauses + int nClausesA; // the number of clauses of A + Pr_Cls_t * pHead; // the head clause + Pr_Cls_t * pTail; // the tail clause + Pr_Cls_t * pLearnt; // the tail clause + Pr_Cls_t * pEmpty; // the empty clause + // internal BCP + int nRootSize; // the number of root level assignments + int nTrailSize; // the number of assignments made + lit * pTrail; // chronological order of assignments (size nVars) + lit * pAssigns; // assignments by variable (size nVars) + char * pSeens; // temporary mark (size nVars) + char * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB] + Pr_Cls_t ** pReasons; // reasons for each assignment (size nVars) + Pr_Cls_t ** pWatches; // watched clauses for each literal (size 2*nVars) + int nVarsAlloc; // the allocated size of arrays + // proof recording + void * pManProof; // proof manager + int Counter; // counter of resolved clauses + // memory management + int nChunkSize; // the number of bytes in a chunk + int nChunkUsed; // the number of bytes used in the last chunk + char * pChunkLast; // the last memory chunk + // internal verification + lit * pResLits; // the literals of the resolvent + int nResLits; // the number of literals of the resolvent + int nResLitsAlloc;// the number of literals of the resolvent + // runtime stats + int timeBcp; + int timeTrace; + int timeRead; + int timeTotal; +}; + +#ifndef PRT +#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) +#endif + +// variable assignments +static const lit LIT_UNDEF = 0xffffffff; + +// variable/literal conversions (taken from MiniSat) +static inline lit toLit (int v) { return v + v; } +static inline lit toLitCond(int v, int c) { return v + v + (c != 0); } +static inline lit lit_neg (lit l) { return l ^ 1; } +static inline int lit_var (lit l) { return l >> 1; } +static inline int lit_sign (lit l) { return l & 1; } +static inline int lit_print(lit l) { return lit_sign(l)? -lit_var(l)-1 : lit_var(l)+1; } +static inline lit lit_read (int s) { return s > 0 ? toLit(s-1) : lit_neg(toLit(-s-1)); } +static inline int lit_check(lit l, int n) { return l >= 0 && lit_var(l) < n; } + +// iterators through the clauses +#define Pr_ManForEachClause( p, pCls ) for( pCls = p->pHead; pCls; pCls = pCls->pNext ) +#define Pr_ManForEachClauseRoot( p, pCls ) for( pCls = p->pHead; pCls != p->pLearnt; pCls = pCls->pNext ) +#define Pr_ManForEachClauseLearnt( p, pCls ) for( pCls = p->pLearnt; pCls; pCls = pCls->pNext ) + +// static procedures +static char * Pr_ManMemoryFetch( Pr_Man_t * p, int nBytes ); +static void Pr_ManMemoryStop( Pr_Man_t * p ); +static void Pr_ManResize( Pr_Man_t * p, int nVarsNew ); + +// exported procedures +extern Pr_Man_t * Pr_ManAlloc( int nVarsAlloc ); +extern void Pr_ManFree( Pr_Man_t * p ); +extern int Pr_ManAddClause( Pr_Man_t * p, lit * pBeg, lit * pEnd, int fRoot, int fClauseA ); +extern int Pr_ManProofWrite( Pr_Man_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pr_Man_t * Pr_ManAlloc( int nVarsAlloc ) +{ + Pr_Man_t * p; + // allocate the manager + p = (Pr_Man_t *)malloc( sizeof(Pr_Man_t) ); + memset( p, 0, sizeof(Pr_Man_t) ); + // allocate internal arrays + Pr_ManResize( p, nVarsAlloc? nVarsAlloc : 256 ); + // set the starting number of variables + p->nVars = 0; + // memory management + p->nChunkSize = (1<<16); // use 64K chunks + // verification + p->nResLitsAlloc = (1<<16); + p->pResLits = malloc( sizeof(lit) * p->nResLitsAlloc ); + // parameters + p->fProofWrite = 0; + p->fProofVerif = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [Resize proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pr_ManResize( Pr_Man_t * p, int nVarsNew ) +{ + // check if resizing is needed + if ( p->nVarsAlloc < nVarsNew ) + { + int nVarsAllocOld = p->nVarsAlloc; + // find the new size + if ( p->nVarsAlloc == 0 ) + p->nVarsAlloc = 1; + while ( p->nVarsAlloc < nVarsNew ) + p->nVarsAlloc *= 2; + // resize the arrays + p->pTrail = (lit *) realloc( p->pTrail, sizeof(lit) * p->nVarsAlloc ); + p->pAssigns = (lit *) realloc( p->pAssigns, sizeof(lit) * p->nVarsAlloc ); + p->pSeens = (char *) realloc( p->pSeens, sizeof(char) * p->nVarsAlloc ); + p->pVarTypes = (char *) realloc( p->pVarTypes, sizeof(char) * p->nVarsAlloc ); + p->pReasons = (Pr_Cls_t **)realloc( p->pReasons, sizeof(Pr_Cls_t *) * p->nVarsAlloc ); + p->pWatches = (Pr_Cls_t **)realloc( p->pWatches, sizeof(Pr_Cls_t *) * p->nVarsAlloc*2 ); + // clean the free space + memset( p->pAssigns + nVarsAllocOld, 0xff, sizeof(lit) * (p->nVarsAlloc - nVarsAllocOld) ); + memset( p->pSeens + nVarsAllocOld, 0, sizeof(char) * (p->nVarsAlloc - nVarsAllocOld) ); + memset( p->pVarTypes + nVarsAllocOld, 0, sizeof(char) * (p->nVarsAlloc - nVarsAllocOld) ); + memset( p->pReasons + nVarsAllocOld, 0, sizeof(Pr_Cls_t *) * (p->nVarsAlloc - nVarsAllocOld) ); + memset( p->pWatches + nVarsAllocOld, 0, sizeof(Pr_Cls_t *) * (p->nVarsAlloc - nVarsAllocOld)*2 ); + } + // adjust the number of variables + if ( p->nVars < nVarsNew ) + p->nVars = nVarsNew; +} + +/**Function************************************************************* + + Synopsis [Deallocate proof manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pr_ManFree( Pr_Man_t * p ) +{ + printf( "Runtime stats:\n" ); +PRT( "Reading ", p->timeRead ); +PRT( "BCP ", p->timeBcp ); +PRT( "Trace ", p->timeTrace ); +PRT( "TOTAL ", p->timeTotal ); + + Pr_ManMemoryStop( p ); + free( p->pTrail ); + free( p->pAssigns ); + free( p->pSeens ); + free( p->pVarTypes ); + free( p->pReasons ); + free( p->pWatches ); + free( p->pResLits ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Adds one clause to the watcher list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Pr_ManWatchClause( Pr_Man_t * p, Pr_Cls_t * pClause, lit Lit ) +{ + assert( lit_check(Lit, p->nVars) ); + if ( pClause->pLits[0] == Lit ) + pClause->pNext0 = p->pWatches[lit_neg(Lit)]; + else + { + assert( pClause->pLits[1] == Lit ); + pClause->pNext1 = p->pWatches[lit_neg(Lit)]; + } + p->pWatches[lit_neg(Lit)] = pClause; +} + +/**Function************************************************************* + + Synopsis [Adds one clause to the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pr_ManAddClause( Pr_Man_t * p, lit * pBeg, lit * pEnd, int fRoot, int fClauseA ) +{ + Pr_Cls_t * pClause; + lit Lit, * i, * j; + int nSize, VarMax; + + // process the literals + if ( pBeg < pEnd ) + { + // insertion sort + VarMax = lit_var( *pBeg ); + for ( i = pBeg + 1; i < pEnd; i++ ) + { + Lit = *i; + VarMax = lit_var(Lit) > VarMax ? lit_var(Lit) : VarMax; + for ( j = i; j > pBeg && *(j-1) > Lit; j-- ) + *j = *(j-1); + *j = Lit; + } + // make sure there is no duplicated variables + for ( i = pBeg + 1; i < pEnd; i++ ) + assert( lit_var(*(i-1)) != lit_var(*i) ); + // resize the manager + Pr_ManResize( p, VarMax+1 ); + } + + // get memory for the clause + nSize = sizeof(Pr_Cls_t) + sizeof(lit) * (pEnd - pBeg); + pClause = (Pr_Cls_t *)Pr_ManMemoryFetch( p, nSize ); + memset( pClause, 0, sizeof(Pr_Cls_t) ); + + // assign the clause + assert( !fClauseA || fRoot ); // clause of A is always a root clause + p->nRoots += fRoot; + p->nClausesA += fClauseA; + pClause->Id = p->nClauses++; + pClause->fA = fClauseA; + pClause->fRoot = fRoot; + pClause->nLits = pEnd - pBeg; + memcpy( pClause->pLits, pBeg, sizeof(lit) * (pEnd - pBeg) ); + + // add the clause to the list + if ( p->pHead == NULL ) + p->pHead = pClause; + if ( p->pTail == NULL ) + p->pTail = pClause; + else + { + p->pTail->pNext = pClause; + p->pTail = pClause; + } + + // mark the first learnt clause + if ( p->pLearnt == NULL && !pClause->fRoot ) + p->pLearnt = pClause; + + // add the empty clause + if ( pClause->nLits == 0 ) + { + if ( p->pEmpty ) + printf( "More than one empty clause!\n" ); + p->pEmpty = pClause; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Fetches memory.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Pr_ManMemoryFetch( Pr_Man_t * p, int nBytes ) +{ + char * pMem; + if ( p->pChunkLast == NULL || nBytes > p->nChunkSize - p->nChunkUsed ) + { + pMem = (char *)malloc( p->nChunkSize ); + *(char **)pMem = p->pChunkLast; + p->pChunkLast = pMem; + p->nChunkUsed = sizeof(char *); + } + pMem = p->pChunkLast + p->nChunkUsed; + p->nChunkUsed += nBytes; + return pMem; +} + +/**Function************************************************************* + + Synopsis [Frees memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pr_ManMemoryStop( Pr_Man_t * p ) +{ + char * pMem, * pNext; + if ( p->pChunkLast == NULL ) + return; + for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext ) + free( pMem ); + free( pMem ); +} + +/**Function************************************************************* + + Synopsis [Reports memory usage in bytes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pr_ManMemoryReport( Pr_Man_t * p ) +{ + int Total; + char * pMem, * pNext; + if ( p->pChunkLast == NULL ) + return 0; + Total = p->nChunkUsed; + for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext ) + Total += p->nChunkSize; + return Total; +} + +/**Function************************************************************* + + Synopsis [Records the proof.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Extra_PrintBinary_( FILE * pFile, unsigned Sign[], int nBits ) +{ + int Remainder, nWords; + int w, i; + + Remainder = (nBits%(sizeof(unsigned)*8)); + nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); + + for ( w = nWords-1; w >= 0; w-- ) + for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) + fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1< 0) ); +} + +/**Function************************************************************* + + Synopsis [Prints the interpolant for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pr_ManPrintInterOne( Pr_Man_t * p, Pr_Cls_t * pClause ) +{ + printf( "Clause %2d : ", pClause->Id ); + Extra_PrintBinary_( stdout, &pClause->uTruth, (1 << p->nVarsAB) ); + printf( "\n" ); +} + + + +/**Function************************************************************* + + Synopsis [Records implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Pr_ManEnqueue( Pr_Man_t * p, lit Lit, Pr_Cls_t * pReason ) +{ + int Var = lit_var(Lit); + if ( p->pAssigns[Var] != LIT_UNDEF ) + return p->pAssigns[Var] == Lit; + p->pAssigns[Var] = Lit; + p->pReasons[Var] = pReason; + p->pTrail[p->nTrailSize++] = Lit; +//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Records implication.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Pr_ManCancelUntil( Pr_Man_t * p, int Level ) +{ + lit Lit; + int i, Var; + for ( i = p->nTrailSize - 1; i >= Level; i-- ) + { + Lit = p->pTrail[i]; + Var = lit_var( Lit ); + p->pReasons[Var] = NULL; + p->pAssigns[Var] = LIT_UNDEF; +//printf( "cancelling var %d\n", Var ); + } + p->nTrailSize = Level; +} + +/**Function************************************************************* + + Synopsis [Propagate one assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Pr_Cls_t * Pr_ManPropagateOne( Pr_Man_t * p, lit Lit ) +{ + Pr_Cls_t ** ppPrev, * pCur, * pTemp; + lit LitF = lit_neg(Lit); + int i; + // iterate through the literals + ppPrev = p->pWatches + Lit; + for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) + { + // make sure the false literal is in the second literal of the clause + if ( pCur->pLits[0] == LitF ) + { + pCur->pLits[0] = pCur->pLits[1]; + pCur->pLits[1] = LitF; + pTemp = pCur->pNext0; + pCur->pNext0 = pCur->pNext1; + pCur->pNext1 = pTemp; + } + assert( pCur->pLits[1] == LitF ); + + // if the first literal is true, the clause is satisfied + if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) + { + ppPrev = &pCur->pNext1; + continue; + } + + // look for a new literal to watch + for ( i = 2; i < (int)pCur->nLits; i++ ) + { + // skip the case when the literal is false + if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] ) + continue; + // the literal is either true or unassigned - watch it + pCur->pLits[1] = pCur->pLits[i]; + pCur->pLits[i] = LitF; + // remove this clause from the watch list of Lit + *ppPrev = pCur->pNext1; + // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) + Pr_ManWatchClause( p, pCur, pCur->pLits[1] ); + break; + } + if ( i < (int)pCur->nLits ) // found new watch + continue; + + // clause is unit - enqueue new implication + if ( Pr_ManEnqueue(p, pCur->pLits[0], pCur) ) + { + ppPrev = &pCur->pNext1; + continue; + } + + // conflict detected - return the conflict clause + return pCur; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Propagate the current assignments.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pr_Cls_t * Pr_ManPropagate( Pr_Man_t * p, int Start ) +{ + Pr_Cls_t * pClause; + int i; + int clk = clock(); + for ( i = Start; i < p->nTrailSize; i++ ) + { + pClause = Pr_ManPropagateOne( p, p->pTrail[i] ); + if ( pClause ) + { +p->timeBcp += clock() - clk; + return pClause; + } + } +p->timeBcp += clock() - clk; + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Prints the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pr_ManPrintClause( Pr_Cls_t * pClause ) +{ + int i; + printf( "Clause ID = %d. Proof = %d. {", pClause->Id, (int)pClause->pProof ); + for ( i = 0; i < (int)pClause->nLits; i++ ) + printf( " %d", pClause->pLits[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints the resolvent.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pr_ManPrintResolvent( lit * pResLits, int nResLits ) +{ + int i; + printf( "Resolvent: {" ); + for ( i = 0; i < nResLits; i++ ) + printf( " %d", pResLits[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Writes one root clause into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pr_ManProofWriteOne( Pr_Man_t * p, Pr_Cls_t * pClause ) +{ + pClause->pProof = (void *)++p->Counter; + + if ( p->fProofWrite ) + { + int v; + fprintf( p->pManProof, "%d", (int)pClause->pProof ); + for ( v = 0; v < (int)pClause->nLits; v++ ) + fprintf( p->pManProof, " %d", lit_print(pClause->pLits[v]) ); + fprintf( p->pManProof, " 0 0\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Traces the proof for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pr_ManProofTraceOne( Pr_Man_t * p, Pr_Cls_t * pConflict, Pr_Cls_t * pFinal ) +{ + Pr_Cls_t * pReason; + int i, v, Var, PrevId; + int fPrint = 0; + int clk = clock(); + + // collect resolvent literals + if ( p->fProofVerif ) + { + assert( (int)pConflict->nLits <= p->nResLitsAlloc ); + memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits ); + p->nResLits = pConflict->nLits; + } + + // mark all the variables in the conflict as seen + for ( v = 0; v < (int)pConflict->nLits; v++ ) + p->pSeens[lit_var(pConflict->pLits[v])] = 1; + + // start the anticedents +// pFinal->pAntis = Vec_PtrAlloc( 32 ); +// Vec_PtrPush( pFinal->pAntis, pConflict ); + + if ( p->nClausesA ) + pFinal->uTruth = pConflict->uTruth; + + // follow the trail backwards + PrevId = (int)pConflict->pProof; + for ( i = p->nTrailSize - 1; i >= 0; i-- ) + { + // skip literals that are not involved + Var = lit_var(p->pTrail[i]); + if ( !p->pSeens[Var] ) + continue; + p->pSeens[Var] = 0; + + // skip literals of the resulting clause + pReason = p->pReasons[Var]; + if ( pReason == NULL ) + continue; + assert( p->pTrail[i] == pReason->pLits[0] ); + + // add the variables to seen + for ( v = 1; v < (int)pReason->nLits; v++ ) + p->pSeens[lit_var(pReason->pLits[v])] = 1; + + + // record the reason clause + assert( pReason->pProof > 0 ); + p->Counter++; + if ( p->fProofWrite ) + fprintf( p->pManProof, "%d * %d %d 0\n", p->Counter, PrevId, (int)pReason->pProof ); + PrevId = p->Counter; + + if ( p->nClausesA ) + { + if ( p->pVarTypes[Var] == 1 ) // var of A + pFinal->uTruth |= pReason->uTruth; + else + pFinal->uTruth &= pReason->uTruth; + } + + // resolve the temporary resolvent with the reason clause + if ( p->fProofVerif ) + { + int v1, v2; + if ( fPrint ) + Pr_ManPrintResolvent( p->pResLits, p->nResLits ); + // check that the var is present in the resolvent + for ( v1 = 0; v1 < p->nResLits; v1++ ) + if ( lit_var(p->pResLits[v1]) == Var ) + break; + if ( v1 == p->nResLits ) + printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var ); + if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) ) + printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var ); + // remove this variable from the resolvent + assert( lit_var(p->pResLits[v1]) == Var ); + p->nResLits--; + for ( ; v1 < p->nResLits; v1++ ) + p->pResLits[v1] = p->pResLits[v1+1]; + // add variables of the reason clause + for ( v2 = 1; v2 < (int)pReason->nLits; v2++ ) + { + for ( v1 = 0; v1 < p->nResLits; v1++ ) + if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) ) + break; + // if it is a new variable, add it to the resolvent + if ( v1 == p->nResLits ) + { + if ( p->nResLits == p->nResLitsAlloc ) + printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n, pFinal->Id" ); + p->pResLits[ p->nResLits++ ] = pReason->pLits[v2]; + continue; + } + // if the variable is the same, the literal should be the same too + if ( p->pResLits[v1] == pReason->pLits[v2] ) + continue; + // the literal is different + printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id ); + } + } + +// Vec_PtrPush( pFinal->pAntis, pReason ); + } + + // unmark all seen variables +// for ( i = p->nTrailSize - 1; i >= 0; i-- ) +// p->pSeens[lit_var(p->pTrail[i])] = 0; + // check that the literals are unmarked +// for ( i = p->nTrailSize - 1; i >= 0; i-- ) +// assert( p->pSeens[lit_var(p->pTrail[i])] == 0 ); + + // use the resulting clause to check the correctness of resolution + if ( p->fProofVerif ) + { + int v1, v2; + if ( fPrint ) + Pr_ManPrintResolvent( p->pResLits, p->nResLits ); + for ( v1 = 0; v1 < p->nResLits; v1++ ) + { + for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) + if ( pFinal->pLits[v2] == p->pResLits[v1] ) + break; + if ( v2 < (int)pFinal->nLits ) + continue; + break; + } + if ( v1 < p->nResLits ) + { + printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id ); + Pr_ManPrintClause( pConflict ); + Pr_ManPrintResolvent( p->pResLits, p->nResLits ); + Pr_ManPrintClause( pFinal ); + } + } +p->timeTrace += clock() - clk; + + // return the proof pointer + if ( p->nClausesA ) + { + Pr_ManPrintInterOne( p, pFinal ); + } + return p->Counter; +} + +/**Function************************************************************* + + Synopsis [Records the proof for one clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pr_ManProofRecordOne( Pr_Man_t * p, Pr_Cls_t * pClause ) +{ + Pr_Cls_t * pConflict; + int i; + + // empty clause never ends up there + assert( pClause->nLits > 0 ); + if ( pClause->nLits == 0 ) + printf( "Error: Empty clause is attempted.\n" ); + + // add assumptions to the trail + assert( !pClause->fRoot ); + assert( p->nTrailSize == p->nRootSize ); + for ( i = 0; i < (int)pClause->nLits; i++ ) + if ( !Pr_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) + { + assert( 0 ); // impossible + return 0; + } + + // propagate the assumptions + pConflict = Pr_ManPropagate( p, p->nRootSize ); + if ( pConflict == NULL ) + { + assert( 0 ); // cannot prove + return 0; + } + + // construct the proof + pClause->pProof = (void *)Pr_ManProofTraceOne( p, pConflict, pClause ); + + // undo to the root level + Pr_ManCancelUntil( p, p->nRootSize ); + + // add large clauses to the watched lists + if ( pClause->nLits > 1 ) + { + Pr_ManWatchClause( p, pClause, pClause->pLits[0] ); + Pr_ManWatchClause( p, pClause, pClause->pLits[1] ); + return 1; + } + assert( pClause->nLits == 1 ); + + // if the clause proved is unit, add it and propagate + if ( !Pr_ManEnqueue( p, pClause->pLits[0], pClause ) ) + { + assert( 0 ); // impossible + return 0; + } + + // propagate the assumption + pConflict = Pr_ManPropagate( p, p->nRootSize ); + if ( pConflict ) + { + // construct the proof + p->pEmpty->pProof = (void *)Pr_ManProofTraceOne( p, pConflict, p->pEmpty ); + printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id ); + return 0; + } + + // update the root level + p->nRootSize = p->nTrailSize; + return 1; +} + +/**Function************************************************************* + + Synopsis [Propagate the root clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pr_ManProcessRoots( Pr_Man_t * p ) +{ + Pr_Cls_t * pClause; + int Counter; + + // make sure the root clauses are preceeding the learnt clauses + Counter = 0; + Pr_ManForEachClause( p, pClause ) + { + assert( (int)pClause->fA == (Counter < (int)p->nClausesA) ); + assert( (int)pClause->fRoot == (Counter < (int)p->nRoots) ); + Counter++; + } + assert( p->nClauses == Counter ); + + // make sure the last clause if empty + assert( p->pTail->nLits == 0 ); + + // go through the root unit clauses + p->nTrailSize = 0; + Pr_ManForEachClauseRoot( p, pClause ) + { + // create watcher lists for the root clauses + if ( pClause->nLits > 1 ) + { + Pr_ManWatchClause( p, pClause, pClause->pLits[0] ); + Pr_ManWatchClause( p, pClause, pClause->pLits[1] ); + } + // empty clause and large clauses + if ( pClause->nLits != 1 ) + continue; + // unit clause + assert( lit_check(pClause->pLits[0], p->nVars) ); + if ( !Pr_ManEnqueue( p, pClause->pLits[0], pClause ) ) + { + // detected root level conflict + printf( "Pr_ManProcessRoots(): Detected a root-level conflict\n" ); + assert( 0 ); + return 0; + } + } + + // propagate the root unit clauses + pClause = Pr_ManPropagate( p, 0 ); + if ( pClause ) + { + // detected root level conflict + printf( "Pr_ManProcessRoots(): Detected a root-level conflict\n" ); + assert( 0 ); + return 0; + } + + // set the root level + p->nRootSize = p->nTrailSize; + return 1; +} + +/**Function************************************************************* + + Synopsis [Records the proof.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pr_ManPrepareInter( Pr_Man_t * p ) +{ + unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + Pr_Cls_t * pClause; + int Var, v; + + // mark the variable encountered in the clauses of A + Pr_ManForEachClauseRoot( p, pClause ) + { + if ( !pClause->fA ) + break; + for ( v = 0; v < (int)pClause->nLits; v++ ) + p->pVarTypes[lit_var(pClause->pLits[v])] = 1; + } + + // check variables that appear in clauses of B + p->nVarsAB = 0; + Pr_ManForEachClauseRoot( p, pClause ) + { + if ( pClause->fA ) + continue; + for ( v = 0; v < (int)pClause->nLits; v++ ) + { + Var = lit_var(pClause->pLits[v]); + if ( p->pVarTypes[Var] == 1 ) // var of A + { + // change it into a global variable + p->nVarsAB++; + p->pVarTypes[Var] = -1; + } + } + } + + // order global variables + p->nVarsAB = 0; + for ( v = 0; v < p->nVars; v++ ) + if ( p->pVarTypes[v] == -1 ) + p->pVarTypes[v] -= p->nVarsAB++; +printf( "There are %d global variables.\n", p->nVarsAB ); + + // set interpolants for root clauses + Pr_ManForEachClauseRoot( p, pClause ) + { + if ( !pClause->fA ) // clause of B + { + pClause->uTruth = ~0; + Pr_ManPrintInterOne( p, pClause ); + continue; + } + // clause of A + pClause->uTruth = 0; + for ( v = 0; v < (int)pClause->nLits; v++ ) + { + Var = lit_var(pClause->pLits[v]); + if ( p->pVarTypes[Var] < 0 ) // global var + { + if ( lit_sign(pClause->pLits[v]) ) // negative var + pClause->uTruth |= ~uTruths[ -p->pVarTypes[Var]-1 ]; + else + pClause->uTruth |= uTruths[ -p->pVarTypes[Var]-1 ]; + } + } + Pr_ManPrintInterOne( p, pClause ); + } +} + +/**Function************************************************************* + + Synopsis [Records the proof.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pr_ManProofWrite( Pr_Man_t * p ) +{ + Pr_Cls_t * pClause; + int RetValue = 1; + + // propagate root level assignments + Pr_ManProcessRoots( p ); + + // prepare the interpolant computation + if ( p->nClausesA ) + Pr_ManPrepareInter( p ); + + // construct proof for each clause + // start the proof + if ( p->fProofWrite ) + p->pManProof = fopen( "proof.cnf_", "w" ); + p->Counter = 0; + + // write the root clauses + Pr_ManForEachClauseRoot( p, pClause ) + Pr_ManProofWriteOne( p, pClause ); + + // consider each learned clause + Pr_ManForEachClauseLearnt( p, pClause ) + { + if ( !Pr_ManProofRecordOne( p, pClause ) ) + { + RetValue = 0; + break; + } + } + + if ( p->nClausesA ) + { + printf( "Interpolant: " ); + } + + + // stop the proof + if ( p->fProofWrite ) + { + fclose( p->pManProof ); + p->pManProof = NULL; + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Reads clauses from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pr_Man_t * Pr_ManProofRead( char * pFileName ) +{ + Pr_Man_t * p = NULL; + char * pCur, * pBuffer = NULL; + int * pArray = NULL; + FILE * pFile; + int RetValue, Counter, nNumbers, Temp; + int nClauses, nClausesA, nRoots, nVars; + + // open the file + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Count not open input file \"%s\".\n", pFileName ); + return NULL; + } + + // read the file + pBuffer = (char *)malloc( (1<<16) ); + for ( Counter = 0; fgets( pBuffer, (1<<16), pFile ); ) + { + if ( pBuffer[0] == 'c' ) + continue; + if ( pBuffer[0] == 'p' ) + { + assert( p == NULL ); + nClausesA = 0; + RetValue = sscanf( pBuffer + 1, "%d %d %d %d", &nVars, &nClauses, &nRoots, &nClausesA ); + if ( RetValue != 3 && RetValue != 4 ) + { + printf( "Wrong input file format.\n" ); + } + p = Pr_ManAlloc( nVars ); + pArray = (int *)malloc( sizeof(int) * (nVars + 10) ); + continue; + } + // skip empty lines + for ( pCur = pBuffer; *pCur; pCur++ ) + if ( !(*pCur == ' ' || *pCur == '\t' || *pCur == '\r' || *pCur == '\n') ) + break; + if ( *pCur == 0 ) + continue; + // scan the numbers from file + nNumbers = 0; + pCur = pBuffer; + while ( *pCur ) + { + // skip spaces + for ( ; *pCur && *pCur == ' '; pCur++ ); + // read next number + Temp = 0; + sscanf( pCur, "%d", &Temp ); + if ( Temp == 0 ) + break; + pArray[ nNumbers++ ] = lit_read( Temp ); + // skip non-spaces + for ( ; *pCur && *pCur != ' '; pCur++ ); + } + // add the clause + if ( !Pr_ManAddClause( p, pArray, pArray + nNumbers, Counter < nRoots, Counter < nClausesA ) ) + { + printf( "Bad clause number %d.\n", Counter ); + return NULL; + } + // count the clauses + Counter++; + } + // check the number of clauses + if ( Counter != nClauses ) + printf( "Expected %d clauses but read %d.\n", nClauses, Counter ); + + // finish + if ( pArray ) free( pArray ); + if ( pBuffer ) free( pBuffer ); + fclose( pFile ); + return p; +} + +/**Function************************************************************* + + Synopsis [Records the proof.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +int Pr_ManProofCount_rec( Pr_Cls_t * pClause ) +{ + Pr_Cls_t * pNext; + int i, Counter; + if ( pClause->fRoot ) + return 0; + if ( pClause->fVisit ) + return 0; + pClause->fVisit = 1; + // count the number of visited clauses + Counter = 1; + Vec_PtrForEachEntry( pClause->pAntis, pNext, i ) + Counter += Pr_ManProofCount_rec( pNext ); + return Counter; +} +*/ + +/**Function************************************************************* + + Synopsis [Records the proof.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Pr_ManProofTest( char * pFileName ) +{ + Pr_Man_t * p; + int clk, clkTotal = clock(); + +clk = clock(); + p = Pr_ManProofRead( pFileName ); +p->timeRead = clock() - clk; + if ( p == NULL ) + return 0; + + Pr_ManProofWrite( p ); + + // print stats +/* + nUsed = Pr_ManProofCount_rec( p->pEmpty ); + printf( "Roots = %d. Learned = %d. Total = %d. Steps = %d. Ave = %.2f. Used = %d. Ratio = %.2f. \n", + p->nRoots, p->nClauses-p->nRoots, p->nClauses, p->Counter, + 1.0*(p->Counter-p->nRoots)/(p->nClauses-p->nRoots), + nUsed, 1.0*nUsed/(p->nClauses-p->nRoots) ); +*/ + printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d. Ave = %.2f. Mem = %.2f Mb\n", + p->nVars, p->nRoots, p->nClauses-p->nRoots, p->Counter, + 1.0*(p->Counter-p->nRoots)/(p->nClauses-p->nRoots), + 1.0*Pr_ManMemoryReport(p)/(1<<20) ); + +p->timeTotal = clock() - clkTotal; + Pr_ManFree( p ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/abc70930/src/sat/proof/pr.h b/abc70930/src/sat/proof/pr.h new file mode 100644 index 00000000..1e71a2d3 --- /dev/null +++ b/abc70930/src/sat/proof/pr.h @@ -0,0 +1,65 @@ +/**CFile**************************************************************** + + FileName [pr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Proof recording.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: pr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef __PR_H__ +#define __PR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _WIN32 +#define inline __inline // compatible with MS VS 6.0 +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Pr_Man_t_ Pr_Man_t; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== pr.c ==========================================================*/ + +#ifdef __cplusplus +} +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/abc70930/src/sat/proof/stats.txt b/abc70930/src/sat/proof/stats.txt new file mode 100644 index 00000000..470b1630 --- /dev/null +++ b/abc70930/src/sat/proof/stats.txt @@ -0,0 +1,66 @@ +UC Berkeley, ABC 1.01 (compiled Jan 20 2007 16:47:34) +abc.rc: No such file or directory +Loaded "abc.rc" from the parent directory. +abc 01> test +Found last conflict after adding unit clause number 10229! +Roots = 7184. Learned = 3047. Total = 10231. Steps = 196361. Ave = 62.09. Used = 2224. Ratio = 0.73. +Runtime stats: +Reading = 0.03 sec +BCP = 0.32 sec +Trace = 0.06 sec +TOTAL = 0.43 sec +abc 01> test +Found last conflict after adding unit clause number 7676! +Roots = 6605. Learned = 1073. Total = 7678. Steps = 52402. Ave = 42.68. Used = 1011. Ratio = 0.94. +Runtime stats: +Reading = 0.01 sec +BCP = 0.02 sec +Trace = 0.02 sec +TOTAL = 0.06 sec +abc 01> test +Found last conflict after adding unit clause number 37868! +Roots = 15443. Learned = 22427. Total = 37870. Steps = 2365472. Ave = 104.79. Used = 19763. Ratio = 0.88. +Runtime stats: +Reading = 0.20 sec +BCP = 14.67 sec +Trace = 0.56 sec +TOTAL = 15.74 sec +abc 01> + + +abc 05> wb ibm_bmc/len25u_renc.blif +abc 05> ps +(no name) : i/o = 348/ 1 lat = 0 nd = 3648 bdd = 15522 lev = 246 +abc 05> sat -v +==================================[MINISAT]=================================== +| Conflicts | ORIGINAL | LEARNT | Progress | +| | Clauses Literals | Limit Clauses Literals Lit/Cl | | +============================================================================== +| 0 | 17413 54996 | 5804 0 0 0.0 | 0.000 % | +| 100 | 17413 54996 | 6384 100 606 6.1 | 0.417 % | +| 250 | 17413 54996 | 7023 250 1586 6.3 | 0.417 % | +| 476 | 17413 54996 | 7725 476 3288 6.9 | 0.417 % | +| 813 | 17413 54996 | 8498 813 7586 9.3 | 0.417 % | +| 1319 | 17403 54970 | 9347 1318 14848 11.3 | 0.442 % | +| 2078 | 17403 54970 | 10282 2076 40186 19.4 | 0.466 % | +| 3217 | 17397 54948 | 11310 3208 99402 31.0 | 0.466 % | +| 4926 | 17392 54930 | 12441 4911 131848 26.8 | 0.491 % | +| 7489 | 17392 54930 | 13686 7474 204217 27.3 | 0.491 % | +| 11336 | 17357 54829 | 15054 11310 332863 29.4 | 0.638 % | +| 17103 | 17346 54794 | 16559 9130 203029 22.2 | 0.687 % | +| 25752 | 17288 54606 | 18215 9083 176982 19.5 | 0.834 % | +| 38727 | 17266 54536 | 20037 12674 278949 22.0 | 0.883 % | +| 58188 | 17240 54453 | 22041 11905 255255 21.4 | 0.957 % | +============================================================================== +Start = 15. Conf = 79435. Dec = 130967. Prop = 24083434. Insp = 136774586. +Total runtime = 18.66 sec. Var select = 0.00 sec. Var update = 0.00 sec. +UNSATISFIABLE Time = 18.69 sec +abc 05> +abc 05> test +Found last conflict after adding unit clause number 96902! +Roots = 17469. Learned = 79435. Total = 96904. Steps = 9700042. Ave = 121.89. Used = 57072. Ratio = 0.72. +Runtime stats: +Reading = 1.26 sec +BCP = 204.99 sec +Trace = 2.85 sec +TOTAL = 209.85 sec \ No newline at end of file diff --git a/abclib.dsp b/abclib.dsp deleted file mode 100644 index 46078652..00000000 --- a/abclib.dsp +++ /dev/null @@ -1,2336 +0,0 @@ -# Microsoft Developer Studio Project File - Name="abclib" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Static Library" 0x0104 - -CFG=abclib - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "abclib.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "abclib.mak" CFG="abclib - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "abclib - Win32 Release" (based on "Win32 (x86) Static Library") -!MESSAGE "abclib - Win32 Debug" (based on "Win32 (x86) Static Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "abclib - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "abclib___Win32_Release" -# PROP BASE Intermediate_Dir "abclib___Win32_Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "abclib\ReleaseLib" -# PROP Intermediate_Dir "abclib\ReleaseLib" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\bsat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\opt\kit" /I "src\map\fpga" /I "src\map\if" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\misc\hash" /I "src\aig\ivy" /I "src\aig\hop" /I "src\aig\rwt" /I "src\aig\deco" /I "src\aig\mem" /I "src\temp\esop" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"abclib\abclib_release.lib" - -!ELSEIF "$(CFG)" == "abclib - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "abclib___Win32_Debug" -# PROP BASE Intermediate_Dir "abclib___Win32_Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "abclib\DebugLib" -# PROP Intermediate_Dir "abclib\DebugLib" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\bsat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\opt\kit" /I "src\map\fpga" /I "src\map\if" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /I "src\misc\vec" /I "src\misc\espresso" /I "src\misc\nm" /I "src\misc\hash" /I "src\aig\ivy" /I "src\aig\hop" /I "src\aig\rwt" /I "src\aig\deco" /I "src\aig\mem" /I "src\temp\esop" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "__STDC__" /D "HAVE_ASSERT_H" /FR /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LIB32=link.exe -lib -# ADD BASE LIB32 /nologo -# ADD LIB32 /nologo /out:"abclib\abclib_debug.lib" - -!ENDIF - -# Begin Target - -# Name "abclib - Win32 Release" -# Name "abclib - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Group "base" - -# PROP Default_Filter "" -# Begin Group "abc" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\abc\abc.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcAig.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcDfs.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcFanio.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcFunc.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcLatch.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcLib.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcMinBase.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcNames.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcNetlist.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcNtk.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcObj.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcRefs.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcShow.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcSop.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abc\abcUtil.c -# End Source File -# End Group -# Begin Group "abci" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\abci\abc.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcAttach.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcAuto.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcBalance.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcBmc.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcClpBdd.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcClpSop.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcDebug.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcDress.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcDsd.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcEspresso.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcExtract.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcFpga.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcFpgaFast.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcFraig.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcFxu.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcGen.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcIf.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcIvy.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcLut.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcMap.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcMini.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcMiter.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcMulti.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcMv.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcNtbdd.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcOrder.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcPrint.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcProve.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcReconv.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcRefactor.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcRenode.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcReorder.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcRestruct.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcResub.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcRewrite.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcRr.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcStrash.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcSweep.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcSymm.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcTiming.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcUnate.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcUnreach.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcVerify.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\abci\abcXsim.c -# End Source File -# End Group -# Begin Group "cmd" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\cmd\cmd.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmd.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdAlias.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdFlag.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdHist.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\cmd\cmdUtils.c -# End Source File -# End Group -# Begin Group "io" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\io\io.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\io.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadAiger.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadBaf.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadBench.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadBlif.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadBlifAig.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadEdif.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadEqn.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioReadPla.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteAiger.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteBaf.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteBench.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteBlif.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteCnf.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteDot.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteEqn.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteGml.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteList.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWritePla.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteVer.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\io\ioWriteVerAux.c -# End Source File -# End Group -# Begin Group "main" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\main\libSupport.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\main.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\main.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\mainFrame.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\mainInit.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\mainInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\main\mainUtils.c -# End Source File -# End Group -# Begin Group "ver" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\base\ver\ver.h -# End Source File -# Begin Source File - -SOURCE=.\src\base\ver\verCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\ver\verFormula.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\ver\verParse.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\ver\verStream.c -# End Source File -# Begin Source File - -SOURCE=.\src\base\ver\verWords.c -# End Source File -# End Group -# End Group -# Begin Group "bdd" - -# PROP Default_Filter "" -# Begin Group "cudd" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\cudd\cudd.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddAbs.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddApply.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddFind.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddInv.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddIte.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddNeg.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAddWalsh.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAndAbs.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAnneal.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddApa.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddAPI.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddApprox.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddBddAbs.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddBddCorr.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddBddIte.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddBridge.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddCache.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddClip.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddCof.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddCompose.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddDecomp.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddEssent.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddExact.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddExport.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddGenCof.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddGenetic.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddGroup.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddHarwell.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddInit.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddInteract.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddLCache.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddLevelQ.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddLinear.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddLiteral.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddMatMult.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddPriority.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddRead.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddRef.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddReorder.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSign.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSolve.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSplit.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSubsetHB.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSubsetSP.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddSymmetry.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddWindow.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddCount.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddFuncs.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddGroup.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddIsop.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddLin.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddMisc.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddPort.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddReord.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddSetop.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddSymm.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\cudd\cuddZddUtil.c -# End Source File -# End Group -# Begin Group "epd" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\epd\epd.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\epd\epd.h -# End Source File -# End Group -# Begin Group "mtr" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\mtr\mtr.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\mtr\mtrBasic.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\mtr\mtrGroup.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\mtr\mtrInt.h -# End Source File -# End Group -# Begin Group "parse" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\parse\parse.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\parse\parseCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\parse\parseEqn.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\parse\parseInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\parse\parseStack.c -# End Source File -# End Group -# Begin Group "dsd" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsd.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdLocal.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdProc.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\dsd\dsdTree.c -# End Source File -# End Group -# Begin Group "reo" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\bdd\reo\reo.h -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoProfile.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoSift.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoSwap.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoTest.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoTransfer.c -# End Source File -# Begin Source File - -SOURCE=.\src\bdd\reo\reoUnits.c -# End Source File -# End Group -# End Group -# Begin Group "sat" - -# PROP Default_Filter "" -# Begin Group "asat" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\sat\asat\added.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\asat\asatmem.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\asat\asatmem.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\asat\jfront.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\asat\solver.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\asat\solver.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\asat\solver_vec.h -# End Source File -# End Group -# Begin Group "msat" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\sat\msat\msat.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatActivity.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatClause.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatClauseVec.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatOrderH.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatQueue.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatRead.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatSolverApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatSolverCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatSolverIo.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatSolverSearch.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatSort.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\msat\msatVec.c -# End Source File -# End Group -# Begin Group "fraig" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\sat\fraig\fraig.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigCanon.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigChoice.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigFanout.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigFeed.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigNode.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigPrime.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\fraig\fraigVec.c -# End Source File -# End Group -# Begin Group "csat" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\sat\csat\csat_apis.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\csat\csat_apis.h -# End Source File -# End Group -# Begin Group "bsat" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\sat\bsat\satMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satMem.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satSolver.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satSolver.h -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satUtil.c -# End Source File -# Begin Source File - -SOURCE=.\src\sat\bsat\satVec.h -# End Source File -# End Group -# End Group -# Begin Group "opt" - -# PROP Default_Filter "" -# Begin Group "fxu" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\fxu\fxu.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxu.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuCreate.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuHeapD.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuHeapS.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuList.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuMatrix.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuPair.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuPrint.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuReduce.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuSelect.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuSingle.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\fxu\fxuUpdate.c -# End Source File -# End Group -# Begin Group "rwr" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\rwr\rwr.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrDec.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrEva.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrExp.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrLib.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrPrint.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrTemp.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\rwr\rwrUtil.c -# End Source File -# End Group -# Begin Group "cut" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\cut\cut.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutExpand.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutList.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutMerge.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutNode.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutOracle.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutPre22.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutSeq.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\cut\cutTruth.c -# End Source File -# End Group -# Begin Group "dec" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\dec\dec.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\dec\decAbc.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\dec\decFactor.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\dec\decMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\dec\decPrint.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\dec\decUtil.c -# End Source File -# End Group -# Begin Group "sim" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\sim\sim.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSeq.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSupp.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSwitch.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSym.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSymSat.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSymSim.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simSymStr.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\sim\simUtils.c -# End Source File -# End Group -# Begin Group "ret" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\ret\retArea.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retDelay.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retFlow.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retIncrem.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retInit.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\ret\retLvalue.c -# End Source File -# End Group -# Begin Group "kit" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\opt\kit\kit.h -# End Source File -# Begin Source File - -SOURCE=.\src\opt\kit\kitBdd.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\kit\kitFactor.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\kit\kitGraph.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\kit\kitHop.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\kit\kitIsop.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\kit\kitSop.c -# End Source File -# Begin Source File - -SOURCE=.\src\opt\kit\kitTruth.c -# End Source File -# End Group -# End Group -# Begin Group "map" - -# PROP Default_Filter "" -# Begin Group "fpga" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\fpga\fpga.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpga.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaCreate.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaCutUtils.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaFanout.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaLib.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaMatch.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaSwitch.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaTime.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaTruth.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaUtils.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\fpga\fpgaVec.c -# End Source File -# End Group -# Begin Group "mapper" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\mapper\mapper.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapper.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperCanon.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperCreate.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperCutUtils.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperFanout.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperLib.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperMatch.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperRefs.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperSuper.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperSwitch.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperTime.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperTree.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperTruth.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperUtils.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mapper\mapperVec.c -# End Source File -# End Group -# Begin Group "mio" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\mio\mio.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mio.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mioApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mioFunc.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mioInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mioRead.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\mio\mioUtils.c -# End Source File -# End Group -# Begin Group "super" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\super\super.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\super\super.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\super\superAnd.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\super\superGate.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\super\superInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\super\superWrite.c -# End Source File -# End Group -# Begin Group "if" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\map\if\if.h -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifCore.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifMap.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifPrepro.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifReduce.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifSeq.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifTime.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifTruth.c -# End Source File -# Begin Source File - -SOURCE=.\src\map\if\ifUtil.c -# End Source File -# End Group -# End Group -# Begin Group "misc" - -# PROP Default_Filter "" -# Begin Group "extra" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\extra\extra.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraBddAuto.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraBddKmap.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraBddMisc.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraBddSymm.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraBddUnate.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilBitMatrix.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilCanon.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilFile.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilMemory.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilMisc.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilProgress.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilReader.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilTruth.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\extra\extraUtilUtil.c -# End Source File -# End Group -# Begin Group "st" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\st\st.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\st\st.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\st\stmm.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\st\stmm.h -# End Source File -# End Group -# Begin Group "util" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\util\util_hack.h -# End Source File -# End Group -# Begin Group "mvc" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\mvc\mvc.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvc.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcCompare.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcContain.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcCover.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcCube.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcDivide.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcDivisor.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcList.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcLits.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcOpAlg.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcOpBool.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcPrint.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcSort.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\mvc\mvcUtils.c -# End Source File -# End Group -# Begin Group "vec" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\vec\vec.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecAtt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecFlt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecPtr.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecStr.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\vec\vecVec.h -# End Source File -# End Group -# Begin Group "espresso" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\espresso\cofactor.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cols.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\compl.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\contain.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cubehack.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cubestr.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cvrin.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cvrm.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cvrmisc.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\cvrout.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\dominate.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\equiv.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\espresso.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\espresso.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\essen.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\exact.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\expand.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\gasp.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\gimpel.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\globals.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\hack.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\indep.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\irred.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\map.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\matrix.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\mincov.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\mincov.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\mincov_int.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\opo.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\pair.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\part.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\primes.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\reduce.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\rows.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\set.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\setc.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\sharp.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\sminterf.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\solution.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\sparse.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\sparse.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\sparse_int.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\unate.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\util_old.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\espresso\verify.c -# End Source File -# End Group -# Begin Group "nm" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\nm\nm.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\nm\nmApi.c -# End Source File -# Begin Source File - -SOURCE=.\src\misc\nm\nmInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\nm\nmTable.c -# End Source File -# End Group -# Begin Group "hash" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\misc\hash\hash.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\hash\hashFlt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\hash\hashInt.h -# End Source File -# Begin Source File - -SOURCE=.\src\misc\hash\hashPtr.h -# End Source File -# End Group -# End Group -# Begin Group "aig" - -# PROP Default_Filter "" -# Begin Group "hop" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\hop\hop.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopBalance.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopDfs.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopObj.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopOper.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\hop\hopUtil.c -# End Source File -# End Group -# Begin Group "ivy" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\ivy\ivy.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyBalance.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyCanon.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyCheck.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyCut.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyCutTrav.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyDfs.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyDsd.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyFanout.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyFastMap.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyFraig.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyHaig.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyMem.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyMulti.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyObj.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyOper.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyResyn.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyRwr.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivySeq.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyShow.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyTable.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\ivy\ivyUtil.c -# End Source File -# End Group -# Begin Group "rwt" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\rwt\rwt.h -# End Source File -# Begin Source File - -SOURCE=.\src\aig\rwt\rwtDec.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\rwt\rwtMan.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\rwt\rwtUtil.c -# End Source File -# End Group -# Begin Group "deco" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\deco\deco.h -# End Source File -# End Group -# Begin Group "mem" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\src\aig\mem\mem.c -# End Source File -# Begin Source File - -SOURCE=.\src\aig\mem\mem.h -# End Source File -# End Group -# Begin Group "ec" - -# PROP Default_Filter "" -# End Group -# End Group -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# End Target -# End Project diff --git a/abclib.dsw b/abclib.dsw deleted file mode 100644 index 260ade17..00000000 --- a/abclib.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "abclib"=.\abclib.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/abctestlib.dsp b/abctestlib.dsp deleted file mode 100644 index e901cbda..00000000 --- a/abctestlib.dsp +++ /dev/null @@ -1,102 +0,0 @@ -# Microsoft Developer Studio Project File - Name="abctestlib" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=abctestlib - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "abctestlib.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "abctestlib.mak" CFG="abctestlib - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "abctestlib - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "abctestlib - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "abctestlib - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib C:\_projects\abc\abclib\abclib_release.lib /nologo /subsystem:console /machine:I386 /out:"_TEST/abctestlib.exe" - -!ELSEIF "$(CFG)" == "abctestlib - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c -# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /YX /FD /GZ /c -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib C:\_projects\abc\abclib\abclib_debug.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abctestlib.exe" /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "abctestlib - Win32 Release" -# Name "abctestlib - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\demo.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/abctestlib.dsw b/abctestlib.dsw deleted file mode 100644 index 7ae6cac9..00000000 --- a/abctestlib.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "abctestlib"=.\abctestlib.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/copyright.txt b/copyright.txt deleted file mode 100644 index 121d63e8..00000000 --- a/copyright.txt +++ /dev/null @@ -1,18 +0,0 @@ -Copyright (c) The Regents of the University of California. All rights reserved. - -Permission is hereby granted, without written agreement and without license or -royalty fees, to use, copy, modify, and distribute this software and its -documentation for any purpose, provided that the above copyright notice and -the following two paragraphs appear in all copies of this software. - -IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR -DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF -THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF -CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, -BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, -AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, -SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - diff --git a/demo.c b/demo.c deleted file mode 100644 index de162409..00000000 --- a/demo.c +++ /dev/null @@ -1,181 +0,0 @@ -/**CFile**************************************************************** - - FileName [demo.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [ABC as a static library.] - - Synopsis [A demo program illustrating the use of ABC as a static library.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: demo.c,v 1.00 2005/11/14 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// procedures to start and stop the ABC framework -// (should be called before and after the ABC procedures are called) -extern void Abc_Start(); -extern void Abc_Stop(); - -// procedures to get the ABC framework and execute commands in it -extern void * Abc_FrameGetGlobalFrame(); -extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [The main() procedure.] - - Description [This procedure compiles into a stand-alone program for - DAG-aware rewriting of the AIGs. A BLIF or PLA file to be considered - for rewriting should be given as a command-line argument. Implementation - of the rewriting is inspired by the paper: Per Bjesse, Arne Boralv, - "DAG-aware circuit compression for formal verification", Proc. ICCAD 2004.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int main( int argc, char * argv[] ) -{ - // parameters - int fUseResyn2 = 0; - int fPrintStats = 1; - int fVerify = 1; - // variables - void * pAbc; - char * pFileName; - char Command[1000]; - int clkRead, clkResyn, clkVer, clk; - - ////////////////////////////////////////////////////////////////////////// - // get the input file name - if ( argc != 2 ) - { - printf( "Wrong number of command-line arguments.\n" ); - return 1; - } - pFileName = argv[1]; - - ////////////////////////////////////////////////////////////////////////// - // start the ABC framework - Abc_Start(); - pAbc = Abc_FrameGetGlobalFrame(); - -clk = clock(); - ////////////////////////////////////////////////////////////////////////// - // read the file - sprintf( Command, "read %s", pFileName ); - if ( Cmd_CommandExecute( pAbc, Command ) ) - { - fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); - return 1; - } - - ////////////////////////////////////////////////////////////////////////// - // balance - sprintf( Command, "balance" ); - if ( Cmd_CommandExecute( pAbc, Command ) ) - { - fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); - return 1; - } -clkRead = clock() - clk; - - ////////////////////////////////////////////////////////////////////////// - // print stats - if ( fPrintStats ) - { - sprintf( Command, "print_stats" ); - if ( Cmd_CommandExecute( pAbc, Command ) ) - { - fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); - return 1; - } - } - -clk = clock(); - ////////////////////////////////////////////////////////////////////////// - // synthesize - if ( fUseResyn2 ) - { - sprintf( Command, "balance; rewrite -l; refactor -l; balance; rewrite -l; rewrite -lz; balance; refactor -lz; rewrite -lz; balance" ); - if ( Cmd_CommandExecute( pAbc, Command ) ) - { - fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); - return 1; - } - } - else - { - sprintf( Command, "balance; rewrite -l; rewrite -lz; balance; rewrite -lz; balance" ); - if ( Cmd_CommandExecute( pAbc, Command ) ) - { - fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); - return 1; - } - } -clkResyn = clock() - clk; - - ////////////////////////////////////////////////////////////////////////// - // print stats - if ( fPrintStats ) - { - sprintf( Command, "print_stats" ); - if ( Cmd_CommandExecute( pAbc, Command ) ) - { - fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); - return 1; - } - } - - ////////////////////////////////////////////////////////////////////////// - // write the result in blif - sprintf( Command, "write_blif result.blif" ); - if ( Cmd_CommandExecute( pAbc, Command ) ) - { - fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); - return 1; - } - - ////////////////////////////////////////////////////////////////////////// - // perform verification -clk = clock(); - if ( fVerify ) - { - sprintf( Command, "cec %s result.blif", pFileName ); - if ( Cmd_CommandExecute( pAbc, Command ) ) - { - fprintf( stdout, "Cannot execute command \"%s\".\n", Command ); - return 1; - } - } -clkVer = clock() - clk; - - printf( "Reading = %6.2f sec ", (float)(clkRead)/(float)(CLOCKS_PER_SEC) ); - printf( "Rewriting = %6.2f sec ", (float)(clkResyn)/(float)(CLOCKS_PER_SEC) ); - printf( "Verification = %6.2f sec\n", (float)(clkVer)/(float)(CLOCKS_PER_SEC) ); - - ////////////////////////////////////////////////////////////////////////// - // stop the ABC framework - Abc_Stop(); - return 0; -} - diff --git a/depends.sh b/depends.sh deleted file mode 100755 index d302cd04..00000000 --- a/depends.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -#echo "## Got: $*" -CC="$1" -DIR="$2" -shift 2 -case "$DIR" in - "" | ".") - $CC -MM -MG "$@" | sed -e 's@^\(.*\)\.o:@\1.d \1.o:@' - ;; - *) - $CC -MM -MG "$@" | sed -e "s@^\(.*\)\.o:@$DIR/\1.d $DIR/\1.o:@" - ;; -esac diff --git a/readme b/readme deleted file mode 100644 index 5c06d4b5..00000000 --- a/readme +++ /dev/null @@ -1,26 +0,0 @@ -Often the code comes directly from a Windows computer. -The following steps may be needed to compile it on UNIX: - ->> dos2unix Makefile Makefile ->> dos2unix depends.sh depends.sh ->> chmod 755 depends.sh ->> make // on Solaris, try "gmake" - -If compiling as a static library, it is necessary to uncomment -#define _LIB in "src/abc/main/main.c" - -Several things to try if it does not compile on your platform: -- Try running all code (not only Makefile and depends.sh) through dos2unix -- Try the following actions: - (a) Remove flags from the libs line (LIBS :=) in Makefile - (b) Remove "src\base\main\libSupport.c" from "src\base\main\module.make" - (c) Comment calls to Libs_Init() and Libs_End() in "src\base\main\mainInit.c" -- Try linking with gcc (rather than g++) - For this replace "LD := g++" with "LD := gcc -lm" in Makefile -- If your Linux distributin does not have "readline", you may have problems - compiling ABC with gcc. Please try installing this library from - http://tiswww.case.edu/php/chet/readline/rltop.html - - -Finally, run regression test: -abc>>> so regtest.script diff --git a/regtest.script b/regtest.script deleted file mode 100644 index c4a23a89..00000000 --- a/regtest.script +++ /dev/null @@ -1,18 +0,0 @@ -r examples/apex4.pla; resyn; if; cec; ps; clp; resyn; map; cec; ps -r examples/C2670.blif; st; w 1.aig; cec 1.aig -r examples/C2670.blif; st; short_names; w 1.bench; cec 1.bench -r examples/C2670.blif; st; short_names; ren -s; w 1.eqn; cec 1.eqn -r examples/C2670.blif; resyn2; if -K 8; cec; ps; u; map; cec; ps -r examples/frg2.blif; dsd; muxes; cec; ps; clp; share; resyn; map; cec; ps -r examples/frg2.blif; bdd; muxes; cec; ps; clp; st; ren -b; muxes; cec; ps -r examples/i10.blif; resyn2; fpga; cec; ps; u; map; cec; ps -r examples/i10.blif; choice; fpga; cec; ps; u; map; cec; ps -r examples/pj1.blif; st; if; cec; ps; u; map; cec; ps -r examples/s38417.blif; comb; w 1.blif; resyn; if; cec 1.blif; ps -r examples/s38417.blif; resyn; if; cec; ps; u; map; cec; ps -r examples/s38584.bench; resyn; ren -s; fx; if; cec; ps; u; map; cec; ps -r examples/s444.blif; b; esd -v; print_exdc; dsd; cec; ps -r examples/s444.blif; double; frames -F 5; w 1.blif; ffpga -K 8; cec 1.blif -r examples/s5378.blif; frames -F 5; cycle; w 1.blif; ps; ret; ps; sec 1.blif -r examples/s6669.blif; cycle; w 1.blif; ps; ret -M 3; resyn; ps; sec 1.blif -time diff --git a/regtest_output.txt b/regtest_output.txt deleted file mode 100644 index 6e0ffec3..00000000 --- a/regtest_output.txt +++ /dev/null @@ -1,96 +0,0 @@ -UC Berkeley, ABC 1.01 (compiled Dec 25 2006 17:15:00) -abc 01> so regtest.script -abc - > r examples/apex4.pla; resyn; if; cec; ps; clp; resyn; map; cec; ps -Networks are equivalent. -examples/apex4: i/o = 9/ 19 lat = 0 nd = 1172 aig = 4365 lev = 7 -The shared BDD size is 917 nodes. BDD construction time = 0.04 sec -A simple supergate library is derived from gate library "mcnc_temp.genlib". -Loaded 20 unique 5-input supergates from "mcnc_temp.super". Time = 0.02 sec -Networks are equivalent. -examples/apex4: i/o = 9/ 19 lat = 0 nd = 1734 aig = 2576 lev = 12 -abc - > r examples/C2670.blif; st; w 1.aig; cec 1.aig -Networks are equivalent after structural hashing. -abc - > r examples/C2670.blif; st; short_names; w 1.bench; cec 1.bench -Networks are equivalent after structural hashing. -abc - > r examples/C2670.blif; st; short_names; ren -s; w 1.eqn; cec 1.eqn -Networks are equivalent. -abc - > r examples/C2670.blif; resyn2; if -K 8; cec; ps; u; map; cec; ps -Networks are equivalent. -C2670.iscas : i/o = 233/ 140 lat = 0 nd = 120 aig = 1056 lev = 4 -Networks are equivalent. -C2670.iscas : i/o = 233/ 140 lat = 0 nd = 467 aig = 651 lev = 14 -abc - > r examples/frg2.blif; dsd; muxes; cec; ps; clp; share; resyn; map; cec; ps -Networks are equivalent. -frg2 : i/o = 143/ 139 lat = 0 nd = 1648 aig = 2268 lev = 18 -The shared BDD size is 1672 nodes. BDD construction time = 0.14 sec -Networks are equivalent. -frg2 : i/o = 143/ 139 lat = 0 nd = 533 aig = 778 lev = 8 -abc - > r examples/frg2.blif; bdd; muxes; cec; ps; clp; st; ren -b; muxes; cec; ps -Networks are equivalent. -frg2 : i/o = 143/ 139 lat = 0 nd = 2868 aig = 4221 lev = 38 -The shared BDD size is 1684 nodes. BDD construction time = 0.14 sec -Networks are equivalent. -frg2 : i/o = 143/ 139 lat = 0 nd = 2331 aig = 3180 lev = 20 -abc - > r examples/i10.blif; resyn2; fpga; cec; ps; u; map; cec; ps -Networks are equivalent. -i10 : i/o = 257/ 224 lat = 0 nd = 808 aig = 2630 lev = 12 -Networks are equivalent. -i10 : i/o = 257/ 224 lat = 0 nd = 1555 aig = 1980 lev = 24 -abc - > r examples/i10.blif; choice; fpga; cec; ps; u; map; cec; ps -Currently stored 3 networks with 5801 nodes will be fraiged. -Total fraiging time = 0.39 sec -Performing FPGA mapping with choices. -Networks are equivalent. -i10 : i/o = 257/ 224 lat = 0 nd = 798 aig = 2543 lev = 12 -Performing mapping with choices. -Networks are equivalent. -i10 : i/o = 257/ 224 lat = 0 nd = 1463 aig = 1993 lev = 23 -abc - > r examples/pj1.blif; st; if; cec; ps; u; map; cec; ps -Networks are equivalent after structural hashing. -exCombCkt : i/o = 1769/1063 lat = 0 nd = 5984 aig = 23156 lev = 52 -Networks are equivalent. -exCombCkt : i/o = 1769/1063 lat = 0 nd = 11474 aig = 16032 lev = 80 -abc - > r examples/s38417.blif; comb; w 1.blif; resyn; if; cec 1.blif; ps -examples/s38417.blif (line 14): Skipping directive ".wire_load_slope". -Networks are equivalent. -s38417 : i/o = 1664/1742 lat = 0 nd = 3479 aig = 10120 lev = 9 -abc - > r examples/s38417.blif; resyn; if; cec; ps; u; map; cec; ps -examples/s38417.blif (line 14): Skipping directive ".wire_load_slope". -examples/s38417.blif (line 14): Skipping directive ".wire_load_slope". -Networks are equivalent. -s38417 : i/o = 28/ 106 lat = 1636 nd = 3479 aig = 10120 lev = 9 -examples/s38417.blif (line 14): Skipping directive ".wire_load_slope". -Networks are equivalent. -s38417 : i/o = 28/ 106 lat = 1636 nd = 7189 aig = 8689 lev = 17 -abc - > r examples/s38584.bench; resyn; ren -s; fx; if; cec; ps; u; map; cec; ps -The network was strashed and balanced before FPGA mapping. -Networks are equivalent. -examples/s38584: i/o = 12/ 278 lat = 1452 nd = 4266 aig = 12569 lev = 10 -The network was strashed and balanced before mapping. -Networks are equivalent. -examples/s38584: i/o = 12/ 278 lat = 1452 nd = 8135 aig = 10674 lev = 18 -abc - > r examples/s444.blif; b; esd -v; print_exdc; dsd; cec; ps -The shared BDD size is 181 nodes. -BDD nodes in the transition relation before reordering 557. -BDD nodes in the transition relation after reordering 456. -Reachability analysis completed in 151 iterations. -The number of minterms in the reachable state set = 8865. -BDD nodes in the unreachable states before reordering 124. -BDD nodes in the unreachable states after reordering 113. -EXDC network statistics: -exdc : i/o = 21/ 21 lat = 0 nd = 21 cube = 86 lev = 2 -Networks are equivalent. -s444 : i/o = 3/ 6 lat = 21 nd = 82 aig = 176 lev = 7 -abc - > r examples/s444.blif; double; frames -F 5; w 1.blif; ffpga -K 8; cec 1.blif -Networks are equivalent after structural hashing. -abc - > r examples/s5378.blif; frames -F 5; cycle; w 1.blif; ps; ret; ps; sec 1.blif -s5378_5_frames: i/o = 175/ 245 lat = 164 and = 6629 (exor = 115) lev = 59 -s5378_5_frames: i/o = 175/ 245 lat = 182 nd = 6957 cube = 6956 lev = 50 -Networks are equivalent after framing. -abc - > r examples/s6669.blif; cycle; w 1.blif; ps; ret -M 3; resyn; ps; sec 1.blif -s6669 : i/o = 83/ 55 lat = 239 nd = 3080 cube = 3080 lev = 93 -s6669 : i/o = 83/ 55 lat = 183 and = 1915 (exor = 371) lev = 97 -Networks are equivalent after fraiging. -abc - > time -elapse: 44.07 seconds, total: 44.07 seconds -abc 150> \ No newline at end of file diff --git a/src/aig/aig/aig.h b/src/aig/aig/aig.h deleted file mode 100644 index 63456b5d..00000000 --- a/src/aig/aig/aig.h +++ /dev/null @@ -1,556 +0,0 @@ -/**CFile**************************************************************** - - FileName [aig.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aig.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __AIG_H__ -#define __AIG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Aig_Man_t_ Aig_Man_t; -typedef struct Aig_Obj_t_ Aig_Obj_t; -typedef struct Aig_MmFixed_t_ Aig_MmFixed_t; -typedef struct Aig_MmFlex_t_ Aig_MmFlex_t; -typedef struct Aig_MmStep_t_ Aig_MmStep_t; -typedef struct Aig_TMan_t_ Aig_TMan_t; - -// object types -typedef enum { - AIG_OBJ_NONE, // 0: non-existent object - AIG_OBJ_CONST1, // 1: constant 1 - AIG_OBJ_PI, // 2: primary input - AIG_OBJ_PO, // 3: primary output - AIG_OBJ_BUF, // 4: buffer node - AIG_OBJ_AND, // 5: AND node - AIG_OBJ_EXOR, // 6: EXOR node - AIG_OBJ_LATCH, // 7: latch - AIG_OBJ_VOID // 8: unused object -} Aig_Type_t; - -// the AIG node -struct Aig_Obj_t_ // 8 words -{ - Aig_Obj_t * pNext; // strashing table - Aig_Obj_t * pFanin0; // fanin - Aig_Obj_t * pFanin1; // fanin - unsigned int Type : 3; // object type - unsigned int fPhase : 1; // value under 000...0 pattern - unsigned int fMarkA : 1; // multipurpose mask - unsigned int fMarkB : 1; // multipurpose mask - unsigned int nRefs : 26; // reference count - unsigned Level : 24; // the level of this node - unsigned nCuts : 8; // the number of cuts - int TravId; // unique ID of last traversal involving the node - int Id; // unique ID of the node - union { // temporary store for user's data - void * pData; - int iData; - float dData; - }; -}; - -// the AIG manager -struct Aig_Man_t_ -{ - char * pName; // the design name - // AIG nodes - Vec_Ptr_t * vPis; // the array of PIs - Vec_Ptr_t * vPos; // the array of POs - Vec_Ptr_t * vObjs; // the array of all nodes (optional) - Vec_Ptr_t * vBufs; // the array of buffers - Aig_Obj_t * pConst1; // the constant 1 node - Aig_Obj_t Ghost; // the ghost node - int nRegs; // the number of registers (registers are last POs) - int nAsserts; // the number of asserts among POs (asserts are first POs) - // AIG node counters - int nObjs[AIG_OBJ_VOID];// the number of objects by type - int nCreated; // the number of created objects - int nDeleted; // the number of deleted objects - // structural hash table - Aig_Obj_t ** pTable; // structural hash table - int nTableSize; // structural hash table size - // representation of fanouts - int * pFanData; // the database to store fanout information - int nFansAlloc; // the size of fanout representation - Vec_Vec_t * vLevels; // used to update timing information - int nBufReplaces; // the number of times replacement led to a buffer - int nBufFixes; // the number of times buffers were propagated - int nBufMax; // the maximum number of buffers during computation - // topological order - unsigned * pOrderData; - int nOrderAlloc; - int iPrev; - int iNext; - int nAndTotal; - int nAndPrev; - // representatives - Aig_Obj_t ** pEquivs; // linked list of equivalent nodes (when choices are used) - Aig_Obj_t ** pReprs; // representatives of each node - int nReprsAlloc; // the number of allocated representatives - // various data members - Aig_MmFixed_t * pMemObjs; // memory manager for objects - Vec_Int_t * vLevelR; // the reverse level of the nodes - int nLevelMax; // maximum number of levels - void * pData; // the temporary data - int nTravIds; // the current traversal ID - int fCatchExor; // enables EXOR nodes - int fAddStrash; // performs additional strashing - Aig_Obj_t ** pObjCopies; // mapping of AIG nodes into FRAIG nodes - void (*pImpFunc) (void*, void*); // implication checking precedure - void * pImpData; // implication checking data - Aig_TMan_t * pManTime; // the timing manager - Vec_Int_t * vPiIds; - Vec_Int_t * vPoIds; - Vec_Ptr_t * vMapped; - Vec_Int_t * vFlopNums; - // timing statistics - int time1; - int time2; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define AIG_MIN(a,b) (((a) < (b))? (a) : (b)) -#define AIG_MAX(a,b) (((a) > (b))? (a) : (b)) -#define AIG_ABS(a) (((a) >= 0)? (a) :-(a)) -#define AIG_INFINITY (100000000) - -#ifndef PRT -#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) -#endif - -static inline int Aig_Base2Log( unsigned n ) { int r; assert( n >= 0 ); if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ); return r; } -static inline int Aig_Base10Log( unsigned n ) { int r; assert( n >= 0 ); if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ); return r; } -static inline char * Aig_UtilStrsav( char * s ) { return s ? strcpy(ALLOC(char, strlen(s)+1), s) : NULL; } -static inline int Aig_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } -static inline int Aig_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -static inline int Aig_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } -static inline void Aig_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } -static inline void Aig_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } -static inline unsigned Aig_InfoMask( int nVar ) { return (~(unsigned)0) >> (32-nVar); } -static inline unsigned Aig_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId & 31)); } -static inline int Aig_WordCountOnes( unsigned uWord ) -{ - uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); - uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); - uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); - uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); - return (uWord & 0x0000FFFF) + (uWord>>16); -} - -static inline Aig_Obj_t * Aig_Regular( Aig_Obj_t * p ) { return (Aig_Obj_t *)((unsigned long)(p) & ~01); } -static inline Aig_Obj_t * Aig_Not( Aig_Obj_t * p ) { return (Aig_Obj_t *)((unsigned long)(p) ^ 01); } -static inline Aig_Obj_t * Aig_NotCond( Aig_Obj_t * p, int c ) { return (Aig_Obj_t *)((unsigned long)(p) ^ (c)); } -static inline int Aig_IsComplement( Aig_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } - -static inline int Aig_ManPiNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_PI]; } -static inline int Aig_ManPoNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_PO]; } -static inline int Aig_ManBufNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_BUF]; } -static inline int Aig_ManAndNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]; } -static inline int Aig_ManExorNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_EXOR]; } -static inline int Aig_ManLatchNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_LATCH]; } -static inline int Aig_ManNodeNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]+p->nObjs[AIG_OBJ_EXOR]; } -static inline int Aig_ManGetCost( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]+3*p->nObjs[AIG_OBJ_EXOR]; } -static inline int Aig_ManObjNum( Aig_Man_t * p ) { return p->nCreated - p->nDeleted; } -static inline int Aig_ManObjNumMax( Aig_Man_t * p ) { return Vec_PtrSize(p->vObjs); } -static inline int Aig_ManRegNum( Aig_Man_t * p ) { return p->nRegs; } - -static inline Aig_Obj_t * Aig_ManConst0( Aig_Man_t * p ) { return Aig_Not(p->pConst1); } -static inline Aig_Obj_t * Aig_ManConst1( Aig_Man_t * p ) { return p->pConst1; } -static inline Aig_Obj_t * Aig_ManGhost( Aig_Man_t * p ) { return &p->Ghost; } -static inline Aig_Obj_t * Aig_ManPi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPis, i); } -static inline Aig_Obj_t * Aig_ManPo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPos, i); } -static inline Aig_Obj_t * Aig_ManLo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPis, Aig_ManPiNum(p)-Aig_ManRegNum(p)+i); } -static inline Aig_Obj_t * Aig_ManLi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vPos, Aig_ManPoNum(p)-Aig_ManRegNum(p)+i); } -static inline Aig_Obj_t * Aig_ManObj( Aig_Man_t * p, int i ) { return p->vObjs ? (Aig_Obj_t *)Vec_PtrEntry(p->vObjs, i) : NULL; } - -static inline Aig_Type_t Aig_ObjType( Aig_Obj_t * pObj ) { return (Aig_Type_t)pObj->Type; } -static inline int Aig_ObjIsNone( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_NONE; } -static inline int Aig_ObjIsConst1( Aig_Obj_t * pObj ) { assert(!Aig_IsComplement(pObj)); return pObj->Type == AIG_OBJ_CONST1; } -static inline int Aig_ObjIsPi( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_PI; } -static inline int Aig_ObjIsPo( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_PO; } -static inline int Aig_ObjIsBuf( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_BUF; } -static inline int Aig_ObjIsAnd( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND; } -static inline int Aig_ObjIsExor( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_EXOR; } -static inline int Aig_ObjIsLatch( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_LATCH; } -static inline int Aig_ObjIsNode( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR; } -static inline int Aig_ObjIsTerm( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_PI || pObj->Type == AIG_OBJ_PO || pObj->Type == AIG_OBJ_CONST1; } -static inline int Aig_ObjIsHash( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR || pObj->Type == AIG_OBJ_LATCH; } -static inline int Aig_ObjIsChoice( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquivs && p->pEquivs[pObj->Id] && pObj->nRefs > 0; } - -static inline int Aig_ObjIsMarkA( Aig_Obj_t * pObj ) { return pObj->fMarkA; } -static inline void Aig_ObjSetMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 1; } -static inline void Aig_ObjClearMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 0; } - -static inline void Aig_ObjSetTravId( Aig_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } -static inline void Aig_ObjSetTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } -static inline void Aig_ObjSetTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } -static inline int Aig_ObjIsTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int)(pObj->TravId == p->nTravIds); } -static inline int Aig_ObjIsTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int)(pObj->TravId == p->nTravIds - 1); } - -static inline int Aig_ObjTravId( Aig_Obj_t * pObj ) { return (int)pObj->pData; } -static inline int Aig_ObjPhase( Aig_Obj_t * pObj ) { return pObj->fPhase; } -static inline int Aig_ObjPhaseReal( Aig_Obj_t * pObj ) { return pObj? Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) : 1; } -static inline int Aig_ObjRefs( Aig_Obj_t * pObj ) { return pObj->nRefs; } -static inline void Aig_ObjRef( Aig_Obj_t * pObj ) { pObj->nRefs++; } -static inline void Aig_ObjDeref( Aig_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } -static inline void Aig_ObjClearRef( Aig_Obj_t * pObj ) { pObj->nRefs = 0; } -static inline int Aig_ObjFaninId0( Aig_Obj_t * pObj ) { return pObj->pFanin0? Aig_Regular(pObj->pFanin0)->Id : -1; } -static inline int Aig_ObjFaninId1( Aig_Obj_t * pObj ) { return pObj->pFanin1? Aig_Regular(pObj->pFanin1)->Id : -1; } -static inline int Aig_ObjFaninC0( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin0); } -static inline int Aig_ObjFaninC1( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin1); } -static inline Aig_Obj_t * Aig_ObjFanin0( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin0); } -static inline Aig_Obj_t * Aig_ObjFanin1( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin1); } -static inline Aig_Obj_t * Aig_ObjChild0( Aig_Obj_t * pObj ) { return pObj->pFanin0; } -static inline Aig_Obj_t * Aig_ObjChild1( Aig_Obj_t * pObj ) { return pObj->pFanin1; } -static inline Aig_Obj_t * Aig_ObjChild0Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Aig_ObjChild1Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj)) : NULL; } -static inline int Aig_ObjLevel( Aig_Obj_t * pObj ) { return pObj->Level; } -static inline int Aig_ObjLevelNew( Aig_Obj_t * pObj ) { return Aig_ObjFanin1(pObj)? 1 + Aig_ObjIsExor(pObj) + AIG_MAX(Aig_ObjFanin0(pObj)->Level, Aig_ObjFanin1(pObj)->Level) : Aig_ObjFanin0(pObj)->Level; } -static inline void Aig_ObjClean( Aig_Obj_t * pObj ) { memset( pObj, 0, sizeof(Aig_Obj_t) ); } -static inline Aig_Obj_t * Aig_ObjFanout0( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert(p->pFanData && pObj->Id < p->nFansAlloc); return Aig_ManObj(p, p->pFanData[5*pObj->Id] >> 1); } -static inline Aig_Obj_t * Aig_ObjEquiv( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquivs? p->pEquivs[pObj->Id] : NULL; } -static inline int Aig_ObjWhatFanin( Aig_Obj_t * pObj, Aig_Obj_t * pFanin ) -{ - if ( Aig_ObjFanin0(pObj) == pFanin ) return 0; - if ( Aig_ObjFanin1(pObj) == pFanin ) return 1; - assert(0); return -1; -} -static inline int Aig_ObjFanoutC( Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) -{ - if ( Aig_ObjFanin0(pFanout) == pObj ) return Aig_ObjFaninC0(pObj); - if ( Aig_ObjFanin1(pFanout) == pObj ) return Aig_ObjFaninC1(pObj); - assert(0); return -1; -} - -// create the ghost of the new node -static inline Aig_Obj_t * Aig_ObjCreateGhost( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) -{ - Aig_Obj_t * pGhost; - assert( Type != AIG_OBJ_AND || !Aig_ObjIsConst1(Aig_Regular(p0)) ); - assert( p1 == NULL || !Aig_ObjIsConst1(Aig_Regular(p1)) ); - assert( Type == AIG_OBJ_PI || Aig_Regular(p0) != Aig_Regular(p1) ); - pGhost = Aig_ManGhost(p); - pGhost->Type = Type; - if ( p1 == NULL || Aig_Regular(p0)->Id < Aig_Regular(p1)->Id ) - { - pGhost->pFanin0 = p0; - pGhost->pFanin1 = p1; - } - else - { - pGhost->pFanin0 = p1; - pGhost->pFanin1 = p0; - } - return pGhost; -} - -// internal memory manager -static inline Aig_Obj_t * Aig_ManFetchMemory( Aig_Man_t * p ) -{ - extern char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ); - Aig_Obj_t * pTemp; - pTemp = (Aig_Obj_t *)Aig_MmFixedEntryFetch( p->pMemObjs ); - memset( pTemp, 0, sizeof(Aig_Obj_t) ); - Vec_PtrPush( p->vObjs, pTemp ); - pTemp->Id = p->nCreated++; - return pTemp; -} -static inline void Aig_ManRecycleMemory( Aig_Man_t * p, Aig_Obj_t * pEntry ) -{ - extern void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ); - assert( pEntry->nRefs == 0 ); - pEntry->Type = AIG_OBJ_NONE; // distinquishes a dead node from a live node - Aig_MmFixedEntryRecycle( p->pMemObjs, (char *)pEntry ); - p->nDeleted++; -} - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator over the primary inputs -#define Aig_ManForEachPi( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPis, pObj, i ) -// iterator over the primary outputs -#define Aig_ManForEachPo( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPos, pObj, i ) -// iterator over the assertions -#define Aig_ManForEachAssert( p, pObj, i ) \ - Vec_PtrForEachEntryStart( p->vPos, pObj, i, Aig_ManPoNum(p)-p->nAsserts ) -// iterator over all objects, including those currently not used -#define Aig_ManForEachObj( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else -// iterator over all nodes -#define Aig_ManForEachNode( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsNode(pObj) ) {} else -// iterator over the nodes whose IDs are stored in the array -#define Aig_ManForEachNodeVec( p, vIds, pObj, i ) \ - for ( i = 0; i < Vec_IntSize(vIds) && ((pObj) = Aig_ManObj(p, Vec_IntEntry(vIds,i))); i++ ) -// iterator over the nodes in the topological order -#define Aig_ManForEachNodeInOrder( p, pObj ) \ - for ( assert(p->pOrderData), p->iPrev = 0, p->iNext = p->pOrderData[1]; \ - p->iNext && (((pObj) = Aig_ManObj(p, p->iNext)), 1); \ - p->iNext = p->pOrderData[2*p->iPrev+1] ) - -// these two procedures are only here for the use inside the iterator -static inline int Aig_ObjFanout0Int( Aig_Man_t * p, int ObjId ) { assert(ObjId < p->nFansAlloc); return p->pFanData[5*ObjId]; } -static inline int Aig_ObjFanoutNext( Aig_Man_t * p, int iFan ) { assert(iFan/2 < p->nFansAlloc); return p->pFanData[5*(iFan >> 1) + 3 + (iFan & 1)]; } -// iterator over the fanouts -#define Aig_ObjForEachFanout( p, pObj, pFanout, iFan, i ) \ - for ( assert(p->pFanData), i = 0; (i < (int)(pObj)->nRefs) && \ - (((iFan) = i? Aig_ObjFanoutNext(p, iFan) : Aig_ObjFanout0Int(p, pObj->Id)), 1) && \ - (((pFanout) = Aig_ManObj(p, iFan>>1)), 1); i++ ) - - -//////////////////////////////////////////////////////////////////////// -/// SEQUENTIAL ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator over the primary inputs -#define Aig_ManForEachPiSeq( p, pObj, i ) \ - Vec_PtrForEachEntryStop( p->vPis, pObj, i, Aig_ManPiNum(p)-Aig_ManRegNum(p) ) -// iterator over the latch outputs -#define Aig_ManForEachLoSeq( p, pObj, i ) \ - Vec_PtrForEachEntryStart( p->vPis, pObj, i, Aig_ManPiNum(p)-Aig_ManRegNum(p) ) -// iterator over the primary outputs -#define Aig_ManForEachPoSeq( p, pObj, i ) \ - Vec_PtrForEachEntryStop( p->vPos, pObj, i, Aig_ManPoNum(p)-Aig_ManRegNum(p) ) -// iterator over the latch inputs -#define Aig_ManForEachLiSeq( p, pObj, i ) \ - Vec_PtrForEachEntryStart( p->vPos, pObj, i, Aig_ManPoNum(p)-Aig_ManRegNum(p) ) -// iterator over the latch input and outputs -#define Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, k ) \ - for ( k = 0; (k < Aig_ManRegNum(p)) && (((pObjLi) = Aig_ManLi(p, k)), 1) \ - && (((pObjLo)=Aig_ManLo(p, k)), 1); k++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== aigCheck.c ========================================================*/ -extern int Aig_ManCheck( Aig_Man_t * p ); -extern void Aig_ManCheckMarkA( Aig_Man_t * p ); -extern void Aig_ManCheckPhase( Aig_Man_t * p ); -/*=== aigDfs.c ==========================================================*/ -extern Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p ); -extern Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes ); -extern Vec_Ptr_t * Aig_ManDfsChoices( Aig_Man_t * p ); -extern Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p ); -extern int Aig_ManLevelNum( Aig_Man_t * p ); -extern int Aig_ManCountLevels( Aig_Man_t * p ); -extern int Aig_DagSize( Aig_Obj_t * pObj ); -extern int Aig_SupportSize( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ); -extern Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pObj, int nVars ); -extern Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ); -extern void Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ); -extern int Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ); -/*=== aigFanout.c ==========================================================*/ -extern void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ); -extern void Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ); -extern void Aig_ManFanoutStart( Aig_Man_t * p ); -extern void Aig_ManFanoutStop( Aig_Man_t * p ); -/*=== aigMan.c ==========================================================*/ -extern Aig_Man_t * Aig_ManStart( int nNodesMax ); -extern Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p ); -extern Aig_Obj_t * Aig_ManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ); -extern Aig_Man_t * Aig_ManDup( Aig_Man_t * p, int fOrdered ); -extern Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ); -extern void Aig_ManStop( Aig_Man_t * p ); -extern int Aig_ManCleanup( Aig_Man_t * p ); -extern void Aig_ManPrintStats( Aig_Man_t * p ); -/*=== aigMem.c ==========================================================*/ -extern void Aig_ManStartMemory( Aig_Man_t * p ); -extern void Aig_ManStopMemory( Aig_Man_t * p ); -/*=== aigMffc.c ==========================================================*/ -extern int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin ); -extern int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin ); -extern int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp ); -extern int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode ); -extern int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves ); -extern int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult ); -/*=== aigObj.c ==========================================================*/ -extern Aig_Obj_t * Aig_ObjCreatePi( Aig_Man_t * p ); -extern Aig_Obj_t * Aig_ObjCreatePo( Aig_Man_t * p, Aig_Obj_t * pDriver ); -extern Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ); -extern void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ); -extern void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop ); -extern void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew ); -extern void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fNodesOnly, int fUpdateLevel ); -/*=== aigOper.c =========================================================*/ -extern Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ); -extern Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ); -extern Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); -extern Aig_Obj_t * Aig_Latch( Aig_Man_t * p, Aig_Obj_t * pObj, int fInitOne ); -extern Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); -extern Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); -extern Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ); -extern Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ); -extern Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ); -extern Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 ); -extern Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ); -extern Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ); -extern Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ); -/*=== aigOrder.c =========================================================*/ -extern void Aig_ManOrderStart( Aig_Man_t * p ); -extern void Aig_ManOrderStop( Aig_Man_t * p ); -extern void Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId ); -extern void Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId ); -extern void Aig_ObjOrderAdvance( Aig_Man_t * p ); -/*=== aigPart.c =========================================================*/ -extern Vec_Ptr_t * Aig_ManSupports( Aig_Man_t * pMan ); -extern Vec_Ptr_t * Aig_ManPartitionSmart( Aig_Man_t * p, int nPartSizeLimit, int fVerbose, Vec_Ptr_t ** pvPartSupps ); -extern Vec_Ptr_t * Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize ); -extern Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize ); -/*=== aigRepr.c =========================================================*/ -extern void Aig_ManReprStart( Aig_Man_t * p, int nIdMax ); -extern void Aig_ManReprStop( Aig_Man_t * p ); -extern void Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ); -extern void Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * p ); -extern Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p, int fOrdered ); -extern Aig_Man_t * Aig_ManRehash( Aig_Man_t * p ); -extern void Aig_ManMarkValidChoices( Aig_Man_t * p ); -/*=== aigRet.c ========================================================*/ -extern Aig_Man_t * Rtm_ManRetime( Aig_Man_t * p, int fForward, int nStepsMax, int fVerbose ); -/*=== aigScl.c ==========================================================*/ -extern Aig_Man_t * Aig_ManRemap( Aig_Man_t * p, Vec_Ptr_t * vMap ); -extern int Aig_ManSeqCleanup( Aig_Man_t * p ); -extern int Aig_ManCountMergeRegs( Aig_Man_t * p ); -extern Aig_Man_t * Aig_ManReduceLaches( Aig_Man_t * p, int fVerbose ); -/*=== aigSeq.c ========================================================*/ -extern int Aig_ManSeqStrash( Aig_Man_t * p, int nLatches, int * pInits ); -/*=== aigShow.c ========================================================*/ -extern void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ); -/*=== aigTable.c ========================================================*/ -extern Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ); -extern Aig_Obj_t * Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 ); -extern void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern int Aig_TableCountEntries( Aig_Man_t * p ); -extern void Aig_TableProfile( Aig_Man_t * p ); -/*=== aigTiming.c ========================================================*/ -extern void Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern int Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj ); -extern void Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease ); -extern void Aig_ManStopReverseLevels( Aig_Man_t * p ); -extern void Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ); -extern void Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ); -extern void Aig_ManVerifyLevel( Aig_Man_t * p ); -extern void Aig_ManVerifyReverseLevel( Aig_Man_t * p ); -/*=== aigTruth.c ========================================================*/ -extern unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore ); -/*=== aigTsim.c ========================================================*/ -extern Aig_Man_t * Aig_ManConstReduce( Aig_Man_t * p, int fVerbose ); -/*=== aigUtil.c =========================================================*/ -extern unsigned Aig_PrimeCudd( unsigned p ); -extern void Aig_ManIncrementTravId( Aig_Man_t * p ); -extern int Aig_ManLevels( Aig_Man_t * p ); -extern void Aig_ManResetRefs( Aig_Man_t * p ); -extern void Aig_ManCleanMarkA( Aig_Man_t * p ); -extern void Aig_ManCleanMarkB( Aig_Man_t * p ); -extern void Aig_ManCleanData( Aig_Man_t * p ); -extern void Aig_ObjCleanData_rec( Aig_Obj_t * pObj ); -extern void Aig_ObjCollectMulti( Aig_Obj_t * pFunc, Vec_Ptr_t * vSuper ); -extern int Aig_ObjIsMuxType( Aig_Obj_t * pObj ); -extern int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ); -extern Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pObj, Aig_Obj_t ** ppObjT, Aig_Obj_t ** ppObjE ); -extern Aig_Obj_t * Aig_ObjReal_rec( Aig_Obj_t * pObj ); -extern void Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); -extern void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); -extern void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ); -extern void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ); -extern void Aig_ManDump( Aig_Man_t * p ); -extern void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName ); -extern void Aig_ManDumpVerilog( Aig_Man_t * p, char * pFileName ); -/*=== aigWin.c =========================================================*/ -extern void Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ); - -/*=== aigMem.c ===========================================================*/ -// fixed-size-block memory manager -extern Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax ); -extern void Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose ); -extern char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ); -extern void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ); -extern void Aig_MmFixedRestart( Aig_MmFixed_t * p ); -extern int Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p ); -extern int Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p ); -// flexible-size-block memory manager -extern Aig_MmFlex_t * Aig_MmFlexStart(); -extern void Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose ); -extern char * Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes ); -extern void Aig_MmFlexRestart( Aig_MmFlex_t * p ); -extern int Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p ); -// hierarchical memory manager -extern Aig_MmStep_t * Aig_MmStepStart( int nSteps ); -extern void Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose ); -extern char * Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes ); -extern void Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes ); -extern int Aig_MmStepReadMemUsage( Aig_MmStep_t * p ); - -/*=== aigTime.c ===========================================================*/ -extern Aig_TMan_t * Aig_TManStart( int nPis, int nPos ); -extern void Aig_TManStop( Aig_TMan_t * p ); -extern void Aig_TManCreateBox( Aig_TMan_t * p, int * pPis, int nPis, int * pPos, int nPos, float * pPiTimes, float * pPoTimes ); -extern void Aig_TManSetPiDelay( Aig_TMan_t * p, int iPi, float Delay ); -extern void Aig_TManSetPoDelay( Aig_TMan_t * p, int iPo, float Delay ); -extern void Aig_TManSetPiArrival( Aig_TMan_t * p, int iPi, float Delay ); -extern void Aig_TManSetPoRequired( Aig_TMan_t * p, int iPo, float Delay ); -extern void Aig_TManIncrementTravId( Aig_TMan_t * p ); -extern float Aig_TManGetPiArrival( Aig_TMan_t * p, int iPi ); -extern float Aig_TManGetPoRequired( Aig_TMan_t * p, int iPo ); - - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/aig/aigCheck.c b/src/aig/aig/aigCheck.c deleted file mode 100644 index 8c53e635..00000000 --- a/src/aig/aig/aigCheck.c +++ /dev/null @@ -1,163 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigCheck.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [AIG checking procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigCheck.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks the consistency of the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCheck( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObj2; - int i; - // check primary inputs - Aig_ManForEachPi( p, pObj, i ) - { - if ( Aig_ObjFanin0(pObj) || Aig_ObjFanin1(pObj) ) - { - printf( "Aig_ManCheck: The PI node \"%p\" has fanins.\n", pObj ); - return 0; - } - } - // check primary outputs - Aig_ManForEachPo( p, pObj, i ) - { - if ( !Aig_ObjFanin0(pObj) ) - { - printf( "Aig_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj ); - return 0; - } - if ( Aig_ObjFanin1(pObj) ) - { - printf( "Aig_ManCheck: The PO node \"%p\" has second fanin.\n", pObj ); - return 0; - } - } - // check internal nodes - Aig_ManForEachObj( p, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - if ( !Aig_ObjFanin0(pObj) || !Aig_ObjFanin1(pObj) ) - { - printf( "Aig_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj ); - return 0; - } - if ( Aig_ObjFanin0(pObj)->Id >= Aig_ObjFanin1(pObj)->Id ) - { - printf( "Aig_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj ); - return 0; - } - pObj2 = Aig_TableLookup( p, pObj ); - if ( pObj2 != pObj ) - { - printf( "Aig_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj ); - return 0; - } - } - // count the total number of nodes - if ( Aig_ManObjNum(p) != 1 + Aig_ManPiNum(p) + Aig_ManPoNum(p) + - Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) ) - { - printf( "Aig_ManCheck: The number of created nodes is wrong.\n" ); - printf( "C1 = %d. Pi = %d. Po = %d. Buf = %d. And = %d. Xor = %d. Lat = %d. Total = %d.\n", - 1, Aig_ManPiNum(p), Aig_ManPoNum(p), Aig_ManBufNum(p), Aig_ManAndNum(p), Aig_ManExorNum(p), Aig_ManLatchNum(p), - 1 + Aig_ManPiNum(p) + Aig_ManPoNum(p) + Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) ); - printf( "Created = %d. Deleted = %d. Existing = %d.\n", - p->nCreated, p->nDeleted, p->nCreated - p->nDeleted ); - return 0; - } - // count the number of nodes in the table - if ( Aig_TableCountEntries(p) != Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) ) - { - printf( "Aig_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); - printf( "Entries = %d. And = %d. Xor = %d. Lat = %d. Total = %d.\n", - Aig_TableCountEntries(p), Aig_ManAndNum(p), Aig_ManExorNum(p), Aig_ManLatchNum(p), - Aig_ManAndNum(p) + Aig_ManExorNum(p) + Aig_ManLatchNum(p) ); - - return 0; - } -// if ( !Aig_ManIsAcyclic(p) ) -// return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks if the markA is reset.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCheckMarkA( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - assert( pObj->fMarkA == 0 ); -} - -/**Function************************************************************* - - Synopsis [Checks the consistency of phase assignment.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCheckPhase( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - if ( Aig_ObjIsPi(pObj) ) - assert( (int)pObj->fPhase == 0 ); - else - assert( (int)pObj->fPhase == (Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) & Aig_ObjPhaseReal(Aig_ObjChild1(pObj))) ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigDfs.c b/src/aig/aig/aigDfs.c deleted file mode 100644 index e9821bdc..00000000 --- a/src/aig/aig/aigDfs.c +++ /dev/null @@ -1,700 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigDfs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [DFS traversal procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigDfs.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDfs_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( pObj == NULL ) - return; - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); - Aig_ManDfs_rec( p, Aig_ObjFanin0(pObj), vNodes ); - Aig_ManDfs_rec( p, Aig_ObjFanin1(pObj), vNodes ); - assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection - Aig_ObjSetTravIdCurrent(p, pObj); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - Aig_ManIncrementTravId( p ); - // mark constant and PIs - Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); - Aig_ManForEachPi( p, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // if there are latches, mark them - if ( Aig_ManLatchNum(p) > 0 ) - Aig_ManForEachObj( p, pObj, i ) - if ( Aig_ObjIsLatch(pObj) ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // go through the nodes - vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); - Aig_ManForEachObj( p, pObj, i ) - if ( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ) - Aig_ManDfs_rec( p, pObj, vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - assert( Aig_ManLatchNum(p) == 0 ); - Aig_ManIncrementTravId( p ); - // mark constant and PIs - Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); - Aig_ManForEachPi( p, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // go through the nodes - vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); - for ( i = 0; i < nNodes; i++ ) - Aig_ManDfs_rec( p, ppNodes[i], vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDfsChoices_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( pObj == NULL ) - return; - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - assert( Aig_ObjIsNode(pObj) ); - Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes ); - Aig_ManDfsChoices_rec( p, Aig_ObjFanin1(pObj), vNodes ); - Aig_ManDfsChoices_rec( p, p->pEquivs[pObj->Id], vNodes ); - assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection - Aig_ObjSetTravIdCurrent(p, pObj); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManDfsChoices( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - assert( p->pEquivs != NULL ); - Aig_ManIncrementTravId( p ); - // mark constant and PIs - Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); - Aig_ManForEachPi( p, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // go through the nodes - vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the reverse DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDfsReverse_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - Aig_Obj_t * pFanout; - int iFanout, i; - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); - Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) - Aig_ManDfsReverse_rec( p, pFanout, vNodes ); - assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection - Aig_ObjSetTravIdCurrent(p, pObj); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the reverse DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - Aig_ManIncrementTravId( p ); - // mark POs - Aig_ManForEachPo( p, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // if there are latches, mark them - if ( Aig_ManLatchNum(p) > 0 ) - Aig_ManForEachObj( p, pObj, i ) - if ( Aig_ObjIsLatch(pObj) ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // go through the nodes - vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); - Aig_ManForEachObj( p, pObj, i ) - if ( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ) - Aig_ManDfsReverse_rec( p, pObj, vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the max number of levels in the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManLevelNum( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, LevelsMax; - LevelsMax = 0; - Aig_ManForEachPo( p, pObj, i ) - LevelsMax = AIG_MAX( LevelsMax, (int)Aig_ObjFanin0(pObj)->Level ); - return LevelsMax; -} - -/**Function************************************************************* - - Synopsis [Computes the max number of levels in the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCountLevels( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i, LevelsMax, Level0, Level1; - // initialize the levels - Aig_ManConst1(p)->iData = 0; - Aig_ManForEachPi( p, pObj, i ) - pObj->iData = 0; - // compute levels in a DFS order - vNodes = Aig_ManDfs( p ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - Level0 = Aig_ObjFanin0(pObj)->iData; - Level1 = Aig_ObjFanin1(pObj)->iData; - pObj->iData = 1 + Aig_ObjIsExor(pObj) + AIG_MAX(Level0, Level1); - } - Vec_PtrFree( vNodes ); - // get levels of the POs - LevelsMax = 0; - Aig_ManForEachPo( p, pObj, i ) - LevelsMax = AIG_MAX( LevelsMax, Aig_ObjFanin0(pObj)->iData ); - return LevelsMax; -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ConeMark_rec( Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return; - Aig_ConeMark_rec( Aig_ObjFanin0(pObj) ); - Aig_ConeMark_rec( Aig_ObjFanin1(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ConeCleanAndMark_rec( Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return; - Aig_ConeCleanAndMark_rec( Aig_ObjFanin0(pObj) ); - Aig_ConeCleanAndMark_rec( Aig_ObjFanin1(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); - pObj->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ConeCountAndMark_rec( Aig_Obj_t * pObj ) -{ - int Counter; - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return 0; - Counter = 1 + Aig_ConeCountAndMark_rec( Aig_ObjFanin0(pObj) ) + - Aig_ConeCountAndMark_rec( Aig_ObjFanin1(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || !Aig_ObjIsMarkA(pObj) ) - return; - Aig_ConeUnmark_rec( Aig_ObjFanin0(pObj) ); - Aig_ConeUnmark_rec( Aig_ObjFanin1(pObj) ); - assert( Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjClearMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_DagSize( Aig_Obj_t * pObj ) -{ - int Counter; - Counter = Aig_ConeCountAndMark_rec( Aig_Regular(pObj) ); - Aig_ConeUnmark_rec( Aig_Regular(pObj) ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the support size of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_SupportSize_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int * pCounter ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p, pObj); - if ( Aig_ObjIsPi(pObj) ) - { - (*pCounter)++; - return; - } - assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); - Aig_SupportSize_rec( p, Aig_ObjFanin0(pObj), pCounter ); - if ( Aig_ObjFanin1(pObj) ) - Aig_SupportSize_rec( p, Aig_ObjFanin1(pObj), pCounter ); -} - -/**Function************************************************************* - - Synopsis [Counts the support size of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_SupportSize( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - int Counter = 0; - assert( !Aig_IsComplement(pObj) ); - assert( !Aig_ObjIsPo(pObj) ); - Aig_ManIncrementTravId( p ); - Aig_SupportSize_rec( p, pObj, &Counter ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Transfers the AIG from one manager into another.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_Transfer_rec( Aig_Man_t * pDest, Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) - return; - Aig_Transfer_rec( pDest, Aig_ObjFanin0(pObj) ); - Aig_Transfer_rec( pDest, Aig_ObjFanin1(pObj) ); - pObj->pData = Aig_And( pDest, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Transfers the AIG from one manager into another.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pRoot, int nVars ) -{ - Aig_Obj_t * pObj; - int i; - // solve simple cases - if ( pSour == pDest ) - return pRoot; - if ( Aig_ObjIsConst1( Aig_Regular(pRoot) ) ) - return Aig_NotCond( Aig_ManConst1(pDest), Aig_IsComplement(pRoot) ); - // set the PI mapping - Aig_ManForEachPi( pSour, pObj, i ) - { - if ( i == nVars ) - break; - pObj->pData = Aig_IthVar(pDest, i); - } - // transfer and set markings - Aig_Transfer_rec( pDest, Aig_Regular(pRoot) ); - // clear the markings - Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); - return Aig_NotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); -} - -/**Function************************************************************* - - Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_Compose_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFunc, Aig_Obj_t * pVar ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsMarkA(pObj) ) - return; - if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsPi(pObj) ) - { - pObj->pData = pObj == pVar ? pFunc : pObj; - return; - } - Aig_Compose_rec( p, Aig_ObjFanin0(pObj), pFunc, pVar ); - Aig_Compose_rec( p, Aig_ObjFanin1(pObj), pFunc, pVar ); - pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - assert( !Aig_ObjIsMarkA(pObj) ); // loop detection - Aig_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ) -{ - // quit if the PI variable is not defined - if ( iVar >= Aig_ManPiNum(p) ) - { - printf( "Aig_Compose(): The PI variable %d is not defined.\n", iVar ); - return NULL; - } - // recursively perform composition - Aig_Compose_rec( p, Aig_Regular(pRoot), pFunc, Aig_ManPi(p, iVar) ); - // clear the markings - Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); - return Aig_NotCond( Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); -} - -/**Function************************************************************* - - Synopsis [Computes the internal nodes of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjCollectCut_rec( Aig_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ -// Aig_Obj_t * pFan0 = Aig_ObjFanin0(pNode); -// Aig_Obj_t * pFan1 = Aig_ObjFanin1(pNode); - if ( pNode->fMarkA ) - return; - pNode->fMarkA = 1; - assert( Aig_ObjIsNode(pNode) ); - Aig_ObjCollectCut_rec( Aig_ObjFanin0(pNode), vNodes ); - Aig_ObjCollectCut_rec( Aig_ObjFanin1(pNode), vNodes ); - Vec_PtrPush( vNodes, pNode ); -//printf( "added %d ", pNode->Id ); -} - -/**Function************************************************************* - - Synopsis [Computes the internal nodes of the cut.] - - Description [Does not include the leaves of the cut.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ) -{ - Aig_Obj_t * pObj; - int i; - // collect and mark the leaves - Vec_PtrClear( vNodes ); - Vec_PtrForEachEntry( vLeaves, pObj, i ) - { - assert( pObj->fMarkA == 0 ); - pObj->fMarkA = 1; -// printf( "%d " , pObj->Id ); - } -//printf( "\n" ); - // collect and mark the nodes - Aig_ObjCollectCut_rec( pRoot, vNodes ); - // clean the nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->fMarkA = 0; - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->fMarkA = 0; -} - - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjCollectSuper_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - int RetValue1, RetValue2, i; - // check if the node is visited - if ( Aig_Regular(pObj)->fMarkA ) - { - // check if the node occurs in the same polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == pObj ) - return 1; - // check if the node is present in the opposite polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == Aig_Not(pObj) ) - return -1; - assert( 0 ); - return 0; - } - // if the new node is complemented or a PI, another gate begins - if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1) ) - { - Vec_PtrPush( vSuper, pObj ); - Aig_Regular(pObj)->fMarkA = 1; - return 0; - } - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - // go through the branches - RetValue1 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper ); - RetValue2 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - // return 1 if at least one branch has a duplicate - return RetValue1 || RetValue2; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - int RetValue, i; - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - // collect the nodes in the implication supergate - Vec_PtrClear( vSuper ); - RetValue = Aig_ObjCollectSuper_rec( pObj, pObj, vSuper ); - assert( Vec_PtrSize(vSuper) > 1 ); - // unmark the visited nodes - Vec_PtrForEachEntry( vSuper, pObj, i ) - Aig_Regular(pObj)->fMarkA = 0; - // if we found the node and its complement in the same implication supergate, - // return empty set of nodes (meaning that we should use constant-0 node) - if ( RetValue == -1 ) - vSuper->nSize = 0; - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigFanout.c b/src/aig/aig/aigFanout.c deleted file mode 100644 index d0beb128..00000000 --- a/src/aig/aig/aigFanout.c +++ /dev/null @@ -1,189 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigFanout.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Fanout manipulation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigFanout.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -// 0: first iFan -// 1: prev iFan0 -// 2: prev iFan1 -// 3: next iFan0 -// 4: next iFan1 - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Aig_FanoutCreate( int FanId, int Num ) { assert( Num < 2 ); return (FanId << 1) | Num; } -static inline int * Aig_FanoutObj( int * pData, int ObjId ) { return pData + 5*ObjId; } -static inline int * Aig_FanoutPrev( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 1 + (iFan & 1); } -static inline int * Aig_FanoutNext( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 3 + (iFan & 1); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Create fanout for all objects in the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManFanoutStart( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - assert( Aig_ManBufNum(p) == 0 ); - // allocate fanout datastructure - assert( p->pFanData == NULL ); - p->nFansAlloc = 2 * Aig_ManObjNumMax(p); - if ( p->nFansAlloc < (1<<12) ) - p->nFansAlloc = (1<<12); - p->pFanData = ALLOC( int, 5 * p->nFansAlloc ); - memset( p->pFanData, 0, sizeof(int) * 5 * p->nFansAlloc ); - // add fanouts for all objects - Aig_ManForEachObj( p, pObj, i ) - { - if ( Aig_ObjChild0(pObj) ) - Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); - if ( Aig_ObjChild1(pObj) ) - Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Deletes fanout for all objects in the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManFanoutStop( Aig_Man_t * p ) -{ - assert( p->pFanData != NULL ); - FREE( p->pFanData ); - p->nFansAlloc = 0; -} - -/**Function************************************************************* - - Synopsis [Adds fanout (pFanout) of node (pObj).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) -{ - int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; - assert( p->pFanData ); - assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) ); - assert( pFanout->Id > 0 ); - if ( pObj->Id >= p->nFansAlloc || pFanout->Id >= p->nFansAlloc ) - { - int nFansAlloc = 2 * AIG_MAX( pObj->Id, pFanout->Id ); - p->pFanData = REALLOC( int, p->pFanData, 5 * nFansAlloc ); - memset( p->pFanData + 5 * p->nFansAlloc, 0, sizeof(int) * 5 * (nFansAlloc - p->nFansAlloc) ); - p->nFansAlloc = nFansAlloc; - } - assert( pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc ); - iFan = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) ); - pPrevC = Aig_FanoutPrev( p->pFanData, iFan ); - pNextC = Aig_FanoutNext( p->pFanData, iFan ); - pFirst = Aig_FanoutObj( p->pFanData, pObj->Id ); - if ( *pFirst == 0 ) - { - *pFirst = iFan; - *pPrevC = iFan; - *pNextC = iFan; - } - else - { - pPrev = Aig_FanoutPrev( p->pFanData, *pFirst ); - pNext = Aig_FanoutNext( p->pFanData, *pPrev ); - assert( *pNext == *pFirst ); - *pPrevC = *pPrev; - *pNextC = *pFirst; - *pPrev = iFan; - *pNext = iFan; - } -} - -/**Function************************************************************* - - Synopsis [Removes fanout (pFanout) of node (pObj).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) -{ - int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; - assert( p->pFanData && pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc ); - assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) ); - assert( pFanout->Id > 0 ); - iFan = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) ); - pPrevC = Aig_FanoutPrev( p->pFanData, iFan ); - pNextC = Aig_FanoutNext( p->pFanData, iFan ); - pPrev = Aig_FanoutPrev( p->pFanData, *pNextC ); - pNext = Aig_FanoutNext( p->pFanData, *pPrevC ); - assert( *pPrev == iFan ); - assert( *pNext == iFan ); - pFirst = Aig_FanoutObj( p->pFanData, pObj->Id ); - assert( *pFirst > 0 ); - if ( *pFirst == iFan ) - { - if ( *pNextC == iFan ) - { - *pFirst = 0; - *pPrev = 0; - *pNext = 0; - *pPrevC = 0; - *pNextC = 0; - return; - } - *pFirst = *pNextC; - } - *pPrev = *pPrevC; - *pNext = *pNextC; - *pPrevC = 0; - *pNextC = 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigMan.c b/src/aig/aig/aigMan.c deleted file mode 100644 index d2714380..00000000 --- a/src/aig/aig/aigMan.c +++ /dev/null @@ -1,324 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [AIG manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the AIG manager.] - - Description [The argument of this procedure is a soft limit on the - the number of nodes, or 0 if the limit is unknown.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManStart( int nNodesMax ) -{ - Aig_Man_t * p; - if ( nNodesMax <= 0 ) - nNodesMax = 10007; - // start the manager - p = ALLOC( Aig_Man_t, 1 ); - memset( p, 0, sizeof(Aig_Man_t) ); - // perform initializations - p->nTravIds = 1; - p->fCatchExor = 0; - // allocate arrays for nodes - p->vPis = Vec_PtrAlloc( 100 ); - p->vPos = Vec_PtrAlloc( 100 ); - p->vObjs = Vec_PtrAlloc( 1000 ); - p->vBufs = Vec_PtrAlloc( 100 ); - // prepare the internal memory manager - p->pMemObjs = Aig_MmFixedStart( sizeof(Aig_Obj_t), nNodesMax ); - // create the constant node - p->pConst1 = Aig_ManFetchMemory( p ); - p->pConst1->Type = AIG_OBJ_CONST1; - p->pConst1->fPhase = 1; - p->nObjs[AIG_OBJ_CONST1]++; - // start the table - p->nTableSize = Aig_PrimeCudd( nNodesMax ); - p->pTable = ALLOC( Aig_Obj_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj; - int i; - // create the new manager - pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - // create the PIs - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePi(pNew); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Duplicates the AIG manager recursively.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( pObj->pData ) - return pObj->pData; - Aig_ManDup_rec( pNew, p, Aig_ObjFanin0(pObj) ); - if ( Aig_ObjIsBuf(pObj) ) - return pObj->pData = Aig_ObjChild0Copy(pObj); - Aig_ManDup_rec( pNew, p, Aig_ObjFanin1(pObj) ); - return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Duplicates the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManDup( Aig_Man_t * p, int fOrdered ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj; - int i; - // create the new manager - pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->nRegs = p->nRegs; - pNew->nAsserts = p->nAsserts; - if ( p->vFlopNums ) - pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); - // create the PIs - Aig_ManCleanData( p ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePi(pNew); - // duplicate internal nodes - if ( fOrdered ) - { - Aig_ManForEachObj( p, pObj, i ) - if ( Aig_ObjIsBuf(pObj) ) - pObj->pData = Aig_ObjChild0Copy(pObj); - else if ( Aig_ObjIsNode(pObj) ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - } - else - { - Aig_ManForEachObj( p, pObj, i ) - if ( !Aig_ObjIsPo(pObj) ) - { - Aig_ManDup_rec( pNew, p, pObj ); - assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level ); - } - } - // add the POs - Aig_ManForEachPo( p, pObj, i ) - Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); - // check the resulting network - if ( !Aig_ManCheck(pNew) ) - printf( "Aig_ManDup(): The check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Extracts the miter composed of XOR of the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj; - int i; - // create the new manager - pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - // create the PIs - Aig_ManCleanData( p ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePi(pNew); - // dump the nodes - Aig_ManDup_rec( pNew, p, pNode1 ); - Aig_ManDup_rec( pNew, p, pNode2 ); - // construct the EXOR - pObj = Aig_Exor( pNew, pNode1->pData, pNode2->pData ); - pObj = Aig_NotCond( pObj, Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ); - // add the PO - Aig_ObjCreatePo( pNew, pObj ); - // check the resulting network - if ( !Aig_ManCheck(pNew) ) - printf( "Aig_ManDup(): The check has failed.\n" ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManStop( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - if ( p->vMapped ) - Vec_PtrFree( p->vMapped ); - // print time - if ( p->time1 ) { PRT( "time1", p->time1 ); } - if ( p->time2 ) { PRT( "time2", p->time2 ); } - // delete timing - if ( p->pManTime ) - Aig_TManStop( p->pManTime ); - // delete fanout - if ( p->pFanData ) - Aig_ManFanoutStop( p ); - // make sure the nodes have clean marks - Aig_ManForEachObj( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); -// Aig_TableProfile( p ); - Aig_MmFixedStop( p->pMemObjs, 0 ); - if ( p->vPis ) Vec_PtrFree( p->vPis ); - if ( p->vPos ) Vec_PtrFree( p->vPos ); - if ( p->vObjs ) Vec_PtrFree( p->vObjs ); - if ( p->vBufs ) Vec_PtrFree( p->vBufs ); - if ( p->vLevelR ) Vec_IntFree( p->vLevelR ); - if ( p->vLevels ) Vec_VecFree( p->vLevels ); - if ( p->vFlopNums) Vec_IntFree( p->vFlopNums ); - FREE( p->pName ); - FREE( p->pObjCopies ); - FREE( p->pReprs ); - FREE( p->pEquivs ); - free( p->pTable ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of dangling nodes removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCleanup( Aig_Man_t * p ) -{ - Vec_Ptr_t * vObjs; - Aig_Obj_t * pNode; - int i, nNodesOld; - nNodesOld = Aig_ManNodeNum(p); - // collect roots of dangling nodes - vObjs = Vec_PtrAlloc( 100 ); - Aig_ManForEachObj( p, pNode, i ) - if ( Aig_ObjIsNode(pNode) && Aig_ObjRefs(pNode) == 0 ) - Vec_PtrPush( vObjs, pNode ); - // recursively remove dangling nodes - Vec_PtrForEachEntry( vObjs, pNode, i ) - Aig_ObjDelete_rec( p, pNode, 1 ); - Vec_PtrFree( vObjs ); - return nNodesOld - Aig_ManNodeNum(p); -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManPrintStats( Aig_Man_t * p ) -{ - printf( "PI/PO/Lat = %5d/%5d/%5d ", Aig_ManPiNum(p), Aig_ManPoNum(p), Aig_ManLatchNum(p) ); - printf( "A = %7d. ", Aig_ManAndNum(p) ); - if ( Aig_ManExorNum(p) ) - printf( "X = %5d. ", Aig_ManExorNum(p) ); -// if ( Aig_ManBufNum(p) ) - printf( "B = %5d. ", Aig_ManBufNum(p) ); -// printf( "Cre = %6d. ", p->nCreated ); -// printf( "Del = %6d. ", p->nDeleted ); -// printf( "Lev = %3d. ", Aig_ManCountLevels(p) ); - printf( "Max = %7d. ", Aig_ManObjNumMax(p) ); - printf( "Lev = %3d. ", Aig_ManLevels(p) ); - if ( Aig_ManRegNum(p) ) - printf( "Lat = %5d. ", Aig_ManRegNum(p) ); - printf( "\n" ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigMem.c b/src/aig/aig/aigMem.c deleted file mode 100644 index dab90777..00000000 --- a/src/aig/aig/aigMem.c +++ /dev/null @@ -1,598 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigMem.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Memory managers.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigMem.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Aig_MmFixed_t_ -{ - // information about individual entries - int nEntrySize; // the size of one entry - int nEntriesAlloc; // the total number of entries allocated - int nEntriesUsed; // the number of entries in use - int nEntriesMax; // the max number of entries in use - char * pEntriesFree; // the linked list of free entries - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -struct Aig_MmFlex_t_ -{ - // information about individual entries - int nEntriesUsed; // the number of entries allocated - char * pCurrent; // the current pointer to free memory - char * pEnd; // the first entry outside the free memory - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -struct Aig_MmStep_t_ -{ - int nMems; // the number of fixed memory managers employed - Aig_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc - int nMapSize; // the size of the memory array - Aig_MmFixed_t ** pMap; // maps the number of bytes into its memory manager -}; - -#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#define REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates memory pieces of fixed size.] - - Description [The size of the chunk is computed as the minimum of - 1024 entries and 64K. Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax ) -{ - Aig_MmFixed_t * p; - - p = ALLOC( Aig_MmFixed_t, 1 ); - memset( p, 0, sizeof(Aig_MmFixed_t) ); - - p->nEntrySize = nEntrySize; - p->nEntriesAlloc = 0; - p->nEntriesUsed = 0; - p->pEntriesFree = NULL; - - p->nChunkSize = nEntriesMax / 8; - if ( p->nChunkSize < 8 ) - p->nChunkSize = 8; - - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", - p->nEntrySize, p->nChunkSize, p->nChunks ); - printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", - p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ) -{ - char * pTemp; - int i; - - // check if there are still free entries - if ( p->nEntriesUsed == p->nEntriesAlloc ) - { // need to allocate more entries - assert( p->pEntriesFree == NULL ); - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); - p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; - // transform these entries into a linked list - pTemp = p->pEntriesFree; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pEntriesFree; - // add to the number of entries allocated - p->nEntriesAlloc += p->nChunkSize; - } - // incrememt the counter of used entries - p->nEntriesUsed++; - if ( p->nEntriesMax < p->nEntriesUsed ) - p->nEntriesMax = p->nEntriesUsed; - // return the first entry in the free entry list - pTemp = p->pEntriesFree; - p->pEntriesFree = *((char **)pTemp); - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ) -{ - // decrement the counter of used entries - p->nEntriesUsed--; - // add the entry to the linked list of free entries - *((char **)pEntry) = p->pEntriesFree; - p->pEntriesFree = pEntry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Relocates all the memory except the first chunk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_MmFixedRestart( Aig_MmFixed_t * p ) -{ - int i; - char * pTemp; - if ( p->nChunks == 0 ) - return; - // deallocate all chunks except the first one - for ( i = 1; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - p->nChunks = 1; - // transform these entries into a linked list - pTemp = p->pChunks[0]; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // set the free entry list - p->pEntriesFree = p->pChunks[0]; - // set the correct statistics - p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; - p->nMemoryUsed = 0; - p->nEntriesAlloc = p->nChunkSize; - p->nEntriesUsed = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p ) -{ - return p->nMemoryAlloc; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p ) -{ - return p->nEntriesMax; -} - - - -/**Function************************************************************* - - Synopsis [Allocates entries of flexible size.] - - Description [Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_MmFlex_t * Aig_MmFlexStart() -{ - Aig_MmFlex_t * p; - - p = ALLOC( Aig_MmFlex_t, 1 ); - memset( p, 0, sizeof(Aig_MmFlex_t) ); - - p->nEntriesUsed = 0; - p->pCurrent = NULL; - p->pEnd = NULL; - - p->nChunkSize = (1 << 18); - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", - p->nChunkSize, p->nChunks ); - printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", - p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes ) -{ - char * pTemp; - // check if there are still free entries - if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) - { // need to allocate more entries - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - if ( nBytes > p->nChunkSize ) - { - // resize the chunk size if more memory is requested than it can give - // (ideally, this should never happen) - p->nChunkSize = 2 * nBytes; - } - p->pCurrent = ALLOC( char, p->nChunkSize ); - p->pEnd = p->pCurrent + p->nChunkSize; - p->nMemoryAlloc += p->nChunkSize; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pCurrent; - } - assert( p->pCurrent + nBytes <= p->pEnd ); - // increment the counter of used entries - p->nEntriesUsed++; - // keep track of the memory used - p->nMemoryUsed += nBytes; - // return the next entry - pTemp = p->pCurrent; - p->pCurrent += nBytes; - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Relocates all the memory except the first chunk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_MmFlexRestart( Aig_MmFlex_t * p ) -{ - int i; - if ( p->nChunks == 0 ) - return; - // deallocate all chunks except the first one - for ( i = 1; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - p->nChunks = 1; - p->nMemoryAlloc = p->nChunkSize; - // transform these entries into a linked list - p->pCurrent = p->pChunks[0]; - p->pEnd = p->pCurrent + p->nChunkSize; - p->nEntriesUsed = 0; - p->nMemoryUsed = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p ) -{ - return p->nMemoryUsed; -} - - - - - -/**Function************************************************************* - - Synopsis [Starts the hierarchical memory manager.] - - Description [This manager can allocate entries of any size. - Iternally they are mapped into the entries with the number of bytes - equal to the power of 2. The smallest entry size is 8 bytes. The - next one is 16 bytes etc. So, if the user requests 6 bytes, he gets - 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. - The input parameters "nSteps" says how many fixed memory managers - are employed internally. Calling this procedure with nSteps equal - to 10 results in 10 hierarchically arranged internal memory managers, - which can allocate up to 4096 (1Kb) entries. Requests for larger - entries are handed over to malloc() and then free()ed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_MmStep_t * Aig_MmStepStart( int nSteps ) -{ - Aig_MmStep_t * p; - int i, k; - p = ALLOC( Aig_MmStep_t, 1 ); - memset( p, 0, sizeof(Aig_MmStep_t) ); - p->nMems = nSteps; - // start the fixed memory managers - p->pMems = ALLOC( Aig_MmFixed_t *, p->nMems ); - for ( i = 0; i < p->nMems; i++ ) - p->pMems[i] = Aig_MmFixedStart( (8<nMapSize = (4<nMems); - p->pMap = ALLOC( Aig_MmFixed_t *, p->nMapSize+1 ); - p->pMap[0] = NULL; - for ( k = 1; k <= 4; k++ ) - p->pMap[k] = p->pMems[0]; - for ( i = 0; i < p->nMems; i++ ) - for ( k = (4<pMap[k] = p->pMems[i]; -//for ( i = 1; i < 100; i ++ ) -//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose ) -{ - int i; - for ( i = 0; i < p->nMems; i++ ) - Aig_MmFixedStop( p->pMems[i], fVerbose ); -// if ( p->pLargeChunks ) -// { -// for ( i = 0; i < p->nLargeChunks; i++ ) -// free( p->pLargeChunks[i] ); -// free( p->pLargeChunks ); -// } - free( p->pMems ); - free( p->pMap ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Creates the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes ) -{ - if ( nBytes == 0 ) - return NULL; - if ( nBytes > p->nMapSize ) - { -// printf( "Allocating %d bytes.\n", nBytes ); -/* - if ( p->nLargeChunks == p->nLargeChunksAlloc ) - { - if ( p->nLargeChunksAlloc == 0 ) - p->nLargeChunksAlloc = 5; - p->nLargeChunksAlloc *= 2; - p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); - } - p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes ); - return p->pLargeChunks[ p->nLargeChunks - 1 ]; -*/ - return ALLOC( char, nBytes ); - } - return Aig_MmFixedEntryFetch( p->pMap[nBytes] ); -} - - -/**Function************************************************************* - - Synopsis [Recycles the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes ) -{ - if ( nBytes == 0 ) - return; - if ( nBytes > p->nMapSize ) - { - free( pEntry ); - return; - } - Aig_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_MmStepReadMemUsage( Aig_MmStep_t * p ) -{ - int i, nMemTotal = 0; - for ( i = 0; i < p->nMems; i++ ) - nMemTotal += p->pMems[i]->nMemoryAlloc; - return nMemTotal; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/aig/aig/aigMffc.c b/src/aig/aig/aigMffc.c deleted file mode 100644 index 47ce896d..00000000 --- a/src/aig/aig/aigMffc.c +++ /dev/null @@ -1,297 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigMffc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Computation of MFFCs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigMffc.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Dereferences the node's MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin ) -{ - Aig_Obj_t * pFanin; - int Counter = 0; - if ( Aig_ObjIsPi(pNode) ) - return 0; - // consider the first fanin - pFanin = Aig_ObjFanin0(pNode); - assert( pFanin->nRefs > 0 ); - if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) - Counter += Aig_NodeDeref_rec( pFanin, LevelMin ); - // skip the buffer - if ( Aig_ObjIsBuf(pNode) ) - return Counter; - assert( Aig_ObjIsNode(pNode) ); - // consider the second fanin - pFanin = Aig_ObjFanin1(pNode); - assert( pFanin->nRefs > 0 ); - if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) - Counter += Aig_NodeDeref_rec( pFanin, LevelMin ); - return Counter + 1; -} - -/**Function************************************************************* - - Synopsis [References the node's MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin ) -{ - Aig_Obj_t * pFanin; - int Counter = 0; - if ( Aig_ObjIsPi(pNode) ) - return 0; - // consider the first fanin - pFanin = Aig_ObjFanin0(pNode); - if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) - Counter += Aig_NodeRef_rec( pFanin, LevelMin ); - // skip the buffer - if ( Aig_ObjIsBuf(pNode) ) - return Counter; - assert( Aig_ObjIsNode(pNode) ); - // consider the second fanin - pFanin = Aig_ObjFanin1(pNode); - if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) - Counter += Aig_NodeRef_rec( pFanin, LevelMin ); - return Counter + 1; -} - -/**Function************************************************************* - - Synopsis [References the node's MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeRefLabel_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin ) -{ - Aig_Obj_t * pFanin; - int Counter = 0; - if ( Aig_ObjIsPi(pNode) ) - return 0; - Aig_ObjSetTravIdCurrent( p, pNode ); - // consider the first fanin - pFanin = Aig_ObjFanin0(pNode); - if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) - Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin ); - if ( Aig_ObjIsBuf(pNode) ) - return Counter; - assert( Aig_ObjIsNode(pNode) ); - // consider the second fanin - pFanin = Aig_ObjFanin1(pNode); - if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) - Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin ); - return Counter + 1; -} - -/**Function************************************************************* - - Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_NodeMffsSupp_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin, Vec_Ptr_t * vSupp, int fTopmost, Aig_Obj_t * pObjSkip ) -{ - // skip visited nodes - if ( Aig_ObjIsTravIdCurrent(p, pNode) ) - return; - Aig_ObjSetTravIdCurrent(p, pNode); - // add to the new support nodes - if ( !fTopmost && pNode != pObjSkip && (Aig_ObjIsPi(pNode) || pNode->nRefs > 0 || pNode->Level <= LevelMin) ) - { - if ( vSupp ) Vec_PtrPush( vSupp, pNode ); - return; - } - assert( Aig_ObjIsNode(pNode) ); - // recur on the children - Aig_NodeMffsSupp_rec( p, Aig_ObjFanin0(pNode), LevelMin, vSupp, 0, pObjSkip ); - Aig_NodeMffsSupp_rec( p, Aig_ObjFanin1(pNode), LevelMin, vSupp, 0, pObjSkip ); -} - -/**Function************************************************************* - - Synopsis [Collects the support of depth-limited MFFC.] - - Description [Returns the number of internal nodes in the MFFC.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeMffsSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp ) -{ - int ConeSize1, ConeSize2; - assert( !Aig_IsComplement(pNode) ); - assert( Aig_ObjIsNode(pNode) ); - if ( vSupp ) Vec_PtrClear( vSupp ); - Aig_ManIncrementTravId( p ); - ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin ); - Aig_NodeMffsSupp_rec( p, pNode, LevelMin, vSupp, 1, NULL ); - ConeSize2 = Aig_NodeRef_rec( pNode, LevelMin ); - assert( ConeSize1 == ConeSize2 ); - assert( ConeSize1 > 0 ); - return ConeSize1; -} - -/**Function************************************************************* - - Synopsis [Labels the nodes in the MFFC.] - - Description [Returns the number of internal nodes in the MFFC.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeMffsLabel( Aig_Man_t * p, Aig_Obj_t * pNode ) -{ - int ConeSize1, ConeSize2; - assert( !Aig_IsComplement(pNode) ); - assert( Aig_ObjIsNode(pNode) ); - Aig_ManIncrementTravId( p ); - ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); - ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); - assert( ConeSize1 == ConeSize2 ); - assert( ConeSize1 > 0 ); - return ConeSize1; -} - -/**Function************************************************************* - - Synopsis [Labels the nodes in the MFFC.] - - Description [Returns the number of internal nodes in the MFFC.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves ) -{ - Aig_Obj_t * pObj; - int i, ConeSize1, ConeSize2; - assert( !Aig_IsComplement(pNode) ); - assert( Aig_ObjIsNode(pNode) ); - Aig_ManIncrementTravId( p ); - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->nRefs++; - ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); - ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->nRefs--; - assert( ConeSize1 == ConeSize2 ); - assert( ConeSize1 > 0 ); - return ConeSize1; -} - -/**Function************************************************************* - - Synopsis [Expands the cut by adding the most closely related node.] - - Description [Returns 1 if the cut exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeMffsExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult ) -{ - Aig_Obj_t * pObj, * pLeafBest; - int i, LevelMax, ConeSize1, ConeSize2, ConeCur1, ConeCur2, ConeBest; - // dereference the current cut - LevelMax = 0; - Vec_PtrForEachEntry( vLeaves, pObj, i ) - LevelMax = AIG_MAX( LevelMax, (int)pObj->Level ); - if ( LevelMax == 0 ) - return 0; - // dereference the cut - ConeSize1 = Aig_NodeDeref_rec( pNode, 0 ); - // try expanding each node in the boundary - ConeBest = AIG_INFINITY; - pLeafBest = NULL; - Vec_PtrForEachEntry( vLeaves, pObj, i ) - { - if ( (int)pObj->Level != LevelMax ) - continue; - ConeCur1 = Aig_NodeDeref_rec( pObj, 0 ); - if ( ConeBest > ConeCur1 ) - { - ConeBest = ConeCur1; - pLeafBest = pObj; - } - ConeCur2 = Aig_NodeRef_rec( pObj, 0 ); - assert( ConeCur1 == ConeCur2 ); - } - assert( pLeafBest != NULL ); - assert( Aig_ObjIsNode(pLeafBest) ); - // deref the best leaf - ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0 ); - // collect the cut nodes - Vec_PtrClear( vResult ); - Aig_ManIncrementTravId( p ); - Aig_NodeMffsSupp_rec( p, pNode, 0, vResult, 1, pLeafBest ); - // ref the nodes - ConeCur2 = Aig_NodeRef_rec( pLeafBest, 0 ); - assert( ConeCur1 == ConeCur2 ); - // ref the original node - ConeSize2 = Aig_NodeRef_rec( pNode, 0 ); - assert( ConeSize1 == ConeSize2 ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigObj.c b/src/aig/aig/aigObj.c deleted file mode 100644 index 34c07dce..00000000 --- a/src/aig/aig/aigObj.c +++ /dev/null @@ -1,416 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigObj.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Adding/removing objects.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigObj.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates primary input.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjCreatePi( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - pObj = Aig_ManFetchMemory( p ); - pObj->Type = AIG_OBJ_PI; - Vec_PtrPush( p->vPis, pObj ); - p->nObjs[AIG_OBJ_PI]++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Creates primary output with the given driver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjCreatePo( Aig_Man_t * p, Aig_Obj_t * pDriver ) -{ - Aig_Obj_t * pObj; - pObj = Aig_ManFetchMemory( p ); - pObj->Type = AIG_OBJ_PO; - Vec_PtrPush( p->vPos, pObj ); - Aig_ObjConnect( p, pObj, pDriver, NULL ); - p->nObjs[AIG_OBJ_PO]++; - return pObj; -} - - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ) -{ - Aig_Obj_t * pObj; - assert( !Aig_IsComplement(pGhost) ); - assert( Aig_ObjIsHash(pGhost) ); - assert( pGhost == &p->Ghost ); - // get memory for the new object - pObj = Aig_ManFetchMemory( p ); - pObj->Type = pGhost->Type; - // add connections - Aig_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); - // update node counters of the manager - p->nObjs[Aig_ObjType(pObj)]++; - assert( pObj->pData == NULL ); - return pObj; -} - -/**Function************************************************************* - - Synopsis [Connect the object to the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ) -{ - assert( !Aig_IsComplement(pObj) ); - assert( !Aig_ObjIsPi(pObj) ); - // add the first fanin - pObj->pFanin0 = pFan0; - pObj->pFanin1 = pFan1; - // increment references of the fanins and add their fanouts - if ( pFan0 != NULL ) - { - assert( Aig_ObjFanin0(pObj)->Type > 0 ); - Aig_ObjRef( Aig_ObjFanin0(pObj) ); - if ( p->pFanData ) - Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); - } - if ( pFan1 != NULL ) - { - assert( Aig_ObjFanin1(pObj)->Type > 0 ); - Aig_ObjRef( Aig_ObjFanin1(pObj) ); - if ( p->pFanData ) - Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj ); - } - // set level and phase - pObj->Level = Aig_ObjLevelNew( pObj ); - pObj->fPhase = Aig_ObjPhaseReal(pFan0) & Aig_ObjPhaseReal(pFan1); - // add the node to the structural hash table - if ( Aig_ObjIsHash(pObj) ) - Aig_TableInsert( p, pObj ); - // add the node to the dynamically updated topological order - if ( p->pOrderData && Aig_ObjIsNode(pObj) ) - Aig_ObjOrderInsert( p, pObj->Id ); -} - -/**Function************************************************************* - - Synopsis [Disconnects the object from the fanins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - // remove connections - if ( pObj->pFanin0 != NULL ) - { - if ( p->pFanData ) - Aig_ObjRemoveFanout( p, Aig_ObjFanin0(pObj), pObj ); - Aig_ObjDeref(Aig_ObjFanin0(pObj)); - } - if ( pObj->pFanin1 != NULL ) - { - if ( p->pFanData ) - Aig_ObjRemoveFanout( p, Aig_ObjFanin1(pObj), pObj ); - Aig_ObjDeref(Aig_ObjFanin1(pObj)); - } - // remove the node from the structural hash table - if ( Aig_ObjIsHash(pObj) ) - Aig_TableDelete( p, pObj ); - // add the first fanin - pObj->pFanin0 = NULL; - pObj->pFanin1 = NULL; - // remove the node from the dynamically updated topological order - if ( p->pOrderData && Aig_ObjIsNode(pObj) ) - Aig_ObjOrderRemove( p, pObj->Id ); -} - -/**Function************************************************************* - - Synopsis [Deletes the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - assert( !Aig_ObjIsTerm(pObj) ); - assert( Aig_ObjRefs(pObj) == 0 ); - if ( p->pFanData && Aig_ObjIsBuf(pObj) ) - Vec_PtrRemove( p->vBufs, pObj ); - p->nObjs[pObj->Type]--; - Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); - Aig_ManRecycleMemory( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Deletes the MFFC of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop ) -{ - Aig_Obj_t * pFanin0, * pFanin1; - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsPi(pObj) ) - return; - assert( !Aig_ObjIsPo(pObj) ); - pFanin0 = Aig_ObjFanin0(pObj); - pFanin1 = Aig_ObjFanin1(pObj); - Aig_ObjDisconnect( p, pObj ); - if ( fFreeTop ) - Aig_ObjDelete( p, pObj ); - if ( pFanin0 && !Aig_ObjIsNone(pFanin0) && Aig_ObjRefs(pFanin0) == 0 ) - Aig_ObjDelete_rec( p, pFanin0, 1 ); - if ( pFanin1 && !Aig_ObjIsNone(pFanin1) && Aig_ObjRefs(pFanin1) == 0 ) - Aig_ObjDelete_rec( p, pFanin1, 1 ); -} - -/**Function************************************************************* - - Synopsis [Replaces the first fanin of the node by the new fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew ) -{ - Aig_Obj_t * pFaninOld; - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsPo(pObj) ); - pFaninOld = Aig_ObjFanin0(pObj); - // decrement ref and remove fanout - if ( p->pFanData ) - Aig_ObjRemoveFanout( p, pFaninOld, pObj ); - Aig_ObjDeref( pFaninOld ); - // update the fanin - pObj->pFanin0 = pFaninNew; - // increment ref and add fanout - if ( p->pFanData ) - Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); - Aig_ObjRef( Aig_ObjFanin0(pObj) ); - // get rid of old fanin - if ( !Aig_ObjIsPi(pFaninOld) && !Aig_ObjIsConst1(pFaninOld) && Aig_ObjRefs(pFaninOld) == 0 ) - Aig_ObjDelete_rec( p, pFaninOld, 1 ); -} - -/**Function************************************************************* - - Synopsis [Replaces node with a buffer fanin by a node without them.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_NodeFixBufferFanins( Aig_Man_t * p, Aig_Obj_t * pObj, int fNodesOnly, int fUpdateLevel ) -{ - Aig_Obj_t * pFanReal0, * pFanReal1, * pResult; - p->nBufFixes++; - if ( Aig_ObjIsPo(pObj) ) - { - assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ); - pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); - assert( Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) == Aig_ObjPhaseReal(pFanReal0) ); - Aig_ObjPatchFanin0( p, pObj, pFanReal0 ); - return; - } - assert( Aig_ObjIsNode(pObj) ); - assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) || Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) ); - // get the real fanins - pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); - pFanReal1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); - // get the new node - if ( Aig_ObjIsNode(pObj) ) - pResult = Aig_Oper( p, pFanReal0, pFanReal1, Aig_ObjType(pObj) ); -// else if ( Aig_ObjIsLatch(pObj) ) -// pResult = Aig_Latch( p, pFanReal0, Aig_ObjInit(pObj) ); - else - assert( 0 ); - // replace the node with buffer by the node without buffer - Aig_ObjReplace( p, pObj, pResult, fNodesOnly, fUpdateLevel ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of dangling nodes removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManPropagateBuffers( Aig_Man_t * p, int fNodesOnly, int fUpdateLevel ) -{ - Aig_Obj_t * pObj; - int nSteps; - assert( p->pFanData ); - for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ ) - { - // get the node with a buffer fanin - for ( pObj = Vec_PtrEntryLast(p->vBufs); Aig_ObjIsBuf(pObj); pObj = Aig_ObjFanout0(p, pObj) ); - // replace this node by a node without buffer - Aig_NodeFixBufferFanins( p, pObj, fNodesOnly, fUpdateLevel ); - // stop if a cycle occured - if ( nSteps > 1000000 ) - { - printf( "Error: A cycle is encountered while propagating buffers.\n" ); - break; - } - } - return nSteps; -} - -/**Function************************************************************* - - Synopsis [Replaces one object by another.] - - Description [The new object (pObjNew) should be used instead of the old - object (pObjOld). If the new object is complemented or used, the buffer - is added and the new object remains in the manager; otherwise, the new - object is deleted.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fNodesOnly, int fUpdateLevel ) -{ - Aig_Obj_t * pObjNewR = Aig_Regular(pObjNew); - // the object to be replaced cannot be complemented - assert( !Aig_IsComplement(pObjOld) ); - // the object to be replaced cannot be a terminal - assert( !Aig_ObjIsPi(pObjOld) && !Aig_ObjIsPo(pObjOld) ); - // the object to be used cannot be a buffer or a PO - assert( !Aig_ObjIsBuf(pObjNewR) && !Aig_ObjIsPo(pObjNewR) ); - // the object cannot be the same - assert( pObjOld != pObjNewR ); - // make sure object is not pointing to itself - assert( pObjOld != Aig_ObjFanin0(pObjNewR) ); - assert( pObjOld != Aig_ObjFanin1(pObjNewR) ); - // recursively delete the old node - but leave the object there - pObjNewR->nRefs++; - Aig_ObjDelete_rec( p, pObjOld, 0 ); - pObjNewR->nRefs--; - // if the new object is complemented or already used, create a buffer - p->nObjs[pObjOld->Type]--; - if ( Aig_IsComplement(pObjNew) || Aig_ObjRefs(pObjNew) > 0 || (fNodesOnly && !Aig_ObjIsNode(pObjNew)) ) - { - pObjOld->Type = AIG_OBJ_BUF; - Aig_ObjConnect( p, pObjOld, pObjNew, NULL ); - p->nBufReplaces++; - } - else - { - Aig_Obj_t * pFanin0 = pObjNew->pFanin0; - Aig_Obj_t * pFanin1 = pObjNew->pFanin1; - int LevelOld = pObjOld->Level; - pObjOld->Type = pObjNew->Type; - Aig_ObjDisconnect( p, pObjNew ); - Aig_ObjConnect( p, pObjOld, pFanin0, pFanin1 ); - // delete the new object - Aig_ObjDelete( p, pObjNew ); - // update levels - if ( p->pFanData ) - { - pObjOld->Level = LevelOld; - Aig_ManUpdateLevel( p, pObjOld ); - } - if ( fUpdateLevel ) - { - Aig_ObjClearReverseLevel( p, pObjOld ); - Aig_ManUpdateReverseLevel( p, pObjOld ); - } - } - p->nObjs[pObjOld->Type]++; - // store buffers if fanout is allocated - if ( p->pFanData && Aig_ObjIsBuf(pObjOld) ) - { - Vec_PtrPush( p->vBufs, pObjOld ); - p->nBufMax = AIG_MAX( p->nBufMax, Vec_PtrSize(p->vBufs) ); - Aig_ManPropagateBuffers( p, fNodesOnly, fUpdateLevel ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigOper.c b/src/aig/aig/aigOper.c deleted file mode 100644 index 68216ee0..00000000 --- a/src/aig/aig/aigOper.c +++ /dev/null @@ -1,532 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigOper.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [AIG operations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigOper.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// procedure to detect an EXOR gate -static inline int Aig_ObjIsExorType( Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) -{ - if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) - return 0; - p0 = Aig_Regular(p0); - p1 = Aig_Regular(p1); - if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) - return 0; - if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) - return 0; - if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) - return 0; - *ppFan0 = Aig_ObjChild0(p0); - *ppFan1 = Aig_ObjChild1(p0); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns i-th elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ) -{ - int v; - for ( v = Aig_ManPiNum(p); v <= i; v++ ) - Aig_ObjCreatePi( p ); - assert( i < Vec_PtrSize(p->vPis) ); - return Aig_ManPi( p, i ); -} - -/**Function************************************************************* - - Synopsis [Perform one operation.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) -{ - if ( Type == AIG_OBJ_AND ) - return Aig_And( p, p0, p1 ); - if ( Type == AIG_OBJ_EXOR ) - return Aig_Exor( p, p0, p1 ); - assert( 0 ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Creates the canonical form of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_CanonPair_rec( Aig_Man_t * p, Aig_Obj_t * pGhost ) -{ - Aig_Obj_t * pResult, * pLat0, * pLat1; - int fCompl0, fCompl1; - Aig_Type_t Type; - assert( Aig_ObjIsNode(pGhost) ); - // consider the case when the pair is canonical - if ( !Aig_ObjIsLatch(Aig_ObjFanin0(pGhost)) || !Aig_ObjIsLatch(Aig_ObjFanin1(pGhost)) ) - { - if ( pResult = Aig_TableLookup( p, pGhost ) ) - return pResult; - return Aig_ObjCreate( p, pGhost ); - } - /// remember the latches - pLat0 = Aig_ObjFanin0(pGhost); - pLat1 = Aig_ObjFanin1(pGhost); - // remember type and compls - Type = Aig_ObjType(pGhost); - fCompl0 = Aig_ObjFaninC0(pGhost); - fCompl1 = Aig_ObjFaninC1(pGhost); - // call recursively - pResult = Aig_Oper( p, Aig_NotCond(Aig_ObjChild0(pLat0), fCompl0), Aig_NotCond(Aig_ObjChild0(pLat1), fCompl1), Type ); - // build latch on top of this - return Aig_Latch( p, pResult, (Type == AIG_OBJ_AND)? fCompl0 & fCompl1 : fCompl0 ^ fCompl1 ); -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) -{ - Aig_Obj_t * pGhost, * pResult; -// Aig_Obj_t * pFan0, * pFan1; - // check trivial cases - if ( p0 == p1 ) - return p0; - if ( p0 == Aig_Not(p1) ) - return Aig_Not(p->pConst1); - if ( Aig_Regular(p0) == p->pConst1 ) - return p0 == p->pConst1 ? p1 : Aig_Not(p->pConst1); - if ( Aig_Regular(p1) == p->pConst1 ) - return p1 == p->pConst1 ? p0 : Aig_Not(p->pConst1); - // check not so trivial cases - if ( p->fAddStrash && (Aig_ObjIsNode(Aig_Regular(p0)) || Aig_ObjIsNode(Aig_Regular(p1))) ) - { // http://fmv.jku.at/papers/BrummayerBiere-MEMICS06.pdf - Aig_Obj_t * pFanA, * pFanB, * pFanC, * pFanD; - pFanA = Aig_ObjChild0(Aig_Regular(p0)); - pFanB = Aig_ObjChild1(Aig_Regular(p0)); - pFanC = Aig_ObjChild0(Aig_Regular(p1)); - pFanD = Aig_ObjChild1(Aig_Regular(p1)); - if ( Aig_IsComplement(p0) ) - { - if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) ) - return p1; - if ( pFanB == p1 ) - return Aig_And( p, Aig_Not(pFanA), pFanB ); - if ( pFanA == p1 ) - return Aig_And( p, Aig_Not(pFanB), pFanA ); - } - else - { - if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) ) - return Aig_Not(p->pConst1); - if ( pFanA == p1 || pFanB == p1 ) - return p0; - } - if ( Aig_IsComplement(p1) ) - { - if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) ) - return p0; - if ( pFanD == p0 ) - return Aig_And( p, Aig_Not(pFanC), pFanD ); - if ( pFanC == p0 ) - return Aig_And( p, Aig_Not(pFanD), pFanC ); - } - else - { - if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) ) - return Aig_Not(p->pConst1); - if ( pFanC == p0 || pFanD == p0 ) - return p1; - } - if ( !Aig_IsComplement(p0) && !Aig_IsComplement(p1) ) - { - if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) ) - return Aig_Not(p->pConst1); - if ( pFanA == pFanC || pFanB == pFanC ) - return Aig_And( p, p0, pFanD ); - if ( pFanB == pFanC || pFanB == pFanD ) - return Aig_And( p, pFanA, p1 ); - if ( pFanA == pFanD || pFanB == pFanD ) - return Aig_And( p, p0, pFanC ); - if ( pFanA == pFanC || pFanA == pFanD ) - return Aig_And( p, pFanB, p1 ); - } - else if ( Aig_IsComplement(p0) && !Aig_IsComplement(p1) ) - { - if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) ) - return p1; - if ( pFanB == pFanC || pFanB == pFanD ) - return Aig_And( p, Aig_Not(pFanA), p1 ); - if ( pFanA == pFanC || pFanA == pFanD ) - return Aig_And( p, Aig_Not(pFanB), p1 ); - } - else if ( !Aig_IsComplement(p0) && Aig_IsComplement(p1) ) - { - if ( pFanC == Aig_Not(pFanA) || pFanC == Aig_Not(pFanB) || pFanD == Aig_Not(pFanA) || pFanD == Aig_Not(pFanB) ) - return p0; - if ( pFanD == pFanA || pFanD == pFanB ) - return Aig_And( p, Aig_Not(pFanC), p0 ); - if ( pFanC == pFanA || pFanC == pFanB ) - return Aig_And( p, Aig_Not(pFanD), p0 ); - } - else // if ( Aig_IsComplement(p0) && Aig_IsComplement(p1) ) - { - if ( pFanA == pFanD && pFanB == Aig_Not(pFanC) ) - return Aig_Not(pFanA); - if ( pFanB == pFanC && pFanA == Aig_Not(pFanD) ) - return Aig_Not(pFanB); - if ( pFanA == pFanC && pFanB == Aig_Not(pFanD) ) - return Aig_Not(pFanA); - if ( pFanB == pFanD && pFanA == Aig_Not(pFanC) ) - return Aig_Not(pFanB); - } - } - // check if it can be an EXOR gate -// if ( Aig_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) -// return Aig_Exor( p, pFan0, pFan1 ); - pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_AND ); - pResult = Aig_CanonPair_rec( p, pGhost ); - return pResult; -} - -/**Function************************************************************* - - Synopsis [Creates the canonical form of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Latch( Aig_Man_t * p, Aig_Obj_t * pObj, int fInitOne ) -{ - Aig_Obj_t * pGhost, * pResult; - pGhost = Aig_ObjCreateGhost( p, Aig_NotCond(pObj, fInitOne), NULL, AIG_OBJ_LATCH ); - pResult = Aig_TableLookup( p, pGhost ); - if ( pResult == NULL ) - pResult = Aig_ObjCreate( p, pGhost ); - return Aig_NotCond( pResult, fInitOne ); -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) -{ -/* - Aig_Obj_t * pGhost, * pResult; - // check trivial cases - if ( p0 == p1 ) - return Aig_Not(p->pConst1); - if ( p0 == Aig_Not(p1) ) - return p->pConst1; - if ( Aig_Regular(p0) == p->pConst1 ) - return Aig_NotCond( p1, p0 == p->pConst1 ); - if ( Aig_Regular(p1) == p->pConst1 ) - return Aig_NotCond( p0, p1 == p->pConst1 ); - // check the table - pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_EXOR ); - if ( pResult = Aig_TableLookup( p, pGhost ) ) - return pResult; - return Aig_ObjCreate( p, pGhost ); -*/ - return Aig_Or( p, Aig_And(p, p0, Aig_Not(p1)), Aig_And(p, Aig_Not(p0), p1) ); -} - -/**Function************************************************************* - - Synopsis [Implements Boolean OR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) -{ - return Aig_Not( Aig_And( p, Aig_Not(p0), Aig_Not(p1) ) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ) -{ -/* - Aig_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; - int Count0, Count1; - // consider trivial cases - if ( p0 == Aig_Not(p1) ) - return Aig_Exor( p, pC, p0 ); - // other cases can be added - // implement the first MUX (F = C * x1 + C' * x0) - - // check for constants here!!! - - pTempA1 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, pC, p1, AIG_OBJ_AND) ); - pTempA2 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pC), p0, AIG_OBJ_AND) ); - if ( pTempA1 && pTempA2 ) - { - pTemp = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pTempA1), Aig_Not(pTempA2), AIG_OBJ_AND) ); - if ( pTemp ) return Aig_Not(pTemp); - } - Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); - // implement the second MUX (F' = C * x1' + C' * x0') - pTempB1 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, pC, Aig_Not(p1), AIG_OBJ_AND) ); - pTempB2 = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pC), Aig_Not(p0), AIG_OBJ_AND) ); - if ( pTempB1 && pTempB2 ) - { - pTemp = Aig_TableLookup( p, Aig_ObjCreateGhost(p, Aig_Not(pTempB1), Aig_Not(pTempB2), AIG_OBJ_AND) ); - if ( pTemp ) return pTemp; - } - Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); - // compare and decide which one to implement - if ( Count0 >= Count1 ) - { - pTempA1 = pTempA1? pTempA1 : Aig_And(p, pC, p1); - pTempA2 = pTempA2? pTempA2 : Aig_And(p, Aig_Not(pC), p0); - return Aig_Or( p, pTempA1, pTempA2 ); - } - pTempB1 = pTempB1? pTempB1 : Aig_And(p, pC, Aig_Not(p1)); - pTempB2 = pTempB2? pTempB2 : Aig_And(p, Aig_Not(pC), Aig_Not(p0)); - return Aig_Not( Aig_Or( p, pTempB1, pTempB2 ) ); -*/ - return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ) -{ - return Aig_Or( p, Aig_Or(p, Aig_And(p, pA, pB), Aig_And(p, pA, pC)), Aig_And(p, pB, pC) ); -} - -/**Function************************************************************* - - Synopsis [Constructs the well-balanced tree of gates.] - - Description [Disregards levels and possible logic sharing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Multi_rec( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Aig_Type_t Type ) -{ - Aig_Obj_t * pObj1, * pObj2; - if ( nObjs == 1 ) - return ppObjs[0]; - pObj1 = Aig_Multi_rec( p, ppObjs, nObjs/2, Type ); - pObj2 = Aig_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); - return Aig_Oper( p, pObj1, pObj2, Type ); -} - -/**Function************************************************************* - - Synopsis [Old code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Multi( Aig_Man_t * p, Aig_Obj_t ** pArgs, int nArgs, Aig_Type_t Type ) -{ - assert( Type == AIG_OBJ_AND || Type == AIG_OBJ_EXOR ); - assert( nArgs > 0 ); - return Aig_Multi_rec( p, pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Implements the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ) -{ - int i; - assert( vPairs->nSize > 0 ); - assert( vPairs->nSize % 2 == 0 ); - for ( i = 0; i < vPairs->nSize; i += 2 ) - vPairs->pArray[i/2] = Aig_Not( Aig_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) ); - vPairs->nSize = vPairs->nSize/2; - return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_OBJ_AND ) ); -} - -/**Function************************************************************* - - Synopsis [Implements the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 ) -{ - int i; - assert( vNodes1->nSize > 0 && vNodes1->nSize > 0 ); - assert( vNodes1->nSize == vNodes2->nSize ); - for ( i = 0; i < vNodes1->nSize; i++ ) - vNodes1->pArray[i] = Aig_Not( Aig_Exor( p, vNodes1->pArray[i], vNodes2->pArray[i] ) ); - return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vNodes1->pArray, vNodes1->nSize, AIG_OBJ_AND ) ); -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ) -{ - Aig_Obj_t * pFunc; - int i; - pFunc = Aig_ManConst1( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Aig_And( p, pFunc, Aig_IthVar(p, i) ); - return pFunc; -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ) -{ - Aig_Obj_t * pFunc; - int i; - pFunc = Aig_ManConst0( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Aig_Or( p, pFunc, Aig_IthVar(p, i) ); - return pFunc; -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ) -{ - Aig_Obj_t * pFunc; - int i; - pFunc = Aig_ManConst0( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Aig_Exor( p, pFunc, Aig_IthVar(p, i) ); - return pFunc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigOrder.c b/src/aig/aig/aigOrder.c deleted file mode 100644 index 62aeca6e..00000000 --- a/src/aig/aig/aigOrder.c +++ /dev/null @@ -1,171 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigOrder.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Dynamically updated topological order.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigOrder.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Initializes the order datastructure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManOrderStart( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - assert( Aig_ManBufNum(p) == 0 ); - // allocate order datastructure - assert( p->pOrderData == NULL ); - p->nOrderAlloc = 2 * Aig_ManObjNumMax(p); - if ( p->nOrderAlloc < (1<<12) ) - p->nOrderAlloc = (1<<12); - p->pOrderData = ALLOC( unsigned, 2 * p->nOrderAlloc ); - memset( p->pOrderData, 0xFF, sizeof(unsigned) * 2 * p->nOrderAlloc ); - // add the constant node - p->pOrderData[0] = p->pOrderData[1] = 0; - p->iPrev = p->iNext = 0; - // add the internal nodes - Aig_ManForEachNode( p, pObj, i ) - Aig_ObjOrderInsert( p, pObj->Id ); -} - -/**Function************************************************************* - - Synopsis [Deletes the order datastructure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManOrderStop( Aig_Man_t * p ) -{ - assert( p->pOrderData ); - FREE( p->pOrderData ); - p->nOrderAlloc = 0; - p->iPrev = p->iNext = 0; -} - -/**Function************************************************************* - - Synopsis [Inserts an entry before iNext.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId ) -{ - int iPrev; - assert( ObjId != 0 ); - assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) ); - if ( ObjId >= p->nOrderAlloc ) - { - int nOrderAlloc = 2 * ObjId; - p->pOrderData = REALLOC( unsigned, p->pOrderData, 2 * nOrderAlloc ); - memset( p->pOrderData + 2 * p->nOrderAlloc, 0xFF, sizeof(unsigned) * 2 * (nOrderAlloc - p->nOrderAlloc) ); - p->nOrderAlloc = nOrderAlloc; - } - assert( p->pOrderData[2*ObjId] == 0xFFFFFFFF ); // prev - assert( p->pOrderData[2*ObjId+1] == 0xFFFFFFFF ); // next - iPrev = p->pOrderData[2*p->iNext]; - assert( p->pOrderData[2*iPrev+1] == (unsigned)p->iNext ); - p->pOrderData[2*ObjId] = iPrev; - p->pOrderData[2*iPrev+1] = ObjId; - p->pOrderData[2*p->iNext] = ObjId; - p->pOrderData[2*ObjId+1] = p->iNext; - p->nAndTotal++; -} - -/**Function************************************************************* - - Synopsis [Removes the entry.] - - Description [If iPrev is removed, it slides backward. - If iNext is removed, it slides forward.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId ) -{ - int iPrev, iNext; - assert( ObjId != 0 ); - assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) ); - iPrev = p->pOrderData[2*ObjId]; - iNext = p->pOrderData[2*ObjId+1]; - p->pOrderData[2*ObjId] = 0xFFFFFFFF; - p->pOrderData[2*ObjId+1] = 0xFFFFFFFF; - p->pOrderData[2*iNext] = iPrev; - p->pOrderData[2*iPrev+1] = iNext; - if ( p->iPrev == ObjId ) - { - p->nAndPrev--; - p->iPrev = iPrev; - } - if ( p->iNext == ObjId ) - p->iNext = iNext; - p->nAndTotal--; -} - -/**Function************************************************************* - - Synopsis [Advances the order forward.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjOrderAdvance( Aig_Man_t * p ) -{ - assert( p->pOrderData ); - assert( p->pOrderData[2*p->iPrev+1] == (unsigned)p->iNext ); - p->iPrev = p->iNext; - p->nAndPrev++; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigPart.c b/src/aig/aig/aigPart.c deleted file mode 100644 index 65e35fc4..00000000 --- a/src/aig/aig/aigPart.c +++ /dev/null @@ -1,990 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigPart.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [AIG partitioning package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigPart.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Part_Man_t_ Part_Man_t; -struct Part_Man_t_ -{ - int nChunkSize; // the size of one chunk of memory (~1 Mb) - int nStepSize; // the step size in saving memory (~64 bytes) - char * pFreeBuf; // the pointer to free memory - int nFreeSize; // the size of remaining free memory - Vec_Ptr_t * vMemory; // the memory allocated - Vec_Ptr_t * vFree; // the vector of free pieces of memory -}; - -typedef struct Part_One_t_ Part_One_t; -struct Part_One_t_ -{ - int nRefs; // the number of references - int nOuts; // the number of outputs - int nOutsAlloc; // the array size - int pOuts[0]; // the array of outputs -}; - -static inline int Part_SizeType( int nSize, int nStepSize ) { return nSize / nStepSize + ((nSize % nStepSize) > 0); } -static inline char * Part_OneNext( char * pPart ) { return *((char **)pPart); } -static inline void Part_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Part_Man_t * Part_ManStart( int nChunkSize, int nStepSize ) -{ - Part_Man_t * p; - p = ALLOC( Part_Man_t, 1 ); - memset( p, 0, sizeof(Part_Man_t) ); - p->nChunkSize = nChunkSize; - p->nStepSize = nStepSize; - p->vMemory = Vec_PtrAlloc( 1000 ); - p->vFree = Vec_PtrAlloc( 1000 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Part_ManStop( Part_Man_t * p ) -{ - void * pMemory; - int i; - Vec_PtrForEachEntry( p->vMemory, pMemory, i ) - free( pMemory ); - Vec_PtrFree( p->vMemory ); - Vec_PtrFree( p->vFree ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Fetches the memory entry of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Part_ManFetch( Part_Man_t * p, int nSize ) -{ - int Type, nSizeReal; - char * pMemory; - assert( nSize > 0 ); - Type = Part_SizeType( nSize, p->nStepSize ); - Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); - if ( pMemory = Vec_PtrEntry( p->vFree, Type ) ) - { - Vec_PtrWriteEntry( p->vFree, Type, Part_OneNext(pMemory) ); - return pMemory; - } - nSizeReal = p->nStepSize * Type; - if ( p->nFreeSize < nSizeReal ) - { - p->pFreeBuf = ALLOC( char, p->nChunkSize ); - p->nFreeSize = p->nChunkSize; - Vec_PtrPush( p->vMemory, p->pFreeBuf ); - } - assert( p->nFreeSize >= nSizeReal ); - pMemory = p->pFreeBuf; - p->pFreeBuf += nSizeReal; - p->nFreeSize -= nSizeReal; - return pMemory; -} - -/**Function************************************************************* - - Synopsis [Recycles the memory entry of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Part_ManRecycle( Part_Man_t * p, char * pMemory, int nSize ) -{ - int Type; - Type = Part_SizeType( nSize, p->nStepSize ); - Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); - Part_OneSetNext( pMemory, Vec_PtrEntry(p->vFree, Type) ); - Vec_PtrWriteEntry( p->vFree, Type, pMemory ); -} - -/**Function************************************************************* - - Synopsis [Fetches the memory entry of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Part_One_t * Part_ManFetchEntry( Part_Man_t * p, int nWords, int nRefs ) -{ - Part_One_t * pPart; - pPart = (Part_One_t *)Part_ManFetch( p, sizeof(Part_One_t) + sizeof(int) * nWords ); - pPart->nRefs = nRefs; - pPart->nOuts = 0; - pPart->nOutsAlloc = nWords; - return pPart; -} - -/**Function************************************************************* - - Synopsis [Recycles the memory entry of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Part_ManRecycleEntry( Part_Man_t * p, Part_One_t * pEntry ) -{ - assert( pEntry->nOuts <= pEntry->nOutsAlloc ); - assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 ); - Part_ManRecycle( p, (char *)pEntry, sizeof(Part_One_t) + sizeof(int) * pEntry->nOutsAlloc ); -} - -/**Function************************************************************* - - Synopsis [Merges two entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Part_One_t * Part_ManMergeEntry( Part_Man_t * pMan, Part_One_t * p1, Part_One_t * p2, int nRefs ) -{ - Part_One_t * p = Part_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs ); - int * pBeg1 = p1->pOuts; - int * pBeg2 = p2->pOuts; - int * pBeg = p->pOuts; - int * pEnd1 = p1->pOuts + p1->nOuts; - int * pEnd2 = p2->pOuts + p2->nOuts; - while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) - { - if ( *pBeg1 == *pBeg2 ) - *pBeg++ = *pBeg1++, pBeg2++; - else if ( *pBeg1 < *pBeg2 ) - *pBeg++ = *pBeg1++; - else - *pBeg++ = *pBeg2++; - } - while ( pBeg1 < pEnd1 ) - *pBeg++ = *pBeg1++; - while ( pBeg2 < pEnd2 ) - *pBeg++ = *pBeg2++; - p->nOuts = pBeg - p->pOuts; - assert( p->nOuts <= p->nOutsAlloc ); - assert( p->nOuts >= p1->nOuts ); - assert( p->nOuts >= p2->nOuts ); - return p; -} - -/**Function************************************************************* - - Synopsis [Tranfers the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Part_ManTransferEntry( Part_One_t * p ) -{ - Vec_Int_t * vSupp; - int i; - vSupp = Vec_IntAlloc( p->nOuts ); - for ( i = 0; i < p->nOuts; i++ ) - Vec_IntPush( vSupp, p->pOuts[i] ); - return vSupp; -} - -/**Function************************************************************* - - Synopsis [Computes supports of the POs in the multi-output AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManSupports( Aig_Man_t * pMan ) -{ - Vec_Ptr_t * vSupports; - Vec_Int_t * vSupp; - Part_Man_t * p; - Part_One_t * pPart0, * pPart1; - Aig_Obj_t * pObj; - int i; - // set the number of PIs/POs - Aig_ManForEachPi( pMan, pObj, i ) - pObj->pNext = (Aig_Obj_t *)i; - Aig_ManForEachPo( pMan, pObj, i ) - pObj->pNext = (Aig_Obj_t *)i; - // start the support computation manager - p = Part_ManStart( 1 << 20, 1 << 6 ); - // consider objects in the topological order - vSupports = Vec_PtrAlloc( Aig_ManPoNum(pMan) ); - Aig_ManCleanData(pMan); - Aig_ManForEachObj( pMan, pObj, i ) - { - if ( Aig_ObjIsNode(pObj) ) - { - pPart0 = Aig_ObjFanin0(pObj)->pData; - pPart1 = Aig_ObjFanin1(pObj)->pData; - pObj->pData = Part_ManMergeEntry( p, pPart0, pPart1, pObj->nRefs ); - assert( pPart0->nRefs > 0 ); - if ( --pPart0->nRefs == 0 ) - Part_ManRecycleEntry( p, pPart0 ); - assert( pPart1->nRefs > 0 ); - if ( --pPart1->nRefs == 0 ) - Part_ManRecycleEntry( p, pPart1 ); - continue; - } - if ( Aig_ObjIsPo(pObj) ) - { - pPart0 = Aig_ObjFanin0(pObj)->pData; - vSupp = Part_ManTransferEntry(pPart0); - Vec_IntPush( vSupp, (int)pObj->pNext ); - Vec_PtrPush( vSupports, vSupp ); - assert( pPart0->nRefs > 0 ); - if ( --pPart0->nRefs == 0 ) - Part_ManRecycleEntry( p, pPart0 ); - continue; - } - if ( Aig_ObjIsPi(pObj) ) - { - if ( pObj->nRefs ) - { - pPart0 = Part_ManFetchEntry( p, 1, pObj->nRefs ); - pPart0->pOuts[ pPart0->nOuts++ ] = (int)pObj->pNext; - pObj->pData = pPart0; - } - continue; - } - if ( Aig_ObjIsConst1(pObj) ) - { - if ( pObj->nRefs ) - pObj->pData = Part_ManFetchEntry( p, 0, pObj->nRefs ); - continue; - } - assert( 0 ); - } -//printf( "Memory usage = %d Mb.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) ); - Part_ManStop( p ); - // sort supports by size - Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); - // clear the number of PIs/POs - Aig_ManForEachPi( pMan, pObj, i ) - pObj->pNext = NULL; - Aig_ManForEachPo( pMan, pObj, i ) - pObj->pNext = NULL; -/* - Aig_ManForEachPo( pMan, pObj, i ) - printf( "%d ", Vec_IntSize( (Vec_Int_t *)Vec_VecEntry(vSupports, i) ) ); - printf( "\n" ); -*/ - return vSupports; -} - -/**Function************************************************************* - - Synopsis [Start char-bases support representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Aig_ManSuppCharStart( Vec_Int_t * vOne, int nPis ) -{ - unsigned * pBuffer; - int i, Entry; - int nWords = Aig_BitWordNum(nPis); - pBuffer = ALLOC( unsigned, nWords ); - memset( pBuffer, 0, sizeof(unsigned) * nWords ); - Vec_IntForEachEntry( vOne, Entry, i ) - { - assert( Entry < nPis ); - Aig_InfoSetBit( pBuffer, Entry ); - } - return pBuffer; -} - -/**Function************************************************************* - - Synopsis [Add to char-bases support representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis ) -{ - int i, Entry; - Vec_IntForEachEntry( vOne, Entry, i ) - { - assert( Entry < nPis ); - Aig_InfoSetBit( pBuffer, Entry ); - } -} - -/**Function************************************************************* - - Synopsis [Find the common variables using char-bases support representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne ) -{ - int i, Entry, nCommon = 0; - Vec_IntForEachEntry( vOne, Entry, i ) - nCommon += Aig_InfoHasBit(pBuffer, Entry); - return nCommon; -} - -/**Function************************************************************* - - Synopsis [Find the best partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsBit, int nSuppSizeLimit, Vec_Int_t * vOne ) -{ - Vec_Int_t * vPartSupp;//, * vPart; - int Attract, Repulse, Value, ValueBest; - int i, nCommon, iBest; - iBest = -1; - ValueBest = 0; - Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i ) - { -// vPart = Vec_PtrEntry( vPartsAll, i ); -// if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit ) -// continue; -// nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne ); - nCommon = Aig_ManSuppCharCommon( Vec_PtrEntry(vPartSuppsBit, i), vOne ); - if ( nCommon == 0 ) - continue; - if ( nCommon == Vec_IntSize(vOne) ) - return i; - // skip partitions whose size exceeds the limit - if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit ) - continue; - Attract = 1000 * nCommon / Vec_IntSize(vOne); - if ( Vec_IntSize(vPartSupp) < 100 ) - Repulse = 1; - else - Repulse = 1+Aig_Base2Log(Vec_IntSize(vPartSupp)-100); - Value = Attract/Repulse; - if ( ValueBest < Value ) - { - ValueBest = Value; - iBest = i; - } - } - if ( ValueBest < 75 ) - return -1; - return iBest; -} - -/**Function************************************************************* - - Synopsis [Perform the smart partitioning.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManPartitionPrint( Aig_Man_t * p, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll ) -{ - Vec_Int_t * vOne; - int i, nOutputs, Counter; - - Counter = 0; - Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) - { - nOutputs = Vec_IntSize(Vec_PtrEntry(vPartsAll, i)); - printf( "%d=(%d,%d) ", i, Vec_IntSize(vOne), nOutputs ); - Counter += nOutputs; - if ( i == Vec_PtrSize(vPartsAll) - 1 ) - break; - } - assert( Counter == Aig_ManPoNum(p) ); -// printf( "\nTotal = %d. Outputs = %d.\n", Counter, Aig_ManPoNum(p) ); -} - -/**Function************************************************************* - - Synopsis [Perform the smart partitioning.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit ) -{ - Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; - int i, iPart; - - if ( nSuppSizeLimit == 0 ) - nSuppSizeLimit = 200; - - // pack smaller partitions into larger blocks - iPart = 0; - vPart = vPartSupp = NULL; - Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) - { - if ( Vec_IntSize(vOne) < nSuppSizeLimit ) - { - if ( vPartSupp == NULL ) - { - assert( vPart == NULL ); - vPartSupp = Vec_IntDup(vOne); - vPart = Vec_PtrEntry(vPartsAll, i); - } - else - { - vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); - Vec_IntFree( vTemp ); - vPart = Vec_IntTwoMerge( vTemp = vPart, Vec_PtrEntry(vPartsAll, i) ); - Vec_IntFree( vTemp ); - Vec_IntFree( Vec_PtrEntry(vPartsAll, i) ); - } - if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit ) - continue; - } - else - vPart = Vec_PtrEntry(vPartsAll, i); - // add the partition - Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); - vPart = NULL; - if ( vPartSupp ) - { - Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) ); - Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); - vPartSupp = NULL; - } - iPart++; - } - // add the last one - if ( vPart ) - { - Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); - vPart = NULL; - - assert( vPartSupp != NULL ); - Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) ); - Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); - vPartSupp = NULL; - iPart++; - } - Vec_PtrShrink( vPartsAll, iPart ); - Vec_PtrShrink( vPartsAll, iPart ); -} - -/**Function************************************************************* - - Synopsis [Perform the smart partitioning.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManPartitionSmart( Aig_Man_t * p, int nSuppSizeLimit, int fVerbose, Vec_Ptr_t ** pvPartSupps ) -{ - Vec_Ptr_t * vPartSuppsBit; - Vec_Ptr_t * vSupports, * vPartsAll, * vPartsAll2, * vPartSuppsAll;//, * vPartPtr; - Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; - int i, iPart, iOut, clk; - - // compute the supports for all outputs -clk = clock(); - vSupports = Aig_ManSupports( p ); -if ( fVerbose ) -{ -PRT( "Supps", clock() - clk ); -} - // start char-based support representation - vPartSuppsBit = Vec_PtrAlloc( 1000 ); - - // create partitions -clk = clock(); - vPartsAll = Vec_PtrAlloc( 256 ); - vPartSuppsAll = Vec_PtrAlloc( 256 ); - Vec_PtrForEachEntry( vSupports, vOne, i ) - { - // get the output number - iOut = Vec_IntPop(vOne); - // find closely matching part - iPart = Aig_ManPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsBit, nSuppSizeLimit, vOne ); - if ( iPart == -1 ) - { - // create new partition - vPart = Vec_IntAlloc( 32 ); - Vec_IntPush( vPart, iOut ); - // create new partition support - vPartSupp = Vec_IntDup( vOne ); - // add this partition and its support - Vec_PtrPush( vPartsAll, vPart ); - Vec_PtrPush( vPartSuppsAll, vPartSupp ); - - Vec_PtrPush( vPartSuppsBit, Aig_ManSuppCharStart(vOne, Aig_ManPiNum(p)) ); - } - else - { - // add output to this partition - vPart = Vec_PtrEntry( vPartsAll, iPart ); - Vec_IntPush( vPart, iOut ); - // merge supports - vPartSupp = Vec_PtrEntry( vPartSuppsAll, iPart ); - vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); - Vec_IntFree( vTemp ); - // reinsert new support - Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); - - Aig_ManSuppCharAdd( Vec_PtrEntry(vPartSuppsBit, iPart), vOne, Aig_ManPiNum(p) ); - } - } - - // stop char-based support representation - Vec_PtrForEachEntry( vPartSuppsBit, vTemp, i ) - free( vTemp ); - Vec_PtrFree( vPartSuppsBit ); - -//printf( "\n" ); -if ( fVerbose ) -{ -PRT( "Parts", clock() - clk ); -} - -clk = clock(); - // reorder partitions in the decreasing order of support sizes - // remember partition number in each partition support - Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) - Vec_IntPush( vOne, i ); - // sort the supports in the decreasing order - Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 ); - // reproduce partitions - vPartsAll2 = Vec_PtrAlloc( 256 ); - Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) - Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) ); - Vec_PtrFree( vPartsAll ); - vPartsAll = vPartsAll2; - - // compact small partitions -// Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); - Aig_ManPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit ); - if ( fVerbose ) -// Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); - printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) ); - -if ( fVerbose ) -{ -//PRT( "Comps", clock() - clk ); -} - - // cleanup - Vec_VecFree( (Vec_Vec_t *)vSupports ); - if ( pvPartSupps == NULL ) - Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll ); - else - *pvPartSupps = vPartSuppsAll; -/* - // converts from intergers to nodes - Vec_PtrForEachEntry( vPartsAll, vPart, iPart ) - { - vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) ); - Vec_IntForEachEntry( vPart, iOut, i ) - Vec_PtrPush( vPartPtr, Aig_ManPo(p, iOut) ); - Vec_IntFree( vPart ); - Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr ); - } -*/ - return vPartsAll; -} - -/**Function************************************************************* - - Synopsis [Perform the naive partitioning.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize ) -{ - Vec_Ptr_t * vParts; - Aig_Obj_t * pObj; - int nParts, i; - nParts = (Aig_ManPoNum(p) / nPartSize) + ((Aig_ManPoNum(p) % nPartSize) > 0); - vParts = (Vec_Ptr_t *)Vec_VecStart( nParts ); - Aig_ManForEachPo( p, pObj, i ) - Vec_IntPush( Vec_PtrEntry(vParts, i / nPartSize), i ); - return vParts; -} - - - -/**Function************************************************************* - - Synopsis [Adds internal nodes in the topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ManDupPart_rec( Aig_Man_t * pNew, Aig_Man_t * pOld, Aig_Obj_t * pObj, Vec_Int_t * vSuppMap ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsTravIdCurrent(pOld, pObj) ) - return pObj->pData; - Aig_ObjSetTravIdCurrent(pOld, pObj); - if ( Aig_ObjIsPi(pObj) ) - { - assert( Vec_IntSize(vSuppMap) == Aig_ManPiNum(pNew) ); - Vec_IntPush( vSuppMap, (int)pObj->pNext ); - return pObj->pData = Aig_ObjCreatePi(pNew); - } - assert( Aig_ObjIsNode(pObj) ); - Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); - Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin1(pObj), vSuppMap ); - return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Adds internal nodes in the topological order.] - - Description [Returns the array of new outputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManDupPart( Aig_Man_t * pNew, Aig_Man_t * pOld, Vec_Int_t * vPart, Vec_Int_t * vSuppMap, int fInverse ) -{ - Vec_Ptr_t * vOutsTotal; - Aig_Obj_t * pObj; - int Entry, i; - // create the PIs - Aig_ManIncrementTravId( pOld ); - Aig_ManConst1(pOld)->pData = Aig_ManConst1(pNew); - Aig_ObjSetTravIdCurrent( pOld, Aig_ManConst1(pOld) ); - if ( !fInverse ) - { - Vec_IntForEachEntry( vSuppMap, Entry, i ) - { - pObj = Aig_ManPi( pOld, Entry ); - pObj->pData = Aig_ManPi( pNew, i ); - Aig_ObjSetTravIdCurrent( pOld, pObj ); - } - } - else - { - Vec_IntForEachEntry( vSuppMap, Entry, i ) - { - pObj = Aig_ManPi( pOld, i ); - pObj->pData = Aig_ManPi( pNew, Entry ); - Aig_ObjSetTravIdCurrent( pOld, pObj ); - } - vSuppMap = NULL; // should not be useful - } - // create the internal nodes - vOutsTotal = Vec_PtrAlloc( Vec_IntSize(vPart) ); - if ( !fInverse ) - { - Vec_IntForEachEntry( vPart, Entry, i ) - { - pObj = Aig_ManPo( pOld, Entry ); - Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); - Vec_PtrPush( vOutsTotal, Aig_ObjChild0Copy(pObj) ); - } - } - else - { - Aig_ManForEachObj( pOld, pObj, i ) - { - if ( Aig_ObjIsPo(pObj) ) - { - Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); - Vec_PtrPush( vOutsTotal, Aig_ObjChild0Copy(pObj) ); - } - else if ( Aig_ObjIsNode(pObj) && pObj->nRefs == 0 ) - Aig_ManDupPart_rec( pNew, pOld, pObj, vSuppMap ); - - } - } - return vOutsTotal; -} - -/**Function************************************************************* - - Synopsis [Create partitioned miter of the two AIGs.] - - Description [Assumes that each output in the second AIG cannot have - more supp vars than the same output in the first AIG.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManMiterPartitioned( Aig_Man_t * p1, Aig_Man_t * p2, int nPartSize ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pMiter; - Vec_Ptr_t * vMiters, * vNodes1, * vNodes2; - Vec_Ptr_t * vParts, * vPartSupps; - Vec_Int_t * vPart, * vPartSupp; - int i, k; - // partition the first manager - vParts = Aig_ManPartitionSmart( p1, nPartSize, 0, &vPartSupps ); - // derive miters - vMiters = Vec_PtrAlloc( Vec_PtrSize(vParts) ); - for ( i = 0; i < Vec_PtrSize(vParts); i++ ) - { - // get partitions and their support - vPart = Vec_PtrEntry( vParts, i ); - vPartSupp = Vec_PtrEntry( vPartSupps, i ); - // create the new miter - pNew = Aig_ManStart( 1000 ); -// pNew->pName = Extra_UtilStrsav( p1->pName ); - // create the PIs - for ( k = 0; k < Vec_IntSize(vPartSupp); k++ ) - Aig_ObjCreatePi( pNew ); - // copy the components - vNodes1 = Aig_ManDupPart( pNew, p1, vPart, vPartSupp, 0 ); - vNodes2 = Aig_ManDupPart( pNew, p2, vPart, vPartSupp, 0 ); - // create the miter - pMiter = Aig_MiterTwo( pNew, vNodes1, vNodes2 ); - Vec_PtrFree( vNodes1 ); - Vec_PtrFree( vNodes2 ); - // create the output - Aig_ObjCreatePo( pNew, pMiter ); - // clean up - Aig_ManCleanup( pNew ); - Vec_PtrPush( vMiters, pNew ); - } - Vec_VecFree( (Vec_Vec_t *)vParts ); - Vec_VecFree( (Vec_Vec_t *)vPartSupps ); - return vMiters; -} - -/**Function************************************************************* - - Synopsis [Performs partitioned choice computation.] - - Description [Assumes that each output in the second AIG cannot have - more supp vars than the same output in the first AIG.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize ) -{ - extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); - extern void * Abc_FrameGetGlobalFrame(); - extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax ); - - Vec_Ptr_t * vOutsTotal, * vOuts; - Aig_Man_t * pAigTotal, * pAigPart, * pAig; - Vec_Int_t * vPart, * vPartSupp; - Vec_Ptr_t * vParts; - Aig_Obj_t * pObj; - void ** ppData; - int i, k, m; - - // partition the first AIG in the array - assert( Vec_PtrSize(vAigs) > 1 ); - pAig = Vec_PtrEntry( vAigs, 0 ); - vParts = Aig_ManPartitionSmart( pAig, nPartSize, 0, NULL ); - - // start the total fraiged AIG - pAigTotal = Aig_ManStartFrom( pAig ); - Aig_ManReprStart( pAigTotal, Vec_PtrSize(vAigs) * Aig_ManObjNumMax(pAig) + 10000 ); - vOutsTotal = Vec_PtrStart( Aig_ManPoNum(pAig) ); - - // set the PI numbers - Vec_PtrForEachEntry( vAigs, pAig, i ) - Aig_ManForEachPi( pAig, pObj, k ) - pObj->pNext = (Aig_Obj_t *)k; - - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); - - // create the total fraiged AIG - vPartSupp = Vec_IntAlloc( 100 ); // maps part PI num into total PI num - Vec_PtrForEachEntry( vParts, vPart, i ) - { - // derive the partition AIG - pAigPart = Aig_ManStart( 5000 ); -// pAigPart->pName = Extra_UtilStrsav( pAigPart->pName ); - Vec_IntClear( vPartSupp ); - Vec_PtrForEachEntry( vAigs, pAig, k ) - { - vOuts = Aig_ManDupPart( pAigPart, pAig, vPart, vPartSupp, 0 ); - if ( k == 0 ) - { - Vec_PtrForEachEntry( vOuts, pObj, m ) - Aig_ObjCreatePo( pAigPart, pObj ); - } - Vec_PtrFree( vOuts ); - } - // derive the total AIG from the partitioned AIG - vOuts = Aig_ManDupPart( pAigTotal, pAigPart, vPart, vPartSupp, 1 ); - // add to the outputs - Vec_PtrForEachEntry( vOuts, pObj, k ) - { - assert( Vec_PtrEntry( vOutsTotal, Vec_IntEntry(vPart,k) ) == NULL ); - Vec_PtrWriteEntry( vOutsTotal, Vec_IntEntry(vPart,k), pObj ); - } - Vec_PtrFree( vOuts ); - // store contents of pData pointers - ppData = ALLOC( void *, Aig_ManObjNumMax(pAigPart) ); - Aig_ManForEachObj( pAigPart, pObj, k ) - ppData[k] = pObj->pData; - // report the process - printf( "Part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", - i+1, Vec_PtrSize(vParts), Aig_ManPiNum(pAigPart), Aig_ManPoNum(pAigPart), - Aig_ManNodeNum(pAigPart), Aig_ManLevelNum(pAigPart) ); - // compute equivalence classes (to be stored in pNew->pReprs) - pAig = Fra_FraigChoice( pAigPart, 1000 ); - Aig_ManStop( pAig ); - // reset the pData pointers - Aig_ManForEachObj( pAigPart, pObj, k ) - pObj->pData = ppData[k]; - free( ppData ); - // transfer representatives to the total AIG - if ( pAigPart->pReprs ) - Aig_ManTransferRepr( pAigTotal, pAigPart ); - Aig_ManStop( pAigPart ); - } - printf( " \r" ); - Vec_VecFree( (Vec_Vec_t *)vParts ); - Vec_IntFree( vPartSupp ); - - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); - - // clear the PI numbers - Vec_PtrForEachEntry( vAigs, pAig, i ) - Aig_ManForEachPi( pAig, pObj, k ) - pObj->pNext = NULL; -/* - // collect the missing outputs (outputs whose driver is not a node) - pAig = Vec_PtrEntry( vAigs, 0 ); - Aig_ManConst1(pAig)->pData = Aig_ManConst1(pAigTotal); - Aig_ManForEachPi( pAig, pObj, i ) - pAig->pData = Aig_ManPi( pAigTotal, i ); - Aig_ManForEachPo( pAig, pObj, i ) - if ( !Aig_ObjIsNode(Aig_ObjFanin0(pObj)) ) - { - assert( Vec_PtrEntry( vOutsTotal, i ) == NULL ); - Vec_PtrWriteEntry( vOutsTotal, i, Aig_ObjChild0Copy(pObj) ); - } -*/ - // add the outputs in the same order - Vec_PtrForEachEntry( vOutsTotal, pObj, i ) - Aig_ObjCreatePo( pAigTotal, pObj ); - Vec_PtrFree( vOutsTotal ); - - // derive the result of choicing - pAig = Aig_ManRehash( pAigTotal ); - // create the equivalent nodes lists - Aig_ManMarkValidChoices( pAig ); - return pAig; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigRepr.c b/src/aig/aig/aigRepr.c deleted file mode 100644 index 6356afd3..00000000 --- a/src/aig/aig/aigRepr.c +++ /dev/null @@ -1,457 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigRepr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Handing node representatives.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigRepr.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the array of representatives.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManReprStart( Aig_Man_t * p, int nIdMax ) -{ - assert( Aig_ManBufNum(p) == 0 ); - assert( p->pReprs == NULL ); - p->nReprsAlloc = nIdMax; - p->pReprs = ALLOC( Aig_Obj_t *, p->nReprsAlloc ); - memset( p->pReprs, 0, sizeof(Aig_Obj_t *) * p->nReprsAlloc ); -} - -/**Function************************************************************* - - Synopsis [Stop the array of representatives.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManReprStop( Aig_Man_t * p ) -{ - assert( p->pReprs != NULL ); - FREE( p->pReprs ); - p->nReprsAlloc = 0; -} - -/**Function************************************************************* - - Synopsis [Set the representative.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) -{ - assert( p->pReprs != NULL ); - assert( !Aig_IsComplement(pNode1) ); - assert( !Aig_IsComplement(pNode2) ); - assert( pNode1->Id < p->nReprsAlloc ); - assert( pNode2->Id < p->nReprsAlloc ); - assert( pNode1->Id < pNode2->Id ); - p->pReprs[pNode2->Id] = pNode1; -} - -/**Function************************************************************* - - Synopsis [Set the representative.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Aig_ObjSetRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) -{ - assert( p->pReprs != NULL ); - assert( !Aig_IsComplement(pNode1) ); - assert( !Aig_IsComplement(pNode2) ); - assert( pNode1->Id < p->nReprsAlloc ); - assert( pNode2->Id < p->nReprsAlloc ); - if ( pNode1 == pNode2 ) - return; - if ( pNode1->Id < pNode2->Id ) - p->pReprs[pNode2->Id] = pNode1; - else - p->pReprs[pNode1->Id] = pNode2; -} - -/**Function************************************************************* - - Synopsis [Find representative.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Aig_Obj_t * Aig_ObjFindRepr( Aig_Man_t * p, Aig_Obj_t * pNode ) -{ - assert( p->pReprs != NULL ); - assert( !Aig_IsComplement(pNode) ); - assert( pNode->Id < p->nReprsAlloc ); -// assert( !p->pReprs[pNode->Id] || p->pReprs[pNode->Id]->Id < pNode->Id ); - return p->pReprs[pNode->Id]; -} - -/**Function************************************************************* - - Synopsis [Clears the representative.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Aig_ObjClearRepr( Aig_Man_t * p, Aig_Obj_t * pNode ) -{ - assert( p->pReprs != NULL ); - assert( !Aig_IsComplement(pNode) ); - assert( pNode->Id < p->nReprsAlloc ); - p->pReprs[pNode->Id] = NULL; -} - -/**Function************************************************************* - - Synopsis [Find representative transitively.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Aig_Obj_t * Aig_ObjFindReprTransitive( Aig_Man_t * p, Aig_Obj_t * pNode ) -{ - Aig_Obj_t * pNext, * pRepr; - if ( (pRepr = Aig_ObjFindRepr(p, pNode)) ) - while ( (pNext = Aig_ObjFindRepr(p, pRepr)) ) - pRepr = pNext; - return pRepr; -} - -/**Function************************************************************* - - Synopsis [Returns representatives of fanin in approapriate polarity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Aig_Obj_t * Aig_ObjRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pRepr; - if ( pRepr = Aig_ObjFindRepr(p, pObj) ) - return Aig_NotCond( pRepr->pData, pObj->fPhase ^ pRepr->fPhase ); - return pObj->pData; -} -static inline Aig_Obj_t * Aig_ObjChild0Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjRepr(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); } -static inline Aig_Obj_t * Aig_ObjChild1Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjRepr(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); } - -/**Function************************************************************* - - Synopsis [Duplicates AIG while substituting representatives.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * pOld ) -{ - Aig_Obj_t * pObj, * pRepr; - int k; - assert( pNew->pReprs != NULL ); - // extend storage to fix pNew - if ( pNew->nReprsAlloc < Aig_ManObjNumMax(pNew) ) - { - int nReprsAllocNew = 2 * Aig_ManObjNumMax(pNew); - pNew->pReprs = REALLOC( Aig_Obj_t *, pNew->pReprs, nReprsAllocNew ); - memset( pNew->pReprs + pNew->nReprsAlloc, 0, sizeof(Aig_Obj_t *) * (nReprsAllocNew-pNew->nReprsAlloc) ); - pNew->nReprsAlloc = nReprsAllocNew; - } - // go through the nodes which have representatives - Aig_ManForEachObj( pOld, pObj, k ) - if ( (pRepr = Aig_ObjFindRepr(pOld, pObj)) ) - Aig_ObjSetRepr( pNew, Aig_Regular(pRepr->pData), Aig_Regular(pObj->pData) ); -} - -/**Function************************************************************* - - Synopsis [Duplicates the AIG manager recursively.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ManDupRepr_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pRepr; - if ( pObj->pData ) - return pObj->pData; - if ( (pRepr = Aig_ObjFindRepr(p, pObj)) ) - { - Aig_ManDupRepr_rec( pNew, p, pRepr ); - return pObj->pData = Aig_NotCond( pRepr->pData, pRepr->fPhase ^ pObj->fPhase ); - } - Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin0(pObj) ); - Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin1(pObj) ); - return pObj->pData = Aig_And( pNew, Aig_ObjChild0Repr(p, pObj), Aig_ObjChild1Repr(p, pObj) ); -} - -/**Function************************************************************* - - Synopsis [Duplicates AIG while substituting representatives.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p, int fOrdered ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj; - int i; - // start the HOP package - pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->nRegs = p->nRegs; - if ( p->vFlopNums ) - pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); - // map the const and primary inputs - Aig_ManCleanData( p ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePi(pNew); - // map the internal nodes - if ( fOrdered ) - { - Aig_ManForEachNode( p, pObj, i ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Repr(p, pObj), Aig_ObjChild1Repr(p, pObj) ); - } - else - { - Aig_ManForEachPo( p, pObj, i ) - Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin0(pObj) ); - } - // transfer the POs - Aig_ManForEachPo( p, pObj, i ) - Aig_ObjCreatePo( pNew, Aig_ObjChild0Repr(p, pObj) ); - // check the new manager - if ( !Aig_ManCheck(pNew) ) - printf( "Aig_ManDupRepr: Check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Transfer representatives and return the number of critical fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManRemapRepr( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj, * pRepr; - int i, nFanouts = 0; - Aig_ManForEachNode( p, pObj, i ) - { - pRepr = Aig_ObjFindReprTransitive( p, pObj ); - if ( pRepr == NULL ) - continue; - assert( pRepr->Id < pObj->Id ); - Aig_ObjSetRepr( p, pObj, pRepr ); - nFanouts += (pObj->nRefs > 0); - } - return nFanouts; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pNode, Aig_Obj_t * pOld ) -{ - // check the trivial cases - if ( pNode == NULL ) - return 0; -// if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode -// return 0; - if ( pNode == pOld ) - return 1; - // skip the visited node - if ( Aig_ObjIsTravIdCurrent( p, pNode ) ) - return 0; - Aig_ObjSetTravIdCurrent( p, pNode ); - // check the children - if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin0(pNode), pOld ) ) - return 1; - if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin1(pNode), pOld ) ) - return 1; - // check equivalent nodes - return Aig_ObjCheckTfi_rec( p, p->pEquivs[pNode->Id], pOld ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pNew, Aig_Obj_t * pOld ) -{ - assert( !Aig_IsComplement(pNew) ); - assert( !Aig_IsComplement(pOld) ); - Aig_ManIncrementTravId( p ); - return Aig_ObjCheckTfi_rec( p, pNew, pOld ); -} - -/**Function************************************************************* - - Synopsis [Iteratively rehashes the AIG.] - - Description [The input AIG is assumed to have representatives assigned.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManRehash( Aig_Man_t * p ) -{ - Aig_Man_t * pTemp; - int i, nFanouts; - assert( p->pReprs != NULL ); - for ( i = 0; nFanouts = Aig_ManRemapRepr( p ); i++ ) - { -// printf( "Iter = %3d. Fanouts = %6d. Nodes = %7d.\n", i+1, nFanouts, Aig_ManNodeNum(p) ); - p = Aig_ManDupRepr( pTemp = p, 1 ); - Aig_ManReprStart( p, Aig_ManObjNumMax(p) ); - Aig_ManTransferRepr( p, pTemp ); - Aig_ManStop( pTemp ); - } - return p; -} - -/**Function************************************************************* - - Synopsis [Marks the nodes that are Creates choices.] - - Description [The input AIG is assumed to have representatives assigned.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManMarkValidChoices( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj, * pRepr; - int i; - assert( p->pReprs != NULL ); - // create equivalent nodes in the manager - assert( p->pEquivs == NULL ); - p->pEquivs = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); - memset( p->pEquivs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); - // make the choice nodes - Aig_ManForEachNode( p, pObj, i ) - { - pRepr = Aig_ObjFindRepr( p, pObj ); - if ( pRepr == NULL ) - continue; - assert( pObj->nRefs == 0 ); - // skip constant and PI classes - if ( !Aig_ObjIsNode(pRepr) ) - { - Aig_ObjClearRepr( p, pObj ); - continue; - } - // skip choices with combinatinal loops - if ( Aig_ObjCheckTfi( p, pObj, pRepr ) ) - { - Aig_ObjClearRepr( p, pObj ); - continue; - } -//printf( "Node %d is represented by node %d.\n", pObj->Id, pRepr->Id ); - // add choice to the choice node - p->pEquivs[pObj->Id] = p->pEquivs[pRepr->Id]; - p->pEquivs[pRepr->Id] = pObj; - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigRet.c b/src/aig/aig/aigRet.c deleted file mode 100644 index 3efe20f0..00000000 --- a/src/aig/aig/aigRet.c +++ /dev/null @@ -1,969 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigRet.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Retiming of AIGs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigRet.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// init values -typedef enum { - RTM_VAL_NONE, // 0: non-existent value - RTM_VAL_ZERO, // 1: initial value 0 - RTM_VAL_ONE, // 2: initial value 1 - RTM_VAL_VOID // 3: unused value -} Rtm_Init_t; - -typedef struct Rtm_Man_t_ Rtm_Man_t; -struct Rtm_Man_t_ -{ - // network representation - Vec_Ptr_t * vObjs; // retiming objects - Vec_Ptr_t * vPis; // PIs only - Vec_Ptr_t * vPos; // POs only - Aig_MmFlex_t * pMem; // the memory manager - // autonomous components after cutting off - // storage for overflow latches - unsigned * pExtra; - int nExtraCur; - int nExtraAlloc; -}; - -typedef struct Rtm_Edg_t_ Rtm_Edg_t; -struct Rtm_Edg_t_ -{ - unsigned long nLats : 12; // the number of latches - unsigned long LData : 20; // the latches themselves -}; - -typedef struct Rtm_Obj_t_ Rtm_Obj_t; -struct Rtm_Obj_t_ -{ - void * pCopy; // the copy of this object - unsigned long Type : 3; // object type - unsigned long fMark : 1; // multipurpose mark - unsigned long fAuto : 1; // this object belongs to an autonomous component - unsigned long fCompl0 : 1; // complemented attribute of the first edge - unsigned long fCompl1 : 1; // complemented attribute of the second edge - unsigned long nFanins : 8; // the number of fanins - unsigned Num : 17; // the retiming number of this node - int Id; // ID of this object - int Temp; // temporary usage - int nFanouts; // the number of fanouts - void * pFanio[0]; // fanins and their edges (followed by fanouts and pointers to their edges) -}; - -static inline Rtm_Obj_t * Rtm_ObjFanin( Rtm_Obj_t * pObj, int i ) { return (Rtm_Obj_t *)pObj->pFanio[2*i]; } -static inline Rtm_Obj_t * Rtm_ObjFanout( Rtm_Obj_t * pObj, int i ) { return (Rtm_Obj_t *)pObj->pFanio[2*(pObj->nFanins+i)]; } -static inline Rtm_Edg_t * Rtm_ObjEdge( Rtm_Obj_t * pObj, int i ) { return (Rtm_Edg_t *)(pObj->pFanio + 2*i + 1); } -static inline Rtm_Edg_t * Rtm_ObjFanoutEdge( Rtm_Obj_t * pObj, int i ) { return (Rtm_Edg_t *)pObj->pFanio[2*(pObj->nFanins+i) + 1]; } - -static inline Rtm_Init_t Rtm_InitNot( Rtm_Init_t Val ) { if ( Val == RTM_VAL_ZERO ) return RTM_VAL_ONE; if ( Val == RTM_VAL_ONE ) return RTM_VAL_ZERO; assert( 0 ); return -1; } -static inline Rtm_Init_t Rtm_InitNotCond( Rtm_Init_t Val, int c ) { return c ? Rtm_InitNot(Val) : Val; } -static inline Rtm_Init_t Rtm_InitAnd(Rtm_Init_t ValA, Rtm_Init_t ValB ) { if ( ValA == RTM_VAL_ONE && ValB == RTM_VAL_ONE ) return RTM_VAL_ONE; if ( ValA == RTM_VAL_ZERO || ValB == RTM_VAL_ZERO ) return RTM_VAL_ZERO; assert( 0 ); return -1; } - -static inline int Rtm_InitWordsNum( int nLats ) { return (nLats >> 4) + ((nLats & 15) > 0); } -static inline int Rtm_InitGetTwo( unsigned * p, int i ) { return (p[i>>4] >> ((i & 15)<<1)) & 3; } -static inline void Rtm_InitSetTwo( unsigned * p, int i, int val ) { p[i>>4] |= (val << ((i & 15)<<1)); } -static inline void Rtm_InitXorTwo( unsigned * p, int i, int val ) { p[i>>4] ^= (val << ((i & 15)<<1)); } - -static inline Rtm_Init_t Rtm_ObjGetFirst1( Rtm_Edg_t * pEdge ) { return pEdge->LData & 3; } -static inline Rtm_Init_t Rtm_ObjGetLast1( Rtm_Edg_t * pEdge ) { return (pEdge->LData >> ((pEdge->nLats-1)<<1)) & 3; } -static inline Rtm_Init_t Rtm_ObjGetOne1( Rtm_Edg_t * pEdge, int i ) { assert( i < (int)pEdge->nLats ); return (pEdge->LData >> (i << 1)) & 3; } -static inline Rtm_Init_t Rtm_ObjRemFirst1( Rtm_Edg_t * pEdge ) { int Val = pEdge->LData & 3; pEdge->LData >>= 2; assert(pEdge->nLats > 0); pEdge->nLats--; return Val; } -static inline Rtm_Init_t Rtm_ObjRemLast1( Rtm_Edg_t * pEdge ) { int Val = (pEdge->LData >> ((pEdge->nLats-1)<<1)) & 3; pEdge->LData ^= Val << ((pEdge->nLats-1)<<1); assert(pEdge->nLats > 0); pEdge->nLats--; return Val; } -static inline void Rtm_ObjAddFirst1( Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { assert( Val > 0 && Val < 4 ); pEdge->LData = (pEdge->LData << 2) | Val; pEdge->nLats++; } -static inline void Rtm_ObjAddLast1( Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { assert( Val > 0 && Val < 4 ); pEdge->LData |= Val << (pEdge->nLats<<1); pEdge->nLats++; } - -static inline Rtm_Init_t Rtm_ObjGetFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return Rtm_InitGetTwo( p->pExtra + pEdge->LData, 0 ); } -static inline Rtm_Init_t Rtm_ObjGetLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return Rtm_InitGetTwo( p->pExtra + pEdge->LData, pEdge->nLats - 1 ); } -static inline Rtm_Init_t Rtm_ObjGetOne2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, int i ) { return Rtm_InitGetTwo( p->pExtra + pEdge->LData, i ); } -static Rtm_Init_t Rtm_ObjRemFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); -static inline Rtm_Init_t Rtm_ObjRemLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Val = Rtm_ObjGetLast2( p, pEdge ); Rtm_InitXorTwo( p->pExtra + pEdge->LData, pEdge->nLats - 1, Val ); pEdge->nLats--; return Val; } -static void Rtm_ObjAddFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ); -static inline void Rtm_ObjAddLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { Rtm_InitSetTwo( p->pExtra + pEdge->LData, pEdge->nLats, Val ); pEdge->nLats++; } - -static void Rtm_ObjTransferToSmall( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); -static void Rtm_ObjTransferToBig( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); -static void Rtm_ObjTransferToBigger( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); - -static inline Rtm_Init_t Rtm_ObjGetFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return pEdge->nLats > 10? Rtm_ObjGetFirst2(p, pEdge) : Rtm_ObjGetFirst1(pEdge); } -static inline Rtm_Init_t Rtm_ObjGetLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return pEdge->nLats > 10? Rtm_ObjGetLast2(p, pEdge) : Rtm_ObjGetLast1(pEdge); } -static inline Rtm_Init_t Rtm_ObjGetOne( Rtm_Man_t * p, Rtm_Edg_t * pEdge, int i ) { return pEdge->nLats > 10? Rtm_ObjGetOne2(p, pEdge, i) : Rtm_ObjGetOne1(pEdge, i); } -static Rtm_Init_t Rtm_ObjRemFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Res = pEdge->nLats > 10 ? Rtm_ObjRemFirst2(p, pEdge) : Rtm_ObjRemFirst1(pEdge); if ( pEdge->nLats == 10 ) Rtm_ObjTransferToSmall(p, pEdge); return Res; } -static Rtm_Init_t Rtm_ObjRemLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Res = pEdge->nLats > 10 ? Rtm_ObjRemLast2(p, pEdge) : Rtm_ObjRemLast1(pEdge); if ( pEdge->nLats == 10 ) Rtm_ObjTransferToSmall(p, pEdge); return Res; } -static void Rtm_ObjAddFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { if ( pEdge->nLats == 10 ) Rtm_ObjTransferToBig(p, pEdge); else if ( (pEdge->nLats & 15) == 15 ) Rtm_ObjTransferToBigger(p, pEdge); if ( pEdge->nLats >= 10 ) Rtm_ObjAddFirst2(p, pEdge, Val); else Rtm_ObjAddFirst1(pEdge, Val); } -static void Rtm_ObjAddLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { if ( pEdge->nLats == 10 ) Rtm_ObjTransferToBig(p, pEdge); else if ( (pEdge->nLats & 15) == 15 ) Rtm_ObjTransferToBigger(p, pEdge); if ( pEdge->nLats >= 10 ) Rtm_ObjAddLast2(p, pEdge, Val); else Rtm_ObjAddLast1(pEdge, Val); } - - -// iterator over the primary inputs -#define Rtm_ManForEachPi( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPis, pObj, i ) -// iterator over the primary outputs -#define Rtm_ManForEachPo( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPos, pObj, i ) -// iterator over all objects, including those currently not used -#define Rtm_ManForEachObj( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vObjs, pObj, i ) -// iterate through the fanins -#define Rtm_ObjForEachFanin( pObj, pFanin, i ) \ - for ( i = 0; i < (int)(pObj)->nFanins && ((pFanin = Rtm_ObjFanin(pObj, i)), 1); i++ ) -// iterate through the fanouts -#define Rtm_ObjForEachFanout( pObj, pFanout, i ) \ - for ( i = 0; i < (int)(pObj)->nFanouts && ((pFanout = Rtm_ObjFanout(pObj, i)), 1); i++ ) -// iterate through the fanin edges -#define Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) \ - for ( i = 0; i < (int)(pObj)->nFanins && ((pEdge = Rtm_ObjEdge(pObj, i)), 1); i++ ) -// iterate through the fanout edges -#define Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) \ - for ( i = 0; i < (int)(pObj)->nFanouts && ((pEdge = Rtm_ObjFanoutEdge(pObj, i)), 1); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transfers from big to small storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rtm_ObjTransferToSmall( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) -{ - assert( pEdge->nLats == 10 ); - pEdge->LData = p->pExtra[pEdge->LData]; -} - -/**Function************************************************************* - - Synopsis [Transfers from small to big storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rtm_ObjTransferToBig( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) -{ - assert( pEdge->nLats == 10 ); - if ( p->nExtraCur + 1 > p->nExtraAlloc ) - { - int nExtraAllocNew = AIG_MAX( 2 * p->nExtraAlloc, 1024 ); - p->pExtra = REALLOC( unsigned, p->pExtra, nExtraAllocNew ); - p->nExtraAlloc = nExtraAllocNew; - } - p->pExtra[p->nExtraCur] = pEdge->LData; - pEdge->LData = p->nExtraCur++; -} - -/**Function************************************************************* - - Synopsis [Transfers to bigger storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rtm_ObjTransferToBigger( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) -{ - int nWords; - assert( (pEdge->nLats & 15) == 15 ); - nWords = (pEdge->nLats + 1) >> 4; - if ( p->nExtraCur + nWords + 1 > p->nExtraAlloc ) - { - int nExtraAllocNew = AIG_MAX( 2 * p->nExtraAlloc, 1024 ); - p->pExtra = REALLOC( unsigned, p->pExtra, nExtraAllocNew ); - p->nExtraAlloc = nExtraAllocNew; - } - memcpy( p->pExtra + p->nExtraCur, p->pExtra + pEdge->LData, sizeof(unsigned) * nWords ); - p->pExtra[p->nExtraCur + nWords] = 0; - pEdge->LData = p->nExtraCur; - p->nExtraCur += nWords + 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rtm_Init_t Rtm_ObjRemFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) -{ - Rtm_Init_t Val = 0, Temp; - unsigned * pB = p->pExtra + pEdge->LData, * pE = pB + Rtm_InitWordsNum( pEdge->nLats-- ) - 1; - while ( pE >= pB ) - { - Temp = *pE & 3; - *pE = (*pE >> 2) | (Val << 30); - Val = Temp; - pE--; - } - assert( Val != 0 ); - return Val; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rtm_ObjAddFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) -{ - unsigned * pB = p->pExtra + pEdge->LData, * pE = pB + Rtm_InitWordsNum( ++pEdge->nLats ); - Rtm_Init_t Temp; - assert( Val != 0 ); - while ( pB < pE ) - { - Temp = *pB >> 30; - *pB = (*pB << 2) | Val; - Val = Temp; - pB++; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rtm_PrintEdge( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) -{ - unsigned LData = pEdge->LData; - printf( "%d : ", pEdge->nLats ); -/* - if ( pEdge->nLats > 10 ) - Extra_PrintBinary( stdout, p->pExtra + pEdge->LData, 2*(pEdge->nLats+1) ); - else - Extra_PrintBinary( stdout, &LData, 2*(pEdge->nLats+1) ); -*/ - printf( "\n" ); -} - - -/**Function************************************************************* - - Synopsis [Allocates the retiming manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rtm_Man_t * Rtm_ManAlloc( Aig_Man_t * p ) -{ - Rtm_Man_t * pRtm; - // start the manager - pRtm = ALLOC( Rtm_Man_t, 1 ); - memset( pRtm, 0, sizeof(Rtm_Man_t) ); - // perform initializations - pRtm->vObjs = Vec_PtrAlloc( Aig_ManObjNum(p) ); - pRtm->vPis = Vec_PtrAlloc( Aig_ManPiNum(p) ); - pRtm->vPos = Vec_PtrAlloc( Aig_ManPoNum(p) ); - pRtm->pMem = Aig_MmFlexStart(); - return pRtm; -} - -/**Function************************************************************* - - Synopsis [Allocates the retiming manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rtm_ManFree( Rtm_Man_t * p ) -{ - Vec_PtrFree( p->vObjs ); - Vec_PtrFree( p->vPis ); - Vec_PtrFree( p->vPos ); - Aig_MmFlexStop( p->pMem, 0 ); - FREE( p->pExtra ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Counts the maximum number of latches on an edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rtm_ManLatchMax( Rtm_Man_t * p ) -{ - Rtm_Obj_t * pObj; - Rtm_Edg_t * pEdge; - int nLatchMax = 0, i, k;//, c, Val; - Rtm_ManForEachObj( p, pObj, i ) - Rtm_ObjForEachFaninEdge( pObj, pEdge, k ) - { -/* - for ( c = 0; c < (int)pEdge->nLats; c++ ) - { - Val = Rtm_ObjGetOne( p, pEdge, c ); - assert( Val == 1 || Val == 2 ); - } -*/ - nLatchMax = AIG_MAX( nLatchMax, (int)pEdge->nLats ); - } - return nLatchMax; -} - -/**Function************************************************************* - - Synopsis [Allocates the retiming object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rtm_Obj_t * Rtm_ObjAlloc( Rtm_Man_t * pRtm, int nFanins, int nFanouts ) -{ - Rtm_Obj_t * pObj; - int Size = sizeof(Rtm_Obj_t) + sizeof(Rtm_Obj_t *) * (nFanins + nFanouts) * 2; - pObj = (Rtm_Obj_t *)Aig_MmFlexEntryFetch( pRtm->pMem, Size ); - memset( pObj, 0, sizeof(Rtm_Obj_t) ); - pObj->Type = (int)(nFanins == 1 && nFanouts == 0); // mark PO - pObj->Num = nFanins; // temporary - pObj->Temp = nFanouts; - pObj->Id = Vec_PtrSize(pRtm->vObjs); - Vec_PtrPush( pRtm->vObjs, pObj ); - return pObj; -} - -/**Function************************************************************* - - Synopsis [Allocates the retiming object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rtm_ObjAddFanin( Rtm_Obj_t * pObj, Rtm_Obj_t * pFanin, int fCompl ) -{ - pObj->pFanio[ 2*pObj->nFanins ] = pFanin; - pObj->pFanio[ 2*pObj->nFanins + 1 ] = NULL; - pFanin->pFanio[ 2*(pFanin->Num + pFanin->nFanouts) ] = pObj; - pFanin->pFanio[ 2*(pFanin->Num + pFanin->nFanouts) + 1 ] = pObj->pFanio + 2*pObj->nFanins + 1; - if ( pObj->nFanins == 0 ) - pObj->fCompl0 = fCompl; - else if ( pObj->nFanins == 1 ) - pObj->fCompl1 = fCompl; - else - assert( 0 ); - pObj->nFanins++; - pFanin->nFanouts++; - assert( pObj->nFanins <= pObj->Num ); - assert( pFanin->nFanouts <= pFanin->Temp ); -} - -/**Function************************************************************* - - Synopsis [Check the possibility of forward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rtm_ObjCheckRetimeFwd( Rtm_Obj_t * pObj ) -{ - Rtm_Edg_t * pEdge; - int i; - Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) - if ( pEdge->nLats == 0 ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Check the possibility of forward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rtm_ObjCheckRetimeBwd( Rtm_Obj_t * pObj ) -{ - Rtm_Edg_t * pEdge; - int i; - Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) - if ( pEdge->nLats == 0 ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Check the possibility of forward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rtm_ObjGetDegreeFwd( Rtm_Obj_t * pObj ) -{ - Rtm_Obj_t * pFanin; - int i, Degree = 0; - Rtm_ObjForEachFanin( pObj, pFanin, i ) - Degree = AIG_MAX( Degree, (int)pFanin->Num ); - return Degree + 1; -} - -/**Function************************************************************* - - Synopsis [Check the possibility of forward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rtm_ObjGetDegreeBwd( Rtm_Obj_t * pObj ) -{ - Rtm_Obj_t * pFanout; - int i, Degree = 0; - Rtm_ObjForEachFanout( pObj, pFanout, i ) - Degree = AIG_MAX( Degree, (int)pFanout->Num ); - return Degree + 1; -} - -/**Function************************************************************* - - Synopsis [Performs forward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rtm_ObjRetimeFwd( Rtm_Man_t * pRtm, Rtm_Obj_t * pObj ) -{ - Rtm_Init_t ValTotal, ValCur; - Rtm_Edg_t * pEdge; - int i; - assert( Rtm_ObjCheckRetimeFwd(pObj) ); - // extract values and compute the result - ValTotal = RTM_VAL_ONE; - Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) - { - ValCur = Rtm_ObjRemFirst( pRtm, pEdge ); - ValCur = Rtm_InitNotCond( ValCur, i? pObj->fCompl1 : pObj->fCompl0 ); - ValTotal = Rtm_InitAnd( ValTotal, ValCur ); - } - // insert the result in the fanout values - Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) - Rtm_ObjAddLast( pRtm, pEdge, ValTotal ); -} - -/**Function************************************************************* - - Synopsis [Performs forward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rtm_ObjRetimeBwd( Rtm_Man_t * pRtm, Rtm_Obj_t * pObj ) -{ - Rtm_Edg_t * pEdge; - int i; - assert( Rtm_ObjCheckRetimeBwd(pObj) ); - // extract values and compute the result - Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) - Rtm_ObjRemLast( pRtm, pEdge ); - // insert the result in the fanout values - Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) - Rtm_ObjAddFirst( pRtm, pEdge, RTM_VAL_VOID ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rtm_ObjMarkAutoFwd_rec( Rtm_Obj_t * pObj ) -{ - Rtm_Obj_t * pFanout; - int i; - if ( pObj->fAuto ) - return; - pObj->fAuto = 1; - Rtm_ObjForEachFanout( pObj, pFanout, i ) - Rtm_ObjMarkAutoFwd_rec( pFanout ); -} - -/**Function************************************************************* - - Synopsis [Marks the nodes unreachable from the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rtm_ManMarkAutoFwd( Rtm_Man_t * pRtm ) -{ - Rtm_Obj_t * pObjRtm; - int i, Counter = 0; - // mark nodes reachable from the PIs - pObjRtm = Vec_PtrEntry( pRtm->vObjs, 0 ); - Rtm_ObjMarkAutoFwd_rec( pObjRtm ); - Rtm_ManForEachPi( pRtm, pObjRtm, i ) - Rtm_ObjMarkAutoFwd_rec( pObjRtm ); - // count the number of autonomous nodes - Rtm_ManForEachObj( pRtm, pObjRtm, i ) - { - pObjRtm->fAuto = !pObjRtm->fAuto; - Counter += pObjRtm->fAuto; - } - // mark the fanins of the autonomous nodes - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rtm_ObjMarkAutoBwd_rec( Rtm_Obj_t * pObj ) -{ - Rtm_Obj_t * pFanin; - int i; - if ( pObj->fAuto ) - return; - pObj->fAuto = 1; - Rtm_ObjForEachFanin( pObj, pFanin, i ) - Rtm_ObjMarkAutoBwd_rec( pFanin ); -} - -/**Function************************************************************* - - Synopsis [Marks the nodes unreachable from the POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rtm_ManMarkAutoBwd( Rtm_Man_t * pRtm ) -{ - Rtm_Obj_t * pObjRtm; - int i, Counter = 0; - // mark nodes reachable from the PIs - pObjRtm = Vec_PtrEntry( pRtm->vObjs, 0 ); - pObjRtm->fAuto = 1; - Rtm_ManForEachPi( pRtm, pObjRtm, i ) - pObjRtm->fAuto = 1; - Rtm_ManForEachPo( pRtm, pObjRtm, i ) - Rtm_ObjMarkAutoBwd_rec( pObjRtm ); - // count the number of autonomous nodes - Rtm_ManForEachObj( pRtm, pObjRtm, i ) - { - pObjRtm->fAuto = !pObjRtm->fAuto; - Counter += pObjRtm->fAuto; - } - // mark the fanins of the autonomous nodes - return Counter; -} - -/**Function************************************************************* - - Synopsis [Derive retiming manager from the given AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rtm_Man_t * Rtm_ManFromAig( Aig_Man_t * p ) -{ - Rtm_Man_t * pRtm; - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - int i; - assert( Aig_ManRegNum(p) > 0 ); - assert( Aig_ManBufNum(p) == 0 ); - // allocate the manager - pRtm = Rtm_ManAlloc( p ); - // allocate objects - pObj = Aig_ManConst1(p); - pObj->pData = Rtm_ObjAlloc( pRtm, 0, pObj->nRefs ); - Aig_ManForEachPiSeq( p, pObj, i ) - { - pObj->pData = Rtm_ObjAlloc( pRtm, 0, pObj->nRefs ); - Vec_PtrPush( pRtm->vPis, pObj->pData ); - } - Aig_ManForEachPoSeq( p, pObj, i ) - { - pObj->pData = Rtm_ObjAlloc( pRtm, 1, 0 ); - Vec_PtrPush( pRtm->vPos, pObj->pData ); - } - Aig_ManForEachLoSeq( p, pObj, i ) - pObj->pData = Rtm_ObjAlloc( pRtm, 1, pObj->nRefs ); - Aig_ManForEachLiSeq( p, pObj, i ) - pObj->pData = Rtm_ObjAlloc( pRtm, 1, 1 ); - Aig_ManForEachNode( p, pObj, i ) - pObj->pData = Rtm_ObjAlloc( pRtm, 2, pObj->nRefs ); - // connect objects - Aig_ManForEachPoSeq( p, pObj, i ) - Rtm_ObjAddFanin( pObj->pData, Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - Aig_ManForEachLiSeq( p, pObj, i ) - Rtm_ObjAddFanin( pObj->pData, Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - Rtm_ObjAddFanin( pObjLo->pData, pObjLi->pData, 0 ); - Aig_ManForEachNode( p, pObj, i ) - { - Rtm_ObjAddFanin( pObj->pData, Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - Rtm_ObjAddFanin( pObj->pData, Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); - } - return pRtm; -} - -/**Function************************************************************* - - Synopsis [Derive AIG manager after retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Rtm_ManToAig_rec( Aig_Man_t * pNew, Rtm_Man_t * pRtm, Rtm_Obj_t * pObjRtm, int * pLatches ) -{ - Rtm_Edg_t * pEdge; - Aig_Obj_t * pRes, * pFanin; - int k, Val; - if ( pObjRtm->pCopy ) - return pObjRtm->pCopy; - // get the inputs - pRes = Aig_ManConst1( pNew ); - Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) - { - if ( pEdge->nLats == 0 ) - pFanin = Rtm_ManToAig_rec( pNew, pRtm, Rtm_ObjFanin(pObjRtm, k), pLatches ); - else - { - Val = Rtm_ObjGetFirst( pRtm, pEdge ); - pFanin = Aig_ManPi( pNew, pLatches[2*pObjRtm->Id + k] + pEdge->nLats - 1 ); - pFanin = Aig_NotCond( pFanin, Val == RTM_VAL_ONE ); - } - pFanin = Aig_NotCond( pFanin, k ? pObjRtm->fCompl1 : pObjRtm->fCompl0 ); - pRes = Aig_And( pNew, pRes, pFanin ); - } - return pObjRtm->pCopy = pRes; -} - -/**Function************************************************************* - - Synopsis [Derive AIG manager after retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Rtm_ManToAig( Rtm_Man_t * pRtm ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObjNew; - Rtm_Obj_t * pObjRtm; - Rtm_Edg_t * pEdge; - int i, k, m, Val, nLatches, * pLatches; - // count latches and mark the first latch on each edge - pLatches = ALLOC( int, 2 * Vec_PtrSize(pRtm->vObjs) ); - nLatches = 0; - Rtm_ManForEachObj( pRtm, pObjRtm, i ) - Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) - { - pLatches[2*pObjRtm->Id + k] = Vec_PtrSize(pRtm->vPis) + nLatches; - nLatches += pEdge->nLats; - } - // create the new manager - pNew = Aig_ManStart( Vec_PtrSize(pRtm->vObjs) + nLatches ); - // create PIs/POs and latches - pObjRtm = Vec_PtrEntry( pRtm->vObjs, 0 ); - pObjRtm->pCopy = Aig_ManConst1(pNew); - Rtm_ManForEachPi( pRtm, pObjRtm, i ) - pObjRtm->pCopy = Aig_ObjCreatePi(pNew); - for ( i = 0; i < nLatches; i++ ) - Aig_ObjCreatePi(pNew); - // create internal nodes - Rtm_ManForEachObj( pRtm, pObjRtm, i ) - Rtm_ManToAig_rec( pNew, pRtm, pObjRtm, pLatches ); - // create POs - Rtm_ManForEachPo( pRtm, pObjRtm, i ) - Aig_ObjCreatePo( pNew, pObjRtm->pCopy ); - // connect latches - Rtm_ManForEachObj( pRtm, pObjRtm, i ) - Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) - { - if ( pEdge->nLats == 0 ) - continue; - pObjNew = Rtm_ObjFanin( pObjRtm, k )->pCopy; - for ( m = 0; m < (int)pEdge->nLats; m++ ) - { - Val = Rtm_ObjGetOne( pRtm, pEdge, pEdge->nLats - 1 - m ); - assert( Val == RTM_VAL_ZERO || Val == RTM_VAL_ONE || Val == RTM_VAL_VOID ); - pObjNew = Aig_NotCond( pObjNew, Val == RTM_VAL_ONE ); - Aig_ObjCreatePo( pNew, pObjNew ); - pObjNew = Aig_ManPi( pNew, pLatches[2*pObjRtm->Id + k] + m ); - pObjNew = Aig_NotCond( pObjNew, Val == RTM_VAL_ONE ); - } -// assert( Aig_Regular(pObjNew)->nRefs > 0 ); - } - free( pLatches ); - pNew->nRegs = nLatches; - // remove useless nodes - Aig_ManCleanup( pNew ); - if ( !Aig_ManCheck( pNew ) ) - printf( "Rtm_ManToAig: The network check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Performs forward retiming with the given limit on depth.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Rtm_ManRetime( Aig_Man_t * p, int fForward, int nStepsMax, int fVerbose ) -{ - Vec_Ptr_t * vQueue; - Aig_Man_t * pNew; - Rtm_Man_t * pRtm; - Rtm_Obj_t * pObj, * pNext; - Aig_Obj_t * pObjAig; - int i, k, nAutos, Degree, DegreeMax = 0; - int clk; - - // create the retiming manager -clk = clock(); - pRtm = Rtm_ManFromAig( p ); - // set registers - Aig_ManForEachLoSeq( p, pObjAig, i ) - Rtm_ObjAddFirst( pRtm, Rtm_ObjEdge(pObjAig->pData, 0), fForward? RTM_VAL_ZERO : RTM_VAL_VOID ); - // detect and mark the autonomous components - if ( fForward ) - nAutos = Rtm_ManMarkAutoFwd( pRtm ); - else - nAutos = Rtm_ManMarkAutoBwd( pRtm ); - if ( fVerbose ) - { - printf( "Detected %d autonomous objects. ", nAutos ); - PRT( "Time", clock() - clk ); - } - - // set the current retiming number - Rtm_ManForEachObj( pRtm, pObj, i ) - { - assert( pObj->nFanins == pObj->Num ); - assert( pObj->nFanouts == pObj->Temp ); - pObj->Num = 0; - } - -clk = clock(); - // put the LOs on the queue - vQueue = Vec_PtrAlloc( 1000 ); - if ( fForward ) - { - Aig_ManForEachLoSeq( p, pObjAig, i ) - { - pObj = pObjAig->pData; - if ( pObj->fAuto ) - continue; - pObj->fMark = 1; - Vec_PtrPush( vQueue, pObj ); - } - } - else - { - Aig_ManForEachLiSeq( p, pObjAig, i ) - { - pObj = pObjAig->pData; - if ( pObj->fAuto ) - continue; - pObj->fMark = 1; - Vec_PtrPush( vQueue, pObj ); - } - } - // perform retiming - DegreeMax = 0; - Vec_PtrForEachEntry( vQueue, pObj, i ) - { - pObj->fMark = 0; - // retime the node - if ( fForward ) - { - Rtm_ObjRetimeFwd( pRtm, pObj ); - // check if its fanouts should be retimed - Rtm_ObjForEachFanout( pObj, pNext, k ) - { - if ( pNext->fMark ) // skip aleady scheduled - continue; - if ( pNext->Type ) // skip POs - continue; - if ( !Rtm_ObjCheckRetimeFwd( pNext ) ) // skip non-retimable - continue; - Degree = Rtm_ObjGetDegreeFwd( pNext ); - DegreeMax = AIG_MAX( DegreeMax, Degree ); - if ( Degree > nStepsMax ) // skip nodes with high degree - continue; - pNext->fMark = 1; - pNext->Num = Degree; - Vec_PtrPush( vQueue, pNext ); - } - } - else - { - Rtm_ObjRetimeBwd( pRtm, pObj ); - // check if its fanouts should be retimed - Rtm_ObjForEachFanin( pObj, pNext, k ) - { - if ( pNext->fMark ) // skip aleady scheduled - continue; - if ( pNext->nFanins == 0 ) // skip PIs - continue; - if ( !Rtm_ObjCheckRetimeBwd( pNext ) ) // skip non-retimable - continue; - Degree = Rtm_ObjGetDegreeBwd( pNext ); - DegreeMax = AIG_MAX( DegreeMax, Degree ); - if ( Degree > nStepsMax ) // skip nodes with high degree - continue; - pNext->fMark = 1; - pNext->Num = Degree; - Vec_PtrPush( vQueue, pNext ); - } - } - } - - if ( fVerbose ) - { - printf( "Performed %d %s latch moves of max depth %d and max latch count %d.\n", - Vec_PtrSize(vQueue), fForward? "fwd":"bwd", DegreeMax, Rtm_ManLatchMax(pRtm) ); - printf( "Memory usage = %d. ", pRtm->nExtraCur ); - PRT( "Time", clock() - clk ); - } - Vec_PtrFree( vQueue ); - - // get the new manager - pNew = Rtm_ManToAig( pRtm ); - pNew->pName = Aig_UtilStrsav( p->pName ); - Rtm_ManFree( pRtm ); - // group the registers -clk = clock(); - pNew = Aig_ManReduceLaches( pNew, fVerbose ); - if ( fVerbose ) - { - PRT( "Register sharing time", clock() - clk ); - } - return pNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigScl.c b/src/aig/aig/aigScl.c deleted file mode 100644 index abd424c1..00000000 --- a/src/aig/aig/aigScl.c +++ /dev/null @@ -1,399 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigScl.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Sequential cleanup.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigScl.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Remaps the manager.] - - Description [Map in the array specifies for each CI nodes the node that - should be used after remapping.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManRemap( Aig_Man_t * p, Vec_Ptr_t * vMap ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj, * pObjMapped; - int i; - // create the new manager - pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->nRegs = p->nRegs; - pNew->nAsserts = p->nAsserts; - if ( p->vFlopNums ) - pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); - // create the PIs - Aig_ManCleanData( p ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePi(pNew); - // implement the mapping - Aig_ManForEachPi( p, pObj, i ) - { - pObjMapped = Vec_PtrEntry( vMap, i ); - pObj->pData = Aig_NotCond( Aig_Regular(pObjMapped)->pData, Aig_IsComplement(pObjMapped) ); - } - // duplicate internal nodes - Aig_ManForEachObj( p, pObj, i ) - if ( Aig_ObjIsBuf(pObj) ) - pObj->pData = Aig_ObjChild0Copy(pObj); - else if ( Aig_ObjIsNode(pObj) ) - pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - // add the POs - Aig_ManForEachPo( p, pObj, i ) - Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) ); - assert( Aig_ManNodeNum(p) >= Aig_ManNodeNum(pNew) ); - // check the resulting network - if ( !Aig_ManCheck(pNew) ) - printf( "Aig_ManDup(): The check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Returns the number of dangling nodes removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManSeqCleanup_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - Aig_ObjSetTravIdCurrent(p, pObj); - // collect latch input corresponding to unmarked PI (latch output) - if ( Aig_ObjIsPi(pObj) ) - { - Vec_PtrPush( vNodes, pObj->pNext ); - return; - } - if ( Aig_ObjIsPo(pObj) ) - { - Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes ); - return; - } - assert( Aig_ObjIsNode(pObj) ); - Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes ); - Aig_ManSeqCleanup_rec( p, Aig_ObjFanin1(pObj), vNodes ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of dangling nodes removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManSeqCleanup( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes, * vCis, * vCos; - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - int i, nTruePis, nTruePos; - assert( Aig_ManBufNum(p) == 0 ); - - // mark the PIs - Aig_ManIncrementTravId( p ); - Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); - Aig_ManForEachPiSeq( p, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - - // prepare to collect nodes reachable from POs - vNodes = Vec_PtrAlloc( 100 ); - Aig_ManForEachPoSeq( p, pObj, i ) - Vec_PtrPush( vNodes, pObj ); - - // remember latch inputs in latch outputs - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - pObjLo->pNext = pObjLi; - // mark the nodes reachable from these nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - Aig_ManSeqCleanup_rec( p, pObj, vNodes ); - assert( Vec_PtrSize(vNodes) <= Aig_ManPoNum(p) ); - // clean latch output pointers - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - pObjLo->pNext = NULL; - - // if some latches are removed, update PIs/POs - if ( Vec_PtrSize(vNodes) < Aig_ManPoNum(p) ) - { - if ( p->vFlopNums ) - { - int nTruePos = Aig_ManPoNum(p)-Aig_ManRegNum(p); - // remember numbers of flops in the flops - Aig_ManForEachLiSeq( p, pObj, i ) - pObj->pNext = (void *)Vec_IntEntry( p->vFlopNums, i - nTruePos ); - // reset the flop numbers - Vec_PtrForEachEntryStart( vNodes, pObj, i, nTruePos ) - Vec_IntWriteEntry( p->vFlopNums, i - nTruePos, (int)pObj->pNext ); - Vec_IntShrink( p->vFlopNums, Vec_PtrSize(vNodes) - nTruePos ); - // clean the next pointer - Aig_ManForEachLiSeq( p, pObj, i ) - pObj->pNext = NULL; - } - // collect new CIs/COs - vCis = Vec_PtrAlloc( Aig_ManPiNum(p) ); - Aig_ManForEachPi( p, pObj, i ) - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - Vec_PtrPush( vCis, pObj ); - else - { - Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); -// Aig_ManRecycleMemory( p, pObj ); - } - vCos = Vec_PtrAlloc( Aig_ManPoNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - Vec_PtrPush( vCos, pObj ); - else - { - Aig_ObjDisconnect( p, pObj ); - Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); -// Aig_ManRecycleMemory( p, pObj ); - } - // remember the number of true PIs/POs - nTruePis = Aig_ManPiNum(p) - Aig_ManRegNum(p); - nTruePos = Aig_ManPoNum(p) - Aig_ManRegNum(p); - // set the new number of registers - p->nRegs -= Aig_ManPoNum(p) - Vec_PtrSize(vNodes); - // create new PIs/POs - assert( Vec_PtrSize(vCis) == nTruePis + p->nRegs ); - assert( Vec_PtrSize(vCos) == nTruePos + p->nRegs ); - Vec_PtrFree( p->vPis ); p->vPis = vCis; - Vec_PtrFree( p->vPos ); p->vPos = vCos; - p->nObjs[AIG_OBJ_PI] = Vec_PtrSize( p->vPis ); - p->nObjs[AIG_OBJ_PO] = Vec_PtrSize( p->vPos ); - - } - Vec_PtrFree( vNodes ); - // remove dangling nodes - return Aig_ManCleanup( p ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of dangling nodes removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManCountMergeRegs( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj, * pFanin; - int i, Counter = 0, Const0 = 0, Const1 = 0; - Aig_ManIncrementTravId( p ); - Aig_ManForEachLiSeq( p, pObj, i ) - { - pFanin = Aig_ObjFanin0(pObj); - if ( Aig_ObjIsConst1(pFanin) ) - { - if ( Aig_ObjFaninC0(pObj) ) - Const0++; - else - Const1++; - } - if ( Aig_ObjIsTravIdCurrent(p, pFanin) ) - continue; - Aig_ObjSetTravIdCurrent(p, pFanin); - Counter++; - } - printf( "Regs = %d. Fanins = %d. Const0 = %d. Const1 = %d.\n", - Aig_ManRegNum(p), Counter, Const0, Const1 ); - return 0; -} - - -/**Function************************************************************* - - Synopsis [Checks how many latches can be reduced.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManReduceLachesCount( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj, * pFanin; - int i, Counter = 0, Diffs = 0; - assert( Aig_ManRegNum(p) > 0 ); - Aig_ManForEachObj( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - Aig_ManForEachLiSeq( p, pObj, i ) - { - pFanin = Aig_ObjFanin0(pObj); - if ( Aig_ObjFaninC0(pObj) ) - { - if ( pFanin->fMarkB ) - Counter++; - else - pFanin->fMarkB = 1; - } - else - { - if ( pFanin->fMarkA ) - Counter++; - else - pFanin->fMarkA = 1; - } - } - // count fanins that have both attributes - Aig_ManForEachLiSeq( p, pObj, i ) - { - pFanin = Aig_ObjFanin0(pObj); - Diffs += pFanin->fMarkA && pFanin->fMarkB; - pFanin->fMarkA = pFanin->fMarkB = 0; - } -// printf( "Diffs = %d.\n", Diffs ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Reduces the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManReduceLachesOnce( Aig_Man_t * p ) -{ - Vec_Ptr_t * vMap; - Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pFanin; - int * pMapping, i; - // start mapping by adding the true PIs - vMap = Vec_PtrAlloc( Aig_ManPiNum(p) ); - Aig_ManForEachPiSeq( p, pObj, i ) - Vec_PtrPush( vMap, pObj ); - // create mapping of fanin nodes into the corresponding latch outputs - pMapping = ALLOC( int, 2 * Aig_ManObjNumMax(p) ); - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - { - pFanin = Aig_ObjFanin0(pObjLi); - if ( Aig_ObjFaninC0(pObjLi) ) - { - if ( pFanin->fMarkB ) - { - Vec_PtrPush( vMap, Aig_ManLo(p, pMapping[2*pFanin->Id + 1]) ); - } - else - { - pFanin->fMarkB = 1; - pMapping[2*pFanin->Id + 1] = i; - Vec_PtrPush( vMap, pObjLo ); - } - } - else - { - if ( pFanin->fMarkA ) - { - Vec_PtrPush( vMap, Aig_ManLo(p, pMapping[2*pFanin->Id]) ); - } - else - { - pFanin->fMarkA = 1; - pMapping[2*pFanin->Id] = i; - Vec_PtrPush( vMap, pObjLo ); - } - } - } - free( pMapping ); - Aig_ManForEachLiSeq( p, pObj, i ) - { - pFanin = Aig_ObjFanin0(pObj); - pFanin->fMarkA = pFanin->fMarkB = 0; - } - return vMap; -} - -/**Function************************************************************* - - Synopsis [Reduces the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManReduceLaches( Aig_Man_t * p, int fVerbose ) -{ - Aig_Man_t * pTemp; - Vec_Ptr_t * vMap; - int nSaved, nCur; - for ( nSaved = 0; nCur = Aig_ManReduceLachesCount(p); nSaved += nCur ) - { - if ( fVerbose ) - { - printf( "Saved = %5d. ", nCur ); - printf( "RBeg = %5d. NBeg = %6d. ", Aig_ManRegNum(p), Aig_ManNodeNum(p) ); - } - vMap = Aig_ManReduceLachesOnce( p ); - p = Aig_ManRemap( pTemp = p, vMap ); - Aig_ManStop( pTemp ); - Vec_PtrFree( vMap ); - Aig_ManSeqCleanup( p ); - if ( fVerbose ) - { - printf( "REnd = %5d. NEnd = %6d. ", Aig_ManRegNum(p), Aig_ManNodeNum(p) ); - printf( "\n" ); - } - if ( p->nRegs == 0 ) - break; - } - return p; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigSeq.c b/src/aig/aig/aigSeq.c deleted file mode 100644 index d296d339..00000000 --- a/src/aig/aig/aigSeq.c +++ /dev/null @@ -1,502 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigSeq.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Sequential strashing.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigSeq.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Converts combinational AIG manager into a sequential one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManSeqStrashConvert( Aig_Man_t * p, int nLatches, int * pInits ) -{ - Aig_Obj_t * pObjLi, * pObjLo, * pLatch; - int i; - assert( Vec_PtrSize( p->vBufs ) == 0 ); - // collect the POs to be converted into latches - for ( i = 0; i < nLatches; i++ ) - { - // get the corresponding PI/PO pair - pObjLi = Aig_ManPo( p, Aig_ManPoNum(p) - nLatches + i ); - pObjLo = Aig_ManPi( p, Aig_ManPiNum(p) - nLatches + i ); - // create latch - pLatch = Aig_Latch( p, Aig_ObjChild0(pObjLi), pInits? pInits[i] : 0 ); - // recycle the old PO object - Aig_ObjDisconnect( p, pObjLi ); - Vec_PtrWriteEntry( p->vObjs, pObjLi->Id, NULL ); - Aig_ManRecycleMemory( p, pObjLi ); - // convert the corresponding PI to be a buffer and connect it to the latch - pObjLo->Type = AIG_OBJ_BUF; - Aig_ObjConnect( p, pObjLo, pLatch, NULL ); - // save the buffer -// Vec_PtrPush( p->vBufs, pObjLo ); - } - // shrink the arrays - Vec_PtrShrink( p->vPis, Aig_ManPiNum(p) - nLatches ); - Vec_PtrShrink( p->vPos, Aig_ManPoNum(p) - nLatches ); - // update the counters of different objects - p->nObjs[AIG_OBJ_PI] -= nLatches; - p->nObjs[AIG_OBJ_PO] -= nLatches; - p->nObjs[AIG_OBJ_BUF] += nLatches; -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDfsSeq_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( pObj == NULL ) - return; - if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) - return; - Aig_ObjSetTravIdCurrent( p, pObj ); - if ( Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) - return; - Aig_ManDfsSeq_rec( p, Aig_ObjFanin0(pObj), vNodes ); - Aig_ManDfsSeq_rec( p, Aig_ObjFanin1(pObj), vNodes ); -// if ( (Aig_ObjFanin0(pObj) == NULL || Aig_ObjIsBuf(Aig_ObjFanin0(pObj))) && -// (Aig_ObjFanin1(pObj) == NULL || Aig_ObjIsBuf(Aig_ObjFanin1(pObj))) ) - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManDfsSeq( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - Aig_ManIncrementTravId( p ); - vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - Aig_ManDfsSeq_rec( p, Aig_ObjFanin0(pObj), vNodes ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDfsUnreach_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( pObj == NULL ) - return; - if ( Aig_ObjIsTravIdPrevious(p, pObj) || Aig_ObjIsTravIdCurrent(p, pObj) ) - return; - Aig_ObjSetTravIdPrevious( p, pObj ); // assume unknown - Aig_ManDfsUnreach_rec( p, Aig_ObjFanin0(pObj), vNodes ); - Aig_ManDfsUnreach_rec( p, Aig_ObjFanin1(pObj), vNodes ); - if ( Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin0(pObj)) && - (Aig_ObjFanin1(pObj) == NULL || Aig_ObjIsTravIdPrevious(p, Aig_ObjFanin1(pObj))) ) - Vec_PtrPush( vNodes, pObj ); - else - Aig_ObjSetTravIdCurrent( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes unreachable from PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManDfsUnreach( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj, * pFanin; - int i, k;//, RetValue; - // collect unreachable nodes - Aig_ManIncrementTravId( p ); - Aig_ManIncrementTravId( p ); - // mark the constant and PIs - Aig_ObjSetTravIdPrevious( p, Aig_ManConst1(p) ); - Aig_ManForEachPi( p, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - // curr marks visited nodes reachable from PIs - // prev marks visited nodes unreachable or unknown - - // collect the unreachable nodes - vNodes = Vec_PtrAlloc( 32 ); - Aig_ManForEachPo( p, pObj, i ) - Aig_ManDfsUnreach_rec( p, Aig_ObjFanin0(pObj), vNodes ); - - // refine resulting nodes - do - { - k = 0; - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - assert( Aig_ObjIsTravIdPrevious(p, pObj) ); - if ( Aig_ObjIsLatch(pObj) || Aig_ObjIsBuf(pObj) ) - { - pFanin = Aig_ObjFanin0(pObj); - assert( Aig_ObjIsTravIdPrevious(p, pFanin) || Aig_ObjIsTravIdCurrent(p, pFanin) ); - if ( Aig_ObjIsTravIdCurrent(p, pFanin) ) - { - Aig_ObjSetTravIdCurrent( p, pObj ); - continue; - } - } - else // AND gate - { - assert( Aig_ObjIsNode(pObj) ); - pFanin = Aig_ObjFanin0(pObj); - assert( Aig_ObjIsTravIdPrevious(p, pFanin) || Aig_ObjIsTravIdCurrent(p, pFanin) ); - if ( Aig_ObjIsTravIdCurrent(p, pFanin) ) - { - Aig_ObjSetTravIdCurrent( p, pObj ); - continue; - } - pFanin = Aig_ObjFanin1(pObj); - assert( Aig_ObjIsTravIdPrevious(p, pFanin) || Aig_ObjIsTravIdCurrent(p, pFanin) ); - if ( Aig_ObjIsTravIdCurrent(p, pFanin) ) - { - Aig_ObjSetTravIdCurrent( p, pObj ); - continue; - } - } - // write it back - Vec_PtrWriteEntry( vNodes, k++, pObj ); - } - Vec_PtrShrink( vNodes, k ); - } - while ( k < i ); - -// if ( Vec_PtrSize(vNodes) > 0 ) -// printf( "Found %d unreachable.\n", Vec_PtrSize(vNodes) ); - return vNodes; - -/* - // the resulting array contains all unreachable nodes except const 1 - if ( Vec_PtrSize(vNodes) == 0 ) - { - Vec_PtrFree( vNodes ); - return 0; - } - RetValue = Vec_PtrSize(vNodes); - - // mark these nodes - Aig_ManIncrementTravId( p ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - Vec_PtrFree( vNodes ); - return RetValue; -*/ -} - - -/**Function************************************************************* - - Synopsis [Removes nodes that do not fanout into POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManRemoveUnmarked( Aig_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i, RetValue; - // collect unmarked nodes - vNodes = Vec_PtrAlloc( 100 ); - Aig_ManForEachObj( p, pObj, i ) - { - if ( Aig_ObjIsTerm(pObj) ) - continue; - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - continue; -//Aig_ObjPrintVerbose( pObj, 0 ); - Aig_ObjDisconnect( p, pObj ); - Vec_PtrPush( vNodes, pObj ); - } - if ( Vec_PtrSize(vNodes) == 0 ) - { - Vec_PtrFree( vNodes ); - return 0; - } - // remove the dangling objects - RetValue = Vec_PtrSize(vNodes); - Vec_PtrForEachEntry( vNodes, pObj, i ) - Aig_ObjDelete( p, pObj ); -// printf( "Removed %d dangling.\n", Vec_PtrSize(vNodes) ); - Vec_PtrFree( vNodes ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Rehashes the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManSeqRehashOne( Aig_Man_t * p, Vec_Ptr_t * vNodes, Vec_Ptr_t * vUnreach ) -{ - Aig_Obj_t * pObj, * pObjNew, * pFanin0, * pFanin1; - int i, RetValue = 0, Counter = 0, Counter2 = 0; - - // mark the unreachable nodes - Aig_ManIncrementTravId( p ); - Vec_PtrForEachEntry( vUnreach, pObj, i ) - Aig_ObjSetTravIdCurrent(p, pObj); -/* - // count the number of unreachable object connections - // that is the number of unreachable objects connected to main objects - Aig_ManForEachObj( p, pObj, i ) - { - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - continue; - - pFanin0 = Aig_ObjFanin0(pObj); - if ( pFanin0 == NULL ) - continue; - if ( Aig_ObjIsTravIdCurrent(p, pFanin0) ) - pFanin0->fMarkA = 1; - - pFanin1 = Aig_ObjFanin1(pObj); - if ( pFanin1 == NULL ) - continue; - if ( Aig_ObjIsTravIdCurrent(p, pFanin1) ) - pFanin1->fMarkA = 1; - } - - // count the objects - Aig_ManForEachObj( p, pObj, i ) - Counter2 += pObj->fMarkA, pObj->fMarkA = 0; - printf( "Connections = %d.\n", Counter2 ); -*/ - - // go through the nodes while skipping unreachable - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - // skip nodes unreachable from the PIs - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - continue; - // process the node - if ( Aig_ObjIsPo(pObj) ) - { - if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ) - continue; - pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); - Aig_ObjPatchFanin0( p, pObj, pFanin0 ); - continue; - } - if ( Aig_ObjIsLatch(pObj) ) - { - if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ) - continue; - pObjNew = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); - pObjNew = Aig_Latch( p, pObjNew, 0 ); - Aig_ObjReplace( p, pObj, pObjNew, 1, 0 ); - RetValue = 1; - Counter++; - continue; - } - if ( Aig_ObjIsNode(pObj) ) - { - if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) && !Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) ) - continue; - pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); - pFanin1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); - pObjNew = Aig_And( p, pFanin0, pFanin1 ); - Aig_ObjReplace( p, pObj, pObjNew, 1, 0 ); - RetValue = 1; - Counter++; - continue; - } - } -// printf( "Rehashings = %d.\n", Counter++ ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [If AIG contains buffers, this procedure removes them.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManRemoveBuffers( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObjNew, * pFanin0, * pFanin1; - int i; - if ( Aig_ManBufNum(p) == 0 ) - return; - Aig_ManForEachObj( p, pObj, i ) - { - if ( Aig_ObjIsPo(pObj) ) - { - if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ) - continue; - pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); - Aig_ObjPatchFanin0( p, pObj, pFanin0 ); - } - else if ( Aig_ObjIsLatch(pObj) ) - { - if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ) - continue; - pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); - pObjNew = Aig_Latch( p, pFanin0, 0 ); - Aig_ObjReplace( p, pObj, pObjNew, 0, 0 ); - } - else if ( Aig_ObjIsAnd(pObj) ) - { - if ( !Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) && !Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) ) - continue; - pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); - pFanin1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); - pObjNew = Aig_And( p, pFanin0, pFanin1 ); - Aig_ObjReplace( p, pObj, pObjNew, 0, 0 ); - } - } - assert( Aig_ManBufNum(p) == 0 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManSeqStrash( Aig_Man_t * p, int nLatches, int * pInits ) -{ - Vec_Ptr_t * vNodes, * vUnreach; -// Aig_Obj_t * pObj, * pFanin; -// int i; - int Iter, RetValue = 1; - - // create latches out of the additional PI/PO pairs - Aig_ManSeqStrashConvert( p, nLatches, pInits ); - - // iteratively rehash the network - for ( Iter = 0; RetValue; Iter++ ) - { -// Aig_ManPrintStats( p ); -/* - Aig_ManForEachObj( p, pObj, i ) - { - assert( pObj->Type > 0 ); - pFanin = Aig_ObjFanin0(pObj); - assert( pFanin == NULL || pFanin->Type > 0 ); - pFanin = Aig_ObjFanin1(pObj); - assert( pFanin == NULL || pFanin->Type > 0 ); - } -*/ - // mark nodes unreachable from the PIs - vUnreach = Aig_ManDfsUnreach( p ); - if ( Iter == 0 && Vec_PtrSize(vUnreach) > 0 ) - printf( "Unreachable objects = %d.\n", Vec_PtrSize(vUnreach) ); - // collect nodes reachable from the POs - vNodes = Aig_ManDfsSeq( p ); - // remove nodes unreachable from the POs - if ( Iter == 0 ) - Aig_ManRemoveUnmarked( p ); - // continue rehashing as long as there are changes - RetValue = Aig_ManSeqRehashOne( p, vNodes, vUnreach ); - Vec_PtrFree( vNodes ); - Vec_PtrFree( vUnreach ); - } - - // perform the final cleanup - Aig_ManIncrementTravId( p ); - vNodes = Aig_ManDfsSeq( p ); - Aig_ManRemoveUnmarked( p ); - Vec_PtrFree( vNodes ); - // remove buffers if they are left -// Aig_ManRemoveBuffers( p ); - - // clean up - if ( !Aig_ManCheck( p ) ) - { - printf( "Aig_ManSeqStrash: The network check has failed.\n" ); - return 0; - } - return 1; - -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigShow.c b/src/aig/aig/aigShow.c deleted file mode 100644 index 96b0e37f..00000000 --- a/src/aig/aig/aigShow.c +++ /dev/null @@ -1,356 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyShow.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Visualization of HAIG.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes the graph structure of AIG for DOT.] - - Description [Useful for graph visualization using tools such as GraphViz: - http://www.graphviz.org/] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_WriteDotAig( Aig_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ) -{ - FILE * pFile; - Aig_Obj_t * pNode;//, * pTemp, * pPrev; - int LevelMax, Level, i; - - if ( Aig_ManNodeNum(pMan) > 200 ) - { - fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" ); - return; - } - if ( (pFile = fopen( pFileName, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); - return; - } - - // mark the nodes - if ( vBold ) - Vec_PtrForEachEntry( vBold, pNode, i ) - pNode->fMarkB = 1; - - // compute levels -// LevelMax = 1 + Aig_ManSetLevels( pMan, fHaig ); - LevelMax = 1 + Aig_ManLevels( pMan ); - Aig_ManForEachPo( pMan, pNode, i ) - pNode->Level = LevelMax; - - // write the DOT header - fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "digraph AIG {\n" ); - fprintf( pFile, "size = \"7.5,10\";\n" ); -// fprintf( pFile, "ranksep = 0.5;\n" ); -// fprintf( pFile, "nodesep = 0.5;\n" ); - fprintf( pFile, "center = true;\n" ); -// fprintf( pFile, "orientation = landscape;\n" ); -// fprintf( pFile, "edge [fontsize = 10];\n" ); -// fprintf( pFile, "edge [dir = none];\n" ); - fprintf( pFile, "edge [dir = back];\n" ); - fprintf( pFile, "\n" ); - - // labels on the left of the picture - fprintf( pFile, "{\n" ); - fprintf( pFile, " node [shape = plaintext];\n" ); - fprintf( pFile, " edge [style = invis];\n" ); - fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); - fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); - // generate node names with labels - for ( Level = LevelMax; Level >= 0; Level-- ) - { - // the visible node name - fprintf( pFile, " Level%d", Level ); - fprintf( pFile, " [label = " ); - // label name - fprintf( pFile, "\"" ); - fprintf( pFile, "\"" ); - fprintf( pFile, "];\n" ); - } - - // genetate the sequence of visible/invisible nodes to mark levels - fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); - for ( Level = LevelMax; Level >= 0; Level-- ) - { - // the visible node name - fprintf( pFile, " Level%d", Level ); - // the connector - if ( Level != 0 ) - fprintf( pFile, " ->" ); - else - fprintf( pFile, ";" ); - } - fprintf( pFile, "\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate title box on top - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - fprintf( pFile, " LevelTitle1;\n" ); - fprintf( pFile, " title1 [shape=plaintext,\n" ); - fprintf( pFile, " fontsize=20,\n" ); - fprintf( pFile, " fontname = \"Times-Roman\",\n" ); - fprintf( pFile, " label=\"" ); - fprintf( pFile, "%s", "AIG structure visualized by ABC" ); - fprintf( pFile, "\\n" ); - fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); -// fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); - fprintf( pFile, "\"\n" ); - fprintf( pFile, " ];\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate statistics box - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - fprintf( pFile, " LevelTitle2;\n" ); - fprintf( pFile, " title2 [shape=plaintext,\n" ); - fprintf( pFile, " fontsize=18,\n" ); - fprintf( pFile, " fontname = \"Times-Roman\",\n" ); - fprintf( pFile, " label=\"" ); - fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Aig_ManNodeNum(pMan), LevelMax ); - fprintf( pFile, "\\n" ); - fprintf( pFile, "\"\n" ); - fprintf( pFile, " ];\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate the COs - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", LevelMax ); - // generate the CO nodes - Aig_ManForEachPo( pMan, pNode, i ) - { -/* - if ( fHaig || pNode->pEquiv == NULL ) - fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, - (Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") ); - else - fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, - (Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":""), - Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); -*/ - fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); - - fprintf( pFile, ", shape = %s", (Aig_ObjIsLatch(pNode)? "box":"invtriangle") ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate nodes of each rank - for ( Level = LevelMax - 1; Level > 0; Level-- ) - { - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", Level ); - Aig_ManForEachObj( pMan, pNode, i ) - { - if ( (int)pNode->Level != Level ) - continue; -/* - if ( fHaig || pNode->pEquiv == NULL ) - fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); - else - fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, - Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); -*/ - fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); - - fprintf( pFile, ", shape = ellipse" ); - if ( vBold && pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - } - - // generate the CI nodes - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", 0 ); - // generate constant node - if ( Aig_ObjRefs(Aig_ManConst1(pMan)) > 0 ) - { - pNode = Aig_ManConst1(pMan); - // check if the costant node is present - fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); - fprintf( pFile, ", shape = ellipse" ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - // generate the CI nodes - Aig_ManForEachPi( pMan, pNode, i ) - { -/* - if ( fHaig || pNode->pEquiv == NULL ) - fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, - (Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":"") ); - else - fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, - (Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":""), - Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); -*/ - fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); - - fprintf( pFile, ", shape = %s", (Aig_ObjIsLatch(pNode)? "box":"triangle") ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate invisible edges from the square down - fprintf( pFile, "title1 -> title2 [style = invis];\n" ); - Aig_ManForEachPo( pMan, pNode, i ) - fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") ); - - // generate edges - Aig_ManForEachObj( pMan, pNode, i ) - { - if ( !Aig_ObjIsNode(pNode) && !Aig_ObjIsPo(pNode) && !Aig_ObjIsBuf(pNode) ) - continue; - // generate the edge from this node to the next - fprintf( pFile, "Node%d%s", pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d%s", Aig_ObjFaninId0(pNode), (Aig_ObjIsLatch(Aig_ObjFanin0(pNode))? "_out":"") ); - fprintf( pFile, " [" ); - fprintf( pFile, "style = %s", Aig_ObjFaninC0(pNode)? "dotted" : "bold" ); -// if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 ) -// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); - fprintf( pFile, "]" ); - fprintf( pFile, ";\n" ); - if ( !Aig_ObjIsNode(pNode) ) - continue; - // generate the edge from this node to the next - fprintf( pFile, "Node%d", pNode->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d%s", Aig_ObjFaninId1(pNode), (Aig_ObjIsLatch(Aig_ObjFanin1(pNode))? "_out":"") ); - fprintf( pFile, " [" ); - fprintf( pFile, "style = %s", Aig_ObjFaninC1(pNode)? "dotted" : "bold" ); -// if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 ) -// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); - fprintf( pFile, "]" ); - fprintf( pFile, ";\n" ); -/* - // generate the edges between the equivalent nodes - if ( fHaig && pNode->pEquiv && Aig_ObjRefs(pNode) > 0 ) - { - pPrev = pNode; - for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Aig_Regular(pTemp->pEquiv) ) - { - fprintf( pFile, "Node%d", pPrev->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d", pTemp->Id ); - fprintf( pFile, " [style = %s]", Aig_IsComplement(pTemp->pEquiv)? "dotted" : "bold" ); - fprintf( pFile, ";\n" ); - pPrev = pTemp; - } - // connect the last node with the first - fprintf( pFile, "Node%d", pPrev->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d", pNode->Id ); - fprintf( pFile, " [style = %s]", Aig_IsComplement(pPrev->pEquiv)? "dotted" : "bold" ); - fprintf( pFile, ";\n" ); - } -*/ - } - - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - fclose( pFile ); - - // unmark nodes - if ( vBold ) - Vec_PtrForEachEntry( vBold, pNode, i ) - pNode->fMarkB = 0; - - Aig_ManForEachPo( pMan, pNode, i ) - pNode->Level = Aig_ObjFanin0(pNode)->Level; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) -{ - extern void Abc_ShowFile( char * FileNameDot ); - static Counter = 0; - char FileNameDot[200]; - FILE * pFile; - // create the file name -// Aig_ShowGetFileName( pMan->pName, FileNameDot ); - sprintf( FileNameDot, "temp%02d.dot", Counter++ ); - // check that the file can be opened - if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); - return; - } - fclose( pFile ); - // generate the file - Aig_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); - // visualize the file - Abc_ShowFile( FileNameDot ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigTable.c b/src/aig/aig/aigTable.c deleted file mode 100644 index 94593d70..00000000 --- a/src/aig/aig/aigTable.c +++ /dev/null @@ -1,268 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigTable.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Structural hashing table.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigTable.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// hashing the node -static unsigned long Aig_Hash( Aig_Obj_t * pObj, int TableSize ) -{ - unsigned long Key = Aig_ObjIsExor(pObj) * 1699; - Key ^= Aig_ObjFanin0(pObj)->Id * 7937; - Key ^= Aig_ObjFanin1(pObj)->Id * 2971; - Key ^= Aig_ObjFaninC0(pObj) * 911; - Key ^= Aig_ObjFaninC1(pObj) * 353; - return Key % TableSize; -} - -// returns the place where this node is stored (or should be stored) -static Aig_Obj_t ** Aig_TableFind( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t ** ppEntry; - if ( Aig_ObjIsLatch(pObj) ) - { - assert( Aig_ObjChild0(pObj) && Aig_ObjChild1(pObj) == NULL ); - } - else - { - assert( Aig_ObjChild0(pObj) && Aig_ObjChild1(pObj) ); - assert( Aig_ObjFanin0(pObj)->Id < Aig_ObjFanin1(pObj)->Id ); - } - for ( ppEntry = p->pTable + Aig_Hash(pObj, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) - if ( *ppEntry == pObj ) - return ppEntry; - assert( *ppEntry == NULL ); - return ppEntry; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [Typically this procedure should not be called.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TableResize( Aig_Man_t * p ) -{ - Aig_Obj_t * pEntry, * pNext; - Aig_Obj_t ** pTableOld, ** ppPlace; - int nTableSizeOld, Counter, i, clk; -clk = clock(); - // save the old table - pTableOld = p->pTable; - nTableSizeOld = p->nTableSize; - // get the new table - p->nTableSize = Aig_PrimeCudd( 2 * Aig_ManNodeNum(p) ); - p->pTable = ALLOC( Aig_Obj_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < nTableSizeOld; i++ ) - for ( pEntry = pTableOld[i], pNext = pEntry? pEntry->pNext : NULL; - pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL ) - { - // get the place where this entry goes in the table - ppPlace = Aig_TableFind( p, pEntry ); - assert( *ppPlace == NULL ); // should not be there - // add the entry to the list - *ppPlace = pEntry; - pEntry->pNext = NULL; - Counter++; - } - assert( Counter == Aig_ManNodeNum(p) ); -// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); -// PRT( "Time", clock() - clk ); - // replace the table and the parameters - free( pTableOld ); -} - -/**Function************************************************************* - - Synopsis [Checks if node with the given attributes is in the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ) -{ - Aig_Obj_t * pEntry; - assert( !Aig_IsComplement(pGhost) ); - if ( pGhost->Type == AIG_OBJ_LATCH ) - { - assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) == NULL ); - if ( !Aig_ObjRefs(Aig_ObjFanin0(pGhost)) ) - return NULL; - } - else - { - assert( pGhost->Type == AIG_OBJ_AND ); - assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) ); - assert( Aig_ObjFanin0(pGhost)->Id < Aig_ObjFanin1(pGhost)->Id ); - if ( !Aig_ObjRefs(Aig_ObjFanin0(pGhost)) || !Aig_ObjRefs(Aig_ObjFanin1(pGhost)) ) - return NULL; - } - for ( pEntry = p->pTable[Aig_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext ) - { - if ( Aig_ObjChild0(pEntry) == Aig_ObjChild0(pGhost) && - Aig_ObjChild1(pEntry) == Aig_ObjChild1(pGhost) && - Aig_ObjType(pEntry) == Aig_ObjType(pGhost) ) - return pEntry; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Checks if node with the given attributes is in the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 ) -{ - Aig_Obj_t * pGhost; - // consider simple cases - if ( pFanin0 == pFanin1 ) - return pFanin0; - if ( pFanin0 == Aig_Not(pFanin1) ) - return Aig_ManConst0(p); - if ( Aig_Regular(pFanin0) == Aig_ManConst1(p) ) - return pFanin0 == Aig_ManConst1(p) ? pFanin1 : Aig_ManConst0(p); - if ( Aig_Regular(pFanin1) == Aig_ManConst1(p) ) - return pFanin1 == Aig_ManConst1(p) ? pFanin0 : Aig_ManConst0(p); - pGhost = Aig_ObjCreateGhost( p, pFanin0, pFanin1, AIG_OBJ_AND ); - return Aig_TableLookup( p, pGhost ); -} - -/**Function************************************************************* - - Synopsis [Adds the new node to the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t ** ppPlace; - assert( !Aig_IsComplement(pObj) ); - assert( Aig_TableLookup(p, pObj) == NULL ); - if ( (pObj->Id & 0xFF) == 0 && 2 * p->nTableSize < Aig_ManNodeNum(p) ) - Aig_TableResize( p ); - ppPlace = Aig_TableFind( p, pObj ); - assert( *ppPlace == NULL ); - *ppPlace = pObj; -} - -/**Function************************************************************* - - Synopsis [Deletes the node from the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t ** ppPlace; - assert( !Aig_IsComplement(pObj) ); - ppPlace = Aig_TableFind( p, pObj ); - assert( *ppPlace == pObj ); // node should be in the table - // remove the node - *ppPlace = pObj->pNext; - pObj->pNext = NULL; -} - -/**Function************************************************************* - - Synopsis [Count the number of nodes in the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_TableCountEntries( Aig_Man_t * p ) -{ - Aig_Obj_t * pEntry; - int i, Counter = 0; - for ( i = 0; i < p->nTableSize; i++ ) - for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) - Counter++; - return Counter; -} - -/**Function******************************************************************** - - Synopsis [Profiles the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Aig_TableProfile( Aig_Man_t * p ) -{ - Aig_Obj_t * pEntry; - int i, Counter; - for ( i = 0; i < p->nTableSize; i++ ) - { - Counter = 0; - for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) - Counter++; - if ( Counter ) - printf( "%d ", Counter ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigTime.c b/src/aig/aig/aigTime.c deleted file mode 100644 index 42f5f575..00000000 --- a/src/aig/aig/aigTime.c +++ /dev/null @@ -1,299 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigTime.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Representation of timing information.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigTime.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Aig_TBox_t_ Aig_TBox_t; -typedef struct Aig_TObj_t_ Aig_TObj_t; - -// timing manager -struct Aig_TMan_t_ -{ - Vec_Ptr_t * vBoxes; // the timing boxes - Aig_MmFlex_t * pMemObj; // memory manager for boxes - int nTravIds; // traversal ID of the manager - int nPis; // the number of PIs - int nPos; // the number of POs - Aig_TObj_t * pPis; // timing info for the PIs - Aig_TObj_t * pPos; // timing info for the POs -}; - -// timing box -struct Aig_TBox_t_ -{ - int iBox; // the unique ID of this box - int TravId; // traversal ID of this box - int nInputs; // the number of box inputs - int nOutputs; // the number of box outputs - int Inouts[0]; // the int numbers of PIs and POs -}; - -// timing object -struct Aig_TObj_t_ -{ - int iObj2Box; // mapping of the object into its box - float timeOffset; // the static timing of the node - float timeActual; // the actual timing of the node -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the network manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_TMan_t * Aig_TManStart( int nPis, int nPos ) -{ - Aig_TMan_t * p; - int i; - p = ALLOC( Aig_TMan_t, 1 ); - memset( p, 0, sizeof(Aig_TMan_t) ); - p->pMemObj = Aig_MmFlexStart(); - p->vBoxes = Vec_PtrAlloc( 100 ); - Vec_PtrPush( p->vBoxes, NULL ); - p->nPis = nPis; - p->nPos = nPos; - p->pPis = ALLOC( Aig_TObj_t, nPis ); - memset( p->pPis, 0, sizeof(Aig_TObj_t) * nPis ); - p->pPos = ALLOC( Aig_TObj_t, nPos ); - memset( p->pPos, 0, sizeof(Aig_TObj_t) * nPos ); - for ( i = 0; i < nPis; i++ ) - p->pPis[i].iObj2Box = -1; - for ( i = 0; i < nPos; i++ ) - p->pPos[i].iObj2Box = -1; - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the network manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TManStop( Aig_TMan_t * p ) -{ - Vec_PtrFree( p->vBoxes ); - Aig_MmFlexStop( p->pMemObj, 0 ); - free( p->pPis ); - free( p->pPos ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Creates the new timing box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TManCreateBox( Aig_TMan_t * p, int * pPis, int nPis, int * pPos, int nPos, float * pPiTimes, float * pPoTimes ) -{ - Aig_TBox_t * pBox; - int i; - pBox = (Aig_TBox_t *)Aig_MmFlexEntryFetch( p->pMemObj, sizeof(Aig_TBox_t) + sizeof(int) * (nPis+nPos) ); - memset( pBox, 0, sizeof(Aig_TBox_t) ); - pBox->iBox = Vec_PtrSize( p->vBoxes ); - Vec_PtrPush( p->vBoxes, pBox ); - pBox->nInputs = nPis; - pBox->nOutputs = nPos; - for ( i = 0; i < nPis; i++ ) - { - assert( pPis[i] < p->nPis ); - pBox->Inouts[i] = pPis[i]; - Aig_TManSetPiArrival( p, pPis[i], pPiTimes[i] ); - p->pPis[pPis[i]].iObj2Box = pBox->iBox; - } - for ( i = 0; i < nPos; i++ ) - { - assert( pPos[i] < p->nPos ); - pBox->Inouts[nPis+i] = pPos[i]; - Aig_TManSetPoRequired( p, pPos[i], pPoTimes[i] ); - p->pPos[pPos[i]].iObj2Box = pBox->iBox; - } -} - -/**Function************************************************************* - - Synopsis [Creates the new timing box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TManSetPiDelay( Aig_TMan_t * p, int iPi, float Delay ) -{ - assert( iPi < p->nPis ); - p->pPis[iPi].timeActual = Delay; -} - -/**Function************************************************************* - - Synopsis [Creates the new timing box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TManSetPoDelay( Aig_TMan_t * p, int iPo, float Delay ) -{ - assert( iPo < p->nPos ); - p->pPos[iPo].timeActual = Delay; -} - -/**Function************************************************************* - - Synopsis [Creates the new timing box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TManSetPiArrival( Aig_TMan_t * p, int iPi, float Delay ) -{ - assert( iPi < p->nPis ); - p->pPis[iPi].timeOffset = Delay; -} - -/**Function************************************************************* - - Synopsis [Creates the new timing box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TManSetPoRequired( Aig_TMan_t * p, int iPo, float Delay ) -{ - assert( iPo < p->nPos ); - p->pPos[iPo].timeOffset = Delay; -} - -/**Function************************************************************* - - Synopsis [Increments the trav ID of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TManIncrementTravId( Aig_TMan_t * p ) -{ - p->nTravIds++; -} - -/**Function************************************************************* - - Synopsis [Returns PI arrival time.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Aig_TManGetPiArrival( Aig_TMan_t * p, int iPi ) -{ - Aig_TBox_t * pBox; - Aig_TObj_t * pObj; - float DelayMax; - int i; - assert( iPi < p->nPis ); - if ( p->pPis[iPi].iObj2Box < 0 ) - return p->pPis[iPi].timeOffset; - pBox = Vec_PtrEntry( p->vBoxes, p->pPis[iPi].iObj2Box ); - // check if box timing is updated - if ( pBox->TravId == p->nTravIds ) - return p->pPis[iPi].timeOffset; - pBox->TravId = p->nTravIds; - // update box timing - DelayMax = -1.0e+20F; - for ( i = 0; i < pBox->nOutputs; i++ ) - { - pObj = p->pPos + pBox->Inouts[pBox->nInputs+i]; - DelayMax = AIG_MAX( DelayMax, pObj->timeActual + pObj->timeOffset ); - } - for ( i = 0; i < pBox->nInputs; i++ ) - { - pObj = p->pPis + pBox->Inouts[i]; - pObj->timeActual = DelayMax + pObj->timeOffset; - } - return p->pPis[iPi].timeActual; -} - -/**Function************************************************************* - - Synopsis [Returns PO required time.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Aig_TManGetPoRequired( Aig_TMan_t * p, int iPo ) -{ - return 0.0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigTiming.c b/src/aig/aig/aigTiming.c deleted file mode 100644 index a5da4513..00000000 --- a/src/aig/aig/aigTiming.c +++ /dev/null @@ -1,351 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigTiming.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Incremental updating of direct/reverse AIG levels.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigTiming.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the reverse level of the node.] - - Description [The reverse level is the level of the node in reverse - topological order, starting from the COs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Aig_ObjReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - assert( p->vLevelR ); - Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 ); - return Vec_IntEntry(p->vLevelR, pObj->Id); -} - -/**Function************************************************************* - - Synopsis [Sets the reverse level of the node.] - - Description [The reverse level is the level of the node in reverse - topological order, starting from the COs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Aig_ObjSetReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj, int LevelR ) -{ - assert( p->vLevelR ); - Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 ); - Vec_IntWriteEntry( p->vLevelR, pObj->Id, LevelR ); -} - -/**Function************************************************************* - - Synopsis [Resets reverse level of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_ObjSetReverseLevel( p, pObj, 0 ); -} - -/**Function************************************************************* - - Synopsis [Returns required level of the node.] - - Description [Converts the reverse levels of the node into its required - level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - assert( p->vLevelR ); - return p->nLevelMax + 1 - Aig_ObjReverseLevel(p, pObj); -} - -/**Function************************************************************* - - Synopsis [Computes the reverse level of the node using its fanout levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjReverseLevelNew( Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pFanout; - int i, iFanout, LevelCur, Level = 0; - Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) - { - LevelCur = Aig_ObjReverseLevel( p, pFanout ); - Level = AIG_MAX( Level, LevelCur ); - } - return Level + 1; -} - -/**Function************************************************************* - - Synopsis [Prepares for the computation of required levels.] - - Description [This procedure should be called before the required times - are used. It starts internal data structures, which records the level - from the COs of the network nodes in reverse topologogical order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - assert( p->pFanData != NULL ); - assert( p->vLevelR == NULL ); - // remember the maximum number of direct levels - p->nLevelMax = Aig_ManLevels(p) + nMaxLevelIncrease; - // start the reverse levels - p->vLevelR = Vec_IntAlloc( 0 ); - Vec_IntFill( p->vLevelR, Aig_ManObjNumMax(p), 0 ); - // compute levels in reverse topological order - vNodes = Aig_ManDfsReverse( p ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - assert( pObj->fMarkA == 0 ); - Aig_ObjSetReverseLevel( p, pObj, Aig_ObjReverseLevelNew(p, pObj) ); - } - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Cleans the data structures used to compute required levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManStopReverseLevels( Aig_Man_t * p ) -{ - assert( p->vLevelR != NULL ); - Vec_IntFree( p->vLevelR ); - p->vLevelR = NULL; - p->nLevelMax = 0; - -} - -/**Function************************************************************* - - Synopsis [Incrementally updates level of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ) -{ - Aig_Obj_t * pFanout, * pTemp; - int iFanout, LevelOld, Lev, k, m; - assert( p->pFanData != NULL ); - assert( Aig_ObjIsNode(pObjNew) ); - // allocate level if needed - if ( p->vLevels == NULL ) - p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 ); - // check if level has changed - LevelOld = Aig_ObjLevel(pObjNew); - if ( LevelOld == Aig_ObjLevelNew(pObjNew) ) - return; - // start the data structure for level update - // we cannot fail to visit a node when using this structure because the - // nodes are stored by their _old_ levels, which are assumed to be correct - Vec_VecClear( p->vLevels ); - Vec_VecPush( p->vLevels, LevelOld, pObjNew ); - pObjNew->fMarkA = 1; - // recursively update level - Vec_VecForEachEntryStart( p->vLevels, pTemp, Lev, k, LevelOld ) - { - pTemp->fMarkA = 0; - assert( Aig_ObjLevel(pTemp) == Lev ); - pTemp->Level = Aig_ObjLevelNew(pTemp); - // if the level did not change, no need to check the fanout levels - if ( Aig_ObjLevel(pTemp) == Lev ) - continue; - // schedule fanout for level update - Aig_ObjForEachFanout( p, pTemp, pFanout, iFanout, m ) - { - if ( Aig_ObjIsNode(pFanout) && !pFanout->fMarkA ) - { - assert( Aig_ObjLevel(pFanout) >= Lev ); - Vec_VecPush( p->vLevels, Aig_ObjLevel(pFanout), pFanout ); - pFanout->fMarkA = 1; - } - } - } -} - -/**Function************************************************************* - - Synopsis [Incrementally updates level of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ) -{ - Aig_Obj_t * pFanin, * pTemp; - int LevelOld, LevFanin, Lev, k; - assert( p->vLevelR != NULL ); - assert( Aig_ObjIsNode(pObjNew) ); - // allocate level if needed - if ( p->vLevels == NULL ) - p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 ); - // check if level has changed - LevelOld = Aig_ObjReverseLevel(p, pObjNew); - if ( LevelOld == Aig_ObjReverseLevelNew(p, pObjNew) ) - return; - // start the data structure for level update - // we cannot fail to visit a node when using this structure because the - // nodes are stored by their _old_ levels, which are assumed to be correct - Vec_VecClear( p->vLevels ); - Vec_VecPush( p->vLevels, LevelOld, pObjNew ); - pObjNew->fMarkA = 1; - // recursively update level - Vec_VecForEachEntryStart( p->vLevels, pTemp, Lev, k, LevelOld ) - { - pTemp->fMarkA = 0; - LevelOld = Aig_ObjReverseLevel(p, pTemp); - assert( LevelOld == Lev ); - Aig_ObjSetReverseLevel( p, pTemp, Aig_ObjReverseLevelNew(p, pTemp) ); - // if the level did not change, to need to check the fanout levels - if ( Aig_ObjReverseLevel(p, pTemp) == Lev ) - continue; - // schedule fanins for level update - pFanin = Aig_ObjFanin0(pTemp); - if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA ) - { - LevFanin = Aig_ObjReverseLevel( p, pFanin ); - assert( LevFanin >= Lev ); - Vec_VecPush( p->vLevels, LevFanin, pFanin ); - pFanin->fMarkA = 1; - } - pFanin = Aig_ObjFanin1(pTemp); - if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA ) - { - LevFanin = Aig_ObjReverseLevel( p, pFanin ); - assert( LevFanin >= Lev ); - Vec_VecPush( p->vLevels, LevFanin, pFanin ); - pFanin->fMarkA = 1; - } - } -} - -/**Function************************************************************* - - Synopsis [Verifies direct level of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManVerifyLevel( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - assert( p->pFanData ); - Aig_ManForEachNode( p, pObj, i ) - if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) ) - { - printf( "Level of node %6d should be %4d instead of %4d.\n", - pObj->Id, Aig_ObjLevelNew(pObj), Aig_ObjLevel(pObj) ); - Counter++; - } - if ( Counter ) - printf( "Levels of %d nodes are incorrect.\n", Counter ); -} - -/**Function************************************************************* - - Synopsis [Verifies reverse level of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManVerifyReverseLevel( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, Counter = 0; - assert( p->vLevelR ); - Aig_ManForEachNode( p, pObj, i ) - if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) ) - { - printf( "Reverse level of node %6d should be %4d instead of %4d.\n", - pObj->Id, Aig_ObjReverseLevelNew(p, pObj), Aig_ObjReverseLevel(p, pObj) ); - Counter++; - } - if ( Counter ) - printf( "Reverse levels of %d nodes are incorrect.\n", Counter ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigTruth.c b/src/aig/aig/aigTruth.c deleted file mode 100644 index a92f9e1d..00000000 --- a/src/aig/aig/aigTruth.c +++ /dev/null @@ -1,98 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigTruth.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Computes truth table for the cut.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigTruth.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Aig_ManCutTruthOne( Aig_Obj_t * pNode, unsigned * pTruth, int nWords ) -{ - unsigned * pTruth0, * pTruth1; - int i; - pTruth0 = Aig_ObjFanin0(pNode)->pData; - pTruth1 = Aig_ObjFanin1(pNode)->pData; - if ( Aig_ObjIsExor(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] ^ pTruth1[i]; - else if ( !Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] & pTruth1[i]; - else if ( !Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] & ~pTruth1[i]; - else if ( Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ~pTruth0[i] & pTruth1[i]; - else // if ( Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; - return pTruth; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [The returned pointer should be used immediately.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore ) -{ - Aig_Obj_t * pObj; - int i, nWords; - assert( Vec_PtrSize(vLeaves) <= Vec_PtrSize(vTruthElem) ); - assert( Vec_PtrSize(vNodes) <= Vec_PtrSize(vTruthStore) ); - assert( Vec_PtrSize(vNodes) == 0 || pRoot == Vec_PtrEntryLast(vNodes) ); - // assign elementary truth tables - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->pData = Vec_PtrEntry( vTruthElem, i ); - // compute truths for other nodes - nWords = Aig_TruthWordNum( Vec_PtrSize(vLeaves) ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pData = Aig_ManCutTruthOne( pObj, Vec_PtrEntry(vTruthStore, i), nWords ); - return pRoot->pData; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigTsim.c b/src/aig/aig/aigTsim.c deleted file mode 100644 index e5b96879..00000000 --- a/src/aig/aig/aigTsim.c +++ /dev/null @@ -1,436 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigTsim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Ternary simulation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigTsim.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define TSI_MAX_ROUNDS 1000 - -#define AIG_XVS0 1 -#define AIG_XVS1 2 -#define AIG_XVSX 3 - -static inline void Aig_ObjSetXsim( Aig_Obj_t * pObj, int Value ) { pObj->nCuts = Value; } -static inline int Aig_ObjGetXsim( Aig_Obj_t * pObj ) { return pObj->nCuts; } -static inline int Aig_XsimInv( int Value ) -{ - if ( Value == AIG_XVS0 ) - return AIG_XVS1; - if ( Value == AIG_XVS1 ) - return AIG_XVS0; - assert( Value == AIG_XVSX ); - return AIG_XVSX; -} -static inline int Aig_XsimAnd( int Value0, int Value1 ) -{ - if ( Value0 == AIG_XVS0 || Value1 == AIG_XVS0 ) - return AIG_XVS0; - if ( Value0 == AIG_XVSX || Value1 == AIG_XVSX ) - return AIG_XVSX; - assert( Value0 == AIG_XVS1 && Value1 == AIG_XVS1 ); - return AIG_XVS1; -} -static inline int Aig_XsimRand2() -{ - return (rand() & 1) ? AIG_XVS1 : AIG_XVS0; -} -static inline int Aig_XsimRand3() -{ - int RetValue; - do { - RetValue = rand() & 3; - } while ( RetValue == 0 ); - return RetValue; -} -static inline int Aig_ObjGetXsimFanin0( Aig_Obj_t * pObj ) -{ - int RetValue; - RetValue = Aig_ObjGetXsim(Aig_ObjFanin0(pObj)); - return Aig_ObjFaninC0(pObj)? Aig_XsimInv(RetValue) : RetValue; -} -static inline int Aig_ObjGetXsimFanin1( Aig_Obj_t * pObj ) -{ - int RetValue; - RetValue = Aig_ObjGetXsim(Aig_ObjFanin1(pObj)); - return Aig_ObjFaninC1(pObj)? Aig_XsimInv(RetValue) : RetValue; -} -static inline void Aig_XsimPrint( FILE * pFile, int Value ) -{ - if ( Value == AIG_XVS0 ) - { - fprintf( pFile, "0" ); - return; - } - if ( Value == AIG_XVS1 ) - { - fprintf( pFile, "1" ); - return; - } - assert( Value == AIG_XVSX ); - fprintf( pFile, "x" ); -} - -// simulation manager -typedef struct Aig_Tsi_t_ Aig_Tsi_t; -struct Aig_Tsi_t_ -{ - Aig_Man_t * pAig; // the original AIG manager - // ternary state representation - int nWords; // the number of words in the states - Vec_Ptr_t * vStates; // the collection of ternary states - Aig_MmFixed_t * pMem; // memory for ternary states - // hash table for terminary states - unsigned ** pBins; - int nBins; -}; - -static inline unsigned * Aig_TsiNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } -static inline void Aig_TsiSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Tsi_t * Aig_TsiStart( Aig_Man_t * pAig ) -{ - Aig_Tsi_t * p; - p = (Aig_Tsi_t *)malloc( sizeof(Aig_Tsi_t) ); - memset( p, 0, sizeof(Aig_Tsi_t) ); - p->pAig = pAig; - p->nWords = Aig_BitWordNum( 2*Aig_ManRegNum(pAig) ); - p->vStates = Vec_PtrAlloc( 1000 ); - p->pMem = Aig_MmFixedStart( sizeof(unsigned) * p->nWords + sizeof(unsigned *), 10000 ); - p->nBins = Aig_PrimeCudd(TSI_MAX_ROUNDS/2); - p->pBins = ALLOC( unsigned *, p->nBins ); - memset( p->pBins, 0, sizeof(unsigned *) * p->nBins ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TsiStop( Aig_Tsi_t * p ) -{ - Aig_MmFixedStop( p->pMem, 0 ); - Vec_PtrFree( p->vStates ); - free( p->pBins ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Computes hash value of the node using its simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_TsiStateHash( unsigned * pState, int nWords, int nTableSize ) -{ - static int s_FPrimes[128] = { - 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, - 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, - 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, - 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, - 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, - 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, - 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, - 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, - 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, - 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, - 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, - 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, - 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 - }; - unsigned uHash; - int i; - uHash = 0; - for ( i = 0; i < nWords; i++ ) - uHash ^= pState[i] * s_FPrimes[i & 0x7F]; - return uHash % nTableSize; -} - -/**Function************************************************************* - - Synopsis [Inserts value into the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_TsiStateLookup( Aig_Tsi_t * p, unsigned * pState, int nWords ) -{ - unsigned * pEntry; - int Hash; - Hash = Aig_TsiStateHash( pState, nWords, p->nBins ); - for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Aig_TsiNext(pEntry, nWords) ) - if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Inserts value into the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TsiStateInsert( Aig_Tsi_t * p, unsigned * pState, int nWords ) -{ - int Hash = Aig_TsiStateHash( pState, nWords, p->nBins ); - assert( !Aig_TsiStateLookup( p, pState, nWords ) ); - Aig_TsiSetNext( pState, nWords, p->pBins[Hash] ); - p->pBins[Hash] = pState; -} - -/**Function************************************************************* - - Synopsis [Inserts value into the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Aig_TsiStateNew( Aig_Tsi_t * p ) -{ - unsigned * pState; - pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMem ); - memset( pState, 0, sizeof(unsigned) * p->nWords ); - Vec_PtrPush( p->vStates, pState ); - return pState; -} - -/**Function************************************************************* - - Synopsis [Inserts value into the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_TsiStatePrint( Aig_Tsi_t * p, unsigned * pState ) -{ - int i, Value, nZeros = 0, nOnes = 0, nDcs = 0; - for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) - { - Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); - if ( Value == 1 ) - printf( "0" ), nZeros++; - else if ( Value == 2 ) - printf( "1" ), nOnes++; - else if ( Value == 3 ) - printf( "x" ), nDcs++; - else - assert( 0 ); - } - printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs ); -} - - -/**Function************************************************************* - - Synopsis [Cycles the circuit to create a new initial state.] - - Description [Simulates the circuit with random input for the given - number of timeframes to get a better initial state.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManTernarySimulate( Aig_Man_t * p, int fVerbose ) -{ - Aig_Tsi_t * pTsi; - Vec_Ptr_t * vMap; - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - unsigned * pState, * pPrev; - int i, k, f, fConstants, Value, nCounter; - // allocate the simulation manager - pTsi = Aig_TsiStart( p ); - // initialize the values - Aig_ObjSetXsim( Aig_ManConst1(p), AIG_XVS1 ); - Aig_ManForEachPiSeq( p, pObj, i ) - Aig_ObjSetXsim( pObj, AIG_XVSX ); - Aig_ManForEachLoSeq( p, pObj, i ) - Aig_ObjSetXsim( pObj, AIG_XVS0 ); - // simulate for the given number of timeframes - for ( f = 0; f < TSI_MAX_ROUNDS; f++ ) - { - // collect this state - pState = Aig_TsiStateNew( pTsi ); - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - { - Value = Aig_ObjGetXsim(pObjLo); - if ( Value & 1 ) - Aig_InfoSetBit( pState, 2 * i ); - if ( Value & 2 ) - Aig_InfoSetBit( pState, 2 * i + 1 ); - } -// Aig_TsiStatePrint( pTsi, pState ); - // check if this state exists - if ( Aig_TsiStateLookup( pTsi, pState, pTsi->nWords ) ) - break; - // insert this state - Aig_TsiStateInsert( pTsi, pState, pTsi->nWords ); - // simulate internal nodes - Aig_ManForEachNode( p, pObj, i ) - Aig_ObjSetXsim( pObj, Aig_XsimAnd(Aig_ObjGetXsimFanin0(pObj), Aig_ObjGetXsimFanin1(pObj)) ); - // transfer the latch values - Aig_ManForEachLiSeq( p, pObj, i ) - Aig_ObjSetXsim( pObj, Aig_ObjGetXsimFanin0(pObj) ); - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - Aig_ObjSetXsim( pObjLo, Aig_ObjGetXsim(pObjLi) ); - } - if ( f == TSI_MAX_ROUNDS ) - { - printf( "Aig_ManTernarySimulate(): Did not reach a fixed point after %d iterations (not a bug).\n", TSI_MAX_ROUNDS ); - Aig_TsiStop( pTsi ); - return NULL; - } - // OR all the states - pState = Vec_PtrEntry( pTsi->vStates, 0 ); - Vec_PtrForEachEntry( pTsi->vStates, pPrev, i ) - { - for ( k = 0; k < pTsi->nWords; k++ ) - pState[k] |= pPrev[k]; - } - // check if there are constants - fConstants = 0; - if ( 2*Aig_ManRegNum(p) == 32*pTsi->nWords ) - { - for ( i = 0; i < pTsi->nWords; i++ ) - if ( pState[i] != ~0 ) - fConstants = 1; - } - else - { - for ( i = 0; i < pTsi->nWords - 1; i++ ) - if ( pState[i] != ~0 ) - fConstants = 1; - if ( pState[i] != Aig_InfoMask( 2*Aig_ManRegNum(p) - 32*(pTsi->nWords-1) ) ) - fConstants = 1; - } - if ( fConstants == 0 ) - { - Aig_TsiStop( pTsi ); - return NULL; - } - - // start mapping by adding the true PIs - vMap = Vec_PtrAlloc( Aig_ManPiNum(p) ); - Aig_ManForEachPiSeq( p, pObj, i ) - Vec_PtrPush( vMap, pObj ); - // find constant registers - nCounter = 0; - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - { - Value = (Aig_InfoHasBit( pState, 2 * i + 1 ) << 1) | Aig_InfoHasBit( pState, 2 * i ); - nCounter += (Value == 1 || Value == 2); - if ( Value == 1 ) - Vec_PtrPush( vMap, Aig_ManConst0(p) ); - else if ( Value == 2 ) - Vec_PtrPush( vMap, Aig_ManConst1(p) ); - else if ( Value == 3 ) - Vec_PtrPush( vMap, pObjLo ); - else - assert( 0 ); -// Aig_XsimPrint( stdout, Value ); - } -// printf( "\n" ); - Aig_TsiStop( pTsi ); - if ( fVerbose ) - printf( "Detected %d constants after %d iterations of ternary simulation.\n", nCounter, f ); - return vMap; -} - -/**Function************************************************************* - - Synopsis [Reduces the circuit using ternary simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Aig_ManConstReduce( Aig_Man_t * p, int fVerbose ) -{ - Aig_Man_t * pTemp; - Vec_Ptr_t * vMap; - while ( vMap = Aig_ManTernarySimulate( p, fVerbose ) ) - { - if ( fVerbose ) - printf( "RBeg = %5d. NBeg = %6d. ", Aig_ManRegNum(p), Aig_ManNodeNum(p) ); - p = Aig_ManRemap( pTemp = p, vMap ); - Aig_ManStop( pTemp ); - Vec_PtrFree( vMap ); - Aig_ManSeqCleanup( p ); - if ( fVerbose ) - printf( "REnd = %5d. NEnd = %6d. \n", Aig_ManRegNum(p), Aig_ManNodeNum(p) ); - } - return p; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigUtil.c b/src/aig/aig/aigUtil.c deleted file mode 100644 index 2fba3cb1..00000000 --- a/src/aig/aig/aigUtil.c +++ /dev/null @@ -1,846 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Various procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function******************************************************************** - - Synopsis [Returns the next prime >= p.] - - Description [Copied from CUDD, for stand-aloneness.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -unsigned int Aig_PrimeCudd( unsigned int p ) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - -/**Function************************************************************* - - Synopsis [Increments the current traversal ID of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManIncrementTravId( Aig_Man_t * p ) -{ - if ( p->nTravIds >= (1<<30)-1 ) - Aig_ManCleanData( p ); - p->nTravIds++; -} - -/**Function************************************************************* - - Synopsis [Collect the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManLevels( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, LevelMax = 0; - Aig_ManForEachPo( p, pObj, i ) - LevelMax = AIG_MAX( LevelMax, (int)Aig_ObjFanin0(pObj)->Level ); - return LevelMax; -} - -/**Function************************************************************* - - Synopsis [Reset reference counters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManResetRefs( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - pObj->nRefs = 0; - Aig_ManForEachObj( p, pObj, i ) - { - if ( Aig_ObjFanin0(pObj) ) - Aig_ObjFanin0(pObj)->nRefs++; - if ( Aig_ObjFanin1(pObj) ) - Aig_ObjFanin1(pObj)->nRefs++; - } -} - -/**Function************************************************************* - - Synopsis [Cleans MarkB.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCleanMarkA( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - pObj->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Cleans MarkB.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCleanMarkB( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - pObj->fMarkB = 0; -} - -/**Function************************************************************* - - Synopsis [Cleans the data pointers for the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCleanData( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p, pObj, i ) - pObj->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Recursively cleans the data pointers in the cone of the node.] - - Description [Applicable to small AIGs only because no caching is performed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjCleanData_rec( Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - assert( !Aig_ObjIsPo(pObj) ); - if ( Aig_ObjIsAnd(pObj) ) - { - Aig_ObjCleanData_rec( Aig_ObjFanin0(pObj) ); - Aig_ObjCleanData_rec( Aig_ObjFanin1(pObj) ); - } - pObj->pData = NULL; -} - - -/**Function************************************************************* - - Synopsis [Detects multi-input gate rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjCollectMulti_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - if ( pRoot != pObj && (Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) || Aig_ObjType(pRoot) != Aig_ObjType(pObj)) ) - { - Vec_PtrPushUnique(vSuper, pObj); - return; - } - Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild0(pObj), vSuper ); - Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild1(pObj), vSuper ); -} - -/**Function************************************************************* - - Synopsis [Detects multi-input gate rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjCollectMulti( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper ) -{ - assert( !Aig_IsComplement(pRoot) ); - Vec_PtrClear( vSuper ); - Aig_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjIsMuxType( Aig_Obj_t * pNode ) -{ - Aig_Obj_t * pNode0, * pNode1; - // check that the node is regular - assert( !Aig_IsComplement(pNode) ); - // if the node is not AND, this is not MUX - if ( !Aig_ObjIsAnd(pNode) ) - return 0; - // if the children are not complemented, this is not MUX - if ( !Aig_ObjFaninC0(pNode) || !Aig_ObjFaninC1(pNode) ) - return 0; - // get children - pNode0 = Aig_ObjFanin0(pNode); - pNode1 = Aig_ObjFanin1(pNode); - // if the children are not ANDs, this is not MUX - if ( !Aig_ObjIsAnd(pNode0) || !Aig_ObjIsAnd(pNode1) ) - return 0; - // otherwise the node is MUX iff it has a pair of equal grandchildren - return (Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1))) || - (Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1))) || - (Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1))) || - (Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1))); -} - - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are inputs of the EXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) -{ - Aig_Obj_t * p0, * p1; - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) ) - return 0; - if ( Aig_ObjIsExor(pObj) ) - { - *ppFan0 = Aig_ObjChild0(pObj); - *ppFan1 = Aig_ObjChild1(pObj); - return 1; - } - assert( Aig_ObjIsAnd(pObj) ); - p0 = Aig_ObjChild0(pObj); - p1 = Aig_ObjChild1(pObj); - if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) - return 0; - p0 = Aig_Regular(p0); - p1 = Aig_Regular(p1); - if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) - return 0; - if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) - return 0; - if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) - return 0; - *ppFan0 = Aig_ObjChild0(p0); - *ppFan1 = Aig_ObjChild1(p0); - return 1; -} - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are control and data inputs of a MUX.] - - Description [If the node is a MUX, returns the control variable C. - Assigns nodes T and E to be the then and else variables of the MUX. - Node C is never complemented. Nodes T and E can be complemented. - This function also recognizes EXOR/NEXOR gates as MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pNode, Aig_Obj_t ** ppNodeT, Aig_Obj_t ** ppNodeE ) -{ - Aig_Obj_t * pNode0, * pNode1; - assert( !Aig_IsComplement(pNode) ); - assert( Aig_ObjIsMuxType(pNode) ); - // get children - pNode0 = Aig_ObjFanin0(pNode); - pNode1 = Aig_ObjFanin1(pNode); - - // find the control variable - if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Aig_ObjFaninC1(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - return Aig_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - return Aig_ObjChild1(pNode0);//pNode1->p2; - } - } - else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Aig_ObjFaninC0(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - return Aig_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - return Aig_ObjChild0(pNode0);//pNode1->p1; - } - } - else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Aig_ObjFaninC0(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - return Aig_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); - return Aig_ObjChild0(pNode0);//pNode1->p1; - } - } - else if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Aig_ObjFaninC1(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - return Aig_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); - return Aig_ObjChild1(pNode0);//pNode1->p2; - } - } - assert( 0 ); // this is not MUX - return NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Aig_ObjReal_rec( Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pObjNew, * pObjR = Aig_Regular(pObj); - if ( !Aig_ObjIsBuf(pObjR) ) - return pObj; - pObjNew = Aig_ObjReal_rec( Aig_ObjChild0(pObjR) ); - return Aig_NotCond( pObjNew, Aig_IsComplement(pObj) ); -} - - -/**Function************************************************************* - - Synopsis [Prints Eqn formula for the AIG rooted at this node.] - - Description [The formula is in terms of PIs, which should have - their names assigned in pObj->pData fields.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) -{ - Vec_Ptr_t * vSuper; - Aig_Obj_t * pFanin; - int fCompl, i; - // store the complemented attribute - fCompl = Aig_IsComplement(pObj); - pObj = Aig_Regular(pObj); - // constant case - if ( Aig_ObjIsConst1(pObj) ) - { - fprintf( pFile, "%d", !fCompl ); - return; - } - // PI case - if ( Aig_ObjIsPi(pObj) ) - { - fprintf( pFile, "%s%s", fCompl? "!" : "", pObj->pData ); - return; - } - // AND case - Vec_VecExpand( vLevels, Level ); - vSuper = Vec_VecEntry(vLevels, Level); - Aig_ObjCollectMulti( pObj, vSuper ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - Aig_ObjPrintEqn( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 ); - if ( i < Vec_PtrSize(vSuper) - 1 ) - fprintf( pFile, " %s ", fCompl? "+" : "*" ); - } - fprintf( pFile, "%s", (Level==0? "" : ")") ); - return; -} - -/**Function************************************************************* - - Synopsis [Prints Verilog formula for the AIG rooted at this node.] - - Description [The formula is in terms of PIs, which should have - their names assigned in pObj->pData fields.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) -{ - Vec_Ptr_t * vSuper; - Aig_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC; - int fCompl, i; - // store the complemented attribute - fCompl = Aig_IsComplement(pObj); - pObj = Aig_Regular(pObj); - // constant case - if ( Aig_ObjIsConst1(pObj) ) - { - fprintf( pFile, "1\'b%d", !fCompl ); - return; - } - // PI case - if ( Aig_ObjIsPi(pObj) ) - { - fprintf( pFile, "%s%s", fCompl? "~" : "", pObj->pData ); - return; - } - // EXOR case - if ( Aig_ObjIsExor(pObj) ) - { - Vec_VecExpand( vLevels, Level ); - vSuper = Vec_VecEntry( vLevels, Level ); - Aig_ObjCollectMulti( pObj, vSuper ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 ); - if ( i < Vec_PtrSize(vSuper) - 1 ) - fprintf( pFile, " ^ " ); - } - fprintf( pFile, "%s", (Level==0? "" : ")") ); - return; - } - // MUX case - if ( Aig_ObjIsMuxType(pObj) ) - { - if ( Aig_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) - { - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); - fprintf( pFile, " ^ " ); - Aig_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 ); - fprintf( pFile, "%s", (Level==0? "" : ")") ); - } - else - { - pFaninC = Aig_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Aig_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 ); - fprintf( pFile, " ? " ); - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin1, fCompl), vLevels, Level+1 ); - fprintf( pFile, " : " ); - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); - fprintf( pFile, "%s", (Level==0? "" : ")") ); - } - return; - } - // AND case - Vec_VecExpand( vLevels, Level ); - vSuper = Vec_VecEntry(vLevels, Level); - Aig_ObjCollectMulti( pObj, vSuper ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 ); - if ( i < Vec_PtrSize(vSuper) - 1 ) - fprintf( pFile, " %s ", fCompl? "|" : "&" ); - } - fprintf( pFile, "%s", (Level==0? "" : ")") ); - return; -} - - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ) -{ - assert( !Aig_IsComplement(pObj) ); - printf( "Node %p : ", pObj ); - if ( Aig_ObjIsConst1(pObj) ) - printf( "constant 1" ); - else if ( Aig_ObjIsPi(pObj) ) - printf( "PI" ); - else - printf( "AND( %p%s, %p%s )", - Aig_ObjFanin0(pObj), (Aig_ObjFaninC0(pObj)? "\'" : " "), - Aig_ObjFanin1(pObj), (Aig_ObjFaninC1(pObj)? "\'" : " ") ); - printf( " (refs = %3d)", Aig_ObjRefs(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ) -{ - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj; - int i; - printf( "PIs: " ); - Aig_ManForEachPi( p, pObj, i ) - printf( " %p", pObj ); - printf( "\n" ); - vNodes = Aig_ManDfs( p ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Write speculative miter for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDump( Aig_Man_t * p ) -{ - static int Counter = 0; - char FileName[20]; - // dump the logic into a file - sprintf( FileName, "aigbug\\%03d.blif", ++Counter ); - Aig_ManDumpBlif( p, FileName ); - printf( "Intermediate AIG with %d nodes was written into file \"%s\".\n", Aig_ManNodeNum(p), FileName ); -} - -/**Function************************************************************* - - Synopsis [Writes the AIG into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName ) -{ - FILE * pFile; - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pConst1 = NULL; - int i, nDigits, Counter = 0; - if ( Aig_ManPoNum(p) == 0 ) - { - printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); - return; - } - // collect nodes in the DFS order - vNodes = Aig_ManDfs( p ); - // assign IDs to objects - Aig_ManConst1(p)->iData = Counter++; - Aig_ManForEachPi( p, pObj, i ) - pObj->iData = Counter++; - Aig_ManForEachPo( p, pObj, i ) - pObj->iData = Counter++; - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->iData = Counter++; - nDigits = Aig_Base10Log( Counter ); - // write the file - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "# BLIF file written by procedure Aig_ManDumpBlif() in ABC\n" ); - fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); - fprintf( pFile, ".model test\n" ); - // write PIs - fprintf( pFile, ".inputs" ); - Aig_ManForEachPiSeq( p, pObj, i ) - fprintf( pFile, " n%0*d", nDigits, pObj->iData ); - fprintf( pFile, "\n" ); - // write POs - fprintf( pFile, ".outputs" ); - Aig_ManForEachPoSeq( p, pObj, i ) - fprintf( pFile, " n%0*d", nDigits, pObj->iData ); - fprintf( pFile, "\n" ); - // write latches - if ( Aig_ManRegNum(p) ) - { - fprintf( pFile, "\n" ); - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - fprintf( pFile, ".latch n%0*d n%0*d 0\n", nDigits, pObjLi->iData, nDigits, pObjLo->iData ); - fprintf( pFile, "\n" ); - } - // write nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - fprintf( pFile, ".names n%0*d n%0*d n%0*d\n", - nDigits, Aig_ObjFanin0(pObj)->iData, - nDigits, Aig_ObjFanin1(pObj)->iData, - nDigits, pObj->iData ); - fprintf( pFile, "%d%d 1\n", !Aig_ObjFaninC0(pObj), !Aig_ObjFaninC1(pObj) ); - } - // write POs - Aig_ManForEachPo( p, pObj, i ) - { - fprintf( pFile, ".names n%0*d n%0*d\n", - nDigits, Aig_ObjFanin0(pObj)->iData, - nDigits, pObj->iData ); - fprintf( pFile, "%d 1\n", !Aig_ObjFaninC0(pObj) ); - if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) - pConst1 = Aig_ManConst1(p); - } - if ( pConst1 ) - fprintf( pFile, ".names n%0*d\n 1\n", nDigits, pConst1->iData ); - fprintf( pFile, ".end\n\n" ); - fclose( pFile ); - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Writes the AIG into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManDumpVerilog( Aig_Man_t * p, char * pFileName ) -{ - FILE * pFile; - Vec_Ptr_t * vNodes; - Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pConst1 = NULL; - int i, nDigits, Counter = 0; - if ( Aig_ManPoNum(p) == 0 ) - { - printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); - return; - } - // collect nodes in the DFS order - vNodes = Aig_ManDfs( p ); - // assign IDs to objects - Aig_ManConst1(p)->iData = Counter++; - Aig_ManForEachPi( p, pObj, i ) - pObj->iData = Counter++; - Aig_ManForEachPo( p, pObj, i ) - pObj->iData = Counter++; - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->iData = Counter++; - nDigits = Aig_Base10Log( Counter ); - // write the file - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "// Verilog file written by procedure Aig_ManDumpVerilog() in ABC\n" ); - fprintf( pFile, "// http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); - fprintf( pFile, "module %s ( clock", p->pName? p->pName: "test" ); - Aig_ManForEachPiSeq( p, pObj, i ) - fprintf( pFile, ", n%0*d", nDigits, pObj->iData ); - Aig_ManForEachPoSeq( p, pObj, i ) - fprintf( pFile, ", n%0*d", nDigits, pObj->iData ); - fprintf( pFile, " );\n" ); - - // write PIs - Aig_ManForEachPiSeq( p, pObj, i ) - fprintf( pFile, "input n%0*d;\n", nDigits, pObj->iData ); - // write POs - Aig_ManForEachPoSeq( p, pObj, i ) - fprintf( pFile, "output n%0*d;\n", nDigits, pObj->iData ); - // write latches - if ( Aig_ManRegNum(p) ) - { - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - fprintf( pFile, "reg n%0*d;\n", nDigits, pObjLo->iData ); - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - fprintf( pFile, "wire n%0*d;\n", nDigits, pObjLi->iData ); - } - // write nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - fprintf( pFile, "wire n%0*d;\n", nDigits, pObj->iData ); - // write nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - fprintf( pFile, "assign n%0*d = %sn%0*d & %sn%0*d;\n", - nDigits, pObj->iData, - !Aig_ObjFaninC0(pObj) ? " " : "~", nDigits, Aig_ObjFanin0(pObj)->iData, - !Aig_ObjFaninC1(pObj) ? " " : "~", nDigits, Aig_ObjFanin1(pObj)->iData - ); - } - // write POs - Aig_ManForEachPoSeq( p, pObj, i ) - { - fprintf( pFile, "assign n%0*d = %sn%0*d;\n", - nDigits, pObj->iData, - !Aig_ObjFaninC0(pObj) ? " " : "~", nDigits, Aig_ObjFanin0(pObj)->iData ); - if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) - pConst1 = Aig_ManConst1(p); - } - if ( Aig_ManRegNum(p) ) - { - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - { - fprintf( pFile, "assign n%0*d = %sn%0*d;\n", - nDigits, pObjLi->iData, - !Aig_ObjFaninC0(pObjLi) ? " " : "~", nDigits, Aig_ObjFanin0(pObjLi)->iData ); - if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObjLi)) ) - pConst1 = Aig_ManConst1(p); - } - } - if ( pConst1 ) - fprintf( pFile, "assign n%0*d = 1\'b1;\n", nDigits, pConst1->iData ); - - // write initial state - if ( Aig_ManRegNum(p) ) - { - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - fprintf( pFile, "always @ (posedge clock) begin n%0*d <= n%0*d; end\n", - nDigits, pObjLo->iData, - nDigits, pObjLi->iData ); - Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) - fprintf( pFile, "initial begin n%0*d <= 1\'b0; end\n", - nDigits, pObjLo->iData ); - } - - fprintf( pFile, "endmodule\n\n" ); - fclose( pFile ); - Vec_PtrFree( vNodes ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aigWin.c b/src/aig/aig/aigWin.c deleted file mode 100644 index 0485b243..00000000 --- a/src/aig/aig/aigWin.c +++ /dev/null @@ -1,184 +0,0 @@ -/**CFile**************************************************************** - - FileName [aigWin.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [Window computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aigWin.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Evaluate the cost of removing the node from the set of leaves.] - - Description [Returns the number of new leaves that will be brought in. - Returns large number if the node cannot be removed from the set of leaves.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Aig_NodeGetLeafCostOne( Aig_Obj_t * pNode, int nFanoutLimit ) -{ - int Cost; - // make sure the node is in the construction zone - assert( pNode->fMarkA ); - // cannot expand over the PI node - if ( Aig_ObjIsPi(pNode) ) - return 999; - // get the cost of the cone - Cost = (!Aig_ObjFanin0(pNode)->fMarkA) + (!Aig_ObjFanin1(pNode)->fMarkA); - // always accept if the number of leaves does not increase - if ( Cost < 2 ) - return Cost; - // skip nodes with many fanouts - if ( (int)pNode->nRefs > nFanoutLimit ) - return 999; - // return the number of nodes that will be on the leaves if this node is removed - return Cost; -} - -/**Function************************************************************* - - Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] - - Description [This procedure looks at the current leaves and tries to change - one leaf at a time in such a way that the cut grows as little as possible. - In evaluating the fanins, this procedure looks only at their immediate - predecessors (this is why it is called a one-level construction procedure).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManFindCut_int( Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ) -{ - Aig_Obj_t * pNode, * pFaninBest, * pNext; - int CostBest, CostCur, i; - // find the best fanin - CostBest = 100; - pFaninBest = NULL; -//printf( "Evaluating fanins of the cut:\n" ); - Vec_PtrForEachEntry( vFront, pNode, i ) - { - CostCur = Aig_NodeGetLeafCostOne( pNode, nFanoutLimit ); -//printf( " Fanin %s has cost %d.\n", Aig_ObjName(pNode), CostCur ); - if ( CostBest > CostCur || - (CostBest == CostCur && pNode->Level > pFaninBest->Level) ) - { - CostBest = CostCur; - pFaninBest = pNode; - } - if ( CostBest == 0 ) - break; - } - if ( pFaninBest == NULL ) - return 0; - assert( CostBest < 3 ); - if ( Vec_PtrSize(vFront) - 1 + CostBest > nSizeLimit ) - return 0; - assert( Aig_ObjIsNode(pFaninBest) ); - // remove the node from the array - Vec_PtrRemove( vFront, pFaninBest ); -//printf( "Removing fanin %s.\n", Aig_ObjName(pFaninBest) ); - - // add the left child to the fanins - pNext = Aig_ObjFanin0(pFaninBest); - if ( !pNext->fMarkA ) - { -//printf( "Adding fanin %s.\n", Aig_ObjName(pNext) ); - pNext->fMarkA = 1; - Vec_PtrPush( vFront, pNext ); - Vec_PtrPush( vVisited, pNext ); - } - // add the right child to the fanins - pNext = Aig_ObjFanin1(pFaninBest); - if ( !pNext->fMarkA ) - { -//printf( "Adding fanin %s.\n", Aig_ObjName(pNext) ); - pNext->fMarkA = 1; - Vec_PtrPush( vFront, pNext ); - Vec_PtrPush( vVisited, pNext ); - } - assert( Vec_PtrSize(vFront) <= nSizeLimit ); - // keep doing this - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes one sequential cut of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ) -{ - Aig_Obj_t * pNode; - int i; - - assert( !Aig_IsComplement(pRoot) ); - assert( Aig_ObjIsNode(pRoot) ); - assert( Aig_ObjChild0(pRoot) ); - assert( Aig_ObjChild1(pRoot) ); - - // start the cut - Vec_PtrClear( vFront ); - Vec_PtrPush( vFront, Aig_ObjFanin0(pRoot) ); - Vec_PtrPush( vFront, Aig_ObjFanin1(pRoot) ); - - // start the visited nodes - Vec_PtrClear( vVisited ); - Vec_PtrPush( vVisited, pRoot ); - Vec_PtrPush( vVisited, Aig_ObjFanin0(pRoot) ); - Vec_PtrPush( vVisited, Aig_ObjFanin1(pRoot) ); - - // mark these nodes - assert( !pRoot->fMarkA ); - assert( !Aig_ObjFanin0(pRoot)->fMarkA ); - assert( !Aig_ObjFanin1(pRoot)->fMarkA ); - pRoot->fMarkA = 1; - Aig_ObjFanin0(pRoot)->fMarkA = 1; - Aig_ObjFanin1(pRoot)->fMarkA = 1; - - // compute the cut - while ( Aig_ManFindCut_int( vFront, vVisited, nSizeLimit, nFanoutLimit ) ); - assert( Vec_PtrSize(vFront) <= nSizeLimit ); - - // clean the visit markings - Vec_PtrForEachEntry( vVisited, pNode, i ) - pNode->fMarkA = 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/aig_.c b/src/aig/aig/aig_.c deleted file mode 100644 index b2313d35..00000000 --- a/src/aig/aig/aig_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [aig_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: aig_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/aig/module.make b/src/aig/aig/module.make deleted file mode 100644 index c35e7121..00000000 --- a/src/aig/aig/module.make +++ /dev/null @@ -1,21 +0,0 @@ -SRC += src/aig/aig/aigCheck.c \ - src/aig/aig/aigDfs.c \ - src/aig/aig/aigFanout.c \ - src/aig/aig/aigMan.c \ - src/aig/aig/aigMem.c \ - src/aig/aig/aigMffc.c \ - src/aig/aig/aigObj.c \ - src/aig/aig/aigOper.c \ - src/aig/aig/aigOrder.c \ - src/aig/aig/aigPart.c \ - src/aig/aig/aigRepr.c \ - src/aig/aig/aigRet.c \ - src/aig/aig/aigScl.c \ - src/aig/aig/aigSeq.c \ - src/aig/aig/aigTable.c \ - src/aig/aig/aigTime.c \ - src/aig/aig/aigTiming.c \ - src/aig/aig/aigTruth.c \ - src/aig/aig/aigTsim.c \ - src/aig/aig/aigUtil.c \ - src/aig/aig/aigWin.c \ No newline at end of file diff --git a/src/aig/bar/bar.c b/src/aig/bar/bar.c deleted file mode 100644 index 8c215b48..00000000 --- a/src/aig/bar/bar.c +++ /dev/null @@ -1,177 +0,0 @@ -/**CFile**************************************************************** - - FileName [bar.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [Progress bar.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bar.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include -#include -#include "bar.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Bar_Progress_t_ -{ - int nItemsNext; // the number of items for the next update of the progress bar - int nItemsTotal; // the total number of items - int posTotal; // the total number of positions - int posCur; // the current position - FILE * pFile; // the output stream -}; - -static void Bar_ProgressShow( Bar_Progress_t * p, char * pString ); -static void Bar_ProgressClean( Bar_Progress_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the progress bar.] - - Description [The first parameter is the output stream (pFile), where - the progress is printed. The current printing position should be the - first one on the given line. The second parameters is the total - number of items that correspond to 100% position of the progress bar.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bar_Progress_t * Bar_ProgressStart( FILE * pFile, int nItemsTotal ) -{ - Bar_Progress_t * p; -// extern int Abc_FrameShowProgress( void * p ); -// extern void * Abc_FrameGetGlobalFrame(); -// if ( !Abc_FrameShowProgress(Abc_FrameGetGlobalFrame()) ) return NULL; - p = (Bar_Progress_t *) malloc(sizeof(Bar_Progress_t)); - memset( p, 0, sizeof(Bar_Progress_t) ); - p->pFile = pFile; - p->nItemsTotal = nItemsTotal; - p->posTotal = 78; - p->posCur = 1; - p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); - Bar_ProgressShow( p, NULL ); - return p; -} - -/**Function************************************************************* - - Synopsis [Updates the progress bar.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bar_ProgressUpdate_int( Bar_Progress_t * p, int nItemsCur, char * pString ) -{ - if ( p == NULL ) return; - if ( nItemsCur < p->nItemsNext ) - return; - if ( nItemsCur >= p->nItemsTotal ) - { - p->posCur = 78; - p->nItemsNext = 0x7FFFFFFF; - } - else - { - p->posCur += 7; - p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); - } - Bar_ProgressShow( p, pString ); -} - - -/**Function************************************************************* - - Synopsis [Stops the progress bar.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bar_ProgressStop( Bar_Progress_t * p ) -{ - if ( p == NULL ) return; - Bar_ProgressClean( p ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Prints the progress bar of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bar_ProgressShow( Bar_Progress_t * p, char * pString ) -{ - int i; - if ( p == NULL ) return; - if ( pString ) - fprintf( p->pFile, "%s ", pString ); - for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ ) - fprintf( p->pFile, "-" ); - if ( i == p->posCur ) - fprintf( p->pFile, ">" ); - for ( i++ ; i <= p->posTotal; i++ ) - fprintf( p->pFile, " " ); - fprintf( p->pFile, "\r" ); - fflush( stdout ); -} - -/**Function************************************************************* - - Synopsis [Cleans the progress bar before quitting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bar_ProgressClean( Bar_Progress_t * p ) -{ - int i; - if ( p == NULL ) return; - for ( i = 0; i <= p->posTotal; i++ ) - fprintf( p->pFile, " " ); - fprintf( p->pFile, "\r" ); - fflush( stdout ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/bar/bar.h b/src/aig/bar/bar.h deleted file mode 100644 index 814fbe6f..00000000 --- a/src/aig/bar/bar.h +++ /dev/null @@ -1,74 +0,0 @@ -/**CFile**************************************************************** - - FileName [bar.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Progress bar.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: bar.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __BAR_H__ -#define __BAR_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -#define BAR_PROGRESS_USE 1 - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Bar_Progress_t_ Bar_Progress_t; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== bar.c ==========================================================*/ -extern Bar_Progress_t * Bar_ProgressStart( FILE * pFile, int nItemsTotal ); -extern void Bar_ProgressStop( Bar_Progress_t * p ); -extern void Bar_ProgressUpdate_int( Bar_Progress_t * p, int nItemsCur, char * pString ); - -static inline void Bar_ProgressUpdate( Bar_Progress_t * p, int nItemsCur, char * pString ) { - if ( BAR_PROGRESS_USE && p && (nItemsCur < *((int*)p)) ) return; Bar_ProgressUpdate_int(p, nItemsCur, pString); } - - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/bar/module.make b/src/aig/bar/module.make deleted file mode 100644 index 26161ba1..00000000 --- a/src/aig/bar/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += src/aig/bar/bar.c diff --git a/src/aig/bdc/bdc.h b/src/aig/bdc/bdc.h deleted file mode 100644 index 71875edb..00000000 --- a/src/aig/bdc/bdc.h +++ /dev/null @@ -1,73 +0,0 @@ -/**CFile**************************************************************** - - FileName [bdc.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Truth-table-based bi-decomposition engine.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 30, 2007.] - - Revision [$Id: bdc.h,v 1.00 2007/01/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __BDC_H__ -#define __BDC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Bdc_Man_t_ Bdc_Man_t; -typedef struct Bdc_Par_t_ Bdc_Par_t; -struct Bdc_Par_t_ -{ - // general parameters - int nVarsMax; // the maximum support - int fVerbose; // enable basic stats - int fVeryVerbose; // enable detailed stats -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== bdcCore.c ==========================================================*/ -extern Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ); -extern void Bdc_ManFree( Bdc_Man_t * p ); -extern int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesLimit ); - - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/bdc/bdcCore.c b/src/aig/bdc/bdcCore.c deleted file mode 100644 index 157927b1..00000000 --- a/src/aig/bdc/bdcCore.c +++ /dev/null @@ -1,189 +0,0 @@ -/**CFile**************************************************************** - - FileName [bdcCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Truth-table-based bi-decomposition engine.] - - Synopsis [The gateway to bi-decomposition.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 30, 2007.] - - Revision [$Id: bdcCore.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bdcInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocate resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bdc_Man_t * Bdc_ManAlloc( Bdc_Par_t * pPars ) -{ - Bdc_Man_t * p; - unsigned * pData; - int i, k, nBits; - p = ALLOC( Bdc_Man_t, 1 ); - memset( p, 0, sizeof(Bdc_Man_t) ); - assert( pPars->nVarsMax > 3 && pPars->nVarsMax < 16 ); - p->pPars = pPars; - p->nWords = Kit_TruthWordNum( pPars->nVarsMax ); - p->nDivsLimit = 200; - p->nNodesLimit = 0; // will be set later - // memory - p->vMemory = Vec_IntStart( 1 << 16 ); - // internal nodes - p->nNodesAlloc = 512; - p->pNodes = ALLOC( Bdc_Fun_t, p->nNodesAlloc ); - // set up hash table - p->nTableSize = (1 << p->pPars->nVarsMax); - p->pTable = ALLOC( Bdc_Fun_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Bdc_Fun_t *) * p->nTableSize ); - p->vSpots = Vec_IntAlloc( 256 ); - // truth tables - p->vTruths = Vec_PtrAllocSimInfo( pPars->nVarsMax + 5, p->nWords ); - // set elementary truth tables - nBits = (1 << pPars->nVarsMax); - Kit_TruthFill( Vec_PtrEntry(p->vTruths, 0), p->nVars ); - for ( k = 0; k < pPars->nVarsMax; k++ ) - { - pData = Vec_PtrEntry( p->vTruths, k+1 ); - Kit_TruthClear( pData, p->nVars ); - for ( i = 0; i < nBits; i++ ) - if ( i & (1 << k) ) - pData[i>>5] |= (1 << (i&31)); - } - p->puTemp1 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 1 ); - p->puTemp2 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 2 ); - p->puTemp3 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 3 ); - p->puTemp4 = Vec_PtrEntry( p->vTruths, pPars->nVarsMax + 4 ); - // start the internal ISFs - p->pIsfOL = &p->IsfOL; Bdc_IsfStart( p, p->pIsfOL ); - p->pIsfOR = &p->IsfOR; Bdc_IsfStart( p, p->pIsfOR ); - p->pIsfAL = &p->IsfAL; Bdc_IsfStart( p, p->pIsfAL ); - p->pIsfAR = &p->IsfAR; Bdc_IsfStart( p, p->pIsfAR ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocate resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_ManFree( Bdc_Man_t * p ) -{ - Vec_IntFree( p->vMemory ); - Vec_IntFree( p->vSpots ); - Vec_PtrFree( p->vTruths ); - free( p->pNodes ); - free( p->pTable ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Clears the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_ManPrepare( Bdc_Man_t * p, Vec_Ptr_t * vDivs ) -{ - unsigned * puTruth; - Bdc_Fun_t * pNode; - int i; - Bdc_TableClear( p ); - Vec_IntClear( p->vMemory ); - // add constant 1 and elementary vars - p->nNodes = p->nNodesNew = 0; - for ( i = 0; i <= p->pPars->nVarsMax; i++ ) - { - pNode = Bdc_FunNew( p ); - pNode->Type = BDC_TYPE_PI; - pNode->puFunc = Vec_PtrEntry( p->vTruths, i ); - pNode->uSupp = i? (1 << (i-1)) : 0; - Bdc_TableAdd( p, pNode ); - } - // add the divisors - Vec_PtrForEachEntry( vDivs, puTruth, i ) - { - pNode = Bdc_FunNew( p ); - pNode->Type = BDC_TYPE_PI; - pNode->puFunc = puTruth; - pNode->uSupp = Kit_TruthSupport( puTruth, p->nVars ); - Bdc_TableAdd( p, pNode ); - if ( i == p->nDivsLimit ) - break; - } -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of one function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_ManDecompose( Bdc_Man_t * p, unsigned * puFunc, unsigned * puCare, int nVars, Vec_Ptr_t * vDivs, int nNodesMax ) -{ - Bdc_Isf_t Isf, * pIsf = &Isf; - // set current manager parameters - p->nVars = nVars; - p->nWords = Kit_TruthWordNum( nVars ); - Bdc_ManPrepare( p, vDivs ); - p->nNodesLimit = (p->nNodes + nNodesMax < p->nNodesAlloc)? p->nNodes + nNodesMax : p->nNodesAlloc; - // copy the function - Bdc_IsfStart( p, pIsf ); - Bdc_IsfClean( pIsf ); - pIsf->uSupp = Kit_TruthSupport( puFunc, p->nVars ) | Kit_TruthSupport( puCare, p->nVars ); - Kit_TruthAnd( pIsf->puOn, puCare, puFunc, p->nVars ); - Kit_TruthSharp( pIsf->puOff, puCare, puFunc, p->nVars ); - // call decomposition - Bdc_SuppMinimize( p, pIsf ); - p->pRoot = Bdc_ManDecompose_rec( p, pIsf ); - if ( p->pRoot == NULL ) - return -1; - return p->nNodesNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/bdc/bdcDec.c b/src/aig/bdc/bdcDec.c deleted file mode 100644 index 747fcb14..00000000 --- a/src/aig/bdc/bdcDec.c +++ /dev/null @@ -1,461 +0,0 @@ -/**CFile**************************************************************** - - FileName [bdcDec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Truth-table-based bi-decomposition engine.] - - Synopsis [Decomposition procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 30, 2007.] - - Revision [$Id: bdcDec.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bdcInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ); -static int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, unsigned * puTruth, Bdc_Type_t Type ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs one step of bi-decomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) -{ - Bdc_Fun_t * pFunc; - Bdc_Isf_t IsfL, * pIsfL = &IsfL; - Bdc_Isf_t IsfB, * pIsfR = &IsfB; - // check computed results - if ( pFunc = Bdc_TableLookup( p, pIsf ) ) - return pFunc; - // decide on the decomposition type - pFunc = Bdc_FunNew( p ); - if ( pFunc == NULL ) - return NULL; - pFunc->Type = Bdc_DecomposeStep( p, pIsf, pIsfL, pIsfR ); - // decompose the left branch - pFunc->pFan0 = Bdc_ManDecompose_rec( p, pIsfL ); - if ( pFunc->pFan0 == NULL ) - return NULL; - // decompose the right branch - if ( Bdc_DecomposeUpdateRight( p, pIsf, pIsfL, pIsfR, pFunc->pFan0->puFunc, pFunc->Type ) ) - { - p->nNodes--; - return pFunc->pFan0; - } - pFunc->pFan1 = Bdc_ManDecompose_rec( p, pIsfL ); - if ( pFunc->pFan1 == NULL ) - return NULL; - // compute the function of node - pFunc->puFunc = (unsigned *)Vec_IntFetch(p->vMemory, p->nWords); - if ( pFunc->Type == BDC_TYPE_AND ) - Kit_TruthAnd( pFunc->puFunc, pFunc->pFan0->puFunc, pFunc->pFan1->puFunc, p->nVars ); - else if ( pFunc->Type == BDC_TYPE_OR ) - Kit_TruthOr( pFunc->puFunc, pFunc->pFan0->puFunc, pFunc->pFan1->puFunc, p->nVars ); - else - assert( 0 ); - // verify correctness - assert( Bdc_TableCheckContainment(p, pIsf, pFunc->puFunc) ); - // convert from OR to AND - if ( pFunc->Type == BDC_TYPE_OR ) - { - pFunc->Type = BDC_TYPE_AND; - pFunc->pFan0 = Bdc_Not(pFunc->pFan0); - pFunc->pFan1 = Bdc_Not(pFunc->pFan1); - Kit_TruthNot( pFunc->puFunc, pFunc->puFunc, p->nVars ); - pFunc = Bdc_Not(pFunc); - } - Bdc_TableAdd( p, Bdc_Regular(pFunc) ); - return pFunc; -} - -/**Function************************************************************* - - Synopsis [Updates the ISF of the right after the left was decompoosed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_DecomposeUpdateRight( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR, unsigned * puTruth, Bdc_Type_t Type ) -{ - if ( Type == BDC_TYPE_OR ) - { -// Right.Q = bdd_appex( Q, CompSpecLeftF, bddop_diff, setRightRes ); -// Right.R = bdd_exist( R, setRightRes ); - -// if ( pR->Q ) Cudd_RecursiveDeref( dd, pR->Q ); -// if ( pR->R ) Cudd_RecursiveDeref( dd, pR->R ); -// pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Cudd_Not(CompSpecF), pL->V ); Cudd_Ref( pR->Q ); -// pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( pR->R ); - -// assert( pR->R != b0 ); -// return (int)( pR->Q == b0 ); - - Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars ); - Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp ); - Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uSupp ); - assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) ); - return Kit_TruthIsConst0(pIsfR->puOn, p->nVars); - } - else if ( Type == BDC_TYPE_AND ) - { -// Right.R = bdd_appex( R, CompSpecLeftF, bddop_and, setRightRes ); -// Right.Q = bdd_exist( Q, setRightRes ); - -// if ( pR->Q ) Cudd_RecursiveDeref( dd, pR->Q ); -// if ( pR->R ) Cudd_RecursiveDeref( dd, pR->R ); -// pR->R = Cudd_bddAndAbstract( dd, pF->R, CompSpecF, pL->V ); Cudd_Ref( pR->R ); -// pR->Q = Cudd_bddExistAbstract( dd, pF->Q, pL->V ); Cudd_Ref( pR->Q ); - -// assert( pR->Q != b0 ); -// return (int)( pR->R == b0 ); - - Kit_TruthSharp( pIsfR->puOn, pIsf->puOn, puTruth, p->nVars ); - Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp ); - Kit_TruthExistSet( pIsfR->puOff, pIsf->puOff, p->nVars, pIsfL->uSupp ); - assert( !Kit_TruthIsConst0(pIsfR->puOff, p->nVars) ); - return Kit_TruthIsConst0(pIsfR->puOn, p->nVars); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Checks existence of OR-bidecomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Bdc_DecomposeGetCost( Bdc_Man_t * p, int nLeftVars, int nRightVars ) -{ - assert( nLeftVars > 0 ); - assert( nRightVars > 0 ); - // compute the decomposition coefficient - if ( nLeftVars >= nRightVars ) - return BDC_SCALE * (p->nVars * nRightVars + nLeftVars); - else // if ( nLeftVars < nRightVars ) - return BDC_SCALE * (p->nVars * nLeftVars + nRightVars); -} - -/**Function************************************************************* - - Synopsis [Checks existence of weak OR-bidecomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_DecomposeFindInitialVarSet( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) -{ - char pVars[16]; - int v, nVars, Beg, End; - - assert( pIsfL->uSupp == 0 ); - assert( pIsfR->uSupp == 0 ); - - // fill in the variables - nVars = 0; - for ( v = 0; v < p->nVars; v++ ) - if ( pIsf->uSupp & (1 << v) ) - pVars[nVars++] = v; - - // try variable pairs - for ( Beg = 0; Beg < nVars; Beg++ ) - { - Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, pVars[Beg] ); - for ( End = nVars - 1; End > Beg; End-- ) - { - Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pVars[End] ); - if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp1, p->puTemp2, p->nVars) ) - { - pIsfL->uSupp = (1 << Beg); - pIsfR->uSupp = (1 << End); - pIsfL->Var = Beg; - pIsfR->Var = End; - return 1; - } - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Checks existence of weak OR-bidecomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_DecomposeWeakOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) -{ - int v, VarCost, VarBest, Cost, VarCostBest = 0; - - for ( v = 0; v < p->nVars; v++ ) - { - Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, v ); -// if ( (Q & !bdd_exist( R, VarSetXa )) != bddfalse ) -// Exist = Cudd_bddExistAbstract( dd, pF->R, Var ); Cudd_Ref( Exist ); -// if ( Cudd_bddIteConstant( dd, pF->Q, Cudd_Not(Exist), b0 ) != b0 ) - if ( !Kit_TruthIsImply( pIsf->puOn, p->puTemp1, p->nVars ) ) - { - // measure the cost of this variable -// VarCost = bdd_satcountset( bdd_forall( Q, VarSetXa ), VarCube ); - -// Univ = Cudd_bddUnivAbstract( dd, pF->Q, Var ); Cudd_Ref( Univ ); -// VarCost = Kit_TruthCountOnes( Univ, p->nVars ); -// Cudd_RecursiveDeref( dd, Univ ); - - Kit_TruthForallNew( p->puTemp2, pIsf->puOn, p->nVars, v ); - VarCost = Kit_TruthCountOnes( p->puTemp2, p->nVars ); - if ( VarCost == 0 ) - VarCost = 1; - if ( VarCostBest < VarCost ) - { - VarCostBest = VarCost; - VarBest = v; - } - } - } - - // derive the components for weak-bi-decomposition if the variable is found - if ( VarCostBest ) - { -// funQLeftRes = Q & bdd_exist( R, setRightORweak ); - -// Temp = Cudd_bddExistAbstract( dd, pF->R, VarBest ); Cudd_Ref( Temp ); -// pL->Q = Cudd_bddAnd( dd, pF->Q, Temp ); Cudd_Ref( pL->Q ); -// Cudd_RecursiveDeref( dd, Temp ); - - Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, VarBest ); - Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars ); - -// pL->R = pF->R; Cudd_Ref( pL->R ); -// pL->V = VarBest; Cudd_Ref( pL->V ); - Kit_TruthCopy( pIsfL->puOff, pIsf->puOff, p->nVars ); - pIsfL->Var = VarBest; - -// assert( pL->Q != b0 ); -// assert( pL->R != b0 ); -// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 ); - - // express cost in percents of the covered boolean space - Cost = VarCostBest * BDC_SCALE / (1<nVars); - if ( Cost == 0 ) - Cost = 1; - return Cost; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Checks existence of OR-bidecomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_DecomposeOr( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) -{ - unsigned uSuppRem; - int v, nLeftVars = 1, nRightVars = 1; - // clean the var sets - Bdc_IsfClean( pIsfL ); - Bdc_IsfClean( pIsfR ); - // find initial variable sets - if ( !Bdc_DecomposeFindInitialVarSet( p, pIsf, pIsfL, pIsfR ) ) - return Bdc_DecomposeWeakOr( p, pIsf, pIsfL, pIsfR ); - // prequantify the variables in the offset - Kit_TruthExistNew( p->puTemp1, pIsf->puOff, p->nVars, pIsfL->Var ); - Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, pIsfR->Var ); - // go through the remaining variables - uSuppRem = pIsf->uSupp & ~pIsfL->uSupp & ~pIsfR->uSupp; - assert( Kit_WordCountOnes(uSuppRem) > 0 ); - for ( v = 0; v < p->nVars; v++ ) - { - if ( (uSuppRem & (1 << v)) == 0 ) - continue; - // prequantify this variable - Kit_TruthExistNew( p->puTemp3, p->puTemp1, p->nVars, v ); - Kit_TruthExistNew( p->puTemp4, p->puTemp2, p->nVars, v ); - if ( nLeftVars < nRightVars ) - { -// if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse ) -// if ( VerifyORCondition( dd, pF->Q, pF->R, pL->V, pR->V, VarNew ) ) - if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) ) - { -// pL->V &= VarNew; - pIsfL->uSupp |= (1 << v); - nLeftVars++; - } -// else if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse ) - else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) ) - { -// pR->V &= VarNew; - pIsfR->uSupp |= (1 << v); - nRightVars++; - } - } - else - { -// if ( (Q & bdd_exist( pF->R, pR->V & VarNew ) & bdd_exist( pF->R, pL->V )) == bddfalse ) - if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp4, p->puTemp1, p->nVars) ) - { -// pR->V &= VarNew; - pIsfR->uSupp |= (1 << v); - nRightVars++; - } -// else if ( (Q & bdd_exist( pF->R, pL->V & VarNew ) & bdd_exist( pF->R, pR->V )) == bddfalse ) - else if ( Kit_TruthIsDisjoint3(pIsf->puOn, p->puTemp3, p->puTemp2, p->nVars) ) - { -// pL->V &= VarNew; - pIsfL->uSupp |= (1 << v); - nLeftVars++; - } - } - } - - // derive the functions Q and R for the left branch -// pL->Q = bdd_appex( pF->Q, bdd_exist( pF->R, pL->V ), bddop_and, pR->V ); -// pL->R = bdd_exist( pF->R, pR->V ); - -// Temp = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( Temp ); -// pL->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pR->V ); Cudd_Ref( pL->Q ); -// Cudd_RecursiveDeref( dd, Temp ); -// pL->R = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( pL->R ); - - Kit_TruthAnd( pIsfL->puOn, pIsf->puOn, p->puTemp1, p->nVars ); - Kit_TruthExistSet( pIsfL->puOn, pIsfL->puOn, p->nVars, pIsfR->uSupp ); - Kit_TruthCopy( pIsfL->puOff, p->puTemp2, p->nVars ); - - // derive the functions Q and R for the right branch -// Temp = Cudd_bddExistAbstract( dd, pF->R, pR->V ); Cudd_Ref( Temp ); -// pR->Q = Cudd_bddAndAbstract( dd, pF->Q, Temp, pL->V ); Cudd_Ref( pR->Q ); -// Cudd_RecursiveDeref( dd, Temp ); -// pR->R = Cudd_bddExistAbstract( dd, pF->R, pL->V ); Cudd_Ref( pR->R ); - -/* - Kit_TruthAnd( pIsfR->puOn, pIsf->puOn, p->puTemp2, p->nVars ); - Kit_TruthExistSet( pIsfR->puOn, pIsfR->puOn, p->nVars, pIsfL->uSupp ); - Kit_TruthCopy( pIsfR->puOff, p->puTemp1, p->nVars ); -*/ - -// assert( pL->Q != b0 ); -// assert( pL->R != b0 ); -// assert( Cudd_bddIteConstant( dd, pL->Q, pL->R, b0 ) == b0 ); - assert( !Kit_TruthIsConst0(pIsfL->puOn, p->nVars) ); - assert( !Kit_TruthIsConst0(pIsfL->puOff, p->nVars) ); - assert( Kit_TruthIsDisjoint(pIsfL->puOn, pIsfL->puOff, p->nVars) ); - - return Bdc_DecomposeGetCost( p, nLeftVars, nRightVars ); -} - -/**Function************************************************************* - - Synopsis [Performs one step of bi-decomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bdc_Type_t Bdc_DecomposeStep( Bdc_Man_t * p, Bdc_Isf_t * pIsf, Bdc_Isf_t * pIsfL, Bdc_Isf_t * pIsfR ) -{ - int CostOr, CostAnd, CostOrL, CostOrR, CostAndL, CostAndR; - - Bdc_IsfClean( p->pIsfOL ); - Bdc_IsfClean( p->pIsfOR ); - Bdc_IsfClean( p->pIsfAL ); - Bdc_IsfClean( p->pIsfAR ); - - // perform OR decomposition - CostOr = Bdc_DecomposeOr( p, pIsf, p->pIsfOL, p->pIsfOR ); - - // perform AND decomposition - Bdc_IsfNot( pIsf ); - CostAnd = Bdc_DecomposeOr( p, pIsf, p->pIsfAL, p->pIsfAR ); - Bdc_IsfNot( pIsf ); - Bdc_IsfNot( p->pIsfAL ); - Bdc_IsfNot( p->pIsfAR ); - - // check the hash table - Bdc_SuppMinimize( p, p->pIsfOL ); - CostOrL = (Bdc_TableLookup(p, p->pIsfOL) != NULL); - Bdc_SuppMinimize( p, p->pIsfOR ); - CostOrR = (Bdc_TableLookup(p, p->pIsfOR) != NULL); - Bdc_SuppMinimize( p, p->pIsfAL ); - CostAndL = (Bdc_TableLookup(p, p->pIsfAL) != NULL); - Bdc_SuppMinimize( p, p->pIsfAR ); - CostAndR = (Bdc_TableLookup(p, p->pIsfAR) != NULL); - - // check if there is any reuse for the components - if ( CostOrL + CostOrR < CostAndL + CostAndR ) - { - Bdc_IsfCopy( pIsfL, p->pIsfOL ); - Bdc_IsfCopy( pIsfR, p->pIsfOR ); - return BDC_TYPE_OR; - } - if ( CostOrL + CostOrR > CostAndL + CostAndR ) - { - Bdc_IsfCopy( pIsfL, p->pIsfAL ); - Bdc_IsfCopy( pIsfR, p->pIsfAR ); - return BDC_TYPE_AND; - } - - // compare the two-component costs - if ( CostOr < CostAnd ) - { - Bdc_IsfCopy( pIsfL, p->pIsfOL ); - Bdc_IsfCopy( pIsfR, p->pIsfOR ); - return BDC_TYPE_OR; - } - return BDC_TYPE_AND; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/bdc/bdcInt.h b/src/aig/bdc/bdcInt.h deleted file mode 100644 index 9649f870..00000000 --- a/src/aig/bdc/bdcInt.h +++ /dev/null @@ -1,150 +0,0 @@ -/**CFile**************************************************************** - - FileName [bdcInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Truth-table-based bi-decomposition engine.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __BDC_INT_H__ -#define __BDC_INT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "kit.h" -#include "bdc.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -#define BDC_SCALE 100 // value used to compute the cost - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// network types -typedef enum { - BDC_TYPE_NONE = 0, // 0: unknown - BDC_TYPE_CONST1, // 1: constant 1 - BDC_TYPE_PI, // 2: primary input - BDC_TYPE_AND, // 4: AND-gate - BDC_TYPE_OR, // 5: OR-gate (temporary) - BDC_TYPE_XOR, // 6: XOR-gate - BDC_TYPE_MUX, // 7: MUX-gate - BDC_TYPE_OTHER // 8: unused -} Bdc_Type_t; - -typedef struct Bdc_Fun_t_ Bdc_Fun_t; -struct Bdc_Fun_t_ -{ - int Type; // Const1, PI, AND, XOR, MUX - Bdc_Fun_t * pFan0; // fanin of the given node - Bdc_Fun_t * pFan1; // fanin of the given node - Bdc_Fun_t * pFan2; // fanin of the given node - unsigned uSupp; // bit mask of current support - unsigned * puFunc; // the function of the node - Bdc_Fun_t * pNext; // next function with same support - void * pCopy; // the copy field -}; - -typedef struct Bdc_Isf_t_ Bdc_Isf_t; -struct Bdc_Isf_t_ -{ - int Var; // the first variable assigned - unsigned uSupp; // the current support - unsigned * puOn; // on-set - unsigned * puOff; // off-set -}; - -struct Bdc_Man_t_ -{ - // external parameters - Bdc_Par_t * pPars; // parameter set - int nVars; // the number of variables - int nWords; // the number of words - int nNodesLimit; // the limit on the number of new nodes - int nDivsLimit; // the limit on the number of divisors - // internal nodes - Bdc_Fun_t * pNodes; // storage for decomposition nodes - int nNodes; // the number of nodes used - int nNodesNew; // the number of nodes used - int nNodesAlloc; // the number of nodes allocated - Bdc_Fun_t * pRoot; // the root node - // resub candidates - Bdc_Fun_t ** pTable; // hash table of candidates - int nTableSize; // hash table size (1 << nVarsMax) - Vec_Int_t * vSpots; // the occupied spots in the table - // elementary truth tables - Vec_Ptr_t * vTruths; // for const 1 and elementary variables - unsigned * puTemp1; // temporary truth table - unsigned * puTemp2; // temporary truth table - unsigned * puTemp3; // temporary truth table - unsigned * puTemp4; // temporary truth table - // temporary ISFs - Bdc_Isf_t * pIsfOL, IsfOL; - Bdc_Isf_t * pIsfOR, IsfOR; - Bdc_Isf_t * pIsfAL, IsfAL; - Bdc_Isf_t * pIsfAR, IsfAR; - // internal memory manager - Vec_Int_t * vMemory; // memory for internal truth tables -}; - -// working with complemented attributes of objects -static inline int Bdc_IsComplement( Bdc_Fun_t * p ) { return (int)((unsigned long)p & (unsigned long)01); } -static inline Bdc_Fun_t * Bdc_Regular( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((unsigned long)p & ~(unsigned long)01); } -static inline Bdc_Fun_t * Bdc_Not( Bdc_Fun_t * p ) { return (Bdc_Fun_t *)((unsigned long)p ^ (unsigned long)01); } -static inline Bdc_Fun_t * Bdc_NotCond( Bdc_Fun_t * p, int c ) { return (Bdc_Fun_t *)((unsigned long)p ^ (unsigned long)(c!=0)); } - -static inline Bdc_Fun_t * Bdc_FunNew( Bdc_Man_t * p ) { Bdc_Fun_t * pRes; if ( p->nNodes == p->nNodesLimit ) return NULL; pRes = p->pNodes + p->nNodes++; memset( pRes, 0, sizeof(Bdc_Fun_t) ); p->nNodesNew++; return pRes; } -static inline void Bdc_IsfStart( Bdc_Man_t * p, Bdc_Isf_t * pF ) { pF->puOn = Vec_IntFetch( p->vMemory, p->nWords ); pF->puOff = Vec_IntFetch( p->vMemory, p->nWords ); } -static inline void Bdc_IsfClean( Bdc_Isf_t * p ) { p->uSupp = 0; p->Var = 0; } -static inline void Bdc_IsfCopy( Bdc_Isf_t * p, Bdc_Isf_t * q ) { Bdc_Isf_t T = *p; *p = *q; *q = T; } -static inline void Bdc_IsfNot( Bdc_Isf_t * p ) { unsigned * puT = p->puOn; p->puOn = p->puOff; p->puOff = puT; } - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== bdcDec.c ==========================================================*/ -extern Bdc_Fun_t * Bdc_ManDecompose_rec( Bdc_Man_t * p, Bdc_Isf_t * pIsf ); -/*=== bdcTable.c ==========================================================*/ -extern Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf ); -extern void Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc ); -extern void Bdc_TableClear( Bdc_Man_t * p ); -extern void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ); -extern int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/bdc/bdcTable.c b/src/aig/bdc/bdcTable.c deleted file mode 100644 index d86a938d..00000000 --- a/src/aig/bdc/bdcTable.c +++ /dev/null @@ -1,140 +0,0 @@ -/**CFile**************************************************************** - - FileName [bdcTable.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Truth-table-based bi-decomposition engine.] - - Synopsis [Hash table for intermediate nodes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 30, 2007.] - - Revision [$Id: bdcTable.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bdcInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Minimizes the support of the ISF.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_SuppMinimize( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) -{ - int v; - // go through the support variables - for ( v = 0; v < p->nVars; v++ ) - { - if ( (pIsf->uSupp & (1 << v)) == 0 ) - continue; - Kit_TruthExistNew( p->puTemp1, pIsf->puOn, p->nVars, v ); - Kit_TruthExistNew( p->puTemp2, pIsf->puOff, p->nVars, v ); - if ( !Kit_TruthIsDisjoint( p->puTemp1, p->puTemp2, p->nVars ) ) - continue; - // remove the variable - Kit_TruthCopy( pIsf->puOn, p->puTemp1, p->nVars ); - Kit_TruthCopy( pIsf->puOff, p->puTemp2, p->nVars ); - pIsf->uSupp &= ~(1 << v); - } -} - -/**Function************************************************************* - - Synopsis [Checks containment of the function in the ISF.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Bdc_TableCheckContainment( Bdc_Man_t * p, Bdc_Isf_t * pIsf, unsigned * puTruth ) -{ - return Kit_TruthIsImply( pIsf->puOn, puTruth, p->nVars ) && - Kit_TruthIsDisjoint( pIsf->puOff, puTruth, p->nVars ); -} - -/**Function************************************************************* - - Synopsis [Adds the new entry to the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Bdc_Fun_t * Bdc_TableLookup( Bdc_Man_t * p, Bdc_Isf_t * pIsf ) -{ - Bdc_Fun_t * pFunc; - for ( pFunc = p->pTable[pIsf->uSupp]; pFunc; pFunc = pFunc->pNext ) - if ( Bdc_TableCheckContainment( p, pIsf, pFunc->puFunc ) ) - return pFunc; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Adds the new entry to the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_TableAdd( Bdc_Man_t * p, Bdc_Fun_t * pFunc ) -{ - if ( p->pTable[pFunc->uSupp] == NULL ) - Vec_IntPush( p->vSpots, pFunc->uSupp ); - pFunc->pNext = p->pTable[pFunc->uSupp]; - p->pTable[pFunc->uSupp] = pFunc; -} - -/**Function************************************************************* - - Synopsis [Adds the new entry to the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Bdc_TableClear( Bdc_Man_t * p ) -{ - int Spot, i; - Vec_IntForEachEntry( p->vSpots, Spot, i ) - p->pTable[Spot] = NULL; - Vec_IntClear( p->vSpots ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/bdc/bdc_.c b/src/aig/bdc/bdc_.c deleted file mode 100644 index 9d0a9462..00000000 --- a/src/aig/bdc/bdc_.c +++ /dev/null @@ -1,49 +0,0 @@ -/**CFile**************************************************************** - - FileName [bdc_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Truth-table-based bi-decomposition engine.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 30, 2007.] - - Revision [$Id: bdc_.c,v 1.00 2007/01/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "bdcInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/bdc/module.make b/src/aig/bdc/module.make deleted file mode 100644 index 8697c998..00000000 --- a/src/aig/bdc/module.make +++ /dev/null @@ -1,4 +0,0 @@ -SRC += src/aig/bdc/bdcCore.c \ - src/aig/bdc/bdcDec.c \ - src/aig/bdc/bdcTable.c - diff --git a/src/aig/cnf/cnf.h b/src/aig/cnf/cnf.h deleted file mode 100644 index 5c7a594e..00000000 --- a/src/aig/cnf/cnf.h +++ /dev/null @@ -1,162 +0,0 @@ -/**CFile**************************************************************** - - FileName [cnf.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: cnf.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CNF_H__ -#define __CNF_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "vec.h" -#include "aig.h" -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Cnf_Man_t_ Cnf_Man_t; -typedef struct Cnf_Dat_t_ Cnf_Dat_t; -typedef struct Cnf_Cut_t_ Cnf_Cut_t; - -// the CNF asserting outputs of AIG to be 1 -struct Cnf_Dat_t_ -{ - Aig_Man_t * pMan; // the AIG manager, for which CNF is computed - int nVars; // the number of variables - int nLiterals; // the number of CNF literals - int nClauses; // the number of CNF clauses - int ** pClauses; // the CNF clauses - int * pVarNums; // the number of CNF variable for each node ID (-1 if unused) -}; - -// the cut used to represent node in the AIG -struct Cnf_Cut_t_ -{ - char nFanins; // the number of leaves - char Cost; // the cost of this cut - short nWords; // the number of words in truth table - Vec_Int_t * vIsop[2]; // neg/pos ISOPs - int pFanins[0]; // the fanins (followed by the truth table) -}; - -// the CNF computation manager -struct Cnf_Man_t_ -{ - Aig_Man_t * pManAig; // the underlying AIG manager - char * pSopSizes; // sizes of SOPs for 4-variable functions - char ** pSops; // the SOPs for 4-variable functions - int aArea; // the area of the mapping - Aig_MmFlex_t * pMemCuts; // memory manager for cuts - int nMergeLimit; // the limit on the size of merged cut - unsigned * pTruths[4]; // temporary truth tables - Vec_Int_t * vMemory; // memory for intermediate ISOP representation - int timeCuts; - int timeMap; - int timeSave; -}; - - -static inline Dar_Cut_t * Dar_ObjBestCut( Aig_Obj_t * pObj ) { Dar_Cut_t * pCut; int i; Dar_ObjForEachCut( pObj, pCut, i ) if ( pCut->fBest ) return pCut; return NULL; } - -static inline int Cnf_CutSopCost( Cnf_Man_t * p, Dar_Cut_t * pCut ) { return p->pSopSizes[pCut->uTruth] + p->pSopSizes[0xFFFF & ~pCut->uTruth]; } - -static inline int Cnf_CutLeaveNum( Cnf_Cut_t * pCut ) { return pCut->nFanins; } -static inline int * Cnf_CutLeaves( Cnf_Cut_t * pCut ) { return pCut->pFanins; } -static inline unsigned * Cnf_CutTruth( Cnf_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nFanins); } - -static inline Cnf_Cut_t * Cnf_ObjBestCut( Aig_Obj_t * pObj ) { return pObj->pData; } -static inline void Cnf_ObjSetBestCut( Aig_Obj_t * pObj, Cnf_Cut_t * pCut ) { pObj->pData = pCut; } - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator over leaves of the cut -#define Cnf_CutForEachLeaf( p, pCut, pLeaf, i ) \ - for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== cnfCore.c ========================================================*/ -extern Cnf_Dat_t * Cnf_Derive( Aig_Man_t * pAig, int nOutputs ); -extern Cnf_Man_t * Cnf_ManRead(); -extern void Cnf_ClearMemory(); -/*=== cnfCut.c ========================================================*/ -extern Cnf_Cut_t * Cnf_CutCreate( Cnf_Man_t * p, Aig_Obj_t * pObj ); -extern void Cnf_CutPrint( Cnf_Cut_t * pCut ); -extern void Cnf_CutFree( Cnf_Cut_t * pCut ); -extern void Cnf_CutUpdateRefs( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, Cnf_Cut_t * pCutRes ); -extern Cnf_Cut_t * Cnf_CutCompose( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int iFan ); -/*=== cnfData.c ========================================================*/ -extern void Cnf_ReadMsops( char ** ppSopSizes, char *** ppSops ); -/*=== cnfMan.c ========================================================*/ -extern Cnf_Man_t * Cnf_ManStart(); -extern void Cnf_ManStop( Cnf_Man_t * p ); -extern Vec_Int_t * Cnf_DataCollectPiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ); -extern void Cnf_DataFree( Cnf_Dat_t * p ); -extern void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable ); -void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p ); -/*=== cnfMap.c ========================================================*/ -extern void Cnf_DeriveMapping( Cnf_Man_t * p ); -extern int Cnf_ManMapForCnf( Cnf_Man_t * p ); -/*=== cnfPost.c ========================================================*/ -extern void Cnf_ManTransferCuts( Cnf_Man_t * p ); -extern void Cnf_ManFreeCuts( Cnf_Man_t * p ); -extern void Cnf_ManPostprocess( Cnf_Man_t * p ); -/*=== cnfUtil.c ========================================================*/ -extern Vec_Ptr_t * Aig_ManScanMapping( Cnf_Man_t * p, int fCollect ); -extern Vec_Ptr_t * Cnf_ManScanMapping( Cnf_Man_t * p, int fCollect, int fPreorder ); -/*=== cnfWrite.c ========================================================*/ -extern void Cnf_SopConvertToVector( char * pSop, int nCubes, Vec_Int_t * vCover ); -extern Cnf_Dat_t * Cnf_ManWriteCnf( Cnf_Man_t * p, Vec_Ptr_t * vMapped, int nOutputs ); -extern Cnf_Dat_t * Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/cnf/cnfCore.c b/src/aig/cnf/cnfCore.c deleted file mode 100644 index 06731451..00000000 --- a/src/aig/cnf/cnfCore.c +++ /dev/null @@ -1,185 +0,0 @@ -/**CFile**************************************************************** - - FileName [cnfCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG-to-CNF conversion.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: cnfCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cnf.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Cnf_Man_t * s_pManCnf = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Converts AIG into the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Dat_t * Cnf_Derive( Aig_Man_t * pAig, int nOutputs ) -{ - Cnf_Man_t * p; - Cnf_Dat_t * pCnf; - Vec_Ptr_t * vMapped; - Aig_MmFixed_t * pMemCuts; - int clk; - // allocate the CNF manager - if ( s_pManCnf == NULL ) - s_pManCnf = Cnf_ManStart(); - // connect the managers - p = s_pManCnf; - p->pManAig = pAig; - - // generate cuts for all nodes, assign cost, and find best cuts -clk = clock(); - pMemCuts = Dar_ManComputeCuts( pAig, 10 ); -p->timeCuts = clock() - clk; - - // find the mapping -clk = clock(); - Cnf_DeriveMapping( p ); -p->timeMap = clock() - clk; -// Aig_ManScanMapping( p, 1 ); - - // convert it into CNF -clk = clock(); - Cnf_ManTransferCuts( p ); - vMapped = Cnf_ManScanMapping( p, 1, 1 ); - pCnf = Cnf_ManWriteCnf( p, vMapped, nOutputs ); - Vec_PtrFree( vMapped ); - Aig_MmFixedStop( pMemCuts, 0 ); -p->timeSave = clock() - clk; - - // reset reference counters - Aig_ManResetRefs( pAig ); -//PRT( "Cuts ", p->timeCuts ); -//PRT( "Map ", p->timeMap ); -//PRT( "Saving ", p->timeSave ); - return pCnf; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Man_t * Cnf_ManRead() -{ - return s_pManCnf; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_ClearMemory() -{ - if ( s_pManCnf == NULL ) - return; - Cnf_ManStop( s_pManCnf ); - s_pManCnf = NULL; -} - - -#if 0 - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Dat_t * Cnf_Derive_old( Aig_Man_t * pAig ) -{ -/* - // iteratively improve area flow - for ( i = 0; i < nIters; i++ ) - { -clk = clock(); - Cnf_ManScanMapping( p, 0 ); - Cnf_ManMapForCnf( p ); -PRT( "iter ", clock() - clk ); - } -*/ - // write the file - vMapped = Aig_ManScanMapping( p, 1 ); - Vec_PtrFree( vMapped ); - -clk = clock(); - Cnf_ManTransferCuts( p ); - - Cnf_ManPostprocess( p ); - Cnf_ManScanMapping( p, 0 ); -/* - Cnf_ManPostprocess( p ); - Cnf_ManScanMapping( p, 0 ); - Cnf_ManPostprocess( p ); - Cnf_ManScanMapping( p, 0 ); -*/ -PRT( "Ext ", clock() - clk ); - -/* - vMapped = Cnf_ManScanMapping( p, 1 ); - pCnf = Cnf_ManWriteCnf( p, vMapped ); - Vec_PtrFree( vMapped ); - - // clean up - Cnf_ManFreeCuts( p ); - Dar_ManCutsFree( pAig ); - return pCnf; -*/ - Aig_MmFixedStop( pMemCuts, 0 ); - return NULL; -} - -#endif - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/cnf/cnfCut.c b/src/aig/cnf/cnfCut.c deleted file mode 100644 index 17ab0c78..00000000 --- a/src/aig/cnf/cnfCut.c +++ /dev/null @@ -1,371 +0,0 @@ -/**CFile**************************************************************** - - FileName [cnfCut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG-to-CNF conversion.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: cnfCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cnf.h" -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates cut of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Cut_t * Cnf_CutAlloc( Cnf_Man_t * p, int nLeaves ) -{ - Cnf_Cut_t * pCut; - int nSize = sizeof(Cnf_Cut_t) + sizeof(int) * nLeaves + sizeof(unsigned) * Aig_TruthWordNum(nLeaves); - pCut = (Cnf_Cut_t *)Aig_MmFlexEntryFetch( p->pMemCuts, nSize ); - pCut->nFanins = nLeaves; - pCut->nWords = Aig_TruthWordNum(nLeaves); - pCut->vIsop[0] = pCut->vIsop[1] = NULL; - return pCut; -} - -/**Function************************************************************* - - Synopsis [Deallocates cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CutFree( Cnf_Cut_t * pCut ) -{ - if ( pCut->vIsop[0] ) - Vec_IntFree( pCut->vIsop[0] ); - if ( pCut->vIsop[1] ) - Vec_IntFree( pCut->vIsop[1] ); -} - -/**Function************************************************************* - - Synopsis [Creates cut for the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Cut_t * Cnf_CutCreate( Cnf_Man_t * p, Aig_Obj_t * pObj ) -{ - Dar_Cut_t * pCutBest; - Cnf_Cut_t * pCut; - unsigned * pTruth; - assert( Aig_ObjIsNode(pObj) ); - pCutBest = Dar_ObjBestCut( pObj ); - assert( pCutBest != NULL ); - assert( pCutBest->nLeaves <= 4 ); - pCut = Cnf_CutAlloc( p, pCutBest->nLeaves ); - memcpy( pCut->pFanins, pCutBest->pLeaves, sizeof(int) * pCutBest->nLeaves ); - pTruth = Cnf_CutTruth(pCut); - *pTruth = (pCutBest->uTruth << 16) | pCutBest->uTruth; - pCut->Cost = Cnf_CutSopCost( p, pCutBest ); - return pCut; -} - -/**Function************************************************************* - - Synopsis [Deallocates cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CutPrint( Cnf_Cut_t * pCut ) -{ - int i; - printf( "{" ); - for ( i = 0; i < pCut->nFanins; i++ ) - printf( "%d ", pCut->pFanins[i] ); - printf( " } " ); -} - -/**Function************************************************************* - - Synopsis [Allocates cut of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CutDeref( Cnf_Man_t * p, Cnf_Cut_t * pCut ) -{ - Aig_Obj_t * pObj; - int i; - Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i ) - { - assert( pObj->nRefs > 0 ); - pObj->nRefs--; - } -} - -/**Function************************************************************* - - Synopsis [Allocates cut of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CutRef( Cnf_Man_t * p, Cnf_Cut_t * pCut ) -{ - Aig_Obj_t * pObj; - int i; - Cnf_CutForEachLeaf( p->pManAig, pCut, pObj, i ) - { - pObj->nRefs++; - } -} - -/**Function************************************************************* - - Synopsis [Allocates cut of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CutUpdateRefs( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, Cnf_Cut_t * pCutRes ) -{ - Cnf_CutDeref( p, pCut ); - Cnf_CutDeref( p, pCutFan ); - Cnf_CutRef( p, pCutRes ); -} - -/**Function************************************************************* - - Synopsis [Merges two arrays of integers.] - - Description [Returns the number of items.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Cnf_CutMergeLeaves( Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int * pFanins ) -{ - int i, k, nFanins = 0; - for ( i = k = 0; i < pCut->nFanins && k < pCutFan->nFanins; ) - { - if ( pCut->pFanins[i] == pCutFan->pFanins[k] ) - pFanins[nFanins++] = pCut->pFanins[i], i++, k++; - else if ( pCut->pFanins[i] < pCutFan->pFanins[k] ) - pFanins[nFanins++] = pCut->pFanins[i], i++; - else - pFanins[nFanins++] = pCutFan->pFanins[k], k++; - } - for ( ; i < pCut->nFanins; i++ ) - pFanins[nFanins++] = pCut->pFanins[i]; - for ( ; k < pCutFan->nFanins; k++ ) - pFanins[nFanins++] = pCutFan->pFanins[k]; - return nFanins; -} - -/**Function************************************************************* - - Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Cnf_TruthPhase( Cnf_Cut_t * pCut, Cnf_Cut_t * pCut1 ) -{ - unsigned uPhase = 0; - int i, k; - for ( i = k = 0; i < pCut->nFanins; i++ ) - { - if ( k == pCut1->nFanins ) - break; - if ( pCut->pFanins[i] < pCut1->pFanins[k] ) - continue; - assert( pCut->pFanins[i] == pCut1->pFanins[k] ); - uPhase |= (1 << i); - k++; - } - return uPhase; -} - -/**Function************************************************************* - - Synopsis [Removes the fanin variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CutRemoveIthVar( Cnf_Cut_t * pCut, int iVar, int iFan ) -{ - int i; - assert( pCut->pFanins[iVar] == iFan ); - pCut->nFanins--; - for ( i = iVar; i < pCut->nFanins; i++ ) - pCut->pFanins[i] = pCut->pFanins[i+1]; -} - -/**Function************************************************************* - - Synopsis [Inserts the fanin variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CutInsertIthVar( Cnf_Cut_t * pCut, int iVar, int iFan ) -{ - int i; - for ( i = pCut->nFanins; i > iVar; i-- ) - pCut->pFanins[i] = pCut->pFanins[i-1]; - pCut->pFanins[iVar] = iFan; - pCut->nFanins++; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [Returns NULL of the cuts cannot be merged.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Cut_t * Cnf_CutCompose( Cnf_Man_t * p, Cnf_Cut_t * pCut, Cnf_Cut_t * pCutFan, int iFan ) -{ - Cnf_Cut_t * pCutRes; - static int pFanins[32]; - unsigned * pTruth, * pTruthFan, * pTruthRes; - unsigned * pTop = p->pTruths[0], * pFan = p->pTruths[2], * pTemp = p->pTruths[3]; - unsigned uPhase, uPhaseFan; - int i, iVar, nFanins, RetValue; - - // make sure the second cut is the fanin of the first - for ( iVar = 0; iVar < pCut->nFanins; iVar++ ) - if ( pCut->pFanins[iVar] == iFan ) - break; - assert( iVar < pCut->nFanins ); - // remove this variable - Cnf_CutRemoveIthVar( pCut, iVar, iFan ); - // merge leaves of the cuts - nFanins = Cnf_CutMergeLeaves( pCut, pCutFan, pFanins ); - if ( nFanins+1 > p->nMergeLimit ) - { - Cnf_CutInsertIthVar( pCut, iVar, iFan ); - return NULL; - } - // create new cut - pCutRes = Cnf_CutAlloc( p, nFanins ); - memcpy( pCutRes->pFanins, pFanins, sizeof(int) * nFanins ); - assert( pCutRes->nFanins <= pCut->nFanins + pCutFan->nFanins ); - - // derive its truth table - // get the truth tables in the composition space - pTruth = Cnf_CutTruth(pCut); - pTruthFan = Cnf_CutTruth(pCutFan); - pTruthRes = Cnf_CutTruth(pCutRes); - for ( i = 0; i < 2*pCutRes->nWords; i++ ) - pTop[i] = pTruth[i % pCut->nWords]; - for ( i = 0; i < pCutRes->nWords; i++ ) - pFan[i] = pTruthFan[i % pCutFan->nWords]; - // move the variable to the end - uPhase = Kit_BitMask( pCutRes->nFanins+1 ) & ~(1 << iVar); - Kit_TruthShrink( pTemp, pTop, pCutRes->nFanins, pCutRes->nFanins+1, uPhase, 1 ); - // compute the phases - uPhase = Cnf_TruthPhase( pCutRes, pCut ) | (1 << pCutRes->nFanins); - uPhaseFan = Cnf_TruthPhase( pCutRes, pCutFan ); - // permute truth-tables to the common support - Kit_TruthStretch( pTemp, pTop, pCut->nFanins+1, pCutRes->nFanins+1, uPhase, 1 ); - Kit_TruthStretch( pTemp, pFan, pCutFan->nFanins, pCutRes->nFanins, uPhaseFan, 1 ); - // perform Boolean operation - Kit_TruthMux( pTruthRes, pTop, pTop+pCutRes->nWords, pFan, pCutRes->nFanins ); - // return the cut to its original condition - Cnf_CutInsertIthVar( pCut, iVar, iFan ); - // consider the simple case - if ( pCutRes->nFanins < 5 ) - { - pCutRes->Cost = p->pSopSizes[0xFFFF & *pTruthRes] + p->pSopSizes[0xFFFF & ~*pTruthRes]; - return pCutRes; - } - - // derive ISOP for positive phase - RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 ); - pCutRes->vIsop[1] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory ); - // derive ISOP for negative phase - Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins ); - RetValue = Kit_TruthIsop( pTruthRes, pCutRes->nFanins, p->vMemory, 0 ); - pCutRes->vIsop[0] = (RetValue == -1)? NULL : Vec_IntDup( p->vMemory ); - Kit_TruthNot( pTruthRes, pTruthRes, pCutRes->nFanins ); - - // compute the cut cost - if ( pCutRes->vIsop[0] == NULL || pCutRes->vIsop[1] == NULL ) - pCutRes->Cost = 127; - else if ( Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]) > 127 ) - pCutRes->Cost = 127; - else - pCutRes->Cost = Vec_IntSize(pCutRes->vIsop[0]) + Vec_IntSize(pCutRes->vIsop[1]); - return pCutRes; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/cnf/cnfData.c b/src/aig/cnf/cnfData.c deleted file mode 100644 index 7b8be51e..00000000 --- a/src/aig/cnf/cnfData.c +++ /dev/null @@ -1,4784 +0,0 @@ -/**CFile**************************************************************** - - FileName [cnfData.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG-to-CNF conversion.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: cnfData.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cnf.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static char s_Data3[81] = "!#&()*+,-.0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz|"; - -static char * s_Data4[] = { -"! B a . 8 .B 8a K !K T Ta j 8j Tj s ( + (B +a (. +8 .B( +8a (K +K T( +T j( ", -"+j Tj( s+ E !E H Ha E. 8E H. H8 EK EK! HT HTa jE 8jE Hj sH d +d Hd g d. 8d ", -"Hd. g8 dK +dK Td gT dj +jd Hjd gs 2 !2 2B a2 5 58 5B 5a 2K 2K! T2 Ta2 5j 58", -"j 5T s5 ; +; ;B a; 5; > 5;B >a ;K +;K T; +T; ;j >j 5T; s> E2 !E2 H2 Ha2 5E ", -"58E H5 H58 EK2 !E2K HT2 TaH2 5jE 8j5E H5T sH5 d; +d; H; g; 5d >d H5d g> dK;", -" dK+; H;T gT; 5dj >jd H;j gs> N !N NB aN N. 8N .BN 8aN Q Q! QT Qa Qj Q8 QTj", -" sQ (N +N (BN +aN N.( +8N (BN. 8a+N Q( +Q QT( +QT Qj( +Q8 TjQ( s+Q W W! HW ", -"Wa W. W8 HW. H8W WQ Q!W Z Za Wj W8Q Zj sZ Wd +W HWd gW Wd. +W8 WdH. gW8 Qd ", -"+WQ Zd gZ Wjd +Wj Zdj gZs m m! mB am 5m 8m 5mB 5am Qm Q!m Tm Qam p p8 pT sp", -" m; +m m;B +ma 5m; >m m;5B >ma Q; +Qm Q;T +Tm p; p> pT; sp> Wm W!m Hm Hma 5", -"W 5W8 H5W H8m WQm WmQ! Zm Zam pW pW8 Zp sZp v v+ vH gv v5 v> vH5 gv> vQ v+Q", -" Zv gZv pv pv> Zpv y # & #B a& #. 8& .B# 8a& #K &K T# T& j# &j Tj# s& #( +&", -" #B( +a& #(. +8& #(.B 8a+& #(K +&K T#( +T& j#( +j& j#T( s+& #E &E H# H& #E.", -" 8&E H#. H8& EK# &EK HT# H&T j#E &jE Hj# sH& d# d& Hd# g& d#. 8d& d#H. g8& ", -"dK# d&K Td# gT& dj# d&j H#dj gs& #2 &2 2B# a&2 5# 5& 5B# 5a& 2K# &2K T#2 T&", -"2 5j# 5&j 5T# s5& ;# ;& ;#B a;& 5;# >& ;#5B >&a ;#K ;&K T;# T;& ;j# >&j 5#T", -"; s>& #E2 &E2 H#2 H&2 5#E 5&E H5# H5& #E2K EK&2 T#H2 H2T& j#5E 5E&j H#5T H5", -"s& d;# d&; H;# g;& 5d# >&d H#5d g>& ;#dK dK;& H#T; T;g& 5#dj d&>j H#;j >&gs", -" #N &N #BN a&N N.# 8&N #BN. aN8& Q# Q& QT# Qa& Qj# Q8& TjQ# sQ& #(N +&N #(N", -"B a&+N #(N. 8&+N .BN#( +8a&N Q#( +Q& T#Q( Q&+T j#Q( Q&+j QTj#( +Qs& W# W& H", -"W# H&W W#. W8& W#H. W8H& WQ# W&Q Z# Z& Wj# W&j Zj# sZ& Wd# +W& WdH# gW& d#W", -". 8dW& HWd#. W8g& Qd# Qd& Zd# gZ& W#dj W&+j djZ# Z&gs m# m& m#B am& 5m# 5&m", -" m#5B am5& Qm# Q&m Tm# Tm& p# p& pT# sp& m;# +m& ;#mB m&a; m;5# >m& 5m;#B a", -"m>& Q;# Q;& Q#T; T;Q& p;# p>& T;p# p&s> Wm# W&m Hm# Hm& 5W# 5W& H#5W 5WH& Q", -"mW# WQm& Zm# Z&m pW# p&W Zp# Zp& v# v& vH# gv& v5# v>& H5v# v&g> vQ# v&Q Zv", -"# Zv& pv# pv& Z#pv y& C !C D Da C. 8C D. D8 CK CK! DT DTa jC 8jC Dj sD C( +", -"C D( +D C(. +8C D(. +D8 CK( +CK DT( +DT jC( +jC Dj( s+D CE !CE HD HDa CE. 8", -"CE HD. H8D EKC !CEK HDT DTHa jCE jC8E HjD sHD dC +dC Dd gD dC. 8dC Dd. gD8 ", -"dKC dK+C DdT gDT djC +Cdj Ddj gsD C2 !C2 D2 Da2 5C 58C 5D 5D8 2KC !C2K DT2 ", -"T2Da 5jC 8j5C 5DT s5D ;C +;C D; +D; 5;C >C 5D; >D ;CK ;C+K D;T D;+T ;jC >jC", -" D;j s>D CE2 CE!2 HD2 H2Da 5CE 8C5E H5D 5DH8 CE2K !E2CK H2DT HDTa2 jC5E 58j", -"CE 5DHj H5sD d;C d;+C H;D gD; 5dC >Cd 5Dd g>D ;CdK +d;CK TdD; D;gT 5Cdj dj>", -"C Dd5T >Dgs CN !CN DN DaN N.C 8CN DN. D8N QC Q!C QD QDa QjC Q8C QDj sQD C(N", -" +CN D(N +DN C(N. 8C+N N.D( +ND8 QC( +QC QD( +QD jCQ( +CQ8 Q(Dj +QsD WC W!C", -" WD WDa WC. W8C WD. WD8 WQC WCQ! ZD ZDa WjC WCQ8 ZDj sZD WdC +WC WDd gWD dC", -"W. +CW8 W.Dd WDg8 QdC +CQd ZDd gZD WCdj +CWj DdZj gDsZ mC mC! Dm Dma 5mC 8m", -"C 5Dm D8m QmC mCQ! QDm DmQa pC p8C pD spD m;C +mC Dm; +Dm m;5C >mC 5mD; >Dm", -" Q;C +CQ; QD; QD+m p;C p>C pD; p>D WmC mCW! HmD DmWa 5WC 5CW8 5WD WD5a QmWC", -" Q!WmC ZDm DmZa pWC W8pC ZpD pDsZ vC v+C vD gvD v5C v>C vD5 v>D vQC +QvC Zv", -"D vDgZ pvC >Cpv pvD yD b b& bD c b. b8 bD. c8 bK bK& bT cT bj b8j bTj sc b(", -" b+ bD( c+ b(. b+8 D(b. c+8 bK( b+K bT( c+T bj( b+j b(Dj sc+ bE b&E bH cH b", -"E. b8E bH. cH8 bKE &EbK bHT cHT bjE bE&j bHj scH bd b+d bHd gc bd. b8d b.Dd", -" gc8 bdK bKd& bTd gcT bdj +jbd Hjbd gsc b2 b&2 bD2 c2 b5 b58 b5D c5 bK2 &2b", -"K bT2 c2T b5j 5&bj b5T sc5 b; b+; b;D c; b5; >b 5Db; c> b;K bK;& bT; c;T b;", -"j >bj 5Tb; c>s bE2 &Eb2 bH2 c2H b5E bE5& bH5 c5H EKb2 bK&E2 HTb2 HTc2 5jbE ", -"&jEb5 H5bT sHc5 bd; d&b; bH; gc; b5d >bd H5bd c>g dKb; d&;bK H;bT gTc; 5dbj", -" bd>j H;bj gsc> bN b&N bDN cN bN. b8N DNb. c8N bQ bQ& bQD cQ bQj bQ8 QDbj s", -"cQ b(N b+N D(bN c+N N.b( +8bN bD(N. +8cN bQ( b+Q b(QD cQ+ Qjb( +Qb8 bQDj( s", -"+cQ bW bW& bHW cW bW. bW8 b.WD cW8 bWQ W&bQ Zb Zc bWj W8bQ Zbj Zcs bWd b+W ", -"WDbd gcW Wdb. +Wb8 bHWd. g8cW bQd +WbQ Zbd Zcg Wjbd +Wbj bdZj gsZc bm bm& b", -"mD cm b5m b8m 5Dbm c5m bQm Q&bm bTm cQm pb pb8 pbD cp bm; b+m Dmb; cm+ 5mb;", -" >bm b5Dm; c>m bQ; +Qbm QDb; cQ; pb; p>b bTp; cp> bWm W&bm bHm cWm b5W 5Wb8", -" H5bW c5W WQbm bWQm& Zbm Zcm pbW bWp& Zpb cpZ vb vb+ vbH cv vb5 v>b bHv5 cv", -"> vbQ b+vQ Zvb cvZ pvb v>pb pvZb yc 0 !0 0B a0 1 18 1B 1a 0K !K0 T0 Ta0 1j ", -"18j 1T s1 0( +0 0B( +a0 1( 1+ 1(B 1+a 0(K +0K T0( +T0 1j( 1+j 1T( s1+ E0 !E", -"0 H0 Ha0 1E 18E 1H 1H8 EK0 !0EK HT0 TaH0 1jE 8j1E 1HT s1H d0 +d0 Hd0 g0 1d ", -"1+d 1Hd g1 dK0 dK+0 Td0 gT0 1dj +j1d 1Td gs1 02 !02 2B0 a02 15 158 15B 1a5 ", -"2K0 !02K T02 T2a0 15j 581j 1T5 s15 ;0 +;0 ;0B a;0 1; >1 1;B >1a ;0K ;0+K T;", -"0 +0T; 1;j >j1 1T; s>1 E02 E0!2 H02 a0H2 15E 581E 1H5 H51a E02K !E20K T0H2 ", -"HTa02 5j1E 158jE H51T 1Hs5 d;0 d;+0 H;0 g;0 1d5 >1d 1H; g>1 ;0dK +d;0K H0T;", -" T;g0 dj1; 1d>j H;1T s>g1 0N !0N 0BN a0N 1N 18N 1NB 1aN Q0 Q!0 QT0 Qa0 1Q 1", -"Q8 1QT s1Q 0(N +0N 0(NB a0+N 1(N 1+N (B1N +a1N Q0( +Q0 T0Q( +0Qa 1Q( 1+Q QT", -"1( 1+sQ W0 W!0 HW0 Wa0 1W 1W8 1HW 1Wa WQ0 W0Q! Z0 Za0 1WQ W81Q Z1 sZ1 Wd0 +", -"W0 WdH0 gW0 1Wd 1+W HW1d g1W Qd0 +0Qd Zd0 gZ0 1Qd +W1Q Z1d gZ1 m0 m0! m0B a", -"m0 1m 1m8 1mB 1am Qm0 m0Q! Tm0 Q0am p1 p18 p1T sp1 m;0 +m0 ;0mB +0am 1m; >m", -"1 m;1B 1a>m Q;0 +0Q; Q0T; +0Tm p1; p>1 1Tp; s1p> Wm0 m0W! Hm0 H0am 1W5 W81m", -" 1Hm H81m QmW0 Q!Wm0 Zm0 amZ0 p1W 1Wp8 Zp1 Z1sp v0 v+0 vH0 gv0 v1 v>1 v1H g", -"v1 vQ0 +Qv0 Zv0 g0Zv pv1 v1p> Zv1 y1 9 9& 9B 9a 91 : 91B :a 9K 9&K 9T 9Ta 9", -"j :j 9T1 s: 9( 9+ 9(B 9+a 91( :+ 1B9( :+a 9(K 9+K 9T( 9+T 9j( :+j 9(1T s:+ ", -"9E 9&E 9H 9Ha 91E :E 9H1 :H 9EK &E9K 9HT H&9T 9jE :jE 9Hj s:H 9d 9+d 9Hd g9", -" 9d1 :d 1H9d g: 9dK 9Kd& 9Td g9T 9dj :dj 1T9d g:s 92 9&2 92B 9a2 95 :5 95B ", -":5a 92K &29K 9T2 92T& 95j :5j 95T s:5 9; 9+; 9;B 9a; 95; :> 1B9; :>a 9;K 9K", -";& 9T; +T9; 9;j :>j 1T9; s:> 9E2 &E92 9H2 92H& 95E :5E 9H5 :H5 EK92 9&E2K H", -"T92 9HT&2 5j9E 5j:E H59T s5:H 9d; d&9; 9H; g9; 95d :>d 1H9; g:> dK9; d&;9K ", -"H;9T 9Tg; 5d9j >j:d H;9j s:g> 9N 9&N 9NB 9aN 91N :N 1B9N :aN 9Q 9Q& 9QT 9Qa", -" 9Q1 :Q 1Q9T s:Q 9(N 9+N (B9N +a9N 1(9N :+N 91(NB +a:N 9Q( 9+Q QT9( +Q9T 9(", -"1Q :Q+ 9Q1T( s+:Q 9W 9W& 9HW 9Wa 9W1 :W 1H9W :HW 9WQ W&9Q Z9 Z9a 9Wj :WQ Z9", -"1 Z: 9Wd 9+W HW9d g9W 1W9d :W+ 9H1Wd g:W 9Qd +W9Q Z9d gZ9 1Q9d :Qd 9dZ1 Z:g", -" 9m 9m& 9mB 9am 95m :m 1B9m :ma 9Qm Q&9m 9Tm Qa9m p9 :p p9T :ps 9m; 9+m m;9", -"B +m9a 1m9; :>m 95;mB :a>m 9Q; +Q9m Q;9T +T9m p9; :p> 9Tp; s>:p 9Wm W&9m 9H", -"m Hm9a 95W :W5 1H9m :Hm WQ9m 9WQm& Z9m 9aZm p9W :pW Zp9 Z:p v9 v9+ v9H gv9 ", -"v91 :v 9Hv1 :vg v9Q 9+vQ Zv9 Zvg9 pv9 :vp pvZ9 y: C0 !C0 D0 Da0 1C 18C 1D 1", -"D8 CK0 !0CK DT0 TaD0 1jC 8j1C 1DT s1D C0( +C0 D0( +D0 1C( 1+C 1D( 1+D 0(CK ", -"CK+0 T0D( DT+0 jC1( 1C+j 1(Dj 1+sD CE0 CE!0 HD0 DaH0 1CE 8C1E 1HD H81D C0EK", -" !E0CK DTH0 HDTa0 jC1E 18jCE Hj1D 1HsD dC0 dC+0 Dd0 gD0 1dC 1C8d 1Dd g1D CK", -"d0 +dC0K D0Td DTg0 1Cdj djC1+ Dd1T s1gD C02 C0!2 D02 D2a0 15C 581C 1D5 5D1a", -" C02K C02!K T2D0 DTa02 5j1C 158jC 5D1T 1Ds5 ;C0 ;C+0 D;0 +0D; 1;C >C1 1D; >", -"D1 CK;0 +;C0K D0T; a;0DT 1C;j 1j>C D;1T s1>D E0C2 C02!E D0H2 HDa02 5C1E 158", -"CE H51D 1H5D8 C02EK EK0!C2 HDT02 DTaH02 15jCE 58j1CE 1H5Dj s1H5D ;Cd0 +d;C0", -" H0D; D;g0 1C5d 1d>C H;1D >Dg1 dK;C0 dK;+C0 H;DT0 gDT;0 djC1; >j1dC 1H;Dj g", -"s>1D C0N C0!N D0N a0DN 1CN 8C1N 1DN 1ND8 QC0 !CQ0 QD0 DaQ0 1QC 1CQ8 1QD 1Qs", -"D 0(CN C0+N 0(DN D0+N C(1N +C1N D(1N 1N+D C0Q( QC+0 D0Q( +0QD QC1( 1C+Q 1(Q", -"D +Q1D WC0 !CW0 WD0 DaW0 1WC 1CW8 1WD WD1a QCW0 Q!WC0 ZD0 DaZ0 1CWj 1WQ8C Z", -"1D sDZ1 dCW0 WC+0 W0Dd WDg0 Wd1C 1C+W WD1d 1WgD dCQ0 +WQC0 DdZ0 ZDg0 1CQd 1", -"+WQC 1DZd gDZ1 mC0 !Cm0 Dm0 D0am 1mC 1C8m 1Dm D81m mCQ0 Q!mC0 Q0Dm am0QD p1", -"C 18pC pD1 s1pD ;Cm0 mC+0 m;D0 +0Dm m;1C 1m>C Dm1; 1D>m ;CQ0 +QmC0 Q0D; +QD", -"m0 1;pC p1>C 1Dp; p1>D mCW0 W!mC0 H0Dm am0WD 1C5W 1W58C Hm1D 1HmD8 WQmC0 Wm", -"CQ!0 DmZ0 ZDam0 1WpC p1W8C pDZ1 Zp1sD vC0 +Cv0 vD0 g0vD v1C >Cv1 v1D vDg1 Q", -"Cv0 v+QC0 Z0vD ZvDg0 pCv1 pv>1C v1pD y1D b9 b9& 9D c9 b1 :b b1D :c b9K 9&bK", -" bT9 c9T b1j :bj b1T s:c b9( b+9 9D( c9+ b1( :b+ b(1D :c+ 9(bK bK9+ b(9T 9+", -"cT b(9j b+:j b(1T s+:c b9E 9&bE bH9 c9H b1E :bE b1H :cH 9EbK b9&EK 9HbT 9Hc", -"T bE9j bj:E 9Hbj :Hsc bd9 9+bd 9Dd gc9 b1d :db 1Hbd g:c bK9d d&Kb9 9Tbd c9g", -"T 9dbj bd:j 1Tbd s:gc b92 9&b2 9D2 c29 b15 :b5 95D :c5 92bK b9&2K b29T 9Tc2", -" 95bj b5:j 95bT c5s: b;9 9+b; 9D; c;9 b1; :>b 1Db; c>: bK9; ;&Kb9 9Tb; 9Tc;", -" 9;bj :b>j 1Tb; s:c> 9Eb2 b9&E2 b29H 9Hc2 bE95 b5:E 9Hb5 c5:H b9E2K 9&EbK2 ", -"bH9T2 c29HT b15jE :b5jE b1H5T :cHs5 9db; d&;b9 9Hb; c;g9 95bd >b:d 1Hb; c>g", -": bd9;K bd9;&K bH;9T c;9gT b1d;j :>bdj b1HT; g:sc> b9N 9&bN 9DN c9N b1N :bN", -" bN1D :cN bQ9 b9Q& 9QD cQ9 b1Q :Qb 1QbT :cQ 9(bN bN9+ D(9N 9+cN 1(bN b+:N b", -"1D(N cN:+ b(9Q 9+bQ 9(QD 9+cQ b(1Q b+:Q b1QD( :+cQ bW9 b9W& 9WD cW9 b1W :Wb", -" 1HbW :cW 9WbQ bW9Q& Zb9 Zc9 9Wbj bW:Q Zb1 Z:c 9Wbd 9+bW WD9d cWg9 1Wbd b+:", -"W b1HWd :Wgc 9Qbd b+W9Q bdZ9 g9Zc 1Qbd bQ:d b1Zd Zcg: bm9 b9m& 9Dm cm9 b1m ", -":mb 1Dbm :cm 9Qbm bQ9m& 9Tbm 9Qcm pb9 :pb p9D cp: 9mb; 9+bm Dm9; 9+cm 1mb; ", -">b:m b1mD; :mc> 9Qb; b+Q9m QD9; 9Qc; b1p; pb:> 9Dp; c>:p 9Wbm bW9m& 9Hbm 9H", -"cm 95bW b5:W 1Hbm c5:W bW9Qm 9WQbm& bmZ9 cmZ9 b1pW pb:W pbZ9 cpZ: vb9 b+v9 ", -"v9D cv9 vb1 :vb b1vD :vc bQv9 vb9+Q vbZ9 Z9cv vbp9 pb:v vbZ1 y:c L !L LB aL", -" L. 8L .BL 8aL M M! TM aM Mj 8M TMj sM (L +L (BL +aL (L. +8L (L.B 8a+L M( +", -"M TM( +TM Mj( +M8 MjT( s+M EL !EL HL HaL EL. 8EL HL. H8L ME ME! HM HMa MjE ", -"8ME HMj sHM dL +dL HdL gL dL. 8dL dLH. g8L dM +Md HMd gM dMj 8dM dMHj gsM L", -"2 !L2 2BL aL2 5L 58L 5BL 5aL M2 M2! TM2 aM2 5M 5M8 5TM s5M ;L +;L ;LB a;L 5", -";L >L ;L5B >La M; +M; T;M aM; 5M; >M T;5M >Ms EL2 EL!2 HL2 aLH2 5EL 8E5L H5", -"L HL5a ME2 !EM2 HM2 H2aM 5ME 5E8M H5M H5sM d;L d;+L H;L g;L 5dL >Ld HL5d g>", -"L dM; +dM; HM; gM; 5dM >Md 5dHM >Mg LN !LN NBL aLN N.L 8LN LBN. aN8L QM Q!M", -" QTM QaM QMj Q8M TMQj sQM (LN +LN (LNB aL+N (LN. 8L+N (BLN. +8aLN QM( +QM T", -"MQ( Qa+M MjQ( Q8+M QTMj( +QsM WL W!L HWL WaL WL. W8L WLH. HLW8 WM WM! ZM Za", -"M WMj W8M ZMj sZM WdL +WL WdHL gWL dLW. +LW8 HWdL. W8gL WMd +WM ZdM gZM dMW", -"j W8+M dMZj sZgM mL mL! mLB amL 5mL 8mL mL5B 5Lam Mm Mm! TmM aMm pM p8M pTM", -" spM m;L +mL ;LmB +Lam m;5L >mL 5m;LB am>L Q;M +Mm MmT; Tm+M pM; >Mp T;pM s", -"p>M WmL mLW! HmL HLam 5WL 5LW8 HL5W HL8m WMm W!Mm ZMm aMZm pWM W8pM ZpM sMZ", -"p vL v+L vHL gvL v5L v>L H5vL >Lgv vM vM+ ZvM gvM pvM >Mv vMZp yM #L &L #BL", -" a&L #L. 8&L #L.B a&8L M# M& TM# T&M Mj# 8M& MjT# sM& #(L +&L #(LB a&+L (L#", -". 8&+L #L.(B +8a&L M#( +M& M#T( T&+M j#M( M&+j TMj#( +Ms& #EL &EL H#L H&L E", -"L#. &E8L #LH. 8&HL M#E M&E HM# HM& j#ME 8EM& MjH# HMs& d#L d&L d#HL g&L #Ld", -". 8Ld& Hd#L. 8&gL dM# dM& H#dM gM& Mjd# d&8M dMjH# sMg& #L2 &L2 #L2B &2aL 5", -"#L 5&L #B5L a&5L M#2 M&2 M#T2 T2M& 5M# 5M& TM5# 5Ms& ;#L ;&L #B;L aL;& ;#5L", -" >&L 5;#LB a&>L M;# M;& T#M; M;T& 5#M; >M& M;#5T sM>& EL#2 EL&2 #LH2 &LH2 #", -"E5L &E5L 5#HL HL5& #EM2 &EM2 M#H2 H2M& M#5E 5EM& H#5M 5MH& ;#dL dL;& ;#HL ;", -"&gL d#5L d&>L H5d#L g&>L d#M; M;d& H#M; M;g& 5#dM dM>& H5Md# >&gM #LN &LN #", -"LNB &LaN #LN. &L8N #LN.B 8a&LN QM# Q&M TMQ# aMQ& MjQ# 8MQ& QTMj# Q&sM (L#N ", -"&L+N #LN(B +a&LN #LN(. +8&LN N.#(BL 8a&+LN M#Q( Q&+M QTM#( +QTM& QMj#( +Q8M", -"& TMjQ#( s+QM& W#L W&L W#HL HLW& #LW. 8&WL HW#L. H8W&L WM# WM& ZM# Z&M MjW#", -" 8MW& MjZ# sMZ& d#WL +LW& HWd#L W&gL Wd#L. d&LW8 Wd#HL. gW8&L W#dM W&+M dMZ", -"# Z&gM dMjW# dM&W8 ZdMj# Z&Mgs m#L m&L #BmL aLm& m#5L 5Lm& 5m#LB am&5L Mm# ", -"Mm& T#Mm MmT& pM# p&M TMp# sMp& ;#mL +Lm& m;#LB am&+L 5m;#L m&>L m;#5BL >ma", -"&L Q#M; M;Q& Mm#T; aMm;& M;p# p&>M pTM;# >Mps& m#WL WLm& m#HL HLm& W#5L 5LW", -"& H5W#L H5&WL W#Mm MmW& MmZ# MmZ& WMp# WMp& pMZ# ZMp& v#L v&L H#vL gLv& 5#v", -"L >Lv& vH5#L gv>&L vM# vM& Z#vM vMZ& p#vM vMp& ZpvM# y&M U U! UD Ua U. U8 U", -"D. U8D UM U!M V Va Uj U8M Vj Vs U( U+ UD( U+D U(. U+8 D(U. +DU8 UM( U+M V( ", -"V+ Uj( U+j Vj( Vs+ UE U!E UH UHa UE. U8E UH. UH8 UME MEU! VH VHa UjE UE8M V", -"Hj VsH Ud U+d UHd gU Ud. U8d U.Dd gU8 UdM +MUd Vd gV Udj +jUd Vdj gVs U2 U!", -"2 UD2 Ua2 U5 U58 U5D U5a UM2 M2U! V2 V2a U5M 5MU8 V5 Vs5 U; U+; U;D Ua; U5;", -" >U 5DU; >UD U;M +MU; V; V+; U;j >MU V5; V> UE2 !EU2 UH2 HaU2 U5E 58UE UH5 ", -"H5U8 MEU2 U!ME2 V2H HaV2 UE5M U58ME V5H sHV5 Ud; +dU; UH; gU; U5d >Ud H5Ud ", -"g>U dMU; dM;U+ Vd; gV; 5dUj Ud>M V5d V>g UN U!N UDN UaN UN. U8N DNU. UND8 U", -"Q UQ! VQ VQa UQj UQ8 VQj VsQ U(N U+N D(UN UN+D N.U( +8UN UD(N. U+D8N UQ( U+", -"Q VQ( V+Q QjU( +QU8 QjV( sQV+ UW UW! UHW UWa UW. UW8 U.WD H8UW UWQ Q!UW VZ ", -"VZa UWj W8UQ VZj sZV UWd U+W WDUd gUW WdU. +WU8 UHWd. UWg8 UQd +WUQ VZd gVZ", -" WjUd +WUj ZjVd sZgV Um Um! UmD Uam U5m U8m 5DUm 5aUm UQm Q!Um Vm Vma pU pU", -"8 Vp Vps Um; U+m DmU; +DUm 5mU; >Um U5Dm; Ua>m UQ; +QUm Vm; V+m pU; p>U Vp;", -" V>p UWm W!Um UHm HmUa U5W 5WU8 H5UW H8Um WMUm Mm!UW VZm ZaVm pUW UWp8 VpZ ", -"sZVp vU vU+ vUH gvU vU5 v>U UHv5 v>gU vUQ U+vM Vv Vvg pvU v>pU Vvp yV bU U&", -" bUD cU bU. b8U UDb. cU8 bM bM& Vb Vc bMj b8M Vbj scV bU( b+U UDb( cU+ U(b.", -" U+b8 bUD(. U+c8 bM( b+M Vb( Vc+ b(Uj U+bj bjV( V+sc bUE U&E bHU cUH UEb. b", -"EU8 b.UH UHc8 bME bEM& VbH VcH bEUj bE8M bHVj sHVc bdU Ud& UHbd gcU b.Ud U8", -"bd bHUd. cUg8 bdM +Mbd Vdb gVc Udbj 8dbM bdVj scgV bU2 U&2 UDb2 c2U b5U U5&", -" bU5D c5U bM2 b2M& V2b Vc2 b5M 5Mb8 V5b c5V b;U U;& bUD; c;U U5b; >bU b5UD;", -" c>U bM; +Mb; V;b c;V U;bj >Mb b5V; V>c UEb2 &EU2 b2UH UHc2 bEU5 UE5& UHb5 ", -"UHc5 MEb2 M&Eb2 bHV2 cHV2 bE5M b5M8E bHV5 cHV5 Udb; d&U; UHb; c;gU U5bd bd>", -"U bH5Ud gUc> dMb; dM&b; bHV; c;gV 5dbM bd>M b5Vd c>gV bUN U&N UDbN cUN UNb.", -" bNU8 bUDN. U8cN bQU UQ& VbQ cQV UQbj UQb8 bQVj VscQ U(bN bNU+ bUD(N U+cN b", -"U(N. b+U8N UD(bN. cU+8N b(UQ U+bQ bQV( V+cQ bQUj( b+QU8 VbQj( cQVs+ bWU UW&", -" UHbW cWU b.UW UWb8 bHUW. UWc8 bWM WMU& ZbV ZcV UWbj W8bM VbZj VZsc UWbd U+", -"bW bHUWd cWgU bWUd. b+WU8 UHWbd. cWUg8 UQbd +WbM VdZb ZcgV bWMdj d&jUW ZbVd", -"j gVZsc bmU Um& bUDm cmU U5bm U8bm b5UDm U5cm bMm Q&Um Vmb cmV pbU pU& Vpb ", -"cpV Umb; U+bm bmUD; U+cm b5Um; bm>U U5Dbm; >Ucm UQb; +Mbm bQV; V+cm bMp; pb", -">M V;pb V>cp UWbm W&Um UHbm UHcm U5bW 5WU& bH5UW U5cW WMbm Mm&bW VmZb VZcm ", -"bWpU UWp& ZbVp VpZc vbU vU& bHvU cvU b5vU >bvU vbUH5 vUc> vbM b+vM Vvb cvV ", -"vbpU vb>M pbVv yVc k k! kB ak 1k 8k 1kB 1ak kM kM! Tk Tka l l8 lT ls k( +k ", -"k(B +ka 1k( 1+k k(1B +k1a kM( +kM Tk( +Tk l( l+ lT( ls+ kE kE! Hk Hka 1kE 8", -"kE 1Hk H8k kME M!kE HkT akHM lE l8E lH lsH dk +kd Hkd gk 1dk 8dk Hk1d g1k d", -"kM dk+M Tdk gkT ld l+d lHd gl k2 k2! k2B ak2 5k 5k8 5kB 5ak kM2 M!k2 Tk2 T2", -"ak l5 l58 l5T ls5 k; +k; k;B ak; 1;k >k 1Bk; >ka k;M k;+M Tk; T;+k l; l> l;", -"T l>s kE2 !Ek2 Hk2 H2ak 5kE 5E8k H5k 5aHk MEk2 kME!2 H2Tk ak2HM l5E 58lE lH", -"5 sHl5 dk; +dk; Hk; gk; 5dk >kd Hk1; >kg k;dM dkM+; TkH; Tkg; ld5 l>d lH; g", -"l> kN kN! kNB akN 1kN 8kN kN1B 1Nak Qk Qk! QkT Qak lQ lQ8 lQT lsQ k(N +kN (", -"BkN +Nak k(1N 1N+k 1k(NB akN1+ Qk( +Qk Q(Tk Qa+k lQ( l+Q QTl( s+lQ Wk Wk! H", -"kW Wak 1Wk W8k Hk1W W8Hk WkQ Q!Wk Zk Zka lW lW8 lZ lZs Wkd +Wk HWdk gkW Wk1", -"d +k1W 1HWdk 1Wgk Qdk Wk+Q Zkd gZk lWd l+W lZd glZ km km! kmB akm 1mk 8km 1", -"Bkm ak1m Qkm Q!km Tkm akTm lp lp8 lpT lsp km; +km m;kB ak+m km1; >km km;1B ", -"ak>m Qk; Qk+m TkQ; Tk+m l;p l>p pTl; spl> Wkm W!km Hkm akHm 5Wk W85k Hk1m W", -"a5k kmWM km!WM Zkm akZm lWp pWl8 lZp splZ vk vk+ vkH gvk v1k >kv 1Hvk gv>k ", -"vkQ +Qvk Zvk Zvgk lv lv> lvZ yl 9k k& 9kB 9ak 91k :k 1B9k :ak 9M 9M& 9Tk 9a", -"M l9 l: l9T ls: 9k( 9+k k(9B +k9a 1k9( :+k 91k(B +k:a 9M( 9+M 9(Tk +T9M l9(", -" l:+ 9Tl( s:l+ 9kE k&E 9Hk Hk& 1k9E :kE 91Hk :Hk 9ME 9EM& 9HM HM9a l9E l:E ", -"lH9 l:H 9dk dk& Hk9d g9k 91dk :dk 9H1dk g:k 9dM +M9d HM9d g9M ld9 l:d 9Hld ", -"gl: 9k2 k&2 k29B 92ak 95k :5k 9B5k 5a:k 9M2 92M& 92Tk 92aM l95 l:5 95lT l5s", -": 9;k k;& 9Bk; ak9; 5k9; >k: k;B95 :a>k 9M; +M9; Tk9; aM9; l;9 l>: 9Tl; s:l", -"> kE92 &Ek2 92Hk H2k& 9E5k 5k:E Hk95 H5:k ME92 k&EM2 92HM 9HM&2 95lE :5lE 9", -"Hl5 l5:H dk9; k;d& Hk9; 9;gk 5k9d :d>k 9H5dk >kg: dM9; dk&M; HM9; 9Mg; 95ld", -" :>ld 9Hl; g:l> 9kN k&N kN9B 9Nak 1k9N :kN 91kNB ak:N 9Qk Qk& Qk9T Qa9M l9Q", -" l:Q 9QlT :Qls k(9N 9N+k 9k(NB akN9+ 91k(N +k:N 1k(9NB :+akN 9(Qk +Q9M 9QTk", -"( 9+QTk 9Ql( :Ql+ l9QT( :Q+ls 9Wk Wk& Hk9W Wk9a 91Wk :Wk 9H1Wk Hk:W 9WM W&9", -"M Z9k Zk& lW9 l:W lZ9 Z:l Wk9d +k9W 9HWdk 9Wgk 9W1dk +W:k 1HW9dk :Wgk WM9d ", -"+W9M 9dZk Z9gk 9Wld :Wl+ Z9ld Z:gl 9mk km& 9Bkm ak9m 5k9m :mk kmB95 ak:m 9M", -"m kmQ& Tk9m aM9m p9l :pl lTp9 ls:p km9; +k9m km;9B akm9+ km;95 :m>k 95;kmB ", -":>akm Qk9; +M9m 9Q;Tk ak;9Q p9l; :pl> l;p9T l>ps: Wk9m kmW& Hk9m kmH& 5k9W ", -"5W:k 9H5Wk Hk:m WM9m km&WM 9MZm kmZ& p9lW lW:p p9lZ lZ:p v9k vk& 9Hvk v9gk ", -"95vk :vk v91Hk gk:v v9M 9+vM v9Zk v9gM lv9 lv: Z9lv yl: Uk U!k Dk Uak 1U 1U", -"8 1UD 1Ua UkM kMU! Vk Vak lU lU8 Vl lsV Uk( U+k Dk( +Dk 1U( 1U+ 1(Dk U+1D k", -"MU( Uk+M Vk( V+k lU( l+U Vl( l+V UkE kEU! UHk HkUa 1UE 1EU8 1UH UH1a kMUE U", -"!kME VHk HkVa lUE U8lE lHV VslH Udk +kUd Ddk gUk 1Ud U+1d UH1d g1U UkdM dkM", -"U+ Vdk gVk ldU U+ld ldV glV Uk2 k2U! Dk2 U2ak 1U5 5kU8 5Dk U51a kMU2 U!kM2 ", -"V2k akV2 lU5 U5l8 Vl5 V5ls U;k +kU; Dk; D;+k 1U; >kU U;1D >kD UkM; k;MU+ V;", -"k +kV; l;U l>U l;V V>l kEU2 U!kE2 U2Hk ak2UH 1EU5 1U58E U51H 1UH5a UkME2 kM", -"EU!2 HkV2 V2Hak U5lE lU58E V5lH lsVH5 dkU; dk;U+ HkU; U;gk U51d 1U>d UH1; g", -"U>k dkMU; U+dk;M HkV; V;gk U5ld >Uld V5ld V>gl UkN kNU! DkN UNak 1UN 1NU8 1", -"NDk 1NUa UQk U!Qk VQk QaVk lUQ UQl8 VlQ lQVs k(UN UN+k k(DN +NDk U(1N 1NU+ ", -"1UD(N 1U+DN U(Qk +kUQ QkV( +QVk UQl( U+lQ VQl( lQV+ UWk U!Wk WDk WkUa 1UW U", -"81W UH1W UW1a WkUQ UWQk! ZkV VaZk lWU UWl8 lZV VlsZ WkUd +kUW DdWk UWgk UW1", -"d U+1W 1UHWd 1UgW QkUd U+WQk VdZk ZkgV UWld U+lW VZld lZgV Umk U!km Dkm akU", -"m 1Um U81m Um1D Ua1m QkUm km!UQ Vmk akVm pUl l8pU Vpl lsVp kmU; +kUm kmD; D", -"k+m Um1; 1U>m 1UmD; Dk>m QkU; U+Qkm QkV; +kVm pUl; pUl> l;Vp Vpl> WkUm km!U", -"W HkUm akmUH U51W 1UW8m UH1m 1UH8m UWQkm UWQkm! VmZk ZkVam pUlW lWpU8 lZVp ", -"VplsZ vUk U+vk vDk vUgk v1U vU>k 1UvD v1gU UQvk vU+Qk Vvk gkVv lvU vUl> lvV", -" ylV t t& tD tc t1 t: t1D t:c tM tM& Vt tcV lt lt: ltV u t( t+ tD( tc+ t1( ", -"t:+ 1Dt( :ct+ tM( t+M Vt( t+V lt( lt+ l(Vt u+ tE t&E tH tcH t1E t:E tH1 t:H", -" tME M&tE tHV VctH ltE lEt: ltH uH td t+d tHd gt td1 t:d 1Htd gt: tdM +Mtd ", -"tdV gtV ltd t:ld tHld ug t2 t&2 tD2 tc2 t5 t:5 t5D tc5 tM2 M&t2 Vt2 V2tc lt", -"5 t5l: t5V u5 t; t+; t;D tc; t5; t> 1Dt; t>c t;M +Mt; t;V Vtc; lt; t>l Vlt;", -" u> tE2 &Et2 tH2 c2tH t5E :5tE tH5 :Ht5 MEt2 tM&E2 V2tH tcVH2 lEt5 t:5lE t5", -"lH uH5 td; d&t; tH; gt; t5d t>d 1Ht; gt> dMt; t+dM; Vdt; t;gV t5ld ldt> tHl", -"; ug> tN t&N tDN tcN t1N t:N 1DtN tN:c tQ tQ& tQV tcQ ltQ t:Q VltQ uQ t(N t", -"+N D(tN c+tN 1(tN :+tN t1D(N t:c+N tQ( t+Q VQt( cQt+ l(tQ tQl+ tQVl( u+Q tW", -" tW& tHW tcW tW1 t:W 1HtW :ctW tWQ WMt& tZ tZc ltW t:lW tZl uZ tWd t+W WDtd", -" gtW 1Wtd :Wt+ tH1Wd tWg: tQd +WtQ tZd gtZ tWld t+lW ldtZ uZg tm tm& tmD tc", -"m t5m t:m 1Dtm :ctm tQm Q&tm tmV cQtm tp tp: tpV up tm; t+m Dmt; cmt+ 1mt; ", -"t>m t5Dm; tmc> tQ; +Qtm Vmt; cQt; tp; tp> t;Vp up> tWm W&tm tHm cWtm t5W :W", -"t5 1Htm :Htm WMtm tWQm& tZm tmZc tpW tW:p tZp uZp tv tv+ tvH gtv tv1 tv: v1", -"tH :vgt tvQ vMt+ tZv cvtZ lvt t>lv tZlv yu ) !) )B a) ). 8) .B) 8a) )K !K) ", -"T) Ta) j) 8j) Tj) s) * +* *B a* *. 8* *B. 8*a *K +*K T* +T* *j +j* T*j s* E", -") !E) H) Ha) E). 8E) H). H8) EK) !)EK HT) TaH) jE) jE8) Hj) sH) d* +d* H* g", -"* d*. 8d* H*. g8* dK* dK+* H*T gT* dj* dj8* H*j gs* )2 !)2 2B) a)2 5) 58) 5", -"B) 5a) 2K) !)2K T)2 T2a) 5j) 8j5) 5T) s5) ;* +;* *B; a;* 5* >* 5*B >*a ;*K ", -";*+K T;* a;T* 5*j >*j 5T* s>* E)2 E)!2 H)2 a)H2 5E) 8E5) H5) H)5a E)2K !)2E", -"K T)H2 HTa)2 jE5) 58jE) H)5T H5s) d;* d;+* H;* g;* 5d* >*d H5* g>* ;*dK +d;", -"*K T;H* T;g* dj5* dj>* 5TH* s*g> )N !)N )BN a)N N.) 8)N )BN. aN8) Q) Q!) QT", -") Qa) Qj) Q8) TjQ) sQ) *N +*N *BN a*N *N. 8*N .B*N aN8* Q* +Q* Q*T Qa* Q*j ", -"Q8* QT*j s*Q W) W!) HW) Wa) W). W8) W)H. H)W8 WQ) W)Q! Z) Za) Wj) W)Q8 Zj) ", -"sZ) W* +W* H*W gW* W*. W8* H.W* W8g* W*Q W*+Q Z* gZ* W*j W*+j Z*j sZ* m) m)", -"! m)B am) 5m) 8m) m)5B 5)am Qm) m)Q! Tm) Q)am p) p8) pT) sp) m* +m* m*B am*", -" 5*m >m* 5m*B am>* Q;* Q*+m Tm* T*+m p* p>* p*T sp* Wm) m)W! Hm) H)am 5W) 5", -")W8 H)5W H)8m QmW) Q!Wm) Zm) amZ) pW) W8p) Zp) s)Zp v* v+* vH* gv* v5* v>* ", -"H5v* >*gv vQ* +Qv* Zv* Z*gv pv* v>p* Zp* y* , ,& ,B ,a ,. ,8 ,.B ,8a ,K ,&K", -" ,T ,Ta ,j ,8j ,Tj s, ,* - *B, -a ,*. -8 ,.*B -8a ,*K -K ,T* -T ,j* -j T*,j", -" s- ,E ,&E ,H ,Ha ,E. ,8E ,H. ,H8 ,EK &E,K ,HT H&,T ,jE ,E&j ,Hj s,H ,d -d ", -",Hd g- ,d. -8d ,.H* g-8 ,dK -dK ,Td g-T ,dj -jd H*,j s-g ,2 ,&2 ,2B ,a2 ,5 ", -",58 ,5B ,5a ,2K &2,K ,T2 ,2T& ,5j 5&,j ,5T s,5 ,; -; ,;B -a; ,5; -> *B,5 ->", -"a ,;K -;K ,T; -T; ,;j ->j 5T,; s-> ,E2 &E,2 ,H2 ,2H& ,5E ,E5& ,H5 H5,8 EK,2", -" ,&E2K HT,2 ,HT&2 5j,E &jE,5 H5,T ,Hs5 ,d; -d; ,H; g-; ,5d ->d H5,d g-> dK,", -"; dK-; H;,T g;-T 5d,j -d>j H;,j g>s- ,N ,&N ,NB ,aN ,N. ,8N .B,N 8a,N ,Q ,Q", -"& ,QT ,Qa ,Qj ,Q8 QT,j s,Q ,*N -N ,N*B -aN *N,. -8N *B,N. 8a-N ,Q* -Q Q*,T ", -"-QT Q*,j -Q8 ,QT*j s-Q ,W ,W& ,HW ,Wa ,W. ,W8 HW,. H8,W ,WQ W&,Q Z, Z&, ,Wj", -" W8,Q Z,j sZ, ,Wd -W H*,W g-W ,.W* -W8 ,HWd. g8-W ,Qd -WQ Z*, Z- W*,j -Wj ,", -"dZj Z-s ,m ,m& ,mB ,am ,5m ,8m 5m,B 5a,m ,Qm Q&,m ,Tm Qa,m p, p&, p,T sp, ,", -"m; -m *B,m -ma 5*,m ->m m*B,5 -a>m ,Q; -Qm Q;,T -Tm p*, -p ,Tp* -ps ,Wm W&,", -"m ,Hm Hm,a ,5W 5W,8 H5,W H8,m WQ,m ,WQm& Z,m ,aZm p,W ,Wp& Zp, Zps, v, -v v", -",H -vg v,5 -v> ,Hv5 g>-v v,Q -vQ Zv, Z-v pv, -pv pvZ, y- C) !C) D) Da) C). ", -"8C) D). D8) CK) !)CK DT) TaD) jC) jC8) Dj) sD) *C +*C D* +D* *C. 8*C D*. D8", -"* *CK *C+K D*T D*+T *jC +C*j D*j s*D CE) CE!) HD) DaH) E)C. CE8) D)H. H)D8 ", -"C)EK CE)!K DTH) HDTa) CEj) 8jCE) H)Dj HDs) d*C d*+C H*D gD* *Cd. d*8C H.D* ", -"D8g* *CdK +d*CK TdD* D*gT dC*j dj*+C D*Hj gDs* C)2 C)!2 D)2 D2a) 5C) 8C5) 5", -"D) 5)D8 C)2K !)2CK T2D) DTa)2 jC5) 58jC) 5)Dj 5Ds) ;*C ;*+C D;* a;D* 5*C >*", -"C 5D* >D* *C;K +;*CK T;D* a;*DT 5C*j *j>C D*5T >Ds* E)C2 CE)!2 D)H2 HDa)2 C", -"E5) 58CE) H)5D H5D8) CE)2K EKC!)2 HDT)2 DTaH)2 5jCE) 8jC5E) H5DT) sH5D) ;*d", -"C +d;*C D;H* D;g* d*5C d*>C 5DH* gD>* dK;*C dK;+*C H;DT* gDT;* dj*5C >*djC ", -"H5*Dj >D*gs C)N C)!N D)N a)DN C)N. C)8N N.D) 8)DN QC) !CQ) QD) DaQ) jCQ) 8C", -"Q) Q)Dj QDs) *CN *C+N D*N +ND* N.*C *C8N *ND. DN8* Q*C +CQ* QD* Q*+D QC*j Q", -"C8* DjQ* QDs* WC) !CW) WD) DaW) C)W. 8CW) D)W. W)D8 QCW) Q!WC) ZD) DaZ) jCW", -") W8QC) DjZ) ZDs) W*C +CW* WD* WDg* *CW. WC8* W.D* D8W* WCQ* +WQ*C Z*D gDZ*", -" WC*j +Wj*C D*Zj sDZ* mC) !Cm) Dm) D)am mC5) mC8) 5)Dm D)8m mCQ) Q!mC) Q)Dm", -" am)QD pC) 8Cp) pD) s)pD m*C +Cm* Dm* D*+m 5Cm* m*>C Dm5* Dm>* QCm* m*C+Q D", -"mQ* am*QD p*C >Cp* pD* pDs* mCW) W!mC) H)Dm am)WD WC5) 5W8C) 5)WD H8mD) WQm", -"C) WmCQ!) DmZ) ZDam) WCp) pW8C) Z)pD ZpDs) v*C +*vC vD* g*vD 5*vC v*>C 5Dv*", -" >*vD Q*vC v+Q*C vDZ* ZvDg* v*pC pv>*C pDZ* y*D ,b ,b& ,D c, ,b. ,8b ,D. c8", -", ,bK bK,& ,DT cT, ,jb b8,j ,Dj sc, b* -b ,D* c- b*. -b8 ,.D* c-8 b*K -bK b", -"T* c-T b*j -jb D*,j s-c ,bE b&,E ,Hb cH, bE,. ,Eb8 ,.bH ,Hc8 bK,E ,b&EK bH,", -"T ,HcT ,Ebj &jE,b bH,j cHs, ,db -bd ,Dd gc- ,.bd b8-d ,.Dd g8c- ,Kbd bd-K b", -"T,d -Tgc bd,j bd-j H*bj gcs- ,b2 b&,2 ,D2 c2, ,5b b5,8 ,5D c5, bK,2 ,b&2K ,", -"2bT ,Tc2 b5,j ,5b&j b5,T c5s, ,;b -b; ,D; c-; b5* ->b 5D,; c>- ,Kb; b;-K bT", -",; -Tc; b;,j >b-j 5Tb* c>s- bE,2 ,b&E2 ,2bH ,Hc2 ,Eb5 ,5b8E bH,5 ,Hc5 ,bE2K", -" bK&,E2 ,HbT2 c2H,T ,5bjE ,5b&jE ,H5bT s,Hc5 bd,; bd-; bH,; c;g- b5,d -d>b ", -"H5b* g-c> ,db;K -bd;K ,H;bT c-Tg; ,5dbj ->bdj ,H;bj s-gc> ,bN b&,N ,DN c,N ", -"bN,. ,Nb8 DN,. ,8cN ,Qb ,bQ& ,QD cQ, bQ,j bQ,8 QD,j cQs, b*N -bN ,ND* c-N *", -"Nb. b8-N ,D*N. -8cN bQ* -Qb QDb* c-Q Q*bj bQ-j ,QD*j cQs- ,Wb ,bW& ,WD cW, ", -",.bW bW,8 ,.WD ,Wc8 bW,Q ,WbQ& Zb, Zc, bW,j ,W8bQ ,DZj s,Zc bW* -Wb H*bW c-", -"W b.W* bW-8 ,WDd. c8-W bQ,d bW-Q Zb* Z-c W*bj bW-j b*Zj Zcs- ,mb ,bm& ,Dm c", -"m, b5,m b8,m 5D,m ,5cm bQ,m ,Qbm& bT,m ,Qcm pb, ,8pb pD, cp, bm* -mb Dm,; c", -"-m 5*bm >b-m ,5Dm* ->cm bQ,; bQ-m QD,; -Qcm pb* -pb ,Dp* cp- bW,m ,Wbm& bH,", -"m ,Hcm b5,W ,5Wb8 5W,D ,5cW ,WbQm bWQ,m& ,DZm cmZ, ,Wpb pbW,8 pbZ, Z,cp vb*", -" -vb vD, cv- ,5vb vb-> ,5vD -vc> ,Qvb vb-Q vbZ* cvZ- vbp* pb-v pbZ* yc- 0) ", -"!0) )B0 a0) 1) 18) 1)B 1a) 0)K 0)!K T0) a0T) 1j) 8j1) 1T) s1) *0 +*0 *B0 a*", -"0 1* 1+* 1*B 1a* *0K *0+K T*0 +0T* 1*j +j1* 1T* s*1 E0) E0!) H0) a0H) 1E) 8", -"E1) 1H) 1)H8 0)EK !E)0K T0H) HTa0) jE1) 18jE) 1)Hj 1Hs) d*0 d*+0 H*0 g*0 1d", -"* 8d1* 1H* g1* *0dK +d*0K H0T* T*g0 dj1* dj*1+ H*1T s*g1 0)2 0)!2 0)2B 0)a2", -" 15) 581) 5B1) 1)5a 0)2K 0)2!K 0)T2 Ta0)2 5j1) 158j) 1)5T 15s) ;*0 ;*+0 ;0*", -"B ;*a0 1;* >*1 *B1; 1a>* *0;K +;*0K ;*T0 a;*T0 ;j1* 1*>j 5T1* s1>* 0)E2 0)2", -"!E 0)H2 Ha0)2 5E1) 158E) 1)H5 1H58) 0)2EK EK0!)2 HT0)2 Ta0H)2 15jE) 58j1E) ", -"1H5T) s1H5) ;*d0 +d;*0 ;*H0 ;*g0 5d1* 1d>* H51* >*g1 dK;*0 dK;+*0 H;T*0 gT;", -"*0 dj*1; >*1dj 1H;T* s*1g> 0)N 0)!N 0)NB 0)aN 1)N 8)1N )B1N a)1N Q0) !0Q) T", -"0Q) a0Q) 1Q) 1)Q8 QT1) 1Qs) *0N *0+N 0B*N *0aN 1*N 1N8* 1N*B 1Na* Q*0 +0Q* ", -"Q0T* Q0a* 1Q* +Q1* Q*1T 1Qs* W0) !0W) W0H) a0W) 1W) 1)W8 HW1) 1)Wa Q0W) Q!W", -"0) Z0) a0Z) 1)Wj 1WQ8) Z1) s)Z1 W*0 +0W* H0W* W*g0 1W* +W1* H*1W 1Wg* W0Q* ", -"+WQ*0 Z*0 g0Z* W*1Q 1+WQ* Z1* Z1s* m0) !0m) )Bm0 m0a) 1m) 1)8m m)1B 1)am m0", -"Q) Q!m0) m0T) am0Q) p1) 18p) 1Tp) p1s) m*0 +0m* m0*B a0m* 1m* 1m>* *B1m am1", -"* Q0m* m*0+Q T0m* am*Q0 p*1 p1>* 1Tp* s1p* m0W) W!m0) m0H) am0H) 1)5W 1W58)", -" 1)Hm 1Hm8) WQm0) Wm0Q!) m0Z) Zam0) 1Wp) p1W8) p1Z) Zp1s) v*0 +*v0 H*v0 v*g", -"0 v1* >*v1 1Hv* g*v1 Q*v0 v+Q*0 v*Z0 Zv*g0 v1p* pv>1* p*Z1 y*1 ,9 ,9& ,9B ,", -"a9 ,1 :, ,1B :a, ,9K 9&,K ,T9 9T,a ,1j :j, ,1T s:, 9* -9 9*B -9a ,1* :- *B,", -"1 :-a 9*K -9K 9T* -T9 9*j :-j 1T9* s-: ,9E 9&,E ,H9 9H,a ,1E :,E ,1H :H, 9E", -",K ,9&EK 9H,T ,H9T& ,E9j ,j:E 9H,j :Hs, ,d9 -9d 9H* g-9 ,1d :-d 1H,d g:- ,K", -"9d 9d-K 9T,d -Tg9 9d,j -j:d 1T,d s-g: ,92 9&,2 92,B ,29a ,15 :5, ,B95 ,5:a ", -"92,K ,9&2K ,29T ,T9&2 95,j ,5:j 95,T :5s, ,;9 -9; *B9; 9a-; ,1; :-> *B95 :a", -"-> ,K9; 9;-K 9T,; 9T-; 9;,j -j:> 1T,; :-s> 9E,2 ,9&E2 ,29H ,H9&2 ,E95 ,5:E ", -"9H,5 ,H:5 ,9E2K 9&E,2K ,H9T2 9HT,a2 ,15jE :5j,E ,1H5T s,H:5 9d,; 9d-; 9H,; ", -"-9g; 95,d ->:d 1H,; :-g> ,d9;K -9d;K ,H;9T -T9g; ,1d;j :->dj ,1HT; g:s-> ,9", -"N 9&,N 9N,B ,N9a ,1N :,N 1N,B ,a:N ,Q9 ,9Q& 9Q,T 9Q,a ,1Q :Q, 1Q,T :Qs, 9*N", -" -9N 9N*B 9a-N ,N1* :-N ,1*NB -a:N 9Q* -Q9 Q*9T 9Q-T 1Q9* :-Q ,1QT* :Qs- ,W", -"9 ,9W& 9H,W 9W,a ,1W :W, 1H,W ,H:W 9W,Q ,W9Q& Z9, ,aZ9 9W,j ,W:Q Z1, Z:, 9W", -"* -W9 H*9W -Wg9 1W,d :-W ,1HW* :Wg- 9Q,d 9W-Q Z9* Z-9 1Q,d -W:Q ,1Z* Z:- ,m", -"9 ,9m& ,B9m 9a,m ,1m :m, ,B1m ,a:m 9Q,m ,Q9m& 9T,m ,Qa9m p9, :p, ,1pT s,:p ", -"9m* -m9 *B9m 9a-m 1m,; :-m ,1m*B :a-m 9Q,; 9Q-m Tm9* 9T-m p9* -p: 9Tp* :ps-", -" 9W,m ,W9m& 9H,m ,Hm9a 95,W ,5:W 1H,m ,H:m ,W9Qm 9WQ,m& ,mZ9 Z9a,m ,1pW p,:", -"W p9Z, Z,:p v9* -v9 ,Hv9 g9-v v1, :v- ,1vH -vg: ,Qv9 v9-Q v9Z* Z9-v v9p* -p", -":v p9Z* y:- C0) C0!) D0) a0D) 1C) 8C1) 1D) 1)D8 0)CK C0)!K T0D) DTa0) jC1) ", -"18jC) 1)Dj 1Ds) *C0 *C+0 D*0 +0D* 1*C 1C8* 1D* +D1* CK*0 +*C0K D0T* a*0DT 1", -"C*j *jC1+ D*1T 1Ds* E0C) C0)!E D0H) HDa0) CE1) 18CE) HD1) 1HD8) C0)EK EK)!C", -"0 HDT0) DTaH0) 1jCE) 8jC1E) 1HDT) s1HD) *Cd0 +d*C0 H0D* D*g0 d*1C 1+d*C H*1", -"D 1Dg* dK*C0 dK*+C0 H*DT0 gDT*0 dj*1C 1+d*jC 1H*Dj s*1gD 0)C2 C02!) 0)D2 Da", -"0)2 5C1) 158C) 1)5D 1D58) C02)K 2K!C0) DT0)2 Ta0D)2 15jC) 58j1C) 1D5T) s15D", -") *C;0 +;*C0 ;*D0 a;*D0 1C5* 1*>C 5D1* 1D>* ;*C0K ;*C+0K D;T*0 D;Ta*0 ;jC1*", -" >*1jC 1D;T* >D*s1 C02E) !E)C02 HD0)2 Da0H)2 15CE) 58C1E) 1H5D) H5D1a) EKC0", -")2 0)C2EK! DT0H)2 0)T2HDa 5jC1E) 5C1)8jE H5D1T) 1H5sD) d;*C0 d;*+C0 H;D*0 g", -"D;*0 1d5*C >*1dC 1H;D* >D*g1 ;*CdK0 dK+*;C0 D;TH*0 D;Tg*0 1d5*jC dj*>C1 H;j", -"1D* gs1>D* 0)CN C0N!) 0)DN Da0)N C)1N 18C)N D)1N 1D8)N C0Q) Q!C0) D0Q) QDa0", -") QC1) 1Q8C) 1)QD s1QD) C0*N +*C0N *0DN a*0DN *C1N 1+*CN 1ND* 1+D*N *CQ0 +Q", -"*C0 Q0D* +QD*0 1CQ* 1+Q*C QD1* s*1QD C0W) W!C0) D0W) WDa0) WC1) 1W8C) 1)WD ", -"1WD8) WQC0) WC0Q!) D0Z) ZDa0) 1WQC) W8C1Q) 1DZ) Z1Ds) *CW0 +W*C0 W0D* gWD*0", -" 1CW* 1+W*C WD1* g1DW* W*QC0 W*C+Q0 D*Z0 Z*Dg0 1W*QC *jC1+W 1DZ* Z1*gD C0m)", -" mC0!) m0D) am0D) mC1) 1m8C) 1)Dm 1Dm8) QmC0) mC0Q!) QDm0) QD0am) 1Cp) p18C", -") 1Dp) pD1s) *Cm0 m*C+0 D0m* am*D0 1Cm* >m1*C Dm1* >Dm1* m*CQ0 +QCm*0 QD;*0", -" am0QD* 1*pC p>1*C 1Dp* p>D1* WmC0) mC0W!) HmD0) WD0am) 1W5C) W8C1m) 1HmD) ", -"am)1WD QmCW0) QCW0m)! ZDm0) am0ZD) p1WC) 1W8pC) Zp1D) sZ1pD) *Cv0 v+*C0 D*v", -"0 gvD*0 1*vC v>1*C 1Dv* gv1D* vQ*C0 +Q*vC0 ZvD*0 gvDZ*0 pv1*C v>1p*C Zp*1D ", -"1Dy* ,b9 b9,& ,D9 c9, ,1b :b, ,1D :c, b9,K ,b9&K 9D,T ,Tc9 b1,j ,j:b b1,T :", -"cs, b*9 -b9 9D* c-9 b1* :-b 1Db* :c- bK9* b9-K 9Tb* c9-T 9*bj :b-j 1Tb* :cs", -"- b9,E ,b9&E 9H,D ,Hc9 ,Eb1 ,b:E b1,H cH:, ,b9EK b9&,EK ,H9bT c9H,T ,1bjE :", -"bj,E ,1HbT s,H:c 9db* bd-9 9Hb* c-g9 b1,d -b:d 1Hb* :cg- ,db9K -b9dK ,Dd9T ", -"c-9gT ,1dbj :-bdj ,1DTd g:sc- b9,2 ,b9&2 ,29D ,9c2 b1,5 ,5:b 95,D :,c5 ,b92", -"K b9&,2K ,D9T2 c29,T ,1b5j :b5,j ,1D5T s,5:c 9;b* b;-9 9D,; -9c; b1,; >b:- ", -"1D,; :-c> ,;b9K -b9;K ,D;9T c-9T; ,1;bj :->bj ,1DT; s-:c> ,b9E2 b9&,E2 ,H9b", -"2 c29,H ,1b5E :b5,E ,1Hb5 :cH,5 b9E,2K b9,&EK2 bH9,T2 ,H9c2T b15,jE ,5b:jE ", -"b1H,5T :cHs,5 ,db9; -b9d; ,H;9D c-9g; ,1db5 :->bd ,1Hb; g:c-> bd9,;K bd9-;K", -" 9H;bT* -T9gc; b1d,;j ->b:dj b1H,T; s-cg:> b9,N ,b9&N ,N9D ,9cN ,Nb1 ,b:N ,", -"N1D cN:, ,b9Q ,Qb9& 9Q,D ,Qc9 b1,Q ,Q:b 1Q,D :,cQ bN9* b9-N 9ND* -9cN bN1* ", -"-b:N ,1D*N cN:- 9Qb* bQ-9 QD9* c9-Q 1Qb* :b-Q ,1QD* c-:Q ,b9W ,Wb9& 9W,D ,W", -"c9 b1,W ,W:b 1W,D :,cW ,Wb9Q bW9,Q& ,DZ9 c9Z, ,1WbQ :Wb,Q ,1Zb :cZ, 9Wb* bW", -"-9 WD9* c9-W 1Wb* :b-W ,1WDd c-:W ,Qdb9 -Wb9Q b*Z9 c-Z9 ,1Qbd :-WbQ b1Z* :c", -"Z- ,b9m ,mb9& 9D,m ,mc9 b1,m ,m:b 1D,m :,cm ,Qb9m bQ9,m& ,QD9m cQ9,m ,1pb :", -"bp, ,1pD p,:c 9mb* bm-9 Dm9* c9-m 1mb* :b-m ,1Dm* c-:m ,Q;b9 -Qb9m ,QD9; c-", -"Q9m b1p* pb:- 9Dp* :c-p ,Wb9m bW9,m& ,Hm9D cW9,m ,1Wb5 :Wb,5 ,1Hbm :cW,5 bW", -"9,Qm WQ9m,b& Zb9,m Zc9,m pb9,W :pb,W Zpb,1 cpZ:, b*v9 -bv9 ,Dv9 v9c- ,1vb v", -"b:- ,1vD :c-v vb9,Q -vb9Q Zvb9* cvZ-9 pvb,1 :v-pb Zpb9* :cy- )L !)L )BL a)L", -" )L. 8)L )L.B a)8L M) M)! TM) aM) Mj) 8M) MjT) sM) *L +*L *BL a*L *L. 8*L .", -"B*L 8La* M* +M* T*M aM* M*j 8M* TM*j s*M E)L E)!L H)L a)HL )LE. E)8L )LH. 8", -")HL ME) !EM) HM) H)aM jEM) ME8) MjH) HMs) d*L d*+L H*L g*L *Ld. d*8L *LH. 8", -"*gL dM* +dM* HM* gM* M*dj dM8* M*Hj s*gM )L2 )L!2 )L2B )La2 5)L 8)5L )B5L a", -")5L M)2 !)M2 M)T2 M2a) 5M) 5)8M TM5) 5Ms) ;*L ;*+L ;L*B ;*aL 5*L >*L 5L*B a", -"*>L M;* +;M* M;T* M;a* 5M* >M* T*5M s*>M )LE2 !)2EL )LH2 Ha)L2 E)5L 58E)L 5", -")HL H58)L E)M2 ME)!2 M)H2 aM)H2 ME5) 5M8E) H)5M sH5M) ;*dL +d;*L ;*HL ;*gL ", -"d*5L d*>L HL5* g*>L d;M* dM;+* M;H* M;g* dM5* dM>* 5MH* >*gM )LN )L!N )LNB ", -")LaN )LN. )L8N .BL)N 8a)LN QM) M)Q! TMQ) Q)aM MjQ) Q)8M QTMj) QMs) *LN *L+N", -" NB*L *LaN N.*L *L8N *BLN. a*L8N Q*M Q*+M QTM* aMQ* QM*j 8MQ* M*jQT Q*sM W)", -"L !)WL W)HL a)WL )LW. 8)WL HW)L. H8W)L WM) M)W! ZM) aMZ) MjW) W)8M MjZ) ZMs", -") W*L +LW* HLW* W*gL *LW. WL8* H*WL. gW8*L WM* W*+M Z*M Z*gM M*Wj 8MW* M*Zj", -" sMZ* m)L !)mL )BmL m)aL m)5L m)8L 5m)LB am)5L Mm) M!m) T)Mm a)Mm pM) 8Mp) ", -"TMp) pMs) m*L +Lm* mL*B aLm* 5Lm* m*>L m*L5B >ma*L Mm* M*+m MmT* Mma* p*M p", -"*>M T*pM sMp* m)WL W!m)L m)HL am)HL W)5L 5W8)L H5W)L H8m)L W)Mm Mm)W! MmZ) ", -"aMmZ) WMp) pW8M) pMZ) ZpMs) v*L +*vL H*vL v*gL 5*vL v*>L vH5*L gv>*L vM* +M", -"v* vMZ* g*vM vMp* >*vM ZMp* y*M ,L ,&L ,LB ,aL ,L. ,8L .B,L 8a,L ,M ,M& ,TM", -" ,aM ,Mj ,8M TM,j s,M ,*L -L ,L*B -aL *L,. -8L *B,L. 8a-L ,M* -M T*,M -TM M", -"*,j -M8 M*j,T s-M ,EL &E,L ,HL ,LH& EL,. 8E,L HL,. ,LH8 ,ME ,EM& ,HM HM,a M", -"j,E ,E8M HM,j ,HsM ,dL -dL ,LH* g-L dL,. 8d-L ,HdL. -8gL ,dM -Md HM,d g-M d", -"M,j 8d-M ,HMdj gMs- ,L2 &L,2 2B,L aL,2 ,5L ,L5& 5B,L ,L5a ,M2 ,2M& TM,2 ,2a", -"M ,5M 5M,8 5T,M ,5sM ,;L -;L ;L,B a;-L ,L5* ->L ,5;LB -a>L ,M; -M; T;,M T;-", -"M 5M,; >M- ,5TM; >Ms- EL,2 ,&EL2 HL,2 ,HaL2 5E,L ,58EL ,LH5 ,H58L ME,2 M&E,", -"2 ,2HM ,HM&2 ,E5M ,5M8E H5,M s,H5M d;,L d;-L ,LH; -;gL ,L5d -d>L ,H5dL >Lg-", -" dM,; dM-; HM,; g;-M 5d,M -d>M ,H5dM g->M ,LN &L,N NB,L aL,N N.,L 8L,N ,LN.", -"B ,8aLN ,QM Q&,M QT,M Qa,M QM,j Q8,M ,QTMj ,QsM *L,N -LN *B,LN aL-N ,*LN. 8", -"L-N ,LN*B. -8aLN Q*,M -QM ,QTM* Qa-M M*j,Q Q8-M ,QTM*j sQ-M ,WL ,LW& HW,L ,", -"LWa WL,. ,LW8 ,HWL. ,H8WL ,WM W&,M Z,M ,aZM WM,j W8,M ,MZj sMZ, ,LW* -WL ,H", -"WdL gL-W ,WdL. W8-L H*L,W. -W8gL WM,d -WM ,dZM Z-M ,WMdj W8-M Z*M,j -MsZ ,m", -"L ,Lm& mL,B ,Lam 5m,L ,L8m ,5mLB ,5amL ,Mm M&,m Tm,M aM,m p,M ,8pM ,TpM sMp", -", ,Lm* -mL m*L,B am-L m*L,5 >L-m ,5Lm*B ->amL Q;,M -Mm Mm*,T Tm-M ,Mp* -pM ", -"p*T,M -Msp Wm,L m&L,W ,LHm ,HmaL ,L5W ,5W8L ,H5WL ,H8mL WM,m Mm&,W ,MZm Z&M", -",m ,WpM p&W,M ZMp, Zp&,M v,L -vL ,HvL gL-v ,5vL >L-v v,H5L -vg>L vM, -vM vM", -"Z, gM-v vMp, >M-v Zp*,M y-M U) U!) UD) Ua) U). U8) D)U. U)D8 UM) M)U! V) Va", -") Uj) U)8M Vj) Vs) U* U+* U*D Ua* U*. U8* U.D* D8U* U*M +MU* V* V+* U*j +jU", -"* V*j s*V UE) !EU) UH) HaU) E)U. 8EU) H)U. U)H8 MEU) U!ME) VH) HaV) jEU) U8", -"ME) HjV) VHs) Ud* +dU* UH* gU* d*U. 8dU* U.H* U8g* dMU* dM*U+ Vd* gV* djU* ", -"U+jd* H*Vj s*gV U)2 !)U2 D)U2 a)U2 U5) 58U) U)5D U)5a M)U2 U!M)2 V2) a)V2 U", -")5M U58M) V5) s)V5 U;* +;U* D;U* a;U* U5* >U* 5DU* Ua>* M;U* M;*U+ V;* a;V*", -" 5MU* U*>M V5* V>* E)U2 U!E)2 H)U2 UHa)2 5EU) U58E) U)H5 UH58) UME)2 ME)U!2", -" H)V2 V2Ha) U5ME) 5MEU8) H5V) VsH5) d;U* U+d;* H;U* U;g* 5dU* Ud>* H5U* >*g", -"U dM;U* U+dM;* H;V* g;V* U5dM* >MUd* H5V* V*g> U)N !)UN D)UN a)UN N.U) 8)UN", -" UD)N. U8D)N UQ) U)Q! VQ) QaV) QjU) U)Q8 QjV) VQs) U*N +*UN UND* UNa* *NU. ", -"UN8* U*DN. U8*DN UQ* +QU* V*Q +QV* Q*Uj Q8U* Q*Vj sQV* UW) W!U) U)WD U)Wa W", -")U. U)W8 UHW). UH8W) U)WM UWQ!) VZ) VaZ) U)Wj UW8Q) VjZ) s)VZ UW* +WU* H*UW", -" UWg* U.W* W8U* UH*W. gUW8* WMU* U+WQ* Z*V Z*gV W*Uj U+W*j ZjV* VZs* Um) m)", -"U! U)Dm U)am 5mU) U)8m U5Dm) U5am) U)Mm Mm)U! Vm) amV) pU) U8p) Vp) s)Vp Um", -"* +mU* DmU* amU* 5*Um Um>* U5*Dm >DmU* Q;U* Mm*U+ Vm* +mV* pU* >Up* Vp* s*V", -"p WmU) UWm!) U)Hm UHma) U)5W U5W8) UH5W) UH8m) Mm)UW UW)Mm! Z)Vm VZam) UWp)", -" pUW8) Z)Vp VpZs) vU* U+v* UHv* g*vU U5v* >*vU vUH5* gvU>* UQv* vU+Q* Vv* V", -"*gv vUp* >MvU* Z*Vp yV* ,U ,U& ,UD cU, ,U. ,U8 UD,. ,Uc8 ,UM U&,M V, Vc, ,U", -"j b8,M V,j s,V ,U* -U U*,D c-U ,.U* -U8 ,UD*. c8-U bM* -UM V*b V- U*,j -Uj ", -",jV* V-s ,UE ,EU& ,UH ,UcH UE,. ,EU8 ,.UH UH,8 ,EbM M&E,U V,H cHV, ,EUj ,U8", -"ME ,HVj sHV, ,Ud -Ud UH,d g-U ,.Ud U8-d ,UHd. g8-U bd,M bd-M Vd, V-g Ud,j U", -"d-j ,dVj s-gV ,U2 ,2U& UD,2 ,Uc2 ,U5 U5,8 U5,D ,Uc5 ,2bM M&2,U V,2 c2V, b5,", -"M ,U58M V5, V5s, ,U; -U; U;,D -Uc; U5,; ->U ,U5D; -Uc> bM,; bM-; V;, V-; U;", -",j -U>M ,5V; V-> UE,2 ,U&E2 ,2UH c2U,H ,EU5 ,U58E UH,5 c5U,H ,UME2 ,UEM&2 ,", -"HV2 VcH,2 ,U5ME M&E,U5 ,HV5 s,VH5 Ud,; Ud-; UH,; g;-U U5,d -d>U ,UH5d ->gU ", -",UdM; -UdM; ,HV; V;g- ,U5dM >M-bd ,5Vd g-V> ,UN ,NU& UD,N ,UcN UN,. ,NU8 ,U", -"DN. cU8,N ,UQ U&,Q V,Q V,cQ UQ,j UQ,8 ,QVj sQV, ,NU* -UN ,UD*N cN-U ,U*N. U", -"8-N U*N,D. c-U8N UQb* -UQ ,QV* V-Q ,UQ*j UQ-j V*bQj -QVs ,UW U&,W UH,W ,UcW", -" ,.UW UW,8 ,UHW. cWU,8 bW,M ,UWQ& Z,V VcZ, UW,j ,UWQ8 ZjV, VZs, UW,d -UW ,U", -"HW* -UcW ,UWd. UW-8 ,U.WD* c-WU8 UQ,d bW-M VdZ, Z-V ,UWdj UW-j Zb*Vj sZV- ,", -"Um U&,m Um,D ,Ucm U5,m U8,m ,U5Dm c5U,m bM,m Mm&,U Vm, V,cm pU, ,Up& Vp, s,", -"Vp Um,; -Um ,UmD; -Ucm ,U5m* >U-m U5*,Dm c>-Um UQ,; bM-m ,QV; V-m ,Up* -pU ", -"V*pb V-p UW,m ,UWm& UH,m cWU,m U5,W ,U5W8 ,UH5W c5W,U ,UWMm ,UWMm& VmZ, ZcV", -",m ,UpW pU&,W Z,Vp cpZV, vU, -vU ,UvD gU-v ,Uv5 v>-U vU,H5 cv->U ,UvM vb-M ", -"Vv, V-v vUp, pv-U V,pv yV- k) k)! k)B ak) 1k) 8k) k)1B 1)ak kM) M!k) Tk) T)", -"ak l) l8) lT) ls) k* +k* k*B ak* 1*k 8k* 1k*B ak1* k*M k*+M Tk* T*+k l* l+*", -" l*T ls* kE) !Ek) Hk) H)ak kE1) kE8) 1)Hk H)8k MEk) kME!) H)Tk ak)HM lE) 8E", -"l) lH) sHl) dk* +dk* Hk* gk* dk1* dk8* Hk1* 1*gk k*dM dkM+* TkH* Tkg* ld* 8", -"dl* lH* gl* k)2 !)k2 2Bk) k2a) 5k) 5)8k k)5B 5)ak M)k2 kM)!2 k)T2 ak)T2 l5)", -" 58l) 5Tl) s5l) k;* +;k* *Bk; k;a* 5k* >k* *B5k ak>* M;k* k;M+* k;T* ak;T* ", -"l;* l>* 5Tl* s>l* E)k2 kE)!2 k)H2 ak)H2 kE5) 5k8E) H)5k H5k8) kME)2 ME)k2! ", -"HkT)2 Hk)aM2 5El) l58E) H5l) lsH5) d;k* dk;+* k;H* k;g* dk5* dk>* 5kH* >*gk", -" dkM;* +kdM;* Hk;T* gkT;* 5dl* >*ld H5l* g>l* k)N !)kN )BkN k)aN k)1N kN8) ", -"1k)NB ak)1N Qk) k)Q! Q)Tk Q)ak lQ) Q8l) QTl) sQl) k*N +Nk* kN*B aNk* 1Nk* k", -"N8* k*N1B ak*1N Qk* Q*+k TkQ* akQ* l*Q +Ql* Q*lT lQs* Wk) k)W! H)Wk W)ak 1)", -"Wk W)8k 1HWk) 1Wak) W)Qk WkQ!) Zk) akZ) lW) W8l) lZ) l)sZ Wk* W*+k WkH* Wkg", -"* Wk1* 8kW* 1H*Wk g1Wk* QkW* +WkQ* Zk* Z*gk lW* +Wl* lZ* l*gZ km) k!m) m)kB", -" a)km 1)km 8)km km)1B akm1) Q)km km)Q! T)km akmQ) lp) p8l) pTl) l)sp km* k*", -"+m *Bkm kma* km1* km>* km*1B >kam* kmQ* km*+Q kmT* akmQ* l*p p>l* lTp* spl*", -" W)km km)W! H)km akmH) 5)Wk 5Wk8) 1Hmk) H8km) km)WM Wk)Mm! kmZ) Zkam) pWl) ", -"lWp8) l)Zp lZps) vk* +kv* Hkv* g*vk 1*vk >*vk v1Hk* >kgv* Qkv* vk+Q* vkZ* Z", -"vkg* lv* v>l* Zpl* yl* ,k ,k& ,kB ,ak ,1k :k, 1k,B ,a:k ,kM k&,M ,Tk 9a,M l", -", l:, l,T ls, ,k* -k *B,k -ka 1*,k :-k k*B,1 :a-k 9M* -kM Tk9* -Tk l*9 l- ,", -"Tl* l-s ,kE ,Ek& ,Hk Hk,a 1k,E ,k:E 1H,k ,H:k ,E9M k&E,M 9H,M ,HkT& l,E :,l", -"E lH, s,lH ,dk -kd Hk,d g-k 1d,k -k:d ,1Hdk :-gk 9d,M 9d-M HM9* -Tgk ld, l-", -"d ,Hld gl- ,k2 ,2k& k2,B ,2ak ,5k ,5:k ,B5k 5a,k ,29M k&2,M ,2Tk ,Tk&2 l,5 ", -":5l, ,5lT l5s, ,k; -k; ,Bk; ak-; 1;,k >k- ,1;kB -a>k 9M,; 9M-; Tk,; Tk-; l;", -", l-> ,Tl; s-l> kE,2 k&E,2 ,2Hk ,Hk&2 ,E5k :5k,E H5,k :H5,k ,kME2 ,kEM&2 ,H", -"kT2 ak2,HM ,5lE l:5,E ,Hl5 ls,H5 dk,; dk-; Hk,; g;-k 5d,k -d>k ,1Hk; g->k ,", -"dkM; -kdM; ,HkT; -Tkg; ,5ld ->ld ,Hl; g-l> ,kN ,Nk& kN,B ,Nak 1k,N ,k:N ,1k", -"NB :ak,N ,Qk Q&,k Qk,T Qa,k l,Q :Ql, ,QlT lQs, ,Nk* -kN k*N,B ak-N k*N,1 :N", -"-k ,1Nk*B :-akN Qk9* -Qk ,QkT* Qa-k ,Ql* l-Q l*9QT -Qls ,Wk W&,k Hk,W Wa,k ", -"1W,k ,W:k ,1HWk :HW,k 9W,M ,WkQ& Zk, ,aZk lW, :Wl, lZ, l,Z: Wk,d -Wk ,HkW* ", -"-Wgk ,1Wdk -k:W 1H*,Wk g:-Wk WM9* 9W-M ,dZk Z-k ,Wld l-W Z9l* l-Z ,km k&,m ", -",Bkm ak,m 1m,k ,k:m ,1mkB :ma,k 9M,m km&,Q Tk,m akm,Q l,p l,:p lTp, spl, km", -",; -km km*,B ak-m km*,1 -k:m kmB,1; :-mak Qk,; 9M-m km*,T Tk-m p9l* l-p l;,", -"pT ls-p Wk,m km&,W Hk,m akm,H 5W,k :W5,k ,1Hkm :Hm,k ,WkMm ,WkMm& ,kZm Zk&,", -"m p,lW :pl,W Zpl, lZ,:p vk, -vk ,Hvk gk-v ,1vk >k-v v1,Hk :v-gk ,Qvk v9-M v", -"kZ, Zk-v lv, l-v Zvl, yl- Uk) k)U! Dk) U)ak 1U) 1)U8 1)Dk 1)Ua kMU) U!kM) V", -"k) akV) lU) U8l) Vl) l)Vs U*k +kU* Dk* D*+k 1U* U+1* U*1D Ua1* UkM* k*MU+ V", -"*k +kV* l*U U+l* l*V Vls* kEU) U!kE) U)Hk ak)UH UE1) 1U8E) 1)UH 1UH8) UkME)", -" kMEU!) HkV) VHak) UEl) lU8E) VHl) lsVH) dkU* dk*U+ HkU* U*gk Ud1* 1U+d* UH", -"1* 1Ug* dkMU* U+dk*M HkV* V*gk Udl* l+Ud* Vdl* l*gV k)U2 U!k)2 k)D2 ak)U2 1", -")U5 1U58) 5)Dk 1Ua5) UkM)2 kM)U!2 k)V2 V2ak) U5l) lU58) l)V5 lsV5) k;U* k;*", -"U+ k;D* ak;U* U51* 1U>* Dk5* Dk>* k;MU* U+kM;* k;V* V+k;* U5l* >Ul* V5l* l*", -"V> UkE)2 kE)U!2 UHk)2 UH)ak2 1U5E) 5kEU8) 1UH5) ak)UH5 kMEU)2 !)k2UME V2Hk)", -" ak)V2H lU5E) U58lE) Vl5H) Vs5lH) dk;U* U+dk;* UH;k* gUk;* 1Ud5* >kUd* 1UH5", -"* >kgU* UdkM;* dkU;+M* Vdk;* gVk;* ldU5* l>Ud* lH;V* V>lg* k)UN U!k)N k)DN ", -"ak)UN U)1N 1U8)N 1UD)N 1Ua)N U)Qk UQk!) QkV) VQak) UQl) lUQ8) VQl) lsVQ) UN", -"k* k*NU+ DNk* ak*UN 1NU* 1U+*N 1U*DN 1Ua*N QkU* U+Qk* QkV* V+Qk* UQl* l+UQ*", -" lQV* s*VlQ U)Wk UWk!) W)Dk UWak) 1)UW 1UW8) 1UHW) 1UWa) UWQk) Wk)UQ! VkZ) ", -"ZkVa) UWl) lWU8) l)VZ lZVs) WkU* U+Wk* DkW* gUWk* UW1* 1U+W* 1UHW* g1UW* UW", -"*Qk +WkUQ* V*Zk gVZk* UWl* l+WU* VlZ* glZV* U)km km)U! D)km akmU) 1)Um 1Um8", -") 1UmD) 1Uam) km)UQ UQ)km! kmV) Vmak) l)pU pUl8) l)Vp Vpls) kmU* km*U+ kmD*", -" akmU* Um1* >kUm* km*1D >kDm* km*UQ U+Qkm* kmV* V+mk* pUl* l>pU* l*Vp V>lp*", -" km)UW UW)km! UHmk) ak)UHm 1UW5) km)UW8 1UHm) ak)U5W UWQkm) W)QkUm! ZkVm) V", -"maZk) lWpU) pU8lW) VplZ) lZsVp) U*vk vU+k* Dkv* gvUk* 1Uv* >kvU* v1UH* >kvD", -"* vUQk* U+Qvk* vkV* Vvgk* vUl* lv>U* l*Vv l*yV t, t&, tD, tc, t1, t:, ,1tD ", -"t,:c tM, ,Mt& Vt, V,tc lt, t:l, l,V u, t* t- t*D t-c t*1 t-: 1Dt* :ct- t*M ", -"t-M t*V V-t lt* l-t Vlt* u- t,E ,&tE tH, cHt, ,1tE :,tE ,1tH t,:H ,MtE tM&,", -"E V,tH tcV,H t,lE t:,lE tHl, uH, td* t-d tH* gt- ,1td :-td 1Ht* t-g: ,dtM -", -"Mtd Vdt* V-gt tdl* ldt- tHl* ug- t,2 ,&t2 ,Dt2 c2t, t5, :5t, ,5tD t,c5 ,Mt2", -" tM&,2 t,V2 tcV,2 t5l, t:5l, V5l, u5, t;* t-; ,Dt; c-t; t5* t>- 5Dt* c>t- ,", -"Mt; -Mt; V;t* t;V- t5l* t>l- V5t* u-> ,Et2 t&,E2 ,Ht2 tcH,2 ,5tE t:5,E ,Ht5", -" t:H,5 tM,E2 M&Et,2 tHV,2 Vc,tH2 t5,lE l:,t5E tH5l, ,Hu5 ,dt; -dt; ,Ht; t;g", -"- ,5td ->td H5t* g-t> tdM,; t-dM; tH;V* V-gt; t5dl* l-t>d tH5l* g-u> t,N ,&", -"tN ,DtN c,tN ,1tN :,tN t1D,N t:c,N tQ, ,Qt& V,tQ t,cQ tQl, t,:Q lQV, uQ, t*", -"N t-N D*tN tNc- 1*tN tN:- t*1DN t-:cN tQ* t-Q V*tQ tQV- tQl* tQl- tQ*Vl u-Q", -" tW, ,Wt& ,HtW t,cW ,1tW t,:W tH1,W t:H,W ,WtQ tWQ,& tZ, Z,tc tWl, t:Wl, l,", -"tZ uZ, tW* t-W H*tW tWg- 1Wt* :-tW tH*1W t-Wg: ,Qtd -WtQ tZ* tZ- tWl* lWt- ", -"l*tZ uZ- tm, ,mt& ,Dtm t,cm ,1tm t,:m t5D,m t:mc, ,Qtm tQm,& V,tm tcQ,m tp,", -" p,t: l,Vp up, tm* t-m Dmt* c-tm 1mt* :-tm t5*Dm t-mc> ,Qt; -Qtm Vmt* tmV- ", -"tp* tp- t*Vp up- ,Wtm tWm,& ,Htm tcW,m ,5tW t:W,5 tH5,W t:H,m tWQ,m Mm&tW, ", -"Z,tm tZc,m p,tW tp:,W Z,tp Zpu, tv* tv- vDt* t-cv v1t* t-:v tv1,H gtv:- vMt", -"* tQ-v t*Vv Z-tv l*tv tvl- l,Vv yu- F !F FB aF F. 8F .BF 8aF FK !KF TF TaF ", -"jF 8jF TjF sF (F +F (BF +aF (F. +8F (F.B 8a+F (FK +FK T(F +TF j(F +jF j(TF ", -"s+F G G! GH Ga G. G8 GH. G8H GK GK! GT GTa Gj G8j GTj sG Gd +G GHd gG Gd. +", -"G8 HdG. gG8 GdK +GK GTd gGT Gjd +Gj TdGj gsG F2 !F2 2BF aF2 5F 58F 5BF 5aF ", -"2KF !F2K TF2 T2aF 5jF 8j5F 5TF s5F ;F +;F ;FB a;F 5;F >F ;F5B >Fa ;FK ;F+K ", -"T;F +FT; ;jF >jF 5FT; s>F G2 G2! GH2 Ga2 G5 G58 G5H G5a G2K 2KG! GT2 TaG2 G", -"5j 58Gj G5T sG5 G; +G; G;H gG; G5d >G H5G; g>G G;K GK+; GT; GTg; G;j >Gj H;", -"Gj s>G FN !FN NBF aFN N.F 8FN FBN. aN8F QF Q!F QTF QaF QjF Q8F TjQF sQF (FN", -" +FN (FNB aF+N (FN. 8F+N .BN(F +8aFN Q(F +QF T(QF +FQa j(QF +FQ8 QTj(F +QsF", -" GW W!G GHW GaW GW. G8W HWG. W8Ga GQ GQ! ZG ZGa GQj GQ8 ZGj sZG GWd +GW HWG", -"d gGW WdG. G8+W GHWd. G8gW GQd +GQ ZGd gZG QdGj GQ+j GjZd sGgZ mF mF! mFB a", -"mF 5mF 8mF mF5B 5Fam QmF mFQ! TmF QFam pF p8F pTF spF m;F +mF ;FmB +Fam m;5", -"F >mF 5m;FB am>F Q;F +FQ; QFT; +FTm p;F p>F T;pF >Fsp Gm Gm! GmH Gam G5W G8", -"m H5Gm H8Gm GQm Q!Gm ZGm GaZm pG pG8 ZpG spG vG v+G vGH gvG vG5 v>G G5vH >G", -"gv vGQ +GvQ ZvG gGZv pvG p>G pGZv yG #F &F #BF a&F #F. 8&F #F.B a&8F #FK &F", -"K T#F T&F j#F &jF j#TF s&F #(F +&F #(FB a&+F (F#. 8&+F #BF(. +8a&F (F#K &F+", -"K #(TF +FT& #(jF +F&j Tj#(F +&sF G# G& GH# Ga& G#. G8& H#G. H8G& G#K G&K GT", -"# GT& Gj# G&j G#Hj sG& Gd# +G& HdG# gG& d#G. 8dG& GHd#. G8g& dKG# GKd& G#Td", -" GTg& G#dj G&+j dj#GT g&sG #F2 &F2 #F2B &2aF 5#F 5&F #B5F a&5F #F2K 2K&F #F", -"T2 &FT2 j#5F 5F&j T#5F 5&sF ;#F ;&F #B;F aF;& ;#5F >&F 5;#FB a&>F #F;K &F;K", -" ;#TF TF;& j#;F &j>F ;j#TF s&>F G#2 G&2 H#G2 G2H& G5# G5& G#H5 H5G& 2KG# &2", -"GK T#G2 G2T& 5jG# 5&Gj G#5T G5s& G;# G;& G#H; G;g& G#5d >G& G5Hd# gG>& ;#GK", -" GK;& G#T; T;G& G#;j G&>j G5Td# >&sG #FN &FN #FNB &FaN #FN. &F8N #FN.B 8a&F", -"N Q#F Q&F T#QF QFT& j#QF QF&j QTj#F Q&sF (F#N &F+N #FN(B +a&FN #FN(. +8&FN ", -"#BFN.( 8a&+FN #(QF +FQ& QT#(F +QT&F Qj#(F &jF+Q Tj#Q(F s+Q&F GW# G&W HWG# W", -"aG& W#G. W8G& GHW#. G8HW& GQ# GQ& ZG# Z&G G#Wj W&Gj GjZ# Z&sG WdG# G&+W GHW", -"d# G&gW GWd#. +GW8& HWdG#. gGW8& G#Qd G&+Q GdZ# gGZ& dj#GQ d&jGQ ZGdj# Z&Gg", -"s m#F m&F #BmF aFm& m#5F 5Fm& 5m#FB am&5F m#QF QFm& m#TF TFm& p#F p&F T#pF ", -"sFp& ;#mF +Fm& m;#FB am&+F 5m;#F m&>F m;#5BF >ma&F ;#QF QF;& Q;T#F +Tm&F ;#", -"pF >Fp& pT;#F p>&sF Gm# Gm& G#Hm HmG& G#5W 5WG& G5HW# G5aW& QmG# Q&Gm GmZ# ", -"GmZ& pG# pG& Z#pG pGZ& vG# v&G GHv# gGv& G5v# >Gv& vGH5# gv>G& GQv# GQv& vG", -"Z# ZGv& vGp# v&pG ZpvG# y&G I I! DI aI I. 8I DI. D8I IK IK! TI TIa Ij 8Ij D", -"jI sI I( +I DI( +DI I(. +I8 I(D. D8+I I(K +IK TI( +TI Ij( +Ij D(Ij sI+ GI G", -"I! J Ja GI. G8I J. J8 GIK IKG! JT JTa GjI 8IGj Jj sJ Id +GI Jd gJ Id. 8Id J", -"d. gJ8 IdK GK+I JTd gJT Idj Gj+I Jjd sJg I2 I2! DI2 aI2 5I 5I8 5DI 5aI I2K ", -"2KI! TI2 I2Ta 5Ij 58Ij 5TI sI5 I; +I; D;I aI; 5I; >I D;5I >DI I;K +KI; TI; ", -"T;+I I;j >Ij T;5I s>I GI2 I2G! J2 Ja2 G5I 5IG8 J5 J58 I2GK GI2!K JT2 TaJ2 5", -"IGj G58Ij J5T sJ5 G;I G;+I J; gJ; 5Id >GI J5d J> GKI; IdK+; J;T gTJ; I;Gj G", -"j>I J;j J>s IN IN! DIN aIN IN. 8IN IND. DN8I QI QI! QDI QaI QIj Q8I DjQI sI", -"Q I(N +IN I(DN +NaI N.I( +N8I DI(N. +D8IN QI( +QI Q(TI QD+I Q(Ij Q8+I Ij(QD", -" +QsI WI WI! JW JWa WI. W8I JW. J8W GQI Q!WI ZJ ZJa WIj Q8WI ZJj sJZ WId +W", -"I JWd gJW W.Id W8+I WdJ. gWJ8 QId GQ+I ZJd gZJ IdWj WI+j ZdJj gZsJ Im Im! D", -"mI aIm 5Im 8Im Dm5I 8IDm QIm Q!Im TIm aITm pI pI8 pDI spI Im; +Im ImD; Dm+I", -" 5mI; >Im Im;5D Dm>I QI; QI+m D;QI TI+m pI; p>I D;pI p>sI GmI W!Im Jm Jma 5", -"WI W85I J5W J8m QIGm Im!GQ ZJm ZaJm pGI G8pI Jp Jps vI vI+ Jv Jvg vI5 v>I J", -"v5 J>v vIQ +QvI JvZ gZJv pvI v>pI Jpv yJ bI I& bDI cI bI. b8I DIb. c8I bKI ", -"I&K bTI cTI bjI I&j TIbj scI bI( b+I DIb( c+I I(b. +Ib8 bDI(. +Ic8 I(bK bK+", -"I b(TI +TcI b(Ij +Ibj Ij(bT c+sI bG bG& Jb cJ bG. bG8 Jb. cJ8 bGK bKG& JbT ", -"cJT bGj G8bj Jjb sJc bGd b+G Jbd gJc b.Id +Gb8 bdJ. J8gc bKId bK+G bTJd gTc", -"J Gjbd +Gbj bdJj gcsJ bI2 I&2 DIb2 c2I b5I 5I& bD5I c5I I2bK &2IK b2TI TIc2", -" 5Ibj Ij5& 5IbT c5sI b;I I;& bDI; c;I 5Ib; >bI b5DI; c>I bKI; IK;& TIb; TIc", -"; I;bj bj>I I;jbT sIc> bG2 b2G& Jb2 cJ2 bG5 G5b8 J5b cJ5 G2bK I&2GK bTJ2 JT", -"c2 G5bj I&jG5 b5Jj c5sJ bG; +Gb; J;b cJ; G5bd >bG b5J; J>c bKG; I;&GK bTJ; ", -"cTJ; G;bj bG>j b;Jj c>sJ bIN I&N DIbN cIN INb. bN8I bDIN. 8IcN bQI QI& QIbT", -" cQI QIbj QIb8 bQDIj cQsI I(bN bN+I bDI(N +IcN bI(N. I&N+8 DI(bN. c+8IN b(Q", -"I +IbQ bQDI( +QcI Ij(bQ I&j+Q bQDIj( sI+cQ bGW WI& JbW cJW b.WI G8bW bWJ. J", -"8cW bGQ G&bQ ZJb ZcJ GQbj GQb8 JjZb ZcsJ WIbd +GbW bWJd cWgJ Id.bW b+GW8 Jb", -"Wd. cJWg8 GQbd +GbQ JbZd gJZc IdjbW IdjW& ZJbdj sJZgc bmI Im& bDIm cmI 5Ibm", -" 8Ibm b5DIm 5Icm QIbm ImQ& TIbm QIcm pbI pI& bTpI cpI Imb; +Ibm Im;bD +Icm ", -"Im;b5 bm>I b5DIm; >Icm QIb; I;Q& bQ;TI QIc; b;pI >bpI pbDI; pIc> bGm G&bm J", -"mb cJm G5bW G8bm b5Jm J5cW GQbm Im&GQ JmZb cmZJ pbG bGp& Jpb cpJ vbG vI& Jv", -"b cvJ bGv5 >bvI vbJ5 J>cv bGvQ QIv& ZbJv JvZc vbpG vIp& pbJv yJc 0F !0F 0BF", -" a0F 1F 18F 1FB 1aF 0FK 0F!K T0F a0TF 1jF 8j1F 1TF s1F 0(F +0F 0(FB a0+F 1(", -"F 1+F (B1F +a1F (F0K 0F+K 0(TF T0+F j(1F 1F+j T(1F 1+sF G0 G0! GH0 Ga0 1G 1", -"G8 1GH 1Ga G0K !KG0 GT0 TaG0 1Gj 18Gj 1GT sG1 Gd0 +G0 HdG0 gG0 1Gd 1+G GH1d", -" g1G dKG0 GK+0 G0Td GTg0 Gj1d +j1G GT1d sGg1 0F2 0F!2 0F2B 0Fa2 15F 581F 5B", -"1F 1F5a 0F2K 2K0!F 0FT2 Ta0F2 5j1F 158jF 1F5T 15sF ;0F ;0+F 0B;F ;0aF 1;F >", -"F1 ;F1B 1a>F 0F;K +;0FK ;0TF a;0TF 1F;j 1j>F 1FT; s1>F G02 !0G2 H0G2 a0G2 1", -"G5 15G8 G51H G51a 2KG0 G02!K T0G2 GTa02 15Gj 1G58j G51T 1Gs5 G;0 +0G; G0H; ", -"G;g0 1G; >G1 G;1H >Gg1 ;0GK +G;0K G0T; gGT;0 Gj1; 1G>j GT1; s1>G 0FN 0F!N 0", -"FNB 0FaN 1FN 8F1N NB1F aF1N Q0F !0QF T0QF a0QF 1QF 1FQ8 QT1F 1QsF (F0N 0F+N", -" 0B(FN +a0FN (F1N +F1N 1(FNB 1+aFN 0(QF Q0+F QT0(F +QT0F Q(1F 1F+Q 1QT(F s1", -"+QF GW0 G0W! HWG0 G0Wa 1GW G81W GH1W Ga1W GQ0 G0Q! ZG0 GaZ0 1GQ G81Q Z1G Z1", -"sG WdG0 GW+0 GHWd0 GWg0 GW1d +G1W 1GHWd 1GgW G0Qd +0GQ GdZ0 ZGg0 GQ1d +G1Q ", -"1GZd gGZ1 m0F !0mF 0BmF m0aF 1mF 1F8m mF1B 1Fam m0QF Q!m0F m0TF am0QF p1F 1", -"8pF 1TpF p1sF ;0mF m0+F m;0FB am0+F m;1F 1m>F 1m;FB >m1aF ;0QF +Qm0F Q;T0F ", -"+Tm0F 1;pF p1>F p1T;F p>1sF Gm0 m0G! G0Hm G0am 1Gm G81m Gm1H Ga1m QmG0 GQm!", -"0 GmZ0 ZGam0 pG1 1Gp8 pGZ1 s1pG vG0 +Gv0 GHv0 vGg0 v1G >Gv1 1GvH gGv1 GQv0 ", -"v+GQ0 vGZ0 ZvGg0 v1pG p1>G ZGv1 y1G 9F 9&F 9FB 9aF 91F :F 1B9F :aF 9FK &F9K", -" 9TF 9FT& 9jF :jF 9F1T s:F 9(F 9+F (B9F +a9F 1(9F :+F 91(FB +a:F (F9K +F9K ", -"T(9F 9F+T j(9F +j:F 9T1(F :+sF 9G 9G& 9GH 9Ga 9G1 :G 1G9H :GH 9GK 9KG& 9GT ", -"GT9a 9Gj :Gj 1G9T s:G 9Gd 9+G GH9d g9G 1G9d :G+ 9G1Hd g:G Gd9K 9K+G GT9d 9G", -"gT Gj9d +G:j 9GT1d sGg: 9F2 &F92 2B9F aF92 95F :5F 5B9F 5a:F 2K9F 9&F2K TF9", -"2 9TaF2 5j9F 5j:F 9F5T :5sF 9;F 9F;& ;F9B 9Fa; 9F1; :>F 95;FB :a>F ;F9K ;&F", -"9K 9FT; 9+T;F 9F;j :j>F 95T;F >Fs: 9G2 92G& GH92 92Ga 9G5 :G5 G59H G5:H G29", -"K 9G&2K 92GT 9GT&2 G59j G5:j G59T s5:G 9G; +G9; G;9H 9Gg; 1G9; :>G 9G5H; :G", -"g> 9KG; 9+G;K GT9; g9GT; G;9j >j:G 9G5Td :>sG 9FN &F9N NB9F aF9N 1F9N :FN 9", -"1FNB aF:N 9QF 9FQ& QT9F 9FQa 9F1Q :QF 9Q1TF sF:Q (F9N +F9N 9(FNB 9+aFN 91(F", -"N +F:N 1(F9NB :+aFN Q(9F 9F+Q 9QT(F 9+QTF 9Q1(F +Q:F 1Q(9TF :Q+sF 9GW G&9W ", -"GH9W Ga9W 1G9W :GW 9G1HW Ga:W 9GQ G&9Q Z9G 9GZ& 1G9Q :GQ 9GZ1 Z:G GW9d +G9W", -" 9GHWd 9GgW 9G1Wd +G:W 1GH9Wd gG:W GQ9d +G9Q 9GZd gGZ9 9GQ1d +G:Q Z91Gd :Gg", -"Z 9mF 9Fm& mF9B 9Fam 9F1m :mF 95mFB am:F Qm9F m&F9Q 9FTm 9QamF p9F :pF 9TpF", -" sF:p m;9F 9F+m 9m;FB 9+maF 95;mF >F:m 1mF9;B :>amF 9FQ; 9+QmF 9Q;TF 9+TmF ", -"9;pF >F:p p9T;F :ps>F 9Gm G&9m Gm9H Ga9m 1G9m :Gm 9G5Hm Ga:m GQ9m 9GQm& 9GZ", -"m Z9Gam p9G :pG pGZ9 sG:p v9G 9+vG 9GvH gGv9 9Gv1 :vG v91GH :Ggv 9GvQ v9+GQ", -" ZGv9 Zv9gG v9pG pv:G Zp9vG y:G I0 I0! DI0 aI0 1I 1I8 1DI 1aI I0K !KI0 TI0 ", -"T0aI 1Ij 18Ij 1TI sI1 I0( +I0 I0D( +0aI 1I( 1+I DI1( +D1I 0(IK I0+K I0T( +0", -"TI 1(Ij +j1I 1(TI 1+sI GI0 I0G! J0 Ja0 1GI G81I J1 J18 I0GK GI0!K JT0 TaJ0 ", -"Gj1I 1G8Ij J1T sJ1 Id0 +0Id Jd0 gJ0 1Id +G1I J1d gJ1 I0dK Id0+K TdJ0 JTg0 I", -"j1d Idj1+ 1TJd g1sJ I02 !0I2 I2D0 I2a0 1I5 158I 5D1I 5a1I 2KI0 I02!K I2T0 T", -"Ia02 15Ij 1I58j 5T1I 1Is5 I;0 +0I; D0I; a0I; 1I; >I1 D;1I 1D>I ;0IK I;0+K T", -"0I; +TI;0 Ij1; 1I>j TI1; s1>I I0G2 GI0!2 J02 a0J2 G51I 1G58I J15 1aJ5 GI02K", -" I02GK! T0J2 JTa02 1G5Ij G581Ij 1TJ5 s1J5 G0I; Id0+; J;0 g0J; G;1I 1G>I J1;", -" J>1 Id0;K +G0I;K T;J0 gJT;0 Idj1; >I1Gj 1TJ; J1s> I0N !0IN I0DN I0aN 1IN 1", -"N8I DI1N 1NaI QI0 I0Q! Q0TI Q0aI 1QI Q81I QD1I 1QsI 0(IN I0+N DI0(N +DI0N I", -"(1N 1N+I 1DI(N 1+DIN I0Q( +0QI QDI0( +QDI0 1(QI +Q1I 1QDI( sI1+Q WI0 I0W! J", -"W0 WaJ0 1WI W81I J1W 1WJ8 G0QI GQI!0 ZJ0 JaZ0 GQ1I 1GQ8I ZJ1 Z1sJ W0Id +0WI", -" WdJ0 JWg0 WI1d +W1I 1WJd gWJ1 Q0Id +GQI0 JdZ0 g0ZJ QI1d 1+GQI ZdJ1 ZJg1 Im", -"0 I!m0 D0Im a0Im 1Im 8I1m Dm1I aI1m Q0Im Im0Q! T0Im QaIm0 pI1 1Ip8 1DpI s1p", -"I m;I0 +0Im Im;D0 +DmI0 Im1; 1I>m 1DmI; >Dm1I Q0I; +QIm0 QD;I0 +TIm0 1Ip; p", -"1>I pD1I; p>D1I G0Im Im0W! Jm0 amJ0 Gm1I 1Gm8I J1m 1aJm Im0GQ GQ0Im! Z0Jm Z", -"Jam0 1GpI pG81I Jp1 J1sp vI0 +Iv0 Jv0 g0Jv v1I >Iv1 Jv1 g1Jv QIv0 vI+Q0 Z0J", -"v JvZg0 v1pI pvI>1 Z1Jv yJ1 9I 9I& 9DI c9I b1I :I 1D9I :cI 9IK 9KI& 9TI 9Tc", -"I 9Ij :Ij 1T9I s:I 9I( 9+I DI9( 9+cI b(1I :I+ b1DI( c+:I I(9K 9K+I 9(TI +T9", -"I 9(Ij +I:j b1TI( s+:I bG9 G&9I J9 cJ9 b1G :Gb J91 :J bK9G I&K9G J9T cTJ9 9", -"Gbj bG:j J9j :Js 9Id 9+bG J9d gJ9 1Gbd :Id b1Jd :Jg 9KId b+G9K 9TJd gTJ9 Id", -"9j Id:j 9dJj sJg: 9I2 92I& DI92 9Ic2 95I :I5 5D9I c5:I I29K I&29K 92TI c29T", -"I 5I9j 5I:j 5T9I s5:I 9I; +I9; D;9I 9Ic; 1Ib; :>I b1;DI :Ic> 9KI; I;&9K TI9", -"; c;9TI I;9j >j:I I;j9D :>sI b29G I&29G J92 c2J9 9Gb5 bG:5 J95 :J5 bG92K 9G", -"2I&K 9TJ2 cJ9T2 b1G5j :Gb5j 95Jj J5s: 9Gb; I;&9G J9; J9c; 1Gb; >b:G b1J; :J", -"> bG;9K I;K9+G 9TJ; cJ;9T Idj95 :>Gbj 9;Jj s:J> 9IN 9NI& DI9N 9IcN bN1I :IN", -" b1DIN cN:I 9QI Q&9I QD9I 9QcI 1Q9I :QI b1QTI :QsI I(9N 9N+I 9DI(N c9+IN b1", -"I(N +I:N 1D(9IN :c+IN 9(QI +Q9I 9QDI( cQ9+I b1QI( +Q:I Ij(9QD :cQ+I 9WI W&9", -"I J9W J9cW 1GbW :WI b1JW :JW 9GbQ bGQ9& ZJ9 cJZ9 1GbQ bG:Q J9Z1 Z:J WI9d +W", -"9I 9WJd gWJ9 b1GWd +W:I J91Wd :WgJ QI9d b+G9Q ZdJ9 ZJg9 Idj9W QI:d ZJ91d gZ", -":J 9Im I&9m Dm9I 9Icm 1Ibm :Im b1mDI cm:I QI9m Im&9Q TI9m cQ9Im p9I :pI 9Dp", -"I sI:p Im9; +I9m 9DmI; cm9+I b1mI; >I:m 1Dm9I; c>:Im QI9; I;&9Q 9QDI; cQ;9I", -" 9Ip; p>:I p9DI; cp:>I 9Gbm Im&9G J9m J9cm 1Gbm bG:m b1Jm :Jm bGQ9m 9GQIm& ", -"JmZ9 ZJ9cm b1pG pb:G Jp9 :Jp v9I 9+vI Jv9 g9Jv b1vI :vI vbJ1 :Jv 9QvI v9I+Q", -" Z9Jv cvZJ9 v9pI pv:I pvJ9 yJ: FL !FL LBF aFL FL. 8FL FL.B aF8L MF MF! TMF ", -"aMF MjF 8MF MjTF sMF (FL +FL (FLB aF+L FL(. 8F+L (BLF. +8aFL M(F +MF M(TF +", -"FaM j(MF +F8M TMj(F +MsF GL GL! GHL GaL GL. G8L HLG. GLH8 GM GM! GTM GaM GM", -"j G8M HMGj sGM GdL +GL HdGL gGL dLG. +LG8 GHdL. G8gL GMd +GM TdGM gMG dMGj ", -"G8+M dMjGT sGgM FL2 FL!2 FL2B FLa2 5FL 8F5L LB5F aF5L MF2 !FM2 MFT2 M2aF 5M", -"F 5F8M TM5F 5MsF ;FL ;F+L LB;F ;FaL ;F5L >FL 5;FLB aF>L M;F +FM; TFM; aFM; ", -"5FM; >MF M;F5T sM>F GL2 !LG2 HLG2 aLG2 G5L 58GL GLH5 GL5a GM2 M2G! G2HM G2a", -"M G5M 5MG8 H5GM G5sM G;L +LG; GLH; G;gL GL5d >GL G5HdL gG>L GM; G;+M HMG; G", -"Mg; 5dGM >MG G5TdM sG>M FLN FL!N FLNB FLaN FLN. FL8N .BLFN 8aFLN QMF MFQ! T", -"MQF QFaM MjQF QF8M QTMjF QMsF FL(N FL+N (BLFN +aFLN N.(FL +8FLN (BFN.L 8aF+", -"LN M(QF QM+F QTM(F aMF+Q QMj(F +Q8MF TMjQ(F s+QMF GWL GLW! HWGL GLWa WLG. G", -"LW8 GHWL. G8HWL GQM Q!GM ZGM GaZM WMGj W8GM GMZj ZGsM WdGL GW+L GHWdL GWgL ", -"GWdL. +GW8L HWdGL. gGW8L QdGM GQ+M GMZd ZGgM dMjGQ +GQ8M ZGdMj gZsGM mFL !F", -"mL LBmF mFaL mF5L mF8L 5mFLB amF5L MmF M!mF TFMm aFMm pMF 8MpF TMpF pMsF ;F", -"mL mF+L m;FLB amF+L 5m;FL mF>L m;F5BL >maFL QFM; +FMm MmFT; aMm+F M;pF pM>F", -" pTM;F >MpsF GmL mLG! GLHm GLam GL5W GL8m G5HWL G5aWL GMm G!Mm GMZm aMGm pG", -"M G8pM ZMpG sMpG vGL +GvL GHvL vGgL G5vL vG>L vGH5L gv>GL vMG +GvM ZGvM gGv", -"M vMpG pG>M ZpvGM yGM #FL &FL #FLB &FaL FL#. &F8L #L.FB 8a&FL M#F M&F M#TF ", -"TFM& j#MF 8FM& TMj#F M&sF (F#L &F+L (BL#F +a&FL #L.(F +8&FL (BF#L. 8a&+FL #", -"(MF +FM& TM#(F aMF+& Mj#(F M&F+j Mj#T(F s+M&F G#L G&L H#GL GLH& #LG. 8&GL G", -"H#L. G8H&L GM# GM& G#HM HMG& MjG# 8MG& GTMj# GMs& d#GL +LG& GHd#L G&gL Gd#L", -". d&LG8 Hd#GL. gG8&L G#dM G&+M dM#GT GMg& dMjG# dM&G8 GTMdj# gsGM& FL#2 FL&", -"2 #L2FB a&FL2 #F5L &F5L 5B#FL 5a&FL #FM2 &FM2 TM#F2 aMF&2 M#5F 5FM& 5TM#F s", -"5M&F #F;L &F;L ;#FLB a;&FL 5;#FL &F>L ;#F5BL >&aFL ;#MF MF;& M;#TF aM;&F M;", -"#5F M&>F 5T#M;F >Ms&F #LG2 &LG2 GH#L2 Ga&L2 5#GL GL5& G5H#L G5a&L M#G2 G2M&", -" GTM#2 GT&M2 G#5M 5MG& G5TM# sG5M& ;#GL GL;& G;H#L gG;&L G5d#L G&>L H5#G;L ", -"g>G&L G#M; M;G& GT;M# gMG;& G5Md# GM>& dM#G5T >MgG& FL#N FL&N #LNFB a&FLN #", -"LNF. 8&FLN .BL#FN a&F8LN M#QF QFM& QTM#F aMFQ& QMj#F M&FQ8 TMjQ#F sQM&F #LN", -"(F +&FLN #FN(BL a&F+LN #(FN.L 8&F+LN (FLBN.# 8a+&FLN QM#(F M&F+Q TM#Q(F +QT", -"M&F Mj#Q(F +Q8M&F #(TFQMj M&Fs+Q W#GL GLW& GHW#L GaW&L GW#L. G8W&L HW#GL. H", -"8WG&L G#WM WMG& GMZ# GMZ& GQMj# GQ8M& ZGMj# Z&GsM GWd#L d&LGW HWdG#L gGW&L ", -"Wd#GL. G8Wd&L WdG#HL. G8Wg&L dM#GQ dM&GQ ZGdM# Z&GgM GQMdj# GQ8dM& dMjZG# g", -"sGZ&M #FmL &FmL m#FLB am&FL 5m#FL m&F5L m#F5BL 5aFm&L m#MF MFm& Mm#TF aMm&F", -" M#pF M&pF pTM#F p&MsF m;#FL m&F+L ;#FmLB m&Fa;L m;#5FL >m&FL LBmF5;# am&>F", -"L Mm#;F Mm&+F Tm#M;F aMFQ;& pM;#F >Mp&F M;#pTF p&F>Ms m#GL GLm& GmH#L Gam&L", -" G5W#L G5&WL H5#GmL amLG5& G#Mm MmG& ZGMm# Z&GMm GMp# GMp& ZpGM# Zp&GM G#vL", -" G&vL vGH#L gvG&L vG5#L v>G&L G5Hv#L v&Gg>L GMv# GMv& ZvGM# Zv&GM pvGM# >Mv", -"G& pGMZv# GMy& UI U!I UDI UaI UI. U8I DIU. 8IUa IM IM! VI VaI UjI 8IM VIj s", -"IV UI( U+I DIU( +IUa I(U. +IU8 UDI(. U+D8I IM( +IM VI( V+I U(Ij +IUj IjV( V", -"+sI UG UG! JU JUa UG. UG8 JU. J8U UGM U!GM VJ VJa UGj G8Uj JjV sJV UGd U+G ", -"JUd gJU U.Id +GU8 UdJ. J8gU IdM +MUG VJd gVJ GjUd +GUj VdJj sJgV UI2 I2U! D", -"IU2 U2aI U5I 5IU8 UD5I 5IUa IM2 I!M2 V2I aIV2 5IM 8I5M V5I V5sI U;I +IU; UD", -"I; aIU; 5IU; >UI U5DI; Ua>I IM; I;+M V;I +IV; I;Uj >MI 5IV; V>I UG2 G2U! JU", -"2 UaJ2 UG5 G5U8 J5U U5J8 U2GM IM2G! VJ2 JaV2 G5Uj UG58M J5V VsJ5 UG; +GU; J", -";U J;gU G5Ud >UG U5J; J>U GMU; IdM+; J;V J;gV G;Uj UG>M V5J; J>V UIN INU! D", -"IUN UNaI INU. UN8I UDIN. U8IDN UQI Q!IM VQI QaVI QIUj QIU8 QIVj VQsI I(UN U", -"N+I UDI(N U+DIN UI(N. U+8IN DI(UN. +DIU8N U(QI +IUQ QIV( +QVI IM(Qj U+Q8I V", -"QIj( sIV+Q UGW U!WI JUW UWJa U.WI G8UW UWJ. UWJ8 UGQ Q!UG ZJV ZaVJ GQUj GQU", -"8 VZJj VZsJ WIUd +GUW UWJd JUgW Id.UW U+GW8 JUWd. gJUW8 GQUd +GUQ VdZJ ZJgV", -" IdMWj IdMW8 ZJVdj gVZsJ UmI U!Im UDIm aIUm 5IUm 8IUm U5DIm U5aIm IMm I!Mm ", -"VmI aIVm pUI U8pI VpI sIVp ImU; +IUm Im;UD U+maI Im;U5 Um>I U5DIm; >DmUI QI", -"U; IM+m QIV; +IVm U;pI pI>M pIV; pIV> UGm U!Gm JmU UaJm G5UW G8Um U5Jm U8Jm", -" GQUm IMmW! JmV JaVm pUG UGp8 JpV VpsJ vUG U+vI JvU gUJv UGv5 >UvI vUJ5 vUJ", -"> vIM +IvM VvJ JvgV vUpG vI>M VvJp yJV bUI U&I UDbI cUI UIb. 8IU& bUDI. U8c", -"I bMI IM& VbI VcI IMbj 8IbM bjVI VcsI UIb( +IU& bUDI( U+cI bUI(. b+U8I UDIb", -"(. cU+8I b(IM +IbM bIV( cIV+ IM(bj IM&+j VbIj( sIVc+ bGU UG& JbU cJU b.UG U", -"Gb8 bUJ. cUJ8 bGM GMU& VJb cJV UGbj G8bM VbJj VJsc UGbd U+bG bdJU cJgU Id.b", -"U b+GU8 JbUd. cJUg8 GMbd +GbM JbVd cJgV IdMbj IdMb8 JjVbd gVJsc UIb2 U2I& b", -"UDI2 UIc2 bU5I 5IU& b5UDI U5cI b2IM I2M& bIV2 cIV2 5IbM IM5& b5VI cIV5 bUI;", -" I;U& b;UDI U;cI b5UI; U&>I U5Db;I cU>I IMb; M;I& b;VI cIV; IM;b5 bM>I V5bI", -"; >IVc b2UG U2G& bUJ2 JUc2 UGb5 G5U& b5JU cUJ5 b2GM IM&G2 JbV2 V2cJ G5bM IM", -"&G5 JbV5 VJc5 UGb; G;U& b;JU cUJ; bG5Ud bG>U J5bUd >UcJ GMb; IdM;& JbV; VJc", -"; IdMb5 bG>M J5Vbd cJV> UIbN UNI& bUDIN UIcN bUIN. I&NU8 UDIbN. cU8IN QIbM ", -"QIU& bQVI VQcI bQUIj IM&Q8 VbQIj sIVcQ bUI(N I&NU+ UDIb(N cU+IN UI(bN. U+8I", -"&N UDbIN.( U+8cIN IM(bQ IM&+Q VbQI( cQV+I bQUIj( U+QI&j Ij(VbQ cQVsI+ UGbW ", -"G&UW bWJU JUcW bGUW. bG8UW JbUW. cJUW8 UGbQ GQU& VJZb VZcJ bGQUj IM&W8 ZJVb", -"j sJZVc bGUWd b+GUW JbUWd cJUgW bWUId. U+GbW8 bWUJd. gJUcW8 IdMbW IdMW& ZJV", -"bd gVZcJ bWMIdj bW8IdM JjVZbd sJZgVc bUIm ImU& bmUDI UmcI b5UIm Im&U5 U5Dbm", -"I c5UIm IMbm MmI& bmVI cIVm bMpI U&pI VbpI pIVc Im;bU Im&U+ UmDb;I cmU+I b5", -"UIm; >ImU& Imb;U5D c>UIm IMmb; IMmb+ VmbI; cQ;VI pbUI; >MbpI VpbI; cpV>I UG", -"bm GmU& bmJU cUJm bG5UW bG8Um J5bUW cJ5UW GMbm IMmG& JbVm VJcm bGpU UGp& pb", -"VJ cJVp bGvU UGv& JbvU vUcJ vbUG5 v>bUG JvbU5 cvJ>U bGvM IMv& vbVJ cJVv pvb", -"UG >MvbG JpVvb cJyV kF kF! kFB akF 1kF 8kF kF1B 1Fak kMF M!kF TkF TFak lF l", -"8F lTF lsF k(F +kF (BkF +Fak k(1F 1F+k 1k(FB akF1+ M(kF kM+F k(TF +FTk l(F ", -"l+F T(lF sFl+ Gk Gk! GkH Gak 1Gk G8k Gk1H Gk1a GkM kMG! GTk TkGa lG lG8 lGH", -" lsG Gkd +Gk GHdk gkG Gk1d +k1G 1GHdk 1Ggk dkGM Gk+M TdGk GTgk lGd l+G GTld", -" glG kF2 !Fk2 2BkF k2aF 5kF 5F8k kF5B 5Fak MFk2 kMF!2 kFT2 akFT2 l5F 58lF 5", -"TlF sFl5 k;F +Fk; ;FkB aFk; 1Fk; >kF k;F1B ak>F kFM; k;M+F TFk; ak;TF l;F l", -">F T;lF >Fls Gk2 k2G! G2Hk G2ak G5k 5kG8 H5Gk 5aGk kMG2 GkM!2 G2Tk GTka2 lG", -"5 G5l8 G5lH l5sG Gk; G;+k HkG; Gkg; Gk1; >kG 1G;Hk >Ggk k;GM +GkM; TkG; gkG", -"T; lG; l>G GTl; g>lG kFN !FkN NBkF kFaN kF1N kN8F 1kFNB akF1N QkF kFQ! QFTk", -" QFak lQF Q8lF QTlF sFlQ (FkN kF+N k(FNB akF+N 1k(FN 1+kFN k(F1NB 1+FakN k(", -"QF +FQk QkT(F +QkTF Q(lF +QlF lQT(F ls+QF GkW W!Gk GHWk WaGk Gk1W W8Gk 1GHW", -"k 1GaWk GQk Q!Gk ZkG GaZk lGW GQl8 lZG sZlG GWdk Gk+W GkHWd GkgW 1GWdk 1+GW", -"k GkH1Wd g1GWk QdGk GQ+k GkZd gGZk GQld +GlW ZGld lGgZ kmF k!mF mFkB aFkm 1", -"Fkm 8Fkm kmF1B akm1F QFkm kmFQ! TFkm akmQF lpF p8lF pTlF sFlp m;kF +Fkm km;", -"FB akm+F km;1F km>F 1mFk;B >kamF QFk; +QkmF Qk;TF ak;QF p;lF >Flp l;pTF l>p", -"sF Gkm G!km HkGm akGm Gk1m 8kGm 1GmHk akm1G QkGm GQkm! GkZm ZkGam lGp l8pG ", -"ZplG splG vkG +Gvk GkvH gGvk 1Gvk >Gvk v1GHk >kgvG GQvk vk+GQ ZGvk ZvkgG lv", -"G p>lG ZvlG ylG 9kF k&F kF9B 9Fak 1k9F :kF 91kFB ak:F 9MF 9FM& 9FTk 9FaM l9", -"F l:F 9TlF sFl: k(9F 9F+k 9k(FB akF9+ 91k(F +k:F 1k(9FB :+akF M(9F 9F+M 9Tk", -"(F 9+TkF 9(lF :+lF l9T(F ls:+F 9Gk Gk& Gk9H Gk9a 91Gk :Gk 9G1Hk Ga:k 9GM G&", -"9M GT9M Ga9M lG9 l:G 9GlH s:lG Gk9d +k9G 9GHdk 9Ggk 9G1dk +G:k 1GH9dk :Ggk ", -"GM9d +G9M 9GTdk 9GgM 9Gld :Gl+ lG9Td lGg: kF92 &Fk2 9kF2B akF92 9F5k 5k:F 9", -"5kFB :5akF MF92 k&FM2 9TkF2 9aMF2 95lF :5lF l95TF ls:5F 9Fk; kF;& k;F9B ak;", -"9F k;F95 :k>F 95Fk;B :>akF 9FM; k;&MF 9T;kF aM;9F 9;lF >Fl: l;9TF l>s:F 92G", -"k G2k& 9GHk2 9Gak2 Gk95 G5:k 9G5Hk :GH5k 92GM 9GM&2 9GTk2 9GaM2 9Gl5 l5:G l", -"G9H5 lsG:5 Gk9; k;G& 9G;Hk g9Gk; 9G5dk :G>k G5k9H; g:>Gk GM9; k;&GM 9GTk; g", -"9MG; 9Gl; :>lG lG;9H l>Gg: kF9N &FkN 9kFNB akF9N 91kFN kF:N 1kF9NB :akFN 9F", -"Qk QFk& 9QTkF 9QakF 9QlF lF:Q l9QTF :QFls 9k(FN k&F+N k(F9NB 9+FakN 1k(9FN ", -":+kFN 1k9(NBF akF:+N 9Qk(F 9+QkF Qk(9TF akF9+Q l9Q(F :Q+lF 9QTl(F ls+:QF Gk", -"9W WkG& 9GHWk 9GaWk 9G1Wk Gk:W 1GH9Wk :GHWk GQ9M QkG& 9GZk GkZ& 9GlW :GlW Z", -"9lG lGZ: 9GWdk dk&GW GkH9Wd g9GWk 1GW9dk :G+Wk 91GkHWd g:GWk 9GQdk dk&GQ Z9", -"Gdk Zk&gG lG9Qd :GQl+ lZ9Gd glZ:G 9Fkm kFm& kmF9B akm9F kmF95 km:F 95FkmB :", -"makF 9FMm km&QF 9TmkF aMm9F lFp9 lF:p p9lTF :plsF km;9F km&+F 9mFk;B akF9+m", -" 95;kmF :>mkF km1;9FB >ka:mF 9Q;kF k;&QF kmF9T; akF9Q; l;p9F l>p:F p9Tl;F :", -"psl>F Gk9m kmG& 9GmHk akm9G 9G5Wk Gk:m G5k9Hm :GmHk GM9m km&GQ Z9Gkm Zk&Gm ", -"p9lG lG:p Zp9lG :pGlZ 9Gvk Gkv& v9GHk gv9Gk v91Gk vk:G 9G5vkH :vGgk 9GvM v9", -"M+G Zv9Gk ZvkG& v9lG lG:v lvZ9G l:yG Ik Ik! DkI aIk 1UI 8Ik Dk1I Ua1I IkM I", -"!kM VIk aIVk lI lI8 lIV lsI Ik( +Ik D(Ik Dk+I 1(Ik U+1I Ik(1D 1U+aI kMI( Ik", -"+M IkV( +IVk lI( l+I VIl( sIl+ UGk U!Gk Jk Jka 1UG U81G J1U J8k IkGM IkMG! ", -"JkV VaJk lGU UGl8 lJ lJs Idk +kUG Jkd gJk UG1d U+1G 1UJd J1gU dkIM Idk+M Vd", -"Jk JkgV lId U+lG lJd glJ Ik2 I!k2 I2Dk I2ak 5Ik 8I5k Dk5I aI5k kMI2 IkM!2 I", -"kV2 V2aIk lI5 5Il8 V5lI l5sI Ik; I;+k IkD; Ika; U;1I >kI Ik;1D Dk>I k;IM Ik", -";+M IkV; V+Ik; lI; l>I V;lI lIV> U2Gk Ik2G! Jk2 akJ2 U51G 1UG58 J5k 5aJk Ik", -"MG2 Gk2IM! V2Jk JkVa2 UGl5 lGU58 lJ5 J5ls GkU; Idk+; Jk; J;gk UG1; 1U>G 1UJ", -"; J>k IdkM; +GkIM; V;Jk gVJk; UGl; >UlG lJ; J>l IkN I!kN DNIk aNIk 1NIk IN8", -"k IkN1D 1UaIN QIk Q!Ik QIVk aIQk lIQ Q8lI VQlI lQsI k(IN +NIk Ik(DN +DkIN I", -"k(1N 1U+IN 1D(IkN akN1+I Q(Ik QI+k VQIk( V+QIk QIl( +QlI VlQI( lsI+Q WIk W!", -"Ik JkW WaJk UG1W 8IWk 1UJW W8Jk GkUQ UGQk! ZJk ZaJk lWI W8lI lJZ lZsJ IdWk ", -"WI+k WkJd gWJk Idk1W IdkW8 J1UWd gJ1UW IdQk Idk+Q ZdJk ZJgk WIld +WlI ZJld ", -"gZlJ Ikm I!km IkDm Ikam Um1I Ik8m Ikm1D akm1I ImQk IkmQ! IkVm VmaIk lIp l8p", -"I lIVp splI kmI; Ik+m IkmD; akm+I Ikm1; Ik>m 1DmIk; >kDIm IkQ; Ikm+Q VmIk; ", -"V+mIk pIl; p>lI VplI; V>lpI GkUm IkmW! Jkm akJm UG1m IkmG8 1UJm 8kJm IkmGQ ", -"Ik!GMm JmZk ZJkam pUlG lGpU8 Jpl lsJp vIk +Ivk Jvk gkJv 1UvI vI>k v1Jk >kJv", -" QIvk vIk+Q ZkJv VvJgk lvI v>lI lvJ ylJ tI tI& tDI tcI t1I t:I 1DtI :Itc tI", -"M IMt& VtI tIVc ltI l:I VtlI uI tI( t+I DIt( c+tI 1It( :It+ t1DI( t:c+I IMt", -"( +ItM VIt( tIV+ tIl( t+lI ltVI( u+I tG tG& tJ tJc tG1 t:G tJ1 :Jt tGM GMt&", -" tJV VJtc ltG t:lG lJt uJ tGd t+G tJd gtJ 1Gtd :Gt+ J1td :Jgt GMtd +GtM VJt", -"d tJgV tGld t+lG ldtJ uJg tI2 I&t2 DIt2 c2tI t5I :It5 5DtI tIc5 IMt2 IM&t2 ", -"tIV2 tcVI2 t5lI l5:I tIV5 u5I t;I +It; D;tI tIc; 1It; t>I t5DI; >Itc IMt; t", -"+IM; tIV; tc;VI t;lI lIt> t5VI; u>I tG2 G&t2 tJ2 c2tJ tG5 :Gt5 tJ5 t5:J GMt", -"2 tGM&2 V2tJ tJVc2 t5lG t:Gl5 t5lJ uJ5 tG; +Gt; tJ; t;gJ 1Gt; t>G J1t; t>J ", -"GMt; t+GM; VJt; tJ;gV tGl; lGt> l;tJ uJ> tIN I&tN DItN cItN 1ItN tN:I t1DIN", -" t:cIN tQI QIt& VQtI tIcQ tQlI :QlI tQVlI uQI I(tN +ItN tDI(N tc+IN t1I(N t", -":+IN 1DIt(N :cIt+N QIt( +QtI tQVI( tcQ+I tQIl( t:Q+I Vl(tQI +QuI tGW G&tW t", -"JW cJtW 1GtW :GtW J1tW tW:J tGQ GQt& tZJ ZctJ tGlW :GtQ lJtZ uZJ WItd +GtW ", -"JWtd tWgJ tG1Wd t:G+W tJ1Wd gtJ:W GQtd +GtQ ZJtd gZtJ tGQld t:G+Q lJZtd gZu", -"J tmI Imt& DmtI tIcm 1Itm :Itm t5DIm t:mcI QItm tQIm& tIVm tcQIm tpI lI:p p", -"IVt upI Imt; +Itm tmDI; tcm+I t5Im; >Itm 1Dmt;I t>cIm QIt; t+QIm tQ;VI tcQI", -"; pIt; pIt> tpVI; p>uI tGm Gmt& tJm cJtm 1Gtm :Gtm J1tm tm:J GQtm tGQm& ZJt", -"m tJmZc tpG tG:p tpJ uJp tvG vIt+ tvJ tJcv v1tG tG:v t5Jv :Jtv vItQ tv+GQ t", -"JVv cvVtJ lGtv lI:v Jptv yuJ e e! eB ae e. 8e e.B 8ea eK eK! Te Tea ej 8ej ", -"Tej se e* +e *Be +ea e*. +e8 e.*B ae8* e*K +eK Te* +Te ej* +ej ejT* se+ Ge ", -"Ge! He Gae Ge. G8e He. H8e GeK eKG! GTe TeGa Gje 8eGj Hej sGe f f+ fH gf f.", -" f8 fH. gf8 fK f+K fT gfT fj f8j fTj sf e2 e2! e2B ae2 5e 5e8 5eB 5ae e2K 2", -"Ke! Te2 T2ae 5ej 58ej 5Te se5 e; +e; e;B ae; 5e; >e *B5e >ea e;K +Ke; Te; T", -";+e e;j >ej Te5* >es Ge2 e2G! He2 G2ae G5e 5eG8 H5e 5aHe e2GK Ge2!K G2Te ae", -"2GT 5eGj G58ej 5THe G5se f; f+; fH; gf; f5 f> f5H f>g f;K +;fK fT; g;fT f5j", -" f>j f5T sf> eN eN! eNB aeN eN. 8eN .BeN aN8e Qe Qe! QeT Qae Qej Q8e QTej s", -"eQ e*N +eN eN*B +Nae *Ne. +N8e *BeN. aeN8* Qe* +Qe TeQ* Qa+e ejQ* Q8+e ej*Q", -"T +Qse We We! HeW Wae We. W8e H.We W8He GQe Q!We Ze Zea Wej Q8We Zej sZe fW", -" f+W fHW gfW fW. f8W HWf. gWf8 fQ fQ+ Zf Zfg fQj fQ8 Zfj sfZ em em! emB aem", -" 5em 8em 5Bem ae8m Qem Q!em Tem aeTm pe pe8 peT spe em; +em *Bem ae+m em5* ", -">em em;5B ae>m Qe; Qe+m TeQ; Te+m pe; >ep Tep* sp>e Gme W!em Hem aeGm 5We W", -"85e 5WHe Wa5e QeGm em!GQ Zem aeZm pGe G8pe Zpe Zpse fv fv+ fvH gfv fv5 f>v ", -"vHf5 gvf> fvQ v+fQ Zfv gvZf fp fp> fpZ yf ,e e& ,eB ,ae ,e. ,8e e.,B 8e,a ,", -"eK e&K ,Te Te& ,je e&j Te,j se& ,e* -e ,e*B -ae e*,. -8e *Be,. 8e-a e*,K -e", -"K ,eT* -Te ,e*j -je ej*,T s-e ,G ,G& ,GH ,Ga ,G. ,G8 ,.He G8,H ,GK ,KG& ,GT", -" GT,a ,Gj G8,j GT,j sG, f, f- fH, gf- f,. f-8 ,Hf. f8g- f,K f-K fT, f-T fj,", -" f-j ,Hfj sf- ,e2 e&2 e2,B ,2ae ,5e 5e& ,B5e 5e,a e2,K &2eK ,2Te T2e& 5e,j ", -"ej5& 5e,T ,5se ,;e -e; ,Be; ae-; 5e,; >e- e;B,5 -a>e ,Ke; e;-K Te,; Te-; e;", -",j -j>e e;j,T >es- ,G2 ,2G& ,2He ,2Ga ,G5 G5,8 G5,H G5,a G2,K e&2GK ,2GT ,G", -"T&2 G5,j e&jG5 G5,T ,Gs5 f;, f-; ,Hf; g;f- f5, f>- ,Hf5 g-f> ,;fK fK-; ,Tf;", -" f;-T ,5fj ->fj ,5fT f>s- ,eN e&N eN,B ,Nae eN,. ,N8e ,eN.B aeN,8 ,Qe Qe& Q", -"e,T Qe,a Qe,j Qe,8 ,QTej ,Qse e*,N -eN *Be,N ae-N ,e*N. 8e-N ,eN*B. -8aeN ,", -"eQ* -Qe ,QTe* Qa-e ej*,Q Q8-e ,QTej* -Qse ,GW We& He,W Ga,W ,.We G8,W ,GHW.", -" ,G8Wa ,GQ G&,Q Ze, Ze& GQ,j GQ,8 ,GZj Zes, fW, f-W ,HfW -Wgf ,Wf. -Wf8 fHW", -",. f-Wg8 fQ, f-Q Zf, Z-f ,Wfj -Wfj fjZ, Z-sf ,me em& ,Bem ae,m 5e,m 8e,m em", -"B,5 aem,5 Qe,m emQ& Te,m emT& pe, pe& ,Tpe pes, em,; -me em;,B ae-m em;,5 -", -"m>e ,5em*B >e-am Qe,; Qe-m ,Q;Te Te-m ,;pe -pe peT,; se-p ,Gm G&,m Gm,H Ga,", -"m G5,W G8,m ,G5Hm em&H5 GQ,m em&GQ ,GZm emZ& pG, ,Gp& pGZ, pGs, fv, -vf fHv", -", gf-v v,f5 -vf> fvH,5 f>g-v v,fQ fQ-v fvZ, -vZf fp, fp- Z,fp yf- Ie Ie! De", -" Dea Ie. 8Ie De. D8e IeK I!eK DeT aITe Ije Ij8e Dej sIe I* +Ie De* +De I*. ", -"8I* D.I* D8+e I*K +KI* TI* De+T I*j I*+j I*Dj sI* GIe IeG! Je Jae IeG. GI8e", -" Je. J8e IeGK GIe!K JTe TeJa GIej IjeG8 Jje sJe fI f+I Jf gJf fI. f8I Jf. J", -"f8 fIK +IfK JfT fTgJ fjI +Ifj Jfj sfJ Ie2 I!e2 De2 I2ae 5Ie 8I5e 5De D85e e", -"2IK Ie2!K I2Te ae2TI Ij5e Ije58 De5T 5Dse I;e I;+e De; D;+e 5I* >eI De5* >e", -"D IKe; I;e+K TeD; ae;TI Ij5* I*>j TI5* sI>e IeG2 GIe!2 Je2 aeJ2 GI5e G58Ie ", -"J5e 5aJe GIe2K Ie2GK! TeJ2 JTae2 IjeG5 G58Ije 5TJe J5se fI; +If; Jf; J;gf f", -"5I f>I Jf5 J>f I;fK f+I;K fTJ; JfTg; 5Ifj >Ifj f5Jj J>sf IeN I!eN DeN DNae ", -"eNI. IN8e eND. DN8e QIe IeQ! QDe DeQa IjQe 8IQe DjQe QDse I*N +NI* DNI* +ND", -"e *NI. IN8* I*ND. +De8N QI* QI+e DeQ* QD+e IjQ* 8IQ* I*jQD QIs* WIe IeW! JW", -"e WaJe IeW. 8IWe WeJ. W8Je QIWe GQIe! ZJe JaZe IjWe GQ8Ie JjZe ZJse fWI +Wf", -"I JfW gWJf WIf. W8fI fWJ. JWf8 fQI +QfI ZfJ gJZf WIfj Q8fI JjZf ZfsJ Ime I!", -"em Dem aeDm Im5e Im8e Dm5e 8eDm ImQe ImeQ! DmQe aemQD pIe 8Ipe pDe pDse Im*", -" Im+e ImD* De+m Im5* Im>e Im*5D De>m ImQ* Im*+Q DeQ; ae;QD pI* pI>e Dep* pD", -">e ImWe ImeW! Jme aeJm WI5e G8mIe 5WJe 8eJm ImeGQ GQIem! JmZe ZJaem WIpe pG", -"8Ie Jpe seJp fvI f+vI Jvf gfJv vIf5 vIf> fvJ5 f>Jv vIfQ fv+QI JvZf ZfJgv fp", -"I pIf> Jpf yJf h h& hD hc h. h8 hD. hc8 hK h&K hT hcT hj h8j hTj hs h* h- h", -"D* hc- h*. h-8 D*h. c-h8 h*K h-K hT* h-T hj* h-j D*hj hs- hG hG& hJ hJc hG.", -" h8G hJ. hJ8 hGK G&hK hJT cJhT hjG G8hj hJj hsJ hf hf- hJf i hf. hf8 h.Jf i", -"8 hfK hKf- hfT iT hfj f-hj Jfhj is h2 h&2 hD2 hc2 h5 h58 h5D hc5 h2K &2hK h", -"T2 c2hT h5j 5&hj h5T hs5 h; h-; h;D hc; h5; h> 5Dh; h>c h;K -;hK hT; c;hT h", -";j h>j 5Th; hs> hG2 G&h2 hJ2 h2cJ h5G G5h8 hJ5 cJh5 G2hK hG&2K JTh2 cJTh2 G", -"5hj h5G&j J5hT h5sJ hf; f-h; hJ; i; hf5 h>f Jfh5 i> f;hK f-;hK J;hT iT; f5h", -"j hjf> J;hj is> hN h&N hDN hcN hN. h8N DNh. c8hN hQ hQ& hQD hcQ hQj hQ8 QDh", -"j hsQ h*N h-N D*hN hNc- *Nh. -8hN hD*N. c-8hN hQ* h-Q QDh* c-hQ Q*hj -Qh8 h", -"QD*j hQs- hW hW& hJW hcW hW. hW8 JWh. cWh8 hWQ GQh& hZ hZc hWj GQh8 hZj hZs", -" hfW h-W JfhW iW fWh. f8hW JfWh. iW8 hfQ f-hQ hZf iZ fQhj fQh8 hjZf iZs hm ", -"hm& hmD hcm h5m h8m 5Dhm c5hm hQm Q&hm hTm cQhm hp hp8 hpD hps hm; h-m Dmh;", -" c-hm 5*hm h>m h5Dm* hmc> hQ; -Qhm QDh; cQh; hp; hp- pDh; cph> hWm Gmh& hJm", -" cJhm h5W G8hm J5hW c5hW GQhm hWQm& hZm hmZc hpG pGh8 hZp cphZ hv hv- hvJ i", -"v hv5 hv> h5Jv iv> hvQ hQ-v hZv iZv hpf fph> Jphv yi e0 e0! e0B ae0 1e 1e8 ", -"1eB 1ae e0K !Ke0 Te0 T0ae 1ej 18ej 1Te se1 e*0 +e0 e0*B +0ae 1e* 1+e *B1e +", -"e1a *0eK e0+K e*T0 +0Te ej1* +j1e Te1* 1+se Ge0 e0G! He0 G0ae 1Ge G81e 1He ", -"Ga1e e0GK Ge0!K G0Te ae0GT Gj1e 1G8ej GT1e 1Gse f0 f+0 fH0 gf0 f1 f1+ f1H g", -"f1 f0K +0fK fT0 g0fT f1j 1+fj f1T sf1 e02 !0e2 2Be0 e2a0 1e5 158e 1B5e 5a1e", -" 2Ke0 e02!K e0T2 ae0T2 15ej 1e58j 5T1e 1es5 e;0 +0e; ;0eB a0e; 1e; >e1 1Be;", -" 1a>e ;0eK e;0+K T0e; ae;T0 ej1; 1e>j Te1; s1>e e0G2 Ge0!2 e0H2 ae0G2 G51e ", -"1G58e H51e 1Ga5e Ge02K e02GK! GTe02 GT0ae2 1G5ej G581ej 1GT5e se1G5 f;0 +;f", -"0 H;f0 f;g0 f15 f>1 1Hf5 g1f> ;0fK f+;0K T;f0 fT;g0 1;fj >jf1 1Tf5 f1s> e0N", -" !0eN 0BeN e0aN 1eN 1N8e eN1B 1Nae Qe0 e0Q! Q0Te Q0ae 1Qe Q81e Qe1T 1Qse *0", -"eN e0+N *Be0N ae0+N e*1N 1N+e 1e*NB 1+eaN e*Q0 +0Qe QeT*0 +QeT0 Qe1* +Q1e 1", -"QeT* se1+Q We0 e0W! H0We W0ae 1We W81e He1W Wa1e G0Qe GQe!0 Ze0 aeZ0 GQ1e 1", -"GQ8e Z1e Z1se fW0 +Wf0 HWf0 fWg0 f1W 1+fW 1HfW gWf1 fQ0 +Qf0 Zf0 g0Zf f1Q 1", -"+fQ Zf1 g1Zf em0 e!m0 m0eB a0em 1em 8e1m 1Bem ae1m Q0em em0Q! T0em aemQ0 pe", -"1 1ep8 1Tpe s1pe e0m* +0em em;0B aem+0 em1; 1e>m 1em*B >e1am Q0e; +Qem0 Qe;", -"T0 ae;Q0 1ep* p1>e pe1T; >eps1 G0em em0W! H0em aemG0 Gm1e 1Gm8e He1m aem1G ", -"em0GQ GQ0em! emZ0 Zeam0 1Gpe pG81e peZ1 Zpes1 fv0 v+f0 vHf0 g0fv fv1 v>f1 f", -"Hv1 fvg1 vQf0 fv+Q0 Z0fv Zfgv0 fp1 p>f1 Z1fp yf1 9e 9e& 9eB 9ae ,1e :e ,B1e", -" :ea 9eK 9Ke& 9Te Te9a 9ej :ej 1T9e s:e 9e* -9e *B9e 9a-e 1e9* :-e ,1e*B -a", -":e e*9K 9e-K Te9* 9T-e ej9* -j:e ,1Te* :-se ,G9 G&9e 9He 9G,a ,1G :Ge 1G,H ", -":He ,K9G e&K9G 9G,T ,GT9a 9G,j ,G:j 1G,T :Gse f9 f-9 f9H gf9 f91 :f ,1fH :f", -"g f9K fK-9 f9T fTg9 f9j :fj ,1fT sf: 9e2 92e& e29B 92ae 95e :e5 9B5e 5a:e e", -"29K e&29K 92Te 9Te&2 5e9j 5e:j 5T9e s5:e 9e; 9e-; 9Be; ae9; 1e,; >e: ,1;eB ", -":a>e 9Ke; -9e;K Te9; -T9e; e;9j >j:e e;j9T s:>e ,29G e&29G 92He ,Ga92 9G,5 ", -",G:5 H59e H5:e ,G92K 9G2e&K ,GT92 ae29GT ,1G5j :G5,j ,1G5T :Hes5 f9; -9f; 9", -"Hf; g;f9 f95 :f> 9Hf5 f>g: 9;fK f-9;K 9Tf; f-T9; 95fj fj:> 95fT s:f> 9eN 9N", -"e& eN9B 9Nae ,N1e :eN ,1eNB ae:N 9Qe Q&9e Qe9T Qa9e 1Q9e :Qe ,1QTe :Qse e*9", -"N 9e-N 9e*NB -9aeN ,1e*N -e:N 1eN9*B :-aeN Qe9* 9Q-e 9QeT* -Q9Te ,1Qe* -Q:e", -" 1Qe9T* s-:Qe 9We W&9e He9W Wa9e 1G,W :We ,1GHW He:W 9G,Q ,GQ9& Z9e 9aZe 1G", -",Q ,G:Q ,1Ze Z:e f9W -Wf9 9HfW gWf9 ,1fW :fW f91HW :Wgf f9Q -Qf9 Zf9 g9Zf ,", -"1fQ :fQ f9Z1 Z:f 9em e&9m 9Bem ae9m 1e,m :em ,1meB ae:m Qe9m em&9Q Te9m aem", -"9Q p9e :pe 9Tpe se:p em9; 9e-m 9em*B -m9ae ,1me; :m>e emB,1; :-mae Qe9; -Q9", -"em 9QeT; -Tm9e 9ep* >e:p p9eT; -ps:e 9G,m em&9G He9m aem9G 1G,m ,G:m ,1GHm ", -"He:m ,GQ9m 9GQem& 9eZm Z9eam ,1pG pG:e p9Ze Ze:p fv9 f9-v fHv9 fvg9 v9f1 :f", -"v fv91H gf:v v9fQ -vf9Q fvZ9 Zf9-v fp9 :fp Z9fp y:f Ie0 I!e0 De0 D0ae 1Ie 8", -"I1e 1De D81e e0IK Ie0!K D0Te ae0TI Ij1e Ije18 De1T 1Dse I*0 +0I* D0I* +0De ", -"1I* +I1e De1* +D1e *0IK I*0+K T0I* +DeT0 Ij1* I*j1+ TI1* 1Is* IeG0 GIe!0 Je", -"0 aeJ0 GI1e 1G8Ie J1e 1aJe GIe0K Ie0GK! TeJ0 JTae0 Ije1G 1G8Ije 1TJe J1se f", -"I0 +If0 Jf0 g0Jf f1I 1+fI Jf1 Jfg1 I0fK f+I0K J0fT JfTg0 1Ifj f1+Ij f1Jj J1", -"sf e0I2 Ie0!2 e0D2 ae0I2 5I1e 1I58e 5D1e 1De5a Ie02K e02IK! DeT02 TI0ae2 Ij", -"e15 5I81ej 1De5T sI15e I0e; I;e+0 D0e; ae;D0 5I1* 1I>e De1; 1D>e I;e0K +I0e", -";K De;T0 ae0TI; I;j1e >I1ej e;j1D sI*>1 GIe02 Ie0G2! e0J2 Jae02 1G5Ie G581I", -"e 1eJ5 J158e Ie0G2K !0I2GeK JTe02 ae0JT2 1G5Ije 8eGj1I5 J15Te sJ15e I;f0 f+", -"I;0 f;J0 Jf;g0 1If5 >If1 f1J5 J1f> fI;0K I;0f+K JfT;0 fT;gJ0 f15Ij f>1Ij Jf", -"15T J>sf1 e0IN Ie0!N e0DN ae0DN Ie1N 1I8eN 1NDe 1DeaN IeQ0 QIe!0 Q0De QDea0", -" QI1e 1QI8e QD1e sI1Qe *0IN I*0+N I*0DN +De0N 1NI* 1+IeN 1De*N 1+DeN Q0I* +", -"QIe0 QDe*0 +QDe0 QI1* 1+QI* 1QDI* sI*1Q IeW0 WIe!0 WeJ0 JWae0 WI1e 1WI8e 1W", -"Je J1W8e GQIe0 QI0We! JeZ0 ZJae0 1GQIe W8I1Qe J1Ze sJZ1e WIf0 f+WI0 fWJ0 Jf", -"Wg0 1WfI f1+WI JWf1 Jf1gW QIf0 fQ+I0 Z0Jf ZfJg0 1QfI f1Q+I JfZ1 Zf1sJ I0em ", -"Ime!0 D0em aemD0 Im1e 1Im8e De1m aem1D ImeQ0 QI0em! QDem0 ae0TIm 1Ipe pI81e", -" 1Dpe pDes1 I0m* Im*+0 Im*D0 am*I0 Im1* >I1em Im*1D >eD1m Im*Q0 Im0+Qe Im*T", -"0 ae0QD; 1Ip* >ep1I pDe1; sI*p1 ImeG0 WI0em! emJ0 Jmae0 1GmIe W8I1em 1eJm J", -"1m8e GQIem0 ImQeW!0 ZJem0 JmaZe0 pG1Ie 1WIpe8 peJ1 Jps1e f0vI fv+I0 J0fv Jv", -"gf0 vIf1 f>v1I fvJ1 J>fv1 fvQI0 vI+fQ0 ZfJv0 JvgZf0 pIf1 fp>1I J1fp Jfy1 h9", -" h9& h9D hc9 h1 h: h1D h:c h9K 9&hK hT9 c9hT h1j h:j h1T hs: h9* h-9 9Dh* h", -"9c- h1* h:- 1Dh* :ch- 9*hK -9hK 9Th* h9-T 9*hj :-hj 1Th* s-h: h9G 9Gh& hJ9 ", -"J9hc h1G h:G hJ1 :Jh 9GhK h9G&K J9hT cJ9hT 9Ghj :Ghj J9hj :Jhs hf9 f9h- Jf9", -" i9 hf1 :fh Jfh1 i: hKf9 f-9hK f9hT i9T f9hj hj:f f9Jj is: h92 9&h2 9Dh2 c2", -"h9 h15 h:5 95hD :ch5 92hK h9&2K 9Th2 hc9T2 95hj :5hj 95hT s:h5 h;9 -9h; 9Dh", -"; h9c; h1; h>: 1Dh; c>h: 9;hK h-9;K 9Th; hc;9T 9;hj :>hj 1Th; s:h> 9Gh2 h9G", -"&2 h2J9 cJ9h2 9Gh5 :Gh5 J9h5 h5:J h9G2K 9G&h2K J9Th2 hcTJ92 h1G5j h:G5j J95", -"hT hsJ:5 f9h; f-9h; J9h; i9; f9h5 :fh> J1h; i:> f9;hK h-;f9K Jf9T; 9Ti; f95", -"hj h>:fj Jf95T s:i> h9N 9&hN 9DhN c9hN h1N h:N 1DhN hN:c hQ9 9Qh& 9QhT h9cQ", -" h1Q h:Q 1QhT s:hQ 9*hN -9hN h9D*N c-9hN 1*hN hN:- h1D*N h:c-N 9Qh* h9-Q hQ", -"9D* c-Qh9 1Qh* :-hQ h1QD* h:Qs- hW9 9Wh& J9hW h9cW h1W h:W J1hW hW:J 9GhQ h", -"W9Q& hZ9 Z9hc 9Whj :GhQ hZ1 hZ: f9hW h9-W JWf9 i9W f1hW hW:f Jf91W i:W f9hQ", -" f-Qh9 Z9hf iZ9 f1hQ hQ:f h1Zf iZ: hm9 9mh& 9Dhm h9cm h1m h:m 1Dhm :chm 9Qh", -"m hQ9m& 9Thm hcQ9m hp9 hp: p9hT h:cp 9mh; h9-m hm9D; c-mh9 1mh; :-hm h1mD; ", -"h:mc> 9Qh; h-Q9m hQ;9D cQ;h9 p9h; h:-p hp9D; cp-h: 9Ghm hW9m& J9hm cJmh9 95", -"hW :Ghm J1hm hm:J hW9Qm 9GQhm& Z9hm hZc9m p9hW hW:p h1Jp Z:hp hv9 v9h- J9hv", -" iv9 hv1 hv: h1Jv i:v v9hQ hv-9Q Z9hv Zvi9 h1fp :fhp Zvh1 yi: eL eL! eLB ae", -"L eL. 8eL .BeL 8Lae Me Me! TeM aMe Mej 8Me TMej seM e*L +eL eL*B +Lae *Le. ", -"+L8e *BeL. aeL8* Me* +Me MeT* Te+M ejM* 8M+e Me*Tj +Mse GeL eLG! HeL GLae e", -"LG. GL8e eLH. HL8e GMe G!Me HMe aMHe MeGj 8eGM MeHj GMse fL f+L fHL gfL fL.", -" f8L HLf. gLf8 fM fM+ fTM gfM fMj f8M HMfj sfM eL2 !Le2 2BeL e2aL 5eL 5L8e ", -"eL5B 5Lae Me2 M!e2 T2Me M2ae 5Me 8M5e Te5M 5Mse e;L +Le; ;LeB aLe; 5Le; >eL", -" e;L5B ae>L Me; M;+e MeT; Mea; Me5* >Me Me;5T se>M eLG2 GeL!2 eLH2 aeLG2 GL", -"5e G58eL HL5e G5aeL G2Me Me2G! H2Me aMeG2 5eGM G5M8e 5MHe se5GM f;L +;fL H;", -"fL f;gL f5L f>L H5fL >Lgf fM; +Mf; HMf; g;fM f5M f>M H5fM >Msf eLN !LeN NBe", -"L eLaN N.eL eN8L eLN.B aeL8N QeM Q!Me QTMe aMQe QMej 8MQe MejQT QesM *LeN e", -"L+N *BeLN aeL+N e*LN. +e8LN eLN*B. 8eLa*N MeQ* Qe+M Me*QT aMe+Q Me*Qj +Qe8M", -" QeTM*j se+QM WeL eLW! HLWe WLae eLW. WL8e HeWL. H8eWL WMe W!Me ZeM aMZe Me", -"Wj 8MWe MeZj sMZe fWL +WfL HWfL fWgL WLf. W8fL fHWL. f8WgL fQM +WfM ZfM gMZ", -"f WMfj W8fM ZMfj fMsZ emL e!mL mLeB aLem 5Lem 8Lem emL5B aem5L Mem M!em MeT", -"m Meam peM 8Mpe TepM sMpe eLm* +Lem em;LB aem+L em;5L em>L 5eLm*B >eamL MeQ", -"; Me+m MemT; aMe+m Mep* pe>M peTM; >Mesp GLem emLW! HLem aemGL 5LWe G8meL H", -"5eWL H8emL MeGm MemW! MeZm ZeaMm GMpe pG8Me ZMpe ZpesM fvL v+fL vHfL gLfv v", -"5fL >Lfv fvH5L f>gvL fvM f+vM fMZv fvgM fpM >Mfp fMZp yfM ,eL e&L eL,B ,Lae", -" eL,. ,L8e ,eL.B aeL,8 ,Me Me& Te,M ae,M Me,j 8e,M Mej,T ,Mse e*,L -eL *Be,", -"L ae-L ,e*L. 8e-L ,eL*B. -8aeL ,eM* -Me Me*,T Te-M Me*,j 8M-e ,TMej* -Mse ,", -"GL ,LG& ,LHe ,LGa GL,. ,LG8 ,GHL. ,G8HL ,GM G&,M GT,M Ga,M GM,j G8,M ,GTMj ", -",GsM f,L f-L ,HfL gLf- ,Lf. -8fL fH,L. f-8gL fM, f-M ,HfM f-gM ,Mfj -Mf8 fT", -"M,j fMs- eL,2 &Le2 ,eL2B aeL,2 ,L5e 5Le& ,5eLB ,5aeL ,2Me M2e& Me2,T aMe,2 ", -"5e,M Me5& ,5TMe se5,M ,Le; e;-L e;L,B ae;-L e;L,5 -e>L ,5Le;B >e-aL Me,; Me", -"-; Me;,T -TMe; Me;,5 -M>e ,5TMe; s->Me GL,2 e&LG2 ,GHL2 ,GaL2 ,LG5 ,G58L ,G", -"5HL ,G5aL ,2GM Me&G2 ,GTM2 Me&H2 G5,M Me&G5 ,G5HM sG,5M ,;fL -;fL fH;,L f-;", -"gL ,5fL >Lf- f5H,L f>g-L ,Mf; f;-M fTM,; f-TM; ,5fM f->M f5T,M f>Ms- eL,N &", -"LeN ,eLNB aeL,N ,eLN. e&L8N eLN,.B ,8LaeN Qe,M MeQ& ,QTMe aMe,Q Mej,Q Me&Q8", -" ,QTMej seM,Q ,e*LN eL-N ,eL*BN -aeLN e*L,N. -8eLN NB*L,e. aeL-8N Me*,Q Qe-", -"M ,QTMe* -QTMe ,QMej* -Q8Me QMej,T* s-QMe ,LWe WLe& ,GHWL ,GaWL ,GWL. ,G8WL", -" HeL,W. aeL,W8 GQ,M MeW& ,GZM MeZ& ,GQMj Me&W8 ZeM,j Ze&sM ,WfL fL-W fHW,L ", -"f-WgL fW,L. f-W8L ,HWfL. gf8-WL ,WfM -WfM fMZ, fMZ- fQM,j f-Q8M ZfM,j sfZ-M", -" ,Lem eLm& emL,B aem,L emL,5 em&5L ,5LemB aeL,8m Me,m emM& Mem,T aMe,m ,Mpe", -" Mep& peT,M pe&sM em;,L em-L ,mLe;B -maeL ,5em*L >e-mL 5m*B,eL -ma>eL Mem,;", -" Me-m ,TmMe; -TmMe peM,; pe-M Me;p,T -psMe ,LGm em&GL ,GmHL em&HL ,G5WL ,G8", -"mL emL,H5 aeL,5W GM,m MemG& ZeM,m Ze&Mm ,GpM pG&,M Zpe,M ZpeM& fLv, fL-v fv", -"H,L -vgfL fv5,L f>-vL v,Hf5L -vgf>L v,fM fM-v Zfv,M -vMZf p,fM fM-p fpZ,M f", -"-yM Ue Ue! UeD Uae Ue. U8e U.De D8Ue UeM U!Me Ve Vea Uej 8MUe Vej seV Ue* U", -"+e DeU* +DUe U.I* +eU8 I*.UD U+eD8 IM* +MUe Ve* V+e I*Uj +eUj I*Vj V+se UGe", -" GeU! JUe UaJe GeU. G8Ue UeJ. U8Je GMUe IM!Ge VJe JaVe GjUe UG8Me VeJj VJse", -" fU fU+ JfU gfU fU. fU8 J.fU fUJ8 fUM U+fM Vf Vfg fUj U+fj Vfj sfV Ue2 e2U!", -" U2De U2ae U5e 5eU8 5DUe 5aUe U2Me IM2e! Ve2 aeV2 5MUe U5e8M V5e V5se Ue; +", -"eU; DeU; aeU; 5IU* >eU U5eD; Ua>e MeU; IM;+e Ve; +eV; IM5* Ue>M 5IV* V>e Ge", -"U2 UGe!2 UeJ2 JUae2 G5Ue UG58e U5Je J5U8e IM2Ge UG2Me! JeV2 VJae2 UG5Me G5M", -"U8e VeJ5 seVJ5 fU; U+f; fUJ; g;fU fU5 f>U fUJ5 gUf> U;fM fU+M; Vf; V;gf U5f", -"M fU>M Vf5 Vf> UeN eNU! UNDe UNae eNU. UN8e UeDN. U8eDN UQe Q!Ue VeQ QaVe Q", -"eUj Q8Ue QeVj sQVe UNI* UN+e I*NUD U+eDN I*NU. U+e8N DeNU*. aeNU8* QIU* +QU", -"e QIV* +QVe IM*Qj IM*Q8 VeQ*j sI*VQ UWe U!We UWJe WaUe U.We W8Ue JUWe. J8UW", -"e GQUe UGQe! ZeV ZaVe WeUj UGQ8e ZjVe VZse fUW U+fW JWfU gWfU UWf. UWf8 JfU", -"W. Jf8UW fUQ U+fQ VfZ ZfgV UWfj UQf8 fjVZ sZVf Uem U!em DeUm aeUm 5eUm 8eUm", -" U5eDm aemU5 QeUm IMme! Vem aeVm pUe U8pe Vpe seVp ImU* +eUm Im*UD aemU+ Im", -"*U5 Ue>m 5DeUm* >eUDm QeU; IMm+e QeV; +eVm Uep* pU>e pIV* >eVp GmUe UGme! U", -"eJm JmUae 5WUe UG8em J5UWe J8mUe IMmWe Im!WMe VeJm ZeVam UGpe pUG8e ZeVp Jp", -"Vse fvU f+vU fUJv fvgU vUf5 v>fU JvfU5 J>fvU vUfQ fvU+Q Vfv gfVv fpU p>fU f", -"pV yVf hU hU& hUD hcU hU. h8U UDh. cUh8 hM hM& Vh Vhc hMj h8M Vhj hsV hU* h", -"-U U*hD -Uhc U*h. -Uh8 hUD*. c-Uh8 hM* h-M Vh* V-h U*hj -Uhj V*hj V-hs hUG ", -"UGh& hJU hUcJ UGh. UGh8 JUh. hUJ8 hMG GMh& VhJ cJVh UGhj G8hM JjVh VhsJ hfU", -" f-U fUhJ iU h.fU fUh8 JfUh. iU8 hfM f-hM Vfh iV fUhj f8hM hjVf iVs hU2 U&h", -"2 UDh2 c2hU h5U U5h8 U5hD hUc5 hM2 M&h2 Vh2 h2Vc h5M 5Mh8 Vh5 c5Vh h;U -Uh;", -" U;hD hUc; U5h; h>U h5UD; >Uhc hM; -Mh; Vh; h;V- U;hj h>M V5h; h>V UGh2 hUG", -"&2 JUh2 cJUh2 UGh5 h5UG8 hUJ5 cJ5hU GMh2 hMG&2 h2VJ VhJc2 G5hM h5MG8 J5Vh V", -"h5sJ fUh; f;-U hUJ; iU; fUh5 fUh> Jf5hU i>U fMh; f-UM; h;Vf iV; f5hM hf>M h", -"5Vf iV> hUN U&hN UDhN cUhN UNh. U8hN hUDN. hcU8N hQU UQh& VhQ cQVh UQhj UQh", -"8 VQhj VshQ U*hN hN-U hUD*N c-UhN hU*N. -U8hN U*DhN. hc8-UN UQh* -UhQ V*hQ ", -"hQV- hQU*j -UQh8 VhQ*j V-hsQ hWU UWh& JUhW hUcW UWh. UWh8 hJUW. hJ8UW hWM W", -"Mh& hZV VhZc UWhj W8hM VZhj sZVh fUhW -UhW JfUhW iUW fUWh. f-UW8 hJWfU. UWi", -"8 fUhQ -UfQ VfhZ iZV fUQhj f-UWj VfZhj sZiV hmU Umh& UmhD hUcm U5hm U8hm h5", -"UDm hc5Um hMm Mmh& Vhm cmVh hpU pUh8 hpV Vphs Umh; -Uhm hmUD; c-mhU h5Um* >", -"Uhm U5*hmD h>cUm UQh; -Mhm Vmh; hmV- pUh; >Mhp h;Vp V-hp UGhm hWUm& hUJm cJ", -"mhU U5hW h5WU8 hJ5UW c5WhU GMhm hWMm& JmVh VhmZc pUhW hpUG8 VphZ cpJVh hvU ", -"fU-v vUhJ ivU vUh5 vUh> hvJU5 v>iU hvM hM-v hvV iVv hMfp >Mhv Vfhp yiV ke k", -"e! keB ake 1ek 8ke 1Bke ak1e keM M!ke Tke akTe le le8 leT lse ke* +ke *Bke ", -"ak+e ke1* +k1e ke*1B ake1+ Mek* ke+M keT* Tk+e le* l+e Tel* sel+ Gke G!ke H", -"ke akHe Gk1e 8eGk Hk1e 8kHe keGM keMG! TkHe akeGT lGe G8le lHe sGle fk fk+ ", -"fkH gfk f1k f8k 1Hfk f1gk fkM +kfM fTk fTgk lf lf+ lfH glf ke2 k!e2 e2kB k2", -"ae 5ke 8k5e 5Bke ak5e k2Me keM!2 T2ke akeT2 le5 5el8 5Tle l5se ke; k;+e kBe", -"; kea; ke1; >ke ke;1B ak>e Mek; ke;+M keT; akeT; le; l>e Tel; >els G2ke ke2", -"G! H2ke akeG2 5eGk G5k8e 5kHe akeG5 keMG2 Gk2Me! GTke2 ak2HMe G5le lG58e H5", -"le lsG5e fk; +kf; Hkf; g;fk f5k f>k H5fk gf>k k;fM fk+M; Tkf; fTkg; lf5 lf>", -" f5lH l>sf keN k!eN eNkB aNke 1Nke kN8e keN1B ake1N Qke Q!ke TkQe akQe leQ ", -"Q8le QelT lQse e*kN +Nke ke*NB ake+N ke*1N 1+ekN 1eNk*B akN1+e keQ* Qk+e Qk", -"eT* ake+Q Qel* +Qle leQT* lse+Q Wke W!ke WkHe akWe Wk1e 8kWe 1HeWk ake1W Qk", -"We GQke! Zke akZe lWe W8le lZe sZle fkW +Wfk HkfW gWfk 1Wfk W8fk f1HWk f8kg", -"W fQk +Qfk Zfk gkZf lfW fQl+ lfZ Zfgl kem k!em kBem keam ke1m ke8m kem1B ak", -"e1m kmQe kemQ! keTm akeTm lep l8pe lTpe sple emk; ke+m kem*B ake+m kem1; ke", -">m keB1m* >keam keQ; kem+Q kemT; akeQ; pel; p>le lepT; l>esp keGm kemW! keH", -"m akeGm Wk5e kemG8 kem1H ake5W kemGQ ke!GMm keZm Zkeam pGle lGp8e Zple lZes", -"p fvk f+vk fHvk fvgk v1fk fv>k fv1Hk f>kgv vkfQ fvk+Q fvZk Zfkgv lfp l>fp Z", -"flv ylf ,ke ke& ,Bke ak9e 1e,k :ek keB,1 ak:e 9Me Mek& Tk9e aM9e le9 l:e ,T", -"le s:le ke9* -ke ke*,B ak-e ke*,1 -k:e ,1ek*B :-ake Me9* 9M-e ,Tke* Tk-e 9e", -"l* l-e le9T* les- ,Gk G&,k Gk,H Ga,k 1G,k ,G:k ,1GHk Hk:e 9G,M ke&GM GT,k a", -"Me9G lG, :Gle ,GlH sGl, f9k f-k ,Hfk f-gk ,1fk :fk f91Hk gk:f f9M -kfM ,Tfk", -" f9gM lf9 lf: f9lH sfl- ,2ke k2e& ke2,B ake,2 5k9e 5k:e ,5keB :e5ak 92Me ke", -"&M2 ,Tke2 aMe92 ,5le l5:e le95T lse:5 ke,; ke-; ke;,B -kae; ke;,1 :e>k keB,", -"1; >k-ae Me9; -kMe; ke;,T -Tke; ,;le >el- le;,T l>es- ,2Gk ke&G2 ,GkH2 ke&H", -"2 G5,k :G5,k ,G5Hk :He5k ,GkM2 ke2GM& ,GTk2 ak2,GT ,Gl5 l:G,5 lG,H5 :Hel5 ,", -"kf; f;-k f9Hk; f-kg; ,5fk >k:f f95Hk f>kg: 9Mf; f-kM; f9Tk; f-Tk; f9l; l>:f", -" lf9H5 glf:> ,Nke kNe& keN,B ake,N keN,1 ke:N ,1NkeB :eakN Qk9e keQ& ,QkTe ", -"ake,Q ,Qle :Qle le9QT :Qels ke*,N ke-N 9eNk*B -kaeN ,1ek*N :-keN ke1*,NB -k", -"a:eN ,Qke* Qk-e Qke9T* -QkTe le9Q* -Qle 9Qel*T l-sQe Gk,W keW& ,GkHW ake,W ", -",1GWk Wk:e 1He,Wk :HeWk GQ,k ke&GQ ,GZk keZ& ,GlW :Wle Z9le leZ: ,Wfk -Wfk ", -"f9HWk f-kgW f91Wk fk:W ,1HfkW :fgWk ,Qfk -Qfk f9Zk f-Zk f9lW lW:f l,Zf Z:lf", -" ke,m emk& kem,B ake,m kem,1 ke:m keB,1m :emak Me9m kemQ& kem,T aMe9m p9le ", -"le:p lep,T :pels kem,; ke-m keB9m* -kmae ,1mke; :-mke ke,m1;B :ea-km ke;,Q ", -"-Qkem ,Tmke; -Tkem lep,; le-p leTp9* l-pse Gk,m kemG& kem,H akm,G ,1Gkm :Gm", -",k ,1Hkem :Hekm Mem9G ,GQkm& Z9ekm Zkem& pGl, :pGle lZep9 Z:elp v9fk fk-v f", -"v9Hk -vkgf fv95k fk:v f1Hvk, :fvgk v9fM -vkfQ Zf9vk Z-kfv l,fp :flv fp9lZ l", -"fy: Uek U!ke Dke akUe 1Ue U81e Ue1D Ua1e keIM IkMe! Vek akVe lIe U8le leV s", -"Ile Ik* +kUe IkD* Dk+e Ue1* U+1e Ik*1D ak*1I k*IM Ik*+M IkV* +kVe lI* U+le ", -"Vel* sIl* GkUe Ik!Ge Jke akJe UG1e 1UG8e 1UJe 8kJe IkMGe UGkMe! VeJk JkVae ", -"UGle lGU8e lJe lesJ fUk U+fk Jfk Jfgk f1U 1Uf8 f1Jk f1gU IkfM fU+kM Vfk gkV", -"f lfU fUl+ lfJ Vfgl U2ke Ik2e! D2ke akeU2 U51e 1Ue58 Dk5e akeU5 IkMe2 ke2IM", -"! keV2 Veka2 U5le lI58e V5le seVl5 keU; Ik;+e keD; akeU; Ue1; 1U>e Ik*5D Dk", -">e Ik;Me +IkMe; keV; V+ek; Uel; lI>e Vel; leV> Ik2Ge UG2ke! keJ2 Jkae2 1UG5", -"e G5kU8e 5kJe J5k8e UGkMe2 IkGMe2! JkVe2 VeaJk2 lGU5e UG5le8 J5le lJs5e U;f", -"k fU+k; fkJ; Jfkg; 1Uf5 fU>k f5Jk Jf>k fUkM; Ik;fM+ V;fk Vfgk; fUl; lIf> l;", -"Vf J>lf UNke IkNe! DNke akeUN 1NUe 1Ue8N 1UeDN 1UaeN QkUe UQek! QkVe VeQak ", -"UQle lIQ8e lQVe seVlQ INk* Ik*+N Ik*DN ak*IN Ik*1N Ik*8N IkN1D* akN1I* IkQ*", -" Ik*+Q VeQk* V+eQk QIl* l+IQe lI*VQ sI*lQ WkUe UWek! WkJe JkWae UW1e 1UW8e ", -"J1UWe J8kWe UGQke Ik!WMe JkZe ZJkae UWle lWI8e ZJle lJZse UWfk fU+Wk JWfk J", -"fkgW 1UfW f1U+W Jf1UW Jf8Wk UQfk fUQ+k ZkVf VfZgk fUlW lfU+W ZflJ glJZf keU", -"m Ikme! keDm akeUm Ue1m Ikm8e kem1D aem1U IkmQe Ik!Mem keVm Vemak pUle lIp8", -"e leVp Vpels kmI* Ikm+e IkmD* akmI* Ikm1* >kIem 1Dekm* >kDem IkmQ* U+Qkem V", -"emk; V+ekm pIl* l>Ipe Vpel; V>elp IkmWe Im!Wke keJm Jkmae 1UGem UG8kem J1mU", -"e J8kem UGQkem ImQkWe! ZJkem ZkaVem lGpUe lG8pUe leJp Jplse vUfk fvU+k fvJk", -" Jvkgf v1fU f>Uv1 Jv1fU J>kfv fvUQk fQ+vIk fkVv Vfvgk lIfp fpUl> Jplf lfyJ ", -"ht ht& htD htc ht1 h:t t1hD t:hc htM tMh& Vht tcVh lh lh: lhV uh ht* t-h hD", -"t* hct- t*h1 t-h: t*1hD h:tc- t*hM hMt- t*Vh Vht- lh* l-h l*Vh uh- htG h&tG", -" tJh hctJ tGh1 tGh: h1tJ tJh: tGhM tGMh& VhtJ tJVhc lhG lGh: lJh uJh tf tf-", -" tfJ it tf1 tf: J1tf it: tfM fMt- tfV iVt lfh tfl- lJtf ui ht2 t&h2 tDh2 h2", -"tc ht5 t:h5 hDt5 tch5 tMh2 htM&2 h2Vt Vhtc2 lh5 h5l: t5Vh uh5 ht; h;t- hDt;", -" tch; t5h; h>t t5*hD htc> t;hM t-hM; t;Vh V-ht; lh; h>l l;Vh uh> h2tG tG&h2", -" h2tJ tJhc2 tGh5 t:Gh5 h5tJ tJ5h: tGMh2 hM&tG2 tJVh2 VhctJ2 h5lG lh:G5 h5lJ", -" hJu5 tf; f-t; h;tJ it; tf5 tf> Jft5 it> fMt; tf-M; t;Vf t;iV l;tf h>lf hJl", -"; ui> htN t&hN tDhN hNtc t1hN hNt: ht1DN h:tcN htQ h&tQ tQVh tchQ lhQ hQl: ", -"VlhQ uhQ hNt* hNt- t*DhN t-hcN t*1hN h:t-N h1Dt*N t-ch:N t*hQ hQt- tQ*Vh V-", -"htQ hQl* hQl- lhVQ* h-uQ htW h&tW hWtJ tchW tWh1 t:hW tJh1W h:WtJ tGhQ tGQh", -"& hZt htZc lhW lWh: hZl uZh tfW hWt- JftW itW f1tW tW:f tfJ1W t:iW tfQ f-tQ", -" tZf iZt lWtf h-lW hZlf uiZ htm h&tm hDtm tchm t5hm t:hm ht5Dm h:mtc tQhm h", -"tQm& tmVh Vhmtc hpl h:tp Vplh uph tmh; hmt- tm*hD t-mhc t5*hm hmt> tmDh1; h", -">tcm tQh; t-Qhm Vhmt; V-mht l;hp hpl- lh;Vp hpu- tGhm tGmh& hmtJ tJmhc t5hW", -" h:Wt5 tJ5hW :Jmht tGQhm tG&hMm hmtZ hZtcm lGhp lhW:p tZhp hZup hvt t-hv tJ", -"hv itv h1tv tvh> hvtJ1 tvi: hQtv hvt-Q tZhv tZiv lvh hvl- hZlv uiy 3 !3 3B ", -"a3 3. 83 .B3 8a3 3K !K3 T3 Ta3 j3 8j3 Tj3 s3 3( +3 3B( +a3 3(. +83 3(.B 8a+", -"3 3(K +3K T3( +T3 j3( +j3 j3T( s+3 E3 !E3 H3 Ha3 E3. 8E3 H3. H83 EK3 !3EK H", -"T3 TaH3 jE3 jE83 Hj3 sH3 d3 +d3 Hd3 g3 d3. 8d3 d3H. g83 dK3 dK+3 Td3 gT3 dj", -"3 +3dj H3dj gs3 4 4! 4B 4a 45 48 45B 48a 4K 4K! 4T 4Ta 4j 48j 4T5 s4 4; 4+ ", -"4;B 4+a 45; >4 5;4B >4a 4;K 4+K 4T; 4+T 4j; >j4 T;4j s>4 4E 4E! 4H 4Ha 45E ", -"48E 4H5 4H8 4EK EK4! 4HT HT4a 4jE 8j4E 4Hj s4H 4d 4+d 4Hd g4 4d5 >4d H54d g", -">4 4dK +d4K 4Td g4T 4dj 4d>j H;4j gs4 3N !3N 3BN a3N N.3 83N 3BN. aN83 Q3 Q", -"!3 QT3 Qa3 Qj3 Q83 TjQ3 sQ3 3(N +3N 3(NB a3+N 3(N. 83+N 3(N.B +8a3N Q3( +Q3", -" T3Q( +3Qa j3Q( +3Q8 QTj3( +Qs3 W3 W!3 HW3 Wa3 W3. W83 W3H. H3W8 WQ3 W3Q! Z", -"3 Za3 Wj3 W3Q8 Zj3 sZ3 Wd3 +W3 WdH3 gW3 d3W. +3W8 HWd3. W8g3 Qd3 +3Qd Zd3 g", -"Z3 W3dj +3Wj djZ3 g3sZ 4m 4m! 4mB 4am 45m 48m 5m4B 8m4a 4Q 4Q! 4QT 4Qa p4 p", -"48 p4T sp4 4m; 4+m m;4B +m4a 5m4; >m4 45m;B 4a>m 4Q; 4+Q Q;4T +Q4T p4; p>4 ", -"4Tp; p>s4 4W 4W! 4HW 4Wa 4W5 4W8 H54W H84W 4WQ Q!4W Z4 Z4a p4W 4Wp8 Zp4 sZ4", -" v4 v4+ v4H gv4 v45 v>4 4Hv5 v>g4 v4Q 4+vQ Zv4 gZ4 pv4 p4v> pvZ4 y4 #3 &3 #", -"B3 a&3 #3. 8&3 #3.B a&83 #3K &3K T#3 T&3 j#3 &j3 j#T3 s&3 #3( +&3 #3(B a&+3", -" 3(#. 8&+3 .B3#( +8a&3 3(#K &3+K #3T( +3T& #3j( +3&j Tj#3( +&s3 #E3 &E3 H#3", -" H&3 E3#. &E83 #3H. 8&H3 #3EK EK&3 T#H3 H3T& #Ej3 jE&3 j#H3 H&s3 d#3 d&3 d#", -"H3 g&3 #3d. 83d& Hd#3. 8&g3 #3dK &3dK d#T3 T&g3 j#d3 d3&j dj#H3 s&g3 4# 4& ", -"4#B 4a& 45# 48& 5B4# 5a4& 4#K 4&K 4T# 4T& 4j# 4&j 4#5T s4& 4;# 4+& ;#4B a;4", -"& 5;4# >&4 45;#B 4a>& ;#4K 4K;& 4#T; +T4& 4#;j 4&>j ;j#4T >&s4 4#E 4&E 4H# ", -"4H& 5#4E 4E5& 4#H5 H54& EK4# &E4K HT4# H&4T j#4E 4E&j 4#Hj 4Hs& 4d# 4d& 4#H", -"; g4& 4#5d 4d>& 4H5d# >&g4 dK4# 4Kd& 4#Td 4Tg& 4#dj d&4j 4Hjd# g&s4 #3N &3N", -" #3NB &3aN #3N. &38N 3BN#. 8a&3N Q#3 Q&3 T#Q3 Q3T& j#Q3 Q3&j QTj#3 Q&s3 3(#", -"N &3+N 3(N#B +a&3N 3(N#. +8&3N 3B(N.# 8a&+3N #3Q( +3Q& QT#3( +QT&3 Qj#3( &j", -"3+Q Tj#Q3( s+Q&3 W#3 W&3 W#H3 H3W& #3W. 8&W3 HW#3. H8W&3 Q#W3 W3Q& Z#3 Z&3 ", -"j#W3 W3&j j#Z3 s3Z& d#W3 +3W& HWd#3 W&g3 Wd#3. d&3W8 Wd#H3. gW8&3 d#Q3 Q3d&", -" d#Z3 g3Z& dj#W3 d&jW3 Zdj#3 Z&3gs 4m# 4&m m#4B am4& 5m4# 8m4& 45m#B am&48 ", -"4Q# 4Q& 4#Tm Qa4& p4# p&4 4Tp# p&s4 m;4# +m4& 4m;#B am&4+ 45m;# 4&>m 5m;4#B", -" >m4a& 4#Q; +Q4& 4QT;# 4+QT& 4;p# p4>& p4T;# p>4s& 4W# 4W& 4#Hm Hm4& 4#5W 5", -"W4& 4H5W# 4H8W& WQ4# W&4Q Z4# Z4& 4Wp# 4Wp& p4Z# Z&s4 v4# v&4 4Hv# v&g4 45v", -"# v4>& v4H5# gv>4& 4Qv# 4Qv& v4Z# Z&g4 v4p# p4v& Zpv4# y&4 C3 !C3 D3 Da3 C3", -". 8C3 D3. D83 CK3 !3CK DT3 TaD3 jC3 jC83 Dj3 sD3 C3( +C3 D3( +D3 3(C. 8C+3 ", -"3(D. +3D8 3(CK CK+3 T3D( DT+3 C3j( jC+3 j3D( +Ds3 CE3 CE!3 HD3 DaH3 E3C. CE", -"83 D3H. H3D8 C3EK EKC!3 DTH3 HDTa3 CEj3 8jCE3 H3Dj HDs3 dC3 dC+3 Dd3 gD3 C3", -"d. dC83 d3D. D8g3 CKd3 +dC3K D3Td DTg3 jCd3 djC+3 D3dj sDg3 4C 4C! 4D 4Da 4", -"5C 48C 4D5 4D8 4CK CK4! 4DT DT4a 4jC 8j4C 4Dj s4D 4;C 4+C 4D; 4+D 5;4C >C4 ", -"45D; >D4 ;C4K +C4K D;4T +D4T 4C;j 4j>C D;4j >Ds4 4CE !C4E 4HD HD4a 5C4E 8C4", -"E H54D H84D EK4C 4CE!K HD4T 4HDTa jC4E 48jCE Hj4D 4HsD 4dC +d4C 4Dd g4D 4C5", -"d 4d>C 5D4d >Dg4 dK4C 4+dCK Dd4T 4DgT 4Cdj >j4dC Dd4j gDs4 C3N C3!N D3N a3D", -"N C3N. C38N N.D3 83DN QC3 !CQ3 QD3 DaQ3 jCQ3 8CQ3 Q3Dj QDs3 3(CN C3+N 3(DN ", -"D3+N C3N(. +8C3N D3(N. +D83N C3Q( QC+3 D3Q( +3QD QjC3( +Q8C3 QDj3( s+QD3 WC", -"3 !CW3 WD3 DaW3 C3W. 8CW3 D3W. W3D8 QCW3 Q!WC3 ZD3 DaZ3 jCW3 W8QC3 DjZ3 ZDs", -"3 dCW3 WC+3 W3Dd WDg3 WdC3. +W8C3 WDd3. gWD83 dCQ3 +WQC3 DdZ3 ZDg3 djCW3 +W", -"jC3 ZDdj3 gZsD3 4mC mC4! 4Dm Dm4a 5m4C 4C8m 45Dm Dm48 4QC 4CQ! 4QD QD4a p4C", -" 48pC pD4 pDs4 m;4C 4C+m 4mD; +m4D 45m;C 4m>C 4D5m; 4D>m 4CQ; 4C+Q Q;4D +Q4", -"D 4;pC p4>C 4Dp; p4>D 4WC W!4C 4WD WD4a 4C5W 4CW8 5W4D WD48 WQ4C 4WQ!C Z4D ", -"4DZa 4WpC p4W8C pDZ4 sDZ4 v4C 4+vC vD4 vDg4 45vC v4>C 4Dv5 v4>D 4QvC v4+QC ", -"vDZ4 gDZ4 v4pC pv>4C p4vD y4D b3 b&3 bD3 c3 b3. b83 D3b. c83 bK3 &3bK bT3 c", -"T3 bj3 b3&j b3Dj sc3 b3( b+3 D3b( c+3 3(b. +8b3 bD3(. +8c3 3(bK +3bK T3b( +", -"Tc3 j3b( b3+j bTj3( c+s3 bE3 &Eb3 bH3 cH3 E3b. 8Eb3 H3b. H8c3 EKb3 bK&E3 HT", -"b3 HTc3 jEb3 &jEb3 b3Hj cHs3 bd3 b3d& b3Dd gc3 d3b. b38d bHd3. c8g3 dKb3 d&", -"3bK b3Td cTg3 b3dj d&jb3 bHjd3 g3sc 4b 4b& 4bD c4 4b5 4b8 b54D c45 4bK bK4&", -" 4bT c4T 4bj b84j b54T sc4 4b; 4b+ b;4D c4+ 45b; >b4 4b5D; c>4 4Kb; 4Kb+ b;", -"4T 4+cT b;4j 4b>j 4bT;j s4c> 4bE b&4E 4bH c4H 4Eb5 4Eb8 b54H 4Hc5 bK4E 4b&E", -"K bH4T 4HcT 4Ebj 4b8jE bH4j sHc4 4bd b+4d bH4d gc4 b54d 4b>d 4bH5d g4c> 4Kb", -"d 4b+dK bT4d gTc4 bd4j >b4dj 4bHdj scg4 b3N &3bN D3bN c3N N.b3 83bN bD3N. 8", -"3cN bQ3 b3Q& b3QD cQ3 Qjb3 b3Q8 bQDj3 s3cQ 3(bN +3bN bD3(N +3cN b3(N. b+83N", -" D3(bN. c+83N Q3b( b3+Q bQD3( +Qc3 bQj3( b+Q83 QD3bj( cQ+s3 bW3 b3W& b3WD c", -"W3 W3b. b3W8 bHW3. W8c3 WQb3 bWQ&3 Zb3 Zc3 b3Wj bW8Q3 bjZ3 s3Zc Wdb3 b3+W b", -"HWd3 g3cW bWd3. b+W83 WD3bd. cW8g3 b3Qd b+WQ3 bdZ3 g3Zc bWjd3 b+Wj3 Zbdj3 Z", -"cgs3 4bm bm4& bm4D c4m 45bm bm48 4b5Dm 48cm 4bQ bQ4& bQ4D c4Q pb4 4bp& 4bpD", -" cp4 4mb; bm4+ 4bDm; 4+cm 4b5m; 4b>m b5m4D; >mc4 b;4Q b+4Q 4bQD; 4+cQ 4bp; ", -"p4>b pb4D; p>c4 4bW bW4& bH4W c4W b54W bW48 4bH5W 4Wc5 bW4Q 4bWQ& Z4b Zc4 4", -"bpW pb4W8 pbZ4 s4Zc vb4 4bv& 4bvD cv4 4bv5 v4>b vb4H5 v>c4 4bvQ vb4+Q vbZ4 ", -"g4Zc p4vb pvb>4 Zpbv4 yc4 6 6! 6B 6a 61 68 61B 68a 6K 6!K 6T 6Ta 6j 68j 6T1", -" s6 6( 6+ 6(B 6+a 61( 6+1 1(6B 1+6a 6(K 6+K 6T( 6+T 6j( 6+j 6(1T s6+ 6E 6!E", -" 6H 6Ha 61E 68E 6H1 6H8 6EK EK6! 6HT HT6a 6jE 8j6E 6Hj s6H 6d 6+d 6Hd g6 6d", -"1 68d 1H6d g61 6dK +d6K 6Td g6T 6dj +j6d 1T6d gs6 46 6!4 46B 4a6 7 78 7B 7a", -" 46K 4K6! 4T6 6T4a 7j 78j 7T 7s 6; 4+6 6;B 6a; 7; 7> 7B; 7>a 6;K 4K6+ 6T; 6", -"+4T 7;j 7>j 7T; 7s> 46E 4E6! 4H6 6H4a 7E 78E 7H 7H8 6E4K 6!4EK 6H4T 4H6Ta 7", -"jE 8j7E 7HT 7sH 4d6 6+4d 6H; g46 7d 7>d 7Hd g7 4K6d 4+6dK 6T4d 4Tg6 7dj >j7", -"d 7Td g7s 6N 6!N 6NB 6aN 61N 68N 1N6B 6N1a 6Q 6Q! 6QT 6Qa 6Q1 6Q8 1Q6T s6Q ", -"6(N 6+N (B6N +a6N 1(6N 6N1+ 61(NB 6+1aN 6Q( 6+Q QT6( +Q6T 6(1Q 1+6Q 6Q1T( 6", -"+sQ 6W 6W! 6HW 6Wa 6W1 6W8 1H6W 1W6a 6WQ Q!6W Z6 Z6a 6Wj W86Q Z61 sZ6 6Wd 6", -"+W HW6d g6W 1W6d 1+6W 6H1Wd 6Wg1 6Qd +W6Q Z6d gZ6 1Q6d +W6j 6dZ1 sZg6 6m 6m", -"! 6mB 6am 7m 78m 7Bm 7am 4Q6 Q!6m 6Tm 6Q4a 7p 7p8 7pT 7sp 6m; 6+m m;6B +m6a", -" 7m; 7>m m;7B >m7a 6Q; 6+4Q Q;6T +T6m 7p; 7p> pT7; 7ps> 4W6 6!4W 6Hm 6W4a 7", -"W 7W8 7HW 7Wa 6W4Q 4WQ6! Z46 4aZ6 7pW pW78 7Z 7Zs v6 v6+ v6H gv6 7v 7v> 7vH", -" g7v v6Q 6+vQ Zv6 Zvg6 7vp pv7> 7Zv y7 69 6& 69B 6a9 691 :6 916B :6a 69K 6&", -"K 6T9 6T& 6j9 :6j 9T6j s:6 69( 6+9 9(6B 9+6a 916( :6+ 691(B 6+:a 9(6K 6K9+ ", -"6(9T 9+6T 6(9j 6+:j 6T91( :6s+ 69E 6&E 6H9 6H& 916E :6E 691H :H6 9E6K &E6K ", -"9H6T H&6T 6E9j 6j:E 9H6j :Hs6 6d9 6d& 9H6d g69 691d :d6 6H91d g:6 6K9d 6Kd&", -" 9T6d 6Tg9 9d6j 6d:j 6Hj9d s:g6 49 49& 49B 49a 79 7: 7B9 7:a 49K 4K6& 49T 6", -"T4& 79j 7:j 7T9 7s: 49; 49+ 4B9; 9+4a 79; 7:> 9;7B :>7a 4K9; 4K9+ 9T6; 9+4T", -" 9;7j >j7: 9T7; 7:s> 49E 4E6& 49H 6H4& 79E 7:E 7H9 7:H 9E4K 49&EK 9H4T 49HT", -"& 9j7E :j7E 9H7T 7Hs: 49d 6d4& 9H4d g49 7d9 7:d 9H7d g7: 4K9d 49+dK 9T4d 49", -"gT 9d7j 7j:d 9T7d 7sg: 69N 6&N 9N6B 6N9a 916N :6N 691NB 6a:N 6Q9 6Q& 9Q6T 9", -"Q6a 9Q6j :Q6 6Q91T :Qs6 9(6N 6N9+ 69(NB 6+9aN 691(N 6+:N 91(6NB :6+aN 6(9Q ", -"9+6Q 6Q9T( 6+Q9T 6Q91( 6+:Q 9Q16T( :Q6s+ 6W9 6W& 9H6W 9W6a 691W :W6 6H91W 6", -"H:W 9W6Q W&6Q Z69 Z6& 9W6j 6W:Q 6jZ9 Z:6 9W6d 9+6W 6H9Wd 6Wg9 6W91d 6+:W 9H", -"16Wd :Wg6 9Q6d Qd6& 6dZ9 Z6g9 6Wj9d 6Q:d Z691d g6Z: 49m 6m& 4B9m 9a6m 79m 7", -":m 9m7B :m7a 49Q 6Q4& 9Q4T 9Q4a 7p9 :p7 p97T :p7s 9m6; 9+6m 49m;B 49+am 9m7", -"; :m7> 7B9m; 7:>am 9Q6; 9+4Q 49QT; 49+Qa 7;p9 7>:p 7p9T; 7p>s: 49W 6W4& 9H4", -"W 9W4a 7W9 7:W 9H7W :H7W 9W4Q 49WQ& Z49 49Z& p97W 7W:p 7Z9 7Z: v69 v6& 49vH", -" v6g9 7v9 :v7 v97H :vg7 49vQ 6Qv& v6Z9 Z4g9 p97v :p7v Z97v y7: 6C 6!C 6D 6D", -"a 61C 68C 6D1 6D8 6CK CK6! 6DT DT6a 6jC 8j6C 6Dj s6D 6C( 6+C 6D( 6+D 1C6( 6", -"C1+ 6(1D 1+6D CK6( +C6K DT6( +D6T jC6( 6C+j 6(Dj 6+sD 6CE !C6E 6HD HD6a 1C6", -"E 8C6E 1H6D H86D EK6C 6!CEK HD6T 6HDTa jC6E 68jCE Hj6D 6HsD 6dC +d6C 6Dd g6", -"D 6C1d 6C8d 1D6d 6Dg1 dK6C 6+dCK Dd6T 6DgT 6Cdj 6+jdC Dd6j gDs6 46C 4C6! 4D", -"6 6D4a 7C 78C 7D 7D8 6C4K 6!4CK 6D4T 4DT6a 7jC 8j7C 7DT 7sD 6;C 4C6+ 6D; 6+", -"4D 7;C 7>C 7D; 7>D ;C6K 4+6CK D;6T 4+D6T ;j7C 7j>C D;7T 7Ds> 6C4E 6!4CE 6H4", -"D 4H6Da 7CE 8C7E 7HD H87D 46CEK 4CE6!K 4H6DT 6HD4Ta jC7E 78jCE Hj7D sH7D 4C", -"6d 4+6dC 6D4d 4Dg6 7dC >C7d 7Dd g7D 4d6CK 6+C4dK 4Dd6T g46DT dj7C 7>djC Dd7", -"T 7Dgs 6CN !C6N 6DN Da6N 1C6N 8C6N 6N1D 6ND8 6QC 6CQ! 6QD QD6a 6C1Q 6CQ8 1Q", -"6D 6QsD C(6N +C6N D(6N 6N+D 61C(N 6+1CN 6D1(N 6+D1N QC6( 6C+Q 6(QD +Q6D 6Q1", -"C( 6+Q1C 6QD1( s6+QD 6WC W!6C 6WD WD6a 6C1W 6CW8 1W6D WD68 WQ6C 6WQ!C Z6D 6", -"DZa 6CWj 6W8QC 6DZ1 sDZ6 Wd6C 6C+W WD6d 6WgD 6W1dC 6+W1C 6WD1d g61WD 6CQd 6", -"+WQC 6DZd gDZ6 6WjdC 6+WjC Z61Dd gZ6sD 6mC mC6! 6Dm Dm6a 7mC 8m7C 7Dm D87m ", -"4C6Q 4Q6!C 6Q4D 4QD6a 7pC p87C 7pD 7Dsp m;6C 6C+m Dm6; +D6m m;7C 7m>C Dm7; ", -">m7D 6CQ; 4+Q6C QD6; 4+Q6D p;7C >C7p 7;pD p>7D 4C6W 4W6!C 6W4D 4WD6a 7WC W8", -"7C 7WD WD7a 4WQ6C 6WC4Q! 4DZ6 Z46Da pW7C 7pW8C 7ZD 7DsZ v6C 6+vC v6D vDg6 7", -"vC >C7v 7vD 7Dgv 6QvC v6+QC vDZ6 Zv6gD 7Cpv 7p>vC 7DZv y7D b6 b6& b6D c6 b6", -"1 :b6 6Db1 :c6 b6K bK6& b6T c6T b6j b6:j 6Dbj sc6 b6( b6+ b(6D c6+ 61b( b6:", -"+ b61D( :+c6 6(bK bK6+ b(6T 6+cT b(6j 6+bj b6T1( s+c6 b6E bE6& b6H c6H 61bE", -" b6:E 6Hb1 c6:H 6EbK b6&EK 6HbT 6HcT bE6j :b6jE 6Hbj sHc6 b6d 6+bd 6Hbd gc6", -" 6db1 b6:d b6H1d :cg6 bK6d b6+dK 6Tbd gTc6 6dbj :db6j b6Hdj scg6 4b6 b64& 4", -"9D c46 7b 7:b 7bD 7c 4Kb6 4b6&K b64T 49cT 7bj :b7j 7bT 7cs b6; b64+ 6Db; c6", -"; 7b; 7>b b;7D 7c> bK6; 4b+6K 6Tb; 6Tc; b;7j >j7b bT7; c>7s 4Eb6 4b6&E b64H", -" 49cH 7bE 7E:b 7bH 7cH 4b6EK b6E4&K 4bH6T c46HT bj7E 7:bjE bH7T 7Hsc b64d 4", -"b+6d 6Hb; c4g6 7bd :d7b bH7d g7c 4bd6K d&Kb6; 4bT6d c6;gT bd7j 7:dbj bT7d g", -"s7c b6N bN6& bN6D c6N 61bN b6:N b61DN cN:6 b6Q 6&bQ 6QbT c6Q 6Qb1 b6:Q b6Q1", -"D c6:Q 6(bN bN6+ b6D(N 6+cN b61(N :b6+N 6D(b1N :c6+N b(6Q 6+bQ b6QD( 6+cQ b", -"6Q1( :Qb6+ b6(1QD :cQ6+ b6W 6&bW 6HbW c6W 6Wb1 b6:W b6H1W c6:W 6WbQ b6WQ& Z", -"b6 Zc6 6Wbj :Wb6Q b6Z1 s6Zc 6Wbd 6+bW b6HWd cWg6 b6W1d :Wb6+ 6WDb1d g:c6W 6", -"Qbd b6+Qd b6Zd g6Zc b6Wdj :Qdb6 Zb61d Zc6g: b6m 6&bm 6Dbm c6m 7bm :m7b bm7D", -" 7cm b64Q 4bQ6& 6Tbm 49cQ 7pb 7b:p pb7D 7cp 6mb; 6+bm 49Dm; 6+cm bm7; >m7b ", -"7bDm; cm7> 6Qb; 4b+6Q 49QD; 6Qc; 7;pb p>7b 7pbD; 7pc> b64W 4bW6& 6Hbm 49cW ", -"7bW :W7b bH7W 7cW 4bW6Q b6W4Q& 4bZ6 c4Z6 pb7W 7pb:W 7Zb 7Zc vb6 b6v& 49vD c", -"v6 7vb 7b:v vb7H 7cv b6vQ vb6+Q vbZ6 Z6cv pv7b :vb7p Zv7b y7c 3L !3L 3BL a3", -"L 3L. 83L 3L.B a38L M3 M3! TM3 aM3 Mj3 8M3 MjT3 sM3 3(L +3L 3(LB a3+L (L3. ", -"83+L 3L.(B +8a3L M3( +M3 M3T( +3aM j3M( +38M TMj3( +Ms3 E3L E3!L H3L a3HL 3", -"LE. E38L 3LH. 83HL ME3 !EM3 HM3 H3aM jEM3 ME83 MjH3 HMs3 d3L d3+L d3HL g3L ", -"3Ld. d38L Hd3L. 83gL dM3 +3dM H3dM gM3 Mjd3 83dM dMjH3 sMg3 4L 4L! 4LB 4aL ", -"45L 48L 5B4L 4L5a 4M 4M! 4TM 4aM 4M5 48M 5T4M s4M 4;L 4+L ;L4B 4La; 5;4L >L", -"4 45;LB 4a>L 4M; 4+M T;4M +T4M M;4j >M4 4T5M; s4>M 4EL !E4L 4HL Ha4L 5E4L 8", -"E4L 4LH5 4LH8 4ME ME4! 4HM HM4a 4E5M 4E8M H54M 4HsM 4dL +d4L 4LH; g4L 4L5d ", -"4d>L 4H5dL >Lg4 4dM +M4d HM4d g4M 5d4M 4d>M 4HM5d g4>M 3LN 3L!N 3LNB 3LaN 3", -"LN. 3L8N 3L.NB 8a3LN QM3 M3Q! TMQ3 Q3aM MjQ3 Q38M QTMj3 QMs3 (L3N 3L+N 3(NL", -"B +a3LN 3L.(N +83LN .BL3(N 8a3+LN M3Q( QM+3 QTM3( aM3+Q QMj3( +Q8M3 TMjQ3( ", -"s+QM3 W3L !3WL W3HL a3WL 3LW. 83WL HW3L. H8W3L WM3 M3W! ZM3 aMZ3 MjW3 W38M ", -"MjZ3 ZMs3 d3WL W3+L HWd3L W3gL Wd3L. +W83L Wd3HL. gW83L W3dM +3WM dMZ3 ZMg3", -" dMjW3 +WM83 ZdMj3 gZsM3 4mL mL4! mL4B 4Lam 5m4L 4L8m 45mLB amL48 4QM Q!4M ", -"Tm4M Qa4M p4M 48pM 4TpM p4sM m;4L 4L+m 4m;LB amL4+ 45m;L 4m>L 5m;4LB >m4aL ", -"Q;4M +Q4M 4QTM; aMm4+ 4Mp; p4>M p4TM; >Mps4 4WL W!4L 4LHm 4LWa 4L5W 4LW8 4H", -"5WL 4H8WL 4WM 4!WM Z4M 4aZM 4WpM W84M p4ZM sMZ4 v4L 4+vL 4HvL v4gL 45vL v4>", -"L v4H5L gv>4L vM4 4+vM vMZ4 Z4gM p4vM v4>M Zpv4M y4M #3L &3L #3LB &3aL 3L#.", -" &38L 3L.#B 8a&3L M#3 M&3 M#T3 T3M& j#M3 83M& TMj#3 M&s3 3(#L &3+L (BL#3 +a", -"&3L 3L.#( +8&3L 3B(#L. 8a&+3L #3M( +3M& TM#3( aM3+& Mj#3( M&3+j Mj#T3( s+M&", -"3 E3#L E3&L #3HL &3HL 3L.#E 8&E3L H#3L. H8&3L #EM3 &EM3 M#H3 H3M& Mj#E3 M&E", -"83 HMj#3 sHM&3 #3dL &3dL Hd#3L &3gL d#3L. d&38L d#3HL. g8&3L M#d3 d3M& dM#H", -"3 M&g3 dMj#3 dM&83 HM#dj3 gsM&3 4#L 4&L #B4L a&4L 5#4L 4L5& 45#LB 48a&L 4M#", -" 4M& TM4# T&4M 4#5M 5M4& 4T5M# 4Ms& ;#4L 4L;& 4;#LB a;&4L 45;#L 4&>L 5;#4LB", -" >&4aL 4#M; +M4& M;#4T aM;4& M;#4j 4M>& 4T5M;# >Ms4& #E4L &E4L H#4L 4LH& 45", -"#EL 48&EL 4H5#L 4H8&L M#4E 4EM& 4#HM HM4& 4M5#E 48M&E 4HM5# s4HM& d#4L 4Ld&", -" 4Hd#L 4&gL 4d5#L >&4dL H5#4dL g>4&L 4#dM dM4& 4HMd# 4Mg& 4dM5# >M4d& dM#4H", -"j >Mg4& 3L#N 3L&N #LN3B a&3LN 3L.#N 8&3LN #L.3BN a&38LN M#Q3 Q3M& QTM#3 aM3", -"Q& QMj#3 M&3Q8 TMjQ#3 sQM&3 3(N#L +&3LN 3B(#LN a&3+LN #L.3(N 8&3+LN 3LNB#(.", -" 3L+N8a& QM#3( M&3+Q TM#Q3( +QTM&3 Mj#Q3( +Q8M&3 TMQj#3( M&3s+Q #3WL &3WL H", -"W#3L H&W3L W#3L. W8&3L W#3HL. W83H&L M#W3 W3M& M#Z3 M&Z3 WMj#3 W8M&3 ZMj#3 ", -"Z&Ms3 Wd#3L d&3WL Wd#H3L gW&3L d#3WL. W83d&L W3HLd#. W8&g3L dM#W3 dM&W3 ZdM", -"#3 Z&Mg3 WM#dj3 dM3W&j dMjZ#3 gsMZ&3 m#4L 4Lm& 4m#LB am&4L 45m#L m&L48 5m#4", -"LB 48am&L 4#Mm Q&4M Mm#4T aMm4& 4Mp# 4Mp& p4TM# p&4sM 4m;#L m&L4+ m;#4LB 4+", -"am&L 5m;4#L >m4&L mL4B5;# am&>L4 Mm#4; Mm&4+ 4QTM;# 4+TMm& p4M;# >Mp4& M;#p", -"4T p&4>Ms W#4L 4LW& 4HW#L 4H&WL 4W5#L 4W8&L H5#4WL m&L4H8 4#WM WM4& 4MZ# 4M", -"Z& p4WM# p&4WM Zp4M# Zp&4M 4#vL 4&vL v4H#L gv4&L v45#L v>4&L 4H5v#L v>&g4L ", -"4Mv# 4Mv& Zv4M# Zv&4M pv4M# >Mv4& pvMZ4# 4My& U3 U!3 UD3 Ua3 U3. U83 D3U. U", -"3D8 UM3 M3U! V3 Va3 Uj3 U38M Vj3 Vs3 U3( U+3 D3U( U3+D 3(U. +8U3 UD3(. U+D8", -"3 M3U( U3+M V3( V+3 j3U( U3+j j3V( s3V+ UE3 !EU3 UH3 HaU3 E3U. 8EU3 H3U. U3", -"H8 MEU3 U!ME3 VH3 HaV3 jEU3 U8ME3 HjV3 VHs3 Ud3 +dU3 U3Dd gU3 d3U. U38d UHd", -"3. U8g3 U3dM dM3U+ Vd3 gV3 U3dj U+jd3 djV3 g3Vs 4U 4U! 4UD 4Ua 4U5 4U8 U54D", -" U54a 4UM U!4M V4 V4a 4Uj U84M V45 s4V 4U; 4U+ U;4D U+4D 45U; >U4 4U5D; 4U>", -"D U;4M U+4M V4; V4+ U;4j 4U>M 4jV; V>4 4UE U!4E 4UH UH4a 4EU5 4EU8 U54H UH4", -"8 UM4E 4UM!E V4H 4HVa 4EUj 4U8ME 4HV5 sHV4 4Ud U+4d UH4d g4U U54d 4U>d 4UH5", -"d >Ug4 Ud4M 4U+dM V4d gV4 Ud4j >M4Ud 4dV5 g4V> U3N !3UN D3UN a3UN N.U3 83UN", -" UD3N. U8D3N UQ3 U3Q! VQ3 QaV3 QjU3 U3Q8 QjV3 VQs3 3(UN +3UN UD3(N U+D3N U3", -"(N. U+83N D3(UN. +D3U8N Q3U( U3+Q Q3V( +QV3 UQj3( U+Q83 VQj3( Vs+Q3 UW3 W!U", -"3 U3WD U3Wa W3U. U3W8 UHW3. UH8W3 U3WM UWQ!3 VZ3 VaZ3 U3Wj UW8Q3 VjZ3 s3VZ ", -"WdU3 U3+W UHWd3 UWg3 UWd3. U+W83 WD3Ud. gUW83 U3Qd U+WQ3 Z3Vd g3VZ UWjd3 U+", -"Wj3 VZdj3 gVZs3 4Um 4!Um Um4D Um4a 45Um Um48 4U5Dm 4U8Dm 4UQ Q!4U V4Q 4QVa ", -"pU4 4Up8 Vp4 s4Vp 4mU; Um4+ 4UDm; 4U+Dm 4U5m; 4U>m U5m4D; >Dm4U U;4Q U+4Q 4", -"QV; 4+Vm 4Up; p4>U p4V; p>V4 4UW 4!UW UH4W UW4a U54W UW48 4UH5W 4UHW8 UW4Q ", -"4UWQ! Z4V ZaV4 4UpW pU4W8 Z4Vp VZs4 vU4 4Uv+ 4UvD vUg4 4Uv5 v4>U vU4H5 gvU>", -"4 4UvM vU4+Q Vv4 g4Vv p4vU >Mv4U pvV4 yV4 bU3 U&3 UDb3 cU3 U3b. b3U8 bUD3. ", -"U8c3 bM3 b3M& Vb3 Vc3 b3Uj b38M bjV3 s3Vc U3b( b3U+ bUD3( U+c3 bU3(. b+U83 ", -"UD3b(. cU+83 M3b( b3+M b3V( c3V+ bMj3( b+M83 Vbj3( Vs+c3 UEb3 &EU3 b3UH UHc", -"3 bUE3. b8UE3 bHU3. cUH83 MEb3 M&Eb3 bHV3 VHc3 bMjE3 b8ME3 VbHj3 VsHc3 b3Ud", -" U3d& bHUd3 cUg3 bdU3. b8dU3 UH3bd. gcU83 b3dM dM&b3 bdV3 g3Vc bdMj3 d&jU3 ", -"Vdbj3 gVsc3 4bU 4U& bU4D c4U b54U b84U 4bU5D 4Uc5 4bM bM4& V4b c4V b54M b84", -"M 4bV5 Vsc4 b;4U b+4U 4bUD; 4Uc; 4bU5; 4b>U b5U4D; >Uc4 b;4M b+4M 4bV; V4c;", -" 4bM;j 4b>M V4b;j c4V> bU4E 4EU& bH4U 4UcH 4bU5E 4b8UE 4bHU5 c4UH5 4EbM 4bM", -"&E 4bVH cHV4 4bM5E 4b8ME V4bH5 c4VsH bd4U Ud4& 4bHUd c4gU 4bdU5 >b4Ud bH54U", -"d c>g4U bd4M dM&4b 4bVd c4gV 4bdUj >Mb4d V4db5 V>gc4 U3bN &3UN bUD3N U3cN b", -"U3N. b8U3N UD3bN. cU83N b3UQ U3Q& bQV3 VQc3 bQUj3 bQ8U3 VbQj3 cQVs3 bU3(N b", -"+U3N UD3b(N cU+3N U3(bN. U+3b8N D3UNb(. U+8c3N bQU3( b+QU3 VbQ3( cQV+3 UQ3b", -"j( &j3U+Q bQjV3( Vs+cQ3 b3UW U3W& bHUW3 UWc3 bWU3. bW8U3 UH3bW. cWU83 b3WM ", -"bWM&3 VbZ3 Z3Vc bWMj3 bW8M3 ZbVj3 ZcVs3 bWUd3 b+WU3 UHWbd3 cWUg3 UW3bd. d&3", -"UW8 W.DdbU3 gU8cW3 bWMd3 b+WM3 ZbVd3 gVZc3 dM3bWj dM3bW8 VdjZb3 ZcsgV3 bm4U", -" Um4& 4bUDm 4Ucm 4bU5m 4b8Um b5U4Dm c4U8m bQ4U UQ4& 4bVm V4cQ 4bpU 4Up& pbV", -"4 c4Vp 4bUm; 4b+Um bmU4D; c4U+m b5m4U; >b4Um 5mD;4bU c>4Um 4bQU; 4b+UQ V4bQ", -"; c4V+Q pb4U; >Mbp4 Vp4b; cpV>4 bW4U UW4& 4bHUW 4UcW 4bWU5 4bWU8 bH54UW c4W", -"U5 bW4M 4bWM& V4Zb VZc4 pb4UW pU&4W ZpbV4 cpZV4 4bvU 4Uv& vb4UH vUc4 vb4U5 ", -"v>b4U 4bHvU5 cv>4U 4bvM vbM4+ vbV4 c4Vv pvb4U >Mv4b Vvp4b c4yV 6k 6!k 6kB 6", -"ak 61k 68k 1k6B 8k6a 6M 6M! 6Tk 6aM l6 l68 l6T ls6 6k( 6+k k(6B +k6a 1k6( +", -"k68 61k(B 6+1ak 6M( 6+M 6(Tk +T6M l6( l+6 6Tl( s6l+ 6kE kE6! 6Hk Hk6a 1k6E ", -"6E8k 61Hk Hk68 6ME ME6! 6HM HM6a l6E 68lE lH6 s6lH 6dk +k6d Hk6d g6k 61dk 8", -"k6d 6H1dk 68gk 6dM +M6d HM6d g6M ld6 6+ld 6Hld gl6 4k 4k! 4kB 4ak 7k 78k 7B", -"k 7ak 4kM 6!4M 4Tk 6a4M 7l 7l8 7lT 7sl 4k; 4+k 4Bk; +k4a 7k; >k7 k;7B 7a>k ", -"6M; 6+4M Tk6; +T4k l;7 l>7 7Tl; 7sl> 4kE kE4! 4Hk Hk4a 7kE 8k7E 7Hk H87k 4E", -"6M 4kM!E 6H4M 4HkaM 7lE 78lE lH7 lH7s 4dk +k4d Hk4d g4k 7dk 7d>k Hk7d g7k 6", -"d4M 4+kdM HM6; 4Tgk ld7 7>ld 7Hld gl7 6kN kN6! kN6B 6Nak 1k6N 6N8k 61kNB ak", -"N68 6Qk Q!6M Qk6T Qa6M l6Q 6Ql8 6QlT lQs6 k(6N 6N+k 6k(NB akN6+ 61k(N 6+1kN", -" 1k(6NB 6+1akN 6(Qk +Q6M 6QTk( 6+QTk 6Ql( 6+lQ l6QT( ls6+Q 6Wk 6!Wk Hk6W Wk", -"6a 61Wk Wk68 6H1Wk 6H8Wk 6WM 6!WM Z6k 6aZk lW6 6Wl8 lZ6 s6lZ Wk6d +k6W 6HWd", -"k 6Wgk 6W1dk 6+W8k 1HW6dk g61Wk WM6d +W6M 6dZk Z6gk 6Wld 6+lW Z6ld g6lZ 4km", -" 6!km 4Bkm ak6m 7km 8k7m km7B ak7m 4Qk Q!4k Qk4T Qa4k 7lp l87p lp7T 7lsp km", -"6; +k6m km;4B akm4+ km7; 7k>m 7Bkm; 7>akm Qk6; +Q4k 4QkT; ak;4Q 7pl; 7pl> 7", -"lpT; l>p7s 4Wk 4!Wk Hk4W Wa4k 7Wk W87k Hk7W Wa7k 6W4M 4WkQ! Z4k 4aZk lW7 l8", -"7W 7Zl lZ7s v6k 4+vk 4Hvk v6gk 7vk >k7v vk7H gk7v v6M 6+vM v6Zk Z4gk lv7 7v", -"l> 7Zlv yl7 69k 6&k 9k6B ak6& 916k :6k 691kB 6a:k 6M9 6M& 9T6M 9a6M l69 l:6", -" 6Tl9 s6l: 9k6( +k6& 69k(B 6+9ak 691k( 6+:k 91k6(B :6+ak 6(9M 9+6M 6T9k( 6+", -"T9M 69l( :6l+ l69T( ls:6+ 9k6E 6Ek& 69Hk Hk6& 691kE 6k:E 6H91k 6H:k 6E9M 6E", -"M& 9H6M HM6& 69lE :6lE 6Hl9 l6:H 69dk dk6& 6H9dk 6&gk 6d91k 6d:k 9H16dk :6g", -"k 9d6M dM6& 6HM9d 6Mg9 6dl9 l6:d lH69d g6l: 49k 4k& 9k4B 9a4k 79k 7:k 9k7B ", -":a7k 49M 6M4& 9T4k 9a4M 7l9 l:7 l97T l:7s 9;4k 9+4k k;B49 ak;49 9;7k 7:>k 7", -"B9k; 7:>ak 9M6; 9+4M 49Tk; aM;49 79l; 7:l> 7l9T; l>7s: 9k4E 4Ek& 9H4k Hk4& ", -"9k7E :k7E 9H7k 7k:H 4E9M 49M&E 9H4M 49HaM 79lE lE7: l97H 7:lH 9d4k dk4& 49H", -"dk 49gk 9d7k 7k:d 7H9dk 7:gk 9d4M dk&4M 49HdM 49gM l97d 7:ld 7Tdl9 l:g7 9k6", -"N 6Nk& 69kNB akN6& 691kN 6k:N 91k6NB :6akN 9Q6M Qk6& 6Q9Tk 6Qa9M 6Ql9 l6:Q ", -"l69QT :Q6ls 69k(N k&N6+ 9k(6NB 6+9akN 91k6(N :6+kN 916k(BN akN:6+ 6Q9k( 6+Q", -"9M 9QT6M( 9+Q6aM l69Q( :Q6l+ 6Q9lT( ls6:Q+ 69Wk Wk6& 6H9Wk 6H&Wk 6W91k 6W:k", -" 9H16Wk :H6Wk 9W6M WM6& 6MZ9 6MZ& 6Wl9 l6:W l6Z9 Z6l: 6W9dk dk&6W 9HW6dk g6", -"9Wk 9W16dk :W6+k 691HWkd g:6Wk 6WM9d dk&6Q Z69dk Z6&gk lW69d :Qdl6 lZ69d gl", -"Z:6 9m4k km4& kmB49 akm49 9m7k 7k:m 7B9km 7:akm 9Q4k Qk4& 49QTk aMm49 p97l ", -"7l:p 7lp9T 7sl:p km;49 km&4+ 49mk;B 49+akm 79km; 7:>km km;7B9 :>m7ak 49Qk; ", -"k;&4Q 9Q;4Tk 49+aMm 7lp9; l>p7: l;p7T9 7spl>: 9W4k Wk4& 49HWk km&4H 9W7k 7k", -":W 7H9Wk 7:HWk 9W4M Mm&6W 49Zk 4kZ& l97W 7:lW Z97l l:7Z 49vk 4kv& v69Hk gv6", -"k& 79vk vk7: 7v9Hk :vkg7 49vM 6Mv& Zv69M Zv6k& v97l l:7v lvZ79 l:y7 6U 6U! ", -"6UD 6Ua 6U1 6U8 1U6D 1U6a 6UM U!6M V6 V6a l6U 6Ul8 Vl6 s6V 6U( 6U+ 6(Dk U+6", -"D 6(1U 1U6+ 6U1D( 6U+1D UM6( U+6M V6( V6+ 6Ul( 6Ul+ l(V6 V6l+ 6UE U!6E 6UH ", -"UH6a 6E1U 6EU8 1U6H UH68 UM6E 6UM!E V6H 6HVa 6UlE l6U8E V6lH sHV6 6Ud U+6d ", -"UH6d g6U 1U6d U86d 6UH1d 6Ug1 Ud6M 6U+dM V6d gV6 6Uld l+6Ud V6ld s6gV 4U6 6", -"!4U 4Dk 6U4a 7U 7U8 7UD 7Ua 6U4M 4U6M! V46 4aV6 7lU l87U 7V 7Vs 6U; 6U4+ U;", -"6D Ua6; 7U; 7>U U;7D 7D>k U;6M 4U+6M V6; 4+V6 7Ul; 7Ul> 7V; 7V> 4E6U 4U6!E ", -"6U4H 4UH6a 7UE U87E 7UH UH7a 4U6ME 6UE4M! 4HV6 V46Ha lE7U 7lU8E 7VH Vs7H 6U", -"4d 4U+6d UH6; 4Ug6 7Ud >U7d UH7d g7U 4Ud6M 6U+4dM 4dV6 V4g6 7Uld l>7Ud 7Vd ", -"g7V 6UN U!6N 6NDk 6NUa 6N1U 6NU8 6U1DN 6U8DN 6UQ Q!6U V6Q 6QVa 6UlQ UQ68 lQ", -"V6 sQV6 U(6N 6NU+ 6UD(N 6U+DN 6U1(N 6U+1N 1U(6DN 6UN1+D 6(UQ U+6Q 6QV( 6+VQ", -" l6UQ( l+6UQ Vl6Q( l+V6Q 6UW 6!UW UH6W UW6a 1U6W UW68 6UH1W 6UHW8 UW6Q 6UWQ", -"! Z6V ZaV6 6UlW lW6U8 VlZ6 VZs6 UW6d U+6W 6UHWd 6UgW 6UW1d 6U+1W 1UW6Dd g6U", -"1W UQ6d 6U+WM VdZ6 Z6gV lW6Ud l+W6U Z6Vld gV6lZ 6Um 6!Um Um6D Ua6m 7Um U87m", -" Um7D Ua7m 6U4Q 4UQ6! V6m 6aVm 7pU 78pU 7Vp Vp7s Um6; U+6m 4Dkm; 4+Dkm Um7;", -" >m7U 7UDm; 7>UDm UQ6; 4U+6Q 6QV; 6+Vm 7;pU p>7U V;7p 7pV> 6U4W 4UW6! UH6m ", -"4UW6a 7UW UW78 UH7W UW7a 4UW6Q Mm!6UW V4Z6 Z4V6a 7UlW 7pUW8 7ZV sZ7V v6U 6U", -"v+ 4Dvk v6gU 7vU v>7U vU7H gU7v 6UvM v6U+Q Vv6 g6Vv 7Ulv 7vUl> 7Vv y7V t6 t", -"6& t6D tc6 t61 t:6 6Dt1 c6t: t6M 6Mt& Vt6 c6V lt6 l6t: V6lt u6 t6( t+6 6Dt(", -" c6t+ 61t( :6t+ t61D( t:c6+ 6Mt( 6+tM t(V6 V6t+ t6l( l6t+ ltV6( u6+ t6E 6&t", -"E tH6 c6tH 61tE :6tE 6Ht1 t6:H 6MtE t6M&E V6tH cHV6 t6lE t:6lE l6tH u6H td6", -" 6+td 6Htd gt6 6dt1 t6:d tH61d t:g6 6dtM t+6dM V6td c6gV l6td t:dl6 tdVl6 u", -"g6 t4 t4& t4D tc4 7t 7t: 7tD 7ct t4M 4Mt& t4V Vtc4 7tl l:7t 7Vt u7 t4; t4+ ", -"4Dt; c4t+ 7t; t>7 7Dt; 7ct> 4Mt; 4+tM V4t; V4t+ l;7t 7tl> t;7V u7> t4E 4&tE", -" t4H c4tH 7tE tE7: 7tH tH7c 4MtE t4M&E V4tH tc4VH lE7t 7tl:E lH7t u7H t4d 4", -"+td 4Htd gt4 7td 7:td 7Htd g7t 4dtM t4+dM V4td t4gV ld7t 7tdl> td7V ug7 t6N", -" 6&tN 6DtN tNc6 61tN :6tN t61DN t:c6N tQ6 6Qt& V6tQ c6tQ l6tQ t6:Q tQVl6 u6", -"Q 6(tN 6+tN t6D(N tc6+N t61(N t:6+N 6D1t(N :c6t+N 6Qt( 6+tQ tQV6( tcQ6+ tQ6", -"l( t:Q6+ Vl6tQ( 6+uQ tW6 6Wt& 6HtW c6tW 6Wt1 t6:W tH61W t:H6W 6WtQ tW6Q& tZ", -"6 Z6tc l6tW t:Wl6 Z6lt uZ6 6Wtd 6+tW tH6Wd tWg6 tW61d t:W6+ 6WDtd1 gt:6W 6Q", -"td t+W6Q Z6td g6tZ tQdl6 t:Q6d tZl6d gZu6 t4m 4&tm 4Dtm c4tm 7tm 7:tm 7Dtm ", -"tm7c t4Q 4Qt& V4tQ c4tQ tp7 :p7t 7Vtp up7 6mt; 4+tm t4Dm; tc4+m 7mt; 7>tm 7", -"tDm; t>7cm 4Qt; 4+tQ t4VQ; tc4+Q 7pt; 7pt> tp7V; 7pu> t4W 4Wt& 4HtW c4tW 7t", -"W 7:tW 7HtW tW7c 4WtQ t4WQ& tZ4 t4Zc lW7t 7tW:p tZ7 uZ7 tv4 v6t+ v6tH g4tv ", -"tv7 7t:v tH7v tvg7 v6tQ tv4+Q t4Vv g4tZ 7tlv lvt7: 7Ztv yu7 < = =B5 =a> =K =+K =T =T+ =j =j> =T5 s= 4=", -"d =H5 g=> =dK +d=K =HT g=T =jd =d>j =Hj s=g =m 5m=B >m=a =Q =Q+ =QT =Qa p= p=> ", -"p=T s=p 4W< 4!W< H= vH=5 v>g= =Qv v+=Q Z= Z=g p=v v>p= Z=p y= ,<", -" <& ,= ,5=B ->=a =,K -=K =T, =T- =j, =j- ,5=T s=- ,4E ,E4& ,4H 4H,a ,E5< ,E", -"48 4H,5 4H,8 4E,K <&E4K 4H,T ,4HT& ,E4j <&j4E 4H,j ,4sH =d, -=d =H, g=- ,5=", -"d =d-> ,H=5 ->g= ,d=K -d=K ,H=T g-=T ,d=j =d-j ,H=j s-g= ,=-m =B5,m =a->m =Q, =Q- ,Q=T -Q=T p=, ", -"-p= p,=T -ps= ,4W 4&,W 4H,W 4W,a 4W,5 4W,8 ,4H5W -= =Hv,5 g=-v> v,=Q =Q-v Z=, Z", -"-= v=p, p=-v Z,p= y-= =C =D5 =D> =CK +C=K =DT +D=T ", -"=jC >C=j =Dj s=D C H5=D g>=D d", -"K=C =+dCK Dd=T gD=T dj=C =j>dC Hj=D gs=D C 5D=m >m=D =QC +Q=C =QD +Q=D p=C >Cp= p=D sp=D ", -"4CW< Cv= =5vD v>=D vQ=C =Qv+C Z=D =DgZ =C", -"pv p=v>C Zp=D y=D b< b<& ,D< c< b<. b8< ,.D< c<8 b ,5=D c=> =bK -b=K =bT c=T =", -"bj -j=b ,D=j s=c ,E4b <&E4b 4b,H ,4cH bE5< ,48bE H5b< H5c< ,4bEK 4bE<&K ,4H", -"bT c4H,T ,4jbE <&E4bj ,4Hbj c5b bH=5 c>g= bd=K", -" =b-dK bH=T gc=T bd=j =b>dj bH=j gsc= bm=b =b5Dm >=cm =bQ -Q=b ,Q=D c=Q p=b =b-p pb=", -"D cp= 4b,W =b =bvH5 v>c= vb=Q -v=bQ Z=b Z=c", -" pv=b -pv=b Zp=b yc= 6< 6!< 6= 7=B =a7 =6K 6+=K =T6 6+=T =j7 7>=j =T7 s=7 6", -"<4E 6!4=7d =H7 g7= 6d=K =6+dK 6H=T g6=T 7d=j 7>=d", -"j 7H=T s=g7 6m7= =m7B =m7a =Q6 6", -"+=Q 6Q=T 6Q=a p=7 7>p= 7p=T p=7s W<6m 7= =H7v", -" 7vg= v6=Q =Qv6+ Z=6 g6Z= p=7v 7p>v= 7Z= y7= ? ?& ?B ?a ?1 ?: ?B1 ?:a ?K ?&", -"K ?T ?Ta ?j ?:j ?T1 s? ?* ?- ?B* ?-a ?1* ?:- 1*?B :-?a ?*K ?-K ?T* ?-T ?j* ", -"?-j 1T?* s?- ?E ?&E ?H ?Ha ?1E ?:E ?H1 ?:H ?EK &E?K ?HT H&?T ?jE :j?E ?Hj s", -"?H ?d ?-d ?Hd g? ?d1 ?:d 1H?d g?: ?dK -d?K ?Td g?T ?dj :d?j 1T?d g?s ?4 ?4&", -" ?B4 ?a4 7? ?:7 7?B ?a7 ?4K 4&?K ?T4 4T?a ?j7 7:?j ?T7 s?7 ?= ?-= ?=B =a? ?", -"=7 A =B7? Aa ?=K =K?- =T? ?-=T =j? Aj ?T=j As ?4E 4&?E ?H4 4H?a 7?E ?E7: ?H", -"7 7:?H 4E?K ?4&EK 4H?T ?H4T& 7j?E ?:7jE 7H?T ?H7s ?=d -=?d =H? g?= ?d7 Ad 7", -"?=H Ag =K?d ?-=dK ?H=T =Tg? ?d=j Ajd ?H=j Ags ?N ?&N ?BN ?aN ?1N ?:N 1N?B :", -"a?N ?Q ?Q& ?QT ?Qa ?Q1 ?:Q 1Q?T s?Q ?*N ?-N *B?N -a?N 1*?N ?N:- ?B1*N ?:-aN", -" ?Q* ?-Q Q*?T -Q?T 1Q?* :-?Q ?Q1T* ?Qs- ?W ?W& ?HW ?Wa ?W1 ?:W 1H?W :H?W ?W", -"Q W&?Q ?Z ?Za ?Wj :W?Q ?Z1 s?Z ?Wd ?-W H*?W g?W 1W?d :-?W ?H1W* ?Wg: ?Qd -W", -"?Q ?Zd g?Z 1Q?d :Q?d Z1?d Z:g? ?m ?m& ?mB ?am ?m7 ?:m 7B?m 7a?m ?Q4 4Q?& ?T", -"m 4Q?a ?p ?p: ?pT s?p ?=m ?-m =B?m ?m=a 7=?m Am ?=7mB Aam =Q? ?-=Q ?Q=T ?Q=", -"a ?p= Ap =T?p Aps ?W4 4W?& ?Hm 4W?a ?W7 7:?W 7H?W 7W?a 4W?Q ?W4Q& ?Z4 Z4?a ", -"?pW ?W:p ?Zp 7Zs? ?v ?v- ?vH g?v ?v7 Av ?H7v Agv ?vQ ?Q-v ?Zv Z-?v ?pv Apv ", -"7Z?v yA 6C7= =D7 7>=D 6C=K =6+CK 6D=T =D6+T 7j=C 7>=jC 7D=T =D7s 46=dC 7H=D =Dg7 =6dCK 6+d", -"=CK =H6DT g=6DT 7=djC =j>7dC 7Dd=T g7s=D =mC =m7D 7>D=m 6Q=C =Q6+C 6Q=D =QD6+ =C7p 7p>=C 7p=D p=D7s =C =D7v 7vDg= =Qv6C v6+=QC Z6=D ", -"Z=g6D 7vp=C p=>7vC =D7Z =Dy7 ?b ?b& ?D ?c ?b1 ?:b ?D1 ?c: ?bK bK?& ?DT ?cT ", -"?jb :b?j ?Dj s?c ?b* ?-b ?D* ?c- b1?* ?b:- 1D?* :c?- b*?K -b?K bT?* c-?T b*", -"?j ?b-j D*?j ?cs- ?bE b&?E ?Hb ?cH b1?E :b?E b1?H :c?H bK?E ?b&EK bH?T cH?T", -" bj?E ?:bjE bH?j ?Hsc ?db -b?d ?Dd g?c b1?d ?b:d 1D?d ?cg: bd?K ?-bdK bT?d ", -"?Tgc bd?j ?:dbj Dd?j gs?c ?4b 4b?& ?D4 ?c4 7?b 7b?: ?D7 7c? 4b?K ?4b&K 4b?T", -" c4?T 7b?j ?:7bj 7b?T 7cs? =b? ?-=b =D? c=? =b7 Ab 7?=D Ac ?b=K ?-=bK ?D=T ", -"=T?c ?j=b Ajb ?D=j Asc 4b?E ?4b&E 4b?H c4?H ?E7b ?:7bE 7b?H ?H7c ?4bEK 4b&?", -"EK ?H4bT ?c4HT ?j7bE 7:b?jE ?H7bT s?7cH ?d=b ?-=bd ?H=b c=g? 7b?d Abd 7b=H ", -"Agc ?=dbK =b-?dK ?Dd=T c=?gT ?d7bj bdAj ?Hj=b gsAc ?bN b&?N ?DN ?cN b1?N :b", -"?N 1D?N ?N:c ?Qb bQ?& ?QD ?cQ b1?Q ?b:Q 1Q?D ?Qsc b*?N -b?N D*?N ?Nc- ?b1*N", -" ?:-bN ?D1*N ?c:-N bQ?* ?b-Q QD?* c-?Q ?Qb1* ?:Q-b ?QD1* ?cQs- ?Wb bW?& ?WD", -" ?cW b1?W ?b:W 1W?D :c?W bW?Q ?WbQ& ?Zb ?Zc bW?j ?:WbQ Zb?j ?cZ: bW?d ?b-W ", -"WD?d ?Wgc ?Wb1d ?:W-b ?WD1d ?cWg: bQ?d ?-WbQ Zb?d ?cZ- ?Wjbd ?:Qbd ?Zb1d g?", -"Zsc ?mb bm?& ?Dm ?cm 7b?m ?b:m 7D?m ?m7c 4b?Q ?Q4b& 4Q?D c4?Q ?pb pb?: ?pD ", -"?pc ?m=b ?b-m ?m=D ?mc= =m7b Abm ?D7=m Acm ?Q=b ?-Q=b ?Q=D =Q?c =b?p Apb =D", -"?p Apc 4b?W ?W4b& 4W?D c4?W 7b?W ?:W7b 7W?D ?W7c ?W4bQ 4bW?Q& Z4?D ?mZc pb?", -"W ?p:bW ?D7Z 7c?Z ?vb vb?- ?vD ?vc =b7v Avb ?D7v Acv vb?Q ?v-bQ =b?Z cv?Z p", -"b?v pvAb =b7Z yAc =L 5B=L >L=a =M =M+ =TM =aM =M5 >M= 5T", -"=M s=M L H5=L >Lg= =Md +M=d =HM g=M 5", -"d=M =d>M H5=M >Mg= L =B5mL =a>mL =QM +Q=M Tm=M Qa=M p=M >Mp= pT=M sp=M 4LW", -"< Lv= =Hv5L g=v>L =Mv =+vM Z=M =MgZ pv=M ", -"v>=M Zp=M y=M ,L-= =B5,L =a->L =M, =M- ,T=M -T=M ,5=M ->=M =T5,M =Ms- 4E,L ", -"<&E4L ,L4H ,4HaL ,45EL ,48EL ,4H5L ,4H8L ,E4M =dL =H5,L g=->L ,d=M =d-M ,H=M g-=M", -" =M5,d >M-=d =HM,5 g=Ms- =mL ,5m=BL ->m=aL ,Q=M -Q=M =QT,M =Q-aM p,=M =M-p p=T,M -ps=M ,", -"L4W =L v,5=HL -v>g=L v,=M =M-", -"v Z,=M =MZ- p=v,M -pv=M Z=p,M =My- U< U U5=D >U=D =U", -"M U+=M V= V=+ =Uj =U>M V=5 s=V 4EU< 4UU ", -"UH=5 g>=U Ud=M =U+dM V=H V=g Ud=j >M=Ud V5=H gVs= Um=U =U5Dm =U>Dm =UQ U+=Q V=", -"Q V+=Q p=U p>=U V=p Vps= U<4W 4UW=U =UvH5", -" g=Uv> vU=Q =Uv+Q Z=V gVZ= pv=U p=Uv> VpZ= yV= ,U< U<& U<,D c=U =bU5D =Uc> =bM -U=M V=b c=V ,U", -"=j =b>M V5=b V-s= ,E4U ,4U&E 4U,H c4U,H ,4U5E ,4U8E ,4UH5 c5Ud =bHU5", -" c=g>U bd=M =bM-d Vd=b gVc= =bM5d >M=bd V=bH5 c=Vgs ,NU< UN<& ,UDUm ,U5=Dm c=>Um ,U=Q -U=Q Vm=b =QV- pb=U =U-p =bV", -"p V=cp 4U,W = =U5vD, cv=>U v", -"b=M -vU=Q =bVv V-Z= p=bvU -pUv= Vv,p= c=yV k= 7B=k =", -"a>k =kM 6+=M =Tk 6a=M l= l=> l=T l=s 4Ek 7H=k >kg= 6d=M =k+dM 6H=M g6=M l=d >=ld l=H gl= m=k 7=mkB >k=am =Qk +Q=k Qk", -"=T Qa=k l=p p=l> lp=T lsp= W<4k =k 7v=", -"Hk g=k7v v6=M =Qkv+ Z=k =kgZ lv= v>l= l=Z yl= ?k ?k& ?Bk ?ak ?1k ?:k 1k?B :", -"a?k ?M ?M& ?Tk ?aM l? l?: l?T s?l ?k* ?-k k*?B -k?a 1*?k -k?: ?B1k* ?:-ak ?", -"M* ?-M Tk?* -T?M l?* l-? ?Tl* s?l- ?kE k&?E ?Hk Hk?a 1k?E :k?E 1H?k ?k:H ?M", -"E M&?E ?HM HM?a l?E lE?: l?H lHs? ?dk -k?d Hk?d g?k 1d?k ?k:d ?H1dk ?:gk ?d", -"M -M?d HM?d g?M l?d ?:ld ?Hld gl? ?4k 4k?& 4k?B 4a?k 7?k ?k7: ?k7B ?k7a ?M4", -" 4M?& 4T?M 4a?M l?7 7l?: 7l?T l?7s =k? =k- ?B=k ?a=k 7?=k Ak ?=7kB Aak =M? ", -"?-=M ?T=k ?a=M l=? Al =Tl? Als 4k?E ?4k&E 4H?k ?H4ak 7k?E ?:7kE ?k7H ?:H7k ", -"4M?E ?M4&E 4H?M ?HM4a lE7? l?7:E 7l?H l?H7s ?d=k =d-k ?H=k =kg? ?k7d Adk ?H", -"7=k Agk ?d=M ?-M=d ?H=M =Mg? ?=ld Ald =Hl? Alg ?kN k&?N kN?B ak?N 1k?N :k?N", -" ?B1kN ?:akN ?Qk Qk?& Qk?T Qa?M l?Q ?Ql: lQ?T ?Qls k*?N ?N-k ?Bk*N ?-akN ?1", -"k*N ?:-kN k*N?B1 :-k?aN Qk?* -Q?M ?QTk* ?-QTk ?Ql* ?Ql- l?QT* l-?sQ ?Wk Wk?", -"& Hk?W Wa?k 1W?k ?k:W ?H1Wk ?:HWk ?WM WM?& ?Zk Zk?a l?W ?:lW ?Zl l?Z: Wk?d ", -"-k?W ?HWdk ?Wgk ?W1dk ?:W-k 1H*?Wk g?:Wk WM?d -W?M Zk?d gk?Z ?Wld ?-lW ld?Z", -" ?Zgl ?mk km?& km?B ak?m 7k?m ?k:m ?m7kB ?:mak ?Mm Mm?& Tk?m aM?m ?pl l?:p ", -"lp?T ls?p ?m=k -k?m ?=mkB ?-mak ?=7km Akm 7=B?mk akAm ?Q=k -Q=k ?Tm=k ?-Tkm", -" ?pl= Alp l=?pT lsAp 4W?k ?W4k& Hk?m ?Hmak ?k7W ?:W7k ?H7Wk ?:Hkm 4W?M ?WM4", -"& Z4?M ?Z4ak lW?p l?W:p l?7Z s?Z7l ?vk =k-v vk?H gk?v vk7? Avk ?v7Hk gvAk ?", -"vM ?M-v =k?Z =kZ- lv? Alv ?Zlv yAl 6U< 6!U< Dk 7U=D =D>k 6U=M =U6+M V=6 V6=a l=U =Ul> l=V 7V", -"s= U=d 7U=H =Ug7 =U6dM", -" 6U+=Md V6=H =kgV ld=U l=>Ud =H7V V=gl 6NU< U=m =U7Dm 7Ua=m 6U=Q =UQ6+ V6=Q V=6+Q 7p=U l=p>U Vpl= V=pl> = 7vU=H g7Uv= =Uv6Q =U+v6M =", -"kVv Vv6g= =Ulv lv=>U Z=7V l=yV ?t ?t& ?tD ?ct ?t1 ?t: t1?D t:?c ?tM tM?& V?", -" V?c l?t ?tl: V?l u? ?t* t-? t*?D t-?c ?1t* ?:t- ?t1D* ?t:c- t*?M ?Mt- V?* ", -"V?- ?tl* l?t- l*V? u?- ?tE t&?E ?tH tc?H t1?E ?Et: ?1tH t:?H tM?E ?tM&E V?H", -" Vc?H lE?t ?t:lE lHV? u?H ?td ?dt- tH?d g?t ?1td t:?d ?tH1d ?tg: td?M ?td-M", -" V?d g?V ?tld l-?td ldV? u?g ?t4 ?&t4 t4?D t4?c 7t? ?:7t ?D7t 7t?c t4?M ?t4", -"M& V?4 c4V? l?7t ?t:7l 7V? u?7 t= t=- t=D t=c t=7 At =D7t Atc t=M =Mt- t=V ", -"V?c= l=t Alt 7Vt= Au ?Et4 ?t4&E t4?H ?tHc4 ?E7t ?t:7E ?H7t 7tH?c ?t4ME t4&?", -"ME V4?H V?c4H 7tl?E l?:7tE ?H7V ?Hu7 t=d -=td t=H gt= ?d7t Atd =H7t Agt td=", -"M t=-dM =HV? V=g? ldt= ltAd =Hlt Aug ?tN t&?N tD?N ?Ntc t1?N ?Nt: ?t1DN ?t:", -"cN ?tQ ?&tQ V?Q tc?Q ?Qlt t:?Q Vl?Q u?Q ?Nt* ?Nt- ?tD*N ?ct-N ?t1*N ?t:-N t", -"*1?DN t-:?cN t*?Q ?Qt- V*?Q ?QV- ?tQl* t-Ql? V?lQ* ?-uQ ?tW ?&tW tH?W tc?W ", -"?1tW t:?W ?tH1W ?cWt: tW?Q ?tWQ& ?ZV ?ctZ ?tlW l?Wt: l?tZ u?Z tW?d ?Wt- ?tH", -"W* ?Wgt ?tW1d t-W?: ?H1tW* g?t:W tQ?d t-W?Q ?dtZ ?Zgt l?Wtd l-W?t V?dlZ g?u", -"Z ?tm ?&tm tm?D tc?m ?m7t t:?m ?tm7D ?cm7t t4?Q ?tQ4& V?m cmV? ?pt ?t:p ?pV", -" u?p t=m ?mt- tm=D tmc= 7=tm Atm t=7Dm tcAm t=Q =Qt- =QV? ?mV- tp= Apt V=?p", -" Aup t4?W ?tW4& tH?m ?cWt4 ?W7t 7tW?: 7tH?W 7cW?t ?tW4Q ?W&t4Q ?mtZ V?mZc ?", -"Wtp ?pt:W tZ?p ?Zup ?vt t-?v =Htv ?vgt 7t?v Atv ?vt7H gtAv =Qtv ?vt-Q ?vV Z", -"-t= tp?v lvAt tZl= Auy 3F !3F 3BF a3F 3F. 83F 3F.B a38F 3FK 3F!K T3F a3TF j", -"3F j38F j3TF s3F 3(F +3F 3(FB a3+F (F3. 83+F 3F.(B +8a3F (F3K 3F+K 3(TF T3+", -"F 3(jF j3+F Tj3(F +3sF G3 G3! GH3 Ga3 G3. G83 H3G. G3H8 G3K !KG3 GT3 TaG3 G", -"j3 8jG3 G3Hj sG3 Gd3 +G3 HdG3 gG3 d3G. +3G8 GHd3. G8g3 dKG3 GK+3 G3Td GTg3 ", -"G3dj +3Gj dj3GT g3sG 4F 4F! 4FB 4aF 45F 48F 5B4F 4F5a 4FK !K4F 4TF Ta4F 4jF", -" 8j4F 4F5T s4F 4;F 4+F ;F4B 4Fa; 5;4F >F4 45;FB 4a>F ;F4K +F4K 4FT; 4F+T 4F", -";j 4j>F ;jF4T >Fs4 4G 4G! 4GH 4Ga 4G5 4G8 G54H G54a 4GK GK4! 4GT GT4a 4Gj G", -"84j G54T s4G 4Gd 4+G G;4H g4G G54d >G4 4GH5d >Gg4 4KG; 4K+G GT4d 4GgT G;4j ", -"4G>j 4GT5d sGg4 3FN 3F!N 3FNB 3FaN 3FN. 3F8N 3F.NB 8a3FN Q3F !3QF T3QF a3QF", -" j3QF 83QF QTj3F Q3sF (F3N 3F+N 3FN(B +a3FN 3F.(N +83FN N.(3BF 8a3+FN 3(QF ", -"Q3+F QT3(F +QT3F Qj3(F +Q83F Tj3Q(F s+Q3F GW3 G3W! HWG3 G3Wa W3G. G3W8 GHW3", -". G8HW3 GQ3 G3Q! ZG3 GaZ3 G3Wj G3Q8 GjZ3 ZGs3 WdG3 GW+3 GHWd3 GWg3 GWd3. +G", -"W83 HWdG3. gGW83 G3Qd +3GQ GdZ3 ZGg3 dj3GQ +GQ83 ZGdj3 gZsG3 4mF mF4! mF4B ", -"4Fam 5m4F 4F8m 45mFB amF48 4QF 4FQ! 4FTm 4FQa p4F 48pF 4TpF p4sF m;4F 4F+m ", -"4m;FB amF4+ 45m;F 4m>F 5m;4FB >m4aF 4FQ; 4F+Q 4QT;F 4+QTF 4;pF p4>F p4T;F p", -">4sF 4GW 4!Gm Gm4H Ga4W G54W G84W 4GH5W 4G8Hm 4GQ Q!4G Z4G 4GZa pG4 4Gp8 pG", -"Z4 Z4sG v4G 4+vG 4GvH v4gG 4Gv5 v4>G v4GH5 gv>4G 4GvQ +G4Q v4ZG gGZ4 v4pG p", -"4>G Zpv4G y4G #3F &3F #3FB &3aF 3F#. &38F 3F.#B 8a&3F 3F#K 3F&K #3TF &3TF #", -"3jF j3&F Tj#3F &3sF 3(#F &3+F 3BF#( +a&3F 3F.#( +8&3F #(F.B3 8a&+3F 3FK#( +", -"&3FK T#3(F +T&3F j#3(F &j3+F j#3T(F s+&3F G#3 G&3 H#G3 G3H& #3G. 8&G3 GH#3.", -" G8H&3 #3GK &3GK T#G3 G3T& j#G3 G3&j GTj#3 G&s3 d#G3 +3G& GHd#3 G&g3 Gd#3. ", -"d&3G8 Hd#G3. gG8&3 Gd#3K d&3GK GTd#3 gGT&3 dj#G3 d&jG3 GT#dj3 gsG&3 4#F 4&F", -" #B4F a&4F 5#4F 4F5& 45#FB 48a&F #F4K &F4K T#4F 4FT& j#4F 4F&j 4T5#F 4&sF ;", -"#4F 4F;& 4;#FB a;&4F 45;#F 4&>F 5;#4FB >&4aF 4;#FK ;&F4K 4T;#F 4+T&F ;j#4F ", -">&4jF 4T#;jF s>4&F 4G# 4G& GH4# Ga4& 4#G5 G54& 4GH5# 4G8H& G#4K 4KG& 4#GT G", -"T4& 4#Gj G&4j 4GT5# 4Gs& 4#G; +G4& 4GHd# 4Gg& 4G5d# 4G>& G5H4d# g>4G& 4Gd#K", -" 4+G&K 4GTd# g4GT& 4Gjd# >G4&j dj#4GT gs4G& 3F#N 3F&N 3FN#B a&3FN 3F.#N 8&3", -"FN .B3#FN a&38FN #3QF &3QF QT#3F Qa&3F Qj#3F &j3QF Tj#Q3F sQ&3F 3FN#( +&3FN", -" #BF3(N a&3+FN #3FN.( 8&3+FN 3F#N.B( 3F&N+8a Q#3(F +Q&3F T#3Q(F Q&3+TF j#3Q", -"(F +Q3&jF 3(jFQT# +Q&s3F W#G3 G3W& GHW#3 GaW&3 GW#3. G8W&3 HW#G3. H8WG&3 Q#", -"G3 G3Q& G#Z3 G&Z3 GQj#3 GQ8&3 ZGj#3 Z&Gs3 GWd#3 d&3GW HWdG#3 gGW&3 Wd#G3. G", -"8Wd&3 W#H3Gd. G8Wg&3 GQd#3 +GQ&3 ZGd#3 Z&Gg3 GQ#dj3 d&3GQ8 dj#ZG3 gsGZ&3 m#", -"4F 4Fm& 4m#FB am&4F 45m#F m&F48 5m#4FB 48am&F Q#4F 4FQ& 4QT#F 4Qa&F 4#pF 4&", -"pF p4T#F p&4sF 4m;#F m&F4+ m;#4FB 4+am&F 5m;4#F >m4&F 5B4Fm;# am&>F4 4Q;#F ", -"4+Q&F Q;#4TF a;F4Q& p4;#F p>4&F 4T;p#F s>4p&F 4#Gm Gm4& 4GHW# 4GaW& 4G5W# 4", -"G8W& G5H4W# G5a4W& 4#GQ GQ4& 4GZ# 4GZ& 4Gp# 4Gp& Zp4G# Zp&4G 4Gv# 4Gv& v4GH", -"# gv4G& v4G5# v>4G& 4GHv5# v>Gg4& v4GQ# v&4GQ Zv4G# Zv&4G pv4G# pv&4G pvGZ4", -"# 4Gy& I3 I3! DI3 aI3 I3. 8I3 I3D. D38I I3K !KI3 TI3 T3aI Ij3 83Ij D3Ij sI3", -" I3( +I3 I3D( +3aI 3(I. +38I DI3(. +D8I3 3(IK I3+K I3T( +3TI j3I( +3Ij Ij3D", -"( +Is3 GI3 I3G! J3 Ja3 I3G. G38I J3. J83 I3GK GI3!K JT3 TaJ3 G3Ij Ij3G8 Jj3", -" sJ3 Id3 +3Id Jd3 gJ3 d3I. 83Id d3J. g3J8 I3dK Id3+K TdJ3 JTg3 I3dj Idj+3 d", -"jJ3 g3sJ 4I 4I! 4DI 4aI 4I5 48I 5D4I 5a4I 4IK IK4! 4TI TI4a 4Ij 8I4j 5T4I s", -"4I 4I; 4+I D;4I +D4I 45I; >I4 4D5I; 4D>I 4KI; 4K+I T;4I +T4I I;4j 4I>j I;j4", -"D >Is4 4GI GI4! J4 J4a G54I G84I J45 J48 GI4K 4GI!K J4T 4TJa Gj4I 4G8Ij J4j", -" sJ4 4Id +G4I J4d gJ4 5I4d 4G>I 4dJ5 J>4 4KId 4+GIK 4TJ; gTJ4 Id4j >I4Gj 4d", -"Jj g4sJ I3N !3IN I3DN I3aN N.I3 IN83 DI3N. D8I3N QI3 I3Q! Q3TI Q3aI Q3Ij Q3", -"8I Ij3QD QIs3 3(IN I3+N DI3(N +DI3N I3(N. +I83N I3(DN. D83+IN I3Q( +3QI QDI", -"3( +QDI3 Ij3Q( +QI83 QD3Ij( sI+Q3 WI3 I3W! JW3 WaJ3 I3W. W38I W3J. W8J3 G3Q", -"I GQI!3 ZJ3 JaZ3 W3Ij GQ8I3 Z3Jj s3ZJ W3Id +3WI WdJ3 JWg3 Id3W. +WI83 JWd3.", -" gJW83 Q3Id +GQI3 JdZ3 g3ZJ IdjW3 +WIj3 ZJdj3 sJZg3 4Im 4!Im Dm4I am4I 45Im", -" 8m4I 4D5Im 4D8Im 4QI Q!4I QD4I Qa4I pI4 48pI 4DpI pIs4 4mI; +m4I Im;4D 4+D", -"Im Im;45 4I>m 4D5Im; >Dm4I Q;4I +Q4I 4QDI; 4+QTI 4Ip; p4>I pD4I; p>D4I 4WI ", -"4!WI J4W 4WJa 5W4I W84I 4WJ5 4WJ8 GQ4I 4GQI! ZJ4 ZaJ4 4GpI pG48I Jp4 s4Jp v", -"I4 4+vI Jv4 g4Jv 4Iv5 v4>I v4J5 v>J4 4QvI vI4+Q Z4Jv ZJg4 p4vI pvI>4 pvJ4 y", -"J4 bI3 I&3 DIb3 cI3 I3b. b38I bDI3. 8Ic3 I3bK &3IK b3TI TIc3 b3Ij I3&j Ij3b", -"T cIs3 I3b( b3+I bDI3( +Ic3 bI3(. I&3+8 DI3b(. c+8I3 bKI3( I&3+K bTI3( c+TI", -"3 Ij3b( I&j+3 bT3Ij( sI+c3 bG3 b3G& Jb3 cJ3 G3b. b3G8 b3J. c3J8 G3bK I&3GK ", -"bTJ3 JTc3 b3Gj I&jG3 bjJ3 s3cJ b3Id b3+G bdJ3 g3cJ Id3b. b+G83 Jbd3. cJ8g3 ", -"Id3bK b+G3K JbTd3 cJTg3 Idjb3 Idj&3 Jjbd3 sJgc3 4bI 4I& bD4I c4I b54I b84I ", -"4b5DI 48cI bK4I 4KI& bT4I 4TcI bj4I I&4j 4bT5I c4sI b;4I b+4I 4bDI; 4+cI 4b", -"5I; 4b>I b5D4I; >Ic4 I;K4b I;&4K 4bTI; c4+TI I;j4b >I4bj 4bTI;j c>s4I 4bG b", -"G4& J4b cJ4 b54G bG48 4bJ5 J4c5 4KbG 4bG&K 4bJT cTJ4 bG4j I&j4G 4bJj cJs4 b", -"G4d b+4G 4bJ; cJg4 4bG5d 4b>G J4b5d c4J> 4bGdK 4b+GK J4bTd cJ4gT Idj4b >bG4", -"j J4jbd J>sc4 I3bN &3IN bDI3N I3cN bI3N. I&38N DI3bN. c8I3N b3QI Q3I& bQDI3", -" QIc3 Ij3bQ I&jQ3 bQDIj3 sIQc3 bI3(N I&3+N DI3b(N c+I3N I3(bN. +I3b8N 3(INb", -"D. +I8c3N bQI3( b+QI3 QI3bT( cQ+I3 bQ3Ij( Ij3b+Q Qjb3TI( cQ+sI3 b3WI W3I& b", -"WJ3 JWc3 bGW3. bG8W3 JbW3. cJW83 b3GQ bGQ&3 JbZ3 Z3cJ bGQj3 I&jW3 ZJbj3 sJZ", -"c3 Id3bW b+GW3 JbWd3 cJWg3 bW3Id. Id3bW8 bWdJ3. gJ8cW3 bGQd3 b+GQ3 ZJbd3 Zc", -"Jg3 Id3bWj Id3bQ8 JjdZb3 ZcgsJ3 bm4I Im4& 4bDIm 4Icm 4b5Im Im&48 b5D4Im c45", -"Im bQ4I QI4& 4bQTI 4QcI 4bpI 4Ip& pb4TI pIc4 Im;4b Im&4+ 4bDIm; c4+Im 4b5Im", -"; >I4bm Imb;4D5 c>4Im 4bQI; I;&4Q bQ;4TI c4Q+I pb4I; p>b4I 4bTpI; cp>4I bG4", -"W WI4& 4bJm J4cW 4bG5W 4bGW8 J4b5W cJ45W bG4Q 4bGQ& J4Zb cJZ4 4bpG pbG48 pb", -"J4 c4Jp 4bvI 4Iv& vbJ4 c4Jv vb4G5 v>b4G Jv4b5 cvJ>4 vb4GQ vI&4Q ZJ4vb cvZJ4", -" pvb4G pvI4& Jpv4b cJy4 6F 6!F 6FB 6aF 61F 68F 1F6B 6F1a 6FK !K6F 6TF Ta6F ", -"6jF 8j6F 6F1T s6F 6(F 6+F (B6F +a6F 1(6F 6F1+ 61(FB 6+1aF (F6K +F6K T(6F 6F", -"+T j(6F 6F+j 6T1(F 6+sF 6G 6G! 6GH 6Ga 6G1 6G8 1G6H 1G6a 6GK GK6! 6GT GT6a ", -"6Gj G86j 1G6T s6G 6Gd 6+G GH6d g6G 1G6d 1+6G 6G1Hd 6Gg1 Gd6K 6K+G GT6d 6GgT", -" Gj6d +G6j 6GT1d sGg6 46F 4F6! 6F4B 4F6a 7F 78F 7BF 7aF 6F4K 6!4FK 4F6T 4T6", -"aF 7jF 8j7F 7TF 7sF 6;F 4F6+ ;F6B 6Fa; 7;F 7>F ;F7B >F7a ;F6K 4+6FK 6FT; 4+", -"T6F ;j7F 7j>F T;7F >F7s 4G6 6!4G 6G4H 6G4a 7G 7G8 7GH 7Ga 4K6G 4G6!K 6G4T 4", -"GT6a 7Gj G87j 7GT 7sG 6G; 6+4G G;6H 4Gg6 7Gd 7>G G;7H g7G 6KG; 4+G6K GT6; g", -"46GT G;7j >j7G GT7d sGg7 6FN !F6N NB6F aF6N 1F6N 8F6N 61FNB 68aFN 6QF 6FQ! ", -"QT6F 6FQa 6F1Q 6FQ8 6Q1TF 6QsF (F6N +F6N 6(FNB 6+aFN 61(FN 6+1FN 1(F6NB 1+F", -"6aN Q(6F 6F+Q 6QT(F 6+QTF 6Q1(F 6+Q1F 1Q(6TF s6+QF 6GW W!6G GH6W Ga6W 1G6W ", -"G86W 6G1HW 6G8Wa 6GQ Q!6G Z6G 6GZa 1G6Q GQ68 6GZ1 Z6sG GW6d +G6W 6GHWd 6GgW", -" 6G1Wd 6+G1W 1GH6Wd g61GW GQ6d +G6Q 6GZd gGZ6 6GQ1d 6+G1Q Z61Gd gZ6sG 6mF m", -"F6! mF6B 6Fam 7mF 8m7F mF7B am7F 4F6Q 4Q6!F 6FTm 4Qa6F 7pF p87F pT7F sF7p m", -";6F 6F+m 6m;FB 6+maF m;7F 7m>F 7Bm;F 7>amF 6FQ; 4+Q6F 6Q;TF 6+TmF p;7F >F7p", -" 7pT;F 7p>sF 6Gm 6!Gm Gm6H Ga6m 7GW G87W Gm7H Ga7W 6G4Q 4GQ6! 4GZ6 Z46Ga 7p", -"G 78pG 7ZG sG7Z v6G 6+vG 6GvH gGv6 7vG v>7G vG7H 7Ggv 6GvQ v6+GQ ZGv6 Zv6gG", -" pv7G p>7G 7GZv y7G 69F 6&F 9F6B 6F9a 916F :6F 691FB 6a:F 9F6K &F6K 6F9T 6F", -"T& 6F9j 6j:F 6T91F :6sF 9(6F 6F9+ 69(FB 6+9aF 691(F 6+:F 91(6FB :6+aF 69(FK", -" 6+9FK 6T9(F 6+T9F 6j9(F :6+jF 9T(6jF s:6+F 6G9 6G& 9G6H 9G6a 691G :G6 6G91", -"H 6G:H 6K9G 6KG& 9G6T GT6& 9G6j 6G:j 6GT9j :Gs6 9G6d 9+6G 6G9Hd 6Gg9 6G91d ", -"6+:G 9G16Hd :Gg6 6G9dK 6+G9K 6GT9d g69GT 6Gj9d :G6+j 9GT6dj g:s6G 49F 4F6& ", -"9F4B 4F9a 79F 7:F 9F7B :a7F 9F4K 49&FK 4F9T 49TaF 9j7F :j7F 9T7F sF7: 4F9; ", -"4F9+ 49;FB 49+aF 9;7F >F7: 7B9;F 7:>aF 49;FK 49+FK 49T;F 49+TF 79;jF 7:>jF ", -"7T9;F 7s:>F 49G 6G4& 9G4H 9G4a 7G9 7:G 9G7H :G7H 4K9G 49G&K 9G4T 49GT& 9G7j", -" 7j:G 9G7T 7:sG 9G4d 9+4G 49GH; 49gG 9G7d :>7G 7G9H; 7Gg: 49GdK 49+GK 49GTd", -" g49GT 7G9dj 7:G>j 7GT9d 7sGg: 9F6N &F6N 69FNB 6a9FN 691FN 6F:N 91F6NB :6aF", -"N 6F9Q 6FQ& 6Q9TF 6Qa9F 6Q91F 6Q:F 9Q16TF :Q6sF 69(FN 6+9FN 9(F6NB 9+F6aN 9", -"1(6FN :6+FN 916N(BF 6+a:FN 6Q9(F 6+Q9F 9Q(6TF 6+F9Qa 9Q(6jF :Q6+F QT1(69F s", -"6+:QF 9G6W G&6W 6G9HW 6Ga9W 6G91W 6G:W 9G16HW :G6Wa 9G6Q GQ6& 6GZ9 6GZ& 6GQ", -"9j 6G:Q Z691G :GZ6 6G9Wd 6+G9W 9GH6Wd g69GW 9G16Wd :G6+W 691HGWd g:6GW 6GQ9", -"d 6+G9Q Z69Gd Z6&gG 9GQ6dj :GQ6+ 6GjZ9d Z:g6G 4F9m 6Fm& 49mFB 49amF 9m7F 7F", -":m 7B9mF 7:amF 4F9Q 49Q&F 49QTF 49QaF 7Fp9 7F:p 7p9TF 7sp:F 49m;F 49+mF 9mF", -"6;B amF49+ 79m;F 7:>mF 9m;7BF :>m7aF 49Q;F 49+QF 4QF9T; a;F49Q 7p9;F 7p>:F ", -"p9;7TF :p>7sF 9G4W Gm6& 49GHm 49GWa 9G7W :G7W 7G9Hm 7:GHm 9G4Q 49GQ& 49ZG Z", -"49Ga p97G 7G:p Z97G 7GZ: 49vG 6Gv& v69GH gv69G v97G 7G:v 7v9GH :vGg7 v69GQ ", -"v6&GQ Zv69G Zv6G& 7pGv9 :vG7p 7Zv9G 7:yG 6I 6I! 6DI 6aI 6I1 68I 1D6I 1a6I 6", -"IK IK6! 6TI TI6a 6Ij 8I6j 1T6I s6I 6I( 6+I DI6( +D6I 6(1I 1+6I 6D1I( 6+D1I ", -"I(6K 6K+I 6(TI +T6I 6(Ij +I6j 6DjI( 6+sI 6GI GI6! J6 J6a 1G6I G86I J61 J68 ", -"GI6K 6GI!K J6T 6TJa Gj6I 6G8Ij J6j sJ6 6Id +G6I J6d gJ6 1I6d 8I6d 6dJ1 J6g1", -" 6KId 6+GIK 6TJd gTJ6 Id6j Idj6+ 6dJj g6sJ 4I6 6!4I 6D4I 6a4I 7I 7I8 7DI 7a", -"I 4K6I 4I6!K 6T4I 4TI6a 7Ij 8I7j 7TI 7sI 6I; 6+4I D;6I aI6; 7I; 7>I D;7I >D", -"7I 6KI; 4+I6K TI6; 4+T6I I;7j >j7I TI7; 7>sI 6G4I 4G6I! J46 4aJ6 7GI G87I 7", -"J 7J8 4G6IK 6GK4I! 4TJ6 J46Ta Gj7I 7G8Ij 7JT 7Js 6I4d 4+G6I J6; J4g6 7Id >G", -"7I 7Jd g7J 4Id6K I;K6+G 6TJ; gJ46T Id7j 7>GIj J;7T sJg7 6IN IN6! DI6N 6NaI ", -"6N1I 6N8I 6D1IN 6D8IN 6QI Q!6I QD6I Qa6I 1Q6I Q86I 6QD1I 6QsI I(6N 6N+I 6DI", -"(N 6+DIN 6I1(N 6+I1N 1D(6IN 6+N1aI 6(QI +Q6I 6QDI( 6+QTI 6QI1( 6+Q1I Ij(6QD", -" s6I+Q 6WI 6!WI J6W 6WJa 1W6I W86I 6WJ1 6WJ8 GQ6I 6GQI! ZJ6 ZaJ6 WI6j 6GQ8I", -" J6Z1 ZJs6 WI6d +W6I 6WJd gWJ6 6WI1d 6+W1I J61Wd gJ61W QI6d 6+GQI ZdJ6 ZJg6", -" Idj6W 6+WIj ZJ61d sJ6gZ 6Im 6!Im Dm6I aI6m 7Im 8I7m Dm7I aI7m 6Q4I 4QI6! T", -"I6m 4Qa6I 7pI 78pI pD7I 7psI Im6; +I6m 6DmI; 6+DIm Im7; >m7I 7DIm; 7>DIm QI", -"6; 4+Q6I 6QDI; 6+TIm 7;pI p>7I 7pDI; 7sIp> 6W4I 4WI6! J6m 6aJm 7WI W87I 7JW", -" J87W 4GQ6I Im!6GQ J4Z6 ZJ46a pG7I 7pG8I 7ZJ sJ7Z v6I 6+vI Jv6 g6Jv 7vI v>7", -"I 7Jv 7vJ> 6QvI v6I+Q Z6Jv Jv6gZ pv7I 7vIp> 7vJp yJ7 b6I 6I& 9D6I c6I 6Ib1 ", -":I6 b61DI c6:I bK6I 6KI& 6IbT 6TcI 6Ibj 6I:j b6T1I :Is6 b(6I 6Ib+ b6DI( 6+c", -"I b61I( 6+:I 6DIb1( :c6+I b6I(K b6+IK b6TI( c6+TI b6jI( :I6+j Ij(b6T s:I6+ ", -"b6G 6&bG J6b cJ6 6Gb1 b6:G b6J1 :J6 bK6G b6G&K b6JT cTJ6 6Gbj :Gb6j b6Jj s6", -":J 6Gbd 6+bG b6Jd cJg6 b6G1d 6I:d J6b1d g6:J b6GdK b6+GK J6bTd cJ6gT Idjb6 ", -":Id6j J6jbd sJ6g: 49I 6I4& 9D4I 49cI 7bI 7:I 9D7I 7cI 4K9I 49I&K 9T4I c46TI", -" bj7I 7j:I bT7I sI7c 6Ib; 9+4I 49DI; 6Ic; b;7I :>7I 7bDI; 7Ic> 49I;K I;&6K ", -"49TI; c6;TI 7bI;j 7:I>j 7bTI; 7sIc> b64G 4bG6& J49 J4c6 7bG :G7b 7Jb 7J: 4b", -"G6K I&K49G 49JT cJ46T bG7j 7:Gbj J97T sJ7c 6Gb; I;&6G 49J; J4g9 bG7d :I7d J", -"97d :Jg7 49IdK IdK49+ J49Td cJ6T; 7bGdj 7:Idj 7JbTd g7Js: bN6I 6NI& b6DIN 6", -"IcN b61IN 6I:N 6DIb1N :c6IN 6IbQ QI6& b6QTI 6QcI b6Q1I 6Q:I 6QIb1T :cQ6I b6", -"I(N b6+IN 9D(6IN c6+IN 6I(b1N :I6+N b(6D1IN c6+:IN b6QI( b6+QI bQ(6TI c6Q+I", -" Ij(b6Q :QI6+ b(6Q1TI sI+c6Q 6GbW WI6& b6JW J6cW b6G1W 6W:I J6b1W J6:W 6GbQ", -" b6GQ& J6Zb cJZ6 b6G1Q :GQb6 ZJ6b1 Z6:J b6GWd b6+WI J6bWd cJ6gW 6WIb1d :WI6", -"+ b6WJ1d :Jg6W b6GQd b6+GQ ZJ6bd Zc6gJ b6WIdj :QI6d ZbdJ6j Z:Jg6 6Ibm Im6& ", -"49DIm 6Icm bm7I :m7I 7bDIm cm7I 9Q4I Im&6Q 49QTI c4Q6I pb7I 7I:p 7pbTI 7Icp", -" 49Im; Im&6+ 9Dm6I; c6m+I 7bIm; 7:I>m 9Dm7I; 7c>Im 49QI; I;&6Q 6QIbT; c6QI;", -" 7pbI; :pI7> 7D;p9I 7cp>I 6Gbm Im&6G 49Jm J6cm bG7W :W7I J97W 7W:J 4bG6Q b6", -"G4Q& J4Z9 Zc4J6 pb7G :pG7b 7bJp Z:7J 49vI 6Iv& vbJ6 c6Jv vb7G 7I:v 7bJv :v7", -"J vb6GQ v6IQ& Jv6Zb cv6ZJ 7vbpG :vI7p Jp97v 7Jy: 3FL 3F!L 3FLB 3FaL FL3. 3F", -"8L 3L.FB 8a3FL M3F !3MF M3TF M3aF j3MF M38F TMj3F M3sF (F3L 3F+L 3FL(B +a3F", -"L 3L.(F +83FL (BL3F. 8a3+FL 3(MF M3+F TM3(F aM3+F Mj3(F +M83F Mj3T(F s+M3F ", -"G3L !3GL H3GL a3GL 3LG. 83GL GH3L. G8H3L GM3 M3G! G3HM G3aM MjG3 G38M GTMj3", -" GMs3 d3GL G3+L GHd3L G3gL Gd3L. +G83L Hd3GL. gG83L G3dM +3GM dM3GT GMg3 dM", -"jG3 +GM83 GTMdj3 gsGM3 4FL !F4L LB4F aF4L 5F4L 8F4L 45FLB 48aFL 4MF MF4! TM", -"4F 4FaM 4F5M 4F8M 4T5MF 4MsF ;F4L +F4L 4;FLB a;F4L 45;FL 4F>L 5;F4LB >F4aL ", -"4FM; 4F+M M;F4T aM;4F M;F4j 4M>F 4T5M;F >Ms4F 4GL GL4! GH4L 4LGa 4LG5 4LG8 ", -"4GH5L 4G8HL 4GM 4!GM GT4M Ga4M G54M G84M 4GT5M 4GsM 4LG; 4L+G 4GHdL 4GgL 4G", -"5dL 4G>L G5H4dL g>4GL GM4d +G4M 4GTdM 4GgM 4GM5d 4G>M G5T4dM >Mg4G FL3N 3FN", -"!L 3FNLB a3FLN 3L.FN 83FLN .BL3FN a3F8LN M3QF Q!M3F QTM3F aM3QF QMj3F Q8M3F", -" TMjQ3F sQM3F 3FN(L +3FLN (BL3FN a3F+LN N.(3FL 83F+LN (FLBN.3 3L+N8aF QM3(F", -" +QM3F TM3Q(F +Q3aMF Mj3Q(F Q83+MF 3(MFQTj +QMs3F W3GL W!G3L GHW3L GaW3L GW", -"3L. G8W3L HW3GL. W83GaL G3WM GQM!3 GMZ3 ZGaM3 GQMj3 GQ8M3 ZGMj3 sZGM3 GWd3L", -" +GW3L HWdG3L gGW3L Wd3GL. G83+WL W3HLGd. G8Wg3L dM3GQ +GQM3 ZGdM3 gZGM3 GQ", -"Mdj3 dM3GQ8 dMjZG3 sZGgM3 mF4L 4mF!L 4mFLB amF4L 45mFL 48mFL 5mF4LB 48FamL ", -"4FMm MmF4! MmF4T aMm4F 4MpF p48MF p4TMF sp4MF 4m;FL 4+mFL m;F4LB 4+FamL 5m;", -"4FL >m4FL mL4B5;F amF>L4 MmF4; 4+QMF 4QTM;F aMF4+Q p4M;F >Mp4F M;Fp4T sp4>M", -"F 4LGm 4GW!L 4GHWL 4GaWL 4G5WL 4G8WL G5H4WL amL4G8 GQ4M 4GQM! 4GZM Z4GaM 4G", -"pM pG48M Zp4GM sZ4GM 4GvL v4+GL v4GHL gv4GL v4G5L v>4GL 4GHv5L g4Lv>G 4GvM ", -"vM4+G Zv4GM gZ4GM pv4GM >Mv4G pvGZ4M 4GyM 3F#L 3F&L 3FL#B a&3FL 3L.#F 8&3FL", -" #L.3BF a&38FL #3MF &3MF TM#3F aM3&F Mj#3F M&38F Mj#T3F sM&3F 3FL#( +&3FL #", -"3(LBF a&3+FL #(F3L. 8&3+FL (FLB#3. 3F+L8a& M#3(F M&3+F M#3T(F +T3M&F j#3M(F", -" +M3&jF 3(MFTj# M&3s+F #3GL &3GL GH#3L Ga&3L G#3L. G8&3L H#3GL. H83G&L M#G3", -" G3M& GTM#3 GT&M3 GMj#3 G8M&3 HM#Gj3 sGM&3 Gd#3L d&3GL Hd#G3L gG&3L d#3GL. ", -"G83d&L H#G3dL. G8&g3L dM#G3 dM&G3 GT#dM3 gMG&3 GM#dj3 dM3G&j dMGjH#3 sG&gM3", -" #F4L &F4L 4#FLB 4a&FL 45#FL 48&FL 5B#4FL 5aF4&L M#4F 4FM& 4TM#F 4T&MF 4M5#", -"F 48M&F 5T#4MF s4M&F 4;#FL ;&F4L ;#F4LB 4aF;&L 5;#4FL >&4FL 5#4L;FB 4a&>FL ", -"M;#4F M;&4F 4T#M;F a;F4M& 4M#;jF >M4&F 5FM;4T# s4&>MF G#4L 4LG& 4GH#L 4Ga&L", -" 4G5#L 4G8&L G5#4HL 4GLH5& 4#GM GM4& 4GTM# 4GTM& 4GM5# 4G8M& 4G#H5M s4GM& 4", -"Gd#L 4+G&L G;#4HL g4G&L G5#4dL >G4&L HL5d4G# >G&g4L 4GMd# dM&4G dM#4GT g4MG", -"& dM#4Gj >MG4& 5#dM4GT >M&s4G 3FN#L &3FLN #LN3BF &3FaLN #LN3F. &3F8LN 3LNB#", -"F. 3F&N8aL QM#3F M&3QF TM#Q3F Qa3M&F Mj#Q3F Q83M&F TMQj#3F M&3sQF #(L3FN &3", -"F+LN (FLB#3N 3L+Na&F 3F#LN.( 3L+N8&F (BN.3F#L 8a+F3L&N M#3Q(F +Q3M&F 3(MFQT", -"# Q3aM+&F 3(MFQj# j3+FQ&M TjQ#3(MF M&s3+QF GW#3L G&W3L HW#G3L Wa3G&L W#3GL.", -" W83G&L W3HLG#. HLW&G83 GQM#3 GQ&M3 ZGM#3 Z&GM3 WM#Gj3 M&3GQ8 GMjZ#3 sGMZ&3", -" Wd#G3L G&3+WL W3HLGd# G&Wg3L W3GLd#. GW+38&L 3LH.WdG# GWg38&L GQ#dM3 dM3GQ", -"& dM#ZG3 gMGZ&3 Q#G3dMj W38M+G& dMZjG#3 sGgZM&3 4m#FL m&F4L m#F4LB 4aFm&L 5", -"m#4FL 48Fm&L mL4B5#F am5&4FL Mm#4F Mm&4F 4T#MmF aMF4Q& p4M#F p&4MF 4TMp#F s", -"4Mp&F m;#4FL 4+Fm&L mL4B;#F a;4&mFL 5#4Lm;F m&F>L4 LB;F5m4# am>&4FL 4Q#M;F ", -"M;F4Q& Q#M;4TF MmT&4+F M;#p4F p&4>MF M;p#4TF >&s4pMF 4GW#L 4G&WL Gm#4HL amL", -"4G& G5#4WL m&L4G8 W#4LG5H HL5&4GW 4GQM# Mm&4G Z4GM# Z4&GM pG4M# pG&4M pGMZ4", -"# Z4MpG& v4G#L v&4GL 4GHv#L v&Gg4L 4G5v#L >G4v&L 45v#GHL >&g4vGL vM4G# vM&4", -"G vMGZ4# Z4GvM& vM4pG# >M4pG& ZGvMp4# y&4GM UI3 I3U! DIU3 U3aI I3U. U38I UD", -"I3. U8ID3 IM3 I!M3 VI3 aIV3 U3Ij 83IM IjV3 VIs3 I3U( U3+I UDI3( U+DI3 UI3(.", -" U+8I3 DI3U(. +DIU83 M3I( +3IM I3V( +IV3 IM3j( U+jI3 VIj3( sIV+3 UG3 G3U! J", -"U3 UaJ3 G3U. U3G8 U3J. U8J3 U3GM IM3G! VJ3 VaJ3 U3Gj UG8M3 VjJ3 s3VJ U3Id U", -"3+G UdJ3 JUg3 Id3U. U+G83 JUd3. gJU83 I3dM IdM+3 J3Vd g3VJ IdMj3 IdM83 JjVd", -"3 gVJs3 4UI U!4I UD4I Ua4I U54I U84I 4U5DI 4U8aI 4IM 4!IM V4I 4aVI Uj4I 8I4", -"M 4IV5 V4sI U;4I U+4I 4UDI; 4U+aI 4U5I; 4U>I U5D4I; >I4Ua I;4M +I4M 4IV; 4+", -"VI IM;4j 4I>M V45I; >IV4 4UG 4!UG J4U 4UJa U54G UG48 4UJ5 4UJ8 UG4M 4UGM! J", -"4V JaV4 UG4j 4UG8M V4J5 VJs4 UG4d U+4G 4UJ; J4gU 4UG5d 4U>G J4U5d >UJ4 Id4M", -" IdM4+ V4J; J4gV IdM4j >MG4U J4V5d J4V> I3UN U!I3N UDI3N UaI3N UI3N. U8I3N ", -"DI3UN. 8I3UaN U3QI IM3Q! QIV3 VQaI3 IM3Qj UQ8I3 VQIj3 sIVQ3 UI3(N U+I3N DI3", -"U(N +I3UaN I3(UN. +I3U8N D3UNI(. +3UND8I IM3Q( U+QI3 VQI3( V+QI3 UQ3Ij( Ij3", -"U+Q Ij3VQ( V+QsI3 U3WI UGW!3 UWJ3 JUWa3 UGW3. UG8W3 JUW3. J8UW3 U3GQ UGQ!3 ", -"Z3VJ ZJVa3 UGQj3 UGQ83 ZJVj3 sJZV3 Id3UW U+GW3 JUWd3 gJUW3 UW3Id. Id3UW8 UW", -"dJ3. gUWJ83 IdMW3 U+GQ3 ZJVd3 gVZJ3 Id3UWj Id3UQ8 VZdJj3 sJZgV3 Um4I Im!4U ", -"4UDIm 4UaIm 4U5Im 4U8Im U5D4Im U8m4aI UQ4I IMm4! 4QVI V4QaI 4UpI pU48I pIV4", -" Vps4I Im;4U 4U+Im 4UDIm; U+m4aI 4U5Im; >I4Um ImU;4D5 4Ua>Im IMm4; IMm4+ V4", -"QI; V4+QI pU4I; >MIp4 Vp4I; V>p4I UG4W 4UGW! 4UJm J4UWa 4UG5W 4UGW8 J4U5W J", -"48UW UG4Q 4UGQ! VZJ4 ZJ4Va 4UpG pUG48 J4Vp JpVs4 4UvI vU4+G vUJ4 Jvg4U vU4G", -"5 v>U4G Jv4U5 J>v4U 4IvM vIM4+ J4Vv VvJg4 pvU4G >Mv4I JpVv4 J4yV UIb3 U3I& ", -"bUDI3 UIc3 bUI3. I&3U8 UDIb3. cU8I3 b3IM I3M& bIV3 VIc3 IM3bj IM&83 VbIj3 s", -"IVc3 bUI3( I&3U+ UDIb3( cU+I3 UI3b(. U+8I&3 3(U.bDI U+8cI3 IM3b( IM&+3 VbI3", -"( Vc+I3 bM3Ij( IM3b+j Ij3Vb( Vc+sI3 b3UG U3G& bUJ3 JUc3 bGU3. bG8U3 JbU3. c", -"JU83 b3GM IM&G3 VbJ3 c3VJ bGMj3 bG8M3 JjVb3 sJVc3 Id3bU b+GU3 JbUd3 cJUg3 U", -"G3bd. I&3U8d bdUJ3. gcUJ83 IdMb3 IdM&3 VJbd3 gVJc3 IM3bdj Id3b8M VdbJj3 sJc", -"gV3 bU4I U&4I 4bUDI 4UcI 4bU5I 4b8UI b5U4DI c4U5I bM4I IM4& 4bVI cIV4 4bM5I", -" IM&48 V4b5I c4VsI 4bUI; I;&4U b;U4DI c4U+I b5U4I; >I4U& 45b;UDI c>4UI IM;4", -"b IM;4& V4bI; c4V+I 4bMI;j >Mb4I I;jV4b V>c4I bG4U UG4& 4bJU cUJ4 4bGU5 4bG", -"U8 J4bU5 cJ4U5 bG4M IM&4G JbV4 VJc4 4bGUj 4bG8M J4Vb5 sJ4Vc 4bGUd 4b+UG J4b", -"Ud cJ4gU bG54Ud >bG4U 4bdJ5U J>c4U IdM4b IdM4& J4Vbd gV4cJ 4bMIdj >Mb4G J4b", -"V5d J>Vc4 bUI3N I&3UN UDIb3N cUI3N UI3bN. U83I&N D3UNbI. U8Ic3N IM3bQ IM&Q3", -" VbQI3 cQVI3 bQUIj3 IM3bQ8 Ij3VbQ cQVsI3 UI3b(N U+3I&N D3UNbI( U+Ic3N 3(U.b", -"IN b3U+8IN UDb.3(IN UIc3+8N bQ3IM( IM3b+Q bQIV3( V+IcQ3 Qjb3IM( b3+Q8IM IjV", -"3bQ( s+cQVI3 bGUW3 UG&W3 JbUW3 cJUW3 UG3bW. I&3UW8 bWUJ3. J8UcW3 bGQU3 IM&W", -"3 ZJVb3 ZcJV3 IM3bWj IM3bW8 JjVZb3 ZcVsJ3 bWUId3 Id3UW& bWUJd3 gJUcW3 Wdb3U", -"G. b3+GUW8 W3J.bdU gWJ8cU3 Id3bWM Id3UQ& VJdZb3 ZcJgV3 IdWjbM3 +WUjI&3 djJ3", -"ZbV g3sJZcV 4bUIm Im&4U bmU4DI c4UIm b5U4Im 4U8Im& 45bmUDI 4U8cmI IMm4b IMm", -"4& V4bQI c4VQI pb4IM pU&4I Vp4bI cpV4I 4bUIm; 4U+Im& Imb;4UD 4U+cmI Imb;4U5", -" Im&>U4 bU4I5mD; c4U>Im 4bQIM; 4b+IMm 4bQV;I c4IV+m IM;pb4 >I4pU& pbIV4; V>", -"4cpI 4bGUW 4UGW& J4bUW cJ4UW bG54UW bG84UW 4bWJ5U c4UJ8m 4bGUQ IM&4W ZJ4Vb ", -"Zc4VJ pbG4U pUG4& JpV4b cpJV4 vb4UG vU&4G Jv4bU cvJ4U 4bGvU5 >I4vU& vb4J5U ", -"J>4cvU vbM4G vIM4& VvJ4b cvVJ4 pb4vIM >I4vbM Vv4Jpb yJVc4 6kF kF6! kF6B 6Fa", -"k 1k6F 6F8k 61kFB akF68 6MF MF6! 6FTk 6FaM l6F 68lF 6TlF sFl6 k(6F 6F+k 6k(", -"FB akF6+ 61k(F 6+1kF 1k(6FB 6+1akF M(6F 6F+M 6Tk(F 6+TkF 6(lF 6+lF l6T(F ls", -"6+F 6Gk 6!Gk Gk6H Gk6a 61Gk Gk68 6G1Hk 6G8Hk 6GM 6!GM GT6M Ga6M lG6 6Gl8 6G", -"lH s6lG Gk6d +k6G 6GHdk 6Ggk 6G1dk 6+G8k 1GH6dk g61Gk GM6d +G6M 6GTdk 6GgM ", -"6Gld 6+lG lG6Td g6lG 4kF kF4! kF4B 4Fak 7kF 8k7F kF7B ak7F 4F6M 4kM!F 4FTk ", -"4TkaF 7lF 78lF lF7T sF7l 4Fk; 4F+k k;F4B ak;4F k;7F 7k>F 7Bk;F 7>akF 6FM; 4", -"+kMF 4Tk;F aM;6F 7;lF >F7l 7lT;F l>7sF 4Gk 4!Gk Gk4H Ga4k 7Gk G87k Gk7H Ga7", -"k 6G4M 4GkM! GT4k 4GTak lG7 l87G 7GlH lG7s Gk4d +G4k 4GkH; 4Ggk Gk7d 7G>k 7", -"GHdk 7Ggk GM6; 4+G6M 4GTdk g4kGT 7Gld 7>lG 7GTld lGg7 kF6N 6!kFN 6kFNB akF6", -"N 61kFN 68kFN 1kF6NB 68FakN 6FQk 6Qk!F 6QTkF 6QakF 6QlF l6Q8F l6QTF ls6QF 6", -"k(FN 6+kFN k(F6NB 6+FakN 1k(6FN +kF68N 1k6(NBF 6F1+akN 6Qk(F 6+QkF Qk(6TF a", -"kF6+Q l6Q(F l+6QF 6QTl(F s6Ql+F Gk6W 6GWk! 6GHWk 6GaWk 6G1Wk 6G8Wk 1GH6Wk G", -"8k6Wa GQ6M 6GQM! 6GZk Z6Gak 6GlW lG6W8 Z6lG lZs6G 6GWdk 6+GWk GkH6Wd g6GWk ", -"1GW6dk +Gk6W8 61GkHWd 6G8gkW 6GQdk 6+GWM Z6Gdk gZ6Gk lG6Qd l+G6W lZ6Gd glZ6", -"G 4Fkm kmF6! kmF4B akm4F km7F 78kmF 7BkmF 7akmF 4FQk 4Qk!F 4QkTF aMm6F lF7p", -" 7lp8F 7lpTF 7slpF km;4F 4+kmF 6mFk;B akF6+m 7km;F 7>mkF km;7BF >km7aF 4Qk;", -"F 4+QkF kmF6T; akF4+Q 7lp;F l>p7F l;p7TF 7spl>F Gk4W 4GkW! 4GkHm akm4G Gk7W", -" 7GW8k 7GHWk 7GaWk GQ4k 4GQk! 4GZk Z4kGa 7plG 7pGl8 lG7Z 7sGlZ 4Gvk v6+Gk v", -"6GHk gv6Gk vk7G 7>Gvk 7vGHk g7vGk 6GvM v6M+G Zv6Gk Z4kgG lG7v l>G7v lvZ7G l", -"Gy7 9k6F 6Fk& 69kFB akF6& 691kF 6k:F 91k6FB :6akF 6F9M 6FM& 6T9kF 6T&kF 69l", -"F :6lF l69TF ls:6F 69k(F k&F6+ 9k(6FB 6+9akF 91k6(F :6+kF 916k(BF akF:6+ 6M", -"9(F 6+M9F 9T(6MF k&F6+T l69(F l:6+F 6T9l(F s:6l+F 69Gk Gk6& 6G9Hk 6Gak& 6G9", -"1k 6G:k 9G16Hk :G6Hk 9G6M GM6& 6GT9M 6GTk& 6Gl9 l6:G lG69H lsG:6 6G9dk dk&6", -"G 9GH6dk g69Gk 9G16dk :G6+k 691HGkd g:6Gk 6GM9d dM&6G 9GT6dM g6M9G lG69d l:", -"G6+ 6GTld9 gl:6G 9k4F 4Fk& 49kFB 49akF 9k7F :k7F 7B9kF 7:akF 4F9M 49M&F 49T", -"kF 49aMF lF79 lF7: 7l9TF 7sl:F k;F49 k;&4F 49Fk;B akF49+ 79k;F 7:>kF k;F7B9", -" :>F7ak 49M;F M;&6F k;F49T aMF49+ 7l9;F l>7:F l;97TF 7s:l>F 9G4k Gk4& 49GHk", -" 49Gak 9G7k 7k:G 7G9Hk 7:GHk 9G4M 49GM& 49GHM 49GaM l97G 7:lG 7GTl9 7sGl: 4", -"9Gdk dk&4G 9G;4Hk g49Gk 7G9dk 7:G>k 9G;7Hk g7:Gk 49GdM M;&6G 9GT4dk g49GM l", -"G79d l>G7: 7G9lH; gl7:G 69kFN k&F6N 9kF6NB 6aFk&N 91k6FN :6kFN 916kNBF akF:", -"6N 6Q9kF 6Q&kF 9QT6MF akF6Q& l69QF :Q6lF 6Q9lTF ls6:QF 9k(6FN 6+Fk&N 9k6(NB", -"F ak6&+FN 916k(FN 6+k:FN NB1F9k6( ak:F6+N 9Q(6MF k&F6+Q QT6F9M( 6F+Q9aM 6Q9", -"l(F l+6:QF 69l(QTF l6:Qs+F 6G9Wk 6G&Wk 9GH6Wk Gak6W& 9G16Wk :G6Wk 691HGkW 6", -"Ga:Wk 6GQ9M 6GQk& Z69Gk Z6&Gk lG69W :GQl6 lZ69G Z:l6G 9GW6dk +Gk6W& 69HkGWd", -" 6G&gkW 691WGkd 6+G:Wk GH1d69Wk g6G:Wk 9GQ6dM 6GQdk& 6GMZ9d Z6Gg9M 6GQld9 :", -"G6l+W lG6Z9d Z:6glG kmF49 km&4F 49FkmB akF6m& 79kmF 7:kmF kmF7B9 :mk7aF 49Q", -"kF Mm&6F kmF49T akF49Q 7lp9F :pl7F p9l7TF :pl7sF 49mk;F kmF49+ km6;9FB ak6m", -";&F km;79F :mk7>F km7B9;F ak:m7>F k;F49Q k;F4Q& Tk9;4QF aM9m4+F l;97pF :p7l", -">F l97Tp;F >F7s:pl 49GWk km&4G 9Gm4Hk 49Gakm 7G9Wk 7:GWk 9Gm7Hk 7Gk:Hm 49GW", -"M Mm&6G Z49Gk Z4kG& 7pGl9 :pG7l 7Zl9G 7Z:lG v69Gk v6&Gk 49GvkH g4Gvk& 7v9Gk", -" :vG7k v9G7Hk g7G:vk v6M9G v6MG& Z4Gv9M Z4Gg9M lv79G lv:7G 7Z9lvG yl7:G 6UI", -" 6!Ik Dk6I Ua6I 1U6I U86I 6U1DI 6U8aI 6IM 6!IM V6I 6aVI lI6 68lI V6lI s6lI ", -"6(Ik U+6I Ik(6D 6U+aI Ik(61 6U+1I 6D1Ik( 1U+6aI 6(IM +I6M 6IV( 6+VI 6Il( 6+", -"lI Vl6I( lsI6+ 6UG 6!UG J6U 6UJa 1U6G UG68 6UJ1 6UJ8 UG6M 6UGM! J6V JaV6 6U", -"lG lG6U8 lJ6 s6lJ UG6d U+6G 6UJd J6gU Idk61 Idk68 J61Ud gJ61U Id6M IdM6+ Vd", -"J6 J6gV 6Ild l+G6U J6ld g6lJ 4Ik 4!Ik Dk4I aI4k 7UI U87I Dk7I Ua7I 6I4M 4Ik", -"M! 4IV6 V46aI lI7 l87I 7VI lI7s U;6I +I4k Ik;4D ak;4I U;7I 7I>k 7UDI; 7>UaI", -" IM6; IM;6+ 6IV; V4+6I 7Il; 7>lI V;7I 7IV> 6U4G 4UG6! J4k 4aJk 7UG UG78 7JU", -" J87U 4UG6M Ik!4GM V4J6 J4V6a 7UlG 7UGl8 7Jl sJ7V UG6; Idk4+ 4dJk J4gk UG7d", -" >U7G Jk7d >k7J Idk4M 4+kIdM V6J; gV4J6 7Ild l>G7U ld7J 7Jgl 6NIk IkN6! IkN", -"6D 6UaIN IkN61 6U8IN 6D1IkN akN68I UQ6I 6UQI! 6QVI V6QaI 6QlI lI6Q8 Vl6QI l", -"sI6Q Ik(6N 6U+IN 6D(IkN akN6+I 1U(6IN 6UN1+I 6(1UDIN 6NU+1aI 6UQI( 6U+QI V6", -"QI( V6+QI lI6Q( l+I6Q V6QlI( sIQV6+ UG6W 6UGW! 6UJW J6WUa 6UG1W 6UGW8 J61UW", -" J68UW UG6Q 6UGQ! J6Zk ZJ6Va 6WlI lWI68 Z6lJ lJZs6 Idk6W 6U+WI J6WUd gJ6UW ", -"1UW6Id 6W8Idk 6UWJ1d J6Wg1U Idk6Q 6U+GQ ZJ6Vd gV6ZJ lWI6d l+W6I lJZ6d glJZ6", -" Um6I Ikm6! Ikm4D akm4I Um7I 7U8Im 7UDIm 7UaIm QI4k IMm6! 6IVm V6maI 7plI 7", -"pU8I 7IVp 7sIVp Ikm6; Ikm4+ 6DmIk; 4+DIkm 7UIm; 7>UIm Ikm7D; >Im7Ua Ik;4Q I", -"Mm6+ V6mI; V6+Im 7pUI; l>I7p 7VpI; 7V>pI UG6m 4WIk! 4WJk J4kWa UG7W 7UGW8 J", -"k7W 7JUW8 IMm6G Ik!4GQ J4Zk ZJ4ak 7WlI 7pUG8 Jp7V Jpl7s 4Ivk v6U+G v6Jk Jv6", -"gU vU7G 7vU>G 7UJv J>k7v 6IvM v6I+M J6Vv Vv6gJ lI7v lvI7> 7Jlv 7Jyl t6I 6It", -"& 6DtI tIc6 6It1 t6:I t61DI t:c6I 6ItM IM6& tIV6 cIV6 t6lI l6:I ltV6I u6I 6", -"It( 6+tI t6DI( tc6+I t61I( t:6+I 6D1tI( :c6t+I t6IM( t+6IM Vt6I( t+V6I lt6I", -"( lt+6I Vt6lI( 6+uI tG6 6Gt& tJ6 c6tJ 6Gt1 t6:G t6J1 J6t: 6GtM tG6M& VtJ6 V", -"Jc6 l6tG t:Gl6 J6lt uJ6 6Gtd 6+tG J6td g6tJ tG61d t:G6+ tJ61d gtJ:6 tG6dM t", -"+G6M tdVJ6 gV6tJ ltG6d t+Gl6 lJt6d gJu6 t4I 4It& 4DtI tIc4 7tI 7It: tD7I 7I", -"tc 4ItM t4IM& tIV4 tc4VI lI7t 7:lI Vt7I u7I 4It; 4+tI t4DI; tc4+I 7It; 7It>", -" 7tDI; t>7cI t4IM; t4+IM t4VI; t4V+I 7tlI; l>I7t 7VtI; 7>uI t4G 4Gt& tJ4 cJ", -"t4 7tG 7:tG 7Jt tJ7c 4GtM t4GM& VJt4 tJ4Vc lG7t 7tGl: tJ7V uJ7 4Gtd 4+tG J4", -"td g4tJ 7Gtd 7>tG td7J 7Jgt t4GdM t4+GM tJ4Vd gt4VJ 7tGld t>G7l lJ;7t g7uJ ", -"6ItN t6I&N t6DIN tc6IN t61IN t:6IN 6D1tIN :I6tcN 6QtI tQ6I& tQV6I tcQ6I tQ6", -"lI t:Q6I Vl6tQI 6QuI t6I(N t+6IN 6DIt(N c6It+N 6I1t(N :I6t+N 61t(DIN t6:Ic+", -"N tQ6I( t+Q6I V6ItQ( t+Ic6Q lI6tQ( t+6:QI l6tQVI( u6+QI 6GtW tG6W& J6tW tcW", -"J6 tG61W t:G6W tJ61W :Jt6W 6GtQ tGQ6& Z6tJ Zc6tJ tGQl6 t:G6Q lJZt6 ZJu6 tG6", -"Wd t+G6W tJ6Wd gtJ6W 6WItd1 t+6:WI J61tWd :J6gtW tGQ6d t+G6Q tZJ6d gtZJ6 tW", -"6lId t+6:GQ tZ6lJd ug6ZJ 4Itm t4Im& t4DIm tc4Im 7Itm t:m7I 7tDIm 7ctIm 4QtI", -" t4QI& t4VQI tc4QI 7Itp :pI7t tp7VI 7puI t4Im; t4+Im 6Dmt;I t+Ic6m 7tIm; t>", -"7Im 7DItm; 7cIt>m t4QI; t4+QI tQIV6; t4IcQ; tp7I; tp>7I 7VItp; u7Ip> 4GtW t", -"4GW& J4tW tJ4cW 7GtW 7tG:W tW7J 7Jt:W 4GtQ t4GQ& ZJt4 tZ4cJ 7ptG tpG7: 7JtZ", -" 7ZuJ v6tG tv4+G t4Jv cv6tJ tG7v :vI7t 7Jtv g7tJv tv4GQ t4+GQ Vv6tJ cvVJ6 l", -"vt7G :vI7l lvJ7t yJu7 e= 5e=B =a>e =eK +e=K =Te +T=e =je =j>e 5T=e s=e 4G", -"< 4!G< 4He Ga4e G5< G84e H54e H84e 4KG< 4G= f5=H f>g= f=K f+=K =Tf gf=T =jf =jf> f5=T sf= m =B5em >e=am", -" =Qe +Q=e Qe=T Qa=e p=e >ep= pe=T sep= 4We 4!We Hf= =H", -"fv5 g=fv> =Qf =+fQ Z=f Zfg= fp= p=f> fpZ= yf= ,e =B5,e >e-=a ,e=K -e=K ,T=e =e-T ,j=e =", -"e-j =T5,e -=se ,4G 4&,G 4G,H 4G,a 4G,5 4G,8 ,4GH5 ,4GH8 ,K4G ,4G&K 4G,T ,4G", -"T& 4G,j <&j4G ,4GHj ,4sG f=, f-= fH=, f-g= =,f5 ->f= =Hf,5 g=f-> f,=K =Kf- ", -"=,fT f-=T =,fj f-=j =Hjf, f-s= e-=m emB=5, =a->em ,Q=e =e-Q =QT,e =Q-Te =ep, pe-= p=T,e -ps=e 4G,", -"W We4& ,4GHm -v= fv5=H, f>-g=v =,fQ f-=Q f=Z,", -" f-Z= p,f= f-p= fpZ=, f-y= I< I 5D=I =D>e =IK +I=K", -" =TI +T=I =Ij >I=j 5T=I s=I G<4I I J=5 J>= f", -"I=K =If+K J=T =TgJ fj=I f>=Ij J=j s=J Im=I =D5Im >eD=m =QI +Q=I QD=I Qa=I p", -"=I p>=I pD=I sp=I WI4e I=I v=J5 v>J= fQ=I =Qf+", -"I Z=J gZJ= =Ifp fp>=I Jp= yJ= h< h<& hD< hc< h<. h8< D= h5=D c=h> h=K =Kh- h=", -"T hc=T h=j =jh> h5=T hs= h4G 4Gh& hJ4 cJh4 4Gh5 4Gh8 J4h5 J4h8 4GhK h4G&K J", -"4hT cJ4hT 4Ghj h48Gj J4hj h4sJ h=f f-h= J=h i= f=h5 f>h= h5J= i>= =Khf h=f-", -"K hJ=T i=T hf=j h=jf> hJ=j is= h=hm h=5Dm c=h>m h=Q h-=Q hQ=D hc=Q hp= h=-p =", -"Dhp s=hp h4W 4Wh& J4hW c4hW 4Wh5 4Wh8 J5h= J=hv5 v>i= =Qhv h=Q-v hZ= iZ= h", -"=fp fp-h= Z=hp yi= 6e 6e! 6eB 6ae 6e1 68e 6B1e 1a6e 6eK eK6! 6Te Te6a 6ej 8", -"e6j 1T6e s6e 6e* 6+e *B6e +e6a 1e6* 1+6e 6e1*B 6+e1a e*6K 6K+e Te6* +T6e ej", -"6* +e6j 6Te1* 6+se 6G< 6!G< 6He Ga6e 1G< G86e 1H6e Ga1< 6KG< 6Ge7 =B7e 7a>e 6e=K =6+eK 6T=e =T6+e ", -"7e=j >j7e 7e=T >e7s 6G4e 4G6 7fH g7f =Kf6 f=6+", -"K f6=T g=f6T 7fj fj7> 7fT sf7 6eN eN6! eN6B 6Nae 6N1e 6N8e 6e1NB 68eaN 6Qe ", -"Q!6e Qe6T Qa6e 1Q6e Q86e 6Qe1T 6Qse e*6N 6N+e 6e*NB 6+eaN 6e1*N 6+e1N 1eN6*", -"B aeN68* Qe6* +Q6e 6QeT* 6+QTe 6Qe1* 6+Q1e 1Qe6T* s6e+Q 6We 6!We He6W Wa6e ", -"1W6e W86e 6He1W 6H8We GQ6e 6GQm7e 7=emB 7ae>m 6Q=e =Q6+e =Q6Te =Qa6e 7ep= 7p>e 7p", -"e=T 7sep= 6W4e 4We6! He6m aem6G 7We W87e He7W Wa7e 4GQ6e 7v fv7H gf7v f6=Q =Qf6+ fvZ6 Z", -"f6g= 7fp 7pf> 7Zf y7f ?e ?e& ?Be ?ae ?1e ?:e 1e?B :e?a ?eK e&?K ?Te Te?a ?j", -"e :e?j 1T?e s?e ?e* ?-e *B?e -a?e 1e?* :e?- ?B1e* ?:-ae e*?K -e?K Te?* ?e-T", -" ej?* ?e-j ?T1e* ?-se ?G ?G& ?GH ?Ga ?G1 ?:G 1G?H :G?H ?GK G&?K ?GT GT?a ?G", -"j :G?j 1G?T s?G ?f ?f- ?fH g?f ?f1 :f? f1?H :fg? ?fK ?Kf- ?fT ?Tgf ?fj ?j:f", -" f1?T s?f ?4e 4e?& 4e?B 4a?e 7?e 7:e ?B7e 7e?a 4e?K ?4e&K 4T?e ?T4ae 7e?j 7", -"j:e 7e?T 7?se ?=e =e?- ?B=e =e?a 7e?= Ae ?=7eB Aae ?e=K ?-=eK =e?T ?-T=e =e", -"?j Aje ?T7=e Ase ?G4 4G?& 4G?H 4G?a ?G7 7:?G 7G?H 7G?a 4G?K ?G4&K 4G?T ?GT4", -"a 7G?j ?:G7j 7G?T ?G7s ?f= f-?= =H?f ?fg= 7f? Af ?H7f Agf =K?f ?f-=K =T?f ?", -"fTg= =j?f Afj ?T7f Asf ?eN e&?N eN?B ae?N 1e?N ?N:e ?B1eN ?:aeN ?Qe Qe?& Qe", -"?T Qa?e 1Q?e :e?Q ?Q1Te ?Qse e*?N -e?N ?Be*N ?-aeN ?1e*N ?:-eN 1e*?BN :-e?a", -"N Qe?* ?e-Q ?QTe* ?-QTe ?Q1e* ?:Q-e 1Qe?T* s?-Qe ?GW G&?W He?W Ga?W 1G?W :G", -"?W ?G1HW ?:GWa ?GQ GQ?& ?ZG Ze?a 1G?Q :G?Q Z1?G sG?Z ?fW f-?W fH?W ?Wgf f1?", -"W ?W:f ?f1HW g?:fW ?fQ f-?Q ?Zf ?fZ- f1?Q ?Q:f ?jZf ?Zsf ?me em?& em?B ae?m", -" 7e?m :e?m ?m7eB ?:mae 4Q?e ?Q4e& Te?m ?Qa4e ?pe 7e:p pe?T se?p =e?m ?e-m ?", -"=emB ?-mae ?=7em Aem 7=e?mB aeAm =e?Q ?-Q=e ?Tm=e ?-Tem pe?= Ape ?p=Te spAe", -" ?Gm Gm?& Gm?H Ga?m 7G?W :G?m ?G7Hm ?:GHm 4G?Q ?GQ4& Z4?G ?Z4Ga ?pG ?G:p ?G", -"7Z sG?p ?vf -v?f fv?H gf?v 7f?v Afv ?v7fH gfAv =Q?f ?fQ-v ?fZ= g?Zfv ?pf Ap", -"f 7f?Z yAf 6I< 6!I< 6De De6a 1I< 8I6e 1D6e D86e 6KI< I=I 7D=I 7D>e 6I=K =I6+K 6T=I =TI6+ 7I=j 7>I=j 7T=I =I7s 4G6I< 4G6I 7Jf J>7f =If6K f6+=IK J6=T J=g6T fj7I 7", -"f>Ij =T7J 7Jsf 6NI< II=m 7De=m 7>Dem 6", -"Q=I =QI6+ =QD6I =Qa6I 7p=I p=I7> p=D7I s=I7p I 7vJ= J>=7v =Qf6I =Q+v6I Z6J= Z=Jg6 7Ifp 7fp>I Z=7", -"J 7Jyf h? h?& h?D ?ch h?1 h:? ?Dh1 ?ch: h?K ?Kh& h?T hT?c h?j ?:hj ?Dhj hs?", -" h?* h?- h*?D h-?c ?1h* ?:h- ?D1h* h:?c- ?Kh* ?Kh- h*?T ?-hT h*?j ?-hj ?Djh", -"* h?s- h?G h&?G ?J ?Jc ?Gh1 ?Gh: ?J1 ?J: ?KhG ?G&hK ?JT cJ?T ?Ghj ?:Ghj ?Jj", -" s?J ?fh h-?f ?Jf i? h1?f ?fh: J1?f i?: ?Khf ?fh-K hT?f i?T hj?f ?fjh: Jf?j", -" i?s h?4 ?4h& ?Dh4 h4?c 7h 7h: 7hD 7hc ?Kh4 h?4&K ?Th4 ?ch4T 7hj 7:hj 7hT h", -"s7 h=? ?-h= h?=D ?ch= 7h= Ah =D7h Ahc =Kh? h=?-K h?=T c=?hT =j7h Ahj =T7h A", -"hs ?Gh4 ?G4h& ?J4 c4?J 7hG 7Gh: ?J7 7c?J ?G4hK h4&?GK J4?T ?Jc4T 7Ghj 7h:Gj", -" hT7J 7Jhs ?fh= h=?f- ?J= i?= 7hf Ahf 7f?J Ai h=?fK ?f-h=K =T?J =Ti? hj7f h", -"fAj =j?J Ais h?N ?&hN hN?D hN?c ?1hN hN?: ?D1hN h:?cN h?Q h&?Q ?QhT hQ?c ?Q", -"h1 ?:hQ ?QDh1 hQs? ?*hN hN?- ?D*hN ?ch-N h?1*N h:?-N h1*?DN ?c-h:N h*?Q ?-h", -"Q ?QDh* ?cQh- h?Q1* h:Q?- ?Q*h1T hs?-Q h?W h&?W ?JW hW?c ?Wh1 ?:hW J1?W ?W:", -"J ?GhQ ?GQh& hZ? ?chZ ?Whj h:W?Q h1?Z s?hZ hW?f ?-hW Jf?W i?W ?fh1W h:W?f ?", -"Jf1W ?:iW hQ?f ?fQh- ?fhZ i?Z ?fQh1 :fQh? hZ?f1 s?iZ h?m h&?m ?Dhm hm?c 7hm", -" ?:hm 7Dhm hm7c ?Qh4 h?Q4& ?Thm ?cQh4 hp? h:?p hT?p s?hp ?=hm ?-hm ?Dmh= c=", -"?hm 7=hm Ahm 7h=Dm hcAm h?=Q h=Q?- h=Q?D c=Qh? h=?p Aph hp?=D hpAs ?Ghm ?Gm", -"h& ?Jm cJ?m 7hW 7:hW hW7J hW7c ?GQh4 ?G&h4Q h4?Z hZ?c4 hW?p hp?:G hZ7 7Zhs ", -"hv? h?-v ?Jv i?v hv7 Ahv 7Jhv Aiv hQ?v hv?-Q ?Zhv ?Ziv ?phv hpAf 7Zhv Aiy <", -"eL L =B5", -"eL >e=aL =Me +M=e Te=M aM=e 5M=e =M>e =T5Me se=M 4LG< 4GLf= =Hf5L g=f>L =Mf =+fM fT=M gf=M f5=M =Mf> =HMf5 =Msf eLe=mL em", -"L=B5 =am>eL Qe=M =Q+Me =QTMe =QaMe pe=M p=>Me p=TMe s=pMe 4LWe 4We!L 4HeWL ", -"4WaeL 4We5L 4W8eL v=L fv5=HL f>vg=L fv=M =Qf+M =MZf g=MZf =M", -"fp fp>=M fpZ=M =Myf e-=L ,5e=BL =a->eL ,M=e =e-M =TM,e =T-Me =M5,e >M-=e ,5T=Me s=-Me ,L", -"4G ,4G&L ,4GHL ,4GaL ,4G5L ,4G8L ,4LH5e <&LG5a 4G,M -=L f5,=HL f>-g=L =,fM f-", -"=M =HMf, g=Mf- =Mf,5 f>M-= =H,f5M sf=-M ,eL 5m=L,eB >m=a-eL =QM,e =Q-Me Mem=T, =Te-Mm", -" p=M,e -p=Me peT=M, s=M-pe ,4GWL L =,f5vHL >Lg=-vf =Qf,M -vMf= Z=f,M Z-=fM fp=,M fp-=M ", -"Z=Mfp, yf-=M Ue =U5De >eU=D =IM +I=M V=I V+=I Ue=j =I>M V5=I >eV= UG4e 4UG J5=U =UJ> fU=M =Uf+M J=V gVJ= fU=j f>U=M =jVf Vfs", -"= UNI< IeU=m U5e=D", -"m >Im=Ua UQ=I =UQ+I Ve=Q V=+QI pU=I p=U>e =IVp V>ep= UW4e 4UWe! UUv= J=vU5 J>=vU fU=Q =Uf+Q VfZ= J=VgZ =Ufp fpU>= V", -"=Jp J=yV hU< U h=U5D c=h>U h=M h-=M V=h h=V- h5=M >Mh= =jVh V=hs 4UhG h4UG& ", -"hUJ4 cJ4hU h4UG5 h48UG J5Uh= J=hU5 =Ui> hf=M h=Mf- h=Vf iV= h=Mf5 h", -">Mf= J=Vh5 s=iV U=Um h5U=Dm h>Uc=m hQ=U h=Q-U =QVh c=VhQ =Uhp -pUh= V=hp cp=V", -"h 4UhW h4WU& J=U hvUJ=5 iv>=U =Mhv h", -"vM-= V=hZ Z=iV fpUh= fp-=U Jp=Vh yVi= 6ek 6!ke 6Bke ak6e e 7=ekB 7ae>k 6M=e =k+Me Tk=e =Tk+e l=e >el= le=T", -" les= G<4k 4Gkk7f fk7H gk7f f6=M =kf+M fT=", -"k g=kfT lf7 l>7f =Hlf g7lf 6Nke k=em =km7eB 7am>ke Qk=e =Qk+e =QkTe =Qake lep= l>ep= l=pTe l=s", -"pe Wk4e k7v 7fvHk g7fvk fQ=k =Qf+", -"k =kZf Z=kgf 7flv lfp7> 7Zlf lfy7 ?ke ke?& ke?B ak?e 1e?k ?k:e ?B1ke ?:ake ", -"?Me Me?& Tk?e aM?e l?e ?:le ?Tle les? ke?* ?e-k ?Bke* ?-ake ?1ke* ?:-ke ke*", -"?B1 :-k?ae Me?* ?e-M ?Tke* ?-Tke ?el* ?-le l?Te* l-?se ?Gk Gk?& Gk?H Ga?k 1", -"G?k ?k:G ?G1Hk ?:GHk ?GM GM?& GT?M Ga?M l?G ?:lG ?GlH lGs? ?fk fk?- fk?H gk", -"?f ?1fk fk?: ?f1Hk g?:fk ?fM f-?M fT?M gM?f lf? ?fl- lH?f lfg? 4k?e ke4& ?B", -"4ke ?a4ke ?k7e 7k:e 7?keB ?a7ke 4M?e ?M4e& ?T4ke ?aM4e 7?le 7:le ?T7le 7sel", -"? ?k=e =e-k ?=ekB =a?ke ?=7ke Ake 7ek?=B akAe =e?M ?-M=e =T?ke ?aM=e ?=le A", -"le l=?Te lsAe 4G?k ?G4k& ?G4Hk ?Ga4k ?k7G ?:G7k ?G7Hk ?G7ak 4G?M ?GM4& ?GT4", -"k ?Ga4M 7l?G l?G7: l?G7H s?G7l =k?f f-=k ?f=Hk g=k?f fk7? Afk 7f?Hk gfAk =M", -"?f ?fM-= ?fT=k g?Mf= ?fl= Alf lf?=H glAf ke?N ke&?N ?BkeN ?akeN ?1keN ?:ekN", -" keN?B1 :ek?aN Qk?e ?Qke& ?QTke ?Qake ?Qle ?:Qle l?QTe s?lQe ?ke*N ?-keN ke", -"*?BN -ke?aN ke*?1N :ek?-N ke?B1*N ak:e?-N ?Qke* ?-Qke Qke?T* ?Qe-Tk l?Qe* l", -"-?Qe leQ?T* s?Ql-e Gk?W ?GWk& ?GHWk ?GaWk ?G1Wk ?:GWk 1He?Wk ?Hk:We GQ?M ?G", -"Qk& Zk?G ?ZGak ?GlW l?G:W lG?Z s?ZlG fk?W ?-Wfk ?fHWk g?fWk ?f1Wk :f?Wk f1H", -"?Wk :fWg?k fQ?M ?fQ-k ?MZf g?Zfk lW?f lf?:W ?Zlf gl?Zf ke?m ?mke& ?mkeB ?am", -"ke ?m7ke ?:mke 7ek?mB ?ak:em Me?m ?Mme& ?Tmke ?aMem le?p :pel? ?plTe s?ple ", -"?=ekm ?-mke =ke?mB ?ae-km 7=e?mk keAm =B?m7ek Akmae ?Mm=e ?-Mem ?Qe=Tk ?Qe=", -"ak l=?pe leAp ?pTl=e Apels Gk?m ?Gmk& ?GmHk ?Gakm ?G7Wk ?:Gkm ?Hk7We ?Gk7Wa", -" GM?m ?GMm& ?Z4Gk ?GaMm lG?p ?pGl: ?Zl7G s?plG fk?v -vk?f ?vfHk g?vfk ?v7fk", -" fvAk 7fH?vk Avkgf fv?M ?vMf- ?Zf=k g?vfM ?plf lfAp lv?Zf ylAf 6Ue 6!Ue Ue6", -"D Ua6e 1U6e U86e 6Ue1D 6U8De Ue6M Ik 7Ue=D 7>UD", -"e 6I=M =Ik+M V6=I V=6+I l=I =Il> =I7V >e7V 4UG6e I =U7J >kJ= =Uf6M =U+f6M =kVf J=Vg6 =Ulf lf7>U l=J 7Vsf 6", -"NUe 6Ue!N 6UeDN 6UaeN 6Ue1N 6U8eN IkN1D< akN1I< UQ6e 6UQe! 6QVe V6eQa QIl< ", -"lIUem 7Dm=Ik >Dm7U", -"e QI=k =QI+k V=6QI =QaIk lIp= l=Ip> V=plI V>e7p I J=k7v J>=vk =Uf6Q =U+f6Q ZJ=k J=kgZ =Ilv fpU7", -"> Jpl= l=yJ h?t h&?t ?Dht ht?c ?th1 ?th: ?t1hD ?t:hc h?M h&?M V?h Vh?c lh? ", -"l?h: lhV? u?h t*h? h?t- ?tDh* ?cht- ?t1h* ?t:h- h?1t*D ?cth:- h*?M ?-hM V*h", -"? h?V- h?l* h?l- V?lh* h?u- ?tG ?&tG ?Jt tJ?c ?1tG t:?G J1?t ?t:J ?GhM ?tGM", -"& ?JV cJV? h?lG lh?:G ?Jl u?J tf? t-?f tf?J i?t f1?t ?t:f ?Jtf1 ?ti: hM?f ?", -"fMt- V?f i?V ?flh lf?h: ?Jlf ui? ht4 h&t4 hDt4 tch4 7ht 7th: 7Dht ht7c ?Mh4", -" h?M4& h4V? V?hc4 7hl l:7h 7Vh u7h t=h t-h= ht=D htc= 7ht= Aht t=7hD htAc h", -"?=M h=Mt- h=V? c=Vh? l=h Alh V=7h Auh t4?G ?tG4& h4tJ tJ4?c ?G7t 7tGh: tJ7h", -" ?J7t: ?tG4M ?G&h4M J4V? ?JVc4 lG7h 7hl:G 7V?J ?Ju7 tf= f-t= t=J it= tf7 At", -"f 7Jtf Ait =Mtf tf=-M V?J= t=iV tfl= lfAh ?Jl= Aiu hN?t ?t&hN ?tDhN ?chtN ?", -"t1hN ?t:hN ht1?DN ?cth:N ?thQ ?tQh& hQV? V?hcQ hQl? lh?:Q V?lhQ h?uQ ?t*hN ", -"t-?hN h?Dt*N t-h?cN h?1t*N t-?h:N hDt*?1N hN?ct-: ?tQh* t-Qh? V?hQ* V?-hQ l", -"h?Q* l-h?Q lhQV?* uh-?Q ?thW ?tGW& ?WtJ ?cWtJ ?tG1W h:W?t ?Jt1W ?J:tW ?WhM ", -"?tGQ& tZ?J hZ?tc h?lW lhW?: lJ?Z hZu? ?Wtf t-W?f ?JtfW ?tiW tf?1W tf:?W tf1", -"?JW i?t:W ?Qtf tfQ?- tf?Z ?ZiV lhW?f lhW?- V?flZ i?uZ ?thm ?tmh& ?tmhD ?cmh", -"t hm7t h:m7t 7htDm 7hctm ?Mhm ?Mmh& hmV? V?mhc 7htp hpl?: 7Vhp hpu? hmt= t-", -"mh= t=hDm t=chm t=7hm htAm 7hDt=m Atmhc ht=Q t=Qh- V?mh= c=Qht hpl= hpAl l=", -"hVp upAh t4hW ?tGm& ?mtJ ?Jmtc hW7t 7hWt: ?J7tW ?J:tm ?tG4Q ?G&t4Q h4tZ V?m", -"cJ lW7h lhW7: tp?J hZu7 tf?v hv?t- tv?J ?vit 7htv hvAt hv7tJ itAv =Qtf hv?-", -"M t=hZ ?viV hvl= lvAh hZl= yAui O !O OB aO O. 8O .BO 8aO OK !KO TO TaO jO j", -"O8 jOT sO (O +O (BO +aO (O. +8O (O.B 8a+O (OK +OK T(O +TO jO( +jO T(jO s+O ", -"EO !EO HO HaO EO. 8EO HO. H8O EKO !OEK HTO TaHO jOE 8EjO HjO sHO dO +dO HdO", -" gO dO. 8dO dOH. g8O dKO dK+O TdO gTO djO jO8d jOTd gsO O2 !O2 2BO aO2 5O 5", -"8O 5BO 5aO 2KO !O2K TO2 T2aO jO5 58jO 5TO s5O ;O +;O ;OB a;O 5;O >O ;O5B >O", -"a ;OK ;O+K T;O +OT; ;jO >jO jOT; s>O EO2 EO!2 HO2 aOH2 5EO 8E5O H5O HO5a EO", -"2K !EO2K TOH2 HTaO2 5EjO jO58E jOH5 H5sO d;O d;+O H;O g;O 5dO >Od HO5d g>O ", -";OdK +d;OK HOT; T;gO jO5d dj>O jOH; >Ogs P P! PB aP P. 8P P.B 8Pa QP Q!P TP", -" QaP Pj Q8P TPj sP P( +P P(B +Pa P(. +P8 .BP( +8aP QP( +QP TP( +TP Pj( +Pj ", -"T(Pj sP+ WP W!P HP HPa WP. W8P HP. H8P WQP WPQ! ZP ZaP WjP 8PWj ZPj sZP dP ", -"+WP HPd gP dP. 8dP H.dP gP8 QdP Qd+P ZdP gZP dPj Wj+P dPZj gsP mP mP! mPB a", -"mP 5P 5P8 5PB 5aP QmP mPQ! TmP amTP pP p8P pTP spP ;P +mP ;PB a;P 5P; >P 5B", -";P >Pa Q;P Q;+P T;P Tm+P p;P >Pp T;pP >Ps WmP mPW! HmP amHP 5WP W85P H5P 5a", -"HP QmWP Q!WmP ZmP amZP pWP W8pP ZpP ZpsP vP v+P vHP gvP v5P >Pv H5vP >Pg vQ", -"P +QvP ZvP ZvgP pvP pv>P ZPpv yP #O &O #BO a&O #O. 8&O #O.B a&8O #OK &OK T#", -"O T&O jO# &jO T#jO s&O #(O +&O #(OB a&+O (O#. 8&+O (BO#. +8a&O (O#K &O+K #(", -"TO +OT& #(jO +&jO jOT#( +&sO #EO &EO H#O H&O EO#. &E8O #OH. 8&HO #OEK EK&O ", -"T#HO HOT& #EjO &EjO H#jO H&sO d#O d&O d#HO g&O #Od. 8Od& Hd#O. 8&gO #OdK &O", -"dK d#TO T&gO d#jO jOd& dj#HO gOs& #O2 &O2 #O2B &2aO 5#O 5&O #B5O a&5O #O2K ", -"2K&O #OT2 &OT2 5#jO jO5& T#5O 5&sO ;#O ;&O #B;O aO;& ;#5O >&O 5;#OB a&>O #O", -";K &O;K ;#TO TO;& ;#jO &j>O ;j#TO s&>O EO#2 EO&2 #OH2 &OH2 #E5O &E5O 5#HO H", -"O5& #O2EK &EO2K HT#O2 H&TO2 jO5#E &jE5O H5T#O sH5&O ;#dO dO;& ;#HO ;&gO d#5", -"O d&>O H5d#O g&>O dK;#O d&;OK H;T#O gT;&O dj#5O >&djO H;j#O gs>&O P# P& P#B", -" aP& P#. 8P& .BP# 8aP& QP# Q&P TP# TP& Pj# P&j T#Pj sP& P#( +P& #BP( +aP& #", -"(P. +8P& P#(.B aP&+8 P#Q( Q&+P P#T( T&+P j#P( P&+j Pj#T( +Ps& WP# W&P HP# H", -"P& P#W. 8PW& P#H. 8PH& QPW# WQP& ZP# Z&P W#Pj P&Wj PjZ# Z&sP dP# dP& H#dP g", -"P& P#d. d&8P dP#H. 8Pg& Q#dP dPQ& dPZ# Z&gP d#Pj P&dj dPjZ# g&sP mP# m&P P#", -"mB m&aP 5P# 5P& P#5B aP5& mPQ# QmP& mPT# m&TP pP# p&P TPp# p&sP ;P# ;P& PB;", -"# ;&aP 5#;P >P& ;P#5B aP>& Q#;P ;PQ& T#;P ;PT& ;Pp# p&>P pT;P# >&sP mPW# Wm", -"P& mPH# m&HP WP5# W&5P H#5P 5PH& WQmP# m&PWQ mPZ# m&ZP WPp# W&pP pPZ# ZPp& ", -"vP# v&P HPv# v&gP 5Pv# v&>P vH5P# >&gP QPv# Q&vP vPZ# ZPv& vPp# pPv& ZpvP# ", -"y&P CO !CO DO DaO CO. 8CO DO. D8O CKO !OCK DTO TaDO jOC 8CjO DjO sDO C(O +C", -"O D(O +DO (OC. 8C+O (OD. +OD8 (OCK CK+O T(DO DT+O C(jO +CjO D(jO +DsO CEO C", -"E!O HDO DaHO EOC. CE8O DOH. HOD8 COEK !EOCK DTHO HDTaO CEjO jO8CE HDjO HDsO", -" dCO dC+O DdO gDO COd. dC8O dOD. D8gO CKdO +dCOK DOTd DTgO dCjO djC+O jODd ", -"gOsD CO2 CO!2 DO2 D2aO 5CO 8C5O 5DO 5OD8 CO2K !C2OK T2DO DTaO2 5CjO jO58C j", -"O5D 5DsO ;CO ;C+O D;O +OD; ;C5O >CO 5OD; >DO CK;O +;COK DOT; a;ODT ;CjO jO>", -"C jOD; sD>O EOC2 !EOC2 DOH2 HDaO2 CE5O 58CEO HO5D H5D8O EKCO2 EK2!CO HDTO2 ", -"DTaHO2 jO5CE 58CjOE H5DjO sH5DO ;CdO +d;CO HOD; D;gO dC5O dC>O 5ODd gD>O dK", -";CO dK;+CO H;DTO gDT;O djC5O >jdCO H;jDO >DOgs PC PC! DP DPa PC. 8PC DP. D8", -"P QPC PCQ! QDP DPQa PjC QC8P DPj sPD PC( +PC DP( +DP C(P. +C8P P(D. D8+P PC", -"Q( QP+C Q(DP QD+P jCP( +CPj D(Pj +DsP WPC PCW! HPD DPWa PCW. WC8P H.DP D8HP", -" QPWC Q!WPC ZDP DPZa WCPj PjCW8 DPZj ZDsP dPC +CdP DdP gPD PCd. 8CdP D.dP D", -"8gP QCdP dPC+Q DdZP ZDgP dCPj dPj+C dPDj gDsP mPC P!mC DmP amDP 5PC 5C8P 5D", -"P D85P mPQC Q!mPC TmDP amPQD pPC 8PpC pDP pDsP ;PC +C;P D;P Dm+P 5C;P >PC D", -";5P >PD QC;P ;PC+Q DPQ; a;PQD ;PpC pP>C D;pP pD>P mPWC W!mPC DmHP amPWD WP5", -"C 5W8PC 5DHP H5PD8 WQmPC WmPQ!C DmZP ZDamP WPpC pW8PC ZPpD sPDZp vPC +PvC v", -"DP vDgP 5PvC vP>C 5DvP vD>P QPvC v+QPC ZPvD ZvDgP vPpC >PpvC pPvD yDP bO b&", -"O bDO cO bO. b8O DOb. c8O bKO &ObK bTO cTO bjO jOb8 jObT scO b(O b+O D(bO c", -"+O (Ob. +8bO bD(O. +8cO (ObK +ObK T(bO +TcO b(jO jOb+ bTj(O c+sO bEO &EbO b", -"HO cHO EOb. 8EbO HOb. H8cO EKbO bK&EO HTbO HTcO bEjO &jEbO jObH cHsO bdO bO", -"d& bODd gcO dOb. bO8d bHdO. c8gO dKbO d&ObK bOTd cTgO jObd d&jbO bHjdO gOsc", -" bO2 &Ob2 DOb2 c2O b5O bO5& bO5D c5O 2KbO bK&O2 TOb2 TOc2 jOb5 &jOb5 bO5T s", -"Oc5 b;O bO;& bOD; c;O 5;bO >bO b5D;O c>O ;ObK ;&ObK bOT; T;cO jOb; bj>O b5T", -";O >Osc EOb2 b&EO2 HOb2 HOc2 5EbO b58EO bOH5 H5cO bKEO2 &EObK2 bHTO2 c2HTO ", -"b5jEO b5E&jO bH5jO c5HsO d;bO d&;bO bOH; gOc; bO5d bd>O bH5dO >Ogc bd;OK bd", -"O;&K bH;TO c;TgO b5djO >bdjO bH;jO c>gsO bP bP& bPD cP bP. b8P b.DP cP8 bQP", -" Q&bP bTP cQP bPj Q8bP DPbj scP bP( b+P b(DP cP+ P(b. +Pb8 bPD(. +Pc8 QPb( ", -"+QbP b(TP +QcP b(Pj +Pbj bTPj( s+cP bWP W&bP bHP cWP WPb. W8bP b.HP H8cP WQ", -"bP bWQP& ZbP ZcP WjbP P&jbW bPZj sPZc bdP +WbP HPbd gcP b.dP 8dbP bHPd. g8c", -"P QdbP dP&bQ bdZP gPZc dPbj dP&bj ZbdPj scgP bmP m&bP DmbP cmP b5P 5Pb8 5Db", -"P c5P QmbP m&PbQ TmbP TmcP pbP b8pP bTpP cpP b;P +mbP D;bP c;P 5Pb; >Pb b5P", -"D; c>P Q;bP ;P&bQ T;bP Q;cP b;pP pb>P pbD;P >Pcp WmbP m&PbW HmbP HmcP 5WbP ", -"b5W8P H5bP H5cP bWQmP bWQm&P bmZP ZmcP bWpP pbW8P ZPpb cPZp vbP b+vP bHvP c", -"vP b5vP vb>P vbH5P >Pcv bQvP vb+QP ZPvb cPZv pPvb >Pbpv ZpbvP ycP 0O !0O 0B", -"O a0O 1O 18O 1OB 1aO 0OK 0O!K T0O a0TO jO1 18jO 1TO s1O 0(O +0O 0(OB a0+O 1", -"(O 1+O (B1O +a1O (O0K 0O+K 0(TO T0+O 1(jO jO1+ T(1O 1+sO E0O E0!O H0O a0HO ", -"1EO 8E1O 1HO 1OH8 0OEK !EO0K T0HO HTa0O 1EjO jO18E jO1H 1HsO d0O d0+O d0HO ", -"g0O 1dO 1O8d Hd1O g1O 0OdK +d0OK d0TO T0gO jO1d djO1+ 1OTd gOs1 0O2 0O!2 0O", -"2B 0Oa2 15O 581O 5B1O 1O5a 0O2K 2K0!O 0OT2 Ta0O2 15jO jO158 1O5T 15sO ;0O ;", -"0+O 0B;O ;0aO 1;O >O1 ;O1B 1a>O 0O;K +;0OK ;0TO a;0TO jO1; jO>1 1OT; s1>O 0", -"OE2 !EO02 0OH2 Ha0O2 5E1O 158EO 1OH5 1H58O EK0O2 2K0!EO HT0O2 Ta0HO2 jO15E ", -"158jOE 1H5jO s1H5O ;0dO +d;0O ;0HO ;0gO 1O5d 1d>O 1OH; >Og1 dK;0O dK;+0O H;", -"T0O gT;0O djO1; >j1dO 1H;jO gs>1O P0 P0! P0B aP0 1P 1P8 1PB 1aP QP0 P0Q! TP", -"0 Q0aP 1QP Q81P 1TP sP1 P0( +P0 0BP( +0aP 1P( 1+P P(1B +P1a P0Q( QP+0 P0T( ", -"+0TP 1(Pj +Q1P 1(TP 1+sP WP0 P0W! HP0 H0aP 1WP W81P 1HP H81P QPW0 Q!WP0 ZP0", -" aPZ0 Wj1P 1WQ8P Z1P Z1sP dP0 +0dP H0dP gP0 1dP +W1P HP1d g1P Q0dP dP0+Q dP", -"Z0 ZPg0 Qd1P dPj1+ 1dZP sPg1 mP0 P!m0 P0mB mPa0 1mP 8m1P 1B5P 5a1P mPQ0 Q!m", -"P0 mPT0 amPQ0 p1P 1Pp8 1TpP p1sP ;P0 +0;P PB;0 a0;P 1;P >P1 1B;P 1a>P Q0;P ", -";P0+Q T0;P a;PQ0 1;pP p1>P T;1P s1>P mPW0 W!mP0 mPH0 amPH0 5W1P 1W58P H51P ", -"1Hm8P WQmP0 WmPQ!0 mPZ0 ZamP0 1WpP p1W8P p1ZP sP1Zp vP0 +Pv0 HPv0 vPg0 v1P ", -"v1>P 1HvP g1>P QPv0 v+QP0 vPZ0 ZvPg0 pPv1 >Ppv1 ZPv1 y1P 9O 9&O 9OB 9aO 91O", -" :O 1B9O :aO 9OK &O9K 9TO 9OT& 9jO :jO jO9T s:O 9(O 9+O (B9O +a9O 1(9O :+O ", -"91(OB +a:O (O9K +O9K T(9O 9O+T 9(jO +j:O 9T1(O :+sO 9EO &E9O 9HO 9OH& 1E9O ", -":EO 9O1H :HO EK9O 9&EOK HT9O 9HTaO 9EjO jO:E jO9H sO:H 9dO 9Od& Hd9O g9O 9O", -"1d :dO 9H1dO g:O dK9O d&O9K 9OTd 9TgO jO9d dj:O 9HjdO gOs: 9O2 &O92 2B9O aO", -"92 95O :5O 5B9O 5a:O 2K9O 9&O2K TO92 9TaO2 jO95 jO:5 9O5T :5sO 9;O 9O;& ;O9", -"B 9Oa; 9O1; :>O 95;OB :a>O ;O9K ;&O9K 9OT; 9+T;O jO9; :j>O 95T;O >Os: EO92 ", -"9&EO2 HO92 9HaO2 5E9O 5E:O 9OH5 H5:O 9EO2K &EO92K 9HTO2 H&O9T2 95jEO :5jEO ", -"9H5jO :H5sO d;9O d&;9O 9OH; 9;gO 9O5d >O:d 9H5dO >Og: 9d;OK 9dO;&K 9H;TO g9", -"T;O 95djO :>djO 9H;jO g:s>O 9P 9P& 9PB 9aP 9P1 :P 1B9P :Pa 9QP Q&9P 9TP Qa9", -"P 9Pj :QP 1T9P s:P 9P( 9+P P(9B +P9a 9(1P :P+ 9P1(B +P:a QP9( +Q9P 9(TP +T9", -"P 9(Pj +Q:P 9TP1( s+:P 9WP W&9P 9HP HP9a 1W9P :WP 1H9P :HP WQ9P 9WQP& Z9P 9", -"aZP Wj9P Wj:P 9PZ1 Z:P 9dP +W9P HP9d g9P 1d9P :dP 9HP1d g:P Qd9P dP&9Q 9dZP", -" Z9gP dP9j Qd:P Z91dP gPZ: 9mP m&9P mP9B am9P 95P :mP 9B5P 5a:P Qm9P m&P9Q ", -"Tm9P 9QamP p9P :pP 9TpP sP:p 9;P +m9P 9B;P a;9P 1;9P >P: 95P;B :a>P Q;9P ;P", -"&9Q T;9P a;P9Q 9;pP >P:p p9T;P s:>P Wm9P m&P9W Hm9P 9HmaP 5W9P 5W:P H59P H5", -":P 9WQmP 9WQm&P 9mZP Z9amP 9WpP pW:P ZPp9 :PZp v9P 9+vP 9HvP v9gP 95vP :vP ", -"v91HP >Pg: 9QvP v9+QP ZPv9 Zv9gP pPv9 pv:P Zp9vP y:P C0O C0!O D0O a0DO 1CO ", -"8C1O 1DO 1OD8 0OCK C0O!K T0DO DTa0O 1CjO jO18C jO1D 1DsO 0(CO C0+O 0(DO D0+", -"O C(1O +C1O D(1O 1O+D C0O(K +C0OK DT0(O +DT0O jO1C( 1+jCO 1DT(O s1+DO E0CO ", -"C0O!E D0HO HDa0O CE1O 18CEO HD1O 1HD8O C0OEK EK0!CO HDT0O DTaH0O jO1CE 18Cj", -"OE 1HDjO s1HDO C0dO +dC0O d0DO D0gO dC1O 1+dCO 1ODd 1DgO dKC0O dKC+0O DdT0O", -" gDT0O djC1O 1+CdjO 1DdjO gs1DO 0OC2 C02!O 0OD2 Da0O2 5C1O 158CO 1O5D 1D58O", -" C02OK 2K0!CO DT0O2 Ta0DO2 jO15C 158jOC 1D5jO s15DO C0;O +;C0O ;0DO a;0DO ;", -"C1O 1C>O 1OD; 1D>O ;C0OK ;C0+OK D;T0O D;0+TO ;jC1O >j1CO 1D;jO >DOs1 C02EO ", -"!EOC02 HD0O2 Da0HO2 15CEO 58C1EO 1H5DO H5D1aO EK2C0O E02K!CO DT0HO2 DTH0aO2", -" 15CjOE 5E1O8jC H5D1TO 1H5sDO d;C0O d;C+0O H;D0O gD;0O 1d5CO >C1dO 1H;DO >D", -"Og1 ;C0dKO C0;O+dK Td0D;O D;Tg0O 1dC;jO djC>O1 djO1D; gs1>DO PC0 !CP0 DP0 D", -"0aP 1PC 1C8P 1DP D81P PCQ0 Q!PC0 Q0DP aP0QD 1CPj PjC18 QD1P 1DsP C0P( PC+0 ", -"P0D( +0DP PC1( 1C+P 1(DP +D1P QPC0( +QPC0 QDP0( +QDP0 PjC1( 1+QPC 1QDP( sP1", -"+D PCW0 W!PC0 H0DP aP0WD WP1C 1W8PC HP1D 1HPD8 WQPC0 WPCQ!0 DPZ0 ZDaP0 PjC1", -"W 1W8PjC 1DZP sP1ZD PCd0 dPC+0 D0dP DPg0 1CdP 1+WPC Dd1P 1DgP dPCQ0 +QCdP0 ", -"ZDdP0 gZDP0 dPj1C dPC1+Q Z1DdP gZ1DP PCm0 mPC!0 mPD0 amPD0 1C5P 1m8PC 5D1P ", -"1Dm8P QmPC0 mPCQ!0 QDmP0 QDmaP0 1PpC p18PC 1DpP sP1pD PC;0 ;PC+0 D0;P a;PD0", -" 1C;P 1P>C D;1P 1D>P ;PCQ0 +QC;P0 QD;P0 aP0QD; p1;PC >Pp1C pD1;P >Ps1D WmPC", -"0 mPCW!0 HmDP0 HmDaP0 1W5PC 5W81PC 1HmDP H8m1DP QmPWC0 QCW0mP! ZDmP0 amPZD0", -" p1WPC 1W8pPC Zp1DP Zp1sPD PCv0 v+PC0 DPv0 gvDP0 1PvC >Pv1C 1DvP >Pg1D vQPC", -"0 +QPvC0 ZvDP0 vDPgZ0 pv1PC pv1>PC Zv1DP 1DyP b9O 9&bO 9DO c9O b1O :bO bO1D", -" :cO 9ObK b9&OK bO9T 9TcO jOb1 bj:O jO9D sO:c 9(bO bO9+ D(9O 9+cO 1(bO b+:O", -" b1D(O c+:O b9(OK b+9OK bT9(O c9+TO b1j(O :b+jO b1T(O :c+sO 9EbO b9&EO bO9H", -" 9HcO 1EbO bE:O bO1H cH:O b9EOK 9&EbKO bH9TO c9HTO b1jEO :bjEO b1HjO :cHsO ", -"bO9d d&Ob9 9ODd c9gO bO1d bd:O b1HdO gO:c bd9OK 9+ObdK bTd9O gc9TO b1djO :d", -"bjO b1TdO g:scO 9Ob2 b9&O2 DO92 9Oc2 bO95 b5:O 9O5D :Oc5 b9O2K 9&ObK2 bT9O2", -" c29TO b15jO :b5jO b1T5O :c5sO bO9; ;&Ob9 9OD; 9;cO bO1; :b>O b1;DO >O:c b;", -"9OK 9+Ob;K bT;9O c;9TO b1;jO :>bjO b1T;O c>s:O b9EO2 9&EbO2 bH9O2 c29HO b15", -"EO :b5EO b1H5O :cH5O 9EObK2 EOb29&K 9HObT2 9HTc2O 95EbjO b5j:EO bHO95T s:Hc", -"5O bd9;O bd9;&O bH;9O c;9gO b1d5O :>bdO b1H;O g:c>O 9dOb;K d&b;9OK bHO9T; g", -"9Tc;O djOb1; >bj:dO djO95D c>sg:O bP9 b9P& 9DP cP9 b1P :Pb 1DbP :cP 9QbP bQ", -"9P& 9TbP 9QcP 9Pbj bQ:P 1TbP :csP b(9P 9+bP 9(DP 9+cP b(1P b+:P b1PD( :+cP ", -"bQ9P( b+Q9P bTP9( cQ9+P b1QP( :Qb+P b1TP( :cQ+P 9WbP bW9P& 9HbP 9HcP 1WbP b", -"W:P 1HbP cW:P bW9QP 9WQbP& bPZ9 cPZ9 b1WPj :WbPj b1ZP :PZc 9dbP dP&b9 Dd9P ", -"cPg9 1dbP bd:P b1HdP :cgP bQd9P 9+QbdP Zb9dP Zcg9P dPjb1 :QdbP Zb1dP g:PZc ", -"9mbP m&Pb9 Dm9P 9mcP 95bP b5:P 5D9P c5:P bQ9mP bQ9m&P bTm9P cQ9mP b1pP pb:P", -" 9DpP :Pcp 9;bP ;P&b9 D;9P 9;cP 1;bP >b:P b1;DP :c>P bQ;9P 9+Qb;P bT;9P cQ;", -"9P pb9;P :p>bP p9D;P cp:>P bW9mP bW9m&P bHm9P cW9mP b1W5P :Wb5P b1H5P :cW5P", -" 9WQbmP QmP&bW9 Zb9mP Zc9mP pb9WP :pbWP Zpb9P cpZ:P bPv9 vb9+P 9DvP v9cP b1", -"vP vb:P vb1HP :Pcv vb9QP b+Qv9P Zvb9P cvZ9P pvb9P :vbpP Zvb1P :cyP R R! RB ", -"Ra R. R8 R.B R8a RM RM! RT RTa Rj R8M RTj sR R( R+ R(B R+a R(. R+8 .BR( +8R", -"a RM( R+M RT( R+T Rj( R+j TjR( sR+ RE RE! RH RHa RE. R8E RH. RH8 RME MER! R", -"HT HMRa RjE RE8M RHj sRH Rd R+d RHd gR Rd. R8d HdR. gR8 RdM +MRd RTd gRT Rd", -"j +jRd HjRd gsR R2 R2! R2B Ra2 R5 R58 R5B R5a RM2 M2R! RT2 R2aM R5M 5MR8 R5", -"T sR5 R; R+; R;B Ra; R5; >R 5;RB >Ra R;M +MR; RT; +TR; R;j >MR 5TR; s>R RE2", -" !ER2 RH2 HaR2 R5E 58RE RH5 H5R8 MER2 RME!2 R2HM aM2RH RE5M R58ME H5RT RHs5", -" Rd; +dR; RH; gR; R5d >Rd H5Rd g>R dMR; dM;R+ HMR; RTg; 5dRj Rd>M H;Rj gR>M", -" RP RP! RPB RaP RP. R8P P.RB 8PRa S S! ST Sa Sj S8 STj Ss RP( R+P P(RB +PRa", -" P(R. +PR8 RP(.B R+8aP S( S+ ST( S+T Sj( S+8 TjS( Ss+ RW RW! RHW RWa RW. RW", -"8 R.HP H8RW SW S!W SZ SZa SWj S8W SZj SsZ RWd R+W HPRd gRW R.dP +WR8 dP.RH ", -"RWg8 Sd S+W SZd gS Sdj S8d ZdSj gSs Rm Rm! RmB Ram R5m R8m RB5P 5aRm Sm S!m", -" STm Sam Sp Sp8 SpT Ssp Rm; R+m RB;P +mRa 5PR; >PR ;PBR5 Ra>P S; S+m S;T Sa", -"; Sp; S> pTS; S>s RWm W!Rm RHm HmRa R5W 5WR8 H5RW H8Rm SWm W!Sm SZm ZaSm Sp", -"W pWS8 SZp SZsp vR vR+ vRH gvR vR5 v>R RHv5 gR>P Sv Sv+ SvZ gSv Svp S>v ZpS", -"v yS R# R& R#B Ra& R#. R8& .BR# 8aR& RM# R&M RT# RT& Rj# R&j TjR# sR& R#( R", -"+& #BR( +aR& #(R. +8R& R#(.B R+8a& M#R( +MR& T#R( +TR& j#R( +jR& RTj#( R+s&", -" R#E R&E RH# RH& #ER. 8&RE H#R. H8R& M#RE REM& R#HM HMR& j#RE RE&j R#Hj RHs", -"& Rd# Rd& HdR# gR& d#R. 8dR& RHd#. R8g& R#dM dMR& R#Td RTg& R#dj d&Rj RHjd#", -" g&sR R#2 R&2 2BR# a&R2 R5# R5& 5BR# 5aR& M#R2 R2M& T#R2 R2T& R#5M 5MR& R#5", -"T R5s& R;# R;& ;#RB a;R& 5;R# >R& R5;#B Ra>& R#M; M;R& R#T; T;R& R#;j R&>M ", -"R5T;# >&sR #ER2 &ER2 H#R2 R2H& 5#RE RE5& R#H5 H5R& RM#E2 M&ER2 RHT#2 RH&T2 ", -"R5M#E R5&ME RH5T# sRH5& d;R# d&R; R#H; R;g& R#5d Rd>& RH5d# >&gR dM;R# dM&R", -"; RH;T# gRT;& R5dM# >MRd& RH;j# >MgR& RP# R&P P#RB aPR& P#R. 8PR& RP#.B aP&", -"R8 S# S& ST# Sa& Sj# S8& TjS# Ss& P#R( +PR& RP#(B aP&R+ RP#(. R+8P& P#(R.B ", -"R+8aP& S#( S+& T#S( +TS& j#S( +jS& STj#( s+S& RW# RW& R#HP HPR& W#R. W8R& R", -"HW#. RH8W& SW# S&W SZ# SZ& WjS# W8S& ZjS# S&sZ R#dP +WR& dP#RH RWg& dP#R. d", -"P&R8 RH#dP. gRW8& Sd# Sd& ZdS# gS& djS# 8dS& SZdj# S&gs Rm# Rm& m#RB amR& R", -"#5P 5PR& R5m#B R5am& Sm# S&m TmS# TmS& Sp# Sp& pTS# S&sp R#;P +mR& ;P#RB a;", -"PR& ;P#R5 Rm>& R5#;PB >PRa& S;# S;& T;S# T;S& p;S# S>& SpT;# S&s> WmR# W&Rm", -" R#Hm HmR& R#5W 5WR& RH5W# RH5W& WmS# W&Sm ZmS# SmZ& pWS# SWp& S#Zp ZpS& vR", -"# vR& RHv# v&gR R5v# >Rv& vRH5# >PgR& Sv# Sv& S#Zv S&gv S#pv pvS& SZpv# yS&", -" RU RU! RD RDa RU. R8U RD. RD8 RUM U!RM VR VRa RjU U8Rj VRj sRV RU( R+U RD(", -" R+D U(R. U+R8 D(R. +DR8 UMR( RU+M VR( V+R R(Uj U+Rj RjV( V+sR RUE U!RE RHU", -" UHRa UER. REU8 R.UH UHR8 UMRE RUM!E VRH RHVa REUj R8UME RHVj VRsH RdU U+Rd", -" RDd gRU R.Ud U8Rd R.Dd RDg8 RUdM R+UdM VdR gVR UdRj R+jUd RdVj sRgV RU2 U!", -"R2 RD2 R2Ua R5U U5R8 R5D U5Ra UMR2 RUM!2 V2R RaV2 U5Rj R5U8M V5R V5sR R;U U", -"+R; RD; UaR; U5R; >RU 5DR; >RD RUM; R+UM; V;R R+V; U;Rj Rj>U R5V; V>R UER2 ", -"RUE!2 R2UH RHUa2 REU5 R5U8E UHR5 RH5U8 RUME2 U!MRE2 RHV2 V2RHa R5UME U58RjE", -" RHV5 VsHR5 UdR; R+Ud; UHR; RDg; U5Rd Rd>U 5DRd >RgU dM;RU R+UdM; RHV; V;gR", -" R5dUj >MRUd R5Vd gRV> UP UP! RDP UaP UP. U8P R.DP D8UP SU S!U SV SVa SUj S", -"8U SVj SsV UP( U+P R(DP +DUP P(U. +PU8 RDP(. R+D8P SU( S+U SV( SV+ UjS( U+S", -"8 VjS( VsS+ RWU R!UW RWD UWRa R.UW UWR8 R.WD H8UP SUW UWS! SZV VZSa UWSj UW", -"S8 SjVZ SVsZ UdP U+RW HPUd gUP U.dP 8dUP RWDd. U8gP SdU U+Sd SVd gSV UdSj U", -"8Sd SjVd SsgV RmU R!Um RDm UaRm U5P U8Rm 5DRm 5aUP SUm UmS! SVm VmSa SpU pU", -"S8 VpS VpSs U;P U+Rm DmR; +DRm 5PU; >PU R5D;P RD>P S;U U+S; SV; V+S; pUS; S", -">U S;Vp S>V UWRm RWUm! UHRm RHmUa U5RW R5WU8 H5UP RH8Um UWSm S!UWm VmSZ SZV", -"am SWpU SpUW8 SZVp SZpVs vRU R+vU vRD vRgU R5vU vU>P R5vD gU>P SvU vUS+ VvS", -" VvgS pUSv vUS> VpSv yVS Rb Rb& RbD cR Rb. Rb8 bDR. cR8 RbM bMR& VRb cRV Rb", -"j b8Rj RbVj scR Rb( Rb+ bDR( cR+ b(R. b+R8 RbD(. R+c8 R(bM bMR+ RbV( V+cR R", -"(bj b+Rj VRbj( s+cR RbE REU& RbH cRH bER. REb8 R.bH RHc8 REbM M&ERb RbVH VR", -"cH REbj Rb8ME bHRj sHcR Rbd b+Rd bHRd gcR R.bd b8Rd RbHd. g8cR bMRd dM&Rb R", -"bVd cRgV bdRj d&jRb VdRbj scgR Rb2 R2U& bDR2 cR2 Rb5 b5R8 b5RD cR5 R2bM M&2", -"Rb RbV2 V2cR b5Rj Rb58M RbV5 c5sR Rb; b+R; b;RD cR; b5R; >Rb Rb5D; c>R bMR;", -" M;&Rb RbV; V;cR b;Rj Rb>M V5Rb; sRc> bER2 Rb&E2 R2bH RHc2 REb5 Rb58E bHR5 ", -"RHc5 RbME2 RbEM&2 V2RbH cRVH2 Rb5ME M&ERb5 V5RbH cR5sH bdR; Rb+d; bHR; c;gR", -" b5Rd Rb>d RbH5d gRc> RbdM; RbdM;& VdRb; gVcR; Rb5dM >MbRd V5dRb V>gcR RbP ", -"UP& bPRD cRP R.bP bPR8 RbDP. R8cP Sb Sb& SVb Sc Sbj Sb8 VbSj Scs R(bP bPR+ ", -"RbDP( R+cP RbP(. Rb+8P bP(RD. cR+8P Sb( Sb+ VbS( Sc+ bjS( b+S8 SVbj( S+sc R", -"bW bWR& bHRW cRW R.bW bWR8 RbHW. RWc8 SbW bWS& SZb ScZ bWSj bWS8 SjZb ZcSs ", -"bWRd b+RW RbHdP cRgP RbWd. dP&U8 dP.RbH cRWg8 Sbd b+Sd ZbSd gSc bdSj b8Sd S", -"Zbdj gsSc Rbm bmR& bmRD cRm b5Rm b8Rm Rb5Dm R5cm Sbm bmS& VmSb Scm Spb pbS8", -" SbVp Scp bmR; b+Rm RbmD; R+cm Rb5;P Rb>P b5PRD; cR>P Sb; b+S; V;Sb Sc; pbS", -"; S>b SpbV; Sc> bWRm RbWm& bHRm RHcm b5RW Rb5W8 RbH5W R5cW bWSm SbWm& SmZb ", -"cmSZ SWpb SpbW8 ZpSb SZcp vRb Rbv& RbvD cvR Rbv5 >Rvb vRbH5 v>cR Svb vbS+ S", -"bVv Scv pvSb v>Sb VvpSb ycS Rk Rk! RkB Rak R1 R18 R1B R1a RkM kMR! RTk TkRa", -" lR lR8 lRT lsR Rk( R+k k(RB +kRa R1( R1+ 1(RB 1+Ra kMR( Rk+M R(Tk +kRT lR(", -" l+R RTl( sRl+ RkE kER! RHk HkRa R1E RE8k R1H 1HR8 kMRE RkM!E HkRT RHTak lR", -"E R8lE lHR sRlH Rdk +kRd HkRd gRk R1d 1+Rd 1HRd gR1 RkdM dkMR+ TkRd RTgk ld", -"R R+ld RHld glR Rk2 k2R! k2RB R2ak R15 5kR8 RB5k 1aR5 kMR2 RkM!2 R2Tk ak2RT", -" lR5 R5l8 R5lT l5sR R;k +kR; RBk; akR; R1; >kR RB1; R1>a RkM; k;MR+ TkR; ak", -";RT l;R l>R RTl; sRl> kER2 RkE!2 R2Hk ak2RH RE5k R158E 1HR5 R1H5a RkME2 kME", -"R2! RHTk2 RHTak2 R5lE lR58E RHl5 lsRH5 dkR; dk;R+ HkR; R;gk 1dR5 R1>d 1HR; ", -"gR>k dkMR; R+dk;M RH;Tk gRTk; R5ld >Rld RHl; gRl> kP kP! kPB akP R1P 8kP RB", -"1P 1PRa Sk S!k STk Sak Sl Sl8 SlT Ssl kP( +kP P(kB ak+P R(1P 1PR+ kP(1B akP", -"1+ Sk( S+k TkS( +TSk Sl( l+S STl( l+Ss RWk R!Wk HkP WkRa R1W 1WR8 1HRW 1WRa", -" SWk WkS! SZk ZkSa lWS S8lW lZS lZSs dkP +kRW dkHP gkP 1WRd 1+RW dkP1H R1gP", -" Sdk +WSk ZkSd gSk ldS S+lW SZld glS Rmk R!km RBkm akRm R1m 1mR8 RB1m 1aRm ", -"Skm kmS! TkSm akSm Slp lpS8 lTSp Slsp k;P +kRm kB;P k;aP 1mR; >kP k;P1B ak>", -"P S;k +kS; TkS; akS; l;S S>l lTS; Ssl> WkRm km!RW HkRm akmRH 1WR5 R1W8m 1HR", -"m akPH5 WkSm S!Wkm SmZk SZakm SplW SlpW8 SplZ SZpls vRk R+vk RHvk vRgk vR1 ", -"vR>k R1vH gk>P Svk vkS+ ZkSv gkSv lvS S>lv lZSv ylS R9 R9& R9B R9a R91 :R 9", -"1RB :Ra R9M 9MR& R9T 9TRa lR9 l:R R9lT s:R R9( R9+ 9(RB 9+Ra 91R( :R+ R91(B", -" R+:a R(9M 9MR+ R(9T 9+RT R9l( :Rl+ lR9T( s+:R R9E REk& R9H 9HRa 91RE :RE 9", -"HR1 :RH RE9M k&ERM 9HRT R9HT& R9lE lE:R R9lH :RlH R9d 9+Rd 9HRd gR9 9dR1 :R", -"d R9H1d g:R 9MRd dk&RM 9TRd R9gM R9ld :Rld lHR9d gRl: R92 R2k& 92RB R29a R9", -"5 :R5 RB95 R5:a R29M k&2RM R29T R9T&2 R9l5 l5:R 95RT s5:R R9; 9+R; RB9; 9aR", -"; 95R; :>R R95;B :a>R 9MR; k;&RM 9TR; aM;R9 R9l; :Rl> l;R9T :>sR 9ER2 k&ER2", -" R29H R9H&2 RE95 R5:E 9HR5 RH:5 R9ME2 R9EM&2 R9HT2 aM2R9H lR95E :R5lE lHR95", -" :RHl5 9dR; dk&R; 9HR; R9g; 95Rd >R:d R9H1; :>gR R9dM; R9dM;& R9HT; gR9T; l", -"dR95 l>:Rd lH;R9 g:Rl> R9P kP& RB9P 9PRa 9PR1 :RP kPB91 Ra:P S9 S9& S9T S9a", -" Sl9 S: lTS9 S:s R(9P 9PR+ kP(9B akP9+ kP(91 R+:P 9P(R1B :R+aP S9( S9+ 9TS(", -" 9+Sa l(S9 S:+ Sl9T( S+s: R9W 9WR& 9HRW 9WRa 9WR1 :RW R9H1W RH:W S9W 9WS& S", -"Z9 Z9Sa S9lW S:W S9lZ S:Z 9WRd 9+RW dkP9H R9gP dkP91 R+:W 9HPR1d :RgP S9d 9", -"+Sd Z9Sd gS9 S9ld S:d SZ9ld gS: R9m 9mR& RB9m 9aRm 95Rm :Rm R95mB Ra:m S9m ", -"9mS& 9TSm 9aSm Sp9 S:p STp9 :pSs 9mR; 9+Rm k;P9B ak;9P k;P95 :R>P k;B95P :>", -"Ram S9; 9+S; 9TS; 9aS; S9l; S:> Sp9T; s:S> 9WRm km&RW 9HRm km&RH 95RW R5:W ", -"R9H1m RH:m 9WSm S9Wm& SmZ9 SZ9am SWp9 :WSp ZpS9 SZ:p vR9 R9v& R9vH vRg9 R9v", -"1 :vR vR91H gR:v Sv9 v9S+ ZvS9 g9Sv S9lv S:v Sv9lZ y:S RUk U!Rk RDk DkRa R1", -"U 1UR8 R1D 1URa UkRM RUkM! VRk RaVk lRU R8lU VlR VlsR UkR( RU+k R(Dk +kRD R", -"(1U 1UR+ R(1D 1+RD RUkM( R+UkM RkV( R+Vk RUl( R+lU VRl( lRV+ UkRE RUk!E HkR", -"D RHUak RE1U R1U8E 1URH R1HU8 RUkME U!kRME RHVk VRHak RUlE lRU8E VRlH lsVRH", -" RUdk R+Udk DkRd RDgk 1URd R1+Ud 1DRd R1gU dkMRU R+UdkM RdVk VRgk RdlU l+RU", -"d lRVd VlgR UkR2 RUk!2 R2Dk ak2RD 1UR5 R1U58 1DR5 R1D5a RUkM2 U!kRM2 RkV2 V", -"2Rak R5lU lRU58 lRV5 lsVR5 RUk; R+Uk; DkR; ak;RD 1UR; R1>U 1DR; R1>D k;MRU ", -"R+Uk;M R;Vk V+Rk; R;lU lR>U lRV; >RVl RUkE2 U!kRE2 RHUk2 RHUak2 R1U5E 1U5R8", -"E R1HU5 1UHR5a UkMRE2 !ER2UkM V2RHk ak2VRH lRU5E R5Ul8E VlRH5 Vs5lHR dk;RU ", -"R+Udk; RH;Dk gRUk; R1dU5 >kRUd R1HU; >kgRD RdUk;M dkR;U+M VdRk; gVRk; ldRU5", -" l>RUd lH;VR V>lgR UPk U!kP DkP akUP 1UP U81P 1PRD Ua1P SUk U!Sk SVk VaSk S", -"lU lUS8 SlV SVls U(kP +kUP D(kP Dk+P 1(UP U+1P R1DP( R1+DP UkS( U+Sk VkS( S", -"kV+ SUl( lUS+ l(SV SVl+ WkUP kP!UW HkUP akPUH 1URW R1WU8 1WRD R1WUa UWSk S!", -"UWk ZkSV SZVak SUlW SlUW8 SVlZ SlVsZ dkUP dkPU+ dkDP UPgk Ud1P dkPU8 dkP1D ", -"1UgP UdSk S+UWk SkVd SVgk lUSd S8dlU SVld SlgV kmUP km!UP DkRm akmRD 1URm R", -"1mU8 1DRm akPU5 UmSk S!Ukm SkVm SVakm pUSl SlpU8 SlVp SlVsp k;UP k;PU+ k;DP", -" ak;UP U;1P 1U>P k;P1D Dk>P U;Sk S+Ukm SkV; SV+km lUS; >USl SVl; SlV> RWUkm", -" RWUkm! RHmDk RWDakm R1WU5 1UWR8m R1HUm 1UHR8m SUWkm km!SUW SZVkm ZkVSam Sl", -"pUW lWpS8U SlVZp VplSsZ UPvk vRU+k RDvk gvRDk R1vU >kvUP R1vD >kgUP SUvk Sv", -"U+k vkSV VvgSk vUSl lv>SU SlVv SlyV tR tR& tRD tcR tR1 t:R R1tD :cR tRM R&t", -"M VtR VtcR ltR :Rlt lRVt uR tR( t+R RDt( cRt+ R1t( :Rt+ tR1D( :+cR RMt( R+t", -"M VRt( tRV+ tRl( lRt+ ltVR( uR+ tRE R&tE tHR cRtH R1tE tE:R R1tH :RtH RMtE ", -"tRM&E VRtH tcVRH tRlE t:RlE lRtH uRH tdR R+td RHtd gtR R1td :Rtd tHR1d t:gR", -" RdtM t+RdM tRVd VtgR lRtd t:dlR tdVlR ugR tR2 R&t2 RDt2 c2tR t5R :Rt5 R5tD", -" cRt5 RMt2 tRM&2 tRV2 tcVR2 lRt5 t:Rl5 tRV5 uR5 t;R R+t; RDt; cRt; R1t; t>R", -" t5RD; :Rc> R;tM t+RM; tRV; tc;VR lRt; >Rlt t5VR; u>R REt2 tR&E2 RHt2 tcRH2", -" R5tE t:R5E RHt5 t:HR5 tRME2 M&EtR2 tHVR2 cRVtH2 t5RlE lt5:RE tH5lR RHu5 Rd", -"t; t+Rd; RHt; t;gR R5td >Rtd tH5Rd gRt> tdRM; dM&t;R tH;VR gtVR; t5dlR t>lR", -"d tH;lR g>uR tP tP& tPD tcP tP1 t:P 1DtP :ctP St St& StV Sct Stl S:t SVlt u", -"S tP( t+P DPt( cPt+ 1Pt( :Pt+ tP1D( t:Pc+ St( St+ S(Vt tcS+ l(St l+St SlVt(", -" uS+ tWR RWt& tHP cRtW R1tW :RtW 1HtP :HtP StW tWS& tZS tZSc lWSt tWS: lZSt", -" uZS tdP R+tW HPtd gtP 1dtP :dtP tHP1d t:gP Std t+Sd SdtZ gtS ldSt t:Sd Std", -"lZ ugS tmR Rmt& RDtm cRtm t5P :Rtm 5DtP cR:m Stm tmS& tmSV tmSc tpS tpS: Vp", -"St upS t;P R+tm D;tP c;tP 1;tP t>P t5PD; tc>P St; t+S; t;SV S;tc l;St S>t S", -"t;Vp u>S RWtm tWRm& RHtm tcWRm R5tW t:WR5 H5tP t:HRm SWtm StWm& tmSZ ScZtm ", -"tWSp S:ptW SZtp SZup tvR vRt+ vRtH gRtv vRt5 >Ptv tvR1H >Pgt tvS S+tv StVv ", -"tvgS Stlv tvS: lvVSt yuS )O !)O )BO a)O )O. 8)O )O.B a)8O )OK )O!K T)O a)TO", -" jO) 8)jO T)jO s)O *O +*O *BO a*O *O. 8*O .B*O 8Oa* *OK *O+K T*O +OT* *jO j", -"O8* jOT* s*O E)O E)!O H)O a)HO )OE. E)8O )OH. 8)HO )OEK !E)OK T)HO HTa)O E)", -"jO jO8E) H)jO H)sO d*O d*+O H*O g*O *Od. d*8O *OH. 8*gO *OdK +d*OK HOT* T*g", -"O d*jO dj*+O jOH* gOs* )O2 )O!2 )O2B )Oa2 5)O 8)5O )B5O a)5O )O2K !)2OK )OT", -"2 Ta)O2 5)jO jO58) T)5O 5)sO ;*O ;*+O ;O*B ;*aO 5*O >*O 5O*B a*>O *O;K +;*O", -"K ;*TO a;*TO jO5* *j>O 5OT* >Os* )OE2 !)2EO )OH2 Ha)O2 E)5O 58E)O 5)HO H58)", -"O EK)O2 !)OEK2 HT)O2 Ta)HO2 jO5E) 58EjO) H5T)O sH5)O ;*dO +d;*O ;*HO ;*gO d", -"*5O d*>O HO5* g*>O dK;*O dK;+*O H;T*O gT;*O dj*5O >*djO H5*jO s*Og> P) P)! ", -"P)B aP) P). 8P) .BP) 8)aP QP) P)Q! TP) Q)aP Pj) Q)8P T)Pj sP) P* +P* P*B aP", -"* P*. 8P* P.*B aP8* Q*P Q*+P TP* T*+P P*j 8PQ* PjT* sP* WP) P)W! HP) H)aP P", -")W. W)8P P)H. H)8P QPW) Q!WP) ZP) aPZ) W)Pj Pj)W8 PjZ) ZPs) W*P W*+P HP* gP", -"* W.P* 8PW* H.P* 8Pg* dPQ* +WQP* Z*P Z*gP P*Wj dPj8* P*Zj s*gP mP) P!m) P)m", -"B mPa) 5P) 5)8P P)5B 5)aP mPQ) Q!mP) mPT) amPQ) pP) 8Pp) TPp) pPs) m*P m*+P", -" *B;P m*aP 5P* >P* *B5P aP>* ;PQ* m*P+Q m*TP am*TP p*P p*>P TPp* s*>P mPW) ", -"W!mP) mPH) amPH) WP5) 5W8P) H)5P H5P8) WQmP) WmPQ!) mPZ) ZamP) WPp) pW8P) p", -"PZ) sP)Zp vP* +Pv* HPv* vPg* 5Pv* vP>* 5PH* >*gP Q*vP v+QP* vPZ* ZvPg* vPp*", -" >Ppv* ZPp* y*P ,O ,&O ,OB ,aO ,O. ,8O .B,O 8a,O ,OK &O,K ,TO ,OT& ,jO ,O&j", -" jO,T s,O ,*O -O ,O*B -aO *O,. -8O *B,O. 8a-O *O,K -OK ,OT* -TO ,O*j -jO *j", -"O,T s-O ,EO &E,O ,HO ,OH& EO,. 8E,O HO,. ,OH8 EK,O ,&EOK HT,O ,HTaO jO,E &j", -"E,O ,OHj ,HsO ,dO -dO ,OH* g-O dO,. 8d-O ,HdO. -8gO dK,O dK-O ,OTd gO-T ,Od", -"j dj-O ,HjdO gOs- ,O2 &O,2 2B,O aO,2 ,5O ,O5& 5B,O ,O5a 2K,O ,&O2K TO,2 ,Ta", -"O2 jO,5 &jO,5 ,O5T ,5sO ,;O -;O ;O,B a;-O ,O5* ->O ,5;OB -a>O ;O,K ;O-K ,OT", -"; T;-O ,O;j >O-j ,5T;O >Os- EO,2 ,&EO2 HO,2 ,HaO2 5E,O ,58EO ,OH5 ,H58O ,EO", -"2K &EO,2K ,HTO2 H&O,T2 ,5jEO ,5E&jO ,H5jO s,H5O d;,O d;-O ,OH; -;gO ,O5d -d", -">O ,H5dO >Og- ,d;OK -d;OK ,H;TO -T;gO ,5djO ->djO ,H;jO s-g>O ,P ,P& ,PB ,a", -"P ,P. ,8P P.,B 8P,a ,QP Q&,P ,TP Qa,P ,Pj Q8,P TP,j sP, ,P* -P *B,P -Pa ,.P", -"* -P8 P*.,B 8P-a Q*,P -QP T*,P -TP P*,j -Pj P*j,T s-P ,WP W&,P ,HP HP,a WP,", -". W8,P ,.HP H8,P WQ,P ,WQP& Z,P ,aZP Wj,P P&j,W ,PZj Z,sP ,dP -WP HP,d g-P ", -",.dP W8-P ,HPd. g8-P Qd,P Qd-P ,dZP Z-P dP,j Wj-P Z*P,j gPs- ,mP m&,P mP,B ", -"am,P ,5P 5P,8 ,B5P 5a,P Qm,P m&P,Q Tm,P ,QamP p,P ,8pP ,TpP p,sP ,;P -mP ,B", -";P am-P 5P,; >P- ,5P*B -a>P Q;,P Q;-P T;,P Tm-P ,;pP -pP p*T,P >Ps- Wm,P m&", -"P,W Hm,P ,HmaP 5W,P ,5W8P H5,P ,H58P ,WQmP ,WQm&P ,mZP Z&m,P ,WpP p&W,P ZPp", -", sP,Zp v,P -vP ,HvP gP-v ,5vP >P-v v,H5P g->P ,QvP vQ-P ZPv, -PZv pPv, pv-", -"P Zp*,P y-P C)O C)!O D)O a)DO )OC. C)8O )OD. 8)DO )OCK !CO)K T)DO DTa)O C)j", -"O jO8C) D)jO D)sO *CO *C+O D*O +OD* CO*. *C8O *OD. DO8* CK*O +*COK DOT* a*O", -"DT *CjO *jC+O jOD* D*sO E)CO CE)!O D)HO HDa)O C).EO 8CE)O HD)O. H8D)O CE)OK", -" EK)!CO HDT)O DTaH)O jOCE) 8CEjO) HjD)O sHD)O *CdO +d*CO HOD* D*gO d*CO. 8d", -"*CO H*DO. gD8*O dK*CO dK*+CO H*DTO gDT*O dj*CO 8dC*jO H*jDO s*DgO )OC2 !)2C", -"O )OD2 Da)O2 C)5O 58C)O D)5O 5D8)O 2KC)O CKO!)2 DT)O2 Ta)DO2 jO5C) 58CjO) 5", -"DT)O s5D)O *C;O +;*CO ;*DO a;*DO *C5O *C>O 5OD* D*>O ;*COK ;*C+OK D;T*O D;T", -"a*O ;jC*O >*jCO 5D*jO >D*sO CE)O2 !O2CE) HD)O2 Da)HO2 5CE)O 8CE5)O H5D)O 5D", -")H8O C)OEK2 C)!OEK2 DT)HO2 DTH)aO2 5CEjO) 5)jO8CE 5D)HjO H5Ds)O d;*CO d;*+C", -"O H;D*O gD;*O 5d*CO >*dCO H5*DO >D*gO ;*CdKO dK+*;CO D;TH*O D;Tg*O 5dC*jO d", -"j*>CO djO5D* gs*>DO PC) !CP) DP) D)aP C)P. PC8) P)D. D)8P PCQ) Q!PC) Q)DP a", -"P)QD jCP) PjC8) D)Pj DPs) P*C +CP* DP* D*+P *CP. 8CP* D.P* 8PD* QCP* P*C+Q ", -"DPQ* aP*QD PC*j P*j+C P*Dj DPs* PCW) W!PC) H)DP aP)WD WPC). W8PC) HPD). H8P", -"D) WQPC) WPCQ!) DPZ) ZDaP) PjCW) W8CPj) ZDPj) sPDZ) WCP* dPC+* DPH* DPg* dP", -"C*. W8*PC HP*D. gPD8* dPCQ* +WQP*C DPZ* Z*DgP dPj*C dPCQ8* Z*DPj sP*gD PCm)", -" mPC!) mPD) amPD) PC5) 5P8C) 5)DP 5DP8) QmPC) mPCQ!) QDmP) QDmaP) PCp) p8PC", -") DPp) sPDp) mCP* m*P+C m*DP am*DP 5CP* P*>C DP5* DP>* m*PQC +QmP*C QD;P* Q", -"D;aP* P*pC >Pp*C DPp* sP*pD WmPC) mPCW!) HmDP) HmDaP) 5WPC) W8C5P) H5PD) aP", -")5WD QmPWC) W)Q!mPC ZDmP) amPZD) pWPC) W8PpC) ZpDP) ZpDsP) P*vC v+P*C DPv* ", -"gvDP* v5P*C >Pv*C vD5P* >PgD* vQP*C P*Cv+Q ZvDP* gvDZ*P pvP*C pv*>PC Zp*DP ", -"DPy* ,bO b&,O ,DO c,O bO,. ,Ob8 DO,. ,8cO bK,O ,b&OK ,ObT ,TcO ,Obj &jO,b ,", -"ODj c,sO b*O -bO ,OD* c-O *Ob. b8-O ,D*O. -8cO *ObK bK-O bOT* cO-T jOb* bj-", -"O ,Dj*O sOc- bE,O ,b&EO ,ObH ,HcO ,bEO. ,8bEO ,HbO. cH8,O ,bEOK bK&,EO ,HbT", -"O cHT,O ,jbEO b8E,jO ,HjbO s,HcO ,Obd bd-O ,ODd gOc- ,dbO. -b8dO ,DdO. c-8g", -"O ,dbOK -bdOK ,DdTO c-TgO ,djbO -jbdO ,DdjO s-gcO bO,2 ,b&O2 DO,2 ,Oc2 ,Ob5", -" ,5b8O ,O5D ,5cO ,bO2K bK&,O2 ,DTO2 c2T,O ,5bjO ,5b&jO ,5DjO s,5cO ,Ob; b;-", -"O ,OD; -;cO bO5* -b>O ,5D;O >Oc- ,;bOK -b;OK ,D;TO c-T;O ,;jbO ->bjO ,D;jO ", -"s-c>O ,bEO2 b&E,O2 ,HbO2 c2H,O ,5bEO b5E,8O ,H5bO c5H,O bKE,O2 EO,2bK& bHO,", -"T2 ,HTc2O b5E,jO 5jbE,8O ,HOb5T c5Hs,O ,db;O -bd;O ,H;bO c-;gO ,5dbO ->bdO ", -",5DdO c>g-O bdO,;K bd;-OK ,HObT; -T;gcO djOb5* >bd-jO djO,5D c>gs-O ,Pb ,bP", -"& ,DP cP, ,.bP b8,P ,.DP ,8cP bQ,P ,QbP& bT,P ,QcP bP,j P&j,b DP,j cPs, bP*", -" -Pb DPb* c-P b.P* b8-P ,DP*. c8-P Q*bP bQ-P TPb* -QcP P*bj bP-j P*j,D c-sP", -" bW,P ,WbP& bH,P ,HcP ,WbP. ,W8bP ,HPb. cW8,P ,WbQP bWQ,P& ,DZP cPZ, ,WjbP ", -"bW8,Pj ZbP,j sP,Zc bd,P bW-P HPb* c-gP ,dPb. -Wb8P ,DdP. c-W8P ,QdbP -WbQP ", -"bPZ* cPZ- dPjb* -WjbP Zb*Pj s-PZc bm,P m&P,b Dm,P ,mcP b5,P ,5Pb8 5D,P ,5cP", -" ,QbmP ,Qbm&P ,QDmP cQm,P ,Ppb pb8,P ,DpP p,cP b;,P bm-P D;,P -mcP 5Pb* >b-", -"P ,5D;P c->P ,Q;bP -Qb;P ,QD;P c-Q;P bPp* pb-P pb*DP cP-p ,WbmP ,Wbm&P ,Hmb", -"P cWm,P ,5WbP b5W,8P ,H5bP c5W,P bWQ,mP QmP&,Wb Zbm,P ZcP,m pbW,P ,W8pbP Zp", -"b,P cpZ,P ,Pvb vb-P ,DvP cP-v vb5,P -v>bP vD,5P cv->P vbQ,P -vbQP Zvb,P cvZ", -"-P pvb,P -pvbP ZpbP* c-yP 0)O 0)!O 0)OB 0)aO 1)O 8)1O )B1O a)1O )O0K !K0)O ", -"0)TO Ta0)O 1)jO jO18) T)1O 1)sO *0O *0+O 0B*O *0aO 1*O 1O8* 1O*B 1Oa* 0O*K ", -"+*0OK *0TO a*0TO jO1* *jO1+ 1OT* 1*sO 0)EO !E)0O 0)HO Ha0)O E)1O 18E)O H)1O", -" 1H8)O EK0)O !0OEK) HT0)O Ta0H)O jO1E) 18EjO) 1HT)O s1H)O *0dO +d*0O *0HO *", -"0gO d*1O 1+d*O 1OH* 1*gO dK*0O dK*+0O H*T0O gT*0O dj*1O 1+d*jO 1H*jO s*1gO ", -")O02 0)2!O 0)2OB a0)O2 5)1O 158)O 15)OB 1a5)O 0)2OK !)O2K0 T0)O2 a0)TO2 jO1", -"5) 158jO) 1T5)O s15)O *0;O +;*0O *B;0O a;*0O 1O5* 1*>O 1;*OB >*1aO ;*0OK ;*", -"0+OK T;*0O T;0a*O ;jO1* >*1jO 1T;*O s*1>O 0)2EO !EO0)2 H0)O2 a0)HO2 15E)O 5", -"8E1)O 1H5)O H5)1aO E)O2K0 0)EO2K! T0)HO2 0)HOTa2 15EjO) 5)jO18E H5)1TO 1H5s", -")O d;*0O d;*+0O H;*0O g;*0O 1d5*O >*1dO 1H;*O g>1*O ;*0dKO dK+*;0O T;0H*O T", -";*g0O 1d5*jO dj*>O1 ;jO1H* g>1s*O P0) !0P) )BP0 P0a) 1P) 1)8P P)1B 1)aP P0Q", -") Q!P0) P0T) aP0Q) 1)Pj Pj)18 1)TP 1Ps) P*0 +0P* P0*B a0P* 1P* +P1* *B1P aP", -"1* Q0P* P*0+Q T0P* aP*Q0 Q*1P P*j1+ TP1* 1Ps* P0W) W!P0) P0H) aP0H) WP1) 1W", -"8P) 1)HP 1HP8) WQP0) WP0Q!) P0Z) ZaP0) Pj)1W 1W8Pj) 1PZ) sP1Z) W0P* dP0+* H", -"0P* P*g0 W*1P 1+WP* HP1* 1Pg* dP0Q* +WQP*0 P*Z0 Z*Pg0 dPj1* 1+WP*j 1PZ* sP*", -"g1 P0m) mP0!) mP0)B amP0) 1)5P 1m8P) 1mP)B 1amP) QmP0) mP0Q!) TmP0) Tm0aP) ", -"1Pp) p18P) p1TP) sP1p) m0P* m*P+0 m*P0B am*P0 5P1* 1P>* 1m*PB >P1a* m*PQ0 +", -"QmP*0 Tm*P0 am0TP* 1Pp* >Pp1* p*1TP sP*p1 WmP0) mP0W!) HmP0) Hm0aP) 1W5P) 5", -"W81P) 1HmP) am)1HP QmPW0) P!m0WQ) ZmP0) amPZ0) p1WP) 1W8pP) Zp1P) Zp1sP) P*", -"v0 v+P*0 vHP*0 gvP*0 1Pv* >Pv1* v1HP* >Pg1* vQP*0 P*0v+Q ZvP*0 gvPZ*0 pv1P*", -" pv1>P* Zp*1P 1Py* ,9O 9&,O 9O,B ,O9a ,1O :,O 1O,B ,a:O 9O,K ,9&OK ,O9T ,T9", -"aO ,O9j ,j:O ,O1T :,sO 9*O -9O 9O*B 9a-O ,O1* :-O ,1*OB -a:O *O9K 9O-K 9OT*", -" 9T-O jO9* :O-j ,1T*O sO:- 9E,O ,9&EO ,O9H ,H9aO 1E,O ,E:O ,O1H ,H:O ,9EOK ", -"9&E,OK ,H9TO 9HT,aO ,1jEO :j,EO ,1HjO s,H:O ,O9d 9d-O 9OH* -9gO ,O1d -d:O ,", -"1HdO gO:- ,d9OK -9dOK ,Td9O -T9gO ,1djO :-djO ,1TdO g:s-O 9O,2 ,9&O2 ,9O2B ", -",a9O2 ,O95 ,5:O ,15OB :5a,O ,9O2K 9&O,2K ,T9O2 9TO,a2 ,15jO :5j,O ,1T5O s,5", -":O ,O9; 9;-O ,;9OB -9a;O ,O1; >O:- ,1;OB :->aO ,;9OK -9;OK ,T;9O -T9;O ,1;j", -"O :->jO ,1T;O s-:>O ,9EO2 9&E,O2 ,H9O2 9HO,a2 ,15EO :5,EO ,1H5O :H5,O 9EO,2", -"K EO,29&K 9HO,T2 HO,29Ta 95E,jO ,5j:EO ,HO95T :H5s,O ,d9;O -9d;O ,H;9O g-9;", -"O ,1d5O :->dO ,1H;O g:->O 9dO,;K 9d;-OK ,HO9T; g9;-TO djO,1; ->j:dO ;jO,1H ", -"s->g:O ,P9 ,9P& ,B9P 9a,P ,1P :P, ,B1P ,a:P 9Q,P ,Q9P& 9T,P ,Qa9P 9P,j ,Q:P", -" 1T,P :Ps, 9P* -P9 *B9P 9a-P 1P9* :-P ,1P*B :a-P Q*9P 9Q-P TP9* 9T-P P*9j -", -"Q:P P*j9T :-sP 9W,P ,W9P& 9H,P ,HP9a 1W,P ,W:P 1H,P ,H:P ,W9QP 9WQ,P& ,PZ9 ", -"Z9a,P ,1WPj :WQ,P ,1ZP :PZ, 9d,P 9W-P HP9* -Pg9 1d,P -W:P ,1HdP :-gP ,Qd9P ", -"-W9QP 9PZ* -PZ9 dPj,1 :-WPj Z9*1P :PZ- 9m,P m&P,9 ,m9PB ,am9P 95,P ,5:P ,1m", -"PB :ma,P ,Q9mP ,Q9m&P ,Tm9P 9Tm,aP ,1pP p,:P p9T,P sP,:p 9;,P 9m-P ,;P9B -m", -"9aP 1;,P :->P ,1;PB :-maP ,Q;9P -Q9;P ,T;9P -Tm9P 9Pp* :P-p p9*TP -ps:P ,W9", -"mP ,W9m&P ,Hm9P 9Hm,aP ,1W5P :W5,P ,1H5P :Hm,P 9WQ,mP QmP&,W9 Z9m,P ,amZ9P ", -"p9W,P :pW,P Zp9,P Z:p,P ,Pv9 v9-P v9H,P -vg9P ,1vP :P-v v1,HP :v-gP v9Q,P -", -"v9QP Zv9,P Z-v9P pv9,P :v-pP Zp9P* :-yP 0)CO C0)!O 0)DO Da0)O C)1O 18C)O D)", -"1O 1D8)O C0)OK !K)C0O DT0)O Ta0D)O jO1C) 18CjO) 1DT)O s1D)O C0*O +*C0O *0DO", -" a*0DO *C1O 1+*CO 1OD* 1+D*O *C0OK *C0+OK D*T0O D*0+TO *jC1O 1+C*jO 1D*jO s", -"*1DO C0)EO !E)C0O HD0)O Da0H)O 1CE)O 8CE1)O 1HD)O H8)1DO EK)C0O 0)EOCK! DT0", -"H)O 0)HODTa 1CEjO) C)8O1jE Hj)1DO 1HDs)O d*C0O d*C+0O H*D0O gD*0O 1d*CO 8dC", -"1*O 1H*DO g1D*O *C0dKO C0dO+*K Td0D*O D*Tg0O 1dC*jO dj1*+CO djO1D* g1Ds*O C", -"02)O !)2C0O D0)O2 a0)DO2 15C)O 58C1)O 1D5)O 5D)1aO CKO0)2 0)C2!KO T0)DO2 0)", -"TODa2 15CjO) 5)jO18C 5D)1TO 1D5s)O ;*C0O ;*C+0O D;*0O D;0a*O 1;*CO >*1CO 1D", -";*O >D*1O *C0;OK C0;O+*K T;0D*O a;D*T0O 1;C*jO *jC>O1 ;jO1D* s*1>DO CEO0)2 ", -"0)C2!EO D0)HO2 0)HODa2 5CE1)O 5E1O8C) H5)1DO 5OD81H) 0)C2EKO C)!OE02K 0)HOD", -"T2 DaHO0)T2 5)jO1CE 5j1EC)8O H)Dj15O 15s)HDO ;*Cd0O C0;O+d* D;0H*O D;*g0O 5", -"dC1*O 1d*>CO 1HO5D* g1*>DO C0;OdK* dK+*C0;O T;H*D0O D*g0T;O dj1;*CO dj>*1CO", -" jOH;1D* >Dgs1*O C0P) PC0!) P0D) aP0D) PC1) 1P8C) 1)DP 1DP8) QPC0) PC0Q!) Q", -"DP0) QD0aP) PjC1) Q8C1P) 1QDP) sP1D) *CP0 P*C+0 D0P* aP*D0 1CP* 1+P*C DP1* ", -"aP*1D P*CQ0 +QCP*0 QD*P0 aP0QD* P*j1C P*C1+Q P*j1D sP*1D WPC0) PC0W!) HPD0)", -" WD0aP) 1WPC) W8C1P) 1HPD) aP)1WD QPCW0) QCW0P)! ZDP0) aP0ZD) 1WCPj) QC8P1W", -") Z1DP) Z1DsP) dPC*0 +WCP*0 HP*D0 gPD*0 1W*PC P*C1+W 1HPD* g1PD* QdCP*0 QCd", -"P+*0 Z*DP0 gPDZ*0 dPC1Q* WC*j1+P Z1*DP sPDZ1* mPC0) PC0m)! DmP0) Dm0aP) 1mP", -"C) 8mC1P) 1DmP) am)1DP mPCQ0) P!m0QC) Tm0DP) amDPQ0) p1PC) 1P8pC) pD1P) pD1", -"sP) m*PC0 +mCP*0 Dm*P0 am0DP* 1m*PC >P1*C 1DmP* >PD1* Q;CP*0 QCm*+P0 ;P0QD*", -" m*DP+Q0 p*1PC p*1>PC pD*1P sP1pD* mPCW0) P!m0WC) Dm0HP) amHPD0) 5WC1P) W)8", -"P1mC 1H)5DP H)8m1DP QCW0mP) !Cm)QPW0 DmPZ0) amZPD0) 1WPpC) 18pCWP) pDPZ1) s", -"1pDZP) vP*C0 P*Cv+0 vDP*0 gP*vD0 v1P*C v1*>PC v1DP* >D*g1P P*CvQ0 P*vC+Q0 v", -"DPZ*0 gDZ*vP0 v1Pp*C >*v1pPC Z1PpD* y*1DP b9,O ,b9&O ,O9D ,9cO ,Ob1 ,b:O ,O", -"1D c,:O ,b9OK b9&,OK ,D9TO c9T,O ,1bjO :bj,O ,1DjO s,O:c bO9* b9-O 9OD* -9c", -"O bO1* -b:O ,1D*O :Oc- b*9OK -b9OK bT*9O c-9TO b1*jO :-bjO b1T*O s-:cO ,b9E", -"O b9&,EO ,H9bO c9H,O ,1bEO :b,EO ,1HbO :cH,O b9E,OK b9,&EKO bH9,TO ,H9cTO b", -"1E,jO ,jb:EO ,1ObHj :cHs,O ,db9O -b9dO ,Dd9O c-9gO ,1dbO :-bdO ,1DdO g:c-O ", -"9dOb*K bd9-OK ,DO9Td -T9gcO djOb1* -jb:dO djO,1D s-cg:O ,b9O2 b9&,O2 ,D9O2 ", -"c29,O ,1b5O :b5,O ,1D5O :c5,O b9O,2K bO,29&K 9DO,T2 ,T9c2O b15,jO ,5b:jO ,1", -"Ob5T :c5s,O ,;b9O -b9;O ,D;9O c-9;O ,1;bO :->bO ,1D;O c>:-O 9;Ob*K b;9-OK ,", -"DO9T; -T9c;O ;jOb1* -jb:>O ;jO,1D c>:s-O b9E,O2 EO,2b9& 9HO,D2 ,H9c2O b1E,5", -"O ,5b:EO ,1ObH5 c5,:HO EO,2b9K 9&,KEOb2 HO,2bT9 ,9c2HTO 5E9O,jb ,b:EjO5 ,O1", -"Hb5T sHc5:,O bd9,;O bd9-;O ,HO9D; g-9c;O ,1Ob5d ->b:dO ,1ObH; c>-g:O ,Obd9;", -"K b9-OdK; ,OH;bT9 gTc;-9O ,O1db;j >j:d-bO 1H,;bTO >Og:s-c ,b9P ,P9b& 9D,P ,", -"Pc9 b1,P ,P:b 1D,P :,cP ,Qb9P bQ9,P& ,QD9P cQ9,P ,1QbP :Qb,P ,1QDP sP,:c 9P", -"b* bP-9 DP9* c9-P 1Pb* :b-P ,1DP* c-:P bQ*9P -Qb9P bTP9* c-Q9P P*jb1 :-QbP ", -"P*j9D s-P:c ,Wb9P bW9,P& ,HP9D cW9,P ,1WbP :Wb,P ,1HbP :cW,P bW9,QP WQP&,b9", -" Zb9,P Zc9,P b1W,Pj ,Wj:Pb Zb1,P Z:c,P ,dPb9 -Wb9P ,Dd9P c-W9P ,1dbP :-WbP ", -",1DdP g:Pc- 9QdbP* bQd-P9 Zb*9P Z-c9P b1WP*j :Wb-Pj Zb1P* Z:-cP ,mb9P bm9,P", -"& ,Dm9P cm9,P ,1mbP :mb,P ,1D5P :cm,P bQ9,mP QmP&,b9 9Dm,TP ,TmcP9 pb9,P :p", -"b,P p9D,P cp:,P ,;Pb9 -mb9P ,D;9P c-m9P ,1;bP :-mbP ,1D;P c>P:- 9Q;bP* bQ;-", -"P9 9QD,;P cm9-TP pb*9P -p:bP p9DP* cp-:P bW9,mP WmbP,9& 9Hm,DP ,HmcP9 b1W,5", -"P ,5W:Pb b1H,5P :H,c5P QmbP,W9 ,bP&WQ9m ,DmZ9P cm9Z,P ,1WpbP pbW:P, Z9PpD, ", -"Z:Pcp, vb9,P -vb9P v9D,P cv-9P vb1,P :v-bP v1D,P :vc-P bQ*v9P vb9-QP Z9PvD,", -" Z-9cvP pbPv1, -pb:vP ZbPp9* y:c-P R) R)! R)B Ra) R). R8) .BR) 8aR) RM) M)R", -"! RT) R)aM Rj) R)8M TjR) sR) R* R+* R*B Ra* R*. R8* R.*B 8*Ra R*M +MR* RT* ", -"+TR* R*j +jR* T*Rj sR* RE) !ER) RH) HaR) E)R. 8ER) H)R. R)H8 MER) RME!) R)H", -"M aM)RH jER) R8ME) R)Hj RHs) Rd* +dR* RH* gR* d*R. 8dR* R.H* R8g* dMR* dM*R", -"+ HMR* RTg* djR* R+jd* H*Rj s*gR R)2 !)R2 2BR) a)R2 R5) 58R) 5BR) R)5a M)R2", -" RM)!2 T)R2 aM)R2 R)5M R58M) R)5T R5s) R;* +;R* *BR; a;R* R5* >R* *BR5 Ra>*", -" M;R* M;*R+ T;R* aM;R* 5MR* R*>M 5TR* >Rs* E)R2 RE)!2 H)R2 RHa)2 5ER) R58E)", -" R)H5 RH58) RME)2 ME)R2! RHT)2 RH)aM2 R5ME) 5MER8) RH5T) sRH5) d;R* R+d;* H", -";R* R;g* 5dR* Rd>* H5R* >*gR dM;R* R+dM;* RH;T* gRT;* R5dM* >MRd* RH5T* >Mg", -"R* RP) P)R! P)RB R)aP P)R. R)8P RP).B aP)R8 S) S!) ST) Sa) Sj) S8) TjS) Ss)", -" R*P +PR* RP*B aPR* R.P* 8PR* P*.RB aP*R8 S* S+* S*T Sa* S*j S8* T*Sj Ss* R", -"W) W!R) R)HP R)Wa W)R. R)W8 RHW). RH8W) SW) W!S) SZ) ZaS) WjS) W8S) ZjS) s)", -"SZ RW* +WR* HPR* RWg* R.W* W8R* RH*W. gRW8* Sd* +WS* SZ* gS* W*Sj W8S* SjZ*", -" s*gS Rm) m)R! m)RB R)am R)5P R)8m R5m)B R5am) Sm) m)S! TmS) amS) Sp) p8S) ", -"pTS) s)Sp Rm* +mR* *BRm amR* 5PR* Rm>* R5*mB >PRa* S;* +mS* TmS* amS* Sp* S", -">* STp* s*S> WmR) RWm!) R)Hm RHma) R)5W R5W8) RH5W) RH8m) WmS) S!Wm) ZmS) S", -"Zam) pWS) SpW8) S)Zp SZps) vR* R+v* RHv* g*vR R5v* >*vR vRH5* >PgR* Sv* v+S", -"* ZvS* S*gv pvS* v>S* ZpS* yS* ,R ,R& ,RB ,Ra ,R. ,R8 RB,. R8,a ,RM R&,M ,R", -"T RT,a ,Rj R8,M RT,j sR, ,R* -R *B,R -Ra ,.R* -R8 ,R*.B R8-a R*,M -RM R*,T ", -"-RT R*,j -Rj ,RT*j s-R ,RE ,ER& ,RH RH,a RE,. ,ER8 ,.RH RH,8 RM,E M&E,R RH,", -"T ,RHT& ,ERj ,R8ME RH,j ,RsH ,Rd -Rd RH,d g-R ,.Rd R8-d ,RHd. g8-R Rd,M Rd-", -"M RT,d -RgM Rd,j Rd-j ,RHdj gRs- ,R2 ,2R& RB,2 ,2Ra ,R5 R5,8 RB,5 R5,a RM,2", -" M&2,R ,2RT ,RT&2 R5,M ,R58M R5,T ,Rs5 ,R; -R; RB,; Ra-; R5,; ->R ,R5*B -a>", -"R R;,M R;-M RT,; RT-; R;,j -R>M ,R5T; ->sR RE,2 ,R&E2 ,2RH ,RH&2 ,ER5 ,R58E", -" RH,5 ,RH5a ,RME2 ,REM&2 ,RHT2 aM2,RH ,R5ME M&E,R5 ,RH5T sR,H5 Rd,; Rd-; RH", -",; g;-R R5,d -d>R ,RH5d ->gR ,RdM; -RdM; ,RHT; -RTg; ,R5dM >M-Rd ,RH;j s-Rg", -"> ,RP R&,P RB,P Ra,P RP,. R8,P ,RP.B ,R8aP S, S&, S,T Sa, S,j S8, ,TSj Ss, ", -"R*,P -RP P*B,R Ra-P P*.,R R8-P ,R.P*B -R8aP S*, S- ,TS* S-T ,jS* S-8 S*T,j ", -"S-s ,RW R&,W RH,W RW,a ,.RW RW,8 ,RHW. ,RHW8 S,W ,WS& SZ, Z&S, ,WSj ,WS8 Sj", -"Z, s,SZ RW,d -RW ,RHW* -RgP ,RWd. RW-8 dP.,RH -RWg8 Sd, S-W Z*S, gS- ,dSj -", -"WS8 SZ*,j s-gS ,Rm R&,m RB,m Ra,m R5,m R8,m ,R5mB ,R5am S,m ,mS& ,TSm ,aSm ", -"Sp, p&S, STp, s,Sp Rm,; -Rm ,Rm*B Ra-m ,R5m* -R>P m*B,R5 >P-Ra S;, S-m ,TS;", -" -TS; p*S, S-p Sp*,T s-S> RW,m ,RWm& RH,m ,RHam R5,W ,R5W8 ,RH5W ,RH8m ,WSm", -" S&W,m SmZ, SZ&,m SWp, Sp&,W ZpS, Ss,Zp vR, -vR ,RvH gR-v ,Rv5 v>-R vR,H5 -", -"vRg> Sv, S-v ZvS, SvZ- pvS, Sv-p Sv,Zp y-S RU) U!R) RD) R)Ua U)R. R)U8 D)R.", -" R)D8 UMR) RUM!) VR) RaV) R)Uj R8UM) RjV) VRs) R*U U+R* RD* UaR* R.U* U8R* ", -"R.D* D8R* RUM* R+UM* V*R R+V* U*Rj R+jU* R*Vj V*sR UER) RUE!) R)UH RHUa) RU", -"E). R8UE) RHU). RH8U) RUME) U!MRE) RHV) VRHa) RjUE) U8ERj) VRHj) VsHR) UdR*", -" R+Ud* UHR* RDg* RdU*. R8dU* RH*U. gRU8* dM*RU R+UdM* RHV* V*gR RdjU* U8dR*", -"j VdR*j s*VgR U)R2 RU)!2 D)R2 RDa)2 R)U5 R5U8) R)5D R5D8) RUM)2 U!MR)2 R)V2", -" V2Ra) R5UM) U58Rj) R5V) Vs5R) U;R* R+U;* D;R* R+D;* U5R* R*>U 5DR* RD>* M;", -"*RU R+UM;* R;V* V+R;* R5*Uj >MRU* R5V* >RV* RUE)2 U!ER)2 RHU)2 UH)Ra2 R5UE)", -" U5ER8) RH5U) RH)U5a UMER)2 !ER)UM2 V2RH) RHaV2) U5ERj) REU85M) V5RH) sRHV5", -") RdU;* U+dR;* RH;U* gRU;* R5dU* >RUd* RH5U* g>RU* RdUM;* dMR;U+* VdR;* gVR", -";* U5dR*j Rdj>U* V5dR* V>gR* UP) P)U! R)DP U)aP P)U. U)8P RDP). RD8P) SU) U", -"!S) SV) VaS) UjS) U8S) VjS) s)SV UP* +PU* DPR* aPU* U.P* 8PU* RD*P. aP*U8 S", -"*U U+S* SV* V+S* U*Sj U8S* SjV* s*SV R)UW RWU!) R)WD RWDa) RWU). RW8U) RWD)", -". RWD8) UWS) S!UW) S)VZ SZVa) SUWj) S8UW) SZVj) SsZV) UWR* R+WU* HPU* UPg* ", -"RW*U. RW8U* RWD*. gUP8* UWS* S+UW* Z*SV S*gV SdU*j S8dU* SZ*Vj Ss*gV R)Um R", -"mU!) R)Dm RDma) U)5P R8mU) R5Dm) RD8m) UmS) S!Um) S)Vm SVam) S)pU SpU8) S)V", -"p SspV) UmR* R+mU* DmR* am*RD 5PU* UP>* R5Dm* >PUD* UmS* S+Um* VmS* SV+m* p", -"US* >US* S*Vp S*V> RWUm) UW)Rm! RHmU) am)RWD R5WU) R5)UW8 R5WD) aP)UH5 SUWm", -") UWmS!) SZVm) VZmSa) SpUW) pUWS8) SZpV) VpZSs) R*vU vRU+* RDv* gvRU* vRU5*", -" >PUv* vRD5* >PgU* vUS* SvU+* S*Vv VvgS* Sp*vU S>vU* VvpS* SVy* ,Rb R&,U ,R", -"D cR, ,.Rb Rb,8 ,.RD ,Rc8 Rb,M ,RbM& V,R V,cR Rb,j ,R8bM ,RVj cRs, Rb* -Rb ", -"R*,D c-R R.b* Rb-8 ,RD*. c8-R bMR* Rb-M ,RV* V-R b*Rj Rb-j V*R,j sRV- ,ERb ", -",Rb&E Rb,H ,RcH ,RbE. ,R8bE ,RHb. cRH,8 ,RbME ,RbM&E ,RVH cRV,H ,RjbE ,Rb&j", -"E V,RHj s,VRH Rb,d Rb-d RD,d c-gR ,Rdb. -Rb8d ,RDd. c-Rg8 ,RdbM -RbdM ,RVd ", -"gRV- ,Rdbj -Rjbd Vd,Rj V-gsR ,2Rb ,Rb&2 ,2RD ,Rc2 Rb,5 ,R5b8 R5,D ,Rc5 ,RbM", -"2 ,RbM&2 ,RV2 cRV,2 ,R5bM Rb5,8M ,RV5 s,VR5 Rb,; Rb-; RD,; -Rc; b5R* >R-U ,", -"R5D; ->cR ,R;bM -RbM; ,RV; V;-R ,R;bj >M-Rb V5*,R -RV> ,RbE2 R&E,U2 ,RHb2 c", -"RH,2 ,R5bE ,REU5& ,RHb5 cR5,H RbE,M2 bER2,M& V,RH2 V,HcR2 ,REb5M ,ER5b8M V5", -",RH s,HcR5 ,Rdb; -Rbd; ,RHb; c-Rg; ,R5bd ->Rbd ,R5Dd c>Rg- Rbd,M; Rbd-M; Vd", -",R; V-gR; Rb5,dM -Rb>Md V5d,R V->gR ,UP U&,P RD,P ,RcP ,.UP U8,P ,RDP. cR8,", -"P Sb, ,US& SV, Sc, ,USj ,US8 SjV, s,Sc bPR* -UP ,RDP* -RcP ,UP*. U8-P P*.,R", -"D c-R8P Sb* S-b V*Sb Sc- b*Sj -US8 SV*,j s-Sc Rb,W ,RWU& RW,D ,RcW ,RWb. ,R", -"Wb8 ,RWD. cRW,8 ,USW SbW,& ZbS, S,Zc SbW,j Sb8,W SZb,j Ss,Zc bWR* Rb-W ,RWD", -"d -RcW ,UdP. -RWb8 dP.,RD c-RW8 ,USd -USd ZbS* Z-Sc Sbd,j S-bW8 SZb*j gScs-", -" Rb,m ,RmU& RD,m ,Rcm U5,P ,R8bm ,R5Dm cR5,m ,USm Sbm,& VmS, cmS, pbS, Spb,", -"8 S,Vp S,cp bmR* Rb-m ,RDm* -Rcm ,U5;P -U>P R5D,;P c>R-m ,US; -US; V;S, S;V", -"- pbS* Sb-p Vp*Sb cpS- ,RWbm RW&,Um ,RHbm cRW,m ,R5bW Rb5,W8 ,R5WD cR5,W Sb", -"W,m ,UWS&m SZb,m ScZ,m Spb,W S8WpU, Vp,SZ ScpZ, ,Rvb vR-U ,RvD cR-v vRb,5 -", -"vR>b vRD,5 cvR-> vbS* Sb-v S,Vv cvS- Svbp* -pUSv Vv,Sp Scy- Rk) k)R! k)RB R", -")ak R1) R)8k 1)RB R)1a kMR) RkM!) R)Tk ak)RT lR) R8l) RTl) l)sR R*k +kR* Rk", -"*B akR* R1* 1+R* *BR1 1aR* RkM* k*MR+ TkR* ak*RT l*R R+l* RTl* sRl* kER) Rk", -"E!) R)Hk ak)RH 1ER) R18E) R)1H R1H8) RkME) kMER)! RHTk) RHTak) REl) lR8E) R", -"Hl) lsRH) dkR* dk*R+ HkR* R*gk 1dR* R1+d* 1HR* R1g* dkMR* R+dk*M RH*Tk gRTk", -"* Rdl* l+Rd* RHl* gRl* k)R2 Rk)!2 Rk)2B ak)R2 R)5k R158) R15)B R1a5) RkM)2 ", -"kM)R2! RTk)2 RT)ak2 R5l) lR58) lR5T) lsR5) k;R* k;*R+ k;*RB ak;R* 1;R* R1>*", -" R1;*B >kRa* k;MR* R+kM;* RT;k* RT;ak* R5l* >Rl* l;RT* l>sR* RkE)2 kE)R2! R", -"Hk)2 RH)ak2 R15E) 5kER8) R1H5) ak)RH5 kMER)2 !ER)kM2 Hk)RT2 akHMR)2 lR5E) R", -"58lE) lHR5) sR5lH) dk;R* R+dk;* RH;k* gRk;* R1d5* >kRd* R1H5* >kgR* RdkM;* ", -"dkR;+M* Hk;RT* RT;gk* ldR5* l>Rd* lH;R* gl>R* kP) k!P) P)kB a)kP R)1P 8)kP ", -"kP)1B akP1) Sk) k)S! TkS) akS) Sl) l)S8 STl) l)Ss kP* k*+P *BkP kPa* 1PR* k", -"P8* kP*1B akP1* S*k +kS* TkS* akS* l*S S+l* lTS* l*Ss R)Wk kP)W! H)kP akPH)", -" R)1W R1W8) R1HW) R1Wa) WkS) S!Wk) S)Zk SZak) SWl) Sl8W) l)SZ SslZ) WkR* dk", -"P+* kPH* kPg* 1WR* dkP8* kP*1H gR1W* WkS* S+Wk* ZkS* S*gk Sdl* S8dl* SZl* l", -"*gS R)km km)R! km)RB akmR) R)1m R1m8) R1m)B akP5) kmS) S!km) STkm) Sakm) l)", -"Sp Slp8) SlpT) Sslp) kmR* km*R+ km*RB akmR* 1mR* kP>* kP*5B >kPa* kmS* S+km", -"* S;Tk* Sa;k* Spl* l*S> Sp*lT Ss*l> km)RW RW)km! RHmk) ak)RHm R1W5) km)RW8 ", -"R1Hm) ak)R5W SWkm) km)S!W SZkm) ZkmSa) SlpW) lWpS8) SZpl) lZpSs) R*vk vR+k*", -" vRHk* gvRk* R1v* >kvR* vR1H* >kgP* vkS* Sv+k* SZ*vk gSvk* l*Sv lv>S* lvZS*", -" l*yS ,R9 R&,k RB,k R9,a ,R1 :R, RB,1 ,R:a R9,M ,R9M& R9,T ,RT9a l,R :Rl, ,", -"RlT sRl, R9* -R9 *BR9 R9-a R*,1 :-R ,R1*B :a-R 9MR* R9-M 9TR* R9-T ,Rl* l-R", -" l*R,T sRl- ,ER9 k&E,R R9,H ,RH9a ,ER1 ,R:E R1,H ,R:H ,R9ME ,R9M&E ,RH9T R9", -"H,aM ,RlE :R,lE ,RlH :RHl, R9,d R9-d 9HR* -Rg9 R1,d -R:d ,R1H* :-gR ,Rd9M -", -"R9dM ,RT9d -RTg9 ,Rld -Rld lH*,R gRl- ,2R9 k&2,R ,R92B ,Ra92 R9,5 ,R:5 ,R15", -"B :R5,a ,R9M2 ,R9M&2 ,RT92 ak2,RT ,Rl5 :R5l, l,R5T ls,R5 R9,; R9-; ,R;9B -R", -"9a; R1,; ->:R ,R1;B :-R>a ,R;9M -R9M; ,RT9; -RT9; ,Rl; -Rl> l;,RT s-Rl> ,R9", -"E2 ,REk&2 ,RH92 ak2,RH ,R15E :R5,E ,R1H5 :RH,5 R9E,M2 k&,MRE2 ,R29HM ,2RH9a", -"M l,R5E l,5:RE lH,R5 s,5:RH ,Rd9; -R9d; ,RH9; g-R9; ,R15d :-R>d ,R1H; g:R->", -" R9d,M; R9d-M; R9H,T; -R;g9M ld,R5 l->Rd lH;,R gl->R ,kP k&,P ,BkP ak,P R1,", -"P ,R:P ,R1PB :Ra,P S9, ,kS& ,TS9 ,aS9 l,S S:, lTS, l,Ss 9PR* -kP kP*,B ak-P", -" kP*,1 -R:P k*B,1P :-RaP S9* S-9 9TS* -TS9 S9l* l-S S9*lT s-S: R9,W kP&,W H", -"k,P akP,H R1,W ,R:W ,R1HP :RH,W ,WS9 S9W,& Z9S, SZ9,a S,lW :WS, SZl, S,Z: 9", -"WR* R9-W dkP,H -kgP dkP,1 -R:W ,1HdkP g:R-W ,dS9 -WS9 Z9S* g9S- Sdl, lWS- l", -"Z*S9 gSl- R9,m km&,R ,Rm9B akm,R R1,m ,R:m ,R1mB :Rm,a ,kSm S9m,& S9T,m S9a", -",m Spl, S,:p Sp9,T Ss,:p 9mR* R9-m k;P,B -Rm9a k;P,1 -R:m k;B,1P :-Ram ,kS;", -" -kS; S9;,T S-9Tm S;l, S>l- Sp9T* l-pSs ,RW9m ,RWkm& ,RH9m ,RHakm ,R15W :RW", -",5 ,R1Hm :RH,m S9W,m km&S,W SZ9,m SamZk, Sp9,W S:p,W lZ,Sp S:Zp, ,Rv9 vR-k ", -"vR9,H -vRg9 ,Rv1 :R-v vR1,H :vRg- v9S* S9-v Sv9Z* gS-v9 l,Sv S-lv lv,SZ l-y", -"S UkR) RUk!) R)Dk ak)RD R)1U R1U8) R)1D R1D8) RUkM) U!kRM) RkV) VRak) RUl) ", -"lRU8) VRl) lsVR) RUk* R+Uk* DkR* ak*RD 1UR* R1+U* 1DR* R1+D* k*MRU R+Uk*M R", -"*Vk V+Rk* R*lU l+RU* lRV* s*VlR RUkE) U!kRE) RHUk) RHUak) R1UE) 1UER8) R1HU", -") R1)UH8 UkMRE) !ER)UkM VRHk) ak)VRH lRUE) R8UlE) VlRH) Vs)lHR dk*RU R+Udk*", -" RH*Dk gRUk* R1dU* 1UdR8* R1HU* gR1U* RdUk*M dkR*U+M VdRk* gVRk* ldRU* R8dl", -"*U lH*VR glVR* RUk)2 U!kR)2 RDk)2 RD)ak2 R1U5) 1U5R8) R1D5) ak)R5D UkMR)2 !", -")k2RUM V2Rk) ak)V2R lRU5) R5Ul8) VlR5) V5Rls) k;*RU R+Uk;* RD;k* RD;ak* R1;", -"U* >kRU* R1D5* >kDR* R;Uk*M k;R*U+M V;Rk* ak;V*R l;RU* l>RU* l;VR* V>lR* Uk", -"ER)2 !ER)Uk2 Hk)RD2 R)UHak2 1UER5) RE1U58) R1)UH5 R)1HU5a E)R2UkM U!RME)k2 ", -"RHkV2) akV2RH) R5UlE) RUlE58) V5RlH) lRV5sH) RdUk;* dkR;U+* Hk;RD* RD;gk* 1", -"UdR5* R1d>U* 1UHR5* >D*gR1 dkR;U*M U+R*k;dM RH;V*k gRkV;* R5dl*U >RUld* lHR", -"V5* glRV>* U)kP kP)U! D)kP akPU) 1)UP 1UP8) R1DP) 1UaP) UkS) S!Uk) VkS) SVa", -"k) SUl) SlU8) l)SV SlVs) kPU* kP*U+ kPD* akPU* UP1* kP*U8 kP*1D aP*1U U*Sk ", -"S+Uk* SkV* SV+k* lUS* S8*lU SVl* Ss*Vl kP)UW UW)kP! RWDk) ak)RWD R1WU) kP)U", -"W8 R1WD) aP)1UH SUWk) UWkS!) SZVk) ZkVSa) SlUW) lWUS8) SlVZ) lZVSs) dkPU* U", -"+WkP* dkPD* gUPk* R1WU* 1U+RW* R1WD* g1UP* SdkU* U+WS*k SZ*Vk gSVk* lW*SU S", -"+UlW* lZ*SV glSV* km)UP Um)kP! RDmk) ak)RDm R1mU) km)U8P R1Dm) ak)U5P SUkm)", -" km)S!U SVkm) VmkSa) SlpU) pUlS8) SlVp) VplSs) km*UP U+mkP* km*RD R+Dkm* kP", -"*U5 >kPU* kP*5D >kDP* S;Uk* km*S+U SV;k* S+kVm* Sp*lU S>lU* Vp*Sl S>Vl* RWU", -"km) k!m)RWU km)RWD akRmUH) kP)U5W R)1WU8m kP)UH5 1HRmU8) km)SUW WmS)U!k Zkm", -"SV) akVmSZ) lWUSp) SplWU8) lZSVp) SlVpsZ) vRUk* kP*vU+ vRDk* gR*vDk vR1U* >", -"P*v1U vR1D* >D*vR1 SvUk* vU+S*k VvSk* gSkVv* lvSU* S>Ulv* lvVS* ylVS* tR, ,", -"Rt& ,RtD t,cR ,Rt1 t,:R R1,D :,cR ,RtM tRM,& tRV, tcV,R tRl, t:Rl, lRV, uR,", -" t*R t-R RDt* cRt- R1t* :Rt- t*R1D c-:R R*tM tR-M tRV* -RVt lRt* -Rlt t*VlR", -" u-R ,RtE tR&,E ,RtH tcR,H tR1,E t:R,E tHR,1 t:H,R tRM,E M&EtR, tHV,R cRVtH", -", ltR,E lt,:RE ltH,R ,RuH ,Rtd -Rtd RHt* gRt- tdR,1 t:d-R tH*R1 g:Rt- tdR,M", -" t-RdM tH*VR V-gtR ltd,R l-tRd tH*lR g-uR ,Rt2 tR&,2 tRD,2 tcR,2 ,Rt5 t:R,5", -" t5R,D tc5,R tRM,2 M&2tR, VtR,2 Vt,cR2 t5Rl, lt5:R, t5V,R ,Ru5 ,Rt; -Rt; t;", -"R,D tc;-R R5t* -Rt> t5*RD c>Rt- t;R,M t-RM; t;V,R V-tR; t5*lR l-t>R t5VR* -", -">uR tR,E2 ,R&tE2 tHR,2 cR,tH2 t5R,E :R,t5E tH5,R tH,cR5 ,RMtE2 M&tE,R2 V,Rt", -"H2 V2tc,RH l,Rt5E lRt5:,E tHRV5, uRH,5 tdR,; t-Rd; tH;,R gt-R; t5d,R t>-Rd ", -"tH5R* gt>-R ,Rdt;M -Rdt;M tHRV;, gtRV-; t5Rld, t>Rl-d tHRl;, u->gR tP, ,Pt&", -" ,DtP t,cP ,1tP t,:P tP1,D t:Pc, St, t&S, VtS, S,tc l,St S,t: SVl, uS, tP* ", -"t-P DPt* c-tP 1Pt* :-tP tP*1D t-P:c St* S-t t*SV StV- l*St Stl- St*Vl u-S ,", -"RtW tWR,& ,HtP tcW,R tWR,1 t:W,R tHP,1 t:H,P S,tW StW,& S,tZ ScZt, Stl,W S:", -"t,W lZ,St SZu, ,dtP -RtW HPt* gPt- tW*R1 t-W:R tHP1* gtP:- tWS* Sdt- S*tZ S", -"-gt Stdl* l-StW tZ*Sl gSu- ,Rtm tmR,& tmR,D tcm,R ,5tP t:m,R t5P,D tc5,P tm", -"S, Stm,& SV,tm Sct,m S,tp S:pt, Vp,St Spu, ,;tP -Rtm tm*RD t-mcR 5Pt* >Pt- ", -"t5PD* t>Pc- tmS* S;t- St;V* V-mSt S*tp tpS- tp*SV S-up tWR,m ,RWtm& tHm,R t", -"H,cRm t5W,R t5,:RW tH5,P tH,:Rm StW,m tWmS&, tZS,m tZmSc, tpS,W tpWS:, tZpS", -", uZ,Sp vRt* tP-v tvR,H cvRt- tvR,1 :vRt- tH5P* :vRc- S*tv tvS- Vv,St V-vSt", -" lvtS* l-vSt Vv,Sl y-uS X X! XB aX X. 8X X.B 8Xa XK XK! TX TXa Xj 8Xj TXj s", -"X X( +X X(B +Xa X(. +X8 .BX( +8aX X(K +XK TX( +TX Xj( +Xj T(Xj sX+ GX GX! H", -"X GaX GX. G8X HX. H8X GXK XKG! GTX TXGa GjX 8XGj HXj sGX dX +GX HXd gX dX. ", -"8dX H.dX gX8 dXK GK+X TdX gXT dXj Gj+X dXHj gsX X2 X2! X2B aX2 5X 5X8 5XB 5", -"aX X2K 2KX! TX2 T2aX 5Xj 58Xj 5TX sX5 X; +X; X;B aX; 5X; >X 5BX; >Xa X;K +K", -"X; TX; T;+X X;j >Xj T;5X >Xs GX2 X2G! HX2 G2aX G5X 5XG8 H5X 5aHX X2GK GX2!K", -" G2TX aX2GT 5XGj G58Xj 5THX G5sX G;X G;+X HX; gX; 5dX >XG 5dHX >Xg GKX; dXK", -"+; TXG; TXg; dj5X Gj>X Td5X gs>X XP XP! XPB aXP XP. 8XP P.XB aX8P QX QX! QX", -"T QaX QXj Q8X XjTP sXQ XP( +XP P(XB aX+P P(X. 8X+P XP(.B aXP+8 QX( +QX Q(TX", -" Qa+X Q(Xj Q8+X Xj(TP +QsX Y Y! YH Ya Y. Y8 YH. Y8H YQ YQ! YZ YZa Yj Y8Q YZ", -"j sY Yd Y+ YHd gY Yd. Y+8 HdY. gY8 YQd Y+Q YZd gYZ Yjd Y+j ZdYj sYg Xm Xm! ", -"XmB aXm 5Xm 8Xm 5BXm aX5P QXm Q!Xm TXm aXTm pX pX8 pXT spX Xm; +Xm XB;P aX+", -"m X;5P >Xm Xm;5B aX>P QX; QX+m TXQ; TX+m pX; >Xp TXp; sp>X Ym Ym! YHm Yam Y", -"5 Y58 Y5H Y5a YQm Q!Ym YZm ZaYm Yp Yp8 YpZ sYp Yv Yv+ YvH gYv Yv5 Y> vHY5 Y", -">g YvQ v+YQ YZv YZgv Ypv Y>p ZpYv yY X# X& X#B aX& X#. 8X& .BX# 8aX& X#K X&", -"K TX# TX& Xj# X&j T#Xj sX& X#( +X& #BX( +aX& #(X. +8X& X#(.B aX&+8 #(XK +KX", -"& X#T( T&+X j#X( X&+j Xj#T( +Xs& GX# G&X HX# HX& X#G. 8XG& X#H. 8XH& X#GK G", -"KX& G#TX TXG& G#Xj X&Gj H#Xj G&sX dX# dX& H#dX gX& X#d. d&8X dX#H. 8Xg& X#d", -"K dKX& T#dX TXg& d#Xj X&dj dXjH# g&sX X#2 X&2 2BX# X2a& 5X# 5X& X#5B aX5& 2", -"KX# &2XK X#T2 T2X& 5#Xj Xj5& 5#TX 5Xs& X;# X;& ;#XB X&a; 5#X; >X& X;#5B aX>", -"& ;#XK XK;& T#X; X;T& X#;j X&>j X;jT# >&sX X#G2 G2X& X#H2 H2X& G#5X 5XG& H#", -"5X 5XH& GX#2K X&2GK GTX#2 GT&X2 Xj#G5 X&jG5 G5TX# sX5G& G#X; X;G& H#X; X;g&", -" 5#dX G&>X H5Xd# >&gX dX#;K dX&;K GT;X# gXT;& dXj5# >XG&j X;jH# >Xgs& XP# X", -"&P P#XB X&aP P#X. X&8P XP#.B aXP8& QX# QX& Q#TX TXQ& Q#Xj 8XQ& Xj#TP QXs& P", -"#X( X&+P XP#(B aXP+& XP#(. X&P+8 P#(X.B +X8aP& X#Q( Q&+X QXT#( +QXT& Xj#Q( ", -"X&j+Q TX#Pj( sX+Q& Y# Y& YH# Ya& Y#. Y8& H#Y. H8Y& YQ# Y&Q YZ# YZ& Yj# Y&j ", -"ZjY# sY& Yd# Y+& HdY# gY& d#Y. 8dY& YHd#. g8Y& QdY# +QY& ZdY# Y&gZ djY# +jY", -"& YZdj# Y&gs Xm# Xm& m#XB X&am 5#Xm Xm5& Xm#5B aXm5& Q#Xm XmQ& T#Xm XmT& pX", -"# pX& TXp# p&sX X#;P X&+m Xm;#B aXm;& Xm;5# Xm>& 5X#;PB >Xam& Q#X; X;Q& QX;", -"T# aX;Q& X;p# p&>X pXT;# >Xps& Ym# Y&m HmY# HmY& Y5# Y5& H5Y# H5Y& QmY# Q&Y", -"m ZmY# YmZ& Yp# Yp& Y#Zp Y&sp Yv# Yv& vHY# Y&gv v5Y# Y>& YvH5# Y&g> vQY# YQ", -"v& Y#Zv ZvY& Y#pv pvY& YZvp# yY& IX IX! DX DXa IX. 8IX DX. D8X IXK I!XK DXT", -" aITX IjX Ij8X DXj sIX IX( +IX DX( +DX X(I. 8I+X X(D. D8+X X(IK IX+K D(TX D", -"X+T I(Xj Ij+X D(Xj +DsX GIX IXG! JX JaX IXG. GI8X JX. J8X IXGK GIX!K JTX TX", -"Ja GIXj IjXG8 JjX sJX IdX Id+X JdX gJX I.dX Id8X dXJ. J8gX IXdK IdX+K TdJX ", -"JTgX dXIj Idj+X dXJj gXsJ IX2 I!X2 DX2 I2aX 5IX 8I5X 5DX D85X X2IK IX2!K I2", -"TX aX2TI Ij5X IjX58 DX5T 5DsX I;X I;+X DX; D;+X I;5X >XI D;5X >XD IKX; I;X+", -"K TXD; aX;TI X;Ij Ij>X X;Dj sI>X IXG2 GIX!2 JX2 aXJ2 GI5X G58IX J5X 5aJX GI", -"X2K IX2GK! TXJ2 JTaX2 IjXG5 G58IjX 5TJX J5sX dXI; IdX+; J;X J;gX Id5X Id>X ", -"5dJX J>X IdX;K +GIX;K TXJ; gJTX; Idj5X >IjdX X;Jj >XsJ IP IP! DXP aIP IP. 8", -"IP D.IP 8IDP QIX Q!IP QDX DXQa IPj 8IQX DjQX sIP IP( +IP D(IP DX+P P(I. 8I+", -"P IP(D. +DX8P Q(IP QI+X Q(DX QD+X I(Pj IP+j IPjD( +IsP YI YI! YJ YJa YI. Y8", -"I YJ. YJ8 YQI QIY! YZJ ZJYa YjI Q8YI YJj sYJ YId Y+I YJd gYJ IdY. +IY8 JdY.", -" Y8gJ QIYd +QYI YdZJ YZgJ IdYj +IYj YdJj sJgY ImX I!Xm DXm aXDm 5IP 8I5P DX", -"5P 8XDm ImQX ImXQ! DmQX aXmQD pIX 8IpX pDX pDsX I;P Im+X I;DP DX+m I;5P >PI", -" I;P5D DX>P I;QX I;P+Q DXQ; aX;QD I;pX pI>X DXp; sI>P YIm ImY! YJm JmYa Y5I", -" 5IY8 YJ5 J5Y8 QIYm YQIm! JmYZ YZJam YpI pIY8 JpY JpsY YvI vIY+ JvY JvgY vI", -"Y5 Y>I Y5Jv Y>J YQvI Yv+QI YZJv gYZJv pIYv pIY> JvYp yJY bX bX& bXD cX bX. ", -"b8X b.DX cX8 bXK bKX& bTX cXT bXj 8Xbj DXbj scX bX( b+X b(DX cX+ X(b. +Xb8 ", -"bXD(. +Xc8 X(bK bK+X b(TX +TcX b(Xj +Xbj bTXj( s+cX bGX G&bX JbX cJX GXb. G", -"8bX bXJ. J8cX GXbK I&KGX bTJX JTcX GjbX I&jGX bXJj cJsX bdX +GbX bdJX gcX b", -".dX 8dbX JbdX. g8cX bKdX dX&bK TdbX gTcX dXbj IdjX& JjbdX scgX bX2 b2X& b2D", -"X cX2 b5X 5Xb8 5DbX c5X X2bK I&2XK b2TX TXc2 5Xbj I&j5X 5TbX c5sX bX; +Xb; ", -"DXb; cX; 5Xb; >Xb b5XD; c>X bKX; I;&XK TXb; TXc; X;bj bX>j X;jbT sc>X GXb2 ", -"I&2GX bXJ2 JXc2 G5bX bG58X b5JX J5cX bGX2K bG2X&K JbTX2 cJTX2 bG5Xj bG5X&j ", -"J5bTX sJc5X G;bX I;&dX bXJ; c;gX 5dbX bG>X J5bdX gc>X bG;XK IdKX;& J;bTX cJ", -";TX dXjb5 >XbGj J;jbX J>scX bXP IP& DXbP cXP b.IP 8IbP IP.bD 8IcP bQX Q&bX ", -"QDbX cQX QXbj Q8bX IPjbT cQsX b(IP +IbP IP(bD +IcP IP(b. IP&+8 DX(bP. cX+8P", -" b(QX +QbX bQXD( +QcX IPjb( IP&+j Ij(bTP sIPc+ Yb Yb& YJb Yc Yb. Yb8 JbY. Y", -"c8 YbQ bQY& YZb YcZ Ybj bQY8 ZbYj sYc Ybd Yb+ JbYd Ycg bdY. b+Y8 YJbd. Y8gc", -" bQYd b+YQ YdZb ZcgY bdYj b+Yj YZbdj gsYc bXm XmI& DXbm cXm 5IbP 8Xbm b5XDm", -" 5IcP QXbm Im&QX TXbm QXcm pbX b8pX bTpX cpX I;bP +Xbm I;PbD +Xcm I;Pb5 bX>", -"P 5DXb;P cX>P QXb; I;PQ& I;PbT QXc; bXp; pb>X pbXD; >Xcp Ybm bmY& JmYb Ycm ", -"Yb5 b5Y8 J5Yb Yc5 bQYm YbQm& YmZb cmYZ Ypb pbY8 YbJp Ycp Yvb vbY+ YbJv Ycv ", -"vbY5 Y>b YJ5vb Yc> YQvb Yvb+Q ZvYb YZcv pvYb p>Yb JpYvb yYc X0 X0! X0B aX0 ", -"1X 1X8 1XB 1aX X0K !KX0 TX0 T0aX 1Xj 18Xj 1TX sX1 X0( +X0 0BX( +0aX 1X( 1+X", -" X(1B +X1a 0(XK X0+K X0T( +0TX 1(Xj +j1X 1(TX 1+sX GX0 X0G! HX0 G0aX 1GX G8", -"1X 1HX Ga1X X0GK GX0!K G0TX aX0GT Gj1X 1G8Xj GT1X 1GsX dX0 +0dX H0dX gX0 1d", -"X +G1X HX1d g1X X0dK dX0+K T0dX TXg0 dj1X dXj1+ Td1X sXg1 X02 !0X2 2BX0 X2a", -"0 1X5 158X 1B5X 5a1X 2KX0 X02!K X0T2 aX0T2 15Xj 1X58j 5T1X 1Xs5 X;0 +0X; ;0", -"XB a0X; 1X; >X1 1BX; 1a>X ;0XK X;0+K T0X; aX;T0 Xj1; 1X>j TX1; s1>X X0G2 GX", -"0!2 X0H2 aX0G2 G51X 1G58X H51X 1Ga5X GX02K X02GK! GTX02 GT0aX2 1G5Xj G581Xj", -" 1GT5X sX1G5 G0X; dX0+; H0X; X;g0 G;1X 1G>X HX1; g1>X dX0;K +G0X;K GT;X0 gX", -"T;0 dXj1; >X1Gj X;j1H >Xgs1 XP0 X!P0 P0XB XPa0 1XP 8X1P XP1B aX1P QX0 X0Q! ", -"Q0TX Q0aX 1QX Q81X QX1T 1QsX P0X( XP+0 XP0(B aXP+0 XP1( +X1P 1XP(B 1+XaP X0", -"Q( +0QX QXT0( +QXT0 1(QX +Q1X 1QXT( sX1+Q Y0 Y0! YH0 Ya0 Y1 Y18 Y1H Y1a YQ0", -" Q!Y0 YZ0 ZaY0 Y1Q 1QY8 YZ1 sY1 Yd0 Y+0 HdY0 gY0 Y1d Y1+ 1HYd gY1 QdY0 +QY0", -" ZdY0 g0YZ 1QYd 1+Yj YdZ1 g1sY Xm0 X!m0 m0XB a0Xm 1Xm 8X1m 1BXm aX1m Q0Xm X", -"m0Q! T0Xm aXmQ0 pX1 1Xp8 1TpX s1pX X0;P +0Xm Xm;0B aXm+0 Xm1; 1X>P 1Xm;B >X", -"1am Q0X; +QXm0 QX;T0 aX;Q0 1Xp; p1>X pX1T; >Xps1 Ym0 m0Y! HmY0 amY0 Y15 1mY", -"8 1HY5 1aY5 QmY0 YQm!0 ZmY0 YZam0 Yp1 p1Y8 ZpY1 Y1sp Yv0 v+Y0 vHY0 g0Yv Yv1", -" Y>1 YHv1 g1Y> vQY0 Yv+Q0 Y0Zv gYZv0 pvY1 p>Y1 ZvY1 yY1 9X 9X& 9XB 9aX 9X1 ", -":X 1B9X :Xa 9XK 9KX& 9TX TX9a 9Xj :Xj 1T9X s:X 9X( 9+X X(9B +X9a 9(1X :X+ 9", -"X1(B +X:a X(9K 9K+X 9(TX +T9X 9(Xj +X:j 9TX1( s+:X 9GX G&9X 9HX Ga9X 1G9X :", -"GX 1H9X :HX GX9K X&K9G GT9X 9GTaX Gj9X Gj:X HX9j :GsX 9dX +G9X HX9d g9X 1d9", -"X :dX 9HX1d g:X 9KdX dX&9K Td9X 9TgX dX9j dX:j dXj9H s:gX 9X2 92X& X29B 92a", -"X 95X :X5 9B5X 5a:X X29K X&29K 92TX 9TX&2 5X9j 5X:j 5T9X s5:X 9X; +X9; 9BX;", -" aX9; 1X9; >X: 95X;B :a>X 9KX; X;&9K TX9; aX;9T X;9j >j:X X;j9T s:>X GX92 X", -"&29G 92HX 9GaX2 G59X G5:X H59X H5:X 9GX2K 9G2X&K 9GTX2 aX29GT 9G5Xj :G5Xj 9", -"G5TX :HXs5 G;9X dX&9; HX9; 9Xg; 5d9X :G>X 9H5dX >Xg: 9G;XK d&K9X; 9GTX; g9X", -"T; dXj95 :>GXj X;j9H g:Xs> 9XP X&9P XP9B aX9P 1X9P :XP 9X1PB aX:P 9QX Q&9X ", -"QX9T Qa9X 1Q9X :QX 9QX1T :QsX XP9( +X9P 9XP(B 9+XaP 9X1P( +X:P 1X(9PB :X+aP", -" 9(QX +Q9X 9QXT( 9+QTX 9QX1( +Q:X Xj(9TP :QXs+ Y9 Y9& Y9H Y9a Y91 Y: 9HY1 Y", -":H Y9Q 9QY& YZ9 Z9Ya Y9j Y:Q Z9Y1 sY: Y9d Y9+ 9HYd gY9 9dY1 Y:+ Y91Hd Y:g 9", -"QYd 9+YQ YdZ9 YZg9 9dYj :QY+ YZ91d gYZ: 9Xm X&9m 9BXm aX9m 1X9m :Xm 95XmB a", -"X:m QX9m Xm&9Q TX9m aXm9Q p9X :pX 9TpX sX:p Xm9; +X9m 9Xm;B aXm9+ 95X;P :X>", -"P X;B95P :Xm>a QX9; X;&9Q 9QXT; aX;9Q 9Xp; >X:p p9XT; :pXs> Y9m 9mY& 9HYm 9", -"aYm Y95 Y:5 9HY5 :HY5 9QYm Y9Qm& YmZ9 YZ9am Yp9 Y:p ZpY9 YpZ: Yv9 v9Y+ YHv9", -" Yvg9 v9Y1 Y:v Yv91H gY:v YQv9 Yv9+Q ZvY9 gY9Zv pvY9 Yp:v Yp9Zv yY: IX0 I!X", -"0 DX0 D0aX 1IX 8I1X 1DX D81X X0IK IX0!K D0TX aX0TI Ij1X IjX18 DX1T 1DsX X0I", -"( IX+0 X0D( +0DX IX1( +I1X 1(DX +D1X IX0(K +IX0K DXT0( +DXT0 IjX1( 1+IXj 1D", -"XT( sI1+X IXG0 GIX!0 JX0 aXJ0 GI1X 1G8IX J1X 1aJX GIX0K IX0GK! TXJ0 JTaX0 I", -"jX1G 1G8IjX 1TJX J1sX I0dX IdX+0 dXJ0 JXg0 Id1X 1+GIX 1dJX J1gX IdX0K +I0dX", -"K JTdX0 gJTX0 Idj1X 1+IdXj J1TdX sJg1X X0I2 IX0!2 X0D2 aX0I2 5I1X 1I58X 5D1", -"X 1DX5a IX02K X02IK! DXT02 TI0aX2 IjX15 5I81Xj 1DX5T sI15X I0X; I;X+0 D0X; ", -"aX;D0 I;1X 1I>X DX1; 1D>X I;X0K +I0X;K DX;T0 aX0TI; I;j1X >I1Xj X;j1D >Xs1D", -" GIX02 IX0G2! X0J2 JaX02 1G5IX G581IX 1XJ5 J158X IX0G2K I!X2G0K JTX02 aX0JT", -"2 1G5IjX Ij1XG58 J15TX sJ15X IdX;0 +GIX;0 X;J0 gJX;0 1G;IX >I1dX 1XJ; J1>X ", -"dX0I;K Id+X;0K J;TX0 gXTJ;0 1IdX;j Idj>X1 J1;TX J>s1X IP0 I!P0 D0IP a0IP 1I", -"P 8I1P DX1P aI1P Q0IP IP0Q! Q0DX QDXa0 QI1X IPj18 QD1X 1IsP P0I( +0IP IP0D(", -" +DXP0 1(IP +I1P 1DXP( 1+DIP IP0Q( +QIX0 QDX0( +QDX0 IPj1( IPj1+ 1QDX( sIP1", -"+ YI0 I0Y! YJ0 JaY0 Y1I 1IY8 YJ1 J1Y8 QIY0 YQI!0 Y0ZJ YZJa0 1QYI Y1Q8I ZJY1", -" Y1sJ IdY0 +IY0 JdY0 g0YJ 1IYd 1+YI YdJ1 YJg1 YQId0 Y+QI0 YZJd0 gYZJ0 Y1QId", -" Y1+QI YZ1Jd gY1sJ I0Xm ImX!0 D0Xm aXmD0 5I1P 1Im8X DX1m aXm1D ImXQ0 QI0Xm!", -" QDXm0 aX0TIm 1IpX pI81X 1DpX sIPp1 I0;P I;P+0 I;PD0 a;PI0 I;1P 1I>P I;P1D ", -">XD1m I;PQ0 Im0+QX I;PT0 aX0QD; pI1X; >Xp1I pDX1; sIP>1 ImY0 YIm!0 Y0Jm YJa", -"m0 1IY5 Y158I J1Y5 YJ15a YQIm0 Im0YQ! YZJm0 ZJmYa0 pIY1 Yp18I Y1Jp JpsY1 Y0", -"vI Yv+I0 Y0Jv gYJv0 vIY1 >IY1 Y1Jv Y1J> YvQI0 vIQY+0 YZvJ0 JvZgY0 Yv1pI Y>p", -"1I JpYv1 YJy1 bX9 I&9X 9DX cX9 b1X :IX 1DbX :cX bK9X I&K9X 9TbX 9TcX 9Xbj b", -"X:j 1TbX :csX b(9X 9+bX 9(DX 9+cX b(1X b+:X b1XD( :+cX bX9(K b+X9K bTX9( cX", -"9+T b1Xj( :I+Xj b1TX( :cXs+ 9GbX bG9X& J9X J9cX 1GbX bG:X b1JX :JX bG9XK bG", -"9X&K 9TJX cJ9TX b1GXj :GbXj 9XJj sX:J 9dbX dX&9I 9dJX cXg9 1dbX bd:X J91dX ", -"gX:J bdX9K IdK9+X J9TdX gJ9TX Idj9X :IdXj J9jdX g:XsJ b29X I&29X 92DX 9Xc2 ", -"95bX b5:X 5D9X c5:X bX92K 9I2X&K bTX92 cX9T2 b1X5j :I5Xj b1T5X :cXs5 9Xb; I", -";&9X DX9; 9Xc; 1Xb; :I>X b1XD; :c>X bX;9K I;K9+X bTX9; cX;9T I;j9X :>IXj X;", -"j9D c>Xs: bG9X2 bG9X&2 9XJ2 cJ9X2 b1G5X :Gb5X 95JX J5:X 9G2bXK bK9GX&2 J9TX", -"2 J9TcX2 9G5bXj bG5:Xj J95TX :Js5X bG;9X 9+GbX; 9XJ; cJ;9X b1GX; :>GbX J95d", -"X >X:J IdK9X; X;G&9IK J9;TX cXTJ9; b1GX;j >Ij:dX J9;Xj :J>sX 9IP I&9P DX9P ", -"9IcP 1IbP :IP b1XDP cX:P 9QbX IP&9Q QD9X 9QcX 1QbX bQ:X IPj9D :IsP 9(IP +I9", -"P 9DXP( cX9+P b1XP( +I:P b1DIP( :cX+P bQX9( b+Q9X 9QDX( cQX9+ IPj9( :QI+X I", -"P(b1T sIP:+ Yb9 9IY& YJ9 Yc9 Yb1 Y:b J9Y1 Y:J bQY9 Yb9Q& ZJY9 Y9Zc b1Yj :QY", -"b ZbY1 Z:Yc bdY9 b+Y9 YdJ9 g9Yc b1Yd :IY+ YJ91d gY:J Yb9Qd Yb+9Q YZb9d gY9Z", -"c Yb1Qd Y:b+Q YZb1d sY:gJ 9Xbm Im&9X DX9m 9Xcm 1Xbm bX:m b1XDm cX:m bQX9m 9", -"QIXm& bTX9m cQX9m b1pX pb:X 9DpX :Xcp I;9P I;P9+ I;P9D cXm9+ I;Pb1 :I>P 95D", -"I;P c>X:m I;P9Q 9+QI;P I;P9T cQX9; pbX9; :pI>X p9DX; cpX:> bmY9 Yb9m& JmY9 ", -"cmY9 b1Y5 :IY5 J9Y5 Y5:J Yb9Qm Im&Y9Q YZb9m YcZ9m pbY9 Yb:p Y9Jp cpY: vbY9 ", -"Yvb9+ Y9Jv Y9cv vbY1 Yb:v Jv9Y1 :JY> Yvb9Q Y9QvI& Jv9YZ YcvZ9 Ypbv9 :vIYp J", -"p9Yv Y:yJ RX RX! RXB RaX RX. R8X X.RB 8XRa XM XM! RTX aXM RjX 8XM TXRj sRX ", -"RX( R+X X(RB +XRa X(R. +XR8 RX(.B R+8aX XM( +XM R(TX +XRT R(Xj +XRj XM(Tj R", -"+sX RG RG! RGH RGa RG. RG8 R.HX G8RH RGM R!GM RGT GTRa RGj G8Rj GTRj sRG RG", -"d R+G HXRd gRG R.dX +GR8 dX.RH RGg8 dXM +MRG GTRd gXM GjRd +GRj dXMHj sRgX ", -"RX2 X2R! X2RB R2aX R5X 5XR8 RB5X 5XRa XM2 M!X2 R2TX X2aM 5XM 8X5M 5XRT R5sX", -" R;X +XR; RBX; aXR; 5XR; >XR X;BR5 Ra>X XM; X;+M TXR; XMa; X;Rj >XM XM;5T s", -"R>X RG2 G2R! R2HX R2Ga RG5 G5R8 G5RH G5Ra R2GM XM2G! R2GT aXMG2 G5Rj RG58M ", -"G5RT RGs5 RG; +GR; G;RH RGg; G5Rd >RG RG5H; gR>X GMR; dXM+; GTR; XMg; G;Rj ", -"RG>M dXMH5 gX>M RXP XPR! XPRB RXaP XPR. RX8P RXP.B aXPR8 SX S!X STX SaX SXj", -" S8X TXSj SsX XPR( RX+P RXP(B aXPR+ RXP(. R+8XP XP(R.B R+8aXP SX( S+X TXS( ", -"+TSX XjS( +XS8 STXj( S+sX YR YR! YRH YaR YR. Y8R RHY. RHY8 SY SY! SZY SYa S", -"Yj SY8 YjSZ sYS YRd Y+R RHYd gYR RdY. R+Y8 YRHd. Y8gR SYd SY+ YZSd gSY YjSd", -" Y+S8 SZYdj sYgS RmX R!Xm RBXm aXRm 5XRm 8XRm XmBR5 aXmR5 SXm XmS! TXSm aXS", -"m SpX pXS8 STpX sXSp XmR; +XRm Xm;RB aXmR+ Xm;R5 Rm>X R5X;PB >XRam S;X +XS;", -" TXS; aXS; pXS; S>X SpTX; >XSs YRm RmY! RHYm RaYm Y5R R5Y8 RHY5 R5Ya SYm Ym", -"S! SmYZ SmYa YpS S8Yp SZYp YpSs YvR vRY+ YHvR YvgR vRY5 Y>R YvRH5 gRY> SvY ", -"YvS+ YZSv SvgY YpSv S>Y SZpYv yYS RX# R&X X#RB aXR& X#R. 8XR& RX#.B aX&R8 X", -"M# XM& R#TX TXR& R#Xj X&Rj XM#Tj R&sX X#R( +XR& RX#(B aX&R+ RX#(. R+8X& X#(", -"R.B R+8aX& M#X( X&+M XM#T( aXM+& XM#j( XM&+j RT#Xj( sX+R& RG# RG& R#HX GaR&", -" G#R. G8R& RGH#. RG8H& R#GM GMR& R#GT GTR& R#Gj G&Rj RGTj# RGs& R#dX +GR& d", -"X#RH RGg& dX#R. dX&R8 RH#dX. gRG8& d#XM XMd& dXMH# XMg& dXMj# dXM&j dX#RHj ", -"gsRG& X#R2 R2X& RX#2B aX&R2 R#5X 5XR& R5X#B R5aX& M#X2 X2M& XM#T2 aXM&2 5#X", -"M XM5& R5TX# sX5R& R#X; X;R& X;#RB aX;R& X;#R5 R&>X R5#X;B >XRa& X#M; M;X& ", -"XM;T# aXM;& XM;5# XM>& X;#R5T >XsR& G#R2 R2G& RGH#2 RGa&2 R#G5 G5R& RG5H# R", -"G5H& XM#G2 XM&G2 RGT#2 XM&H2 RG5M# XM&G5 RG5T# sRG5& R#G; G;R& RG;H# gRG;& ", -"RG5d# RG>& dX#RH5 >XgR& dXM;# dXM;& XM;H# gXM;& dXM5# >XMG& dX#R5T >XgM& XP", -"R# RXP& RXP#B aXPR& RXP#. X&PR8 XP#R.B R8aX&P SX# S&X TXS# TXS& XjS# 8XS& S", -"TXj# S&sX RXP#( X&PR+ XP#R(B R+aX&P XP#R(. R+8X&P .BR(XP# aXR&+P8 X#S( +XS&", -" STX#( S+TX& SXj#( S+8X& Xj#ST( Ss+X& YR# Y&R RHY# RHY& R#Y. R8Y& YRH#. Y8R", -"H& SY# SY& S#YZ YZS& S#Yj Y8S& SZYj# S&sY RdY# R+Y& YRHd# Y&gR YRd#. Y+R8& ", -"RHdY#. gYR8& YdS# Y+S& SZYd# S&gY SYdj# SY+&j YZjSd# gSsY& R#Xm XmR& Xm#RB ", -"aXmR& Xm#R5 Xm&R5 R5#XmB R5aXm& XmS# XmS& STXm# SaXm& S#pX pXS& SpTX# Sp&sX", -" Xm;R# Xm&R+ Rm#X;B RamX;& R5X;P# >XRm& 5#XmR;B aXm>R& X;S# X;S& S;TX# Sa;X", -"& SpX;# S&>X pXTS;# S>sX& RmY# RmY& YRHm# YaRm& R5Y# R5Y& Y5RH# Y5aR& YmS# ", -"SmY& SZYm# SZ&Ym S#Yp S&Yp SZpY# Yp&Ss Y#vR vRY& YvRH# gYvR& YvR5# >RY& vRH", -"Y5# Y>gR& S#Yv YvS& YZvS# Sv&gY SvpY# S&Y> YpZSv# SYy& [ [! [D [a [. [8 [D.", -" [8D [M [!M V[ V[a [j [8M V[j [s [( [+ [D( [+D [(. [+8 D([. +D[8 [M( [+M V[", -"( V[+ [j( [+j V([j [s+ [G [!G [J [Ja [G. [8G [J. J8[ [GM GM[! VJ[ [aVJ [jG ", -"G8[j Jj[ [sJ [d [+G [Jd g[ [d. [8d J.[d g[8 [dM +G[M V[d g[V [dj +G[j [dJj ", -"g[s [2 [!2 [D2 [a2 [5 [58 [5D [5a [M2 M2[! V[2 V2[a [5M 5M[8 V[5 [s5 [; [+;", -" [;D [a; [5; [> 5D[; [>D [;M +M[; V[; [+V; [;j [>M [5V; V>[ [G2 G2[! [J2 J2", -"[a [5G G5[8 J5[ [5J8 GM[2 [!GM2 V2[J VJ[a2 G5[j [5G8M V[J5 J5[s [d; +G[; J;", -"[ g[; [5d [>G [5J; g[> GM[; [+GM; V[J; V;g[ G;[j [d>M [5Vd V>g[ [P [!P [DP ", -"[aP [P. [8P DP[. D8[P S[ S[! SV[ S[a S[j S[8 [jSV [sS [P( [+P DP[( +D[P P([", -". +P[8 [DP(. [+D8P S[( S[+ S(V[ V[S+ S([j [+S8 SV[j( S+[s [Y [Y! YJ[ Ya[ [Y", -". Y8[ Y.[J [JY8 S[Y S![Y ] ]a Yj[ Y8S[ ]j ]s [Yd Y+[ [dYJ g[Y Y.[d [+Y8 YJ[", -"d. Y8g[ S[d Y+S[ ]d ]g [dYj [+Yj ]jd ]gs [m [m! [mD [am [5m [8m 5D[m 5a[m S", -"[m S![m V[m [aVm [p [p8 [pV [ps [m; [+m Dm[; +D[m 5P[; [>m [5D;P [a>P S[; [", -"+S; V[S; [+Vm [p; S>[ V;[p [pV> [Ym Ym[! Jm[ [aJm Y5[ [5Y8 [JY5 [5Ya [mSY S", -"[Ym! ]m ]am [pY Y8[p ]p ]ps [v [v+ [vJ g[v [v5 Y>[ J5[v Y>g[ [vS S+[v ]v ]g", -"v [pv [pY> ]pv ]y [b [& [bD [c [b. [8b bD[. [c8 [bM [&M V[b [cV [jb [&j Vb[", -"j [sc [b( [+b bD[( [c+ b([. b+[8 [bD(. c+[8 bM[( b+[M [bV( V+[c bj[( b+[j V", -"[bj( [+sc [bG [&G [Jb [cJ bG[. bG[8 [bJ. J8[c bG[M GM[& JbV[ VJ[c bG[j G&[j", -" Jb[j [csJ [db [d& Jb[d g[c bd[. b8[d [Jbd. [8gc bd[M dM[& Vb[d [cgV bd[j d", -"&[j Jj[bd gs[c [b2 [&2 bD[2 [c2 [5b [5& b5[D [c5 bM[2 M&[2 [bV2 V2[c b5[j 5", -"M[& Vb[5 c5[s [;b [;& b;[D [c; b5[; [>b [5bD; [>c bM[; M;[& Vb[; V[c; b;[j ", -"[&>M V[5b; c>[s bG[2 G&[2 [bJ2 c2[J bG[5 G5[& Jb[5 J5[c [bGM2 [&GM2 VJ[b2 [", -"cJV2 [5bGM [5&GM J5V[b [sJc5 bG[; G;[& Jb[; c;g[ b5[d >b[d J5[bd c>g[ [dbM;", -" [d&M; J;V[b g[Vc; [5dbM [>bGM J;[bj J>V[c [bP [&P bP[D [cP bP[. b8[P [bDP.", -" [8cP S[b S[& V[Sb Sc[ [jSb [8Sb SV[bj [sSc bP[( b+[P [bDP( [+cP [bP(. [+b8", -"P bPD[(. [c+8P [bS( [+Sb SV[b( S+[c S[bj( S[+b8 V[jSb( [scS+ Yb[ Y&[ [JYb Y", -"c[ [bY. [8Yb YJ[b. Y8[c SYb YbS& ]b ]c YjSb YbS8 ]jb ]sc [dYb [+Yb YJ[bd Yc", -"g[ Yb[d. Yb+[8 [JdYb. g[Yc8 YbSd YbS+ ]bd ]gc S[dbj S[8bd bd]j gs]c [mb [m&", -" bm[D [cm b5[m b8[m [5bDm [5cm [mSb [mS& Vb[m cmS[ [pb [p& pbV[ cp[ bm[; b+", -"[m [mbD; [+cm [5b;P [&>P b5P[;D >P[c [;Sb [;S& SV;[b S;[c [;pb Sb[> [pVb; [", -">Sc [mYb [mY& Jb[m Jm[c [5Yb [5Y& YJ5[b Y5[c SmYb S[&Ym ]bm ]cm SbYp Y&[p ]", -"pb ]pc [vb [v& vb[J cv[ [5vb Yb[> [vJb5 [>Yc Sb[v S&[v ]vb ]cv pb[v SbY> pv", -"]b ]yc kX kX! kXB akX R1X 8kX RB1X 1XRa kXM M!kX TkX akTX lX lX8 lXT lsX kX", -"( +kX X(kB ak+X R(1X 1XR+ kX(1B akX1+ k(XM kX+M T(kX Tk+X lX( l+X TXl( sXl+", -" RGk R!Gk HkX GkRa R1G 1GR8 1GRH 1GRa kXGM kXMG! GkRT akXGT lGR RGl8 lHX sR", -"lG dkX +kRG dkHX gkX 1GRd 1+RG dkX1H R1gX kXdM dkX+M dkTX TkgX ldX R+lG HXl", -"d glX kX2 X!k2 X2kB k2aX 5kX 8k5X 5BkX ak5X k2XM kXM!2 T2kX akXT2 lX5 5Xl8 ", -"5TlX l5sX kX; k;+X kBX; kXa; 1XR; >kX kX;1B ak>X XMk; kX;+M kXT; akXT; lX; ", -"l>X TXl; >Xls R2Gk kX2G! H2kX akXG2 1GR5 R1G58 5kHX akXG5 kXMG2 Gk2XM! RGTk", -"2 ak2RGT RGl5 lGR58 H5lX lsGR5 GkR; dkX+; kXH; kXg; 1GR; R1>G dkXH5 gk>X dk", -"XM; +GkXM; dkXT; gkXT; RGl; lG>X HXl; >Xgl kXP X!kP XPkB kXaP kX1P kX8P kXP", -"1B akX1P SkX kXS! TkSX akSX lXS S8lX STlX lXSs XPk( kX+P kXP(B akX+P kXP1( ", -"R1+XP 1X(kPB 1+XakP kXS( +kSX STkX( S+TkX SXl( S+lX SlTX( Ssl+X Yk Yk! YkH ", -"Yak Y1R Y8k R1YH R1Ya SYk S!Yk YZk YkSa lY lY8 lYZ lYs Ykd Y+k HkYd gYk R1Y", -"d R1Y+ Y1RHd Y1gR YkSd YkS+ YdZk SYgk lYd lY+ YZld glY kXm X!km kBXm kXam 1", -"XRm kX8m kXm1B akX1m kXSm kXmS! kXTm SakXm lXp l8pX lTpX splX Xmk; kX+m kXm", -";B akX+m kXm1; kX>P kXB1;P >kXam kXS; S+kXm S;TkX Sa;kX S;lX lXS> lXpT; l>X", -"Ss Ykm kmY! HkYm akYm Y5k 5kY8 H5Yk 5aYk SmYk SYkm! YmZk SYakm lYp lpY8 lZY", -"p lsYp Yvk vkY+ YHvk Yvgk vRY1 Y>k Yv1RH >kgY YkSv SY+vk ZvYk gYkSv lYv lY>", -" YZlv ylY R9X kX& RB9X 9XRa 9XR1 :RX kXB91 Ra:X 9XM XMk& 9XRT aX9M lX9 l:X ", -"9TlX s:lX R(9X 9XR+ kX(9B akX9+ kX(91 R+:X 9X(R1B :R+aX 9(XM +X9M R9TX( aXM", -"9+ 9Xl( :Xl+ lX9T( lsX:+ R9G 9GR& 9GRH 9GRa 9GR1 :RG R9G1H RG:H 9MRG kX&GM ", -"9GRT aXM9G R9lG :RlG 9HlX :RsG 9GRd 9+RG dkX9H R9gX dkX91 R+:G 9HXR1d :RgX ", -"dX9M dkXM& dkX9T 9XgM 9dlX :dlX lHX9d lXg: R29X k2X& kX29B akX92 9XR5 R5:X ", -"R95XB :R5aX 92XM kX&M2 R9TX2 aXM92 95lX l5:X lX95T lsX:5 9XR; X;k& kX;9B ak", -"X9; kX;95 :R>X k;B95X :>RaX XM9; kX;M& kX;9T aXM9; 9Xl; l:>X lX;9T l>Xs: R2", -"9G kX&G2 R9GH2 kX&H2 9GR5 RG:5 R9GH5 :RGH5 R9GM2 kX2GM& R9GT2 aX29GM lGR95 ", -":RGl5 lHX95 :RGs5 9GR; dkX;& kX;9H gR9G; dkX95 >R:G 9G5RH; g:R>X dXM9; kX;d", -"M& XM;9H g9XM; lG;R9 l>G:R lHX9; glX:> kX9P X&kP kXP9B akX9P kXP91 kX:P 9X1", -"kPB :RaXP S9X 9XS& 9TSX 9aSX S9lX S:X Sl9TX sXS: kXP9( kX&+P 9X(kPB 9+XakP ", -"9X1kP( :R+XP kX9P1(B akX:P+ 9XS( 9+SX S9TX( S9+TX Sl9X( :XS+ lXTS9( S:s+X Y", -"9R Yk& R9YH R9Ya R9Y1 Y:R Y9R1H :RYa SY9 Y9S& YZS9 Y9Sa lY9 lY: Y9lZ S:sY R", -"9Yd R9Y+ Y9RHd Y9gR Y9R1d :RY+ R9HY1d gRY: Y9Sd Y9S+ SZ9Yd SYg9 Y9ld l+Y: l", -"YZ9d Y:gl 9XRm Xmk& kXm9B akX9m kXm95 Rm:X kXB95P :RmaX 9XSm S9Xm& S9TXm S9", -"aXm p9lX lX:p Sp9TX :pXSs kXm9; kXm9+ kXB9;P kX&a;P 95Xk;P :>RXm 1;9PkXB :X", -"a>kP 9XS; S9+Xm S9;TX S9aX; Sp9X; >XS: S9TlX; S:>sX R9Ym kmY& Y9RHm Y9aRm R", -"9Y5 :RY5 Y95RH Y:RH5 SmY9 SY9m& SZ9Ym SY9am S9Yp YpS: Yp9lZ lYs:p vRY9 vkY&", -" Yv9RH gY9vR Yv9R1 >kY: Y9HvR1 :vRgY YvS9 Sv9Y+ Sv9YZ gS9Yv Y9lv Y:lv lYvZ9", -" lYy: [k [!k [Dk [ak [1 [18 [1D [1a [kM kM[! V[k Vk[a [l [l8 [lV [sl [k( [+", -"k Dk[( +D[k [1( [1+ 1D[( 1+[a kM[( +k[M [kV( Vk[+ [l( [l+ l(V[ l+[s [Gk Gk[", -"! Jk[ [aJk [1G 1G[8 J1[ [1J8 Gk[M [!GkM V[Jk JkV[a [lG [8lG lJ[ lJ[s [dk +G", -"[k [dJk g[k [1d 1+[d [dJ1 g[1 dk[M [+GkM Vk[d V[gk [ld [+lG V[ld gl[ [k2 k2", -"[! Dk[2 ak[2 [15 5k[8 1D[5 1a[5 kM[2 [!kM2 [kV2 V[ak2 [l5 l5[8 V5[l [5ls [;", -"k +k[; Dk[; ak[; [1; [>1 1D[; [a>k k;[M [+kM; Vk[; V[+k; [l; [>l V[l; l>[s ", -"Gk[2 [!Gk2 [kJ2 Jk[a2 1G[5 [1G58 [1J5 J1[5a [GkM2 GkM[!2 JkV[2 V[aJk2 [5lG ", -"[lG58 J5[l [slJ5 Gk[; [+Gk; [;Jk [;gk 1G[; [d>k [1J; >kg[ [dkM; +Gk[;M Jk;V", -"[ g[Vk; [5ld lG[> J;[l [>gl [kP kP[! Dk[P ak[P [1P 1P[8 1D[P 1a[P S[k [!Sk ", -"SkV[ Sk[a [lS S8[l SV[l [lSs kP[( +k[P [DkP( [+DkP 1P[( 1+[P [1DP( [1+DP [k", -"S( Sk[+ SV[k( SV+[k l(S[ S[l+ SlV[( [slS+ Yk[ [!Yk YJk JkYa Y1[ [1Y8 J1Yk J", -"8Yk YkS[ S[Yk! ]k ]ak lY[ Y8[l ]l ]ls [dYk [+Yk YdJk YJgk [dY1 [1Y+ YJ1[d Y", -"1g[ Sk[d S[+Yk ]dk ]gk S[ld Y+[l ]ld ]lg [mk km[! Dk[m ak[m [1m 1m[8 1D[m 1", -"a[m Sk[m S[km! Vk[m S[akm [pl lp[8 [lVp ls[p km[; +k[m [mDk; [+mDk 1m[; [1>", -"P [1mD; [>1Dm Sk[; S[+km SV;[k S[ak; l;[p l>[p [plV; V>[Sl [mYk Yk[m! JmYk ", -"YJkam [1Y5 Y1[8m J5Yk YJ58k S[Ykm YkmS[! ]km ak]m [plY [plY8 ]lp ls]p [vk [", -"+vk YkJv gk[v [v1 >k[v J1[v g1[v vkS[ [vS+k ]vk gv]k lv[ [>lY ]lv ]yl [t [t", -"& [tD [ct [t1 [: tD[1 [:c [tM tM[& V[t V[tc [lt [:l V[lt u[ [t( t+[ [Dt( t+", -"[c t([1 [:+ [t1D( [+:c [Mt( tM[+ t(V[ V[t+ l([t l+[: [lVt( u[+ tG[ [&tG tJ[", -" [ctJ [1tG [:G [tJ1 :J[ [GtM tG[M& V[tJ tJV[c tG[l lG[: [ltJ uJ[ td[ [+tG [", -"Jtd g[t [1td [:d td[J1 g[: tM[d t+[GM V[td V[gt td[l ld[: lJ[td ug[ [t2 t2[", -"& [Dt2 c2[t t5[ [:5 tD[5 t5[c [Mt2 [tM&2 V2[t [cVt2 t5[l [5l: V[t5 u[5 t;[ ", -"[+t; tD[; t;[c [1t; t>[ t5[D; c>[: tM[; t+[M; V[t; [c;Vt t;[l l>[: [l;Vt u[", -"> [Gt2 tG[&2 t2[J tJ[c2 [5tG [5:G [Jt5 J5[: tG[M2 [&MtG2 tJV[2 [cVtJ2 tG5[l", -" [:lG5 lJ[t5 J5u[ [dt; t+[G; [Jt; t;g[ [5td tG[> tJ5[d t>g[ tG;[M tGM[;& tJ", -";V[ g[tV; [ldt5 [:dl> lJ;[t g[u> tP[ [&tP [DtP tP[c [1tP [:P tP[1D :P[c St[", -" [tS& V[St [cSt [lSt S:[ SlV[t u[S [Pt( [+tP tP[D( tcP[+ tP[1( [+:P [1DtP( ", -"[:c+P S([t t+S[ StV[( St+[c Stl[( S+[: [lVSt( S[u+ tY tY& tYJ tYc tY1 tY: Y", -"1tJ :JtY tYS S&tY ]t ]tc lYt tYS: ]lt ]u tYd tY+ YJtd gtY Y1td t+Y: tYJ1d Y", -":g[ SdtY S+tY ]td ]gt ldtY l+tY lt]d ]ug tm[ [&tm tD[m tm[c [1tm [:m t5[Dm ", -":m[c tmS[ S[&tm V[tm [cmSt tp[ [p: V[tp up[ [mt; [+tm tm[D; [cmt+ t5[;P >P[", -": tmD[1; [:mc> t;S[ St+[m St;V[ Sc;[t t;[p [pt> tp[V; S>u[ tYm Y&tm YJtm tm", -"Yc tY5 t5Y: YJt5 t5Yc tmSY tYSm& ]tm tc]m tpY Y:tp ]pt ]up tYv t+[v tJ[v tv", -"g[ t5[v tY> [v1tJ Yct> St[v [v&St ]tv gt]v tYlv tYS> lv]t ]yu Xe Xe! XeB aX", -"e Xe. 8Xe e.XB aX8e XeK X!eK TXe aXTe Xje Xj8e XjTe sXe X* +Xe X*B aX* X*. ", -"8X* X.*B aX8* X*K +KX* TX* TX+e X*j X*+j XjT* sX* GXe XeG! HXe aXHe XeG. GX", -"8e XeH. 8XHe XeGK GXe!K TXHe aXeGT GXej XjeG8 XjHe HXse fX f+X fHX gfX fX. ", -"f8X HXf. f8gX fXK +XfK fTX fTgX fjX +Xfj HXfj sfX Xe2 X!e2 e2XB X2ae 5Xe 8X", -"5e Xe5B aX5e e2XK Xe2!K XeT2 aXeT2 Xj5e Xje58 TX5e 5Xse X;e X;+e *BX; X;ae ", -"5X* >Xe *B5X aX>e XKe; X;e+K X;Te aX;Te Xj5* X*>j TX5* sX>e XeG2 GXe!2 XeH2", -" aXeG2 GX5e G58Xe 5XHe G5aXe GXe2K Xe2GK! GTXe2 GTXae2 XjeG5 G58Xje G5TXe s", -"X5He fX; +Xf; HXf; fXg; f5X f>X H5fX gf>X X;fK f+X;K TXf; fTXg; 5Xfj fj>X 5", -"TfX >Xsf eP eP! ePB aeP eP. 8eP P.eB ae8P QXe Q!eP TeP aXQe ePj 8XQe ejTP s", -"eP X*P +eP *BeP ae+P X.P* 8e+P X*P.B aX*8P QX* QX+e TXQ* Te+P XjQ* 8XQ* X*j", -"TP +esP Ye Ye! YHe Yae Ye. Y8e HeY. H8Ye YQe QeY! YZe ZeYa Yje Q8Ye ZeYj sY", -"e Yf Yf+ YfH gYf Yf. Yf8 fHY. Y8gf YfQ fQY+ ZfY ZfgY Yfj fQY8 YjZf sYf Xme ", -"X!em XBem Xmae 5eP 8e5P 5BeP ae5P XmQe XmeQ! XmTe aXmQe pXe 8Xpe TXpe pXse ", -"Xm* Xm+e *BXm Xma* Xm5* >eP Xm*5B ae>P XmQ* Xm*+Q XmT* aXmQ* pX* pX>e TXp* ", -"se>P Yem emY! HeYm aeYm Y5e 5eY8 H5Ye 5aYe QeYm YQem! YmZe YZaem Ype peY8 Z", -"eYp seYp Yfv fvY+ YHfv Yfgv Yf5 Y>f YHf5 f>gY fQYv Yfv+Q YvZf gYZfv fpY fpY", -"> ZfYp yYf ,X ,X& ,XB ,aX ,X. ,8X X.,B 8X,a ,XK ,KX& ,TX TX,a ,Xj 8X,j TX,j", -" sX, ,X* -X *B,X -Xa ,.X* -X8 X*.,B 8X-a ,KX* -XK T*,X -TX X*,j -Xj X*j,T s", -"-X ,GX G&,X ,HX Ga,X GX,. G8,X ,.HX H8,X GX,K X&K,G GT,X ,GTaX Gj,X X&j,G H", -"X,j ,GsX fX, f-X ,HfX g-X ,Xf. -Xf8 fHX,. g8-X ,XfK fK-X ,TfX -TgX ,Xfj -Xf", -"j fTX,j gXs- ,X2 ,2X& X2,B ,2aX ,5X 5X,8 ,B5X 5a,X X2,K X&2,K ,2TX ,TX&2 5X", -",j X&j,5 5T,X ,5sX ,X; -X; ,BX; aX-; 5X,; >X- ,5X*B -a>X ,KX; X;-K TX,; TX-", -"; X;,j -j>X X;j,T >Xs- GX,2 X&2,G ,2HX ,GaX2 G5,X ,G58X H5,X ,G5aX ,GX2K ,G", -"2X&K ,GTX2 aX2,GT ,G5Xj ,G5X&j ,G5TX sX,G5 ,Xf; f;-X HX,; g;-X ,5fX f->X f5", -"H,X g->X fX;,K f-X;K fTX,; f-TX; f5X,j f>-Xj f5T,X s-Xf> ,XP eP& ,BeP aX,P ", -",.eP 8X,P eP.,B aeP,8 ,QX Q&,X QX,T Qa,X QX,j Q8,X ePj,T ,QsX X*,P -XP X*P,", -"B aX-P X*P,. 8X-P ,X.P*B -X8aP Q*,X -QX ,QXT* Qa-X X*j,Q Q8-X ,TXP*j -QsX Y", -", Y&e Y,H Ya, Y,. Y8, ,HY. ,HY8 Y,Q ,QY& YZ, ZeY& Yj, ,QY8 Z,Yj sY, Yf, Y- ", -"fHY, Y-g f,Y. Y-8 YfH,. Y8g- fQY, Y-Q Y,Zf Y-Z fjY, Y-j YZ,fj sY- ,Xm X&,m ", -",BXm aX,m 5X,m 8X,m ,5XmB aXm,5 QX,m Xm&,Q TX,m aXm,Q pX, ,8pX ,TpX pXs, Xm", -",; -Xm Xm*,B aX-m Xm*,5 -X>P X;B,5P >X-am QX,; QX-m Xm*,T TX-m ,Xp* -pX pX*", -",T sX-p Y,m ,mY& ,HYm ,aYm Y5, ,5Y8 ,HY5 ,5Ya ,QYm Y&Q,m YmZ, YZ&,m Yp, peY", -"& ZpY, s,Yp Yv, Y-v YHv, -vgY f5Y, Y-> Yf5,H g-Y> YQv, -QYv ZvY, YZ-v Y,fp ", -"Y-p fpZY, yY- IXe I!Xe DXe aXDe XeI. IX8e XeD. 8XDe XeIK IXe!K TXDe aXeTI I", -"Xej IjX8e XjDe DXse I*X I*+X DX* DX+e I.X* I*8X D.X* 8XD* IKX* I*X+K TXD* a", -"X*TI X*Ij I*j+X X*Dj DXs* IXGe GIXe! JXe aXJe GIXe. G8IXe XeJ. 8XJe GIXeK I", -"XeGK! TXJe JTaXe IjXGe G8IXje XjJe JXse fIX +IfX JfX JfgX IXf. 8IfX fXJ. JX", -"f8 IXfK f+IXK JXfT JfTgX IjfX f8IXj JXfj JfsX XeI2 IXe!2 XeD2 aXeI2 IX5e 5I", -"8Xe DX5e 5DX8e IXe2K Xe2IK! DXTe2 DXTae2 IjX5e 5I8Xje 5DXTe sI5Xe X;I* I;X+", -"e X;De aX;De I*5X I*>X DX5* DX>e I;XeK +IXe;K DX;Te DX;+Te I;jX* >IjX* X;jD", -"e sI*>X GIXe2 IXeG2! XeJ2 JaXe2 G5IXe 5IXG8e 5XJe J58Xe IXeG2K I!X2GeK JTXe", -"2 aXeJT2 G5IXje 8eGj5IX J5TXe sJ5Xe I;fX f+IX; fXJ; JfXg; 5IfX fI>X JXf5 Jf", -">X fIX;K I;Xf+K JfTX; fTXgJ; f5IXj f>IXj Jf5TX J>sfX IPe I!eP DeP aeDP I.eP", -" IP8e D.eP 8eDP IPQe IPeQ! DXQe aePQD ePIj IPj8e ePDj DesP IP* IP+e IPD* De", -"+P I.P* IP8* IP*D. aP*8I IPQ* IP*+Q DXQ* aX*QD P*Ij IP*+j IP*Dj IPs* YIe Ie", -"Y! YJe JaYe IeY. 8IYe JeY. YeJ8 QIYe YQIe! ZeYJ YZJae IjYe Y8QIe YeJj YJse ", -"YfI f+YI YJf YJgf fIY. YIf8 Y.Jf JfY8 YIfQ Yf+QI YJZf gYZJf YIfj Yf8QI JfYj", -" YJsf emIP ImXe! XmDe aXmDe IP5e 5IP8e De5P aeP5D ImXQe QIXem! QDXem QDXaem", -" IPpe pI8eP DXpe sIPpe XmI* Im*+X XmD* aXmD* IP5* IP>e IP*5D De>P Im*QX +QI", -"Xm* Im*TX +QDXm* IPp* >XpI* DXp* sIP>e ImYe YIem! YeJm YJaem 5IYe Y58Ie YeJ", -"5 YJ58e YQIem ImeYQ! YZJem ZJeYam YIpe Yp8Ie peYJ JpsYe vIYf Yfv+I YfJv gYJ", -"fv YIf5 >IYf JfY5 YJf> YfvQI fvQY+I YZvJf ZfJgYv pIYf fpY>I YJfp YJyf hX hX", -"& hDX hcX hX. h8X DXh. cXh8 hXK X&hK hTX cXhT hjX 8Xhj DXhj hsX hX* h-X DXh", -"* c-X X*h. -Xh8 hDX*. c8-X X*hK hK-X TXh* -TcX X*hj -Xhj hTX*j sXh- hGX G&h", -"X hJX cXhJ GXh. G8hX JXh. hXJ8 GXhK hGX&K JThX cJThX GjhX h8GXj hXJj sXhJ h", -"fX -Xhf hXJf iX fXh. hXf8 JfXh. i8X fXhK f-XhK hXfT iTX hXfj f-jhX JfjhX is", -"X hX2 X&h2 DXh2 h2cX h5X 5Xh8 5DhX cXh5 X2hK hX&2K TXh2 cXTh2 5Xhj h58Xj 5T", -"hX sXh5 h;X -Xh; DXh; cXh; 5Xh; h>X h5DX; hc>X X;hK -X;hK TXh; c-XT; X;hj h", -"j>X h5TX; >Xhs GXh2 hGX&2 JXh2 cJXh2 G5hX h5G8X hXJ5 cJ5hX hGX2K X&2hGK hJT", -"X2 hJTcX2 h5GXj X&jh5G hJ5TX hsJ5X fXh; f-Xh; hXJ; iX; hXf5 hf>X Jf5hX i>X ", -"hfX;K hf;-XK hJ;TX TXi; hf5Xj h>fXj J;jhX >Xis hP hP& hPD hcP hP. h8P DPh. ", -"cPh8 hQX QXh& hTP cQhP hPj Q8hP DPhj hsP hP* h-P DPh* c-hP P*h. -Ph8 hPD*. ", -"c-X8P QXh* -QhP TPh* -QcX P*hj -Phj hTP*j hPs- hY hY& hYJ Ych hY. hY8 h.YJ ", -"h8Yc hYQ Y&hQ hZY YchZ hYj Y8hQ YZhj hsY hYf Y-h YJhf iY h.Yf h8Y- hYJf. iY", -"8 YfhQ hQY- ZfhY iZY Yfhj hjY- hYjZf isY hmX Xmh& DXhm cXhm h5P 5Ph8 5DhP c", -"5hP QXhm hQXm& TXhm cQXhm hpX pXh8 pDhP hPcp h;P -Xhm D;hP c;hP 5Ph; h>P h5", -"PD; hc>P QXh; -QXhm T;hP c-QXm pXh; >Xhp hpDX; >Phs hYm Y&hm YJhm hmYc hY5 ", -"Y5h8 YJh5 h5Yc YQhm hYQm& YZhm hZYcm hpY h8Yp hYJp sYhp hvY Y-hv JvhY iYv Y", -"fh5 h>Y hY5Jv iY> YvhQ hvY-Q YZhv YZiv hYfp Y-hp JpfhY yiY Xe0 X!e0 e0XB Xe", -"a0 1Xe 8X1e Xe1B aX1e e0XK Xe0!K XeT0 aXeT0 Xj1e Xje18 TX1e 1Xse X*0 +0X* X", -"0*B a0X* 1X* +X1e *B1X aX1* *0XK X*0+K T0X* aX*T0 Xj1* X*j1+ TX1* 1Xs* XeG0", -" GXe!0 XeH0 aXeG0 GX1e 1G8Xe HX1e 1GaXe GXe0K Xe0GK! GTXe0 GTXae0 Xje1G 1G8", -"Xje 1GTXe sX1He fX0 +Xf0 HXf0 fXg0 f1X 1+fX 1HfX f1gX X0fK f+X0K TXf0 fTXg0", -" 1Xfj f1+Xj 1TfX f1sX e0X2 Xe0!2 Xe02B aXe02 5X1e 1X58e 1X5eB 1aX5e Xe02K e", -"02XK! TXe02 TX0ae2 Xje15 5X81ej 1TX5e sX15e X0e; X;e+0 X;e0B aX;e0 5X1* 1X>", -"e 1X;*B >X1ae X;e0K +X0e;K TX;e0 aX0Te; X;j1e >X1ej 1TX5* sX*>1 GXe02 Xe0G2", -"! HXe02 HX0ae2 1G5Xe G581Xe 1HX5e H5X1ae Xe0G2K 2Ke!GX0 TX0He2 aXHeT02 1G5X", -"je 8eGj1X5 H5X1Te 1HXse5 X;f0 f+X;0 fHX;0 gfX;0 1Xf5 f1>X f1H5X f>g1X fX;0K", -" X;0f+K fTX;0 gX;fT0 f15Xj f>1Xj f1T5X sf>1X eP0 P!e0 P0eB a0eP 1eP 8e1P 1B", -"eP ae1P Q0eP eP0Q! T0eP aePQ0 QX1e ePj18 Te1P 1esP X0P* +0eP X*P0B aX*P0 X*", -"1P +e1P 1X*PB aX*1P Q0X* +QXe0 QX*T0 aX*Q0 QX1* ePj1+ 1QXT* sX*1Q Ye0 e0Y! ", -"HeY0 aeY0 Y1e 1eY8 1HYe 1aYe QeY0 YQe!0 Y0Ze YZae0 1QYe Y1Q8e ZeY1 Y1se Yf0", -" f+Y0 fHY0 g0Yf Yf1 f1Y+ YHf1 Yfg1 Y0fQ Yf+Q0 Y0Zf gYZf0 f1Yj Yf1+Q Y1Zf Y1", -"sf X0em Xme!0 Xme0B aXme0 5e1P 1Xm8e 1XmeB aXm1e XmeQ0 QX0em! TXme0 aX0Tem ", -"1Xpe pX18e pX1Te sePp1 X0m* Xm*+0 Xm*0B aXm*0 Xm1* 1e>P Xm*1B >eP1a Xm*Q0 X", -"m0+Qe Xm*T0 aX0Qe; 1Xp* >Xp1e pX*1T sX*p1 emY0 Yem!0 YHem0 Yaem0 1eY5 Y158e", -" Y1H5e Y1a5e YQem0 em0YQ! YZem0 ZemYa0 peY1 Yp18e YZ1pe sYp1e Y0fv Yfv+0 Yf", -"vH0 gYfv0 fvY1 Y1f> Yf1vH gY1f> YfvQ0 fvQY+0 YZvf0 ZfvgY0 Y1fp fpY>1 fpZY1 ", -"Yfy1 ,X9 X&9e ,B9X 9a,X ,1X :Xe ,B1X ,a:X ,K9X X&K9e 9T,X ,TX9a 9X,j ,X:j 1", -"T,X :Xse 9X* -X9 *B9X 9a-X 1X9* :-X ,1X*B :a-X 9KX* 9X-K TX9* 9T-X X*9j -j:", -"X X*j9T :-sX 9G,X ,G9X& 9H,X ,Ga9X 1G,X ,G:X 1H,X ,H:X ,G9XK ,G9X&K ,GT9X 9", -"GT,aX ,1GXj :GX,j ,1GTX sX,:G f9X -Xf9 9HfX f9gX ,1fX :fX f91HX gX:f 9XfK f", -"-9XK 9TfX f-T9X 9Xfj fj:X f9T1X sX:f ,29X X&29e ,X92B ,aX92 95,X ,5:X ,1X5B", -" :X5,a ,X92K 9X2e&K ,TX92 aX29Te ,1X5j :X5,j ,1T5X sX,:5 9X,; 9X-; ,X;9B -X", -"9a; 1X,; :->X ,1X;B :-X>a ,X;9K -X9;K ,TX9; -TX9; X;j,1 :-X>j ,1TX; s-X:> ,", -"G9X2 ,G9X&2 ,HX92 aX29He ,1G5X :G5,X ,1H5X :HX,5 9G2,XK X&9eG2K ,G29TX ,2GT", -"9aX 9G5,Xj ,G5:Xj 9G5,TX sX5:He 9Xf; f-9X; f9HX; gf9X; 95fX >X:f f95HX g:Xf", -"> f9X;K -X;f9K f9TX; f9;-TX f95Xj :f>Xj f95TX sf:>X 9eP e&9P 9BeP ae9P 1X,P", -" :eP ,1XPB ae:P 9Q,X eP&9Q Te9P aeP9Q 1Q,X ,Q:X ePj9T :esP X*9P 9X-P 9X*PB ", -"-X9aP ,1XP* -X:P X*B,1P :-XaP QX9* 9Q-X 9QXT* -QX9T X*j9Q -Q:X 9TXP*j s-X:Q", -" Y9e 9eY& ,HY9 ,aY9 Y1, Y:e ,1YH :HY, ,QY9 Y9Qe& Z9Y, YZ9,a ,1Yj :QY, Z1Y, ", -"seY: Yf9 Y-9 YHf9 g9Y- f9Y1 Y:f Yf91H gY:f fQY9 -QY9 Y9Zf Y9Z- f9Yj Yj:f Zf", -"9Y1 Y:sf 9X,m Xm&9e ,Xm9B aXm9e 1X,m ,X:m ,1XmB :Xm,a ,QX9m 9QXem& ,TX9m 9Q", -"a,Xm ,1pX pX:e p9X,T :pXse Xm9* 9X-m Xm*9B -Xm9a Xm*,1 :e>P XmB,1; :-Xam Xm", -"*9Q -QX9m Xm*9T -TX9m 9Xp* :X-p p9XT* -pXs: ,mY9 Y9em& Y9H,m Y9a,m ,1Y5 :eY", -"5 Y95,H Y:H,5 Y9Q,m em&Y9Q YZ9,m Y9mZe& p9Y, Y,:p Yp9Ze sY:pe fvY9 Y9-v Yf9", -"vH gY9-v f9Y5 :fY> Yf9H5 Y:gf> Yf9vQ Y-v9Q Zf9Yv Y-Zv9 Y9fp fpY: fp9YZ Y:yf", -" XeI0 IXe!0 XeD0 aXeD0 IX1e 1I8Xe DX1e 1DX8e IXe0K Xe0IK! DXTe0 DXTae0 IjX1", -"e 1I8Xje 1DXTe sI1Xe I0X* I*X+0 D0X* aX*D0 I*1X 1+IX* DX1* aX*1D I*X0K +I0X", -"*K DX*T0 aX0TI* I*j1X 1+IX*j X*j1D sI*1X GIXe0 IXeG0! XeJ0 JaXe0 1GIXe G8I1", -"Xe 1XJe J18Xe IXeG0K I!XKGe0 JTXe0 aXeJT0 1GIXje 8eGj1IX J1TXe sJ1Xe IXf0 f", -"+IX0 fXJ0 JfXg0 1IfX f1+IX JXf1 Jf1gX fIX0K +IXf0K JfTX0 fTXgJ0 f1IXj 1+Ifj", -"X Jf1TX sfJ1X IXe02 Xe0I2! DXe02 DX0ae2 1I5Xe 5I81Xe 1DX5e 5DX1ae Xe0I2K I!", -"X2e0K TX0De2 aXDeT02 1I5Xje 8X5e1Ij 5DX1Te 1DXse5 I;Xe0 +IXe;0 DX;e0 aX0De;", -" 1I;X* >I1X* 1DX5* >XD1e X;0I*K +KI;X*0 I;0TX* X;De+T0 1I;X*j I*j>X1 1DXe;j", -" >I1sX* IXeG02 I!X2Ge0 JXe02 aXeJ02 G5I1Xe 8X5e1GI J15Xe 1aXJ5e IXG0e2K IXG", -"02Ke! TXeJ02 aXJeT02 Ij1XG5e GX8e15Ij 1TXJ5e J15sXe fIX;0 I;Xf+0 JfX;0 gfXJ", -";0 f15IX f>1IX Jf15X J>f1X I;Xf0K I;fX+0K fTXJ;0 X;g0JfT I;jf1X f1I>Xj J1Xf", -"5T sf1J>X I0eP IPe!0 D0eP aePD0 IP1e 1IP8e De1P aeP1D IPeQ0 QI0eP! QDXe0 aX", -"0QDe IPj1e Q8I1eP ePj1D sIP1e I0P* IP*+0 IP*D0 aP*I0 IP1* IP*1+ IP*1D aP*1I", -" IP*Q0 IP0+Qe IP*T0 aX0QD* IP*1Q 1+QIP* IP*1T sIP1* IeY0 YIe!0 JeY0 YJae0 1", -"IYe Y18Ie YeJ1 YJ18e YQIe0 QIeY0! YZJe0 ZJeYa0 Y1QIe 1QIY8e YZ1Je sYJ1e fIY", -"0 Yf+I0 Y0Jf gYJf0 YIf1 Yf1+I JfY1 gY1Jf YfQI0 fQIY+0 YJfZ0 ZfJgY0 Yf1QI Y1", -"IfQ8 Zf1YJ sYfJ1 ImXe0 em0IP! DXme0 aX0Dem 1ImeP 8Im1eP 1DXem 1DXaem QIXem0", -" ImQXe0! Im0TeP aXQeIm0 pI1eP 1IPpe8 pDX1e sX1pDe Im*X0 Im0+eP Xm*D0 aX0Im*", -" Im*1X >eP1I Xm*1D >eD1P Im0QX* Im+XQe0 Im0TX* XmD*+Q0 pI*1X >I1pX* pDX1* >", -"I1seP YIem0 ImeY0! YJem0 JmeYa0 Y15Ie 1ImY8e YJ15e Y1eJ8m ImeYQ0 QmY0Ie! Ze", -"mYJ0 aeJmYZ0 Yp1Ie pI8Y1e JpY1e sY1Jpe YfvI0 fvIY+0 YJfv0 JvfgY0 Yf1vI Y>f1", -"I Jv1Yf Y>Jf1 fQIYv0 YQvIf+0 JvYZf0 gJZfYv0 fpY1I Y>1fpI JpfY1 yJYf1 h9X 9X", -"h& 9DhX h9cX h1X h:X 1DhX :Xhc 9XhK h9X&K 9ThX cX9hT 9Xhj :Xhj 1ThX sXh: 9X", -"h* h9-X DX9* c9-X 1Xh* :Xh- h1DX* c-:X h9X*K -X9hK hT9X* c-X9T h1X*j h:-Xj ", -"h1TX* s-Xh: 9GhX h9GX& hXJ9 cJ9hX 1GhX hG:X hXJ1 :XhJ h9GXK X&Kh9G J9ThX hJ", -"9cXT h1GXj h:GXj J9jhX hsJ:X hXf9 f-9hX JXf9 i9X hXf1 :Xhf Jf91X i:X f9XhK ", -"hf9-XK Jf9TX 9TiX f9jhX :fhXj Jf9Xj s:iX 9Xh2 h9X&2 h9DX2 cX9h2 95hX :Xh5 h", -"15DX h:c5X h9X2K X&2h9K hT9X2 hT9cX2 h15Xj h:5Xj h1T5X hs:5X 9Xh; -X9h; h;9", -"DX c-X9; 1Xh; >Xh: h1;DX c>Xh: h;9XK h;9-XK hT;9X cX9hT; h1;Xj h>:Xj h1TX; ", -"hs>:X h9GX2 X&2h9G J9Xh2 hJ9cX2 h1G5X h:G5X J95hX :Jh5X 9GXh2K X&h29GK hTXJ", -"92 h9cXJT2 9G5hjX h5G:Xj J9Xh5T :J5hsX f9Xh; hf9-X; Jf9X; 9Xi; f95hX h>:fX ", -"Jf95X >Xi: h;Xf9K h9-Xf;K J9XhT; i9;TX f9Xh;j :fXh>j J9Xf5T is:>X hP9 9Ph& ", -"9DhP h9cP h1P h:P 1DhP :chP 9QhP hQ9X& 9ThP cQXh9 9Phj :QhP 1ThP s:hP 9Ph* ", -"h9-P hP9D* c-X9P 1Ph* :-hP h1PD* h:Pc- hQ9X* -QXh9 hTP9* c-Q9X h1QX* h:Q-X ", -"h1TP* hsP:- hY9 h9Y& Y9hJ Y9hc hY1 Y:h YJh1 hY:J Y9hQ hY9Q& Y9hZ hZYc9 Y9hj", -" hQY: YZh1 Y:hZ Y9hf Y9h- JfY9 iY9 Yfh1 hY:f hY1Jf iY: hYf9Q Y-h9Q Zf9hY YZ", -"i9 hY1fQ Y:hfQ hZ1Yf sYi: 9Xhm hm9X& hm9DX cXmh9 95hP :Xhm h1mDX h:mcX hQ9X", -"m Xm&hQ9 hTm9X cX9hTm p9hP hP:p hp9DX cpXh: 9;hP -Xmh9 h;P9D c-X9m 1;hP >Ph", -": h1;DP h>P:c hQ;9X -Q9h;P hT;9P cQ9-Xm hp9X; -pXh: p9DX* cp-:X Y9hm hY9m& ", -"hYJ9m Ych9m Y9h5 h5Y: hY1J5 Y:Jh5 hY9Qm hQ9Y&m hZY9m Yc9hZm h1Yp Y:hp Jp9hY", -" hZ:Yp Y9hv hvY-9 Jv9hY Yvi9 Yvh1 Y:hv hv1YJ Y:iv hvY9Q Y-9hvQ hZvY9 iZYv9 ", -"fp9hY hv:Yp JpfY9 yYi: Re Re! ReB Rae Re. R8e e.RB 8eRa ReM R!Me RTe TeRa R", -"ej 8MRe TeRj sRe Re* R+e *BRe +eRa R.X* +eR8 X*.RB aX*R8 XM* +MRe TXR* +TRe", -" X*Rj +eRj XM*Tj R+se RGe GeR! RHe GaRe GeR. G8Re R.He H8Re GMRe XM!Ge GTRe", -" aXMHe GjRe RG8Me HeRj RGse fR fR+ fRH gfR fR. fR8 RHf. f8gR fRM R+fM fRT f", -"RgM fRj R+fj RHfj sfR Re2 e2R! e2RB R2ae R5e 5eR8 RB5e 5aRe R2Me XM2e! R2Te", -" aXMe2 5MRe R5e8M 5TRe R5se Re; +eR; RBe; aeR; 5XR* >eR R5e*B Ra>e MeR; XM;", -"+e TeR; aXMe; XM5* Re>M XM*5T sR>e GeR2 RGe!2 R2He RGae2 G5Re RG58e H5Re RG", -"5ae XM2Ge RG2Me! RGTe2 aX2HMe RG5Me G5MR8e RG5Te sRG5e fR; R+f; RHf; g;fR f", -"R5 f>R RHf5 gRf> R;fM fR+M; RTf; fRTg; R5fM fR>M R5fT sRf> ReP R!eP RBeP aP", -"Re R.eP 8PRe eP.RB aePR8 Se Se! SeT Sae Sej S8e TeSj Sse ePR* +PRe X*PRB aX", -"*RP X*PR. R+e8P Re.P*B R8eaP* Se* S+e TXS* +TSe X*Sj +eS8 SeT*j S+se YRe Re", -"Y! RHYe RaYe ReY. R8Ye YRHe. Y8RHe SYe YeS! SZe YaSe YjSe Y8Se SjZe seSZ Yf", -"R fRY+ YHfR YfgR Y.fR fRY8 YfRH. gYfR8 Sf Sf+ SfZ gSf Sfj Sf8 fjSZ sfS Rem ", -"R!em RBem aeRm 5eRm 8eRm R5emB aemR5 Sem emS! TeSm aeSm Spe peS8 STpe seSp ", -"XmR* +eRm Xm*RB aXmR* Xm*R5 Re>P XmBR5* >eRam Se; +eS; TeS; aeS; pXS* S>e S", -"peT; >eSs ReYm YRem! HeRm YaRem R5Ye Y5R8e Y5RHe Y5aRe YeSm SYem! SmZe SZea", -"m SeYp SpeY8 ZpSe SseYp fvR f+vR fHvR fvgR fRY5 fRY> Yf5RH f>RgY Sfv fvS+ Z", -"fSv gfSv Sfp Sf> SZfp yfS ,RX Re& RB,X Ra,X ,.Re R8,X ,RX.B ,R8aX ,XM X&,M ", -"RT,X TeR& Re,j 8X,M ,RTXj ,RsX R*,X -RX X*B,R Ra-X X*.,R R8-X ,R.X*B -R8aX ", -"X*,M -XM XM*,T RT-X XM*,j Re-j ,RTX*j -RsX ,RG R&,G RG,H RG,a ,.RG RG,8 ,RG", -"H. ,RGH8 RG,M XM&,G RG,T aXM,G RG,j e&jRG ,RGHj ,RsG fR, f-R ,RfH f-gR ,Rf.", -" -Rf8 fRH,. f-Rg8 ,RfM -RfM ,RfT -RfT ,Rfj -Rfj fRT,j f-sR ,2Re R2e& ,RX2B ", -",RaX2 R5,X 5eR& ,R5XB ,R5aX ,2XM XM&,2 ,RTX2 aXM,2 5X,M XM&,5 ,R5TX sX,R5 R", -"e,; Re-; ,R;XB -RaX; ,R5X; -R>X X;B,R5 >X-Ra XM,; XM-; XM;,T -RTX; XM;,5 -X", -">M ,RTX;j s-R>X ,2RG ,RG&2 ,RGH2 ,RGa2 RG,5 ,RG5& ,RGH5 ,RG5a ,RGM2 X&2,GM ", -",RGT2 aX2,GM ,RG5M ,G5XM& ,RG5T sRG,5 ,Rf; f;-R fRH,; f-Rg; ,Rf5 ->fR fR5,H", -" f>Rg- fRM,; f-RM; fRT,; f-RT; fR5,M f>R-M fR5,T sfR-> Re,P ePR& ePB,R aeP,", -"R eP.,R eP&R8 ,R.ePB ,R8aeP Se, Se& ,TSe ,aSe ,XSj ,8Se SeT,j Ses, X*P,R Re", -"-P ,RXP*B -RaeP ,RXP*. -R8eP ePR*,.B aeP-R8 ,XS* S-X SeT,* -TSe Se*,j -XS8 ", -"X*jS,T sXS- Y,R ,RY& ,RYH ,RYa ,RY. ,RY8 Y,RH. Y8,RH SY, Y&Se YZS, YaS, YjS", -", Y8S, SZe,j SYs, fRY, Y-R YfR,H gRY- YfR,. -RY8 fRHY,. Y-gR8 Sf, Sf- S,Zf ", -"Y-gS fjS, S8Y- SfZ,j S-sY Re,m emR& ,RmXB aXm,R ,R5Xm em&R5 XmB,R5 ,R5aXm ,", -"XSm emS& SeT,m Sae,m pXS, peS& Spe,T Ssep& Xm*,R Re-m XmB,R; -RmaX ,R5Xm* >", -"X-Rm Xm,;R5B >Xa-Rm ,XS; -XS; Se;,T S-TXm Spe,; >XS- S;TpX, -pXSs ,RYm Y&R,", -"m Y,RHm Ya,Rm ,RY5 Y5&,R Y5,RH Y5a,R SmY, SY&,m SZe,m SZem& S,Yp Yp&Se Yp,S", -"Z sY,Sp vRY, fR-v Yv,RH -vRgY Yf5,R -RY> Y5HvR, Y->gR YvS, SvY- Sv,Zf gSf-v", -" S,fp Y-S> SfpZ, Sfy- [e [!e [De [ae [e. [8e De[. D8[e [Me Me[! V[e [aVe [j", -"e 8M[e [jVe [se [* [+e [*D [a* [*. [8* D*[. D8[* [*M +M[* V[* [+Ve [*j +e[j", -" [jV* [s* [Ge Ge[! [Je Je[a Ge[. G8[e [eJ. Je[8 GM[e [!GMe [JVe VJ[ae Gj[e ", -"[8GMe Je[j [Jse [f [f+ [fJ g[f [f. [f8 J.[f J8[f [fM [+fM Vf[ Vfg[ [fj [+fj", -" Jj[f sf[ [e2 e2[! De[2 ae[2 [5e 5e[8 5D[e 5a[e Me[2 [!Me2 [eV2 V[ae2 5M[e ", -"[58Me [5Ve [5se [;e +e[; De[; ae[; [5* [>e 5D[* [a>e Me[; [+Me; [;Ve V[+e; ", -"5M[* [*>M [5V* >e[s Ge[2 [!Ge2 [eJ2 [Jae2 G5[e [5G8e Je[5 J5[8e [GMe2 Me2[!", -"G VJ[e2 [JaVe2 [5GMe G5M[8e J5V[e [sJ5e [f; f+[; J;[f [;gf [f5 [>f J5[f f>g", -"[ [;fM [f+M; V;[f Vfg[; [5fM >M[f V[f5 [>sf [eP eP[! De[P ae[P eP[. 8e[P [D", -"eP. [8DeP S[e [!Se SVe VeSa [jSe [8Se SjVe SVse [*P +e[P DP[* aP[* P*[. 8P[", -"* [*DP. [8*DP S[* [+Se V[S* V+Se [jS* [8S* SVe*j s*S[ [Ye Ye[! Ye[J Ye[a [e", -"Y. Ye[8 YJ[e. YJ8[e [YSe S[Ye! ]e ]ae Ye[j S[8Ye ]je ]se [fY Y+[f YJ[f [fgY", -" Y.[f Y8[f YJf[. g[Yf8 Sf[ S+[f ]f ]gf Yj[f S8[f ]fj ]sf [me em[! De[m ae[m", -" 5e[m 8e[m [5Dem [5aem [mSe S[em! VmSe SVeam [pe [8pe SeVp se[p [m* +e[m Dm", -"[* am[* 5P[* [m>e [5*Dm [>Dem [mS* S[+em VeS; SV+em [p* >e[p V*[p SV>e Ye[m", -" [Yem! Je[m Ya[em Ye[5 Y5[8e YJ5[e Y5[ae S[Yem [YmSe! ]em ae]m [Ype [pY8e ]", -"pe sp]e [vf [+fv [fJv gf[v Y5[f f>[v [vJf5 [>fgY [vSf [vfS+ ]fv gf]v fp[ [>", -"Sf ]pf ]yf [h [h& [hD [ch [h. h8[ [Dh. h8[c hM[ [&hM Vh[ [cVh hj[ [8hM V[hj", -" hs[ [h* [- hD[* [-c h.[* [-8 [hD*. [8c- [*hM [-M [hV* V-[ [*hj [-j Vh[*j [", -"s- [hG hG[& hJ[ hJ[c [Gh. hG[8 h.[J [Jh8 [GhM [hGM& V[hJ VhJ[c hG[j h8[GM [", -"Jhj hJ[s [fh [-f hJ[f i[ h.[f h8[f [fJh. i[8 hM[f fM[- [fVh iV[ hj[f fj[- V", -"f[hj i[s [h2 h2[& [Dh2 h2[c h5[ [5h8 hD[5 h5[c [Mh2 [h&M2 h2V[ Vh[c2 [5hM h", -"5[8M V[h5 h5[s h;[ [-; hD[; h;[c [5h; h>[ h5[D; c>[- [;hM [;-M V[h; V;[- [;", -"hj >M[- Vh5[; [sh> [Gh2 [hG&2 h2[J [cJh2 hG[5 h5[G8 [Jh5 [c5hJ [hGM2 [&GhM2", -" VhJ[2 [cJVh2 h5[GM h5G[&j Vh5[J hs[J5 h;[f [;f- [Jh; i[; h5[f f>[- [f5hJ i", -"[> [fhM; [-fM; Vf[h; V[i; [f5hM [-jf> Vf5[h V>i[ hP[ [&hP [DhP hP[c [Ph. [8", -"hP [hDP. [ch8P Sh Sh& ShV Shc Shj Sh8 SVhj hsS [*hP [-P [hDP* cP[- [h*P. [8", -"-P [*DhP. [-c8P Sh* Sh- S*Vh V-Sh S*hj h8S- ShV*j S-hs hY[ [hY& [JhY [chY h", -".[Y [hY8 hYJ[. hY8[c ShY S&hY ]h ]hc SYhj SYh8 ]hj ]hs [fhY Y-[ hYJ[f i[Y h", -"Y[f. Y8[- [fJhY. Y8i[ Shf Y-Sh ]hf ]i hjSf h8Sf hf]j ]is hm[ [&hm hD[m hm[c", -" [5hm [8hm h5[Dm [c5hm Shm S&hm SVhm hmSc hp[ h8[p VpSh Schp [mh; [-m hm[D;", -" cm[- h5[m* >P[- h5D[m* [-mc> Sh; hmS- SVh; h;Sc h;[p h>S [p*Vh Sch> [Yhm h", -"Y[m& [Jhm [cmhY [hY5 hY5[8 hY5[J Yc5[h SYhm ShYm& ]hm hc]m hY[p [p&hY ]ph h", -"p]s hv[ [-v hJ[v i[v h5[v [-Y> hv[J5 Y>i[ hvS S-hv ]hv ]iv Sfhp Sfh> hp]f ]", -"yi Rek R!ke RBke akRe R1e 1eR8 RB1e 1aRe XMke kXMe! TkRe akXTe lXe R8le RTl", -"e sRle kX* +kRe *BkX kXa* 1XR* 1+Re kX*1B akX1* XMk* kX*+M kXT* akXT* lX* R", -"+le TXl* sXl* GkRe kX!Ge HkRe akXHe 1GRe R1G8e 1HRe R1Gae kXMGe RGkMe! RGTk", -"e RGTake RGle lGR8e RHle lsGRe fRk R+fk RHfk fRgk fR1 R1f8 R1fH fRg1 kXfM f", -"R+kM RTfk fRTgk lfR fRl+ fRlH lXsf R2ke kX2e! kX2eB akXe2 1eR5 R1e58 R1e5B ", -"akX5e kXMe2 XM2ke! RTek2 ak2RTe R5le lX58e lX5Te lsX5e keR; kX;+e kX;*B akX", -"e; 1eR; R1>e kX*5B >kXae kX;Me +kXMe; kX;Te kX;aMe Rel; lX>e lX;Te l>Xse kX", -"2Ge RG2ke! RHek2 ak2RHe R1G5e G5kR8e R1H5e RG5ake RGkMe2 M!kXGe2 kX2HMe akR", -"eGT2 lGR5e RG5le8 lHX5e sX5lHe R;fk fR+k; fRHk; gfRk; R1f5 fR>k fR1H5 f>Rg1", -" fRkM; kX;fM+ fRTk; fT;gkX fRl; >Xlf lfRH5 glf>X keP k!eP kBeP keaP 1PRe ke", -"8P keP1B ake1P Sek keS! TkSe akSe leS S8le lTSe leSs X*kP ke+P kX*PB akXP* ", -"kX*1P kX*8P kXB1P* R1+aeP kXS* +kSe SeTk* S+eTk Sel* S+le lX*ST Ssel+ Yke k", -"eY! HkYe akYe R1Ye 8kYe Y1RHe Y1aRe YkSe SYke! ZkSe SZeak lYe Y8le SZle les", -"Y Yfk fkY+ YHfk Yfgk fRY1 f8Yk Yf1RH gY1fR Sfk fkS+ YkZf gkSf lYf l+Sf ZflY", -" gSlf keRm kXme! kXmeB akXem 1eRm kXm8e keP5B ake5P keSm Sekm! SeTkm Saekm ", -"Sple Spel8 SpelT Sselp Xmk* kXm+e kXm*B akXm* kXm1* ke>P kXB1m* >keaP keS; ", -"S+ekm Se;Tk Saek; Sel; leS> Se;lT S>els keYm Ykem! YkHem Yakem 5kYe Y5k8e Y", -"5kHe Y5ake SYkem YkmSe! SZekm SamZke leYp lYp8e lYZpe lYspe fvYk Yfkv+ Yfkv", -"H gYkfv f5Yk Yf>k Yf5Hk Y>kgf fkSv Sfv+k ZfkSv gSfvk Sflv S>lf lYfZp lYyf ,", -"kX 9eR& RB9e 9aRe R1,X :Re ,R1XB Ra:e 9X,M kX&,M 9TRe akX,T lX, :Rle ,TlX s", -"Xl, 9XR* -kX kX*,B ak-X kX*,1 -R:X k*B,1X :-RaX XM9* 9X-M kX*,T Tk-X ,Xl* l", -"-X lX*,T lXs- R9,G kX&,G 9HRe akX,G R1,G ,R:G ,R1HX RH:e ,RG9M ,GkXM& ,RG9T", -" ,GTakX ,RlG :RGle ,HlX sX,lG fR9 -Rf9 R9fH fRg9 ,Rf1 :fR fR91H gR:f R9fM f", -"-R9M R9fT f-R9T fRl, lX:f lfR,H g-lX ,2kX kX&,2 ,kX2B akX,2 95Re R5:e ,5kXB", -" :Re5a ,kXM2 kX2Me& ,TkX2 ak2,TX ,5lX :Rel5 lX,5T sX,l5 9eR; kX-; kX;,B -kX", -"a; kX;,1 :R>e kXB,1; :>Rae kX;,M -kXM; kX;,T -TkX; ,Xl; >Xl- lX;,T l-Xs> ,R", -"G92 ke2RG& ,HkX2 ak2,RG ,R1G5 :RG,5 ,H5kX :RH5e kX2,GM XMk&,G2 kX2,GT aX9M,", -"G2 lG,R5 :R5lG, lHX,5 sX5lG, R9f; f-R9; fR9H; fR9g; R9f5 :Rf> fR9H5 :fRg> f", -"R9M; f9;-XM fR9T; fR;-Tk lfR,5 lf:>X fR95T gl->X 9PRe ePk& keP,B akX,P keP,", -"1 Re:P kXB,1P :ReaP S9e 9eS& 9TSe 9aSe S9le S:e S9elT seS: kX*,P kX-P kXB9P", -"* -kXaP ,1XkP* :-ReP X*9PR1B :Xa-kP 9XS* -kSe S9eT* S-9TX S9el* lXS- S9TlX*", -" l-SsX Yk, ,kY& ,HYk ,aYk ,RY1 :RY, Y1,RH Y:R,H Y9Se SY9e& Z9Se SZ9ae lY, l", -"eY: YZl, l,sY fRY9 Y-k Yf9RH gkY- Yf9R1 Yk:f Y9HfR1 Y:gfR Sf9 S9Y- S9Zf g9S", -"f l,Sf lY- lYfZ9 sYl- 9eRm kXme& kXm,B akX,m kXm,1 Re:m kXB,1m :Ream 9eSm S", -"9em& S9eTm S9aem p9Se Se:p Sp9Te S:esp kXm,; kX-m kXB,;P -kXam ,R1Xm* :-RXm", -" Xm9*R1B :Ra>eP 9eS; S-9Xm S9eT; S9ae; Sp9X* >eS: S9Tle; -pXls ,kYm Yk&,m Y", -"k,Hm Yak,m ,5Yk Y:R,5 Y5k,H Y5a,k SY9,m SemYk& SZ9em S9mYa, l,Yp lY:pe lY,Z", -"p lYsp, vRf9 Yk-v Yvk,H Y-kgv Yf9R5 >kY- Y9HfR5 :vRgf fvS9 Sf-v9 Sf9Zv gSfv", -"9 S9fp Y-lv fp9SZ lYy- [ke ke[! Dk[e ak[e [1e 1e[8 1D[e 1a[e ke[M [!kMe [kV", -"e V[ake [le [8le V[le le[s [*k +k[* Dk[* ak[* [1* 1+[* 1D[* 1a[* k*[M [+kMe", -" Vk[* V[+ke [l* [+le V[l* l*[s Gk[e [!Gke [kJe Jk[ae 1G[e [1G8e Je[1 J1[8e ", -"[GkMe keM[!G JkV[e V[aJke [Gle [lG8e [Jle [slJe [fk [+fk Jk[f gk[f [f1 [1f8", -" J1[f g1[f [kfM [f+kM fkV[ Vfg[k lf[ l+[f [lVf g[lf ke[2 [!ke2 [Dke2 [ake2 ", -"1e[5 [158e [15De [1a5e [kMe2 keM[!2 V[ke2 [akVe2 [5le [l58e [lV5e [sl5e ke[", -"; [+ke; [;Dke [a;ke 1e[; [1>e [1;De [>1De [;kMe ke;[+M V[;ke Vek[a; [5l* >e", -"[l [l;Ve V>[le [Gke2 ke2[!G Jk[e2 [aeJk2 [1G5e G5k[8e J1[5e J1e[5a keM[G2 k", -"e[!GM2 V[eJk2 akVe[J2 [lG5e [5Gle8 lJ[5e lJ5[se [;fk [f+k; [fJk; g[fk; [1f5", -" >k[f [f1J5 J>k[f [fkM; [+kfM; Vf[k; g[kVf; l;[f [>lf Vf5[l J>l[f ke[P keP[", -"! keDP [akeP 1e[P [18eP [1DeP [1aeP [kSe S[ke! SkVe SVeak S[le S[8le SVle [", -"slSe kP[* [+keP [*DkP [a*kP 1P[* [1+eP [1*DP [1aP* Sk[* S[+ke SVek* SV+ke S", -"[l* [l+Se [l*SV [s*Sl [kYe Yk[e! YeJk YJkae Ye[1 Y1[8e YJ1[e YJ8ke S[Yke Yk", -"[Se! ]ke ak]e [Yle lY[8e ]le ls]e Yk[f Yfk[+ JfYk gYk[f Y1[f [f1Y+ [f1YJ g[", -"1Yf fkS[ Sf[+k ]fk gf]k [lSf lYf[+ ]lf gl]f ke[m [mke! [mDke [amke 1e[m [1m", -"8e [1mDe [1aem S[kem [mkSe! SVekm SakVem le[p [pl8e [plVe [psle km[* [+mke ", -"[m*Dk [amk* 1m[* [>1em [1mD* >kDeP S[;ke S+k[m* SVek; S+kVem l*[p [p*l> [p*", -"Vl V>eSl Yk[em [meYk! YJkem YaeJkm Y1[5e Y1e[8m YJ5ke Y1e[5a Yk[Sem ke[mSY!", -" ke]m ]akem [plYe lY8[pe le]p ]lpse fk[v [vf+k [vJfk g[vfk f1[v [v1f> [v1Jf", -" J>kYf [vfSk Sf+[vk fv]k ]gfvk [plf fp[l> lf]p yl]f ht[ [&ht hD[t ht[c h1[ ", -"[:h hD[1 [ch: [thM ht[M& V[ht Vh[tc lh[ lh[: [lVh u[h t*[ [-t tD[* [ct- [1t", -"* [:- t*[1D :c[- tM[* [t-M V[t* V[t- t*[l l-[ lhV[* u[- [htG tG[h& [Jht tJ[", -"hc hG[1 [h:G [Jh1 hJ[: tG[hM [h&tGM tJV[h Vh[tJc [hlG [:lhG hJ[l hJu[ tf[ [", -"-tf [ftJ i[t h1[f :f[ [f1tJ i[: [tfM [-tfM V[tf V[it [ltf [:lf lJh[f ui[ h2", -"[t ht[&2 ht[D2 [cht2 [ht5 h5[: t5[hD [:hc5 ht[M2 hM&[t2 Vh[t2 [ctVh2 h5[l [", -":lh5 lhV[5 h5u[ [ht; t;[- t;[hD [-tc; [1h; [:h> t5[D* [:-c> t;[hM [-tM; Vh;", -"[t V-[t; h;[l [>l- lh;V[ h>u[ tG[h2 [h&tG2 tJ[h2 [chtJ2 tG5[h [:hG5 tJ5[h :", -"J[h5 [h2tGM hG[&tM2 Vh[tJ2 h2tJ[cV lh[G5 lhG[:5 lJh[5 uh5[J t;[f [-tf; tJ;[", -"f t;i[ t5[f [>tf tf5[J t>i[ tf[M; tfM[-; tfV[; iV[t; lh;[f l-[f> Vf5[t i[u>", -" htP h&tP hDtP tchP tPh1 hP[: htP1D [:hcP Sht S&ht VhSt htSc Shl Sh: SlVh u", -"hS t*hP hPt- tP*hD [-tcP tP*h1 :P[- tPD[1* [:-cP S*ht St[- St*Vh V-[St l*Sh", -" Shl- ShlV* Shu- tYh Y&ht tJhY htYc h1tY hY[: hY1tJ tY:hJ tYSh ShtY& ]ht ht", -"]c lYh Y:Sh ]lh ]uh tYf tY- YJtf itY Y1tf Y:tf tYfJ1 tYi: Sft tYS- ]tf ]it ", -"Shlf tYl- lf]h ui] tmhP tm[h& tm[hD [cmht t5hP hm[: t5PhD [:mhc hmSt Shtm& ", -"VhmSt Shctm tpSh S:hp hplSV hpu[ t;hP tm[- tm[D* [-mtc t5[m* ht>P t5Dh;P [:", -"-cm h;St [-mSt Sh;Vt V-[tm l;Sh S:h> [p*Vt h>uS hmtY tYhm& tJmhY tYchm h5tY", -" [:mhY tY5hJ [:mhJ ShtYm tYmSh& ht]m ]htcm hplY [p:hY hp]l ]puh tYhv Y-tv h", -"v[tJ tYiv h1[v tYh> [v1hJ tYi> tvSh [-vSt hv]t ]tiv hvlY h>lY lv]h ]yui n n", -"! nB an n. 8n n.B 8na nK n!K Tn Tna nj 8nj Tnj sn n( +n n(B +na n(. +n8 .Bn", -"( +8an n(K +nK Tn( +Tn nj( +nj T(nj sn+ nE n!E Hn Hna nE. 8nE Hn. H8n nEK E", -"Kn! HnT HTan njE 8Enj Hnj snH dn +nd Hnd gn dn. 8dn H.dn gn8 dnK +Kdn Tdn g", -"nT dnj dn+j dnHj gsn 4n 4n! 4nB 4an 5n 48n 5nB 5an 4nK n!4K 4Tn Tn4a 4jn 8n", -"4j 5Tn s4n ;n 4+n ;nB a;n 5n; >n 5B;n >na ;nK 4K+n T;n +n4T ;nj >nj T;5n >n", -"s 4nE n!4E 4Hn Hn4a 5nE 4E8n H5n Hn48 nE4K 4nE!K Hn4T 4HTan 4Enj njE48 Hn4j", -" 4Hsn 4dn +n4d H;n g4n 5dn >nd 5dHn >ng 4Kdn dnK4+ T;Hn 4Tgn dn4j dn>j Td5n", -" gs>n Pn n!P PnB aPn Pn. 8Pn n.PB aP8n Qn Qn! QnT Qan Qnj Q8n PjTn sPn Pn( ", -"+Pn n(PB aP+n n(P. 8P+n Pn(.B aPn+8 Qn( +Qn Q(Tn Qa+n Q(nj Q8+n Pj(Tn +Qsn ", -"Wn Wn! HPn Wan Wn. W8n H.Wn W8Hn WnQ Q!Wn Zn Zna Wnj Q8Wn Znj sZn Wnd +Wn d", -"PHn gPn W.dn W8+n dP.Hn W8gn Qdn Wn+Q Znd gZn dnWj Wn+j dnZj gnsZ o o! oB o", -"a o5 o8 o5B o8a oQ o!Q oT oTa op op8 opT os o; o+ o;B o+a o5; o> 5;oB o>a o", -"Q; o+Q oT; o+T op; o>p pTo; os> oW o!W oH oHa o5W o8W oH5 oH8 oWQ Q!oW oZ o", -"Za opW pWo8 oZp osZ ov ov+ ovH go ov5 o>v vHo5 go> ovQ v+oQ oZv goZ opv pvo", -"> opZv yo n# &n n#B an& n#. 8n& .Bn# 8a&n n#K &nK Tn# T&n nj# &nj T#nj sn& ", -"n#( +n& #Bn( +a&n #(n. +8&n n#(.B an&+8 #(nK +K&n n#T( T&+n j#n( &n+j nj#T(", -" +ns& n#E &nE Hn# H&n #En. 8E&n n#H. 8nH& EKn# nK&E H#Tn T&Hn j#nE &Enj H#n", -"j H&sn dn# d&n H#dn gn& n#d. d&8n dn#H. 8ng& n#dK dK&n T#dn T&gn d#nj &ndj ", -"dnjH# g&sn 4n# 4&n n#4B an4& 5n# 5&n n#5B an5& n#4K 4K&n 4#Tn Tn4& 4#nj &n4", -"j 5#Tn 4&sn ;n# ;&n nB;# ;&an 5#;n >n& ;n#5B an>& n#;K ;K&n T#;n ;&Tn ;#nj ", -"&n>j ;njT# >&sn n#4E 4E&n 4#Hn Hn4& n#5E 5E&n H#5n 5&Hn 4n#EK &nE4K 4HTn# 4", -"H&Tn nj#4E &nj4E 4Hjn# snH4& 4#dn dn4& H#;n 4&gn 5#dn d&>n H5nd# >&gn dn#4K", -" d&n4K 4Tdn# g4T&n dnj4# >nd&j ;njH# >ngs& Pn# P&n n#PB P&an n#P. P&8n Pn#.", -"B aP&8n Qn# Q&n Q#Tn T&Qn Q#nj 8nQ& Pj#Tn Q&sn n#P( P&+n Pn#(B aP&+n Pn#(. ", -"P&n+8 n#(P.B +P8an& n#Q( Q&+n QnT#( +QnT& Pj#n( P&j+n TP#nj( sP+&n Wn# W&n ", -"H#Wn W&Hn n#W. 8nW& HPn#. H8P&n W#Qn Q&Wn Zn# Z&n W#nj &nWj njZ# Z&sn W#dn ", -"W&+n dP#Hn W&gn dP#n. dP&8n HP#dn. gP8&n Q#dn d&Qn dnZ# Z&gn dPjn# dP&nj Zn", -"dj# Z&ngs o# o& o#B oa& o5# o8& 5Bo# 5ao& oQ# o&Q oT# oT& op# op& pTo# os& ", -"o;# o+& ;#oB a;o& 5;o# o>& o5;#B >&oa Q;o# +Qo& T;o# +To& p;o# p>o& opT;# o", -"&s> oW# o&W oH# oH& 5Wo# 5Wo& H5o# H5o& WQo# W&oQ oZ# oZ& pWo# oWp& Z#op Z&", -"os ov# ov& vHo# go& v5o# v>o& ovH5# o&g> vQo# oQv& Z#ov Z&go o#pv pvo& oZpv", -"# yo& nC n!C Dn Dna nC. 8nC Dn. D8n nCK CKn! DnT DTan njC 8Cnj Dnj snD nC( ", -"+nC Dn( +Dn C(n. +C8n n(D. D8+n CKn( nC+K D(Tn Dn+T jCn( +Cnj D(nj +Dsn nCE", -" !CnE HnD HDan CEn. nC8E H.Dn D8Hn EKnC n!CEK HDTn HnDTa jCnE njC8E DnHj Hn", -"sD dnC +Cdn Ddn gnD nCd. 8Cdn D.dn D8gn nCdK dnC+K TdDn DngT dCnj dnj+C dnD", -"j gDsn 4nC n!4C 4Dn Dn4a 5nC 4C8n 5Dn D85n nC4K 4nC!K Dn4T 4DTan 4Cnj njC48", -" Dn4j 4Dsn ;nC 4C+n D;n +n4D 5C;n >nC D;5n >nD nC;K ;nC+K T;Dn a;nDT ;Cnj n", -"j>C ;nDj >Dsn nC4E 4nC!E Hn4D 4HDan nC5E 48nCE 5DHn 4H8Dn 4nCEK n!C4EK 4HDT", -"n HnD4Ta njC4E 48CnjE 4HjDn snH4D 4Cdn dnC4+ D;Hn 4Dgn 5Cdn dn>C Dd5n >Dgn ", -"dnC4K 4+CdnK 4DdTn g4DTn dnj4C >ndjC dnj4D >ngsD PnC PCn! DPn aPDn nCP. Pn8", -"C PnD. 8PDn QnC n!QC QDn DnQa QCnj QC8n DjQn QDsn nCP( Pn+C PnD( DP+n PnC(.", -" +P8nC DPn(. +DP8n nCQ( +CQn Q(Dn QD+n PjCn( +Qn8C QDnj( sP+Dn WnC n!WC WDn", -" DnWa nCW. WC8n W.Dn D8Wn WCQn WnQ!C ZnD DnZa WCnj W8nQC DnZj sDZn WCdn +CW", -"n DdWn WDgn dPCn. +Wn8C WDnd. gPD8n QCdn +WnQC DdZn gDZn dPjnC +WnjC ZnDdj ", -"gZnsD oC o!C oD oDa o5C o8C oD5 oD8 oQC Q!oC oDQ QDoa opC p8oC opD osD o;C ", -"o+C oD; o+D 5;oC o>C 5Do; o>D Q;oC +QoC QDo; +QoD p;oC >Cop o;pD oDs> oWC W", -"!oC oHD WDoa 5WoC W8oC H5oD H8oD WQoC o!WQC oZD ZDoa pWoC opW8C oDZp oDsZ o", -"vC v+oC ovD goD v5oC >Cov o5vD oDg> vQoC ov+QC oDZv oDgZ oCpv o>pvC pvoD yo", -"D bn bn& bnD cn bn. b8n b.Dn cn8 bnK bK&n bTn cnT bnj 8nbj Dnbj scn bn( b+n", -" b(Dn cn+ n(b. +nb8 bnD(. +nc8 n(bK bK+n b(Tn +Tcn b(nj +nbj bTnj( s+cn bnE", -" bE&n bHn cnH nEb. bE8n b.Hn H8cn nEbK &nEbK HnbT HncT bEnj &njbE Hnbj sHcn", -" bdn +nbd Hnbd gcn b.dn 8dbn bHnd. g8cn bKdn d&nbK Tdbn gTcn dnbj d&nbj dnj", -"bH gnsc 4bn bn4& bn4D c4n b5n bn48 5Dbn c5n 4Kbn &nK4b bn4T 4Tcn bn4j &nj4b", -" 5Tbn c4sn b;n bn4+ D;bn c;n 5nb; >nb b5nD; c>n bK;n ;&nbK T;bn T;cn ;nbj b", -"n>j ;njbT sc>n 4Ebn &nE4b bn4H 4Hcn bE5n 4b8nE H5bn H5cn 4bnEK 4bE&nK 4bHTn", -" c4HTn 4bjnE &nE4bj 4bHnj c5nsH bn4d d&n4b H;bn c4gn 5dbn bd>n bH5dn gc>n 4", -"bdnK d&Kb;n 4bTdn c;ngT dnj4b >nbdj ;njbH c>ngs bPn P&bn DPbn cPn Pnb. 8Pbn", -" bPDn. 8Pcn bQn Q&bn QDbn cQn Qnbj Q8bn bQnDj cQsn Pnb( +Pbn bPDn( +Pcn bPn", -"(. b+P8n DP(bn. cP+8n b(Qn +Qbn bQnD( +Qcn bQnj( b+Q8n Pj(bTn cQns+ bWn W&b", -"n HPbn cWn b.Wn W8bn bHPn. W8cn WnbQ bWnQ& Zbn Zcn Wnbj &njbW bnZj snZc Wnb", -"d +Wbn bHPdn cWgn bWnd. b+W8n dP.bHn cWng8 Qdbn d&nbQ bdZn gnZc dPjbn b+Wnj", -" Zbndj Zcngs ob ob& obD oc ob5 ob8 b5oD oc5 obQ bQo& obT ocQ opb pbo8 pboD ", -"osc ob; ob+ b;oD oc+ b5o; o>b ob5D; oc> bQo; b+oQ bTo; o+cQ o;pb p>ob opbD;", -" c>os obW bWo& obH ocH b5oW bWo8 bHo5 oHc5 bWoQ obWQ& oZb ocZ oWpb opbW8 op", -"Zb Zcos ovb vbo+ vboH goc o5vb v>ob ovbH5 c>go oQvb ovb+Q ovZb Zcgo pvob o>", -"bpv oZbpv yoc 6n 6!n 6nB 6an 1n 68n 1nB 1an 6nK n!6K 6Tn Tn6a 6jn 8n6j 1Tn ", -"s6n 6n( 6+n n(6B +n6a 1n( 1+n n(1B +n1a n(6K 6K+n 6(Tn +n6T 6(nj +n6j 1(Tn ", -"6+sn 6nE n!6E 6Hn Hn6a 1nE 6E8n 1Hn H81n nE6K 6!nEK Hn6T 6HTan 6Enj njE68 H", -"n6j 6Hsn 6dn +n6d Hn6d g6n 1dn +n1d Hn1d g1n 6Kdn dnK6+ Tn6d 6Tgn dn6j dnj6", -"+ Td1n s6gn 46n 4n6! 6n4B 46an 7n 78n 7Bn 7an 6n4K 6!4nK 46Tn 4T6an 7nj 8n7", -"j 7Tn 7sn 6;n +n6; 6B;n an6; 7;n >n7 ;n7B 7a>n 6K;n ;nK6+ Tn6; a;n6T ;n7j 7", -"n>j T;7n >n7s 6n4E 6!4nE 46Hn 4H6an 7nE 8n7E 7Hn H87n 46nEK 4nE6!K 4H6Tn 6H", -"T4an nj7E 78njE Hn7T 7Hsn dn6; 4+6dn Hn6; 6;gn 7dn 7d>n H;7n g7n dnK6; 4+6d", -"nK 4Td6n g46Tn dn7j 7>dnj Td7n gn7s 6P 6P! 6PB 6aP 6P1 68P 6B1P 1a6P 6QP Q!", -"6P 6TP Qa6P 6Pj Q86P 1T6P s6P 6P( 6+P P(6B +P6a 6(1P 1+6P 6P1(B 6+P1a 6(Qn ", -"+Q6P 6(TP +T6P 6(Pj +Q1n 6TP1( 6+sP 6WP 6!Wn 6HP HP6a 1Wn W86P 1H6P H86P Wn", -"6Q 6WQn! Z6P 6aZn Wn6j 6W8Qn Z1n Z6sP 6dP +W6P HP6d g6P 1d6P +W1n 6HP1d 68g", -"P Qd6P 6+WQn 6dZn Z6gP Qd1n dPj6+ 1dZn s6gP o6 o!6 o6B oa6 7o 7o8 7oB 7oa o", -"6Q 6Qo! oT6 6Qoa 7op o87p 7oT os7 o6; o+6 6;oB 6+oa 7o; o>7 o;7B 7ao> 6Qo; ", -"6+oQ 6To; 6+oT 7;op 7po> 7;oT o>7s o6W 6Wo! oH6 6Hoa 7oW o87W 7oH oH7a 6WoQ", -" o!6WQ oZ6 oaZ6 op7W 7opW8 7Zo os7Z ov6 v6o+ v6oH go6 7vo o>7v ov7H go7 oQv", -"6 ov6+Q ovZ6 g6oZ op7v 7p>ov oZ7v yo7 9n 6&n 9nB 9an 9n1 :n 1B9n :na 9nK 6K", -"&n 9Tn T&9n 9nj :nj 1T9n s:n 9n( 9+n n(9B +n9a 9(1n :n+ 9n1(B +n:a n(9K 9K+", -"n 9(Tn +T9n 9(nj +n:j 9Tn1( s+:n 9nE 6E&n 9Hn H&9n 9E1n :nE 1H9n :Hn nE9K &", -"nE6K Hn9T 6H&Tn 9Enj nj:E Hn9j :Hsn 9dn +n9d Hn9d g9n 1d9n :dn 9Hn1d g:n 9K", -"dn d&n6K Td9n 9Tgn dn9j dn:j dnj9H gns: 49n 9n4& 4B9n 9n4a 79n 7:n 9n7B :n7", -"a 4K9n &nK49 9n4T 49Tan 9n7j 7j:n 9T7n 7:sn 9;n 9n4+ 9B;n a;9n 9;7n >n: 7B9", -";n :a>n 9K;n ;&n6K T;9n a;n9T ;n9j >j:n 7T9;n s:>n 4E9n &nE49 9n4H 49Han 9n", -"7E 7E:n 9H7n :n7H 49nEK 49E&nK 49HTn 9Hn4T& 79njE 7:njE 7H9Tn 7:Hsn 9n4d d&", -"n49 H;9n 49gn 9d7n :d>n 7H9dn >ng: 49dnK d&K9;n 49Tdn g49Tn 7d9nj 7:dnj 7Td", -"9n g:n7s 6P9 6P& 6B9P 9a6P 1P9n :P6 6P19B 6a:P 9Qn Q&6P 9T6P Qa9n 9P6j :Qn ", -"6TP9j :Qsn 6(9P 9+6P 6P9(B 6+P9a 6P19( 6+:P 1P(9nB :P6+a 9(Qn +Q9n 6TP9( 6+", -"T9P 6Pj9( +Q:n Pj(9Tn :Qns+ 9Wn W&6P 9H6P HP6& 1W9n :Wn 6HP91 6H:P Wn9Q 6W&", -"Qn Z9n 6PZ& Wn9j Wn:Q 9nZ1 Z:n 9d6P +W9n 6HP9d 6Pg9 6dP91 6d:P 1HP9dn :Wgn ", -"Qd9n dP&6Q 9dZn Z9gn dPj9n Qd:n Z9n1d gnZ: o9 o9& o9B o9a 7o9 o: 7Bo9 o:a o", -"9Q 6Qo& o9T 6To& op9 o:p o97T os: o9; o9+ 9;oB 9+oa 7;o9 o:> 7o9;B oa:> 9Qo", -"; 9+oQ 9To; 9+oT o;p9 o>:p 7oT9; s:o> o9W 6Wo& o9H 6Ho& o97W o:W o97H o:H 9", -"WoQ o9WQ& oZ9 o9Z& oWp9 op:W Z97o Z:o ov9 v6o& v9oH go9 o97v :vo 7oHv9 go: ", -"oQv9 ov9+Q ovZ9 g9oZ pvo9 op:v oZ97v yo: 6nC n!6C 6Dn Dn6a 1nC 6C8n 1Dn D81", -"n nC6K 6!nCK Dn6T 6DTan 6Cnj njC68 Dn6j 6Dsn nC6( 6C+n 6(Dn +n6D nC1( 1C+n ", -"1(Dn +D1n 6nC(K 6+nCK 6DTn( 6+DTn njC6( 6+jnC 6Djn( sn+6D nC6E 6!nCE Hn6D 6", -"HDan nC1E 68nCE Hn1D 6H8Dn 6nCEK n!C6EK 6HDTn HnD6Ta njC6E 68CnjE 6HjDn snH", -"6D 6Cdn dnC6+ Dn6d 6Dgn 1Cdn 68dnC Dd1n 1Dgn dnC6K 6+CdnK 6DdTn g6DTn dnj6C", -" dnC6+j dnj6D gs6Dn 6n4C 6!4nC 46Dn 4D6an 7nC 8n7C 7Dn D87n 46nCK 4nC6!K 4D", -"T6n 6DT4an nj7C 78njC Dn7T 7Dsn 6C;n ;nC6+ Dn6; a;n6D ;n7C 7n>C D;7n 7D>n ;", -"nC6K 6+C;nK 6D;Tn +Dn6T; ;nj7C 7>jnC 7DT;n 7s>Dn 46nCE 4nC6!E 4H6Dn 6HD4an ", -"nC7E 78nCE Hn7D 7HD8n 6nC4EK 4n6!EKC 6HD4Tn 46anHDT 7njCE njC78E 7HDTn 7sHD", -"n dnC6; 4+6dnC 4Dd6n g46Dn dn7C 7>dnC Dd7n 7Dgn 6dC;nK dn6;+CK Ddn6T; 6D;gn", -"T 7dnjC >nj7dC 7DdTn g7sDn 6PC PC6! 6DP DP6a 6C1P 6C8P 1D6P D86P 6CQn 6QP!C", -" QD6P 6QDaP 6CPj 6Q8PC QD1n 6DsP PC6( 6C+P 6(DP +D6P 6P1C( 6+P1C 6DP1( 6+D1", -"P 6QPC( 6+QPC 6QDP( 6+QDP 6PjC( 6+PjC 6DPj( s6P+D 6CWn 6WP!C HP6D 6HPDa 1CW", -"n 6W8PC WD1n 6H8DP 6WQPC WnC6Q! 6DZn Z6DaP 6WjPC PjC6W8 1DZn Z1nsD 6CdP 6+W", -"PC Dd6P 6DgP 6dP1C 68dPC 6Dd1P g6P1D 6QdPC dPC6+Q Z6DdP gZ6DP dPj6C dPC6+j ", -"Z1nDd Z1ngD o6C 6!oC oD6 6Doa 7oC 7Co8 7oD oD7a 6QoC o!6QC 6QoD oD6Qa 7Cop ", -"7op8C op7D 7Dos 6;oC 6+oC 6Do; 6+oD o;7C >C7o 7;oD 7Do> o6Q;C o+6QC oD6Q; o", -"+D6Q 7op;C 7p>oC 7oDp; os7>D 6WoC o!6WC 6HoD oH6Da oW7C 7oW8C oH7D 7oHD8 o6", -"WQC 6WQo!C oDZ6 oZ6Da 7opWC op87WC 7DoZ osZ7D oCv6 ov6+C v6oD oDg6 7Cov 7vo", -">C ov7D 7Dgo ov6QC v6Qo+C Zv6oD goZ6D 7vopC o>p7vC 7vDoZ 7oyD b6n 6&bn 9Dn ", -"c6n b1n :nb 1Dbn :cn bK9n &nKb6 6Tbn 6Tcn 6jbn bn:j 1Tbn :csn b(9n 6+bn 9(D", -"n 6+cn b(1n b+:n b1nD( :+cn b6n(K b6+nK b6Tn( c6+Tn b6jn( :nb+j b1Tn( :cns+", -" bE9n &nEb6 6Hbn 6Hcn bE1n bn:E 1Hbn cn:H b6nEK b6E&nK b6HTn c6HTn b6jnE :n", -"bjE b6Hnj :cnsH 6dbn d&nb6 Dd9n c6gn 1dbn bd:n b1Hdn :cgn b6dnK dnKb6+ b6Td", -"n gc6Tn dnjb6 :dnbj dnj9D g:nsc bn49 4b6&n 9n4D 49cn 7bn :n7b bn7D 7cn 4b6n", -"K 4b6&nK 4bT9n c46Tn bn7j 7:bnj bT7n sn7c 6;bn ;&nb6 D;9n 6;cn b;7n 7b>n 7b", -"D;n >n7c b6;nK ;nKb6+ b6T;n c6;Tn 7b;nj 7>bnj 7bT;n c>n7s 4b6nE 4b6&nE 4bH9", -"n c46Hn bn7E 7:bnE bH7n cn7H bnE49K 4Eb6&nK bHn49T 49HcnT 7bnjE :nj7bE 7bHT", -"n 7csHn 4bd9n b6d;&n 49Ddn c6;gn bd7n 7:dbn 7bHdn gn7c dnKb6; dn4&b6K bTn49", -"d c4Tg9n 7bdnj 7bj:dn 7bTdn g7csn b6P 6&bP 6DbP c6P 6Pb1 b6:P b6P1D c6:P 6Q", -"bP b6QP& 6TbP 6QcP 6Pbj bQ:n b6T1P c6sP b(6P 6+bP b6PD( 6+cP b6P1( :Pb6+ b6", -"(1DP :cP6+ b6QP( b6+Qn b6TP( c6Q+P b6Pj( :Qnb+ Pj(b6T :cQ+n 6WbP b6WP& 6HbP", -" 6HcP 1Wbn bW:n b6H1P cW:n b6WQn 6W&bQn b6Zn c6Zn b6WPj :WnbQ b1Zn :cZn 6db", -"P dP&b6 b6HdP c6gP b6d1P :Wnb+ 6HPb1d g:Pc6 b6QdP b6QdP& Zb6dP Zc6gP dPjb6 ", -":Qdbn Zb1dn Z:ngc ob6 b6o& o9D oc6 7ob o:b ob7D 7co b6oQ ob6Q& b6oT o9cQ op", -"7b ob:p ob7T os7c b6o; b6o+ 9Do; o9c; 7;ob 7bo> 7obD; c>o: ob6Q; ob+6Q obT6", -"; oc6+Q 7obp; o:p>b 7obT; os:c> b6oW ob6W& b6oH o9cW ob7W ob:W ob7H 7Hoc ob", -"6WQ b6Wo&Q obZ6 Z6oc 7obpW o:pbW 7boZ oc7Z vbo9 ovb6+ v9oD g6oc ov7b ob:v 7", -"vboH 7cgo ovb6Q obQv6& oZbv6 cv6oZ 7vbop :vopb 7Zbov 7cyo Rn Rn! RnB Ran Rn", -". R8n n.RB 8nRa Mn Mn! RTn aMn Rjn 8Mn TnRj sRn Rn( R+n n(RB +nRa n(R. +nR8", -" Rn(.B R+8an Mn( +Mn R(Tn +nRT R(nj +nRj Mn(Tj R+sn RnE n!RE RHn HnRa nER. ", -"RE8n R.Hn HnR8 MnE MEn! HMn aMHn REnj 8EMn HnRj RHsn Rdn +nRd HnRd gRn R.dn", -" 8nRd dn.RH R8gn dMn dM+n TnRd gMn dnRj dM8n dMnHj sRgn R4 R4! R4B R4a R45 ", -"R48 RB5n 48Ra R4M 4!Mn R4T 4TRa R4j 48Rj 4TR5 sR4 R4; R4+ RB;n 4+Ra 5nR; >n", -"R ;nBR5 R4>a M;n 4MR+ 4TR; 4+RT 4jR; >Mn M;n5T sR>n R4E 4!RE R4H 4HRa RE5n ", -"RE48 4HR5 4HR8 RE4M MnE4! 4HRT aMn4H RE4j R48ME 4HRj R4sH R4d 4+Rd 4HRd gR4", -" 4dR5 R4>d R4H5d gR>n 4MRd dMn4+ 4TRd R4gM 4dRj dM>n dMnH5 gM>n RPn n!RP Pn", -"RB RPan PnR. RP8n RPn.B aPnR8 Sn S!n STn San Snj S8n TnSj Ssn PnR( RP+n RPn", -"(B aPnR+ RPn(. R+8Pn Pn(R.B R+8aPn Sn( S+n TnS( +TSn njS( +nS8 STnj( S+sn R", -"Wn R!Wn HnRW WnRa R.Wn WnR8 RHWn. RH8Wn SWn WnS! SZn ZnSa WnSj W8Sn SjZn sn", -"SZ WnRd +nRW RHWdn RWgn dP.Rn R+W8n RHWdn. gRW8n Sdn +WSn ZnSd gSn dnSj 8dS", -"n SZdnj gnSs oR o!R oRB oaR oR5 o8R R5oB R5oa So So! SoT Soa Sop So8 oTSp o", -"sS oR; o+R R;oB R+oa R5o; o>R oR5;B >Roa So; So+ oTS; o+Sa opS; S>o SpTo; o", -"sS> oRW RWo! oHR RHoa R5oW RWo8 RHo5 RHo8 SoW o!SW oZS SaoZ SWop SWo8 SpoZ ", -"oZSs ovR vRo+ vRoH goR o5vR vRo> ovRH5 gRo> Svo ovS+ oZSv goS opSv o>Sv SZp", -"ov yoS Rn# R&n n#RB anR& n#R. 8nR& Rn#.B an&R8 Mn# M&n R#Tn TnR& R#nj M&8n ", -"Mn#Tj R&sn n#R( +nR& Rn#(B an&R+ Rn#(. R+8&n n#(R.B R+8an& n#M( M&+n Mn#T( ", -"aMn+& Mn#j( M&n+j RT#nj( sn+R& n#RE RE&n R#Hn HnR& Rn#E. &nER8 RHn#. RH8&n ", -"n#ME ME&n H#Mn M&Hn Mn#jE M&n8E RHjn# snHR& R#dn dnR& dn#RH R&gn dn#R. d&nR", -"8 RH#dn. gR8&n d#Mn M&dn dMnH# M&gn dMnj# dM&8n dM#Hnj gsR&n R4# R4& 4#RB 4", -"aR& R#5n 48R& R45#B R48a& R#4M 4MR& R#4T 4TR& R#4j 4&Rj R4T5# R4s& R#;n 4+R", -"& ;n#RB a;nR& ;n#R5 R4>& R5#;nB >nRa& M#;n ;&Mn M;nT# aM;&n M;n5# M&>n M;#5", -"Tn >Mns& 4#RE RE4& R#4H 4HR& R45#E R48&E R4H5# R4H5& Mn#4E M&n4E R4HT# M&n4", -"H R4j#E M&n5E R4Hj# sR4H& R#4d 4dR& R4Hd# R4g& R4d5# >nRd& dn#RH5 >ngR& dMn", -"4# dM&R4 M;nH# gR4T& dMn5# >Mnd& dM#H5n >Mg&n PnR# RP&n RPn#B aP&Rn RPn#. P", -"&nR8 Pn#R.B R8aP&n Sn# S&n TnS# T&Sn njS# 8nS& STnj# S&sn RPn#( P&nR+ Pn#R(", -"B R+aP&n Pn#R(. R+8P&n .BR(Pn# aP8nR+& n#S( +nS& STn#( S+T&n Snj#( S+8&n nj", -"#ST( Ss+&n R#Wn WnR& RHWn# RH&Wn RWn#. RW8&n Hn#RW. H8nRW& WnS# W&Sn S#Zn Z", -"nS& SWnj# S8W&n SZnj# SZ&sn dP#Rn dP&Rn RHWdn# gRW&n RW#dn. RW8d&n dPHnR#. ", -"RW8gn& dnS# d&Sn SZdn# S&gn Sdnj# S8d&n ZnjSd# gSs&n oR# o&R R#oB Rao& R5o#", -" R5o& oR5#B o8Ra& So# So& S#oT oTS& S#op opS& SpTo# S&os R;o# R+o& oR;#B o+", -"Ra& oR5;# >Ro& R5;o#B o>Ra& o;S# o+S& S;To# Sa;o& Sp;o# S&o> opTS;# os>S& R", -"Wo# RWo& RHo# RHo& oR5W# o8RW& oHR5# oH8R& oWS# SWo& S#oZ S&oZ SpWo# Sp&oW ", -"SZpo# osZS& o#vR vRo& ovRH# o&gR ovR5# o>vR& vR5oH# go>R& S#ov ovS& SvoZ# S", -"&go Svop# Sv&o> oZpSv# Soy& Un Un! RDn Uan Un. U8n R.Dn D8Un UnM U!Mn Vn Vn", -"a Unj 8MUn Vnj snV Un( U+n R(Dn +DUn n(U. +nU8 RDn(. R+D8n U(Mn +MUn Vn( V+", -"n U(nj +nUj njV( V+sn UnE n!UE UHn HnUa nEU. UE8n U.Hn H8Un UEMn MnEU! VnH ", -"HnVa UEnj U8nME HnVj sHVn Udn +nUd HnUd gUn U.dn 8dUn RDdn. U8gn dMUn dMnU+", -" Vdn gVn dnUj dMnU8 dnVj sngV R4U 4!Un R4D 4URa U5n 4UR8 4DR5 4DR8 Un4M Mn!", -"4U V4R R4Va 4URj R48Uj V5n V4sR U;n 4UR+ 4DR; 4+RD 5nU; >nU R4D5; R4>D M;Un", -" M;nU+ V;n R4V+ ;nUj Un>M 5nV; V>n RE4U R4U!E 4URH R4HUa UE5n R48UE H5Un R4", -"HU8 MnE4U 4UEMn! R4VH V4RHa R4jUE MnE4U8 H5Vn snV4H 4URd R4+Ud 4DRd R4gU 5d", -"Un Ud>n R4D5d gU>n dMn4U 4U+dMn R4Vd V4gR dMnU5 >MnUd 5dVn >ngV UPn n!UP DP", -"Un aPUn PnU. 8PUn RDPn. RD8Pn SUn UnS! SVn VnSa UnSj U8Sn SjVn snSV PnU( +P", -"Un RDPn( R+DPn UPn(. U+P8n DP(Un. +DPU8n UnS( U+Sn S(Vn VnS+ SUnj( S+U8n SV", -"nj( SV+sn UWn U!Wn HPUn WaUn U.Wn W8Un RWDn. RWD8n UWSn S!UWn ZnV ZaVn WnUj", -" S8UWn ZjVn VZsn WnUd +WUn RWDdn UWgn UWnd. U+W8n dP.UHn gUP8n UdSn S+UWn V", -"dZn SVgn SdUnj S8dUn SVdnj gVnSs oU oU! oUD oUa oU5 oU8 R5oD RDo8 SoU S!oU ", -"oV oVa opU oUS8 oVp oVs oU; oU+ RDo; R+oD U5o; o>U oU5D; >RoD oUS; oUS+ oV;", -" oV+ o;pU oUS> V;op oV> oUW UWo! oUH UHoa U5oW UWo8 UHo5 UHo8 SWoU oUWS! oV", -"Z VZoa oWpU opUW8 VpoZ sZoV ovU vUo+ vRoD goU o5vU v>oU ovUH5 gUo> oUSv Svo", -"U+ oVv goV pvoU o>USv opVv yoV Rbn U&n bnRD cRn R.bn bnR8 RbDn. R8cn bMn M&", -"bn Vnb cnV bnRj 8Mbn bnVj cRsn R(bn bnR+ RbDn( R+cn Rbn(. Rb+8n bn(RD. cR+8", -"n b(Mn +Mbn bnV( V+cn Rbjn( &njU+ Vnbj( snVc+ REbn UE&n bnRH RHcn RbnE. Rb8", -"nE RbHn. cRH8n bEMn M&nbE bHVn cHVn RbjnE &njUE VnbHj snVcH bnRd d&Un RbHdn", -" cRgn Rbdn. d&nU8 dn.RbH gcR8n dMbn dM&bn bdVn cngV dMnbj dMnb8 Vdnbj gVnsc", -" R4b 4bR& 4bRD cR4 4bR5 4bR8 R4b5D R4c5 4MRb M&n4b R4Vb V4cR 4bRj M&nb5 b5V", -"n cRs4 4bR; 4bR+ R4bD; R4c; R4b5; R4>b b5nRD; cR>n M;bn M;&bn b;Vn V;cn M;n", -"b5 bM>n V5nb; cnV> RE4b R4b&E 4bRH R4cH R4b5E R4b8E R4bH5 cR4H5 R4bME M&ER4", -"b V4RbH cR4VH R4bjE M&Eb5n V5nbH cR4sH 4bRd d&n4U R4bH; cRg4 R4b5d >nbRd 4b", -"HR5d c>Rg4 dMn4b R4bdM& V4dRb gV4cR dMnb5 >Mbdn V5dbn V>ngc UPbn P&Un RbDPn", -" UPcn RbPn. Rb8Pn bPnRD. cR8Pn Sbn bnS& VnSb Scn bnSj b8Sn SVbnj snSc RbPn(", -" Rb+Pn bPnRD( cR+Pn UP(bn. U+Pb8n R(bPDn. U+Pcn8 bnS( b+Sn SVbn( cnS+ Sbnj(", -" Sb+8n VnjSb( Scs+n bnRW W&Un RbHWn RWcn RbWn. RbW8n Rb.WDn cRW8n bWSn SbW&", -"n ZnSb ZnSc SbWnj Sb8Wn SZbnj ZcnSs RbWdn dP&Un bWnRDd cRWgn dn.RbW b+nRW8 ", -"R.bHWnd cW8gUn bdSn Sb+Wn SZbdn gnSc Sbdnj Sb8dn SbjVdn gScsn obR oU& RboD ", -"ocR Rbo5 Rbo8 obR5D oUc5 Sob obS& oVb Sco opSb obS8 obVp osSc Rbo; Rbo+ obR", -"D; oUc; obR5; >Rob Rb5oD; cRo> obS; obS+ V;ob S+oc Spbo; Sbo> oVpb; ocS> Rb", -"oW UWo& RboH oUcW obR5W ob8RW obHR5 ocRH5 SWob oU&SW SboZ ZcoV SpboW Sb8oW ", -"oVZpb oVsZc vRob vUo& ovbRH gRoc ovbR5 o>bvR ob5vRD cvRo> ovSb Svbo+ obVv S", -"cgo Svbop S>bov oVvpb Scyo q q! qB qa q1 q8 q1B q8a qM q!M qT qTa lq q8l qT", -"l sq q( q+ q(B q+a q1( q+1 1(qB 1+qa qM( q+M qT( q+T lq( l+q l(qT sq+ qE q!", -"E qH qHa q1E q8E qH1 qH8 qME MEq! qHT HMqa lqE lEq8 lHq sqH qd q+d qHd gq q", -"d1 q8d 1Hqd gq1 qdM +Mqd qTd gqT ldq q+ld qHld glq q4 q!4 q4B qa4 7q 7q8 7q", -"B 7qa q4M 4Mq! qT4 4Tqa 7lq q87l 7qT sq7 q; q+4 q;B qa; 7q; q> 7Bq; q>a q;M", -" 4+qM qT; 4+qT l;q q>l qTl; sq> q4E 4Eq! qH4 4Hqa 7qE 7Eq8 7qH qH7a 4MqE q!", -"4ME 4HqT qH4aM lE7q 7lq8E 7qlH 7Hsq qd4 4+qd qH; gq4 7qd q>d qH7d gq7 4dqM ", -"q+4dM 4Tqd qTg4 7qld ldq> qHl; sqg7 qP q!P qPB qaP q1P q8P 1PqB 1aqP Sq Sq!", -" SqT Sqa Slq Sq8 qTSl sqS qP( q+P P(qB +Pqa 1Pq( 1+qP q1P(B q+1aP Sq( Sq+ S", -"(qT q+Sa l(Sq Sql+ SlqT( S+sq qW qW! qHW qWa qW1 qW8 1HqW 1Wqa SqW S!qW Zq ", -"Zqa lWq qWS8 Zql sqZ qWd q+W HPqd gqW 1Wqd 1+qW qH1dP qWg1 Sqd q+Sd Zqd gqZ", -" Sqld q+lW ldZq sqgS oq oq! oqB oqa 7oq oq8 7Boq oq7a Soq S!oq oqT oqSa r r", -"8 rT rs oq; oq+ oBq; q+oa q;7o q>o 7oq;B oaq> Sq; oqS+ qTS; q+oT r; r> r;T ", -"rs> oqW o!qW oqH qHoa 7qW qWo8 oq7H qHo8 qWSo SqWo! Zqo oaZq rW rW8 rZ rZs ", -"vq vq+ vqH goq vq7 vq> 7Hvq vqg7 vqS S+vq Zqv Zqgo rv rv> rZv yr q9 q& q9B ", -"qa9 q91 :q 91qB :qa q9M q&M qT9 qT& lq9 :ql l9qT sq: q9( q+9 9(qB 9+qa 91q(", -" :q+ q91(B :+qa 9Mq( 9+qM 9Tq( 9+qT q9l( l+:q qTl9( q+s: q9E q&E qH9 qH& 91", -"qE :qE 9Hq1 :qH 9MqE M&qE 9HqT HMq& q9lE lE:q l9qH lH:q qd9 qd& 9Hqd gq9 9d", -"q1 :qd qH91d gq: 9dqM dMq& 9Tqd qTg9 l9qd ld:q lHq9d g:sq q49 q&4 49qB 49qa", -" 7q9 :q7 q97B 7a:q 49qM 4Mq& 49qT 4Tq& l97q 7l:q 79qT :q7s q;9 q;& 9;qB 9aq", -"; 79q; q>: 7q9;B qa:> 9Mq; M;q& 9Tq; T;q& l9q; :ql> 7qT9; s:q> 49qE 4&qE 49", -"qH 4Hq& q97E 7E:q 79qH 7H:q q49ME q&4ME qH49T qH&4T 7lq9E :ql7E 7qHl9 :qH7s", -" 49qd 4dq& 9Hq; q;g9 79qd 7d:q 7qH9d g:q> qd49M qd&4M qH;9T gq49T 7qdl9 q>l", -":d 7qT9d glq7: q9P q&P 9PqB 9aqP 9Pq1 :qP q91PB qa:P Sq9 Sq& qTS9 qTS& lqS9", -" S:q Slq9T S:sq 9Pq( 9+qP q9P(B q+9aP q91P( q+:P 9P1q(B :q+aP q9S( q+S9 Sq9", -"T( Sq+9T Slq9( S+:q qTlS9( sq:S+ qW9 qW& 9HqW 9Wqa 9Wq1 :qW qH91W qH:W qWS9", -" qWS& Zq9 Zq& l9qW lW:q lqZ9 Zq: 9Wqd 9+qW qH9dP qWg9 qW19d q+:W 9HPqd1 gP:", -"q qdS9 qdS& qdZ9 g9Zq Sqdl9 Sd:q Zql9d S:gq oq9 oq& q9oB qao9 o97q o:q 7oq9", -"B oa:q So9 oqS& oTS9 o9Sa r9 r: r9T rs: q;o9 q+o9 oq9;B oq+9a 7oq9; q>o: o9", -";7qB o:q>a o9S; o9S+ Sq;9T Sqa9; r;9 r:> 9Tr; s:r> qWo9 qWo& qHo9 qHo& 79qW", -" 7W:q 7oHq9 oq:H SWo9 Sq&oW S9oZ oqZ& r9W r:W rZ9 rZ: vq9 vq& qHv9 g9vq v97", -"q :vq vq79H :vgq S9vq S&vq Z9vq Sog9 rv9 r:v Zvr9 yr: qU q!U qD qDa q1U q8U", -" qD1 qD8 qUM U!qM Vq Vqa lqU lUq8 Vql sqV qU( q+U qD( q+D 1Uq( 1Uq+ 1Dq( 1+", -"qD UMq( U+qM Vq( Vq+ qUl( lUq+ l(Vq l+Vq qUE U!qE qHU UHqa 1UqE U8qE 1UqH U", -"Hq8 UMqE q!UME VqH VHqa qUlE q8lUE lHVq qHVs qdU U+qd qDd gqU 1Uqd U8qd 1Dq", -"d qDg1 UdqM q+UdM Vqd gqV lUqd l+qUd ldVq gVsq q4U 4Uq! qD4 4Uqa 7qU q87U 7", -"qD qD7a 4UqM q!4UM Vq4 qaV4 lq7U 7lqU8 7Vq 7Vsq q;U 4Uq+ qD; 4+qD q;7U q>U ", -"q;7D q>D U;qM q+4UM Vq; q+V4 lUq; lq>U l;Vq V>q 4UqE q!4UE 4UqH qH4Ua qU7E ", -"7qU8E qH7U 7qHU8 q4UME 4UMq!E qHV4 Vq4Ha 7lqUE q8l7UE 7HVq sq7VH 4Uqd q+4Ud", -" 4Dqd qDg4 qd7U >Uqd qD7d gUq> qd4UM 4U+qdM qHV; g4Vq 7qdlU q>lUd 7dVq 7Vgq", -" qUP UPq! qDP UaqP 1UqP U8qP 1DqP D8qP SqU q!SU VqS SaVq lUSq SUq8 SlVq VqS", -"s UPq( U+qP DPq( +DqP q1UP( q+1UP qD1P( q+D1P qUS( SUq+ S(Vq S+Vq SlqU( Sq+", -"lU SlVq( Vq+Ss qWU UWq! qWD UWqa 1UqW UWq8 1WqD WDq8 SUqW SqUW! ZqV qaVZ lU", -"qW Sq8UW lZVq sZVq UWqd U+qW WDqd qWgU qW1Ud q+W1U qWD1d gq1UW SUqd Sq+UW S", -"dVq gVZq SqdlU Sq8Ud VqdlZ glqSV oqU q!oU oqD qDoa 7oU o87U oq7D oU7a oUSq ", -"SqUo! oVq oaVq rU rU8 rV rVs q;oU q+oU q;oD q+oD 7;oU 7Uo> 7oUD; oDq> SUq; ", -"Sq+oU S;Vq o+Vq r;U r>U rV; rV> qWoU oqUW! qHoU oqHUa oU7W 7oUW8 oU7H 7oUH8", -" SqUoW oUWSq! oVZq oVZqa rUW UWr8 rZV sZrV vqU q+vU vqD gUvq 7Uvq vUq> 7Dvq", -" 7ogU vUSq vqSU+ Vvq oVgq rvU v>rU rVv yrV tq tq& tqD cq tq1 :qt t1qD cq: t", -"qM tMq& Vqt cqV ltq lt:q ltVq uq tq( tq+ t(qD cq+ q1t( t+:q tq1D( q+:c qMt(", -" tMq+ t(Vq t+Vq l(tq tql+ Vqlt( uq+ tqE tEq& tqH cqH q1tE tE:q t1qH tH:q qM", -"tE tqM&E tHVq qHVc lEtq :qltE tqlH uqH tqd q+td qHtd gqt t1qd td:q tqH1d g:", -"cq tMqd tq+dM tdVq gVcq tqld :qdlt Vqdlt uqg tq4 q&t4 qDt4 cq4 7tq :q7t 7Dt", -"q 7cq q4tM tq4M& t4Vq c4Vq 7ltq 7tl:q Vq7t uq7 tq; q+t4 qDt; cq; 7qt; t>q t", -"q;7D cq> tMq; tq+4M t;Vq c;Vq tql; ltq> Vq;7t uq> q4tE tq4&E qHt4 qHc4 tE7q", -" 7tq:E 7qtH 7Hcq tq4ME q&Mt4E tqHV4 cqV4H 7tlqE :ql7tE 7tHVq 7quH qdt4 tq+4", -"d qHt; g4cq 7qtd tdq> 7tHqd t>gq tqd4M t4Mqd& Vqdt4 cq;gV 7tdlq t>qld 7Vdtq", -" gqu7 tqP q&tP qDtP cqP q1tP tP:q tq1DP :Pcq Stq S&tq VqSt Scq Sqlt :qSt Sl", -"Vtq uqS qPt( q+tP tqDP( q+cP tq1P( tq+:P qD1tP( cq:+P S(tq tqS+ StqV( S+cq ", -"Stlq( St+:q VqlSt( Squ+ tqW q&tW qHtW cqW t1qW tW:q tqH1W :Wcq tWSq Sq&tW t", -"Zq Zqc tqlW :qWSt ltZq uZq qWtd q+tW tqHdP gPcq tqW1d :qWt+ tW1qDd cqWg: Sd", -"tq St+qW tdZq Scgq Stdlq S:dtq tZqld gquZ ot ot& otD otc ot7 ot: 7Dot ot7c ", -"otS S&ot oVt otSc rt rt: rVt ur ot; ot+ oDt; t+oc 7ot; t>o ot7D; oct> S;ot ", -"S+ot t;oV S;cq rt; rt> t;rV ur> otW o&tW otH tHoc 7otW tWo: 7otH tHo: tWSo ", -"otSW& tZo octZ rtW t:rW rZt urZ tvo t+vq tHvq got 7tvq ot:v otH7v t>go Stvq", -" ot+Sv Zqtv tZgo rtv tvr: tZrv ury n= 5n=B =a>n =nK", -" +n=K =Tn +T=n =jn =j>n 5T=n s=n n H5=n >ng= dn=K =+dnK Hn=T gn=T dn=j >n=dj Hn=j gns=

        = o5=B =ao> =Qo o+=Q =To o+=T p=o p=o> op=T s=o oW< Wo= =5oH o>g= ov=Q ov=+Q Z=o Z=go ovp= o>pv= p=oZ yo= ,n ,n& ,nB ,an ,", -"n. ,8n n.,B 8n,a ,nK ,K&n ,Tn T&,n ,nj 8n,j Tn,j sn, ,n* -n *B,n -na ,.n* -", -"n8 n*.,B 8n-a ,Kn* -nK T*,n -Tn n*,j -nj n*j,T s-n ,nE ,E&n ,Hn H&,n nE,. ,", -"E8n ,.Hn H8,n nE,K <&EnK Hn,T ,HnT& ,Enj <&jnE Hn,j ,Hsn ,dn -nd Hn,d g-n ,", -".dn 8d-n ,Hnd. g8-n ,Kdn dn-K Td,n -Tgn dn,j dn-j dnj,H gns- ,4n 4&,n 4B,n ", -"4a,n ,5n 48,n ,B5n 5a,n 4n,K <&K4n 4T,n ,4Tan 4j,n <&j5n 5T,n ,4sn =n, -=n ", -",n=B -n=a ,5=n >n- =B5,n -a>n ,n=K =K-n ,T=n -n=T ,n=j -n=j =T5,n >ns- 4n,E", -" <&E4n 4H,n ,4Han ,E5n ,48nE H5,n ,4H8n ,4nEK ,4E&nK ,4HTn 4H&,Tn ,4jnE n =H5,n g->n =dn,K -=dnK =HT,n ", -"g=-Tn =jd,n >n-dj =Hj,n s-ng= ,P< o=5,B ->oa o,=Q o-Q o,=T o-T o,p= o-p p=o,T os- o,W ,Wo& oH, ,Hoa ,", -"5oW ,Wo8 ,Ho5 ,Ho8 ,WoQ o&W,Q oZ, oaZ, oWp, op&,W opZ, s,oZ ov, o-v o,=H go", -"- o5v, -vo> ov,H5 g-o> oQv, -Qov ovZ, Z-o pvo, op-v oZ,p= yo- C 5D=n =D>n nC=K =+nCK Dn=T =D+Tn nj=C >n=jC Dn=j sn=D 4n=dC =H5Dn g=>Dn =d", -"nCK dnC=+K =HDTn g=DTn =jdnC =jd>nC =HjDn s=gDn Co= =5oD =Do", -"> oQ=C o=+QC oD=Q o+D=Q =Cop o>p=C op=D =Dos Wv=C ovD=5 go>=D ov=QC =Qvo+C =DoZ goZ=D p=ovC p=vo>C p=D", -"oZ =Dyo ,nb <&bn ,Dn cn =b5Dn >nc= bn=K =b-nK bT=n cn=T bn=j >n-bj =bT5n snc", -"= ,4bnE ,4b&nE ,4Hbn c4H,n ,5nbE <&Eb5n ,H5bn c5n-bd =bH5n c", -"=g>n =bdnK -nd=bK =bHTn c=gTn =bjdn >nd=bj =bHnj s=cgn b

        =bo5D", -" c>o- ob=Q -Qob ob=T =Qoc op=b ob-p p=boD ocs= ,Wob obW<& ,Hob oHc< ob5,W o", -"b8,W obH,5 ocH,5 obW,Q bWb ovD,5 cv=o> ovb=Q o-vbQ =boZ ocZ- p=bov o-pvb Z=bop o", -"cy- 6n =n7B =n7a 6n=K =6+nK 6T=n =T6+n 7n=j 7>=nj =n7T 7=sn 46", -"=dn =n7H 7=gn =6dnK d", -"nK=6+ =H6Tn g=6Tn 7=dnj >n=7dj 7Td=n g7s=n 6P< 6!

        =B7o 7o=a o6=Q o=6+Q =6o", -"T o+T=6 7op= 7o=p> 7o=T 7os= 6Wo< o!6W< 6Ho< oH6a< oW7< 7oW8< 7 7o=H 7og= ov=6Q =Qvo+6 o=Z6 goZ=6 7o=pv o>p7v= 7oZ= 7oy= ?n ?&n ?Bn ?an ", -"?1n ?:n 1n?B :n?a ?nK &n?K ?Tn T&?n ?jn :n?j 1T?n s?n ?n* ?-n n*?B -n?a 1n?", -"* :-n ?B1n* :a-n n*?K ?K-n Tn?* -n?T n*?j -n?j ?T1n* ?-sn ?nE &n?E ?Hn H&?n", -" 1n?E ?E:n 1H?n :n?H nE?K ?&nEK Hn?T ?HTan nj?E ?:njE Hn?j ?Hsn ?dn -n?d Hn", -"?d g?n 1d?n :n?d ?H1dn ?:gn dn?K ?-dnK Td?n ?Tgn dn?j ?:dnj ?Hjdn gns? ?4n ", -"4&?n 4n?B 4a?n 7?n :n7? ?n7B ?n7a 4n?K ?4&nK 4T?n ?T4an 7n?j ?:7nj ?n7T 7?s", -"n ?=n -n?= ?B=n =n?a =n7? An ?=7nB Aan ?n=K ?-=nK =n?T ?-T=n =n?j Ajn ?T7=n", -" Asn 4n?E ?4&nE 4H?n ?H4an 7n?E ?:7nE ?n7H ?:H7n ?4nEK &nE?4K ?H4Tn 4H&?Tn ", -"?j7nE 7:n?jE ?H7Tn s?7Hn =n?d ?-=dn =n?H ?=gn ?n7d Adn ?H7=n Agn ?=dnK -=n?", -"dK ?Td=n g?=Tn ?d7nj dnAj ?Hj=n gsAn ?P ?P& ?PB ?aP ?P1 ?:P 1P?B :P?a ?QP Q", -"&?P ?TP Qa?P ?Pj :Q?P 1T?P s?P ?P* ?-P P*?B -P?a 1P?* :-?P ?P1*B ?:P-a Qn?*", -" -Q?P TP?* -T?P P*?j -Q:n ?TP1* ?-sP ?WP W&?P ?HP HP?a 1W?P :W?P 1H?P :H?P ", -"Wn?Q ?WQP& ?ZP Z&?P Wn?j ?:WQn Z1?P sP?Z ?dP -W?P HP?d g?P 1d?P :d?P ?HP1d ", -"?:gP Qd?P ?-WQn Zn?d gP?Z dP?j ?:QdP ?Z1dP gPs? o? o?& o?B o?a o?7 o:? 7Bo?", -" ?ao: o?Q o&?Q o?T oT?a ?po o:?p 7o?T s?o o?= o-? =Bo? =ao? 7o?= Ao 7o=?B A", -"oa =Qo? ?Qo- =To? ?To- p=o? Aop o?Tp= Aos o?W o&?W o?H oH?a 7o?W ?Wo: 7o?H ", -"?Ho: oW?Q o?WQ& ?Zo ?aoZ op?W o:?pW o?7Z os?Z ?vo o-?v =Ho? go? o?7v Aov o?", -"H7v Aog ov?Q o-?vQ o?Z= ?Zgo op?v opAv ?Zo7v yAo =nC =n7D 7", -">D=n =6nCK 6+n=CK =D6Tn 6+D=Tn 7=njC >nj7=C =D7Tn s=7Dn 6n=7dC 7Dd=n g7=Dn ", -"dnC=6K dn=C6+K 6Dd=Tn g6D=Tn =jn7dC >j7d=nC 7Hn=Dj s=Dg7n 6C

        C 7o=D o>D", -"7= o=6QC =Q6o+C =QDo6 o+6=QD 7o=pC p=7o>C p=D7o s=o7D o6W=7vC 7vDo= go7=D =Q6ovC =6o+vQ", -"C Z=o6D Z=6goD p=o7vC >C7vp=o 7Z=oD yo7=D ?bn bn?& ?Dn ?cn b1?n ?b:n 1D?n :", -"n?c bn?K ?b&nK bT?n cn?T bn?j ?:bnj Dn?j sn?c bn?* ?b-n Dn?* cn?- 1nb* :b-n", -" ?D1n* c-:n ?bn*K ?-bnK ?DTn* ?-Tcn ?jbn* ?-jbn ?Djn* s-n?c bn?E ?b&nE bH?n", -" cn?H ?b1nE ?:bnE ?Hb1n ?:Hcn ?bnEK &nE?bK ?HbTn ?cHTn ?jbnE :nb?jE ?Hjbn s", -"?cHn bd?n ?-bdn Dd?n gn?c ?d1bn ?:dbn ?Dd1n g:n?c ?dbnK -nb?dK ?DdTn g?cTn ", -"?djbn ?db-nj ?Ddnj g?scn 4b?n ?4b&n 4D?n ?4cn ?n7b ?:7bn ?n7D cn7? ?4bnK &n", -"K?4b ?D4Tn ?c4Tn ?j7bn 7:b?jn ?D7Tn s?7cn ?b=n ?-=bn =n?D cn?= =n7b Abn ?D7", -"=n Acn ?=nbK =bn?-K =bT?n c=?Tn =b7nj bnAj ?Dj=n scAn ?4bnE &nE?4b ?H4bn ?c", -"4Hn 7?bnE 7bn?:E ?H7bn 7c?Hn 4bn?EK &n?E4bK 4bH?Tn c4H?Tn 7bn?jE 7j?E:nb ?H", -"n7bT 7cHs?n ?=dbn =b-?dn ?Dd=n c=?gn ?d7bn bdAn ?D7dn gcAn =bn?dK =d-n?bK ?", -"Hn=bT g?Tc=n ?dn=bj Adnbj ?Hn=bj Agnsc ?Pb bP?& ?DP ?cP b1?P ?b:P 1D?P :c?P", -" bQ?P ?QbP& bT?P cQ?P bP?j ?:QbP DP?j sP?c bP?* ?b-P DP?* c-?P ?Pb1* ?:P-b ", -"?DP1* ?cP:- ?QbP* ?-QbP ?QDP* ?cQ-P ?Pjb* ?-Pbj ?DP*j s?Pc- bW?P ?WbP& bH?P", -" cW?P ?Wb1P ?:WbP ?HPb1 ?cW:P ?WbQn bWn?Q& Zb?P ?PZc ?WjbP ?Wb:Qn ?Zb1P s?Z", -"cP bd?P ?-WbP Dd?P gP?c ?dPb1 ?:dbP ?Dd1P g?P:c ?QdbP ?Wb-Qn ?ZbdP g?ZcP ?d", -"Pbj ?Wb-Pj ?DdPj g?scP o?b ?bo& o?D oc? 7bo? ob?: 7o?D ?co: ob?Q o?bQ& ob?T", -" ?Qoc ob?p o:?pb op?D ocs? =bo? ob?- =Do? ?co- 7o=b Aob o?D7= Aoc o?=bQ o-?", -"bQ o?D=Q oc?=Q p=bo? opAb ?pDo= osAc ob?W o?bW& ob?H ?Hoc ?W7ob o:?bW o?H7b", -" o:H?c o?bWQ obW?Q& ?DoZ oc?Z ?pobW ?pbo:W ?Zo7b s?oZc ob?v o-?vb ov?D ocg?", -" 7vbo? ovAb ?vD7o goAc ?vobQ ?vbo-Q ?Zo=b go?Zc ?pvob Aopvb ?pvoD yoAc R< R", -" R5=B >R=a =RM R+=M =RT R+=T =Rj =R>M R", -"5=T s=R 4R RH=5 g>=R Rd=M =R+dM", -" RH=T gR=T Rd=j >M=Rd RH=j gs=R R

        o=5RB o>=Ra S= S=+ S=T S=a S=p S>= Sp=T s=S RWo< o!RW< RHo< o", -"HRa< 5WR< o8RW< oHR5< oH8R< oWS< S=R =RvH5 g=Ro> S=v v=S+ S=Z gS= p=Sv v>S= SZp= y=S ,", -"R< R<& RB,n Ra,n ,.R< R8,n ,R<.B ,R8a< ,Mn =R =R5,B >n-Ra ,R=M -R=M ,R=T -R=T ,R=j -R=j =RT,5 =Rs- ,ER4 ,R4&E ", -"R4,H ,R4H& ,R45E ,R48E ,R4H5 ,R4H8 ,R4ME n-Rd =RH,5 g=R-> =Rd,M =R-dM =RH,T g=", -"R-T =Rj,d >M-dn =RH,j s=Rg- R<,P o,5=RB o->Ra ", -"S=, S-o S,=T =TS- S,p= o-S> S=p,T S-s= ,RoW o&R,W ,RoH oH&,R o,R5W o8,RW oH", -",R5 oH8,R SWo, S<&oW S,oZ oZ&S< Sp<,W SpR =R5oH, go->R ovS, Svo- S,Z= S-go Sv,p= o-pSv S=Zp, S-yo Rn R5=D >R=D Un=M =RU+M V=R V+=R Rj=U >M=Un V5=R >nV= R4UnU=d =RHU5 g=R>U =RUdM d", -"Mn=U+ Vd=R =RgV =RjUd >nd=Uj V=RH5 V>ng= U

        =RDo5 o>U=D S=U S+", -"=U S=V =aoV Sp=U =US> VpS= oVs= UWo< oUWUv= =Rv5D goU>= =USv S=vU+ oVZ= V=go p=USv S>=vU oVvp= S=yV ,Un bn =Rb5D =Rc> Rb=M =R-bM Vn=b =RV- Rb=j >M-bn V=R,5 >nV- ,R4bE <&ER", -"4b ,R4bH cR4,H ,U5nE <&ERb5 ,UH5n cR5H< n-Ud =RbH5 c=Rg> =RbdM =bd", -"-Mn V=R,H c=VgR =Rbdj >Md=Rb =RbHj c=Rgs bPR< ", -"oU ob5=RD oc->R S=b =bS- =boV Sc= Sp=b =bS> oV,p= Scs= ,UoW oU&,W ,UoH ocR,", -"H oU,5W oU8,W oUH,5 cR5W< Sb ob5=RH cv=>R =bSv o-USv SZ=b Z=Sc S=bpv o-", -"pvU oVvp, Scy= q< q!< q= =B7q =aq> q=M q+=M q=T q+=T l=q q", -">l= 7q=T sq= 4=qd 7q=H g=q> qd=M ", -"q=+dM qH=T =Tgq ldq= q>l=d lHq= l=gq q

        7o=qB q>o=a S=q S+q= Sq=T Sq=a r= r>= r=T rs= oq= vq7=H vq>g= vqS= vq=S+ Zq= S=gq rv= v>r= rZ= ", -"yr= ?q ?q& ?qB ?qa ?q1 :q? q1?B ?a:q ?qM q&?M ?qT qT?a l?q l?:q qTl? s?q ?q", -"* -q ?Bq* -qa ?1q* -q: ?q1*B qa:- q*?M -qM q*?T -qT ?ql* l-q ?qTl* sq- ?qE ", -"?Eq& ?qH qH?a q1?E ?E:q ?1qH ?H:q qM?E ?qM&E qH?T ?qHT& lE?q :ql?E ?qlH ?Hs", -"q ?qd -qd qH?d g?q ?1qd ?d:q ?qH1d g:-q qd?M qd-M qT?d gM-q ?qld ld-q l?Hqd", -" gql- ?q4 ?4q& q4?B ?4qa ?q7 7?:q 7B?q 7q?a q4?M ?q4M& ?4qT ?qT4a 7l?q ?q7l", -": 7q?T ?q7s q=? -q= =B?q =a-q 7?q= Aq ?q7=B Aqa ?q=M =M-q ?q=T =T-q l?q= Al", -"q l=?qT Aqs q4?E ?q4&E ?4qH ?qH4a ?E7q ?q7:E 7q?H :qH7? ?q4ME q&4?ME ?qH4T ", -"?H4qT& ?q7lE l?7:qE l?H7q s?q7H ?dq= qd-= ?q=H g=-q 7q?d Aqd q=H7? Aqg ?qd=", -"M -q=dM q=H?T -qTg= l=?qd ldAq l=H?q glAq ?qP q&?P qP?B qa?P q1?P ?P:q ?q1P", -"B ?qa:P S? S?& S?T S?a S?l S?: ?TSl s?S q*?P -qP ?qP*B qa-P ?q1P* :P-q q*1?", -"PB -q:aP S?* S?- S*?T ?TS- l*S? S?l- S?lT* S-s? ?qW q&?W qH?W qW?a ?1qW ?W:", -"q ?qH1W :qH?W S?W S&?W S?Z ?aZq lWS? ?WS: l?Zq ?Zsq qW?d -qW ?qHW* gP-q ?qW", -"1d :W-q ?H1qW* -qWg: S?d ?WS- ?dZq g?S ldS? lW-q S?Zld s?gS o?q o&?q ?Boq o", -"q?a 7o?q o?:q ?q7oB o:?qa S?o S&o? ?TSo ?aSo r? r?: r?T r?s q=o? o-q o?q=B ", -"oa-q ?q7o= Aoq q=7o?B oqAa S?= o-S? =TS? =aS? r?= Ar =Tr? Ars oq?W ?qWo& oq", -"?H o?Hqa 7q?W o:?qW o?H7q o:H?q ?WSo S?oW& o?Zq S?Zoa r?W ?:rW r?Z s?rZ ?vq", -" -qv ?Hvq ?vgq ?q7v Aqv ?vq7H goAq S?v S-?v S=?Z S?go r?v Arv ?Zrv Ary qU< ", -"U 7q=D =Dq> qU=M q=U+M V=q =aVq lq=U q>l=U Vql= V=sq q4U=Ud q=H7U q>Dg= q=UdM q+U", -"=Md =HVq V=gq l=qUd l=Uq>d V=qlH V>qg= Uo=U q=D7o q>Do= Sq=U S=qU+ VqS= oV+q= r=U =Ur> rV= s=rV oqUW< qW=U vqD7= vq>=D vq=SU S=Uvq+ V=Zq Vv", -"qg= =Urv rv>=U Z=rV y=rV ?qt q&?t ?qD cq? ?1tq ?t:q ?1qD :q?c tq?M ?qtM& V?", -"q V?cq ?qlt ?t:lq l?Vq u?q tq* -qt qDt* cq- t1q* :qt- ?qD1* :c-q tMq* -Mtq ", -"t*Vq V-q tql* lt-q V?lq* uq- ?Etq ?qt&E tq?H ?Hcq ?qt1E ?t:qE ?qHt1 cq?:H ?", -"qtME tq&?ME ?HVq cq?VH l?qtE l?t:qE V?lqH ?quH tq?d td-q qHt* cqg? ?qdt1 -q", -"t:d ?qD1d cq-g: ?qdtM -qtdM ?dVq V?gq l?dtq l-qtd V?dlq g?uq t4?q ?qt4& ?4q", -"D c4?q ?q7t ?q7t: 7q?D ?q7c ?qt4M tq4?M& V4?q cq?V4 ?q7lt :ql7t? ?q7V ?qu7 ", -"t=q -qt= ?q=D cq= q=7t Aqt q=D7t Aqc tq=M -qt=M Vqt= V=cq ltq= ltAq V=q7t A", -"uq ?qt4E t4&?qE ?qHt4 cq?4H ?q7tE :q?7tE 7tH?q 7cq?H tq4?ME M&?Etq4 V?q4H V", -"?4cqH l?q7tE lE7t:q? 7V?qH u?q7H tdq= -qt=d tq=H t=gq 7tdq= tqAd t=H7q gqAt", -" t=qdM t=d-qM V?dq= cq=gV l=tqd Aqdlt V?d7q uqAg ?tP ?&tP tP?D ?Pcq ?1tP t:", -"?P ?qD1P cq?:P S?t S&?t S?V S?c l?St ?tS: SlV? u?S t*?P ?Pt- ?qDP* cP-q ?tP", -"1* -qt:P ?D1tP* cq-:P S*?t St-q S*V? cqS- St*l? l-qSt S?Vl* S?u- tq?W ?qWt&", -" tH?P ?Wcq ?qWt1 :qW?t ?qW1D cqW?: ?WSt S?tW& tZS? Sc?Z l?WSt S?:tW S?Zlt S", -"?uZ td?P tW-q ?qWDd ?tgP ?td1P -qWt: ?H1tdP cq-:W ?dSt -qWSt ?dSV S?gt S?dl", -"t -qWlt V?dSl g?uS ot? o&?t ?Dot ?cot o?7t ?to: ot?7D ot:?c otS? ot?S& oV? ", -"ocS? r?t ?tr: r?V ur? t=o ot- =Dot oct= 7ot= Aot t=o7D otAc S=t t=S- oVt= t", -"=Sc rt= Art t=rV Aru ?Wot ot?W& ?Hot otc?H ot?7W ot:?W otH7? ot:?H ot?SW S?", -"Wot& oV?Z oV?Zc ?trW r?t:W ?ZrV r?uZ ot?v o-tv =Hot t=go ?vq7t tvAo otH7= g", -"oAt tvS? ot-Sv tZS= ?vSc ?vrt rtAv ?vrV yAur Xn n!X XnB aXn Xn. 8Xn n.XB aX", -"8n XnK XKn! TXn aXTn Xjn Xj8n XjTn sXn Xn( +Xn n(XB aX+n n(X. 8X+n Xn(.B aX", -"n+8 n(XK Xn+K XnT( TX+n X(nj Xj+n XjnT( +Xsn Gn Gn! GnH Gan Gn. G8n G.Hn H8", -"Gn GnK n!GK GTn TnGa Gnj 8nGj HnGj sGn Gnd +Gn dXHn gXn G.dn G8+n dX.Hn G8g", -"n GKdn GK+n TdGn GTgn dnGj Gn+j dXjHn sGgn 4X 4X! 4XB 4aX 4X5 48X 4B5X 5a4X", -" 4XK XK4! 4TX TX4a 4Xj 8X4j 5T4X s4X 4X; 4+X 4BX; +X4a X;5n >X4 X;B5n 4a>X ", -"4KX; 4K+X T;4X +T4X X;4j 4X>j X;j4T s4>X 4GX 4!Gn 4HX Ga4X G5n G84X H54X H8", -"4X 4KGn 4GX!K GT4X 4GTaX Gn4j 4G8Xj HX4j 4GsX 4dX +G4X HX4d g4X 5d4X >nG 4H", -"X5d g4>X 4KdX 4+GXK Td4X 4TgX dX4j Gn>j dXj4H s4gX XPn XPn! PnXB XPan PnX. ", -"XP8n XPn.B aXP8n QXn n!QX TXQn aXQn XjQn 8XQn XjnTP QXsn PnX( XP+n XPn(B aX", -"P+n XPn(. +X8Pn Pn(X.B +X8aPn XnQ( QX+n QXnT( +QXTn XjnQ( +QX8n QXTnj( sX+Q", -"n Yn Yn! YHn Yan Yn. Y8n HnY. H8Yn YQn QnY! YZn ZnYa Yjn Q8Yn ZnYj sYn Ydn ", -"Y+n HnYd gYn dnY. +nY8 YHdn. Y8gn QdYn +QYn YdZn YZgn dnYj +nYj YZdnj gnsY ", -"oX o!X oXB oaX o5X o8X 5XoB 5aoX oQX QXo! oTX QaoX opX pXo8 pXoT osX oX; o+", -"X X;oB +Xoa 5Xo; o>X o5X;B oa>X QXo; +QoX TXo; +ToX o;pX op>X opTX; >Xos oY", -" oY! oYH Yao Y5o Y8o oHY5 oHY8 oYQ YQo! oZY YaoZ Ypo opY8 oZYp sYo Yvo Y+o ", -"oHYv goY ovY5 Y>o YvoH5 Y>go YQov YQo+ YvoZ oZgY opYv o>Yp YZvop yoY Xn# X&", -"n n#XB X&an n#X. X&8n Xn#.B aXn8& n#XK XK&n XnT# X&Tn X#nj &nXj XjnT# X&sn ", -"n#X( X&+n Xn#(B aXn+& Xn#(. X&n+8 n#(X.B +X8an& Xn#(K X&n+K TXn#( +TX&n Xjn", -"#( X&j+n TX#nj( sX+&n Gn# G&n G#Hn H&Gn n#G. 8nG& GnH#. G8nH& n#GK GK&n G#T", -"n T&Gn G#nj &nGj GTnj# G&sn G#dn G&+n dX#Hn G&gn dX#n. dX&8n HX#dn. gX8&n d", -"X#nK dX&nK GTnd# gXT&n dXjn# dX&nj dX#Hnj gsX&n 4X# 4X& X#4B aX4& 4#5X 5X4&", -" 4X5#B 48Xa& X#4K 4KX& 4#TX TX4& 4#Xj X&4j 4TX5# 4Xs& 4#X; +X4& X;#4B aX;4&", -" X;#5n 4X>& 5X#;nB >X4a& X;#4K X;&4K 4TX;# X;&4T X;j4# >X4&j X;#5Tn >Xs4& 4", -"#Gn G&4X 4#HX HX4& G#5n 5&Gn 4HX5# 4H8X& 4GX#K 4G&XK 4GTX# 4GTX& 4GjX# X&j4", -"G 4HXj# s4GX& 4#dX dX4& 4HXd# 4Xg& 4dX5# G&>n dX#H5n >Xg4& 4dX#K dX&4K 4TdX", -"# g4XT& dXj4# >nG&j dX#4Hj >nsG& PnX# XP&n XPn#B aXP&n XPn#. X&P8n Pn#X.B 8", -"XaP&n XnQ# X&Qn QXnT# QaX&n XjnQ# X&jQn QXTnj# sXQ&n XPn#( X&P+n Pn#X(B +Xa", -"P&n Pn#X(. +X8P&n .BX(Pn# aX+P8n& QXn#( +QX&n TX#Qn( QX&+Tn QX#nj( +QX&nj Q", -"#TnXj( +QXsn& Yn# Y&n HnY# H&Yn n#Y. 8nY& YHn#. Y8H&n QnY# Q&Yn Y#Zn ZnY& n", -"jY# &nYj YZnj# Y&sn dnY# +nY& YHdn# Y&gn Ydn#. Y+8&n dn#YH. gY8&n YQdn# Y+Q", -"&n YZdn# gYZ&n Yjdn# Y+j&n ZndYj# sYg&n oX# o&X X#oB aXo& 5Xo# 5Xo& o5X#B o", -"8aX& QXo# QXo& TXo# TXo& o#pX pXo& opTX# o&sX X;o# +Xo& oX;#B o+aX& o5X;# o", -"&>X X;#o5B o>aX& oQX;# o+QX& oTX;# o+TX& opX;# o>pX& pX;oT# os>X& oY# Y&o Y", -"#oH oHY& o5Y# o8Y& Y5oH# Y5ao& oQY# YQo& Y#oZ Y&oZ Y#op opY& YpoZ# Y&os Y#o", -"v ovY& YvoH# Y&go Yvo5# Y&o> ovHY5# goY>& YvoQ# Yv&oQ YZvo# goZY& Ypov# Yp&", -"o> oZvYp# Y&yo In In! DXn aIn In. 8In D.In 8IDn InK IKn! TIn aITn Inj Ij8n ", -"InDj sIn In( +In D(In DX+n n(I. 8I+n In(D. +DX8n n(IK +KIn T(In TI+n I(nj I", -"n+j InjD( +Isn GnI G!In Jn Jna G.In 8IGn Jn. J8n GKIn InKG! JnT TnJa InGj I", -"njG8 Jnj sJn Idn Gn+I Jnd gJn I.dn Id8n dnJ. J8gn dKIn Idn+K TdJn gTJn dnIj", -" Idn+j dnJj gnsJ 4IX 4!In 4DX DX4a 5In 8I4X 5D4X D84X 4KIn InK4! DX4T 4DXTa", -" In4j Inj48 DX4j 4DsX I;n +I4X D;4X +D4X I;5n >nI I;n5D 4D>X IK;n I;n+K I;T", -"n a;nTI ;nIj In>j I;n5T sI>n Gn4I In!4G J4X 4aJn 5IGn 4G8In J5n 48Jn InK4G ", -"4GKIn! 4TJn J4TaX Inj4G 4G8Inj 4XJj J4sX Id4X Idn4+ J;n J4gX Id5n Gn>I 5dJn", -" J>n Idn4K IdK4+X T;Jn gJ4TX Idn4j >nGIj ;nJj >nsJ IPn n!IP IPDn IPan PnI. ", -"IP8n IPnD. D8XPn QIn Q!In DXQn aIQn IjQn 8IQn IPjDn QIsn PnI( IP+n IPnD( +D", -"XPn IPn(. +IP8n DP(In. D8P+In Q(In QI+n QDXn( +QDIn IPjn( IPj+n IP(Dnj sIP+", -"n YIn InY! YJn JnYa InY. 8IYn Y.Jn JnY8 QIYn YQIn! ZJn ZaJn InYj Y8QIn JnYj", -" YJsn IdYn +IYn YdJn YJgn IdnY. Y+8In YJdn. gYJ8n IdQn Y+QIn ZdJn ZJgn YjId", -"n Y+jIn YJjdn sJngY oI oI! oDI oaI oI5 o8I 5DoI 5aoI oIQ QIo! oTI QaoI opI ", -"pIo8 pDoI osI oI; o+I DXo; +DoI 5Io; o>I oD5I; oD>X QIo; +QoI TIo; +ToI o;p", -"I p>oI opDI; sIo> oYI YIo! oJ oJa oIY5 oIY8 oJ5 oJ8 YQoI oYQI! oJZ oaZJ oIY", -"p Y8opI oJp oJs ovI oIY+ oJv goJ o5vI oIY> J5ov oJ> oQvI Y+oQI JvoZ gZoJ pv", -"oI o>IYp opJv yoJ bXn I&n DXbn cXn b.In 8Ibn In.bD 8Icn bKIn IK&n TIbn TIcn", -" Inbj &nIj InjbT cXsn b(In +Ibn In(bD +Icn In(b. I&n+8 DX(bn. cX+8n In(bK I", -"&n+K bTXn( cX+Tn Injb( I&n+j Ij(bTn sInc+ bGn G&bn Jnb cJn b.Gn G8bn bnJ. J", -"8cn bKGn I&nGK bTJn cTJn Gnbj I&nGj bnJj cJsn Gnbd +Gbn bdJn cJgn Idnb. Idn", -"b8 Jnbd. cJng8 IdnbK Idn&K JnbTd cJngT Idnbj Idn&j Jnjbd sJngc 4bX bX4& bX4", -"D c4X b54X b84X 4bX5D 48cX 4KbX I&n4K bT4X 4TcX bX4j I&n4j 4bT5X c4sX b;4X ", -"b+4X I;nbD 4+cX I;nb5 4b>X 5DXb;n c4>X I;nbK I;&nK I;nbT c4X+T I;nbj >Xb4j ", -"4bTX;j c>Xs4 bG4X I&n4G 4bJn J4cX G5bn I&nG5 b5Jn J5cn 4bGXK InK4G& J4bTX c", -"J4TX 4bGXj 4bGX&j J4jbX sJ4cX bd4X Idn4& b;Jn c4gX Idnb5 bG>n J5nbd cJ>n 4b", -"dXK IdK;&n J;nbT cJ;Tn dXj4b >nbGj J;nbj J>nsc IPbn P&In IPnbD IPcn IPnb. I", -"P&8n bPDIn. cX8Pn QIbn I&Qn bQXDn QIcn IPjbn IP&nj bTPInj sIPcn IPnb( IP&+n", -" bPDIn( cX+Pn bP(In. +IPb8n IPbnD(. +IPcn8 bQXn( I&n+Q IP(bTn cQX+n IP(bnj ", -"b+QInj InbjQD( sI+cQn Ybn bnY& JnYb Ycn bnY. b8Yn YJbn. cnY8 bQYn YbQ&n ZnY", -"b ZnYc bnYj Yb8Qn YZbnj snYc bdYn b+Yn YJbdn gnYc Ybdn. Yb+8n JndYb. Ycg8n ", -"YbQdn Yb+Qn YZbdn ZcngY Ybjdn Yb+nj YbdJnj sYcgn obI oI& bXoD ocI b5oI b8oI", -" ob5DX o8cX bQoI QIo& bToI oTcX pboI pIo& opbDX sIoc bXo; b+oI obDI; o+cX o", -"b5I; ob>X b5XoD; >Xoc obQI; ob+QI obTI; oc+QI opbI; o>bpI ob;pDX osc>X Ybo ", -"obY& oJb Yco obY5 obY8 J5ob Y5oc YQob YboQ& YboZ ZcoJ opYb Ypbo8 obJp osYc ", -"ovYb obY+ obJv Ycgo Yvbo5 Ybo> oJvb5 ocY> YvboQ Ybo+Q oJZvb ocZgY Ypbov Y>b", -"op oJpvb Ycyo 6X 6X! 6XB 6aX 6X1 68X 6B1X 1a6X 6XK XK6! 6TX TX6a 6Xj 8X6j 1", -"T6X s6X 6X( 6+X X(6B +X6a 6(1X 1+6X 6X1(B 6+X1a X(6K 6K+X 6(TX +T6X 6(Xj +X", -"6j 6TX1( 6+sX 6GX 6!Gn 6HX Ga6X 1Gn G86X 1H6X Ga1n 6KGn 6GX!K GT6X 6GTaX Gn", -"6j 6G8Xj GT1n 6GsX 6dX +G6X HX6d g6X 1d6X +G1n 6HX1d 68gX 6KdX 6+GXK Td6X 6", -"TgX dX6j dXj6+ dXj6H s6gX 4X6 6!4X 4B6X 6a4X 7X 7X8 7XB 7aX 4K6X 4X6!K 6T4X", -" 4TX6a 7Xj 8X7j 7TX 7sX 6X; 6+4X 6BX; aX6; 7X; >X7 X;7B 7a>X 6KX; 4+X6K TX6", -"; aX;6T X;7j >j7X TX7; >X7s 6G4X 4G6n! 6H4X 4Ga6X 7GX G87X 7HX Ga7X 4G6XK 6", -"GK4X! 4GT6X 6GT4aX Gn7j 7G8Xj GT7X 7GsX 6d4X 4+G6X HX6; 4Xg6 7dX 7G>X HX7d ", -"g7X 4dX6K X;K6+G 4Td6X g4X6T dX7j 7>GXj Td7X gX7s 6XP XP6! XP6B aX6P 1X6P 8", -"X6P 6X1PB 68XaP 6QX Q!6X QX6T Qa6X 1Q6X Q86X 6QX1T 6QsX XP6( +X6P 6XP(B 6+X", -"aP 6X1P( 6+X1P 1X(6PB 1+X6aP 6(QX +Q6X 6QXT( 6+QTX 6QX1( 6+Q1X Xj(6TP s6X+Q", -" Y6 Y6! Y6H Y6a Y61 Y68 6HY1 6HY8 Y6Q 6QY! YZ6 Z6Ya Y6j 6QY8 Z6Y1 sY6 Y6d Y", -"6+ 6HYd gY6 6dY1 6+Y1 Y61Hd Y6g1 6QYd 6+YQ YdZ6 YZg6 6dYj 6+Yj YZ61d g6sY o", -"6X 6Xo! 6XoB 6aoX 7oX o87X oX7B oa7X 6QoX o!6QX 6ToX oT6aX 7pX 78pX oT7X 7o", -"sX 6Xo; 6+oX o6X;B o+6aX oX7; 7o>X 7oX;B 7oa>X QX6; o+6QX oT6X; o+T6X 7;pX ", -"7p>X 7oTX; os7>X Y6o o!Y6 oHY6 oaY6 7Y 7Y8 7YH 7Ya o6YQ Y6oQ! Y6oZ YZ6oa 7Y", -"p Y87p 7ZY sY7 Yv6 o+Y6 YHv6 Yvg6 7Yv Y>7 7HYv g7Y YQv6 Yv6+Q ZvY6 gY6oZ 7v", -"Yp 7pY> YZ7v y7Y 6X9 6X& 6B9X 9a6X 1X9n :X6 6X19B 6a:X 6K9X 6KX& 9T6X TX6& ", -"9X6j 6X:j 6TX9j :Xs6 6(9X 9+6X 6X9(B 6+X9a 6X19( 6+:X 1X(9nB :X6+a 6X9(K 6+", -"X9K 6TX9( 6+T9X 6Xj9( :X6+j Xj(9Tn s:X6+ 9Gn G&6X 9H6X Ga9n 1G9n :Gn 6HX91 ", -"6H:X 9KGn 6G&XK GT9n 6GTX& Gn9j Gn:j 6HX9j :Gsn 9d6X +G9n 6HX9d 6Xg9 6dX91 ", -"6d:X 1HX9dn :Ggn 6dX9K dX&6K 6Td9X g6X9T dXj9n :Gn+j 9GTdnj g:Xs6 49X 6X4& ", -"4B9X 9a4X 7X9 7:X 9X7B :X7a 4K9X 49X&K 9T4X 49TaX 9X7j 7j:X 9T7X 7:sX 9X6; ", -"9+4X 49X;B aX;49 9X7; 7:>X 7X9;B 7:X>a 49X;K X;&6K 49TX; X;&6T 7X9;j 7:X>j ", -"7TX9; 7sX:> 9G4X 49GX& 9H4X 49GaX 9G7X :G7X 9H7X :H7X 49GXK X&K49G 49GTX 6G", -"T4X& 7G9Xj 7:GXj 7GT9X 7sG:X 9d4X dX&49 49HdX 49gX 9d7X :G>n 7HX9d 7:gX 49d", -"XK dXK49+ 49TdX g49TX 7dX9j 7:dXj 7Td9X g7Xs: 9X6P X&6P 6XP9B 6aX9P 6X19P 6", -"X:P 9X16PB :X6aP 9Q6X QX6& 6QX9T 6Qa9X 6QX9j 6Q:X 9TX6Pj :QXs6 6XP9( 6+X9P ", -"9X(6PB 9+X6aP 9X16P( :X6+P 6(9X1PB 6+X:Pa 6QX9( 6+Q9X 6Q(9TX 9+Q6TX Xj(9Qn ", -":QX6+ 6(QX9T1 sX+:Qn Y69 Y6& 6HY9 6HY& 9nY1 Y:6 Y691H :HY6 6QY9 6QY& Z6Y9 Z", -"6Y& 6jY9 :QY6 YZ69j s6Y: 6dY9 6+Y9 Y69Hd Y6g9 Y691d :dY6 9HnY1d g6Y: Y69Qd ", -"Y6+9Q YZ69d gY6Z9 Y6j9d Y:6+Q Y9dZ1n sY:g6 o9X 6Xo& 9XoB 9aoX o97X o:X 7o9X", -"B oa:X 9QoX o9QX& 9ToX o9TaX p97X 7X:p 7oT9X sXo: 9Xo; 9+oX o9X;B o9+aX 7o9", -"X; >Xo: o9;7XB o:>aX o9QX; o9+QX o9TX; o9+TX 7pX9; o:p>X 7T;p9X os:>X Y9o o", -"9Y& oHY9 o9Ya 7Y9 Y:o 7HY9 Yao: YQo9 Y6&oQ Y9oZ oZ9Ya Y97p Ypo: Y97Z Y:7Z o", -"vY9 o9Y+ Yv69H Y9go Y97v :v7Y 7Yv9H Y:go Yv69Q Yv6Q& oZ9Yv go9YZ Yp97v Y:op", -"v 7ZYv9 Y:yo 6IX 6!In 6DX DX6a 1In 8I6X 1D6X D86X 6KIn InK6! DX6T 6DXTa In6", -"j Inj68 DX6j 6DsX 6(In +I6X 6(DX +D6X 1(In +I1n 6DX1( 6+D1X In(6K 6+IXK 6DX", -"T( 6+DTX Inj6( Inj6+ 6DXj( sIn6+ Gn6I In!6G J6X 6aJn Gn1I 6G8In J1n 68Jn In", -"K6G 6GKIn! 6TJn J6TaX Inj6G 6G8Inj 6XJj J6sX Id6X Idn6+ 6dJn J6gX Id1n Idn6", -"8 1dJn J1gn Idn6K IdK6+X J6TdX gJ6TX Idn6j 6+GInj J6jdX sJ6gX 6I4X In!46 6D", -"4X 4DX6a 7IX 8I7X 7DX D87X InK46 6IK4X! 4DX6T 6TI4aX In7j 7I8Xj DX7T 7DsX I", -";6X I;n6+ DX6; aX;6D I;7X 7I>X DX7; 7D>X I;n6K I;K6+X I;n6T 6+D4TX 7IX;j 7>", -"IXj 7DXT; 7sI>X 4G6In 4G6In! 4XJ6 J46aX Gn7I 7G8In 7JX J87X 4G6InK 6!4GInK ", -"J46TX 4TXJ6a 7GIXj Inj7G8 Jn7T sX7J Idn6; 6+GI;n 6XJ; gJ46X Id7X 7>GIn J;7X", -" >X7J IdK6X; Id4X6+K J6;TX J4Tg6X 7IdXj >Ij7dX 7JTdX J>n7s 6IP 6!IP DX6P aI", -"6P 1I6P 8I6P 6DX1P 6D8IP QI6X 6QIn! QD6X 6QDaX QI1n IPj68 IPj6D 6IsP 6(IP +", -"I6P 6DXP( 6+DIP 6IP1( 6+I1P IP(1Dn 1+D6IP 6QIX( 6+QIP 6QDX( 6+QDX IPj6( IPj", -"6+ IP(6Dj sIP6+ Y6I 6IY! YJ6 J6Ya 6IY1 68YI J6Y1 J6Y8 6QYI Y6QI! ZJY6 YZ6Ja", -" 6IYj Y68QI J6Yj YJs6 6IYd 6+YI YdJ6 YJg6 Y61Id Y6+1I YJ61d gY6J1 Y6QId Y6+", -"QI YZ6Jd gY6ZJ Y6jId Y6+Ij YJ6dj sY6gJ oI6 6Io! 6DoI 6aoI 7oI o87I oD7I oa7", -"I 6QoI oIQ6! 6ToI oTI6a op7I 7oIp8 oT7I 7osI 6Io; 6+oI oD6I; o+D6I 7;oI 7Io", -"> 7oDI; o>D7I oIQ6; o+I6Q oTI6; o+T6I 7oIp; o>I7p 7oTI; osI7> oIY6 Y6oI! oJ", -"6 oaJ6 7YI 7IY8 7Jo Y87J Y6oQI oIQY6! Z6oJ oJZ6a 7IYp 7Yp8I oJ7Z 7JsY v6oI ", -"Yv6+I Y6Jv g6oJ 7IYv 7IY> 7voJ 7Jgo Yv6QI Y6Qo+I oJZv6 goJZ6 7vIYp Y>7pI oJ", -"p7v 7Jyo b6X 6&bX 6DbX c6X 6Xb1 :In b6X1D c6:X bK6X I&n6K 6TbX 6TcX 6Xbj In", -":j Inj9D :Isn b(6X 6+bX b6XD( 6+cX b6X1( +I:n b6(1DX :cX6+ b6X(K b6+XK b6TX", -"( c6X+T Inj9( :In+j In(b1T sIn:+ 6GbX I&n6G J9n J6cX 1Gbn bG:n b1Jn :Jn b6G", -"XK I&K9Gn 9TJn cJ6TX Inj9G :Gnbj 9nJj sn:J 6dbX Idn6& 9dJn c6gX Idnb1 Id:n ", -"J9n1d gn:J Idn9K IdK6X& J9nTd c6XgT Idn9j :Idnj J9ndj :Jngs b64X I&n49 9D4X", -" 49cX 7bX :I7X bX7D 7cX 4bX6K I&K49X 4bT6X c4X6T bX7j 7:IXj bT7X sX7c 6Xb; ", -"I;&6X I;n9D 6Xc; bX7; 7b>X 7bXD; >X7c I;n9K I;K6X& I;n9T c6XT; 7bX;j 7>bXj ", -"7bTX; 7cXs> 4bG6X 49GI&n 49Jn cJ46X bG7X 7:GbX J97X 7X:J InK49G 4KbG6X& J49", -"TX c4TJ9n 7bGXj 7bj:Gn 7JbTX 7Js:X Idn49 49+Idn 9;Jn cJ6X; bd7X 7:IdX 7JbdX", -" >n:J IdK49X dX4&b6K J9;Tn c4Tg6X 7bdXj >Ij:Gn 7bTdX J>ns: 6IbP IP6& b6XDP ", -"6IcP b6X1P 6I:P 6DXb1P :cX6P 6QbX IP&6Q b6QDX 6QcX IPjb6 QI:n b6TIPj sIP:n ", -"b6XP( IP&6+ IP(9Dn c6X+P IP(b1n :IP6+ b(6X1DP :I+c6P b6QX( b6+QX IP(b6T c6Q", -"+X IP(b6j :QI+n 6XbjQD( sI+:Qn Yb6 b6Y& J6Yb Yc6 b6Y1 :IY6 YJ6b1 Y6:J b6YQ ", -"Yb6Q& ZbY6 Y6Zc b6Yj Y:b6Q YZb6j s6Yc b6Yd b6Y+ YJ6bd g6Yc Yb61d Y:b6+ YbdJ", -"1n Y:Jg6 Yb6Qd Yb6+Q YZb6d Yc6gZ Yb6dj Yb6+j YbdZ1n sYcg6 o9I 6Io& 9DoI o9c", -"X ob7I o:I 7obDX 7Ioc 9QoI o9IQ& 9ToI oc6QI pb7X op:I 7obTI sIo: 9Io; 9+oI ", -"o9DI; oc6+I 7obI; :Io> 7D;o9I o:Ic> o9IQ; o9+QI o9TI; c6QX; 7pbX; o:Ip> 7b;", -"oTI os:>I obY6 Ybo6& oJ9 Y6oc 7Yb Ybo: Yb7J Yc7 Ybo6Q Y6QoI& Z9oJ oJ9Zc Yb7", -"p o:IYp Yb7Z Yc7Z vbY6 Yvb6+ o9Jv g9oJ Yb7v 7>Yb oJ97v Ycg7 Yvb6Q YbQo9+ oJ", -"9Zv oJ9gZ 7Ybpv :vIop oJpv9 Ycy7 RXn n!RX XnRB RXan XnR. RX8n RXn.B aXnR8 X", -"Mn n!XM XMTn XMan MnXj XM8n XMnTj XMsn XnR( RX+n RXn(B aXnR+ RXn(. R+8Xn Xn", -"(R.B R+8aXn X(Mn XM+n XMnT( aXM+n XMnj( R+jXn RTXnj( sX+Mn RGn R!Gn GnRH Gn", -"Ra R.Gn GnR8 RGHn. RG8Hn GMn G!Mn GnRT aMGn GnRj 8MGn RGTnj RGsn GnRd +nRG ", -"RGHdn RGgn dX.Rn R+G8n RGHdn. gRG8n dMGn GM+n dXMHn GMgn dXMnj dXM8n RGTdnj", -" gsRGn R4X 4!RX RB4X 4XRa 4XR5 4XR8 R45XB R48aX 4XM 4!XM 4XRT aX4M 4XRj 8X4", -"M R4T5X R4sX 4XR; 4XR+ X;BR4 aX;R4 R45X; R4>X R45X;B >XR4a X;4M +X4M XM;4T ", -"aXM4+ XM;4j 4X>M R4TX;j >XsR4 R4G 4!RG 4GRH 4GRa 4GR5 4GR8 R4GH5 R4GH8 4MRG", -" R4GM! 4GRT aXM4G 4GRj R4G8M R4GHj R4sG 4GRd 4+RG R4GH; R4gX R4G5d R4>G 4HX", -"R5d >XgR4 dX4M dXM4+ dXM4H 4XgM dXM4j GM>n R4HdXj >Xg4M XPRn RXPn! RXPnB aX", -"PRn RXPn. R8XPn XPnR.B R8XaPn SXn n!SX TXSn aXSn XjSn 8XSn STXnj SXsn RXPn(", -" R+XPn XPnR(B R+XaPn XPnR(. +XPR8n .BR(XPn aX+PR8n XnS( +XSn STXn( S+TXn SX", -"nj( S+8Xn XjnST( Ss+Xn YRn RnY! RHYn RaYn RnY. R8Yn YRHn. Y8RHn SYn YnS! Zn", -"SY SnYa SnYj SnY8 SZYnj SYsn RdYn R+Yn YRHdn YRgn YRdn. Y+R8n dn.YRH gYR8n ", -"YdSn SnY+ SZYdn SYgn SYdnj SY+8n YZnSdj gSsYn oRX RXo! RXoB RaoX R5oX R8oX ", -"oR5XB o8RaX SoX o!SX SXoT SXoa pXSo SXo8 SpToX sXSo R;oX R+oX oRX;B o+RaX o", -"R5X; oR>X X;BoR5 o>RaX oXS; SXo+ S;ToX Sa;oX SpXo; So>X opTS;X os>SX oYR YR", -"o! YRoH YRoa oRY5 YRo8 Y5oRH Y5aoR SoY S!oY SYoZ YaSo SoYp Y8So SZpoY SosY ", -"vRoY YRo+ YvoRH oYgR YvoR5 >RoY ovRY5H goY>R YvSo Y+So YZvSo SogY SvoYp SoY", -"> YpoSvZ SoyY XnR# RX&n RXn#B aXnR& RXn#. X&nR8 Xn#R.B R8aX&n X#Mn MnX& XMn", -"T# aXM&n XMnj# XM&8n RTXnj# sX&Mn RXn#( X&nR+ Xn#R(B R+aX&n Xn#R(. R+8X&n .", -"BR(Xn# aXR&+n8 XMn#( XM&+n TX#Mn( +TXM&n Mn#Xj( +XM&nj XMTnj#( XM&sn+ R#Gn ", -"GnR& RGHn# RGa&n RGn#. RG8&n Gn#RH. G8nRH& G#Mn M&Gn RGTn# aMnG& RGjn# M&nG", -"8 XM#Hnj sRG&n dX#Rn dX&Rn RGHdn# gRG&n RG#dn. RG8d&n dXHnR#. RG8gn& dXMn# ", -"dXM&n dX#HMn gXM&n dM#Gnj XM&dnj dXHjMn# sX&gMn R#4X 4XR& R4X#B R4aX& R45X#", -" R48X& 4X#R5B 4aXR5& 4#XM XM4& R4TX# aXM4& R4jX# XM&48 XM#5Tn sR4X& X;#R4 X", -";&R4 R4#X;B R4aX;& R45X;# >XR4& 5#X;R4B R4a>X& XM;4# XM;4& XM#T;n XM&a;n XM", -"#;nj >XM4& X;Rj4T# sX&>Mn R#4G 4GR& R4GH# R4GH& R4G5# R4G5& R4#H5X 4G8RH& R", -"4GM# XM&4G R4GT# XM&4H R4Gj# M&nG5 XM#4Hj sR4G& R4Gd# dX&R4 dX#R4H gR4G& dn", -"#RG5 >nGR& H#5nRG; >X&gR4 dXM4# dXM4& dX#R4T g4XM& dX#R4j >MG&n dX4MH5# sX&", -"gR4 RXPn# X&PRn XPnR#B RaXP&n XPnR#. R8XP&n .BP#RXn aXR&8Pn XnS# X&Sn STXn#", -" SaX&n SXnj# S8X&n XjnST# SsX&n XPnR#( R+XP&n XPRn#B( aXR&+Pn #(P.RXn 8X+PR", -"&n XnR(.BP# anR&8X+P SXn#( S+X&n TXnS#( +TXS&n XjnS#( X&jS+n XjSnT#( S+Xsn&", -" RnY# R&Yn YRHn# YaR&n YRn#. Y8R&n RHnY#. RH8Y&n YnS# SnY& SZYn# SZ&Yn SYnj", -"# SY8&n YjnSZ# sYS&n YRdn# Y+R&n dn#YRH gYR&n dn#YR. d&nY8R dnY#RH. gR8Y&n ", -"SYdn# SY+&n YZnSd# gSY&n YjnSd# S+nY&j dnYjSZ# sY&gSn RXo# R&oX oRX#B oaRX&", -" oR5X# o8RX& R5Xo#B R5ao&X oXS# SXo& oTXS# oT&SX SpXo# Sp&oX oTXSp# osSX& o", -"RX;# o+RX& X;#oRB aX;o&R X;#oR5 o>RX& X;o#R5B oaR>X& S;Xo# S;&oX oTXS;# S+X", -"oT& opXS;# S>oX& X;S#opT S>Xos& oRY# YRo& oYRH# YaoR& Y5oR# Y5&oR oHRY5# Y5", -"RoH& S#oY Y&So oZYS# oZ&SY YpoS# Yp&So oZSYp# sYoS& YvoR# Yv&oR oHRYv# goYR", -"& ovRY5# Y>oR& YRoHv5# Y>Rgo& SvoY# Sv&oY oZYSv# goSY& YpoSv# S>Yo& SZYpov#", -" yoYS& [n [!n [Dn [an [n. [8n Dn[. D8[n [Mn Mn[! V[n [aVn [jn 8M[n [jVn [sn", -" [n( [+n Dn[( +D[n n([. +n[8 [Dn(. [+D8n Mn[( +M[n [nV( [+Vn nj[( +n[j V[nj", -"( [+sn [Gn Gn[! Jn[ [aJn Gn[. G8[n [nJ. [8Jn GM[n [!GMn JnV JaVn Gn[j [8GMn", -" VnJj Jn[s [dn +G[n [dJn g[n dn[. 8d[n Jn[d. [8gn dM[n [+GMn VdJn JngV dn[j", -" [+jGn JnVdj gn[s [4 [4! [4D [4a [45 [48 4D[5 4D[8 [4M 4M[! V[4 [aV4 [4j 48", -"[j [4V5 [s4 [4; [4+ 4D[; 4+[a 5n[; [>4 [45D; [a>n 4M[; 4+[M [4V; [4V+ 4j[; ", -"[4>M V[4;j >n[s [4G 4G[! J4[ [aJ4 4G[5 4G[8 [4J5 [4J8 4G[M [4GM! V[J4 J4V[a", -" 4G[j [48GM V5Jn J4[s [4d 4+[d [4J; g[4 4d[5 [d>n J4[5d >ng[ 4d[M [4+GM V;J", -"n V[g4 4d[j [>4GM J4[dj g4[s [Pn n![P DP[n aP[n Pn[. 8P[n [DPn. [8DPn S[n [", -"!Sn VnS[ Sn[a Sn[j Sn[8 SV[nj S[sn Pn[( +P[n [DPn( [+DPn [Pn(. [+8Pn DPn[(.", -" +DP[8n [nS( Sn[+ SV[n( SV+[n S[nj( S[+8n VnjS[( [sS+n [Yn Yn[! [YJn Yn[a [", -"nY. Yn[8 YJ[n. YJ8[n Sn[Y S[Yn! ]n ]an Yn[j S[8Yn ]jn ]sn Yn[d Yn[+ YJ[dn [", -"Ygn [Ydn. Y+[8n [YdJn. g[Y8n Sn[d S[+Yn ]dn ]gn S[dnj S[8dn dn]j gs]n o[ o[", -"! o[D o[a o[5 o[8 [5oD [5oa o[S S!o[ oV[ Sao[ [po S8o[ [poV os[ o[; o[+ [;o", -"D [+oD o5[; [>o o[5D; oD[> S;o[ S+o[ V;o[ V[o+ [;op o[S> oVp[; [>oV o[Y o![", -"Y oJ[ Yao[ Y5o[ Y8o[ J5o[ J8o[ SYo[ o[YS! ]o ]oa o[Yp [poY8 ]op ]os [vo Y+o", -"[ [voJ go[ [5ov o[Y> oJ[v5 [>go o[Sv [voS+ ]ov ]og op[v [pvo> op]v ]yo [bn ", -"[&n bn[D [cn bn[. b8[n [bDn. [8cn bM[n M&[n [bVn V[cn bn[j &n[j V[bnj sn[c ", -"bn[( b+[n [bDn( [+cn [bn(. [+b8n bnD[(. [c+8n [bMn( [+bMn V[bn( [cV+n [jbn(", -" [+jbn [jbVn( [sc+n bG[n G&[n [bJn Jn[c [bGn. [8bGn Jn[b. [cJ8n GMbn [&GMn ", -"JbVn VJcn [jbGn [&jGn JnVbj [sJcn bd[n d&[n Jn[bd gn[c [dbn. [8dbn [dbJn. g", -"[c8n [dbMn [d&Mn JnVbd gVn[c [djbn [d&nj Jnb[dj g[scn [4b [4& 4b[D [c4 4b[5", -" 4b[8 [4b5D [4c5 4b[M 4M[& Vb[4 V[c4 4b[j 4&[j V[4b5 s4[c 4b[; 4b[+ [4bD; [", -"4c; [4b5; [&>n b5n[;D >n[c [4bM; [4+bM V[4b; [c4V+ [4jb; [>4bM V4b[;j V>[c4", -" 4b[G 4G[& Jb[4 J4[c [4bG5 [48bG J4[b5 [c4J5 [4bGM [4&GM J4V[b [c4VJ [4jbG ", -"[4&Gj J4[bj [s4cJ 4b[d 4d[& J4[bd g4[c [4db5 [>4bG J4b[5d J>n[c [4dbM [4dM&", -" J;Vbn g[4Vc [4dbj >MbGn J4b[dj J>Vcn bP[n P&[n [bDPn [Pcn [bPn. [8bPn bPD[", -"n. [c8Pn [bSn Sn[& SV[bn cnS[ S[bnj S[8bn V[nSbj [scSn [bPn( [+bPn bPD[n( [", -"c+Pn bPn[(. b+P[8n bD[(Pn. [+8cPn S[bn( S[+bn V[nSb( Sc[+n [jnSb( Sbn[+j nj", -"V(S[b Sc+[sn [bYn Yn[& YJ[bn [Ycn Yb[n. Yb8[n Jn[Yb. Yc[8n SnYb S[&Yn ]bn ]", -"cn SYbnj SYb8n bn]j sc]n Yb[dn Yb+[n Jn[Ybd g[Ycn [dnYb. Ybn[8d dnJ.Yb[ Yc8", -"g[n S[dbn S[d&n bd]n gc]n Sbn[dj SbnY+j ]jnbd ]cngs o[b o[& [boD oc[ [5ob [", -"5o& o[b5D c5o[ Sbo[ S&o[ V[ob o[Sc ob[p o&[p oVp[b [poc [;ob [+ob o[bD; c;o", -"[ o[b5; ob[> [5boD; [>oc S[;ob o[+Sb oV[b; oV+[c [pob; [p&o> [pboV; oV>[c Y", -"bo[ Y&o[ [Job o[Yc Ybo[5 o[8Yb oJ[b5 oJ8[c YbSo o[&SY ]ob ]oc [poYb [p&oY o", -"p]b os]c ob[v o&[v oJ[vb ocg[ [vob5 [v&o> [vboJ5 oJ>[c [voSb [v&So ov]b go]", -"c [pvob [pvo& ]opvb yo]c qX q!X qXB qaX q1X q8X 1XqB 1aqX qXM XMq! qTX TXqa", -" lXq q8lX qTlX sqX qX( q+X X(qB +Xqa 1Xq( 1+qX q1X(B q+1aX XMq( +XqM TXq( +", -"TqX qXl( q+lX lXqT( q+sX qG qG! qGH qGa qG1 qG8 1GqH 1Gqa qGM GMq! qGT GTqa", -" lGq q8lG qGlH sqG qGd q+G HXqd gqG 1Gqd 1+qG qG1Hd qGg1 GMqd +GqM GTqd qGg", -"M qGld q+lG lGqTd lGgq q4X 4Xq! 4XqB 4aqX 7qX q87X qX7B qa7X 4XqM q!4XM 4Tq", -"X qT4aX lX7 l87X 7TlX lX7s q;X 4+qX X;qB aXq; q;7X q>X 7qX;B qa>X XMq; q+4X", -"M TXq; q+T4X 7Xl; lXq> 7qTX; >Xsq qG4 4Gq! 4GqH 4Gqa 7qG q87G qG7H qG7a 4Gq", -"M qG4M! 4GqT qGT4a 7qlG 7qGl8 7HlX 7qsG qG; 4+qG G;qH qGg4 qG7d q>G 7qGH; >", -"Xgq GMq; q+G4M GTq; gq4GT 7dlX lGq> 7qGTd lXg7 qXP XPq! XPqB aXqP 1XqP 8XqP", -" q1XPB q8aXP SqX q!SX SXqT SXqa SqlX SXq8 SlqTX SqsX XPq( +XqP qXP(B q+aXP ", -"q1XP( q+1XP 1XPq(B 1+XqaP qXS( SXq+ SqTX( Sq+TX SlqX( Sq+lX lXTSq( sqS+X Yq", -" Yq! YqH Yqa Yq1 Yq8 qHY1 qHY8 YqS S!Yq ZqY SaYq lYq S8Yq ZqlY sqY Yqd Yq+ ", -"YHqd gqY qdY1 q+Y1 Yq1Hd g1Yq SdYq S+Yq qdYZ gYZq ldYq l+Yq lYZqd gqlY oqX ", -"oXq! qXoB oXqa oq7X oXq8 7oqXB 7oaqX SXoq SqXo! oXqT SqaoX rX r8X rTX rsX o", -"Xq; oXq+ oqX;B oq+aX 7oqX; oq>X oq;7XB q>oaX SXq; Sq+oX Sq;TX SqaX; r;X r>X", -" TXr; >Xrs Yqo o!Yq oHYq oqYa 7Yq Y87q 7HYq Ya7q SoYq YqoS! oZYq YqaoZ rY r", -"Y8 rZY rsY vqY Y+vq qHYv gYvq vq7Y Y>q vq7YH Y>gq YqSv vqYS+ YZvq goqSY rYv", -" rY> YZrv yrY q9X q&X 9XqB 9aqX 9Xq1 :qX q91XB qa:X 9XqM XMq& 9TqX TXq& q9l", -"X lX:q lXq9T sX:q 9Xq( 9+qX q9X(B q+9aX q91X( q+:X 9X1q(B :q+aX q9XM( q+9XM", -" qT9X( q+T9X lXq9( :ql+X qT9lX( sq:+X qG9 qG& 9GqH 9Gqa 9Gq1 :qG qG91H qG:H", -" 9GqM GMq& 9GqT GTq& l9qG lG:q lGq9H sG:q 9Gqd 9+qG qG9Hd qGg9 qG91d q+:G 9", -"HXqd1 gX:q qG9dM q+G9M qGT9d gq9GT lGq9d :qGl+ lG9qTd glq:G 49qX 4Xq& q49XB", -" qa49X q97X 7X:q 7q9XB 7qa:X 9X4M q&4XM qT49X qT&4X l97X 7:lX 7qT9X 7sX:q 9", -"Xq; X;q& q;9XB qa;9X 7q9X; >X:q q;97XB q>:aX q;9XM q;&XM qT;9X qT;X& lX79; ", -"q>l:X 7T9lX; sq>:X 49qG 4Gq& qG49H qGa49 79qG 7G:q 7qG9H :qG7H qG49M qG&4M ", -"qGT49 qGT4& 7qGl9 :qG7l 7qG9T sqG7: 9Gq; G;q& qG;9H gq49G 7qG9d :Gq> 7G9qH;", -" q>Gg: qG;9M qG;M& qGT9; g49XM 7dXl9 q>Gl: 7G9qTd q>Gs: 9XqP X&qP q9XPB qa9", -"XP q91XP qX:P 9X1qPB :qaXP q9SX SXq& Sq9TX Sqa9X Slq9X :XSq lXqS9T sq:SX q9", -"XP( q+9XP 9XPq(B 9+XqaP 9X1qP( :q+XP 91q(XPB q+a:XP Sq9X( Sq+9X qTXS9( S9Xq", -"+T lXqS9( S:q+X l9qTSX( S:+sqX Yq9 Yq& qHY9 qHY& q9Y1 Y:q Yq91H Ya:q S9Yq S", -"&Yq Y9Zq Y&Zq lqY9 YqS: lYZq9 Y:sq qdY9 q+Y9 Yq9Hd g9Yq Yq91d Y+:q qH9Y1d Y", -":gq SqdY9 Yq+S9 ZqY9d gqZY9 lYq9d lY:q+ Zq9lYd glY:q q9oX oXq& oq9XB oqa9X ", -"7oq9X oq:X oq97XB o:qaX SXo9 Sq&oX oqT9X S9aoX r9X r:X 9TrX s:rX oq9X; oq+9", -"X q;Xo9B o9Xqa; oq97X; o:q>X 7Boq9X; q>ao:X Sq;9X Sq;X& S9XqT; S9Xo+T 9Xr; ", -">Xr: r;X9T r>Xs: oqY9 oqY& Y9oqH Yqao9 Y97q Yqo: 7Yq9H o:HYq Y9So Yq&So oZ9", -"Yq Zq&oY rY9 rY: YZr9 sYr: Y9vq Y&vq vqY9H vq&gY vq7Y9 vqY: 7Y9vqH go:Yq vq", -"YS9 vq&SY ZqvY9 vq&YZ Yvr9 Y:rv rZYv9 rYy: [q [q! [qD [qa [q1 [q8 qD[1 qD[8", -" [qM [Mq! Vq[ [aVq [lq q8[l [lVq sq[ [q( [q+ [(qD q+[a [(q1 q+[1 [q1D( [q+1", -"D [(qM [Mq+ V([q [qV+ l([q [ql+ Vql[( [+sq [qG [!qG Jq Jqa qG[1 qG[8 Jq1 Jq", -"8 [MqG [qGM! JqV qaVJ [qlG [lqG8 Jql sqJ [qd q+[d Jqd gqJ qd[1 q8[d qdJ1 g1", -"Jq [Mqd [q+GM VdJq gVJq [qld [l+qG ldJq sqg[ [q4 q![4 qD[4 qa[4 7[ 7[8 7[D ", -"7[a q4[M [q4M! [qV4 Vq[4a 7[l [87l 7V[ 7[s [q; q+[4 qD[; qa[; 7[; 7[> [;7D ", -"7D[> [Mq; [q+4M [qV; Vq+[4 l;7[ l>7[ V;7[ V>7[ qG[4 [q4G! Jq4 qaJ4 7[G [87G", -" 7Jq 7aJq [q4GM qGM[4! J4Vq JqV4a lG7[ 7[lG8 Jq7V 7Jsq qG[; [q+4G Jq; g4Jq ", -"7[d 7G[> 7dJq g7[ [qd4M [4Mq+G J;Vq Jq;gV ld7[ [>l7G l;Jq 7Vg[ [qP [Pq! [Pq", -"D [Pqa [Pq1 [Pq8 [q1DP [q8DP Sq[ S![q S[Vq [qSa Sq[l [qS8 SlV[q Sq[s qP[( [", -"Pq+ [qDP( [q+DP [q1P( [q+1P qDP[1( [1Pq+D S([q [qS+ Sq[V( Vq+S[ Sq[l( [l+Sq", -" [lSVq( sq[S+ Yq[ [!Yq JqY YaJq [qY1 [qY8 Y1Jq Y8Jq S[Yq Sq[Y! ]q ]qa [lYq ", -"Yq8[l ]lq ]qs [dYq [qY+ qdYJ gYJq Y1[qd Yq+[1 JqY1d Jq8gY [qSd Yq+S[ ]qd ]q", -"g lYq[d lY+[q ld]q gl]q o[q o![q [qoD [qoa 7[o o87[ 7Do[ 7ao[ Sqo[ Sq[o! Vq", -"o[ oVq[a r[ r[8 rV[ r[s [;oq [qo+ o[qD; o[+qD [;7o o[q> 7[oD; [>o7D [qS; o[", -"+Sq oVq[; oV+[q r[; r[> V[r; V>r[ o[Yq Yqo[! oJq oaJq 7[Y Y87[ oJ7[ Ya7[ Sq", -"[oY o[SYq! ]oq oq]a r[Y Y8r[ ]r ]rs vq[ [+vq Jqv oJgq 7[v 7[Y> vq7J 7[go Sq", -"[v vq[S+ ]qv go]q r[v Y>r[ ]rv ]yr tq[ [q& qD[t cq[ [1tq [:q tq[1D [:cq tM[", -"q [Mq& V[tq [cVq tq[l [l:q Vql[t uq[ t([q [qt+ tq[D( [+cq tq[1( [+:q [1Dtq(", -" cq[:+ tq[M( tq+[M Vq[t( cqV[+ [lqt( [:lq+ [ltVq( [qu+ tqG [&qG Jqt cqJ t1q", -"G tG:q J1tq :Jq tMqG tqGM& VqtJ cJVq tqlG [:lqG ltJq uJq [qtd q+tG tdJq cqg", -"[ tqG1d [q:d Jqt1d :Jgq tqGdM tq+GM JqVtd cqJgV [ldtq [:dlq Jqltd gquJ t4[ ", -"[&t4 tD[4 t4[c 7[t 7[: [t7D 7[c tM[4 t4[M& V[t4 cqV[4 [l7t l:7[ V[7t u7[ [q", -"t; [4t+ tq;[D [qc; t;7[ 7[t> 7[tD; [>7c tq;[M t4[+M Vq;[t cq;V[ [l;7t [>l7t", -" 7V[t; 7[u> [4tG tqG4& t4Jq c4Jq tG7[ 7G[: tJ7[ :J7[ tqG4M t4MqG& JqVt4 cqJ", -"V4 7tG[l 7[:lG Jql7t 7Juq [4td tq+4G t;Jq t4g[ td7[ tGq> Jq;7t 7[gt tqGM; t", -"4M[d& Jq;Vt cqJV; 7[dlt [:d7l Jqlt; g7u[ [qtP [Pq& tq[DP [qcP tq[1P [q:P [q", -"1tPD cq[:P tqS[ [qS& Sq[Vt Sq[c Sq[lt Sq[: VqlSt[ Squ[ tq[P( tq+[P [qDtP( c", -"q[+P [q1tP( [:q+P t1qD[P( [:+cqP Sq[t( St+[q Vq[St( Scq[+ [lqSt( S:[q+ SlVq", -"[t( uS+[q tYq Y&tq JqtY Ycq Y1tq Yq[: JqtY1 cqY: YqSt Yq&St ]qt ]qc ltYq lY", -"t:q lt]q ]uq tdYq t+Yq JqtYd tYgq tYq1d [:dYq tY1Jqd g[:Yq StdYq tY+Sq tq]d", -" gq]t lYtqd [:dSq ]lqtd ]qug ot[ [qo& [toD o[cq ot7[ o:[ ot7[D oc7[ o[St ot", -"[S& V[ot oVt[c r[t r[: V[rt ur[ t;o[ t+o[ ot[D; otc[+ ot7[; [>ot 7[Dot; cq>", -"o[ ot[S; ot+S[ oVt[; oVt[+ t;r[ t>r[ rV[t; r[u> tYo Y&ot oJt otYc tY7 7[Y: ", -"7JtY 7[Yc SotY tYoS& ]ot ot]c rtY tYr: ]rt ur] vqtY Y+ot oJtv tYgo 7[tv 7Yt", -"> oJt7v tYg7 vq[St ot+SY tv]o go]t tYrv tYr> rt]v ]yur w w! wB wa w. w8 w.B", -" w8a wK w!K wT wTa wj w8j wTj sw w* w+ w*B w+a w*. w+8 *Bw. 8*wa w*K w+K wT", -"* w+T wj* w+j T*wj sw+ wG w!G wH wHa wG. w8G wH. wH8 wGK GKw! wHT GTwa wjG ", -"G8wj wHj swG fw fw+ fwH gw fw. fw8 f.wH gw8 fwK fKw+ fwT gwT fwj w+fj wHfj ", -"gws w4 w!4 w4B wa4 w5 w58 w5B w5a w4K 4Kw! wT4 4Twa w5j 48wj w5T sw4 w= w=+", -" w=B =aw w=5 w> =Bw5 w>a w=K =Kw+ =Tw w+=T =jw w>j w5=T sw> w4G 4Gw! wH4 4G", -"wa w5G 4Gw8 wH5 4Hw8 4GwK w!4GK 4GwT wH4Ta 4Gwj w5G8j 4Hwj wHs4 fw= w+f= =H", -"w gw= fw5 w>f wHf5 gw> =Kfw fw=+K fw=T =Tgw fw=j fjw> wH=j s=gw wP w!P wPB ", -"waP wP. w8P P.wB 8Pwa wQ wQ! wQT wQa wQj wQ8 TPwj swQ wP* w+P P*wB +Pwa P*w", -". +Pw8 wP*.B w+a8P wQ* w+Q Q*wT +QwT Q*wj +Qw8 wQT*j w+sP Yw Yw! YwH Ywa Yw", -". Yw8 Y.wH wHY8 YwQ Y!wQ Zw Zwa Ywj wQY8 Zwj sYw Yfw Yw+ wHYf gwY Y.fw fwY8", -" YfwH. Y8gw fwQ w+fQ Zwf gwZ fwYj w+Yj fjZw sYgw ow ow! owB owa ow5 ow8 oBw", -"5 w5oa owQ o!wQ owT wQoa pw pw8 pwT swo ow= ow+ =Bow ow=a w5o= w>o ow=5B oa", -"w> =Qw w+=Q ow=T w+oT pw= pw> =Tpw pws= Ywo o!Yw owH owYa Yw5 owY8 wHY5 wHo", -"8 wQoY YwoQ! Zwo oaZw pwY Y8pw Zwp osZw x x+ xH xg x5 x> xH5 xg> xQ x+Q xZ ", -"xZg xp xp> xZp yx w, w& w,B wa& w,. w8& ,.wB ,8wa w,K w&K wT, wT& wj, w&j ,", -"Twj sw& w*, -w *Bw, -wa ,*w. -w8 w*,.B -8wa ,*wK -wK ,Tw* -wT ,jw* -wj wT*,", -"j sw- wG, w&G wH, wH& ,Gw. ,Gw8 ,Hw. ,Hw8 ,GwK G&wK ,GwT GTw& ,Gwj G&wj ,Hw", -"j wHs, fw, -wf f,wH gw- w,f. f8-w fwH,. w8g- w,fK fK-w f,wT fT-w f,wj fj-w ", -"fwT,j s-gw w4, w&4 ,4wB ,4wa w5, w5& ,5wB ,5wa ,4wK 4&wK ,4wT 4Tw& ,4wj 4&w", -"j ,5wT w5s, w=, -w= w,=B =a-w =,w5 w>- w=5,B wa-> w,=K =K-w =,wT =T-w =,wj ", -"=j-w =Tw,5 s-w> ,4wG 4Gw& ,4wH 4Hw& ,Gw5 G5w& ,Hw5 H5w& w4G,K w&4GK wH4,T w", -"H&4T w5G,j w5&Gj wH5,T sw4,G =,fw f=-w =,wH -wg= f,w5 -wf> =Hw,5 g-w> fw=,K", -" -wf=K =Hw,T -wTg= fw5,j w>f-j =Hw,j gws-> wP, w&P ,PwB ,awP ,Pw. ,8wP wP,.", -"B w8a,P wQ, wQ& ,QwT ,Qwa ,Qwj ,Qw8 wQT,j wQs, ,Pw* -wP wP*,B wa-P wP*,. w8", -"-P P*.w,B -w8aP ,Qw* -wQ wQT,* wQ-T wQ*,j wQ-j P*jwT, sP-w Yw, Yw& wHY, wHY", -"& w,Y. w8Y& YwH,. Yw8,H wQY, wQY& Zw, Zw& wjY, w&Yj wjZ, s,Zw fwY, Y-w Yfw,", -"H Y-gw Yfw,. Y8-w fwHY,. gwY-8 f,wQ fQ-w fwZ, Z-w Yfjw, Yj-w Zwf,j Y-sw ow,", -" ow& w,oB wao& w5o, w5o& ow5,B ow8,a wQo, wQo& wTo, wTo& pw, pw& wTp, s,pw ", -"w=o, o-w ow=,B oa-w ow=,5 w>o- w=5o,B o-w>a =,wQ =Q-w owT=, oT-w w=p, -pw p", -"w=,T o-sw Y,o owY& oHY, oaY, o,Y5 o8Y, Yw5,H Yw5,a YQo, Yw&oQ Y,oZ owZ& Y,p", -"w Y&pw Z,pw Y,os x, x- x,H xg- x,5 x-> ,Hx5 g-x> x,Q x-Q xZ, xZ- xp, xp- Zp", -"x, yx- wI w!I wD wDa wI. w8I wD. wD8 wIK IKw! wDT TIwa wjI 8Iwj wDj swD wI*", -" w+I wD* w+D I*w. +Iw8 D*w. +Dw8 I*wK +IwK D*wT +DwT I*wj +Iwj D*wj w+sI wG", -"I GIw! Jw Jwa GIw. G8wI Jw. Jw8 GIwK w!GIK JwT JTwa GjwI w8GIj Jwj swJ fwI ", -"fIw+ Jwf gwJ wIf. fIw8 J.fw J8gw wIfK fw+IK fTJw wTgJ fIwj fw8Ij fwJj sJgw ", -"w4I 4Iw! wD4 4Dwa w5I 48wI w5D 4Dw8 4IwK w!4IK 4DwT wD4Ta 4Iwj w58Ij 4Dwj w", -"5sI =Iw w+=I =Dw w+=D w5=I w>I w5=D w>D wI=K =Iw+K wD=T =Dw+T wj=I >Iwj wD=", -"j =Dsw 4GwI w!4GI Jw4 waJ4 G5wI w5G8I Jw5 w5J8 w4GIK 4GIw!K wTJ4 Jw4Ta w5GI", -"j 4G8wjI w5Jj s4Jw fw=I =Ifw+ J=w J=gw fIw5 >Ifw fwJ5 J>w =IfwK fw+=IK =TJw", -" J=gwT =Ijfw w>fIj =jJw J>sw wIP IPw! wDP DPwa IPw. 8IwP DPw. D8wP wQI QIw!", -" wQD QDwa QIwj Q8wI QDwj wQsI IPw* +IwP DPw* +DwP IP*w. w+8IP wDP*. w+D8P Q", -"Iw* +QwI QDw* +QwD wQI*j w+Q8I wQD*j sw+QD YwI w!YI JwY YaJw wIY. YIw8 Y.Jw", -" Y8Jw YIwQ YwQI! ZwJ waZJ YIwj Yw8QI YjJw sJZw YIfw YIw+ YfJw JwgY YfwI. Yf", -"8wI YJfw. Jw8gY fIwQ Yw+QI JwZf gZJw YfjwI Yw+Ij JwjZf gwZsJ owI w!oI owD w", -"Doa w5oI w8oI w5oD wDo8 wQoI owQI! wQoD owDQa pwI w8pI pwD sIpw =Io o+=I ow", -"=D oa=I =5oI =Io> owD=5 oDw> oI=Q ow+QI oT=I ow+QD =Ipw pIw> =Dpw =Ios oIYw", -" YwoI! oJw oaJw YIw5 Yw58I Y5Jw o8Jw YwoQI oIQYw! oJZw oJZwa pIYw pwY8I Jpw", -" oJsw xI x+I xJ xJg x5I x>I xJ5 xJ> xQI +QxI xZJ gZxJ xpI p>xI xJp yxJ hw h", -"w& hwD cw hw. hw8 h.wD cw8 hwK hKw& hwT cwT hwj w8hj wDhj hsw hw* -wh h*wD ", -"cw- w*h. h8-w hwD*. w8c- w*hK hK-w h*wT hT-w h*wj hj-w hwT*j s-cw hwG hGw& ", -"Jwh cwJ wGh. hGw8 h.Jw h8Jw wGhK hwG&K hTJw wTcJ hGwj hw8Gj hjJw sJcw hfw h", -"f-w hfJw iw h.fw fwh8 Jwhf. iw8 hKfw -whfK fwhT iwT fwhj -wjhf Jwjhf isw hw", -"4 w&h4 wDh4 cw4 hw5 w5h8 wDh5 cw5 w4hK hw4&K wTh4 wTc4 w5hj hw5&j w5hT h4sw", -" h=w -wh= hw=D cw= w=h5 h>w h=w5D cw> =Khw h=-wK hw=T =Tcw hw=j hjw> h=Tw5 ", -"swh> w4hG hw4G& h4Jw c4Jw hGw5 hw5G8 h5Jw c5Jw hw4GK w&Gh4K Jwh4T cwJ4T hw5", -"Gj h4Gw&j Jw5hT cw5sJ fwh= h=f-w Jwh= iw= fwh5 hfw> J=hw5 iw> h=fwK -wfh=K ", -"J=hwT =Tiw h=jfw h>wfj J=jhw swi> hwP w&hP wDhP cwP wPh. w8hP hwDP. w8cP hw", -"Q w&hQ wQhT cwQ wQhj wQh8 hwQDj hQsw wPh* hP-w hwDP* cP-w hwP*. -wh8P wD*hP", -". cw-8P h*wQ hQ-w hwQD* cQ-w hwQ*j -wQh8 hQ*wDj cwQs- hYw Y&hw JwhY Ycw h.Y", -"w Ywh8 hYJw. Y8cw YwhQ hYwQ& hZw Zwc Ywhj hY8wQ hjZw swhZ Yfhw -whY hYJfw i", -"Yw hYfw. hY8-w JwfhY. Ywi8 fwhQ -wQhY hfZw iZw hYjfw Y-jhw hZwfj sYiw oh oh", -"& ohD ohc oh5 oh8 oDh5 h5oc ohQ o&hQ ohT hQoc hpo h8pw hTpw hso oh= oh- =Do", -"h c=oh o=h5 h>o oh=5D och> =Qoh hQo- =Toh =Qcw h=pw o-hp ohTp= ohs= ohY Y&o", -"h oJh ohYc Ywh5 Y8oh h5oJ h8oJ oYhQ ohYQ& hZo ochZ hYpw oh8Yp Zwhp oJhs xh ", -"xh- xJh ix xh5 xh> hJx5 ix> xhQ h-xQ xZh ixZ xph hpx- hZxp ixy w6 w!6 w6B w", -"a6 w1 w18 w1B w1a w6K 6!wK wT6 6Twa w1j 68wj w1T sw6 w6* w+6 6*wB 6+wa w1* ", -"w1+ 1*wB 1+wa 6*wK 6+wK 6Tw* 6+wT 6*wj 6+wj 1Tw* w1s* w6G 6Gw! wH6 6Gwa w1G", -" 6Gw8 w1H 6Hw8 6GwK w!6GK 6GwT wH6Ta 6Gwj w1G8j 6Hwj w1sG fw6 w+f6 wHf6 gw6", -" fw1 w1f8 wHf1 gw1 w6fK fw6+K wTf6 wTg6 w1fj fw1+j w1fT g6sw w46 6!w4 46wB ", -"4aw6 7w 7w8 7wB 7wa 46wK w!46K 4Tw6 wT46a 7wj 78wj 7wT sw7 w=6 =6w+ w6=B =6", -"wa 7w= w>7 =B7w =a7w w6=K w=6+K =6wT =Tw6+ =j7w wj7> =T7w 7sw> 4Gw6 w!46G 4", -"Hw6 wH46a 7wG w87G 7wH wH7a w46GK 4G6w!K wH46T 4GTwa6 wj7G 7wG8j wH7T sG7w ", -"w=f6 fw=6+ =6wH w=g6 7fw w>7f =H7w g7w fw=6K w=+f6K =Hw6T gw=6T fj7w w>7fj ", -"fw7T swg7 w6P 6Pw! 6PwB 6awP w1P 68wP 1PwB 1awP wQ6 6Qw! 6QwT 6Qwa w1Q 6Qw8", -" 1QwT w1sP 6Pw* 6+wP w6P*B w+6aP 1Pw* 1+wP w1P*B w1+aP 6Qw* 6+wQ wQ6T* w+Q6", -"T 1Qw* 1+wQ w1QT* sw6+Q Yw6 w!Y6 wHY6 waY6 Yw1 w1Y8 wHY1 w1Ya wQY6 Yw6Q! Zw", -"6 waZ6 w1Yj Yw1Q8 Zw1 s6Zw Yf6 f6Y+ YHf6 Yfg6 fwY1 f6Y8 Yf61H Ywg1 fQY6 Yf6", -"+Q Y6Zf g6Zw f6Yj Yf6+j fwZ1 g1Zw ow6 w!o6 w6oB o6wa 7wo o87w 7Bow ow7a o6w", -"Q ow6Q! o6wT owT6a pw7 w87p 7Tpw 7spw =6ow o6w+ ow=6B ow+6a ow7= o>7w 7o=wB", -" w>o7a =6wQ ow+6Q owT=6 ow+6T p=7w 7pw> pw7=T pw>7s owY6 Ywo6! o6wH Ywao6 7", -"Yw Y87w 7HYw Ya7w Ywo6Q owQY6! owZ6 Zwo6a pw7Y pw7Y8 7Zw 7Zsw x6 x6+ x6H xg", -"6 x7 x7> x7H xg7 x6Q 6+xQ xZ6 gZx6 xp7 7px> xZ7 yx7 ?w ?w& ?wB ?wa ?w1 :w ?", -"Bw1 :wa ?wK ?Kw& ?wT wT?a ?wj :wj w1?T s?w ?w* -w? w*?B ?a-w ?*w1 :w- ?w1*B", -" wa:- w*?K ?K-w ?*wT ?T-w ?*wj ?j-w ?wT1* s-:w ?wG w&?G ?wH wH?a w1?G :wG w", -"1?H :wH wG?K ?wG&K wH?T ?wHT& wj?G wj:G wH?j sG:w ?fw -w?f fw?H g?w f1?w :f", -"w ?wHf1 gw: ?Kfw ?f-wK fw?T ?Tgw fw?j fj:w ?fTw1 s?gw ?w4 ?4w& w4?B ?4wa 7w", -"? :w7 7B?w ?a7w w4?K ?w4&K ?4wT ?wT4a ?j7w wj7: ?T7w 7s:w ?w= ?=-w =B?w ?w=", -"a ?=7w Aw ?w=7B Awa =K?w ?w=-K ?w=T -wT?= ?w=j Awj 7wT?= Asw w4?G ?w4G& ?4w", -"H ?wH4a ?G7w 7G:w ?H7w 7H:w ?w4GK w&4?GK ?wH4T ?G4wT& ?wj7G :w7Gj 7wH?T :wH", -"7s fw?= ?w=f- ?w=H ?wg= 7w?f Afw 7wH?f Agw ?w=fK -w=?fK ?fTw= g?w=T ?fj7w f", -"wAj 7fT?w gwAs ?wP w&?P wP?B wa?P w1?P :wP ?w1PB wa:P ?wQ w&?Q wQ?T wQ?a w1", -"?Q :wQ ?wQ1T sP:w wP?* ?P-w ?wP*B ?-Pwa ?w1P* :P-w w1*?PB :w-aP ?*wQ ?Q-w ?", -"wQT* -wQ?T ?wQ1* :Q-w ?Q*w1T :wQs- ?Y ?Y& ?YH ?Ya ?Y1 ?Y: Y1?H ?HY: ?YQ Y&?", -"Q ?ZY ?aZw ?Yj ?QY: ?jZw s?Y ?Yf ?Y- Yf?H g?Y Y1?f :f?Y ?Yf1H Y:g? Yf?Q ?QY", -"- ?fZw ?Zgw Yf?j ?jY- ?ZYf1 sYg? o?w o&?w ?Bow ow?a o?7w :wo 7wo?B oa:w ow?", -"Q ?wQo& ow?T o?Twa ?pw :wp ?Tpw ?psw ow?= -wo? ?w=oB o-?wa ?w=7o Aow o?=7wB", -" owAa ?w=Q o-?wQ o?Tw= o-T?w ?wp= Apw ?pw=T swAo ?Yo Y&o? oY?H Yao? ?Y7 :w7", -"Y ?H7Y ?a7Y oY?Q ?YoQ& o?Zw ?ZoYa ?pY Y:?p 7Z?Y ?psY x? x?- x?H x?g x?7 Ax ", -"?Hx7 Axg x?Q ?-xQ x?Z g?xZ x?p Axp ?Zxp Axy w6I 6Iw! wD6 6Dwa w1I 68wI w1D ", -"6Dw8 6IwK w!6IK 6DwT wD6Ta 6Iwj w18Ij 6Dwj w1sI 6Iw* 6+wI 6Dw* 6+wD 1Iw* 1+", -"wI 1Dw* 1+wD w6I*K w+6IK wD6T* w+D6T w1I*j w1+Ij w1DT* sw6+D 6GwI w!6GI Jw6", -" waJ6 1GwI w1G8I Jw1 w1J8 w6GIK 6GIw!K wTJ6 Jw6Ta w1GIj 6G8wjI w1Jj s6Jw w6", -"fI fw6+I fwJ6 g6Jw fIw1 fw1+I fwJ1 g1Jw fw6IK w+If6K Jwf6T gwJ6T fw1Ij f6Iw", -"+j Jw1fT gwsJ6 4Iw6 w!46I 4Dw6 wD46a 7wI w87I 7wD wD7a w46IK 4I6w!K wD46T 4", -"TIwa6 wj7I 7w8Ij wD7T sI7w w6=I =Iw6+ =6wD =Dw6+ =I7w 7Iw> =D7w 7Dw> =Iw6K ", -"w+6=IK =Dw6T =D6w+T 7w=Ij w>7Ij 7wD=T w>D7s w46GI 4G6w!I w4J6 Jw64a wG7I 7w", -"G8I 7Jw 7aJw 4G6wIK 6!w4GIK Jw64T wT4J6a 7wGIj w8G7Ij 7TJw 7Jsw =Ifw6 fw6=I", -"+ w=J6 J=gw6 fw7I w>7fI 7wJ= 7Jgw fw6=IK =6w+fIK J=w6T gw6J=T 7fwIj 7fIw>j ", -"J=j7w J>w7s 6IwP w!6IP 6DwP wD6aP 1IwP w18IP 1DwP w1D8P 6QwI wQ6I! 6QwD wQD", -"6a 1QwI w1Q8I 1QwD sw6QD IP6* w+6IP wD6P* w+D6P w1IP* w1+IP w1DP* w1+DP wQ6", -"I* w+Q6I wQD6* w+Q6D w1QI* w1+QI w1QD* sIP6* w6YI Yw6I! Y6Jw YJ6wa YIw1 Yw1", -"8I Y1Jw Jw1Y8 Yw6QI wQIY6! Z6Jw ZwJ6a Yw1QI Y6IwQ8 Z1Jw sYwJ6 YIf6 Yf6+I Jf", -"Y6 gY6Jw Yf61I Yf68I Jw1Yf gw1YJ Yf6QI Y6Iw+Q Zf6Jw gwZJ6 Yf6Ij Y6IfQ8 Zw1J", -"f gwZJ1 w6oI ow6I! o6wD owD6a ow7I 7oIw8 ow7D 7wDo8 ow6QI wQ6oI! owD6Q oD6w", -"Qa 7Ipw pw78I 7Dpw osI7w =6oI ow+6I owD=6 ow+6D 7o=I w>o7I 7wDo= w>D7o =Qw6", -"I o+6=QI oTI=6 o+6=TI pw7=I pw>7I pwD7= osI7= Ywo6I owIY6! J6ow oJw6a 7IYw ", -"7Yw8I 7woJ oJ87w owQY6I o!Yw6QI oJZw6 Zw6oJa pw7YI 7Y8pwI Zw7J oJs7w x6I 6+", -"xI xJ6 gJx6 x7I 7>xI xJ7 g7xJ 6QxI x6+QI ZJx6 xZJg6 7pxI xp7>I 7ZxJ x7yJ h?", -"w w&h? ?wD cw? hw1 :wh w1?D :wc ?Khw ?w&hK ?whT ?Tcw ?whj hj:w w1hT :whs h*", -"?w h?-w ?*wD -w?c h*w1 -wh: ?wD1* :c-w ?w*hK -w?hK ?wDT* cw?-T ?wjh* :wh-j ", -"?wD*j :wcs- ?Ghw ?wGh& ?Jw cw?J hGw1 :Ghw h1Jw :Jw ?wGhK hw&?GK ?TJw cw?JT ", -"?wjhG :whGj ?jJw ?Jsw hw?f ?fh-w Jw?f i?w fwh1 hf:w Jw1?f i:w ?fhwK -wh?fK ", -"?fTJw ?wiT ?fjhw :fwhj ?Jjfw s?iw ?wh4 ?w4h& ?4wD c4?w 7hw :w7h ?D7w 7cw ?w", -"4hK h4&?wK ?wD4T cw?4T hj7w :w7hj hT7w 7hsw ?wh= ?w=h- ?w=D ?wc= 7wh= Ahw 7", -"wDh= Acw ?w=hK -w?h=K h=T?w cw=?T h=j7w hwAj 7hTw= hsAw ?w4hG hw4?G& J4?w c", -"w?J4 7Ghw :w7hG 7w?J :w7J hw4?GK hGw&?4K ?Jw4T ?J4cwT 7hwGj 7hG:wj ?J7wT hs", -"7Jw ?w=hf ?f-h=w ?wJ= ?wi= hf7w hfAw ?J7fw Aiw ?fwh=K =K?f-wh ?J=wT i?w=T 7", -"hfwj Ahjfw J=j?w isAw h?P h&?P ?DhP hP?c ?Ph1 hP:w ?wD1P :Pcw ?whQ ?wQh& ?T", -"hP ?Qcw ?Phj hQ:w ?wQ1D hPs? h*?P ?-hP ?wDP* cw?-P h?P1* :wh-P ?D*h1P :wc-P", -" ?wQh* -wQh? ?wQD* cwQ?- ?Pjh* :wQh- ?Q*w1D :wc-Q ?Yh Y&h? ?JY ?Yc h1?Y hY:", -"w Y1?J Y:?J hQ?Y ?YhQ& ?YhZ Yc?Z hj?Y :wQhY h1Zw ?JsY ?fhY h?Y- YJ?f i?Y hY", -"1?f ?Y:hf ?JYf1 ?Yi: ?fQhY ?Y-hQ hZ?Yf ?ZiY ?Yjhf :wQhf hZwf1 s?iY oh? o&h?", -" ?Doh ?coh 7ho oh: 7Doh oh7c hQo? oh?Q& hTo? ohc?Q oh?p :whp ?Dpw ohs? o?h=", -" h?o- oh?=D ohc?- 7oh= Aoh 7ho=D ohAc oh?=Q oh-?Q ohT?= oh-?T hpo?= hpAo oh", -"T7= hsAo oh?Y oh?Y& ?Jo oc?J 7hY 7hY: 7J?Y 7hYc oh?YQ ?YQoh& oJ?Z hZo?c ?Yh", -"p :wphY 7YhZ Yc?p x?h h?x- x?J ix? x7h Axh ?Jx7 Aix h?xQ x?h-Q hZx? x?iZ hp", -"x? xpAh hZx7 yAix wR w!R wRB waR wR. w8R R.wB R8wa wM wM! wTR waM wMj w8M R", -"Twj swR wR* w+R R*wB R+wa R*w. R+w8 wR*.B w+R8a wM* w+M RTw* R+wT R*wj R+wj", -" wTR*j w+sR wRG RGw! wHR RGwa RGw. RGw8 RHw. RHw8 wMG GMw! wHM GawM RGwj G8", -"wM RHwj wHsR fwR w+fR wHfR gwR wRf. w8fR fwRH. w8gR fwM w+fM wHfM gwM wMfj ", -"w8fM fwTRj gRsw wR4 R4w! R4wB R4wa w5R R4w8 R5wB R5wa wM4 4Mw! R4wT 4awM w5", -"M 48wM R5wT w5sR =Rw w+=R wR=B wa=R w5=R w>R =Rw5B >Rwa =Mw w+=M wT=R wa=M ", -"w5=M w>M =RTw5 >Msw R4wG w!R4G R4wH wHR4a RGw5 w5RG8 RHw5 wH5R8 4GwM wM4G! ", -"4HwM wHM4a G5wM w5MG8 H5wM swR4G =Rf =+fR fR=H =Rgw f5=R =Rf> =RfH5 gRw> fw", -"=M =Rf+M fR=T =Mgw fR=j fw>M =RfHj >Mgw wRP RPw! RPwB RawP RPw. R8wP wRP.B ", -"w8RaP Sw Sw! SwT Swa Swj Sw8 STwj swS R*wP R+wP wRP*B w+RaP wRP*. w+R8P P*.", -"wRB aP*w8R Sw* Sw+ wTS* w+Sa wjS* w+S8 SwT*j s*Sw YwR w!YR YRwH YRwa wRY. Y", -"Rw8 YwRH. Yw8RH SwY S!Yw ZwS SaZw YjSw YwS8 wjSZ SsZw fRYw YRw+ YfwRH YwgR ", -"YfwR. Yf8wR fRHYw. gwYR8 Sfw YwS+ ZwSf gwS fjSw fwS8 SfZwj swgS owR w!oR wR", -"oB oRwa oRw5 oRw8 owR5B ow8Ra Swo S!ow oTSw owSa pwS S8pw wTSp Sspw ow=R oR", -"w+ ow=RB ow+Ra ow=R5 >Row =R5owB w>oRa S=w owS+ =TSw =aSw pwS= S>w pw=ST S>", -"sw YRow YwoR! oRwH YwaoR YRw5 Yw5R8 Yw5RH Yw5Ra YwSo SwoY! oZSw SwaoZ YpSw ", -"pwYS8 SZpw sYoSw xR xR+ xRH xgR xR5 x>R RHx5 g>xR xS xS+ xZS xgS xpS x>S SZ", -"xp yxS wR, w&R ,RwB ,Rwa ,Rw. ,Rw8 wR,.B w8R,a wM, wM& ,RwT ,awM ,Rwj ,8wM ", -"wTR,j wMs, ,Rw* -wR wR*,B wa-R wR*,. w8-R ,R*w.B -wR8a ,Mw* -wM wTR,* wT-R ", -"wM*,j w8-M ,RTwj* sR-w ,RwG RGw& ,RwH RHw& wRG,. w8R,G wHR,. wH8,R ,GwM GMw", -"& ,HwM HMw& wMG,j w8M,G wHM,j swR,G wRf, fR-w fwR,H gR-w fwR,. -wfR8 wH,fR.", -" gw-R8 f,wM fM-w fwT,R gM-w fwM,j -wMf8 fR,wHj gws-R ,Rw4 R4w& wR4,B waR,4 ", -",Rw5 R5w& w5R,B w5a,R ,4wM 4Mw& wTR,4 wT&R4 ,5wM 5Mw& w5T,R swR,4 wR=, =R-w", -" =Rw,B -w=Ra =Rw,5 -Rw> w5,=RB w>-Ra =,wM =M-w =RTw, -wT=R =Rjw, >M-w =R,w5", -"T w>Ms- R4,G w&R4G wHR,4 wH&R4 w5R,G w5&RG wH5,R wH5R& wM4,G wM&4G wHM,4 wH", -"M4& w5M,G w5MG& wH5,M wH5M& =,fR f-=R =Rf,H g=R-w =Rf,5 w>f-R =R,wH5 gw>-R ", -"=Rf,M -wMf= =Rf,T gwM-= =Rf,j w>Mf- =R,f5T w>Mg- ,RwP R&wP wRP,B waR,P wRP,", -". w8R,P ,RPw.B ,R8waP Sw, Sw& wTS, wTS& wjS, w8S& SwT,j s,Sw wRP,* wR-P P*B", -"wR, -wRaP P*.wR, -wR8P ,RwBP*. w8R-Pa w*S, S-w SwT,* Sa-w Sw*,j S8-w wT*S,j", -" S-sw wRY, YRw& YwR,H Ywa,R YwR,. Yw8,R wHRY,. Y8RwH& YwS, YwS& S,Zw S&Zw S", -"Y,wj Sw8Y& ZwS,j sYwS& Yfw,R -RYw fwRY,H gwY-R fwRY,. Y-wR8 ,Hw.YfR Y-Rgw8 ", -"fwS, SwY- SfZw, S-gw Sfw,j Sf-w8 ZwjSf, gwSs- wRo, oRw& owR,B owa,R owR,5 o", -"w8,R w5Ro,B oaRw5& owS, owS& Swo,T Swao& S,pw S&pw pwS,T os,Sw ow=,R -Row =", -"R,owB o-wRa =R5ow, o-w>R =Bow,R5 w>Ro-a w=S, Swo- S=w,T o-TSw pw=S, pwS- S=", -"Tpw, os-Sw YRo, Yw&oR Y,oRH Yao,R Yw5,R Yw5R& Y5RoH, Y5Roa, Y,So Sw&oY oZ,S", -"w Zw&So pwYS, pw&SY ZwpS, os,SY x,R x-R ,RxH g-xR ,Rx5 ->xR x,RH5 xg->R xS,", -" x-S SZx, gSx- Spx, S-xp xZpS, y-xS [w [w! [wD [wa [w. [w8 w.[D [8wD [wM [!", -"wM Vw Vwa [wj [8wM Vwj swV [w* [w+ [*wD wD[+ w.[* w8[+ [wD*. [w+D8 [*wM wM[", -"+ Vw* Vw+ [*wj wj[+ wjV* s*Vw [wG wG[! Jw[ wa[J w.[G wG[8 J.[w [wJ8 [GwM [w", -"GM! VwJ waVJ wG[j [w8GM JjVw sJVw [fw w+[f [fJw g[w f.[w [wf8 Jw[f. w8g[ [w", -"fM [fw+M Vfw gwV [wfj [f8wM fjVw swg[ [w4 w![4 wD[4 wa[4 [w5 w8[4 [5wD wa[5", -" wM[4 [w4M! Vw4 waV4 wM[5 [w58M Vw5 s4Vw [= [=+ [=D [=a [=5 [>w [5=D =D[> [", -"=M [+=M Vw= =aVw [=j >M[= =jVw s=[ wG[4 [w4G! [wJ4 Jw[4a wG[5 [w5G8 [wJ5 Jw", -"5[8 [w4GM wMG[4! J4Vw VwJ4a [w5GM [4Gw8M J5Vw Vw5sJ [=f [+f= J=[ g[= f5[= f", -">[= J5[= [>gw =M[f [=f+M VwJ= V=g[ =j[f [>f=M Jj[= s=g[ [wP wP[! wP[D wP[a ", -"[Pw. wP[8 [wDP. [w8DP Sw[ S![w VwS SaVw wjS[ [wS8 wjSV SsVw wP[* wP[+ [wDP*", -" [w+DP [wP*. [w+8P [*PwD. [+PwD8 [wS* [wS+ S*Vw S+Vw S[*wj Sw+[8 VwS*j Vw+S", -"s Yw[ [!Yw [JYw [wYa Y.[w [wY8 Yw[J. Jw8[Y YwS[ Yw[S! ]w ]wa [wYj Sw8[Y ]wj", -" ]sw Yw[f [wY+ YJf[w Ywg[ Yw[f. [f8Yw [fYJw. g[wY8 [fSw Sw+[f ]fw ]gw [fjSw", -" Sf8[w fw]j gw]s o[w o![w [woD [woa w5o[ [wo8 o[w5D o[8wD o[Sw Swo[! oVw oa", -"Vw pw[ w8[p Vwp oVsw [=o o+[= =Do[ =ao[ [5o= o[w> [=o5D [>o=D S=[ S+[= VwS=", -" S[=a [p= [>S= pwV= VwS> Ywo[ Yw[o! Jwo[ oJ[wa [wY5 o[8Yw oJ[w5 oJ8[w Yw[So", -" o[YSw! ]ow ow]a Yw[p pw[Y8 ]pw sw]o x[ x[+ xJ[ xg[ x[5 x[> J5x[ g[x> x[S S", -"[x+ ]x ]xg xp[ S>x[ ]xp ]yx hw[ [w& wD[h cw[ h.[w [wh8 hw[D. w8[c hwM w&hM ", -"Vwh cwV [whj w8hM hjVw Vwhs [*hw [-w hw[D* [-cw hw[*. w8[- wD*[h. cw[-8 h*w", -"M hM-w V*hw V-w hwM*j [w-j Vwh*j V-sw hG[w wG[& [Jhw [cJw hw[G. hw8[G Jw[h.", -" cwJ[8 hGwM hwMG& VhJw cJVw hwMGj hw8GM VwJhj cwVsJ hw[f [f-w Jw[hf i[w [fh", -"w. [-fw8 [fhJw. [wi8 fwhM [-fwM hfVw iVw [fjhw [-jfw Vfwhj swiV h4[ w&[4 hD", -"[4 h4[c [wh5 [4h8 hw5[D [wc5 [4hM hwM4& h4Vw c4Vw [4hj hw58M h5Vw h4[s [=h ", -"[-= [h=D c=[ h5[= w>[- [=h5D [>cw hw=M =M[- h=Vw Vwc= hj[= =j[- Vw=h5 Vwh> ", -"hG[4 h4[G& [Jh4 cwJ[4 hw5[G h4[G8 Jw5[h cw5[J hwM4G h4GwM& VwJh4 cwVJ4 hw5G", -"M h4Gw8M Vw5hJ cwVJ5 [fh= f-[= hJ[= i[= [=hf5 [-=f> J=[h5 [>iw [=hfM [-=fM ", -"J=Vhw Vwi= [=jhf [-=fj J=[hj s=i[ [whP wP[& hw[DP [wcP hw[P. hw8[P hPD[w. c", -"w[8P Shw S&hw VwSh Scw hjSw h8Sw VwhSj Shsw hw[P* [w-P hPD[w* cw[-P hP*[w. ", -"[-w8P h*wD[P. [-8cwP S*hw Sw[- VwhS* cwS- Shw*j [-jSw Sh*Vwj V-wSs [hYw [wY", -"& hYJ[w Yw[c hY[w. hY8[w Jw[hY. Ycw[8 SwhY Sw&hY ]hw ]cw hYjSw Sh8Yw hw]j h", -"s]w hY[fw Yw[- Jw[hYf Ywi[ [fwhY. Y-[w8 h.Jw[fY i[Yw8 hfSw Shf-w hf]w ]iw S", -"hfwj [-jYw ]hfwj iw]s oh[ [ho& [hoD o[cw h5o[ h8o[ oh[5D ohc[5 Sho S&oh oVh", -" ohSc pwSh Soh8 oVhp oVhs [=oh o-[ oh[=D [-oc oh[=5 [>oh [=5ohD cw>o[ Sh= o", -"hS- V=Sh cwS= S=hp S=h> oVhp= Shs= o[hY oh[Y& hJo[ oJh[c oh[Y5 oh8[Y oJh[5 ", -"oJh[8 SohY ShoY& ]oh oh]c pw[hY oh8SY hp]o hs]o x[h x[- hJx[ ix[ h5x[ h>x[ ", -"xJ[h5 x[i> xhS Shx- ]xh ]ix hpx[ h>xS xp]h ix]y wq wq! wqB wqa wq1 wq8 q1wB", -" q8wa wqM q!wM wqT qTwa lw lw8 lwT lws wq* wq+ wBq* q+wa q*w1 q+w1 wq1*B wq", -"+1a q*wM q+wM q*wT q+wT lw* lw+ wTl* l+sw wqG w!qG wqH qGwa qGw1 qGw8 qHw1 ", -"qHw8 qGwM wqGM! qGwT wqHaM lwG w8lG lwH lGsw fq fq+ fqH gqf fq1 fq8 qHf1 g1", -"fq fqM q+fM fqT gMfq lfq l+fq lHfq glw wq4 w4q! q4wB w4qa 7wq w87q 7Bwq wq7", -"a q4wM wq4M! w4qT wqT4a lw7 w87l 7Tlw 7slw q=w w+q= =Bwq wq=a q=7w w>q 7wq=", -"B waq> wq=M q=w+M wq=T q=Tw+ lw= lw> =Tlw swl= w4qG wq4G! w4qH wqH4a wq7G 7", -"qGw8 wq7H 7wHq8 wq4GM qG4wM! wqH4T wT4qGa lG7w lw7G8 lH7w lws7G fq= q+f= =H", -"fq g=fq 7fq fq> 7Hfq 7fgq =Mfq fq=+M =Tfq fqTg= 7flw w>lf =Hlw g7lw wqP wPq", -"! qPwB wPqa q1wP wPq8 wq1PB wq8aP Swq S!wq wTSq wqSa lwS S8lw wTSl Sslw wPq", -"* wPq+ wqP*B wq+aP wq1P* wq+1P q*Pw1B w1Pqa* wqS* wqS+ Sq*wT Sw+qT l*Sw l+S", -"w lwST* lwsS+ Yqw q!Yw wHYq wqYa wqY1 wqY8 Yw1qH Yq8wH YqSw SwqY! Zqw waZq ", -"lYw Y8lw lwZ sYlw fqY Y+fq qHYf gYfq Y1fq Y8fq fqY1H fq8gY Sfq S+fq Zqf Sfg", -"q Sflw S8fq Zqlf gwlY oqw o!wq oBwq wqoa oq7w wqo8 7woqB 7waoq oqSw Swoq! w", -"qoT Swaoq rw rw8 rwT rsw owq= wqo+ q=owB q=aow 7o=wq oqw> q=o7wB w>qoa q=Sw", -" Sw+q= q=TSw S=awq rw= rw> =Trw swr> oqYw Yqow! wqoH Yqaow 7wYq Yq87w 7wHYq", -" 7Yawq SwoYq YqoSw! oqZw Zqwoa rYw Ywr8 rZw sYrw xq xq+ xqH xqg xq7 xq> 7qx", -"H gqx7 xqS Sqx+ xZq gqxZ xr xr> xrZ yxr ?qw wq& ?Bwq wq?a w1?q :wq ?qw1B wa", -":q ?wM w&?M wq?T wa?M lw? lw: ?Tlw s?lw q*?w -qw ?qw*B wa-q ?qw1* -q:w w1*?", -"qB :wq-a ?*wM ?M-w ?qTw* wq-T ?wl* l-w lw?T* swl- ?qG qGw& wq?H qG?a ?1qG ?", -"G:q ?qG1H wq:H wM?G ?qGM& wH?M ?qGT& ?qlG lG:w ?wlH lH:w fq? fq- ?Hfq fqg? ", -"f1?q :fq fq?1H :fgq ?Mfq fM-q ?Tfq ?wgM ?flw :flw fqTl? lwg? ?4wq w4q& ?qw4", -"B ?qaw4 ?q7w :q7w ?q7wB :wq7a ?4wM ?wM4& ?qTw4 ?wa4M l?7w l:7w 7wTl? lws7? ", -"?wq= q=-w ?w=qB -qw=a ?q7w= Aqw q=?7wB wqAa ?w=M -qw=M q=T?w -qTw= ?wl= Alw", -" lw=?T lwAs ?4qG ?qG4& ?qG4H ?qG4a 7q?G :wq7G 7wH?q :wH7q ?qG4M ?G4wM& ?qG4", -"T ?G4waM lw?7G lw:7G lwH7? :wH7l q=?f f-q= fq?=H fq-g= ?q7f Aqf 7fq?H gqAf ", -"fq?=M fq-=M fqT?= fq-=T lf?7w lfAq fqT7? glAw wq?P wPq& ?qwPB ?qawP ?qw1P w", -"q:P wq1?PB :wqaP S?w S&?w ?TSw ?aSw S?lw S:w lw?ST S?sw ?qwP* wq-P wq*?PB -", -"qwaP wq1?P* :wq-P ?Bwq1P* -qa:wP S*?w Sw-q S?wT* -qTSw lw?S* S-lw S?Tlw* l-", -"wSs ?Yq Y&?q ?HYq ?aYq Y1?q Yq:w ?Yq1H :wHYq S?Y S&?Y Zq?Y ?aSY lY? ?YS: ?Z", -"lY s?lY fq?Y Y-q fq?YH ?Ygq fq?Y1 fqY: ?Y1fqH g?Y:q S?f S-?Y Sf?Z S?gw S?lf", -" ?Yl- lY?Zf g?lY oq?w wqo& o?qwB o?awq ?q7ow oq:w o?q7wB :woqa o?Sw Sw&o? o", -"?TSw S?aow r?w r:w ?wrT s?rw ?w=oq oq-w q=wo?B o-qwa o?q7w= oqAw =B7wo?q Ao", -"awq ?wS= o-qSw S?=wT o-qwT ?wr= Arw r=T?w rsAw o?Yq Yq&o? o?HYq ?Yaoq ?q7Y ", -":woYq ?Y7qH :woqH So?Y S?Yo& S?ZoY S?Yoa r?Y ?Yr: ?ZrY s?rY x?q xq- ?qxH g?", -"xq ?qx7 Axq x?q7H xqAg x?S S?x- S?xZ g?xS xr? Axr r?xZ yxAr [qw [!wq wqD wa", -"[q [w1 w8[q wD[1 wa[1 wM[q [qwM! Vwq waVq lw[ w8[l lwV Vwsq [q* w+[q [*qD q", -"+wD [*w1 [1w+ [q*1D [q8D* [Mq* [q+wM [qV* wqV+ [ql* [wl+ l*Vw l+Vw qG[w [qw", -"G! Jqw waJq wG[1 [q8wG [wJ1 wqJ8 [qwGM wMG[q! VwJq JqVwa [wlG lw[G8 lwJ Jqs", -"w fq[ [+fq Jqf Jqgw [qf1 [qf8 J1fq J8fq [qfM fq[+M fqV Vfgq [lfq fq8[l Jqlf", -" g[lw [4wq [qw4! w4qD [qaw4 7[w w87[ [w7D [w7a [qw4M [4Mwq! wqV4 Vwq4a 7[lw", -" lw7[8 7Vw 7Vsw [=q [+q= [q=D [q=a 7[= w>7[ =D7[ =a7[ [q=M [=q+M Vq[= Vw=q+", -" l=[ [>lw Vwl= 7[s= [qw4G [4Gwq! wqJ4 Jqw4a [w7G 7[wG8 7wJq Jq87w [4GwqM [!", -"wq4GM JqVw4 Vw4Jqa lw7[G 7[Glw8 7Jlw lwJ7s [=fq fq[=+ Jq= J=gq 7[f [>7f Jq7", -"f 7[gw fq[=M [=+fqM V=Jq Jq=gV 7[lf fq>[l Jql= g[l= wP[q [qwP! wPqD [qawP w", -"P[1 [q8wP [w1DP [w1aP [qSw Sq[w! VqSw VwqSa [lSw Sw8[l SlVw lwVSs [Pq* [q+w", -"P [q*DP [qaP* [q*1P [q8P* w1PqD* w1P[a* [qS* Sw+[q VwqS* Vw+Sq lw[S* lw+S[ ", -"lwVS* Vw+Sl [qYw Yw[q! JwYq JqYwa [wY1 Yq8[w JqYw1 Jq8Yw Sq[Yw Yq[Sw! ]qw w", -"q]a Yw[l lYw[8 ]lw lw]s [fYq fq[Y+ YJfq JqfgY fq[Y1 fq8[Y JqfY1 JqfY8 Sq[f ", -"Sfq[+ ]qf gq]f lYf[q fq8S[ lf]q gl]w [qow o[qw! wqoD o[awq o[7w o[87w 7wDo[", -" 7[aow Sq[ow o[qSw! oqVw oVwqa r[w [wr8 rVw swrV q=o[ [=oq+ [=oqD [=aoq 7o[", -"= [>o7w 7[=oD w>qoD Sq[= S=[q+ oVwq= oVwq+ r[= [>rw Vwr= s=r[ Yw[oq o[wYq! ", -"oqJw oJqwa Yw7[ 7[Yw8 oJq7w oJqw8 YqoSw[ Sqo[Yw! oq]w ]oqwa Ywr[ r[Yw8 ]rw ", -"rs]w xq[ [qx+ xJq gqxJ x7[ 7[x> 7Jxq g7x[ Sqx[ xq[S+ ]xq xq]g xr[ r[x> ]xr ", -"yx]r z z& zD zc z1 z: z1D z:c zM zM& zV zVc zl zl: zlV uz z* z- z*D zc- z*1", -" z:- 1Dz* :cz- z*M z-M zV* zV- zl* zl- l*zV uz- zG zG& zJ zJc z1G z:G zJ1 z", -"J: zGM GMz& zJV cJzV zlG l:zG zlJ uzJ zf zf- zJf iz zf1 z:f Jfz1 iz: zfM f-", -"zM zVf izV zlf lfz: lfzJ uzi z4 z4& z4D zc4 z7 z7: z7D z7c z4M 4Mz& zV4 c4z", -"V zl7 l:z7 z7V uz7 z= z-= z=D zc= z7= Az =Dz7 Azc z=M =Mz- zV= c=zV zl= Azl", -" l=zV Azu z4G 4Gz& zJ4 cJz4 z7G 7:zG zJ7 7Jz: 4GzM z4GM& J4zV zJVc4 lGz7 zl", -"7:G 7Jzl zJu7 zf= f-z= zJ= iz= z7f Azf 7Jzf Azi =Mzf zf-=M J=zV zVi= lfz7 z", -"lAf l=zJ uzAi zP zP& zDP zcP z1P z:P 1DzP :czP zS zS& zVS zcS zlS z:S SlzV ", -"uzS z*P z-P DPz* c-zP 1Pz* :-zP z*1DP z:c-P zS* z-S SVz* Scz- l*zS l-zS zlV", -"S* z-uS zY zY& zJY zYc zY1 zY: YJz1 Y:zJ zYS SYz& ]z ]zc zlY lYz: ]zl uz] z", -"Yf zY- YJzf izY Yfz1 Y:zf zJYf1 zYi: zfS Sfz- ]zf ]zi lYzf lYz- zl]f ]zui z", -"o zo& zoD zoc zo7 zo: 7ozD 7czo zoS Soz& zoV Sczo zr zr: zrV uzr zo= zo- =D", -"zo ocz- 7oz= Azo zo7=D zoAc z=S S-zo S=zV Scz= zr= Azr rVz= uzAr zoY Y&zo z", -"oJ Yczo z7Y Y:zo 7Jzo Ycz7 SozY zoYS& ]zo zo]c zrY rYz: ]zr ]zur zx zx- zxJ", -" izx zx7 Azx xJz7 izAx zxS x-zS ]zx iz]x zxr zxAr zx]r | ", -NULL -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Prepares the data for MSOPs of 4-variable functions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_ReadMsops( char ** ppSopSizes, char *** ppSops ) -{ - unsigned uMasks[4][2] = { - { 0x5555, 0xAAAA }, - { 0x3333, 0xCCCC }, - { 0x0F0F, 0xF0F0 }, - { 0x00FF, 0xFF00 } - }; - char Map[256], * pPrev, * pMemory; - char * pSopSizes, ** pSops; - int i, k, b, Size; - - // map chars into their numbers - for ( i = 0; i < 256; i++ ) - Map[i] = -1; - for ( i = 0; i < 81; i++ ) - Map[s_Data3[i]] = i; - - // count the number of strings - for ( Size = 0; s_Data4[Size] && Size < 100000; Size++ ); - assert( Size < 100000 ); - - // allocate memory - pMemory = ALLOC( char, Size * 75 ); - // copy the array into memory - for ( i = 0; i < Size; i++ ) - for ( k = 0; k < 75; k++ ) - if ( s_Data4[i][k] == ' ' ) - pMemory[i*75+k] = -1; - else - pMemory[i*75+k] = Map[s_Data4[i][k]]; - - // set pointers and compute SOP sizes - pSopSizes = ALLOC( char, 65536 ); - pSops = ALLOC( char *, 65536 ); - pSopSizes[0] = 0; - pSops[0] = NULL; - pPrev = pMemory; - for ( k = 0, i = 1; i < 65536; k++ ) - if ( pMemory[k] == -1 ) - { - pSopSizes[i] = pMemory + k - pPrev; - pSops[i++] = pPrev; - pPrev = pMemory + k + 1; - } - *ppSopSizes = pSopSizes; - *ppSops = pSops; - - // verify the results - derive truth table from SOP - for ( i = 1; i < 65536; i++ ) - { - int uTruth = 0, uCube, Lit; - for ( k = 0; k < pSopSizes[i]; k++ ) - { - uCube = 0xFFFF; - Lit = pSops[i][k]; - for ( b = 3; b >= 0; b-- ) - { - if ( Lit % 3 == 0 ) - uCube &= uMasks[b][0]; - else if ( Lit % 3 == 1 ) - uCube &= uMasks[b][1]; - Lit = Lit / 3; - } - uTruth |= uCube; - } - assert( uTruth == i ); - } -} - -#if 0 - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManDeriveCnfTest() -{ - int i, k, Lit; - printf( "\n" ); - for ( i = 80; i >= 0; i-- ) - { - Lit = i; - for ( k = 0; k < 4; k++ ) - { - if ( Lit % 3 == 0 ) - printf( "%c", 'A' + k ); - else if ( Lit % 3 == 1 ) - printf( "%c", 'a' + k ); - Lit = Lit / 3; - } - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManDeriveCnfTest2() -{ - char s_Data3[81] = "!#&()*+,-.0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]abcdefghijklmnopqrstuvwxyz|"; - - unsigned uMasks[4][2] = { - { 0x5555, 0xAAAA }, - { 0x3333, 0xCCCC }, - { 0x0F0F, 0xF0F0 }, - { 0x00FF, 0xFF00 } - }; - char Buffer[100], * pCur; - FILE * pFile; - int CountCur, Counter = 0, nLines = 0; - int pLines[1<<16] = {0}; - int pNums[1<<16] = {0}; - unsigned uTruth, uTruth2, uCube, cCube; - char * pSops[1<<16] = {0}; - char Sop[10]; - char Cube[4]; - int i, k; - - pFile = fopen( "cands2.txt", "r" ); - while ( fgets( Buffer, 100, pFile ) ) - { - if ( Buffer[0] == '0' ) - Extra_ReadHexadecimal( &uTruth2, Buffer+2, 4 ); - else - uTruth2 = 0xFFFFFF; - - // skip all chars till a-d or A-D - if ( Buffer[0] == '0' ) - for ( pCur = Buffer; *pCur != '\n'; pCur++ ) - { -// if ( *pCur >= 'a' && *pCur <= 'd' || *pCur >= 'A' && *pCur <= 'D' ) - if ( *pCur == ':' ) - { - pCur++; - break; - } - } - else - pCur = Buffer; - - - uTruth = 0; - CountCur = 0; - uCube = 0xFFFF; - for ( i = 0; i < 4; i++ ) - Cube[i] = 2; - - for ( ; *pCur; pCur++ ) - { - if ( *pCur == '+' || *pCur == '\n' ) - { - uTruth |= uCube; - uCube = 0xFFFF; - - // get the cube - cCube = 0; - for ( i = 0; i < 4; i++ ) - cCube = 3 * cCube + Cube[i]; - for ( i = 0; i < 4; i++ ) - Cube[i] = 2; - - assert( cCube >= 0 && cCube < 81 ); - Sop[CountCur] = cCube; - CountCur++; - if ( *pCur == '\n' ) - { - Sop[CountCur] = 0; - break; - } - } - else if ( *pCur >= 'a' && *pCur <= 'd' ) - { - uCube &= uMasks[*pCur-'a'][1]; - Cube[*pCur-'a'] = 1; - } - else if ( *pCur >= 'A' && *pCur <= 'D' ) - { - uCube &= uMasks[*pCur-'A'][0]; - Cube[*pCur-'A'] = 0; - } - } - assert( *pCur == '\n' ); - assert( uTruth2 == 0xFFFFFF || uTruth2 == uTruth ); - - Counter += CountCur; - pNums[uTruth] = CountCur; - pSops[uTruth] = ALLOC( char, CountCur ); - memcpy( pSops[uTruth], Sop, CountCur ); - pLines[nLines++] = Counter; - } - fclose( pFile ); - - printf( "Lines = %d. Counter = %d.\n", nLines, Counter ); - -/* - // write the number of cubes - for ( i = 0; i < 65536; i++ ) - printf( "%d,%d ", pNums[i], pNums[i] + pNums[0xffff & ~i] ); - printf( "\n" ); -*/ - - // write the number of cubes - Counter = 0; - for ( i = 1; i < 65536; i++ ) - { - CountCur = pNums[i]; - assert( CountCur > 0 ); - for ( k = 0; k <= CountCur; k++ ) - { - if ( k < CountCur ) - { - assert( pSops[i][k] >= 0 && pSops[i][k] < 81 ); - printf( "%c", s_Data3[pSops[i][k]] ); - } - else - printf( " " ); - if ( ++Counter == 75 ) - { - printf( "\",\n\"" ); - Counter = 0; - } - } - } - printf( "\n" ); - - return 1; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/cnf/cnfMan.c b/src/aig/cnf/cnfMan.c deleted file mode 100644 index 1edc012a..00000000 --- a/src/aig/cnf/cnfMan.c +++ /dev/null @@ -1,202 +0,0 @@ -/**CFile**************************************************************** - - FileName [cnfMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG-to-CNF conversion.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: cnfMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cnf.h" -#include "satSolver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Cnf_Lit2Var( int Lit ) { return (Lit & 1)? -(Lit >> 1)-1 : (Lit >> 1)+1; } -static inline int Cnf_Lit2Var2( int Lit ) { return (Lit & 1)? -(Lit >> 1) : (Lit >> 1); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Man_t * Cnf_ManStart() -{ - Cnf_Man_t * p; - int i; - // allocate the manager - p = ALLOC( Cnf_Man_t, 1 ); - memset( p, 0, sizeof(Cnf_Man_t) ); - // derive internal data structures - Cnf_ReadMsops( &p->pSopSizes, &p->pSops ); - // allocate memory manager for cuts - p->pMemCuts = Aig_MmFlexStart(); - p->nMergeLimit = 10; - // allocate temporary truth tables - p->pTruths[0] = ALLOC( unsigned, 4 * Aig_TruthWordNum(p->nMergeLimit) ); - for ( i = 1; i < 4; i++ ) - p->pTruths[i] = p->pTruths[i-1] + Aig_TruthWordNum(p->nMergeLimit); - p->vMemory = Vec_IntAlloc( 1 << 18 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_ManStop( Cnf_Man_t * p ) -{ - Vec_IntFree( p->vMemory ); - free( p->pTruths[0] ); - Aig_MmFlexStop( p->pMemCuts, 0 ); - free( p->pSopSizes ); - free( p->pSops[1] ); - free( p->pSops ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of CI IDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Cnf_DataCollectPiSatNums( Cnf_Dat_t * pCnf, Aig_Man_t * p ) -{ - Vec_Int_t * vCiIds; - Aig_Obj_t * pObj; - int i; - vCiIds = Vec_IntAlloc( Aig_ManPiNum(p) ); - Aig_ManForEachPi( p, pObj, i ) - Vec_IntPush( vCiIds, pCnf->pVarNums[pObj->Id] ); - return vCiIds; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_DataFree( Cnf_Dat_t * p ) -{ - if ( p == NULL ) - return; - free( p->pClauses[0] ); - free( p->pClauses ); - free( p->pVarNums ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Writes CNF into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_DataWriteIntoFile( Cnf_Dat_t * p, char * pFileName, int fReadable ) -{ - FILE * pFile; - int * pLit, * pStop, i; - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - printf( "Cnf_WriteIntoFile(): Output file cannot be opened.\n" ); - return; - } - fprintf( pFile, "c Result of efficient AIG-to-CNF conversion using package CNF\n" ); - fprintf( pFile, "p %d %d\n", p->nVars, p->nClauses ); - for ( i = 0; i < p->nClauses; i++ ) - { - for ( pLit = p->pClauses[i], pStop = p->pClauses[i+1]; pLit < pStop; pLit++ ) - fprintf( pFile, "%d ", fReadable? Cnf_Lit2Var2(*pLit) : Cnf_Lit2Var(*pLit) ); - fprintf( pFile, "0\n" ); - } - fprintf( pFile, "\n" ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Writes CNF into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p ) -{ - sat_solver * pSat; - int i, status; - pSat = sat_solver_new(); - sat_solver_setnvars( pSat, p->nVars ); - for ( i = 0; i < p->nClauses; i++ ) - { - if ( !sat_solver_addclause( pSat, p->pClauses[i], p->pClauses[i+1] ) ) - { - sat_solver_delete( pSat ); - return NULL; - } - } - status = sat_solver_simplify(pSat); - if ( status == 0 ) - { - sat_solver_delete( pSat ); - return NULL; - } - return pSat; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/cnf/cnfMap.c b/src/aig/cnf/cnfMap.c deleted file mode 100644 index d966df15..00000000 --- a/src/aig/cnf/cnfMap.c +++ /dev/null @@ -1,356 +0,0 @@ -/**CFile**************************************************************** - - FileName [cnfMap.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG-to-CNF conversion.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: cnfMap.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cnf.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes area flow of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CutAssignAreaFlow( Cnf_Man_t * p, Dar_Cut_t * pCut, int * pAreaFlows ) -{ - Aig_Obj_t * pLeaf; - int i; - pCut->Value = 0; - pCut->uSign = 100 * Cnf_CutSopCost( p, pCut ); - Dar_CutForEachLeaf( p->pManAig, pCut, pLeaf, i ) - { - pCut->Value += pLeaf->nRefs; - if ( !Aig_ObjIsNode(pLeaf) ) - continue; - assert( pLeaf->nRefs > 0 ); - pCut->uSign += pAreaFlows[pLeaf->Id] / (pLeaf->nRefs? pLeaf->nRefs : 1); - } -} - -/**Function************************************************************* - - Synopsis [Computes area flow of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_CutSuperAreaFlow( Vec_Ptr_t * vSuper, int * pAreaFlows ) -{ - Aig_Obj_t * pLeaf; - int i, nAreaFlow; - nAreaFlow = 100 * (Vec_PtrSize(vSuper) + 1); - Vec_PtrForEachEntry( vSuper, pLeaf, i ) - { - pLeaf = Aig_Regular(pLeaf); - if ( !Aig_ObjIsNode(pLeaf) ) - continue; - assert( pLeaf->nRefs > 0 ); - nAreaFlow += pAreaFlows[pLeaf->Id] / (pLeaf->nRefs? pLeaf->nRefs : 1); - } - return nAreaFlow; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_DeriveMapping( Cnf_Man_t * p ) -{ - Vec_Ptr_t * vSuper; - Aig_Obj_t * pObj; - Dar_Cut_t * pCut, * pCutBest; - int i, k, AreaFlow, * pAreaFlows; - // allocate area flows - pAreaFlows = ALLOC( int, Aig_ManObjNumMax(p->pManAig) ); - memset( pAreaFlows, 0, sizeof(int) * Aig_ManObjNumMax(p->pManAig) ); - // visit the nodes in the topological order and update their best cuts - vSuper = Vec_PtrAlloc( 100 ); - Aig_ManForEachNode( p->pManAig, pObj, i ) - { - // go through the cuts - pCutBest = NULL; - Dar_ObjForEachCut( pObj, pCut, k ) - { - pCut->fBest = 0; - if ( k == 0 ) - continue; - Cnf_CutAssignAreaFlow( p, pCut, pAreaFlows ); - if ( pCutBest == NULL || pCutBest->uSign > pCut->uSign || - (pCutBest->uSign == pCut->uSign && pCutBest->Value < pCut->Value) ) - pCutBest = pCut; - } - // check the big cut -// Aig_ObjCollectSuper( pObj, vSuper ); - // get the area flow of this cut -// AreaFlow = Cnf_CutSuperAreaFlow( vSuper, pAreaFlows ); - AreaFlow = AIG_INFINITY; - if ( AreaFlow >= (int)pCutBest->uSign ) - { - pAreaFlows[pObj->Id] = pCutBest->uSign; - pCutBest->fBest = 1; - } - else - { - pAreaFlows[pObj->Id] = AreaFlow; - pObj->fMarkB = 1; // mark the special node - } - } - Vec_PtrFree( vSuper ); - free( pAreaFlows ); - -/* - // compute the area of mapping - AreaFlow = 0; - Aig_ManForEachPo( p->pManAig, pObj, i ) - AreaFlow += Dar_ObjBestCut(Aig_ObjFanin0(pObj))->uSign / 100 / Aig_ObjFanin0(pObj)->nRefs; - printf( "Area of the network = %d.\n", AreaFlow ); -*/ -} - - - -#if 0 - -/**Function************************************************************* - - Synopsis [Computes area of the first level.] - - Description [The cut need to be derefed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_CutDeref( Aig_Man_t * p, Dar_Cut_t * pCut ) -{ - Aig_Obj_t * pLeaf; - int i; - Dar_CutForEachLeaf( p, pCut, pLeaf, i ) - { - assert( pLeaf->nRefs > 0 ); - if ( --pLeaf->nRefs > 0 || !Aig_ObjIsAnd(pLeaf) ) - continue; - Aig_CutDeref( p, Aig_ObjBestCut(pLeaf) ); - } -} - -/**Function************************************************************* - - Synopsis [Computes area of the first level.] - - Description [The cut need to be derefed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_CutRef( Aig_Man_t * p, Dar_Cut_t * pCut ) -{ - Aig_Obj_t * pLeaf; - int i, Area = pCut->Value; - Dar_CutForEachLeaf( p, pCut, pLeaf, i ) - { - assert( pLeaf->nRefs >= 0 ); - if ( pLeaf->nRefs++ > 0 || !Aig_ObjIsAnd(pLeaf) ) - continue; - Area += Aig_CutRef( p, Aig_ObjBestCut(pLeaf) ); - } - return Area; -} - -/**Function************************************************************* - - Synopsis [Computes exact area of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_CutArea( Aig_Man_t * p, Dar_Cut_t * pCut ) -{ - int Area; - Area = Aig_CutRef( p, pCut ); - Aig_CutDeref( p, pCut ); - return Area; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the second cut is better.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Cnf_CutCompare( Dar_Cut_t * pC0, Dar_Cut_t * pC1 ) -{ - if ( pC0->Area < pC1->Area - 0.0001 ) - return -1; - if ( pC0->Area > pC1->Area + 0.0001 ) // smaller area flow is better - return 1; -// if ( pC0->NoRefs < pC1->NoRefs ) -// return -1; -// if ( pC0->NoRefs > pC1->NoRefs ) // fewer non-referenced fanins is better -// return 1; -// if ( pC0->FanRefs / pC0->nLeaves > pC1->FanRefs / pC1->nLeaves ) -// return -1; -// if ( pC0->FanRefs / pC0->nLeaves < pC1->FanRefs / pC1->nLeaves ) -// return 1; // larger average fanin ref-counter is better -// return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns the cut with the smallest area flow.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dar_Cut_t * Cnf_ObjFindBestCut( Aig_Obj_t * pObj ) -{ - Dar_Cut_t * pCut, * pCutBest; - int i; - pCutBest = NULL; - Dar_ObjForEachCut( pObj, pCut, i ) - if ( pCutBest == NULL || Cnf_CutCompare(pCutBest, pCut) == 1 ) - pCutBest = pCut; - return pCutBest; -} - -/**Function************************************************************* - - Synopsis [Computes area flow of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_CutAssignArea( Cnf_Man_t * p, Dar_Cut_t * pCut ) -{ - Aig_Obj_t * pLeaf; - int i; - pCut->Area = (float)pCut->Cost; - pCut->NoRefs = 0; - pCut->FanRefs = 0; - Dar_CutForEachLeaf( p->pManAig, pCut, pLeaf, i ) - { - if ( !Aig_ObjIsNode(pLeaf) ) - continue; - if ( pLeaf->nRefs == 0 ) - { - pCut->Area += Aig_ObjBestCut(pLeaf)->Cost; - pCut->NoRefs++; - } - else - { - if ( pCut->FanRefs + pLeaf->nRefs > 15 ) - pCut->FanRefs = 15; - else - pCut->FanRefs += pLeaf->nRefs; - } - } -} - -/**Function************************************************************* - - Synopsis [Performs one round of "area recovery" using exact local area.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_ManMapForCnf( Cnf_Man_t * p ) -{ - Aig_Obj_t * pObj; - Dar_Cut_t * pCut, * pCutBest; - int i, k; - // visit the nodes in the topological order and update their best cuts - Aig_ManForEachNode( p->pManAig, pObj, i ) - { - // find the old best cut - pCutBest = Aig_ObjBestCut(pObj); - Dar_ObjClearBestCut(pCutBest); - // if the node is used, dereference its cut - if ( pObj->nRefs ) - Aig_CutDeref( p->pManAig, pCutBest ); - - // evaluate the cuts of this node - Dar_ObjForEachCut( pObj, pCut, k ) -// Cnf_CutAssignAreaFlow( p, pCut ); - pCut->Area = (float)Cnf_CutArea( p->pManAig, pCut ); - - // find the new best cut - pCutBest = Cnf_ObjFindBestCut(pObj); - Dar_ObjSetBestCut( pCutBest ); - // if the node is used, reference its cut - if ( pObj->nRefs ) - Aig_CutRef( p->pManAig, pCutBest ); - } - return 1; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/cnf/cnfPost.c b/src/aig/cnf/cnfPost.c deleted file mode 100644 index 988275b2..00000000 --- a/src/aig/cnf/cnfPost.c +++ /dev/null @@ -1,233 +0,0 @@ -/**CFile**************************************************************** - - FileName [cnfPost.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG-to-CNF conversion.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: cnfPost.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cnf.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_ManPostprocess_old( Cnf_Man_t * p ) -{ -// extern int Aig_ManLargeCutEval( Aig_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCutR, Dar_Cut_t * pCutL, int Leaf ); - int nNew, Gain, nGain = 0, nVars = 0; - - Aig_Obj_t * pObj, * pFan; - Dar_Cut_t * pCutBest, * pCut; - int i, k;//, a, b, Counter; - Aig_ManForEachObj( p->pManAig, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) ) - continue; - if ( pObj->nRefs == 0 ) - continue; -// pCutBest = Aig_ObjBestCut(pObj); - pCutBest = NULL; - - Dar_CutForEachLeaf( p->pManAig, pCutBest, pFan, k ) - { - if ( !Aig_ObjIsNode(pFan) ) - continue; - assert( pFan->nRefs != 0 ); - if ( pFan->nRefs != 1 ) - continue; -// pCut = Aig_ObjBestCut(pFan); - pCut = NULL; -/* - // find how many common variable they have - Counter = 0; - for ( a = 0; a < (int)pCut->nLeaves; a++ ) - { - for ( b = 0; b < (int)pCutBest->nLeaves; b++ ) - if ( pCut->pLeaves[a] == pCutBest->pLeaves[b] ) - break; - if ( b == (int)pCutBest->nLeaves ) - continue; - Counter++; - } - printf( "%d ", Counter ); -*/ - // find the new truth table after collapsing these two cuts - - -// nNew = Aig_ManLargeCutEval( p->pManAig, pObj, pCutBest, pCut, pFan->Id ); - nNew = 0; - - -// printf( "%d+%d=%d:%d(%d) ", pCutBest->Cost, pCut->Cost, -// pCutBest->Cost+pCut->Cost, nNew, pCutBest->Cost+pCut->Cost-nNew ); - - Gain = pCutBest->Value + pCut->Value - nNew; - if ( Gain > 0 ) - { - nGain += Gain; - nVars++; - } - } - } - printf( "Total gain = %d. Vars = %d.\n", nGain, nVars ); -} - -/**Function************************************************************* - - Synopsis [Transfers cuts of the mapped nodes into internal representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_ManTransferCuts( Cnf_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_MmFlexRestart( p->pMemCuts ); - Aig_ManForEachObj( p->pManAig, pObj, i ) - { - if ( Aig_ObjIsNode(pObj) && pObj->nRefs > 0 ) - pObj->pData = Cnf_CutCreate( p, pObj ); - else - pObj->pData = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Transfers cuts of the mapped nodes into internal representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_ManFreeCuts( Cnf_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachObj( p->pManAig, pObj, i ) - if ( pObj->pData ) - { - Cnf_CutFree( pObj->pData ); - pObj->pData = NULL; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_ManPostprocess( Cnf_Man_t * p ) -{ - Cnf_Cut_t * pCut, * pCutFan, * pCutRes; - Aig_Obj_t * pObj, * pFan; - int Order[16], Costs[16]; - int i, k, fChanges; - Aig_ManForEachNode( p->pManAig, pObj, i ) - { - if ( pObj->nRefs == 0 ) - continue; - pCut = Cnf_ObjBestCut(pObj); - - // sort fanins according to their size - Cnf_CutForEachLeaf( p->pManAig, pCut, pFan, k ) - { - Order[k] = k; - Costs[k] = Aig_ObjIsNode(pFan)? Cnf_ObjBestCut(pFan)->Cost : 0; - } - // sort the cuts by Weight - do { - int Temp; - fChanges = 0; - for ( k = 0; k < pCut->nFanins - 1; k++ ) - { - if ( Costs[Order[k]] <= Costs[Order[k+1]] ) - continue; - Temp = Order[k]; - Order[k] = Order[k+1]; - Order[k+1] = Temp; - fChanges = 1; - } - } while ( fChanges ); - - -// Cnf_CutForEachLeaf( p->pManAig, pCut, pFan, k ) - for ( k = 0; (k < (int)(pCut)->nFanins) && ((pFan) = Aig_ManObj(p->pManAig, (pCut)->pFanins[Order[k]])); k++ ) - { - if ( !Aig_ObjIsNode(pFan) ) - continue; - assert( pFan->nRefs != 0 ); - if ( pFan->nRefs != 1 ) - continue; - pCutFan = Cnf_ObjBestCut(pFan); - // try composing these two cuts -// Cnf_CutPrint( pCut ); - pCutRes = Cnf_CutCompose( p, pCut, pCutFan, pFan->Id ); -// Cnf_CutPrint( pCut ); -// printf( "\n" ); - // check if the cost if reduced - if ( pCutRes == NULL || pCutRes->Cost == 127 || pCutRes->Cost > pCut->Cost + pCutFan->Cost ) - { - if ( pCutRes ) - Cnf_CutFree( pCutRes ); - continue; - } - // update the cut - Cnf_ObjSetBestCut( pObj, pCutRes ); - Cnf_ObjSetBestCut( pFan, NULL ); - Cnf_CutUpdateRefs( p, pCut, pCutFan, pCutRes ); - assert( pFan->nRefs == 0 ); - Cnf_CutFree( pCut ); - Cnf_CutFree( pCutFan ); - break; - } - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/cnf/cnfUtil.c b/src/aig/cnf/cnfUtil.c deleted file mode 100644 index cd47cb58..00000000 --- a/src/aig/cnf/cnfUtil.c +++ /dev/null @@ -1,188 +0,0 @@ -/**CFile**************************************************************** - - FileName [cnfUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG-to-CNF conversion.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: cnfUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cnf.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes area, references, and nodes used in the mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManScanMapping_rec( Cnf_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vMapped ) -{ - Aig_Obj_t * pLeaf; - Dar_Cut_t * pCutBest; - int aArea, i; - if ( pObj->nRefs++ || Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) - return 0; - assert( Aig_ObjIsAnd(pObj) ); - // collect the node first to derive pre-order - if ( vMapped ) - Vec_PtrPush( vMapped, pObj ); - // visit the transitive fanin of the selected cut - if ( pObj->fMarkB ) - { - Vec_Ptr_t * vSuper = Vec_PtrAlloc( 100 ); - Aig_ObjCollectSuper( pObj, vSuper ); - aArea = Vec_PtrSize(vSuper) + 1; - Vec_PtrForEachEntry( vSuper, pLeaf, i ) - aArea += Aig_ManScanMapping_rec( p, Aig_Regular(pLeaf), vMapped ); - Vec_PtrFree( vSuper ); - //////////////////////////// - pObj->fMarkB = 1; - } - else - { - pCutBest = Dar_ObjBestCut( pObj ); - aArea = Cnf_CutSopCost( p, pCutBest ); - Dar_CutForEachLeaf( p->pManAig, pCutBest, pLeaf, i ) - aArea += Aig_ManScanMapping_rec( p, pLeaf, vMapped ); - } - return aArea; -} - -/**Function************************************************************* - - Synopsis [Computes area, references, and nodes used in the mapping.] - - Description [Collects the nodes in reverse topological order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Aig_ManScanMapping( Cnf_Man_t * p, int fCollect ) -{ - Vec_Ptr_t * vMapped = NULL; - Aig_Obj_t * pObj; - int i; - // clean all references - Aig_ManForEachObj( p->pManAig, pObj, i ) - pObj->nRefs = 0; - // allocate the array - if ( fCollect ) - vMapped = Vec_PtrAlloc( 1000 ); - // collect nodes reachable from POs in the DFS order through the best cuts - p->aArea = 0; - Aig_ManForEachPo( p->pManAig, pObj, i ) - p->aArea += Aig_ManScanMapping_rec( p, Aig_ObjFanin0(pObj), vMapped ); -// printf( "Variables = %6d. Clauses = %8d.\n", vMapped? Vec_PtrSize(vMapped) + Aig_ManPiNum(p->pManAig) + 1 : 0, p->aArea + 2 ); - return vMapped; -} - -/**Function************************************************************* - - Synopsis [Computes area, references, and nodes used in the mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_ManScanMapping_rec( Cnf_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vMapped, int fPreorder ) -{ - Aig_Obj_t * pLeaf; - Cnf_Cut_t * pCutBest; - int aArea, i; - if ( pObj->nRefs++ || Aig_ObjIsPi(pObj) || Aig_ObjIsConst1(pObj) ) - return 0; - assert( Aig_ObjIsAnd(pObj) ); - assert( pObj->pData != NULL ); - // add the node to the mapping - if ( vMapped && fPreorder ) - Vec_PtrPush( vMapped, pObj ); - // visit the transitive fanin of the selected cut - if ( pObj->fMarkB ) - { - Vec_Ptr_t * vSuper = Vec_PtrAlloc( 100 ); - Aig_ObjCollectSuper( pObj, vSuper ); - aArea = Vec_PtrSize(vSuper) + 1; - Vec_PtrForEachEntry( vSuper, pLeaf, i ) - aArea += Cnf_ManScanMapping_rec( p, Aig_Regular(pLeaf), vMapped, fPreorder ); - Vec_PtrFree( vSuper ); - //////////////////////////// - pObj->fMarkB = 1; - } - else - { - pCutBest = pObj->pData; - assert( pCutBest->Cost < 127 ); - aArea = pCutBest->Cost; - Cnf_CutForEachLeaf( p->pManAig, pCutBest, pLeaf, i ) - aArea += Cnf_ManScanMapping_rec( p, pLeaf, vMapped, fPreorder ); - } - // add the node to the mapping - if ( vMapped && !fPreorder ) - Vec_PtrPush( vMapped, pObj ); - return aArea; -} - -/**Function************************************************************* - - Synopsis [Computes area, references, and nodes used in the mapping.] - - Description [Collects the nodes in reverse topological order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Cnf_ManScanMapping( Cnf_Man_t * p, int fCollect, int fPreorder ) -{ - Vec_Ptr_t * vMapped = NULL; - Aig_Obj_t * pObj; - int i; - // clean all references - Aig_ManForEachObj( p->pManAig, pObj, i ) - pObj->nRefs = 0; - // allocate the array - if ( fCollect ) - vMapped = Vec_PtrAlloc( 1000 ); - // collect nodes reachable from POs in the DFS order through the best cuts - p->aArea = 0; - Aig_ManForEachPo( p->pManAig, pObj, i ) - p->aArea += Cnf_ManScanMapping_rec( p, Aig_ObjFanin0(pObj), vMapped, fPreorder ); -// printf( "Variables = %6d. Clauses = %8d.\n", vMapped? Vec_PtrSize(vMapped) + Aig_ManPiNum(p->pManAig) + 1 : 0, p->aArea + 2 ); - return vMapped; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/cnf/cnfWrite.c b/src/aig/cnf/cnfWrite.c deleted file mode 100644 index 45a3efad..00000000 --- a/src/aig/cnf/cnfWrite.c +++ /dev/null @@ -1,443 +0,0 @@ -/**CFile**************************************************************** - - FileName [cnfWrite.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG-to-CNF conversion.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: cnfWrite.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cnf.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes the cover into the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cnf_SopConvertToVector( char * pSop, int nCubes, Vec_Int_t * vCover ) -{ - int Lits[4], Cube, iCube, i, b; - Vec_IntClear( vCover ); - for ( i = 0; i < nCubes; i++ ) - { - Cube = pSop[i]; - for ( b = 0; b < 4; b++ ) - { - if ( Cube % 3 == 0 ) - Lits[b] = 1; - else if ( Cube % 3 == 1 ) - Lits[b] = 2; - else - Lits[b] = 0; - Cube = Cube / 3; - } - iCube = 0; - for ( b = 0; b < 4; b++ ) - iCube = (iCube << 2) | Lits[b]; - Vec_IntPush( vCover, iCube ); - } -} - -/**Function************************************************************* - - Synopsis [Returns the number of literals in the SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_SopCountLiterals( char * pSop, int nCubes ) -{ - int nLits = 0, Cube, i, b; - for ( i = 0; i < nCubes; i++ ) - { - Cube = pSop[i]; - for ( b = 0; b < 4; b++ ) - { - if ( Cube % 3 != 2 ) - nLits++; - Cube = Cube / 3; - } - } - return nLits; -} - -/**Function************************************************************* - - Synopsis [Returns the number of literals in the SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_IsopCountLiterals( Vec_Int_t * vIsop, int nVars ) -{ - int nLits = 0, Cube, i, b; - Vec_IntForEachEntry( vIsop, Cube, i ) - { - for ( b = 0; b < nVars; b++ ) - { - if ( (Cube & 3) == 1 || (Cube & 3) == 2 ) - nLits++; - Cube >>= 2; - } - } - return nLits; -} - -/**Function************************************************************* - - Synopsis [Writes the cube and returns the number of literals in it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cnf_IsopWriteCube( int Cube, int nVars, int * pVars, int * pLiterals ) -{ - int nLits = nVars, b; - for ( b = 0; b < nVars; b++ ) - { - if ( (Cube & 3) == 1 ) // value 0 --> write positive literal - *pLiterals++ = 2 * pVars[b]; - else if ( (Cube & 3) == 2 ) // value 1 --> write negative literal - *pLiterals++ = 2 * pVars[b] + 1; - else - nLits--; - Cube >>= 2; - } - return nLits; -} - -/**Function************************************************************* - - Synopsis [Derives CNF for the mapping.] - - Description [The last argument shows the number of last outputs - of the manager, which will not be converted into clauses but the - new variables for which will be introduced.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Dat_t * Cnf_ManWriteCnf( Cnf_Man_t * p, Vec_Ptr_t * vMapped, int nOutputs ) -{ - Aig_Obj_t * pObj; - Cnf_Dat_t * pCnf; - Cnf_Cut_t * pCut; - Vec_Int_t * vCover, * vSopTemp; - int OutVar, PoVar, pVars[32], * pLits, ** pClas; - unsigned uTruth; - int i, k, nLiterals, nClauses, Cube, Number; - - // count the number of literals and clauses - nLiterals = 1 + Aig_ManPoNum( p->pManAig ) + 3 * nOutputs; - nClauses = 1 + Aig_ManPoNum( p->pManAig ) + nOutputs; - Vec_PtrForEachEntry( vMapped, pObj, i ) - { - assert( Aig_ObjIsNode(pObj) ); - pCut = Cnf_ObjBestCut( pObj ); - - // positive polarity of the cut - if ( pCut->nFanins < 5 ) - { - uTruth = 0xFFFF & *Cnf_CutTruth(pCut); - nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth]; - assert( p->pSopSizes[uTruth] >= 0 ); - nClauses += p->pSopSizes[uTruth]; - } - else - { - nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[1], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[1]); - nClauses += Vec_IntSize(pCut->vIsop[1]); - } - // negative polarity of the cut - if ( pCut->nFanins < 5 ) - { - uTruth = 0xFFFF & ~*Cnf_CutTruth(pCut); - nLiterals += Cnf_SopCountLiterals( p->pSops[uTruth], p->pSopSizes[uTruth] ) + p->pSopSizes[uTruth]; - assert( p->pSopSizes[uTruth] >= 0 ); - nClauses += p->pSopSizes[uTruth]; - } - else - { - nLiterals += Cnf_IsopCountLiterals( pCut->vIsop[0], pCut->nFanins ) + Vec_IntSize(pCut->vIsop[0]); - nClauses += Vec_IntSize(pCut->vIsop[0]); - } -//printf( "%d ", nClauses-(1 + Aig_ManPoNum( p->pManAig )) ); - } -//printf( "\n" ); - - // allocate CNF - pCnf = ALLOC( Cnf_Dat_t, 1 ); - memset( pCnf, 0, sizeof(Cnf_Dat_t) ); - pCnf->nLiterals = nLiterals; - pCnf->nClauses = nClauses; - pCnf->pClauses = ALLOC( int *, nClauses + 1 ); - pCnf->pClauses[0] = ALLOC( int, nLiterals ); - pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; - - // create room for variable numbers - pCnf->pVarNums = ALLOC( int, Aig_ManObjNumMax(p->pManAig) ); - memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p->pManAig) ); - // assign variables to the last (nOutputs) POs - Number = 1; - if ( nOutputs ) - { - assert( nOutputs == Aig_ManRegNum(p->pManAig) ); - Aig_ManForEachLiSeq( p->pManAig, pObj, i ) - pCnf->pVarNums[pObj->Id] = Number++; - } - // assign variables to the internal nodes - Vec_PtrForEachEntry( vMapped, pObj, i ) - pCnf->pVarNums[pObj->Id] = Number++; - // assign variables to the PIs and constant node - Aig_ManForEachPi( p->pManAig, pObj, i ) - pCnf->pVarNums[pObj->Id] = Number++; - pCnf->pVarNums[Aig_ManConst1(p->pManAig)->Id] = Number++; - pCnf->nVars = Number; - - // assign the clauses - vSopTemp = Vec_IntAlloc( 1 << 16 ); - pLits = pCnf->pClauses[0]; - pClas = pCnf->pClauses; - Vec_PtrForEachEntry( vMapped, pObj, i ) - { - pCut = Cnf_ObjBestCut( pObj ); - - // save variables of this cut - OutVar = pCnf->pVarNums[ pObj->Id ]; - for ( k = 0; k < (int)pCut->nFanins; k++ ) - { - pVars[k] = pCnf->pVarNums[ pCut->pFanins[k] ]; - assert( pVars[k] <= Aig_ManObjNumMax(p->pManAig) ); - } - - // positive polarity of the cut - if ( pCut->nFanins < 5 ) - { - uTruth = 0xFFFF & *Cnf_CutTruth(pCut); - Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vSopTemp ); - vCover = vSopTemp; - } - else - vCover = pCut->vIsop[1]; - Vec_IntForEachEntry( vCover, Cube, k ) - { - *pClas++ = pLits; - *pLits++ = 2 * OutVar; - pLits += Cnf_IsopWriteCube( Cube, pCut->nFanins, pVars, pLits ); - } - - // negative polarity of the cut - if ( pCut->nFanins < 5 ) - { - uTruth = 0xFFFF & ~*Cnf_CutTruth(pCut); - Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vSopTemp ); - vCover = vSopTemp; - } - else - vCover = pCut->vIsop[0]; - Vec_IntForEachEntry( vCover, Cube, k ) - { - *pClas++ = pLits; - *pLits++ = 2 * OutVar + 1; - pLits += Cnf_IsopWriteCube( Cube, pCut->nFanins, pVars, pLits ); - } - } - Vec_IntFree( vSopTemp ); - - // write the constant literal - OutVar = pCnf->pVarNums[ Aig_ManConst1(p->pManAig)->Id ]; - assert( OutVar <= Aig_ManObjNumMax(p->pManAig) ); - *pClas++ = pLits; - *pLits++ = 2 * OutVar; - - // write the output literals - Aig_ManForEachPo( p->pManAig, pObj, i ) - { - OutVar = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ]; - if ( i < Aig_ManPoNum(p->pManAig) - nOutputs ) - { - *pClas++ = pLits; - *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); - } - else - { - PoVar = pCnf->pVarNums[ pObj->Id ]; - // first clause - *pClas++ = pLits; - *pLits++ = 2 * PoVar; - *pLits++ = 2 * OutVar + !Aig_ObjFaninC0(pObj); - // second clause - *pClas++ = pLits; - *pLits++ = 2 * PoVar + 1; - *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); - } - } - - // verify that the correct number of literals and clauses was written - assert( pLits - pCnf->pClauses[0] == nLiterals ); - assert( pClas - pCnf->pClauses == nClauses ); - return pCnf; -} - - -/**Function************************************************************* - - Synopsis [Derives a simple CNF for the AIG.] - - Description [The last argument shows the number of last outputs - of the manager, which will not be converted into clauses but the - new variables for which will be introduced.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cnf_Dat_t * Cnf_DeriveSimple( Aig_Man_t * p, int nOutputs ) -{ - Aig_Obj_t * pObj; - Cnf_Dat_t * pCnf; - int OutVar, PoVar, pVars[32], * pLits, ** pClas; - int i, nLiterals, nClauses, Number; - - // count the number of literals and clauses - nLiterals = 1 + 7 * Aig_ManNodeNum(p) + Aig_ManPoNum( p ) + 3 * nOutputs; - nClauses = 1 + 3 * Aig_ManNodeNum(p) + Aig_ManPoNum( p ) + nOutputs; - - // allocate CNF - pCnf = ALLOC( Cnf_Dat_t, 1 ); - memset( pCnf, 0, sizeof(Cnf_Dat_t) ); - pCnf->nLiterals = nLiterals; - pCnf->nClauses = nClauses; - pCnf->pClauses = ALLOC( int *, nClauses + 1 ); - pCnf->pClauses[0] = ALLOC( int, nLiterals ); - pCnf->pClauses[nClauses] = pCnf->pClauses[0] + nLiterals; - - // create room for variable numbers - pCnf->pVarNums = ALLOC( int, Aig_ManObjNumMax(p) ); - memset( pCnf->pVarNums, 0xff, sizeof(int) * Aig_ManObjNumMax(p) ); - // assign variables to the last (nOutputs) POs - Number = 1; - if ( nOutputs ) - { - assert( nOutputs == Aig_ManRegNum(p) ); - Aig_ManForEachLiSeq( p, pObj, i ) - pCnf->pVarNums[pObj->Id] = Number++; - } - // assign variables to the internal nodes - Aig_ManForEachNode( p, pObj, i ) - pCnf->pVarNums[pObj->Id] = Number++; - // assign variables to the PIs and constant node - Aig_ManForEachPi( p, pObj, i ) - pCnf->pVarNums[pObj->Id] = Number++; - pCnf->pVarNums[Aig_ManConst1(p)->Id] = Number++; - pCnf->nVars = Number; -/* - // print CNF numbers - printf( "SAT numbers of each node:\n" ); - Aig_ManForEachObj( p, pObj, i ) - printf( "%d=%d ", pObj->Id, pCnf->pVarNums[pObj->Id] ); - printf( "\n" ); -*/ - // assign the clauses - pLits = pCnf->pClauses[0]; - pClas = pCnf->pClauses; - Aig_ManForEachNode( p, pObj, i ) - { - OutVar = pCnf->pVarNums[ pObj->Id ]; - pVars[0] = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ]; - pVars[1] = pCnf->pVarNums[ Aig_ObjFanin1(pObj)->Id ]; - - // positive phase - *pClas++ = pLits; - *pLits++ = 2 * OutVar; - *pLits++ = 2 * pVars[0] + !Aig_ObjFaninC0(pObj); - *pLits++ = 2 * pVars[1] + !Aig_ObjFaninC1(pObj); - // negative phase - *pClas++ = pLits; - *pLits++ = 2 * OutVar + 1; - *pLits++ = 2 * pVars[0] + Aig_ObjFaninC0(pObj); - *pClas++ = pLits; - *pLits++ = 2 * OutVar + 1; - *pLits++ = 2 * pVars[1] + Aig_ObjFaninC1(pObj); - } - - // write the constant literal - OutVar = pCnf->pVarNums[ Aig_ManConst1(p)->Id ]; - assert( OutVar <= Aig_ManObjNumMax(p) ); - *pClas++ = pLits; - *pLits++ = 2 * OutVar; - - // write the output literals - Aig_ManForEachPo( p, pObj, i ) - { - OutVar = pCnf->pVarNums[ Aig_ObjFanin0(pObj)->Id ]; - if ( i < Aig_ManPoNum(p) - nOutputs ) - { - *pClas++ = pLits; - *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); - } - else - { - PoVar = pCnf->pVarNums[ pObj->Id ]; - // first clause - *pClas++ = pLits; - *pLits++ = 2 * PoVar; - *pLits++ = 2 * OutVar + !Aig_ObjFaninC0(pObj); - // second clause - *pClas++ = pLits; - *pLits++ = 2 * PoVar + 1; - *pLits++ = 2 * OutVar + Aig_ObjFaninC0(pObj); - } - } - - // verify that the correct number of literals and clauses was written - assert( pLits - pCnf->pClauses[0] == nLiterals ); - assert( pClas - pCnf->pClauses == nClauses ); - return pCnf; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/cnf/cnf_.c b/src/aig/cnf/cnf_.c deleted file mode 100644 index 7c9ca499..00000000 --- a/src/aig/cnf/cnf_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [cnf_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG-to-CNF conversion.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: cnf_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cnf.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/cnf/module.make b/src/aig/cnf/module.make deleted file mode 100644 index dbcaeba4..00000000 --- a/src/aig/cnf/module.make +++ /dev/null @@ -1,8 +0,0 @@ -SRC += src/aig/cnf/cnfCore.c \ - src/aig/cnf/cnfCut.c \ - src/aig/cnf/cnfData.c \ - src/aig/cnf/cnfMan.c \ - src/aig/cnf/cnfMap.c \ - src/aig/cnf/cnfPost.c \ - src/aig/cnf/cnfUtil.c \ - src/aig/cnf/cnfWrite.c diff --git a/src/aig/csw/csw.h b/src/aig/csw/csw.h deleted file mode 100644 index 1443f4d9..00000000 --- a/src/aig/csw/csw.h +++ /dev/null @@ -1,65 +0,0 @@ -/**CFile**************************************************************** - - FileName [csw.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Cut sweeping.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - July 11, 2007.] - - Revision [$Id: csw.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CSW_H__ -#define __CSW_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== cnfCore.c ========================================================*/ -extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/csw/cswCore.c b/src/aig/csw/cswCore.c deleted file mode 100644 index 20893058..00000000 --- a/src/aig/csw/cswCore.c +++ /dev/null @@ -1,94 +0,0 @@ -/**CFile**************************************************************** - - FileName [cswCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Cut sweeping.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - July 11, 2007.] - - Revision [$Id: cswCore.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cswInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose ) -{ - Csw_Man_t * p; - Aig_Man_t * pRes; - Aig_Obj_t * pObj, * pObjNew, * pObjRes; - int i, clk; -clk = clock(); - // start the manager - p = Csw_ManStart( pAig, nCutsMax, nLeafMax, fVerbose ); - // set elementary cuts at the PIs - Aig_ManForEachPi( p->pManRes, pObj, i ) - { - Csw_ObjPrepareCuts( p, pObj, 1 ); - Csw_ObjAddRefs( p, pObj, Aig_ManPi(p->pManAig,i)->nRefs ); - } - // process the nodes - Aig_ManForEachNode( pAig, pObj, i ) - { - // create the new node - pObjNew = Aig_And( p->pManRes, Csw_ObjChild0Equiv(p, pObj), Csw_ObjChild1Equiv(p, pObj) ); - // check if this node can be represented using another node -// pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 ); -// pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) ); - // try recursively if resubsitution is used - do { - pObjRes = Csw_ObjSweep( p, Aig_Regular(pObjNew), pObj->nRefs > 1 ); - pObjRes = Aig_NotCond( pObjRes, Aig_IsComplement(pObjNew) ); - pObjNew = pObjRes; - } while ( Csw_ObjCuts(p, Aig_Regular(pObjNew)) == NULL && !Aig_ObjIsConst1(Aig_Regular(pObjNew)) ); - // save the resulting node - Csw_ObjSetEquiv( p, pObj, pObjRes ); - // add to the reference counter - Csw_ObjAddRefs( p, Aig_Regular(pObjRes), pObj->nRefs ); - } - // add the POs - Aig_ManForEachPo( pAig, pObj, i ) - Aig_ObjCreatePo( p->pManRes, Csw_ObjChild0Equiv(p, pObj) ); - // remove dangling nodes - Aig_ManCleanup( p->pManRes ); - // return the resulting manager -p->timeTotal = clock() - clk; -p->timeOther = p->timeTotal - p->timeCuts - p->timeHash; - pRes = p->pManRes; - Csw_ManStop( p ); - return pRes; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/csw/cswCut.c b/src/aig/csw/cswCut.c deleted file mode 100644 index b3b7152b..00000000 --- a/src/aig/csw/cswCut.c +++ /dev/null @@ -1,602 +0,0 @@ -/**CFile**************************************************************** - - FileName [cswCut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Cut sweeping.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - July 11, 2007.] - - Revision [$Id: cswCut.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cswInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Compute the cost of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Csw_CutFindCost( Csw_Man_t * p, Csw_Cut_t * pCut ) -{ - Aig_Obj_t * pLeaf; - int i, Cost = 0; - assert( pCut->nFanins > 0 ); - Csw_CutForEachLeaf( p->pManRes, pCut, pLeaf, i ) - { -// Cost += pLeaf->nRefs; - Cost += Csw_ObjRefs( p, pLeaf ); -// printf( "%d ", pLeaf->nRefs ); - } -//printf( "\n" ); - return Cost * 100 / pCut->nFanins; -} - -/**Function************************************************************* - - Synopsis [Compute the cost of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Csw_CutFindCost2( Csw_Man_t * p, Csw_Cut_t * pCut ) -{ - Aig_Obj_t * pLeaf; - float Cost = 0.0; - int i; - assert( pCut->nFanins > 0 ); - Csw_CutForEachLeaf( p->pManRes, pCut, pLeaf, i ) - Cost += (float)1.0/pLeaf->nRefs; - return 1/Cost; -} - -/**Function************************************************************* - - Synopsis [Returns the next free cut to use.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Csw_Cut_t * Csw_CutFindFree( Csw_Man_t * p, Aig_Obj_t * pObj ) -{ - Csw_Cut_t * pCut, * pCutMax; - int i; - pCutMax = NULL; - Csw_ObjForEachCut( p, pObj, pCut, i ) - { - if ( pCut->nFanins == 0 ) - return pCut; - if ( pCutMax == NULL || pCutMax->Cost < pCut->Cost ) - pCutMax = pCut; - } - assert( pCutMax != NULL ); - pCutMax->nFanins = 0; - return pCutMax; -} - -/**Function************************************************************* - - Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Cut_TruthPhase( Csw_Cut_t * pCut, Csw_Cut_t * pCut1 ) -{ - unsigned uPhase = 0; - int i, k; - for ( i = k = 0; i < pCut->nFanins; i++ ) - { - if ( k == pCut1->nFanins ) - break; - if ( pCut->pFanins[i] < pCut1->pFanins[k] ) - continue; - assert( pCut->pFanins[i] == pCut1->pFanins[k] ); - uPhase |= (1 << i); - k++; - } - return uPhase; -} - -/**Function************************************************************* - - Synopsis [Performs truth table computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Csw_CutComputeTruth( Csw_Man_t * p, Csw_Cut_t * pCut, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, int fCompl0, int fCompl1 ) -{ - // permute the first table - if ( fCompl0 ) - Kit_TruthNot( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax ); - else - Kit_TruthCopy( p->puTemp[0], Csw_CutTruth(pCut0), p->nLeafMax ); - Kit_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut0), 0 ); - // permute the second table - if ( fCompl1 ) - Kit_TruthNot( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax ); - else - Kit_TruthCopy( p->puTemp[1], Csw_CutTruth(pCut1), p->nLeafMax ); - Kit_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nFanins, p->nLeafMax, Cut_TruthPhase(pCut, pCut1), 0 ); - // produce the resulting table - Kit_TruthAnd( Csw_CutTruth(pCut), p->puTemp[2], p->puTemp[3], p->nLeafMax ); -// assert( pCut->nFanins >= Kit_TruthSupportSize( Csw_CutTruth(pCut), p->nLeafMax ) ); - return Csw_CutTruth(pCut); -} - -/**Function************************************************************* - - Synopsis [Performs support minimization for the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Csw_CutSupportMinimize( Csw_Man_t * p, Csw_Cut_t * pCut ) -{ - unsigned * pTruth; - int uSupp, nFansNew, i, k; - // get truth table - pTruth = Csw_CutTruth( pCut ); - // get support - uSupp = Kit_TruthSupport( pTruth, p->nLeafMax ); - // get the new support size - nFansNew = Kit_WordCountOnes( uSupp ); - // check if there are redundant variables - if ( nFansNew == pCut->nFanins ) - return nFansNew; - assert( nFansNew < pCut->nFanins ); - // minimize support - Kit_TruthShrink( p->puTemp[0], pTruth, nFansNew, p->nLeafMax, uSupp, 1 ); - for ( i = k = 0; i < pCut->nFanins; i++ ) - if ( uSupp & (1 << i) ) - pCut->pFanins[k++] = pCut->pFanins[i]; - assert( k == nFansNew ); - pCut->nFanins = nFansNew; -// assert( nFansNew == Kit_TruthSupportSize( pTruth, p->nLeafMax ) ); -//Extra_PrintBinary( stdout, pTruth, (1<nLeafMax) ); printf( "\n" ); - return nFansNew; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pDom is contained in pCut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Csw_CutCheckDominance( Csw_Cut_t * pDom, Csw_Cut_t * pCut ) -{ - int i, k; - for ( i = 0; i < (int)pDom->nFanins; i++ ) - { - for ( k = 0; k < (int)pCut->nFanins; k++ ) - if ( pDom->pFanins[i] == pCut->pFanins[k] ) - break; - if ( k == (int)pCut->nFanins ) // node i in pDom is not contained in pCut - return 0; - } - // every node in pDom is contained in pCut - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the cut is contained.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Csw_CutFilter( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCut ) -{ - Csw_Cut_t * pTemp; - int i; - // go through the cuts of the node - Csw_ObjForEachCut( p, pObj, pTemp, i ) - { - if ( pTemp->nFanins < 2 ) - continue; - if ( pTemp == pCut ) - continue; - if ( pTemp->nFanins > pCut->nFanins ) - { - // skip the non-contained cuts - if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) - continue; - // check containment seriously - if ( Csw_CutCheckDominance( pCut, pTemp ) ) - { - // remove contained cut - pTemp->nFanins = 0; - } - } - else - { - // skip the non-contained cuts - if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) - continue; - // check containment seriously - if ( Csw_CutCheckDominance( pTemp, pCut ) ) - { - // remove the given - pCut->nFanins = 0; - return 1; - } - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Csw_CutMergeOrdered( Csw_Man_t * p, Csw_Cut_t * pC0, Csw_Cut_t * pC1, Csw_Cut_t * pC ) -{ - int i, k, c; - assert( pC0->nFanins >= pC1->nFanins ); - // the case of the largest cut sizes - if ( pC0->nFanins == p->nLeafMax && pC1->nFanins == p->nLeafMax ) - { - for ( i = 0; i < pC0->nFanins; i++ ) - if ( pC0->pFanins[i] != pC1->pFanins[i] ) - return 0; - for ( i = 0; i < pC0->nFanins; i++ ) - pC->pFanins[i] = pC0->pFanins[i]; - pC->nFanins = pC0->nFanins; - return 1; - } - // the case when one of the cuts is the largest - if ( pC0->nFanins == p->nLeafMax ) - { - for ( i = 0; i < pC1->nFanins; i++ ) - { - for ( k = pC0->nFanins - 1; k >= 0; k-- ) - if ( pC0->pFanins[k] == pC1->pFanins[i] ) - break; - if ( k == -1 ) // did not find - return 0; - } - for ( i = 0; i < pC0->nFanins; i++ ) - pC->pFanins[i] = pC0->pFanins[i]; - pC->nFanins = pC0->nFanins; - return 1; - } - - // compare two cuts with different numbers - i = k = 0; - for ( c = 0; c < p->nLeafMax; c++ ) - { - if ( k == pC1->nFanins ) - { - if ( i == pC0->nFanins ) - { - pC->nFanins = c; - return 1; - } - pC->pFanins[c] = pC0->pFanins[i++]; - continue; - } - if ( i == pC0->nFanins ) - { - if ( k == pC1->nFanins ) - { - pC->nFanins = c; - return 1; - } - pC->pFanins[c] = pC1->pFanins[k++]; - continue; - } - if ( pC0->pFanins[i] < pC1->pFanins[k] ) - { - pC->pFanins[c] = pC0->pFanins[i++]; - continue; - } - if ( pC0->pFanins[i] > pC1->pFanins[k] ) - { - pC->pFanins[c] = pC1->pFanins[k++]; - continue; - } - pC->pFanins[c] = pC0->pFanins[i++]; - k++; - } - if ( i < pC0->nFanins || k < pC1->nFanins ) - return 0; - pC->nFanins = c; - return 1; -} - -/**Function************************************************************* - - Synopsis [Prepares the object for FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Csw_CutMerge( Csw_Man_t * p, Csw_Cut_t * pCut0, Csw_Cut_t * pCut1, Csw_Cut_t * pCut ) -{ - assert( p->nLeafMax > 0 ); - // merge the nodes - if ( pCut0->nFanins < pCut1->nFanins ) - { - if ( !Csw_CutMergeOrdered( p, pCut1, pCut0, pCut ) ) - return 0; - } - else - { - if ( !Csw_CutMergeOrdered( p, pCut0, pCut1, pCut ) ) - return 0; - } - pCut->uSign = pCut0->uSign | pCut1->uSign; - return 1; -} - -/**Function************************************************************* - - Synopsis [Consider cut with more than 2 fanins having 2 true variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Csw_ObjTwoVarCut( Csw_Man_t * p, Csw_Cut_t * pCut ) -{ - Aig_Obj_t * pRes, * pIn0, * pIn1; - int nVars, uTruth, fCompl = 0; - assert( pCut->nFanins > 2 ); - // minimize support of this cut - nVars = Csw_CutSupportMinimize( p, pCut ); - assert( nVars == 2 ); - // get the fanins - pIn0 = Aig_ManObj( p->pManRes, pCut->pFanins[0] ); - pIn1 = Aig_ManObj( p->pManRes, pCut->pFanins[1] ); - // derive the truth table - uTruth = 0xF & *Csw_CutTruth(pCut); - if ( uTruth == 14 || uTruth == 13 || uTruth == 11 || uTruth == 7 ) - { - uTruth = 0xF & ~uTruth; - fCompl = 1; - } - // compute the result - pRes = NULL; - if ( uTruth == 1 ) // 0001 // 1110 14 - pRes = Aig_And( p->pManRes, Aig_Not(pIn0), Aig_Not(pIn1) ); - if ( uTruth == 2 ) // 0010 // 1101 13 - pRes = Aig_And( p->pManRes, pIn0 , Aig_Not(pIn1) ); - if ( uTruth == 4 ) // 0100 // 1011 11 - pRes = Aig_And( p->pManRes, Aig_Not(pIn0), pIn1 ); - if ( uTruth == 8 ) // 1000 // 0111 7 - pRes = Aig_And( p->pManRes, pIn0 , pIn1 ); - if ( pRes ) - pRes = Aig_NotCond( pRes, fCompl ); - return pRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Csw_Cut_t * Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ) -{ - Csw_Cut_t * pCutSet, * pCut; - int i; - // create the cutset of the node - pCutSet = (Csw_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts ); - Csw_ObjSetCuts( p, pObj, pCutSet ); - Csw_ObjForEachCut( p, pObj, pCut, i ) - { - pCut->nFanins = 0; - pCut->iNode = pObj->Id; - pCut->nCutSize = p->nCutSize; - pCut->nLeafMax = p->nLeafMax; - } - // add unit cut if needed - if ( fTriv ) - { - pCut = pCutSet; - pCut->Cost = 0; - pCut->iNode = pObj->Id; - pCut->nFanins = 1; - pCut->pFanins[0] = pObj->Id; - pCut->uSign = Aig_ObjCutSign( pObj->Id ); - memset( Csw_CutTruth(pCut), 0xAA, sizeof(unsigned) * p->nTruthWords ); - } - return pCutSet; -} - -/**Function************************************************************* - - Synopsis [Derives cuts for one node and sweeps this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ) -{ - int fUseResub = 1; - Csw_Cut_t * pCut0, * pCut1, * pCut, * pCutSet; - Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj); - Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj); - Aig_Obj_t * pObjNew; - unsigned * pTruth; - int i, k, nVars, nFanins, iVar, clk; - - assert( !Aig_IsComplement(pObj) ); - if ( !Aig_ObjIsNode(pObj) ) - return pObj; - if ( Csw_ObjCuts(p, pObj) ) - return pObj; - // the node is not processed yet - assert( Csw_ObjCuts(p, pObj) == NULL ); - assert( Aig_ObjIsNode(pObj) ); - - // set up the first cut - pCutSet = Csw_ObjPrepareCuts( p, pObj, fTriv ); - - // compute pair-wise cut combinations while checking table - Csw_ObjForEachCut( p, pFanin0, pCut0, i ) - if ( pCut0->nFanins > 0 ) - Csw_ObjForEachCut( p, pFanin1, pCut1, k ) - if ( pCut1->nFanins > 0 ) - { - // make sure K-feasible cut exists - if ( Kit_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->nLeafMax ) - continue; - // get the next cut of this node - pCut = Csw_CutFindFree( p, pObj ); -clk = clock(); - // assemble the new cut - if ( !Csw_CutMerge( p, pCut0, pCut1, pCut ) ) - { - assert( pCut->nFanins == 0 ); - continue; - } - // check containment - if ( Csw_CutFilter( p, pObj, pCut ) ) - { - assert( pCut->nFanins == 0 ); - continue; - } - // create its truth table - pTruth = Csw_CutComputeTruth( p, pCut, pCut0, pCut1, Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); - // support minimize the truth table - nFanins = pCut->nFanins; -// nVars = Csw_CutSupportMinimize( p, pCut ); // leads to quality degradation - nVars = Kit_TruthSupportSize( pTruth, p->nLeafMax ); -p->timeCuts += clock() - clk; - - // check for trivial truth tables - if ( nVars == 0 ) - { - p->nNodesTriv0++; - return Aig_NotCond( Aig_ManConst1(p->pManRes), !(pTruth[0] & 1) ); - } - if ( nVars == 1 ) - { - p->nNodesTriv1++; - iVar = Kit_WordFindFirstBit( Kit_TruthSupport(pTruth, p->nLeafMax) ); - assert( iVar < pCut->nFanins ); - return Aig_NotCond( Aig_ManObj(p->pManRes, pCut->pFanins[iVar]), (pTruth[0] & 1) ); - } - if ( nVars == 2 && nFanins > 2 && fUseResub ) - { - if ( pObjNew = Csw_ObjTwoVarCut( p, pCut ) ) - { - p->nNodesTriv2++; - return pObjNew; - } - } - - // check if an equivalent node with the same cut exists -clk = clock(); - pObjNew = pCut->nFanins > 2 ? Csw_TableCutLookup( p, pCut ) : NULL; -p->timeHash += clock() - clk; - if ( pObjNew ) - { - p->nNodesCuts++; - return pObjNew; - } - - // assign the cost - pCut->Cost = Csw_CutFindCost( p, pCut ); - assert( pCut->nFanins > 0 ); - assert( pCut->Cost > 0 ); - } - p->nNodesTried++; - - // load the resulting cuts into the table -clk = clock(); - Csw_ObjForEachCut( p, pObj, pCut, i ) - { - if ( pCut->nFanins > 2 ) - { - assert( pCut->Cost > 0 ); - Csw_TableCutInsert( p, pCut ); - } - } -p->timeHash += clock() - clk; - - // return the node if could not replace it - return pObj; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/csw/cswInt.h b/src/aig/csw/cswInt.h deleted file mode 100644 index 37efe9b4..00000000 --- a/src/aig/csw/cswInt.h +++ /dev/null @@ -1,157 +0,0 @@ -/**CFile**************************************************************** - - FileName [cswInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Cut sweeping.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - July 11, 2007.] - - Revision [$Id: cswInt.h,v 1.00 2007/07/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CSW_INT_H__ -#define __CSW_INT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "aig.h" -#include "dar.h" -#include "kit.h" -#include "csw.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Csw_Man_t_ Csw_Man_t; -typedef struct Csw_Cut_t_ Csw_Cut_t; - -// the cut used to represent node in the AIG -struct Csw_Cut_t_ -{ - Csw_Cut_t * pNext; // the next cut in the table - int Cost; // the cost of the cut -// float Cost; // the cost of the cut - unsigned uSign; // cut signature - int iNode; // the node, for which it is the cut - short nCutSize; // the number of bytes in the cut - char nLeafMax; // the maximum number of fanins - char nFanins; // the current number of fanins - int pFanins[0]; // the fanins (followed by the truth table) -}; - -// the CNF computation manager -struct Csw_Man_t_ -{ - // AIG manager - Aig_Man_t * pManAig; // the input AIG manager - Aig_Man_t * pManRes; // the output AIG manager - Aig_Obj_t ** pEquiv; // the equivalent nodes in the resulting manager - Csw_Cut_t ** pCuts; // the cuts for each node in the output manager - int * pnRefs; // the number of references of each new node - // hash table for cuts - Csw_Cut_t ** pTable; // the table composed of cuts - int nTableSize; // the size of hash table - // parameters - int nCutsMax; // the max number of cuts at the node - int nLeafMax; // the max number of leaves of a cut - int fVerbose; // enables verbose output - // internal variables - int nCutSize; // the number of bytes needed to store one cut - int nTruthWords; // the number of truth table words - Aig_MmFixed_t * pMemCuts; // memory manager for cuts - unsigned * puTemp[4]; // used for the truth table computation - // statistics - int nNodesTriv0; // the number of trivial nodes - int nNodesTriv1; // the number of trivial nodes - int nNodesTriv2; // the number of trivial nodes - int nNodesCuts; // the number of rewritten nodes - int nNodesTried; // the number of nodes tried - int timeCuts; // time to compute the cut and its truth table - int timeHash; // time for hashing cuts - int timeOther; // other time - int timeTotal; // total time -}; - -static inline int Csw_CutLeaveNum( Csw_Cut_t * pCut ) { return pCut->nFanins; } -static inline int * Csw_CutLeaves( Csw_Cut_t * pCut ) { return pCut->pFanins; } -static inline unsigned * Csw_CutTruth( Csw_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nLeafMax); } -static inline Csw_Cut_t * Csw_CutNext( Csw_Cut_t * pCut ) { return (Csw_Cut_t *)(((char *)pCut) + pCut->nCutSize); } - -static inline int Csw_ObjRefs( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pnRefs[pObj->Id]; } -static inline void Csw_ObjAddRefs( Csw_Man_t * p, Aig_Obj_t * pObj, int nRefs ) { p->pnRefs[pObj->Id] += nRefs; } - -static inline Csw_Cut_t * Csw_ObjCuts( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; } -static inline void Csw_ObjSetCuts( Csw_Man_t * p, Aig_Obj_t * pObj, Csw_Cut_t * pCuts ) { p->pCuts[pObj->Id] = pCuts; } - -static inline Aig_Obj_t * Csw_ObjEquiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquiv[pObj->Id]; } -static inline void Csw_ObjSetEquiv( Csw_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pEquiv ) { p->pEquiv[pObj->Id] = pEquiv; } - -static inline Aig_Obj_t * Csw_ObjChild0Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Csw_ObjChild1Equiv( Csw_Man_t * p, Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Csw_ObjEquiv(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)) : NULL; } - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator over cuts of the node -#define Csw_ObjForEachCut( p, pObj, pCut, i ) \ - for ( i = 0, pCut = Csw_ObjCuts(p, pObj); i < p->nCutsMax; i++, pCut = Csw_CutNext(pCut) ) -// iterator over leaves of the cut -#define Csw_CutForEachLeaf( p, pCut, pLeaf, i ) \ - for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== cnfCut.c ========================================================*/ -extern Csw_Cut_t * Csw_ObjPrepareCuts( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ); -extern Aig_Obj_t * Csw_ObjSweep( Csw_Man_t * p, Aig_Obj_t * pObj, int fTriv ); -/*=== cnfMan.c ========================================================*/ -extern Csw_Man_t * Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose ); -extern void Csw_ManStop( Csw_Man_t * p ); -/*=== cnfTable.c ========================================================*/ -extern int Csw_TableCountCuts( Csw_Man_t * p ); -extern void Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut ); -extern Aig_Obj_t * Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/csw/cswMan.c b/src/aig/csw/cswMan.c deleted file mode 100644 index c3061dee..00000000 --- a/src/aig/csw/cswMan.c +++ /dev/null @@ -1,125 +0,0 @@ -/**CFile**************************************************************** - - FileName [cswMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Cut sweeping.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - July 11, 2007.] - - Revision [$Id: cswMan.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cswInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the cut sweeping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Csw_Man_t * Csw_ManStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fVerbose ) -{ - Csw_Man_t * p; - Aig_Obj_t * pObj; - int i; - assert( nCutsMax >= 2 ); - assert( nLeafMax <= 16 ); - // allocate the fraiging manager - p = ALLOC( Csw_Man_t, 1 ); - memset( p, 0, sizeof(Csw_Man_t) ); - p->nCutsMax = nCutsMax; - p->nLeafMax = nLeafMax; - p->fVerbose = fVerbose; - p->pManAig = pMan; - // create the new manager - p->pManRes = Aig_ManStartFrom( pMan ); - assert( Aig_ManPiNum(p->pManAig) == Aig_ManPiNum(p->pManRes) ); - // allocate room for cuts and equivalent nodes - p->pnRefs = ALLOC( int, Aig_ManObjNumMax(pMan) ); - p->pEquiv = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pMan) ); - p->pCuts = ALLOC( Csw_Cut_t *, Aig_ManObjNumMax(pMan) ); - memset( p->pCuts, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pMan) ); - memset( p->pnRefs, 0, sizeof(int) * Aig_ManObjNumMax(pMan) ); - // allocate memory manager - p->nTruthWords = Aig_TruthWordNum(nLeafMax); - p->nCutSize = sizeof(Csw_Cut_t) + sizeof(int) * nLeafMax + sizeof(unsigned) * p->nTruthWords; - p->pMemCuts = Aig_MmFixedStart( p->nCutSize * p->nCutsMax, 512 ); - // allocate hash table for cuts - p->nTableSize = Aig_PrimeCudd( Aig_ManNodeNum(pMan) * p->nCutsMax / 2 ); - p->pTable = ALLOC( Csw_Cut_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); - // set the pointers to the available fraig nodes - Csw_ObjSetEquiv( p, Aig_ManConst1(p->pManAig), Aig_ManConst1(p->pManRes) ); - Aig_ManForEachPi( p->pManAig, pObj, i ) - Csw_ObjSetEquiv( p, pObj, Aig_ManPi(p->pManRes, i) ); - // room for temporary truth tables - p->puTemp[0] = ALLOC( unsigned, 4 * p->nTruthWords ); - p->puTemp[1] = p->puTemp[0] + p->nTruthWords; - p->puTemp[2] = p->puTemp[1] + p->nTruthWords; - p->puTemp[3] = p->puTemp[2] + p->nTruthWords; - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Csw_ManStop( Csw_Man_t * p ) -{ - if ( p->fVerbose ) - { - int nNodesBeg = Aig_ManNodeNum(p->pManAig); - int nNodesEnd = Aig_ManNodeNum(p->pManRes); - printf( "Beg = %7d. End = %7d. (%6.2f %%) Try = %7d. Cuts = %8d.\n", - nNodesBeg, nNodesEnd, 100.0*(nNodesBeg-nNodesEnd)/nNodesBeg, - p->nNodesTried, Csw_TableCountCuts( p ) ); - printf( "Triv0 = %6d. Triv1 = %6d. Triv2 = %6d. Cut-replace = %6d.\n", - p->nNodesTriv0, p->nNodesTriv1, p->nNodesTriv2, p->nNodesCuts ); - PRTP( "Cuts ", p->timeCuts, p->timeTotal ); - PRTP( "Hashing ", p->timeHash, p->timeTotal ); - PRTP( "Other ", p->timeOther, p->timeTotal ); - PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); - } - free( p->puTemp[0] ); - Aig_MmFixedStop( p->pMemCuts, 0 ); - free( p->pnRefs ); - free( p->pEquiv ); - free( p->pCuts ); - free( p->pTable ); - free( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/csw/cswTable.c b/src/aig/csw/cswTable.c deleted file mode 100644 index 87e36ae1..00000000 --- a/src/aig/csw/cswTable.c +++ /dev/null @@ -1,161 +0,0 @@ -/**CFile**************************************************************** - - FileName [cswTable.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Cut sweeping.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - July 11, 2007.] - - Revision [$Id: cswTable.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cswInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes hash value of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Csw_CutHash( Csw_Cut_t * pCut ) -{ - static int s_FPrimes[128] = { - 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, - 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, - 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, - 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, - 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, - 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, - 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, - 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, - 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, - 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, - 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, - 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, - 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 - }; - unsigned uHash; - int i; - assert( pCut->nFanins <= 16 ); - uHash = 0; - for ( i = 0; i < pCut->nFanins; i++ ) - uHash ^= pCut->pFanins[i] * s_FPrimes[i]; - return uHash; -} - -/**Function************************************************************* - - Synopsis [Returns the total number of cuts in the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Csw_TableCountCuts( Csw_Man_t * p ) -{ - Csw_Cut_t * pEnt; - int i, Counter = 0; - for ( i = 0; i < p->nTableSize; i++ ) - for ( pEnt = p->pTable[i]; pEnt; pEnt = pEnt->pNext ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Adds the cut to the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Csw_TableCutInsert( Csw_Man_t * p, Csw_Cut_t * pCut ) -{ - int iEntry = Csw_CutHash(pCut) % p->nTableSize; - pCut->pNext = p->pTable[iEntry]; - p->pTable[iEntry] = pCut; -} - -/**Function************************************************************* - - Synopsis [Returns an equivalent node if it exists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Csw_TableCutLookup( Csw_Man_t * p, Csw_Cut_t * pCut ) -{ - Aig_Obj_t * pRes = NULL; - Csw_Cut_t * pEnt; - unsigned * pTruthNew, * pTruthOld; - int iEntry = Csw_CutHash(pCut) % p->nTableSize; - for ( pEnt = p->pTable[iEntry]; pEnt; pEnt = pEnt->pNext ) - { - if ( pEnt->nFanins != pCut->nFanins ) - continue; - if ( pEnt->uSign != pCut->uSign ) - continue; - if ( memcmp( pEnt->pFanins, pCut->pFanins, sizeof(int) * pCut->nFanins ) ) - continue; - pTruthOld = Csw_CutTruth(pEnt); - pTruthNew = Csw_CutTruth(pCut); - if ( (pTruthOld[0] & 1) == (pTruthNew[0] & 1) ) - { - if ( Kit_TruthIsEqual( pTruthOld, pTruthNew, pCut->nFanins ) ) - { - pRes = Aig_ManObj( p->pManRes, pEnt->iNode ); - assert( pRes->fPhase == Aig_ManObj( p->pManRes, pCut->iNode )->fPhase ); - break; - } - } - else - { - if ( Kit_TruthIsOpposite( pTruthOld, pTruthNew, pCut->nFanins ) ) - { - pRes = Aig_Not( Aig_ManObj( p->pManRes, pEnt->iNode ) ); - assert( Aig_Regular(pRes)->fPhase != Aig_ManObj( p->pManRes, pCut->iNode )->fPhase ); - break; - } - } - } - return pRes; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/csw/csw_.c b/src/aig/csw/csw_.c deleted file mode 100644 index 1c59f152..00000000 --- a/src/aig/csw/csw_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [csw_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Cut sweeping.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - July 11, 2007.] - - Revision [$Id: csw_.c,v 1.00 2007/07/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cswInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/csw/module.make b/src/aig/csw/module.make deleted file mode 100644 index 8fdb7bef..00000000 --- a/src/aig/csw/module.make +++ /dev/null @@ -1,4 +0,0 @@ -SRC += src/aig/csw/cswCore.c \ - src/aig/csw/cswCut.c \ - src/aig/csw/cswMan.c \ - src/aig/csw/cswTable.c diff --git a/src/aig/dar/dar.h b/src/aig/dar/dar.h deleted file mode 100644 index 1f25e767..00000000 --- a/src/aig/dar/dar.h +++ /dev/null @@ -1,103 +0,0 @@ -/**CFile**************************************************************** - - FileName [dar.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: dar.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DAR_H__ -#define __DAR_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dar_RwrPar_t_ Dar_RwrPar_t; -typedef struct Dar_RefPar_t_ Dar_RefPar_t; - -struct Dar_RwrPar_t_ -{ - int nCutsMax; // the maximum number of cuts to try - int nSubgMax; // the maximum number of subgraphs to try - int fFanout; // support fanout representation - int fUpdateLevel; // update level - int fUseZeros; // performs zero-cost replacement - int fVerbose; // enables verbose output - int fVeryVerbose; // enables very verbose output -}; - -struct Dar_RefPar_t_ -{ - int nMffcMin; // the min MFFC size for which refactoring is used - int nLeafMax; // the max number of leaves of a cut - int nCutsMax; // the max number of cuts to consider - int fExtend; // extends the cut below MFFC - int fUpdateLevel; // updates the level after each move - int fUseZeros; // perform zero-cost replacements - int fVerbose; // verbosity level - int fVeryVerbose; // enables very verbose output -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== darBalance.c ========================================================*/ -extern Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel ); -/*=== darCore.c ========================================================*/ -extern void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars ); -extern int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ); -extern Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax ); -/*=== darRefact.c ========================================================*/ -extern void Dar_ManDefaultRefParams( Dar_RefPar_t * pPars ); -extern int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars ); -/*=== darScript.c ========================================================*/ -extern Aig_Man_t * Dar_ManRewriteDefault( Aig_Man_t * pAig ); -extern Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose ); -extern Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ); -extern Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ); -extern Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/dar/darBalance.c b/src/aig/dar/darBalance.c deleted file mode 100644 index 989535f2..00000000 --- a/src/aig/dar/darBalance.c +++ /dev/null @@ -1,398 +0,0 @@ -/**CFile**************************************************************** - - FileName [darBalance.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [Algebraic AIG balancing.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: darBalance.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Aig_Obj_t * Dar_Balance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); -static Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); -static int Dar_BalanceFindLeft( Vec_Ptr_t * vSuper ); -static void Dar_BalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); -static void Dar_BalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj ); -static Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs algebraic balancing of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_ManBalance( Aig_Man_t * p, int fUpdateLevel ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj, * pDriver, * pObjNew; - Vec_Vec_t * vStore; - int i; - // create the new manager - pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); - pNew->pName = Aig_UtilStrsav( p->pName ); - pNew->nRegs = p->nRegs; - pNew->nAsserts = p->nAsserts; - if ( p->vFlopNums ) - pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); - // map the PI nodes - Aig_ManCleanData( p ); - Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); - Aig_ManForEachPi( p, pObj, i ) - pObj->pData = Aig_ObjCreatePi(pNew); - // balance the AIG - vStore = Vec_VecAlloc( 50 ); - Aig_ManForEachPo( p, pObj, i ) - { - pDriver = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); - pObjNew = Dar_Balance_rec( pNew, Aig_Regular(pDriver), vStore, 0, fUpdateLevel ); - pObjNew = Aig_NotCond( pObjNew, Aig_IsComplement(pDriver) ); - Aig_ObjCreatePo( pNew, pObjNew ); - } - Vec_VecFree( vStore ); - // remove dangling nodes - if ( i = Aig_ManCleanup( pNew ) ) - printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); - // check the resulting AIG - if ( !Aig_ManCheck(pNew) ) - printf( "Dar_ManBalance(): The check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Returns the new node constructed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Dar_Balance_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) -{ - Aig_Obj_t * pObjNew; - Vec_Ptr_t * vSuper; - int i; - assert( !Aig_IsComplement(pObjOld) ); - assert( !Aig_ObjIsBuf(pObjOld) ); - // return if the result is known - if ( pObjOld->pData ) - return pObjOld->pData; - assert( Aig_ObjIsNode(pObjOld) ); - // get the implication supergate - vSuper = Dar_BalanceCone( pObjOld, vStore, Level ); - // check if supergate contains two nodes in the opposite polarity - if ( vSuper->nSize == 0 ) - return pObjOld->pData = Aig_ManConst0(pNew); - if ( Vec_PtrSize(vSuper) < 2 ) - printf( "BUG!\n" ); - // for each old node, derive the new well-balanced node - for ( i = 0; i < Vec_PtrSize(vSuper); i++ ) - { - pObjNew = Dar_Balance_rec( pNew, Aig_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); - vSuper->pArray[i] = Aig_NotCond( pObjNew, Aig_IsComplement(vSuper->pArray[i]) ); - } - // build the supergate - pObjNew = Dar_BalanceBuildSuper( pNew, vSuper, Aig_ObjType(pObjOld), fUpdateLevel ); - // make sure the balanced node is not assigned -// assert( pObjOld->Level >= Aig_Regular(pObjNew)->Level ); - assert( pObjOld->pData == NULL ); - return pObjOld->pData = pObjNew; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_BalanceCone_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - int RetValue1, RetValue2, i; - // check if the node is visited - if ( Aig_Regular(pObj)->fMarkB ) - { - // check if the node occurs in the same polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == pObj ) - return 1; - // check if the node is present in the opposite polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == Aig_Not(pObj) ) - return -1; - assert( 0 ); - return 0; - } - // if the new node is complemented or a PI, another gate begins - if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1) ) - { - Vec_PtrPush( vSuper, pObj ); - Aig_Regular(pObj)->fMarkB = 1; - return 0; - } - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - // go through the branches - RetValue1 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper ); - RetValue2 = Dar_BalanceCone_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - // return 1 if at least one branch has a duplicate - return RetValue1 || RetValue2; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) -{ - Vec_Ptr_t * vNodes; - int RetValue, i; - assert( !Aig_IsComplement(pObj) ); - // extend the storage - if ( Vec_VecSize( vStore ) <= Level ) - Vec_VecPush( vStore, Level, 0 ); - // get the temporary array of nodes - vNodes = Vec_VecEntry( vStore, Level ); - Vec_PtrClear( vNodes ); - // collect the nodes in the implication supergate - RetValue = Dar_BalanceCone_rec( pObj, pObj, vNodes ); - assert( vNodes->nSize > 1 ); - // unmark the visited nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - Aig_Regular(pObj)->fMarkB = 0; - // if we found the node and its complement in the same implication supergate, - // return empty set of nodes (meaning that we should use constant-0 node) - if ( RetValue == -1 ) - vNodes->nSize = 0; - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_NodeCompareLevelsDecrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) -{ - int Diff = Aig_ObjLevel(Aig_Regular(*pp1)) - Aig_ObjLevel(Aig_Regular(*pp2)); - if ( Diff > 0 ) - return -1; - if ( Diff < 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Builds implication supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Dar_BalanceBuildSuper( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel ) -{ - Aig_Obj_t * pObj1, * pObj2; - int LeftBound; - assert( vSuper->nSize > 1 ); - // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, Aig_NodeCompareLevelsDecrease ); - // balance the nodes - while ( vSuper->nSize > 1 ) - { - // find the left bound on the node to be paired - LeftBound = (!fUpdateLevel)? 0 : Dar_BalanceFindLeft( vSuper ); - // find the node that can be shared (if no such node, randomize choice) - Dar_BalancePermute( p, vSuper, LeftBound, Type == AIG_OBJ_EXOR ); - // pull out the last two nodes - pObj1 = Vec_PtrPop(vSuper); - pObj2 = Vec_PtrPop(vSuper); - Dar_BalancePushUniqueOrderByLevel( vSuper, Aig_Oper(p, pObj1, pObj2, Type) ); - } - return Vec_PtrEntry(vSuper, 0); -} - -/**Function************************************************************* - - Synopsis [Finds the left bound on the next candidate to be paired.] - - Description [The nodes in the array are in the decreasing order of levels. - The last node in the array has the smallest level. By default it would be paired - with the next node on the left. However, it may be possible to pair it with some - other node on the left, in such a way that the new node is shared. This procedure - finds the index of the left-most node, which can be paired with the last node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_BalanceFindLeft( Vec_Ptr_t * vSuper ) -{ - Aig_Obj_t * pObjRight, * pObjLeft; - int Current; - // if two or less nodes, pair with the first - if ( Vec_PtrSize(vSuper) < 3 ) - return 0; - // set the pointer to the one before the last - Current = Vec_PtrSize(vSuper) - 2; - pObjRight = Vec_PtrEntry( vSuper, Current ); - // go through the nodes to the left of this one - for ( Current--; Current >= 0; Current-- ) - { - // get the next node on the left - pObjLeft = Vec_PtrEntry( vSuper, Current ); - // if the level of this node is different, quit the loop - if ( Aig_ObjLevel(Aig_Regular(pObjLeft)) != Aig_ObjLevel(Aig_Regular(pObjRight)) ) - break; - } - Current++; - // get the node, for which the equality holds - pObjLeft = Vec_PtrEntry( vSuper, Current ); - assert( Aig_ObjLevel(Aig_Regular(pObjLeft)) == Aig_ObjLevel(Aig_Regular(pObjRight)) ); - return Current; -} - -/**Function************************************************************* - - Synopsis [Moves closer to the end the node that is best for sharing.] - - Description [If there is no node with sharing, randomly chooses one of - the legal nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_BalancePermute( Aig_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) -{ - Aig_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; - int RightBound, i; - // get the right bound - RightBound = Vec_PtrSize(vSuper) - 2; - assert( LeftBound <= RightBound ); - if ( LeftBound == RightBound ) - return; - // get the two last nodes - pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); - pObj2 = Vec_PtrEntry( vSuper, RightBound ); - if ( Aig_Regular(pObj1) == p->pConst1 || Aig_Regular(pObj2) == p->pConst1 ) - return; - // find the first node that can be shared - for ( i = RightBound; i >= LeftBound; i-- ) - { - pObj3 = Vec_PtrEntry( vSuper, i ); - if ( Aig_Regular(pObj3) == p->pConst1 ) - { - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - pGhost = Aig_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_OBJ_EXOR : AIG_OBJ_AND ); - if ( Aig_TableLookup( p, pGhost ) ) - { - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - } -/* - // we did not find the node to share, randomize choice - { - int Choice = rand() % (RightBound - LeftBound + 1); - pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_BalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pObj1, * pObj2; - int i; - if ( Vec_PtrPushUnique(vStore, pObj) ) - return; - // find the p of the node - for ( i = vStore->nSize-1; i > 0; i-- ) - { - pObj1 = vStore->pArray[i ]; - pObj2 = vStore->pArray[i-1]; - if ( Aig_ObjLevel(Aig_Regular(pObj1)) <= Aig_ObjLevel(Aig_Regular(pObj2)) ) - break; - vStore->pArray[i ] = pObj2; - vStore->pArray[i-1] = pObj1; - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/darCore.c b/src/aig/dar/darCore.c deleted file mode 100644 index 5e1c0fad..00000000 --- a/src/aig/dar/darCore.c +++ /dev/null @@ -1,244 +0,0 @@ -/**CFile**************************************************************** - - FileName [darCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [Core of the rewriting package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: darCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the structure with default assignment of parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_ManDefaultRwrParams( Dar_RwrPar_t * pPars ) -{ - memset( pPars, 0, sizeof(Dar_RwrPar_t) ); - pPars->nCutsMax = 8; // 8 - pPars->nSubgMax = 5; // 5 is a "magic number" - pPars->fFanout = 1; - pPars->fUpdateLevel = 0; - pPars->fUseZeros = 0; - pPars->fVerbose = 0; - pPars->fVeryVerbose = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_ManRewrite( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) -{ - Dar_Man_t * p; - Bar_Progress_t * pProgress; - Dar_Cut_t * pCut; - Aig_Obj_t * pObj, * pObjNew; - int i, k, nNodesOld, nNodeBefore, nNodeAfter, Required; - int clk = 0, clkStart; - // prepare the library - Dar_LibPrepare( pPars->nSubgMax ); - // create rewriting manager - p = Dar_ManStart( pAig, pPars ); - // remove dangling nodes - Aig_ManCleanup( pAig ); - // if updating levels is requested, start fanout and timing - if ( p->pPars->fFanout ) - Aig_ManFanoutStart( pAig ); - if ( p->pPars->fUpdateLevel ) - Aig_ManStartReverseLevels( pAig, 0 ); - // set elementary cuts for the PIs - Dar_ManCutsStart( p ); - // resynthesize each node once - clkStart = clock(); - p->nNodesInit = Aig_ManNodeNum(pAig); - nNodesOld = Vec_PtrSize( pAig->vObjs ); - - pProgress = Bar_ProgressStart( stdout, nNodesOld ); - Aig_ManForEachObj( pAig, pObj, i ) -// pProgress = Bar_ProgressStart( stdout, 100 ); -// Aig_ManOrderStart( pAig ); -// Aig_ManForEachNodeInOrder( pAig, pObj ) - { -// Bar_ProgressUpdate( pProgress, 100*pAig->nAndPrev/pAig->nAndTotal, NULL ); - - Bar_ProgressUpdate( pProgress, i, NULL ); - if ( !Aig_ObjIsNode(pObj) ) - continue; - if ( i > nNodesOld ) - break; - - // consider freeing the cuts -// if ( (i & 0xFFF) == 0 && Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) > 100 ) -// Dar_ManCutsStart( p ); - - // compute cuts for the node - p->nNodesTried++; -clk = clock(); - Dar_ObjComputeCuts_rec( p, pObj ); -p->timeCuts += clock() - clk; - - // check if there is a trivial cut - Dar_ObjForEachCut( pObj, pCut, k ) - if ( pCut->nLeaves == 0 || (pCut->nLeaves == 1 && pCut->pLeaves[0] != pObj->Id && Aig_ManObj(p->pAig, pCut->pLeaves[0])) ) - break; - if ( k < (int)pObj->nCuts ) - { - assert( pCut->nLeaves < 2 ); - if ( pCut->nLeaves == 0 ) // replace by constant - { - assert( pCut->uTruth == 0 || pCut->uTruth == 0xFFFF ); - pObjNew = Aig_NotCond( Aig_ManConst1(p->pAig), pCut->uTruth==0 ); - } - else - { - assert( pCut->uTruth == 0xAAAA || pCut->uTruth == 0x5555 ); - pObjNew = Aig_NotCond( Aig_ManObj(p->pAig, pCut->pLeaves[0]), pCut->uTruth==0x5555 ); - } - // remove the old cuts - Dar_ObjSetCuts( pObj, NULL ); - // replace the node - Aig_ObjReplace( pAig, pObj, pObjNew, 1, p->pPars->fUpdateLevel ); - continue; - } - - // evaluate the cuts - p->GainBest = -1; - Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : AIG_INFINITY; - Dar_ObjForEachCut( pObj, pCut, k ) - Dar_LibEval( p, pObj, pCut, Required ); - // check the best gain - if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) - { -// Aig_ObjOrderAdvance( pAig ); - continue; - } - // remove the old cuts - Dar_ObjSetCuts( pObj, NULL ); - // if we end up here, a rewriting step is accepted - nNodeBefore = Aig_ManNodeNum( pAig ); - pObjNew = Dar_LibBuildBest( p ); // pObjNew can be complemented! - pObjNew = Aig_NotCond( pObjNew, Aig_ObjPhaseReal(pObjNew) ^ pObj->fPhase ); - assert( (int)Aig_Regular(pObjNew)->Level <= Required ); - // replace the node - Aig_ObjReplace( pAig, pObj, pObjNew, 1, p->pPars->fUpdateLevel ); - // compare the gains - nNodeAfter = Aig_ManNodeNum( pAig ); - assert( p->GainBest <= nNodeBefore - nNodeAfter ); - // count gains of this class - p->ClassGains[p->ClassBest] += nNodeBefore - nNodeAfter; - } -// Aig_ManOrderStop( pAig ); - -p->timeTotal = clock() - clkStart; -p->timeOther = p->timeTotal - p->timeCuts - p->timeEval; - - Bar_ProgressStop( pProgress ); - p->nCutMemUsed = Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20); - Dar_ManCutsFree( p ); - // put the nodes into the DFS order and reassign their IDs -// Aig_NtkReassignIds( p ); - // fix the levels -// Aig_ManVerifyLevel( pAig ); - if ( p->pPars->fFanout ) - Aig_ManFanoutStop( pAig ); - if ( p->pPars->fUpdateLevel ) - { -// Aig_ManVerifyReverseLevel( pAig ); - Aig_ManStopReverseLevels( pAig ); - } - // stop the rewriting manager - Dar_ManStop( p ); - Aig_ManCheckPhase( pAig ); - // check - if ( !Aig_ManCheck( pAig ) ) - { - printf( "Aig_ManRewrite: The network check has failed.\n" ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_MmFixed_t * Dar_ManComputeCuts( Aig_Man_t * pAig, int nCutsMax ) -{ - Dar_Man_t * p; - Dar_RwrPar_t Pars, * pPars = &Pars; - Aig_Obj_t * pObj; - Aig_MmFixed_t * pMemCuts; - int i, nNodes, clk = 0, clkStart = clock(); - // remove dangling nodes - if ( nNodes = Aig_ManCleanup( pAig ) ) - { -// printf( "Removing %d nodes.\n", nNodes ); - } - // create default parameters - Dar_ManDefaultRwrParams( pPars ); - pPars->nCutsMax = nCutsMax; - // create rewriting manager - p = Dar_ManStart( pAig, pPars ); - // set elementary cuts for the PIs - Dar_ManCutsStart( p ); - // compute cuts for each nodes in the topological order - Aig_ManForEachNode( pAig, pObj, i ) - Dar_ObjComputeCuts( p, pObj ); - // free the cuts - pMemCuts = p->pMemCuts; - p->pMemCuts = NULL; -// Dar_ManCutsFree( p ); - // stop the rewriting manager - Dar_ManStop( p ); - return pMemCuts; -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/darCut.c b/src/aig/dar/darCut.c deleted file mode 100644 index 08bd77a9..00000000 --- a/src/aig/dar/darCut.c +++ /dev/null @@ -1,698 +0,0 @@ -/**CFile**************************************************************** - - FileName [darCut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [Computation of 4-input cuts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: darCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the number of 1s in the machine word.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dar_WordCountOnes( unsigned uWord ) -{ - uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); - uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); - uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); - uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); - return (uWord & 0x0000FFFF) + (uWord>>16); -} - -/**Function************************************************************* - - Synopsis [Compute the cost of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dar_CutFindValue( Dar_Man_t * p, Dar_Cut_t * pCut ) -{ - Aig_Obj_t * pLeaf; - int i, Value, nOnes; - assert( pCut->fUsed ); - Value = 0; - nOnes = 0; - Dar_CutForEachLeaf( p->pAig, pCut, pLeaf, i ) - { - if ( pLeaf == NULL ) - return 0; - assert( pLeaf != NULL ); - Value += pLeaf->nRefs; - nOnes += (pLeaf->nRefs == 1); - } - if ( pCut->nLeaves < 2 ) - return 1001; -// Value = Value * 100 / pCut->nLeaves; - if ( Value > 1000 ) - Value = 1000; - if ( nOnes > 3 ) - Value = 5 - nOnes; - return Value; -} - -/**Function************************************************************* - - Synopsis [Returns the next free cut to use.] - - Description [Uses the cut with the smallest value.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dar_Cut_t * Dar_CutFindFree( Dar_Man_t * p, Aig_Obj_t * pObj ) -{ - Dar_Cut_t * pCut, * pCutMax; - int i; - pCutMax = NULL; - Dar_ObjForEachCutAll( pObj, pCut, i ) - { - if ( pCut->fUsed == 0 ) - return pCut; - if ( pCut->nLeaves < 3 ) - continue; - if ( pCutMax == NULL || pCutMax->Value > pCut->Value ) - pCutMax = pCut; - } - if ( pCutMax == NULL ) - { - Dar_ObjForEachCutAll( pObj, pCut, i ) - { - if ( pCut->nLeaves < 2 ) - continue; - if ( pCutMax == NULL || pCutMax->Value > pCut->Value ) - pCutMax = pCut; - } - } - if ( pCutMax == NULL ) - { - Dar_ObjForEachCutAll( pObj, pCut, i ) - { - if ( pCutMax == NULL || pCutMax->Value > pCut->Value ) - pCutMax = pCut; - } - } - assert( pCutMax != NULL ); - pCutMax->fUsed = 0; - return pCutMax; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pDom is contained in pCut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dar_CutCheckDominance( Dar_Cut_t * pDom, Dar_Cut_t * pCut ) -{ - int i, k; - assert( pDom->fUsed && pCut->fUsed ); - for ( i = 0; i < (int)pDom->nLeaves; i++ ) - { - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) - break; - if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut - return 0; - } - // every node in pDom is contained in pCut - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the cut is contained.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dar_CutFilter( Aig_Obj_t * pObj, Dar_Cut_t * pCut ) -{ - Dar_Cut_t * pTemp; - int i; - assert( pCut->fUsed ); - // go through the cuts of the node - Dar_ObjForEachCut( pObj, pTemp, i ) - { - if ( pTemp == pCut ) - continue; - if ( pTemp->nLeaves > pCut->nLeaves ) - { - // skip the non-contained cuts - if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) - continue; - // check containment seriously - if ( Dar_CutCheckDominance( pCut, pTemp ) ) - { - // remove contained cut - pTemp->fUsed = 0; - } - } - else - { - // skip the non-contained cuts - if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) - continue; - // check containment seriously - if ( Dar_CutCheckDominance( pTemp, pCut ) ) - { - // remove the given cut - pCut->fUsed = 0; - return 1; - } - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dar_CutMergeOrdered( Dar_Cut_t * pC, Dar_Cut_t * pC0, Dar_Cut_t * pC1 ) -{ - int i, k, c; - assert( pC0->nLeaves >= pC1->nLeaves ); - - // the case of the largest cut sizes - if ( pC0->nLeaves == 4 && pC1->nLeaves == 4 ) - { - if ( pC0->uSign != pC1->uSign ) - return 0; - for ( i = 0; i < (int)pC0->nLeaves; i++ ) - if ( pC0->pLeaves[i] != pC1->pLeaves[i] ) - return 0; - for ( i = 0; i < (int)pC0->nLeaves; i++ ) - pC->pLeaves[i] = pC0->pLeaves[i]; - pC->nLeaves = pC0->nLeaves; - return 1; - } - - // the case when one of the cuts is the largest - if ( pC0->nLeaves == 4 ) - { - if ( (pC0->uSign & pC1->uSign) != pC1->uSign ) - return 0; - for ( i = 0; i < (int)pC1->nLeaves; i++ ) - { - for ( k = (int)pC0->nLeaves - 1; k >= 0; k-- ) - if ( pC0->pLeaves[k] == pC1->pLeaves[i] ) - break; - if ( k == -1 ) // did not find - return 0; - } - for ( i = 0; i < (int)pC0->nLeaves; i++ ) - pC->pLeaves[i] = pC0->pLeaves[i]; - pC->nLeaves = pC0->nLeaves; - return 1; - } - - // compare two cuts with different numbers - i = k = 0; - for ( c = 0; c < 4; c++ ) - { - if ( k == (int)pC1->nLeaves ) - { - if ( i == (int)pC0->nLeaves ) - { - pC->nLeaves = c; - return 1; - } - pC->pLeaves[c] = pC0->pLeaves[i++]; - continue; - } - if ( i == (int)pC0->nLeaves ) - { - if ( k == (int)pC1->nLeaves ) - { - pC->nLeaves = c; - return 1; - } - pC->pLeaves[c] = pC1->pLeaves[k++]; - continue; - } - if ( pC0->pLeaves[i] < pC1->pLeaves[k] ) - { - pC->pLeaves[c] = pC0->pLeaves[i++]; - continue; - } - if ( pC0->pLeaves[i] > pC1->pLeaves[k] ) - { - pC->pLeaves[c] = pC1->pLeaves[k++]; - continue; - } - pC->pLeaves[c] = pC0->pLeaves[i++]; - k++; - } - if ( i < (int)pC0->nLeaves || k < (int)pC1->nLeaves ) - return 0; - pC->nLeaves = c; - return 1; -} - -/**Function************************************************************* - - Synopsis [Prepares the object for FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dar_CutMerge( Dar_Cut_t * pCut, Dar_Cut_t * pCut0, Dar_Cut_t * pCut1 ) -{ - assert( !pCut->fUsed ); - // merge the nodes - if ( pCut0->nLeaves <= pCut1->nLeaves ) - { - if ( !Dar_CutMergeOrdered( pCut, pCut1, pCut0 ) ) - return 0; - } - else - { - if ( !Dar_CutMergeOrdered( pCut, pCut0, pCut1 ) ) - return 0; - } - pCut->uSign = pCut0->uSign | pCut1->uSign; - pCut->fUsed = 1; - return 1; -} - - -/**Function************************************************************* - - Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dar_CutTruthPhase( Dar_Cut_t * pCut, Dar_Cut_t * pCut1 ) -{ - unsigned uPhase = 0; - int i, k; - for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) - { - if ( k == (int)pCut1->nLeaves ) - break; - if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) - continue; - assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); - uPhase |= (1 << i); - k++; - } - return uPhase; -} - -/**Function************************************************************* - - Synopsis [Swaps two advancent variables of the truth table.] - - Description [Swaps variable iVar and iVar+1.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dar_CutTruthSwapAdjacentVars( unsigned uTruth, int iVar ) -{ - assert( iVar >= 0 && iVar <= 2 ); - if ( iVar == 0 ) - return (uTruth & 0x99999999) | ((uTruth & 0x22222222) << 1) | ((uTruth & 0x44444444) >> 1); - if ( iVar == 1 ) - return (uTruth & 0xC3C3C3C3) | ((uTruth & 0x0C0C0C0C) << 2) | ((uTruth & 0x30303030) >> 2); - if ( iVar == 2 ) - return (uTruth & 0xF00FF00F) | ((uTruth & 0x00F000F0) << 4) | ((uTruth & 0x0F000F00) >> 4); - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Expands the truth table according to the phase.] - - Description [The input and output truth tables are in pIn/pOut. The current number - of variables is nVars. The total number of variables in nVarsAll. The last argument - (Phase) contains shows where the variables should go.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dar_CutTruthStretch( unsigned uTruth, int nVars, unsigned Phase ) -{ - int i, k, Var = nVars - 1; - for ( i = 3; i >= 0; i-- ) - if ( Phase & (1 << i) ) - { - for ( k = Var; k < i; k++ ) - uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, k ); - Var--; - } - assert( Var == -1 ); - return uTruth; -} - -/**Function************************************************************* - - Synopsis [Shrinks the truth table according to the phase.] - - Description [The input and output truth tables are in pIn/pOut. The current number - of variables is nVars. The total number of variables in nVarsAll. The last argument - (Phase) contains shows what variables should remain.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dar_CutTruthShrink( unsigned uTruth, int nVars, unsigned Phase ) -{ - int i, k, Var = 0; - for ( i = 0; i < 4; i++ ) - if ( Phase & (1 << i) ) - { - for ( k = i-1; k >= Var; k-- ) - uTruth = Dar_CutTruthSwapAdjacentVars( uTruth, k ); - Var++; - } - return uTruth; -} - -/**Function************************************************************* - - Synopsis [Performs truth table computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dar_CutTruth( Dar_Cut_t * pCut, Dar_Cut_t * pCut0, Dar_Cut_t * pCut1, int fCompl0, int fCompl1 ) -{ - unsigned uTruth0 = fCompl0 ? ~pCut0->uTruth : pCut0->uTruth; - unsigned uTruth1 = fCompl1 ? ~pCut1->uTruth : pCut1->uTruth; - uTruth0 = Dar_CutTruthStretch( uTruth0, pCut0->nLeaves, Dar_CutTruthPhase(pCut, pCut0) ); - uTruth1 = Dar_CutTruthStretch( uTruth1, pCut1->nLeaves, Dar_CutTruthPhase(pCut, pCut1) ); - return uTruth0 & uTruth1; -} - -/**Function************************************************************* - - Synopsis [Minimize support of the cut.] - - Description [Returns 1 if the node's support has changed] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dar_CutSuppMinimize( Dar_Cut_t * pCut ) -{ - unsigned uMasks[4][2] = { - { 0x5555, 0xAAAA }, - { 0x3333, 0xCCCC }, - { 0x0F0F, 0xF0F0 }, - { 0x00FF, 0xFF00 } - }; - unsigned uPhase = 0, uTruth = 0xFFFF & pCut->uTruth; - int i, k, nLeaves; - assert( pCut->fUsed ); - // compute the truth support of the cut's function - nLeaves = pCut->nLeaves; - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - if ( (uTruth & uMasks[i][0]) == ((uTruth & uMasks[i][1]) >> (1 << i)) ) - nLeaves--; - else - uPhase |= (1 << i); - if ( nLeaves == (int)pCut->nLeaves ) - return 0; - // shrink the truth table - uTruth = Dar_CutTruthShrink( uTruth, pCut->nLeaves, uPhase ); - pCut->uTruth = 0xFFFF & uTruth; - // update leaves and signature - pCut->uSign = 0; - for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) - { - if ( !(uPhase & (1 << i)) ) - continue; - pCut->pLeaves[k++] = pCut->pLeaves[i]; - pCut->uSign |= Aig_ObjCutSign( pCut->pLeaves[i] ); - } - assert( k == nLeaves ); - pCut->nLeaves = nLeaves; - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_ManCutsFree( Dar_Man_t * p ) -{ - if ( p->pMemCuts == NULL ) - return; - Aig_MmFixedStop( p->pMemCuts, 0 ); - p->pMemCuts = NULL; -// Aig_ManCleanData( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dar_Cut_t * Dar_ObjPrepareCuts( Dar_Man_t * p, Aig_Obj_t * pObj ) -{ - Dar_Cut_t * pCutSet, * pCut; - int i; - assert( Dar_ObjCuts(pObj) == NULL ); - pObj->nCuts = p->pPars->nCutsMax; - // create the cutset of the node - pCutSet = (Dar_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts ); - Dar_ObjSetCuts( pObj, pCutSet ); - Dar_ObjForEachCut( pObj, pCut, i ) - pCut->fUsed = 0; - // add unit cut if needed - pCut = pCutSet; - pCut->fUsed = 1; - if ( Aig_ObjIsConst1(pObj) ) - { - pCut->nLeaves = 0; - pCut->uSign = 0; - pCut->uTruth = 0xFFFF; - } - else - { - pCut->nLeaves = 1; - pCut->pLeaves[0] = pObj->Id; - pCut->uSign = Aig_ObjCutSign( pObj->Id ); - pCut->uTruth = 0xAAAA; - } - pCut->Value = Dar_CutFindValue( p, pCut ); - return pCutSet; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_ManCutsStart( Dar_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManCleanData( p->pAig ); - Aig_MmFixedRestart( p->pMemCuts ); - Dar_ObjPrepareCuts( p, Aig_ManConst1(p->pAig) ); - Aig_ManForEachPi( p->pAig, pObj, i ) - Dar_ObjPrepareCuts( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dar_Cut_t * Dar_ObjComputeCuts( Dar_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pFanin0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); - Aig_Obj_t * pFanin1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); - Aig_Obj_t * pFaninR0 = Aig_Regular(pFanin0); - Aig_Obj_t * pFaninR1 = Aig_Regular(pFanin1); - Dar_Cut_t * pCutSet, * pCut0, * pCut1, * pCut; - int i, k, RetValue; - - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - assert( Dar_ObjCuts(pObj) == NULL ); - assert( Dar_ObjCuts(pFaninR0) != NULL ); - assert( Dar_ObjCuts(pFaninR1) != NULL ); - - // set up the first cut - pCutSet = Dar_ObjPrepareCuts( p, pObj ); - // make sure fanins cuts are computed - Dar_ObjForEachCut( pFaninR0, pCut0, i ) - Dar_ObjForEachCut( pFaninR1, pCut1, k ) - { - p->nCutsAll++; - // make sure K-feasible cut exists - if ( Dar_WordCountOnes(pCut0->uSign | pCut1->uSign) > 4 ) - continue; - // get the next cut of this node - pCut = Dar_CutFindFree( p, pObj ); - // create the new cut - if ( !Dar_CutMerge( pCut, pCut0, pCut1 ) ) - { - assert( !pCut->fUsed ); - continue; - } - p->nCutsTried++; - // check dominance - if ( Dar_CutFilter( pObj, pCut ) ) - { - assert( !pCut->fUsed ); - continue; - } - // compute truth table - pCut->uTruth = 0xFFFF & Dar_CutTruth( pCut, pCut0, pCut1, Aig_IsComplement(pFanin0), Aig_IsComplement(pFanin1) ); - - // minimize support of the cut - if ( Dar_CutSuppMinimize( pCut ) ) - { - RetValue = Dar_CutFilter( pObj, pCut ); - assert( !RetValue ); - } - - // assign the value of the cut - pCut->Value = Dar_CutFindValue( p, pCut ); - // if the cut contains removed node, do not use it - if ( pCut->Value == 0 ) - { - p->nCutsSkipped++; - pCut->fUsed = 0; - } - else if ( pCut->nLeaves < 2 ) - return pCutSet; - } - // count the number of nontrivial cuts cuts - Dar_ObjForEachCut( pObj, pCut, i ) - p->nCutsUsed += pCut->fUsed; - // discount trivial cut - p->nCutsUsed--; - return pCutSet; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dar_Cut_t * Dar_ObjComputeCuts_rec( Dar_Man_t * p, Aig_Obj_t * pObj ) -{ - if ( Dar_ObjCuts(pObj) ) - return Dar_ObjCuts(pObj); - if ( Aig_ObjIsBuf(pObj) ) - return Dar_ObjComputeCuts_rec( p, Aig_ObjFanin0(pObj) ); - Dar_ObjComputeCuts_rec( p, Aig_ObjFanin0(pObj) ); - Dar_ObjComputeCuts_rec( p, Aig_ObjFanin1(pObj) ); - return Dar_ObjComputeCuts( p, pObj ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/darData.c b/src/aig/dar/darData.c deleted file mode 100644 index abf1d378..00000000 --- a/src/aig/dar/darData.c +++ /dev/null @@ -1,11287 +0,0 @@ -/**CFile**************************************************************** - - FileName [dar_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [Storage for AIG subgraph data.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: dar_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -const int s_nDataSize1 = 2*43906; -unsigned int s_Data1[2*43906] = { - 4, 6, 5, 7, 9, 11, 5, 6, 4, 7, 15, 17, - 2, 8, 4, 21, 3, 10, 5, 25, 7, 25, 9, 25, - 2, 10, 7, 33, 9, 33, 2, 14, 5, 39, 6, 39, - 17, 39, 3, 16, 7, 47, 33, 47, 2, 16, 4, 53, - 7, 53, 3, 14, 5, 59, 17, 59, 53, 59, 3, 11, - 7, 67, 4, 68, 5, 66, 6, 73, 33, 67, 7, 76, - 5, 77, 9, 77, 9, 66, 33, 85, 3, 9, 4, 88, - 7, 91, 88, 93, 6, 88, 21, 89, 11, 89, 21, 100, - 25, 101, 11, 88, 7, 107, 33, 107, 2, 11, 5, 113, - 7, 112, 30, 113, 25, 113, 5, 120, 7, 121, 9, 120, - 9, 113, 25, 128, 21, 129, 9, 112, 2, 9, 6, 137, - 5, 138, 11, 136, 3, 17, 7, 144, 113, 145, 15, 144, - 113, 151, 3, 15, 6, 155, 4, 156, 17, 154, 113, 161, - 2, 17, 7, 165, 5, 166, 155, 165, 15, 164, 2, 15, - 6, 174, 17, 174, 3, 13, 113, 181, 135, 181, 143, 181, - 2, 12, 9, 189, 181, 189, 9, 192, 2, 13, 85, 197, - 107, 197, 3, 12, 7, 203, 11, 203, 33, 203, 197, 203, - 9, 211, 3, 19, 7, 215, 33, 215, 173, 215, 179, 215, - 2, 18, 215, 225, 2, 19, 151, 229, 161, 229, 3, 18, - 113, 235, 229, 235, 2, 4, 25, 241, 9, 241, 15, 241, - 11, 241, 6, 240, 7, 240, 59, 253, 7, 241, 9, 257, - 6, 241, 253, 261, 3, 5, 251, 265, 6, 266, 241, 269, - 253, 265, 7, 272, 7, 273, 241, 277, 53, 265, 7, 280, - 248, 265, 9, 285, 11, 265, 241, 288, 9, 291, 17, 265, - 9, 265, 257, 265, 25, 299, 251, 298, 7, 264, 3, 305, - 5, 305, 128, 305, 101, 305, 299, 305, 241, 305, 7, 317, - 265, 319, 9, 305, 113, 322, 113, 305, 9, 326, 6, 264, - 241, 331, 17, 331, 53, 331, 253, 331, 7, 265, 59, 341, - 241, 343, 331, 341, 241, 346, 241, 347, 15, 341, 113, 353, - 241, 340, 7, 357, 265, 357, 59, 357, 331, 357, 256, 265, - 7, 367, 59, 367, 331, 367, 6, 265, 5, 375, 242, 375, - 316, 375, 25, 375, 241, 382, 305, 375, 241, 386, 241, 387, - 11, 375, 241, 375, 265, 394, 7, 397, 25, 394, 305, 394, - 251, 395, 257, 375, 241, 374, 260, 265, 241, 265, 251, 413, - 331, 413, 261, 413, 375, 413, 257, 413, 19, 413, 12, 413, - 11, 413, 9, 428, 9, 413, 11, 433, 11, 432, 15, 413, - 11, 412, 9, 441, 7, 413, 241, 445, 265, 445, 375, 445, - 409, 445, 411, 445, 6, 412, 241, 457, 445, 457, 241, 460, - 6, 413, 357, 465, 367, 465, 7, 412, 265, 471, 59, 471, - 331, 471, 465, 471, 241, 479, 2, 6, 353, 483, 322, 483, - 30, 483, 25, 483, 9, 490, 305, 483, 9, 494, 19, 483, - 413, 483, 12, 483, 244, 483, 241, 483, 9, 506, 9, 483, - 305, 510, 25, 510, 11, 510, 241, 510, 257, 510, 247, 483, - 11, 483, 2, 524, 4, 527, 5, 524, 3, 531, 9, 524, - 258, 483, 151, 483, 257, 483, 9, 540, 155, 483, 17, 545, - 235, 483, 181, 483, 161, 483, 4, 482, 2, 555, 5, 482, - 2, 559, 6, 559, 17, 559, 5, 483, 2, 567, 6, 566, - 241, 567, 483, 573, 9, 573, 9, 567, 4, 483, 6, 581, - 3, 582, 3, 7, 289, 587, 510, 587, 11, 591, 11, 590, - 516, 587, 413, 587, 483, 598, 498, 587, 500, 587, 19, 587, - 483, 606, 502, 587, 12, 587, 483, 612, 534, 587, 524, 587, - 9, 618, 288, 587, 305, 623, 25, 623, 11, 587, 265, 629, - 331, 631, 510, 628, 9, 628, 483, 636, 483, 628, 9, 640, - 265, 628, 305, 645, 25, 645, 375, 628, 265, 587, 11, 653, - 33, 655, 11, 652, 25, 659, 305, 659, 295, 587, 241, 587, - 9, 587, 4, 668, 2, 671, 3, 668, 5, 675, 524, 668, - 483, 668, 11, 681, 11, 680, 11, 668, 483, 686, 392, 587, - 165, 587, 375, 587, 17, 695, 11, 695, 11, 694, 113, 587, - 567, 587, 305, 705, 25, 705, 555, 704, 5, 586, 3, 713, - 7, 713, 623, 713, 645, 713, 659, 713, 128, 713, 394, 713, - 101, 713, 299, 713, 705, 713, 510, 713, 483, 713, 9, 736, - 9, 713, 113, 740, 483, 740, 241, 713, 375, 746, 375, 713, - 241, 750, 113, 713, 9, 754, 4, 586, 7, 759, 589, 759, - 33, 759, 5, 587, 7, 767, 2, 768, 47, 767, 483, 773, - 759, 767, 483, 777, 17, 767, 113, 781, 483, 781, 483, 766, - 47, 787, 759, 787, 17, 787, 566, 587, 47, 795, 759, 795, - 17, 795, 4, 587, 3, 803, 6, 805, 7, 802, 494, 803, - 490, 803, 736, 803, 25, 803, 483, 816, 305, 803, 483, 820, - 713, 803, 483, 824, 483, 803, 305, 828, 25, 828, 713, 828, - 555, 829, 483, 802, 580, 587, 483, 587, 413, 842, 19, 842, - 12, 842, 11, 843, 9, 851, 9, 842, 11, 855, 11, 854, - 11, 842, 9, 860, 5, 843, 803, 865, 9, 865, 839, 865, - 841, 865, 4, 842, 483, 875, 865, 875, 483, 878, 4, 843, - 787, 883, 795, 883, 5, 842, 587, 889, 47, 889, 759, 889, - 17, 889, 883, 889, 483, 899, 3, 4, 559, 903, 19, 903, - 12, 903, 842, 903, 587, 903, 483, 912, 165, 912, 9, 903, - 11, 918, 483, 903, 241, 923, 555, 923, 587, 922, 11, 922, - 15, 903, 11, 903, 9, 934, 483, 934, 524, 903, 692, 903, - 767, 903, 375, 945, 165, 903, 7, 949, 587, 948, 6, 902, - 3, 955, 7, 902, 787, 959, 795, 959, 889, 959, 767, 959, - 483, 967, 33, 959, 7, 903, 956, 973, 88, 973, 4, 973, - 3, 973, 955, 980, 9, 980, 3, 972, 4, 972, 955, 973, - 3, 990, 375, 973, 9, 973, 3, 996, 6, 903, 4, 1001, - 3, 1001, 3, 1000, 4, 1000, 2, 5, 955, 1011, 914, 1011, - 918, 1011, 11, 1017, 11, 1016, 912, 1011, 483, 1022, 920, 1011, - 906, 1011, 19, 1011, 903, 1030, 842, 1011, 903, 1034, 908, 1011, - 910, 1011, 12, 1011, 903, 1042, 922, 1011, 587, 1046, 928, 1011, - 936, 1011, 934, 1011, 9, 1054, 15, 1011, 11, 1011, 918, 1060, - 9, 1060, 903, 1064, 903, 1060, 9, 1068, 483, 1011, 912, 1072, - 903, 1072, 587, 1076, 587, 1072, 903, 1080, 155, 1072, 587, 1011, - 922, 1086, 483, 1086, 903, 1090, 903, 1086, 483, 1094, 11, 1087, - 9, 1099, 9, 1086, 11, 1103, 17, 1011, 9, 1011, 934, 1108, - 903, 1108, 11, 1113, 11, 1112, 11, 1108, 903, 1118, 587, 1108, - 11, 1123, 668, 1011, 11, 1127, 544, 1011, 155, 1011, 483, 1132, - 67, 1011, 375, 1137, 7, 1010, 2, 1141, 959, 1141, 85, 1141, - 107, 1141, 203, 1141, 67, 1141, 9, 1153, 215, 1141, 47, 1141, - 759, 1141, 6, 1010, 2, 1163, 5, 1163, 17, 1163, 7, 1011, - 2, 1171, 5, 1171, 2, 1170, 5, 1170, 1163, 1171, 5, 1180, - 2, 1181, 483, 1171, 903, 1170, 375, 1189, 972, 1011, 375, 1193, - 6, 1011, 2, 1197, 5, 1197, 2, 1196, 5, 1196, 1141, 1197, - 2, 1206, 5, 1207, 903, 1196, 1000, 1011, 903, 1011, 19, 1216, - 842, 1216, 12, 1216, 11, 1217, 9, 1225, 587, 1216, 483, 1228, - 11, 1216, 9, 1232, 9, 1216, 11, 1237, 11, 1236, 15, 1216, - 483, 1216, 587, 1244, 7, 1217, 59, 1249, 331, 1249, 1213, 1249, - 1215, 1249, 6, 1216, 1249, 1259, 6, 1217, 1189, 1263, 1193, 1263, - 7, 1216, 375, 1269, 1263, 1269, 3, 6, 413, 1275, 1216, 1275, - 241, 1275, 9, 1281, 11, 1283, 11, 1280, 9, 1287, 17, 1275, - 3, 1290, 5, 1293, 4, 1290, 2, 1297, 903, 1291, 1011, 1275, - 11, 1275, 241, 1304, 9, 1307, 248, 1275, 9, 1311, 973, 1275, - 9, 1315, 341, 1275, 803, 1319, 9, 1319, 5, 1274, 3, 1325, - 17, 1325, 357, 1325, 367, 1325, 471, 1325, 341, 1325, 241, 1337, - 1249, 1325, 253, 1325, 53, 1325, 5, 1275, 6, 1347, 2, 1348, - 918, 1347, 903, 1347, 9, 1354, 9, 1347, 903, 1358, 4, 1275, - 6, 1362, 265, 1363, 2, 7, 393, 1369, 334, 1369, 1325, 1369, - 1363, 1374, 17, 1374, 62, 1369, 331, 1369, 17, 1382, 59, 1369, - 17, 1386, 1328, 1369, 1304, 1369, 9, 1393, 17, 1369, 331, 1396, - 241, 1397, 59, 1396, 1325, 1396, 11, 1369, 1275, 1406, 9, 1409, - 265, 1369, 241, 1412, 11, 1413, 15, 1369, 5, 1418, 3, 1421, - 2, 1418, 4, 1425, 1011, 1419, 107, 1369, 67, 1369, 803, 1433, - 9, 1433, 1359, 1369, 203, 1369, 215, 1369, 85, 1369, 5, 1368, - 2, 1447, 7, 1447, 47, 1447, 85, 1447, 107, 1447, 203, 1447, - 67, 1447, 9, 1461, 215, 1447, 759, 1447, 959, 1447, 4, 1368, - 2, 1471, 7, 1471, 265, 1471, 7, 1476, 331, 1471, 59, 1471, - 1325, 1471, 5, 1369, 7, 1486, 803, 1487, 1275, 1486, 803, 1493, - 9, 1493, 1346, 1369, 803, 1499, 9, 1499, 4, 1369, 7, 1505, - 3, 1506, 1060, 1505, 11, 1505, 1011, 1512, 1011, 1505, 7, 1517, - 11, 1517, 11, 1516, 1347, 1505, 1275, 1504, 1362, 1369, 1275, 1369, - 413, 1531, 19, 1531, 12, 1531, 1216, 1531, 1011, 1531, 903, 1540, - 9, 1531, 11, 1545, 11, 1544, 11, 1531, 9, 1550, 903, 1531, - 1011, 1554, 11, 1530, 9, 1559, 5, 1531, 959, 1563, 47, 1563, - 759, 1563, 17, 1563, 1527, 1563, 1529, 1563, 4, 1530, 1563, 1577, - 4, 1531, 1493, 1581, 1499, 1581, 5, 1530, 803, 1587, 9, 1587, - 1581, 1587, 1, 974, 1, 975, 1, 982, 1, 983, 0, 204, - 0, 195, 0, 881, 0, 463, 0, 212, 0, 900, 0, 480, - 0, 194, 0, 880, 0, 462, 0, 213, 0, 901, 0, 481, - 0, 205, 0, 216, 0, 217, 1, 446, 0, 448, 0, 415, - 0, 421, 1, 92, 0, 92, 1, 94, 1645, 1647, 1, 93, - 88, 1650, 1645, 1653, 0, 93, 1, 95, 1657, 1659, 0, 108, - 0, 109, 1, 360, 0, 368, 0, 358, 0, 414, 1, 447, - 1637, 1675, 0, 449, 1635, 1679, 0, 191, 0, 877, 0, 473, - 1, 473, 0, 459, 1, 459, 0, 891, 0, 207, 0, 458, - 0, 876, 0, 190, 1, 458, 0, 472, 0, 890, 0, 206, - 1, 472, 1, 977, 1, 976, 0, 399, 0, 398, 0, 397, - 7, 1722, 0, 275, 0, 269, 241, 1728, 0, 270, 1, 279, - 0, 321, 0, 274, 0, 271, 1, 278, 0, 320, 1, 277, - 241, 1746, 0, 319, 265, 1750, 1, 276, 0, 318, 1, 926, - 0, 1518, 0, 950, 0, 1519, 0, 951, 1, 998, 1, 999, - 0, 575, 0, 1478, 0, 282, 0, 1479, 0, 283, 0, 369, - 0, 359, 1667, 1785, 0, 420, 1, 422, 1, 927, 1, 1421, - 5, 1794, 1419, 1797, 3, 1794, 1799, 1801, 0, 527, 2, 1804, - 525, 1807, 4, 1804, 1809, 1811, 1, 671, 4, 1814, 669, 1817, - 2, 1814, 1819, 1821, 0, 1293, 3, 1824, 1291, 1827, 5, 1824, - 1829, 1831, 1, 1425, 2, 1834, 1419, 1837, 4, 1834, 1839, 1841, - 0, 531, 5, 1844, 525, 1847, 3, 1844, 1849, 1851, 1, 675, - 3, 1854, 669, 1857, 5, 1854, 1859, 1861, 0, 1297, 4, 1864, - 1291, 1867, 2, 1864, 1869, 1871, 1, 1422, 0, 528, 1, 672, - 0, 1294, 1, 1426, 0, 532, 1, 676, 0, 1298, 1, 123, - 0, 79, 1, 993, 0, 124, 1, 80, 0, 1210, 0, 1184, - 0, 125, 1891, 1905, 1, 81, 1893, 1909, 1, 122, 1897, 1913, - 0, 78, 1899, 1917, 0, 1208, 0, 1182, 1, 992, 1, 361, - 1671, 1927, 0, 574, 1, 984, 1, 985, 1, 114, 9, 1937, - 0, 68, 1, 980, 955, 1942, 9, 1942, 0, 568, 9, 1949, - 1, 924, 1, 925, 0, 306, 375, 1957, 0, 308, 1413, 1961, - 0, 26, 1, 306, 1, 308, 1, 714, 0, 1142, 0, 1448, - 0, 1450, 1, 1450, 1413, 1979, 0, 1474, 0, 54, 0, 56, - 1, 1472, 0, 1326, 0, 60, 1, 60, 0, 1166, 0, 40, - 1, 956, 973, 2001, 973, 2000, 0, 556, 1, 22, 0, 1475, - 1, 1165, 1168, 2012, 1169, 2013, 2015, 2017, 1168, 2013, 1169, 2012, - 2021, 2023, 1, 1167, 2, 2027, 1197, 2029, 1997, 2031, 0, 57, - 1, 957, 0, 1451, 1980, 2039, 1979, 2039, 1413, 2042, 1413, 2039, - 1979, 2046, 1, 1449, 5, 2051, 1451, 2053, 1975, 2055, 1, 1451, - 1977, 2059, 1413, 2061, 0, 307, 1967, 2065, 375, 2067, 0, 309, - 1969, 2071, 1413, 2073, 0, 41, 1, 307, 1958, 2079, 1957, 2079, - 375, 2082, 375, 2079, 1957, 2086, 1, 309, 1962, 2091, 1961, 2091, - 1413, 2094, 1413, 2091, 1961, 2098, 1, 41, 2, 2103, 43, 2105, - 1999, 2107, 1, 1143, 5, 2111, 1171, 2113, 1973, 2115, 1, 561, - 564, 2118, 565, 2119, 2121, 2123, 564, 2119, 565, 2118, 2127, 2129, - 0, 91, 7, 2132, 0, 569, 1, 981, 9, 2139, 955, 2139, - 0, 69, 9, 2145, 1, 115, 0, 432, 0, 500, 0, 1245, - 0, 1237, 0, 501, 0, 433, 1, 1415, 1, 348, 1, 388, - 1, 826, 1, 126, 1, 1376, 1, 380, 1, 814, 1, 118, - 1, 302, 1, 710, 1, 102, 1, 402, 1, 834, 1, 130, - 1, 404, 1, 836, 1, 132, 1, 314, 1, 732, 1, 104, - 0, 1236, 0, 1244, 1, 1414, 0, 202, 1, 888, 1, 202, - 1603, 2215, 0, 106, 1, 106, 1663, 2221, 1, 794, 0, 366, - 0, 84, 1, 786, 1, 84, 1941, 2233, 1, 390, 1, 994, - 1, 450, 1, 105, 1, 733, 1, 405, 1, 315, 1, 837, - 1, 133, 1, 407, 1, 451, 1, 391, 1, 1383, 0, 905, - 1, 905, 0, 1477, 1, 1477, 1775, 2269, 6, 2269, 7, 2269, - 6, 2268, 2275, 2277, 1983, 2269, 7, 2268, 2273, 2283, 0, 281, - 1, 281, 1777, 2289, 6, 2289, 7, 2289, 6, 2288, 2295, 2297, - 1987, 2289, 7, 2288, 2293, 2303, 1, 1387, 1, 406, 2227, 2309, - 1, 995, 0, 461, 1, 461, 1621, 2317, 1699, 2317, 0, 1261, - 1, 1261, 0, 879, 0, 193, 1, 879, 1619, 2331, 1701, 2331, - 1, 193, 1617, 2337, 1703, 2337, 0, 1579, 0, 211, 9, 2344, - 1, 1579, 1, 211, 1623, 2351, 1711, 2351, 0, 479, 241, 2356, - 0, 899, 483, 2360, 0, 227, 1, 479, 1627, 2367, 1707, 2367, - 1, 899, 1625, 2373, 1709, 2373, 1, 227, 0, 1273, 0, 1593, - 0, 239, 1, 1273, 1, 1593, 1, 239, 0, 478, 2367, 2393, - 1, 478, 2359, 2397, 1615, 2397, 2357, 2397, 1687, 2397, 0, 1272, - 2387, 2407, 1, 1272, 2381, 2411, 0, 898, 2373, 2415, 0, 210, - 2351, 2419, 1, 898, 2363, 2423, 1613, 2423, 2361, 2423, 1695, 2423, - 1, 210, 2347, 2433, 1611, 2433, 2345, 2433, 1697, 2433, 0, 1592, - 2389, 2443, 0, 192, 9, 2446, 2337, 2449, 2337, 2447, 1, 1592, - 2383, 2455, 1, 192, 1605, 2459, 2329, 2459, 1683, 2459, 0, 460, - 241, 2466, 2317, 2469, 2317, 2467, 0, 878, 483, 2474, 2331, 2477, - 2331, 2475, 0, 238, 2391, 2483, 1, 460, 1609, 2487, 2315, 2487, - 1691, 2487, 1, 878, 1607, 2495, 2327, 2495, 1685, 2495, 1, 238, - 2385, 2503, 0, 1260, 2325, 2507, 0, 1578, 2349, 2511, 0, 226, - 2379, 2515, 1, 1260, 2323, 2519, 1, 1578, 2343, 2523, 1, 226, - 2365, 2527, 1, 349, 1, 127, 1, 827, 1, 389, 1, 119, - 1, 815, 1, 381, 1, 1377, 1, 131, 1, 835, 1, 303, - 1, 403, 1, 711, 1, 103, 1, 1366, 1, 694, 1, 702, - 9, 2563, 0, 572, 1, 572, 1931, 2569, 0, 1516, 1, 1516, - 1761, 2575, 7, 2575, 6, 2574, 2579, 2581, 6, 2575, 7, 2574, - 2585, 2587, 0, 944, 0, 948, 1, 578, 587, 2595, 1, 948, - 1763, 2599, 7, 2599, 6, 2598, 2603, 2605, 6, 2599, 7, 2598, - 2609, 2611, 1, 1186, 1, 996, 3, 2616, 1, 544, 1, 465, - 471, 2622, 1687, 2625, 1, 197, 203, 2628, 1697, 2631, 1, 883, - 889, 2634, 1695, 2637, 1, 181, 189, 2640, 1683, 2643, 0, 445, - 1693, 2647, 1713, 2647, 265, 2646, 1675, 2653, 2257, 2647, 375, 2647, - 457, 2647, 1, 445, 264, 2662, 241, 2662, 1679, 2667, 375, 2662, - 457, 2662, 1691, 2673, 1, 865, 875, 2676, 1685, 2679, 0, 215, - 7, 2682, 1, 215, 1633, 2687, 1, 1563, 0, 457, 241, 2692, - 2317, 2695, 1, 457, 241, 2698, 445, 2699, 445, 2698, 1691, 2705, - 0, 875, 483, 2708, 2331, 2711, 1, 875, 865, 2714, 1685, 2717, - 0, 189, 9, 2720, 2337, 2723, 1, 189, 181, 2726, 1683, 2729, - 0, 203, 7, 2732, 2215, 2735, 11, 2732, 2351, 2739, 0, 471, - 7, 2742, 1689, 2745, 265, 2742, 2367, 2749, 0, 889, 587, 2752, - 2373, 2755, 1, 203, 1629, 2759, 197, 2758, 1697, 2763, 1, 471, - 265, 2766, 2647, 2769, 465, 2766, 1687, 2773, 1, 889, 883, 2776, - 1695, 2779, 0, 107, 7, 2782, 2221, 2785, 1, 107, 1665, 2789, - 1, 795, 0, 367, 2255, 2795, 375, 2795, 7, 2794, 1, 367, - 265, 2802, 1783, 2805, 0, 85, 7, 2808, 2233, 2811, 0, 357, - 7, 2814, 1927, 2817, 1, 85, 2145, 2821, 1, 357, 265, 2824, - 1785, 2827, 1, 787, 0, 573, 483, 2832, 2569, 2835, 1, 579, - 1, 573, 1773, 2841, 1, 997, 1, 545, 1, 1187, 903, 2849, - 1, 1367, 0, 949, 7, 2854, 2599, 2857, 0, 945, 483, 2861, - 1, 949, 1767, 2865, 0, 1517, 7, 2868, 2575, 2871, 1, 1517, - 1765, 2875, 1, 703, 1, 695, 1, 332, 1, 266, 1731, 2885, - 1733, 2885, 1, 1012, 1, 30, 113, 2892, 0, 316, 265, 2896, - 375, 2897, 0, 272, 7, 2902, 1735, 2903, 1, 736, 803, 2908, - 1, 316, 1737, 2913, 375, 2912, 1, 272, 1727, 2919, 241, 2918, - 0, 1374, 2545, 2925, 1, 1374, 1363, 2928, 1, 1382, 0, 904, - 483, 2934, 2265, 2937, 1, 904, 0, 1476, 7, 2942, 2269, 2945, - 1, 1476, 1779, 2949, 2011, 2949, 0, 280, 7, 2954, 2289, 2957, - 1, 280, 1781, 2961, 2035, 2961, 1, 1386, 1, 99, 1, 991, - 0, 1181, 2, 2972, 0, 347, 2165, 2977, 1, 347, 1, 263, - 273, 2983, 272, 2982, 2985, 2987, 272, 2983, 273, 2982, 2991, 2993, - 0, 77, 0, 1207, 5, 2998, 1, 77, 5, 3002, 1917, 3005, - 9, 3003, 0, 121, 7, 3010, 1913, 3013, 9, 3011, 0, 387, - 2259, 3019, 1, 121, 9, 3023, 1, 825, 483, 3027, 1, 387, - 241, 3030, 241, 3031, 1, 98, 0, 1206, 2, 3038, 0, 386, - 2237, 3043, 3033, 3043, 1, 386, 241, 3048, 1, 824, 483, 3052, - 1, 990, 3, 3056, 0, 120, 3023, 3061, 9, 3063, 0, 1180, - 5, 3066, 1, 120, 3016, 3071, 5, 3070, 1897, 3075, 3013, 3075, - 3011, 3071, 9, 3080, 9, 3070, 9, 3071, 3011, 3086, 0, 76, - 3008, 3091, 7, 3090, 1899, 3095, 3005, 3095, 3003, 3091, 9, 3100, - 9, 3091, 3003, 3104, 0, 346, 2531, 3109, 1, 76, 2997, 3113, - 9, 3115, 1, 776, 1, 346, 241, 3120, 2977, 3123, 1, 21, - 2, 3127, 1275, 3129, 9, 3131, 4, 3126, 3133, 3135, 2, 3126, - 668, 3139, 3135, 3141, 587, 3139, 9, 3144, 3135, 3147, 9, 3139, - 587, 3150, 3135, 3153, 100, 3126, 129, 3126, 129, 3127, 100, 3127, - 89, 3127, 11, 3164, 11, 3127, 89, 3169, 89, 3168, 89, 3126, - 0, 25, 2243, 3177, 2547, 3177, 2539, 3177, 2533, 3177, 3024, 3177, - 3, 3177, 1369, 3189, 11, 3191, 5, 3176, 3193, 3195, 3, 3176, - 524, 3199, 3195, 3201, 483, 3199, 11, 3204, 3195, 3207, 11, 3199, - 483, 3210, 3195, 3213, 3023, 3177, 9, 3216, 101, 3177, 128, 3177, - 113, 3177, 9, 3224, 9, 3177, 3023, 3228, 113, 3228, 1, 33, - 5, 3234, 6, 3237, 2997, 3235, 9, 3241, 3177, 3235, 67, 3235, - 9, 3247, 67, 3234, 3239, 3251, 1, 25, 128, 3254, 101, 3254, - 113, 3255, 9, 3254, 113, 3262, 113, 3254, 9, 3266, 9, 3267, - 0, 33, 2759, 3273, 2789, 3273, 2821, 3273, 9, 3273, 67, 3272, - 9, 3283, 1, 251, 298, 3286, 395, 3286, 395, 3287, 298, 3287, - 257, 3287, 265, 3297, 265, 3296, 265, 3287, 257, 3302, 265, 3286, - 0, 305, 2249, 3309, 2553, 3309, 2543, 3309, 2537, 3309, 3034, 3309, - 3031, 3309, 241, 3320, 3235, 3309, 299, 3309, 394, 3309, 375, 3309, - 241, 3330, 241, 3309, 3031, 3334, 375, 3334, 241, 3308, 375, 3341, - 1, 331, 2647, 3345, 413, 3345, 241, 3344, 1369, 3344, 341, 3344, - 0, 253, 7, 3356, 265, 3356, 3345, 3357, 1, 555, 923, 3364, - 923, 3365, 704, 3364, 829, 3364, 829, 3365, 704, 3365, 0, 713, - 2245, 3379, 2549, 3379, 2541, 3379, 2535, 3379, 3028, 3379, 3027, 3379, - 483, 3390, 3235, 3379, 705, 3379, 828, 3379, 803, 3379, 483, 3400, - 483, 3379, 3027, 3404, 803, 3404, 1, 759, 3, 3410, 6, 3413, - 3273, 3411, 767, 3410, 3415, 3419, 0, 559, 0, 251, 413, 3424, - 413, 3425, 257, 3425, 413, 3431, 412, 3430, 3433, 3435, 412, 3431, - 413, 3430, 3439, 3441, 1, 305, 3, 3445, 375, 3447, 3, 3444, - 394, 3444, 299, 3444, 241, 3444, 375, 3456, 375, 3444, 241, 3460, - 1, 253, 265, 3464, 0, 555, 4, 3469, 15, 3471, 483, 3473, - 2, 3468, 3475, 3477, 4, 3468, 524, 3481, 3477, 3483, 11, 3481, - 483, 3486, 3477, 3489, 483, 3481, 11, 3492, 3477, 3495, 1, 713, - 5, 3499, 17, 3501, 587, 3503, 3, 3498, 3505, 3507, 5, 3498, - 668, 3511, 3507, 3513, 9, 3511, 587, 3516, 3507, 3519, 587, 3511, - 9, 3522, 3507, 3525, 828, 3498, 705, 3498, 483, 3498, 803, 3532, - 803, 3498, 483, 3536, 1, 559, 903, 3540, 1, 955, 980, 3544, - 3, 3544, 973, 3549, 973, 3548, 973, 3545, 2139, 3555, 1011, 3544, - 973, 3544, 3, 3560, 0, 1141, 2, 3564, 9, 3565, 3411, 3565, - 0, 1447, 9, 3573, 3411, 3573, 1, 1471, 4, 3579, 11, 3581, - 1369, 3583, 2, 3578, 3585, 3587, 4, 3578, 1418, 3591, 3587, 3593, - 15, 3591, 1369, 3596, 3587, 3599, 1369, 3591, 15, 3602, 3587, 3605, - 265, 3578, 2011, 3609, 0, 1325, 5, 3613, 9, 3615, 1275, 3617, - 3, 3612, 3619, 3621, 5, 3612, 1290, 3625, 3621, 3627, 17, 3625, - 1275, 3630, 3621, 3633, 1275, 3625, 17, 3636, 3621, 3639, 1, 53, - 265, 3642, 2035, 3645, 0, 59, 5, 3648, 1, 1141, 3177, 3653, - 3379, 3653, 3309, 3653, 0, 1163, 5, 3660, 1, 959, 3565, 3665, - 3273, 3665, 3573, 3665, 1, 1447, 3177, 3673, 3309, 3673, 3379, 3673, - 0, 1471, 7, 3680, 2269, 3683, 3345, 3681, 1, 1325, 1369, 3688, - 3357, 3689, 3681, 3689, 0, 39, 5, 3696, 1, 47, 3565, 3701, - 3573, 3701, 3273, 3701, 0, 53, 2, 3709, 587, 3711, 17, 3713, - 7, 3708, 2289, 3717, 4, 3708, 3715, 3721, 2, 3708, 1290, 3725, - 3721, 3727, 1275, 3725, 17, 3730, 3721, 3733, 17, 3725, 1275, 3736, - 3721, 3739, 3345, 3709, 3689, 3709, 1, 59, 3, 3747, 483, 3749, - 15, 3751, 5, 3746, 3753, 3755, 3, 3746, 1418, 3759, 3755, 3761, - 1369, 3759, 15, 3764, 3755, 3767, 15, 3759, 1369, 3770, 3755, 3773, - 1369, 3746, 3681, 3747, 3357, 3747, 3709, 3747, 1, 330, 1369, 3785, - 471, 3785, 367, 3785, 357, 3785, 341, 3785, 241, 3795, 0, 1162, - 17, 3799, 0, 758, 767, 3803, 0, 32, 2215, 3807, 2221, 3807, - 2233, 3807, 3249, 3807, 3246, 3807, 9, 3817, 3235, 3807, 67, 3820, - 9, 3823, 67, 3807, 3235, 3826, 9, 3829, 1, 758, 3807, 3833, - 1, 32, 3104, 3837, 3284, 3837, 3091, 3837, 9, 3842, 3283, 3837, - 9, 3846, 3273, 3837, 67, 3851, 9, 3853, 9, 3837, 3283, 3856, - 3091, 3856, 0, 1470, 3785, 3863, 0, 24, 2203, 3867, 3259, 3867, - 2191, 3867, 3257, 3867, 2179, 3867, 2895, 3867, 2171, 3867, 3265, 3867, - 3269, 3867, 3085, 3867, 3071, 3867, 9, 3889, 3267, 3867, 9, 3893, - 2893, 3867, 113, 3897, 3263, 3867, 113, 3901, 3255, 3867, 101, 3905, - 128, 3905, 113, 3905, 9, 3910, 9, 3905, 113, 3914, 3837, 3867, - 128, 3867, 101, 3867, 9, 3867, 113, 3924, 113, 3867, 9, 3928, - 1, 24, 3220, 3933, 3222, 3933, 3232, 3933, 3226, 3933, 3224, 3933, - 9, 3942, 3228, 3933, 113, 3946, 3177, 3933, 101, 3950, 128, 3950, - 113, 3950, 9, 3956, 9, 3950, 113, 3960, 128, 3933, 3177, 3964, - 101, 3933, 3177, 3968, 9, 3933, 3224, 3972, 3177, 3972, 113, 3976, - 113, 3972, 3177, 3980, 113, 3933, 3228, 3984, 3177, 3984, 9, 3988, - 9, 3984, 3177, 3992, 0, 712, 2201, 3997, 3531, 3997, 2189, 3997, - 3529, 3997, 2177, 3997, 2911, 3997, 2169, 3997, 3535, 3997, 3539, 3997, - 3055, 3997, 3053, 3997, 483, 4019, 3537, 3997, 483, 4023, 2909, 3997, - 803, 4027, 3533, 3997, 803, 4031, 3499, 3997, 705, 4035, 828, 4035, - 803, 4035, 483, 4040, 483, 4035, 803, 4044, 3837, 3997, 828, 3997, - 705, 3997, 483, 3997, 803, 4054, 803, 3997, 483, 4058, 0, 52, - 3785, 4063, 0, 304, 2199, 4067, 3455, 4067, 2187, 4067, 3453, 4067, - 2175, 4067, 2917, 4067, 2167, 4067, 3459, 4067, 3463, 4067, 3051, 4067, - 3049, 4067, 241, 4089, 3461, 4067, 241, 4093, 2913, 4067, 375, 4097, - 3457, 4067, 375, 4101, 3445, 4067, 299, 4105, 394, 4105, 375, 4105, - 241, 4110, 241, 4105, 375, 4114, 3837, 4067, 394, 4067, 299, 4067, - 241, 4067, 375, 4124, 375, 4067, 241, 4128, 0, 38, 17, 4133, - 0, 252, 265, 4137, 3785, 4137, 0, 558, 17, 4143, 1, 712, - 3396, 4147, 3398, 4147, 3408, 4147, 3402, 4147, 3400, 4147, 483, 4156, - 3404, 4147, 803, 4160, 3379, 4147, 705, 4164, 828, 4164, 803, 4164, - 483, 4170, 483, 4164, 803, 4174, 9, 4147, 828, 4147, 3379, 4180, - 705, 4147, 3379, 4184, 483, 4147, 3400, 4188, 3379, 4188, 803, 4192, - 803, 4188, 3379, 4196, 803, 4147, 3404, 4200, 3379, 4200, 483, 4204, - 483, 4200, 3379, 4208, 1, 304, 3326, 4213, 3328, 4213, 3338, 4213, - 3332, 4213, 3330, 4213, 241, 4222, 3334, 4213, 375, 4226, 3309, 4213, - 299, 4230, 394, 4230, 375, 4230, 241, 4236, 241, 4230, 375, 4240, - 9, 4213, 394, 4213, 3309, 4246, 299, 4213, 3309, 4250, 241, 4213, - 3330, 4254, 3309, 4254, 375, 4258, 375, 4254, 3309, 4262, 375, 4213, - 3334, 4266, 3309, 4266, 241, 4270, 241, 4266, 3309, 4274, 0, 1446, - 3833, 4279, 0, 1140, 3833, 4283, 1, 1446, 3867, 4287, 3997, 4287, - 4067, 4287, 1, 46, 4279, 4295, 3807, 4295, 4283, 4295, 1, 1140, - 3867, 4303, 4067, 4303, 3997, 4303, 1, 58, 1369, 4311, 4063, 4311, - 3863, 4311, 4137, 4311, 1, 958, 3807, 4321, 4279, 4321, 4283, 4321, - 1, 1324, 1369, 4329, 3863, 4329, 4063, 4329, 4137, 4329, 1, 214, - 1631, 4339, 2685, 4339, 0, 214, 1, 1562, 1, 444, 449, 4349, - 7, 4349, 265, 4353, 2647, 4355, 2658, 4349, 251, 4349, 2647, 4349, - 375, 4362, 375, 4349, 2647, 4366, 0, 444, 2701, 4371, 1689, 4371, - 1705, 4371, 447, 4371, 2665, 4371, 2241, 4371, 3785, 4371, 2671, 4371, - 265, 4371, 331, 4371, 2663, 4371, 375, 4393, 375, 4371, 1, 510, - 257, 4399, 1, 1058, 0, 1396, 0, 1406, 0, 628, 375, 4409, - 1, 652, 1, 288, 1, 267, 1741, 4417, 1, 1013, 1, 1375, - 1, 333, 2903, 4425, 3361, 4425, 0, 1375, 2931, 4431, 2173, 4431, - 1, 273, 2905, 4437, 1739, 4437, 6, 4436, 7, 4437, 4443, 4445, - 6, 4437, 3359, 4437, 7, 4436, 4449, 4453, 0, 273, 2883, 4457, - 2913, 4457, 3351, 4457, 3457, 4457, 2923, 4457, 1749, 4457, 1743, 4457, - 1, 31, 3224, 4473, 3177, 4473, 113, 4476, 113, 4473, 3177, 4480, - 1, 737, 3400, 4485, 3379, 4485, 803, 4488, 803, 4485, 3379, 4492, - 1, 317, 2903, 4497, 3361, 4497, 2900, 4497, 7, 4497, 265, 4505, - 2897, 4507, 1753, 4497, 1745, 4497, 3330, 4497, 2897, 4497, 375, 4516, - 3309, 4497, 375, 4520, 375, 4497, 2897, 4524, 3309, 4524, 0, 317, - 7, 4530, 2913, 4531, 375, 4535, 375, 4531, 1, 507, 1, 245, - 0, 1397, 1, 913, 0, 1407, 1, 653, 11, 4551, 1, 289, - 1, 629, 713, 4557, 25, 4557, 305, 4557, 0, 629, 375, 4565, - 0, 340, 3785, 4569, 4311, 4569, 4329, 4569, 4555, 4569, 0, 766, - 1413, 4579, 922, 4579, 903, 4579, 483, 4584, 483, 4579, 903, 4588, - 0, 66, 75, 4593, 7, 4593, 3113, 4593, 9, 4599, 3251, 4593, - 9, 4603, 375, 4593, 483, 4593, 9, 4593, 1, 340, 331, 4613, - 1, 766, 483, 4616, 2591, 4617, 483, 4621, 1, 66, 5, 4624, - 6, 4627, 3248, 4625, 1941, 4625, 9, 4633, 36, 4625, 3247, 4625, - 9, 4638, 9, 4624, 1941, 4643, 3807, 4643, 33, 4625, 9, 4648, - 9, 4625, 3247, 4652, 33, 4652, 3807, 4625, 9, 4659, 0, 1170, - 2615, 4663, 903, 4665, 0, 112, 3972, 4669, 3270, 4669, 3086, 4669, - 1938, 4669, 1937, 4669, 9, 4678, 2564, 4669, 3071, 4669, 9, 4684, - 3267, 4669, 9, 4688, 2563, 4669, 9, 4692, 9, 4669, 3267, 4696, - 3933, 4696, 1937, 4696, 3071, 4696, 2563, 4696, 3933, 4669, 9, 4708, - 1, 1170, 1413, 4713, 922, 4713, 483, 4713, 903, 4718, 903, 4713, - 483, 4722, 1, 112, 2, 4727, 7, 4729, 3261, 4727, 9, 4733, - 25, 4727, 903, 4727, 587, 4727, 9, 4727, 0, 972, 3059, 4745, - 1925, 4745, 3563, 4745, 3553, 4745, 3549, 4745, 3547, 4745, 2005, 4745, - 2001, 4745, 1595, 4745, 1945, 4745, 1599, 4745, 2239, 4745, 1717, 4745, - 2619, 4745, 1769, 4745, 1947, 4745, 1933, 4745, 1943, 4745, 955, 4781, - 9, 4781, 0, 802, 807, 4787, 375, 4787, 7, 4787, 805, 4793, - 265, 4793, 483, 4787, 0, 144, 483, 4801, 1, 972, 3551, 4805, - 2003, 4805, 375, 4805, 955, 4805, 9, 4805, 1011, 4805, 1, 802, - 713, 4819, 483, 4819, 1, 144, 0, 256, 2309, 4827, 4437, 4827, - 264, 4826, 299, 4833, 264, 4827, 367, 4837, 265, 4826, 2309, 4841, - 4805, 4827, 4613, 4827, 375, 4827, 510, 4827, 483, 4827, 9, 4852, - 9, 4827, 483, 4856, 0, 1504, 1, 256, 2798, 4863, 7, 4863, - 265, 4867, 264, 4862, 264, 4863, 2795, 4863, 375, 4874, 265, 4862, - 4873, 4879, 305, 4863, 713, 4863, 25, 4863, 375, 4863, 2795, 4888, - 265, 4863, 4871, 4893, 1, 164, 0, 374, 241, 4899, 0, 1346, - 9, 4903, 0, 154, 0, 1412, 2853, 4909, 2163, 4909, 0, 1418, - 1, 1346, 1, 154, 483, 4919, 1, 1412, 241, 4922, 1, 1290, - 4915, 4927, 1, 1280, 1, 246, 0, 566, 2596, 4935, 586, 4934, - 705, 4939, 586, 4935, 795, 4943, 2595, 4935, 587, 4946, 587, 4935, - 2595, 4950, 0, 1086, 375, 4955, 0, 922, 1759, 4959, 2265, 4959, - 3367, 4959, 4421, 4959, 1953, 4959, 1, 566, 5, 4971, 6, 4973, - 1950, 4971, 1949, 4971, 9, 4978, 586, 4970, 586, 4971, 587, 4970, - 4985, 4987, 4827, 4971, 9, 4971, 1949, 4992, 4745, 4971, 4569, 4971, - 587, 4971, 4983, 5001, 1, 1086, 9, 5005, 1, 922, 3369, 5009, - 555, 5009, 257, 5009, 1, 932, 0, 88, 3171, 5019, 10, 5018, - 101, 5023, 101, 5019, 10, 5019, 107, 5029, 0, 934, 375, 5033, - 0, 1108, 587, 5037, 1, 1362, 265, 5041, 1, 88, 93, 5045, - 1643, 5047, 93, 5044, 1645, 5051, 1645, 5045, 2135, 5045, 973, 5044, - 4745, 5059, 3163, 5045, 3173, 5045, 3167, 5045, 7, 5044, 10, 5044, - 10, 5045, 11, 5044, 3807, 5075, 5073, 5075, 33, 5045, 21, 5045, - 973, 5045, 4805, 5085, 3807, 5045, 4279, 5045, 4283, 5045, 4745, 5045, - 11, 5045, 5071, 5097, 1, 1304, 1, 1108, 973, 5103, 972, 5102, - 5105, 5107, 972, 5103, 973, 5102, 5111, 5113, 257, 5103, 0, 260, - 0, 580, 0, 136, 0, 668, 1, 260, 4139, 5127, 4138, 5127, - 264, 5126, 5131, 5133, 264, 5127, 4137, 5137, 265, 5126, 4137, 5141, - 5137, 5142, 5129, 5141, 5138, 5141, 5137, 5141, 4137, 5150, 265, 5127, - 4137, 5154, 5133, 5157, 5133, 5155, 4137, 5161, 4137, 5127, 265, 5165, - 5137, 5167, 265, 5164, 5133, 5171, 1, 580, 1, 136, 5019, 5177, - 1, 524, 5125, 5181, 1, 296, 5019, 5185, 0, 1413, 2559, 5189, - 2209, 5189, 4925, 5189, 0, 1419, 5181, 5197, 1, 295, 973, 5201, - 972, 5201, 49, 5201, 48, 5201, 972, 5200, 5203, 5211, 973, 5200, - 5205, 5215, 48, 5200, 5207, 5219, 49, 5200, 5209, 5223, 1, 1413, - 1417, 5227, 1, 1291, 5125, 5231, 5197, 5231, 0, 1087, 375, 5237, - 0, 923, 1793, 5241, 2941, 5241, 5012, 5241, 3543, 5241, 3559, 5241, - 2891, 5241, 5017, 5241, 1955, 5241, 555, 5241, 5009, 5258, 5009, 5241, - 555, 5262, 1, 1087, 5037, 5267, 1, 923, 555, 5270, 4959, 5273, - 241, 5270, 4959, 5277, 4959, 5271, 555, 5281, 1, 933, 4959, 5285, - 0, 935, 375, 5289, 0, 1109, 5005, 5293, 1, 935, 0, 669, - 4927, 5299, 1, 525, 4915, 5303, 5299, 5303, 1, 669, 1, 297, - 0, 341, 483, 5313, 3747, 5313, 3689, 5313, 3345, 5313, 4415, 5313, - 0, 257, 2255, 5325, 4888, 5325, 4881, 5325, 3467, 5325, 2919, 5325, - 4871, 5325, 4893, 5336, 4894, 5325, 7, 5324, 4863, 5343, 4872, 5325, - 4879, 5347, 4869, 5325, 4893, 5325, 4871, 5352, 5343, 5353, 3, 5325, - 5, 5358, 4862, 5360, 4863, 5361, 5363, 5365, 5343, 5364, 4862, 5361, - 4863, 5360, 5371, 5373, 5344, 5361, 5343, 5361, 4863, 5378, 5, 5325, - 3, 5382, 4862, 5384, 4863, 5385, 5387, 5389, 5343, 5388, 4862, 5385, - 4863, 5384, 5395, 5397, 5344, 5385, 5343, 5385, 4863, 5402, 264, 5325, - 4863, 5406, 4879, 5409, 5344, 5407, 5343, 5407, 4863, 5414, 4863, 5407, - 4871, 5419, 5343, 5418, 7, 5325, 265, 5425, 4863, 5427, 266, 5325, - 375, 5325, 4863, 5432, 510, 5325, 483, 5325, 9, 5438, 9, 5325, - 483, 5442, 251, 5325, 265, 5446, 265, 5447, 4892, 5325, 265, 5325, - 257, 5454, 1, 5457, 7, 5455, 5459, 5461, 0, 5461, 5457, 5465, - 251, 5454, 4863, 5454, 4863, 5325, 3, 5472, 5, 5474, 5, 5472, - 3, 5478, 375, 5472, 7, 5473, 5361, 5485, 5385, 5485, 5477, 5485, - 5481, 5485, 5407, 5485, 264, 5472, 4879, 5497, 5485, 5497, 264, 5473, - 4893, 5503, 265, 5472, 265, 5324, 4417, 5509, 251, 5509, 1, 341, - 5325, 5515, 331, 5514, 1, 257, 445, 5521, 265, 5522, 449, 5521, - 448, 5521, 414, 5521, 415, 5521, 421, 5521, 420, 5521, 253, 5521, - 265, 5538, 340, 5521, 341, 5521, 272, 5520, 241, 5546, 273, 5521, - 5549, 5551, 272, 5521, 273, 5520, 412, 5521, 251, 5559, 241, 5520, - 265, 5562, 5551, 5565, 272, 5563, 5557, 5569, 500, 5521, 432, 5521, - 501, 5521, 413, 5520, 5525, 5579, 5529, 5579, 5533, 5579, 5535, 5579, - 5555, 5579, 5541, 5579, 251, 5579, 5559, 5592, 5560, 5579, 5559, 5579, - 251, 5598, 5577, 5579, 433, 5521, 5579, 5605, 264, 5520, 5543, 5609, - 367, 5609, 264, 5521, 299, 5615, 412, 5520, 5527, 5619, 5531, 5619, - 5537, 5619, 5551, 5619, 5573, 5619, 5575, 5619, 413, 5521, 375, 5632, - 5619, 5635, 251, 5632, 5619, 5639, 5619, 5633, 251, 5643, 483, 5632, - 5619, 5647, 9, 5632, 5619, 5651, 7, 5521, 265, 5654, 5609, 5657, - 265, 5655, 5615, 5661, 2227, 5521, 375, 5665, 4841, 5521, 375, 5669, - 375, 5520, 2227, 5673, 4841, 5673, 4827, 5673, 375, 5521, 413, 5680, - 5619, 5683, 413, 5681, 5559, 5687, 483, 5521, 413, 5690, 5619, 5693, - 413, 5691, 5559, 5697, 9, 5521, 413, 5700, 5619, 5703, 413, 5701, - 5559, 5707, 251, 5521, 413, 5710, 5619, 5713, 413, 5711, 5559, 5717, - 265, 5521, 445, 5720, 5579, 5723, 253, 5720, 5579, 5727, 7, 5720, - 5609, 5731, 4827, 5521, 3, 5735, 5, 5736, 5, 5735, 3, 5740, - 375, 5735, 7, 5734, 5739, 5747, 5743, 5747, 264, 5735, 5747, 5753, - 265, 5735, 265, 5520, 2647, 5759, 5545, 5759, 1783, 5759, 241, 5758, - 5551, 5767, 0, 1171, 4714, 5771, 4716, 5771, 4720, 5771, 4724, 5771, - 2850, 5771, 1413, 5771, 4713, 5782, 922, 5771, 4713, 5786, 4718, 5771, - 903, 5790, 2849, 5771, 903, 5794, 483, 5771, 4722, 5798, 903, 5798, - 4713, 5802, 4713, 5798, 903, 5806, 4722, 5771, 483, 5810, 903, 5771, - 4718, 5814, 2849, 5814, 483, 5814, 4713, 5820, 4713, 5814, 483, 5824, - 4713, 5771, 1413, 5828, 922, 5828, 483, 5828, 903, 5834, 903, 5828, - 483, 5838, 0, 973, 1895, 5843, 2037, 5843, 1597, 5843, 1601, 5843, - 2142, 5843, 2313, 5843, 4810, 5843, 1715, 5843, 1771, 5843, 1935, 5843, - 2140, 5843, 2139, 5843, 955, 5866, 9, 5866, 375, 5843, 4805, 5872, - 483, 5843, 9, 5843, 2139, 5878, 955, 5843, 2139, 5882, 1011, 5843, - 4805, 5843, 375, 5888, 1, 1171, 3, 5892, 4663, 5895, 903, 5897, - 483, 5892, 4663, 5901, 903, 5903, 4663, 5893, 1413, 5907, 922, 5907, - 483, 5907, 903, 5912, 903, 5907, 483, 5916, 1, 973, 956, 5920, - 4745, 5923, 88, 5920, 4745, 5927, 5, 5920, 4745, 5931, 1011, 5933, - 3, 5920, 955, 5936, 4745, 5939, 9, 5936, 4745, 5943, 4745, 5937, - 955, 5947, 9, 5947, 375, 5920, 4745, 5953, 955, 5920, 3, 5956, - 4745, 5959, 5325, 5921, 9, 5920, 3, 5964, 4745, 5967, 4745, 5921, - 375, 5971, 0, 767, 903, 5974, 4617, 5977, 483, 5979, 4617, 5975, - 1413, 5983, 922, 5983, 903, 5983, 483, 5988, 483, 5983, 903, 5992, - 0, 567, 4989, 5997, 4983, 5997, 5001, 6000, 5002, 5997, 4984, 5997, - 4987, 6007, 5001, 5997, 4983, 6010, 3, 5997, 7, 6014, 4970, 6016, - 4971, 6017, 6019, 6021, 4970, 6017, 4971, 6016, 6025, 6027, 7, 5997, - 3, 6030, 4970, 6032, 4971, 6033, 6035, 6037, 4970, 6033, 4971, 6032, - 6041, 6043, 3, 5996, 7, 6047, 2, 5996, 4992, 6051, 6015, 6051, - 7, 6055, 4971, 6057, 9, 6051, 4971, 6060, 4971, 6051, 9, 6064, - 586, 5997, 4971, 6068, 4987, 6071, 4971, 6069, 4983, 6075, 2, 5997, - 6048, 6079, 4971, 6081, 7, 6079, 6047, 6084, 4971, 6087, 4971, 6085, - 6047, 6091, 6047, 6079, 7, 6094, 4971, 6097, 4992, 5997, 587, 6101, - 2839, 5997, 587, 6105, 9, 5997, 4971, 6108, 587, 6111, 4971, 5997, - 2, 6115, 7, 6117, 4975, 6117, 586, 6114, 4987, 6123, 5, 6114, - 6, 6127, 6117, 6129, 6119, 6127, 586, 6115, 5001, 6135, 9, 6114, - 587, 6139, 587, 6115, 9, 6143, 0, 67, 4636, 6147, 37, 6147, - 3008, 6147, 4656, 6147, 4650, 6147, 7, 6146, 4643, 6159, 2233, 6159, - 4625, 6159, 9, 6165, 5, 6147, 6, 6169, 36, 6147, 4625, 6172, - 3807, 6173, 4648, 6147, 9, 6178, 3003, 6147, 9, 6182, 33, 6146, - 6151, 6187, 3856, 6187, 3837, 6187, 9, 6192, 9, 6187, 3837, 6196, - 33, 6147, 4652, 6200, 3807, 6201, 9, 6205, 9, 6200, 4625, 6208, - 3807, 6209, 4625, 6200, 9, 6214, 4652, 6147, 33, 6218, 9, 6147, - 4648, 6222, 3003, 6222, 33, 6222, 4625, 6228, 3807, 6229, 33, 6223, - 3837, 6235, 4625, 6222, 33, 6238, 4625, 6147, 75, 6243, 4629, 6243, - 7, 6243, 4627, 6249, 6171, 6243, 375, 6243, 36, 6242, 33, 6242, - 9, 6258, 9, 6242, 33, 6262, 0, 89, 5079, 6267, 5071, 6267, - 5097, 6270, 5098, 6267, 5072, 6267, 5075, 6277, 5097, 6267, 5071, 6280, - 107, 6267, 5, 6267, 7, 6286, 5044, 6288, 5045, 6289, 6291, 6293, - 5044, 6289, 5045, 6288, 6297, 6299, 7, 6267, 5, 6302, 5044, 6304, - 5045, 6305, 6307, 6309, 5044, 6305, 5045, 6304, 6313, 6315, 5, 6266, - 7, 6318, 5045, 6321, 7, 6319, 7, 6266, 5, 6326, 5045, 6329, - 5075, 6327, 2221, 6327, 5045, 6327, 4, 6266, 6287, 6339, 7, 6341, - 5045, 6343, 10, 6266, 5075, 6347, 2221, 6347, 5045, 6347, 10, 6267, - 5097, 6355, 5045, 6354, 5075, 6359, 5045, 6355, 5071, 6363, 1274, 6267, - 4, 6267, 6324, 6369, 5045, 6371, 7, 6369, 6319, 6374, 5045, 6377, - 5044, 6374, 5045, 6375, 6319, 6383, 6381, 6383, 5044, 6375, 5045, 6374, - 6389, 6391, 6319, 6369, 7, 6394, 5045, 6397, 6, 6267, 3, 6400, - 3, 6267, 6, 6404, 21, 6267, 11, 6409, 5045, 6411, 5045, 6267, - 10, 6414, 5075, 6417, 10, 6415, 5097, 6421, 5311, 6267, 11, 6266, - 2969, 6427, 5082, 6427, 5045, 6427, 21, 6432, 21, 6427, 5045, 6436, - 1, 767, 4580, 6441, 4582, 6441, 4586, 6441, 4590, 6441, 2862, 6441, - 1413, 6441, 4579, 6452, 922, 6441, 4579, 6456, 4584, 6441, 483, 6460, - 2861, 6441, 483, 6464, 759, 6440, 903, 6441, 4588, 6470, 483, 6470, - 4579, 6474, 4579, 6470, 483, 6478, 4588, 6441, 903, 6482, 483, 6441, - 4584, 6486, 2861, 6486, 903, 6486, 4579, 6492, 4579, 6486, 903, 6496, - 4579, 6441, 1413, 6500, 922, 6500, 903, 6500, 483, 6506, 483, 6500, - 903, 6510, 1, 567, 5, 6514, 6, 6517, 4935, 6517, 2137, 6515, - 9, 6523, 14, 6515, 2, 6515, 563, 6529, 4935, 6531, 6519, 6529, - 4935, 6535, 7, 6529, 6520, 6539, 4935, 6539, 6517, 6542, 6517, 6539, - 4935, 6546, 1197, 6529, 4935, 6551, 6, 6515, 5, 6554, 5, 6515, - 6, 6558, 5325, 6515, 903, 6515, 9, 6514, 4950, 6567, 587, 6567, - 4935, 6570, 4935, 6567, 587, 6574, 241, 6515, 4950, 6515, 9, 6581, - 587, 6515, 9, 6585, 4935, 6587, 4935, 6584, 9, 6591, 4935, 6515, - 2, 6594, 7, 6597, 5, 6595, 6539, 6601, 6599, 6601, 6, 6601, - 6597, 6607, 9, 6595, 587, 6611, 587, 6594, 9, 6615, 5843, 6515, - 5313, 6515, 587, 6514, 1, 67, 4594, 6625, 4606, 6625, 3280, 6625, - 75, 6625, 4593, 6632, 2146, 6625, 2145, 6625, 9, 6638, 7, 6625, - 73, 6643, 4593, 6645, 375, 6625, 4593, 6648, 33, 6624, 4593, 6653, - 9, 6655, 9, 6625, 3273, 6658, 2145, 6658, 4593, 6625, 75, 6664, - 375, 6664, 36, 6665, 33, 6665, 9, 6672, 9, 6665, 33, 6676, - 3273, 6625, 9, 6680, 1, 89, 1657, 6685, 25, 6685, 3565, 6685, - 3573, 6685, 3273, 6685, 21, 6684, 483, 6685, 5843, 6685, 11, 6684, - 0, 1487, 10, 6705, 7, 6705, 5, 6708, 5, 6705, 7, 6712, - 0, 1347, 0, 113, 2149, 6719, 9, 6721, 4736, 6719, 9, 6725, - 3023, 6719, 9, 6729, 4740, 6719, 9, 6733, 2879, 6719, 9, 6737, - 587, 6719, 4727, 6740, 9, 6743, 25, 6719, 4727, 6746, 9, 6749, - 4727, 6719, 5, 6753, 6, 6755, 4731, 6755, 2, 6752, 7, 6761, - 6755, 6763, 6757, 6761, 25, 6752, 9, 6769, 587, 6752, 9, 6773, - 9, 6753, 25, 6777, 587, 6777, 3255, 6719, 9, 6783, 0, 137, - 1, 113, 31, 6788, 2, 6788, 7, 6793, 4669, 6793, 4697, 6789, - 14, 6788, 6, 6789, 6, 6788, 5, 6804, 11, 6788, 5, 6808, - 5, 6788, 6, 6813, 6, 6812, 4696, 6813, 9, 6813, 4669, 6820, - 4669, 6813, 9, 6824, 7, 6788, 6815, 6829, 15, 6788, 6803, 6833, - 8, 6788, 8, 6789, 4669, 6839, 1368, 6789, 5, 6789, 35, 6845, - 4669, 6847, 6795, 6845, 4669, 6851, 6, 6845, 6796, 6855, 4669, 6855, - 6793, 6858, 6793, 6855, 4669, 6862, 1171, 6845, 4669, 6867, 17, 6845, - 4669, 6871, 7, 6789, 6811, 6875, 6807, 6875, 6817, 6875, 6801, 6875, - 2, 6874, 2, 6789, 7, 6886, 30, 6788, 3867, 6891, 25, 6788, - 4696, 6895, 3867, 6895, 9, 6899, 9, 6894, 3867, 6903, 4669, 6895, - 9, 6906, 9, 6895, 4669, 6910, 587, 6788, 4696, 6915, 9, 6915, - 4669, 6918, 4669, 6915, 9, 6922, 25, 6789, 4473, 6927, 6791, 6927, - 3972, 6927, 3933, 6927, 9, 6934, 9, 6927, 3933, 6938, 4696, 6789, - 6837, 6943, 25, 6943, 587, 6943, 9, 6789, 6837, 6951, 4669, 6953, - 587, 6951, 4669, 6957, 25, 6951, 4669, 6961, 4669, 6950, 25, 6965, - 6837, 6965, 587, 6965, 4669, 6789, 5, 6972, 6, 6975, 2, 6973, - 6855, 6979, 6977, 6979, 7, 6979, 6975, 6985, 25, 6973, 9, 6989, - 587, 6973, 9, 6993, 9, 6972, 6837, 6997, 25, 6997, 587, 6997, - 9, 6973, 6839, 7005, 9, 6788, 6799, 7009, 6840, 7009, 6839, 7009, - 4669, 7014, 4669, 7009, 6839, 7018, 25, 7008, 3867, 7023, 25, 7009, - 3933, 7027, 1, 137, 6267, 7031, 0, 375, 413, 7034, 413, 7035, - 241, 7034, 3307, 7041, 2885, 7041, 0, 261, 0, 803, 16, 7049, - 7, 7049, 4, 7052, 4, 7049, 7, 7056, 0, 581, 0, 145, - 1, 375, 317, 7064, 265, 7065, 256, 7068, 256, 7069, 4901, 7065, - 4, 7065, 2, 7077, 265, 7077, 2, 7076, 4899, 7083, 2, 7065, - 265, 7087, 4, 7086, 4899, 7091, 2, 7064, 265, 7064, 3, 7064, - 7084, 7099, 7092, 7099, 7083, 7099, 4899, 7104, 7091, 7099, 4899, 7108, - 7075, 7099, 4899, 7099, 7083, 7114, 7091, 7114, 240, 7064, 240, 7065, - 265, 7123, 7, 7125, 7114, 7123, 7099, 7123, 4899, 7130, 4899, 7123, - 7099, 7134, 413, 7065, 7, 7138, 3, 7065, 7079, 7143, 4899, 7145, - 7081, 7143, 4899, 7149, 5, 7065, 7089, 7153, 4899, 7155, 445, 7065, - 4349, 7159, 7121, 7159, 367, 7065, 4863, 7165, 973, 7065, 4805, 7169, - 316, 7064, 4067, 7173, 973, 7064, 4745, 7177, 445, 7064, 4371, 7181, - 257, 7064, 4841, 7185, 2227, 7185, 4827, 7185, 7071, 7185, 305, 7064, - 4067, 7195, 241, 7197, 241, 7194, 4067, 7201, 587, 7064, 257, 7065, - 4863, 7207, 7073, 7207, 628, 7065, 587, 7065, 11, 7214, 11, 7065, - 587, 7218, 241, 7219, 305, 7065, 4497, 7225, 7067, 7225, 4254, 7225, - 4213, 7225, 241, 7232, 241, 7225, 4213, 7236, 4900, 7065, 7121, 7241, - 7095, 7241, 7097, 7241, 241, 7065, 7095, 7249, 4899, 7251, 7097, 7249, - 4899, 7255, 6, 7249, 7121, 7249, 4899, 7261, 4899, 7248, 7121, 7265, - 7095, 7265, 7097, 7265, 4899, 7065, 241, 7272, 7121, 7275, 7095, 7275, - 7097, 7275, 241, 7273, 7123, 7283, 241, 7064, 4371, 7287, 7141, 7287, - 7127, 7287, 7075, 7287, 7134, 7287, 7123, 7287, 4899, 7298, 4899, 7287, - 7123, 7302, 305, 7286, 4067, 7307, 305, 7287, 4213, 7311, 1, 261, - 413, 7315, 3357, 7315, 264, 7319, 265, 7318, 7321, 7323, 264, 7318, - 265, 7319, 7327, 7329, 1, 803, 737, 7332, 4799, 7333, 1274, 7332, - 6, 7333, 2, 7341, 2, 7340, 4787, 7345, 2, 7333, 6, 7348, - 4787, 7351, 2, 7332, 6, 7332, 3, 7356, 587, 7332, 3, 7360, - 3, 7332, 7346, 7365, 7352, 7365, 7345, 7365, 4787, 7370, 7351, 7365, - 4787, 7374, 6, 7365, 6, 7364, 7337, 7365, 4787, 7365, 7345, 7384, - 7351, 7384, 7, 7332, 7379, 7391, 1275, 7332, 7341, 7395, 482, 7332, - 482, 7333, 7384, 7401, 7365, 7401, 4787, 7404, 4787, 7401, 7365, 7408, - 3, 7333, 7343, 7413, 4787, 7415, 7, 7333, 7363, 7419, 7359, 7419, - 7381, 7419, 7339, 7419, 736, 7332, 3997, 7429, 713, 7332, 3997, 7433, - 483, 7435, 483, 7432, 3997, 7439, 11, 7333, 483, 7443, 713, 7333, - 4485, 7447, 7335, 7447, 4188, 7447, 4147, 7447, 483, 7454, 483, 7447, - 4147, 7458, 4798, 7333, 7399, 7463, 7355, 7463, 483, 7333, 7355, 7469, - 4787, 7471, 7399, 7469, 4787, 7475, 4787, 7468, 7399, 7479, 7355, 7479, - 4787, 7333, 483, 7484, 7399, 7487, 7355, 7487, 483, 7485, 7401, 7493, - 483, 7332, 7337, 7497, 7408, 7497, 7401, 7497, 4787, 7502, 4787, 7497, - 7401, 7506, 713, 7496, 3997, 7511, 713, 7497, 4147, 7515, 1, 145, - 586, 7519, 7, 7519, 3, 7522, 3, 7519, 7, 7526, 1, 155, - 483, 7530, 0, 175, 482, 7535, 6, 7535, 2, 7538, 2, 7535, - 6, 7542, 1, 1505, 1011, 7546, 6, 7549, 7, 7549, 6, 7548, - 7553, 7555, 7, 7548, 7551, 7559, 1, 1363, 8, 7563, 6, 7563, - 4, 7566, 4, 7563, 6, 7570, 1374, 7563, 4423, 7575, 1374, 7562, - 4431, 7579, 265, 7562, 5189, 7583, 1, 165, 903, 7586, 6, 7589, - 7, 7589, 6, 7588, 7593, 7595, 7, 7588, 7591, 7599, 1, 175, - 44, 7602, 45, 7603, 7605, 7607, 44, 7603, 45, 7602, 7611, 7613, - 0, 299, 3289, 7617, 2181, 7617, 3307, 7617, 2885, 7617, 1, 299, - 4371, 7627, 2801, 7627, 1669, 7627, 5461, 7627, 3295, 7627, 305, 7626, - 4067, 7639, 251, 7627, 305, 7627, 4213, 7645, 0, 705, 3371, 7649, - 2183, 7649, 0, 101, 3157, 7655, 2185, 7655, 3175, 7655, 6697, 7655, - 3037, 7655, 6685, 7655, 21, 7667, 1, 705, 3377, 7671, 713, 7670, - 3997, 7675, 555, 7671, 713, 7671, 4147, 7681, 1, 101, 3163, 7685, - 25, 7684, 3867, 7689, 21, 7685, 25, 7685, 3933, 7695, 0, 129, - 2253, 7699, 21, 7699, 1, 129, 21, 7704, 0, 395, 2247, 7709, - 4417, 7709, 265, 7709, 7, 7715, 251, 7709, 0, 829, 2251, 7721, - 555, 7721, 1, 395, 2647, 7727, 1719, 7727, 251, 7726, 1, 829, - 555, 7734, 0, 298, 265, 7739, 7, 7741, 7627, 7743, 2551, 7739, - 7642, 7739, 4417, 7739, 7627, 7739, 251, 7752, 251, 7739, 7627, 7756, - 1, 298, 2647, 7761, 1783, 7761, 251, 7760, 7617, 7767, 7617, 7761, - 251, 7771, 0, 704, 2555, 7775, 7678, 7775, 7671, 7775, 555, 7780, - 555, 7775, 7671, 7784, 0, 100, 2557, 7789, 7692, 7789, 2969, 7789, - 5082, 7789, 5045, 7789, 21, 7798, 7685, 7789, 21, 7802, 21, 7789, - 7685, 7806, 5045, 7806, 1, 704, 555, 7812, 7649, 7815, 7649, 7813, - 555, 7819, 1, 100, 21, 7822, 7655, 7825, 7655, 7823, 21, 7829, - 0, 128, 3159, 7833, 2197, 7833, 7707, 7833, 7705, 7833, 21, 7841, - 1, 128, 3161, 7845, 7702, 7845, 25, 7844, 3867, 7851, 21, 7845, - 7699, 7854, 7699, 7845, 21, 7858, 25, 7845, 3933, 7863, 0, 394, - 3291, 7867, 2193, 7867, 7733, 7867, 2885, 7867, 3307, 7867, 7727, 7867, - 251, 7879, 0, 828, 3373, 7883, 2195, 7883, 7737, 7883, 7735, 7883, - 555, 7891, 1, 394, 4371, 7895, 3293, 7895, 7718, 7895, 1721, 7895, - 1725, 7895, 7717, 7895, 305, 7894, 4067, 7909, 251, 7895, 7709, 7912, - 7709, 7895, 251, 7916, 305, 7895, 4213, 7921, 1, 828, 3375, 7925, - 7724, 7925, 713, 7924, 3997, 7931, 555, 7925, 7721, 7934, 7721, 7925, - 555, 7938, 713, 7925, 4147, 7943, 0, 8, 6, 7947, 3, 7948, - 1274, 7947, 113, 7947, 3, 7947, 0, 7957, 6, 7956, 0, 7956, - 9, 7963, 11, 7957, 587, 7947, 1, 10, 5081, 7971, 5026, 7971, - 7, 7971, 2, 7976, 1368, 7971, 5097, 7971, 931, 7971, 1417, 7971, - 939, 7971, 941, 7971, 272, 7971, 1476, 7971, 280, 7971, 949, 7971, - 1517, 7971, 4696, 7971, 149, 7971, 631, 7971, 970, 7971, 50, 7971, - 764, 7971, 357, 7971, 367, 7971, 471, 7971, 1249, 7971, 5019, 7971, - 101, 8022, 128, 7971, 101, 7971, 5019, 8028, 4669, 7971, 9, 8032, - 759, 7971, 33, 8036, 1471, 7971, 265, 8040, 959, 7971, 33, 8044, - 253, 7971, 265, 8048, 113, 7971, 9, 8052, 375, 7971, 88, 7971, - 89, 7971, 2, 7971, 1, 8063, 7, 8062, 1, 8062, 11, 8069, - 9, 8063, 3, 7971, 9, 8074, 33, 7971, 959, 8078, 47, 8078, - 759, 8078, 25, 7971, 305, 7971, 713, 7971, 2, 7970, 8059, 8093, - 8077, 8093, 8075, 8093, 9, 8099, 3867, 8093, 3997, 8093, 4067, 8093, - 3, 7970, 4696, 8109, 8061, 8109, 8072, 8109, 8063, 8109, 9, 8116, - 4669, 8109, 9, 8120, 9, 8109, 4669, 8124, 8063, 8124, 47, 7971, - 33, 8130, 53, 7971, 265, 8134, 265, 7971, 253, 8138, 1471, 8138, - 53, 8138, 587, 7971, 483, 7971, 9, 7971, 4669, 8150, 113, 8150, - 3, 8150, 8093, 8157, 3, 8151, 8063, 8161, 0, 10, 203, 8165, - 107, 8165, 5019, 8169, 85, 8165, 2215, 8165, 2221, 8165, 2233, 8165, - 5075, 8165, 4643, 8165, 5045, 8165, 25, 8185, 4551, 8165, 922, 8165, - 1413, 8165, 273, 8165, 281, 8165, 1477, 8165, 1516, 8165, 948, 8165, - 4625, 8165, 9, 8205, 759, 8165, 959, 8165, 67, 8165, 9, 8213, - 1505, 8165, 1011, 8216, 88, 8165, 33, 8221, 89, 8165, 5019, 8225, - 3, 8165, 33, 8229, 9, 8231, 8063, 8229, 9, 8228, 33, 8237, - 2, 8165, 9, 8241, 33, 8165, 1141, 8165, 1447, 8165, 2, 8164, - 2215, 8251, 2221, 8251, 5075, 8251, 2233, 8251, 4643, 8251, 8229, 8251, - 4625, 8251, 9, 8265, 4295, 8251, 3833, 8251, 4321, 8251, 5045, 8251, - 3, 8164, 8241, 8277, 8093, 8277, 3837, 8277, 4287, 8277, 4303, 8277, - 128, 8277, 101, 8277, 113, 8277, 9, 8292, 9, 8277, 113, 8296, - 47, 8165, 165, 8165, 903, 8302, 265, 8165, 587, 8165, 1011, 8165, - 1505, 8310, 1369, 8165, 483, 8165, 903, 8316, 903, 8165, 483, 8320, - 165, 8320, 9, 8165, 3, 8326, 33, 8329, 3, 8327, 113, 8333, - 0, 240, 4266, 8337, 4888, 8337, 4892, 8337, 4213, 8337, 375, 8344, - 4863, 8337, 375, 8348, 265, 8348, 261, 8337, 3335, 8337, 375, 8357, - 347, 8337, 386, 8337, 331, 8337, 305, 8337, 375, 8366, 340, 8337, - 331, 8371, 375, 8337, 4213, 8374, 4863, 8374, 305, 8374, 1325, 8337, - 59, 8337, 7, 8337, 265, 8387, 4213, 8389, 4863, 8389, 305, 8389, - 265, 8386, 331, 8397, 7, 8336, 5141, 8401, 5137, 8402, 5137, 8401, - 5141, 8406, 5150, 8401, 5154, 8401, 5133, 8413, 5161, 8401, 5127, 8401, - 265, 8419, 5137, 8421, 265, 8418, 5133, 8425, 265, 8401, 5127, 8429, - 5141, 8431, 5127, 8428, 5133, 8435, 3785, 8401, 4329, 8401, 4311, 8401, - 483, 8337, 9, 8337, 1275, 8337, 15, 8337, 265, 8337, 4863, 8452, - 257, 8452, 1, 8457, 6, 8452, 1, 8461, 241, 8462, 241, 8461, - 1, 8466, 7, 8452, 331, 8471, 7, 8453, 7895, 8475, 7287, 8475, - 8465, 8475, 8469, 8475, 7627, 8475, 8459, 8475, 0, 8475, 8457, 8489, - 375, 8475, 1, 264, 3293, 8495, 7718, 8495, 3295, 8495, 3305, 8495, - 3301, 8495, 5512, 8495, 5451, 8495, 7756, 8495, 7091, 8495, 4899, 8512, - 7083, 8495, 4899, 8516, 7092, 8495, 7084, 8495, 4696, 8495, 7075, 8495, - 7123, 8495, 4899, 8528, 7134, 8495, 445, 8495, 4349, 8535, 8386, 8495, - 331, 8539, 471, 8495, 367, 8495, 357, 8495, 631, 8495, 1249, 8495, - 628, 8495, 8387, 8495, 8401, 8495, 4137, 8495, 3863, 8495, 4063, 8495, - 8475, 8495, 4371, 8495, 4549, 8495, 4545, 8495, 407, 8495, 1417, 8495, - 665, 8495, 338, 8495, 1480, 8495, 336, 8495, 4745, 8495, 4669, 8495, - 9, 8586, 4899, 8495, 7091, 8590, 7083, 8590, 7123, 8590, 4569, 8495, - 7709, 8495, 251, 8600, 341, 8495, 4863, 8605, 241, 8605, 253, 8495, - 331, 8610, 251, 8495, 7709, 8614, 5509, 8614, 7739, 8614, 256, 8495, - 375, 8623, 7739, 8495, 251, 8626, 5509, 8495, 251, 8630, 257, 8495, - 305, 8635, 53, 8495, 331, 8638, 1471, 8495, 331, 8642, 6, 8495, - 4349, 8647, 4497, 8647, 413, 8647, 4213, 8647, 8109, 8647, 4147, 8647, - 3933, 8647, 445, 8647, 316, 8647, 4713, 8647, 4863, 8647, 8337, 8647, - 305, 8647, 241, 8672, 241, 8647, 305, 8676, 587, 8647, 8387, 8647, - 7, 8495, 3785, 8685, 4329, 8685, 4311, 8685, 8337, 8684, 331, 8693, - 331, 8685, 8337, 8697, 15, 8685, 241, 8684, 375, 8703, 331, 8495, - 253, 8706, 1471, 8706, 53, 8706, 305, 8495, 6, 8494, 8539, 8717, - 8693, 8717, 4371, 8717, 8623, 8717, 8703, 8717, 8685, 8717, 8337, 8729, - 241, 8729, 471, 8717, 367, 8717, 357, 8717, 1369, 8717, 341, 8717, - 241, 8743, 4569, 8717, 4137, 8717, 4063, 8717, 3863, 8717, 8401, 8717, - 7, 8494, 8389, 8757, 8555, 8757, 8374, 8757, 8670, 8757, 8635, 8757, - 8676, 8757, 8647, 8757, 8337, 8770, 241, 8770, 8337, 8757, 8647, 8776, - 375, 8776, 9, 8757, 375, 8757, 8337, 8784, 241, 8757, 1, 8789, - 8647, 8791, 8647, 8788, 587, 8495, 11, 8796, 11, 8495, 587, 8800, - 9, 8495, 4669, 8804, 1369, 8495, 17, 8495, 241, 8495, 1, 8813, - 7, 8815, 8717, 8817, 7, 8814, 8647, 8821, 7, 8812, 8717, 8825, - 375, 8825, 7, 8813, 1, 8830, 8647, 8833, 8647, 8831, 331, 8831, - 6, 8813, 8337, 8495, 7, 8842, 8717, 8845, 331, 8845, 483, 8843, - 9, 8843, 7, 8843, 8647, 8855, 375, 8855, 0, 264, 3299, 8861, - 5431, 8861, 5469, 8861, 5449, 8861, 4888, 8861, 4863, 8861, 375, 8872, - 629, 8861, 394, 8861, 299, 8861, 659, 8861, 623, 8861, 645, 8861, - 101, 8861, 705, 8861, 128, 8861, 828, 8861, 3345, 8861, 3445, 8861, - 375, 8899, 2981, 8861, 3049, 8861, 7195, 8861, 3461, 8861, 4613, 8861, - 331, 8910, 4614, 8861, 375, 8861, 4863, 8916, 241, 8916, 803, 8861, - 483, 8922, 113, 8861, 9, 8926, 256, 8861, 331, 8931, 5455, 8861, - 251, 8935, 7, 8861, 331, 8939, 241, 8941, 241, 8938, 331, 8945, - 331, 8861, 4613, 8948, 7, 8860, 3837, 8953, 8093, 8953, 394, 8953, - 299, 8953, 375, 8953, 241, 8962, 4303, 8953, 4287, 8953, 241, 8953, - 375, 8970, 483, 8861, 803, 8974, 9, 8861, 113, 8978, 17, 8861, - 241, 8861, 375, 8984, 7, 8984, 331, 8989, 7, 8985, 375, 8993, - 1, 240, 3342, 8997, 2900, 8997, 8672, 8997, 8743, 8997, 3795, 8997, - 8770, 8997, 8729, 8997, 2658, 8997, 7159, 8997, 2703, 8997, 2660, 8997, - 413, 8997, 8757, 8997, 8647, 9022, 8684, 8997, 8717, 9027, 8605, 8997, - 457, 8997, 2647, 9032, 8647, 8997, 305, 9036, 8757, 9036, 8916, 8997, - 257, 8997, 2647, 8997, 375, 9046, 457, 9046, 3341, 8997, 375, 9052, - 2897, 8997, 375, 9056, 305, 8997, 8647, 9060, 340, 8997, 8717, 9065, - 3785, 9065, 8495, 9065, 375, 8997, 3341, 9072, 2897, 9072, 2647, 9072, - 8861, 9072, 7, 8997, 413, 9082, 0, 9085, 1, 9083, 264, 9088, - 264, 9089, 8495, 9082, 8717, 9095, 8495, 9083, 8757, 9099, 305, 9099, - 265, 9083, 2897, 9105, 3341, 9105, 2647, 9105, 9087, 9105, 1, 9105, - 9085, 9115, 9093, 9105, 8861, 9105, 265, 9082, 8717, 9123, 3785, 9123, - 9091, 9123, 8495, 9123, 483, 8997, 9, 8997, 265, 8997, 7, 9136, - 8717, 9139, 3785, 9139, 8495, 9139, 7, 9137, 8647, 9147, 8495, 8997, - 7, 9150, 8717, 9153, 7, 9151, 8647, 9157, 8861, 8997, 375, 9160, - 0, 482, 6, 9165, 4, 9167, 803, 9165, 5, 9165, 587, 9173, - 9, 9173, 5, 9164, 17, 9179, 19, 9165, 12, 9165, 9, 9165, - 11, 9186, 11, 9165, 9, 9190, 1, 586, 4795, 9195, 807, 9195, - 4787, 9198, 4788, 9195, 4790, 9195, 8374, 9195, 8389, 9195, 4797, 9195, - 8086, 9195, 8090, 9195, 8251, 9195, 4283, 9195, 4279, 9195, 3807, 9195, - 1491, 9195, 631, 9195, 1160, 9195, 1466, 9195, 764, 9195, 357, 9195, - 367, 9195, 471, 9195, 1249, 9195, 8800, 9195, 8647, 9195, 4787, 9195, - 807, 9246, 375, 9246, 33, 9195, 759, 9252, 1141, 9195, 759, 9256, - 803, 9195, 375, 9195, 4787, 9262, 8337, 9262, 8165, 9195, 265, 9269, - 566, 9195, 567, 9195, 7971, 9195, 25, 9276, 713, 9276, 8495, 9195, - 11, 9282, 4, 9195, 483, 9287, 5, 9195, 17, 9291, 483, 9290, - 759, 9195, 1141, 9296, 1447, 9296, 33, 9296, 713, 9195, 7971, 9304, - 25, 9195, 7971, 9308, 8337, 9195, 375, 9312, 4, 9194, 9273, 9317, - 9295, 9317, 9291, 9317, 483, 9323, 4279, 9317, 3807, 9317, 4283, 9317, - 8251, 9317, 5, 9194, 9275, 9335, 9288, 9335, 9287, 9335, 483, 9340, - 8647, 9335, 9, 9335, 483, 9335, 9287, 9348, 1447, 9195, 759, 9352, - 11, 9195, 8495, 9357, 8495, 9356, 9, 9195, 1011, 9195, 483, 9195, - 5, 9366, 9317, 9369, 5, 9367, 9287, 9373, 0, 586, 7, 9377, - 4, 9378, 16, 9377, 8800, 9377, 273, 9377, 1477, 9377, 281, 9377, - 948, 9377, 1516, 9377, 750, 9377, 386, 9377, 347, 9377, 510, 9377, - 767, 9377, 375, 9377, 305, 9406, 713, 9406, 165, 9377, 903, 9412, - 8495, 9377, 11, 9416, 566, 9377, 759, 9421, 5, 9377, 759, 9425, - 483, 9427, 483, 9424, 759, 9431, 4, 9377, 0, 9435, 7, 9434, - 0, 9434, 587, 9441, 713, 9435, 713, 9377, 375, 9446, 305, 9377, - 375, 9450, 4, 9376, 767, 9455, 5, 9376, 3837, 9459, 8093, 9459, - 828, 9459, 705, 9459, 803, 9459, 483, 9468, 4287, 9459, 4303, 9459, - 483, 9459, 803, 9476, 1505, 9377, 1011, 9480, 11, 9377, 8495, 9484, - 903, 9377, 165, 9488, 9, 9377, 483, 9492, 1011, 9377, 1505, 9496, - 483, 9377, 9, 9500, 5, 9500, 759, 9505, 5, 9501, 803, 9509, - 1, 482, 6, 9513, 5, 9514, 14, 9513, 5, 9513, 1, 9521, - 6, 9520, 1, 9520, 483, 9527, 11, 9513, 0, 902, 524, 9533, - 1291, 9533, 767, 9533, 7, 9533, 3, 9541, 305, 9533, 375, 9544, - 386, 9533, 347, 9533, 375, 9533, 305, 9552, 483, 9533, 11, 9556, - 11, 9533, 483, 9560, 1, 1010, 5038, 9565, 5037, 9565, 587, 9568, - 668, 9565, 1419, 9565, 8982, 9565, 7, 9564, 3867, 9579, 8277, 9579, - 9459, 9579, 8953, 9579, 4067, 9579, 3997, 9579, 375, 9565, 483, 9565, - 9, 9565, 587, 9596, 587, 9565, 5037, 9600, 9, 9600, 17, 9565, - 8861, 9606, 8861, 9565, 7, 9611, 17, 9610, 0, 1010, 9535, 9617, - 9537, 9617, 9559, 9617, 9563, 9617, 5, 9617, 6, 9627, 7, 9627, - 5006, 9617, 5005, 9617, 9, 9634, 9362, 9617, 1290, 9617, 9533, 9641, - 525, 9617, 9533, 9645, 8804, 9617, 8150, 9617, 922, 9617, 1413, 9617, - 7971, 9617, 9, 9656, 6, 9617, 11, 9661, 9195, 9617, 9, 9664, - 6, 9616, 17, 9669, 7, 9616, 9195, 9673, 9317, 9673, 4321, 9673, - 3833, 9673, 4295, 9673, 5045, 9673, 19, 9617, 12, 9617, 11, 9617, - 9, 9690, 483, 9617, 903, 9694, 1275, 9617, 17, 9698, 9533, 9701, - 9, 9617, 5005, 9704, 9195, 9704, 7971, 9704, 8495, 9704, 11, 9704, - 17, 9617, 1275, 9716, 9533, 9719, 903, 9617, 483, 9722, 8495, 9617, - 9, 9726, 1, 902, 9573, 9731, 9575, 9731, 9599, 9731, 9605, 9731, - 1418, 9731, 9565, 9741, 669, 9731, 9565, 9745, 8386, 9731, 7, 9731, - 8337, 9750, 7, 9730, 9673, 9755, 8251, 9755, 4283, 9755, 3807, 9755, - 4279, 9755, 483, 9731, 15, 9731, 1369, 9768, 9565, 9771, 1369, 9731, - 15, 9774, 9565, 9777, 1011, 9731, 8337, 9731, 7, 9782, 9617, 9731, - 6, 9786, 7, 9786, 6, 9787, 9791, 9793, 7, 9787, 9789, 9797, - 0, 1274, 5, 9801, 1, 1368, 4904, 9805, 4903, 9805, 9, 9808, - 9484, 9805, 1517, 9805, 1476, 9805, 272, 9805, 280, 9805, 949, 9805, - 1197, 9805, 1471, 9805, 265, 9826, 253, 9805, 265, 9830, 53, 9805, - 265, 9834, 5, 9804, 3867, 9839, 8277, 9839, 8953, 9839, 9459, 9839, - 3997, 9839, 4067, 9839, 11, 9805, 9377, 9852, 9, 9805, 4903, 9856, - 265, 9805, 1471, 9860, 253, 9860, 53, 9860, 9377, 9805, 11, 9868, - 5, 9869, 0, 1368, 5075, 9875, 2221, 9875, 4643, 9875, 2233, 9875, - 2215, 9875, 4339, 9875, 7, 9875, 5, 9888, 4, 9889, 10, 9875, - 8714, 9875, 8800, 9875, 4625, 9875, 9, 9901, 47, 9875, 305, 9875, - 8495, 9906, 959, 9875, 5045, 9875, 4551, 9875, 1325, 9875, 59, 9875, - 331, 9875, 5, 9875, 0, 9923, 7, 9922, 0, 9922, 1369, 9929, - 9287, 9923, 4, 9875, 1011, 9935, 8495, 9875, 10, 9938, 10, 9939, - 305, 9938, 11, 9938, 9943, 9947, 11, 9939, 9941, 9951, 4, 9874, - 8495, 9955, 8717, 9955, 4329, 9955, 4311, 9955, 3785, 9955, 5, 9874, - 9195, 9967, 9755, 9967, 9317, 9967, 3833, 9967, 4295, 9967, 4321, 9967, - 5045, 9967, 759, 9875, 11, 9875, 8495, 9984, 17, 9875, 903, 9875, - 265, 9875, 15, 9875, 9195, 9875, 241, 9997, 1, 1274, 6,10001, - 4,10002, 4,10003, 8,10001, 5123,10001, 5,10011, 4,10010, -10013,10015, 4,10011, 5,10010,10019,10021, 341,10001, 4663,10001, - 903,10027, 1471,10001, 253,10001, 53,10001, 4,10001, 1,10037, - 6,10036, 1,10036, 1275,10043, 5,10001, 9935,10047, 8337,10001, - 9,10051, 5,10000, 8685,10055, 1369,10055, 8401,10055, 3863,10055, - 4137,10055, 4063,10055, 4569,10055, 9955,10055, 241,10001, 17,10001, - 1369,10001, 5,10077, 0, 14, 6,10081, 2,10082, 482,10081, - 2,10081, 0,10089, 6,10088, 0,10088, 15,10095, 2,10080, - 17,10099, 1369,10081, 17,10081, 1, 16, 7,10107, 3,10108, - 586,10107, 8306,10107, 1447,10107, 1141,10107, 9875,10107, 241,10121, - 265,10120, 9992,10107, 545,10107, 695,10107, 1382,10107, 1374,10107, - 1386,10107, 59,10107, 1369,10138, 154,10107, 483,10143, 1325,10107, - 1369,10146, 331,10107, 1369,10150, 3,10107, 1,10155, 7,10154, - 1,10154, 17,10161, 8241,10155, 15,10154, 483,10167, 3,10106, - 9673,10171, 8251,10171, 3807,10171, 4279,10171, 4283,10171, 9967,10171, - 33,10107, 1369,10107, 331,10186, 1325,10186, 59,10186, 1011,10107, - 265,10107, 8165,10196, 9875,10196, 1275,10107, 15,10107, 3,10204, - 483,10207, 3,10205, 1369,10211, 8165,10107, 265,10214, 0, 16, - 4,10219, 3,10220, 3,10221, 7,10219, 2,10226,10225,10229, - 2,10227,10223,10233, 1368,10219,10225,10237, 902,10219,10233,10241, - 59,10219, 1325,10219, 331,10219, 3,10219, 4,10250,10233,10253, - 2,10219, 7,10256,10225,10259, 903,10257, 8495,10219, 587,10265, -10001,10219, 903,10269, 2,10218, 8495,10273, 8717,10273,10055,10273, - 4311,10273, 4329,10273, 3785,10273, 265,10219, 1275,10219, 1, 14, - 8982,10291, 8861,10291, 17,10294, 4745,10291, 1011,10299, 53,10291, - 253,10291, 1471,10291, 2,10291, 3,10291, 483,10311,10257,10311, - 59,10291, 17,10316, 62,10291, 1325,10291, 17,10322, 331,10291, - 17,10326, 1328,10291, 334,10291, 393,10291, 1359,10291, 1031,10291, - 499,10291, 8337,10291, 483,10343, 9875,10291, 1011,10347, 3,10290, - 8685,10351, 1369,10351, 8401,10351, 9955,10351, 4063,10351, 4137,10351, - 3863,10351, 4569,10351,10273,10351, 241,10291, 1369,10291, 17,10291, - 8861,10374, 59,10374, 1325,10374, 331,10374, 1, 11, 340,10385, - 341,10385, 264,10385, 375,10391, 1010,10385, 264,10384, 341,10397, -10387,10397, 5,10385, 6,10402, 2,10402, 2,10403, 7,10385, - 265,10410,10397,10413, 265,10411,10391,10417, 5,10384, 29,10421, - 341,10421, 6,10421, 25,10427, 8262,10385, 9,10431, 8279,10385, - 9,10435, 88,10384, 3807,10439, 6347,10439, 6327,10439, 8251,10439, - 9875,10439, 8165,10439, 8229,10385, 8251,10452, 9,10455, 9,10453, - 8251,10459, 8241,10385, 33,10385, 6685,10465, 9,10465, 6267,10385, - 101,10471, 8240,10385, 8296,10475, 8277,10475, 9,10478, 9,10475, - 8277,10482, 8228,10385, 6719,10385, 9,10489, 265,10384,10389,10493, - 5313,10493, 8251,10385, 8229,10498, 9,10501, 483,10384, 5197,10505, - 5125,10505, 1275,10384, 1369,10385, 6685,10513, 9,10513, 1011,10385, - 265,10385, 7,10520,10397,10523, 2,10384,10423,10527,10428,10527, -10427,10527, 25,10532,10425,10527, 340,10527,10397,10539,10399,10527, -10392,10527, 375,10527,10391,10546, 7,10527, 265,10550,10397,10553, - 265,10551,10391,10557,10391,10527, 375,10560,10463,10527, 9,10565, -10487,10527, 9,10569,10519,10527, 6,10573, 7,10572,10575,10577, - 7,10573, 6,10572,10581,10583, 25,10527,10427,10586, 8165,10527, - 903,10527, 265,10527, 7,10594,10397,10597, 9,10527, 3,10384, -10482,10603, 5,10602, 6,10607, 5,10603, 6,10611,10475,10613, -10458,10603,10395,10603, 6,10619, 7,10618,10621,10623, 7,10619, - 6,10618,10627,10629,10407,10603, 6,10633, 7,10632,10635,10637, - 7,10633, 6,10632,10641,10643, 8326,10603,10453,10603, 9,10648, -10475,10603, 9,10652, 9875,10603, 9,10657,10521,10603, 375,10661, - 9,10602, 8251,10665, 3807,10665, 9875,10665, 8165,10665, 8165,10603, - 9,10674, 9,10675, 3807,10603, 9,10681, 9,10603,10475,10684, -10453,10684, 8165,10684, 8251,10603, 9,10693, 2,10385,10613,10697, - 8165,10699,10646,10697, 8327,10697,10690,10697,10676,10697, 5,10696, -10603,10711, 6,10713, 7,10712,10715,10717, 7,10713, 6,10712, -10721,10723, 8326,10697,10603,10726, 8251,10727,10674,10697, 9,10732, - 8165,10696,10613,10737,10705,10737, 8296,10737,10684,10737, 8277,10737, - 9,10746,10603,10737, 9,10750, 9,10737,10603,10754, 8277,10754, - 265,10697, 8165,10697,10684,10762, 8251,10763, 9,10767, 9,10762, -10603,10770, 8251,10771,10603,10762, 9,10776,10684,10697, 8165,10780, - 8165,10781, 9,10697,10674,10786, 8165,10786,10603,10790, 8251,10791, - 8165,10787,10603,10797, 8277,10797,10603,10786, 8165,10802, 8165,10803, -10603,10697, 8326,10808, 8165,10808, 9,10812, 8165,10809, 9,10817, - 9,10808, 8165,10820, 8165,10821, 67,10697,10427,10827, 3,10385, - 8225,10831, 8242,10831,10427,10831,10409,10831, 6,10839, 7,10838, -10841,10843, 7,10839, 6,10838,10847,10849, 7,10831,10421,10853, - 375,10831,10590,10831, 9,10859, 8165,10830,10527,10863, 9,10865, - 8165,10831,10527,10868, 9,10871, 9,10831, 8241,10874,10527,10831, - 8326,10879, 8165,10878, 9,10883, 8165,10879, 9,10886, 9,10879, - 8165,10890, 8165,10891, 8241,10831, 9,10896, 89,10384, 88,10385, - 8225,10903, 8165,10385, 264,10907, 1368,10906,10909,10911, 7,10906, - 2,10915, 2,10914,10909,10919, 265,10915, 5,10907, 3,10924, -10919,10927,10911,10927, 3,10925,10917,10933, 1369,10925, 1369,10906, - 265,10907,10939,10941, 2,10907,10937,10945, 8229,10945, 9,10949, -10831,10945, 9,10953, 3,10907, 5,10957, 6,10959,10786,10957, - 5,10956,10919,10965,10911,10965,10697,10957, 9,10970, 9,10957, -10697,10974, 2,10906,10961,10979,10613,10979, 8296,10979,10974,10979, -10684,10979, 7,10978,10927,10991,10965,10991,10909,10991, 8277,10979, - 9,10998,10957,10979, 9,11002,10603,10979, 9,11006, 9,10979, -10603,11010, 8277,11010,10957,11010, 3,10906,10923,11019,10945,11019, - 9,11023,10527,11019, 9,11027, 9,10384, 1369,11031, 33,11031, - 3,11030, 8251,11037, 3807,11037, 9875,11037, 8165,11037, 3,11031, - 8241,11047, 1, 9, 69,11051, 6625,11053, 981,11050, 980,11050, - 4745,11059, 7966,11050, 7967,11050, 4,11050, 7,11067, 1275,11067, - 7954,11051, 7967,11051,11063,11075, 120,11050, 3867,11079, 112,11050, -11073,11083, 66,11050, 8251,11087, 1941,11087, 6159,11087, 3807,11087, - 9875,11087, 8165,11087, 121,11050, 7966,11051,11065,11103, 7957,11051, - 11,11106, 1141,11051, 1447,11051, 67,11051, 7,11114,11087,11117, - 113,11051,11083,11121, 7947,11123, 7947,11120,11083,11127, 89,11051, - 8495,11131, 25,11050, 113,11134, 3867,11137, 3867,11135, 113,11141, - 567,11050, 4950,11145, 587,11145, 4935,11148, 4935,11145, 587,11152, - 973,11050, 3,11156, 4745,11159, 587,11051, 566,11162, 566,11163, - 567,11163,11165,11169, 567,11162,11167,11173, 1011,11051, 1369,11051, - 6625,11179, 7956,11051, 7955,11051, 33,11051, 6625,11187, 25,11051, -11101,11191, 3984,11191, 3023,11191, 3933,11191, 113,11198, 113,11191, - 3933,11202, 973,11051, 2139,11207,11057,11207, 567,11051, 4971,11213, - 587,11215, 257,11051, 483,11219, 483,11050, 257,11223, 1011,11050, - 973,11227, 972,11226,11229,11231, 972,11227, 973,11226,11235,11237, - 257,11227, 265,11050, 5019,11243, 903,11051, 7,11246, 2,11050, -11187,11251,11073,11251,11127,11251,11207,11251,11113,11251,11111,11251, -11075,11251,11179,11251,11121,11251, 7947,11269, 25,11251, 5019,11251, - 3,11050,11068,11276,11069,11277,11279,11281,11068,11277,11069,11276, -11285,11287,11185,11277, 973,11276, 4745,11293,11103,11277,11109,11277, -11249,11277, 10,11276, 10,11277, 11,11276, 8251,11307, 3807,11307, - 9875,11307,11305,11307, 8165,11307, 33,11277, 7971,11319, 8165,11277, - 25,11323, 7947,11277, 973,11277, 4805,11329, 3807,11277, 8251,11277, - 4279,11277, 4283,11277, 9673,11277, 9967,11277, 9875,11277, 4745,11277, - 11,11277,11303,11349, 7971,11349, 2,11051,11315,11355,11303,11355, -11349,11358,11350,11355,11304,11355,11307,11365,11349,11355,11303,11368, - 5,11355, 7,11372,11276,11374,11277,11375,11377,11379,11276,11375, -11277,11374,11383,11385, 7,11355, 5,11388,11276,11390,11277,11391, -11393,11395,11276,11391,11277,11390,11399,11401, 5,11354, 7,11404, -11277,11407, 7,11405, 7,11354,11087,11413, 5,11412,11277,11417, -11307,11413,11277,11413, 4,11354,11373,11425, 7,11427,11277,11429, - 10,11354,11087,11433,11307,11433,11277,11433, 10,11355,11349,11441, -11277,11440,11307,11445,11277,11441,11303,11449, 4,11355,11410,11453, -11277,11455, 7,11453,11405,11458,11277,11461,11276,11458,11277,11459, -11405,11467,11465,11467,11276,11459,11277,11458,11473,11475,11405,11453, - 7,11478,11277,11481, 1,11452, 1,11355, 4,11486, 67,11355, - 1275,11355, 9,11493,11485,11495,11489,11495, 7947,11355, 11,11501, -11277,11503,11277,11355, 10,11506,11307,11509, 10,11507,11349,11513, - 11,11354,11326,11517,11277,11517, 7947,11520, 7947,11517,11277,11524, - 3,11051, 8213,11529, 8052,11529, 7971,11529, 113,11534, 113,11529, - 7971,11538, 8241,11529, 7947,11528, 483,11529, 112,11051,11326,11549, -11277,11549, 7947,11552, 7947,11549,11277,11556, 67,11050,11187,11561, -11053,11561,11179,11561, 66,11051, 113,11050,11556,11571,11185,11571, -11549,11571, 7947,11576, 25,11570, 3867,11581, 7947,11571,11549,11584, - 25,11571, 3933,11589, 7947,11051, 113,11592,11083,11595,11251,11595, - 113,11593,11549,11601, 3,11593,11549,11605,11517,11605, 3,11592, - 11,11051, 8116,11613, 8099,11613,11272,11613,11561,11613,11491,11613, -11251,11613, 25,11624, 8074,11613, 8093,11629, 25,11613,11251,11632, - 8109,11613, 8063,11636, 8063,11613, 8109,11640, 7957,11612,11277,11645, - 6625,11613, 113,11613, 2,11613,11183,11653,11545,11653,11611,11653, -11529,11653, 7947,11661, 3,11613, 7971,11664, 8093,11667, 7971,11665, - 8109,11671, 2,11612,11605,11675,11326,11675,11277,11675, 7947,11680, - 7947,11675,11277,11684, 7971,11613, 3,11688, 8093,11691, 3,11689, - 8063,11695, 11,11050,11355,11699, 113,11701, 1369,11699,11251,11705, - 33,11699,11251,11709, 3,11698, 8251,11713, 3807,11713,11433,11713, -11413,11713, 9875,11713, 8165,11713, 3,11699, 8241,11727, 0, 11, - 8095,11731, 8112,11731, 6688,11731, 6285,11731, 203,11730, 2351,11741, - 8159,11731, 8162,11731, 8128,11731, 8114,11731, 8097,11731, 8118,11731, - 8100,11731, 5,11730, 1369,11759, 8116,11731, 9,11762, 8099,11731, - 9,11766, 181,11731, 98,11731, 5019,11773, 8058,11731, 8093,11777, - 8156,11731, 8093,11781, 8076,11731, 8093,11785, 30,11731, 8124,11731, - 8063,11790, 8072,11731, 8109,11794, 8063,11731, 8161,11798, 8124,11798, - 8109,11798, 9,11804, 9,11798, 8109,11808, 25,11731, 6685,11812, - 9,11812, 89,11731, 5019,11819, 21,11821, 21,11818, 5019,11825, - 2759,11731, 2789,11731, 2821,11731, 6658,11731, 6685,11731, 25,11836, - 4413,11731, 113,11731, 9,11842, 128,11731, 659,11731, 623,11731, - 645,11731, 705,11731, 299,11731, 828,11731, 394,11731, 241,11731, - 375,11862, 483,11731, 803,11866, 8074,11731, 8093,11871, 9,11873, - 9,11870, 8093,11877, 101,11731, 21,11731, 89,11882, 5019,11885, - 89,11883, 5045,11889, 8061,11731, 8109,11892, 803,11731, 483,11896, - 375,11731, 241,11900, 587,11901, 6625,11731, 9,11906, 6789,11731, - 2,11911, 6855,11913, 1369,11730, 587,11730, 375,11919, 8109,11731, - 8061,11922, 8072,11922, 8063,11922, 9,11928, 9,11922, 8063,11932, - 145,11731, 903,11730, 375,11939, 265,11731, 8161,11731, 8063,11944, - 2,11730, 8124,11949, 8804,11949, 3972,11949, 8150,11949, 8495,11949, - 9,11958, 7971,11949, 9,11962, 3933,11949, 9,11966, 9,11949, - 8109,11970, 8495,11970, 3933,11970, 7971,11970, 8109,11949, 9,11980, - 3,11730, 483,11985, 2,11731, 8075,11989, 9,11991, 3,11731, - 8151,11994, 5,11995, 6,11999, 0,11998, 0,11995, 5,12004, - 8150,11994, 8093,12009, 7971,11994, 8093,12013, 9,12015, 9,12012, - 8093,12019, 1369,11995, 11,12023,12003,12025,12007,12025, 7971,11995, - 8161,12031,11997,12031, 8124,12031, 8109,12031, 9,12038, 9,12031, - 8109,12042, 9,11994, 7971,12046, 8093,12049, 7971,12047, 8109,12053, - 89,11730, 5082,12057, 2969,12057, 5045,12057, 21,12062, 21,12057, - 5045,12066, 88,11731, 7971,12070, 8093,12073, 7971,12071, 8109,12077, - 8150,11731, 3,12080, 8093,12083, 3,12081, 8063,12087, 7971,11731, - 1368,12091, 264,12090,12093,12095, 5,12090, 3,12099, 3,12098, -12093,12103, 1369,12099, 7,12091, 2,12108,12103,12111,12095,12111, - 2,12109,12101,12117, 265,12109, 265,12090, 1369,12091,12123,12125, - 88,12090, 8093,12129, 88,12091, 8061,12133, 2,12091,12001,12137, - 7,12136,12103,12141,12095,12141, 9,12137, 3,12091, 8061,12149, - 8072,12149,12121,12149, 8063,12149, 9,12156, 9,12149, 8063,12160, - 2,12090,12107,12165,12149,12165, 9,12169, 3,12090, 5,12173, - 6,12175,12137,12177,12146,12173, 5,12172,12111,12183,12141,12183, -12093,12183, 8093,12173, 9,12191,12137,12173, 9,12194, 9,12172, - 8093,12199, 9,12173,12137,12202, 9,12090, 3,12206, 8093,12209, - 3,12207, 8063,12213, 9,11731, 8116,12216, 8099,12216, 8074,12216, - 8093,12223, 25,12216, 8109,12216, 8063,12228, 8063,12216, 8109,12232, - 6625,12216, 113,12216, 3,12216, 7971,12240, 8093,12243, 7971,12241, - 8109,12247, 7971,12216, 3,12250, 8093,12253, 3,12251, 8063,12257, - 0, 9, 192,12261, 2329,12263, 211,12261, 2419,12267, 211,12260, - 2433,12271, 192,12260, 2337,12275, 189,12260, 2337,12279, 4,12261, - 7,12282, 413,12260, 413,12261, 1216,12260, 1216,12261, 1086,12261, - 9617,12295, 137,12261, 587,12261, 1011,12300, 9617,12303, 1011,12301, - 9565,12307, 1011,12261, 9617,12311, 587,12313, 587,12310, 9617,12317, - 1011,12260, 5267,12321, 9600,12321, 9565,12321, 587,12326, 587,12321, - 9565,12330, 587,12260, 5231,12335, 5181,12335,10505,12335, 1275,12261, - 2,12260,10001,12345, 5,12347, 4,12346,12349,12351, 4,12347, - 5,12346,12355,12357, 3,12260,11243,12361,11251,12361, 5177,12361, - 5185,12361, 2,12261, 3,12261,11355,12373, 1, 265, 471,12376, - 2647,12379, 357,12376, 1785,12383, 586,12377, 375,12387, 586,12376, - 413,12377, 3,12377, 7,12394, 375,12397, 7,12395, 331,12401, - 483,12395, 15,12405, 5,12377, 17,12409, 587,12411, 3,12376, - 669,12415, 1418,12415,12413,12415, 1369,12415, 15,12422, 15,12415, - 1369,12426, 5,12376,12417,12431, 1419,12431,12415,12435, 668,12431, -12415,12439,12419,12431,12407,12431,12429,12431, 9,12431, 587,12448, -12415,12451,12425,12431, 587,12431, 9,12456,12415,12459, 6719,12377, - 9,12463, 7867,12377, 251,12467, 3357,12377, 3681,12377, 3709,12377, - 2647,12377, 5843,12377, 4407,12377,11917,12377, 305,12377, 713,12377, - 25,12377, 4405,12377, 7041,12377, 251,12493, 1471,12376, 2011,12497, - 53,12376, 2035,12501, 257,12377, 253,12376, 5325,12507, 251,12376, - 7867,12511, 7617,12511, 7041,12511, 7617,12377, 251,12519, 1363,12376, - 5189,12523, 483,12377, 9,12377, 8938,12377, 375,12531, 5313,12377, - 7035,12377, 7091,12537, 7083,12537, 7123,12537, 241,12537, 11,12376, - 5313,12547, 587,12376,12387,12551,11731,12551, 9,12376, 5019,12557, -12361,12557, 1369,12376, 11,12377, 587,12377,12391,12567, 7,12376, - 2,12571, 4,12572,12537,12575, 4,12571, 2,12578,12537,12581, -12545,12571, 240,12571,12537,12587, 8948,12571, 331,12571, 8861,12592, - 8861,12571, 331,12596, 4827,12571, 6,12377, 257,12603, 265,12605, - 241,12603, 1,12609,12607,12611, 7,12377, 3,12614, 375,12617, - 8861,12614, 375,12621, 375,12615, 8861,12625, 241,12614, 375,12629, - 257,12376, 2647,12633, 1783,12633, 256,12377, 375,12639, 8861,12377, - 261,12643, 260,12643, 256,12643, 6,12643, 241,12650, 7,12643, - 241,12654, 331,12655, 6,12642,12645,12661, 7,12642,12647,12665, -12653,12665, 375,12665, 241,12643, 6,12672,12665,12675, 7,12672, - 6,12673,12679,12681,12655,12681, 7,12673,12675,12687, 241,12377, - 7,12691, 331,12693, 7,12690, 375,12697, 8997,12691, 7,12701, - 241,12376, 4457,12705, 374,12705, 5189,12705, 265,12705, 6,12712, - 8386,12705, 6,12705, 265,12718, 7,12705, 8337,12722, 8337,12705, - 7,12726, 8861,12705, 6,12731, 7,12731, 6,12730,12735,12737, - 7,12730,12733,12741, 1, 241, 448,12745, 4349,12747, 445,12744, - 1679,12751, 457,12744, 4371,12755, 8461,12744, 8475,12759, 277,12744, - 4457,12763, 923,12744, 4959,12767, 8388,12744, 8389,12744, 4,12745, - 11,12775, 1369,12777, 2,12745, 1275,12781, 9,12783, 2,12744, - 1419,12787, 668,12787,12779,12787, 587,12787, 9,12794, 9,12787, - 587,12798, 4,12744,12789,12803, 669,12803,12787,12807, 1418,12803, -12787,12811,12791,12803,12785,12803,12801,12803, 15,12803, 1369,12820, -12787,12823,12797,12803, 1369,12803, 15,12828,12787,12831, 445,12745, - 265,12834, 4349,12837, 923,12745, 5009,12841, 8374,12745, 346,12745, - 2981,12847, 386,12745, 387,12745, 3049,12853, 347,12745, 8389,12745, -12771,12859, 1412,12745, 5227,12863, 346,12744, 2977,12867,12857,12867, - 386,12744, 4067,12873,12853,12873, 1412,12744, 5189,12879, 374,12744, -12845,12883, 387,12744, 3043,12887,12851,12887, 347,12744,12847,12893, - 272,12745, 4453,12897, 4437,12897, 1755,12897, 8388,12745, 8495,12905, -12773,12905, 8387,12745, 265,12911, 8861,12913, 265,12910, 8495,12917, - 253,12745, 59,12744, 1325,12744, 341,12745, 375,12745,12883,12929, - 8337,12931, 8337,12928,12883,12935, 4371,12745, 457,12939, 375,12939, - 4531,12745, 375,12945, 8366,12745, 375,12949, 305,12744, 4457,12953, - 375,12952, 4067,12957, 4067,12953, 375,12961, 331,12744, 4457,12965, -12927,12965, 8386,12745, 8495,12971, 331,12971, 1325,12971, 59,12971, - 265,12971, 8375,12745, 8495,12983, 305,12745,12887,12987, 4266,12987, - 3031,12987, 4213,12987, 375,12994, 8337,12986, 375,12999, 375,12987, - 4213,13002, 5325,12745, 7,13007, 5361,13009, 5385,13009, 5407,13009, - 1275,12744, 15,12744, 8475,12745, 375,13021, 8461,13021, 6,12744, - 8429,13027, 8428,13027, 4139,13027, 4138,13027, 3,13026, 5,13036, - 5,13026, 3,13040, 264,13026,13031,13045,13035,13045, 264,13027, - 8401,13051, 4137,13051, 265,13026, 8401,13057,13051,13058,13029,13057, -13052,13057, 4137,13057,13051,13066,13033,13057,13054,13057,13051,13057, - 8401,13074, 4137,13074, 4137,13027, 265,13081,13051,13083, 265,13080, -13045,13087, 341,13027, 265,13027, 8401,13092,13045,13095, 4137,13092, -13045,13099,13045,13093, 8401,13103, 4137,13103, 8401,13027, 265,13109, -13051,13111, 265,13108,13045,13115, 7,12744, 8605,13119, 8374,13119, - 8916,13119, 8389,13119, 412,13119, 241,13119, 265,13130, 264,13118, - 264,13119, 8452,13119, 8647,13119, 265,13118,13137,13143, 8861,13119, - 375,13146, 8337,13119, 375,13150, 265,13150, 305,13119, 713,13119, - 25,13119, 375,13119, 8861,13162, 8337,13162, 265,13119, 241,13168, -13135,13169, 8337,13168, 6,12745,12965,13177,13145,13177,13139,13177, - 8453,13177,13119,13185,12923,13177,12925,13177,13135,13177,13169,13192, -13172,13177,13136,13177,13143,13199,13175,13177,13155,13177,13169,13177, -13135,13206, 3,13177, 5,13210,13118,13212,13119,13213,13215,13217, -13118,13213,13119,13212,13221,13223, 5,13177, 3,13226,13118,13228, -13119,13229,13231,13233,13118,13229,13119,13228,13237,13239, 264,13177, -13119,13242,13143,13245,13119,13243,13135,13249, 413,13177, 8452,13177, - 8861,13255, 305,13177, 8337,13177, 265,13260, 8861,13263, 265,13261, - 8495,13267, 265,13177, 8337,13270, 8861,13273, 8861,13271, 8337,13277, -13119,13177, 264,13280,13143,13283, 264,13281,13169,13287, 265,13280, -13287,13291, 265,13281,13283,13295, 8387,13177, 264,13299, 265,13298, -13301,13303, 264,13298, 265,13299,13307,13309, 265,13176, 8842,13313, - 8495,13313, 8337,13316, 8337,13313, 8495,13320, 7,12745,13039,13325, -13043,13325,13045,13325, 241,13324, 0,13333, 8717,13325, 8495,13325, - 8337,13339, 305,13339, 4311,13325, 4329,13325, 3785,13325,10351,13325, -10055,13325, 8337,13324, 8495,13355, 331,13355, 1325,13355, 59,13355, - 265,13355, 59,13325, 8337,13367, 1325,13325, 8337,13371, 331,13325, - 8337,13375, 8861,13375, 265,13325,13051,13381,13335,13381, 5325,13381, - 1,13381,13333,13389, 8861,13381, 8337,13381,13027,13325, 264,13396, - 264,13397, 265,13396,13401,13403, 265,13397,13399,13407, 265,13324, - 8717,13411, 3785,13411,13045,13411, 8495,13411, 374,12745, 8842,13421, - 8495,13421, 8337,13424, 8337,13421, 8495,13428, 340,12745, 8717,13433, -13045,13433, 3785,13433, 8495,13433, 375,12744, 4371,13443,13428,13443, -12983,13443, 8475,13443,13421,13443, 8337,13452, 305,13442, 4067,13457, - 8337,13443,13421,13460, 305,13443, 4213,13465, 8452,12745, 8647,13469, - 7,13469, 8495,13473, 8337,12745, 375,13476,12883,13479, 375,13477, - 305,13483,13421,13483, 305,13476, 375,13489, 6,13477, 8453,13493, - 8452,13492,13495,13497, 8452,13493, 8453,13492,13501,13503, 7,13477, -13213,13507,13229,13507, 375,13507,13243,13507, 265,13507,13177,13517, - 6,13476, 3,13521, 5,13522,13507,13525, 5,13521, 3,13528, -13507,13531,13517,13521, 264,13521,13507,13537, 7,13476, 8495,13541, - 331,13541, 1325,13541, 59,13541, 265,13541, 265,13476, 8647,13553, - 7,13553, 8495,13557, 265,13477,13177,13561,13521,13561, 7,13561, - 265,12745, 445,13568, 4349,13571, 445,13569, 4371,13575, 8770,13569, - 8729,13569,13027,13569, 375,13583, 8684,13569, 8717,13587, 331,13569, -13177,13591, 8757,13569, 8647,13594, 8647,13569, 8757,13598, 8387,13568, - 8495,13603, 6,13569, 7,13569, 8647,13609, 8495,13608, 8717,13613, - 8495,13609, 8757,13617, 6,13568, 8842,13621, 8495,13621, 8337,13624, -13609,13621, 8337,13621, 8495,13630, 7,13568, 8717,13635, 3785,13635, -13045,13635, 8495,13635,13607,13635, 8337,13568, 8647,13647, 7,13647, - 8495,13651, 8495,13569, 6,13654, 7,13654, 8717,13659, 6,13655, -13659,13663, 7,13655,13657,13667, 8647,13667, 265,12744,13258,13673, -12845,13673,13091,13673,12935,13673,12927,13673,12929,13673, 8337,13685, -13479,13673,12911,13673,13260,13673,12859,13673, 4457,13673, 5189,13673, -13177,13673, 305,13700, 8337,13700, 305,13673,13177,13706, 8386,13673, - 7,13673, 8337,13712, 8861,13673, 6,13717, 7,13717, 6,13716, -13721,13723, 7,13716,13719,13727, 8337,13673,13177,13730, 7,13730, - 1, 587, 264,13737, 375,13739, 16,13737, 264,13736, 341,13745, - 7,13737, 4,13748, 4,13749, 3,13736, 717,13755, 341,13755, - 6,13755, 713,13761, 17,13755, 566,13736, 1108,13737, 9565,13769, -11731,13737, 265,13772,11942,13737, 3565,13737, 3573,13737, 3273,13737, - 375,13736, 113,13736, 4696,13787, 9,13787, 4669,13790, 4669,13787, - 9,13794, 1011,13737, 9565,13799, 9,13801, 9,13798, 9565,13805, - 241,13737, 9,13737, 1011,13810, 9565,13813, 1011,13811, 9617,13817, - 113,13737, 4727,13821, 9,13823, 7049,13737, 807,13827, 375,13827, - 265,13736,11731,13833, 1487,13737, 1011,13736, 5293,13839, 9704,13839, - 9617,13839, 9,13844, 9,13839, 9617,13848, 265,13737,11731,13852, - 4,13736,13757,13857,13762,13857,13761,13857, 713,13862,13759,13857, - 340,13857,13745,13869,13747,13857,13740,13857, 375,13857,13739,13876, - 7,13857, 265,13880,13745,13883, 265,13881,13739,13887,13739,13857, - 375,13890, 713,13857,13761,13894, 265,13857, 7,13898,13745,13901, - 483,13857, 5,13736,13853,13907, 375,13909, 483,13906, 4,13737, - 7,13914, 767,13915,13761,13919, 5,13737, 3,13923, 1,13924, - 1,13923, 3,13928, 17,13923, 587,13933,13927,13935,13931,13935, - 567,13736, 483,13736, 5,13942, 1, 483, 9174,13946, 9175,13946, - 2,13947, 7,13952, 2,13946, 7,13957, 6,13946, 9170,13947, - 9175,13947,13949,13965, 824,13946, 3997,13969, 802,13946,13963,13973, - 766,13946, 825,13946, 9174,13947,13951,13981, 803,13947,13973,13985, - 9165,13987, 9165,13984,13973,13991, 713,13946, 803,13994, 3997,13997, - 3997,13995, 803,14001, 1171,13946, 4663,14005, 903,14007, 155,13946, - 9172,13947, 9171,13947, 713,13947,13979,14017, 4200,14017, 3027,14017, - 4147,14017, 803,14024, 803,14017, 4147,14028, 1171,13947, 4722,14033, - 903,14033, 4713,14036, 4713,14033, 903,14040, 257,13947, 9,14045, - 9,13946, 257,14049, 903,13946, 257,14053, 11,13946, 5197,14057, - 5125,14057,12335,14057, 4,13946, 2,14065, 7,14067,14013,14069, - 5,13946,13958,14072,13959,14073,14075,14077,13958,14073,13959,14072, -14081,14083, 586,14072, 586,14073, 587,14072,14089,14091, 4827,14073, - 9,14073, 4569,14073, 4745,14073, 587,14073,14087,14103, 4,13947, -14093,14107,14087,14107,14103,14110,14104,14107,14088,14107,14091,14117, -14103,14107,14087,14120, 3,14107, 7,14124,14072,14126,14073,14127, -14129,14131,14072,14127,14073,14126,14135,14137, 7,14107, 3,14140, -14072,14142,14073,14143,14145,14147,14072,14143,14073,14142,14151,14153, - 3,14106, 7,14157, 2,14106,14125,14161, 7,14163,14073,14165, - 586,14107,14073,14168,14091,14171,14073,14169,14087,14175, 2,14107, -14158,14179,14073,14181, 7,14179,14157,14184,14073,14187,14073,14185, -14157,14191,14157,14179, 7,14194,14073,14197,14073,14107, 586,14200, -14091,14203, 586,14201,14103,14207, 5,13947,14069,14211, 9165,14213, - 6,14211, 9165,14210,14069,14219, 17,14211, 802,13947, 9165,14225, - 803,13946,14226,14229,14015,14229,14225,14229, 9165,14234, 713,14228, - 3997,14239, 9165,14229,14225,14242, 713,14229, 4147,14247, 9165,13947, - 803,14250,13973,14253, 803,14251,14225,14257, 4,14251, 2,14261, - 7,14263, 5,14250,14265,14267,14069,14267, 587,13947, 9340,14273, - 9323,14273, 9290,14273, 9317,14279, 9335,14273, 9287,14282, 9287,14273, - 9335,14286, 5,14273, 9195,14290, 9317,14293, 9195,14291, 9335,14297, - 9195,14273, 5,14300, 9317,14303, 5,14301, 9287,14307, 587,13946, - 5,14310, 0, 265, 446,14315, 4371,14317, 445,14314, 1675,14321, - 8725,14315, 8766,14315, 471,14314, 2367,14329, 8827,14315, 8836,14315, - 319,14314, 4497,14337, 1302,14315, 667,14315, 8794,14315, 8768,14315, - 8727,14315, 8774,14315, 8732,14315, 1011,14315, 1275,14354, 3,14315, - 1369,14359, 11,14361, 5,14315, 9,14365, 1275,14367, 3,14314, - 1291,14371, 524,14371,14369,14371, 483,14371, 11,14378, 11,14371, - 483,14382, 5,14314, 525,14387,14371,14389,14373,14387,14375,14387, - 1290,14387,14371,14397,14363,14387,14385,14387,14381,14387, 17,14387, - 1275,14406,14371,14409, 1275,14387, 17,14412,14371,14415, 8770,14315, - 241,14418, 8729,14315, 241,14422, 445,14315, 241,14426, 4371,14429, - 1303,14315, 666,14315, 8784,14315, 4266,14315, 8622,14315, 8717,14441, - 8824,14315, 8717,14445, 8702,14315, 8717,14449, 256,14314, 7185,14453, - 2309,14453, 5673,14453, 5521,14453, 375,14461, 4213,14315, 375,14464, - 316,14315, 4533,14469, 1757,14469, 8697,14315, 629,14315, 407,14315, - 5325,14479, 3121,14315, 3031,14315, 5519,14315, 3355,14315, 510,14315, - 8788,14315, 8647,14492, 8676,14315, 8757,14496, 8647,14315, 8831,14500, - 8788,14500, 8757,14500, 241,14506, 241,14500, 8757,14510, 331,14315, - 1325,14315, 59,14315, 5521,14315, 375,14521, 375,14315, 4213,14524, - 8757,14524, 53,14525, 1471,14525, 253,14525, 253,14314, 4425,14537, - 4497,14537, 483,14315, 9,14542, 9,14315, 483,14546, 8684,14315, - 8717,14551, 241,14553, 241,14550, 8717,14557, 331,14551, 251,14315, - 257,14563, 8495,14565, 8635,14315, 8757,14568, 5515,14315, 331,14573, - 8757,14315, 8635,14576, 8676,14576, 8647,14576, 241,14582, 375,14576, - 241,14576, 8647,14588, 1369,14314, 2853,14593, 15,14315, 1275,14315, - 1011,14598, 587,14315, 241,14602, 8831,14315, 8647,14606, 6,14314, -14341,14611,14343,14611,14601,14611,14357,14611, 8495,14611, 241,14611, - 7,14314,14433,14625,14435,14625,14605,14625, 8495,14625, 3785,14625, -10055,14625,10351,14625, 4329,14625, 4311,14625, 4555,14625,14073,14625, - 4971,14625, 8717,14625, 7,14315, 8813,14652,14623,14653, 8495,14657, - 4,14653, 2,14660,14620,14663, 8495,14663,14611,14666,14611,14663, - 8495,14670, 2,14653, 4,14674,14620,14677, 8495,14677,14611,14680, -14611,14677, 8495,14684, 240,14653,14620,14689, 8495,14689,14611,14692, -14611,14689, 8495,14696, 8812,14652, 8717,14701, 8495,14652, 8717,14705, - 241,14707, 241,14704, 8717,14711, 331,14705, 15,14653, 483,14717, - 1275,14653, 9,14721, 8495,14653, 8831,14725,14655,14725, 8788,14725, - 8757,14725, 241,14732, 241,14725, 8757,14736, 375,14653, 8647,14653, - 241,14652, 8647,14745, 8495,14744, 8717,14749, 8495,14745, 8757,14753, - 257,14314, 8614,14757, 4417,14757, 8495,14757, 251,14762, 251,14757, - 8495,14766, 256,14315, 8647,14771, 7207,14771, 5432,14771, 5325,14771, - 375,14778, 8495,14770, 8717,14783, 375,14771, 5325,14786, 8495,14771, - 8757,14791, 8812,14315, 6,14794, 7,14794, 8717,14799, 6,14795, -14799,14803, 7,14795,14797,14807, 8647,14807, 8495,14315, 261,14812, - 260,14812, 256,14812, 8717,14819, 256,14813, 8635,14823, 6,14813, -14815,14827, 7,14813,14817,14831, 8635,14831, 8676,14831, 8647,14831, - 241,14838, 375,14831, 241,14831, 8647,14844, 6,14812, 241,14848, -14831,14851, 7,14812, 8717,14855, 241,14857, 241,14854, 8717,14861, - 331,14855, 241,14812, 6,14866,14831,14869, 7,14866, 8717,14873, - 6,14867,14873,14877,14855,14877, 7,14867,14869,14883, 8647,14883, - 241,14315, 445,14888, 4371,14891, 445,14889, 4349,14895, 8770,14888, - 8729,14888, 587,14888,14625,14903, 8684,14888, 8717,14907, 8757,14888, - 8647,14910, 8387,14889, 8495,14915, 8647,14888, 8757,14918, 6,14889, - 8842,14923, 8495,14923, 8337,14926, 8337,14923, 8495,14930, 7,14889, - 8717,14935, 3785,14935, 8495,14935, 6,14888,14935,14943, 7,14888, - 8647,14947, 8495,14946, 8717,14951,14923,14947, 8495,14947, 8757,14957, - 8495,14888, 6,14960, 7,14960, 8717,14965, 6,14961,14965,14969, - 7,14961,14963,14973, 8647,14973, 8337,14889, 8647,14979, 7,14979, - 8495,14983,12745,14315, 375,14987, 241,14314, 9099,14991, 9036,14991, - 8647,14991, 8997,14996, 5521,14991, 375,15001, 375,14991, 9082,14991, - 8495,15007, 7,14991, 8495,15011, 8997,15013, 8997,15010, 8495,15017, - 8997,14991, 8647,15020, 7,15020, 8495,15025, 0, 241, 460,15029, - 2315,15031, 479,15029, 2393,15035, 479,15028, 2397,15039, 460,15028, - 2317,15043, 457,15028, 2317,15047, 269,15028, 2885,15051, 464,15029, - 16,15029, 413,15029, 6,15058, 4,15029, 7,15062, 7,15063, - 15,15063, 483,15069, 2,15029, 587,15073, 17,15075, 2,15028, - 525,15079, 1290,15079,15071,15079, 1275,15079, 17,15086, 17,15079, - 1275,15090, 4,15028, 1291,15095,15079,15097,15081,15095,15083,15095, - 524,15095,15079,15105,15077,15095,15093,15095,15089,15095, 11,15095, - 483,15114,15079,15117, 483,15095, 11,15120,15079,15123, 9072,15029, - 305,15127, 9105,15029, 305,15131, 9083,15029, 413,15135, 412,15134, -15137,15139, 412,15135, 413,15134,15143,15145, 3445,15029, 375,15149, -12526,15029,12528,15029, 251,15029, 375,15029, 305,15159, 8997,15161, - 8997,15158, 305,15165,12614,15029, 375,15169, 7065,15029, 265,15173, - 7259,15175, 305,15028, 9105,15179, 9072,15179, 375,15179, 8997,15184, - 8997,15179, 375,15188, 9082,15029, 375,15193, 265,15193, 5521,15029, - 375,15199, 265,15199, 483,15029,12377,15204, 9,15029,12377,15208, - 17,15029,13737,15029, 375,15215, 6,15028, 3,15219, 5,15220, -15193,15223, 5,15219, 3,15226,15193,15229,15197,15219,15057,15219, - 3,15235, 2,15234,15237,15239, 2,15235, 3,15234,15243,15245, -15065,15219, 3,15249, 2,15248,15251,15253, 2,15249, 3,15248, -15257,15259, 264,15219,15193,15263, 8997,15219, 7,15028, 4437,15269, -15213,15269, 3,15273, 2,15272,15275,15277, 2,15273, 3,15272, -15281,15283,12571,15269, 4805,15269, 4613,15269,14073,15269, 375,15269, - 510,15269, 4971,15269, 483,15269, 9,15300, 9,15269, 483,15304, - 6,15029, 9020,15309, 9021,15309,12393,15309,12392,15309, 8337,15309, - 265,15318, 8452,15308, 241,15322, 8453,15309,15325,15327, 8452,15309, - 8453,15308, 412,15309, 8997,15335, 241,15308, 265,15338,15327,15341, - 8452,15339,15333,15345,15067,15309, 3,15349, 2,15348,15351,15353, - 2,15349, 3,15348,15357,15359, 413,15308,15313,15363,15315,15363, -15331,15363,15321,15363, 8997,15363,15335,15372,15336,15363,15335,15363, - 8997,15378, 412,15308,15311,15383,15317,15383,15327,15383, 413,15309, -12377,15390,15383,15393, 8997,15390,15383,15397,15383,15391, 8997,15401, -12377,15309, 413,15404,15383,15407, 413,15405,15335,15411, 8997,15309, - 413,15414,15383,15417, 413,15415,15335,15421, 265,15309, 8337,15424, -15363,15427, 265,15308, 241,15430,15327,15433, 7,15029,15223,15437, - 8997,15439,15229,15437, 8997,15443,15263,15437, 8997,15447, 4,15436, -15219,15451, 3,15453, 2,15452,15455,15457, 2,15453, 3,15452, -15461,15463, 264,15436, 264,15437,12377,15436, 375,15471, 8997,15436, -15223,15475,15229,15475, 375,15475,15263,15475, 265,15475,15219,15485, - 59,15437, 1325,15437, 331,15437, 1275,15437, 9,15495, 15,15437, - 483,15499, 265,15437,15266,15503,15219,15503, 8997,15506,15467,15503, - 8997,15503,15219,15512, 305,15503, 265,15436,15469,15519, 331,15519, - 375,15028, 3307,15525, 2885,15525,12511,15525,12377,15525, 251,15533, - 340,15029, 331,15537, 9136,15029, 7,15541, 8997,15029, 375,15544, - 305,15547, 305,15545, 375,15551, 6,15545, 3,15555, 5,15556, - 5,15555, 3,15560, 264,15555, 7,15545, 8495,15567, 331,15567, - 1325,15567, 59,15567, 265,15567, 7,15544,15559,15579,15563,15579, -15223,15579,15229,15579, 375,15579,15263,15579,15565,15579, 265,15579, -15219,15595,15555,15595, 265,15544,15555,15601, 7,15601, 265,15545, - 8647,15607, 7,15607, 8495,15611, 265,15029, 7,15615, 375,15617, - 7,15614, 331,15621, 8997,15614, 7,15625,12377,15029,13421,15629, -13313,15629,13621,15629,14923,15629,12721,15629,12715,15629,12709,15629, - 375,15629,12705,15645, 7,15629, 331,15649, 483,15628, 9,15628, - 7,15628, 375,15657, 265,15028, 9036,15661, 9099,15661, 241,15661, - 6,15667,15629,15669, 8647,15661, 8997,15672, 5521,15661, 375,15677, - 9082,15661, 8495,15681, 375,15661, 7,15661, 8495,15687, 8997,15689, - 8997,15686, 8495,15693, 8997,15661, 8647,15696, 7,15696, 8495,15701, - 0, 587, 9319,15705, 9336,15705, 889,15704, 2373,15711, 9371,15705, - 9374,15705, 9350,15705, 9338,15705, 9321,15705, 9342,15705, 9324,15705, - 578,15705, 3,15705, 6,15730, 7,15705, 567,15735, 9195,15737, - 4,15735, 9366,15741, 483,15741, 9195,15744, 9195,15741, 483,15748, - 7,15704, 9340,15705, 483,15754, 9323,15705, 483,15758, 579,15705, - 9272,15705, 9317,15765, 9368,15705, 9317,15769, 9294,15705, 9317,15773, - 566,15704,15729,15777, 9348,15705, 9287,15780, 9288,15705, 9335,15784, - 9287,15705, 9373,15788, 9348,15788, 9335,15788, 483,15794, 483,15788, - 9335,15798, 567,15705, 9,15802,15777,15805,15777,15803, 9,15809, -12377,15705, 11,15813, 9,15705, 567,15816,15777,15819, 567,15817, - 9290,15705, 9317,15825, 483,15827, 483,15824, 9317,15831, 9275,15705, - 9335,15834, 375,15705, 11,15839, 11,15704, 375,15843, 9335,15705, - 9275,15846, 9288,15846, 9287,15846, 483,15852, 483,15846, 9287,15856, - 9,15704, 5231,15861, 5181,15861,10505,15861,14057,15861, 1011,15704, - 375,15871, 9373,15705, 9287,15874, 4,15704, 9262,15879, 375,15879, - 9195,15882, 7,15879, 265,15887, 9195,15889, 9195,15879, 375,15892, - 483,15879, 5,15704, 5,15705, 9367,15900, 9366,15900, 9317,15905, - 9195,15900, 9317,15909, 483,15911, 483,15908, 9317,15915, 9195,15901, - 9373,15919,15903,15919, 9348,15919, 9335,15919, 483,15926, 483,15919, - 9335,15930, 483,15900, 9195,15934, 9317,15937, 9195,15935, 9335,15941, - 567,15704,15763,15945, 9,15945, 566,15705,15823,15951,15948,15951, -15945,15951, 9,15956, 9195,15950, 9317,15961, 9195,15951, 9335,15965, - 9,15951,15945,15968, 9366,15705, 5,15972, 9317,15975, 5,15973, - 9287,15979, 9195,15705, 566,15982, 9317,15985, 566,15983, 9275,15989, - 5,15983, 9275,15993, 9288,15993, 9287,15993, 483,15998, 483,15993, - 9287,16002, 5,15982, 9317,16007, 483,16009, 483,16006, 9317,16013, - 483,15982, 5,16016, 9317,16019, 5,16017, 9287,16023, 483,15705, - 9340,16026, 9323,16026, 9290,16026, 9317,16033, 9335,16026, 9287,16036, - 9287,16026, 9335,16040, 5,16026, 9195,16044, 9317,16047, 9195,16045, - 9335,16051, 9195,16026, 5,16054, 9317,16057, 5,16055, 9287,16061, - 0, 483, 878,16065, 2327,16067, 899,16065, 2415,16071, 899,16064, - 2423,16075, 878,16064, 2331,16079, 875,16064, 2331,16083, 573,16064, - 2569,16087, 2,16064, 15,16091, 413,16064, 413,16065, 573,16065, - 2567,16099, 1216,16064, 1216,16065, 904,16065, 2263,16107, 6515,16065, - 5,16111, 6539,16113, 903,16064, 4421,16117, 5285,16117, 2265,16117, - 4,16064, 5,16064, 4,16065, 2,16129, 7,16131, 0,16130, - 0,16129, 2,16136, 15,16129, 483,16141,16135,16143,16139,16143, - 9513,16065, 5,16149,16133,16151, 4,16148, 2,16155, 7,16157, -16151,16159, 1, 1011, 996,16162, 14,16162, 5,16163, 6,16169, - 9617,16171, 2,16162, 9617,16175,16171,16176,16172,16175,16171,16175, - 9617,16182, 7,16175,16169,16187, 9617,16189, 5,16162,16186,16193, -16175,16193, 7,16196, 7,16197,16187,16193, 6,16192,16195,16205, -16199,16205, 7,16192,16203,16211,16175,16211, 3,16211,16162,16217, - 3,16193, 7,16221,16162,16222,16162,16221, 7,16226, 7,16227, -16205,16231, 6,16193,16201,16235,16214,16235,16175,16235,16211,16240, -16211,16235,16175,16244,16225,16235,16229,16235,16219,16235, 7,16193, -16175,16254,16205,16257,16205,16255,16175,16261, 9704,16163, 587,16265, - 5293,16163, 587,16269, 997,16162, 972,16162,16235,16275, 9,16275, -14652,16163, 973,16163,16273,16283,16278,16283, 9,16283,16275,16288, -16275,16283, 9,16292, 955,16162, 5241,16297, 1505,16162, 6,16301, - 7,16300,16303,16305, 7,16301, 6,16300,16309,16311, 67,16162, -16235,16315, 9,16163, 9617,16318, 587,16321, 587,16319, 9617,16325, - 15,16162, 257,16163, 9,16331, 9,16162, 973,16335,16275,16337, - 973,16334, 257,16335, 587,16162, 5293,16345, 9704,16345, 9617,16345, - 9,16350, 9,16345, 9617,16354, 6,16162, 5,16358, 7,16162, -16221,16362,16235,16365,16235,16363, 8647,16363, 903,16362,16235,16373, - 6,16163,16329,16377, 7,16163,16167,16381,16205,16381,16361,16381, - 8717,16381,14315,16380, 4311,16381, 4329,16381, 3785,16381,10351,16381, -10055,16381, 973,16162, 9,16402, 972,16163,16341,16407,16165,16407, -16405,16407,16403,16407, 9,16415, 9617,16163, 1368,16418, 14,16418, - 2,16418, 7,16425,16423,16427, 7,16424, 5,16418, 6,16433, -16431,16435,16421,16435, 6,16432,16427,16441, 2,16419,16435,16445, -16171,16445, 7,16445,16433,16451, 9,16418, 587,16455, 587,16419, - 9,16459, 6,16418, 5,16462,16427,16465, 7,16418, 2,16468, -16435,16471,14315,16163, 7,16474, 17,16475, 903,16162, 3,16480, - 6,16483, 6,16482, 5241,16481, 1274,16480, 15,16480, 1275,16480, - 6,16480, 3,16496, 5,16496, 7,16480,16485,16503,16235,16503, - 6,16481,16495,16509,16493,16509, 7,16481,16499,16515,16501,16515, -16487,16515,16205,16515,16361,16515,16491,16515,16167,16515, 1, 903, - 9542,16530, 9543,16530, 1274,16530, 3,16530, 9541,16539, 6,16538, - 7,16538, 5,16545,16530,16547, 5,16539, 7,16551,16530,16552, -16530,16551, 7,16556, 7,16557,16543,16561, 6,16539, 9533,16565, -16545,16565,16555,16565,16559,16565,16549,16565, 7,16539,16543,16577, - 4,16530,16576,16581,16543,16583,16539,16581, 7,16586,16543,16589, - 7,16587,16565,16593,16545,16581,16565,16596,16565,16581,16545,16600, -16568,16581,16579,16581, 7,16581,16539,16608,16543,16611,16539,16609, -16545,16615, 1170,16530,16565,16619, 9541,16531,16535,16623, 559,16530, - 5241,16627, 767,16530,16565,16631, 165,16530, 6,16635, 7,16634, -16637,16639, 7,16635, 6,16634,16643,16645, 9540,16531,16543,16649, -16533,16649,16539,16649,16537,16649, 1275,16530,16623,16659, 9533,16659, - 257,16531, 483,16665, 483,16530, 257,16669, 15,16530, 5241,16673, - 6,16530, 3,16676,16649,16679, 7,16530,16541,16683,16566,16683, -16551,16682,16565,16689,16565,16683, 9533,16692, 375,16683, 1011,16682, -16565,16699, 9533,16683,16565,16702,15269,16683, 4827,16683, 6,16531, -16662,16711,16659,16711, 9533,16714, 9533,16711,16659,16718, 7,16531, -16539,16723, 9533,16725,16537,16723, 9533,16729, 1007,16723,16543,16723, - 9533,16735,16679,16723, 9533,16739, 331,16723, 1325,16723, 59,16723, - 9533,16722,16543,16749,16539,16749,16679,16749,16537,16749, 9533,16531, - 1275,16759,16711,16761, 7,16759,16565,16765, 7,16758,16539,16769, -16543,16769,16679,16769,16537,16769,15029,16531, 7,16779, 1011,16530, - 5,16782, 6,16785, 6,16784, 5241,16783, 14,16782, 1275,16782, - 15,16782, 6,16782, 5,16798, 3,16798, 7,16782,16787,16805, -16565,16805, 6,16783,16797,16811,16795,16811, 7,16783,16801,16817, -16803,16817,16789,16817,16543,16817,16679,16817,16793,16817,16537,16817, - 1, 1369, 1010,16833, 16,16833, 2,16833, 5,16838, 5,16839, -16837,16843, 7,16833, 4,16846,16843,16849, 4,16847,16841,16853, -16835,16853, 2,16832, 11,16859,15900,16833, 331,16832, 59,16832, - 6717,16833, 9,16869, 1325,16832, 265,16832, 4,16833, 7,16876, -16843,16879, 2,16877, 1,16882, 1,16877, 2,16886, 11,16877, - 1369,16891,16885,16893,16889,16893, 5,16833, 2,16898,16853,16901, -15705,16898, 1275,16898, 9,16907, 1346,16833, 9,16911,15705,16833, - 11,16915, 5,16914, 1275,16833, 5,16921, 17,16923, 5,16920, - 9,16927, 1275,16832, 6717,16931, 9,16933, 1, 1275, 5814,16937, - 902,16937, 902,16936, 3,16937, 7,16944, 413,16937, 1216,16937, - 6787,16937, 5,16953, 4,16952,16955,16957, 4,16953, 5,16952, -16961,16963, 1505,16937, 5771,16937, 903,16968, 1011,16937, 903,16972, - 903,16936,16941,16977, 241,16936, 17,16936, 5299,16983, 4915,16983, - 11,16936, 903,16937, 5771,16990,16943,16991, 1011,16990,15208,16937, - 9,16937,15029,17000,15029,16937, 9,17004, 4,16936, 265,17009, - 5,16936, 4,16937, 1011,17015, 1369,16936, 6717,17019, 9,17021, - 1, 17, 4,17025, 6,17026, 113,17025, 1275,17024, 5299,17033, - 4915,17033, 241,17025, 2,17024, 3,17024,11731,17025, 265,17045, - 1, 15, 5886,17049, 5,17048, 483,17053, 413,17049, 1216,17049, - 165,17049, 5843,17049, 1011,17062,14315,17049, 17,17067, 903,17049, - 1011,17070, 1011,17048, 241,17048, 903,17048, 5241,17079, 1011,17049, - 5843,17082, 903,17082,15204,17049, 483,17049,15029,17090,15029,17049, - 483,17094, 3,17048, 483,17099, 2,17049, 3,17049, 5,17105, - 1,17106, 1,17105, 5,17110, 483,17105, 15,17115,17109,17117, -17113,17117, 1369,17105, 0, 1011, 2,17125, 7,17127, 9565,17129, - 5,17124, 9565,17133,17129,17134,17130,17133,17129,17133, 9565,17140, - 6,17133,17127,17145, 9565,17147, 9600,17125, 9,17151, 5267,17125, - 9,17155,16722,17125,10385,17125, 9,17161, 587,17125, 9565,17164, - 9,17167, 9,17165, 9565,17171, 1275,17125, 903,17175, 9,17125, - 375,17125, 587,17181, 9,17124, 5267,17185, 9600,17185, 9565,17185, - 587,17190, 587,17185, 9565,17194, 587,17124, 375,17199,13737,17125, - 9,17203, 6,17124,17176,17207,17175,17207, 903,17210, 903,17207, -17175,17214, 7,17124,10001,17219, 903,17221, 6,17125, 3,17224, -17219,17227, 903,17229, 7,17125, 88,17233, 89,17233, 265,17233, - 264,17232,17239,17241, 264,17233, 3,17233, 9,17246, 3,17232, -17237,17251, 9,17251, 2,17232,17235,17257,17249,17257,17247,17257, - 9,17263, 265,17232,17245,17267, 2,17233,17254,17271, 9,17271, -17251,17274,17251,17271, 9,17278,16531,17232, 9,17233, 3,17284, -17257,17287, 3,17285,17271,17291, 903,17233, 9565,17125, 1368,17297, - 14,17297, 2,17296, 7,17303, 2,17297, 7,17306, 7,17307, -17301,17311, 5,17297,17305,17315,17129,17315, 6,17314,17311,17321, - 6,17315,17309,17325,17303,17325,17299,17325, 587,17296, 9,17333, - 9,17297, 587,17337, 6,17297, 5,17340,17311,17343, 7,17297, - 2,17346,17325,17349,12377,17125, 9,17353,16531,17125, 6,17357, - 7,17357, 6,17356,17361,17363, 7,17356,17359,17367, 0, 903, - 767,17370, 4617,17373, 483,17375, 15,17371, 1011,17379, 767,17371, - 4588,17383, 483,17383, 4579,17386, 4579,17383, 483,17390, 375,17371, - 11,17395, 483,17370, 2265,17399, 4421,17399, 5285,17399, 11,17370, - 375,17407, 6,17370,17380,17411,17379,17411, 1011,17414, 1011,17411, -17379,17418, 7,17370, 3549,17423, 2001,17423, 8495,17423,10291,17423, - 1011,17431,14073,17423,11277,17423, 4971,17423, 5045,17423, 6,17371, - 5,17442,17423,17445, 1011,17447, 7,17371, 1011,17451, 0, 1369, - 2789,17455, 2821,17455, 2759,17455, 2687,17455, 6658,17455, 2,17455, - 6,17466, 6625,17455, 9,17470,12551,17455, 1347,17455,13808,17455, - 6685,17455,13833,17455, 4413,17455,17025,17455, 265,17487, 241,17486, -17038,17455, 903,17455, 9,17455, 6625,17496, 17,17454,12377,17501, - 11,17454,12377,17505, 803,17455, 15,17454, 5303,17511, 4927,17511, -17033,17511,16983,17511, 265,17454, 2853,17521,17082,17455, 11,17455, -12377,17526,12564,17455, 241,17455,13737,17532,17025,17532, 1011,17455, -17049,17538,12377,17455, 10,17543, 10,17542, 305,17543, 11,17543, -17547,17551, 11,17542,17545,17555,17049,17455, 1011,17558, 4,17454, - 5,17455,13737,17455, 241,17566, 0, 1275, 3,17570, 9,17573, - 4,17570, 5,17570, 9856,17579, 9805,17579, 9,17582, 9,17579, - 9805,17586, 5,17571, 3,17591, 0,17592, 0,17591, 3,17596, - 9,17591, 1275,17601,17595,17603,17599,17603, 17,17591, 9805,17609, - 1369,17590, 17,17613, 1486,17571, 17,17617, 1369,17571,17577,17621, - 9,17623, 5,17621, 9,17627, 5,17620, 17,17631, 0, 17, - 4,17634, 587,17637, 155,17635, 1011,17635, 1369,17634,12377,17645, -16990,17635, 587,17635,12377,17650,12566,17635, 903,17635,16937,17656, -12377,17635, 587,17660,16937,17635, 903,17664, 3,17634, 483,17669, - 2,17635, 4,17673, 0,17674, 0,17673, 4,17678, 587,17673, - 17,17683,17677,17685,17681,17685, 3,17635, 1369,17691, 0, 15, - 5,17695, 7,17696, 1369,17694, 5303,17701, 4927,17701,16983,17701, -17033,17701, 3,17694, 3,17695,10104,17712,10105,17713,17715,17717, -10104,17713,10105,17712,17721,17723, 1, 13, 113,17727, 0, 12, -17727,17731, 9,17732, 2,17735, 2,17734, 137,17732, 136,17732, - 2,17733,17741,17745, 3,17733,17739,17749,17743,17749, 2,17732, - 9,17754,17749,17757,17749,17755, 3,17732,17737,17763,17745,17763, - 0, 13, 1, 12, 1369,17771, 33,17771, 3,17770, 8251,17777, - 3807,17777, 9875,17777, 8165,17777, 3,17771, 8241,17787,17769,17771, - 9,17791, 2,17792, 2,17793, 137,17791, 136,17791, 2,17791, - 9,17802, 3,17791,17797,17807, 2,17790,17807,17811,17799,17811, - 3,17790,17805,17817,17795,17817,17803,17817,17801,17817, 1, 413, - 4,17826, 2,17826, 5,17826, 6,17833, 6,17832, 3,17826, - 6,17839, 6,17838, 2653,17827, 1637,17827,14537,17827,14321,17827, - 260,17826, 2903,17827, 1639,17827, 1641,17827, 3361,17827, 331,17826, -17521,17827, 4909,17827,14593,17827, 261,17826, 257,17826, 14,17826, - 1274,17826, 2159,17827, 2161,17827, 251,17827, 2647,17827, 331,17885, - 15,17826, 1275,17826,14652,17827, 6,17827,17829,17895,17831,17895, - 8997,17895,17863,17895,17871,17895,17889,17895,17891,17895, 7,17827, -17833,17911,17839,17911, 8495,17911, 413,17910, 0,17919,17837,17911, -17843,17911, 265,17911,17921,17927, 1,17927,17919,17931, 2647,17927, - 8717,17911, 3785,17911,17853,17911,17875,17911,17877,17911,14315,17910, - 261,17911, 7,17826,17835,17951,17841,17951, 8647,17951, 251,17951, - 6,17826, 5,17960,17911,17963, 3,17960,17911,17967,15029,17827, - 265,17971,17895,17973, 7,17971,14315,17827, 6,17978, 7,17978, - 6,17979,17983,17985, 7,17979,17981,17989, 0, 412, 9036,17993, - 9099,17993,17829,17993,17895,17998,17831,17993,17895,18002,17896,17993, -17898,17993,17913,17993,17915,17993, 446,17993, 4371,18015, 4379,17993, -17900,17993,17917,17993, 4360,17993, 3429,17993,17882,17993, 7039,17993, -17958,17993,17949,17993, 241,17993, 445,18036, 4371,18039, 445,18037, - 4349,18043,16097,17993,12289,17993, 8647,17993, 8997,18050, 4349,17993, - 251,18054,17951,17993, 251,18058, 251,17993, 4349,18062,17827,18062, -17951,18062,17895,17993,17829,18070,17831,18070, 8997,18070, 5521,17993, - 375,18079, 445,17993, 241,18082, 4371,18085, 3,18083, 2,18082, -18089,18091, 2,18083, 3,18082,18095,18097, 465,17993, 5,18101, - 4,18100,18103,18105, 4,18101, 5,18100,18109,18111, 9082,17993, - 8495,18115,17910,17993,17833,18119,17839,18119, 8495,18119, 375,17993, - 7,17993, 8495,18129, 8997,18131,17827,18129,17829,18135,17831,18135, - 8997,18135, 8997,18128, 8495,18143,17827,18128,17833,18147,17839,18147, - 8495,18147, 8997,17993, 8647,18154,17895,18154, 7,18154, 8495,18161, -17827,17993, 241,18164, 6,18167, 6,18166, 265,18165,17895,18173, - 261,18164, 375,18165, 260,18164, 251,18164, 6,18165,18177,18185, - 7,18165,18171,18189,18181,18189, 6,18164,18173,18195, 241,18194, -18189,18199,18189,18195, 7,18164,17833,18205,17839,18205,18169,18205, -18185,18205, 8495,18205, 1, 843, 0, 842,18217,18219, 483,18220, - 4,18223, 4,18222, 581,18220, 580,18220, 4,18221,18229,18233, - 5,18221,18227,18237,18231,18237, 4,18220, 483,18242,18237,18245, -18237,18243, 5,18220,18225,18251,18233,18251, 0, 413,15309,18257, - 265,18258,15363,18261,15424,18257,15363,18265,13375,18257,13381,18257, - 4888,18257,13162,18257, 251,18256, 375,18256, 265,18257,15309,18281, -15383,18283,15309,18280,15363,18287, 331,18257, 2663,18257, 251,18293, - 9,18256, 483,18256, 375,18257, 4863,18300,13119,18300, 4863,18257, - 375,18306,13119,18257, 375,18310, 6,18257, 264,18314, 7,18257, - 264,18318, 264,18319, 265,18319,18321,18325, 265,18318,18323,18329, - 8647,18319, 375,18319, 331,18319, 7,18256, 1689,18339, 1705,18339, - 2701,18339,18317,18339, 8717,18339,12755,18339, 7627,18339, 7895,18339, - 3785,18339,13443,18339, 7287,18339, 265,18339, 331,18339, 8495,18339, - 375,18339,12745,18339, 457,18371, 375,18371, 6,18256,18291,18377, -12745,18257,17895,18381, 8647,18381, 7,18381, 8495,18387, 1, 412, - 1679,18391, 448,18391, 4349,18395, 4351,18391, 4390,18391,18300,18391, - 4457,18391,18277,18391, 1673,18391,18279,18391, 1789,18391,18364,18391, -18335,18391, 3427,18391, 7037,18391, 265,18391, 445,18422, 4349,18425, - 445,18423, 4371,18429,16095,18391,12287,18391, 5189,18391,18299,18391, -18297,18391, 2153,18391, 2151,18391, 4371,18391, 331,18446,18339,18391, - 331,18450, 331,18391, 4371,18454,18339,18454, 445,18391, 265,18460, - 4349,18463, 5,18461, 4,18460,18467,18469, 4,18461, 5,18460, -18473,18475, 465,18391, 3,18479, 2,18478,18481,18483, 2,18479, - 3,18478,18487,18489, 8386,18391,18318,18391, 375,18391,18257,18496, - 7,18391, 265,18501,18257,18503, 8337,18500,18257,18500, 8337,18391, - 7,18510, 8861,18391, 6,18515, 7,18515, 6,18514,18519,18521, - 7,18514,18517,18525,18257,18391, 265,18528, 241,18529, 6,18532, - 6,18533, 375,18528, 261,18529, 260,18529, 251,18529, 6,18529, - 241,18546,18531,18547, 7,18529, 8495,18553,18537,18553, 6,18528, -18553,18559,18541,18559, 7,18528,18549,18565,18535,18565,18547,18565, -18543,18565, 0, 843, 1, 842, 5,18576,18575,18577, 483,18581, - 4,18582, 4,18583, 581,18581, 580,18581, 4,18581, 483,18592, - 5,18581,18587,18597, 4,18580,18597,18601,18589,18601, 5,18580, -18595,18607,18585,18607,18593,18607,18591,18607, 1, 1217,16117,18617, -12291,18617,16103,18617, 4959,18617,17399,18617, 2205,18617, 2207,18617, - 1269,18617, 5,18633, 4,18632,18635,18637, 4,18633, 5,18632, -18641,18643, 1259,18617, 2,18647, 3,18646,18649,18651, 3,18647, - 2,18646,18655,18657, 7,18617, 0, 1216, 9,18662,18617,18665, - 483,18662,18617,18669,18660,18663, 7,18663,18617,18674,18617,18663, - 6,18679, 7,18679, 6,18678,18683,18685, 7,18678,18681,18689, - 1, 1531, 4904,18693,17609,18693,17586,18693, 4903,18693, 9,18700, -17579,18693, 9,18704, 9,18693, 4903,18708,17579,18708, 5,18692, - 0, 1530,18693,18717, 4,18719, 5,18719, 4,18718,18723,18725, - 5,18718,18721,18729, 1, 19, 1369,18733, 3,18733, 3,18732, - 9875,18739, 0, 18,18733,18743, 2,18745, 3,18745, 2,18744, -18749,18751, 3,18744,18747,18755, 0, 1217,12293,18759,16105,18759, - 1269,18759, 2,18765, 3,18764,18767,18769, 3,18765, 2,18764, -18773,18775, 1259,18759, 5,18779, 4,18778,18781,18783, 4,18779, - 5,18778,18787,18789, 375,18759, 7,18759, 1, 1216, 4,18796, -18759,18799, 3,18796, 6,18803, 6,18802, 5,18796, 6,18809, - 6,18808, 2,18796,18759,18815, 5241,18797, 14,18796, 1274,18796, - 2157,18797, 2155,18797,18795,18797,18799,18829,18815,18829, 15,18796, - 1275,18796, 6,18796, 3,18838, 5,18838, 7,18796,18805,18845, -18811,18845,18794,18797,18803,18851,18809,18851, 6,18797,18800,18857, -18816,18857,18799,18857,18759,18862,18815,18857,18759,18866,18835,18857, -18837,18857,18759,18857,18799,18874,18815,18874, 7,18797,18841,18881, -18843,18881,18803,18881,18759,18887,18809,18881,18759,18891,18807,18881, -18813,18881,18821,18881,18823,18881,18759,18880,18803,18903,18809,18903, -18759,18797, 6,18909, 7,18909, 6,18908,18913,18915, 7,18908, -18803,18919,18809,18919,18911,18919, 0, 1531, 1, 1530, 6717,18929, - 9,18931,18927,18929, 4,18935, 5,18935, 4,18934,18939,18941, - 5,18934,18937,18945, 0, 19, 1, 18,18949,18951, 2,18953, - 3,18953, 2,18952,18957,18959, 3,18952,18955,18963, 0, 2, -11303,18967,11349,18968, 5071,18967, 5097,18972,11350,18967, 5098,18967, -11304,18967,11307,18981, 5072,18967, 5075,18985,11315,18967, 5079,18967, -13961,18967, 581,18993, 4,18992,18995,18997, 5,18992, 580,18993, -19001,19003, 5,18993, 4,18993, 483,19008,19001,19011, 483,18993, - 4,19014,19001,19017, 4,19015,19007,19021, 1181,18966, 1206,18966, - 3451,18967, 375,19029, 1967,18967, 375,19033, 567,18966, 4992,19037, - 9,19037, 4971,19040, 4971,19037, 9,19044, 1141,18966, 555,18966, - 981,18967,16129,18966,16143,19055, 9523,18967, 483,19059, 9525,19061, - 1007,18967, 1297,18966, 524,18966, 0,19069, 4,19070, 4,19069, - 0,19074, 97,18967,11067,18967, 1275,19080, 7947,19083, 1205,18967, - 571,18967,11070,18967, 7947,19091,10043,18967, 1275,19094,10041,19097, -10044,18967,10041,19101, 1206,18967, 3001,19105, 1901,19105, 30,18967, - 8165,19111, 8150,18967, 33,19115, 1181,18967, 3663,19119, 1997,19119, - 3069,19119, 1923,19119, 9769,18967, 3972,18967, 8124,18967, 9357,18967, - 9346,18967, 8782,18967, 4244,18967, 4178,18967, 9768,18967, 8804,18967, - 8245,18967, 8249,18967, 8247,18967, 6950,18967,12299,18967, 4652,18967, -10684,18967,14096,18967, 4992,18967, 203,18967,11731,19167,17771,18967, - 113,19171,14223,18967, 85,18967,11731,19177,11031,18967, 113,19181, - 107,18967,11731,19185,11699,18967, 113,19189, 8701,18967, 9293,18967, - 3933,18967, 9,19196, 8109,18967, 9,19200, 4213,18967, 9,19204, - 4147,18967, 9,19208, 8757,18967, 9,19212, 9335,18967, 9,19216, -10202,18967, 7947,19221,17637,19221, 578,18967, 4935,19227,11349,18967, -11303,19230, 5097,18967, 5071,19234, 8647,18967, 11,19239,10603,18967, - 375,19243,10427,19243,10609,19243, 7,19243,10607,19251, 9,19242, - 4625,18967, 375,19257, 75,19257, 4629,19257, 7,19257, 4627,19265, - 9,19256,11277,18967, 10,19270,11307,19273, 10,19271,11349,19277, - 483,19271, 5045,18967, 10,19282, 5075,19285, 10,19283, 5097,19289, - 483,19283, 6789,18967, 9,19294, 288,18967, 525,18967,19073,19301, -19077,19301, 1811,19301, 1877,19301, 5,19301,17563,19301, 4861,19301, - 1290,18967, 5,19317, 3721,19317, 1985,19317,17563,19317, 4861,19317, - 296,18967, 8861,19329, 12,18967, 8165,19333, 18,18967, 25,18967, - 9,19338, 8165,19341, 8165,19339, 9,19345, 7971,18967, 9,19348, - 33,19351, 33,19349, 9,19355, 47,18967,11731,19359,10107,18967, - 1275,19362, 7947,19365,17637,19365, 113,19363, 59,18967,17635,19373, -10291,18967, 165,19377, 375,18967, 510,18967, 11,18967, 8165,19385, - 9,19387, 265,19384, 9,19384, 8165,19393, 9,18967, 567,19397, - 4971,19399, 6,19397, 25,19396, 8165,19405, 7971,19396, 33,19409, - 3933,19396, 8109,19396, 4213,19396, 4147,19396, 9335,19396, 8757,19396, - 8495,19396, 6789,19396, 4625,19396,10603,19396, 4971,19396,14073,19396, - 567,19396, 4935,19437, 11,19397, 8109,19441, 3933,19441, 8495,19441, - 7971,19441, 265,19396, 8861,19451, 11,19396, 8165,19455, 483,19396, - 17,18967, 1275,19460, 4861,19463,17563,19463, 3721,19463, 1985,19463, - 15,19460, 15,18967, 9731,19474, 1011,19475, 483,19475, 17,19474, - 6515,18967, 483,19485, 6527,19487, 6557,19487, 6561,19487,14210,18967, - 17,19495, 4971,18967, 9,19498,14073,18967, 9,19502, 5921,18967, - 375,19507,10046,18967, 16,18966, 0,19513, 4,19514,19317,19517, -19463,19517, 4,19513, 0,19522,19317,19525,19463,19525, 8495,19513, -10351,19513, 4311,19513, 4329,19513, 8717,19513,10055,19513, 3785,19513, - 14,18966, 6,19545, 2,19546, 2,19545, 6,19550, 482,19545, - 17,19545, 10,18966,17777,19559, 2215,19559,11307,19559, 5075,19559, -11713,19559, 2221,19559,11087,19559,10439,19559,10665,19559, 4643,19559, -11037,19559, 2233,19559, 9195,19559,11277,19559, 5045,19559,19455,19559, -19333,19559,19393,19559,19385,19559, 9,19597, 9317,19559, 9755,19559, - 4321,19559,10171,19559, 4295,19559, 3833,19559,10603,19559, 9,19613, - 4625,19559, 9,19617, 8,18967, 11,19621, 14,18967, 9731,19625, - 17,19625, 11,18966, 8124,19631, 3972,19631, 8804,19631, 8150,19631, - 7971,19631, 9,19640, 3933,19631, 9,19644, 8109,19631, 9,19648, - 8495,19631, 9,19652, 9,19631, 8109,19656, 3933,19656, 8495,19656, - 7971,19656, 9,18966,10001,19667, 5,19669, 4,19668,19671,19673, - 4,19669, 5,19668,19677,19679, 16,18967, 7,19683, 10,18967, -11277,19686,11307,19689, 5045,19686, 5075,19693,11349,19687, 5097,19687, - 9195,19687,19656,19687,19441,19687,19631,19687, 9,19706,11277,19687, -11303,19711, 5045,19687, 5071,19715, 9,19687,19631,19718, 19,18967, - 13,18967,19631,19725,10385,18967, 101,19729, 128,19729, 9,19729, - 113,19734, 483,19729,10081,19739,11759,19739,10405,19739, 113,19729, - 9,19746, 67,18967,11613,19751,12216,19751, 9,19751,11731,19756, -11731,19751, 9,19760, 566,18967, 253,19765, 1471,19765, 53,19765, - 256,18967, 629,18967, 1413,18967, 1471,19777, 1346,18967, 340,18967, - 8165,19783, 567,18967, 4935,19787, 9,19789, 9,19786, 4935,19793, - 305,18967, 959,18967,11731,19799, 759,18967,11731,19803, 331,18967, -17635,19807, 1325,18967,17635,19811,10001,18967,10003,19815, 4,19817, - 4,19816,10007,19815, 580,19815,10006,19815, 483,19815, 4,19828, - 4,19829, 581,19815, 4,19815,10003,19836, 483,19836, 5,19815, -19819,19843,19833,19843, 4,19814,19835,19849,19823,19849,19843,19849, - 5,19814,19839,19857,19821,19857,19825,19857,19827,19857,19841,19857, -19831,19857,19837,19857, 9731,18967, 15,19872, 8495,18967, 483,19877, - 9,19876, 9195,18967, 113,19883,11731,19883, 241,18967, 7,19888, - 483,18967, 9,19892, 17,19893, 903,19897, 5,19892, 253,19901, - 1471,19901, 53,19901, 5,19893, 1505,19909, 903,18967, 7,19913, - 1275,18967,10043,19916,10041,19919,11067,19916, 7947,19923,17637,19917, -10107,19927, 0,19916, 4,19931, 0,19932,19917,19935, 7,19932, -19937,19939, 7,19931, 4,19942, 16,19931, 6,19916, 4,19949, - 6,19950,19917,19953, 1,19950,19955,19957, 1,19949, 4,19960, - 8,19916, 4,19965, 1,19966, 1,19965, 4,19970,10107,19916, - 7947,19975,17637,19975, 7947,19917,11067,19981,10107,19981, 9,19917, - 2009,19987, 3135,19987,19969,19987,19973,19987, 5231,19987,19957,19987, -19963,19987, 0,19987, 5175,19987,14065,19987, 17,19916,19525,20009, -19517,20009, 3721,20009, 1985,20009, 1,20009,19987,20019,20003,20009, - 4861,20009,17563,20009, 5,19916, 4,19917, 5,19917, 265,18967, -17635,20035, 5771,20035, 9,20035, 11,20034, 11,20035, 9,20034, - 8861,20047, 483,20035, 7,20034, 8165,20053, 7,20035, 8495,20057, - 587,18967, 7,20061, 4,20063, 4,20062, 16,20061, 17,20061, - 4,20060,20071,20073, 5,20060,20067,20077,20069,20077, 4,20061, - 7,20082,20077,20085, 5,20061,20065,20089,13947,18967, 5,20092, - 17,20095, 5,20093, 9,20099, 4,18966, 8770,20103, 8729,20103, - 8697,20103, 8784,20103, 4266,20103, 9262,20103, 2,20103, 7,20117, - 8684,20103, 8717,20121, 331,20121, 8647,20103, 8757,20126, 8757,20103, - 8647,20130, 375,20130, 4213,20103, 375,20136, 9750,20103,19687,20103, - 347,20103, 386,20103, 340,20103, 331,20149, 375,20103, 8757,20152, - 4213,20152, 9195,20152, 305,20152, 9,20103,10291,20103, 483,20165, - 59,20103, 15,20103, 9195,20103, 375,20172, 331,20103,10001,20103, - 9,20179, 305,20103, 375,20182, 7,20103, 8495,20186, 8717,20189, - 331,20189, 8495,20187, 8757,20195, 9731,20186, 265,20187, 8757,20201, - 4213,20201, 9195,20201, 305,20201, 265,20186, 331,20211, 8647,20187, - 1325,20103, 7,20102, 8495,20219,10351,20219, 4311,20219, 4329,20219, - 3785,20219,10055,20219, 8717,20219, 483,20103, 1275,20103, 265,20103, - 7,20239, 8495,20241, 375,20241, 7,20238, 331,20247, 9731,20103, - 7,20250, 8495,20103, 7,20254, 8717,20257, 331,20257, 483,20255, - 9,20255, 7,20255, 8647,20267, 375,20267, 5,18966, 9535,20273, - 9537,20273, 2,20273, 6,20278, 9559,20273, 482,20273, 9563,20273, - 9362,20273, 922,20273, 1413,20273, 19,20273, 12,20273, 8150,20273, - 8804,20273,19385,20273, 1290,20273, 9533,20305, 525,20273, 9533,20309, - 7971,20273, 9,20312, 11,20273, 9,20316, 17,20273, 1275,20320, - 9533,20323, 9,20273, 9195,20326, 11,20326, 7971,20326, 8495,20326, - 9195,20273, 9,20336, 6,20273, 5,20341, 2,20340, 5,20340, -18967,20347, 11,20341, 7,20273, 5,20353, 6,20272, 17,20357, - 7,20272, 9195,20361,11277,20361, 5045,20361, 9755,20361, 4295,20361, -10171,20361, 4321,20361, 3833,20361, 9317,20361, 483,20273, 903,20380, - 1275,20273, 17,20384, 9533,20387, 903,20273, 483,20390, 8495,20273, - 9,20394, 9731,20273, 6,20398, 7,20398, 6,20399,20403,20405, - 7,20399,20401,20409, 6,18966,19836,20413,19857,20415,19854,20413, -19871,20413,19815,20413, 4,20423,19843,20425, 4,20422,19857,20429, -19477,20413,19145,20413,19875,20413,19843,20413,19849,20438,19849,20413, -19843,20442,19718,20413,19473,20413,19483,20413,19725,20413, 19,20413, - 12,20413,19337,20413,19687,20413, 9,20460,19475,20413, 9731,20465, - 17,20465, 9,20413,19687,20470, 11,20470, 11,20413, 9,20476, - 8495,20413, 5,20413, 9,20483, 4,20413,19815,20487,19849,20489, -19815,20486,19857,20493, 5,20412, 17,20497, 7,18966,10439,20501, -11087,20501,10665,20501, 4643,20501,11307,20501, 5075,20501,17777,20501, - 2215,20501,18739,20501, 4339,20501,11713,20501, 2221,20501,11037,20501, - 2233,20501,19626,20501,19129,20501, 0,20501, 4,20534,19301,20537, -19317,20537,19463,20537,20009,20537,10036,20501,19843,20547, 8800,20501, - 8714,20501, 5045,20501,11277,20501, 4551,20501,19628,20501,19455,20501, -19393,20501,19723,20501,19333,20501, 305,20501, 8495,20570, 959,20501, -19625,20501, 9731,20576, 17,20576,10603,20501, 9,20583, 4625,20501, - 9,20587,19385,20501, 9,20591, 759,20501, 47,20501,10107,20501, - 241,20599, 265,20598,10196,20501, 11,20501, 8495,20606, 17,20501, -19625,20610, 59,20501,10291,20501, 1011,20617, 15,20501, 1325,20501, - 8495,20501, 10,20624, 10,20625, 305,20624, 11,20624,20629,20633, - 11,20625,20627,20637, 9731,20501,19625,20640, 4,20501, 7,20645, - 483,20647,18967,20649, 0,20644,19301,20653,19317,20653,19463,20653, -20009,20653,20651,20653, 7,20644,19916,20665,20653,20667, 1275,20665, -18967,20670,20653,20673,18967,20665, 1275,20676,20653,20679,10001,20644, -19843,20683, 1011,20645,10047,20645, 5,20501, 9287,20691, 331,20501, - 4,20500, 8495,20697, 4311,20697,10351,20697, 3785,20697, 4329,20697, - 8717,20697,10055,20697, 5,20500, 9195,20713,11277,20713, 5045,20713, - 4321,20713, 9755,20713, 4295,20713,10171,20713, 9317,20713, 3833,20713, - 903,20501, 265,20501,10107,20734, 9195,20501, 241,20739,10001,20501, - 4,20742,19843,20745, 5,20742,18967,20748, 4,20743,20751,20753, -19511,20753,19857,20753, 5,20743, 7,18967, 8810,20762, 8811,20762, - 2,20763, 1,20768,20483,20763, 8495,20773, 8800,20763,20273,20763, - 8495,20763, 11,20780, 8810,20763,20767,20785,10081,20763, 1011,20789, - 1010,20788,20791,20793, 1010,20789, 1011,20788,20797,20799, 566,20763, - 11,20763, 9731,20805, 8495,20805, 8495,20804, 265,20763,20482,20763, - 17,20815, 567,20763, 9195,20819, 9,20763, 8811,20763,20765,20825, - 241,20762, 265,20762, 8165,20831, 1011,20763, 375,20763, 4,20762, -20815,20839, 5,20762,11276,20842, 5044,20842,11277,20842,11276,20843, -20849,20851, 5045,20842, 5044,20843,20855,20857,20773,20843,20470,20843, -20103,20843,20413,20843, 9,20866, 9195,20843,11277,20843,20845,20873, - 5045,20843,20847,20877, 9,20843,20413,20880, 4,20763,20480,20885, - 7,20884,20843,20889, 9366,20885, 1,20885, 3,20894,20842,20896, -20843,20897,20899,20901,20889,20900,20842,20897,20843,20896,20907,20909, -20890,20897,20889,20897,20843,20914, 3,20885, 1,20918,20842,20920, -20843,20921,20923,20925,20889,20924,20842,20921,20843,20920,20931,20933, -20890,20921,20889,20921,20843,20938, 9195,20885, 483,20942,20866,20885, - 8495,20885,20413,20948, 483,20885, 9195,20952,20413,20885, 8495,20956, -20843,20956,20843,20885, 1,20962, 3,20964, 3,20962, 1,20968, - 7,20963,20897,20973,20921,20973,20967,20973,20971,20973,20413,20962, - 5,20763, 7,20985, 17,20985,20413,20989,20413,20984,20839,20993, - 17,20993, 483,20984,20839,20985, 1,21001, 3,21002, 3,21001, - 1,21006, 7,21000,21005,21011,21009,21011,20413,21001,20413,20763, - 5,21019,20885,21021, 9,21021, 5,21018,20839,21027, 17,21027, - 483,20763, 5,21032, 5,18967, 0,21037, 3,21038, 9357,21037, -20742,21037,20761,21045,20187,21037, 8495,21049,20501,21037,10001,21036, -20753,21055,20763,21037, 8495,21059,13947,21036, 17,21063, 256,21037, -20186,21037,20885,21037, 7,21071,20897,21073,20921,21073, 9,21037, - 1275,21079, 9533,21081,21041,21081, 17,21037, 9195,21087, 7971,21087, - 8495,21087, 483,21036, 253,21095, 1471,21095, 53,21095, 1275,21036, - 6,21036,20640,21105,20610,21105,21069,21105, 9731,21105,20501,21112, -20501,21105, 9731,21116, 17,21116, 17,21105,20501,21122, 7,21036, -11276,21126, 5044,21126,11277,21126,11276,21127,21133,21135, 5045,21126, - 5044,21127,21139,21141, 1,21127, 3,21144,18967,21147, 3,21127, - 1,21150,18967,21153,18967,21127,20470,21127,21049,21127,20413,21127, - 9,21162,20103,21127, 9195,21127,11277,21127,21129,21171, 5045,21127, -21131,21175, 9,21127,20413,21178, 6,21037,21149,21183,21155,21183, -20254,21183,19243,21183,19257,21183,18967,21183, 1,21183, 3,21196, -21126,21198,21127,21199,21201,21203,21126,21199,21127,21198,21207,21209, - 3,21183, 1,21212,21126,21214,21127,21215,21217,21219,21126,21215, -21127,21214,21223,21225, 8495,21183,20103,21228,19687,21183,20843,21183, -21166,21183, 11,21183,20501,21239,20103,21183, 8495,21242,21127,21242, -21127,21183,20103,21248,20763,21183, 9731,21253, 17,21253, 7,21037, -19625,21259, 15,21259,20413,21263,20103,21258,21105,21267, 241,21258, -21105,21259,20103,21273,20103,21037, 7,21277,21199,21279,21215,21279, -11277,21279, 5045,21279,21183,21279, 6,21276, 1,21291, 3,21292, -21279,21295, 3,21291, 1,21298,21279,21301, 7,21276,21105,21305, - 241,21037, 483,21309, 7,21308, 4,18967,21183,21315, 0,21314, -20309,21319, 524,21319,20273,21323,20305,21319, 1291,21319,20273,21329, -21081,21319,20323,21319,20387,21319, 11,21319, 483,21338,20273,21341, - 483,21319, 11,21344,20273,21347, 165,21315,17635,21315, 1011,21352, -17642,21315,20413,21315, 6,21359, 9,21315,20352,21315,11277,21365, - 5045,21365,20985,21315, 11,21315,10075,21315, 483,21315, 1347,21315, - 6,21314, 1,21381, 3,21382,21365,21385, 3,21381, 1,21388, -21365,21391,20273,21381, 11,21381, 7,21314, 6,21315, 17,21401, - 7,21315,21384,21404,21390,21404,21385,21405,20273,21411,21407,21411, -21391,21405,20273,21417,21409,21417,21385,21404,21384,21405,21423,21425, -21391,21404,21390,21405,21429,21431,11276,21404, 5044,21404,11276,21405, -11277,21404,21439,21441, 5044,21405, 5045,21404,21445,21447, 0,21405, - 4,21450, 4,21405, 0,21454, 8495,21405, 5045,21405,20273,21461, -21437,21461,11277,21405,20273,21467,21435,21467, 9,21405,20273,21404, -21385,21475,21391,21475,11277,21475, 5045,21475, 265,21405, 483,21405, -18967,21487,21453,21489,21457,21489,21381,21405,20273,21315, 6,21497, - 1,21499, 3,21500, 3,21499, 1,21504, 7,21496,21503,21509, -21507,21509,21385,21509,21391,21509,11277,21509, 5045,21509, 1011,21315, -17635,21522, 6,18967, 2,21526, 11,21529,20103,21527,20690,21527, - 9,21535,21259,21527, 9,21539, 17,21527, 4,21526, 11,21545, - 5,21526,20640,21549,21259,21549,20610,21549, 9731,21549,20501,21556, -20501,21549, 9731,21560, 17,21560, 17,21549,20501,21566, 4,21527, - 15,21571, 5,21527, 482,21575, 2,21575, 6,21578, 6,21575, - 2,21582, 9,21575,20501,21587,20501,21574, 9,21591,20501,21527, - 5,21595, 17,21597, 5,21594, 9,21601, 1, 3,19718,21604, -19719,21604,19402,21605,20962,21604,20973,21613,21248,21604,21272,21604, -21494,21604,20963,21604,21249,21604,21001,21604,21011,21627,21273,21604, -21495,21604,21178,21604,20880,21604,21179,21604,20881,21604,21049,21604, -20773,21604,21361,21604,15753,21605, 803,21649,14387,21605, 375,21653, - 9663,21604, 9177,21604,20351,21604,20485,21604,21360,21604, 990,21604, - 4745,21667,19685,21605,21087,21671,21156,21605,21087,21675,21317,21605, -21291,21604,21279,21681,21499,21604,21509,21685, 996,21604, 4745,21689, -21472,21604,21473,21604, 761,21605, 3419,21697, 6469,21697, 3119,21697, -21048,21604,20772,21604, 973,21604, 955,21708, 4745,21711, 9,21708, - 4745,21715, 4745,21709, 955,21719, 9,21719, 2077,21605, 7,21725, - 14,21724,21727,21729, 6,21725, 15,21724,21733,21735,20350,21604, -20484,21604, 9662,21604, 9176,21604,21380,21604,21104,21604,21126,21604, -21183,21751, 9,21751,20842,21604,20885,21757, 9,21757, 305,21604, -18967,21763, 375,21765, 955,21604, 973,21769, 4805,21771, 973,21768, - 4745,21775,17423,21769, 4745,21769, 713,21604,21404,21604,21381,21785, - 9,21785,20884,21604,21316,21605,21182,21604,20501,21795,21793,21795, -21405,21604,21381,21800, 9,21800,20885,21604,20843,21806,20890,21807, -20889,21807,20843,21812,20973,21807,21073,21807,20413,21807,20843,21807, -21757,21823,20889,21822,21183,21604,21127,21828,21279,21829,21679,21829, -20103,21829,21127,21829,21751,21839,21105,21604,21381,21604,21365,21845, -21405,21844,20413,21845,21475,21845,21405,21845,21785,21855,20273,21855, -21509,21845,20843,21604,20885,21862, 9,21862,21127,21604,21183,21868, -18967,21869,21183,21873, 9,21868, 1199,21605,13923,21604,13935,21881, - 9437,21605, 587,21885, 9439,21887, 1177,21605, 1421,21604, 668,21604, - 1,21895, 5,21896, 5,21895, 1,21900, 117,21605,11759,21605, - 1369,21906, 7971,21909,11760,21605, 7971,21913, 809,21605, 989,21605, - 9929,21605, 1369,21920, 9927,21923, 9930,21605, 9927,21927,19596,21605, - 9,21931,19556,21605,20170,21605,19707,21605, 9,21939,20956,21605, -21791,21943,21242,21605,21795,21947,20773,21605,21707,21951,21049,21605, -21705,21955,21373,21605,20464,21605,19557,21605,20499,21605,20359,21605, - 9181,21605, 9671,21605, 4145,21605, 3801,21605, 4135,21605,10101,21605, -20577,21605,19656,21605,19441,21605,19332,21605,19392,21605,19454,21605, -21059,21605,19440,21605,19657,21605, 4134,21605,10100,21605,20498,21605, -20358,21605,20142,21605, 9,22007,20576,21605,20864,21605, 9,22013, -21116,21605,21166,21605,21183,22019, 9,22019,21560,21605, 9180,21605, - 9670,21605, 3800,21605, 4144,21605,21026,21605,20839,22035,20814,21605, -20839,22039,20992,21605,20839,22043,21359,21605,21845,22047,21647,22047, -21053,21605,21795,22053,20779,21605, 8087,21605, 8091,21605, 8089,21605, -20303,21605, 9,22065,20465,21605,10786,21605,11131,21605, 4696,21605, -11970,21605,19722,21605,19333,21605,19393,21605,19455,21605,20351,21605, -21739,22087,20485,21605,21741,22091, 9663,21605,21743,22095, 9177,21605, -21745,22099,20350,21605,21661,22103,20484,21605,21663,22107, 9662,21605, -21657,22111, 9176,21605,21659,22115,10099,21605, 17,22119, 17,22118, - 4133,21605, 17,22125, 17,22124, 8251,21605, 9,22131, 3807,21605, - 9,22135, 13,21604,18967,22139, 19,21604,20501,22143, 9875,22143, - 12,21604, 8251,22149, 3807,22149,19559,22149,20501,22149, 9875,22149, - 8165,22149, 18,21604, 3799,21605, 17,22165, 17,22164, 4143,21605, - 17,22171, 17,22170, 4283,21605, 9,22177, 4279,21605, 9,22181, - 9669,21605, 17,22185, 17,22184, 9179,21605, 17,22191, 17,22190, - 9673,21605, 9,22197, 9967,21605, 9,22201,19624,21605,20501,22205, - 17,22205,19686,21605,22149,22211,19441,22211,19656,22211,21607,22211, -19631,22211, 9,22220, 9,22211,19631,22224,19559,21605,19385,22228, - 9,22231, 9,22229,19545,21605, 17,22236, 17,22237,10102,21605, - 7971,22243,17053,22243, 629,21605,21117,21605,21561,21605,20867,21605, -20885,22255,21167,21605,21183,22259,21548,21605, 17,22263,20501,22263, -21104,21605,21069,22269,21267,22269,21305,22269,21259,22269,20103,22277, - 17,22269,20501,22269,20838,21605,20985,22285,20842,21605,21865,22289, -21809,22289,21613,22289,21637,22289,21867,22289,20773,22289,20956,22289, -21863,22289,20885,22305, 9,22305,20885,22289,20413,22310,20413,22289, -20885,22314,21126,21605,21871,22319,21831,22319,21617,22319,21635,22319, -21877,22319,21049,22319,21242,22319,21869,22319,21183,22335, 9,22335, -21183,22319,20103,22340,20103,22319,21183,22344,21020,21605,20885,22349, -21278,21605,21183,22353,21052,21605,21829,22357,21127,22357,21358,21605, -21747,22363,21665,22363,21532,21605,20497,21605, 17,22371, 17,22370, -20361,21605, 9,22377,20713,21605, 9,22381,20357,21605, 17,22385, - 17,22384,21048,21605,21643,22391,20772,21605,21645,22395,21509,21605, -21381,22399,21499,22399, 9,22399,21475,21605,21381,22407, 9,22407, -21365,21605,21381,22413, 9,22413,11971,21605, 4697,21605, 8387,21605, - 9,22423,11949,21605, 11,22426, 5,22428, 6,22426, 5,22432, - 5,22426, 6,22436, 6,22437, 7,22426,22441,22443, 7,22427, -22435,22447,22439,22447,22431,22447, 14,22426,22447,22455, 6,22427, - 15,22426,22459,22461, 9,22426, 9,22427, 4669,21605, 11,22468, - 5,22470, 6,22468, 5,22474, 5,22468, 6,22478, 6,22479, - 7,22468,22483,22485, 7,22469,22477,22489,22481,22489,22473,22489, - 14,22468,22489,22497, 6,22469, 15,22468,22501,22503, 9,22468, - 9,22469,12345,21605, 5,22510, 4,22510, 12,22510, 13,22511, -22517,22519, 12,22511, 13,22510,22523,22525, 4,22511,22513,22529, - 5,22511,22515,22533, 5123,21605, 5,22536, 4,22536, 12,22536, - 13,22537,22543,22545, 12,22537, 13,22536,22549,22551, 4,22537, -22539,22555, 5,22537,22541,22559,10697,21605, 9,22562,19385,21605, -19559,22566, 9,22569, 9,22567,19559,22573,19397,21605, 6,22576, - 11,22577, 11,22576,19475,21605,20413,22584, 1406,21605, 1396,21605, - 525,21605, 903,22593, 934,21605, 9,22597, 1290,21605, 903,22601, - 669,21605,21899,22605,21903,22605, 1861,22605, 1887,22605, 4,22605, -17013,22605, 4917,22605,19687,21605,22139,22621,21609,22621, 9,22621, -20103,22620, 9,22629,19625,21605,20501,22632,19384,21605,21087,22637, -20326,22637, 9,22636,20273,22637, 9,22644, 9,22637,20273,22648, -19396,21605, 5,22652, 10,22652,19441,22657, 10,22653,19455,22661, - 11,22652,22661,22665, 11,22653,22657,22669,19474,21605,20413,22673, - 1418,21605, 4,22677, 3755,22677, 1995,22677,17013,22677, 4917,22677, - 12,21605,22139,22689,18967,22688, 18,21605,22143,22695,21252,21605, -21279,21605,21183,22701,21291,22701, 9,22701,20483,21605,20763,22708, -20187,21605,21036,22712,21069,22715,21036,22713,21049,22719,21037,22713, -21037,22712, 9,22713,20353,21605, 5,22729,21315,22729, 33,21605, - 8150,22735,17727,22735, 9,22735, 7971,22740, 7971,22735, 9,22744, -17025,22735, 8165,21605, 30,22751, 181,22751, 9,22751, 25,22756, - 25,22751, 9,22760, 145,22751, 53,21605,17049,22767,10219,21605, - 903,22771, 155,22771,10081,21605, 1369,22776, 7971,22779,17053,22779, - 257,21605, 9,22785, 1171,21605, 4722,22789, 4713,22789, 903,22792, -21315,22789, 903,22789, 4713,22798, 628,21605, 9,22803, 11,21605, - 766,22807, 767,22807,20984,22807,20762,22806,22813,22815,20985,22807, -20762,22807,22140,22807,19718,22807,19725,22807, 586,22806,22809,22829, - 5,22807,20763,22832,22815,22835,20763,22833,22821,22839, 587,22832, -22829,22843, 587,22833, 586,22807,22847,22849, 5515,22807,17043,22807, - 4825,22807,17727,22807, 8150,22807,22139,22807,18967,22862,19396,22806, -19397,22806,19396,22807,22869,22871,19397,22807,22867,22875,22653,22875, -20763,22807, 5,22880,22815,22883,19687,22807, 9,22886, 7971,22807, - 9,22890,19461,22807, 9,22807,19687,22896, 7971,22896,18967,22896, -18967,22807,22139,22904, 9,22904,20103,22905, 9,22911, 1369,22806, - 903,22806, 9,22917, 587,22807, 5,22920,22829,22923,18967,22806, -20326,22927,21087,22927, 9,22926,20273,22927, 9,22934, 9,22927, -20273,22938, 9,22806,18967,22942,20763,22806,22819,22947, 587,22806, -22811,22951, 9,22951, 17,21605,19722,22956,19723,22957,22959,22961, -19723,22956,19722,22957,22965,22967,19396,22956,19396,22957,19397,22956, -22973,22975,19545,22956,20497,22956,20357,22956, 4133,22956,10099,22956, - 3799,22956, 4143,22956, 9179,22956, 9669,22956,19475,22957,21315,22957, -19397,22957,22971,23001, 1369,22956, 1275,22956, 903,23007, 587,22957, - 903,22957, 15,21605,20103,23014,18967,23015,20501,23019, 1369,23014, - 4917,23023,17013,23023, 3755,23023, 1995,23023,18967,23014,20413,23033, - 9,21605,19631,23036,19384,23036,19384,23037,22567,23043,19385,23036, -10697,23036, 4669,23036,11949,23036, 11,23037,23047,23055,22567,23055, -18967,23055,18967,23036, 10,23062, 10,23063, 11,23062,23067,23069, - 11,23063,23065,23073, 11,23036,18967,23076, 7049,21605, 587,23081, - 7051,23083, 7055,23083, 7059,23083,17219,21605, 903,23091, 4663,21605, - 903,23095, 4745,21605, 955,23099, 9,23099, 4569,21605,17423,21605, - 955,23107, 9,23107,14625,21605, 5997,21605, 7,23114, 5,23114, - 6,23119,23117,23121, 6,23118, 6,23114, 5,23126, 7,23115, -23129,23131,23125,23131, 14,23114,23131,23137, 6,23115, 15,23114, -23141,23143,20482,21605,20762,23146,20773,23149,20762,23147,20815,23153, -20839,23147,21399,23147,19683,23147,20763,23147,20843,23163,23149,23163, -20763,23146,20839,23169,23153,23169,20186,21605,21036,23174,21049,23177, -21036,23175,21069,23181, 331,23175, 59,23175, 1325,23175, 265,23175, -20644,21605,20352,21605, 9660,21605, 8386,21605, 59,23199, 331,23199, - 1325,23199, 265,23199,21243,21605,21829,23209,20957,21605,21807,23213, -21272,21605,21631,23217,20962,21605, 9,23221,21248,21605,21625,23225, -21549,21605,20501,23228,21105,21605,20501,23232,20843,21605,21758,23237, -21623,23237,21760,23237,21641,23237,20885,23237,21757,23246,20889,23247, -21757,23237,20885,23252, 9,23252,20103,23236, 9,23259, 9,23237, -21757,23262,20885,23236, 9,23267,21127,21605,21752,23271,21625,23271, -21754,23271,21639,23271,18967,23270,21087,23281,21183,23271,21751,23284, -21751,23271,21183,23288, 9,23288,20103,23270,21183,23295, 9,23295, - 9,23271,21751,23300,21405,21605,21633,23305,21394,23305,21786,23305, -21381,23305,20273,23312,21785,23312,20326,23305,21087,23305,21695,23305, -21037,23305,21036,23304,23325,23327,21036,23305,21037,23304,23331,23333, -21788,23305,21785,23305,21381,23338, 9,23338, 9,23305,20273,23344, -21785,23344,20273,23305,21381,23350, 9,23350,21259,21605,21843,23357, -20885,21605,20763,23360, 5,23363,18967,23362, 6,23360,18967,23368, -18967,23360, 6,23372, 6,23373, 7,23360,23377,23379, 7,23361, -23365,23383, 4,23383,23363,23387,23371,23383,23375,23383,23367,23383, -21526,23360,23383,23397, 6,23361,21527,23360,23401,23403, 9,23361, -20843,23407,21791,23361,20413,23411,20413,23360,21791,23415,20843,23360, - 9,23419,21183,21605,21315,23422,21795,23425,21795,23423,20103,23429, -20103,23422,21795,23433,20763,23422,21249,21605,21617,23439,21001,21605, - 9,23443,21273,21605,21619,23447,21371,21605, 9,23451,21253,21605, - 8,21604,22363,23457,22053,23457,21983,23457,23039,23457,21985,23457, -22077,23457,22075,23457,22465,23457,22507,23457,23053,23457,23051,23457, -20501,23457,23037,23457,19631,23483,11949,23483, 4669,23483,18967,23457, - 10,21604,22870,23493,22869,23493,22867,23493,23041,23493,22583,23493, -21995,23493,22665,23493,21991,23493,19441,23493,22626,23493,21997,23493, -19656,23493,22908,23493,22902,23493,22419,23493,22421,23493,11970,23493, - 4696,23493,21987,23493,23069,23493,21989,23493,23079,23493,22643,23493, -22933,23493,22945,23493,22693,23493,22904,23493, 9,23546,22896,23493, -18967,23550,22621,23493, 9,23554,19396,23493,22807,23558, 8647,23493, -22637,23493, 9,23565,23077,23493,18967,23569,22689,23493,18967,23573, -22927,23493, 9,23577,22943,23493,18967,23581,22807,23493,19396,23584, -19396,23585,18967,23584, 9,23590, 9,23584,18967,23594,18967,23585, - 9,23598, 9,23585,18967,23602,19631,23493, 9,23606,18967,23493, -22896,23610,22807,23610, 9,23614, 9,23610,22807,23618, 9,23493, -11949,23622, 4669,23622,22621,23622,19631,23622,22904,23622,22807,23622, -18967,23634,18967,23622,22807,23638, 4669,23493, 9,23642,11949,23493, - 9,23646, 16,21604,22979,23651,21935,23651,22239,23651,22389,23651, -22375,23651,22001,23651,21999,23651,22005,23651,22003,23651,22123,23651, -22129,23651,22983,23651,22981,23651,22987,23651,22985,23651,22989,23651, -22995,23651,22993,23651,22991,23651,22169,23651,22029,23651,22027,23651, -22175,23651,22031,23651,22189,23651,22195,23651,22033,23651, 7,23651, - 3,23706, 3,23651, 7,23710, 586,23651,22957,23651,19545,23717, -20357,23717,20497,23717,10099,23717, 4133,23717, 3799,23717, 9669,23717, - 9179,23717, 4143,23717,19559,23651,20713,23651,20361,23651, 9967,23651, - 9673,23651, 4283,23651, 3807,23651, 8251,23651, 4279,23651, 14,21604, -23175,23755,23199,23755, 5,23755, 1,23760,22677,23763,23023,23763, - 1,23755, 5,23768,22677,23771,23023,23771,16381,23755,14625,23755, - 4569,23755,13325,23755, 8685,23755,19513,23755, 1369,23755, 17,23755, -20219,23755, 4063,23755,10273,23755,20697,23755, 4137,23755, 8401,23755, - 9955,23755, 3863,23755,19631,21605, 11,23808, 5,23810, 6,23808, - 5,23814, 5,23808, 6,23818, 6,23819, 7,23808,23823,23825, - 7,23809,23817,23829,23821,23829,23813,23829, 14,23808,23829,23837, - 6,23809, 15,23808,23841,23843, 9,23808,23457,23847, 9,23809, -19667,21605, 5,23852, 4,23852, 12,23852, 13,23853,23859,23861, - 12,23853, 13,23852,23865,23867, 4,23853,23855,23871, 5,23853, -23857,23875, 8,21605,23646,23879,23642,23879,23606,23879,23851,23879, -22467,23879,22509,23879,19384,23879,19631,23879,23493,23894,23493,23879, -11949,23898, 4669,23898,19631,23898,11949,23879,23493,23906, 4669,23879, -23493,23910,18967,23879, 11,23914, 11,23915,23493,23919, 11,23879, -18967,23922, 14,21605,18967,23926,20501,23929, 17,23929,18967,23927, -20413,23935, 16,21605,22241,23939,22387,23939,22373,23939,22121,23939, -22127,23939,22167,23939,22173,23939,22187,23939,22193,23939,19545,23939, -10099,23939, 4133,23939, 3799,23939, 4143,23939, 9669,23939, 9179,23939, -20357,23939,20497,23939,19625,23939,21549,23939,21105,23939, 11,21604, -23053,23983,23051,23983,23039,23983,21985,23983,22085,23983, 5,23982, - 6,23995,21983,23983,22077,23983,22075,23983,22081,23983,22083,23983, -22572,23983,23847,23983,22465,23983,22507,23983,22211,23983, 9,24017, -19396,23983,22567,23983, 9,24022, 8165,23983, 9,24027,23037,23983, -11949,24031, 4669,24031,19631,24031,19559,23983, 9,24039, 8251,23983, - 9,24043, 3807,23983, 9,24047, 9875,23983, 9,24051,20501,23983, - 9,24055, 9,23982, 8251,24059, 3807,24059,22211,24059,19559,24059, -20501,24059, 9875,24059, 8165,24059, 9,23983,22567,24074,18967,24074, -18967,23983,21183,24081,23997,24081, 375,24081, 7,24081,23995,24089, - 9,24080, 9,21604,22869,24095,23894,24095,21997,24095,21365,24095, -21475,24095,21509,24095,21405,24094,22047,24095,22357,24095,23919,24095, -21995,24095,22583,24095,23906,24095,23910,24095,21127,24094,22319,24125, -20843,24094,22289,24129,22419,24095,22421,24095,21279,24095, 973,24094, - 4745,24139,19559,24095,20361,24095,20713,24095, 9673,24095, 9967,24095, - 4283,24095, 4279,24095, 8251,24095, 3807,24095, 33,24095, 7971,24161, - 8165,24095, 25,24165, 9875,24095,20501,24095, 4745,24095,17423,24095, -21405,24095,20273,24177,21785,24177,19631,24095,23879,24182, 4669,24095, -23879,24186,11949,24095,23879,24190, 973,24095, 4805,24195,19687,24095, -23493,24199,23879,24095,19631,24202,11949,24202, 4669,24202,20413,24095, - 11,24094, 8251,24213, 3807,24213,22211,24213,19559,24213,20501,24213, - 9875,24213, 8165,24213,21127,24095,21751,24229,20843,24095,21757,24233, - 11,24095,19687,24237,23610,24237,23493,24237,18967,24242, 7971,24237, -18967,24237,23493,24248,18967,24095, 10,24252,24213,24255, 10,24253, -24237,24259, 483,24253, 10,21605,23893,24265,24020,24265,22581,24265, -22669,24265,19455,24265,23917,24265,19333,24265,23073,24265,19393,24265, -23060,24265,24092,24265,23925,24265,24078,24265,23651,24265, 9755,24265, - 9317,24265, 4321,24265, 3833,24265,10171,24265, 4295,24265,22149,24265, -18967,24307,24213,24265,18967,24311,24059,24265,18967,24315,21183,24265, -19396,24265,23983,24320,19559,24321, 922,24265, 1413,24265,19683,24265, -24074,24265,18967,24332,23055,24265,18967,24336,24080,24265, 9,24340, -20839,24265,21399,24265,19385,24265,23879,24349, 9,24349,23983,24265, -19396,24355,19396,24354,18967,24355, 9,24360, 9,24355,18967,24364, -18967,24354, 9,24368, 9,24354,18967,24372,18967,24264,19441,24377, -24213,24377,24059,24377,22149,24377,19656,24377,19631,24377, 9,24388, -23983,24377, 9,24393, 9,24377,19631,24396, 903,24265, 483,24400, - 483,24265, 903,24404,18967,24265,23055,24408,24074,24408,19559,24409, - 9,24415, 9,24408,23983,24418,19559,24419,23983,24408, 9,24424, - 9,24265,24080,24428,18967,24428,19559,24433,23983,24432,23983,24428, -18967,24438,18967,24429,19631,24443, 17,21604,21963,24447,23958,24447, -23972,24447,23974,24447,23960,24447,23962,24447,21979,24447,21977,24447, -21967,24447,21965,24447,23964,24447,23966,24447,23968,24447,23970,24447, -21971,24447,21969,24447,21975,24447,21973,24447,22807,24447,19545,24447, -23939,24486,20357,24447,23939,24490,20497,24447,23939,24494, 9669,24447, -23939,24498, 9179,24447,23939,24502, 3799,24447,23939,24506, 4143,24447, -23939,24510,10099,24447,23939,24514, 4133,24447,23939,24518,23939,24447, -19545,24522,20357,24522,20497,24522,10099,24522, 4133,24522, 3799,24522, - 9669,24522, 9179,24522, 4143,24522, 15,24446, 15,21604,23357,24545, -22713,24545,22423,24545, 8337,24545,20103,24545, 17,24544, 483,24545, - 19,21605,22163,24561,18967,24560, 13,21605,24080,24567,22149,24567, -23983,24567,18967,24572,18967,24567,23983,24576, 113,21605,10385,24581, -23879,24583, 9,24583,11731,21605, 67,24589,23879,24591, 9,24591, - 137,21605,12261,21605, 587,24599,10107,24601,11067,24601,12285,24601, - 1346,21605, 1505,24609, 256,21605, 8495,24613,10107,24613, 1486,21605, - 803,24619, 1504,21605,20029,24623,21103,24623,19781,24623, 973,21605, - 2845,24631, 4812,24631, 955,24631, 4805,24636, 2971,24631, 4814,24631, - 9,24631, 4805,24644, 4805,24631, 955,24648, 9,24648, 341,21605, - 803,24655,17049,24655,20884,21605,21820,24661,21807,24661,20413,24664, -20413,24661,21807,24668,21182,21605,21195,24673,21836,24673,21829,24673, -20103,24678,20103,24673,21829,24682,20984,21605,20839,24687,20413,24689, -20413,24686,20839,24693,21258,21605,23755,24697,21749,24697,21574,21605, - 9,24703,21404,21605,24109,24707,21803,24707,21849,24707,21621,24707, -21693,24707,21805,24707,21801,24707,21381,24721, 9,24721, 1141,21605, -17025,24727, 1447,21605,17025,24731, 253,21605,17049,24735, 1471,21605, -17049,24739,21018,21605, 5,24742,20839,24745, 5,24743,20885,24749, -21276,21605, 7,24753,20413,21605, 6,24756, 4,24759,18967,24760, -18967,24759, 4,24764, 4,24765,21314,24759,21570,24756,21571,24757, -24773,24775, 6,24757,21314,24778,21314,24779,20885,24757,24661,24785, -21571,24756,21570,24757,24789,24791,21315,24757,24783,24795,21381,24757, -20885,24756,21791,24801,19475,24756,20984,24756,20839,24807,21315,24756, -21747,24811,24781,24811,23457,24811, 5,24756,20762,24819,20762,24818, -24763,24819,24767,24819,20839,24819,21399,24819,24771,24819,19683,24819, -20763,24819,20843,24837,24823,24837,20763,24818,24821,24843,20839,24843, - 5,24757,24769,24849,20885,24849,24661,24849,20763,24756, 5,24856, -20839,24859, 5,24857,20885,24863,20103,21605,21183,24867,21127,24869, -24673,24869, 15,24866,21183,24866,21795,24877, 15,24867,19687,24866, - 9,24883,19625,24866,20843,24866, 9,24889,21549,24866,21127,24866, -21183,24895, 9,24895,21105,24866,20763,24866, 5,24903,21527,24866, - 9,24867,19687,24909,20843,24909,21127,24909, 6,24866,21036,24917, - 5,24917,18967,24920,18967,24917, 5,24924,21036,24916, 5,24916, -18967,24930,24881,24917,18967,24916, 5,24936, 7,24866,23755,24941, - 1325,24941, 331,24941, 59,24941, 265,24941, 7,24867,23929,24953, -22205,24953,24919,24953,24923,24953,24927,24953,24929,24953,24933,24953, -24939,24953,24905,24953, 4,24953,24903,24973,22269,24953,22263,24953, - 375,24953,21037,24953,24917,24983, 6,24867, 5,24986,24941,24989, -24901,24987,24893,24987,24887,24987,21037,24866,24987,24999, 7,24999, -20273,21605,21258,25004,21259,25005,25007,25009,21183,25005,21259,25004, -21258,25005,25015,25017, 375,25005, 6,25004, 7,25004, 7,25005, -25023,25027,21315,25027, 6,25005,25025,25033,20501,21605, 7,25036, - 4,25039, 4,25038,20885,25037, 7,25037,18967,25047, 5,25049, - 5,25048, 5,25047,18967,25054, 5,25046,21036,25047,21037,25037, -22269,25063,21105,25063, 16,25036, 10,25037, 803,25037, 903,25037, - 9,25037, 17,25036,19625,25036,21105,25036,21549,25036,21037,25036, -21829,25087,25059,25087,21127,25087,24095,25087,25071,25087, 11,25037, - 4,25036, 7,25100,25051,25101, 5,25036,25041,25107,18967,25106, -25099,25111, 5,25037,25103,25115,25043,25115,25087,25115, 7,25114, -25087,25123,25069,25115, 4,25037,25111,25129,25057,25129,25053,25129, -25061,25129,25079,25129, 9165,21605, 9168,25140, 9169,25141,25143,25145, - 9169,25140, 9168,25141,25149,25151, 8337,21605, 15,25155, 6,25155, - 5,25158, 7,25155, 375,25163, 6,25154,25157,25167, 7,25154, -25161,25171,23755,25171, 59,25171, 331,25171, 1325,25171, 265,25171, - 9617,21605, 9630,25184, 9631,25185,25187,25189, 9629,25185, 9631,25184, - 9630,25185,25195,25197, 375,25185, 6,25185, 7,25185, 6,25184, -25205,25207, 7,25184,25203,25211, 9875,21605, 7,25214, 4,25216, - 4,25217, 9893,25215, 16,25214, 803,25215, 9,25215, 17,25214, - 903,25215, 4,25215,25231,25235, 5,25215,25219,25239,25225,25239, - 4,25214, 7,25244,25239,25247, 5,25214,25221,25251, 843,21605, - 9,25255, 413,21605, 7,25259, 375,25259, 1530,21605, 9,25265, - 1216,21605, 7,25269,21497,21605, 7,25273,21277,21605, 7,25276, -21183,25279, 7,25277,21105,25283,21019,21605, 5,25286,20885,25289, - 5,25287,20839,25293, 265,21605, 7,25297, 7971,25299, 587,21605, - 11,25302, 9,25305, 9,25303, 11,25309, 5,25303,20501,25313, - 9875,25313, 903,21605, 9,25319, 11,25321, 11,25318, 9,25325, - 7,25319, 1141,25329, 33,25329, 1447,25329, 1011,25318, 7,25337, - 1275,21605, 9,25341, 1369,25343, 17,25340, 903,25347, 5,25340, - 1505,25351, 5,25341, 253,25355, 53,25355, 1471,25355, 1369,25340, - 9,25363, 1011,21605, 7,25367, 959,25369, 47,25369, 759,25369, - 903,25366, 7,25377, 1369,21605, 9929,25380, 9927,25383,11759,25380, - 7971,25387,17053,25381,10081,25391, 7,25380, 4,25394, 5,25395, - 7,25398,25381,25401, 0,25398,25403,25405, 4,25395, 0,25395, - 5,25410, 1,25380, 5,25415, 1,25416,25381,25419, 6,25416, -25421,25423, 6,25415, 5,25426, 14,25415, 10,25380, 5,25433, - 0,25434, 0,25433, 5,25438, 16,25380,10081,25380, 7971,25445, -17053,25445, 7971,25381,11759,25451,10081,25451, 17,25380, 11,25380, - 11,25381, 1965,25461, 3195,25461,25437,25461,25441,25461, 5197,25461, -25405,25461,25413,25461, 1,25461, 4579,25461,15899,25461, 15,25380, -23763,25483,23771,25483, 3755,25483, 1995,25483, 0,25483,25461,25493, -25477,25483, 4917,25483,17013,25483, 4,25380, 7,25502,20029,25503, -19781,25503,21103,25503, 5,25380,25409,25513, 803,25513, 4,25381, -20033,25519,25457,25519, 5,25381,25397,25525,25505,25525,25443,25525, -10219,25525, 959,25525, 47,25525, 759,25525, 1275,25380, 9,25541, - 241,21605, 9,25545, 483,25545, 7,25544, 8495,25551,10107,25551, -17571,21605, 7,25557, 4,25558, 4,25559, 16,25557, 17,25557, - 4,25556,25567,25569, 5,25556,25561,25573,25565,25573, 4,25557, - 7,25578,25573,25581, 5,25557,25563,25585,17371,21605,16711,25589, - 7,25589,14315,21605, 5,25594, 6,25596, 6,25597, 14,25594, - 15,25594, 6,25594, 5,25606, 7,25594,25601,25611, 6,25595, -25605,25615, 7,25595,25609,25619,25599,25619,25603,25619,15705,21605, - 767,25627, 483,25629, 4,25627, 483,25633,21527,21605,20103,25636, - 5,25637, 17,25641, 5,25636, 9,25645,21315,21605,21183,25648, -21795,25651,21183,25649,24673,25655,21747,25649,20413,25659,23457,25649, -20413,25663,20413,25648,23457,25667,21747,25667,21037,21605,21829,25673, -20501,25675,21127,25673,20501,25679,21105,25673, 11,25673,20501,25685, - 15,25673,20501,25672,24095,25691,21829,25691,21127,25691,20187,25672, -24095,25673,20501,25701, 6,25673, 7,25673, 6,25672,25707,25709, -20103,25709, 7,25672,21749,25715,23755,25715,25705,25715,20103,25672, - 7,25723,20763,21605,20482,25726,20839,25729,20483,25726,21183,25726, - 4,25727,23147,25737,24819,25737, 5,25727,23383,25743,20956,25743, -20773,25743,24953,25743,20885,25743,20413,25752,20413,25743,20885,25756, - 4,25726,21605,25761, 7,25763,25743,25765,24849,25761,20413,25761, - 5,25726,20839,25773,20413,25775,20413,25772,20839,25779,20413,25726, - 5,25782,20839,25785, 5,25783,20885,25789, 5,21604,25275,25793, -25003,25793,25725,25793,24755,25793,21049,25793,21242,25793,20773,25793, -20956,25793,25699,25793,22725,25793,22391,25793,24682,25793,23209,25793, -25712,25793,25733,25793,22711,25793,22395,25793,24668,25793,23213,25793, -25770,25793,25083,25793,23235,25793,22017,25793,25085,25793,23231,25793, -22025,25793,25087,25793,25691,25793,22357,25793,22047,25793,23455,25793, -15567,25793,12971,25793,13355,25793,13541,25793,22869,25793,22635,25793, -23021,25793,23894,25793,23919,25793,21997,25793,21995,25793,22583,25793, -23906,25793,23910,25793,22419,25793,22421,25793,23034,25793,19656,25793, -19441,25793,11970,25793, 4696,25793,22674,25793,22069,25793,25081,25793, -22011,25793, 9357,25793,25205,25793,25027,25793, 9356,25793,25171,25793, -24941,25793,23199,25793,23175,25793,20606,25793,25593,25793,19396,25793, -11131,25793,21059,25793,23018,25793,20501,25933,20057,25793,22633,25793, -20501,25939,21405,25793, 357,25793, 367,25793, 471,25793, 1249,25793, - 628,25793, 4569,25793,14625,25793, 4545,25793,13325,25793, 8337,25961, - 4549,25793,23229,25793,20501,25967,23233,25793,20501,25971,25706,25793, -20186,25793, 8386,25793, 9083,25793, 9484,25793, 9984,25793,20187,25793, - 8387,25793,19513,25793, 8401,25793,20219,25793, 4137,25793,10273,25793, - 4063,25793, 3863,25793,20697,25793, 9955,25793,20353,25793,25709,25793, -20103,26010,25715,25793,24673,25793,20103,26016,24697,25793,21183,25793, -20103,26022,21259,25793, 4745,25793,17423,25793, 9082,25793,22673,25793, -20413,26034,23033,25793,20413,26038,25551,25793,24613,25793,22249,25793, -20326,25793,21087,25793, 9704,25793,23879,25793,19631,26054,11949,26054, - 4669,26054,11949,25793,23879,26062, 9,26062, 4669,25793,23879,26068, - 9,26068,20805,25793,23015,25793,18967,26076,20501,26079,18967,26077, -20413,26083,19631,25793,23879,26086, 9,26086, 9377,25793, 11,26092, - 341,25793, 241,26097, 8165,25793, 256,25793, 257,25793, 11,25793, - 9195,26106,20501,26106, 587,26106, 9377,26106, 9875,26106,20763,26106, -20804,25793,10219,25793, 587,26123, 53,25793,20501,25793, 10,26128, - 10,26129, 11,26128,26133,26135, 11,26129,26131,26139,20413,25793, -20885,26142,24661,26142,25761,26142,22673,26142,23033,26142,20762,25793, -25761,25793,20413,26156,24661,25793,20413,26160,20885,25793,20413,26164, - 17,25793,20762,26168,20762,26169,20763,26169,26171,26175,20763,26168, -26173,26179, 9,25793,11949,26182, 4669,26182,19631,26182,18967,26182, -20273,26182, 9617,26182,20763,25793, 11,26196,25707,25793, 9875,25793, - 10,26202, 10,26203, 11,26202,26207,26209, 11,26203,26205,26213, - 253,25793, 6,25793,25273,26219,24753,26219,24999,26219,24953,26219, -25005,26219,25723,26219,25707,26219,25185,26219,25163,26219,25589,26219, -24081,26219, 4713,26219,16363,26219, 9195,26219, 4863,26219,13119,26219, - 8757,26219, 4213,26219,23493,26219, 8109,26219, 3933,26219, 4147,26219, - 9335,26219,20103,26219, 8337,26219,20273,26219, 8997,26219,25673,26219, - 241,26219,18967,26219, 11,26279, 11,26219, 587,26219, 8387,26219, -14653,26219,20187,26219, 7,25793, 8717,26293, 3785,26293,25673,26292, -23755,26293,10351,26293, 4311,26293, 4329,26293,10055,26293,20103,26292, - 8337,26292, 8997,26292, 15,26293,18967,26317,18967,26292, 241,26292, - 9195,25793, 11,26324, 1471,25793, 6,25792,23175,26331,25977,26331, -24941,26331,26311,26331,26299,26331,25975,26331,25715,26331,24697,26331, -26315,26331,23199,26331,25171,26331,25979,26331,26033,26331,26313,26331, -16381,26331,26323,26331,26103,26331,13325,26331, 8685,26331,26155,26331, -26321,26331,26293,26331,20103,26375,25673,26375, 8997,26375, 8337,26375, - 241,26375,18967,26375, 17,26331, 1369,26331, 4569,26331,19513,26331, - 4063,26331,10273,26331, 3863,26331,20697,26331, 9955,26331, 4137,26331, -20219,26331, 8401,26331,14625,26331, 7,25792,25987,26415,26266,26415, -26201,26415,26274,26415,26272,26415,25989,26415,25981,26415,26268,26415, -21604,26415,18967,26433,26219,26435, 8997,26415,26219,26438,26105,26415, -26276,26415, 8647,26415,19396,26415,26197,26415,26278,26415,26219,26415, -20103,26454,25673,26454, 8997,26454, 8337,26454, 241,26454,18967,26454, - 8337,26415,26219,26468,20103,26415,26219,26472, 9,26415,18967,26476, - 241,26415, 1,26481,26219,26483,26219,26480,25673,26415,26219,26488, -18967,26415, 9,26492,26219,26492, 587,25793, 11,26498, 1369,25793, -25673,25793,20501,26505, 6,26504, 7,26504,26331,26511, 6,26505, -26511,26515, 7,26505,26509,26519,26219,26519,18967,25793, 9,26524, -23015,26524,20501,26529, 483,26525, 6,26524, 7,26524,26331,26537, - 7,26525,26219,26541, 6,26525, 241,25793, 1,26547, 7,26549, -26331,26551, 7,26548,26219,26555, 7,26547, 1,26558,26219,26561, -26219,26559, 7,26546,26331,26567,20273,25793, 9,26570,14315,25793, - 8997,25793, 7,26576,26331,26579, 7,26577,26219,26583, 9617,25793, - 9,26586, 8337,25793, 7,26590,26331,26593, 483,26591, 9,26591, - 7,26591,26219,26601,20103,25793,21183,26604,24673,26604,25709,26604, - 7,26604,26331,26613, 483,26605, 9,26605, 7,26605,26219,26621, - 4,21604,21955,26625,24877,26625,23433,26625,21947,26625,21951,26625, -24801,26625,23415,26625,21943,26625,22282,26625,22251,26625,22266,26625, -22253,26625,24811,26625,25667,26625,22363,26625,22053,26625,21116,26625, -21560,26625,25735,26625,23437,26625,22699,26625,21253,26625,23930,26625, -22206,26625,24805,26625,23937,26625,22587,26625,23039,26625,23053,26625, -23051,26625,21961,26625,21981,26625,20465,26625,20576,26625,21985,26625, -21983,26625,22077,26625,22075,26625, 9573,26625, 9575,26625,23847,26625, -22465,26625,22507,26625, 3,26625, 7,26712, 9605,26625, 586,26625, - 9599,26625,19474,26625,20413,26723,20186,26625,20805,26625,22423,26625, -22713,26625,22205,26625,20501,26734,19625,26625,20501,26738,19687,26625, -23929,26625,20501,26744,23934,26625,20413,26749,22585,26625,20413,26753, - 8386,26625,23927,26625,18967,26759,20501,26761,18967,26758,20413,26765, -23037,26625,19631,26769,11949,26769, 4669,26769, 1418,26625, 9565,26777, - 669,26625, 9565,26781,22263,26625,20501,26784,22269,26625,20501,26788, -21549,26625,20501,26792,20843,26625,21105,26625,20501,26798,21127,26625, -23423,26625,20103,26805,23357,26625, 7971,26625, 1170,26625,25203,26813, -20501,26625,22269,26816,22263,26816,21105,26816,21549,26816,22205,26816, -23929,26816,19625,26816,20762,26625,26219,26833,23361,26625,20413,26837, - 11,26625, 1,26841,18967,26841, 15,26625,18967,26846,20413,26849, -18967,26847,20501,26853, 1369,26846, 9565,26857, 7,26625, 4,26861, - 3,26860, 4,26860,21605,26867,20103,26860, 8337,26860,18967,26860, -26219,26875, 1011,26860,25203,26879, 6,26625,21604,26882,20763,26883, - 6,26624,24811,26889,22053,26889,22363,26889,25667,26889,20501,26889, -25649,26889,20413,26901,18967,26889, 7,26624,24265,26907,19559,26907, - 9673,26907, 8251,26907, 3807,26907, 4283,26907,20361,26907, 4279,26907, -20713,26907, 9967,26907, 483,26625, 1369,26625, 15,26930, 9565,26933, -25649,26625,20413,26937,18967,26625, 15,26940,20413,26943,23927,26940, -20413,26947, 6,26940,21604,26950, 7,26940,26219,26955, 7,26941, -26953,26959,26885,26959,26331,26959,23755,26959, 6,26941, 1011,26625, - 7,26971,25207,26973,23197,26973, 7,26970,25203,26979,20103,26625, - 7,26982, 8337,26625, 7,26986, 9565,26625, 9617,26625, 6,26992, - 7,26992, 6,26993,26997,26999, 7,26993,26995,27003,20273,26625, - 6,27006, 7,27006, 6,27007,27011,27013, 7,27007,27009,27017, - 7,21604,25987,27021,26266,27021,22732,27021,22733,27021,25087,27021, -25691,27021,22357,27021,22047,27021,26027,27021,25989,27021,26268,27021, -20819,27021,20152,27021, 8374,27021, 8389,27021,20201,27021,20952,27021, - 1,27021, 4,27056, 4,27057, 3,27021, 4,27062, 902,27021, -19559,27021,20361,27021, 9673,27021,20713,27021, 9967,27021, 4283,27021, - 4279,27021, 8251,27021, 3807,27021,26100,27021,26106,27021,26128,27021, -26202,27021, 8647,27021,20326,27021,25239,27021,25115,27021, 8800,27021, -21087,27021, 357,27021, 367,27021, 471,27021, 1249,27021, 8086,27021, -19687,27021, 9704,27021,25742,27021,20885,27021, 483,27122, 1141,27021, - 375,27021,20103,27128, 8337,27128,25673,27021,20501,27135,26219,27021, -20103,27138, 8337,27138, 11,27139, 17,27139, 1447,27021,21127,27021, -20843,27021, 8165,27021,25793,27154, 265,27155, 33,27021, 567,27021, -22729,27021,21315,27164, 11,27021,25793,27169, 8495,27169,25793,27168, - 8495,27168,18967,27169,21037,27169,21497,27021,21277,27021,21276,27021, -21496,27021,20273,27021, 9,27190,21315,27190,20103,27021,26219,27196, - 375,27196,21037,27196,21314,27021,22729,27205,20273,27205,21036,27021, -25129,27211,20103,27211,21183,27021, 9,27021,20273,27218, 9617,27218, -21315,27021,22729,27224,20273,27224,21037,27021,20103,27230,25743,27021, - 25,27021, 7971,27236, 7971,27021, 25,27240, 9617,27021, 9,27244, - 8337,27021,26219,27248, 375,27248, 4,27021,25037,27255,25215,27255, - 3,27254, 1,27254,25727,27255, 483,27255,20691,27255, 9923,27255, -18967,27255,20103,27273,18967,27254,22729,27277,20273,27277, 5,27021, -27061,27283, 1,27283,25727,27282,18967,27283,22729,27291,20273,27291, - 17,27283,18967,27297,18967,27282,25129,27301,20103,27301,25793,27021, - 8165,27306, 11,27306,20501,27306, 9875,27306, 9731,27021, 8495,27021, - 11,27318, 4,27020, 1,27323,27283,27324,27286,27323,27289,27323, -27121,27323,24265,27323,27225,27323,27290,27323,27211,27323,27301,27323, -27283,27323, 1,27344,25727,27345,18967,27344,18967,27345,19559,27323, -18967,27323,27283,27356, 4283,27323, 9673,27323, 8251,27323, 3807,27323, -20361,27323, 9967,27323,20713,27323, 4279,27323, 5,27020,27059,27377, -27263,27377,27235,27377,27264,27377, 8647,27377,19396,27377,27231,27377, -27272,27377,27205,27377,27277,27377,27255,27377, 1,27399,25727,27398, -18967,27398,18967,27399,26219,27377, 9,27377,18967,27410,25727,27377, -27255,27414,18967,27377, 9,27418,27255,27418, 1011,27021,25727,27021, - 5,27426,27323,27429, 5,27427,27255,27433,18967,27021, 7,27437, -21605,27439, 4,27441, 4,27440, 4,27439,21605,27446, 4,27438, - 16,27437, 113,27437,11731,27437, 17,27437, 4,27436,22729,27461, -21605,27460,27459,27465,27377,27461,20273,27461, 5,27436,25129,27473, -27443,27473,27323,27473,20103,27473, 5,27437,25101,27483,23193,27483, - 7,27483,21605,27489,27461,27491,27449,27483,27445,27483,27461,27483, -27255,27483,21315,27483, 4,27437, 7,27504,27473,27505,27283,27505, -21037,27505, 483,27021,20885,27514,20501,27021, 241,27519,25793,27518, - 9875,27021, 241,27525,25793,27524,20413,27021, 6,21604,24811,27533, -25667,27533,22363,27533,22053,27533, 1,27533, 5,27542,22605,27545, -22677,27545,23023,27545,25483,27545,20644,27533,21359,27533,25793,27557, -12345,27533, 5,27561, 4,27560,27563,27565, 4,27561, 5,27560, -27569,27571, 5123,27533, 5,27575, 4,27574,27577,27579, 4,27575, - 5,27574,27583,27585,19667,27533, 5,27589, 4,27588,27591,27593, - 4,27589, 5,27588,27597,27599, 341,27533,21052,27533,25793,27605, -25649,27533,20413,27609,25673,27533,21183,27613,26861,27533, 9,27617, -26293,27533, 9,27621,17219,27533, 903,27625, 4663,27533, 903,27629, -23195,27533,21315,27633,10219,27533, 903,27637, 53,27533,25025,27533, -21315,27643,20103,27533, 9,27647,21314,27533,24795,27651,26142,27651, -20413,27651,25793,27656,25793,27651,20413,27660,21036,27533,25129,27665, -21259,27533,26625,27669, 17,27533,21315,27673,21037,27533,25793,27677, -20501,27679,20501,27676,25793,27683, 8337,27533, 9,27687, 1471,27533, - 5,27533, 6,27693, 587,27695,21605,27697, 1,27692,22605,27701, -22677,27701,23023,27701,25483,27701,27699,27701, 6,27692,25380,27713, -27701,27715, 1369,27713,21605,27718,27701,27721,21605,27713, 1369,27724, -27701,27727, 9,27693,18967,27692,25129,27733, 9935,27693,20645,27693, - 4,27533,20501,27740,26524,27741,20501,27745,25793,27741,18967,27748, -20501,27751,18967,27749,20413,27755,18967,27741,25793,27758,20501,27761, -20501,27759,25793,27765,18967,27740,26142,27769,20413,27769,25793,27772, -25793,27769,20413,27776,26940,27533,26969,27781, 253,27533, 4,27532, -24811,27787,22053,27787,22363,27787,25667,27787,20501,27787,25649,27787, -20413,27799,18967,27787, 5,27532,24941,27805,23175,27805,25715,27805, -24697,27805,25171,27805,23199,27805,26959,27805,16381,27805,13325,27805, - 8685,27805,26293,27805, 17,27805, 1369,27805, 4569,27805,19513,27805, - 4063,27805,10273,27805, 4137,27805,20219,27805, 8401,27805, 3863,27805, -14625,27805,20697,27805, 9955,27805, 241,27533,18967,27533,20486,27857, -20487,27857,20413,27857, 4,27862, 4,27863, 580,27857, 483,27857, - 4,27870, 4,27871, 581,27857, 4,27856,27861,27879,26142,27879, -27877,27879,20413,27879,25793,27886,25793,27879,20413,27890, 5,27856, -25129,27895,27859,27895,27865,27895,27869,27895,27873,27895, 5,27857, -25101,27907,27555,27907,23193,27907,27743,27907,27886,27907,27867,27907, -27875,27907,20413,27907,27879,27922,27879,27907,20413,27926, 4,27857, -20413,27930,27895,27933, 483,27930,27895,27937,27895,27931,20413,27941, - 1369,27533, 5,27945,20501,27533,21037,27949, 4,27948,27907,27953, - 5,27948,18967,27956,21037,27948,25793,27961, 4,27949,27959,27965, -27665,27965,27733,27965,27895,27965, 5,27949,27961,27975, 7,21605, - 1,27979, 2,27981, 5,27983, 5,27982, 1010,27981, 5,27981, - 2,27990, 3,27978, 9,27995, 4311,27979,10351,27979, 4329,27979, - 3785,27979,10055,27979, 8717,27979,26283,27979,26388,27979,23790,27979, -27828,27979,22143,27979,22149,27979,24213,27979,24059,27979, 331,27979, - 8337,28027,20103,28027,21036,27978,21049,28033,21242,28033,21183,28033, -20103,28038,20103,28033,21183,28042,26331,27979,20103,28047, 8337,28047, - 17,28046,21277,27978,21183,28055,27693,27979,18967,28059,25793,27979, -21127,28063,20843,28063,19687,28063, 8337,28063,20103,28063, 7971,28063, - 241,28063, 8495,27979, 241,28079, 8337,27978,26331,28083,27805,28083, - 1325,28083, 331,28083, 59,28083,23755,28083,25793,28083, 265,28083, -21037,27979,27665,28101,28033,28101, 11,28101,21315,27979, 1325,27979, - 8337,28111,20103,28111, 59,27979, 8337,28117,20103,28117,10291,27979, - 483,28123,20273,27978,27533,28127,21315,28129,20103,27978,26331,28133, -27805,28133,23755,28133, 331,28133, 1325,28133, 59,28133,25793,28133, - 265,28133,21105,27979, 11,27979,20103,28153, 8337,28153, 17,27979, -26331,28158, 8337,28159,20103,28159,27805,28158,23755,28158,27731,27979, -27692,27979, 9,28173,23755,27979,20103,28177, 8337,28177, 17,28176, -23983,27979, 9,28185, 15,27979, 3,28189,20273,28189, 9617,28189, -27805,27979,20103,28197, 8337,28197, 17,28196, 241,27978,25793,28205, - 8495,28205,10107,28205, 265,27979,20103,28213, 8337,28213, 4,27978, -27985,28219,21105,28219,21549,28219,19625,28219,28173,28219,18967,28229, - 5,27978,19397,28233,28060,28233,18966,28232,18966,28233, 9,28241, -27323,28233,23651,28233,26907,28233, 9755,28233, 9317,28233, 4321,28233, - 3833,28233,10171,28233, 4295,28233,28101,28233,21183,28233, 1413,28233, - 922,28233,27856,28233,28059,28233,18967,28272,19396,28233,28239,28277, -19683,28233,18967,28232,28235,28283,28242,28283,28241,28283, 9,28288, - 9,28283,28241,28292,27533,28233,18967,28296, 9,28233,18967,28300, -28239,28303,18967,28301,28241,28307,21399,28233,20839,28233, 483,28233, - 903,28314, 903,28233, 483,28318,18967,28233,28059,28322,28239,28323, - 9,28327,27533,28322, 9,28322,28239,28333, 4,27979,27987,28337, -27993,28337,28270,28337,28330,28337,28298,28337,27989,28337, 586,28337, - 3,28337, 7,28352, 7,28337, 3,28356,27856,28337,28233,28360, -21575,28337,28296,28337,18967,28366,27533,28337,28322,28370,18967,28370, -28233,28374,28233,28370,18967,28378,28322,28337,27533,28382,18967,28337, -28296,28386,27533,28386,28233,28390,28233,28386,27533,28394,28233,28337, -27856,28398,27533,28398,18967,28402,18967,28398,27533,28406, 5,27979, -27255,28411, 9287,28411,20885,28411,27533,28410,28219,28419,18967,28421, - 9,28419, 241,28411, 483,28427,28219,28411,27856,28431,27533,28431, -18967,28434,18967,28431,27533,28438,18967,28410,28219,28443, 17,28443, -21036,27979,21069,28449,21267,28449,21305,28449,28219,28449,21259,28449, -20103,28459, 17,28449,21037,27978,26331,28465,21749,28465,27805,28465, -23755,28465,28449,28465,25793,28465,10001,27979, 9,28479,27533,27979, -21496,28483,21277,28483,20885,28483,27931,28483, 9,28483, 9731,28483, -21037,28482,21037,28483,21315,28483,20273,28500,21036,28482,28499,28505, -21036,28483,28497,28509,20273,28483,21315,28512, 4,28483, 5,28483, -28386,28519,28337,28519,18967,28522,18967,28519,28337,28526, 17,28519, - 4,28482,28519,28533, 5,28482,28517,28537,28219,28537,18967,28541, - 9,28537, 1275,27979,20031,28547,20885,28547, 5,28547,18967,27979, -20103,28555, 5,28555,28337,28559, 9,28559, 5,28554,28219,28565, - 17,28565,21527,27979,18967,27978,28519,28573, 7,28573, 4,28576, - 4,28577,28553,28573,21605,28573, 5,28584,28581,28587, 5,28585, -28579,28591, 16,28573,28591,28595, 11,28573,20273,28573, 567,28573, - 5,28572, 4,28573, 7,28606,28591,28609,28483,28607,28547,28607, - 483,28607, 5,28573,21605,28618,28581,28621,20762,21605,20803,28625, - 7,28625, 4,28628,25743,28631, 4,28629,24687,28635,25773,28635, -21035,28625, 16,28625,25743,28643,20999,28625,20985,28625, 483,28649, - 11,28625,20273,28625, 567,28625, 4,28624,20985,28659, 5,28624, -20956,28663,20773,28663,20885,28663,20413,28668,20413,28663,20885,28672, -20482,28625,20839,28677, 4,28625, 7,28680,25743,28683,20843,28681, - 483,28681, 5,28625,21605,28690,28635,28693,20839,28691,20413,28697, -20413,28690,20839,28701,20413,28625, 5,28705,20885,28707, 5,28704, -20839,28711, 5,21605,21183,28715,18967,28716,24673,28719,21194,28715, -24673,28723,28573,28714,28581,28727,20620,28714,20621,28714, 9994,28714, - 9995,28714, 1,28715, 1,28714,26781,28741, 668,28741,26625,28745, -26777,28741, 1419,28741,26625,28751,26857,28741,26933,28741, 2,28741, - 9,28741, 587,28760,26625,28763, 587,28741, 9,28766,26625,28769, -21018,28714,20839,28773,19396,28715,22579,28777,21611,28777,19683,28715, -20413,28783,23490,28715,20413,28787,21526,28714,26816,28791,24953,28791, - 17,28791,20501,28791,26625,28798,26625,28791,20501,28802,20762,28714, -20773,28807,20956,28807,20885,28807,20413,28812,20413,28807,20885,28816, -27787,28715,18967,28821,20501,28823,18967,28820,20413,28827,27802,28715, -20413,28831,21019,28714,20885,28835,27856,28715,20413,28839,27931,28715, -20413,28843,26904,28715,20413,28847,26861,28715,18967,28851,20823,28715, -20645,28715, 9935,28715,21362,28715,21376,28715,27533,28715,18967,28865, -20501,28867,18967,28864,20413,28871, 9994,28715,28737,28875,20822,28715, -28807,28879,20763,28715,28835,28883,28816,28883,20866,28883,21021,28883, -20413,28883,28807,28892,20843,28892,28807,28883,20413,28898, 9,28899, -20843,28883,20413,28904, 9,28882,28807,28909, 803,28715, 11,28913, -27979,28715,18967,28917,20621,28715,28731,28921,20413,28714,21399,28925, -20839,28925,25737,28925,19683,28925,20763,28925,20843,28935,28807,28935, -20763,28924,20839,28941,25737,28715,20413,28945,20839,28715,20413,28949, -20620,28715,28733,28953,21399,28715,20413,28957, 483,28715,21315,28960, -26860,28715,28337,28715, 11,28967,23457,28715,18967,28970,20413,28973, -18967,28971,20501,28977, 9,28715,21315,28980,20763,28981,20763,28980, -28807,28987, 17,28715,11949,28991, 4669,28991,19631,28991,18967,28991, -20273,28991, 9617,28991, 9995,28715,28735,29005, 1275,28714, 1505,29009, -26889,28715,18967,29012,20413,29015,18967,29013,20501,29019, 1369,28714, - 803,29023, 587,28715, 1505,28715, 6,28714,26940,29031,20413,29033, -28965,29031,18967,29037,18967,29030,26816,29041,24953,29041, 17,29041, -20501,29041,26625,29048,26625,29041,20501,29052,26625,29031,18967,29056, -20413,29059,18967,29057,20501,29063,18967,29031,20413,29067,26625,29069, -26625,29066,20413,29073, 7,28714,19397,29077, 0,29077, 2,29080, -28991,29083, 2,29077, 0,29087, 0,29086,28991,29091,28999,29077, - 1,29076,29091,29097,29083,29097,29081,29097, 2,29103, 1,29077, -29089,29107, 2,29107,28852,29077, 0,29076, 2,29115,29107,29116, -29110,29115,29107,29115, 2,29122,18966,29076,18966,29077,29097,29129, -28991,29129, 9,29129,27323,29077,23651,29077,26907,29077, 9755,29077, - 9317,29077, 4321,29077, 3833,29077,10171,29077, 4295,29077,21183,29077, - 1413,29077, 922,29077,26940,29077,28851,29077,18967,29162,19396,29077, -29127,29167,19683,29077,18967,29076,29079,29173,29134,29173,29129,29173, - 9,29178, 9,29173,29129,29182,26625,29077,18967,29186,21399,29077, - 9,29077,18967,29192,29127,29195,18967,29193,29129,29199,20839,29077, - 483,29077, 903,29204, 903,29077, 483,29208,18967,29077,29115,29213, -28851,29212,29127,29213, 9,29219,26625,29212, 9,29212,29127,29225, - 6,28715,29083,29229,29097,29230,29091,29229,29097,29234,29098,29229, -29100,29229,29105,29229,29109,29229,29119,29229,29121,29229,29125,29229, -29111,29229,29115,29253,24907,29229,25639,29229,22369,29229,28600,29229, -28557,29229,28654,29229,22057,29229,29178,29229,29160,29229,19706,29229, -10737,29229,10475,29229,10979,29229,19597,29229,12137,29229,29219,29229, -29215,29229,29130,29229,29222,29229,29129,29229,29173,29294,29097,29294, -29188,29229,29097,29229,29091,29302,29083,29302,29129,29302, 1,29229, - 5,29310, 5,29229, 1,29314,29173,29229,29129,29318,19687,29229, -19631,29322,26940,29229,29077,29326,10697,29229, 8165,29331,19631,29229, -19687,29334,21575,29229,20273,29229,28573,29340,28625,29340,29186,29229, -18967,29346,19384,29229,19559,29351,28625,29229,20273,29354,28573,29229, -20273,29358, 11,29229,18967,29362,19559,29365,18967,29363,19631,29369, - 587,29229,21605,29373,29313,29375,29317,29375,26625,29229,29212,29380, -18967,29380,29077,29384,29077,29380,18967,29388,29212,29229,29127,29393, -29115,29393,26625,29392,18967,29229,29186,29400,29077,29401,29173,29405, -29097,29405,26625,29400,29077,29410, 11,29401,19687,29415, 11,29400, -19559,29419,29077,29400,29127,29423,26625,29422,29115,29423,29077,29229, -26940,29430,26625,29430,18967,29434,18967,29430,29127,29439,26625,29438, -29115,29439,18967,29431,29129,29447, 7,28715,28791,29451,29041,29451, -19625,29451,21549,29451,21105,29451,26625,29450,29031,29463,18967,29465, - 1275,29451, 903,29469,29031,29451,26940,29473,26625,29473,18967,29476, -18967,29473,26625,29480,20763,28714,28635,29485,28855,29485,20839,29485, -20413,29491,20413,29484,20839,29495, 9,29485,20762,28715,28941,29501, -29495,29501,28773,29501,20815,29501,20993,29501,21027,29501,28985,29501, -29498,29501,29485,29501,20413,29519, 9,29518,20985,29501,20413,29525, - 9,29501,29485,29528,21527,28714,29229,29533, 9,29533,26940,28715, -20413,29539, 9731,28715, 7,29543,26625,28715,20762,29547, 6,29547, - 7,29547,29400,29553,29229,29553,18967,29556,18967,29552,18967,29553, -29229,29562, 6,29546,29553,29567, 7,29546,29551,29571,29031,29571, -18967,29575,18967,29546,20413,29579,18967,29547,20501,29583, 6,29582, - 7,29582, 6,29583,29589,29591, 7,29583,29587,29595, 903,28715, - 7,29599,18967,28715,21183,29602,24673,29605,21183,29603,21795,29609, -23457,29602,20413,29613,27787,29602,20413,29617,27533,29602,20413,29621, -20413,29603,27787,29625,26889,29625,26625,29625,27533,29625,23457,29625, -26889,29602,20413,29637,26625,29602,20413,29641,21315,28715,21183,29645, -24673,29645,25709,29645, 7,29645, 483,29644, 9,29644,18967,28714, -27965,29659,27948,29659,26816,29659,26898,29659,27796,29659,24953,29659, -20119,29659,25129,29659,29653,29659,26887,29659,23480,29659,25099,29659, -21605,29659, 6,29684,29645,29687,29451,29659,28625,29691,28573,29691, -20187,29659,28625,29659,19683,29659,20839,29659,21399,29659,28573,29659, -27787,29659,20501,29708,20501,29659,27787,29712,26889,29712,26625,29712, -27533,29712,23457,29712,27533,29659,20501,29724, 17,29659, 6,29658, -26816,29731,24953,29731,29451,29731, 17,29731,20501,29731,26625,29740, -26625,29731,20501,29744, 7,29658,29697,29749,20103,29749,20186,29659, -29731,29755, 6,29659,29752,29759,24941,29759,23175,29759,29645,29759, -28133,29759,21605,29758,29645,29771,20103,29759,29749,29774,29077,29759, -29749,29759,20103,29780, 11,29759,20763,29759,26625,29787, 7,29659, -29731,29791,20103,29793,20103,29790,29731,29797,23457,29659,20501,29800, -26889,29659,20501,29804,20103,29659, 7,29809,29759,29811, 7,29808, -29731,29815,26625,29659,20501,29818, 6,29819, 7,29819, 6,29818, -29825,29827, 7,29818,29823,29831,21036,21605,27965,29835,27951,29835, -27948,29835,26816,29835,27796,29835,26898,29835,27216,29835,28151,29835, -28101,29835,26887,29835,21194,29835,24673,29857,24675,29835,21069,29835, -21267,29835,21305,29835,24953,29835,20119,29835,22723,29835,25129,29835, -25063,29835,23480,29835,21796,29835,21795,29835,20501,29882,25099,29835, -18967,29835,21183,29889,21795,29891,21183,29888,24673,29895,21259,29835, -20103,29899,21183,29835,27021,29902,18967,29902,24673,29907,20187,29835, -21127,29911,28573,29835,28625,29835,19683,29835,20839,29835,21399,29835, -27787,29835,20501,29924,27533,29835,20501,29928,27021,29835,21183,29932, -20501,29835,27787,29936,26889,29936,26625,29936,27533,29936,23457,29936, -21795,29936, 17,29835, 6,29834,26816,29953,21069,29953,21267,29953, -24953,29953,21305,29953,25063,29953,21259,29953,20103,29967, 17,29953, -20501,29953,26625,29972,26625,29953,20501,29976, 7,29834,21242,29981, -29911,29981,21049,29981,21183,29981,20103,29988,20103,29981,21183,29992, -20186,29835,29953,29997,21105,29997, 6,29835,28133,30003,21279,30003, -21166,30003,29992,30003,23175,30003,24941,30003,20103,30003,21127,30016, -29981,30016,21127,30003,20103,30022,29981,30003,20103,30026, 11,30003, -20763,30003,26625,30033, 7,29835,21105,30037,20103,30039,29953,30037, -20103,30043,20103,30036,29953,30047,21105,30047,23457,29835,20501,30052, -26889,29835,20501,30056,26625,29835,20501,30060, 6,30061, 7,30061, - 6,30060,30067,30069, 7,30060,30065,30073,20103,29835, 7,30077, -30003,30079,21183,30079, 7,30076,29953,30085,21105,30085, 4,21605, -26371,30091,26450,30091,26539,30091,26542,30091,27439,30090,27483,30101, -17048,30091,26496,30091,26452,30091,26373,30091,26466,30091,26386,30091, - 586,30091, 803,30117, 586,30090, 767,30121, 1,30091, 15,30124, - 2,30124, 7,30124,26219,30131, 7,30125,23755,30135,26331,30135, -27805,30135,25793,30135, 1,30090,26454,30145,26375,30145,26415,30145, -26219,30150,26219,30145,26415,30154,26292,30145,26331,30159,25793,30145, - 7,30162,26331,30165, 7,30163,26219,30169, 7,30145,25793,30173, -26415,30175,25793,30172,26331,30179, 3,30090, 767,30183,26454,30091, -18967,30186,26375,30091,18967,30190,28159,30091, 8684,30091, 8647,30091, -26154,30091,26331,30201,26534,30091,26541,30205,26536,30091,26331,30209, -26320,30091,26331,30213,19384,30091,20501,30217,19474,30091,20611,30091, - 9989,30091,20762,30090,20985,30227,27436,30091,20501,30231,27507,30231, -27451,30231,27453,30231,26492,30091,26219,30240,26278,30091,26415,30244, -26219,30091,26541,30248,26492,30248,26415,30248,18967,30254,18967,30248, -26415,30258,27021,30091,18967,30263,20413,30265,18967,30262,20501,30269, -21527,30091, 9,30273,21258,30091,21575,30091,20501,30279,20985,30091, -20501,30090,27907,30285,27483,30285, 340,30091, 9,30091, 483,30091, -26292,30091,26331,30297,18967,30299,18967,30296,26331,30303,20413,30091, -20763,30307,25793,30309,26197,30091,26415,30312, 375,30091,24095,30091, -18967,30319,20413,30321,18967,30318,20501,30325,24252,30091,20501,30329, - 15,30091, 1,30332,18967,30332, 11,30091,18967,30339,20413,30341, -18967,30338,20501,30345, 1369,30339, 9565,30349,28741,30349,30129,30349, -27979,30339,19631,30357,11949,30357, 4669,30357,26415,30091, 1,30365, -26219,30367,26197,30364,26278,30364,26219,30364,18967,30374,18967,30364, -26219,30378,18967,30365,26219,30383, 1369,30090,20029,30387,19781,30387, -21103,30387,26541,30091,26219,30394, 6,30090,23646,30399,23642,30399, -23606,30399,24349,30399,26086,30399,26062,30399,26068,30399,24583,30399, -24591,30399,19384,30399,24265,30419,25793,30399,19631,30422,11949,30422, - 4669,30422,11949,30399,23493,30430,25793,30430, 4669,30399,23493,30436, -25793,30436,19631,30399,23493,30442,25793,30442, 11,30399,18967,30448, -24265,30451,18967,30399, 11,30454,24265,30457, 11,30455,23493,30461, -25793,30461,23493,30399,11949,30466, 4669,30466,19631,30466, 7,30090, -21549,30475,21105,30475,19625,30475, 6,30091,26524,30483,26545,30485, -26524,30482,26541,30489, 7,30091,26525,30492,30455,30493,25793,30497, - 2,30493, 0,30500,30422,30503,25793,30503,30399,30506,30399,30503, -25793,30510, 0,30493, 2,30514,30422,30517,25793,30517,30399,30520, -30399,30517,25793,30524, 1,30492,26219,30529,18966,30493,30422,30533, -25793,30533,30399,30536,30399,30533,25793,30540, 8495,30492,21183,30493, - 8495,30493,26524,30492,26331,30551,21037,30492,25793,30492,26331,30557, -18967,30559,18967,30556,26331,30563, 265,30492, 265,30493,25793,30493, -26541,30571,30495,30571,26492,30571,26415,30571,18967,30578,18967,30571, -26415,30582,18967,30492,26219,30587,25793,30586,26331,30591,25793,30587, -26415,30595,20763,30090,26142,30599,24849,30599,25793,30599,20413,30604, -20413,30599,25793,30608,20762,30091,26219,30613,20885,30613,25793,30612, -26331,30619,25793,30613,26415,30623,26524,30091,20501,30627, 6,30626, -26541,30631, 7,30626,26331,30635, 6,30627,26537,30639,30635,30639, - 7,30627,30631,30645,26219,30645, 8495,30091, 7,30650,25793,30091, - 1,30655, 7,30656,26219,30659, 7,30657,26331,30663,20762,30654, -26331,30667,20762,30655,26197,30671,26219,30671, 6,30655, 7,30655, -26197,30679,26278,30679, 1,30678,26219,30685,26219,30679,18967,30688, -18967,30678,26219,30693,18967,30679,26219,30696, 6,30654,30679,30701, - 7,30654,26331,30705,18967,30707,30677,30705,18967,30704,26331,30713, -18967,30654,20501,30717, 6,30716, 7,30716,26331,30723, 6,30717, -30723,30727, 7,30717,30721,30731,26219,30731,18967,30655,20413,30737, - 7,30736,26219,30741, 7,30737,26331,30745, 265,30091, 0,30748, - 6,30751,21605,30752,21605,30751, 6,30756, 6,30757, 7,30748, -30755,30763,30759,30763, 7,30749,30761,30769,18967,30091,26454,30772, -26375,30772,26292,30772,26331,30779, 11,30772,20501,30783, 15,30772, -27021,30772,20501,30789,20501,30773,25793,30793,27021,30793,24095,30793, -26415,30772,26219,30800,20187,30773,25793,30805,26219,30772,26415,30808, -24095,30772,20501,30813, 6,30773,26604,30817,29645,30817,25793,30817, -20103,30822,20103,30817,25793,30826, 7,30773,26331,30831,27805,30831, -23755,30831,25793,30831, 6,30772,30831,30841, 7,30772,26219,30845, -25793,30844,26331,30849,30817,30845,25793,30845,26415,30855,25793,30772, -20501,30859, 6,30858, 7,30858,26331,30865, 6,30859,30865,30869, - 7,30859,30863,30873,26219,30873,20103,30773,26219,30879, 7,30879, -25793,30883,21037,30091, 6,30887, 7,30887, 6,30886,30891,30893, - 7,30886,30889,30897,18967,30090,27530,30901,26142,30901,26009,30901, -26270,30901,28571,30901,26454,30901,26375,30901,24210,30901,27459,30901, -26219,30901,20273,30920,26415,30920,20413,30901,25793,30926,27021,30926, -24095,30926,27021,30901,20413,30934,20985,30901,24095,30901,20413,30940, -20352,30901,25793,30945,26292,30901,26331,30949, 7,30901,25793,30953, -20273,30955,26415,30955,20273,30952,25793,30961,25793,30952,26331,30965, -26415,30901,26219,30968,20273,30901,26219,30972, 7,30972,25793,30977, -25793,30901,20413,30980, 7,30981,26219,30985, 7,30980,26331,30989, -21314,21605,27530,30993,26142,30993,26270,30993,26009,30993,26454,30993, -26375,30993,28571,30993,24795,30993,24799,30993,24210,30993,21850,30993, -21845,30993,20413,31016,27459,30993,18967,30993, 6,31023,29645,31025, -26219,30993,20273,31028,26415,31028,27021,30993,20413,31034,20413,30993, -25793,31038,27021,31038,24095,31038,21845,31038,20985,30993,24095,30993, -20413,31050,26292,30993,26331,31055,20352,30993,25793,31059, 7,30993, -25793,31063,20273,31065,26415,31065,25793,31062,26331,31071,20273,31062, -25793,31075,26415,30993,26219,31078,25793,30993,20413,31082, 7,31083, -26219,31087, 7,31082,26331,31091,20273,30993,26219,31094, 7,31094, -25793,31099, 6,21605,27347,31103,27401,31103,27378,31103,27327,31103, -27380,31103,27329,31103,27263,31103,27377,31116,27285,31103,27059,31103, -27377,31122,27194,31103,27203,31103,27215,31103,27208,31103,27228,31103, -27233,31103,27188,31103,27187,31103,27184,31103,27183,31103,27294,31103, -27275,31103,27305,31103,27280,31103,27481,31103,27470,31103,27341,31103, -27394,31103,27122,31103,27390,31103,27337,31103,26796,31103,26802,31103, -30939,31103,30229,31103,30616,31103,31049,31103,28681,31103,20843,31180, -28686,31103,22287,31103,28661,31103,28649,31103,27502,31103,27513,31103, -25030,31103,24983,31103,30283,31103,25683,31103,21058,31103,29835,31205, -21195,31103,29835,31209,25629,31103,13894,31103,13919,31103,27498,31103, -27509,31103,27930,31103,27895,31223,27857,31103, 4,31226,27895,31229, - 4,31227,27907,31233,27479,31103,27468,31103,27500,31103,27511,31103, -26941,31103, 9457,31103,30118,31103,30185,31103,30123,31103,30105,31103, -26742,31103, 9444,31103, 9435,31103, 713,31260,30751,31102,30763,31265, -30221,31103,19397,31102,28777,31271, 3119,31103, 3027,31103, 3805,31103, - 4820,31103, 6469,31103, 3419,31103,27422,31103,27359,31103,27392,31103, -27339,31103,27343,31103,27396,31103,27404,31103,27351,31103,27352,31103, -27407,31103, 9539,31103,24554,31103,29659,31102,29645,31311,17294,31103, -26843,31103,30335,31103,26845,31103,25689,31103,30337,31103,30787,31103, -24552,31103,25157,31103,24881,31103,28387,31103,28386,31102,31335,31337, -28387,31102,28386,31103,31341,31343,27287,31103,27323,31347,30127,31103, -30117,31103, 803,31352, 3,31103, 0,31356,27277,31103,20273,31360, -27377,31360,27461,31103,20273,31366,27483,31366,27377,31366,27205,31103, -20273,31374,27377,31374,27218,31103,27316,31103,27398,31103,18967,31384, -27345,31103,18967,31388, 413,31103,30292,31103,26986,31103,26982,31103, - 9287,31103,27224,31103,20273,31402,27323,31403,21276,31103,29835,31409, -21496,31103,27021,31412,27021,31413,21277,31103,27021,31418,27021,31419, -21183,31419, 6441,31103, 759,31427, 4403,31103,17075,31103,16329,31103, - 4919,31103,17099,31103, 9362,31103, 5309,31103, 4547,31103,27291,31103, -20273,31446,27323,31447,26810,31103,26990,31103, 777,31103, 824,31103, - 244,31103, 4933,31103, 5297,31103,17077,31103,13019,31103,12705,31103, -13673,31103,18391,31103,18617,31103,14597,31103,27210,31103,27323,31481, -27472,31103,27323,31485,27300,31103,27323,31489,26317,31103,26476,31103, - 9134,31103, 1216,31103,19687,31103,26625,31500,19397,31103,29659,31505, -29835,31505,22655,31505,23622,31103,27410,31103,22139,31103,22163,31103, -24543,31103,24557,31103, 305,31103,21036,31102,26816,31527,25063,31527, -31245,31527,21069,31527,21267,31527,21305,31527,24953,31527,21259,31527, -20103,31543, 17,31527,20501,31527,26625,31548,26625,31527,20501,31552, -26415,31103, 9,31556,26940,31103,29645,31103,29659,31563,27418,31103, -27255,31566,27272,31103,27377,31570,27255,31103,27483,31574,27418,31574, -27377,31574,18967,31580,18967,31574,27377,31584, 8446,31103, 155,31103, -17049,31103, 1369,31593, 8861,31103,26625,31103,21127,31598,20843,31598, -19687,31598, 8337,31598,20103,31598, 7971,31598, 9565,31598,18967,31598, - 9731,31103,27021,31616,30613,31103,20885,31620, 9617,31102,26973,31625, - 8337,31103,24545,31628,26625,31628, 9,31628, 4819,31103, 713,31636, -13857,31103, 713,31640, 4543,31103,21372,31103,21315,31103,27190,31648, -27483,31648,25027,31648,27021,31649,20273,31657,27377,31657,27021,31648, -20273,31662,27323,31663,20273,31648,27021,31668,27021,31669, 11,31648, -21037,31103,29835,31677,20103,31679,20763,31676,29835,31683,20103,31676, -29835,31687, 713,31103,13857,31690, 9435,31690, 4819,31690, 803,31690, - 25,31103, 7971,31103,26625,31702,20884,31103,29659,31707,29835,31707, -20984,31103,28659,31713,28625,31713,30227,31713,22285,31713,17233,31103, - 903,31722,30091,31103, 9,31726,20162,31103,20171,31103,25027,31103, -21315,31734,27190,31103,21315,31738,21127,31103,26625,31742,20843,31103, -26625,31746,28681,31746, 9565,31103,26625,31752, 8997,31103, 9,31756, - 766,31103, 9455,31761,30121,31761, 3803,31761, 759,31761, 9,31103, -27021,31770,30091,31770, 9195,31770, 241,31770,26415,31770, 8997,31770, -27377,31770,23493,31770, 8337,31770,20103,31770, 1011,31103, 903,31792, - 241,31103, 9,31796,27297,31103,27282,31103,27323,31803,18967,31805, -18967,31802,27323,31809, 17,31803,20103,31103,24545,31814,26625,31814, -21037,31814,29835,31821, 9,31814,21037,31815,25793,31827,20273,31103, -27224,31830,27291,31830,27205,31830,27277,31830,27461,31830,21315,31830, -27021,31842,27021,31843,27021,31830,21315,31848,27231,31103,27377,31852, - 803,31103,30117,31856, 713,31856,20885,31103,27021,31862,30613,31862, -23493,31103, 9,31868,24545,31103,20103,31872, 8337,31872, 17,31873, - 11,31103,28715,31881,19631,31883,11949,31883, 4669,31883,21315,31880, - 8451,31103,27377,31103,27059,31894,27263,31894,27205,31894,27231,31894, -27461,31894,27272,31894,27277,31894,27255,31894,18967,31910, 9,31894, -18967,31894,27255,31916, 903,31103,17233,31920, 1011,31920, 257,31103, -27483,31103,21315,31928,27461,31928,27255,31928, 4,31102,23646,31937, -23642,31937,23606,31937,24349,31937,26086,31937,26062,31937,26068,31937, -24583,31937,24591,31937,19384,31937,24265,31957,25793,31937,19631,31960, -11949,31960, 4669,31960,11949,31937,23493,31968,25793,31968, 4669,31937, -23493,31974,25793,31974,19631,31937,23493,31980,25793,31980, 11,31937, -18967,31986,24265,31989,18967,31937, 11,31992,24265,31995, 11,31993, -23493,31999,25793,31999,23493,31937,11949,32004, 4669,32004,19631,32004, - 5,31102,26940,32013,20413,32015,18967,32012,26816,32019,24953,32019, -31245,32019, 17,32019,20501,32019,26625,32028,26625,32019,20501,32032, -26625,32013,18967,32036,20413,32039,18967,32037,20501,32043,18967,32013, -20413,32047,26625,32049,26625,32046,20413,32053, 4,31103,27857,32057, -27879,32059,27857,32056,27895,32063,20763,32056,29835,32067,29659,32067, -28715,32057,29083,32073,29091,32073,19631,32073,11949,32073, 4669,32073, -29129,32073,18967,32073,29077,32087,18967,32056,23147,32091,24819,32091, -28925,32091,28715,32091,20413,32099, 5,31103,27437,32102,19397,32103, -21605,32103,20762,32108,20762,32109, 586,32108, 586,32109,31993,32103, -25793,32119, 2,32103,21605,32123, 0,32122,31960,32127,25793,32127, -31937,32130,31937,32127,25793,32134,32073,32127, 0,32103,21605,32141, - 2,32140,31960,32145,25793,32145,31937,32148,31937,32145,25793,32152, -32073,32145, 586,32140, 586,32141,21605,32102,18966,32102,18966,32103, -21605,32167, 7,32169, 9,32167,31960,32167,25793,32167,31937,32176, -31937,32167,25793,32180,32073,32167, 1,32103,32125,32187,31937,32189, - 3,32103,32143,32193,31937,32195,28573,32103,28625,32103,20843,32201, - 9195,32103,20501,32103,21183,32103,27436,32102,27323,32211, 9377,32103, - 713,32215, 9875,32103,19396,32103,32165,32221, 9,32103,18967,32224, -32165,32227,18967,32225,32167,32231,20763,32102,22285,32235,28659,32235, -28625,32235,32111,32235,30227,32235,30772,32103,20501,32247,27021,32102, -27323,32251,18967,32253,18967,32250,27323,32257, 17,32251, 1369,32103, - 903,32103, 9,32265, 587,32102, 9455,32269,32159,32269,32115,32269, - 3803,32269,30121,32269, 759,32269,25673,32103,20501,32283,20763,32103, -32113,32287,27021,32287,30613,32287, 587,32103,32161,32295,32117,32295, -30117,32295, 713,32295,27021,32103,27483,32305,32105,32305,27418,32305, -27377,32305,18967,32312,18967,32305,27377,32316,31992,32103,32163,32321, -18967,32103,32163,32325,31937,32327,32165,32325, 9,32331, 9,32324, -32165,32335,30091,32324,20501,32339,31937,32324,32163,32343,31937,32103, -18967,32346,32163,32349,30091,32103, 9,32353,18967,32352,20501,32357, -18967,32353,20413,32361,18967,32102,24953,32365,32171,32365,32107,32365, -32172,32365,32167,32365, 9,32374, 9,32365,32167,32378,27021,32364, -27323,32383,27021,32365,27377,32387,21037,31102,26604,32391,31561,32391, -31615,32391,29645,32391,25793,32391,20103,32400,20103,32391,25793,32404, -21314,31103,23147,32409,24819,32409,28925,32409,28715,32409,20413,32417, -21036,31103,25673,32421,20501,32423,25087,32421,25691,32421,22357,32421, -24953,32421,21049,32421,21242,32421,21183,32421,20103,32438,27021,32420, -27323,32443,20103,32421,21183,32446,27021,32421,27377,32451,27436,31103, - 5,32454,27323,32457, 5,32455,27255,32461, 9195,31103, 9,32464, -27021,31103,21496,32468,21277,32468,20885,32468, 9,32468, 9731,32468, -21037,32468,21315,32468,20273,32482,27323,32483,21037,32469,21315,32469, -27205,32491,21036,32468,27323,32495,32489,32495,21036,32469,27231,32501, -32481,32501,20273,32468,21315,32506, 4,32469, 5,32469,27231,32513, -27272,32513,27255,32513,18967,32518,18967,32513,27255,32522, 9,32513, - 4,32468,32513,32529, 5,32468,27323,32533,18967,32535,32511,32533, -18967,32532,27323,32541, 17,32533,18967,32468, 5,32546,27323,32549, - 5,32547,27255,32553, 587,31103,30091,32557, 803,32559, 5,32556, - 9455,32563, 3803,32563,30121,32563, 759,32563, 5,32557, 9435,32573, - 803,32573,18967,31103,32391,32579,26625,32581,27398,32578,27345,32578, -21605,32578, 7,32589, 4,32591, 4,32590, 4,32589, 7,32596, - 16,32589,27282,32578,27323,32603,26625,32578,32391,32607,27377,32578, -27255,32610,20483,32579,25793,32615,27255,32578,27377,32618,21183,32579, -26625,32623, 4,32579,26142,32627,24849,32627,21605,32627, 7,32633, -25793,32627,20413,32636,20413,32627,25793,32640, 5,32579,32593,32645, - 4,32578,24819,32649,23147,32649,28925,32649,28715,32649,20413,32657, - 5,32578,24953,32661,32595,32661,32599,32661,32635,32661,32601,32661, -27021,32660,27323,32673,27021,32661,27377,32677,27021,32578, 5,32680, -27323,32683, 5,32681,27255,32687,20763,31103,18967,32691, 5,32692, - 5,32693,21037,32690,29835,32699,29659,32691,29835,32691,21036,32691, -21037,32691,25793,32709,30091,32691,20885,32713, 4,32691,32697,32717, - 5,32691,18967,32720,28681,32721, 4,32690,32723,32727,32695,32727, -29659,32727,29835,32727,32707,32727, 5,32690,28625,32739,22285,32739, -28659,32739,30227,32739,32709,32739,18967,31102, 5,32750,26816,32753, -24953,32753,31245,32753, 17,32753,26625,32753,20501,32762,20501,32753, -26625,32766, 5,32751, 9,32771,30091,32771,20501,32775,21526,21605, - 5,32778,26816,32781,24953,32781, 17,32781,26625,32781,20501,32788, -20501,32781,26625,32792, 5,32779, 9,32797,30091,32797,20501,32801, -18967,21605,20355,32804,20354,32804,26415,32805,26219,32810,26454,32805, -26375,32805,21127,32805,21183,32818,21248,32805,21273,32805,20986,32805, -20987,32805,28109,32804,28108,32805,32831,32833,31676,32805,31527,32837, -28109,32805,28108,32804,32841,32843,20352,32805, 4,32847,22729,32849, -22731,32847,32809,32847,20486,32805,26292,32805,26331,32859,19622,32804, -19623,32805,32863,32865,19623,32804,19622,32805,32869,32871, 386,32805, - 347,32805,21396,32804,21397,32805,32879,32881,21546,32804,21547,32805, -32885,32887,21397,32804,21396,32805,32891,32893,21547,32804,21546,32805, -32897,32899,20477,32805,27673,32805,20476,32805,27672,32805,21127,32804, -21087,32911,29031,32804,31881,32805,21543,32805,21087,32805,21127,32921, -31880,32805,21542,32805,26219,32805,26415,32928,27283,32805,31103,32933, -20353,32805,32807,32937,20487,32805,21403,32804,21402,32805,32943,32945, -21573,32804,21572,32805,32949,32951,21403,32805,21402,32804,32955,32957, -21573,32805,21572,32804,32961,32963,20985,32804,32829,32967,21401,32804, -32056,32805,29450,32805,29041,32975,28791,32975,29731,32975,29659,32975, -20984,32805,21400,32805,32971,32987,32103,32805, 7,32990,32365,32993, -32057,32805,29451,32805,32915,32999,20984,32804,32827,33003,20985,32805, -31103,33007, 7,33006,33003,33011,21400,32804,21401,32805,33015,33017, -21183,32805,21127,33020,20413,32805, 4,33025, 4,33024, 11,33024, -27533,32805, 17,33032,20273,32805, 7,33037, 7,33036, 15,33037, -25793,32805, 7,33045,26219,33047, 7,33044,26331,33051,21527,32805, - 17,33054,31103,32805, 4,33059,21037,33059,32421,33063,21037,33058, -31527,33067, 4,33058, 11,33058,21037,32805,31103,33075,32391,33077, -31103,33074,31527,33081,28715,32805,29031,33085, 7,33085,29759,33089, -21527,33085,29229,33093, 7,33084,29041,33097,29731,33097,29659,33097, -28791,33097, 15,33085, 580,32805, 1170,32805, 256,32805, 629,32805, - 1413,32805, 922,32805, 581,32805, 1171,32805, 767,32805,31103,33125, - 375,32805, 305,33128, 510,32805, 18,32804, 12,32804,23493,33137, - 1291,32805, 525,32805, 13,32805,22807,33145,33137,33145, 19,32805, -33135,33151, 18,32805, 13,32804, 12,32805,33157,33159, 19,32804, -33155,33163, 16,32805,32421,33167,25743,33167,32365,33167,32661,33167, -27533,33167,21037,33167,31103,33179, 10,32805,19333,33183,33137,33183, -31648,33183,19455,33183,24237,33183,22896,33183,19393,33183,19385,33183, - 9,33199,22807,33183, 9,33202,20413,33183, 9,33183,22807,33208, -21315,33183,31103,33212,31103,33183,21315,33216, 14,32804,32847,33221, -33041,33221,24953,33221,32975,33221,33097,33221,26816,33221,33167,33221, -33111,33221, 17,33221,20501,33221,26625,33240,26625,33221,20501,33244, - 10,32804,22149,33249,19441,33249,24213,33249,24059,33249,19656,33249, - 9,33249,19631,33260,19631,33249, 9,33264,23983,33249, 9,33269, - 524,32805, 1290,32805, 11,32804,21087,33277,20326,33277,33183,33277, - 9,33283, 9,33276,23493,33287,33183,33287,23493,33277, 9,33293, -20273,33277, 9,33296, 9,33277,20273,33300, 9,32804, 11,33304, -23493,33307,33183,33307, 11,33305,24265,33313,33249,33313, 15,32804, -32937,33319,32999,33319,26142,33319,33123,33319,20413,33319,25793,33328, -20273,33319,25793,33319,20413,33334, 11,32805,24567,33339,33157,33339, -24428,33339,20413,33338,31103,33338,33260,33339,33249,33339, 9,33352, -24265,33339, 9,33356, 9,33339,24265,33360,33249,33360, 483,33338, - 9,32805,30090,33368,30090,33369,30091,33368,33373,33375, 483,33368, - 11,33369,20273,33381,30091,33369,33371,33385,20501,33385, 17,32805, -19474,33390,19475,33391,33393,33395,21314,33390,19474,33391,19475,33390, -33401,33403,21314,33391,21315,33390,33407,33409,27533,33390,21527,33390, -33319,33391, 1275,33390,21315,33391,33399,33421, 305,32805, 375,33424, - 1011,32805, 7,33428,33221,33431, 15,33429, 7,33429, 241,32805, - 7,33438, 483,32805, 4,33442, 903,33442, 9,33442, 4,33443, - 11,33442, 903,32805, 9,33455, 483,33454, 1275,32805, 17,33460, - 7,32805,20985,33464,33003,33467,20985,33465,32985,33471,25672,33465, -30772,33465,25673,33465,30773,33465,21036,33465,30090,33465,20273,33464, -33221,33487,25793,33464,26331,33491,28715,33464,29731,33495,29659,33495, -28791,33495,29041,33495,33221,33495,18967,33465, 5,33506,30091,33506, - 5,33507,33485,33513, 17,33507,21605,33465, 4,33518,33513,33521, -21037,33518, 4,33519,33509,33527,33483,33527, 11,33519,25793,33465, -26415,33535, 1011,33464,33221,33539, 241,33464, 8495,33465,32103,33465, -20273,33547,32165,33547,21037,33465,21604,33553,21605,33552,33555,33557, -21605,33553,21604,33552,33561,33563,28715,33465,20273,33567,29533,33567, -30091,33465,18967,33572,33221,33465,20273,33577,23927,33465,20273,33581, -29031,33465,20273,33585,32013,33465,20273,33589, 15,33465,29835,33465, -29659,33465,29077,33597,32102,33465, 4,33465,24687,33603,25773,33603, -21605,33602,33513,33609,31830,33603,32645,33603,29485,33603,22729,33603, -31103,33603,20273,33620,20273,33603,31103,33624, 5,33465,18967,33628, -33527,33631,31103,33628,20103,33629,31103,33637, 5,33464,33519,33641, - 7,33641,21605,33645,33603,33647,33620,33641,33547,33641,33557,33641, -33475,33641,33525,33641,33481,33641,31648,33641,20413,33641,33603,33641, -31103,33666,21315,33641,31103,33670,31103,33641,33603,33674,21315,33674, - 4,33464,33507,33681,25743,33681,33601,33681,32365,33681,32661,33681, -33635,33681,33575,33681,33477,33681,33511,33681,33479,33681,32421,33681, -33221,33681,27533,33681,33629,33681,31103,33709,21037,33681,31103,33713, -31103,33465, 5,33716,33681,33719, 5,33717,33603,33723, 6,32804, -33624,33727,33713,33727,33085,33727,29229,33733,33179,33727,21036,33727, -33681,33739,33167,33739,28714,33727,33567,33745,18967,33727, 5,33749, -33603,33751, 5,33748,33681,33755,33167,33755,20273,33727,33603,33760, -33603,33727,20273,33764,29451,33727, 17,33727, 5,33726,26816,33773, -33681,33773,24953,33773,33487,33773,33041,33773,33495,33773,33097,33773, -32847,33773,32975,33773,33167,33773,33111,33773,33539,33773,33431,33773, - 17,33773,33465,33773,20273,33803,26625,33773,20501,33806,20501,33773, -26625,33810, 5,33727,33603,33815,18967,33814,33681,33819,33167,33819, - 9,33815,33465,33815,20273,33827,30091,33815,20501,33831,33465,33727, -18967,33834, 4,33837, 4,33836,21315,33834,21314,33834, 4,33835, -33843,33847, 5,33835,33841,33851,33845,33851, 4,33834,18967,33856, -33851,33859,33851,33857, 5,33834,33839,33865,33847,33865, 5,32805, -27953,33871,27743,33871,27555,33871, 2,33870, 0,33870, 3,33870, - 1,33870,33609,33871,33521,33871,30285,33871,33485,33871,32717,33871, -25101,33871,33027,33871,33061,33871,23193,33871,33593,33871,33451,33871, -20413,33871,20885,33871,33603,33871,27533,33913,23015,33871,20501,33917, -27741,33871,20501,33921, 9,33871,30492,33871, 6,33871,33879,33929, -33881,33929,20273,33929, 7,33871,33883,33937,33885,33937,25793,33937, -32805,33936, 4,33945,21605,33937,33947,33949, 5,33949,33945,33953, -33603,33949,30091,33936,21527,33937,27533,33937,21315,33963, 7,33870, -31648,33967,20413,33967,31103,33967,21315,33972,21315,33967,31103,33976, -21315,33871,21605,33981,33929,33983,30091,33871,20501,33987, 6,33986, - 7,33986, 6,33987,33993,33995, 7,33987,33991,33999, 4,32804, -27530,34003,26142,34003,26270,34003,26009,34003,33879,34003,33929,34012, -33881,34003,33929,34016,33930,34003,33932,34003,33939,34003,33941,34003, -33506,34003,33681,34029,33683,34003,33934,34003,33943,34003,26454,34003, -26375,34003,33769,34003,32937,34003,32999,34003,33664,34003,32941,34003, -33908,34003,32997,34003,28571,34003,33970,34003,33961,34003,18967,34003, -33465,34062,33681,34065,33465,34063,33641,34069,33206,34003,33123,34003, -33121,34003,24210,34003,33413,34003,33415,34003,32903,34003,32909,34003, -33771,34003,32917,34003,32927,34003,33275,34003,33143,34003,27459,34003, -33419,34003,33463,34003,33035,34003,33057,34003,33517,34003,26219,34003, -20273,34110,26415,34110,24265,34003,28233,34003,29077,34003,33183,34003, -20413,34122,33641,34003,20413,34126,33967,34003,20413,34130,33391,34003, -27533,34135,20413,34003,25793,34138,27021,34138,33641,34138,33871,34138, -33967,34138,33183,34138,24095,34138,27021,34003,20413,34154,33929,34003, -33879,34158,33881,34158,20273,34158,20985,34003,31103,34167, 11,34003, -21605,34171,33465,34003,18967,34174,33681,34177,24095,34003,20413,34180, -26292,34003,26331,34185,20352,34003,25793,34189,33936,34003,33883,34193, -33885,34193,25793,34193, 7,34003,25793,34201,20273,34203,26415,34203, -33871,34201,33879,34209,33881,34209,20273,34209,25793,34200,26331,34217, -20273,34200,25793,34221,33871,34200,33883,34225,33885,34225,25793,34225, -26415,34003,26219,34232,20273,34003,26219,34236,33929,34236, 7,34236, -25793,34243,25793,34003,20413,34246, 7,34247,26219,34251, 7,34246, -26331,34255,33871,34003,18967,34258, 6,34261, 6,34260,21605,34259, -33929,34267,21527,34258,31103,34259,21526,34258,20413,34258, 6,34259, -34271,34279, 7,34259,34265,34283,34275,34283, 6,34258,34267,34289, -18967,34288,34283,34293,34283,34289, 7,34258,33883,34299,33885,34299, -34263,34299,34279,34299,25793,34299, 4,32805, 2,34311, 7,34313, -27669,34311,23357,34311,32468,34311,28483,34311,27978,34311,31746,34311, -31742,34311,31500,34311,20413,34310,23014,34311,31103,34310,21605,34311, - 7,34338, 7,34339,33773,34343,33221,34343, 15,34338,27021,34311, -31103,34350,28411,34311,33629,34311,20413,34357, 483,34310,31103,34311, -27021,34362,20843,34362,21127,34362,19687,34362,19687,34311,31103,34372, -20843,34311,31103,34376,21127,34311,31103,34380, 15,34311,21605,34384, - 375,34311,33727,34311, 9,34391, 7,34311,21605,34394,25793,34395, - 265,34395,31103,34395, 7,34310,33755,34405,33819,34405,33773,34405, -33739,34405,25743,34405,32661,34405,32421,34405,32365,34405,33221,34405, -27533,34405,21037,34405,33727,34427,31103,34427,21037,34311,33929,34433, -26219,34433, 7,34433,25793,34439,28715,34311,20413,34443, 5,32804, -27965,34447,27948,34447,26816,34447,27796,34447,26898,34447,20353,34447, -29451,34447,32847,34447,33487,34447,33041,34447,32975,34447,33495,34447, -33097,34447,34343,34447,34315,34447,33527,34447,33518,34447,33641,34481, -33643,34447,24953,34447,20119,34447,33706,34447,34362,34447,32727,34447, -25129,34447,34333,34447,33029,34447,34337,34447,33071,34447,32691,34447, -34424,34447,34403,34447,32067,34447,31707,34447,26887,34447,32857,34447, -32973,34447,21605,34447,33465,34522,33641,34525,33465,34523,33681,34529, -33176,34447,33111,34447,33109,34447,31505,34447,23480,34447,33347,34447, -33349,34447,32905,34447,32907,34447,32919,34447,32925,34447,33273,34447, -33141,34447,25099,34447,33539,34447,34361,34447,33445,34447,33431,34447, -33367,34447,33453,34447,33031,34447,33073,34447,33533,34447,20187,34447, -19683,34447,20839,34447,21399,34447,33167,34447,27533,34586,33681,34447, -27533,34590,34405,34447,27533,34594,28625,34447,28573,34447,33339,34447, -20413,34603, 1171,34447,27787,34447,20501,34608,27533,34447,20501,34612, -33681,34612,34405,34612,33167,34612,20501,34447,27787,34622,26889,34622, -26625,34622,27533,34622,23457,34622,34395,34447, 17,34447,33465,34447, -29077,34639,20273,34639,21605,34638,33641,34645,28233,34639,24265,34639, - 11,34639, 6,34446,26816,34655,34405,34655,33041,34655,33097,34655, -34343,34655,33681,34655,32847,34655,33487,34655,32975,34655,33495,34655, -24953,34655,33167,34655,33111,34655,33539,34655,33431,34655, 17,34655, -33465,34655,20273,34689,20501,34655,26625,34692,26625,34655,20501,34696, - 7,34446,34635,34701,34579,34701,34311,34701,20103,34701,20186,34447, -34655,34711,34394,34447,34655,34715,31103,34447,34311,34718, 6,34447, -34706,34723,34395,34723,33039,34723,33089,34723,34397,34723,34341,34723, -20273,34723,34708,34723,23175,34723,24941,34723,34325,34723,28133,34723, -33437,34723,20103,34723,34701,34750,34701,34723,34311,34754,20103,34754, - 11,34723,34311,34723,34701,34762,20763,34723,26625,34767, 7,34447, -21605,34771,34311,34773,34655,34771,34311,34777,20103,34777,20103,34770, -34655,34783,34311,34770,34655,34787,23457,34447,20501,34790,26889,34447, -20501,34794,20103,34447, 7,34799,34723,34801, 7,34798,34655,34805, -26625,34447,20501,34808, 6,34809, 7,34809, 6,34808,34815,34817, - 7,34808,34813,34821,34311,34447,21605,34824,18967,34825, 6,34828, - 6,34829,31103,34824,21527,34825,21526,34825,20413,34825, 6,34825, -18967,34842,34827,34843, 7,34825,34723,34849,25793,34849,34833,34849, - 6,34824,34849,34857,34837,34857, 7,34824,34655,34863,34845,34863, -34831,34863,34843,34863,34839,34863, 6,32805,34236,34875,34120,34875, -34433,34875,20962,34875,21001,34875,34118,34875,34355,34875,25648,34875, -21314,34874,34891,34893,25649,34875,33087,34875,21314,34875,34116,34875, -23017,34875,34335,34875,21937,34875,34170,34875,34173,34875,21959,34875, -21315,34874,34897,34917,34385,34875,34387,34875,24875,34875,33332,34875, -33435,34875,33043,34875,33107,34875,34349,34875,21605,34875,21315,34936, -34893,34939,21315,34937,34901,34943,20273,34875,34003,34946,33319,34946, -20885,34875,20843,34952,21315,34875,21605,34956,34893,34959,19475,34875, -26625,34963,24265,34875,34003,34966,29077,34875,34003,34970,28233,34875, -34003,34974,20843,34875,20885,34978, 11,34875,34003,34982,33319,34875, -20273,34986,34003,34875,29077,34990,20273,34990,28233,34990,24265,34990, - 11,34990,30993,34875,30901,34875,20984,34875,20839,35007, 5,34875, -20763,35011,20843,35013,20763,35010,20839,35017,20763,34875, 5,35020, -20839,35023, 5,35021,20885,35027, 7,32804,34736,35031,34459,35031, -34461,35031,29691,35031,29340,35031,28714,35031,33603,35043,21605,35031, - 5,35047,33681,35049,34405,35049,33167,35049, 5,35046,33603,35057, -34607,35031,34637,35031,33924,35031,34447,35031, 11,35031,32103,35031, -29835,35031,29659,35031,20273,35031,34723,35076,29229,35076,35011,35031, -34723,35031,20273,35084, 567,35031,29229,35031,20273,35090, 9,35031, -33871,35094,33871,35031, 9,35098, 4,35030, 5,35030,35083,35105, -34875,35105,35010,35031,35103,35111, 4,35031,35108,35115, 7,35114, -35049,35119,35105,35115,34875,35122,34875,35115,35105,35126, 483,35115, - 5,35031,21605,35132,33603,35135,35103,35133,34875,35139,34875,35132, -35103,35143,34875,35031,18967,35147, 4,35148, 4,35149,21315,35147, -21314,35147, 4,35147,18967,35158, 5,35147,35115,35163,35153,35163, - 4,35146,35163,35169,35155,35169, 5,35146,35103,35175,35161,35175, -35151,35175,35159,35175,35157,35175, 0, 4,14087,35187,14103,35188, - 4983,35187, 5001,35192,14104,35187, 5002,35187,14088,35187,14091,35201, - 4984,35187, 4987,35205,14093,35187, 4989,35187,28758,35187,29229,35213, -28741,35187, 2,35216,29229,35219,20501,35186,19463,35223,19317,35223, -19301,35223,20009,35223, 53,35186,19463,35233,20009,35233,19317,35233, -19053,35187, 989,35241, 1201,35187,18967,35245, 1203,35247,17673,35186, -17685,35251,21405,35186,21489,35255,19513,35186,19463,35259,20009,35259, -19317,35259,10157,35187, 17,35267,10159,35269,20343,35187,18967,35273, -20345,35275, 1179,35187, 527,35186,19301,35281,19916,35186, 4,35285, - 7,35286, 7,35285, 4,35290, 16,35285,19069,35186,19301,35297, - 1290,35186, 0,35301, 2,35302, 2,35301, 0,35306,18966,35301, -21530,35187,20501,35313, 1489,35187,16859,35187, 11,35318, 9875,35321, -21529,35187, 11,35324,20501,35327, 147,35187,16860,35187, 9875,35333, - 987,35187, 8069,35187, 11,35338, 8067,35341, 8070,35187, 8067,35345, -27519,35187,27525,35187,26322,35187,26566,35187,26102,35187,26276,35187, -26105,35187,33464,35187,29600,35187,32295,35187,31856,35187,25636,35187, -29229,35371, 9,35371,28555,35187,29229,35377, 9,35377,19301,35187, -20501,35383, 527,35383,19069,35383, 4266,35187, 8056,35187, 8147,35187, -20739,35187, 9997,35187, 8784,35187, 8622,35187, 8824,35187, 8702,35187, - 8697,35187, 8676,35187, 8635,35187,20828,35187,19772,35187,19890,35187, -19774,35187,19894,35187,19382,35187,19458,35187,32557,35187, 803,35429, -19463,35187,20501,35433, 53,35433,19513,35433,20009,35187, 53,35441, -20501,35441,19513,35441,19317,35187,20501,35449, 53,35449,19513,35449, -19914,35187,21066,35187,20575,35187,21312,35187,21270,35187, 694,35187, - 9377,35467,16920,35187, 9,35471,17621,35187, 9,35475, 4213,35187, - 375,35478, 8757,35187, 375,35482, 9530,35187, 9875,35487,16091,35487, -20501,35487,19751,35187, 53,35495, 253,35495, 117,35495, 71,35495, - 1471,35495, 1397,35187, 9592,35187,16514,35187,19380,35187,13836,35187, -20595,35187, 9911,35187, 9983,35187, 9905,35187,17566,35187,16816,35187, -17910,35187,18880,35187,14103,35187,14087,35532, 5001,35187, 4983,35536, -20597,35187,26219,35187, 241,35542, 587,35543, 8647,35187, 241,35548, - 587,35549,14073,35187, 586,35554,14091,35557, 586,35555,14103,35561, - 4971,35187, 586,35564, 4987,35567, 586,35565, 5001,35571, 1291,35187, -35305,35575,35309,35575, 1871,35575, 1889,35575, 3,35575,19667,35575, -12345,35575, 5123,35575,19067,35575,35311,35575,18967,35575, 1297,35597, -35301,35597,19917,35187,35289,35603,35293,35603,19939,35603,19945,35603, - 6,35603,19947,35603,35295,35603, 17,35603,19931,35619,35285,35619, - 1108,35187, 11,35625,22806,35187, 9,35629, 524,35187, 3,35633, - 3477,35633, 2007,35633,19051,35633,19667,35633,12345,35633, 5123,35633, -18967,35633, 555,35649, 713,35187, 1325,35187,17455,35655,10001,35187, - 1505,35659, 9513,35187, 11,35662, 9875,35665,16091,35665,20501,35665, -19396,35187, 483,35672,17455,35187,13737,35676, 803,35187,31103,35680, -31103,35187, 803,35684, 113,35187, 375,35187, 587,35691, 9195,35693, - 4213,35690, 7971,35690, 8757,35690, 587,35690, 9377,35703, 9565,35690, -18967,35690,19892,35187, 9,35710, 510,35187,18967,35714, 587,35187, - 375,35718, 9377,35721, 9377,35719, 375,35725, 483,35187,19396,35728, - 587,35729, 11,35728, 5123,35735,12345,35735, 3477,35735, 2007,35735, -19667,35735,19051,35735,18967,35735, 555,35749,18967,35728, 9,35752, - 9,35728,18967,35756, 1275,35187,16833,35760, 9,35763, 903,35761, - 9,35761,21575,35187,18967,35771,21577,35773,21581,35773,21585,35773, - 6685,35187, 7519,35187, 17,35783, 7521,35785, 7525,35785, 7529,35785, -21258,35187, 241,35792,16722,35187,32103,35187, 9,35799,10310,35187, - 8684,35187, 241,35804, 331,35805,26292,35187, 241,35810, 482,35186, - 2,35815, 0,35816,35633,35819,35735,35819, 0,35815, 2,35824, -35633,35827,35735,35827,35749,35815,35649,35815,18966,35815,35735,35837, -35633,35837, 1368,35186,25793,35843, 8495,35843,23755,35843,10055,35843, - 4329,35843, 4311,35843,26331,35843,27805,35843, 3785,35843, 8717,35843, -10351,35843, 586,35186,31761,35867,32563,35867,32269,35867, 7,35867, - 4,35874, 4,35867, 7,35878, 16,35867, 767,35867,31103,35885, - 482,35187, 587,35889, 1274,35187, 587,35186, 9262,35895, 375,35895, - 9195,35898, 7,35895, 265,35903, 9195,35905, 9195,35895, 375,35908, - 483,35895, 483,35186, 1369,35186,19463,35917,19301,35917,20009,35917, -19317,35917, 1368,35187, 7,35927, 586,35187,14073,35930,14091,35933, - 4971,35930, 4987,35937,31856,35931,32295,35931, 7971,35931,14073,35931, -14087,35947, 4971,35931, 4983,35951,31103,35931, 803,35954, 803,35931, -31103,35958, 483,35931, 1531,35187,13737,35187, 1487,35966,17455,35966, -16833,35187, 1196,35972, 1196,35973, 1197,35972,35977,35979, 1197,35973, -35975,35983, 1275,35972, 9,35987, 767,35187,31103,35991, 1487,35187, -13737,35994,16937,35187, 17,35999, 9377,36001,17573,36001,16947,36001, - 1347,35187,18967,36009, 555,36011, 251,36011, 1365,36011, 1351,36011, - 21,36011,20762,35187, 241,36022, 256,35187,25793,36026,25793,36027, - 8495,36026, 8495,36027,18967,36026,21037,36026, 972,35187, 9377,36041, - 629,35187,18967,36044, 340,35187, 9377,36049,27978,35187,28353,36053, -30003,36053,29759,36053,34723,36053,21183,36053, 2,36053,28337,36065, -28189,36065,28191,36053, 959,36053, 759,36053, 47,36053, 66,35187, - 89,35187, 7,36080, 973,35187,35895,36085,21527,35187,21605,36088, -29229,36091, 9,36091, 145,35187, 165,35187, 305,35187, 25,35187, -27533,35187, 1505,36105, 331,35187,17455,36109, 59,35187,17455,36113, -29599,35187, 7,36116,26546,35187, 7,36120, 8812,35187, 7,36124, -10291,35187, 3,36129, 3,36128, 9565,35187, 375,36134, 8495,35187, - 256,36138, 7,36139, 375,36143, 7,36138, 241,36146, 331,36147, - 241,36138, 7,36152, 7971,35187, 375,36156,25793,35187, 256,36160, - 7,36160, 241,36164, 241,36160, 7,36168,32805,35187, 7,36172, -19888,35187, 7,36176,18967,35187, 256,36180, 629,36180, 510,36180, - 375,36180, 483,36180, 9,36190, 9,36180, 483,36194, 7,36180, - 241,36198, 7,36181,25793,36203, 8495,36203, 241,36180, 7,36208, - 241,35187,26292,36212,26219,36212, 8684,36212, 8647,36212,20762,36212, -21258,36212, 7,36212,25793,36226,25793,36227, 8495,36226, 8495,36227, -18967,36226,21037,36226,25793,36212, 7,36240, 8495,36212, 7,36244, -18967,36212, 7,36248,21037,36212, 7,36252, 9,35187,19892,36256, - 1011,36256, 11,36261,18967,36256, 483,36264, 483,36256,18967,36268, - 903,35187, 7,36272, 9377,36275,19913,35187, 6,36279, 7,36279, - 6,36278,36283,36285, 7,36278,36281,36289, 15,35187,25381,36293, - 483,36293, 2,36293,28189,36299, 1011,35187,16710,36303,16711,36303, -16710,36302,36307,36309, 0,36303, 6,36312,16711,36302,36305,36317, - 9,36302, 11,36321, 1275,36302,36315,36325, 11,36303, 9,36329, - 6,36302, 3,36332, 6,36303, 0,36336,36325,36339, 7,36303, -25793,36343, 8495,36343,21605,35187,21037,36348,21105,36348,21527,36348, -29229,36355, 9,36355,21549,36348,19625,36348,21526,36348, 5,36364, - 922,36349, 918,36349, 1505,36349, 1419,36349, 668,36349, 483,36349, - 903,36378, 587,36349, 9,36382, 9,36349, 903,36386, 11,36387, - 587,36386, 15,36348, 11,36348, 9,36397, 6,36348,21036,36400, - 5,36400,18967,36404,18967,36400, 5,36408, 7,36348,30003,36413, -29759,36413,34723,36413,21183,36413, 959,36413, 47,36413, 759,36413, - 6,36349,36353,36429,36361,36429,36351,36429,36363,36429, 7,36349, -36403,36439,31527,36439,22269,36439,28791,36439,22263,36439,32781,36439, -36367,36439,21105,36439,21549,36439,29953,36439,29731,36439,34655,36439, -33773,36439,29835,36439,29659,36439,34447,36439,32753,36439,32019,36439, -29041,36439,23929,36439,22205,36439,19625,36439,33221,36439,36407,36439, -36411,36439,18967,36348, 5,36490, 6,36493,36413,36495, 6,36492, -36439,36499,36439,36493, 14,36490,36439,36505, 6,36491,36395,36509, - 6,36490, 5,36512,36439,36515, 903,36349, 7,36519, 9,36518, - 483,36518, 265,35187,17455,36527, 5843,36527, 483,36527, 587,36527, - 9,36527, 7,36526, 9377,36539, 7,36527, 11,35187, 8069,36544, - 8067,36547,16859,36544, 9875,36551,21529,36544,20501,36555,16091,36545, - 9513,36559, 7,36544, 2,36563, 7,36564,36545,36567, 1,36564, -36569,36571, 1,36563, 2,36574, 0,36544, 2,36579, 0,36580, -36545,36583, 6,36580,36585,36587, 6,36579, 2,36590, 482,36579, - 1368,36544, 2,36597, 1,36598, 1,36597, 2,36602,18966,36544, - 2,36607, 6,36608, 6,36607, 2,36612, 482,36607, 9513,36544, -20501,36619, 9875,36619,16091,36619,20501,36545,21529,36627, 9513,36627, - 9875,36545,16859,36633, 9513,36633, 1369,36545, 1989,36639, 3587,36639, -36601,36639,36605,36639, 5303,36639,36571,36639,36577,36639, 0,36639, - 4897,36639,17041,36639,18967,36545,20281,36661,20345,36661,36611,36661, -36615,36661,36587,36661,36593,36661, 7,36661,20285,36661,36595,36661, -36617,36661, 483,36661,20273,36683,36579,36683,36607,36683,21605,36544, - 9,36691, 483,36544,35819,36695,35827,36695, 3477,36695, 2007,36695, - 1,36695,36639,36705,36655,36695,19051,36695,19667,36695, 5123,36695, -12345,36695,35837,36695,18967,36695, 555,36721,35815,36721, 3,36544, - 3,36545, 375,36729,21308,35187, 7,36732,16481,35187, 7,36736, -21037,35187, 256,36740, 7,36740, 241,36744, 241,36740, 7,36748, -16531,35187, 7,36752, 1011,36753, 7,36757,18797,35187, 7,36760, -17827,35187, 7,36764,16783,35187, 7,36768, 2,35186,27138,36773, -28047,36773,26454,36773, 8770,36773,26375,36773, 8729,36773, 8697,36773, - 8784,36773,28197,36773, 4266,36773, 9262,36773,28111,36773,27128,36773, -28027,36773,28117,36773,28177,36773,31872,36773,28063,36773,31598,36773, -24545,36773,31103,36812, 8684,36773, 8717,36817, 331,36817,26292,36773, -26331,36823, 8647,36773, 8757,36826,26219,36773,27021,36830,26415,36830, -26415,36773,26219,36836, 8757,36773, 8647,36840, 375,36840, 4213,36773, - 375,36846,28153,36773,26860,36773,28213,36773,35931,36773,28159,36773, -31770,36773, 347,36773, 386,36773, 9750,36773,27978,36773,26331,36869, -27805,36869, 1325,36869, 331,36869, 59,36869,23755,36869,25793,36869, - 265,36869, 340,36773, 331,36887,31103,36773,24545,36890,26625,36890, - 9,36890, 375,36773, 8757,36898, 4213,36898, 9195,36898,27021,36898, - 305,36898, 483,36773, 9195,36773, 375,36912,10001,36773, 9,36917, - 1325,36773, 1275,36773, 331,36773,27533,36773, 9,36927, 305,36773, - 375,36930,10291,36773, 483,36935,27021,36773,26219,36938, 375,36938, - 7,36773,25793,36944,26331,36947, 8495,36944, 8717,36951, 331,36951, -25793,36945,26415,36957,27021,36957, 8495,36945, 8757,36963,26625,36944, - 9731,36944,21605,36945,24545,36971,26625,36971, 9,36971, 265,36945, - 8757,36979, 4213,36979,27021,36979, 9195,36979, 305,36979,21605,36944, -26331,36991,27805,36991,23755,36991, 59,36991, 331,36991, 1325,36991, -25793,36991, 265,36991, 265,36944, 331,37009, 8647,36945,26219,36945, - 59,36773, 7,36772,25793,37019, 8495,37019,23755,37019,10055,37019, - 4329,37019, 4311,37019, 3785,37019,27805,37019,10351,37019, 8717,37019, -26331,37019, 9,36773,31103,37042, 15,36773,31103,37047, 9731,36773, - 7,37050,21605,36773, 15,37055,31103,37057, 6,37055, 5,37060, - 7,37055,26219,37065, 375,37065, 6,37054,37057,37071, 7,37054, -26331,37075,37063,37075,27805,37075,23755,37075, 59,37075, 331,37075, - 1325,37075,25793,37075, 265,37075, 265,36773, 7,37095, 8495,37097, - 375,37097, 7,37094, 331,37103,26625,36773,31103,37106, 7,37106, - 8495,36773, 7,37112, 8717,37115, 331,37115, 9,37113, 483,37113, - 7,37113, 8647,37125, 375,37125,25793,36773, 7,37130,26331,37133, - 483,37131, 9,37131, 7,37131,26219,37141, 3,35186,20305,37145, - 9641,37145,20309,37145, 9645,37145, 4,37145, 7,37154,35603,37157, - 9719,37145, 16,37145,35603,37163,35619,37145,21081,37145,20323,37145, -20387,37145, 9701,37145,35719,37145, 524,37145,20273,37179, 9617,37179, - 1291,37145, 9617,37185,20273,37185, 305,37145, 375,37190, 386,37145, - 347,37145, 767,37145,31103,37199, 483,37145, 11,37202, 9617,37205, -20273,37205, 375,37145, 305,37210, 7,37145, 3,37215,18967,37217, -35187,37219, 4,37214,35603,37223,37221,37223, 3,37214,35187,37229, - 11,37145, 483,37232, 9617,37235,20273,37235, 6,35186,19975,37241, - 0,37241, 2,37244,35575,37247,35633,37247,35735,37247,36695,37247, -18966,37241,35735,37257,35633,37257,35575,37257,36695,37257,35749,37241, -35649,37241,36721,37241,35597,37241,19365,37241,19221,37241,19917,37241, -10107,37279, 587,37241, 3,37241, 2,37241, 6,37287, 17,37289, -35187,37291, 0,37286,35575,37295,35633,37295,35735,37295,36695,37295, -37293,37295, 6,37286,36544,37307,37295,37309, 11,37307,35187,37312, -37295,37315,35187,37307, 11,37318,37295,37321, 7,35186, 4,37325, - 3,37326, 3,37327,35927,37331, 902,37325,25525,37325, 1325,37325, -10001,37325, 903,37341, 1275,37325, 59,37325,25793,37325, 587,37349, - 8495,37325, 587,37353, 2,37325, 7,37356,37331,37359, 903,37357, -10311,37357, 3,37325, 4,37366,27533,37325, 903,37371, 331,37325, - 2,37324,25793,37377, 8495,37377,23755,37377, 4329,37377,10055,37377, -27805,37377, 3785,37377, 4311,37377,26331,37377, 8717,37377,10351,37377, -21605,37325, 903,37401, 155,37401, 265,37325, 7,35187, 5045,37408, - 805,37409, 9195,37413, 4,37408,37279,37417,19916,37417,37241,37421, - 1275,37417,18967,37424,37241,37427,18967,37417, 1275,37430,37241,37433, -26546,37408,32805,37408,29599,37408, 652,37409, 9195,37443, 8812,37408, -19888,37408,19913,37408,21308,37408,16481,37408,37285,37409,16783,37408, -17827,37408,18797,37408,26498,37409, 8796,37409, 8495,37408, 241,37468, - 331,37469,25793,37408, 241,37474,25793,37409, 241,37479, 587,37478, - 8495,37409, 241,37485, 587,37484,21037,37408, 241,37490, 88,37409, -37411,37495,16531,37408, 587,37409, 265,37500, 9195,37503,26625,37501, -25793,37501, 8495,37501,25793,37500, 8495,37500, 9731,37501, 265,37409, - 587,37518, 9195,37521, 4213,37519, 7971,37519, 8757,37519, 587,37519, - 9377,37531, 9565,37519, 89,37409, 5069,37537, 9195,37537,27021,37537, - 483,37409, 1275,37409, 9,37547,26503,37409, 8809,37409,18967,37408, - 241,37554, 241,37408,25793,37558,25793,37559, 8495,37558, 8495,37559, -18967,37558,21037,37558, 903,37408, 9377,37573,21605,37408,30003,37577, -29759,37577,34723,37577,21183,37577,37495,37577, 959,37577, 47,37577, - 759,37577, 265,37408, 9377,37595, 903,37409,31103,37598,31920,37409, -31103,37409, 903,37604, 375,37409, 2,37408,37331,37611,37495,37611, - 3,37408,14072,37616, 4970,37616,14072,37617,14073,37616,37623,37625, - 4971,37616, 4970,37617,37629,37631, 7,37617, 4,37635, 1,37616, -37537,37639, 9,37639,36773,37617,37537,37617, 7971,37617,14073,37617, -37619,37651, 4971,37617,37621,37655, 483,37617, 9,37617, 2,37409, -37369,37663,37329,37663,37637,37663, 7,37662,37617,37671,37335,37663, - 9362,37663,27218,37663,37642,37663,37639,37663, 9,37682,28189,37663, - 1,37663, 5,37688,37616,37690,37617,37691,37693,37695,37671,37694, -37616,37691,37617,37690,37701,37703,37672,37691,37671,37691,37617,37708, - 5,37663, 1,37712,37616,37714,37617,37715,37717,37719,37671,37718, -37616,37715,37617,37714,37725,37727,37672,37715,37671,37715,37617,37732, -28337,37663,37660,37663,27021,37663, 9,37740, 9195,37663, 9,37744, - 9,37663,37639,37748,27021,37748, 9195,37748,37617,37748,37241,37663, -37617,37663, 1,37760, 5,37762, 5,37760, 1,37766, 7,37761, -37691,37771,37715,37771,37765,37771,37769,37771, 9,37760, 3,37409, -37577,37783, 9,37785, 16,37783, 4,37783, 7,37790, 7,37783, - 4,37794,18967,37783,35187,37799,37789,37801,37793,37801,37797,37801, - 9,37782,37577,37809,37611,37809,37611,37783, 1,37815, 5,37816, - 5,37815, 1,37820, 7,37814,37819,37825,37823,37825, 9,37815, - 9,37409, 3,37832,37577,37835,37611,37835, 3,37833,37663,37841, - 3,35187,10104,37844,10105,37844, 0,37845, 5,37850, 4,37844, -36773,37855,10104,37845,37849,37859,10105,37845,37847,37863,36945,37845, -37855,37867,10291,37844,36944,37845, 265,37873,37663,37845, 7,37877, -37691,37879,37715,37879, 1369,37845, 11,37885, 9617,37887,37853,37887, -20273,37887, 11,37844, 6,37844, 7,37844,14072,37898, 4970,37898, -14073,37898,14072,37899,37905,37907, 4971,37898, 4970,37899,37911,37913, -35187,37899,36773,37899, 7971,37899,14073,37899,37901,37923, 4971,37899, -37903,37927, 483,37899, 6,37845,37856,37933,37855,37933,36773,37936, - 1,37933, 5,37940,37898,37942,37899,37943,37945,37947,37898,37943, -37899,37942,37951,37953, 5,37933, 1,37956,37898,37958,37899,37959, -37961,37963,37898,37959,37899,37958,37967,37969,36773,37933,37855,37972, -37899,37933, 7,37845, 265,37979,36773,37981,35187,37978, 2,37985, - 4,37979,37987,37989, 3,37989,37985,37993,37663,37989,36773,37978, - 265,37999,37897,37979,36773,37845, 4,38005,37933,38007, 7,38005, -37943,38011,37959,38011,14073,38011, 4971,38011, 6,38004, 1,38021, - 5,38022,38011,38025, 5,38021, 1,38028,38011,38031,38007,38021, - 7,38004, 265,38037,18967,37845, 4,38041,37933,38043, 256,38041, - 7,38041, 241,38048, 241,38041, 7,38052, 2,35187,29229,38057, -28741,38059,28741,38056,29229,38063, 0,38057, 0,38056,28714,38069, -37185,38069, 1290,38069,37145,38075,37179,38069, 525,38069,37145,38081, -37887,38069,37205,38069,37235,38069, 5,38069,21605,38090,21605,38069, - 5,38094, 1275,38069, 17,38098,37145,38101, 17,38069, 1275,38104, -37145,38107, 1505,38057,17455,38057, 903,38112,17494,38057, 483,38057, -37214,38057,14073,38121, 4971,38121,37783,38057, 587,38057,10373,38057, - 9,38057, 155,38057, 6,38056, 1,38137, 5,38138,38121,38141, - 5,38137, 1,38144,38121,38147,37145,38137, 587,38137, 7,38056, -37331,38155, 6,38057, 5,38158,18966,38159, 0,38159, 2,38164, - 2,38159, 0,38168, 1369,38159, 17,38159,35187,38175,38163,38177, -38167,38177,38171,38177, 7,38057,38141,38185,37145,38187,38147,38185, -37145,38191,34447,38185,28715,38185,38069,38197,38071,38185,29659,38185, -29835,38185,38093,38185,38097,38185, 4971,38185,37145,38211,14073,38185, -37145,38215,37145,38184,38141,38219,38147,38219,14073,38219, 4971,38219, -21605,38185, 903,38229,37145,38057, 4,38232, 6,38233, 1,38237, - 5,38238, 5,38237, 1,38242,38235,38237, 7,38233, 265,38249, - 7,38232,38241,38253,38245,38253,38141,38253,38147,38253,14073,38253, - 4971,38253, 903,38057,17455,38266, 6,35187, 4,38271, 1,38272, - 0,38270, 17,38277,37844,38278,37845,38279,38281,38283,37845,38278, -37844,38279,38287,38289, 1369,38271, 2,38270, 587,38295, 3,38270, - 2,38271, 1275,38301, 1, 5,35962,38304,35963,38304,37760,38304, -37771,38311,37976,38304,38002,38304,37761,38304,37977,38304,37815,38304, -37825,38323,38003,38304,37930,38304,37658,38304,37931,38304,37659,38304, - 77,38304, 3095,38337, 1917,38337, 120,38304, 3013,38343, 1897,38343, - 79,38305, 3113,38349, 125,38305, 3023,38353,35929,38305,37885,38357, -37916,38305,37885,38361,38021,38304,38011,38365,38237,38304,38253,38369, - 4597,38305, 6625,38373, 113,38304, 4696,38377, 9,38377, 4669,38380, - 4669,38377, 9,38384,37896,38304,37898,38304,37933,38391, 483,38391, -37616,38304,37663,38397, 483,38397, 59,38304,23023,38403,25483,38403, -22677,38403,27533,38304,23023,38411,22677,38411,22605,38411,25483,38411, -37663,38304,37617,38420,37672,38421,37671,38421,37617,38426,37771,38421, -37879,38421,37617,38421,38397,38435,37671,38434,37933,38304,37899,38440, -38011,38441,37899,38441,38391,38447,37897,38304,38137,38304,38121,38453, -38219,38453,38185,38453,37145,38459,38253,38453,37617,38304,37663,38464, - 483,38464,37899,38304,37933,38470, 483,38470, 979,38305,21605,38477, - 987,38479,21879,38305, 1205,38483,29229,38304,29375,38487,17105,38304, -17117,38491,23755,38304,23023,38495,22677,38495,25483,38495,26863,38305, -21605,38503,26865,38505,10091,38305, 15,38509,10093,38511, 1009,38305, - 675,38304,22605,38517, 1418,38304, 1,38521, 3,38522, 3,38521, - 1,38526,21604,38521,21895,38304,22605,38533,25380,38304, 5,38537, - 6,38538, 6,38537, 5,38542, 14,38537, 1365,38305,17573,38305, - 9,38550,10001,38553,27996,38305,27533,38557, 1203,38305,17574,38305, -10001,38563, 177,38305,27995,38305, 9,38568,27533,38571, 7963,38305, - 9,38574, 7961,38577, 7964,38305, 7961,38581, 120,38305, 77,38305, -37758,38305,37972,38305,37457,38305,37867,38305,35912,38305,35733,38305, -35732,38305,35913,38305,22605,38305,27533,38605, 675,38605,21895,38605, -36856,38305, 483,38613,37644,38305, 483,38617,37918,38305,37933,38621, - 483,38621,37177,38305, 483,38627, 4798,38305,15896,38305,23023,38305, - 59,38635,27533,38635,23755,38635,22677,38305,27533,38643, 59,38643, -23755,38643,25483,38305, 59,38651,27533,38651,23755,38651,25368,38305, -30290,38305,27127,38305,30762,38305,30566,38305, 843,38304,35187,38669, - 1531,38304, 842,38304, 1530,38304,35930,38305,38675,38679,38307,38679, - 9492,38305,10001,38685,13755,38685,27533,38685,24597,38305, 59,38693, - 331,38693, 97,38693, 141,38693, 1325,38693, 629,38305,37896,38305, -37610,38305,37783,38709,37616,38305,38467,38713,38423,38713,38311,38713, -38331,38713,38469,38713,38465,38713,37663,38725, 483,38725,37898,38305, -38473,38731,38443,38731,38315,38731,38329,38731,38475,38731,38471,38731, -37933,38743, 483,38743,37866,38305,37456,38305,17508,38305, 9257,38305, -27149,38305, 9353,38305, 9253,38305,38253,38305,38137,38763,38237,38763, - 483,38763,38219,38305,38137,38771, 483,38771,38121,38305,38137,38777, - 483,38777,15897,38305, 4799,38305,27161,38305,20187,38305, 483,38789, - 8387,38305, 483,38793, 9541,38305,15879,38305, 483,38798, 4787,38305, - 483,38802,16125,38305, 3,38806, 2,38806, 842,38806, 843,38807, -38813,38815, 842,38807, 843,38806,38819,38821, 2,38807,38809,38825, - 3,38807,38811,38829, 5121,38305, 3,38832, 2,38832, 842,38832, - 843,38833,38839,38841, 842,38833, 843,38832,38845,38847, 2,38833, -38835,38851, 3,38833,38837,38855,35729,38305, 587,38859, 587,38858, -19384,38305, 483,38865, 669,38305, 1011,38869, 1086,38305, 483,38873, - 1418,38305, 1011,38877,25381,38305,38541,38881,38545,38881,25423,38881, -25429,38881, 7,38881,25431,38881,38547,38881, 15,38881,25415,38897, -38537,38897, 1419,38305,38525,38903,38529,38903, 1801,38903, 1875,38903, - 2,38903,23983,38903,10603,38903, 4625,38903,21893,38903,38531,38903, -21605,38903, 1421,38925,38521,38925, 1108,38305, 9565,38931, 246,38305, - 483,38935, 294,38305, 8495,38939,35931,38305,38669,38943,38309,38943, - 483,38943,36773,38942, 483,38951,19396,38305,35718,38305,37885,38957, -37202,38957,37145,38957, 483,38962, 483,38957,37145,38966, 668,38305, - 2,38971, 3507,38971, 1971,38971,21783,38971,23983,38971,10603,38971, - 4625,38971,21605,38971, 713,38987,20060,38305, 483,38991, 713,38305, -16833,38995,38011,38305,37933,38999,38021,38999, 483,38999,37285,38305, -37409,39006,36945,38305,37845,39011,37845,39010, 483,39011,37215,38305, - 3,39019,38057,39019, 9377,38305, 9,39024,10001,39027,13755,39027, -27533,39027, 1471,38305,16937,39035, 9875,38305, 1011,39039, 1347,39039, - 555,38305,20763,38305, 566,39046, 566,39047, 567,39046,39051,39053, - 567,39047,39049,39057, 257,38305, 483,39061, 973,38305, 4816,39065, - 4805,39065, 1011,39068,38057,39065, 1011,39065, 4805,39074, 628,38305, - 483,39079, 1406,38305, 587,38305,23584,39085,24355,39085,37782,39085, -37408,39084,39091,39093,37783,39085,37408,39085,38670,39085, 3,39085, -37409,39102,39093,39105,37409,39103,39099,39109,38669,39085,35187,39112, -35728,39084,23493,39085,22807,39118,22807,39085,23493,39122,35729,39084, -35728,39085,39127,39129,35729,39085,39117,39133,37409,39085, 3,39136, -39093,39139, 483,39085,35187,39142,35187,39085,38669,39146, 483,39146, -36773,39147, 483,39153, 1011,39084, 483,39157, 9,39084, 4625,39161, -10603,39161, 3507,39161, 1971,39161,23983,39161,21783,39161,21605,39161, - 713,39175,18967,39084, 483,39179,35187,39084,37202,39183,37885,39183, -37145,39183, 483,39188, 483,39183,37145,39192,37409,39084,39097,39197, - 11,39084, 483,39201, 1369,38305,35964,39204,35965,39205,39207,39209, -35965,39204,35964,39205,39213,39215,35761,39205,38057,39205, 15,39204, - 1011,39223, 11,39205, 1011,39205, 11,39204, 1275,38305, 483,38305, -35895,39234, 4787,39234,15879,39234,21405,38305, 1011,39243, 483,39243, - 7535,38305, 15,39249, 7537,39251, 7541,39251, 7545,39251,28337,38305, -21605,39259,28351,39261,28355,39261,28359,39261, 6147,38305, 483,39269, -15269,38305, 483,39273,17423,38305, 1011,39277, 483,39277, 4827,38305, - 483,39283, 4745,38305, 1011,39287, 483,39287,17232,38305,30492,38305, -25793,39295, 265,39294, 4569,38305, 483,39301,14625,38305, 483,39305, - 7063,38305, 483,39309,37284,38305,37356,38305,17233,38305,30493,38305, - 483,39319,37973,38305,37759,38305,38002,38305,38327,39327,37760,38305, - 483,39331,37976,38305,38321,39335,37617,38305,38398,39339,38319,39339, -38400,39339,38335,39339,37663,39339,38397,39348,37671,39349,38397,39339, -37663,39354, 483,39354,36773,39338, 483,39361, 483,39339,38397,39364, -37663,39338, 483,39369,37899,38305,38392,39373,38321,39373,38394,39373, -38333,39373,35187,39372,37885,39383,37933,39373,38391,39386,38391,39373, -37933,39390, 483,39390,36773,39372,37933,39397, 483,39397, 483,39373, -38391,39402,38185,38305,38150,39407,38137,39407,37145,39410,37202,39407, -37885,39407, 483,39407,37145,39418,37145,39407,38137,39422, 483,39422, -37979,38305,38451,39429,37663,38305,37409,39432, 3,39435, 7,39433, -39437,39439, 2,39439,39435,39443, 483,39433,37617,39447,37241,39432, -37617,39432, 483,39453,37933,38305,36773,39456,37977,38305,38315,39461, -37815,38305, 483,39465,38003,38305,38317,39469,38127,38305, 483,39473, - 482,38304, 5,39477, 6,39478, 6,39477, 5,39482, 14,39477, - 586,38304,39122,39489,39128,39489,39127,39489,38863,39489,38601,39489, -38948,39489,38603,39489,39150,39489,39144,39489,38783,39489,38785,39489, - 3,39489, 1,39512,38971,39515,39161,39515, 1,39489, 3,39520, -38971,39523,39161,39523,39175,39489,38987,39489,21604,39489,39161,39533, -38971,39533,39146,39489, 483,39538,39142,39489,35187,39542,38943,39489, - 483,39546,35728,39489,39085,39550,22807,39489,39085,39554,26219,39489, - 8647,39489,19396,39489,39085,39489,22807,39564,35728,39564,35187,39564, - 483,39570, 483,39564,35187,39574,35895,39489, 9,39489,18967,39580, -18967,39489, 9,39584,35187,39489,39142,39588,39085,39588, 483,39592, - 483,39588,39085,39596, 483,39489,38943,39600,39146,39600,39085,39600, -35187,39606,35187,39600,39085,39610, 4787,39489,15879,39489, 1368,38304, - 3867,39619, 8277,39619, 3997,39619, 4067,39619, 9459,39619, 8953,39619, - 1274,38304,27979,39633,14625,39633, 4569,39633,16381,39633,13325,39633, -26293,39633, 8685,39633,35843,39633, 1369,39633,19513,39633, 3863,39633, -37019,39633, 9955,39633,37377,39633, 8401,39633,10273,39633,20697,39633, - 4137,39633,20219,39633, 4063,39633,35895,38305, 483,39674,35915,38305, - 3,39678, 2,39678, 842,39678, 843,39679,39685,39687, 842,39679, - 843,39678,39691,39693, 2,39679,39681,39697, 3,39679,39683,39701, - 482,38305,39616,39705,39614,39705,39578,39705,35718,39705,35895,39705, -39489,39714,39489,39705,15879,39718, 4787,39718,35895,39718,15879,39705, -39489,39726, 4787,39705,39489,39730,35187,39705, 587,39734, 587,39735, -39489,39739, 587,39705,35187,39742, 1368,38305, 587,38304,39241,39749, -39239,39749,39237,39749,38599,39749,38597,39749,38633,39749,38631,39749, -39677,39749,38801,39749,38805,39749,38679,39749, 483,39771,39235,39749, -15879,39775, 4787,39775,35895,39775, 483,39748,38679,39783, 483,38304, -38121,39787,38219,39787,38253,39787,37899,39786,38731,39795,37617,39786, -38713,39799,38011,39787,38185,39787,37145,39805,14625,39787, 4569,39787, -19396,39787,35931,39787,39489,39815,15269,39787, 4827,39787, 587,39786, -38679,39823,37899,39787,38391,39827,37617,39787,38397,39831,17423,39787, - 4745,39787, 9,39787,18967,39838,18967,39787, 9,39842, 587,39787, -39588,39847,39489,39847,35187,39850,35187,39847,39489,39854,35187,39787, - 586,39858,39823,39861, 586,39859,39847,39865, 586,38305,39713,39869, -38861,39869,39737,39869,39745,39869,38675,39869,35187,39879,39823,39869, -35187,39883,39783,39869,35187,39887, 1108,39869, 295,39869,35927,39869, -37611,39869,38155,39869,35719,39869,39705,39901,39749,39869,22807,39905, -35728,39905,35187,39905, 483,39910, 483,39905,35187,39914,35187,39868, -39823,39919,39783,39919,38675,39919,39749,39919, 483,39927, 1011,39869, - 9,39930, 9,39869, 1011,39934, 1369,38304, 1275,39938, 1275,38304, -39429,39943,23023,39943,22605,39943,25483,39943,22677,39943, 1369,39942, - 803,38305,17455,39956,13737,39957,39705,39961, 1505,38305,21605,39965, - 713,39967, 305,39967, 1489,39967, 1509,39967, 25,39967,15705,38305, - 767,39979,39705,39981,17455,38305, 15,39985, 9513,39987,16859,39987, -17469,39987, 803,39984, 154,38305, 165,39997, 374,38305, 11,40001, - 66,38305, 340,38305,30091,40006,27978,38305,39633,40011,23755,40011, -27805,40011,26331,40011,25793,40011, 8495,40011, 511,38305, 11,40025, - 935,38305, 483,40029, 1109,38305, 11,40033, 295,38305, 256,38305, - 375,40039, 9805,40039,20762,38305, 1141,40045, 1447,40045, 33,40045, - 88,38305,11251,40053, 5177,40053, 136,38305,36727,40059,37895,40059, -36079,40059, 144,38305, 113,40067, 341,38305, 113,40071,16937,40071, -27979,38305,38411,40077, 483,40077,39943,40077, 9565,40077, 113,38305, - 4727,40087, 9,40089,37662,38305,37241,40093,37932,38305,36773,40097, -37782,38305,37978,38305,39633,40103,38389,40103, 305,38305,16833,40109, - 25,38305,16833,40113,20501,38305, 1011,40117, 1347,40117, 253,38305, -16937,40123, 53,38305,16937,40127, 251,38305, 21,38305,38004,38305, - 7,40135,37241,38305, 6,40138, 2,40141,35187,40142,35187,40141, - 2,40146, 2,40147,38056,40141,37663,40138, 3,40138,40145,40157, -40149,40157,40153,40157, 3,40139,40151,40165,40093,40165,36773,38305, -37933,40171,37899,40173,37933,40170,35931,40170, 483,40179,37617,40170, - 483,40183,37899,40170,37933,40187, 483,40187,37409,40170, 3,40193, - 483,40171,35931,40197,37617,40197,37899,40197, 6,40170,37844,40205, - 3,40205,35187,40208,35187,40205, 3,40212, 7,40171,40207,40217, -40211,40217,40215,40217,40195,40217, 2,40217,40193,40227,37845,40217, -40205,40231,37845,40170, 7,40235,37325,38305, 7,40238, 2,40241, - 2,40240, 7,40239,35187,40247, 3,40249, 3,40248, 3,40247, -35187,40254, 3,40246,37844,40247, 1368,40238, 586,40239, 1369,40238, -37845,40238,40259,40269,40265,40269, 587,40239, 2,40238, 7,40276, -40251,40277, 3,40238,40243,40283,35187,40282,40275,40287, 3,40239, -40279,40291,40245,40291,40269,40291, 7,40290,40269,40299,40263,40291, - 2,40239,40287,40305,40257,40305,40253,40305,40261,40305,40267,40305, -10219,38305, 7,40316, 2,40318, 2,40319, 1368,40316, 1369,40316, - 2,40317,40327,40329, 3,40317,40321,40333,40325,40333, 2,40316, - 7,40338,40333,40341, 3,40316,40323,40345, 413,38305, 7,40349, - 375,40349, 1217,38305, 483,40355, 1216,38305, 7,40359, 412,38305, - 483,40363,36348,38305, 2,40366,36429,40369,38233,38305, 7,40373, -25296,38305, 7,40377, 265,38305,27978,40381,30492,40380, 17,40380, - 8495,40387, 6,40380, 11,40391, 7,40380,30091,40394, 7,40381, -27021,40399, 9195,40399,40391,40399,40001,40399,21605,40398, 6,40381, -40395,40411,40007,40411, 17,40411,21605,40381, 7,40418, 17,40419, - 241,40380, 483,40425,21605,40380, 7,40429,30091,40380, 7,40432, - 11,38305,18967,40436, 483,40439, 587,40436, 483,40443, 1369,40436, - 483,40437, 587,40449, 3,40436, 3,40437, 9875,40455,20501,40455, - 1011,38305, 483,40461, 587,40463, 587,40460, 483,40467, 9,40460, - 9565,40471, 7,40461, 959,40475, 759,40475, 47,40475, 903,40460, - 7,40483, 15,38305, 1369,40486, 1011,40489, 241,40486, 483,40493, - 3,40486, 165,40497, 3,40487, 253,40501, 1471,40501, 53,40501, -21605,38305,27533,40509, 15,40509,31103,40513, 1275,40509, 7,40508, -23755,40519,39633,40519,27805,40519,26331,40519,25793,40519, 8495,40519, - 7,40509,26219,40533, 305,40533, 25,40533, 713,40533, 265,40509, -31103,40543, 265,40508, 7,40547,25367,38305, 6,40551, 7,40551, - 6,40550,40555,40557, 7,40550,40553,40561, 17,38305,19917,40565, - 587,40565, 265,40564, 8495,40571, 265,40565, 8861,40575, 3,40564, - 113,40579, 3,40565,10109,40583,10108,40583,10108,40582,40585,40589, -10109,40582,40587,40593, 1141,40583, 1447,40583, 33,40583, 903,38305, - 7,40603, 1141,40605, 1447,40605, 33,40605, 1011,40602, 7,40613, -18967,38305, 1108,40617, 1072,40617, 165,40617, 1291,40617, 524,40617, - 9,40617, 1011,40628, 11,40616, 483,40633, 11,40617, 483,40636, - 483,40617, 11,40641, 1011,40640, 587,40641, 11,40640, 9,40616, - 587,40616, 483,40653, 7,40616, 1141,40657, 1447,40657, 33,40657, - 1011,40617,21183,40665, 7,40665, 483,40664, 9,40664, 241,38305, - 483,40675, 15,40674, 483,40679, 9,40675, 7,40674, 375,40685, - 9805,40685, 7,40675, 265,40691, 59,40691, 331,40691, 1325,40691, - 265,40674, 483,40701, 9,38305, 7963,40704, 7961,40707,27995,40704, -27533,40711,17573,40704,10001,40715,13755,40705, 9377,40719, 1,40704, - 3,40723, 1,40724,40705,40727, 7,40724,40729,40731, 7,40723, - 3,40734, 586,40723, 6,40704, 3,40741, 6,40742,40705,40745, - 0,40742,40747,40749, 0,40741, 3,40752,21604,40704, 3,40757, - 7,40758, 7,40757, 3,40762, 586,40757, 1274,40704, 3,40769, - 0,40770, 0,40769, 3,40774, 9377,40704,27533,40779,10001,40779, -13755,40779,10001,40705,17573,40787, 9377,40787,27533,40705,27995,40793, - 9377,40793,21605,40705,26715,40799,26865,40799,40761,40799,40765,40799, -40731,40799,40737,40799, 6,40799,26719,40799,40739,40799,40767,40799, - 587,40799,26625,40821,40723,40821,40757,40821, 1275,40705, 1991,40829, - 3621,40829,40773,40829,40777,40829, 5299,40829,40749,40829,40755,40829, - 1,40829, 4907,40829,17711,40829, 1011,40704, 9565,40851, 587,40704, -39515,40855,39523,40855, 3507,40855, 1971,40855, 0,40855,40829,40865, -40845,40855,21783,40855,23983,40855, 4625,40855,10603,40855,39533,40855, -21605,40855, 713,40881,39489,40881,18967,40704, 1011,40705,18967,40889, - 9617,40889, 2,40704,36727,40895,37895,40895,36079,40895, 3,40704, -11251,40903, 5177,40903, 2,40705,36729,40909, 3,40705,11355,40913, -30748,38305, 7,40916,17125,38305, 7,40920,30091,38305, 340,40924, - 7,40924,25793,40929, 265,40928, 1011,40925, 7,40935, 265,40925, - 7,40939, 265,40924, 7,40942,14315,38305,31103,40947, 375,40947, - 7,40947, 8495,40953,37845,38305,37897,40957, 1275,40957,36945,40956, - 6,40957, 7,40957, 6,40956,40967,40969,36773,40969, 7,40956, -38389,40975,39633,40975,40965,40975,36773,40956, 7,40983,37409,38305, -37285,40986, 113,40987, 2,40987,39313,40993,40157,40993, 3,40987, -39439,40999,40217,40999, 2,40986,38305,41005, 7,41007,40999,41009, -40165,41005,37241,41005, 3,40986, 3,38304,40375,41019,40237,41019, -40985,41019,40137,41019,40963,41019,39015,41019,38749,41019,40098,41019, -39323,41019,40972,41019,40989,41019,39009,41019,38751,41019,40094,41019, -39325,41019,41014,41019,15567,41019,12971,41019,13355,41019,13541,41019, -21049,41019,21242,41019,39127,41019,39714,41019,39739,41019,38603,41019, -38601,41019,38863,41019,39726,41019,39730,41019,20956,41019,20773,41019, -38783,41019,38785,41019,11970,41019,19441,41019,19656,41019, 4696,41019, - 5,41019, 6,41097,27169,41019,27168,41019,33465,41019,40011,41019, -30492,41019,40519,41019,39295,41019,30493,41019,40929,41019, 357,41019, - 367,41019, 471,41019, 1249,41019, 628,41019,20057,41019, 4569,41019, -14625,41019, 4545,41019,36203,41019,36343,41019,40953,41019,21183,41019, -20103,41142,13325,41019, 8337,41147, 4549,41019, 9357,41019, 9356,41019, -40966,41019,36026,41019,37558,41019,36226,41019,36944,41019, 8386,41019, -20186,41019, 9083,41019, 9484,41019,36027,41019,37559,41019,36227,41019, -36945,41019, 8387,41019,20187,41019,19513,41019,35843,41019,20219,41019, - 8401,41019,37019,41019,20697,41019, 4137,41019, 9955,41019, 3863,41019, - 4063,41019,37377,41019,10273,41019,21405,41019,20606,41019, 9984,41019, -37215,41019,40969,41019,36773,41218,40975,41019,40097,41019,36773,41224, -40103,41019,37979,41019,19396,41019,11131,41019,21059,41019, 9082,41019, -28205,41019,25551,41019,24613,41019,20326,41019,21087,41019,39705,41019, -35895,41250,15879,41250, 4787,41250,11949,41019, 9,41258, 4669,41019, - 9,41262,15879,41019,39705,41266, 4787,41019,39705,41270,20805,41019, -37501,41019,19631,41019, 9,41278,35895,41019,39705,41282, 9704,41019, -40387,41019,38939,41019,40033,41019,40571,41019,20804,41019, 341,41019, - 241,41299,27979,41019, 241,41303, 9377,41019, 11,41306, 256,41019, -35187,41310, 257,41019,35187,41315,20763,41019, 11,41318, 4745,41019, -17423,41019, 587,41019, 11,41326,37409,41326,37500,41019, 9875,41019, - 10,41334, 10,41335, 11,41334,41339,41341, 11,41335,41337,41345, - 1471,41019,37325,41019, 587,41351,37241,41019,40093,41354,41005,41354, -37408,41019, 241,41360,41005,41019,37241,41364,40093,41019,37241,41368, -20885,41019,20413,41372, 1369,41019,37409,41377,37409,41019, 241,41381, - 587,41380,40967,41019, 9195,41019, 11,41388,20413,41019,20885,41392, -10219,41019, 587,41397,20501,41019, 10,41400, 10,41401, 11,41400, -41405,41407, 11,41401,41403,41411, 253,41019, 6,41019,40373,41417, -40135,41417,40235,41417,40983,41417,40967,41417,27021,41417,40533,41417, -30091,41417, 4713,41417,16363,41417, 4863,41417,13119,41417,26415,41417, - 8757,41417,23493,41417,27377,41417, 4213,41417, 9195,41417,39489,41417, - 9335,41417, 4147,41417, 3933,41417, 8109,41417,36212,41417,36773,41417, -20103,41417, 8337,41417,37145,41417, 8997,41417,40957,41417, 241,41417, -35187,41478,18967,41417, 11,41483,35187,41417, 241,41486, 587,41487, - 587,41417, 8387,41417,20187,41417,14653,41417,36945,41417, 7,41019, -30091,41502,26331,41503, 8717,41503,23755,41503,27805,41503, 3785,41503, -40957,41502,36212,41502,39633,41503,10055,41503, 4329,41503, 4311,41503, -10351,41503,36773,41502,20103,41502, 8337,41502, 8997,41502, 1275,41503, - 15,41503,18967,41541,35187,41502, 241,41544, 241,41502,35187,41548, -27021,41019, 11,41552, 53,41019, 6,41018,41165,41559,41531,41559, -41517,41559,41157,41559,40975,41559,40103,41559,41537,41559,41169,41559, -41167,41559,41239,41559,41533,41559,41535,41559,40011,41559,27979,41559, -40519,41559,41549,41559,41311,41559,16381,41559,13325,41559,26293,41559, - 8685,41559,41361,41559,41545,41559,41503,41559,36773,41607,40957,41607, - 8997,41607,20103,41607, 8337,41607, 241,41607,35187,41607, 1369,41559, - 4569,41559,35843,41559,19513,41559, 3863,41559, 9955,41559, 4063,41559, -37377,41559,10273,41559,20697,41559, 4137,41559,37019,41559,20219,41559, - 8401,41559,14625,41559, 7,41018,41181,41653,41466,41653,41387,41653, -41476,41653,41474,41653,41185,41653,41183,41653,41171,41653,41468,41653, -41470,41653, 8997,41653,41417,41674,41315,41653,41478,41653,26219,41653, - 8647,41653,41381,41653,41486,41653,19396,41653,41417,41653,36773,41692, -40957,41692, 8997,41692,20103,41692, 8337,41692, 241,41692,35187,41692, -20103,41653,41417,41708, 8337,41653,41417,41712,36773,41653,41417,41716, - 483,41653, 9,41653,18967,41722, 241,41653, 1,41727,41417,41729, -41417,41726,18967,41653, 9,41734,40957,41653,41417,41738,35187,41653, -41417,41742, 11,41019,27021,41746, 587,41746, 9195,41746,20501,41746, - 9377,41746, 9875,41746,20763,41746, 9,41019, 4669,41762,11949,41762, -19631,41762,18967,41762,20273,41762, 9617,41762, 17,41019,20762,41776, -20762,41777,20763,41776,41781,41783,20763,41777,41779,41787,40957,41019, - 6,41790, 7,41790,41559,41795, 6,41791,41795,41799, 7,41791, -41793,41803,41417,41803, 9617,41019, 9,41808,36212,41019, 7,41812, -35187,41019, 256,41816, 7,41816, 241,41820,41559,41821, 7,41817, -41417,41827, 241,41816, 7,41830, 241,41019, 1,41835, 7,41837, -41559,41839, 7,41836,41417,41843,37408,41834, 7,41835, 1,41848, -41417,41851,41417,41849, 7,41834,41559,41857,35187,41856,35187,41834, - 7,41862,18967,41019, 483,41867, 9,41866,30091,41019, 7,41872, -14315,41019, 8997,41019, 7,41878,41559,41881, 7,41879,41417,41885, -20273,41019, 9,41888, 8337,41019, 7,41892,41559,41895, 9,41893, - 483,41893, 7,41893,41417,41903,20103,41019,21183,41906, 7,41906, -41559,41911, 9,41907, 483,41907, 7,41907,41417,41919,36773,41019, -40097,41922,40969,41922, 7,41922,41559,41929, 9,41923, 483,41923, - 7,41923,41417,41937, 2,38304,38595,41941,40177,41941,39459,41941, -38591,41941,38593,41941,40155,41941,39451,41941,38589,41941,39237,41941, -39241,41941,39239,41941,38599,41941,38597,41941,38633,41941,38631,41941, -26777,41941, 9741,41941,26781,41941, 9745,41941,39677,41941,38801,41941, -38805,41941, 5,41941, 6,41986,38881,41989, 9771,41941, 14,41941, -38881,41995,38897,41941,30349,41941,26857,41941,26933,41941, 9777,41941, -40077,41941,31598,41941,35931,41941,37519,41941,35690,41941,40651,41941, -38955,41941,40887,41941,39235,41941,35895,42025,15879,42025, 4787,42025, - 8982,41941, 668,41941,26625,42035, 9731,42035, 1419,41941, 9731,42041, -26625,42041,40471,41941,38931,41941,40037,41941,40851,41941,37617,41941, -37899,41941,39457,41941,36773,42059,39429,41941,27021,41941, 375,41941, -35187,42066,31103,41941,26625,42070, 9195,41941, 483,41941,39433,41941, -37241,42079, 587,41941, 1,42083,35187,42083, 9,42082, 9731,42089, -26625,42089, 6,41941, 2,42095,21605,42097,38305,42099, 5,42094, -38881,42103,42101,42103, 2,42094,38305,42109, 7,41940, 9459,42113, - 8953,42113, 3997,42113, 4067,42113, 8277,42113, 3867,42113, 9,41941, - 587,42126, 9731,42129,26625,42129, 17,41941, 8861,42134,26625,41941, -31103,42138, 8861,41941, 7,42143, 17,42142,35187,41941, 375,42148, - 9731,41941, 7,38304,39023,42155,41231,42155,25445,42155, 1,42155, - 2,42162, 3,42162,38903,42167,38971,42167,39161,42167,40855,42167, -18967,42167, 2,42163, 3,42163, 5,42155, 2,42182, 3,42182, - 2,42183,42187,42189, 3,42183,42185,42193,21604,42155,18967,42197, -39161,42197,38971,42197,38903,42197,40855,42197,39175,42155,38987,42155, -40881,42155,38925,42155,22779,42155,22243,42155,28063,42155,41303,42155, -31598,42155,25299,42155, 357,42155, 367,42155, 471,42155, 1249,42155, -35690,42155,37519,42155, 272,42155, 1476,42155, 280,42155, 949,42155, - 1517,42155,40387,42155,40571,42155,40033,42155,38939,42155,21087,42155, -20326,42155, 9704,42155, 9304,42155,35931,42155,40998,42155, 253,42155, - 265,42270, 375,42155,35187,42274,31103,42155,26625,42278,25381,42155, -10081,42283,41417,42155, 1369,42287,26625,42155,31103,42290, 9617,42155, - 9,42294, 53,42155, 265,42298,20273,42155, 9,42302,37899,42155, -37617,42155, 1471,42155, 265,42310, 587,42155,35187,42315,38233,42155, -38004,42155,36773,42155,37845,42322,38056,42155,39019,42327,37145,42327, -37844,42155,40305,42333,37933,42155, 483,42155,37845,42155,36773,42340, -40999,42155, 305,42155,21605,42347, 713,42155, 9195,42350,21605,42351, - 9195,42155, 713,42356, 2,42155, 1,42360, 8229,42361,40987,42361, -35187,42361,36773,42369,35187,42360,39019,42373,37145,42373, 3,42155, -42179,42379, 1,42379, 7,42379, 15,42385,38305,42387, 1,42378, -38903,42391,38971,42391,39161,42391,40855,42391,18967,42391,42389,42391, - 7,42378,40704,42405,42391,42407, 9,42405,38305,42410,42391,42413, -38305,42405, 9,42416,42391,42419,40987,42378, 1369,42379,35187,42378, -40305,42427, 25,42155,21605,42431, 2,42154, 1,42435,42379,42436, -42382,42435,42423,42435,42269,42435,42333,42435,42427,42435,42379,42435, - 1,42450,40987,42451,35187,42451, 3997,42435, 4067,42435, 9459,42435, - 8953,42435, 8277,42435, 3867,42435, 3,42154,42165,42471,42363,42471, -42345,42471,42366,42471,26219,42471, 8647,42471,42341,42471,42368,42471, -19396,42471,42361,42471, 1,42491,40987,42490,35187,42490,41417,42471, - 483,42471,18967,42471, 9,42502, 9,42471,18967,42506,40987,42471, -42361,42510,35187,42471,42361,42514,32805,42155, 265,42155, 253,42520, - 1471,42520, 53,42520,40987,42155, 3,42528,42435,42531, 3,42529, -42361,42535,35187,42155, 7,42539,38305,42541, 2,42543, 2,42542, - 2,42541,38305,42548, 2,42540, 1368,42539, 375,42538, 1369,42539, - 2,42538,39019,42561,38305,42560,42559,42565,37145,42561, 3,42538, -40305,42571,42545,42571,42435,42571, 3,42539,40277,42579,39315,42579, - 7,42579,38305,42585,42561,42587,42551,42579,42547,42579,42561,42579, -42361,42579, 2,42539, 7,42598,42571,42599,37845,42599, 9,42155, -20273,42606, 9617,42606, 6,38304,40509,42613,31103,42615,21604,42613, -40471,42613,40851,42613,40037,42613,38931,42613, 8982,42613,27979,42613, - 483,42631,41941,42631,40957,42613,37933,42637,41503,42613, 483,42641, - 8861,42613, 17,42644,17423,42613, 1011,42649, 4745,42613, 1011,42653, - 9875,42613, 1011,42657, 1471,42613,36773,42613, 483,42663,37844,42613, -40305,42667,37979,42613,41941,42671, 1369,42613,38057,42675, 331,42613, - 17,42678, 1325,42613, 17,42682, 334,42613, 1328,42613, 8337,42613, - 483,42691,20103,42613, 483,42695, 53,42613, 393,42613, 1359,42613, - 3,42613, 483,42705,35187,42704,40305,42709,10257,42705,37357,42705, - 2,42613, 62,42613, 59,42613, 17,42720,20501,42613, 1011,42725, - 253,42613, 3,42612,40975,42731,40103,42731,27979,42731,40519,42731, -40011,42731,16381,42731,13325,42731,26293,42731, 8685,42731,41503,42731, - 1369,42731, 4569,42731,35843,42731,19513,42731, 3863,42731, 9955,42731, -20697,42731, 4137,42731,37019,42731, 8401,42731,20219,42731, 4063,42731, -14625,42731,37377,42731,10273,42731,18967,42613, 165,42783, 241,42613, -35187,42613, 3,42788,40305,42791, 3,42789,40277,42795,39315,42795, - 17,42613, 8861,42800, 331,42800, 1325,42800, 59,42800, 7,38305, -25004,42810,25005,42810,25184,42810,25185,42810, 264,42811, 5,42811, - 0,42822, 3,42822, 1,42810, 4,42829,25004,42811,42815,42833, -25184,42811,42819,42837,25005,42811,42813,42841,25185,42811,42817,42845, -41493,42811,41622,42811,25367,42810,30748,42810,39650,42811,42752,42811, -38673,42811,38675,42811,39823,42811,39783,42811,27533,42811,26625,42869, - 331,42811,35187,42873,41559,42811, 1369,42876, 767,42811,18967,42881, -41019,42811,37899,42885,37617,42885,35931,42885,27021,42885,30091,42885, - 9195,42885,25793,42811,30091,42899,27021,42899,37845,42811,42667,42905, - 59,42811,35187,42909, 1325,42811,35187,42913,37897,42811,17125,42810, -30091,42810,25793,42921,41019,42921, 265,42920, 1369,42811,30091,42929, -41559,42928,20103,42929, 8337,42929,36773,42929,42731,42928,39633,42928, -42707,42811,42704,42811, 483,42947,39633,42811, 1369,42950,39749,42811, - 483,42955, 1275,42811, 265,42810,40411,42961,30091,42960,21605,42810, -26331,42967,25793,42967,23755,42967,27805,42967,39633,42967,42731,42967, -41559,42967,41019,42967, 8495,42967,42731,42811, 1369,42986, 241,42810, - 375,42991, 9805,42991,18967,42810, 1141,42997, 33,42997, 1447,42997, - 265,42811,35187,43005, 9377,43005, 9533,43005,37145,43005,21605,42811, -34311,43015,42619,43015,26625,43015,24545,43015, 9731,43015, 2,42810, - 3,42810, 0,43028,43005,43031, 295,43029, 1108,43029,35927,43029, -38155,43029,37611,43029, 9,43029, 1011,43044, 1011,43029, 9,43048, - 2,42811,42831,43053, 5,43053,42829,43057,36256,43053, 9,43053, -35187,43062,35187,43053, 9,43066, 3,42811, 5,43070,22807,43071, -37663,43071,42613,43070, 483,43079, 241,43071, 9,43083,37845,42810, -41559,43087,38389,43087,42731,43087,39633,43087,41019,43087,42613,42811, -32805,43099,37845,43098,37845,43099,37844,43098,43105,43107,37844,43099, -43103,43111, 3,43099, 1369,43115, 3,43098, 483,43119, 15,42811, -20273,43123, 9617,43123,35187,42810, 7,43129, 2,43130, 2,43131, -38305,43129, 3,43136,43135,43139, 3,43137,43133,43143, 1368,43129, -43143,43147, 59,43129, 1325,43129, 331,43129, 265,43129, 2,43129, - 7,43158,43143,43161, 3,43129,38305,43164,43135,43167,37408,38305, - 7,43171, 2,43172,40999,43175, 2,43173,40101,43179,41017,43179, - 1368,43171,40999,43185, 59,43171, 1325,43171, 331,43171, 265,43171, - 2,43170,37783,43197, 2,43171, 7,43200,40999,43203,37617,43201, - 3,43171,38305,43208,43179,43211, 3,38305,43129,43214,43135,43217, - 1,43214, 1011,43221,42041,43221, 1418,43221,41941,43227,42035,43221, - 669,43221,41941,43233,42089,43221,42129,43221, 1369,43221, 15,43240, -41941,43243, 15,43221, 1369,43246,41941,43249,11989,43215, 9,43253, -13737,43215, 9,43257,37357,43215,10257,43215,38118,43215,38132,43215, -37544,43215,37409,43215, 483,43270, 113,43215, 587,43275,37345,43215, -37241,43214,40993,43281,40993,43215,37241,43285, 9,43215,38057,43288, - 483,43215,38057,43292,37409,43292,10289,43215, 15,43214, 165,43301, - 11,43214, 9,43214,11251,43307, 5177,43307, 17,43214, 113,43313, - 11,43215, 165,43215, 7,43214, 0,43321, 4,43322, 4,43321, - 0,43326,35186,43321, 295,43321, 1108,43321,35927,43321,38155,43321, -37611,43321, 9,43321, 1011,43342, 1011,43321, 9,43346, 7,43215, -21604,43351, 1,43351, 3,43354, 3,43351, 1,43358, 15,43351, -38305,43363,43353,43365,43357,43365,43361,43365, 1011,43363,37409,43214, -43179,43375,41941,43215,37408,43379, 7,43379,35187,43382,35187,43379, - 6,43386, 7,43386, 6,43387,43391,43393, 7,43387,43389,43397, - 1011,43215,37408,43401, 7,43401,35187,43404,35187,43401, 7,43408, -38057,43215,40097,43413,40969,43413, 7,43413, 9,43412, 483,43412, -35187,43214,40305,43425,40275,43425,38305,43425, 6,43430,43413,43433, - 6,43425,38305,43436,43413,43439,41941,43425, 6,43443, 7,43443, - 6,43442,43447,43449, 7,43442,43445,43453, 1011,43425, 7,43457, -37844,38305,42336,43461,42917,43461,42905,43461,39013,43461,40305,43461, -40275,43461,37933,43461,42155,43474,42155,43461,37933,43478, 6,43460, -41941,43461, 6,43485, 7,43485, 6,43484,43489,43491, 7,43484, -43487,43495, 1011,43461, 7,43499, 2,38305,41603,43503,41686,43503, -41825,43503,41828,43503,42541,43502,42579,43513,16936,43503,36400,43503, -36439,43519,36348,43503, 6,43523,36413,43525, 6,43522,36439,43529, -36439,43523,41744,43503,41688,43503,41605,43503,41706,43503,41620,43503, - 1,43503, 1275,43544, 4,43544, 7,43544,41417,43551, 7,43545, -39633,43555,41559,43555,42731,43555,41019,43555, 1,43502,41692,43565, -41607,43565,41653,43565,41417,43570,41417,43565,41653,43574,41502,43565, -41559,43579,41019,43565, 7,43582,41559,43585, 7,43583,41417,43589, - 7,43565,41019,43593,41653,43595,41019,43592,41559,43599, 5,43502, -21605,43603,42810,43604,42811,43605,43607,43609,42811,43604,42810,43605, -43613,43615,41692,43503,35187,43618,41607,43503,35187,43622,41360,43503, -41559,43627,41820,43503,41559,43631,41544,43503,41559,43635,35760,43503, - 8315,43503,37408,43502,37783,43643,42538,43503,42601,43647,42553,43647, -42555,43647,41742,43503,41417,43654,41486,43503,41653,43658,41417,43503, -41827,43662,41742,43662,41653,43662,35187,43668,35187,43662,41653,43672, -37783,43503,37325,43502,42795,43679,42579,43679,41502,43503,41559,43685, -35187,43687,35187,43684,41559,43691,37241,43503,37409,43695,41019,43697, -41381,43503,41653,43700, 1275,43503, 1,43704,35187,43704, 9,43705, - 9731,43711,43221,43711,43549,43711,26625,43711, 587,43503,42811,43721, -35895,43723,15879,43723, 4787,43723,41653,43503, 1,43731,41417,43733, -41381,43730,41486,43730,41417,43730,35187,43740,35187,43730,41417,43744, - 9,43502,36727,43749,36079,43749,37895,43749,41827,43503,41417,43756, - 6,43502,39616,43761,39614,43761,39578,43761,39901,43761,41282,43761, -41266,43761,41270,43761,39961,43761,39981,43761,35718,43761,39869,43781, -41019,43761,35895,43784,15879,43784, 4787,43784,15879,43761,39489,43792, -41019,43792, 4787,43761,39489,43798,41019,43798,35895,43761,39489,43804, -41019,43804, 587,43761,35187,43810,39869,43813,35187,43761, 587,43816, -39869,43819, 587,43817,39489,43823,41019,43823,39489,43761,15879,43828, - 4787,43828,35895,43828, 7,43502, 6,43503,36348,43838,36439,43841, -36348,43839,36429,43845, 7,43503,41817,43848,43817,43849,41019,43853, - 4,43849, 0,43856,43784,43859,41019,43859,43761,43862,43761,43859, -41019,43866, 0,43849, 4,43870,43784,43873,41019,43873,43761,43876, -43761,43873,41019,43880, 1,43848,41417,43885,35186,43849,43784,43889, -41019,43889,43761,43892,43761,43889,41019,43896,41816,43848,41559,43901, -41019,43848,41559,43905,35187,43907,35187,43904,41559,43911,41019,43849, -41827,43915,43851,43915,41742,43915,41653,43915,35187,43922,35187,43915, -41653,43926,35187,43848,41417,43931,41019,43930,41559,43935,41019,43931, -41653,43939,37409,43502,41354,43943,40165,43943,41019,43943,37241,43948, -37241,43943,41019,43952,37408,43503,41417,43957,37663,43957,41019,43956, -41559,43963,41019,43957,41653,43967,41816,43503, 6,43970, 7,43970, -41559,43975, 6,43971,43975,43979, 7,43971,43973,43983,41417,43983, -41019,43503, 1,43989, 7,43990,41417,43993, 7,43991,41559,43997, -37408,43988,41559,44001,37408,43989,41381,44005, 7,43989,41381,44009, -41486,44009, 1,44008,41417,44015,41417,44009,35187,44018,35187,44009, -41417,44022, 7,43988,41559,44027,35187,44029,35187,44026,41559,44033, -35187,43988, 6,44036, 7,44036,41559,44041, 6,44037,44041,44045, - 7,44037,44039,44049,41417,44049,21605,43503, 7,44055, 265,44057, -35187,43503,41692,44060,41607,44060,41502,44060,41559,44067, 1275,44060, -41653,44060,41417,44072,36945,44061,41019,44077,41417,44060,41653,44080, - 6,44061,41922,44085,43413,44085,41019,44085,36773,44090,36773,44085, -41019,44094, 7,44061,41559,44099,42731,44099,39633,44099,41019,44099, - 6,44060,44099,44109, 7,44060,41417,44113,41019,44112,41559,44117, -44085,44113,41019,44113,41653,44123,41019,44060, 6,44126, 7,44126, -41559,44131, 6,44127,44131,44135, 7,44127,44129,44139,41417,44139, -36773,44061,41417,44145, 7,44145,41019,44149,35187,43502,41217,44153, -41472,44153,29229,44153,41099,44153,36429,44153,42559,44153,41417,44153, -37145,44166,37783,44153,37214,44153,41019,44173, 7,44153,41019,44177, -37145,44179,37145,44176,41019,44183,37145,44153,41417,44186, 7,44186, -41019,44191,38056,38305,41472,44195,41217,44195,41099,44195,29229,44195, -36429,44195,42559,44195,35187,44195, 6,44209,43413,44211,41417,44195, -37145,44214,37783,44195,37214,44195,41019,44221, 7,44195,41019,44225, -37145,44227,37145,44224,41019,44231,37145,44195,41417,44234, 7,44234, -41019,44239, 6,38305,42453,44243,42493,44243,42472,44243,42439,44243, -42474,44243,42441,44243,42363,44243,42471,44256,42381,44243,42165,44243, -42471,44262,42325,44243,42330,44243,42343,44243,42321,44243,42319,44243, -42371,44243,42376,44243,42568,44243,42447,44243,42484,44243,42054,44243, -42056,44243,44171,44243,43645,44243,43960,44243,44219,44243,43201,44243, -37617,44298,43206,44243,38711,44243,43199,44243,42605,44243,40231,44243, -43677,44243,40959,44243,10586,44243,10827,44243,42594,44243,42603,44243, -42577,44243,42596,44243, 6664,44243, 6243,44243, 9780,44242, 566,44242, - 566,44243, 567,44242,44337,44339,43517,44243, 9781,44242,42012,44243, -36303,44242,36303,44243,26970,44242,26971,44242,43639,44243, 4593,44243, - 6625,44358, 3113,44243, 3023,44243, 4736,44243, 6653,44243,42518,44243, - 3251,44243,42516,44243,42486,44243,42449,44243,42496,44243,42456,44243, -19257,44243,19243,44243,43425,44242,43413,44389,40511,44243,17452,44243, -42085,44243,43707,44243,42087,44243,40961,44243,43709,44243,44071,44243, -36099,44243,36098,44242,44409,44411,36099,44242,36098,44243,44415,44417, -43605,44243,43222,44242,43223,44243,44423,44425,43222,44243,43223,44242, -44429,44431,42199,44243,24081,44243,42181,44243,42383,44243,42435,44441, -42401,44243,42177,44243,43547,44243, 5,44242,42283,44451,25380,44451, -42155,44455, 1369,44451,21605,44458,42155,44461,21605,44451, 1369,44464, -42155,44467,42373,44243,37145,44470,42561,44243,37145,44474,42579,44474, -42327,44243,37145,44480,27514,44243,42490,44243,35187,44486,42451,44243, -35187,44490, 413,44243,32805,44243,42155,44496,28547,44243,42064,44243, -42138,44243,40517,44243,40543,44243,30294,44243,38004,44243,43461,44513, -38232,44243,42155,44517,38005,44243,42155,44521,30749,44243, 9780,44243, -44345,44527,26970,44243,44355,44531, 6625,44243, 4593,44534, 33,44535, - 9781,44243,44333,44541,25005,44243,26971,44243,44353,44547,25185,44243, -25589,44243,42074,44243,42152,44243,10831,44243, 77,44243, 120,44243, - 506,44243,38041,44243, 5101,44243,16989,44243,10511,44243, 4931,44243, - 5267,44243,16981,44243,13017,44243,12705,44243,13673,44243,18391,44243, -18617,44243,14599,44243, 9366,44243,36302,44243,18217,44243,42332,44243, -42435,44599,42570,44243,42435,44603,42426,44243,42435,44607,41539,44243, -41720,44243, 9132,44243, 1216,44243,36302,44242, 3,44618,44351,44621, -30748,44243,30748,44242,44525,44627,30749,44242,44625,44631,16931,44243, -35931,44243,41941,44636,39600,44243,42500,44243,18929,44243,38669,44243, -38677,44243,17019,44243,39941,44243,39955,44243,27021,44243, 483,44656, -41941,44656,37844,44242,44351,44663,41653,44243, 483,44666,43413,44243, -43425,44671,42514,44243,42361,44674,42368,44243,42471,44678,42361,44243, -42579,44682,42514,44682,42471,44682,35187,44688,35187,44682,42471,44692, -20234,44243, 8444,44243, 567,44243,44335,44701,16937,44243, 11,44705, - 1369,44705,26625,44243,41941,44710,41941,44243,37899,44714,37617,44714, -35931,44714,27021,44714,26625,44714, 9195,44714, 9731,44714,43957,44243, -37663,44730,20103,44243, 483,44734, 8337,44243, 483,44738, 9533,44243, - 4727,44243, 25,44744,10527,44243, 25,44748, 4541,44243,38128,44243, -38057,44243,42155,44757,37145,44759,37145,44756,42155,44763, 587,44756, -37845,44243,43461,44769,36773,44771,36773,44768,43461,44775, 25,44243, -10527,44778, 4727,44778, 113,44778, 9195,44243,41941,44786, 483,44786, -37782,44243,43197,44793,43643,44793,38709,44793,17451,44243, 1011,44800, -35688,44243,36910,44243,36923,44243,37899,44243,41941,44810,37617,44243, -41941,44814,43201,44814, 9731,44243,41941,44820, 8997,44243, 483,44824, - 66,44243, 33,44829, 483,44243,27021,44832,30091,44832, 241,44832, - 9195,44832,41653,44832, 8997,44832,42471,44832,39489,44832,20103,44832, - 8337,44832,36773,44832, 903,44243, 1011,44856,18967,44243, 567,44861, - 566,44860,44863,44865, 566,44861, 567,44860,44869,44871, 241,44243, - 483,44874,42425,44243,42378,44243,42435,44881,35187,44883,35187,44880, -42435,44887, 1369,44881,36773,44243,37845,44892,43461,44895, 483,44892, -37845,44893,41019,44901,37145,44243,42327,44904,42373,44904,42561,44904, -38057,44904,42155,44913,42341,44243,42471,44916,30091,44243, 483,44920, - 113,44243, 25,44924,35187,44924,17125,44243,37663,44243,43957,44932, -39489,44243, 483,44936,39943,44243, 1369,44941, 587,44243,43215,44945, -35895,44947,15879,44947, 4787,44947,38057,44944, 8449,44243,20237,44243, - 265,44242,40399,44961, 11,44961,42471,44243,42165,44966,42363,44966, -42341,44966,42368,44966,42361,44966,35187,44976, 483,44966,35187,44966, -42361,44982,20834,44243, 1011,44243,17451,44988,35187,44988, 903,44988, -20763,44988,20763,44243, 1011,44998, 257,44243,42579,44243,42561,45004, -42361,45004, 2,44242,39616,45011,39614,45011,39578,45011,39901,45011, -41282,45011,41266,45011,41270,45011,39961,45011,39981,45011,35718,45011, -39869,45031,41019,45011,35895,45034,15879,45034, 4787,45034,15879,45011, -39489,45042,41019,45042, 4787,45011,39489,45048,41019,45048,35895,45011, -39489,45054,41019,45054, 587,45011,35187,45060,39869,45063,35187,45011, - 587,45066,39869,45069, 587,45067,39489,45073,41019,45073,39489,45011, -15879,45078, 4787,45078,35895,45078, 3,44242,36302,45087,44349,45089, -35187,45086,44351,45093, 2,44243, 14,45097, 5,45097, 6,45100, - 6,45097, 5,45104,21605,45097,38305,45109,45099,45111,45103,45111, -45107,45111,43215,45097,43325,45119,43329,45119,35895,45119,15879,45119, - 4787,45119,43331,45119,35187,45119,43321,45133,35187,45096,39313,45137, -40157,45137,43281,45137,43215,45137,37241,45145, 3,44243,42539,45148, -38305,45149,37408,45152,37408,45153,45067,45149,41019,45159, 4,45149, - 0,45163,38305,45163, 0,45162,45034,45169,41019,45169,45011,45172, -45011,45169,41019,45176,45119,45169, 0,45149,38305,45183, 4,45182, -45034,45187,41019,45187,45011,45190,45011,45187,41019,45194,45119,45187, - 0,45148,38305,45148, 1,45148,45176,45205,45194,45205,45169,45205, -45011,45210,45187,45205,45011,45214,45159,45205,45011,45205,45169,45220, -45187,45220,35186,45148,35186,45149,38305,45229, 7,45231,45220,45229, -45205,45229,45011,45236,45034,45229,41019,45229,45011,45242,45011,45229, -45205,45246,41019,45246,45119,45229, 1,45149,45165,45255,45011,45257, -45167,45255,45011,45261, 5,45149,45185,45265,45011,45267,43171,45149, -37617,45271,42538,45148,42435,45275,37409,45148,38709,45279,43197,45279, -45155,45279,43643,45279,42155,45148,42435,45289,35187,45291,35187,45288, -42435,45295, 1369,45289, 1011,45149, 483,45301, 11,45148, 33,45305, -37409,45149,45157,45309,43957,45309, 11,45149, 25,45315,35187,45315, -42155,45149,42579,45321,45151,45321,42514,45321,42471,45321,35187,45328, -35187,45321,42471,45332,45066,45149,45201,45337,45203,45337,35187,45149, -45201,45343,45011,45345,45203,45343,45011,45349,45011,45342,45201,45353, -45203,45353,45011,45149,35187,45358,45201,45361,45203,45361,35187,45148, -40217,45367,45233,45367,42155,45366,42435,45373,42155,45367,42471,45377, -37845,44242,41922,45381,43413,45381,44595,45381,44993,45381,41019,45381, -36773,45390,36773,45381,41019,45394,38056,44243,39313,45399,40157,45399, -43281,45399,43215,45399,37241,45407,37844,44243,40217,45411,42155,45410, -42435,45415,42155,45411,42471,45419,42538,44243, 3,45422,42435,45425, - 3,45423,42361,45429,42155,44243,32805,45432,37845,45432,37845,45433, -37844,45432,42435,45441,45439,45441,37844,45433,42341,45447,45437,45447, - 3,45433,42341,45453,42368,45453,42361,45453,35187,45458,35187,45453, -42361,45462, 483,45453, 3,45432,42435,45469,35187,45471,35187,45468, -42435,45475, 1369,45469,35187,45432, 3,45480,42435,45483, 3,45481, -42361,45487, 11,44243, 8861,45491, 3,45490, 33,45495, 3,45491, - 113,45499, 331,45491, 1325,45491, 59,45491,35187,44243,42490,45508, -42451,45508,38305,45508, 7,45515, 2,45517, 2,45516, 2,45515, - 7,45522, 1368,45515, 1011,45508,45381,45529,42378,45508,42435,45533, -42471,45508,42361,45536,37285,45509,41019,45541,42361,45508,42471,45544, - 113,45508, 2,45509,41354,45551,40165,45551,38305,45551, 7,45557, -41019,45551,37241,45560,37241,45551,41019,45564, 3,45509,45519,45569, - 2,45508,40157,45573,39313,45573,43281,45573,43215,45573,37241,45581, - 3,45508,40217,45585,45521,45585,45525,45585,45559,45585,45527,45585, -42155,45584,42435,45597,42155,45585,42471,45601,42155,45508, 3,45604, -42435,45607, 3,45605,42361,45611,37409,44243,43503,45615,37663,45617, - 3,45615,43201,45621, 3,45614,38709,45625,43197,45625,43643,45625, -35187,44242, 3,45632,44351,45635,35187,38305,37214,45639, 2,45641, -39019,45643,39021,45641,37286,45639,35890,45638,35891,45639,45651,45653, -35891,45638,35890,45639,45657,45659,38152,45638,38153,45639,45663,45665, -38296,45638,38297,45639,45669,45671,38153,45638,38152,45639,45675,45677, -38297,45638,38296,45639,45681,45683,37283,45639,42675,45639,37282,45639, -42674,45639,37899,45638,37885,45695,38293,45639,37885,45639,37899,45701, -44945,45639,38292,45639,44944,45639,37287,45639,38173,45638,38172,45639, -45713,45715,38303,45638,38302,45639,45719,45721,38173,45639,38172,45638, -45725,45727,38303,45639,38302,45638,45731,45733,45096,45639,45149,45639, - 7,45738,45367,45741,45097,45639,37241,45639, 2,45747, 2,45746, - 587,45746,42613,45639, 1369,45754,38271,45639, 1369,45758,44243,45639, - 2,45763, 2,45762, 587,45762, 136,45639, 137,45639, 1530,45638, - 842,45638, 669,45639, 1419,45639, 843,45639,39085,45783,45777,45783, - 1531,45639,45775,45789, 1530,45639, 843,45638, 842,45639,45795,45797, - 1531,45638,45793,45801, 1368,45639,45411,45805,40999,45805,45367,45805, -45585,45805,42613,45805,37845,45805,44243,45817, 586,45639,39847,45821, -39142,45821,39085,45821, 483,45826,37241,45821, 483,45821,39085,45832, - 586,45638,38675,45837,39823,45837,39783,45837,39749,45837, 483,45845, - 1418,45639, 668,45639, 587,45638,37885,45853,37202,45853,37145,45853, - 483,45858, 483,45853,37145,45862, 587,45639,37241,45866,44243,45866, - 9,45866, 483,45639, 587,45875,37145,45877, 1369,45639,35760,45880, -35761,45881,45883,45885,35760,45881,35761,45880,45889,45891,42613,45880, -38271,45880, 15,45880, 9,45639, 2,45900, 2,45901, 587,45900, - 265,45639, 375,45909, 15,45639, 1369,45912, 7,45639,40956,45917, -44060,45917,40957,45917,44061,45917,43502,45917,37844,45917,35187,45917, - 3,45930,43503,45930, 3,45931,45927,45937, 1369,45931,38305,45917, - 2,45942,45937,45945,37845,45942, 2,45943,45933,45951,45929,45951, - 587,45943,45149,45917,37145,45959,45227,45959,37845,45917,38305,45964, -43503,45917,35187,45968, 375,45917,45148,45917, 2,45917,40101,45977, -41017,45977,38305,45976,45937,45983,44904,45977,45569,45977,43375,45977, -39019,45977,44243,45977,37145,45994,37145,45977,44243,45998, 3,45917, -35187,46002,45951,46005,44243,46002, 3,45916,45943,46011, 7,46011, -38305,46015,45977,46017,45994,46011,45959,46011,45967,46011,45919,46011, -45949,46011,45925,46011,37241,46011,45977,46011,44243,46034,44243,46011, -45977,46038, 2,45916,45931,46043,40999,46043,45975,46043,45367,46043, -45585,46043,46009,46043,45971,46043,45921,46043,45935,46043,45923,46043, -45411,46043,42613,46043,46003,46043,44243,46069,37845,46043,44243,46073, -44243,45917, 3,46076,46043,46079, 3,46077,45977,46083, 6,45638, -45998,46087,46073,46087,45817,46087,37844,46087,46043,46095,45805,46095, -35187,46087, 3,46101,45977,46103, 3,46100,46043,46107,45805,46107, -37145,46087,45977,46112,45977,46087,37145,46116, 3,46087,35187,46120, -46043,46123,45805,46123,45917,46121,37145,46129,45917,46087,35187,46132, - 2,46135, 2,46134,38057,46132,38056,46132, 2,46133,46141,46145, - 3,46133,46139,46149,46143,46149, 2,46132,35187,46154,46149,46157, -46149,46155, 3,46132,46137,46163,46145,46163, 3,45639, 5,46169, - 6,46171, 4,46168, 0,46168, 5,46168, 1,46168,45983,46169, -45945,46169,43679,46169,45927,46169,40277,46169,45749,46169,45765,46169, -39315,46169,45905,46169,37241,46169,45977,46169,42613,46203,43848,46169, - 256,46169, 6,46169,46175,46211,46177,46211,37145,46211, 7,46169, -46179,46219,46181,46219,41019,46219,45639,46218, 2,46227,38305,46219, -46229,46231, 3,46231,46227,46235,45977,46231,43503,46218, 241,46218, -38271,46219, 7,46168,37241,46247,38057,46169,38305,46251,46211,46253, -43503,46169, 6,46256, 7,46256, 6,46257,46261,46263, 7,46257, -46259,46267, 241,46169, 7,46270, 2,45638,41472,46275,41217,46275, -46175,46275,46211,46280,46177,46275,46211,46284,46212,46275,46214,46275, -46221,46275,46223,46275,46173,46275,45930,46275,46043,46299,46045,46275, -46216,46275,46225,46275,41099,46275,46032,46275,45711,46275,46200,46275, -45745,46275,46248,46275,46245,46275,35187,46275,45917,46322,46043,46325, -45917,46323,46011,46329,45830,46275,29229,46275,45773,46275,36429,46275, -45895,46275,45897,46275,45687,46275,45693,46275,45705,46275,45707,46275, -45849,46275,45779,46275,42559,46275,45899,46275,45915,46275,45757,46275, -45761,46275,45941,46275,41417,46275,37145,46368,45821,46275,37241,46372, -46011,46275,37241,46376,46247,46275,37241,46380,45881,46275,42613,46385, -37241,46275,46011,46388,46169,46388,46247,46388,45821,46388,46211,46275, -46175,46398,46177,46398,37145,46398,37783,46275,44243,46407,45917,46275, -35187,46410,46043,46413,37214,46275,41019,46417,46218,46275,46179,46421, -46181,46421,41019,46421, 7,46275,41019,46429,37145,46431,46169,46429, -46175,46435,46177,46435,37145,46435,37145,46428,41019,46443,46169,46428, -46179,46447,46181,46447,41019,46447,37145,46275,41417,46454,46211,46454, - 7,46454,41019,46461,46169,46275,35187,46464, 6,46467, 6,46466, -38305,46465,46211,46473,38271,46464,44243,46465,38270,46464,37241,46464, - 6,46465,46477,46485, 7,46465,46471,46489,46481,46489, 6,46464, -46473,46495,35187,46494,46489,46499,46489,46495, 7,46464,46179,46505, -46181,46505,46469,46505,46485,46505,41019,46505, 2,45639,42671,46517, -39429,46517,44814,46517,44810,46517,44636,46517,37241,46516,40077,46517, -44243,46516,46003,46517,37241,46535, 9,46516,44243,46517,37617,46540, -37899,46540,35931,46540,35931,46517,44243,46548,37617,46517,44243,46552, -37899,46517,44243,46556, 7,46517,44243,46561, 7,46516,46107,46565, -46123,46565,46095,46565,40999,46565,45585,46565,45411,46565,45367,46565, -42613,46565,37845,46565,46087,46583,44243,46583,37845,46517,46211,46589, -41417,46589, 7,46589,41019,46595, 3,45638,45951,46599,45942,46599, -46011,46603,46013,46599,46066,46599,46540,46599,40305,46599,46529,46599, -45751,46599,46533,46599,45767,46599,46580,46599,46563,46599,45649,46599, -45737,46599,38305,46599,45917,46630,46011,46633,45917,46631,46043,46637, -45814,46599,45771,46599,45869,46599,45871,46599,45689,46599,45691,46599, -45699,46599,45709,46599,45851,46599,45781,46599,40275,46599,46539,46599, -45903,46599,45873,46599,45907,46599,45753,46599,45769,46599,45957,46599, -45805,46599,42613,46676,46043,46599,42613,46680,46565,46599,42613,46684, -45867,46599,37241,46689,42613,46599,46043,46692,46565,46692,45805,46692, -45917,46599,38305,46700,46011,46703,46560,46599,44243,46599,46517,46708, - 7,46599,38305,46713,46517,46715,46517,46712,41941,46599, 6,46721, - 7,46721, 6,46720,46725,46727, 7,46720,46723,46731, 1011,46599, - 7,46735,46517,46599,38305,46738,35187,46739, 6,46742, 6,46743, -44243,46738,38271,46739,38270,46739,37241,46739, 6,46739,35187,46756, -46741,46757, 7,46739,41019,46763,46747,46763, 6,46738,46763,46769, -46751,46769, 7,46738,46759,46775,46745,46775,46757,46775,46753,46775, - 6,45639, 7,45638,43214,46787,45977,46789,38305,46787, 3,46793, -46043,46795,46565,46795,45805,46795, 3,46792,45977,46803, 59,46787, - 1325,46787, 331,46787, 265,46787, 2,46787, 7,46814,46795,46817, - 3,46787,38305,46820,45977,46823,46785,46787,35187,46827, 2,46828, - 2,46829,38057,46827,38056,46827, 2,46827,35187,46838, 3,46827, -46833,46843, 2,46826,46843,46847,46835,46847, 3,46826,46841,46853, -46831,46853,46839,46853,46837,46853, 0, 6,13135,46863,13169,46864, - 4871,46863, 4893,46868,13172,46863, 4894,46863,13136,46863,13143,46877, - 4872,46863, 4879,46881,13145,46863, 4881,46863,37417,46863,38056,46888, -38057,46889,46891,46893,38057,46888,38056,46889,46897,46899,17176,46863, -17380,46863,16950,46863,17058,46863,16948,46863,17056,46863,16974,46863, -17072,46863,16996,46863,17086,46863, 3348,46863,18291,46863, 7316,46863, - 8455,46863, 8343,46863, 8353,46863,13139,46863,13175,46863,13155,46863, -13517,46863,15197,46863,15485,46863,15512,46863,15595,46863,15203,46863, - 5757,46863, 5453,46863, 5471,46863, 5455,46863, 4863,46959, 5507,46863, -12569,46863,12387,46863,12551,46966,12552,46863,16995,46863,16941,46863, -16977,46974,16978,46863,17017,46862,17016,46862,19836,46863,19857,46985, -19815,46863, 4,46988,19857,46991, 4,46989,19843,46995,27930,46863, -27895,46999,27857,46863, 4,47002,27895,47005, 4,47003,27907,47009, -36303,46862,36325,47013,27128,46863, 9136,46863,27266,46863,27163,46863, -34310,46863,34447,47025,46516,46863,46599,47029,33454,46863,33368,46863, -28027,46863,28111,46863,28117,46863,26928,46863,24253,46863,30569,46863, -30316,46863,28213,46863,26525,46863, 9137,46863, 273,46863, 1477,46863, - 281,46863,17011,46863, 5043,46863,15503,46863, 8997,47066,24558,46863, -26575,46863,41877,46863, 120,46863, 77,46863,16977,46863,16941,47080, - 9262,46863,14813,46863,26605,46863,41923,46863, 8843,46863,37131,46863, -41907,46863,26591,46863,41893,46863,37113,46863,20255,46863, 9288,46863, - 8697,46863, 9275,46863, 8784,46863,19877,46863,41867,46863,20043,46863, -21376,46863,21485,46863,19787,46863,19391,46863,19299,46863,19271,46863, -19283,46863,17010,46863, 5042,46863,36518,46863,40664,46863,17017,46863, -46983,47143, 1516,46863, 948,46863,17016,46863,46981,47151,16972,46863, - 903,47154,17070,46863, 1011,47158,17175,46863, 903,47162,17379,46863, - 1011,47166, 4213,46863, 375,47170, 8757,46863, 375,47174, 4266,46863, -16865,46863,16873,46863,16867,46863,12642,46863, 8896,46863,14740,46863, - 8355,46863, 264,47193, 265,47192,47195,47197, 264,47192, 265,47193, -47201,47203,14515,46863,14517,46863,14519,46863,20201,46863,36979,46863, -20152,46863,36898,46863,20239,46863,37095,46863,21522,46863,38266,46863, -17082,46863, 903,47228,16990,46863,16943,47233, 1011,47232,35780,46863, -29644,46863,43412,46863,15628,46863, 9044,46863, 264,47247, 265,47246, -47249,47251, 264,47246, 265,47247,47255,47257,12484,46863,12486,46863, -12488,46863,12551,46863,12387,47266,12547,46863,12633,46863,12507,46863, -12497,46863,12501,46863,13381,46863,13169,46863,13135,47282, 4893,46863, - 4871,47286,12563,46863,27255,46863, 483,47292, 9287,46863, 483,47296, -13119,46863, 264,47300,13143,47303, 264,47301,13169,47307, 4863,46863, - 264,47310, 4879,47313, 264,47311, 4893,47317, 7315,46863, 413,47320, - 264,47320, 264,47321, 265,47320,47327,47329, 265,47321,47325,47333, -14653,46863, 375,47336,16875,46863,12504,46863,19478,46863,35766,46863, -20044,46863,36534,46863,12566,46863,12391,47353,33338,46863,34447,47357, -45866,46863,46599,47361,25545,46863,40675,46863, 1413,46863, 922,46863, - 1281,46863, 247,46863,36303,46863,38299,47377,37897,47377,36335,47377, -35893,47377,20035,46863, 11,47387, 11,47386,36527,46863, 587,47392, -24545,46863, 483,47396,35761,46863, 903,47400,19475,46863, 1011,47404, - 1086,46863, 934,46863, 1216,46863,17049,47412,16937,47412, 9766,46863, - 5519,46863, 8389,46863, 8861,46863, 3345,47424,12377,47424, 8337,46863, - 375,47430, 8374,46863, 8365,46863,20169,46863,36921,46863, 8453,46863, - 4863,47443,13119,47443, 9072,46863, 9105,46863, 305,46863,12377,47452, - 9731,46863, 483,47456, 8997,46863,15503,47460, 265,47460, 265,47461, - 257,47460, 264,47469, 265,47468,47471,47473, 264,47468, 265,47469, -47477,47479, 375,47460,15029,46863,12377,47484, 375,46863,27021,47488, -30091,47488, 9195,47488, 8757,47488, 4213,47488,14653,47488,20103,47488, -36773,47488, 8337,47488, 8997,47488, 241,47488, 6578,46863, 394,46863, - 828,46863, 128,46863, 299,46863, 705,46863, 101,46863,28715,46863, -21315,47526, 165,46863, 903,47530,43215,46863,38057,47534, 1505,46863, - 1011,47538,30091,46863, 375,47542, 113,46863, 25,47546, 9,47546, - 803,46863, 483,47552, 518,46863, 504,46863, 508,46863, 645,46863, - 623,46863, 659,46863, 510,46863, 241,47568, 506,46863, 9,47572, - 244,46863, 483,47576, 265,46863, 8997,47580, 5041,47580,17009,47580, - 8861,47581, 241,46863, 265,47591, 6515,47590, 375,47590, 510,47590, - 483,47590, 9,47600, 9,47590, 483,47604, 1011,46863,16990,47608, -17070,47608,17379,47608,40617,47608,16937,47608, 903,47618, 1505,47608, -17049,47608, 903,47624,21315,47608,19475,47608, 587,47608, 903,47608, -16937,47634,17049,47634, 903,46863,16937,47641,16977,47643,17082,47640, -16972,47640,17175,47640,32805,47640,36349,47640,17049,47640, 1011,47656, - 165,47640,16937,47640,16943,47663, 1011,47662,38057,47640,35761,47640, - 483,47640, 11,47640, 1011,47640,17049,47676,16937,47676,10527,47640, - 4727,47640, 6515,47640, 6564,46863, 6685,46863,35187,47690, 11,47691, - 6515,46863, 241,47696, 903,47696, 587,47697,10761,46863,10592,46863, - 4738,46863,13857,46863, 483,47710,10527,46863, 903,47714, 9,47714, - 3345,46863, 413,47720, 8861,47720, 1369,47721, 341,47721, 3747,46863, - 1369,47731, 3689,46863, 1369,47735,17000,46863,17090,46863, 2691,46863, - 2777,46863, 2793,46863, 2831,46863, 6486,46863, 4415,46863,10493,46863, -13941,46863,10901,46863, 4727,46863, 903,47760, 9,47760, 4819,46863, - 483,47766, 6703,46863, 6623,46863, 5759,46863, 7823,46863, 7813,46863, - 7761,46863, 7705,46863, 7735,46863, 7727,46863,13904,46863,10600,46863, - 4742,46863, 4822,46863, 2875,46863, 2865,46863, 2961,46863, 2949,46863, - 2919,46863, 3645,46863, 3609,46863, 3467,46863,17102,46863,17104,46863, - 1369,47815, 5041,46863, 265,47819, 265,47818, 4919,46863, 483,47824, -17100,46863,17009,46863, 265,47831, 265,47830,17099,46863, 483,47836, - 4920,46863, 6441,46863, 483,47842,17123,46863, 3353,46863, 3691,46863, -10154,46863, 3777,46863, 2847,46863, 2881,46863, 2933,46863, 2929,46863, - 2967,46863, 5271,46863, 4923,46863, 3355,46863, 3031,46863, 3121,46863, -20819,46863,37537,46863,20952,46863,37748,46863,20885,46863, 483,47884, -37663,46863, 9,47888,11529,46863, 1010,46862,23717,47895,24522,47895, -24447,47895,23939,47900,23939,47895,24447,47904,22956,47895,23651,47909, -21605,47895, 17,47913,23939,47915, 17,47912,23651,47919, 17,47895, -21605,47923,24447,47925,21605,47922,23651,47929, 264,46862,47135,47933, -47823,47933,47835,47933,47137,47933,47587,47933,47585,47933,47465,47933, -47583,47933,47019,47933,47581,47933,17009,47953, 5041,47953, 8997,47953, - 265,46862,47063,47961,47065,47961,47055,47961, 8997,47961, 5041,47961, -17009,47961, 8495,47961, 241,47961, 241,46862, 240,46863, 265,47981, - 1,47982, 0,47982, 5521,47983, 5520,47982,47989,47991, 5520,47983, - 5521,47982,47995,47997, 0,47983,47985,48001, 1,47983,47987,48005, - 264,46863,15193,48009,15475,48009,15579,48009,13119,48008,13143,48017, - 4863,48008, 4879,48021,47972,48009,47970,48009,47821,48009,47833,48009, -13507,48009,47968,48009,47467,48009, 53,48009, 1471,48009, 8997,48009, -47961,48042, 253,48009,17009,48009,47961,48048, 5041,48009,47961,48052, -15437,48009, 8997,48057,20501,48009,47961,48009,17009,48062, 5041,48062, - 8997,48062,20219,48009,37019,48009,19513,48009,35843,48009,20697,48009, -37377,48009,13119,48009,13135,48083, 4863,48009, 4871,48087,18967,48009, - 483,48091, 1369,48009, 9875,48009, 8401,48009, 9955,48009,10273,48009, - 4137,48009, 3863,48009, 4063,48009, 241,48009, 413,46863, 3345,48112, - 7315,48112,17049,48112,16937,48112,12377,46863, 8861,48122,15029,48122, - 305,48122, 713,48122, 25,48122, 587,48123,12387,48135, 11,48123, - 257,48123, 253,48123, 1471,48123, 53,48123, 1369,48123, 257,48122, - 587,48122,12391,48153, 257,46863, 9136,48156, 9137,48156, 264,48157, -48159,48163,17827,48156,48163,48167, 413,48156, 1,48170, 264,48156, - 8997,48175, 241,48175, 1,48179, 265,48157, 8997,48183,48175,48184, - 4425,48183,48161,48183,48176,48183,48175,48183, 8997,48194, 5579,48183, -17873,48183, 1791,48183,48173,48183,48181,48183, 265,48156, 8997,48208, -48163,48211,48163,48209, 8997,48215, 8997,48156, 265,48218,48163,48221, - 265,48219,48175,48225,12377,48156,36925,46863,20177,46863, 8383,46863, - 8385,46863, 88,46863, 11,48239,37409,48239, 566,46863,27021,48245, - 9195,48245,20501,48245, 9377,48245, 9875,48245, 587,48245,20763,48245, - 653,46863, 11,48261, 289,46863, 587,48265,36349,46863, 903,48268, -40617,46863, 1011,48272, 66,46863, 33,48277,20217,46863,37017,46863, -37845,46863,38057,46863, 903,48286,43215,48286, 155,48286,21315,46863, - 483,48294, 1011,48294,28715,48294, 1347,48294, 1347,46863,21315,48304, - 155,46863,38057,48308,21378,46863,38134,46863,20103,46863, 375,48316, -36773,46863, 375,48320, 713,46863,12377,48324, 25,46863, 113,48328, -12377,48328,26625,46863, 483,48334,10107,46863,38056,48338,38056,48339, -38057,48338,48343,48345,38057,48339,48341,48349, 3,48339, 3,48338, - 9195,46863, 375,48356,27021,46863, 375,48360, 19,46863, 59,48365, -32805,46863, 4,48368,34447,48371, 903,48368, 9,48368, 4,48369, -33871,48379, 11,48368,34447,48383,45639,46863, 2,48386,46599,48389, - 2,48387,46169,48393, 587,48386,46599,48397,36256,46863,35187,46863, - 6685,48402, 9,48402, 483,46863,27255,48408,26625,48408,24545,48408, - 9287,48408,21315,48408, 903,48408, 9731,48408,13857,48408, 803,48408, - 244,48408,17049,48408, 6441,48408, 4819,48408,17099,48408, 4919,48408, - 9,48408, 241,48440, 241,48408, 9,48444,20885,48408, 5,48408, -27021,48451, 9195,48451,20501,48451, 9377,48451, 9875,48451, 587,48451, -20763,48451, 9,46863,32805,48466,10527,48466, 113,48466, 506,48466, -16937,48466, 4727,48466, 483,48466, 241,48480, 241,48466, 483,48484, -37663,48466, 265,48467, 11,48491, 3,48466, 11,48495,37409,48495, -35187,48466,19917,46863,18967,48503, 5,48504, 5,48505,21036,48503, -21037,48503, 4,48503,48509,48515, 5,48503,18967,48518, 4,48502, -48521,48523,48507,48523,48511,48523, 5,48502,48513,48531, 587,46863, -12377,48535,12551,48537,45639,48535,46275,48541,12377,48534,12391,48545, -36527,48534,45639,48534,46599,48551, 265,48535,17827,48555, 1011,48534, - 11,46863,32805,48561,34003,48563,20035,48560,32805,48560,34447,48569, - 903,48560, 1275,48561, 9,48575, 3,48560, 33,48579, 3,48561, - 113,48583,16937,46863, 1216,48586, 413,48586,21036,48586,21037,48586, -21036,48587,48595,48597,21037,48587,48593,48601, 903,48587,16941,48605, - 1011,48586, 903,48608, 903,48586,16943,48613, 1011,48612, 9,48586, -17049,46863, 1216,48620, 413,48620, 903,48620, 1011,48626, 1011,48620, - 903,48630, 483,48620, 2,48620, 3,48620, 1369,48639, 2,48621, - 3,48621, 483,48645, 2,46862, 6,48649, 4,48651, 5,48649, - 9,48655,21604,48657,21604,48656,21605,48657,48661,48663,21605,48656, -48659,48667, 5,48648,23717,48671,24522,48671,24447,48671,23939,48676, -23939,48671,24447,48680,22956,48671,23651,48685, 17,48671,21605,48689, -24447,48691,21605,48688,23651,48695,21605,48671, 17,48699,23939,48701, - 17,48698,23651,48705, 19,48649, 12,48649, 9,48649, 11,48712, - 11,48649, 9,48716,21605,48649,48652,48720,48653,48721,48723,48725, -48653,48720,48652,48721,48729,48731, 3,46862, 5,48735, 4,46862, -19975,48739,19365,48739,19221,48739,19917,48739,10107,48747, 587,48739, - 5,46862,25451,48753,42283,48753,19739,48753, 0,48753, 3,48761, -25380,48753, 7971,48765,42155,48765, 164,48753,48353,48771,20763,48753, - 1011,48775, 1010,48774,48777,48779, 1010,48775, 1011,48774,48783,48785, - 2,48753, 17,48788,48353,48791, 2,48752,23717,48795,24522,48795, -23939,48795,24447,48800,24447,48795,23939,48804,22956,48795,23651,48809, -21605,48795, 17,48813,23939,48815, 17,48812,23651,48819, 17,48795, -21605,48823,24447,48825,21605,48822,23651,48829, 1369,48753,21605,48832, - 7971,48835,42155,48835,21605,48753, 1369,48840,42155,48843, 7971,48843, - 17,48753,37844,48848,48762,48848,48763,48849,48853,48855,37844,48849, -48763,48848,48762,48849,48861,48863,37845,48848,48859,48867,37845,48849, -48851,48871, 2,48849,48355,48875,47853,48875, 2,48848,48353,48881, - 5,46863, 374,48884, 374,48885, 375,48884,48889,48891,19381,48885, -19380,48884,48895,48897,19381,48884,19380,48885,48901,48903,20812,48884, -20813,48884,20812,48885,48909,48911, 1197,48885,21604,48915,21604,48914, -21605,48915,48919,48921,21605,48914,48917,48925, 375,48885,48887,48929, -20813,48885,48907,48933,20501,48885, 1011,48937,27021,48885, 483,48941, - 9195,48885, 483,48945, 9377,48885, 483,48949, 9875,48885, 1011,48953, - 587,48885, 483,48957, 1369,48885, 1011,48961,38057,48961,20763,48885, - 483,48967, 903,48885, 375,48971, 483,48884,27021,48975, 9195,48975, -20501,48975, 9377,48975, 9875,48975, 587,48975,20763,48975,18967,48885, - 483,48991, 165,48991, 2,48884,48961,48997, 3,48884,13118,49000, - 4862,49000,13118,49001,13119,49000,49007,49009, 4863,49000, 4862,49001, -49013,49015,15193,49001,15475,49001,15579,49001,13507,49001,20501,49001, - 253,49001,15437,49001, 8997,49031,20219,49001,37019,49001,19513,49001, -35843,49001,20697,49001,37377,49001,13119,49001,49003,49047, 4863,49001, -49005,49051, 241,49001, 9875,49001, 53,49001, 1471,49001, 8401,49001, - 9955,49001,10273,49001, 4137,49001, 3863,49001, 4063,49001, 1369,49001, -18967,49001, 483,49077, 2,48885, 1,49081, 7,49082,49000,49084, -49001,49085,49087,49089,49000,49085,49001,49084,49093,49095, 7,49081, - 1,49098,49000,49100,49001,49101,49103,49105,49000,49101,49001,49100, -49109,49111, 1,49080, 7,49115, 7,49080,49001,49119, 0,49080, -49083,49123, 7,49125,49001,49127, 0,49081,49116,49131,49001,49133, - 7,49131,49115,49136,49001,49139,49001,49137,49115,49143,49115,49131, - 7,49146,49001,49149,49001,49081, 3,48885,37357,49155, 165,49155, -10257,49155, 483,49155,35187,48885, 375,49165, 9,48885, 1,49168, - 3,49171,46863,49172,46863,49171, 3,49176, 3,49177,37845,49169, -37845,49168,37844,49168,49183,49187,37844,49169,49185,49191, 2,49168, -49175,49195,49179,49195, 2,49169,49181,49201, 3,46863,49171,49204, -49195,49207, 6,49205, 11,49211, 0,49205, 0,49204,40704,49217, -38305,49217, 9,49220, 9,49217,38305,49224, 6,49204,40705,49229, -49217,49231,49219,49229,18967,49229, 4,49236, 5,49236, 5,49237, - 4,49237,46863,49244,49241,49247,46863,49237, 4,49250,49241,49253, - 4,49251,49243,49257,49227,49229, 17,49229,49223,49229,37325,49205, - 903,49267,10107,49204,48875,49271,10219,49205, 903,49275,17049,49204, - 1369,49279, 11,49205, 25,49283, 9,49283, 17,49205, 903,49289, -21315,49289,37409,49205, 9,49295, 1011,49205, 375,49299, 9,49204, - 11,49303,37409,49303, 11,49204, 33,49309,35187,49205, 1505,49313, - 4,49204,49289,49317, 5,49204,13118,49320, 4862,49320,13118,49321, -13119,49320,49327,49329, 4863,49320, 4862,49321,49333,49335,15193,49321, -15475,49321,15579,49321,13507,49321,20501,49321, 253,49321,15437,49321, - 8997,49351,37019,49321,20219,49321,35843,49321,19513,49321,37377,49321, -20697,49321,13119,49321,49323,49367, 4863,49321,49325,49371, 241,49321, - 9875,49321, 1471,49321, 53,49321, 8401,49321,10273,49321, 9955,49321, - 4137,49321, 4063,49321, 3863,49321, 1369,49321,18967,49321, 483,49397, - 4,49205, 1,49401, 7,49402,49320,49404,49321,49405,49407,49409, -49320,49405,49321,49404,49413,49415, 7,49401, 1,49418,49320,49420, -49321,49421,49423,49425,49320,49421,49321,49420,49429,49431, 1,49400, - 7,49435, 7,49400,49321,49439, 0,49400,49403,49443, 7,49445, -49321,49447, 0,49401,49436,49451,49321,49453, 7,49451,49435,49456, -49321,49459,49321,49457,49435,49463,49435,49451, 7,49466,49321,49469, -49321,49401, 5,49205,20645,49475, 1505,49475, 9935,49475,18967,49205, - 7,49483, 4,49484, 4,49485, 16,49483, 17,49483, 4,49482, -49493,49495, 5,49482,49487,49499,49491,49499, 4,49483, 7,49504, -49499,49507, 5,49483,49489,49511, 2,46863, 6,49515, 17,49517, -35187,49519, 0,49515,38305,49523, 15,49525, 0,49514,36545,49529, -49521,49529, 15,49529, 6,49514,49531,49537,36544,49537,49529,49541, -49527,49537, 11,49537,35187,49546,49529,49549,35187,49537, 11,49552, -49529,49555,45639,49514,46599,49559,45639,49515,46275,49563,17125,49515, - 16,49567, 16,49566, 17,49567,49571,49573, 17,49566,49569,49577, -17049,49514, 4,49514, 7,49583, 1,49585, 265,49583, 1,49588, - 0,49588,49587,49589,49586,49588,49595,49597,49587,49588,49586,49589, -49601,49603, 0,49589,49591,49607, 1,49589,49593,49611, 4,49515, - 1011,49615, 1,49617, 0,49617, 1,49616,49621,49623, 0,49616, -49619,49627, 4,46863,27857,49630,27895,49633,19815,49630,19857,49637, -49237,49631,49239,49641,49237,49630,49241,49645,32805,49630,34447,49649, -32805,49631,34003,49653,27857,49631,27879,49657,19815,49631,19849,49661, - 2,49630, 7,49665, 1,49667, 265,49665, 1,49670, 0,49670, -49669,49671,49668,49670,49677,49679,49669,49670,49668,49671,49683,49685, - 0,49671,49673,49689, 1,49671,49675,49693, 2,49631, 903,49697, - 1,49699, 0,49699, 1,49698,49703,49705, 0,49698,49701,49709, - 1, 7, 377,49713,48110,49712,48111,49712,49152,49712,49472,49712, -49153,49712,49473,49712,49374,49712,49054,49712,49375,49712,49055,49712, - 704,49712, 100,49712,26502,49712,41376,49712, 8808,49712,47622,49713, -47660,49713,47146,49713,47148,49713,49059,49713,49379,49713,49158,49713, -49478,49713,49061,49713,49381,49713,48998,49713,49318,49713,47224,49713, -47226,49713,48041,49713,48039,49713,47058,49713,47060,49713,47220,49713, -47222,49713,48047,49713,47056,49713,47442,49713,49349,49713,49029,49713, -49121,49713,49441,49713,47628,49713,47668,49713,48962,49713,49290,49713, -22798,49713,39074,49713,31498,49713,44616,49713,31392,49713,44494,49713, -47540,49713,47532,49713,31794,49713,44858,49713,48298,49713,48288,49713, -31924,49713,44994,49713, 8652,49713, 8535,49713,13252,49713,43989,49712, -41417,49843,30655,49712,26219,49847,26503,49712,41377,49712, 8809,49712, -26547,49712,26219,49857,41835,49712,41417,49861, 273,49712,12897,49865, - 8813,49712, 8647,49869, 376,49713, 705,49712, 101,49712, 803,49712, - 483,49879,30091,49712,26219,49883, 113,49712, 9,49887,43503,49712, -41417,49891,43215,49712, 483,49895,43214,49712, 112,49712, 802,49712, -49320,49712,49401,49905, 241,49905,49000,49712,49081,49911, 241,49911, -49081,49712,49001,49916,49001,49917,49911,49921,49401,49712,49321,49924, -49321,49925,49905,49929,49001,49712,49081,49932, 241,49932,49321,49712, -49401,49938, 241,49938, 414,49713,18391,49945, 420,49713,18391,49949, - 449,49713,18391,49953, 8808,49713,49855,49957, 8453,49713,46863,49960, -20239,49713,46863,49964,37095,49713,46863,49968,47976,49713,47593,49713, -26502,49713,49851,49977,31921,49713,47592,49713, 8495,49983, 828,49713, -49903,49987, 128,49713,49901,49991, 705,49713,49737,49995, 101,49713, -49739,49999,47977,49713, 8495,50003,47488,49713,48122,49713,48480,49713, -48440,49713,47568,49713, 1344,49713, 1482,49713, 64,49713, 1484,49713, - 336,49713, 1480,49713, 254,49713, 1342,49713, 338,49713, 1123,49713, - 931,49713, 665,49713, 1417,49713, 1429,49713, 1301,49713, 1127,49713, - 941,49713, 523,49713, 1283,49713, 939,49713, 1103,49713, 171,49713, - 1525,49713, 407,49713, 1517,49713, 949,49713, 280,49713, 1476,49713, - 272,49713, 1017,49713, 1077,49713, 1047,49713, 1113,49713, 1245,49713, - 1237,49713, 501,49713, 433,49713, 929,49713, 591,49713, 915,49713, - 681,49713, 1555,49713, 911,49713, 1545,49713, 855,49713,41376,49713, -49853,50107, 4900,49713,14622,49713,48113,49713, 8997,50115, 1382,49713, - 695,49713,48286,49713, 903,50122,48294,49713, 1011,50126,26503,49713, -49741,50131,47530,49713, 903,50134,47538,49713, 1011,50138,49289,49713, -49317,50142, 903,50142,48961,49713,48997,50148, 1011,50148,21522,49713, -46863,50154,38266,49713,46863,50158, 394,49713, 299,49713,31792,49713, - 903,50166,44856,49713, 1011,50170,22789,49713, 903,50174,39065,49713, - 1011,50178, 1386,49713, 545,49713,41377,49713,49743,50187, 413,49712, - 8647,50191,18062,50191,17993,50191, 251,50196, 251,50191,17993,50200, -46863,50191, 412,49712,48008,49713,50207,50209,49717,50209, 341,50209, -40381,49713, 17,50217, 913,49713, 483,50221, 289,49713, 8809,49713, -49745,50227,49000,49713,49935,50231,49919,50231,49721,50231,49731,50231, -49937,50231,49933,50231,49081,50243, 241,50243,49320,49713,49941,50249, -49927,50249,49723,50249,49729,50249,49943,50249,49939,50249,49401,50261, - 241,50261, 1374,49713, 8672,49713,12534,49713,12921,49713, 264,50273, - 265,50272,50275,50277, 264,50272, 265,50273,50281,50283, 8605,49713, -26097,49713,41299,49713,26277,49713,41479,49713,26104,49713,41314,49713, - 1477,49713,46863,50300, 281,49713,46863,50304, 1516,49713,46863,50308, - 948,49713,46863,50312,44988,49713, 903,50316,31920,49713, 1011,50320, -43293,49713,49895,50325,15156,49713, 264,50329, 265,50328,50331,50333, - 264,50328, 265,50329,50337,50339, 8916,49713,14623,49713, 8495,50345, - 4901,49713, 8495,50349,14611,49713, 241,50352, 4899,49713, 241,50356, -15219,49713, 412,50360, 413,50361,50363,50365, 412,50361, 413,50360, -50369,50371, 5119,49713, 412,50374, 413,50375,50377,50379, 412,50375, - 413,50374,50383,50385,13177,49713, 413,50388, 264,50388, 264,50389, - 265,50388,50395,50397, 265,50389,50393,50401, 5313,49713,12377,50404, -47591,49713, 265,50409, 8861,50411, 265,50408, 8495,50415,47641,49713, -43292,49713,49899,50421,15158,49713,39228,49713,23012,49713,40676,49713, -25546,49713, 500,49713,18391,50435, 432,49713,18391,50439, 1244,49713, -18617,50443, 1236,49713,18617,50447, 1109,49713, 903,50451, 1412,49713, - 305,50455,44832,49713,31770,49713,25545,49713, 9,50462,40675,49713, - 483,50466, 935,49713, 483,50471, 1087,49713, 9,50475, 1413,49713, - 295,49713, 1290,49713, 903,50483, 1304,49713, 9,50487,48009,49713, -50191,50491,49719,50491, 241,50491,22957,49713, 903,50498,39205,49713, - 1011,50502,47608,49713, 1505,50506,21315,50506,47640,49713, 165,50512, -38057,50512, 510,49713,46863,50518, 922,49713, 1108,49713, 1280,49713, - 9,50527, 246,49713, 483,50531, 412,49713,47460,50535, 483,50535, - 9,50535, 8997,50535,46863,50542,46863,50535, 8997,50546, 1216,49713, -44243,50550,31103,50550, 483,50550,18617,50557, 9,50550,18617,50561, - 8677,49713, 305,49713, 241,50567,16163,50567, 8647,50566, 8495,49713, - 257,50574, 1141,49713,16531,50579, 253,49713, 59,50582, 1325,50582, - 331,50582, 265,50582, 8634,49713, 8611,49713,41349,49713,26127,49713, - 273,49713,12705,50601,13673,50601,18391,50601, 2923,50601,46863,50600, - 331,49713, 53,50612, 1471,50612, 253,50612, 1369,50612, 8861,49713, - 241,50623, 375,50625, 375,50622, 251,49713, 413,50631,17993,50633, - 413,50630,18391,50637,15029,50630, 264,50641, 265,50640,50643,50645, - 264,50640, 265,50641,50649,50651,39204,49713, 257,49713, 265,50657, -26625,50657,25793,50657,41019,50657, 8495,50657, 9731,50657,25793,50656, -41019,50656, 8495,50656, 265,50656, 4863,50677,12377,49713,46863,50680, - 5313,50680, 341,49713, 241,50687, 298,49713, 4863,50691, 704,49713, -49875,50695, 9195,50695, 100,49713,49877,50701, 395,49713, 829,49713, -49879,50707, 9195,50707, 129,49713,49887,50713, 89,49713,48884,50716, -48884,50717,48885,50717,50719,50723,48885,50716,50721,50727, 11,50716, - 567,49713,42155,50733,41941,50733, 7971,50733, 9565,50733, 587,50733, - 9377,50743, 587,50732, 9195,50747,38057,49713,47640,50750,46863,50750, - 903,50754, 903,50750,46863,50758,21315,49713,47608,50762,46863,50762, - 1011,50766, 1011,50762,46863,50770, 628,49713, 1396,49713, 241,50777, - 288,49713, 7971,50781, 265,49713,23584,50785,39564,50785,24355,50785, -39905,50785, 5520,50785, 256,50784,50795,50797, 5521,50785, 256,50785, -50204,50785, 10,50784, 1,50785, 257,50808,50797,50811, 257,50809, -50803,50815, 10,50785,50191,50785,46863,50820,47590,50784,23493,50785, -22807,50826,39489,50785,39085,50830,22807,50785,23493,50834,39085,50785, -39489,50838, 1087,50785, 935,50785,47591,50784, 8495,50847,47590,50785, -50847,50851, 4213,50785, 8757,50785,26415,50785,41653,50785,27377,50785, - 9335,50785,42471,50785, 8109,50785, 4147,50785, 3933,50785, 53,50784, - 1471,50784, 253,50784,47591,50785,50825,50881, 257,50785, 1,50884, -50797,50887,50797,50885, 4827,50885, 305,50785, 8861,50895, 8495,50785, - 331,50899,46863,50785,50191,50902, 241,50902, 241,50785,46863,50908, - 8337,50909,46863,50913, 1369,50784, 305,50917, 11,50785,50807,50921, - 8165,50921, 1369,50921, 241,50784,47460,50929, 483,50929, 9,50929, - 8997,50929,46863,50936,46863,50929, 8997,50940, 257,50784,50801,50945, -50803,50945, 4863,50945, 11,50784,50819,50953, 7971,50953, 1011,49713, -31920,50958,48294,50958,44856,50958,47538,50958,48961,50958,39065,50958, -21315,50958,46863,50972,31103,50958, 903,50976, 1505,50958,46863,50980, -44243,50958, 903,50984,39205,50958, 9,50958, 903,50958,31103,50992, -44243,50992,46863,50958,21315,50998, 1505,50998, 903,49713,44988,51004, -48286,51004,31792,51004,47530,51004,49289,51004,22789,51004,38057,51004, -46863,51018,44243,51004, 1011,51022, 165,51004,46863,51026,31103,51004, - 1011,51030,22957,51004, 483,51004, 1011,51004,44243,51038,31103,51038, -46863,51004,38057,51044, 165,51044, 241,49713,47961,51050, 4899,51050, -14611,51050, 375,51050,12377,51051, 375,51061, 8997,51051, 375,51065, - 265,51065,46863,51069, 1275,51050, 9,51073, 15,51050, 483,51077, - 265,51050,47460,51081, 483,51081, 9,51081, 8997,51081,46863,51088, -46863,51081, 8997,51092, 8647,49713, 413,51096, 305,51097, 11,51097, - 1369,51097, 341,51097, 305,51096,41417,49713, 11,51111, 1369,51111, -26219,49713, 11,51117, 1369,51117,32102,49713,27021,51123,45148,49713, - 11,51127, 1369,51127,31857,49713,44925,49713,32294,49713,45314,49713, -17565,49713,32103,49713, 241,51143, 587,51142,45149,49713, 11,51148, -49317,49713,49289,51152,48997,49713,48961,51156,49001,49713,49912,51161, -49725,51161,49914,51161,49735,51161,49081,51161,49911,51170,49911,51161, -49081,51174, 241,51174, 241,51161,49911,51180,49321,49713,49906,51185, -49727,51185,49908,51185,49733,51185,49401,51185,49905,51194,49905,51185, -49401,51198, 241,51198, 241,51185,49905,51204,49475,49713, 1505,51208, -49155,49713, 165,51212, 240,49712,51059,51217,50163,51217,50165,51217, -51051,51217, 375,51225, 264,49712,49715,51229,50838,51229,50834,51229, -50850,51229,50847,51229,50945,51229,49983,51229,50415,51229,50677,51229, -50691,51229,50496,51229,50003,51229,50906,51229,50910,51229,50345,51229, -50349,51229, 8374,51229, 8389,51229,50705,51229,20152,51229,36898,51229, -20201,51229,36979,51229,50902,51229, 241,51276,50908,51229,46863,51280, -50491,51229, 241,51284,47590,51229,50785,51288,22807,51229,50785,51292, -39085,51229,50785,51296,26219,51229,41417,51229,14524,51229,35690,51229, -50733,51229,37519,51229,50781,51229,50953,51229,50455,51229,50917,51229, -19396,51229, 8647,51229,20103,51229, 375,51324,36773,51229, 375,51328, - 8337,51229, 375,51332,50785,51229,39085,51336,22807,51336,47590,51336, -46863,51336, 241,51344, 241,51336,46863,51348,47488,51229,47961,51229, - 9,51229,18967,51356, 483,51229,35187,51229, 375,51362,18967,51229, - 9,51366,46863,51229,50908,51370,50785,51370, 241,51374, 241,51370, -50785,51378, 375,51370, 241,51229,50491,51384,50902,51384,50785,51384, -46863,51390,46863,51384,50785,51394, 375,51229, 8337,51398,20103,51398, -36773,51398,14315,51398,35187,51398,46863,51398,14315,51229, 375,51412, - 4899,51229,14611,51229, 1010,49712, 3867,51421, 8277,51421, 4067,51421, - 3997,51421, 8953,51421, 9459,51421, 902,49712,50321,51435,51031,51435, -24265,51435,28233,51435,29077,51435,51005,51435,31103,51447,19559,51435, - 4283,51435, 9673,51435, 4279,51435, 3807,51435,20361,51435,20713,51435, - 9967,51435, 8251,51435,47961,49713, 241,51468,47979,49713, 412,51472, - 413,51473,51475,51477, 412,51473, 413,51472,51481,51483, 240,49713, - 340,51487,51398,51487,51418,51487,51416,51487,51354,51487,47974,51487, -47589,51487, 8590,51487,12537,51487,14620,51487, 375,51487,51229,51508, - 7,51487, 265,51512, 265,51513,51229,51517,47580,51487, 8861,51521, -47961,51487,51229,51524, 8495,51524,51229,51487, 375,51530,14611,51530, - 4899,51530,47961,51530, 8495,51487, 4899,51540,47961,51540,14611,51540, -14611,51487,51229,51548, 8495,51548, 4899,51487,51229,51554, 8495,51554, -46863,51487, 265,51560, 8861,51563, 265,51561, 8495,51567,51229,51567, - 265,51487, 7,51572,15309,51573,15308,51572,51577,51579,15308,51573, -15309,51572,51583,51585,46863,51572, 8861,51589, 902,49713,31103,51593, -43053,51593,46863,51593, 1010,49713, 1505,51601, 918,51601, 9,51601, - 903,51606, 903,51601, 9,51610, 265,49712,49873,51615,50165,51615, -51059,51615,51057,51615,51055,51615,51053,51615,49975,51615,49973,51615, -50113,51615,50111,51615,50163,51615,51471,51615,50355,51615,50359,51615, -50209,51615, 241,51645, 8948,51615,50225,51615,50479,51615, 331,51615, - 8861,51654, 8861,51615, 331,51658, 4827,51615,15269,51615,51051,51615, - 375,51667,14611,51667, 4899,51667,47961,51667, 241,51614,50209,51677, - 241,49712,18300,51681, 8605,51681, 8916,51681,50945,51681,49321,51680, -50249,51691,49001,51680,50231,51695,50705,51681, 8374,51681,51508,51681, -50691,51681,47443,51681, 8389,51681,50677,51681,51517,51681, 8861,51681, - 375,51714,26219,51681,41417,51681, 305,51681,48009,51681,51229,51725, - 8647,51681, 8452,51681,46863,51731, 713,51681, 25,51681,18257,51681, - 375,51738, 8337,51681, 375,51742, 265,51742,46863,51747, 375,51681, -18257,51750, 8861,51750, 8337,51750,51487,51750,51487,51681, 375,51760, - 265,51680,50209,51765,49321,51681,49905,51769,49001,51681,49911,51773, - 265,51681,51370,51777,51229,51777,46863,51780,46863,51777,51229,51784, - 8337,51776,46863,51789,46863,51681, 264,51792,51765,51795, 264,51793, -51777,51799, 264,49713,51489,51803,51515,51803,51575,51803,51521,51803, -50411,51803,50659,51803,51563,51803, 8471,51803, 8397,51803, 8371,51803, -20149,51803,36887,51803,20211,51803,37009,51803,20247,51803,37103,51803, -51589,51803,50207,51803,46863,51839,51765,51803,46863,51843,51677,51803, -46863,51847,36773,51803,46863,51851,20103,51803,46863,51855, 8337,51803, -46863,51859, 4613,51803,12571,51803,36539,51803,37595,51803,36049,51803, -47581,51803,51487,51873,51615,51803,39085,51877,22807,51877,47590,51877, -46863,51877, 241,51884, 241,51877,46863,51888,46863,51802,51765,51893, -51677,51893,50207,51893,51615,51893, 241,51901, 341,51893, 1369,51803, - 341,51803,51487,51909, 8337,51909,20103,51909,36773,51909,35187,51909, -14315,51909,46863,51909,12377,51803, 375,51925, 1011,49712,26219,51929, -41417,51929, 8647,51929, 903,49712,49981,51937,51594,51937, 375,51937, -31103,51937,51593,51944,51593,51937,31103,51948,15269,51937, 4827,51937, - 1217,49713, 483,51957, 9,51957, 413,49713, 8647,51962,13177,51962, - 251,51962,18391,51969, 375,51962,18391,51973,44243,51962,31103,51962, -18391,51963, 251,51981, 483,51962,18391,51985, 9,51962,18391,51989, - 375,49713, 5,51992,51615,51995, 413,51993,17993,51999, 413,51992, -18391,52003, 241,51993,51487,52007,46863,51992, 241,51992,51217,52013, -51615,52013, 8861,51992,12377,51993,51487,52021,15029,51992,14315,49713, - 341,52027,51487,52029,15029,49713, 266,52032, 267,52032, 264,52033, -52035,52039, 465,52032,52039,52043, 413,52032, 6,52046, 264,52032, - 251,52051, 241,52051, 6,52055, 265,52033, 251,52059,52051,52060, - 8841,52059,52037,52059,52052,52059,52051,52059, 251,52070,15363,52059, -15055,52059,15061,52059,52049,52059,52057,52059, 265,52032, 251,52084, -52039,52087,52039,52085, 251,52091, 251,52032, 265,52094,52039,52097, - 265,52095,52051,52101, 375,52032, 8639,49713, 8643,49713,26217,49713, -41415,49713, 164,49713,51593,52115, 903,52115, 1504,49713,51601,52121, - 144,49713, 113,52125, 802,49713,49880,52129,49879,52129, 483,52132, - 9366,52129, 9195,52129, 483,52138, 483,52129,49879,52142, 9195,52142, -31103,52129, 112,49713,49888,52151,49887,52151, 9,52154, 9,52151, -49887,52158,44243,52151, 1486,49713, 803,52165,43214,49713,49896,52169, -49895,52169, 483,52172, 483,52169,49895,52176, 1073,49713, 903,52181, - 525,49713, 903,52185, 669,49713, 483,52189, 566,49713,51929,52193, -51615,52193,10107,52193,21036,49713, 17,52201, 88,49713,37611,52205, -36083,52205,38155,52205,35927,52205, 1346,49713, 1505,52215, 154,49713, - 483,52219,26329,49713,41557,49713, 165,49713,49155,52226,47640,52226, -46863,52226, 903,52232, 903,52226,46863,52236,43215,52226, 1505,49713, -49475,52242,47608,52242,46863,52242, 1011,52248, 1011,52242,46863,52252, -28715,52242, 803,49713,49903,52259, 483,52261, 483,52258,49903,52265, - 113,49713,49901,52269, 9,52271, 9,52268,49901,52275,28715,49713, - 1505,52278,43215,49713,49899,52283, 483,52285, 483,52282,49899,52289, - 165,52282,29028,49713,43318,49713,25793,49713, 257,52298, 713,49713, - 241,52303,16163,52303,41019,49713, 257,52308, 25,49713, 241,52313, -16163,52313, 1447,49713,16531,52319, 33,49713,16531,52323, 1471,49713, - 59,52326, 1325,52326, 331,52326, 265,52326, 53,49713, 1325,52336, - 59,52336, 331,52336, 265,52336, 1325,49713, 53,52346, 1471,52346, - 253,52346, 1369,52346, 59,49713, 1471,52356, 53,52356, 253,52356, - 1369,52356,48466,49713, 483,52366,48408,49713, 9,52370, 843,49713, - 9,52375, 1530,49713, 9,52379,40436,49713, 113,52383, 587,49713, -28714,52387,36212,52387,30091,52387, 567,52386, 9195,52395, 11,52386, -32103,52386,35187,52387, 241,52402, 241,52387,35187,52406, 4,52386, - 9366,52411, 9195,52411, 483,52414, 483,52411, 9195,52418,31103,52411, - 5,52387,21605,52424, 9195,52425,27021,52425,21605,52387, 11,52433, - 5,52432, 11,49713,32805,52439,19888,52439,19913,52439, 265,52439, -51803,52447,43503,52439, 1275,52438, 9,52453, 89,52438, 587,52438, - 265,52438,51229,52461, 7971,52461,45149,52438,18967,52439, 241,52468, - 241,52439,18967,52472, 2,52438, 9,52477,44243,52477, 3,52439, - 7971,52483,42155,52483, 2,52439,52205,52489,38305,52439, 265,52493, -38305,52438, 113,52497, 1369,49713, 331,52500, 59,52500,40674,52501, -38305,52501, 265,52509, 241,52508, 241,52501,38305,52514, 1325,52500, - 265,52500,51229,52521, 305,52521, 17,52500, 241,52527,38305,52500, -35187,52501, 265,52501, 331,52535,51803,52535, 4,52500,51601,52541, - 5,52500, 803,52545, 5,52501, 959,52549, 47,52549, 759,52549, - 4,52501, 1275,52500, 9,52559, 17,49713, 1275,52562, 903,52565, - 1369,52562, 241,52569, 2,52562, 903,52573,51593,52573, 3,52562, - 113,52579, 3,52563, 1141,52583, 1447,52583, 33,52583, 2,52563, - 265,52591,51803,52591,38305,49713, 1369,52596, 3,52596, 3,52597, - 8165,52603,20501,52603, 9875,52603, 11,52603, 11,52596, 113,52613, - 15,49713, 1010,52617, 1010,52616, 1011,52616,52619,52623, 1011,52617, -52621,52627, 241,52616, 483,52631, 3,52616, 483,52635, 3,52617, - 1369,52639, 1275,49713, 17,52642, 903,52645, 11,52642, 9,52649, - 241,52642, 9,52653, 9,52643, 1369,52657, 11,52657, 5,52642, - 1505,52663, 5,52643, 53,52667, 1471,52667, 253,52667, 1369,52642, - 9,52675,18967,49713, 241,52679, 9,52681, 5,52678, 17,52685, - 5,52679, 9,52689, 483,49713, 803,52693,52129,52695,43215,52693, -52169,52699, 1216,52693,18759,52703, 413,52693,17993,52707, 803,52692, -49903,52711,48466,52692,43215,52692,49899,52717,40675,52692, 1216,52692, -18617,52723, 413,52692,18391,52727,44243,52692,38305,52693,46169,52733, - 9,52692,46863,52736, 903,52692, 5,52692,10107,52743,51929,52743, -51615,52743, 5,52693,46863,52692, 9,52752, 9,49713, 113,52757, -52151,52759, 4,52756, 7,52763, 2,52765, 2,52764, 2,52763, - 7,52770, 1368,52763, 1216,52757,18759,52777, 413,52757,17993,52781, - 113,52756,49901,52785,48408,52756,25545,52756, 1216,52756,18617,52793, - 413,52756,18391,52797,31103,52756, 483,52756,46863,52802, 1011,52756, - 3,52756,52769,52809,52773,52809,37611,52809,38155,52809,35927,52809, -52489,52809,52775,52809, 3,52757,52767,52825,52151,52825,37663,52825, -52477,52825,31103,52825,46863,52756, 483,52836,31103,49713, 1216,52840, - 413,52840,21036,52840,21037,52840,21037,52841,52847,52851, 903,52841, -51593,52855, 1011,52840, 903,52858,21036,52841,52849,52863, 903,52840, -51435,52867, 1011,52866, 9,52840, 5,52840,27021,52875,44243,49713, - 1216,52878, 413,52878, 903,52878, 1011,52884, 1011,52878, 903,52888, - 483,52878, 3,52878, 11,52895, 1369,52895, 3,52879, 483,52901, -49205,49713, 5,52905,48885,49713, 113,52909, 3,52909, 3,49712, -20819,52915,50945,52915,51508,52915,37537,52915,36898,52915,20152,52915, - 8374,52915,50695,52915,50701,52915,50707,52915,50713,52915,50691,52915, -50705,52915,37748,52915,20952,52915,52395,52915,52457,52915,52142,52915, -52158,52915, 8389,52915,50677,52915,51517,52915,50747,52915,50731,52915, -52418,52915,52478,52915,36979,52915,20201,52915,26219,52915,26106,52915, -52129,52915, 483,52976,52411,52915, 483,52980,51123,52915,32103,52915, -52875,52915,31770,52915,42885,52915,20885,52915, 483,52994,40399,52915, -44714,52915, 357,52915, 367,52915, 471,52915, 1249,52915, 8800,52915, - 8647,52915,47488,52915, 8086,52915,19687,52915,19559,52915,20361,52915, - 9673,52915,20713,52915, 9967,52915, 4283,52915, 4279,52915, 3807,52915, - 8251,52915,41746,52915,41417,52915,44832,52915, 9704,52915,20326,52915, -21087,52915,52906,52915,48245,52915,48975,52915,48451,52915,52151,52915, - 9,53058,52477,52915, 9,53062,51487,52915, 375,53066,50785,52915, - 8165,52915, 265,53073, 1447,52915,38305,53077,21127,52915,20843,52915, -52425,52915,37663,52915, 9,53086, 1141,52915,38305,53091, 566,52915, - 567,52915,46863,53097,44243,52915,41941,53100, 483,53100, 375,52915, -51487,53106,20103,53106, 8337,53106,36773,53106,46863,53106,41941,52915, -44243,53118, 33,52915,38305,53123, 9617,52915, 9,53126, 8337,52915, - 375,53130,48884,52915, 1011,52915,48885,52915, 483,53139,52907,52915, - 25,52915, 7971,53144,41019,52915, 11,53148, 305,52915, 8495,52915, - 11,53154,20103,52915, 375,53158,20273,52915, 9,53162, 4,52915, -28411,53167,31103,53167,48408,53167,52905,53167, 483,53167,46863,53176, -20691,53167, 9923,53167,46863,53167, 483,53184, 5,52915,52905,53188, - 17,53189,18967,53193,46863,53188, 483,53188,25793,52915, 11,53200, - 713,52915, 7971,52915, 25,53206,36773,52915, 375,53210, 4,52914, -53191,53215,53051,53215,24265,53215,28233,53215,29077,53215,53135,53215, -53197,53215,53189,53215,52905,53231,46863,53231,19559,53215, 9673,53215, - 4283,53215,20361,53215, 9967,53215,20713,53215, 8251,53215, 4279,53215, - 3807,53215, 5,52914,53143,53255,53174,53255,50785,53255,53139,53255, -53184,53255,50733,53255,19396,53255,53167,53255,52905,53270,46863,53270, - 8647,53255,41417,53255,26219,53255, 9,53255,18967,53282, 483,53255, -18967,53255, 9,53288,52905,53255,53167,53292,46863,53255,53167,53296, - 11,52915,25793,53301,25793,53300, 8495,53301, 8495,53300,18967,53301, -41019,53301,41019,53300,21037,53301, 9,52915,52151,53318,37663,53318, -52477,53318,31103,53318,20273,53318, 9617,53318,52905,52915, 5,53332, -53215,53335, 5,53333,53167,53339, 9875,52915,35187,53343, 241,53343, -46863,52915, 375,53348, 5,53348,53215,53353, 5,53349,53167,53357, - 483,52915,52129,53360,20885,53360,52411,53360,44243,53360, 5,53361, - 5,53360,18967,52915,11731,53375, 113,53375,31103,52915, 9,53380, -20501,52915,35187,53385, 241,53385, 2,49712,52711,53391,52785,53391, -51059,53391,50165,53391,49995,53391,49999,53391,49987,53391,49991,53391, -50163,53391,52013,53391,52265,53391,52275,53391,17609,53391, 4904,53391, -17586,53391,52259,53391, 483,53423, 272,53391, 1476,53391, 280,53391, - 949,53391, 1517,53391,52269,53391, 9,53437, 9484,53391,51803,53391, -51051,53391, 375,53445, 4903,53391, 9,53448,17579,53391, 9,53452, -42991,53391,40039,53391,40685,53391, 1197,53391, 265,53391, 253,53464, - 1471,53464, 53,53464, 53,53391, 265,53472, 253,53391, 265,53476, - 5,53391, 1471,53391, 265,53482, 5,53390, 8953,53487, 9459,53487, - 4067,53487, 3997,53487, 8277,53487, 3867,53487, 11,53391, 9377,53500, - 9,53391, 4903,53504,17579,53504, 9377,53391, 11,53510, 5,53511, - 5,49712,48765,53517,48835,53517,48843,53517,25445,53517,22779,53517, -22243,53517, 7,53517, 2,53531,28063,53517,25299,53517,31598,53517, -53152,53517,50733,53517,35690,53517,37519,53517,50781,53517,52461,53517, -50953,53517, 272,53517, 1476,53517, 280,53517, 949,53517, 1517,53517, - 357,53517, 367,53517, 471,53517, 1249,53517, 9304,53517,53204,53517, -53144,53517,35931,53517,52912,53517,20326,53517,21087,53517,20273,53517, - 9,53586,50785,53517, 1369,53591,53391,53591,25381,53517,48753,53597, -10081,53597, 9704,53517, 53,53517, 265,53604,37899,53517,37617,53517, -52483,53517, 9617,53517, 9,53614, 253,53517, 265,53618,31103,53517, -26625,53622, 375,53517,35187,53626,26625,53517,31103,53630, 1471,53517, - 265,53634, 265,53517, 253,53638, 1471,53638, 53,53638,49204,53517, -49205,53517,52913,53517, 713,53517, 9195,53652,52915,53652,21605,53653, - 305,53517,52915,53660,21605,53661, 2,53517, 8229,53667,52909,53667, -46863,53667, 3,53517,52909,53674,53391,53675, 1369,53675,46863,53674, -52915,53517, 305,53684, 713,53684, 25,53684, 25,53517,52915,53692, -21605,53693, 9195,53517, 713,53698, 2,53516,53677,53703,53581,53703, -53647,53703,53683,53703,53675,53703,52909,53713,46863,53713, 4067,53703, - 3997,53703, 8953,53703, 9459,53703, 8277,53703, 3867,53703, 3,53516, -53651,53731,53670,53731,50785,53731,50733,53731,53649,53731,53672,53731, -19396,53731,53667,53731,52909,53746,46863,53746, 8647,53731,26219,53731, -41417,53731, 483,53731,18967,53731, 9,53760, 9,53731,18967,53764, -52909,53731,53667,53768,46863,53731,53667,53772, 587,53517,35187,53777, - 483,53517,52909,53517, 3,53782,53703,53785, 3,53783,53667,53789, -46863,53517, 3,53792,53703,53795, 3,53793,53667,53799, 9,53517, -20273,53802, 9617,53802,35187,53517, 375,53808, 4,49712,48747,53813, -37279,53813,19981,53813,24601,53813, 7,53813,21605,53823,53071,53813, -52743,53813,52193,53813,50225,53813, 8306,53813, 545,53813, 695,53813, - 1382,53813, 1374,53813, 1386,53813,51906,53813,53442,53813,53199,53813, -53373,53813,53095,53813,51803,53813, 1369,53856,53391,53856, 9992,53813, -20734,53813,19916,53813,48739,53867,37241,53867, 7947,53867,28205,53813, -24613,53813,25551,53813,53189,53813, 483,53881, 33,53813, 9875,53813, - 265,53886, 241,53887,20501,53813, 265,53892, 241,53893, 1141,53813, - 154,53813, 483,53901, 1447,53813, 331,53813, 1369,53906, 265,53813, - 8165,53910, 9875,53910,20501,53910, 1011,53813, 59,53813, 1369,53920, - 3,53813, 8241,53925, 15,53924, 483,53929,53391,53813,51803,53932, - 1325,53813, 1369,53936, 3,53812,24265,53941,28233,53941,29077,53941, - 9673,53941,19559,53941, 4283,53941,20361,53941, 8251,53941, 3807,53941, - 9967,53941,20713,53941, 4279,53941, 1369,53813, 331,53966, 1325,53966, - 59,53966,51803,53966,18967,53813, 1275,53976,48739,53979,37241,53979, - 7947,53979, 113,53977, 1275,53813,18967,53988,48739,53991, 7947,53991, -37241,53991, 8165,53813, 265,53998,46863,53813,38056,54002,38056,54003, -38057,54002,54007,54009,38057,54003,54005,54013, 15,53813, 3,54017, - 1369,54019, 3,54016, 483,54023, 5,49713, 375,54026,51615,54029, - 1368,54027, 7,54027, 2,54034, 2,54035,32805,54027,31103,54041, -20035,54027, 375,54045, 341,54027,18967,54049,12377,54027, 375,54053, -52915,54027,31103,54057,27021,54027,31103,54061,30091,54027,31103,54065, -31103,54026,27021,54069,52915,54069,18967,54027,47608,54075,46863,54075, - 1011,54078, 1011,54075,46863,54082,53924,54027,53825,54087, 483,54087, -51929,54027, 483,54093,51615,54027, 375,54097, 483,54097, 1369,54026, - 803,54103, 483,54026,53813,54107,10107,54107,51929,54107,51615,54107, - 1275,54026, 1505,54117,18967,54026, 17,54121, 1369,54027,51601,54125, - 2,54026,54078,54129,54075,54129,46863,54132,52541,54129, 1505,54129, - 918,54129,52121,54129,54125,54129, 903,54129, 9,54146, 9,54129, - 903,54150,46863,54129,54075,54154, 3,54026,54033,54159,54037,54159, -53966,54159,12571,54159, 4613,54159,51615,54159, 8337,54159,46863,54173, -52591,54159,53932,54159,53391,54159,53813,54180,53813,54159, 1369,54184, -53391,54184,36773,54159,46863,54191,20103,54159,46863,54195, 1369,54159, -53813,54198, 2,54027, 0,54202,54159,54205,46863,54207, 7,54202, -54159,54211, 265,54203, 9,54215,54159,54203, 9,54219,46863,54219, - 3,54027,48286,54225,54039,54225,54150,54225,52573,54225,52115,54225, -38057,54225,46863,54236,53813,54224,53825,54241, 483,54241, 9,54225, -54129,54246, 483,54225,53813,54251,54154,54225,46863,54225,38057,54256, -54129,54256,54129,54225, 9,54262,46863,54262,10107,54027, 483,54269, -53813,54027, 483,54273, 3,54273, 1369,54277,53391,54277, 3,54272, -53825,54283, 483,54283, 17,54027,20273,54289, 9617,54289, 3,49713, -16722,54295,16530,54294,54297,54299,16723,54295,16531,54294,54303,54305, -16530,54295, 1,54295,35187,54311, 17,54313, 7,54295,16531,54316, -54299,54319,16531,54317,54309,54323, 15,54317,38305,54327, 1,54294, -40705,54331,54329,54331, 17,54331, 7,54294,54333,54339,40704,54339, -54331,54343,49713,54339, 4,54346, 4,54339,49713,54350,54315,54339, - 9,54339,38305,54356,54331,54359,38305,54339, 9,54362,54331,54365, -52489,54295, 9,54369,36527,54295, 375,54373, 341,54295,12377,54295, - 9,54379,16531,54295, 7,54382,54299,54385,37611,54295, 9,54389, - 8321,54295,35927,54295, 9,54395,38155,54295, 9,54399,43503,54295, -44243,54403, 113,54295,38305,54406,40086,54295, 8241,54295,44243,54294, - 11,54415, 1369,54415, 1486,54295,35187,54295,47640,54423,46863,54423, - 903,54426, 903,54423,46863,54430,53480,54295,11731,54295,51615,54295, - 241,54295, 17,54294, 113,54443,38305,54294, 9,54294,37611,54449, -38155,54449,35927,54449,52489,54449, 15,54294, 483,54459, 11,54295, -44243,54463,38305,54295, 113,54466,38057,54295, 7,54471, 375,54471, - 4,54294,54426,54477,54423,54477,46863,54480,52573,54477,54377,54477, -52115,54477,43053,54477,46863,54477,54423,54492, 5,54294,54473,54497, - 6,54497,54471,54501,53966,54497,12571,54497, 4613,54497,51615,54497, - 8337,54497,46863,54513,52591,54497,53932,54497,53813,54497, 1369,54520, -53391,54520,53391,54497,53813,54526,20103,54497,46863,54531,36773,54497, -46863,54535, 1369,54497,53813,54538, 4,54295, 0,54542,54497,54545, -46863,54547, 5,54295,48294,54551,21315,54551,46863,54554,53391,54550, - 1369,54550,46863,54551,21315,54562,53391,54295, 5,54567,53813,54569, - 5,54566, 1369,54295, 9893,54575,52129,54575,54353,54575,54349,54575, -20885,54575,52411,54575,44243,54575, 5,54574, 5,54575,53813,54593, - 2,49713,53227,54597,53262,54597,53355,54597,53358,54597,53298,54597, -53264,54597,53229,54597,53274,54597,53234,54597,49168,54597, 1,54597, - 7,54597, 567,54621,52915,54623, 4,54621,54575,54627,53360,54627, -52915,54627, 483,54632, 483,54627,52915,54636, 9,54621, 1,54596, -36544,54643,35187,54643, 11,54646, 11,54643,35187,54650, 7,54596, -36545,54655,54643,54657,54645,54655,21605,54655,54653,54655,54649,54655, - 15,54655,53270,54597,46863,54670,53231,54597,46863,54674,49169,54597, -54097,54597,53134,54597,53215,54683,53352,54597,53215,54687,53196,54597, -53215,54691, 8311,54597,48884,54596,54617,54697,53731,54597,53881,54597, -54283,54597,54241,54597,54087,54597,36256,54597,53296,54597,53167,54712, -53184,54597,53255,54716,53167,54597,53357,54720,53296,54720,53255,54720, -46863,54726,46863,54720,53255,54730,48885,54597, 9,54734,54697,54737, -54697,54735, 9,54741,35187,54597, 9,54744, 9,54597,48885,54748, -54697,54751,48885,54749,35187,54748, 11,54749,52915,54759,53188,54597, -53215,54763,46863,54765,46863,54762,53215,54769,53813,54763,53139,54597, -53255,54774,44243,54597, 11,54779,54225,54597,53813,54783,51229,54597, - 265,54597,54027,54789,47961,54791,14611,54791, 4899,54791, 375,54791, - 17,54596, 903,54801,51593,54801,54477,54801,54225,54801, 11,54596, -53318,54811,52825,54811,52915,54811, 9,54816, 9,54811,52915,54820, -44243,54811,53255,54597,53139,54826,53184,54826,53167,54826,46863,54832, -46863,54826,53167,54836,53357,54597,53167,54840, 4,54596,51418,54845, -51416,54845,51398,54845,51354,54845,51909,54845, 340,54845,51803,54857, -51873,54845,47974,54845,47589,54845, 8590,54845,14620,54845,12537,54845, -52021,54845,52029,54845,53106,54845, 375,54845,51229,54878,52915,54878, - 0,54845, 6,54885, 7,54845, 265,54888,51803,54891, 265,54889, -51229,54895,52915,54895,47580,54845,51803,54901, 8861,54901, 8495,54845, -47961,54906, 4899,54906,14611,54906,52915,54845, 375,54914,14611,54845, -51229,54918, 8495,54918, 4899,54845,51229,54924, 8495,54924,47961,54845, -51229,54930, 8495,54930, 265,54845, 7,54936,51803,54939,54887,54937, -54886,54936,54943,54945,54887,54936,54886,54937,54949,54951,46863,54936, - 8861,54955,51803,54955,46863,54845, 265,54960,51803,54963, 8861,54963, - 265,54961,51229,54969, 8495,54969,51229,54845, 375,54974,14611,54974, - 4899,54974,47961,54974, 5,54596, 1505,54985, 918,54985,52541,54985, -52121,54985,54125,54985, 903,54985, 9,54996, 9,54985, 903,55000, - 5,54597,54889,55005,52915,55007,53349,55004, 6,55005,54914,55013, -52915,55013,54845,55016,54845,55013,52915,55020, 53,55005, 1471,55005, - 253,55005,52557,55005,53348,55004,53215,55033, 241,55005, 9,55037, -52915,55004,53215,55041,46863,55043,46863,55040,53215,55047,53813,55041, - 17,55005,35187,55053,52915,55005,53357,55057,55011,55057,53296,55057, -53255,55057,46863,55064,46863,55057,53255,55068,46863,55004,52915,55072, -53215,55075,52915,55073,53255,55079,48885,54596,54679,55083, 9,55083, -48884,54597,54755,55089,55086,55089,55083,55089, 9,55094,52915,55088, -53215,55099,52915,55089,53255,55103, 9,55089,55083,55106,53348,54597, - 5,55110,53215,55113, 5,55111,53167,55117,52915,54597,48884,55120, -53215,55123,48884,55121,53139,55127, 5,55121,53139,55131,53184,55131, -53167,55131,46863,55136,46863,55131,53167,55140, 5,55120,53215,55145, -46863,55147,46863,55144,53215,55151,53813,55145,46863,55120, 5,55156, -53215,55159, 5,55157,53167,55163,21605,54597,54027,55167,31103,55169, -46863,54597,53270,55172,53231,55172,53188,55172,53215,55179,53255,55172, -53167,55182,53167,55172,53255,55186, 5,55172,52915,55190,53215,55193, -52915,55191,53255,55197,52915,55172, 5,55200,53215,55203, 5,55201, -53167,55207, 4,49713,51398,55211, 375,55211,51229,55214,53709,55211, -53740,55211,51909,55211,53797,55211,53800,55211, 340,55211,51803,55229, -54339,55210,54575,55233,53774,55211,53742,55211,53711,55211,53750,55211, -53716,55211,54663,55211,53533,55211, 1368,55211,52205,55251,54449,55251, -52809,55251,54295,55251, 9,55259, 7,55211, 265,55263,51229,55265, - 89,55263,52915,55269, 265,55262,51803,55273, 2,55262,52205,55277, -52809,55277,54449,55277,54295,55277, 9,55285, 2,55263,52825,55289, -53318,55289, 9,55289,52915,55294,52915,55289, 9,55298,53746,55211, -46863,55302,53713,55211,46863,55306,31796,55211,25037,55211,25215,55211, -42338,55211,42076,55211,43053,55211,42959,55211,54575,55211,54339,55325, -54786,55211,51360,55211,53780,55211,52751,55211, 8148,55211, 9594,55211, -54377,55211,54439,55211,53758,55211,54700,55211,54826,55211,53286,55211, -53646,55211,53703,55353,53794,55211,53703,55357,53682,55211,53703,55361, -53371,55211, 842,55211, 9377,55367,54591,55211,54421,55211,54561,55211, -53681,55211,53255,55211,54597,55378, 483,55378,53679,55211,54573,55211, -55131,55211,54559,55211,54435,55211,19892,55211,53772,55211,53667,55396, -53672,55211,53731,55400,53667,55211,53799,55404,53772,55404,53731,55404, -46863,55410,46863,55404,53731,55414, 935,55211,20733,55211, 9991,55211, -41941,55211, 483,55424, 9565,55211, 483,55428, 1487,55211,54597,55211, -51229,55434, 53,55435, 1471,55435, 253,55435,53731,55434,53255,55434, -47546,55211, 66,55211, 1369,55451, 241,55211,31103,55454,18967,55211, - 483,55458, 483,55211,42155,55462,41941,55462,51229,55462,53517,55462, - 7971,55462, 9565,55462,53731,55462,53255,55462, 587,55462, 9377,55481, -18967,55462, 587,55463, 9195,55487,52915,55487,53674,55211,53703,55493, -46863,55495, 1369,55493,46863,55492,53703,55501,53391,55493,53649,55211, -53731,55506,31103,55211, 241,55510, 587,55511, 113,55211,46863,55516, -17455,55211,54551,55211, 1369,55523,53391,55523,51229,55211, 375,55528, -54597,55528, 483,55528, 1011,55211, 8165,55537, 9875,55537,20501,55537, - 11,55537, 265,55211, 7,55546,51803,55549,54295,55547,47961,55553, -14611,55553, 4899,55553, 375,55553, 1369,55210,54985,55563,51601,55563, -54129,55563, 587,55210, 9366,55571,54575,55571,53360,55571, 9195,55571, - 483,55578,52915,55571, 483,55582, 483,55571, 9195,55586,52915,55586, -31103,55571,53731,55211,53649,55594,53672,55594,53667,55594,46863,55600, - 483,55594,54597,55594,46863,55594,53667,55608, 587,55211, 9377,55613, - 483,55615, 483,55612, 9377,55619,21605,55211,21526,55622, 6,55623, -21527,55622,55627,55629, 7,55622, 7,55623,55625,55635, 6,55622, -18967,55638,55635,55641,18967,55622, 6,55645,55633,55647, 6,55644, -55635,55651, 1347,55211, 1369,55655,53799,55211,53667,55658, 2,55210, -51418,55663,51416,55663,51398,55663,51354,55663,51909,55663, 340,55663, -51803,55675,51873,55663,47974,55663,47589,55663, 8590,55663,14620,55663, -12537,55663,52021,55663,52029,55663,53106,55663, 375,55663,51229,55696, -52915,55696, 0,55663, 6,55703, 7,55663, 265,55706,51803,55709, - 265,55707,51229,55713,52915,55713,47580,55663,51803,55719, 8861,55719, - 8495,55663,47961,55724, 4899,55724,14611,55724,52915,55663, 375,55732, -14611,55663,51229,55736, 8495,55736, 4899,55663,51229,55742, 8495,55742, -47961,55663,51229,55748, 8495,55748, 265,55663, 7,55754,51803,55757, -55705,55755,55704,55754,55761,55763,55705,55754,55704,55755,55767,55769, -46863,55754, 8861,55773,51803,55773,46863,55663, 265,55778,51803,55781, - 8861,55781, 265,55779,51229,55787, 8495,55787,51229,55663, 375,55792, -14611,55792, 4899,55792,47961,55792, 3,55210,54801,55803,52573,55803, -52115,55803,43053,55803,46863,55803, 2,55211, 7,55814,52205,55817, -52809,55817,54449,55817,54295,55817, 9,55825,54295,55815,54501,55829, - 7,55829,54497,55833, 375,55829, 3,55211,55707,55839,52915,55841, -55706,55839,53793,55838,55779,55839, 6,55839,55732,55851,52915,55851, -55663,55854,55663,55851,52915,55858, 0,55851,55829,55851, 0,55850, -55663,55867, 0,55839, 6,55870,55663,55873, 0,55838,49713,55838, -55845,55879, 1,55838,55868,55883,55874,55883,55867,55883,55663,55888, -55873,55883,55663,55892,55849,55883,55663,55883,55867,55898,55873,55898, -46862,55839,55898,55905,55883,55905,55663,55908,55663,55905,55883,55912, - 1,55839,55863,55917,55663,55919, 7,55839,55663,55922,55879,55925, -55879,55923,55663,55929,52591,55839,53792,55838,53703,55935,43027,55839, -43837,55839,39747,55839,53517,55838,53703,55945,46863,55947, 1369,55945, -46863,55944,53703,55953,53391,55945, 1369,55839,18967,55959, 11,55838, - 1369,55963,18967,55839,46863,55967, 11,55839,46863,55971,53517,55839, -53799,55975,55847,55975,53772,55975,53731,55975,46863,55982,46863,55975, -53731,55986,55778,55839,55877,55991,46863,55839,55877,55995,55663,55997, -55663,55994,55877,56001,55663,55839, 7,56004,55879,56007,46863,56004, -55877,56011,46863,55838,53517,56014,53703,56017,53517,56015,53731,56021, -49204,55211,53517,56024,53703,56027,53517,56025,53731,56031,53792,55211, - 3,56034,53703,56037, 3,56035,53667,56041, 7971,55211, 483,56044, -42155,55211, 483,56048,53517,55211, 483,56052,49204,56052,53703,56057, -49204,56053,53649,56061, 3,56053,53649,56065,53672,56065,53667,56065, -46863,56070, 483,56065,54597,56065,46863,56065,53667,56078, 3,56052, -53703,56083,46863,56085, 1369,56083,46863,56082,53703,56091,53391,56083, -46863,56052, 3,56096,53703,56099, 3,56097,53667,56103, 11,55211, - 3,56106, 1369,56109, 3,56107, 483,56113,46863,55211,53746,56116, -53713,56116,53674,56116,53703,56123,53731,56116,53667,56126,53667,56116, -53731,56130, 113,56116, 3,56116,53517,56136,53703,56139,53517,56137, -53731,56143,53517,56116, 3,56146,53703,56149, 3,56147,53667,56153, -46863,49713,47982,56156,47983,56157,56159,56161,47983,56156,47982,56157, -56165,56167,49588,56156,49589,56157,56171,56173,49670,56156,49671,56157, -56177,56179,49589,56156,49588,56157,56183,56185,49671,56156,49670,56157, -56189,56191, 8453,56156, 273,56156,21522,56156,38266,56156, 1516,56156, - 948,56156,20239,56156,37095,56156, 1477,56156, 281,56156,49617,56156, -49616,56157,56215,56217,49699,56156,49698,56157,56221,56223,49617,56157, -49616,56156,56227,56229,49699,56157,49698,56156,56233,56235, 1216,56156, - 412,56156,12377,56156, 375,56156, 510,56156,38057,56156, 903,56248, - 165,56156, 903,56252,21315,56156, 1011,56256, 1505,56156, 1011,56260, - 413,56157,50785,56265,56241,56265, 1217,56157,56239,56271, 1216,56157, - 413,56156, 412,56157,56277,56279, 1217,56156,56275,56283, 264,56157, -51777,56287,50908,56287,50785,56287, 241,56292, 241,56287,50785,56296, - 375,56287, 264,56156,50207,56303,51765,56303,51677,56303,51615,56303, - 241,56311, 341,56303, 1011,56156, 1505,56316,21315,56316, 903,56156, - 165,56322,38057,56322, 483,56156, 9,56328, 9,56156, 483,56332, - 5,56157, 4,56156,56337,56339,46863,56340, 2,56343, 2,56342, -49515,56340,49514,56340, 2,56341,56349,56353, 3,56341,56347,56357, -56351,56357, 2,56340,46863,56362,56357,56365,56357,56363, 3,56340, -56345,56371,56353,56371, 3,56157, 375,56377, 2,56156,56337,56381, - 1,56383, 0,56382,56385,56387, 0,56383, 1,56382,56391,56393, -56377,56381,46863,56396, 4,56399, 4,56398,49631,56396,49630,56396, - 4,56397,56405,56409, 5,56397,56403,56413,56407,56413, 4,56396, -46863,56418,56413,56421,56413,56419, 5,56396,56401,56427,56409,56427, - 2,56157, 3,56156,56337,56435, 7,56437, 6,56436,56439,56441, - 6,56437, 7,56436,56445,56447,56433,56435,46863,56451, 4,56452, - 4,56453,49631,56451,49630,56451, 4,56451,46863,56462, 5,56451, -56457,56467, 4,56450,56467,56471,56459,56471, 5,56450,56465,56477, -56455,56477,56463,56477,56461,56477, 4,56157,56435,56487, 1,56489, - 0,56488,56491,56493, 0,56489, 1,56488,56497,56499,56381,56487, - 7,56503, 6,56502,56505,56507, 6,56503, 7,56502,56511,56513, - 5,56156,56487,56517,46863,56519, 2,56520, 2,56521,49515,56519, -49514,56519, 2,56519,46863,56530, 3,56519,56525,56535, 2,56518, -56535,56539,56527,56539, 3,56518,56533,56545,56523,56545,56531,56545, -56529,56545, 1, 2,11709,56555,11632,56555,11035,56555,10468,56555, -17775,56555,11788,56555,12226,56555,11816,56555,11770,56555,44558,56555, -42181,56555,44243,56576,44438,56555,10856,56555, 3447,56555, 375,56584, - 3448,56555,11705,56555,11033,56555,10516,56555,17773,56555,18735,56555, -10427,56555,10831,56600,10836,56555,10855,56555,16623,56555,16711,56555, - 9533,56610,16718,56555, 3555,56555, 5882,56555, 9261,56555, 483,56621, - 3699,56555, 15,56625, 6,56624,56627,56629, 14,56625, 7,56624, -56633,56635, 1999,56555, 15,56639, 6,56638,56641,56643, 14,56639, - 7,56638,56647,56649,29450,56555,29731,56653,29659,56653,28791,56653, -29041,56653,38067,56555, 5,56663,38185,56665,42155,56554,44243,56669, -42471,56670,44966,56669,42471,56669,44243,56676, 1471,56554,36639,56681, -15390,56555,15383,56685,28715,56555,21527,56689,29229,56691, 7,56689, -29759,56695, 7,56688,28791,56699,29041,56699,29731,56699,29659,56699, - 1005,56555,16877,56554,16893,56711, 9925,56555, 1369,56715, 9927,56717, -35336,56555, 989,56721,35278,56555, 1177,56725, 987,56555,35187,56728, - 989,56731,36563,56554,36639,56735, 671,56554,36597,56554,36639,56741, - 1418,56554, 1,56745, 4,56746, 4,56745, 1,56750, 147,56555, -35187,56754, 53,56757,17637,56555, 587,56760,10107,56763,35316,56555, - 1471,56767,35330,56555, 53,56771,17638,56555,10107,56775, 1489,56555, -35187,56778, 1471,56781, 1179,56555,35187,56784, 1177,56787,37229,56555, -35187,56790,37223,56793, 9441,56555, 587,56796, 9439,56799,37230,56555, -37223,56803, 9442,56555, 9439,56807,45432,56555,42435,56811, 30,56555, -11731,56814,45433,56555,56669,56819,43099,56555,52259,56555, 483,56825, -44742,56555,44904,56555,52613,56555,52383,56555,52497,56555,39231,56555, -40447,56555,39083,56555,38797,56555,39019,56555,39301,56555,39429,56555, -39305,56555, 386,56555, 347,56555,54492,56555,45508,56555,56116,56555, -55812,56555,40987,56555,52909,56555,51598,56555,50419,56555,56332,56555, -52836,56555,52366,56555,36639,56555, 1471,56881,36563,56881,36597,56881, - 181,56555,11731,56888,50579,56555,52319,56555,52323,56555,54436,56555, -54406,56555,52532,56555,52514,56555,55520,56555,44930,56555,39317,56555, -51141,56555,40123,56555,39228,56555,40676,56555,47366,56555,40682,56555, -52599,56555,50655,56555,52531,56555,36538,56555,36048,56555,37594,56555, -42918,56555,40922,56555,39292,56555,11111,56555,11113,56555,11187,56555, -17508,56555,17180,56555, 3280,56555, 3574,56555, 3568,56555,12216,56555, - 25,56958,11613,56555, 25,56962,48406,56555,48400,56555,48500,56555, -43292,56555,47534,56555,17494,56555,39065,56555,48961,56555,49162,56555, -17496,56555,11179,56555,47892,56555,11546,56555,11207,56555, 5878,56555, -52446,56555,35506,56555,39035,56555,40087,56555, 9,57003,10513,56555, - 9,57006,36102,56555, 253,57011, 53,57011, 117,57011, 1471,57011, - 7968,56555,53813,57021,10107,57021,11067,57021,37282,56555,53813,57029, -37417,57029,10107,57029,35652,56555, 253,57037, 1471,57037, 809,57037, - 53,57037,38293,56555,53813,57047,37417,57047,38275,57047,10107,57047, - 1397,56555,35187,57056,52439,56555, 265,57060,40127,56555,43318,56555, -48750,56555,53813,57069,10107,57069,36100,56555, 253,57075, 53,57075, - 1471,57075, 9404,56555, 483,57083, 8053,56555, 9,57087,10465,56555, - 9,57090,11936,56555,10119,56555,10185,56555,53885,56555,10117,56555, -45490,56555, 33,57105, 8212,56555, 9,57109,11812,56555, 9,57112, -53899,56555, 6719,56555, 11,57119, 5,57120, 6,57119, 5,57124, - 5,57119, 6,57128, 6,57129, 7,57119,57133,57135, 15,57119, - 6,57118,57139,57141, 14,57119, 7,57118,57131,57147,57127,57147, -57123,57147,57145,57147, 6787,56555, 5,57157, 4,57157, 12,57157, - 13,57156,57163,57165, 13,57157, 12,57156,57169,57171, 5,57156, -57161,57175, 4,57156,57159,57179,10831,56555, 375,57182,44243,57182, -10427,57182, 9,57183,11529,56555,46863,57192, 483,57192,17640,56555, -39226,56555,48572,56555,47410,56555,40568,56555,47374,56555,47674,56555, -17656,56555,47676,56555,47634,56555,48112,56555,47412,56555, 5814,56555, - 918,56555,36256,56555,46863,57226,48466,56555,49713,57230,35187,57230, - 11,57231,47608,56555, 903,57238,52756,56555,46863,57242,48620,56555, - 247,56555,46863,57248, 1419,56555,56749,57253,56753,57253,25519,57253, - 1841,57253, 1883,57253,22679,57253, 5,57253,22677,57267,14065,57253, - 5175,57253,40565,56555, 587,57274, 922,56555,51593,56555,46863,57280, -47640,56555, 11,57285, 1011,57284, 11,57284,35718,56555, 9439,57293, -37223,57293, 9381,57293,37157,57293,35877,57293,35881,57293, 9383,57293, -37163,57293,35883,57293, 17,57293,37145,57313, 9377,57313,35867,57313, -51051,56555, 375,57321,50959,56555, 9,57325,39205,56555, 10,57329, - 10,57328, 11,57329,57333,57335, 1011,57328, 11,57328,57331,57341, -48402,56555, 9,57344,48560,56555, 903,57348,36544,56555, 6,57353, -36661,57355,36675,57353, 8067,57353, 7979,57353, 7981,57353,39747,57353, -43837,57353,43027,57353, 1369,57353, 7971,57373, 934,56555,46863,57376, - 668,56555, 5,57381,22605,57383,22615,57381, 3135,57381, 2009,57381, -14065,57381, 5175,57381,53905,56555,55432,56555,10303,56555,42661,56555, - 25,56555,11613,57404,12216,57404, 9,57404,11731,57410,35187,57404, - 253,57415, 53,57415, 117,57415, 1471,57415,11731,57404, 9,57424, - 8165,56555, 67,57428, 9,57431, 7947,56555, 587,57434,53813,57437, -10107,57437,11067,57437,17049,56555,46863,57444, 165,56555,43215,57448, - 113,56555,54295,57452, 767,56555, 483,57457, 9377,57459, 9377,57456, - 483,57463, 803,56555,17455,57466, 375,56555,10831,57470, 3447,57470, - 305,57470,17125,57470, 510,56555, 11,56555, 33,57483,44243,57485, -44243,57482, 33,57489,39205,57482,47640,57482,46863,57482, 903,57496, -35187,57482,43027,57501,43837,57501, 8067,57501, 7979,57501,39747,57501, - 7981,57501, 1369,57501, 7971,57515, 903,57482,46863,57518, 9,56555, -10465,57522,11812,57522,10513,57522, 25,57522,11731,57530,56156,57522, -40675,57522, 3565,57522, 3573,57522, 3273,57522,11731,57522, 25,57544, -48402,57522,17455,57522, 5843,57522, 11,57523,46863,57555,49713,57522, -46863,57558, 903,57522,35187,57522,46863,57564,46863,57522,49713,57568, -35187,57568, 11,57569, 587,57522, 5175,57577,14065,57577, 3135,57577, - 2009,57577, 483,57522,55839,56555, 483,57589, 5771,56555, 903,57592, - 6705,56555, 1369,57597, 6707,57599, 6711,57599, 6715,57599, 3697,56555, - 16,57607, 16,57606, 17,57607,57611,57613, 17,57606,57609,57617, - 3709,56555, 8075,56555, 9,57623, 3273,56555, 9,57626, 3423,56555, - 16,57631, 16,57630, 17,57631,57635,57637, 17,57630,57633,57641, - 3661,56555, 16,57645, 16,57644, 17,57645,57649,57651, 17,57644, -57647,57655, 3681,56555, 3357,56555,53675,56555, 9,57663,42379,56555, - 9,57667, 3573,56555, 9,57670, 3565,56555, 9,57674,52878,56555, -15436,56555, 375,57681,54550,56555,17232,56555,38305,57686, 4935,56555, - 6,57691, 5,57692, 7,57691, 5,57691, 6,57698, 6,57699, -57697,57703, 6,57690, 15,57691,57707,57709, 7,57690,57695,57713, -57701,57713, 14,57691,57713,57719,55803,56555,46863,57722,16127,56555, - 6,57727, 5,57728, 7,57727, 5,57727, 6,57734, 6,57735, -57733,57739, 6,57726, 15,57727,57743,57745, 7,57726,57731,57749, -57737,57749, 14,57727,57749,57755,54477,56555,46863,57758,49155,56555, - 483,57762, 5843,56555, 955,57766, 9,57766, 5313,56555, 9802,56555, -48736,56555, 9434,56555, 483,57779,15309,56555, 413,57782,15383,57785, - 413,57783,15335,57789, 8,56554, 4,57793, 1,57794,57381,57797, -57577,57797, 1,57793, 4,57802,57381,57805,57577,57805, 10,56554, - 7,57811, 2,57812,57353,57815,57501,57815, 2,57811, 7,57820, -57353,57823,57501,57823,57515,57811,57373,57811, 1368,57811,57501,57833, -57353,57833, 3867,57811, 8277,57811, 3997,57811, 4067,57811, 9459,57811, - 8953,57811,57483,57811, 9,57811, 14,56555,38881,57855, 11,56554, -44778,57859,44243,57859, 25,57862,47640,57859, 25,57859,44243,57868, -48466,57859, 903,57859,46863,57874,46863,57859, 903,57878, 9,57878, - 9,57859,46863,57884, 9,56554,40903,57889,40053,57889,43307,57889, - 5019,57889,12361,57889, 16,56555,19625,57901,21105,57901,21549,57901, -17591,57901, 17,56554,36639,57911, 10,56555,57859,57915,11731,56555, - 30,57918, 181,57918,54295,57918, 9,57918, 25,57926, 145,57918, - 25,57918, 9,57932, 67,56555, 9,57937, 8165,57939, 8165,57936, - 9,57943,17635,56555, 155,57946, 903,57946, 145,56555,11731,57952, -17695,56555, 1369,57957, 7971,57959,53517,57959,17053,57959,17699,57959, -42155,57959, 155,56555,17635,57970,10305,56555,42699,56555,10307,56555, - 566,56555,53813,57981,10107,57981, 256,56555,42810,56555,17125,57988, - 1170,56555, 629,56555, 1413,56555,37408,56555,25793,57999,41019,57999, - 8495,57999, 265,57998, 1346,56555,48884,56555,27021,58011,52915,58011, - 9195,58011,20763,58011, 340,56555, 331,58021,35187,58020,38270,56555, - 766,56555,25519,58029, 802,56555, 9366,58033, 9195,58033, 483,58036, - 483,58033, 9195,58040,31103,58033,42729,56555, 257,56555,44243,58048, - 1487,56555,55211,58052,44243,56555,10831,58056,42181,58056,42155,58057, -42471,58063,42155,58056,42435,58067, 9533,58056,37145,58056, 11,58057, - 25,58075,35187,58056,17125,58056, 11,58056, 33,58083,49713,58056, - 257,58056,55211,56555,46863,58090,17455,58090, 1487,58090, 1197,56555, - 4,58099, 5,58098,58101,58103, 5,58099, 4,58098,58107,58109, - 1505,56555,45002,56555,42155,56555,42435,58117,44243,58119,44243,58116, -42435,58123, 305,56555, 375,58126,35187,58126, 253,58131, 1471,58131, - 53,58131, 713,56555,35187,58138, 253,58141, 1471,58141, 809,58141, - 53,58141,37241,56555, 587,58150,53813,58153,37417,58153,10107,58153, - 955,56555, 5843,58160,48739,56555, 587,58164,53813,58167,10107,58167, -40461,56555, 9,58173,52501,56555,35187,58176, 241,58176, 9801,56555, - 17,58182, 4,58183,58185,58187, 5,58183,57901,58191, 4,58182, - 7,58194,58191,58197, 5,58182,48735,56555, 17,58202, 4,58203, -58205,58207, 5,58203,57901,58211, 4,58202, 7,58214,58211,58217, - 5,58202, 9533,56555,16711,58222,44243,58222,37145,56555,44243,58228, - 8861,56555, 5,58233, 6,58235, 6,58234, 14,58233, 15,58233, - 6,58233, 5,58244, 7,58233,58237,58249, 6,58232,58243,58253, - 7,58232,58239,58257,58247,58257,58241,58257, 9377,56555, 767,58264, - 483,58267, 4,58264, 483,58271, 1217,56555, 483,58275, 413,56555, -15309,58278,15383,58281,15309,58279,15363,58285,46863,58278, 412,56555, - 483,58291, 1216,56555,46863,58294,56156,56555, 9,58298, 1011,56555, -39205,58302,47640,58302,46863,58302, 903,58308, 7,58302, 903,58302, -46863,58314,43215,58302, 7,58319,38305,56555,17232,58322, 7,58322, -17125,58326,17125,58322, 7,58330,49713,56555,48466,58334, 9,58334, -46863,58338,44243,58334,46863,58334, 9,58344, 241,56555,52501,58348, - 7,58348, 7,58349, 265,58355, 265,58348, 483,58359, 483,56555, -40675,58362,43215,58362,49155,58362,11529,58362, 903,58362, 9,58362, - 5,58362,53813,58377,10107,58377, 5,58363,55211,58383,40675,56555, - 7,58387, 9,58386, 483,58386,46863,58386,35187,56555,37229,58396, -37223,58399, 1177,58397, 1179,58403, 989,58397, 987,58407, 1179,58396, - 1177,58411, 987,58396, 989,58415, 1489,58396, 1471,58419, 147,58396, - 53,58423, 117,58397, 25,58427, 809,58397, 713,58431, 2,58396, - 7,58435, 2,58436,58397,58439, 5,58436,58441,58443, 5,58435, - 7,58446, 10,58435, 4,58396, 7,58453, 4,58454,58397,58457, - 3,58454,58459,58461, 3,58453, 7,58464, 586,58453, 1368,58396, - 7,58471, 5,58472, 5,58471, 7,58476, 10,58471, 16,58396, - 7,58483, 3,58484, 3,58483, 7,58488, 586,58483,44243,58396, -52501,58396, 340,58396,48466,58396, 1397,58396, 25,58396, 1471,58505, - 253,58505, 53,58505, 117,58505, 713,58396, 53,58515, 253,58515, - 1471,58515, 809,58515, 53,58397, 147,58525, 305,58525, 713,58525, - 25,58525, 1471,58397, 1489,58535, 305,58535, 25,58535, 713,58535, - 305,58396, 253,58545, 1471,58545, 53,58545, 253,58397, 305,58553, - 25,58553, 713,58553, 9,58396,46863,58560, 1369,58397, 9891,58565, - 9927,58565,58475,58565,58479,58565,58443,58565,58449,58565, 4,58565, - 9895,58565,19687,58565,20843,58565,21127,58565,58451,58565,58481,58565, - 11,58565, 9875,58593,58435,58593,58471,58593, 17,58397,10111,58601, -10159,58601,58487,58601,58491,58601,36729,58601,58461,58601,58467,58601, - 2,58601,10113,58601,58469,58601,58493,58601, 587,58601,10107,58625, -58453,58625,58483,58625,46863,58396, 9,58632, 11,58396,57815,58637, -57823,58637, 8067,58637, 7979,58637, 3,58637,58601,58647,58617,58637, - 7981,58637,39747,58637,43027,58637,43837,58637,57833,58637, 1369,58637, - 7971,58663,57811,58663, 587,58396,35877,58669,35881,58669, 9439,58669, - 9381,58669, 5,58669,58565,58679,58579,58669,37223,58669,37157,58669, - 9383,58669,37163,58669,35883,58669, 17,58669, 9377,58695,37145,58695, -35867,58695, 6,58396, 7,58396,25793,58705,41019,58705, 8495,58705, - 265,58704, 6,58397,36661,58715,58705,58715,57999,58715, 7,58397, -58703,58723,58027,58723, 265,58396, 6,58728, 7,58728, 6,58729, -58733,58735, 7,58729,58731,58739, 903,56555,17455,58742,17635,58742, -47608,58742, 5771,58742,48560,58742, 11,58743,46863,58755, 9,58742, - 483,58742,46863,58742, 11,58763, 1011,58762, 11,58762, 11,58742, -46863,58770, 7,58743, 8165,58775, 1011,58742,46863,58778,46863,56555, -21036,58782,21036,58783,21037,58782,58787,58789,21037,58783,58785,58793, -54477,58782,55211,58782,55803,58782,52756,58782,51593,58782,40675,58782, -43215,58782,36256,58782,11529,58782, 934,58782, 247,58782, 1216,58782, - 413,58782,17049,58782, 11,58783, 903,58825, 9,58825, 9,58782, -49713,58830,35187,58830, 11,58831, 1011,58782, 903,58838,35187,58782, - 9,58842, 903,58782, 11,58847, 1011,58846, 11,58846, 11,58782, - 903,58854, 5,58782,27021,58859,52915,58859, 9195,58859,20763,58859, -49713,58782, 9,58868, 1275,56555, 17,58872, 4,58872, 7,58876, - 5,58872, 4,58873,58875,58883, 5,58873,58879,58887,57901,58887, - 265,56555,37408,58892,52439,58892, 7,58892, 331,58899,35187,58898, - 7,58893, 375,58905, 241,58892, 483,58909,38305,58893, 375,58913, -35187,58892, 6,58916, 7,58916, 6,58917,58921,58923, 7,58917, -58919,58927, 587,56555, 9441,58930, 9439,58933,17637,58930,10107,58937, -37417,58931,37241,58941,11067,58931, 7947,58945, 7,58930, 4,58949, - 7,58950,58931,58953, 0,58950,58955,58957, 0,58949, 4,58960, -35186,58949, 1,58930, 4,58967, 1,58968,58931,58971, 6,58968, -58973,58975, 6,58967, 4,58978, 8,58967, 16,58930, 4,58985, - 0,58986, 0,58985, 4,58990,35186,58985,22807,58931,37241,58930, -10107,58999,53813,58999,37417,58999, 7947,58930,53813,59007,10107,59007, -11067,59007,10107,58931,17637,59015,48739,59015,37241,59015, 7947,59015, -48739,58930,53813,59025,10107,59025,53813,58931,48739,59031,37241,59031, - 7947,59031,40565,58930, 17,58931, 1985,59041, 3721,59041,58989,59041, -58993,59041, 5299,59041,58957,59041,58963,59041, 1,59041,35233,59041, -35917,59041, 4861,59041,17563,59041,58965,59041,58995,59041,35187,59041, - 53,59071,58949,59071,58985,59071,35187,58930,35881,59079,35877,59079, -37223,59079,37157,59079, 6,59079, 9439,59079, 9381,59079,37163,59079, - 9383,59079,35883,59079, 17,59079,37145,59101, 9377,59101,35867,59101, - 9,58930,57797,59109,57805,59109, 3135,59109, 2009,59109, 0,59109, -59041,59119,59057,59109, 5175,59109,14065,59109, 4,58930, 9366,59129, - 9195,59129, 483,59132, 483,59129, 9195,59136,31103,59129, 5,58930, -25519,59143, 5,58931,25503,59147,24623,59147,30387,59147,58565,59147, -22605,59147,36526,56555, 6,59158, 7,59158, 6,59159,59163,59165, - 7,59159,59161,59169,40920,56555, 7,59172,43400,56555, 7,59177, -16065,56555, 5,59181, 7,59182, 7,59183,56555,59186, 6,59182, -59189,59191, 6,59183,56555,59183, 7,59196,59191,59199, 7,59197, -59195,59203,15029,56555, 5,59206, 6,59209, 6,59208, 14,59206, - 15,59206, 6,59206, 5,59218, 7,59206,59211,59223, 375,59223, - 6,59207,59217,59229, 7,59207,59221,59233,59213,59233, 59,59233, -59215,59233, 331,59233, 1325,59233, 265,59233,43215,56555, 9,59249, - 483,59248,46863,59248, 165,59248, 1011,59248, 7,59259,17125,56555, - 4,59262, 7,59265, 1011,59266, 1011,59265, 7,59270, 7,59271, - 1170,59265, 5,59263,57993,59279,58313,59279,17129,59279,42811,59263, -42811,59262,44243,59262,42810,59262,59287,59293,42810,59263,59289,59297, - 375,59262, 6,59262,59269,59303,59273,59303,59277,59303, 7,59262, -38305,59310, 6,59263,59275,59315,59311,59315, 7,59263,59303,59321, -38305,59262, 7,59324,54295,56555,11731,59328, 113,59328, 5,59328, - 5,59329,57901,59337,17455,56555, 7,59341, 4,59342, 4,59343, - 16,59341, 17,59341,55211,59340, 803,59340, 903,59340, 9,59340, - 4,59340,59351,59361, 5,59340,59345,59365,59349,59365, 4,59341, - 7,59370,59365,59373, 5,59341,59347,59377, 4,56554,26454,59381, -26375,59381, 8672,59381, 8743,59381,41692,59381,41607,59381, 8770,59381, - 8729,59381, 3795,59381,47953,59381,48062,59381,47961,59381,48009,59404, -48009,59381,47961,59408,26219,59381,26415,59412,41417,59381,41653,59416, -44832,59381,31770,59381, 8757,59381, 8647,59424,41653,59381,41417,59428, -26415,59381,26219,59432, 8647,59381, 305,59436, 8757,59436, 8605,59381, -47580,59381,47933,59445, 8684,59381, 8717,59449, 8916,59381,44243,59381, - 483,59454,41502,59381,41559,59459, 340,59381, 8717,59463, 3785,59463, - 8495,59463, 375,59381, 8861,59470,46863,59470,47488,59381,26292,59381, -26331,59479, 9,59381,31103,59482, 305,59381, 8647,59486, 7,59381, - 1,59491, 264,59492, 264,59493,25793,59491,26415,59499,41019,59491, -41653,59503, 8495,59491, 305,59507, 8757,59507, 8495,59490, 8717,59513, -41019,59490,41559,59517, 265,59491,59497,59521, 8861,59521,46863,59521, -25793,59490,26331,59529, 265,59490, 8717,59533,59495,59533, 3785,59533, - 8495,59533,31103,59381, 9,59542, 483,59381,44243,59546,46863,59381, - 265,59551,48009,59553, 265,59550,47933,59557, 375,59550,41019,59381, - 7,59563,41417,59565, 7,59562,41559,59569, 265,59381,46863,59573, -47961,59575,46863,59572,47933,59579, 7,59573, 8647,59583, 7,59572, - 8717,59587, 3785,59587, 8495,59587,25793,59381, 7,59595,26219,59597, - 7,59594,26331,59601, 8495,59381, 7,59604, 8717,59607, 7,59605, - 8647,59611, 8861,59381, 375,59614, 5,56554,26777,59619, 9741,59619, - 9745,59619,26781,59619,30349,59619,26857,59619,26933,59619, 2,59619, - 7,59634,57353,59637,57501,59637,58637,59637, 6,59635, 9777,59619, - 1368,59619,57501,59649,57353,59649,58637,59649,57515,59619,57373,59619, -58663,59619, 9771,59619,40077,59619,31598,59619,55462,59619,50733,59619, -37519,59619,35690,59619, 8982,59619,55211,59619, 483,59678, 668,59619, - 9731,59683,26625,59683, 1419,59619, 9731,59689,26625,59689, 17,59619, - 8861,59694, 9,59619, 587,59698, 9731,59701,26625,59701, 375,59619, -35187,59706, 6,59619, 7,59619, 5,59713, 2,59712,57353,59717, -57501,59717,58637,59717, 5,59712,58396,59725,59717,59727,35187,59725, -56555,59730,59717,59733,56555,59725,35187,59736,59717,59739, 7,59618, - 3867,59743, 8277,59743, 3997,59743, 4067,59743, 9459,59743, 8953,59743, -31103,59619,26625,59756, 483,59619,55211,59760, 587,59619, 9,59764, - 9731,59767,26625,59767,35187,59619, 375,59772,26625,59619,31103,59776, - 8861,59619, 7,59781, 17,59780, 6,56554,36633,59787,36627,59787, - 1,59787, 4,59792,57253,59795,57381,59795,57577,59795,59109,59795, - 5,59792,38304,59787,39987,59787,36544,59787, 9875,59811,20501,59811, - 11,59787,35187,59816,20501,59819, 9875,59819, 5,59787, 1,59824, - 4,59787, 6,59829, 1369,59831,56555,59833, 1,59828,57253,59837, -57381,59837,57577,59837,59109,59837,59835,59837, 6,59828,58930,59849, -59837,59851, 587,59849,56555,59854,59837,59857,56555,59849, 587,59860, -59837,59863,35187,59787, 11,59866,20501,59869, 9875,59869, 7,56554, - 4904,59875,17586,59875,17609,59875,40685,59875,40039,59875,42991,59875, - 9484,59875, 272,59875, 1476,59875, 280,59875, 949,59875, 1517,59875, - 1197,59875, 4903,59875, 9,59902,17579,59875, 9,59906, 11,59875, - 9377,59910, 9,59875, 4903,59914,17579,59914, 253,59875, 265,59920, - 53,59875, 265,59924, 1471,59875, 265,59928, 5,59874, 3867,59933, - 8277,59933, 4067,59933, 3997,59933, 8953,59933, 9459,59933, 265,59875, - 253,59946, 1471,59946, 53,59946, 9377,59875, 11,59954, 5,59955, - 7,56555,59826,59960,59827,59961,59963,59965,59827,59960,59826,59961, -59969,59971,59804,59960,59805,59961,59975,59977,59805,59960,59804,59961, -59981,59983,21036,59960,14072,59960,14073,59960,14072,59961,59991,59993, -59183,59960,59191,59997,59183,59961,59185,60001, 4970,59960, 4971,59960, - 4970,59961,60007,60009,16169,59961, 9617,60013,39786,59961,59807,59961, -59806,59961,28715,59960,28791,60023,29731,60023,29659,60023,29041,60023, -21036,59961,21037,59960,60033,60035,38304,59961,59787,60038, 483,60038, -38304,59960,60019,60045,59787,60045, 483,60045,18967,59961, 5,60053, - 5,60052, 2,59961, 0,60059,56555,60061, 5,60063,59961,60065, - 7,60064,60067,60069,59960,60065, 6,60064,60073,60075, 1,59961, - 3,60079, 5,60081,56555,60082,56555,60081, 5,60086, 5,60087, - 1011,60079,56555,60093, 5,60079, 1,59960,21036,60099, 3,60099, -56555,60103, 5,60105, 5,60104, 5,60103,56555,60110, 5,60099, -18967,60114,18967,60099, 5,60118, 5,60119, 2,59960,59811,60125, -36545,60125,59787,60129,59819,60125,59869,60125, 15,60125,29659,59961, -29077,60139,39787,59961,60045,60143,32103,59961,41746,59961,26106,59961, - 8800,59961,36526,59960,40920,59960, 1163,59961,41019,59961, 11,60160, -35187,60161,59619,59961, 4971,59961,60005,60169,14073,59961,59989,60173, - 4555,59961, 559,59961, 39,59961, 8495,59961,35187,60183, 11,60182, -15029,59960, 375,60189,17125,59960,38305,60192, 11,59961,41019,60196, -25793,60196, 8495,60196, 265,59961, 3447,60205,10831,60205, 305,60205, -17125,60205,11731,60205, 567,59961,46863,60217, 15,59961, 3651,60221, - 1993,60221, 4903,60221,17579,60221, 241,59960,38305,59960,60017,60233, -60021,60233,60041,60233,60043,60233,60039,60233,59787,60243, 483,60243, -17125,60232, 1011,59960,59279,60251,21037,59961,59987,60255, 11,60255, -28715,59961,29533,60261,20273,60261, 9617,60261,35187,59960,25793,60269, -41019,60269, 8495,60269,58715,60269, 265,60268, 265,59960, 331,60281, -35187,60280,38305,59961,37845,60287,37844,60286,60289,60291,37844,60287, -37845,60286,60295,60297,60048,60287,59787,60287,60045,60302,60050,60287, -60045,60287,59787,60308, 483,60308, 483,60287,60045,60314, 1011,59961, -25793,59961,35187,60321, 11,60320, 4,59960,60091,60327,60107,60327, -60033,60327,60101,60327,59337,60327,58191,60327,58211,60327,60057,60327, -60117,60327,60121,60327,21549,60327,21105,60327,19625,60327,58887,60327, -17591,60327, 5,59960, 1,60359, 3,60361,60205,60363,60255,60359, - 4,59961,60085,60369,60089,60369,60113,60369,60109,60369,57685,60369, -59335,60369,58201,60369,58221,60369,57775,60369,57777,60369,60095,60369, -60055,60369,60123,60369,31103,60369,21575,60369,58881,60369,58009,60369, -17579,60369, 4903,60369,48408,60369,46863,60369, 483,60410, 483,60369, -46863,60414, 5,59961,18967,60418,60327,60421, 1368,60419, 2,60419, - 7,60426, 7,60419, 2,60430,59787,59961,38304,60435,60287,60437, -38304,60434,60233,60441, 483,59961,38304,60445,60287,60447,38304,60444, -60233,60451, 5,56555,60081,60454,60369,60457,60103,60454,60369,60461, - 1,60455, 3,60464, 1,60454,59491,60469,59490,60469,59381,60469, - 7,60474, 7,60475, 5,60469,59961,60481, 6,60468,60473,60485, -60477,60485, 7,60468,60471,60491,59381,60491, 6,60469,59381,60497, -60491,60498,60479,60497,60494,60497,60491,60497,59381,60506, 7,60469, -59381,60510,60485,60513,60485,60511,59381,60517, 2,60454,60261,60521, -60483,60521,53813,60455, 483,60527,52915,60455,46863,60531,59875,60455, - 9801,60454,60369,60537,48735,60454,60369,60541,10107,60455, 483,60545, - 9195,60455,46863,60549,54295,60454,60369,60553, 587,60455,17455,60557, -11731,60557, 9,60455, 8861,60563, 17,60455, 587,60567,26625,60569, - 9731,60569,60467,60569, 483,60454,53813,60577,10107,60577,20763,60455, -46863,60583,46863,60454,27021,60587,52915,60587, 9195,60587,20763,60587, - 1275,60454,60369,60597, 587,60454,25519,60601,27021,60455,46863,60605, - 6,60454,38881,60609,59381,60455,30091,60455,31103,60615, 4,56555, - 2,60619, 0,60621,56555,60623, 5,60625, 7,60621,60627,60629, - 1,60618,59689,60633, 1418,60633,59619,60637,59683,60633, 669,60633, -59619,60643,60569,60633,59701,60633,59767,60633, 15,60633, 1369,60652, -59619,60655, 1369,60633, 15,60658,59619,60661, 842,60619, 9377,60665, -59787,60619, 9377,60618, 483,60671, 587,60619, 483,60674, 9377,60677, - 9377,60675, 483,60681,21527,60619, 9,60685,31103,60619, 587,60689, - 587,60618, 9366,60693, 9195,60693, 483,60696, 483,60693, 9195,60700, -31103,60693, 483,60619, 587,60706, 9377,60709, 9377,60707, 587,60707, - 9195,60715, 7,60618,59337,60719,58191,60719,58211,60719,21105,60719, -21549,60719,19625,60719,58887,60719,17591,60719, 6,60619, 1,60737, - 4,60738, 4,60737, 1,60742, 1369,60737,56555,60747,60741,60749, -60745,60749, 7,60619, 2,60755,21183,60755, 9377,60755,59619,60619, -38305,60619, 3,60764, 2,60764,56555,60765, 6,60770,60769,60773, - 6,60765,56555,60776,60769,60779, 1011,60619,46862,60782,46862,60783, -46863,60783,60785,60789,46863,60782,60787,60793, 6,56555,36303,60797, -36302,60796,60799,60801,36303,60796,36302,60797,60805,60807,40946,60796, -40946,60797,60765,60796,60769,60815, 2,60797, 0,60818,40947,60796, -60813,60823,40947,60797,60811,60827,60765,60797,60767,60831,59381,60797, - 17,60797,35187,60837,20501,60839,60125,60839,60821,60839, 9875,60839, -35187,60796,58723,60849, 5,60796,38881,60853, 0, 3, 8169,60857, - 8028,60857, 8173,60857, 8214,60857, 8167,60857, 8154,60857, 8026,60857, - 8054,60857,17728,60857,60210,60857,60283,60857,58128,60857,58023,60857, -57476,60857,56854,60857,56856,60857,58901,60857,58906,60857,58122,60857, -58066,60857,56810,60857,56822,60857,16743,60857,16696,60857, 4810,60857, -16745,60857,16729,60857,16714,60857, 6648,60857, 2079,60857, 375,60916, - 2086,60857,16733,60857,16565,60857,16683,60924,16692,60857,16735,60857, -16739,60857,51942,60857,44534,60857,42383,60857,44243,60938,44440,60857, -16747,60857, 75,60857, 6625,60946, 6632,60857, 6645,60857,60079,60857, - 5,60955,60327,60957, 5,60954,60369,60961,60096,60857,60369,60965, - 1325,60856,40829,60969, 1173,60857,17591,60856,17603,60975,10039,60857, - 1275,60979,10041,60981,38560,60857, 1205,60985, 1203,60857,38305,60988, - 1205,60991,38514,60857, 1007,60995,40741,60856,40829,60999, 531,60856, - 1290,60856, 0,61005, 5,61006, 5,61005, 0,61010,40769,60856, -40829,61015,38548,60857, 1325,61019, 177,60857,38305,61022, 59,61025, -17053,60857, 483,61028,10081,61031, 1009,60857,38305,61034, 1007,61037, - 1365,60857,38305,61040, 1325,61043,38566,60857, 59,61047,17054,60857, -10081,61051,42109,60857,38305,61054,42103,61057, 9527,60857, 483,61060, - 9525,61063,42110,60857,42103,61067, 9528,60857, 9525,61071, 386,60857, -56555,61074, 8150,60857, 113,61078, 347,60857,56555,61082,58905,60857, - 375,61086,45432,60857,56555,61090,43099,60857,56555,61094,40829,60857, - 1325,61099,40741,61099,40769,61099,60535,60857, 9,61107,57916,60857, - 9,61111,57851,60857, 9,61115,17727,60857, 113,61118,57060,60857, - 8309,60857,60230,60857,57986,60857,57998,60857,60268,60857,58352,60857, -58704,60857,13820,60857,13772,60857,57994,60857,58056,60857,42155,61144, -36101,60857, 375,61149,37407,60857,47392,60857,36532,60857,36536,60857, -57284,60857,58760,60857,58762,60857,58846,60857,58372,60857,57278,60857, -57996,60857,57470,60857, 305,61174,60205,60857, 305,61178,58374,60857, -58830,60857,57586,60857,57480,60857,57230,60857,57568,60857,40684,60857, -36542,60857, 375,61197,42990,60857,40038,60857,37498,60857,36754,60857, -35796,60857, 8225,60857, 8242,60857, 128,60857, 7971,61214, 101,60857, - 7971,61218,37362,60857,48122,60857,12526,60857, 6698,60857,47690,60857, -38704,60857,11943,60857, 9,61235,12343,60857, 5,61239, 4,61238, -61241,61243, 4,61239, 5,61238,61247,61249,40132,60857, 331,61253, - 59,61253, 97,61253, 1325,61253, 8148,60857,48753,61263,10081,61263, -11759,61263,39044,60857, 331,61271, 1325,61271, 571,61271, 59,61271, -42338,60857,48753,61281,44451,61281,10081,61281,42959,60857,48753,61289, -44451,61289,42825,61289,10081,61289, 629,60857,56555,61298,38305,61298, - 289,60857, 587,61305,10287,60857,17660,60857,10262,60857,40130,60857, - 331,61315, 59,61315, 1325,61315,53780,60857,48753,61323,10081,61323, -60668,60857, 9,61329, 8213,60857, 9,61332,11813,60857, 9,61337, -17030,60857, 8211,60857, 8301,60857, 8209,60857,38110,60857, 8052,60857, - 9,61350,10464,60857, 9,61355,10527,60857, 9,61359, 4727,60857, - 9,61363,11989,60857, 11,61367, 5,61368, 6,61367, 5,61372, - 5,61367, 6,61376, 6,61377, 7,61367,61381,61383, 15,61367, - 6,61366,61387,61389, 14,61367, 7,61366,61379,61395,61375,61395, -61371,61395,61393,61395,12371,60857, 5,61405, 4,61405, 12,61405, - 13,61404,61411,61413, 13,61405, 12,61404,61417,61419, 5,61404, -61409,61423, 4,61404,61407,61427, 6625,60857,44243,61430, 375,61430, - 75,61430, 9,61431, 6685,60857, 483,61440,46863,61440,17060,60857, -35768,60857,50524,60857,52806,60857,50480,60857,36296,60857,50990,60857, - 510,60857,56555,61460,47608,60857,36293,60857, 483,61466, 295,60857, -49713,61470, 1291,60857,61009,61475,61013,61475,20033,61475, 1831,61475, - 1881,61475,19319,61475, 4,61475,19317,61489,15899,61475, 4579,61475, -48561,60857, 9,61497, 922,60857,56555,61500,51937,60857, 375,61504, -57915,60857,57859,61508, 9,61511,39234,60857,60853,61515,60609,61515, - 9525,61515,42103,61515, 9517,61515,41989,61515,39485,61515,39481,61515, -57855,61515, 9519,61515,41995,61515,39487,61515, 15,61515, 9513,61541, -41941,61541,39477,61541,50958,60857, 9,61548,35761,60857, 9,61552, -35719,60857, 375,61557,57482,60857,57852,61561,57811,61561, 9,61564, - 9,61561,57811,61568,57522,60857, 483,61572,46863,61572, 1072,60857, - 1108,60857,49713,61580, 524,60857, 4,61585,19301,61587,19311,61585, - 3195,61585, 1965,61585,15899,61585, 4579,61585,40704,60857, 7,61601, -40799,61603,40813,61601, 7961,61601, 7951,61601, 7953,61601,35893,61601, -37897,61601,38299,61601, 1275,61601, 7947,61621,52756,60857, 1011,61624, -10245,60857,37339,60857, 33,60857,10385,61632, 9,61635, 7971,60857, - 101,61638, 128,61638, 9,61638, 113,61644, 483,61638,48753,61649, -10081,61649,11759,61649, 113,61638, 9,61656, 21,60857,38305,61660, - 331,61663, 59,61663, 97,61663, 1325,61663,47640,60857,56555,61672, -17635,60857,12377,61676,11731,60857,13737,61680, 567,60857,46863,61685, -55211,60857,44243,60857, 6625,61690,42383,61690,58116,61690,42155,61690, -56555,61698,56555,61690,42155,61702, 1505,60857,38057,61706, 288,60857, -46863,61711,48466,60857,56555,61714, 11,60857, 340,61719, 341,61719, - 264,61718,61721,61725, 7,61719, 265,61728,61725,61731, 265,61729, - 264,61719,61735,61737,56555,61719,57859,61741, 9,61743, 483,61718, - 4579,61747,15899,61747, 3195,61747, 1965,61747, 265,61719, 7,61756, -61725,61759,56555,61718,57852,61763,57811,61763, 9,61766, 9,61763, -57811,61770, 265,61718,61723,61775,46863,61775, 9,60857, 8213,61780, - 8052,61780, 7971,61780, 113,61786,36527,61780,58782,61780,58362,61780, - 8241,61780, 113,61780, 7971,61798,35761,61780,50958,61780, 483,61780, -56555,61806, 1011,61780,49713,61810,38305,61780,38299,61815,37897,61815, - 7961,61815, 7951,61815,35893,61815, 7953,61815, 1275,61815, 7947,61829, -49713,61780, 1011,61832,56555,61780,46863,61836, 483,61836,46863,61780, -56555,61842, 7563,60857, 1275,61847, 7565,61849, 7569,61849, 7573,61849, - 7065,60857,35187,61857,10089,60857, 16,61861, 16,61860, 17,61861, -61865,61867, 17,61860,61863,61871,10257,60857, 903,61874, 8241,60857, - 9,61878, 3255,60857, 9,61883,48789,60857, 16,61887, 16,61886, - 17,61887,61891,61893, 17,61886,61889,61897,37357,60857, 903,61900, - 3499,60857, 9,61905, 3445,60857, 9,61909,38184,60857, 375,61913, -16722,60857,16543,61917,16679,61917,16537,61917,35187,61916,13922,60857, -13753,61927, 4805,60857, 375,61930,16683,60857,16565,61934, 375,61934, - 6515,60857, 9,61941,59824,60857,60369,61945, 9,61945, 9520,60857, - 9,61951,16711,60857,16659,61954, 8,60856, 3,61959, 6,61960, -61601,61963,61815,61963, 6,61959, 3,61968,61601,61971,61815,61971, -61829,61959,61621,61959, 1274,61959,61815,61981,61601,61981, 16,60856, - 10,60856, 5,61989, 0,61990,61585,61993,61747,61993, 0,61989, - 5,61998,61585,62001,61747,62001,57811,61989,59933,61989,59743,61989, - 8093,61989, 3837,61989,39619,61989,51421,61989,53703,61989,42435,61989, - 4287,61989, 4303,61989,53487,61989,42113,61989, 9839,61989, 9579,61989, - 9,61989, 113,62036, 128,61989, 101,61989, 113,61989, 9,62044, -57859,60857,57915,62048, 9,62051, 9,62049,57915,62055, 11,60856, - 483,62059, 9,60856,57889,62063, 5185,62063,11243,62063,12557,62063, -11251,62063, 5177,62063, 16,60857,57293,62077,35603,62077,58669,62077, -59079,62077,55005,62077, 17,60856,61685,62089, 483,62089, 15,60856, -40829,62095, 10,60857,21183,62099, 759,62099, 47,62099, 959,62099, - 203,62099, 107,62099, 85,62099, 67,62099, 9,62115, 113,60857, - 8150,62118,17727,62118,13737,62118, 9,62118, 7971,62126,17025,62118, - 7971,62118, 9,62132,10385,60857, 9,62137, 33,62139, 33,62136, - 9,62143, 165,60857,17049,62146,17025,60857, 1275,62151, 7947,62153, -48739,62153,17637,62153,17029,62153,37241,62153, 113,62150,17049,60857, - 165,62166,10247,60857,37347,60857,10249,60857,16659,60857,16711,62176, -37408,60857,56555,62180,16531,62180, 340,60857,51803,62187, 331,62187, - 1325,62187, 59,62187,52439,60857,56555,62196,52563,60857, 265,62201, - 1413,60857,56555,62204, 256,60857,56555,62208,38305,62208, 566,60857, -61987,62215, 9377,62215,37325,62215,10219,62215, 959,62215, 47,62215, - 759,62215, 587,62215,20763,62215,42810,60857,43073,62235,42827,62235, -58703,62235,60849,62235,58027,62235,42821,62235, 1325,62235, 59,62235, - 331,62235, 265,62235,42613,62235,56555,62257, 241,62234, 580,60857, -20033,62263,59143,62263,60601,62263,58029,62263,55210,60857,31103,62273, -37375,60857, 1347,60857,37409,60857, 375,62280, 375,60857,58905,62284, -16683,62284, 4805,62284,58126,62284, 6625,62284, 2079,62284,51937,62284, - 305,62284,56555,62300,56555,62284, 305,62304,37409,62284, 803,60857, -37608,60857, 305,60857,60205,62314,57470,62314, 375,62314,56555,62320, -56555,62314, 375,62324,58116,60857,44243,62328,58126,60857, 375,62332, -42155,60857,58056,62336,44243,62336,56555,62340, 483,62336,48753,62345, -44451,62345,10081,62345,56555,62336,44243,62352,53517,60857, 483,62356, -48753,62359,10081,62359, 251,60857,38305,62364, 331,62367, 1325,62367, - 59,62367, 555,60857,38305,62374, 331,62377, 1325,62377, 571,62377, - 59,62377,60612,60857, 7,62387,36273,60857, 7,62391,59787,60857, -60619,62394, 9,62397, 5,62394,60369,62401, 9,62401, 5,62395, -60327,62407,60719,62407,57901,62407, 17,62407,59381,60857,60455,62416, - 7,62419, 9513,60857, 5,62423, 17,62425, 5,62422, 9,62429, -58362,60857, 903,62432, 9,62432,58348,60857, 7,62438,58782,60857, - 903,62442, 9,62442,58396,60857, 7,62448,58742,60857, 9,62453, - 483,62452,46863,62452,60763,60857, 7,62461, 903,60857,58782,62464, -58362,62464,37357,62464,10257,62464, 483,62464,56555,62474,46863,62464, -56555,62478,56555,62464, 9,62483,46863,62482, 483,62482,38057,62464, - 7,62491, 265,60857,46863,62495, 11,62497, 11,62494,46863,62501, - 7,62494,51803,62505, 331,62505, 1325,62505, 59,62505, 7,62495, - 375,62515,35187,60857,59960,62518,16722,62518, 7,62518,56555,62524, -16531,62524,56555,62518, 7,62530,16531,62518, 7,62534,46863,60857, -36527,62538,58742,62538,57522,62538,12377,62538, 6685,62538, 1011,62538, - 903,62538,56555,62552, 9,62538,56555,62556,56555,62538, 903,62560, - 9,62560,36527,60857, 7,62567, 331,62569, 9,62566,46863,62566, - 483,62566, 7,62566, 375,62579,38305,60857,42109,62582,42103,62585, - 1205,62583, 1203,62589, 1007,62583, 1009,62593, 1203,62582, 1205,62597, - 1009,62582, 1007,62601, 177,62582, 59,62605, 1365,62582, 1325,62609, - 571,62583, 555,62613, 97,62583, 21,62617, 5,62582, 6,62621, - 5,62622,62583,62625, 2,62622,62627,62629, 2,62621, 6,62632, - 482,62621, 3,62582, 6,62639, 3,62640,62583,62643, 4,62640, -62645,62647, 4,62639, 6,62650, 8,62639, 14,62582, 6,62657, - 2,62658, 2,62657, 6,62662, 482,62657, 1274,62582, 6,62669, - 4,62670, 4,62669, 6,62674, 8,62669, 256,62582, 629,62582, - 555,62582, 59,62685, 331,62685, 1325,62685, 571,62685, 21,62582, - 1325,62695, 331,62695, 59,62695, 97,62695, 1325,62583, 1365,62705, - 251,62705, 21,62705, 555,62705, 59,62583, 177,62715, 251,62715, - 555,62715, 21,62715, 251,62582, 331,62725, 59,62725, 1325,62725, - 331,62583, 251,62733, 555,62733, 21,62733, 15,62583,10085,62741, -10093,62741,62661,62741,62665,62741,40909,62741,62629,62741,62635,62741, - 3,62741,10087,62741,62637,62741,62667,62741, 483,62741,10081,62765, -62621,62765,62657,62765, 1275,62583,10005,62773,10041,62773,62673,62773, -62677,62773,62647,62773,62653,62773, 5,62773,10009,62773,23879,62773, -31937,62773,30399,62773,62655,62773,62679,62773, 9,62773,10001,62801, -62639,62801,62669,62801, 483,62582,39485,62809,39481,62809, 9525,62809, - 9517,62809, 4,62809,62773,62819,62787,62809,42103,62809,41989,62809, - 9519,62809,41995,62809,57855,62809,60853,62809,60609,62809,39487,62809, - 15,62809, 9513,62841,41941,62841,39477,62841, 9,62582,61971,62849, -61963,62849, 7961,62849, 7951,62849, 2,62849,62741,62859,62757,62849, - 7953,62849,35893,62849,38299,62849,37897,62849,61981,62849, 1275,62849, - 7947,62875,61959,62875, 6,62582, 7,62582,58703,62883,58027,62883, -60849,62883, 59,62883, 1325,62883, 331,62883, 265,62883,42613,62883, -56555,62899, 241,62882, 7,62583,58715,62905,58056,62905,40799,62905, - 375,62905,56555,62905,44243,62914,44243,62905,56555,62918, 265,62583, - 375,62923,62881,62923, 241,62582, 6,62928, 7,62928, 6,62929, -62933,62935, 7,62929,62931,62939, 1011,60857,52756,62942,46863,62942, - 483,62942, 9,62942,49713,62950,49713,62942, 9,62954, 7,62943, -10107,62959,53813,62959,49713,60857,22807,62965, 1108,62964, 295,62964, - 9,62964, 1011,62972, 1011,62964, 9,62976, 4,62964,31103,62981, - 241,60857,59960,62984,42810,62984, 7,62984,56555,62990,38305,62990, -56555,62984, 7,62996,38305,62984, 6,63000, 7,63000, 6,63001, -63005,63007, 7,63001,63003,63011, 483,60857, 9527,63014, 9525,63017, -17053,63014,10081,63021,11759,63015, 7971,63025,44451,63015,42155,63029, - 0,63014, 5,63033, 0,63034,63015,63037, 7,63034,63039,63041, - 7,63033, 5,63044, 10,63033, 6,63014, 5,63051, 6,63052, -63015,63055, 1,63052,63057,63059, 1,63051, 5,63062,38304,63051, - 14,63014, 5,63069, 1,63070, 1,63069, 5,63074,38304,63069, -36527,63014,58742,63014,57522,63014,12377,63014, 6685,63014, 7971,63014, -48753,63091,10081,63091,11759,63091,42155,63014,10081,63099,48753,63099, -44451,63099,10081,63015,17053,63107,53517,63107,42155,63107, 7971,63107, -53517,63014,48753,63117,10081,63117,48753,63015,53517,63123, 7971,63123, -42155,63123,36293,63014, 17,63015, 11,63015, 9,63014,56555,63136, - 15,63015, 1995,63141, 3755,63141,63073,63141,63077,63141, 5303,63141, -63059,63141,63065,63141, 0,63141,38403,63141,39943,63141, 4917,63141, -17013,63141,63067,63141,63079,63141,38305,63141, 59,63171,63051,63171, -63069,63171, 903,63014,56555,63178, 1011,63014, 11,63014,61993,63185, -62001,63185, 3195,63185, 1965,63185, 1,63185,63141,63195,63157,63185, - 4579,63185,15899,63185,38305,63014,39481,63205,39485,63205,42103,63205, -41989,63205, 7,63205, 9525,63205, 9517,63205,41995,63205, 9519,63205, -57855,63205,60609,63205,60853,63205,39487,63205, 15,63205,41941,63233, - 9513,63233,39477,63233, 4,63014,20033,63241,59143,63241,60601,63241, -58029,63241,63133,63241, 5,63014,61987,63253, 9377,63253,37325,63253, -10219,63253, 959,63253, 47,63253, 759,63253, 587,63253,20763,63253, - 4,63015, 7,63272,63253,63275,20029,63273,59147,63273,21103,63273, -19781,63273,19301,63273,62773,63273, 5,63015, 803,63291,56555,63014, - 903,63294, 9,63294,40674,60857, 6,63300, 7,63300, 6,63301, -63305,63307, 7,63301,63303,63311,38266,60857, 7,63315,36752,60857, - 7,63318,16937,60857, 580,63322, 483,63322, 4,63327, 4,63326, -49631,63322,49630,63322, 581,63322, 4,63322, 483,63338,46863,63338, - 5,63322,63329,63345, 4,63323,63333,63349,63337,63349, 5,63323, -63335,63355,63325,63355,63331,63355,63341,63355,63343,63355,46863,63322, - 4,63366,63355,63369, 4,63367,63345,63373,38057,60857, 5,63376, - 6,63379, 6,63378, 14,63376, 15,63376, 1505,63376, 6,63376, - 5,63390, 7,63376,63381,63395, 375,63395, 6,63377,63387,63401, - 7,63377,63393,63405,63383,63405,38161,63405, 59,63405,63385,63405, - 331,63405, 1325,63405, 265,63405, 903,63376, 7,63423,16531,60857, - 1275,63427,16711,63429,37408,63426, 7,63426,16543,63435,16679,63435, -16537,63435,35187,63434, 7,63427,16565,63445,35187,63426, 7,63448, -12377,60857, 9,63453,46863,63452, 483,63452,17635,63452,13737,60857, - 113,63462,11731,63462, 5,63462,13753,63469, 5,63463,13751,63473, -13917,63473,13743,63473,60619,60857,59787,63480, 9,63483,60455,60857, -59381,63486, 7,63489, 5,60856,45491,63493,42800,63493,59694,63493, -10374,63493,60563,63493, 9606,63493,42134,63493, 629,63493, 705,63493, - 101,63493, 299,63493, 828,63493, 128,63493, 394,63493,48122,63493, - 803,63493, 483,63524,42613,63493, 17,63528,51992,63493, 375,63493, - 241,63534,49713,63534,10291,63493, 17,63540, 256,63493, 113,63493, - 9,63546, 17,63493,42613,63550,10291,63550,59619,63550, 9565,63550, -41941,63550, 9,63493, 113,63562, 7,63493,21605,63567, 241,63566, - 7,63492,59933,63573,59743,63573,57811,63573, 8093,63573, 3837,63573, -53703,63573, 4287,63573,42435,63573, 4303,63573,53487,63573, 9839,63573, -42113,63573, 9579,63573,39619,63573,51421,63573,31103,63493,46863,63493, -12377,63606, 483,63493, 803,63610,49713,63493, 375,63614,56555,63493, - 5,63619, 6,63621, 6,63620, 14,63619, 15,63619, 6,63618, -63629,63631, 7,63618,63625,63635,63627,63635, 7,63619,63623,63641, - 6,63619, 5,63644,63635,63647, 241,63493, 375,63650, 7,63650, -59619,63493, 7,63657, 17,63656,12377,63493,46863,63662, 9565,63493, - 7,63667, 17,63666,41941,63493, 7,63673, 17,63672, 4,60856, -20305,63679, 9641,63679, 9645,63679,20309,63679,21081,63679,20323,63679, -20387,63679, 3,63679, 6,63694,61601,63697,61815,63697,62849,63697, - 6,63695, 9701,63679, 1274,63679,61815,63709,61601,63709,62849,63709, -61829,63679,61621,63679,62875,63679, 9719,63679,43005,63679,58056,63679, - 386,63679, 347,63679, 767,63679,31103,63733, 524,63679, 9617,63737, -20273,63737, 1291,63679, 9617,63743,20273,63743, 305,63679, 375,63748, - 375,63679, 305,63752,44243,63679,56555,63756, 11,63679, 483,63760, - 9617,63763,20273,63763, 7,63679,38305,63769,56555,63771, 6,63679, - 4,63775, 3,63774,61601,63779,61815,63779,62849,63779, 4,63774, -62582,63787,63779,63789,38305,63787,60857,63792,63779,63795,60857,63787, -38305,63798,63779,63801, 7,63678,63253,63805,62215,63805, 483,63679, - 11,63810, 9617,63813,20273,63813,56555,63679,44243,63818, 7,60856, -40787,63823,40793,63823, 0,63823, 5,63828,61475,63831,61585,63831, -61747,63831,63185,63831,36001,63823,26106,63823,32103,63823,41746,63823, -43005,63823, 8800,63823,59910,63823,36539,63823,37595,63823,36049,63823, -63253,63823,62215,63823,61305,63823,48975,63823,48245,63823,48451,63823, -60707,63823, 386,63823, 347,63823, 510,63823,60755,63823, 9852,63823, -53500,63823,36041,63823,37573,63823,36275,63823, 375,63823, 305,63892, - 273,63823, 281,63823, 1477,63823, 1516,63823, 948,63823,40704,63823, -10001,63907,27533,63907, 8495,63823, 11,63912,48885,63823, 483,63917, -41019,63823, 11,63920, 567,63823,63493,63925, 165,63823, 903,63928, - 11,63823,25793,63932,41019,63932, 8495,63932,59875,63932, 9805,63932, -53391,63932,60618,63823, 483,63947, 9,63823, 483,63950,38305,63950, -27533,63955,10001,63955, 1505,63823, 1011,63960, 305,63823, 375,63964, - 4,63823,63610,63969,63291,63969,63493,63969, 483,63974, 483,63969, -63493,63978,56555,63968, 483,63983, 5,63823, 7,63987, 1275,63989, -60857,63991, 0,63986,61475,63995,61585,63995,61747,63995,63185,63995, -63993,63995, 7,63986,63014,64007,63995,64009, 483,64007,60857,64012, -63995,64015,60857,64007, 483,64018,63995,64021, 4,63822,63253,64025, -62215,64025, 5,63822,59743,64031,59933,64031,57811,64031, 8093,64031, - 3837,64031,42435,64031, 4303,64031,53703,64031, 4287,64031,42113,64031, - 9579,64031,53487,64031, 9839,64031,51421,64031,39619,64031,25793,63823, - 11,64062, 903,63823, 165,64066,38305,63823, 9,64070,27533,64073, -10001,64073, 1011,63823, 1505,64078,56555,63823, 4,64082, 483,64085, - 483,63823, 9,64088,59875,63823, 11,64092, 5,64093, 9805,63823, - 11,64098, 5,64099,53391,63823, 11,64104, 5,64105, 6,60856, -60454,64111,60369,64113, 5,64111,56555,64116,60369,64119,56555,64111, - 17,64122, 4,64122, 7,64126, 5,64122,60369,64131, 5,64123, -60327,64135,60719,64135,64129,64135,57901,64135, 4,64123,64125,64145, - 7,60857,16539,64149,16683,64151, 264,64149, 264,64148, 3,64149, -16530,64158,16530,64159, 1,64158,58396,64148,58348,64148,36527,64148, - 375,64171,40674,64148,36752,64148, 331,64149, 1325,64149, 59,64149, -38057,64148, 375,64185,16531,64148,64161,64189,16543,64189,16679,64189, -16537,64189,35187,64188, 17,64149, 241,64201,38305,64149,42383,64205, - 6625,64205,58116,64205,42155,64205,56555,64212,56555,64205,42155,64216, -16531,64149,64163,64221,16659,64221,48885,64149,56555,64227, 15,64149, - 483,64231,38305,64231,27533,64235,64165,64235,10001,64235,35187,64148, -56555,64242,16531,64242, 265,64148,64155,64249,51803,64249, 331,64249, - 1325,64249, 59,64249, 241,64148,56555,64260,38305,64260,38305,64148, -58703,64267,58027,64267,60849,64267, 59,64267, 1325,64267, 331,64267, - 265,64267,42613,64267,56555,64283, 241,64266, 265,64149,64157,64289, -41941,64289,51229,64289, 4213,64289, 8757,64289, 9565,64289,59619,64289, - 305,64289, 713,64289, 25,64289, 8165,64289, 9617,64289,20273,64289, - 4,64148,57293,64317,35603,64317,58669,64317,59079,64317,55005,64317, - 5,64148, 3,64329, 1,64331,64205,64333,21183,64329, 759,64329, - 47,64329, 959,64329, 4,64149,43053,64345,54985,64345,54129,64345, -51601,64345,58782,64345,46863,64345,56555,64356,56555,64345,46863,64360, - 5,64149, 803,64365, 1275,64149, 9,64369,56555,64148,25793,64373, - 8495,64373,41019,64373,35187,64372, 241,64372,59960,60857,25793,64385, -41019,64385, 8495,64385, 241,64384,35187,64384, 5,60857,60079,64396, -60369,64399, 0,64396,63743,64403, 1290,64403,63679,64407,63737,64403, - 525,64403,63679,64413,63763,64403,63813,64403, 17,64403, 1275,64420, -63679,64423, 1275,64403, 17,64426,63679,64429, 3,64396, 6,64433, - 759,64397, 483,64437,64025,64397, 483,64441,63823,64397, 483,64445, - 9377,64397, 483,64449, 9513,64396, 9,64453, 959,64397, 483,64457, -37325,64397, 483,64461, 47,64397, 483,64465,10219,64397, 483,64469, -59787,64396,60369,64473, 9,64473,13737,64396,13753,64479,49713,64397, -61987,64397, 483,64485, 9,64397,42613,64489,59619,64489,10291,64489, - 9565,64489,41941,64489, 17,64397, 113,64501,63805,64397, 483,64505, -20763,64397, 483,64509, 483,64396,64025,64513,63823,64513,61987,64513, -63805,64513, 9377,64513,37325,64513,10219,64513, 959,64513, 47,64513, - 759,64513, 587,64513,20763,64513, 587,64397, 483,64539, 7,64396, -21183,64543, 759,64543, 47,64543, 959,64543, 6,64397,56555,64553, - 4,64554, 5,64554, 5,64555,64557,64561, 4,64555,64559,64565, - 7,64397, 0,64569, 5,64570, 5,64569, 0,64574,21105,64569, -21549,64569,19625,64569, 1275,64569,60857,64585,64573,64587,64577,64587, -63679,64397,63705,64593,64435,64593,31103,64593, 375,64593, 7,64593, -64433,64603, 903,64397, 375,64607, 7,64607,35187,64397,60796,64612, -60797,64612,31103,64613,60797,64613,64615,64621, 375,64613,60796,64613, -64617,64627,56555,64397,59787,64631, 9,64633,56555,64396,59914,64637, -60221,64637,59875,64637, 9,64642,60369,64637, 9,64637,59875,64648, -60454,60857,59914,64653,60221,64653,59875,64653, 9,64658,60369,64653, - 9,64653,59875,64664, 4,60857, 8743,64669, 8605,64669, 8672,64669, - 8647,64669, 305,64676, 3795,64669,10025,64669,27603,64669,31524,64669, -31690,64669,31700,64669,63569,64669,46862,64669, 0,64669, 2,64696, - 6,64696, 6,64697,63604,64669,24655,64669,63534,64669, 8916,64669, -62092,64669,63133,64669,48408,64669, 713,64669,31103,64718, 305,64669, - 8647,64722,31103,64722, 25,64669,31103,64728, 340,64669, 8717,64733, - 3785,64733, 8495,64733, 483,64669,62089,64740,46863,64740, 375,64669, -63493,64746, 8861,64746,62089,64669, 483,64752, 15,64669, 483,64757, -20273,64759, 9617,64759,64403,64759,64699,64759,31103,64669, 305,64768, - 713,64768, 25,64768,63493,64768,49713,64769, 483,64668,20033,64781, -59143,64781,58029,64781,60601,64781,49713,64668,31103,64791,46863,64669, - 483,64794, 6,64668,64795,64799, 2,64801, 3,64800,64803,64805, - 3,64801, 2,64800,64809,64811, 7,64668,57293,64815,64695,64815, - 2,64819, 3,64818,64821,64823, 3,64819, 2,64818,64827,64829, -64701,64815, 2,64833, 3,64832,64835,64837, 3,64833, 2,64832, -64841,64843,35603,64815,59079,64815,58669,64815,55005,64815, 6,64669, - 0,64854,64815,64857, 2,64859, 3,64858,64861,64863, 3,64859, - 2,64858,64867,64869, 7,64669,60857,64873, 264,64874, 264,64875, - 1,64873, 264,64880, 264,64881,64703,64873, 2,64887, 3,64886, -64889,64891, 3,64887, 2,64886,64895,64897,25793,64873,41019,64873, - 8495,64873, 305,64905,59875,64873,53391,64873, 9805,64873,38305,64873, - 483,64915, 265,64872, 8717,64919,64883,64919,64877,64919, 3785,64919, - 8495,64919, 265,64873,64885,64931,64879,64931,63493,64931, 8861,64931, -46863,64931, 8861,64669, 375,64942,63493,64669,31103,64946, 375,64946, - 265,64669, 7,64952, 8717,64955, 3785,64955, 8495,64955, 7,64953, - 8647,64963,56555,64669,59381,64967, 7,64969,56555,64668,31103,64973, - 375,64973,59712,64973, 7,64973, 265,64981,59619,64980,59619,64973, - 7,64986,60618,60857,31103,64991, 375,64991,59712,64991, 7,64991, - 265,64999,59619,64998,59619,64991, 7,65004, 6,60857, 264,65009, -64746,65011, 375,65011,64669,65014,64931,65011,64669,65011, 375,65020, - 264,65008,64733,65025, 341,65025,64669,65029,64955,65025,64919,65025, - 3,65008, 341,65037,64669,65039,63907,65037,40705,65037,63823,65045, -64235,65037,63955,65037,64073,65037, 17,65037,64953,65009, 375,65057, - 4,65009, 1274,65061, 3,65061, 6,65064, 6,65061, 3,65068, -56555,65008,60796,60857,56555,60857, 386,65076,45432,65076, 347,65076, -43099,65076,60418,65077,60327,65087,59961,65077, 5,65091,60369,65093, - 5,65090,60327,65097, 18,65076, 12,65076, 1291,65076,48561,65076, - 525,65076,49630,65076, 580,65076, 1170,65076,37408,65076, 256,65076, -52439,65076, 629,65076, 1413,65076,47640,65076, 922,65076,49631,65076, - 581,65076, 1171,65076,44243,65076,42155,65136, 375,65076, 305,65140, -48466,65076, 510,65076, 13,65077,65103,65149, 19,65077,65101,65153, - 13,65076, 18,65077, 19,65076,65159,65161, 12,65077,65157,65165, -57915,65165, 14,65077,57901,65171,60719,65171,60327,65171,65115,65171, - 17,65171, 10,65077, 9,65183, 16,65076,65171,65187, 10,65076, -65165,65191,48560,65076, 524,65076, 1290,65076, 11,65076,65149,65201, -57852,65201,65184,65201,65183,65201, 9,65208,57811,65201, 9,65212, - 9,65201,65183,65216,57811,65216,46863,65200, 483,65200, 9,65076, - 483,65226,46863,65226, 17,65076, 1275,65232, 11,65077,65191,65237, - 9,65239,57915,65237, 9,65243, 9,65236,65191,65247,57915,65247, - 9,65077, 11,65253,65183,65255,57811,65255, 11,65252,65191,65261, -57915,65261, 15,65077,65233,65267,65135,65267, 305,65076, 375,65272, -42155,65076,44243,65276, 1011,65076, 7,65281, 7,65280,65171,65285, - 15,65281, 241,65076, 7,65290, 483,65076, 4,65295, 4,65294, - 903,65294, 9,65294, 11,65294, 903,65076, 9,65307,46863,65306, - 483,65306,35187,65076, 7,65314, 1275,65076, 17,65318,46863,65076, - 4,65323, 4,65322, 903,65322, 9,65322, 11,65322, 7,65077, - 9,65335, 11,65335, 567,65335, 4,65335, 483,65343, 5,65335, - 5,65334,65343,65349, 4,65334,65347,65353, 6,65076,65350,65357, -65355,65357,65289,65357,65349,65357,65343,65364,65343,65357,65349,65368, - 11,65357,65346,65357,65353,65375, 5,65357,65335,65379,65349,65381, -65335,65378,65353,65385,65335,65357, 4,65389, 5,65389,65343,65393, - 4,65388,65393,65397, 5,65388,65391,65401,65353,65401, 5,65077, -60629,65407,59960,65406,59960,65407,38185,65407,57993,65407,65115,65407, -65113,65407,65111,65407,59961,65406,65413,65425,60327,65425,65197,65407, -65195,65407,65105,65407,60251,65407,58313,65407,65299,65407,65327,65407, -65285,65407,65225,65407,65223,65407,65305,65407,65333,65407,56555,65407, - 7,65454, 7,65455,59961,65407,60359,65461,65411,65461, 11,65461, - 1171,65407,65335,65469,65335,65407,65187,65407,57901,65407,60327,65407, -60719,65407, 17,65407,65335,65483,59875,65483,64385,65407,64373,65407, - 6,65407,65459,65493,60755,65493,65283,65493, 11,65493, 7,65407, -56555,65502, 7,65406,65461,65507,65493,65507, 6,65406,65505,65513, -65457,65513,60719,65513,65413,65513,60327,65513,57901,65513,65187,65513, -65115,65513,65285,65513,65503,65513, 17,65513, 4,65076, 2,65537, - 7,65539,65407,65541,65510,65537,65533,65537,65507,65537,65493,65548, -31103,65537,65493,65537,65507,65554, 483,65536,65407,65559,46863,65536, -65407,65563, 375,65537, 15,65537,65357,65569, 7,65536,65513,65573, -65171,65573,65407,65573,59712,65537,65502,65537,65513,65583, 7,65537, -65493,65587,65407,65587,65507,65591, 265,65587,59619,65586,65407,65586, -65513,65599,59619,65537, 7,65602,65407,65537, 6,65607, 7,65607, -65493,65611, 6,65606,65611,65615, 7,65606,65609,65619,65513,65619, - 4,65077,65135,65625,65133,65625,65131,65625,65372,65625,65199,65625, -65109,65625,65107,65625,65235,65625,65321,65625, 11,65625,65357,65644, -65233,65625,65357,65625, 11,65650,65075,65625,65073,65625, 7,65625, -60455,65625, 7,65661, 5,65076, 2,65664,65625,65667, 1,65664, - 3,65664, 0,65664,65625,65675,59914,65665,60221,65665,65336,65665, -65297,65665,65325,65665,59875,65665, 9,65688,65659,65665,65667,65693, -65675,65693,60369,65665, 9,65665,65335,65700,59875,65700,65335,65665, - 9,65706,65658,65665,65671,65711,65673,65711, 6,65665,65668,65717, -65676,65717,65667,65717,65625,65722,65675,65717,65625,65726,65625,65717, -65667,65730,65675,65730, 7,65665,65671,65737,65625,65739,65673,65737, -65625,65743,65625,65736,65671,65747,65673,65747,65625,65665, 6,65753, - 7,65753, 6,65752,65757,65759, 7,65752,65671,65763,65673,65763, -65755,65763, 6,65077,60619,65771, 9,65773, 17,65771,65625,65777, -65537,65771, 9,65781, 5,65771,60369,65785, 9,65785, 5,65770, -65573,65791,60327,65791,60719,65791,57901,65791,65187,65791,65115,65791, -65285,65791, 17,65791, 7,65076,25793,65809,41019,65809, 8495,65809, - 1011,65808,65513,65817,65791,65817,65407,65817,65171,65817, 241,65808, -35187,65808, 15,65809,65665,65831,65407,65809, 11,65835, 4,65808, -65791,65839,65513,65839,65171,65839,65407,65839, 4,65809,65785,65849, -65665,65849,65771,65809, 4,65855, 5,65855, 4,65854,65859,65861, - 5,65854,65857,65865, 1, 4,49284,65869,49311,65869,48330,65869, -48279,65869,47548,65869,47076,65869,47078,65869,48581,65869,48584,65869, -54254,65869,54260,65869,54266,65869,54222,65869, 8672,65869, 8743,65869, - 3795,65869, 8605,65869, 8647,65869, 305,65904,27021,65868,31103,65909, -27377,65910,31894,65909,27377,65909,31103,65916, 21,65868,57577,65921, -59109,65921,19987,65921,57381,65921,59787,65868,57577,65931,57381,65931, -57253,65931,59109,65931,15390,65869,15383,65941,44768,65869,44663,65945, -48284,65869,37897,65949,44243,65869,37845,65953,45411,65955,37845,65952, -44663,65959,37845,65869,44243,65963,45381,65965,44243,65962,44663,65969, -46863,65962,37897,65973, 1175,65869,56555,65977, 1177,65979,49215,65869, - 9,65983,49229,65985,56709,65869, 1009,65989,54641,65869,54643,65993, -60737,65868,60749,65997,11355,65868,11495,66001,57793,65868,57577,66005, -57381,66005,59109,66005,59715,65869,56555,66013,59717,66015, 7959,65869, - 9,66019, 7961,66021,49534,65869,49537,66025,19086,65869, 1203,66029, -49529,65869, 15,66032,49537,66035,19064,65869, 1009,66039,54668,65869, -54643,66043, 1205,65869,18967,66046, 1203,66049,19949,65868,19987,66053, - 1425,65868,57253,66057, 668,65868, 1,66061, 2,66062, 2,66061, - 1,66066,56554,66061,58930,65868, 4,66073, 6,66074, 6,66073, - 4,66078, 8,66073,19965,65868,19987,66085,56745,65868,57253,66089, -60136,65869,59787,66093, 571,65869,18967,66096, 555,66099,16091,65869, - 15,66102, 9513,66105,19078,65869, 21,66109,54655,65869, 15,66112, -54643,66115, 1007,65869,18967,66118, 1009,66121,60125,65869, 15,66124, -59787,66127,19088,65869, 555,66131,16092,65869, 9513,66135, 97,65869, -18967,66138, 21,66141,20347,65869,18967,66144,20345,66147,10095,65869, - 15,66150,10093,66153,20348,65869,20345,66157,10096,65869,10093,66161, -32468,65869,27323,66165,33442,65869,48368,65869,32469,65869,65909,66173, -28483,65869,28479,65869,63604,65869,31690,65869,31700,65869,31524,65869, -31596,65869,32464,65869,53380,65869,25037,65869,24655,65869,25457,65869, -23005,65869,27603,65869,22591,65869,23105,65869,23357,65869,23113,65869, - 120,65869,46863,66212, 77,65869,46863,66216,54154,65869,54225,66220, -56328,65869,58298,65869,58868,65869,52752,65869,52370,65869,58344,65869, -57253,65869,59787,66237, 1425,66237,56745,66237,19987,65869, 21,66245, -19949,66245,19965,66245,25215,65869,48583,65869, 113,66254,25459,65869, -31920,65869,32263,65869,23099,65869,23107,65869,24631,65869,22915,65869, -22589,65869,65294,65869,65322,65869,63534,65869,54256,65869,54129,66280, -25305,65869,32295,65869,31796,65869,62092,65869,63133,65869,22785,65869, -22803,65869,22951,65869,24735,65869,23012,65869,25546,65869,47364,65869, -25548,65869,62442,65869,63294,65869,62432,65869,62560,65869,57577,65869, - 21,66319,59787,66319,57793,66319,57381,65869,59787,66327, 21,66327, -57793,66327,59109,65869, 21,66335,59787,66335,57793,66335,48578,65869, - 33,66343,48276,65869, 33,66347,49308,65869, 33,66351,59340,65869, -63135,65869,61464,65869,61580,65869,61578,65869,62946,65869,62950,65869, -62550,65869,61810,65869,63182,65869,62948,65869,57660,65869,57766,65869, -62060,65869,57772,65869,22767,65869,19810,65869, 251,66387, 555,66387, - 1365,66387, 21,66387, 9994,65869, 9513,66397,16859,66397,59787,66397, -20620,65869,59787,66405,21529,66405, 9513,66405,19372,65869, 251,66413, - 21,66413, 177,66413, 555,66413,20823,65869,59787,66423,21529,66423, -20771,66423, 9513,66423,57971,65869, 21,66433, 251,66433, 177,66433, - 159,66433, 555,66433,25303,65869, 11,66445,24739,65869,29028,65869, -57658,65869,57620,65869,48328,65869, 113,66456,19806,65869, 251,66461, - 555,66461, 21,66461, 8916,65869,54262,65869,46863,66470,54219,65869, -46863,66474,32556,65869, 759,66479, 7061,65869, 3,66483, 2,66483, - 842,66483, 843,66482,66489,66491, 843,66483, 842,66482,66495,66497, - 3,66482,66487,66501, 2,66482,66485,66505,47546,65869, 25,66508, -49283,65869, 25,66512,47600,65869,48444,65869,47572,65869,62146,65869, -17476,65869,23010,65869,63184,65869,61584,65869,48558,65869,47408,65869, -25460,65869,61474,65869,47372,65869,61746,65869,47632,65869,17538,65869, -47634,65869,47676,65869,48112,65869,47412,65869, 5886,65869,48095,65869, - 1072,65869,60857,66560,48408,65869,49713,66564, 241,66564, 587,66565, - 903,66564,48420,65869,61780,65869, 1011,66576,47640,65869, 1011,66580, - 483,66580,47590,65869, 483,66586,47672,65869,47368,65869, 1413,65869, -46863,66594,52692,65869,46863,66598,47370,65869, 922,65869,46863,66604, -49075,65869,49395,65869,48586,65869,10025,65869, 1281,65869,46863,66616, - 1291,65869,60857,66620, 669,65869,66065,66625,66069,66625,40909,66625, - 1821,66625, 1879,66625,38973,66625, 3,66625,38971,66639,57911,66625, -17041,66625, 4897,66625,56739,66625,66071,66625,56555,66625, 671,66653, -66061,66653,25381,65869, 11,66659, 11,66658,58931,65869,66077,66665, -66081,66665,58715,66665,58975,66665,58981,66665,59089,66665, 7,66665, -59079,66679,23879,66665,30399,66665,31937,66665,58983,66665,66083,66665, - 9,66665,58967,66693,66073,66693,58782,65869,49713,66698,60857,66698, - 11,66699, 1108,65869,60857,66706,62089,65869, 483,66710, 4802,65869, - 5314,65869,17670,65869,17693,65869,62059,65869, 483,66722,47608,65869, -60857,66726, 903,66726, 11,66727, 587,66726,19474,65869,10093,66737, -20345,66737,10085,66737,20281,66737,19549,66737,19553,66737,10087,66737, -20285,66737,19555,66737, 483,66737,20273,66757,10081,66757,19545,66757, -61718,65869, 483,66764,22957,65869, 903,66768, 587,66768,62538,65869, -56555,66774, 1011,66774, 288,65869, 9,66781,19916,65869, 7,66785, -35603,66787,35613,66785,10041,66785,10005,66785,10009,66785,23879,66785, -30399,66785,31937,66785, 9,66785,10001,66805,63014,65869,56555,66808, - 11,66809, 587,66809, 1011,66808, 11,66808,48534,65869, 1011,66820, - 1418,65869, 3,66825,38903,66827,38913,66825, 3587,66825, 1989,66825, -56681,66825,57911,66825,17041,66825, 4897,66825,56555,66825, 1471,66845, - 1086,65869,46863,66848, 524,65869,60857,66852, 1304,65869, 9,66857, - 1530,65869, 9,66861, 9195,65869,31103,66864,10031,65869,27641,65869, - 713,65869,31103,66872, 1447,65869,13737,66877, 9875,65869, 15,66880, - 9513,66883,16859,66883,59787,66883, 803,66881, 1325,65869,18967,66892, - 251,66895, 555,66895, 1365,66895, 21,66895,16937,65869,46863,66904, - 1505,65869,28715,66908, 5438,65869,49162,65869, 113,65869,48583,66916, -48328,66916, 25,66916,46863,66922,46863,66916, 25,66926, 375,65869, -63493,66930, 8861,66930,58334,65869,46863,66936,58362,65869,60857,66940, - 506,65869,46863,66944, 587,65869, 759,66949,31103,66951,31103,66948, - 759,66955,22957,66948,47608,66948,46863,66948, 1011,66962, 1011,66948, -46863,66966, 1369,65869, 15,66970, 4897,66973,17041,66973, 3587,66973, - 1989,66973,57911,66973,56681,66973,56555,66973, 1471,66987, 1275,66970, - 9,66991, 1275,65869,18967,66994,31937,66997,30399,66997,10041,66997, -10005,66997,23879,66997,10009,66997, 9,66997,10001,67011, 11,66994, - 9,67015, 9,66995, 11,67019, 1369,67019, 1369,66994, 9,67025, - 483,65869,32805,67028,56156,67028,65076,67028,25545,67028,62089,67028, -62942,67028,62059,67028,47590,67028,47640,67028,17669,67028, 5313,67028, - 4801,67028, 587,67029,46863,67055,61718,67028,49713,67028,46863,67060, - 1011,67028,60857,67064, 903,67028,46863,67068,46863,67028,49713,67072, - 587,67073, 241,67072, 903,67072,60857,67028,56555,67082, 587,67083, - 11,67083, 1011,67082, 11,67082, 11,67028,60857,67094, 5325,67028, -56555,67028,60857,67100, 241,67028,46863,67104, 4593,67028,11985,67028, - 5843,67028,49155,67028, 5876,65869,49155,65869, 483,67118, 6267,65869, - 9,67123, 6367,67125, 6403,67125, 6407,67125,60419,65869,56555,67133, -60425,67135,60429,67135,60433,67135, 5325,65869, 483,67142,55005,65869, - 9,67147, 5843,65869,56555,67150, 1011,67150, 483,67150,12023,65869, -11986,65869, 4608,65869,11985,65869, 483,67164, 3681,65869,56555,67168, - 3709,65869,56555,67172, 3357,65869,56555,67176,52840,65869, 4593,65869, - 483,67182,54202,65869,54159,67187,46863,67189, 4801,65869, 483,67192, -54129,65869,54256,67196,46863,67196,54225,67200,54225,67196,46863,67204, -17669,65869, 483,67208, 5313,65869,56555,67212, 483,67212,15309,65869, - 413,67218,15383,67221, 413,67219,15335,67225,54225,65869,54154,67228, -46863,67228,54129,67232,54129,67228,46863,67236, 1274,65868, 6,67241, - 4,67242,66785,67245,66997,67245, 4,67241, 6,67250,66785,67253, -66997,67253,67011,67241,66805,67241, 8,67241,66997,67263,66785,67263, - 1368,65868, 1,67269, 2,67270,66825,67273,66973,67273, 2,67269, - 1,67278,66825,67281,66973,67281,66987,67269,66845,67269,56554,67269, -66973,67291,66825,67291, 586,65868,24265,67297,28233,67297,29077,67297, -19559,67297, 8251,67297,20361,67297, 9673,67297,20713,67297, 4283,67297, - 9967,67297, 4279,67297, 3807,67297, 482,65869, 903,67323, 1,67325, - 0,67325, 1,67324,67329,67331, 0,67324,67327,67335, 587,65868, -31690,67339,31103,67339, 713,67342, 713,67339,31103,67346,48408,67339, -46863,67339, 483,67352, 483,67339,46863,67356, 483,65868,57577,67361, -57253,67361,19987,67361,59109,67361,57381,67361, 1369,65868, 1275,65868, -47953,67375,48062,67375,47961,67375,48009,67380,48009,67375,47961,67384, -47580,67375,47933,67389,46863,67375, 265,67393,48009,67395, 265,67392, -47933,67399, 265,67375,46863,67403,47961,67405,46863,67402,47933,67409, - 1368,65869,48009,67413,49321,67413,49001,67413, 265,67413,46863,67421, - 586,65869,58056,67425,58601,67425,40799,67425,44243,67425,56555,67432, -35927,67425,38155,67425,37611,67425, 375,67425, 510,67425, 9,67425, - 483,67446,56555,67425,44243,67450, 483,67425, 9,67454, 843,65869, - 9,67459,15705,65869, 9,67463,10001,67465,13755,67465,15733,67465, -27533,67465,17455,65869,56555,67474, 1347,67474, 1011,67474, 767,65869, -56555,67483, 1471,67485, 253,67485, 809,67485, 771,67485, 53,67485, - 1347,65869,17455,67496, 567,65869, 9,67501,10033,65869,27691,65869, -10035,65869,27978,65869,26331,67511,23755,67511,27805,67511, 256,65869, -25793,67519,59875,67519,41019,67519, 8495,67519,53391,67519, 9805,67519, - 972,65869,25793,67533,41019,67533, 8495,67533,20762,65869,58715,67541, - 375,67541, 154,65869,40909,67547,49204,65869, 11,67550, 33,67553, - 11,67551, 25,67557, 1369,67551,37409,67551, 340,65869,25793,67565, -41019,67565, 8717,67565, 8495,67565, 3785,67565,49514,65869, 66,65869, - 33,67579,46863,67581,46863,67578, 33,67585, 112,65869,44243,67589, -27785,65869, 257,65869,67373,67595,31103,67594,31103,65869,27021,67601, -27377,67603,27021,67600,27323,67607, 25,67600, 713,67600, 305,67600, -63493,67600, 8861,67600, 9195,67600,52915,67600, 1369,67601, 587,67601, - 713,67627, 903,67600, 241,67600, 587,67600, 759,67635,49713,67600, - 257,67600, 165,65869,60857,67642,31926,65869,27021,65869,27323,67649, -31103,67651,31103,67648,27323,67655,52915,65869,31103,67658, 305,65869, - 8647,67662,31103,67662, 25,65869,49283,67668,47546,67668,31103,67668, - 113,67668,46863,67676,46863,67668, 113,67680,20501,65869, 15,67684, -59787,67687,21529,67687, 9513,67687, 803,67685, 1141,65869,13737,67697, - 33,65869,13737,67701, 331,65869,18967,67704, 251,67707, 21,67707, - 555,67707, 59,65869,18967,67714, 251,67717, 21,67717, 177,67717, - 555,67717, 8861,65869,60796,67727,60797,67727,60796,67726,67731,67733, -31103,67726,60797,67726,67729,67739, 375,67726,63493,65869,60796,67745, -60797,67745,31103,67744,60797,67744,67747,67753,60796,67744,67749,67757, - 375,67744, 413,65869,15309,67762,15383,67765,15309,67763,15363,67769, -46863,67762,32805,65869, 9,67775, 483,67774,46863,67774, 1216,65869, -46863,67782,65076,65869, 9,67787, 483,67786,46863,67786,56156,65869, - 483,67794,56555,67794,56555,65869,56156,67800,63014,67800,62538,67800, - 3357,67800,17455,67800, 5313,67800, 5843,67800, 3681,67800, 3709,67800, -46863,67800,49713,67820,60857,67820, 11,67821,49713,67800,46863,67828, - 483,67800,60857,67832, 11,67801,46863,67837,60857,67800, 9,67841, - 483,67840,46863,67840,15029,67800, 7,67849, 903,65869,31103,67852, -22957,67852,47608,67852,48408,67852,46863,67852, 1011,67862, 483,67862, - 483,67852,46863,67868, 7,67852,25793,67873,41019,67873, 8495,67873, - 1011,67852,46863,67880,28715,67852, 7,67885,21605,65869, 15,67889, -31103,67891, 7,67888,26331,67895,23755,67895,27805,67895, 7,67889, -26219,67903,49713,65869,58782,67906,48408,67906, 483,67906,46863,67912, -31103,67906,56555,67906,46863,67918, 3,67907,31103,67923,46863,67906, - 483,67926,56555,67926, 241,65869,31103,67932,48408,67932,46863,67932, - 483,67938, 483,67932,46863,67942, 7,67932,25793,67947,59875,67947, -41019,67947, 8495,67947,53391,67947, 9805,67947,56555,67933, 7,67961, - 9,65869,25545,67964,62942,67964,60857,67964, 1011,67970, 1011,67964, -60857,67974,25545,65869, 7,67979, 483,67978, 9,67978,46863,67978, -46863,65869,37844,67988,37896,67989,37844,67989, 6,67994,37845,67988, -67993,67999,67997,67999,67995,67999,37897,67999,54262,67988,54219,67988, - 120,67988, 77,67988, 6,67989,37844,68017,37844,68016,67999,68021, -32805,67988,37845,67989,68019,68027,67991,68027,37899,68027,37897,67989, -67991,68035,54129,67988,54225,68038,52692,67988,58334,67988,65076,67988, -54225,67988,54129,68048,25545,67988, 66,67988, 33,68055,62942,67988, - 25,67988, 113,68060, 113,67988, 25,68064, 506,67988, 1086,67988, - 1281,67988, 1216,67988, 413,67988, 922,67988, 1413,67988,16937,67988, - 587,67989, 483,68085, 483,67988,49713,68088, 241,68088, 587,68089, - 903,68088, 241,67988, 483,68098, 903,67988, 1011,68102, 483,68102, - 1275,67989,56555,67988,49713,68110,60857,68110, 11,68111,60857,67988, -56555,68118, 1011,68118, 1011,67988,60857,68124, 903,68124, 11,68125, - 587,68124, 587,67988, 1011,68134, 2,67988, 3,67988, 11,68140, - 33,68143, 11,68141, 25,68147, 1369,68141,37409,68141, 2,67989, - 3,67989, 483,68157,49713,67988,56555,68160, 483,68160, 11,67988, - 3,68166, 33,68169, 3,68167, 113,68173, 15,65869,10095,68176, -10093,68179,54643,68177,54655,68183,49537,68177,49529,68187,54655,68176, -54643,68191,49529,68176,49537,68195,16091,68176, 9513,68199,60125,68176, -59787,68203,16859,68177, 9875,68207,21529,68177,20501,68211, 1,68176, - 2,68215, 1,68216,68177,68219, 7,68216,68221,68223, 7,68215, - 2,68226, 1368,68215, 6,68176, 2,68233, 6,68234,68177,68237, - 0,68234,68239,68241, 0,68233, 2,68244,18966,68233,56554,68176, - 2,68251, 7,68252, 7,68251, 2,68256, 1368,68251, 482,68176, - 2,68263, 0,68264, 0,68263, 2,68268,18966,68263,20501,68176, - 9513,68275,59787,68275,21529,68275, 9875,68176,59787,68283, 9513,68283, -16859,68283,59787,68177,60125,68291, 9875,68291,20501,68291, 9513,68177, -16091,68299,20501,68299, 9875,68299, 483,68177, 2007,68307, 3477,68307, -68267,68307,68271,68307, 5197,68307,68241,68307,68247,68307, 1,68307, -19051,68307,19667,68307, 5123,68307,12345,68307,68249,68307,68273,68307, -18967,68307, 555,68337,68233,68337,68263,68337,56555,68177,59637,68345, -59717,68345,68255,68345,68259,68345,68223,68345,68229,68345, 6,68345, -59649,68345,39747,68345,43837,68345,43027,68345,68231,68345,68261,68345, - 1369,68345,59619,68373,68215,68373,68251,68373,18967,68176,19553,68381, -19549,68381,20345,68381,20281,68381, 7,68381,68345,68391,68359,68381, -10093,68381,10085,68381,20285,68381,10087,68381,19555,68381, 483,68381, -20273,68407,10081,68407,19545,68407, 1369,68176,67281,68415,67273,68415, - 3587,68415, 1989,68415, 0,68415,68307,68425,68323,68415,56681,68415, -57911,68415, 4897,68415,17041,68415,67291,68415,56555,68415, 1471,68441, -67269,68441, 3,68176,40909,68447, 3,68177,40895,68451,40059,68451, -43749,68451,38903,68451,18967,65869,20347,68460,20345,68463, 1203,68461, - 1205,68467, 1009,68461, 1007,68471, 1205,68460, 1203,68475, 1007,68460, - 1009,68479, 97,68460, 21,68483, 571,68460, 555,68487, 177,68461, - 59,68491, 1365,68461, 1325,68495, 2,68460, 6,68499, 2,68500, -68461,68503, 5,68500,68505,68507, 5,68499, 6,68510, 14,68499, - 4,68460, 6,68517, 4,68518,68461,68521, 3,68518,68523,68525, - 3,68517, 6,68528, 1274,68517, 482,68460, 6,68535, 5,68536, - 5,68535, 6,68540, 14,68535, 8,68460, 6,68547, 3,68548, - 3,68547, 6,68552, 1274,68547, 256,68461, 629,68461, 1325,68460, - 21,68563, 251,68563, 555,68563, 1365,68563, 59,68460, 555,68573, - 251,68573, 21,68573, 177,68573, 555,68461, 571,68583, 331,68583, - 59,68583, 1325,68583, 21,68461, 97,68593, 331,68593, 1325,68593, - 59,68593, 331,68460, 251,68603, 555,68603, 21,68603, 251,68461, - 331,68611, 59,68611, 1325,68611, 9,68461, 7951,68619, 7961,68619, -68551,68619,68555,68619,68451,68619,68525,68619,68531,68619, 2,68619, - 7953,68619,35893,68619,38299,68619,37897,68619,68533,68619,68557,68619, - 1275,68619, 7947,68649,68517,68649,68547,68649, 483,68461, 9517,68657, - 9525,68657,68539,68657,68543,68657,20033,68657,68507,68657,68513,68657, - 4,68657, 9519,68657,57855,68657,60853,68657,60609,68657,68515,68657, -68545,68657, 15,68657, 9513,68687,68499,68687,68535,68687, 1275,68460, -67245,68695,67253,68695,10041,68695,10005,68695, 5,68695,68657,68705, -68673,68695,10009,68695,23879,68695,31937,68695,30399,68695,67263,68695, - 9,68695,10001,68721,67241,68721, 15,68460,19549,68727,19553,68727, -10093,68727,10085,68727, 3,68727,68619,68737,68635,68727,20345,68727, -20281,68727,10087,68727,20285,68727,19555,68727, 483,68727,10081,68753, -20273,68753,19545,68753, 7,68460,58715,68761, 375,68761, 7,68461, -58703,68767,58027,68767,60849,68767,68345,68767,35603,68767, 59,68767, - 1325,68767, 331,68767, 265,68767, 241,68766, 241,68461, 6,68789, - 7,68789, 6,68788,68793,68795, 7,68788,68791,68799, 265,68460, - 375,68803, 1011,65869,59960,68807,61780,68806,63014,68806,62538,68806, -17455,68806,47640,68806, 5843,68806,48534,68806, 483,68806,60857,68824, - 9,68806,60857,68828,46863,68806,60857,68832, 903,68832, 11,68833, - 587,68832, 587,68806,46863,68842, 11,68807,46863,68847, 7,68807, -56555,68850,63823,68851, 9377,68851, 903,68806,46863,68858,56555,68807, - 6,68863, 7,68863, 6,68862,68867,68869, 7,68862,68865,68873, -60857,68806, 7,68877, 483,68876,46863,68876, 9,68876,62942,65869, - 7,68887,46863,68886, 9,68886, 483,68886,60857,65869,58782,68896, -58362,68896,47608,68896, 1108,68896, 1072,68896, 165,68896, 524,68896, - 1291,68896, 11,68897, 483,68915, 9,68896, 1011,68918, 587,68897, - 483,68923,46863,68896,56555,68926, 1011,68926, 483,68896,56555,68932, - 587,68933, 11,68933, 1011,68932, 11,68932, 11,68896, 483,68944, - 7,68897, 1141,68949, 1447,68949, 33,68949,56555,68896, 9,68957, -46863,68956, 483,68956, 1011,68896, 7,68965, 9,68964, 483,68964, -46863,68964, 265,65869,16710,68974,44242,68974,16711,68974,16710,68975, -68981,68983,45086,68975,44242,68975, 3,68988,44243,68974,68987,68993, -68991,68993,60797,68975,60796,68974,68999,69001,60796,68975,60797,68974, -69005,69007, 3,68975,44242,69011,44242,69010,68993,69015, 6,69010, - 1274,68975,44243,68975,69013,69023,45087,68975,68979,69027,16711,68975, -68977,69031, 1275,68975, 4899,69035,14611,69035,47961,69035, 11,68974, - 9,69043,46863,68974,69019,69047,69021,69047, 9,68975, 11,69053, - 6,68974, 0,69056,69035,69059, 7,68974,25793,69063,41019,69063, - 8717,69063, 8495,69063, 3785,69063, 6,68975, 3,69074,69047,69077, - 7,68975, 8647,69081,21605,68975, 375,69085,18967,68974, 375,69089, - 11,65869,39085,69093,49204,69092, 33,69097, 803,69093,63014,69092, -25381,69092, 265,69092, 9,69107,60857,69092, 483,69110, 483,69092, -60857,69114, 1275,69092, 9,69119, 2,69092,44243,69123, 3,69092, - 33,69127,46863,69129,46863,69126, 33,69133, 3,69093,49283,69137, -47546,69137, 113,69137,46863,69142,46863,69137, 113,69146,46863,69092, - 3,69150, 33,69153, 3,69151, 113,69157,20034,65869, 375,69161, -48560,65869, 3,69164, 33,69167, 3,69165, 113,69171,59206,65869, - 7,69175,29598,65869, 7,69179,60455,65869, 256,69183, 375,69183, - 7,69183, 241,69188, 241,69183, 7,69192,15029,65869,56555,69196, - 7,69199,28715,65869, 256,69203, 1505,69202, 7,69203, 241,69208, - 241,69203, 7,69212, 903,69202, 7,69217,54027,65869, 375,69221, - 2,69220,54159,69225,46863,69227, 2,69221,54256,69231,46863,69231, -54225,69234,54225,69231,46863,69238,17635,65869, 7,69243, 2,69244, - 2,69245, 1368,69243, 1369,69243, 2,69242,69253,69255, 3,69242, -69247,69259,69251,69259, 2,69243, 7,69264,69259,69267, 3,69243, -69249,69271, 2,65868,41692,69275,41607,69275, 8672,69275, 8743,69275, -26454,69275,26375,69275, 8770,69275, 8729,69275, 3795,69275,47953,69275, -48062,69275,47961,69275,48009,69298,48009,69275,47961,69302,41417,69275, -41653,69306,26219,69275,26415,69310,31770,69275,44832,69275, 8757,69275, - 8647,69318,26415,69275,26219,69322,41653,69275,41417,69326, 8647,69275, - 305,69330, 8757,69330, 8605,69275,47580,69275,47933,69339, 8684,69275, - 8717,69343, 8916,69275,31103,69275, 9,69348,26292,69275,26331,69353, - 340,69275, 8717,69357, 3785,69357, 8495,69357, 375,69275, 8861,69364, -46863,69364,47488,69275,41502,69275,41559,69373, 483,69275,44243,69376, - 305,69275, 8647,69380, 7,69275, 1,69385, 264,69386, 264,69387, -41019,69385,41653,69393,25793,69385,26415,69397, 8495,69385, 305,69401, - 8757,69401, 8495,69384, 8717,69407,25793,69384,26331,69411, 265,69385, -69391,69415, 8861,69415,46863,69415,41019,69384,41559,69423, 265,69384, - 8717,69427,69389,69427, 3785,69427, 8495,69427,44243,69275, 483,69436, - 9,69275,31103,69440,46863,69275, 265,69445,48009,69447, 265,69444, -47933,69451, 375,69444,25793,69275, 7,69457,26219,69459, 7,69456, -26331,69463, 265,69275,46863,69467,47961,69469,46863,69466,47933,69473, - 7,69467, 8647,69477, 7,69466, 8717,69481, 3785,69481, 8495,69481, -41019,69275, 7,69489,41417,69491, 7,69488,41559,69495, 8495,69275, - 7,69498, 8717,69501, 7,69499, 8647,69505, 8861,69275, 375,69508, - 3,65868,21116,69513,21253,69513,21560,69513,20465,69513,20576,69513, -59683,69513,42035,69513, 9573,69513,59689,69513, 9575,69513,42041,69513, -43711,69513,42089,69513,42129,69513, 1,69513, 6,69543,68974,69544, -68975,69545,69547,69549,68974,69545,68975,69544,69553,69555, 4,69513, - 6,69558,66665,69561,66785,69561,66997,69561,68695,69561, 9599,69513, - 8,69513,66997,69573,66785,69573,66665,69573,68695,69573,67011,69513, -66805,69513,68721,69513,66693,69513,60569,69513,59701,69513,59767,69513, - 9605,69513,32468,69513,28483,69513,19625,69513,20501,69602,43015,69513, -44714,69513,19474,69513,20413,69611,20805,69513,20186,69513,21549,69513, -20501,69618,21105,69513,20501,69622, 1418,69513,59619,69627, 9565,69627, -41941,69627, 669,69513, 9565,69635,59619,69635,41941,69635,37501,69513, -31103,69513,27021,69644, 8386,69513,50657,69513,36944,69513,48408,69513, - 1369,69513, 15,69656, 9565,69659,41941,69659,59619,69659, 483,69513, -46863,69666,20501,69513,21105,69670,21549,69670,19625,69670, 6,69513, - 3,69679,56555,69681,65869,69683, 4,69678,66665,69687,66785,69687, -66997,69687,68695,69687,69685,69687, 3,69678,68460,69699,69687,69701, -18967,69699,65869,69704,69687,69707,65869,69699,18967,69710,69687,69713, - 7,69513,20103,69716, 8337,69716,36773,69716,27021,69513,31103,69724, - 7,69512,24265,69729,28233,69729,29077,69729,20361,69729, 9673,69729, - 4279,69729, 9967,69729,19559,69729, 4283,69729,20713,69729, 3807,69729, - 8251,69729,44243,69513,41941,69754,46863,69513, 483,69758, 15,69513, -18967,69763,20501,69765,18967,69762,20413,69769, 1369,69762, 9565,69773, -41941,69773,59619,69773, 8337,69513, 7,69780,18967,69513, 15,69784, -20413,69787, 1011,69513,44242,69790,44242,69791,44243,69790,69795,69797, -44243,69791,69793,69801,28715,69513, 7,69805,36773,69513, 7,69808, -41941,69513,44243,69812,20103,69513, 7,69816,20273,69513, 6,69820, - 7,69820, 6,69821,69825,69827, 7,69821,69823,69831, 9617,69513, - 6,69834, 7,69834, 6,69835,69839,69841, 7,69835,69837,69845, - 6,65868, 1,69849, 3,69850, 4,69849, 3,69855,67988,69856, -67989,69857,69859,69861,67988,69857,67989,69856,69865,69867,21604,69849, - 3,69849, 1,69872, 7,65868,59007,69877,58999,69877,59025,69877, -19981,69877,48747,69877,37279,69877,57047,69877,57029,69877,58153,69877, - 1,69877, 2,69896,66625,69899,66825,69899,66973,69899,68415,69899, -58167,69877,56554,69877,66973,69911,66825,69911,66625,69911,68415,69911, -66987,69877,66845,69877,68441,69877,66653,69877,24601,69877,57437,69877, -57021,69877,57069,69877,54107,69877,52743,69877,52193,69877,20734,69877, -25551,69877,24613,69877,28205,69877,20501,69877, 265,69950, 241,69951, - 1141,69877,56555,69957,60577,69877,62959,69877,58377,69877,57981,69877, -19916,69877, 7947,69969,48739,69969,37241,69969,58931,69877,48739,69977, - 7947,69977,37241,69977, 8306,69877, 33,69877,56555,69987, 1447,69877, -56555,69991, 9875,69877, 241,69995, 265,69994, 9992,69877, 545,69877, - 695,69877, 1382,69877, 1374,69877, 1386,69877, 154,69877, 483,70013, -60455,69877, 483,70017, 1369,69877, 331,70020, 1325,70020, 59,70020, - 1325,69877, 1369,70028, 1275,69877,18967,70032,48739,70035,37241,70035, - 7947,70035, 59,69877, 1369,70042, 2,69877, 7,70047, 9,70049, -65869,70051, 1,70046,66625,70055,66825,70055,66973,70055,68415,70055, -70053,70055, 7,70046,68176,70067,70055,70069, 15,70067,65869,70072, -70055,70075,65869,70067, 15,70078,70055,70081, 3,69877, 8241,70085, - 15,70084, 483,70089, 331,69877, 1369,70092, 3,69876,24265,70097, -28233,70097,29077,70097,19559,70097,20713,70097, 4283,70097,20361,70097, - 9673,70097, 4279,70097, 9967,70097, 8251,70097, 3807,70097,18967,69877, - 1275,70122,48739,70125,37241,70125, 7947,70125, 113,70123, 1011,69877, - 265,69877,20501,70136, 8165,70136, 9875,70136,46863,69877,38056,70144, -38056,70145,38057,70144,70149,70151,38057,70145,70147,70155, 15,69877, - 3,70159, 1369,70161, 3,70158, 483,70165,54027,69877, 483,70169, - 8165,69877, 265,70172, 7,65869,69874,70176,69875,70177,70179,70181, -69875,70176,69874,70177,70185,70187,69852,70176,69853,70177,70191,70193, -69853,70176,69852,70177,70197,70199,11276,70176,11277,70176,11276,70177, -70205,70207, 5044,70176, 5045,70176, 5044,70177,70213,70215,40583,70177, -40583,70176,40582,70176,70219,70223,40582,70177,70221,70227,24094,70177, -69871,70177,69870,70177,21604,70177,69849,70236, 9,70236,21604,70176, -70233,70243,69849,70243, 9,70243, 4,70177, 0,70250, 1,70177, - 264,70254, 264,70255,24095,70177,70243,70261,45149,70177,26498,70177, -41326,70177, 8796,70177,27533,70177, 9,70273,25793,70177,27021,70277, - 587,70276, 241,70277, 5045,70177,70211,70285,11277,70177,70203,70289, - 4551,70177,10001,70177, 9,70295, 8495,70177, 305,70299, 587,70298, - 241,70299, 88,70177, 1369,70307, 587,70177,25793,70310,41019,70310, - 8495,70310, 1369,70177,20103,70319,36773,70319, 8337,70319, 265,70177, -70259,70327,63493,70327, 8861,70327,46863,70327, 89,70177,46863,70337, - 483,70177,18967,70341,37241,70343,48739,70343,70253,70343, 7947,70343, - 1275,70177,44243,70353,21605,70176,70231,70357,70235,70357,70239,70357, -70241,70357,70237,70357,69849,70367, 9,70367,26331,70357,23755,70357, -27805,70357, 241,70176,25793,70379,59875,70379,41019,70379, 8495,70379, - 9805,70379,53391,70379, 903,70176,25793,70393, 8495,70393,41019,70393, -18967,70176,58715,70401, 375,70401, 265,70176,70257,70407,25793,70407, -41019,70407, 8717,70407, 8495,70407, 3785,70407,21605,70177,70246,70421, -69849,70421,70243,70424,70248,70421,70243,70421,69849,70430, 9,70430, -24545,70421, 9,70421,70243,70438, 903,70421, 241,70177,51487,70445, - 375,70177, 1369,70449,41019,70177, 587,70452, 241,70453, 2,70176, -48009,70459, 265,70459,46863,70463,49321,70459,49001,70459, 3,70176, -58056,70471,58601,70471,40799,70471,44243,70471,56555,70478,35927,70471, - 375,70471, 510,70471, 483,70471, 9,70488,38155,70471,37611,70471, -56555,70471,44243,70496, 9,70471, 483,70500, 2,70177,44243,70505, -48466,70505,47640,70505,46863,70505, 9,70512, 903,70512, 903,70505, -46863,70518, 9,70505,46863,70522,49155,70505, 3,70177, 1369,70529, - 9,70531,37663,70529, 9,70528, 1369,70537,18967,70529,44243,70541, -69849,70177,21604,70545,70421,70547,21604,70544,70357,70551, 9,70177, -21604,70555,70421,70557,21604,70554,70357,70561, 3,70554, 1369,70565, - 3,70555, 483,70569, 3,65869,60078,70572,60079,70572,13748,70573, -13736,70572,70579,70581,13736,70573,13737,70572,13749,70573,70587,70589, - 1,70573, 5,70592, 1,70572,69385,70597,69384,70597,69275,70597, - 7,70602, 7,70603,59961,70597, 6,70596,70601,70611,70605,70611, - 7,70596,70599,70617,69275,70617, 6,70597,69275,70623,70617,70624, -70607,70623,70620,70623,70617,70623,69275,70632,56555,70623, 7,70597, -69275,70638,70611,70641,70611,70639,69275,70645,48560,70572, 33,70649, -60230,70573,57986,70573,58352,70573, 8309,70573,13737,70573, 7,70660, -70581,70663,59960,70573,70575,70667,70611,70667, 241,70666, 256,70573, -56555,70674, 11,70573,48583,70679,48328,70679, 25,70679,46863,70684, -46863,70679, 25,70688,59961,70573,70577,70693, 483,70573, 15,70697, -41941,70699, 9565,70699,70595,70699,59619,70699, 1369,70573,46863,70709, -37409,70573,46863,70713,46863,70572, 11,70716, 33,70719, 1369,70717, - 11,70717, 25,70725,37409,70717, 15,70572,40909,70731, 11,70572, - 33,70735,46863,70737,46863,70734, 33,70741, 6,70572, 1,70744, -70667,70747, 5,70744, 7,70572,70609,70753,58056,70753,70636,70753, -70623,70753,56555,70760,40799,70753,58601,70753,44243,70753,56555,70768, -35927,70753, 375,70753, 510,70753, 483,70753, 9,70778,38155,70753, -37611,70753, 9,70753, 483,70786,56555,70753,70623,70790,44243,70790, - 6,70573,70731,70797,56555,70797, 7,70573,13737,70802,70581,70805, -13737,70803,70585,70809,70611,70803,56555,70813,70747,70803,56555,70817, -70751,70803,42613,70803,56555,70823,54497,70803,54159,70803,51803,70803, -58348,70802,10291,70803,56555,70835, 59,70803, 1325,70803, 331,70803, - 1275,70803, 9,70845,56555,70802,70611,70849,70747,70849, 241,70848, - 241,70802,56555,70856, 15,70803, 483,70861,69275,70573,58348,70573, - 7,70866,38057,70573, 7,70871,43503,70573,44243,70875,56555,70573, - 256,70878, 7,70878,70611,70883,70747,70883, 241,70882, 7,70879, -70623,70891, 241,70878, 7,70894, 241,70573,44242,70899,44242,70898, -44243,70899,70903,70905,59960,70898,44243,70898,70901,70911, 7,70898, -56555,70914,56555,70898, 7,70918, 2,65869, 1,70922,69635,70925, - 668,70925,69513,70929,69627,70925, 1419,70925,69513,70935,70699,70925, -69659,70925,69773,70925, 587,70925, 9,70944,69513,70947, 9,70925, - 587,70950,69513,70953,54027,70922,54159,70957,46863,70959,54027,70923, -54154,70963,46863,70963,54129,70966,54129,70963,46863,70970,44243,70923, - 11,70975,46863,70922, 11,70922,44243,70981, 6,70922, 0,70985, - 5,70986, 5,70985, 0,70991, 0,70990, 1,70984,70995,70997, -70989,70997,70987,70997, 5,71003, 1,70985,70993,71007, 5,71007, - 0,70984, 5,71013,71007,71014,71010,71013,71007,71013, 5,71020, - 903,70985, 1,71025, 0,71025, 1,71024,71029,71031, 0,71024, -71027,71035, 7,70922,48009,71039, 265,71039,46863,71043,49321,71039, -49001,71039, 7,70923,70989,71051,70997,71052,70995,71051,70997,71056, -70998,71051,71000,71051,71005,71051,71009,71051,71017,71051,71019,71051, -71023,71051,71011,71051,71013,71075,14219,71051,14013,71051,14267,71051, -16151,71051,70997,71051,70995,71086,70989,71086,56554,71051, 1,71051, - 2,71094, 2,71051, 1,71098,14211,71051, 9165,71103, 9,71051, -65869,71107,71093,71109,71097,71109,71101,71109,70985,71051,69513,70923, - 903,70923,46862,71120,46862,71121,46863,71121,71123,71127,46863,71120, -71125,71131, 6,65869, 1,71134,70803,71137,56555,71139, 4,71134, -69977,71143,58930,71143,69877,71147,69969,71143,19917,71143,69877,71153, -70343,71143,70035,71143,70125,71143, 587,71143,56555,71162,69877,71165, -56555,71143, 587,71168,69877,71171, 2,71134, 903,71175, 1,71177, - 0,71177, 1,71176,71181,71183, 0,71176,71179,71187, 2,71135, - 265,71191, 0,71192, 1,71192, 0,71193,71197,71199, 1,71193, -71195,71203, 3,71135, 8,71207, 4,71207, 6,71210, 6,71207, - 4,71214,56555,71207,65869,71219,71209,71221,71213,71221,71217,71221, - 0, 5,59619,71229,59961,71230,60166,71229, 1207,71228,19105,71237, - 1180,71228,19119,71241,60158,71228,60180,71228,60178,71228,60318,71228, -60167,71229, 1197,71228,59875,71255,53391,71255, 9805,71255,60159,71228, -60181,71228,60179,71228,38158,71229,44195,71269, 1196,71228,60319,71228, -28739,71229, 2,71277,29229,71279, 59,71228,60221,71283,63823,71228, -61747,71287,61585,71287,61475,71287,63185,71287, 39,71228,56555,71297, - 15,71299, 6,71298,71301,71303, 14,71299, 7,71298,71307,71309, - 1163,71228,19119,71313, 25,71228,61747,71317,63185,71317,25461,71317, -61585,71317,70985,71228,71086,71327,70997,71327,71051,71330,71051,71327, -70997,71334,38057,71229, 6,71338,44195,71341,60973,71229, 1179,71345, -49213,71229,49217,71349,54619,71229, 11,71353,54655,71355, 1003,71229, -60857,71359, 1007,71361,11995,71228,12025,71365,64569,71228,64587,71369, -61989,71228,61747,71373,63185,71373,61585,71373, 8065,71229, 11,71381, - 8067,71383,63777,71229,60857,71387,63779,71389,21918,71229, 987,71393, -54336,71229,54339,71397, 989,71229,21605,71400, 987,71403,21890,71229, - 1179,71407,49262,71229,49217,71411,54331,71229, 17,71414,54339,71417, -25395,71228,25461,71421, 1293,71228,61475,71425,25433,71228,25461,71429, -61005,71228,61475,71433,63014,71228, 5,71437, 7,71438, 7,71437, - 5,71442, 10,71437, 524,71228, 0,71449, 3,71450, 3,71449, - 0,71454,60856,71449,21904,71229, 25,71461, 809,71229,21605,71464, - 713,71467,13755,71229, 17,71470, 9377,71473,65054,71229,63823,71477, - 117,71229,21605,71480, 25,71483,21916,71229, 713,71487,13764,71229, - 9377,71491,65037,71229, 17,71494,63823,71497, 1177,71229,21605,71500, - 1179,71503,49229,71229, 17,71506,49217,71509,26867,71229,21605,71512, -26865,71515,10161,71229, 17,71518,10159,71521,26868,71229,26865,71525, -10162,71229,10159,71529, 1180,71229, 2975,71533, 1903,71533,19025,71533, -33464,71229,34655,71541,34447,71541,33221,71541,33773,71541, 1207,71229, -19027,71551, 3567,71551, 1973,71551, 3041,71551, 1921,71551,19049,71551, - 9824,71229,71273,71565,53462,71229,71273,71569,59900,71229,71273,71573, -60319,71229,71251,71577,60159,71229,71245,71581,60178,71229,71267,71585, -59901,71229,71255,71589,60158,71229,71263,71593,60180,71229,71265,71597, -25461,71229, 25,71601,25395,71601,25433,71601,61475,71229,63823,71609, - 1293,71609,61005,71609,65808,71229,65513,71617,65791,71617,65407,71617, -65171,71617,60835,71229,60318,71229,71275,71629, 9617,71629,19797,71229, - 375,71635,20735,71229,47386,71229,20040,71229,20050,71229,61747,71229, -63823,71647, 25,71647,61989,71647,63185,71229, 25,71655,63823,71655, -61989,71655,61585,71229,63823,71663, 25,71663,61989,71663,20056,71229, - 375,71671, 9825,71229,71255,71675,53463,71229,71255,71679,57562,71229, -58846,71229,58372,71229,58758,71229,58762,71229,57224,71229,57284,71229, -57278,71229,58760,71229,20686,71229,24738,71229, 305,71703, 713,71703, - 1489,71703, 25,71703,10074,71229, 9377,71713,17573,71713,63823,71713, -22766,71229, 305,71721, 25,71721, 147,71721, 713,71721,27672,71229, -63823,71731,27995,71731, 9377,71731,62147,71229, 25,71739, 305,71739, - 147,71739, 169,71739, 713,71739,31881,71229,63823,71751,27995,71751, -31359,71751, 9377,71751,60221,71229, 59,71761, 653,71229, 11,71765, - 9993,71229,17542,71229, 9936,71229,24734,71229, 305,71775, 713,71775, - 25,71775,60834,71229,21350,71229,16129,71229, 3,71787, 2,71787, - 842,71787, 843,71786,71793,71795, 843,71787, 842,71786,71799,71801, - 3,71786,71791,71805, 2,71786,71789,71809,16966,71229,19480,71229, -50522,71229,52740,71229,57380,71229,59108,71229,50478,71229,57252,71229, -19986,71229,51036,71229,57576,71229,58112,71229,58362,71229, 903,71836, -47640,71229,56555,71840,60179,71229,71249,71845,60181,71229,71247,71849, -63015,71229,71441,71853,71445,71853,62905,71853,63041,71853,63047,71853, -63215,71853, 6,71853,63205,71867,19687,71853,21127,71853,20843,71853, -63049,71853,71447,71853, 11,71853,63033,71881,71437,71881,19917,71229, - 9,71886, 525,71229,71453,71891,71457,71891,36729,71891, 1851,71891, - 1885,71891,35635,71891, 2,71891,35633,71905,62095,71891,17711,71891, - 4907,71891,61003,71891,71459,71891,60857,71891, 531,71919,71449,71919, - 1413,71229, 331,71925,49713,71924, 1419,71229,56555,71930,58782,71229, - 903,71934, 296,71229, 8861,71939, 1106,71229,18967,71943, 9617,71943, -24095,71229,46863,71949,57522,71229, 11,71953, 903,71952, 587,71952, -51004,71229, 483,71960,22956,71229,70471,71965,70753,71965,10159,71965, -26865,71965,10111,71965,26715,71965,23709,71965,23713,71965,67425,71965, -10113,71965,26719,71965,23715,71965, 587,71965,10107,71991,26625,71991, -23651,71991,19475,71229, 483,71998, 918,71229,56555,72002, 922,71229, -56555,72006,49713,72006, 668,71229,56555,72012, 1290,71229, 2,72017, -35575,72019,35585,72017, 3621,72017, 1991,72017,60969,72017,62095,72017, -17711,72017, 4907,72017,60857,72017, 1325,72037,58930,71229, 9,72040, -52692,71229, 903,72044,25380,71229, 6,72049,38881,72051,38891,72049, - 9927,72049, 9891,72049, 9895,72049,19687,72049,21127,72049,20843,72049, - 11,72049, 9875,72069, 1447,71229,15705,72073, 9917,71229,20615,71229, - 759,71229,17455,72081, 9195,71229, 1487,72085, 1471,71229,21605,72088, - 305,72091, 713,72091, 1489,72091, 25,72091, 9805,71229, 1197,72101, - 1275,72101, 9,72105, 1197,72100,71273,72109,10001,71229, 17,72112, - 9377,72115,17573,72115,63823,72115,17455,71229,12377,72122,59961,71229, -59619,72126, 1011,72126, 9617,72131, 1011,72127, 9565,72135,59619,72135, - 89,71229,17455,72141,60797,71229,59381,72144, 165,71229,21315,72148, - 587,71229,66971,72153,17455,72153,57522,72152, 9,72152,56555,72160, -56555,72152, 9,72164,60857,72153, 9,72169, 1369,71229,39085,72173, -21605,72172,20843,72177,21127,72177, 9927,72177, 9891,72177,19687,72177, - 9895,72177, 11,72177, 9875,72191, 1275,71229, 17,72194, 4907,72197, -17711,72197, 3621,72197, 1991,72197,62095,72197,60969,72197,60857,72197, - 1325,72211, 483,71229,20035,72214,58742,72214,19475,72214,51004,72214, -56555,72214, 903,72224, 903,72214,56555,72228,49713,72228,49713,72214, - 903,72234,55839,71229,46863,72239,65061,71229,60857,72243,65063,72245, -65067,72245,65071,72245, 7065,71229,18967,72253, 6789,71229, 11,72257, - 6843,72259, 6885,72259, 6889,72259,11277,71229,46863,72267, 9935,71229, - 1011,72270,20645,71229, 1011,72274, 3445,71229, 375,72279, 5045,71229, -46863,72283,17104,71229,48643,72287,12614,71229, 375,72291,69872,71229, -68155,72295,71116,71229,71013,72299,70985,71229,71013,72303,71051,72305, -71051,72302,71013,72309,71051,71229,70985,72313,70997,72315,70985,72312, -71013,72319, 482,71228,23717,72323,24522,72323,24447,72323,23939,72328, -23939,72323,24447,72332,22956,72323,23651,72337,21605,72323, 17,72341, -23939,72343, 17,72340,23651,72347, 17,72323,21605,72351,24447,72353, -21605,72350,23651,72357, 1368,71228, 7,72361, 5,72362,72049,72365, -72177,72365, 5,72361, 7,72370,72049,72373,72177,72373,72191,72361, -72069,72361, 10,72361,72177,72383,72049,72383,27021,72361,24095,72361, - 9195,72361,52915,72361,23651,72361,51435,72361,21605,72361, 9,72401, -67297,72361,70097,72361,69729,72361,11277,72361, 5045,72361,10171,72361, -53941,72361, 9755,72361,26907,72361, 4321,72361,27323,72361, 3833,72361, - 9317,72361, 4295,72361,53215,72361, 1274,71228, 3,72435, 0,72436, -72017,72439,72197,72439, 0,72435, 3,72444,72017,72447,72197,72447, -72211,72435,72037,72435,60856,72435,72197,72457,72017,72457, 586,71228, -39619,72463,51421,72463,57811,72463,59933,72463,59743,72463, 8093,72463, - 3837,72463,42435,72463, 4287,72463,53703,72463, 4303,72463,42113,72463, - 9839,72463,53487,72463, 9579,72463, 483,72463, 803,72494, 828,72463, - 705,72463, 803,72463, 483,72502, 482,71229,66737,72507,36661,72507, -62741,72507,68727,72507,68381,72507, 1274,71229, 587,71228,61747,72521, -25461,72521,61475,72521,63185,72521,61585,72521, 483,71228,56555,72533, - 6,72535, 5,72536, 7,72535, 5,72535, 6,72542, 6,72543, -72541,72547, 6,72534, 15,72535,72551,72553, 7,72534,72545,72557, -72539,72557, 14,72535,72557,72563, 1368,71229,55839,72567,51803,72567, -54159,72567,54497,72567, 265,72567, 1275,71228,59914,72579,60221,72579, -18708,72579, 9856,72579,53504,72579, 9805,72579, 9,72590,53391,72579, - 9,72594,59875,72579, 9,72598,18693,72579, 9,72602,60369,72579, - 9,72579,18693,72608, 9805,72608,59875,72608,53391,72608, 586,71229, - 33,72619, 1447,72619, 1141,72619, 889,72619, 795,72619, 787,72619, - 767,72619, 483,72633, 1505,71229,16937,72636,56555,72636, 581,71229, -60857,72643, 1325,72645, 331,72645, 571,72645, 585,72645, 59,72645, -16937,71229, 1505,72656,13947,71229, 2,72661,14217,72663, 11,72661, - 9875,72667,16091,72667,13955,72667,20501,72667, 9919,71229,20623,71229, - 9921,71229, 1196,71229,72103,72683,71256,72683,71258,72683,71260,72683, -71255,72683,59875,72692,53391,72692, 9805,72692,59875,72683,71255,72700, - 9805,72683,71255,72704,53391,72683,71255,72708, 154,71229,64148,71229, - 1325,72715, 59,72715, 331,72715, 265,72715,52501,71229, 265,72725, - 297,71229,18967,72729, 1107,71229,59960,71229,21105,72735,65513,72735, -65791,72735,65407,72735,21549,72735,19625,72735,65171,72735,59619,72735, - 15,72735, 88,71229,70177,72755,70176,72754,72757,72759,70176,72755, -70177,72754,72763,72765, 1141,72755, 1447,72755, 33,72755, 11,72755, -37409,72755, 972,71229, 59,72779, 1325,72779, 331,72779,27978,71229, -60796,71229,59381,72789,31102,71229,62905,72793,68761,72793,70401,72793, -67541,72793, 164,71229,36729,72803,68447,72803,70731,72803,67547,72803, -54596,71229,44243,72813,20695,71229, 155,71229,20763,71229, 375,72820, - 1197,71229,71273,72825,59875,72827, 9805,72827,53391,72827,53391,72824, -71273,72835, 9805,72824,71273,72839,59875,72824,71273,72843, 375,71229, -20763,72846,20836,71229, 1141,71229,15705,72853, 33,71229,15705,72857, -27021,71229, 1487,72861, 959,71229,17455,72865,52915,71229, 1487,72869, - 47,71229,17455,72873,59875,71229, 1197,72877,72683,72879, 1275,72877, - 9,72883, 1197,72876,71273,72887, 253,71229,21605,72890, 305,72893, - 25,72893, 713,72893,53391,71229, 1197,72901,72683,72903, 1275,72901, - 9,72907, 1197,72900,71273,72911, 53,71229,21605,72914, 305,72917, - 25,72917, 147,72917, 713,72917,27533,71229, 17,72926,63823,72929, -27995,72929, 9377,72929,30749,71229, 7,72937,26970,71229, 7,72941, -70864,71229, 7,72945,69849,71229, 3,72948,68155,72951, 3,72949, -67577,72955,68139,72955,70979,72955,69275,71229,70573,72962, 7,72965, -69513,71229, 1011,72968, 7,72971, 9780,71229, 7,72975,59381,71229, - 2,72979,72789,72981,60797,72978, 6,72978,56555,72986,72981,72989, -26625,71229, 1011,72992, 7,72995, 9731,71229, 1011,72998, 7,73001, -69790,71229, 7,73005, 13,71229,32805,71229, 7,73010,33221,73013, -34655,73013,33773,73013,34447,73013, 15,73011,34875,73023, 7,73011, -34723,73027, 19,71229, 59,73031, 18,71229,65076,71229, 7,73037, -65493,73039, 7,73036,65171,73043,65791,73043,65513,73043,65407,73043, - 15,73037,65357,73053, 12,71229,68974,71229, 375,73059,71119,71229, - 7,73063, 1011,71229,52387,73067,20762,73067,59961,73066, 9617,73073, -20645,73066, 9935,73066, 17,73066,18967,73081, 9617,73081, 6,73066, - 7,73067,18967,73088,26625,73066, 7,73093,18967,73067, 7,73096, - 17,73097, 9731,73066, 7,73103,69513,73066, 7,73107,21315,73066, - 7,73111, 15,71229,18967,73115, 17,73117, 3,73114, 3,73115, -72567,73123, 17,73114, 265,71229, 9,73128, 8861,73131,60857,73129, - 9,73135,65869,73128, 375,73139, 11,71229,60857,73143, 9,73145, - 1275,73143, 9,73149, 9,73142,60857,71229, 7,73154, 59,73157, - 1325,73157, 331,73157, 265,73157, 7,73155, 375,73167, 265,73155, - 375,73171,12377,73154, 7,73175,18967,71229, 7,73179,25793,73181, -41019,73181, 8495,73181,46863,71229,20035,73188,58742,73188, 903,73188, -56555,73194,56555,73188, 903,73198,20035,71229,21183,73203, 7,73203, - 331,73207, 483,73202,46863,73202, 9,73202, 7,73202, 375,73217, -49713,71229,39085,73221, 136,73220, 1197,73220, 137,73220, 922,73220, - 1413,73220, 1011,73220, 6,73234, 483,73220, 903,73238, 903,73220, - 483,73242, 2,73220, 9,73246,44243,73247, 3,73220, 5,73253, - 6,73255, 9,73253, 2,73221,73257,73261,73229,73261,73258,73261, -29229,73261,72683,73261,73237,73261,73087,73261, 9,73261,73253,73276, -73253,73261, 9,73280, 3,73221,73225,73285,73249,73285,73227,73285, -73247,73285, 9,73293, 9,73220, 2,73296,73285,73299, 2,73297, -73253,73303, 17,71229,10161,73306,10159,73309,54339,73307,54331,73313, -49217,73307,49229,73317,54331,73306,54339,73321,49229,73306,49217,73325, -65037,73306,63823,73329,13755,73306, 9377,73333,27995,73307,27533,73337, -17573,73307,10001,73341, 7,73306, 3,73345, 7,73346,73307,73349, - 1,73346,73351,73353, 1,73345, 3,73356,21604,73345, 0,73306, - 3,73363, 0,73364,73307,73367, 6,73364,73369,73371, 6,73363, - 3,73374, 1274,73363, 586,73306, 3,73381, 1,73382, 1,73381, - 3,73386,21604,73381,60856,73306, 3,73393, 6,73394, 6,73393, - 3,73398, 1274,73393,10001,73306,63823,73405, 9377,73405,17573,73405, -27533,73306, 9377,73413,63823,73413,27995,73413, 9377,73307,13755,73421, -27533,73421,10001,73421,63823,73307,65037,73429,10001,73429,27533,73429, -60857,73307,63697,73437,63779,73437,73397,73437,73401,73437,73371,73437, -73377,73437, 7,73437,63709,73437,35893,73437,37897,73437,38299,73437, -73379,73437,73403,73437, 1275,73437,63679,73465,73363,73465,73393,73465, - 587,73307, 1971,73473, 3507,73473,73385,73473,73389,73473, 5231,73473, -73353,73473,73359,73473, 0,73473,21783,73473,23983,73473, 4625,73473, -10603,73473,73361,73473,73391,73473,21605,73473, 713,73503,73345,73503, -73381,73503, 1011,73306,18967,73511, 9617,73511, 1275,73306,72439,73517, -72447,73517, 3621,73517, 1991,73517, 1,73517,73473,73527,73489,73517, -60969,73517,62095,73517, 4907,73517,17711,73517,72457,73517,60857,73517, - 1325,73543,72435,73543,21605,73306,23713,73549,23709,73549,26865,73549, -26715,73549, 6,73549,73437,73559,73451,73549,10159,73549,10111,73549, -26719,73549,10113,73549,67425,73549,70753,73549,70471,73549,23715,73549, - 587,73549,26625,73581,10107,73581,23651,73581, 1011,73307, 9565,73589, - 2,73306,36729,73593,68447,73593,67547,73593,70731,73593, 2,73307, -36727,73603,68451,73603,37895,73603,36079,73603,35575,73603, 15,73306, -21605,71229,26867,73616,26865,73619, 1179,73617, 1177,73623, 987,73617, - 989,73627, 1177,73616, 1179,73631, 989,73616, 987,73635, 809,73616, - 713,73639, 117,73616, 25,73643, 1489,73617, 1471,73647, 147,73617, - 53,73651,26219,73617, 5,73616, 7,73657, 5,73658,73617,73661, - 2,73658,73663,73665, 2,73657, 7,73668, 1368,73657, 3,73616, - 7,73675, 3,73676,73617,73679, 4,73676,73681,73683, 4,73675, - 7,73686, 16,73675, 10,73616, 7,73693, 2,73694, 2,73693, - 7,73698, 1368,73693, 586,73616, 7,73705, 4,73706, 4,73705, - 7,73710, 16,73705,44243,73617,48466,73617, 340,73617, 1397,73617, - 53,73616, 713,73725, 305,73725, 25,73725, 147,73725, 1471,73616, - 25,73735, 305,73735, 713,73735, 1489,73735, 25,73617, 117,73745, - 253,73745, 1471,73745, 53,73745, 713,73617, 809,73755, 253,73755, - 53,73755, 1471,73755, 253,73616, 305,73765, 25,73765, 713,73765, - 305,73617, 253,73773, 1471,73773, 53,73773, 9,73617,46863,73780, - 587,73617, 9381,73785, 9439,73785,73709,73785,73713,73785,25519,73785, -73683,73785,73689,73785, 5,73785, 9383,73785,62077,73785,64317,73785, -64815,73785,73691,73785,73715,73785, 17,73785, 9377,73815,73675,73815, -73705,73815, 11,73617, 7979,73823, 8067,73823,73697,73823,73701,73823, -73603,73823,73665,73823,73671,73823, 3,73823, 7981,73823,39747,73823, -43027,73823,43837,73823,73673,73823,73703,73823, 1369,73823, 7971,73853, -73657,73853,73693,73853, 17,73616,23709,73861,23713,73861,10159,73861, -10111,73861, 2,73861,73823,73871,73839,73861,26865,73861,26715,73861, -10113,73861,26719,73861,67425,73861,70471,73861,70753,73861,23715,73861, - 587,73861,10107,73893,26625,73893,23651,73893, 1369,73616,72365,73901, -72373,73901, 9927,73901, 9891,73901, 4,73901,73785,73911,73801,73901, - 9895,73901,19687,73901,20843,73901,21127,73901,72383,73901, 11,73901, - 9875,73927,72361,73927,46863,73617, 9,73932, 6,73616,62905,73937, -68761,73937,70401,73937,67541,73937, 7,73616, 6,73617,62883,73949, -68767,73949,64267,73949,62235,73949,38881,73949,73437,73949,73947,73949, -72787,73949, 7,73617,25793,73967,41019,73967, 8495,73967,73937,73967, -72793,73967, 265,73966, 265,73617, 6,73981, 7,73981, 6,73980, -73985,73987, 7,73980,73983,73991, 903,71229,64148,73995,57522,73994, -58782,73994,58362,73994,52501,73995,52692,73994,46863,73994,56555,74008, - 9,73994,56555,74012, 483,73994,56555,74016,49713,74016,49713,73994, - 483,74022, 15,73995, 483,74027, 7,73994, 59,74031, 1325,74031, - 331,74031, 7,73995,60857,74038,59875,74039, 375,74039, 9805,74039, -53391,74039,60857,73995, 6,74051, 7,74051, 6,74050,74055,74057, - 7,74050,74053,74061,56555,73994, 7,74065,46863,74064, 483,74064, - 9,74064,58742,71229, 7,74075, 9,74074,46863,74074, 483,74074, -56555,71229,43502,74085,21036,74085, 6,74089, 6,74088,43503,74085, - 6,74095, 6,74094,21037,74085,59634,74085,59635,74085, 6,74105, - 6,74104,21104,74085,59645,74085,43838,74085,21548,74085,21526,74085, - 5,74118,59644,74085,19624,74085,18967,74085, 5,74126, 6,74128, - 6,74129, 6,74126, 5,74134, 6,74127, 14,74126,38305,74085, - 2,74142,59619,74085, 2,74146, 5,74085,59961,74151, 6,74151, -21526,74150, 6,74150,18967,74158,18967,74150, 6,74162, 6,74163, - 2,74085,59619,74168,38305,74168, 14,74085,18967,74174,21527,74085, -74155,74179, 9,74179,19625,74085,21549,74085,43839,74085,21105,74085, -47640,74084, 922,74084, 918,74084, 1505,74084, 668,74084, 1419,74084, - 483,74084, 903,74204, 11,74085, 9,74209, 15,74085,74139,74213, -46863,74084, 903,74216, 9,74084, 11,74221, 903,74220, 587,74220, - 587,74084, 9,74228, 6,74084,74191,74233,74189,74233,74187,74233, -74113,74233,74087,74233,74101,74233,74103,74233,74171,74233,74169,74233, -59619,74251,74149,74233,72981,74233,74185,74233,74145,74233,74173,74233, -74213,74233,59381,74233, 7,74084,74093,74269,74099,74269,74123,74269, -74109,74269,74159,74269,74089,74269,74095,74269,74105,74269,74151,74269, -74111,74269,74115,74269,74117,74269,74157,74269,74121,74269,21105,74269, -21549,74269,65513,74269,65791,74269,65407,74269,74125,74269,19625,74269, -65171,74269,74175,74269,74131,74269,74129,74269,74137,74269,74177,74269, -74161,74269,74165,74269,74163,74269,74141,74269,59619,74269, 15,74269, - 6,74085,21036,74336,74269,74339,43503,74336,74269,74343,59635,74336, -74269,74347, 5,74336,74269,74351,18967,74350,74269,74355,18967,74336, - 5,74358,74269,74361, 7,74085,74091,74365,74097,74365,74107,74365, -74155,74365,21183,74365,65493,74365,74133,74365,74167,74365, 9,74365, - 959,74365, 47,74365, 759,74365, 903,74084, 7,74391, 483,74390, - 9,74390,46863,74390, 9,71229,20035,74400,58742,74400,58930,74400, -19917,74400, 903,74400,56555,74410, 265,74400, 8861,74415, 587,74400, -56555,74418,56555,74400, 11,74423, 903,74422, 587,74422, 265,74401, - 8495,74431, 11,74431, 3,74400,70177,74437,70176,74436,74439,74441, -70176,74437,70177,74436,74445,74447, 1141,74437, 1447,74437, 33,74437, - 11,74437,37409,74437, 3,74401, 113,74461, 11,74400,21522,71229, - 7,74467,63452,71229, 7,74471,13673,71229, 7,74475,17049,71229, - 3,74478,48643,74481, 2,74479, 3,74479,48637,74487,49581,74487, -47813,74487,21315,71229, 165,74494, 1011,74494, 7,74499,16163,71229, - 2,74503,72683,74505,73087,74505,16171,74505, 375,74503,64669,71229, - 7,74515, 265,74517,12377,71229, 256,74521,17455,74520, 7,74520, - 375,74527, 7,74521, 241,74530, 331,74531,60857,74520, 7,74537, - 241,74521, 7,74540,10385,71229, 375,74545,70899,71229, 7,74549, -18391,71229, 7,74553,18617,71229, 7,74557,12705,71229, 7,74561, -70573,71229,69275,74564, 7,74567, 3,71228,74332,74571,72750,74571, -71253,74571,72985,74571,72147,74571,71783,74571,71577,74571,67600,74571, -45491,74571,42800,74571,59710,74571,74365,74593,74269,74571,59619,74596, -72735,74571,59619,74600,59694,74571,60563,74571, 629,74571, 101,74571, - 705,74571, 299,74571, 128,74571, 828,74571, 394,74571,48122,74571, -70327,74571,66930,74571, 9606,74571,10374,74571, 113,74571, 9,74632, -74465,74571,73153,74571,73031,74571,73057,74571,73131,74571,71939,74571, -72733,74571,74415,74571,72145,74571,59381,74653,42134,74571,10291,74571, - 17,74658,51992,74571, 375,74571, 241,74664,65869,74664,49713,74664, -60796,74571,74213,74673, 256,74571, 803,74571, 483,74678, 483,74571, - 803,74682,31103,74571,65869,74686, 6,74571,59619,74690,74365,74693, -56555,74690,74213,74697, 7,74571, 241,74700, 7,74570,57811,74705, -59933,74705,59743,74705, 9839,74705, 9579,74705,39619,74705,51421,74705, - 4287,74705, 4303,74705, 8093,74705, 3837,74705,53487,74705,42113,74705, -42435,74705,53703,74705,42613,74571, 17,74736,46863,74571,12377,74740, - 9,74571, 113,74744,49713,74571, 375,74748, 17,74571,42613,74752, -59619,74752,10291,74752, 9565,74752,41941,74752, 9565,74571, 7,74765, - 17,74764,65869,74571,60796,74771,60797,74771,31103,74770,60797,74770, -74773,74779,60796,74770,74775,74783, 375,74770, 241,74571, 375,74788, - 7,74788,56555,74571, 5,74795,74269,74797,72735,74797, 6,74797, -74365,74803, 6,74796,74269,74807,72735,74807, 14,74795,72735,74813, -74269,74813, 15,74795, 6,74795, 5,74820,74269,74823,72735,74823, - 7,74795,74803,74829, 6,74794,74213,74833,74819,74833, 7,74794, -74807,74839,74823,74839,71229,74838,74807,74845,74823,74845,74797,74845, -74813,74845,74813,74839,12377,74571,46863,74856,41941,74571, 7,74861, - 17,74860,59619,74571,74269,74866,72735,74866, 6,74866,74365,74873, - 6,74867,74269,74877,72735,74877, 7,74867, 17,74866, 2,71228, -71233,74887,56555,74887,72129,74887,72127,74887,59619,74895,71235,74887, -72790,74887,71627,74887,74153,74887,74155,74887,74365,74906,74372,74887, -74158,74887,74269,74913,74279,74887,74350,74887,74269,74919,74353,74887, -74266,74887,74150,74887, 6,74927,74365,74929, 6,74926,74269,74933, -74269,74927,74287,74887,74336,74887, 5,74940,74269,74943,60261,74887, -71629,74887,63737,74887,37179,74887, 9535,74887,63743,74887, 9537,74887, -37185,74887,74264,74887,74174,74887,74269,74965,74315,74887,73073,74887, -37887,74887,37205,74887,37235,74887,74085,74887, 5,74978, 6,74981, -74365,74983, 6,74980,74269,74987,74269,74981, 6,74978, 5,74992, -74269,74995, 6,74979,74213,74999, 14,74978,74269,75003, 5,74887, -74336,75006,74269,75009,74085,75006, 6,75013,74365,75015, 6,75012, -74269,75019,74269,75013,74085,75007,74233,75025, 6,75006,72735,75029, -74085,75028,74269,75033,74269,75029,74085,75029,74233,75039, 7,75006, -71853,75043,72049,75043,72177,75043,73901,75043, 6,75007,74365,75053, - 7,75007,72131,74887,72753,74887,74335,74887, 9563,74887,74382,74887, - 10,74887,72177,75069,72049,75069,71853,75069,73901,75069, 14,74887, -74085,75079,74233,75081,74085,75078,74269,75085,72735,75079,74269,75079, -72191,74887,72069,74887,73927,74887,71881,74887,64759,74887,63763,74887, -63813,74887, 9559,74887,74213,74887,74233,75108,74365,74887,74155,75112, - 9,75112,43123,74887,42606,74887,53318,74887, 9362,74887,27218,74887, -28189,74887,74233,74887,59381,75130,74213,75130,72789,74887,59381,75136, -64289,74887,26182,74887,28991,74887, 8804,74887,54289,74887,53802,74887, - 8150,74887, 1290,74887,63679,75155, 9533,75155,37145,75155, 525,74887, - 9533,75163,63679,75163,37145,75163, 922,74887, 1413,74887,73615,74887, -73127,74887,73009,74887,73035,74887,73081,74887,71943,74887,72729,74887, -73511,74887,41762,74887, 7971,74887, 9,75192,53517,74887, 9,75196, - 483,74887, 903,75200, 9195,74887, 9,75204, 1275,74887, 17,75208, - 9533,75211,37145,75211,63679,75211,27021,74887, 9,75218, 7,74887, - 2,75223,60857,75225,71229,75227, 5,75222,71853,75231,72049,75231, -72177,75231,73901,75231,75229,75231, 2,75222,73616,75243,75231,75245, -21605,75243,71229,75248,75231,75251,71229,75243,21605,75254,75231,75257, - 6,74887,74150,75260,74269,75263,74085,75260, 5,75266,74269,75269, -56555,75261,71229,75272,74085,75261,74155,75277, 9,75277, 5,75260, -72735,75283,74085,75282,74269,75287,74269,75283,74085,75283,74233,75293, -75275,75283, 11,75261,21604,75299,21604,75298,21605,75299,75303,75305, -21605,75298,75301,75309,52915,74887, 9,75312, 6,74886,23717,75317, -24522,75317,24447,75317,23939,75322,23939,75317,24447,75326,22956,75317, -23651,75331, 17,75317,21605,75335,24447,75337,21605,75334,23651,75341, -21605,75317, 17,75345,23939,75347, 17,75344,23651,75351, 7,74886, -27021,75355,24095,75355, 9195,75355,52915,75355,21605,75355, 9,75365, -67297,75355,26907,75355, 9755,75355, 9317,75355, 3833,75355,23651,75355, -51435,75355,27323,75355, 4321,75355,69729,75355,53215,75355, 4295,75355, -70097,75355,53941,75355,10171,75355, 5045,75355,11277,75355,42155,74887, - 9,75402, 19,74887, 12,74887, 11,74887, 9,75410, 9,74887, -74365,75414,42155,75414,27021,75414,52915,75414, 9195,75414,25793,75414, -53517,75414, 7971,75414, 8495,75414,41019,75414, 11,75414, 17,74887, - 1275,75438, 9533,75441,37145,75441,63679,75441, 8495,74887, 9,75448, - 903,74887, 483,75452,21605,74887,26219,75457,42810,75456,75056,75456, -75057,75457,75463,75465,75053,75457,42810,75457,75057,75456,75056,75457, -75473,75475,42811,75456,75471,75479,42811,75457,75461,75483,44243,75457, - 375,75457, 6,75457, 7,75457,25793,75493, 6,75456,75493,75497, - 7,75456,75491,75501,41019,74887, 9,75504,59381,74887,72789,75508, -74233,75508,25793,74887, 9,75514,26625,74887, 6,75518, 7,75518, - 6,75519,75523,75525, 7,75519,75521,75529, 9731,74887, 6,75532, - 7,75532, 6,75533,75537,75539, 7,75533,75535,75543,69513,74887, - 6,75546, 7,75546, 6,75547,75551,75553, 7,75547,75549,75557, - 7,71228,73276,75561,27306,75561,73261,75561, 9,75566,24095,75561, -52603,75561,53910,75561,55537,75561,20053,75561,20831,75561,19783,75561, -64289,75561,27021,75561,25793,75586, 265,75587, 959,75561,60857,75593, -58775,75561, 5045,75561,11277,75561, 4551,75561,70136,75561,10196,75561, - 273,75561, 1477,75561, 281,75561, 948,75561, 1516,75561, 922,75561, - 1413,75561,52915,75561, 265,75623, 47,75561,60857,75627,25793,75561, -27021,75630, 9195,75561, 265,75635, 759,75561,60857,75639, 89,75561, - 5019,75643,60857,75643, 1505,75561, 1011,75648, 587,75561,60857,75653, -70573,75653, 1369,75561,43503,75659, 483,75561, 903,75662, 165,75561, - 903,75666, 1141,75561,18967,75671, 1447,75561,18967,75675, 2,75561, -61780,75679, 9,75679,60857,75682,54295,75679,70085,75679,53925,75679, -10155,75679,11529,75679,60857,75679, 9,75696, 3,75561,73221,75701, - 9,75703, 8063,75701,53667,75701,42361,75701, 33,75561,18967,75713, - 2,75560,27021,75717,24095,75717, 9195,75717,52915,75717,21605,75717, - 9,75727,67297,75717,23651,75717,51435,75717,27323,75717, 4321,75717, - 9755,75717,26907,75717, 9317,75717, 3833,75717,69729,75717,53941,75717, -10171,75717,70097,75717,53215,75717, 4295,75717, 5045,75717,11277,75717, - 3,75560,57811,75765,59933,75765,59743,75765,39619,75765,51421,75765, - 4287,75765, 4303,75765, 9839,75765, 9579,75765, 8093,75765, 3837,75765, -42113,75765,53487,75765,42435,75765,53703,75765, 265,75561,53813,75796, -69877,75796,10107,75796, 1011,75561, 1505,75804,54597,75805,21605,75561, - 9,75811, 145,75811, 903,75561, 165,75816, 483,75816,54295,75817, - 9,75561,73261,75824,69877,75561, 265,75828,10107,75561, 265,75832, -53813,75561, 265,75836, 6,71228,63091,75841,63099,75841,63117,75841, -25451,75841,53597,75841,42283,75841,61289,75841,61281,75841,62345,75841, - 0,75841, 3,75860,71891,75863,72017,75863,72197,75863,73517,75863, - 3,75861,62359,75841,60856,75841,72197,75877,72017,75877,71891,75877, -73517,75877,72211,75841,72037,75841,73543,75841,71919,75841,19739,75841, -61649,75841,61263,75841,61323,75841,20763,75841, 1011,75903, 1010,75902, -75905,75907, 1010,75903, 1011,75902,75911,75913,25380,75841, 7971,75917, -53517,75917,42155,75917,63015,75841,53517,75925, 7971,75925,42155,75925, - 1369,75841,21605,75932,53517,75935,42155,75935, 7971,75935, 3,75841, - 6,75943, 11,75945,71229,75947, 0,75942,71891,75951,72017,75951, -72197,75951,73517,75951,75949,75951, 6,75942,73306,75963,75951,75965, - 17,75963,71229,75968,75951,75971,71229,75963, 17,75974,75951,75977, - 2,75841,60857,75981, 16,75983, 16,75982, 17,75983,75987,75989, - 17,75982,75985,75993, 2,75840,23717,75997,24522,75997,23939,75997, -24447,76002,24447,75997,23939,76006,22956,75997,23651,76011,21605,75997, - 17,76015,23939,76017, 17,76014,23651,76021, 17,75997,21605,76025, -24447,76027,21605,76024,23651,76031,21605,75841, 1369,76034,53517,76037, -42155,76037, 7971,76037, 17,75841,37844,76044,75872,76044,75873,76045, -76049,76051,37844,76045,75873,76044,75872,76045,76057,76059,37845,76044, -76055,76063,37845,76045,76047,76067, 7,71229,74797,76071,74829,76073, - 264,76071, 5,76071, 3,76078, 3,76079, 5,76070,75925,76085, -63014,76085,75841,76089,75917,76085,25381,76085,75841,76095,75935,76085, -76037,76085, 483,76085,60857,76102,75841,76105,60857,76085, 483,76108, -75841,76111,32805,76070,34655,76115,33773,76115,34447,76115,33221,76115, -32805,76071,34003,76125,33319,76125,34447,76071,35031,76131,65407,76071, -65335,76135,65076,76070,65513,76139,65791,76139,65407,76139,65171,76139, -65076,76071,65625,76149,65267,76149,20035,76070, 375,76155,74794,76071, -59381,76159,74819,76159,74571,76071,56555,76165,59619,76167,56555,76164, -59381,76171,12377,76070, 375,76175,49204,76071, 1369,76071, 241,76181, -56555,76071,74571,76184,59381,76187,59381,76185,74571,76191,49205,76071, -65869,76195, 1275,76071, 903,76199,60857,76070, 59,76203, 1325,76203, - 331,76203, 265,76203, 903,76070, 59,76213, 1325,76213, 331,76213, -56555,76070,74877,76221,74866,76221,65513,76221,65791,76221,65407,76221, -74807,76221,74823,76221,74797,76221,21105,76221,75029,76221,75283,76221, -21549,76221,19625,76221,65171,76221,75079,76221,74813,76221,59619,76221, -74571,76254,74571,76221,59619,76258, 15,76221,74887,76263,21605,76070, -73949,76267, 265,76071,63823,76271,63679,76271,72619,76271, 9377,76271, - 9533,76271,37145,76271, 2,76070,76077,76285,76081,76285,55839,76285, -54159,76285,54497,76285,51803,76285,73123,76285,76179,76285,65869,76301, - 265,76285, 3,76070,76196,76307,67988,76307, 33,76307, 1447,76307, - 1141,76307,76271,76307,76195,76307,65869,76320, 9,76307,46863,76307, -65869,76326,65869,76307,76195,76330,46863,76330, 2,76071,76310,76337, -76328,76337,76334,76337,76083,76337, 10,76337, 5,76337, 7,76348, - 7,76337, 5,76352,55803,76337,54225,76337,54477,76337,51593,76337, -67988,76337,76307,76364,64345,76337,76324,76337,73121,76337,72713,76337, -76326,76337,65869,76376, 9,76337,76307,76380,60857,76337,71229,76385, -76347,76387,76351,76387,76355,76387, 903,76337,46863,76337,76330,76396, -65869,76396,76307,76400,76307,76396,65869,76404,76330,76337,46863,76408, -65869,76337,76326,76412,46863,76412,76307,76416,76307,76412,46863,76420, -76307,76337,67988,76424, 9,76424,46863,76424,65869,76430,65869,76424, -46863,76434, 3,76071, 5,76438,76285,76441, 113,76439,46863,76438, -76285,76447,65869,76449,76285,76439,67988,76453, 9,76453,46863,76453, -65869,76458,65869,76453,46863,76462, 15,76071,74485,76467,73261,76467, -46863,76071, 3,76472,76285,76475,65869,76477, 3,76473,76412,76481, -65869,76481,76337,76484,76337,76481,65869,76488,65869,76070, 375,76493, -70176,71229, 375,76497, 3,71229,70554,76500, 5,76501, 1,76505, -71229,76507, 2,76509,59961,76505,74887,76513, 6,76505,76511,76517, -73261,76517, 0,76500,75163,76523, 524,76523,74887,76527,75155,76523, - 1291,76523,74887,76533,75211,76523,75441,76523, 483,76523, 11,76540, -74887,76543, 11,76523, 483,76546,74887,76549, 33,76501, 9,76553, - 8147,76501,42315,76501,53777,76501,70555,76500,70176,76500, 9,76565, -43848,76501,70177,76501,76563,76571,76566,76571, 9,76571,76565,76576, -76565,76571, 9,76580, 1141,76501, 9,76585, 1447,76501, 9,76589, -69849,76500,68155,76593,17049,76500,48643,76597, 1369,76501, 803,76601, - 15,76500,76337,76605,37409,76501, 9,76609, 9,76500,70177,76613, -76565,76615,70177,76612, 1141,76613, 1447,76613, 33,76613, 11,76613, -37409,76613, 11,76501, 9,76631, 6,76500, 7,76500, 33,76637, - 1447,76637, 1141,76637,76271,76637, 6,76501,60856,76647, 0,76647, - 3,76650, 3,76647, 0,76654, 11,76647,71229,76659,76649,76661, -76653,76661,76657,76661, 7,76501,43503,76668,70177,76500, 9,76672, -70176,76501,76619,76677,76503,76677,76675,76677,76673,76677, 9,76685, -43503,76501, 7,76688, 17,76689, 1011,76501, 375,76695, 7,76695, -18967,76501, 4,76700, 5,76700,76071,76705, 6,76704, 6,76705, -76070,76701,76709,76713,76705,76713, 14,76700,76713,76719,71229,76701, - 7,76723,76711,76725, 7,76722,76709,76729,76705,76729,76719,76729, - 15,76723,76071,76701,76703,76739, 15,76700,76739,76743, 6,76700, - 5,76746,76729,76749,76713,76749, 7,76700,76707,76755,76711,76755, - 6,76701,76743,76761,76737,76761, 7,76701,76749,76767,76709,76767, -71229,76766,76749,76773,76709,76773,76705,76773,76719,76773,76719,76767, -65869,76500,68155,76785,68109,76785, 256,76785, 7,76785, 241,76792, - 241,76785, 7,76796,70572,71229,68155,76801,68109,76801, 256,76801, - 7,76801, 241,76808, 241,76801, 7,76812, 2,71229, 0,76817, - 4,76818, 0,76816, 2,76823, 5,76816,62284,76817,62186,76817, -64248,76817,62504,76817,64205,76817,61690,76817,52501,76817,70021,76817, -17496,76817,11179,76817,10187,76817,53967,76817,17455,76817, 9,76852, -16065,76817, 16,76857, 16,76856, 17,76857,76861,76863, 17,76856, -76859,76867,70802,76817, 340,76817,60857,76872,64148,76817, 265,76876, - 9,76817,17455,76880, 375,76817,60857,76884, 587,76817, 17,76889, -37145,76891, 9533,76891,76523,76891,76821,76891,63679,76891,44243,76817, -60857,76902,49713,76903, 17,76816,36729,76909,68447,76909,67547,76909, -70731,76909,49713,76816,44243,76919,54295,76817, 9,76923, 6,76816, -66737,76927,36661,76927,62741,76927,68381,76927,68727,76927, 7,76816, -54497,76939,55839,76939,54159,76939,51803,76939,73123,76939, 265,76939, - 7,76817,62494,76952,70573,76952, 265,76952,60857,76958,60857,76952, - 265,76962, 265,76953,60857,76967,62494,76817, 7,76970,43215,76817, - 9,76975, 265,76817,64148,76978, 483,76979, 7,76978,60857,76984, -60857,76978, 7,76988,60857,76817,42810,76993,42810,76992,42811,76993, -76997,76999, 375,76992, 340,76992,42811,76992,76995,77007,44243,76992, - 6,76992, 7,76992, 265,77014, 6,76993,77015,77019, 7,76993, -77013,77023, 265,76993, 7,77027, 265,76992, 7,77030,65869,76817, -69275,77035, 7,77037,70573,76817, 6,77041, 7,77041, 6,77040, -77045,77047, 7,77040,77043,77051,65869,76816,69716,77055, 7,77055, -69513,77058,69513,77055, 7,77062,70922,71229,69716,77067, 7,77067, -69513,77070,69513,77067, 7,77074, 6,71229,74890,77079,59619,77081, -38056,77078, 5,77084,76825,77079,76827,77089,55814,77078,55815,77079, -77093,77095,55815,77078,55814,77079,77099,77101, 1346,77078, 1346,77079, - 1347,77078,77107,77109,17126,77079,17125,77079, 2,77114,17127,77079, - 9565,77119,74169,77079,59619,77123,60621,77079,59619,77127,38056,77079, -38057,77078,44195,77133,58303,77079, 1010,77079, 1010,77078,77119,77141, -35187,77079, 2,77144, 0,77079, 4,77149, 2,77151,71229,77152, -71229,77151, 2,77156, 2,77157,76816,77151, 1011,77149,71229,77165, - 5,77079, 1,77168, 5,77078,38056,77173,77133,77175, 2,77172, -58302,77079,77141,77181, 9565,77181,59619,77181,20501,77079, 1011,77189, - 1010,77188,77191,77193, 1010,77189, 1011,77188,77197,77199, 567,77079, -21604,77203,21604,77202,21605,77203,77207,77209,21605,77202,77205,77213, - 1347,77079,77105,77217,74887,77079,56555,77220,59619,77223,56555,77221, -59381,77227, 9875,77079, 1011,77231, 1010,77230,77233,77235, 1010,77231, - 1011,77230,77239,77241,56555,77079,74887,77244,59619,77247,59619,77245, -74887,77251, 1011,77244, 9565,77255,77141,77255,59619,77255, 1011,77245, - 9617,77263,77139,77263,74887,77263, 587,77079,21605,77271,42155,77273, -53517,77273,76085,77273,77171,77273, 7971,77273, 1011,77078,77113,77285, -77117,77285,74505,77285,77131,77285,77137,77285,77147,77285,73261,77285, -38057,77079,77179,77301,77087,77301,41941,77301,76827,77301, 9565,77301, -59619,77301,77141,77301,56555,77078,72981,77317,75508,77317,74887,77317, -59381,77322,59381,77317,74887,77326,21605,77078,62905,77331,68761,77331, -67541,77331,70401,77331,73967,77331, 1011,77079,56555,77343,59381,77345, -56555,77342,59619,77349,77141,77349, 9565,77349, 2,77078,66737,77357, - 5,77356,77301,77361,62741,77357,36661,77357,68727,77357,68381,77357, - 3,77078,77161,77373, 2,77079,17125,77376,77285,77379,35187,77376, -77285,77383, 3,77079,77155,77387,77159,77387,77163,77387,77167,77387, - 11,77079,37844,77397,37844,77396,37845,77397,77401,77403,37845,77396, -77399,77407,65869,71229, 1530,77410, 842,77410,48535,77410, 669,77410, - 1419,77410,49514,77410, 136,77410,49515,77410, 137,77410, 843,77411, -77415,77431, 1531,77411,77413,77435, 843,77410, 1530,77411, 1531,77410, -77441,77443, 842,77411,77439,77447, 1418,77410,48534,77410, 668,77410, - 587,77410,46863,77456, 9,77456, 1369,77410, 15,77462, 9,77410, - 2,77467, 2,77466, 587,77466, 265,77410, 375,77475, 15,77410, - 1369,77478,46863,77410, 2,77483, 2,77482, 587,77482, 7,77411, - 59,77491, 1325,77491, 331,77491, 265,77491, 6,77410,77491,77501, - 2,77503, 3,77503, 2,77502,77507,77509, 3,77502,77505,77513, - 3,77411,67577,77517,77425,77517,77423,77517,68139,77517,70979,77517, -77455,77517,77453,77517,77421,77517,77471,77517,77487,77517,77461,77517, -77459,77517,77473,77517,77489,77517, 7,77517, 1011,77517, 7,77549, - 2,77410, 9,77552,77517,77555,46863,77552,77517,77559,69716,77553, -77546,77553, 7,77553,69513,77566,77517,77566,69513,77553, 7,77572, -77517,77553, 6,77577, 7,77577, 6,77576,77581,77583, 7,77576, -77579,77587, 2,77411,76517,77591,29229,77591,72789,77591,77429,77591, -77427,77591,72683,77591,74233,77591,77317,77591,77451,77591,77419,77591, -77417,77591,77285,77591,73087,77591,77465,77591,77481,77591, 7,77591, -70573,77591, 7,77625, 3,77410, 4,77628,77591,77631, 1,77628, - 5,77628, 0,77628,77591,77639, 5,77629, 6,77643,77591,77645, -68155,77629,77469,77629,77485,77629,68109,77629,77623,77629,77631,77657, -77639,77657, 256,77629,77622,77629,77635,77665,77637,77665, 6,77629, -77632,77671,77640,77671,77631,77671,77591,77676,77639,77671,77591,77680, -77591,77671,77631,77684,77639,77684, 7,77629,77635,77691,77591,77693, -77637,77691,77591,77697, 241,77690,77591,77690,77635,77703,77637,77703, - 241,77629, 7,77708,77591,77629, 6,77713, 7,77713, 6,77712, -77717,77719, 7,77712,77635,77723,77637,77723,77715,77723, 6,77411, - 7,77410, 375,77733,77731,77733, 2,77737, 3,77737, 2,77736, -77741,77743, 3,77736,77739,77747, 1, 6,18363,77751, 4389,77751, -18362,77751, 4388,77751,70572,77750,70667,77761,70849,77761,70803,77761, -56555,77767,70883,77761, 272,77751, 8997,77773, 4425,77773, 8452,77751, - 251,77779, 8841,77779, 8453,77751, 273,77751, 4139,77751, 8429,77751, - 4138,77751, 8428,77751,70879,77751,70797,77797,18257,77751, 465,77801, - 445,77751,17827,77805, 4371,77751, 265,77808,18339,77751, 265,77812, -64953,77751, 375,77817,14888,77751, 375,77821,13569,77751, 375,77825, - 4137,77751, 265,77828, 8401,77751, 265,77832, 413,77750,77835,77837, -77831,77837,77795,77837,77793,77837,77815,77837,77811,77837,77757,77837, -77759,77837, 241,77837, 1217,77750, 412,77750, 8401,77859, 4137,77859, -18339,77859, 4371,77859,77791,77859,77789,77859,77753,77859,77755,77859, - 1216,77750,40461,77751, 9,77879,59573,77751, 375,77883,69467,77751, - 375,77887, 7047,77751, 412,77891, 413,77890,77893,77895, 413,77891, - 412,77890,77899,77901,12615,77751, 375,77905,45880,77751,46275,77909, -33390,77751,34003,77913,77462,77751,77591,77917,65232,77751,65625,77921, - 923,77751,16481,77925,16783,77925,18797,77925,25367,77751, 9,77933, -68975,77751, 375,77937,62984,77751, 9,77941, 1412,77751,17827,77945, - 412,77751,77837,77949, 1216,77751, 9137,77751, 375,77955, 253,77751, - 9136,77959, 9137,77959,17826,77959, 1,77959, 413,77966,17827,77959, - 413,77959, 1,77972, 265,77958, 8997,77977, 4425,77977,77963,77977, -77965,77977,77969,77977,77975,77977, 265,77959, 8997,77990, 8997,77959, - 265,77994, 265,77995,12377,77959, 8337,77751, 266,78003, 267,78003, - 464,78003, 6,78003, 413,78010, 465,78003, 413,78003, 6,78016, - 265,78002, 251,78021, 8841,78021,78007,78021,78009,78021,78013,78021, -78019,78021, 265,78003, 251,78034, 251,78003, 265,78038, 265,78039, - 375,78003,38057,77751, 265,77751,18339,78048,77837,78051, 4371,78048, -77837,78055, 253,78048, 8997,78059, 4425,78059, 8337,78048, 251,78065, - 8841,78065,77837,78049, 8401,78071, 4137,78071,18339,78071, 4371,78071, - 4137,78048,77837,78081, 8401,78048,77837,78085, 241,78049, 8401,78089, - 4137,78089, 1369,78048,17827,78095, 241,78048, 1011,77751,56555,78101, -60369,78103, 241,77751, 413,78107,14315,78106, 375,78111,57522,78107, -67028,78107, 265,78107,60857,78106, 9,78121,56555,78107, 9,78124, -65869,78107, 483,78128, 483,78107,65869,78132, 9,78107,56555,78136, - 265,78106, 8685,77751, 375,78143, 264,77750,78066,78147,78060,78147, -78091,78147,78093,78147,18339,78147, 4371,78147,17911,78147,13433,78147, -13411,78147,13635,78147,77978,78147,78022,78147,77999,78147,78043,78147, -77774,78147,77780,78147,64733,78147,64955,78147,78021,78147, 251,78184, -77977,78147, 8997,78188,78065,78147, 251,78192,78059,78147, 8997,78196, -77779,78147, 251,78200,77773,78147, 8997,78204, 9139,78147, 9123,78147, - 9065,78147,14935,78147,64919,78147,59463,78147,69357,78147,59533,78147, -69427,78147,59587,78147,69481,78147,78088,78147, 8401,78231, 4137,78231, - 8997,78147,78059,78236,77977,78236,77773,78236, 251,78147,78065,78244, -78021,78244,77779,78244,27979,78147,26293,78147,41503,78147, 8685,78147, -78141,78147,77949,78147,78099,78147,78049,78147, 8337,78267, 251,78269, - 253,78267, 8997,78273, 241,78266, 8401,78277, 4137,78277, 241,78267, - 1369,78147, 241,78147, 6,78287,78065,78289,78021,78289,77779,78289, - 1,78287,78059,78297,77977,78297,77773,78297,78049,78286, 8401,78305, - 4137,78305,16381,78147,19513,78147,35843,78147,13325,78147,70407,78147, -69063,78147,67565,78147, 341,78147,64669,78325, 8997,78325,59381,78325, -69275,78325,65869,78325, 241,78325, 471,78147, 367,78147, 357,78147, - 8401,78147, 4137,78147,37019,78147, 4063,78147,20219,78147, 3863,78147, -20697,78147,37377,78147, 9955,78147,10273,78147,14625,78147, 4569,78147, - 265,77750,77785,78369, 251,78371,77787,78369, 8997,78375, 253,78369, - 8997,78379, 8337,78369, 251,78383, 241,78368, 8401,78387, 4137,78387, -77791,78387,77789,78387, 241,78369, 241,77750, 8428,78399,78147,78401, - 4138,78399,78147,78405, 4137,78399, 265,78409, 265,78408,78147,78413, - 8401,78399, 265,78417, 265,78416,78147,78421, 265,78398, 8401,78425, - 4137,78425,77791,78425,77789,78425, 265,78399, 8401,78434,78147,78437, - 4137,78434,78147,78441,78147,78435, 8401,78445, 4137,78445, 240,77751, - 265,78451, 1010,77751,28337,78455, 264,77751,78426,78459,78428,78459, -78419,78459,78411,78459,78388,78459,78390,78459,77860,78459,77862,78459, -77864,78459,77866,78459,18339,78459,77859,78480, 4371,78459,77859,78484, -78381,78459,78385,78459,13381,78459,77961,78459,78005,78459,77993,78459, -78037,78459,77997,78459,78041,78459,78015,78459,77971,78459,77807,78459, -77803,78459,64746,78459,78382,78459, 251,78517,78378,78459, 8997,78521, -78035,78459, 251,78525,77991,78459, 8997,78529, 9072,78459, 9105,78459, -59470,78459,69364,78459,59521,78459,69415,78459,64931,78459, 413,78459, -77859,78459, 8401,78548, 4137,78548,18339,78548, 4371,78548,78425,78459, - 8401,78558, 4137,78558,78387,78459, 8401,78564, 4137,78564, 8401,78459, -78425,78570,78387,78570,77859,78570, 4137,78459,78425,78578,78387,78578, -77859,78578, 8337,78459,78369,78586, 251,78589, 253,78459,78369,78592, - 8997,78595,78396,78459,78119,78459,78369,78459, 8337,78602, 251,78605, - 253,78602, 8997,78609, 241,78603, 8401,78613, 4137,78613, 241,78602, -69275,78459, 375,78620,59381,78459, 375,78624, 8997,78459, 375,78628, -64669,78459, 375,78632,70327,78459,65869,78459, 375,78638,66930,78459, - 375,78459,64669,78644, 8997,78644,59381,78644,69275,78644,65869,78644, - 241,78644, 241,78459,78369,78658, 375,78658, 394,78459, 299,78459, - 1217,77751, 413,77751,77859,78671,78369,78671, 375,78671,14315,77751, - 241,78678, 375,78681, 375,78679, 341,77751,12377,78687, 257,77751, - 375,78691,70572,77751,70693,78695,70800,78695,70797,78695,56555,78700, -56555,78695,70797,78704, 1346,77751, 9,78709, 1061,77751, 9,78713, - 525,77751, 9,78717,64396,77751, 9,78721,38056,77751,29229,78725, - 9,78725, 137,77751,56555,78731, 5,78733, 4,78732,78735,78737, - 4,78733, 5,78732,78741,78743,20103,77751, 375,78747, 1471,77751, -12377,78751,36773,77751, 375,78755, 53,77751,12377,78759,45639,77751, - 1369,78762,46275,78765,32805,77751, 17,78768,34003,78771,77410,77751, - 1369,78774,77591,78777,65076,77751, 17,78780,65625,78783, 1275,77751, - 5,78786, 9,78789, 5,78787, 17,78793,35187,77751, 1196,78797, - 6,78797, 1011,78800, 137,78797, 136,78797, 1197,78797, 1413,78797, - 922,78797, 1011,78797, 6,78814, 903,78797, 483,78818, 483,78797, - 903,78822, 2,78796,78805,78827,29229,78827,78799,78827,78817,78827, -78803,78827, 9,78827, 3,78796,78807,78841,78809,78841, 2,78797, -78841,78847, 9,78849, 9,78846,78841,78853, 3,78797, 5,78857, - 6,78859,78827,78861,78838,78857, 9,78857,78827,78866,78827,78857, - 9,78870, 9,78797, 2,78875,78857,78877, 3,78875, 2,78874, -78841,78883, 3,78874, 17,77751,65076,78889,65407,78891,32805,78889, -34447,78895,20035,78889,58742,78889,65076,78888,65625,78903,32805,78888, -34003,78907, 903,78889,56555,78910,56555,78889, 903,78914,65869,78889, - 2,78919, 3,78919, 2,78918, 3,78918,18967,77751, 295,78929, - 1108,78929, 1011,78929, 9,78934, 9,78929, 1011,78938, 483,78929, -18967,78943, 5,78944, 5,78945,21036,78943,21037,78943, 4,78943, -78949,78955, 5,78943,18967,78958, 4,78942,78961,78963,78947,78963, -78951,78963, 5,78942,78953,78971, 1369,77751,12376,78974,12376,78975, -12377,78974,78979,78981,77410,78975,77517,78985,45639,78975,46599,78989, -12377,78975,78977,78993,36527,78975,68806,78975,77410,78974,77591,79001, -45639,78974,46275,79005, 1011,78975,65869,79008,65869,78975, 1011,79012, - 265,78974,17827,79017,56555,78975, 4,79021, 5,79021, 4,79020, - 5,79020,60857,77751, 241,79030, 9,79033, 5,79030, 9,79037, - 5,79031, 17,79041,70177,77751,38056,79045,38056,79044,38057,79045, -79049,79051,38057,79044,79047,79055, 375,79045,27979,77751, 375,79061, - 2,77750,68283,79065,68275,79065,36633,79065,36627,79065,39987,79065, -66423,79065,66883,79065,66405,79065,66397,79065,67687,79065,78047,79065, - 9,79087,36544,79065, 9875,79091,20501,79091,68177,79065, 9875,79097, -20501,79097,64396,79065, 9,79103, 5,79065,60857,79106, 9,79109, -35187,79065, 11,79112,20501,79115, 9875,79115, 11,79065,35187,79120, - 9875,79123,20501,79123,60857,79065, 5,79129, 17,79131, 5,79128, - 9,79135, 3,77750,40779,79139,63907,79139,73421,79139,73429,79139, -64235,79139,67465,79139,63955,79139,39027,79139,38685,79139,64073,79139, - 6,79139, 4,79161,78728,79139,78838,79139,78827,79139, 9,79168, -78725,79139, 9,79172, 9934,79139,20644,79139, 4663,79139, 903,79181, -17219,79139, 903,79185,12345,79139, 5,79189, 4,79188,79191,79193, - 4,79189, 5,79188,79197,79199, 5123,79139, 5,79203, 4,79202, -79205,79207, 4,79203, 5,79202,79211,79213,19667,79139, 5,79217, - 4,79216,79219,79221, 4,79217, 5,79216,79225,79227,73306,79139, - 9377,79231,63823,79231,40705,79139, 9377,79237,63823,79237,21036,79139, -70177,79139, 9,79245, 341,79139,64669,79249,65869,79249, 253,79139, -65869,79255, 8337,79139, 9,79259, 241,79139, 1471,79139,65869,79265, -37325,79139, 903,79269,20103,79139, 9,79273,10219,79139, 903,79277, - 4,79139,20501,79280, 9875,79280, 5,79139, 6,79287,78827,79289, -78725,79289,18967,79286, 9935,79287,20645,79287,36773,79139, 9,79301, - 53,79139,65869,79305, 5,79138,27979,79309, 8685,79309,41503,79309, -26293,79309, 1369,79309,16381,79309,13325,79309,35843,79309,19513,79309, - 8401,79309, 4137,79309,14625,79309, 4569,79309,37019,79309, 4063,79309, - 3863,79309,37377,79309,20219,79309,10273,79309, 9955,79309,20697,79309, - 9,79139,78725,79352,78827,79352,35187,79139, 1505,79359, 17,79139, -71229,79362, 9377,79365,63823,79365,21315,79363,71229,79139, 17,79372, -63823,79375, 9377,79375,18967,79139,20413,79381, 4,79383, 4,79382, -20487,79381,20486,79381,79161,79381, 4,79393, 4,79392,79163,79381, - 580,79381,49630,79381,79162,79381,46863,79381, 4,79406, 4,79407, - 483,79381, 4,79412, 4,79413,49631,79381, 581,79381, 4,79381, -20413,79422,79161,79422,46863,79422, 483,79422, 5,79381,79385,79433, -79179,79433,79283,79433,79395,79433,79411,79433,79417,79433,20413,79433, - 4,79380,79389,79449,79446,79449,79421,79449,79419,79449,79399,79449, -79433,79449,20413,79460,20413,79449,79433,79464, 5,79380,79425,79469, -79387,79469,79391,79469,79427,79469,79397,79469,79401,79469,79403,79469, -79405,79469,79429,79469,79409,79469,79431,79469,79415,79469,79423,79469, -20413,79495, 1369,79139, 5,79499,27979,79139,65869,79503, 9,79503, -20501,79139, 4,79508,79433,79511, 5,79508,18967,79514,21037,79508, - 4,79509,79517,79521,79243,79521,79295,79521,79469,79521, 5,79509, -79519,79531, 9875,79139, 4,79534, 5,79534, 4,79535, 5,79535, - 4,77750, 3,79545, 5,77750,10256,79549,37356,79549, 4745,79549, - 1011,79555,17423,79549, 1011,79559,63550,79549,64489,79549,63493,79549, - 17,79566,70803,79549,56555,79571,74752,79549, 8982,79549,74571,79549, - 17,79578, 8861,79549, 17,79582,37844,79549,27979,79549, 483,79589, - 253,79549,56555,79593, 8337,79549, 483,79597, 241,79549, 1325,79549, - 17,79602, 331,79549, 17,79606, 1328,79549, 334,79549, 53,79549, -56555,79615,20501,79549, 1011,79619,36773,79549, 483,79623, 9875,79549, - 1011,79627, 1359,79549, 393,79549, 2,79549,37325,79634,10219,79634, - 3,79549, 483,79641,35187,79640,10257,79641,37357,79641, 62,79549, - 59,79549, 17,79652,20103,79549, 483,79657, 1471,79549,56555,79661, - 3,79548,27979,79665, 8685,79665,26293,79665,41503,79665, 1369,79665, -16381,79665,13325,79665,19513,79665,35843,79665, 8401,79665, 4137,79665, -14625,79665, 4569,79665,20219,79665, 3863,79665, 4063,79665,20697,79665, -37019,79665, 9955,79665,10273,79665,37377,79665,18967,79549, 165,79709, - 1369,79549,38057,79713,35187,79549, 3,79717, 3,79716, 17,79549, -63493,79722,74571,79722, 8861,79722, 1325,79722, 331,79722, 59,79722, -37325,79549, 2,79736, 3,79736, 2,79737, 3,79737,10219,79549, - 2,79746, 3,79746, 2,79747, 3,79747, 5,77751, 1196,79756, - 1196,79757, 1197,79756,79761,79763,21604,79757, 6,79757, 587,79769, -21605,79771, 1,79757, 3,79774, 3,79775,18967,79775, 483,79781, - 1,79756,25381,79785,63014,79785,79773,79785,60857,79785, 483,79792, - 483,79785,60857,79796, 6,79756,79787,79801,63015,79801,79785,79805, -25380,79801,79785,79809,79789,79801,79783,79801,79799,79801, 1369,79801, -21605,79818,79785,79821,79795,79801,21605,79801, 1369,79826,79785,79829, - 1216,79757, 413,79757, 1197,79757,79759,79837,79546,79757, 903,79757, -20735,79757, 9993,79757, 1275,79756, 9,79849,60857,79756, 9,79853, -56555,79757, 1505,79856,21605,79757,21376,79757, 483,79757,21315,79864, -58112,79757,21315,79757, 483,79870, 1505,79757,56555,79874, 2,79756, -79767,79879, 7,79881, 6,79880,79883,79885, 6,79881, 7,79880, -79889,79891,79777,79879, 7,79895, 6,79894,79897,79899, 6,79895, - 7,79894,79903,79905,28337,79879, 3,79756,79861,79911, 7,79913, - 6,79912,79915,79917, 6,79913, 7,79912,79921,79923, 2,79757, -79779,79927, 7,79929, 6,79928,79931,79933, 6,79929, 7,79928, -79937,79939, 3,79757, 1,79942,79879,79945, 7,79947, 6,79946, -79949,79951, 6,79947, 7,79946,79955,79957,79545,79942,79545,79757, - 2,79963, 3,79963, 2,79962, 3,79962, 9,79757,63493,79973, -74571,79973, 8861,79973, 1325,79973, 331,79973, 59,79973, 3,77751, -79112,79987, 9,79989,78847,79987, 9,79993, 1216,79987,12371,79987, - 5,79999, 4,79998,80001,80003, 4,79999, 5,79998,80007,80009, - 413,79987, 375,79987,60454,79987,60369,80017, 566,79987,35187,79987, -79065,80022, 9,80025,79106,79987, 1011,79987,37407,79987,10287,79987, -65869,79987, 165,80036,38132,79987, 9,79987,38057,80042,67642,79987, -38057,79987, 9,80048, 165,79987,65869,80052, 5,79986, 4,79987, - 5,79987,79065,80060,56555,80060,60369,80065, 483,80060,79065,79987, -35187,80070, 9,80073, 4,80071, 5,80071, 4,80070, 5,80070, -56555,79987,49630,80084,46863,80084, 4,80089, 4,80088, 581,80084, - 580,80084,49631,80084, 4,80084,46863,80100, 483,80100, 5,80084, -60369,80107,80091,80107, 4,80085,80095,80113,80099,80113, 5,80085, -60327,80119,60719,80119,80097,80119,80087,80119,57901,80119,80093,80119, -80103,80119,80105,80119, 483,80084, 4,80136,80119,80139, 4,80137, -80107,80143, 483,79987, 5,80146, 2,77751,79538,80151,79541,80153, -79514,80151,79521,80157,79024,80151,79027,80161,78958,80151,78963,80165, -79021,80151, 5,80168,79027,80171, 5,80169,79023,80175,78943,80151, - 5,80178,78963,80181, 5,80179,78955,80185, 1,80151, 7,80189, - 4,80191, 4,80190, 16,80189, 4,80189, 7,80198,28714,80151, - 17,80203,79286,80151,79541,80207,79521,80207,35187,80150,79289,80213, -29229,80213,79352,80213, 9,80213,79139,80220,79139,80213, 9,80224, - 9,80151, 4,80150, 265,80231, 5,80150,80193,80235,28337,80235, - 4,80151, 1011,80241, 5,80151,80195,80245,80201,80245,79534,80245, -79543,80251,79508,80245,79531,80255,79021,80244,79027,80259,78943,80244, -78963,80263,79021,80245,79029,80267,78943,80245,78971,80271,80197,80245, -28219,80245,30475,80245,23939,80245,79139,80244,79541,80283,79521,80283, -21605,80244, 17,80289,79139,80151,35187,80293, 9,80295, 4,80293, - 5,80293,79537,80301,79511,80301,79177,80301,79179,80301,79285,80301, -79283,80301, 4,80292,80301,80315, 5,80292,79541,80319,79521,80319, -80299,80319,21605,80151, 5,80326, 17,80329, 5,80327, 9,80333, - 4,77751,79750,80337,79753,80339,79740,80337,79743,80343,78922,80337, -78925,80347,78880,80337,78883,80351,78919,80337, 3,80354,78925,80357, - 3,80355,78921,80361,78875,80337, 3,80364,78883,80367, 3,80365, -78877,80371, 6,80337, 1369,80375,56555,80377, 1,80337,60857,80381, - 1275,80383, 1,80336,58931,80387,19916,80387,80379,80387,18967,80387, - 1275,80394, 1275,80387,18967,80398, 6,80336,19917,80403,80387,80405, -80389,80403,80391,80403,58930,80403,80387,80413,80385,80403,80401,80403, - 587,80403,56555,80420,80387,80423,80397,80403,56555,80403, 587,80428, -80387,80431,43214,80337,79640,80337,79753,80437,79743,80437, 2,80336, - 265,80443, 2,80337, 903,80447, 3,80337,67988,80450,67988,80451, -67989,80450,80455,80457,79746,80451,79755,80461,79736,80451,79745,80465, -78919,80450,78925,80469,78875,80450,78883,80473,78919,80451,78927,80477, -78875,80451,78887,80481,67989,80451,80453,80485,79549,80450,79753,80489, -79743,80489,38305,80450,79549,80337, 2,80497, 3,80497,79749,80501, -79739,80501,79551,80501,79553,80501,79639,80501,79637,80501, 2,80496, -80501,80515, 3,80496,79753,80519,79743,80519,80499,80519,38305,80337, - 3,80526, 3,80527, 0, 7, 1517,80532, 2575,80535, 949,80532, - 2599,80539, 1476,80532, 2269,80543, 280,80532, 2289,80547, 272,80532, - 4437,80551, 121,80532,38343,80555, 3075,80555, 1913,80555, 76,80532, - 3005,80563, 1899,80563,38337,80563, 123,80533, 3061,80571, 81,80533, - 2997,80575, 367,80532, 7627,80579, 357,80532, 1927,80583, 397,80532, - 7895,80587, 1516,80532, 948,80532, 107,80532, 2221,80595, 203,80532, - 2215,80599, 215,80532, 4339,80603, 91,80532, 5045,80607, 1477,80532, - 281,80532, 273,80532, 317,80532,14469,80617, 67,80532,11087,80621, - 4643,80621, 2233,80621, 4625,80621, 9,80629, 53,80532, 2289,80633, - 1471,80532, 2269,80637,80012,80533,77949,80641,79834,80533,77949,80645, -79996,80533,78669,80649,79832,80533,78669,80653,78546,80533,77949,80657, -78108,80533,78141,80661,77949,80661,77855,80533,77949,80667, 416,80533, -17993,80671, 418,80533,17993,80675, 447,80533,17993,80679, 295,80532, - 294,80532, 76,80533,38587,80687,26285,80533,26390,80533,26106,80533, - 121,80533,38585,80697,26502,80533,32269,80533,31761,80533,32563,80533, -31921,80533,31591,80533,78287,80533,78141,80713,78099,80713,77949,80713, -23788,80533,27830,80533,27947,80533,41746,80533,26216,80533,41414,80533, -26126,80533,41348,80533,26328,80533,41556,80533,29029,80533,43319,80533, - 203,80533, 2211,80745,60857,80745, 85,80533, 4593,80751, 2229,80751, -60857,80751,80229,80533,39823,80533,23013,80533,39229,80533,39783,80533, -38673,80533,38675,80533, 107,80533, 5019,80773, 2219,80773,60857,80773, -80228,80533,40956,80533,45411,80783,37899,80783,41493,80533, 1517,80533, - 2573,80791,80591,80791, 949,80533, 2593,80797,80593,80797, 280,80533, - 2287,80803,80613,80803, 1476,80533, 2267,80809,80611,80809, 272,80533, - 4457,80815,80615,80815, 8673,80533, 8681,80533, 8800,80533, 8742,80533, -41622,80533, 8740,80533, 8610,80533, 8642,80533, 8638,80533,39650,80533, -42752,80533, 8717,80533, 413,80843, 1369,80842, 341,80842, 3785,80533, - 413,80851, 1369,80850, 341,80850, 413,80532, 8717,80859, 3785,80859, -13443,80859, 7627,80859, 7287,80859, 7895,80859,12755,80859, 1689,80859, - 2701,80859, 1705,80859,77859,80859,78459,80880,78548,80859,78048,80859, -77837,80887,78071,80859,18454,80859,78147,80859,78459,80859,77859,80896, - 265,80859,77751,80900,77837,80903,77751,80901,77859,80907,18391,80859, - 331,80910, 331,80859,18391,80914, 8495,80859,77751,80859, 265,80920, -77837,80923,12745,80859, 375,80927, 457,80927, 375,80859,13977,80533, -80021,80533,13767,80533, 4347,80533, 2213,80533, 2225,80533, 2231,80533, -10079,80533,79501,80533,18715,80533,18579,80533,14313,80533,80149,80533, -13945,80533, 4987,80533,14091,80533, 4619,80533,80069,80533,13913,80533, - 4555,80533,16635,80533,16301,80533, 2575,80533, 2599,80533, 2289,80533, - 2269,80533, 4437,80533, 7549,80533, 7589,80533,13785,80533,80015,80533, -23755,80533, 1369,80996,39633,80533, 1369,81000,78284,80533, 7205,80533, - 2561,80533, 2261,80533, 4423,80533, 2307,80533,79318,80533,10058,80533, -79674,80533,26331,80533, 1369,81022,41559,80533, 1369,81026, 4329,80533, - 1369,81030, 4311,80533, 1369,81034,10354,80533, 3786,80533, 4330,80533, -27805,80533, 1369,81044,42731,80533, 1369,81048,10055,80533, 1369,81052, -10351,80533, 1369,81056, 4312,80533,78645,80533,78324,80533,78458,80533, - 375,81067, 3794,80533,78147,80533, 413,81073, 1369,81072, 341,81072, - 215,80533, 4345,81081,60857,81081,79309,80533, 1369,81086,79665,80533, - 1369,81090, 1477,80533,80543,81095, 281,80533,80547,81099, 1516,80533, -80535,81103, 948,80533,80539,81107,13443,80533,16669,80533,43293,80533, -26104,80533,41314,80533,26277,80533,41479,80533,13027,80533, 264,81124, - 264,81125, 413,81125, 265,81124,81129,81133, 265,81125,81127,81137, - 5127,80533, 264,81140, 264,81141, 413,81141, 265,81140,81145,81149, - 265,81141,81143,81153,15309,80533, 412,81157, 413,81156,81159,81161, - 413,81157, 412,81156,81165,81167,32294,80533,45314,80533,31857,80533, -44925,80533,14053,80533,22897,80533,39143,80533,78107,80533, 413,81184, -78141,81187,77949,81187, 413,81185,77859,81193, 1276,80533,17993,81197, - 438,80533,17993,81201, 1278,80533,18759,81205, 1242,80533,18759,81209, -22806,80533, 903,81213, 9,81213,39084,80533, 483,81219,39204,80533, -41941,81223,22956,80533,26625,81227, 1109,80533,35187,81231, 294,80533, -80683,81235,35187,81235, 1413,80533, 1471,81241, 295,80533,80685,81245, -39749,80533, 483,81249,24095,80533,35187,81253, 11,81252,39787,80533, - 241,81259, 903,81259, 587,81258,24236,80533,39846,80533,78459,80533, - 413,81270,77949,81273, 413,81271,77859,81277,39232,80533,46169,81281, - 510,80533, 11,81285, 1108,80533, 11,81289, 1216,80533,79987,81292, -78669,81295,79757,81292,78669,81299, 1275,81292,18759,81303, 15,81292, -18759,81307, 8808,80533,41376,80533, 7195,80533, 1141,80533,14315,81317, - 959,80533,17125,81321, 253,80533,25793,81324,41019,81324, 8495,81324, - 317,80533,15661,81333,14991,81333,17993,81333, 2899,81333, 273,80533, -80551,81343, 8634,80533, 8677,80533, 331,80533, 413,81351,18391,81353, - 413,81350,17993,81357, 8861,81351,63493,81351,74571,81351,15029,81351, - 8495,80533, 586,81368, 586,81369, 587,81368,81373,81375, 11,81368, - 253,81368, 1471,81368, 53,81368, 587,81369,81371,81387, 305,81369, - 713,81369, 25,81369, 1369,81368, 257,81369, 257,81368,14011,80533, - 257,80533,25793,81404,41019,81404, 8495,81404, 973,80533,20103,81413, - 8337,81413,36773,81413, 341,80533,30091,81421, 8717,81420,20103,81421, -36773,81421, 8337,81421, 3785,81420,78147,81420, 89,80533,10831,81437, -10903,81437, 5019,81437,60857,81437,17125,81437, 567,80533,63493,81449, -74571,81449, 8861,81449, 652,80533,60857,81457, 288,80533, 8861,81461, - 265,80533,78670,81465,77859,81467, 413,81465,77751,81471,77837,81473, -77751,81470,77859,81477,73154,81465,62059,81465,78107,81465,15029,81465, - 4593,81465,11985,81465,78459,81465,80057,81465,79911,81465, 8861,81465, -63493,81465,74571,81465,72152,81465,61718,81465,77751,81465, 413,81508, -77859,81511, 413,81509,77949,81515, 17,81464,35187,81519, 11,81465, -60857,81522, 587,81465,71229,81526,71229,81465,60857,81530, 11,81531, - 587,81530,60857,81465, 10,81539, 10,81538, 305,81539, 11,81539, -81543,81547,71229,81538, 11,81538,81541,81553, 587,81464,60857,81557, - 11,81464, 8861,81561, 1011,80533,50785,81565, 9,81564, 11,81569, - 11,81565, 9,81573,71229,81565,77387,81577, 903,80533,50959,81581, -45149,80533,35187,81585, 11,81584,32103,80533,27021,81591, 241,81591, - 903,81591, 587,81590, 7333,80533, 483,81601, 6789,80533, 9,81605, - 903,81605,14073,80533, 241,81611, 903,81611, 587,81610,11277,80533, -35187,81619, 11,81618,42707,80533, 3445,80533, 375,81627,10313,80533, -79643,80533, 2621,80533,14229,80533,11571,80533, 5045,80533,35187,81641, - 11,81640, 4971,80533, 241,81647, 903,81647, 587,81646, 7009,80533, - 7497,80533, 7287,80533, 7845,80533, 7925,80533, 7895,80533, 7685,80533, - 7671,80533, 7627,80533,14102,80533,11348,80533, 5096,80533, 5000,80533, - 7533,80533, 4617,80533, 483,81683,13907,80533, 483,81687, 7563,80533, - 264,81691, 264,81690, 265,81691,81695,81697, 265,81690,81693,81701, - 7531,80533, 483,81705,79634,80533,80501,81709,79719,81709,79640,80533, - 483,81715,42716,80533,42795,81719,42704,80533, 483,81723,10308,80533, -36131,81727,10310,80533, 483,81731, 5227,80533, 5009,80533, 3461,80533, - 2981,80533, 3049,80533,80061,80533, 483,81745, 240,80532,77859,81749, -78459,81750,78089,81749,78147,81755,78305,81749,78231,81749,78277,81749, -78445,81749,78564,81749,78613,81749,78558,81749,78548,81749,78071,81749, -78387,81749,78459,81776,78425,81749,78459,81780,78434,81749,78147,81785, -13103,81749, 5161,81749,13074,81749, 5150,81749,13057,81749,13051,81796, - 5141,81749, 5137,81800,13051,81749,13057,81804, 5137,81749, 5141,81808, -13092,81749,13045,81813, 5154,81749, 5133,81817,78048,81749,77837,81821, -78459,81749,78387,81824,78425,81824,77859,81824,25793,81749,41019,81749, - 8495,81749,78147,81749,48009,81749,49321,81749,49001,81749,78399,81749, - 265,81847,78459,81849, 265,81846,78147,81853, 265,81749,13027,81856, -13045,81859, 5127,81856, 5133,81863,13027,81857,13057,81867, 5127,81857, - 5141,81871,78399,81856,78147,81875,77751,81856,77837,81879,77751,81857, -78387,81883,78425,81883,77859,81883,77751,81749, 265,81890,77837,81893, -23755,81749,39633,81749, 3785,81749, 8717,81749,79309,81749,79665,81749, -10055,81749,10351,81749,27805,81749,42731,81749,26331,81749, 4329,81749, -41559,81749, 4311,81749, 5127,81749, 265,81925, 5137,81927, 265,81924, - 5133,81931,13027,81749, 265,81935,13051,81937, 265,81934,13045,81941, - 1010,80532,27021,81945,24095,81945,52915,81945, 9195,81945,81565,81945, - 9,81955,81569,81945,23651,81945,67297,81945,81289,81945,21605,81945, - 9,81967,51435,81945, 4321,81945, 9755,81945,11277,81945, 5045,81945, - 4295,81945, 3833,81945,69729,81945,26907,81945,70097,81945,27323,81945, -53941,81945,53215,81945,10171,81945, 9317,81945, 264,80532,51421,82001, -39619,82001,57811,82001,59743,82001,59933,82001, 8093,82001, 3837,82001, -53703,82001, 4303,82001,42435,82001, 4287,82001,53487,82001, 9579,82001, -42113,82001, 9839,82001, 241,82001, 375,82032, 394,82001, 299,82001, - 375,82001, 241,82040,78399,80533, 264,82044, 264,82045, 413,82045, - 265,82044,82049,82053, 265,82045,82047,82057, 240,80533,78397,82061, -78459,82063,78099,82061,78147,82066,78264,82061,78283,82061,78260,82061, -78262,82061,78661,82061,78599,82061,78619,82061,78601,82061,78675,82061, -77837,82061,77949,82088,78673,82061,77950,82061,78118,82061,78459,82097, -78670,82061,77859,82101,77949,82061,78147,82104,77837,82104,78141,82061, -78147,82110, 413,82061,77751,82115,77837,82117,77751,82114,77859,82121, -78147,82061,78099,82124,78141,82124,77949,82124,78107,82061, 265,82132, -78459,82135, 265,82133,78147,82139,77751,82061, 413,82142,77859,82145, - 413,82143,77949,82149, 265,82061,78107,82152,78459,82155,78107,82153, -78141,82159, 902,80533,37663,82163,37599,82163, 265,80532,25793,82169, -41019,82169,39787,82169,23755,82169,39633,82169, 8495,82169,78147,82169, - 8717,82169, 3785,82169,79309,82169,79665,82169,27805,82169,42731,82169, -10055,82169,10351,82169,26331,82169,41559,82169, 4329,82169, 4311,82169, - 4555,82169,14073,82169, 4971,82169,21605,82169,65869,82215,38305,82169, -56555,82219, 483,82219, 241,80532, 4437,82225, 7,82225, 265,82229, -39787,82225,51615,82225, 4613,82225,12571,82225,14073,82225, 4971,82225, - 375,82225, 510,82225,51937,82225,16683,82225, 4805,82225, 9,82225, - 483,82254, 483,82225, 9,82258,38305,82225, 483,82263, 1010,80533, -55211,82267,64345,82267,36256,82267,35187,82267, 9,82274, 9,82267, -35187,82278, 1011,80532,10001,82283, 903,82285,27533,82283, 903,82289, -79139,82283, 903,82293,82267,82283, 9,82296,82278,82283,81231,82283, -21605,82283, 903,82305, 9,82283,82267,82308, 903,80532, 3549,82313, - 2001,82313,21769,82313,10291,82313, 1011,82321,42613,82313, 1011,82325, -79549,82313, 1011,82329,24095,82313,25793,82313, 8495,82313, 5045,82313, -11277,82313,39787,82313,14073,82313, 4971,82313,21605,82313, 955,82349, - 9,82349,65869,82349,38305,82313, 1011,82357, 483,82357,41019,82313, - 264,80533, 53,82365, 1471,82365, 253,82365,72567,82365,76285,82365, -76939,82365,77751,82364, 375,82379, 471,82365, 367,82365, 357,82365, - 341,82365, 241,82389, 241,82365, 9,82393, 483,82393, 413,80533, -78106,82398,78107,82399,82401,82403,78459,82403,78106,82399,78107,82398, -82409,82411,78141,82411,77949,82411,79987,82398,77949,82419,79757,82398, -77949,82423,78459,82398,77949,82427, 331,82398,17993,82431, 261,82398, -17993,82435,77949,82399,78459,82439,17993,82399, 331,82443, 1275,82398, -17993,82447, 15,82398,17993,82451, 375,80533, 53,82455, 1471,82455, - 253,82455, 1369,82455, 11,82455, 261,80533, 413,82467,18391,82469, - 413,82466,17993,82473,15029,82467, 264,82477, 265,82476,82479,82481, - 264,82476, 265,82477,82485,82487,16531,80533, 483,82491,12745,80533, - 264,82495,13129,82495, 413,82495,13119,82501,15503,82495,50535,82495, -50929,82495,51081,82495,82231,82495,13171,82495,13133,82495, 264,82494, - 265,82495,82519,82521, 265,82494,82497,82525, 375,82495, 257,82495, - 264,82531, 265,82530,82533,82535, 264,82530, 265,82531,82539,82541, - 566,80533, 53,82545, 253,82545, 1471,82545, 88,80533, 1369,82553, - 1346,80533,55211,82557,28714,80533,28337,82561,60618,80533,60757,82565, - 3,82565,60755,82569, 154,80533,37663,82573,43214,80533,43053,82577, - 483,82577,43502,80533,80531,82583,46169,82583, 67,80533,11529,82589, -11569,82589, 4610,82589,61780,82589, 9,82589, 4593,82598,60857,82598, -60857,82589, 9,82604, 4593,82589, 9,82608,37845,80533,38305,82612, -45411,82615,37899,82615,79926,80533,79987,82621, 4,82623, 5,82622, -82625,82627, 5,82623, 4,82622,82631,82633,80058,80533,79757,82637, - 2,82639, 3,82638,82641,82643, 3,82639, 2,82638,82647,82649, -80244,80533, 17,82653, 1447,80533,14315,82657, 33,80533,14315,82661, - 759,80533,17125,82665, 47,80533,17125,82669, 1471,80533,41019,82672, -25793,82672, 8495,82672, 53,80533,25793,82680,41019,82680, 8495,82680, -25793,80533, 586,82688, 586,82689, 11,82688, 1369,82688, 587,82688, -82693,82699, 253,82688, 53,82688, 1471,82688, 587,82689,82691,82709, - 25,82689, 713,82689, 305,82689, 257,82688, 257,82689, 1325,80533, -74571,82723,63493,82723, 8861,82723,15029,82723,41019,80533, 586,82732, - 586,82733, 587,82732,82737,82739, 11,82732, 253,82732, 1471,82732, - 53,82732, 713,82733, 25,82733, 305,82733, 587,82733,82735,82757, - 257,82732, 1369,82732, 257,82733, 59,80533,63493,82767,74571,82767, - 8861,82767,15029,82767,79139,80533,80244,82777,80245,82777,80293,82777, - 4,82782,80319,82785, 4,82783,80301,82789,80298,82777,80319,82793, -21036,82777,21037,82777, 1216,82777, 413,82777,80245,82776,82779,82805, - 1011,82777, 903,82808,21037,82776,82797,82813,80244,82776,82781,82817, -21036,82776,82799,82821,65869,82777, 9,82777, 903,82777, 1011,82828, - 4,82777,80293,82833,80315,82835,80293,82832,80319,82839,79549,80533, -80450,82843,80451,82843,80497,82843, 2,82848,80519,82851, 2,82849, -80501,82855,80498,82843,80519,82859, 1216,82843, 413,82843,80451,82842, -82845,82867, 903,82843, 1011,82870,80450,82842,82847,82875,56555,82843, - 483,82843, 1011,82843, 903,82882, 2,82842,80501,82887,79719,82887, - 3,82842,80337,82892, 483,82893, 3,82843,82867,82899, 1369,82899, - 2,82843,82875,82905,82895,82905,80497,82905,80515,82911,80497,82904, -80519,82915,80519,82905,80437,82905,80489,82905,79587,82905,79721,82905, -79645,82905,80337,82842, 3,82930,82905,82933, 3,82931,82887,82937, -27533,80533, 1216,82941, 413,82941,21036,82941,21037,82941, 1011,82941, - 903,82950,21037,82940,82947,82955,21036,82940,82949,82959, 9,82941, -65869,82941, 903,82941, 1011,82966,42613,80533, 1216,82971, 413,82971, - 903,82971, 1011,82976, 483,82971,56555,82971, 1011,82971, 903,82984, - 2,82971,42667,82989,42791,82989,42709,82989, 3,82971, 1369,82997, - 2,82970,42795,83001, 3,82970, 483,83005,10001,80533, 1216,83009, - 413,83009,21036,83009,21037,83009,21036,83008,83017,83019, 1011,83009, - 903,83022,21037,83008,83015,83027,65869,83009, 9,83009, 903,83009, - 1011,83034,10291,80533, 1216,83039, 413,83039, 903,83039, 1011,83044, -56555,83039, 483,83039, 1011,83039, 903,83052, 2,83039,37871,83057, -36133,83057,35803,83057, 3,83039, 1369,83065, 2,83038,36131,83069, - 3,83038, 483,83073, 1369,80533,26331,83076,25793,83076,23755,83076, -27805,83076,40381,83077,41559,83076, 8717,83076,21036,83077,39633,83076, -78147,83076,79309,83076,10055,83076,42731,83076, 3785,83076,79665,83076, - 4329,83076,10351,83076, 4311,83076,38305,83076,41941,83115,41019,83076, - 8495,83076,38305,83077,41019,83123, 5,83077,18967,83126,18967,83077, - 11,83131, 5,83130, 17,80533,25367,83137,62984,83137,60857,83137, - 265,83143, 241,83142, 241,83137,60857,83148,21605,83136,26625,83153, - 265,83136,35187,83157,21605,83137,25793,83161,35187,83137, 265,83165, - 587,80533,62984,83169,62518,83169,68807,83169,36526,83169,17125,83169, - 265,83169,35187,83180,35187,83169,60857,83184, 265,83184,32103,83168, -38305,83168, 483,83193,39787,83168,14073,83168, 4971,83168, 265,83168, -60857,83203, 241,83169,60857,83206,60857,83169, 241,83210,35187,83210, - 11,80533,25793,83216,41019,83216, 8495,83216, 265,83217, 8495,83225, -45149,83216,21605,83216, 903,83231, 9,83231,24095,83216,11277,83216, - 5045,83216, 265,83216, 8861,83243, 3,83217, 375,83247,38305,80533, -76424,83251,54262,83251,54219,83251,76453,83251,42185,83251,42193,83260, -42194,83251,42191,83251,42193,83251,42185,83268,80450,83251,37844,83251, -37845,83251,44663,83277,38707,83277,43483,83277,37897,83277,80451,83251, -80450,83250,83287,83289, 120,83251, 77,83251,32805,83251,54225,83251, -54129,83298,76337,83251,76307,83302,76307,83251,76337,83306,54129,83251, -54225,83310, 113,83251, 25,83314, 506,83251, 1216,83251, 413,83251, - 1413,83251,37845,83250,45411,83327,83275,83327,37899,83327,37897,83250, -83275,83335,65076,83251,37844,83250, 6,83340,83277,83343,83277,83341, -80451,83250,83273,83349, 66,83251, 33,83353, 25,83251, 113,83356, - 1281,83251, 1086,83251, 922,83251, 483,83251, 241,83366, 587,83367, - 903,83366, 241,83251, 483,83374, 903,83251, 1011,83378, 483,83378, - 1369,83250,41941,83385, 587,83250, 483,83389, 587,83251, 1011,83392, - 1011,83251, 903,83396, 11,83397, 587,83396, 1275,83250,46169,83405, -60857,83251,56555,83408,56555,83251, 11,83413,60857,83412, 2,83250, -80531,83419,46169,83419, 3,83250,43053,83425, 483,83425, 2,83251, -80435,83431,80495,83431,43461,83431,80529,83431,46599,83431,43425,83431, - 3,83251,43837,83445,43027,83445, 11,83445, 25,83451,39747,83445, - 11,83444, 33,83457, 1369,83445, 11,83251, 3,83463, 113,83465, - 3,83462, 33,83469, 15,80533, 1216,83473,18617,83475, 413,83473, -18391,83479,25545,83473,62942,83473, 1216,83472,18759,83487, 413,83472, -17993,83491,60857,83473, 1011,83494,18967,83473, 17,83499, 1011,83473, -60857,83502, 3,83472,37663,83507, 3,83473,37611,83511,38155,83511, -35927,83511,21605,80533,27065,83519,27261,83519,21036,83519,21037,83519, -27067,83519,27255,83519,73221,83519,55211,83519,36256,83519,51593,83519, -55803,83519,64345,83519,54477,83519, 1216,83519, 413,83519,21037,83518, -83525,83551,21036,83518,83527,83555, 247,83519, 934,83519, 9,83519, -35187,83562, 11,83563, 1011,83519, 903,83568, 17,83518,26625,83573, - 11,83518, 903,83577, 9,83577, 11,83519, 903,83582, 903,83519, -27021,83587, 1011,83586, 11,83587, 11,83586,35187,83519, 9,83596, -65869,83519, 5,83518,28337,83603, 5,83519,27021,83607,52915,83607, - 9195,83607,20501,83607, 9875,83607,30475,83607,28219,83607,23939,83607, - 1275,80533,43214,83624,43214,83625,43215,83624,83629,83631, 1216,83625, -18617,83635, 413,83625,18391,83639,43215,83625,83627,83643,40675,83625, -73994,83625, 1216,83624,18759,83651, 413,83624,17993,83655,71229,83625, - 903,83658, 903,83625,71229,83662,38305,83624,46169,83667, 5,83624, -55211,83671, 5,83625,53813,83675,10107,83675,69877,83675, 483,80533, - 241,83683, 9,83685, 9,83682, 11,83689, 17,83683, 903,83693, - 11,83683, 9,83697, 5,83682, 53,83701, 253,83701, 1471,83701, - 5,83683, 1505,83709, 9,80533,80151,83712, 1011,83713,82267,83717, - 241,83713, 483,83721, 483,83712, 11,83725, 1011,83712,81945,83729, - 11,83729, 3,83712, 1369,83735, 3,83713, 483,83739,17025,80533, - 5,83742, 2,83745, 17,83746, 17,83745, 2,83750, 2,83751, - 164,83745,38057,83743,38057,83742,38056,83742,83759,83763,38056,83743, -83761,83767, 3,83742,83749,83771,83753,83771,83757,83771, 3,83743, -83755,83779,13737,80533, 375,83783,80151,80533, 9,83786,35187,83787, - 9,83791, 5,83787, 9,83795, 5,83786, 17,83799,79987,80533, - 413,83802,77949,83805, 413,83803,77859,83809, 1216,83802,78669,83813, - 1216,83803,77857,83817, 4,83803,79549,83821, 2,83823, 3,83822, -83825,83827, 3,83823, 2,83822,83831,83833, 4,83802,79757,83837, - 2,83839, 3,83838,83841,83843, 3,83839, 2,83838,83847,83849, -79757,80533, 413,83852,77949,83855, 413,83853,77859,83859, 1216,83852, -78669,83863, 1216,83853,77857,83867, 2,83853,79139,83871, 4,83873, - 5,83872,83875,83877, 5,83873, 4,83872,83881,83883, 2,83852, -79987,83887, 4,83889, 5,83888,83891,83893, 5,83889, 4,83888, -83897,83899, 3,80532,79231,83903,79237,83903,79365,83903,79375,83903, -73413,83903,73405,83903,40793,83903,40787,83903,71751,83903,36001,83903, -71731,83903,72115,83903,72929,83903,71713,83903, 7,83903, 4,83933, -83519,83935,32103,83903,26106,83903,41746,83903,43005,83903, 8800,83903, -64513,83903,63253,83903,62215,83903,59910,83903,41019,83903, 11,83956, -60755,83903,60707,83903, 9852,83903,48975,83903,48245,83903,48451,83903, -76271,83903,82267,83903, 9,83974,82278,83903,83157,83903,81231,83903, -81235,83903,81519,83903, 386,83903, 347,83903, 510,83903, 273,83903, - 281,83903, 1477,83903, 1516,83903, 948,83903, 165,83903, 903,84004, -40704,83903,79139,84009,27533,84009,10001,84009,73307,83903,79139,84017, -27533,84017,10001,84017,53500,83903,37595,83903,36049,83903,36539,83903, -68851,83903,36041,83903,37573,83903,36275,83903, 1505,83903, 1011,84040, -25793,83903, 11,84044,64397,83903, 483,84049, 8495,83903, 11,84052, -60618,83903, 483,84057, 375,83903, 305,84060, 903,83903, 165,84064, - 1011,83903, 1505,84068, 305,83903, 375,84072, 4,83903,56555,84076, - 483,84079, 5,83902,57811,84083,59743,84083,59933,84083, 9579,84083, - 9839,84083,51421,84083,39619,84083, 4303,84083, 4287,84083, 8093,84083, - 3837,84083,42113,84083,53487,84083,53703,84083,42435,84083,48885,83903, - 483,84115, 11,83903,25793,84118,41019,84118, 8495,84118,59875,84118, - 9805,84118,53391,84118, 9,83903,82267,84132, 483,84132,38305,84132, -79139,84139,10001,84139,27533,84139,38305,83903, 9,84146,79139,84149, -27533,84149,10001,84149, 9805,83903, 11,84156, 5,84157, 483,83903, - 9,84162,56555,83903, 4,84166, 483,84169,53391,83903, 11,84172, - 5,84173,59875,83903, 11,84178, 5,84179, 2,80532,11087,84185, -11307,84185,11713,84185,10439,84185, 2221,84185,10665,84185,11037,84185, - 2233,84185,17777,84185, 2215,84185,18739,84185, 4339,84185,79091,84185, -79097,84185, 5075,84185, 4643,84185,79115,84185,79123,84185,59811,84185, -36619,84185,68291,84185,68299,84185,24213,84185,24059,84185,22149,84185, -22143,84185,72667,84185,60839,84185,35665,84185,59819,84185,59869,84185, -35487,84185, 7,84185, 4,84251,27306,84185,24095,84185,53910,84185, -55537,84185,79280,84185,80301,84263,83607,84185,40455,84185,25313,84185, - 8714,84185,32103,84185,26106,84185, 8800,84185,41746,84185,81569,84185, -48009,84185,49001,84185,49321,84185, 4551,84185,81531,84185,81289,84185, -81245,84185,83729,84185,10196,84185,70136,84185,10603,84185, 9,84305, - 4625,84185, 9,84309,81565,84185, 9,84313,23983,84185, 9,84317, -76501,84185,68176,84185,79065,84323,59787,84323, 9513,84323,36545,84185, -79065,84331,59787,84331, 9513,84331, 759,84185,35187,84339,10107,84185, - 265,84342, 241,84343,69877,84185, 265,84348, 241,84349, 305,84185, - 8495,84354, 959,84185,35187,84359,28714,84185,77079,84185, 1011,84365, - 1010,84364,84367,84369, 1010,84365, 1011,84364,84373,84375, 47,84185, -35187,84379,48245,84185,48975,84185,48451,84185,11277,84185, 5045,84185, -52603,84185, 8495,84185, 10,84394, 10,84395, 305,84394, 11,84394, -84399,84403, 11,84395,84397,84407, 331,84185,71229,84411,79549,84185, - 1011,84415, 265,84185,53813,84418,71229,84419,10107,84418,69877,84418, -79757,84419, 903,84185,55211,84431,10291,84185, 1011,84435,25793,84185, - 10,84438, 10,84439,27021,84438, 11,84438,84443,84447, 11,84439, -84441,84451,42613,84185, 1011,84455, 1325,84185,71229,84459, 5,84185, -27255,84463, 9287,84463,53167,84463,21605,84462, 4,84185,79139,84472, -80301,84475,49475,84473,73066,84473,28715,84473, 1011,84473,71229,84484, -71229,84473, 1011,84488,27693,84473,10047,84473,79287,84473,41019,84185, - 10,84498, 10,84499, 11,84498,84503,84505, 11,84499,84501,84509, - 59,84185,71229,84513, 4,84184, 8495,84517,41019,84517,25793,84517, -49001,84517,49321,84517,48009,84517, 265,84517,78147,84517,23755,84517, -39633,84517, 3785,84517, 8717,84517,41559,84517, 4311,84517,79665,84517, -10351,84517,26331,84517,42731,84517, 4329,84517,79309,84517,27805,84517, -10055,84517, 5,84184,27021,84563,24095,84563, 9195,84563,52915,84563, -21605,84563, 9,84573,23651,84563, 9755,84563,51435,84563,67297,84563, - 4321,84563,69729,84563,26907,84563, 9317,84563,53215,84563,27323,84563, -53941,84563, 3833,84563,10171,84563,70097,84563, 4295,84563, 5045,84563, -11277,84563,53813,84185, 265,84610, 241,84611,48885,84185, 1011,84617, - 11,84185,25793,84620, 8495,84620,41019,84620, 17,84185,30091,84629, -65869,84185, 15,84632,79065,84635,59787,84635, 9513,84635, 803,84633, -38305,84185, 1011,84645, 1347,84645, 15,84185,28714,84650,28714,84651, -65869,84650,79065,84657, 9513,84657,59787,84657,28715,84650,84655,84665, -28715,84651,84653,84669, 9195,84185, 241,84673,35187,84673,21605,84185, -27255,84679, 7,84678, 4,84682, 4,84683,84253,84679, 16,84678, -55211,84679, 803,84679, 9,84679, 17,84678, 903,84679,65869,84679, - 4,84679,84699,84705, 5,84679,84685,84709,84691,84709,27021,84709, - 4,84678, 7,84716,84709,84719, 5,84678,84687,84723,52915,84185, -35187,84727, 241,84727,27021,84185,35187,84733, 241,84733,25793,84732, -79139,84185,80245,84740, 4,84740,80301,84745, 5,84740,80151,84748, - 4,84741,80319,84753,84751,84753,80207,84753,80283,84753, 5,84741, -84743,84763, 5,80532,80759,84767, 7,84767, 2,84770, 3,84770, -83251,84775, 2,84771,84776,84779,84775,84779,83251,84782,83251,84779, -84775,84786, 3,84771,84773,84791,83251,84793,27306,84767,24095,84767, -52603,84767,53910,84767,55537,84767,84438,84767,84394,84767,84498,84767, -81539,84767,25793,84767,27021,84814,84185,84814,64289,84767,84060,84767, -81569,84767,83729,84767,81245,84767,81289,84767,70136,84767,10196,84767, - 273,84767, 1477,84767, 281,84767, 948,84767, 1516,84767,81565,84767, - 9,84847, 1505,84767, 1011,84850, 5045,84767,11277,84767, 4551,84767, - 922,84767, 1413,84767,20831,84767,19783,84767,20053,84767,58775,84767, - 9195,84767, 265,84873, 47,84767,60857,84877, 165,84767, 903,84880, -41019,84767,84185,84884,27021,84767,25793,84888, 265,84889, 8495,84767, -84185,84894, 959,84767,60857,84899, 89,84767, 5019,84903,60857,84903, - 375,84767,83903,84908, 759,84767,60857,84913, 265,84767,53813,84916, -69877,84916,10107,84916, 1011,84767, 1505,84924,54597,84925, 903,84767, - 165,84930, 483,84930,54295,84931, 1447,84767,18967,84939, 1141,84767, -18967,84943, 2,84767,61780,84947, 9,84947,60857,84950,54295,84947, -70085,84947,11529,84947,10155,84947,53925,84947,60857,84947, 9,84964, - 3,84767, 8063,84969,42361,84969,53667,84969,84185,84767,41019,84976, - 8495,84976,25793,84976,83903,84767, 375,84984, 33,84767,18967,84989, - 2,84766,27021,84993,24095,84993, 9195,84993,52915,84993,21605,84993, - 9,85003,67297,84993, 9755,84993,51435,84993,23651,84993, 4321,84993, -26907,84993,69729,84993,10171,84993,53941,84993,70097,84993,53215,84993, - 9317,84993, 4295,84993,27323,84993, 3833,84993, 5045,84993,11277,84993, - 3,84766,57811,85041,59743,85041,59933,85041,51421,85041,39619,85041, - 4303,85041, 4287,85041, 9579,85041, 9839,85041, 8093,85041, 3837,85041, -53487,85041,42113,85041,53703,85041,42435,85041,52915,84767, 265,85073, - 587,84767,60857,85077,70573,85077, 1369,84767,43503,85083, 483,84767, - 903,85086,21605,84767, 9,85091, 145,85091,10107,84767, 265,85096, - 9,84767,53813,84767, 265,85102,69877,84767, 265,85106, 4,80532, -83715,85111,80781,85111,83789,85111, 7,85111, 2,85118,83511,85121, - 2,85119,82163,85125,83507,85125,82573,85125, 1368,85111,83511,85133, -25525,85111,84498,85111,84438,85111,84709,85111,79634,85111,80501,85145, -84394,85111,64513,85111,63253,85111,62215,85111,81539,85111,64397,85111, - 483,85159,83787,85111, 9,85163,43214,85111, 8495,85111,84185,85168, - 587,85169, 331,85111,60857,85175,79139,85111, 903,85179, 265,85111, -60857,85183,79987,85183,10001,85111, 903,85189,41019,85111,84185,85192, - 587,85193,27533,85111, 903,85199, 59,85111,60857,85203, 3,85111, - 4,85206,85125,85209,38305,85206, 2,85111, 7,85214,83511,85217, -79549,85214,80501,85221,49155,85215,62464,85215,43215,85215, 903,85215, -60857,85230,60857,85215, 903,85234,42705,85215,10311,85215,79641,85215, -84185,85111,25793,85244,41019,85244, 8495,85244,25793,85111,84185,85252, - 587,85253, 1325,85111,60857,85259, 2,85110, 8495,85263,25793,85263, -41019,85263,49321,85263,49001,85263,48009,85263, 265,85263,78147,85263, -39633,85263,23755,85263, 3785,85263, 8717,85263,26331,85263, 4329,85263, -79309,85263,10055,85263,41559,85263,27805,85263, 4311,85263,79665,85263, -42731,85263,10351,85263,49205,85111, 903,85309,21605,85111, 903,85313, - 155,85313, 1275,85111,43215,85319,77751,85111,38305,85111, 7,85324, - 2,85326, 2,85327, 1368,85324, 1369,85324, 2,85325,85335,85337, - 3,85325,85329,85341,85333,85341,84185,85341, 2,85324, 7,85348, -85341,85351, 3,85324,85331,85355,79549,85111,80451,85358, 2,85358, -80501,85363, 3,85358,80337,85366, 2,85359,80519,85371,85369,85371, -80437,85371,80489,85371, 3,85359,85361,85381, 5,80533,83932,85385, -83933,85385,64148,85385,64149,85385, 0,85385,56555,85395, 1369,85397, - 7,85385,83903,85400,60857,85400, 265,85401,83903,85407, 1275,85401, -60857,85411, 0,85384,63015,85415,25380,85415,85413,85415,21605,85415, - 1369,85422, 1369,85415,21605,85426, 7,85384,85417,85431,25381,85431, -85415,85435,63014,85431,85415,85439,85419,85431,85399,85431,85429,85431, -85425,85431, 483,85431,60857,85450,85415,85453,60857,85431, 483,85456, -85415,85459,54440,85385,83903,85385, 7,85464,27425,85385,53137,85385, - 9365,85385, 803,85385,60857,85474,62310,85385,85206,85385,85125,85481, - 241,85385, 483,85485,54295,85484,54295,85385, 241,85490, 483,85384, - 53,85495, 253,85495, 1471,85495, 1275,85384,55211,85503,21605,85384, -28337,85507, 1369,85385, 1011,85511,60857,85385, 7,85514, 803,85514, - 2,85384,85389,85521,85393,85521,55211,85521,64345,85521,84132,85521, -36256,85521,83903,85521, 9,85534, 9,85521,83903,85538,35187,85538, -35187,85521, 9,85544, 3,85384,85467,85549,85387,85549,85403,85549, -85401,85549,83903,85557,85391,85549,85517,85549,85405,85549, 53,85549, - 1471,85549, 253,85549,76285,85549,76939,85549,72567,85549, 241,85549, - 483,85579, 9,85579, 2,85385, 3,85385, 165,85587, 1108,85587, - 1072,85587,76337,85587, 1011,85587, 483,85596, 9,85596,85111,85586, -85125,85603, 9,85587, 1011,85606, 483,85587, 1011,85610,80151,85384, - 17,85615,85111,85385, 1368,85618, 7,85618, 2,85623, 2,85622, - 1369,85618, 2,85619,85629,85631, 3,85619,85627,85635,85121,85635, -85217,85635,85621,85635,85133,85635, 2,85618, 7,85646,85635,85649, - 3,85618,85625,85653,85125,85653,55211,85385, 265,85659, 17,85385, - 3,80533,73221,85665, 9,85667,78796,85665, 9,85671, 8139,85665, -53639,85665,42521,85665,85322,85665, 9,85681,55004,85665,85111,85665, -77751,85686, 9,85689,42613,85664, 483,85693,10291,85664, 483,85697, -79549,85664, 483,85701,85585,85665, 9,85705, 9,85664, 1369,85709, - 15,85664,37663,85713,85125,85713,38305,85664,43053,85719, 483,85719, - 17,85665, 903,85725,35187,85665,77751,85728, 9,85731, 4,85664, -85125,85735,37663,85735, 5,85664,76939,85741, 1471,85741, 53,85741, - 253,85741,76285,85741,72567,85741, 241,85741, 9,85755, 483,85755, - 5,85665, 1505,85761, 922,85761, 918,85761,54597,85760, 903,85761, - 9,85770, 483,85770, 483,85761, 903,85776, 9,85761, 903,85780, -77751,85760, 9,85785,79756,85665, 9,85789,84185,85665, 16,85792, - 7,85792, 4,85797, 4,85796, 17,85792, 4,85793,85803,85805, - 483,85805, 5,85793,85801,85811,85797,85811,85795,85811, 4,85792, - 7,85818,85811,85821, 5,85792,85799,85825,54597,85665, 11,85829, - 5,85828, 1369,85665, 9,85835,18967,85665, 4,85839, 483,85841, -77751,85665,35187,85844, 9,85847, 9,85845,85111,85851,85111,85844, - 9,85855, 5,85845, 17,85859, 5,85844, 9,85863,77751,85664, - 375,85867,79986,80533, 375,85871, 2,80533,80080,85875,80079,85877, -80298,85875,80319,85881,80293,85875, 4,85884,80319,85887, 4,85885, -80301,85891,11727,85875,11047,85875,17787,85875,18737,85875,78670,85875, -77859,85903,10874,85875,77952,85875,77857,85909, 7,85874,83903,85913, -85167,85875,85355,85875,85213,85875, 1216,85875,77751,85923,77877,85925, -77751,85922,77857,85929,62310,85875,64483,85875,68896,85875,62464,85875, -61780,85875,61688,85875,85159,85875,10831,85875, 9,85946, 413,85875, -77751,85951,77837,85953,77751,85950,77859,85957,74571,85875,17178,85875, -50959,85875,43400,85875,11177,85875,84077,85875,85913,85971,40675,85875, -55546,85875,54440,85875,69196,85875,17125,85875, 9,85982,15029,85875, -65869,85986,52169,85875,49155,85875,40453,85875,43305,85875,40005,85875, -84767,85875,77751,86001, 9,86003,73994,85875,42613,85874,42795,86009, -10291,85874,36131,86013,70135,85875,53919,85875,10195,85875,79842,85875, -79757,85875, 903,86024,63493,85875, 8861,85875,80058,85875,80079,86033, -54422,85875,11529,85875,54447,85875,52601,85875, 145,85875,35187,86044, -36096,85875,79601,85875,79549,85874,80501,86053,79719,86053,64396,85875, -85111,86059, 1011,85875,43215,86062, 241,85875,54295,86066,65869,85875, -60857,86070,15029,86070, 9,85875,10831,86076,60857,86076,17125,86076, -84076,85875, 483,86085, 803,85875,60857,86088, 903,85875,53813,86093, -60857,86092,10107,86093,69877,86093,79757,86092,71229,86092, 265,85875, -55211,86106,10371,85875,42787,85875,55211,85875,60857,86114, 265,86114, -38305,85874,46169,86121,80531,86121,72818,85875, 11,85875,43215,86128, -43316,85875,35187,85875,54295,86134, 145,86134,71229,85875, 903,86140, - 155,86140,43215,85875, 10,86147, 10,86146,85111,86147, 1011,86146, -84767,86147, 11,86147,86151,86159, 11,86146,86149,86163, 155,85875, -71229,86166, 5,85874,55211,86171,64345,86171,84132,86171,36256,86171, -83903,86171, 9,86180, 9,86171,83903,86184,35187,86184,35187,86171, - 9,86190, 4,85875,80070,86195,80077,86197,80293,86195,80315,86201, -80293,86194,80319,86205, 483,86195,83903,86209,80533,86194, 3,86213, - 7,86195,86215,86217, 2,86217,86213,86221,79987,86194,80079,86225, -83903,86194, 483,86229,77751,86195,79545,86233, 3,86235, 2,86234, -86237,86239, 2,86235, 3,86234,86243,86245,77751,86194,79549,86249, - 3,86251, 2,86250,86253,86255, 2,86251, 3,86250,86259,86261, - 5,85875,85914,86265,85913,86265,83903,86268,49713,86265,49712,86264, -86273,86275,49712,86265,49713,86264,86279,86281,53813,86265,64317,86265, -64815,86265,62077,86265,10107,86265,69877,86265, 17,86265,83903,86297, -35187,86297,60857,86264,85111,86303,65869,86265, 9,86307, 587,86265, -60857,86311,83903,86265,85913,86314,79757,85874,79987,86319, 4,86321, - 5,86320,86323,86325, 5,86321, 4,86320,86329,86331,80336,85875, -79549,86335, 3,86337, 2,86336,86339,86341, 2,86337, 3,86336, -86345,86347,83903,85875, 16,86351, 7,86351,86265,86355, 4,86354, - 4,86355, 17,86351, 4,86351, 7,86364, 5,86351,86361,86369, - 4,86350,86363,86373, 483,86373, 5,86350,86359,86379,86367,86379, -86355,86379,86353,86379,54295,85875, 241,86388,35187,86388,60857,85875, - 7,86395, 4,86396, 4,86397,86265,86397, 16,86395, 17,86395, - 803,86394,55211,86394, 903,86394,65869,86394, 9,86394, 4,86394, -86407,86419, 5,86394,86399,86423,86405,86423,85111,86423, 4,86395, - 7,86430,86423,86433, 5,86395,86401,86437,77751,85875, 413,86440, -77859,86443, 413,86441,77949,86447, 1216,86440,77857,86451, 1216,86441, -78669,86455, 4,86441,79757,86459, 3,86461, 2,86460,86463,86465, - 2,86461, 3,86460,86469,86471, 4,86440,79549,86475, 3,86477, - 2,86476,86479,86481, 2,86477, 3,86476,86485,86487,79987,85875, -80244,86491,80245,86491,80151,86491, 5,86496, 5,86497, 4,86491, -80083,86503,80029,86503,80063,86503,86501,86503, 5,86491,80151,86512, - 4,86490,80079,86517,86513,86517,86493,86517,86515,86517,86499,86517, - 5,86490,86495,86529,86503,86529,77751,85874,86529,86535,86503,86536, -86532,86535,86521,86535,86512,86535,86517,86545,86503,86535,86529,86548, -86491,86535, 5,86552,86517,86555, 5,86553,86503,86559,85663,86535, -85100,86535, 9,86535,84767,86566,84767,86535, 9,86570, 5,86535, -86491,86574,86517,86577,86491,86575,86529,86581,80150,80533,80315,86585, -80301,86586,80298,86585,80319,86591,80301,86585,80315,86594,80316,86585, -80325,86585,80293,86585, 4,86602,80319,86605, 4,86603,80301,86609, -85663,86585,85100,86585, 9,86585,84767,86616,84767,86585, 9,86620, - 4,86585,80293,86625,80315,86627,80293,86624,80319,86631, 4,80533, -79968,86635,79967,86637,80498,86635,80519,86641,80497,86635, 2,86644, -80519,86647, 2,86645,80501,86651,78670,86635,77859,86655,77952,86635, -77857,86659, 0,86635,21605,86663, 587,86665, 7,86635, 483,86669, -18967,86671, 0,86634,19917,86675,58930,86675,86673,86675,56555,86675, - 587,86682, 587,86675,56555,86686, 7,86634,58931,86691,86675,86693, -86677,86691,86679,86691,19916,86691,86675,86701,86265,86691,86667,86691, -86689,86691,86685,86691, 1275,86691,18967,86712,86675,86715,18967,86691, - 1275,86718,86675,86721,29023,86635,25513,86635,24619,86635,84363,86635, -84723,86635,84471,86635, 1216,86635,77751,86737,77877,86739,77751,86736, -77857,86743,63610,86635,63291,86635,84321,86635,86028,86635,86030,86635, -85960,86635,86437,86635,76631,86635,76601,86635,74682,86635, 8974,86635, - 413,86635,77751,86769,77837,86771,77751,86768,77859,86775,63493,86635, - 483,86778,85875,86778,29598,86635,25545,86635,59206,86635,15029,86635, -56555,86790,62942,86635,80030,86635,79987,86635, 1011,86798,74571,86635, -85875,86802, 483,86802, 8861,86635,85875,86808, 483,86808,79926,86635, -79967,86815,85875,86635, 8861,86818,63493,86818,74571,86818,79263,86635, -76816,86635,77387,86829,76500,86635,84185,86833, 11,86833, 903,86635, -28715,86838,56555,86635,15029,86842, 483,86635,63493,86846,74571,86846, - 8861,86846, 1011,86635,79987,86854,60857,86854,10073,86635,27855,86635, -62278,86635, 587,86635,28715,86866,29026,86635,60857,86635, 1011,86872, - 1347,86872,28715,86635, 11,86879,84185,86879, 903,86878, 587,86878, - 1347,86635,60857,86888, 2,86634, 4,86893, 7,86895, 3,86634, -85125,86899,37663,86899, 2,86635,79962,86905,79965,86907,80497,86905, -80515,86911,80497,86904,80519,86915,79757,86904,79967,86919,71229,86904, -77387,86923,77751,86905,79065,86927, 5,86929, 4,86928,86931,86933, - 4,86929, 5,86928,86937,86939,77751,86904,79139,86943, 5,86945, - 4,86944,86947,86949, 4,86945, 5,86944,86953,86955, 3,86635, -85217,86959,85121,86959,86897,86959,86217,86959,85133,86959, 6,86959, - 6,86958, 7,86958,86971,86975, 7,86959,86973,86979,60755,86959, -35927,86959,38155,86959,37611,86959,71229,86958,84185,86991, 11,86991, -79987,86634,79757,86997, 2,86999, 3,86998,87001,87003, 3,86999, - 2,86998,87007,87009,80150,86635,79139,87013, 5,87015, 4,87014, -87017,87019, 4,87015, 5,87014,87023,87025,84767,86635, 1368,87029, - 7,87029, 2,87032, 2,87033, 1369,87029, 2,87029, 7,87040, - 3,87029,87037,87045, 2,87028,87039,87049, 3,87028,87035,87053, -87043,87053,87031,87053,71229,86635, 7,87061, 2,87062, 2,87063, - 1368,87061, 1369,87061, 2,87060,77387,87073,87071,87073, 3,87060, -87065,87079,87069,87079,84185,87079, 11,87079, 2,87061,77373,87089, -76635,87089, 7,87088,87079,87095,72519,87089, 3,87061,87067,87101, -85875,87101,77751,86635, 413,87106,77859,87109, 413,87107,77949,87113, - 1216,87106,77857,87117, 1216,87107,78669,87121, 2,87107,79987,87125, - 5,87127, 4,87126,87129,87131, 4,87127, 5,87126,87135,87137, - 2,87106,79139,87141, 5,87143, 4,87142,87145,87147, 4,87143, - 5,87142,87151,87153,79757,86635,80450,87157,80451,87157,80337,87157, - 3,87162, 3,87163, 2,87157,79971,87169,79841,87169,79961,87169, -87167,87169, 3,87157,80337,87178, 2,87156,79967,87183,87179,87183, -87159,87183,87181,87183,87165,87183, 3,87156,87161,87195,87169,87195, -77751,86634,87195,87201,87169,87202,87198,87201,87187,87201,87178,87201, -87183,87211,87169,87201,87195,87214,87157,87201, 3,87218,87183,87221, - 3,87219,87169,87225, 3,87201,87157,87228,87183,87231,87157,87229, -87195,87235,80336,80533,80515,87239,80501,87240,80498,87239,80519,87245, -80501,87239,80515,87248,80516,87239,80525,87239,80497,87239, 2,87256, -80519,87259, 2,87257,80501,87263, 2,87239,80497,87267,80515,87269, -80497,87266,80519,87273,77751,80533,79962,87277, 2,87279,79971,87281, - 2,87278,79967,87285,80070,87277, 4,87289,80083,87291, 4,87288, -80079,87295,79968,87277,79967,87299,80080,87277,80079,87303,80498,87277, -80519,87307,80298,87277,80319,87311,80497,87277, 2,87314,80519,87317, - 2,87315,80501,87321,80293,87277, 4,87324,80319,87327, 4,87325, -80301,87331,81857,87277,78453,87277,80233,87277,80445,87277, 8453,87277, - 273,87277,84484,87277,85230,87277,84531,87277,85277,87277,21522,87277, - 1516,87277,38266,87277, 948,87277,20239,87277, 1477,87277,37095,87277, - 281,87277,84473,87277, 1011,87370,85215,87277, 903,87374,80242,87277, -80448,87277,80447,87277, 903,87382,80241,87277, 1011,87386,38057,87277, - 903,87390, 165,87277, 903,87394,21315,87277, 1011,87398, 1505,87277, - 1011,87402, 1216,87276, 412,87276, 413,87277,87409,87411, 1217,87277, -87407,87415, 413,87276, 1216,87277, 1217,87276,87421,87423, 412,87277, -87419,87427,12377,87277, 375,87277,57522,87277,67028,87277,67800,87277, - 510,87277, 240,87277, 265,87443,77750,87445,77751,87444,87447,87449, -77751,87445,77750,87444,87453,87455, 264,87277,84517,87459,85263,87459, -81749,87459, 341,87459, 264,87276, 375,87469, 241,87277,81464,87472, -81465,87473,87475,87477,81464,87473,81465,87472,87481,87483, 1011,87277, -84473,87486,80241,87486, 1505,87486,21315,87486, 903,87277,85215,87496, -80447,87496, 165,87496,38057,87496, 483,87277,65869,87506, 9,87506, - 9,87277,56555,87512, 483,87512,56555,87277, 9,87518,65869,87518, -65869,87277, 483,87524,56555,87524, 5,87277,84185,87531, 1011,87533, - 2,87531,80532,87536, 3,87531,85215,87541, 3,87530,87539,87545, -85263,87545,84517,87545,81749,87545, 2,87530,87533,87555, 4,87276, -87531,87559, 2,87561, 3,87561, 2,87560,87565,87567, 3,87560, -87563,87571, 3,87277,85111,87575, 903,87577,87559,87575, 0,87581, - 1,87580,87583,87585, 1,87581, 0,87580,87589,87591, 4,87575, -80532,87594, 5,87575,84473,87599, 5,87574,87597,87603,84517,87603, -85263,87603,81749,87603, 4,87574,87577,87613, 2,87276,85663,87617, -85100,87617, 9,87617,84767,87622,84767,87617, 9,87626,87575,87617, - 4,87631, 5,87631, 4,87630,87635,87637, 5,87630,87633,87641, - 2,87277,79962,87645,79965,87647,80497,87645,80515,87651,80497,87644, -80519,87655,79962,87644,79967,87659,87559,87645, 7,87663, 6,87662, -87665,87667, 6,87663, 7,87662,87671,87673, 4,87645, 1011,87677, -77751,87679,77750,87678,87681,87683,77750,87679,77751,87678,87687,87689, - 4,87644, 265,87693,77750,87695,77751,87694,87697,87699,77751,87695, -77750,87694,87703,87705, 3,87276, 375,87709,87645,87709, 4,87713, - 5,87713, 4,87712,87717,87719, 5,87712,87715,87723, 4,87277, -80070,87727,80077,87729,80293,87727,80315,87733,80293,87726,80319,87737, -80070,87726,80079,87741, 2,87727, 903,87745,77751,87747,77750,87746, -87749,87751,77750,87747,77751,87746,87755,87757, 2,87726, 265,87761, -77750,87763,77751,87762,87765,87767,77751,87763,77750,87762,87771,87773, - 5,87276,87575,87777, 7,87779, 6,87778,87781,87783, 6,87779, - 7,87778,87787,87789,87645,87777, 0,87793, 1,87792,87795,87797, - 1,87793, 0,87792,87801,87803,87727,87777, 2,87807, 3,87807, - 2,87806,87811,87813, 3,87806,87809,87817 -}; - -const int s_nDataSize2 = 24772; -unsigned int s_Data2[24772] = { - 3, 9, 5, 6, 119, 796, 636, 113, 449, 235, 239, 105, - 789, 96, 439, 624, 630, 230, 111, 110, 787, 786, 628, 627, - 116, 115, 436, 435, 227, 226, 93, 92, 792, 791, 100, 99, - 443, 442, 633, 632, 128, 183, 234, 178, 233, 85, 762, 203, - 32, 742, 356, 169, 152, 12, 672, 741, 127, 168, 671, 740, - 50, 352, 149, 64, 414, 197, 276, 751, 722, 396, 275, 434, - 721, 785, 274, 795, 720, 448, 273, 719, 474, 758, 718, 392, - 269, 748, 715, 400, 118, 794, 635, 81, 76, 750, 747, 597, - 595, 91, 433, 225, 74, 745, 680, 565, 268, 476, 271, 761, - 350, 678, 345, 567, 757, 471, 470, 563, 469, 561, 551, 461, - 465, 706, 650, 714, 261, 332, 641, 708, 676, 542, 260, 458, - 755, 314, 325, 658, 288, 349, 760, 654, 656, 564, 562, 644, - 552, 642, 550, 259, 252, 254, 322, 311, 329, 109, 784, 626, - 43, 395, 182, 55, 399, 186, 104, 447, 238, 41, 389, 173, - 175, 193, 485, 580, 579, 734, 25, 733, 528, 548, 310, 546, - 344, 526, 308, 560, 342, 525, 556, 558, 523, 524, 522, 520, - 307, 622, 623, 431, 618, 620, 429, 617, 305, 615, 519, 518, - 516, 778, 304, 250, 302, 776, 216, 218, 774, 215, 301, 300, - 514, 771, 513, 541, 298, 512, 297, 535, 321, 508, 510, 319, - 538, 539, 533, 507, 509, 296, 146, 705, 531, 537, 317, 557, - 341, 143, 697, 555, 544, 339, 613, 426, 217, 773, 619, 428, - 221, 780, 611, 610, 424, 609, 769, 423, 422, 768, 213, 625, - 783, 670, 732, 782, 578, 577, 731, 484, 387, 668, 669, 171, - 172, 375, 191, 575, 729, 482, 446, 667, 237, 574, 728, 481, - 398, 666, 185, 573, 727, 480, 394, 665, 181, 572, 695, 694, - 140, 738, 372, 246, 690, 689, 136, 244, 369, 767, 212, 766, - 702, 701, 367, 257, 700, 315, 726, 382, 59, 407, 190, 52, - 366, 157, 65, 417, 201, 63, 413, 194, 686, 692, 243, 248, - 699, 256, 150, 354, 365, 364, 353, 156, 685, 348, 242, 661, - 192, 409, 376, 378, 411, 164, 569, 717, 473, 391, 660, 177, - 189, 406, 374, 371, 405, 162, 200, 416, 363, 362, 415, 155, - 313, 324, 361, 360, 331, 312, 328, 381, 316, 330, 359, 323, - 4596,24359,41366,41344, 4857,37718, 4594,24357, 4846,37706, 4678,26650, - 4592,24355, 4844,37704, 4591,24354, 4843,37703, 8816,41900,22056,15422, - 7473, 8464,42932, 8814,41898, 6804,20483,12853, 8462,42930, 8809,42808, -21978,15306, 7385, 8456,42895, 8807,41327,21965,15246,15293, 7372, 8454, -42893, 3212,20457,36983, 3516, 6187, 6184,20453,29352,10563,10421, 2593, -20452, 6183, 5637, 2589, 6182, 2645, 2619, 2283,26212,20199, 2269,12513, - 2614, 2661,18113, 2288, 4777,35226, 4775, 4774, 4773,42536, 2198,32674, -32753, 8833, 8780,40027,43084,39938,43445, 8548, 8831,24157,26148,31156, -29057, 8503, 8771, 8777,24156,26147,36425,33823,40025,43073,43081,39936, -43443,22500,18803, 8829, 8770,40023,43072,39934,43438, 8546, 8827,24155, -26146,31154,29044, 8501, 8765,24153,26140,36424,33800,33820,40022,43066, -39933,43435,22498,18801,43065,40020,43434,39931,18800,22493, 8764, 8499, -26128,24151,33799,36411, 8826, 8544,26120,24146,29025,31141, 8762, 8824, -43063,40019,43432,39929, 2287, 2286,21235,26865,13688,26627,13207,20826, - 2106, 2073, 4667, 4378, 1966, 4054,13206,20825, 2159, 2168,18699,39853, -10355,39675, 2167,39852,13205,18520, 2158,39674,20824,20823,42653,42280, -18519,10116,21390,13926, 2032,42279, 1932,42652, 2166, 2157,42651, 5184, -42278, 5035, 2070,21389,20822, 4377,13925,13204, 5034, 5183,13924,21388, - 5033, 5182,39673,42650,39851,42277, 4221, 5142,18518,21387,18698,20821, - 4220, 4982,10115,13923,10354,13203,39850,42276,39672,42649,20820,18697, -42648,39671,42275,39849,18517,21386, 4376, 5032,13202,10353,13922,10114, - 4375, 5181,20819,18696,21385,18516, 4981, 5141,42274,39848,42647,39670, - 5031, 5180,42646, 5140,42273, 4980, 4219,21384,20818, 4374,13921,13201, - 5135, 5174,39653,42257,39831,42630, 5172, 5133,24141,26112,31138,29023, - 5026, 4969, 4975,24140,26111,36408,33796,39651,42249,42254,39829,42628, -21363,18686, 5139, 5179,39669,42272,39847,42645, 5178, 5138,18515,20817, -18695,21383, 5030, 4979,10113,13200,10352,13920,39668,42271,39846,42644, -21382,18694, 5170,24183, 5169,36516, 5168,39992, 5167,22753, 5166,21404, - 5165,39867, 5164,21361, 4045,26846, 4044,21215, 5162,39827, 5191,21359, - 5190,39825, 5189, 5160, 5159, 4043, 5157, 5024, 1891,42248, 1847,42621, - 4193, 4341,18472,20750, 1681,21357,10093,13145,13869, 2660, 7371, 2659, - 2658,13144,20749, 1846, 1890,39824,18682,39649,10344, 1872,39823,18507, -13143, 1889,39648,20748,20747,42620,42247,10107,18506,21356,13868, 1871, -42246, 1843,42619, 2205,26240,26211, 2200,24249,24232, 2478, 2517,36625, -34562,31491,29570, 2507, 2558,34076,37229,29433,31635, 8704, 8600,35491, -38460,30352,32396,28999, 8171, 8335,38314,35364,32268,30297,30134, 8698, - 8591,35488,38453,30345,32384,32389, 8166, 8333,38305,35357,32255,30292, - 2285, 7325, 1898,14098, 1896, 1895, 1894,39359,24288,41706,41800,20017, -37217,39357,36575,18022,26236,20013,24246,39355,39925,18013,18779,20001, -22482,39395,20196,39397,20208,40017,39923,20064,42324,12370,42658,19065, -18776,41387,41382, 9904,21392,10687,10412,41365,41360,18055,18053,39685, -20893,39857,18775,43056,43431,42334,18524,42660,22479,40016,39922,14502, -15946,39376,39374,20062,20060,21649,22478,39380,39378,12368,18702,43055, -43430,18057,39680, 9906,39855,39991,21351,22752,39816,39990,39815,22751, -21350,39639,39814,33754,42230,28989,42602,18468,18677,24118,26056,31087, -28988,10090,10312,10318,24117,26055,36340,33753,39637,20700,20705,39812, -18675,42228,42600,42219,42225,18464,42598,21348,39635,39810,13101,13106, -13844,26054,24116,33752,36339,20699,21346,26053,24115,28987,31086,42218, -42595,36338,39633,31085,39808,39667,39845,39666,39844,39665,39843,18693, -18692,10351,10350,18514,39842,13199,13198,10112,39664,20816,20815,10111, -18513,42270,42643,13919,21381,13918,42269,21380,42642,39806,21403,21344, -39866,39805,39865,21343,21402,39804,21342,21175,26830,39802,21173,26826, -21340,39346,24061,39338,32626,39333, 9843,39332,39331, 9814,39328,15936, -39183,11746,19744,25614,39182,39181,39180,19836,42268,11903,42641,17932, -17931,40961,40960, 9771,21379, 9770, 9769,40959,40958,17930,17929,39663, -20814,39841,17928,40957,40956,42267,18512,42640,19835,39179,39178,11902, -11901,39177,39176,19834,19833,19832,19831,39175,39174,11900,18691,40955, -40954,17927,39662, 9768,39840,39173,19830,11899,17926,40953,13197, 9767, -40952,20813, 9766,17925,40951,11898,19829,39172,11897,42266,19828,19827, -42639,11896,40950,21378,13917,39171,39170,39169,39168,14088, 3310, 3309, -35263, 2276,26305, 5245, 6267, 5248, 5445,10636,10624, 5401, 7751, 5390, - 5674, 2548, 5410, 3350, 3931, 3971, 3960, 6123,28071,22800, 8025,27598, -16338, 7478,22061,15427, 3847, 3840, 3822, 5835,26825,21172, 7148,26571, -13617, 6808,20693,13100, 3469, 3729, 3618, 6021,27993,22666, 7965,27534, -16152,16158, 7368,21963,15285,15291, 3513, 3757, 3655, 6026,28010,22688, - 7970,27539,16193, 7376,21969,15297, 3722, 3611,27986,22657,22659,16147, - 3608, 3610,25575,25569,25573,25568, 2720, 2722,23945,23941,23943,23940, - 3606,26233,26200, 2718,24244,24224, 3603,22654,16143, 2716,22466,15931, - 8720, 2547, 2499, 2498,35234, 8719,35524, 7050,35233, 6181,20028, 5622, -20027, 5610, 7023,23939,24648,23938,24484, 5952, 7920,22462,25567,27390, -15928,25566,27757, 5620, 7027,36388,33781,31116,29009, 5970, 7936,33795, -36407,29022,31137, 5612, 7025,24121,24653,24129,24494, 5960, 7922,26081, -27412,26074,27796, 5601, 7014, 6501, 5946,27753,22458, 7917,27387,15926, - 4317, 7284,21850,15156, 5825, 5940, 5824, 5794, 7123, 6732, 6038,28015, -22709, 7982,27551,16225, 7395,21983,15311, 8718, 5673, 7049, 8717,35523, -23937,21560,14272,15352,40871,22739,16272,23936,22733,16263,14776,40870, -21558,14265,23935,21474,14087,15148,40869,22445,15906,23934,41714,40868, -34075,23933,34079,40867,41730,23932,41537,31827,37396,23931,41448, 4494, -23930,41503,23929,26451,38349,32305,23928,24323,23927,40866,31785,37351, -23925,40858, 4472,23924,40862,23923,40853,38197,23920,23919,38475,23914, -23913,38152,23908,40840,28843,38481,23905,23904,23903,23902,23901,23900, -23899,23898,23897,23896,40839,40838,23895,23894,40837,40836,23893,40835, -23892,23891,40834,40833,23890,40832,23889,23888,40831,40830,23887,40829, -23886,23885,40828,40827,23884,23882,40823,40826,40822,23879,23878,40819, -40818,23877,23876,23922,23875,23874,32490,32499,23873,23872,32793,23871, -17197,23870,23869,29043,33819,24320,40817,29655,38507,24317,24309,28839, -33590,23867,23868,23865,40816,25558,25555,23866,40815,23860,23864,21472, -14085,40814,22439,15900,25548,23863,40812,23859,23856,40811,40805,40808, -23858,33581,33583,23854,23881,33580,33592,23853,23852,19635,33579,40804, -23848,23844,33560,33558,35258,40795,23843,33557,33556,35255,25392,23842, -33555,33554,23841,24131,24133,23789,17857,23787,18134,25390,26230,23785, -25387,26229,26199,23783,23782,23781,23780,23779,23778,24120,24128,23777, -17845,23775,27731,25366,18759,23762,23761,23760,23759,23758,23757,23851, -23847,40801,40803,23850,33457,33578,35260,23849,33572,23756,33456,23755, -25328,18750,10402,24219,24218,24217,24239,41600,41620,24216,24215,24238, -29171,33958,24221,24241,24214,24237,24213,24236,24223,24243,24231,24248, -24235,24212,41619,41599,24580,24740,24486,24650,24479,24643,24493,24652, -24536,24696,24535,24695,24534,24694,24533,24693,24640,40701,30096,38438, -24638,24477,35149,24692,24532,24054,24053,24052,24051,24050,23803,17878, -23801,25476,23799,23798,23797,33549, 3281, 2981,35267, 2427, 2429, 2425, - 2424, 2495, 7047, 7649, 2423,21521,14156, 2422,35247,23754,40705,23741, -40684,40700,23725, 4338,40674,23724,40673, 7842, 7748, 7750, 7746, 7745, - 7744, 7761, 7758, 7769, 7651, 7653, 7648, 7647, 7646, 7645,21520,14155, - 6300,21670,14601, 7644,35246, 8354,35392, 7811, 7809, 7813,37284,31745, - 7771,36483,31210, 7788, 7802,36473,31194, 4186, 4465, 4184,13064, 4181, - 4180, 4236, 4246,23721,39799,39630,23720,18459,23719,10083,18671,39628, -33435,13819,10309,39797,28701,21329,36039,30815,42588,42206,25299,25298, -13062,42586,20667,20672,42197,42203,23718,21332,13824,33434,42590,28700, -42208,30814,36038,25297,20676,13069,39022,22404,15866,17830,43413,13837, - 9689,43025,21338, 9687,17828,40683,11384,19518,39000,11387,42593,21639, -19521,42214,14460,40699,20689,13087,24049,24531,24691, 4190,23717,22449, -15912,25296,20692,13099,23753,22427,15895,25337,20666,13060,23716,22403, -15865,25288,20665,13059,13584, 4199, 4197,23711,19508,11363,25282,20745, -13140, 9063, 9396, 9184, 9168, 9338,38785,32799, 9254,23359,17393, 9336, -38782,32791, 9247,23353,17357, 9344,38793,32809, 9282,23387,17431, 9456, -38858,32878, 9094,23244,17141,23710,21540,14212,15278,40657,22649,16130, - 2758,21538,14208, 3347, 5771, 1853, 5082, 1788, 4966,42481,42234, 1708, -26963,42233,26591,42480, 1852, 3346, 3345,42479,37847, 1851,37846, 1835, -13635,42478,42232,37845,26590, 1785,10346, 1834,35043, 1833,37844,13634, - 6891,27206, 6890,42477, 6889,37843, 5951, 5949,22464,27759, 5930, 5929, -22774,28067, 5928, 5927,20495,26455, 5926, 5925,26249,26192, 5924,26307, - 5934, 5932,27724,22402, 5923, 6119, 5922, 7262,27717, 5920, 6917, 6277, - 5918, 5917, 5916, 5915, 5914, 5954, 6118, 6927,27234, 6888,42759,27205, -29027,43024,42739, 8746,29048, 8768,43069, 6886, 6887,27204,42738,28699, -43023, 8745, 8742,43021, 8741,43020, 8740,43019, 8784,43196, 8739,43018, - 8767,43068, 8523, 8744, 4957,42196, 5672,42195, 4956,42194,24230,42193, -33939,33938,24127,42192,33769,35199,24492,42191,35198,33768,24688,20662, -24528,20661,24048,41181, 4990, 4842,42304,37700, 5671, 5670,42303,37699, - 2546, 2545,37881,42519, 5669, 5668,37880,42518, 2544, 5667, 5666, 4137, - 5106, 5104, 5072, 5070, 5074, 5076, 5068, 5067, 5066, 5065, 5064, 5063, - 5100, 5096, 5095, 5094, 5084, 5062, 4634, 5061,42190,28698,42457,26562, - 4635, 5091,42302,26982,42517,26626, 4666, 5090,37879, 4989,13687,42301, -42516,37878,26981, 4665,10365, 4136,35060, 5089,42515, 4988,26625,42300, -42514,26624,26980, 4664,42299, 4135,26979, 5088, 4134, 4987, 4663,42298, -42513, 2163,37877,13686, 2162,42512, 2150,26623,37876,10364,35059,13685, - 2161,42297, 2142,37875, 2140,42511, 2149,42296, 5087, 4986, 1917,26978, -42295,26622,42510, 2148, 4848, 4862, 4827, 4826, 4841,37698, 4882,13463, -42509,42294,37697,26621, 4840,10189, 4881,34876, 4839,37696, 4880,13462, -37874,13684, 5086,37695, 4985,13461,42293,42508,37694,26977, 4838,10188, - 4879,34875,23729,34834,40698,40656,23709,34880,40655,41381,24211,34827, -41560,41559, 4874,34826, 4876,34861, 4892,34905, 4878,37693,13460, 4898, -37778,13508, 8353,35391, 8390,35436, 8581, 8534, 8602,38462, 8683,38525, -15448, 8641,38478, 8579,15277,38435,15138,33431,16652,33730,33429,34560, -29423,29381,40645,41866,33391,26227,33910,40643,18131,33513,11326,11531, -33511,28664,40769,33510,40787,33508,28642,40785,33751,18774,41232,27772, -33679,28943,12118,40634,40633,33677,28941,40629,40632,40628,33675,28936, -41598,41618,33605,33597,33360,33359,33358,33357,33787,39161,39321,39320, -36288,34527,26330,41849,18165,34522,26325,33349,34055,41845,18161,34536, -39160,38969,23693,41793,39327,39626,32091,42030,33307,32090, 4703,33453, -28723,25230,25229,33306,28623,26436,26446,33608,33305,40807,35522,19640, -33304,40825,35232,19645,33303,34053,33301,34044,34048,33298,41691,33296, -41683,41686,33295,33536,33540,33535,33292,33287,33282,33286,33935,33933, -33279,40631,33711,41180,33709,41173,35230,19918,33708,41172,35520,19917, -33707,41171,33577,28797,33278,28611,33892,29148,33886,29144,33277,28610, -33276,28609,33275,28608,33274,28607,33291,28620,33273,28606,43071,33822, -43437,35917,33272,28605,36118,33548,30917,35916,33484,35981,35979,30906, -28760,30775,33546,36116,33383,36083,28645,33367,28749,33482,33271,35915, -36081,30729,33270,28604,39412,30728,39470,35914,33309,33311,39410,39456, -18196,25216,28625,35913,39468,39505,20324,25215,30734,41748,35944,41830, -23695,23697,28638,39458,33331,39507,25232,25234,30736,33269,41797,41832, -18192,23675,35964,35966,41701,41752,20319,23674,35912,30727,41697,28603, -41792,33268,33267,28602,36620,34558,31487,35911,33425,33427,36622,28601, -37113,31476,28689,35910,31489,33266,34471,37010,34556,30813,36021,36023, -29384,34420,37214,28675,33409,33411,31478,37012,30791,33265,29426,35909, -37115,34422,36005,36007,34066,30726,34473,29386,35908,30725,34068,37210, -29428,33264,39067,39069,23701,30724,23703,35907,23673,39065,33386,25214, -23672,39063,28670,25213,36000,30777,40776,40768,25250,25252,33263,40764, -28600,40762,33262,28599,43013,30723,43400,35906,23671,21636,22383,25212, -14454,15824,15837,33740,28975,43052,33261,43429,36320,33739,28974,43051, -31074,43428,36319,24075,31084,21648,28986,22477,26012,36329,14493,33749, -15945,43398,43011,22377,15823,14439,21634,26052,24114,33366,33365,28644, -33480,28747,36111,33529,30902,36079,33473,33260,33259,33972,33258,33553, -33285,28618,41597,41617,33284,33970,33294,33539,33528,28778,11448,40591, -40590,33526,33525,33524,33523,39058,39057,23835,30901,23815,36110,33479, -25517,28746,25494,40753,40752,33538,28787,40610,40608,33522,33780,40589, -42861,23670,33778,35362,33256,35344,33254,33463,34043,29414,41685,41783, -34041,29411,26400,26365,34040,41682,34039,34052,29420,34038,29410,34037, -29409,34065,34064,29425,34036,29408,39406,31565,39466,37204,34456,39450, -18188,26395,37101,39499,20313,26360,41742,41824,24283,24274,29519,34552, -31485,41780,36616,41681,34035,29407,36615,34551,31484,37203,34455,29376, -37100,31472,34411,37003,34047,29418,41695,41790,34046,34050,34034,34073, -34032,33930,33941,29158,33932,29155,33929,29153,33798,41083,18043,35223, -35283,35285,35154,35225,35169,30109,40588,40587,35146,30088,22376,15822, -35144,30086,22374,15820,35142,30084,22372,15818,39529,39623,35148,35209, -39159,35167,39318,35262,30208,40586,40585,35254,30204,41614,41595,35257, -30206,40794,40799,35162,40709,18758,34825,35269,35266,10793,10619,35245, -10783,10561,35251,35243,35242,33724,33728,33722,33721,33968,34685,29738, -40704,40703,34727,29780,41380,41359,34710,29763,20739,40561,13138,40560, -34684,29737,20657,40559,13052,40558,33851,27196, 9902,42736,26993,36435, -42547,42321,12366,27711,36437,43010,33439,42468, 9680,42735, 9685,36043, -11382,33445,11374,42216,36041,43009,33849,37911, 9900,42734,35066,36431, -37907,33847,12364,27710,36433,43008,35081,12602,37746,35083,35007,31772, -37338,35022,35015,35047,35005,35004,35003,35002,35001,35000,10302,35071, -10368,35013,35012,35011,34999,10301,13577,37817,34998,42180,10300,28558, -17770,37820,19393,34996,13579,42450,37818,26546,35045,35058,42292,10363, -26976,10362,37873,13683,35057,13682,42507,37872,26620,35056,37692,10361, -13459,34874,37871,37691,35055,13681,10187,37870,34873,35054,37869,10360, -13680,35053,37868,33660,25733, 9805,40999,26975,36216,42506,42291,11876, -25732,36215,40998,33659,42505, 9804,40997, 9803,36214,11875,33658,11874, -42290,36213,40996,33657,37867, 9802,40995,35052,36212,37866,33656,11873, -25731,36211,40994,33655,37690, 9801,40993,34872,36210,37689,33654,11872, -25730,36209,40992,33496,34824,18484,18433,34860,34891,18526,34871,42289, -10186,26974,10185,37688,13458,34870,13457,42504,37687,26619,34869,37686, -10184,13456,34868,37685,34922,37771,10204,13501,34915,37764,35355,41246, -40557,24074,35361,40556,41290,23645,35390,35394,35388,35387,35423,35431, -35421,35420,35419,34424,34430,29390,34410,29375,34409,29374,34408,29373, -43003,34454,43397,37099,34419,34418,29383,34554,25244,41863,17813,34550, -27709, 2281,26243,26215, 2280, 2279,26242,26806,26214,26542,23643,17768, - 9617,19682,25590, 9615,11631,25602,17766,11650,19701,23641,24043,17975, - 9857,19915,25886, 9855,12116,25884,17973,12114,19913,24041,24525,18827, -24685,10438,18963,10587,18825,10436,24523,10585,24683,18961, 2443, 2442, -18824,26805,10435,26541, 2441,21154,13576, 9256,38787,32802, 9246,38781, -32790, 9253,38784,32798, 6490, 6682,39661,39839, 6676, 6675, 6674, 6673, - 6672,39158, 6697,23640, 6775, 6783,36532,31231, 6580, 6579,18960,26804, -10584,26540, 6578,21153,13575, 6857,38536,32501, 6867,38538,32503, 6855, -38534,32498, 6822,20490,12860, 7477,22060,15426, 6814,20485,12855, 7472, -22055,15421, 8988,38813,32831, 8677,38488, 8239,38346, 6280,21655, 6279, -21654, 6320,23639,23638,23637,23636,40555,23635, 6274, 6315,38953, 8751, - 8823, 6245,23632,23631,14039,20651,37335,31769,15808,34822,24166,24163, -37375,31808,23727,25314,39344,39342,23630,14031,25171,15799, 6241,42999, - 8753,42998, 6240,42997, 6239,42996, 6238, 7605, 7603,21633,24145,14431, -24150,23743,21632,14430, 7577, 7576,21645,23768,14481,23764, 6237, 6236, -21631,42614,14429,42241, 6235,21630,14428,24073,24072,24071,24070,41264, -24069,24066,24065,37331,31766,24064,26009,24063,21647,14491, 8775,43079, - 8774,43078, 8737,42995, 7643,21669,14595,23622,21711,14828, 7827, 7826, -21710,23621,14827,23620, 7824,21709,14826, 6347, 6349, 6351,38519,32485, - 6362,38530,32492, 6364,38532,32494, 6358,38528,32489,18365,24583,18606, -18598,18597,18596,42444,37811,24657,24497,24634,24469,35138,24040,24039, -24522,24682,24681,24521,24578,24738,39405,39465,41680,20283,41779,18147, -18187,41741,20312,39449,41823,39498,24520,24680,24679,24519,24038,24037, -39157,39156,40949,19826,40948,17924,23619,23846,24202,35241,41126,33720, -25977,35386,41125,33719,25976,33718,41124,24482,24646,23834,23814,19058, -10678,43037,36075,43422,30854,19057,10677,42994,35892,43396,30674,15796, -22352,24144,24149,23613,23612,19134,10762,42990,37248,43394,31694,18444, -10075,18466,10092,18432,10073,18431,10072,18552,10124,18550,10122,23611, -23610,24036,24035,24518,24678,24677,24517,18454,10080,23609,23608,22370, -22368,15817,18448,25149,25148,18744,18741,10391,20660,23752,23751,22426, -22425,15894,18430,25336,25335,18757,18756,10405,20648,24161,24159,22349, -22348,15794,18522,26155,26150,18733,18732,10388,20880,35161,40708,34821, -25334,18505,10106,18494,10104,23607,23606,19397,19395,11212,18488,25147, -25146,17776,17773, 9620,20742,18381,38855,18383,23136,18385,38407,17765, -38850,17764,23121,17763,38405,17762,43195,17839,43034,17985,42989,17984, -42731,28965,42744,31065,17998,28977,19979,31082,42988,19997,43054,18379, -37275,17761,42173,28551,26945,42439,42170,28550,26539,30673,42436,42437, -19380,26536,26537,17760,42307,28549,30672,19379,42537,17759,42176,28548, -26948,37814,17758,34994,19378,30671,42446,19377,37812,17757,42746,28547, -30670,19376,43059,18265,10019,18264,10018,42987,20311,43393,18186,18921, -18906,18919,18915,18807,18731,38831,18730,23104,18729,38403,18869,18878, -18890,18823, 1666, 1701, 1613,22346,27707, 5904,15787,15792,27365, 7899, -15124,15129,21836, 7255, 1669, 1704, 1616,22339,27700, 5897,15785,27358, - 7892,15122,21829, 7248, 1664, 1699, 1611,22772,28065, 6116,16309,27593, - 8020,15404,22040, 7459, 1663, 1698, 1610,21183,26835, 5820,13632,26587, - 7143,13137,20738, 6799, 1829, 1839,37855,42487, 1838, 1828,42486,37854, - 2028, 2063, 1963,40545,40543, 2030, 2065, 1965, 2026, 2061, 1961, 2025, - 2060, 1960, 2154, 2146,37897,42535, 2153, 2145,37896,42534, 1827, 1837, -37853,42485, 1662, 1697,21182,26834, 1622, 4117, 7502, 7272, 7274,27373, -27378,27730,27742,17756,17854, 7245,27355,27697,18094, 7287,27392,27763, - 6313, 7244,27354,27696, 6266, 7243,27353,27695, 6311, 7242,28038,27694, - 7421, 7241,27352,27693, 6335, 7267, 7266, 7265, 7494,23605,23604,25145, -25144,23603,25143, 7324, 7323, 7322, 7321, 7320,20812,13196, 7319, 7318, -21377,13916, 7317, 4373, 7238,26225,26196, 8973,23120,16979, 8991,23130, -16996, 7361, 7359,33574,27527,28795,27980,30929,36127,23669,25203,23595, -25135,23750,25342, 8946,23103,16963,18369,38399,17755,38397,18727,38395, -39660, 8200,39838, 8199, 8198, 8197, 8196,39155, 8195, 8452,38335,42884, - 8140, 8431,38284,42842, 8238, 8459,38345,42916,17754,17853,18767,18068, - 4795, 4925,37367,42056, 4484, 4737,42533,37895, 4794, 4924,37366,42055, - 4483, 4736,37894,42532, 5148, 4829,39792,26808, 5188, 4825,39864,26903, -39989,27146, 4804,37381, 4788,37328, 4856,37595, 4824,37717, 5146, 4855, -39788,26801, 6299,27264,27094, 4457, 7316, 4456,27091,27262, 6297, 4299, - 4454,27752,27386, 7280, 4453,27978,27525, 7357, 4452,28047,27577, 7432, - 4451,27140,27285, 6329, 4450,27692,27351, 7237,13569, 4475,27089,27259, - 6295, 6696,21031,13404,34709,29762, 4560,34755,29808, 4581,34683,29736, - 4540,33871,35166,33467,24062,23862,25554,23594,25134,23714,23713,25286, - 4462, 4464, 4447, 4446, 4445, 4444, 4443, 4442, 4441, 4490, 4488, 4440, - 4439,34673,29726, 4521,33234, 4460, 4438, 4471, 4714, 4116, 4473, 4716, - 4119, 4497, 4755, 4167, 4493, 4495, 4753, 4165, 4466, 4711, 4111, 6367, -21723,14912, 6860,21744,15033, 9259,23362,17407,23593, 6328,21692,14780, - 6339,21695,14794, 6324,21690,14774, 4486, 4739, 4149, 4482, 4735, 4147, -14023, 4480, 4733, 4145, 4479, 4732, 4144, 4793, 4923,37365,42054, 4807, -37432, 4864,37753, 4806, 4936,37431,42088, 7907,23592,42849,23591,42851, -23590,42847, 8458,42915, 4918, 4916, 4911, 4910, 4909, 4933, 4932, 4931, - 4908, 4907, 4914,33979,42019,18138,33978,33765,42018,18021,35195,35194, -42017,18787,33764, 4922, 4792,42053,37364, 4747,26177, 4701,26259, 4705, - 4704, 4700, 4699, 4698, 4724, 4726, 4741, 4152, 4707, 4109, 4697, 4101, - 4696, 4100, 4695, 4099, 4694, 4098, 4693, 4097, 4745, 4156, 4749, 4162, - 4751,25133,24475,35152,24229,33977,24126,33763,24491,35193,34428,29388, -37024,34477,31481,37194,37023,31480,42016,37193,42435,34476,18270,10027, -26730,20331,26939,18213,20344,12777,42015,18212,42434,20330,18798,10416, -26729,20025,26938,18796,21497,14105,42014,18038,42433,21501,18025, 9892, -26728,21500,26937,18037,20021,12308,42013,18795,42432,20024, 4927,42065, - 4906,42012, 4935,42087, 4159, 4161, 4096, 4095, 5108,35087, 5099,35070, - 5057,34992, 4094, 5661, 4092, 5336,14586,14141,11159,11144, 4091, 5658, - 4090, 5522,14874,14302,14990,14331, 5862, 8892,17350,17552, 4089, 4088, - 4087, 5339, 4103, 5225,14403,14016, 5549,35329,26162,10521,41333,26658, -38425,42315,42540,15112,26160,38424,41335,33653,25729, 9800,40991,26618, -36208,42288,42503,11871,25728,36207,40990, 4791, 4921,37363,42052, 4478, - 4731,21062,26749, 4143, 4142,37893,42531, 4053, 4052,21234,26864, 4790, - 4920,37362,42051, 4477, 4730,21061,26748, 2152, 2144,37892,42530, 2059, - 2024,21233,26863, 4141, 4051, 1959, 4140,35970,21026,19466,37325,19470, -37594,35973,20647,36795,37324,20288,21025,20446,20646,37216,37593,36757, -37592,20286,20645,20426,21024,37208,37323,36392,41275,36391,41274,36390, -41273,36562,26297,36140,27688,36146,27687,37256,36530,36566,21023,20236, -37322,20194,37591,36542,20644,36570,37273,38249,36136,30938,42243,33227, -42616,33585,35886,30656,42245,33587,42618,33226,35885,30655,43077,28533, -43442,33225,36062,30839,43032,28725,43420,33455,35884,30654,42323,28532, -42657,33224,35963,40621,35883,30653,28530,41592,37231,31646,37228,31634, -37227,31633,37226,31632,37225,31631,36387,31115,36386,31114,36385,31113, -36384,31112,36134,40810,36142,40821,36071,40723,42984,38423,38141,32157, -38140,32156,38139,32155,38149,27088,38109,42750,38108,42749,38107,42748, -38187,27117,38186,27116,38100,42743,38088,27686,38247,38185,27115,38191, -27124,38214,27132,38159,27072,38158,32171,38157,32170,38156,32169,38228, -27110,38222,32183,38091,32101,38138,27063,36315,41193,31056,36314,41192, -31055,36313,41191,31054,36317,41195,31058,36312,31053,36311,31052,36310, -31051,36488,36486,36503,36501,37279,38775,37277,23368,37238,21750,37281, -21729,38738,38749,38748,38747,38746,38867,37264,27685,37262,31730,42983, -29628,43392,34603,37271,21705,37267,27297,37266,21703,37261,21701,36206, -40989,40988,36205,36204,40987,11870,25727,37684,13455,36203,40986,11869, -25726,37865,13677,36202,40985,11868,36078,42982,36077,40791,11447,37590, -37321,37589,37320,37588,37319,37587,37318,37601,37727,37586,37585,38474, -27258,38427,42992,38441,43041,42981,38422,38491,38421,40661,15111,25290, -37828,13590,37018,41853,37017,41852,37016,41851,37014,41847,37022,41855, -36427,41329,37904,42542,20055,26153,42839,38280,36037,40659,42464,37830, -19498,25285,42838,38279,36429,41331,27347,21820,20057,26158,42837,38278, -37832,42467,37810,42431,37809,42430,37825,31965,37834,31981,37808,31952, -37807,31951,37806,31950,37805,31949,37804,31948,37917,37915,37803,37802, -37901,37900,37801,42429,37800,42428,37799,42427,37910,42544,37909,32040, -37903,32034,37891,42529,37361,42050,21232,26862,21060,26747,37890,42528, -42049,37360,21231,26861,26746,21059,37889,42527,21230,26860,37888,42526, -21229,26859,36250,41019,31021,36249,41018,31020,36248,41017,31019,40536, -36252,41021,31023,36246,41015,37359,42048,19815,25716,41014,36245,36244, -41013,42047,37358,19814,25715,41012,36243,36242,41011,37887,42525,19813, -25714,41010,36241,36240,41009,42524,37886,19812,25713,41008,36239,36238, -41007,25712,19811,19810,25711,41006,36237,38303,27404,38277,32219,32089, -31946,38295,32233,38293,32229,38301,32251,38313,32267,38312,32266,38311, -32265,38310,32264,38316,32270,38322,27497,38321,32275,38320,32274,38319, -32273,38348,32304,37330,37597,39790,37599,37315,37576,39863,37575,39988, -37574,37314,37380,21016,21068,20643,20887,37573,37716,37379,37715,39787, -37714,37313,37312,37393,37311,31761,37371,31804,37429,31832,37334,37333, -31768,37340,31774,37317,31763,37373,31806,37310,31760,37309,31759,37308, -31758,37307,31757,37306,31756,37305,31755,37342,31782,37304,31754,37395, -31826,37357,42046,21058,26745,37356,42045,21057,26744,37384,21073,20905, -37725,37383,42080,21072,26757,36539,31236,42240,33909,42613,33908,36552, -36554,41277,27230,41843,41861,41231,32116,41230,41229,41228,40619,41868, -26318,41870,26320,40616,41138,41136,41859,41151,41140,40535,21494,14101, -23589,22490,15957,40534,22327,15761,11105,12188,25952,21433,14012,41188, -42876,41187,42788,41186,41198,41197,41185,41184,41183,41190,22326,15760, -25107,21432,14011,40532,21476,14091,25705,22469,15935,40531,22471,15939, -25961,21478,14093,40530,40528,40529,40526,40524,40522,40521,40546,40520, -40525,40519,40517,40518,40515,40513,40511,40510,40516,40509,40544,40508, -40527,40507,41533,40506,41451,40505,41499,40504,26449,40503,25565,42936, -22325,41892,27294,40502,40500,40501,40498,40497,22354,40496,27209,40495, -40494,40493,40492,40491,40490,40489,40488,40487,40486,40485,40484,40483, -40482,40481,40480,40479,40478,40477,40476,40475,40474,40473,40472,40471, -40470,40844,40873,40842,40469,40468,40467,40731,40727,40726,41525,41516, -41491,41482,41440,41413,41439,41412,41515,41524,41481,41490,43735,22324, -15759,16624,28157,21431,14010,43733,32591,21430,14009,28150,22323,15758, -43855,22322,43755,43758,43761,43764,43754,43757,43760,43763,43720,43719, -43718,43717,43716,43715,40425,40428,21429,14008,23586,22321,15757,40421, -40427,40420,40539,21428,14007,25691,22320,15756,40538,40419,41106,41105, -41104,41103,41102,41101,41100,41099,41098,41097,41096,41095,41094,41093, -41092,41091,41624,41622,41170,41169,41155,41150,41149,25938,40466,41386, -41364,41377,41358,41385,41363,41376,41357,41362,41384,41356,41375,40682, -40681,40697,40696,40680,40695,42655,42309,42637,42264,42636,42263,42635, -42262,42612,42239,41840,41839,40760,40781,40751,40750,40749,40748,40747, -40746,40745,40744,40743,19610,11499,40767,40742,19609,11498,40922,40921, -40920,40919,19824,11893,40806,19637,40824,19642,43451,43494,43383,43382, -43381,43426,43425,43403,43406,43493,42869,43492,41082,43497,25564,43543, -26448,43380,27232,43418,27208,41130,41128,41123,41122,41121,19910,41120, -19909,41119,21668,14585,25832,19949,12173,41118,21519,14140,25831,19948, -12172,40717,21471,14084,25676,22424,15893,40716,21470,14083,23749,22423, -15892,40715,21469,14082,25333,20638,13037,40714,40713,21468,21467,14081, -18429,25332,25331,18755,18754,10404,20637,43096,43094,43089,43552,43379, -43378,43391,43377,43405,43402,43376,43412,43411,43410,43050,27771,43049, -27770,43154,43150,43147,43146,42787,42875,42786,42791,42879,42790,42878, -42785,42874,42784,42873,42783,42872,42797,42800,42887,42799,42886,42804, -42889,42806,42891,42796,42883,42795,42882,42794,42881,42756,42863,42773, -42771,42766,42151,26932,42150,26931,42149,42148,42147,43496,43152,43542, -43214,43417,43030,42146,42578,43375,42972,42145,26304,42144, 8714,42143, - 4292,42142,41168,42213,26958,42212,26957,42211,42592,19520,28500,11386, -33192,42172,26944,42175,26947,41865,40982,40981,36199,25725,40980,33652, -36198,41589,38420,41594,26258,28531,41575,30651,28499,28529,30616,41573, -28498,26256,41591,41588,26253,29448,41570,31341,29251,41587,37002,26222, -41569,34280,36861,41579,41583,42426,42003,42441,42021,42422,42001,42421, -42000,42420,41999,42419,41998,42418,41997,42549,42554,42417,42416,42415, -42414,42413,42461,42460,42466,42035,42463,42033,42157,42424,42141,42412, -40979,40978,25668,42855,26110,42918,25092,42853,42871,42934,22317,42082, -25091,41996,26252,41995,41994,42037,43149,43093,42770,43091,42768,42068, -26182,43088,42765,42067,41993,41992,41991,41990,41989,41988,41090,42493, -42031,42411,42455,41986,42410,42058,35228,41985,33976,41984,33762,41983, -35192,41982,42064,26720,26751,42079,26756,41556,41555,41554,41553,41552, -41551,41550,41549,41548,41547,28954,36303,29445,28595,30719,28949,31037, -31036,28948,29138,29146,42040,18503,28890,11603,42085,18546,29136,12591, -28992,34983,33191,33607,28497,28496,28495,30615,28494,30614,28598,30722, -28597,30721,28493,40722,28492,43040,28938,33362,33190,28940,28933,33521, -28882,33189,28885,28491,33576,28490,28489,34058,28488,43036,30613,28487, -33738,43048,30612,28486,33188,33589,30951,30611,36138,35850,37007,33187, -34415,37109,35849,34465,37206,33186,33354,35968,35848,34061,36115,33185, -33364,35978,35847,33545,36598,33184,33281,35919,35846,33986,37009,33183, -34417,37112,35845,34470,37005,33182,34413,37103,35844,34460,36002,33181, -33988,36600,35843,33389,36004,33180,34063,37213,35842,33408,35921,33179, -33533,36113,35841,33289,29190,34982,29185,31274,29184,33907,37001,33984, -34407,37098,36596,34453,37212,33407,18346,19496,28643,33544,28617,28614, -28485,28484,28483,28673,28481,28479,29406,31544,29413,33178,34458,29378, -33352,37000,34029,34406,37097,37202,34452,29424,33406,34469,29382,29417, -29281,29422,29317,29405,29250,28838,28836,37849,42483,28814,30940,28478, -28477,37842,42476,28476,30606,28475,28474,38452,43058,28473,30605,28472, -28471,42453,37823,28739,28734,38419,42971,29679,43208,29678,43207,31729, -29627,33177,43206,31728,29626,29677,29650,43205,38505,28776,28775,42970, -36999,33520,34405,37096,36109,34451,35977,33543,17815,19590,28786,28783, -28774,28772,28771,30898,28770,28769,42474,37840,29623,12817,34588,34600, -31712,31658,37250,37234,37236,37269,29630,29589,34609,34590,33919,33906, -33913,33905,42969,31273,29183,33904,31235,36538,33925,31246,36556,36588, -29160,33943,37105,34462,18195,20323,37111,34468,18199,20327,37192,34475, -34981,37798,37021,34427,37199,34486,34447,37041,37036,34442,37198,34485, -34446,37040,37035,34441,37197,34484,34445,37039,37034,34440,37196,34483, -34444,37038,37033,34439,29372,42968,31543,29404,33981,31196,30367,30203, -30366,41981,18427,30356,14108,42029,18442,30336,14049,43491,18868,41980, -32456,32455,30380,30282,32249,32248,37303,10546,37572,14501,20624,30273, -35009,30290,34980,30280,30107,30279,30106,42967,38418,34593,34595,19025, -34597,19027,34592,19023,35427,30962,17897,28470,17732,38480,19333,35429, -19649,30604,38482,28844,35458,30603,17731,29656,18373,38508,20466,35444, -19332,31721,38493,28469,35460,31660,18367,29663,18375,38516,20472,35448, -20459,31725,38495,29587,28963,35440,31716,18371,30078,18726,38490,21427, -35454,20463,32088,38502,29646,29661,38512,29659,38510,34979,37797,17730, -19331,34977,37793,37795,35338,30602,17729,30097,18746,38439,21463,35336, -19330,32099,38437,28468,29180,29178,35416,31261,18112,29162,38477,20192, -35434,31268,18127,29166,38486,20217,35328,31264,18119,29164,38417,20198, -35327,31092,18019,30124,18785,38416,21482,35326,20004,32123,38415,28995, -34436,37030,18144,20280,34399,36995,29581,31652,29460,31502,31466,29366, -29003,31106,30139,30601,32132,28467,30142,30600,32143,28466,31130,29012, -34426,37020,17728,19329,34393,36989,28465,30597,29451,31497,31451,29356, -29455,29447,31340,30077,32087,31494,29249,30178,30202,30177,30299,30201, -30200,34404,36998,18725,21426,34279,36860,29360,30138,38134,36982,29363, -30425,38670,36988,29362,36987,29359,36981,29848,31780,31779,37302,10167, -37571,13097,20623,29838,31753,31752,37378,10150,37713,13026,20886,29854, -29837,29836,29887,36236,41005,31801,32030,31800,32029,41004,36235,37355, -42044,31799,32028,31798,32027,29877,29972,42043,37354,31797,32026,31796, -32025,29876,29971,37885,42523,31795,32024,31794,32023,29875,29970,42522, -37884,31793,32022,31792,32021,29874,29969,29873,29968,31791,32020,31790, -32019,29872,29967,37442,31835,31838,29892,20945,13294,37758,10198,37441, -42091,31834,32051,31837,32054,29891,29979,29963,29965,29961,29949,29948, -29947,29946,29945,29976,29975,29974,29956,31972,31971,41977,33975,31945, -33761,31944,31943,35191,29944,31942,31941,42063,42090,32050,32053,29978, -37353,42042,31017,31016,31015,31014,28924,28923,37883,42521,31013,31012, -31011,31010,28922,28921,36234,41003,31009,31008,28920,31007,31006,28919, -36573,36559,30749,41750,39927,27061,36085,28663,39519,26343,39521,26345, -39517,38971,39061,30955,30953,28834,28832,26597, 9597,20771, 9596,30942, -28812,13649,13159,36568,29087,20211,36550,30974,39555,30976,31207,31202, -39566,31213,39568,31215,32332,32324,14975,14864,32331,30971, 9587,30784, -30885,11334,11536,31035,28947,31034,28946,31033,28945,31032,30680,30682, -31027,43145,27971,38105,36361,38104,36360,38103,36359,38102,36358,30596, -30904,30595,30731,30594,30858,30593,30922,30592,31569,30591,31279,41602, -28464,40779,28463,40729,28462,30788,30920,30787,30919,30589,32108,30587, -30851,40741,31218,31282,31217,33158,31244,33923,33157,31281,31243,33922, -31223,31649,31222,33156,34481,31229,33155,31648,34480,31228,31103,41708, -30586,41705,30751,34057,30585,34060,30837,33551,31227,34479,33921,31242, -30584,33388,31238,33912,30583,33405,34467,30582,30581,34464,31590,33351, -33917,31240,31277,33471,30580,33542,30579,35822,28461,24137,33154,24135, -30578,35821,28460,20315,33153,18190,30577,35820,28459,20322,33152,18194, -40766,40775,28458,28669,33151,33385,31272,30897,33903,31234,31271,34450, -33902,31233,31270,36595,29182,20310,33983,18185,30576,35819,28457,20059, -33150,18701,40773,28667,42406,40772,30889,33149,30856,33148,31111,42577, -31110,31109,12307,41976,20622,30843,33147,31877,31865,31864,31875,38137, -37570,31904,31542,30896,31541,34449,31540,37201,29403,20309,34026,18184, -31630,42576,31629,31628,12776,41975,20621,31903,43374,33146,31108,31627, -33356,33519,31045,33145,43156,38484,28456,28455,38443,43045,28454,28453, -31152,30572,38414,42966,29040,29047,43204,38501,29676,29645,30895,36108, -28768,23808,33518,23827,31710,42921,31727,29625,36586,36582,36581,36580, -36579,36584,40740,29152,33928,31288,36607,29197,20336,33993,18262,31287, -36606,29196,20335,33992,18261,31286,36605,29195,23570,33991,23569,31284, -36603,29194,20334,33990,18260,37259,22029,43144,27970,32398,33816,32358, -33967,32372,33144,32371,32472,32357,32356,32355,32375,32377,32470,33143, -32469,32454,31940,32488,14328,32491,14344,32497,14301,32500,14308,39361, -26101,32247,10545,39782,26792,32246,31751,14500,13025,32238,39552,32227, -32323,32235,32231,32312,42580,32225,14040,42025,20652,32253,32263,42575, -32262,32261,14104,41974,20620,32260,32259,32300,32243,41593,28452,30571, -31099,41604,28451,30570,28450,30569,28449,41607,29090,41606,29089,30841, -28727,31733,29666,31732,29665,31225,31499,31220,31266,30568,31496,30567, -31263,30566,32131,30565,31105,30564,31091,30563,32122,30562,28448,42539, -28447,37827,28446,32197,32191,32196,32190,31097,31096,31095,38514,20470, -31258,31251,33142,31249,33223,31256,31255,31254,30650,30561,41572,26255, -41586,29175,31260,32084,31062,28962,32185,25060,43143,27969,32154,32153, -32152,32151,21506,32150,21505,37792,38136,43087,27905,42764,27245,41135, -25798,38184,32179,32181,32177,32114,32083,31493,32129,32128,32127,41585, -29248,31771,10157,39784,26794,31750,10149,39862,26902,39987,27145,31749, -31778,13024,13096,31777,10166,39781,26791,33466,43424,35165,40725,33880, -43390,32468,43373,32475,32374,33139,32354,31789,32018,31005,31004,31788, -32017,31787,32016,31830,13286,31829,32048,32045,25059,31976,25310,31939, -26251,31947,31983,31938,31937,32043,12475,31936,14107,31974,14074,31959, -35141,31935,33974,31934,33760,31933,35190,31932,13023,32258,14103,31931, -13022,31930,13021,32223,14038,32221,32257,32014,32013,31992,11595,31990, -31988,31986,31985,31963,31929,37791,29943,21499,34974,18036,29942,34973, -31928,18794,37790,20023,31927,37789,29941,20329,34972,18211,31926,31970, -32047,31003,32903,32767,32894,32750,32590,32608,16656,32623,12282,11039, -32630,32627,16680,32582,16581,32576,32615,32614,32573,32572,32570,32568, -32651,32665,32650,33138,32656,33896,33137,32664,32655,33895,32654,33894, -34023,32564,32563,33517,32562,41669,32828,32827,17502,17501,32745,32744, -16798,16797,32825,17495,32917,17319,32824,32850,17318,32849,32783,17544, -32797,17565,32561,32560,32658,32646,32926,32914,32913,32559,32558,32690, -32795,17563,17381,32684,32777,17541,17317,32672,17200,32670,17194,32669, -32741,16962,32740,32739,32738,32789,32923,32737,32736,32766,32755,10229, -10284,10239,10165,10237,10159,10228,10148,10227,10147,10226,10283, 9863, - 9748,40145,10048,40165,10050,40167,32291,31050,30365,28953,30176,28952, -28951,30343,30129,32290,32168,30364,30175,30174,30363,30199,30379, 9665, -21011,36541,36756,35972,36365,20445, 9752, 9582, 9750, 9581, 9627, 9634, - 9580, 9579, 9578,11036, 9648,11282, 9577,11035, 9667,34545,34581,35202, -33772, 9889, 9885, 9884, 9883,17877,17837,17713,17879,18133,17856,17712, -18096,17858,18098,18135,17711, 9949, 9955, 9953, 9952, 9951,18129,18093, -10037, 9640,23566,23565, 9646,23564,20220,33136,41616, 9694, 9697,23563, -19433,33135,40607,23562,24496,33134,35221,24699,33133,24539,33132,24046, -41177,10234,10296,10225,10282, 9726,21010, 9717, 9716, 9715, 9714, 9713, -11524, 9728,17865,24209,33927,10733,10730,23561,19623,33131,40798,23560, -24148,33130,33815,10024,21009,23559,20317,33129,41789,23694,20321,33330, -41796,40707,35160,25330,18753,34859,10070,18483,13378,34808,10099,18426, -13436,34909,10126,18555,13494,10794,10495,10784,10441,10782,10434,10796, -10498,10799,10512,10801,10515,10281,10224,10280,10223,10290,10231,35069, -34971,10279,26303,10278,10277,24228,33937,24125,24490,33767,35197,24673, -13015,24513,13014,24030,41167,10777,10431,10306,10236,34976,10768,10408, -10359,10183,10358,10182, 9797, 9796, 9795, 9799, 9794, 9793,10191,10196, -10146,10145,34402,34382,34392,34391,34390,34389,17710,18023,26235,26237, -26202,26204,18125,18089,18105,18118,17709,18100,18018,17708,18784,18778, -17707,18012,18092,26221,26195,18091,18724,18111,37836,42470,21174,26829, -37838,42472,21177,26832,37857,42495, 9576, 9575,21216,26848,11031,11030, -36545,41564,20204,26213, 9574,11029,36549,41567,20210,26218,41566,26217, -10511,10644,10497,10634,10420,10555,10514,10653,10508,10637,10403,34807, -14078,18425,36535,41546,20191,26194,10473,10618,10430,10580,10480,10623, -10491,10625,30183,10532,40102,10560,10582,10554,10579,32289,32272,10562, -10590,10628,10770,10617,10776,10620,10632,10550,10549,10548,10655,10630, -10616, 9860, 9852, 9851, 9854,10530,20618, 5566,20617, 9573,20885, 9712, -20616, 4291, 4290, 4289, 4288, 4287, 4286, 4356, 4355, 4354,41343,41339, -40665, 6669, 6709,20614,13010, 6821,20611,13007, 7470,22053,15419, 6720, -21548,14238,30101,35158,15891,22422,29753,34700,13136,20737, 4549, 4518, -29770,34717, 4565,29796,34743, 4572,29734,34681, 4535,41611,18173,41613, -33786,35208,34535,18103, 4285,42625,32907,32906,32195,32189,32188,32194, - 4993,42313, 4949,42140,42312,20607,20879,42139,10304,20606,13058,42138, -10729,20605,16109,42137,42448,42178,10276,42491,42136,42490, 4948,42489, -10286,42409, 4954,42443,36593,42135, 4284,42134,10029,42133, 9940,20935, - 9939,23558,12616,42351,23557,20934,33126,42350, 9183, 4283,10121,18549, - 4282,40459, 4281, 4280,20604,42634,13003,42261, 4279,20603,13002, 5137, - 4978,20602,42260,13001,42633,42632,42259,20601,20600,13000,12999,18690, -10349,20599,20598,12998,18689, 4278,20597,12997,18511,10110,20596,20595, -12996,18510,40918,20594,12995,17923, 9765,40917,20593,40916,17922,40692, -40691,40690,40689, 4320, 4322,40418,40417, 4306,40416,42585,42574, 4973, -42252, 4972,42405,42201,20670,42404,42200,10316,20703,13104,42223,10315, -42403,10097,18481,20592,20591,18478,12994,13134,20735,18415,18413,20734, -10063, 4277,20590,12993, 4335,20733,13133,35135,30076,22307,15748, 4399, - 4401, 4276, 4275, 4274, 4273, 4272, 4271,29721,34668, 4515, 4304,40712, -21466,14080,23748,22421,15890,40415,40514,41545,41544, 6668, 8194,33785, -35207,34534,40424,21425,14006,23588,22306,15747,40423,40414,40413,21439, -14026,23556,22334,15779, 4372, 4369, 4368, 4367,35151,30093,22413,15879, -35150, 4709,42027,20654,31957,13047, 4743, 4692,42062,20878,31969,13057, -32452,16107,32464,32480,32369,18743,24473,20658,26549,18117,24227,20589, -26528,18017,24124,20588,26527,18783,24489,20587,26526,40412,10275,20877, -12992,42311,41973,20586,31925,12991,30092,30275,29355,29432,30137,30296, -29002,29008, 4318,17706,23555,20691,26570,40411,25557, 6570, 4334,29718, -34665,12990,20585, 8185, 4333,34541,40410,21144,13573,23554,21321,13811, - 4337, 4332, 4331,17775,23649,20740,26589,18110,24208,20732,26586, 4339, -17705,23553,20744,26593,10094,18475,20584,20583,18473,12989,13156,20767, -18411,18408,20766,10060, 4269,20582,12988, 4346,20765,13155,23552,23551, -20958,20950,18569,13299,10132,18561,20957,23550,18568,23549,10131,18560, -23548,20949,23547,13298,10128,18557,20955,20947,18566,13296,23546,20967, -13309, 4426, 4425,20966,23545,13308,23544, 4422,20964,13306,18123,20907, -18736,26927,18735,20656,18116,20581,18016,20580,18782,20579,18072,27682, -18077,20932,18075,26926,18074,20930,18070,20923, 7374,21967,15295, 6806, -20578,12987, 7475,22058,15424, 7355,21955,15281, 6829,20897,13255, 7482, -22065,15432,17704,26941,39072,22305,15746,25553,21424,14005, 4345, 4344, -20764,39836,13154,39658, 4330, 4329,20731,26878,13132,26640, 5176, 5028, -20763,39657,13153,39835, 4328, 4672,20730,26639,13131,26877,39834,39656, -20762,20761,13152,13151,26876,26638,20729,20728,13130,13129, 4343,21375, -13913, 4327,21249,13704,39129,20760,13150,25661,20727,13128, 4364,20803, -13187, 4385,20846,13227, 4366,17904,26925,17903,20775,18109,20759, 4352, - 4363,17703,20773, 7224,21817,15106, 7278,21845,15151, 6793,20758,13149, - 7453,22033,15389, 4419, 4418,18063,20916,18723,20909, 4414, 4413,17702, -20911, 7222,21815,15104, 7399,21987,15317, 7350,21950,15275, 4312, 4362, -17701,20681, 7220,21813,15100,23543, 7430,22016,15356, 7436,22020,15361, - 7409,22000,15333, 7391,21981,15309, 9607, 9609,20868,26645,26883, 9571, -21254, 9570, 9569, 9568,20862,26642,26881, 9605,21252, 9603, 9711, 9710, -20845,26634,26872, 9709,21244, 9708,32149,17742,27675,18764,26633,17850, -27739, 7293,27674,27803, 7219, 7264,27723,27722, 7263,17700,27691, 7218, -27690,27673, 7233, 4397, 4384, 4387, 4383,10544,26524,14097,37564,10164, -26523,13611,37563,37712,26522,26665,37562, 4854,37711, 4819,37561,10169, -26582,13623,37610,37603,26564, 4833,37657,23542,26552,23747,26521,10144, -26664,13559,37710,24179,26684, 4622,26520, 4642,26575, 4621, 4680,26519, -26657, 4620, 4010, 4619, 4009, 4618, 4008, 4617, 4007, 4616, 4006, 4615, - 4005, 4614, 4004, 4613, 4003, 4612, 4002, 4651, 4042, 4650, 4041, 4649, - 4040,17699,42365, 4999,42364,42338,26673,42337,26672,17698,26694,10370, -26693, 9943,26689, 9942,26688, 4611,26518, 4610,42500, 4609,37862, 4608, -26517,42499,26516,37861,26515, 4984,42285,42284,26514,10357,26513, 4837, -37681,37680,26512,10181,26511,40976,36197,36196,40975, 9792,26510, 4627, - 4019, 4677, 4066, 4629, 4023, 4679,26656, 9567,17697,26655,26157,26889, -26152, 9850,17972,26509,25868,26789,25867, 5989, 4001, 5982, 4017, 9724, - 9832, 9821, 4068, 4021, 4025, 4000, 3999, 3998, 3997, 3996, 3995, 3994, - 3993, 3992,18079,18763,17849,17696, 5676, 3991, 5978, 4076, 9819, 4640, - 4639,26788,26573,26828,26827, 4655, 4607,26604,26847,26850,26787, 4653, - 4606,26845,26508,26844,26786, 4072, 4071, 4070, 9601, 9599,13239,13706, - 9566, 9565,13247,13710, 9707, 9706,13224,13694,32148,17740,27672,18762, -26869,17848,27738,17695,27802,26341,38967,25052,26190,25051,26188,25050, -12633,25049,12628,25048,26338,25047,12682,25046,26280,25045,12771,26095, -26329,25111,12672,25228,25044,25043,25042,25041,25040,25039,25038,25037, -25270,25269,25980,25979,25036,25035,25034,25033,25032,25295,25294,25293, -25292,26167,26172,26166,26171,26165,26170,26164,26169,25309,25308,25307, -26176,26181,26175,26180,26174,26179,25031,25030,25029,25028,25027,25026, -25025,25024,25023,25022,25021,25020,25019,25018,25017,25016,25015,25014, -25013,25012,25011,25010,25009,25008,25238,25236,25264,25266,25543,25542, -25537,25539,26316,26327,26091,25226,26059,26061,26058,32176,38181,25804, -25806,25802,25801,26108,20020,26093,20015,25242,19468,26336,20349,26335, -20348,26334,20347,26332,20343,26323,20340,25391,25370,29835,25369,34970, -26099,31094,32126,31253,35415,38473,36287,38148,36286,36285,25935,27057, -25934,26098,25933,26374,25963,27671,27340,25960,25932,27255,27085,25931, -25959,27050,26097,25967,26186,26184,33117,33965,33116,28439,29173,33964, -29435,34082,33115,28438,33114,34081,26377,26419,25260,33911,33531,28780, -28785,33537,33915,25007,25006,25005,33469,33960,29416,34045,33300,28622, -33283,28616,29170,33957,33350,34056,26369,26402,25004,26005,25003,25341, -29168,33955,34022,33954,26394,26357,28189,22298,28165,28167,33113,33899, -33112,28437,29150,33898,28123,33901,33516,28767,28122,28121,25552,40394, -25551,25550,28436,28435,28641,29402,29401,34021,26373,34969,26372,25248, -19474,11313,19927,25892,12124,28434,28433,25826,25825,26224,25828,26930, -26924,25830,25824,26967,41117,19947,12165,25389,26063,26083,27025,21441, -27190,21629,27108,27071,27244,32175,38180,27074,27070,27069,27076,27059, -21496,27027,27670,27047,34611,35085,27135,27056,34968,27055,38179,35414, -38472,38147,38146,27084,27254,27083,27253,27052,27222,31101,36363,26296, -26288,26271,26287,26283,20247,26285,26264,26290,26273,26294,26277,26293, -26276,26292,26275,25344,28055,28057,27828,27726,27784,27403,27783,27402, -27715,29840,27669,29881,29192,42830,42130,43047,27769,42402,37788,43086, -42763,41134,27668,42752,41279,41836,28023,27667,27737,29834,27736,27904, -27496,27903,27495,38178,32174,28432,28862,29400,29399,29247,27982,27966, -27515,38471,32426,38145,32163,36284,31043,27984,36120,40793,28431,28430, -29046,29039,27762,35413,38470,27243,27242,27068,28429,28880,29398,27126, -27270,27100,26923,27010,27012,26951,26961,26969,26954,26922,26921,26920, -26919,26918,42210,42129,30264,27000,42552,37919,29189,28991,30289,26917, -42459,37899,26956,42401,37787,43142,26916,41838,27054,26915,26914,27261, -27093,27122,27137,27139,27143,26929,27252,27082,26987,26986,26985,26984, -26965,27045,42306,26262,26269,26268,25864,25862,19907,12099,25861,21133, -13558,26232,25284,21158,13589,36233,41002,41001,36232,25459,25467,25466, -25439,25438,25437,25463,25462,25478,25436,25435,25434,25433,25432,25431, -25430,25429,25448,26797,26913,25450,25428,26630,26868,25427,25455,19572, -11451,19575,25453,11454,25425,19564,11435,25422,25421,34547,36611,29498, -31483,40783,36087,27782,27902,27499,27501,27494,27493,27401,27721,27720, -27719,27519,27514,27513,27512,26737,26742,26739,26717,26716,26715,26714, -26713,26735,26734,26733,36534,41543,26558,22395,26507,22420,26675,22296, -26506,20726,26578,20695,26505,20577,20876,26654,30266,30082,29431,29354, -30295,30136,29007,29001,26504,26785,26503,26784,26502,26783,26501,26782, -26653,20576,26803,26818,26810,26781,26780,26779,26778,26777,26905,26776, -26775,26774,26773,26772,26814,27666,26771,27735,27975,27749,28027,28044, -28037,26796,26770,26831,21179,21176,13621,13619,26843,21132,13557,26822, -26821,26820,25684,19793,25679,19791,25660,19781,25659,26261,25658,32147, -25657,26231,25656,25655,25654,27734,25653,25682,27665,27767,25704,27766, -27664,25703,25707,25652,27718,20178,20182,19439,11301,19435,11297,19999, -12305,20245,12674,20249,12676,20253,12680,20252,12679,20251,12678,26247, -21597,21596,21595,21594,30157,35219,33813,29037,29457,34543,40385,40384, -40383,40625,19655,20477,20475,42960,43367,42673,42571,42959,43366,19653, -28426,33105,28425,33104,19651,28424,33103,41111,41110,41108,31886,28423, -28422,28421,28420,19639,11546,19644,11548,19622,19115,41179,41153,19536, -11398,21323,21148,37369,37702,31765,21152,21314,21131,37377,37709,31776, -21130,32245,21129,21313,21128,21312,21127,21311,21126,21401,21305,37295, -37560,31748,21304,21374,13912,20757,20756,13148,21373,21241,13693,20725, -20724,13127,21240,21372,13911,21371,19612,11504,28419,40382,40381,19823, -11892,39128,20755,39127,19822,19780,11781,25651,20723,25650,19779,19821, -11891,19820,19819,11890,11889,19818,41089,41088,19437,11299,19540,11402, -19531,11393,20034,12310,20037,12329,15739,22295,20036,12328,20290,12758, -20300,12769,20299,12768,20298,12767,32458,40797,41132,40630,41662,41707, -41690,41785,41661,41774,41660,41773,41700,41699,41795,41684,41688,41659, -41727,41811,41725,41657,28418,28417,20229,12982,20228,20575,20225,12655, -20222,12653,28416,26302,42400,37786,22294,15738,22293,15737,22292,15736, -22291,15735,22290,15734,22289,15733,22288,15732,22287,15731,34719,29772, -35227,30162,29728,34675,35140,30081,34689,29742,35134,30075,29774,34721, -35133,30074,35253,30198,35132,30073,28931,33671,35130,30071,22286,35177, -22285,22284,22353,22283,31910,29115,29113,31879,28415,28414,22438,15899, -22282,15730,22746,21563,37294,37559,31747,21562,22748,16285,22750,16288, -22415,15884,22281,15729,22280,15728,22392,15849,22463,15930,34658,29711, -35157,30100,29710,34657,35156,30099,22419,15889,31863,29036,29035,22651, -16133,22653,16140,22658,16151,19922,19920,19906,40380,19905,19904,41087, -41116,19968,12203,19966,12201,19946,12164,19945,12163,38940,25109,21310, -21125,20232,12661,20234,12663,20240,12667,20239,12666,20238,12665,20242, -12669,20305,12687,20304,12686,20303,12685,20307,12689,20176,12631,20175, -12630,20180,12635,32140,31127,32139,31126,32138,31125,32137,31124,20351, -20346,31463,31462,31456,31448,31447,31446,31445,31862,32146,31924,41972, -21504,21503,21578,21577,21576,21575,27661,21437,21457,21455,32173,21534, -21532,21530,27660,41713,41802,42860,42754,41724,41810,21525,14160,21523, -14158,21518,14134,21517,14133,21542,14214,22955,23406,23405,23404,23403, -22986,21686,14735,21651,14505,41289,41281,42958,43365,40371,40370,43076, -43441,21638,14457,21657,14512,21674,14605,21672,14603,21667,14579,21666, -14578,19579,11459,19601,11477,25419,25417,19561,35438,30308,41723,41809, -27202,27033,21034,27713,21008,27733,25368,21007,27659,21075,22411,15877, -34878,29879,41558,41577,40612,40614,41693,41787,22278,15727,34907,29889, -26560,26816,22277,15726,26551,26812,22394,15852,22364,15806,34804,29833, -26500,26769,22363,15805,21481,20207,22481,20203,20213,20206,20202,26499, -26768,20201,20270,12650,20269,41342,41338,41337,41341,40664,40663,41562, -41581,20573,12980,29751,34698,34655,29708,34696,29749,34653,29706,41610, -20570,20569,34533,35206,33784,20568,18102,20567,12979,42624,42623,23537, -23536,20566,12978,20565,12977,41086,41085,36592,12658,20564,41808,41374, -41353,41373,41352,41372,41351,41371,40369,40368,40367,40366,40365,40364, -42597,42570,42569,42627,20664,13056,20563,12976,20800,13184,20754,20753, -13147,20799,20842,13223,20722,20721,13126,20841,20798,13183,20797,20650, -13049,20562,12975,20561,12974,20560,12973,20559,12972,41979,31961,42023, -42061,41971,31968,41970,32451,41969,40363,20875,13250,31923,42060,26496, -26767,21448,14037,20720,13125,20719,13124,25860,25859,20718,20717,25966, -25556,20796,13182,20927,13282,20929,13284,20809,13192,20795,13181,20866, -13243,20840,13222,20852,13232,20839,13221,21150,21156,21136,21124,21123, -21122,21121,21120,21278,27658,21119,25367,27732,21118,28025,21138,21117, -13556,21116,13555,21115,13554,21114,13553,21263,21262,21261,25415,25413, -12352,14223,12821,14281,12823,14284,11140,14523,11132,16013,16393,16380, -14985,14869,16399,16386,15015,14892,11966,11104,10996,14459,11321,11539, -11466,10995,11332,11472,11534,10994,11346,16643,10993,16653,11530,11520, -11433,12281,12285,11348,11345,40140,39228,11990,14113,11989,15240,11988, -21492,20011,21491,20010,21490,20009,21489,20008,21488,20007,21512,20042, -34803,29832,23535,23699,24207,21511,20041,33102,11672,22276,35218,11555, -11551,41176,11366,35137,40362,33101,40361,40523,41542,21487,21370,35188, -33950,13910,33100,40360,40499,41541,21486,20006,35187,33949,11888,43364, -33099,43363,12766,42568,18668,12657,36591,33098,32353,11080,12046,12039, -12010,12036,12014,11189,11191,37683,42287,11099,11101,37864,42502,11089, -11091,11066,11068,11117,36201,40984,12614,42348,27657,22275,42347,37744, -12613,12600,42346,37743,12538,12537,33097,13266,23526,27656,22272,12536, -12510,15773,14398,15722,33962,15721,26417,15720,26663,40355,15797,15719, -15718,33946,33830,33433,15717,15716,15715,26691,16233,33096,33095,15713, -33094,37344,33868,37388,33875,20474,32309,33833,33437,33837,17996,33093, -33092,15709,15706,15921,40354,33812,23525,20040,15834,32487,32496,32776, -40353,40352,33091,33811,33810,33809,37293,33808,33807,33806,33805,32299, -32474,32388,33090,32352,17684,23524,27756,22461,27655,22255,17843,23772, -17841,23746,27728,22418,26585,20716,15700,15099,15888,26495,26494,20558, -27029,21447,27036,21462,16104,14669,17900,16103,12971,40351,31922,32450, -25572,19660,17683,23523,26493,20557,16102,15274,26492,20556,12088,12087, -12086,41166,23522,12131,12085,42128,12084,40627,35975,37785,42399,12082, -12113,12079,12078,12077,12076,42498,37860,12075,12074,42283,37679,12073, -12072,40974,36195,12071,12123,41772,41771,41770,41769,41782,36891,41799, -36967,41768,36859,41807,12968,41806,36986,41805,36985,41767,36858,41766, -12517,12514,37751,12606,37749,12604,11378,42546,37906,11431,11430,11429, -11446,11450,11428,11427,11426,21537,12242,20215,20189,20274,21113,20200, -20268,20272,22254,20265,20555,20264,20794,20263,20262,21369,20261,20260, -22253,20257,20715,20267,24168,23521,41348,40350,24206,41540,22356,21036, -22362,21005,21070,22252,21510,21004,21146,22251,21140,22330,21435,21317, -13366,18487,13365,15909,18447,15816,21112,22361,15804,18405,15803,13364, -14077,13363,13435,13809,13572,15699,13492,18554,15698,36471,36498,36547, -15137,14053,16177,14484,40139,39954,15239,14112,15238,14111,15697,15887, -15864,40711,21465,20752,15098,20937,15326,36469,20468,15273,14182,20554, -15272,16100,14326,14299,15021,14896,15013,14890,14961,14960,14959,14958, -14853,14768,14231,14499,14426,14030,14767,14665,14705,14195,14692,14187, -14663,14180,14730,14577,14729,14132,14728,12159,14727,14726,43440,43362, -18059,34607,17682,34605,18720,34602,34903,14772,14786,14269,15355,14267, -14784,16269,15351,16265,14868,14852,14851,14850,14849,14957,14889,25722, -33651,14576,14575,14574,26973,14573,35051,14572,26612,14571,34867,14570, -14569,14096,13552,23520,14062,23519,39795,23518,21316,22250,39531,20793, -14004,39655,14003,21368,14002,39833,14001,14000,13999,39126,19817,40119, -40138,14280,14283,14228,20553,21485,20792,21484,14237,33758,33757,39753, -14240,39752,33089,14247,34800,14246,33088,21111,21451,14222,14207,26584, -15097,16099,14131,25721,33650,14130,14129,14128,26972,14127,35050,14126, -26611,14125,34866,14124,14123,14052,12157,12155,12153,12182,12152,12151, -12150,26971,12149,35049,12148,26610,12147,34865,33649,25720,13454,12146, -16900,17343,16912,17380,16619,16568,23517,16689,16566,24234,16564,22248, -16724,24188,16723,33085,16729,33890,33084,24187,23516,33889,16728,33888, -34012,16559,23826,33515,41648,16558,17067,17181,16557,26220,18087,16720, -16810,16773,16772,20552,17681,16771,16556,18719,16956,16955,17537,17300, -17536,17299,17535,17534,17297,17295,17293,17292,17291,17290,17533,17388, -17377,12965,12964,13095,12963,41609,18172,34532,35205,33783,15477,15532, -17101,12962,32905,32193,32187,16767,12961,13055,41347,13067,12960,18502, -12959,12958,18545,12957,17199,14073,18441,14048,32032,31967,31921,21110, -21446,14036,18404,14035,17680,23511,18740,24471,13163,13660,26601,20777, -18115,24226,18015,24123,18781,24488,12956,13551,26652,20874,40347,13054, -13588,26487,20551,40346,40512,41539,33756,35186,33948,13180,19648,25562, -20465,26438,30161,30303,21450,27031,29353,29430,30135,30294,29000,29006, -21461,27035,36984,41804,12955,13550,37747,42357,12954,13549,40345,25560, -26486,13123,33952,13122,13121,25965,25559,15460,15514,17055,17772,23647, -17679,23510,18108,24205,18121,17678,18738,18114,18014,18780,12953,26651, -18061,18085,17677,18083,18718,18081,15279,16126,15095,15694,17676,17906, -18107,15149,15902,13263,15344,16259,15353,16267,15187,15955,15289,16156, -15127,15790,15093,15692,13548,13610,13596,23508,22329,23745,22417,15809, -34823,15691,34863,22242,24181,15690,15886,20714,13547,40796,35139,33827, -33803,15828,15687,41794,13546,42222,13545,13544,13587,16239,34799,16238, -33082,13543,13578,42408,37794,37816,42445,13657,42127,13656,13655,13654, -42398,37782,13764,42369,17675,42368,13763,42367,13761,17674,13760,15683, -13728,13727,13542,13541,13540,42497,13539,37859,13538,42282,13537,13536, -37678,13535,40973,36194,13534,15680,14206,14568,14122,13667,13586,20550, -13585,11809,11819,11779,11817,12121,11775,11797, 9551,34857,33081,33079, - 1870,10340, 1763,21210, 1607,32011, 1803,35041,30536,30534,19291,31901, -17673,29870,28404,28402, 1820,37989, 1577,29932, 1748,18661, 1887,13864, -35765,35763,10964,37629, 9549,34854,33077,33074, 1867,10337, 1760,21207, - 1604,32008, 1800,35038,30532,30529,19289,31898,17671,29867,28400,28397, - 1817,37986, 1574,29929, 1745,18658, 1884,13861,35761,35758,10962,37626, - 9546,33071,33068,33066,19054,18717,14385,19286,38275,38056,30331,33064, -30526,30524,19282,30522,17667,28391,28388,28386,32215,35749,35477,35586, -10674,17664,21625,22234,35746,35744,10957,35742, 9542,33055,33053,33050, -19051,18714,14382,19279,38272,38053,30328,33047,30516,30513,19277,30510, -17661,28384,28382,28379,32212,35739,35474,35583,10671,17657,21622,22231, -35737,35734,10955,35731,17797,34167,33045,33043,36731,34323,33345,31399, -18340,31381,19447,34342,35958,30508,19267,31584,17649,29534,33325,28371, -17808,36906,20409,29311,35939,29295,34185,36925,35717,35715,19461,36750, -17796,34166,33029,33027,36730,34322,33344,31398,18339,31380,19446,34341, -35957,30500,19259,31583,17641,29533,33324,28368,17807,36905,20408,29310, -35938,29294,34184,36924,35713,35711,19460,36749,43358,33025,33022,33020, - 7205,40213, 6413,24632, 7559,39912, 6227,33018,42727,30498,27180,30496, -24775,28366,40212,28363, 7556,35709, 6226,43355, 7202,27333, 6412,42724, -35706,35704,39911,35702,43361,33015,33058,33061, 7208,40209, 6409,24630, - 7562,39908, 6223,33013,42730,30519,27183,30493,24778,28361,40216,28394, - 7555,35699, 6230,43354, 7201,27332, 6416,42723,35755,35752,39915,35697, -17638,10331,34848,35032,30491, 1811,33011, 1568, 9531, 1739,19256, 1878, -35695,32002,21053,21201,18613,18652,33008,29923,17635, 1861,10944, 1754, -35692, 1598,28359, 1794,37620,37980,19253,13855,17632,34202,33647,33633, -36770,34359,33005,31436,18359,31419,19250,34375,35689,30992,19768,31615, -17920,29549,33004,28918,17631,36945,20439,29346,35688,29330,34219,36962, -36230,36193,19249,36789,17630,33377,33646,33632,36229,33003,30991,17919, -30769,19248,35687,19767,28655,28917,35994,36192,17889,10746,35613,35557, -30927, 8803,33565, 5749, 9746, 8073,19628, 8560,36125,32295,22558,21685, -18903,19091,33570,30376,17895, 8844,11544, 6969,36132, 6014,28802, 8448, -38196,38333,19633,14689,17888,10745,35612,35556,30926, 8802,33564, 5748, - 9745, 8072,19627, 8559,36124,32294,22557,21684,18902,19090,33569,30375, -17894, 8843,11543, 6968,36131, 6013,28801, 8447,38195,38332,19632,14688, -17887,17628,35611,35555,30925,30488,33563,33001, 9744, 9528,19626,19246, -36123,35685,22556,21683,18901,19089,33568,32999,17893,17626,11542,10941, -36130,35683,28800,28356,38194,38331,19631,19244,39563,10143,34967,34798, -30660,42077,33233,26992,33856,42320,31186,31181,39684,31861,24419,21003, -26998,18587,42331,29831,29068,29085,36449,39689,35890,24423,28540,39559, -37950,37553,42072,13360,33862,18638,33197,33201,35065,37723,32038,34797, -31175,18619,33846,21002,30630,37949,31192,19345,29074,17746,28509,34966, -36467,18586,29079,21066,29936,37552,38021,34889,35855,35859,36462,21109, -33210,18637,33451,33444,35020,37608,31979,34796,30643,18604,33205,21001, -30835,37948,30639,19516,28522,17835,28711,34965,35868,18585,28517,21046, -29911,37551,37970,34832,36049,36060,35864,21108,18010,35175,33221,33215, -31081,18584,33736,21859,37947,37550,29904,35353,36327,30648,19351,32120, -17752,30423,33747,28527,31920,38450,34964,34795,36337,18946,28984,21000, -35874,35879,19988,38641,17823,18358,28697,29563,30809,31435,33401,34358, -38685,38468,31614,31418,36017,36769,11343,12750, 9663,10013,33421,34218, -32162,32425,36788,36944,36033,36961,28685,29329,30799,31601,19492,20438, -17822,18357,28696,29562,30808,31434,33400,34357,38467,38684,31613,31417, -36016,36768,11342,12749, 9662,10012,33420,34217,32424,32161,36787,36943, -36032,36960,28684,29328,30798,31600,19491,20437,17821,18356,33685,33684, -30807,31433,33399,34356,36258,36257,31612,31416,36015,36767,19976,19975, -17962,17961,33419,34216,31042,31041,36786,36942,36031,36959,28683,29327, -36265,36264,19490,20436,10003,34321,34165,34340,17795,32160,11309,35238, -35956,35937,28636,34183,31582,38466,20424,31397,18329,29293,29532,35383, -30747,36729,33323,33343, 9657,38683,19459,30427,36748,36904,12740,36923, -10002,34320,34164,34339,17794,32423,11308,35382,35955,35936,28635,34182, -31581,38682,20423,31396,18328,29292,29531,35237,30746,36728,33322,33342, - 9656,38465,19458,30305,36747,36903,12739,36922,33683,34319,34163,34338, -17793,31040,19974,33715,35954,35935,33682,34181,31580,36256,31048,31395, -28956,29291,29530,33714,36263,36727,33321,33341,17960,36255,19457,28928, -36746,36902,36262,36921,43340,17624,32997,32995, 7188,40208, 6408,32993, - 7542,39907, 6222,24772,42710,35681,27167,19242,24766,17621,40196,32990, - 7554,27177, 6210,43353, 7200,35678, 6396,42722,35675,35673,39895,19240, -34525,23507,32987, 7309,32975, 7308,24977,23337,17054,17288,23183,40340, -24975,23336,17053,17287,23182,40338,40336,23181,17052,24973,23335,17286, -38810,32821,40605,39392,25222,38772,40603,39389,25224,32726,38771,32725, -40601,40599,23180,39383,17051,39386,25220,25218,23334,24199,17285,24192, -25279,25281,38770,38769,38961,32820,32724,32723,38959,38809,40652,40654, -38955,38957,41224,17050,25995,23333,41226,23179,25993,17284,23681,23679, -32973,39048,40641,13960,23505,13952,23503,13969,23500,23498,39722,23496, -39746,23493,39745,40067,31682,40070,31685,40072,31687,40066,31681,40065, -31680,40055,31673,39721, 9923,39744, 9934,39743, 9933,16510,32971, 2826, -28343, 2824,40334,40332,40331,40329,40327,40325,40323,40321, 6294,22565, -16042, 6271,22626,16092, 4266,22625,16091,10919,19223, 6624,10911,24964, - 7087,19217,24960, 5724, 2709, 3037, 3181, 4265,22622,16089, 4298,22620, -16087, 7349,21949,15271, 7347,21947,15269, 7345,21945,15267, 3206, 5752, -10899,17800,34171,33121,33125,36735,34327,33348,31403,18344,31385,19450, -34346,35961,30552,19305,31588,17694,29538,33328,28443,17811,36910,20413, -29315,35942,29299,34189,36929,35807,35803,19464,36754,17799,34170,33120, -33124,36734,34326,33347,31402,18343,31384,19449,34345,35960,30551,19304, -31587,17693,29537,33327,28442,17810,36909,20412,29314,35941,29298,34188, -36928,35806,35802,19463,36753,18636,34169,33119,33123,36733,34325,34794, -31401,18342,31383,20999,34344,37946,30550,19303,31586,17692,29536,34963, -28441,18583,36908,20411,29313,37549,29297,34187,36927,35805,35801,21107, -36752,34520,23692,17727,34206,33644,33630,36773,34362,33170,31439,18362, -31423,19328,34379,35834,30989,19765,31619,17917,29553,33166,28915,17723, -36949,20442,29350,35830,29333,34222,36965,36227,36190,19324,36793,17726, -34205,33423,33403,37945,34793,33169,31860,18635,31422,19327,34378,35833, -30811,19494,31618,17825,29552,33165,28687,17722,36948,21106,29349,35829, -29830,34962,37548,36019,36035,19323,36792,17725,34204,34961,34792,36772, -34361,33168,31438,18361,31421,19326,34377,35832,31859,21105,31617,18634, -29551,33164,29829,17721,36947,20441,29348,35828,29332,34221,36964,37944, -37547,19322,36791,17719,33381,33643,33629,36226,33162,30988,17916,30773, -19320,35826,19764,28659,28914,35998,36189,17718,33380,33494,33506,37943, -34791,33161,31858,18633,30772,19319,33379,35825,30915,19588,30771,17875, -28658,33160,28758,17717,35997,21104,28657,35824,29828,34960,37546,36106, -36096,19318,35996,34201,17619,33398,33418,34790,37942,31857,32969,31415, -18632,34374,19209,30806,35662,31611,19489,29548,17820,28682,32964,36941, -17615,29345,21103,29827,35647,37538,34959,36030,36014,36785,19204,38965, -38827,38964,38402,38963,38394,30483,30481,30479,30197,30173,30172,37558, -37533,33232,26991,33855,42319,26997,31853,42071,34785,30663,10141,42330, -20996,31185,37937,30659,42076,28539,39558,29067,34954,39683,18580,28536, -13358,39562,37532,24418,29823,36448,39688,35889,24422,37708,37640,36827, -41765,29940,37091,37531,38132,37530,29954,29939,29952,29938,18047,17687, -18179,17690,37648,36442,36300,26727,26710,26725,26709,36053,36296,36454, - 8812, 5812, 8435, 8792, 4905,43814,43311,43002,43286,42582,42845,42928, -42841,17738,17994,17736,17882,37784,37852,36298,36308,42834,26708,42866, -42924,42836,41896, 4061, 5984, 5996, 3392, 6655, 3665, 5991, 2355,11822, -11824,12297,12293,41271,41244, 9823, 9825,28555,30678,23629,25170,28972, -31072,24113,26051,28716,30818,23740,25326,28544,30669,23602,25142, 9678, - 9673,12176,11804, 6292,22567,16044,14145,14590, 2539, 5657,14143,14588, -14164,14610, 2549, 5675, 1621, 5475, 1922, 5500, 3097, 5374, 5384, 3103, - 1927, 5218, 5216, 1912, 5230, 1907, 5228, 1909, 1924, 5240, 1920, 5242, - 5251, 1915,16600,16633,10970,11111,10966,11285,11116,12195,12208,11050, -24332,28819,28826,30947,37995,11048,37653,24461,38605,24787,38432,11046, -28807,30934,11044,43887,43853,43884,43850,43879,43845,43876,43842,14147, -14592,11113,12199,17610,19104,17607,19103,35640,28333, 8578, 8135, 4818, - 4785, 8230, 8669, 8667, 8228, 8584, 8161, 8176, 8596, 8576, 8133, 6923, - 6164,36294, 8790,36293, 6921, 6162, 6901, 6157, 4816, 4783, 8178, 8598, - 6925, 6166, 8586, 8163, 6903, 6159,24751,12788,39418,38649,38634,36069, -38630,37529,39997,39585,40148,40037,40013,40113,39995,39678,40109,39587, -39677,39544,39583,40111,39582,38677,35816,35815,38676,38692,38648,32845, -30554,32330,30665,31742,31199,32322,32317,10868,10865,28325,28322,28318, -28315,18253,11572,11569,37502,37165,35655,35652,35793,36302,36292,18631, -34162,32968,32963,36726,34318,34789,31394,18338,31379,20998,34337,37941, -30485,19208,31579,17614,29529,34958,28341,18582,36901,20407,29309,37537, -29290,34180,36920,35646,35661,21102,36745,18630,18355,32967,32962,31856, -31432,34788,34355,34200,34373,31610,31414,37940,36766,19207,19203,17613, -17618,34957,34215,29547,29344,36784,36940,37536,36958,29826,29326,35645, -35660,21101,20435,18629,17873,32966,32961,31855,30913,34787,33504,33376, -33375,30768,30767,37939,36104,19206,19202,17612,17617,34956,33492,28654, -28653,35993,35992,37535,36094,29825,28756,35644,35659,21100,19586,35799, - 9353, 9466, 9351, 8511, 8467, 9356, 9355,38382,28878,28873,28860,28855, -36282,36277,35797,18255,27821, 2597,18244,18243, 2456, 2596,18258,20185, -18251,18250,18248, 2639,37181,37178,37131,37164,37190,37163,37162,37161, - 2628, 2484,37160,37130,37159,37189,37158,37107,35671,28353,30196,28348, -30171,28352,28351,30211,28330,32980,32985,32978,32983,28346,28350,28329, -32887,32733,36647,36641,39425,39436,39434,17467,17466,17465,11252,11231, -11249,11228,28577,30701,28571,30695,17464,36512,36527,32681,33885, 2803, -29143, 2801,33883, 2815,29141, 2814,17283,36510,23099, 8940,16953, 8939, -24190,24197,17374,36514,23332, 9222,17282, 9221,24186,24195,16899,36509, -17342,36508,16716,36507,23331, 9220,17281, 9219,23513,23515,16898,35774, -16770,35773,35812,32912, 9413, 9412,38826,38825,32843,32842,36520,32749, -36525,32722,36524,32765, 9315, 9314,38768,38767,32721,32720,36523,32902, -36522,32643,11922,11919,17550,32854,17500,32826,17196,32891,17326,32918, -14566,13036,13033,13045, 9827,20640,20632, 5980,21627, 6232,20630, 4294, -28502,30618, 3072, 3390, 3308, 3501, 3294, 3479, 3296, 3485, 3291, 3474, -24393,42188,24390,42185,10400,38621,10397,38618,38600,37957,38597,37954, - 3369, 3053, 2347, 2474, 2341, 2468, 3497, 3306, 3387, 3070, 3372, 3056, - 3462, 3288, 3460, 3286, 3367, 3051, 6898, 5577, 6896, 5575, 6912, 5608, - 3262,38172,27114, 3033,38221,27106, 3031, 2490,38144,27081, 2488, 9523, -38143,27080, 9895, 3361, 3413, 3411, 2340, 2338,19193,20045, 3436,16188, - 7760,16186,16190,16166, 7755,27548, 7979,27546, 7977,27554, 7985,27371, - 7905,27369, 7903,10218,34894,29094,29104,23572,40849,33705,33700, 5477, - 3365, 5504, 2343, 5409, 3495, 5442, 3385, 5436, 3375, 5376, 3454, 5430, - 3363, 5327, 2345, 5283, 2367,32622,30556,30756,31026,32607,30558,30783, -30872,30884, 6085, 1558, 5512, 1532, 5502, 1551, 6098, 1541,16642,32605, -32620,16677,16631,16675,14167,14613,10974,10972, 5387, 3106,12007,12006, -19884,19883,27888,27479,25821,25820,22532,21907,15995,15226,13355,13354, -20992,20991,27887,27478,16175,22682, 3640,22681, 3639,28006, 3745,36150, -14722,16168,31028,14779,14262, 5486, 3092,14788,14271, 5514, 2300,14739, -14218, 5444, 3337, 3130, 5407,14202,14718, 3108, 5389,14190,14695, 3105, - 5386,14188,14693,14733,14211, 5433, 3328, 3090, 5367,14184,14674, 2302, - 5285,14115,14519, 2320, 5325,14137,14582,10976,10978, 2315, 5308,14118, -14556,12287,16679,12187,12185,12167,12213,12211,12145,12210,12220,12171, -12005,19882,25918,25819,19938,12144,13353,20990,25795,12218,12143,11787, -16647,11802,11800,11791,11789,12169,12012,11287,12142,12004,11785,11783, -32625,32624,16645,11772,16644,11535,11333,11771,11770,11769,11768,37781, -39432,42704,17745,19044,28513,30325,30629,32526,33196,35580,33861,33845, -31191,31174,35858,38269,11123,14378, 9612,10668,33200,35471,29073,29078, -36461,36466,35854,38050,28508,30067,30634,32209,19344,21619,17744,37488, -28512,29885,30628,32037,33195,35064,33860,33844,31190,37929,35857,37722, -11122,29816, 9611,31846,33199,34888,29072,34947,36460,36465,35853,38020, -28507,29935,30633,31908,19343,34770,42124,18618,28511,29884,30627,39579, -33194,35063,33859,39542,31189,31173,41965,37721,26764,13467,24372,10194, -39541,34887,29071,29077,36459,41964,35852,38019,28506,42123,30632,31907, -39578,21065,35579,33450,33204,33209,10667, 9684,21618,19515,32208,30827, -35470,33443,30642,30638,32525,30834,30066,28710,28516,28521,38268,36059, -30324,28721,19043,17834,14377,11391,35867,35863,38049,36048,35019,33449, -33203,33208,31845, 9683,34769,19514,31883,30826,34831,33442,37928,30637, -31978,30833,29910,28709,34946,28520,37607,36058,29852,28720,37487,17833, -29815,11390,35866,35862,37969,36047,35018,33448,39540,33207,10162,24371, -21045,39577,31882,30825,34830,39539,30641,30636,39576,30832,42122,28708, -28515,28519,37606,41963,29851,28719,18603,42121,13429,26763,41962,35861, -37968,36046,18009,35174,33220,33214,31080,10542,33735,21858, 9872,32383, -19996,35352,36326,30647,19350,32119,17751,30422,33746,28526,18003,38449, -12303,30287,36336,18945,28983,15177,35873,35878,19987,38640,18008,35578, -33219,33213,31079,10666,33734,21857, 9871,32382,19995,35469,36325,30646, -19349,32524,17750,30421,33745,28525,18002,38448,12302,30323,36335,19042, -28982,15176,35872,35877,19986,38639,18007,35173,33218,39538,31078,10541, -39575,21856,24379,32381,39537,35351,36324,30645,19348,39574,17749,42120, -33744,28524,41961,38447,26910,30286,42119,18944,28981,15175,35871,41960, -19985,38638,18006,35172,33217,33212,31077,31844,33733,34768, 9870,32380, -19994,35350,36323,37927,19347,32118,17748,30420,33743,34945,18001,38446, -12301,30285,36334,37486,28980,29814,35870,35876,19984,38637,35881,43188, -19019,43115,19000,43043,18937,42904,19125,40860,41464,40864,41531,40856, -41497,27449,27858,26485,26484,18893,35399,18905,18871,36637, 8640,43490, - 8638, 8636, 8632,43488, 8630,27913, 6309,27643, 6199,27650, 6201,27648, -27317,15071,21781,27319,36291,30114,30113,18035,18034,18843,27630, 6194, -27198,26411,27628,27627,27626,17953,18752,18873,18877, 6850,14325,14323, -13562,27200,27195,26544,26498,35410,18842,18840, 7945, 4605,36290,29959, -29958,18839,26754,26753,18838,30779,28661,28542,28311,32951,38593,37485, -26198,38808,32719,26208,26206,26210,28413,12590,18544,11602,18501,10103, -18493,11601,18500, 7875, 7873,27185,26532,26483,27409,27411,26491,27792, -26530,26719,26489,26712,12815,27808,26482,27790,27795,27794,26070,27380, -30341,10472,28732,29134,29567,29569,30349,30351,29019,29021,27745,26481, -26480,25346,25339,25355,38807,32718,26068,26073,25349,25351,25348, 2714, -26479,25856,26478,25855,26477,25854,26067,26078,32125,19191,26065,26076, -26476,26475,26072,26080,26131,26136,32145,10040,37484,37483, 4063, 5977, -22224,15675,18722,38647,38592,36537,38591,26410,26474,26473,26416,26683, -27293,27228,26245,26662,35635,28328,28327,43141, 8634, 3698, 3417,43138, - 8621, 3713, 3441, 4213, 6544, 4218, 6524,40309,21826,15119,24933,20136, -12548,31819,24935,29131,37427,37426,37408,38126,37407,24931,24929,17280, -35772,17341,35771, 8954, 8953, 8972, 8971,32782,38780,32780, 9335,38778, - 9333,35811,32911,35810,32910,35809,32909, 9436, 9435, 9450, 9449, 8407, - 8256,38629, 8415, 8264, 8255, 8406, 8263, 8414,35185,30123,35217,30156, -35214,30153,35789,40137,14174,32950,32949,32948,32953,35923,39167,35925, -38697,30195,42782,38646,27407,27788,27787, 8189,35791,12362,12359,11671, -11668, 8208,38343, 8206,38341, 8147,38291, 8145,38289, 8143,38287,10851, -27142,10850,27121,10849,27044, 6334, 1523,11177,11175,15347,23665,25199, -23667,25201,41325,41317,41322,41314,12358,23576,40851,37545,38125,37544, -37543,37541,41764,40304,28309,28308,28307,43105,18991,28306,28304,28884, -35642,42567,41159, 9349,33613, 2854,28895, 2849,33611, 2852,28893, 2847, -13527,26472,11550,36307, 9348,13526,18492,33879,41480,33867,41510,41496, -41445,41530,41535,43810,43282,43307,37913,41501,41463,13758,43028,41495, -43007,41529,12582,18534,26682,12589,18543,33877,41478,33870,41514, 4208, - 6553, 4263,22580,16060,11642,19693, 6603,11623,25597, 7060,19674,25585, - 5684, 2676, 3005, 3140, 4055, 5988, 4207, 6550,20547, 5987,19189,20546, - 9831,13525,20545, 9723,40302,40300,40298,38633,31123,25354,25357,40313, -40315,40312,40311,19187, 2935, 2932, 2975, 2972, 2931, 2389, 2392, 2388, -38391,12812,38367,38390,38360,10845,23489, 9521,23488,23541,23486,10861, -35182,30120,10858,12326,35220,30158,12323, 3320, 3318, 3083, 2317,41305, -27826,27824,27810,30339,28303,30476,21529,28302,30475,21527,28301,30474, -35418,30472,24979,41370,28299,40542,28298,40374,28297,41301,28504,41303, -28296,40378,28295,40389, 9517,22223, 9515,22222,28294,30471,15673,28293, -30470,26087,23485,26085,23484,26089,23634,26143,23482,28291,30468,35840, -25163,24068,33717,30467,33713,31149,36306,36274,36305,33668,36280,36279, -33666,41175,33726,30753, 8805, 9754,35271,35600,11567,11566, 8646,35602, -11561, 8644,40541,43812,40373,43309,40377,40376,43284,40388, 5853,40387, -35409,30466, 8193,35407,30465, 8192,35381,30464, 8184,35379,30463,35570, -30461,43352,28290,30460,27624,28289,30459,28287,30457,39372,30625,39369, -30622,38899,31715,39351,30456,39349,30978,39353,31089,29622,31709,38885, -31720,38884,30455, 8191,38882,30961,39786,30454,31739,35838,35795, 9519, -24942,24946,10856,10860,36345,36353,36344,36355,36343,36351,27406,35181, -30119,35281,30226, 8360, 8356, 8330, 8358,39348,32112,36349,36348,36347, -35184,30122,28764,41298,25054,40688,35240,30453, 8794,35249,30966,28852, -35594,28858,28857,35592,35385,30452, 4903,35397,30969,11554,35412,30451, -24989,41350,37156,36374,38124,38073,32589,11073,42118,18242,16618,38061, -11079,42117,17959,36254,33491,33503,36103,33681,30912,17872,30766,19973, -36261,19585,31039,28755,35991,36093,33703,33698,37155,38123,36373,18241, -37154, 9818,20884,14498,26409,27227,26106,41758,37129,18218,12026,42159, -18240,12035,42116,35785,38881,32098,33691,33693,33689,22218,12043,13218, -10294,10292,12028,30542,30450,30538,30449,31151,30448,31161,30447,31163, -31165,10883,22217, 5329,42155,42974, 8736,42153, 4951,41300,31460,30446, -31458,30544,31450,30445,30548,30444,30546,30443,30850,30442,31129,30441, -31171,30440,31177,31167,35657,35781, 5119, 5121,43484,18837,42822,32959, -28339,32957,28337,10890,10889,35180,30118,10888,35116,30009,32955,28335, -32956,28336,10886,32142,30439,32107,30438,33826,29060,33828,29062,30848, -31159,32105,31158,18239,12112,42115,40294,22797,16335,11611,19666,23481, -11704,19724,23480,11710,19727,23478,11634,19685,23477,11722,19733,23476, -40292,21574,14298,14322,21593,40290,11726,19737,23475,11202,19384,23474, -11677,19713,23473,11674,11673,19710,23534,11205,19387,23472,11208,19390, -23471,11353,19502,23470,11011,19312,23469,11649,19700,23468,12449,20095, -23467,11007,19309,23466,11630,19681,23465,12445,20092,23464,16116,10909, -19216, 6507,10843,19185, 7796, 5508, 1553, 6102, 1544,11201,19383, 7799, -10841,19183, 6769,10917,10916,19222, 6757, 1919, 5507, 5506, 2337,11200, -19382, 7798, 3099, 5379, 5378, 3456,11204,19386, 7743, 3078, 5354,14173, -14650,11010,19311, 6602,10930,19231, 7795,10927,10929,19230, 7724,10926, -19228, 7741, 5302, 2336,11207,19389, 7616,10838,19181,41258,11641,19692, -41257,10836,19179,41256,16649,22930,25272,11033,19314,25535,11323,19482, -25545,11004,19307,25874,11315,19476,25895,12442,20090,25866,11468,19595, -25469,11456,19577,25457,32610,32609,16651,22932,25274,30785,30886,11537, -11335,11325,19484,25547,25471,19597,11470,16682,12289,16681,25058,22939, -16691,12141,11331,16598,30781,11329,11767,11766,11320,19480,25541,12003, -12140,11319,19479,41255,17819,18627,28695,29901,30805,31851,33397,34784, -34199,34372,31609,31413,36013,37935,11341,13776, 9661,10272,33417,34953, -29546,29343,36783,36939,36029,37525,28681,29821,30797,31919,19488,21087, -17818,18651,28694,29922,30804,31892,33396,34847,34198,34371,31608,31412, -36012,37979,11340,13854, 9660,10330,33416,35031,29545,29342,36782,36938, -36028,37619,28680,29861,30796,32001,19487,21199,35953,18354,28693,29561, -30803,31431,33395,34354,34197,34370,35934,31411,36011,36765,28634,12748, -30745,10011,33415,34214,33340,29341,36781,36937,36027,36957,28679,29325, -30795,31599,33320,20434,35951,18353,28692,29560,30802,31430,33394,34353, -34196,34369,35932,31410,36010,36764,28632,12747,30743,10010,33414,34213, -33338,29340,36780,36936,36026,36956,28678,29324,30794,31598,33318,20433, -18163,34524,18170,34539,38973,41703,29442,14761,14765,14758,14451,13068, -10317,20704,13105,42224,24299,30412,43809,43281,43306,38235,27349, 7889, -14291,14320,14307,14275,27292,32314,26432, 8142,38286, 8205,38340,32311, -26426,27542, 7973,24301,30414,29621,31708,38245, 2898,34620, 3233,38243, - 2890,34618, 3225,38241, 2909,34616, 3245, 2476, 2353,29613,31699,38239, - 2333,34614, 2311,38232, 2959,32947, 2997,38230, 2957,33238, 2995,32946, - 2920, 3256,38218,33236, 2918, 3254,38216,32945, 2913, 3249,38211,33141, - 2911, 3247,38209, 3284, 3458,28841,30957,38225, 2952,33595, 2990,32944, - 2906, 3242,38205,33111, 2889, 3224,38171,26471,33619, 2904, 3240,38203, -33617, 2902, 3238,38201,33615, 2900, 3236,38199, 9347,33603, 2896, 3231, -38189,33601, 2888, 3223,38170,33599, 2908, 3244,38207,40288, 5473,19177, - 6077,19175, 6083,40286, 5510,20671,42202,28668,40774,28870,35518,28876, -28875,35516, 3026, 2497,12321,35396,30968,43080, 8776,42253, 4974, 9563, -35780, 9562,35779, 9561,35778, 9560,35777,35621,35776,43187,43525,33087, -28410, 8381,40344, 6063,40349, 5471, 8656, 8665,35769,35619,43193,43529, -24924,24922,19170, 6052,40280, 5460,19169, 6094,40279, 5498,40284, 6048, -40278, 5456,35768, 9554,35767, 9553,42816,42903,33083,28406, 8214, 8219, -42821,42908,35276,30221,10834,40283, 5465,19173, 6057,40282, 5484,19172, - 6072, 4604,35480, 8688,38151, 7004,35486, 8696,38161, 7021,35484, 8694, -38154, 7019,11715,11706,15672,11667,11713,11702,15669,11664,11699,11717, -11708, 5397, 3116,14777,14260, 5481, 3113, 5447, 3389,14741,14220, 5446, - 3339, 5412, 3500, 3132, 5411,14204,14721, 7329,21927,15249, 5494, 2352, - 5372, 3448, 3101, 5382,14186,14691, 2327, 5344,14162,14608, 3077, 5353, -14172,14646,11648,19699, 6601,35482, 8692,38166, 7017, 5392, 3473, 3110, - 5391,14192,14699,23463,43692,43694,24920,38951,22867,16482,33249,28118, -16479,28586,28115,22864,30710,35901,40584,16114,11661,23661,38948,22861, -16476,43690,33246,28112,16473,43689,28583,28109,22858,30707,35898,40581, -25195,23462,43789,43767,24919,23461,43688,43686,24918,16464,28568,30692, -28588,33251,30712,24853,35903,24812,28590,33253,30714,24855,35905,24814, -28576,30700,28575,30699,28574,30698,28594,30718,28593,30717,28592,30716, -23460,26117,23459,26125,25062,24917,25064,24916,23615,26119,23618,26127, -24915,25159,24914,25161,23458,25068,23457,25070,25378,24913,25384,24912, -23580,24911,23578,24910,25380,25086,25386,25084,23456,23455,43698,43696, -43702,43700,24909,24908,23454,28127,23453,28131,28125,24907,28129,24906, -23452,25073,23451,25076,27214,24905,27040,24904,23584,24903,23582,24902, -27216,25090,27042,25088, 9897,23617,27212,23825,27038,23807,25508,25507, -25485,25484,38076,32635,24060,43752,24059,43747,43751,25989,43746,25988, -16663,38064,23708,23707,28163,28162,28160,28159,25277,25276,33688,11488, -11501,33695,11465,19593,41254,23833,23813,24901,25514,24900,25491,25516, -25493,23824,23806,25376,25506,25382,25483,25505,25482,23840,23819,25258, -25524,25255,25501,25521,25498,16662,40650,40648,12139,16661,17475,16660, -17494,16708,32634,16655,11765,16654,16668,16665,17463,25268,22928,16640, -16658,12002,16657,41253,22927,16639,27274,27104, 8615, 2949, 8724, 2967, -24899,24898, 5711, 3168,27087,27257,39591,39593,39778,39780,24897,24896, -25305,41442,41415,24895,24981,41405,41436,24894,40670,21283,13733,25304, -20144,12556,40669,23178,17049,25303,23330,17279,40668,22082,15459,25302, -21736,14943,40667,22103,15510,25301,21714,14841,31816,38978,12457,20101, -23723,12456,20100,23722,12455,20099,25853,25930,41147,41165,24893,25153, -25151,41527,41493,41518,41484,24892,24891,24985,24983,41512,41476,41523, -41489,24890,24889,29127,37418,38081,38944,38942,25926,25928,41143,41145, -41161,41163,24888,24887,25157,24316,25155,24308,26445,24886,26435,24885, -31153,30573, 8606,27241, 8708,27067,24884,11397,24883,19535, 5633,40721, - 8611,27268, 8716,27098,24882,13815,24881,21327,27278,27119,15862, 8485, -22401, 8532,24880,24879,27266,27096,13813, 5014,21325, 5150,24878,24877, -24305,25080,24314,25078,24876,26430,24875,26443,38381,12808,38372, 9614, -33240,28553,30852,30588,23810,25510,23829,25487,24874,25489,24873,25512, -28730,32109,30590, 8604,27239, 8706,27065,25072,11400,25075,19538,23818, -25523,23839,25500,25257,25497,25254,25520,25114,41379,26145,23677,25211, -24077,36418,36416,36452,21509,20039,35274,30219,12320,35212,30151,33801, -29031,33802,29032,12319,12317,12316,12325,33814,29038,29030,31148,29029, -31147,33804,29034,31169,31146,33818,29042,23805,25504,23823,25481,26115, -25480,26123,25503,25094,40694,30575,35818,25066,41355,14455,13070,10319, -20706,13107,42226,34316,10000,34335,34160,17805,17791,20405,11306,35931, -35950,34178,28631,31377,31577,31392,20421,29288,18326,29307,29527,36724, -30742,33337,33317,18336, 9654,19444,19455,36899,36743,36918,12737,34315, - 9999,34334,34159,17804,17790,20404,11305,35930,35949,34177,28630,31376, -31576,31391,20420,29287,18325,29306,29526,36723,30741,33336,33316,18335, - 9653,19443,19454,36898,36742,36917,12736,34314, 9998,34333,34158,34388, -36806,31455,29578,35929,35948,34387,28629,31375,31575,31644,20419,29577, -18324,29305,29525,36980,30740,33335,33315,29358,31643,36979,34229,36897, -36741,36916,12735,34530,23691,34519,23690,34518,23689,37417,37349,37500, -37481,37567,37337,37555,33628,33624,33374,33373, 9760, 9764,19763,19759, -31002,30998,33638,33642,30765,30764,30983,30987,28913,28909,28652,28651, -36225,36221,28904,28900,17915,17911,11887,11883,35990,35989,36188,36184, -34783,33502,33372,33371,10271, 9735,21086,19584,31918,30877,34952,33490, -30763,30762,31850,30911,29820,28754,28650,28649,37934,36102,29900,28792, -18626,17871,13775,11515,35988,35987,37524,36092,34846,33501,33370,33369, -10329, 9734,21198,19583,32000,30876,35030,33489,30761,30760,31891,30910, -29860,28753,28648,28647,37978,36101,29921,28791,18650,17870,13853,11514, -35986,35985,37618,36091,33500,33499,38464,38679, 9733, 9732,19582,19581, -30875,30874,33488,33487,30759,30758,30909,30908,28752,28751,32408,32159, -36100,36099,28790,28789,17869,17868,11513,11512,35984,35983,36090,36089, -20673,42204,28671,40777,43082, 8778,35236,31145,42255, 4976,12467,15666, -12584,18536,15665,18529,11600,18499,43684,43683,43682,43681,41521,41506, -41487,41472,28106,28105,41520,41486,41505,41471,28104,28103,12588,18542, -35566,30397,17734,29615,31701,29620,31707,11594,11580,11593,11592,13438, -40317,40319, 2675,11660,19708,41252, 6693,40409,12569,20157,40408,40672, -12563,20151,40276,40403,40406,12618,42353,20165,42669,40402,40405,40550, -40548,12621,42356,20168,42672,40274,40272,40554,40552,35279,30224,34631, -29684,40270,43213,40268,43541,40400,40397,24303,34628,29681,40399,43210, -40396,43538,32283,11690, 3331,32281,11697,11696,11695,11694,19722, 2733, -11692,19720, 2731, 6695, 6692,34708,29761,20865,13242,11180,11183,11179, -11182, 2831,15192,39417,31625,18280,19041,29473,30322,31309,32523,34248, -35577,34246,34106,31307,31515,36671,38267,12696,14376, 9964,10665,34104, -35468,29216,29471,36826,36669,36824,38048,29214,30065,31513,32207,20360, -21617,18318,37584,29511,29813,31361,31913,34295,34944,34300,34148,31356, -37965,36713,37480,12727,29846, 9992,31873,34152,34767,29271,34991,36876, -36717,36881,37926,29266,29895,31557,31843,20395,34820,42168,18576,29518, -29812,31369,39620,34308,34943,34307,39550,31368,31564,42011,37479,26800, -13352,24374,10138,39549,34766,29279,29517,36889,42010,36888,37925,29278, -42167,31563,31842,39619,20989,18315,18575,34990,34819,31355,31912,34299, -34942,34294,34151,31360,31556,36716,37478,21142,21022,18640,18594,34147, -34765,29265,29510,36880,36712,36875,37924,29270,29894,37964,37583,20398, -20988,39536,10155,34989,34818,31354,41959,34298,26909,34293,42114,31359, -31555,39573,31872,24378,21021,26908,18593,42113,29845,29264,29509,36879, -39572,36874,24377,29269,39535,37963,37582,41958,13391,39547,10137,34941, -34764,31365,42007,34304,26936,34303,42164,31364,31560,39617,31841,24384, -20987,26935,18574,42163,29811,29275,29514,36885,39616,36884,24383,29274, -39546,37923,37477,42006,13351,38766,32717,41738,39446,26352,38806,41818, -39493,26389,32819,38805,32818,38804,32817,41744,39452,26362,38765,41826, -39501,26397,32716,38764,32715,41740,41820,23329,39495,17278,39448,26391, -26354,23177,24271,17048,24282,41746,41828,23176,39503,17047,39454,26399, -26364,23328,24276,17277,24285,24278,26367,18312,19039,29506,30320,31351, -32521,34285,35575,34290,34140,31346,31552,36705,38265,12724,14374, 9989, -10663,34144,35466,29261,29502,36866,36709,36871,38046,29256,30063,31548, -32205,20392,21615,18311,37476,29505,29843,31350,31955,34284,34987,34289, -34139,31345,37922,36704,37580,12723,29810, 9988,31840,34143,34816,29260, -34940,36865,36708,36870,37961,29255,29907,31547,31870,20391,34763,42112, -18591,29504,29842,31349,39571,34283,34986,34288,39534,31344,31551,41957, -37579,26762,13389,24370,10153,39533,34815,29259,29501,36864,41956,36869, -37960,29254,42111,31546,31869,39570,21019,18310,18590,34939,34762,31348, -31954,34282,34985,34287,34138,31343,31550,36703,37578,21080,20986,18621, -18573,34142,34814,29258,29500,36863,36707,36868,37959,29253,29906,37921, -37475,20390,21018,39491,41816,18351,18625,29558,29899,31428,31849,34351, -34782,34367,34194,31408,31606,36762,37933,12745,13774,10008,10270,34211, -34951,29338,29543,36934,36778,36954,37523,29322,29819,31596,31917,20431, -21085,18350,18649,29557,29920,31427,31890,34350,34845,34366,34193,31407, -31605,36761,37977,12744,13852,10007,10328,34210,35029,29337,29542,36933, -36777,36953,37617,29321,29859,31595,31999,20430,21197,39509,41834,39497, -41822,39416,39422,36636,26312,40618,12761, 9997,34313,34157,34332,17789, -17803,11304,20403,35947,35928,28628,34176,31574,31374,20418,31390,18323, -29286,29524,29304,30739,36722,33314,33334, 9652,18334,19453,19442,36740, -36896,12734,36915, 9996,34312,34156,34331,17788,17802,11303,20402,35946, -35927,28627,34175,31573,31373,20417,31389,18322,29285,29523,29303,30738, -36721,33313,33333, 9651,18333,19452,19441,36739,36895,12733,36914,26314, -40623,12765,40108,39363,34244,18711,34242,34102, 9962,32204,20358,35465, -31511,10662,34100,21614,31305,38045,31303,20356,29212,18278,29210,35574, -36667,19038,29469,14373,18276,38264,12694,30319,36822,36665,36820,22228, -34292,18709,34297,34146, 9991,32202,20394,35463,31554,10660,34150,21612, -31353,38043,31358,20397,29263,18314,29268,35572,36711,19036,29508,14371, -18317,38262,12726,30317,36873,36715,36878,22226,26350,24269,27187,27023, -34349,33623,34365,34192,10006, 9763,20429,19758,31594,30997,34209,33641, -31406,31604,31426,30986,29320,28908,29336,29541,36760,36220,29556,28899, -18349,17910,12743,11882,36932,36776,36952,36183,34348,33627,34364,34191, -10005, 9759,20428,19762,31593,31001,34208,33637,31405,31603,31425,30982, -29319,28912,29335,29540,36759,36224,29555,28903,18348,17914,12742,11886, -36931,36775,36951,36187,34330,18612,34311,34174, 9995,31998,20416,35028, -31572,10327,34155,21196,31388,37616,31372,20401,29302,18332,29284,34844, -36738,18648,29522,13851,18321,37976,12732,29919,36913,36720,36894,21052, -34329,18579,34310,34173, 9994,31916,20415,34950,31571,10269,34154,21084, -31387,37522,31371,20400,29301,18331,29283,34781,36737,18624,29521,13773, -18320,37932,12731,29898,36912,36719,36893,20995,39415,36635,36645,36634, -18150,32346,18876,18918,24312,24295,43680,43679,43678,43677,26441,26422, -24311,28102,24294,28101,28100,26440,28099,26421,29619,31706,35564,30395, -24748,12785,38909,17715,34572,32943,34565,32942,33109,32941,33107,32940, -33462,32939,33464,33255,33791,32938,33839,32937,26996,33854,42329,33231, - 4860,26990, 4869,42075, 4812,31180, 4889,42318,30662,30658,42070,31184, -42110,29066,28535,28538, 4851,41955, 4868,29084, 4811,42109, 4886,26761, -41954,35888,26760,36447,33841,33229, 6909, 6154,33836,33460,36639,34574, -33128,35369,32936,35343,32935,35345,33257, 4929, 4853, 4801, 8174, 8594, -26661,35341,33835,20883, 4403,27646,33832,36456,29081,34567,33172,36633, -33793,33174,35371,33176,20032, 6170,31135, 7934,31122,21877,36400,15196, -38669,38458,32136,32394,36405, 8854,12314, 8759,21876, 7933,32393,31121, -38668,12313,36399,36404,32135, 8758,15195, 8853,38457,31134,20031, 7031, -27226,35360,33777, 6907, 6152,27545, 7976,27376, 7910,25374, 5783,40720, - 5590,40719,27247, 8608,27078, 8710,11395,25577,19533,25579,25372,34570, -33459,36372,38122,40107,18793,26105,38657, 5299, 6951, 5277, 6942, 5207, -35783,36420,35787,36422,35213,30152,35211,30150,35122,30023, 8388, 8378, - 8328,24307, 8365,36415,36414,35216,30155,26359,24273, 8422, 8428, 5279, - 6944, 5209,32415,39946, 7623, 5315,32412,39943, 7620, 5312,18875,32509, -16150, 2984,35426,30960,32517,16139,30869,11425,25477,25461,30880,11462, -30866,11422,39427,30599,35836,36440,36444,10217,34885,14438,42333,10393, -20892,14503,42335,10413,20894,10266,34883,20882, 5976,26660, 7452,40393, -22765,40392,42558,17686,24994,24996,38675,37474,26104,38673,37292,41297, -41296, 5257,41295,42384,35378,31144, 7315,41309,22694,41308,42557,18046, -26133,26138,42926,17689,25000,24998,26707,26706,11659,19707,23731,16164, -22675, 3628,22673, 3626,27999, 3736,16172,22678, 3635,22677, 3634,28001, - 3741,36160,14714,11656,36158,14704,11128,11130,11151,11166,11150,11165, -18238,11137,11136,11156,11171,11139,11158,11173,43676,43675,40426,40422, -23861,43674,43673,25549,11054,28809,30936,11052,11058,24334,28821,28828, -30949,37997,11056,37655,19527,24456,19529,24467,17847,28737,30847,28736, -30846,17852,24463,38607,24789,38434,22436,24452,22433,24449,18761,32104, -30104,18766, 9511,24629,23450,22216,19145,21808, 9502,24823, 9509,24627, - 9506,24624,23447,22213,10827,22210,19142,10825,27623,21805, 9499,24821, -12241,24413,11978,11977,24351,37674,12240,38014,12239,24346,11976,11975, -24408,38009,12238,37669,36177,23963,36172,23958,34838,10321,34735,29788, -34724,29777,29106,29096,34761,10289,12275,18486,39272,17971,34802,10265, -12256,24403,12237,12236,24341,37664,12254,38004,12252,24339,12235,12234, -24401,38002,12250,37662,36165,23951,36167,23953,34650,29703,34652,29705, -25917,25916,25915,25914,25913,25912,12270,24399,12269,12268,24337,37660, -12267,38000,36163,23949,34648,29701,39271,39270,39269,39268,39614, 9840, -39611, 9837,39311,39313,15815,18446,15664,18407,25958,25957,39326,39325, -15938,18403,11852,24415,11851,11850,24353,37676,11849,38016,11848,24410, -11847,11846,24348,37671,11845,38011,36179,23965,36174,23960,23948,36162, -34737,29790,34726,29779,23955,36169,25637,25636,25635,25634,39114,39113, -39112,39111,39110,39109,25665,25663,12587,18541,11879,18498,14047,18440, -25702,25701,39166,39165,14090,18402,39108,17936,11844,24405,11843,11842, -24343,37666,11841,38006,34806,10216,34670,29723,34760,10233,11867,24398, -11866,11865,24336,37659,11864,37999,34647,29700,10477, 2940,32467,16149, -32466,16148,22209,30149,27815,22206,30146,27818,21516,30358,29052,42781, - 5262,29055, 5650,32406,39962, 7642, 5292,32403,39959, 7639, 5289,30355, -31454,31143,27276,27113,15961, 8496,22495, 8542,26122,26114, 9817, 9816, -40359,40358,40357,38632,36068,38628,36066,25364, 5587,25362, 5585,27744, -35164,27741,32167,30182,43039, 8749,28286,30437,28285,30436,28557,30676, -23626,25167,28284,30435,15392,38911,22203,15663,28480,30608,28283,30434, -13472,38888,38891, 9556, 9558,32073,17462,28408,30540,28282,30433,28281, -30432,28546,30667,23599,25139,28280,30431,32743,17461,17460,16952,32742, -32889,17532,32841,17492,32823,28445,30560,26002,23327,17046,17276,23175, -41237,32840,32328,32320,26000,23174,17275,17045,23326,41235,16461,22851, -41251,16456,22848,41249,14757,14744,14494,14440,28961,31061,24084,26022, - 9874, 9881,41268,41241,15171,24103,26041,24102,26040,24101,26039,24100, -26038,24099,26037,41261,24098,26036,24096,26034,24095,26033,24094,26032, -28970,31070,24093,26031,17457,14547, 9868, 9879, 9866, 9877,28967,31067, -24111,26049,15173,41263,24108,26046,39341,22202,15662,28964,31064,24106, -26044,28960,31060,24082,26020, 9865, 9876,32852,17456,17548,32851,17455, -32816,32785,32916,17531,17044, 9586, 9584,32333,32325, 9591, 9589, 9595, - 9593,28279,30430,12843,38913,22201,15661,28482,30610,40679,23173,17043, -25319,23325,17274,40677,23324,17273,25317,23172,17042,32839,32327,32319, -13094,11464,19592,25465,14477,13090,14461,13088,11377,11369,28713,30829, -23737,25323,13425,39016,38994,39015,38993,39014,38992,39013,38991,39012, -38990, 9676, 9671,17454,28706,30823,28704,30821,11381,11373,13427,25313, -22200,15660,11379,11371,11376,11368,28703,30820,28278,30429,36332,17990, -14546,14542,14497,14496,22199,15659,17992,36342,13093,13092,22198,15658, -36055, 2866, 2829, 3638, 3744, 3499, 3633, 3740, 3484,11658, 3631, 3738, - 3477,11670,11655, 5719, 3176, 5341, 4133, 4211, 6542, 5449, 3341, 6652, - 3662, 3115, 5396,14196,14706, 3112, 5394,14194,14701,42953, 8732,11657, -19706, 7754, 3118, 5400, 5399, 3481,11676,19712, 7757,11654,19704, 7752, - 5403, 3483, 3120, 5402,14198,14713,27282,27129,15657, 8469,22197, 8525, -25605,25607, 5438, 3330, 5347, 2330, 4205, 6539, 4204, 6536, 4216, 6535, -18237,30015, 5335,42108, 5656,42107, 5334, 4130, 4202, 6534, 9809, 9807, -12024,12022,26008,26705,31206,13483,12498,43672,43671,41432,41401,28098, -41431,41400,28097,12417,12474,37392,41411,10446,37390,41407,43005,41462, -12490,13482,12473,13478,12472, 4325,13891,13909,41113,11025,11027,11024, -41934,41909,41932,41907,41930,41905,43557,43224,41928,41903,25633,26470, -39107,22052,15418,25818,26704,10264,10263,10262,10261, 9791, 9790, 2808, -12838,12830, 2417, 2470, 2512,26469,25852,26468,26467,26466,26465,12840, -41950,41925,41947,41922,41942,41917,41939,41914,15417,22051, 7469,12848, -12847,12835,26703,26702,26701,26700,26699,25611,31367,29516,42166, 4823, -42009, 4867,26799, 4810, 4873,34306,36887,42106,26907,41953,31562,29277, -34302,26934,42162, 4821,42005, 4866,31559, 4809, 4871,31363,29273,42105, -29513,41952,26759,36883,13383,12952,13474,12951,13042,12950,13020,12949, -14487,15161,13350,13349,20985,20984,27892,27483,13348,20983,25782,13347, -20982,25206,12948,12947,20544, 4262,12946,12945,26464,14072,26566,26463, -14046,26580,26462,18439, 4603,14071,13524,14070,18453,18438,17861, 4657, -26461,17863,13626,18471,14057, 4633,13523,14045,22196,21308,39164,39106, -39324,34716,29769,10260,10259,10258,10257,10256,10255,13793,13786,13790, -13783,10254,10253,10252,10251,42104, 9370,42103, 4943,42102, 8891,42101, - 4942,42100, 5521,42099, 4941,42098, 4940,42097, 5861,42096, 5548,42095, - 4939,42094, 4938,42093, 5224,39607, 6179,39604, 6176,39600, 5011,39597, - 5008,32103,30103,11072,11078,12111,13800,13797,39315,12034,12944,13018, -26606,13076,13075,13600,32387,18401,26557,32345,32365,14060,26556,14059, -26555,34072,34074,35363,33779,32386,32385,32344,32363,14015,13566,18400, -18399,32343,32360,41729,41726,14014,13565,32342,31867,18491,10102,13908, -18497,32463,16138,39646,39105,39267,39266,39104, 8395,38401, 6355,41721, - 2806,14942,14940,15509, 2419, 2472, 2515,15507,38567,30014,30070, 6192, -21609,14364,18236,30013, 5520, 4129,14974,15523,13346,13345,13381,13344, -13040,13343,14489,15163,24034,23979,13415,25700,25956,25911,18771,18770, -14056,10057,10087,17950,18452,18437,18457,10079,14044,17955,25910,25632, -25631,30112,25667,14089,14069,15937,24022,15654,15908,17948,18398,18397, -32341,15653,30111,12274,11878,12266,12265,12264,12263,11863,11862,11861, -11860,11840,11839,11838,11837,11836,11835,11834,11833,11974,11973,12233, -12232,11832,11831,11830,11829,12231,12230,11972,11971,12229,12228,12248, -12246,12260,12258,12227,12226,32071,25909,12471,23983,23975,13362,39031, -39034,23974,23973,24018,13370,24017,25987,23323,17041,17272,23171,41218, -41216,23170,17040,25985,23322,17271,16688,16705,41214,41212,41210,43228, -43561,41208,41207,43742,19608,11484,16702,22946,41206,41222,23193,17068, -25991,23345,17302,41220,32632,32631,32629,32628,24058,43750,43745,25983, -24057,43749,43744,25982,16694,16693,16711,11413,41203,43739,19605,11481, -16698,22943,41202,11444,12020,11198,11196, 2533, 5649,11154,11169,19364, -19373,23443,23442,25123,25132,17605,17604, 9495, 9494,11149,11164,19361, -19370,23441,23439,25120,25129,17603,17601, 9493, 9491,11276,19424,25193, -11263,28096,22842,19411,28093,16450,25186,22839,16447,14152,14598,14154, -14600,40573,43670,43669,40565,11273,19421,25190,11260,28090,22836,19408, -28087,16444,25183,22833,16441,40575,40567,11622,11639,19673,19690,23659, -23654,25584,25596,17786,17781, 9645, 9639,40577,40569,11148,11163,19360, -19369,23657,23652,25119,25128,17784,17779, 9643, 9637,11628,11646,19679, -19697,23437,23436,25589,25601,17599,17598, 9489, 9488,25173,21913,15232, -25175,22538,16001,12943,12942,20543,20542,27895,27486,11632,11651,19683, -19702,23644,23642,25591,25603,17769,17767, 9618, 9616,11621,11638,19672, -19689,23435,23433,25583,25595,17597,17595, 9487, 9485,24843,24802,27885, -27476,24840,24799,27882,27473,11280,11267,19428,19415,24847,24806,11243, -11222,11278,11265,19426,19413,24845,24804,11247,11226,11246,11225,11245, -11224, 9633, 9626, 9631, 9624, 9630, 9623, 9629,22193,22192, 9622,11609, -19664, 6702,11613,19668, 6646,11653,10814,19162, 2877,11724,19735, 6704, -11720,19731, 6648,12357,10807,19156, 2750,35666,14645,35664,14654,14724, -11679,19715, 6691,35668,14649,10928,10937,12356,22619, 3566,27955, 3703, -22617, 3564,27953, 3701, 3642, 3747, 3503, 3652, 3754, 3510, 3650, 3752, - 3508,12361,10908,19215, 2747,10907,19214, 2708,10905,19212, 2706,12355, -22624, 3568,27957, 3705, 3648, 3750, 3506,10913,19219, 2711,36153,14644, - 3409, 2351,16161,22670, 3623,22669, 3622,27996, 3733, 3621, 3732, 3472, -36155,14698, 5721, 3178,11637,11620,19688,19671,25594,25582, 6644, 2752, - 7104, 3068, 5757, 3211,22609, 3556,27948, 3691, 3647, 3749, 3505,11625, -19676, 2678,14720,14712,14697,12350,20053, 6708,10920,10912,19224,19218, -24965,24961, 6625, 2710, 7088, 3038, 5725, 3182,14643,11645,11627,19696, -19678,25600,25588, 6598, 2670, 7057, 3002, 5681, 3137,11643,11624,19694, -19675,25598,25586, 6604, 2677, 7061, 3006, 5685, 3141, 6665,11636,11619, -19687,19670,25593,25581, 6597, 2669, 7056, 3001, 5680, 3136, 7420, 8000, - 6079,22010,27569, 1609,15345,28036, 1696,16260,22730, 1661, 5493, 1546, - 6090, 1536,14782,14264, 5488, 3076,11352,19501, 6767,11351,19500, 6759, - 7423, 8002, 6081,22012,27571, 1593,15349,28040, 1694,16262,22732, 1659, -11360,11358, 4196, 6563, 4559, 2510, 5632, 6430, 6983, 5538, 5417, 3315, - 2532, 5648, 6454, 6991, 5552, 7418, 7998, 6076,22006,27567, 1615,15341, -28034, 1703,16258,22728, 1668, 7429, 8005, 6096,22015,27574, 1945,15354, -28043, 2010,16268,22736, 2045,11018, 7431, 8007, 6100,22017,27576, 1943, -15357,28046, 2008,16271,22738, 2043, 7354, 7956, 6008,21954,27522, 3450, -15280,27974, 3718,16127,22646, 3599,11022, 7356, 7958, 6010,21956,27524, - 3452,15282,27977, 3720,16129,22648, 3601, 3219, 5763, 3215, 5759, 3217, - 5761,12345, 7373,21966,15294,12347, 7375, 7969, 6025,21968,27538, 3512, -15296,28009, 3756,16192,22687, 3654, 6020, 3468, 7964, 3728,27533,27992, - 7367, 3617,21962,22665,15290,16157,11605,11607, 6022, 3470, 7966, 3730, -27535,27994, 7369, 3619,21964,22667,15292,16159, 7212, 7880, 5884,21812, -27338, 1956,15096,27654, 2021,15695,22246, 2056,15652, 7176, 7863, 5878, -21771,27307, 1958,15057,27622, 2023,15651,22191, 2058, 5882, 1979, 7878, - 2086,27336,27652, 7210, 2119,21810,22244,15094,15693,15650, 5877, 1981, - 7862, 2088,27306,27621, 7175, 2121,21770,22190,15056,15649, 5903, 1972, - 7898, 2079,27364,27706, 7254, 2112,21835,22345,15128,15791, 5905, 1970, - 7900, 2077,27366,27708, 7256, 2110,21837,22347,15130,15793, 7277, 7914, - 5937,21844,27383, 1947,15150,27748, 2012,15903,22442, 2047, 7279, 7916, - 5939,21846,27385, 1942,15152,27751, 2007,15905,22444, 2042,11579,15682, -15954,15648, 7174, 7861, 5876,21769,27305, 1951,15055,27620, 2016,15647, -22189, 2051, 7225, 7887, 5893,21818,27346, 1941,15107,27681, 2006,15745, -22304, 2041, 5965, 1995, 7927, 2103,27417,27801, 7292, 2136,21871,22489, -15188,15956, 5967, 1997, 7929, 2105,27419,27805, 7295, 2138,21873,22492, -15190,15959,15725,15646, 5875, 1974, 7860, 2081,27304,27619, 7173, 2114, -21768,22188,15054,15645, 5898, 1969, 7893, 2076,27359,27701, 7249, 2109, -21830,22340,15123,15786, 5963, 1993, 7925, 2101,27415,27799, 7290, 2134, -21869,22487,15186,15953, 5975, 2335, 1930, 5492, 3095, 5371, 1929, 5238, - 4396, 6018, 3466, 7962, 3726,27531,27990, 7365, 3615,21960,22663,15288, -16155,15644, 5874, 1989, 7859, 2097,27303,27618, 7172, 2130,21767,22187, -15053,15643, 5896, 1991, 7891, 2099,27357,27699, 7247, 2132,21828,22338, -15121,15784, 5901, 1987, 7896, 2095,27362,27704, 7252, 2128,21833,22343, -15126,15789,40964,40969,11764,11763,12001,12000,19881,19880,27891,27482, -25817,25816,22535,21910,15998,15229,11762,11761,19755,19754,27894,27485, -25630,25629,22537,21912,16000,15231,40905,40903, 9789, 9788,40901,40899, -40897,40896,40966,40971,40909,40907,40895,40894, 6556, 2584,10923,19227, - 7632, 5986, 2350, 6894, 5573, 5343, 2349, 6532, 2574, 6531, 2573,11135, - 5333, 2323, 6530, 2572, 6538, 2576, 6558, 2586, 6548, 2579, 6523, 2567, - 6552, 2581,42955,43330,42965,43372,42963,43370,43386,42977,43388,42979, -43328,42952,27399,27780,18424,10069,27918,27458,27867,27441,27850,27237, -18451,10078,26723,26534,25881,26460,25851,25613,25872,25850,25533,33674, -28935,33476,28743,34646,29699,15642,22186,10387,20541,25975,33672,28932, -25970,25973,25724, 6489, 6488,22185,16713,32639,32637,35179,30117,23822, -35131,30072,15714,22269,15641,22184,15819,22373,15848,22391,12098,15640, -22183,22249,16565,32569,32571, 9719,33478,28745,23832,25719,25969,25718, -34680,29733,14043,18436,14466,14392,25879,25878,39323,17980,39257,17970, -39317,17978,26434,29669,40064,43549,26428,39091,17935,39163,17943,39090, -17934,39625,18600,34033,34028,34031,32368,15883,33670,28930,41658,41677, -41679,39052,40789,10443,20697,10475,20687, 6684, 6686,10479,20540, 6681, - 6680,18396,10056,14100,18395,32340,15639,21550,16438,32542,32541,22717, -16437,32540,32539,15638,22182,35542,14642, 7787, 7786,10643,19009,10642, -24512,19008,24672,12068,19901,24016, 6774, 6773,15637,22181,34007,34006, -41647,41646,27847,27438,26554, 9787, 9786, 9785, 9784,43226,43559,43555, -43222,25849,25610,26004,26007,15109,14390,26698,25609,10775,34837,15977, -15208,22514,21889,27846,27437,15976,15207,27398,27397,21864,21863,22513, -21888,27779,27778,15181,15180,27845,27436,22476,22475,15944,15943,24033, -24032,23978,23977,27844,27435,22564,22563,16041,16040,27843,27434,21895, -21894,15214,15213,27842,27433,22520,22519,15983,15982,15206,21887,15205, -27865,21886,27456,27841,27432,21015,21014,13387,13386,27840,27431,20628, -20627,13030,13029,15204,21885,25773,12104,12103,11744,11743,12094,12096, -10779,34810, 9700,23972,23971,27861,27452,20981,20980,13342,13341,11739, -11738, 7942, 7940,10724,10721,23970,23969,23982,24015,23968,23967,24014, -23981,24013,24025,24027,24012,12070,27864,27455,22512,22511,15975,15974, -27863,27454,20636,20634,13035,13032,24511,24671,19132,19131,10760,10759, -10732,10735,24516,24676,19106,19108,10731,10734,24510,24670,19113,19112, -10741,10740,24509,24669,19062,19061,10684,10683,10781,34759,15212,21893, -25753, 7947,10429,10571,18816,18957,24508,24668,10426,10568,24505,18813, -18954,24665,27870,27461,21901,21898,15220,15217,27873,27464,22526,22523, -15989,15986,10439,10588,18828,18964,24526,24686,10437,10586,24524,18826, -18962,24684,11737,11736,11945,11944,10596,10595,11735,11734, 9849, 9848, -12067,12066,14142,14587, 9783, 9782,12065,12063,19900,19898,25848,25846, -24011,24009,17969,17967, 9847, 9845,27876,27467,20539,20538,12941,12940, -15223,21904,25776,12061,12060,14139,14584,12117,12115,19916,19914,25887, -25885,24044,24042,17976,17974, 9858, 9856,11432,19557,25411,28147,22914, -16602,41080,11934,19847,25742,28084,22830,16436,12222,12284,16672,12217, -12215,41025,43668,11931,19844,25739,28081,22827,16433,11412,41027,11312, -19473,25900,25247,19933,12130,41029,11109,19341,25898,25106,19931,12128, -12154,19940,25920,28156,22923,16635,12183,19958,25945,25943,19956,12181, -12158,19944,25924,25951,19964,12197,11798,19788,25675,25673,19786,11796, -11776,19772,25641,25639,19770,11774,24992,20537,12939,12938,20536,25208, -12059,11760,19753,25628,25627,19752,11759,11818,19804,25696,25688,19797, -11808,11820,19806,25698,25690,19799,11810,40597,40758,40595,40594,11733, -11449,11453,19574,25452,28145,22912,16597,12058,11816,19802,25694,25686, -19795,11806,40639,41075,40637,11758,16629,11108,12193,11999,19879,25908, -25815,19937,12138,12206,12205,12038,11757,19751,25785,25626,19870,11960, -12937,20535,25784,25002,20534,12936,12057,43728,43725,32603,11411,19550, -25402,28149,22917,16605,23999,25793,23996,25790,11938,19851,24003,11913, -11936,19849,24001,11917,11916,11915,12045,12042,13120,15165,12156,19942, -25922,25823,19886,12009,12122,19926,25891,25643,19774,11778,12125,19928, -25893,25625,19750,11756,11815,32602,30882,43667,40537,12120,19924,25889, -25693,19801,11814,11107,12033,12192,19962,25949,28154,22921,16628,12191, -19961,25948,12190,19960,25947,25839,19892,12032,12296,19991,26015,12292, -27396,21862,19981,27777,15179,26011,22474,15942,15399,12056,12846,12547, -17076,15466,12055,15522,39256,39255,39254,39253,39252,39251,39263,39265, -39250,39249,39248,39247,41047,41046,41059,41061,41051,41045,41043,41042, -41041,41040,41039,41038,41037,41036,41035,25752,22562,16039,25751,22518, -15981,25750,21013,13385,25749,20626,13028,13044,20642,25772,11943,12102, -11742,12092,41054,41053,41056,12137,41034,14685,12136,11996,25761,20979, -13340,11732,12162,25907,17091,15471,15526,39246,19972,12273,12354,17039, -15458,15506,25771,22510,15973,24007,19896,12053,12090,24029,19903,12089, -24006,19895,12052,24005,19894,12051,15407,12851,41065,41064,41063,41070, -41068,41049,12119,41032,25779,22529,15992,11924,12041,41078,41073,11731, -11311,19472,25246,28144,22911,16596,12050,25764,20533,12935,12049,12100, -19908,25863,12189,12110,11106,19340,25105,28153,22920,16627,12109,19912, -25883,12262,11859,17316,14861,11730,14973,14817,11729,12834,12408,39101, -39103,39089,39088,39087,39086,39093,39095,39085,39084,39125,39121,39124, -39120,40887,40886,40885,40884,40883,40882,40927,40893,40881,40880,40879, -11755,40878,14710,14683,11754,11753,25624,25623,14807,12832,39083,20489, -12859,39082,20052,12349,39081,21547,14236,39080,39079,43776,43805,39078, -40447,43732,17270,14840,14939,17396,14901,15027,12225,12244,40915,40914, -40913, 9781, 9780,11077,40876,40925,40891,40889,40936,40934,39151,39147, -39150,39146,11813,11812,40932,40930,40938,14394,11970,12224,40944,40943, -40942,11828,11827,40940,11826,40911,40947,39308,39307,39140,39139,11752, -19749,25622,25621,19748,11751,14389,39077,39076, 9722, 9721,12135,19936, -25814,25906,19878,11995,12934,13377,12967,13339,39117,39116,39149,39145, -39154,39153, 9830, 9829,13375,12933,13338,12970,40737,40739,40734,17453, -16185,16111,14676,12161,12134,12133,19935,25905,25813,19877,11994,12179, -11794,11750,11749,16595,11439,11438,19567,25441,15755,17269,15754,15753, -25531,25446,25408,19555,11420,25620,26459,25475,25474,25473,19599,11474, -25445,25444,19570,11442,25406,19553,11418,25399,19547,11408,16959,17482, -13265,13337,15636,39056,22178,15634,28773,30900,39099,39097,39119,39123, -39075,39074, 9703, 9705,17452,28766,30894,28763,30892,28762,30891,12175, -19951,25937,25837,19890,12018,40756,16626,11529,39135,39137,14641,11793, -19784,25671,11748,19747,25619,12932,20532,25424,12048,11528,11522,11747, -19746,25618,11780,19776,25645,12178,19954,25941,11436,19565,25426,11993, -11992,19876,19875,27860,27451,25812,25811,22516,21891,15979,15210,25844, -30888,11476,30863,11415,25810,12017,12016,19889,19888,27839,27430,25836, -25835,22509,21884,15972,15203,25834,25940,19953,25939,19544,25396,25395, -25617,19745,25616,19562,25420,25418,25647,19778,25649,19560,25416,25414, -25670,19783,25669,19543,25394,25393,34715,29768, 1823, 1805,12576,24366, - 1065, 1012,24432,38030,12599,37738,35076,34899,38032,37740,24173,22266, -24434,21419,27315,26681,20922,13278,20920,13276,29112,20926,13281, 1859, - 1842, 1150, 1140, 9932,39742, 9931,39741,24819,39740,34742,29795,13907, -18540, 1482, 1476,12573,24363,12596,37734, 1062, 1009,24428,38026,12611, -42344,12595,37733,35078,34901,38034,37742,24175,22274,24436,21423, 9930, -39739, 9929,39738, 9926,39729, 9925,39728,24831,39727,29130,37421,29129, -37420,29099,29109, 1469,36495,37425,37424,37423,12586,18539,12624,42360, -20171,42676, 1479, 1473,12626,20173,42362, 1481,42678, 1475, 8054, 9922, -39720,29125,37415,38037, 1149, 1139, 1152, 1142,12620,20167,42355, 1145, -42671, 1135,35453,39526,38500,38702,24594,22314,41882,29647,27291,27290, -27617,27314,27289,12795,30387,38366,30408,38358,38363,38365, 2930,38357, - 2387,37255,29642,37254,29641,37253,29640,19022,43201,30416,38370,27663, -37246,36144,37245,38299,40063,31679,40062,31678,31738,31737,31705,35446, -31723,24604,15633,41888,29654, 8044,31735,38376, 2386,35443,31719,35442, -31718,32516,16284,32479,16283,35456,39528,38504,38704,24596,22316,41884, -29649,24601,29658,41890,15385,37241,37244, 1421,40058,31676,40057,31675, -38385,12811,24756,12793,29602,30390,38389,38388,29600,29596,29618,31704, -34636, 1433,29689, 1438,43219,43551,24599,29653,41887,15383,24598,29652, -41886,15382, 1285, 1418, 8050,38379,12806,24754,12791,24750,12787,38378, -38384,12810,38375,38387, 1306, 1294, 1303, 1291,29617,31703,29612,31698, -34634, 1429,29687, 1436,43217,43548,34630, 1300,29683, 1288,43212,43540, -30964, 3798, 3778, 3800, 3780,35425,30959,32462,16137,32461,16136,36652, -34579,34586,36650,34577,34584,34085,29464,31470,29585,31656,31506,29370, -29462,31468,29583,31654,31504,29368,36644,21875, 7932,32392, 5254,31444, -20450,38667,12312,36398,36403,31443,31624,36800, 8757,12755, 8518,15194, - 8852,38456, 8493,31120,31133,36972,36799,36971,12754,32134,20030,31623, - 6169,20449, 7030, 8702, 8337,38763, 9313,41293, 8934,36480, 8701,43062, - 8761,18031, 8593, 8173,38803,36371,36370,36369,18030,18029,18028,27225, -41287,29017,38339, 8204,38308, 8169,34386,32391,34385,34228,31132, 7931, -33774, 8517,31642, 8756,34227, 5253,36397,31641,38666,35366,35201,38455, -33771,29576,36805, 6168,29575, 8492,36402, 8851,29015, 7029,36978,36804, -36977,30301, 8061,41292, 7297,38121,38120,36368,18792,38119,36491,38118, -38117,38116,31119,31118,41283,18027,41285,18033,27911,27641,42858,42857, -26103,35204, 5619,36383, 5616,36380,24771, 7553,40207, 6407,31301,24617, -34240,40205,34238,34098,31299,39906,36663, 7199,39905, 6221,43351, 7551, -34096, 6406,29208,43349,36818,36661,36816,42721,29206,27330,42720, 7197, -27172, 6220,24769, 7550,40204, 6404,31297,24616,34236,40203,34234,34094, -31295,39903,36659, 7196,39901, 6218,43348, 7549,34092, 6402,29204,43347, -36814,36657,36812,42718,29202,27329,42716, 7195,27170, 6216,34504,30404, -34501,30401,18155,41645, 6885, 6148,41642, 7307,41673,41778,22311,41672, -22818,41641,22547,41640,22332,41639,26348,26380,22545,41668,18159,41675, -38227, 2955,34005, 2993, 2916,38213,34004, 3252, 2894,38183,34025, 3229, - 2887,38169,34020, 3222, 2627, 2643,38824, 9409,41720, 9218,36476, 2626, -41719, 2595, 2647, 2634,23169,18235,22102,18234,18217,21766,22081,18233, -37188,18232,18231,18230,18216,21765,21923,18229,18215,36632,14274,35340, -34569,20455, 2653,31640,31453,36976,12760,36803, 2617, 8060, 8540, 8244, -38393, 6849,41718, 6440, 2625,36148, 8149,38297,41717, 3792,18228,18227, - 6920, 6161,18226,18225,18224,18223,21921,18222,18221,41757,26415,41756, -26414,20448, 2591,31622,31442,36970,12753,36798, 2464,18210,26408,26407, -41754,34549,35325,41666, 7314,41665,41776,22693,41664, 6432,42556,18178, -26697,26356,26393,34087,38762, 9312,41711, 8933,36479, 2483,41710, 2455, -38802,37153,37152,37151,18209,18208,21763,18207,29565,21760,37224, 2557, -18220,37221, 2554,36643,20333,36602,39439,31285,36604,39484,24264,40237, -40132,40235,40130,39442,31290,36609,41735,39478,24258,40093,40186,40088, -40181,18143,34398,34435,37029,20279,36994,18145,34400,34437,37031,20281, -36996,39483,24263,39482,24262,39486,24266,40091,40184,40086,40179,40083, -40176,40081,40174,40241,40136,40239,40134,34758,10627,34757,10559,39303, -39305,34812,10557,37291,38086,37290,38094,37289,38080,38614,37288,38662, -37287,38664,37301,38656,37473,38655,30133,20531,10622,20530,10525,18394, -10055,18422,10067,18393,10054,26458,26696,10410,13522,15751,22319,25877, -34645,29698,34644,29697,34660,29713,38660,37435,37440,34753,29806,34751, -29804,34672,29725,34643,29696,34642,29695,34656,29709,34662,29715,34730, -29783,34732,29785,34677,29730,34641,29694,34640,29693,34667,29720,34666, -29719,37327,38096,20808,13191,18392,18391,10053,20807,20851,13231,18390, -18389,10052,20850,20857,13235,18421,18419,10066,20855,18410,10062,18477, -10096,20791,13179,18409,18412,10061,20790,14025,18388,13571,18387,20836, -13215,18414,18417,10064,20835,13521,18416,34836,10553,34691,29744,13625, -18470,13520,18480,39295,39298,12931,20529,20572,10615,12981,20574,12930, -20528,12929,20527,12928,20526,32453,16108,27288,18450,10077, 5631,37822, - 5630,42452,42565,18490,10101,13290,20941,13178,20789,13214,20834,34706, -29759,34699,29752,13177,18474,20788,20787,18476,10095,13213,18479,20833, -20832,18482,10098,13176,18538,13175,18496,32478,16282,32460,16135,13212, -20831,13174,20786,13220,20838,13190,20806,13230,20849,32339,15631,32362, -15847,32337,15629,39186,39188,15802,22360,25843,39259,39261,15628,22173, -25858,39245,39244,12083,12081,10274,39719,40156,40256,40155,40255,24386, -15813,24636,13407,30271,30269, 6595, 6594,34679,29732,14042,18435, 6251, - 6249,13292,20943,34704,29757,34702,29755,34701,29754,13119,13118,18533, -32482,16287,10342,39718,40154,40254,40153,40253,24396,13488,24439,13440, -30194,30193,34714,29767,38659,37400,37405, 8700,30362,30361,30170,30169, -37413,34739,29792,39737,10247,30192,30191,34741,29794,13117,37729,13629, -42340,24441,13487,24438,13490,39736,10215,39748,10210,39731,10209,39726, -10220,39735,10208,39725,10245,39733,10222,39717,10213,20954,10594,10379, -39764,10378,39763,39762,10528,40246,40143,40245,40142,40220,40105,40219, -40104,18564,10135,20952,13301,18563,18571,10134,20960,10373,39756,18559, -10130,20948,13297,18558,18567,10129,20956,10205,34916,34923,37772,13502, -37765,10203,34914,34921,37770,13500,37763,39761,10377,40172,40079,40170, -40077,40152,40252,40151,40251,39766,10523,40161,40261,40160,40260,40233, -40128,40231,40126,34851, 9960,34232,34090,10334, 1864,21204, 1757,32005, - 1601,35035, 1797,31293,31509,31895,20354,29864,18274,29200,29467,37983, - 1814,29926, 1571,18655, 1742,13858, 1881,36810,36655,37623,12692,34934, -34778,34003, 7306,34002,29395,34001,34498,34011,34508,34000,34497,40229, -34492,41761,34931,34775,41968,34018,34514,40243,34516,42397, 1037,41633, - 1031,41632, 1048,42392, 1022,41635, 1050,42394, 1024,41760,41631, 1046, -42390, 1020,41629, 2954,41628, 2992,41627, 2915,41626, 3251,41650, 2892, -41652, 3227,41656, 2886,41654, 3221,34263, 9979,34254,34121, 9970, 936, -20366, 931,31521, 926,34112, 921,31315,31530,31324,20375,29222,18286, -29231,29479,36686, 916,29488, 911,18294, 906,12712, 901,36842,36677, -36833,12703,34381,31639,34224, 2650,34226, 2616,31621, 2599, 2652,36975, -34384,36802,29572,36797,29574,36969, 2482, 6384,37645,37150,37149,39645, -37635,37644,37632,37148,37147,37146,37145,37144,27910, 2624, 8314, 6262, -41716,37187,38260,37297,37347,42609,32086,38078,37639,34016, 7313,34015, -29397,34014,34512,37090, 2481, 2480, 2630, 2637, 2505, 6421,37518,37128, -37399,37127,37495,37126,37469,37124,37468,37513,37142,37123,37511,37462, -37299,37756,37434,37122,37141,37121,37140,39431,36631,37412,37404,37498, -37494,37472,10043,37461,37460,37467,10039,37458,37457,37647,37138,37137, -37120,37510,37517,37520,37174,37505,37439,29444,37119,37136,37135,37172, -37170,37118,37117, 2641, 2632,39414,26406,26405,27640,42564, 2623,37566, -37286,31638,12764,12757,41733, 2622, 2621,37527,37402,37492,10045,37455, -37454,37465,37185,37508,37437,37184,37183,26413,27645,42561,20297, 2612, -20295, 2610,35114, 2608,35112, 2606,12763,37557,39421,18930,22264,27005, -21417,13951,24817,38564,38257,38562,37452,38560,30007,38068,32735,32711, -38761,32710, 9311,38760, 9310,38072,32709,38071,32901,38070,32764,17268, -23321,24825, 9217,24780, 9216,17267,38060,16897,38059,17340,38058,17530, -38066,27635,27312, 7608,38801,32708,27786,32093,30095,22171,15627,38645, -30126,38644,38643, 5247, 5530,32815,38800,32814, 9381,38799, 9380,38075, -32813,27684,30333,18707,35295,27162,27153,35405,22170,39882,38555,24446, -22351,39919,38609,24465,35332,27193,35291,27160,27150,35403,42950, 8731, -42949, 8730,42948, 8729,42947, 8728,35377,32076,40005, 8482,40002, 8479, -35541,14640,35540,14639,14313,27249,27251,17038,23168,24827, 9024,24782, - 9023,17037,38063,27021,16563,38690,23265,21508,37451,38084,32336,32515, -15626,32520,15625,32511,15677,32508,15624,32529,16280,38571, 5200,32335, -15623,35539,14638,14662,14637,35552,14666, 8626, 8629,14668,14708,18932, -22271,27007,21421,13942,24829,30360,42780,35108,30005, 5647,35143,30085, - 5665,22165,18820, 5605, 5604,35347,32111,32506,15929, 6955, 5331,40061, -43546,42762,18769, 6937, 5272, 6936, 5271, 6935, 5270, 6933, 5268, 5629, -22268, 6939, 5274,22180,22164, 6946, 5281,25809,32240,18748, 8323, 8156, - 8316, 8158, 8320, 8153, 5580,35374,32097,35335,32096,35334,32095,32513, -15882,32367,15881,38759, 9309,43061, 8932,36478, 8059,38798,38115,38114, -38113,18791,18790,18789,30347,37642,37515,37450,38130,37755,38112,38111, -27909,27639,37569,38128, 3646,22685,16184, 6338, 1522,12640,12645,15371, - 6342, 1510,12642,12647,15373, 6782, 6781,14798,21699, 6344,14796,21697, - 6341, 7801, 1555, 7440,12375, 7443, 8012, 6107,22026,27582, 1592,15367, -28052, 1693,16277,22744, 1658, 1489, 7435,12373, 7437, 8010, 6105,22021, -27580, 1940,15362,28050, 2005,16275,22742, 2040, 7442,22025,15366, 7439, -22023,15364, 7426, 1562,12340,12333,12338,12331, 5804, 3214,12342,12335, - 6027, 3514, 7971, 3758,27540,28011, 7377, 3656,21970,22689,15298,16194, -15505,12533,15504,14938,16379,14982,16012,12532, 6752, 1497, 6749, 1494, -41395,41428,41393,41426,41397,41430, 7673, 2785,12396, 3807, 8862,12509, -12436,12393, 5370, 3094,12439,12401, 5365, 3088,14737,14216, 5440, 3335, - 3128, 5405,14200,14716, 3087, 5364,14181,14664, 7871,12398, 4411, 4409, -12435,20087, 6593, 3074, 5351,14171,14636,12448,20094, 6591,12546,15118, -21825, 7236,12545,20135, 6451,12407,12544,12406,12388,12506, 3804, 8859, -12522,12505, 7664, 2776, 7671, 2783, 7717, 2884,41403,41434, 6017, 3465, - 7961, 3725,27530,27989, 7364, 3614,21959,22662,15287,16154,15051,21757, - 7169,12568,20156, 6382,14937,21735, 6848,41461,41460,12427,20084, 2755, -31205,31204,16392,12489,12488,12426, 4417,13481, 2225, 7635, 2415,15621, - 7167, 7858, 5873,21755,27302, 2239,15049,27613, 2245,15620,22163, 2261, - 7304, 7938, 5973,21879,27421, 2241,15198,27830, 2247,15967,22504, 2264, - 7251, 7895, 5900,21832,27361, 2237,15125,27703, 2243,15788,22342, 2257, -16032,12416,20081, 7526,31201,12415,12414,15686,15952, 2667,15619, 7166, - 7857, 5872,21754,27301, 1949,15048,27612, 2014,15618,22162, 2049,12423, - 7223, 7885, 5891,21816,27344, 1939,15105,27679, 2004,15743,22302, 2039, -12404, 7351, 7953, 6005,21951,27517, 3446,15276,27968, 3715,16106,22638, - 3587, 2256,21296,12567,13748,20155, 2235, 2255,21295,12566,13747,20154, - 2234,12560,20148, 6450,41459,15243, 3788,41450,15617,41420,41458,12425, -20083, 2209,31821,12497,12496,15117,21824, 7235,12562,20150, 6449, 2227, - 2223,12487,20114, 4245,12485,20112, 4243,12875,20501, 4242,14245,41418, -41456,12559,20147, 2220, 6016, 3464, 7960, 3724,27529,27988, 7363, 3613, -21958,22661,15286,16153,12500,12432, 7405, 7990, 6044,21993,27559, 1591, -15324,28021, 1692,16231,22715, 1657,15316,41467, 2217,12430, 7400, 7988, - 6042,21988,27557, 1938,15318,28019, 2003,16229,22713, 2038, 7404,21992, -15323, 7402,21990,15321, 1457,21287,12552,13738,20140, 1453,41444,15320, -41469, 1463,15615,15612,16030,12413,20080, 1444,12412,20079, 1443,31824, -31818,12565,20153, 2233,12484,32070,12483,12482,13480,13746,21294, 2254, -12481,20111, 4241,12480,20110, 4240,12492,20116, 6512,12479,20109, 6380, - 2268,22161,15610,15609,22160, 2259,15966,22503, 2263,12420,12419,15685, -22239, 2251,12495,12558,20146, 2219,12554,20142, 1460,15103, 2216,41454, -12422,41409,41438,15245, 3790,41453,11020,40855,30973,11578,11577,11591, -11575,11589, 4564,11583,11582, 2666,11586,11585,12828,12826, 5829, 3832, -12874,12870,20498, 3812,12869,20497, 3811, 3831, 5828, 3830, 5827, 3834, - 5831,12877,12879,12873, 7468,22050,15416, 2531, 5823, 3818, 3836, 3843, -12884,20506, 3875, 3905, 5843, 3898, 5839, 3900, 5841,12888, 7474,22057, -15423,12890, 7476, 8024, 6122,22059,27597, 3926,15425,28070, 3966,16337, -22799, 3955, 6117, 1968, 8021, 2075,27594,28066, 7460, 2108,22041,22773, -15405,16310, 7454, 8017, 6112,22034,27590, 1937,15390,28062, 2002,16302, -22767, 2037, 6115, 1983, 8019, 2091,27592,28064, 7456, 2124,22037,22769, -15401,16306, 7450, 8015, 6110,22032,27588, 1954,15388,28060, 2019,16293, -22756, 2054, 6109, 1977, 8014, 2084,27587,28059, 7449, 2117,22031,22755, -15387,16292,12895, 7488, 8031, 6129,22071,27604, 1590,15438,28077, 1691, -16344,22806, 1656, 3810, 3826, 3829,12893, 7483, 8029, 6127,22066,27602, - 1936,15433,28075, 2001,16342,22804, 2036, 7487,22070,15437, 7485,22068, -15435, 5838, 3897, 3886, 3910, 3915, 3877, 3891, 3902, 3874, 3889, 3896, - 3873, 3888, 3895, 3879, 3893, 3904, 6124, 3932, 8026, 3972,27599,28072, - 7479, 3961,22062,22801,15428,16339, 3884, 3908, 3913, 3809, 3825, 3828, -12865,43305,43632,43303,43630,43300,43627,43299,43626,14287,43298,43625, -43296,43623,14936,21734, 6847,22080,14935,22079,19102,22101,19101,14934, -43294,14933,43621,14932,14931,15462,15475,15457,15456,14956,14950, 6852, - 6846, 6845,15485,14333,14993,14992,14981,15007,15006,15005,15022,15014, -15010,15009,15004,15025,14351,15024,15483,15020,14349,15012, 5524, 1639, -14997,14337,14991,14332,14980,14979,14978,14995,14335,14984, 5519, 1906, -14339,15000,14999,43316,43637,15003,15479,14306,43314,43635,15041,14354, -15040,15493,15044,14356,15043,15495, 6866,14914,21725, 6369,14916,21727, - 6371,12858,20488, 6820,12872,20500, 3817, 3953,22796,16334,12883,20505, - 3872, 3952,22795,16333, 3951,22794,16332, 3865,22785,16323,19032,19100, -38551,19030,19099,38548,30001,29999, 6915, 4625, 4602,35104,29997,15608, -22159,15607,22158,15821,22375, 3127, 3334,35145,30087, 3314, 3325,15606, -27585, 4632,15846,22390,40060,43545, 2385, 2530, 2543,40009,43415, 2964, -38234,30168,30190,40054,43537,30277,23167,19097,40033,43462,38797,32707, - 2929,30189,40458,23320,17266,25101,23166,17036,40446,23349,17310,25097, -23198,17075,38926,38925,38924,38923,39028,39026,38922,38921,38920,38919, -39041,39043,40452,40462,40454,40445,40444,40442,40449,32588,32587,32586, -40456,23339,17294,25099,23187,17062,32922,32788,16896,17339,32594,40441, -16617,25096,16879,23055,40439,16911,23063,40438,40437,23400,17527,16871, -23049,40436,40435,22906,16587,40434,22905,16586,16585,22904,40433,40432, -22903,16584,16868,23046,40465,16590,22909,40464,16609,16607,16594,43731, -43730,40431,40430,39039,39038,39037,39036,16616,38937,38936,39243,39241, -38935,38934,39292,39288,17173,16615,16752,16614,16613,16612,16744,16611, -16789,39239,39238,16852,17211,32900,32763,16623,16621,11076,11075,39237, -39236,39278,39277,39276,39275,11952,19862,25769,25748,19855,11942,32899, -32762,17499,17451,17325,25842,21445,14034,17484,16791,25870,23275,17187, -25841,23273,17185,25876,23263,17165,11948,19858,25763,13414,13413,39216, -39215,39197,39196,39291,39287,12478,12477,13373,13336,13335,13368,12031, -12030,39235,39234,12108,12107,39284,39283,11941,11940,19854,19853,27900, -27491,25747,25746,22542,21917,16005,15236,39233,39232,39203,39201,27879, -27470,27855,27446,27838,27429,25904,25903,25745,25955,25902,18666,42563, -25759,25755,25998,27775,25808,27637,27015,27615,41158,41157,27836,27427, -27049,27611,39207,39211,11951,11950,19861,19860,27835,27426,25768,25767, -22508,21883,15971,15202,25766,11956,11954,19866,19864,27875,27466,25778, -25775,22528,21903,15991,15222,39221,39219,39224,39223,39290,39286,39231, -39230,39281,39280,14930,14929,14847,14954,14316,21588, 3816,14319,21591, - 3882,14318,21590, 2882,14948,14946,14294,21570, 893,14296,21572, 964, - 8262, 8413, 8261, 8412, 8253, 8404, 3081, 5860, 3167, 5859, 3175, 8260, - 8411, 1395, 1411, 1414,21584,14311,14347,21606, 1403,14305,21581, 1409, -14342,21602, 3815, 8259, 8410, 8258, 8409, 8252, 8403, 1406, 1393, 1111, - 1117,14703,14648,14660, 8187, 8350, 3080, 2322, 5710, 3166, 5718, 3174, -11162,11147,19368,19359,25127,25118, 6642, 2749, 7102, 3062, 5755, 3209, -11161,11146,19367,19358,25126,25117, 6623, 2705, 7086, 3036, 5723, 3180, -14635,11168,11153,19372,19363,25131,25122, 6590, 2665, 7054, 2999, 5678, - 3134,11160,11145,19366,19357,25125,25116, 6600, 2674, 7059, 3004, 5683, - 3139,14894,16401,15605,15603,14362,15842,14927,16368,43326,42946,43324, -42944,43321,42941,42939,43319,43255,43588,43263,43596,43262,43595,14473, -21643, 6260,30231,32200,38696,30229,38545,30262,30167,38588,30018,30166, -30012, 3276, 3434,43569,43236,43566,43233,16329,22791, 6234,16050,22573, - 6247, 7829, 7736, 7585, 7869, 7600, 6756, 7794, 7740, 6576,14475, 6583, - 7597, 4175,14479, 4170,15601,22157, 6792,15140,15600,22156, 7261,14360, - 2881, 2805, 5527, 2986, 2945, 2937, 2928, 2927, 2384, 2977,38654,30261, - 8287, 8126, 8281, 8116, 830, 8286, 8125, 8285, 8124, 824, 827, 8303, - 8131, 8302, 8123, 8307, 8101, 8300, 8301, 8120, 8121, 8299, 8119, 8297, - 8118, 8295, 8104, 8292, 8129, 8306, 8103, 8308, 8106,30038,30035,38259, -30315, 8425, 8427,32057,14884,13417,15599,22155, 6511,15656,22195, 7821, - 6331, 6427,15712, 6424, 7414,15705,22257, 6844, 5887, 5799,16243,14926, -21733, 6841,15598,15965, 6473,22154,15597,15868,15596,15840,22386, 6843, -14445, 5911, 5635,14453,14444,14448,15830,15844,22388, 6840, 5913, 5628, -15833,15827,15826,14839, 7575,15595, 2872, 2741,14925,21732, 6839,15594, -22153, 2833,15593,22152, 2835,15592,22151, 2438,15591,22150, 2432, 2664, -15875,22409, 2445, 2717,15589,22148, 7839,16355,16374,15782,22336, 7823, -16357,22809, 7240,16207,22702, 7765,14756,14227,14755,14226,14754,14225, -16218,16217,43513,43174,43510,43171,16224, 6719,21546,14235,16216,22706, - 6725,14763,14230,16220,15588,22147, 7390,15933,22467, 7388,43505,43166, -43502,43163,16209,22704, 7767,15811,22366, 7394,16146,22656, 7387,16145, - 3605,22655,16144,15587,22146, 7231,15855,16035,15854,16034, 2839,15860, -22399, 2838,15859,22398, 7229,15586,22145, 7501,30128,38653,30132,38652, -38681,38651,30131,13334,16069,22590,16078, 6270,22599, 6269,16181,12927, -27932, 6914, 6960, 5414, 8057, 5957, 6506, 6505,18941,18940,10538,10537, -16179,13333,16170,13332,16388,15017, 7588, 6306, 5236, 5811, 5851, 5869, - 6740, 7127, 5798, 6468, 6996, 5564,14405,14018,14404,14017,15770, 6466, - 6994, 5562,14450,14447,15769,15768,15767,16373,22815, 7228,14407,14020, -15772,16122,22643, 7227,14409,14022,14443, 5547, 5223,32069,27917,16038, -22561,16037, 6291,22560, 6288,27915,15874,22408, 4435,15801,22359, 4459, - 6574,22144,15585, 6562,22358,15800, 6582,22406,15872,16011, 5655, 4128, -15584,22143, 4437, 5660, 4093,14634,14633,14632,14631,43483,18998,16048, -22571, 6258,43478,43131,43475,43128, 6707,21367,13906,16183,22684, 4239, -14678, 6689,21336,13835,14680,16124,13331, 5770, 5919,14672,14671, 5768, - 5868, 5766, 5907, 6561, 4189,15911,22448, 6838, 5943, 5627, 6442, 6987, - 5542,15703, 5594, 5416, 5598, 6075, 7011, 7997,28033,27566, 6496, 7417, -22727,22005,16257,15340,15583, 5600, 5867, 7013, 7854,27610,27300, 6498, - 7163,22142,21753,15582,15047, 5945, 5645, 6724, 7116, 5787, 5602, 5947, - 7015, 7918,27754,27388, 6502, 7285,22459,21851,15927,15157, 5597, 5962, - 7010, 7924,27798,27414, 6495, 7289,22486,21868,15951,15185,15455,16352, -15503,16351,16350,15513,22106, 7835,14844,21717, 7820,14886,21720, 7819, -15410,22044, 7818,14825,21708, 7817,14824,21707, 7816,16199,22692, 7815, -14883,14823,43587,43254,43586,43253, 7825, 2663,16362,22811, 1398,16367, -16366,43289,43616,43594,43261, 2414,16372,22814, 1155,16371,22813, 2421, -16359,43280,43613,43252,43585,14838,16365,16364,43278,43611,43275,43608, -43273,43606,43291,43618,15447,38524, 8682,15449,38526, 8684,43271,43604, -43270,43603,43598,43265,43259,43592,16370,43269,43602,43017,43408,15858, - 3596,22642,16121,15857,22397, 2837,14234,21545, 6718, 5782,14743,21688, - 6318,16198,16215,16304,16214,16197,16213,16206,22701, 7764,16205,22700, - 7763, 6717,21544,14233,16291,16212, 5810,43103,43458,40124,14170,40123, -14169,30188,30187,38695,30186,38694,30185,32066,32060,14630,14629,14628, - 3343, 7680,39970,32449, 5425, 7677,39967,32446, 5422, 8440, 8451, 3712, - 3440, 3696, 3415, 3589, 3585, 3711, 3439,14244,43101,43456, 6671,21079, -13519,15581,16237,43099,43454,43111,18997, 3710, 3438,43109,18995,43123, -43470,43120,43467,16101,22636, 3583,15932, 3604,16312,16142,14805, 5765, - 5233,43113,43460,16120, 3595,16119,22641, 3594,16118,22640, 3593,14803, -16047,22570, 3522,16046,22569, 3521, 6706,20785,13173, 6447,21556,14255, - 6445,22725,16252, 6333, 6444,14418,14028,14442,15337, 5596, 6067, 7009, - 7995,28031,27564, 6494, 7412,22724,22003,16251,15336, 6435,21554,14253, - 6438,22722,16249, 6434, 7416,14753,14387, 5540, 6065, 6985, 7993,28029, -27562, 6437, 7410,22721,22001,16248,15334,15301,21973, 7380, 6030, 5803, - 6029, 5775, 6743, 7129, 5801, 6731, 7122, 5793, 6727, 7118, 5789,14760, - 6032, 5777,14746, 7386,21979,15307, 5781, 5452, 6034, 5779, 6723, 7115, - 5786, 5795, 6039, 7124, 7983,28016,27552, 6733, 7396,22710,21984,16226, -15312,14752,14748, 5791, 6037, 7120, 7981,28014,27550, 6729, 7392,22708, -21982,16222,15310,43027,14465,21641, 6257,16327,22789, 6256,32237,15002, -14464,14463, 6589, 6484,21453,14051,16246,14469,14468,15689,15950, 6254, -15580, 5571, 5866, 7001, 7853,27609,27299, 6481, 7162,22141,21752,15579, -15046,14751,14471, 5569, 5889, 6999, 7883,27677,27342, 6479, 7221,22300, -21814,15741,15101,16326,22788, 3938,43577,43244,43574,43241, 6819,21366, -13905, 6818,20784,13172,16331,22793, 4238, 5813, 3987, 6796,21319,13807, - 5817, 4015, 5809, 4012, 6805,20713,13116, 6807, 7147, 5834,20783,26609, - 3845,13171,26853, 3838,13666,21222, 3820, 6790, 7138, 5808,20805,26616, - 1953,13189,26857, 2018,13674,21227, 2053, 5807, 1976, 7137, 2083,26636, -26874, 6789, 2116,20848,21247,13229,13701, 5821, 1967, 7144, 2074,26629, -26867, 6800, 2107,20830,21239,13211,13692, 6794, 7140, 5815,20782,26608, - 1935,13170,26852, 2000,13665,21221, 2035, 5819, 1985, 7142, 2093,26647, -26885, 6798, 2126,20870,21256,13245,13708,16325,22787, 3937, 3940, 3946, - 3921, 3959, 3970, 3930, 3950, 3964, 3924, 3936, 3944, 3919, 3949, 3963, - 3923, 3957, 3968, 3928, 6835, 7154, 5848,20903,26670, 1589,13261,26895, - 1690,13717,21268, 1655, 3935, 3943, 3918, 6830, 7152, 5846,20898,26668, - 1934,13256,26893, 1999,13715,21266, 2034, 6834,20902,13260, 6832,20900, -13258,16315,22777, 3856, 3855, 3861, 3850, 5836, 3848, 7149, 3841,26628, -26866, 6809, 3823,20829,21238,13210,13691, 3934, 3942, 3917,14837,21713, - 6353,22100,14836,14835,14846, 6851,21738,14952, 6837,21731,14924,15502, -15501,15516,15528,15540,14882,15536, 5864, 1638,16378, 5858, 4127, 5857, - 1905, 6854,21740,14967,14881,15534,14878,14906,15544,15546, 6862,21746, -15035, 6864,21748,15037,14867,14908,14897,14891,14888,14899,14875,14880, -16098,16095,22634,22631, 3578, 3575,22629, 3573,27960, 3708,22608, 3555, -27947, 3688,22606, 3553,27945, 3686,40118,14110,30165,38687,30164,32068, - 3274, 3432, 3268, 3426,27965,27963,14626, 5349,27940,35536,14625,35538, -14627,35535,14624,35534,14623, 6664, 6663, 4303,21444,14033, 6560,21443, -14032, 5738, 3196, 2528, 2527, 5644, 7042, 8345, 8183, 2526, 3323, 3317, - 5640, 7038, 6931, 5266, 5641, 7039, 2524, 3313, 7732,39979,32435, 5362, - 7729,39976,32432, 5359,22612, 3559,27951, 3694,22611, 3558,27950, 3693, - 7630,39953,32422, 5322, 7627,39950,32419, 5319,35533,14622,35532,14621, -35531,14620,35545,14653,35530,14619,35544,14652,10716,10713,10708,10705, -35527,14616,35529,14618,10710,10707,10593,10592, 2702, 2690,18867,18855, -10470,10458, 5741, 3199, 7099, 3049,24735,24575, 5733, 3191, 3272, 3430, - 5735, 3193, 5734, 3192, 7096, 3046,24732,24572, 5731, 3189, 7094, 3044, -24730,24570, 5728, 3186, 7091, 3041,24727,24567, 5715, 3172, 7083, 3029, -24724,24564, 3270, 3428, 2700, 2688,18865,18853,10468,10456,43482,18834, - 5709, 3165, 5704, 3161, 5626, 4113, 5855, 4085, 5662, 3986, 5701, 3158, - 5693, 3150, 7077, 3022, 7069, 3014,24716,24556,24708,24548, 6620, 2699, - 6612, 2687,18985,18864,18977,18852,10613,10467,10605,10455, 5697, 3154, - 5689, 3146, 7073, 3018,22604, 7065, 3010,24712,24552, 3551,24704,24544, - 6616, 2694, 6608, 2682,27943,18981,18859,18973,18847, 3684,10609,10462, -10601,10450,22603, 3550,27942, 3683, 2696, 2684,18861,18849,10464,10452, - 5698, 3155, 5690, 3147, 7074, 3019, 7066, 3011,24713,24553,24705,24545, - 6617, 2695, 6609, 2683,18982,18860,18974,18848,10610,10463,10602,10451, -28004, 3126, 3060, 3379, 3125, 3123, 3122, 3333, 3066, 3383, 3065, 3382, -10507,18914,10506, 2875,18913, 2874, 3304, 3493, 3302, 3491, 3301, 3490, - 2746, 2745,18889,18888,10490,10489, 2744, 2743,18887,18886,10488,10487, -14522, 5654, 2538,15766,15765,14397, 8138, 8310, 5559, 5546, 5545, 5222, - 5707, 5221, 5717, 5544, 5220,16422,16417,16419,43666,43661,43664,43659, -43656,43654,43652,43650,43643,43648,43641,43646, 1721, 7573, 1718, 7570, - 7711, 2859, 7706, 2844,16494, 7690, 2800, 7688, 2798, 7687, 2797, 7709, - 2857, 7704, 2842,16484, 7694, 2813,16502, 7685, 2795, 7714, 2864, 7684, - 2794,16491,16490, 7693, 2812, 7683, 2793,16534,16541,16532,16539,16547, -16552,16489,16551,32547,16545,32549,16550,16549,32544,16488,32584,32596, -16580,22899,28140,32583,38724,43714,22901,28142,38722,43712,16582,32581, -16671,16593,16569,16412,16411,16410, 7682, 2792, 7692, 2811,16524,16526, -16408,16407,16430,16406,16509,16506, 3645,22871,16497,16427,16426,22823, - 4558,16425,22822, 4556,16592,16500,16511,16465,16469,16467, 7701, 2822, - 7699, 2820, 7697, 2818,16504,16951,23098, 8930,32714,16751,16750, 4324, -16746,32898,32761, 9180,23289,17210, 6722,23032,16851,17209,23288, 9179, -17215,23293, 9187,16839,16989, 6471,23037,16857,16836,16987,16831,16984, -43775,43804, 4361, 9178,17191,23279, 9156,17164,23262, 9137,17189,23277, - 9154,16785,17184,23272, 9152,17183,23271, 9151,17163,23261, 9136,16793, -17260,23314, 9210,17259,23313, 9209,17258,17257,17256,17540,17520,16895, -16894,17384,16916,17373,17084,23204, 9040,17546, 4126, 8890, 8929,23097, -16950,16949,23096, 8928,16948,23095, 8927,16947,43871,43830,43869,43828, -17472, 6376,22977,16757,16765,22969, 7161,17449,16799,17459,32713,16749, -16748,17470,17447, 8952, 8951,16830,23015, 7448,16850,23031, 6788,32760, -17208,23287, 9177, 8970, 8969,16809,22996, 4555,16808,22995, 6317,16849, -23030, 7159,16829,23014, 6374,16848,23029, 7446,16828,23013, 6786,17207, -23286, 9176,16782,16847,23028, 7215,16827,23012, 6419,16779,17480,32732, -32754,32731,16784,17182,16768, 9189,43807,43778, 4268,17176,17161,43867, -43826,17160,43865,43824, 9208,23312,17030,17255,23160, 9017, 9207,23311, -17029,17254,23159, 9016, 9226,23343,17066,17298,23191, 9030,17028,17253, - 9206,23310,17252, 9205,23309,17251,17027,23158, 9015,17250,23308, 9204, -17026,23157, 9014,17249,23307, 9203,17248,23306, 9202,17025,23156, 9013, -17247,16867,17519,16893,16892,16891,16890,16902,16865,23045, 6470,16873, -16870,23048, 6378, 6190,23395,17522,16864,23044, 4525,16883,23059, 4509, -16914,23065, 4508, 9201,23305,17246, 9249,23355,17360,17420,23377, 9272, -17138,23241, 9091, 5871, 7856, 7524, 7165, 8042, 6140,16927,17143,23076, -23246, 7522, 9096,28180,28208, 8040, 9120, 6138, 8876,17436,23391, 9286, -17592,28242, 9307,23430,28276, 8912, 7520, 8038, 6136,17136,23239, 9089, -17430,23386, 9281,17586,28237, 9302,23425,28271, 8907, 7518, 8036, 6134, - 9269,23374,16924,17140,17417,23073,23243, 7516, 9093,28177,28205, 8034, - 9117, 6132, 8873,17372,16889, 9229,23348,17074,17309,23197, 9034,17073, -23196, 9033,16881,23057, 4517,16670,16574,22893,28134,32575,38716,43706, -22895,28136,38718,43708,16576,32577,32601,16573,22892,28133,16625,22919, -28152,16946,23094, 8925,16945,23093, 8924,38796,32704,17444,17443,17498, -17477,17504,17488,17490,17442,17441,16795, 3581,22981,16775,16774,22980, - 4507, 3580,23011,16826, 8943,23102,17179,16957,23268, 9147,32748,32893, - 3864,22994,16807,16806,22993, 4539, 2179,23010,16825,17509,16846,23027, - 2193, 2184,23020,16838,16855,23035, 2197, 2182,23018,16834,16811,22998, - 4506,16813,23000, 4524,16982,16819,43800,43771, 9166, 1673, 9200,23304, -17024,17245,23155, 9012, 9228,23347,17072,17308,23195, 9032, 9224,23341, -17064,17296,23189, 9028,32759,32897,17214,23292, 9186,17206,23285, 9175, - 3948,23026,16845, 3644,23025,16844,43803,43774, 9174, 2192,17159,23260, - 9135, 9134,23259,17158,17440,17514,17512,16860,23040, 2191,17000,23134, - 8995,16998,23132, 8993, 3591,23024,16843,17222,16994, 9192,23296,17218, - 9194,23298,17220,17507,16992,23127, 8987,16862,23042, 1328,23154,17244, -17023,17474,17243,17022,17497,17021,17486,17439,17496,17057,17093,17020, -17019,17117,17352,17371,17370,17376,17369,17390,17379,17392,17109, 8894, - 1637,17338, 8889, 1904,17356,17103,17438,17401,17126,17403,17128,17409, -23364, 9261,17411,23366, 9263, 8923,23092,16944, 8922,23091,16943, 9133, - 2862, 9144, 2791, 9142, 2810, 838,22973,16764,16761,22976, 840, 9131, - 2790,16736,16734,17324, 8978,16842,23023, 3814, 9107,23257,17154,17107, -23220, 9070, 9076,23226,17115, 8968, 8967,23119,16978,16803,22990, 3881, -16802,22989, 2880,32747,16805,22992, 1327,16816,23003, 1334, 9165, 8962, - 8961, 1344, 9163, 8966,23118,16977, 8964,23116,16975,17217,23295, 9191, - 9011,23153,17018,17017,23152, 9010,17120,23229, 9079,17082,23202, 9038, - 9062,23213,17099,32758,32757, 8984, 8982, 8977, 8976, 2171, 2170, 2178, -23009,16824,43802,43773, 9173, 2190, 9199,23303,17016,17242,23151, 9009, - 9198,23302,17015,17241,23150, 9008, 9196,23300,17239,23148,17238,17237, -17236,17235,17234,17233,17232,17231,17518,17517,17172,17337,17336,17335, -17334,17345,17205,32896,17333,32921,28257, 9056,43837, 9245, 9395,28250, - 9329,43796, 9392,28197, 9326,43902,28224, 9053,43895, 9242,43834, 9049, -28254, 9238, 9388,43793, 9322,28247, 9385,43899, 9319,28194,43892, 9046, -28221, 9235, 9232,23352,17089,17323,23207, 9043,17321,17320,32773,32680, -32679,32772,32685,32778,32683,32775,32792,32688,38823,32771,17516,17539, -17543,17204,23284, 9172,17013,23147,17012, 9006,23146, 9005,17011,17010, -23145,23144, 9004, 9003,17009,17007,23143,23141, 9002, 9000,17081,17080, -23201,23200, 9037, 9036,38830, 9416,32848, 9415,32847,38829, 9215,23319, -17035,17265,23165, 9022, 9213,23317,17033,17263,23163, 9020,17203,23283, - 9171,16878,23054, 2188,17529,23402, 1325,17526,23399, 9170,16876,23052, - 1324,17525,23398, 2187, 1177, 1188, 1160, 1185, 1167, 1170,32806,32697, - 1220, 1215, 1246, 1202, 1250, 1232,32811,32702,17134,23237, 9087,17427, -17583,23383,23422,28234,28268, 9278, 1184, 9299, 1187, 8904, 1176,16926, -23075, 1159,17142,28179, 1166,23245,28207, 1169, 9095, 9119, 8875, 9275, -23380,17423, 9277,23382,17426,17148,16931,23251,23080,28212,28184, 9101, - 1236, 9124, 1240, 8880, 1226,32808,32699,38792,38755,43819,43784, 9280, - 1245, 9301, 1249, 8906, 1231,23385,23083,28236,28187, 9343, 1254, 9363, - 1256, 8883, 1210,38860,38757,43860,43786, 9458, 1260, 9471, 1262, 8911, - 1219,17429,16934,28215,28270, 9127, 1208, 9376, 1258,32880,32701,43821, -43907, 9306, 1214, 9480, 1264,28241,28275, 9365, 1222, 9378, 1242,43862, -43909, 9473, 1228, 9482, 1252,17153,17585,23256,23424, 9106, 1197,32810, -32931,38794,38872, 9285, 1201,23390,23429, 9345, 1204,38864,38874, 9462, - 1206,17435,17591,32884,32933,17434,17590,23389,23428,28240,28274, 9284, - 1200, 9305, 1213, 8910, 1218,17433,17589,23388,23427,28239,28273, 9283, - 1199, 9304, 1212, 8909, 1217,17147,16930,23250,23079, 9100, 1235,28211, -28183, 9123, 1239, 8879, 1225,16933,23082, 1244,17152,28186, 1248,23255, -28214, 1230, 9105, 9126, 8882,17145,23248, 9098,17151,23254,17150, 9104, -23253, 9103,38863, 9461,32883, 9460,32882,38862, 1316, 1319, 1337, 1313, - 1340, 1322,17098,23212,17097, 9061,23211, 9060,38834, 9427,32857, 9426, -32856,38833,17367,17366,17365,17364,17363,16908,32794,32925,17425,17582, - 9448, 9447, 1380,17560,23409, 1373,38849, 9446,32872, 9444,32870,38847, -38841, 9434,32864, 9432,32862,38839,38837, 9430,32860, 9429,32859,38836, -32691,32796,17106,17105,23219,23218, 9069, 9068,38844, 9439,32867, 9438, -32866,38843, 1370, 1378, 1348, 1375, 1356, 1362,16910,23062, 2186, 1385, -23412,17568, 9252,23358,17387, 1382, 1390, 1353, 1387, 1359, 1365,32693, -32800,17114,23225,17113, 9075,23224, 9074,38853, 9453,32875, 9452,32874, -38852,17332,17331,17330,17329,16888,32787,32920,17432,17588,17358,17556, -17351,17553,17389,17570,17378,17562,17382,17564,17394,17572,17362,17558, - 9442, 9441, 9424, 9423, 1368, 1108,13330,13329,13400,13397,17078,17315, -17071,17307,15133,13770,13518,14434,15468,14972,15521,14863,13769,14436, -15135,13517,13768,14811,15395,13516,13767,14420,15116,13515,15518,14860, -15465,14965,13805,14816,15398,13568,17124,17405,17070,17314,15369,14792, -14790,15359,14821,15430,15491,14910,14770,15314,12926,13328,15520,14971, -13327,12925,13326,12924,13325,12923,15542,15031,13469,13253,14815,15397, -15464,14859,17349,16906,17347,16904,14873,16397,14871,16395,14532,13324, -14527,13323,14525,13393,14530,12922,14535,12984,14537,12921,14517,12920, -16382,14987,16384,14989,16022,13322,16017,13321,16015,13395,16020,12919, -16025,12986,16027,12918,16008,12917,15775,15777,14402,14400,17398,14510, -14903,14858,14508,14424,14819,16961,17305,14412,14855,13876,13883,13881, -13873,14422,14414,14416,14809,13946,13944,13878,13889,13887,15029,14923, -13451,14963,13840,13900,13831,13803,13842,13981,13779,13829,13959,13950, -13971,13964,13962,13967,16068,22589,16077, 4261,22598, 4260,16066,22587, -16075, 4259,22596, 4257,15256,21934,15263, 7336,21941, 7343,15254,21932, -15261, 7334,21939, 7341,12916,20525, 4255,13079,20683, 4314,12915,20524, - 4254,12914,20523, 4253,13081,20685, 4316,13320,20978, 4434,13419,21040, - 4468,13319,20977, 4433,13318,20976, 4432,13317,20975, 4431,12913,20522, - 4252,12912,20521, 4251,12911,20520, 4250, 4301,22781,16319,15412,22046, - 7464,12910,20519, 6816,12909,20518, 6634,12908,20517, 6661,12907,20516, - 6459,12906,20515, 6453,12905,20514, 6802,13316,20974, 6632,13315,20973, - 6637,13314,20972, 6628,13313,20971, 6457,16321,22783, 4249,16308,22771, - 4248,16203,22698, 6715,15914,22451, 6492,15305,21977, 7384,15303,21975, - 7382,15155,21849, 7283,15414,22048, 7466,13006,20610, 6813,15403,22039, - 7458,13009,20613, 6659,16201,22696, 6713,13403,21030, 6639, 8092, 8571, - 8574, 8095,38612,37449,38626,37448,38624,37446,38541,37444,14814,17313, -17312,12904,12903,12902,12901,13083,13012, 7107, 5350,42779,42777, 4169, - 4393,14834,14922, 4390, 4349, 4424, 4270, 4347,18969,43135,27930,27928, -27921, 4601, 4600, 4598,27511,27509,27504, 7785, 6772, 6679, 6487, 6688, - 8090, 8569,30259,35323,30254,35317,30252,35315, 8089, 8568,18967,43133, -30251,35314,30244,35307,30257,35321,30249,35312,15087,21797, 4505, 4504, - 4512, 4579, 4577, 4514,29692,34639,29691,34638,29707,34654,29717,34664, -29799,34746,29801,34748,29740,34687,13958, 6932, 5267, 6930, 5265, 4503, - 4502, 4501, 4520, 4519, 4551, 8363, 2934, 2926, 2974, 2970, 8370, 2925, - 2383, 2391, 2382, 8368, 8347,30250,35313, 8343, 7722, 7720,19096,19094, -10709,10706, 4500,22238,15684, 4499,22236,15681,13514,21078, 7566,12900, -20513, 6779,12899,20512, 6826,12898,20511, 6737,17122,23231, 9081, 9066, -23216,17102,17111,23222, 9072, 9026,23185,17056,17095,23209, 9058,12897, -20510, 7806,15550,22120, 7851, 7507,22090,15478,15533,22114, 7845,15538, -22116, 7847, 7499,22084,15461,15530,22111, 7841,15711,22261, 6742,15708, -22259, 7774, 7581,22380,15829,15836,22382, 7583,15923,22457, 7564, 7593, -22241,15688,15442,22075, 7492,15489,22096, 7513,15481,22092, 7509, 7837, -22108,15515,17005,23139, 8998, 8997,23138,17004,15500,22099, 7832, 7497, -22078,15454,15453,22077, 7496, 7831,22098,15499,15473,22087, 7504, 4529, -22140,15578,13822,15577, 4527,22139,15576,13817,15575,15724,13513,15574, -22138, 4179,15573,13583,14251,15710,15572,22137, 7776,14257,15571,16242, -15707,15570,22136, 6745,16254,15569,15832,15835,15702,15922,15568,22135, - 6500,15567,15925, 4188, 4538,22455,15920, 4537,22454,15919, 7591,22453, -15918,15917,13613,15916, 7595,22134,15566,14065,15565,17228,14833, 4173, -13188,20804, 4365,13228,20847, 4386,17227,13237,20859, 4389,13169,20781, - 4360,14099,13827, 4534,13603,21164, 7590,14068,14024,13570,13209,20828, - 4382,13512,13412,13411,17003,17226,15452,14832,15498,14921,17328,16887, -14866,16391,14521,13410,16377,14977,16010,13409,14396,13941,13885,13074, -20679, 4310,13073,20678, 4309, 4308,22776,16314,15300,21972, 7379,13072, - 4531,15564,22133, 6475,15870,15563,15825,13599,13511,15764, 6771, 6670, - 6678, 6486, 7784,13448,13897, 3266, 3424,42761,42776, 6929, 5264, 2924, - 2381,18833,43481, 8713, 2380, 2379, 2962,19078,42868,18806,43450, 2923, - 1016, 1058,35100,29992, 1044,35096,29988,15561,22131,35097,29989, 1040, - 2404, 1034, 1042, 1054, 1028, 5115, 5117,16064,22585,16073, 4297,22594, - 4296,27926, 4624, 6948, 5294,15252,21930,15259, 7332,21937, 7339,27507, - 8352,14813,14857,14970,14969,42775,13447,13896,13446,13895, 7110, 5369, - 2980, 8377, 7739, 7738,19111,19110,10739,10738,18987,43158, 2942, 8712, - 4563,13639,21187, 4554,13904, 4195, 4381,15070,21780, 4533,13903,14067, -13957,16938,16937,42132,42573,17002,17225,15451,14920,15497,14831,14919, -15409,22043, 7462,13305,20963, 6811,13304,20962, 6657,16196,22691, 6711, -13303,13986,13985,13984,17224,14918,14830,42689,42380,42688,42379, 4429, -13311,20969, 4428,13977,16936,13307,20965, 4423,13509,37779, 4899,13507, -37777, 4897,13983,42687,42378,42373,42682,13988,42377,42686,42691,42382, - 9078,23228,17119, 7511,22094,15487,15440,22073, 7490,13115,20712, 6824, -42802, 8376, 8375, 7849,22118,15548,13826,13445,13894,13114,13628, 2232, -21214,13743,13651,21291, 2250, 6477,21167,15144,13606,21841, 7270,13956, -21399, 2214, 2231,21355,13867,15143,21840, 7269, 6483,21334,13833,13955, - 4574,13113,13949, 4571, 4570,13731,21281, 4553,13168,13737,21286, 2230, -13742,21290, 2249,13954,21398, 2213,13948,21396, 2229,13112,20711, 6735, -13940,15265,21943,15066,21776,15085,21795,30243,35306,15560,22130, 4548, -29765,34712,29750,34697, 2378, 5130, 5127,43480,18832, 2377,35094,29986, - 2376,35090,29982,15558,22128,35091,29983, 2403,15077,21787,30235,35299, -30246,35309, 8342,13111,20710, 6777,13110,20709, 7804, 4550,13208,20827, - 4380,18680,42605, 4379,13646,18934,42986, 8312, 1778,42238,42611,13167, -20780, 4359, 7035, 5307,42741, 1710, 1626, 8327, 8326, 2375, 8340, 8325, - 7615, 7612,19074,19071,10696,10693, 4562,13166, 8224, 8659,19004,43178, -15330,21997, 8664, 8226, 2922, 2374, 8223, 8658, 5467, 955, 6059, 953, - 5464, 959, 6056, 957, 8661, 8663, 8218, 8221,14243,14242,16236,16235, -32298,32297, 8076, 6069,42820,42819, 8383,10641,19007,10640, 6755,19006, - 6754,15343,22008, 7135, 5491,42828, 2373, 8387, 8386, 7793, 7792,19130, -19129,10758,10757,19123,42907,43185,43523,42818,42906, 8672, 8675, 1503, - 6071, 5483, 1507,32302, 7134, 5490, 8080, 6089,19017,43192,43191,43528, -43190,43527,42827,42913, 8385, 7791, 7790,19128,19127,10756,10755,10651, -19016,10648, 6766,19013, 6763, 8233, 8236,42911,42825, 5497, 1549, 6093, - 1539, 5496, 1548, 6092, 1538,15069,21779,15332,21999,15083,21793,15090, -21800,15088,21798,15674,22221,15557,22127,15556,22126,15559,22129,15555, -22125,15078,21788,15080,21790,15076,21786,15554,22124,15562,22132,15553, -22123,15552,22122,15074,21784,15073,21783,15184,21867,15949,22485,15948, -22484,15988,15219,22525,21900,27872,27463,15985,15216,27869,22522,21897, -27460,27857,27448,27849,27440,25615,27633,27608,21778,15068,27834,27425, -27765,27606,15970,15201,22507,21882,27833,27424,15969,15200,27899,27898, -22541,22540,22506,21881,27490,27489,16004,16003,27832,27423,21916,21915, -15235,15234,27897,27488 -}; - - -const int s_nDataSize3 = 24772; -unsigned int s_Data3[24772] = { -//Output priorities (total = 24772): -10, 9, 12, 6, 11, 14, 4, 1, 7, 5, 2, 3, 13, 8, 0, -0, 1, 2, 219, 218, 76, 217, 216, 77, 1, 0, 74, 78, 79, 75, -70, 71, 72, 68, 73, 69, 310, 299, 296, 331, 297, 332, 114, 26, 298, -340, 330, 336, 338, 339, 62, 112, 328, 334, 329, 335, 113, 337, 327, 333, -115, 60, 27, 61, 63, 273, 215, 36, 213, 31, 35, 39, 319, 312, 320, -323, 324, 343, 157, 345, 28, 178, 32, 59, 269, 58, 309, 305, 275, 271, -308, 304, 34, 117, 181, 129, 154, 211, 30, 38, 177, 193, 55, 130, 268, -33, 303, 174, 29, 37, 119, 212, 143, 188, 66, 270, 141, 183, 194, 179, -126, 261, 190, 267, 344, 346, 272, 189, 173, 274, 51, 322, 321, 342, 315, -214, 311, 14, 57, 223, 348, 125, 176, 192, 317, 280, 314, 165, 160, 175, -326, 127, 17, 247, 172, 262, 5, 231, 99, 138, 124, 54, 301, 325, 167, -15, 43, 205, 47, 122, 147, 292, 295, 83, 106, 86, 87, 220, 131, 347, -293, 150, 209, 233, 67, 116, 148, 156, 171, 180, 191, 256, 195, 341, 128, -277, 291, 281, 289, 294, 313, 102, 46, 103, 207, 229, 236, 240, 224, 227, -249, 170, 49, 251, 258, 318, 133, 197, 278, 2, 56, 252, 265, 254, 20, -142, 151, 316, 164, 121, 162, 41, 107, 139, 203, 288, 302, 48, 52, 110, -53, 64, 4, 16, 284, 135, 307, 3, 40, 155, 202, 23, 93, 22, 92, -290, 65, 210, 50, 98, 208, 94, 123, 137, 187, 225, 7, 10, 120, 109, -263, 287, 186, 108, 152, 264, 90, 253, 96, 97, 136, 200, 118, 140, 300, -306, 185, 6, 11, 89, 259, 85, 101, 132, 196, 24, 45, 260, 244, 91, -18, 104, 232, 19, 44, 105, 184, 21, 84, 226, 250, 283, 279, 286, 158, -248, 257, 255, 80, 169, 13, 100, 81, 168, 199, 238, 9, 12, 82, 182, -201, 266, 146, 204, 230, 239, 241, 159, 221, 285, 134, 88, 242, 246, 8, -144, 222, 149, 161, 228, 237, 276, 95, 206, 282, 163, 198, 243, 235, 245, -42, 166, 25, 111, 145, 153, 234, 13, 0, 1, 8, 3, 11, 7, 9, -2, 12, 4, 6, 5, 10, 0, 61, 62, 0, 2, 3, 5, 6, 8, -15, 17, 1, 4, 7, 9, 10, 11, 12, 13, 14, 16, 18, 19, 20, -21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, -51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 63, 64, 65, 66, 67, -68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 4, 5, -2, 0, 1, 3, 7, 10, 8, 11, 6, 9, 97, 100, 22, 123, 124, -125, 98, 101, 40, 39, 66, 72, 75, 69, 68, 74, 21, 41, 67, 73, -77, 30, 71, 23, 106, 36, 54, 55, 63, 96, 32, 99, 58, 59, 65, -38, 107, 27, 17, 56, 57, 64, 70, 76, 29, 15, 31, 122, 102, 25, -48, 49, 50, 51, 52, 53, 26, 28, 103, 37, 127, 104, 120, 121, 24, -33, 46, 47, 62, 112, 113, 116, 105, 20, 13, 126, 128, 35, 34, 19, -42, 43, 44, 45, 60, 61, 18, 79, 84, 91, 16, 14, 82, 89, 94, -85, 119, 83, 88, 95, 118, 78, 90, 81, 86, 93, 12, 80, 87, 92, -108, 109, 110, 111, 114, 115, 117, 148, 542, 149, 147, 303, 531, 555, 573, -574, 532, 556, 150, 153, 155, 578, 304, 560, 536, 151, 154, 157, 534, 558, -576, 533, 538, 557, 575, 547, 551, 570, 305, 568, 306, 540, 541, 544, 546, -550, 553, 562, 564, 565, 571, 552, 554, 572, 535, 559, 577, 537, 561, 569, -539, 543, 545, 548, 549, 563, 566, 567, 308, 307, 152, 156, 158, 382, 144, -128, 145, 438, 446, 450, 458, 462, 470, 474, 482, 492, 500, 504, 510, 516, -522, 530, 204, 394, 528, 381, 397, 480, 498, 396, 400, 436, 444, 448, 456, -460, 468, 472, 490, 502, 508, 514, 520, 286, 388, 393, 294, 403, 273, 384, -385, 387, 391, 399, 408, 313, 317, 347, 354, 414, 419, 426, 25, 88, 127, -130, 198, 275, 336, 483, 126, 281, 283, 341, 432, 299, 325, 390, 402, 415, -416, 417, 418, 427, 428, 116, 124, 134, 142, 221, 229, 298, 479, 486, 497, -527, 24, 87, 227, 311, 315, 329, 353, 506, 512, 518, 30, 34, 41, 196, -300, 484, 48, 104, 186, 191, 264, 335, 343, 363, 234, 276, 441, 443, 453, -455, 465, 467, 477, 495, 525, 222, 269, 476, 494, 524, 395, 89, 140, 413, -420, 425, 481, 499, 505, 511, 517, 529, 200, 257, 327, 398, 401, 440, 445, -452, 457, 464, 469, 32, 36, 42, 47, 345, 365, 435, 442, 447, 454, 459, -466, 471, 478, 489, 496, 501, 507, 513, 519, 526, 202, 323, 146, 170, 177, -179, 248, 255, 368, 380, 206, 122, 132, 258, 279, 288, 296, 349, 375, 434, -46, 114, 165, 180, 201, 219, 243, 250, 297, 405, 429, 33, 38, 43, 172, -203, 208, 346, 392, 404, 410, 485, 488, 183, 216, 261, 348, 386, 430, 20, -26, 65, 100, 131, 162, 167, 174, 182, 188, 189, 194, 210, 218, 240, 252, -260, 266, 272, 284, 360, 372, 383, 423, 12, 17, 57, 92, 99, 129, 213, -215, 230, 231, 278, 291, 293, 339, 389, 406, 411, 422, 15, 60, 62, 97, -117, 119, 135, 199, 224, 225, 236, 245, 267, 302, 321, 326, 377, 407, 102, -137, 175, 274, 431, 412, 421, 424, 173, 238, 246, 251, 253, 262, 270, 282, -366, 370, 378, 437, 439, 449, 451, 461, 463, 473, 475, 491, 493, 503, 509, -515, 521, 523, 0, 1, 81, 82, 106, 160, 168, 184, 185, 192, 193, 263, -271, 277, 322, 358, 22, 28, 31, 40, 67, 98, 103, 105, 138, 254, 316, -319, 355, 328, 10, 14, 49, 52, 59, 70, 73, 90, 112, 133, 220, 228, -232, 233, 301, 309, 314, 331, 333, 337, 344, 351, 35, 37, 44, 163, 342, -409, 433, 487, 259, 27, 29, 39, 50, 161, 164, 176, 178, 181, 187, 190, -197, 205, 239, 241, 242, 324, 332, 359, 361, 362, 371, 373, 374, 6, 7, -45, 55, 56, 75, 77, 79, 80, 108, 109, 159, 166, 169, 171, 195, 217, -237, 247, 249, 256, 265, 268, 280, 334, 340, 350, 357, 367, 369, 379, 2, -3, 9, 18, 19, 21, 23, 53, 63, 64, 66, 68, 72, 76, 83, 84, -93, 95, 96, 101, 107, 111, 120, 121, 123, 125, 139, 141, 143, 212, 244, -290, 295, 310, 312, 318, 320, 330, 338, 352, 356, 4, 5, 8, 11, 13, -51, 54, 58, 61, 69, 71, 74, 78, 85, 86, 94, 110, 113, 115, 136, -207, 209, 211, 214, 223, 226, 235, 285, 287, 289, 292, 364, 376, 16, 91, -118, 0, 3, 19, 149, 96, 20, 150, 5, 1, 6, 4, 2, 147, 93, -91, 145, 148, 95, 146, 85, 55, 66, 76, 59, 73, 81, 51, 61, 64, -54, 58, 92, 94, 63, 173, 62, 86, 65, 75, 60, 74, 82, 56, 52, -53, 57, 171, 167, 160, 159, 170, 72, 141, 162, 172, 28, 68, 29, 140, -168, 27, 70, 126, 139, 69, 163, 89, 137, 166, 71, 169, 129, 142, 164, -116, 135, 143, 90, 67, 113, 121, 165, 161, 131, 123, 125, 133, 30, 7, -138, 10, 117, 119, 11, 120, 127, 134, 130, 132, 115, 124, 114, 136, 9, -118, 33, 77, 157, 158, 8, 12, 88, 155, 156, 34, 78, 99, 97, 128, -36, 44, 87, 35, 43, 15, 13, 17, 122, 21, 23, 25, 144, 37, 45, -47, 103, 32, 42, 80, 39, 49, 83, 108, 40, 50, 84, 38, 46, 48, -31, 41, 79, 18, 98, 22, 24, 26, 14, 16, 105, 107, 100, 152, 111, -109, 104, 101, 110, 112, 106, 153, 102, 151, 154, 0, 1, 3, 4, 2, -12, 13, 10, 11, 14, 9, 6, 5, 7, 8, 21, 24, 23, 22, 20, -19, 15, 16, 17, 18, 0, 1, 3, 2, 108, 109, 139, 153, 122, 96, -178, 97, 126, 95, 101, 100, 94, 174, 140, 172, 175, 173, 5, 36, 154, -88, 83, 80, 35, 161, 151, 19, 11, 6, 147, 143, 34, 176, 123, 37, -169, 170, 171, 163, 164, 165, 166, 167, 168, 155, 156, 157, 158, 159, 160, -82, 162, 177, 152, 81, 111, 7, 12, 20, 128, 4, 93, 21, 64, 13, -148, 60, 62, 118, 10, 18, 33, 144, 30, 48, 135, 149, 86, 114, 99, -124, 129, 130, 131, 61, 63, 65, 8, 14, 16, 22, 24, 26, 28, 73, -75, 77, 90, 56, 72, 74, 76, 78, 51, 53, 55, 57, 59, 67, 69, -71, 79, 89, 91, 50, 52, 54, 58, 66, 68, 70, 92, 107, 39, 41, -43, 45, 47, 110, 103, 105, 120, 145, 127, 38, 40, 42, 44, 46, 137, -102, 104, 106, 31, 32, 49, 9, 15, 17, 23, 29, 87, 25, 27, 150, -141, 142, 84, 85, 146, 98, 116, 119, 133, 115, 121, 136, 132, 125, 117, -112, 113, 138, 134, 2, 0, 1, 3, 8, 6, 7, 4, 5, 9, 10, -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -15, 16, 2, 1, 4, 8, 7, 9, 6, 0, 5, 3, 10, 109, 107, -108, 97, 105, 28, 30, 21, 81, 26, 32, 106, 20, 24, 35, 22, 34, -96, 104, 62, 27, 111, 11, 18, 23, 36, 83, 37, 12, 95, 17, 46, -56, 25, 40, 42, 87, 89, 14, 16, 13, 29, 103, 82, 110, 15, 19, -31, 33, 102, 38, 66, 67, 68, 69, 70, 71, 72, 85, 41, 115, 117, -91, 93, 94, 99, 101, 43, 73, 86, 88, 114, 116, 50, 52, 74, 76, -77, 78, 79, 39, 113, 44, 45, 47, 48, 49, 51, 53, 54, 55, 57, -58, 59, 60, 61, 63, 64, 65, 75, 80, 84, 90, 92, 98, 100, 112, -0, 1, 20, 17, 18, 12, 19, 16, 21, 15, 23, 14, 22, 13, 0, -6, 5, 11, 3, 9, 2, 8, 1, 7, 4, 10, 3, 4, 11, 14, -17, 32, 0, 1, 2, 5, 6, 7, 8, 9, 10, 12, 13, 15, 16, -18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, -34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 2, 3, 0, 1, -15, 13, 17, 21, 77, 76, 33, 30, 34, 110, 105, 114, 118, 31, 32, -35, 101, 100, 16, 131, 12, 14, 130, 135, 132, 112, 120, 116, 111, 115, -119, 79, 117, 113, 121, 20, 133, 80, 134, 78, 81, 44, 109, 49, 47, -124, 46, 28, 48, 126, 26, 87, 89, 90, 88, 6, 5, 7, 9, 11, -19, 36, 38, 40, 42, 86, 91, 18, 4, 10, 39, 8, 37, 41, 43, -45, 60, 127, 27, 61, 106, 129, 59, 108, 128, 53, 54, 57, 58, 62, -50, 29, 56, 63, 52, 55, 107, 122, 123, 125, 51, 64, 65, 66, 67, -68, 69, 70, 71, 72, 73, 74, 75, 82, 83, 84, 85, 92, 93, 94, -95, 96, 97, 98, 99, 102, 103, 104, 23, 25, 24, 22, 175, 174, 176, -162, 158, 165, 124, 166, 15, 155, 126, 160, 120, 121, 122, 123, 125, 127, -128, 129, 153, 157, 171, 152, 163, 170, 96, 97, 108, 0, 3, 6, 9, -12, 66, 69, 72, 75, 78, 81, 130, 131, 150, 151, 156, 159, 161, 168, -169, 173, 177, 154, 164, 167, 172, 1, 2, 4, 5, 7, 8, 10, 11, -13, 14, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, -29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, -59, 60, 61, 62, 63, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, -79, 80, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, -95, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112, -113, 114, 115, 116, 117, 118, 119, 132, 133, 134, 135, 136, 137, 138, 139, -140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 178, 179, 0, 1, 2, -8, 6, 7, 3, 5, 4, 0, 1305, 1308, 540, 545, 558, 563, 564, 569, -570, 575, 576, 581, 582, 587, 588, 593, 594, 599, 600, 605, 606, 611, 612, -617, 618, 623, 624, 629, 630, 635, 636, 641, 642, 647, 648, 653, 654, 657, -662, 663, 668, 669, 672, 677, 678, 681, 684, 687, 690, 0, 1, 2, 3, -4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, -19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, -34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, -49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, -94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, -109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, -124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, -154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, -169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, -184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, -199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, -214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, -229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, -244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, -259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, -274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, -289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, -304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, -319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, -334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, -349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, -364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, -379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, -394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, -409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, -424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, -439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, -454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, -469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, -484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, -499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, -514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, -529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 541, 542, 543, 544, -546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 559, 560, 561, -562, 565, 566, 567, 568, 571, 572, 573, 574, 577, 578, 579, 580, 583, 584, -585, 586, 589, 590, 591, 592, 595, 596, 597, 598, 601, 602, 603, 604, 607, -608, 609, 610, 613, 614, 615, 616, 619, 620, 621, 622, 625, 626, 627, 628, -631, 632, 633, 634, 637, 638, 639, 640, 643, 644, 645, 646, 649, 650, 651, -652, 655, 656, 658, 659, 660, 661, 664, 665, 666, 667, 670, 671, 673, 674, -675, 676, 679, 680, 682, 683, 685, 686, 688, 689, 691, 692, 693, 694, 695, -696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, -711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, -726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, -741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, -756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, -771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, -786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, -801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, -816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, -831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, -846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, -861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, -876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, -891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, -906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, -921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, -936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, -951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, -966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, -981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, -996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, -1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, -1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, -1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, -1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, -1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, -1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, -1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, -1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, -1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, -1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, -1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, -1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, -1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, -1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, -1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, -1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, -1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, -1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, -1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, -1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1306, 1307, 1309, 1310, 158, 161, -164, 167, 170, 173, 74, 77, 86, 89, 0, 3, 12, 15, 24, 27, 36, -39, 48, 51, 60, 63, 110, 113, 122, 125, 134, 137, 146, 149, 76, 88, -156, 160, 162, 165, 169, 171, 2, 132, 175, 26, 38, 50, 62, 72, 83, -84, 95, 108, 120, 78, 90, 96, 104, 174, 14, 144, 176, 9, 21, 33, -45, 57, 69, 79, 81, 91, 93, 98, 106, 119, 131, 143, 155, 59, 71, -157, 159, 163, 166, 168, 172, 99, 101, 103, 105, 11, 35, 47, 73, 75, -80, 82, 85, 87, 92, 94, 97, 100, 102, 107, 117, 129, 141, 8, 20, -23, 32, 44, 56, 68, 114, 126, 138, 150, 153, 179, 186, 191, 198, 180, -192, 1, 4, 5, 6, 7, 10, 13, 16, 17, 18, 19, 22, 25, 28, -29, 30, 31, 34, 37, 40, 41, 42, 43, 46, 49, 52, 53, 54, 55, -58, 61, 64, 65, 66, 67, 70, 109, 111, 112, 115, 116, 118, 121, 123, -124, 127, 128, 130, 133, 135, 136, 139, 140, 142, 145, 147, 148, 151, 152, -154, 213, 214, 215, 216, 177, 189, 184, 196, 221, 222, 223, 224, 178, 181, -182, 183, 185, 187, 188, 190, 193, 194, 195, 197, 199, 200, 201, 202, 203, -204, 205, 206, 207, 208, 209, 210, 211, 212, 217, 218, 219, 220, 2, 4, -6, 8, 10, 12, 32, 34, 36, 46, 48, 52, 54, 56, 58, 60, 62, -64, 86, 87, 88, 105, 106, 107, 108, 109, 112, 113, 115, 117, 121, 1, -3, 5, 7, 9, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, -25, 26, 27, 28, 29, 30, 31, 33, 35, 37, 38, 39, 40, 41, 42, -43, 44, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 66, 67, -68, 71, 73, 75, 76, 78, 79, 80, 82, 83, 84, 92, 93, 94, 96, -97, 98, 99, 100, 101, 102, 103, 104, 110, 111, 114, 116, 118, 119, 120, -122, 124, 126, 127, 129, 131, 141, 143, 145, 146, 148, 150, 152, 153, 156, -166, 167, 170, 173, 174, 176, 180, 182, 184, 186, 0, 22, 24, 50, 69, -70, 72, 74, 77, 81, 85, 89, 90, 91, 95, 123, 125, 128, 130, 132, -133, 134, 135, 136, 137, 138, 139, 140, 142, 144, 147, 149, 151, 154, 155, -157, 158, 159, 160, 161, 162, 163, 164, 165, 168, 169, 171, 172, 175, 177, -178, 179, 181, 183, 185, 122, 85, 89, 92, 106, 118, 136, 148, 156, 164, -27, 35, 37, 38, 52, 57, 62, 67, 71, 83, 55, 65, 68, 121, 26, -53, 63, 66, 80, 82, 105, 114, 119, 123, 137, 143, 14, 25, 30, 31, -100, 28, 117, 108, 134, 3, 12, 34, 36, 39, 40, 45, 46, 51, 59, -60, 61, 73, 74, 75, 76, 77, 78, 84, 86, 87, 88, 90, 91, 93, -94, 95, 110, 112, 115, 116, 120, 127, 128, 130, 132, 141, 142, 152, 175, -58, 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 16, -17, 18, 19, 20, 21, 22, 23, 24, 29, 32, 33, 41, 42, 43, 44, -47, 48, 49, 50, 54, 56, 64, 69, 70, 72, 79, 81, 96, 97, 98, -99, 101, 102, 103, 104, 107, 109, 111, 113, 124, 125, 126, 129, 131, 133, -135, 138, 139, 140, 144, 145, 146, 147, 149, 150, 151, 153, 154, 155, 157, -158, 159, 160, 161, 162, 163, 165, 166, 167, 168, 169, 170, 171, 172, 173, -174, 176, 177, 23, 29, 5, 24, 25, 26, 27, 28, 30, 31, 0, 1, -2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -18, 19, 20, 21, 22, 32, 83, 84, 96, 99, 100, 16, 85, 98, 18, -26, 27, 37, 40, 49, 52, 17, 51, 55, 57, 97, 8, 3, 19, 9, -50, 56, 58, 10, 53, 72, 82, 87, 89, 91, 14, 118, 129, 12, 81, -86, 88, 90, 130, 11, 20, 21, 22, 23, 24, 25, 28, 29, 30, 31, -32, 33, 34, 35, 36, 43, 67, 68, 69, 93, 95, 41, 45, 47, 4, -5, 6, 13, 38, 117, 128, 71, 0, 1, 2, 15, 39, 92, 94, 65, -70, 122, 123, 127, 7, 42, 44, 46, 48, 54, 59, 60, 61, 62, 63, -64, 66, 105, 106, 109, 110, 111, 112, 113, 114, 121, 124, 126, 73, 74, -75, 76, 77, 78, 79, 80, 101, 102, 103, 104, 107, 108, 115, 116, 119, -120, 125, 18, 24, 5, 7, 9, 13, 0, 1, 2, 3, 4, 6, 8, -10, 11, 12, 14, 15, 16, 17, 19, 20, 21, 22, 23, 25, 26, 27, -28, 29, 30, 38, 37, 3, 2, 39, 4, 40, 5, 109, 110, 111, 99, -107, 97, 105, 140, 141, 142, 0, 98, 106, 1, 100, 108, 34, 35, 36, -10, 11, 42, 46, 50, 54, 58, 62, 66, 70, 13, 17, 21, 30, 6, -88, 90, 96, 102, 113, 115, 121, 123, 125, 135, 137, 139, 9, 14, 18, -22, 33, 44, 48, 52, 56, 60, 64, 68, 72, 116, 126, 130, 43, 47, -51, 55, 59, 63, 67, 71, 85, 91, 93, 103, 80, 82, 83, 73, 75, -76, 119, 129, 133, 12, 16, 20, 31, 7, 41, 45, 49, 53, 57, 61, -65, 69, 117, 127, 131, 87, 89, 95, 101, 112, 114, 120, 122, 124, 134, -136, 138, 86, 92, 94, 104, 118, 128, 132, 79, 81, 84, 74, 77, 78, -8, 15, 19, 23, 32, 24, 25, 28, 26, 27, 29, 0, 1, 2, 3, -4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, -19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, -34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, -49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, -94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, -109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, -124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, -154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 34, 5, 6, 7, -8, 9, 10, 11, 12, 33, 47, 2, 4, 19, 20, 21, 36, 37, 38, -40, 41, 0, 1, 3, 13, 14, 15, 16, 17, 18, 22, 23, 24, 25, -26, 27, 28, 29, 30, 31, 32, 35, 39, 42, 43, 44, 45, 46, 48, -49, 50, 144, 145, 0, 141, 142, 143, 155, 154, 139, 140, 146, 147, 150, -151, 76, 82, 83, 84, 85, 86, 87, 158, 131, 77, 132, 159, 23, 24, -25, 26, 27, 28, 32, 33, 73, 79, 91, 95, 1, 3, 5, 12, 13, -14, 15, 16, 17, 18, 19, 20, 21, 22, 29, 30, 31, 34, 102, 104, -106, 108, 112, 113, 114, 115, 116, 117, 118, 119, 138, 37, 39, 41, 43, -48, 50, 52, 54, 2, 4, 6, 7, 8, 9, 10, 11, 36, 38, 40, -42, 44, 45, 46, 47, 56, 57, 58, 59, 60, 62, 64, 66, 68, 70, -72, 74, 75, 78, 80, 81, 88, 89, 90, 92, 93, 94, 96, 97, 98, -100, 103, 105, 107, 109, 137, 160, 161, 162, 35, 49, 51, 53, 55, 61, -63, 65, 67, 69, 71, 99, 101, 110, 111, 120, 121, 122, 123, 124, 125, -126, 127, 128, 129, 130, 133, 134, 135, 136, 148, 149, 152, 153, 156, 157, -4, 11, 5, 6, 7, 8, 10, 9, 12, 17, 18, 19, 21, 2, 3, -0, 1, 13, 14, 15, 16, 20, 28, 32, 34, 38, 40, 22, 23, 24, -25, 26, 27, 29, 30, 31, 33, 35, 36, 37, 39, 41, 73, 69, 95, -11, 72, 14, 12, 13, 93, 71, 74, 94, 87, 81, 86, 79, 60, 96, -98, 88, 59, 82, 97, 44, 46, 54, 68, 92, 100, 45, 53, 67, 43, -91, 99, 80, 89, 77, 1, 3, 9, 5, 6, 7, 8, 70, 28, 83, -22, 34, 42, 49, 51, 57, 17, 23, 29, 37, 63, 19, 25, 31, 39, -48, 50, 52, 56, 58, 62, 64, 66, 84, 76, 90, 78, 75, 85, 4, -0, 2, 10, 20, 26, 32, 36, 40, 15, 61, 16, 18, 24, 30, 35, -38, 47, 55, 65, 21, 27, 33, 41, 0, 1, 2, 3, 4, 5, 6, -7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, -22, 23, 24, 25, 26, 40, 42, 3, 1, 51, 5, 49, 48, 22, 24, -4, 2, 52, 50, 76, 78, 80, 94, 96, 98, 23, 47, 26, 27, 63, -64, 65, 70, 71, 21, 77, 79, 81, 17, 20, 33, 37, 41, 43, 57, -55, 56, 58, 59, 60, 61, 62, 18, 19, 25, 32, 36, 95, 97, 99, -0, 38, 39, 54, 67, 69, 73, 75, 85, 87, 91, 93, 53, 66, 84, -86, 90, 89, 6, 7, 11, 12, 13, 82, 83, 68, 72, 74, 92, 8, -9, 10, 14, 15, 16, 28, 29, 30, 31, 34, 35, 44, 45, 46, 88, -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, -45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, -60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, -75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, -105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, -120, 121, 122, 123, 124, 125, 0, 1, 2, 3, 4, 5, 6, 7, 8, -9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, -24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, -39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, -69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -84, 85, 86, 87, 88, 89, 90, 91, 92, 0, 1, 2, 3, 4, 5, -6, 7, 8, 1, 3, 43, 0, 2, 4, 5, 6, 7, 8, 9, 10, -11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -41, 42, 44, 45, 46, 89, 90, 0, 1, 2, 3, 4, 5, 6, 7, -8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, -38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, -53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, -68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, -83, 84, 85, 86, 87, 88, 91, 92, 93, 94, 95, 96, 97, 98, 99, -100, 101, 102, 103, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -26, 27, 28, 29, 30, 31, 0, 1, 2, 3, 4, 5, 6, 7, 8, -9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, -24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, -39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, -69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 186, 189, 174, -185, 179, 180, 177, 181, 188, 191, 60, 63, 175, 183, 176, 184, 64, 61, -62, 65, 178, 182, 187, 190, 130, 142, 154, 166, 104, 110, 116, 13, 24, -36, 78, 122, 136, 148, 160, 172, 7, 18, 30, 84, 102, 108, 114, 105, -111, 117, 120, 123, 74, 86, 98, 107, 113, 119, 125, 1, 9, 20, 32, -44, 45, 55, 75, 99, 103, 109, 115, 0, 6, 19, 31, 42, 43, 54, -72, 73, 85, 96, 97, 137, 149, 161, 173, 2, 46, 47, 56, 76, 77, -100, 101, 127, 133, 139, 145, 151, 157, 163, 169, 8, 21, 33, 87, 106, -112, 118, 121, 124, 128, 129, 140, 141, 152, 153, 3, 4, 15, 26, 38, -48, 49, 50, 51, 57, 58, 66, 67, 68, 69, 80, 90, 91, 92, 93, -126, 131, 134, 138, 143, 146, 150, 155, 158, 162, 167, 170, 10, 11, 22, -23, 34, 35, 88, 89, 135, 147, 159, 171, 5, 12, 14, 16, 17, 25, -27, 28, 29, 37, 39, 40, 41, 52, 53, 59, 70, 71, 79, 81, 82, -83, 94, 95, 132, 144, 156, 164, 165, 168, 756, 759, 761, 104, 105, 640, -647, 700, 107, 757, 760, 102, 222, 224, 310, 420, 431, 441, 460, 468, 491, -494, 501, 558, 571, 654, 666, 683, 722, 7, 10, 31, 34, 60, 65, 162, -165, 178, 434, 467, 477, 480, 550, 569, 657, 671, 682, 718, 751, 13, 37, -54, 175, 181, 262, 265, 313, 385, 465, 551, 563, 641, 645, 701, 719, 253, -316, 333, 339, 364, 365, 369, 371, 436, 439, 461, 496, 499, 505, 514, 520, -522, 577, 585, 588, 598, 601, 608, 617, 622, 685, 727, 733, 223, 240, 191, -709, 92, 115, 144, 199, 248, 252, 290, 307, 338, 372, 382, 410, 475, 508, -513, 515, 527, 547, 566, 567, 572, 580, 587, 590, 595, 604, 606, 615, 619, -688, 716, 725, 730, 735, 739, 747, 11, 16, 22, 23, 35, 40, 46, 47, -52, 53, 59, 64, 88, 89, 94, 103, 118, 121, 124, 138, 143, 149, 163, -164, 179, 184, 190, 202, 205, 208, 225, 244, 245, 250, 259, 268, 280, 281, -284, 285, 291, 322, 328, 332, 340, 373, 379, 388, 400, 401, 404, 405, 411, -421, 426, 428, 429, 437, 442, 450, 455, 457, 469, 478, 481, 488, 497, 502, -529, 530, 536, 537, 540, 553, 564, 570, 625, 626, 630, 635, 637, 643, 655, -656, 668, 670, 678, 681, 691, 692, 699, 703, 704, 724, 738, 749, 750, 753, -560, 574, 723, 85, 331, 470, 101, 217, 633, 642, 697, 742, 745, 754, 19, -43, 48, 187, 324, 97, 218, 296, 416, 130, 137, 166, 226, 241, 271, 279, -319, 327, 391, 399, 440, 482, 142, 283, 325, 403, 443, 453, 485, 758, 0, -24, 67, 298, 336, 346, 464, 489, 504, 507, 510, 516, 518, 521, 523, 524, -535, 552, 559, 573, 576, 579, 582, 583, 591, 592, 594, 599, 602, 603, 607, -611, 614, 616, 620, 623, 632, 644, 649, 651, 661, 663, 667, 669, 684, 687, -696, 708, 720, 726, 729, 732, 736, 1, 2, 3, 4, 5, 6, 8, 9, -12, 14, 15, 17, 18, 20, 21, 25, 26, 27, 28, 29, 30, 32, 33, -36, 38, 39, 41, 42, 44, 45, 49, 50, 51, 55, 56, 57, 58, 61, -62, 63, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, -80, 81, 82, 83, 84, 86, 87, 90, 91, 93, 95, 96, 98, 99, 100, -106, 108, 109, 110, 111, 112, 113, 114, 116, 117, 119, 120, 122, 123, 125, -126, 127, 128, 129, 131, 132, 133, 134, 135, 136, 139, 140, 141, 145, 146, -147, 148, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 167, -168, 169, 170, 171, 172, 173, 174, 176, 177, 180, 182, 183, 185, 186, 188, -189, 192, 193, 194, 195, 196, 197, 198, 200, 201, 203, 204, 206, 207, 209, -210, 211, 212, 213, 214, 215, 216, 219, 220, 221, 227, 228, 229, 230, 231, -232, 233, 234, 235, 236, 237, 238, 239, 242, 243, 246, 247, 249, 251, 254, -255, 256, 257, 258, 260, 261, 263, 264, 266, 267, 269, 270, 272, 273, 274, -275, 276, 277, 278, 282, 286, 287, 288, 289, 292, 293, 294, 295, 297, 299, -300, 301, 302, 303, 304, 305, 306, 308, 309, 311, 312, 314, 315, 317, 318, -320, 321, 323, 326, 329, 330, 334, 335, 337, 341, 342, 343, 344, 345, 347, -348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, -363, 366, 367, 368, 370, 374, 375, 376, 377, 378, 380, 381, 383, 384, 386, -387, 389, 390, 392, 393, 394, 395, 396, 397, 398, 402, 406, 407, 408, 409, -412, 413, 414, 415, 417, 418, 419, 422, 423, 424, 425, 427, 430, 432, 433, -435, 438, 444, 445, 446, 447, 448, 449, 451, 452, 454, 456, 458, 459, 462, -463, 466, 471, 472, 473, 474, 476, 479, 483, 484, 486, 487, 490, 492, 493, -495, 498, 500, 503, 506, 509, 511, 512, 517, 519, 525, 526, 528, 531, 532, -533, 534, 538, 539, 541, 542, 543, 544, 545, 546, 548, 549, 554, 555, 556, -557, 561, 562, 565, 568, 575, 578, 581, 584, 586, 589, 593, 596, 597, 600, -605, 609, 610, 612, 613, 618, 621, 624, 627, 628, 629, 631, 634, 636, 638, -639, 646, 648, 650, 652, 653, 658, 659, 660, 662, 664, 665, 672, 673, 674, -675, 676, 677, 679, 680, 686, 689, 690, 693, 694, 695, 698, 702, 705, 706, -707, 710, 711, 712, 713, 714, 715, 717, 721, 728, 731, 734, 737, 740, 741, -743, 744, 746, 748, 752, 755, 325, 326, 324, 15, 258, 103, 123, 3, 9, -124, 331, 14, 259, 16, 2, 8, 337, 102, 335, 340, 4, 10, 17, 120, -246, 247, 276, 333, 334, 33, 72, 128, 338, 5, 11, 76, 105, 127, 0, -13, 74, 73, 122, 1, 75, 7, 300, 336, 364, 6, 12, 228, 235, 263, -265, 270, 280, 291, 106, 297, 77, 135, 162, 169, 192, 199, 201, 214, 216, -225, 260, 262, 104, 306, 316, 339, 170, 200, 223, 341, 137, 160, 190, 203, -215, 218, 141, 150, 157, 171, 180, 187, 312, 313, 317, 39, 125, 143, 148, -158, 173, 178, 188, 308, 318, 107, 322, 362, 35, 91, 97, 109, 299, 230, -272, 293, 244, 256, 289, 323, 367, 38, 121, 302, 303, 311, 327, 245, 257, -261, 290, 305, 234, 264, 279, 34, 36, 79, 85, 115, 126, 298, 307, 309, -319, 328, 57, 63, 69, 198, 229, 271, 292, 82, 88, 90, 96, 108, 118, -304, 320, 329, 37, 41, 80, 86, 116, 301, 332, 139, 159, 164, 168, 189, -194, 205, 213, 217, 220, 222, 40, 136, 145, 167, 177, 197, 202, 212, 227, -18, 27, 48, 363, 237, 267, 282, 196, 240, 241, 252, 253, 285, 286, 142, -147, 152, 155, 156, 172, 175, 182, 185, 186, 310, 321, 330, 346, 347, 348, -355, 138, 163, 165, 193, 195, 204, 210, 219, 226, 131, 132, 208, 250, 251, -278, 314, 315, 357, 365, 140, 146, 179, 206, 211, 20, 29, 50, 161, 166, -191, 221, 224, 269, 368, 26, 44, 47, 58, 64, 70, 81, 87, 117, 144, -151, 153, 174, 181, 183, 93, 99, 111, 232, 274, 295, 59, 65, 71, 133, -134, 149, 154, 176, 184, 209, 350, 361, 239, 242, 254, 284, 287, 268, 56, -62, 68, 78, 84, 94, 100, 112, 114, 92, 98, 110, 238, 283, 55, 61, -67, 349, 236, 243, 255, 266, 281, 288, 19, 24, 28, 42, 45, 49, 129, -130, 207, 248, 249, 277, 354, 359, 360, 233, 275, 296, 352, 353, 22, 31, -52, 54, 60, 66, 83, 89, 95, 101, 113, 119, 342, 345, 366, 231, 273, -294, 25, 43, 46, 23, 32, 53, 343, 351, 358, 21, 30, 51, 344, 356, -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, -45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, -60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, -75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, -90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, -105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, -120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, -135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, -150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, -165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, -180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, -195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, -210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, -225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, -240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, -255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, -270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, -285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, -300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, -315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, -330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, -345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, -360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, -375, 376, 377, 19, 29, 33, 45, 86, 88, 90, 92, 18, 27, 31, 47, -82, 103, 37, 41, 55, 87, 11, 35, 39, 43, 49, 51, 53, 57, 61, -63, 89, 91, 105, 109, 114, 20, 9, 13, 107, 28, 30, 32, 34, 46, -48, 78, 84, 133, 135, 93, 112, 134, 136, 36, 40, 62, 66, 80, 38, -42, 44, 50, 52, 54, 56, 58, 64, 127, 131, 137, 1, 15, 16, 21, -22, 102, 111, 113, 128, 132, 138, 23, 25, 59, 68, 70, 94, 69, 3, -4, 6, 7, 10, 104, 106, 108, 110, 121, 123, 67, 24, 26, 60, 122, -124, 72, 76, 81, 96, 85, 74, 98, 129, 83, 125, 0, 2, 5, 8, -12, 14, 17, 71, 73, 75, 77, 79, 95, 97, 99, 100, 126, 65, 130, -101, 118, 116, 120, 115, 117, 119, 219, 220, 221, 127, 131, 135, 139, 228, -229, 230, 231, 232, 233, 234, 235, 222, 223, 224, 225, 226, 227, 236, 237, -238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, -253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 275, -276, 277, 278, 9, 13, 17, 21, 25, 29, 36, 40, 44, 48, 49, 56, -60, 64, 68, 72, 76, 80, 84, 171, 176, 180, 184, 0, 1, 2, 3, -4, 5, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20, 22, -23, 24, 26, 27, 28, 30, 31, 32, 33, 34, 35, 37, 38, 39, 41, -42, 43, 45, 46, 47, 50, 51, 52, 53, 54, 55, 57, 58, 59, 61, -62, 63, 65, 66, 67, 69, 70, 71, 73, 74, 75, 77, 78, 79, 81, -82, 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, -98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, -113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 128, -129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 143, 144, 145, 146, -147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, -162, 163, 164, 165, 166, 167, 168, 169, 170, 172, 173, 174, 175, 177, 178, -179, 181, 182, 183, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, -196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, -211, 212, 213, 214, 215, 216, 217, 218, 267, 268, 269, 270, 271, 272, 273, -274, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 1, 2, -3, 4, 0, 8, 12, 11, 102, 127, 6, 5, 101, 7, 128, 4, 3, -10, 1, 2, 0, 9, 92, 90, 97, 114, 94, 95, 99, 112, 111, 123, -116, 118, 120, 121, 125, 98, 89, 91, 96, 93, 100, 113, 24, 34, 16, -36, 14, 22, 13, 21, 33, 18, 26, 30, 115, 117, 124, 119, 122, 126, -17, 25, 29, 104, 19, 27, 31, 106, 28, 20, 32, 15, 23, 35, 54, -56, 110, 51, 72, 88, 38, 40, 49, 58, 60, 64, 66, 74, 81, 105, -107, 37, 39, 50, 52, 57, 59, 63, 65, 71, 73, 82, 87, 42, 43, -45, 48, 61, 67, 70, 76, 77, 79, 83, 86, 53, 55, 41, 44, 46, -47, 62, 68, 69, 75, 78, 80, 84, 85, 109, 103, 108, 7, 8, 6, -9, 17, 10, 28, 26, 24, 50, 68, 4, 34, 5, 0, 23, 46, 2, -18, 33, 1, 85, 19, 58, 62, 70, 29, 31, 35, 3, 25, 27, 47, -48, 49, 51, 11, 90, 30, 32, 36, 40, 41, 42, 43, 44, 45, 12, -13, 14, 15, 16, 20, 21, 22, 37, 38, 39, 52, 53, 54, 55, 56, -57, 59, 60, 61, 63, 64, 65, 66, 67, 69, 71, 72, 73, 74, 75, -76, 77, 78, 79, 80, 81, 82, 83, 84, 86, 87, 88, 89, 88, 125, -101, 103, 124, 127, 134, 135, 25, 29, 37, 45, 165, 177, 163, 180, 138, -142, 113, 24, 28, 36, 40, 41, 44, 48, 49, 58, 59, 60, 61, 66, -67, 68, 69, 70, 71, 72, 73, 89, 92, 93, 145, 148, 149, 94, 105, -109, 151, 154, 161, 173, 96, 99, 100, 102, 104, 107, 108, 111, 114, 115, -116, 118, 119, 120, 122, 123, 126, 132, 133, 136, 137, 140, 141, 155, 156, -159, 160, 164, 169, 171, 172, 175, 176, 179, 181, 182, 183, 0, 1, 2, -3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -18, 19, 20, 21, 22, 23, 26, 27, 30, 31, 32, 33, 34, 35, 38, -39, 42, 43, 46, 47, 50, 51, 52, 53, 54, 55, 56, 57, 62, 63, -64, 65, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, -87, 90, 91, 95, 97, 98, 106, 110, 112, 117, 121, 128, 129, 130, 131, -139, 143, 144, 146, 147, 150, 152, 153, 157, 158, 162, 166, 167, 168, 170, -174, 178, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 0, 1, 2, 3, -4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, -19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, -34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, -49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, -64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, -94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, -109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, -124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, -139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, -154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, -169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, -184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, -199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, -214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, -229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, -244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, -259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, -274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, -289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, -304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, -319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, -334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, -349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, -364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, -379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, -394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, -409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, -424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, -439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, -454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, -469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, -484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, -499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, -514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, -529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, -544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, -559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, -574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, -589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, -604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, -619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, -634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, -649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, -664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, -679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, -694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, -709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, -724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, -739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, -754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, -769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, -784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, -799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, -814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, -829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, -844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, -859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, -874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, -889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, -904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, -919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, -934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, -949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, -964, 965, 966, 967, 968, 969, 970, 971, 306, 146, 158, 174, 216, 233, 27, -29, 121, 123, 125, 127, 144, 150, 152, 173, 188, 218, 295, 299, 307, 0, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 28, 30, 31, 32, -33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, -48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, -78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, -108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 122, 124, -126, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, -142, 143, 145, 147, 148, 149, 151, 153, 154, 155, 156, 157, 159, 160, 161, -162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 175, 176, 177, 178, -179, 180, 181, 182, 183, 184, 185, 186, 187, 189, 190, 191, 192, 193, 194, -195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, -210, 211, 212, 213, 214, 215, 217, 219, 220, 221, 222, 223, 224, 225, 226, -227, 228, 229, 230, 231, 232, 234, 235, 236, 237, 238, 239, 240, 241, 242, -243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, -258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, -273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, -288, 289, 290, 291, 292, 293, 294, 296, 297, 298, 300, 301, 302, 303, 304, -305, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, -322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, -337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, -352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, -367, 368, 369, 370, 371, 372, 373, 374, 76, 106, 77, 107, 125, 115, 126, -60, 61, 71, 59, 96, 99, 110, 89, 70, 58, 25, 27, 33, 35, 86, -87, 72, 75, 79, 94, 112, 95, 100, 73, 74, 78, 101, 102, 105, 109, -88, 26, 32, 34, 103, 104, 108, 24, 97, 98, 113, 114, 44, 64, 69, -36, 38, 41, 43, 47, 54, 57, 63, 66, 111, 37, 39, 40, 42, 45, -46, 55, 56, 62, 65, 67, 68, 90, 92, 5, 11, 9, 84, 8, 4, -10, 2, 48, 50, 52, 81, 82, 0, 6, 12, 14, 85, 80, 83, 49, -51, 53, 91, 93, 118, 121, 124, 3, 17, 18, 21, 22, 29, 30, 1, -7, 13, 15, 116, 119, 122, 129, 16, 19, 20, 23, 28, 31, 117, 120, -123, 127, 128, 130, 3, 4, 5, 6, 25, 26, 27, 28, 29, 33, 41, -54, 61, 62, 99, 101, 105, 106, 107, 108, 133, 134, 0, 7, 30, 83, -86, 87, 88, 90, 91, 92, 93, 135, 136, 137, 1, 2, 31, 32, 34, -100, 102, 103, 104, 119, 132, 138, 139, 140, 16, 21, 22, 23, 24, 44, -51, 64, 65, 66, 67, 69, 71, 72, 73, 74, 75, 76, 8, 9, 10, -11, 12, 13, 14, 15, 35, 36, 42, 43, 46, 48, 49, 50, 52, 60, -63, 77, 78, 79, 80, 81, 82, 85, 89, 94, 95, 96, 97, 98, 109, -110, 111, 112, 113, 114, 115, 120, 121, 17, 18, 19, 20, 37, 38, 39, -40, 45, 47, 53, 55, 56, 57, 58, 59, 68, 70, 84, 116, 117, 118, -122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 141, 142, 143, 144, 145, -146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, -161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, -176, 177, 178, 179, 180, 181, 182, 49, 18, 16, 17, 42, 45, 15, 8, -46, 39, 6, 48, 7, 9, 10, 41, 44, 5, 40, 43, 30, 47, 51, -52, 25, 19, 20, 21, 22, 23, 24, 3, 4, 29, 31, 32, 33, 34, -35, 36, 37, 38, 71, 73, 11, 12, 13, 14, 50, 70, 0, 1, 2, -26, 27, 28, 60, 62, 69, 61, 63, 64, 65, 72, 75, 76, 54, 55, -56, 57, 58, 59, 66, 68, 81, 82, 83, 84, 86, 74, 53, 67, 77, -78, 79, 80, 85, 87, 88, 0, 1, 2, 3, 4, 5, 6, 7, 8, -9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, -24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, -39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, -69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, -99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, -114, 115, 116, 117, 118, 119, 120, 121, 122, 0, 1, 2, 3, 4, 5, -6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -21, 100, 31, 35, 41, 33, 30, 34, 40, 82, 81, 103, 47, 32, 15, -99, 46, 9, 21, 8, 69, 65, 67, 14, 62, 57, 58, 60, 80, 56, -20, 11, 97, 10, 85, 86, 1, 22, 26, 36, 16, 17, 78, 79, 105, -108, 5, 24, 28, 38, 44, 45, 59, 61, 63, 70, 109, 111, 0, 4, -25, 29, 39, 50, 51, 54, 55, 71, 72, 73, 74, 75, 76, 77, 95, -96, 101, 102, 104, 110, 98, 18, 19, 83, 84, 89, 23, 27, 37, 42, -43, 48, 113, 2, 3, 6, 7, 12, 13, 49, 52, 53, 87, 88, 90, -91, 92, 93, 94, 106, 107, 112, 64, 66, 68, 5, 4, 0, 39, 48, -17, 8, 6, 7, 77, 78, 75, 76, 79, 80, 16, 15, 73, 56, 55, -74, 40, 41, 42, 60, 9, 10, 11, 12, 13, 14, 59, 43, 62, 1, -2, 3, 44, 61, 58, 68, 22, 23, 28, 35, 36, 45, 46, 47, 57, -67, 69, 70, 71, 19, 18, 20, 21, 24, 25, 26, 27, 29, 30, 31, -32, 33, 34, 37, 38, 49, 50, 51, 52, 53, 54, 63, 64, 65, 66, -72, 81, 82, 83, 84, 34, 44, 71, 32, 43, 30, 35, 72, 33, 11, -10, 39, 37, 13, 38, 42, 36, 12, 41, 31, 8, 9, 40, 50, 69, -55, 20, 24, 28, 135, 1, 5, 15, 136, 70, 46, 51, 114, 115, 45, -3, 7, 17, 113, 116, 54, 128, 129, 134, 138, 0, 4, 14, 26, 19, -23, 27, 48, 62, 63, 68, 123, 124, 125, 126, 131, 132, 29, 49, 59, -60, 66, 127, 130, 133, 86, 110, 119, 57, 58, 65, 83, 87, 103, 111, -122, 18, 22, 82, 102, 61, 64, 67, 21, 25, 52, 2, 6, 16, 75, -76, 85, 90, 95, 99, 100, 109, 120, 56, 73, 74, 77, 78, 79, 80, -81, 84, 88, 89, 91, 92, 93, 94, 96, 97, 98, 101, 104, 105, 106, -107, 108, 112, 117, 118, 121, 137, 47, 53, 4, 5, 0, 1, 2, 3, -7, 8, 6, 9, 10, 20, 25, 27, 18, 19, 21, 23, 24, 26, 28, -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -15, 16, 17, 22, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -40, 41, 76, 96, 112, 109, 110, 94, 95, 49, 73, 56, 61, 65, 68, -102, 30, 37, 38, 40, 41, 44, 45, 47, 48, 55, 57, 59, 60, 79, -82, 88, 89, 90, 91, 92, 98, 100, 105, 108, 111, 0, 1, 2, 3, -4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, -19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, -35, 36, 39, 42, 43, 46, 50, 51, 52, 53, 54, 58, 62, 63, 64, -66, 67, 69, 70, 71, 72, 74, 75, 77, 78, 80, 81, 83, 84, 85, -86, 87, 93, 97, 99, 101, 103, 104, 106, 107, 113, 91, 42, 46, 77, -26, 8, 78, 41, 43, 44, 47, 68, 5, 30, 45, 89, 90, 48, 49, -50, 51, 25, 76, 93, 14, 70, 88, 4, 23, 24, 29, 59, 63, 75, -79, 92, 97, 0, 1, 2, 6, 7, 15, 16, 17, 20, 21, 27, 31, -32, 33, 34, 35, 36, 62, 64, 67, 72, 61, 66, 71, 86, 94, 12, -74, 55, 58, 60, 81, 83, 3, 9, 10, 11, 13, 18, 19, 22, 28, -37, 38, 39, 40, 53, 56, 65, 69, 73, 82, 84, 85, 52, 54, 57, -80, 87, 95, 96, 1, 8, 10, 13, 12, 6, 2, 0, 11, 9, 5, -25, 7, 19, 43, 44, 45, 32, 33, 34, 50, 51, 52, 26, 22, 23, -3, 4, 28, 15, 36, 37, 49, 30, 31, 29, 14, 20, 21, 24, 27, -17, 39, 46, 16, 35, 53, 38, 40, 41, 42, 18, 47, 48, 0, 1, -2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, -47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, -77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, -92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, -107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, -122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 49, 310, 312, -314, 269, 271, 273, 275, 277, 279, 281, 297, 299, 0, 1, 2, 3, 4, -5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, -35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50, -51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, -66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, -81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, -96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, -111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, -126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, -141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, -156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, -171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, -186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, -201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, -216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, -231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, -246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, -261, 262, 263, 264, 265, 266, 267, 268, 270, 272, 274, 276, 278, 280, 282, -283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 298, -300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 311, 313, 315, 316, 317, -318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, -333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, -348, 349, 350, 351, 352, 353, 354, 355, 179, 200, 161, 175, 243, 100, 104, -196, 198, 223, 227, 176, 203, 212, 215, 162, 163, 247, 160, 174, 216, 218, -158, 172, 96, 157, 166, 170, 197, 199, 217, 219, 159, 173, 178, 201, 99, -101, 103, 105, 177, 202, 213, 214, 98, 102, 92, 108, 112, 116, 120, 124, -128, 132, 184, 192, 208, 180, 188, 204, 239, 249, 221, 225, 154, 165, 169, -51, 53, 55, 57, 59, 63, 67, 71, 75, 79, 83, 87, 95, 119, 123, -127, 131, 138, 142, 146, 150, 183, 191, 207, 236, 241, 245, 250, 61, 65, -69, 73, 77, 81, 85, 89, 93, 109, 113, 117, 140, 144, 148, 152, 8, -9, 14, 15, 20, 21, 50, 52, 54, 56, 91, 107, 111, 115, 121, 125, -129, 133, 134, 135, 136, 137, 141, 145, 149, 153, 155, 164, 168, 181, 187, -189, 195, 205, 211, 58, 62, 66, 70, 74, 78, 82, 86, 118, 122, 126, -130, 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 16, 17, -18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, -35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, -60, 64, 68, 72, 76, 80, 84, 88, 139, 143, 147, 151, 186, 194, 210, -222, 226, 238, 242, 246, 248, 94, 97, 156, 167, 171, 228, 230, 90, 106, -110, 114, 220, 224, 237, 240, 244, 251, 182, 185, 190, 193, 206, 209, 229, -231, 232, 233, 234, 235, 24, 51, 54, 111, 25, 52, 55, 112, 13, 31, -34, 37, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 26, 27, 28, 29, 30, -32, 33, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, -49, 50, 53, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, -68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, -83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, -98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 113, 114, -115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, -130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 0, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -16, 17, 8, 16, 18, 7, 26, 30, 34, 104, 14, 15, 17, 19, 22, -48, 68, 73, 75, 79, 11, 1, 6, 20, 28, 32, 36, 38, 40, 44, -98, 102, 103, 105, 106, 115, 2, 13, 21, 23, 49, 53, 54, 55, 56, -57, 58, 60, 61, 64, 66, 67, 69, 76, 83, 85, 95, 100, 10, 0, -3, 4, 5, 9, 12, 24, 25, 27, 29, 31, 33, 35, 37, 39, 41, -42, 43, 45, 46, 47, 50, 51, 52, 59, 62, 63, 65, 70, 71, 72, -74, 77, 78, 80, 81, 82, 84, 86, 87, 88, 89, 90, 91, 92, 93, -94, 96, 97, 99, 101, 107, 108, 109, 110, 111, 112, 113, 114, 116, 117, -118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 121, 120, 103, 101, 102, -86, 111, 124, 27, 44, 100, 10, 13, 82, 92, 98, 78, 88, 94, 42, -40, 9, 11, 12, 14, 80, 84, 90, 96, 45, 119, 122, 46, 48, 50, -52, 104, 106, 109, 110, 1, 4, 18, 25, 29, 32, 19, 34, 22, 5, -8, 38, 107, 39, 16, 17, 21, 26, 30, 33, 43, 87, 125, 41, 83, -93, 99, 2, 24, 28, 31, 35, 53, 55, 81, 91, 97, 105, 0, 3, -7, 6, 15, 20, 23, 36, 37, 47, 49, 51, 54, 56, 57, 58, 59, -60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, -75, 76, 77, 79, 85, 89, 95, 108, 112, 113, 114, 115, 116, 117, 118, -123, 161, 57, 60, 95, 169, 165, 171, 0, 160, 40, 168, 164, 39, 58, -59, 96, 1, 2, 50, 55, 64, 75, 85, 92, 97, 71, 77, 81, 87, -6, 16, 30, 44, 181, 170, 49, 56, 63, 76, 86, 91, 98, 174, 180, -5, 15, 29, 43, 72, 78, 82, 88, 113, 126, 194, 195, 198, 158, 159, -162, 163, 114, 125, 144, 145, 166, 167, 192, 193, 156, 47, 48, 51, 52, -53, 54, 61, 62, 65, 66, 83, 84, 89, 90, 93, 94, 99, 100, 101, -102, 103, 104, 130, 131, 132, 133, 134, 135, 152, 175, 176, 177, 67, 69, -73, 79, 105, 3, 4, 7, 8, 13, 14, 17, 18, 19, 20, 25, 26, -27, 28, 31, 32, 33, 34, 37, 38, 41, 42, 45, 46, 68, 70, 74, -80, 106, 117, 118, 142, 143, 178, 179, 138, 9, 140, 147, 148, 107, 109, -111, 139, 141, 146, 149, 182, 183, 184, 185, 190, 191, 115, 119, 121, 123, -137, 155, 157, 187, 189, 197, 10, 11, 12, 21, 22, 23, 24, 35, 36, -108, 110, 112, 116, 120, 122, 124, 127, 128, 129, 136, 150, 151, 153, 154, -173, 186, 188, 196, 172, 37, 36, 33, 32, 35, 34, 4, 2, 6, 0, -44, 45, 47, 46, 42, 43, 39, 41, 40, 38, 5, 7, 3, 1, 51, -17, 11, 15, 19, 9, 13, 10, 14, 18, 16, 23, 24, 27, 28, 31, -8, 12, 20, 22, 21, 25, 26, 29, 30, 49, 48, 50, 179, 176, 165, -178, 171, 175, 174, 177, 162, 168, 190, 188, 202, 200, 33, 75, 93, 51, -81, 87, 173, 164, 157, 114, 3, 6, 156, 15, 21, 27, 170, 167, 123, -63, 69, 39, 45, 57, 199, 211, 172, 208, 205, 214, 181, 184, 203, 196, -169, 198, 201, 160, 161, 137, 163, 125, 209, 119, 183, 215, 166, 207, 204, -213, 197, 191, 206, 210, 182, 212, 187, 185, 53, 83, 89, 192, 186, 193, -136, 180, 194, 130, 142, 154, 155, 148, 149, 131, 143, 116, 32, 74, 92, -122, 101, 107, 110, 113, 98, 104, 71, 65, 41, 47, 59, 2, 11, 14, -20, 26, 195, 189, 147, 150, 151, 145, 133, 127, 139, 126, 138, 132, 144, -117, 159, 52, 82, 88, 158, 120, 96, 102, 108, 99, 105, 111, 30, 72, -90, 8, 5, 9, 0, 124, 97, 103, 109, 12, 18, 24, 48, 78, 84, -66, 60, 70, 62, 35, 77, 95, 68, 42, 50, 80, 86, 17, 23, 29, -36, 54, 38, 44, 56, 152, 153, 64, 40, 58, 46, 128, 140, 129, 134, -135, 141, 146, 106, 100, 112, 121, 7, 4, 115, 118, 34, 61, 76, 94, -16, 22, 28, 37, 43, 55, 49, 79, 85, 67, 1, 13, 19, 25, 31, -73, 91, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, -27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, -42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, -72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, -87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, -102, 103, 104, 105, 106, 107, 108, 109, 110, 2, 5, 8, 11, 14, 17, -20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, -65, 68, 0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, -19, 21, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, -42, 43, 45, 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, -64, 66, 67, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -53, 52, 72, 71, 73, 70, 97, 98, 96, 99, 68, 80, 82, 74, 77, -78, 5, 22, 25, 41, 49, 1, 9, 17, 95, 103, 102, 104, 75, 76, -79, 66, 69, 93, 67, 94, 81, 83, 84, 85, 86, 87, 88, 89, 90, -91, 106, 107, 92, 100, 101, 105, 32, 34, 38, 12, 15, 54, 58, 62, -39, 14, 36, 57, 61, 65, 31, 35, 47, 29, 45, 42, 28, 44, 30, -46, 18, 16, 55, 59, 63, 40, 21, 26, 50, 3, 7, 11, 19, 0, -4, 8, 33, 37, 20, 23, 24, 27, 43, 48, 51, 2, 6, 10, 13, -56, 60, 64, 0, 2, 1, 11, 5, 6, 12, 3, 4, 9, 10, 14, -7, 8, 13, 21, 36, 18, 23, 24, 25, 26, 27, 28, 29, 30, 31, -32, 33, 34, 35, 37, 15, 16, 22, 17, 19, 20, 0, 1, 0, 1, -2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 48, 5, 34, 63, -4, 62, 50, 47, 49, 33, 35, 36, 29, 3, 6, 61, 64, 54, 58, -45, 32, 51, 56, 60, 70, 57, 40, 46, 11, 55, 59, 44, 53, 65, -72, 14, 15, 17, 20, 22, 27, 66, 68, 69, 71, 26, 19, 67, 1, -9, 12, 7, 25, 24, 28, 30, 31, 10, 8, 16, 18, 21, 23, 52, -0, 2, 41, 42, 43, 13, 37, 38, 39, 107, 15, 97, 100, 101, 105, -99, 33, 81, 79, 80, 34, 92, 95, 86, 48, 118, 41, 43, 119, 35, -36, 37, 75, 102, 103, 104, 23, 24, 25, 26, 31, 4, 17, 19, 21, -22, 27, 38, 39, 52, 56, 58, 64, 70, 72, 82, 47, 87, 51, 55, -57, 77, 78, 98, 116, 117, 28, 29, 30, 32, 40, 42, 5, 7, 9, -93, 96, 1, 2, 3, 6, 8, 10, 12, 54, 59, 65, 66, 68, 69, -71, 73, 74, 76, 83, 84, 89, 90, 106, 109, 111, 112, 114, 44, 45, -46, 49, 50, 11, 53, 16, 18, 20, 0, 13, 14, 60, 61, 62, 63, -67, 85, 88, 91, 94, 108, 110, 113, 115, 13, 4, 46, 47, 2, 6, -37, 38, 43, 51, 54, 55, 58, 67, 69, 0, 1, 3, 5, 7, 8, -9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 39, 40, 41, -42, 44, 45, 48, 49, 50, 52, 53, 56, 57, 59, 60, 61, 62, 63, -64, 65, 66, 68, 70, 71, 72, 73, 74, 75, 7, 4, 6, 5, 2, -3, 9, 8, 0, 1, 23, 22, 24, 25, 14, 26, 30, 34, 10, 11, -12, 13, 15, 16, 17, 18, 19, 20, 21, 27, 28, 29, 31, 32, 33, -35, 36, 37, 0, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -25, 26, 27, 28, 29, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, -55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, -70, 71, 72, 73, 0, 1, 2, 3, 4, 4, 0, 1, 2, 3, 5, -6, 7, 8, 0, 1, 2, 3, 4, 5, 323, 139, 149, 165, 207, 234, -320, 296, 300, 20, 44, 45, 52, 138, 147, 189, 191, 192, 193, 210, 213, -215, 217, 226, 232, 236, 238, 293, 322, 325, 74, 122, 306, 150, 264, 4, -5, 197, 201, 117, 172, 188, 195, 203, 222, 244, 245, 265, 271, 291, 292, -332, 2, 18, 19, 22, 34, 46, 57, 82, 84, 85, 88, 89, 120, 130, -133, 134, 136, 137, 140, 142, 143, 145, 146, 148, 153, 159, 160, 161, 162, -166, 169, 173, 184, 185, 209, 211, 219, 228, 229, 231, 237, 240, 242, 243, -246, 247, 248, 251, 253, 254, 257, 286, 294, 298, 324, 335, 33, 98, 118, -200, 204, 303, 305, 327, 100, 196, 205, 275, 123, 126, 282, 0, 1, 3, -6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 21, 23, 24, -25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 37, 38, 39, 40, 41, -42, 43, 47, 48, 49, 50, 51, 53, 54, 55, 56, 58, 59, 60, 61, -62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 75, 76, 77, -78, 79, 80, 81, 83, 86, 87, 90, 91, 92, 93, 94, 95, 96, 97, -99, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, -115, 116, 119, 121, 124, 125, 127, 128, 129, 131, 132, 135, 141, 144, 151, -152, 154, 155, 156, 157, 158, 163, 164, 167, 168, 170, 171, 174, 175, 176, -177, 178, 179, 180, 181, 182, 183, 186, 187, 190, 194, 198, 199, 202, 206, -208, 212, 214, 216, 218, 220, 221, 223, 224, 225, 227, 230, 233, 235, 239, -241, 249, 250, 252, 255, 256, 258, 259, 260, 261, 262, 263, 266, 267, 268, -269, 270, 272, 273, 274, 276, 277, 278, 279, 280, 281, 283, 284, 285, 287, -288, 289, 290, 295, 297, 299, 301, 302, 304, 307, 308, 309, 310, 311, 312, -313, 314, 315, 316, 317, 318, 319, 321, 326, 328, 329, 330, 331, 333, 334, -336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, -351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, 1, -2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, -47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, -77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, -92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, -107, 108, 109, 4, 5, 18, 20, 0, 1, 2, 3, 6, 7, 8, 9, -10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 22, 23, 24, 25, 26, -0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, -55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, -70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, -85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, -100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, -115, 116, 117, 118, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, -56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, -71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, -86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, -101, 102, 103, 104, 105, 106, 107, 38, 40, 39, 65, 63, 66, 26, 28, -11, 20, 24, 32, 108, 8, 47, 45, 48, 49, 105, 109, 139, 75, 124, -18, 22, 30, 34, 111, 102, 114, 118, 77, 123, 133, 1, 5, 17, 46, -69, 73, 81, 29, 78, 101, 37, 50, 64, 9, 51, 55, 61, 76, 68, -72, 84, 2, 6, 14, 19, 23, 35, 67, 71, 79, 83, 107, 113, 115, -117, 137, 147, 36, 10, 27, 53, 57, 59, 135, 13, 103, 104, 126, 3, -7, 15, 41, 44, 54, 58, 60, 70, 74, 80, 82, 0, 4, 12, 16, -21, 25, 31, 33, 42, 43, 52, 56, 62, 85, 88, 91, 94, 106, 110, -112, 116, 119, 120, 121, 122, 125, 127, 128, 129, 130, 131, 132, 134, 136, -138, 140, 141, 142, 143, 144, 145, 146, 148, 89, 86, 87, 90, 92, 93, -95, 96, 97, 98, 99, 100, 0, 1, 2, 3, 4, 5, 6, 7, 8, -9, 10, 11, 12, 1, 2, 4, 32, 36, 38, 3, 34, 28, 31, 35, -37, 6, 12, 14, 19, 20, 22, 33, 39, 43, 53, 54, 55, 56, 57, -61, 67, 69, 70, 71, 30, 0, 5, 7, 8, 9, 10, 11, 13, 15, -16, 17, 18, 21, 23, 24, 25, 26, 27, 29, 40, 41, 42, 44, 45, -46, 47, 48, 49, 50, 51, 52, 58, 59, 60, 62, 63, 64, 65, 66, -68, 72, 16, 28, 34, 38, 42, 2, 14, 15, 18, 19, 26, 29, 30, -31, 32, 33, 40, 43, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, -11, 12, 13, 17, 20, 21, 22, 23, 24, 25, 27, 35, 36, 37, 39, -41, 2, 0, 7, 1, 86, 5, 74, 21, 89, 85, 88, 3, 4, 6, -51, 23, 111, 70, 56, 90, 98, 27, 78, 53, 68, 80, 87, 116, 12, -25, 109, 114, 103, 108, 110, 9, 57, 62, 65, 91, 96, 99, 69, 71, -72, 73, 81, 49, 50, 52, 93, 101, 36, 55, 64, 125, 19, 20, 22, -106, 41, 8, 11, 13, 29, 34, 37, 54, 102, 107, 118, 123, 126, 14, -15, 16, 18, 82, 83, 84, 92, 97, 100, 104, 112, 17, 32, 121, 94, -24, 113, 76, 77, 79, 10, 61, 95, 26, 28, 30, 31, 35, 38, 39, -40, 46, 58, 59, 60, 63, 66, 67, 75, 105, 115, 117, 119, 120, 124, -127, 128, 33, 42, 43, 44, 45, 47, 48, 122, 0, 1, 2, 3, 4, -5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 2, 0, 1, 3, 4, -5, 6, 7, 8, 82, 11, 26, 19, 75, 6, 9, 47, 54, 66, 73, -80, 87, 0, 3, 4, 5, 18, 23, 24, 25, 44, 53, 62, 63, 65, -67, 68, 69, 70, 72, 76, 77, 86, 88, 89, 90, 91, 92, 93, 22, -10, 15, 21, 49, 58, 50, 59, 83, 1, 2, 7, 8, 12, 13, 14, -16, 17, 20, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, -39, 40, 41, 42, 43, 45, 46, 48, 51, 52, 55, 56, 57, 60, 61, -64, 71, 74, 78, 79, 81, 84, 85, 0, 1, 0, 1, 34, 2, 12, -13, 32, 37, 76, 3, 10, 11, 19, 20, 21, 22, 23, 27, 28, 29, -30, 35, 53, 55, 78, 4, 16, 17, 5, 6, 7, 8, 9, 14, 15, -18, 24, 25, 26, 31, 33, 36, 38, 39, 40, 41, 42, 43, 44, 45, -46, 47, 48, 49, 50, 51, 52, 54, 56, 57, 58, 59, 60, 61, 62, -63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 79, -80, 81, 82, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -12, 13, 14, 15, 5, 30, 31, 0, 1, 2, 3, 4, 6, 7, 8, -9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, -24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 59, 0, 1, -2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, -48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 60, 61, 62, 63, -64, 65, 36, 61, 20, 1, 19, 126, 127, 60, 56, 33, 34, 35, 21, -22, 52, 59, 67, 71, 72, 63, 65, 66, 32, 45, 57, 84, 91, 114, -125, 64, 0, 2, 3, 68, 70, 73, 26, 46, 53, 54, 55, 58, 115, -131, 74, 12, 96, 97, 99, 41, 42, 44, 49, 50, 75, 80, 83, 85, -103, 106, 107, 108, 109, 110, 111, 112, 113, 116, 117, 118, 119, 120, 124, -13, 62, 76, 77, 78, 86, 128, 129, 94, 23, 24, 25, 27, 28, 29, -30, 31, 37, 38, 39, 40, 43, 47, 48, 51, 4, 5, 6, 7, 8, -9, 10, 11, 14, 15, 16, 17, 18, 69, 79, 81, 82, 87, 88, 89, -90, 92, 93, 95, 98, 100, 101, 102, 104, 105, 121, 122, 123, 130, 132, -3, 2, 10, 11, 1, 4, 6, 8, 5, 7, 9, 0, 31, 30, 15, -43, 49, 53, 57, 45, 12, 13, 16, 18, 32, 34, 36, 14, 33, 35, -37, 21, 23, 17, 19, 20, 22, 24, 25, 26, 27, 28, 29, 42, 48, -52, 56, 38, 41, 44, 46, 50, 54, 39, 40, 47, 51, 55, 35, 36, -3, 5, 7, 9, 11, 2, 17, 30, 34, 14, 20, 23, 4, 6, 13, -16, 18, 19, 22, 24, 25, 31, 32, 33, 8, 10, 12, 15, 21, 0, -1, 26, 27, 28, 29, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -40, 41, 42, 43, 44, 45, 46, 47, 5, 4, 6, 21, 0, 3, 18, -16, 15, 17, 9, 12, 20, 7, 14, 19, 8, 10, 11, 13, 1, 2, -167, 168, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, -43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, -73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, -103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, -118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, -133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, -148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, -163, 164, 165, 166, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, -2, 3, 7, 6, 8, 9, 16, 2, 18, 19, 28, 27, 24, 25, 26, -17, 3, 20, 22, 21, 23, 13, 0, 4, 14, 1, 5, 12, 10, 11, -15, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 12, 13, -14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, -9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, -24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, -39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, -69, 70, 71, 72, 73, 18, 22, 28, 35, 53, 54, 57, 59, 0, 1, -2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -17, 19, 20, 21, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, -36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, -51, 52, 55, 56, 58, 9, 13, 4, 6, 11, 15, 8, 12, 5, 7, -10, 14, 2, 3, 0, 1, 0, 3, 4, 7, 1, 2, 5, 6, 8, -9, 10, 0, 1, 2, 65, 64, 66, 52, 46, 49, 53, 59, 44, 48, -45, 57, 34, 25, 26, 27, 36, 56, 24, 43, 47, 0, 1, 2, 3, -4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, -19, 20, 21, 22, 23, 28, 29, 30, 31, 32, 33, 35, 37, 38, 39, -40, 41, 42, 50, 51, 54, 55, 58, 60, 61, 62, 63, 0, 1, 2, -3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, -48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, -78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, -108, 109, 110, 111, 112, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -40, 41, 42, 43, 44, 45, 46, 47, 48, 0, 1, 2, 3, 4, 5, -6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -21, 22, 23, 24, 25, 26, 0, 1, 2, 3, 4, 5, 6, 7, 8, -9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, -24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, -39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, -69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, -99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, -114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, -129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, -144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, -159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, -174, 175, 84, 86, 5, 16, 18, 21, 81, 82, 3, 6, 10, 12, 14, -22, 24, 26, 29, 39, 41, 42, 54, 56, 58, 60, 62, 75, 0, 1, -2, 4, 7, 8, 9, 11, 13, 15, 17, 19, 20, 23, 25, 27, 28, -30, 31, 32, 33, 34, 35, 36, 37, 38, 40, 43, 44, 45, 46, 47, -48, 49, 50, 51, 52, 53, 55, 57, 59, 61, 63, 64, 65, 66, 67, -68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 83, 85, 0, -2, 4, 6, 14, 16, 18, 20, 8, 31, 10, 11, 24, 25, 28, 29, -32, 33, 36, 38, 40, 41, 44, 45, 9, 30, 1, 3, 5, 7, 12, -13, 15, 17, 19, 21, 22, 23, 26, 27, 34, 35, 37, 39, 42, 43, -46, 47, 27, 28, 35, 36, 45, 46, 13, 14, 59, 60, 0, 1, 2, -3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, -20, 21, 22, 23, 24, 25, 26, 29, 30, 31, 32, 33, 34, 37, 38, -39, 40, 41, 42, 43, 44, 47, 48, 49, 50, 51, 52, 53, 54, 55, -56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, -73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, -103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, -118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, -133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, -148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, -163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, -178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, -193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, -208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, -223, 224, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -13, 14, 15, 16, 17, 0, 4, 1, 2, 3, 7, 5, 9, 6, 8, -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -30, 31, 32, 33, 34, 35, 36, 37, 8, 11, 9, 10, 0, 1, 4, -5, 2, 3, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 11, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, -27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, -42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, -57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, -72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, -87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, -102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, -117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, -132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, -147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, -162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, -177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, -207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, -222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, -237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, -252, 253, 254, 255, 256, 257, 0, 1, 2, 3, 4, 5, 6, 7, 8, -9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, -35, 1, 2, 20, 29, 32, 33, 34, 0, 3, 4, 5, 6, 7, 8, -9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, -25, 26, 27, 28, 30, 31, 36, 37, 38, 39, 40, 41, 42, 43, 44, -45, 46, 47, 48, 49, 50, 51, 52, 53, 0, 1, 2, 3, 4, 5, -6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -36, 37, 38, 39, 40, 0, 1, 0, 1, 2, 3, 4, 5, 0, 1, -2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, -47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, -77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, -92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, -107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, -122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, -137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, -152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, -167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, -182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, -197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, -212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, -227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, -242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, -257, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, -29, 0, 1, 4, 27, 19, 21, 5, 18, 6, 8, 10, 11, 12, 14, -15, 16, 17, 20, 0, 1, 2, 3, 7, 9, 13, 22, 23, 24, 25, -26, 28, 29, 30, 31, 32, 33, 34, 35, 0, 1, 2, 3, 4, 0, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -16, 17, 18, 19, 112, 110, 113, 111, 29, 37, 18, 93, 96, 97, 99, -98, 92, 100, 104, 105, 108, 101, 61, 62, 69, 77, 86, 70, 78, 85, -68, 76, 87, 60, 54, 55, 59, 30, 38, 73, 81, 90, 94, 19, 14, -16, 71, 79, 84, 50, 51, 57, 0, 2, 4, 6, 8, 10, 12, 20, -26, 34, 44, 64, 72, 80, 91, 40, 63, 13, 5, 7, 9, 11, 15, -1, 3, 39, 21, 48, 49, 56, 95, 74, 82, 89, 31, 25, 33, 45, -65, 43, 103, 106, 107, 109, 17, 52, 53, 58, 28, 36, 41, 23, 27, -35, 47, 42, 66, 22, 24, 32, 46, 67, 75, 83, 88, 102, 6, 7, -0, 1, 3, 5, 2, 4, 50, 48, 52, 54, 56, 2, 6, 14, 18, -22, 26, 30, 34, 49, 53, 55, 57, 58, 59, 60, 0, 1, 3, 4, -5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 19, 20, 21, 23, -24, 25, 27, 28, 29, 31, 32, 33, 35, 36, 37, 38, 39, 40, 41, -42, 43, 44, 45, 46, 47, 51, 23, 24, 25, 26, 16, 18, 20, 22, -15, 17, 19, 21, 6, 8, 10, 12, 14, 0, 2, 1, 3, 4, 5, -11, 7, 9, 13, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, -56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, -71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, -86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, -101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, -116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, -131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 1, 0, -2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, -2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, -47, 48, 49, 50, 51, 52, 53, 54, 55, 0, 1, 2, 3, 4, 5, -6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 112, 114, 19, 61, 70, -18, 111, 3, 5, 6, 66, 82, 109, 110, 113, 58, 102, 104, 31, 35, -36, 37, 38, 71, 77, 86, 93, 95, 96, 108, 47, 25, 45, 46, 53, -55, 75, 40, 41, 42, 52, 60, 83, 84, 24, 26, 11, 12, 22, 23, -28, 30, 57, 63, 65, 69, 81, 90, 106, 32, 33, 34, 49, 50, 51, -72, 73, 78, 79, 87, 88, 94, 4, 7, 8, 9, 10, 20, 21, 29, -39, 43, 44, 48, 54, 56, 59, 62, 64, 67, 68, 74, 76, 80, 89, -91, 92, 100, 101, 115, 116, 16, 99, 13, 14, 15, 17, 27, 85, 97, -98, 103, 105, 107, 117, 7, 10, 19, 0, 1, 2, 3, 4, 5, 6, -8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 0, 1, 2, 3, 4, -5, 7, 17, 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, -13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 0, 1, 0, 7, 11, -5, 6, 10, 3, 4, 1, 2, 8, 9, 12, 0, 1, 2, 3, 4, -0, 1, 2, 3, 4, 1, 3, 0, 2, 4, 5, 6, 7, 8, 9, -10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4, -5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, -35, 36, 0, 1, 75, 78, 76, 15, 79, 77, 8, 85, 14, 0, 4, -10, 81, 83, 84, 87, 12, 80, 82, 11, 9, 2, 6, 86, 36, 38, -37, 13, 1, 5, 3, 7, 49, 22, 24, 28, 32, 50, 58, 63, 66, -71, 23, 25, 29, 33, 47, 48, 51, 52, 53, 54, 46, 17, 19, 16, -20, 21, 26, 27, 30, 31, 34, 35, 39, 40, 41, 42, 43, 44, 45, -55, 56, 57, 59, 60, 61, 62, 64, 65, 67, 68, 69, 70, 72, 73, -74, 18, 11, 22, 1, 3, 5, 7, 9, 10, 13, 15, 16, 18, 20, -26, 28, 0, 2, 4, 6, 8, 12, 14, 17, 19, 21, 23, 24, 25, -27, 29, 47, 45, 43, 48, 42, 44, 49, 46, 33, 11, 27, 31, 37, -38, 63, 17, 18, 21, 23, 25, 29, 32, 35, 77, 83, 97, 0, 5, -9, 15, 16, 19, 39, 41, 53, 69, 20, 22, 24, 26, 28, 30, 34, -36, 76, 82, 96, 102, 103, 1, 3, 7, 13, 40, 51, 57, 61, 67, -71, 73, 75, 81, 87, 95, 101, 106, 107, 70, 2, 4, 6, 8, 10, -12, 14, 50, 52, 54, 55, 56, 58, 59, 60, 62, 64, 65, 66, 68, -72, 74, 78, 79, 80, 84, 85, 86, 88, 89, 90, 91, 92, 93, 94, -98, 99, 100, 104, 105, 108, 109, 0, 1, 46, 43, 47, 42, 3, 44, -5, 20, 4, 18, 24, 26, 30, 38, 34, 36, 7, 9, 22, 2, 45, -21, 40, 19, 35, 37, 39, 32, 12, 14, 28, 10, 16, 41, 25, 27, -31, 6, 8, 23, 33, 11, 17, 13, 15, 29, 52, 50, 53, 48, 49, -51, 0, 1, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, -6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, -51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, -66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, -81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, -96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, -111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, -126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, -141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, -156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, -171, 172, 173, 174, 175, 176, 177, 178, 179, 0, 1, 2, 3, 4, 5, -6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, -51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, -66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, -81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, -96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, -111, 112, 113, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, -27, 28, 29, 30, 31, 32, 33, 34, 35, 5, 15, 19, 27, 31, 35, -39, 43, 96, 104, 120, 121, 131, 0, 1, 2, 10, 12, 24, 25, 46, -47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 76, 77, 78, 79, 80, -81, 82, 83, 84, 85, 86, 87, 88, 90, 91, 93, 95, 97, 99, 101, -103, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, -119, 122, 123, 124, 125, 126, 127, 128, 129, 130, 132, 133, 134, 135, 136, -137, 138, 140, 144, 148, 152, 156, 160, 164, 3, 4, 6, 7, 8, 9, -11, 13, 14, 16, 17, 18, 20, 21, 22, 23, 26, 28, 29, 30, 32, -33, 34, 36, 37, 38, 40, 41, 42, 44, 45, 57, 58, 59, 60, 61, -62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 89, -92, 94, 98, 100, 102, 139, 141, 142, 143, 145, 146, 147, 149, 150, 151, -153, 154, 155, 157, 158, 159, 161, 162, 163, 165, 166, 36, 57, 60, 65, -68, 114, 135, 156, 161, 162, 165, 170, 176, 179, 182, 183, 188, 191, 194, -197, 198, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43, -44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 58, 59, -61, 62, 63, 64, 66, 67, 69, 70, 71, 72, 73, 74, 75, 76, 77, -78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, -108, 109, 110, 111, 112, 113, 115, 116, 117, 118, 119, 120, 121, 122, 123, -124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 136, 137, 138, 139, -140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, -155, 157, 158, 159, 160, 163, 164, 166, 167, 168, 169, 171, 172, 173, 174, -175, 177, 178, 180, 181, 184, 185, 186, 187, 189, 190, 192, 193, 195, 196, -199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, -214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, -229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, -244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, -259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, -274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, -289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, -304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, -319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, -334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, -349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, -364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, -379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, -394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, -409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, -424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, -439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, -454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, -469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, -484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, -499, 500, 501, 502, 503, 504, 505, 506, 0, 1, 2, 3, 4, 5, 6, -7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, -40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, -55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, -70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, -85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, -100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, -115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, -130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, -145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, -160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, -175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, -190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, -205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, -220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, -235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, -250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, -265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, -280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, -295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, -310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, -325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, -340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, -355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, -370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, -385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, -400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, -415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, -430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, -445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, -460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, -475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, -490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, -505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, -520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, -535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, -550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, -565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, -580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, -595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, -610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, -625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, -640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, -655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -15, 16, 17, 18, 19, 20, 21, 0, 1, 2, 3, 4, 5, 6, 7, -8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, -38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, -53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, -68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, -83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, -98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, -113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, -128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, -143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, -158, 159, 160, 161, 162, 163, 164, 165, 166, 0, 1, 2, 3, 4, 5, -6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2, 3, 4, 5, -0, 3, 5, 10, 16, 18, 94, 4, 6, 7, 8, 17, 37, 44, 48, -51, 56, 66, 69, 75, 79, 82, 84, 88, 98, 99, 102, 1, 2, 9, -11, 12, 13, 14, 15, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, -29, 30, 31, 32, 33, 34, 35, 36, 38, 39, 40, 41, 42, 43, 45, -46, 47, 49, 50, 52, 53, 54, 55, 57, 58, 59, 60, 61, 62, 63, -64, 65, 67, 68, 70, 71, 72, 73, 74, 76, 77, 78, 80, 81, 83, -85, 86, 87, 89, 90, 91, 92, 93, 95, 96, 97, 100, 101, 103, 104, -105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, -120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, -135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, -150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, -165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, -180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, -81, 18, 24, 33, 69, 83, 19, 25, 35, 71, 0, 1, 2, 3, 4, -5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, -22, 23, 26, 27, 28, 29, 30, 31, 32, 34, 36, 37, 38, 39, 40, -41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, -56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 72, -73, 74, 75, 76, 77, 78, 79, 80, 82, 84, 85, 86, 87, 88, 89, -90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, -105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, -120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, -135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, -150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, -165, 166, 167, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -12, 13, 14, 15, 16, 17, 4, 5, 6, 31, 32, 39, 40, 41, 0, -1, 2, 3, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, -19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 35, -36, 37, 38, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, -69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, -99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, -114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, -129, 130, 131, 132, 133, 134, 135, 136, 0, 1, 3, 22, 23, 26, 34, -0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -16, 17, 18, 19, 20, 21, 24, 25, 27, 28, 29, 30, 31, 32, 33, -35, 36, 37, 38, 39, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 0, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, -31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, -46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, -61, 62, 63, 64, 65, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, -25, 26, 27, 28, 29, 30, 31, 32, 33, 51, 0, 1, 2, 3, 4, -5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, -35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, -50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, -66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 0, 1, 2, -3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 0, 1, -2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, -47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, -77, 74, 75, 92, 93, 116, 143, 144, 149, 14, 15, 34, 35, 36, 37, -68, 69, 98, 99, 104, 105, 110, 111, 154, 155, 156, 157, 166, 167, 168, -169, 178, 179, 180, 181, 4, 5, 6, 7, 22, 23, 24, 25, 46, 47, -50, 51, 56, 57, 60, 61, 80, 82, 85, 87, 121, 122, 123, 124, 133, -134, 135, 136, 190, 191, 194, 197, 202, 203, 206, 207, 212, 213, 216, 217, -0, 1, 2, 3, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, -21, 26, 27, 28, 29, 30, 31, 32, 33, 38, 39, 40, 41, 42, 43, -44, 45, 48, 49, 52, 53, 54, 55, 58, 59, 62, 63, 64, 65, 66, -67, 70, 71, 72, 73, 76, 77, 78, 79, 81, 83, 84, 86, 88, 89, -90, 91, 94, 95, 96, 97, 100, 101, 102, 103, 106, 107, 108, 109, 112, -113, 114, 115, 117, 118, 119, 120, 125, 126, 127, 128, 129, 130, 131, 132, -137, 138, 139, 140, 141, 142, 145, 146, 147, 148, 150, 151, 152, 153, 158, -159, 160, 161, 162, 163, 164, 165, 170, 171, 172, 173, 174, 175, 176, 177, -182, 183, 184, 185, 186, 187, 188, 189, 192, 193, 195, 196, 198, 199, 200, -201, 204, 205, 208, 209, 210, 211, 214, 215, 218, 219, 220, 221, 0, 1, -2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, -32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 0, 1, 2, -3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, -18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, -48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, -78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, -93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, -108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, -123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, -138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, -153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, -168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, -183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, -198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, -213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, -228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, -243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, -258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, -273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, -288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, -303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, -318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, -333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, -348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, -363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, -45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 0, 1, 2, 3, -4, 5, 6, 7, 0, 1, 14, 15, 16, 17, 2, 3, 4, 5, 8, -9, 10, 11, 12, 13, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -28, 29, 30, 31, 32, 33, 11, 2, 5, 10, 8, 4, 9, 1, 7, -3, 0, 6, 42, 45, 36, 39, 12, 16, 18, 22, 38, 41, 44, 47, -37, 40, 43, 46, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -11, 13, 14, 15, 17, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, -30, 31, 32, 33, 34, 35, 0, 1, 2, 3, 4, 5, 6, 7, 8, -9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, -24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, -39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, -54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, -69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, -84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, -99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, -114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, -129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, -144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, -159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, -174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, -189, 190, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, -28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, -43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, -73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, -88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, -103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 4, 5, -6, 8, 1, 3, 0, 2, 7, 9, 0, 1, 2, 3, 4, 5, 6, -7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, -22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, -67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, -82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, -97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, -112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, -127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, -142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, -157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, -172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, -187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, -202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, -217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, -232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, -247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, -262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, -277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, -292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, -307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, -322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, -337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, -352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, -367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, -382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, -397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, -412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, -427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, -442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, -457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, -472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, -487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, -502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, -517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, -532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, -547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, -562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, -577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, -592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, -607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, -622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, -637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, -652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, -667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, -682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, -697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, -712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, -727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, -742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, -757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, -772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, -787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, -802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, -817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, -832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, -847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, -862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, -877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, -892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, -907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, -922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, -937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, -952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, -967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, -982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, -997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, -1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, -1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, -1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, -1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, -1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, -1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, -1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, -1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131, -1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, -1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, -1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, -1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, -1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, -1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, -1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, -1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, -1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, -1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, -1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, -1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, -1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, -1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, -1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, -1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, -1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, -1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, -1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, -1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, -1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, -1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, -1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, -1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, 1491, -1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, -1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, -1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, -1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, -1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, -1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, -1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, -1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, -1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, -1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, -1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, -1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, -1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, -1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, -1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, -1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, -1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, -1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, -1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, -1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, -1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, -1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, -1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, -1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, -1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, -1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, -1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, -1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, -1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, -1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, -1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, -1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, -1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, -1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, -2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, -2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, -2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, -2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, -2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, -2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, -2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, -2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, -2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, -2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, -2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, -2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, -2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, -2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, -2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, -2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, -2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, -2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, -2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, -2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, -2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, -2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, -2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, -2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, -2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, -2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, -2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418, 2419, 2420, 2421, -2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, -2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, -2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, -2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, -2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, -2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, -2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, -2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, -2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, -2557, 2558, 2559, 2560, 2561, 2562, 2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, -2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, -2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, -2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, -2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, -2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, -2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, -2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, -2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, -2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, -2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, -2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, -2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, -2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, -2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, -2782, 2783, 2784, 2785, 2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, -2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, -2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, -2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, -2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, -2857, 2858, 2859, 2860, 2861, 2862, 2863, 9, 11, 6, 7, 8, 10, 4, 5, -0, 1, 2, 3, 0, 2, 10, 3, 6, 1, 9, 11, 4, 8, 7, -5, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, -29, 30, 31, 32, 33, 34, 35, 68, 116, 22, 10, 97, 117, 52, 110, -7, 19, 111, 115, 6, 18, 0, 74, 88, 12, 48, 108, 99, 109, 38, -104, 4, 16, 24, 96, 15, 3, 50, 84, 71, 85, 36, 102, 103, 119, -54, 86, 100, 30, 25, 105, 113, 69, 53, 63, 98, 87, 93, 89, 95, -9, 21, 62, 114, 5, 17, 26, 55, 2, 14, 65, 8, 20, 64, 92, -42, 106, 11, 23, 46, 66, 34, 101, 107, 56, 35, 47, 57, 67, 76, -118, 75, 83, 82, 94, 37, 77, 29, 51, 1, 13, 27, 49, 58, 112, -39, 59, 28, 70, 44, 73, 80, 81, 32, 72, 31, 43, 33, 40, 41, -45, 60, 61, 78, 79, 90, 91 -}; - - -/**Function************************************************************* - - Synopsis [Reads library from array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Dar_LibReadNodes() -{ - Vec_Int_t * vResult; - int i; - vResult = Vec_IntAlloc( s_nDataSize1 ); - for ( i = 0; i < s_nDataSize1; i++ ) - Vec_IntPush( vResult, s_Data1[i] ); - return vResult; -} - -/**Function************************************************************* - - Synopsis [Reads library from array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Dar_LibReadOuts() -{ - Vec_Int_t * vResult; - int i; - vResult = Vec_IntAlloc( s_nDataSize2 ); - for ( i = 0; i < s_nDataSize2; i++ ) - Vec_IntPush( vResult, s_Data2[i] ); - return vResult; -} - -/**Function************************************************************* - - Synopsis [Reads library from array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Dar_LibReadPrios() -{ - Vec_Int_t * vResult; - int i; - vResult = Vec_IntAlloc( s_nDataSize3 ); - for ( i = 0; i < s_nDataSize3; i++ ) - Vec_IntPush( vResult, s_Data3[i] ); - return vResult; -} - -//#if 0 - -#include "abc.h" - -/**Function************************************************************* - - Synopsis [Generate arrays.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_NtkGenerateArrays( Abc_Ntk_t * pNtk ) -{ - extern int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ); - - Abc_Obj_t * pObj; - int i, Count = 0; - assert( Abc_NtkPiNum(pNtk) == 4 ); - assert( Abc_NtkIsStrash(pNtk) ); - assert( Abc_ObjFanoutNum(Abc_AigConst1(pNtk)) == 0 ); -/* - { - unsigned char * pBuffer; - int Pos, uLit, uLit0, uLit1, Size, Digit; - - Abc_NtkForEachPi( pNtk, pObj, i ) - pObj->pCopy = (void *)Count++; - - Pos = 0; - pBuffer = ALLOC( char, 200000 ); - Abc_AigForEachAnd( pNtk, pObj, i ) - { - pObj->pCopy = (void *)Count++; - uLit = ((int)pObj->pCopy << 1); - uLit0 = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj); - uLit1 = (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj); - assert( uLit0 < uLit1 ); - Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); - Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); - } - // write the buffer - Size = 0; - for ( i = 0; i < Pos; i++ ) - { - if ( i % 36 == 0 ) - printf( "\n" ); - - Digit = pBuffer[i] & 0xF; - if ( Digit < 10 ) - printf( "%d", Digit ); - else - printf( "%c", Digit - 10 + 'A' ); - - - Digit = pBuffer[i]; - Digit >>= 4; - if ( Digit < 10 ) - printf( "%d", Digit ); - else - printf( "%c", Digit - 10 + 'A' ); - - } - printf( "\n" ); - printf( "Size = %d.\n", Pos ); - } -*/ - - - Abc_NtkForEachPi( pNtk, pObj, i ) - pObj->pCopy = (void *)Count++; - Abc_AigForEachAnd( pNtk, pObj, i ) - { -// if ( (Count - 4) % 6 == 0 ) -// printf( "\n" ); -// printf( "%5d,", (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj) ); -// printf( "%5d,", (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj) ); - pObj->pCopy = (void *)Count++; - } -// printf( "\n" ); -// printf( "Nodes = %d.\n", Count-4 ); - - - - Abc_NtkForEachPo( pNtk, pObj, i ) - { - if ( i % 12 == 0 ) - printf( "\n" ); - printf( "%5d,", (int)Abc_ObjFanin0(pObj)->pCopy ); - } - printf( "\n" ); - printf( "Outputs = %d.\n", Abc_NtkPoNum(pNtk) ); - - -/* - { - unsigned char * pBuffer; - Vec_Int_t * vOuts; - int Pos, Prev, Out; - - vOuts = Vec_IntAlloc( 25000 ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Vec_IntPush( vOuts, Abc_ObjFaninId0(pObj) ); - Vec_IntSort( vOuts, 0 ); - - Pos = 0; - pBuffer = ALLOC( char, 50000 ); - Prev = 0; - Vec_IntForEachEntry( vOuts, Out, i ) - { - assert( Prev < Out ); - Pos = Io_WriteAigerEncode( pBuffer, Pos, Out - Prev ); - Prev = Out; - } - Vec_IntFree( vOuts ); - - // write the buffer - for ( i = 0; i < Pos; i++ ) - { - if ( i % 32 == 0 ) - printf( "\n" ); - printf( "%d,", pBuffer[i] ); - } - printf( "\n" ); - printf( "Size = %d.\n", Pos ); - } -*/ - -} - -//#endif - - - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/darInt.h b/src/aig/dar/darInt.h deleted file mode 100644 index 97331416..00000000 --- a/src/aig/dar/darInt.h +++ /dev/null @@ -1,165 +0,0 @@ -/**CFile**************************************************************** - - FileName [darInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: darInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DAR_INT_H__ -#define __DAR_INT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "vec.h" -#include "aig.h" -#include "dar.h" -#include "bar.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dar_Man_t_ Dar_Man_t; -typedef struct Dar_Cut_t_ Dar_Cut_t; - -// the AIG 4-cut -struct Dar_Cut_t_ // 6 words -{ - unsigned uSign; // cut signature - unsigned uTruth : 16; // the truth table of the cut function - unsigned Value : 11; // the value of the cut - unsigned fBest : 1; // marks the best cut - unsigned fUsed : 1; // marks the cut currently in use - unsigned nLeaves : 3; // the number of leaves - int pLeaves[4]; // the array of leaves -}; - -// the AIG manager -struct Dar_Man_t_ -{ - // input data - Dar_RwrPar_t * pPars; // rewriting parameters - Aig_Man_t * pAig; // AIG manager - // various data members - Aig_MmFixed_t * pMemCuts; // memory manager for cuts - void * pManCnf; // CNF managers - // current rewriting step - Vec_Ptr_t * vLeavesBest; // the best set of leaves - int OutBest; // the best output (in the library) - int OutNumBest; // the best number of the output - int GainBest; // the best gain - int LevelBest; // the level of node with the best gain - int ClassBest; // the equivalence class of the best replacement - // function statistics - int nTotalSubgs; // the total number of subgraphs tried - int ClassTimes[222];// the runtimes for each class - int ClassGains[222];// the gains for each class - int ClassSubgs[222];// the graphs for each class - int nCutMemUsed; // memory used for cuts - // rewriting statistics - int nNodesInit; // the original number of nodes - int nNodesTried; // the number of nodes attempted - int nCutsAll; // all cut pairs - int nCutsTried; // computed cuts - int nCutsUsed; // used cuts - int nCutsBad; // bad cuts due to absent fanin - int nCutsGood; // good cuts - int nCutsSkipped; // skipped bad cuts - // timing statistics - int timeCuts; - int timeEval; - int timeOther; - int timeTotal; - int time1; - int time2; -}; - -static inline Dar_Cut_t * Dar_ObjCuts( Aig_Obj_t * pObj ) { return pObj->pData; } -static inline void Dar_ObjSetCuts( Aig_Obj_t * pObj, Dar_Cut_t * pCuts ) { assert( !Aig_ObjIsNone(pObj) ); pObj->pData = pCuts; } - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator over all cuts of the node -#define Dar_ObjForEachCutAll( pObj, pCut, i ) \ - for ( (pCut) = Dar_ObjCuts(pObj), i = 0; i < (int)(pObj)->nCuts; i++, pCut++ ) -#define Dar_ObjForEachCut( pObj, pCut, i ) \ - for ( (pCut) = Dar_ObjCuts(pObj), i = 0; i < (int)(pObj)->nCuts; i++, pCut++ ) if ( (pCut)->fUsed==0 ) {} else -// iterator over leaves of the cut -#define Dar_CutForEachLeaf( p, pCut, pLeaf, i ) \ - for ( i = 0; (i < (int)(pCut)->nLeaves) && (((pLeaf) = Aig_ManObj(p, (pCut)->pLeaves[i])), 1); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== darBalance.c ========================================================*/ -/*=== darCore.c ===========================================================*/ -/*=== darCut.c ============================================================*/ -extern void Dar_ManCutsStart( Dar_Man_t * p ); -extern void Dar_ManCutsFree( Dar_Man_t * p ); -extern Dar_Cut_t * Dar_ObjComputeCuts_rec( Dar_Man_t * p, Aig_Obj_t * pObj ); -extern Dar_Cut_t * Dar_ObjComputeCuts( Dar_Man_t * p, Aig_Obj_t * pObj ); -/*=== darData.c ===========================================================*/ -extern Vec_Int_t * Dar_LibReadNodes(); -extern Vec_Int_t * Dar_LibReadOuts(); -extern Vec_Int_t * Dar_LibReadPrios(); -/*=== darLib.c ============================================================*/ -extern void Dar_LibStart(); -extern void Dar_LibStop(); -extern void Dar_LibPrepare( int nSubgraphs ); -extern void Dar_LibReturnCanonicals( unsigned * pCanons ); -extern void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required ); -extern Aig_Obj_t * Dar_LibBuildBest( Dar_Man_t * p ); -/*=== darMan.c ============================================================*/ -extern Dar_Man_t * Dar_ManStart( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ); -extern void Dar_ManStop( Dar_Man_t * p ); -extern void Dar_ManPrintStats( Dar_Man_t * p ); -/*=== darPrec.c ============================================================*/ -extern char ** Dar_Permutations( int n ); -extern void Dar_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/dar/darLib.c b/src/aig/dar/darLib.c deleted file mode 100644 index 14a47cee..00000000 --- a/src/aig/dar/darLib.c +++ /dev/null @@ -1,980 +0,0 @@ -/**CFile**************************************************************** - - FileName [darLib.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [Library of AIG subgraphs used for rewriting.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: darLib.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dar_Lib_t_ Dar_Lib_t; -typedef struct Dar_LibObj_t_ Dar_LibObj_t; -typedef struct Dar_LibDat_t_ Dar_LibDat_t; - -struct Dar_LibObj_t_ // library object (2 words) -{ - unsigned Fan0 : 16; // the first fanin - unsigned Fan1 : 16; // the second fanin - unsigned fCompl0 : 1; // the first compl attribute - unsigned fCompl1 : 1; // the second compl attribute - unsigned fPhase : 1; // the phase of the node - unsigned fTerm : 1; // indicates a PI - unsigned Num : 28; // internal use -}; - -struct Dar_LibDat_t_ // library object data -{ - Aig_Obj_t * pFunc; // the corresponding AIG node if it exists - int Level; // level of this node after it is constructured - int TravId; // traversal ID of the library object data - unsigned char fMffc; // set to one if node is part of MFFC - unsigned char nLats[3]; // the number of latches on the input/output stem -}; - -struct Dar_Lib_t_ // library -{ - // objects - Dar_LibObj_t * pObjs; // the set of library objects - int nObjs; // the number of objects used - int iObj; // the current object - // structures by class - int nSubgr[222]; // the number of subgraphs by class - int * pSubgr[222]; // the subgraphs for each class - int * pSubgrMem; // memory for subgraph pointers - int nSubgrTotal; // the total number of subgraph - // structure priorities - int * pPriosMem; // memory for priority of structures - int * pPrios[222]; // pointers to the priority numbers - // structure places in the priorities - int * pPlaceMem; // memory for places of structures in the priority lists - int * pPlace[222]; // pointers to the places numbers - // structure scores - int * pScoreMem; // memory for scores of structures - int * pScore[222]; // pointers to the scores numbers - // nodes by class - int nNodes[222]; // the number of nodes by class - int * pNodes[222]; // the nodes for each class - int * pNodesMem; // memory for nodes pointers - int nNodesTotal; // the total number of nodes - // prepared library - int nSubgraphs; - int nNodes0Max; - // nodes by class - int nNodes0[222]; // the number of nodes by class - int * pNodes0[222]; // the nodes for each class - int * pNodes0Mem; // memory for nodes pointers - int nNodes0Total; // the total number of nodes - // structures by class - int nSubgr0[222]; // the number of subgraphs by class - int * pSubgr0[222]; // the subgraphs for each class - int * pSubgr0Mem; // memory for subgraph pointers - int nSubgr0Total; // the total number of subgraph - // object data - Dar_LibDat_t * pDatas; - int nDatas; - // information about NPN classes - char ** pPerms4; - unsigned short * puCanons; - char * pPhases; - char * pPerms; - unsigned char * pMap; -}; - -static Dar_Lib_t * s_DarLib = NULL; - -static inline Dar_LibObj_t * Dar_LibObj( Dar_Lib_t * p, int Id ) { return p->pObjs + Id; } -static inline int Dar_LibObjTruth( Dar_LibObj_t * pObj ) { return pObj->Num < (0xFFFF & ~pObj->Num) ? pObj->Num : (0xFFFF & ~pObj->Num); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dar_Lib_t * Dar_LibAlloc( int nObjs ) -{ - unsigned uTruths[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 }; - Dar_Lib_t * p; - int i, clk = clock(); - p = ALLOC( Dar_Lib_t, 1 ); - memset( p, 0, sizeof(Dar_Lib_t) ); - // allocate objects - p->nObjs = nObjs; - p->pObjs = ALLOC( Dar_LibObj_t, nObjs ); - memset( p->pObjs, 0, sizeof(Dar_LibObj_t) * nObjs ); - // allocate canonical data - p->pPerms4 = Dar_Permutations( 4 ); - Dar_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap ); - // start the elementary objects - p->iObj = 4; - for ( i = 0; i < 4; i++ ) - { - p->pObjs[i].fTerm = 1; - p->pObjs[i].Num = uTruths[i]; - } -// PRT( "Library start", clock() - clk ); - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibFree( Dar_Lib_t * p ) -{ - free( p->pObjs ); - free( p->pDatas ); - free( p->pNodesMem ); - free( p->pNodes0Mem ); - free( p->pSubgrMem ); - free( p->pSubgr0Mem ); - free( p->pPriosMem ); - FREE( p->pPlaceMem ); - FREE( p->pScoreMem ); - free( p->pPerms4 ); - free( p->puCanons ); - free( p->pPhases ); - free( p->pPerms ); - free( p->pMap ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Returns canonical truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibReturnCanonicals( unsigned * pCanons ) -{ - int Visits[222] = {0}; - int i, k; - // find canonical truth tables - for ( i = k = 0; i < (1<<16); i++ ) - if ( !Visits[s_DarLib->pMap[i]] ) - { - Visits[s_DarLib->pMap[i]] = 1; - pCanons[k++] = ((i<<16) | i); - } - assert( k == 222 ); -} - -/**Function************************************************************* - - Synopsis [Adds one AND to the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibAddNode( Dar_Lib_t * p, int Id0, int Id1, int fCompl0, int fCompl1 ) -{ - Dar_LibObj_t * pFan0 = Dar_LibObj( p, Id0 ); - Dar_LibObj_t * pFan1 = Dar_LibObj( p, Id1 ); - Dar_LibObj_t * pObj = p->pObjs + p->iObj++; - pObj->Fan0 = Id0; - pObj->Fan1 = Id1; - pObj->fCompl0 = fCompl0; - pObj->fCompl1 = fCompl1; - pObj->fPhase = (fCompl0 ^ pFan0->fPhase) & (fCompl1 ^ pFan1->fPhase); - pObj->Num = 0xFFFF & (fCompl0? ~pFan0->Num : pFan0->Num) & (fCompl1? ~pFan1->Num : pFan1->Num); -} - -/**Function************************************************************* - - Synopsis [Adds one AND to the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibSetup_rec( Dar_Lib_t * p, Dar_LibObj_t * pObj, int Class, int fCollect ) -{ - if ( pObj->fTerm || (int)pObj->Num == Class ) - return; - pObj->Num = Class; - Dar_LibSetup_rec( p, Dar_LibObj(p, pObj->Fan0), Class, fCollect ); - Dar_LibSetup_rec( p, Dar_LibObj(p, pObj->Fan1), Class, fCollect ); - if ( fCollect ) - p->pNodes[Class][ p->nNodes[Class]++ ] = pObj-p->pObjs; - else - p->nNodes[Class]++; -} - -/**Function************************************************************* - - Synopsis [Adds one AND to the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibSetup( Dar_Lib_t * p, Vec_Int_t * vOuts, Vec_Int_t * vPrios ) -{ - int fTraining = 0; - Dar_LibObj_t * pObj; - int nNodesTotal, uTruth, Class, Out, i, k; - assert( p->iObj == p->nObjs ); - - // count the number of representatives of each class - for ( i = 0; i < 222; i++ ) - p->nSubgr[i] = p->nNodes[i] = 0; - Vec_IntForEachEntry( vOuts, Out, i ) - { - pObj = Dar_LibObj( p, Out ); - uTruth = Dar_LibObjTruth( pObj ); - Class = p->pMap[uTruth]; - p->nSubgr[Class]++; - } - // allocate memory for the roots of each class - p->pSubgrMem = ALLOC( int, Vec_IntSize(vOuts) ); - p->pSubgr0Mem = ALLOC( int, Vec_IntSize(vOuts) ); - p->nSubgrTotal = 0; - for ( i = 0; i < 222; i++ ) - { - p->pSubgr[i] = p->pSubgrMem + p->nSubgrTotal; - p->pSubgr0[i] = p->pSubgr0Mem + p->nSubgrTotal; - p->nSubgrTotal += p->nSubgr[i]; - p->nSubgr[i] = 0; - } - assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); - // add the outputs to storage - Vec_IntForEachEntry( vOuts, Out, i ) - { - pObj = Dar_LibObj( p, Out ); - uTruth = Dar_LibObjTruth( pObj ); - Class = p->pMap[uTruth]; - p->pSubgr[Class][ p->nSubgr[Class]++ ] = Out; - } - - if ( fTraining ) - { - // allocate memory for the priority of roots of each class - p->pPriosMem = ALLOC( int, Vec_IntSize(vOuts) ); - p->nSubgrTotal = 0; - for ( i = 0; i < 222; i++ ) - { - p->pPrios[i] = p->pPriosMem + p->nSubgrTotal; - p->nSubgrTotal += p->nSubgr[i]; - for ( k = 0; k < p->nSubgr[i]; k++ ) - p->pPrios[i][k] = k; - - } - assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); - - // allocate memory for the priority of roots of each class - p->pPlaceMem = ALLOC( int, Vec_IntSize(vOuts) ); - p->nSubgrTotal = 0; - for ( i = 0; i < 222; i++ ) - { - p->pPlace[i] = p->pPlaceMem + p->nSubgrTotal; - p->nSubgrTotal += p->nSubgr[i]; - for ( k = 0; k < p->nSubgr[i]; k++ ) - p->pPlace[i][k] = k; - - } - assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); - - // allocate memory for the priority of roots of each class - p->pScoreMem = ALLOC( int, Vec_IntSize(vOuts) ); - p->nSubgrTotal = 0; - for ( i = 0; i < 222; i++ ) - { - p->pScore[i] = p->pScoreMem + p->nSubgrTotal; - p->nSubgrTotal += p->nSubgr[i]; - for ( k = 0; k < p->nSubgr[i]; k++ ) - p->pScore[i][k] = 0; - - } - assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); - } - else - { - int Counter = 0; - // allocate memory for the priority of roots of each class - p->pPriosMem = ALLOC( int, Vec_IntSize(vOuts) ); - p->nSubgrTotal = 0; - for ( i = 0; i < 222; i++ ) - { - p->pPrios[i] = p->pPriosMem + p->nSubgrTotal; - p->nSubgrTotal += p->nSubgr[i]; - for ( k = 0; k < p->nSubgr[i]; k++ ) - p->pPrios[i][k] = Vec_IntEntry(vPrios, Counter++); - - } - assert( p->nSubgrTotal == Vec_IntSize(vOuts) ); - assert( Counter == Vec_IntSize(vPrios) ); - } - - // create traversal IDs - for ( i = 0; i < p->iObj; i++ ) - Dar_LibObj(p, i)->Num = 0xff; - // count nodes in each class - for ( i = 0; i < 222; i++ ) - for ( k = 0; k < p->nSubgr[i]; k++ ) - Dar_LibSetup_rec( p, Dar_LibObj(p, p->pSubgr[i][k]), i, 0 ); - // count the total number of nodes - p->nNodesTotal = 0; - for ( i = 0; i < 222; i++ ) - p->nNodesTotal += p->nNodes[i]; - // allocate memory for the nodes of each class - p->pNodesMem = ALLOC( int, p->nNodesTotal ); - p->pNodes0Mem = ALLOC( int, p->nNodesTotal ); - p->nNodesTotal = 0; - for ( i = 0; i < 222; i++ ) - { - p->pNodes[i] = p->pNodesMem + p->nNodesTotal; - p->pNodes0[i] = p->pNodes0Mem + p->nNodesTotal; - p->nNodesTotal += p->nNodes[i]; - p->nNodes[i] = 0; - } - // create traversal IDs - for ( i = 0; i < p->iObj; i++ ) - Dar_LibObj(p, i)->Num = 0xff; - // add the nodes to storage - nNodesTotal = 0; - for ( i = 0; i < 222; i++ ) - { - for ( k = 0; k < p->nSubgr[i]; k++ ) - Dar_LibSetup_rec( p, Dar_LibObj(p, p->pSubgr[i][k]), i, 1 ); - nNodesTotal += p->nNodes[i]; -//printf( "Class %3d : Subgraphs = %4d. Nodes = %5d.\n", i, p->nSubgr[i], p->nNodes[i] ); - } - assert( nNodesTotal == p->nNodesTotal ); - // prepare the number of the PI nodes - for ( i = 0; i < 4; i++ ) - Dar_LibObj(p, i)->Num = i; -} - -/**Function************************************************************* - - Synopsis [Starts the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibCreateData( Dar_Lib_t * p, int nDatas ) -{ - if ( p->nDatas == nDatas ) - return; - FREE( p->pDatas ); - // allocate datas - p->nDatas = nDatas; - p->pDatas = ALLOC( Dar_LibDat_t, nDatas ); - memset( p->pDatas, 0, sizeof(Dar_LibDat_t) * nDatas ); -} - -/**Function************************************************************* - - Synopsis [Adds one AND to the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibSetup0_rec( Dar_Lib_t * p, Dar_LibObj_t * pObj, int Class, int fCollect ) -{ - if ( pObj->fTerm || (int)pObj->Num == Class ) - return; - pObj->Num = Class; - Dar_LibSetup0_rec( p, Dar_LibObj(p, pObj->Fan0), Class, fCollect ); - Dar_LibSetup0_rec( p, Dar_LibObj(p, pObj->Fan1), Class, fCollect ); - if ( fCollect ) - p->pNodes0[Class][ p->nNodes0[Class]++ ] = pObj-p->pObjs; - else - p->nNodes0[Class]++; -} - -/**Function************************************************************* - - Synopsis [Starts the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibPrepare( int nSubgraphs ) -{ - Dar_Lib_t * p = s_DarLib; - int i, k, nNodes0Total; - if ( p->nSubgraphs == nSubgraphs ) - return; - - // favor special classes: - // 1 : F = (!d*!c*!b*!a) - // 4 : F = (!d*!c*!(b*a)) - // 12 : F = (!d*!(c*!(!b*!a))) - // 20 : F = (!d*!(c*b*a)) - - // set the subgraph counters - p->nSubgr0Total = 0; - for ( i = 0; i < 222; i++ ) - { -// if ( i == 1 || i == 4 || i == 12 || i == 20 ) // special classes - if ( i == 1 ) // special classes - p->nSubgr0[i] = p->nSubgr[i]; - else - p->nSubgr0[i] = AIG_MIN( p->nSubgr[i], nSubgraphs ); - p->nSubgr0Total += p->nSubgr0[i]; - for ( k = 0; k < p->nSubgr0[i]; k++ ) - p->pSubgr0[i][k] = p->pSubgr[i][ p->pPrios[i][k] ]; - } - - // count the number of nodes - // clean node counters - for ( i = 0; i < 222; i++ ) - p->nNodes0[i] = 0; - // create traversal IDs - for ( i = 0; i < p->iObj; i++ ) - Dar_LibObj(p, i)->Num = 0xff; - // count nodes in each class - // count the total number of nodes and the largest class - p->nNodes0Total = 0; - p->nNodes0Max = 0; - for ( i = 0; i < 222; i++ ) - { - for ( k = 0; k < p->nSubgr0[i]; k++ ) - Dar_LibSetup0_rec( p, Dar_LibObj(p, p->pSubgr0[i][k]), i, 0 ); - p->nNodes0Total += p->nNodes0[i]; - p->nNodes0Max = AIG_MAX( p->nNodes0Max, p->nNodes0[i] ); - } - - // clean node counters - for ( i = 0; i < 222; i++ ) - p->nNodes0[i] = 0; - // create traversal IDs - for ( i = 0; i < p->iObj; i++ ) - Dar_LibObj(p, i)->Num = 0xff; - // add the nodes to storage - nNodes0Total = 0; - for ( i = 0; i < 222; i++ ) - { - for ( k = 0; k < p->nSubgr0[i]; k++ ) - Dar_LibSetup0_rec( p, Dar_LibObj(p, p->pSubgr0[i][k]), i, 1 ); - nNodes0Total += p->nNodes0[i]; - } - assert( nNodes0Total == p->nNodes0Total ); - // prepare the number of the PI nodes - for ( i = 0; i < 4; i++ ) - Dar_LibObj(p, i)->Num = i; - - // realloc the datas - Dar_LibCreateData( p, p->nNodes0Max + 32 ); - // allocated more because Dar_LibBuildBest() sometimes requires more entries -} - -/**Function************************************************************* - - Synopsis [Reads library from array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dar_Lib_t * Dar_LibRead() -{ - Vec_Int_t * vObjs, * vOuts, * vPrios; - Dar_Lib_t * p; - int i; - // read nodes and outputs - vObjs = Dar_LibReadNodes(); - vOuts = Dar_LibReadOuts(); - vPrios = Dar_LibReadPrios(); - // create library - p = Dar_LibAlloc( Vec_IntSize(vObjs)/2 + 4 ); - // create nodes - for ( i = 0; i < vObjs->nSize; i += 2 ) - Dar_LibAddNode( p, vObjs->pArray[i] >> 1, vObjs->pArray[i+1] >> 1, - vObjs->pArray[i] & 1, vObjs->pArray[i+1] & 1 ); - // create outputs - Dar_LibSetup( p, vOuts, vPrios ); - Vec_IntFree( vObjs ); - Vec_IntFree( vOuts ); - Vec_IntFree( vPrios ); - return p; -} - -/**Function************************************************************* - - Synopsis [Starts the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibStart() -{ - int clk = clock(); - assert( s_DarLib == NULL ); - s_DarLib = Dar_LibRead(); -// printf( "The 4-input library started with %d nodes and %d subgraphs. ", s_DarLib->nObjs - 4, s_DarLib->nSubgrTotal ); -// PRT( "Time", clock() - clk ); -} - -/**Function************************************************************* - - Synopsis [Stops the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibStop() -{ - assert( s_DarLib != NULL ); - Dar_LibFree( s_DarLib ); - s_DarLib = NULL; -} - -/**Function************************************************************* - - Synopsis [Updates the score of the class and adjusts the priority of this class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibIncrementScore( int Class, int Out, int Gain ) -{ - int * pPrios = s_DarLib->pPrios[Class]; // pPrios[i] = Out - int * pPlace = s_DarLib->pPlace[Class]; // pPlace[Out] = i - int * pScore = s_DarLib->pScore[Class]; // score of Out - int Out2; - assert( Class >= 0 && Class < 222 ); - assert( Out >= 0 && Out < s_DarLib->nSubgr[Class] ); - assert( pPlace[pPrios[Out]] == Out ); - // increment the score - pScore[Out] += Gain; - // move the out in the order - while ( pPlace[Out] > 0 && pScore[Out] > pScore[ pPrios[pPlace[Out]-1] ] ) - { - // get the previous output in the priority list - Out2 = pPrios[pPlace[Out]-1]; - // swap Out and Out2 - pPlace[Out]--; - pPlace[Out2]++; - pPrios[pPlace[Out]] = Out; - pPrios[pPlace[Out2]] = Out2; - } -} - -/**Function************************************************************* - - Synopsis [Prints out the priorities into the file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibDumpPriorities() -{ - int i, k, Out, Out2, Counter = 0, Printed = 0; - printf( "\nOutput priorities (total = %d):\n", s_DarLib->nSubgrTotal ); - for ( i = 0; i < 222; i++ ) - { -// printf( "Class%d: ", i ); - for ( k = 0; k < s_DarLib->nSubgr[i]; k++ ) - { - Out = s_DarLib->pPrios[i][k]; - Out2 = k == 0 ? Out : s_DarLib->pPrios[i][k-1]; - assert( s_DarLib->pScore[i][Out2] >= s_DarLib->pScore[i][Out] ); -// printf( "%d(%d), ", Out, s_DarLib->pScore[i][Out] ); - printf( "%d, ", Out ); - Printed++; - if ( ++Counter == 15 ) - { - printf( "\n" ); - Counter = 0; - } - } - } - printf( "\n" ); - assert( Printed == s_DarLib->nSubgrTotal ); -} - - -/**Function************************************************************* - - Synopsis [Matches the cut with its canonical form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_LibCutMatch( Dar_Man_t * p, Dar_Cut_t * pCut ) -{ - Aig_Obj_t * pFanin; - unsigned uPhase; - char * pPerm; - int i; - assert( pCut->nLeaves == 4 ); - // get the fanin permutation - uPhase = s_DarLib->pPhases[pCut->uTruth]; - pPerm = s_DarLib->pPerms4[ s_DarLib->pPerms[pCut->uTruth] ]; - // collect fanins with the corresponding permutation/phase - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - { - pFanin = Aig_ManObj( p->pAig, pCut->pLeaves[pPerm[i]] ); - if ( pFanin == NULL ) - { - p->nCutsBad++; - return 0; - } - pFanin = Aig_NotCond(pFanin, ((uPhase >> i) & 1) ); - s_DarLib->pDatas[i].pFunc = pFanin; - s_DarLib->pDatas[i].Level = Aig_Regular(pFanin)->Level; - } - p->nCutsGood++; - return 1; -} - - - -/**Function************************************************************* - - Synopsis [Marks the MFFC of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_LibCutMarkMffc( Aig_Man_t * p, Aig_Obj_t * pRoot, int nLeaves ) -{ - int i, nNodes; - // mark the cut leaves - for ( i = 0; i < nLeaves; i++ ) - Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs++; - // label MFFC with current ID - nNodes = Aig_NodeMffsLabel( p, pRoot ); - // unmark the cut leaves - for ( i = 0; i < nLeaves; i++ ) - Aig_Regular(s_DarLib->pDatas[i].pFunc)->nRefs--; - return nNodes; -} - -/**Function************************************************************* - - Synopsis [Evaluates one cut.] - - Description [Returns the best gain.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibObjPrint_rec( Dar_LibObj_t * pObj ) -{ - if ( pObj->fTerm ) - { - printf( "%c", 'a' + pObj - s_DarLib->pObjs ); - return; - } - printf( "(" ); - Dar_LibObjPrint_rec( Dar_LibObj(s_DarLib, pObj->Fan0) ); - if ( pObj->fCompl0 ) - printf( "\'" ); - Dar_LibObjPrint_rec( Dar_LibObj(s_DarLib, pObj->Fan1) ); - if ( pObj->fCompl0 ) - printf( "\'" ); - printf( ")" ); -} - - -/**Function************************************************************* - - Synopsis [Assigns numbers to the nodes of one class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibEvalAssignNums( Dar_Man_t * p, int Class ) -{ - Dar_LibObj_t * pObj; - Dar_LibDat_t * pData, * pData0, * pData1; - Aig_Obj_t * pFanin0, * pFanin1; - int i; - for ( i = 0; i < s_DarLib->nNodes0[Class]; i++ ) - { - // get one class node, assign its temporary number and set its data - pObj = Dar_LibObj(s_DarLib, s_DarLib->pNodes0[Class][i]); - pObj->Num = 4 + i; - assert( (int)pObj->Num < s_DarLib->nNodes0Max + 4 ); - pData = s_DarLib->pDatas + pObj->Num; - pData->fMffc = 0; - pData->pFunc = NULL; - pData->TravId = 0xFFFF; - - // explore the fanins - assert( (int)Dar_LibObj(s_DarLib, pObj->Fan0)->Num < s_DarLib->nNodes0Max + 4 ); - assert( (int)Dar_LibObj(s_DarLib, pObj->Fan1)->Num < s_DarLib->nNodes0Max + 4 ); - pData0 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan0)->Num; - pData1 = s_DarLib->pDatas + Dar_LibObj(s_DarLib, pObj->Fan1)->Num; - pData->Level = 1 + AIG_MAX(pData0->Level, pData1->Level); - if ( pData0->pFunc == NULL || pData1->pFunc == NULL ) - continue; - pFanin0 = Aig_NotCond( pData0->pFunc, pObj->fCompl0 ); - pFanin1 = Aig_NotCond( pData1->pFunc, pObj->fCompl1 ); - pData->pFunc = Aig_TableLookupTwo( p->pAig, pFanin0, pFanin1 ); - if ( pData->pFunc ) - { - // update the level to be more accurate - pData->Level = Aig_Regular(pData->pFunc)->Level; - // mark the node if it is part of MFFC - pData->fMffc = Aig_ObjIsTravIdCurrent(p->pAig, pData->pFunc); - } - } -} - -/**Function************************************************************* - - Synopsis [Evaluates one cut.] - - Description [Returns the best gain.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_LibEval_rec( Dar_LibObj_t * pObj, int Out, int nNodesSaved, int Required ) -{ - Dar_LibDat_t * pData; - int Area; - if ( pObj->fTerm ) - return 0; - assert( pObj->Num > 3 ); - pData = s_DarLib->pDatas + pObj->Num; - if ( pData->Level > Required ) - return 0xff; - if ( pData->pFunc && !pData->fMffc ) - return 0; - if ( pData->TravId == Out ) - return 0; - pData->TravId = Out; - // this is a new node - get a bound on the area of its branches - nNodesSaved--; - Area = Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan0), Out, nNodesSaved, Required+1 ); - if ( Area > nNodesSaved ) - return 0xff; - Area += Dar_LibEval_rec( Dar_LibObj(s_DarLib, pObj->Fan1), Out, nNodesSaved, Required+1 ); - if ( Area > nNodesSaved ) - return 0xff; - return Area + 1; -} - -/**Function************************************************************* - - Synopsis [Evaluates one cut.] - - Description [Returns the best gain.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibEval( Dar_Man_t * p, Aig_Obj_t * pRoot, Dar_Cut_t * pCut, int Required ) -{ - int fTraining = 0; - Dar_LibObj_t * pObj; - int Out, k, Class, nNodesSaved, nNodesAdded, nNodesGained, clk; - clk = clock(); - if ( pCut->nLeaves != 4 ) - return; - // check if the cut exits and assigns leaves and their levels - if ( !Dar_LibCutMatch(p, pCut) ) - return; - // mark MFFC of the node - nNodesSaved = Dar_LibCutMarkMffc( p->pAig, pRoot, pCut->nLeaves ); - // evaluate the cut - Class = s_DarLib->pMap[pCut->uTruth]; - Dar_LibEvalAssignNums( p, Class ); - // profile outputs by their savings - p->nTotalSubgs += s_DarLib->nSubgr0[Class]; - p->ClassSubgs[Class] += s_DarLib->nSubgr0[Class]; - for ( Out = 0; Out < s_DarLib->nSubgr0[Class]; Out++ ) - { - pObj = Dar_LibObj(s_DarLib, s_DarLib->pSubgr0[Class][Out]); - if ( Aig_Regular(s_DarLib->pDatas[pObj->Num].pFunc) == pRoot ) - continue; - nNodesAdded = Dar_LibEval_rec( pObj, Out, nNodesSaved - !p->pPars->fUseZeros, Required ); - nNodesGained = nNodesSaved - nNodesAdded; - if ( fTraining && nNodesGained >= 0 ) - Dar_LibIncrementScore( Class, Out, nNodesGained + 1 ); - if ( nNodesGained < 0 || (nNodesGained == 0 && !p->pPars->fUseZeros) ) - continue; - if ( nNodesGained < p->GainBest || - (nNodesGained == p->GainBest && s_DarLib->pDatas[pObj->Num].Level >= p->LevelBest) ) - continue; - // remember this possibility - Vec_PtrClear( p->vLeavesBest ); - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - Vec_PtrPush( p->vLeavesBest, s_DarLib->pDatas[k].pFunc ); - p->OutBest = s_DarLib->pSubgr0[Class][Out]; - p->OutNumBest = Out; - p->LevelBest = s_DarLib->pDatas[pObj->Num].Level; - p->GainBest = nNodesGained; - p->ClassBest = Class; - assert( p->LevelBest <= Required ); - } -clk = clock() - clk; -p->ClassTimes[Class] += clk; -p->timeEval += clk; -} - -/**Function************************************************************* - - Synopsis [Clears the fields of the nodes used in this cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_LibBuildClear_rec( Dar_LibObj_t * pObj, int * pCounter ) -{ - if ( pObj->fTerm ) - return; - pObj->Num = (*pCounter)++; - s_DarLib->pDatas[ pObj->Num ].pFunc = NULL; - Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan0), pCounter ); - Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, pObj->Fan1), pCounter ); -} - -/**Function************************************************************* - - Synopsis [Reconstructs the best cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Dar_LibBuildBest_rec( Dar_Man_t * p, Dar_LibObj_t * pObj ) -{ - Aig_Obj_t * pFanin0, * pFanin1; - Dar_LibDat_t * pData = s_DarLib->pDatas + pObj->Num; - if ( pData->pFunc ) - return pData->pFunc; - pFanin0 = Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan0) ); - pFanin1 = Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, pObj->Fan1) ); - pFanin0 = Aig_NotCond( pFanin0, pObj->fCompl0 ); - pFanin1 = Aig_NotCond( pFanin1, pObj->fCompl1 ); - pData->pFunc = Aig_And( p->pAig, pFanin0, pFanin1 ); -// assert( pData->Level == (int)Aig_Regular(pData->pFunc)->Level ); - return pData->pFunc; -} - -/**Function************************************************************* - - Synopsis [Reconstructs the best cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Dar_LibBuildBest( Dar_Man_t * p ) -{ - int i, Counter = 4; - for ( i = 0; i < Vec_PtrSize(p->vLeavesBest); i++ ) - s_DarLib->pDatas[i].pFunc = Vec_PtrEntry( p->vLeavesBest, i ); - Dar_LibBuildClear_rec( Dar_LibObj(s_DarLib, p->OutBest), &Counter ); - return Dar_LibBuildBest_rec( p, Dar_LibObj(s_DarLib, p->OutBest) ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/darMan.c b/src/aig/dar/darMan.c deleted file mode 100644 index 155d48bd..00000000 --- a/src/aig/dar/darMan.c +++ /dev/null @@ -1,132 +0,0 @@ -/**CFile**************************************************************** - - FileName [darMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [AIG manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: darMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dar_Man_t * Dar_ManStart( Aig_Man_t * pAig, Dar_RwrPar_t * pPars ) -{ - Dar_Man_t * p; - // start the manager - p = ALLOC( Dar_Man_t, 1 ); - memset( p, 0, sizeof(Dar_Man_t) ); - p->pPars = pPars; - p->pAig = pAig; - // prepare the internal memory manager - p->pMemCuts = Aig_MmFixedStart( p->pPars->nCutsMax * sizeof(Dar_Cut_t), 1024 ); - // other data - p->vLeavesBest = Vec_PtrAlloc( 4 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_ManStop( Dar_Man_t * p ) -{ - if ( p->pPars->fVerbose ) - Dar_ManPrintStats( p ); - if ( p->pMemCuts ) - Aig_MmFixedStop( p->pMemCuts, 0 ); - if ( p->vLeavesBest ) - Vec_PtrFree( p->vLeavesBest ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_ManPrintStats( Dar_Man_t * p ) -{ - unsigned pCanons[222]; - int Gain, i; - extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); - - Gain = p->nNodesInit - Aig_ManNodeNum(p->pAig); - printf( "Tried = %8d. Beg = %8d. End = %8d. Gain = %6d. (%6.2f %%). Cut mem = %d Mb\n", - p->nNodesTried, p->nNodesInit, Aig_ManNodeNum(p->pAig), Gain, 100.0*Gain/p->nNodesInit, p->nCutMemUsed ); - printf( "Cuts = %8d. Tried = %8d. Used = %8d. Bad = %5d. Skipped = %5d. Ave = %.2f.\n", - p->nCutsAll, p->nCutsTried, p->nCutsUsed, p->nCutsBad, p->nCutsSkipped, - (float)p->nCutsUsed/Aig_ManNodeNum(p->pAig) ); - - printf( "Bufs = %5d. BufMax = %5d. BufReplace = %6d. BufFix = %6d. Levels = %4d.\n", - Aig_ManBufNum(p->pAig), p->pAig->nBufMax, p->pAig->nBufReplaces, p->pAig->nBufFixes, Aig_ManLevels(p->pAig) ); - PRT( "Cuts ", p->timeCuts ); - PRT( "Eval ", p->timeEval ); - PRT( "Other ", p->timeOther ); - PRT( "TOTAL ", p->timeTotal ); - - if ( !p->pPars->fVeryVerbose ) - return; - Dar_LibReturnCanonicals( pCanons ); - for ( i = 0; i < 222; i++ ) - { - if ( p->ClassGains[i] == 0 && p->ClassTimes[i] == 0 ) - continue; - printf( "%3d : ", i ); - printf( "G = %6d (%5.2f %%) ", p->ClassGains[i], Gain? 100.0*p->ClassGains[i]/Gain : 0.0 ); - printf( "S = %8d (%5.2f %%) ", p->ClassSubgs[i], p->nTotalSubgs? 100.0*p->ClassSubgs[i]/p->nTotalSubgs : 0.0 ); - printf( "R = %7d ", p->ClassGains[i]? p->ClassSubgs[i]/p->ClassGains[i] : 9999999 ); - Kit_DsdPrintFromTruth( pCanons + i, 4 ); -// PRTP( "T", p->ClassTimes[i], p->timeEval ); - } -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/darPrec.c b/src/aig/dar/darPrec.c deleted file mode 100644 index c3e62389..00000000 --- a/src/aig/dar/darPrec.c +++ /dev/null @@ -1,388 +0,0 @@ -/**CFile**************************************************************** - - FileName [darPrec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [Truth table precomputation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: darPrec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Allocated one-memory-chunk array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ** Dar_ArrayAlloc( int nCols, int nRows, int Size ) -{ - char ** pRes; - char * pBuffer; - int i; - assert( nCols > 0 && nRows > 0 && Size > 0 ); - pBuffer = ALLOC( char, nCols * (sizeof(void *) + nRows * Size) ); - pRes = (char **)pBuffer; - pRes[0] = pBuffer + nCols * sizeof(void *); - for ( i = 1; i < nCols; i++ ) - pRes[i] = pRes[0] + i * nRows * Size; - return pRes; -} - -/**Function******************************************************************** - - Synopsis [Computes the factorial.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Dar_Factorial( int n ) -{ - int i, Res = 1; - for ( i = 1; i <= n; i++ ) - Res *= i; - return Res; -} - -/**Function******************************************************************** - - Synopsis [Fills in the array of permutations.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Dar_Permutations_rec( char ** pRes, int nFact, int n, char Array[] ) -{ - char ** pNext; - int nFactNext; - int iTemp, iCur, iLast, k; - - if ( n == 1 ) - { - pRes[0][0] = Array[0]; - return; - } - - // get the next factorial - nFactNext = nFact / n; - // get the last entry - iLast = n - 1; - - for ( iCur = 0; iCur < n; iCur++ ) - { - // swap Cur and Last - iTemp = Array[iCur]; - Array[iCur] = Array[iLast]; - Array[iLast] = iTemp; - - // get the pointer to the current section - pNext = pRes + (n - 1 - iCur) * nFactNext; - - // set the last entry - for ( k = 0; k < nFactNext; k++ ) - pNext[k][iLast] = Array[iLast]; - - // call recursively for this part - Dar_Permutations_rec( pNext, nFactNext, n - 1, Array ); - - // swap them back - iTemp = Array[iCur]; - Array[iCur] = Array[iLast]; - Array[iLast] = iTemp; - } -} - -/**Function******************************************************************** - - Synopsis [Computes the set of all permutations.] - - Description [The number of permutations in the array is n!. The number of - entries in each permutation is n. Therefore, the resulting array is a - two-dimentional array of the size: n! x n. To free the resulting array, - call free() on the pointer returned by this procedure.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -char ** Dar_Permutations( int n ) -{ - char Array[50]; - char ** pRes; - int nFact, i; - // allocate memory - nFact = Dar_Factorial( n ); - pRes = (char **)Dar_ArrayAlloc( nFact, n, sizeof(char) ); - // fill in the permutations - for ( i = 0; i < n; i++ ) - Array[i] = i; - Dar_Permutations_rec( pRes, nFact, n, Array ); - // print the permutations -/* - { - int i, k; - for ( i = 0; i < nFact; i++ ) - { - printf( "{" ); - for ( k = 0; k < n; k++ ) - printf( " %d", pRes[i][k] ); - printf( " }\n" ); - } - } -*/ - return pRes; -} - -/**Function************************************************************* - - Synopsis [Permutes the given vector of minterms.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_TruthPermute_int( int * pMints, int nMints, char * pPerm, int nVars, int * pMintsP ) -{ - int m, v; - // clean the storage for minterms - memset( pMintsP, 0, sizeof(int) * nMints ); - // go through minterms and add the variables - for ( m = 0; m < nMints; m++ ) - for ( v = 0; v < nVars; v++ ) - if ( pMints[m] & (1 << v) ) - pMintsP[m] |= (1 << pPerm[v]); -} - -/**Function************************************************************* - - Synopsis [Permutes the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Dar_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse ) -{ - unsigned Result; - int * pMints; - int * pMintsP; - int nMints; - int i, m; - - assert( nVars < 6 ); - nMints = (1 << nVars); - pMints = ALLOC( int, nMints ); - pMintsP = ALLOC( int, nMints ); - for ( i = 0; i < nMints; i++ ) - pMints[i] = i; - - Dar_TruthPermute_int( pMints, nMints, pPerms, nVars, pMintsP ); - - Result = 0; - if ( fReverse ) - { - for ( m = 0; m < nMints; m++ ) - if ( Truth & (1 << pMintsP[m]) ) - Result |= (1 << m); - } - else - { - for ( m = 0; m < nMints; m++ ) - if ( Truth & (1 << m) ) - Result |= (1 << pMintsP[m]); - } - - free( pMints ); - free( pMintsP ); - - return Result; -} - -/**Function************************************************************* - - Synopsis [Changes the phase of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Dar_TruthPolarize( unsigned uTruth, int Polarity, int nVars ) -{ - // elementary truth tables - static unsigned Signs[5] = { - 0xAAAAAAAA, // 1010 1010 1010 1010 1010 1010 1010 1010 - 0xCCCCCCCC, // 1010 1010 1010 1010 1010 1010 1010 1010 - 0xF0F0F0F0, // 1111 0000 1111 0000 1111 0000 1111 0000 - 0xFF00FF00, // 1111 1111 0000 0000 1111 1111 0000 0000 - 0xFFFF0000 // 1111 1111 1111 1111 0000 0000 0000 0000 - }; - unsigned uTruthRes, uCof0, uCof1; - int nMints, Shift, v; - assert( nVars < 6 ); - nMints = (1 << nVars); - uTruthRes = uTruth; - for ( v = 0; v < nVars; v++ ) - if ( Polarity & (1 << v) ) - { - uCof0 = uTruth & ~Signs[v]; - uCof1 = uTruth & Signs[v]; - Shift = (1 << v); - uCof0 <<= Shift; - uCof1 >>= Shift; - uTruth = uCof0 | uCof1; - } - return uTruth; -} - -/**Function************************************************************* - - Synopsis [Computes NPN canonical forms for 4-variable functions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ) -{ - unsigned short * uCanons; - unsigned char * uMap; - unsigned uTruth, uPhase, uPerm; - char ** pPerms4, * uPhases, * uPerms; - int nFuncs, nClasses; - int i, k; - - nFuncs = (1 << 16); - uCanons = ALLOC( unsigned short, nFuncs ); - uPhases = ALLOC( char, nFuncs ); - uPerms = ALLOC( char, nFuncs ); - uMap = ALLOC( unsigned char, nFuncs ); - memset( uCanons, 0, sizeof(unsigned short) * nFuncs ); - memset( uPhases, 0, sizeof(char) * nFuncs ); - memset( uPerms, 0, sizeof(char) * nFuncs ); - memset( uMap, 0, sizeof(unsigned char) * nFuncs ); - pPerms4 = Dar_Permutations( 4 ); - - nClasses = 1; - nFuncs = (1 << 15); - for ( uTruth = 1; uTruth < (unsigned)nFuncs; uTruth++ ) - { - // skip already assigned - if ( uCanons[uTruth] ) - { - assert( uTruth > uCanons[uTruth] ); - uMap[~uTruth & 0xFFFF] = uMap[uTruth] = uMap[uCanons[uTruth]]; - continue; - } - uMap[uTruth] = nClasses++; - for ( i = 0; i < 16; i++ ) - { - uPhase = Dar_TruthPolarize( uTruth, i, 4 ); - for ( k = 0; k < 24; k++ ) - { - uPerm = Dar_TruthPermute( uPhase, pPerms4[k], 4, 0 ); - if ( uCanons[uPerm] == 0 ) - { - uCanons[uPerm] = uTruth; - uPhases[uPerm] = i; - uPerms[uPerm] = k; - - uPerm = ~uPerm & 0xFFFF; - uCanons[uPerm] = uTruth; - uPhases[uPerm] = i | 16; - uPerms[uPerm] = k; - } - else - assert( uCanons[uPerm] == uTruth ); - } - uPhase = Dar_TruthPolarize( ~uTruth & 0xFFFF, i, 4 ); - for ( k = 0; k < 24; k++ ) - { - uPerm = Dar_TruthPermute( uPhase, pPerms4[k], 4, 0 ); - if ( uCanons[uPerm] == 0 ) - { - uCanons[uPerm] = uTruth; - uPhases[uPerm] = i; - uPerms[uPerm] = k; - - uPerm = ~uPerm & 0xFFFF; - uCanons[uPerm] = uTruth; - uPhases[uPerm] = i | 16; - uPerms[uPerm] = k; - } - else - assert( uCanons[uPerm] == uTruth ); - } - } - } - uPhases[(1<<16)-1] = 16; - assert( nClasses == 222 ); - free( pPerms4 ); - if ( puCanons ) - *puCanons = uCanons; - else - free( uCanons ); - if ( puPhases ) - *puPhases = uPhases; - else - free( uPhases ); - if ( puPerms ) - *puPerms = uPerms; - else - free( uPerms ); - if ( puMap ) - *puMap = uMap; - else - free( uMap ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/darRefact.c b/src/aig/dar/darRefact.c deleted file mode 100644 index 142c7721..00000000 --- a/src/aig/dar/darRefact.c +++ /dev/null @@ -1,591 +0,0 @@ -/**CFile**************************************************************** - - FileName [darRefact.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [Refactoring.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: darRefact.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the refactoring manager -typedef struct Ref_Man_t_ Ref_Man_t; -struct Ref_Man_t_ -{ - // input data - Dar_RefPar_t * pPars; // rewriting parameters - Aig_Man_t * pAig; // AIG manager - // computed cuts - Vec_Vec_t * vCuts; // the storage for cuts - // truth table and ISOP - Vec_Ptr_t * vTruthElem; // elementary truth tables - Vec_Ptr_t * vTruthStore; // storage for truth tables - Vec_Int_t * vMemory; // storage for ISOP - Vec_Ptr_t * vCutNodes; // storage for internal nodes of the cut - // various data members - Vec_Ptr_t * vLeavesBest; // the best set of leaves - Kit_Graph_t * pGraphBest; // the best factored form - int GainBest; // the best gain - int LevelBest; // the level of node with the best gain - // node statistics - int nNodesInit; // the initial number of nodes - int nNodesTried; // the number of nodes tried - int nNodesBelow; // the number of nodes below the level limit - int nNodesExten; // the number of nodes with extended cut - int nCutsUsed; // the number of rewriting steps - int nCutsTried; // the number of cuts tries - // timing statistics - int timeCuts; - int timeEval; - int timeOther; - int timeTotal; -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the structure with default assignment of parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_ManDefaultRefParams( Dar_RefPar_t * pPars ) -{ - memset( pPars, 0, sizeof(Dar_RefPar_t) ); - pPars->nMffcMin = 2; // the min MFFC size for which refactoring is used - pPars->nLeafMax = 12; // the max number of leaves of a cut - pPars->nCutsMax = 5; // the max number of cuts to consider - pPars->fUpdateLevel = 0; - pPars->fUseZeros = 0; - pPars->fVerbose = 0; - pPars->fVeryVerbose = 0; -} - -/**Function************************************************************* - - Synopsis [Starts the rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ref_Man_t * Dar_ManRefStart( Aig_Man_t * pAig, Dar_RefPar_t * pPars ) -{ - Ref_Man_t * p; - // start the manager - p = ALLOC( Ref_Man_t, 1 ); - memset( p, 0, sizeof(Ref_Man_t) ); - p->pAig = pAig; - p->pPars = pPars; - // other data - p->vCuts = Vec_VecStart( pPars->nCutsMax ); - p->vTruthElem = Vec_PtrAllocTruthTables( pPars->nLeafMax ); - p->vTruthStore = Vec_PtrAllocSimInfo( 256, Kit_TruthWordNum(pPars->nLeafMax) ); - p->vMemory = Vec_IntAlloc( 1 << 16 ); - p->vCutNodes = Vec_PtrAlloc( 256 ); - p->vLeavesBest = Vec_PtrAlloc( pPars->nLeafMax ); - return p; -} - -/**Function************************************************************* - - Synopsis [Prints out the statistics of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_ManRefPrintStats( Ref_Man_t * p ) -{ - int Gain = p->nNodesInit - Aig_ManNodeNum(p->pAig); - printf( "NodesBeg = %8d. NodesEnd = %8d. Gain = %6d. (%6.2f %%).\n", - p->nNodesInit, Aig_ManNodeNum(p->pAig), Gain, 100.0*Gain/p->nNodesInit ); - printf( "Tried = %6d. Below = %5d. Extended = %5d. Used = %5d. Levels = %4d.\n", - p->nNodesTried, p->nNodesBelow, p->nNodesExten, p->nCutsUsed, Aig_ManLevels(p->pAig) ); - PRT( "Cuts ", p->timeCuts ); - PRT( "Eval ", p->timeEval ); - PRT( "Other ", p->timeOther ); - PRT( "TOTAL ", p->timeTotal ); -} - -/**Function************************************************************* - - Synopsis [Stops the rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dar_ManRefStop( Ref_Man_t * p ) -{ - if ( p->pPars->fVerbose ) - Dar_ManRefPrintStats( p ); - Vec_VecFree( p->vCuts ); - Vec_PtrFree( p->vTruthElem ); - Vec_PtrFree( p->vTruthStore ); - Vec_PtrFree( p->vLeavesBest ); - Vec_IntFree( p->vMemory ); - Vec_PtrFree( p->vCutNodes ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ref_ObjComputeCuts( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Vec_t * vCuts ) -{ -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ref_ObjPrint( Aig_Obj_t * pObj ) -{ - printf( "%d", pObj? Aig_Regular(pObj)->Id : -1 ); - if ( pObj ) - printf( "(%d) ", Aig_IsComplement(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of new nodes added when using this graph.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure. - Returns -1 if the number of nodes and levels exceeded the given limit or - the number of levels exceeded the maximum allowed level.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_RefactTryGraph( Aig_Man_t * pAig, Aig_Obj_t * pRoot, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph, int NodeMax, int LevelMax ) -{ - Kit_Node_t * pNode, * pNode0, * pNode1; - Aig_Obj_t * pAnd, * pAnd0, * pAnd1; - int i, Counter, LevelNew, LevelOld; - // check for constant function or a literal - if ( Kit_GraphIsConst(pGraph) || Kit_GraphIsVar(pGraph) ) - return 0; - // set the levels of the leaves - Kit_GraphForEachLeaf( pGraph, pNode, i ) - { - pNode->pFunc = Vec_PtrEntry(vCut, i); - pNode->Level = Aig_Regular(pNode->pFunc)->Level; - assert( Aig_Regular(pNode->pFunc)->Level < (1<<14)-1 ); - } -//printf( "Trying:\n" ); - // compute the AIG size after adding the internal nodes - Counter = 0; - Kit_GraphForEachNode( pGraph, pNode, i ) - { - // get the children of this node - pNode0 = Kit_GraphNode( pGraph, pNode->eEdge0.Node ); - pNode1 = Kit_GraphNode( pGraph, pNode->eEdge1.Node ); - // get the AIG nodes corresponding to the children - pAnd0 = pNode0->pFunc; - pAnd1 = pNode1->pFunc; - if ( pAnd0 && pAnd1 ) - { - // if they are both present, find the resulting node - pAnd0 = Aig_NotCond( pAnd0, pNode->eEdge0.fCompl ); - pAnd1 = Aig_NotCond( pAnd1, pNode->eEdge1.fCompl ); - pAnd = Aig_TableLookupTwo( pAig, pAnd0, pAnd1 ); - // return -1 if the node is the same as the original root - if ( Aig_Regular(pAnd) == pRoot ) - return -1; - } - else - pAnd = NULL; - // count the number of added nodes - if ( pAnd == NULL || Aig_ObjIsTravIdCurrent(pAig, Aig_Regular(pAnd)) ) - { - if ( ++Counter > NodeMax ) - return -1; - } - // count the number of new levels - LevelNew = 1 + AIG_MAX( pNode0->Level, pNode1->Level ); - if ( pAnd ) - { - if ( Aig_Regular(pAnd) == Aig_ManConst1(pAig) ) - LevelNew = 0; - else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd0) ) - LevelNew = (int)Aig_Regular(pAnd0)->Level; - else if ( Aig_Regular(pAnd) == Aig_Regular(pAnd1) ) - LevelNew = (int)Aig_Regular(pAnd1)->Level; - LevelOld = (int)Aig_Regular(pAnd)->Level; -// assert( LevelNew == LevelOld ); - } - if ( LevelNew > LevelMax ) - return -1; - pNode->pFunc = pAnd; - pNode->Level = LevelNew; -/* -printf( "Checking " ); -Ref_ObjPrint( pAnd0 ); -printf( " and " ); -Ref_ObjPrint( pAnd1 ); -printf( " Result " ); -Ref_ObjPrint( pNode->pFunc ); -printf( "\n" ); -*/ - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Dar_RefactBuildGraph( Aig_Man_t * pAig, Vec_Ptr_t * vCut, Kit_Graph_t * pGraph ) -{ - Aig_Obj_t * pAnd0, * pAnd1; - Kit_Node_t * pNode; - int i; - // check for constant function - if ( Kit_GraphIsConst(pGraph) ) - return Aig_NotCond( Aig_ManConst1(pAig), Kit_GraphIsComplement(pGraph) ); - // set the leaves - Kit_GraphForEachLeaf( pGraph, pNode, i ) - pNode->pFunc = Vec_PtrEntry(vCut, i); - // check for a literal - if ( Kit_GraphIsVar(pGraph) ) - return Aig_NotCond( Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); - // build the AIG nodes corresponding to the AND gates of the graph -//printf( "Building (current number %d):\n", Aig_ManObjNumMax(pAig) ); - Kit_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Aig_NotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Aig_NotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Aig_And( pAig, pAnd0, pAnd1 ); -/* -printf( "Checking " ); -Ref_ObjPrint( pAnd0 ); -printf( " and " ); -Ref_ObjPrint( pAnd1 ); -printf( " Result " ); -Ref_ObjPrint( pNode->pFunc ); -printf( "\n" ); -*/ - } - // complement the result if necessary - return Aig_NotCond( pNode->pFunc, Kit_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_ManRefactorTryCuts( Ref_Man_t * p, Aig_Obj_t * pObj, int nNodesSaved, int Required ) -{ - Vec_Ptr_t * vCut; - Kit_Graph_t * pGraphCur; - int k, RetValue, GainCur, nNodesAdded; - unsigned * pTruth; - - p->GainBest = -1; - p->pGraphBest = NULL; - Vec_VecForEachLevel( p->vCuts, vCut, k ) - { - if ( Vec_PtrSize(vCut) == 0 ) - continue; -// if ( Vec_PtrSize(vCut) != 0 && Vec_PtrSize(Vec_VecEntry(p->vCuts, k+1)) != 0 ) -// continue; - - p->nCutsTried++; - // get the cut nodes - Aig_ObjCollectCut( pObj, vCut, p->vCutNodes ); - // get the truth table - pTruth = Aig_ManCutTruth( pObj, vCut, p->vCutNodes, p->vTruthElem, p->vTruthStore ); - if ( Kit_TruthIsConst0(pTruth, Vec_PtrSize(vCut)) ) - { - p->GainBest = Vec_PtrSize(p->vCutNodes); - p->pGraphBest = Kit_GraphCreateConst0(); - Vec_PtrCopy( p->vLeavesBest, vCut ); - return p->GainBest; - } - if ( Kit_TruthIsConst1(pTruth, Vec_PtrSize(vCut)) ) - { - p->GainBest = Vec_PtrSize(p->vCutNodes); - p->pGraphBest = Kit_GraphCreateConst1(); - Vec_PtrCopy( p->vLeavesBest, vCut ); - return p->GainBest; - } - - // try the positive phase - RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 ); - if ( RetValue > -1 ) - { - pGraphCur = Kit_SopFactor( p->vMemory, 0, Vec_PtrSize(vCut), p->vMemory ); - nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required ); - if ( nNodesAdded > -1 ) - { - GainCur = nNodesSaved - nNodesAdded; - if ( p->GainBest < GainCur || (p->GainBest == GainCur && - (Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) ) - { - p->GainBest = GainCur; - if ( p->pGraphBest ) - Kit_GraphFree( p->pGraphBest ); - p->pGraphBest = pGraphCur; - Vec_PtrCopy( p->vLeavesBest, vCut ); - } - else - Kit_GraphFree( pGraphCur ); - } - else - Kit_GraphFree( pGraphCur ); - } - // try negative phase - Kit_TruthNot( pTruth, pTruth, Vec_PtrSize(vCut) ); - RetValue = Kit_TruthIsop( pTruth, Vec_PtrSize(vCut), p->vMemory, 0 ); - if ( RetValue > -1 ) - { - pGraphCur = Kit_SopFactor( p->vMemory, 1, Vec_PtrSize(vCut), p->vMemory ); - nNodesAdded = Dar_RefactTryGraph( p->pAig, pObj, vCut, pGraphCur, nNodesSaved - !p->pPars->fUseZeros, Required ); - if ( nNodesAdded > -1 ) - { - GainCur = nNodesSaved - nNodesAdded; - if ( p->GainBest < GainCur || (p->GainBest == GainCur && - (Kit_GraphIsConst(pGraphCur) || Kit_GraphRootLevel(pGraphCur) < Kit_GraphRootLevel(p->pGraphBest))) ) - { - p->GainBest = GainCur; - if ( p->pGraphBest ) - Kit_GraphFree( p->pGraphBest ); - p->pGraphBest = pGraphCur; - Vec_PtrCopy( p->vLeavesBest, vCut ); - } - else - Kit_GraphFree( pGraphCur ); - } - else - Kit_GraphFree( pGraphCur ); - } - } - return p->GainBest; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if a non-PI node has nLevelMin or below.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_ObjCutLevelAchieved( Vec_Ptr_t * vCut, int nLevelMin ) -{ - Aig_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( vCut, pObj, i ) - if ( !Aig_ObjIsPi(pObj) && (int)pObj->Level <= nLevelMin ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dar_ManRefactor( Aig_Man_t * pAig, Dar_RefPar_t * pPars ) -{ - Bar_Progress_t * pProgress; - Ref_Man_t * p; - Vec_Ptr_t * vCut, * vCut2; - Aig_Obj_t * pObj, * pObjNew; - int nNodesOld, nNodeBefore, nNodeAfter, nNodesSaved, nNodesSaved2; - int i, Required, nLevelMin, clkStart, clk; - - // start the manager - p = Dar_ManRefStart( pAig, pPars ); - // remove dangling nodes - Aig_ManCleanup( pAig ); - // if updating levels is requested, start fanout and timing - Aig_ManFanoutStart( pAig ); - if ( p->pPars->fUpdateLevel ) - Aig_ManStartReverseLevels( pAig, 0 ); - - // resynthesize each node once - clkStart = clock(); - vCut = Vec_VecEntry( p->vCuts, 0 ); - vCut2 = Vec_VecEntry( p->vCuts, 1 ); - p->nNodesInit = Aig_ManNodeNum(pAig); - nNodesOld = Vec_PtrSize( pAig->vObjs ); - pProgress = Bar_ProgressStart( stdout, nNodesOld ); - Aig_ManForEachObj( pAig, pObj, i ) - { - Bar_ProgressUpdate( pProgress, i, NULL ); - if ( !Aig_ObjIsNode(pObj) ) - continue; - if ( i > nNodesOld ) - break; - Vec_VecClear( p->vCuts ); - -//printf( "\nConsidering node %d.\n", pObj->Id ); - // get the bounded MFFC size -clk = clock(); - nLevelMin = AIG_MAX( 0, Aig_ObjLevel(pObj) - 10 ); - nNodesSaved = Aig_NodeMffsSupp( pAig, pObj, nLevelMin, vCut ); - if ( nNodesSaved < p->pPars->nMffcMin ) // too small to consider - { -p->timeCuts += clock() - clk; - continue; - } - p->nNodesTried++; - if ( Vec_PtrSize(vCut) > p->pPars->nLeafMax ) // get one reconv-driven cut - { - Aig_ManFindCut( pObj, vCut, p->vCutNodes, p->pPars->nLeafMax, 50 ); - nNodesSaved = Aig_NodeMffsLabelCut( p->pAig, pObj, vCut ); - } - else if ( Vec_PtrSize(vCut) < p->pPars->nLeafMax - 2 && p->pPars->fExtend ) - { - if ( !Dar_ObjCutLevelAchieved(vCut, nLevelMin) ) - { - if ( Aig_NodeMffsExtendCut( pAig, pObj, vCut, vCut2 ) ) - { - nNodesSaved2 = Aig_NodeMffsLabelCut( p->pAig, pObj, vCut ); - assert( nNodesSaved2 == nNodesSaved ); - } - if ( Vec_PtrSize(vCut2) > p->pPars->nLeafMax ) - Vec_PtrClear(vCut2); - if ( Vec_PtrSize(vCut2) > 0 ) - { - p->nNodesExten++; -// printf( "%d(%d) ", Vec_PtrSize(vCut), Vec_PtrSize(vCut2) ); - } - } - else - p->nNodesBelow++; - } -p->timeCuts += clock() - clk; - - // try the cuts -clk = clock(); - Required = pAig->vLevelR? Aig_ObjRequiredLevel(pAig, pObj) : AIG_INFINITY; - Dar_ManRefactorTryCuts( p, pObj, nNodesSaved, Required ); -p->timeEval += clock() - clk; - - // check the best gain - if ( !(p->GainBest > 0 || (p->GainBest == 0 && p->pPars->fUseZeros)) ) - { - if ( p->pGraphBest ) - Kit_GraphFree( p->pGraphBest ); - continue; - } -//printf( "\n" ); - - // if we end up here, a rewriting step is accepted - nNodeBefore = Aig_ManNodeNum( pAig ); - pObjNew = Dar_RefactBuildGraph( pAig, p->vLeavesBest, p->pGraphBest ); - assert( (int)Aig_Regular(pObjNew)->Level <= Required ); - // replace the node - Aig_ObjReplace( pAig, pObj, pObjNew, 1, p->pPars->fUpdateLevel ); - // compare the gains - nNodeAfter = Aig_ManNodeNum( pAig ); - assert( p->GainBest <= nNodeBefore - nNodeAfter ); - Kit_GraphFree( p->pGraphBest ); - p->nCutsUsed++; -// break; - } -p->timeTotal = clock() - clkStart; -p->timeOther = p->timeTotal - p->timeCuts - p->timeEval; - - Bar_ProgressStop( pProgress ); - // put the nodes into the DFS order and reassign their IDs -// Aig_NtkReassignIds( p ); - // fix the levels - Aig_ManFanoutStop( pAig ); - if ( p->pPars->fUpdateLevel ) - Aig_ManStopReverseLevels( pAig ); - - // stop the rewriting manager - Dar_ManRefStop( p ); - Aig_ManCheckPhase( pAig ); - if ( !Aig_ManCheck( pAig ) ) - { - printf( "Dar_ManRefactor: The network check has failed.\n" ); - return 0; - } - return 1; - -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/darResub.c b/src/aig/dar/darResub.c deleted file mode 100644 index f819934e..00000000 --- a/src/aig/dar/darResub.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [darResub.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: darResub.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/darScript.c b/src/aig/dar/darScript.c deleted file mode 100644 index 9eb5e280..00000000 --- a/src/aig/dar/darScript.c +++ /dev/null @@ -1,369 +0,0 @@ -/**CFile**************************************************************** - - FileName [darScript.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [Rewriting scripts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: darScript.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" -#include "ioa.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs one iteration of AIG rewriting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_ManRewriteDefault( Aig_Man_t * pAig ) -{ - Aig_Man_t * pTemp; - Dar_RwrPar_t Pars, * pPars = &Pars; - Dar_ManDefaultRwrParams( pPars ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - Dar_ManRewrite( pAig, pPars ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - return pAig; -} - -/**Function************************************************************* - - Synopsis [Reproduces script "compress2".] - - Description [] - - SideEffects [This procedure does not tighten level during restructuring.] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose ) -//alias rwsat "st; rw -l; b -l; rw -l; rf -l" -{ - Aig_Man_t * pTemp; - - Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr; - Dar_RefPar_t ParsRef, * pParsRef = &ParsRef; - - Dar_ManDefaultRwrParams( pParsRwr ); - Dar_ManDefaultRefParams( pParsRef ); - - pParsRwr->fUpdateLevel = 0; - pParsRef->fUpdateLevel = 0; - - pParsRwr->fVerbose = fVerbose; - pParsRef->fVerbose = fVerbose; - - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - // refactor - Dar_ManRefactor( pAig, pParsRef ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - } - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - return pAig; -} - - -/**Function************************************************************* - - Synopsis [Reproduces script "compress".] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_ManCompress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ) -//alias compress2 "b -l; rw -l; rwz -l; b -l; rwz -l; b -l" -{ - Aig_Man_t * pTemp; - - Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr; - Dar_RefPar_t ParsRef, * pParsRef = &ParsRef; - - Dar_ManDefaultRwrParams( pParsRwr ); - Dar_ManDefaultRefParams( pParsRef ); - - pParsRwr->fUpdateLevel = fUpdateLevel; - pParsRef->fUpdateLevel = fUpdateLevel; - - pParsRwr->fVerbose = fVerbose; - pParsRef->fVerbose = fVerbose; - - pAig = Aig_ManDup( pAig, 0 ); - - // balance - if ( fBalance ) - { -// pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); -// Aig_ManStop( pTemp ); - } - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - // refactor - Dar_ManRefactor( pAig, pParsRef ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - } - - pParsRwr->fUseZeros = 1; - pParsRef->fUseZeros = 1; - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - return pAig; -} - -/**Function************************************************************* - - Synopsis [Reproduces script "compress2".] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_ManCompress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ) -//alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l" -{ - Aig_Man_t * pTemp; - - Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr; - Dar_RefPar_t ParsRef, * pParsRef = &ParsRef; - - Dar_ManDefaultRwrParams( pParsRwr ); - Dar_ManDefaultRefParams( pParsRef ); - - pParsRwr->fUpdateLevel = fUpdateLevel; - pParsRef->fUpdateLevel = fUpdateLevel; - - pParsRwr->fVerbose = fVerbose; - pParsRef->fVerbose = fVerbose; - - pAig = Aig_ManDup( pAig, 0 ); - - // balance - if ( fBalance ) - { -// pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); -// Aig_ManStop( pTemp ); - } - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - // refactor - Dar_ManRefactor( pAig, pParsRef ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - // balance -// if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - } - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - pParsRwr->fUseZeros = 1; - pParsRef->fUseZeros = 1; - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - } - - // refactor - Dar_ManRefactor( pAig, pParsRef ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - // rewrite - Dar_ManRewrite( pAig, pParsRwr ); - pAig = Aig_ManDup( pTemp = pAig, 0 ); - Aig_ManStop( pTemp ); - - // balance - if ( fBalance ) - { - pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); - Aig_ManStop( pTemp ); - } - return pAig; -} - -/**Function************************************************************* - - Synopsis [Reproduces script "compress2".] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Dar_ManChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ) -//alias resyn "b; rw; rwz; b; rwz; b" -//alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" -{ - Vec_Ptr_t * vAigs; - vAigs = Vec_PtrAlloc( 3 ); - pAig = Aig_ManDup(pAig, 0); - Vec_PtrPush( vAigs, pAig ); - pAig = Dar_ManCompress (pAig, 0, fUpdateLevel, fVerbose); - Vec_PtrPush( vAigs, pAig ); - pAig = Dar_ManCompress2(pAig, fBalance, fUpdateLevel, fVerbose); - Vec_PtrPush( vAigs, pAig ); - return vAigs; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Dar_ManChoiceSynthesisExt() -{ - Vec_Ptr_t * vAigs; - Aig_Man_t * pMan; - vAigs = Vec_PtrAlloc( 3 ); - pMan = Ioa_ReadAiger( "i10_1.aig", 1 ); - Vec_PtrPush( vAigs, pMan ); - pMan = Ioa_ReadAiger( "i10_2.aig", 1 ); - Vec_PtrPush( vAigs, pMan ); - pMan = Ioa_ReadAiger( "i10_3.aig", 1 ); - Vec_PtrPush( vAigs, pMan ); - return vAigs; -} - -/**Function************************************************************* - - Synopsis [Reproduces script "compress2".] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Dar_ManChoice( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fVerbose ) -{ - Aig_Man_t * pMan, * pTemp; - Vec_Ptr_t * vAigs; - int i, clk; - -clk = clock(); -// vAigs = Dar_ManChoiceSynthesisExt(); - vAigs = Dar_ManChoiceSynthesis( pAig, fBalance, fUpdateLevel, fVerbose ); - - // swap the first and last network - // this should lead to the primary choice being "better" because of synthesis - pMan = Vec_PtrPop( vAigs ); - Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); - Vec_PtrWriteEntry( vAigs, 0, pMan ); - -if ( fVerbose ) -{ -PRT( "Synthesis time", clock() - clk ); -} -clk = clock(); - pMan = Aig_ManChoicePartitioned( vAigs, 300 ); - Vec_PtrForEachEntry( vAigs, pTemp, i ) - Aig_ManStop( pTemp ); - Vec_PtrFree( vAigs ); -if ( fVerbose ) -{ -PRT( "Choicing time ", clock() - clk ); -} - return pMan; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/darTruth.c b/src/aig/dar/darTruth.c deleted file mode 100644 index 7fd47787..00000000 --- a/src/aig/dar/darTruth.c +++ /dev/null @@ -1,353 +0,0 @@ -/**CFile**************************************************************** - - FileName [darTruth.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [Computes the truth table of a cut.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: darTruth.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#if 0 - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCollectCut_rec( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Int_t * vNodes ) -{ - if ( pNode->fMarkA ) - return; - pNode->fMarkA = 1; - assert( Aig_ObjIsAnd(pNode) || Aig_ObjIsExor(pNode) ); - Aig_ManCollectCut_rec( p, Aig_ObjFanin0(pNode), vNodes ); - Aig_ManCollectCut_rec( p, Aig_ObjFanin1(pNode), vNodes ); - Vec_IntPush( vNodes, pNode->Id ); -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [Does not modify the array of leaves. Uses array vTruth to store - temporary truth tables. The returned pointer should be used immediately.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCollectCut( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) -{ - int i, Leaf; - // collect and mark the leaves - Vec_IntClear( vNodes ); - Vec_IntForEachEntry( vLeaves, Leaf, i ) - { - Vec_IntPush( vNodes, Leaf ); - Aig_ManObj(p, Leaf)->fMarkA = 1; - } - // collect and mark the nodes - Aig_ManCollectCut_rec( p, pRoot, vNodes ); - // clean the nodes - Vec_IntForEachEntry( vNodes, Leaf, i ) - Aig_ManObj(p, Leaf)->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Aig_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth ) -{ - return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManCutTruthOne( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Int_t * vTruth, int nWords ) -{ - unsigned * pTruth, * pTruth0, * pTruth1; - int i; - pTruth = Aig_ObjGetTruthStore( pNode->Level, vTruth ); - pTruth0 = Aig_ObjGetTruthStore( Aig_ObjFanin0(pNode)->Level, vTruth ); - pTruth1 = Aig_ObjGetTruthStore( Aig_ObjFanin1(pNode)->Level, vTruth ); - if ( Aig_ObjIsExor(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] ^ pTruth1[i]; - else if ( !Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] & pTruth1[i]; - else if ( !Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] & ~pTruth1[i]; - else if ( Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ~pTruth0[i] & pTruth1[i]; - else // if ( Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [Does not modify the array of leaves. Uses array vTruth to store - temporary truth tables. The returned pointer should be used immediately.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Aig_ManCutTruth( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ) -{ - static unsigned uTruths[8][8] = { // elementary truth tables - { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, - { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, - { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, - { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, - { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, - { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, - { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, - { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } - }; - int i, Leaf; - // collect the cut -// Aig_ManCollectCut( p, pRoot, vLeaves, vNodes ); - // set the node numbers - Vec_IntForEachEntry( vNodes, Leaf, i ) - Aig_ManObj(p, Leaf)->Level = i; - // alloc enough memory - Vec_IntClear( vTruth ); - Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) ); - // set the elementary truth tables - Vec_IntForEachEntry( vLeaves, Leaf, i ) - memcpy( Aig_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) ); - // compute truths for other nodes - Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) ) - Aig_ManCutTruthOne( p, Aig_ManObj(p, Leaf), vTruth, 8 ); - return Aig_ObjGetTruthStore( pRoot->Level, vTruth ); -} - -static inline int Kit_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -static inline void Kit_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~pIn[w]; -} - -/**Function************************************************************* - - Synopsis [Computes the cost based on two ISOPs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManLargeCutEvalIsop( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) -{ - extern int Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth ); - int RetValue, nClauses; - // compute ISOP for the positive phase - RetValue = Kit_TruthIsop( pTruth, nVars, vMemory, 0 ); - if ( RetValue == -1 ) - return AIG_INFINITY; - assert( RetValue == 0 || RetValue == 1 ); - nClauses = Vec_IntSize( vMemory ); - // compute ISOP for the negative phase - Kit_TruthNot( pTruth, pTruth, nVars ); - RetValue = Kit_TruthIsop( pTruth, nVars, vMemory, 0 ); - if ( RetValue == -1 ) - return AIG_INFINITY; - Kit_TruthNot( pTruth, pTruth, nVars ); - assert( RetValue == 0 || RetValue == 1 ); - nClauses += Vec_IntSize( vMemory ); - return nClauses; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManLargeCutCollect_rec( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) -{ - if ( Aig_ObjIsTravIdCurrent(p, pNode) ) - return; - if ( Aig_ObjIsTravIdPrevious(p, pNode) ) - { - Vec_IntPush( vLeaves, pNode->Id ); -// Vec_IntPush( vNodes, pNode->Id ); - Aig_ObjSetTravIdCurrent( p, pNode ); - return; - } - assert( Aig_ObjIsAnd(pNode) || Aig_ObjIsExor(pNode) ); - Aig_ObjSetTravIdCurrent( p, pNode ); - Aig_ManLargeCutCollect_rec( p, Aig_ObjFanin0(pNode), vLeaves, vNodes ); - Aig_ManLargeCutCollect_rec( p, Aig_ObjFanin1(pNode), vLeaves, vNodes ); - Vec_IntPush( vNodes, pNode->Id ); -} - -/**Function************************************************************* - - Synopsis [Collect leaves and nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Aig_ManLargeCutCollect( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Cut_t * pCutR, Aig_Cut_t * pCutL, int Leaf, - Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) -{ - Vec_Int_t * vTemp; - Aig_Obj_t * pObj; - int Node, i; - - Aig_ManIncrementTravId( p ); - Aig_CutForEachLeaf( p, pCutR, pObj, i ) - if ( pObj->Id != Leaf ) - Aig_ObjSetTravIdCurrent( p, pObj ); - Aig_CutForEachLeaf( p, pCutL, pObj, i ) - Aig_ObjSetTravIdCurrent( p, pObj ); - - // collect the internal nodes and leaves - Aig_ManIncrementTravId( p ); - vTemp = Vec_IntAlloc( 100 ); - Aig_ManLargeCutCollect_rec( p, pRoot, vLeaves, vTemp ); - - Vec_IntForEachEntry( vLeaves, Node, i ) - Vec_IntPush( vNodes, Node ); - Vec_IntForEachEntry( vTemp, Node, i ) - Vec_IntPush( vNodes, Node ); - - Vec_IntFree( vTemp ); - -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Aig_ManLargeCutEval( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Cut_t * pCutR, Aig_Cut_t * pCutL, int Leaf ) -{ - Vec_Int_t * vLeaves, * vNodes, * vTruth, * vMemory; - unsigned * pTruth; - int RetValue; -// Aig_Obj_t * pObj; - - vMemory = Vec_IntAlloc( 1 << 16 ); - vTruth = Vec_IntAlloc( 1 << 16 ); - vLeaves = Vec_IntAlloc( 100 ); - vNodes = Vec_IntAlloc( 100 ); - - Aig_ManLargeCutCollect( p, pRoot, pCutR, pCutL, Leaf, vLeaves, vNodes ); -/* - // collect the nodes - Aig_CutForEachLeaf( p, pCutR, pObj, i ) - { - if ( pObj->Id == Leaf ) - continue; - if ( pObj->fMarkA ) - continue; - pObj->fMarkA = 1; - Vec_IntPush( vLeaves, pObj->Id ); - Vec_IntPush( vNodes, pObj->Id ); - } - Aig_CutForEachLeaf( p, pCutL, pObj, i ) - { - if ( pObj->fMarkA ) - continue; - pObj->fMarkA = 1; - Vec_IntPush( vLeaves, pObj->Id ); - Vec_IntPush( vNodes, pObj->Id ); - } - // collect and mark the nodes - Aig_ManCollectCut_rec( p, pRoot, vNodes ); - // clean the nodes - Vec_IntForEachEntry( vNodes, Leaf, i ) - Aig_ManObj(p, Leaf)->fMarkA = 0; -*/ - - pTruth = Aig_ManCutTruth( p, pRoot, vLeaves, vNodes, vTruth ); - RetValue = Aig_ManLargeCutEvalIsop( pTruth, Vec_IntSize(vLeaves), vMemory ); - - Vec_IntFree( vLeaves ); - Vec_IntFree( vNodes ); - Vec_IntFree( vTruth ); - Vec_IntFree( vMemory ); - - return RetValue; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/dar_.c b/src/aig/dar/dar_.c deleted file mode 100644 index 12fd7d17..00000000 --- a/src/aig/dar/dar_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [dar_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: dar_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "darInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/dar/module.make b/src/aig/dar/module.make deleted file mode 100644 index 0a1f7687..00000000 --- a/src/aig/dar/module.make +++ /dev/null @@ -1,11 +0,0 @@ -SRC += src/aig/dar/darBalance.c \ - src/aig/dar/darCore.c \ - src/aig/dar/darCut.c \ - src/aig/dar/darData.c \ - src/aig/dar/darLib.c \ - src/aig/dar/darMan.c \ - src/aig/dar/darPrec.c \ - src/aig/dar/darRefact.c \ - src/aig/dar/darResub.c \ - src/aig/dar/darScript.c \ - src/aig/dar/darTruth.c diff --git a/src/aig/deco/deco.h b/src/aig/deco/deco.h deleted file mode 100644 index 67126902..00000000 --- a/src/aig/deco/deco.h +++ /dev/null @@ -1,703 +0,0 @@ -/**CFile**************************************************************** - - FileName [deco.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [A simple decomposition tree/node data structure and its APIs.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: deco.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DEC_H__ -#define __DEC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dec_Edge_t_ Dec_Edge_t; -struct Dec_Edge_t_ -{ - unsigned fCompl : 1; // the complemented bit - unsigned Node : 30; // the decomposition node pointed by the edge -}; - -typedef struct Dec_Node_t_ Dec_Node_t; -struct Dec_Node_t_ -{ - Dec_Edge_t eEdge0; // the left child of the node - Dec_Edge_t eEdge1; // the right child of the node - // other info - void * pFunc; // the function of the node (BDD or AIG) - unsigned Level : 14; // the level of this node in the global AIG - // printing info - unsigned fNodeOr : 1; // marks the original OR node - unsigned fCompl0 : 1; // marks the original complemented edge - unsigned fCompl1 : 1; // marks the original complemented edge - // latch info - unsigned nLat0 : 5; // the number of latches on the first edge - unsigned nLat1 : 5; // the number of latches on the second edge - unsigned nLat2 : 5; // the number of latches on the output edge -}; - -typedef struct Dec_Graph_t_ Dec_Graph_t; -struct Dec_Graph_t_ -{ - int fConst; // marks the constant 1 graph - int nLeaves; // the number of leaves - int nSize; // the number of nodes (including the leaves) - int nCap; // the number of allocated nodes - Dec_Node_t * pNodes; // the array of leaves and internal nodes - Dec_Edge_t eRoot; // the pointer to the topmost node -}; - -typedef struct Dec_Man_t_ Dec_Man_t; -struct Dec_Man_t_ -{ - void * pMvcMem; // memory manager for MVC cover (used for factoring) - Vec_Int_t * vCubes; // storage for cubes - Vec_Int_t * vLits; // storage for literals - // precomputation information about 4-variable functions - unsigned short * puCanons; // canonical forms - char * pPhases; // canonical phases - char * pPerms; // canonical permutations - unsigned char * pMap; // mapping of functions into class numbers -}; - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// interator throught the leaves -#define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \ - for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ ) -// interator throught the internal nodes -#define Dec_GraphForEachNode( pGraph, pAnd, i ) \ - for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates an edge pointing to the node in the given polarity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl ) -{ - Dec_Edge_t eEdge = { fCompl, Node }; - return eEdge; -} - -/**Function************************************************************* - - Synopsis [Converts the edge into unsigned integer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge ) -{ - return (eEdge.Node << 1) | eEdge.fCompl; -} - -/**Function************************************************************* - - Synopsis [Converts unsigned integer into the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge ) -{ - return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); -} - -/**Function************************************************************* - - Synopsis [Converts the edge into unsigned integer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge ) -{ - return *(unsigned *)&eEdge; -} - -/**Function************************************************************* - - Synopsis [Converts unsigned integer into the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge ) -{ - return *(Dec_Edge_t *)&Edge; -} - -/**Function************************************************************* - - Synopsis [Creates a graph with the given number of leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves ) -{ - Dec_Graph_t * pGraph; - pGraph = ALLOC( Dec_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Dec_Graph_t) ); - pGraph->nLeaves = nLeaves; - pGraph->nSize = nLeaves; - pGraph->nCap = 2 * nLeaves + 50; - pGraph->pNodes = ALLOC( Dec_Node_t, pGraph->nCap ); - memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates constant 0 graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreateConst0() -{ - Dec_Graph_t * pGraph; - pGraph = ALLOC( Dec_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Dec_Graph_t) ); - pGraph->fConst = 1; - pGraph->eRoot.fCompl = 1; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates constant 1 graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreateConst1() -{ - Dec_Graph_t * pGraph; - pGraph = ALLOC( Dec_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Dec_Graph_t) ); - pGraph->fConst = 1; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates the literal graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ) -{ - Dec_Graph_t * pGraph; - assert( 0 <= iLeaf && iLeaf < nLeaves ); - pGraph = Dec_GraphCreate( nLeaves ); - pGraph->eRoot.Node = iLeaf; - pGraph->eRoot.fCompl = fCompl; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates a graph with the given number of leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Dec_GraphFree( Dec_Graph_t * pGraph ) -{ - FREE( pGraph->pNodes ); - free( pGraph ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is a constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphIsConst( Dec_Graph_t * pGraph ) -{ - return pGraph->fConst; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphIsConst0( Dec_Graph_t * pGraph ) -{ - return pGraph->fConst && pGraph->eRoot.fCompl; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is constant 1.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphIsConst1( Dec_Graph_t * pGraph ) -{ - return pGraph->fConst && !pGraph->eRoot.fCompl; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is complemented.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphIsComplement( Dec_Graph_t * pGraph ) -{ - return pGraph->eRoot.fCompl; -} - -/**Function************************************************************* - - Synopsis [Checks if the graph is complemented.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Dec_GraphComplement( Dec_Graph_t * pGraph ) -{ - pGraph->eRoot.fCompl ^= 1; -} - - -/**Function************************************************************* - - Synopsis [Returns the number of leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph ) -{ - return pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Returns the number of internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph ) -{ - return pGraph->nSize - pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i ) -{ - return pGraph->pNodes + i; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph ) -{ - return pGraph->pNodes + pGraph->nSize - 1; -} - -/**Function************************************************************* - - Synopsis [Returns the number of the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) -{ - return pNode - pGraph->pNodes; -} - -/**Function************************************************************* - - Synopsis [Check if the graph represents elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphIsVar( Dec_Graph_t * pGraph ) -{ - return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Check if the graph represents elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) -{ - return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Returns the elementary variable elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph ) -{ - assert( Dec_GraphIsVar( pGraph ) ); - return Dec_GraphNode( pGraph, pGraph->eRoot.Node ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of the elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph ) -{ - assert( Dec_GraphIsVar( pGraph ) ); - return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Sets the root of the graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot ) -{ - pGraph->eRoot = eRoot; -} - -/**Function************************************************************* - - Synopsis [Appends a new node to the graph.] - - Description [This procedure is meant for internal use.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph ) -{ - Dec_Node_t * pNode; - if ( pGraph->nSize == pGraph->nCap ) - { - pGraph->pNodes = REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); - pGraph->nCap = 2 * pGraph->nCap; - } - pNode = pGraph->pNodes + pGraph->nSize++; - memset( pNode, 0, sizeof(Dec_Node_t) ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates an AND node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) -{ - Dec_Node_t * pNode; - // get the new node - pNode = Dec_GraphAppendNode( pGraph ); - // set the inputs and other info - pNode->eEdge0 = eEdge0; - pNode->eEdge1 = eEdge1; - pNode->fCompl0 = eEdge0.fCompl; - pNode->fCompl1 = eEdge1.fCompl; - return Dec_EdgeCreate( pGraph->nSize - 1, 0 ); -} - -/**Function************************************************************* - - Synopsis [Creates an OR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) -{ - Dec_Node_t * pNode; - // get the new node - pNode = Dec_GraphAppendNode( pGraph ); - // set the inputs and other info - pNode->eEdge0 = eEdge0; - pNode->eEdge1 = eEdge1; - pNode->fCompl0 = eEdge0.fCompl; - pNode->fCompl1 = eEdge1.fCompl; - // make adjustments for the OR gate - pNode->fNodeOr = 1; - pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl; - pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl; - return Dec_EdgeCreate( pGraph->nSize - 1, 1 ); -} - -/**Function************************************************************* - - Synopsis [Creates an XOR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type ) -{ - Dec_Edge_t eNode0, eNode1, eNode; - if ( Type == 0 ) - { - // derive the first AND - eEdge0.fCompl ^= 1; - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - eEdge0.fCompl ^= 1; - // derive the second AND - eEdge1.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - } - else - { - // derive the first AND - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the second AND - eEdge0.fCompl ^= 1; - eEdge1.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - eNode.fCompl ^= 1; - } - return eNode; -} - -/**Function************************************************************* - - Synopsis [Creates an XOR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type ) -{ - Dec_Edge_t eNode0, eNode1, eNode; - if ( Type == 0 ) - { - // derive the first AND - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); - // derive the second AND - eEdgeC.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - } - else - { - // complement the arguments - eEdgeT.fCompl ^= 1; - eEdgeE.fCompl ^= 1; - // derive the first AND - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); - // derive the second AND - eEdgeC.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - eNode.fCompl ^= 1; - } - return eNode; -} - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/deco/module.make b/src/aig/deco/module.make deleted file mode 100644 index d6d908e7..00000000 --- a/src/aig/deco/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += diff --git a/src/aig/fra/fra.h b/src/aig/fra/fra.h deleted file mode 100644 index 210af244..00000000 --- a/src/aig/fra/fra.h +++ /dev/null @@ -1,300 +0,0 @@ -/**CFile**************************************************************** - - FileName [fra.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [[New FRAIG package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fra.h,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __FRA_H__ -#define __FRA_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "vec.h" -#include "aig.h" -#include "dar.h" -#include "satSolver.h" -#include "bar.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Fra_Par_t_ Fra_Par_t; -typedef struct Fra_Man_t_ Fra_Man_t; -typedef struct Fra_Cla_t_ Fra_Cla_t; -typedef struct Fra_Sml_t_ Fra_Sml_t; -typedef struct Fra_Bmc_t_ Fra_Bmc_t; - -// FRAIG parameters -struct Fra_Par_t_ -{ - int nSimWords; // the number of words in the simulation info - double dSimSatur; // the ratio of refined classes when saturation is reached - int fPatScores; // enables simulation pattern scoring - int MaxScore; // max score after which resimulation is used - double dActConeRatio; // the ratio of cone to be bumped - double dActConeBumpMax; // the largest bump in activity - int fChoicing; // enables choicing - int fSpeculate; // use speculative reduction - int fProve; // prove the miter outputs - int fVerbose; // verbose output - int fDoSparse; // skip sparse functions - int fConeBias; // bias variables in the cone (good for unsat runs) - int nBTLimitNode; // conflict limit at a node - int nBTLimitMiter; // conflict limit at an output - int nFramesP; // the number of timeframes to in the prefix - int nFramesK; // the number of timeframes to unroll - int nMaxImps; // the maximum number of implications to consider - int fRewrite; // use rewriting for constraint reduction - int fLatchCorr; // computes latch correspondence only - int fUseImps; // use implications - int fWriteImps; // record implications -}; - -// FRAIG equivalence classes -struct Fra_Cla_t_ -{ - Aig_Man_t * pAig; // the original AIG manager - Aig_Obj_t ** pMemRepr; // pointers to representatives of each node - Vec_Ptr_t * vClasses; // equivalence classes - Vec_Ptr_t * vClasses1; // equivalence class of Const1 node - Vec_Ptr_t * vClassesTemp; // temporary storage for new classes - Aig_Obj_t ** pMemClasses; // memory allocated for equivalence classes - Aig_Obj_t ** pMemClassesFree; // memory allocated for equivalence classes to be used - Vec_Ptr_t * vClassOld; // old equivalence class after splitting - Vec_Ptr_t * vClassNew; // new equivalence class(es) after splitting - int nPairs; // the number of pairs of nodes - int fRefinement; // set to 1 when refinement has happened - Vec_Int_t * vImps; // implications - // procedures used for class refinement - int (*pFuncNodeHash) (Aig_Obj_t *, int); // returns has key of the node - int (*pFuncNodeIsConst) (Aig_Obj_t *); // returns 1 if the node is a constant - int (*pFuncNodesAreEqual)(Aig_Obj_t *, Aig_Obj_t *); // returns 1 if nodes are equal up to a complement -}; - -// simulation manager -struct Fra_Sml_t_ -{ - Aig_Man_t * pAig; // the original AIG manager - int nPref; // the number of times frames in the prefix - int nFrames; // the number of times frames - int nWordsFrame; // the number of words in each time frame - int nWordsTotal; // the total number of words at a node - int nWordsPref; // the number of word in the prefix - int fNonConstOut; // have seen a non-const-0 output during simulation - int nSimRounds; // statistics - int timeSim; // statistics - unsigned pData[0]; // simulation data for the nodes -}; - -// FRAIG manager -struct Fra_Man_t_ -{ - // high-level data - Fra_Par_t * pPars; // parameters governing fraiging - // AIG managers - Aig_Man_t * pManAig; // the starting AIG manager - Aig_Man_t * pManFraig; // the final AIG manager - // mapping AIG into FRAIG - int nFramesAll; // the number of timeframes used - Aig_Obj_t ** pMemFraig; // memory allocated for points to the fraig nodes - int nSizeAlloc; // allocated size of the arrays for timeframe nodes - // equivalence classes - Fra_Cla_t * pCla; // representation of (candidate) equivalent nodes - // simulation info - Fra_Sml_t * pSml; // simulation manager - // bounded model checking manager - Fra_Bmc_t * pBmc; - // counter example storage - int nPatWords; // the number of words in the counter example - unsigned * pPatWords; // the counter example - Vec_Int_t * vCex; - // satisfiability solving - sat_solver * pSat; // SAT solver - int nSatVars; // the number of variables currently used - Vec_Ptr_t * vPiVars; // the PIs of the cone used - sint64 nBTLimitGlobal; // resource limit - sint64 nInsLimitGlobal; // resource limit - Vec_Ptr_t ** pMemFanins; // the arrays of fanins for some FRAIG nodes - int * pMemSatNums; // the array of SAT numbers for some FRAIG nodes - int nMemAlloc; // allocated size of the arrays for FRAIG varnums and fanins - Vec_Ptr_t * vTimeouts; // the nodes, for which equivalence checking timed out - // statistics - int nSimRounds; - int nNodesMiter; - int nLitsBeg; - int nLitsEnd; - int nNodesBeg; - int nNodesEnd; - int nRegsBeg; - int nRegsEnd; - int nSatCalls; - int nSatCallsSat; - int nSatCallsUnsat; - int nSatProof; - int nSatFails; - int nSatFailsReal; - int nSpeculs; - int nChoices; - int nChoicesFake; - int nSatCallsRecent; - int nSatCallsSkipped; - // runtime - int timeSim; - int timeTrav; - int timeRwr; - int timeSat; - int timeSatUnsat; - int timeSatSat; - int timeSatFail; - int timeRef; - int timeTotal; - int time1; - int time2; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline unsigned * Fra_ObjSim( Fra_Sml_t * p, int Id ) { return p->pData + p->nWordsTotal * Id; } -static inline unsigned Fra_ObjRandomSim() { return (rand() << 24) ^ (rand() << 12) ^ rand(); } - -static inline Aig_Obj_t * Fra_ObjFraig( Aig_Obj_t * pObj, int i ) { return ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i]; } -static inline void Fra_ObjSetFraig( Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pMemFraig[((Fra_Man_t *)pObj->pData)->nFramesAll*pObj->Id + i] = pNode; } - -static inline Vec_Ptr_t * Fra_ObjFaninVec( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id]; } -static inline void Fra_ObjSetFaninVec( Aig_Obj_t * pObj, Vec_Ptr_t * vFanins ) { ((Fra_Man_t *)pObj->pData)->pMemFanins[pObj->Id] = vFanins; } - -static inline int Fra_ObjSatNum( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id]; } -static inline void Fra_ObjSetSatNum( Aig_Obj_t * pObj, int Num ) { ((Fra_Man_t *)pObj->pData)->pMemSatNums[pObj->Id] = Num; } - -static inline Aig_Obj_t * Fra_ClassObjRepr( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id]; } -static inline void Fra_ClassObjSetRepr( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pCla->pMemRepr[pObj->Id] = pNode; } - -static inline Aig_Obj_t * Fra_ObjChild0Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Fra_ObjChild1Fra( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Fra_ObjFraig(Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } - -static inline int Fra_ImpLeft( int Imp ) { return Imp & 0xFFFF; } -static inline int Fra_ImpRight( int Imp ) { return Imp >> 16; } -static inline int Fra_ImpCreate( int Left, int Right ) { return (Right << 16) | Left; } - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== fraClass.c ========================================================*/ -extern int Fra_BmcNodeIsConst( Aig_Obj_t * pObj ); -extern int Fra_BmcNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); -extern void Fra_BmcStop( Fra_Bmc_t * p ); -extern void Fra_BmcPerform( Fra_Man_t * p, int nPref, int nDepth ); -/*=== fraClass.c ========================================================*/ -extern Fra_Cla_t * Fra_ClassesStart( Aig_Man_t * pAig ); -extern void Fra_ClassesStop( Fra_Cla_t * p ); -extern void Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed ); -extern void Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose ); -extern void Fra_ClassesPrepare( Fra_Cla_t * p, int fLatchCorr ); -extern int Fra_ClassesRefine( Fra_Cla_t * p ); -extern int Fra_ClassesRefine1( Fra_Cla_t * p, int fRefineNewClass, int * pSkipped ); -extern int Fra_ClassesCountLits( Fra_Cla_t * p ); -extern int Fra_ClassesCountPairs( Fra_Cla_t * p ); -extern void Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 ); -extern void Fra_ClassesLatchCorr( Fra_Man_t * p ); -extern void Fra_ClassesPostprocess( Fra_Cla_t * p ); -extern void Fra_ClassesSelectRepr( Fra_Cla_t * p ); -extern Aig_Man_t * Fra_ClassesDeriveAig( Fra_Cla_t * p, int nFramesK ); -/*=== fraCnf.c ========================================================*/ -extern void Fra_CnfNodeAddToSolver( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); -/*=== fraCore.c ========================================================*/ -extern void Fra_FraigSweep( Fra_Man_t * pManAig ); -extern int Fra_FraigMiterStatus( Aig_Man_t * p ); -extern Aig_Man_t * Fra_FraigPerform( Aig_Man_t * pManAig, Fra_Par_t * pPars ); -extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax ); -extern Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax ); -/*=== fraImp.c ========================================================*/ -extern Vec_Int_t * Fra_ImpDerive( Fra_Man_t * p, int nImpMaxLimit, int nImpUseLimit, int fLatchCorr ); -extern void Fra_ImpAddToSolver( Fra_Man_t * p, Vec_Int_t * vImps, int * pSatVarNums ); -extern int Fra_ImpCheckForNode( Fra_Man_t * p, Vec_Int_t * vImps, Aig_Obj_t * pNode, int Pos ); -extern int Fra_ImpRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vImps ); -extern void Fra_ImpCompactArray( Vec_Int_t * vImps ); -extern double Fra_ImpComputeStateSpaceRatio( Fra_Man_t * p ); -extern int Fra_ImpVerifyUsingSimulation( Fra_Man_t * p ); -extern void Fra_ImpRecordInManager( Fra_Man_t * p, Aig_Man_t * pNew ); -/*=== fraInd.c ========================================================*/ -extern Aig_Man_t * Fra_FraigInduction( Aig_Man_t * p, int nFramesP, int nFramesK, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose, int * pnIter ); -/*=== fraLcr.c ========================================================*/ -extern Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter ); -/*=== fraMan.c ========================================================*/ -extern void Fra_ParamsDefault( Fra_Par_t * pParams ); -extern void Fra_ParamsDefaultSeq( Fra_Par_t * pParams ); -extern Fra_Man_t * Fra_ManStart( Aig_Man_t * pManAig, Fra_Par_t * pParams ); -extern void Fra_ManClean( Fra_Man_t * p, int nNodesMax ); -extern Aig_Man_t * Fra_ManPrepareComb( Fra_Man_t * p ); -extern void Fra_ManFinalizeComb( Fra_Man_t * p ); -extern void Fra_ManStop( Fra_Man_t * p ); -extern void Fra_ManPrint( Fra_Man_t * p ); -/*=== fraSat.c ========================================================*/ -extern int Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); -extern int Fra_NodesAreImp( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR ); -extern int Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew ); -/*=== fraSec.c ========================================================*/ -extern int Fra_FraigSec( Aig_Man_t * p, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ); -/*=== fraSim.c ========================================================*/ -extern int Fra_SmlNodeHash( Aig_Obj_t * pObj, int nTableSize ); -extern int Fra_SmlNodeIsConst( Aig_Obj_t * pObj ); -extern int Fra_SmlNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ); -extern int Fra_SmlNodeNotEquWeight( Fra_Sml_t * p, int Left, int Right ); -extern int Fra_SmlCheckOutput( Fra_Man_t * p ); -extern void Fra_SmlSavePattern( Fra_Man_t * p ); -extern void Fra_SmlSimulate( Fra_Man_t * p, int fInit ); -extern void Fra_SmlResimulate( Fra_Man_t * p ); -extern Fra_Sml_t * Fra_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ); -extern void Fra_SmlStop( Fra_Sml_t * p ); -extern Fra_Sml_t * Fra_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ); -extern Fra_Sml_t * Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords ); - - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/fra/fraBmc.c b/src/aig/fra/fraBmc.c deleted file mode 100644 index 1140f3a4..00000000 --- a/src/aig/fra/fraBmc.c +++ /dev/null @@ -1,362 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraBmc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [Bounded model checking.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraBmc.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// simulation manager -struct Fra_Bmc_t_ -{ - // parameters - int nPref; // the size of the prefix - int nDepth; // the depth of the frames - int nFramesAll; // the total number of timeframes - // implications to be filtered - Vec_Int_t * vImps; - // AIG managers - Aig_Man_t * pAig; // the original AIG manager - Aig_Man_t * pAigFrames; // initialized timeframes - Aig_Man_t * pAigFraig; // the fraiged initialized timeframes - // mapping of nodes - Aig_Obj_t ** pObjToFrames; // mapping of the original node into frames - Aig_Obj_t ** pObjToFraig; // mapping of the frames node into fraig -}; - -static inline Aig_Obj_t * Bmc_ObjFrames( Aig_Obj_t * pObj, int i ) { return ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFrames[((Fra_Man_t *)pObj->pData)->pBmc->nFramesAll*pObj->Id + i]; } -static inline void Bmc_ObjSetFrames( Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFrames[((Fra_Man_t *)pObj->pData)->pBmc->nFramesAll*pObj->Id + i] = pNode; } - -static inline Aig_Obj_t * Bmc_ObjFraig( Aig_Obj_t * pObj ) { return ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFraig[pObj->Id]; } -static inline void Bmc_ObjSetFraig( Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ((Fra_Man_t *)pObj->pData)->pBmc->pObjToFraig[pObj->Id] = pNode; } - -static inline Aig_Obj_t * Bmc_ObjChild0Frames( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond(Bmc_ObjFrames(Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } -static inline Aig_Obj_t * Bmc_ObjChild1Frames( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond(Bmc_ObjFrames(Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns 1 if the nodes are equivalent.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_BmcNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) -{ - Fra_Man_t * p = pObj0->pData; - Aig_Obj_t * pObjFrames0, * pObjFrames1; - Aig_Obj_t * pObjFraig0, * pObjFraig1; - int i; - for ( i = p->pBmc->nPref; i < p->pBmc->nFramesAll; i++ ) - { - pObjFrames0 = Aig_Regular( Bmc_ObjFrames(pObj0, i) ); - pObjFrames1 = Aig_Regular( Bmc_ObjFrames(pObj1, i) ); - if ( pObjFrames0 == pObjFrames1 ) - continue; - pObjFraig0 = Aig_Regular( Bmc_ObjFraig(pObjFrames0) ); - pObjFraig1 = Aig_Regular( Bmc_ObjFraig(pObjFrames1) ); - if ( pObjFraig0 != pObjFraig1 ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is costant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_BmcNodeIsConst( Aig_Obj_t * pObj ) -{ - Fra_Man_t * p = pObj->pData; - return Fra_BmcNodesAreEqual( pObj, Aig_ManConst1(p->pManAig) ); -} - -/**Function************************************************************* - - Synopsis [Refines implications using BMC.] - - Description [The input is the combinational FRAIG manager, - which is used to FRAIG the timeframes. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_BmcFilterImplications( Fra_Man_t * p, Fra_Bmc_t * pBmc ) -{ - Aig_Obj_t * pLeft, * pRight; - Aig_Obj_t * pLeftT, * pRightT; - Aig_Obj_t * pLeftF, * pRightF; - int i, f, Imp, Left, Right; - int fComplL, fComplR; - assert( p->nFramesAll == 1 ); - assert( p->pManAig == pBmc->pAigFrames ); - Vec_IntForEachEntry( pBmc->vImps, Imp, i ) - { - if ( Imp == 0 ) - continue; - Left = Fra_ImpLeft(Imp); - Right = Fra_ImpRight(Imp); - // get the corresponding nodes - pLeft = Aig_ManObj( pBmc->pAig, Left ); - pRight = Aig_ManObj( pBmc->pAig, Right ); - // iterate through the timeframes - for ( f = pBmc->nPref; f < pBmc->nFramesAll; f++ ) - { - // get timeframe nodes - pLeftT = Bmc_ObjFrames( pLeft, f ); - pRightT = Bmc_ObjFrames( pRight, f ); - // get the corresponding FRAIG nodes - pLeftF = Fra_ObjFraig( Aig_Regular(pLeftT), 0 ); - pRightF = Fra_ObjFraig( Aig_Regular(pRightT), 0 ); - // get the complemented attributes - fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF) ^ Aig_IsComplement(pLeftT); - fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF) ^ Aig_IsComplement(pRightT); - // check equality - if ( Aig_Regular(pLeftF) == Aig_Regular(pRightF) ) - { - if ( fComplL == fComplR ) // x => x - always true - continue; - assert( fComplL != fComplR ); - // consider 4 possibilities: - // NOT(1) => 1 or 0 => 1 - always true - // 1 => NOT(1) or 1 => 0 - never true - // NOT(x) => x or x - not always true - // x => NOT(x) or NOT(x) - not always true - if ( Aig_ObjIsConst1(Aig_Regular(pLeftF)) && fComplL ) // proved implication - continue; - // disproved implication - Vec_IntWriteEntry( pBmc->vImps, i, 0 ); - break; - } - // check the implication - if ( Fra_NodesAreImp( p, Aig_Regular(pLeftF), Aig_Regular(pRightF), fComplL, fComplR ) != 1 ) - { - Vec_IntWriteEntry( pBmc->vImps, i, 0 ); - break; - } - } - } - Fra_ImpCompactArray( pBmc->vImps ); -} - - -/**Function************************************************************* - - Synopsis [Starts the BMC manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Bmc_t * Fra_BmcStart( Aig_Man_t * pAig, int nPref, int nDepth ) -{ - Fra_Bmc_t * p; - p = ALLOC( Fra_Bmc_t, 1 ); - memset( p, 0, sizeof(Fra_Bmc_t) ); - p->pAig = pAig; - p->nPref = nPref; - p->nDepth = nDepth; - p->nFramesAll = nPref + nDepth; - p->pObjToFrames = ALLOC( Aig_Obj_t *, p->nFramesAll * Aig_ManObjNumMax(pAig) ); - memset( p->pObjToFrames, 0, sizeof(Aig_Obj_t *) * p->nFramesAll * Aig_ManObjNumMax(pAig) ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the BMC manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_BmcStop( Fra_Bmc_t * p ) -{ - Aig_ManStop( p->pAigFrames ); - Aig_ManStop( p->pAigFraig ); - free( p->pObjToFrames ); - free( p->pObjToFraig ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Constructs initialized timeframes of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_BmcFrames( Fra_Bmc_t * p ) -{ - Aig_Man_t * pAigFrames; - Aig_Obj_t * pObj, * pObjNew; - Aig_Obj_t ** pLatches; - int i, k, f; - - // start the fraig package - pAigFrames = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * p->nFramesAll ); - pAigFrames->pName = Aig_UtilStrsav( p->pAig->pName ); - // create PI nodes for the frames - for ( f = 0; f < p->nFramesAll; f++ ) - Bmc_ObjSetFrames( Aig_ManConst1(p->pAig), f, Aig_ManConst1(pAigFrames) ); - for ( f = 0; f < p->nFramesAll; f++ ) - Aig_ManForEachPiSeq( p->pAig, pObj, i ) - Bmc_ObjSetFrames( pObj, f, Aig_ObjCreatePi(pAigFrames) ); - // set initial state for the latches - Aig_ManForEachLoSeq( p->pAig, pObj, i ) - Bmc_ObjSetFrames( pObj, 0, Aig_ManConst0(pAigFrames) ); - - // add timeframes - pLatches = ALLOC( Aig_Obj_t *, Aig_ManRegNum(p->pAig) ); - for ( f = 0; f < p->nFramesAll; f++ ) - { - // add internal nodes of this frame - Aig_ManForEachNode( p->pAig, pObj, i ) - { - pObjNew = Aig_And( pAigFrames, Bmc_ObjChild0Frames(pObj,f), Bmc_ObjChild1Frames(pObj,f) ); - Bmc_ObjSetFrames( pObj, f, pObjNew ); - } - if ( f == p->nFramesAll - 1 ) - break; - // save the latch input values - k = 0; - Aig_ManForEachLiSeq( p->pAig, pObj, i ) - pLatches[k++] = Bmc_ObjChild0Frames(pObj,f); - assert( k == Aig_ManRegNum(p->pAig) ); - // insert them to the latch output values - k = 0; - Aig_ManForEachLoSeq( p->pAig, pObj, i ) - Bmc_ObjSetFrames( pObj, f+1, pLatches[k++] ); - assert( k == Aig_ManRegNum(p->pAig) ); - } - free( pLatches ); - // add POs to all the dangling nodes - Aig_ManForEachObj( pAigFrames, pObjNew, i ) - if ( Aig_ObjIsNode(pObjNew) && pObjNew->nRefs == 0 ) - Aig_ObjCreatePo( pAigFrames, pObjNew ); - - // return the new manager - return pAigFrames; -} - -/**Function************************************************************* - - Synopsis [Performs BMC for the given AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_BmcPerform( Fra_Man_t * p, int nPref, int nDepth ) -{ - Aig_Obj_t * pObj; - int i, nImpsOld, clk = clock(); - assert( p->pBmc == NULL ); - // derive and fraig the frames - p->pBmc = Fra_BmcStart( p->pManAig, nPref, nDepth ); - p->pBmc->pAigFrames = Fra_BmcFrames( p->pBmc ); - // if implications are present, configure the AIG manager to check them - if ( p->pCla->vImps ) - { - p->pBmc->pAigFrames->pImpFunc = Fra_BmcFilterImplications; - p->pBmc->pAigFrames->pImpData = p->pBmc; - p->pBmc->vImps = p->pCla->vImps; - nImpsOld = Vec_IntSize(p->pCla->vImps); - } - p->pBmc->pAigFraig = Fra_FraigEquivence( p->pBmc->pAigFrames, 1000000 ); - p->pBmc->pObjToFraig = p->pBmc->pAigFrames->pObjCopies; - p->pBmc->pAigFrames->pObjCopies = NULL; - // annotate frames nodes with pointers to the manager - Aig_ManForEachObj( p->pBmc->pAigFrames, pObj, i ) - pObj->pData = p; - // report the results - if ( p->pPars->fVerbose ) - { - printf( "Original AIG = %d. Init %d frames = %d. Fraig = %d. ", - Aig_ManNodeNum(p->pBmc->pAig), p->pBmc->nFramesAll, - Aig_ManNodeNum(p->pBmc->pAigFrames), Aig_ManNodeNum(p->pBmc->pAigFraig) ); - PRT( "Time", clock() - clk ); - printf( "Before BMC: " ); -// Fra_ClassesPrint( p->pCla, 0 ); - printf( "Const = %5d. Class = %5d. Lit = %5d. ", - Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); - if ( p->pCla->vImps ) - printf( "Imp = %5d. ", nImpsOld ); - printf( "\n" ); - } - // refine the classes - p->pCla->pFuncNodeIsConst = Fra_BmcNodeIsConst; - p->pCla->pFuncNodesAreEqual = Fra_BmcNodesAreEqual; - Fra_ClassesRefine( p->pCla ); - Fra_ClassesRefine1( p->pCla, 1, NULL ); - p->pCla->pFuncNodeIsConst = Fra_SmlNodeIsConst; - p->pCla->pFuncNodesAreEqual = Fra_SmlNodesAreEqual; - // report the results - if ( p->pPars->fVerbose ) - { - printf( "After BMC: " ); -// Fra_ClassesPrint( p->pCla, 0 ); - printf( "Const = %5d. Class = %5d. Lit = %5d. ", - Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); - if ( p->pCla->vImps ) - printf( "Imp = %5d. ", Vec_IntSize(p->pCla->vImps) ); - printf( "\n" ); - } - // free the BMC manager - Fra_BmcStop( p->pBmc ); - p->pBmc = NULL; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraCec.c b/src/aig/fra/fraCec.c deleted file mode 100644 index e705f4fc..00000000 --- a/src/aig/fra/fraCec.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraCec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [CEC engined based on fraiging.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraCec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraClass.c b/src/aig/fra/fraClass.c deleted file mode 100644 index a03fa6e5..00000000 --- a/src/aig/fra/fraClass.c +++ /dev/null @@ -1,854 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraClass.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraClass.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -/* - The candidate equivalence classes are stored as a vector of pointers - to the array of pointers to the nodes in each class. - The first node of the class is its representative node. - The representative has the smallest topological order among the class nodes. - The nodes inside each class are ordered according to their topological order. - The classes are ordered according to the topological order of their representatives. - The array of pointers to the class nodes is terminated with a NULL pointer. - To enable dynamic addition of new classes (during class refinement), - each array has at least as many NULLs in the end, as there are nodes in the class. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline Aig_Obj_t * Fra_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } -static inline void Fra_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Cla_t * Fra_ClassesStart( Aig_Man_t * pAig ) -{ - Fra_Cla_t * p; - p = ALLOC( Fra_Cla_t, 1 ); - memset( p, 0, sizeof(Fra_Cla_t) ); - p->pAig = pAig; - p->pMemRepr = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) ); - memset( p->pMemRepr, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(pAig) ); - p->vClasses = Vec_PtrAlloc( 100 ); - p->vClasses1 = Vec_PtrAlloc( 100 ); - p->vClassesTemp = Vec_PtrAlloc( 100 ); - p->vClassOld = Vec_PtrAlloc( 100 ); - p->vClassNew = Vec_PtrAlloc( 100 ); - p->pFuncNodeHash = Fra_SmlNodeHash; - p->pFuncNodeIsConst = Fra_SmlNodeIsConst; - p->pFuncNodesAreEqual = Fra_SmlNodesAreEqual; - return p; -} - -/**Function************************************************************* - - Synopsis [Stop representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClassesStop( Fra_Cla_t * p ) -{ - FREE( p->pMemClasses ); - FREE( p->pMemRepr ); - if ( p->vClassesTemp ) Vec_PtrFree( p->vClassesTemp ); - if ( p->vClassNew ) Vec_PtrFree( p->vClassNew ); - if ( p->vClassOld ) Vec_PtrFree( p->vClassOld ); - if ( p->vClasses1 ) Vec_PtrFree( p->vClasses1 ); - if ( p->vClasses ) Vec_PtrFree( p->vClasses ); - if ( p->vImps ) Vec_IntFree( p->vImps ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Starts representation of equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClassesCopyReprs( Fra_Cla_t * p, Vec_Ptr_t * vFailed ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManReprStart( p->pAig, Aig_ManObjNumMax(p->pAig) ); - memmove( p->pAig->pReprs, p->pMemRepr, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p->pAig) ); - if ( Vec_PtrSize(p->vClasses1) == 0 && Vec_PtrSize(p->vClasses) == 0 ) - { - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( p->pAig->pReprs[i] != NULL ) - printf( "Classes are not cleared!\n" ); - assert( p->pAig->pReprs[i] == NULL ); - } - } - if ( vFailed ) - Vec_PtrForEachEntry( vFailed, pObj, i ) - p->pAig->pReprs[pObj->Id] = NULL; -} - -/**Function************************************************************* - - Synopsis [Prints simulation classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClassCount( Aig_Obj_t ** pClass ) -{ - Aig_Obj_t * pTemp; - int i; - for ( i = 0; pTemp = pClass[i]; i++ ); - return i; -} - -/**Function************************************************************* - - Synopsis [Count the number of literals.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClassesCountLits( Fra_Cla_t * p ) -{ - Aig_Obj_t ** pClass; - int i, nNodes, nLits = 0; - nLits = Vec_PtrSize( p->vClasses1 ); - Vec_PtrForEachEntry( p->vClasses, pClass, i ) - { - nNodes = Fra_ClassCount( pClass ); - assert( nNodes > 1 ); - nLits += nNodes - 1; - } - return nLits; -} - -/**Function************************************************************* - - Synopsis [Count the number of pairs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClassesCountPairs( Fra_Cla_t * p ) -{ - Aig_Obj_t ** pClass; - int i, nNodes, nPairs = 0; - Vec_PtrForEachEntry( p->vClasses, pClass, i ) - { - nNodes = Fra_ClassCount( pClass ); - assert( nNodes > 1 ); - nPairs += nNodes * (nNodes - 1) / 2; - } - return nPairs; -} - -/**Function************************************************************* - - Synopsis [Prints simulation classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_PrintClass( Aig_Obj_t ** pClass ) -{ - Aig_Obj_t * pTemp; - int i; - for ( i = 1; pTemp = pClass[i]; i++ ) - assert( Fra_ClassObjRepr(pTemp) == pClass[0] ); - printf( "{ " ); - for ( i = 0; pTemp = pClass[i]; i++ ) - printf( "%d(%d) ", pTemp->Id, pTemp->Level ); - printf( "}\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints simulation classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClassesPrint( Fra_Cla_t * p, int fVeryVerbose ) -{ - Aig_Obj_t ** pClass; - Aig_Obj_t * pObj; - int i; - - printf( "Const = %5d. Class = %5d. Lit = %5d. ", - Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses), Fra_ClassesCountLits(p) ); - if ( p->vImps && Vec_IntSize(p->vImps) > 0 ) - printf( "Imp = %5d. ", Vec_IntSize(p->vImps) ); - printf( "\n" ); - - if ( fVeryVerbose ) - { - Vec_PtrForEachEntry( p->vClasses1, pObj, i ) - assert( Fra_ClassObjRepr(pObj) == Aig_ManConst1(p->pAig) ); - printf( "Constants { " ); - Vec_PtrForEachEntry( p->vClasses1, pObj, i ) - printf( "%d ", pObj->Id ); - printf( "}\n" ); - Vec_PtrForEachEntry( p->vClasses, pClass, i ) - { - printf( "%3d (%3d) : ", i, Fra_ClassCount(pClass) ); - Fra_PrintClass( pClass ); - } - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Creates initial simulation classes.] - - Description [Assumes that simulation info is assigned.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClassesPrepare( Fra_Cla_t * p, int fLatchCorr ) -{ - Aig_Obj_t ** ppTable, ** ppNexts; - Aig_Obj_t * pObj, * pTemp; - int i, k, nTableSize, nEntries, nNodes, iEntry; - - // allocate the hash table hashing simulation info into nodes - nTableSize = Aig_PrimeCudd( Aig_ManObjNumMax(p->pAig) ); - ppTable = ALLOC( Aig_Obj_t *, nTableSize ); - ppNexts = ALLOC( Aig_Obj_t *, nTableSize ); - memset( ppTable, 0, sizeof(Aig_Obj_t *) * nTableSize ); - - // add all the nodes to the hash table - Vec_PtrClear( p->vClasses1 ); - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( fLatchCorr ) - { - if ( !Aig_ObjIsPi(pObj) ) - continue; - } - else - { - if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) - continue; - // skip the node with more that the given number of levels -// if ( pObj->Level > 3 ) -// continue; - } - // hash the node by its simulation info - iEntry = p->pFuncNodeHash( pObj, nTableSize ); - // check if the node belongs to the class of constant 1 - if ( p->pFuncNodeIsConst( pObj ) ) - { - Vec_PtrPush( p->vClasses1, pObj ); - Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pAig) ); - continue; - } - // add the node to the class - if ( ppTable[iEntry] == NULL ) - { - ppTable[iEntry] = pObj; - Fra_ObjSetNext( ppNexts, pObj, pObj ); - } - else - { - Fra_ObjSetNext( ppNexts, pObj, Fra_ObjNext(ppNexts,ppTable[iEntry]) ); - Fra_ObjSetNext( ppNexts, ppTable[iEntry], pObj ); - } - } - - // count the total number of nodes in the non-trivial classes - // mark the representative nodes of each equivalence class - nEntries = 0; - for ( i = 0; i < nTableSize; i++ ) - if ( ppTable[i] && ppTable[i] != Fra_ObjNext(ppNexts, ppTable[i]) ) - { - for ( pTemp = Fra_ObjNext(ppNexts, ppTable[i]), k = 1; - pTemp != ppTable[i]; - pTemp = Fra_ObjNext(ppNexts, pTemp), k++ ); - assert( k > 1 ); - nEntries += k; - // mark the node - assert( ppTable[i]->fMarkA == 0 ); - ppTable[i]->fMarkA = 1; - } - - // allocate room for classes - p->pMemClasses = ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->vClasses1)) ); - p->pMemClassesFree = p->pMemClasses + 2*nEntries; - - // copy the entries into storage in the topological order - Vec_PtrClear( p->vClasses ); - nEntries = 0; - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) - continue; - // skip the nodes that are not representatives of non-trivial classes - if ( pObj->fMarkA == 0 ) - continue; - pObj->fMarkA = 0; - // add the class of nodes - Vec_PtrPush( p->vClasses, p->pMemClasses + 2*nEntries ); - // count the number of entries in this class - for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1; - pTemp != pObj; - pTemp = Fra_ObjNext(ppNexts, pTemp), k++ ); - nNodes = k; - assert( nNodes > 1 ); - // add the nodes to the class in the topological order - p->pMemClasses[2*nEntries] = pObj; - for ( pTemp = Fra_ObjNext(ppNexts, pObj), k = 1; - pTemp != pObj; - pTemp = Fra_ObjNext(ppNexts, pTemp), k++ ) - { - p->pMemClasses[2*nEntries+nNodes-k] = pTemp; - Fra_ClassObjSetRepr( pTemp, pObj ); - } - // add as many empty entries - p->pMemClasses[2*nEntries + nNodes] = NULL; - // increment the number of entries - nEntries += k; - } - free( ppTable ); - free( ppNexts ); - // now it is time to refine the classes - Fra_ClassesRefine( p ); -} - -/**Function************************************************************* - - Synopsis [Refines one class using simulation info.] - - Description [Returns the new class if refinement happened.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t ** Fra_RefineClassOne( Fra_Cla_t * p, Aig_Obj_t ** ppClass ) -{ - Aig_Obj_t * pObj, ** ppThis; - int i; - assert( ppClass[0] != NULL && ppClass[1] != NULL ); - - // check if the class is going to be refined - for ( ppThis = ppClass + 1; pObj = *ppThis; ppThis++ ) - if ( !p->pFuncNodesAreEqual(ppClass[0], pObj) ) - break; - if ( pObj == NULL ) - return NULL; - // split the class - Vec_PtrClear( p->vClassOld ); - Vec_PtrClear( p->vClassNew ); - Vec_PtrPush( p->vClassOld, ppClass[0] ); - for ( ppThis = ppClass + 1; pObj = *ppThis; ppThis++ ) - if ( p->pFuncNodesAreEqual(ppClass[0], pObj) ) - Vec_PtrPush( p->vClassOld, pObj ); - else - Vec_PtrPush( p->vClassNew, pObj ); -/* - printf( "Refining class (" ); - Vec_PtrForEachEntry( p->vClassOld, pObj, i ) - printf( "%d,", pObj->Id ); - printf( ") + (" ); - Vec_PtrForEachEntry( p->vClassNew, pObj, i ) - printf( "%d,", pObj->Id ); - printf( ")\n" ); -*/ - // put the nodes back into the class memory - Vec_PtrForEachEntry( p->vClassOld, pObj, i ) - { - ppClass[i] = pObj; - ppClass[Vec_PtrSize(p->vClassOld)+i] = NULL; - Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL ); - } - ppClass += 2*Vec_PtrSize(p->vClassOld); - // put the new nodes into the class memory - Vec_PtrForEachEntry( p->vClassNew, pObj, i ) - { - ppClass[i] = pObj; - ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL; - Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL ); - } - return ppClass; -} - -/**Function************************************************************* - - Synopsis [Iteratively refines the classes after simulation.] - - Description [Returns the number of refinements performed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_RefineClassLastIter( Fra_Cla_t * p, Vec_Ptr_t * vClasses ) -{ - Aig_Obj_t ** pClass, ** pClass2; - int nRefis; - pClass = Vec_PtrEntryLast( vClasses ); - for ( nRefis = 0; pClass2 = Fra_RefineClassOne( p, pClass ); nRefis++ ) - { - // if the original class is trivial, remove it - if ( pClass[1] == NULL ) - Vec_PtrPop( vClasses ); - // if the new class is trivial, stop - if ( pClass2[1] == NULL ) - { - nRefis++; - break; - } - // othewise, add the class and continue - assert( pClass2[0] != NULL ); - Vec_PtrPush( vClasses, pClass2 ); - pClass = pClass2; - } - return nRefis; -} - -/**Function************************************************************* - - Synopsis [Refines the classes after simulation.] - - Description [Assumes that simulation info is assigned. Returns the - number of classes refined.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClassesRefine( Fra_Cla_t * p ) -{ - Vec_Ptr_t * vTemp; - Aig_Obj_t ** pClass; - int i, nRefis; - // refine the classes - nRefis = 0; - Vec_PtrClear( p->vClassesTemp ); - Vec_PtrForEachEntry( p->vClasses, pClass, i ) - { - // add the class to the new array - assert( pClass[0] != NULL ); - Vec_PtrPush( p->vClassesTemp, pClass ); - // refine the class iteratively - nRefis += Fra_RefineClassLastIter( p, p->vClassesTemp ); - } - // exchange the class representation - vTemp = p->vClassesTemp; - p->vClassesTemp = p->vClasses; - p->vClasses = vTemp; - return nRefis; -} - -/**Function************************************************************* - - Synopsis [Refines constant 1 equivalence class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ClassesRefine1( Fra_Cla_t * p, int fRefineNewClass, int * pSkipped ) -{ - Aig_Obj_t * pObj, ** ppClass; - int i, k, nRefis = 1; - // check if there is anything to refine - if ( Vec_PtrSize(p->vClasses1) == 0 ) - return 0; - // make sure constant 1 class contains only non-constant nodes - assert( Vec_PtrEntry(p->vClasses1,0) != Aig_ManConst1(p->pAig) ); - // collect all the nodes to be refined - k = 0; - Vec_PtrClear( p->vClassNew ); - Vec_PtrForEachEntry( p->vClasses1, pObj, i ) - { - if ( p->pFuncNodeIsConst( pObj ) ) - Vec_PtrWriteEntry( p->vClasses1, k++, pObj ); - else - Vec_PtrPush( p->vClassNew, pObj ); - } - Vec_PtrShrink( p->vClasses1, k ); - if ( Vec_PtrSize(p->vClassNew) == 0 ) - return 0; -/* - printf( "Refined const-1 class: {" ); - Vec_PtrForEachEntry( p->vClassNew, pObj, i ) - printf( " %d", pObj->Id ); - printf( " }\n" ); -*/ - if ( Vec_PtrSize(p->vClassNew) == 1 ) - { - Fra_ClassObjSetRepr( Vec_PtrEntry(p->vClassNew,0), NULL ); - return 1; - } - // create a new class composed of these nodes - ppClass = p->pMemClassesFree; - p->pMemClassesFree += 2 * Vec_PtrSize(p->vClassNew); - Vec_PtrForEachEntry( p->vClassNew, pObj, i ) - { - ppClass[i] = pObj; - ppClass[Vec_PtrSize(p->vClassNew)+i] = NULL; - Fra_ClassObjSetRepr( pObj, i? ppClass[0] : NULL ); - } - assert( ppClass[0] != NULL ); - Vec_PtrPush( p->vClasses, ppClass ); - // iteratively refine this class - if ( fRefineNewClass ) - nRefis += Fra_RefineClassLastIter( p, p->vClasses ); - else if ( pSkipped ) - (*pSkipped)++; - return nRefis; -} - -/**Function************************************************************* - - Synopsis [Starts representation of equivalence classes with one class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClassesTest( Fra_Cla_t * p, int Id1, int Id2 ) -{ - Aig_Obj_t ** pClass; - p->pMemClasses = ALLOC( Aig_Obj_t *, 4 ); - pClass = p->pMemClasses; - assert( Id1 < Id2 ); - pClass[0] = Aig_ManObj( p->pAig, Id1 ); - pClass[1] = Aig_ManObj( p->pAig, Id2 ); - pClass[2] = NULL; - pClass[3] = NULL; - Fra_ClassObjSetRepr( pClass[1], pClass[0] ); - Vec_PtrPush( p->vClasses, pClass ); -} - -/**Function************************************************************* - - Synopsis [Creates latch correspondence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClassesLatchCorr( Fra_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i, nEntries = 0; - Vec_PtrClear( p->pCla->vClasses1 ); - Aig_ManForEachLoSeq( p->pManAig, pObj, i ) - { - Vec_PtrPush( p->pCla->vClasses1, pObj ); - Fra_ClassObjSetRepr( pObj, Aig_ManConst1(p->pManAig) ); - } - // allocate room for classes - p->pCla->pMemClasses = ALLOC( Aig_Obj_t *, 2*(nEntries + Vec_PtrSize(p->pCla->vClasses1)) ); - p->pCla->pMemClassesFree = p->pCla->pMemClasses + 2*nEntries; -} - -/**Function************************************************************* - - Synopsis [Postprocesses the classes by removing half of the less useful.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClassesPostprocess( Fra_Cla_t * p ) -{ - int Ratio = 2; - Fra_Sml_t * pComb; - Aig_Obj_t * pObj, * pRepr, ** ppClass; - int * pWeights, WeightMax = 0, i, k, c; - // perform combinational simulation - pComb = Fra_SmlSimulateComb( p->pAig, 32 ); - // compute the weight of each node in the classes - pWeights = ALLOC( int, Aig_ManObjNumMax(p->pAig) ); - memset( pWeights, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) ); - Aig_ManForEachObj( p->pAig, pObj, i ) - { - pRepr = Fra_ClassObjRepr( pObj ); - if ( pRepr == NULL ) - continue; - pWeights[i] = Fra_SmlNodeNotEquWeight( pComb, pRepr->Id, pObj->Id ); - WeightMax = AIG_MAX( WeightMax, pWeights[i] ); - } - Fra_SmlStop( pComb ); - printf( "Before: Const = %6d. Class = %6d. ", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) ); - // remove nodes from classes whose weight is less than WeightMax/Ratio - k = 0; - Vec_PtrForEachEntry( p->vClasses1, pObj, i ) - { - if ( pWeights[pObj->Id] >= WeightMax/Ratio ) - Vec_PtrWriteEntry( p->vClasses1, k++, pObj ); - else - Fra_ClassObjSetRepr( pObj, NULL ); - } - Vec_PtrShrink( p->vClasses1, k ); - // in each class, compact the nodes - Vec_PtrForEachEntry( p->vClasses, ppClass, i ) - { - k = 1; - for ( c = 1; ppClass[c]; c++ ) - { - if ( pWeights[ppClass[c]->Id] >= WeightMax/Ratio ) - ppClass[k++] = ppClass[c]; - else - Fra_ClassObjSetRepr( ppClass[c], NULL ); - } - ppClass[k] = NULL; - } - // remove classes with only repr - k = 0; - Vec_PtrForEachEntry( p->vClasses, ppClass, i ) - if ( ppClass[1] != NULL ) - Vec_PtrWriteEntry( p->vClasses, k++, ppClass ); - Vec_PtrShrink( p->vClasses, k ); - printf( "After: Const = %6d. Class = %6d. \n", Vec_PtrSize(p->vClasses1), Vec_PtrSize(p->vClasses) ); - free( pWeights ); -} - -/**Function************************************************************* - - Synopsis [Postprocesses the classes by selecting representative lowest in top order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClassesSelectRepr( Fra_Cla_t * p ) -{ - Aig_Obj_t ** pClass, * pNodeMin; - int i, c, cMinSupp, nSuppSizeMin, nSuppSizeCur; - // reassign representatives in each class - Vec_PtrForEachEntry( p->vClasses, pClass, i ) - { - // collect support sizes and find the min-support node - pNodeMin = NULL; - nSuppSizeMin = AIG_INFINITY; - for ( c = 0; pClass[c]; c++ ) - { - nSuppSizeCur = Aig_SupportSize( p->pAig, pClass[c] ); -// nSuppSizeCur = 1; - if ( nSuppSizeMin > nSuppSizeCur || - (nSuppSizeMin == nSuppSizeCur && pNodeMin->Level > pClass[c]->Level) ) - { - nSuppSizeMin = nSuppSizeCur; - pNodeMin = pClass[c]; - cMinSupp = c; - } - } - // skip the case when the repr did not change - if ( cMinSupp == 0 ) - continue; - // make the new node the representative of the class - pClass[cMinSupp] = pClass[0]; - pClass[0] = pNodeMin; - // set the representative - for ( c = 0; pClass[c]; c++ ) - Fra_ClassObjSetRepr( pClass[c], c? pClass[0] : NULL ); - } -} - - - -static inline Aig_Obj_t * Fra_ObjEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return ppEquivs[pObj->Id]; } -static inline void Fra_ObjSetEqu( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj, Aig_Obj_t * pNode ) { ppEquivs[pObj->Id] = pNode; } - -static inline Aig_Obj_t * Fra_ObjChild0Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj)); } -static inline Aig_Obj_t * Fra_ObjChild1Equ( Aig_Obj_t ** ppEquivs, Aig_Obj_t * pObj ) { return Aig_NotCond(Fra_ObjEqu(ppEquivs,Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj)); } - -/**Function************************************************************* - - Synopsis [Add the node and its constraints to the new AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fra_ClassesDeriveNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, Aig_Obj_t ** ppEquivs ) -{ - Aig_Obj_t * pObjNew, * pObjRepr, * pObjReprNew, * pMiter;//, * pObjNew2; - // skip nodes without representative - if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL ) - return; - assert( pObjRepr->Id < pObj->Id ); - // get the new node - pObjNew = Fra_ObjEqu( ppEquivs, pObj ); - // get the new node of the representative - pObjReprNew = Fra_ObjEqu( ppEquivs, pObjRepr ); - // if this is the same node, no need to add constraints - if ( Aig_Regular(pObjNew) == Aig_Regular(pObjReprNew) ) - return; - // these are different nodes - perform speculative reduction -// pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase ); - // set the new node -// Fra_ObjSetEqu( ppEquivs, pObj, pObjNew2 ); - // add the constraint - pMiter = Aig_Exor( pManFraig, Aig_Regular(pObjNew), Aig_Regular(pObjReprNew) ); - pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) ); - pMiter = Aig_Not( pMiter ); - Aig_ObjCreatePo( pManFraig, pMiter ); -} - -/**Function************************************************************* - - Synopsis [Derives AIG for the partitioned problem.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_ClassesDeriveAig( Fra_Cla_t * p, int nFramesK ) -{ - Aig_Man_t * pManFraig; - Aig_Obj_t * pObj, * pObjNew; - Aig_Obj_t ** pLatches, ** ppEquivs; - int i, k, f, nFramesAll = nFramesK + 1; - assert( Aig_ManRegNum(p->pAig) > 0 ); - assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) ); - assert( nFramesK > 0 ); - // start the fraig package - pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pAig) * nFramesAll ); - pManFraig->pName = Aig_UtilStrsav( p->pAig->pName ); - // allocate place for the node mapping - ppEquivs = ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p->pAig) ); - Fra_ObjSetEqu( ppEquivs, Aig_ManConst1(p->pAig), Aig_ManConst1(pManFraig) ); - // create latches for the first frame - Aig_ManForEachLoSeq( p->pAig, pObj, i ) - Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreatePi(pManFraig) ); - // add timeframes - pLatches = ALLOC( Aig_Obj_t *, Aig_ManRegNum(p->pAig) ); - for ( f = 0; f < nFramesAll; f++ ) - { - // create PIs for this frame - Aig_ManForEachPiSeq( p->pAig, pObj, i ) - Fra_ObjSetEqu( ppEquivs, pObj, Aig_ObjCreatePi(pManFraig) ); - // set the constraints on the latch outputs - Aig_ManForEachLoSeq( p->pAig, pObj, i ) - Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs ); - // add internal nodes of this frame - Aig_ManForEachNode( p->pAig, pObj, i ) - { - pObjNew = Aig_And( pManFraig, Fra_ObjChild0Equ(ppEquivs, pObj), Fra_ObjChild1Equ(ppEquivs, pObj) ); - Fra_ObjSetEqu( ppEquivs, pObj, pObjNew ); - Fra_ClassesDeriveNode( pManFraig, pObj, ppEquivs ); - } - if ( f == nFramesAll - 1 ) - break; - if ( f == nFramesAll - 2 ) - pManFraig->nAsserts = Aig_ManPoNum(pManFraig); - // save the latch input values - k = 0; - Aig_ManForEachLiSeq( p->pAig, pObj, i ) - pLatches[k++] = Fra_ObjChild0Equ( ppEquivs, pObj ); - // insert them to the latch output values - k = 0; - Aig_ManForEachLoSeq( p->pAig, pObj, i ) - Fra_ObjSetEqu( ppEquivs, pObj, pLatches[k++] ); - } - free( pLatches ); - free( ppEquivs ); - // mark the asserts - assert( Aig_ManPoNum(pManFraig) % nFramesAll == 0 ); -printf( "Assert miters = %6d. Output miters = %6d.\n", - pManFraig->nAsserts, Aig_ManPoNum(pManFraig) - pManFraig->nAsserts ); - // remove dangling nodes - Aig_ManCleanup( pManFraig ); - return pManFraig; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraCnf.c b/src/aig/fra/fraCnf.c deleted file mode 100644 index d56c0254..00000000 --- a/src/aig/fra/fraCnf.c +++ /dev/null @@ -1,286 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraCnf.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraCnf.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_AddClausesMux( Fra_Man_t * p, Aig_Obj_t * pNode ) -{ - Aig_Obj_t * pNodeI, * pNodeT, * pNodeE; - int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; - - assert( !Aig_IsComplement( pNode ) ); - assert( Aig_ObjIsMuxType( pNode ) ); - // get nodes (I = if, T = then, E = else) - pNodeI = Aig_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); - // get the variable numbers - VarF = Fra_ObjSatNum(pNode); - VarI = Fra_ObjSatNum(pNodeI); - VarT = Fra_ObjSatNum(Aig_Regular(pNodeT)); - VarE = Fra_ObjSatNum(Aig_Regular(pNodeE)); - // get the complementation flags - fCompT = Aig_IsComplement(pNodeT); - fCompE = Aig_IsComplement(pNodeE); - - // f = ITE(i, t, e) - - // i' + t' + f - // i' + t + f' - // i + e' + f - // i + e + f' - - // create four clauses - pLits[0] = toLitCond(VarI, 1); - pLits[1] = toLitCond(VarT, 1^fCompT); - pLits[2] = toLitCond(VarF, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarI, 1); - pLits[1] = toLitCond(VarT, 0^fCompT); - pLits[2] = toLitCond(VarF, 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarI, 0); - pLits[1] = toLitCond(VarE, 1^fCompE); - pLits[2] = toLitCond(VarF, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarI, 0); - pLits[1] = toLitCond(VarE, 0^fCompE); - pLits[2] = toLitCond(VarF, 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - - // two additional clauses - // t' & e' -> f' - // t & e -> f - - // t + e + f' - // t' + e' + f - - if ( VarT == VarE ) - { -// assert( fCompT == !fCompE ); - return; - } - - pLits[0] = toLitCond(VarT, 0^fCompT); - pLits[1] = toLitCond(VarE, 0^fCompE); - pLits[2] = toLitCond(VarF, 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarT, 1^fCompT); - pLits[1] = toLitCond(VarE, 1^fCompE); - pLits[2] = toLitCond(VarF, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_AddClausesSuper( Fra_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vSuper ) -{ - Aig_Obj_t * pFanin; - int * pLits, nLits, RetValue, i; - assert( !Aig_IsComplement(pNode) ); - assert( Aig_ObjIsNode( pNode ) ); - // create storage for literals - nLits = Vec_PtrSize(vSuper) + 1; - pLits = ALLOC( int, nLits ); - // suppose AND-gate is A & B = C - // add !A => !C or A + !C - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - pLits[0] = toLitCond(Fra_ObjSatNum(Aig_Regular(pFanin)), Aig_IsComplement(pFanin)); - pLits[1] = toLitCond(Fra_ObjSatNum(pNode), 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - } - // add A & B => C or !A + !B + C - Vec_PtrForEachEntry( vSuper, pFanin, i ) - pLits[i] = toLitCond(Fra_ObjSatNum(Aig_Regular(pFanin)), !Aig_IsComplement(pFanin)); - pLits[nLits-1] = toLitCond(Fra_ObjSatNum(pNode), 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); - assert( RetValue ); - free( pLits ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_CollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) -{ - // if the new node is complemented or a PI, another gate begins - if ( Aig_IsComplement(pObj) || Aig_ObjIsPi(pObj) || (!fFirst && Aig_ObjRefs(pObj) > 1) || - (fUseMuxes && Aig_ObjIsMuxType(pObj)) ) - { - Vec_PtrPushUnique( vSuper, pObj ); - return; - } - // go through the branches - Fra_CollectSuper_rec( Aig_ObjChild0(pObj), vSuper, 0, fUseMuxes ); - Fra_CollectSuper_rec( Aig_ObjChild1(pObj), vSuper, 0, fUseMuxes ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Fra_CollectSuper( Aig_Obj_t * pObj, int fUseMuxes ) -{ - Vec_Ptr_t * vSuper; - assert( !Aig_IsComplement(pObj) ); - assert( !Aig_ObjIsPi(pObj) ); - vSuper = Vec_PtrAlloc( 4 ); - Fra_CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); - return vSuper; -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ObjAddToFrontier( Fra_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vFrontier ) -{ - Fra_Man_t * pTemp = pObj->pData; - assert( !Aig_IsComplement(pObj) ); - if ( Fra_ObjSatNum(pObj) ) - return; - assert( Fra_ObjSatNum(pObj) == 0 ); - assert( Fra_ObjFaninVec(pObj) == NULL ); - if ( Aig_ObjIsConst1(pObj) ) - return; -//printf( "Assigning node %d number %d\n", pObj->Id, p->nSatVars ); - Fra_ObjSetSatNum( pObj, p->nSatVars++ ); - if ( Aig_ObjIsNode(pObj) ) - Vec_PtrPush( vFrontier, pObj ); -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_CnfNodeAddToSolver( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) -{ - Vec_Ptr_t * vFrontier, * vFanins; - Aig_Obj_t * pNode, * pFanin; - int i, k, fUseMuxes = 1; - assert( pOld || pNew ); - // quit if CNF is ready - if ( (!pOld || Fra_ObjFaninVec(pOld)) && (!pNew || Fra_ObjFaninVec(pNew)) ) - return; - // start the frontier - vFrontier = Vec_PtrAlloc( 100 ); - if ( pOld ) Fra_ObjAddToFrontier( p, pOld, vFrontier ); - if ( pNew ) Fra_ObjAddToFrontier( p, pNew, vFrontier ); - // explore nodes in the frontier - Vec_PtrForEachEntry( vFrontier, pNode, i ) - { - // create the supergate - assert( Fra_ObjSatNum(pNode) ); - assert( Fra_ObjFaninVec(pNode) == NULL ); - if ( fUseMuxes && Aig_ObjIsMuxType(pNode) ) - { - vFanins = Vec_PtrAlloc( 4 ); - Vec_PtrPushUnique( vFanins, Aig_ObjFanin0( Aig_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( vFanins, Aig_ObjFanin0( Aig_ObjFanin1(pNode) ) ); - Vec_PtrPushUnique( vFanins, Aig_ObjFanin1( Aig_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( vFanins, Aig_ObjFanin1( Aig_ObjFanin1(pNode) ) ); - Vec_PtrForEachEntry( vFanins, pFanin, k ) - Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); - Fra_AddClausesMux( p, pNode ); - } - else - { - vFanins = Fra_CollectSuper( pNode, fUseMuxes ); - Vec_PtrForEachEntry( vFanins, pFanin, k ) - Fra_ObjAddToFrontier( p, Aig_Regular(pFanin), vFrontier ); - Fra_AddClausesSuper( p, pNode, vFanins ); - } - assert( Vec_PtrSize(vFanins) > 1 ); - Fra_ObjSetFaninVec( pNode, vFanins ); - } - Vec_PtrFree( vFrontier ); -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraCore.c b/src/aig/fra/fraCore.c deleted file mode 100644 index b390edbe..00000000 --- a/src/aig/fra/fraCore.c +++ /dev/null @@ -1,428 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraCore.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/* - Speculating reduction in the sequential case leads to an interesting - situation when a counter-ex may not refine any classes. This happens - for non-constant equivalence classes. In such cases the representative - of the class (proved by simulation to be non-constant) may be reduced - to a constant during the speculative reduction. The fraig-representative - of this representative node is a constant node, even though this is a - non-constant class. Experiments have shown that this situation happens - very often at the beginning of the refinement iteration when there are - many spurious candidate equivalence classes (especially if heavy-duty - simulatation of BMC was node used at the beginning). As a result, the - SAT solver run may return a counter-ex that distinguishes the given - representative node from the constant-1 node but this counter-ex - does not distinguish the nodes in the non-costant class... This is why - there is no check of refinment after a counter-ex in the sequential case. -*/ - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reports the status of the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_FraigMiterStatus( Aig_Man_t * p ) -{ - Aig_Obj_t * pObj, * pObjNew; - int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; - if ( p->pData ) - return 0; - Aig_ManForEachPoSeq( p, pObj, i ) - { - pObjNew = Aig_ObjChild0(pObj); - // check if the output is constant 0 - if ( pObjNew == Aig_ManConst0(p) ) - { - CountConst0++; - continue; - } - // check if the output is constant 1 - if ( pObjNew == Aig_ManConst1(p) ) - { - CountNonConst0++; - continue; - } - // check if the output can be constant 0 - if ( Aig_Regular(pObjNew)->fPhase != (unsigned)Aig_IsComplement(pObjNew) ) - { - CountNonConst0++; - continue; - } - CountUndecided++; - } -/* - if ( p->pParams->fVerbose ) - { - printf( "Miter has %d outputs. ", Aig_ManPoNum(p->pManAig) ); - printf( "Const0 = %d. ", CountConst0 ); - printf( "NonConst0 = %d. ", CountNonConst0 ); - printf( "Undecided = %d. ", CountUndecided ); - printf( "\n" ); - } -*/ - if ( CountNonConst0 ) - return 0; - if ( CountUndecided ) - return -1; - return 1; -} - -/**Function************************************************************* - - Synopsis [Write speculative miter for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fra_FraigNodeSpeculate( Fra_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pObjFraig, Aig_Obj_t * pObjReprFraig ) -{ - static int Counter = 0; - char FileName[20]; - Aig_Man_t * pTemp; - Aig_Obj_t * pNode; - int i; - // create manager with the logic for these two nodes - pTemp = Aig_ManExtractMiter( p->pManFraig, pObjFraig, pObjReprFraig ); - // dump the logic into a file - sprintf( FileName, "aig\\%03d.blif", ++Counter ); - Aig_ManDumpBlif( pTemp, FileName ); - printf( "Speculation cone with %d nodes was written into file \"%s\".\n", Aig_ManNodeNum(pTemp), FileName ); - // clean up - Aig_ManStop( pTemp ); - Aig_ManForEachObj( p->pManFraig, pNode, i ) - pNode->pData = p; -} - -/**Function************************************************************* - - Synopsis [Verifies the generated counter-ex.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_FraigVerifyCounterEx( Fra_Man_t * p, Vec_Int_t * vCex ) -{ - Aig_Obj_t * pObj, ** ppClass; - int i, c; - assert( Aig_ManPiNum(p->pManAig) == Vec_IntSize(vCex) ); - // make sure the input pattern is not used - Aig_ManForEachObj( p->pManAig, pObj, i ) - assert( !pObj->fMarkB ); - // simulate the cex through the AIG - Aig_ManConst1(p->pManAig)->fMarkB = 1; - Aig_ManForEachPi( p->pManAig, pObj, i ) - pObj->fMarkB = Vec_IntEntry(vCex, i); - Aig_ManForEachNode( p->pManAig, pObj, i ) - pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & - (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); - Aig_ManForEachPo( p->pManAig, pObj, i ) - pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); - // check if the classes hold - Vec_PtrForEachEntry( p->pCla->vClasses1, pObj, i ) - { - if ( pObj->fPhase != pObj->fMarkB ) - printf( "The node %d is not constant under cex!\n", pObj->Id ); - } - Vec_PtrForEachEntry( p->pCla->vClasses, ppClass, i ) - { - for ( c = 1; ppClass[c]; c++ ) - if ( (ppClass[0]->fPhase ^ ppClass[c]->fPhase) != (ppClass[0]->fMarkB ^ ppClass[c]->fMarkB) ) - printf( "The nodes %d and %d are not equal under cex!\n", ppClass[0]->Id, ppClass[c]->Id ); -// for ( c = 0; ppClass[c]; c++ ) -// if ( Fra_ObjFraig(ppClass[c],p->pPars->nFramesK) == Aig_ManConst1(p->pManFraig) ) -// printf( "A member of non-constant class has a constant repr!\n" ); - } - // clean the simulation pattern - Aig_ManForEachObj( p->pManAig, pObj, i ) - pObj->fMarkB = 0; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fra_FraigNode( Fra_Man_t * p, Aig_Obj_t * pObj ) -{ - Aig_Obj_t * pObjRepr, * pObjFraig, * pObjFraig2, * pObjReprFraig; - int RetValue; - assert( !Aig_IsComplement(pObj) ); - // get representative of this class - pObjRepr = Fra_ClassObjRepr( pObj ); - if ( pObjRepr == NULL || // this is a unique node - (!p->pPars->fDoSparse && pObjRepr == Aig_ManConst1(p->pManAig)) ) // this is a sparse node - return; - // get the fraiged node - pObjFraig = Fra_ObjFraig( pObj, p->pPars->nFramesK ); - // get the fraiged representative - pObjReprFraig = Fra_ObjFraig( pObjRepr, p->pPars->nFramesK ); - // if the fraiged nodes are the same, return - if ( Aig_Regular(pObjFraig) == Aig_Regular(pObjReprFraig) ) - { - p->nSatCallsSkipped++; - return; - } - assert( p->pPars->nFramesK || Aig_Regular(pObjFraig) != Aig_ManConst1(p->pManFraig) ); - // if they are proved different, the c-ex will be in p->pPatWords - RetValue = Fra_NodesAreEquiv( p, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); - if ( RetValue == 1 ) // proved equivalent - { -// if ( p->pPars->fChoicing ) -// Aig_ObjCreateRepr( p->pManFraig, Aig_Regular(pObjReprFraig), Aig_Regular(pObjFraig) ); - // the nodes proved equal - pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); - Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjFraig2 ); - return; - } - if ( RetValue == -1 ) // failed - { - if ( p->vTimeouts == NULL ) - p->vTimeouts = Vec_PtrAlloc( 100 ); - Vec_PtrPush( p->vTimeouts, pObj ); - if ( !p->pPars->fSpeculate ) - return; - assert( 0 ); - // speculate - p->nSpeculs++; - pObjFraig2 = Aig_NotCond( pObjReprFraig, pObj->fPhase ^ pObjRepr->fPhase ); - Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjFraig2 ); - Fra_FraigNodeSpeculate( p, pObj, Aig_Regular(pObjFraig), Aig_Regular(pObjReprFraig) ); - return; - } - // disprove the nodes - p->pCla->fRefinement = 1; - // if we do not include the node into those disproved, we may end up - // merging this node with another representative, for which proof has timed out - if ( p->vTimeouts ) - Vec_PtrPush( p->vTimeouts, pObj ); - // verify that the counter-example satisfies all the constraints -// if ( p->vCex ) -// Fra_FraigVerifyCounterEx( p, p->vCex ); - // simulate the counter-example and return the Fraig node - Fra_SmlResimulate( p ); - if ( !p->pPars->nFramesK && Fra_ClassObjRepr(pObj) == pObjRepr ) - printf( "Fra_FraigNode(): Error in class refinement!\n" ); - assert( p->pPars->nFramesK || Fra_ClassObjRepr(pObj) != pObjRepr ); -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_FraigSweep( Fra_Man_t * p ) -{ - Bar_Progress_t * pProgress; - Aig_Obj_t * pObj, * pObjNew; - int i, k = 0, Pos = 0; - // fraig latch outputs - Aig_ManForEachLoSeq( p->pManAig, pObj, i ) - { - Fra_FraigNode( p, pObj ); - if ( p->pPars->fUseImps ) - Pos = Fra_ImpCheckForNode( p, p->pCla->vImps, pObj, Pos ); - } - if ( p->pPars->fLatchCorr ) - return; - // fraig internal nodes - pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(p->pManAig) ); - Aig_ManForEachNode( p->pManAig, pObj, i ) - { - Bar_ProgressUpdate( pProgress, i, NULL ); - // derive and remember the new fraig node - pObjNew = Aig_And( p->pManFraig, Fra_ObjChild0Fra(pObj,p->pPars->nFramesK), Fra_ObjChild1Fra(pObj,p->pPars->nFramesK) ); - Fra_ObjSetFraig( pObj, p->pPars->nFramesK, pObjNew ); - Aig_Regular(pObjNew)->pData = p; - // quit if simulation detected a counter-example for a PO - if ( p->pManFraig->pData ) - continue; - // perform fraiging - Fra_FraigNode( p, pObj ); - if ( p->pPars->fUseImps ) - Pos = Fra_ImpCheckForNode( p, p->pCla->vImps, pObj, Pos ); - } - Bar_ProgressStop( pProgress ); - // try to prove the outputs of the miter - p->nNodesMiter = Aig_ManNodeNum(p->pManFraig); -// Fra_MiterStatus( p->pManFraig ); -// if ( p->pPars->fProve && p->pManFraig->pData == NULL ) -// Fra_MiterProve( p ); - // compress implications after processing all of them - if ( p->pPars->fUseImps ) - Fra_ImpCompactArray( p->pCla->vImps ); -} - -/**Function************************************************************* - - Synopsis [Performs fraiging of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_FraigPerform( Aig_Man_t * pManAig, Fra_Par_t * pPars ) -{ - Fra_Man_t * p; - Aig_Man_t * pManAigNew; - int clk; - if ( Aig_ManNodeNum(pManAig) == 0 ) - return Aig_ManDup(pManAig, 1); -clk = clock(); - assert( Aig_ManLatchNum(pManAig) == 0 ); - p = Fra_ManStart( pManAig, pPars ); - p->pManFraig = Fra_ManPrepareComb( p ); - p->pSml = Fra_SmlStart( pManAig, 0, 1, pPars->nSimWords ); - Fra_SmlSimulate( p, 0 ); -// if ( p->pPars->fChoicing ) -// Aig_ManReprStart( p->pManFraig, Aig_ManObjNumMax(p->pManAig) ); - // collect initial states - p->nLitsBeg = Fra_ClassesCountLits( p->pCla ); - p->nNodesBeg = Aig_ManNodeNum(pManAig); - p->nRegsBeg = Aig_ManRegNum(pManAig); - // perform fraig sweep - Fra_FraigSweep( p ); - // call back the procedure to check implications - if ( pManAig->pImpFunc ) - pManAig->pImpFunc( p, pManAig->pImpData ); - // finalize the fraiged manager - Fra_ManFinalizeComb( p ); - if ( p->pPars->fChoicing ) - { -int clk2 = clock(); - Fra_ClassesCopyReprs( p->pCla, p->vTimeouts ); - pManAigNew = Aig_ManDupRepr( p->pManAig, 1 ); - Aig_ManReprStart( pManAigNew, Aig_ManObjNumMax(pManAigNew) ); - Aig_ManTransferRepr( pManAigNew, p->pManAig ); - Aig_ManMarkValidChoices( pManAigNew ); - Aig_ManStop( p->pManFraig ); - p->pManFraig = NULL; -p->timeTrav += clock() - clk2; - } - else - { - Aig_ManCleanup( p->pManFraig ); - pManAigNew = p->pManFraig; - p->pManFraig = NULL; - } -p->timeTotal = clock() - clk; - // collect final stats - p->nLitsEnd = Fra_ClassesCountLits( p->pCla ); - p->nNodesEnd = Aig_ManNodeNum(pManAigNew); - p->nRegsEnd = Aig_ManRegNum(pManAigNew); - Fra_ManStop( p ); - return pManAigNew; -} - -/**Function************************************************************* - - Synopsis [Performs choicing of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax ) -{ - Fra_Par_t Pars, * pPars = &Pars; - Fra_ParamsDefault( pPars ); - pPars->nBTLimitNode = nConfMax; - pPars->fChoicing = 1; - pPars->fDoSparse = 1; - pPars->fSpeculate = 0; - pPars->fProve = 0; - pPars->fVerbose = 0; - return Fra_FraigPerform( pManAig, pPars ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax ) -{ - Aig_Man_t * pFraig; - Fra_Par_t Pars, * pPars = &Pars; - Fra_ParamsDefault( pPars ); - pPars->nBTLimitNode = nConfMax; - pPars->fChoicing = 0; - pPars->fDoSparse = 1; - pPars->fSpeculate = 0; - pPars->fProve = 0; - pPars->fVerbose = 0; - pFraig = Fra_FraigPerform( pManAig, pPars ); - return pFraig; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraImp.c b/src/aig/fra/fraImp.c deleted file mode 100644 index a5fc7d58..00000000 --- a/src/aig/fra/fraImp.c +++ /dev/null @@ -1,721 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraImp.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [Detecting and proving implications.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraImp.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Counts the number of 1s in each siminfo of each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Fra_SmlCountOnesOne( Fra_Sml_t * p, int Node ) -{ - unsigned * pSim; - int k, Counter = 0; - pSim = Fra_ObjSim( p, Node ); - for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - Counter += Aig_WordCountOnes( pSim[k] ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of 1s in each siminfo of each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int * Fra_SmlCountOnes( Fra_Sml_t * p ) -{ - Aig_Obj_t * pObj; - int i, * pnBits; - pnBits = ALLOC( int, Aig_ManObjNumMax(p->pAig) ); - memset( pnBits, 0, sizeof(int) * Aig_ManObjNumMax(p->pAig) ); - Aig_ManForEachObj( p->pAig, pObj, i ) - pnBits[i] = Fra_SmlCountOnesOne( p, i ); - return pnBits; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if implications holds.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Sml_NodeCheckImp( Fra_Sml_t * p, int Left, int Right ) -{ - unsigned * pSimL, * pSimR; - int k; - pSimL = Fra_ObjSim( p, Left ); - pSimR = Fra_ObjSim( p, Right ); - for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - if ( pSimL[k] & ~pSimR[k] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Counts the number of 1s in the complement of the implication.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Sml_NodeNotImpWeight( Fra_Sml_t * p, int Left, int Right ) -{ - unsigned * pSimL, * pSimR; - int k, Counter = 0; - pSimL = Fra_ObjSim( p, Left ); - pSimR = Fra_ObjSim( p, Right ); - for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - Counter += Aig_WordCountOnes( pSimL[k] & ~pSimR[k] ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Computes the complement of the implication.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Sml_NodeSaveNotImpPatterns( Fra_Sml_t * p, int Left, int Right, unsigned * pResult ) -{ - unsigned * pSimL, * pSimR; - int k; - pSimL = Fra_ObjSim( p, Left ); - pSimR = Fra_ObjSim( p, Right ); - for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - pResult[k] |= pSimL[k] & ~pSimR[k]; -} - -/**Function************************************************************* - - Synopsis [Returns the array of nodes sorted by the number of 1s.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Fra_SmlSortUsingOnes( Fra_Sml_t * p, int fLatchCorr ) -{ - Aig_Obj_t * pObj; - Vec_Ptr_t * vNodes; - int i, nNodes, nTotal, nBits, * pnNodes, * pnBits, * pMemory; - assert( p->nWordsTotal > 0 ); - // count 1s in each node's siminfo - pnBits = Fra_SmlCountOnes( p ); - // count number of nodes having that many 1s - nNodes = 0; - nBits = p->nWordsTotal * 32; - pnNodes = ALLOC( int, nBits + 1 ); - memset( pnNodes, 0, sizeof(int) * (nBits + 1) ); - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( i == 0 ) continue; - // skip non-PI and non-internal nodes - if ( fLatchCorr ) - { - if ( !Aig_ObjIsPi(pObj) ) - continue; - } - else - { - if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) - continue; - } - // skip nodes participating in the classes -// if ( Fra_ClassObjRepr(pObj) ) -// continue; - assert( pnBits[i] <= nBits ); // "<" because of normalized info - pnNodes[pnBits[i]]++; - nNodes++; - } - // allocate memory for all the nodes - pMemory = ALLOC( int, nNodes + nBits + 1 ); - // markup the memory for each node - vNodes = Vec_PtrAlloc( nBits + 1 ); - Vec_PtrPush( vNodes, pMemory ); - for ( i = 1; i <= nBits; i++ ) - { - pMemory += pnNodes[i-1] + 1; - Vec_PtrPush( vNodes, pMemory ); - } - // add the nodes - memset( pnNodes, 0, sizeof(int) * (nBits + 1) ); - Aig_ManForEachObj( p->pAig, pObj, i ) - { - if ( i == 0 ) continue; - // skip non-PI and non-internal nodes - if ( fLatchCorr ) - { - if ( !Aig_ObjIsPi(pObj) ) - continue; - } - else - { - if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsPi(pObj) ) - continue; - } - // skip nodes participating in the classes -// if ( Fra_ClassObjRepr(pObj) ) -// continue; - pMemory = Vec_PtrEntry( vNodes, pnBits[i] ); - pMemory[ pnNodes[pnBits[i]]++ ] = i; - } - // add 0s in the end - nTotal = 0; - Vec_PtrForEachEntry( vNodes, pMemory, i ) - { - pMemory[ pnNodes[i]++ ] = 0; - nTotal += pnNodes[i]; - } - assert( nTotal == nNodes + nBits + 1 ); - free( pnNodes ); - free( pnBits ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Returns the array of implications with the highest cost.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Fra_SmlSelectMaxCost( Vec_Int_t * vImps, int * pCosts, int nCostMax, int nImpLimit, int * pCostRange ) -{ - Vec_Int_t * vImpsNew; - int * pCostCount, nImpCount, Imp, i, c; - assert( Vec_IntSize(vImps) >= nImpLimit ); - // count how many implications have each cost - pCostCount = ALLOC( int, nCostMax + 1 ); - memset( pCostCount, 0, sizeof(int) * (nCostMax + 1) ); - for ( i = 0; i < Vec_IntSize(vImps); i++ ) - { - assert( pCosts[i] <= nCostMax ); - pCostCount[ pCosts[i] ]++; - } - assert( pCostCount[0] == 0 ); - // select the bound on the cost (above this bound, implication will be included) - nImpCount = 0; - for ( c = nCostMax; c > 0; c-- ) - { - nImpCount += pCostCount[c]; - if ( nImpCount >= nImpLimit ) - break; - } -// printf( "Cost range >= %d.\n", c ); - // collect implications with the given costs - vImpsNew = Vec_IntAlloc( nImpLimit ); - Vec_IntForEachEntry( vImps, Imp, i ) - { - if ( pCosts[i] < c ) - continue; - Vec_IntPush( vImpsNew, Imp ); - if ( Vec_IntSize( vImpsNew ) == nImpLimit ) - break; - } - free( pCostCount ); - if ( pCostRange ) - *pCostRange = c; - return vImpsNew; -} - -/**Function************************************************************* - - Synopsis [Compares two implications using their largest ID.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sml_CompareMaxId( unsigned short * pImp1, unsigned short * pImp2 ) -{ - int Max1 = AIG_MAX( pImp1[0], pImp1[1] ); - int Max2 = AIG_MAX( pImp2[0], pImp2[1] ); - if ( Max1 < Max2 ) - return -1; - if ( Max1 > Max2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Derives implication candidates.] - - Description [Implication candidates have the property that - (1) they hold using sequential simulation information - (2) they do not hold using combinational simulation information - (3) they have as high expressive power as possible (heuristically) - that is, they are easy to disprove combinationally - meaning they cover relatively larger sequential subspace.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Fra_ImpDerive( Fra_Man_t * p, int nImpMaxLimit, int nImpUseLimit, int fLatchCorr ) -{ - int nSimWords = 64; - Fra_Sml_t * pSeq, * pComb; - Vec_Int_t * vImps, * vTemp; - Vec_Ptr_t * vNodes; - int * pImpCosts, * pNodesI, * pNodesK; - int nImpsTotal = 0, nImpsTried = 0, nImpsNonSeq = 0, nImpsComb = 0, nImpsCollected = 0; - int CostMin = AIG_INFINITY, CostMax = 0; - int i, k, Imp, CostRange, clk = clock(); - assert( Aig_ManObjNumMax(p->pManAig) < (1 << 15) ); - assert( nImpMaxLimit > 0 && nImpUseLimit > 0 && nImpUseLimit <= nImpMaxLimit ); - // normalize both managers - pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords ); - pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nSimWords, 1 ); - // get the nodes sorted by the number of 1s - vNodes = Fra_SmlSortUsingOnes( pSeq, fLatchCorr ); - // count the total number of implications - for ( k = nSimWords * 32; k > 0; k-- ) - for ( i = k - 1; i > 0; i-- ) - for ( pNodesI = Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ ) - for ( pNodesK = Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ ) - nImpsTotal++; - - // compute implications and their costs - pImpCosts = ALLOC( int, nImpMaxLimit ); - vImps = Vec_IntAlloc( nImpMaxLimit ); - for ( k = pSeq->nWordsTotal * 32; k > 0; k-- ) - for ( i = k - 1; i > 0; i-- ) - { - for ( pNodesI = Vec_PtrEntry( vNodes, i ); *pNodesI; pNodesI++ ) - for ( pNodesK = Vec_PtrEntry( vNodes, k ); *pNodesK; pNodesK++ ) - { - nImpsTried++; - if ( !Sml_NodeCheckImp(pSeq, *pNodesI, *pNodesK) ) - { - nImpsNonSeq++; - continue; - } - if ( Sml_NodeCheckImp(pComb, *pNodesI, *pNodesK) ) - { - nImpsComb++; - continue; - } - nImpsCollected++; - Imp = Fra_ImpCreate( *pNodesI, *pNodesK ); - pImpCosts[ Vec_IntSize(vImps) ] = Sml_NodeNotImpWeight(pComb, *pNodesI, *pNodesK); - CostMin = AIG_MIN( CostMin, pImpCosts[ Vec_IntSize(vImps) ] ); - CostMax = AIG_MAX( CostMax, pImpCosts[ Vec_IntSize(vImps) ] ); - Vec_IntPush( vImps, Imp ); - if ( Vec_IntSize(vImps) == nImpMaxLimit ) - goto finish; - } - } -finish: - Fra_SmlStop( pComb ); - Fra_SmlStop( pSeq ); - - // select implications with the highest cost - CostRange = CostMin; - if ( Vec_IntSize(vImps) > nImpUseLimit ) - { - vImps = Fra_SmlSelectMaxCost( vTemp = vImps, pImpCosts, nSimWords * 32, nImpUseLimit, &CostRange ); - Vec_IntFree( vTemp ); - } - - // dealloc - free( pImpCosts ); - free( Vec_PtrEntry(vNodes, 0) ); - Vec_PtrFree( vNodes ); - // reorder implications topologically - qsort( (void *)Vec_IntArray(vImps), Vec_IntSize(vImps), sizeof(int), - (int (*)(const void *, const void *)) Sml_CompareMaxId ); -if ( p->pPars->fVerbose ) -{ -printf( "Implications: All = %d. Try = %d. NonSeq = %d. Comb = %d. Res = %d.\n", - nImpsTotal, nImpsTried, nImpsNonSeq, nImpsComb, nImpsCollected ); -printf( "Implication weight: Min = %d. Pivot = %d. Max = %d. ", - CostMin, CostRange, CostMax ); -PRT( "Time", clock() - clk ); -} - return vImps; -} - - -// the following three procedures are called to -// - add implications to the SAT solver -// - check implications using the SAT solver -// - refine implications using after a cex is generated - -/**Function************************************************************* - - Synopsis [Add implication clauses to the SAT solver.] - - Description [Note that implications should be checked in the first frame!] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ImpAddToSolver( Fra_Man_t * p, Vec_Int_t * vImps, int * pSatVarNums ) -{ - sat_solver * pSat = p->pSat; - Aig_Obj_t * pLeft, * pRight; - Aig_Obj_t * pLeftF, * pRightF; - int pLits[2], Imp, Left, Right, i, f, status; - int fComplL, fComplR; - Vec_IntForEachEntry( vImps, Imp, i ) - { - // get the corresponding nodes - pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) ); - pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) ); - // check if all the nodes are present - for ( f = 0; f < p->pPars->nFramesK; f++ ) - { - // map these info fraig - pLeftF = Fra_ObjFraig( pLeft, f ); - pRightF = Fra_ObjFraig( pRight, f ); - if ( Aig_ObjIsNone(Aig_Regular(pLeftF)) || Aig_ObjIsNone(Aig_Regular(pRightF)) ) - { - Vec_IntWriteEntry( vImps, i, 0 ); - break; - } - } - if ( f < p->pPars->nFramesK ) - continue; - // add constraints in each timeframe - for ( f = 0; f < p->pPars->nFramesK; f++ ) - { - // map these info fraig - pLeftF = Fra_ObjFraig( pLeft, f ); - pRightF = Fra_ObjFraig( pRight, f ); - // get the corresponding SAT numbers - Left = pSatVarNums[ Aig_Regular(pLeftF)->Id ]; - Right = pSatVarNums[ Aig_Regular(pRightF)->Id ]; - assert( Left > 0 && Left < p->nSatVars ); - assert( Right > 0 && Right < p->nSatVars ); - // get the complemented attributes - fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF); - fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF); - // get the constraint - // L => R L' v R (complement = L & R') - pLits[0] = 2 * Left + !fComplL; - pLits[1] = 2 * Right + fComplR; - // add contraint to solver - if ( !sat_solver_addclause( pSat, pLits, pLits + 2 ) ) - { - sat_solver_delete( pSat ); - p->pSat = NULL; - return; - } - } - } - status = sat_solver_simplify(pSat); - if ( status == 0 ) - { - sat_solver_delete( pSat ); - p->pSat = NULL; - } -// printf( "Total imps = %d. ", Vec_IntSize(vImps) ); - Fra_ImpCompactArray( vImps ); -// printf( "Valid imps = %d. \n", Vec_IntSize(vImps) ); -} - -/**Function************************************************************* - - Synopsis [Check implications for the node (if they are present).] - - Description [Returns the new position in the array.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ImpCheckForNode( Fra_Man_t * p, Vec_Int_t * vImps, Aig_Obj_t * pNode, int Pos ) -{ - Aig_Obj_t * pLeft, * pRight; - Aig_Obj_t * pLeftF, * pRightF; - int i, Imp, Left, Right, Max, RetValue; - int fComplL, fComplR; - Vec_IntForEachEntryStart( vImps, Imp, i, Pos ) - { - if ( Imp == 0 ) - continue; - Left = Fra_ImpLeft(Imp); - Right = Fra_ImpRight(Imp); - Max = AIG_MAX( Left, Right ); - assert( Max >= pNode->Id ); - if ( Max > pNode->Id ) - return i; - // get the corresponding nodes - pLeft = Aig_ManObj( p->pManAig, Left ); - pRight = Aig_ManObj( p->pManAig, Right ); - // get the corresponding FRAIG nodes - pLeftF = Fra_ObjFraig( pLeft, p->pPars->nFramesK ); - pRightF = Fra_ObjFraig( pRight, p->pPars->nFramesK ); - // get the complemented attributes - fComplL = pLeft->fPhase ^ Aig_IsComplement(pLeftF); - fComplR = pRight->fPhase ^ Aig_IsComplement(pRightF); - // check equality - if ( Aig_Regular(pLeftF) == Aig_Regular(pRightF) ) - { - if ( fComplL == fComplR ) // x => x - always true - continue; - assert( fComplL != fComplR ); - // consider 4 possibilities: - // NOT(1) => 1 or 0 => 1 - always true - // 1 => NOT(1) or 1 => 0 - never true - // NOT(x) => x or x - not always true - // x => NOT(x) or NOT(x) - not always true - if ( Aig_ObjIsConst1(Aig_Regular(pLeftF)) && fComplL ) // proved implication - continue; - // disproved implication - p->pCla->fRefinement = 1; - Vec_IntWriteEntry( vImps, i, 0 ); - continue; - } - // check the implication - // - if true, a clause is added - // - if false, a cex is simulated - // make sure the implication is refined - RetValue = Fra_NodesAreImp( p, Aig_Regular(pLeftF), Aig_Regular(pRightF), fComplL, fComplR ); - if ( RetValue != 1 ) - { - p->pCla->fRefinement = 1; - if ( RetValue == 0 ) - Fra_SmlResimulate( p ); - if ( Vec_IntEntry(vImps, i) != 0 ) - printf( "Fra_ImpCheckForNode(): Implication is not refined!\n" ); - assert( Vec_IntEntry(vImps, i) == 0 ); - } - } - return i; -} - -/**Function************************************************************* - - Synopsis [Removes those implications that no longer hold.] - - Description [Returns 1 if refinement has happened.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ImpRefineUsingCex( Fra_Man_t * p, Vec_Int_t * vImps ) -{ - Aig_Obj_t * pLeft, * pRight; - int Imp, i, RetValue = 0; - Vec_IntForEachEntry( vImps, Imp, i ) - { - if ( Imp == 0 ) - continue; - // get the corresponding nodes - pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) ); - pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) ); - // check if implication holds using this simulation info - if ( !Sml_NodeCheckImp(p->pSml, pLeft->Id, pRight->Id) ) - { - Vec_IntWriteEntry( vImps, i, 0 ); - RetValue = 1; - } - } - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Removes empty implications.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ImpCompactArray( Vec_Int_t * vImps ) -{ - int i, k, Imp; - k = 0; - Vec_IntForEachEntry( vImps, Imp, i ) - if ( Imp ) - Vec_IntWriteEntry( vImps, k++, Imp ); - Vec_IntShrink( vImps, k ); -} - -/**Function************************************************************* - - Synopsis [Determines the ratio of the state space by computed implications.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -double Fra_ImpComputeStateSpaceRatio( Fra_Man_t * p ) -{ - int nSimWords = 64; - Fra_Sml_t * pComb; - unsigned * pResult; - double Ratio = 0.0; - int Left, Right, Imp, i; - if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 ) - return Ratio; - // simulate the AIG manager with combinational patterns - pComb = Fra_SmlSimulateComb( p->pManAig, nSimWords ); - // go through the implications and collect where they do not hold - pResult = Fra_ObjSim( pComb, 0 ); - assert( pResult[0] == 0 ); - Vec_IntForEachEntry( p->pCla->vImps, Imp, i ) - { - Left = Fra_ImpLeft(Imp); - Right = Fra_ImpRight(Imp); - Sml_NodeSaveNotImpPatterns( pComb, Left, Right, pResult ); - } - // count the number of ones in this area - Ratio = 100.0 * Fra_SmlCountOnesOne( pComb, 0 ) / (32*(pComb->nWordsTotal-pComb->nWordsPref)); - Fra_SmlStop( pComb ); - return Ratio; -} - -/**Function************************************************************* - - Synopsis [Returns the number of failed implications.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_ImpVerifyUsingSimulation( Fra_Man_t * p ) -{ - int nFrames = 2000; - int nSimWords = 8; - Fra_Sml_t * pSeq; - char * pfFails; - int Left, Right, Imp, i, Counter; - if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 ) - return 0; - // simulate the AIG manager with combinational patterns - pSeq = Fra_SmlSimulateSeq( p->pManAig, p->pPars->nFramesP, nFrames, nSimWords ); - // go through the implications and check how many of them do not hold - pfFails = ALLOC( char, Vec_IntSize(p->pCla->vImps) ); - memset( pfFails, 0, sizeof(char) * Vec_IntSize(p->pCla->vImps) ); - Vec_IntForEachEntry( p->pCla->vImps, Imp, i ) - { - Left = Fra_ImpLeft(Imp); - Right = Fra_ImpRight(Imp); - pfFails[i] = !Sml_NodeCheckImp( pSeq, Left, Right ); - } - // count how many has failed - Counter = 0; - for ( i = 0; i < Vec_IntSize(p->pCla->vImps); i++ ) - Counter += pfFails[i]; - free( pfFails ); - Fra_SmlStop( pSeq ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Record proven implications in the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ImpRecordInManager( Fra_Man_t * p, Aig_Man_t * pNew ) -{ - Aig_Obj_t * pLeft, * pRight, * pMiter; - int nPosOld, Imp, i; - if ( p->pCla->vImps == NULL || Vec_IntSize(p->pCla->vImps) == 0 ) - return; - // go through the implication - nPosOld = Aig_ManPoNum(pNew); - Vec_IntForEachEntry( p->pCla->vImps, Imp, i ) - { - pLeft = Aig_ManObj( p->pManAig, Fra_ImpLeft(Imp) ); - pRight = Aig_ManObj( p->pManAig, Fra_ImpRight(Imp) ); - // record the implication: L' + R - pMiter = Aig_Or( pNew, - Aig_NotCond(pLeft->pData, !pLeft->fPhase), - Aig_NotCond(pRight->pData, pRight->fPhase) ); - Aig_ObjCreatePo( pNew, pMiter ); - } - pNew->nAsserts = Aig_ManPoNum(pNew) - nPosOld; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraInd.c b/src/aig/fra/fraInd.c deleted file mode 100644 index f45e8af0..00000000 --- a/src/aig/fra/fraInd.c +++ /dev/null @@ -1,479 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraInd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [Inductive prover.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraInd.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" -#include "cnf.h" -#include "dar.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs AIG rewriting on the constaint manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_FraigInductionRewrite( Fra_Man_t * p ) -{ - Aig_Man_t * pTemp; - Aig_Obj_t * pObj, * pObjPo; - int nTruePis, k, i, clk = clock(); - // perform AIG rewriting on the speculated frames - pTemp = Aig_ManDup( p->pManFraig, 0 ); -// pTemp = Dar_ManRwsat( pTemp, 1, 0 ); - pTemp = Dar_ManRewriteDefault( pTemp ); -// printf( "Before = %6d. After = %6d.\n", Aig_ManNodeNum(p->pManFraig), Aig_ManNodeNum(pTemp) ); -//Aig_ManDumpBlif( p->pManFraig, "1.blif" ); -//Aig_ManDumpBlif( pTemp, "2.blif" ); -// Fra_FramesWriteCone( pTemp ); -// Aig_ManStop( pTemp ); - // transfer PI/register pointers - assert( p->pManFraig->nRegs == pTemp->nRegs ); - assert( p->pManFraig->nAsserts == pTemp->nAsserts ); - nTruePis = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); - memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll ); - Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), p->pPars->nFramesK, Aig_ManConst1(pTemp) ); - Aig_ManForEachPiSeq( p->pManAig, pObj, i ) - Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ManPi(pTemp,nTruePis*p->pPars->nFramesK+i) ); - k = 0; - assert( Aig_ManRegNum(p->pManAig) == Aig_ManPoNum(pTemp) - pTemp->nAsserts ); - Aig_ManForEachLoSeq( p->pManAig, pObj, i ) - { - pObjPo = Aig_ManPo(pTemp, pTemp->nAsserts + k++); - Fra_ObjSetFraig( pObj, p->pPars->nFramesK, Aig_ObjChild0(pObjPo) ); - } - // exchange - Aig_ManStop( p->pManFraig ); - p->pManFraig = pTemp; -p->timeRwr += clock() - clk; -} - -/**Function************************************************************* - - Synopsis [Performs speculative reduction for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Fra_FramesConstrainNode( Aig_Man_t * pManFraig, Aig_Obj_t * pObj, int iFrame ) -{ - Aig_Obj_t * pObjNew, * pObjNew2, * pObjRepr, * pObjReprNew, * pMiter; - // skip nodes without representative - if ( (pObjRepr = Fra_ClassObjRepr(pObj)) == NULL ) - return; - assert( pObjRepr->Id < pObj->Id ); - // get the new node - pObjNew = Fra_ObjFraig( pObj, iFrame ); - // get the new node of the representative - pObjReprNew = Fra_ObjFraig( pObjRepr, iFrame ); - // if this is the same node, no need to add constraints - if ( Aig_Regular(pObjNew) == Aig_Regular(pObjReprNew) ) - return; - // these are different nodes - perform speculative reduction - pObjNew2 = Aig_NotCond( pObjReprNew, pObj->fPhase ^ pObjRepr->fPhase ); - // set the new node - Fra_ObjSetFraig( pObj, iFrame, pObjNew2 ); - // add the constraint - pMiter = Aig_Exor( pManFraig, Aig_Regular(pObjNew), Aig_Regular(pObjReprNew) ); - pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) ); - pMiter = Aig_Not( pMiter ); - Aig_ObjCreatePo( pManFraig, pMiter ); -} - -/**Function************************************************************* - - Synopsis [Prepares the inductive case with speculative reduction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_FramesWithClasses( Fra_Man_t * p ) -{ - Aig_Man_t * pManFraig; - Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; - int i, k, f; - assert( p->pManFraig == NULL ); - assert( Aig_ManRegNum(p->pManAig) > 0 ); - assert( Aig_ManRegNum(p->pManAig) < Aig_ManPiNum(p->pManAig) ); - - // start the fraig package - pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pManAig) * p->nFramesAll ); - pManFraig->pName = Aig_UtilStrsav( p->pManAig->pName ); - pManFraig->nRegs = p->pManAig->nRegs; - // create PI nodes for the frames - for ( f = 0; f < p->nFramesAll; f++ ) - Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), f, Aig_ManConst1(pManFraig) ); - for ( f = 0; f < p->nFramesAll; f++ ) - Aig_ManForEachPiSeq( p->pManAig, pObj, i ) - Fra_ObjSetFraig( pObj, f, Aig_ObjCreatePi(pManFraig) ); - // create latches for the first frame - Aig_ManForEachLoSeq( p->pManAig, pObj, i ) - Fra_ObjSetFraig( pObj, 0, Aig_ObjCreatePi(pManFraig) ); - - // add timeframes -// pManFraig->fAddStrash = 1; - for ( f = 0; f < p->nFramesAll - 1; f++ ) - { - // set the constraints on the latch outputs - Aig_ManForEachLoSeq( p->pManAig, pObj, i ) - Fra_FramesConstrainNode( pManFraig, pObj, f ); - // add internal nodes of this frame - Aig_ManForEachNode( p->pManAig, pObj, i ) - { - pObjNew = Aig_And( pManFraig, Fra_ObjChild0Fra(pObj,f), Fra_ObjChild1Fra(pObj,f) ); - Fra_ObjSetFraig( pObj, f, pObjNew ); - Fra_FramesConstrainNode( pManFraig, pObj, f ); - } - // transfer latch input to the latch outputs - Aig_ManForEachLiLoSeq( p->pManAig, pObjLi, pObjLo, k ) - Fra_ObjSetFraig( pObjLo, f+1, Fra_ObjChild0Fra(pObjLi,f) ); - } -// pManFraig->fAddStrash = 0; - // mark the asserts - pManFraig->nAsserts = Aig_ManPoNum(pManFraig); - // add the POs for the latch outputs of the last frame - Aig_ManForEachLoSeq( p->pManAig, pObj, i ) - Aig_ObjCreatePo( pManFraig, Fra_ObjFraig(pObj,p->nFramesAll-1) ); - - // remove dangling nodes - Aig_ManCleanup( pManFraig ); - // make sure the satisfying assignment is node assigned - assert( pManFraig->pData == NULL ); - return pManFraig; -} - -/**Function************************************************************* - - Synopsis [Prepares the inductive case with speculative reduction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_FramesAddMore( Aig_Man_t * p, int nFrames ) -{ - Aig_Obj_t * pObj, ** pLatches; - int i, k, f, nNodesOld; - // set copy pointer of each object to point to itself - Aig_ManForEachObj( p, pObj, i ) - pObj->pData = pObj; - // iterate and add objects - nNodesOld = Aig_ManObjNumMax(p); - pLatches = ALLOC( Aig_Obj_t *, Aig_ManRegNum(p) ); - for ( f = 0; f < nFrames; f++ ) - { - // clean latch inputs and outputs - Aig_ManForEachLiSeq( p, pObj, i ) - pObj->pData = NULL; - Aig_ManForEachLoSeq( p, pObj, i ) - pObj->pData = NULL; - // save the latch input values - k = 0; - Aig_ManForEachLiSeq( p, pObj, i ) - { - if ( Aig_ObjFanin0(pObj)->pData ) - pLatches[k++] = Aig_ObjChild0Copy(pObj); - else - pLatches[k++] = NULL; - } - // insert them as the latch output values - k = 0; - Aig_ManForEachLoSeq( p, pObj, i ) - pObj->pData = pLatches[k++]; - // create the next time frame of nodes - Aig_ManForEachNode( p, pObj, i ) - { - if ( i > nNodesOld ) - break; - if ( Aig_ObjFanin0(pObj)->pData && Aig_ObjFanin1(pObj)->pData ) - pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); - else - pObj->pData = NULL; - } - } - free( pLatches ); -} - -/**Function************************************************************* - - Synopsis [Performs choicing of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_FraigInduction( Aig_Man_t * pManAig, int nFramesP, int nFramesK, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose, int * pnIter ) -{ - int fUseSimpleCnf = 0; - int fUseOldSimulation = 0; - // other paramaters affecting performance - // - presence of FRAIGing in Abc_NtkDarSeqSweep() - // - using distance-1 patterns in Fra_SmlAssignDist1() - // - the number of simulation patterns - // - the number of BMC frames - - Fra_Man_t * p; - Fra_Par_t Pars, * pPars = &Pars; - Aig_Obj_t * pObj; - Cnf_Dat_t * pCnf; - Aig_Man_t * pManAigNew; - int nNodesBeg, nRegsBeg; - int nIter, i, clk = clock(), clk2; - - if ( Aig_ManNodeNum(pManAig) == 0 ) - { - if ( pnIter ) *pnIter = 0; - return Aig_ManDup(pManAig, 1); - } - assert( Aig_ManLatchNum(pManAig) == 0 ); - assert( Aig_ManRegNum(pManAig) > 0 ); - assert( nFramesK > 0 ); -//Aig_ManShow( pManAig, 0, NULL ); - - nNodesBeg = Aig_ManNodeNum(pManAig); - nRegsBeg = Aig_ManRegNum(pManAig); - - // enhance the AIG by adding timeframes -// Fra_FramesAddMore( pManAig, 3 ); - - // get parameters - Fra_ParamsDefaultSeq( pPars ); - pPars->nFramesP = nFramesP; - pPars->nFramesK = nFramesK; - pPars->nMaxImps = nMaxImps; - pPars->fVerbose = fVerbose; - pPars->fRewrite = fRewrite; - pPars->fLatchCorr = fLatchCorr; - pPars->fUseImps = fUseImps; - pPars->fWriteImps = fWriteImps; - - // start the fraig manager for this run - p = Fra_ManStart( pManAig, pPars ); - // derive and refine e-classes using K initialized frames - if ( fUseOldSimulation ) - { - if ( pPars->nFramesP > 0 ) - { - pPars->nFramesP = 0; - printf( "Fra_FraigInduction(): Prefix cannot be used.\n" ); - } - p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords ); - Fra_SmlSimulate( p, 1 ); - } - else - { - // bug: r iscas/blif/s5378.blif ; st; ssw -v - // bug: r iscas/blif/s1238.blif ; st; ssw -v - // refine the classes with more simulation rounds -if ( fVerbose ) -printf( "Simulating %d AIG nodes for %d cycles ... ", Aig_ManNodeNum(pManAig), pPars->nFramesP + 32 ); - p->pSml = Fra_SmlSimulateSeq( pManAig, pPars->nFramesP, 32, 1 ); //pPars->nFramesK + 1, 1 ); -if ( fVerbose ) -{ -PRT( "Time", clock() - clk ); -} - Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr ); -// Fra_ClassesPostprocess( p->pCla ); - // allocate new simulation manager for simulating counter-examples - Fra_SmlStop( p->pSml ); - p->pSml = Fra_SmlStart( pManAig, 0, pPars->nFramesK + 1, pPars->nSimWords ); - } - - // select the most expressive implications - if ( pPars->fUseImps ) - p->pCla->vImps = Fra_ImpDerive( p, 5000000, pPars->nMaxImps, pPars->fLatchCorr ); - - // perform BMC (for the min number of frames) - Fra_BmcPerform( p, pPars->nFramesP, pPars->nFramesK+1 ); // +1 is needed to prevent non-refinement -//Fra_ClassesPrint( p->pCla, 1 ); -// if ( p->vCex == NULL ) -// p->vCex = Vec_IntAlloc( 1000 ); - - p->nLitsBeg = Fra_ClassesCountLits( p->pCla ); - p->nNodesBeg = nNodesBeg; // Aig_ManNodeNum(pManAig); - p->nRegsBeg = nRegsBeg; // Aig_ManRegNum(pManAig); - - // dump AIG of the timeframes -// pManAigNew = Fra_ClassesDeriveAig( p->pCla, pPars->nFramesK ); -// Aig_ManDumpBlif( pManAigNew, "frame_aig.blif" ); -// Fra_ManPartitionTest2( pManAigNew ); -// Aig_ManStop( pManAigNew ); - - // iterate the inductive case - p->pCla->fRefinement = 1; - for ( nIter = 0; p->pCla->fRefinement; nIter++ ) - { - int nLitsOld = Fra_ClassesCountLits(p->pCla); - int nImpsOld = p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0; - // mark the classes as non-refined - p->pCla->fRefinement = 0; - // derive non-init K-timeframes while implementing e-classes -clk2 = clock(); - p->pManFraig = Fra_FramesWithClasses( p ); -p->timeTrav += clock() - clk2; -//Aig_ManDumpBlif( p->pManFraig, "testaig.blif" ); - - // perform AIG rewriting - if ( p->pPars->fRewrite ) - Fra_FraigInductionRewrite( p ); - - // convert the manager to SAT solver (the last nLatches outputs are inputs) - if ( fUseSimpleCnf || pPars->fUseImps ) - pCnf = Cnf_DeriveSimple( p->pManFraig, Aig_ManRegNum(p->pManFraig) ); - else - pCnf = Cnf_Derive( p->pManFraig, Aig_ManRegNum(p->pManFraig) ); -//Cnf_DataWriteIntoFile( pCnf, "temp.cnf", 1 ); - - p->pSat = Cnf_DataWriteIntoSolver( pCnf ); - p->nSatVars = pCnf->nVars; - assert( p->pSat != NULL ); - if ( p->pSat == NULL ) - printf( "Fra_FraigInduction(): Computed CNF is not valid.\n" ); - if ( pPars->fUseImps ) - { - Fra_ImpAddToSolver( p, p->pCla->vImps, pCnf->pVarNums ); - if ( p->pSat == NULL ) - printf( "Fra_FraigInduction(): Adding implicationsn to CNF led to a conflict.\n" ); - } - - // set the pointers to the manager - Aig_ManForEachObj( p->pManFraig, pObj, i ) - pObj->pData = p; - - // prepare solver for fraiging the last timeframe - Fra_ManClean( p, Aig_ManObjNumMax(p->pManFraig) + Aig_ManNodeNum(p->pManAig) ); - - // transfer PI/LO variable numbers - Aig_ManForEachObj( p->pManFraig, pObj, i ) - { - if ( pCnf->pVarNums[pObj->Id] == -1 ) - continue; - Fra_ObjSetSatNum( pObj, pCnf->pVarNums[pObj->Id] ); - Fra_ObjSetFaninVec( pObj, (void *)1 ); - } - Cnf_DataFree( pCnf ); - - // report the intermediate results - if ( fVerbose ) - { - printf( "%3d : Const = %6d. Class = %6d. L = %6d. LR = %6d. ", - nIter, Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), - Fra_ClassesCountLits(p->pCla), p->pManFraig->nAsserts ); - if ( p->pCla->vImps ) - printf( "I = %6d. ", Vec_IntSize(p->pCla->vImps) ); - printf( "NR = %6d.\n", Aig_ManNodeNum(p->pManFraig) ); - } - - // perform sweeping - p->nSatCallsRecent = 0; - p->nSatCallsSkipped = 0; - Fra_FraigSweep( p ); - -// Sat_SolverPrintStats( stdout, p->pSat ); - - // remove FRAIG and SAT solver - Aig_ManStop( p->pManFraig ); p->pManFraig = NULL; - sat_solver_delete( p->pSat ); p->pSat = NULL; - memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll ); -// printf( "Recent SAT called = %d. Skipped = %d.\n", p->nSatCallsRecent, p->nSatCallsSkipped ); - assert( p->vTimeouts == NULL ); - if ( p->vTimeouts ) - printf( "Fra_FraigInduction(): SAT solver timed out!\n" ); - // check if refinement has happened -// p->pCla->fRefinement = (int)(nLitsOld != Fra_ClassesCountLits(p->pCla)); - if ( p->pCla->fRefinement && - nLitsOld == Fra_ClassesCountLits(p->pCla) && - nImpsOld == (p->pCla->vImps? Vec_IntSize(p->pCla->vImps) : 0) ) - { - printf( "Fra_FraigInduction(): Internal error. The result may not verify.\n" ); - break; - } - } -/* - // verify implications using simulation - if ( p->pCla->vImps && Vec_IntSize(p->pCla->vImps) ) - { - int Temp, clk = clock(); - if ( Temp = Fra_ImpVerifyUsingSimulation( p ) ) - printf( "Implications failing the simulation test = %d (out of %d). ", Temp, Vec_IntSize(p->pCla->vImps) ); - else - printf( "All %d implications have passed the simulation test. ", Vec_IntSize(p->pCla->vImps) ); - PRT( "Time", clock() - clk ); - } -*/ - - // move the classes into representatives and reduce AIG -clk2 = clock(); -// Fra_ClassesPrint( p->pCla, 1 ); - Fra_ClassesSelectRepr( p->pCla ); - Fra_ClassesCopyReprs( p->pCla, p->vTimeouts ); - pManAigNew = Aig_ManDupRepr( pManAig, 0 ); - // add implications to the manager - if ( fWriteImps && p->pCla->vImps && Vec_IntSize(p->pCla->vImps) ) - Fra_ImpRecordInManager( p, pManAigNew ); - // cleanup the new manager - Aig_ManSeqCleanup( pManAigNew ); -// Aig_ManCountMergeRegs( pManAigNew ); -p->timeTrav += clock() - clk2; -p->timeTotal = clock() - clk; - // get the final stats - p->nLitsEnd = Fra_ClassesCountLits( p->pCla ); - p->nNodesEnd = Aig_ManNodeNum(pManAigNew); - p->nRegsEnd = Aig_ManRegNum(pManAigNew); - // free the manager - Fra_ManStop( p ); - // check the output -// if ( Aig_ManPoNum(pManAigNew) - Aig_ManRegNum(pManAigNew) == 1 ) -// if ( Aig_ObjChild0( Aig_ManPo(pManAigNew,0) ) == Aig_ManConst0(pManAigNew) ) -// printf( "Proved output constant 0.\n" ); - if ( pnIter ) *pnIter = nIter; - return pManAigNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraLcr.c b/src/aig/fra/fraLcr.c deleted file mode 100644 index 50fd6687..00000000 --- a/src/aig/fra/fraLcr.c +++ /dev/null @@ -1,655 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraLcorr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [Latch correspondence computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraLcorr.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Fra_Lcr_t_ Fra_Lcr_t; -struct Fra_Lcr_t_ -{ - // original AIG - Aig_Man_t * pAig; - // equivalence class representation - Fra_Cla_t * pCla; - // partitioning information - Vec_Ptr_t * vParts; // output partitions - int * pInToOutPart; // mapping of PI num into PO partition num - int * pInToOutNum; // mapping of PI num into the num of this PO in the partition - // AIGs for the partitions - Vec_Ptr_t * vFraigs; - // other variables - int fRefining; - // parameters - int nFramesP; - int fVerbose; - // statistics - int nIters; - int nLitsBeg; - int nLitsEnd; - int nNodesBeg; - int nNodesEnd; - int nRegsBeg; - int nRegsEnd; - // runtime - int timeSim; - int timePart; - int timeTrav; - int timeFraig; - int timeUpdate; - int timeTotal; -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the retiming manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Lcr_t * Lcr_ManAlloc( Aig_Man_t * pAig ) -{ - Fra_Lcr_t * p; - p = ALLOC( Fra_Lcr_t, 1 ); - memset( p, 0, sizeof(Fra_Lcr_t) ); - p->pAig = pAig; - p->pInToOutPart = ALLOC( int, Aig_ManPiNum(pAig) ); - memset( p->pInToOutPart, 0, sizeof(int) * Aig_ManPiNum(pAig) ); - p->pInToOutNum = ALLOC( int, Aig_ManPiNum(pAig) ); - memset( p->pInToOutNum, 0, sizeof(int) * Aig_ManPiNum(pAig) ); - p->vFraigs = Vec_PtrAlloc( 1000 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Prints stats for the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lcr_ManPrint( Fra_Lcr_t * p ) -{ - printf( "Iterations = %d. LitBeg = %d. LitEnd = %d. (%6.2f %%).\n", - p->nIters, p->nLitsBeg, p->nLitsEnd, 100.0*p->nLitsEnd/p->nLitsBeg ); - printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", - p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg, - p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/p->nRegsBeg ); - PRT( "AIG simulation ", p->timeSim ); - PRT( "AIG partitioning", p->timePart ); - PRT( "AIG rebuiding ", p->timeTrav ); - PRT( "FRAIGing ", p->timeFraig ); - PRT( "AIG updating ", p->timeUpdate ); - PRT( "TOTAL RUNTIME ", p->timeTotal ); -} - -/**Function************************************************************* - - Synopsis [Deallocates the retiming manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lcr_ManFree( Fra_Lcr_t * p ) -{ - Aig_Obj_t * pObj; - int i; - if ( p->fVerbose ) - Lcr_ManPrint( p ); - Aig_ManForEachPi( p->pAig, pObj, i ) - pObj->pNext = NULL; - Vec_PtrFree( p->vFraigs ); - if ( p->pCla ) Fra_ClassesStop( p->pCla ); - if ( p->vParts ) Vec_VecFree( (Vec_Vec_t *)p->vParts ); - free( p->pInToOutPart ); - free( p->pInToOutNum ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Prepare the AIG for class computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Man_t * Fra_LcrAigPrepare( Aig_Man_t * pAig ) -{ - Fra_Man_t * p; - Aig_Obj_t * pObj; - int i; - p = ALLOC( Fra_Man_t, 1 ); - memset( p, 0, sizeof(Fra_Man_t) ); - Aig_ManForEachPi( pAig, pObj, i ) - pObj->pData = p; - return p; -} - -/**Function************************************************************* - - Synopsis [Prepare the AIG for class computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_LcrAigPrepareTwo( Aig_Man_t * pAig, Fra_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachPi( pAig, pObj, i ) - pObj->pData = p; -} - -/**Function************************************************************* - - Synopsis [Compares two nodes for equivalence after partitioned fraiging.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_LcrNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) -{ - Fra_Man_t * pTemp = pObj0->pData; - Fra_Lcr_t * pLcr = (Fra_Lcr_t *)pTemp->pBmc; - Aig_Man_t * pFraig; - Aig_Obj_t * pOut0, * pOut1; - int nPart0, nPart1; - assert( Aig_ObjIsPi(pObj0) ); - assert( Aig_ObjIsPi(pObj1) ); - // find the partition to which these nodes belong - nPart0 = pLcr->pInToOutPart[(int)pObj0->pNext]; - nPart1 = pLcr->pInToOutPart[(int)pObj1->pNext]; - // if this is the result of refinement of the class created const-1 nodes - // the nodes may end up in different partions - we assume them equivalent - if ( nPart0 != nPart1 ) - { - assert( 0 ); - return 1; - } - assert( nPart0 == nPart1 ); - pFraig = Vec_PtrEntry( pLcr->vFraigs, nPart0 ); - // get the fraig outputs - pOut0 = Aig_ManPo( pFraig, pLcr->pInToOutNum[(int)pObj0->pNext] ); - pOut1 = Aig_ManPo( pFraig, pLcr->pInToOutNum[(int)pObj1->pNext] ); - return Aig_ObjFanin0(pOut0) == Aig_ObjFanin0(pOut1); -} - -/**Function************************************************************* - - Synopsis [Compares the node with a constant after partioned fraiging.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_LcrNodeIsConst( Aig_Obj_t * pObj ) -{ - Fra_Man_t * pTemp = pObj->pData; - Fra_Lcr_t * pLcr = (Fra_Lcr_t *)pTemp->pBmc; - Aig_Man_t * pFraig; - Aig_Obj_t * pOut; - int nPart; - assert( Aig_ObjIsPi(pObj) ); - // find the partition to which these nodes belong - nPart = pLcr->pInToOutPart[(int)pObj->pNext]; - pFraig = Vec_PtrEntry( pLcr->vFraigs, nPart ); - // get the fraig outputs - pOut = Aig_ManPo( pFraig, pLcr->pInToOutNum[(int)pObj->pNext] ); - return Aig_ObjFanin0(pOut) == Aig_ManConst1(pFraig); -} - -/**Function************************************************************* - - Synopsis [Give the AIG and classes, reduces AIG for partitioning.] - - Description [Ignores registers that are not in the classes. - Places candidate equivalent classes of registers into single outputs - (for ease of partitioning). The resulting combinational AIG contains - outputs in the same order as equivalence classes of registers, - followed by constant-1 registers. Preserves the set of all inputs. - Complemented attributes of the outputs do not matter because we need - then only for collecting the structural info.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_LcrDeriveAigForPartitioning( Fra_Lcr_t * pLcr ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj, * pObjPo, * pObjNew, ** ppClass, * pMiter; - int i, c, Offset; - // remember the numbers of the inputs of the original AIG - Aig_ManForEachPi( pLcr->pAig, pObj, i ) - { - pObj->pData = pLcr; - pObj->pNext = (Aig_Obj_t *)i; - } - // compute the LO/LI offset - Offset = Aig_ManPoNum(pLcr->pAig) - Aig_ManPiNum(pLcr->pAig); - // create the PIs - Aig_ManCleanData( pLcr->pAig ); - pNew = Aig_ManStartFrom( pLcr->pAig ); - // go over the equivalence classes - Vec_PtrForEachEntry( pLcr->pCla->vClasses, ppClass, i ) - { - pMiter = Aig_ManConst0(pNew); - for ( c = 0; ppClass[c]; c++ ) - { - assert( Aig_ObjIsPi(ppClass[c]) ); - pObjPo = Aig_ManPo( pLcr->pAig, Offset+(int)ppClass[c]->pNext ); - pObjNew = Aig_ManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) ); - pMiter = Aig_Exor( pNew, pMiter, pObjNew ); - } - Aig_ObjCreatePo( pNew, pMiter ); - } - // go over the constant candidates - Vec_PtrForEachEntry( pLcr->pCla->vClasses1, pObj, i ) - { - assert( Aig_ObjIsPi(pObj) ); - pObjPo = Aig_ManPo( pLcr->pAig, Offset+(int)pObj->pNext ); - pMiter = Aig_ManDup_rec( pNew, pLcr->pAig, Aig_ObjFanin0(pObjPo) ); - Aig_ObjCreatePo( pNew, pMiter ); - } - return pNew; -} - -/**Function************************************************************* - - Synopsis [Remaps partitions into the inputs of original AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_LcrRemapPartitions( Vec_Ptr_t * vParts, Fra_Cla_t * pCla, int * pInToOutPart, int * pInToOutNum ) -{ - Vec_Int_t * vOne, * vOneNew; - Aig_Obj_t ** ppClass, * pObjPi; - int Out, Offset, i, k, c; - // compute the LO/LI offset - Offset = Aig_ManPoNum(pCla->pAig) - Aig_ManPiNum(pCla->pAig); - Vec_PtrForEachEntry( vParts, vOne, i ) - { - vOneNew = Vec_IntAlloc( Vec_IntSize(vOne) ); - Vec_IntForEachEntry( vOne, Out, k ) - { - if ( Out < Vec_PtrSize(pCla->vClasses) ) - { - ppClass = Vec_PtrEntry( pCla->vClasses, Out ); - for ( c = 0; ppClass[c]; c++ ) - { - pInToOutPart[(int)ppClass[c]->pNext] = i; - pInToOutNum[(int)ppClass[c]->pNext] = Vec_IntSize(vOneNew); - Vec_IntPush( vOneNew, Offset+(int)ppClass[c]->pNext ); - } - } - else - { - pObjPi = Vec_PtrEntry( pCla->vClasses1, Out - Vec_PtrSize(pCla->vClasses) ); - pInToOutPart[(int)pObjPi->pNext] = i; - pInToOutNum[(int)pObjPi->pNext] = Vec_IntSize(vOneNew); - Vec_IntPush( vOneNew, Offset+(int)pObjPi->pNext ); - } - } - // replace the class - Vec_PtrWriteEntry( vParts, i, vOneNew ); - Vec_IntFree( vOne ); - } -} - -/**Function************************************************************* - - Synopsis [Creates AIG of one partition with speculative reduction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Fra_LcrCreatePart_rec( Fra_Cla_t * pCla, Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) -{ - assert( !Aig_IsComplement(pObj) ); - if ( Aig_ObjIsTravIdCurrent(p, pObj) ) - return pObj->pData; - Aig_ObjSetTravIdCurrent(p, pObj); - if ( Aig_ObjIsPi(pObj) ) - { -// Aig_Obj_t * pRepr = Fra_ClassObjRepr(pObj); - Aig_Obj_t * pRepr = pCla->pMemRepr[pObj->Id]; - if ( pRepr == NULL ) - pObj->pData = Aig_ObjCreatePi( pNew ); - else - { - pObj->pData = Fra_LcrCreatePart_rec( pCla, pNew, p, pRepr ); - pObj->pData = Aig_NotCond( pObj->pData, pRepr->fPhase ^ pObj->fPhase ); - } - return pObj->pData; - } - Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin0(pObj) ); - Fra_LcrCreatePart_rec( pCla, pNew, p, Aig_ObjFanin1(pObj) ); - return pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Creates AIG of one partition with speculative reduction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_LcrCreatePart( Fra_Lcr_t * p, Vec_Int_t * vPart ) -{ - Aig_Man_t * pNew; - Aig_Obj_t * pObj, * pObjNew; - int Out, i; - // create new AIG for this partition - pNew = Aig_ManStartFrom( p->pAig ); - Aig_ManIncrementTravId( p->pAig ); - Aig_ObjSetTravIdCurrent( p->pAig, Aig_ManConst1(p->pAig) ); - Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew); - Vec_IntForEachEntry( vPart, Out, i ) - { - pObj = Aig_ManPo( p->pAig, Out ); - if ( pObj->fMarkA ) - { - pObjNew = Fra_LcrCreatePart_rec( p->pCla, pNew, p->pAig, Aig_ObjFanin0(pObj) ); - pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ); - } - else - pObjNew = Aig_ManConst1( pNew ); - Aig_ObjCreatePo( pNew, pObjNew ); - } - return pNew; -} - -/**Function************************************************************* - - Synopsis [Marks the nodes belonging to the equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClassNodesMark( Fra_Lcr_t * p ) -{ - Aig_Obj_t * pObj, ** ppClass; - int i, c, Offset; - // compute the LO/LI offset - Offset = Aig_ManPoNum(p->pCla->pAig) - Aig_ManPiNum(p->pCla->pAig); - // mark the nodes remaining in the classes - Vec_PtrForEachEntry( p->pCla->vClasses1, pObj, i ) - { - pObj = Aig_ManPo( p->pCla->pAig, Offset+(int)pObj->pNext ); - pObj->fMarkA = 1; - } - Vec_PtrForEachEntry( p->pCla->vClasses, ppClass, i ) - { - for ( c = 0; ppClass[c]; c++ ) - { - pObj = Aig_ManPo( p->pCla->pAig, Offset+(int)ppClass[c]->pNext ); - pObj->fMarkA = 1; - } - } -} - -/**Function************************************************************* - - Synopsis [Unmarks the nodes belonging to the equivalence classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ClassNodesUnmark( Fra_Lcr_t * p ) -{ - Aig_Obj_t * pObj, ** ppClass; - int i, c, Offset; - // compute the LO/LI offset - Offset = Aig_ManPoNum(p->pCla->pAig) - Aig_ManPiNum(p->pCla->pAig); - // mark the nodes remaining in the classes - Vec_PtrForEachEntry( p->pCla->vClasses1, pObj, i ) - { - pObj = Aig_ManPo( p->pCla->pAig, Offset+(int)pObj->pNext ); - pObj->fMarkA = 0; - } - Vec_PtrForEachEntry( p->pCla->vClasses, ppClass, i ) - { - for ( c = 0; ppClass[c]; c++ ) - { - pObj = Aig_ManPo( p->pCla->pAig, Offset+(int)ppClass[c]->pNext ); - pObj->fMarkA = 0; - } - } -} - -/**Function************************************************************* - - Synopsis [Performs choicing of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_FraigLatchCorrespondence( Aig_Man_t * pAig, int nFramesP, int nConfMax, int fProve, int fVerbose, int * pnIter ) -{ - int nPartSize = 200; - int fReprSelect = 0; - - Fra_Lcr_t * p; - Fra_Sml_t * pSml; - Fra_Man_t * pTemp; - Aig_Man_t * pAigPart, * pAigNew = NULL; - Vec_Int_t * vPart; -// Aig_Obj_t * pObj = Aig_ManObj(pAig, 2078); - int i, nIter, timeSim, clk = clock(), clk2, clk3; - if ( Aig_ManNodeNum(pAig) == 0 ) - { - if ( pnIter ) *pnIter = 0; - return Aig_ManDup(pAig, 1); - } - assert( Aig_ManLatchNum(pAig) == 0 ); - assert( Aig_ManRegNum(pAig) > 0 ); - - // simulate the AIG -clk2 = clock(); -if ( fVerbose ) -printf( "Simulating AIG with %d nodes for %d cycles ... ", Aig_ManNodeNum(pAig), nFramesP + 32 ); - pSml = Fra_SmlSimulateSeq( pAig, nFramesP, 32, 1 ); -if ( fVerbose ) -{ -PRT( "Time", clock() - clk2 ); -timeSim = clock() - clk2; -} - // check if simulation discovered non-constant-0 POs - if ( fProve && pSml->fNonConstOut ) - { - Fra_SmlStop( pSml ); - return NULL; - } - - // start the manager - p = Lcr_ManAlloc( pAig ); - p->nFramesP = nFramesP; - p->fVerbose = fVerbose; - p->timeSim += timeSim; - - pTemp = Fra_LcrAigPrepare( pAig ); - pTemp->pBmc = (Fra_Bmc_t *)p; - pTemp->pSml = pSml; - - // get preliminary info about equivalence classes - pTemp->pCla = p->pCla = Fra_ClassesStart( p->pAig ); - Fra_ClassesPrepare( p->pCla, 1 ); - p->pCla->pFuncNodeIsConst = Fra_LcrNodeIsConst; - p->pCla->pFuncNodesAreEqual = Fra_LcrNodesAreEqual; - Fra_SmlStop( pTemp->pSml ); - - // partition the AIG for latch correspondence computation -clk2 = clock(); -if ( fVerbose ) -printf( "Partitioning AIG ... " ); - pAigPart = Fra_LcrDeriveAigForPartitioning( p ); - p->vParts = (Vec_Ptr_t *)Aig_ManPartitionSmart( pAigPart, nPartSize, 0, NULL ); - Fra_LcrRemapPartitions( p->vParts, p->pCla, p->pInToOutPart, p->pInToOutNum ); - Aig_ManStop( pAigPart ); -if ( fVerbose ) -{ -PRT( "Time", clock() - clk2 ); -p->timePart += clock() - clk2; -} - - // get the initial stats - p->nLitsBeg = Fra_ClassesCountLits( p->pCla ); - p->nNodesBeg = Aig_ManNodeNum(p->pAig); - p->nRegsBeg = Aig_ManRegNum(p->pAig); - - // perforn interative reduction of the partitions - p->fRefining = 1; - for ( nIter = 0; p->fRefining; nIter++ ) - { - p->fRefining = 0; - clk3 = clock(); - // derive AIGs for each partition - Fra_ClassNodesMark( p ); - Vec_PtrClear( p->vFraigs ); - Vec_PtrForEachEntry( p->vParts, vPart, i ) - { -clk2 = clock(); - pAigPart = Fra_LcrCreatePart( p, vPart ); -p->timeTrav += clock() - clk2; -clk2 = clock(); - pAigNew = Fra_FraigEquivence( pAigPart, nConfMax ); -p->timeFraig += clock() - clk2; - Vec_PtrPush( p->vFraigs, pAigNew ); - Aig_ManStop( pAigPart ); - } - Fra_ClassNodesUnmark( p ); - // report the intermediate results - if ( fVerbose ) - { - printf( "%3d : Const = %6d. Class = %6d. L = %6d. Part = %3d. ", - nIter, Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), - Fra_ClassesCountLits(p->pCla), Vec_PtrSize(p->vParts) ); - PRT( "T", clock() - clk3 ); - } - // refine the classes - Fra_LcrAigPrepareTwo( p->pAig, pTemp ); - if ( Fra_ClassesRefine( p->pCla ) ) - p->fRefining = 1; - if ( Fra_ClassesRefine1( p->pCla, 0, NULL ) ) - p->fRefining = 1; - // clean the fraigs - Vec_PtrForEachEntry( p->vFraigs, pAigPart, i ) - Aig_ManStop( pAigPart ); - - // repartition if needed - if ( 1 ) - { -clk2 = clock(); - Vec_VecFree( (Vec_Vec_t *)p->vParts ); - pAigPart = Fra_LcrDeriveAigForPartitioning( p ); - p->vParts = (Vec_Ptr_t *)Aig_ManPartitionSmart( pAigPart, nPartSize, 0, NULL ); - Fra_LcrRemapPartitions( p->vParts, p->pCla, p->pInToOutPart, p->pInToOutNum ); - Aig_ManStop( pAigPart ); -p->timePart += clock() - clk2; - } - } - free( pTemp ); - p->nIters = nIter; - - // move the classes into representatives and reduce AIG -clk2 = clock(); -// Fra_ClassesPrint( p->pCla, 1 ); - if ( fReprSelect ) - Fra_ClassesSelectRepr( p->pCla ); - Fra_ClassesCopyReprs( p->pCla, NULL ); - pAigNew = Aig_ManDupRepr( p->pAig, 0 ); - Aig_ManSeqCleanup( pAigNew ); -// Aig_ManCountMergeRegs( pAigNew ); -p->timeUpdate += clock() - clk2; -p->timeTotal = clock() - clk; - // get the final stats - p->nLitsEnd = Fra_ClassesCountLits( p->pCla ); - p->nNodesEnd = Aig_ManNodeNum(pAigNew); - p->nRegsEnd = Aig_ManRegNum(pAigNew); - Lcr_ManFree( p ); - if ( pnIter ) *pnIter = nIter; - return pAigNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraMan.c b/src/aig/fra/fraMan.c deleted file mode 100644 index f505b0c2..00000000 --- a/src/aig/fra/fraMan.c +++ /dev/null @@ -1,304 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [Starts the FRAIG manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraMan.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Sets the default solving parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ParamsDefault( Fra_Par_t * pPars ) -{ - memset( pPars, 0, sizeof(Fra_Par_t) ); - pPars->nSimWords = 32; // the number of words in the simulation info - pPars->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached - pPars->fPatScores = 0; // enables simulation pattern scoring - pPars->MaxScore = 25; // max score after which resimulation is used - pPars->fDoSparse = 1; // skips sparse functions -// pPars->dActConeRatio = 0.05; // the ratio of cone to be bumped -// pPars->dActConeBumpMax = 5.0; // the largest bump of activity - pPars->dActConeRatio = 0.3; // the ratio of cone to be bumped - pPars->dActConeBumpMax = 10.0; // the largest bump of activity - pPars->nBTLimitNode = 100; // conflict limit at a node - pPars->nBTLimitMiter = 500000; // conflict limit at an output - pPars->nFramesK = 0; // the number of timeframes to unroll - pPars->fConeBias = 1; - pPars->fRewrite = 0; -} - -/**Function************************************************************* - - Synopsis [Sets the default solving parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ParamsDefaultSeq( Fra_Par_t * pPars ) -{ - memset( pPars, 0, sizeof(Fra_Par_t) ); - pPars->nSimWords = 1; // the number of words in the simulation info - pPars->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached - pPars->fPatScores = 0; // enables simulation pattern scoring - pPars->MaxScore = 25; // max score after which resimulation is used - pPars->fDoSparse = 1; // skips sparse functions - pPars->dActConeRatio = 0.3; // the ratio of cone to be bumped - pPars->dActConeBumpMax = 10.0; // the largest bump of activity - pPars->nBTLimitNode = 10000000; // conflict limit at a node - pPars->nBTLimitMiter = 500000; // conflict limit at an output - pPars->nFramesK = 1; // the number of timeframes to unroll - pPars->fConeBias = 0; - pPars->fRewrite = 0; - pPars->fLatchCorr = 0; -} - -/**Function************************************************************* - - Synopsis [Starts the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Man_t * Fra_ManStart( Aig_Man_t * pManAig, Fra_Par_t * pPars ) -{ - Fra_Man_t * p; - Aig_Obj_t * pObj; - int i; - // allocate the fraiging manager - p = ALLOC( Fra_Man_t, 1 ); - memset( p, 0, sizeof(Fra_Man_t) ); - p->pPars = pPars; - p->pManAig = pManAig; - p->nSizeAlloc = Aig_ManObjNumMax( pManAig ); - p->nFramesAll = pPars->nFramesK + 1; - // allocate storage for sim pattern - p->nPatWords = Aig_BitWordNum( (Aig_ManPiNum(pManAig) - Aig_ManRegNum(pManAig)) * p->nFramesAll + Aig_ManRegNum(pManAig) ); - p->pPatWords = ALLOC( unsigned, p->nPatWords ); - p->vPiVars = Vec_PtrAlloc( 100 ); - // equivalence classes - p->pCla = Fra_ClassesStart( pManAig ); - // allocate other members - p->pMemFraig = ALLOC( Aig_Obj_t *, p->nSizeAlloc * p->nFramesAll ); - memset( p->pMemFraig, 0, sizeof(Aig_Obj_t *) * p->nSizeAlloc * p->nFramesAll ); - // set random number generator - srand( 0xABCABC ); - // set the pointer to the manager - Aig_ManForEachObj( p->pManAig, pObj, i ) - pObj->pData = p; - return p; -} - -/**Function************************************************************* - - Synopsis [Starts the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ManClean( Fra_Man_t * p, int nNodesMax ) -{ - int i; - // remove old arrays - for ( i = 0; i < p->nMemAlloc; i++ ) - if ( p->pMemFanins[i] && p->pMemFanins[i] != (void *)1 ) - Vec_PtrFree( p->pMemFanins[i] ); - // realloc for the new size - if ( p->nMemAlloc < nNodesMax ) - { - int nMemAllocNew = nNodesMax + 5000; - p->pMemFanins = REALLOC( Vec_Ptr_t *, p->pMemFanins, nMemAllocNew ); - p->pMemSatNums = REALLOC( int, p->pMemSatNums, nMemAllocNew ); - p->nMemAlloc = nMemAllocNew; - } - // prepare for the new run - memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc ); - memset( p->pMemSatNums, 0, sizeof(int) * p->nMemAlloc ); -} - -/**Function************************************************************* - - Synopsis [Prepares the new manager to begin fraiging.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Fra_ManPrepareComb( Fra_Man_t * p ) -{ - Aig_Man_t * pManFraig; - Aig_Obj_t * pObj; - int i; - assert( p->pManFraig == NULL ); - // start the fraig package - pManFraig = Aig_ManStart( Aig_ManObjNumMax(p->pManAig) ); - pManFraig->pName = Aig_UtilStrsav( p->pManAig->pName ); - pManFraig->nRegs = p->pManAig->nRegs; - pManFraig->nAsserts = p->pManAig->nAsserts; - // set the pointers to the available fraig nodes - Fra_ObjSetFraig( Aig_ManConst1(p->pManAig), 0, Aig_ManConst1(pManFraig) ); - Aig_ManForEachPi( p->pManAig, pObj, i ) - Fra_ObjSetFraig( pObj, 0, Aig_ObjCreatePi(pManFraig) ); - // set the pointers to the manager - Aig_ManForEachObj( pManFraig, pObj, i ) - pObj->pData = p; - // allocate memory for mapping FRAIG nodes into SAT numbers and fanins - p->nMemAlloc = p->nSizeAlloc; - p->pMemFanins = ALLOC( Vec_Ptr_t *, p->nMemAlloc ); - memset( p->pMemFanins, 0, sizeof(Vec_Ptr_t *) * p->nMemAlloc ); - p->pMemSatNums = ALLOC( int, p->nMemAlloc ); - memset( p->pMemSatNums, 0, sizeof(int) * p->nMemAlloc ); - // make sure the satisfying assignment is node assigned - assert( pManFraig->pData == NULL ); - return pManFraig; -} - -/**Function************************************************************* - - Synopsis [Finalizes the combinational miter after fraiging.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ManFinalizeComb( Fra_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - // add the POs - Aig_ManForEachPo( p->pManAig, pObj, i ) - Aig_ObjCreatePo( p->pManFraig, Fra_ObjChild0Fra(pObj,0) ); - // postprocess - Aig_ManCleanMarkB( p->pManFraig ); -} - - -/**Function************************************************************* - - Synopsis [Stops the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ManStop( Fra_Man_t * p ) -{ - if ( p->pPars->fVerbose ) - Fra_ManPrint( p ); - // save mapping from original nodes into FRAIG nodes - if ( p->pManAig ) - { - if ( p->pManAig->pObjCopies ) - free( p->pManAig->pObjCopies ); - p->pManAig->pObjCopies = p->pMemFraig; - p->pMemFraig = NULL; - } - Fra_ManClean( p, 0 ); - if ( p->vTimeouts ) Vec_PtrFree( p->vTimeouts ); - if ( p->vPiVars ) Vec_PtrFree( p->vPiVars ); - if ( p->pSat ) sat_solver_delete( p->pSat ); - if ( p->pCla ) Fra_ClassesStop( p->pCla ); - if ( p->pSml ) Fra_SmlStop( p->pSml ); - if ( p->vCex ) Vec_IntFree( p->vCex ); - FREE( p->pMemFraig ); - FREE( p->pMemFanins ); - FREE( p->pMemSatNums ); - FREE( p->pPatWords ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Prints stats for the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ManPrint( Fra_Man_t * p ) -{ - double nMemory = 1.0*Aig_ManObjNumMax(p->pManAig)*(p->pSml->nWordsTotal*sizeof(unsigned)+6*sizeof(void*))/(1<<20); - printf( "SimWord = %d. Round = %d. Mem = %0.2f Mb. LitBeg = %d. LitEnd = %d. (%6.2f %%).\n", - p->pPars->nSimWords, p->pSml->nSimRounds, nMemory, p->nLitsBeg, p->nLitsEnd, 100.0*p->nLitsEnd/(p->nLitsBeg?p->nLitsBeg:1) ); - printf( "Proof = %d. Cex = %d. Fail = %d. FailReal = %d. C-lim = %d. ImpRatio = %6.2f %%\n", - p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->pPars->nBTLimitNode, Fra_ImpComputeStateSpaceRatio(p) ); - printf( "NBeg = %d. NEnd = %d. (Gain = %6.2f %%). RBeg = %d. REnd = %d. (Gain = %6.2f %%).\n", - p->nNodesBeg, p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/(p->nNodesBeg?p->nNodesBeg:1), - p->nRegsBeg, p->nRegsEnd, 100.0*(p->nRegsBeg-p->nRegsEnd)/(p->nRegsBeg?p->nRegsBeg:1) ); - if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat ); - PRT( "AIG simulation ", p->pSml->timeSim ); - PRT( "AIG traversal ", p->timeTrav ); - if ( p->timeRwr ) - { - PRT( "AIG rewriting ", p->timeRwr ); - } - PRT( "SAT solving ", p->timeSat ); - PRT( " Unsat ", p->timeSatUnsat ); - PRT( " Sat ", p->timeSatSat ); - PRT( " Fail ", p->timeSatFail ); - PRT( "Class refining ", p->timeRef ); - PRT( "TOTAL RUNTIME ", p->timeTotal ); - if ( p->time1 ) { PRT( "time1 ", p->time1 ); } - if ( p->nSpeculs ) - printf( "Speculations = %d.\n", p->nSpeculs ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraPart.c b/src/aig/fra/fraPart.c deleted file mode 100644 index 691b2b3d..00000000 --- a/src/aig/fra/fraPart.c +++ /dev/null @@ -1,263 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraPart.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [Partitioning for induction.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraPart.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ManPartitionTest( Aig_Man_t * p, int nComLim ) -{ - Bar_Progress_t * pProgress; - Vec_Vec_t * vSupps, * vSuppsIn; - Vec_Ptr_t * vSuppsNew; - Vec_Int_t * vSupNew, * vSup, * vSup2, * vTemp;//, * vSupIn; - Vec_Int_t * vOverNew, * vQuantNew; - Aig_Obj_t * pObj; - int i, k, nCommon, CountOver, CountQuant; - int nTotalSupp, nTotalSupp2, Entry, Largest;//, iVar; - double Ratio, R; - int clk; - - nTotalSupp = 0; - nTotalSupp2 = 0; - Ratio = 0.0; - - // compute supports -clk = clock(); - vSupps = (Vec_Vec_t *)Aig_ManSupports( p ); -PRT( "Supports", clock() - clk ); - // remove last entry - Aig_ManForEachPo( p, pObj, i ) - { - vSup = Vec_VecEntry( vSupps, i ); - Vec_IntPop( vSup ); - // remember support -// pObj->pNext = (Aig_Obj_t *)vSup; - } - - // create reverse supports -clk = clock(); - vSuppsIn = Vec_VecStart( Aig_ManPiNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - { - vSup = Vec_VecEntry( vSupps, i ); - Vec_IntForEachEntry( vSup, Entry, k ) - Vec_VecPush( vSuppsIn, Entry, (void *)i ); - } -PRT( "Inverse ", clock() - clk ); - -clk = clock(); - // compute extended supports - Largest = 0; - vSuppsNew = Vec_PtrAlloc( Aig_ManPoNum(p) ); - vOverNew = Vec_IntAlloc( Aig_ManPoNum(p) ); - vQuantNew = Vec_IntAlloc( Aig_ManPoNum(p) ); - pProgress = Bar_ProgressStart( stdout, Aig_ManPoNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - { - Bar_ProgressUpdate( pProgress, i, NULL ); - // get old supports - vSup = Vec_VecEntry( vSupps, i ); - if ( Vec_IntSize(vSup) < 2 ) - continue; - // compute new supports - CountOver = CountQuant = 0; - vSupNew = Vec_IntDup( vSup ); - // go through the nodes where the first var appears - Aig_ManForEachPo( p, pObj, k ) -// iVar = Vec_IntEntry( vSup, 0 ); -// vSupIn = Vec_VecEntry( vSuppsIn, iVar ); -// Vec_IntForEachEntry( vSupIn, Entry, k ) - { -// pObj = Aig_ManObj( p, Entry ); - // get support of this output -// vSup2 = (Vec_Int_t *)pObj->pNext; - vSup2 = Vec_VecEntry( vSupps, k ); - // count the number of common vars - nCommon = Vec_IntTwoCountCommon(vSup, vSup2); - if ( nCommon < 2 ) - continue; - if ( nCommon > nComLim ) - { - vSupNew = Vec_IntTwoMerge( vTemp = vSupNew, vSup2 ); - Vec_IntFree( vTemp ); - CountOver++; - } - else - CountQuant++; - } - // save the results - Vec_PtrPush( vSuppsNew, vSupNew ); - Vec_IntPush( vOverNew, CountOver ); - Vec_IntPush( vQuantNew, CountQuant ); - - if ( Largest < Vec_IntSize(vSupNew) ) - Largest = Vec_IntSize(vSupNew); - - nTotalSupp += Vec_IntSize(vSup); - nTotalSupp2 += Vec_IntSize(vSupNew); - if ( Vec_IntSize(vSup) ) - R = Vec_IntSize(vSupNew) / Vec_IntSize(vSup); - else - R = 0; - Ratio += R; - - if ( R < 5.0 ) - continue; - - printf( "%6d : ", i ); - printf( "S = %5d. ", Vec_IntSize(vSup) ); - printf( "SNew = %5d. ", Vec_IntSize(vSupNew) ); - printf( "R = %7.2f. ", R ); - printf( "Over = %5d. ", CountOver ); - printf( "Quant = %5d. ", CountQuant ); - printf( "\n" ); -/* - Vec_IntForEachEntry( vSupNew, Entry, k ) - printf( "%d ", Entry ); - printf( "\n" ); -*/ - } - Bar_ProgressStop( pProgress ); -PRT( "Scanning", clock() - clk ); - - // print cumulative statistics - printf( "PIs = %6d. POs = %6d. Lim = %3d. AveS = %3d. SN = %3d. R = %4.2f Max = %5d.\n", - Aig_ManPiNum(p), Aig_ManPoNum(p), nComLim, - nTotalSupp/Aig_ManPoNum(p), nTotalSupp2/Aig_ManPoNum(p), - Ratio/Aig_ManPoNum(p), Largest ); - - Vec_VecFree( vSupps ); - Vec_VecFree( vSuppsIn ); - Vec_VecFree( (Vec_Vec_t *)vSuppsNew ); - Vec_IntFree( vOverNew ); - Vec_IntFree( vQuantNew ); -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_ManPartitionTest2( Aig_Man_t * p ) -{ - Vec_Vec_t * vSupps, * vSuppsIn; - Vec_Int_t * vSup, * vSup2, * vSup3; - Aig_Obj_t * pObj; - int Entry, Entry2, Entry3, Counter; - int i, k, m, n, clk; - char * pSupp; - - // compute supports -clk = clock(); - vSupps = (Vec_Vec_t *)Aig_ManSupports( p ); -PRT( "Supports", clock() - clk ); - // remove last entry - Aig_ManForEachPo( p, pObj, i ) - { - vSup = Vec_VecEntry( vSupps, i ); - Vec_IntPop( vSup ); - // remember support -// pObj->pNext = (Aig_Obj_t *)vSup; - } - - // create reverse supports -clk = clock(); - vSuppsIn = Vec_VecStart( Aig_ManPiNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - { - if ( i == p->nAsserts ) - break; - vSup = Vec_VecEntry( vSupps, i ); - Vec_IntForEachEntry( vSup, Entry, k ) - Vec_VecPush( vSuppsIn, Entry, (void *)i ); - } -PRT( "Inverse ", clock() - clk ); - - // create affective supports -clk = clock(); - pSupp = ALLOC( char, Aig_ManPiNum(p) ); - Aig_ManForEachPo( p, pObj, i ) - { - if ( i % 50 != 0 ) - continue; - vSup = Vec_VecEntry( vSupps, i ); - memset( pSupp, 0, sizeof(char) * Aig_ManPiNum(p) ); - // go through each input of this output - Vec_IntForEachEntry( vSup, Entry, k ) - { - pSupp[Entry] = 1; - vSup2 = Vec_VecEntry( vSuppsIn, Entry ); - // go though each assert of this input - Vec_IntForEachEntry( vSup2, Entry2, m ) - { - vSup3 = Vec_VecEntry( vSupps, Entry2 ); - // go through each input of this assert - Vec_IntForEachEntry( vSup3, Entry3, n ) - { - pSupp[Entry3] = 1; - } - } - } - // count the entries - Counter = 0; - for ( m = 0; m < Aig_ManPiNum(p); m++ ) - Counter += pSupp[m]; - printf( "%d(%d) ", Vec_IntSize(vSup), Counter ); - } - printf( "\n" ); -PRT( "Extension ", clock() - clk ); - - free( pSupp ); - Vec_VecFree( vSupps ); - Vec_VecFree( vSuppsIn ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraSat.c b/src/aig/fra/fraSat.c deleted file mode 100644 index 11029b69..00000000 --- a/src/aig/fra/fraSat.c +++ /dev/null @@ -1,452 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraSat.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include "fra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Fra_SetActivityFactors( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Runs equivalence test for the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) -{ - int pLits[4], RetValue, RetValue1, nBTLimit, clk, clk2 = clock(); - int status; - - // make sure the nodes are not complemented - assert( !Aig_IsComplement(pNew) ); - assert( !Aig_IsComplement(pOld) ); - assert( pNew != pOld ); - - // if at least one of the nodes is a failed node, perform adjustments: - // if the backtrack limit is small, simply skip this node - // if the backtrack limit is > 10, take the quare root of the limit - nBTLimit = p->pPars->nBTLimitNode; - if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) ) - { - p->nSatFails++; - // fail immediately -// return -1; - if ( nBTLimit <= 10 ) - return -1; - nBTLimit = (int)pow(nBTLimit, 0.7); - } - - p->nSatCalls++; - p->nSatCallsRecent++; - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - { - p->pSat = sat_solver_new(); - p->nSatVars = 1; - sat_solver_setnvars( p->pSat, 1000 ); - // var 0 is reserved for const1 node - add the clause - pLits[0] = toLit( 0 ); - sat_solver_addclause( p->pSat, pLits, pLits + 1 ); - } - - // if the nodes do not have SAT variables, allocate them - Fra_CnfNodeAddToSolver( p, pOld, pNew ); - - if ( p->pSat->qtail != p->pSat->qhead ) - { - status = sat_solver_simplify(p->pSat); - assert( status != 0 ); - assert( p->pSat->qtail == p->pSat->qhead ); - } - - // prepare variable activity - if ( p->pPars->fConeBias ) - Fra_SetActivityFactors( p, pOld, pNew ); - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 -clk = clock(); - pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 ); - pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); -//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, - (sint64)nBTLimit, (sint64)0, - p->nBTLimitGlobal, p->nInsLimitGlobal ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - pLits[0] = lit_neg( pLits[0] ); - pLits[1] = lit_neg( pLits[1] ); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - // continue solving the other implication - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - Fra_SmlSavePattern( p ); - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatFail += clock() - clk; - // mark the node as the failed node - if ( pOld != p->pManFraig->pConst1 ) - pOld->fMarkB = 1; - pNew->fMarkB = 1; - p->nSatFailsReal++; - return -1; - } - - // if the old node was constant 0, we already know the answer - if ( pOld == p->pManFraig->pConst1 ) - { - p->nSatProof++; - return 1; - } - - // solve under assumptions - // A = 0; B = 1 OR A = 0; B = 0 -clk = clock(); - pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 1 ); - pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase ); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, - (sint64)nBTLimit, (sint64)0, - p->nBTLimitGlobal, p->nInsLimitGlobal ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - pLits[0] = lit_neg( pLits[0] ); - pLits[1] = lit_neg( pLits[1] ); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - Fra_SmlSavePattern( p ); - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatFail += clock() - clk; - // mark the node as the failed node - pOld->fMarkB = 1; - pNew->fMarkB = 1; - p->nSatFailsReal++; - return -1; - } -/* - // check BDD proof - { - int RetVal; - PRT( "Sat", clock() - clk2 ); - clk2 = clock(); - RetVal = Fra_NodesAreEquivBdd( pOld, pNew ); -// printf( "%d ", RetVal ); - assert( RetVal ); - PRT( "Bdd", clock() - clk2 ); - printf( "\n" ); - } -*/ - // return SAT proof - p->nSatProof++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Runs the result of test for pObj => pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_NodesAreImp( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew, int fComplL, int fComplR ) -{ - int pLits[4], RetValue, RetValue1, nBTLimit, clk, clk2 = clock(); - int status; - - // make sure the nodes are not complemented - assert( !Aig_IsComplement(pNew) ); - assert( !Aig_IsComplement(pOld) ); - assert( pNew != pOld ); - - // if at least one of the nodes is a failed node, perform adjustments: - // if the backtrack limit is small, simply skip this node - // if the backtrack limit is > 10, take the quare root of the limit - nBTLimit = p->pPars->nBTLimitNode; -/* - if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) ) - { - p->nSatFails++; - // fail immediately -// return -1; - if ( nBTLimit <= 10 ) - return -1; - nBTLimit = (int)pow(nBTLimit, 0.7); - } -*/ - p->nSatCalls++; - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - { - p->pSat = sat_solver_new(); - p->nSatVars = 1; - sat_solver_setnvars( p->pSat, 1000 ); - // var 0 is reserved for const1 node - add the clause - pLits[0] = toLit( 0 ); - sat_solver_addclause( p->pSat, pLits, pLits + 1 ); - } - - // if the nodes do not have SAT variables, allocate them - Fra_CnfNodeAddToSolver( p, pOld, pNew ); - - if ( p->pSat->qtail != p->pSat->qhead ) - { - status = sat_solver_simplify(p->pSat); - assert( status != 0 ); - assert( p->pSat->qtail == p->pSat->qhead ); - } - - // prepare variable activity - if ( p->pPars->fConeBias ) - Fra_SetActivityFactors( p, pOld, pNew ); - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 -clk = clock(); -// pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 ); -// pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); - pLits[0] = toLitCond( Fra_ObjSatNum(pOld), fComplL ); - pLits[1] = toLitCond( Fra_ObjSatNum(pNew), !fComplR ); -//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, - (sint64)nBTLimit, (sint64)0, - p->nBTLimitGlobal, p->nInsLimitGlobal ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - pLits[0] = lit_neg( pLits[0] ); - pLits[1] = lit_neg( pLits[1] ); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - // continue solving the other implication - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - Fra_SmlSavePattern( p ); - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatFail += clock() - clk; - // mark the node as the failed node - if ( pOld != p->pManFraig->pConst1 ) - pOld->fMarkB = 1; - pNew->fMarkB = 1; - p->nSatFailsReal++; - return -1; - } - // return SAT proof - p->nSatProof++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Runs equivalence test for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew ) -{ - int pLits[2], RetValue1, RetValue, clk; - - // make sure the nodes are not complemented - assert( !Aig_IsComplement(pNew) ); - assert( pNew != p->pManFraig->pConst1 ); - p->nSatCalls++; - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - { - p->pSat = sat_solver_new(); - p->nSatVars = 1; - sat_solver_setnvars( p->pSat, 1000 ); - // var 0 is reserved for const1 node - add the clause - pLits[0] = toLit( 0 ); - sat_solver_addclause( p->pSat, pLits, pLits + 1 ); - } - - // if the nodes do not have SAT variables, allocate them - Fra_CnfNodeAddToSolver( p, NULL, pNew ); - - // prepare variable activity - if ( p->pPars->fConeBias ) - Fra_SetActivityFactors( p, NULL, pNew ); - - // solve under assumptions -clk = clock(); - pLits[0] = toLitCond( Fra_ObjSatNum(pNew), pNew->fPhase ); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, - (sint64)p->pPars->nBTLimitMiter, (sint64)0, - p->nBTLimitGlobal, p->nInsLimitGlobal ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - pLits[0] = lit_neg( pLits[0] ); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); - assert( RetValue ); - // continue solving the other implication - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - if ( p->pPatWords ) - Fra_SmlSavePattern( p ); - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatFail += clock() - clk; - // mark the node as the failed node - pNew->fMarkB = 1; - p->nSatFailsReal++; - return -1; - } - - // return SAT proof - p->nSatProof++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Sets variable activities in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_SetActivityFactors_rec( Fra_Man_t * p, Aig_Obj_t * pObj, int LevelMin, int LevelMax ) -{ - Vec_Ptr_t * vFanins; - Aig_Obj_t * pFanin; - int i, Counter = 0; - assert( !Aig_IsComplement(pObj) ); - assert( Fra_ObjSatNum(pObj) ); - // skip visited variables - if ( Aig_ObjIsTravIdCurrent(p->pManFraig, pObj) ) - return 0; - Aig_ObjSetTravIdCurrent(p->pManFraig, pObj); - // add the PI to the list - if ( pObj->Level <= (unsigned)LevelMin || Aig_ObjIsPi(pObj) ) - return 0; - // set the factor of this variable - // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pPars->dActConeBumpMax / ThisBump - p->pSat->factors[Fra_ObjSatNum(pObj)] = p->pPars->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin); - veci_push(&p->pSat->act_vars, Fra_ObjSatNum(pObj)); - // explore the fanins - vFanins = Fra_ObjFaninVec( pObj ); - Vec_PtrForEachEntry( vFanins, pFanin, i ) - Counter += Fra_SetActivityFactors_rec( p, Aig_Regular(pFanin), LevelMin, LevelMax ); - return 1 + Counter; -} - -/**Function************************************************************* - - Synopsis [Sets variable activities in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_SetActivityFactors( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew ) -{ - int clk, LevelMin, LevelMax; - assert( pOld || pNew ); -clk = clock(); - // reset the active variables - veci_resize(&p->pSat->act_vars, 0); - // prepare for traversal - Aig_ManIncrementTravId( p->pManFraig ); - // determine the min and max level to visit - assert( p->pPars->dActConeRatio > 0 && p->pPars->dActConeRatio < 1 ); - LevelMax = AIG_MAX( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) ); - LevelMin = (int)(LevelMax * (1.0 - p->pPars->dActConeRatio)); - // traverse - if ( pOld && !Aig_ObjIsConst1(pOld) ) - Fra_SetActivityFactors_rec( p, pOld, LevelMin, LevelMax ); - if ( pNew && !Aig_ObjIsConst1(pNew) ) - Fra_SetActivityFactors_rec( p, pNew, LevelMin, LevelMax ); -//Fra_PrintActivity( p ); -p->timeTrav += clock() - clk; - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraSec.c b/src/aig/fra/fraSec.c deleted file mode 100644 index f9bbfe44..00000000 --- a/src/aig/fra/fraSec.c +++ /dev/null @@ -1,279 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraSec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [Performs SEC based on seq sweeping.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraSec.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" -#include "ioa.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_FraigSec2( Aig_Man_t * p, int nFramesFix, int fVerbose, int fVeryVerbose ) -{ - Aig_Man_t * pNew; - int nFrames, RetValue, nIter, clk, clkTotal = clock(); - int fLatchCorr = 0; - if ( nFramesFix ) - { - nFrames = nFramesFix; - // perform seq sweeping for one frame number - pNew = Fra_FraigInduction( p, 0, nFrames, 0, 0, 0, fLatchCorr, 0, fVeryVerbose, &nIter ); - } - else - { - // perform seq sweeping while increasing the number of frames - for ( nFrames = 1; ; nFrames++ ) - { -clk = clock(); - pNew = Fra_FraigInduction( p, 0, nFrames, 0, 0, 0, fLatchCorr, 0, fVeryVerbose, &nIter ); - RetValue = Fra_FraigMiterStatus( pNew ); - if ( fVerbose ) - { - printf( "FRAMES %3d : Iters = %3d. ", nFrames, nIter ); - if ( RetValue == 1 ) - printf( "UNSAT " ); - else - printf( "UNDECIDED " ); -PRT( "Time", clock() - clk ); - } - if ( RetValue != -1 ) - break; - Aig_ManStop( pNew ); - } - } - - // get the miter status - RetValue = Fra_FraigMiterStatus( pNew ); - Aig_ManStop( pNew ); - - // report the miter - if ( RetValue == 1 ) - printf( "Networks are equivalent after seq sweeping with K=%d frames (%d iters). ", nFrames, nIter ); - else if ( RetValue == 0 ) - printf( "Networks are NOT EQUIVALENT. " ); - else - printf( "Networks are UNDECIDED after seq sweeping with K=%d frames (%d iters). ", nFrames, nIter ); -PRT( "Time", clock() - clkTotal ); - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_FraigSec( Aig_Man_t * p, int nFramesMax, int fRetimeFirst, int fVerbose, int fVeryVerbose ) -{ - Fra_Sml_t * pSml; - Aig_Man_t * pNew, * pTemp; - int nFrames, RetValue, nIter, clk, clkTotal = clock(); - int fLatchCorr = 0; - - pNew = Aig_ManDup( p, 1 ); - if ( fVerbose ) - { - printf( "Original miter: Latches = %5d. Nodes = %6d.\n", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); - } -//Aig_ManDumpBlif( pNew, "after.blif" ); - - // perform sequential cleanup -clk = clock(); - if ( pNew->nRegs ) - pNew = Aig_ManReduceLaches( pNew, 0 ); - if ( pNew->nRegs ) - pNew = Aig_ManConstReduce( pNew, 0 ); - if ( fVerbose ) - { - printf( "Sequential cleanup: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -PRT( "Time", clock() - clk ); - } - - // perform forward retiming - if ( fRetimeFirst && pNew->nRegs ) - { -clk = clock(); - pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); - Aig_ManStop( pTemp ); - if ( fVerbose ) - { - printf( "Forward retiming: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -PRT( "Time", clock() - clk ); - } - } - - // run latch correspondence -clk = clock(); - if ( pNew->nRegs ) - { - pNew = Aig_ManDup( pTemp = pNew, 1 ); - Aig_ManStop( pTemp ); - pNew = Fra_FraigLatchCorrespondence( pTemp = pNew, 0, 100000, 1, fVeryVerbose, &nIter ); - Aig_ManStop( pTemp ); - if ( pNew == NULL ) - { - RetValue = 0; - printf( "Networks are NOT EQUIVALENT after simulation. " ); -PRT( "Time", clock() - clkTotal ); - return RetValue; - } - - if ( fVerbose ) - { - printf( "Latch-corr (I=%3d): Latches = %5d. Nodes = %6d. ", - nIter, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -PRT( "Time", clock() - clk ); - } - } - - // perform fraiging -clk = clock(); - pNew = Fra_FraigEquivence( pTemp = pNew, 100 ); - Aig_ManStop( pTemp ); - if ( fVerbose ) - { - printf( "Fraiging: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -PRT( "Time", clock() - clk ); - } - - // perform seq sweeping while increasing the number of frames - RetValue = Fra_FraigMiterStatus( pNew ); - if ( RetValue == -1 ) - for ( nFrames = 1; nFrames <= nFramesMax; nFrames *= 2 ) - { -clk = clock(); - pNew = Fra_FraigInduction( pTemp = pNew, 0, nFrames, 0, 0, 0, fLatchCorr, 0, fVeryVerbose, &nIter ); - Aig_ManStop( pTemp ); - RetValue = Fra_FraigMiterStatus( pNew ); - if ( fVerbose ) - { - printf( "K-step (K=%2d,I=%3d): Latches = %5d. Nodes = %6d. ", - nFrames, nIter, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -PRT( "Time", clock() - clk ); - } - if ( RetValue != -1 ) - break; - // perform rewriting -clk = clock(); - pNew = Aig_ManDup( pTemp = pNew, 1 ); - Aig_ManStop( pTemp ); - pNew = Dar_ManRewriteDefault( pNew ); - if ( fVerbose ) - { - printf( "Rewriting: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -PRT( "Time", clock() - clk ); - } - - // perform retiming -clk = clock(); - pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); - Aig_ManStop( pTemp ); - pNew = Aig_ManDup( pTemp = pNew, 1 ); - Aig_ManStop( pTemp ); - if ( fVerbose ) - { - printf( "Forward retiming: Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -PRT( "Time", clock() - clk ); - } - - if ( pNew->nRegs ) - pNew = Aig_ManConstReduce( pNew, 0 ); - - // perform sequential simulation -clk = clock(); - pSml = Fra_SmlSimulateSeq( pNew, 0, 128 * nFrames, 1 + 16/(1+Aig_ManNodeNum(pNew)/1000) ); - if ( fVerbose ) - { - printf( "Seq simulation : Latches = %5d. Nodes = %6d. ", - Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); -PRT( "Time", clock() - clk ); - } - if ( pSml->fNonConstOut ) - { - Fra_SmlStop( pSml ); - Aig_ManStop( pNew ); - RetValue = 0; - printf( "Networks are NOT EQUIVALENT after simulation. " ); -PRT( "Time", clock() - clkTotal ); - return RetValue; - } - Fra_SmlStop( pSml ); - } - - // get the miter status - RetValue = Fra_FraigMiterStatus( pNew ); - - // report the miter - if ( RetValue == 1 ) - { - printf( "Networks are equivalent. " ); -PRT( "Time", clock() - clkTotal ); - } - else if ( RetValue == 0 ) - { - printf( "Networks are NOT EQUIVALENT. " ); -PRT( "Time", clock() - clkTotal ); - } - else - { - static int Counter = 1; - char pFileName[1000]; - printf( "Networks are UNDECIDED. " ); -PRT( "Time", clock() - clkTotal ); - sprintf( pFileName, "sm%03d.aig", Counter++ ); - Ioa_WriteAiger( pNew, pFileName, 0 ); - printf( "The unsolved reduced miter is written into file \"%s\".\n", pFileName ); - } - Aig_ManStop( pNew ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fraSim.c b/src/aig/fra/fraSim.c deleted file mode 100644 index b77c775a..00000000 --- a/src/aig/fra/fraSim.c +++ /dev/null @@ -1,823 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraSim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fraSim.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes hash value of the node using its simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_SmlNodeHash( Aig_Obj_t * pObj, int nTableSize ) -{ - Fra_Man_t * p = pObj->pData; - static int s_FPrimes[128] = { - 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, - 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, - 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, - 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, - 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, - 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, - 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, - 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, - 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, - 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, - 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, - 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, - 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 - }; - unsigned * pSims; - unsigned uHash; - int i; -// assert( p->pSml->nWordsTotal <= 128 ); - uHash = 0; - pSims = Fra_ObjSim(p->pSml, pObj->Id); - for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ ) - uHash ^= pSims[i] * s_FPrimes[i & 0x7F]; - return uHash % nTableSize; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_SmlNodeIsConst( Aig_Obj_t * pObj ) -{ - Fra_Man_t * p = pObj->pData; - unsigned * pSims; - int i; - pSims = Fra_ObjSim(p->pSml, pObj->Id); - for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ ) - if ( pSims[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation infos are equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_SmlNodesAreEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) -{ - Fra_Man_t * p = pObj0->pData; - unsigned * pSims0, * pSims1; - int i; - pSims0 = Fra_ObjSim(p->pSml, pObj0->Id); - pSims1 = Fra_ObjSim(p->pSml, pObj1->Id); - for ( i = p->pSml->nWordsPref; i < p->pSml->nWordsTotal; i++ ) - if ( pSims0[i] != pSims1[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Counts the number of 1s in the XOR of simulation data.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_SmlNodeNotEquWeight( Fra_Sml_t * p, int Left, int Right ) -{ - unsigned * pSimL, * pSimR; - int k, Counter = 0; - pSimL = Fra_ObjSim( p, Left ); - pSimR = Fra_ObjSim( p, Right ); - for ( k = p->nWordsPref; k < p->nWordsTotal; k++ ) - Counter += Aig_WordCountOnes( pSimL[k] ^ pSimR[k] ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_SmlNodeIsZero( Fra_Sml_t * p, Aig_Obj_t * pObj ) -{ - unsigned * pSims; - int i; - pSims = Fra_ObjSim(p, pObj->Id); - for ( i = p->nWordsPref; i < p->nWordsTotal; i++ ) - if ( pSims[i] ) - return 0; - return 1; -} - - - -/**Function************************************************************* - - Synopsis [Generated const 0 pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlSavePattern0( Fra_Man_t * p, int fInit ) -{ - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); -} - -/**Function************************************************************* - - Synopsis [[Generated const 1 pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlSavePattern1( Fra_Man_t * p, int fInit ) -{ - Aig_Obj_t * pObj; - int i, k, nTruePis; - memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords ); - if ( !fInit ) - return; - // clear the state bits to correspond to all-0 initial state - nTruePis = Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); - k = 0; - Aig_ManForEachLoSeq( p->pManAig, pObj, i ) - Aig_InfoXorBit( p->pPatWords, nTruePis * p->nFramesAll + k++ ); -} - -/**Function************************************************************* - - Synopsis [Copy pattern from the solver into the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlSavePattern( Fra_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); - Aig_ManForEachPi( p->pManFraig, pObj, i ) - if ( p->pSat->model.ptr[Fra_ObjSatNum(pObj)] == l_True ) - Aig_InfoSetBit( p->pPatWords, i ); - - if ( p->vCex ) - { - Vec_IntClear( p->vCex ); - for ( i = 0; i < Aig_ManPiNum(p->pManAig) - Aig_ManRegNum(p->pManAig); i++ ) - Vec_IntPush( p->vCex, Aig_InfoHasBit( p->pPatWords, i ) ); - for ( i = Aig_ManPiNum(p->pManFraig) - Aig_ManRegNum(p->pManFraig); i < Aig_ManPiNum(p->pManFraig); i++ ) - Vec_IntPush( p->vCex, Aig_InfoHasBit( p->pPatWords, i ) ); - } - -/* - printf( "Pattern: " ); - Aig_ManForEachPi( p->pManFraig, pObj, i ) - printf( "%d", Aig_InfoHasBit( p->pPatWords, i ) ); - printf( "\n" ); -*/ -} - - - -/**Function************************************************************* - - Synopsis [Creates the counter-example from the successful pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlCheckOutputSavePattern( Fra_Man_t * p, Aig_Obj_t * pObj ) -{ - unsigned * pSims; - int i, k, BestPat, * pModel; - // find the word of the pattern - pSims = Fra_ObjSim(p->pSml, pObj->Id); - for ( i = 0; i < p->pSml->nWordsTotal; i++ ) - if ( pSims[i] ) - break; - assert( i < p->pSml->nWordsTotal ); - // find the bit of the pattern - for ( k = 0; k < 32; k++ ) - if ( pSims[i] & (1 << k) ) - break; - assert( k < 32 ); - // determine the best pattern - BestPat = i * 32 + k; - // fill in the counter-example data - pModel = ALLOC( int, Aig_ManPiNum(p->pManFraig) ); - Aig_ManForEachPi( p->pManAig, pObj, i ) - { - pModel[i] = Aig_InfoHasBit(Fra_ObjSim(p->pSml, pObj->Id), BestPat); -// printf( "%d", pModel[i] ); - } -// printf( "\n" ); - // set the model - assert( p->pManFraig->pData == NULL ); - p->pManFraig->pData = pModel; - return; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the one of the output is already non-constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_SmlCheckOutput( Fra_Man_t * p ) -{ - Aig_Obj_t * pObj; - int i; - // make sure the reference simulation pattern does not detect the bug - pObj = Aig_ManPo( p->pManAig, 0 ); - assert( Aig_ObjFanin0(pObj)->fPhase == (unsigned)Aig_ObjFaninC0(pObj) ); - Aig_ManForEachPo( p->pManAig, pObj, i ) - { - if ( !Fra_SmlNodeIsConst( Aig_ObjFanin0(pObj) ) ) - { - // create the counter-example from this pattern - Fra_SmlCheckOutputSavePattern( p, Aig_ObjFanin0(pObj) ); - return 1; - } - } - return 0; -} - - - -/**Function************************************************************* - - Synopsis [Assigns random patterns to the PI node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlAssignRandom( Fra_Sml_t * p, Aig_Obj_t * pObj ) -{ - unsigned * pSims; - int i; - assert( Aig_ObjIsPi(pObj) ); - pSims = Fra_ObjSim( p, pObj->Id ); - for ( i = 0; i < p->nWordsTotal; i++ ) - pSims[i] = Fra_ObjRandomSim(); -} - -/**Function************************************************************* - - Synopsis [Assigns constant patterns to the PI node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlAssignConst( Fra_Sml_t * p, Aig_Obj_t * pObj, int fConst1, int iFrame ) -{ - unsigned * pSims; - int i; - assert( Aig_ObjIsPi(pObj) ); - pSims = Fra_ObjSim( p, pObj->Id ) + p->nWordsFrame * iFrame; - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = fConst1? ~(unsigned)0 : 0; -} - -/**Function************************************************************* - - Synopsis [Assings random simulation info for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlInitialize( Fra_Sml_t * p, int fInit ) -{ - Aig_Obj_t * pObj; - int i; - if ( fInit ) - { - assert( Aig_ManRegNum(p->pAig) > 0 ); - assert( Aig_ManRegNum(p->pAig) < Aig_ManPiNum(p->pAig) ); - // assign random info for primary inputs - Aig_ManForEachPiSeq( p->pAig, pObj, i ) - Fra_SmlAssignRandom( p, pObj ); - // assign the initial state for the latches - Aig_ManForEachLoSeq( p->pAig, pObj, i ) - Fra_SmlAssignConst( p, pObj, 0, 0 ); - } - else - { - Aig_ManForEachPi( p->pAig, pObj, i ) - Fra_SmlAssignRandom( p, pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Assings distance-1 simulation info for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlAssignDist1( Fra_Sml_t * p, unsigned * pPat ) -{ - Aig_Obj_t * pObj; - int f, i, k, Limit, nTruePis; - assert( p->nFrames > 0 ); - if ( p->nFrames == 1 ) - { - // copy the PI info - Aig_ManForEachPi( p->pAig, pObj, i ) - Fra_SmlAssignConst( p, pObj, Aig_InfoHasBit(pPat, i), 0 ); - // flip one bit - Limit = AIG_MIN( Aig_ManPiNum(p->pAig), p->nWordsTotal * 32 - 1 ); - for ( i = 0; i < Limit; i++ ) - Aig_InfoXorBit( Fra_ObjSim( p, Aig_ManPi(p->pAig,i)->Id ), i+1 ); - } - else - { - int fUseDist1 = 0; - - // copy the PI info for each frame - nTruePis = Aig_ManPiNum(p->pAig) - Aig_ManRegNum(p->pAig); - for ( f = 0; f < p->nFrames; f++ ) - Aig_ManForEachPiSeq( p->pAig, pObj, i ) - Fra_SmlAssignConst( p, pObj, Aig_InfoHasBit(pPat, nTruePis * f + i), f ); - // copy the latch info - k = 0; - Aig_ManForEachLoSeq( p->pAig, pObj, i ) - Fra_SmlAssignConst( p, pObj, Aig_InfoHasBit(pPat, nTruePis * p->nFrames + k++), 0 ); -// assert( p->pManFraig == NULL || nTruePis * p->nFrames + k == Aig_ManPiNum(p->pManFraig) ); - - // flip one bit of the last frame - if ( fUseDist1 ) //&& p->nFrames == 2 ) - { - Limit = AIG_MIN( nTruePis, p->nWordsFrame * 32 - 1 ); - for ( i = 0; i < Limit; i++ ) - Aig_InfoXorBit( Fra_ObjSim( p, Aig_ManPi(p->pAig, i)->Id ) + p->nWordsFrame*(p->nFrames-1), i+1 ); - } - } -} - - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlNodeSimulate( Fra_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) -{ - unsigned * pSims, * pSims0, * pSims1; - int fCompl, fCompl0, fCompl1, i; - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsNode(pObj) ); - assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); - // get hold of the simulation information - pSims = Fra_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; - pSims0 = Fra_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame; - pSims1 = Fra_ObjSim(p, Aig_ObjFanin1(pObj)->Id) + p->nWordsFrame * iFrame; - // get complemented attributes of the children using their random info - fCompl = pObj->fPhase; - fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj)); - fCompl1 = Aig_ObjPhaseReal(Aig_ObjChild1(pObj)); - // simulate - if ( fCompl0 && fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = (pSims0[i] | pSims1[i]); - else - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = ~(pSims0[i] | pSims1[i]); - } - else if ( fCompl0 && !fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = (pSims0[i] | ~pSims1[i]); - else - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = (~pSims0[i] & pSims1[i]); - } - else if ( !fCompl0 && fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = (~pSims0[i] | pSims1[i]); - else - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = (pSims0[i] & ~pSims1[i]); - } - else // if ( !fCompl0 && !fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = ~(pSims0[i] & pSims1[i]); - else - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = (pSims0[i] & pSims1[i]); - } -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlNodeCopyFanin( Fra_Sml_t * p, Aig_Obj_t * pObj, int iFrame ) -{ - unsigned * pSims, * pSims0; - int fCompl, fCompl0, i; - assert( !Aig_IsComplement(pObj) ); - assert( Aig_ObjIsPo(pObj) ); - assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); - // get hold of the simulation information - pSims = Fra_ObjSim(p, pObj->Id) + p->nWordsFrame * iFrame; - pSims0 = Fra_ObjSim(p, Aig_ObjFanin0(pObj)->Id) + p->nWordsFrame * iFrame; - // get complemented attributes of the children using their random info - fCompl = pObj->fPhase; - fCompl0 = Aig_ObjPhaseReal(Aig_ObjChild0(pObj)); - // copy information as it is - if ( fCompl0 ) - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = ~pSims0[i]; - else - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims[i] = pSims0[i]; -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlNodeTransferNext( Fra_Sml_t * p, Aig_Obj_t * pOut, Aig_Obj_t * pIn, int iFrame ) -{ - unsigned * pSims0, * pSims1; - int i; - assert( !Aig_IsComplement(pOut) ); - assert( !Aig_IsComplement(pIn) ); - assert( Aig_ObjIsPo(pOut) ); - assert( Aig_ObjIsPi(pIn) ); - assert( iFrame == 0 || p->nWordsFrame < p->nWordsTotal ); - // get hold of the simulation information - pSims0 = Fra_ObjSim(p, pOut->Id) + p->nWordsFrame * iFrame; - pSims1 = Fra_ObjSim(p, pIn->Id) + p->nWordsFrame * (iFrame+1); - // copy information as it is - for ( i = 0; i < p->nWordsFrame; i++ ) - pSims1[i] = pSims0[i]; -} - - -/**Function************************************************************* - - Synopsis [Check if any of the POs becomes non-constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fra_SmlCheckNonConstOutputs( Fra_Sml_t * p ) -{ - Aig_Obj_t * pObj; - int i; - Aig_ManForEachPoSeq( p->pAig, pObj, i ) - if ( !Fra_SmlNodeIsZero(p, pObj) ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Simulates AIG manager.] - - Description [Assumes that the PI simulation info is attached.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlSimulateOne( Fra_Sml_t * p ) -{ - Aig_Obj_t * pObj, * pObjLi, * pObjLo; - int f, i, clk; -clk = clock(); - for ( f = 0; f < p->nFrames; f++ ) - { - // simulate the nodes - Aig_ManForEachNode( p->pAig, pObj, i ) - Fra_SmlNodeSimulate( p, pObj, f ); - // copy simulation info into outputs - Aig_ManForEachPoSeq( p->pAig, pObj, i ) - Fra_SmlNodeCopyFanin( p, pObj, f ); - // quit if this is the last timeframe - if ( f == p->nFrames - 1 ) - break; - // copy simulation info into outputs - Aig_ManForEachLiSeq( p->pAig, pObj, i ) - Fra_SmlNodeCopyFanin( p, pObj, f ); - // copy simulation info into the inputs - Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) - Fra_SmlNodeTransferNext( p, pObjLi, pObjLo, f ); - } -p->timeSim += clock() - clk; -p->nSimRounds++; -} - - -/**Function************************************************************* - - Synopsis [Resimulates fraiging manager after finding a counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlResimulate( Fra_Man_t * p ) -{ - int nChanges, clk; - Fra_SmlAssignDist1( p->pSml, p->pPatWords ); - Fra_SmlSimulateOne( p->pSml ); -// if ( p->pPars->fPatScores ) -// Fra_CleanPatScores( p ); - if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) - return; -clk = clock(); - nChanges = Fra_ClassesRefine( p->pCla ); - nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); - if ( p->pCla->vImps ) - nChanges += Fra_ImpRefineUsingCex( p, p->pCla->vImps ); -p->timeRef += clock() - clk; - if ( !p->pPars->nFramesK && nChanges < 1 ) - printf( "Error: A counter-example did not refine classes!\n" ); -// assert( nChanges >= 1 ); -//printf( "Refined classes = %5d. Changes = %4d.\n", Vec_PtrSize(p->vClasses), nChanges ); -} - -/**Function************************************************************* - - Synopsis [Performs simulation of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlSimulate( Fra_Man_t * p, int fInit ) -{ - int fVerbose = 0; - int nChanges, nClasses, clk; - assert( !fInit || Aig_ManRegNum(p->pManAig) ); - // start the classes - Fra_SmlInitialize( p->pSml, fInit ); - Fra_SmlSimulateOne( p->pSml ); - Fra_ClassesPrepare( p->pCla, p->pPars->fLatchCorr ); -// Fra_ClassesPrint( p->pCla, 0 ); -if ( fVerbose ) -printf( "Starting classes = %5d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); - -//return; - - // refine classes by walking 0/1 patterns - Fra_SmlSavePattern0( p, fInit ); - Fra_SmlAssignDist1( p->pSml, p->pPatWords ); - Fra_SmlSimulateOne( p->pSml ); - if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) - return; -clk = clock(); - nChanges = Fra_ClassesRefine( p->pCla ); - nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); -p->timeRef += clock() - clk; -if ( fVerbose ) -printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) ); - Fra_SmlSavePattern1( p, fInit ); - Fra_SmlAssignDist1( p->pSml, p->pPatWords ); - Fra_SmlSimulateOne( p->pSml ); - if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) - return; -clk = clock(); - nChanges = Fra_ClassesRefine( p->pCla ); - nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); -p->timeRef += clock() - clk; - -if ( fVerbose ) -printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) ); - // refine classes by random simulation - do { - Fra_SmlInitialize( p->pSml, fInit ); - Fra_SmlSimulateOne( p->pSml ); - nClasses = Vec_PtrSize(p->pCla->vClasses); - if ( p->pPars->fProve && Fra_SmlCheckOutput(p) ) - return; -clk = clock(); - nChanges = Fra_ClassesRefine( p->pCla ); - nChanges += Fra_ClassesRefine1( p->pCla, 1, NULL ); -p->timeRef += clock() - clk; -if ( fVerbose ) -printf( "Refined classes = %5d. Changes = %4d. Lits = %6d.\n", Vec_PtrSize(p->pCla->vClasses), nChanges, Fra_ClassesCountLits(p->pCla) ); - } while ( (double)nChanges / nClasses > p->pPars->dSimSatur ); - -// if ( p->pPars->fVerbose ) -// printf( "Consts = %6d. Classes = %6d. Literals = %6d.\n", -// Vec_PtrSize(p->pCla->vClasses1), Vec_PtrSize(p->pCla->vClasses), Fra_ClassesCountLits(p->pCla) ); -// Fra_ClassesPrint( p->pCla, 0 ); -} - - -/**Function************************************************************* - - Synopsis [Allocates simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Sml_t * Fra_SmlStart( Aig_Man_t * pAig, int nPref, int nFrames, int nWordsFrame ) -{ - Fra_Sml_t * p; - p = (Fra_Sml_t *)malloc( sizeof(Fra_Sml_t) + sizeof(unsigned) * Aig_ManObjNumMax(pAig) * (nPref + nFrames) * nWordsFrame ); - memset( p, 0, sizeof(Fra_Sml_t) + sizeof(unsigned) * (nPref + nFrames) * nWordsFrame ); - p->pAig = pAig; - p->nPref = nPref; - p->nFrames = nPref + nFrames; - p->nWordsFrame = nWordsFrame; - p->nWordsTotal = (nPref + nFrames) * nWordsFrame; - p->nWordsPref = nPref * nWordsFrame; - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fra_SmlStop( Fra_Sml_t * p ) -{ - free( p ); -} - - -/**Function************************************************************* - - Synopsis [Performs simulation of the uninitialized circuit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Sml_t * Fra_SmlSimulateComb( Aig_Man_t * pAig, int nWords ) -{ - Fra_Sml_t * p; - p = Fra_SmlStart( pAig, 0, 1, nWords ); - Fra_SmlInitialize( p, 0 ); - Fra_SmlSimulateOne( p ); - return p; -} - -/**Function************************************************************* - - Synopsis [Performs simulation of the initialized circuit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fra_Sml_t * Fra_SmlSimulateSeq( Aig_Man_t * pAig, int nPref, int nFrames, int nWords ) -{ - Fra_Sml_t * p; - p = Fra_SmlStart( pAig, nPref, nFrames, nWords ); - Fra_SmlInitialize( p, 1 ); - Fra_SmlSimulateOne( p ); - p->fNonConstOut = Fra_SmlCheckNonConstOutputs( p ); - return p; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/fra_.c b/src/aig/fra/fra_.c deleted file mode 100644 index 2b601587..00000000 --- a/src/aig/fra/fra_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [fra_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [New FRAIG package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 30, 2007.] - - Revision [$Id: fra_.c,v 1.00 2007/06/30 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/fra/module.make b/src/aig/fra/module.make deleted file mode 100644 index e7264fdc..00000000 --- a/src/aig/fra/module.make +++ /dev/null @@ -1,12 +0,0 @@ -SRC += src/aig/fra/fraBmc.c \ - src/aig/fra/fraCec.c \ - src/aig/fra/fraClass.c \ - src/aig/fra/fraCnf.c \ - src/aig/fra/fraCore.c \ - src/aig/fra/fraImp.c \ - src/aig/fra/fraInd.c \ - src/aig/fra/fraLcr.c \ - src/aig/fra/fraMan.c \ - src/aig/fra/fraSat.c \ - src/aig/fra/fraSec.c \ - src/aig/fra/fraSim.c diff --git a/src/aig/hop/cudd2.c b/src/aig/hop/cudd2.c deleted file mode 100644 index 28d13ce0..00000000 --- a/src/aig/hop/cudd2.c +++ /dev/null @@ -1,355 +0,0 @@ -/**CFile**************************************************************** - - FileName [cudd2.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Recording AIGs for the BDD operations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 3, 2006.] - - Revision [$Id: cudd2.c,v 1.00 2006/10/03 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "hop.h" -#include "st.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Aig_CuddMan_t_ Aig_CuddMan_t; -struct Aig_CuddMan_t_ -{ - Aig_Man_t * pAig; // internal AIG package - st_table * pTable; // hash table mapping BDD nodes into AIG nodes -}; - -// static Cudd AIG manager used in this experiment -static Aig_CuddMan_t * s_pCuddMan = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start AIG recording.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_Init( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ) -{ - int v; - // start the BDD-to-AIG manager when the first BDD manager is allocated - if ( s_pCuddMan != NULL ) - return; - s_pCuddMan = ALLOC( Aig_CuddMan_t, 1 ); - s_pCuddMan->pAig = Aig_ManStart(); - s_pCuddMan->pTable = st_init_table( st_ptrcmp, st_ptrhash ); - for ( v = 0; v < (int)numVars; v++ ) - Aig_ObjCreatePi( s_pCuddMan->pAig ); -} - -/**Function************************************************************* - - Synopsis [Stops AIG recording.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_Quit( void * pCudd ) -{ - assert( s_pCuddMan != NULL ); - Aig_ManDumpBlif( s_pCuddMan->pAig, "aig_temp.blif" ); - Aig_ManStop( s_pCuddMan->pAig ); - st_free_table( s_pCuddMan->pTable ); - free( s_pCuddMan ); - s_pCuddMan = NULL; -} - -/**Function************************************************************* - - Synopsis [Fetches AIG node corresponding to the BDD node from the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Aig_Obj_t * Cudd2_GetArg( void * pArg ) -{ - Aig_Obj_t * pNode; - assert( s_pCuddMan != NULL ); - if ( !st_lookup( s_pCuddMan->pTable, (char *)Aig_Regular(pArg), (char **)&pNode ) ) - { - printf( "Cudd2_GetArg(): An argument BDD is not in the hash table.\n" ); - return NULL; - } - return Aig_NotCond( pNode, Aig_IsComplement(pArg) ); -} - -/**Function************************************************************* - - Synopsis [Inserts the AIG node corresponding to the BDD node into the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Cudd2_SetArg( Aig_Obj_t * pNode, void * pResult ) -{ - assert( s_pCuddMan != NULL ); - if ( st_is_member( s_pCuddMan->pTable, (char *)Aig_Regular(pResult) ) ) - return; - pNode = Aig_NotCond( pNode, Aig_IsComplement(pResult) ); - st_insert( s_pCuddMan->pTable, (char *)Aig_Regular(pResult), (char *)pNode ); -} - -/**Function************************************************************* - - Synopsis [Registers constant 1 node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddOne( void * pCudd, void * pResult ) -{ - Cudd2_SetArg( Aig_ManConst1(s_pCuddMan->pAig), pResult ); -} - -/**Function************************************************************* - - Synopsis [Adds elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddIthVar( void * pCudd, int iVar, void * pResult ) -{ - int v; - assert( s_pCuddMan != NULL ); - for ( v = Aig_ManPiNum(s_pCuddMan->pAig); v <= iVar; v++ ) - Aig_ObjCreatePi( s_pCuddMan->pAig ); - Cudd2_SetArg( Aig_ManPi(s_pCuddMan->pAig, iVar), pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddAnd( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_And( s_pCuddMan->pAig, pNode0, pNode1 ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddOr( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), Aig_Not(pResult) ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddNand( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddAnd( pCudd, pArg0, pArg1, Aig_Not(pResult) ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddNor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddXor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddXnor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) -{ - Cudd2_bddXor( pCudd, pArg0, pArg1, Aig_Not(pResult) ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddIte( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode2, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode2 = Cudd2_GetArg( pArg2 ); - pNode = Aig_Mux( s_pCuddMan->pAig, pNode0, pNode1, pNode2 ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Performs BDD operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_Compose( s_pCuddMan->pAig, pNode0, pNode1, v ); - Cudd2_SetArg( pNode, pResult ); -} - -/**Function************************************************************* - - Synopsis [Should be called after each containment check.] - - Description [Result should be 1 if Cudd2_bddLeq returned 1.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddLeq( void * pCudd, void * pArg0, void * pArg1, int Result ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_And( s_pCuddMan->pAig, pNode0, Aig_Not(pNode1) ); - Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); -} - -/**Function************************************************************* - - Synopsis [Should be called after each equality check.] - - Description [Result should be 1 if they are equal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cudd2_bddEqual( void * pCudd, void * pArg0, void * pArg1, int Result ) -{ - Aig_Obj_t * pNode0, * pNode1, * pNode; - pNode0 = Cudd2_GetArg( pArg0 ); - pNode1 = Cudd2_GetArg( pArg1 ); - pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); - Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/hop/cudd2.h b/src/aig/hop/cudd2.h deleted file mode 100644 index 69711c11..00000000 --- a/src/aig/hop/cudd2.h +++ /dev/null @@ -1,82 +0,0 @@ -/**CFile**************************************************************** - - FileName [cudd2.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 3, 2006.] - - Revision [$Id: cudd2.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CUDD2_H__ -#define __CUDD2_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -// HA: Added for printing messages -#ifndef MSG -#define MSG(msg) (printf("%s = \n",(msg))); -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern void Cudd2_Init ( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ); -extern void Cudd2_Quit ( void * pCudd ); -extern void Cudd2_bddOne ( void * pCudd, void * pResult ); -extern void Cudd2_bddIthVar ( void * pCudd, int iVar, void * pResult ); -extern void Cudd2_bddAnd ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddOr ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddNand ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddNor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddXor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddXnor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); -extern void Cudd2_bddIte ( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ); -extern void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ); -extern void Cudd2_bddLeq ( void * pCudd, void * pArg0, void * pArg1, int Result ); -extern void Cudd2_bddEqual ( void * pCudd, void * pArg0, void * pArg1, int Result ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/hop/hop.h b/src/aig/hop/hop.h deleted file mode 100644 index e8e916cc..00000000 --- a/src/aig/hop/hop.h +++ /dev/null @@ -1,347 +0,0 @@ -/**CFile**************************************************************** - - FileName [hop.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: hop.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __HOP_H__ -#define __HOP_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Hop_Man_t_ Hop_Man_t; -typedef struct Hop_Obj_t_ Hop_Obj_t; -typedef int Hop_Edge_t; - -// object types -typedef enum { - AIG_NONE, // 0: non-existent object - AIG_CONST1, // 1: constant 1 - AIG_PI, // 2: primary input - AIG_PO, // 3: primary output - AIG_AND, // 4: AND node - AIG_EXOR, // 5: EXOR node - AIG_VOID // 6: unused object -} Hop_Type_t; - -// the AIG node -struct Hop_Obj_t_ // 6 words -{ - void * pData; // misc - Hop_Obj_t * pNext; // strashing table - Hop_Obj_t * pFanin0; // fanin - Hop_Obj_t * pFanin1; // fanin - unsigned int Type : 3; // object type - unsigned int fPhase : 1; // value under 000...0 pattern - unsigned int fMarkA : 1; // multipurpose mask - unsigned int fMarkB : 1; // multipurpose mask - unsigned int nRefs : 26; // reference count (level) - int Id; // unique ID of the node -}; - -// the AIG manager -struct Hop_Man_t_ -{ - // AIG nodes - Vec_Ptr_t * vPis; // the array of PIs - Vec_Ptr_t * vPos; // the array of POs - Vec_Ptr_t * vObjs; // the array of all nodes (optional) - Hop_Obj_t * pConst1; // the constant 1 node - Hop_Obj_t Ghost; // the ghost node - // AIG node counters - int nObjs[AIG_VOID];// the number of objects by type - int nCreated; // the number of created objects - int nDeleted; // the number of deleted objects - // stuctural hash table - Hop_Obj_t ** pTable; // structural hash table - int nTableSize; // structural hash table size - // various data members - void * pData; // the temporary data - int nTravIds; // the current traversal ID - int fRefCount; // enables reference counting - int fCatchExor; // enables EXOR nodes - // memory management - Vec_Ptr_t * vChunks; // allocated memory pieces - Vec_Ptr_t * vPages; // memory pages used by nodes - Hop_Obj_t * pListFree; // the list of free nodes - // timing statistics - int time1; - int time2; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define AIG_MIN(a,b) (((a) < (b))? (a) : (b)) -#define AIG_MAX(a,b) (((a) > (b))? (a) : (b)) - -#ifndef PRT -#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) -#endif - -static inline int Hop_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } -static inline int Hop_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -static inline int Hop_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } -static inline void Hop_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } -static inline void Hop_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } -static inline int Hop_Base2Log( unsigned n ) { int r; assert( n >= 0 ); if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ); return r; } -static inline int Hop_Base10Log( unsigned n ) { int r; assert( n >= 0 ); if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ); return r; } - -static inline Hop_Obj_t * Hop_Regular( Hop_Obj_t * p ) { return (Hop_Obj_t *)((unsigned long)(p) & ~01); } -static inline Hop_Obj_t * Hop_Not( Hop_Obj_t * p ) { return (Hop_Obj_t *)((unsigned long)(p) ^ 01); } -static inline Hop_Obj_t * Hop_NotCond( Hop_Obj_t * p, int c ) { return (Hop_Obj_t *)((unsigned long)(p) ^ (c)); } -static inline int Hop_IsComplement( Hop_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } - -static inline Hop_Obj_t * Hop_ManConst0( Hop_Man_t * p ) { return Hop_Not(p->pConst1); } -static inline Hop_Obj_t * Hop_ManConst1( Hop_Man_t * p ) { return p->pConst1; } -static inline Hop_Obj_t * Hop_ManGhost( Hop_Man_t * p ) { return &p->Ghost; } -static inline Hop_Obj_t * Hop_ManPi( Hop_Man_t * p, int i ) { return (Hop_Obj_t *)Vec_PtrEntry(p->vPis, i); } -static inline Hop_Obj_t * Hop_ManPo( Hop_Man_t * p, int i ) { return (Hop_Obj_t *)Vec_PtrEntry(p->vPos, i); } -static inline Hop_Obj_t * Hop_ManObj( Hop_Man_t * p, int i ) { return p->vObjs ? (Hop_Obj_t *)Vec_PtrEntry(p->vObjs, i) : NULL; } - -static inline Hop_Edge_t Hop_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } -static inline int Hop_EdgeId( Hop_Edge_t Edge ) { return Edge >> 1; } -static inline int Hop_EdgeIsComplement( Hop_Edge_t Edge ) { return Edge & 1; } -static inline Hop_Edge_t Hop_EdgeRegular( Hop_Edge_t Edge ) { return (Edge >> 1) << 1; } -static inline Hop_Edge_t Hop_EdgeNot( Hop_Edge_t Edge ) { return Edge ^ 1; } -static inline Hop_Edge_t Hop_EdgeNotCond( Hop_Edge_t Edge, int fCond ) { return Edge ^ fCond; } - -static inline int Hop_ManPiNum( Hop_Man_t * p ) { return p->nObjs[AIG_PI]; } -static inline int Hop_ManPoNum( Hop_Man_t * p ) { return p->nObjs[AIG_PO]; } -static inline int Hop_ManAndNum( Hop_Man_t * p ) { return p->nObjs[AIG_AND]; } -static inline int Hop_ManExorNum( Hop_Man_t * p ) { return p->nObjs[AIG_EXOR]; } -static inline int Hop_ManNodeNum( Hop_Man_t * p ) { return p->nObjs[AIG_AND]+p->nObjs[AIG_EXOR];} -static inline int Hop_ManGetCost( Hop_Man_t * p ) { return p->nObjs[AIG_AND]+3*p->nObjs[AIG_EXOR]; } -static inline int Hop_ManObjNum( Hop_Man_t * p ) { return p->nCreated - p->nDeleted; } - -static inline Hop_Type_t Hop_ObjType( Hop_Obj_t * pObj ) { return (Hop_Type_t)pObj->Type; } -static inline int Hop_ObjIsNone( Hop_Obj_t * pObj ) { return pObj->Type == AIG_NONE; } -static inline int Hop_ObjIsConst1( Hop_Obj_t * pObj ) { assert(!Hop_IsComplement(pObj)); return pObj->Type == AIG_CONST1; } -static inline int Hop_ObjIsPi( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PI; } -static inline int Hop_ObjIsPo( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PO; } -static inline int Hop_ObjIsAnd( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND; } -static inline int Hop_ObjIsExor( Hop_Obj_t * pObj ) { return pObj->Type == AIG_EXOR; } -static inline int Hop_ObjIsNode( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } -static inline int Hop_ObjIsTerm( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PI || pObj->Type == AIG_PO || pObj->Type == AIG_CONST1; } -static inline int Hop_ObjIsHash( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } - -static inline int Hop_ObjIsMarkA( Hop_Obj_t * pObj ) { return pObj->fMarkA; } -static inline void Hop_ObjSetMarkA( Hop_Obj_t * pObj ) { pObj->fMarkA = 1; } -static inline void Hop_ObjClearMarkA( Hop_Obj_t * pObj ) { pObj->fMarkA = 0; } - -static inline void Hop_ObjSetTravId( Hop_Obj_t * pObj, int TravId ) { pObj->pData = (void *)TravId; } -static inline void Hop_ObjSetTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj ) { pObj->pData = (void *)p->nTravIds; } -static inline void Hop_ObjSetTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj ) { pObj->pData = (void *)(p->nTravIds - 1); } -static inline int Hop_ObjIsTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj ) { return (int )((int)pObj->pData == p->nTravIds); } -static inline int Hop_ObjIsTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj ) { return (int )((int)pObj->pData == p->nTravIds - 1); } - -static inline int Hop_ObjTravId( Hop_Obj_t * pObj ) { return (int)pObj->pData; } -static inline int Hop_ObjPhase( Hop_Obj_t * pObj ) { return pObj->fPhase; } -static inline int Hop_ObjRefs( Hop_Obj_t * pObj ) { return pObj->nRefs; } -static inline void Hop_ObjRef( Hop_Obj_t * pObj ) { pObj->nRefs++; } -static inline void Hop_ObjDeref( Hop_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } -static inline void Hop_ObjClearRef( Hop_Obj_t * pObj ) { pObj->nRefs = 0; } -static inline int Hop_ObjFaninC0( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj->pFanin0); } -static inline int Hop_ObjFaninC1( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj->pFanin1); } -static inline Hop_Obj_t * Hop_ObjFanin0( Hop_Obj_t * pObj ) { return Hop_Regular(pObj->pFanin0); } -static inline Hop_Obj_t * Hop_ObjFanin1( Hop_Obj_t * pObj ) { return Hop_Regular(pObj->pFanin1); } -static inline Hop_Obj_t * Hop_ObjChild0( Hop_Obj_t * pObj ) { return pObj->pFanin0; } -static inline Hop_Obj_t * Hop_ObjChild1( Hop_Obj_t * pObj ) { return pObj->pFanin1; } -static inline Hop_Obj_t * Hop_ObjChild0Copy( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin0(pObj)? Hop_NotCond((Hop_Obj_t *)Hop_ObjFanin0(pObj)->pData, Hop_ObjFaninC0(pObj)) : NULL; } -static inline Hop_Obj_t * Hop_ObjChild1Copy( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin1(pObj)? Hop_NotCond((Hop_Obj_t *)Hop_ObjFanin1(pObj)->pData, Hop_ObjFaninC1(pObj)) : NULL; } -static inline int Hop_ObjLevel( Hop_Obj_t * pObj ) { return pObj->nRefs; } -static inline int Hop_ObjLevelNew( Hop_Obj_t * pObj ) { return 1 + Hop_ObjIsExor(pObj) + AIG_MAX(Hop_ObjFanin0(pObj)->nRefs, Hop_ObjFanin1(pObj)->nRefs); } -static inline int Hop_ObjFaninPhase( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj)? !Hop_Regular(pObj)->fPhase : pObj->fPhase; } -static inline void Hop_ObjClean( Hop_Obj_t * pObj ) { memset( pObj, 0, sizeof(Hop_Obj_t) ); } -static inline int Hop_ObjWhatFanin( Hop_Obj_t * pObj, Hop_Obj_t * pFanin ) -{ - if ( Hop_ObjFanin0(pObj) == pFanin ) return 0; - if ( Hop_ObjFanin1(pObj) == pFanin ) return 1; - assert(0); return -1; -} -static inline int Hop_ObjFanoutC( Hop_Obj_t * pObj, Hop_Obj_t * pFanout ) -{ - if ( Hop_ObjFanin0(pFanout) == pObj ) return Hop_ObjFaninC0(pObj); - if ( Hop_ObjFanin1(pFanout) == pObj ) return Hop_ObjFaninC1(pObj); - assert(0); return -1; -} - -// create the ghost of the new node -static inline Hop_Obj_t * Hop_ObjCreateGhost( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ) -{ - Hop_Obj_t * pGhost; - assert( Type != AIG_AND || !Hop_ObjIsConst1(Hop_Regular(p0)) ); - assert( p1 == NULL || !Hop_ObjIsConst1(Hop_Regular(p1)) ); - assert( Type == AIG_PI || Hop_Regular(p0) != Hop_Regular(p1) ); - pGhost = Hop_ManGhost(p); - pGhost->Type = Type; - if ( Hop_Regular(p0)->Id < Hop_Regular(p1)->Id ) - { - pGhost->pFanin0 = p0; - pGhost->pFanin1 = p1; - } - else - { - pGhost->pFanin0 = p1; - pGhost->pFanin1 = p0; - } - return pGhost; -} - -// internal memory manager -static inline Hop_Obj_t * Hop_ManFetchMemory( Hop_Man_t * p ) -{ - extern void Hop_ManAddMemory( Hop_Man_t * p ); - Hop_Obj_t * pTemp; - if ( p->pListFree == NULL ) - Hop_ManAddMemory( p ); - pTemp = p->pListFree; - p->pListFree = *((Hop_Obj_t **)pTemp); - memset( pTemp, 0, sizeof(Hop_Obj_t) ); - if ( p->vObjs ) - { - assert( p->nCreated == Vec_PtrSize(p->vObjs) ); - Vec_PtrPush( p->vObjs, pTemp ); - } - pTemp->Id = p->nCreated++; - return pTemp; -} -static inline void Hop_ManRecycleMemory( Hop_Man_t * p, Hop_Obj_t * pEntry ) -{ - pEntry->Type = AIG_NONE; // distinquishes dead node from live node - *((Hop_Obj_t **)pEntry) = p->pListFree; - p->pListFree = pEntry; -} - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator over the primary inputs -#define Hop_ManForEachPi( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPis, pObj, i ) -// iterator over the primary outputs -#define Hop_ManForEachPo( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPos, pObj, i ) -// iterator over all objects, including those currently not used -#define Hop_ManForEachNode( p, pObj, i ) \ - for ( i = 0; i < p->nTableSize; i++ ) \ - if ( ((pObj) = p->pTable[i]) == NULL ) {} else - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== hopBalance.c ========================================================*/ -extern Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel ); -extern Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel ); -/*=== hopCheck.c ========================================================*/ -extern int Hop_ManCheck( Hop_Man_t * p ); -/*=== hopDfs.c ==========================================================*/ -extern Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p ); -extern Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode ); -extern int Hop_ManCountLevels( Hop_Man_t * p ); -extern void Hop_ManCreateRefs( Hop_Man_t * p ); -extern int Hop_DagSize( Hop_Obj_t * pObj ); -extern void Hop_ConeUnmark_rec( Hop_Obj_t * pObj ); -extern Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pObj, int nVars ); -extern Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar ); -/*=== hopMan.c ==========================================================*/ -extern Hop_Man_t * Hop_ManStart(); -extern Hop_Man_t * Hop_ManDup( Hop_Man_t * p ); -extern void Hop_ManStop( Hop_Man_t * p ); -extern int Hop_ManCleanup( Hop_Man_t * p ); -extern void Hop_ManPrintStats( Hop_Man_t * p ); -/*=== hopMem.c ==========================================================*/ -extern void Hop_ManStartMemory( Hop_Man_t * p ); -extern void Hop_ManStopMemory( Hop_Man_t * p ); -/*=== hopObj.c ==========================================================*/ -extern Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p ); -extern Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver ); -extern Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost ); -extern void Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 ); -extern void Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj ); -extern void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj ); -extern void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj ); -extern Hop_Obj_t * Hop_ObjRepr( Hop_Obj_t * pObj ); -extern void Hop_ObjCreateChoice( Hop_Obj_t * pOld, Hop_Obj_t * pNew ); -/*=== hopOper.c =========================================================*/ -extern Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i ); -extern Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ); -extern Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); -extern Hop_Obj_t * Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); -extern Hop_Obj_t * Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); -extern Hop_Obj_t * Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 ); -extern Hop_Obj_t * Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC ); -extern Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs ); -extern Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars ); -extern Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars ); -extern Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars ); -/*=== hopTable.c ========================================================*/ -extern Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost ); -extern void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj ); -extern void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj ); -extern int Hop_TableCountEntries( Hop_Man_t * p ); -extern void Hop_TableProfile( Hop_Man_t * p ); -/*=== hopUtil.c =========================================================*/ -extern void Hop_ManIncrementTravId( Hop_Man_t * p ); -extern void Hop_ManCleanData( Hop_Man_t * p ); -extern void Hop_ObjCleanData_rec( Hop_Obj_t * pObj ); -extern void Hop_ObjCollectMulti( Hop_Obj_t * pFunc, Vec_Ptr_t * vSuper ); -extern int Hop_ObjIsMuxType( Hop_Obj_t * pObj ); -extern int Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ); -extern Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pObj, Hop_Obj_t ** ppObjT, Hop_Obj_t ** ppObjE ); -extern void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); -extern void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); -extern void Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig ); -extern void Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig ); -extern void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/hop/hopBalance.c b/src/aig/hop/hopBalance.c deleted file mode 100644 index 73c90685..00000000 --- a/src/aig/hop/hopBalance.c +++ /dev/null @@ -1,391 +0,0 @@ -/**CFile**************************************************************** - - FileName [hopBalance.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Algebraic AIG balancing.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: hopBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "hop.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); -static Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); -static int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); -static void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); -static void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs algebraic balancing of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel ) -{ - Hop_Man_t * pNew; - Hop_Obj_t * pObj, * pObjNew; - Vec_Vec_t * vStore; - int i; - // create the new manager - pNew = Hop_ManStart(); - pNew->fRefCount = 0; - // map the PI nodes - Hop_ManCleanData( p ); - Hop_ManConst1(p)->pData = Hop_ManConst1(pNew); - Hop_ManForEachPi( p, pObj, i ) - pObj->pData = Hop_ObjCreatePi(pNew); - // balance the AIG - vStore = Vec_VecAlloc( 50 ); - Hop_ManForEachPo( p, pObj, i ) - { - pObjNew = Hop_NodeBalance_rec( pNew, Hop_ObjFanin0(pObj), vStore, 0, fUpdateLevel ); - Hop_ObjCreatePo( pNew, Hop_NotCond( pObjNew, Hop_ObjFaninC0(pObj) ) ); - } - Vec_VecFree( vStore ); - // remove dangling nodes -// Hop_ManCreateRefs( pNew ); -// if ( i = Hop_ManCleanup( pNew ) ) -// printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); - // check the resulting AIG - if ( !Hop_ManCheck(pNew) ) - printf( "Hop_ManBalance(): The check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Returns the new node constructed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) -{ - Hop_Obj_t * pObjNew; - Vec_Ptr_t * vSuper; - int i; - assert( !Hop_IsComplement(pObjOld) ); - // return if the result is known - if ( pObjOld->pData ) - return pObjOld->pData; - assert( Hop_ObjIsNode(pObjOld) ); - // get the implication supergate - vSuper = Hop_NodeBalanceCone( pObjOld, vStore, Level ); - // check if supergate contains two nodes in the opposite polarity - if ( vSuper->nSize == 0 ) - return pObjOld->pData = Hop_ManConst0(pNew); - if ( Vec_PtrSize(vSuper) < 2 ) - printf( "BUG!\n" ); - // for each old node, derive the new well-balanced node - for ( i = 0; i < Vec_PtrSize(vSuper); i++ ) - { - pObjNew = Hop_NodeBalance_rec( pNew, Hop_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); - vSuper->pArray[i] = Hop_NotCond( pObjNew, Hop_IsComplement(vSuper->pArray[i]) ); - } - // build the supergate - pObjNew = Hop_NodeBalanceBuildSuper( pNew, vSuper, Hop_ObjType(pObjOld), fUpdateLevel ); - // make sure the balanced node is not assigned -// assert( pObjOld->Level >= Hop_Regular(pObjNew)->Level ); - assert( pObjOld->pData == NULL ); - return pObjOld->pData = pObjNew; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Hop_NodeBalanceCone_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - int RetValue1, RetValue2, i; - // check if the node is visited - if ( Hop_Regular(pObj)->fMarkB ) - { - // check if the node occurs in the same polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == pObj ) - return 1; - // check if the node is present in the opposite polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == Hop_Not(pObj) ) - return -1; - assert( 0 ); - return 0; - } - // if the new node is complemented or a PI, another gate begins - if ( pObj != pRoot && (Hop_IsComplement(pObj) || Hop_ObjType(pObj) != Hop_ObjType(pRoot) || Hop_ObjRefs(pObj) > 1) ) - { - Vec_PtrPush( vSuper, pObj ); - Hop_Regular(pObj)->fMarkB = 1; - return 0; - } - assert( !Hop_IsComplement(pObj) ); - assert( Hop_ObjIsNode(pObj) ); - // go through the branches - RetValue1 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild0(pObj), vSuper ); - RetValue2 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild1(pObj), vSuper ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - // return 1 if at least one branch has a duplicate - return RetValue1 || RetValue2; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) -{ - Vec_Ptr_t * vNodes; - int RetValue, i; - assert( !Hop_IsComplement(pObj) ); - // extend the storage - if ( Vec_VecSize( vStore ) <= Level ) - Vec_VecPush( vStore, Level, 0 ); - // get the temporary array of nodes - vNodes = Vec_VecEntry( vStore, Level ); - Vec_PtrClear( vNodes ); - // collect the nodes in the implication supergate - RetValue = Hop_NodeBalanceCone_rec( pObj, pObj, vNodes ); - assert( vNodes->nSize > 1 ); - // unmark the visited nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - Hop_Regular(pObj)->fMarkB = 0; - // if we found the node and its complement in the same implication supergate, - // return empty set of nodes (meaning that we should use constant-0 node) - if ( RetValue == -1 ) - vNodes->nSize = 0; - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Hop_NodeCompareLevelsDecrease( Hop_Obj_t ** pp1, Hop_Obj_t ** pp2 ) -{ - int Diff = Hop_ObjLevel(Hop_Regular(*pp1)) - Hop_ObjLevel(Hop_Regular(*pp2)); - if ( Diff > 0 ) - return -1; - if ( Diff < 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Builds implication supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel ) -{ - Hop_Obj_t * pObj1, * pObj2; - int LeftBound; - assert( vSuper->nSize > 1 ); - // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, Hop_NodeCompareLevelsDecrease ); - // balance the nodes - while ( vSuper->nSize > 1 ) - { - // find the left bound on the node to be paired - LeftBound = (!fUpdateLevel)? 0 : Hop_NodeBalanceFindLeft( vSuper ); - // find the node that can be shared (if no such node, randomize choice) - Hop_NodeBalancePermute( p, vSuper, LeftBound, Type == AIG_EXOR ); - // pull out the last two nodes - pObj1 = Vec_PtrPop(vSuper); - pObj2 = Vec_PtrPop(vSuper); - Hop_NodeBalancePushUniqueOrderByLevel( vSuper, Hop_Oper(p, pObj1, pObj2, Type) ); - } - return Vec_PtrEntry(vSuper, 0); -} - -/**Function************************************************************* - - Synopsis [Finds the left bound on the next candidate to be paired.] - - Description [The nodes in the array are in the decreasing order of levels. - The last node in the array has the smallest level. By default it would be paired - with the next node on the left. However, it may be possible to pair it with some - other node on the left, in such a way that the new node is shared. This procedure - finds the index of the left-most node, which can be paired with the last node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) -{ - Hop_Obj_t * pObjRight, * pObjLeft; - int Current; - // if two or less nodes, pair with the first - if ( Vec_PtrSize(vSuper) < 3 ) - return 0; - // set the pointer to the one before the last - Current = Vec_PtrSize(vSuper) - 2; - pObjRight = Vec_PtrEntry( vSuper, Current ); - // go through the nodes to the left of this one - for ( Current--; Current >= 0; Current-- ) - { - // get the next node on the left - pObjLeft = Vec_PtrEntry( vSuper, Current ); - // if the level of this node is different, quit the loop - if ( Hop_ObjLevel(Hop_Regular(pObjLeft)) != Hop_ObjLevel(Hop_Regular(pObjRight)) ) - break; - } - Current++; - // get the node, for which the equality holds - pObjLeft = Vec_PtrEntry( vSuper, Current ); - assert( Hop_ObjLevel(Hop_Regular(pObjLeft)) == Hop_ObjLevel(Hop_Regular(pObjRight)) ); - return Current; -} - -/**Function************************************************************* - - Synopsis [Moves closer to the end the node that is best for sharing.] - - Description [If there is no node with sharing, randomly chooses one of - the legal nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) -{ - Hop_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; - int RightBound, i; - // get the right bound - RightBound = Vec_PtrSize(vSuper) - 2; - assert( LeftBound <= RightBound ); - if ( LeftBound == RightBound ) - return; - // get the two last nodes - pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); - pObj2 = Vec_PtrEntry( vSuper, RightBound ); - if ( Hop_Regular(pObj1) == p->pConst1 || Hop_Regular(pObj2) == p->pConst1 ) - return; - // find the first node that can be shared - for ( i = RightBound; i >= LeftBound; i-- ) - { - pObj3 = Vec_PtrEntry( vSuper, i ); - if ( Hop_Regular(pObj3) == p->pConst1 ) - { - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - pGhost = Hop_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_EXOR : AIG_AND ); - if ( Hop_TableLookup( p, pGhost ) ) - { - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - } -/* - // we did not find the node to share, randomize choice - { - int Choice = rand() % (RightBound - LeftBound + 1); - pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj ) -{ - Hop_Obj_t * pObj1, * pObj2; - int i; - if ( Vec_PtrPushUnique(vStore, pObj) ) - return; - // find the p of the node - for ( i = vStore->nSize-1; i > 0; i-- ) - { - pObj1 = vStore->pArray[i ]; - pObj2 = vStore->pArray[i-1]; - if ( Hop_ObjLevel(Hop_Regular(pObj1)) <= Hop_ObjLevel(Hop_Regular(pObj2)) ) - break; - vStore->pArray[i ] = pObj2; - vStore->pArray[i-1] = pObj1; - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/hop/hopCheck.c b/src/aig/hop/hopCheck.c deleted file mode 100644 index 9120906f..00000000 --- a/src/aig/hop/hopCheck.c +++ /dev/null @@ -1,110 +0,0 @@ -/**CFile**************************************************************** - - FileName [hopCheck.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [AIG checking procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: hopCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "hop.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks the consistency of the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Hop_ManCheck( Hop_Man_t * p ) -{ - Hop_Obj_t * pObj, * pObj2; - int i; - // check primary inputs - Hop_ManForEachPi( p, pObj, i ) - { - if ( Hop_ObjFanin0(pObj) || Hop_ObjFanin1(pObj) ) - { - printf( "Hop_ManCheck: The PI node \"%p\" has fanins.\n", pObj ); - return 0; - } - } - // check primary outputs - Hop_ManForEachPo( p, pObj, i ) - { - if ( !Hop_ObjFanin0(pObj) ) - { - printf( "Hop_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj ); - return 0; - } - if ( Hop_ObjFanin1(pObj) ) - { - printf( "Hop_ManCheck: The PO node \"%p\" has second fanin.\n", pObj ); - return 0; - } - } - // check internal nodes - Hop_ManForEachNode( p, pObj, i ) - { - if ( !Hop_ObjFanin0(pObj) || !Hop_ObjFanin1(pObj) ) - { - printf( "Hop_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj ); - return 0; - } - if ( Hop_ObjFanin0(pObj)->Id >= Hop_ObjFanin1(pObj)->Id ) - { - printf( "Hop_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj ); - return 0; - } - pObj2 = Hop_TableLookup( p, pObj ); - if ( pObj2 != pObj ) - { - printf( "Hop_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj ); - return 0; - } - } - // count the total number of nodes - if ( Hop_ManObjNum(p) != 1 + Hop_ManPiNum(p) + Hop_ManPoNum(p) + Hop_ManAndNum(p) + Hop_ManExorNum(p) ) - { - printf( "Hop_ManCheck: The number of created nodes is wrong.\n" ); - return 0; - } - // count the number of nodes in the table - if ( Hop_TableCountEntries(p) != Hop_ManAndNum(p) + Hop_ManExorNum(p) ) - { - printf( "Hop_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); - return 0; - } -// if ( !Hop_ManIsAcyclic(p) ) -// return 0; - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/hop/hopDfs.c b/src/aig/hop/hopDfs.c deleted file mode 100644 index 49e5f221..00000000 --- a/src/aig/hop/hopDfs.c +++ /dev/null @@ -1,399 +0,0 @@ -/**CFile**************************************************************** - - FileName [hopDfs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [DFS traversal procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: hopDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "hop.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ManDfs_rec( Hop_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) - return; - Hop_ManDfs_rec( Hop_ObjFanin0(pObj), vNodes ); - Hop_ManDfs_rec( Hop_ObjFanin1(pObj), vNodes ); - assert( !Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjSetMarkA(pObj); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Hop_Obj_t * pObj; - int i; - vNodes = Vec_PtrAlloc( Hop_ManNodeNum(p) ); - Hop_ManForEachNode( p, pObj, i ) - Hop_ManDfs_rec( pObj, vNodes ); - Hop_ManForEachNode( p, pObj, i ) - Hop_ObjClearMarkA(pObj); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Collects internal nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode ) -{ - Vec_Ptr_t * vNodes; - Hop_Obj_t * pObj; - int i; - assert( !Hop_IsComplement(pNode) ); - vNodes = Vec_PtrAlloc( 16 ); - Hop_ManDfs_rec( pNode, vNodes ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - Hop_ObjClearMarkA(pObj); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the max number of levels in the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Hop_ManCountLevels( Hop_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Hop_Obj_t * pObj; - int i, LevelsMax, Level0, Level1; - // initialize the levels - Hop_ManConst1(p)->pData = NULL; - Hop_ManForEachPi( p, pObj, i ) - pObj->pData = NULL; - // compute levels in a DFS order - vNodes = Hop_ManDfs( p ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - Level0 = (int)Hop_ObjFanin0(pObj)->pData; - Level1 = (int)Hop_ObjFanin1(pObj)->pData; - pObj->pData = (void *)(1 + Hop_ObjIsExor(pObj) + AIG_MAX(Level0, Level1)); - } - Vec_PtrFree( vNodes ); - // get levels of the POs - LevelsMax = 0; - Hop_ManForEachPo( p, pObj, i ) - LevelsMax = AIG_MAX( LevelsMax, (int)Hop_ObjFanin0(pObj)->pData ); - return LevelsMax; -} - -/**Function************************************************************* - - Synopsis [Creates correct reference counters at each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ManCreateRefs( Hop_Man_t * p ) -{ - Hop_Obj_t * pObj; - int i; - if ( p->fRefCount ) - return; - p->fRefCount = 1; - // clear refs - Hop_ObjClearRef( Hop_ManConst1(p) ); - Hop_ManForEachPi( p, pObj, i ) - Hop_ObjClearRef( pObj ); - Hop_ManForEachNode( p, pObj, i ) - Hop_ObjClearRef( pObj ); - Hop_ManForEachPo( p, pObj, i ) - Hop_ObjClearRef( pObj ); - // set refs - Hop_ManForEachNode( p, pObj, i ) - { - Hop_ObjRef( Hop_ObjFanin0(pObj) ); - Hop_ObjRef( Hop_ObjFanin1(pObj) ); - } - Hop_ManForEachPo( p, pObj, i ) - Hop_ObjRef( Hop_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ConeMark_rec( Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) - return; - Hop_ConeMark_rec( Hop_ObjFanin0(pObj) ); - Hop_ConeMark_rec( Hop_ObjFanin1(pObj) ); - assert( !Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ConeCleanAndMark_rec( Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) - return; - Hop_ConeCleanAndMark_rec( Hop_ObjFanin0(pObj) ); - Hop_ConeCleanAndMark_rec( Hop_ObjFanin1(pObj) ); - assert( !Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjSetMarkA( pObj ); - pObj->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Hop_ConeCountAndMark_rec( Hop_Obj_t * pObj ) -{ - int Counter; - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) - return 0; - Counter = 1 + Hop_ConeCountAndMark_rec( Hop_ObjFanin0(pObj) ) + - Hop_ConeCountAndMark_rec( Hop_ObjFanin1(pObj) ); - assert( !Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjSetMarkA( pObj ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ConeUnmark_rec( Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) - return; - Hop_ConeUnmark_rec( Hop_ObjFanin0(pObj) ); - Hop_ConeUnmark_rec( Hop_ObjFanin1(pObj) ); - assert( Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjClearMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of AIG nodes rooted at this cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Hop_DagSize( Hop_Obj_t * pObj ) -{ - int Counter; - Counter = Hop_ConeCountAndMark_rec( Hop_Regular(pObj) ); - Hop_ConeUnmark_rec( Hop_Regular(pObj) ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Transfers the AIG from one manager into another.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_Transfer_rec( Hop_Man_t * pDest, Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) - return; - Hop_Transfer_rec( pDest, Hop_ObjFanin0(pObj) ); - Hop_Transfer_rec( pDest, Hop_ObjFanin1(pObj) ); - pObj->pData = Hop_And( pDest, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); - assert( !Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Transfers the AIG from one manager into another.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pRoot, int nVars ) -{ - Hop_Obj_t * pObj; - int i; - // solve simple cases - if ( pSour == pDest ) - return pRoot; - if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) - return Hop_NotCond( Hop_ManConst1(pDest), Hop_IsComplement(pRoot) ); - // set the PI mapping - Hop_ManForEachPi( pSour, pObj, i ) - { - if ( i == nVars ) - break; - pObj->pData = Hop_IthVar(pDest, i); - } - // transfer and set markings - Hop_Transfer_rec( pDest, Hop_Regular(pRoot) ); - // clear the markings - Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); - return Hop_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); -} - -/**Function************************************************************* - - Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_Compose_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFunc, Hop_Obj_t * pVar ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( Hop_ObjIsMarkA(pObj) ) - return; - if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) - { - pObj->pData = pObj == pVar ? pFunc : pObj; - return; - } - Hop_Compose_rec( p, Hop_ObjFanin0(pObj), pFunc, pVar ); - Hop_Compose_rec( p, Hop_ObjFanin1(pObj), pFunc, pVar ); - pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); - assert( !Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar ) -{ - // quit if the PI variable is not defined - if ( iVar >= Hop_ManPiNum(p) ) - { - printf( "Hop_Compose(): The PI variable %d is not defined.\n", iVar ); - return NULL; - } - // recursively perform composition - Hop_Compose_rec( p, Hop_Regular(pRoot), pFunc, Hop_ManPi(p, iVar) ); - // clear the markings - Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); - return Hop_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/hop/hopMan.c b/src/aig/hop/hopMan.c deleted file mode 100644 index 99f5d316..00000000 --- a/src/aig/hop/hopMan.c +++ /dev/null @@ -1,164 +0,0 @@ -/**CFile**************************************************************** - - FileName [hopMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [AIG manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: hopMan.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "hop.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Man_t * Hop_ManStart() -{ - Hop_Man_t * p; - // start the manager - p = ALLOC( Hop_Man_t, 1 ); - memset( p, 0, sizeof(Hop_Man_t) ); - // perform initializations - p->nTravIds = 1; - p->fRefCount = 1; - p->fCatchExor = 0; - // allocate arrays for nodes - p->vPis = Vec_PtrAlloc( 100 ); - p->vPos = Vec_PtrAlloc( 100 ); - // prepare the internal memory manager - Hop_ManStartMemory( p ); - // create the constant node - p->pConst1 = Hop_ManFetchMemory( p ); - p->pConst1->Type = AIG_CONST1; - p->pConst1->fPhase = 1; - p->nCreated = 1; - // start the table -// p->nTableSize = 107; - p->nTableSize = 10007; - p->pTable = ALLOC( Hop_Obj_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ManStop( Hop_Man_t * p ) -{ - Hop_Obj_t * pObj; - int i; - // make sure the nodes have clean marks - pObj = Hop_ManConst1(p); - assert( !pObj->fMarkA && !pObj->fMarkB ); - Hop_ManForEachPi( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - Hop_ManForEachPo( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - Hop_ManForEachNode( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - // print time - if ( p->time1 ) { PRT( "time1", p->time1 ); } - if ( p->time2 ) { PRT( "time2", p->time2 ); } -// Hop_TableProfile( p ); - if ( p->vChunks ) Hop_ManStopMemory( p ); - if ( p->vPis ) Vec_PtrFree( p->vPis ); - if ( p->vPos ) Vec_PtrFree( p->vPos ); - if ( p->vObjs ) Vec_PtrFree( p->vObjs ); - free( p->pTable ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of dangling nodes removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Hop_ManCleanup( Hop_Man_t * p ) -{ - Vec_Ptr_t * vObjs; - Hop_Obj_t * pNode; - int i, nNodesOld; - assert( p->fRefCount ); - nNodesOld = Hop_ManNodeNum(p); - // collect roots of dangling nodes - vObjs = Vec_PtrAlloc( 100 ); - Hop_ManForEachNode( p, pNode, i ) - if ( Hop_ObjRefs(pNode) == 0 ) - Vec_PtrPush( vObjs, pNode ); - // recursively remove dangling nodes - Vec_PtrForEachEntry( vObjs, pNode, i ) - Hop_ObjDelete_rec( p, pNode ); - Vec_PtrFree( vObjs ); - return nNodesOld - Hop_ManNodeNum(p); -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ManPrintStats( Hop_Man_t * p ) -{ - printf( "PI/PO = %d/%d. ", Hop_ManPiNum(p), Hop_ManPoNum(p) ); - printf( "A = %7d. ", Hop_ManAndNum(p) ); - printf( "X = %5d. ", Hop_ManExorNum(p) ); - printf( "Cre = %7d. ", p->nCreated ); - printf( "Del = %7d. ", p->nDeleted ); - printf( "Lev = %3d. ", Hop_ManCountLevels(p) ); - printf( "\n" ); -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/hop/hopMem.c b/src/aig/hop/hopMem.c deleted file mode 100644 index 0665470a..00000000 --- a/src/aig/hop/hopMem.c +++ /dev/null @@ -1,115 +0,0 @@ -/**CFile**************************************************************** - - FileName [hopMem.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Memory management for the AIG nodes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: hopMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "hop.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// memory management -#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes -#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ManStartMemory( Hop_Man_t * p ) -{ - p->vChunks = Vec_PtrAlloc( 128 ); - p->vPages = Vec_PtrAlloc( 128 ); -} - -/**Function************************************************************* - - Synopsis [Stops the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ManStopMemory( Hop_Man_t * p ) -{ - void * pMemory; - int i; - Vec_PtrForEachEntry( p->vChunks, pMemory, i ) - free( pMemory ); - Vec_PtrFree( p->vChunks ); - Vec_PtrFree( p->vPages ); - p->pListFree = NULL; -} - -/**Function************************************************************* - - Synopsis [Allocates additional memory for the nodes.] - - Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. - Records the pointer to the AIG manager in the -1 entry.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ManAddMemory( Hop_Man_t * p ) -{ - char * pMemory; - int i, nBytes; - assert( sizeof(Hop_Obj_t) <= 64 ); - assert( p->pListFree == NULL ); -// assert( (Hop_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); - // allocate new memory page - nBytes = sizeof(Hop_Obj_t) * (1<vChunks, pMemory ); - // align memory at the 32-byte boundary - pMemory = pMemory + 64 - (((int)pMemory) & 63); - // remember the manager in the first entry - Vec_PtrPush( p->vPages, pMemory ); - // break the memory down into nodes - p->pListFree = (Hop_Obj_t *)pMemory; - for ( i = 1; i <= IVY_PAGE_MASK; i++ ) - { - *((char **)pMemory) = pMemory + sizeof(Hop_Obj_t); - pMemory += sizeof(Hop_Obj_t); - } - *((char **)pMemory) = NULL; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/hop/hopObj.c b/src/aig/hop/hopObj.c deleted file mode 100644 index c8e70dd3..00000000 --- a/src/aig/hop/hopObj.c +++ /dev/null @@ -1,271 +0,0 @@ -/**CFile**************************************************************** - - FileName [hopObj.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Adding/removing objects.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: hopObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "hop.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates primary input.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p ) -{ - Hop_Obj_t * pObj; - pObj = Hop_ManFetchMemory( p ); - pObj->Type = AIG_PI; - Vec_PtrPush( p->vPis, pObj ); - p->nObjs[AIG_PI]++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Creates primary output with the given driver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver ) -{ - Hop_Obj_t * pObj; - pObj = Hop_ManFetchMemory( p ); - pObj->Type = AIG_PO; - Vec_PtrPush( p->vPos, pObj ); - // add connections - pObj->pFanin0 = pDriver; - if ( p->fRefCount ) - Hop_ObjRef( Hop_Regular(pDriver) ); - else - pObj->nRefs = Hop_ObjLevel( Hop_Regular(pDriver) ); - // set the phase - pObj->fPhase = Hop_ObjFaninPhase(pDriver); - // update node counters of the manager - p->nObjs[AIG_PO]++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost ) -{ - Hop_Obj_t * pObj; - assert( !Hop_IsComplement(pGhost) ); - assert( Hop_ObjIsNode(pGhost) ); - assert( pGhost == &p->Ghost ); - // get memory for the new object - pObj = Hop_ManFetchMemory( p ); - pObj->Type = pGhost->Type; - // add connections - Hop_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); - // update node counters of the manager - p->nObjs[Hop_ObjType(pObj)]++; - assert( pObj->pData == NULL ); - return pObj; -} - -/**Function************************************************************* - - Synopsis [Connect the object to the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 ) -{ - assert( !Hop_IsComplement(pObj) ); - assert( Hop_ObjIsNode(pObj) ); - // add the first fanin - pObj->pFanin0 = pFan0; - pObj->pFanin1 = pFan1; - // increment references of the fanins and add their fanouts - if ( p->fRefCount ) - { - if ( pFan0 != NULL ) - Hop_ObjRef( Hop_ObjFanin0(pObj) ); - if ( pFan1 != NULL ) - Hop_ObjRef( Hop_ObjFanin1(pObj) ); - } - else - pObj->nRefs = Hop_ObjLevelNew( pObj ); - // set the phase - pObj->fPhase = Hop_ObjFaninPhase(pFan0) & Hop_ObjFaninPhase(pFan1); - // add the node to the structural hash table - Hop_TableInsert( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Connect the object to the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - assert( Hop_ObjIsNode(pObj) ); - // remove connections - if ( pObj->pFanin0 != NULL ) - Hop_ObjDeref(Hop_ObjFanin0(pObj)); - if ( pObj->pFanin1 != NULL ) - Hop_ObjDeref(Hop_ObjFanin1(pObj)); - // remove the node from the structural hash table - Hop_TableDelete( p, pObj ); - // add the first fanin - pObj->pFanin0 = NULL; - pObj->pFanin1 = NULL; -} - -/**Function************************************************************* - - Synopsis [Deletes the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - assert( !Hop_ObjIsTerm(pObj) ); - assert( Hop_ObjRefs(pObj) == 0 ); - // update node counters of the manager - p->nObjs[pObj->Type]--; - p->nDeleted++; - // remove connections - Hop_ObjDisconnect( p, pObj ); - // remove PIs/POs from the arrays - if ( Hop_ObjIsPi(pObj) ) - Vec_PtrRemove( p->vPis, pObj ); - // free the node - Hop_ManRecycleMemory( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Deletes the MFFC of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj ) -{ - Hop_Obj_t * pFanin0, * pFanin1; - assert( !Hop_IsComplement(pObj) ); - if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) - return; - assert( Hop_ObjIsNode(pObj) ); - pFanin0 = Hop_ObjFanin0(pObj); - pFanin1 = Hop_ObjFanin1(pObj); - Hop_ObjDelete( p, pObj ); - if ( pFanin0 && !Hop_ObjIsNone(pFanin0) && Hop_ObjRefs(pFanin0) == 0 ) - Hop_ObjDelete_rec( p, pFanin0 ); - if ( pFanin1 && !Hop_ObjIsNone(pFanin1) && Hop_ObjRefs(pFanin1) == 0 ) - Hop_ObjDelete_rec( p, pFanin1 ); -} - -/**Function************************************************************* - - Synopsis [Returns the representative of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_ObjRepr( Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( pObj->pData == NULL || pObj->pData == pObj ) - return pObj; - return Hop_ObjRepr( pObj->pData ); -} - -/**Function************************************************************* - - Synopsis [Sets an equivalence relation between the nodes.] - - Description [Makes the representative of pNew point to the representaive of pOld.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ObjCreateChoice( Hop_Obj_t * pOld, Hop_Obj_t * pNew ) -{ - Hop_Obj_t * pOldRepr; - Hop_Obj_t * pNewRepr; - assert( pOld != NULL && pNew != NULL ); - pOldRepr = Hop_ObjRepr(pOld); - pNewRepr = Hop_ObjRepr(pNew); - if ( pNewRepr != pOldRepr ) - pNewRepr->pData = pOldRepr; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/hop/hopOper.c b/src/aig/hop/hopOper.c deleted file mode 100644 index a31ca0f2..00000000 --- a/src/aig/hop/hopOper.c +++ /dev/null @@ -1,373 +0,0 @@ -/**CFile**************************************************************** - - FileName [hopOper.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [AIG operations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: hopOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "hop.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// procedure to detect an EXOR gate -static inline int Hop_ObjIsExorType( Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ) -{ - if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) ) - return 0; - p0 = Hop_Regular(p0); - p1 = Hop_Regular(p1); - if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) ) - return 0; - if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) ) - return 0; - if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) ) - return 0; - *ppFan0 = Hop_ObjChild0(p0); - *ppFan1 = Hop_ObjChild1(p0); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns i-th elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i ) -{ - int v; - for ( v = Hop_ManPiNum(p); v <= i; v++ ) - Hop_ObjCreatePi( p ); - assert( i < Vec_PtrSize(p->vPis) ); - return Hop_ManPi( p, i ); -} - -/**Function************************************************************* - - Synopsis [Perform one operation.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ) -{ - if ( Type == AIG_AND ) - return Hop_And( p, p0, p1 ); - if ( Type == AIG_EXOR ) - return Hop_Exor( p, p0, p1 ); - assert( 0 ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) -{ - Hop_Obj_t * pGhost, * pResult; -// Hop_Obj_t * pFan0, * pFan1; - // check trivial cases - if ( p0 == p1 ) - return p0; - if ( p0 == Hop_Not(p1) ) - return Hop_Not(p->pConst1); - if ( Hop_Regular(p0) == p->pConst1 ) - return p0 == p->pConst1 ? p1 : Hop_Not(p->pConst1); - if ( Hop_Regular(p1) == p->pConst1 ) - return p1 == p->pConst1 ? p0 : Hop_Not(p->pConst1); - // check if it can be an EXOR gate -// if ( Hop_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) -// return Hop_Exor( p, pFan0, pFan1 ); - // check the table - pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_AND ); - if ( pResult = Hop_TableLookup( p, pGhost ) ) - return pResult; - return Hop_ObjCreate( p, pGhost ); -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) -{ -/* - Hop_Obj_t * pGhost, * pResult; - // check trivial cases - if ( p0 == p1 ) - return Hop_Not(p->pConst1); - if ( p0 == Hop_Not(p1) ) - return p->pConst1; - if ( Hop_Regular(p0) == p->pConst1 ) - return Hop_NotCond( p1, p0 == p->pConst1 ); - if ( Hop_Regular(p1) == p->pConst1 ) - return Hop_NotCond( p0, p1 == p->pConst1 ); - // check the table - pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_EXOR ); - if ( pResult = Hop_TableLookup( p, pGhost ) ) - return pResult; - return Hop_ObjCreate( p, pGhost ); -*/ - return Hop_Or( p, Hop_And(p, p0, Hop_Not(p1)), Hop_And(p, Hop_Not(p0), p1) ); -} - -/**Function************************************************************* - - Synopsis [Implements Boolean OR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) -{ - return Hop_Not( Hop_And( p, Hop_Not(p0), Hop_Not(p1) ) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 ) -{ -/* - Hop_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; - int Count0, Count1; - // consider trivial cases - if ( p0 == Hop_Not(p1) ) - return Hop_Exor( p, pC, p0 ); - // other cases can be added - // implement the first MUX (F = C * x1 + C' * x0) - - // check for constants here!!! - - pTempA1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC, p1, AIG_AND) ); - pTempA2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), p0, AIG_AND) ); - if ( pTempA1 && pTempA2 ) - { - pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempA1), Hop_Not(pTempA2), AIG_AND) ); - if ( pTemp ) return Hop_Not(pTemp); - } - Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); - // implement the second MUX (F' = C * x1' + C' * x0') - pTempB1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC, Hop_Not(p1), AIG_AND) ); - pTempB2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), Hop_Not(p0), AIG_AND) ); - if ( pTempB1 && pTempB2 ) - { - pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempB1), Hop_Not(pTempB2), AIG_AND) ); - if ( pTemp ) return pTemp; - } - Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); - // compare and decide which one to implement - if ( Count0 >= Count1 ) - { - pTempA1 = pTempA1? pTempA1 : Hop_And(p, pC, p1); - pTempA2 = pTempA2? pTempA2 : Hop_And(p, Hop_Not(pC), p0); - return Hop_Or( p, pTempA1, pTempA2 ); - } - pTempB1 = pTempB1? pTempB1 : Hop_And(p, pC, Hop_Not(p1)); - pTempB2 = pTempB2? pTempB2 : Hop_And(p, Hop_Not(pC), Hop_Not(p0)); - return Hop_Not( Hop_Or( p, pTempB1, pTempB2 ) ); -*/ - return Hop_Or( p, Hop_And(p, pC, p1), Hop_And(p, Hop_Not(pC), p0) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC ) -{ - return Hop_Or( p, Hop_Or(p, Hop_And(p, pA, pB), Hop_And(p, pA, pC)), Hop_And(p, pB, pC) ); -} - -/**Function************************************************************* - - Synopsis [Constructs the well-balanced tree of gates.] - - Description [Disregards levels and possible logic sharing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_Multi_rec( Hop_Man_t * p, Hop_Obj_t ** ppObjs, int nObjs, Hop_Type_t Type ) -{ - Hop_Obj_t * pObj1, * pObj2; - if ( nObjs == 1 ) - return ppObjs[0]; - pObj1 = Hop_Multi_rec( p, ppObjs, nObjs/2, Type ); - pObj2 = Hop_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); - return Hop_Oper( p, pObj1, pObj2, Type ); -} - -/**Function************************************************************* - - Synopsis [Old code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_Multi( Hop_Man_t * p, Hop_Obj_t ** pArgs, int nArgs, Hop_Type_t Type ) -{ - assert( Type == AIG_AND || Type == AIG_EXOR ); - assert( nArgs > 0 ); - return Hop_Multi_rec( p, pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Implements the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs ) -{ - int i; - assert( vPairs->nSize > 0 ); - assert( vPairs->nSize % 2 == 0 ); - // go through the cubes of the node's SOP - for ( i = 0; i < vPairs->nSize; i += 2 ) - vPairs->pArray[i/2] = Hop_Not( Hop_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) ); - vPairs->nSize = vPairs->nSize/2; - return Hop_Not( Hop_Multi_rec( p, (Hop_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_AND ) ); -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars ) -{ - Hop_Obj_t * pFunc; - int i; - pFunc = Hop_ManConst1( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Hop_And( p, pFunc, Hop_IthVar(p, i) ); - return pFunc; -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars ) -{ - Hop_Obj_t * pFunc; - int i; - pFunc = Hop_ManConst0( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Hop_Or( p, pFunc, Hop_IthVar(p, i) ); - return pFunc; -} - -/**Function************************************************************* - - Synopsis [Creates AND function with nVars inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars ) -{ - Hop_Obj_t * pFunc; - int i; - pFunc = Hop_ManConst0( p ); - for ( i = 0; i < nVars; i++ ) - pFunc = Hop_Exor( p, pFunc, Hop_IthVar(p, i) ); - return pFunc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/hop/hopTable.c b/src/aig/hop/hopTable.c deleted file mode 100644 index 76390054..00000000 --- a/src/aig/hop/hopTable.c +++ /dev/null @@ -1,262 +0,0 @@ -/**CFile**************************************************************** - - FileName [hopTable.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [Structural hashing table.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006. ] - - Revision [$Id: hopTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "hop.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// hashing the node -static unsigned long Hop_Hash( Hop_Obj_t * pObj, int TableSize ) -{ - unsigned long Key = Hop_ObjIsExor(pObj) * 1699; - Key ^= Hop_ObjFanin0(pObj)->Id * 7937; - Key ^= Hop_ObjFanin1(pObj)->Id * 2971; - Key ^= Hop_ObjFaninC0(pObj) * 911; - Key ^= Hop_ObjFaninC1(pObj) * 353; - return Key % TableSize; -} - -// returns the place where this node is stored (or should be stored) -static Hop_Obj_t ** Hop_TableFind( Hop_Man_t * p, Hop_Obj_t * pObj ) -{ - Hop_Obj_t ** ppEntry; - assert( Hop_ObjChild0(pObj) && Hop_ObjChild1(pObj) ); - assert( Hop_ObjFanin0(pObj)->Id < Hop_ObjFanin1(pObj)->Id ); - for ( ppEntry = p->pTable + Hop_Hash(pObj, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) - if ( *ppEntry == pObj ) - return ppEntry; - assert( *ppEntry == NULL ); - return ppEntry; -} - -static void Hop_TableResize( Hop_Man_t * p ); -static unsigned int Cudd_PrimeAig( unsigned int p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks if a node with the given attributes is in the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost ) -{ - Hop_Obj_t * pEntry; - assert( !Hop_IsComplement(pGhost) ); - assert( Hop_ObjChild0(pGhost) && Hop_ObjChild1(pGhost) ); - assert( Hop_ObjFanin0(pGhost)->Id < Hop_ObjFanin1(pGhost)->Id ); - if ( p->fRefCount && (!Hop_ObjRefs(Hop_ObjFanin0(pGhost)) || !Hop_ObjRefs(Hop_ObjFanin1(pGhost))) ) - return NULL; - for ( pEntry = p->pTable[Hop_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext ) - { - if ( Hop_ObjChild0(pEntry) == Hop_ObjChild0(pGhost) && - Hop_ObjChild1(pEntry) == Hop_ObjChild1(pGhost) && - Hop_ObjType(pEntry) == Hop_ObjType(pGhost) ) - return pEntry; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Adds the new node to the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj ) -{ - Hop_Obj_t ** ppPlace; - assert( !Hop_IsComplement(pObj) ); - assert( Hop_TableLookup(p, pObj) == NULL ); - if ( (pObj->Id & 0xFF) == 0 && 2 * p->nTableSize < Hop_ManNodeNum(p) ) - Hop_TableResize( p ); - ppPlace = Hop_TableFind( p, pObj ); - assert( *ppPlace == NULL ); - *ppPlace = pObj; -} - -/**Function************************************************************* - - Synopsis [Deletes the node from the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj ) -{ - Hop_Obj_t ** ppPlace; - assert( !Hop_IsComplement(pObj) ); - ppPlace = Hop_TableFind( p, pObj ); - assert( *ppPlace == pObj ); // node should be in the table - // remove the node - *ppPlace = pObj->pNext; - pObj->pNext = NULL; -} - -/**Function************************************************************* - - Synopsis [Count the number of nodes in the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Hop_TableCountEntries( Hop_Man_t * p ) -{ - Hop_Obj_t * pEntry; - int i, Counter = 0; - for ( i = 0; i < p->nTableSize; i++ ) - for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [Typically this procedure should not be called.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_TableResize( Hop_Man_t * p ) -{ - Hop_Obj_t * pEntry, * pNext; - Hop_Obj_t ** pTableOld, ** ppPlace; - int nTableSizeOld, Counter, nEntries, i, clk; -clk = clock(); - // save the old table - pTableOld = p->pTable; - nTableSizeOld = p->nTableSize; - // get the new table - p->nTableSize = Cudd_PrimeAig( 2 * Hop_ManNodeNum(p) ); - p->pTable = ALLOC( Hop_Obj_t *, p->nTableSize ); - memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < nTableSizeOld; i++ ) - for ( pEntry = pTableOld[i], pNext = pEntry? pEntry->pNext : NULL; pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL ) - { - // get the place where this entry goes in the table - ppPlace = Hop_TableFind( p, pEntry ); - assert( *ppPlace == NULL ); // should not be there - // add the entry to the list - *ppPlace = pEntry; - pEntry->pNext = NULL; - Counter++; - } - nEntries = Hop_ManNodeNum(p); - assert( Counter == nEntries ); -// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); -// PRT( "Time", clock() - clk ); - // replace the table and the parameters - free( pTableOld ); -} - -/**Function******************************************************************** - - Synopsis [Profiles the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Hop_TableProfile( Hop_Man_t * p ) -{ - Hop_Obj_t * pEntry; - int i, Counter; - for ( i = 0; i < p->nTableSize; i++ ) - { - Counter = 0; - for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) - Counter++; - if ( Counter ) - printf( "%d ", Counter ); - } -} - -/**Function******************************************************************** - - Synopsis [Returns the next prime >= p.] - - Description [Copied from CUDD, for stand-aloneness.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -unsigned int Cudd_PrimeAig( unsigned int p) -{ - int i,pn; - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/hop/hopUtil.c b/src/aig/hop/hopUtil.c deleted file mode 100644 index 87fdb15e..00000000 --- a/src/aig/hop/hopUtil.c +++ /dev/null @@ -1,572 +0,0 @@ -/**CFile**************************************************************** - - FileName [hopUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Various procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: hopUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "hop.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Increments the current traversal ID of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ManIncrementTravId( Hop_Man_t * p ) -{ - if ( p->nTravIds >= (1<<30)-1 ) - Hop_ManCleanData( p ); - p->nTravIds++; -} - -/**Function************************************************************* - - Synopsis [Cleans the data pointers for the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ManCleanData( Hop_Man_t * p ) -{ - Hop_Obj_t * pObj; - int i; - p->nTravIds = 1; - Hop_ManConst1(p)->pData = NULL; - Hop_ManForEachPi( p, pObj, i ) - pObj->pData = NULL; - Hop_ManForEachPo( p, pObj, i ) - pObj->pData = NULL; - Hop_ManForEachNode( p, pObj, i ) - pObj->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Recursively cleans the data pointers in the cone of the node.] - - Description [Applicable to small AIGs only because no caching is performed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ObjCleanData_rec( Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - assert( !Hop_ObjIsPo(pObj) ); - if ( Hop_ObjIsAnd(pObj) ) - { - Hop_ObjCleanData_rec( Hop_ObjFanin0(pObj) ); - Hop_ObjCleanData_rec( Hop_ObjFanin1(pObj) ); - } - pObj->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Detects multi-input gate rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ObjCollectMulti_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - if ( pRoot != pObj && (Hop_IsComplement(pObj) || Hop_ObjIsPi(pObj) || Hop_ObjType(pRoot) != Hop_ObjType(pObj)) ) - { - Vec_PtrPushUnique(vSuper, pObj); - return; - } - Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild0(pObj), vSuper ); - Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild1(pObj), vSuper ); -} - -/**Function************************************************************* - - Synopsis [Detects multi-input gate rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ObjCollectMulti( Hop_Obj_t * pRoot, Vec_Ptr_t * vSuper ) -{ - assert( !Hop_IsComplement(pRoot) ); - Vec_PtrClear( vSuper ); - Hop_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Hop_ObjIsMuxType( Hop_Obj_t * pNode ) -{ - Hop_Obj_t * pNode0, * pNode1; - // check that the node is regular - assert( !Hop_IsComplement(pNode) ); - // if the node is not AND, this is not MUX - if ( !Hop_ObjIsAnd(pNode) ) - return 0; - // if the children are not complemented, this is not MUX - if ( !Hop_ObjFaninC0(pNode) || !Hop_ObjFaninC1(pNode) ) - return 0; - // get children - pNode0 = Hop_ObjFanin0(pNode); - pNode1 = Hop_ObjFanin1(pNode); - // if the children are not ANDs, this is not MUX - if ( !Hop_ObjIsAnd(pNode0) || !Hop_ObjIsAnd(pNode1) ) - return 0; - // otherwise the node is MUX iff it has a pair of equal grandchildren - return (Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1))) || - (Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1))) || - (Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1))) || - (Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1))); -} - - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are inputs of the EXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ) -{ - Hop_Obj_t * p0, * p1; - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) ) - return 0; - if ( Hop_ObjIsExor(pObj) ) - { - *ppFan0 = Hop_ObjChild0(pObj); - *ppFan1 = Hop_ObjChild1(pObj); - return 1; - } - assert( Hop_ObjIsAnd(pObj) ); - p0 = Hop_ObjChild0(pObj); - p1 = Hop_ObjChild1(pObj); - if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) ) - return 0; - p0 = Hop_Regular(p0); - p1 = Hop_Regular(p1); - if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) ) - return 0; - if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) ) - return 0; - if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) ) - return 0; - *ppFan0 = Hop_ObjChild0(p0); - *ppFan1 = Hop_ObjChild1(p0); - return 1; -} - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are control and data inputs of a MUX.] - - Description [If the node is a MUX, returns the control variable C. - Assigns nodes T and E to be the then and else variables of the MUX. - Node C is never complemented. Nodes T and E can be complemented. - This function also recognizes EXOR/NEXOR gates as MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pNode, Hop_Obj_t ** ppNodeT, Hop_Obj_t ** ppNodeE ) -{ - Hop_Obj_t * pNode0, * pNode1; - assert( !Hop_IsComplement(pNode) ); - assert( Hop_ObjIsMuxType(pNode) ); - // get children - pNode0 = Hop_ObjFanin0(pNode); - pNode1 = Hop_ObjFanin1(pNode); - - // find the control variable - if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Hop_ObjFaninC1(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); - return Hop_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); - return Hop_ObjChild1(pNode0);//pNode1->p2; - } - } - else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Hop_ObjFaninC0(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); - return Hop_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); - return Hop_ObjChild0(pNode0);//pNode1->p1; - } - } - else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Hop_ObjFaninC0(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); - return Hop_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); - return Hop_ObjChild0(pNode0);//pNode1->p1; - } - } - else if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Hop_ObjFaninC1(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); - return Hop_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); - return Hop_ObjChild1(pNode0);//pNode1->p2; - } - } - assert( 0 ); // this is not MUX - return NULL; -} - - -/**Function************************************************************* - - Synopsis [Prints Eqn formula for the AIG rooted at this node.] - - Description [The formula is in terms of PIs, which should have - their names assigned in pObj->pData fields.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) -{ - Vec_Ptr_t * vSuper; - Hop_Obj_t * pFanin; - int fCompl, i; - // store the complemented attribute - fCompl = Hop_IsComplement(pObj); - pObj = Hop_Regular(pObj); - // constant case - if ( Hop_ObjIsConst1(pObj) ) - { - fprintf( pFile, "%d", !fCompl ); - return; - } - // PI case - if ( Hop_ObjIsPi(pObj) ) - { - fprintf( pFile, "%s%s", fCompl? "!" : "", pObj->pData ); - return; - } - // AND case - Vec_VecExpand( vLevels, Level ); - vSuper = Vec_VecEntry(vLevels, Level); - Hop_ObjCollectMulti( pObj, vSuper ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - Hop_ObjPrintEqn( pFile, Hop_NotCond(pFanin, fCompl), vLevels, Level+1 ); - if ( i < Vec_PtrSize(vSuper) - 1 ) - fprintf( pFile, " %s ", fCompl? "+" : "*" ); - } - fprintf( pFile, "%s", (Level==0? "" : ")") ); - return; -} - -/**Function************************************************************* - - Synopsis [Prints Verilog formula for the AIG rooted at this node.] - - Description [The formula is in terms of PIs, which should have - their names assigned in pObj->pData fields.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) -{ - Vec_Ptr_t * vSuper; - Hop_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC; - int fCompl, i; - // store the complemented attribute - fCompl = Hop_IsComplement(pObj); - pObj = Hop_Regular(pObj); - // constant case - if ( Hop_ObjIsConst1(pObj) ) - { - fprintf( pFile, "1\'b%d", !fCompl ); - return; - } - // PI case - if ( Hop_ObjIsPi(pObj) ) - { - fprintf( pFile, "%s%s", fCompl? "~" : "", pObj->pData ); - return; - } - // EXOR case - if ( Hop_ObjIsExor(pObj) ) - { - Vec_VecExpand( vLevels, Level ); - vSuper = Vec_VecEntry( vLevels, Level ); - Hop_ObjCollectMulti( pObj, vSuper ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 ); - if ( i < Vec_PtrSize(vSuper) - 1 ) - fprintf( pFile, " ^ " ); - } - fprintf( pFile, "%s", (Level==0? "" : ")") ); - return; - } - // MUX case - if ( Hop_ObjIsMuxType(pObj) ) - { - if ( Hop_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) - { - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1 ); - fprintf( pFile, " ^ " ); - Hop_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 ); - fprintf( pFile, "%s", (Level==0? "" : ")") ); - } - else - { - pFaninC = Hop_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Hop_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 ); - fprintf( pFile, " ? " ); - Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin1, fCompl), vLevels, Level+1 ); - fprintf( pFile, " : " ); - Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1 ); - fprintf( pFile, "%s", (Level==0? "" : ")") ); - } - return; - } - // AND case - Vec_VecExpand( vLevels, Level ); - vSuper = Vec_VecEntry(vLevels, Level); - Hop_ObjCollectMulti( pObj, vSuper ); - fprintf( pFile, "%s", (Level==0? "" : "(") ); - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, fCompl), vLevels, Level+1 ); - if ( i < Vec_PtrSize(vSuper) - 1 ) - fprintf( pFile, " %s ", fCompl? "|" : "&" ); - } - fprintf( pFile, "%s", (Level==0? "" : ")") ); - return; -} - - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig ) -{ - assert( !Hop_IsComplement(pObj) ); - printf( "Node %p : ", pObj ); - if ( Hop_ObjIsConst1(pObj) ) - printf( "constant 1" ); - else if ( Hop_ObjIsPi(pObj) ) - printf( "PI" ); - else - printf( "AND( %p%s, %p%s )", - Hop_ObjFanin0(pObj), (Hop_ObjFaninC0(pObj)? "\'" : " "), - Hop_ObjFanin1(pObj), (Hop_ObjFaninC1(pObj)? "\'" : " ") ); - printf( " (refs = %3d)", Hop_ObjRefs(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig ) -{ - Vec_Ptr_t * vNodes; - Hop_Obj_t * pObj; - int i; - printf( "PIs: " ); - Hop_ManForEachPi( p, pObj, i ) - printf( " %p", pObj ); - printf( "\n" ); - vNodes = Hop_ManDfs( p ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - Hop_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes the AIG into the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName ) -{ - FILE * pFile; - Vec_Ptr_t * vNodes; - Hop_Obj_t * pObj, * pConst1 = NULL; - int i, nDigits, Counter = 0; - if ( Hop_ManPoNum(p) == 0 ) - { - printf( "Hop_ManDumpBlif(): AIG manager does not have POs.\n" ); - return; - } - // collect nodes in the DFS order - vNodes = Hop_ManDfs( p ); - // assign IDs to objects - Hop_ManConst1(p)->pData = (void *)Counter++; - Hop_ManForEachPi( p, pObj, i ) - pObj->pData = (void *)Counter++; - Hop_ManForEachPo( p, pObj, i ) - pObj->pData = (void *)Counter++; - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pData = (void *)Counter++; - nDigits = Hop_Base10Log( Counter ); - // write the file - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "# BLIF file written by procedure Hop_ManDumpBlif() in ABC\n" ); - fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); - fprintf( pFile, ".model test\n" ); - // write PIs - fprintf( pFile, ".inputs" ); - Hop_ManForEachPi( p, pObj, i ) - fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData ); - fprintf( pFile, "\n" ); - // write POs - fprintf( pFile, ".outputs" ); - Hop_ManForEachPo( p, pObj, i ) - fprintf( pFile, " n%0*d", nDigits, (int)pObj->pData ); - fprintf( pFile, "\n" ); - // write nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - fprintf( pFile, ".names n%0*d n%0*d n%0*d\n", - nDigits, (int)Hop_ObjFanin0(pObj)->pData, - nDigits, (int)Hop_ObjFanin1(pObj)->pData, - nDigits, (int)pObj->pData ); - fprintf( pFile, "%d%d 1\n", !Hop_ObjFaninC0(pObj), !Hop_ObjFaninC1(pObj) ); - } - // write POs - Hop_ManForEachPo( p, pObj, i ) - { - fprintf( pFile, ".names n%0*d n%0*d\n", - nDigits, (int)Hop_ObjFanin0(pObj)->pData, - nDigits, (int)pObj->pData ); - fprintf( pFile, "%d 1\n", !Hop_ObjFaninC0(pObj) ); - if ( Hop_ObjIsConst1(Hop_ObjFanin0(pObj)) ) - pConst1 = Hop_ManConst1(p); - } - if ( pConst1 ) - fprintf( pFile, ".names n%0*d\n 1\n", nDigits, (int)pConst1->pData ); - fprintf( pFile, ".end\n\n" ); - fclose( pFile ); - Vec_PtrFree( vNodes ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/hop/hop_.c b/src/aig/hop/hop_.c deleted file mode 100644 index 468413fa..00000000 --- a/src/aig/hop/hop_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivy_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Minimalistic And-Inverter Graph package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/hop/module.make b/src/aig/hop/module.make deleted file mode 100644 index b06d91fd..00000000 --- a/src/aig/hop/module.make +++ /dev/null @@ -1,9 +0,0 @@ -SRC += src/aig/hop/hopBalance.c \ - src/aig/hop/hopCheck.c \ - src/aig/hop/hopDfs.c \ - src/aig/hop/hopMan.c \ - src/aig/hop/hopMem.c \ - src/aig/hop/hopObj.c \ - src/aig/hop/hopOper.c \ - src/aig/hop/hopTable.c \ - src/aig/hop/hopUtil.c diff --git a/src/aig/ioa/ioa.h b/src/aig/ioa/ioa.h deleted file mode 100644 index 3458d12e..00000000 --- a/src/aig/ioa/ioa.h +++ /dev/null @@ -1,80 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioa.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [AIG package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: ioa.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __IOA_H__ -#define __IOA_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "vec.h" -#include "bar.h" -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== ioaReadAig.c ========================================================*/ -extern Aig_Man_t * Ioa_ReadAiger( char * pFileName, int fCheck ); -/*=== ioaWriteAig.c =======================================================*/ -extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols ); -/*=== ioaUtil.c =======================================================*/ -extern int Ioa_FileSize( char * pFileName ); -extern char * Ioa_FileNameGeneric( char * FileName ); -extern char * Ioa_TimeStamp(); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/ioa/ioaReadAig.c b/src/aig/ioa/ioaReadAig.c deleted file mode 100644 index 937e446f..00000000 --- a/src/aig/ioa/ioaReadAig.c +++ /dev/null @@ -1,312 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioaReadAiger.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to read binary AIGER format developed by - Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - December 16, 2006.] - - Revision [$Id: ioaReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ioa.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -unsigned Ioa_ReadAigerDecode( char ** ppPos ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the AIG in the binary AIGER format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Ioa_ReadAiger( char * pFileName, int fCheck ) -{ - Bar_Progress_t * pProgress; - FILE * pFile; - Vec_Ptr_t * vNodes, * vDrivers;//, * vTerms; - Aig_Obj_t * pObj, * pNode0, * pNode1; - Aig_Man_t * pManNew; - int nTotal, nInputs, nOutputs, nLatches, nAnds, nFileSize, i;//, iTerm, nDigits; - char * pContents, * pDrivers, * pSymbols, * pCur, * pName;//, * pType; - unsigned uLit0, uLit1, uLit; - - // read the file into the buffer - nFileSize = Ioa_FileSize( pFileName ); - pFile = fopen( pFileName, "rb" ); - pContents = ALLOC( char, nFileSize ); - fread( pContents, nFileSize, 1, pFile ); - fclose( pFile ); - - // check if the input file format is correct - if ( strncmp(pContents, "aig", 3) != 0 ) - { - fprintf( stdout, "Wrong input file format.\n" ); - return NULL; - } - - // read the file type - pCur = pContents; while ( *pCur++ != ' ' ); - // read the number of objects - nTotal = atoi( pCur ); while ( *pCur++ != ' ' ); - // read the number of inputs - nInputs = atoi( pCur ); while ( *pCur++ != ' ' ); - // read the number of latches - nLatches = atoi( pCur ); while ( *pCur++ != ' ' ); - // read the number of outputs - nOutputs = atoi( pCur ); while ( *pCur++ != ' ' ); - // read the number of nodes - nAnds = atoi( pCur ); while ( *pCur++ != '\n' ); - // check the parameters - if ( nTotal != nInputs + nLatches + nAnds ) - { - fprintf( stdout, "The paramters are wrong.\n" ); - return NULL; - } - - // allocate the empty AIG - pManNew = Aig_ManStart( nAnds ); - pName = Ioa_FileNameGeneric( pFileName ); - pManNew->pName = Aig_UtilStrsav( pName ); -// pManNew->pSpec = Ioa_UtilStrsav( pFileName ); - free( pName ); - - // prepare the array of nodes - vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); - Vec_PtrPush( vNodes, Aig_ManConst0(pManNew) ); - - // create the PIs - for ( i = 0; i < nInputs + nLatches; i++ ) - { - pObj = Aig_ObjCreatePi(pManNew); - Vec_PtrPush( vNodes, pObj ); - } -/* - // create the POs - for ( i = 0; i < nOutputs + nLatches; i++ ) - { - pObj = Aig_ObjCreatePo(pManNew); - } -*/ - // create the latches - pManNew->nRegs = nLatches; -/* - nDigits = Ioa_Base10Log( nLatches ); - for ( i = 0; i < nLatches; i++ ) - { - pObj = Aig_ObjCreateLatch(pManNew); - Aig_LatchSetInit0( pObj ); - pNode0 = Aig_ObjCreateBi(pManNew); - pNode1 = Aig_ObjCreateBo(pManNew); - Aig_ObjAddFanin( pObj, pNode0 ); - Aig_ObjAddFanin( pNode1, pObj ); - Vec_PtrPush( vNodes, pNode1 ); - // assign names to latch and its input -// Aig_ObjAssignName( pObj, Aig_ObjNameDummy("_L", i, nDigits), NULL ); -// printf( "Creating latch %s with input %d and output %d.\n", Aig_ObjName(pObj), pNode0->Id, pNode1->Id ); - } -*/ - - // remember the beginning of latch/PO literals - pDrivers = pCur; - - // scroll to the beginning of the binary data - for ( i = 0; i < nLatches + nOutputs; ) - if ( *pCur++ == '\n' ) - i++; - - // create the AND gates - pProgress = Bar_ProgressStart( stdout, nAnds ); - for ( i = 0; i < nAnds; i++ ) - { - Bar_ProgressUpdate( pProgress, i, NULL ); - uLit = ((i + 1 + nInputs + nLatches) << 1); - uLit1 = uLit - Ioa_ReadAigerDecode( &pCur ); - uLit0 = uLit1 - Ioa_ReadAigerDecode( &pCur ); -// assert( uLit1 > uLit0 ); - pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); - pNode1 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); - assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches ); - Vec_PtrPush( vNodes, Aig_And(pManNew, pNode0, pNode1) ); - } - Bar_ProgressStop( pProgress ); - - // remember the place where symbols begin - pSymbols = pCur; - - // read the latch driver literals - vDrivers = Vec_PtrAlloc( nLatches + nOutputs ); - pCur = pDrivers; -// Aig_ManForEachLatchInput( pManNew, pObj, i ) - for ( i = 0; i < nLatches; i++ ) - { - uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); - pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); -// Aig_ObjAddFanin( pObj, pNode0 ); - Vec_PtrPush( vDrivers, pNode0 ); - } - // read the PO driver literals -// Aig_ManForEachPo( pManNew, pObj, i ) - for ( i = 0; i < nOutputs; i++ ) - { - uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); - pNode0 = Aig_NotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); -// Aig_ObjAddFanin( pObj, pNode0 ); - Vec_PtrPush( vDrivers, pNode0 ); - } - - - // create the POs - for ( i = 0; i < nOutputs; i++ ) - Aig_ObjCreatePo( pManNew, Vec_PtrEntry(vDrivers, nLatches + i) ); - for ( i = 0; i < nLatches; i++ ) - Aig_ObjCreatePo( pManNew, Vec_PtrEntry(vDrivers, i) ); - Vec_PtrFree( vDrivers ); - -/* - // read the names if present - pCur = pSymbols; - if ( *pCur != 'c' ) - { - int Counter = 0; - while ( pCur < pContents + nFileSize && *pCur != 'c' ) - { - // get the terminal type - pType = pCur; - if ( *pCur == 'i' ) - vTerms = pManNew->vPis; - else if ( *pCur == 'l' ) - vTerms = pManNew->vBoxes; - else if ( *pCur == 'o' ) - vTerms = pManNew->vPos; - else - { - fprintf( stdout, "Wrong terminal type.\n" ); - return NULL; - } - // get the terminal number - iTerm = atoi( ++pCur ); while ( *pCur++ != ' ' ); - // get the node - if ( iTerm >= Vec_PtrSize(vTerms) ) - { - fprintf( stdout, "The number of terminal is out of bound.\n" ); - return NULL; - } - pObj = Vec_PtrEntry( vTerms, iTerm ); - if ( *pType == 'l' ) - pObj = Aig_ObjFanout0(pObj); - // assign the name - pName = pCur; while ( *pCur++ != '\n' ); - // assign this name - *(pCur-1) = 0; - Aig_ObjAssignName( pObj, pName, NULL ); - if ( *pType == 'l' ) - { - Aig_ObjAssignName( Aig_ObjFanin0(pObj), Aig_ObjName(pObj), "L" ); - Aig_ObjAssignName( Aig_ObjFanin0(Aig_ObjFanin0(pObj)), Aig_ObjName(pObj), "_in" ); - } - // mark the node as named - pObj->pCopy = (Aig_Obj_t *)Aig_ObjName(pObj); - } - - // assign the remaining names - Aig_ManForEachPi( pManNew, pObj, i ) - { - if ( pObj->pCopy ) continue; - Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); - Counter++; - } - Aig_ManForEachLatchOutput( pManNew, pObj, i ) - { - if ( pObj->pCopy ) continue; - Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); - Aig_ObjAssignName( Aig_ObjFanin0(pObj), Aig_ObjName(pObj), "L" ); - Aig_ObjAssignName( Aig_ObjFanin0(Aig_ObjFanin0(pObj)), Aig_ObjName(pObj), "_in" ); - Counter++; - } - Aig_ManForEachPo( pManNew, pObj, i ) - { - if ( pObj->pCopy ) continue; - Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); - Counter++; - } - if ( Counter ) - printf( "Ioa_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter ); - } - else - { -// printf( "Ioa_ReadAiger(): I/O/register names are not given. Generating short names.\n" ); - Aig_ManShortNames( pManNew ); - } -*/ - - // skipping the comments - free( pContents ); - Vec_PtrFree( vNodes ); - - // remove the extra nodes - Aig_ManCleanup( pManNew ); - - // check the result - if ( fCheck && !Aig_ManCheck( pManNew ) ) - { - printf( "Ioa_ReadAiger: The network check has failed.\n" ); - Aig_ManStop( pManNew ); - return NULL; - } - return pManNew; -} - - -/**Function************************************************************* - - Synopsis [Extracts one unsigned AIG edge from the input buffer.] - - Description [This procedure is a slightly modified version of Armin Biere's - procedure "unsigned decode (FILE * file)". ] - - SideEffects [Updates the current reading position.] - - SeeAlso [] - -***********************************************************************/ -unsigned Ioa_ReadAigerDecode( char ** ppPos ) -{ - unsigned x = 0, i = 0; - unsigned char ch; - -// while ((ch = getnoneofch (file)) & 0x80) - while ((ch = *(*ppPos)++) & 0x80) - x |= (ch & 0x7f) << (7 * i++); - - return x | (ch << (7 * i)); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ioa/ioaUtil.c b/src/aig/ioa/ioaUtil.c deleted file mode 100644 index 79dcca1e..00000000 --- a/src/aig/ioa/ioaUtil.c +++ /dev/null @@ -1,117 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioaUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to read binary AIGER format developed by - Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - December 16, 2006.] - - Revision [$Id: ioaUtil.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ioa.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the file size.] - - Description [The file should be closed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ioa_FileSize( char * pFileName ) -{ - FILE * pFile; - int nFileSize; - pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - printf( "Ioa_FileSize(): The file is unavailable (absent or open).\n" ); - return 0; - } - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - fclose( pFile ); - return nFileSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ioa_FileNameGeneric( char * FileName ) -{ - char * pDot; - char * pUnd; - char * pRes; - - // find the generic name of the file - pRes = Aig_UtilStrsav( FileName ); - // find the pointer to the "." symbol in the file name -// pUnd = strstr( FileName, "_" ); - pUnd = NULL; - pDot = strstr( FileName, "." ); - if ( pUnd ) - pRes[pUnd - FileName] = 0; - else if ( pDot ) - pRes[pDot - FileName] = 0; - return pRes; -} - -/**Function************************************************************* - - Synopsis [Returns the time stamp.] - - Description [The file should be closed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ioa_TimeStamp() -{ - static char Buffer[100]; - char * TimeStamp; - time_t ltime; - // get the current time - time( <ime ); - TimeStamp = asctime( localtime( <ime ) ); - TimeStamp[ strlen(TimeStamp) - 1 ] = 0; - strcpy( Buffer, TimeStamp ); - return Buffer; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ioa/ioaWriteAig.c b/src/aig/ioa/ioaWriteAig.c deleted file mode 100644 index a6c23fd4..00000000 --- a/src/aig/ioa/ioaWriteAig.c +++ /dev/null @@ -1,292 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioaWriteAiger.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write binary AIGER format developed by - Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - December 16, 2006.] - - Revision [$Id: ioaWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ioa.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/* - The following is taken from the AIGER format description, - which can be found at http://fmv.jku.at/aiger -*/ - - -/* - The AIGER And-Inverter Graph (AIG) Format Version 20061129 - ---------------------------------------------------------- - Armin Biere, Johannes Kepler University, 2006 - - This report describes the AIG file format as used by the AIGER library. - The purpose of this report is not only to motivate and document the - format, but also to allow independent implementations of writers and - readers by giving precise and unambiguous definitions. - - ... - -Introduction - - The name AIGER contains as one part the acronym AIG of And-Inverter - Graphs and also if pronounced in German sounds like the name of the - 'Eiger', a mountain in the Swiss alps. This choice should emphasize the - origin of this format. It was first openly discussed at the Alpine - Verification Meeting 2006 in Ascona as a way to provide a simple, compact - file format for a model checking competition affiliated to CAV 2007. - - ... - -Binary Format Definition - - The binary format is semantically a subset of the ASCII format with a - slightly different syntax. The binary format may need to reencode - literals, but translating a file in binary format into ASCII format and - then back in to binary format will result in the same file. - - The main differences of the binary format to the ASCII format are as - follows. After the header the list of input literals and all the - current state literals of a latch can be omitted. Furthermore the - definitions of the AND gates are binary encoded. However, the symbol - table and the comment section are as in the ASCII format. - - The header of an AIGER file in binary format has 'aig' as format - identifier, but otherwise is identical to the ASCII header. The standard - file extension for the binary format is therefore '.aig'. - - A header for the binary format is still in ASCII encoding: - - aig M I L O A - - Constants, variables and literals are handled in the same way as in the - ASCII format. The first simplifying restriction is on the variable - indices of inputs and latches. The variable indices of inputs come first, - followed by the pseudo-primary inputs of the latches and then the variable - indices of all LHS of AND gates: - - input variable indices 1, 2, ... , I - latch variable indices I+1, I+2, ... , (I+L) - AND variable indices I+L+1, I+L+2, ... , (I+L+A) == M - - The corresponding unsigned literals are - - input literals 2, 4, ... , 2*I - latch literals 2*I+2, 2*I+4, ... , 2*(I+L) - AND literals 2*(I+L)+2, 2*(I+L)+4, ... , 2*(I+L+A) == 2*M - - All literals have to be defined, and therefore 'M = I + L + A'. With this - restriction it becomes possible that the inputs and the current state - literals of the latches do not have to be listed explicitly. Therefore, - after the header only the list of 'L' next state literals follows, one per - latch on a single line, and then the 'O' outputs, again one per line. - - In the binary format we assume that the AND gates are ordered and respect - the child parent relation. AND gates with smaller literals on the LHS - come first. Therefore we can assume that the literals on the right-hand - side of a definition of an AND gate are smaller than the LHS literal. - Furthermore we can sort the literals on the RHS, such that the larger - literal comes first. A definition thus consists of three literals - - lhs rhs0 rhs1 - - with 'lhs' even and 'lhs > rhs0 >= rhs1'. Also the variable indices are - pairwise different to avoid combinational self loops. Since the LHS - indices of the definitions are all consecutive (as even integers), - the binary format does not have to keep 'lhs'. In addition, we can use - the order restriction and only write the differences 'delta0' and 'delta1' - instead of 'rhs0' and 'rhs1', with - - delta0 = lhs - rhs0, delta1 = rhs0 - rhs1 - - The differences will all be strictly positive, and in practice often very - small. We can take advantage of this fact by the simple little-endian - encoding of unsigned integers of the next section. After the binary delta - encoding of the RHSs of all AND gates, the optional symbol table and - optional comment section start in the same format as in the ASCII case. - - ... - -*/ - -static unsigned Ioa_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } -static unsigned Ioa_ObjAigerNum( Aig_Obj_t * pObj ) { return (unsigned)pObj->pData; } -static void Ioa_ObjSetAigerNum( Aig_Obj_t * pObj, unsigned Num ) { pObj->pData = (void *)Num; } - -int Ioa_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes the AIG in the binary AIGER format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols ) -{ - Bar_Progress_t * pProgress; - FILE * pFile; - Aig_Obj_t * pObj, * pDriver; - int i, nNodes, Pos, nBufferSize; - unsigned char * pBuffer; - unsigned uLit0, uLit1, uLit; - -// assert( Aig_ManIsStrash(pMan) ); - // start the output stream - pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Ioa_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); - return; - } -/* - Aig_ManForEachLatch( pMan, pObj, i ) - if ( !Aig_LatchIsInit0(pObj) ) - { - fprintf( stdout, "Ioa_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" ); - return; - } -*/ - // set the node numbers to be used in the output file - nNodes = 0; - Ioa_ObjSetAigerNum( Aig_ManConst1(pMan), nNodes++ ); - Aig_ManForEachPi( pMan, pObj, i ) - Ioa_ObjSetAigerNum( pObj, nNodes++ ); - Aig_ManForEachNode( pMan, pObj, i ) - Ioa_ObjSetAigerNum( pObj, nNodes++ ); - - // write the header "M I L O A" where M = I + L + A - fprintf( pFile, "aig %u %u %u %u %u\n", - Aig_ManPiNum(pMan) + Aig_ManNodeNum(pMan), - Aig_ManPiNum(pMan) - Aig_ManRegNum(pMan), - Aig_ManRegNum(pMan), - Aig_ManPoNum(pMan) - Aig_ManRegNum(pMan), - Aig_ManNodeNum(pMan) ); - - // if the driver node is a constant, we need to complement the literal below - // because, in the AIGER format, literal 0/1 is represented as number 0/1 - // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0 - - // write latch drivers - Aig_ManForEachLiSeq( pMan, pObj, i ) - { - pDriver = Aig_ObjFanin0(pObj); - fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); - } - - // write PO drivers - Aig_ManForEachPoSeq( pMan, pObj, i ) - { - pDriver = Aig_ObjFanin0(pObj); - fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); - } - - // write the nodes into the buffer - Pos = 0; - nBufferSize = 6 * Aig_ManNodeNum(pMan) + 100; // skeptically assuming 3 chars per one AIG edge - pBuffer = ALLOC( char, nBufferSize ); - pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(pMan) ); - Aig_ManForEachNode( pMan, pObj, i ) - { - Bar_ProgressUpdate( pProgress, i, NULL ); - uLit = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pObj), 0 ); - uLit0 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); - uLit1 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); - assert( uLit0 < uLit1 ); - Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); - Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); - if ( Pos > nBufferSize - 10 ) - { - printf( "Ioa_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); - fclose( pFile ); - return; - } - } - assert( Pos < nBufferSize ); - Bar_ProgressStop( pProgress ); - - // write the buffer - fwrite( pBuffer, 1, Pos, pFile ); - free( pBuffer ); -/* - // write the symbol table - if ( fWriteSymbols ) - { - // write PIs - Aig_ManForEachPi( pMan, pObj, i ) - fprintf( pFile, "i%d %s\n", i, Aig_ObjName(pObj) ); - // write latches - Aig_ManForEachLatch( pMan, pObj, i ) - fprintf( pFile, "l%d %s\n", i, Aig_ObjName(Aig_ObjFanout0(pObj)) ); - // write POs - Aig_ManForEachPo( pMan, pObj, i ) - fprintf( pFile, "o%d %s\n", i, Aig_ObjName(pObj) ); - } -*/ - // write the comment - fprintf( pFile, "c\n" ); - if ( pMan->pName ) - fprintf( pFile, ".model %s\n", pMan->pName ); - fprintf( pFile, "This file was produced by the AIG package in ABC on %s\n", Ioa_TimeStamp() ); - fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Adds one unsigned AIG edge to the output buffer.] - - Description [This procedure is a slightly modified version of Armin Biere's - procedure "void encode (FILE * file, unsigned x)" ] - - SideEffects [Returns the current writing position.] - - SeeAlso [] - -***********************************************************************/ -int Ioa_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ) -{ - unsigned char ch; - while (x & ~0x7f) - { - ch = (x & 0x7f) | 0x80; -// putc (ch, file); - pBuffer[Pos++] = ch; - x >>= 7; - } - ch = x; -// putc (ch, file); - pBuffer[Pos++] = ch; - return Pos; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ioa/module.make b/src/aig/ioa/module.make deleted file mode 100644 index 66b4a0d5..00000000 --- a/src/aig/ioa/module.make +++ /dev/null @@ -1,3 +0,0 @@ -SRC += src/aig/ioa/ioaReadAig.c \ - src/aig/ioa/ioaWriteAig.c \ - src/aig/ioa/ioaUtil.c diff --git a/src/aig/ivy/attr.h b/src/aig/ivy/attr.h deleted file mode 100644 index 16cf0b84..00000000 --- a/src/aig/ivy/attr.h +++ /dev/null @@ -1,414 +0,0 @@ -/**CFile**************************************************************** - - FileName [attr.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network attributes.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: attr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __ATTR_H__ -#define __ATTR_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Attr_ManStruct_t_ Attr_Man_t; -struct Attr_ManStruct_t_ -{ - // attribute info - int nAttrSize; // the size of each attribute in bytes - Extra_MmFixed_t * pManMem; // memory manager for attributes - int nAttrs; // the number of attributes allocated - void ** pAttrs; // the array of attributes - int fUseInt; // uses integer attributes - // attribute specific info - void * pManAttr; // the manager for this attribute - void (*pFuncFreeMan) (void *); // the procedure to call to free attribute-specific manager - void (*pFuncFreeObj) (void *, void *); // the procedure to call to free attribute-specific data -}; - -// at any time, an attribute of the given ID can be -// - not available (p->nAttrs < Id) -// - available but not allocated (p->nAttrs >= Id && p->pAttrs[Id] == NULL) -// - available and allocated (p->nAttrs >= Id && p->pAttrs[Id] != NULL) - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the attribute manager.] - - Description [The manager is simple if it does not need memory manager.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Attr_Man_t * Attr_ManAlloc( int nAttrSize, int fManMem ) -{ - Attr_Man_t * p; - p = ALLOC( Attr_Man_t, 1 ); - memset( p, 0, sizeof(Attr_Man_t) ); - p->nAttrSize = nAttrSize; - if ( fManMem ) - p->pManMem = Extra_MmFixedStart( nAttrSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Start the attribute manager for integers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Attr_Man_t * Attr_ManStartInt( int nAttrs ) -{ - Attr_Man_t * p; - p = Attr_ManAlloc( sizeof(int), 0 ); - p->nAttrs = nAttrs; - p->pAttrs = (void **)ALLOC( int, nAttrs ); - memset( (int *)p->pAttrs, 0, sizeof(int) * nAttrs ); - p->fUseInt = 1; - return p; -} - -/**Function************************************************************* - - Synopsis [Start the attribute manager for pointers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Attr_Man_t * Attr_ManStartPtr( int nAttrs ) -{ - Attr_Man_t * p; - p = Attr_ManAlloc( sizeof(void *), 0 ); - p->nAttrs = nAttrs; - p->pAttrs = ALLOC( void *, nAttrs ); - memset( p->pAttrs, 0, sizeof(void *) * nAttrs ); - return p; -} - -/**Function************************************************************* - - Synopsis [Start the attribute manager for the fixed entry size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Attr_Man_t * Attr_ManStartPtrMem( int nAttrs, int nAttrSize ) -{ - Attr_Man_t * p; - int i; - p = Attr_ManAlloc( nAttrSize, 1 ); - p->nAttrs = nAttrs; - p->pAttrs = ALLOC( void *, nAttrs ); - for ( i = 0; i < p->nAttrs; i++ ) - { - p->pAttrs[i] = Extra_MmFixedEntryFetch( p->pManMem ); - memset( p->pAttrs[i], 0, nAttrSize ); - } - return p; -} - -/**Function************************************************************* - - Synopsis [Stop the attribute manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Attr_ManStop( Attr_Man_t * p ) -{ - // free the attributes of objects - if ( p->pFuncFreeObj ) - { - int i; - if ( p->fUseInt ) - { - for ( i = 0; i < p->nAttrs; i++ ) - if ( ((int *)p->pAttrs)[i] ) - p->pFuncFreeObj( p->pManAttr, (void *)((int *)p->pAttrs)[i] ); - } - else - { - for ( i = 0; i < p->nAttrs; i++ ) - if ( p->pAttrs[i] ) - p->pFuncFreeObj( p->pManAttr, p->pAttrs[i] ); - } - } - // free the attribute manager - if ( p->pManAttr && p->pFuncFreeMan ) - p->pFuncFreeMan( p->pManAttr ); - // free the memory manager - if ( p->pManMem ) - Extra_MmFixedStop( p->pManMem); - // free the attribute manager - FREE( p->pAttrs ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Reads the attribute of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Attr_ManReadAttrInt( Attr_Man_t * p, int Id ) -{ - assert( p->fUseInt ); - if ( Id >= p->nAttrs ) - return 0; - return ((int *)p->pAttrs)[Id]; -} - -/**Function************************************************************* - - Synopsis [Reads the attribute of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Attr_ManReadAttrPtr( Attr_Man_t * p, int Id ) -{ - assert( !p->fUseInt ); - if ( Id >= p->nAttrs ) - return NULL; - return p->pAttrs[Id]; -} - -/**Function************************************************************* - - Synopsis [Writes the attribute of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Attr_ManWriteAttrInt( Attr_Man_t * p, int Id, int Attr ) -{ - assert( p->fUseInt ); - ((int *)p->pAttrs)[Id] = Attr; -} - -/**Function************************************************************* - - Synopsis [Writes the attribute of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Attr_ManWriteAttrPtr( Attr_Man_t * p, int Id, void * pAttr ) -{ - assert( !p->fUseInt ); - assert( p->pManMem == NULL ); - p->pAttrs[Id] = pAttr; -} - -/**Function************************************************************* - - Synopsis [Returns or creates the pointer to the attribute of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int * Attr_ManFetchSpotInt( Attr_Man_t * p, int Id ) -{ - assert( p->fUseInt ); - if ( Id >= p->nAttrs ) - { - // save the old size - int i, nAttrsOld = p->nAttrs; - // get the new size - p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024; - p->pAttrs = realloc( p->pAttrs, sizeof(int) * p->nAttrs ); - // fill in the empty spots - for ( i = nAttrsOld; i < p->nAttrs; i++ ) - ((int *)p->pAttrs)[Id] = 0; - } - return ((int *)p->pAttrs) + Id; -} - -/**Function************************************************************* - - Synopsis [Returns or creates the pointer to the attribute of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void ** Attr_ManFetchSpotPtr( Attr_Man_t * p, int Id ) -{ - assert( !p->fUseInt ); - if ( Id >= p->nAttrs ) - { - // save the old size - int i, nAttrsOld = p->nAttrs; - // get the new size - p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024; - p->pAttrs = realloc( p->pAttrs, sizeof(void *) * p->nAttrs ); - // fill in the empty spots - for ( i = nAttrsOld; i < p->nAttrs; i++ ) - p->pAttrs[Id] = NULL; - } - // if memory manager is available but entry is not created, create it - if ( p->pManMem && p->pAttrs[Id] != NULL ) - { - p->pAttrs[Id] = Extra_MmFixedEntryFetch( p->pManMem ); - memset( p->pAttrs[Id], 0, p->nAttrSize ); - } - return p->pAttrs + Id; -} - - -/**Function************************************************************* - - Synopsis [Returns or creates the attribute of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Attr_ManFetchAttrInt( Attr_Man_t * p, int Id ) -{ - return *Attr_ManFetchSpotInt( p, Id ); -} - -/**Function************************************************************* - - Synopsis [Returns or creates the attribute of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Attr_ManFetchAttrPtr( Attr_Man_t * p, int Id ) -{ - return *Attr_ManFetchSpotPtr( p, Id ); -} - -/**Function************************************************************* - - Synopsis [Sets the attribute of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Attr_ManSetAttrInt( Attr_Man_t * p, int Id, int Attr ) -{ - *Attr_ManFetchSpotInt( p, Id ) = Attr; -} - -/**Function************************************************************* - - Synopsis [Sets the attribute of the given object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Attr_ManSetAttrPtr( Attr_Man_t * p, int Id, void * pAttr ) -{ - assert( p->pManMem == NULL ); - *Attr_ManFetchSpotPtr( p, Id ) = pAttr; -} - - - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/ivy/ivy.h b/src/aig/ivy/ivy.h deleted file mode 100644 index ed19d67c..00000000 --- a/src/aig/ivy/ivy.h +++ /dev/null @@ -1,557 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivy.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivy.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __IVY_H__ -#define __IVY_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "extra.h" -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ivy_Man_t_ Ivy_Man_t; -typedef struct Ivy_Obj_t_ Ivy_Obj_t; -typedef int Ivy_Edge_t; -typedef struct Ivy_FraigParams_t_ Ivy_FraigParams_t; - -// object types -typedef enum { - IVY_NONE, // 0: non-existent object - IVY_PI, // 1: primary input (and constant 1 node) - IVY_PO, // 2: primary output - IVY_ASSERT, // 3: assertion - IVY_LATCH, // 4: sequential element - IVY_AND, // 5: AND node - IVY_EXOR, // 6: EXOR node - IVY_BUF, // 7: buffer (temporary) - IVY_VOID // 8: unused object -} Ivy_Type_t; - -// latch initial values -typedef enum { - IVY_INIT_NONE, // 0: not a latch - IVY_INIT_0, // 1: zero - IVY_INIT_1, // 2: one - IVY_INIT_DC // 3: don't-care -} Ivy_Init_t; - -// the AIG node -struct Ivy_Obj_t_ // 24 bytes (32-bit) or 32 bytes (64-bit) // 10 words - 16 words -{ - int Id; // integer ID - int TravId; // traversal ID - unsigned Type : 4; // object type - unsigned fMarkA : 1; // multipurpose mask - unsigned fMarkB : 1; // multipurpose mask - unsigned fExFan : 1; // set to 1 if last fanout added is EXOR - unsigned fPhase : 1; // value under 000...0 pattern - unsigned fFailTfo : 1; // the TFO of the failed node - unsigned Init : 2; // latch initial value - unsigned Level : 21; // logic level - int nRefs; // reference counter - Ivy_Obj_t * pFanin0; // fanin - Ivy_Obj_t * pFanin1; // fanin - Ivy_Obj_t * pFanout; // fanout - Ivy_Obj_t * pNextFan0; // next fanout of the first fanin - Ivy_Obj_t * pNextFan1; // next fanout of the second fanin - Ivy_Obj_t * pPrevFan0; // prev fanout of the first fanin - Ivy_Obj_t * pPrevFan1; // prev fanout of the second fanin - Ivy_Obj_t * pEquiv; // equivalent node -}; - -// the AIG manager -struct Ivy_Man_t_ -{ - // AIG nodes - Vec_Ptr_t * vPis; // the array of PIs - Vec_Ptr_t * vPos; // the array of POs - Vec_Ptr_t * vBufs; // the array of buffers - Vec_Ptr_t * vObjs; // the array of objects - Ivy_Obj_t * pConst1; // the constant 1 node - Ivy_Obj_t Ghost; // the ghost node - // AIG node counters - int nObjs[IVY_VOID];// the number of objects by type - int nCreated; // the number of created objects - int nDeleted; // the number of deleted objects - // stuctural hash table - int * pTable; // structural hash table - int nTableSize; // structural hash table size - // various data members - int fCatchExor; // set to 1 to detect EXORs - int nTravIds; // the traversal ID - int nLevelMax; // the maximum level - Vec_Int_t * vRequired; // required times - int fFanout; // fanout is allocated - void * pData; // the temporary data - void * pCopy; // the temporary data - Ivy_Man_t * pHaig; // history AIG if present - int nClassesSkip; // the number of skipped classes - // memory management - Vec_Ptr_t * vChunks; // allocated memory pieces - Vec_Ptr_t * vPages; // memory pages used by nodes - Ivy_Obj_t * pListFree; // the list of free nodes - // timing statistics - int time1; - int time2; -}; - -struct Ivy_FraigParams_t_ -{ - int nSimWords; // the number of words in the simulation info - double dSimSatur; // the ratio of refined classes when saturation is reached - int fPatScores; // enables simulation pattern scoring - int MaxScore; // max score after which resimulation is used - double dActConeRatio; // the ratio of cone to be bumped - double dActConeBumpMax; // the largest bump in activity - int fProve; // prove the miter outputs - int fVerbose; // verbose output - int fDoSparse; // skip sparse functions - int nBTLimitNode; // conflict limit at a node - int nBTLimitMiter; // conflict limit at an output -// int nBTLimitGlobal; // conflict limit global -// int nInsLimitNode; // inspection limit at a node -// int nInsLimitMiter; // inspection limit at an output -// int nInsLimitGlobal; // inspection limit global -}; - - -#define IVY_CUT_LIMIT 256 -#define IVY_CUT_INPUT 6 - -typedef struct Ivy_Cut_t_ Ivy_Cut_t; -struct Ivy_Cut_t_ -{ - int nLatches; - short nSize; - short nSizeMax; - int pArray[IVY_CUT_INPUT]; - unsigned uHash; -}; - -typedef struct Ivy_Store_t_ Ivy_Store_t; -struct Ivy_Store_t_ -{ - int nCuts; - int nCutsM; - int nCutsMax; - int fSatur; - Ivy_Cut_t pCuts[IVY_CUT_LIMIT]; // storage for cuts -}; - -#define IVY_LEAF_MASK 255 -#define IVY_LEAF_BITS 8 - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define IVY_MIN(a,b) (((a) < (b))? (a) : (b)) -#define IVY_MAX(a,b) (((a) > (b))? (a) : (b)) - -static inline int Ivy_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } -static inline int Ivy_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -static inline int Ivy_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } -static inline void Ivy_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } -static inline void Ivy_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } - -static inline Ivy_Obj_t * Ivy_Regular( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned long)(p) & ~01); } -static inline Ivy_Obj_t * Ivy_Not( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((unsigned long)(p) ^ 01); } -static inline Ivy_Obj_t * Ivy_NotCond( Ivy_Obj_t * p, int c ) { return (Ivy_Obj_t *)((unsigned long)(p) ^ (c)); } -static inline int Ivy_IsComplement( Ivy_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } - -static inline Ivy_Obj_t * Ivy_ManConst0( Ivy_Man_t * p ) { return Ivy_Not(p->pConst1); } -static inline Ivy_Obj_t * Ivy_ManConst1( Ivy_Man_t * p ) { return p->pConst1; } -static inline Ivy_Obj_t * Ivy_ManGhost( Ivy_Man_t * p ) { return &p->Ghost; } -static inline Ivy_Obj_t * Ivy_ManPi( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPis, i); } -static inline Ivy_Obj_t * Ivy_ManPo( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPos, i); } -static inline Ivy_Obj_t * Ivy_ManObj( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vObjs, i); } - -static inline Ivy_Edge_t Ivy_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } -static inline int Ivy_EdgeId( Ivy_Edge_t Edge ) { return Edge >> 1; } -static inline int Ivy_EdgeIsComplement( Ivy_Edge_t Edge ) { return Edge & 1; } -static inline Ivy_Edge_t Ivy_EdgeRegular( Ivy_Edge_t Edge ) { return (Edge >> 1) << 1; } -static inline Ivy_Edge_t Ivy_EdgeNot( Ivy_Edge_t Edge ) { return Edge ^ 1; } -static inline Ivy_Edge_t Ivy_EdgeNotCond( Ivy_Edge_t Edge, int fCond ) { return Edge ^ fCond; } -static inline Ivy_Edge_t Ivy_EdgeFromNode( Ivy_Obj_t * pNode ) { return Ivy_EdgeCreate( Ivy_Regular(pNode)->Id, Ivy_IsComplement(pNode) ); } -static inline Ivy_Obj_t * Ivy_EdgeToNode( Ivy_Man_t * p, Ivy_Edge_t Edge ){ return Ivy_NotCond( Ivy_ManObj(p, Ivy_EdgeId(Edge)), Ivy_EdgeIsComplement(Edge) ); } - -static inline int Ivy_LeafCreate( int Id, int Lat ) { return (Id << IVY_LEAF_BITS) | Lat; } -static inline int Ivy_LeafId( int Leaf ) { return Leaf >> IVY_LEAF_BITS; } -static inline int Ivy_LeafLat( int Leaf ) { return Leaf & IVY_LEAF_MASK; } - -static inline int Ivy_ManPiNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PI]; } -static inline int Ivy_ManPoNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PO]; } -static inline int Ivy_ManAssertNum( Ivy_Man_t * p ) { return p->nObjs[IVY_ASSERT]; } -static inline int Ivy_ManLatchNum( Ivy_Man_t * p ) { return p->nObjs[IVY_LATCH]; } -static inline int Ivy_ManAndNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]; } -static inline int Ivy_ManExorNum( Ivy_Man_t * p ) { return p->nObjs[IVY_EXOR]; } -static inline int Ivy_ManBufNum( Ivy_Man_t * p ) { return p->nObjs[IVY_BUF]; } -static inline int Ivy_ManObjNum( Ivy_Man_t * p ) { return p->nCreated - p->nDeleted; } -static inline int Ivy_ManObjIdMax( Ivy_Man_t * p ) { return Vec_PtrSize(p->vObjs)-1; } -static inline int Ivy_ManNodeNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR];} -static inline int Ivy_ManHashObjNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR]+p->nObjs[IVY_LATCH]; } -static inline int Ivy_ManGetCost( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+3*p->nObjs[IVY_EXOR]+8*p->nObjs[IVY_LATCH]; } - -static inline Ivy_Type_t Ivy_ObjType( Ivy_Obj_t * pObj ) { return pObj->Type; } -static inline Ivy_Init_t Ivy_ObjInit( Ivy_Obj_t * pObj ) { return pObj->Init; } -static inline int Ivy_ObjIsConst1( Ivy_Obj_t * pObj ) { return pObj->Id == 0; } -static inline int Ivy_ObjIsGhost( Ivy_Obj_t * pObj ) { return pObj->Id < 0; } -static inline int Ivy_ObjIsNone( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_NONE; } -static inline int Ivy_ObjIsPi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI; } -static inline int Ivy_ObjIsPo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO; } -static inline int Ivy_ObjIsCi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsCo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsAssert( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_ASSERT; } -static inline int Ivy_ObjIsLatch( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsAnd( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND; } -static inline int Ivy_ObjIsExor( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_EXOR; } -static inline int Ivy_ObjIsBuf( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_BUF; } -static inline int Ivy_ObjIsNode( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR; } -static inline int Ivy_ObjIsTerm( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; } -static inline int Ivy_ObjIsHash( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR || pObj->Type == IVY_LATCH; } -static inline int Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; } - -static inline int Ivy_ObjIsMarkA( Ivy_Obj_t * pObj ) { return pObj->fMarkA; } -static inline void Ivy_ObjSetMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 1; } -static inline void Ivy_ObjClearMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 0; } - -static inline void Ivy_ObjSetTravId( Ivy_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } -static inline void Ivy_ObjSetTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } -static inline void Ivy_ObjSetTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } -static inline int Ivy_ObjIsTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); } -static inline int Ivy_ObjIsTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds - 1); } - -static inline int Ivy_ObjId( Ivy_Obj_t * pObj ) { return pObj->Id; } -static inline int Ivy_ObjTravId( Ivy_Obj_t * pObj ) { return pObj->TravId; } -static inline int Ivy_ObjPhase( Ivy_Obj_t * pObj ) { return pObj->fPhase; } -static inline int Ivy_ObjExorFanout( Ivy_Obj_t * pObj ) { return pObj->fExFan; } -static inline int Ivy_ObjRefs( Ivy_Obj_t * pObj ) { return pObj->nRefs; } -static inline void Ivy_ObjRefsInc( Ivy_Obj_t * pObj ) { pObj->nRefs++; } -static inline void Ivy_ObjRefsDec( Ivy_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } -static inline int Ivy_ObjFaninId0( Ivy_Obj_t * pObj ) { return pObj->pFanin0? Ivy_ObjId(Ivy_Regular(pObj->pFanin0)) : 0; } -static inline int Ivy_ObjFaninId1( Ivy_Obj_t * pObj ) { return pObj->pFanin1? Ivy_ObjId(Ivy_Regular(pObj->pFanin1)) : 0; } -static inline int Ivy_ObjFaninC0( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin0); } -static inline int Ivy_ObjFaninC1( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin1); } -static inline Ivy_Obj_t * Ivy_ObjFanin0( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin0); } -static inline Ivy_Obj_t * Ivy_ObjFanin1( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin1); } -static inline Ivy_Obj_t * Ivy_ObjChild0( Ivy_Obj_t * pObj ) { return pObj->pFanin0; } -static inline Ivy_Obj_t * Ivy_ObjChild1( Ivy_Obj_t * pObj ) { return pObj->pFanin1; } -static inline Ivy_Obj_t * Ivy_ObjChild0Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin0(pObj)? Ivy_NotCond(Ivy_ObjFanin0(pObj)->pEquiv, Ivy_ObjFaninC0(pObj)) : NULL; } -static inline Ivy_Obj_t * Ivy_ObjChild1Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin1(pObj)? Ivy_NotCond(Ivy_ObjFanin1(pObj)->pEquiv, Ivy_ObjFaninC1(pObj)) : NULL; } -static inline Ivy_Obj_t * Ivy_ObjEquiv( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj)->pEquiv? Ivy_NotCond(Ivy_Regular(pObj)->pEquiv, Ivy_IsComplement(pObj)) : NULL; } -static inline int Ivy_ObjLevel( Ivy_Obj_t * pObj ) { return pObj->Level; } -static inline int Ivy_ObjLevelNew( Ivy_Obj_t * pObj ) { return 1 + Ivy_ObjIsExor(pObj) + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level); } -static inline int Ivy_ObjFaninPhase( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj)? !Ivy_Regular(pObj)->fPhase : pObj->fPhase; } - -static inline void Ivy_ObjClean( Ivy_Obj_t * pObj ) -{ - int IdSaved = pObj->Id; - memset( pObj, 0, sizeof(Ivy_Obj_t) ); - pObj->Id = IdSaved; -} -static inline void Ivy_ObjOverwrite( Ivy_Obj_t * pBase, Ivy_Obj_t * pData ) -{ - int IdSaved = pBase->Id; - memcpy( pBase, pData, sizeof(Ivy_Obj_t) ); - pBase->Id = IdSaved; -} -static inline int Ivy_ObjWhatFanin( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanin ) -{ - if ( Ivy_ObjFanin0(pObj) == pFanin ) return 0; - if ( Ivy_ObjFanin1(pObj) == pFanin ) return 1; - assert(0); return -1; -} -static inline int Ivy_ObjFanoutC( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - if ( Ivy_ObjFanin0(pFanout) == pObj ) return Ivy_ObjFaninC0(pObj); - if ( Ivy_ObjFanin1(pFanout) == pObj ) return Ivy_ObjFaninC1(pObj); - assert(0); return -1; -} - -// create the ghost of the new node -static inline Ivy_Obj_t * Ivy_ObjCreateGhost( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type, Ivy_Init_t Init ) -{ - Ivy_Obj_t * pGhost, * pTemp; - assert( Type != IVY_AND || !Ivy_ObjIsConst1(Ivy_Regular(p0)) ); - assert( p1 == NULL || !Ivy_ObjIsConst1(Ivy_Regular(p1)) ); - assert( Type == IVY_PI || Ivy_Regular(p0) != Ivy_Regular(p1) ); - assert( Type != IVY_LATCH || !Ivy_IsComplement(p0) ); -// assert( p1 == NULL || (!Ivy_ObjIsLatch(Ivy_Regular(p0)) || !Ivy_ObjIsLatch(Ivy_Regular(p1))) ); - pGhost = Ivy_ManGhost(p); - pGhost->Type = Type; - pGhost->Init = Init; - pGhost->pFanin0 = p0; - pGhost->pFanin1 = p1; - if ( p1 && Ivy_ObjFaninId0(pGhost) > Ivy_ObjFaninId1(pGhost) ) - pTemp = pGhost->pFanin0, pGhost->pFanin0 = pGhost->pFanin1, pGhost->pFanin1 = pTemp; - return pGhost; -} - -// get the complemented initial state -static Ivy_Init_t Ivy_InitNotCond( Ivy_Init_t Init, int fCompl ) -{ - assert( Init != IVY_INIT_NONE ); - if ( fCompl == 0 ) - return Init; - if ( Init == IVY_INIT_0 ) - return IVY_INIT_1; - if ( Init == IVY_INIT_1 ) - return IVY_INIT_0; - return IVY_INIT_DC; -} - -// get the initial state after forward retiming over AND gate -static Ivy_Init_t Ivy_InitAnd( Ivy_Init_t InitA, Ivy_Init_t InitB ) -{ - assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); - if ( InitA == IVY_INIT_0 || InitB == IVY_INIT_0 ) - return IVY_INIT_0; - if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) - return IVY_INIT_DC; - return IVY_INIT_1; -} - -// get the initial state after forward retiming over EXOR gate -static Ivy_Init_t Ivy_InitExor( Ivy_Init_t InitA, Ivy_Init_t InitB ) -{ - assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); - if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) - return IVY_INIT_DC; - if ( InitA == IVY_INIT_0 && InitB == IVY_INIT_1 ) - return IVY_INIT_1; - if ( InitA == IVY_INIT_1 && InitB == IVY_INIT_0 ) - return IVY_INIT_1; - return IVY_INIT_0; -} - -// internal memory manager -static inline Ivy_Obj_t * Ivy_ManFetchMemory( Ivy_Man_t * p ) -{ - extern void Ivy_ManAddMemory( Ivy_Man_t * p ); - Ivy_Obj_t * pTemp; - if ( p->pListFree == NULL ) - Ivy_ManAddMemory( p ); - pTemp = p->pListFree; - p->pListFree = *((Ivy_Obj_t **)pTemp); - memset( pTemp, 0, sizeof(Ivy_Obj_t) ); - return pTemp; -} -static inline void Ivy_ManRecycleMemory( Ivy_Man_t * p, Ivy_Obj_t * pEntry ) -{ - pEntry->Type = IVY_NONE; // distinquishes dead node from live node - *((Ivy_Obj_t **)pEntry) = p->pListFree; - p->pListFree = pEntry; -} - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator over the primary inputs -#define Ivy_ManForEachPi( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPis, pObj, i ) -// iterator over the primary outputs -#define Ivy_ManForEachPo( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vPos, pObj, i ) -// iterator over all objects, including those currently not used -#define Ivy_ManForEachObj( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else -// iterator over the combinational inputs -#define Ivy_ManForEachCi( p, pObj, i ) \ - Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCi(pObj) ) {} else -// iterator over the combinational outputs -#define Ivy_ManForEachCo( p, pObj, i ) \ - Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCo(pObj) ) {} else -// iterator over logic nodes (AND and EXOR gates) -#define Ivy_ManForEachNode( p, pObj, i ) \ - Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsNode(pObj) ) {} else -// iterator over logic latches -#define Ivy_ManForEachLatch( p, pObj, i ) \ - Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsLatch(pObj) ) {} else -// iterator over the nodes whose IDs are stored in the array -#define Ivy_ManForEachNodeVec( p, vIds, pObj, i ) \ - for ( i = 0; i < Vec_IntSize(vIds) && ((pObj) = Ivy_ManObj(p, Vec_IntEntry(vIds,i))); i++ ) -// iterator over the fanouts of an object -#define Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, i ) \ - for ( i = 0, Ivy_ObjCollectFanouts(p, pObj, vArray); \ - i < Vec_PtrSize(vArray) && ((pFanout) = Vec_PtrEntry(vArray,i)); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== ivyBalance.c ========================================================*/ -extern Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ); -extern Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ); -/*=== ivyCanon.c ========================================================*/ -extern Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); -extern Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); -extern Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); -/*=== ivyCheck.c ========================================================*/ -extern int Ivy_ManCheck( Ivy_Man_t * p ); -extern int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ); -extern int Ivy_ManCheckFanouts( Ivy_Man_t * p ); -extern int Ivy_ManCheckChoices( Ivy_Man_t * p ); -/*=== ivyCut.c ==========================================================*/ -extern void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ); -extern Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); -/*=== ivyDfs.c ==========================================================*/ -extern Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ); -extern Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ); -extern void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ); -extern Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ); -extern Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ); -extern int Ivy_ManIsAcyclic( Ivy_Man_t * p ); -extern int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ); -/*=== ivyDsd.c ==========================================================*/ -extern int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ); -extern void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ); -extern unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ); -extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); -extern Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ); -/*=== ivyFanout.c ==========================================================*/ -extern void Ivy_ManStartFanout( Ivy_Man_t * p ); -extern void Ivy_ManStopFanout( Ivy_Man_t * p ); -extern void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); -extern void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); -extern void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ); -extern void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ); -extern Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -/*=== ivyFastMap.c =============================================================*/ -extern void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ); -extern void Ivy_FastMapStop( Ivy_Man_t * pAig ); -extern void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ); -extern void Ivy_FastMapReverseLevel( Ivy_Man_t * pAig ); -/*=== ivyFraig.c ==========================================================*/ -extern int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ); -extern Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); -extern Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); -extern void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ); -/*=== ivyHaig.c ==========================================================*/ -extern void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ); -extern void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ); -extern void Ivy_ManHaigStop( Ivy_Man_t * p ); -extern void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ); -extern void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ); -extern void Ivy_ManHaigSimulate( Ivy_Man_t * p ); -/*=== ivyMan.c ==========================================================*/ -extern Ivy_Man_t * Ivy_ManStart(); -extern Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ); -extern Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ); -extern Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ); -extern void Ivy_ManStop( Ivy_Man_t * p ); -extern int Ivy_ManCleanup( Ivy_Man_t * p ); -extern int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ); -extern void Ivy_ManPrintStats( Ivy_Man_t * p ); -extern void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ); -/*=== ivyMem.c ==========================================================*/ -extern void Ivy_ManStartMemory( Ivy_Man_t * p ); -extern void Ivy_ManStopMemory( Ivy_Man_t * p ); -/*=== ivyMulti.c ==========================================================*/ -extern Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); -extern Ivy_Obj_t * Ivy_Multi1( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); -extern Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ); -extern Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); -extern int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSol ); -/*=== ivyObj.c ==========================================================*/ -extern Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ); -extern Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ); -extern Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ); -extern void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ); -extern void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ); -extern void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); -extern void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); -extern void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ); -extern void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ); -/*=== ivyOper.c =========================================================*/ -extern Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ); -extern Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); -extern Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); -extern Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); -extern Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ); -extern Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ); -extern Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ); -extern Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); -/*=== ivyResyn.c =========================================================*/ -extern Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); -extern Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); -extern Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ); -/*=== ivyRewrite.c =========================================================*/ -extern int Ivy_ManSeqRewrite( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); -extern int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); -extern int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ); -/*=== ivySeq.c =========================================================*/ -extern int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ); -/*=== ivyShow.c =========================================================*/ -extern void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ); -/*=== ivyTable.c ========================================================*/ -extern Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ); -extern int Ivy_TableCountEntries( Ivy_Man_t * p ); -extern void Ivy_TableProfile( Ivy_Man_t * p ); -/*=== ivyUtil.c =========================================================*/ -extern void Ivy_ManIncrementTravId( Ivy_Man_t * p ); -extern void Ivy_ManCleanTravId( Ivy_Man_t * p ); -extern unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ); -extern void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ); -extern Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ); -extern int Ivy_ManLevels( Ivy_Man_t * p ); -extern void Ivy_ManResetLevels( Ivy_Man_t * p ); -extern int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ); -extern void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ); -extern int Ivy_ObjIsMuxType( Ivy_Obj_t * pObj ); -extern Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pObj, Ivy_Obj_t ** ppObjT, Ivy_Obj_t ** ppObjE ); -extern Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ); -extern void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ); -extern void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ); -extern int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/ivy/ivyBalance.c b/src/aig/ivy/ivyBalance.c deleted file mode 100644 index 5627039a..00000000 --- a/src/aig/ivy/ivyBalance.c +++ /dev/null @@ -1,404 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyBalance.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Algebraic AIG balancing.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); -static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); -static int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); -static void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); -static void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs algebraic balancing of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ) -{ - Ivy_Man_t * pNew; - Ivy_Obj_t * pObj, * pDriver; - Vec_Vec_t * vStore; - int i, NewNodeId; - // clean the old manager - Ivy_ManCleanTravId( p ); - // create the new manager - pNew = Ivy_ManStart(); - // map the nodes - Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) ); - Ivy_ManForEachPi( p, pObj, i ) - pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) ); - // if HAIG is defined, trasfer the pointers to the PIs/latches -// if ( p->pHaig ) -// Ivy_ManHaigTrasfer( p, pNew ); - // balance the AIG - vStore = Vec_VecAlloc( 50 ); - Ivy_ManForEachPo( p, pObj, i ) - { - pDriver = Ivy_ObjReal( Ivy_ObjChild0(pObj) ); - NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel ); - NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) ); - Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) ); - } - Vec_VecFree( vStore ); - if ( i = Ivy_ManCleanup( pNew ) ) - { -// printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); - } - // check the resulting AIG - if ( !Ivy_ManCheck(pNew) ) - printf( "Ivy_ManBalance(): The check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCompareLevelsDecrease( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) -{ - int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level; - if ( Diff > 0 ) - return -1; - if ( Diff < 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns the ID of new node constructed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) -{ - Ivy_Obj_t * pObjNew; - Vec_Ptr_t * vSuper; - int i, NewNodeId; - assert( !Ivy_IsComplement(pObjOld) ); - assert( !Ivy_ObjIsBuf(pObjOld) ); - // return if the result is known - if ( Ivy_ObjIsConst1(pObjOld) ) - return pObjOld->TravId; - if ( pObjOld->TravId ) - return pObjOld->TravId; - assert( Ivy_ObjIsNode(pObjOld) ); - // get the implication supergate - vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level ); - if ( vSuper->nSize == 0 ) - { // it means that the supergate contains two nodes in the opposite polarity - pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) ); - return pObjOld->TravId; - } - if ( vSuper->nSize < 2 ) - printf( "BUG!\n" ); - // for each old node, derive the new well-balanced node - for ( i = 0; i < vSuper->nSize; i++ ) - { - NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); - NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(vSuper->pArray[i]) ); - vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId ); - } - // build the supergate - pObjNew = Ivy_NodeBalanceBuildSuper( pNew, vSuper, Ivy_ObjType(pObjOld), fUpdateLevel ); - vSuper->nSize = 0; - // make sure the balanced node is not assigned - assert( pObjOld->TravId == 0 ); - pObjOld->TravId = Ivy_EdgeFromNode( pObjNew ); -// assert( pObjOld->Level >= Ivy_Regular(pObjNew)->Level ); - return pObjOld->TravId; -} - -/**Function************************************************************* - - Synopsis [Builds implication supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ) -{ - Ivy_Obj_t * pObj1, * pObj2; - int LeftBound; - assert( vSuper->nSize > 1 ); - // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, Ivy_NodeCompareLevelsDecrease ); - // balance the nodes - while ( vSuper->nSize > 1 ) - { - // find the left bound on the node to be paired - LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper ); - // find the node that can be shared (if no such node, randomize choice) - Ivy_NodeBalancePermute( p, vSuper, LeftBound, Type == IVY_EXOR ); - // pull out the last two nodes - pObj1 = Vec_PtrPop(vSuper); - pObj2 = Vec_PtrPop(vSuper); - Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(p, pObj1, pObj2, Type) ); - } - return Vec_PtrEntry(vSuper, 0); -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper ) -{ - int RetValue1, RetValue2, i; - // check if the node is visited - if ( Ivy_Regular(pObj)->fMarkB ) - { - // check if the node occurs in the same polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == pObj ) - return 1; - // check if the node is present in the opposite polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == Ivy_Not(pObj) ) - return -1; - assert( 0 ); - return 0; - } - // if the new node is complemented or a PI, another gate begins - if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1) ) - { - Vec_PtrPush( vSuper, pObj ); - Ivy_Regular(pObj)->fMarkB = 1; - return 0; - } - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjIsNode(pObj) ); - // go through the branches - RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper ); - RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - // return 1 if at least one branch has a duplicate - return RetValue1 || RetValue2; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) -{ - Vec_Ptr_t * vNodes; - int RetValue, i; - assert( !Ivy_IsComplement(pObj) ); - // extend the storage - if ( Vec_VecSize( vStore ) <= Level ) - Vec_VecPush( vStore, Level, 0 ); - // get the temporary array of nodes - vNodes = Vec_VecEntry( vStore, Level ); - Vec_PtrClear( vNodes ); - // collect the nodes in the implication supergate - RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes ); - assert( vNodes->nSize > 1 ); - // unmark the visited nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - Ivy_Regular(pObj)->fMarkB = 0; - // if we found the node and its complement in the same implication supergate, - // return empty set of nodes (meaning that we should use constant-0 node) - if ( RetValue == -1 ) - vNodes->nSize = 0; - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Finds the left bound on the next candidate to be paired.] - - Description [The nodes in the array are in the decreasing order of levels. - The last node in the array has the smallest level. By default it would be paired - with the next node on the left. However, it may be possible to pair it with some - other node on the left, in such a way that the new node is shared. This procedure - finds the index of the left-most node, which can be paired with the last node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) -{ - Ivy_Obj_t * pObjRight, * pObjLeft; - int Current; - // if two or less nodes, pair with the first - if ( Vec_PtrSize(vSuper) < 3 ) - return 0; - // set the pointer to the one before the last - Current = Vec_PtrSize(vSuper) - 2; - pObjRight = Vec_PtrEntry( vSuper, Current ); - // go through the nodes to the left of this one - for ( Current--; Current >= 0; Current-- ) - { - // get the next node on the left - pObjLeft = Vec_PtrEntry( vSuper, Current ); - // if the level of this node is different, quit the loop - if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level ) - break; - } - Current++; - // get the node, for which the equality holds - pObjLeft = Vec_PtrEntry( vSuper, Current ); - assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level ); - return Current; -} - -/**Function************************************************************* - - Synopsis [Moves closer to the end the node that is best for sharing.] - - Description [If there is no node with sharing, randomly chooses one of - the legal nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) -{ - Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; - int RightBound, i; - // get the right bound - RightBound = Vec_PtrSize(vSuper) - 2; - assert( LeftBound <= RightBound ); - if ( LeftBound == RightBound ) - return; - // get the two last nodes - pObj1 = Vec_PtrEntry( vSuper, RightBound + 1 ); - pObj2 = Vec_PtrEntry( vSuper, RightBound ); - if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 ) - return; - // find the first node that can be shared - for ( i = RightBound; i >= LeftBound; i-- ) - { - pObj3 = Vec_PtrEntry( vSuper, i ); - if ( Ivy_Regular(pObj3) == p->pConst1 ) - { - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE ); - if ( Ivy_TableLookup( p, pGhost ) ) - { - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, i, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - return; - } - } -/* - // we did not find the node to share, randomize choice - { - int Choice = rand() % (RightBound - LeftBound + 1); - pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); - if ( pObj3 == pObj2 ) - return; - Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pObj1, * pObj2; - int i; - if ( Vec_PtrPushUnique(vStore, pObj) ) - return; - // find the p of the node - for ( i = vStore->nSize-1; i > 0; i-- ) - { - pObj1 = vStore->pArray[i ]; - pObj2 = vStore->pArray[i-1]; - if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level ) - break; - vStore->pArray[i ] = pObj2; - vStore->pArray[i-1] = pObj1; - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyCanon.c b/src/aig/ivy/ivyCanon.c deleted file mode 100644 index 5768b87e..00000000 --- a/src/aig/ivy/ivyCanon.c +++ /dev/null @@ -1,144 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyCanon.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Finding canonical form of objects.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyCanon.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Ivy_Obj_t * Ivy_TableLookupPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1, int fCompl0, int fCompl1, Ivy_Type_t Type ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the canonical form of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_CanonPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) -{ - Ivy_Obj_t * pResult, * pLat0, * pLat1; - Ivy_Init_t Init, Init0, Init1; - int fCompl0, fCompl1; - Ivy_Type_t Type; - assert( Ivy_ObjIsNode(pGhost) ); - assert( Ivy_ObjIsAnd(pGhost) || (!Ivy_ObjFaninC0(pGhost) && !Ivy_ObjFaninC1(pGhost)) ); - assert( Ivy_ObjFaninId0(pGhost) != 0 && Ivy_ObjFaninId1(pGhost) != 0 ); - // consider the case when the pair is canonical - if ( !Ivy_ObjIsLatch(Ivy_ObjFanin0(pGhost)) || !Ivy_ObjIsLatch(Ivy_ObjFanin1(pGhost)) ) - { - if ( pResult = Ivy_TableLookup( p, pGhost ) ) - return pResult; - return Ivy_ObjCreate( p, pGhost ); - } - /// remember the latches - pLat0 = Ivy_ObjFanin0(pGhost); - pLat1 = Ivy_ObjFanin1(pGhost); - // remember type and compls - Type = Ivy_ObjType(pGhost); - fCompl0 = Ivy_ObjFaninC0(pGhost); - fCompl1 = Ivy_ObjFaninC1(pGhost); - // call recursively - pResult = Ivy_Oper( p, Ivy_NotCond(Ivy_ObjFanin0(pLat0), fCompl0), Ivy_NotCond(Ivy_ObjFanin0(pLat1), fCompl1), Type ); - // build latch on top of this - Init0 = Ivy_InitNotCond( Ivy_ObjInit(pLat0), fCompl0 ); - Init1 = Ivy_InitNotCond( Ivy_ObjInit(pLat1), fCompl1 ); - Init = (Type == IVY_AND)? Ivy_InitAnd(Init0, Init1) : Ivy_InitExor(Init0, Init1); - return Ivy_Latch( p, pResult, Init ); -} - -/**Function************************************************************* - - Synopsis [Creates the canonical form of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) -{ - Ivy_Obj_t * pGhost, * pResult; - pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_AND, IVY_INIT_NONE ); - pResult = Ivy_CanonPair_rec( p, pGhost ); - return pResult; -} - -/**Function************************************************************* - - Synopsis [Creates the canonical form of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) -{ - Ivy_Obj_t * pGhost, * pResult; - int fCompl = Ivy_IsComplement(pObj0) ^ Ivy_IsComplement(pObj1); - pObj0 = Ivy_Regular(pObj0); - pObj1 = Ivy_Regular(pObj1); - pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_EXOR, IVY_INIT_NONE ); - pResult = Ivy_CanonPair_rec( p, pGhost ); - return Ivy_NotCond( pResult, fCompl ); -} - -/**Function************************************************************* - - Synopsis [Creates the canonical form of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) -{ - Ivy_Obj_t * pGhost, * pResult; - int fCompl = Ivy_IsComplement(pObj); - pObj = Ivy_Regular(pObj); - pGhost = Ivy_ObjCreateGhost( p, pObj, NULL, IVY_LATCH, Ivy_InitNotCond(Init, fCompl) ); - pResult = Ivy_TableLookup( p, pGhost ); - if ( pResult == NULL ) - pResult = Ivy_ObjCreate( p, pGhost ); - return Ivy_NotCond( pResult, fCompl ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyCheck.c b/src/aig/ivy/ivyCheck.c deleted file mode 100644 index 55448f19..00000000 --- a/src/aig/ivy/ivyCheck.c +++ /dev/null @@ -1,273 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyCheck.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [AIG checking procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks the consistency of the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCheck( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj, * pObj2; - int i; - Ivy_ManForEachObj( p, pObj, i ) - { - // skip deleted nodes - if ( Ivy_ObjId(pObj) != i ) - { - printf( "Ivy_ManCheck: Node with ID %d is listed as number %d in the array of objects.\n", pObj->Id, i ); - return 0; - } - // consider the constant node and PIs - if ( i == 0 || Ivy_ObjIsPi(pObj) ) - { - if ( Ivy_ObjFaninId0(pObj) || Ivy_ObjFaninId1(pObj) || Ivy_ObjLevel(pObj) ) - { - printf( "Ivy_ManCheck: The AIG has non-standard constant or PI node with ID \"%d\".\n", pObj->Id ); - return 0; - } - continue; - } - if ( Ivy_ObjIsPo(pObj) ) - { - if ( Ivy_ObjFaninId1(pObj) ) - { - printf( "Ivy_ManCheck: The AIG has non-standard PO node with ID \"%d\".\n", pObj->Id ); - return 0; - } - continue; - } - if ( Ivy_ObjIsBuf(pObj) ) - { - if ( Ivy_ObjFanin1(pObj) ) - { - printf( "Ivy_ManCheck: The buffer with ID \"%d\" contains second fanin.\n", pObj->Id ); - return 0; - } - continue; - } - if ( Ivy_ObjIsLatch(pObj) ) - { - if ( Ivy_ObjFanin1(pObj) ) - { - printf( "Ivy_ManCheck: The latch with ID \"%d\" contains second fanin.\n", pObj->Id ); - return 0; - } - if ( Ivy_ObjInit(pObj) == IVY_INIT_NONE ) - { - printf( "Ivy_ManCheck: The latch with ID \"%d\" does not have initial state.\n", pObj->Id ); - return 0; - } - pObj2 = Ivy_TableLookup( p, pObj ); - if ( pObj2 != pObj ) - printf( "Ivy_ManCheck: Latch with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); - continue; - } - // consider the AND node - if ( !Ivy_ObjFanin0(pObj) || !Ivy_ObjFanin1(pObj) ) - { - printf( "Ivy_ManCheck: The AIG has internal node \"%d\" with a NULL fanin.\n", pObj->Id ); - return 0; - } - if ( Ivy_ObjFaninId0(pObj) >= Ivy_ObjFaninId1(pObj) ) - { - printf( "Ivy_ManCheck: The AIG has node \"%d\" with a wrong ordering of fanins.\n", pObj->Id ); - return 0; - } - if ( Ivy_ObjLevel(pObj) != Ivy_ObjLevelNew(pObj) ) - printf( "Ivy_ManCheck: Node with ID \"%d\" has level %d but should have level %d.\n", pObj->Id, Ivy_ObjLevel(pObj), Ivy_ObjLevelNew(pObj) ); - pObj2 = Ivy_TableLookup( p, pObj ); - if ( pObj2 != pObj ) - printf( "Ivy_ManCheck: Node with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); - if ( Ivy_ObjRefs(pObj) == 0 ) - printf( "Ivy_ManCheck: Node with ID \"%d\" has no fanouts.\n", pObj->Id ); - // check fanouts - if ( p->fFanout && Ivy_ObjRefs(pObj) != Ivy_ObjFanoutNum(p, pObj) ) - printf( "Ivy_ManCheck: Node with ID \"%d\" has mismatch between the number of fanouts and refs.\n", pObj->Id ); - } - // count the number of nodes in the table - if ( Ivy_TableCountEntries(p) != Ivy_ManAndNum(p) + Ivy_ManExorNum(p) + Ivy_ManLatchNum(p) ) - { - printf( "Ivy_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); - return 0; - } -// if ( !Ivy_ManCheckFanouts(p) ) -// return 0; - if ( !Ivy_ManIsAcyclic(p) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Verifies the fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i, Counter = 0; - Ivy_ManForEachObj( p, pObj, i ) - if ( Ivy_ObjIsNode(pObj) ) - Counter += (Ivy_ObjRefs(pObj) == 0); - if ( Counter ) - printf( "Sequential AIG has %d dangling nodes.\n", Counter ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Verifies the fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCheckFanouts( Ivy_Man_t * p ) -{ - Vec_Ptr_t * vFanouts; - Ivy_Obj_t * pObj, * pFanout, * pFanin; - int i, k, RetValue = 1; - if ( !p->fFanout ) - return 1; - vFanouts = Vec_PtrAlloc( 100 ); - // make sure every fanin is a fanout - Ivy_ManForEachObj( p, pObj, i ) - { - pFanin = Ivy_ObjFanin0(pObj); - if ( pFanin == NULL ) - continue; - Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) - if ( pFanout == pObj ) - break; - if ( k == Vec_PtrSize(vFanouts) ) - { - printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); - RetValue = 0; - } - - pFanin = Ivy_ObjFanin1(pObj); - if ( pFanin == NULL ) - continue; - Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) - if ( pFanout == pObj ) - break; - if ( k == Vec_PtrSize(vFanouts) ) - { - printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); - RetValue = 0; - } - // check that the previous fanout has the same fanin - if ( pObj->pPrevFan0 ) - { - if ( Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && - Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) && - Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && - Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) ) - { - printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan0->Id ); - RetValue = 0; - } - } - // check that the previous fanout has the same fanin - if ( pObj->pPrevFan1 ) - { - if ( Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && - Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) && - Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && - Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) ) - { - printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan1->Id ); - RetValue = 0; - } - } - } - // make sure every fanout is a fanin - Ivy_ManForEachObj( p, pObj, i ) - { - Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, k ) - if ( Ivy_ObjFanin0(pFanout) != pObj && Ivy_ObjFanin1(pFanout) != pObj ) - { - printf( "Node %d is a fanout of node %d but the fanin is not there.\n", pFanout->Id, pObj->Id ); - RetValue = 0; - } - } - Vec_PtrFree( vFanouts ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Checks that each choice node has exactly one node with fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCheckChoices( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj, * pTemp; - int i; - Ivy_ManForEachObj( p->pHaig, pObj, i ) - { - if ( Ivy_ObjRefs(pObj) == 0 ) - continue; - // count the number of nodes in the loop - assert( !Ivy_IsComplement(pObj->pEquiv) ); - for ( pTemp = pObj->pEquiv; pTemp && pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - if ( Ivy_ObjRefs(pTemp) > 1 ) - printf( "Node %d has member %d in its equiv class with %d fanouts.\n", pObj->Id, pTemp->Id, Ivy_ObjRefs(pTemp) ); - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyCut.c b/src/aig/ivy/ivyCut.c deleted file mode 100644 index e257d8a6..00000000 --- a/src/aig/ivy/ivyCut.c +++ /dev/null @@ -1,989 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyCut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Computes reconvergence driven sequential cut.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyCut.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Ivy_NodeCutHashValue( int NodeId ) { return 1 << (NodeId % 31); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Evaluate the cost of removing the node from the set of leaves.] - - Description [Returns the number of new leaves that will be brought in. - Returns large number if the node cannot be removed from the set of leaves.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_NodeGetLeafCostOne( Ivy_Man_t * p, int Leaf, Vec_Int_t * vInside ) -{ - Ivy_Obj_t * pNode; - int nLatches, FaninLeaf, Cost; - // make sure leaf is not a contant node - assert( Leaf > 0 ); - // get the node - pNode = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); - // cannot expand over the PI node - if ( Ivy_ObjIsPi(pNode) || Ivy_ObjIsConst1(pNode) ) - return 999; - // get the number of latches - nLatches = Ivy_LeafLat(Leaf) + Ivy_ObjIsLatch(pNode); - if ( nLatches > 15 ) - return 999; - // get the first fanin - FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); - Cost = FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); - // quit if this is the one fanin node - if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) - return Cost; - assert( Ivy_ObjIsNode(pNode) ); - // get the second fanin - FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); - Cost += FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); - return Cost; -} - -/**Function************************************************************* - - Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] - - Description [This procedure looks at the current leaves and tries to change - one leaf at a time in such a way that the cut grows as little as possible. - In evaluating the fanins, this procedure looks only at their immediate - predecessors (this is why it is called a one-level construction procedure).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManSeqFindCut_int( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSizeLimit ) -{ - Ivy_Obj_t * pNode; - int CostBest, CostCur, Leaf, LeafBest, Next, nLatches, i; - int LeavesBest[10]; - int Counter; - - // add random selection of the best fanin!!! - - // find the best fanin - CostBest = 99; - LeafBest = -1; - Counter = -1; -//printf( "Evaluating fanins of the cut:\n" ); - Vec_IntForEachEntry( vFront, Leaf, i ) - { - CostCur = Ivy_NodeGetLeafCostOne( p, Leaf, vInside ); -//printf( " Fanin %s has cost %d.\n", Ivy_ObjName(pNode), CostCur ); - if ( CostBest > CostCur ) - { - CostBest = CostCur; - LeafBest = Leaf; - LeavesBest[0] = Leaf; - Counter = 1; - } - else if ( CostBest == CostCur ) - LeavesBest[Counter++] = Leaf; - - if ( CostBest <= 1 ) // can be if ( CostBest <= 1 ) - break; - } - if ( CostBest == 99 ) - return 0; -// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); - - assert( CostBest < 3 ); - if ( Vec_IntSize(vFront) - 1 + CostBest > nSizeLimit ) - return 0; -// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); - - assert( Counter > 0 ); -printf( "%d", Counter ); - - LeafBest = LeavesBest[rand() % Counter]; - - // remove the node from the array - assert( LeafBest >= 0 ); - Vec_IntRemove( vFront, LeafBest ); -//printf( "Removing fanin %s.\n", Ivy_ObjName(pNode) ); - - // get the node and its latches - pNode = Ivy_ManObj( p, Ivy_LeafId(LeafBest) ); - nLatches = Ivy_LeafLat(LeafBest) + Ivy_ObjIsLatch(pNode); - assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ); - - // add the left child to the fanins - Next = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); - if ( Next && Vec_IntFind(vInside, Next) == -1 ) - { -//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); - Vec_IntPush( vFront, Next ); - Vec_IntPush( vInside, Next ); - } - - // quit if this is the one fanin node - if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) - return 1; - assert( Ivy_ObjIsNode(pNode) ); - - // add the right child to the fanins - Next = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); - if ( Next && Vec_IntFind(vInside, Next) == -1 ) - { -//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); - Vec_IntPush( vFront, Next ); - Vec_IntPush( vInside, Next ); - } - assert( Vec_IntSize(vFront) <= nSizeLimit ); - // keep doing this - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes one sequential cut of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ) -{ - assert( !Ivy_IsComplement(pRoot) ); - assert( Ivy_ObjIsNode(pRoot) ); - assert( Ivy_ObjFaninId0(pRoot) ); - assert( Ivy_ObjFaninId1(pRoot) ); - - // start the cut - Vec_IntClear( vFront ); - Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); - Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); - - // start the visited nodes - Vec_IntClear( vInside ); - Vec_IntPush( vInside, Ivy_LeafCreate(pRoot->Id, 0) ); - Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); - Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); - - // compute the cut - while ( Ivy_ManSeqFindCut_int( p, vFront, vInside, nSize ) ); - assert( Vec_IntSize(vFront) <= nSize ); -} - - - - - -/**Function************************************************************* - - Synopsis [Computing Boolean cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindBoolCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume, Ivy_Obj_t * pPivot ) -{ - int RetValue0, RetValue1; - if ( pObj == pPivot ) - { - Vec_PtrPushUnique( vLeaves, pObj ); - Vec_PtrPushUnique( vVolume, pObj ); - return 1; - } - if ( pObj->fMarkA ) - return 0; - -// assert( !Ivy_ObjIsCi(pObj) ); - if ( Ivy_ObjIsCi(pObj) ) - return 0; - - if ( Ivy_ObjIsBuf(pObj) ) - { - RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); - if ( !RetValue0 ) - return 0; - Vec_PtrPushUnique( vVolume, pObj ); - return 1; - } - assert( Ivy_ObjIsNode(pObj) ); - RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); - RetValue1 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin1(pObj), vLeaves, vVolume, pPivot ); - if ( !RetValue0 && !RetValue1 ) - return 0; - // add new leaves - if ( !RetValue0 ) - { - Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin0(pObj) ); - Vec_PtrPushUnique( vVolume, Ivy_ObjFanin0(pObj) ); - } - if ( !RetValue1 ) - { - Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin1(pObj) ); - Vec_PtrPushUnique( vVolume, Ivy_ObjFanin1(pObj) ); - } - Vec_PtrPushUnique( vVolume, pObj ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns the cost of one node (how many new nodes are added.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindBoolCutCost( Ivy_Obj_t * pObj ) -{ - int Cost; - // make sure the node is in the construction zone - assert( pObj->fMarkA == 1 ); - // cannot expand over the PI node - if ( Ivy_ObjIsCi(pObj) ) - return 999; - // always expand over the buffer - if ( Ivy_ObjIsBuf(pObj) ) - return !Ivy_ObjFanin0(pObj)->fMarkA; - // get the cost of the cone - Cost = (!Ivy_ObjFanin0(pObj)->fMarkA) + (!Ivy_ObjFanin1(pObj)->fMarkA); - // return the number of nodes to be added to the leaves if this node is removed - return Cost; -} - -/**Function************************************************************* - - Synopsis [Computing Boolean cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindBoolCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVolume, Vec_Ptr_t * vLeaves ) -{ - Ivy_Obj_t * pObj, * pFaninC, * pFanin0, * pFanin1, * pPivot; - int RetValue, LevelLimit, Lev, k; - assert( !Ivy_IsComplement(pRoot) ); - // clear the frontier and collect the nodes - Vec_PtrClear( vFront ); - Vec_PtrClear( vVolume ); - if ( Ivy_ObjIsMuxType(pRoot) ) - pFaninC = Ivy_ObjRecognizeMux( pRoot, &pFanin0, &pFanin1 ); - else - { - pFaninC = NULL; - pFanin0 = Ivy_ObjFanin0(pRoot); - pFanin1 = Ivy_ObjFanin1(pRoot); - } - // start cone A - pFanin0->fMarkA = 1; - Vec_PtrPush( vFront, pFanin0 ); - Vec_PtrPush( vVolume, pFanin0 ); - // start cone B - pFanin1->fMarkB = 1; - Vec_PtrPush( vFront, pFanin1 ); - Vec_PtrPush( vVolume, pFanin1 ); - // iteratively expand until the common node (pPivot) is found or limit is reached - assert( Ivy_ObjLevel(pRoot) == Ivy_ObjLevelNew(pRoot) ); - pPivot = NULL; - LevelLimit = IVY_MAX( Ivy_ObjLevel(pRoot) - 10, 1 ); - for ( Lev = Ivy_ObjLevel(pRoot) - 1; Lev >= LevelLimit; Lev-- ) - { - while ( 1 ) - { - // find the next node to expand on this level - Vec_PtrForEachEntry( vFront, pObj, k ) - if ( (int)pObj->Level == Lev ) - break; - if ( k == Vec_PtrSize(vFront) ) - break; - assert( (int)pObj->Level <= Lev ); - assert( pObj->fMarkA ^ pObj->fMarkB ); - // remove the old node - Vec_PtrRemove( vFront, pObj ); - - // expand this node - pFanin0 = Ivy_ObjFanin0(pObj); - if ( !pFanin0->fMarkA && !pFanin0->fMarkB ) - { - Vec_PtrPush( vFront, pFanin0 ); - Vec_PtrPush( vVolume, pFanin0 ); - } - // mark the new nodes - if ( pObj->fMarkA ) - pFanin0->fMarkA = 1; - if ( pObj->fMarkB ) - pFanin0->fMarkB = 1; - - if ( Ivy_ObjIsBuf(pObj) ) - { - if ( pFanin0->fMarkA && pFanin0->fMarkB ) - { - pPivot = pFanin0; - break; - } - continue; - } - - // expand this node - pFanin1 = Ivy_ObjFanin1(pObj); - if ( !pFanin1->fMarkA && !pFanin1->fMarkB ) - { - Vec_PtrPush( vFront, pFanin1 ); - Vec_PtrPush( vVolume, pFanin1 ); - } - // mark the new nodes - if ( pObj->fMarkA ) - pFanin1->fMarkA = 1; - if ( pObj->fMarkB ) - pFanin1->fMarkB = 1; - - // consider if it is time to quit - if ( pFanin0->fMarkA && pFanin0->fMarkB ) - { - pPivot = pFanin0; - break; - } - if ( pFanin1->fMarkA && pFanin1->fMarkB ) - { - pPivot = pFanin1; - break; - } - } - if ( pPivot != NULL ) - break; - } - if ( pPivot == NULL ) - return 0; - // if the MUX control is defined, it should not be - if ( pFaninC && !pFaninC->fMarkA && !pFaninC->fMarkB ) - Vec_PtrPush( vFront, pFaninC ); - // clean the markings - Vec_PtrForEachEntry( vVolume, pObj, k ) - pObj->fMarkA = pObj->fMarkB = 0; - - // mark the nodes on the frontier (including the pivot) - Vec_PtrForEachEntry( vFront, pObj, k ) - pObj->fMarkA = 1; - // cut exists, collect all the nodes on the shortest path to the pivot - Vec_PtrClear( vLeaves ); - Vec_PtrClear( vVolume ); - RetValue = Ivy_ManFindBoolCut_rec( p, pRoot, vLeaves, vVolume, pPivot ); - assert( RetValue == 1 ); - // unmark the nodes on the frontier (including the pivot) - Vec_PtrForEachEntry( vFront, pObj, k ) - pObj->fMarkA = 0; - - // mark the nodes in the volume - Vec_PtrForEachEntry( vVolume, pObj, k ) - pObj->fMarkA = 1; - // expand the cut without increasing its size - while ( 1 ) - { - Vec_PtrForEachEntry( vLeaves, pObj, k ) - if ( Ivy_ManFindBoolCutCost(pObj) < 2 ) - break; - if ( k == Vec_PtrSize(vLeaves) ) - break; - // the node can be expanded - // remove the old node - Vec_PtrRemove( vLeaves, pObj ); - // expand this node - pFanin0 = Ivy_ObjFanin0(pObj); - if ( !pFanin0->fMarkA ) - { - pFanin0->fMarkA = 1; - Vec_PtrPush( vVolume, pFanin0 ); - Vec_PtrPush( vLeaves, pFanin0 ); - } - if ( Ivy_ObjIsBuf(pObj) ) - continue; - // expand this node - pFanin1 = Ivy_ObjFanin1(pObj); - if ( !pFanin1->fMarkA ) - { - pFanin1->fMarkA = 1; - Vec_PtrPush( vVolume, pFanin1 ); - Vec_PtrPush( vLeaves, pFanin1 ); - } - } - // unmark the nodes in the volume - Vec_PtrForEachEntry( vVolume, pObj, k ) - pObj->fMarkA = 0; - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManTestCutsBool( Ivy_Man_t * p ) -{ - Vec_Ptr_t * vFront, * vVolume, * vLeaves; - Ivy_Obj_t * pObj;//, * pTemp; - int i, RetValue;//, k; - vFront = Vec_PtrAlloc( 100 ); - vVolume = Vec_PtrAlloc( 100 ); - vLeaves = Vec_PtrAlloc( 100 ); - Ivy_ManForEachObj( p, pObj, i ) - { - if ( !Ivy_ObjIsNode(pObj) ) - continue; - if ( Ivy_ObjIsMuxType(pObj) ) - { - printf( "m" ); - continue; - } - if ( Ivy_ObjIsExor(pObj) ) - printf( "x" ); - RetValue = Ivy_ManFindBoolCut( p, pObj, vFront, vVolume, vLeaves ); - if ( RetValue == 0 ) - printf( "- " ); - else - printf( "%d ", Vec_PtrSize(vLeaves) ); -/* - printf( "( " ); - Vec_PtrForEachEntry( vFront, pTemp, k ) - printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); - printf( ")\n" ); -*/ - } - printf( "\n" ); - Vec_PtrFree( vFront ); - Vec_PtrFree( vVolume ); - Vec_PtrFree( vLeaves ); -} - - - -/**Function************************************************************* - - Synopsis [Find the hash value of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) -{ - int i; -// for ( i = 1; i < pCut->nSize; i++ ) -// assert( pCut->pArray[i-1] < pCut->pArray[i] ); - pCut->uHash = 0; - for ( i = 0; i < pCut->nSize; i++ ) - pCut->uHash |= (1 << (pCut->pArray[i] % 31)); - return pCut->uHash; -} - -/**Function************************************************************* - - Synopsis [Removes one node to the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Ivy_NodeCutShrink( Ivy_Cut_t * pCut, int iOld ) -{ - int i, k; - for ( i = k = 0; i < pCut->nSize; i++ ) - if ( pCut->pArray[i] != iOld ) - pCut->pArray[k++] = pCut->pArray[i]; - assert( k == pCut->nSize - 1 ); - pCut->nSize--; -} - -/**Function************************************************************* - - Synopsis [Adds one node to the cut.] - - Description [Returns 1 if the cuts is still okay.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_NodeCutExtend( Ivy_Cut_t * pCut, int iNew ) -{ - int i; - for ( i = 0; i < pCut->nSize; i++ ) - if ( pCut->pArray[i] == iNew ) - return 1; - // check if there is room - if ( pCut->nSize == pCut->nSizeMax ) - return 0; - // add the new one - for ( i = pCut->nSize - 1; i >= 0; i-- ) - if ( pCut->pArray[i] > iNew ) - pCut->pArray[i+1] = pCut->pArray[i]; - else - { - assert( pCut->pArray[i] < iNew ); - break; - } - pCut->pArray[i+1] = iNew; - pCut->nSize++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_NodeCutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) -{ - int i; - if ( pCut->nSize < pCut->nSizeMax ) - return 1; - for ( i = 0; i < pCut->nSize; i++ ) - if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Derives new cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_NodeCutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) -{ - unsigned uHash = 0; - int i, k; - assert( pCut->nSize > 0 ); - assert( IdNew0 < IdNew1 ); - for ( i = k = 0; i < pCut->nSize; i++ ) - { - if ( pCut->pArray[i] == IdOld ) - continue; - if ( IdNew0 <= pCut->pArray[i] ) - { - if ( IdNew0 < pCut->pArray[i] ) - { - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_NodeCutHashValue( IdNew0 ); - } - IdNew0 = 0x7FFFFFFF; - } - if ( IdNew1 <= pCut->pArray[i] ) - { - if ( IdNew1 < pCut->pArray[i] ) - { - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_NodeCutHashValue( IdNew1 ); - } - IdNew1 = 0x7FFFFFFF; - } - pCutNew->pArray[ k++ ] = pCut->pArray[i]; - uHash |= Ivy_NodeCutHashValue( pCut->pArray[i] ); - } - if ( IdNew0 < 0x7FFFFFFF ) - { - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_NodeCutHashValue( IdNew0 ); - } - if ( IdNew1 < 0x7FFFFFFF ) - { - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_NodeCutHashValue( IdNew1 ); - } - pCutNew->nSize = k; - pCutNew->uHash = uHash; - assert( pCutNew->nSize <= pCut->nSizeMax ); -// for ( i = 1; i < pCutNew->nSize; i++ ) -// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Check if the cut exists.] - - Description [Returns 1 if the cut exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCutFindOrAdd( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) -{ - Ivy_Cut_t * pCut; - int i, k; - assert( pCutNew->uHash ); - // try to find the cut - for ( i = 0; i < pCutStore->nCuts; i++ ) - { - pCut = pCutStore->pCuts + i; - if ( pCut->uHash == pCutNew->uHash && pCut->nSize == pCutNew->nSize ) - { - for ( k = 0; k < pCutNew->nSize; k++ ) - if ( pCut->pArray[k] != pCutNew->pArray[k] ) - break; - if ( k == pCutNew->nSize ) - return 1; - } - } - assert( pCutStore->nCuts < pCutStore->nCutsMax ); - // add the cut - pCut = pCutStore->pCuts + pCutStore->nCuts++; - *pCut = *pCutNew; - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pDom is contained in pCut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) -{ - int i, k; - for ( i = 0; i < pDom->nSize; i++ ) - { - for ( k = 0; k < pCut->nSize; k++ ) - if ( pDom->pArray[i] == pCut->pArray[k] ) - break; - if ( k == pCut->nSize ) // node i in pDom is not contained in pCut - return 0; - } - // every node in pDom is contained in pCut - return 1; -} - -/**Function************************************************************* - - Synopsis [Check if the cut exists.] - - Description [Returns 1 if the cut exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) -{ - Ivy_Cut_t * pCut; - int i, k; - assert( pCutNew->uHash ); - // try to find the cut - for ( i = 0; i < pCutStore->nCuts; i++ ) - { - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - if ( pCut->nSize == pCutNew->nSize ) - { - if ( pCut->uHash == pCutNew->uHash ) - { - for ( k = 0; k < pCutNew->nSize; k++ ) - if ( pCut->pArray[k] != pCutNew->pArray[k] ) - break; - if ( k == pCutNew->nSize ) - return 1; - } - continue; - } - if ( pCut->nSize < pCutNew->nSize ) - { - // skip the non-contained cuts - if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) - continue; - // check containment seriously - if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) - return 1; - continue; - } - // check potential containment of other cut - - // skip the non-contained cuts - if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) - continue; - // check containment seriously - if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) - { - // remove the current cut -// --pCutStore->nCuts; -// for ( k = i; k < pCutStore->nCuts; k++ ) -// pCutStore->pCuts[k] = pCutStore->pCuts[k+1]; -// i--; - pCut->nSize = 0; - } - } - assert( pCutStore->nCuts < pCutStore->nCutsMax ); - // add the cut - pCut = pCutStore->pCuts + pCutStore->nCuts++; - *pCut = *pCutNew; - return 0; -} - -/**Function************************************************************* - - Synopsis [Print the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeCompactCuts( Ivy_Store_t * pCutStore ) -{ - Ivy_Cut_t * pCut; - int i, k; - for ( i = k = 0; i < pCutStore->nCuts; i++ ) - { - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - pCutStore->pCuts[k++] = *pCut; - } - pCutStore->nCuts = k; -} - -/**Function************************************************************* - - Synopsis [Print the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodePrintCut( Ivy_Cut_t * pCut ) -{ - int i; - assert( pCut->nSize > 0 ); - printf( "%d : {", pCut->nSize ); - for ( i = 0; i < pCut->nSize; i++ ) - printf( " %d", pCut->pArray[i] ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodePrintCuts( Ivy_Store_t * pCutStore ) -{ - int i; - printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); - for ( i = 0; i < pCutStore->nCuts; i++ ) - Ivy_NodePrintCut( pCutStore->pCuts + i ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Ivy_Obj_t * Ivy_ObjRealFanin( Ivy_Obj_t * pObj ) -{ - if ( !Ivy_ObjIsBuf(pObj) ) - return pObj; - return Ivy_ObjRealFanin( Ivy_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) -{ - static Ivy_Store_t CutStore, * pCutStore = &CutStore; - Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; - Ivy_Obj_t * pLeaf; - int i, k, iLeaf0, iLeaf1; - - assert( nLeaves <= IVY_CUT_INPUT ); - - // start the structure - pCutStore->nCuts = 0; - pCutStore->nCutsMax = IVY_CUT_LIMIT; - // start the trivial cut - pCutNew->uHash = 0; - pCutNew->nSize = 1; - pCutNew->nSizeMax = nLeaves; - pCutNew->pArray[0] = pObj->Id; - Ivy_NodeCutHash( pCutNew ); - // add the trivial cut - Ivy_NodeCutFindOrAdd( pCutStore, pCutNew ); - assert( pCutStore->nCuts == 1 ); - - // explore the cuts - for ( i = 0; i < pCutStore->nCuts; i++ ) - { - // expand this cut - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - for ( k = 0; k < pCut->nSize; k++ ) - { - pLeaf = Ivy_ManObj( p, pCut->pArray[k] ); - if ( Ivy_ObjIsCi(pLeaf) ) - continue; -/* - *pCutNew = *pCut; - Ivy_NodeCutShrink( pCutNew, pLeaf->Id ); - if ( !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId0(pLeaf) ) ) - continue; - if ( Ivy_ObjIsNode(pLeaf) && !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId1(pLeaf) ) ) - continue; - Ivy_NodeCutHash( pCutNew ); -*/ - iLeaf0 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin0(pLeaf)) ); - iLeaf1 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin1(pLeaf)) ); -// if ( iLeaf0 == iLeaf1 ) // strange situation observed on Jan 18, 2007 -// continue; - if ( !Ivy_NodeCutPrescreen( pCut, iLeaf0, iLeaf1 ) ) - continue; - if ( iLeaf0 > iLeaf1 ) - Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf1, iLeaf0 ); - else - Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ); - Ivy_NodeCutFindOrAddFilter( pCutStore, pCutNew ); - if ( pCutStore->nCuts == IVY_CUT_LIMIT ) - break; - } - if ( pCutStore->nCuts == IVY_CUT_LIMIT ) - break; - } - Ivy_NodeCompactCuts( pCutStore ); -// Ivy_NodePrintCuts( pCutStore ); - return pCutStore; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManTestCutsAll( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; - int clk = clock(); - nNodeTotal = nNodeOver = 0; - nCutsTotal = -Ivy_ManNodeNum(p); - Ivy_ManForEachObj( p, pObj, i ) - { - if ( !Ivy_ObjIsNode(pObj) ) - continue; - nCutsCut = Ivy_NodeFindCutsAll( p, pObj, 5 )->nCuts; - nCutsTotal += nCutsCut; - nNodeOver += (nCutsCut == IVY_CUT_LIMIT); - nNodeTotal++; - } - printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", - nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); - PRT( "Time", clock() - clk ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyCutTrav.c b/src/aig/ivy/ivyCutTrav.c deleted file mode 100644 index ea57c9f5..00000000 --- a/src/aig/ivy/ivyCutTrav.c +++ /dev/null @@ -1,473 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyCutTrav.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyCutTrav.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ); -static void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ); -static void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes cuts for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Store_t * Ivy_NodeFindCutsTravAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves, int nNodeLimit, - Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront, Vec_Int_t * vStore, Vec_Vec_t * vBitCuts ) -{ - static Ivy_Store_t CutStore, * pCutStore = &CutStore; - Vec_Ptr_t * vCuts, * vCuts0, * vCuts1; - unsigned * pBitCut; - Ivy_Obj_t * pLeaf; - Ivy_Cut_t * pCut; - int i, k, nWords, nNodes; - - assert( nLeaves <= IVY_CUT_INPUT ); - - // find the given number of nodes in the TFI - Ivy_NodeComputeVolume( pObj, nNodeLimit - 1, vNodes, vFront ); - nNodes = Vec_PtrSize(vNodes); -// assert( nNodes <= nNodeLimit ); - - // make sure vBitCuts has enough room - Vec_VecExpand( vBitCuts, nNodes-1 ); - Vec_VecClear( vBitCuts ); - - // prepare the memory manager - Vec_IntClear( vStore ); - Vec_IntGrow( vStore, 64000 ); - - // set elementary cuts for the leaves - nWords = Extra_BitWordNum( nNodes ); - Vec_PtrForEachEntry( vFront, pLeaf, i ) - { - assert( Ivy_ObjTravId(pLeaf) < nNodes ); - // get the new bitcut - pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); - // set it as the cut of this leaf - Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); - } - - // compute the cuts for each node - Vec_PtrForEachEntry( vNodes, pLeaf, i ) - { - // skip the leaves - vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pLeaf) ); - if ( Vec_PtrSize(vCuts) > 0 ) - continue; - // add elementary cut - pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); - // set it as the cut of this leaf - Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); - // get the fanin cuts - vCuts0 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin0(pLeaf) ) ); - vCuts1 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin1(pLeaf) ) ); - assert( Vec_PtrSize(vCuts0) > 0 ); - assert( Vec_PtrSize(vCuts1) > 0 ); - // merge the cuts - Ivy_NodeFindCutsMerge( vCuts0, vCuts1, vCuts, nLeaves, nWords, vStore ); - } - - // start the structure - pCutStore->nCuts = 0; - pCutStore->nCutsMax = IVY_CUT_LIMIT; - // collect the cuts of the root node - vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pObj) ); - Vec_PtrForEachEntry( vCuts, pBitCut, i ) - { - pCut = pCutStore->pCuts + pCutStore->nCuts++; - pCut->nSize = 0; - pCut->nSizeMax = nLeaves; - pCut->uHash = 0; - for ( k = 0; k < nNodes; k++ ) - if ( Extra_TruthHasBit(pBitCut, k) ) - pCut->pArray[ pCut->nSize++ ] = Ivy_ObjId( Vec_PtrEntry(vNodes, k) ); - assert( pCut->nSize <= nLeaves ); - if ( pCutStore->nCuts == pCutStore->nCutsMax ) - break; - } - - // clean the travIds - Vec_PtrForEachEntry( vNodes, pLeaf, i ) - pLeaf->TravId = 0; - return pCutStore; -} - -/**Function************************************************************* - - Synopsis [Creates elementary bit-cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ) -{ - unsigned * pBitCut; - pBitCut = Vec_IntFetch( vStore, nWords ); - memset( pBitCut, 0, 4 * nWords ); - Extra_TruthSetBit( pBitCut, NodeId ); - return pBitCut; -} - -/**Function************************************************************* - - Synopsis [Compares the node by level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_CompareNodesByLevel( Ivy_Obj_t ** ppObj1, Ivy_Obj_t ** ppObj2 ) -{ - Ivy_Obj_t * pObj1 = *ppObj1; - Ivy_Obj_t * pObj2 = *ppObj2; - if ( pObj1->Level < pObj2->Level ) - return -1; - if ( pObj1->Level > pObj2->Level ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Mark all nodes up to the given depth.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeComputeVolumeTrav1_rec( Ivy_Obj_t * pObj, int Depth ) -{ - if ( Ivy_ObjIsCi(pObj) || Depth == 0 ) - return; - Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin0(pObj), Depth - 1 ); - Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin1(pObj), Depth - 1 ); - pObj->fMarkA = 1; -} - -/**Function************************************************************* - - Synopsis [Collect the marked nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeComputeVolumeTrav2_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - if ( !pObj->fMarkA ) - return; - Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin0(pObj), vNodes ); - Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin1(pObj), vNodes ); - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pTemp, * pFanin; - int i, nNodes; - // mark nodes up to the given depth - Ivy_NodeComputeVolumeTrav1_rec( pObj, 6 ); - // collect the marked nodes - Vec_PtrClear( vFront ); - Ivy_NodeComputeVolumeTrav2_rec( pObj, vFront ); - // find the fanins that are not marked - Vec_PtrClear( vNodes ); - Vec_PtrForEachEntry( vFront, pTemp, i ) - { - pFanin = Ivy_ObjFanin0(pTemp); - if ( !pFanin->fMarkA ) - { - pFanin->fMarkA = 1; - Vec_PtrPush( vNodes, pFanin ); - } - pFanin = Ivy_ObjFanin1(pTemp); - if ( !pFanin->fMarkA ) - { - pFanin->fMarkA = 1; - Vec_PtrPush( vNodes, pFanin ); - } - } - // remember the number of nodes in the frontier - nNodes = Vec_PtrSize( vNodes ); - // add the remaining nodes - Vec_PtrForEachEntry( vFront, pTemp, i ) - Vec_PtrPush( vNodes, pTemp ); - // unmark the nodes - Vec_PtrForEachEntry( vNodes, pTemp, i ) - { - pTemp->fMarkA = 0; - pTemp->TravId = i; - } - // collect the frontier nodes - Vec_PtrClear( vFront ); - Vec_PtrForEachEntryStop( vNodes, pTemp, i, nNodes ) - Vec_PtrPush( vFront, pTemp ); -// printf( "%d ", Vec_PtrSize(vNodes) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pLeaf, * pPivot, * pFanin; - int LevelMax, i; - assert( Ivy_ObjIsNode(pObj) ); - // clear arrays - Vec_PtrClear( vNodes ); - Vec_PtrClear( vFront ); - // add the root - pObj->fMarkA = 1; - Vec_PtrPush( vNodes, pObj ); - Vec_PtrPush( vFront, pObj ); - // expand node with maximum level - LevelMax = pObj->Level; - do { - // get the node to expand - pPivot = NULL; - Vec_PtrForEachEntryReverse( vFront, pLeaf, i ) - { - if ( (int)pLeaf->Level == LevelMax ) - { - pPivot = pLeaf; - break; - } - } - // decrease level if we did not find the node - if ( pPivot == NULL ) - { - if ( --LevelMax == 0 ) - break; - continue; - } - // the node to expand is found - // remove it from frontier - Vec_PtrRemove( vFront, pPivot ); - // add fanins - pFanin = Ivy_ObjFanin0(pPivot); - if ( !pFanin->fMarkA ) - { - pFanin->fMarkA = 1; - Vec_PtrPush( vNodes, pFanin ); - Vec_PtrPush( vFront, pFanin ); - } - pFanin = Ivy_ObjFanin1(pPivot); - if ( pFanin && !pFanin->fMarkA ) - { - pFanin->fMarkA = 1; - Vec_PtrPush( vNodes, pFanin ); - Vec_PtrPush( vFront, pFanin ); - } - // quit if we collected enough nodes - } while ( Vec_PtrSize(vNodes) < nNodeLimit ); - - // sort nodes by level - Vec_PtrSort( vNodes, Ivy_CompareNodesByLevel ); - // make sure the nodes are ordered in the increasing number of levels - pFanin = Vec_PtrEntry( vNodes, 0 ); - pPivot = Vec_PtrEntryLast( vNodes ); - assert( pFanin->Level <= pPivot->Level ); - - // clean the marks and remember node numbers in the TravId - Vec_PtrForEachEntry( vNodes, pFanin, i ) - { - pFanin->fMarkA = 0; - pFanin->TravId = i; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Extra_TruthOrWords( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nWords ) -{ - int w; - for ( w = nWords-1; w >= 0; w-- ) - pOut[w] = pIn0[w] | pIn1[w]; -} -static inline int Extra_TruthIsImplyWords( unsigned * pIn1, unsigned * pIn2, int nWords ) -{ - int w; - for ( w = nWords-1; w >= 0; w-- ) - if ( pIn1[w] & ~pIn2[w] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Merges two sets of bit-cuts at a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, - int nLeaves, int nWords, Vec_Int_t * vStore ) -{ - unsigned * pBitCut, * pBitCut0, * pBitCut1, * pBitCutTest; - int i, k, c, w, Counter; - // iterate through the cut pairs - Vec_PtrForEachEntry( vCuts0, pBitCut0, i ) - Vec_PtrForEachEntry( vCuts1, pBitCut1, k ) - { - // skip infeasible cuts - Counter = 0; - for ( w = 0; w < nWords; w++ ) - { - Counter += Extra_WordCountOnes( pBitCut0[w] | pBitCut1[w] ); - if ( Counter > nLeaves ) - break; - } - if ( Counter > nLeaves ) - continue; - // the new cut is feasible - create it - pBitCutTest = Vec_IntFetch( vStore, nWords ); - Extra_TruthOrWords( pBitCutTest, pBitCut0, pBitCut1, nWords ); - // filter contained cuts; try to find containing cut - w = 0; - Vec_PtrForEachEntry( vCuts, pBitCut, c ) - { - if ( Extra_TruthIsImplyWords( pBitCut, pBitCutTest, nWords ) ) - break; - if ( Extra_TruthIsImplyWords( pBitCutTest, pBitCut, nWords ) ) - continue; - Vec_PtrWriteEntry( vCuts, w++, pBitCut ); - } - if ( c != Vec_PtrSize(vCuts) ) - continue; - Vec_PtrShrink( vCuts, w ); - // add the cut - Vec_PtrPush( vCuts, pBitCutTest ); - } -} - -/**Function************************************************************* - - Synopsis [Compute the set of all cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManTestCutsTravAll( Ivy_Man_t * p ) -{ - Ivy_Store_t * pStore; - Ivy_Obj_t * pObj; - Vec_Ptr_t * vNodes, * vFront; - Vec_Int_t * vStore; - Vec_Vec_t * vBitCuts; - int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; - int clk = clock(); - - vNodes = Vec_PtrAlloc( 100 ); - vFront = Vec_PtrAlloc( 100 ); - vStore = Vec_IntAlloc( 100 ); - vBitCuts = Vec_VecAlloc( 100 ); - - nNodeTotal = nNodeOver = 0; - nCutsTotal = -Ivy_ManNodeNum(p); - Ivy_ManForEachObj( p, pObj, i ) - { - if ( !Ivy_ObjIsNode(pObj) ) - continue; - pStore = Ivy_NodeFindCutsTravAll( p, pObj, 4, 60, vNodes, vFront, vStore, vBitCuts ); - nCutsCut = pStore->nCuts; - nCutsTotal += nCutsCut; - nNodeOver += (nCutsCut == IVY_CUT_LIMIT); - nNodeTotal++; - } - printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", - nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); - PRT( "Time", clock() - clk ); - - Vec_PtrFree( vNodes ); - Vec_PtrFree( vFront ); - Vec_IntFree( vStore ); - Vec_VecFree( vBitCuts ); - -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyDfs.c b/src/aig/ivy/ivyDfs.c deleted file mode 100644 index c27cba31..00000000 --- a/src/aig/ivy/ivyDfs.c +++ /dev/null @@ -1,493 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyDfs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [DFS collection procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collects nodes in the DFS order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManDfs_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Int_t * vNodes ) -{ - if ( Ivy_ObjIsMarkA(pObj) ) - return; - Ivy_ObjSetMarkA(pObj); - if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) - { - if ( p->pHaig == NULL && pObj->pEquiv ) - Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); - return; - } -//printf( "visiting node %d\n", pObj->Id ); -/* - if ( pObj->Id == 87 || pObj->Id == 90 ) - { - int y = 0; - } -*/ - assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); - Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); - if ( !Ivy_ObjIsBuf(pObj) ) - Ivy_ManDfs_rec( p, Ivy_ObjFanin1(pObj), vNodes ); - if ( p->pHaig == NULL && pObj->pEquiv ) - Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); - Vec_IntPush( vNodes, pObj->Id ); - -//printf( "adding node %d with fanins %d and %d and equiv %d (refs = %d)\n", -// pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id, -// pObj->pEquiv? Ivy_Regular(pObj->pEquiv)->Id: -1, Ivy_ObjRefs(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ) -{ - Vec_Int_t * vNodes; - Ivy_Obj_t * pObj; - int i; - assert( Ivy_ManLatchNum(p) == 0 ); - // make sure the nodes are not marked - Ivy_ManForEachObj( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - // collect the nodes - vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); - Ivy_ManForEachPo( p, pObj, i ) - Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); - // unmark the collected nodes -// Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) -// Ivy_ObjClearMarkA(pObj); - Ivy_ManForEachObj( p, pObj, i ) - Ivy_ObjClearMarkA(pObj); - // make sure network does not have dangling nodes - assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ) -{ - Vec_Int_t * vNodes, * vLatches; - Ivy_Obj_t * pObj; - int i; -// assert( Ivy_ManLatchNum(p) > 0 ); - // make sure the nodes are not marked - Ivy_ManForEachObj( p, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - // collect the latches - vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); - Ivy_ManForEachLatch( p, pObj, i ) - Vec_IntPush( vLatches, pObj->Id ); - // collect the nodes - vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); - Ivy_ManForEachPo( p, pObj, i ) - Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); - // unmark the collected nodes -// Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) -// Ivy_ObjClearMarkA(pObj); - Ivy_ManForEachObj( p, pObj, i ) - Ivy_ObjClearMarkA(pObj); - // make sure network does not have dangling nodes -// assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); - -// temporary!!! - - if ( pvLatches == NULL ) - Vec_IntFree( vLatches ); - else - *pvLatches = vLatches; - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Collects nodes in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCollectCone_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vCone ) -{ - if ( pObj->fMarkA ) - return; - if ( Ivy_ObjIsBuf(pObj) ) - { - Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); - Vec_PtrPush( vCone, pObj ); - return; - } - assert( Ivy_ObjIsNode(pObj) ); - Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); - Ivy_ManCollectCone_rec( Ivy_ObjFanin1(pObj), vCone ); - Vec_PtrPushUnique( vCone, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects nodes in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) -{ - Ivy_Obj_t * pTemp; - int i; - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjIsNode(pObj) ); - // mark the nodes - Vec_PtrForEachEntry( vFront, pTemp, i ) - Ivy_Regular(pTemp)->fMarkA = 1; - assert( pObj->fMarkA == 0 ); - // collect the cone - Vec_PtrClear( vCone ); - Ivy_ManCollectCone_rec( pObj, vCone ); - // unmark the nodes - Vec_PtrForEachEntry( vFront, pTemp, i ) - Ivy_Regular(pTemp)->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Returns the nodes by level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ) -{ - Vec_Vec_t * vNodes; - Ivy_Obj_t * pObj; - int i; - vNodes = Vec_VecAlloc( 100 ); - Ivy_ManForEachObj( p, pObj, i ) - { - assert( !Ivy_ObjIsBuf(pObj) ); - if ( Ivy_ObjIsNode(pObj) ) - Vec_VecPush( vNodes, pObj->Level, pObj ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes required levels for each node.] - - Description [Assumes topological ordering of the nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - Vec_Int_t * vLevelsR; - Vec_Vec_t * vNodes; - int i, k, Level, LevelMax; - assert( p->vRequired == NULL ); - // start the required times - vLevelsR = Vec_IntStart( Ivy_ManObjIdMax(p) + 1 ); - // iterate through the nodes in the reverse order - vNodes = Ivy_ManLevelize( p ); - Vec_VecForEachEntryReverseReverse( vNodes, pObj, i, k ) - { - Level = Vec_IntEntry( vLevelsR, pObj->Id ) + 1 + Ivy_ObjIsExor(pObj); - if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId0(pObj) ) < Level ) - Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId0(pObj), Level ); - if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId1(pObj) ) < Level ) - Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId1(pObj), Level ); - } - Vec_VecFree( vNodes ); - // convert it into the required times - LevelMax = Ivy_ManLevels( p ); -//printf( "max %5d\n",LevelMax ); - Ivy_ManForEachObj( p, pObj, i ) - { - Level = Vec_IntEntry( vLevelsR, pObj->Id ); - Vec_IntWriteEntry( vLevelsR, pObj->Id, LevelMax - Level ); -//printf( "%5d : %5d %5d\n", pObj->Id, Level, LevelMax - Level ); - } - p->vRequired = vLevelsR; - return vLevelsR; -} - -/**Function************************************************************* - - Synopsis [Recursively detects combinational loops.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManIsAcyclic_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - // skip the node if it is already visited - if ( Ivy_ObjIsTravIdPrevious(p, pObj) ) - return 1; - // check if the node is part of the combinational loop - if ( Ivy_ObjIsTravIdCurrent(p, pObj) ) - { - fprintf( stdout, "Manager contains combinational loop!\n" ); - fprintf( stdout, "Node \"%d\" is encountered twice on the following path:\n", Ivy_ObjId(pObj) ); - fprintf( stdout, " %d", Ivy_ObjId(pObj) ); - return 0; - } - // mark this node as a node on the current path - Ivy_ObjSetTravIdCurrent( p, pObj ); - // explore equivalent nodes if pObj is the main node - if ( p->pHaig == NULL && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) - { - Ivy_Obj_t * pTemp; - assert( !Ivy_IsComplement(pObj->pEquiv) ); - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - { - // traverse the fanin's cone searching for the loop - if ( !Ivy_ManIsAcyclic_rec(p, pTemp) ) - { - // return as soon as the loop is detected - fprintf( stdout, " -> (%d", Ivy_ObjId(pObj) ); - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - fprintf( stdout, " %d", Ivy_ObjId(pTemp) ); - fprintf( stdout, ")" ); - return 0; - } - } - } - // quite if it is a CI node - if ( Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) - { - // mark this node as a visited node - Ivy_ObjSetTravIdPrevious( p, pObj ); - return 1; - } - assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); - // traverse the fanin's cone searching for the loop - if ( !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) ) - { - // return as soon as the loop is detected - fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); - return 0; - } - // traverse the fanin's cone searching for the loop - if ( Ivy_ObjIsNode(pObj) && !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin1(pObj)) ) - { - // return as soon as the loop is detected - fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); - return 0; - } - // mark this node as a visited node - Ivy_ObjSetTravIdPrevious( p, pObj ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Detects combinational loops.] - - Description [This procedure is based on the idea suggested by Donald Chai. - As we traverse the network and visit the nodes, we need to distinquish - three types of nodes: (1) those that are visited for the first time, - (2) those that have been visited in this traversal but are currently not - on the traversal path, (3) those that have been visited and are currently - on the travesal path. When the node of type (3) is encountered, it means - that there is a combinational loop. To mark the three types of nodes, - two new values of the traversal IDs are used.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManIsAcyclic( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int fAcyclic, i; - // set the traversal ID for this DFS ordering - Ivy_ManIncrementTravId( p ); - Ivy_ManIncrementTravId( p ); - // pObj->TravId == pNet->nTravIds means "pObj is on the path" - // pObj->TravId == pNet->nTravIds - 1 means "pObj is visited but is not on the path" - // pObj->TravId < pNet->nTravIds - 1 means "pObj is not visited" - // traverse the network to detect cycles - fAcyclic = 1; - Ivy_ManForEachCo( p, pObj, i ) - { - // traverse the output logic cone - if ( fAcyclic = Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) ) - continue; - // stop as soon as the first loop is detected - fprintf( stdout, " (cone of %s \"%d\")\n", Ivy_ObjIsLatch(pObj)? "latch" : "PO", Ivy_ObjId(pObj) ); - break; - } - return fAcyclic; -} - -/**Function************************************************************* - - Synopsis [Sets the levels of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManSetLevels_rec( Ivy_Obj_t * pObj, int fHaig ) -{ - // quit if the node is visited - if ( Ivy_ObjIsMarkA(pObj) ) - return pObj->Level; - Ivy_ObjSetMarkA(pObj); - // quit if this is a CI - if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) - return 0; - assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); - // get levels of the fanins - Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); - if ( !Ivy_ObjIsBuf(pObj) ) - Ivy_ManSetLevels_rec( Ivy_ObjFanin1(pObj), fHaig ); - // get level of the node - if ( Ivy_ObjIsBuf(pObj) ) - pObj->Level = 1 + Ivy_ObjFanin0(pObj)->Level; - else if ( Ivy_ObjIsNode(pObj) ) - pObj->Level = Ivy_ObjLevelNew( pObj ); - else assert( 0 ); - // get level of other choices - if ( fHaig && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) - { - Ivy_Obj_t * pTemp; - unsigned LevelMax = pObj->Level; - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - { - Ivy_ManSetLevels_rec( pTemp, fHaig ); - LevelMax = IVY_MAX( LevelMax, pTemp->Level ); - } - // get this level - pObj->Level = LevelMax; - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - pTemp->Level = LevelMax; - } - return pObj->Level; -} - -/**Function************************************************************* - - Synopsis [Sets the levels of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ) -{ - Ivy_Obj_t * pObj; - int i, LevelMax; - // check if CIs have choices - if ( fHaig ) - { - Ivy_ManForEachCi( p, pObj, i ) - if ( pObj->pEquiv ) - printf( "CI %d has a choice, which will not be visualized.\n", pObj->Id ); - } - // clean the levels - Ivy_ManForEachObj( p, pObj, i ) - pObj->Level = 0; - // compute the levels - LevelMax = 0; - Ivy_ManForEachCo( p, pObj, i ) - { - Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); - LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); - } - // compute levels of nodes without fanout - Ivy_ManForEachObj( p, pObj, i ) - if ( (Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj)) && Ivy_ObjRefs(pObj) == 0 ) - { - Ivy_ManSetLevels_rec( pObj, fHaig ); - LevelMax = IVY_MAX( LevelMax, (int)pObj->Level ); - } - // clean the marks - Ivy_ManForEachObj( p, pObj, i ) - Ivy_ObjClearMarkA(pObj); - return LevelMax; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyDsd.c b/src/aig/ivy/ivyDsd.c deleted file mode 100644 index 3b8a2e68..00000000 --- a/src/aig/ivy/ivyDsd.c +++ /dev/null @@ -1,819 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyDsd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Disjoint-support decomposition.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyDsd.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// decomposition types -typedef enum { - IVY_DEC_PI, // 0: var - IVY_DEC_CONST1, // 1: CONST1 - IVY_DEC_BUF, // 2: BUF - IVY_DEC_AND, // 3: AND - IVY_DEC_EXOR, // 4: EXOR - IVY_DEC_MUX, // 5: MUX - IVY_DEC_MAJ, // 6: MAJ - IVY_DEC_PRIME // 7: undecomposable -} Ivy_DecType_t; - -typedef struct Ivy_Dec_t_ Ivy_Dec_t; -struct Ivy_Dec_t_ -{ - unsigned Type : 4; // the node type (PI, CONST1, AND, EXOR, MUX, PRIME) - unsigned fCompl : 1; // shows if node is complemented (root node only) - unsigned nFans : 3; // the number of fanins - unsigned Fan0 : 4; // fanin 0 - unsigned Fan1 : 4; // fanin 1 - unsigned Fan2 : 4; // fanin 2 - unsigned Fan3 : 4; // fanin 3 - unsigned Fan4 : 4; // fanin 4 - unsigned Fan5 : 4; // fanin 5 -}; - -static inline int Ivy_DecToInt( Ivy_Dec_t Node ) { return *((int *)&Node); } -static inline Ivy_Dec_t Ivy_IntToDec( int Node ) { return *((Ivy_Dec_t *)&Node); } -static inline void Ivy_DecClear( Ivy_Dec_t * pNode ) { *((int *)pNode) = 0; } - - -static unsigned s_Masks[6][2] = { - { 0x55555555, 0xAAAAAAAA }, - { 0x33333333, 0xCCCCCCCC }, - { 0x0F0F0F0F, 0xF0F0F0F0 }, - { 0x00FF00FF, 0xFF00FF00 }, - { 0x0000FFFF, 0xFFFF0000 }, - { 0x00000000, 0xFFFFFFFF } -}; - -static inline int Ivy_TruthWordCountOnes( unsigned uWord ) -{ - uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); - uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); - uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); - uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); - return (uWord & 0x0000FFFF) + (uWord>>16); -} - -static inline int Ivy_TruthCofactorIsConst( unsigned uTruth, int Var, int Cof, int Const ) -{ - if ( Const == 0 ) - return (uTruth & s_Masks[Var][Cof]) == 0; - else - return (uTruth & s_Masks[Var][Cof]) == s_Masks[Var][Cof]; -} - -static inline int Ivy_TruthCofactorIsOne( unsigned uTruth, int Var ) -{ - return (uTruth & s_Masks[Var][0]) == 0; -} - -static inline unsigned Ivy_TruthCofactor( unsigned uTruth, int Var ) -{ - unsigned uCofactor = uTruth & s_Masks[Var >> 1][(Var & 1) == 0]; - int Shift = (1 << (Var >> 1)); - if ( Var & 1 ) - return uCofactor | (uCofactor << Shift); - return uCofactor | (uCofactor >> Shift); -} - -static inline unsigned Ivy_TruthCofactor2( unsigned uTruth, int Var0, int Var1 ) -{ - return Ivy_TruthCofactor( Ivy_TruthCofactor(uTruth, Var0), Var1 ); -} - -// returns 1 if the truth table depends on this var (var is regular interger var) -static inline int Ivy_TruthDepends( unsigned uTruth, int Var ) -{ - return Ivy_TruthCofactor(uTruth, Var << 1) != Ivy_TruthCofactor(uTruth, (Var << 1) | 1); -} - -static inline void Ivy_DecSetVar( Ivy_Dec_t * pNode, int iNum, unsigned Var ) -{ - assert( iNum >= 0 && iNum <= 5 ); - switch( iNum ) - { - case 0: pNode->Fan0 = Var; break; - case 1: pNode->Fan1 = Var; break; - case 2: pNode->Fan2 = Var; break; - case 3: pNode->Fan3 = Var; break; - case 4: pNode->Fan4 = Var; break; - case 5: pNode->Fan5 = Var; break; - } -} - -static inline unsigned Ivy_DecGetVar( Ivy_Dec_t * pNode, int iNum ) -{ - assert( iNum >= 0 && iNum <= 5 ); - switch( iNum ) - { - case 0: return pNode->Fan0; - case 1: return pNode->Fan1; - case 2: return pNode->Fan2; - case 3: return pNode->Fan3; - case 4: return pNode->Fan4; - case 5: return pNode->Fan5; - } - return ~0; -} - -static int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ); -static int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ); - -//int nTruthDsd; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes DSD of truth table of 5 variables or less.] - - Description [Returns 1 if the function is a constant or is fully - DSD decomposable using AND/EXOR/MUX gates.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ) -{ - Ivy_Dec_t Node; - int i, RetValue; - // set the PI variables - Vec_IntClear( vTree ); - for ( i = 0; i < 5; i++ ) - Vec_IntPush( vTree, 0 ); - // check if it is a constant - if ( uTruth == 0 || ~uTruth == 0 ) - { - Ivy_DecClear( &Node ); - Node.Type = IVY_DEC_CONST1; - Node.fCompl = (uTruth == 0); - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - return 1; - } - // perform the decomposition - RetValue = Ivy_TruthDecompose_rec( uTruth, vTree ); - if ( RetValue == -1 ) - return 0; - // get the topmost node - if ( (RetValue >> 1) < 5 ) - { // add buffer - Ivy_DecClear( &Node ); - Node.Type = IVY_DEC_BUF; - Node.fCompl = (RetValue & 1); - Node.Fan0 = ((RetValue >> 1) << 1); - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - } - else if ( RetValue & 1 ) - { // check if the topmost node has to be complemented - Node = Ivy_IntToDec( Vec_IntPop(vTree) ); - assert( Node.fCompl == 0 ); - Node.fCompl = (RetValue & 1); - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - } - if ( uTruth != Ivy_TruthDsdCompute(vTree) ) - printf( "Verification failed.\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes DSD of truth table.] - - Description [Returns the number of topmost decomposition node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ) -{ - Ivy_Dec_t Node; - int Supp[5], Vars0[5], Vars1[5], Vars2[5], * pVars; - int nSupp, Count0, Count1, Count2, nVars, RetValue, fCompl, i; - unsigned uTruthCof, uCof0, uCof1; - - // get constant confactors - Count0 = Count1 = Count2 = nSupp = 0; - for ( i = 0; i < 5; i++ ) - { - if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 0) ) - Vars0[Count0++] = (i << 1) | 0; - else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 0) ) - Vars0[Count0++] = (i << 1) | 1; - else if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 1) ) - Vars1[Count1++] = (i << 1) | 0; - else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 1) ) - Vars1[Count1++] = (i << 1) | 1; - else - { - uCof0 = Ivy_TruthCofactor( uTruth, (i << 1) | 1 ); - uCof1 = Ivy_TruthCofactor( uTruth, (i << 1) | 0 ); - if ( uCof0 == ~uCof1 ) - Vars2[Count2++] = (i << 1) | 0; - else if ( uCof0 != uCof1 ) - Supp[nSupp++] = i; - } - } - assert( Count0 == 0 || Count1 == 0 ); - assert( Count0 == 0 || Count2 == 0 ); - assert( Count1 == 0 || Count2 == 0 ); - - // consider the case of a single variable - if ( Count0 == 1 && nSupp == 0 ) - return Vars0[0]; - - // consider more complex decompositions - if ( Count0 == 0 && Count1 == 0 && Count2 == 0 ) - return Ivy_TruthRecognizeMuxMaj( uTruth, Supp, nSupp, vTree ); - - // extract the nodes - Ivy_DecClear( &Node ); - if ( Count0 > 0 ) - nVars = Count0, pVars = Vars0, Node.Type = IVY_DEC_AND, fCompl = 0; - else if ( Count1 > 0 ) - nVars = Count1, pVars = Vars1, Node.Type = IVY_DEC_AND, fCompl = 1, uTruth = ~uTruth; - else if ( Count2 > 0 ) - nVars = Count2, pVars = Vars2, Node.Type = IVY_DEC_EXOR, fCompl = 0; - else - assert( 0 ); - Node.nFans = nVars+(nSupp>0); - - // compute cofactor - uTruthCof = uTruth; - for ( i = 0; i < nVars; i++ ) - { - uTruthCof = Ivy_TruthCofactor( uTruthCof, pVars[i] ); - Ivy_DecSetVar( &Node, i, pVars[i] ); - } - - if ( Node.Type == IVY_DEC_EXOR ) - fCompl ^= ((Node.nFans & 1) == 0); - - if ( nSupp > 0 ) - { - assert( uTruthCof != 0 && ~uTruthCof != 0 ); - // call recursively - RetValue = Ivy_TruthDecompose_rec( uTruthCof, vTree ); - // quit if non-decomposable - if ( RetValue == -1 ) - return -1; - // remove the complement from the child if the node is EXOR - if ( Node.Type == IVY_DEC_EXOR && (RetValue & 1) ) - { - fCompl ^= 1; - RetValue ^= 1; - } - // set the new decomposition - Ivy_DecSetVar( &Node, nVars, RetValue ); - } - else if ( Node.Type == IVY_DEC_EXOR ) - fCompl ^= (uTruthCof == 0); - - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - return ((Vec_IntSize(vTree)-1) << 1) | fCompl; -} - -/**Function************************************************************* - - Synopsis [Returns a non-negative number if the truth table is a MUX.] - - Description [If the truth table is a MUX, returns the variable as follows: - first, control variable; second, positive cofactor; third, negative cofactor.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ) -{ - Ivy_Dec_t Node; - int i, k, RetValue0, RetValue1; - unsigned uCof0, uCof1, Num; - char Count[3]; - assert( nSupp >= 3 ); - // start the node - Ivy_DecClear( &Node ); - Node.Type = IVY_DEC_MUX; - Node.nFans = 3; - // try each of the variables - for ( i = 0; i < nSupp; i++ ) - { - // get the cofactors with respect to these variables - uCof0 = Ivy_TruthCofactor( uTruth, (pSupp[i] << 1) | 1 ); - uCof1 = Ivy_TruthCofactor( uTruth, pSupp[i] << 1 ); - // go through all other variables and make sure - // each of them belongs to the support of one cofactor - for ( k = 0; k < nSupp; k++ ) - { - if ( k == i ) - continue; - if ( Ivy_TruthDepends(uCof0, pSupp[k]) && Ivy_TruthDepends(uCof1, pSupp[k]) ) - break; - } - if ( k < nSupp ) - continue; - // MUX decomposition exists - RetValue0 = Ivy_TruthDecompose_rec( uCof0, vTree ); - if ( RetValue0 == -1 ) - break; - RetValue1 = Ivy_TruthDecompose_rec( uCof1, vTree ); - if ( RetValue1 == -1 ) - break; - // both of them exist; create the node - Ivy_DecSetVar( &Node, 0, pSupp[i] << 1 ); - Ivy_DecSetVar( &Node, 1, RetValue1 ); - Ivy_DecSetVar( &Node, 2, RetValue0 ); - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - return ((Vec_IntSize(vTree)-1) << 1) | 0; - } - // check majority gate - if ( nSupp > 3 ) - return -1; - if ( Ivy_TruthWordCountOnes(uTruth) != 16 ) - return -1; - // this is a majority gate; determine polarity - Node.Type = IVY_DEC_MAJ; - Count[0] = Count[1] = Count[2] = 0; - for ( i = 0; i < 8; i++ ) - { - Num = 0; - for ( k = 0; k < 3; k++ ) - if ( i & (1 << k) ) - Num |= (1 << pSupp[k]); - assert( Num < 32 ); - if ( (uTruth & (1 << Num)) == 0 ) - continue; - for ( k = 0; k < 3; k++ ) - if ( i & (1 << k) ) - Count[k]++; - } - assert( Count[0] == 1 || Count[0] == 3 ); - assert( Count[1] == 1 || Count[1] == 3 ); - assert( Count[2] == 1 || Count[2] == 3 ); - Ivy_DecSetVar( &Node, 0, (pSupp[0] << 1)|(Count[0] == 1) ); - Ivy_DecSetVar( &Node, 1, (pSupp[1] << 1)|(Count[1] == 1) ); - Ivy_DecSetVar( &Node, 2, (pSupp[2] << 1)|(Count[2] == 1) ); - Vec_IntPush( vTree, Ivy_DecToInt(Node) ); - return ((Vec_IntSize(vTree)-1) << 1) | 0; -} - - -/**Function************************************************************* - - Synopsis [Computes truth table of decomposition tree for verification.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_TruthDsdCompute_rec( int iNode, Vec_Int_t * vTree ) -{ - unsigned uTruthChild, uTruthTotal; - int Var, i; - // get the node - Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); - // compute the node function - if ( Node.Type == IVY_DEC_CONST1 ) - return s_Masks[5][ !Node.fCompl ]; - if ( Node.Type == IVY_DEC_PI ) - return s_Masks[iNode][ !Node.fCompl ]; - if ( Node.Type == IVY_DEC_BUF ) - { - uTruthTotal = Ivy_TruthDsdCompute_rec( Node.Fan0 >> 1, vTree ); - return Node.fCompl? ~uTruthTotal : uTruthTotal; - } - if ( Node.Type == IVY_DEC_AND ) - { - uTruthTotal = s_Masks[5][1]; - for ( i = 0; i < (int)Node.nFans; i++ ) - { - Var = Ivy_DecGetVar( &Node, i ); - uTruthChild = Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); - uTruthTotal = (Var & 1)? uTruthTotal & ~uTruthChild : uTruthTotal & uTruthChild; - } - return Node.fCompl? ~uTruthTotal : uTruthTotal; - } - if ( Node.Type == IVY_DEC_EXOR ) - { - uTruthTotal = 0; - for ( i = 0; i < (int)Node.nFans; i++ ) - { - Var = Ivy_DecGetVar( &Node, i ); - uTruthTotal ^= Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); - assert( (Var & 1) == 0 ); - } - return Node.fCompl? ~uTruthTotal : uTruthTotal; - } - assert( Node.fCompl == 0 ); - if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) - { - unsigned uTruthChildC, uTruthChild1, uTruthChild0; - int VarC, Var1, Var0; - VarC = Ivy_DecGetVar( &Node, 0 ); - Var1 = Ivy_DecGetVar( &Node, 1 ); - Var0 = Ivy_DecGetVar( &Node, 2 ); - uTruthChildC = Ivy_TruthDsdCompute_rec( VarC >> 1, vTree ); - uTruthChild1 = Ivy_TruthDsdCompute_rec( Var1 >> 1, vTree ); - uTruthChild0 = Ivy_TruthDsdCompute_rec( Var0 >> 1, vTree ); - assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); - uTruthChildC = (VarC & 1)? ~uTruthChildC : uTruthChildC; - uTruthChild1 = (Var1 & 1)? ~uTruthChild1 : uTruthChild1; - uTruthChild0 = (Var0 & 1)? ~uTruthChild0 : uTruthChild0; - if ( Node.Type == IVY_DEC_MUX ) - return (uTruthChildC & uTruthChild1) | (~uTruthChildC & uTruthChild0); - else - return (uTruthChildC & uTruthChild1) | (uTruthChildC & uTruthChild0) | (uTruthChild1 & uTruthChild0); - } - assert( 0 ); - return 0; -} - - -/**Function************************************************************* - - Synopsis [Computes truth table of decomposition tree for verification.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ) -{ - return Ivy_TruthDsdCompute_rec( Vec_IntSize(vTree)-1, vTree ); -} - -/**Function************************************************************* - - Synopsis [Prints the decomposition tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthDsdPrint_rec( FILE * pFile, int iNode, Vec_Int_t * vTree ) -{ - int Var, i; - // get the node - Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); - // compute the node function - if ( Node.Type == IVY_DEC_CONST1 ) - fprintf( pFile, "Const1%s", (Node.fCompl? "\'" : "") ); - else if ( Node.Type == IVY_DEC_PI ) - fprintf( pFile, "%c%s", 'a' + iNode, (Node.fCompl? "\'" : "") ); - else if ( Node.Type == IVY_DEC_BUF ) - { - Ivy_TruthDsdPrint_rec( pFile, Node.Fan0 >> 1, vTree ); - fprintf( pFile, "%s", (Node.fCompl? "\'" : "") ); - } - else if ( Node.Type == IVY_DEC_AND ) - { - fprintf( pFile, "AND(" ); - for ( i = 0; i < (int)Node.nFans; i++ ) - { - Var = Ivy_DecGetVar( &Node, i ); - Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); - fprintf( pFile, "%s", (Var & 1)? "\'" : "" ); - if ( i != (int)Node.nFans-1 ) - fprintf( pFile, "," ); - } - fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); - } - else if ( Node.Type == IVY_DEC_EXOR ) - { - fprintf( pFile, "EXOR(" ); - for ( i = 0; i < (int)Node.nFans; i++ ) - { - Var = Ivy_DecGetVar( &Node, i ); - Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); - if ( i != (int)Node.nFans-1 ) - fprintf( pFile, "," ); - assert( (Var & 1) == 0 ); - } - fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); - } - else if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) - { - int VarC, Var1, Var0; - assert( Node.fCompl == 0 ); - VarC = Ivy_DecGetVar( &Node, 0 ); - Var1 = Ivy_DecGetVar( &Node, 1 ); - Var0 = Ivy_DecGetVar( &Node, 2 ); - fprintf( pFile, "%s", (Node.Type == IVY_DEC_MUX)? "MUX(" : "MAJ(" ); - Ivy_TruthDsdPrint_rec( pFile, VarC >> 1, vTree ); - fprintf( pFile, "%s", (VarC & 1)? "\'" : "" ); - fprintf( pFile, "," ); - Ivy_TruthDsdPrint_rec( pFile, Var1 >> 1, vTree ); - fprintf( pFile, "%s", (Var1 & 1)? "\'" : "" ); - fprintf( pFile, "," ); - Ivy_TruthDsdPrint_rec( pFile, Var0 >> 1, vTree ); - fprintf( pFile, "%s", (Var0 & 1)? "\'" : "" ); - fprintf( pFile, ")" ); - } - else assert( 0 ); -} - - -/**Function************************************************************* - - Synopsis [Prints the decomposition tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ) -{ - fprintf( pFile, "F = " ); - Ivy_TruthDsdPrint_rec( pFile, Vec_IntSize(vTree)-1, vTree ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Implement DSD in the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ManDsdConstruct_rec( Ivy_Man_t * p, Vec_Int_t * vFront, int iNode, Vec_Int_t * vTree ) -{ - Ivy_Obj_t * pResult, * pChild, * pNodes[16]; - int Var, i; - // get the node - Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); - // compute the node function - if ( Node.Type == IVY_DEC_CONST1 ) - return Ivy_NotCond( Ivy_ManConst1(p), Node.fCompl ); - if ( Node.Type == IVY_DEC_PI ) - { - pResult = Ivy_ManObj( p, Vec_IntEntry(vFront, iNode) ); - return Ivy_NotCond( pResult, Node.fCompl ); - } - if ( Node.Type == IVY_DEC_BUF ) - { - pResult = Ivy_ManDsdConstruct_rec( p, vFront, Node.Fan0 >> 1, vTree ); - return Ivy_NotCond( pResult, Node.fCompl ); - } - if ( Node.Type == IVY_DEC_AND || Node.Type == IVY_DEC_EXOR ) - { - for ( i = 0; i < (int)Node.nFans; i++ ) - { - Var = Ivy_DecGetVar( &Node, i ); - assert( Node.Type == IVY_DEC_AND || (Var & 1) == 0 ); - pChild = Ivy_ManDsdConstruct_rec( p, vFront, Var >> 1, vTree ); - pChild = Ivy_NotCond( pChild, (Var & 1) ); - pNodes[i] = pChild; - } - -// Ivy_MultiEval( pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); - - pResult = Ivy_Multi( p, pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); - return Ivy_NotCond( pResult, Node.fCompl ); - } - assert( Node.fCompl == 0 ); - if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) - { - int VarC, Var1, Var0; - VarC = Ivy_DecGetVar( &Node, 0 ); - Var1 = Ivy_DecGetVar( &Node, 1 ); - Var0 = Ivy_DecGetVar( &Node, 2 ); - pNodes[0] = Ivy_ManDsdConstruct_rec( p, vFront, VarC >> 1, vTree ); - pNodes[1] = Ivy_ManDsdConstruct_rec( p, vFront, Var1 >> 1, vTree ); - pNodes[2] = Ivy_ManDsdConstruct_rec( p, vFront, Var0 >> 1, vTree ); - assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); - pNodes[0] = Ivy_NotCond( pNodes[0], (VarC & 1) ); - pNodes[1] = Ivy_NotCond( pNodes[1], (Var1 & 1) ); - pNodes[2] = Ivy_NotCond( pNodes[2], (Var0 & 1) ); - if ( Node.Type == IVY_DEC_MUX ) - return Ivy_Mux( p, pNodes[0], pNodes[1], pNodes[2] ); - else - return Ivy_Maj( p, pNodes[0], pNodes[1], pNodes[2] ); - } - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Implement DSD in the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ) -{ - int Entry, i; - // implement latches on the frontier (TEMPORARY!!!) - Vec_IntForEachEntry( vFront, Entry, i ) - Vec_IntWriteEntry( vFront, i, Ivy_LeafId(Entry) ); - // recursively construct the tree - return Ivy_ManDsdConstruct_rec( p, vFront, Vec_IntSize(vTree)-1, vTree ); -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthDsdComputePrint( unsigned uTruth ) -{ - static Vec_Int_t * vTree = NULL; - if ( vTree == NULL ) - vTree = Vec_IntAlloc( 12 ); - if ( Ivy_TruthDsd( uTruth, vTree ) ) - Ivy_TruthDsdPrint( stdout, vTree ); - else - printf( "Undecomposable\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthTestOne( unsigned uTruth ) -{ - static int Counter = 0; - static Vec_Int_t * vTree = NULL; - // decompose - if ( vTree == NULL ) - vTree = Vec_IntAlloc( 12 ); - - if ( !Ivy_TruthDsd( uTruth, vTree ) ) - { -// printf( "Undecomposable\n" ); - } - else - { -// nTruthDsd++; - printf( "%5d : ", Counter++ ); - Extra_PrintBinary( stdout, &uTruth, 32 ); - printf( " " ); - Ivy_TruthDsdPrint( stdout, vTree ); - if ( uTruth != Ivy_TruthDsdCompute(vTree) ) - printf( "Verification failed.\n" ); - } -// Vec_IntFree( vTree ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthTest() -{ - FILE * pFile; - char Buffer[100]; - unsigned uTruth; - int i; - - pFile = fopen( "npn4.txt", "r" ); - for ( i = 0; i < 222; i++ ) -// pFile = fopen( "npn5.txt", "r" ); -// for ( i = 0; i < 616126; i++ ) - { - fscanf( pFile, "%s", Buffer ); - Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); -// Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); - uTruth |= (uTruth << 16); -// uTruth = ~uTruth; - Ivy_TruthTestOne( uTruth ); - } - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthTest3() -{ - FILE * pFile; - char Buffer[100]; - unsigned uTruth; - int i; - - pFile = fopen( "npn3.txt", "r" ); - for ( i = 0; i < 14; i++ ) - { - fscanf( pFile, "%s", Buffer ); - Extra_ReadHexadecimal( &uTruth, Buffer+2, 3 ); - uTruth = uTruth | (uTruth << 8) | (uTruth << 16) | (uTruth << 24); - Ivy_TruthTestOne( uTruth ); - } - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TruthTest5() -{ - FILE * pFile; - char Buffer[100]; - unsigned uTruth; - int i; - -// pFile = fopen( "npn4.txt", "r" ); -// for ( i = 0; i < 222; i++ ) - pFile = fopen( "npn5.txt", "r" ); - for ( i = 0; i < 616126; i++ ) - { - fscanf( pFile, "%s", Buffer ); -// Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); - Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); -// uTruth |= (uTruth << 16); -// uTruth = ~uTruth; - Ivy_TruthTestOne( uTruth ); - } - fclose( pFile ); -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyFanout.c b/src/aig/ivy/ivyFanout.c deleted file mode 100644 index 3930186a..00000000 --- a/src/aig/ivy/ivyFanout.c +++ /dev/null @@ -1,309 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyFanout.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Representation of the fanouts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyFanout.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// getting hold of the next fanout of the node -static inline Ivy_Obj_t * Ivy_ObjNextFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - if ( pFanout == NULL ) - return NULL; - if ( Ivy_ObjFanin0(pFanout) == pObj ) - return pFanout->pNextFan0; - assert( Ivy_ObjFanin1(pFanout) == pObj ); - return pFanout->pNextFan1; -} - -// getting hold of the previous fanout of the node -static inline Ivy_Obj_t * Ivy_ObjPrevFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - if ( pFanout == NULL ) - return NULL; - if ( Ivy_ObjFanin0(pFanout) == pObj ) - return pFanout->pPrevFan0; - assert( Ivy_ObjFanin1(pFanout) == pObj ); - return pFanout->pPrevFan1; -} - -// getting hold of the place where the next fanout will be attached -static inline Ivy_Obj_t ** Ivy_ObjNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - if ( Ivy_ObjFanin0(pFanout) == pObj ) - return &pFanout->pNextFan0; - assert( Ivy_ObjFanin1(pFanout) == pObj ); - return &pFanout->pNextFan1; -} - -// getting hold of the place where the next fanout will be attached -static inline Ivy_Obj_t ** Ivy_ObjPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - if ( Ivy_ObjFanin0(pFanout) == pObj ) - return &pFanout->pPrevFan0; - assert( Ivy_ObjFanin1(pFanout) == pObj ); - return &pFanout->pPrevFan1; -} - -// getting hold of the place where the next fanout will be attached -static inline Ivy_Obj_t ** Ivy_ObjPrevNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - Ivy_Obj_t * pTemp; - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - pTemp = Ivy_ObjPrevFanout(pObj, pFanout); - if ( pTemp == NULL ) - return &pObj->pFanout; - if ( Ivy_ObjFanin0(pTemp) == pObj ) - return &pTemp->pNextFan0; - assert( Ivy_ObjFanin1(pTemp) == pObj ); - return &pTemp->pNextFan1; -} - -// getting hold of the place where the next fanout will be attached -static inline Ivy_Obj_t ** Ivy_ObjNextPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) -{ - Ivy_Obj_t * pTemp; - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_IsComplement(pFanout) ); - pTemp = Ivy_ObjNextFanout(pObj, pFanout); - if ( pTemp == NULL ) - return NULL; - if ( Ivy_ObjFanin0(pTemp) == pObj ) - return &pTemp->pPrevFan0; - assert( Ivy_ObjFanin1(pTemp) == pObj ); - return &pTemp->pPrevFan1; -} - -// iterator through the fanouts of the node -#define Ivy_ObjForEachFanoutInt( pObj, pFanout ) \ - for ( pFanout = (pObj)->pFanout; pFanout; \ - pFanout = Ivy_ObjNextFanout(pObj, pFanout) ) - -// safe iterator through the fanouts of the node -#define Ivy_ObjForEachFanoutIntSafe( pObj, pFanout, pFanout2 ) \ - for ( pFanout = (pObj)->pFanout, \ - pFanout2 = Ivy_ObjNextFanout(pObj, pFanout); \ - pFanout; \ - pFanout = pFanout2, \ - pFanout2 = Ivy_ObjNextFanout(pObj, pFanout) ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the fanout representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManStartFanout( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - assert( !p->fFanout ); - p->fFanout = 1; - Ivy_ManForEachObj( p, pObj, i ) - { - if ( Ivy_ObjFanin0(pObj) ) - Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); - if ( Ivy_ObjFanin1(pObj) ) - Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Stops the fanout representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManStopFanout( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - assert( p->fFanout ); - p->fFanout = 0; - Ivy_ManForEachObj( p, pObj, i ) - pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; -} - -/**Function************************************************************* - - Synopsis [Add the fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) -{ - assert( p->fFanout ); - if ( pFanin->pFanout ) - { - *Ivy_ObjNextFanoutPlace(pFanin, pFanout) = pFanin->pFanout; - *Ivy_ObjPrevFanoutPlace(pFanin, pFanin->pFanout) = pFanout; - } - pFanin->pFanout = pFanout; -} - -/**Function************************************************************* - - Synopsis [Removes the fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) -{ - Ivy_Obj_t ** ppPlace1, ** ppPlace2, ** ppPlaceN; - assert( pFanin->pFanout != NULL ); - - ppPlace1 = Ivy_ObjNextFanoutPlace(pFanin, pFanout); - ppPlaceN = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanout); - assert( *ppPlaceN == pFanout ); - if ( ppPlaceN ) - *ppPlaceN = *ppPlace1; - - ppPlace2 = Ivy_ObjPrevFanoutPlace(pFanin, pFanout); - ppPlaceN = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanout); - assert( ppPlaceN == NULL || *ppPlaceN == pFanout ); - if ( ppPlaceN ) - *ppPlaceN = *ppPlace2; - - *ppPlace1 = NULL; - *ppPlace2 = NULL; -} - -/**Function************************************************************* - - Synopsis [Replaces the fanout of pOld to be pFanoutNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ) -{ - Ivy_Obj_t ** ppPlace; - ppPlace = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanoutOld); - assert( *ppPlace == pFanoutOld ); - if ( ppPlace ) - *ppPlace = pFanoutNew; - ppPlace = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanoutOld); - assert( ppPlace == NULL || *ppPlace == pFanoutOld ); - if ( ppPlace ) - *ppPlace = pFanoutNew; - // assuming that pFanoutNew already points to the next fanout -} - -/**Function************************************************************* - - Synopsis [Starts iteration through the fanouts.] - - Description [Copies the currently available fanouts into the array.] - - SideEffects [Can be used while the fanouts are being removed.] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ) -{ - Ivy_Obj_t * pFanout; - assert( p->fFanout ); - assert( !Ivy_IsComplement(pObj) ); - Vec_PtrClear( vArray ); - Ivy_ObjForEachFanoutInt( pObj, pFanout ) - Vec_PtrPush( vArray, pFanout ); -} - -/**Function************************************************************* - - Synopsis [Reads one fanout.] - - Description [Returns fanout if there is only one fanout.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - return pObj->pFanout; -} - -/**Function************************************************************* - - Synopsis [Reads one fanout.] - - Description [Returns fanout if there is only one fanout.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pFanout; - int Counter = 0; - Ivy_ObjForEachFanoutInt( pObj, pFanout ) - Counter++; - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyFastMap.c b/src/aig/ivy/ivyFastMap.c deleted file mode 100644 index c4a043f2..00000000 --- a/src/aig/ivy/ivyFastMap.c +++ /dev/null @@ -1,1593 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyFastMap.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Fast FPGA mapping.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyFastMap.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define IVY_INFINITY 10000 - -typedef struct Ivy_SuppMan_t_ Ivy_SuppMan_t; -struct Ivy_SuppMan_t_ -{ - int nLimit; // the limit on the number of inputs - int nObjs; // the number of entries - int nSize; // size of each entry in bytes - char * pMem; // memory allocated - Vec_Vec_t * vLuts; // the array of nodes used in the mapping -}; - -typedef struct Ivy_Supp_t_ Ivy_Supp_t; -struct Ivy_Supp_t_ -{ - char nSize; // the number of support nodes - char fMark; // multipurpose mask - char fMark2; // multipurpose mask - char fMark3; // multipurpose mask - int nRefs; // the number of references - short Delay; // the delay of the node - short DelayR; // the reverse delay of the node - int pArray[0]; // the support nodes -}; - -static inline Ivy_Supp_t * Ivy_ObjSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - return (Ivy_Supp_t *)(((Ivy_SuppMan_t*)pAig->pData)->pMem + pObj->Id * ((Ivy_SuppMan_t*)pAig->pData)->nSize); -} -static inline Ivy_Supp_t * Ivy_ObjSuppStart( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp; - pSupp = Ivy_ObjSupp( pAig, pObj ); - pSupp->fMark = 0; - pSupp->Delay = 0; - pSupp->nSize = 1; - pSupp->pArray[0] = pObj->Id; - return pSupp; -} - -static void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, int Time, char * pStr ); -static int Ivy_FastMapDelay( Ivy_Man_t * pAig ); -static int Ivy_FastMapArea( Ivy_Man_t * pAig ); -static void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); -static void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); -static int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ); -static void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ); -static void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ); -static int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); -static int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); -static int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); -static void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ); -static int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); -static int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); - - -extern int s_MappingTime; -extern int s_MappingMem; - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs fast K-LUT mapping of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ) -{ - Ivy_SuppMan_t * pMan; - Ivy_Obj_t * pObj; - int i, Delay, Area, clk, clkTotal = clock(); - // start the memory for supports - pMan = ALLOC( Ivy_SuppMan_t, 1 ); - memset( pMan, 0, sizeof(Ivy_SuppMan_t) ); - pMan->nLimit = nLimit; - pMan->nObjs = Ivy_ManObjIdMax(pAig) + 1; - pMan->nSize = sizeof(Ivy_Supp_t) + nLimit * sizeof(int); - pMan->pMem = (char *)malloc( pMan->nObjs * pMan->nSize ); - memset( pMan->pMem, 0, pMan->nObjs * pMan->nSize ); - pMan->vLuts = Vec_VecAlloc( 100 ); - pAig->pData = pMan; -clk = clock(); - // set the PI mapping - Ivy_ObjSuppStart( pAig, Ivy_ManConst1(pAig) ); - Ivy_ManForEachPi( pAig, pObj, i ) - Ivy_ObjSuppStart( pAig, pObj ); - // iterate through all nodes in the topological order - Ivy_ManForEachNode( pAig, pObj, i ) - Ivy_FastMapNode( pAig, pObj, nLimit ); - // find the best arrival time and area - Delay = Ivy_FastMapDelay( pAig ); - Area = Ivy_FastMapArea(pAig); - if ( fVerbose ) - Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Delay oriented mapping: " ); - -// 2-1-2 (doing 2-1-2-1-2 improves 0.5%) - - if ( fRecovery ) - { -clk = clock(); - Ivy_FastMapRequired( pAig, Delay, 0 ); - // remap the nodes - Ivy_FastMapRecover( pAig, nLimit ); - Delay = Ivy_FastMapDelay( pAig ); - Area = Ivy_FastMapArea(pAig); - if ( fVerbose ) - Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 2 : " ); - -clk = clock(); - Ivy_FastMapRequired( pAig, Delay, 0 ); - // iterate through all nodes in the topological order - Ivy_ManForEachNode( pAig, pObj, i ) - Ivy_FastMapNodeArea( pAig, pObj, nLimit ); - Delay = Ivy_FastMapDelay( pAig ); - Area = Ivy_FastMapArea(pAig); - if ( fVerbose ) - Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 1 : " ); - -clk = clock(); - Ivy_FastMapRequired( pAig, Delay, 0 ); - // remap the nodes - Ivy_FastMapRecover( pAig, nLimit ); - Delay = Ivy_FastMapDelay( pAig ); - Area = Ivy_FastMapArea(pAig); - if ( fVerbose ) - Ivy_FastMapPrint( pAig, Delay, Area, clock() - clk, "Area recovery 2 : " ); - } - - - s_MappingTime = clock() - clkTotal; - s_MappingMem = pMan->nObjs * pMan->nSize; -/* - { - Vec_Ptr_t * vNodes; - vNodes = Vec_PtrAlloc( 100 ); - Vec_VecForEachEntry( pMan->vLuts, pObj, i, k ) - Vec_PtrPush( vNodes, pObj ); - Ivy_ManShow( pAig, 0, vNodes ); - Vec_PtrFree( vNodes ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Cleans memory used for decomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapStop( Ivy_Man_t * pAig ) -{ - Ivy_SuppMan_t * p = pAig->pData; - Vec_VecFree( p->vLuts ); - free( p->pMem ); - free( p ); - pAig->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Prints statistics.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, int Time, char * pStr ) -{ - printf( "%s : Delay = %3d. Area = %6d. ", pStr, Delay, Area ); - PRT( "Time", Time ); -} - -/**Function************************************************************* - - Synopsis [Computes delay after LUT mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapDelay( Ivy_Man_t * pAig ) -{ - Ivy_Supp_t * pSupp; - Ivy_Obj_t * pObj; - int i, DelayMax = 0; - Ivy_ManForEachPo( pAig, pObj, i ) - { - pObj = Ivy_ObjFanin0(pObj); - if ( !Ivy_ObjIsNode(pObj) ) - continue; - pSupp = Ivy_ObjSupp( pAig, pObj ); - if ( DelayMax < pSupp->Delay ) - DelayMax = pSupp->Delay; - } - return DelayMax; -} - -/**Function************************************************************* - - Synopsis [Computes area after mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapArea_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Vec_t * vLuts ) -{ - Ivy_Supp_t * pSupp; - int i, Counter; - pSupp = Ivy_ObjSupp( pAig, pObj ); - // skip visited nodes and PIs - if ( pSupp->fMark || pSupp->nSize == 1 ) - return 0; - pSupp->fMark = 1; - // compute the area of this node - Counter = 0; - for ( i = 0; i < pSupp->nSize; i++ ) - Counter += Ivy_FastMapArea_rec( pAig, Ivy_ManObj(pAig, pSupp->pArray[i]), vLuts ); - // add the node to the array of LUTs - Vec_VecPush( vLuts, pSupp->Delay, pObj ); - return 1 + Counter; -} - -/**Function************************************************************* - - Synopsis [Computes area after mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapArea( Ivy_Man_t * pAig ) -{ - Vec_Vec_t * vLuts; - Ivy_Obj_t * pObj; - int i, Counter = 0; - // get the array to store the nodes - vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; - Vec_VecClear( vLuts ); - // explore starting from each node - Ivy_ManForEachPo( pAig, pObj, i ) - Counter += Ivy_FastMapArea_rec( pAig, Ivy_ObjFanin0(pObj), vLuts ); - // clean the marks - Ivy_ManForEachNode( pAig, pObj, i ) - Ivy_ObjSupp( pAig, pObj )->fMark = 0; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Ivy_ObjIsNodeInt1( Ivy_Obj_t * pObj ) -{ - return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) == 1; -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Ivy_ObjIsNodeInt2( Ivy_Obj_t * pObj ) -{ - return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) <= 2; -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntSelectSort( int * pArray, int nSize ) -{ - int temp, i, j, best_i; - for ( i = 0; i < nSize-1; i++ ) - { - best_i = i; - for ( j = i+1; j < nSize; j++ ) - if ( pArray[j] < pArray[best_i] ) - best_i = j; - temp = pArray[i]; - pArray[i] = pArray[best_i]; - pArray[best_i] = temp; - } -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntRemoveDup( int * pArray, int nSize ) -{ - int i, k; - if ( nSize < 2 ) - return nSize; - for ( i = k = 1; i < nSize; i++ ) - if ( pArray[i] != pArray[i-1] ) - pArray[k++] = pArray[i]; - return k; -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeArea2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) -{ - static int Store[32], StoreSize; - static char Supp0[16], Supp1[16]; - static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; - static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; - Ivy_Obj_t * pFanin0, * pFanin1; - Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; - int RetValue, DelayOld; - assert( nLimit <= 32 ); - assert( Ivy_ObjIsNode(pObj) ); - // get the fanins - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - // get the supports - pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); - pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->fMark == 0 ); - // get the old delay of the node - DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); - assert( DelayOld <= pSupp->DelayR ); - // copy the current cut - memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); - StoreSize = pSupp->nSize; - // get the fanin support - if ( Ivy_ObjRefs(pFanin0) > 1 && pSupp0->Delay < pSupp->DelayR ) - { - pSupp0 = pTemp0; - pSupp0->nSize = 1; - pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); - } - // get the fanin support - if ( Ivy_ObjRefs(pFanin1) > 1 && pSupp1->Delay < pSupp->DelayR ) - { - pSupp1 = pTemp1; - pSupp1->nSize = 1; - pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); - } - // merge the cuts - if ( pSupp0->nSize < pSupp1->nSize ) - RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); - else - RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); - if ( !RetValue ) - { - pSupp->nSize = 2; - pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); - pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); - } - // check the resulting delay - pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); - if ( pSupp->Delay > pSupp->DelayR ) - { - pSupp->nSize = StoreSize; - memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); - pSupp->Delay = DelayOld; - } -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) -{ - static int Store[32], StoreSize; - static char Supp0[16], Supp1[16]; - static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; - static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; - Ivy_Obj_t * pFanin0, * pFanin1; - Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; - int RetValue, DelayOld, RefsOld; - int AreaBef, AreaAft; - assert( nLimit <= 32 ); - assert( Ivy_ObjIsNode(pObj) ); - // get the fanins - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - // get the supports - pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); - pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->fMark == 0 ); - - // get the area - if ( pSupp->nRefs == 0 ) - AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); - else - AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); -// if ( AreaBef == 1 ) -// return; - - // deref the cut if the node is refed - if ( pSupp->nRefs != 0 ) - Ivy_FastMapNodeDeref( pAig, pObj ); - - // get the old delay of the node - DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); - assert( DelayOld <= pSupp->DelayR ); - // copy the current cut - memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); - StoreSize = pSupp->nSize; - // get the fanin support - if ( Ivy_ObjRefs(pFanin0) > 2 && pSupp0->Delay < pSupp->DelayR ) -// if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results - { - pSupp0 = pTemp0; - pSupp0->nSize = 1; - pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); - } - // get the fanin support - if ( Ivy_ObjRefs(pFanin1) > 2 && pSupp1->Delay < pSupp->DelayR ) -// if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR ) - { - pSupp1 = pTemp1; - pSupp1->nSize = 1; - pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); - } - // merge the cuts - if ( pSupp0->nSize < pSupp1->nSize ) - RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); - else - RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); - if ( !RetValue ) - { - pSupp->nSize = 2; - pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); - pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); - } - - // check the resulting delay - pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); - - RefsOld = pSupp->nRefs; pSupp->nRefs = 0; - AreaAft = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); - pSupp->nRefs = RefsOld; - - if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) -// if ( pSupp->Delay > pSupp->DelayR ) - { - pSupp->nSize = StoreSize; - memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); - pSupp->Delay = DelayOld; -// printf( "-" ); - } -// else -// printf( "+" ); - - if ( pSupp->nRefs != 0 ) - Ivy_FastMapNodeRef( pAig, pObj ); -} - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) -{ - Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; - int fFaninParam = 2; - int RetValue; - assert( Ivy_ObjIsNode(pObj) ); - // get the supports - pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); - pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); - pSupp = Ivy_ObjSupp( pAig, pObj ); - pSupp->fMark = 0; - // get the delays - if ( pSupp0->Delay == pSupp1->Delay ) - pSupp->Delay = (pSupp0->Delay == 0) ? pSupp0->Delay + 1: pSupp0->Delay; - else if ( pSupp0->Delay > pSupp1->Delay ) - { - pSupp->Delay = pSupp0->Delay; - pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); - pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); - } - else // if ( pSupp0->Delay < pSupp1->Delay ) - { - pSupp->Delay = pSupp1->Delay; - pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); - pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); - } - // merge the cuts - if ( pSupp0->nSize < pSupp1->nSize ) - RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); - else - RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); - if ( !RetValue ) - { - pSupp->Delay++; - if ( fFaninParam == 2 ) - { - pSupp->nSize = 2; - pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); - pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); - } - else if ( fFaninParam == 3 ) - { - Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - pSupp->nSize = 0; - // process the first fanin - if ( Ivy_ObjIsNodeInt1(pFanin0) ) - { - pFaninA = Ivy_ObjFanin0(pFanin0); - pFaninB = Ivy_ObjFanin1(pFanin0); - if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); - else - { - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); - } - } - else - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); - // process the second fanin - if ( Ivy_ObjIsNodeInt1(pFanin1) ) - { - pFaninA = Ivy_ObjFanin0(pFanin1); - pFaninB = Ivy_ObjFanin1(pFanin1); - if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); - else - { - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); - } - } - else - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); - // sort the fanins - Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); - pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); - assert( pSupp->pArray[0] < pSupp->pArray[1] ); - } - else if ( fFaninParam == 4 ) - { - Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - pSupp->nSize = 0; - // consider the case when exactly one of them is internal - if ( Ivy_ObjIsNodeInt1(pFanin0) ^ Ivy_ObjIsNodeInt1(pFanin1) ) - { - pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); - pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); - if ( Ivy_ObjIsNodeInt1(pFanin0) && pSupp0->nSize < nLimit ) - { - pSupp->Delay = IVY_MAX( pSupp0->Delay, pSupp1->Delay + 1 ); - pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); - pSupp1->pArray[0] = Ivy_ObjId(pFanin1); - // merge the cuts - RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); - assert( RetValue ); - assert( pSupp->nSize > 1 ); - return; - } - if ( Ivy_ObjIsNodeInt1(pFanin1) && pSupp1->nSize < nLimit ) - { - pSupp->Delay = IVY_MAX( pSupp1->Delay, pSupp0->Delay + 1 ); - pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); - pSupp0->pArray[0] = Ivy_ObjId(pFanin0); - // merge the cuts - RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); - assert( RetValue ); - assert( pSupp->nSize > 1 ); - return; - } - } - // process the first fanin - if ( Ivy_ObjIsNodeInt1(pFanin0) ) - { - pFaninA = Ivy_ObjFanin0(pFanin0); - pFaninB = Ivy_ObjFanin1(pFanin0); - if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); - else - { - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); - } - } - else - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin0); - // process the second fanin - if ( Ivy_ObjIsNodeInt1(pFanin1) ) - { - pFaninA = Ivy_ObjFanin0(pFanin1); - pFaninB = Ivy_ObjFanin1(pFanin1); - if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); - else - { - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninA); - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFaninB); - } - } - else - pSupp->pArray[pSupp->nSize++] = Ivy_ObjId(pFanin1); - // sort the fanins - Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); - pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); - assert( pSupp->pArray[0] < pSupp->pArray[1] ); - assert( pSupp->nSize > 1 ); - } - } - assert( pSupp->Delay > 0 ); -} - -/**Function************************************************************* - - Synopsis [Merges two supports] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ) -{ - int i, k, c; - assert( pSupp0->nSize >= pSupp1->nSize ); - // the case of the largest cut sizes - if ( pSupp0->nSize == nLimit && pSupp1->nSize == nLimit ) - { - for ( i = 0; i < pSupp0->nSize; i++ ) - if ( pSupp0->pArray[i] != pSupp1->pArray[i] ) - return 0; - for ( i = 0; i < pSupp0->nSize; i++ ) - pSupp->pArray[i] = pSupp0->pArray[i]; - pSupp->nSize = pSupp0->nSize; - return 1; - } - // the case when one of the cuts is the largest - if ( pSupp0->nSize == nLimit ) - { - for ( i = 0; i < pSupp1->nSize; i++ ) - { - for ( k = pSupp0->nSize - 1; k >= 0; k-- ) - if ( pSupp0->pArray[k] == pSupp1->pArray[i] ) - break; - if ( k == -1 ) // did not find - return 0; - } - for ( i = 0; i < pSupp0->nSize; i++ ) - pSupp->pArray[i] = pSupp0->pArray[i]; - pSupp->nSize = pSupp0->nSize; - return 1; - } - - // compare two cuts with different numbers - i = k = 0; - for ( c = 0; c < nLimit; c++ ) - { - if ( k == pSupp1->nSize ) - { - if ( i == pSupp0->nSize ) - { - pSupp->nSize = c; - return 1; - } - pSupp->pArray[c] = pSupp0->pArray[i++]; - continue; - } - if ( i == pSupp0->nSize ) - { - if ( k == pSupp1->nSize ) - { - pSupp->nSize = c; - return 1; - } - pSupp->pArray[c] = pSupp1->pArray[k++]; - continue; - } - if ( pSupp0->pArray[i] < pSupp1->pArray[k] ) - { - pSupp->pArray[c] = pSupp0->pArray[i++]; - continue; - } - if ( pSupp0->pArray[i] > pSupp1->pArray[k] ) - { - pSupp->pArray[c] = pSupp1->pArray[k++]; - continue; - } - pSupp->pArray[c] = pSupp0->pArray[i++]; - k++; - } - if ( i < pSupp0->nSize || k < pSupp1->nSize ) - return 0; - pSupp->nSize = c; - return 1; -} - -/**Function************************************************************* - - Synopsis [Creates integer vector with the support of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ) -{ - Ivy_Supp_t * pSupp; - pSupp = Ivy_ObjSupp( pAig, pObj ); - vLeaves->nCap = 8; - vLeaves->nSize = pSupp->nSize; - vLeaves->pArray = pSupp->pArray; -} - -/**Function************************************************************* - - Synopsis [Sets the required times of the intermediate nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapRequired_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Ivy_Obj_t * pRoot, int DelayR ) -{ - Ivy_Supp_t * pSupp; - pSupp = Ivy_ObjSupp( pAig, pObj ); - if ( pObj != pRoot && (pSupp->nRefs > 0 || Ivy_ObjIsCi(pObj)) ) - return; - Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin0(pObj), pRoot, DelayR ); - Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin1(pObj), pRoot, DelayR ); -// assert( pObj == pRoot || pSupp->DelayR == IVY_INFINITY ); - pSupp->DelayR = DelayR; -} - -/**Function************************************************************* - - Synopsis [Computes the required times for each node.] - - Description [Sets reference counters for each node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ) -{ - Vec_Vec_t * vLuts; - Vec_Ptr_t * vNodes; - Ivy_Obj_t * pObj; - Ivy_Supp_t * pSupp, * pSuppF; - int i, k, c; - // clean the required times - Ivy_ManForEachPi( pAig, pObj, i ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - pSupp->DelayR = IVY_INFINITY; - pSupp->nRefs = 0; - } - Ivy_ManForEachNode( pAig, pObj, i ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - pSupp->DelayR = IVY_INFINITY; - pSupp->nRefs = 0; - } - // set the required times of the POs - Ivy_ManForEachPo( pAig, pObj, i ) - { - pSupp = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); - pSupp->DelayR = Delay; - pSupp->nRefs++; - } - // get the levelized nodes used in the mapping - vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; - // propagate the required times - Vec_VecForEachLevelReverse( vLuts, vNodes, i ) - Vec_PtrForEachEntry( vNodes, pObj, k ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->nRefs > 0 ); - for ( c = 0; c < pSupp->nSize; c++ ) - { - pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); - pSuppF->DelayR = IVY_MIN( pSuppF->DelayR, pSupp->DelayR - 1 ); - pSuppF->nRefs++; - } - } -/* - // print out some of the required times - Ivy_ManForEachPi( pAig, pObj, i ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - printf( "%d ", pSupp->DelayR ); - } - printf( "\n" ); -*/ - - if ( fSetInter ) - { - // set the required times of the intermediate nodes - Vec_VecForEachLevelReverse( vLuts, vNodes, i ) - Vec_PtrForEachEntry( vNodes, pObj, k ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - Ivy_FastMapRequired_rec( pAig, pObj, pObj, pSupp->DelayR ); - } - // make sure that all required times are assigned - Ivy_ManForEachNode( pAig, pObj, i ) - { - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->DelayR < IVY_INFINITY ); - } - } -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ) -{ - Vec_Ptr_t * vFront, * vFrontOld; - Ivy_Obj_t * pObj; - int i; - vFront = Vec_PtrAlloc( nLimit ); - vFrontOld = Vec_PtrAlloc( nLimit ); - Ivy_ManCleanTravId( pAig ); - // iterate through all nodes in the topological order - Ivy_ManForEachNode( pAig, pObj, i ) - Ivy_FastMapNodeRecover( pAig, pObj, nLimit, vFront, vFrontOld ); - Vec_PtrFree( vFrontOld ); - Vec_PtrFree( vFront ); -} - -/**Function************************************************************* - - Synopsis [Computes the delay of the cut rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp, * pSuppF; - int c, Delay = 0; - pSupp = Ivy_ObjSupp( pAig, pObj ); - for ( c = 0; c < pSupp->nSize; c++ ) - { - pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); - Delay = IVY_MAX( Delay, pSuppF->Delay ); - } - return 1 + Delay; -} - - -/**function************************************************************* - - synopsis [References the cut.] - - description [This procedure is similar to the procedure NodeReclaim.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp, * pSuppF; - Ivy_Obj_t * pNodeChild; - int aArea, i; - // start the area of this cut - aArea = 1; - // go through the children - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->nSize > 1 ); - for ( i = 0; i < pSupp->nSize; i++ ) - { - pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); - pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); - assert( pSuppF->nRefs >= 0 ); - if ( pSuppF->nRefs++ > 0 ) - continue; - if ( pSuppF->nSize == 1 ) - continue; - aArea += Ivy_FastMapNodeRef( pAig, pNodeChild ); - } - return aArea; -} - -/**function************************************************************* - - synopsis [Dereferences the cut.] - - description [This procedure is similar to the procedure NodeRecusiveDeref.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp, * pSuppF; - Ivy_Obj_t * pNodeChild; - int aArea, i; - // start the area of this cut - aArea = 1; - // go through the children - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->nSize > 1 ); - for ( i = 0; i < pSupp->nSize; i++ ) - { - pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); - pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); - assert( pSuppF->nRefs > 0 ); - if ( --pSuppF->nRefs > 0 ) - continue; - if ( pSuppF->nSize == 1 ) - continue; - aArea += Ivy_FastMapNodeDeref( pAig, pNodeChild ); - } - return aArea; -} - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp; - int aResult, aResult2; - if ( Ivy_ObjIsCi(pObj) ) - return 0; - assert( Ivy_ObjIsNode(pObj) ); - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->nRefs > 0 ); - aResult = Ivy_FastMapNodeDeref( pAig, pObj ); - aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); - assert( aResult == aResult2 ); - return aResult; -} - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSupp; - int aResult, aResult2; - if ( Ivy_ObjIsCi(pObj) ) - return 0; - assert( Ivy_ObjIsNode(pObj) ); - pSupp = Ivy_ObjSupp( pAig, pObj ); - assert( pSupp->nRefs == 0 ); - aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); - aResult = Ivy_FastMapNodeDeref( pAig, pObj ); - assert( aResult == aResult2 ); - return aResult; -} - - - - -/**Function************************************************************* - - Synopsis [Counts the number of nodes with no external fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapCutCost( Ivy_Man_t * pAig, Vec_Ptr_t * vFront ) -{ - Ivy_Supp_t * pSuppF; - Ivy_Obj_t * pFanin; - int i, Counter = 0; - Vec_PtrForEachEntry( vFront, pFanin, i ) - { - pSuppF = Ivy_ObjSupp( pAig, pFanin ); - if ( pSuppF->nRefs == 0 ) - Counter++; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapMark_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - if ( Ivy_ObjIsTravIdCurrent(pAig, pObj) ) - return; - assert( Ivy_ObjIsNode(pObj) ); - Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin0(pObj) ); - Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin1(pObj) ); - Ivy_ObjSetTravIdCurrent(pAig, pObj); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the number of fanins will grow.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeWillGrow( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pFanin0, * pFanin1; - assert( Ivy_ObjIsNode(pObj) ); - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - return !Ivy_ObjIsTravIdCurrent(pAig, pFanin0) && !Ivy_ObjIsTravIdCurrent(pAig, pFanin1); -} - -/**Function************************************************************* - - Synopsis [Returns the increase in the number of fanins with no external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeFaninCost( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) -{ - Ivy_Supp_t * pSuppF; - Ivy_Obj_t * pFanin; - int Counter = 0; - assert( Ivy_ObjIsNode(pObj) ); - // check if the node has external refs - pSuppF = Ivy_ObjSupp( pAig, pObj ); - if ( pSuppF->nRefs == 0 ) - Counter--; - // increment the number of fanins without external refs - pFanin = Ivy_ObjFanin0(pObj); - pSuppF = Ivy_ObjSupp( pAig, pFanin ); - if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) - Counter++; - // increment the number of fanins without external refs - pFanin = Ivy_ObjFanin1(pObj); - pSuppF = Ivy_ObjSupp( pAig, pFanin ); - if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Updates the frontier.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeFaninUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pFanin; - assert( Ivy_ObjIsNode(pObj) ); - Vec_PtrRemove( vFront, pObj ); - pFanin = Ivy_ObjFanin0(pObj); - if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) - { - Ivy_ObjSetTravIdCurrent(pAig, pFanin); - Vec_PtrPush( vFront, pFanin ); - } - pFanin = Ivy_ObjFanin1(pObj); - if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) - { - Ivy_ObjSetTravIdCurrent(pAig, pFanin); - Vec_PtrPush( vFront, pFanin ); - } -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeFaninCompact0( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pFanin; - int i; - Vec_PtrForEachEntry( vFront, pFanin, i ) - { - if ( Ivy_ObjIsCi(pFanin) ) - continue; - if ( Ivy_FastMapNodeWillGrow(pAig, pFanin) ) - continue; - if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) - { - Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeFaninCompact1( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pFanin; - int i; - Vec_PtrForEachEntry( vFront, pFanin, i ) - { - if ( Ivy_ObjIsCi(pFanin) ) - continue; - if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) < 0 ) - { - Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeFaninCompact2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) -{ - Ivy_Obj_t * pFanin; - int i; - Vec_PtrForEachEntry( vFront, pFanin, i ) - { - if ( Ivy_ObjIsCi(pFanin) ) - continue; - if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) - { - Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FastMapNodeFaninCompact_int( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) -{ - if ( Ivy_FastMapNodeFaninCompact0(pAig, pObj, nLimit, vFront) ) - return 1; - if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact1(pAig, pObj, nLimit, vFront) ) - return 1; - if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact2(pAig, pObj, nLimit, vFront) ) - return 1; - assert( Vec_PtrSize(vFront) <= nLimit ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeFaninCompact( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) -{ - while ( Ivy_FastMapNodeFaninCompact_int( pAig, pObj, nLimit, vFront ) ); -} - -/**Function************************************************************* - - Synopsis [Prepares node mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodePrepare( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) -{ - Ivy_Supp_t * pSupp; - Ivy_Obj_t * pFanin; - int i; - pSupp = Ivy_ObjSupp( pAig, pObj ); - // expand the cut downwards from the given place - Vec_PtrClear( vFront ); - Vec_PtrClear( vFrontOld ); - Ivy_ManIncrementTravId( pAig ); - for ( i = 0; i < pSupp->nSize; i++ ) - { - pFanin = Ivy_ManObj(pAig, pSupp->pArray[i]); - Vec_PtrPush( vFront, pFanin ); - Vec_PtrPush( vFrontOld, pFanin ); - Ivy_ObjSetTravIdCurrent( pAig, pFanin ); - } - // mark the nodes in the cone - Ivy_FastMapMark_rec( pAig, pObj ); -} - -/**Function************************************************************* - - Synopsis [Updates the frontier.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) -{ - Ivy_Supp_t * pSupp; - Ivy_Obj_t * pFanin; - int i; - pSupp = Ivy_ObjSupp( pAig, pObj ); - // deref node's cut - Ivy_FastMapNodeDeref( pAig, pObj ); - // update the node's cut - pSupp->nSize = Vec_PtrSize(vFront); - Vec_PtrForEachEntry( vFront, pFanin, i ) - pSupp->pArray[i] = pFanin->Id; - // ref the new cut - Ivy_FastMapNodeRef( pAig, pObj ); -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeRecover2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) -{ - Ivy_Supp_t * pSupp; - int CostBef, CostAft; - int AreaBef, AreaAft; - pSupp = Ivy_ObjSupp( pAig, pObj ); -// if ( pSupp->nRefs == 0 ) -// return; - if ( pSupp->nRefs == 0 ) - AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); - else - AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - // get the area - if ( AreaBef == 1 ) - return; - - if ( pSupp->nRefs == 0 ) - { - pSupp->nRefs = 1000000; - Ivy_FastMapNodeRef( pAig, pObj ); - } - // the cut is non-trivial - Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); - // iteratively modify the cut - CostBef = Ivy_FastMapCutCost( pAig, vFront ); - Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); - CostAft = Ivy_FastMapCutCost( pAig, vFront ); - assert( CostBef >= CostAft ); - // update the node - Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); - // get the new area - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - if ( AreaAft > AreaBef ) - { - Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - assert( AreaAft == AreaBef ); - } - if ( pSupp->nRefs == 1000000 ) - { - pSupp->nRefs = 0; - Ivy_FastMapNodeDeref( pAig, pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) -{ - Ivy_Supp_t * pSupp; - int CostBef, CostAft; - int AreaBef, AreaAft; - int DelayOld; - pSupp = Ivy_ObjSupp( pAig, pObj ); - DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); - assert( pSupp->Delay <= pSupp->DelayR ); - if ( pSupp->nRefs == 0 ) - return; - // get the area - AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); -// if ( AreaBef == 1 ) -// return; - if ( pObj->Id == 102 ) - { - int x = 0; - } - // the cut is non-trivial - Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); - // iteratively modify the cut - Ivy_FastMapNodeDeref( pAig, pObj ); - CostBef = Ivy_FastMapCutCost( pAig, vFront ); - Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); - CostAft = Ivy_FastMapCutCost( pAig, vFront ); - Ivy_FastMapNodeRef( pAig, pObj ); - assert( CostBef >= CostAft ); - // update the node - Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); - pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); - // get the new area - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) - { - Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - assert( AreaAft == AreaBef ); - pSupp->Delay = DelayOld; - } -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FastMapNodeRecover4( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) -{ - Ivy_Supp_t * pSupp; - int CostBef, CostAft; - int AreaBef, AreaAft; - int DelayOld; - pSupp = Ivy_ObjSupp( pAig, pObj ); - DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); - assert( pSupp->Delay <= pSupp->DelayR ); -// if ( pSupp->nRefs == 0 ) -// return; -// AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - // get the area - if ( pSupp->nRefs == 0 ) - AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); - else - AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - if ( AreaBef == 1 ) - return; - - if ( pSupp->nRefs == 0 ) - { - pSupp->nRefs = 1000000; - Ivy_FastMapNodeRef( pAig, pObj ); - } - // the cut is non-trivial - Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); - // iteratively modify the cut - CostBef = Ivy_FastMapCutCost( pAig, vFront ); - Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); - CostAft = Ivy_FastMapCutCost( pAig, vFront ); - assert( CostBef >= CostAft ); - // update the node - Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); - pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); - // get the new area - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) - { - Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); - AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); - assert( AreaAft == AreaBef ); - pSupp->Delay = DelayOld; - } - if ( pSupp->nRefs == 1000000 ) - { - pSupp->nRefs = 0; - Ivy_FastMapNodeDeref( pAig, pObj ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyFraig.c b/src/aig/ivy/ivyFraig.c deleted file mode 100644 index 1ab91dd2..00000000 --- a/src/aig/ivy/ivyFraig.c +++ /dev/null @@ -1,2762 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyFraig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Functional reduction of AIGs] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyFraig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "satSolver.h" -#include "extra.h" -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ivy_FraigMan_t_ Ivy_FraigMan_t; -typedef struct Ivy_FraigSim_t_ Ivy_FraigSim_t; -typedef struct Ivy_FraigList_t_ Ivy_FraigList_t; - -struct Ivy_FraigList_t_ -{ - Ivy_Obj_t * pHead; - Ivy_Obj_t * pTail; - int nItems; -}; - -struct Ivy_FraigSim_t_ -{ - int Type; - Ivy_FraigSim_t * pNext; - Ivy_FraigSim_t * pFanin0; - Ivy_FraigSim_t * pFanin1; - unsigned pData[0]; -}; - -struct Ivy_FraigMan_t_ -{ - // general info - Ivy_FraigParams_t * pParams; // various parameters - // temporary backtrack limits because "sint64" cannot be defined in Ivy_FraigParams_t ... - sint64 nBTLimitGlobal; // global limit on the number of backtracks - sint64 nInsLimitGlobal;// global limit on the number of clause inspects - // AIG manager - Ivy_Man_t * pManAig; // the starting AIG manager - Ivy_Man_t * pManFraig; // the final AIG manager - // simulation information - int nSimWords; // the number of words - char * pSimWords; // the simulation info - Ivy_FraigSim_t * pSimStart; // the list of simulation info for internal nodes - // counter example storage - int nPatWords; // the number of words in the counter example - unsigned * pPatWords; // the counter example - int * pPatScores; // the scores of each pattern - // equivalence classes - Ivy_FraigList_t lClasses; // equivalence classes - Ivy_FraigList_t lCand; // candidatates - int nPairs; // the number of pairs of nodes - // equivalence checking - sat_solver * pSat; // SAT solver - int nSatVars; // the number of variables currently used - Vec_Ptr_t * vPiVars; // the PIs of the cone used - // other - ProgressBar * pProgress; - // statistics - int nSimRounds; - int nNodesMiter; - int nClassesZero; - int nClassesBeg; - int nClassesEnd; - int nPairsBeg; - int nPairsEnd; - int nSatCalls; - int nSatCallsSat; - int nSatCallsUnsat; - int nSatProof; - int nSatFails; - int nSatFailsReal; - // runtime - int timeSim; - int timeTrav; - int timeSat; - int timeSatUnsat; - int timeSatSat; - int timeSatFail; - int timeRef; - int timeTotal; - int time1; - int time2; -}; - -typedef struct Prove_ParamsStruct_t_ Prove_Params_t; -struct Prove_ParamsStruct_t_ -{ - // general parameters - int fUseFraiging; // enables fraiging - int fUseRewriting; // enables rewriting - int fUseBdds; // enables BDD construction when other methods fail - int fVerbose; // prints verbose stats - // iterations - int nItersMax; // the number of iterations - // mitering - int nMiteringLimitStart; // starting mitering limit - float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration - // rewriting - int nRewritingLimitStart; // the number of rewriting iterations - float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration - // fraiging - int nFraigingLimitStart; // starting backtrack(conflict) limit - float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration - // last-gasp BDD construction - int nBddSizeLimit; // the number of BDD nodes when construction is aborted - int fBddReorder; // enables dynamic BDD variable reordering - // last-gasp mitering - int nMiteringLimitLast; // final mitering limit - // global SAT solver limits - sint64 nTotalBacktrackLimit; // global limit on the number of backtracks - sint64 nTotalInspectLimit; // global limit on the number of clause inspects - // global resources applied - sint64 nTotalBacktracksMade; // the total number of backtracks made - sint64 nTotalInspectsMade; // the total number of inspects made -}; - -static inline Ivy_FraigSim_t * Ivy_ObjSim( Ivy_Obj_t * pObj ) { return (Ivy_FraigSim_t *)pObj->pFanout; } -static inline Ivy_Obj_t * Ivy_ObjClassNodeLast( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } -static inline Ivy_Obj_t * Ivy_ObjClassNodeRepr( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } -static inline Ivy_Obj_t * Ivy_ObjClassNodeNext( Ivy_Obj_t * pObj ) { return pObj->pNextFan1; } -static inline Ivy_Obj_t * Ivy_ObjNodeHashNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } -static inline Ivy_Obj_t * Ivy_ObjEquivListNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } -static inline Ivy_Obj_t * Ivy_ObjEquivListPrev( Ivy_Obj_t * pObj ) { return pObj->pPrevFan1; } -static inline Ivy_Obj_t * Ivy_ObjFraig( Ivy_Obj_t * pObj ) { return pObj->pEquiv; } -static inline int Ivy_ObjSatNum( Ivy_Obj_t * pObj ) { return (int)pObj->pNextFan0; } -static inline Vec_Ptr_t * Ivy_ObjFaninVec( Ivy_Obj_t * pObj ) { return (Vec_Ptr_t *)pObj->pNextFan1; } - -static inline void Ivy_ObjSetSim( Ivy_Obj_t * pObj, Ivy_FraigSim_t * pSim ) { pObj->pFanout = (Ivy_Obj_t *)pSim; } -static inline void Ivy_ObjSetClassNodeLast( Ivy_Obj_t * pObj, Ivy_Obj_t * pLast ) { pObj->pNextFan0 = pLast; } -static inline void Ivy_ObjSetClassNodeRepr( Ivy_Obj_t * pObj, Ivy_Obj_t * pRepr ) { pObj->pNextFan0 = pRepr; } -static inline void Ivy_ObjSetClassNodeNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pNextFan1 = pNext; } -static inline void Ivy_ObjSetNodeHashNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } -static inline void Ivy_ObjSetEquivListNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } -static inline void Ivy_ObjSetEquivListPrev( Ivy_Obj_t * pObj, Ivy_Obj_t * pPrev ) { pObj->pPrevFan1 = pPrev; } -static inline void Ivy_ObjSetFraig( Ivy_Obj_t * pObj, Ivy_Obj_t * pNode ) { pObj->pEquiv = pNode; } -static inline void Ivy_ObjSetSatNum( Ivy_Obj_t * pObj, int Num ) { pObj->pNextFan0 = (Ivy_Obj_t *)Num; } -static inline void Ivy_ObjSetFaninVec( Ivy_Obj_t * pObj, Vec_Ptr_t * vFanins ) { pObj->pNextFan1 = (Ivy_Obj_t *)vFanins; } - -static inline unsigned Ivy_ObjRandomSim() { return (rand() << 24) ^ (rand() << 12) ^ rand(); } - -// iterate through equivalence classes -#define Ivy_FraigForEachEquivClass( pList, pEnt ) \ - for ( pEnt = pList; \ - pEnt; \ - pEnt = Ivy_ObjEquivListNext(pEnt) ) -#define Ivy_FraigForEachEquivClassSafe( pList, pEnt, pEnt2 ) \ - for ( pEnt = pList, \ - pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL; \ - pEnt; \ - pEnt = pEnt2, \ - pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL ) -// iterate through nodes in one class -#define Ivy_FraigForEachClassNode( pClass, pEnt ) \ - for ( pEnt = pClass; \ - pEnt; \ - pEnt = Ivy_ObjClassNodeNext(pEnt) ) -// iterate through nodes in the hash table -#define Ivy_FraigForEachBinNode( pBin, pEnt ) \ - for ( pEnt = pBin; \ - pEnt; \ - pEnt = Ivy_ObjNodeHashNext(pEnt) ) - -static Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); -static Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); -static Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, sint64 nBTLimitGlobal, sint64 nInsLimitGlobal, sint64 * pnSatConfs, sint64 * pnSatInspects ); -static void Ivy_FraigPrint( Ivy_FraigMan_t * p ); -static void Ivy_FraigStop( Ivy_FraigMan_t * p ); -static void Ivy_FraigSimulate( Ivy_FraigMan_t * p ); -static void Ivy_FraigSweep( Ivy_FraigMan_t * p ); -static Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ); -static int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); -static int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ); -static void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); -static int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ); -static void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ); -static int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ); -static void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ); -static void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, int clk, int fVerbose ); -static int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ); - -static int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ); - -static sint64 s_nBTLimitGlobal = 0; -static sint64 s_nInsLimitGlobal = 0; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Sets the default solving parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ) -{ - memset( pParams, 0, sizeof(Ivy_FraigParams_t) ); - pParams->nSimWords = 32; // the number of words in the simulation info - pParams->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached - pParams->fPatScores = 0; // enables simulation pattern scoring - pParams->MaxScore = 25; // max score after which resimulation is used - pParams->fDoSparse = 1; // skips sparse functions -// pParams->dActConeRatio = 0.05; // the ratio of cone to be bumped -// pParams->dActConeBumpMax = 5.0; // the largest bump of activity - pParams->dActConeRatio = 0.3; // the ratio of cone to be bumped - pParams->dActConeBumpMax = 10.0; // the largest bump of activity - - pParams->nBTLimitNode = 100; // conflict limit at a node - pParams->nBTLimitMiter = 500000; // conflict limit at an output -// pParams->nBTLimitGlobal = 0; // conflict limit global -// pParams->nInsLimitGlobal = 0; // inspection limit global -} - -/**Function************************************************************* - - Synopsis [Performs combinational equivalence checking for the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ) -{ - Prove_Params_t * pParams = pPars; - Ivy_FraigParams_t Params, * pIvyParams = &Params; - Ivy_Man_t * pManAig, * pManTemp; - int RetValue, nIter, clk, timeStart = clock();//, Counter; - sint64 nSatConfs, nSatInspects; - - // start the network and parameters - pManAig = *ppManAig; - Ivy_FraigParamsDefault( pIvyParams ); - pIvyParams->fVerbose = pParams->fVerbose; - pIvyParams->fProve = 1; - - if ( pParams->fVerbose ) - { - printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", - pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); - printf( "Mitering = %d (%3.1f). Rewriting = %d (%3.1f). Fraiging = %d (%3.1f).\n", - pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, - pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, - pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti ); - printf( "Mitering last = %d.\n", - pParams->nMiteringLimitLast ); - } - - // if SAT only, solve without iteration - if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) - { - clk = clock(); - pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); - pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); - RetValue = Ivy_FraigMiterStatus( pManAig ); - Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); - *ppManAig = pManAig; - return RetValue; - } - - if ( Ivy_ManNodeNum(pManAig) < 500 ) - { - // run the first mitering - clk = clock(); - pIvyParams->nBTLimitMiter = pParams->nMiteringLimitStart / Ivy_ManPoNum(pManAig); - pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); - RetValue = Ivy_FraigMiterStatus( pManAig ); - Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); - if ( RetValue >= 0 ) - { - *ppManAig = pManAig; - return RetValue; - } - } - - // check the current resource limits - RetValue = -1; - for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) - { - if ( pParams->fVerbose ) - { - printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, - (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), - (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); - fflush( stdout ); - } - - // try rewriting - if ( pParams->fUseRewriting ) - { // bug in Ivy_NodeFindCutsAll() when leaves are identical! -/* - clk = clock(); - Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); - pManAig = Ivy_ManRwsat( pManAig, 0 ); - RetValue = Ivy_FraigMiterStatus( pManAig ); - Ivy_FraigMiterPrint( pManAig, "Rewriting ", clk, pParams->fVerbose ); -*/ - } - if ( RetValue >= 0 ) - break; - - // try fraiging followed by mitering - if ( pParams->fUseFraiging ) - { - clk = clock(); - pIvyParams->nBTLimitNode = (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)); - pIvyParams->nBTLimitMiter = (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)) / Ivy_ManPoNum(pManAig); - pManAig = Ivy_FraigPerform_int( pManTemp = pManAig, pIvyParams, pParams->nTotalBacktrackLimit, pParams->nTotalInspectLimit, &nSatConfs, &nSatInspects ); Ivy_ManStop( pManTemp ); - RetValue = Ivy_FraigMiterStatus( pManAig ); - Ivy_FraigMiterPrint( pManAig, "Fraiging ", clk, pParams->fVerbose ); - } - if ( RetValue >= 0 ) - break; - - // add to the number of backtracks and inspects - pParams->nTotalBacktracksMade += nSatConfs; - pParams->nTotalInspectsMade += nSatInspects; - // check if global resource limit is reached - if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || - (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) - { - printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); - *ppManAig = pManAig; - return -1; - } - } - - if ( RetValue < 0 ) - { - if ( pParams->fVerbose ) - { - printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); - fflush( stdout ); - } - clk = clock(); - pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); - if ( pParams->nTotalBacktrackLimit ) - s_nBTLimitGlobal = pParams->nTotalBacktrackLimit - pParams->nTotalBacktracksMade; - if ( pParams->nTotalInspectLimit ) - s_nInsLimitGlobal = pParams->nTotalInspectLimit - pParams->nTotalInspectsMade; - pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); - s_nBTLimitGlobal = 0; - s_nInsLimitGlobal = 0; - RetValue = Ivy_FraigMiterStatus( pManAig ); - Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); - // make sure that the sover never returns "undecided" when infinite resource limits are set - if( RetValue == -1 && pParams->nTotalInspectLimit == 0 && - pParams->nTotalBacktrackLimit == 0 ) - { - extern void Prove_ParamsPrint( Prove_Params_t * pParams ); - Prove_ParamsPrint( pParams ); - printf("ERROR: ABC has returned \"undecided\" in spite of no limits...\n"); - exit(1); - } - } - - // assign the model if it was proved by rewriting (const 1 miter) - if ( RetValue == 0 && pManAig->pData == NULL ) - { - pManAig->pData = ALLOC( int, Ivy_ManPiNum(pManAig) ); - memset( pManAig->pData, 0, sizeof(int) * Ivy_ManPiNum(pManAig) ); - } - *ppManAig = pManAig; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, sint64 nBTLimitGlobal, sint64 nInsLimitGlobal, sint64 * pnSatConfs, sint64 * pnSatInspects ) -{ - Ivy_FraigMan_t * p; - Ivy_Man_t * pManAigNew; - int clk; - if ( Ivy_ManNodeNum(pManAig) == 0 ) - return Ivy_ManDup(pManAig); -clk = clock(); - assert( Ivy_ManLatchNum(pManAig) == 0 ); - p = Ivy_FraigStart( pManAig, pParams ); - // set global limits - p->nBTLimitGlobal = nBTLimitGlobal; - p->nInsLimitGlobal = nInsLimitGlobal; - - Ivy_FraigSimulate( p ); - Ivy_FraigSweep( p ); - pManAigNew = p->pManFraig; -p->timeTotal = clock() - clk; - if ( pnSatConfs ) - *pnSatConfs = p->pSat? p->pSat->stats.conflicts : 0; - if ( pnSatInspects ) - *pnSatInspects = p->pSat? p->pSat->stats.inspects : 0; - Ivy_FraigStop( p ); - return pManAigNew; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) -{ - Ivy_FraigMan_t * p; - Ivy_Man_t * pManAigNew; - int clk; - if ( Ivy_ManNodeNum(pManAig) == 0 ) - return Ivy_ManDup(pManAig); -clk = clock(); - assert( Ivy_ManLatchNum(pManAig) == 0 ); - p = Ivy_FraigStart( pManAig, pParams ); - Ivy_FraigSimulate( p ); - Ivy_FraigSweep( p ); - pManAigNew = p->pManFraig; -p->timeTotal = clock() - clk; - Ivy_FraigStop( p ); - return pManAigNew; -} - -/**Function************************************************************* - - Synopsis [Applies brute-force SAT to the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) -{ - Ivy_FraigMan_t * p; - Ivy_Man_t * pManAigNew; - Ivy_Obj_t * pObj; - int i, clk; -clk = clock(); - assert( Ivy_ManLatchNum(pManAig) == 0 ); - p = Ivy_FraigStartSimple( pManAig, pParams ); - // set global limits - p->nBTLimitGlobal = s_nBTLimitGlobal; - p->nInsLimitGlobal = s_nInsLimitGlobal; - // duplicate internal nodes - Ivy_ManForEachNode( p->pManAig, pObj, i ) - pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); - // try to prove each output of the miter - Ivy_FraigMiterProve( p ); - // add the POs - Ivy_ManForEachPo( p->pManAig, pObj, i ) - Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); - // clean the new manager - Ivy_ManForEachObj( p->pManFraig, pObj, i ) - { - if ( Ivy_ObjFaninVec(pObj) ) - Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); - pObj->pNextFan0 = pObj->pNextFan1 = NULL; - } - // remove dangling nodes - Ivy_ManCleanup( p->pManFraig ); - pManAigNew = p->pManFraig; -p->timeTotal = clock() - clk; - -//printf( "Final nodes = %6d. ", Ivy_ManNodeNum(pManAigNew) ); -//PRT( "Time", p->timeTotal ); - Ivy_FraigStop( p ); - return pManAigNew; -} - -/**Function************************************************************* - - Synopsis [Starts the fraiging manager without simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) -{ - Ivy_FraigMan_t * p; - // allocat the fraiging manager - p = ALLOC( Ivy_FraigMan_t, 1 ); - memset( p, 0, sizeof(Ivy_FraigMan_t) ); - p->pParams = pParams; - p->pManAig = pManAig; - p->pManFraig = Ivy_ManStartFrom( pManAig ); - p->vPiVars = Vec_PtrAlloc( 100 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Starts the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) -{ - Ivy_FraigMan_t * p; - Ivy_FraigSim_t * pSims; - Ivy_Obj_t * pObj; - int i, k, EntrySize; - // clean the fanout representation - Ivy_ManForEachObj( pManAig, pObj, i ) -// pObj->pEquiv = pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; - assert( !pObj->pEquiv && !pObj->pFanout ); - // allocat the fraiging manager - p = ALLOC( Ivy_FraigMan_t, 1 ); - memset( p, 0, sizeof(Ivy_FraigMan_t) ); - p->pParams = pParams; - p->pManAig = pManAig; - p->pManFraig = Ivy_ManStartFrom( pManAig ); - // allocate simulation info - p->nSimWords = pParams->nSimWords; -// p->pSimWords = ALLOC( unsigned, Ivy_ManObjNum(pManAig) * p->nSimWords ); - EntrySize = sizeof(Ivy_FraigSim_t) + sizeof(unsigned) * p->nSimWords; - p->pSimWords = (char *)malloc( Ivy_ManObjNum(pManAig) * EntrySize ); - memset( p->pSimWords, 0, EntrySize ); - k = 0; - Ivy_ManForEachObj( pManAig, pObj, i ) - { - pSims = (Ivy_FraigSim_t *)(p->pSimWords + EntrySize * k++); - pSims->pNext = NULL; - if ( Ivy_ObjIsNode(pObj) ) - { - if ( p->pSimStart == NULL ) - p->pSimStart = pSims; - else - ((Ivy_FraigSim_t *)(p->pSimWords + EntrySize * (k-2)))->pNext = pSims; - pSims->pFanin0 = Ivy_ObjSim( Ivy_ObjFanin0(pObj) ); - pSims->pFanin1 = Ivy_ObjSim( Ivy_ObjFanin1(pObj) ); - pSims->Type = (Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) << 2) | (Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)) << 1) | pObj->fPhase; - } - else - { - pSims->pFanin0 = NULL; - pSims->pFanin1 = NULL; - pSims->Type = 0; - } - Ivy_ObjSetSim( pObj, pSims ); - } - assert( k == Ivy_ManObjNum(pManAig) ); - // allocate storage for sim pattern - p->nPatWords = Ivy_BitWordNum( Ivy_ManPiNum(pManAig) ); - p->pPatWords = ALLOC( unsigned, p->nPatWords ); - p->pPatScores = ALLOC( int, 32 * p->nSimWords ); - p->vPiVars = Vec_PtrAlloc( 100 ); - // set random number generator - srand( 0xABCABC ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigStop( Ivy_FraigMan_t * p ) -{ - if ( p->pParams->fVerbose ) - Ivy_FraigPrint( p ); - if ( p->vPiVars ) Vec_PtrFree( p->vPiVars ); - if ( p->pSat ) sat_solver_delete( p->pSat ); - FREE( p->pPatScores ); - FREE( p->pPatWords ); - FREE( p->pSimWords ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Prints stats for the fraiging manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigPrint( Ivy_FraigMan_t * p ) -{ - double nMemory; - nMemory = (double)Ivy_ManObjNum(p->pManAig)*p->nSimWords*sizeof(unsigned)/(1<<20); - printf( "SimWords = %d. Rounds = %d. Mem = %0.2f Mb. ", p->nSimWords, p->nSimRounds, nMemory ); - printf( "Classes: Beg = %d. End = %d.\n", p->nClassesBeg, p->nClassesEnd ); - printf( "Limits: BTNode = %d. BTMiter = %d.\n", p->pParams->nBTLimitNode, p->pParams->nBTLimitMiter ); - printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", - p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->nClassesZero ); - printf( "Final = %d. Miter = %d. Total = %d. Mux = %d. (Exor = %d.) SatVars = %d.\n", - Ivy_ManNodeNum(p->pManFraig), p->nNodesMiter, Ivy_ManNodeNum(p->pManAig), 0, 0, p->nSatVars ); - if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat ); - PRT( "AIG simulation ", p->timeSim ); - PRT( "AIG traversal ", p->timeTrav ); - PRT( "SAT solving ", p->timeSat ); - PRT( " Unsat ", p->timeSatUnsat ); - PRT( " Sat ", p->timeSatSat ); - PRT( " Fail ", p->timeSatFail ); - PRT( "Class refining ", p->timeRef ); - PRT( "TOTAL RUNTIME ", p->timeTotal ); - if ( p->time1 ) { PRT( "time1 ", p->time1 ); } -} - - - -/**Function************************************************************* - - Synopsis [Assigns random patterns to the PI node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeAssignRandom( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_FraigSim_t * pSims; - int i; - assert( Ivy_ObjIsPi(pObj) ); - pSims = Ivy_ObjSim(pObj); - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = Ivy_ObjRandomSim(); -} - -/**Function************************************************************* - - Synopsis [Assigns constant patterns to the PI node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeAssignConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int fConst1 ) -{ - Ivy_FraigSim_t * pSims; - int i; - assert( Ivy_ObjIsPi(pObj) ); - pSims = Ivy_ObjSim(pObj); - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = fConst1? ~(unsigned)0 : 0; -} - -/**Function************************************************************* - - Synopsis [Assings random simulation info for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAssignRandom( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - Ivy_ManForEachPi( p->pManAig, pObj, i ) - Ivy_NodeAssignRandom( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Assings distance-1 simulation info for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAssignDist1( Ivy_FraigMan_t * p, unsigned * pPat ) -{ - Ivy_Obj_t * pObj; - int i, Limit; - Ivy_ManForEachPi( p->pManAig, pObj, i ) - { - Ivy_NodeAssignConst( p, pObj, Ivy_InfoHasBit(pPat, i) ); -// printf( "%d", Ivy_InfoHasBit(pPat, i) ); - } -// printf( "\n" ); - - Limit = IVY_MIN( Ivy_ManPiNum(p->pManAig), p->nSimWords * 32 - 1 ); - for ( i = 0; i < Limit; i++ ) - Ivy_InfoXorBit( Ivy_ObjSim( Ivy_ManPi(p->pManAig,i) )->pData, i+1 ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeHasZeroSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_FraigSim_t * pSims; - int i; - pSims = Ivy_ObjSim(pObj); - for ( i = 0; i < p->nSimWords; i++ ) - if ( pSims->pData[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation info is composed of all zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeComplementSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_FraigSim_t * pSims; - int i; - pSims = Ivy_ObjSim(pObj); - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = ~pSims->pData[i]; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if simulation infos are equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCompareSims( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) -{ - Ivy_FraigSim_t * pSims0, * pSims1; - int i; - pSims0 = Ivy_ObjSim(pObj0); - pSims1 = Ivy_ObjSim(pObj1); - for ( i = 0; i < p->nSimWords; i++ ) - if ( pSims0->pData[i] != pSims1->pData[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeSimulateSim( Ivy_FraigMan_t * p, Ivy_FraigSim_t * pSims ) -{ - unsigned * pData, * pData0, * pData1; - int i; - pData = pSims->pData; - pData0 = pSims->pFanin0->pData; - pData1 = pSims->pFanin1->pData; - switch( pSims->Type ) - { - case 0: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (pData0[i] & pData1[i]); - break; - case 1: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = ~(pData0[i] & pData1[i]); - break; - case 2: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (pData0[i] & ~pData1[i]); - break; - case 3: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (~pData0[i] | pData1[i]); - break; - case 4: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (~pData0[i] & pData1[i]); - break; - case 5: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (pData0[i] | ~pData1[i]); - break; - case 6: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = ~(pData0[i] | pData1[i]); - break; - case 7: - for ( i = 0; i < p->nSimWords; i++ ) - pData[i] = (pData0[i] | pData1[i]); - break; - } -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeSimulate( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_FraigSim_t * pSims, * pSims0, * pSims1; - int fCompl, fCompl0, fCompl1, i; - assert( !Ivy_IsComplement(pObj) ); - // get hold of the simulation information - pSims = Ivy_ObjSim(pObj); - pSims0 = Ivy_ObjSim(Ivy_ObjFanin0(pObj)); - pSims1 = Ivy_ObjSim(Ivy_ObjFanin1(pObj)); - // get complemented attributes of the children using their random info - fCompl = pObj->fPhase; - fCompl0 = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); - fCompl1 = Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); - // simulate - if ( fCompl0 && fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (pSims0->pData[i] | pSims1->pData[i]); - else - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = ~(pSims0->pData[i] | pSims1->pData[i]); - } - else if ( fCompl0 && !fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (pSims0->pData[i] | ~pSims1->pData[i]); - else - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (~pSims0->pData[i] & pSims1->pData[i]); - } - else if ( !fCompl0 && fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (~pSims0->pData[i] | pSims1->pData[i]); - else - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (pSims0->pData[i] & ~pSims1->pData[i]); - } - else // if ( !fCompl0 && !fCompl1 ) - { - if ( fCompl ) - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = ~(pSims0->pData[i] & pSims1->pData[i]); - else - for ( i = 0; i < p->nSimWords; i++ ) - pSims->pData[i] = (pSims0->pData[i] & pSims1->pData[i]); - } -} - -/**Function************************************************************* - - Synopsis [Computes hash value using simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_NodeHash( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) -{ - static int s_FPrimes[128] = { - 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, - 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, - 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, - 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, - 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, - 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, - 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, - 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, - 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, - 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, - 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, - 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, - 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 - }; - Ivy_FraigSim_t * pSims; - unsigned uHash; - int i; - assert( p->nSimWords <= 128 ); - uHash = 0; - pSims = Ivy_ObjSim(pObj); - for ( i = 0; i < p->nSimWords; i++ ) - uHash ^= pSims->pData[i] * s_FPrimes[i]; - return uHash; -} - -/**Function************************************************************* - - Synopsis [Simulates AIG manager.] - - Description [Assumes that the PI simulation info is attached.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSimulateOne( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i, clk; -clk = clock(); - Ivy_ManForEachNode( p->pManAig, pObj, i ) - { - Ivy_NodeSimulate( p, pObj ); -/* - if ( Ivy_ObjFraig(pObj) == NULL ) - printf( "%3d --- -- %d : ", pObj->Id, pObj->fPhase ); - else - printf( "%3d %3d %2d %d : ", pObj->Id, Ivy_Regular(Ivy_ObjFraig(pObj))->Id, Ivy_ObjSatNum(Ivy_Regular(Ivy_ObjFraig(pObj))), pObj->fPhase ); - Extra_PrintBinary( stdout, Ivy_ObjSim(pObj), 30 ); - printf( "\n" ); -*/ - } -p->timeSim += clock() - clk; -p->nSimRounds++; -} - -/**Function************************************************************* - - Synopsis [Simulates AIG manager.] - - Description [Assumes that the PI simulation info is attached.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSimulateOneSim( Ivy_FraigMan_t * p ) -{ - Ivy_FraigSim_t * pSims; - int clk; -clk = clock(); - for ( pSims = p->pSimStart; pSims; pSims = pSims->pNext ) - Ivy_NodeSimulateSim( p, pSims ); -p->timeSim += clock() - clk; -p->nSimRounds++; -} - -/**Function************************************************************* - - Synopsis [Adds one node to the equivalence class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeAddToClass( Ivy_Obj_t * pClass, Ivy_Obj_t * pObj ) -{ - if ( Ivy_ObjClassNodeNext(pClass) == NULL ) - Ivy_ObjSetClassNodeNext( pClass, pObj ); - else - Ivy_ObjSetClassNodeNext( Ivy_ObjClassNodeLast(pClass), pObj ); - Ivy_ObjSetClassNodeLast( pClass, pObj ); - Ivy_ObjSetClassNodeRepr( pObj, pClass ); - Ivy_ObjSetClassNodeNext( pObj, NULL ); -} - -/**Function************************************************************* - - Synopsis [Adds equivalence class to the list of classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAddClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) -{ - if ( pList->pHead == NULL ) - { - pList->pHead = pClass; - pList->pTail = pClass; - Ivy_ObjSetEquivListPrev( pClass, NULL ); - Ivy_ObjSetEquivListNext( pClass, NULL ); - } - else - { - Ivy_ObjSetEquivListNext( pList->pTail, pClass ); - Ivy_ObjSetEquivListPrev( pClass, pList->pTail ); - Ivy_ObjSetEquivListNext( pClass, NULL ); - pList->pTail = pClass; - } - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [Updates the list of classes after base class has split.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigInsertClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pBase, Ivy_Obj_t * pClass ) -{ - Ivy_ObjSetEquivListPrev( pClass, pBase ); - Ivy_ObjSetEquivListNext( pClass, Ivy_ObjEquivListNext(pBase) ); - if ( Ivy_ObjEquivListNext(pBase) ) - Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pBase), pClass ); - Ivy_ObjSetEquivListNext( pBase, pClass ); - if ( pList->pTail == pBase ) - pList->pTail = pClass; - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [Removes equivalence class from the list of classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigRemoveClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) -{ - if ( pList->pHead == pClass ) - pList->pHead = Ivy_ObjEquivListNext(pClass); - if ( pList->pTail == pClass ) - pList->pTail = Ivy_ObjEquivListPrev(pClass); - if ( Ivy_ObjEquivListPrev(pClass) ) - Ivy_ObjSetEquivListNext( Ivy_ObjEquivListPrev(pClass), Ivy_ObjEquivListNext(pClass) ); - if ( Ivy_ObjEquivListNext(pClass) ) - Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pClass), Ivy_ObjEquivListPrev(pClass) ); - Ivy_ObjSetEquivListNext( pClass, NULL ); - Ivy_ObjSetEquivListPrev( pClass, NULL ); - pClass->fMarkA = 0; - pList->nItems--; -} - -/**Function************************************************************* - - Synopsis [Count the number of pairs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigCountPairsClasses( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pClass, * pNode; - int nPairs = 0, nNodes; - return nPairs; - - Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) - { - nNodes = 0; - Ivy_FraigForEachClassNode( pClass, pNode ) - nNodes++; - nPairs += nNodes * (nNodes - 1) / 2; - } - return nPairs; -} - -/**Function************************************************************* - - Synopsis [Creates initial simulation classes.] - - Description [Assumes that simulation info is assigned.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigCreateClasses( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t ** pTable; - Ivy_Obj_t * pObj, * pConst1, * pBin, * pEntry; - int i, nTableSize; - unsigned Hash; - pConst1 = Ivy_ManConst1(p->pManAig); - // allocate the table - nTableSize = Ivy_ManObjNum(p->pManAig) / 2 + 13; - pTable = ALLOC( Ivy_Obj_t *, nTableSize ); - memset( pTable, 0, sizeof(Ivy_Obj_t *) * nTableSize ); - // collect nodes into the table - Ivy_ManForEachObj( p->pManAig, pObj, i ) - { - if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) - continue; - Hash = Ivy_NodeHash( p, pObj ); - if ( Hash == 0 && Ivy_NodeHasZeroSim( p, pObj ) ) - { - Ivy_NodeAddToClass( pConst1, pObj ); - continue; - } - // add the node to the table - pBin = pTable[Hash % nTableSize]; - Ivy_FraigForEachBinNode( pBin, pEntry ) - if ( Ivy_NodeCompareSims( p, pEntry, pObj ) ) - { - Ivy_NodeAddToClass( pEntry, pObj ); - break; - } - // check if the entry was added - if ( pEntry ) - continue; - Ivy_ObjSetNodeHashNext( pObj, pBin ); - pTable[Hash % nTableSize] = pObj; - } - // collect non-trivial classes - assert( p->lClasses.pHead == NULL ); - Ivy_ManForEachObj( p->pManAig, pObj, i ) - { - if ( !Ivy_ObjIsConst1(pObj) && !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) - continue; - Ivy_ObjSetNodeHashNext( pObj, NULL ); - if ( Ivy_ObjClassNodeRepr(pObj) == NULL ) - { - assert( Ivy_ObjClassNodeNext(pObj) == NULL ); - continue; - } - // recognize the head of the class - if ( Ivy_ObjClassNodeNext( Ivy_ObjClassNodeRepr(pObj) ) != NULL ) - continue; - // clean the class representative and add it to the list - Ivy_ObjSetClassNodeRepr( pObj, NULL ); - Ivy_FraigAddClass( &p->lClasses, pObj ); - } - // free the table - free( pTable ); -} - -/**Function************************************************************* - - Synopsis [Recursively refines the class after simulation.] - - Description [Returns 1 if the class has changed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigRefineClass_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass ) -{ - Ivy_Obj_t * pClassNew, * pListOld, * pListNew, * pNode; - int RetValue = 0; - // check if there is refinement - pListOld = pClass; - Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClass), pClassNew ) - { - if ( !Ivy_NodeCompareSims(p, pClass, pClassNew) ) - { - if ( p->pParams->fPatScores ) - Ivy_FraigAddToPatScores( p, pClass, pClassNew ); - break; - } - pListOld = pClassNew; - } - if ( pClassNew == NULL ) - return 0; - // set representative of the new class - Ivy_ObjSetClassNodeRepr( pClassNew, NULL ); - // start the new list - pListNew = pClassNew; - // go through the remaining nodes and sort them into two groups: - // (1) matches of the old node; (2) non-matches of the old node - Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClassNew), pNode ) - if ( Ivy_NodeCompareSims( p, pClass, pNode ) ) - { - Ivy_ObjSetClassNodeNext( pListOld, pNode ); - pListOld = pNode; - } - else - { - Ivy_ObjSetClassNodeNext( pListNew, pNode ); - Ivy_ObjSetClassNodeRepr( pNode, pClassNew ); - pListNew = pNode; - } - // finish both lists - Ivy_ObjSetClassNodeNext( pListNew, NULL ); - Ivy_ObjSetClassNodeNext( pListOld, NULL ); - // update the list of classes - Ivy_FraigInsertClass( &p->lClasses, pClass, pClassNew ); - // if the old class is trivial, remove it - if ( Ivy_ObjClassNodeNext(pClass) == NULL ) - Ivy_FraigRemoveClass( &p->lClasses, pClass ); - // if the new class is trivial, remove it; otherwise, try to refine it - if ( Ivy_ObjClassNodeNext(pClassNew) == NULL ) - Ivy_FraigRemoveClass( &p->lClasses, pClassNew ); - else - RetValue = Ivy_FraigRefineClass_rec( p, pClassNew ); - return RetValue + 1; -} - -/**Function************************************************************* - - Synopsis [Creates the counter-example from the successful pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigCheckOutputSimsSavePattern( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_FraigSim_t * pSims; - int i, k, BestPat, * pModel; - // find the word of the pattern - pSims = Ivy_ObjSim(pObj); - for ( i = 0; i < p->nSimWords; i++ ) - if ( pSims->pData[i] ) - break; - assert( i < p->nSimWords ); - // find the bit of the pattern - for ( k = 0; k < 32; k++ ) - if ( pSims->pData[i] & (1 << k) ) - break; - assert( k < 32 ); - // determine the best pattern - BestPat = i * 32 + k; - // fill in the counter-example data - pModel = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); - Ivy_ManForEachPi( p->pManAig, pObj, i ) - { - pModel[i] = Ivy_InfoHasBit(Ivy_ObjSim(pObj)->pData, BestPat); -// printf( "%d", pModel[i] ); - } -// printf( "\n" ); - // set the model - assert( p->pManFraig->pData == NULL ); - p->pManFraig->pData = pModel; - return; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the one of the output is already non-constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigCheckOutputSims( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - // make sure the reference simulation pattern does not detect the bug - pObj = Ivy_ManPo( p->pManAig, 0 ); - assert( Ivy_ObjFanin0(pObj)->fPhase == (unsigned)Ivy_ObjFaninC0(pObj) ); // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) == 0 - Ivy_ManForEachPo( p->pManAig, pObj, i ) - { - // complement simulation info -// if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) -// Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); - // check - if ( !Ivy_NodeHasZeroSim( p, Ivy_ObjFanin0(pObj) ) ) - { - // create the counter-example from this pattern - Ivy_FraigCheckOutputSimsSavePattern( p, Ivy_ObjFanin0(pObj) ); - return 1; - } - // complement simulation info -// if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) -// Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Refines the classes after simulation.] - - Description [Assumes that simulation info is assigned. Returns the - number of classes refined.] - - SideEffects [Large equivalence class of constant 0 may cause problems.] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigRefineClasses( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pClass, * pClass2; - int clk, RetValue, Counter = 0; - // check if some outputs already became non-constant - // this is a special case when computation can be stopped!!! - if ( p->pParams->fProve ) - Ivy_FraigCheckOutputSims( p ); - if ( p->pManFraig->pData ) - return 0; - // refine the classed -clk = clock(); - Ivy_FraigForEachEquivClassSafe( p->lClasses.pHead, pClass, pClass2 ) - { - if ( pClass->fMarkA ) - continue; - RetValue = Ivy_FraigRefineClass_rec( p, pClass ); - Counter += ( RetValue > 0 ); -//if ( Ivy_ObjIsConst1(pClass) ) -//printf( "%d ", RetValue ); -//if ( Ivy_ObjIsConst1(pClass) ) -// p->time1 += clock() - clk; - } -p->timeRef += clock() - clk; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Print the class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigPrintClass( Ivy_Obj_t * pClass ) -{ - Ivy_Obj_t * pObj; - printf( "Class {" ); - Ivy_FraigForEachClassNode( pClass, pObj ) - printf( " %d(%d)%c", pObj->Id, pObj->Level, pObj->fPhase? '+' : '-' ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [Count the number of elements in the class.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigCountClassNodes( Ivy_Obj_t * pClass ) -{ - Ivy_Obj_t * pObj; - int Counter = 0; - Ivy_FraigForEachClassNode( pClass, pObj ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Prints simulation classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigPrintSimClasses( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pClass; - Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) - { -// Ivy_FraigPrintClass( pClass ); - printf( "%d ", Ivy_FraigCountClassNodes( pClass ) ); - } -// printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Generated const 0 pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSavePattern0( Ivy_FraigMan_t * p ) -{ - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); -} - -/**Function************************************************************* - - Synopsis [[Generated const 1 pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSavePattern1( Ivy_FraigMan_t * p ) -{ - memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords ); -} - -/**Function************************************************************* - - Synopsis [Generates the counter-example satisfying the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ) -{ - int * pModel; - Ivy_Obj_t * pObj; - int i; - pModel = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); - Ivy_ManForEachPi( p->pManFraig, pObj, i ) - pModel[i] = ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ); - return pModel; -} - -/**Function************************************************************* - - Synopsis [Copy pattern from the solver into the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSavePattern( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); - Ivy_ManForEachPi( p->pManFraig, pObj, i ) -// Vec_PtrForEachEntry( p->vPiVars, pObj, i ) - if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) - Ivy_InfoSetBit( p->pPatWords, i ); -// Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); -} - -/**Function************************************************************* - - Synopsis [Copy pattern from the solver into the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSavePattern2( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); -// Ivy_ManForEachPi( p->pManFraig, pObj, i ) - Vec_PtrForEachEntry( p->vPiVars, pObj, i ) - if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) -// Ivy_InfoSetBit( p->pPatWords, i ); - Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); -} - -/**Function************************************************************* - - Synopsis [Copy pattern from the solver into the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSavePattern3( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - for ( i = 0; i < p->nPatWords; i++ ) - p->pPatWords[i] = Ivy_ObjRandomSim(); - Vec_PtrForEachEntry( p->vPiVars, pObj, i ) - if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ (p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True) ) - Ivy_InfoXorBit( p->pPatWords, pObj->Id - 1 ); -} - - -/**Function************************************************************* - - Synopsis [Performs simulation of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSimulate( Ivy_FraigMan_t * p ) -{ - int nChanges, nClasses; - // start the classes - Ivy_FraigAssignRandom( p ); - Ivy_FraigSimulateOne( p ); - Ivy_FraigCreateClasses( p ); -//printf( "Starting classes = %5d. Pairs = %6d.\n", p->lClasses.nItems, Ivy_FraigCountPairsClasses(p) ); - // refine classes by walking 0/1 patterns - Ivy_FraigSavePattern0( p ); - Ivy_FraigAssignDist1( p, p->pPatWords ); - Ivy_FraigSimulateOne( p ); - nChanges = Ivy_FraigRefineClasses( p ); - if ( p->pManFraig->pData ) - return; -//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); - Ivy_FraigSavePattern1( p ); - Ivy_FraigAssignDist1( p, p->pPatWords ); - Ivy_FraigSimulateOne( p ); - nChanges = Ivy_FraigRefineClasses( p ); - if ( p->pManFraig->pData ) - return; -//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); - // refine classes by random simulation - do { - Ivy_FraigAssignRandom( p ); - Ivy_FraigSimulateOne( p ); - nClasses = p->lClasses.nItems; - nChanges = Ivy_FraigRefineClasses( p ); - if ( p->pManFraig->pData ) - return; -//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); - } while ( (double)nChanges / nClasses > p->pParams->dSimSatur ); -// Ivy_FraigPrintSimClasses( p ); -} - - - -/**Function************************************************************* - - Synopsis [Cleans pattern scores.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigCleanPatScores( Ivy_FraigMan_t * p ) -{ - int i, nLimit = p->nSimWords * 32; - for ( i = 0; i < nLimit; i++ ) - p->pPatScores[i] = 0; -} - -/**Function************************************************************* - - Synopsis [Adds to pattern scores.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ) -{ - Ivy_FraigSim_t * pSims0, * pSims1; - unsigned uDiff; - int i, w; - // get hold of the simulation information - pSims0 = Ivy_ObjSim(pClass); - pSims1 = Ivy_ObjSim(pClassNew); - // iterate through the differences and record the score - for ( w = 0; w < p->nSimWords; w++ ) - { - uDiff = pSims0->pData[w] ^ pSims1->pData[w]; - if ( uDiff == 0 ) - continue; - for ( i = 0; i < 32; i++ ) - if ( uDiff & ( 1 << i ) ) - p->pPatScores[w*32+i]++; - } -} - -/**Function************************************************************* - - Synopsis [Selects the best pattern.] - - Description [Returns 1 if such pattern is found.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigSelectBestPat( Ivy_FraigMan_t * p ) -{ - Ivy_FraigSim_t * pSims; - Ivy_Obj_t * pObj; - int i, nLimit = p->nSimWords * 32, MaxScore = 0, BestPat = -1; - for ( i = 1; i < nLimit; i++ ) - { - if ( MaxScore < p->pPatScores[i] ) - { - MaxScore = p->pPatScores[i]; - BestPat = i; - } - } - if ( MaxScore == 0 ) - return 0; -// if ( MaxScore > p->pParams->MaxScore ) -// printf( "Max score is %3d. ", MaxScore ); - // copy the best pattern into the selected pattern - memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); - Ivy_ManForEachPi( p->pManAig, pObj, i ) - { - pSims = Ivy_ObjSim(pObj); - if ( Ivy_InfoHasBit(pSims->pData, BestPat) ) - Ivy_InfoSetBit(p->pPatWords, i); - } - return MaxScore; -} - -/**Function************************************************************* - - Synopsis [Resimulates fraiging manager after finding a counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigResimulate( Ivy_FraigMan_t * p ) -{ - int nChanges; - Ivy_FraigAssignDist1( p, p->pPatWords ); - Ivy_FraigSimulateOne( p ); - if ( p->pParams->fPatScores ) - Ivy_FraigCleanPatScores( p ); - nChanges = Ivy_FraigRefineClasses( p ); - if ( p->pManFraig->pData ) - return; - if ( nChanges < 1 ) - printf( "Error: A counter-example did not refine classes!\n" ); - assert( nChanges >= 1 ); -//printf( "Refined classes! = %5d. Changes = %4d.\n", p->lClasses.nItems, nChanges ); - if ( !p->pParams->fPatScores ) - return; - - // perform additional simulation using dist1 patterns derived from successful patterns - while ( Ivy_FraigSelectBestPat(p) > p->pParams->MaxScore ) - { - Ivy_FraigAssignDist1( p, p->pPatWords ); - Ivy_FraigSimulateOne( p ); - Ivy_FraigCleanPatScores( p ); - nChanges = Ivy_FraigRefineClasses( p ); - if ( p->pManFraig->pData ) - return; -//printf( "Refined class!!! = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); - if ( nChanges == 0 ) - break; - } -} - - -/**Function************************************************************* - - Synopsis [Prints the status of the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, int clk, int fVerbose ) -{ - if ( !fVerbose ) - return; - printf( "Nodes = %7d. Levels = %4d. ", Ivy_ManNodeNum(pNtk), Ivy_ManLevels(pNtk) ); - PRT( pString, clock() - clk ); -} - -/**Function************************************************************* - - Synopsis [Reports the status of the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ) -{ - Ivy_Obj_t * pObj, * pObjNew; - int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; - if ( pMan->pData ) - return 0; - Ivy_ManForEachPo( pMan, pObj, i ) - { - pObjNew = Ivy_ObjChild0(pObj); - // check if the output is constant 1 - if ( pObjNew == pMan->pConst1 ) - { - CountNonConst0++; - continue; - } - // check if the output is constant 0 - if ( pObjNew == Ivy_Not(pMan->pConst1) ) - { - CountConst0++; - continue; - } - // check if the output can be constant 0 - if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) - { - CountNonConst0++; - continue; - } - CountUndecided++; - } -/* - if ( p->pParams->fVerbose ) - { - printf( "Miter has %d outputs. ", Ivy_ManPoNum(p->pManAig) ); - printf( "Const0 = %d. ", CountConst0 ); - printf( "NonConst0 = %d. ", CountNonConst0 ); - printf( "Undecided = %d. ", CountUndecided ); - printf( "\n" ); - } -*/ - if ( CountNonConst0 ) - return 0; - if ( CountUndecided ) - return -1; - return 1; -} - -/**Function************************************************************* - - Synopsis [Tries to prove each output of the miter until encountering a sat output.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj, * pObjNew; - int i, RetValue, clk = clock(); - int fVerbose = 0; - Ivy_ManForEachPo( p->pManAig, pObj, i ) - { - if ( i && fVerbose ) - { - PRT( "Time", clock() -clk ); - } - pObjNew = Ivy_ObjChild0Equiv(pObj); - // check if the output is constant 1 - if ( pObjNew == p->pManFraig->pConst1 ) - { - if ( fVerbose ) - printf( "Output %2d (out of %2d) is constant 1. ", i, Ivy_ManPoNum(p->pManAig) ); - // assing constant 0 model - p->pManFraig->pData = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); - memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); - break; - } - // check if the output is constant 0 - if ( pObjNew == Ivy_Not(p->pManFraig->pConst1) ) - { - if ( fVerbose ) - printf( "Output %2d (out of %2d) is already constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); - continue; - } - // check if the output can be constant 0 - if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) - { - if ( fVerbose ) - printf( "Output %2d (out of %2d) cannot be constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); - // assing constant 0 model - p->pManFraig->pData = ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); - memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); - break; - } -/* - // check the representative of this node - pRepr = Ivy_ObjClassNodeRepr(Ivy_ObjFanin0(pObj)); - if ( Ivy_Regular(pRepr) != p->pManAig->pConst1 ) - printf( "Representative is not constant 1.\n" ); - else - printf( "Representative is constant 1.\n" ); -*/ - // try to prove the output constant 0 - RetValue = Ivy_FraigNodeIsConst( p, Ivy_Regular(pObjNew) ); - if ( RetValue == 1 ) // proved equivalent - { - if ( fVerbose ) - printf( "Output %2d (out of %2d) was proved constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); - // set the constant miter - Ivy_ObjFanin0(pObj)->pEquiv = Ivy_NotCond( p->pManFraig->pConst1, !Ivy_ObjFaninC0(pObj) ); - continue; - } - if ( RetValue == -1 ) // failed - { - if ( fVerbose ) - printf( "Output %2d (out of %2d) has timed out at %d backtracks. ", i, Ivy_ManPoNum(p->pManAig), p->pParams->nBTLimitMiter ); - continue; - } - // proved satisfiable - if ( fVerbose ) - printf( "Output %2d (out of %2d) was proved NOT a constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); - // create the model - p->pManFraig->pData = Ivy_FraigCreateModel(p); - break; - } - if ( fVerbose ) - { - PRT( "Time", clock() -clk ); - } -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigSweep( Ivy_FraigMan_t * p ) -{ - Ivy_Obj_t * pObj;//, * pTemp; - int i, k = 0; -p->nClassesZero = p->lClasses.pHead? (Ivy_ObjIsConst1(p->lClasses.pHead) ? Ivy_FraigCountClassNodes(p->lClasses.pHead) : 0) : 0; -p->nClassesBeg = p->lClasses.nItems; - // duplicate internal nodes - p->pProgress = Extra_ProgressBarStart( stdout, Ivy_ManNodeNum(p->pManAig) ); - Ivy_ManForEachNode( p->pManAig, pObj, i ) - { - Extra_ProgressBarUpdate( p->pProgress, k++, NULL ); - // default to simple strashing if simulation detected a counter-example for a PO - if ( p->pManFraig->pData ) - pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); - else - pObj->pEquiv = Ivy_FraigAnd( p, pObj ); - assert( pObj->pEquiv != NULL ); -// pTemp = Ivy_Regular(pObj->pEquiv); -// assert( Ivy_Regular(pObj->pEquiv)->Type ); - } - Extra_ProgressBarStop( p->pProgress ); -p->nClassesEnd = p->lClasses.nItems; - // try to prove the outputs of the miter - p->nNodesMiter = Ivy_ManNodeNum(p->pManFraig); -// Ivy_FraigMiterStatus( p->pManFraig ); - if ( p->pParams->fProve && p->pManFraig->pData == NULL ) - Ivy_FraigMiterProve( p ); - // add the POs - Ivy_ManForEachPo( p->pManAig, pObj, i ) - Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); - // clean the old manager - Ivy_ManForEachObj( p->pManAig, pObj, i ) - pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; - // clean the new manager - Ivy_ManForEachObj( p->pManFraig, pObj, i ) - { - if ( Ivy_ObjFaninVec(pObj) ) - Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); - pObj->pNextFan0 = pObj->pNextFan1 = NULL; - } - // remove dangling nodes - Ivy_ManCleanup( p->pManFraig ); - // clean up the class marks - Ivy_FraigForEachEquivClass( p->lClasses.pHead, pObj ) - pObj->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Performs fraiging for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ) -{ - Ivy_Obj_t * pObjNew, * pFanin0New, * pFanin1New, * pObjReprNew; - int RetValue; - // get the fraiged fanins - pFanin0New = Ivy_ObjChild0Equiv(pObjOld); - pFanin1New = Ivy_ObjChild1Equiv(pObjOld); - // get the candidate fraig node - pObjNew = Ivy_And( p->pManFraig, pFanin0New, pFanin1New ); - // get representative of this class - if ( Ivy_ObjClassNodeRepr(pObjOld) == NULL || // this is a unique node - (!p->pParams->fDoSparse && Ivy_ObjClassNodeRepr(pObjOld) == p->pManAig->pConst1) ) // this is a sparse node - { - assert( Ivy_Regular(pFanin0New) != Ivy_Regular(pFanin1New) ); - assert( pObjNew != Ivy_Regular(pFanin0New) ); - assert( pObjNew != Ivy_Regular(pFanin1New) ); - return pObjNew; - } - // get the fraiged representative - pObjReprNew = Ivy_ObjFraig(Ivy_ObjClassNodeRepr(pObjOld)); - // if the fraiged nodes are the same return - if ( Ivy_Regular(pObjNew) == Ivy_Regular(pObjReprNew) ) - return pObjNew; - assert( Ivy_Regular(pObjNew) != Ivy_ManConst1(p->pManFraig) ); -// printf( "Node = %d. Repr = %d.\n", pObjOld->Id, Ivy_ObjClassNodeRepr(pObjOld)->Id ); - - // they are different (the counter-example is in p->pPatWords) - RetValue = Ivy_FraigNodesAreEquiv( p, Ivy_Regular(pObjReprNew), Ivy_Regular(pObjNew) ); - if ( RetValue == 1 ) // proved equivalent - { - // mark the class as proved - if ( Ivy_ObjClassNodeNext(pObjOld) == NULL ) - Ivy_ObjClassNodeRepr(pObjOld)->fMarkA = 1; - return Ivy_NotCond( pObjReprNew, pObjOld->fPhase ^ Ivy_ObjClassNodeRepr(pObjOld)->fPhase ); - } - if ( RetValue == -1 ) // failed - return pObjNew; - // simulate the counter-example and return the new node - Ivy_FraigResimulate( p ); - return pObjNew; -} - -/**Function************************************************************* - - Synopsis [Prints variable activity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigPrintActivity( Ivy_FraigMan_t * p ) -{ - int i; - for ( i = 0; i < p->nSatVars; i++ ) - printf( "%d %.3f ", i, p->pSat->activity[i] ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Runs equivalence test for the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) -{ - int pLits[4], RetValue, RetValue1, nBTLimit, clk, clk2 = clock(); - - // make sure the nodes are not complemented - assert( !Ivy_IsComplement(pNew) ); - assert( !Ivy_IsComplement(pOld) ); - assert( pNew != pOld ); - - // if at least one of the nodes is a failed node, perform adjustments: - // if the backtrack limit is small, simply skip this node - // if the backtrack limit is > 10, take the quare root of the limit - nBTLimit = p->pParams->nBTLimitNode; - if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) - { - p->nSatFails++; - // fail immediately -// return -1; - if ( nBTLimit <= 10 ) - return -1; - nBTLimit = (int)pow(nBTLimit, 0.7); - } - p->nSatCalls++; - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - { - p->pSat = sat_solver_new(); - p->nSatVars = 1; - sat_solver_setnvars( p->pSat, 1000 ); - // var 0 is reserved for const1 node - add the clause -// pLits[0] = toLit( 0 ); -// sat_solver_addclause( p->pSat, pLits, pLits + 1 ); - } - - // if the nodes do not have SAT variables, allocate them - Ivy_FraigNodeAddToSolver( p, pOld, pNew ); - - // prepare variable activity - Ivy_FraigSetActivityFactors( p, pOld, pNew ); - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 -clk = clock(); - pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 0 ); - pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); -//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, - (sint64)nBTLimit, (sint64)0, - p->nBTLimitGlobal, p->nInsLimitGlobal ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - pLits[0] = lit_neg( pLits[0] ); - pLits[1] = lit_neg( pLits[1] ); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - // continue solving the other implication - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - Ivy_FraigSavePattern( p ); - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatFail += clock() - clk; - // mark the node as the failed node - if ( pOld != p->pManFraig->pConst1 ) - pOld->fFailTfo = 1; - pNew->fFailTfo = 1; - p->nSatFailsReal++; - return -1; - } - - // if the old node was constant 0, we already know the answer - if ( pOld == p->pManFraig->pConst1 ) - { - p->nSatProof++; - return 1; - } - - // solve under assumptions - // A = 0; B = 1 OR A = 0; B = 0 -clk = clock(); - pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 1 ); - pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase ); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, - (sint64)nBTLimit, (sint64)0, - p->nBTLimitGlobal, p->nInsLimitGlobal ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - pLits[0] = lit_neg( pLits[0] ); - pLits[1] = lit_neg( pLits[1] ); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - Ivy_FraigSavePattern( p ); - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatFail += clock() - clk; - // mark the node as the failed node - pOld->fFailTfo = 1; - pNew->fFailTfo = 1; - p->nSatFailsReal++; - return -1; - } -/* - // check BDD proof - { - int RetVal; - PRT( "Sat", clock() - clk2 ); - clk2 = clock(); - RetVal = Ivy_FraigNodesAreEquivBdd( pOld, pNew ); -// printf( "%d ", RetVal ); - assert( RetVal ); - PRT( "Bdd", clock() - clk2 ); - printf( "\n" ); - } -*/ - // return SAT proof - p->nSatProof++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Runs equivalence test for one node.] - - Description [Returns the fraiged node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pNew ) -{ - int pLits[2], RetValue1, RetValue, clk; - - // make sure the nodes are not complemented - assert( !Ivy_IsComplement(pNew) ); - assert( pNew != p->pManFraig->pConst1 ); - p->nSatCalls++; - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - { - p->pSat = sat_solver_new(); - p->nSatVars = 1; - sat_solver_setnvars( p->pSat, 1000 ); - // var 0 is reserved for const1 node - add the clause -// pLits[0] = toLit( 0 ); -// sat_solver_addclause( p->pSat, pLits, pLits + 1 ); - } - - // if the nodes do not have SAT variables, allocate them - Ivy_FraigNodeAddToSolver( p, NULL, pNew ); - - // prepare variable activity - Ivy_FraigSetActivityFactors( p, NULL, pNew ); - - // solve under assumptions -clk = clock(); - pLits[0] = toLitCond( Ivy_ObjSatNum(pNew), pNew->fPhase ); - RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, - (sint64)p->pParams->nBTLimitMiter, (sint64)0, - p->nBTLimitGlobal, p->nInsLimitGlobal ); -p->timeSat += clock() - clk; - if ( RetValue1 == l_False ) - { -p->timeSatUnsat += clock() - clk; - pLits[0] = lit_neg( pLits[0] ); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); - assert( RetValue ); - // continue solving the other implication - p->nSatCallsUnsat++; - } - else if ( RetValue1 == l_True ) - { -p->timeSatSat += clock() - clk; - if ( p->pPatWords ) - Ivy_FraigSavePattern( p ); - p->nSatCallsSat++; - return 0; - } - else // if ( RetValue1 == l_Undef ) - { -p->timeSatFail += clock() - clk; - // mark the node as the failed node - pNew->fFailTfo = 1; - p->nSatFailsReal++; - return -1; - } - - // return SAT proof - p->nSatProof++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAddClausesMux( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode ) -{ - Ivy_Obj_t * pNodeI, * pNodeT, * pNodeE; - int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; - - assert( !Ivy_IsComplement( pNode ) ); - assert( Ivy_ObjIsMuxType( pNode ) ); - // get nodes (I = if, T = then, E = else) - pNodeI = Ivy_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); - // get the variable numbers - VarF = Ivy_ObjSatNum(pNode); - VarI = Ivy_ObjSatNum(pNodeI); - VarT = Ivy_ObjSatNum(Ivy_Regular(pNodeT)); - VarE = Ivy_ObjSatNum(Ivy_Regular(pNodeE)); - // get the complementation flags - fCompT = Ivy_IsComplement(pNodeT); - fCompE = Ivy_IsComplement(pNodeE); - - // f = ITE(i, t, e) - - // i' + t' + f - // i' + t + f' - // i + e' + f - // i + e + f' - - // create four clauses - pLits[0] = toLitCond(VarI, 1); - pLits[1] = toLitCond(VarT, 1^fCompT); - pLits[2] = toLitCond(VarF, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarI, 1); - pLits[1] = toLitCond(VarT, 0^fCompT); - pLits[2] = toLitCond(VarF, 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarI, 0); - pLits[1] = toLitCond(VarE, 1^fCompE); - pLits[2] = toLitCond(VarF, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarI, 0); - pLits[1] = toLitCond(VarE, 0^fCompE); - pLits[2] = toLitCond(VarF, 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - - // two additional clauses - // t' & e' -> f' - // t & e -> f - - // t + e + f' - // t' + e' + f - - if ( VarT == VarE ) - { -// assert( fCompT == !fCompE ); - return; - } - - pLits[0] = toLitCond(VarT, 0^fCompT); - pLits[1] = toLitCond(VarE, 0^fCompE); - pLits[2] = toLitCond(VarF, 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); - pLits[0] = toLitCond(VarT, 1^fCompT); - pLits[1] = toLitCond(VarE, 1^fCompE); - pLits[2] = toLitCond(VarF, 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Addes clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigAddClausesSuper( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode, Vec_Ptr_t * vSuper ) -{ - Ivy_Obj_t * pFanin; - int * pLits, nLits, RetValue, i; - assert( !Ivy_IsComplement(pNode) ); - assert( Ivy_ObjIsNode( pNode ) ); - // create storage for literals - nLits = Vec_PtrSize(vSuper) + 1; - pLits = ALLOC( int, nLits ); - // suppose AND-gate is A & B = C - // add !A => !C or A + !C - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - pLits[0] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), Ivy_IsComplement(pFanin)); - pLits[1] = toLitCond(Ivy_ObjSatNum(pNode), 1); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); - assert( RetValue ); - } - // add A & B => C or !A + !B + C - Vec_PtrForEachEntry( vSuper, pFanin, i ) - pLits[i] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), !Ivy_IsComplement(pFanin)); - pLits[nLits-1] = toLitCond(Ivy_ObjSatNum(pNode), 0); - RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); - assert( RetValue ); - free( pLits ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigCollectSuper_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) -{ - // if the new node is complemented or a PI, another gate begins - if ( Ivy_IsComplement(pObj) || Ivy_ObjIsPi(pObj) || (!fFirst && Ivy_ObjRefs(pObj) > 1) || - (fUseMuxes && Ivy_ObjIsMuxType(pObj)) ) - { - Vec_PtrPushUnique( vSuper, pObj ); - return; - } - // go through the branches - Ivy_FraigCollectSuper_rec( Ivy_ObjChild0(pObj), vSuper, 0, fUseMuxes ); - Ivy_FraigCollectSuper_rec( Ivy_ObjChild1(pObj), vSuper, 0, fUseMuxes ); -} - -/**Function************************************************************* - - Synopsis [Collects the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ivy_FraigCollectSuper( Ivy_Obj_t * pObj, int fUseMuxes ) -{ - Vec_Ptr_t * vSuper; - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_ObjIsPi(pObj) ); - vSuper = Vec_PtrAlloc( 4 ); - Ivy_FraigCollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); - return vSuper; -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigObjAddToFrontier( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vFrontier ) -{ - assert( !Ivy_IsComplement(pObj) ); - if ( Ivy_ObjSatNum(pObj) ) - return; - assert( Ivy_ObjSatNum(pObj) == 0 ); - assert( Ivy_ObjFaninVec(pObj) == NULL ); - if ( Ivy_ObjIsConst1(pObj) ) - return; -//printf( "Assigning node %d number %d\n", pObj->Id, p->nSatVars ); - Ivy_ObjSetSatNum( pObj, p->nSatVars++ ); - if ( Ivy_ObjIsNode(pObj) ) - Vec_PtrPush( vFrontier, pObj ); -} - -/**Function************************************************************* - - Synopsis [Updates the solver clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) -{ - Vec_Ptr_t * vFrontier, * vFanins; - Ivy_Obj_t * pNode, * pFanin; - int i, k, fUseMuxes = 1; - assert( pOld || pNew ); - // quit if CNF is ready - if ( (!pOld || Ivy_ObjFaninVec(pOld)) && (!pNew || Ivy_ObjFaninVec(pNew)) ) - return; - // start the frontier - vFrontier = Vec_PtrAlloc( 100 ); - if ( pOld ) Ivy_FraigObjAddToFrontier( p, pOld, vFrontier ); - if ( pNew ) Ivy_FraigObjAddToFrontier( p, pNew, vFrontier ); - // explore nodes in the frontier - Vec_PtrForEachEntry( vFrontier, pNode, i ) - { - // create the supergate - assert( Ivy_ObjSatNum(pNode) ); - assert( Ivy_ObjFaninVec(pNode) == NULL ); - if ( fUseMuxes && Ivy_ObjIsMuxType(pNode) ) - { - vFanins = Vec_PtrAlloc( 4 ); - Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin1(pNode) ) ); - Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin0(pNode) ) ); - Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin1(pNode) ) ); - Vec_PtrForEachEntry( vFanins, pFanin, k ) - Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); - Ivy_FraigAddClausesMux( p, pNode ); - } - else - { - vFanins = Ivy_FraigCollectSuper( pNode, fUseMuxes ); - Vec_PtrForEachEntry( vFanins, pFanin, k ) - Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); - Ivy_FraigAddClausesSuper( p, pNode, vFanins ); - } - assert( Vec_PtrSize(vFanins) > 1 ); - Ivy_ObjSetFaninVec( pNode, vFanins ); - } - Vec_PtrFree( vFrontier ); -} - -/**Function************************************************************* - - Synopsis [Sets variable activities in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigSetActivityFactors_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int LevelMin, int LevelMax ) -{ - Vec_Ptr_t * vFanins; - Ivy_Obj_t * pFanin; - int i, Counter = 0; - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjSatNum(pObj) ); - // skip visited variables - if ( Ivy_ObjIsTravIdCurrent(p->pManFraig, pObj) ) - return 0; - Ivy_ObjSetTravIdCurrent(p->pManFraig, pObj); - // add the PI to the list - if ( pObj->Level <= (unsigned)LevelMin || Ivy_ObjIsPi(pObj) ) - return 0; - // set the factor of this variable - // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pParams->dActConeBumpMax / ThisBump - p->pSat->factors[Ivy_ObjSatNum(pObj)] = p->pParams->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin); - veci_push(&p->pSat->act_vars, Ivy_ObjSatNum(pObj)); - // explore the fanins - vFanins = Ivy_ObjFaninVec( pObj ); - Vec_PtrForEachEntry( vFanins, pFanin, i ) - Counter += Ivy_FraigSetActivityFactors_rec( p, Ivy_Regular(pFanin), LevelMin, LevelMax ); - return 1 + Counter; -} - -/**Function************************************************************* - - Synopsis [Sets variable activities in the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) -{ - int clk, LevelMin, LevelMax; - assert( pOld || pNew ); -clk = clock(); - // reset the active variables - veci_resize(&p->pSat->act_vars, 0); - // prepare for traversal - Ivy_ManIncrementTravId( p->pManFraig ); - // determine the min and max level to visit - assert( p->pParams->dActConeRatio > 0 && p->pParams->dActConeRatio < 1 ); - LevelMax = IVY_MAX( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) ); - LevelMin = (int)(LevelMax * (1.0 - p->pParams->dActConeRatio)); - // traverse - if ( pOld && !Ivy_ObjIsConst1(pOld) ) - Ivy_FraigSetActivityFactors_rec( p, pOld, LevelMin, LevelMax ); - if ( pNew && !Ivy_ObjIsConst1(pNew) ) - Ivy_FraigSetActivityFactors_rec( p, pNew, LevelMin, LevelMax ); -//Ivy_FraigPrintActivity( p ); -p->timeTrav += clock() - clk; - return 1; -} - - - -#include "cuddInt.h" - -/**Function************************************************************* - - Synopsis [Checks equivalence using BDDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Ivy_FraigNodesAreEquivBdd_int( DdManager * dd, DdNode * bFunc, Vec_Ptr_t * vFront, int Level ) -{ - DdNode ** pFuncs; - DdNode * bFuncNew; - Vec_Ptr_t * vTemp; - Ivy_Obj_t * pObj, * pFanin; - int i, NewSize; - // create new frontier - vTemp = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( vFront, pObj, i ) - { - if ( (int)pObj->Level != Level ) - { - pObj->fMarkB = 1; - pObj->TravId = Vec_PtrSize(vTemp); - Vec_PtrPush( vTemp, pObj ); - continue; - } - - pFanin = Ivy_ObjFanin0(pObj); - if ( pFanin->fMarkB == 0 ) - { - pFanin->fMarkB = 1; - pFanin->TravId = Vec_PtrSize(vTemp); - Vec_PtrPush( vTemp, pFanin ); - } - - pFanin = Ivy_ObjFanin1(pObj); - if ( pFanin->fMarkB == 0 ) - { - pFanin->fMarkB = 1; - pFanin->TravId = Vec_PtrSize(vTemp); - Vec_PtrPush( vTemp, pFanin ); - } - } - // collect the permutation - NewSize = IVY_MAX(dd->size, Vec_PtrSize(vTemp)); - pFuncs = ALLOC( DdNode *, NewSize ); - Vec_PtrForEachEntry( vFront, pObj, i ) - { - if ( (int)pObj->Level != Level ) - pFuncs[i] = Cudd_bddIthVar( dd, pObj->TravId ); - else - pFuncs[i] = Cudd_bddAnd( dd, - Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ), - Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ) ); - Cudd_Ref( pFuncs[i] ); - } - // add the remaining vars - assert( NewSize == dd->size ); - for ( i = Vec_PtrSize(vFront); i < dd->size; i++ ) - { - pFuncs[i] = Cudd_bddIthVar( dd, i ); - Cudd_Ref( pFuncs[i] ); - } - - // create new - bFuncNew = Cudd_bddVectorCompose( dd, bFunc, pFuncs ); Cudd_Ref( bFuncNew ); - // clean trav Id - Vec_PtrForEachEntry( vTemp, pObj, i ) - { - pObj->fMarkB = 0; - pObj->TravId = 0; - } - // deref - for ( i = 0; i < dd->size; i++ ) - Cudd_RecursiveDeref( dd, pFuncs[i] ); - free( pFuncs ); - - free( vFront->pArray ); - *vFront = *vTemp; - - vTemp->nCap = vTemp->nSize = 0; - vTemp->pArray = NULL; - Vec_PtrFree( vTemp ); - - Cudd_Deref( bFuncNew ); - return bFuncNew; -} - -/**Function************************************************************* - - Synopsis [Checks equivalence using BDDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ) -{ - static DdManager * dd = NULL; - DdNode * bFunc, * bTemp; - Vec_Ptr_t * vFront; - Ivy_Obj_t * pObj; - int i, RetValue, Iter, Level; - // start the manager - if ( dd == NULL ) - dd = Cudd_Init( 50, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - // create front - vFront = Vec_PtrAlloc( 100 ); - Vec_PtrPush( vFront, pObj1 ); - Vec_PtrPush( vFront, pObj2 ); - // get the function - bFunc = Cudd_bddXor( dd, Cudd_bddIthVar(dd,0), Cudd_bddIthVar(dd,1) ); Cudd_Ref( bFunc ); - bFunc = Cudd_NotCond( bFunc, pObj1->fPhase != pObj2->fPhase ); - // try running BDDs - for ( Iter = 0; ; Iter++ ) - { - // find max level - Level = 0; - Vec_PtrForEachEntry( vFront, pObj, i ) - if ( Level < (int)pObj->Level ) - Level = (int)pObj->Level; - if ( Level == 0 ) - break; - bFunc = Ivy_FraigNodesAreEquivBdd_int( dd, bTemp = bFunc, vFront, Level ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - if ( bFunc == Cudd_ReadLogicZero(dd) ) // proved - {printf( "%d", Iter ); break;} - if ( Cudd_DagSize(bFunc) > 1000 ) - {printf( "b" ); break;} - if ( dd->size > 120 ) - {printf( "s" ); break;} - if ( Iter > 50 ) - {printf( "i" ); break;} - } - if ( bFunc == Cudd_ReadLogicZero(dd) ) // unsat - RetValue = 1; - else if ( Level == 0 ) // sat - RetValue = 0; - else - RetValue = -1; // spaceout/timeout - Cudd_RecursiveDeref( dd, bFunc ); - Vec_PtrFree( vFront ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyHaig.c b/src/aig/ivy/ivyHaig.c deleted file mode 100644 index 87021600..00000000 --- a/src/aig/ivy/ivyHaig.c +++ /dev/null @@ -1,530 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyHaig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [HAIG management procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyHaig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/* - HAIGing rules in working AIG: - - Each node in the working AIG has a pointer to the corresponding node in HAIG - (this node is not necessarily the representative of the equivalence class of HAIG nodes) - - This pointer is complemented if the AIG node and its corresponding HAIG node have different phase - - Choice node rules in HAIG: - - Equivalent nodes are linked into a ring - - Exactly one node in the ring has fanouts (this node is called the representative) - - The pointer going from a node to the next node in the ring is complemented - if the first node is complemented, compared to the representative node of the equivalence class - - (consequence of the above) The representative node always has non-complemented pointer to the next node - - New nodes are inserted into the ring immediately after the representative node -*/ - -// returns the representative node of the given HAIG node -static inline Ivy_Obj_t * Ivy_HaigObjRepr( Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pTemp; - assert( !Ivy_IsComplement(pObj) ); - // if the node has no equivalent node or has fanout, it is representative - if ( pObj->pEquiv == NULL || Ivy_ObjRefs(pObj) > 0 ) - return pObj; - // the node belongs to a class and is not a representative - // complemented edge (pObj->pEquiv) tells if it is complemented w.r.t. the repr - for ( pTemp = Ivy_Regular(pObj->pEquiv); pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - if ( Ivy_ObjRefs(pTemp) > 0 ) - break; - // return the representative node - assert( Ivy_ObjRefs(pTemp) > 0 ); - return Ivy_NotCond( pTemp, Ivy_IsComplement(pObj->pEquiv) ); -} - -// counts the number of nodes in the equivalence class -static inline int Ivy_HaigObjCountClass( Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pTemp; - int Counter; - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjRefs(pObj) > 0 ); - if ( pObj->pEquiv == NULL ) - return 1; - assert( !Ivy_IsComplement(pObj->pEquiv) ); - Counter = 1; - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - Counter++; - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts HAIG for the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ) -{ - Vec_Int_t * vLatches; - Ivy_Obj_t * pObj; - int i; - assert( p->pHaig == NULL ); - p->pHaig = Ivy_ManDup( p ); - - if ( fVerbose ) - { - printf( "Starting : " ); - Ivy_ManPrintStats( p->pHaig ); - } - - // collect latches of design D and set their values to be DC - vLatches = Vec_IntAlloc( 100 ); - Ivy_ManForEachLatch( p->pHaig, pObj, i ) - { - pObj->Init = IVY_INIT_DC; - Vec_IntPush( vLatches, pObj->Id ); - } - p->pHaig->pData = vLatches; -/* - { - int x; - Ivy_ManShow( p, 0, NULL ); - Ivy_ManShow( p->pHaig, 1, NULL ); - x = 0; - } -*/ -} - -/**Function************************************************************* - - Synopsis [Transfers the HAIG to the newly created manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ) -{ - Ivy_Obj_t * pObj; - int i; - assert( p->pHaig != NULL ); - Ivy_ManConst1(pNew)->pEquiv = Ivy_ManConst1(p)->pEquiv; - Ivy_ManForEachPi( pNew, pObj, i ) - pObj->pEquiv = Ivy_ManPi( p, i )->pEquiv; - pNew->pHaig = p->pHaig; -} - -/**Function************************************************************* - - Synopsis [Stops HAIG for the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigStop( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - assert( p->pHaig != NULL ); - Vec_IntFree( p->pHaig->pData ); - Ivy_ManStop( p->pHaig ); - p->pHaig = NULL; - // remove dangling pointers to the HAIG objects - Ivy_ManForEachObj( p, pObj, i ) - pObj->pEquiv = NULL; -} - -/**Function************************************************************* - - Synopsis [Creates a new node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pEquiv0, * pEquiv1; - assert( p->pHaig != NULL ); - assert( !Ivy_IsComplement(pObj) ); - if ( Ivy_ObjType(pObj) == IVY_BUF ) - pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); - else if ( Ivy_ObjType(pObj) == IVY_LATCH ) - { -// pObj->pEquiv = Ivy_Latch( p->pHaig, Ivy_ObjChild0Equiv(pObj), pObj->Init ); - pEquiv0 = Ivy_ObjChild0Equiv(pObj); - pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); - pObj->pEquiv = Ivy_Latch( p->pHaig, pEquiv0, pObj->Init ); - } - else if ( Ivy_ObjType(pObj) == IVY_AND ) - { -// pObj->pEquiv = Ivy_And( p->pHaig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); - pEquiv0 = Ivy_ObjChild0Equiv(pObj); - pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); - pEquiv1 = Ivy_ObjChild1Equiv(pObj); - pEquiv1 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv1)), Ivy_IsComplement(pEquiv1) ); - pObj->pEquiv = Ivy_And( p->pHaig, pEquiv0, pEquiv1 ); - } - else assert( 0 ); - // make sure the node points to the representative -// pObj->pEquiv = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObj->pEquiv)), Ivy_IsComplement(pObj->pEquiv) ); -} - -/**Function************************************************************* - - Synopsis [Checks if the old node is in the TFI of the new node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjIsInTfi_rec( Ivy_Obj_t * pObjNew, Ivy_Obj_t * pObjOld, int Levels ) -{ - if ( pObjNew == pObjOld ) - return 1; - if ( Levels == 0 || Ivy_ObjIsCi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) - return 0; - if ( Ivy_ObjIsInTfi_rec( Ivy_ObjFanin0(pObjNew), pObjOld, Levels - 1 ) ) - return 1; - if ( Ivy_ObjIsNode(pObjNew) && Ivy_ObjIsInTfi_rec( Ivy_ObjFanin1(pObjNew), pObjOld, Levels - 1 ) ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Sets the pair of equivalent nodes in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ) -{ - Ivy_Obj_t * pObjOldHaig, * pObjNewHaig; - Ivy_Obj_t * pObjOldHaigR, * pObjNewHaigR; - int fCompl; -//printf( "\nCreating choice for %d and %d in AIG\n", pObjOld->Id, Ivy_Regular(pObjNew)->Id ); - - assert( p->pHaig != NULL ); - assert( !Ivy_IsComplement(pObjOld) ); - // get pointers to the representatives of pObjOld and pObjNew - pObjOldHaig = pObjOld->pEquiv; - pObjNewHaig = Ivy_NotCond( Ivy_Regular(pObjNew)->pEquiv, Ivy_IsComplement(pObjNew) ); - // get the classes - pObjOldHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjOldHaig)), Ivy_IsComplement(pObjOldHaig) ); - pObjNewHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjNewHaig)), Ivy_IsComplement(pObjNewHaig) ); - // get regular pointers - pObjOldHaigR = Ivy_Regular(pObjOldHaig); - pObjNewHaigR = Ivy_Regular(pObjNewHaig); - // check if there is phase difference between them - fCompl = (Ivy_IsComplement(pObjOldHaig) != Ivy_IsComplement(pObjNewHaig)); - // if the class is the same, nothing to do - if ( pObjOldHaigR == pObjNewHaigR ) - return; - // if the second node belongs to a class, do not merge classes (for the time being) - if ( Ivy_ObjRefs(pObjOldHaigR) == 0 || pObjNewHaigR->pEquiv != NULL || - Ivy_ObjRefs(pObjNewHaigR) > 0 ) //|| Ivy_ObjIsInTfi_rec(pObjNewHaigR, pObjOldHaigR, 10) ) - { -/* - if ( pObjNewHaigR->pEquiv != NULL ) - printf( "c" ); - if ( Ivy_ObjRefs(pObjNewHaigR) > 0 ) - printf( "f" ); - printf( " " ); -*/ - p->pHaig->nClassesSkip++; - return; - } - - // add this node to the class of pObjOldHaig - assert( Ivy_ObjRefs(pObjOldHaigR) > 0 ); - assert( !Ivy_IsComplement(pObjOldHaigR->pEquiv) ); - if ( pObjOldHaigR->pEquiv == NULL ) - pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ); - else - pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR->pEquiv, fCompl ); - pObjOldHaigR->pEquiv = pObjNewHaigR; -//printf( "Setting choice node %d -> %d.\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); - // update the class of the new node -// Ivy_Regular(pObjNew)->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ^ Ivy_IsComplement(pObjNew) ); -//printf( "Creating choice for %d and %d in HAIG\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); - -// if ( pObjOldHaigR->Id == 13 ) -// { -// Ivy_ManShow( p, 0 ); -// Ivy_ManShow( p->pHaig, 1 ); -// } -// if ( !Ivy_ManIsAcyclic( p->pHaig ) ) -// printf( "HAIG contains a cycle\n" ); -} - -/**Function************************************************************* - - Synopsis [Count the number of choices and choice nodes in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManHaigCountChoices( Ivy_Man_t * p, int * pnChoices ) -{ - Ivy_Obj_t * pObj; - int nChoices, nChoiceNodes, Counter, i; - assert( p->pHaig != NULL ); - nChoices = nChoiceNodes = 0; - Ivy_ManForEachObj( p->pHaig, pObj, i ) - { - if ( Ivy_ObjIsTerm(pObj) || i == 0 ) - continue; - if ( Ivy_ObjRefs(pObj) == 0 ) - continue; - Counter = Ivy_HaigObjCountClass( pObj ); - nChoiceNodes += (int)(Counter > 1); - nChoices += Counter - 1; -// if ( Counter > 1 ) -// printf( "Choice node %d %s\n", pObj->Id, Ivy_ObjIsLatch(pObj)? "(latch)": "" ); - } - *pnChoices = nChoices; - return nChoiceNodes; -} - -/**Function************************************************************* - - Synopsis [Prints statistics of the HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ) -{ - int nChoices, nChoiceNodes; - - assert( p->pHaig != NULL ); - - if ( fVerbose ) - { - printf( "Final : " ); - Ivy_ManPrintStats( p ); - printf( "HAIG : " ); - Ivy_ManPrintStats( p->pHaig ); - - // print choice node stats - nChoiceNodes = Ivy_ManHaigCountChoices( p, &nChoices ); - printf( "Total choice nodes = %d. Total choices = %d. Skipped classes = %d.\n", - nChoiceNodes, nChoices, p->pHaig->nClassesSkip ); - } - - if ( Ivy_ManIsAcyclic( p->pHaig ) ) - { - if ( fVerbose ) - printf( "HAIG is acyclic\n" ); - } - else - printf( "HAIG contains a cycle\n" ); - -// if ( fVerbose ) -// Ivy_ManHaigSimulate( p ); -} - - -/**Function************************************************************* - - Synopsis [Applies the simulation rules.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Ivy_Init_t Ivy_ManHaigSimulateAnd( Ivy_Init_t In0, Ivy_Init_t In1 ) -{ - assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); - if ( In0 == IVY_INIT_DC || In1 == IVY_INIT_DC ) - return IVY_INIT_DC; - if ( In0 == IVY_INIT_1 && In1 == IVY_INIT_1 ) - return IVY_INIT_1; - return IVY_INIT_0; -} - -/**Function************************************************************* - - Synopsis [Applies the simulation rules.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Ivy_Init_t Ivy_ManHaigSimulateChoice( Ivy_Init_t In0, Ivy_Init_t In1 ) -{ - assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); - if ( (In0 == IVY_INIT_0 && In1 == IVY_INIT_1) || (In0 == IVY_INIT_1 && In1 == IVY_INIT_0) ) - { - printf( "Compatibility fails.\n" ); - return IVY_INIT_0; - } - if ( In0 == IVY_INIT_DC && In1 == IVY_INIT_DC ) - return IVY_INIT_DC; - if ( In0 != IVY_INIT_DC ) - return In0; - return In1; -} - -/**Function************************************************************* - - Synopsis [Simulate HAIG using modified 3-valued simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManHaigSimulate( Ivy_Man_t * p ) -{ - Vec_Int_t * vNodes, * vLatches, * vLatchesD; - Ivy_Obj_t * pObj, * pTemp; - Ivy_Init_t In0, In1; - int i, k, Counter; - int fVerbose = 0; - - // check choices - Ivy_ManCheckChoices( p ); - - // switch to HAIG - assert( p->pHaig != NULL ); - p = p->pHaig; - -if ( fVerbose ) -Ivy_ManForEachPi( p, pObj, i ) -printf( "Setting PI %d\n", pObj->Id ); - - // collect latches and nodes in the DFS order - vNodes = Ivy_ManDfsSeq( p, &vLatches ); - -if ( fVerbose ) -Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) -printf( "Collected node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); - - // set the PI values - Ivy_ManConst1(p)->Init = IVY_INIT_1; - Ivy_ManForEachPi( p, pObj, i ) - pObj->Init = IVY_INIT_0; - - // set the latch values - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - pObj->Init = IVY_INIT_DC; - // set the latches of D to be determinate - vLatchesD = p->pData; - Ivy_ManForEachNodeVec( p, vLatchesD, pObj, i ) - pObj->Init = IVY_INIT_0; - - // perform several rounds of simulation - for ( k = 0; k < 10; k++ ) - { - // count the number of non-determinate values - Counter = 0; - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - Counter += ( pObj->Init == IVY_INIT_DC ); - printf( "Iter %d : Non-determinate = %d\n", k, Counter ); - - // simulate the internal nodes - Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) - { -if ( fVerbose ) -printf( "Processing node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); - In0 = Ivy_InitNotCond( Ivy_ObjFanin0(pObj)->Init, Ivy_ObjFaninC0(pObj) ); - In1 = Ivy_InitNotCond( Ivy_ObjFanin1(pObj)->Init, Ivy_ObjFaninC1(pObj) ); - pObj->Init = Ivy_ManHaigSimulateAnd( In0, In1 ); - // simulate the equivalence class if the node is a representative - if ( pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) - { -if ( fVerbose ) -printf( "Processing choice node %d\n", pObj->Id ); - In0 = pObj->Init; - assert( !Ivy_IsComplement(pObj->pEquiv) ); - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - { -if ( fVerbose ) -printf( "Processing secondary node %d\n", pTemp->Id ); - In1 = Ivy_InitNotCond( pTemp->Init, Ivy_IsComplement(pTemp->pEquiv) ); - In0 = Ivy_ManHaigSimulateChoice( In0, In1 ); - } - pObj->Init = In0; - } - } - - // simulate the latches - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - { - pObj->Level = Ivy_ObjFanin0(pObj)->Init; -if ( fVerbose ) -printf( "Using latch %d with fanin %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id ); - } - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - pObj->Init = pObj->Level, pObj->Level = 0; - } - // free arrays - Vec_IntFree( vNodes ); - Vec_IntFree( vLatches ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyMan.c b/src/aig/ivy/ivyMan.c deleted file mode 100644 index 07faef85..00000000 --- a/src/aig/ivy/ivyMan.c +++ /dev/null @@ -1,546 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [AIG manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManStart() -{ - Ivy_Man_t * p; - // start the manager - p = ALLOC( Ivy_Man_t, 1 ); - memset( p, 0, sizeof(Ivy_Man_t) ); - // perform initializations - p->Ghost.Id = -1; - p->nTravIds = 1; - p->fCatchExor = 1; - // allocate arrays for nodes - p->vPis = Vec_PtrAlloc( 100 ); - p->vPos = Vec_PtrAlloc( 100 ); - p->vBufs = Vec_PtrAlloc( 100 ); - p->vObjs = Vec_PtrAlloc( 100 ); - // prepare the internal memory manager - Ivy_ManStartMemory( p ); - // create the constant node - p->pConst1 = Ivy_ManFetchMemory( p ); - p->pConst1->fPhase = 1; - Vec_PtrPush( p->vObjs, p->pConst1 ); - p->nCreated = 1; - // start the table - p->nTableSize = 10007; - p->pTable = ALLOC( int, p->nTableSize ); - memset( p->pTable, 0, sizeof(int) * p->nTableSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ) -{ - Ivy_Man_t * pNew; - Ivy_Obj_t * pObj; - int i; - // create the new manager - pNew = Ivy_ManStart(); - // create the PIs - Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); - Ivy_ManForEachPi( p, pObj, i ) - pObj->pEquiv = Ivy_ObjCreatePi(pNew); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Duplicates the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ) -{ - Vec_Int_t * vNodes, * vLatches; - Ivy_Man_t * pNew; - Ivy_Obj_t * pObj; - int i; - // collect latches and nodes in the DFS order - vNodes = Ivy_ManDfsSeq( p, &vLatches ); - // create the new manager - pNew = Ivy_ManStart(); - // create the PIs - Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); - Ivy_ManForEachPi( p, pObj, i ) - pObj->pEquiv = Ivy_ObjCreatePi(pNew); - // create the fake PIs for latches - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - pObj->pEquiv = Ivy_ObjCreatePi(pNew); - // duplicate internal nodes - Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) - if ( Ivy_ObjIsBuf(pObj) ) - pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); - else - pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); - // add the POs - Ivy_ManForEachPo( p, pObj, i ) - Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(pObj) ); - // transform additional PI nodes into latches and connect them - Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) - { - assert( !Ivy_ObjFaninC0(pObj) ); - pObj->pEquiv->Type = IVY_LATCH; - pObj->pEquiv->Init = pObj->Init; - Ivy_ObjConnect( pNew, pObj->pEquiv, Ivy_ObjChild0Equiv(pObj), NULL ); - } - // shrink the arrays - Vec_PtrShrink( pNew->vPis, Ivy_ManPiNum(p) ); - // update the counters of different objects - pNew->nObjs[IVY_PI] -= Ivy_ManLatchNum(p); - pNew->nObjs[IVY_LATCH] += Ivy_ManLatchNum(p); - // free arrays - Vec_IntFree( vNodes ); - Vec_IntFree( vLatches ); - // make sure structural hashing did not change anything - assert( Ivy_ManNodeNum(p) == Ivy_ManNodeNum(pNew) ); - assert( Ivy_ManLatchNum(p) == Ivy_ManLatchNum(pNew) ); - // check the resulting network - if ( !Ivy_ManCheck(pNew) ) - printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ) -{ - Vec_Ptr_t * vMapping; - Ivy_Man_t * pNew; - Ivy_Obj_t * pObj; - int i, f, nPis, nPos, nIdMax; - assert( Ivy_ManLatchNum(pMan) == 0 ); - assert( nFrames > 0 ); - // prepare the mapping - nPis = Ivy_ManPiNum(pMan) - nLatches; - nPos = Ivy_ManPoNum(pMan) - nLatches; - nIdMax = Ivy_ManObjIdMax(pMan); - // create the new manager - pNew = Ivy_ManStart(); - // set the starting values of latch inputs - for ( i = 0; i < nLatches; i++ ) - Ivy_ManPo(pMan, nPos+i)->pEquiv = fInit? Ivy_Not(Ivy_ManConst1(pNew)) : Ivy_ObjCreatePi(pNew); - // add timeframes - vMapping = Vec_PtrStart( nIdMax * nFrames + 1 ); - for ( f = 0; f < nFrames; f++ ) - { - // create PIs - Ivy_ManConst1(pMan)->pEquiv = Ivy_ManConst1(pNew); - for ( i = 0; i < nPis; i++ ) - Ivy_ManPi(pMan, i)->pEquiv = Ivy_ObjCreatePi(pNew); - // transfer values to latch outputs - for ( i = 0; i < nLatches; i++ ) - Ivy_ManPi(pMan, nPis+i)->pEquiv = Ivy_ManPo(pMan, nPos+i)->pEquiv; - // perform strashing - Ivy_ManForEachNode( pMan, pObj, i ) - pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); - // create POs - for ( i = 0; i < nPos; i++ ) - Ivy_ManPo(pMan, i)->pEquiv = Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, i)) ); - // set the results of latch inputs - for ( i = 0; i < nLatches; i++ ) - Ivy_ManPo(pMan, nPos+i)->pEquiv = Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, nPos+i)); - // save the pointers in this frame - Ivy_ManForEachObj( pMan, pObj, i ) - Vec_PtrWriteEntry( vMapping, f * nIdMax + i, pObj->pEquiv ); - } - // connect latches - if ( !fInit ) - for ( i = 0; i < nLatches; i++ ) - Ivy_ObjCreatePo( pNew, Ivy_ManPo(pMan, nPos+i)->pEquiv ); - // remove dangling nodes - Ivy_ManCleanup(pNew); - *pvMapping = vMapping; - // check the resulting network - if ( !Ivy_ManCheck(pNew) ) - printf( "Ivy_ManFrames(): The check has failed.\n" ); - return pNew; -} - - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManStop( Ivy_Man_t * p ) -{ - if ( p->time1 ) { PRT( "Update lev ", p->time1 ); } - if ( p->time2 ) { PRT( "Update levR ", p->time2 ); } -// Ivy_TableProfile( p ); -// if ( p->vFanouts ) Ivy_ManStopFanout( p ); - if ( p->vChunks ) Ivy_ManStopMemory( p ); - if ( p->vRequired ) Vec_IntFree( p->vRequired ); - if ( p->vPis ) Vec_PtrFree( p->vPis ); - if ( p->vPos ) Vec_PtrFree( p->vPos ); - if ( p->vBufs ) Vec_PtrFree( p->vBufs ); - if ( p->vObjs ) Vec_PtrFree( p->vObjs ); - free( p->pTable ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Removes nodes without fanout.] - - Description [Returns the number of dangling nodes removed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCleanup( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pNode; - int i, nNodesOld; - nNodesOld = Ivy_ManNodeNum(p); - Ivy_ManForEachObj( p, pNode, i ) - if ( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) - if ( Ivy_ObjRefs(pNode) == 0 ) - Ivy_ObjDelete_rec( p, pNode, 1 ); -//printf( "Cleanup removed %d nodes.\n", nNodesOld - Ivy_ManNodeNum(p) ); - return nNodesOld - Ivy_ManNodeNum(p); -} - -/**Function************************************************************* - - Synopsis [Marks nodes reachable from the given one.] - - Description [Returns the number of dangling nodes removed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCleanupSeq_rec( Ivy_Obj_t * pObj ) -{ - if ( Ivy_ObjIsMarkA(pObj) ) - return; - Ivy_ObjSetMarkA(pObj); - if ( pObj->pFanin0 != NULL ) - Ivy_ManCleanupSeq_rec( Ivy_ObjFanin0(pObj) ); - if ( pObj->pFanin1 != NULL ) - Ivy_ManCleanupSeq_rec( Ivy_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Removes logic that does not feed into POs.] - - Description [Returns the number of dangling nodes removed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManCleanupSeq( Ivy_Man_t * p ) -{ - Vec_Ptr_t * vNodes; - Ivy_Obj_t * pObj; - int i, RetValue; - // mark the constant and PIs - Ivy_ObjSetMarkA( Ivy_ManConst1(p) ); - Ivy_ManForEachPi( p, pObj, i ) - Ivy_ObjSetMarkA( pObj ); - // mark nodes visited from POs - Ivy_ManForEachPo( p, pObj, i ) - Ivy_ManCleanupSeq_rec( pObj ); - // collect unmarked nodes - vNodes = Vec_PtrAlloc( 100 ); - Ivy_ManForEachObj( p, pObj, i ) - { - if ( Ivy_ObjIsMarkA(pObj) ) - Ivy_ObjClearMarkA(pObj); - else - Vec_PtrPush( vNodes, pObj ); - } - if ( Vec_PtrSize(vNodes) == 0 ) - { - Vec_PtrFree( vNodes ); -//printf( "Sequential sweep cleaned out %d nodes.\n", 0 ); - return 0; - } - // disconnect the marked objects - Vec_PtrForEachEntry( vNodes, pObj, i ) - Ivy_ObjDisconnect( p, pObj ); - // remove the dangling objects - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsLatch(pObj) || Ivy_ObjIsBuf(pObj) ); - assert( Ivy_ObjRefs(pObj) == 0 ); - // update node counters of the manager - p->nObjs[pObj->Type]--; - p->nDeleted++; - // delete buffer from the array of buffers - if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) - Vec_PtrRemove( p->vBufs, pObj ); - // free the node - Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); - Ivy_ManRecycleMemory( p, pObj ); - } - // return the number of nodes freed - RetValue = Vec_PtrSize(vNodes); - Vec_PtrFree( vNodes ); -//printf( "Sequential sweep cleaned out %d nodes.\n", RetValue ); - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [Checks if latches form self-loop.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManLatchIsSelfFeed_rec( Ivy_Obj_t * pLatch, Ivy_Obj_t * pLatchRoot ) -{ - if ( !Ivy_ObjIsLatch(pLatch) && !Ivy_ObjIsBuf(pLatch) ) - return 0; - if ( pLatch == pLatchRoot ) - return 1; - return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatchRoot ); -} - -/**Function************************************************************* - - Synopsis [Checks if latches form self-loop.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManLatchIsSelfFeed( Ivy_Obj_t * pLatch ) -{ - if ( !Ivy_ObjIsLatch(pLatch) ) - return 0; - return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatch ); -} - - -/**Function************************************************************* - - Synopsis [Returns the number of dangling nodes removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ) -{ - Ivy_Obj_t * pNode; - int LimitFactor = 100; - int NodeBeg = Ivy_ManNodeNum(p); - int nSteps; - for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ ) - { - pNode = Vec_PtrEntryLast(p->vBufs); - while ( Ivy_ObjIsBuf(pNode) ) - pNode = Ivy_ObjReadFirstFanout( p, pNode ); - // check if this buffer should remain - if ( Ivy_ManLatchIsSelfFeed(pNode) ) - { - Vec_PtrPop(p->vBufs); - continue; - } -//printf( "Propagating buffer %d with input %d and output %d\n", Ivy_ObjFaninId0(pNode), Ivy_ObjFaninId0(Ivy_ObjFanin0(pNode)), pNode->Id ); -//printf( "Latch num %d\n", Ivy_ManLatchNum(p) ); - Ivy_NodeFixBufferFanins( p, pNode, fUpdateLevel ); - if ( nSteps > NodeBeg * LimitFactor ) - { - printf( "Structural hashing is not finished after %d forward latch moves.\n", NodeBeg * LimitFactor ); - printf( "This circuit cannot be forward-retimed completely. Quitting.\n" ); - break; - } - } -// printf( "Number of steps = %d. Nodes beg = %d. Nodes end = %d.\n", nSteps, NodeBeg, Ivy_ManNodeNum(p) ); - return nSteps; -} - -/**Function************************************************************* - - Synopsis [Stops the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManPrintStats( Ivy_Man_t * p ) -{ - printf( "PI/PO = %d/%d ", Ivy_ManPiNum(p), Ivy_ManPoNum(p) ); - printf( "A = %7d. ", Ivy_ManAndNum(p) ); - printf( "L = %5d. ", Ivy_ManLatchNum(p) ); -// printf( "X = %d. ", Ivy_ManExorNum(p) ); -// printf( "B = %3d. ", Ivy_ManBufNum(p) ); - printf( "MaxID = %7d. ", Ivy_ManObjIdMax(p) ); -// printf( "Cre = %d. ", p->nCreated ); -// printf( "Del = %d. ", p->nDeleted ); - printf( "Lev = %3d. ", Ivy_ManLatchNum(p)? -1 : Ivy_ManLevels(p) ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Converts a combinational AIG manager into a sequential one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ) -{ - Ivy_Obj_t * pObj, * pLatch; - Ivy_Init_t Init; - int i; - if ( nLatches == 0 ) - return; - assert( nLatches < Ivy_ManPiNum(p) && nLatches < Ivy_ManPoNum(p) ); - assert( Ivy_ManPiNum(p) == Vec_PtrSize(p->vPis) ); - assert( Ivy_ManPoNum(p) == Vec_PtrSize(p->vPos) ); - assert( Vec_PtrSize( p->vBufs ) == 0 ); - // create fanouts - if ( p->fFanout == 0 ) - Ivy_ManStartFanout( p ); - // collect the POs to be converted into latches - for ( i = 0; i < nLatches; i++ ) - { - // get the latch value - Init = pInits? pInits[i] : IVY_INIT_0; - // create latch - pObj = Ivy_ManPo( p, Ivy_ManPoNum(p) - nLatches + i ); - pLatch = Ivy_Latch( p, Ivy_ObjChild0(pObj), Init ); - Ivy_ObjDisconnect( p, pObj ); - // recycle the old PO object - Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); - Ivy_ManRecycleMemory( p, pObj ); - // convert the corresponding PI to a buffer and connect it to the latch - pObj = Ivy_ManPi( p, Ivy_ManPiNum(p) - nLatches + i ); - pObj->Type = IVY_BUF; - Ivy_ObjConnect( p, pObj, pLatch, NULL ); - // save the buffer - Vec_PtrPush( p->vBufs, pObj ); - } - // shrink the arrays - Vec_PtrShrink( p->vPis, Ivy_ManPiNum(p) - nLatches ); - Vec_PtrShrink( p->vPos, Ivy_ManPoNum(p) - nLatches ); - // update the counters of different objects - p->nObjs[IVY_PI] -= nLatches; - p->nObjs[IVY_PO] -= nLatches; - p->nObjs[IVY_BUF] += nLatches; - p->nDeleted -= 2 * nLatches; - // remove dangling nodes - Ivy_ManCleanup(p); - Ivy_ManCleanupSeq(p); -/* - // check for dangling nodes - Ivy_ManForEachObj( p, pObj, i ) - if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsPo(pObj) && !Ivy_ObjIsConst1(pObj) ) - { - assert( Ivy_ObjRefs(pObj) > 0 ); - assert( Ivy_ObjRefs(pObj) == Ivy_ObjFanoutNum(p, pObj) ); - } -*/ - // perform hashing by propagating the buffers - Ivy_ManPropagateBuffers( p, 0 ); - if ( Ivy_ManBufNum(p) ) - printf( "The number of remaining buffers is %d.\n", Ivy_ManBufNum(p) ); - // fix the levels - Ivy_ManResetLevels( p ); - // check the resulting network - if ( !Ivy_ManCheck(p) ) - printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyMem.c b/src/aig/ivy/ivyMem.c deleted file mode 100644 index 2a96857c..00000000 --- a/src/aig/ivy/ivyMem.c +++ /dev/null @@ -1,116 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyMem.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Memory management for the AIG nodes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// memory management -#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes -#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManStartMemory( Ivy_Man_t * p ) -{ - p->vChunks = Vec_PtrAlloc( 128 ); - p->vPages = Vec_PtrAlloc( 128 ); -} - -/**Function************************************************************* - - Synopsis [Stops the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManStopMemory( Ivy_Man_t * p ) -{ - void * pMemory; - int i; - Vec_PtrForEachEntry( p->vChunks, pMemory, i ) - free( pMemory ); - Vec_PtrFree( p->vChunks ); - Vec_PtrFree( p->vPages ); - p->pListFree = NULL; -} - -/**Function************************************************************* - - Synopsis [Allocates additional memory for the nodes.] - - Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. - Records the pointer to the AIG manager in the -1 entry.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManAddMemory( Ivy_Man_t * p ) -{ - char * pMemory; - int i, nBytes; - int EntrySizeMax = 128; - assert( sizeof(Ivy_Obj_t) <= EntrySizeMax ); - assert( p->pListFree == NULL ); -// assert( (Ivy_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); - // allocate new memory page - nBytes = sizeof(Ivy_Obj_t) * (1<vChunks, pMemory ); - // align memory at the 32-byte boundary - pMemory = pMemory + EntrySizeMax - (((int)pMemory) & (EntrySizeMax-1)); - // remember the manager in the first entry - Vec_PtrPush( p->vPages, pMemory ); - // break the memory down into nodes - p->pListFree = (Ivy_Obj_t *)pMemory; - for ( i = 1; i <= IVY_PAGE_MASK; i++ ) - { - *((char **)pMemory) = pMemory + sizeof(Ivy_Obj_t); - pMemory += sizeof(Ivy_Obj_t); - } - *((char **)pMemory) = NULL; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyMulti.c b/src/aig/ivy/ivyMulti.c deleted file mode 100644 index a7970156..00000000 --- a/src/aig/ivy/ivyMulti.c +++ /dev/null @@ -1,301 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyMulti.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Constructing multi-input AND/EXOR gates.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define IVY_EVAL_LIMIT 128 - -typedef struct Ivy_Eva_t_ Ivy_Eva_t; -struct Ivy_Eva_t_ -{ - Ivy_Obj_t * pArg; // the argument node - unsigned Mask; // the mask of covered nodes - int Weight; // the number of covered nodes -}; - -static void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ); -static int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Constructs a balanced tree while taking sharing into account.] - - Description [Returns 1 if the implementation exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSols ) -{ - static Ivy_Eva_t pEvals[IVY_EVAL_LIMIT]; - Ivy_Eva_t * pEval, * pFan0, * pFan1; - Ivy_Obj_t * pObj, * pTemp; - int nEvals, nEvalsOld, i, k, x, nLeaves; - unsigned uMaskAll; - - // consider special cases - nLeaves = Vec_PtrSize(vLeaves); - assert( nLeaves > 2 ); - if ( nLeaves > 32 || nLeaves + Vec_PtrSize(vCone) > IVY_EVAL_LIMIT ) - return 0; -// if ( nLeaves == 1 ) -// return Vec_PtrEntry( vLeaves, 0 ); -// if ( nLeaves == 2 ) -// return Ivy_Oper( Vec_PtrEntry(vLeaves, 0), Vec_PtrEntry(vLeaves, 1), Type ); - - // set the leaf entries - uMaskAll = ((1 << nLeaves) - 1); - nEvals = 0; - Vec_PtrForEachEntry( vLeaves, pObj, i ) - { - pEval = pEvals + nEvals; - pEval->pArg = pObj; - pEval->Mask = (1 << nEvals); - pEval->Weight = 1; - // mark the leaf - Ivy_Regular(pObj)->TravId = nEvals; - nEvals++; - } - - // propagate masks through the cone - Vec_PtrForEachEntry( vCone, pObj, i ) - { - pObj->TravId = nEvals + i; - if ( Ivy_ObjIsBuf(pObj) ) - pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask; - else - pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask | pEvals[Ivy_ObjFanin1(pObj)->TravId].Mask; - } - - // set the internal entries - Vec_PtrForEachEntry( vCone, pObj, i ) - { - if ( i == Vec_PtrSize(vCone) - 1 ) - break; - // skip buffers - if ( Ivy_ObjIsBuf(pObj) ) - continue; - // skip nodes without external fanout - if ( Ivy_ObjRefs(pObj) == 0 ) - continue; - assert( !Ivy_IsComplement(pObj) ); - pEval = pEvals + nEvals; - pEval->pArg = pObj; - pEval->Mask = pEvals[pObj->TravId].Mask; - pEval->Weight = Extra_WordCountOnes(pEval->Mask); - // mark the node - pObj->TravId = nEvals; - nEvals++; - } - - // find the available nodes - nEvalsOld = nEvals; - for ( i = 1; i < nEvals; i++ ) - for ( k = 0; k < i; k++ ) - { - pFan0 = pEvals + i; - pFan1 = pEvals + k; - pTemp = Ivy_TableLookup(p, Ivy_ObjCreateGhost(p, pFan0->pArg, pFan1->pArg, Type, IVY_INIT_NONE)); - // skip nodes in the cone - if ( pTemp == NULL || pTemp->fMarkB ) - continue; - // skip the leaves - for ( x = 0; x < nLeaves; x++ ) - if ( pTemp == Ivy_Regular(vLeaves->pArray[x]) ) - break; - if ( x < nLeaves ) - continue; - pEval = pEvals + nEvals; - pEval->pArg = pTemp; - pEval->Mask = pFan0->Mask | pFan1->Mask; - pEval->Weight = (pFan0->Mask & pFan1->Mask) ? Extra_WordCountOnes(pEval->Mask) : pFan0->Weight + pFan1->Weight; - // save the argument - pObj->TravId = nEvals; - nEvals++; - // quit if the number of entries exceeded the limit - if ( nEvals == IVY_EVAL_LIMIT ) - goto Outside; - // quit if we found an acceptable implementation - if ( pEval->Mask == uMaskAll ) - goto Outside; - } -Outside: - -// Ivy_MultiPrint( pEvals, nLeaves, nEvals ); - if ( !Ivy_MultiCover( p, pEvals, nLeaves, nEvals, nLimit, vSols ) ) - return 0; - assert( Vec_PtrSize( vSols ) > 0 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes how many uncovered ones this one covers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ) -{ - Ivy_Eva_t * pEval; - int i, k; - for ( i = nLeaves; i < nEvals; i++ ) - { - pEval = pEvals + i; - printf( "%2d (id = %5d) : |", i-nLeaves, Ivy_ObjId(pEval->pArg) ); - for ( k = 0; k < nLeaves; k++ ) - { - if ( pEval->Mask & (1 << k) ) - printf( "+" ); - else - printf( " " ); - } - printf( "| Lev = %d.\n", Ivy_ObjLevel(pEval->pArg) ); - } -} - -/**Function************************************************************* - - Synopsis [Computes how many uncovered ones this one covers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_MultiWeight( unsigned uMask, int nMaskOnes, unsigned uFound ) -{ - assert( uMask & ~uFound ); - if ( (uMask & uFound) == 0 ) - return nMaskOnes; - return Extra_WordCountOnes( uMask & ~uFound ); -} - -/**Function************************************************************* - - Synopsis [Finds the cover.] - - Description [Returns 1 if the cover is found.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ) -{ - int fVerbose = 0; - Ivy_Eva_t * pEval, * pEvalBest; - unsigned uMaskAll, uFound, uTemp; - int i, k, BestK, WeightBest, WeightCur, LevelBest, LevelCur; - uMaskAll = (nLeaves == 32)? (~(unsigned)0) : ((1 << nLeaves) - 1); - uFound = 0; - // solve the covering problem - if ( fVerbose ) - printf( "Solution: " ); - Vec_PtrClear( vSols ); - for ( i = 0; i < nLimit; i++ ) - { - BestK = -1; - for ( k = nEvals - 1; k >= 0; k-- ) - { - pEval = pEvals + k; - if ( (pEval->Mask & ~uFound) == 0 ) - continue; - if ( BestK == -1 ) - { - BestK = k; - pEvalBest = pEval; - WeightBest = Ivy_MultiWeight( pEvalBest->Mask, pEvalBest->Weight, uFound ); - LevelBest = Ivy_ObjLevel( Ivy_Regular(pEvalBest->pArg) ); - continue; - } - // compare BestK and the new one (k) - WeightCur = Ivy_MultiWeight( pEval->Mask, pEval->Weight, uFound ); - LevelCur = Ivy_ObjLevel( Ivy_Regular(pEval->pArg) ); - if ( WeightBest < WeightCur || - (WeightBest == WeightCur && LevelBest > LevelCur) ) - { - BestK = k; - pEvalBest = pEval; - WeightBest = WeightCur; - LevelBest = LevelCur; - } - } - assert( BestK != -1 ); - // if the cost is only 1, take the leaf - if ( WeightBest == 1 && BestK >= nLeaves ) - { - uTemp = (pEvalBest->Mask & ~uFound); - for ( k = 0; k < nLeaves; k++ ) - if ( uTemp & (1 << k) ) - break; - assert( k < nLeaves ); - BestK = k; - pEvalBest = pEvals + BestK; - } - if ( fVerbose ) - { - if ( BestK < nLeaves ) - printf( "L(%d) ", BestK ); - else - printf( "%d ", BestK - nLeaves ); - } - // update the found set - Vec_PtrPush( vSols, pEvalBest->pArg ); - uFound |= pEvalBest->Mask; - if ( uFound == uMaskAll ) - break; - } - if ( uFound == uMaskAll ) - { - if ( fVerbose ) - printf( " Found \n\n" ); - return 1; - } - else - { - if ( fVerbose ) - printf( " Not found \n\n" ); - return 0; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyMulti8.c b/src/aig/ivy/ivyMulti8.c deleted file mode 100644 index 059d1500..00000000 --- a/src/aig/ivy/ivyMulti8.c +++ /dev/null @@ -1,427 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyMulti.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Constructing multi-input AND/EXOR gates.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ivy_Eval_t_ Ivy_Eval_t; -struct Ivy_Eval_t_ -{ - unsigned Mask : 5; // the mask of covered nodes - unsigned Weight : 3; // the number of covered nodes - unsigned Cost : 4; // the number of overlapping nodes - unsigned Level : 12; // the level of this node - unsigned Fan0 : 4; // the first fanin - unsigned Fan1 : 4; // the second fanin -}; - -static Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); -static void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ); -static int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ); -static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Constructs the well-balanced tree of gates.] - - Description [Disregards levels and possible logic sharing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pObj1, * pObj2; - if ( nObjs == 1 ) - return ppObjs[0]; - pObj1 = Ivy_Multi_rec( ppObjs, nObjs/2, Type ); - pObj2 = Ivy_Multi_rec( ppObjs + nObjs/2, nObjs - nObjs/2, Type ); - return Ivy_Oper( pObj1, pObj2, Type ); -} - -/**Function************************************************************* - - Synopsis [Constructs a balanced tree while taking sharing into account.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgsInit, int nArgs, Ivy_Type_t Type ) -{ - static char NumBits[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5}; - static Ivy_Eval_t pEvals[15+15*14/2]; - static Ivy_Obj_t * pArgs[16]; - Ivy_Eval_t * pEva, * pEvaBest; - int nArgsNew, nEvals, i, k; - Ivy_Obj_t * pTemp; - - // consider the case of one argument - assert( nArgs > 0 ); - if ( nArgs == 1 ) - return pArgsInit[0]; - // consider the case of two arguments - if ( nArgs == 2 ) - return Ivy_Oper( pArgsInit[0], pArgsInit[1], Type ); - -//Ivy_MultiEval( pArgsInit, nArgs, Type ); printf( "\n" ); - - // set the initial ones - for ( i = 0; i < nArgs; i++ ) - { - pArgs[i] = pArgsInit[i]; - pEva = pEvals + i; - pEva->Mask = (1 << i); - pEva->Weight = 1; - pEva->Cost = 0; - pEva->Level = Ivy_Regular(pArgs[i])->Level; - pEva->Fan0 = 0; - pEva->Fan1 = 0; - } - - // find the available nodes - pEvaBest = pEvals; - nArgsNew = nArgs; - for ( i = 1; i < nArgsNew; i++ ) - for ( k = 0; k < i; k++ ) - if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)) ) - { - pEva = pEvals + nArgsNew; - pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; - pEva->Weight = NumBits[pEva->Mask]; - pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; - pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); - pEva->Fan0 = k; - pEva->Fan1 = i; -// assert( pEva->Level == (unsigned)Ivy_ObjLevel(pTemp) ); - // compare - if ( pEvaBest->Weight < pEva->Weight || - pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || - pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) - pEvaBest = pEva; - // save the argument - pArgs[nArgsNew++] = pTemp; - if ( nArgsNew == 15 ) - goto Outside; - } -Outside: - -// printf( "Best = %d.\n", pEvaBest - pEvals ); - - // the case of no common nodes - if ( nArgsNew == nArgs ) - { - Ivy_MultiSort( pArgs, nArgs ); - return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); - } - // the case of one common node - if ( nArgsNew == nArgs + 1 ) - { - assert( pEvaBest - pEvals == nArgs ); - k = 0; - for ( i = 0; i < nArgs; i++ ) - if ( i != (int)pEvaBest->Fan0 && i != (int)pEvaBest->Fan1 ) - pArgs[k++] = pArgs[i]; - pArgs[k++] = pArgs[nArgs]; - assert( k == nArgs - 1 ); - nArgs = k; - Ivy_MultiSort( pArgs, nArgs ); - return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); - } - // the case when there is a node that covers everything - if ( (int)pEvaBest->Mask == ((1 << nArgs) - 1) ) - return Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); - - // evaluate node pairs - nEvals = nArgsNew; - for ( i = 1; i < nArgsNew; i++ ) - for ( k = 0; k < i; k++ ) - { - pEva = pEvals + nEvals; - pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; - pEva->Weight = NumBits[pEva->Mask]; - pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; - pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); - pEva->Fan0 = k; - pEva->Fan1 = i; - // compare - if ( pEvaBest->Weight < pEva->Weight || - pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || - pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) - pEvaBest = pEva; - // save the argument - nEvals++; - } - assert( pEvaBest - pEvals >= nArgsNew ); - -// printf( "Used (%d, %d).\n", pEvaBest->Fan0, pEvaBest->Fan1 ); - - // get the best implementation - pTemp = Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); - - // collect those not covered by EvaBest - k = 0; - for ( i = 0; i < nArgs; i++ ) - if ( (pEvaBest->Mask & (1 << i)) == 0 ) - pArgs[k++] = pArgs[i]; - pArgs[k++] = pTemp; - assert( k == nArgs - (int)pEvaBest->Weight + 1 ); - nArgs = k; - Ivy_MultiSort( pArgs, nArgs ); - return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Implements multi-input AND/EXOR operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pNode0, * pNode1; - if ( iNum < nArgs ) - return pArgs[iNum]; - pNode0 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan0, pArgs, nArgs, Type ); - pNode1 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan1, pArgs, nArgs, Type ); - return Ivy_Oper( pNode0, pNode1, Type ); -} - -/**Function************************************************************* - - Synopsis [Selection-sorts the nodes in the decreasing over of level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ) -{ - Ivy_Obj_t * pTemp; - int i, j, iBest; - - for ( i = 0; i < nArgs-1; i++ ) - { - iBest = i; - for ( j = i+1; j < nArgs; j++ ) - if ( Ivy_Regular(pArgs[j])->Level > Ivy_Regular(pArgs[iBest])->Level ) - iBest = j; - pTemp = pArgs[i]; - pArgs[i] = pArgs[iBest]; - pArgs[iBest] = pTemp; - } -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ) -{ - Ivy_Obj_t * pNode1, * pNode2; - int i; - // try to find the node in the array - for ( i = 0; i < nArgs; i++ ) - if ( pArray[i] == pNode ) - return nArgs; - // put the node last - pArray[nArgs++] = pNode; - // find the place to put the new node - for ( i = nArgs-1; i > 0; i-- ) - { - pNode1 = pArray[i ]; - pNode2 = pArray[i-1]; - if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level ) - break; - pArray[i ] = pNode2; - pArray[i-1] = pNode1; - } - return nArgs; -} - -/**Function************************************************************* - - Synopsis [Balances the array recursively.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pNodeNew; - // consider the case of one argument - assert( nArgs > 0 ); - if ( nArgs == 1 ) - return pArgs[0]; - // consider the case of two arguments - if ( nArgs == 2 ) - return Ivy_Oper( pArgs[0], pArgs[1], Type ); - // get the last two nodes - pNodeNew = Ivy_Oper( pArgs[nArgs-1], pArgs[nArgs-2], Type ); - // add the new node - nArgs = Ivy_MultiPushUniqueOrderByLevel( pArgs, nArgs - 2, pNodeNew ); - return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Implements multi-input AND/EXOR operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pTemp; - int i, k; - int nArgsOld = nArgs; - for ( i = 0; i < nArgs; i++ ) - printf( "%d[%d] ", i, Ivy_Regular(pArgs[i])->Level ); - for ( i = 1; i < nArgs; i++ ) - for ( k = 0; k < i; k++ ) - { - pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)); - if ( pTemp != NULL ) - { - printf( "%d[%d]=(%d,%d) ", nArgs, Ivy_Regular(pTemp)->Level, k, i ); - pArgs[nArgs++] = pTemp; - } - } - printf( " ((%d/%d)) ", nArgsOld, nArgs-nArgsOld ); - return NULL; -} - - - -/**Function************************************************************* - - Synopsis [Old code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pArgsRef[5], * pTemp; - int i, k, m, nArgsNew, Counter = 0; - - -//Ivy_MultiEval( pArgs, nArgs, Type ); printf( "\n" ); - - - assert( Type == IVY_AND || Type == IVY_EXOR ); - assert( nArgs > 0 ); - if ( nArgs == 1 ) - return pArgs[0]; - - // find the nodes with more than one fanout - nArgsNew = 0; - for ( i = 0; i < nArgs; i++ ) - if ( Ivy_ObjRefs( Ivy_Regular(pArgs[i]) ) > 0 ) - pArgsRef[nArgsNew++] = pArgs[i]; - - // go through pairs - if ( nArgsNew >= 2 ) - for ( i = 0; i < nArgsNew; i++ ) - for ( k = i + 1; k < nArgsNew; k++ ) - if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) - Counter++; -// printf( "%d", Counter ); - - // go through pairs - if ( nArgsNew >= 2 ) - for ( i = 0; i < nArgsNew; i++ ) - for ( k = i + 1; k < nArgsNew; k++ ) - if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) - { - nArgsNew = 0; - for ( m = 0; m < nArgs; m++ ) - if ( pArgs[m] != pArgsRef[i] && pArgs[m] != pArgsRef[k] ) - pArgs[nArgsNew++] = pArgs[m]; - pArgs[nArgsNew++] = pTemp; - assert( nArgsNew == nArgs - 1 ); - return Ivy_Multi1( pArgs, nArgsNew, Type ); - } - return Ivy_Multi_rec( pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Old code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi2( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - assert( Type == IVY_AND || Type == IVY_EXOR ); - assert( nArgs > 0 ); - return Ivy_Multi_rec( pArgs, nArgs, Type ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyObj.c b/src/aig/ivy/ivyObj.c deleted file mode 100644 index 59dda19c..00000000 --- a/src/aig/ivy/ivyObj.c +++ /dev/null @@ -1,476 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyObj.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Adding/removing objects.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ) -{ - return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, NULL, NULL, IVY_PI, IVY_INIT_NONE) ); -} - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ) -{ - return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pDriver, NULL, IVY_PO, IVY_INIT_NONE) ); -} - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) -{ - Ivy_Obj_t * pObj; - assert( !Ivy_IsComplement(pGhost) ); - assert( Ivy_ObjIsGhost(pGhost) ); - assert( Ivy_TableLookup(p, pGhost) == NULL ); - // get memory for the new object - pObj = Ivy_ManFetchMemory( p ); - assert( Ivy_ObjIsNone(pObj) ); - pObj->Id = Vec_PtrSize(p->vObjs); - Vec_PtrPush( p->vObjs, pObj ); - // add basic info (fanins, compls, type, init) - pObj->Type = pGhost->Type; - pObj->Init = pGhost->Init; - // add connections - Ivy_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); - // compute level - if ( Ivy_ObjIsNode(pObj) ) - pObj->Level = Ivy_ObjLevelNew(pObj); - else if ( Ivy_ObjIsLatch(pObj) ) - pObj->Level = 0; - else if ( Ivy_ObjIsOneFanin(pObj) ) - pObj->Level = Ivy_ObjFanin0(pObj)->Level; - else if ( !Ivy_ObjIsPi(pObj) ) - assert( 0 ); - // create phase - if ( Ivy_ObjIsNode(pObj) ) - pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) & Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); - else if ( Ivy_ObjIsOneFanin(pObj) ) - pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); - // set the fail TFO flag - if ( Ivy_ObjIsNode(pObj) ) - pObj->fFailTfo = Ivy_ObjFanin0(pObj)->fFailTfo | Ivy_ObjFanin1(pObj)->fFailTfo; - // mark the fanins in a special way if the node is EXOR - if ( Ivy_ObjIsExor(pObj) ) - { - Ivy_ObjFanin0(pObj)->fExFan = 1; - Ivy_ObjFanin1(pObj)->fExFan = 1; - } - // add PIs/POs to the arrays - if ( Ivy_ObjIsPi(pObj) ) - Vec_PtrPush( p->vPis, pObj ); - else if ( Ivy_ObjIsPo(pObj) ) - Vec_PtrPush( p->vPos, pObj ); -// else if ( Ivy_ObjIsBuf(pObj) ) -// Vec_PtrPush( p->vBufs, pObj ); - if ( p->vRequired && Vec_IntSize(p->vRequired) <= pObj->Id ) - Vec_IntFillExtra( p->vRequired, 2 * Vec_IntSize(p->vRequired), 1000000 ); - // update node counters of the manager - p->nObjs[Ivy_ObjType(pObj)]++; - p->nCreated++; - -// printf( "Adding %sAIG node: ", p->pHaig==NULL? "H":" " ); -// Ivy_ObjPrintVerbose( p, pObj, p->pHaig==NULL ); -// printf( "\n" ); - - // if HAIG is defined, create a corresponding node - if ( p->pHaig ) - Ivy_ManHaigCreateObj( p, pObj ); - return pObj; -} - -/**Function************************************************************* - - Synopsis [Connect the object to the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || pFan1 != NULL ); - // add the first fanin - pObj->pFanin0 = pFan0; - pObj->pFanin1 = pFan1; - // increment references of the fanins and add their fanouts - if ( Ivy_ObjFanin0(pObj) != NULL ) - { - Ivy_ObjRefsInc( Ivy_ObjFanin0(pObj) ); - if ( p->fFanout ) - Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); - } - if ( Ivy_ObjFanin1(pObj) != NULL ) - { - Ivy_ObjRefsInc( Ivy_ObjFanin1(pObj) ); - if ( p->fFanout ) - Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); - } - // add the node to the structural hash table - Ivy_TableInsert( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Connect the object to the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || Ivy_ObjFanin1(pObj) != NULL ); - // remove connections - if ( pObj->pFanin0 != NULL ) - { - Ivy_ObjRefsDec(Ivy_ObjFanin0(pObj)); - if ( p->fFanout ) - Ivy_ObjDeleteFanout( p, Ivy_ObjFanin0(pObj), pObj ); - } - if ( pObj->pFanin1 != NULL ) - { - Ivy_ObjRefsDec(Ivy_ObjFanin1(pObj)); - if ( p->fFanout ) - Ivy_ObjDeleteFanout( p, Ivy_ObjFanin1(pObj), pObj ); - } - assert( pObj->pNextFan0 == NULL ); - assert( pObj->pNextFan1 == NULL ); - assert( pObj->pPrevFan0 == NULL ); - assert( pObj->pPrevFan1 == NULL ); - // remove the node from the structural hash table - Ivy_TableDelete( p, pObj ); - // add the first fanin - pObj->pFanin0 = NULL; - pObj->pFanin1 = NULL; -} - -/**Function************************************************************* - - Synopsis [Replaces the first fanin of the node by the new fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ) -{ - Ivy_Obj_t * pFaninOld; - assert( !Ivy_IsComplement(pObj) ); - pFaninOld = Ivy_ObjFanin0(pObj); - // decrement ref and remove fanout - Ivy_ObjRefsDec( pFaninOld ); - if ( p->fFanout ) - Ivy_ObjDeleteFanout( p, pFaninOld, pObj ); - // update the fanin - pObj->pFanin0 = pFaninNew; - // increment ref and add fanout - Ivy_ObjRefsInc( Ivy_Regular(pFaninNew) ); - if ( p->fFanout ) - Ivy_ObjAddFanout( p, Ivy_Regular(pFaninNew), pObj ); - // get rid of old fanin - if ( !Ivy_ObjIsPi(pFaninOld) && !Ivy_ObjIsConst1(pFaninOld) && Ivy_ObjRefs(pFaninOld) == 0 ) - Ivy_ObjDelete_rec( p, pFaninOld, 1 ); -} - -/**Function************************************************************* - - Synopsis [Deletes the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) -{ - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjRefs(pObj) == 0 || !fFreeTop ); - // update node counters of the manager - p->nObjs[pObj->Type]--; - p->nDeleted++; - // remove connections - Ivy_ObjDisconnect( p, pObj ); - // remove PIs/POs from the arrays - if ( Ivy_ObjIsPi(pObj) ) - Vec_PtrRemove( p->vPis, pObj ); - else if ( Ivy_ObjIsPo(pObj) ) - Vec_PtrRemove( p->vPos, pObj ); - else if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) - Vec_PtrRemove( p->vBufs, pObj ); - // clean and recycle the entry - if ( fFreeTop ) - { - // free the node - Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); - Ivy_ManRecycleMemory( p, pObj ); - } - else - { - int nRefsOld = pObj->nRefs; - Ivy_Obj_t * pFanout = pObj->pFanout; - Ivy_ObjClean( pObj ); - pObj->pFanout = pFanout; - pObj->nRefs = nRefsOld; - } -} - -/**Function************************************************************* - - Synopsis [Deletes the MFFC of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) -{ - Ivy_Obj_t * pFanin0, * pFanin1; - assert( !Ivy_IsComplement(pObj) ); - assert( !Ivy_ObjIsNone(pObj) ); - if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsPi(pObj) ) - return; - pFanin0 = Ivy_ObjFanin0(pObj); - pFanin1 = Ivy_ObjFanin1(pObj); - Ivy_ObjDelete( p, pObj, fFreeTop ); - if ( pFanin0 && !Ivy_ObjIsNone(pFanin0) && Ivy_ObjRefs(pFanin0) == 0 ) - Ivy_ObjDelete_rec( p, pFanin0, 1 ); - if ( pFanin1 && !Ivy_ObjIsNone(pFanin1) && Ivy_ObjRefs(pFanin1) == 0 ) - Ivy_ObjDelete_rec( p, pFanin1, 1 ); -} - -/**Function************************************************************* - - Synopsis [Replaces one object by another.] - - Description [Both objects are currently in the manager. The new object - (pObjNew) should be used instead of the old object (pObjOld). If the - new object is complemented or used, the buffer is added.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ) -{ - int nRefsOld;//, clk; - // the object to be replaced cannot be complemented - assert( !Ivy_IsComplement(pObjOld) ); - // the object to be replaced cannot be a terminal - assert( Ivy_ObjIsNone(pObjOld) || !Ivy_ObjIsPi(pObjOld) ); - // the object to be used cannot be a PO or assert - assert( !Ivy_ObjIsBuf(Ivy_Regular(pObjNew)) ); - // the object cannot be the same - assert( pObjOld != Ivy_Regular(pObjNew) ); -//printf( "Replacing %d by %d.\n", Ivy_Regular(pObjOld)->Id, Ivy_Regular(pObjNew)->Id ); - - // if HAIG is defined, create the choice node - if ( p->pHaig ) - { -// if ( pObjOld->Id == 31 ) -// { -// Ivy_ManShow( p, 0 ); -// Ivy_ManShow( p->pHaig, 1 ); -// } - Ivy_ManHaigCreateChoice( p, pObjOld, pObjNew ); - } - // if the new object is complemented or already used, add the buffer - if ( Ivy_IsComplement(pObjNew) || Ivy_ObjIsLatch(pObjNew) || Ivy_ObjRefs(pObjNew) > 0 || Ivy_ObjIsPi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) - pObjNew = Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pObjNew, NULL, IVY_BUF, IVY_INIT_NONE) ); - assert( !Ivy_IsComplement(pObjNew) ); - if ( fUpdateLevel ) - { -//clk = clock(); - // if the new node's arrival time is different, recursively update arrival time of the fanouts - if ( p->fFanout && !Ivy_ObjIsBuf(pObjNew) && pObjOld->Level != pObjNew->Level ) - { - assert( Ivy_ObjIsNode(pObjOld) ); - pObjOld->Level = pObjNew->Level; - Ivy_ObjUpdateLevel_rec( p, pObjOld ); - } -//p->time1 += clock() - clk; - // if the new node's required time has changed, recursively update required time of the fanins -//clk = clock(); - if ( p->vRequired ) - { - int ReqNew = Vec_IntEntry(p->vRequired, pObjOld->Id); - if ( ReqNew < Vec_IntEntry(p->vRequired, pObjNew->Id) ) - { - Vec_IntWriteEntry( p->vRequired, pObjNew->Id, ReqNew ); - Ivy_ObjUpdateLevelR_rec( p, pObjNew, ReqNew ); - } - } -//p->time2 += clock() - clk; - } - // delete the old object - if ( fDeleteOld ) - Ivy_ObjDelete_rec( p, pObjOld, fFreeTop ); - // make sure object is not pointing to itself - assert( Ivy_ObjFanin0(pObjNew) == NULL || pObjOld != Ivy_ObjFanin0(pObjNew) ); - assert( Ivy_ObjFanin1(pObjNew) == NULL || pObjOld != Ivy_ObjFanin1(pObjNew) ); - // make sure the old node has no fanin fanout pointers - if ( p->fFanout ) - { - assert( pObjOld->pFanout != NULL ); - assert( pObjNew->pFanout == NULL ); - pObjNew->pFanout = pObjOld->pFanout; - } - // transfer the old object - assert( Ivy_ObjRefs(pObjNew) == 0 ); - nRefsOld = pObjOld->nRefs; - Ivy_ObjOverwrite( pObjOld, pObjNew ); - pObjOld->nRefs = nRefsOld; - // patch the fanout of the fanins - if ( p->fFanout ) - { - Ivy_ObjPatchFanout( p, Ivy_ObjFanin0(pObjOld), pObjNew, pObjOld ); - if ( Ivy_ObjFanin1(pObjOld) ) - Ivy_ObjPatchFanout( p, Ivy_ObjFanin1(pObjOld), pObjNew, pObjOld ); - } - // update the hash table - Ivy_TableUpdate( p, pObjNew, pObjOld->Id ); - // recycle the object that was taken over by pObjOld - Vec_PtrWriteEntry( p->vObjs, pObjNew->Id, NULL ); - Ivy_ManRecycleMemory( p, pObjNew ); - // if the new node is the buffer propagate it - if ( p->fFanout && Ivy_ObjIsBuf(pObjOld) ) - Vec_PtrPush( p->vBufs, pObjOld ); -// Ivy_ManCheckFanouts( p ); -// printf( "\n" ); -/* - if ( p->pHaig ) - { - int x; - Ivy_ManShow( p, 0, NULL ); - Ivy_ManShow( p->pHaig, 1, NULL ); - x = 0; - } -*/ -// if ( Ivy_ManCheckFanoutNums(p) ) -// { -// int x = 0; -// } -} - -/**Function************************************************************* - - Synopsis [Fixes buffer fanins.] - - Description [This situation happens because NodeReplace is a lazy - procedure, which does not propagate the change to the fanouts but - instead records the change in the form of a buf/inv node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ) -{ - Ivy_Obj_t * pFanReal0, * pFanReal1, * pResult; - if ( Ivy_ObjIsPo(pNode) ) - { - if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ) - return; - pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); - Ivy_ObjPatchFanin0( p, pNode, pFanReal0 ); -// Ivy_ManCheckFanouts( p ); - return; - } - if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) && !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ) - return; - // get the real fanins - pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); - pFanReal1 = Ivy_ObjReal( Ivy_ObjChild1(pNode) ); - // get the new node - if ( Ivy_ObjIsNode(pNode) ) - pResult = Ivy_Oper( p, pFanReal0, pFanReal1, Ivy_ObjType(pNode) ); - else if ( Ivy_ObjIsLatch(pNode) ) - pResult = Ivy_Latch( p, pFanReal0, Ivy_ObjInit(pNode) ); - else - assert( 0 ); - -//printf( "===== Replacing %d by %d.\n", pNode->Id, pResult->Id ); -//Ivy_ObjPrintVerbose( p, pNode, 0 ); printf( "\n" ); -//Ivy_ObjPrintVerbose( p, pResult, 0 ); printf( "\n" ); - - // perform the replacement - Ivy_ObjReplace( p, pNode, pResult, 1, 0, fUpdateLevel ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyOper.c b/src/aig/ivy/ivyOper.c deleted file mode 100644 index 8115ce4f..00000000 --- a/src/aig/ivy/ivyOper.c +++ /dev/null @@ -1,293 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyOper.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [AIG operations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// procedure to detect an EXOR gate -static inline int Ivy_ObjIsExorType( Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Obj_t ** ppFan0, Ivy_Obj_t ** ppFan1 ) -{ - if ( !Ivy_IsComplement(p0) || !Ivy_IsComplement(p1) ) - return 0; - p0 = Ivy_Regular(p0); - p1 = Ivy_Regular(p1); - if ( !Ivy_ObjIsAnd(p0) || !Ivy_ObjIsAnd(p1) ) - return 0; - if ( Ivy_ObjFanin0(p0) != Ivy_ObjFanin0(p1) || Ivy_ObjFanin1(p0) != Ivy_ObjFanin1(p1) ) - return 0; - if ( Ivy_ObjFaninC0(p0) == Ivy_ObjFaninC0(p1) || Ivy_ObjFaninC1(p0) == Ivy_ObjFaninC1(p1) ) - return 0; - *ppFan0 = Ivy_ObjChild0(p0); - *ppFan1 = Ivy_ObjChild1(p0); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Perform one operation.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ) -{ - if ( Type == IVY_AND ) - return Ivy_And( p, p0, p1 ); - if ( Type == IVY_EXOR ) - return Ivy_Exor( p, p0, p1 ); - assert( 0 ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) -{ -// Ivy_Obj_t * pFan0, * pFan1; - // check trivial cases - if ( p0 == p1 ) - return p0; - if ( p0 == Ivy_Not(p1) ) - return Ivy_Not(p->pConst1); - if ( Ivy_Regular(p0) == p->pConst1 ) - return p0 == p->pConst1 ? p1 : Ivy_Not(p->pConst1); - if ( Ivy_Regular(p1) == p->pConst1 ) - return p1 == p->pConst1 ? p0 : Ivy_Not(p->pConst1); - // check if it can be an EXOR gate -// if ( Ivy_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) -// return Ivy_CanonExor( pFan0, pFan1 ); - return Ivy_CanonAnd( p, p0, p1 ); -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) -{ -/* - // check trivial cases - if ( p0 == p1 ) - return Ivy_Not(p->pConst1); - if ( p0 == Ivy_Not(p1) ) - return p->pConst1; - if ( Ivy_Regular(p0) == p->pConst1 ) - return Ivy_NotCond( p1, p0 == p->pConst1 ); - if ( Ivy_Regular(p1) == p->pConst1 ) - return Ivy_NotCond( p0, p1 == p->pConst1 ); - // check the table - return Ivy_CanonExor( p, p0, p1 ); -*/ - return Ivy_Or( p, Ivy_And(p, p0, Ivy_Not(p1)), Ivy_And(p, Ivy_Not(p0), p1) ); -} - -/**Function************************************************************* - - Synopsis [Implements Boolean OR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) -{ - return Ivy_Not( Ivy_And( p, Ivy_Not(p0), Ivy_Not(p1) ) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ) -{ - Ivy_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; - int Count0, Count1; - // consider trivial cases - if ( p0 == Ivy_Not(p1) ) - return Ivy_Exor( p, pC, p0 ); - // other cases can be added - // implement the first MUX (F = C * x1 + C' * x0) - pTempA1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, p1, IVY_AND, IVY_INIT_NONE) ); - pTempA2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), p0, IVY_AND, IVY_INIT_NONE) ); - if ( pTempA1 && pTempA2 ) - { - pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempA1), Ivy_Not(pTempA2), IVY_AND, IVY_INIT_NONE) ); - if ( pTemp ) return Ivy_Not(pTemp); - } - Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); - // implement the second MUX (F' = C * x1' + C' * x0') - pTempB1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, Ivy_Not(p1), IVY_AND, IVY_INIT_NONE) ); - pTempB2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), Ivy_Not(p0), IVY_AND, IVY_INIT_NONE) ); - if ( pTempB1 && pTempB2 ) - { - pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempB1), Ivy_Not(pTempB2), IVY_AND, IVY_INIT_NONE) ); - if ( pTemp ) return pTemp; - } - Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); - // compare and decide which one to implement - if ( Count0 >= Count1 ) - { - pTempA1 = pTempA1? pTempA1 : Ivy_And(p, pC, p1); - pTempA2 = pTempA2? pTempA2 : Ivy_And(p, Ivy_Not(pC), p0); - return Ivy_Or( p, pTempA1, pTempA2 ); - } - pTempB1 = pTempB1? pTempB1 : Ivy_And(p, pC, Ivy_Not(p1)); - pTempB2 = pTempB2? pTempB2 : Ivy_And(p, Ivy_Not(pC), Ivy_Not(p0)); - return Ivy_Not( Ivy_Or( p, pTempB1, pTempB2 ) ); - -// return Ivy_Or( Ivy_And(pC, p1), Ivy_And(Ivy_Not(pC), p0) ); -} - -/**Function************************************************************* - - Synopsis [Implements ITE operation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ) -{ - return Ivy_Or( p, Ivy_Or(p, Ivy_And(p, pA, pB), Ivy_And(p, pA, pC)), Ivy_And(p, pB, pC) ); -} - -/**Function************************************************************* - - Synopsis [Constructs the well-balanced tree of gates.] - - Description [Disregards levels and possible logic sharing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) -{ - Ivy_Obj_t * pObj1, * pObj2; - if ( nObjs == 1 ) - return ppObjs[0]; - pObj1 = Ivy_Multi_rec( p, ppObjs, nObjs/2, Type ); - pObj2 = Ivy_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); - return Ivy_Oper( p, pObj1, pObj2, Type ); -} - -/**Function************************************************************* - - Synopsis [Old code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) -{ - assert( Type == IVY_AND || Type == IVY_EXOR ); - assert( nArgs > 0 ); - return Ivy_Multi_rec( p, pArgs, nArgs, Type ); -} - -/**Function************************************************************* - - Synopsis [Implements the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ) -{ - int i; - assert( vPairs->nSize > 0 ); - assert( vPairs->nSize % 2 == 0 ); - // go through the cubes of the node's SOP - for ( i = 0; i < vPairs->nSize; i += 2 ) - vPairs->pArray[i/2] = Ivy_Not( Ivy_Exor( p, vPairs->pArray[i], vPairs->pArray[i+1] ) ); - vPairs->nSize = vPairs->nSize/2; - return Ivy_Not( Ivy_Multi_rec( p, (Ivy_Obj_t **)vPairs->pArray, vPairs->nSize, IVY_AND ) ); -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) -{ - return Ivy_CanonLatch( p, pObj, Init ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyResyn.c b/src/aig/ivy/ivyResyn.c deleted file mode 100644 index f42d7464..00000000 --- a/src/aig/ivy/ivyResyn.c +++ /dev/null @@ -1,196 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyResyn.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [AIG rewriting script.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyResyn.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs several passes of rewriting on the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) -{ - int clk; - Ivy_Man_t * pTemp; - -if ( fVerbose ) { printf( "Original:\n" ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pMan, fUpdateLevel ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); -clk = clock(); - Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Performs several passes of rewriting on the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) -{ - int clk; - Ivy_Man_t * pTemp; - -if ( fVerbose ) { printf( "Original:\n" ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pMan, fUpdateLevel ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); -clk = clock(); - Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); -clk = clock(); - Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); -clk = clock(); - Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Performs several passes of rewriting on the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ) -{ - int clk; - Ivy_Man_t * pTemp; - -if ( fVerbose ) { printf( "Original:\n" ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - Ivy_ManRewritePre( pMan, 0, 0, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, 0 ); -// pMan = Ivy_ManDup( pTemp = pMan ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -/* -clk = clock(); - Ivy_ManRewritePre( pMan, 0, 0, 0 ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Rewrite", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); - -clk = clock(); - pMan = Ivy_ManBalance( pTemp = pMan, 0 ); - Ivy_ManStop( pTemp ); -if ( fVerbose ) { printf( "\n" ); } -if ( fVerbose ) { PRT( "Balance", clock() - clk ); } -if ( fVerbose ) Ivy_ManPrintStats( pMan ); -*/ - return pMan; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyRwr.c b/src/aig/ivy/ivyRwr.c deleted file mode 100644 index 3f8720ba..00000000 --- a/src/aig/ivy/ivyRwr.c +++ /dev/null @@ -1,609 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyRwt.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Rewriting based on precomputation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyRwt.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" -#include "deco.h" -#include "rwt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ); -static int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ); -static Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, - Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ); - -static int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); -static void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs incremental rewriting of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ) -{ - Rwt_Man_t * pManRwt; - Ivy_Obj_t * pNode; - int i, nNodes, nGain; - int clk, clkStart = clock(); - // start the rewriting manager - pManRwt = Rwt_ManStart( 0 ); - p->pData = pManRwt; - if ( pManRwt == NULL ) - return 0; - // create fanouts - if ( fUpdateLevel && p->fFanout == 0 ) - Ivy_ManStartFanout( p ); - // compute the reverse levels if level update is requested - if ( fUpdateLevel ) - Ivy_ManRequiredLevels( p ); - // set the number of levels -// p->nLevelMax = Ivy_ManLevels( p ); - // resynthesize each node once - nNodes = Ivy_ManObjIdMax(p); - Ivy_ManForEachNode( p, pNode, i ) - { - // fix the fanin buffer problem - Ivy_NodeFixBufferFanins( p, pNode, 1 ); - if ( Ivy_ObjIsBuf(pNode) ) - continue; - // stop if all nodes have been tried once - if ( i > nNodes ) - break; - // for each cut, try to resynthesize it - nGain = Ivy_NodeRewrite( p, pManRwt, pNode, fUpdateLevel, fUseZeroCost ); - if ( nGain > 0 || nGain == 0 && fUseZeroCost ) - { - Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt); - int fCompl = Rwt_ManReadCompl(pManRwt); -/* - { - Ivy_Obj_t * pObj; - int i; - printf( "USING: (" ); - Vec_PtrForEachEntry( Rwt_ManReadLeaves(pManRwt), pObj, i ) - printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pObj)) ); - printf( ") Gain = %d.\n", nGain ); - } - if ( nGain > 0 ) - { // print stats on the MFFC - extern void Ivy_NodeMffsConeSuppPrint( Ivy_Obj_t * pNode ); - printf( "Node %6d : Gain = %4d ", pNode->Id, nGain ); - Ivy_NodeMffsConeSuppPrint( pNode ); - } -*/ - // complement the FF if needed -clk = clock(); - if ( fCompl ) Dec_GraphComplement( pGraph ); - Ivy_GraphUpdateNetwork( p, pNode, pGraph, fUpdateLevel, nGain ); - if ( fCompl ) Dec_GraphComplement( pGraph ); -Rwt_ManAddTimeUpdate( pManRwt, clock() - clk ); - } - } -Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart ); - // print stats - if ( fVerbose ) - Rwt_ManPrintStats( pManRwt ); - // delete the managers - Rwt_ManStop( pManRwt ); - p->pData = NULL; - // fix the levels - if ( fUpdateLevel ) - Vec_IntFree( p->vRequired ), p->vRequired = NULL; - else - Ivy_ManResetLevels( p ); - // check - if ( i = Ivy_ManCleanup(p) ) - printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); - if ( !Ivy_ManCheck(p) ) - printf( "Ivy_ManRewritePre(): The check has failed.\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs rewriting for one node.] - - Description [This procedure considers all the cuts computed for the node - and tries to rewrite each of them using the "forest" of different AIG - structures precomputed and stored in the RWR manager. - Determines the best rewriting and computes the gain in the number of AIG - nodes in the final network. In the end, p->vFanins contains information - about the best cut that can be used for rewriting, while p->pGraph gives - the decomposition dag (represented using decomposition graph data structure). - Returns gain in the number of nodes or -1 if node cannot be rewritten.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ) -{ - int fVeryVerbose = 0; - Dec_Graph_t * pGraph; - Ivy_Store_t * pStore; - Ivy_Cut_t * pCut; - Ivy_Obj_t * pFanin; - unsigned uPhase, uTruthBest, uTruth; - char * pPerm; - int Required, nNodesSaved, nNodesSaveCur; - int i, c, GainCur, GainBest = -1; - int clk, clk2; - - p->nNodesConsidered++; - // get the required times - Required = fUpdateLevel? Vec_IntEntry( pMan->vRequired, pNode->Id ) : 1000000; - // get the node's cuts -clk = clock(); - pStore = Ivy_NodeFindCutsAll( pMan, pNode, 5 ); -p->timeCut += clock() - clk; - - // go through the cuts -clk = clock(); - for ( c = 1; c < pStore->nCuts; c++ ) - { - pCut = pStore->pCuts + c; - // consider only 4-input cuts - if ( pCut->nSize != 4 ) - continue; - // skip the cuts with buffers - for ( i = 0; i < (int)pCut->nSize; i++ ) - if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, pCut->pArray[i]) ) ) - break; - if ( i != pCut->nSize ) - { - p->nCutsBad++; - continue; - } - p->nCutsGood++; - // get the fanin permutation -clk2 = clock(); - uTruth = 0xFFFF & Ivy_NodeGetTruth( pNode, pCut->pArray, pCut->nSize ); // truth table -p->timeTruth += clock() - clk2; - pPerm = p->pPerms4[ p->pPerms[uTruth] ]; - uPhase = p->pPhases[uTruth]; - // collect fanins with the corresponding permutation/phase - Vec_PtrClear( p->vFaninsCur ); - Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); - for ( i = 0; i < (int)pCut->nSize; i++ ) - { - pFanin = Ivy_ManObj( pMan, pCut->pArray[pPerm[i]] ); - assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) ); - pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); - Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); - } -clk2 = clock(); -/* - printf( "Considering: (" ); - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pFanin)) ); - printf( ")\n" ); -*/ - // mark the fanin boundary - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); - // label MFFC with current ID - Ivy_ManIncrementTravId( pMan ); - nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); - // unmark the fanin boundary - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); -p->timeMffc += clock() - clk2; - - // evaluate the cut -clk2 = clock(); - pGraph = Rwt_CutEvaluate( pMan, p, pNode, p->vFaninsCur, nNodesSaved, Required, &GainCur, uTruth ); -p->timeEval += clock() - clk2; - - // check if the cut is better than the current best one - if ( pGraph != NULL && GainBest < GainCur ) - { - // save this form - nNodesSaveCur = nNodesSaved; - GainBest = GainCur; - p->pGraph = pGraph; - p->fCompl = ((uPhase & (1<<4)) > 0); - uTruthBest = uTruth; - // collect fanins in the - Vec_PtrClear( p->vFanins ); - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Vec_PtrPush( p->vFanins, pFanin ); - } - } -p->timeRes += clock() - clk; - - if ( GainBest == -1 ) - return -1; - -// printf( "%d", nNodesSaveCur - GainBest ); -/* - if ( GainBest > 0 ) - { - if ( Rwt_CutIsintean( pNode, p->vFanins ) ) - printf( "b" ); - else - { - printf( "Node %d : ", pNode->Id ); - Vec_PtrForEachEntry( p->vFanins, pFanin, i ) - printf( "%d ", Ivy_Regular(pFanin)->Id ); - printf( "a" ); - } - } -*/ -/* - if ( GainBest > 0 ) - if ( p->fCompl ) - printf( "c" ); - else - printf( "." ); -*/ - - // copy the leaves - Vec_PtrForEachEntry( p->vFanins, pFanin, i ) - Dec_GraphNode(p->pGraph, i)->pFunc = pFanin; - - p->nScores[p->pMap[uTruthBest]]++; - p->nNodesGained += GainBest; - if ( fUseZeroCost || GainBest > 0 ) - p->nNodesRewritten++; - - // report the progress - if ( fVeryVerbose && GainBest > 0 ) - { - printf( "Node %6d : ", Ivy_ObjId(pNode) ); - printf( "Fanins = %d. ", p->vFanins->nSize ); - printf( "Save = %d. ", nNodesSaveCur ); - printf( "Add = %d. ", nNodesSaveCur-GainBest ); - printf( "GAIN = %d. ", GainBest ); - printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); - printf( "Class = %d. ", p->pMap[uTruthBest] ); - printf( "\n" ); - } - return GainBest; -} - -/**Function************************************************************* - - Synopsis [Computes the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_NodeGetTruth_rec( Ivy_Obj_t * pObj, int * pNums, int nNums ) -{ - static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - unsigned uTruth0, uTruth1; - int i; - for ( i = 0; i < nNums; i++ ) - if ( pObj->Id == pNums[i] ) - return uMasks[i]; - assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); - uTruth0 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin0(pObj), pNums, nNums ); - if ( Ivy_ObjFaninC0(pObj) ) - uTruth0 = ~uTruth0; - if ( Ivy_ObjIsBuf(pObj) ) - return uTruth0; - uTruth1 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin1(pObj), pNums, nNums ); - if ( Ivy_ObjFaninC1(pObj) ) - uTruth1 = ~uTruth1; - return uTruth0 & uTruth1; -} - - -/**Function************************************************************* - - Synopsis [Computes the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ) -{ - assert( nNums < 6 ); - return Ivy_NodeGetTruth_rec( pObj, pNums, nNums ); -} - -/**Function************************************************************* - - Synopsis [Evaluates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ) -{ - Vec_Ptr_t * vSubgraphs; - Dec_Graph_t * pGraphBest, * pGraphCur; - Rwt_Node_t * pNode, * pFanin; - int nNodesAdded, GainBest, i, k; - // find the matching class of subgraphs - vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); - p->nSubgraphs += vSubgraphs->nSize; - // determine the best subgraph - GainBest = -1; - Vec_PtrForEachEntry( vSubgraphs, pNode, i ) - { - // get the current graph - pGraphCur = (Dec_Graph_t *)pNode->pNext; - // copy the leaves - Vec_PtrForEachEntry( vFaninsCur, pFanin, k ) - Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; - // detect how many unlabeled nodes will be reused - nNodesAdded = Ivy_GraphToNetworkCount( pMan, pRoot, pGraphCur, nNodesSaved, LevelMax ); - if ( nNodesAdded == -1 ) - continue; - assert( nNodesSaved >= nNodesAdded ); - // count the gain at this node - if ( GainBest < nNodesSaved - nNodesAdded ) - { - GainBest = nNodesSaved - nNodesAdded; - pGraphBest = pGraphCur; - } - } - if ( GainBest == -1 ) - return NULL; - *pGainBest = GainBest; - return pGraphBest; -} - - -/**Function************************************************************* - - Synopsis [Counts the number of new nodes added when using this graph.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure. - Returns -1 if the number of nodes and levels exceeded the given limit or - the number of levels exceeded the maximum allowed level.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ) -{ - Dec_Node_t * pNode, * pNode0, * pNode1; - Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; - int i, Counter, LevelNew, LevelOld; - // check for constant function or a literal - if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) - return 0; - // set the levels of the leaves - Dec_GraphForEachLeaf( pGraph, pNode, i ) - pNode->Level = Ivy_Regular(pNode->pFunc)->Level; - // compute the AIG size after adding the internal nodes - Counter = 0; - Dec_GraphForEachNode( pGraph, pNode, i ) - { - // get the children of this node - pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); - pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); - // get the AIG nodes corresponding to the children - pAnd0 = pNode0->pFunc; - pAnd1 = pNode1->pFunc; - if ( pAnd0 && pAnd1 ) - { - // if they are both present, find the resulting node - pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); - pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); - pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); - // return -1 if the node is the same as the original root - if ( Ivy_Regular(pAnd) == pRoot ) - return -1; - } - else - pAnd = NULL; - // count the number of added nodes - if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) - { - if ( ++Counter > NodeMax ) - return -1; - } - // count the number of new levels - LevelNew = 1 + RWT_MAX( pNode0->Level, pNode1->Level ); - if ( pAnd ) - { - if ( Ivy_Regular(pAnd) == p->pConst1 ) - LevelNew = 0; - else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd0) ) - LevelNew = (int)Ivy_Regular(pAnd0)->Level; - else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd1) ) - LevelNew = (int)Ivy_Regular(pAnd1)->Level; - LevelOld = (int)Ivy_Regular(pAnd)->Level; -// assert( LevelNew == LevelOld ); - } - if ( LevelNew > LevelMax ) - return -1; - pNode->pFunc = pAnd; - pNode->Level = LevelNew; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_GraphToNetwork( Ivy_Man_t * p, Dec_Graph_t * pGraph ) -{ - Ivy_Obj_t * pAnd0, * pAnd1; - Dec_Node_t * pNode; - int i; - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - return Ivy_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); - // build the AIG nodes corresponding to the AND gates of the graph - Dec_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); - } - // complement the result if necessary - return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Replaces MFFC of the node by the new factored form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) -{ - Ivy_Obj_t * pRootNew; - int nNodesNew, nNodesOld, Required; - Required = fUpdateLevel? Vec_IntEntry( p->vRequired, pRoot->Id ) : 1000000; - nNodesOld = Ivy_ManNodeNum(p); - // create the new structure of nodes - pRootNew = Ivy_GraphToNetwork( p, pGraph ); - assert( (int)Ivy_Regular(pRootNew)->Level <= Required ); -// if ( Ivy_Regular(pRootNew)->Level == Required ) -// printf( "Difference %d.\n", Ivy_Regular(pRootNew)->Level - Required ); - // remove the old nodes -// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); -/* - if ( Ivy_IsComplement(pRootNew) ) - printf( "c" ); - else - printf( "d" ); - if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) - printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); - printf( " " ); -*/ - Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 1 ); - // compare the gains - nNodesNew = Ivy_ManNodeNum(p); - assert( nGain <= nNodesOld - nNodesNew ); - // propagate the buffer - Ivy_ManPropagateBuffers( p, 1 ); -} - -/**Function************************************************************* - - Synopsis [Replaces MFFC of the node by the new factored form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_GraphUpdateNetwork3( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) -{ - Ivy_Obj_t * pRootNew, * pFanin; - int nNodesNew, nNodesOld, i, nRefsOld; - nNodesOld = Ivy_ManNodeNum(p); - -//printf( "Before = %d. ", Ivy_ManNodeNum(p) ); - // mark the cut - Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) - Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); - // deref the old cone - nRefsOld = pRoot->nRefs; - pRoot->nRefs = 0; - Ivy_ObjDelete_rec( p, pRoot, 0 ); - pRoot->nRefs = nRefsOld; - // unmark the cut - Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) - Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); -//printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); - - // create the new structure of nodes - pRootNew = Ivy_GraphToNetwork( p, pGraph ); -//printf( "Create = %d. ", Ivy_ManNodeNum(p) ); - // remove the old nodes -// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); -/* - if ( Ivy_IsComplement(pRootNew) ) - printf( "c" ); - else - printf( "d" ); - if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) - printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); - printf( " " ); -*/ - Ivy_ObjReplace( p, pRoot, pRootNew, 0, 0, 1 ); -//printf( "Replace = %d. ", Ivy_ManNodeNum(p) ); - - // delete remaining dangling nodes - Vec_PtrForEachEntry( ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) - { - pFanin = Ivy_Regular(pFanin); - if ( !Ivy_ObjIsNone(pFanin) && Ivy_ObjRefs(pFanin) == 0 ) - Ivy_ObjDelete_rec( p, pFanin, 1 ); - } -//printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); -//printf( "\n" ); - - // compare the gains - nNodesNew = Ivy_ManNodeNum(p); - assert( nGain <= nNodesOld - nNodesNew ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyRwrAlg.c b/src/aig/ivy/ivyRwrAlg.c deleted file mode 100644 index fc48deb0..00000000 --- a/src/aig/ivy/ivyRwrAlg.c +++ /dev/null @@ -1,408 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyRwrAlg.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Algebraic AIG rewriting.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyRwrAlg.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ); -static Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ); -static int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Algebraic AIG rewriting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ) -{ - Vec_Int_t * vRequired; - Vec_Ptr_t * vFront, * vLeaves, * vCone, * vSol; - Ivy_Obj_t * pObj, * pResult; - int i, RetValue, LevelR, nNodesOld; - int CountUsed, CountUndo; - vRequired = fUpdateLevel? Ivy_ManRequiredLevels( p ) : NULL; - vFront = Vec_PtrAlloc( 100 ); - vLeaves = Vec_PtrAlloc( 100 ); - vCone = Vec_PtrAlloc( 100 ); - vSol = Vec_PtrAlloc( 100 ); - // go through the nodes in the topological order - CountUsed = CountUndo = 0; - nNodesOld = Ivy_ManObjIdNext(p); - Ivy_ManForEachObj( p, pObj, i ) - { - assert( !Ivy_ObjIsBuf(pObj) ); - if ( i >= nNodesOld ) - break; - // skip no-nodes and MUX roots - if ( !Ivy_ObjIsNode(pObj) || Ivy_ObjIsExor(pObj) || Ivy_ObjIsMuxType(pObj) ) - continue; -// if ( pObj->Id > 297 ) // 296 --- 297 -// break; - if ( pObj->Id == 297 ) - { - int x = 0; - } - // get the largest algebraic cut - RetValue = Ivy_ManFindAlgCut( pObj, vFront, vLeaves, vCone ); - // the case of a trivial tree cut - if ( RetValue == 1 ) - continue; - // the case of constant 0 cone - if ( RetValue == -1 ) - { - Ivy_ObjReplace( pObj, Ivy_ManConst0(p), 1, 0, 1 ); - continue; - } - assert( Vec_PtrSize(vLeaves) > 2 ); - // get the required level for this node - LevelR = vRequired? Vec_IntEntry(vRequired, pObj->Id) : 1000000; - // create a new cone - pResult = Ivy_NodeRewriteAlg( pObj, vFront, vLeaves, vCone, vSol, LevelR, fUseZeroCost ); - if ( pResult == NULL || pResult == pObj ) - continue; - assert( Vec_PtrSize(vSol) == 1 || !Ivy_IsComplement(pResult) ); - if ( Ivy_ObjLevel(Ivy_Regular(pResult)) > LevelR && Ivy_ObjRefs(Ivy_Regular(pResult)) == 0 ) - Ivy_ObjDelete_rec(Ivy_Regular(pResult), 1), CountUndo++; - else - Ivy_ObjReplace( pObj, pResult, 1, 0, 1 ), CountUsed++; - } - printf( "Used = %d. Undo = %d.\n", CountUsed, CountUndo ); - Vec_PtrFree( vFront ); - Vec_PtrFree( vCone ); - Vec_PtrFree( vSol ); - if ( vRequired ) Vec_IntFree( vRequired ); - if ( i = Ivy_ManCleanup(p) ) - printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); - if ( !Ivy_ManCheck(p) ) - printf( "Ivy_ManRewriteAlg(): The check has failed.\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Analizes one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ) -{ - int fVerbose = 0; - Ivy_Obj_t * pTemp; - int k, Counter, nMffc, RetValue; - - if ( fVerbose ) - { - if ( Ivy_ObjIsExor(pObj) ) - printf( "x " ); - else - printf( " " ); - } - -/* - printf( "%d ", Vec_PtrSize(vFront) ); - printf( "( " ); - Vec_PtrForEachEntry( vFront, pTemp, k ) - printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); - printf( ")\n" ); -*/ - // collect nodes in the cone - if ( Ivy_ObjIsExor(pObj) ) - Ivy_ManCollectCone( pObj, vFront, vCone ); - else - Ivy_ManCollectCone( pObj, vLeaves, vCone ); - - // deref nodes in the cone - Vec_PtrForEachEntry( vCone, pTemp, k ) - { - Ivy_ObjRefsDec( Ivy_ObjFanin0(pTemp) ); - Ivy_ObjRefsDec( Ivy_ObjFanin1(pTemp) ); - pTemp->fMarkB = 1; - } - - // count the MFFC size - Vec_PtrForEachEntry( vFront, pTemp, k ) - Ivy_Regular(pTemp)->fMarkA = 1; - nMffc = Ivy_NodeCountMffc( pObj ); - Vec_PtrForEachEntry( vFront, pTemp, k ) - Ivy_Regular(pTemp)->fMarkA = 0; - - if ( fVerbose ) - { - Counter = 0; - Vec_PtrForEachEntry( vCone, pTemp, k ) - Counter += (Ivy_ObjRefs(pTemp) > 0); - printf( "%5d : Leaves = %2d. Cone = %2d. ConeRef = %2d. Mffc = %d. Lev = %d. LevR = %d.\n", - pObj->Id, Vec_PtrSize(vFront), Vec_PtrSize(vCone), Counter-1, nMffc, Ivy_ObjLevel(pObj), LevelR ); - } -/* - printf( "Leaves:" ); - Vec_PtrForEachEntry( vLeaves, pTemp, k ) - printf( " %d%s", Ivy_Regular(pTemp)->Id, Ivy_IsComplement(pTemp)? "\'" : "" ); - printf( "\n" ); - printf( "Cone:\n" ); - Vec_PtrForEachEntry( vCone, pTemp, k ) - printf( " %5d = %d%s %d%s\n", pTemp->Id, - Ivy_ObjFaninId0(pTemp), Ivy_ObjFaninC0(pTemp)? "\'" : "", - Ivy_ObjFaninId1(pTemp), Ivy_ObjFaninC1(pTemp)? "\'" : "" ); -*/ - - RetValue = Ivy_MultiPlus( vLeaves, vCone, Ivy_ObjType(pObj), nMffc + fUseZeroCost, vSols ); - - // ref nodes in the cone - Vec_PtrForEachEntry( vCone, pTemp, k ) - { - Ivy_ObjRefsInc( Ivy_ObjFanin0(pTemp) ); - Ivy_ObjRefsInc( Ivy_ObjFanin1(pTemp) ); - pTemp->fMarkA = 0; - pTemp->fMarkB = 0; - } - - if ( !RetValue ) - return NULL; - - if ( Vec_PtrSize( vSols ) == 1 ) - return Vec_PtrEntry( vSols, 0 ); - return Ivy_NodeBalanceBuildSuper( vSols, Ivy_ObjType(pObj), 1 ); -} - -/**Function************************************************************* - - Synopsis [Comparison for node pointers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCountMffc_rec( Ivy_Obj_t * pNode ) -{ - if ( Ivy_ObjRefs(pNode) > 0 || Ivy_ObjIsCi(pNode) || pNode->fMarkA ) - return 0; - assert( pNode->fMarkB ); - pNode->fMarkA = 1; -// printf( "%d ", pNode->Id ); - if ( Ivy_ObjIsBuf(pNode) ) - return Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ); - return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); -} - -/**Function************************************************************* - - Synopsis [Comparison for node pointers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ) -{ - assert( pNode->fMarkB ); - return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); -} - -/**Function************************************************************* - - Synopsis [Comparison for node pointers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindAlgCutCompare( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) -{ - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Computing one algebraic cut.] - - Description [Returns 1 if the tree-leaves of this node where traversed - and found to have no external references (and have not been collected). - Returns 0 if the tree-leaves have external references and are collected.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindAlgCut_rec( Ivy_Obj_t * pObj, Ivy_Type_t Type, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) -{ - int RetValue0, RetValue1; - Ivy_Obj_t * pObjR = Ivy_Regular(pObj); - assert( !Ivy_ObjIsBuf(pObjR) ); - assert( Type != IVY_EXOR || !Ivy_IsComplement(pObj) ); - - // make sure the node is not visited twice in different polarities - if ( Ivy_IsComplement(pObj) ) - { // if complemented, mark B - if ( pObjR->fMarkA ) - return -1; - pObjR->fMarkB = 1; - } - else - { // if non-complicated, mark A - if ( pObjR->fMarkB ) - return -1; - pObjR->fMarkA = 1; - } - Vec_PtrPush( vCone, pObjR ); - - // if the node is the end of the tree, return - if ( Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Type ) - { - if ( Ivy_ObjRefs(pObjR) == 1 ) - return 1; - assert( Ivy_ObjRefs(pObjR) > 1 ); - Vec_PtrPush( vFront, pObj ); - return 0; - } - - // branch on the node - assert( !Ivy_IsComplement(pObj) ); - assert( Ivy_ObjIsNode(pObj) ); - // what if buffer has more than one fanout??? - RetValue0 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild0(pObj) ), Type, vFront, vCone ); - RetValue1 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild1(pObj) ), Type, vFront, vCone ); - if ( RetValue0 == -1 || RetValue1 == -1 ) - return -1; - - // the case when both have no external references - if ( RetValue0 && RetValue1 ) - { - if ( Ivy_ObjRefs(pObj) == 1 ) - return 1; - assert( Ivy_ObjRefs(pObj) > 1 ); - Vec_PtrPush( vFront, pObj ); - return 0; - } - // the case when one of them has external references - if ( RetValue0 ) - Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild0(pObj) ) ); - if ( RetValue1 ) - Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild1(pObj) ) ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Computing one algebraic cut.] - - Description [Algebraic cut stops when we hit (a) CI, (b) complemented edge, - (c) boundary of different gates. Returns 1 if this is a pure tree. - Returns -1 if the contant 0 is detected. Return 0 if the array can be used.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ) -{ - Ivy_Obj_t * pObj, * pPrev; - int RetValue, i; - assert( !Ivy_IsComplement(pRoot) ); - assert( Ivy_ObjIsNode(pRoot) ); - // clear the frontier and collect the nodes - Vec_PtrClear( vCone ); - Vec_PtrClear( vFront ); - Vec_PtrClear( vLeaves ); - RetValue = Ivy_ManFindAlgCut_rec( pRoot, Ivy_ObjType(pRoot), vFront, vCone ); - // clean the marks - Vec_PtrForEachEntry( vCone, pObj, i ) - pObj->fMarkA = pObj->fMarkB = 0; - // quit if the same node is found in both polarities - if ( RetValue == -1 ) - return -1; - // return if the node is the root of a tree - if ( RetValue == 1 ) - return 1; - // return if the cut is composed of two nodes - if ( Vec_PtrSize(vFront) <= 2 ) - return 1; - // sort the entries in increasing order - Vec_PtrSort( vFront, Ivy_ManFindAlgCutCompare ); - // remove duplicates from vFront and save the nodes in vLeaves - pPrev = Vec_PtrEntry(vFront, 0); - Vec_PtrPush( vLeaves, pPrev ); - Vec_PtrForEachEntryStart( vFront, pObj, i, 1 ) - { - // compare current entry and the previous entry - if ( pObj == pPrev ) - { - if ( Ivy_ObjIsExor(pRoot) ) // A <+> A = 0 - { - // vLeaves are no longer structural support of pRoot!!! - Vec_PtrPop(vLeaves); - pPrev = Vec_PtrSize(vLeaves) == 0 ? NULL : Vec_PtrEntryLast(vLeaves); - } - continue; - } - if ( pObj == Ivy_Not(pPrev) ) - { - assert( Ivy_ObjIsAnd(pRoot) ); - return -1; - } - pPrev = pObj; - Vec_PtrPush( vLeaves, pObj ); - } - if ( Vec_PtrSize(vLeaves) == 0 ) - return -1; - if ( Vec_PtrSize(vLeaves) <= 2 ) - return 1; - return 0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivySeq.c b/src/aig/ivy/ivySeq.c deleted file mode 100644 index 0ee29fee..00000000 --- a/src/aig/ivy/ivySeq.c +++ /dev/null @@ -1,1134 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivySeq.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivySeq.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" -#include "deco.h" -#include "rwt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ); -static void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ); -static unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ); -static Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ); -static int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ); -static Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ); -static void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ); -static Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); - -static inline int Ivy_CutHashValue( int NodeId ) { return 1 << (NodeId % 31); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//int nMoves; -//int nMovesS; -//int nClauses; -//int timeInv; - -/**Function************************************************************* - - Synopsis [Performs incremental rewriting of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ) -{ - Rwt_Man_t * pManRwt; - Ivy_Obj_t * pNode; - int i, nNodes, nGain; - int clk, clkStart = clock(); - - // set the DC latch values - Ivy_ManForEachLatch( p, pNode, i ) - pNode->Init = IVY_INIT_DC; - // start the rewriting manager - pManRwt = Rwt_ManStart( 0 ); - p->pData = pManRwt; - if ( pManRwt == NULL ) - return 0; - // create fanouts - if ( p->fFanout == 0 ) - Ivy_ManStartFanout( p ); - // resynthesize each node once - nNodes = Ivy_ManObjIdMax(p); - Ivy_ManForEachNode( p, pNode, i ) - { - assert( !Ivy_ObjIsBuf(pNode) ); - assert( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ); - assert( !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ); - // fix the fanin buffer problem -// Ivy_NodeFixBufferFanins( p, pNode ); -// if ( Ivy_ObjIsBuf(pNode) ) -// continue; - // stop if all nodes have been tried once - if ( i > nNodes ) - break; - // for each cut, try to resynthesize it - nGain = Ivy_NodeRewriteSeq( p, pManRwt, pNode, fUseZeroCost ); - if ( nGain > 0 || nGain == 0 && fUseZeroCost ) - { - Dec_Graph_t * pGraph = Rwt_ManReadDecs(pManRwt); - int fCompl = Rwt_ManReadCompl(pManRwt); - // complement the FF if needed -clk = clock(); - if ( fCompl ) Dec_GraphComplement( pGraph ); - Ivy_GraphUpdateNetworkSeq( p, pNode, pGraph, nGain ); - if ( fCompl ) Dec_GraphComplement( pGraph ); -Rwt_ManAddTimeUpdate( pManRwt, clock() - clk ); - } - } -Rwt_ManAddTimeTotal( pManRwt, clock() - clkStart ); - // print stats - if ( fVerbose ) - Rwt_ManPrintStats( pManRwt ); - // delete the managers - Rwt_ManStop( pManRwt ); - p->pData = NULL; - // fix the levels - Ivy_ManResetLevels( p ); -// if ( Ivy_ManCheckFanoutNums(p) ) -// printf( "Ivy_ManRewritePre(): The check has failed.\n" ); - // check - if ( !Ivy_ManCheck(p) ) - printf( "Ivy_ManRewritePre(): The check has failed.\n" ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Performs rewriting for one node.] - - Description [This procedure considers all the cuts computed for the node - and tries to rewrite each of them using the "forest" of different AIG - structures precomputed and stored in the RWR manager. - Determines the best rewriting and computes the gain in the number of AIG - nodes in the final network. In the end, p->vFanins contains information - about the best cut that can be used for rewriting, while p->pGraph gives - the decomposition dag (represented using decomposition graph data structure). - Returns gain in the number of nodes or -1 if node cannot be rewritten.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ) -{ - int fVeryVerbose = 0; - Dec_Graph_t * pGraph; - Ivy_Store_t * pStore; - Ivy_Cut_t * pCut; - Ivy_Obj_t * pFanin;//, * pFanout; - Vec_Ptr_t * vFanout; - unsigned uPhase, uTruthBest, uTruth;//, nNewClauses; - char * pPerm; - int nNodesSaved, nNodesSaveCur; - int i, c, GainCur, GainBest = -1; - int clk, clk2;//, clk3; - - p->nNodesConsidered++; - // get the node's cuts -clk = clock(); - pStore = Ivy_CutComputeForNode( pMan, pNode, 5 ); -p->timeCut += clock() - clk; - - // go through the cuts -clk = clock(); - vFanout = Vec_PtrAlloc( 100 ); - for ( c = 1; c < pStore->nCuts; c++ ) - { - pCut = pStore->pCuts + c; - // consider only 4-input cuts - if ( pCut->nSize != 4 ) - continue; - // skip the cuts with buffers - for ( i = 0; i < (int)pCut->nSize; i++ ) - if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, Ivy_LeafId(pCut->pArray[i])) ) ) - break; - if ( i != pCut->nSize ) - { - p->nCutsBad++; - continue; - } - p->nCutsGood++; - // get the fanin permutation -clk2 = clock(); - uTruth = 0xFFFF & Ivy_CutGetTruth( pMan, pNode, pCut->pArray, pCut->nSize ); // truth table -p->timeTruth += clock() - clk2; - pPerm = p->pPerms4[ p->pPerms[uTruth] ]; - uPhase = p->pPhases[uTruth]; - // collect fanins with the corresponding permutation/phase - Vec_PtrClear( p->vFaninsCur ); - Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); - for ( i = 0; i < (int)pCut->nSize; i++ ) - { - pFanin = Ivy_ManObj( pMan, Ivy_LeafId( pCut->pArray[pPerm[i]] ) ); - assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) || Ivy_ObjIsConst1(pFanin) ); - pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); - Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); - } -clk2 = clock(); - // mark the fanin boundary - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); - // label MFFC with current ID - Ivy_ManIncrementTravId( pMan ); - nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); - // label fanouts with the current ID -// Ivy_ObjForEachFanout( pMan, pNode, vFanout, pFanout, i ) -// Ivy_ObjSetTravIdCurrent( pMan, pFanout ); - // unmark the fanin boundary - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); -p->timeMffc += clock() - clk2; - - // evaluate the cut -clk2 = clock(); - pGraph = Rwt_CutEvaluateSeq( pMan, p, pNode, pCut, pPerm, p->vFaninsCur, nNodesSaved, &GainCur, uTruth ); -p->timeEval += clock() - clk2; - - - // check if the cut is better than the current best one - if ( pGraph != NULL && GainBest < GainCur ) - { - // save this form - nNodesSaveCur = nNodesSaved; - GainBest = GainCur; - p->pGraph = pGraph; - p->pCut = pCut; - p->pPerm = pPerm; - p->fCompl = ((uPhase & (1<<4)) > 0); - uTruthBest = uTruth; - // collect fanins in the - Vec_PtrClear( p->vFanins ); - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Vec_PtrPush( p->vFanins, pFanin ); - } - } - Vec_PtrFree( vFanout ); -p->timeRes += clock() - clk; - - if ( GainBest == -1 ) - return -1; -/* - { - Ivy_Cut_t * pCut = p->pCut; - printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); - for ( i = 0; i < pCut->nSize; i++ ) - printf( " %d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); - printf( " }\n" ); - } -*/ - -//clk3 = clock(); -//nNewClauses = Ivy_CutTruthPrint( pMan, p->pCut, uTruth ); -//timeInv += clock() - clk; - -// nClauses += nNewClauses; -// nMoves++; -// if ( nNewClauses > 0 ) -// nMovesS++; - - // copy the leaves - Ivy_GraphPrepare( p->pGraph, p->pCut, p->vFanins, p->pPerm ); - - p->nScores[p->pMap[uTruthBest]]++; - p->nNodesGained += GainBest; - if ( fUseZeroCost || GainBest > 0 ) - p->nNodesRewritten++; - -/* - if ( GainBest > 0 ) - { - Ivy_Cut_t * pCut = p->pCut; - printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); - for ( i = 0; i < pCut->nSize; i++ ) - printf( " %5d(%2d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); - printf( " }\n" ); - } -*/ - - // report the progress - if ( fVeryVerbose && GainBest > 0 ) - { - printf( "Node %6d : ", Ivy_ObjId(pNode) ); - printf( "Fanins = %d. ", p->vFanins->nSize ); - printf( "Save = %d. ", nNodesSaveCur ); - printf( "Add = %d. ", nNodesSaveCur-GainBest ); - printf( "GAIN = %d. ", GainBest ); - printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); - printf( "Class = %d. ", p->pMap[uTruthBest] ); - printf( "\n" ); - } - return GainBest; -} - - -/**Function************************************************************* - - Synopsis [Evaluates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ) -{ - Vec_Ptr_t * vSubgraphs; - Dec_Graph_t * pGraphBest, * pGraphCur; - Rwt_Node_t * pNode; - int nNodesAdded, GainBest, i; - // find the matching class of subgraphs - vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); - p->nSubgraphs += vSubgraphs->nSize; - // determine the best subgraph - GainBest = -1; - Vec_PtrForEachEntry( vSubgraphs, pNode, i ) - { - // get the current graph - pGraphCur = (Dec_Graph_t *)pNode->pNext; - -// if ( pRoot->Id == 8648 ) -// Dec_GraphPrint( stdout, pGraphCur, NULL, NULL ); - // copy the leaves -// Vec_PtrForEachEntry( vFaninsCur, pFanin, k ) -// Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; - Ivy_GraphPrepare( pGraphCur, pCut, vFaninsCur, pPerm ); - - // detect how many unlabeled nodes will be reused - nNodesAdded = Ivy_GraphToNetworkSeqCountSeq( pMan, pRoot, pGraphCur, nNodesSaved ); - if ( nNodesAdded == -1 ) - continue; - assert( nNodesSaved >= nNodesAdded ); - // count the gain at this node - if ( GainBest < nNodesSaved - nNodesAdded ) - { - GainBest = nNodesSaved - nNodesAdded; - pGraphBest = pGraphCur; - } - } - if ( GainBest == -1 ) - return NULL; - *pGainBest = GainBest; - return pGraphBest; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ) -{ - Dec_Node_t * pNode, * pNode0, * pNode1; - int i; - assert( Dec_GraphLeaveNum(pGraph) == pCut->nSize ); - assert( Vec_PtrSize(vFanins) == pCut->nSize ); - // label the leaves with latch numbers - Dec_GraphForEachLeaf( pGraph, pNode, i ) - { - pNode->pFunc = Vec_PtrEntry( vFanins, i ); - pNode->nLat2 = Ivy_LeafLat( pCut->pArray[pPerm[i]] ); - } - // propagate latches through the nodes - Dec_GraphForEachNode( pGraph, pNode, i ) - { - // get the children of this node - pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); - pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); - // distribute the latches - pNode->nLat2 = IVY_MIN( pNode0->nLat2, pNode1->nLat2 ); - pNode->nLat0 = pNode0->nLat2 - pNode->nLat2; - pNode->nLat1 = pNode1->nLat2 - pNode->nLat2; - } -} - -/**Function************************************************************* - - Synopsis [Counts the number of new nodes added when using this graph.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure. - Returns -1 if the number of nodes and levels exceeded the given limit or - the number of levels exceeded the maximum allowed level.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ) -{ - Dec_Node_t * pNode, * pNode0, * pNode1; - Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; - int i, k, Counter, fCompl; - // check for constant function or a literal - if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) - return 0; - // compute the AIG size after adding the internal nodes - Counter = 0; - Dec_GraphForEachNode( pGraph, pNode, i ) - { - // get the children of this node - pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); - pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); - // get the AIG nodes corresponding to the children - pAnd0 = pNode0->pFunc; - pAnd1 = pNode1->pFunc; - // skip the latches - for ( k = 0; pAnd0 && k < (int)pNode->nLat0; k++ ) - { - fCompl = Ivy_IsComplement(pAnd0); - pAnd0 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd0), NULL, IVY_LATCH, IVY_INIT_DC) ); - if ( pAnd0 ) - pAnd0 = Ivy_NotCond( pAnd0, fCompl ); - } - for ( k = 0; pAnd1 && k < (int)pNode->nLat1; k++ ) - { - fCompl = Ivy_IsComplement(pAnd1); - pAnd1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd1), NULL, IVY_LATCH, IVY_INIT_DC) ); - if ( pAnd1 ) - pAnd1 = Ivy_NotCond( pAnd1, fCompl ); - } - // get the new node - if ( pAnd0 && pAnd1 ) - { - // if they are both present, find the resulting node - pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); - pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); - assert( !Ivy_ObjIsLatch(Ivy_Regular(pAnd0)) || !Ivy_ObjIsLatch(Ivy_Regular(pAnd1)) ); - if ( Ivy_Regular(pAnd0) == Ivy_Regular(pAnd1) || Ivy_ObjIsConst1(Ivy_Regular(pAnd0)) || Ivy_ObjIsConst1(Ivy_Regular(pAnd1)) ) - pAnd = Ivy_And( p, pAnd0, pAnd1 ); - else - pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); - // return -1 if the node is the same as the original root - if ( Ivy_Regular(pAnd) == pRoot ) - return -1; - } - else - pAnd = NULL; - // count the number of added nodes - if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) - { - if ( ++Counter > NodeMax ) - return -1; - } - pNode->pFunc = pAnd; - } - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ) -{ - Ivy_Obj_t * pAnd0, * pAnd1; - Dec_Node_t * pNode; - int i, k; - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - { - // get the variable node - pNode = Dec_GraphVar(pGraph); - // add the remaining latches - for ( k = 0; k < (int)pNode->nLat2; k++ ) - pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC ); - return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); - } - // build the AIG nodes corresponding to the AND gates of the graph - Dec_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - // add the latches - for ( k = 0; k < (int)pNode->nLat0; k++ ) - pAnd0 = Ivy_Latch( p, pAnd0, IVY_INIT_DC ); - for ( k = 0; k < (int)pNode->nLat1; k++ ) - pAnd1 = Ivy_Latch( p, pAnd1, IVY_INIT_DC ); - // create the node - pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); - } - // add the remaining latches - for ( k = 0; k < (int)pNode->nLat2; k++ ) - pNode->pFunc = Ivy_Latch( p, pNode->pFunc, IVY_INIT_DC ); - // complement the result if necessary - return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Replaces MFFC of the node by the new factored form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ) -{ - Ivy_Obj_t * pRootNew; - int nNodesNew, nNodesOld; - nNodesOld = Ivy_ManNodeNum(p); - // create the new structure of nodes - pRootNew = Ivy_GraphToNetworkSeq( p, pGraph ); - Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 0 ); - // compare the gains - nNodesNew = Ivy_ManNodeNum(p); - assert( nGain <= nNodesOld - nNodesNew ); - // propagate the buffer - Ivy_ManPropagateBuffers( p, 0 ); -} - - - - - - - - - -/**Function************************************************************* - - Synopsis [Computes the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_CutGetTruth_rec( Ivy_Man_t * p, int Leaf, int * pNums, int nNums ) -{ - static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - unsigned uTruth0, uTruth1; - Ivy_Obj_t * pObj; - int i; - for ( i = 0; i < nNums; i++ ) - if ( Leaf == pNums[i] ) - return uMasks[i]; - pObj = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); - if ( Ivy_ObjIsLatch(pObj) ) - { - assert( !Ivy_ObjFaninC0(pObj) ); - Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) + 1 ); - return Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); - } - assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); - Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) ); - uTruth0 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); - if ( Ivy_ObjFaninC0(pObj) ) - uTruth0 = ~uTruth0; - if ( Ivy_ObjIsBuf(pObj) ) - return uTruth0; - Leaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pObj), Ivy_LeafLat(Leaf) ); - uTruth1 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); - if ( Ivy_ObjFaninC1(pObj) ) - uTruth1 = ~uTruth1; - return uTruth0 & uTruth1; -} - - -/**Function************************************************************* - - Synopsis [Computes the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ) -{ - assert( Ivy_ObjIsNode(pObj) ); - assert( nNums < 6 ); - return Ivy_CutGetTruth_rec( p, Ivy_LeafCreate(pObj->Id, 0), pNums, nNums ); -} - - - - - -/**Function************************************************************* - - Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) -{ - int i; - if ( pCut->nSize < pCut->nSizeMax ) - return 1; - for ( i = 0; i < pCut->nSize; i++ ) - if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Derives new cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutDeriveNew2( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) -{ - unsigned uHash = 0; - int i, k; - assert( pCut->nSize > 0 ); - assert( IdNew0 < IdNew1 ); - for ( i = k = 0; i < pCut->nSize; i++ ) - { - if ( pCut->pArray[i] == IdOld ) - continue; - if ( IdNew0 >= 0 ) - { - if ( IdNew0 <= pCut->pArray[i] ) - { - if ( IdNew0 < pCut->pArray[i] ) - { - if ( k == pCut->nSizeMax ) - return 0; - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_CutHashValue( IdNew0 ); - } - IdNew0 = -1; - } - } - if ( IdNew1 >= 0 ) - { - if ( IdNew1 <= pCut->pArray[i] ) - { - if ( IdNew1 < pCut->pArray[i] ) - { - if ( k == pCut->nSizeMax ) - return 0; - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_CutHashValue( IdNew1 ); - } - IdNew1 = -1; - } - } - if ( k == pCut->nSizeMax ) - return 0; - pCutNew->pArray[ k++ ] = pCut->pArray[i]; - uHash |= Ivy_CutHashValue( pCut->pArray[i] ); - } - if ( IdNew0 >= 0 ) - { - if ( k == pCut->nSizeMax ) - return 0; - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_CutHashValue( IdNew0 ); - } - if ( IdNew1 >= 0 ) - { - if ( k == pCut->nSizeMax ) - return 0; - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_CutHashValue( IdNew1 ); - } - pCutNew->nSize = k; - pCutNew->uHash = uHash; - assert( pCutNew->nSize <= pCut->nSizeMax ); - for ( i = 1; i < pCutNew->nSize; i++ ) - assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Derives new cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) -{ - unsigned uHash = 0; - int i, k; - assert( pCut->nSize > 0 ); - assert( IdNew0 < IdNew1 ); - for ( i = k = 0; i < pCut->nSize; i++ ) - { - if ( pCut->pArray[i] == IdOld ) - continue; - if ( IdNew0 <= pCut->pArray[i] ) - { - if ( IdNew0 < pCut->pArray[i] ) - { - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_CutHashValue( IdNew0 ); - } - IdNew0 = 0x7FFFFFFF; - } - if ( IdNew1 <= pCut->pArray[i] ) - { - if ( IdNew1 < pCut->pArray[i] ) - { - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_CutHashValue( IdNew1 ); - } - IdNew1 = 0x7FFFFFFF; - } - pCutNew->pArray[ k++ ] = pCut->pArray[i]; - uHash |= Ivy_CutHashValue( pCut->pArray[i] ); - } - if ( IdNew0 < 0x7FFFFFFF ) - { - pCutNew->pArray[ k++ ] = IdNew0; - uHash |= Ivy_CutHashValue( IdNew0 ); - } - if ( IdNew1 < 0x7FFFFFFF ) - { - pCutNew->pArray[ k++ ] = IdNew1; - uHash |= Ivy_CutHashValue( IdNew1 ); - } - pCutNew->nSize = k; - pCutNew->uHash = uHash; - assert( pCutNew->nSize <= pCut->nSizeMax ); -// for ( i = 1; i < pCutNew->nSize; i++ ) -// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Find the hash value of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) -{ - int i; - pCut->uHash = 0; - for ( i = 0; i < pCut->nSize; i++ ) - pCut->uHash |= (1 << (pCut->pArray[i] % 31)); - return pCut->uHash; -} - -/**Function************************************************************* - - Synopsis [Derives new cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutDeriveNew3( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) -{ - int i, k; - assert( pCut->nSize > 0 ); - assert( IdNew0 < IdNew1 ); - for ( i = k = 0; i < pCut->nSize; i++ ) - { - if ( pCut->pArray[i] == IdOld ) - continue; - if ( IdNew0 <= pCut->pArray[i] ) - { - if ( IdNew0 < pCut->pArray[i] ) - pCutNew->pArray[ k++ ] = IdNew0; - IdNew0 = 0x7FFFFFFF; - } - if ( IdNew1 <= pCut->pArray[i] ) - { - if ( IdNew1 < pCut->pArray[i] ) - pCutNew->pArray[ k++ ] = IdNew1; - IdNew1 = 0x7FFFFFFF; - } - pCutNew->pArray[ k++ ] = pCut->pArray[i]; - } - if ( IdNew0 < 0x7FFFFFFF ) - pCutNew->pArray[ k++ ] = IdNew0; - if ( IdNew1 < 0x7FFFFFFF ) - pCutNew->pArray[ k++ ] = IdNew1; - pCutNew->nSize = k; - assert( pCutNew->nSize <= pCut->nSizeMax ); - Ivy_NodeCutHash( pCutNew ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pDom is contained in pCut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) -{ - int i, k; - for ( i = 0; i < pDom->nSize; i++ ) - { - assert( i==0 || pDom->pArray[i-1] < pDom->pArray[i] ); - for ( k = 0; k < pCut->nSize; k++ ) - if ( pDom->pArray[i] == pCut->pArray[k] ) - break; - if ( k == pCut->nSize ) // node i in pDom is not contained in pCut - return 0; - } - // every node in pDom is contained in pCut - return 1; -} - -/**Function************************************************************* - - Synopsis [Check if the cut exists.] - - Description [Returns 1 if the cut exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_CutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) -{ - Ivy_Cut_t * pCut; - int i, k; - assert( pCutNew->uHash ); - // try to find the cut - for ( i = 0; i < pCutStore->nCuts; i++ ) - { - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - if ( pCut->nSize == pCutNew->nSize ) - { - if ( pCut->uHash == pCutNew->uHash ) - { - for ( k = 0; k < pCutNew->nSize; k++ ) - if ( pCut->pArray[k] != pCutNew->pArray[k] ) - break; - if ( k == pCutNew->nSize ) - return 1; - } - continue; - } - if ( pCut->nSize < pCutNew->nSize ) - { - // skip the non-contained cuts - if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) - continue; - // check containment seriously - if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) - return 1; - continue; - } - // check potential containment of other cut - - // skip the non-contained cuts - if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) - continue; - // check containment seriously - if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) - { - // remove the current cut - pCut->nSize = 0; - } - } - assert( pCutStore->nCuts < pCutStore->nCutsMax ); - // add the cut - pCut = pCutStore->pCuts + pCutStore->nCuts++; - *pCut = *pCutNew; - return 0; -} - -/**Function************************************************************* - - Synopsis [Compresses the cut representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_CutCompactAll( Ivy_Store_t * pCutStore ) -{ - Ivy_Cut_t * pCut; - int i, k; - pCutStore->nCutsM = 0; - for ( i = k = 0; i < pCutStore->nCuts; i++ ) - { - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - if ( pCut->nSize < pCut->nSizeMax ) - pCutStore->nCutsM++; - pCutStore->pCuts[k++] = *pCut; - } - pCutStore->nCuts = k; -} - -/**Function************************************************************* - - Synopsis [Print the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_CutPrintForNode( Ivy_Cut_t * pCut ) -{ - int i; - assert( pCut->nSize > 0 ); - printf( "%d : {", pCut->nSize ); - for ( i = 0; i < pCut->nSize; i++ ) - printf( " %d", pCut->pArray[i] ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_CutPrintForNodes( Ivy_Store_t * pCutStore ) -{ - int i; - printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); - for ( i = 0; i < pCutStore->nCuts; i++ ) - Ivy_CutPrintForNode( pCutStore->pCuts + i ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Ivy_CutReadLeaf( Ivy_Obj_t * pFanin ) -{ - int nLats, iLeaf; - assert( !Ivy_IsComplement(pFanin) ); - if ( !Ivy_ObjIsLatch(pFanin) ) - return Ivy_LeafCreate( pFanin->Id, 0 ); - iLeaf = Ivy_CutReadLeaf(Ivy_ObjFanin0(pFanin)); - nLats = Ivy_LeafLat(iLeaf); - assert( nLats < IVY_LEAF_MASK ); - return 1 + iLeaf; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) -{ - static Ivy_Store_t CutStore, * pCutStore = &CutStore; - Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; - Ivy_Man_t * pMan = p; - Ivy_Obj_t * pLeaf; - int i, k, Temp, nLats, iLeaf0, iLeaf1; - - assert( nLeaves <= IVY_CUT_INPUT ); - - // start the structure - pCutStore->nCuts = 0; - pCutStore->nCutsMax = IVY_CUT_LIMIT; - // start the trivial cut - pCutNew->uHash = 0; - pCutNew->nSize = 1; - pCutNew->nSizeMax = nLeaves; - pCutNew->pArray[0] = Ivy_LeafCreate( pObj->Id, 0 ); - pCutNew->uHash = Ivy_CutHashValue( pCutNew->pArray[0] ); - // add the trivial cut - pCutStore->pCuts[pCutStore->nCuts++] = *pCutNew; - assert( pCutStore->nCuts == 1 ); - - // explore the cuts - for ( i = 0; i < pCutStore->nCuts; i++ ) - { - // expand this cut - pCut = pCutStore->pCuts + i; - if ( pCut->nSize == 0 ) - continue; - for ( k = 0; k < pCut->nSize; k++ ) - { - pLeaf = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[k]) ); - if ( Ivy_ObjIsCi(pLeaf) || Ivy_ObjIsConst1(pLeaf) ) - continue; - assert( Ivy_ObjIsNode(pLeaf) ); - nLats = Ivy_LeafLat(pCut->pArray[k]); - - // get the fanins fanins - iLeaf0 = Ivy_CutReadLeaf( Ivy_ObjFanin0(pLeaf) ); - iLeaf1 = Ivy_CutReadLeaf( Ivy_ObjFanin1(pLeaf) ); - assert( nLats + Ivy_LeafLat(iLeaf0) < IVY_LEAF_MASK && nLats + Ivy_LeafLat(iLeaf1) < IVY_LEAF_MASK ); - iLeaf0 = nLats + iLeaf0; - iLeaf1 = nLats + iLeaf1; - if ( !Ivy_CutPrescreen( pCut, iLeaf0, iLeaf1 ) ) - continue; - // the given cut exist - if ( iLeaf0 > iLeaf1 ) - Temp = iLeaf0, iLeaf0 = iLeaf1, iLeaf1 = Temp; - // create the new cut - if ( !Ivy_CutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ) ) - continue; - // add the cut - Ivy_CutFindOrAddFilter( pCutStore, pCutNew ); - if ( pCutStore->nCuts == IVY_CUT_LIMIT ) - break; - } - if ( pCutStore->nCuts == IVY_CUT_LIMIT ) - break; - } - if ( pCutStore->nCuts == IVY_CUT_LIMIT ) - pCutStore->fSatur = 1; - else - pCutStore->fSatur = 0; -// printf( "%d ", pCutStore->nCuts ); - Ivy_CutCompactAll( pCutStore ); -// printf( "%d \n", pCutStore->nCuts ); -// Ivy_CutPrintForNodes( pCutStore ); - return pCutStore; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs ) -{ - Ivy_Store_t * pStore; - Ivy_Obj_t * pObj; - int i, nCutsTotal, nCutsTotalM, nNodeTotal, nNodeOver; - int clk = clock(); - if ( nInputs > IVY_CUT_INPUT ) - { - printf( "Cannot compute cuts for more than %d inputs.\n", IVY_CUT_INPUT ); - return; - } - nNodeTotal = nNodeOver = 0; - nCutsTotal = nCutsTotalM = -Ivy_ManNodeNum(p); - Ivy_ManForEachObj( p, pObj, i ) - { - if ( !Ivy_ObjIsNode(pObj) ) - continue; - pStore = Ivy_CutComputeForNode( p, pObj, nInputs ); - nCutsTotal += pStore->nCuts; - nCutsTotalM += pStore->nCutsM; - nNodeOver += pStore->fSatur; - nNodeTotal++; - } - printf( "All = %6d. Minus = %6d. Triv = %6d. Node = %6d. Satur = %6d. ", - nCutsTotal, nCutsTotalM, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); - PRT( "Time", clock() - clk ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyShow.c b/src/aig/ivy/ivyShow.c deleted file mode 100644 index cd726e43..00000000 --- a/src/aig/ivy/ivyShow.c +++ /dev/null @@ -1,338 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyShow.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Visualization of HAIG.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) -{ - extern void Abc_ShowFile( char * FileNameDot ); - static Counter = 0; - char FileNameDot[200]; - FILE * pFile; - // create the file name -// Ivy_ShowGetFileName( pMan->pName, FileNameDot ); - sprintf( FileNameDot, "temp%02d.dot", Counter++ ); - // check that the file can be opened - if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); - return; - } - fclose( pFile ); - // generate the file - Ivy_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); - // visualize the file - Abc_ShowFile( FileNameDot ); -} - -/**Function************************************************************* - - Synopsis [Writes the graph structure of AIG for DOT.] - - Description [Useful for graph visualization using tools such as GraphViz: - http://www.graphviz.org/] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ) -{ - FILE * pFile; - Ivy_Obj_t * pNode, * pTemp, * pPrev; - int LevelMax, Level, i; - - if ( Ivy_ManNodeNum(pMan) > 200 ) - { - fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" ); - return; - } - if ( (pFile = fopen( pFileName, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); - return; - } - - // mark the nodes - if ( vBold ) - Vec_PtrForEachEntry( vBold, pNode, i ) - pNode->fMarkB = 1; - - // compute levels - LevelMax = 1 + Ivy_ManSetLevels( pMan, fHaig ); - - // write the DOT header - fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "digraph AIG {\n" ); - fprintf( pFile, "size = \"7.5,10\";\n" ); -// fprintf( pFile, "ranksep = 0.5;\n" ); -// fprintf( pFile, "nodesep = 0.5;\n" ); - fprintf( pFile, "center = true;\n" ); -// fprintf( pFile, "orientation = landscape;\n" ); -// fprintf( pFile, "edge [fontsize = 10];\n" ); -// fprintf( pFile, "edge [dir = none];\n" ); - fprintf( pFile, "edge [dir = back];\n" ); - fprintf( pFile, "\n" ); - - // labels on the left of the picture - fprintf( pFile, "{\n" ); - fprintf( pFile, " node [shape = plaintext];\n" ); - fprintf( pFile, " edge [style = invis];\n" ); - fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); - fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); - // generate node names with labels - for ( Level = LevelMax; Level >= 0; Level-- ) - { - // the visible node name - fprintf( pFile, " Level%d", Level ); - fprintf( pFile, " [label = " ); - // label name - fprintf( pFile, "\"" ); - fprintf( pFile, "\"" ); - fprintf( pFile, "];\n" ); - } - - // genetate the sequence of visible/invisible nodes to mark levels - fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); - for ( Level = LevelMax; Level >= 0; Level-- ) - { - // the visible node name - fprintf( pFile, " Level%d", Level ); - // the connector - if ( Level != 0 ) - fprintf( pFile, " ->" ); - else - fprintf( pFile, ";" ); - } - fprintf( pFile, "\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate title box on top - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - fprintf( pFile, " LevelTitle1;\n" ); - fprintf( pFile, " title1 [shape=plaintext,\n" ); - fprintf( pFile, " fontsize=20,\n" ); - fprintf( pFile, " fontname = \"Times-Roman\",\n" ); - fprintf( pFile, " label=\"" ); - fprintf( pFile, "%s", "AIG structure visualized by ABC" ); - fprintf( pFile, "\\n" ); - fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); - fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); - fprintf( pFile, "\"\n" ); - fprintf( pFile, " ];\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate statistics box - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - fprintf( pFile, " LevelTitle2;\n" ); - fprintf( pFile, " title2 [shape=plaintext,\n" ); - fprintf( pFile, " fontsize=18,\n" ); - fprintf( pFile, " fontname = \"Times-Roman\",\n" ); - fprintf( pFile, " label=\"" ); - fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Ivy_ManNodeNum(pMan), LevelMax ); - fprintf( pFile, "\\n" ); - fprintf( pFile, "\"\n" ); - fprintf( pFile, " ];\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate the COs - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", LevelMax ); - // generate the CO nodes - Ivy_ManForEachCo( pMan, pNode, i ) - { - if ( fHaig || pNode->pEquiv == NULL ) - fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, - (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); - else - fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, - (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":""), - Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); - fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"invtriangle") ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate nodes of each rank - for ( Level = LevelMax - 1; Level > 0; Level-- ) - { - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", Level ); - Ivy_ManForEachObj( pMan, pNode, i ) - { - if ( (int)pNode->Level != Level ) - continue; - if ( fHaig || pNode->pEquiv == NULL ) - fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); - else - fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, - Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); - fprintf( pFile, ", shape = ellipse" ); - if ( vBold && pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - } - - // generate the CI nodes - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", 0 ); - // generate constant node - if ( Ivy_ObjRefs(Ivy_ManConst1(pMan)) > 0 ) - { - pNode = Ivy_ManConst1(pMan); - // check if the costant node is present - fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); - fprintf( pFile, ", shape = ellipse" ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - // generate the CI nodes - Ivy_ManForEachCi( pMan, pNode, i ) - { - if ( fHaig || pNode->pEquiv == NULL ) - fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, - (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":"") ); - else - fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, - (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":""), - Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); - fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"triangle") ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate invisible edges from the square down - fprintf( pFile, "title1 -> title2 [style = invis];\n" ); - Ivy_ManForEachCo( pMan, pNode, i ) - fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); - - // generate edges - Ivy_ManForEachObj( pMan, pNode, i ) - { - if ( !Ivy_ObjIsNode(pNode) && !Ivy_ObjIsCo(pNode) && !Ivy_ObjIsBuf(pNode) ) - continue; - // generate the edge from this node to the next - fprintf( pFile, "Node%d%s", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d%s", Ivy_ObjFaninId0(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin0(pNode))? "_out":"") ); - fprintf( pFile, " [" ); - fprintf( pFile, "style = %s", Ivy_ObjFaninC0(pNode)? "dotted" : "bold" ); -// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 ) -// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); - fprintf( pFile, "]" ); - fprintf( pFile, ";\n" ); - if ( !Ivy_ObjIsNode(pNode) ) - continue; - // generate the edge from this node to the next - fprintf( pFile, "Node%d", pNode->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d%s", Ivy_ObjFaninId1(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin1(pNode))? "_out":"") ); - fprintf( pFile, " [" ); - fprintf( pFile, "style = %s", Ivy_ObjFaninC1(pNode)? "dotted" : "bold" ); -// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 ) -// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); - fprintf( pFile, "]" ); - fprintf( pFile, ";\n" ); - // generate the edges between the equivalent nodes - if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 ) - { - pPrev = pNode; - for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) ) - { - fprintf( pFile, "Node%d", pPrev->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d", pTemp->Id ); - fprintf( pFile, " [style = %s]", Ivy_IsComplement(pTemp->pEquiv)? "dotted" : "bold" ); - fprintf( pFile, ";\n" ); - pPrev = pTemp; - } - // connect the last node with the first - fprintf( pFile, "Node%d", pPrev->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d", pNode->Id ); - fprintf( pFile, " [style = %s]", Ivy_IsComplement(pPrev->pEquiv)? "dotted" : "bold" ); - fprintf( pFile, ";\n" ); - } - } - - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - fclose( pFile ); - - // unmark nodes - if ( vBold ) - Vec_PtrForEachEntry( vBold, pNode, i ) - pNode->fMarkB = 0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyTable.c b/src/aig/ivy/ivyTable.c deleted file mode 100644 index 2ac0ae49..00000000 --- a/src/aig/ivy/ivyTable.c +++ /dev/null @@ -1,301 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyTable.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Structural hashing table.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006. ] - - Revision [$Id: ivyTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// hashing the node -static unsigned Ivy_Hash( Ivy_Obj_t * pObj, int TableSize ) -{ - unsigned Key = Ivy_ObjIsExor(pObj) * 1699; - Key ^= Ivy_ObjFaninId0(pObj) * 7937; - Key ^= Ivy_ObjFaninId1(pObj) * 2971; - Key ^= Ivy_ObjFaninC0(pObj) * 911; - Key ^= Ivy_ObjFaninC1(pObj) * 353; - Key ^= Ivy_ObjInit(pObj) * 911; - return Key % TableSize; -} - -// returns the place where this node is stored (or should be stored) -static int * Ivy_TableFind( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - int i; - assert( Ivy_ObjIsHash(pObj) ); - for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) - if ( p->pTable[i] == pObj->Id ) - break; - return p->pTable + i; -} - -static void Ivy_TableResize( Ivy_Man_t * p ); -static unsigned int Cudd_PrimeAig( unsigned int p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks if node with the given attributes is in the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pEntry; - int i; - assert( !Ivy_IsComplement(pObj) ); - if ( !Ivy_ObjIsHash(pObj) ) - return NULL; - assert( Ivy_ObjIsLatch(pObj) || Ivy_ObjFaninId0(pObj) > 0 ); - assert( Ivy_ObjFaninId1(pObj) == 0 || Ivy_ObjFaninId0(pObj) < Ivy_ObjFaninId1(pObj) ); - if ( Ivy_ObjFanin0(pObj)->nRefs == 0 || (Ivy_ObjChild1(pObj) && Ivy_ObjFanin1(pObj)->nRefs == 0) ) - return NULL; - for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) - { - pEntry = Ivy_ManObj( p, p->pTable[i] ); - if ( Ivy_ObjChild0(pEntry) == Ivy_ObjChild0(pObj) && - Ivy_ObjChild1(pEntry) == Ivy_ObjChild1(pObj) && - Ivy_ObjInit(pEntry) == Ivy_ObjInit(pObj) && - Ivy_ObjType(pEntry) == Ivy_ObjType(pObj) ) - return pEntry; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Adds the node to the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - int * pPlace; - assert( !Ivy_IsComplement(pObj) ); - if ( !Ivy_ObjIsHash(pObj) ) - return; - if ( (pObj->Id & 63) == 0 ) - { - if ( p->nTableSize < 2 * Ivy_ManHashObjNum(p) ) - Ivy_TableResize( p ); - } - pPlace = Ivy_TableFind( p, pObj ); - assert( *pPlace == 0 ); - *pPlace = pObj->Id; -} - -/**Function************************************************************* - - Synopsis [Deletes the node from the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pEntry; - int i, * pPlace; - assert( !Ivy_IsComplement(pObj) ); - if ( !Ivy_ObjIsHash(pObj) ) - return; - pPlace = Ivy_TableFind( p, pObj ); - assert( *pPlace == pObj->Id ); // node should be in the table - *pPlace = 0; - // rehash the adjacent entries - i = pPlace - p->pTable; - for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize ) - { - pEntry = Ivy_ManObj( p, p->pTable[i] ); - p->pTable[i] = 0; - Ivy_TableInsert( p, pEntry ); - } -} - -/**Function************************************************************* - - Synopsis [Updates the table to point to the new node.] - - Description [If the old node (pObj) is in the table, updates the table - to point to an object with different ID (ObjIdNew). The table should - not contain an object with ObjIdNew (this is currently not checked).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ) -{ - int * pPlace; - assert( !Ivy_IsComplement(pObj) ); - if ( !Ivy_ObjIsHash(pObj) ) - return; - pPlace = Ivy_TableFind( p, pObj ); - assert( *pPlace == pObj->Id ); // node should be in the table - *pPlace = ObjIdNew; -} - -/**Function************************************************************* - - Synopsis [Count the number of nodes in the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_TableCountEntries( Ivy_Man_t * p ) -{ - int i, Counter = 0; - for ( i = 0; i < p->nTableSize; i++ ) - Counter += (p->pTable[i] != 0); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [Typically this procedure should not be called.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_TableResize( Ivy_Man_t * p ) -{ - int * pTableOld, * pPlace; - int nTableSizeOld, Counter, nEntries, e, clk; -clk = clock(); - // save the old table - pTableOld = p->pTable; - nTableSizeOld = p->nTableSize; - // get the new table - p->nTableSize = Cudd_PrimeAig( 5 * Ivy_ManHashObjNum(p) ); - p->pTable = ALLOC( int, p->nTableSize ); - memset( p->pTable, 0, sizeof(int) * p->nTableSize ); - // rehash the entries from the old table - Counter = 0; - for ( e = 0; e < nTableSizeOld; e++ ) - { - if ( pTableOld[e] == 0 ) - continue; - Counter++; - // get the place where this entry goes in the table table - pPlace = Ivy_TableFind( p, Ivy_ManObj(p, pTableOld[e]) ); - assert( *pPlace == 0 ); // should not be in the table - *pPlace = pTableOld[e]; - } - nEntries = Ivy_ManHashObjNum(p); -// assert( Counter == nEntries ); -// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); -// PRT( "Time", clock() - clk ); - // replace the table and the parameters - free( pTableOld ); -} - -/**Function******************************************************************** - - Synopsis [Profiles the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Ivy_TableProfile( Ivy_Man_t * p ) -{ - int i, Counter = 0; - for ( i = 0; i < p->nTableSize; i++ ) - { - if ( p->pTable[i] ) - Counter++; - else if ( Counter ) - { - printf( "%d ", Counter ); - Counter = 0; - } - } -} - -/**Function******************************************************************** - - Synopsis [Returns the next prime >= p.] - - Description [Copied from CUDD, for stand-aloneness.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -unsigned int Cudd_PrimeAig( unsigned int p) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivyUtil.c b/src/aig/ivy/ivyUtil.c deleted file mode 100644 index ab62a276..00000000 --- a/src/aig/ivy/ivyUtil.c +++ /dev/null @@ -1,818 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivyUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [Various procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivyUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Increments the current traversal ID of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManIncrementTravId( Ivy_Man_t * p ) -{ - if ( p->nTravIds >= (1<<30)-1 - 1000 ) - Ivy_ManCleanTravId( p ); - p->nTravIds++; -} - -/**Function************************************************************* - - Synopsis [Sets the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCleanTravId( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - p->nTravIds = 1; - Ivy_ManForEachObj( p, pObj, i ) - pObj->TravId = 0; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCollectCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vNodes ) -{ - if ( pNode->fMarkA ) - return; - pNode->fMarkA = 1; - assert( Ivy_ObjIsAnd(pNode) || Ivy_ObjIsExor(pNode) ); - Ivy_ManCollectCut_rec( p, Ivy_ObjFanin0(pNode), vNodes ); - Ivy_ManCollectCut_rec( p, Ivy_ObjFanin1(pNode), vNodes ); - Vec_IntPush( vNodes, pNode->Id ); -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [Does not modify the array of leaves. Uses array vTruth to store - temporary truth tables. The returned pointer should be used immediately.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) -{ - int i, Leaf; - // collect and mark the leaves - Vec_IntClear( vNodes ); - Vec_IntForEachEntry( vLeaves, Leaf, i ) - { - Vec_IntPush( vNodes, Leaf ); - Ivy_ManObj(p, Leaf)->fMarkA = 1; - } - // collect and mark the nodes - Ivy_ManCollectCut_rec( p, pRoot, vNodes ); - // clean the nodes - Vec_IntForEachEntry( vNodes, Leaf, i ) - Ivy_ManObj(p, Leaf)->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Ivy_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth ) -{ - return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManCutTruthOne( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vTruth, int nWords ) -{ - unsigned * pTruth, * pTruth0, * pTruth1; - int i; - pTruth = Ivy_ObjGetTruthStore( pNode->TravId, vTruth ); - pTruth0 = Ivy_ObjGetTruthStore( Ivy_ObjFanin0(pNode)->TravId, vTruth ); - pTruth1 = Ivy_ObjGetTruthStore( Ivy_ObjFanin1(pNode)->TravId, vTruth ); - if ( Ivy_ObjIsExor(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] ^ pTruth1[i]; - else if ( !Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] & pTruth1[i]; - else if ( !Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] & ~pTruth1[i]; - else if ( Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ~pTruth0[i] & pTruth1[i]; - else // if ( Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [Does not modify the array of leaves. Uses array vTruth to store - temporary truth tables. The returned pointer should be used immediately.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ) -{ - static unsigned uTruths[8][8] = { // elementary truth tables - { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, - { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, - { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, - { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, - { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, - { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, - { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, - { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } - }; - int i, Leaf; - // collect the cut - Ivy_ManCollectCut( p, pRoot, vLeaves, vNodes ); - // set the node numbers - Vec_IntForEachEntry( vNodes, Leaf, i ) - Ivy_ManObj(p, Leaf)->TravId = i; - // alloc enough memory - Vec_IntClear( vTruth ); - Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) ); - // set the elementary truth tables - Vec_IntForEachEntry( vLeaves, Leaf, i ) - memcpy( Ivy_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) ); - // compute truths for other nodes - Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) ) - Ivy_ManCutTruthOne( p, Ivy_ManObj(p, Leaf), vTruth, 8 ); - return Ivy_ObjGetTruthStore( pRoot->TravId, vTruth ); -} - -/**Function************************************************************* - - Synopsis [Collect the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ) -{ - Vec_Int_t * vLatches; - Ivy_Obj_t * pObj; - int i; - vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); - Ivy_ManForEachLatch( p, pObj, i ) - Vec_IntPush( vLatches, pObj->Id ); - return vLatches; -} - -/**Function************************************************************* - - Synopsis [Collect the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManLevels( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i, LevelMax = 0; - Ivy_ManForEachPo( p, pObj, i ) - LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); - return LevelMax; -} - -/**Function************************************************************* - - Synopsis [Collect the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ManResetLevels_rec( Ivy_Obj_t * pObj ) -{ - if ( pObj->Level || Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) - return pObj->Level; - if ( Ivy_ObjIsBuf(pObj) ) - return pObj->Level = Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); - assert( Ivy_ObjIsNode(pObj) ); - Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); - Ivy_ManResetLevels_rec( Ivy_ObjFanin1(pObj) ); - return pObj->Level = Ivy_ObjLevelNew( pObj ); -} - -/**Function************************************************************* - - Synopsis [Collect the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManResetLevels( Ivy_Man_t * p ) -{ - Ivy_Obj_t * pObj; - int i; - Ivy_ManForEachObj( p, pObj, i ) - pObj->Level = 0; - Ivy_ManForEachCo( p, pObj, i ) - Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [References/references the node and returns MFFC size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjRefDeref( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fReference, int fLabel ) -{ - Ivy_Obj_t * pNode0, * pNode1; - int Counter; - // label visited nodes - if ( fLabel ) - Ivy_ObjSetTravIdCurrent( p, pNode ); - // skip the CI - if ( Ivy_ObjIsPi(pNode) ) - return 0; - assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsBuf(pNode) || Ivy_ObjIsLatch(pNode) ); - // process the internal node - pNode0 = Ivy_ObjFanin0(pNode); - pNode1 = Ivy_ObjFanin1(pNode); - Counter = Ivy_ObjIsNode(pNode); - if ( fReference ) - { - if ( pNode0->nRefs++ == 0 ) - Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); - if ( pNode1 && pNode1->nRefs++ == 0 ) - Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); - } - else - { - assert( pNode0->nRefs > 0 ); - assert( pNode1 == NULL || pNode1->nRefs > 0 ); - if ( --pNode0->nRefs == 0 ) - Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); - if ( pNode1 && --pNode1->nRefs == 0 ) - Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); - } - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Labels MFFC with the current label.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pNode ) -{ - int nConeSize1, nConeSize2; - assert( !Ivy_IsComplement( pNode ) ); - assert( Ivy_ObjIsNode( pNode ) ); - nConeSize1 = Ivy_ObjRefDeref( p, pNode, 0, 1 ); // dereference - nConeSize2 = Ivy_ObjRefDeref( p, pNode, 1, 0 ); // reference - assert( nConeSize1 == nConeSize2 ); - assert( nConeSize1 > 0 ); - return nConeSize1; -} - -/**Function************************************************************* - - Synopsis [Recursively updates fanout levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pFanout; - Vec_Ptr_t * vFanouts; - int i, LevelNew; - assert( p->fFanout ); - assert( Ivy_ObjIsNode(pObj) ); - vFanouts = Vec_PtrAlloc( 10 ); - Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) - { - if ( Ivy_ObjIsCo(pFanout) ) - { -// assert( (int)Ivy_ObjFanin0(pFanout)->Level <= p->nLevelMax ); - continue; - } - LevelNew = Ivy_ObjLevelNew( pFanout ); - if ( (int)pFanout->Level == LevelNew ) - continue; - pFanout->Level = LevelNew; - Ivy_ObjUpdateLevel_rec( p, pFanout ); - } - Vec_PtrFree( vFanouts ); -} - -/**Function************************************************************* - - Synopsis [Compute the new required level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjLevelRNew( Ivy_Man_t * p, Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pFanout; - Vec_Ptr_t * vFanouts; - int i, Required, LevelNew = 1000000; - assert( p->fFanout && p->vRequired ); - vFanouts = Vec_PtrAlloc( 10 ); - Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) - { - Required = Vec_IntEntry(p->vRequired, pFanout->Id); - LevelNew = IVY_MIN( LevelNew, Required ); - } - Vec_PtrFree( vFanouts ); - return LevelNew - 1; -} - -/**Function************************************************************* - - Synopsis [Recursively updates fanout levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ) -{ - Ivy_Obj_t * pFanin; - if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) - return; - assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); - // process the first fanin - pFanin = Ivy_ObjFanin0(pObj); - if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) - { - Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); - Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); - } - if ( Ivy_ObjIsBuf(pObj) ) - return; - // process the second fanin - pFanin = Ivy_ObjFanin1(pObj); - if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) - { - Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); - Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); - } -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_ObjIsMuxType( Ivy_Obj_t * pNode ) -{ - Ivy_Obj_t * pNode0, * pNode1; - // check that the node is regular - assert( !Ivy_IsComplement(pNode) ); - // if the node is not AND, this is not MUX - if ( !Ivy_ObjIsAnd(pNode) ) - return 0; - // if the children are not complemented, this is not MUX - if ( !Ivy_ObjFaninC0(pNode) || !Ivy_ObjFaninC1(pNode) ) - return 0; - // get children - pNode0 = Ivy_ObjFanin0(pNode); - pNode1 = Ivy_ObjFanin1(pNode); - // if the children are not ANDs, this is not MUX - if ( !Ivy_ObjIsAnd(pNode0) || !Ivy_ObjIsAnd(pNode1) ) - return 0; - // otherwise the node is MUX iff it has a pair of equal grandchildren - return (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || - (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1))) || - (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || - (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1))); -} - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are control and data inputs of a MUX.] - - Description [If the node is a MUX, returns the control variable C. - Assigns nodes T and E to be the then and else variables of the MUX. - Node C is never complemented. Nodes T and E can be complemented. - This function also recognizes EXOR/NEXOR gates as MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pNode, Ivy_Obj_t ** ppNodeT, Ivy_Obj_t ** ppNodeE ) -{ - Ivy_Obj_t * pNode0, * pNode1; - assert( !Ivy_IsComplement(pNode) ); - assert( Ivy_ObjIsMuxType(pNode) ); - // get children - pNode0 = Ivy_ObjFanin0(pNode); - pNode1 = Ivy_ObjFanin1(pNode); - // find the control variable -// if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) - if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Ivy_ObjFaninC0(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); - return Ivy_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); - return Ivy_ObjChild0(pNode0);//pNode1->p1; - } - } -// else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) - else if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Ivy_ObjFaninC0(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); - return Ivy_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); - return Ivy_ObjChild0(pNode0);//pNode1->p1; - } - } -// else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) - else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Ivy_ObjFaninC1(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); - return Ivy_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); - return Ivy_ObjChild1(pNode0);//pNode1->p2; - } - } -// else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) - else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Ivy_ObjFaninC1(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); - return Ivy_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); - return Ivy_ObjChild1(pNode0);//pNode1->p2; - } - } - assert( 0 ); // this is not MUX - return NULL; -} - -/**Function************************************************************* - - Synopsis [Returns the real fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ) -{ - Ivy_Obj_t * pFanin; - if ( pObj == NULL || !Ivy_ObjIsBuf( Ivy_Regular(pObj) ) ) - return pObj; - pFanin = Ivy_ObjReal( Ivy_ObjChild0(Ivy_Regular(pObj)) ); - return Ivy_NotCond( pFanin, Ivy_IsComplement(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ) -{ - Ivy_Obj_t * pTemp; - int fShowFanouts = 0; - assert( !Ivy_IsComplement(pObj) ); - printf( "Node %5d : ", Ivy_ObjId(pObj) ); - if ( Ivy_ObjIsConst1(pObj) ) - printf( "constant 1" ); - else if ( Ivy_ObjIsPi(pObj) ) - printf( "PI" ); - else if ( Ivy_ObjIsPo(pObj) ) - printf( "PO" ); - else if ( Ivy_ObjIsLatch(pObj) ) - printf( "latch (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); - else if ( Ivy_ObjIsBuf(pObj) ) - printf( "buffer (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); - else - printf( "AND( %5d%s, %5d%s )", - Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " "), - Ivy_ObjFanin1(pObj)->Id, (Ivy_ObjFaninC1(pObj)? "\'" : " ") ); - printf( " (refs = %3d)", Ivy_ObjRefs(pObj) ); - if ( fShowFanouts ) - { - Vec_Ptr_t * vFanouts; - Ivy_Obj_t * pFanout; - int i; - vFanouts = Vec_PtrAlloc( 10 ); - printf( "\nFanouts:\n" ); - Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) - { - printf( " " ); - printf( "Node %5d : ", Ivy_ObjId(pFanout) ); - if ( Ivy_ObjIsPo(pFanout) ) - printf( "PO" ); - else if ( Ivy_ObjIsLatch(pFanout) ) - printf( "latch (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); - else if ( Ivy_ObjIsBuf(pFanout) ) - printf( "buffer (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); - else - printf( "AND( %5d%s, %5d%s )", - Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " "), - Ivy_ObjFanin1(pFanout)->Id, (Ivy_ObjFaninC1(pFanout)? "\'" : " ") ); - printf( "\n" ); - } - Vec_PtrFree( vFanouts ); - return; - } - if ( !fHaig ) - { - if ( pObj->pEquiv == NULL ) - printf( " HAIG node not given" ); - else - printf( " HAIG node = %d%s", Ivy_Regular(pObj->pEquiv)->Id, (Ivy_IsComplement(pObj->pEquiv)? "\'" : " ") ); - return; - } - if ( pObj->pEquiv == NULL ) - return; - // there are choices - if ( Ivy_ObjRefs(pObj) > 0 ) - { - // print equivalence class - printf( " { %5d ", pObj->Id ); - assert( !Ivy_IsComplement(pObj->pEquiv) ); - for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) - printf( " %5d%s", pTemp->Id, (Ivy_IsComplement(pTemp->pEquiv)? "\'" : " ") ); - printf( " }" ); - return; - } - // this is a secondary node - for ( pTemp = Ivy_Regular(pObj->pEquiv); Ivy_ObjRefs(pTemp) == 0; pTemp = Ivy_Regular(pTemp->pEquiv) ); - assert( Ivy_ObjRefs(pTemp) > 0 ); - printf( " class of %d", pTemp->Id ); -} - -/**Function************************************************************* - - Synopsis [Prints node in HAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ) -{ - Vec_Int_t * vNodes; - Ivy_Obj_t * pObj; - int i; - printf( "PIs: " ); - Ivy_ManForEachPi( p, pObj, i ) - printf( " %d", pObj->Id ); - printf( "\n" ); - printf( "POs: " ); - Ivy_ManForEachPo( p, pObj, i ) - printf( " %d", pObj->Id ); - printf( "\n" ); - printf( "Latches: " ); - Ivy_ManForEachLatch( p, pObj, i ) - printf( " %d=%d%s", pObj->Id, Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); - printf( "\n" ); - vNodes = Ivy_ManDfsSeq( p, NULL ); - Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) - Ivy_ObjPrintVerbose( p, pObj, fHaig ), printf( "\n" ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Performs incremental rewriting of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_CutTruthPrint2( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ) -{ - int i; - printf( "Trying cut : {" ); - for ( i = 0; i < pCut->nSize; i++ ) - printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); - printf( " } " ); - Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Performs incremental rewriting of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ) -{ - Vec_Ptr_t * vArray; - Ivy_Obj_t * pObj, * pFanout; - int nLatches = 0; - int nPresent = 0; - int i, k; - int fVerbose = 0; - - if ( fVerbose ) - printf( "Trying cut : {" ); - for ( i = 0; i < pCut->nSize; i++ ) - { - if ( fVerbose ) - printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); - nLatches += Ivy_LeafLat(pCut->pArray[i]); - } - if ( fVerbose ) - printf( " } " ); - if ( fVerbose ) - printf( "Latches = %d. ", nLatches ); - - // check if there are latches on the fanout edges - vArray = Vec_PtrAlloc( 100 ); - for ( i = 0; i < pCut->nSize; i++ ) - { - pObj = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[i]) ); - Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, k ) - { - if ( Ivy_ObjIsLatch(pFanout) ) - { - nPresent++; - break; - } - } - } - Vec_PtrSize( vArray ); - if ( fVerbose ) - { - printf( "Present = %d. ", nPresent ); - if ( nLatches > nPresent ) - printf( "Clauses = %d. ", 2*(nLatches - nPresent) ); - printf( "\n" ); - } - return ( nLatches > nPresent ) ? 2*(nLatches - nPresent) : 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/ivy_.c b/src/aig/ivy/ivy_.c deleted file mode 100644 index 65689689..00000000 --- a/src/aig/ivy/ivy_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [ivy_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [And-Inverter Graph package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 11, 2006.] - - Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/ivy/module.make b/src/aig/ivy/module.make deleted file mode 100644 index daef43df..00000000 --- a/src/aig/ivy/module.make +++ /dev/null @@ -1,22 +0,0 @@ -SRC += src/aig/ivy/ivyBalance.c \ - src/aig/ivy/ivyCanon.c \ - src/aig/ivy/ivyCheck.c \ - src/aig/ivy/ivyCut.c \ - src/aig/ivy/ivyCutTrav.c \ - src/aig/ivy/ivyDfs.c \ - src/aig/ivy/ivyDsd.c \ - src/aig/ivy/ivyFanout.c \ - src/aig/ivy/ivyFastMap.c \ - src/aig/ivy/ivyFraig.c \ - src/aig/ivy/ivyHaig.c \ - src/aig/ivy/ivyMan.c \ - src/aig/ivy/ivyMem.c \ - src/aig/ivy/ivyMulti.c \ - src/aig/ivy/ivyObj.c \ - src/aig/ivy/ivyOper.c \ - src/aig/ivy/ivyResyn.c \ - src/aig/ivy/ivyRwr.c \ - src/aig/ivy/ivySeq.c \ - src/aig/ivy/ivyShow.c \ - src/aig/ivy/ivyTable.c \ - src/aig/ivy/ivyUtil.c diff --git a/src/aig/kit/cloud.c b/src/aig/kit/cloud.c deleted file mode 100644 index 6e6691f0..00000000 --- a/src/aig/kit/cloud.c +++ /dev/null @@ -1,987 +0,0 @@ -/**CFile**************************************************************** - - FileName [cloudCore.c] - - PackageName [Fast application-specific BDD package.] - - Synopsis [The package core.] - - Author [Alan Mishchenko ] - - Affiliation [ECE Department. Portland State University, Portland, Oregon.] - - Date [Ver. 1.0. Started - June 10, 2002.] - - Revision [$Id: cloudCore.c,v 1.0 2002/06/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cloud.h" - -// the number of operators using cache -static int CacheOperNum = 4; - -// the ratio of cache size to the unique table size for each operator -static int CacheLogRatioDefault[4] = { - 2, // CLOUD_OPER_AND, - 8, // CLOUD_OPER_XOR, - 8, // CLOUD_OPER_BDIFF, - 8 // CLOUD_OPER_LEQ -}; - -// the ratio of cache size to the unique table size for each operator -static int CacheSize[4] = { - 2, // CLOUD_OPER_AND, - 2, // CLOUD_OPER_XOR, - 2, // CLOUD_OPER_BDIFF, - 2 // CLOUD_OPER_LEQ -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// static functions -static CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ); -static void cloudCacheAllocate( CloudManager * dd, CloudOper oper ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function******************************************************************** - - Synopsis [Starts the cloud manager.] - - Description [The first arguments is the number of elementary variables used. - The second arguments is the number of bits of the unsigned integer used to - represent nodes in the unique table. If the second argument is 0, the package - assumes 23 to represent nodes, which is equivalent to 2^23 = 8,388,608 nodes.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -CloudManager * Cloud_Init( int nVars, int nBits ) -{ - CloudManager * dd; - int i; - int clk1, clk2; - - assert( nVars <= 100000 ); - assert( nBits < 32 ); - - // assign the defaults - if ( nBits == 0 ) - nBits = CLOUD_NODE_BITS; - - // start the manager - dd = CALLOC( CloudManager, 1 ); - dd->nMemUsed += sizeof(CloudManager); - - // variables - dd->nVars = nVars; // the number of variables allocated - // bits - dd->bitsNode = nBits; // the number of bits used for the node - for ( i = 0; i < CacheOperNum; i++ ) - dd->bitsCache[i] = nBits - CacheLogRatioDefault[i]; - // shifts - dd->shiftUnique = 8*sizeof(unsigned) - (nBits + 1); // gets node index in the hash table - for ( i = 0; i < CacheOperNum; i++ ) - dd->shiftCache[i] = 8*sizeof(unsigned) - dd->bitsCache[i]; - // nodes - dd->nNodesAlloc = (1 << (nBits + 1)); // 2 ^ (nBits + 1) - dd->nNodesLimit = (1 << nBits); // 2 ^ nBits - - // unique table -clk1 = clock(); - dd->tUnique = CALLOC( CloudNode, dd->nNodesAlloc ); - dd->nMemUsed += sizeof(CloudNode) * dd->nNodesAlloc; -clk2 = clock(); -//PRT( "calloc() time", clk2 - clk1 ); - - // set up the constant node (the only node that is not in the hash table) - dd->nSignCur = 1; - dd->tUnique[0].s = dd->nSignCur; - dd->tUnique[0].v = CLOUD_CONST_INDEX; - dd->tUnique[0].e = CLOUD_VOID; - dd->tUnique[0].t = CLOUD_VOID; - dd->one = dd->tUnique; - dd->zero = Cloud_Not(dd->one); - dd->nNodesCur = 1; - - // special nodes - dd->pNodeStart = dd->tUnique + 1; - dd->pNodeEnd = dd->tUnique + dd->nNodesAlloc; - - // set up the elementary variables - dd->vars = ALLOC( CloudNode *, dd->nVars ); - dd->nMemUsed += sizeof(CloudNode *) * dd->nVars; - for ( i = 0; i < dd->nVars; i++ ) - dd->vars[i] = cloudMakeNode( dd, i, dd->one, dd->zero ); - - return dd; -}; - -/**Function******************************************************************** - - Synopsis [Stops the cloud manager.] - - Description [The first arguments tells show many elementary variables are used. - The second arguments tells how many bits of the unsigned integer are used - to represent regular nodes in the unique table.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Cloud_Quit( CloudManager * dd ) -{ - int i; - FREE( dd->ppNodes ); - free( dd->tUnique ); - free( dd->vars ); - for ( i = 0; i < 4; i++ ) - FREE( dd->tCaches[i] ); - free( dd ); -} - -/**Function******************************************************************** - - Synopsis [Prepares the manager for another run.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Cloud_Restart( CloudManager * dd ) -{ - int i; - assert( dd->one->s == dd->nSignCur ); - dd->nSignCur++; - dd->one->s++; - for ( i = 0; i < dd->nVars; i++ ) - dd->vars[i]->s++; - dd->nNodesCur = 1 + dd->nVars; -} - -/**Function******************************************************************** - - Synopsis [This optional function allocates operation cache of the given size.] - - Description [Cache for each operation is allocated independently when the first - operation of the given type is performed. The user can allocate cache of his/her - preferred size by calling Cloud_CacheAllocate before the first operation of the - given type is performed, but this call is optional. Argument "logratio" gives - the binary logarithm of the ratio of the size of the unique table to that of cache. - For example, if "logratio" is equal to 3, and the unique table will be 2^3=8 times - larger than cache; so, if unique table is 2^23 = 8,388,608 nodes, the cache size - will be 2^3=8 times smaller and equal to 2^20 = 1,048,576 entries.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Cloud_CacheAllocate( CloudManager * dd, CloudOper oper, int logratio ) -{ - assert( logratio > 0 ); // cache cannot be larger than the unique table - assert( logratio < dd->bitsNode ); // cache cannot be smaller than 2 entries - - if ( logratio ) - { - dd->bitsCache[oper] = dd->bitsNode - logratio; - dd->shiftCache[oper] = 8*sizeof(unsigned) - dd->bitsCache[oper]; - } - cloudCacheAllocate( dd, oper ); -} - -/**Function******************************************************************** - - Synopsis [Internal cache allocation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void cloudCacheAllocate( CloudManager * dd, CloudOper oper ) -{ - int nCacheEntries = (1 << dd->bitsCache[oper]); - - if ( CacheSize[oper] == 1 ) - { - dd->tCaches[oper] = (CloudCacheEntry2 *)CALLOC( CloudCacheEntry1, nCacheEntries ); - dd->nMemUsed += sizeof(CloudCacheEntry1) * nCacheEntries; - } - else if ( CacheSize[oper] == 2 ) - { - dd->tCaches[oper] = (CloudCacheEntry2 *)CALLOC( CloudCacheEntry2, nCacheEntries ); - dd->nMemUsed += sizeof(CloudCacheEntry2) * nCacheEntries; - } - else if ( CacheSize[oper] == 3 ) - { - dd->tCaches[oper] = (CloudCacheEntry2 *)CALLOC( CloudCacheEntry3, nCacheEntries ); - dd->nMemUsed += sizeof(CloudCacheEntry3) * nCacheEntries; - } -} - - - -/**Function******************************************************************** - - Synopsis [Returns or creates a new node] - - Description [Checks the unique table for the existance of the node. If the node is - present, returns the node. If the node is absent, creates a new node.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -CloudNode * Cloud_MakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ) -{ - CloudNode * pRes; - CLOUD_ASSERT(t); - CLOUD_ASSERT(e); - assert( v < Cloud_V(t) && v < Cloud_V(e) ); // variable should be above in the order - if ( Cloud_IsComplement(t) ) - { - pRes = cloudMakeNode( dd, v, Cloud_Not(t), Cloud_Not(e) ); - if ( pRes != CLOUD_VOID ) - pRes = Cloud_Not(pRes); - } - else - pRes = cloudMakeNode( dd, v, t, e ); - return pRes; -} - -/**Function******************************************************************** - - Synopsis [Returns or creates a new node] - - Description [Checks the unique table for the existance of the node. If the node is - present, returns the node. If the node is absent, creates a new node.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -CloudNode * cloudMakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ) -{ - CloudNode * entryUnique; - - CLOUD_ASSERT(t); - CLOUD_ASSERT(e); - - assert( ((int)v) >= 0 && ((int)v) < dd->nVars ); // the variable must be in the range - assert( v < Cloud_V(t) && v < Cloud_V(e) ); // variable should be above in the order - assert( !Cloud_IsComplement(t) ); // the THEN edge must not be complemented - - // make sure we are not searching for the constant node - assert( t && e ); - - // get the unique entry - entryUnique = dd->tUnique + cloudHashCudd3(v, t, e, dd->shiftUnique); - while ( entryUnique->s == dd->nSignCur ) - { - // compare the node - if ( entryUnique->v == v && entryUnique->t == t && entryUnique->e == e ) - { // the node is found - dd->nUniqueHits++; - return entryUnique; // returns the node - } - // increment the hash value modulus the hash table size - if ( ++entryUnique - dd->tUnique == dd->nNodesAlloc ) - entryUnique = dd->tUnique + 1; - // increment the number of steps through the table - dd->nUniqueSteps++; - } - dd->nUniqueMisses++; - - // check if the new node can be created - if ( ++dd->nNodesCur == dd->nNodesLimit ) - { // initiate the restart - printf( "Cloud needs restart!\n" ); -// fflush( stdout ); -// exit(1); - return CLOUD_VOID; - } - // create the node - entryUnique->s = dd->nSignCur; - entryUnique->v = v; - entryUnique->t = t; - entryUnique->e = e; - return entryUnique; // returns the node -} - - -/**Function******************************************************************** - - Synopsis [Performs the AND or two BDDs] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -CloudNode * cloudBddAnd( CloudManager * dd, CloudNode * f, CloudNode * g ) -{ - CloudNode * F, * G, * r; - CloudCacheEntry2 * cacheEntry; - CloudNode * fv, * fnv, * gv, * gnv, * t, * e; - CloudVar var; - - assert( f <= g ); - - // terminal cases - F = Cloud_Regular(f); - G = Cloud_Regular(g); - if ( F == G ) - { - if ( f == g ) - return f; - else - return dd->zero; - } - if ( F == dd->one ) - { - if ( f == dd->one ) - return g; - else - return f; - } - - // check cache - cacheEntry = dd->tCaches[CLOUD_OPER_AND] + cloudHashCudd2(f, g, dd->shiftCache[CLOUD_OPER_AND]); -// cacheEntry = dd->tCaches[CLOUD_OPER_AND] + cloudHashBuddy2(f, g, dd->shiftCache[CLOUD_OPER_AND]); - r = cloudCacheLookup2( cacheEntry, dd->nSignCur, f, g ); - if ( r != CLOUD_VOID ) - { - dd->nCacheHits++; - return r; - } - dd->nCacheMisses++; - - - // compute cofactors - if ( cloudV(F) <= cloudV(G) ) - { - var = cloudV(F); - if ( Cloud_IsComplement(f) ) - { - fnv = Cloud_Not(cloudE(F)); - fv = Cloud_Not(cloudT(F)); - } - else - { - fnv = cloudE(F); - fv = cloudT(F); - } - } - else - { - var = cloudV(G); - fv = fnv = f; - } - - if ( cloudV(G) <= cloudV(F) ) - { - if ( Cloud_IsComplement(g) ) - { - gnv = Cloud_Not(cloudE(G)); - gv = Cloud_Not(cloudT(G)); - } - else - { - gnv = cloudE(G); - gv = cloudT(G); - } - } - else - { - gv = gnv = g; - } - - if ( fv <= gv ) - t = cloudBddAnd( dd, fv, gv ); - else - t = cloudBddAnd( dd, gv, fv ); - - if ( t == CLOUD_VOID ) - return CLOUD_VOID; - - if ( fnv <= gnv ) - e = cloudBddAnd( dd, fnv, gnv ); - else - e = cloudBddAnd( dd, gnv, fnv ); - - if ( e == CLOUD_VOID ) - return CLOUD_VOID; - - if ( t == e ) - r = t; - else - { - if ( Cloud_IsComplement(t) ) - { - r = cloudMakeNode( dd, var, Cloud_Not(t), Cloud_Not(e) ); - if ( r == CLOUD_VOID ) - return CLOUD_VOID; - r = Cloud_Not(r); - } - else - { - r = cloudMakeNode( dd, var, t, e ); - if ( r == CLOUD_VOID ) - return CLOUD_VOID; - } - } - cloudCacheInsert2( cacheEntry, dd->nSignCur, f, g, r ); - return r; -} - -/**Function******************************************************************** - - Synopsis [Performs the AND or two BDDs] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -static inline CloudNode * cloudBddAnd_gate( CloudManager * dd, CloudNode * f, CloudNode * g ) -{ - if ( f <= g ) - return cloudBddAnd(dd,f,g); - else - return cloudBddAnd(dd,g,f); -} - -/**Function******************************************************************** - - Synopsis [Performs the AND or two BDDs] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -CloudNode * Cloud_bddAnd( CloudManager * dd, CloudNode * f, CloudNode * g ) -{ - if ( Cloud_Regular(f) == CLOUD_VOID || Cloud_Regular(g) == CLOUD_VOID ) - return CLOUD_VOID; - CLOUD_ASSERT(f); - CLOUD_ASSERT(g); - if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) - cloudCacheAllocate( dd, CLOUD_OPER_AND ); - return cloudBddAnd_gate( dd, f, g ); -} - -/**Function******************************************************************** - - Synopsis [Performs the OR or two BDDs] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -CloudNode * Cloud_bddOr( CloudManager * dd, CloudNode * f, CloudNode * g ) -{ - CloudNode * res; - if ( Cloud_Regular(f) == CLOUD_VOID || Cloud_Regular(g) == CLOUD_VOID ) - return CLOUD_VOID; - CLOUD_ASSERT(f); - CLOUD_ASSERT(g); - if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) - cloudCacheAllocate( dd, CLOUD_OPER_AND ); - res = cloudBddAnd_gate( dd, Cloud_Not(f), Cloud_Not(g) ); - res = Cloud_NotCond( res, res != CLOUD_VOID ); - return res; -} - -/**Function******************************************************************** - - Synopsis [Performs the XOR or two BDDs] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -CloudNode * Cloud_bddXor( CloudManager * dd, CloudNode * f, CloudNode * g ) -{ - CloudNode * t0, * t1, * r; - if ( Cloud_Regular(f) == CLOUD_VOID || Cloud_Regular(g) == CLOUD_VOID ) - return CLOUD_VOID; - CLOUD_ASSERT(f); - CLOUD_ASSERT(g); - if ( dd->tCaches[CLOUD_OPER_AND] == NULL ) - cloudCacheAllocate( dd, CLOUD_OPER_AND ); - t0 = cloudBddAnd_gate( dd, f, Cloud_Not(g) ); - if ( t0 == CLOUD_VOID ) - return CLOUD_VOID; - t1 = cloudBddAnd_gate( dd, Cloud_Not(f), g ); - if ( t1 == CLOUD_VOID ) - return CLOUD_VOID; - r = Cloud_bddOr( dd, t0, t1 ); - return r; -} - - - -/**Function******************************************************************** - - Synopsis [Performs a DFS from f, clearing the LSB of the next - pointers.] - - Description [] - - SideEffects [None] - - SeeAlso [cloudSupport cloudDagSize] - -******************************************************************************/ -static void cloudClearMark( CloudManager * dd, CloudNode * n ) -{ - if ( !cloudNodeIsMarked(n) ) - return; - // clear visited flag - cloudNodeUnmark(n); - if ( cloudIsConstant(n) ) - return; - cloudClearMark( dd, cloudT(n) ); - cloudClearMark( dd, Cloud_Regular(cloudE(n)) ); -} - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cloud_Support.] - - Description [Performs the recursive step of Cloud_Support. Performs a - DFS from f. The support is accumulated in supp as a side effect. Uses - the LSB of the then pointer as visited flag.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void cloudSupport( CloudManager * dd, CloudNode * n, int * support ) -{ - if ( cloudIsConstant(n) || cloudNodeIsMarked(n) ) - return; - // set visited flag - cloudNodeMark(n); - support[cloudV(n)] = 1; - cloudSupport( dd, cloudT(n), support ); - cloudSupport( dd, Cloud_Regular(cloudE(n)), support ); -} - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a DD depends.] - - Description [Finds the variables on which a DD depends. - Returns a BDD consisting of the product of the variables if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -CloudNode * Cloud_Support( CloudManager * dd, CloudNode * n ) -{ - CloudNode * res; - int * support, i; - - CLOUD_ASSERT(n); - - // allocate and initialize support array for cloudSupport - support = CALLOC( int, dd->nVars ); - - // compute support and clean up markers - cloudSupport( dd, Cloud_Regular(n), support ); - cloudClearMark( dd, Cloud_Regular(n) ); - - // transform support from array to cube - res = dd->one; - for ( i = dd->nVars - 1; i >= 0; i-- ) // for each level bottom-up - if ( support[i] == 1 ) - { - res = Cloud_bddAnd( dd, res, dd->vars[i] ); - if ( res == CLOUD_VOID ) - break; - } - FREE( support ); - return res; -} - -/**Function******************************************************************** - - Synopsis [Counts the variables on which a DD depends.] - - Description [Counts the variables on which a DD depends. - Returns the number of the variables if successful; Cloud_OUT_OF_MEM - otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int Cloud_SupportSize( CloudManager * dd, CloudNode * n ) -{ - int * support, i, count; - - CLOUD_ASSERT(n); - - // allocate and initialize support array for cloudSupport - support = CALLOC( int, dd->nVars ); - - // compute support and clean up markers - cloudSupport( dd, Cloud_Regular(n), support ); - cloudClearMark( dd, Cloud_Regular(n) ); - - // count support variables - count = 0; - for ( i = 0; i < dd->nVars; i++ ) - { - if ( support[i] == 1 ) - count++; - } - - FREE( support ); - return count; -} - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cloud_DagSize.] - - Description [Performs the recursive step of Cloud_DagSize. Returns the - number of nodes in the graph rooted at n.] - - SideEffects [None] - -******************************************************************************/ -static int cloudDagSize( CloudManager * dd, CloudNode * n ) -{ - int tval, eval; - if ( cloudNodeIsMarked(n) ) - return 0; - // set visited flag - cloudNodeMark(n); - if ( cloudIsConstant(n) ) - return 1; - tval = cloudDagSize( dd, cloudT(n) ); - eval = cloudDagSize( dd, Cloud_Regular(cloudE(n)) ); - return tval + eval + 1; - -} - -/**Function******************************************************************** - - Synopsis [Counts the number of nodes in a DD.] - - Description [Counts the number of nodes in a DD. Returns the number - of nodes in the graph rooted at node.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Cloud_DagSize( CloudManager * dd, CloudNode * n ) -{ - int res; - res = cloudDagSize( dd, Cloud_Regular( n ) ); - cloudClearMark( dd, Cloud_Regular( n ) ); - return res; - -} - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cloud_DagSize.] - - Description [Performs the recursive step of Cloud_DagSize. Returns the - number of nodes in the graph rooted at n.] - - SideEffects [None] - -******************************************************************************/ -static int Cloud_DagCollect_rec( CloudManager * dd, CloudNode * n, int * pCounter ) -{ - int tval, eval; - if ( cloudNodeIsMarked(n) ) - return 0; - // set visited flag - cloudNodeMark(n); - if ( cloudIsConstant(n) ) - { - dd->ppNodes[(*pCounter)++] = n; - return 1; - } - tval = Cloud_DagCollect_rec( dd, cloudT(n), pCounter ); - eval = Cloud_DagCollect_rec( dd, Cloud_Regular(cloudE(n)), pCounter ); - dd->ppNodes[(*pCounter)++] = n; - return tval + eval + 1; - -} - -/**Function******************************************************************** - - Synopsis [Counts the number of nodes in a DD.] - - Description [Counts the number of nodes in a DD. Returns the number - of nodes in the graph rooted at node.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Cloud_DagCollect( CloudManager * dd, CloudNode * n ) -{ - int res, Counter = 0; - if ( dd->ppNodes == NULL ) - dd->ppNodes = ALLOC( CloudNode *, dd->nNodesLimit ); - res = Cloud_DagCollect_rec( dd, Cloud_Regular( n ), &Counter ); - cloudClearMark( dd, Cloud_Regular( n ) ); - assert( res == Counter ); - return res; - -} - -/**Function******************************************************************** - - Synopsis [Counts the number of nodes in an array of DDs.] - - Description [Counts the number of nodes in a DD. Returns the number - of nodes in the graph rooted at node.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Cloud_SharingSize( CloudManager * dd, CloudNode ** pn, int nn ) -{ - int res, i; - res = 0; - for ( i = 0; i < nn; i++ ) - res += cloudDagSize( dd, Cloud_Regular( pn[i] ) ); - for ( i = 0; i < nn; i++ ) - cloudClearMark( dd, Cloud_Regular( pn[i] ) ); - return res; -} - - -/**Function******************************************************************** - - Synopsis [Returns one cube contained in the given BDD.] - - Description [] - - SideEffects [] - -******************************************************************************/ -CloudNode * Cloud_GetOneCube( CloudManager * dd, CloudNode * bFunc ) -{ - CloudNode * bFunc0, * bFunc1, * res; - - if ( Cloud_IsConstant(bFunc) ) - return bFunc; - - // cofactor - if ( Cloud_IsComplement(bFunc) ) - { - bFunc0 = Cloud_Not( cloudE(bFunc) ); - bFunc1 = Cloud_Not( cloudT(bFunc) ); - } - else - { - bFunc0 = cloudE(bFunc); - bFunc1 = cloudT(bFunc); - } - - // try to find the cube with the negative literal - res = Cloud_GetOneCube( dd, bFunc0 ); - if ( res == CLOUD_VOID ) - return CLOUD_VOID; - - if ( res != dd->zero ) - { - res = Cloud_bddAnd( dd, res, Cloud_Not(dd->vars[Cloud_V(bFunc)]) ); - } - else - { - // try to find the cube with the positive literal - res = Cloud_GetOneCube( dd, bFunc1 ); - if ( res == CLOUD_VOID ) - return CLOUD_VOID; - assert( res != dd->zero ); - res = Cloud_bddAnd( dd, res, dd->vars[Cloud_V(bFunc)] ); - } - return res; -} - -/**Function******************************************************************** - - Synopsis [Prints the BDD as a set of disjoint cubes to the standard output.] - - Description [] - - SideEffects [] - -******************************************************************************/ -void Cloud_bddPrint( CloudManager * dd, CloudNode * Func ) -{ - CloudNode * Cube; - int fFirst = 1; - - if ( Func == dd->zero ) - printf( "Constant 0." ); - else if ( Func == dd->one ) - printf( "Constant 1." ); - else - { - while ( 1 ) - { - Cube = Cloud_GetOneCube( dd, Func ); - if ( Cube == CLOUD_VOID || Cube == dd->zero ) - break; - if ( fFirst ) fFirst = 0; - else printf( " + " ); - Cloud_bddPrintCube( dd, Cube ); - Func = Cloud_bddAnd( dd, Func, Cloud_Not(Cube) ); - } - } - printf( "\n" ); -} - -/**Function******************************************************************** - - Synopsis [Prints one cube.] - - Description [] - - SideEffects [] - -******************************************************************************/ -void Cloud_bddPrintCube( CloudManager * dd, CloudNode * bCube ) -{ - CloudNode * bCube0, * bCube1; - - assert( !Cloud_IsConstant(bCube) ); - while ( 1 ) - { - // get the node structure - if ( Cloud_IsConstant(bCube) ) - break; - - // cofactor the cube - if ( Cloud_IsComplement(bCube) ) - { - bCube0 = Cloud_Not( cloudE(bCube) ); - bCube1 = Cloud_Not( cloudT(bCube) ); - } - else - { - bCube0 = cloudE(bCube); - bCube1 = cloudT(bCube); - } - - if ( bCube0 != dd->zero ) - { - assert( bCube1 == dd->zero ); - printf( "[%d]'", cloudV(bCube) ); - bCube = bCube0; - } - else - { - assert( bCube1 != dd->zero ); - printf( "[%d]", cloudV(bCube) ); - bCube = bCube1; - } - } -} - - -/**Function******************************************************************** - - Synopsis [Prints info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Cloud_PrintInfo( CloudManager * dd ) -{ - if ( dd == NULL ) return; - printf( "The number of unique table nodes allocated = %12d.\n", dd->nNodesAlloc ); - printf( "The number of unique table nodes present = %12d.\n", dd->nNodesCur ); - printf( "The number of unique table hits = %12d.\n", dd->nUniqueHits ); - printf( "The number of unique table misses = %12d.\n", dd->nUniqueMisses ); - printf( "The number of unique table steps = %12d.\n", dd->nUniqueSteps ); - printf( "The number of cache hits = %12d.\n", dd->nCacheHits ); - printf( "The number of cache misses = %12d.\n", dd->nCacheMisses ); - printf( "The current signature = %12d.\n", dd->nSignCur ); - printf( "The total memory in use = %12d.\n", dd->nMemUsed ); -} - -/**Function******************************************************************** - - Synopsis [Prints the state of the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Cloud_PrintHashTable( CloudManager * dd ) -{ - int i; - - for ( i = 0; i < dd->nNodesAlloc; i++ ) - if ( dd->tUnique[i].v == CLOUD_CONST_INDEX ) - printf( "-" ); - else - printf( "+" ); - printf( "\n" ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/kit/cloud.h b/src/aig/kit/cloud.h deleted file mode 100644 index ac9d45f4..00000000 --- a/src/aig/kit/cloud.h +++ /dev/null @@ -1,269 +0,0 @@ -/**CFile**************************************************************** - - FileName [cloud.h] - - PackageName [Fast application-specific BDD package.] - - Synopsis [Interface of the package.] - - Author [Alan Mishchenko ] - - Affiliation [ECE Department. Portland State University, Portland, Oregon.] - - Date [Ver. 1.0. Started - June 10, 2002.] - - Revision [$Id: cloud.h,v 1.0 2002/06/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CLOUD_H__ -#define __CLOUD_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#ifdef _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#endif - -//////////////////////////////////////////////////////////////////////// -// n | 2^n || n | 2^n || n | 2^n || n | 2^n // -//====================================================================// -// 1 | 2 || 9 | 512 || 17 | 131,072 || 25 | 33,554,432 // -// 2 | 4 || 10 | 1,024 || 18 | 262,144 || 26 | 67,108,864 // -// 3 | 8 || 11 | 2,048 || 19 | 524,288 || 27 | 134,217,728 // -// 4 | 16 || 12 | 4,096 || 20 | 1,048,576 || 28 | 268,435,456 // -// 5 | 32 || 13 | 8,192 || 21 | 2,097,152 || 29 | 536,870,912 // -// 6 | 64 || 14 | 16,384 || 22 | 4,194,304 || 30 | 1,073,741,824 // -// 7 | 128 || 15 | 32,768 || 23 | 8,388,608 || 31 | 2,147,483,648 // -// 8 | 256 || 16 | 65,536 || 24 | 16,777,216 || 32 | 4,294,967,296 // -//////////////////////////////////////////////////////////////////////// - -// data structure typedefs -typedef struct cloudManager CloudManager; -typedef unsigned CloudVar; -typedef unsigned CloudSign; -typedef struct cloudNode CloudNode; -typedef struct cloudCacheEntry1 CloudCacheEntry1; -typedef struct cloudCacheEntry2 CloudCacheEntry2; -typedef struct cloudCacheEntry3 CloudCacheEntry3; - -// operation codes used to set up the cache -typedef enum { - CLOUD_OPER_AND, - CLOUD_OPER_XOR, - CLOUD_OPER_BDIFF, - CLOUD_OPER_LEQ -} CloudOper; - -/* -// the number of operators using cache -static int CacheOperNum = 4; - -// the ratio of cache size to the unique table size for each operator -static int CacheLogRatioDefault[4] = { - 4, // CLOUD_OPER_AND, - 8, // CLOUD_OPER_XOR, - 8, // CLOUD_OPER_BDIFF, - 8 // CLOUD_OPER_LEQ -}; - -// the ratio of cache size to the unique table size for each operator -static int CacheSize[4] = { - 2, // CLOUD_OPER_AND, - 2, // CLOUD_OPER_XOR, - 2, // CLOUD_OPER_BDIFF, - 2 // CLOUD_OPER_LEQ -}; -*/ - -// data structure definitions -struct cloudManager // the fast bdd manager -{ - // variables - int nVars; // the number of variables allocated - // bits - int bitsNode; // the number of bits used for the node - int bitsCache[4]; // default: bitsNode - CacheSizeRatio[i] - // shifts - int shiftUnique; // 8*sizeof(unsigned) - (bitsNode + 1) - int shiftCache[4]; // 8*sizeof(unsigned) - bitsCache[i] - // nodes - int nNodesAlloc; // 2 ^ (bitsNode + 1) - int nNodesLimit; // 2 ^ bitsNode - int nNodesCur; // the current number of nodes (including const1 and vars) - // signature - CloudSign nSignCur; - - // statistics - int nMemUsed; // memory usage in bytes - // cache stats - int nUniqueHits; // hits in the unique table - int nUniqueMisses; // misses in the unique table - int nCacheHits; // hits in the caches - int nCacheMisses; // misses in the caches - // the number of steps through the hash table - int nUniqueSteps; - - // tables - CloudNode * tUnique; // the unique table to store BDD nodes - - // special nodes - CloudNode * pNodeStart; // the pointer to the first node - CloudNode * pNodeEnd; // the pointer to the first node out of the table - - // constants and variables - CloudNode * one; // the one function - CloudNode * zero; // the zero function - CloudNode ** vars; // the elementary variables - - // temporary storage for nodes - CloudNode ** ppNodes; - - // caches - CloudCacheEntry2 * tCaches[20]; // caches -}; - -struct cloudNode // representation of the node in the unique table -{ - CloudSign s; // signature - CloudVar v; // variable - CloudNode * e; // negative cofactor - CloudNode * t; // positive cofactor -}; -struct cloudCacheEntry1 // one-argument cache -{ - CloudSign s; // signature - CloudNode * a; // argument 1 - CloudNode * r; // result -}; -struct cloudCacheEntry2 // the two-argument cache -{ - CloudSign s; // signature - CloudNode * a; - CloudNode * b; - CloudNode * r; -}; -struct cloudCacheEntry3 // the three-argument cache -{ - CloudSign s; // signature - CloudNode * a; - CloudNode * b; - CloudNode * c; - CloudNode * r; -}; - - -// parameters -#define CLOUD_NODE_BITS 23 -#define CLOUD_ONE ((unsigned)0x00000001) -#define CLOUD_NOT_ONE ((unsigned)0xfffffffe) -#define CLOUD_VOID ((unsigned)0x00000000) - -#define CLOUD_CONST_INDEX ((unsigned)0x0fffffff) -#define CLOUD_MARK_ON ((unsigned)0x10000000) -#define CLOUD_MARK_OFF ((unsigned)0xefffffff) - -// hash functions a la Buddy -#define cloudHashBuddy2(x,y,s) ((((x)+(y))*((x)+(y)+1)/2) & ((1<<(32-(s)))-1)) -#define cloudHashBuddy3(x,y,z,s) (cloudHashBuddy2((cloudHashBuddy2((x),(y),(s))),(z),(s)) & ((1<<(32-(s)))-1)) -// hash functions a la Cudd -#define DD_P1 12582917 -#define DD_P2 4256249 -#define DD_P3 741457 -#define DD_P4 1618033999 -#define cloudHashCudd2(f,g,s) ((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) -#define cloudHashCudd3(f,g,h,s) (((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2 + (unsigned)(h)) * DD_P3) >> (s)) - -// node complementation (using node) -#define Cloud_Regular(p) ((CloudNode*)(((unsigned)(p)) & CLOUD_NOT_ONE)) // get the regular node (w/o bubble) -#define Cloud_Not(p) ((CloudNode*)(((unsigned)(p)) ^ CLOUD_ONE)) // complement the node -#define Cloud_NotCond(p,c) (((int)(c))? Cloud_Not(p):(p)) // complement the node conditionally -#define Cloud_IsComplement(p) ((int)(((unsigned)(p)) & CLOUD_ONE)) // check if complemented -// checking constants (using node) -#define Cloud_IsConstant(p) (((Cloud_Regular(p))->v & CLOUD_MARK_OFF) == CLOUD_CONST_INDEX) -#define cloudIsConstant(p) (((p)->v & CLOUD_MARK_OFF) == CLOUD_CONST_INDEX) - -// retrieving values from the node (using node structure) -#define Cloud_V(p) ((Cloud_Regular(p))->v) -#define Cloud_E(p) ((Cloud_Regular(p))->e) -#define Cloud_T(p) ((Cloud_Regular(p))->t) -// retrieving values from the regular node (using node structure) -#define cloudV(p) ((p)->v) -#define cloudE(p) ((p)->e) -#define cloudT(p) ((p)->t) -// marking/unmarking (using node structure) -#define cloudNodeMark(p) ((p)->v |= CLOUD_MARK_ON) -#define cloudNodeUnmark(p) ((p)->v &= CLOUD_MARK_OFF) -#define cloudNodeIsMarked(p) ((int)((p)->v & CLOUD_MARK_ON)) - -// cache lookups and inserts (using node) -#define cloudCacheLookup1(p,sign,f) (((p)->s == (sign) && (p)->a == (f))? ((p)->r): (CLOUD_VOID)) -#define cloudCacheLookup2(p,sign,f,g) (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g))? ((p)->r): (CLOUD_VOID)) -#define cloudCacheLookup3(p,sign,f,g,h) (((p)->s == (sign) && (p)->a == (f) && (p)->b == (g) && (p)->c == (h))? ((p)->r): (CLOUD_VOID)) -// cache inserts -#define cloudCacheInsert1(p,sign,f,r) (((p)->s = (sign)), ((p)->a = (f)), ((p)->r = (r))) -#define cloudCacheInsert2(p,sign,f,g,r) (((p)->s = (sign)), ((p)->a = (f)), ((p)->b = (g)), ((p)->r = (r))) -#define cloudCacheInsert3(p,sign,f,g,h,r) (((p)->s = (sign)), ((p)->a = (f)), ((p)->b = (g)), ((p)->c = (h)), ((p)->r = (r))) - -//#define CLOUD_ASSERT(p) (assert((p) >= (dd->pNodeStart-1) && (p) < dd->pNodeEnd)) -#define CLOUD_ASSERT(p) assert((p) >= dd->tUnique && (p) < dd->tUnique+dd->nNodesAlloc) - -// utility macros -#ifndef ALLOC -#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#endif - -#ifndef CALLOC -#define CALLOC(type, num) ((type *) calloc((num), sizeof(type))) -#endif - -#ifndef FREE -#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#endif - -#ifndef PRT -#define PRT(a,t) fprintf( stdout, "%s = ", (a)); printf( "%.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) ) -#endif - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// -// starting/stopping -extern CloudManager * Cloud_Init( int nVars, int nBits ); -extern void Cloud_Quit( CloudManager * dd ); -extern void Cloud_Restart( CloudManager * dd ); -extern void Cloud_CacheAllocate( CloudManager * dd, CloudOper oper, int size ); -extern CloudNode * Cloud_MakeNode( CloudManager * dd, CloudVar v, CloudNode * t, CloudNode * e ); -// support and node count -extern CloudNode * Cloud_Support( CloudManager * dd, CloudNode * n ); -extern int Cloud_SupportSize( CloudManager * dd, CloudNode * n ); -extern int Cloud_DagSize( CloudManager * dd, CloudNode * n ); -extern int Cloud_DagCollect( CloudManager * dd, CloudNode * n ); -extern int Cloud_SharingSize( CloudManager * dd, CloudNode * * pn, int nn ); -// cubes -extern CloudNode * Cloud_GetOneCube( CloudManager * dd, CloudNode * n ); -extern void Cloud_bddPrint( CloudManager * dd, CloudNode * Func ); -extern void Cloud_bddPrintCube( CloudManager * dd, CloudNode * Cube ); -// operations -extern CloudNode * Cloud_bddAnd( CloudManager * dd, CloudNode * f, CloudNode * g ); -extern CloudNode * Cloud_bddOr( CloudManager * dd, CloudNode * f, CloudNode * g ); -// stats -extern void Cloud_PrintInfo( CloudManager * dd ); -extern void Cloud_PrintHashTable( CloudManager * dd ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/aig/kit/kit.h b/src/aig/kit/kit.h deleted file mode 100644 index 06a93cf0..00000000 --- a/src/aig/kit/kit.h +++ /dev/null @@ -1,594 +0,0 @@ -/**CFile**************************************************************** - - FileName [kit.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kit.h,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __KIT_H__ -#define __KIT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include "vec.h" -#include "extra.h" -#include "cloud.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Kit_Sop_t_ Kit_Sop_t; -struct Kit_Sop_t_ -{ - int nCubes; // the number of cubes - unsigned * pCubes; // the storage for cubes -}; - -typedef struct Kit_Edge_t_ Kit_Edge_t; -struct Kit_Edge_t_ -{ - unsigned fCompl : 1; // the complemented bit - unsigned Node : 30; // the decomposition node pointed by the edge -}; - -typedef struct Kit_Node_t_ Kit_Node_t; -struct Kit_Node_t_ -{ - Kit_Edge_t eEdge0; // the left child of the node - Kit_Edge_t eEdge1; // the right child of the node - // other info - void * pFunc; // the function of the node (BDD or AIG) - unsigned Level : 14; // the level of this node in the global AIG - // printing info - unsigned fNodeOr : 1; // marks the original OR node - unsigned fCompl0 : 1; // marks the original complemented edge - unsigned fCompl1 : 1; // marks the original complemented edge - // latch info - unsigned nLat0 : 5; // the number of latches on the first edge - unsigned nLat1 : 5; // the number of latches on the second edge - unsigned nLat2 : 5; // the number of latches on the output edge -}; - -typedef struct Kit_Graph_t_ Kit_Graph_t; -struct Kit_Graph_t_ -{ - int fConst; // marks the constant 1 graph - int nLeaves; // the number of leaves - int nSize; // the number of nodes (including the leaves) - int nCap; // the number of allocated nodes - Kit_Node_t * pNodes; // the array of leaves and internal nodes - Kit_Edge_t eRoot; // the pointer to the topmost node -}; - - -// DSD node types -typedef enum { - KIT_DSD_NONE = 0, // 0: unknown - KIT_DSD_CONST1, // 1: constant 1 - KIT_DSD_VAR, // 2: elementary variable - KIT_DSD_AND, // 3: multi-input AND - KIT_DSD_XOR, // 4: multi-input XOR - KIT_DSD_PRIME // 5: arbitrary function of 3+ variables -} Kit_Dsd_t; - -// DSD node -typedef struct Kit_DsdObj_t_ Kit_DsdObj_t; -struct Kit_DsdObj_t_ -{ - unsigned Id : 6; // the number of this node - unsigned Type : 3; // none, const, var, AND, XOR, MUX, PRIME - unsigned fMark : 1; // finished checking output - unsigned Offset : 8; // offset to the truth table - unsigned nRefs : 8; // offset to the truth table - unsigned nFans : 6; // the number of fanins of this node - unsigned char pFans[0]; // the fanin literals -}; - -// DSD network -typedef struct Kit_DsdNtk_t_ Kit_DsdNtk_t; -struct Kit_DsdNtk_t_ -{ - unsigned char nVars; // at most 16 (perhaps 18?) - unsigned char nNodesAlloc; // the number of allocated nodes (at most nVars) - unsigned char nNodes; // the number of nodes - unsigned char Root; // the root of the tree - unsigned * pMem; // memory for the truth tables (memory manager?) - unsigned * pSupps; // supports of the nodes - Kit_DsdObj_t** pNodes; // the nodes -}; - -// DSD manager -typedef struct Kit_DsdMan_t_ Kit_DsdMan_t; -struct Kit_DsdMan_t_ -{ - int nVars; // the maximum number of variables - int nWords; // the number of words in TTs - Vec_Ptr_t * vTtElems; // elementary truth tables - Vec_Ptr_t * vTtNodes; // the node truth tables - // BDD representation - CloudManager * dd; // BDD package - Vec_Ptr_t * vTtBdds; // the node truth tables - Vec_Int_t * vNodes; // temporary array for BDD nodes -}; - -static inline int Kit_DsdVar2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } -static inline int Kit_DsdLit2Var( int Lit ) { return Lit >> 1; } -static inline int Kit_DsdLitIsCompl( int Lit ) { return Lit & 1; } -static inline int Kit_DsdLitNot( int Lit ) { return Lit ^ 1; } -static inline int Kit_DsdLitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } -static inline int Kit_DsdLitRegular( int Lit ) { return Lit & 0xfe; } - -static inline unsigned Kit_DsdObjOffset( int nFans ) { return (nFans >> 2) + ((nFans & 3) > 0); } -static inline unsigned * Kit_DsdObjTruth( Kit_DsdObj_t * pObj ) { return pObj->Type == KIT_DSD_PRIME ? (unsigned *)pObj->pFans + pObj->Offset: NULL; } -static inline int Kit_DsdNtkObjNum( Kit_DsdNtk_t * pNtk ){ return pNtk->nVars + pNtk->nNodes; } -static inline Kit_DsdObj_t * Kit_DsdNtkObj( Kit_DsdNtk_t * pNtk, int Id ) { assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return Id < pNtk->nVars ? NULL : pNtk->pNodes[Id - pNtk->nVars]; } -static inline Kit_DsdObj_t * Kit_DsdNtkRoot( Kit_DsdNtk_t * pNtk ) { return Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(pNtk->Root) ); } -static inline int Kit_DsdLitIsLeaf( Kit_DsdNtk_t * pNtk, int Lit ) { int Id = Kit_DsdLit2Var(Lit); assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return Id < pNtk->nVars; } -static inline unsigned Kit_DsdLitSupport( Kit_DsdNtk_t * pNtk, int Lit ) { int Id = Kit_DsdLit2Var(Lit); assert( Id >= 0 && Id < pNtk->nVars + pNtk->nNodes ); return pNtk->pSupps? (Id < pNtk->nVars? (1 << Id) : pNtk->pSupps[Id - pNtk->nVars]) : 0; } - -#define Kit_DsdNtkForEachObj( pNtk, pObj, i ) \ - for ( i = 0; (i < (pNtk)->nNodes) && ((pObj) = (pNtk)->pNodes[i]); i++ ) -#define Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) \ - for ( i = 0; (i < (pObj)->nFans) && ((iLit) = (pObj)->pFans[i], 1); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define KIT_MIN(a,b) (((a) < (b))? (a) : (b)) -#define KIT_MAX(a,b) (((a) > (b))? (a) : (b)) -#define KIT_INFINITY (100000000) - -#ifndef ALLOC -#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#endif - -#ifndef FREE -#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#endif - -#ifndef REALLOC -#define REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) -#endif - -static inline int Kit_CubeHasLit( unsigned uCube, int i ) { return(uCube & (unsigned)(1< 0; } -static inline unsigned Kit_CubeSetLit( unsigned uCube, int i ) { return uCube | (unsigned)(1<> (32-nVar); } - -static inline int Kit_CubeIsMarked( unsigned uCube ) { return Kit_CubeHasLit( uCube, 31 ); } -static inline unsigned Kit_CubeMark( unsigned uCube ) { return Kit_CubeSetLit( uCube, 31 ); } -static inline unsigned Kit_CubeUnmark( unsigned uCube ) { return Kit_CubeRemLit( uCube, 31 ); } - -static inline int Kit_SopCubeNum( Kit_Sop_t * cSop ) { return cSop->nCubes; } -static inline unsigned Kit_SopCube( Kit_Sop_t * cSop, int i ) { return cSop->pCubes[i]; } -static inline void Kit_SopShrink( Kit_Sop_t * cSop, int nCubesNew ) { cSop->nCubes = nCubesNew; } -static inline void Kit_SopPushCube( Kit_Sop_t * cSop, unsigned uCube ) { cSop->pCubes[cSop->nCubes++] = uCube; } -static inline void Kit_SopWriteCube( Kit_Sop_t * cSop, unsigned uCube, int i ) { cSop->pCubes[i] = uCube; } - -static inline Kit_Edge_t Kit_EdgeCreate( int Node, int fCompl ) { Kit_Edge_t eEdge = { fCompl, Node }; return eEdge; } -static inline unsigned Kit_EdgeToInt( Kit_Edge_t eEdge ) { return (eEdge.Node << 1) | eEdge.fCompl; } -static inline Kit_Edge_t Kit_IntToEdge( unsigned Edge ) { return Kit_EdgeCreate( Edge >> 1, Edge & 1 ); } -static inline unsigned Kit_EdgeToInt_( Kit_Edge_t eEdge ) { return *(unsigned *)&eEdge; } -static inline Kit_Edge_t Kit_IntToEdge_( unsigned Edge ) { return *(Kit_Edge_t *)&Edge; } - -static inline int Kit_GraphIsConst( Kit_Graph_t * pGraph ) { return pGraph->fConst; } -static inline int Kit_GraphIsConst0( Kit_Graph_t * pGraph ) { return pGraph->fConst && pGraph->eRoot.fCompl; } -static inline int Kit_GraphIsConst1( Kit_Graph_t * pGraph ) { return pGraph->fConst && !pGraph->eRoot.fCompl; } -static inline int Kit_GraphIsComplement( Kit_Graph_t * pGraph ) { return pGraph->eRoot.fCompl; } -static inline int Kit_GraphIsVar( Kit_Graph_t * pGraph ) { return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; } -static inline void Kit_GraphComplement( Kit_Graph_t * pGraph ) { pGraph->eRoot.fCompl ^= 1; } -static inline void Kit_GraphSetRoot( Kit_Graph_t * pGraph, Kit_Edge_t eRoot ) { pGraph->eRoot = eRoot; } -static inline int Kit_GraphLeaveNum( Kit_Graph_t * pGraph ) { return pGraph->nLeaves; } -static inline int Kit_GraphNodeNum( Kit_Graph_t * pGraph ) { return pGraph->nSize - pGraph->nLeaves; } -static inline Kit_Node_t * Kit_GraphNode( Kit_Graph_t * pGraph, int i ) { return pGraph->pNodes + i; } -static inline Kit_Node_t * Kit_GraphNodeLast( Kit_Graph_t * pGraph ) { return pGraph->pNodes + pGraph->nSize - 1; } -static inline int Kit_GraphNodeInt( Kit_Graph_t * pGraph, Kit_Node_t * pNode ) { return pNode - pGraph->pNodes; } -static inline int Kit_GraphNodeIsVar( Kit_Graph_t * pGraph, Kit_Node_t * pNode ) { return Kit_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; } -static inline Kit_Node_t * Kit_GraphVar( Kit_Graph_t * pGraph ) { assert( Kit_GraphIsVar( pGraph ) ); return Kit_GraphNode( pGraph, pGraph->eRoot.Node ); } -static inline int Kit_GraphVarInt( Kit_Graph_t * pGraph ) { assert( Kit_GraphIsVar( pGraph ) ); return Kit_GraphNodeInt( pGraph, Kit_GraphVar(pGraph) ); } -static inline Kit_Node_t * Kit_GraphNodeFanin0( Kit_Graph_t * pGraph, Kit_Node_t * pNode ){ return Kit_GraphNodeIsVar(pGraph, pNode)? NULL : Kit_GraphNode(pGraph, pNode->eEdge0.Node); } -static inline Kit_Node_t * Kit_GraphNodeFanin1( Kit_Graph_t * pGraph, Kit_Node_t * pNode ){ return Kit_GraphNodeIsVar(pGraph, pNode)? NULL : Kit_GraphNode(pGraph, pNode->eEdge1.Node); } -static inline int Kit_GraphRootLevel( Kit_Graph_t * pGraph ) { return Kit_GraphNode(pGraph, pGraph->eRoot.Node)->Level; } - -static inline int Kit_Float2Int( float Val ) { return *((int *)&Val); } -static inline float Kit_Int2Float( int Num ) { return *((float *)&Num); } -static inline int Kit_BitWordNum( int nBits ) { return nBits/(8*sizeof(unsigned)) + ((nBits%(8*sizeof(unsigned))) > 0); } -static inline int Kit_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -static inline unsigned Kit_BitMask( int nBits ) { assert( nBits <= 32 ); return ~((~(unsigned)0) << nBits); } - -static inline void Kit_TruthSetBit( unsigned * p, int Bit ) { p[Bit>>5] |= (1<<(Bit & 31)); } -static inline void Kit_TruthXorBit( unsigned * p, int Bit ) { p[Bit>>5] ^= (1<<(Bit & 31)); } -static inline int Kit_TruthHasBit( unsigned * p, int Bit ) { return (p[Bit>>5] & (1<<(Bit & 31))) > 0; } - -static inline int Kit_WordFindFirstBit( unsigned uWord ) -{ - int i; - for ( i = 0; i < 32; i++ ) - if ( uWord & (1 << i) ) - return i; - return -1; -} -static inline int Kit_WordHasOneBit( unsigned uWord ) -{ - return (uWord & (uWord - 1)) == 0; -} -static inline int Kit_WordCountOnes( unsigned uWord ) -{ - uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); - uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); - uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); - uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); - return (uWord & 0x0000FFFF) + (uWord>>16); -} -static inline int Kit_TruthCountOnes( unsigned * pIn, int nVars ) -{ - int w, Counter = 0; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - Counter += Kit_WordCountOnes(pIn[w]); - return Counter; -} -static inline int Kit_TruthFindFirstBit( unsigned * pIn, int nVars ) -{ - int w; - for ( w = 0; w < Kit_TruthWordNum(nVars); w++ ) - if ( pIn[w] ) - return 32*w + Kit_WordFindFirstBit(pIn[w]); - return -1; -} -static inline int Kit_TruthFindFirstZero( unsigned * pIn, int nVars ) -{ - int w; - for ( w = 0; w < Kit_TruthWordNum(nVars); w++ ) - if ( ~pIn[w] ) - return 32*w + Kit_WordFindFirstBit(~pIn[w]); - return -1; -} -static inline int Kit_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn0[w] != pIn1[w] ) - return 0; - return 1; -} -static inline int Kit_TruthIsOpposite( unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn0[w] != ~pIn1[w] ) - return 0; - return 1; -} -static inline int Kit_TruthIsEqualWithPhase( unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - if ( (pIn0[0] & 1) == (pIn1[0] & 1) ) - { - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn0[w] != pIn1[w] ) - return 0; - } - else - { - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn0[w] != ~pIn1[w] ) - return 0; - } - return 1; -} -static inline int Kit_TruthIsConst0( unsigned * pIn, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn[w] ) - return 0; - return 1; -} -static inline int Kit_TruthIsConst1( unsigned * pIn, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn[w] != ~(unsigned)0 ) - return 0; - return 1; -} -static inline int Kit_TruthIsImply( unsigned * pIn1, unsigned * pIn2, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn1[w] & ~pIn2[w] ) - return 0; - return 1; -} -static inline int Kit_TruthIsDisjoint( unsigned * pIn1, unsigned * pIn2, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn1[w] & pIn2[w] ) - return 0; - return 1; -} -static inline int Kit_TruthIsDisjoint3( unsigned * pIn1, unsigned * pIn2, unsigned * pIn3, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn1[w] & pIn2[w] & pIn3[w] ) - return 0; - return 1; -} -static inline void Kit_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn[w]; -} -static inline void Kit_TruthClear( unsigned * pOut, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = 0; -} -static inline void Kit_TruthFill( unsigned * pOut, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~(unsigned)0; -} -static inline void Kit_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~pIn[w]; -} -static inline void Kit_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] & pIn1[w]; -} -static inline void Kit_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] | pIn1[w]; -} -static inline void Kit_TruthXor( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] ^ pIn1[w]; -} -static inline void Kit_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] & ~pIn1[w]; -} -static inline void Kit_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~(pIn0[w] & pIn1[w]); -} -static inline void Kit_TruthAndPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 ) -{ - int w; - if ( fCompl0 && fCompl1 ) - { - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~(pIn0[w] | pIn1[w]); - } - else if ( fCompl0 && !fCompl1 ) - { - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~pIn0[w] & pIn1[w]; - } - else if ( !fCompl0 && fCompl1 ) - { - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] & ~pIn1[w]; - } - else // if ( !fCompl0 && !fCompl1 ) - { - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] & pIn1[w]; - } -} -static inline void Kit_TruthMux( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, unsigned * pCtrl, int nVars ) -{ - int w; - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = (pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]); -} -static inline void Kit_TruthMuxPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, unsigned * pCtrl, int nVars, int fComp0 ) -{ - int w; - if ( fComp0 ) - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = (~pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]); - else - for ( w = Kit_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = (pIn0[w] & ~pCtrl[w]) | (pIn1[w] & pCtrl[w]); -} -static inline void Kit_TruthIthVar( unsigned * pTruth, int nVars, int iVar ) -{ - unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - int k, nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5))); - if ( iVar < 5 ) - { - for ( k = 0; k < nWords; k++ ) - pTruth[k] = Masks[iVar]; - } - else - { - for ( k = 0; k < nWords; k++ ) - if ( k & (1 << (iVar-5)) ) - pTruth[k] = ~(unsigned)0; - else - pTruth[k] = 0; - } -} - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -#define Kit_SopForEachCube( cSop, uCube, i ) \ - for ( i = 0; (i < Kit_SopCubeNum(cSop)) && ((uCube) = Kit_SopCube(cSop, i)); i++ ) -#define Kit_CubeForEachLiteral( uCube, Lit, nLits, i ) \ - for ( i = 0; (i < (nLits)) && ((Lit) = Kit_CubeHasLit(uCube, i)); i++ ) - -#define Kit_GraphForEachLeaf( pGraph, pLeaf, i ) \ - for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Kit_GraphNode(pGraph, i)), 1); i++ ) -#define Kit_GraphForEachNode( pGraph, pAnd, i ) \ - for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Kit_GraphNode(pGraph, i)), 1); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== kitBdd.c ==========================================================*/ -extern DdNode * Kit_SopToBdd( DdManager * dd, Kit_Sop_t * cSop, int nVars ); -extern DdNode * Kit_GraphToBdd( DdManager * dd, Kit_Graph_t * pGraph ); -extern DdNode * Kit_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars, int fMSBonTop ); -/*=== kitCloud.c ==========================================================*/ -extern CloudNode * Kit_TruthToCloud( CloudManager * dd, unsigned * pTruth, int nVars ); -extern unsigned * Kit_CloudToTruth( Vec_Int_t * vNodes, int nVars, Vec_Ptr_t * vStore, int fInv ); -extern int Kit_CreateCloud( CloudManager * dd, CloudNode * pFunc, Vec_Int_t * vNodes ); -extern int Kit_CreateCloudFromTruth( CloudManager * dd, unsigned * pTruth, int nVars, Vec_Int_t * vNodes ); -extern unsigned * Kit_TruthCompose( CloudManager * dd, unsigned * pTruth, int nVars, unsigned ** pInputs, int nVarsAll, Vec_Ptr_t * vStore, Vec_Int_t * vNodes ); -extern void Kit_TruthCofSupports( Vec_Int_t * vBddDir, Vec_Int_t * vBddInv, int nVars, Vec_Int_t * vMemory, unsigned * puSupps ); -/*=== kitDsd.c ==========================================================*/ -extern Kit_DsdMan_t * Kit_DsdManAlloc( int nVars, int nNodes ); -extern void Kit_DsdManFree( Kit_DsdMan_t * p ); -extern Kit_DsdNtk_t * Kit_DsdDeriveNtk( unsigned * pTruth, int nVars, int nLutSize ); -extern unsigned * Kit_DsdTruthCompute( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk ); -extern void Kit_DsdTruth( Kit_DsdNtk_t * pNtk, unsigned * pTruthRes ); -extern void Kit_DsdTruthPartial( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned * pTruthRes, unsigned uSupp ); -extern void Kit_DsdTruthPartialTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthCo, unsigned * pTruthDec ); -extern void Kit_DsdPrint( FILE * pFile, Kit_DsdNtk_t * pNtk ); -extern void Kit_DsdPrintExpanded( Kit_DsdNtk_t * pNtk ); -extern void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ); -extern Kit_DsdNtk_t * Kit_DsdDecompose( unsigned * pTruth, int nVars ); -extern Kit_DsdNtk_t * Kit_DsdDecomposeExpand( unsigned * pTruth, int nVars ); -extern Kit_DsdNtk_t * Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nDecMux ); -extern void Kit_DsdVerify( Kit_DsdNtk_t * pNtk, unsigned * pTruth, int nVars ); -extern void Kit_DsdNtkFree( Kit_DsdNtk_t * pNtk ); -extern int Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk ); -extern unsigned Kit_DsdNonDsdSupports( Kit_DsdNtk_t * pNtk ); -extern unsigned Kit_DsdGetSupports( Kit_DsdNtk_t * p ); -extern Kit_DsdNtk_t * Kit_DsdExpand( Kit_DsdNtk_t * p ); -extern Kit_DsdNtk_t * Kit_DsdShrink( Kit_DsdNtk_t * p, int pPrios[] ); -extern void Kit_DsdRotate( Kit_DsdNtk_t * p, int pFreqs[] ); -extern int Kit_DsdCofactoring( unsigned * pTruth, int nVars, int * pCofVars, int nLimit, int fVerbose ); -/*=== kitFactor.c ==========================================================*/ -extern Kit_Graph_t * Kit_SopFactor( Vec_Int_t * vCover, int fCompl, int nVars, Vec_Int_t * vMemory ); -/*=== kitGraph.c ==========================================================*/ -extern Kit_Graph_t * Kit_GraphCreate( int nLeaves ); -extern Kit_Graph_t * Kit_GraphCreateConst0(); -extern Kit_Graph_t * Kit_GraphCreateConst1(); -extern Kit_Graph_t * Kit_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ); -extern void Kit_GraphFree( Kit_Graph_t * pGraph ); -extern Kit_Node_t * Kit_GraphAppendNode( Kit_Graph_t * pGraph ); -extern Kit_Edge_t Kit_GraphAddNodeAnd( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ); -extern Kit_Edge_t Kit_GraphAddNodeOr( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ); -extern Kit_Edge_t Kit_GraphAddNodeXor( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1, int Type ); -extern Kit_Edge_t Kit_GraphAddNodeMux( Kit_Graph_t * pGraph, Kit_Edge_t eEdgeC, Kit_Edge_t eEdgeT, Kit_Edge_t eEdgeE, int Type ); -extern unsigned Kit_GraphToTruth( Kit_Graph_t * pGraph ); -extern Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); -extern int Kit_GraphLeafDepth_rec( Kit_Graph_t * pGraph, Kit_Node_t * pNode, Kit_Node_t * pLeaf ); -/*=== kitHop.c ==========================================================*/ -//extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); -//extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); -//extern Hop_Obj_t * Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory ); -/*=== kitIsop.c ==========================================================*/ -extern int Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth ); -/*=== kitSop.c ==========================================================*/ -extern void Kit_SopCreate( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory ); -extern void Kit_SopCreateInverse( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory ); -extern void Kit_SopDup( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ); -extern void Kit_SopDivideByLiteralQuo( Kit_Sop_t * cSop, int iLit ); -extern void Kit_SopDivideByCube( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ); -extern void Kit_SopDivideInternal( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ); -extern void Kit_SopMakeCubeFree( Kit_Sop_t * cSop ); -extern int Kit_SopIsCubeFree( Kit_Sop_t * cSop ); -extern void Kit_SopCommonCubeCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ); -extern int Kit_SopAnyLiteral( Kit_Sop_t * cSop, int nLits ); -extern int Kit_SopDivisor( Kit_Sop_t * cResult, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ); -extern void Kit_SopBestLiteralCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, unsigned uCube, int nLits, Vec_Int_t * vMemory ); -/*=== kitTruth.c ==========================================================*/ -extern void Kit_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start ); -extern void Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ); -extern void Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ); -extern int Kit_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ); -extern int Kit_TruthSupportSize( unsigned * pTruth, int nVars ); -extern unsigned Kit_TruthSupport( unsigned * pTruth, int nVars ); -extern void Kit_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ); -extern void Kit_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ); -extern void Kit_TruthCofactor0New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ); -extern void Kit_TruthCofactor1New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ); -extern void Kit_TruthExist( unsigned * pTruth, int nVars, int iVar ); -extern void Kit_TruthExistNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ); -extern void Kit_TruthExistSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ); -extern void Kit_TruthForall( unsigned * pTruth, int nVars, int iVar ); -extern void Kit_TruthForallNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ); -extern void Kit_TruthForallSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ); -extern void Kit_TruthUniqueNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ); -extern void Kit_TruthMuxVar( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ); -extern void Kit_TruthMuxVarPhase( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar, int fCompl0 ); -extern void Kit_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ); -extern int Kit_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ); -extern int Kit_TruthBestCofVar( unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 ); -extern void Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ); -extern void Kit_TruthCountOnesInCofsSlow( unsigned * pTruth, int nVars, short * pStore, unsigned * pAux ); -extern unsigned Kit_TruthHash( unsigned * pIn, int nWords ); -extern unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ); -extern char * Kit_TruthDumpToFile( unsigned * pTruth, int nVars, int nFile ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/kit/kitAig.c b/src/aig/kit/kitAig.c deleted file mode 100644 index 0d5c1686..00000000 --- a/src/aig/kit/kitAig.c +++ /dev/null @@ -1,121 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitAig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [Procedures involving AIGs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kitAig.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" -#include "aig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Kit_GraphToAigInternal( Aig_Man_t * pMan, Kit_Graph_t * pGraph ) -{ - Kit_Node_t * pNode; - Aig_Obj_t * pAnd0, * pAnd1; - int i; - // check for constant function - if ( Kit_GraphIsConst(pGraph) ) - return Aig_NotCond( Aig_ManConst1(pMan), Kit_GraphIsComplement(pGraph) ); - // check for a literal - if ( Kit_GraphIsVar(pGraph) ) - return Aig_NotCond( Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); - // build the AIG nodes corresponding to the AND gates of the graph - Kit_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Aig_NotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Aig_NotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Aig_And( pMan, pAnd0, pAnd1 ); - } - // complement the result if necessary - return Aig_NotCond( pNode->pFunc, Kit_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Kit_GraphToAig( Aig_Man_t * pMan, Aig_Obj_t ** pFanins, Kit_Graph_t * pGraph ) -{ - Kit_Node_t * pNode; - int i; - // collect the fanins - Kit_GraphForEachLeaf( pGraph, pNode, i ) - pNode->pFunc = pFanins[i]; - // perform strashing - return Kit_GraphToAigInternal( pMan, pGraph ); -} - -/**Function************************************************************* - - Synopsis [Strashed onen logic nodes using its truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Obj_t * Kit_TruthToAig( Aig_Man_t * pMan, Aig_Obj_t ** pFanins, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) -{ - Aig_Obj_t * pObj; - Kit_Graph_t * pGraph; - // transform truth table into the decomposition tree - if ( vMemory == NULL ) - { - vMemory = Vec_IntAlloc( 0 ); - pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); - Vec_IntFree( vMemory ); - } - else - pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); - // derive the AIG for the decomposition tree - pObj = Kit_GraphToAig( pMan, pFanins, pGraph ); - Kit_GraphFree( pGraph ); - return pObj; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/kit/kitBdd.c b/src/aig/kit/kitBdd.c deleted file mode 100644 index 9c8d4f7a..00000000 --- a/src/aig/kit/kitBdd.c +++ /dev/null @@ -1,231 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitBdd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [Procedures involving BDDs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kitBdd.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" -#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the BDD for the given SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Kit_SopToBdd( DdManager * dd, Kit_Sop_t * cSop, int nVars ) -{ - DdNode * bSum, * bCube, * bTemp, * bVar; - unsigned uCube; - int Value, i, v; - assert( nVars < 16 ); - // start the cover - bSum = Cudd_ReadLogicZero(dd); Cudd_Ref( bSum ); - // check the logic function of the node - Kit_SopForEachCube( cSop, uCube, i ) - { - bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); - for ( v = 0; v < nVars; v++ ) - { - Value = ((uCube >> 2*v) & 3); - if ( Value == 1 ) - bVar = Cudd_Not( Cudd_bddIthVar( dd, v ) ); - else if ( Value == 2 ) - bVar = Cudd_bddIthVar( dd, v ); - else - continue; - bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - bSum = Cudd_bddOr( dd, bTemp = bSum, bCube ); - Cudd_Ref( bSum ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - } - // complement the result if necessary - Cudd_Deref( bSum ); - return bSum; -} - -/**Function************************************************************* - - Synopsis [Converts graph to BDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Kit_GraphToBdd( DdManager * dd, Kit_Graph_t * pGraph ) -{ - DdNode * bFunc, * bFunc0, * bFunc1; - Kit_Node_t * pNode; - int i; - - // sanity checks - assert( Kit_GraphLeaveNum(pGraph) >= 0 ); - assert( Kit_GraphLeaveNum(pGraph) <= pGraph->nSize ); - - // check for constant function - if ( Kit_GraphIsConst(pGraph) ) - return Cudd_NotCond( b1, Kit_GraphIsComplement(pGraph) ); - // check for a literal - if ( Kit_GraphIsVar(pGraph) ) - return Cudd_NotCond( Cudd_bddIthVar(dd, Kit_GraphVarInt(pGraph)), Kit_GraphIsComplement(pGraph) ); - - // assign the elementary variables - Kit_GraphForEachLeaf( pGraph, pNode, i ) - pNode->pFunc = Cudd_bddIthVar( dd, i ); - - // compute the function for each internal node - Kit_GraphForEachNode( pGraph, pNode, i ) - { - bFunc0 = Cudd_NotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - bFunc1 = Cudd_NotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( pNode->pFunc ); - } - - // deref the intermediate results - bFunc = pNode->pFunc; Cudd_Ref( bFunc ); - Kit_GraphForEachNode( pGraph, pNode, i ) - Cudd_RecursiveDeref( dd, pNode->pFunc ); - Cudd_Deref( bFunc ); - - // complement the result if necessary - return Cudd_NotCond( bFunc, Kit_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Kit_TruthToBdd_rec( DdManager * dd, unsigned * pTruth, int iBit, int nVars, int nVarsTotal, int fMSBonTop ) -{ - DdNode * bF0, * bF1, * bF; - int Var; - if ( nVars <= 5 ) - { - unsigned uTruth, uMask; - uMask = ((~(unsigned)0) >> (32 - (1<>5] >> (iBit&31)) & uMask; - if ( uTruth == 0 ) - return b0; - if ( uTruth == uMask ) - return b1; - } - // find the variable to use - Var = fMSBonTop? nVarsTotal-nVars : nVars-1; - // other special cases can be added - bF0 = Kit_TruthToBdd_rec( dd, pTruth, iBit, nVars-1, nVarsTotal, fMSBonTop ); Cudd_Ref( bF0 ); - bF1 = Kit_TruthToBdd_rec( dd, pTruth, iBit+(1<<(nVars-1)), nVars-1, nVarsTotal, fMSBonTop ); Cudd_Ref( bF1 ); - bF = Cudd_bddIte( dd, dd->vars[Var], bF1, bF0 ); Cudd_Ref( bF ); - Cudd_RecursiveDeref( dd, bF0 ); - Cudd_RecursiveDeref( dd, bF1 ); - Cudd_Deref( bF ); - return bF; -} - -/**Function************************************************************* - - Synopsis [Compute BDD corresponding to the truth table.] - - Description [If truth table has N vars, the BDD depends on N topmost - variables of the BDD manager. The most significant variable of the table - is encoded by the topmost variable of the manager. BDD construction is - efficient in this case because BDD is constructed one node at a time, - by simply adding BDD nodes on top of existent BDD nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Kit_TruthToBdd( DdManager * dd, unsigned * pTruth, int nVars, int fMSBonTop ) -{ - return Kit_TruthToBdd_rec( dd, pTruth, 0, nVars, nVars, fMSBonTop ); -} - -/**Function************************************************************* - - Synopsis [Verifies that the factoring is correct.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_SopFactorVerify( Vec_Int_t * vCover, Kit_Graph_t * pFForm, int nVars ) -{ - static DdManager * dd = NULL; - Kit_Sop_t Sop, * cSop = &Sop; - DdNode * bFunc1, * bFunc2; - Vec_Int_t * vMemory; - int RetValue; - // get the manager - if ( dd == NULL ) - dd = Cudd_Init( 16, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - // derive SOP - vMemory = Vec_IntAlloc( Vec_IntSize(vCover) ); - Kit_SopCreate( cSop, vCover, nVars, vMemory ); - // get the functions - bFunc1 = Kit_SopToBdd( dd, cSop, nVars ); Cudd_Ref( bFunc1 ); - bFunc2 = Kit_GraphToBdd( dd, pFForm ); Cudd_Ref( bFunc2 ); -//Extra_bddPrint( dd, bFunc1 ); printf("\n"); -//Extra_bddPrint( dd, bFunc2 ); printf("\n"); - RetValue = (bFunc1 == bFunc2); - if ( bFunc1 != bFunc2 ) - { - int s; - Extra_bddPrint( dd, bFunc1 ); printf("\n"); - Extra_bddPrint( dd, bFunc2 ); printf("\n"); - s = 0; - } - Cudd_RecursiveDeref( dd, bFunc1 ); - Cudd_RecursiveDeref( dd, bFunc2 ); - Vec_IntFree( vMemory ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/kit/kitCloud.c b/src/aig/kit/kitCloud.c deleted file mode 100644 index 7b160fea..00000000 --- a/src/aig/kit/kitCloud.c +++ /dev/null @@ -1,368 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitCloud.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [Procedures using BDD package CLOUD.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kitCloud.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// internal representation of the function to be decomposed -typedef struct Kit_Mux_t_ Kit_Mux_t; -struct Kit_Mux_t_ -{ - unsigned v : 5; // variable - unsigned t : 12; // then edge - unsigned e : 12; // else edge - unsigned c : 1; // complemented attr of else edge - unsigned i : 1; // complemented attr of top node -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derive BDD from the truth table for 5 variable functions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -CloudNode * Kit_TruthToCloud5_rec( CloudManager * dd, unsigned uTruth, int nVars, int nVarsAll ) -{ - static unsigned uVars[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - CloudNode * pCof0, * pCof1; - unsigned uCof0, uCof1; - assert( nVars <= 5 ); - if ( uTruth == 0 ) - return dd->zero; - if ( uTruth == ~0 ) - return dd->one; - if ( nVars == 1 ) - { - if ( uTruth == uVars[0] ) - return dd->vars[nVarsAll-1]; - if ( uTruth == ~uVars[0] ) - return Cloud_Not(dd->vars[nVarsAll-1]); - assert( 0 ); - } -// Count++; - assert( nVars > 1 ); - uCof0 = uTruth & ~uVars[nVars-1]; - uCof1 = uTruth & uVars[nVars-1]; - uCof0 |= uCof0 << (1<<(nVars-1)); - uCof1 |= uCof1 >> (1<<(nVars-1)); - if ( uCof0 == uCof1 ) - return Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll ); - if ( uCof0 == ~uCof1 ) - { - pCof0 = Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll ); - pCof1 = Cloud_Not( pCof0 ); - } - else - { - pCof0 = Kit_TruthToCloud5_rec( dd, uCof0, nVars - 1, nVarsAll ); - pCof1 = Kit_TruthToCloud5_rec( dd, uCof1, nVars - 1, nVarsAll ); - } - return Cloud_MakeNode( dd, nVarsAll - nVars, pCof1, pCof0 ); -} - -/**Function******************************************************************** - - Synopsis [Compute BDD for the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -CloudNode * Kit_TruthToCloud_rec( CloudManager * dd, unsigned * pTruth, int nVars, int nVarsAll ) -{ - CloudNode * pCof0, * pCof1; - unsigned * pTruth0, * pTruth1; - if ( nVars <= 5 ) - return Kit_TruthToCloud5_rec( dd, pTruth[0], nVars, nVarsAll ); - if ( Kit_TruthIsConst0(pTruth, nVars) ) - return dd->zero; - if ( Kit_TruthIsConst1(pTruth, nVars) ) - return dd->one; -// Count++; - pTruth0 = pTruth; - pTruth1 = pTruth + Kit_TruthWordNum(nVars-1); - if ( Kit_TruthIsEqual( pTruth0, pTruth1, nVars - 1 ) ) - return Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll ); - if ( Kit_TruthIsOpposite( pTruth0, pTruth1, nVars - 1 ) ) - { - pCof0 = Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll ); - pCof1 = Cloud_Not( pCof0 ); - } - else - { - pCof0 = Kit_TruthToCloud_rec( dd, pTruth0, nVars - 1, nVarsAll ); - pCof1 = Kit_TruthToCloud_rec( dd, pTruth1, nVars - 1, nVarsAll ); - } - return Cloud_MakeNode( dd, nVarsAll - nVars, pCof1, pCof0 ); -} - -/**Function******************************************************************** - - Synopsis [Compute BDD for the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -CloudNode * Kit_TruthToCloud( CloudManager * dd, unsigned * pTruth, int nVars ) -{ - CloudNode * pRes; - pRes = Kit_TruthToCloud_rec( dd, pTruth, nVars, nVars ); -// printf( "%d/%d ", Count, Cloud_DagSize(dd, pRes) ); - return pRes; -} - -/**Function******************************************************************** - - Synopsis [Transforms the array of BDDs into the integer array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Kit_CreateCloud( CloudManager * dd, CloudNode * pFunc, Vec_Int_t * vNodes ) -{ - Kit_Mux_t Mux; - int nNodes, i; - // collect BDD nodes - nNodes = Cloud_DagCollect( dd, pFunc ); - if ( nNodes >= (1<<12) ) // because in Kit_Mux_t edge is 12 bit - return 0; - assert( nNodes == Cloud_DagSize( dd, pFunc ) ); - assert( nNodes < dd->nNodesLimit ); - Vec_IntClear( vNodes ); - Vec_IntPush( vNodes, 0 ); // const1 node - dd->ppNodes[0]->s = 0; - for ( i = 1; i < nNodes; i++ ) - { - dd->ppNodes[i]->s = i; - Mux.v = dd->ppNodes[i]->v; - Mux.t = dd->ppNodes[i]->t->s; - Mux.e = Cloud_Regular(dd->ppNodes[i]->e)->s; - Mux.c = Cloud_IsComplement(dd->ppNodes[i]->e); - Mux.i = (i == nNodes - 1)? Cloud_IsComplement(pFunc) : 0; - // put the MUX into the array - Vec_IntPush( vNodes, *((int *)&Mux) ); - } - assert( Vec_IntSize(vNodes) == nNodes ); - // reset signatures - for ( i = 0; i < nNodes; i++ ) - dd->ppNodes[i]->s = dd->nSignCur; - return 1; -} - -/**Function******************************************************************** - - Synopsis [Transforms the array of BDDs into the integer array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Kit_CreateCloudFromTruth( CloudManager * dd, unsigned * pTruth, int nVars, Vec_Int_t * vNodes ) -{ - CloudNode * pFunc; - Cloud_Restart( dd ); - pFunc = Kit_TruthToCloud( dd, pTruth, nVars ); - Vec_IntClear( vNodes ); - return Kit_CreateCloud( dd, pFunc, vNodes ); -} - -/**Function************************************************************* - - Synopsis [Computes composition of truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Kit_CloudToTruth( Vec_Int_t * vNodes, int nVars, Vec_Ptr_t * vStore, int fInv ) -{ - unsigned * pThis, * pFan0, * pFan1; - Kit_Mux_t Mux; - int i, Entry; - assert( Vec_IntSize(vNodes) <= Vec_PtrSize(vStore) ); - pThis = Vec_PtrEntry( vStore, 0 ); - Kit_TruthFill( pThis, nVars ); - Vec_IntForEachEntryStart( vNodes, Entry, i, 1 ) - { - Mux = *((Kit_Mux_t *)&Entry); - assert( (int)Mux.e < i && (int)Mux.t < i && (int)Mux.v < nVars ); - pFan0 = Vec_PtrEntry( vStore, Mux.e ); - pFan1 = Vec_PtrEntry( vStore, Mux.t ); - pThis = Vec_PtrEntry( vStore, i ); - Kit_TruthMuxVarPhase( pThis, pFan0, pFan1, nVars, fInv? Mux.v : nVars-1-Mux.v, Mux.c ); - } - // complement the result - if ( Mux.i ) - Kit_TruthNot( pThis, pThis, nVars ); - return pThis; -} - -/**Function************************************************************* - - Synopsis [Computes composition of truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Kit_TruthCompose( CloudManager * dd, unsigned * pTruth, int nVars, - unsigned ** pInputs, int nVarsAll, Vec_Ptr_t * vStore, Vec_Int_t * vNodes ) -{ - CloudNode * pFunc; - unsigned * pThis, * pFan0, * pFan1; - Kit_Mux_t Mux; - int i, Entry, RetValue; - // derive BDD from truth table - Cloud_Restart( dd ); - pFunc = Kit_TruthToCloud( dd, pTruth, nVars ); - // convert it into nodes - RetValue = Kit_CreateCloud( dd, pFunc, vNodes ); - if ( RetValue == 0 ) - printf( "Kit_TruthCompose(): Internal failure!!!\n" ); - // verify the result -// pFan0 = Kit_CloudToTruth( vNodes, nVars, vStore, 0 ); -// if ( !Kit_TruthIsEqual( pTruth, pFan0, nVars ) ) -// printf( "Failed!\n" ); - // compute truth table from the BDD - assert( Vec_IntSize(vNodes) <= Vec_PtrSize(vStore) ); - pThis = Vec_PtrEntry( vStore, 0 ); - Kit_TruthFill( pThis, nVarsAll ); - Vec_IntForEachEntryStart( vNodes, Entry, i, 1 ) - { - Mux = *((Kit_Mux_t *)&Entry); - pFan0 = Vec_PtrEntry( vStore, Mux.e ); - pFan1 = Vec_PtrEntry( vStore, Mux.t ); - pThis = Vec_PtrEntry( vStore, i ); - Kit_TruthMuxPhase( pThis, pFan0, pFan1, pInputs[nVars-1-Mux.v], nVarsAll, Mux.c ); - } - // complement the result - if ( Mux.i ) - Kit_TruthNot( pThis, pThis, nVarsAll ); - return pThis; -} - -/**Function******************************************************************** - - Synopsis [Compute BDD for the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Kit_TruthCofSupports( Vec_Int_t * vBddDir, Vec_Int_t * vBddInv, int nVars, Vec_Int_t * vMemory, unsigned * puSupps ) -{ - Kit_Mux_t Mux; - unsigned * puSuppAll, * pThis, * pFan0, * pFan1; - int i, v, Var, Entry, nSupps; - nSupps = 2 * nVars; - - // extend storage - if ( Vec_IntSize( vMemory ) < nSupps * Vec_IntSize(vBddDir) ) - Vec_IntGrow( vMemory, nSupps * Vec_IntSize(vBddDir) ); - puSuppAll = Vec_IntArray( vMemory ); - // clear storage for the const node - memset( puSuppAll, 0, sizeof(unsigned) * nSupps ); - // compute supports from nodes - Vec_IntForEachEntryStart( vBddDir, Entry, i, 1 ) - { - Mux = *((Kit_Mux_t *)&Entry); - Var = nVars - 1 - Mux.v; - pFan0 = puSuppAll + nSupps * Mux.e; - pFan1 = puSuppAll + nSupps * Mux.t; - pThis = puSuppAll + nSupps * i; - for ( v = 0; v < nSupps; v++ ) - pThis[v] = pFan0[v] | pFan1[v] | (1<nVars = nVars; - p->nWords = Kit_TruthWordNum( p->nVars ); - p->vTtElems = Vec_PtrAllocTruthTables( p->nVars ); - p->vTtNodes = Vec_PtrAllocSimInfo( nNodes, p->nWords ); - p->dd = Cloud_Init( 16, 14 ); - p->vTtBdds = Vec_PtrAllocSimInfo( (1<<12), p->nWords ); - p->vNodes = Vec_IntAlloc( 512 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the DSD manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdManFree( Kit_DsdMan_t * p ) -{ - Cloud_Quit( p->dd ); - Vec_IntFree( p->vNodes ); - Vec_PtrFree( p->vTtBdds ); - Vec_PtrFree( p->vTtElems ); - Vec_PtrFree( p->vTtNodes ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Allocates the DSD node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_DsdObj_t * Kit_DsdObjAlloc( Kit_DsdNtk_t * pNtk, Kit_Dsd_t Type, int nFans ) -{ - Kit_DsdObj_t * pObj; - int nSize = sizeof(Kit_DsdObj_t) + sizeof(unsigned) * (Kit_DsdObjOffset(nFans) + (Type == KIT_DSD_PRIME) * Kit_TruthWordNum(nFans)); - pObj = (Kit_DsdObj_t *)ALLOC( char, nSize ); - memset( pObj, 0, nSize ); - pObj->Id = pNtk->nVars + pNtk->nNodes; - pObj->Type = Type; - pObj->nFans = nFans; - pObj->Offset = Kit_DsdObjOffset( nFans ); - // add the object - if ( pNtk->nNodes == pNtk->nNodesAlloc ) - { - pNtk->nNodesAlloc *= 2; - pNtk->pNodes = REALLOC( Kit_DsdObj_t *, pNtk->pNodes, pNtk->nNodesAlloc ); - } - assert( pNtk->nNodes < pNtk->nNodesAlloc ); - pNtk->pNodes[pNtk->nNodes++] = pObj; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Deallocates the DSD node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdObjFree( Kit_DsdNtk_t * p, Kit_DsdObj_t * pObj ) -{ - free( pObj ); -} - -/**Function************************************************************* - - Synopsis [Allocates the DSD network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_DsdNtk_t * Kit_DsdNtkAlloc( int nVars ) -{ - Kit_DsdNtk_t * pNtk; - pNtk = ALLOC( Kit_DsdNtk_t, 1 ); - memset( pNtk, 0, sizeof(Kit_DsdNtk_t) ); - pNtk->pNodes = ALLOC( Kit_DsdObj_t *, nVars ); - pNtk->nVars = nVars; - pNtk->nNodesAlloc = nVars; - pNtk->pMem = ALLOC( unsigned, 6 * Kit_TruthWordNum(nVars) ); - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Deallocate the DSD network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdNtkFree( Kit_DsdNtk_t * pNtk ) -{ - Kit_DsdObj_t * pObj; - unsigned i; - Kit_DsdNtkForEachObj( pNtk, pObj, i ) - free( pObj ); - FREE( pNtk->pSupps ); - free( pNtk->pNodes ); - free( pNtk->pMem ); - free( pNtk ); -} - -/**Function************************************************************* - - Synopsis [Prints the hex unsigned into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdPrintHex( FILE * pFile, unsigned * pTruth, int nFans ) -{ - int nDigits, Digit, k; - nDigits = (1 << nFans) / 4; - for ( k = nDigits - 1; k >= 0; k-- ) - { - Digit = ((pTruth[k/8] >> ((k%8) * 4)) & 15); - if ( Digit < 10 ) - fprintf( pFile, "%d", Digit ); - else - fprintf( pFile, "%c", 'A' + Digit-10 ); - } -} - -/**Function************************************************************* - - Synopsis [Recursively print the DSD formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdPrint_rec( FILE * pFile, Kit_DsdNtk_t * pNtk, int Id ) -{ - Kit_DsdObj_t * pObj; - unsigned iLit, i; - char Symbol; - - pObj = Kit_DsdNtkObj( pNtk, Id ); - if ( pObj == NULL ) - { - assert( Id < pNtk->nVars ); - fprintf( pFile, "%c", 'a' + Id ); - return; - } - - if ( pObj->Type == KIT_DSD_CONST1 ) - { - assert( pObj->nFans == 0 ); - fprintf( pFile, "Const1" ); - return; - } - - if ( pObj->Type == KIT_DSD_VAR ) - assert( pObj->nFans == 1 ); - - if ( pObj->Type == KIT_DSD_AND ) - Symbol = '*'; - else if ( pObj->Type == KIT_DSD_XOR ) - Symbol = '+'; - else - Symbol = ','; - - if ( pObj->Type == KIT_DSD_PRIME ) - Kit_DsdPrintHex( stdout, Kit_DsdObjTruth(pObj), pObj->nFans ); - - fprintf( pFile, "(" ); - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - { - if ( Kit_DsdLitIsCompl(iLit) ) - fprintf( pFile, "!" ); - Kit_DsdPrint_rec( pFile, pNtk, Kit_DsdLit2Var(iLit) ); - if ( i < pObj->nFans - 1 ) - fprintf( pFile, "%c", Symbol ); - } - fprintf( pFile, ")" ); -} - -/**Function************************************************************* - - Synopsis [Print the DSD formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdPrint( FILE * pFile, Kit_DsdNtk_t * pNtk ) -{ - fprintf( pFile, "F = " ); - if ( Kit_DsdLitIsCompl(pNtk->Root) ) - fprintf( pFile, "!" ); - Kit_DsdPrint_rec( pFile, pNtk, Kit_DsdLit2Var(pNtk->Root) ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Print the DSD formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdPrintExpanded( Kit_DsdNtk_t * pNtk ) -{ - Kit_DsdNtk_t * pTemp; - pTemp = Kit_DsdExpand( pNtk ); - Kit_DsdPrint( stdout, pTemp ); - Kit_DsdNtkFree( pTemp ); -} - -/**Function************************************************************* - - Synopsis [Print the DSD formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdPrintFromTruth( unsigned * pTruth, int nVars ) -{ - Kit_DsdNtk_t * pTemp; - pTemp = Kit_DsdDecomposeMux( pTruth, nVars, 5 ); - Kit_DsdVerify( pTemp, pTruth, nVars ); - Kit_DsdPrintExpanded( pTemp ); - Kit_DsdNtkFree( pTemp ); -} - -/**Function************************************************************* - - Synopsis [Derives the truth table of the DSD node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Kit_DsdTruthComputeNode_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id ) -{ - Kit_DsdObj_t * pObj; - unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp; - unsigned i, iLit, fCompl; -// unsigned m, nMints, * pTruthPrime, * pTruthMint; - - // get the node with this ID - pObj = Kit_DsdNtkObj( pNtk, Id ); - pTruthRes = Vec_PtrEntry( p->vTtNodes, Id ); - - // special case: literal of an internal node - if ( pObj == NULL ) - { - assert( Id < pNtk->nVars ); - return pTruthRes; - } - - // constant node - if ( pObj->Type == KIT_DSD_CONST1 ) - { - assert( pObj->nFans == 0 ); - Kit_TruthFill( pTruthRes, pNtk->nVars ); - return pTruthRes; - } - - // elementary variable node - if ( pObj->Type == KIT_DSD_VAR ) - { - assert( pObj->nFans == 1 ); - iLit = pObj->pFans[0]; - pTruthFans[0] = Kit_DsdTruthComputeNode_rec( p, pNtk, Kit_DsdLit2Var(iLit) ); - if ( Kit_DsdLitIsCompl(iLit) ) - Kit_TruthNot( pTruthRes, pTruthFans[0], pNtk->nVars ); - else - Kit_TruthCopy( pTruthRes, pTruthFans[0], pNtk->nVars ); - return pTruthRes; - } - - // collect the truth tables of the fanins - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - pTruthFans[i] = Kit_DsdTruthComputeNode_rec( p, pNtk, Kit_DsdLit2Var(iLit) ); - // create the truth table - - // simple gates - if ( pObj->Type == KIT_DSD_AND ) - { - Kit_TruthFill( pTruthRes, pNtk->nVars ); - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Kit_DsdLitIsCompl(iLit) ); - return pTruthRes; - } - if ( pObj->Type == KIT_DSD_XOR ) - { - Kit_TruthClear( pTruthRes, pNtk->nVars ); - fCompl = 0; - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - { - Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); - fCompl ^= Kit_DsdLitIsCompl(iLit); - } - if ( fCompl ) - Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); - return pTruthRes; - } - assert( pObj->Type == KIT_DSD_PRIME ); -/* - // get the truth table of the prime node - pTruthPrime = Kit_DsdObjTruth( pObj ); - // get storage for the temporary minterm - pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); - - // go through the minterms - nMints = (1 << pObj->nFans); - Kit_TruthClear( pTruthRes, pNtk->nVars ); - for ( m = 0; m < nMints; m++ ) - { - if ( !Kit_TruthHasBit(pTruthPrime, m) ) - continue; - Kit_TruthFill( pTruthMint, pNtk->nVars ); - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<nVars ); - } -*/ - pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); - Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); - return pTruthRes; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table of the DSD network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Kit_DsdTruthCompute( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk ) -{ - unsigned * pTruthRes; - int i; - // assign elementary truth ables - assert( pNtk->nVars <= p->nVars ); - for ( i = 0; i < (int)pNtk->nVars; i++ ) - Kit_TruthCopy( Vec_PtrEntry(p->vTtNodes, i), Vec_PtrEntry(p->vTtElems, i), p->nVars ); - // compute truth table for each node - pTruthRes = Kit_DsdTruthComputeNode_rec( p, pNtk, Kit_DsdLit2Var(pNtk->Root) ); - // complement the truth table if needed - if ( Kit_DsdLitIsCompl(pNtk->Root) ) - Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); - return pTruthRes; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table of the DSD node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Kit_DsdTruthComputeNodeOne_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id, unsigned uSupp ) -{ - Kit_DsdObj_t * pObj; - unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp; - unsigned i, iLit, fCompl, nPartial = 0; -// unsigned m, nMints, * pTruthPrime, * pTruthMint; - - // get the node with this ID - pObj = Kit_DsdNtkObj( pNtk, Id ); - pTruthRes = Vec_PtrEntry( p->vTtNodes, Id ); - - // special case: literal of an internal node - if ( pObj == NULL ) - { - assert( Id < pNtk->nVars ); - assert( !uSupp || uSupp != (uSupp & ~(1<Type == KIT_DSD_CONST1 ) - { - assert( pObj->nFans == 0 ); - Kit_TruthFill( pTruthRes, pNtk->nVars ); - return pTruthRes; - } - - // elementary variable node - if ( pObj->Type == KIT_DSD_VAR ) - { - assert( pObj->nFans == 1 ); - iLit = pObj->pFans[0]; - assert( Kit_DsdLitIsLeaf( pNtk, iLit ) ); - pTruthFans[0] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(iLit), uSupp ); - if ( Kit_DsdLitIsCompl(iLit) ) - Kit_TruthNot( pTruthRes, pTruthFans[0], pNtk->nVars ); - else - Kit_TruthCopy( pTruthRes, pTruthFans[0], pNtk->nVars ); - return pTruthRes; - } - - // collect the truth tables of the fanins - if ( uSupp ) - { - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - if ( uSupp != (uSupp & ~Kit_DsdLitSupport(pNtk, iLit)) ) - pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(iLit), uSupp ); - else - { - pTruthFans[i] = NULL; - nPartial = 1; - } - } - else - { - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(iLit), uSupp ); - } - // create the truth table - - // simple gates - if ( pObj->Type == KIT_DSD_AND ) - { - Kit_TruthFill( pTruthRes, pNtk->nVars ); - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - if ( pTruthFans[i] ) - Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Kit_DsdLitIsCompl(iLit) ); - return pTruthRes; - } - if ( pObj->Type == KIT_DSD_XOR ) - { - Kit_TruthClear( pTruthRes, pNtk->nVars ); - fCompl = 0; - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - { - if ( pTruthFans[i] ) - { - Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); - fCompl ^= Kit_DsdLitIsCompl(iLit); - } - } - if ( fCompl ) - Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); - return pTruthRes; - } - assert( pObj->Type == KIT_DSD_PRIME ); - - if ( uSupp && nPartial ) - { - // find the only non-empty component - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - if ( pTruthFans[i] ) - break; - assert( i < pObj->nFans ); - return pTruthFans[i]; - } -/* - // get the truth table of the prime node - pTruthPrime = Kit_DsdObjTruth( pObj ); - // get storage for the temporary minterm - pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); - - // go through the minterms - nMints = (1 << pObj->nFans); - Kit_TruthClear( pTruthRes, pNtk->nVars ); - for ( m = 0; m < nMints; m++ ) - { - if ( !Kit_TruthHasBit(pTruthPrime, m) ) - continue; - Kit_TruthFill( pTruthMint, pNtk->nVars ); - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<nVars ); - } -*/ - pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); - Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); - return pTruthRes; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table of the DSD network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Kit_DsdTruthComputeOne( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp ) -{ - unsigned * pTruthRes; - int i; - // if support is specified, request that supports are available - if ( uSupp ) - Kit_DsdGetSupports( pNtk ); - // assign elementary truth tables - assert( pNtk->nVars <= p->nVars ); - for ( i = 0; i < (int)pNtk->nVars; i++ ) - Kit_TruthCopy( Vec_PtrEntry(p->vTtNodes, i), Vec_PtrEntry(p->vTtElems, i), p->nVars ); - // compute truth table for each node - pTruthRes = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(pNtk->Root), uSupp ); - // complement the truth table if needed - if ( Kit_DsdLitIsCompl(pNtk->Root) ) - Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); - return pTruthRes; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table of the DSD node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Kit_DsdTruthComputeNodeTwo_rec( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, int Id, unsigned uSupp, int iVar, unsigned * pTruthDec ) -{ - Kit_DsdObj_t * pObj; - int pfBoundSet[16]; - unsigned * pTruthRes, * pTruthFans[16], * pTruthTemp; - unsigned i, iLit, fCompl, nPartial, uSuppFan, uSuppCur; -// unsigned m, nMints, * pTruthPrime, * pTruthMint; - assert( uSupp > 0 ); - - // get the node with this ID - pObj = Kit_DsdNtkObj( pNtk, Id ); - pTruthRes = Vec_PtrEntry( p->vTtNodes, Id ); - if ( pObj == NULL ) - { - assert( Id < pNtk->nVars ); - return pTruthRes; - } - assert( pObj->Type != KIT_DSD_CONST1 ); - assert( pObj->Type != KIT_DSD_VAR ); - - // count the number of intersecting fanins - // collect the total support of the intersecting fanins - nPartial = 0; - uSuppFan = 0; - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - { - uSuppCur = Kit_DsdLitSupport(pNtk, iLit); - if ( uSupp & uSuppCur ) - { - nPartial++; - uSuppFan |= uSuppCur; - } - } - - // if there is no intersection, or full intersection, use simple procedure - if ( nPartial == 0 || nPartial == pObj->nFans ) - return Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Id, 0 ); - - // if support of the component includes some other variables - // we need to continue constructing it as usual by the two-function procedure - if ( uSuppFan != (uSuppFan & uSupp) ) - { - assert( nPartial == 1 ); -// return Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Id, uSupp, iVar, pTruthDec ); - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - { - if ( uSupp & Kit_DsdLitSupport(pNtk, iLit) ) - pTruthFans[i] = Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Kit_DsdLit2Var(iLit), uSupp, iVar, pTruthDec ); - else - pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(iLit), 0 ); - } - - // create composition/decomposition functions - if ( pObj->Type == KIT_DSD_AND ) - { - Kit_TruthFill( pTruthRes, pNtk->nVars ); - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Kit_DsdLitIsCompl(iLit) ); - return pTruthRes; - } - if ( pObj->Type == KIT_DSD_XOR ) - { - Kit_TruthClear( pTruthRes, pNtk->nVars ); - fCompl = 0; - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - { - fCompl ^= Kit_DsdLitIsCompl(iLit); - Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); - } - if ( fCompl ) - Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); - return pTruthRes; - } - assert( pObj->Type == KIT_DSD_PRIME ); - } - else - { - assert( uSuppFan == (uSuppFan & uSupp) ); - assert( nPartial < pObj->nFans ); - // the support of the insecting component(s) is contained in the bound-set - // and yet there are components that are not contained in the bound set - - // solve the fanins and collect info, which components belong to the bound set - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - { - pTruthFans[i] = Kit_DsdTruthComputeNodeOne_rec( p, pNtk, Kit_DsdLit2Var(iLit), 0 ); - pfBoundSet[i] = (int)((uSupp & Kit_DsdLitSupport(pNtk, iLit)) > 0); - } - - // create composition/decomposition functions - if ( pObj->Type == KIT_DSD_AND ) - { - Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar ); - Kit_TruthFill( pTruthDec, pNtk->nVars ); - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - if ( pfBoundSet[i] ) - Kit_TruthAndPhase( pTruthDec, pTruthDec, pTruthFans[i], pNtk->nVars, 0, Kit_DsdLitIsCompl(iLit) ); - else - Kit_TruthAndPhase( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars, 0, Kit_DsdLitIsCompl(iLit) ); - return pTruthRes; - } - if ( pObj->Type == KIT_DSD_XOR ) - { - Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar ); - Kit_TruthClear( pTruthDec, pNtk->nVars ); - fCompl = 0; - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - { - fCompl ^= Kit_DsdLitIsCompl(iLit); - if ( pfBoundSet[i] ) - Kit_TruthXor( pTruthDec, pTruthDec, pTruthFans[i], pNtk->nVars ); - else - Kit_TruthXor( pTruthRes, pTruthRes, pTruthFans[i], pNtk->nVars ); - } - if ( fCompl ) - Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); - return pTruthRes; - } - assert( pObj->Type == KIT_DSD_PRIME ); - assert( nPartial == 1 ); - - // find the only non-empty component - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - if ( pfBoundSet[i] ) - break; - assert( i < pObj->nFans ); - - // save this component as the decomposed function - Kit_TruthCopy( pTruthDec, pTruthFans[i], pNtk->nVars ); - // set the corresponding component to be the new variable - Kit_TruthIthVar( pTruthFans[i], pNtk->nVars, iVar ); - } -/* - // get the truth table of the prime node - pTruthPrime = Kit_DsdObjTruth( pObj ); - // get storage for the temporary minterm - pTruthMint = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes); - - // go through the minterms - nMints = (1 << pObj->nFans); - Kit_TruthClear( pTruthRes, pNtk->nVars ); - for ( m = 0; m < nMints; m++ ) - { - if ( !Kit_TruthHasBit(pTruthPrime, m) ) - continue; - Kit_TruthFill( pTruthMint, pNtk->nVars ); - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - Kit_TruthAndPhase( pTruthMint, pTruthMint, pTruthFans[i], pNtk->nVars, 0, ((m & (1<nVars ); - } -*/ - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - assert( !Kit_DsdLitIsCompl(iLit) ); - pTruthTemp = Kit_TruthCompose( p->dd, Kit_DsdObjTruth(pObj), pObj->nFans, pTruthFans, pNtk->nVars, p->vTtBdds, p->vNodes ); - Kit_TruthCopy( pTruthRes, pTruthTemp, pNtk->nVars ); - return pTruthRes; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table of the DSD network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Kit_DsdTruthComputeTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthDec ) -{ - unsigned * pTruthRes, uSuppAll; - int i; - assert( uSupp > 0 ); - assert( pNtk->nVars <= p->nVars ); - // compute support of all nodes - uSuppAll = Kit_DsdGetSupports( pNtk ); - // consider special case - there is no overlap - if ( (uSupp & uSuppAll) == 0 ) - { - Kit_TruthClear( pTruthDec, pNtk->nVars ); - return Kit_DsdTruthCompute( p, pNtk ); - } - // consider special case - support is fully contained - if ( (uSupp & uSuppAll) == uSuppAll ) - { - pTruthRes = Kit_DsdTruthCompute( p, pNtk ); - Kit_TruthCopy( pTruthDec, pTruthRes, pNtk->nVars ); - Kit_TruthIthVar( pTruthRes, pNtk->nVars, iVar ); - return pTruthRes; - } - // assign elementary truth tables - for ( i = 0; i < (int)pNtk->nVars; i++ ) - Kit_TruthCopy( Vec_PtrEntry(p->vTtNodes, i), Vec_PtrEntry(p->vTtElems, i), p->nVars ); - // compute truth table for each node - pTruthRes = Kit_DsdTruthComputeNodeTwo_rec( p, pNtk, Kit_DsdLit2Var(pNtk->Root), uSupp, iVar, pTruthDec ); - // complement the truth table if needed - if ( Kit_DsdLitIsCompl(pNtk->Root) ) - Kit_TruthNot( pTruthRes, pTruthRes, pNtk->nVars ); - return pTruthRes; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table of the DSD network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdTruth( Kit_DsdNtk_t * pNtk, unsigned * pTruthRes ) -{ - Kit_DsdMan_t * p; - unsigned * pTruth; - p = Kit_DsdManAlloc( pNtk->nVars, Kit_DsdNtkObjNum(pNtk) ); - pTruth = Kit_DsdTruthCompute( p, pNtk ); - Kit_TruthCopy( pTruthRes, pTruth, pNtk->nVars ); - Kit_DsdManFree( p ); -} - -/**Function************************************************************* - - Synopsis [Derives the truth table of the DSD network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdTruthPartialTwo( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned uSupp, int iVar, unsigned * pTruthCo, unsigned * pTruthDec ) -{ - unsigned * pTruth = Kit_DsdTruthComputeTwo( p, pNtk, uSupp, iVar, pTruthDec ); - if ( pTruthCo ) - Kit_TruthCopy( pTruthCo, pTruth, pNtk->nVars ); -} - -/**Function************************************************************* - - Synopsis [Derives the truth table of the DSD network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdTruthPartial( Kit_DsdMan_t * p, Kit_DsdNtk_t * pNtk, unsigned * pTruthRes, unsigned uSupp ) -{ - unsigned * pTruth = Kit_DsdTruthComputeOne( p, pNtk, uSupp ); - Kit_TruthCopy( pTruthRes, pTruth, pNtk->nVars ); -/* - // verification - { - // compute the same function using different procedure - unsigned * pTruthTemp = Vec_PtrEntry(p->vTtNodes, pNtk->nVars + pNtk->nNodes + 1); - pNtk->pSupps = NULL; - Kit_DsdTruthComputeTwo( p, pNtk, uSupp, -1, pTruthTemp ); -// if ( !Kit_TruthIsEqual( pTruthTemp, pTruthRes, pNtk->nVars ) ) - if ( !Kit_TruthIsEqualWithPhase( pTruthTemp, pTruthRes, pNtk->nVars ) ) - { - printf( "Verification FAILED!\n" ); - Kit_DsdPrint( stdout, pNtk ); - Kit_DsdPrintFromTruth( pTruthRes, pNtk->nVars ); - Kit_DsdPrintFromTruth( pTruthTemp, pNtk->nVars ); - } -// else -// printf( "Verification successful.\n" ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Counts the number of blocks of the given number of inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdCountLuts_rec( Kit_DsdNtk_t * pNtk, int nLutSize, int Id, int * pCounter ) -{ - Kit_DsdObj_t * pObj; - unsigned iLit, i, Res0, Res1; - pObj = Kit_DsdNtkObj( pNtk, Id ); - if ( pObj == NULL ) - return 0; - if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) - { - assert( pObj->nFans == 2 ); - Res0 = Kit_DsdCountLuts_rec( pNtk, nLutSize, Kit_DsdLit2Var(pObj->pFans[0]), pCounter ); - Res1 = Kit_DsdCountLuts_rec( pNtk, nLutSize, Kit_DsdLit2Var(pObj->pFans[1]), pCounter ); - if ( Res0 == 0 && Res1 > 0 ) - return Res1 - 1; - if ( Res0 > 0 && Res1 == 0 ) - return Res0 - 1; - (*pCounter)++; - return nLutSize - 2; - } - assert( pObj->Type == KIT_DSD_PRIME ); - if ( (int)pObj->nFans > nLutSize ) //+ 1 ) - { - *pCounter = 1000; - return 0; - } - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - Kit_DsdCountLuts_rec( pNtk, nLutSize, Kit_DsdLit2Var(iLit), pCounter ); - (*pCounter)++; -// if ( (int)pObj->nFans == nLutSize + 1 ) -// (*pCounter)++; - return nLutSize - pObj->nFans; -} - -/**Function************************************************************* - - Synopsis [Counts the number of blocks of the given number of inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdCountLuts( Kit_DsdNtk_t * pNtk, int nLutSize ) -{ - int Counter = 0; - if ( Kit_DsdNtkRoot(pNtk)->Type == KIT_DSD_CONST1 ) - return 0; - if ( Kit_DsdNtkRoot(pNtk)->Type == KIT_DSD_VAR ) - return 0; - Kit_DsdCountLuts_rec( pNtk, nLutSize, Kit_DsdLit2Var(pNtk->Root), &Counter ); - if ( Counter >= 1000 ) - return -1; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of blocks of the given number of inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdNonDsdSizeMax( Kit_DsdNtk_t * pNtk ) -{ - Kit_DsdObj_t * pObj; - unsigned i, nSizeMax = 0; - Kit_DsdNtkForEachObj( pNtk, pObj, i ) - { - if ( pObj->Type != KIT_DSD_PRIME ) - continue; - if ( nSizeMax < pObj->nFans ) - nSizeMax = pObj->nFans; - } - return nSizeMax; -} - -/**Function************************************************************* - - Synopsis [Finds the union of supports of the non-DSD blocks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Kit_DsdNonDsdSupports( Kit_DsdNtk_t * pNtk ) -{ - Kit_DsdObj_t * pObj; - unsigned i, uSupport = 0; -// FREE( pNtk->pSupps ); - Kit_DsdGetSupports( pNtk ); - Kit_DsdNtkForEachObj( pNtk, pObj, i ) - { - if ( pObj->Type != KIT_DSD_PRIME ) - continue; - uSupport |= Kit_DsdLitSupport( pNtk, Kit_DsdVar2Lit(pObj->Id,0) ); - } - return uSupport; -} - - -/**Function************************************************************* - - Synopsis [Expands the node.] - - Description [Returns the new literal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdExpandCollectAnd_rec( Kit_DsdNtk_t * p, int iLit, int * piLitsNew, int * nLitsNew ) -{ - Kit_DsdObj_t * pObj; - unsigned i, iLitFanin; - // check the end of the supergate - pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); - if ( Kit_DsdLitIsCompl(iLit) || Kit_DsdLit2Var(iLit) < p->nVars || pObj->Type != KIT_DSD_AND ) - { - piLitsNew[(*nLitsNew)++] = iLit; - return; - } - // iterate through the fanins - Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) - Kit_DsdExpandCollectAnd_rec( p, iLitFanin, piLitsNew, nLitsNew ); -} - -/**Function************************************************************* - - Synopsis [Expands the node.] - - Description [Returns the new literal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdExpandCollectXor_rec( Kit_DsdNtk_t * p, int iLit, int * piLitsNew, int * nLitsNew ) -{ - Kit_DsdObj_t * pObj; - unsigned i, iLitFanin; - // check the end of the supergate - pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); - if ( Kit_DsdLit2Var(iLit) < p->nVars || pObj->Type != KIT_DSD_XOR ) - { - piLitsNew[(*nLitsNew)++] = iLit; - return; - } - // iterate through the fanins - pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); - Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) - Kit_DsdExpandCollectXor_rec( p, iLitFanin, piLitsNew, nLitsNew ); - // if the literal was complemented, pass the complemented attribute somewhere - if ( Kit_DsdLitIsCompl(iLit) ) - piLitsNew[0] = Kit_DsdLitNot( piLitsNew[0] ); -} - -/**Function************************************************************* - - Synopsis [Expands the node.] - - Description [Returns the new literal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdExpandNode_rec( Kit_DsdNtk_t * pNew, Kit_DsdNtk_t * p, int iLit ) -{ - unsigned * pTruth, * pTruthNew; - unsigned i, iLitFanin, piLitsNew[16], nLitsNew = 0; - Kit_DsdObj_t * pObj, * pObjNew; - - // consider the case of simple gate - pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); - if ( pObj == NULL ) - return iLit; - if ( pObj->Type == KIT_DSD_AND ) - { - Kit_DsdExpandCollectAnd_rec( p, Kit_DsdLitRegular(iLit), piLitsNew, &nLitsNew ); - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_AND, nLitsNew ); - for ( i = 0; i < pObjNew->nFans; i++ ) - pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, piLitsNew[i] ); - return Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(iLit) ); - } - if ( pObj->Type == KIT_DSD_XOR ) - { - int fCompl = Kit_DsdLitIsCompl(iLit); - Kit_DsdExpandCollectXor_rec( p, Kit_DsdLitRegular(iLit), piLitsNew, &nLitsNew ); - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_XOR, nLitsNew ); - for ( i = 0; i < pObjNew->nFans; i++ ) - { - pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, Kit_DsdLitRegular(piLitsNew[i]) ); - fCompl ^= Kit_DsdLitIsCompl(piLitsNew[i]); - } - return Kit_DsdVar2Lit( pObjNew->Id, fCompl ); - } - assert( pObj->Type == KIT_DSD_PRIME ); - - // create new PRIME node - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_PRIME, pObj->nFans ); - // copy the truth table - pTruth = Kit_DsdObjTruth( pObj ); - pTruthNew = Kit_DsdObjTruth( pObjNew ); - Kit_TruthCopy( pTruthNew, pTruth, pObj->nFans ); - // create fanins - Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i ) - { - pObjNew->pFans[i] = Kit_DsdExpandNode_rec( pNew, p, iLitFanin ); - // complement the corresponding inputs of the truth table - if ( Kit_DsdLitIsCompl(pObjNew->pFans[i]) ) - { - pObjNew->pFans[i] = Kit_DsdLitRegular(pObjNew->pFans[i]); - Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i ); - } - } - // if the incoming phase is complemented, absorb it into the prime node - if ( Kit_DsdLitIsCompl(iLit) ) - Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans ); - return Kit_DsdVar2Lit( pObjNew->Id, 0 ); -} - -/**Function************************************************************* - - Synopsis [Expands the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_DsdNtk_t * Kit_DsdExpand( Kit_DsdNtk_t * p ) -{ - Kit_DsdNtk_t * pNew; - Kit_DsdObj_t * pObjNew; - assert( p->nVars <= 16 ); - // create a new network - pNew = Kit_DsdNtkAlloc( p->nVars ); - // consider simple special cases - if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) - { - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 ); - pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(p->Root) ); - return pNew; - } - if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) - { - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 ); - pObjNew->pFans[0] = Kit_DsdNtkRoot(p)->pFans[0]; - pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(p->Root) ); - return pNew; - } - // convert the root node - pNew->Root = Kit_DsdExpandNode_rec( pNew, p, p->Root ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Sorts the literals by their support.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdCompSort( int pPrios[], unsigned uSupps[], unsigned char * piLits, int nVars, int piLitsRes[] ) -{ - int nSuppSizes[16], Priority[16], pOrder[16]; - int i, k, iVarBest, SuppMax, PrioMax; - // compute support sizes and priorities of the components - for ( i = 0; i < nVars; i++ ) - { - assert( uSupps[i] ); - pOrder[i] = i; - Priority[i] = KIT_INFINITY; - for ( k = 0; k < 16; k++ ) - if ( uSupps[i] & (1 << k) ) - Priority[i] = KIT_MIN( Priority[i], pPrios[k] ); - assert( Priority[i] != 16 ); - nSuppSizes[i] = Kit_WordCountOnes(uSupps[i]); - } - // sort the components by pririty - Extra_BubbleSort( pOrder, Priority, nVars, 0 ); - // find the component by with largest size and lowest priority - iVarBest = -1; - SuppMax = 0; - PrioMax = 0; - for ( i = 0; i < nVars; i++ ) - { - if ( SuppMax < nSuppSizes[i] || (SuppMax == nSuppSizes[i] && PrioMax < Priority[i]) ) - { - SuppMax = nSuppSizes[i]; - PrioMax = Priority[i]; - iVarBest = i; - } - } - assert( iVarBest != -1 ); - // copy the resulting literals - k = 0; - piLitsRes[k++] = piLits[iVarBest]; - for ( i = 0; i < nVars; i++ ) - { - if ( pOrder[i] == iVarBest ) - continue; - piLitsRes[k++] = piLits[pOrder[i]]; - } - assert( k == nVars ); -} - -/**Function************************************************************* - - Synopsis [Shrinks multi-input nodes.] - - Description [Takes the array of variable priorities pPrios.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdShrink_rec( Kit_DsdNtk_t * pNew, Kit_DsdNtk_t * p, int iLit, int pPrios[] ) -{ - Kit_DsdObj_t * pObj, * pObjNew; - unsigned * pTruth, * pTruthNew; - unsigned i, piLitsNew[16], uSupps[16]; - int iLitFanin, iLitNew; - - // consider the case of simple gate - pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); - if ( pObj == NULL ) - return iLit; - if ( pObj->Type == KIT_DSD_AND ) - { - // get the supports - Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) - uSupps[i] = Kit_DsdLitSupport( p, iLitFanin ); - // put the largest component last - // sort other components in the decreasing order of priority of their vars - Kit_DsdCompSort( pPrios, uSupps, pObj->pFans, pObj->nFans, piLitsNew ); - // construct the two-input node network - iLitNew = Kit_DsdShrink_rec( pNew, p, piLitsNew[0], pPrios ); - for ( i = 1; i < pObj->nFans; i++ ) - { - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_AND, 2 ); - pObjNew->pFans[0] = Kit_DsdShrink_rec( pNew, p, piLitsNew[i], pPrios ); - pObjNew->pFans[1] = iLitNew; - iLitNew = Kit_DsdVar2Lit( pObjNew->Id, 0 ); - } - return Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(iLit) ); - } - if ( pObj->Type == KIT_DSD_XOR ) - { - // get the supports - Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) - { - assert( !Kit_DsdLitIsCompl(iLitFanin) ); - uSupps[i] = Kit_DsdLitSupport( p, iLitFanin ); - } - // put the largest component last - // sort other components in the decreasing order of priority of their vars - Kit_DsdCompSort( pPrios, uSupps, pObj->pFans, pObj->nFans, piLitsNew ); - // construct the two-input node network - iLitNew = Kit_DsdShrink_rec( pNew, p, piLitsNew[0], pPrios ); - for ( i = 1; i < pObj->nFans; i++ ) - { - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_XOR, 2 ); - pObjNew->pFans[0] = Kit_DsdShrink_rec( pNew, p, piLitsNew[i], pPrios ); - pObjNew->pFans[1] = iLitNew; - iLitNew = Kit_DsdVar2Lit( pObjNew->Id, 0 ); - } - return Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(iLit) ); - } - assert( pObj->Type == KIT_DSD_PRIME ); - - // create new PRIME node - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_PRIME, pObj->nFans ); - // copy the truth table - pTruth = Kit_DsdObjTruth( pObj ); - pTruthNew = Kit_DsdObjTruth( pObjNew ); - Kit_TruthCopy( pTruthNew, pTruth, pObj->nFans ); - // create fanins - Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i ) - { - pObjNew->pFans[i] = Kit_DsdShrink_rec( pNew, p, iLitFanin, pPrios ); - // complement the corresponding inputs of the truth table - if ( Kit_DsdLitIsCompl(pObjNew->pFans[i]) ) - { - pObjNew->pFans[i] = Kit_DsdLitRegular(pObjNew->pFans[i]); - Kit_TruthChangePhase( pTruthNew, pObjNew->nFans, i ); - } - } - // if the incoming phase is complemented, absorb it into the prime node - if ( Kit_DsdLitIsCompl(iLit) ) - Kit_TruthNot( pTruthNew, pTruthNew, pObj->nFans ); - return Kit_DsdVar2Lit( pObjNew->Id, 0 ); -} - -/**Function************************************************************* - - Synopsis [Shrinks the network.] - - Description [Transforms the network to have two-input nodes so that the - higher-ordered nodes were decomposed out first.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_DsdNtk_t * Kit_DsdShrink( Kit_DsdNtk_t * p, int pPrios[] ) -{ - Kit_DsdNtk_t * pNew; - Kit_DsdObj_t * pObjNew; - assert( p->nVars <= 16 ); - // create a new network - pNew = Kit_DsdNtkAlloc( p->nVars ); - // consider simple special cases - if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) - { - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_CONST1, 0 ); - pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(p->Root) ); - return pNew; - } - if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) - { - pObjNew = Kit_DsdObjAlloc( pNew, KIT_DSD_VAR, 1 ); - pObjNew->pFans[0] = Kit_DsdNtkRoot(p)->pFans[0]; - pNew->Root = Kit_DsdVar2Lit( pObjNew->Id, Kit_DsdLitIsCompl(p->Root) ); - return pNew; - } - // convert the root node - pNew->Root = Kit_DsdShrink_rec( pNew, p, p->Root, pPrios ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Rotates the network.] - - Description [Transforms prime nodes to have the fanin with the - highest frequency of supports go first.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdRotate( Kit_DsdNtk_t * p, int pFreqs[] ) -{ - Kit_DsdObj_t * pObj; - unsigned * pIn, * pOut, * pTemp, k; - int i, v, Temp, uSuppFanin, iFaninLit, WeightMax, FaninMax, nSwaps; - int Weights[16]; - // go through the prime nodes - Kit_DsdNtkForEachObj( p, pObj, i ) - { - if ( pObj->Type != KIT_DSD_PRIME ) - continue; - // count the fanin frequencies - Kit_DsdObjForEachFanin( p, pObj, iFaninLit, k ) - { - uSuppFanin = Kit_DsdLitSupport( p, iFaninLit ); - Weights[k] = 0; - for ( v = 0; v < 16; v++ ) - if ( uSuppFanin & (1 << v) ) - Weights[k] += pFreqs[v] - 1; - } - // find the most frequent fanin - WeightMax = 0; - FaninMax = -1; - for ( k = 0; k < pObj->nFans; k++ ) - if ( WeightMax < Weights[k] ) - { - WeightMax = Weights[k]; - FaninMax = k; - } - // no need to reorder if there are no frequent fanins - if ( FaninMax == -1 ) - continue; - // move the fanins number k to the first place - nSwaps = 0; - pIn = Kit_DsdObjTruth(pObj); - pOut = p->pMem; -// for ( v = FaninMax; v < ((int)pObj->nFans)-1; v++ ) - for ( v = FaninMax-1; v >= 0; v-- ) - { - // swap the fanins - Temp = pObj->pFans[v]; - pObj->pFans[v] = pObj->pFans[v+1]; - pObj->pFans[v+1] = Temp; - // swap the truth table variables - Kit_TruthSwapAdjacentVars( pOut, pIn, pObj->nFans, v ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - nSwaps++; - } - if ( nSwaps & 1 ) - Kit_TruthCopy( pOut, pIn, pObj->nFans ); - } -} - -/**Function************************************************************* - - Synopsis [Compute the support.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Kit_DsdGetSupports_rec( Kit_DsdNtk_t * p, int iLit ) -{ - Kit_DsdObj_t * pObj; - unsigned uSupport, k; - int iFaninLit; - pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); - if ( pObj == NULL ) - return Kit_DsdLitSupport( p, iLit ); - uSupport = 0; - Kit_DsdObjForEachFanin( p, pObj, iFaninLit, k ) - uSupport |= Kit_DsdGetSupports_rec( p, iFaninLit ); - p->pSupps[pObj->Id - p->nVars] = uSupport; - assert( uSupport <= 0xFFFF ); - return uSupport; -} - -/**Function************************************************************* - - Synopsis [Compute the support.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Kit_DsdGetSupports( Kit_DsdNtk_t * p ) -{ - Kit_DsdObj_t * pRoot; - unsigned uSupport; - assert( p->pSupps == NULL ); - p->pSupps = ALLOC( unsigned, p->nNodes ); - // consider simple special cases - pRoot = Kit_DsdNtkRoot(p); - if ( pRoot->Type == KIT_DSD_CONST1 ) - { - assert( p->nNodes == 1 ); - uSupport = p->pSupps[0] = 0; - } - if ( pRoot->Type == KIT_DSD_VAR ) - { - assert( p->nNodes == 1 ); - uSupport = p->pSupps[0] = Kit_DsdLitSupport( p, pRoot->pFans[0] ); - } - else - uSupport = Kit_DsdGetSupports_rec( p, p->Root ); - assert( uSupport <= 0xFFFF ); - return uSupport; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if there is a component with more than 3 inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdFindLargeBox_rec( Kit_DsdNtk_t * pNtk, int Id, int Size ) -{ - Kit_DsdObj_t * pObj; - unsigned iLit, i, RetValue; - pObj = Kit_DsdNtkObj( pNtk, Id ); - if ( pObj == NULL ) - return 0; - if ( pObj->Type == KIT_DSD_PRIME && (int)pObj->nFans > Size ) - return 1; - RetValue = 0; - Kit_DsdObjForEachFanin( pNtk, pObj, iLit, i ) - RetValue |= Kit_DsdFindLargeBox_rec( pNtk, Kit_DsdLit2Var(iLit), Size ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if there is a component with more than 3 inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdFindLargeBox( Kit_DsdNtk_t * pNtk, int Size ) -{ - return Kit_DsdFindLargeBox_rec( pNtk, Kit_DsdLit2Var(pNtk->Root), Size ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the non-DSD 4-var func is implementable with two 3-LUTs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdRootNodeHasCommonVars( Kit_DsdObj_t * pObj0, Kit_DsdObj_t * pObj1 ) -{ - unsigned i, k; - for ( i = 0; i < pObj0->nFans; i++ ) - { - if ( Kit_DsdLit2Var(pObj0->pFans[i]) >= 4 ) - continue; - for ( k = 0; k < pObj1->nFans; k++ ) - if ( Kit_DsdLit2Var(pObj0->pFans[i]) == Kit_DsdLit2Var(pObj1->pFans[k]) ) - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the non-DSD 4-var func is implementable with two 3-LUTs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdCheckVar4Dec2( Kit_DsdNtk_t * pNtk0, Kit_DsdNtk_t * pNtk1 ) -{ - assert( pNtk0->nVars == 4 ); - assert( pNtk1->nVars == 4 ); - if ( Kit_DsdFindLargeBox(pNtk0, 2) ) - return 0; - if ( Kit_DsdFindLargeBox(pNtk1, 2) ) - return 0; - return Kit_DsdRootNodeHasCommonVars( Kit_DsdNtkRoot(pNtk0), Kit_DsdNtkRoot(pNtk1) ); -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdDecompose_rec( Kit_DsdNtk_t * pNtk, Kit_DsdObj_t * pObj, unsigned uSupp, unsigned char * pPar, int nDecMux ) -{ - Kit_DsdObj_t * pRes, * pRes0, * pRes1; - int nWords = Kit_TruthWordNum(pObj->nFans); - unsigned * pTruth = Kit_DsdObjTruth(pObj); - unsigned * pCofs2[2] = { pNtk->pMem, pNtk->pMem + nWords }; - unsigned * pCofs4[2][2] = { {pNtk->pMem + 2 * nWords, pNtk->pMem + 3 * nWords}, {pNtk->pMem + 4 * nWords, pNtk->pMem + 5 * nWords} }; - int i, iLit0, iLit1, nFans0, nFans1, nPairs; - int fEquals[2][2], fOppos, fPairs[4][4]; - unsigned j, k, nFansNew, uSupp0, uSupp1; - - assert( pObj->nFans > 0 ); - assert( pObj->Type == KIT_DSD_PRIME ); - assert( uSupp == (uSupp0 = (unsigned)Kit_TruthSupport(pTruth, pObj->nFans)) ); - - // compress the truth table - if ( uSupp != Kit_BitMask(pObj->nFans) ) - { - nFansNew = Kit_WordCountOnes(uSupp); - Kit_TruthShrink( pNtk->pMem, pTruth, nFansNew, pObj->nFans, uSupp, 1 ); - for ( j = k = 0; j < pObj->nFans; j++ ) - if ( uSupp & (1 << j) ) - pObj->pFans[k++] = pObj->pFans[j]; - assert( k == nFansNew ); - pObj->nFans = k; - uSupp = Kit_BitMask(pObj->nFans); - } - - // consider the single variable case - if ( pObj->nFans == 1 ) - { - pObj->Type = KIT_DSD_NONE; - if ( pTruth[0] == 0x55555555 ) - pObj->pFans[0] = Kit_DsdLitNot(pObj->pFans[0]); - else - assert( pTruth[0] == 0xAAAAAAAA ); - // update the parent pointer - *pPar = Kit_DsdLitNotCond( pObj->pFans[0], Kit_DsdLitIsCompl(*pPar) ); - return; - } - - // decompose the output - if ( !pObj->fMark ) - for ( i = pObj->nFans - 1; i >= 0; i-- ) - { - // get the two-variable cofactors - Kit_TruthCofactor0New( pCofs2[0], pTruth, pObj->nFans, i ); - Kit_TruthCofactor1New( pCofs2[1], pTruth, pObj->nFans, i ); -// assert( !Kit_TruthVarInSupport( pCofs2[0], pObj->nFans, i) ); -// assert( !Kit_TruthVarInSupport( pCofs2[1], pObj->nFans, i) ); - // get the constant cofs - fEquals[0][0] = Kit_TruthIsConst0( pCofs2[0], pObj->nFans ); - fEquals[0][1] = Kit_TruthIsConst0( pCofs2[1], pObj->nFans ); - fEquals[1][0] = Kit_TruthIsConst1( pCofs2[0], pObj->nFans ); - fEquals[1][1] = Kit_TruthIsConst1( pCofs2[1], pObj->nFans ); - fOppos = Kit_TruthIsOpposite( pCofs2[0], pCofs2[1], pObj->nFans ); - assert( !Kit_TruthIsEqual(pCofs2[0], pCofs2[1], pObj->nFans) ); - if ( fEquals[0][0] + fEquals[0][1] + fEquals[1][0] + fEquals[1][1] + fOppos == 0 ) - { - // check the MUX decomposition - uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans ); - uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans ); - assert( uSupp == (uSupp0 | uSupp1 | (1<nFans ); - pRes1 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans ); - for ( k = 0; k < pObj->nFans; k++ ) - { - pRes0->pFans[k] = (uSupp0 & (1 << k))? pObj->pFans[k] : 127; - pRes1->pFans[k] = (uSupp1 & (1 << k))? pObj->pFans[k] : 127; - } - Kit_TruthCopy( Kit_DsdObjTruth(pRes0), pCofs2[0], pObj->nFans ); - Kit_TruthCopy( Kit_DsdObjTruth(pRes1), pCofs2[1], pObj->nFans ); - // update the current one - assert( pObj->Type == KIT_DSD_PRIME ); - pTruth[0] = 0xCACACACA; - pObj->nFans = 3; - pObj->pFans[2] = pObj->pFans[i]; - pObj->pFans[0] = 2*pRes0->Id; pRes0->nRefs++; - pObj->pFans[1] = 2*pRes1->Id; pRes1->nRefs++; - // call recursively - Kit_DsdDecompose_rec( pNtk, pRes0, uSupp0, pObj->pFans + 0, nDecMux ); - Kit_DsdDecompose_rec( pNtk, pRes1, uSupp1, pObj->pFans + 1, nDecMux ); - return; - } - - // create the new node - pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_AND, 2 ); - pRes->nRefs++; - pRes->nFans = 2; - pRes->pFans[0] = pObj->pFans[i]; pObj->pFans[i] = 127; uSupp &= ~(1 << i); - pRes->pFans[1] = 2*pObj->Id; - // update the parent pointer - *pPar = Kit_DsdLitNotCond( 2 * pRes->Id, Kit_DsdLitIsCompl(*pPar) ); - // consider different decompositions - if ( fEquals[0][0] ) - { - Kit_TruthCopy( pTruth, pCofs2[1], pObj->nFans ); - } - else if ( fEquals[0][1] ) - { - pRes->pFans[0] = Kit_DsdLitNot(pRes->pFans[0]); - Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans ); - } - else if ( fEquals[1][0] ) - { - *pPar = Kit_DsdLitNot(*pPar); - pRes->pFans[1] = Kit_DsdLitNot(pRes->pFans[1]); - Kit_TruthCopy( pTruth, pCofs2[1], pObj->nFans ); - } - else if ( fEquals[1][1] ) - { - *pPar = Kit_DsdLitNot(*pPar); - pRes->pFans[0] = Kit_DsdLitNot(pRes->pFans[0]); - pRes->pFans[1] = Kit_DsdLitNot(pRes->pFans[1]); - Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans ); - } - else if ( fOppos ) - { - pRes->Type = KIT_DSD_XOR; - Kit_TruthCopy( pTruth, pCofs2[0], pObj->nFans ); - } - else - assert( 0 ); - // decompose the remainder - assert( Kit_DsdObjTruth(pObj) == pTruth ); - Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pRes->pFans + 1, nDecMux ); - return; - } - pObj->fMark = 1; - - // decompose the input - for ( i = pObj->nFans - 1; i >= 0; i-- ) - { - assert( Kit_TruthVarInSupport( pTruth, pObj->nFans, i ) ); - // get the single variale cofactors - Kit_TruthCofactor0New( pCofs2[0], pTruth, pObj->nFans, i ); - Kit_TruthCofactor1New( pCofs2[1], pTruth, pObj->nFans, i ); - // check the existence of MUX decomposition - uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans ); - uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans ); - assert( uSupp == (uSupp0 | uSupp1 | (1<fMark = 0; - Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux ); - return; - } - assert( uSupp0 && uSupp1 ); - // get the number of unique variables - nFans0 = Kit_WordCountOnes( uSupp0 & ~uSupp1 ); - nFans1 = Kit_WordCountOnes( uSupp1 & ~uSupp0 ); - if ( nFans0 == 1 && nFans1 == 1 ) - { - // get the cofactors w.r.t. the unique variables - iLit0 = Kit_WordFindFirstBit( uSupp0 & ~uSupp1 ); - iLit1 = Kit_WordFindFirstBit( uSupp1 & ~uSupp0 ); - // get four cofactors - Kit_TruthCofactor0New( pCofs4[0][0], pCofs2[0], pObj->nFans, iLit0 ); - Kit_TruthCofactor1New( pCofs4[0][1], pCofs2[0], pObj->nFans, iLit0 ); - Kit_TruthCofactor0New( pCofs4[1][0], pCofs2[1], pObj->nFans, iLit1 ); - Kit_TruthCofactor1New( pCofs4[1][1], pCofs2[1], pObj->nFans, iLit1 ); - // check existence conditions - fEquals[0][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][0], pObj->nFans ); - fEquals[0][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][1], pObj->nFans ); - fEquals[1][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][1], pObj->nFans ); - fEquals[1][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][0], pObj->nFans ); - if ( (fEquals[0][0] && fEquals[0][1]) || (fEquals[1][0] && fEquals[1][1]) ) - { - // construct the MUX - pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, 3 ); - Kit_DsdObjTruth(pRes)[0] = 0xCACACACA; - pRes->nRefs++; - pRes->nFans = 3; - pRes->pFans[0] = pObj->pFans[iLit0]; pObj->pFans[iLit0] = 127; uSupp &= ~(1 << iLit0); - pRes->pFans[1] = pObj->pFans[iLit1]; pObj->pFans[iLit1] = 127; uSupp &= ~(1 << iLit1); - pRes->pFans[2] = pObj->pFans[i]; pObj->pFans[i] = 2 * pRes->Id; // remains in support - // update the node -// if ( fEquals[0][0] && fEquals[0][1] ) -// Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, i ); -// else -// Kit_TruthMuxVar( pTruth, pCofs4[0][1], pCofs4[0][0], pObj->nFans, i ); - Kit_TruthMuxVar( pTruth, pCofs4[1][0], pCofs4[1][1], pObj->nFans, i ); - if ( fEquals[1][0] && fEquals[1][1] ) - pRes->pFans[0] = Kit_DsdLitNot(pRes->pFans[0]); - // decompose the remainder - Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux ); - return; - } - } - - // try other inputs - for ( k = i+1; k < pObj->nFans; k++ ) - { - // get four cofactors ik - Kit_TruthCofactor0New( pCofs4[0][0], pCofs2[0], pObj->nFans, k ); // 00 - Kit_TruthCofactor1New( pCofs4[0][1], pCofs2[0], pObj->nFans, k ); // 01 - Kit_TruthCofactor0New( pCofs4[1][0], pCofs2[1], pObj->nFans, k ); // 10 - Kit_TruthCofactor1New( pCofs4[1][1], pCofs2[1], pObj->nFans, k ); // 11 - // compare equal pairs - fPairs[0][1] = fPairs[1][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[0][1], pObj->nFans ); - fPairs[0][2] = fPairs[2][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][0], pObj->nFans ); - fPairs[0][3] = fPairs[3][0] = Kit_TruthIsEqual( pCofs4[0][0], pCofs4[1][1], pObj->nFans ); - fPairs[1][2] = fPairs[2][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][0], pObj->nFans ); - fPairs[1][3] = fPairs[3][1] = Kit_TruthIsEqual( pCofs4[0][1], pCofs4[1][1], pObj->nFans ); - fPairs[2][3] = fPairs[3][2] = Kit_TruthIsEqual( pCofs4[1][0], pCofs4[1][1], pObj->nFans ); - nPairs = fPairs[0][1] + fPairs[0][2] + fPairs[0][3] + fPairs[1][2] + fPairs[1][3] + fPairs[2][3]; - if ( nPairs != 3 && nPairs != 2 ) - continue; - - // decomposition exists - pRes = Kit_DsdObjAlloc( pNtk, KIT_DSD_AND, 2 ); - pRes->nRefs++; - pRes->nFans = 2; - pRes->pFans[0] = pObj->pFans[k]; pObj->pFans[k] = 2 * pRes->Id; // remains in support - pRes->pFans[1] = pObj->pFans[i]; pObj->pFans[i] = 127; uSupp &= ~(1 << i); - if ( !fPairs[0][1] && !fPairs[0][2] && !fPairs[0][3] ) // 00 - { - pRes->pFans[0] = Kit_DsdLitNot(pRes->pFans[0]); - pRes->pFans[1] = Kit_DsdLitNot(pRes->pFans[1]); - Kit_TruthMuxVar( pTruth, pCofs4[1][1], pCofs4[0][0], pObj->nFans, k ); - } - else if ( !fPairs[1][0] && !fPairs[1][2] && !fPairs[1][3] ) // 01 - { - pRes->pFans[1] = Kit_DsdLitNot(pRes->pFans[1]); - Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, k ); - } - else if ( !fPairs[2][0] && !fPairs[2][1] && !fPairs[2][3] ) // 10 - { - pRes->pFans[0] = Kit_DsdLitNot(pRes->pFans[0]); - Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[1][0], pObj->nFans, k ); - } - else if ( !fPairs[3][0] && !fPairs[3][1] && !fPairs[3][2] ) // 11 - { -// unsigned uSupp0 = Kit_TruthSupport(pCofs4[0][0], pObj->nFans); -// unsigned uSupp1 = Kit_TruthSupport(pCofs4[1][1], pObj->nFans); -// unsigned uSupp; -// Extra_PrintBinary( stdout, &uSupp0, pObj->nFans ); printf( "\n" ); -// Extra_PrintBinary( stdout, &uSupp1, pObj->nFans ); printf( "\n" ); - Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[1][1], pObj->nFans, k ); -// uSupp = Kit_TruthSupport(pTruth, pObj->nFans); -// Extra_PrintBinary( stdout, &uSupp, pObj->nFans ); printf( "\n" ); printf( "\n" ); - } - else - { - assert( fPairs[0][3] && fPairs[1][2] ); - pRes->Type = KIT_DSD_XOR;; - Kit_TruthMuxVar( pTruth, pCofs4[0][0], pCofs4[0][1], pObj->nFans, k ); - } - // decompose the remainder - Kit_DsdDecompose_rec( pNtk, pObj, uSupp, pPar, nDecMux ); - return; - } - } -/* - // if all decomposition methods failed and we are still above the limit, perform MUX-decomposition - if ( nDecMux > 0 && (int)pObj->nFans > nDecMux ) - { - int iBestVar = Kit_TruthBestCofVar( pTruth, pObj->nFans, pCofs2[0], pCofs2[1] ); - uSupp0 = Kit_TruthSupport( pCofs2[0], pObj->nFans ); - uSupp1 = Kit_TruthSupport( pCofs2[1], pObj->nFans ); - // perform MUX decomposition - pRes0 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans ); - pRes1 = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, pObj->nFans ); - for ( k = 0; k < pObj->nFans; k++ ) - pRes0->pFans[k] = pRes1->pFans[k] = pObj->pFans[k]; - Kit_TruthCopy( Kit_DsdObjTruth(pRes0), pCofs2[0], pObj->nFans ); - Kit_TruthCopy( Kit_DsdObjTruth(pRes1), pCofs2[1], pObj->nFans ); - // update the current one - assert( pObj->Type == KIT_DSD_PRIME ); - pTruth[0] = 0xCACACACA; - pObj->nFans = 3; - pObj->pFans[0] = 2*pRes0->Id; pRes0->nRefs++; - pObj->pFans[1] = 2*pRes1->Id; pRes1->nRefs++; - pObj->pFans[2] = pObj->pFans[iBestVar]; - // call recursively - Kit_DsdDecompose_rec( pNtk, pRes0, uSupp0, pObj->pFans + 0, nDecMux ); - Kit_DsdDecompose_rec( pNtk, pRes1, uSupp1, pObj->pFans + 1, nDecMux ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_DsdNtk_t * Kit_DsdDecomposeInt( unsigned * pTruth, int nVars, int nDecMux ) -{ - Kit_DsdNtk_t * pNtk; - Kit_DsdObj_t * pObj; - unsigned uSupp; - int i, nVarsReal; - assert( nVars <= 16 ); - pNtk = Kit_DsdNtkAlloc( nVars ); - pNtk->Root = Kit_DsdVar2Lit( pNtk->nVars, 0 ); - // create the first node - pObj = Kit_DsdObjAlloc( pNtk, KIT_DSD_PRIME, nVars ); - assert( pNtk->pNodes[0] == pObj ); - for ( i = 0; i < nVars; i++ ) - pObj->pFans[i] = Kit_DsdVar2Lit( i, 0 ); - Kit_TruthCopy( Kit_DsdObjTruth(pObj), pTruth, nVars ); - uSupp = Kit_TruthSupport( pTruth, nVars ); - // consider special cases - nVarsReal = Kit_WordCountOnes( uSupp ); - if ( nVarsReal == 0 ) - { - pObj->Type = KIT_DSD_CONST1; - pObj->nFans = 0; - if ( pTruth[0] == 0 ) - pNtk->Root = Kit_DsdLitNot(pNtk->Root); - return pNtk; - } - if ( nVarsReal == 1 ) - { - pObj->Type = KIT_DSD_VAR; - pObj->nFans = 1; - pObj->pFans[0] = Kit_DsdVar2Lit( Kit_WordFindFirstBit(uSupp), (pTruth[0] & 1) ); - return pNtk; - } - Kit_DsdDecompose_rec( pNtk, pNtk->pNodes[0], uSupp, &pNtk->Root, nDecMux ); - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_DsdNtk_t * Kit_DsdDecompose( unsigned * pTruth, int nVars ) -{ - return Kit_DsdDecomposeInt( pTruth, nVars, 0 ); -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_DsdNtk_t * Kit_DsdDecomposeExpand( unsigned * pTruth, int nVars ) -{ - Kit_DsdNtk_t * pNtk, * pTemp; - pNtk = Kit_DsdDecomposeInt( pTruth, nVars, 0 ); - pNtk = Kit_DsdExpand( pTemp = pNtk ); - Kit_DsdNtkFree( pTemp ); - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of the truth table.] - - Description [Uses MUXes to break-down large prime nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_DsdNtk_t * Kit_DsdDecomposeMux( unsigned * pTruth, int nVars, int nDecMux ) -{ - return Kit_DsdDecomposeInt( pTruth, nVars, nDecMux ); -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdTestCofs( Kit_DsdNtk_t * pNtk, unsigned * pTruthInit ) -{ - Kit_DsdNtk_t * pNtk0, * pNtk1, * pTemp; -// Kit_DsdObj_t * pRoot; - unsigned * pCofs2[2] = { pNtk->pMem, pNtk->pMem + Kit_TruthWordNum(pNtk->nVars) }; - unsigned i, * pTruth; - int fVerbose = 1; - int RetValue = 0; - - pTruth = pTruthInit; -// pRoot = Kit_DsdNtkRoot(pNtk); -// pTruth = Kit_DsdObjTruth(pRoot); -// assert( pRoot->nFans == pNtk->nVars ); - - if ( fVerbose ) - { - printf( "Function: " ); -// Extra_PrintBinary( stdout, pTruth, (1 << pNtk->nVars) ); - Extra_PrintHexadecimal( stdout, pTruth, pNtk->nVars ); - printf( "\n" ); - Kit_DsdPrint( stdout, pNtk ); - } - for ( i = 0; i < pNtk->nVars; i++ ) - { - Kit_TruthCofactor0New( pCofs2[0], pTruth, pNtk->nVars, i ); - pNtk0 = Kit_DsdDecompose( pCofs2[0], pNtk->nVars ); - pNtk0 = Kit_DsdExpand( pTemp = pNtk0 ); - Kit_DsdNtkFree( pTemp ); - - if ( fVerbose ) - { - printf( "Cof%d0: ", i ); - Kit_DsdPrint( stdout, pNtk0 ); - } - - Kit_TruthCofactor1New( pCofs2[1], pTruth, pNtk->nVars, i ); - pNtk1 = Kit_DsdDecompose( pCofs2[1], pNtk->nVars ); - pNtk1 = Kit_DsdExpand( pTemp = pNtk1 ); - Kit_DsdNtkFree( pTemp ); - - if ( fVerbose ) - { - printf( "Cof%d1: ", i ); - Kit_DsdPrint( stdout, pNtk1 ); - } - -// if ( Kit_DsdCheckVar4Dec2( pNtk0, pNtk1 ) ) -// RetValue = 1; - - Kit_DsdNtkFree( pNtk0 ); - Kit_DsdNtkFree( pNtk1 ); - } - if ( fVerbose ) - printf( "\n" ); - - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdEval( unsigned * pTruth, int nVars, int nLutSize ) -{ - Kit_DsdMan_t * p; - Kit_DsdNtk_t * pNtk; - unsigned * pTruthC; - int Result; - - // decompose the function - pNtk = Kit_DsdDecompose( pTruth, nVars ); - Result = Kit_DsdCountLuts( pNtk, nLutSize ); -// printf( "\n" ); -// Kit_DsdPrint( stdout, pNtk ); -// printf( "Eval = %d.\n", Result ); - - // recompute the truth table - p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk) ); - pTruthC = Kit_DsdTruthCompute( p, pNtk ); - if ( !Kit_TruthIsEqual( pTruth, pTruthC, nVars ) ) - printf( "Verification failed.\n" ); - Kit_DsdManFree( p ); - - Kit_DsdNtkFree( pNtk ); - return Result; -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdVerify( Kit_DsdNtk_t * pNtk, unsigned * pTruth, int nVars ) -{ - Kit_DsdMan_t * p; - unsigned * pTruthC; - p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk)+2 ); - pTruthC = Kit_DsdTruthCompute( p, pNtk ); - if ( !Extra_TruthIsEqual( pTruth, pTruthC, nVars ) ) - printf( "Verification failed.\n" ); - Kit_DsdManFree( p ); -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdTest( unsigned * pTruth, int nVars ) -{ - Kit_DsdMan_t * p; - unsigned * pTruthC; - Kit_DsdNtk_t * pNtk, * pTemp; - pNtk = Kit_DsdDecompose( pTruth, nVars ); - -// if ( Kit_DsdFindLargeBox(pNtk, Kit_DsdLit2Var(pNtk->Root)) ) -// Kit_DsdPrint( stdout, pNtk ); - -// if ( Kit_DsdNtkRoot(pNtk)->nFans == (unsigned)nVars && nVars == 6 ) - - printf( "\n" ); - Kit_DsdPrint( stdout, pNtk ); - - pNtk = Kit_DsdExpand( pTemp = pNtk ); - Kit_DsdNtkFree( pTemp ); - - Kit_DsdPrint( stdout, pNtk ); - -// if ( Kit_DsdFindLargeBox(pNtk, Kit_DsdLit2Var(pNtk->Root)) ) -// Kit_DsdTestCofs( pNtk, pTruth ); - - // recompute the truth table - p = Kit_DsdManAlloc( nVars, Kit_DsdNtkObjNum(pNtk) ); - pTruthC = Kit_DsdTruthCompute( p, pNtk ); -// Extra_PrintBinary( stdout, pTruth, 1 << nVars ); printf( "\n" ); -// Extra_PrintBinary( stdout, pTruthC, 1 << nVars ); printf( "\n" ); - if ( Extra_TruthIsEqual( pTruth, pTruthC, nVars ) ) - { -// printf( "Verification is okay.\n" ); - } - else - printf( "Verification failed.\n" ); - Kit_DsdManFree( p ); - - - Kit_DsdNtkFree( pNtk ); -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdPrecompute4Vars() -{ - Kit_DsdMan_t * p; - Kit_DsdNtk_t * pNtk, * pTemp; - FILE * pFile; - unsigned uTruth; - unsigned * pTruthC; - char Buffer[256]; - int i, RetValue; - int Counter1 = 0, Counter2 = 0; - - pFile = fopen( "5npn/npn4.txt", "r" ); - for ( i = 0; fgets( Buffer, 100, pFile ); i++ ) - { - Buffer[6] = 0; - Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); - uTruth = ((uTruth & 0xffff) << 16) | (uTruth & 0xffff); - pNtk = Kit_DsdDecompose( &uTruth, 4 ); - - pNtk = Kit_DsdExpand( pTemp = pNtk ); - Kit_DsdNtkFree( pTemp ); - - - if ( Kit_DsdFindLargeBox(pNtk, 3) ) - { -// RetValue = 0; - RetValue = Kit_DsdTestCofs( pNtk, &uTruth ); - printf( "\n" ); - printf( "%3d : Non-DSD function %s %s\n", i, Buffer + 2, RetValue? "implementable" : "" ); - Kit_DsdPrint( stdout, pNtk ); - - Counter1++; - Counter2 += RetValue; - } - -/* - printf( "%3d : Function %s ", i, Buffer + 2 ); - if ( !Kit_DsdFindLargeBox(pNtk, 3) ) - Kit_DsdPrint( stdout, pNtk ); - else - printf( "\n" ); -*/ - - p = Kit_DsdManAlloc( 4, Kit_DsdNtkObjNum(pNtk) ); - pTruthC = Kit_DsdTruthCompute( p, pNtk ); - if ( !Extra_TruthIsEqual( &uTruth, pTruthC, 4 ) ) - printf( "Verification failed.\n" ); - Kit_DsdManFree( p ); - - Kit_DsdNtkFree( pNtk ); - } - fclose( pFile ); - printf( "non-DSD = %d implementable = %d\n", Counter1, Counter2 ); -} - - -/**Function************************************************************* - - Synopsis [Returns the set of cofactoring variables.] - - Description [If there is no DSD components returns 0.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdCofactoringGetVars( Kit_DsdNtk_t ** ppNtk, int nSize, int * pVars ) -{ - Kit_DsdObj_t * pObj; - unsigned m; - int i, k, v, Var, nVars, iFaninLit; - // go through all the networks - nVars = 0; - for ( i = 0; i < nSize; i++ ) - { - // go through the prime objects of each networks - Kit_DsdNtkForEachObj( ppNtk[i], pObj, k ) - { - if ( pObj->Type != KIT_DSD_PRIME ) - continue; - if ( pObj->nFans == 3 ) - continue; - // collect direct fanin variables - Kit_DsdObjForEachFanin( ppNtk[i], pObj, iFaninLit, m ) - { - if ( !Kit_DsdLitIsLeaf(ppNtk[i], iFaninLit) ) - continue; - // add it to the array - Var = Kit_DsdLit2Var( iFaninLit ); - for ( v = 0; v < nVars; v++ ) - if ( pVars[v] == Var ) - break; - if ( v == nVars ) - pVars[nVars++] = Var; - } - } - } - return nVars; -} - -/**Function************************************************************* - - Synopsis [Canonical decomposition into completely DSD-structure.] - - Description [Returns the number of cofactoring steps. Also returns - the cofactoring variables in pVars.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_DsdCofactoring( unsigned * pTruth, int nVars, int * pCofVars, int nLimit, int fVerbose ) -{ - Kit_DsdNtk_t * ppNtks[5][16] = {0}, * pTemp; - unsigned * ppCofs[5][16]; - int pTryVars[16], nTryVars; - int nPrimeSizeMin, nPrimeSizeMax, nPrimeSizeCur; - int nSuppSizeMin, nSuppSizeMax, iVarBest; - int i, k, v, nStep, nSize, nMemSize; - assert( nLimit < 5 ); - - // allocate storage for cofactors - nMemSize = Kit_TruthWordNum(nVars); - ppCofs[0][0] = ALLOC( unsigned, 80 * nMemSize ); - nSize = 0; - for ( i = 0; i < 5; i++ ) - for ( k = 0; k < 16; k++ ) - ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++; - assert( nSize == 80 ); - - // copy the function - Kit_TruthCopy( ppCofs[0][0], pTruth, nVars ); - ppNtks[0][0] = Kit_DsdDecompose( ppCofs[0][0], nVars ); - - if ( fVerbose ) - printf( "\nProcessing prime function with %d support variables:\n", nVars ); - - // perform recursive cofactoring - for ( nStep = 0; nStep < nLimit; nStep++ ) - { - nSize = (1 << nStep); - // find the variables to use in the cofactoring step - nTryVars = Kit_DsdCofactoringGetVars( ppNtks[nStep], nSize, pTryVars ); - if ( nTryVars == 0 ) - break; - // cofactor w.r.t. the above variables - iVarBest = -1; - nPrimeSizeMin = 10000; - nSuppSizeMin = 10000; - for ( v = 0; v < nTryVars; v++ ) - { - nPrimeSizeMax = 0; - nSuppSizeMax = 0; - for ( i = 0; i < nSize; i++ ) - { - // cofactor and decompose cofactors - Kit_TruthCofactor0New( ppCofs[nStep+1][2*i+0], ppCofs[nStep][i], nVars, pTryVars[v] ); - Kit_TruthCofactor1New( ppCofs[nStep+1][2*i+1], ppCofs[nStep][i], nVars, pTryVars[v] ); - ppNtks[nStep+1][2*i+0] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+0], nVars ); - ppNtks[nStep+1][2*i+1] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+1], nVars ); - // compute the largest non-decomp block - nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[nStep+1][2*i+0]); - nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); - nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[nStep+1][2*i+1]); - nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); - // compute the sum total of supports - nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nStep+1][2*i+0], nVars ); - nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nStep+1][2*i+1], nVars ); - // free the networks - Kit_DsdNtkFree( ppNtks[nStep+1][2*i+0] ); - Kit_DsdNtkFree( ppNtks[nStep+1][2*i+1] ); - } - // find the min max support size of the prime component - if ( nPrimeSizeMin > nPrimeSizeMax || (nPrimeSizeMin == nPrimeSizeMax && nSuppSizeMin > nSuppSizeMax) ) - { - nPrimeSizeMin = nPrimeSizeMax; - nSuppSizeMin = nSuppSizeMax; - iVarBest = pTryVars[v]; - } - } - assert( iVarBest != -1 ); - // save the variable - if ( pCofVars ) - pCofVars[nStep] = iVarBest; - // cofactor w.r.t. the best - for ( i = 0; i < nSize; i++ ) - { - Kit_TruthCofactor0New( ppCofs[nStep+1][2*i+0], ppCofs[nStep][i], nVars, iVarBest ); - Kit_TruthCofactor1New( ppCofs[nStep+1][2*i+1], ppCofs[nStep][i], nVars, iVarBest ); - ppNtks[nStep+1][2*i+0] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+0], nVars ); - ppNtks[nStep+1][2*i+1] = Kit_DsdDecompose( ppCofs[nStep+1][2*i+1], nVars ); - if ( fVerbose ) - { - ppNtks[nStep+1][2*i+0] = Kit_DsdExpand( pTemp = ppNtks[nStep+1][2*i+0] ); - Kit_DsdNtkFree( pTemp ); - ppNtks[nStep+1][2*i+1] = Kit_DsdExpand( pTemp = ppNtks[nStep+1][2*i+1] ); - Kit_DsdNtkFree( pTemp ); - - printf( "Cof%d%d: ", nStep+1, 2*i+0 ); - Kit_DsdPrint( stdout, ppNtks[nStep+1][2*i+0] ); - printf( "Cof%d%d: ", nStep+1, 2*i+1 ); - Kit_DsdPrint( stdout, ppNtks[nStep+1][2*i+1] ); - } - } - } - - // free the networks - for ( i = 0; i < 5; i++ ) - for ( k = 0; k < 16; k++ ) - if ( ppNtks[i][k] ) - Kit_DsdNtkFree( ppNtks[i][k] ); - free( ppCofs[0][0] ); - - assert( nStep <= nLimit ); - return nStep; -} - -/**Function************************************************************* - - Synopsis [Canonical decomposition into completely DSD-structure.] - - Description [Returns the number of cofactoring steps. Also returns - the cofactoring variables in pVars.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose ) -{ - Kit_DsdNtk_t * ppNtks[32] = {0}, * pTemp; - unsigned * ppCofs[5][16]; - int piCofVar[5]; - int nPrimeSizeMax, nPrimeSizeCur, nSuppSizeMax; - int i, k, v1, v2, v3, v4, s, nSteps, nSize, nMemSize; - assert( nCofLevel < 5 ); - - // print the function - ppNtks[0] = Kit_DsdDecompose( pTruth, nVars ); - ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); - Kit_DsdNtkFree( pTemp ); - if ( fVerbose ) - Kit_DsdPrint( stdout, ppNtks[0] ); - Kit_DsdNtkFree( ppNtks[0] ); - - // allocate storage for cofactors - nMemSize = Kit_TruthWordNum(nVars); - ppCofs[0][0] = ALLOC( unsigned, 80 * nMemSize ); - nSize = 0; - for ( i = 0; i < 5; i++ ) - for ( k = 0; k < 16; k++ ) - ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++; - assert( nSize == 80 ); - - // copy the function - Kit_TruthCopy( ppCofs[0][0], pTruth, nVars ); - - if ( nCofLevel == 1 ) - for ( v1 = 0; v1 < nVars; v1++ ) - { - nSteps = 0; - piCofVar[nSteps++] = v1; - - printf( " Variables { " ); - for ( i = 0; i < nSteps; i++ ) - printf( "%c ", 'a' + piCofVar[i] ); - printf( "}\n" ); - - // single cofactors - for ( s = 1; s <= nSteps; s++ ) - { - for ( k = 0; k < s; k++ ) - { - nSize = (1 << k); - for ( i = 0; i < nSize; i++ ) - { - Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); - Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); - } - } - } - // compute DSD networks - nSize = (1 << nSteps); - nPrimeSizeMax = 0; - nSuppSizeMax = 0; - for ( i = 0; i < nSize; i++ ) - { - ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); - ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); - Kit_DsdNtkFree( pTemp ); - if ( fVerbose ) - { - printf( "Cof%d%d: ", nSteps, i ); - Kit_DsdPrint( stdout, ppNtks[i] ); - } - // compute the largest non-decomp block - nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); - nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); - Kit_DsdNtkFree( ppNtks[i] ); - nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); - } - printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); - } - - if ( nCofLevel == 2 ) - for ( v1 = 0; v1 < nVars; v1++ ) - for ( v2 = v1+1; v2 < nVars; v2++ ) - { - nSteps = 0; - piCofVar[nSteps++] = v1; - piCofVar[nSteps++] = v2; - - printf( " Variables { " ); - for ( i = 0; i < nSteps; i++ ) - printf( "%c ", 'a' + piCofVar[i] ); - printf( "}\n" ); - - // single cofactors - for ( s = 1; s <= nSteps; s++ ) - { - for ( k = 0; k < s; k++ ) - { - nSize = (1 << k); - for ( i = 0; i < nSize; i++ ) - { - Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); - Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); - } - } - } - // compute DSD networks - nSize = (1 << nSteps); - nPrimeSizeMax = 0; - nSuppSizeMax = 0; - for ( i = 0; i < nSize; i++ ) - { - ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); - ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); - Kit_DsdNtkFree( pTemp ); - if ( fVerbose ) - { - printf( "Cof%d%d: ", nSteps, i ); - Kit_DsdPrint( stdout, ppNtks[i] ); - } - // compute the largest non-decomp block - nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); - nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); - Kit_DsdNtkFree( ppNtks[i] ); - nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); - } - printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); - } - - if ( nCofLevel == 3 ) - for ( v1 = 0; v1 < nVars; v1++ ) - for ( v2 = v1+1; v2 < nVars; v2++ ) - for ( v3 = v2+1; v3 < nVars; v3++ ) - { - nSteps = 0; - piCofVar[nSteps++] = v1; - piCofVar[nSteps++] = v2; - piCofVar[nSteps++] = v3; - - printf( " Variables { " ); - for ( i = 0; i < nSteps; i++ ) - printf( "%c ", 'a' + piCofVar[i] ); - printf( "}\n" ); - - // single cofactors - for ( s = 1; s <= nSteps; s++ ) - { - for ( k = 0; k < s; k++ ) - { - nSize = (1 << k); - for ( i = 0; i < nSize; i++ ) - { - Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); - Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); - } - } - } - // compute DSD networks - nSize = (1 << nSteps); - nPrimeSizeMax = 0; - nSuppSizeMax = 0; - for ( i = 0; i < nSize; i++ ) - { - ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); - ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); - Kit_DsdNtkFree( pTemp ); - if ( fVerbose ) - { - printf( "Cof%d%d: ", nSteps, i ); - Kit_DsdPrint( stdout, ppNtks[i] ); - } - // compute the largest non-decomp block - nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); - nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); - Kit_DsdNtkFree( ppNtks[i] ); - nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); - } - printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); - } - - if ( nCofLevel == 4 ) - for ( v1 = 0; v1 < nVars; v1++ ) - for ( v2 = v1+1; v2 < nVars; v2++ ) - for ( v3 = v2+1; v3 < nVars; v3++ ) - for ( v4 = v3+1; v4 < nVars; v4++ ) - { - nSteps = 0; - piCofVar[nSteps++] = v1; - piCofVar[nSteps++] = v2; - piCofVar[nSteps++] = v3; - piCofVar[nSteps++] = v4; - - printf( " Variables { " ); - for ( i = 0; i < nSteps; i++ ) - printf( "%c ", 'a' + piCofVar[i] ); - printf( "}\n" ); - - // single cofactors - for ( s = 1; s <= nSteps; s++ ) - { - for ( k = 0; k < s; k++ ) - { - nSize = (1 << k); - for ( i = 0; i < nSize; i++ ) - { - Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); - Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); - } - } - } - // compute DSD networks - nSize = (1 << nSteps); - nPrimeSizeMax = 0; - nSuppSizeMax = 0; - for ( i = 0; i < nSize; i++ ) - { - ppNtks[i] = Kit_DsdDecompose( ppCofs[nSteps][i], nVars ); - ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); - Kit_DsdNtkFree( pTemp ); - if ( fVerbose ) - { - printf( "Cof%d%d: ", nSteps, i ); - Kit_DsdPrint( stdout, ppNtks[i] ); - } - // compute the largest non-decomp block - nPrimeSizeCur = Kit_DsdNonDsdSizeMax(ppNtks[i]); - nPrimeSizeMax = KIT_MAX( nPrimeSizeMax, nPrimeSizeCur ); - Kit_DsdNtkFree( ppNtks[i] ); - nSuppSizeMax += Kit_TruthSupportSize( ppCofs[nSteps][i], nVars ); - } - printf( "Max = %2d. Supps = %2d.\n", nPrimeSizeMax, nSuppSizeMax ); - } - - - free( ppCofs[0][0] ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/kit/kitFactor.c b/src/aig/kit/kitFactor.c deleted file mode 100644 index 4ef3fd94..00000000 --- a/src/aig/kit/kitFactor.c +++ /dev/null @@ -1,338 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitFactor.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [Algebraic factoring.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kitFactor.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// factoring fails if intermediate memory usage exceed this limit -#define KIT_FACTOR_MEM_LIMIT (1<<16) - -static Kit_Edge_t Kit_SopFactor_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ); -static Kit_Edge_t Kit_SopFactorLF_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, Kit_Sop_t * cSimple, int nLits, Vec_Int_t * vMemory ); -static Kit_Edge_t Kit_SopFactorTrivial( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits ); -static Kit_Edge_t Kit_SopFactorTrivialCube( Kit_Graph_t * pFForm, unsigned uCube, int nLits ); - -extern int Kit_SopFactorVerify( Vec_Int_t * cSop, Kit_Graph_t * pFForm, int nVars ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Factors the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Graph_t * Kit_SopFactor( Vec_Int_t * vCover, int fCompl, int nVars, Vec_Int_t * vMemory ) -{ - Kit_Sop_t Sop, Res; - Kit_Sop_t * cSop = &Sop, * cRes = &Res; - Kit_Graph_t * pFForm; - Kit_Edge_t eRoot; - int nCubes = Vec_IntSize(vCover); - - // works for up to 15 variables because divisin procedure - // used the last bit for marking the cubes going to the remainder - assert( nVars < 16 ); - - // check for trivial functions - if ( Vec_IntSize(vCover) == 0 ) - return Kit_GraphCreateConst0(); - if ( Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover, 0) == 0 ) //(int)Kit_CubeMask(2 * nVars) ) - return Kit_GraphCreateConst1(); - - // prepare memory manager -// Vec_IntClear( vMemory ); - Vec_IntGrow( vMemory, KIT_FACTOR_MEM_LIMIT ); - - // perform CST - Kit_SopCreateInverse( cSop, vCover, 2 * nVars, vMemory ); // CST - - // start the factored form - pFForm = Kit_GraphCreate( nVars ); - // factor the cover - eRoot = Kit_SopFactor_rec( pFForm, cSop, 2 * nVars, vMemory ); - // finalize the factored form - Kit_GraphSetRoot( pFForm, eRoot ); - if ( fCompl ) - Kit_GraphComplement( pFForm ); - - // verify the factored form -// Vec_IntShrink( vCover, nCubes ); -// if ( !Kit_SopFactorVerify( vCover, pFForm, nVars ) ) -// printf( "Verification has failed.\n" ); - return pFForm; -} - -/**Function************************************************************* - - Synopsis [Recursive factoring procedure.] - - Description [For the pseudo-code, see Hachtel/Somenzi, - Logic synthesis and verification algorithms, Kluwer, 1996, p. 432.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Edge_t Kit_SopFactor_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ) -{ - Kit_Sop_t Div, Quo, Rem, Com; - Kit_Sop_t * cDiv = &Div, * cQuo = &Quo, * cRem = &Rem, * cCom = &Com; - Kit_Edge_t eNodeDiv, eNodeQuo, eNodeRem, eNodeAnd; - - // make sure the cover contains some cubes - assert( Kit_SopCubeNum(cSop) > 0 ); - - // get the divisor - if ( !Kit_SopDivisor(cDiv, cSop, nLits, vMemory) ) - return Kit_SopFactorTrivial( pFForm, cSop, nLits ); - - // divide the cover by the divisor - Kit_SopDivideInternal( cSop, cDiv, cQuo, cRem, vMemory ); - - // check the trivial case - assert( Kit_SopCubeNum(cQuo) > 0 ); - if ( Kit_SopCubeNum(cQuo) == 1 ) - return Kit_SopFactorLF_rec( pFForm, cSop, cQuo, nLits, vMemory ); - - // make the quotient cube free - Kit_SopMakeCubeFree( cQuo ); - - // divide the cover by the quotient - Kit_SopDivideInternal( cSop, cQuo, cDiv, cRem, vMemory ); - - // check the trivial case - if ( Kit_SopIsCubeFree( cDiv ) ) - { - eNodeDiv = Kit_SopFactor_rec( pFForm, cDiv, nLits, vMemory ); - eNodeQuo = Kit_SopFactor_rec( pFForm, cQuo, nLits, vMemory ); - eNodeAnd = Kit_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); - if ( Kit_SopCubeNum(cRem) == 0 ) - return eNodeAnd; - eNodeRem = Kit_SopFactor_rec( pFForm, cRem, nLits, vMemory ); - return Kit_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); - } - - // get the common cube - Kit_SopCommonCubeCover( cCom, cDiv, vMemory ); - - // solve the simple problem - return Kit_SopFactorLF_rec( pFForm, cSop, cCom, nLits, vMemory ); -} - - -/**Function************************************************************* - - Synopsis [Internal recursive factoring procedure for the leaf case.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Edge_t Kit_SopFactorLF_rec( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, Kit_Sop_t * cSimple, int nLits, Vec_Int_t * vMemory ) -{ - Kit_Sop_t Div, Quo, Rem; - Kit_Sop_t * cDiv = &Div, * cQuo = &Quo, * cRem = &Rem; - Kit_Edge_t eNodeDiv, eNodeQuo, eNodeRem, eNodeAnd; - assert( Kit_SopCubeNum(cSimple) == 1 ); - // get the most often occurring literal - Kit_SopBestLiteralCover( cDiv, cSop, Kit_SopCube(cSimple, 0), nLits, vMemory ); - // divide the cover by the literal - Kit_SopDivideByCube( cSop, cDiv, cQuo, cRem, vMemory ); - // get the node pointer for the literal - eNodeDiv = Kit_SopFactorTrivialCube( pFForm, Kit_SopCube(cDiv, 0), nLits ); - // factor the quotient and remainder - eNodeQuo = Kit_SopFactor_rec( pFForm, cQuo, nLits, vMemory ); - eNodeAnd = Kit_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); - if ( Kit_SopCubeNum(cRem) == 0 ) - return eNodeAnd; - eNodeRem = Kit_SopFactor_rec( pFForm, cRem, nLits, vMemory ); - return Kit_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); -} - - -/**Function************************************************************* - - Synopsis [Factoring cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Edge_t Kit_SopFactorTrivialCube_rec( Kit_Graph_t * pFForm, unsigned uCube, int nStart, int nFinish ) -{ - Kit_Edge_t eNode1, eNode2; - int i, iLit, nLits, nLits1, nLits2; - assert( uCube ); - // count the number of literals in this interval - nLits = 0; - for ( i = nStart; i < nFinish; i++ ) - if ( Kit_CubeHasLit(uCube, i) ) - { - iLit = i; - nLits++; - } - // quit if there is only one literal - if ( nLits == 1 ) - return Kit_EdgeCreate( iLit/2, iLit%2 ); // CST - // split the literals into two parts - nLits1 = nLits/2; - nLits2 = nLits - nLits1; -// nLits2 = nLits/2; -// nLits1 = nLits - nLits2; - // find the splitting point - nLits = 0; - for ( i = nStart; i < nFinish; i++ ) - if ( Kit_CubeHasLit(uCube, i) ) - { - if ( nLits == nLits1 ) - break; - nLits++; - } - // recursively construct the tree for the parts - eNode1 = Kit_SopFactorTrivialCube_rec( pFForm, uCube, nStart, i ); - eNode2 = Kit_SopFactorTrivialCube_rec( pFForm, uCube, i, nFinish ); - return Kit_GraphAddNodeAnd( pFForm, eNode1, eNode2 ); -} - -/**Function************************************************************* - - Synopsis [Factoring cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Edge_t Kit_SopFactorTrivialCube( Kit_Graph_t * pFForm, unsigned uCube, int nLits ) -{ - return Kit_SopFactorTrivialCube_rec( pFForm, uCube, 0, nLits ); -} - -/**Function************************************************************* - - Synopsis [Factoring SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Edge_t Kit_SopFactorTrivial_rec( Kit_Graph_t * pFForm, unsigned * pCubes, int nCubes, int nLits ) -{ - Kit_Edge_t eNode1, eNode2; - int nCubes1, nCubes2; - if ( nCubes == 1 ) - return Kit_SopFactorTrivialCube_rec( pFForm, pCubes[0], 0, nLits ); - // split the cubes into two parts - nCubes1 = nCubes/2; - nCubes2 = nCubes - nCubes1; -// nCubes2 = nCubes/2; -// nCubes1 = nCubes - nCubes2; - // recursively construct the tree for the parts - eNode1 = Kit_SopFactorTrivial_rec( pFForm, pCubes, nCubes1, nLits ); - eNode2 = Kit_SopFactorTrivial_rec( pFForm, pCubes + nCubes1, nCubes2, nLits ); - return Kit_GraphAddNodeOr( pFForm, eNode1, eNode2 ); -} - -/**Function************************************************************* - - Synopsis [Factoring the cover, which has no algebraic divisors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Edge_t Kit_SopFactorTrivial( Kit_Graph_t * pFForm, Kit_Sop_t * cSop, int nLits ) -{ - return Kit_SopFactorTrivial_rec( pFForm, cSop->pCubes, cSop->nCubes, nLits ); -} - - -/**Function************************************************************* - - Synopsis [Testing procedure for the factoring code.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_FactorTest( unsigned * pTruth, int nVars ) -{ - Vec_Int_t * vCover, * vMemory; - Kit_Graph_t * pGraph; -// unsigned uTruthRes; - int RetValue; - - // derive SOP - vCover = Vec_IntAlloc( 0 ); - RetValue = Kit_TruthIsop( pTruth, nVars, vCover, 0 ); - assert( RetValue == 0 ); - - // derive factored form - vMemory = Vec_IntAlloc( 0 ); - pGraph = Kit_SopFactor( vCover, 0, nVars, vMemory ); -/* - // derive truth table - assert( nVars <= 5 ); - uTruthRes = Kit_GraphToTruth( pGraph ); - if ( uTruthRes != pTruth[0] ) - printf( "Verification failed!" ); -*/ - printf( "Vars = %2d. Cubes = %3d. FFNodes = %3d. FF_memory = %3d.\n", - nVars, Vec_IntSize(vCover), Kit_GraphNodeNum(pGraph), Vec_IntSize(vMemory) ); - - Vec_IntFree( vMemory ); - Vec_IntFree( vCover ); - Kit_GraphFree( pGraph ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/kit/kitGraph.c b/src/aig/kit/kitGraph.c deleted file mode 100644 index 8bc7ca91..00000000 --- a/src/aig/kit/kitGraph.c +++ /dev/null @@ -1,397 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitGraph.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [Decomposition graph representation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kitGraph.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates a graph with the given number of leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Graph_t * Kit_GraphCreate( int nLeaves ) -{ - Kit_Graph_t * pGraph; - pGraph = ALLOC( Kit_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Kit_Graph_t) ); - pGraph->nLeaves = nLeaves; - pGraph->nSize = nLeaves; - pGraph->nCap = 2 * nLeaves + 50; - pGraph->pNodes = ALLOC( Kit_Node_t, pGraph->nCap ); - memset( pGraph->pNodes, 0, sizeof(Kit_Node_t) * pGraph->nSize ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates constant 0 graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Graph_t * Kit_GraphCreateConst0() -{ - Kit_Graph_t * pGraph; - pGraph = ALLOC( Kit_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Kit_Graph_t) ); - pGraph->fConst = 1; - pGraph->eRoot.fCompl = 1; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates constant 1 graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Graph_t * Kit_GraphCreateConst1() -{ - Kit_Graph_t * pGraph; - pGraph = ALLOC( Kit_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Kit_Graph_t) ); - pGraph->fConst = 1; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates the literal graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Graph_t * Kit_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ) -{ - Kit_Graph_t * pGraph; - assert( 0 <= iLeaf && iLeaf < nLeaves ); - pGraph = Kit_GraphCreate( nLeaves ); - pGraph->eRoot.Node = iLeaf; - pGraph->eRoot.fCompl = fCompl; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates a graph with the given number of leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_GraphFree( Kit_Graph_t * pGraph ) -{ - FREE( pGraph->pNodes ); - free( pGraph ); -} - -/**Function************************************************************* - - Synopsis [Appends a new node to the graph.] - - Description [This procedure is meant for internal use.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Node_t * Kit_GraphAppendNode( Kit_Graph_t * pGraph ) -{ - Kit_Node_t * pNode; - if ( pGraph->nSize == pGraph->nCap ) - { - pGraph->pNodes = REALLOC( Kit_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); - pGraph->nCap = 2 * pGraph->nCap; - } - pNode = pGraph->pNodes + pGraph->nSize++; - memset( pNode, 0, sizeof(Kit_Node_t) ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates an AND node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Edge_t Kit_GraphAddNodeAnd( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ) -{ - Kit_Node_t * pNode; - // get the new node - pNode = Kit_GraphAppendNode( pGraph ); - // set the inputs and other info - pNode->eEdge0 = eEdge0; - pNode->eEdge1 = eEdge1; - pNode->fCompl0 = eEdge0.fCompl; - pNode->fCompl1 = eEdge1.fCompl; - return Kit_EdgeCreate( pGraph->nSize - 1, 0 ); -} - -/**Function************************************************************* - - Synopsis [Creates an OR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Edge_t Kit_GraphAddNodeOr( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1 ) -{ - Kit_Node_t * pNode; - // get the new node - pNode = Kit_GraphAppendNode( pGraph ); - // set the inputs and other info - pNode->eEdge0 = eEdge0; - pNode->eEdge1 = eEdge1; - pNode->fCompl0 = eEdge0.fCompl; - pNode->fCompl1 = eEdge1.fCompl; - // make adjustments for the OR gate - pNode->fNodeOr = 1; - pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl; - pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl; - return Kit_EdgeCreate( pGraph->nSize - 1, 1 ); -} - -/**Function************************************************************* - - Synopsis [Creates an XOR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Edge_t Kit_GraphAddNodeXor( Kit_Graph_t * pGraph, Kit_Edge_t eEdge0, Kit_Edge_t eEdge1, int Type ) -{ - Kit_Edge_t eNode0, eNode1, eNode; - if ( Type == 0 ) - { - // derive the first AND - eEdge0.fCompl ^= 1; - eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - eEdge0.fCompl ^= 1; - // derive the second AND - eEdge1.fCompl ^= 1; - eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the final OR - eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - } - else - { - // derive the first AND - eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the second AND - eEdge0.fCompl ^= 1; - eEdge1.fCompl ^= 1; - eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the final OR - eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - eNode.fCompl ^= 1; - } - return eNode; -} - -/**Function************************************************************* - - Synopsis [Creates an XOR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Edge_t Kit_GraphAddNodeMux( Kit_Graph_t * pGraph, Kit_Edge_t eEdgeC, Kit_Edge_t eEdgeT, Kit_Edge_t eEdgeE, int Type ) -{ - Kit_Edge_t eNode0, eNode1, eNode; - if ( Type == 0 ) - { - // derive the first AND - eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); - // derive the second AND - eEdgeC.fCompl ^= 1; - eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); - // derive the final OR - eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - } - else - { - // complement the arguments - eEdgeT.fCompl ^= 1; - eEdgeE.fCompl ^= 1; - // derive the first AND - eNode0 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); - // derive the second AND - eEdgeC.fCompl ^= 1; - eNode1 = Kit_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); - // derive the final OR - eNode = Kit_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - eNode.fCompl ^= 1; - } - return eNode; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Kit_GraphToTruth( Kit_Graph_t * pGraph ) -{ - unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - unsigned uTruth, uTruth0, uTruth1; - Kit_Node_t * pNode; - int i; - - // sanity checks - assert( Kit_GraphLeaveNum(pGraph) >= 0 ); - assert( Kit_GraphLeaveNum(pGraph) <= pGraph->nSize ); - assert( Kit_GraphLeaveNum(pGraph) <= 5 ); - - // check for constant function - if ( Kit_GraphIsConst(pGraph) ) - return Kit_GraphIsComplement(pGraph)? 0 : ~((unsigned)0); - // check for a literal - if ( Kit_GraphIsVar(pGraph) ) - return Kit_GraphIsComplement(pGraph)? ~uTruths[Kit_GraphVarInt(pGraph)] : uTruths[Kit_GraphVarInt(pGraph)]; - - // assign the elementary variables - Kit_GraphForEachLeaf( pGraph, pNode, i ) - pNode->pFunc = (void *)uTruths[i]; - - // compute the function for each internal node - Kit_GraphForEachNode( pGraph, pNode, i ) - { - uTruth0 = (unsigned)Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; - uTruth1 = (unsigned)Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; - uTruth0 = pNode->eEdge0.fCompl? ~uTruth0 : uTruth0; - uTruth1 = pNode->eEdge1.fCompl? ~uTruth1 : uTruth1; - uTruth = uTruth0 & uTruth1; - pNode->pFunc = (void *)uTruth; - } - - // complement the result if necessary - return Kit_GraphIsComplement(pGraph)? ~uTruth : uTruth; -} - -/**Function************************************************************* - - Synopsis [Derives the factored form from the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Kit_Graph_t * Kit_TruthToGraph( unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) -{ - Kit_Graph_t * pGraph; - int RetValue; - // derive SOP - RetValue = Kit_TruthIsop( pTruth, nVars, vMemory, 1 ); // tried 1 and found not useful in "renode" - if ( RetValue == -1 ) - return NULL; - if ( Vec_IntSize(vMemory) > 128 ) - return NULL; -// printf( "Isop size = %d.\n", Vec_IntSize(vMemory) ); - assert( RetValue == 0 || RetValue == 1 ); - // derive factored form - pGraph = Kit_SopFactor( vMemory, RetValue, nVars, vMemory ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Derives the maximum depth from the leaf to the root.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_GraphLeafDepth_rec( Kit_Graph_t * pGraph, Kit_Node_t * pNode, Kit_Node_t * pLeaf ) -{ - int Depth0, Depth1, Depth; - if ( pNode == pLeaf ) - return 0; - if ( Kit_GraphNodeIsVar(pGraph, pNode) ) - return -100; - Depth0 = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeFanin0(pGraph, pNode), pLeaf ); - Depth1 = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeFanin1(pGraph, pNode), pLeaf ); - Depth = KIT_MAX( Depth0, Depth1 ); - Depth = (Depth == -100) ? -100 : Depth + 1; - return Depth; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/kit/kitHop.c b/src/aig/kit/kitHop.c deleted file mode 100644 index f914fbab..00000000 --- a/src/aig/kit/kitHop.c +++ /dev/null @@ -1,144 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitHop.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [Procedures involving AIGs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kitHop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" -#include "hop.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Kit_GraphToHopInternal( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) -{ - Kit_Node_t * pNode; - Hop_Obj_t * pAnd0, * pAnd1; - int i; - // check for constant function - if ( Kit_GraphIsConst(pGraph) ) - return Hop_NotCond( Hop_ManConst1(pMan), Kit_GraphIsComplement(pGraph) ); - // check for a literal - if ( Kit_GraphIsVar(pGraph) ) - return Hop_NotCond( Kit_GraphVar(pGraph)->pFunc, Kit_GraphIsComplement(pGraph) ); - // build the AIG nodes corresponding to the AND gates of the graph - Kit_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Hop_NotCond( Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Hop_NotCond( Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 ); - } - // complement the result if necessary - return Hop_NotCond( pNode->pFunc, Kit_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ) -{ - Kit_Node_t * pNode; - int i; - // collect the fanins - Kit_GraphForEachLeaf( pGraph, pNode, i ) - pNode->pFunc = Hop_IthVar( pMan, i ); - // perform strashing - return Kit_GraphToHopInternal( pMan, pGraph ); -} - -/**Function************************************************************* - - Synopsis [Strashed onen logic nodes using its truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ) -{ - Hop_Obj_t * pObj; - Kit_Graph_t * pGraph; - // transform truth table into the decomposition tree - if ( vMemory == NULL ) - { - vMemory = Vec_IntAlloc( 0 ); - pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); - Vec_IntFree( vMemory ); - } - else - pGraph = Kit_TruthToGraph( pTruth, nVars, vMemory ); - // derive the AIG for the decomposition tree - pObj = Kit_GraphToHop( pMan, pGraph ); - Kit_GraphFree( pGraph ); - return pObj; -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Kit_CoverToHop( Hop_Man_t * pMan, Vec_Int_t * vCover, int nVars, Vec_Int_t * vMemory ) -{ - Kit_Graph_t * pGraph; - Hop_Obj_t * pFunc; - // perform factoring - pGraph = Kit_SopFactor( vCover, 0, nVars, vMemory ); - // convert graph to the AIG - pFunc = Kit_GraphToHop( pMan, pGraph ); - Kit_GraphFree( pGraph ); - return pFunc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/kit/kitIsop.c b/src/aig/kit/kitIsop.c deleted file mode 100644 index 42fae2ea..00000000 --- a/src/aig/kit/kitIsop.c +++ /dev/null @@ -1,325 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitIsop.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [ISOP computation based on Morreale's algorithm.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kitIsop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// ISOP computation fails if intermediate memory usage exceed this limit -#define KIT_ISOP_MEM_LIMIT (1<<16) - -// static procedures to compute ISOP -static unsigned * Kit_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ); -static unsigned Kit_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes ISOP from TT.] - - Description [Returns the cover in vMemory. Uses the rest of array in vMemory - as an intermediate memory storage. Returns the cover with -1 cubes, if the - the computation exceeded the memory limit (KIT_ISOP_MEM_LIMIT words of - intermediate data).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthIsop( unsigned * puTruth, int nVars, Vec_Int_t * vMemory, int fTryBoth ) -{ - Kit_Sop_t cRes, * pcRes = &cRes; - Kit_Sop_t cRes2, * pcRes2 = &cRes2; - unsigned * pResult; - int RetValue = 0; - assert( nVars >= 0 && nVars < 16 ); - // if nVars < 5, make sure it does not depend on those vars -// for ( i = nVars; i < 5; i++ ) -// assert( !Kit_TruthVarInSupport(puTruth, 5, i) ); - // prepare memory manager - Vec_IntClear( vMemory ); - Vec_IntGrow( vMemory, KIT_ISOP_MEM_LIMIT ); - // compute ISOP for the direct polarity - pResult = Kit_TruthIsop_rec( puTruth, puTruth, nVars, pcRes, vMemory ); - if ( pcRes->nCubes == -1 ) - { - vMemory->nSize = -1; - return -1; - } - assert( Kit_TruthIsEqual( puTruth, pResult, nVars ) ); - if ( pcRes->nCubes == 0 || (pcRes->nCubes == 1 && pcRes->pCubes[0] == 0) ) - { - vMemory->pArray[0] = 0; - Vec_IntShrink( vMemory, pcRes->nCubes ); - return 0; - } - if ( fTryBoth ) - { - // compute ISOP for the complemented polarity - Kit_TruthNot( puTruth, puTruth, nVars ); - pResult = Kit_TruthIsop_rec( puTruth, puTruth, nVars, pcRes2, vMemory ); - if ( pcRes2->nCubes >= 0 ) - { - assert( Kit_TruthIsEqual( puTruth, pResult, nVars ) ); - if ( pcRes->nCubes > pcRes2->nCubes ) - { - RetValue = 1; - pcRes = pcRes2; - } - } - Kit_TruthNot( puTruth, puTruth, nVars ); - } -// printf( "%d ", vMemory->nSize ); - // move the cover representation to the beginning of the memory buffer - memmove( vMemory->pArray, pcRes->pCubes, pcRes->nCubes * sizeof(unsigned) ); - Vec_IntShrink( vMemory, pcRes->nCubes ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Computes ISOP 6 variables or more.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Kit_TruthIsop_rec( unsigned * puOn, unsigned * puOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ) -{ - Kit_Sop_t cRes0, cRes1, cRes2; - Kit_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2; - unsigned * puRes0, * puRes1, * puRes2; - unsigned * puOn0, * puOn1, * puOnDc0, * puOnDc1, * pTemp, * pTemp0, * pTemp1; - int i, k, Var, nWords, nWordsAll; -// assert( Kit_TruthIsImply( puOn, puOnDc, nVars ) ); - // allocate room for the resulting truth table - nWordsAll = Kit_TruthWordNum( nVars ); - pTemp = Vec_IntFetch( vStore, nWordsAll ); - if ( pTemp == NULL ) - { - pcRes->nCubes = -1; - return NULL; - } - // check for constants - if ( Kit_TruthIsConst0( puOn, nVars ) ) - { - pcRes->nCubes = 0; - pcRes->pCubes = NULL; - Kit_TruthClear( pTemp, nVars ); - return pTemp; - } - if ( Kit_TruthIsConst1( puOnDc, nVars ) ) - { - pcRes->nCubes = 1; - pcRes->pCubes = Vec_IntFetch( vStore, 1 ); - if ( pcRes->pCubes == NULL ) - { - pcRes->nCubes = -1; - return NULL; - } - pcRes->pCubes[0] = 0; - Kit_TruthFill( pTemp, nVars ); - return pTemp; - } - assert( nVars > 0 ); - // find the topmost var - for ( Var = nVars-1; Var >= 0; Var-- ) - if ( Kit_TruthVarInSupport( puOn, nVars, Var ) || - Kit_TruthVarInSupport( puOnDc, nVars, Var ) ) - break; - assert( Var >= 0 ); - // consider a simple case when one-word computation can be used - if ( Var < 5 ) - { - unsigned uRes = Kit_TruthIsop5_rec( puOn[0], puOnDc[0], Var+1, pcRes, vStore ); - for ( i = 0; i < nWordsAll; i++ ) - pTemp[i] = uRes; - return pTemp; - } - assert( Var >= 5 ); - nWords = Kit_TruthWordNum( Var ); - // cofactor - puOn0 = puOn; puOn1 = puOn + nWords; - puOnDc0 = puOnDc; puOnDc1 = puOnDc + nWords; - pTemp0 = pTemp; pTemp1 = pTemp + nWords; - // solve for cofactors - Kit_TruthSharp( pTemp0, puOn0, puOnDc1, Var ); - puRes0 = Kit_TruthIsop_rec( pTemp0, puOnDc0, Var, pcRes0, vStore ); - if ( pcRes0->nCubes == -1 ) - { - pcRes->nCubes = -1; - return NULL; - } - Kit_TruthSharp( pTemp1, puOn1, puOnDc0, Var ); - puRes1 = Kit_TruthIsop_rec( pTemp1, puOnDc1, Var, pcRes1, vStore ); - if ( pcRes1->nCubes == -1 ) - { - pcRes->nCubes = -1; - return NULL; - } - Kit_TruthSharp( pTemp0, puOn0, puRes0, Var ); - Kit_TruthSharp( pTemp1, puOn1, puRes1, Var ); - Kit_TruthOr( pTemp0, pTemp0, pTemp1, Var ); - Kit_TruthAnd( pTemp1, puOnDc0, puOnDc1, Var ); - puRes2 = Kit_TruthIsop_rec( pTemp0, pTemp1, Var, pcRes2, vStore ); - if ( pcRes2->nCubes == -1 ) - { - pcRes->nCubes = -1; - return NULL; - } - // create the resulting cover - pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes; - pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes ); - if ( pcRes->pCubes == NULL ) - { - pcRes->nCubes = -1; - return NULL; - } - k = 0; - for ( i = 0; i < pcRes0->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+0)); - for ( i = 0; i < pcRes1->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+1)); - for ( i = 0; i < pcRes2->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes2->pCubes[i]; - assert( k == pcRes->nCubes ); - // create the resulting truth table - Kit_TruthOr( pTemp0, puRes0, puRes2, Var ); - Kit_TruthOr( pTemp1, puRes1, puRes2, Var ); - // copy the table if needed - nWords <<= 1; - for ( i = 1; i < nWordsAll/nWords; i++ ) - for ( k = 0; k < nWords; k++ ) - pTemp[i*nWords + k] = pTemp[k]; - // verify in the end -// assert( Kit_TruthIsImply( puOn, pTemp, nVars ) ); -// assert( Kit_TruthIsImply( pTemp, puOnDc, nVars ) ); - return pTemp; -} - -/**Function************************************************************* - - Synopsis [Computes ISOP for 5 variables or less.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Kit_TruthIsop5_rec( unsigned uOn, unsigned uOnDc, int nVars, Kit_Sop_t * pcRes, Vec_Int_t * vStore ) -{ - unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - Kit_Sop_t cRes0, cRes1, cRes2; - Kit_Sop_t * pcRes0 = &cRes0, * pcRes1 = &cRes1, * pcRes2 = &cRes2; - unsigned uOn0, uOn1, uOnDc0, uOnDc1, uRes0, uRes1, uRes2; - int i, k, Var; - assert( nVars <= 5 ); - assert( (uOn & ~uOnDc) == 0 ); - if ( uOn == 0 ) - { - pcRes->nCubes = 0; - pcRes->pCubes = NULL; - return 0; - } - if ( uOnDc == 0xFFFFFFFF ) - { - pcRes->nCubes = 1; - pcRes->pCubes = Vec_IntFetch( vStore, 1 ); - if ( pcRes->pCubes == NULL ) - { - pcRes->nCubes = -1; - return 0; - } - pcRes->pCubes[0] = 0; - return 0xFFFFFFFF; - } - assert( nVars > 0 ); - // find the topmost var - for ( Var = nVars-1; Var >= 0; Var-- ) - if ( Kit_TruthVarInSupport( &uOn, 5, Var ) || - Kit_TruthVarInSupport( &uOnDc, 5, Var ) ) - break; - assert( Var >= 0 ); - // cofactor - uOn0 = uOn1 = uOn; - uOnDc0 = uOnDc1 = uOnDc; - Kit_TruthCofactor0( &uOn0, Var + 1, Var ); - Kit_TruthCofactor1( &uOn1, Var + 1, Var ); - Kit_TruthCofactor0( &uOnDc0, Var + 1, Var ); - Kit_TruthCofactor1( &uOnDc1, Var + 1, Var ); - // solve for cofactors - uRes0 = Kit_TruthIsop5_rec( uOn0 & ~uOnDc1, uOnDc0, Var, pcRes0, vStore ); - if ( pcRes0->nCubes == -1 ) - { - pcRes->nCubes = -1; - return 0; - } - uRes1 = Kit_TruthIsop5_rec( uOn1 & ~uOnDc0, uOnDc1, Var, pcRes1, vStore ); - if ( pcRes1->nCubes == -1 ) - { - pcRes->nCubes = -1; - return 0; - } - uRes2 = Kit_TruthIsop5_rec( (uOn0 & ~uRes0) | (uOn1 & ~uRes1), uOnDc0 & uOnDc1, Var, pcRes2, vStore ); - if ( pcRes2->nCubes == -1 ) - { - pcRes->nCubes = -1; - return 0; - } - // create the resulting cover - pcRes->nCubes = pcRes0->nCubes + pcRes1->nCubes + pcRes2->nCubes; - pcRes->pCubes = Vec_IntFetch( vStore, pcRes->nCubes ); - if ( pcRes->pCubes == NULL ) - { - pcRes->nCubes = -1; - return 0; - } - k = 0; - for ( i = 0; i < pcRes0->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes0->pCubes[i] | (1 << ((Var<<1)+0)); - for ( i = 0; i < pcRes1->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes1->pCubes[i] | (1 << ((Var<<1)+1)); - for ( i = 0; i < pcRes2->nCubes; i++ ) - pcRes->pCubes[k++] = pcRes2->pCubes[i]; - assert( k == pcRes->nCubes ); - // derive the final truth table - uRes2 |= (uRes0 & ~uMasks[Var]) | (uRes1 & uMasks[Var]); -// assert( (uOn & ~uRes2) == 0 ); -// assert( (uRes2 & ~uOnDc) == 0 ); - return uRes2; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/kit/kitSop.c b/src/aig/kit/kitSop.c deleted file mode 100644 index 3fa81351..00000000 --- a/src/aig/kit/kitSop.c +++ /dev/null @@ -1,570 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitSop.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [Procedures involving SOPs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kitSop.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates SOP from the cube array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_SopCreate( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nVars, Vec_Int_t * vMemory ) -{ - unsigned uCube; - int i; - // start the cover - cResult->nCubes = 0; - cResult->pCubes = Vec_IntFetch( vMemory, Vec_IntSize(vInput) ); - // add the cubes - Vec_IntForEachEntry( vInput, uCube, i ) - Kit_SopPushCube( cResult, uCube ); -} - -/**Function************************************************************* - - Synopsis [Creates SOP from the cube array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_SopCreateInverse( Kit_Sop_t * cResult, Vec_Int_t * vInput, int nLits, Vec_Int_t * vMemory ) -{ - unsigned uCube, uMask = 0; - int i, nCubes = Vec_IntSize(vInput); - // start the cover - cResult->nCubes = 0; - cResult->pCubes = Vec_IntFetch( vMemory, nCubes ); - // add the cubes -// Vec_IntForEachEntry( vInput, uCube, i ) - for ( i = 0; i < nCubes; i++ ) - { - uCube = Vec_IntEntry( vInput, i ); - uMask = ((uCube | (uCube >> 1)) & 0x55555555); - uMask |= (uMask << 1); - Kit_SopPushCube( cResult, uCube ^ uMask ); - } -} - -/**Function************************************************************* - - Synopsis [Duplicates SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_SopDup( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ) -{ - unsigned uCube; - int i; - // start the cover - cResult->nCubes = 0; - cResult->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) ); - // add the cubes - Kit_SopForEachCube( cSop, uCube, i ) - Kit_SopPushCube( cResult, uCube ); -} - -/**Function************************************************************* - - Synopsis [Derives the quotient of division by literal.] - - Description [Reduces the cover to be equal to the result of - division of the given cover by the literal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_SopDivideByLiteralQuo( Kit_Sop_t * cSop, int iLit ) -{ - unsigned uCube; - int i, k = 0; - Kit_SopForEachCube( cSop, uCube, i ) - { - if ( Kit_CubeHasLit(uCube, iLit) ) - Kit_SopWriteCube( cSop, Kit_CubeRemLit(uCube, iLit), k++ ); - } - Kit_SopShrink( cSop, k ); -} - - -/**Function************************************************************* - - Synopsis [Divides cover by one cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_SopDivideByCube( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ) -{ - unsigned uCube, uDiv; - int i; - // get the only cube - assert( Kit_SopCubeNum(cDiv) == 1 ); - uDiv = Kit_SopCube(cDiv, 0); - // allocate covers - vQuo->nCubes = 0; - vQuo->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) ); - vRem->nCubes = 0; - vRem->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) ); - // sort the cubes - Kit_SopForEachCube( cSop, uCube, i ) - { - if ( Kit_CubeContains( uCube, uDiv ) ) - Kit_SopPushCube( vQuo, Kit_CubeSharp(uCube, uDiv) ); - else - Kit_SopPushCube( vRem, uCube ); - } -} - -/**Function************************************************************* - - Synopsis [Divides cover by one cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_SopDivideInternal( Kit_Sop_t * cSop, Kit_Sop_t * cDiv, Kit_Sop_t * vQuo, Kit_Sop_t * vRem, Vec_Int_t * vMemory ) -{ - unsigned uCube, uDiv, uCube2, uDiv2, uQuo; - int i, i2, k, k2, nCubesRem; - assert( Kit_SopCubeNum(cSop) >= Kit_SopCubeNum(cDiv) ); - // consider special case - if ( Kit_SopCubeNum(cDiv) == 1 ) - { - Kit_SopDivideByCube( cSop, cDiv, vQuo, vRem, vMemory ); - return; - } - // allocate quotient - vQuo->nCubes = 0; - vQuo->pCubes = Vec_IntFetch( vMemory, Kit_SopCubeNum(cSop) / Kit_SopCubeNum(cDiv) ); - // for each cube of the cover - // it either belongs to the quotient or to the remainder - Kit_SopForEachCube( cSop, uCube, i ) - { - // skip taken cubes - if ( Kit_CubeIsMarked(uCube) ) - continue; - // find a matching cube in the divisor - Kit_SopForEachCube( cDiv, uDiv, k ) - if ( Kit_CubeContains( uCube, uDiv ) ) - break; - // the cube is not found - if ( k == Kit_SopCubeNum(cDiv) ) - continue; - // the quotient cube exists - uQuo = Kit_CubeSharp( uCube, uDiv ); - // find corresponding cubes for other cubes of the divisor - Kit_SopForEachCube( cDiv, uDiv2, k2 ) - { - if ( k2 == k ) - continue; - // find a matching cube - Kit_SopForEachCube( cSop, uCube2, i2 ) - { - // skip taken cubes - if ( Kit_CubeIsMarked(uCube2) ) - continue; - // check if the cube can be used - if ( Kit_CubeContains( uCube2, uDiv2 ) && uQuo == Kit_CubeSharp( uCube2, uDiv2 ) ) - break; - } - // the case when the cube is not found - if ( i2 == Kit_SopCubeNum(cSop) ) - break; - } - // we did not find some cubes - continue looking at other cubes - if ( k2 != Kit_SopCubeNum(cDiv) ) - continue; - // we found all cubes - add the quotient cube - Kit_SopPushCube( vQuo, uQuo ); - - // mark the first cube - Kit_SopWriteCube( cSop, Kit_CubeMark(uCube), i ); - // mark other cubes that have this quotient - Kit_SopForEachCube( cDiv, uDiv2, k2 ) - { - if ( k2 == k ) - continue; - // find a matching cube - Kit_SopForEachCube( cSop, uCube2, i2 ) - { - // skip taken cubes - if ( Kit_CubeIsMarked(uCube2) ) - continue; - // check if the cube can be used - if ( Kit_CubeContains( uCube2, uDiv2 ) && uQuo == Kit_CubeSharp( uCube2, uDiv2 ) ) - break; - } - assert( i2 < Kit_SopCubeNum(cSop) ); - // the cube is found, mark it - // (later we will add all unmarked cubes to the remainder) - Kit_SopWriteCube( cSop, Kit_CubeMark(uCube2), i2 ); - } - } - // determine the number of cubes in the remainder - nCubesRem = Kit_SopCubeNum(cSop) - Kit_SopCubeNum(vQuo) * Kit_SopCubeNum(cDiv); - // allocate remainder - vRem->nCubes = 0; - vRem->pCubes = Vec_IntFetch( vMemory, nCubesRem ); - // finally add the remaining unmarked cubes to the remainder - // and clean the marked cubes in the cover - Kit_SopForEachCube( cSop, uCube, i ) - { - if ( !Kit_CubeIsMarked(uCube) ) - { - Kit_SopPushCube( vRem, uCube ); - continue; - } - Kit_SopWriteCube( cSop, Kit_CubeUnmark(uCube), i ); - } - assert( nCubesRem == Kit_SopCubeNum(vRem) ); -} - -/**Function************************************************************* - - Synopsis [Returns the common cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Kit_SopCommonCube( Kit_Sop_t * cSop ) -{ - unsigned uMask, uCube; - int i; - uMask = ~(unsigned)0; - Kit_SopForEachCube( cSop, uCube, i ) - uMask &= uCube; - return uMask; -} - -/**Function************************************************************* - - Synopsis [Makes the cover cube-free.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_SopMakeCubeFree( Kit_Sop_t * cSop ) -{ - unsigned uMask, uCube; - int i; - uMask = Kit_SopCommonCube( cSop ); - if ( uMask == 0 ) - return; - // remove the common cube - Kit_SopForEachCube( cSop, uCube, i ) - Kit_SopWriteCube( cSop, Kit_CubeSharp(uCube, uMask), i ); -} - -/**Function************************************************************* - - Synopsis [Checks if the cover is cube-free.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_SopIsCubeFree( Kit_Sop_t * cSop ) -{ - return Kit_SopCommonCube( cSop ) == 0; -} - -/**Function************************************************************* - - Synopsis [Creates SOP composes of the common cube of the given SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_SopCommonCubeCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, Vec_Int_t * vMemory ) -{ - assert( Kit_SopCubeNum(cSop) > 0 ); - cResult->nCubes = 0; - cResult->pCubes = Vec_IntFetch( vMemory, 1 ); - Kit_SopPushCube( cResult, Kit_SopCommonCube(cSop) ); -} - - -/**Function************************************************************* - - Synopsis [Find any literal that occurs more than once.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_SopAnyLiteral( Kit_Sop_t * cSop, int nLits ) -{ - unsigned uCube; - int i, k, nLitsCur; - // go through each literal - for ( i = 0; i < nLits; i++ ) - { - // go through all the cubes - nLitsCur = 0; - Kit_SopForEachCube( cSop, uCube, k ) - if ( Kit_CubeHasLit(uCube, i) ) - nLitsCur++; - if ( nLitsCur > 1 ) - return i; - } - return -1; -} - -/**Function************************************************************* - - Synopsis [Find the least often occurring literal.] - - Description [Find the least often occurring literal among those - that occur more than once.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_SopWorstLiteral( Kit_Sop_t * cSop, int nLits ) -{ - unsigned uCube; - int i, k, iMin, nLitsMin, nLitsCur; - int fUseFirst = 1; - - // go through each literal - iMin = -1; - nLitsMin = 1000000; - for ( i = 0; i < nLits; i++ ) - { - // go through all the cubes - nLitsCur = 0; - Kit_SopForEachCube( cSop, uCube, k ) - if ( Kit_CubeHasLit(uCube, i) ) - nLitsCur++; - // skip the literal that does not occur or occurs once - if ( nLitsCur < 2 ) - continue; - // check if this is the best literal - if ( fUseFirst ) - { - if ( nLitsMin > nLitsCur ) - { - nLitsMin = nLitsCur; - iMin = i; - } - } - else - { - if ( nLitsMin >= nLitsCur ) - { - nLitsMin = nLitsCur; - iMin = i; - } - } - } - if ( nLitsMin < 1000000 ) - return iMin; - return -1; -} - -/**Function************************************************************* - - Synopsis [Find the least often occurring literal.] - - Description [Find the least often occurring literal among those - that occur more than once.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_SopBestLiteral( Kit_Sop_t * cSop, int nLits, unsigned uMask ) -{ - unsigned uCube; - int i, k, iMax, nLitsMax, nLitsCur; - int fUseFirst = 1; - - // go through each literal - iMax = -1; - nLitsMax = -1; - for ( i = 0; i < nLits; i++ ) - { - if ( !Kit_CubeHasLit(uMask, i) ) - continue; - // go through all the cubes - nLitsCur = 0; - Kit_SopForEachCube( cSop, uCube, k ) - if ( Kit_CubeHasLit(uCube, i) ) - nLitsCur++; - // skip the literal that does not occur or occurs once - if ( nLitsCur < 2 ) - continue; - // check if this is the best literal - if ( fUseFirst ) - { - if ( nLitsMax < nLitsCur ) - { - nLitsMax = nLitsCur; - iMax = i; - } - } - else - { - if ( nLitsMax <= nLitsCur ) - { - nLitsMax = nLitsCur; - iMax = i; - } - } - } - if ( nLitsMax >= 0 ) - return iMax; - return -1; -} - -/**Function************************************************************* - - Synopsis [Computes a level-zero kernel.] - - Description [Modifies the cover to contain one level-zero kernel.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_SopDivisorZeroKernel_rec( Kit_Sop_t * cSop, int nLits ) -{ - int iLit; - // find any literal that occurs at least two times - iLit = Kit_SopWorstLiteral( cSop, nLits ); - if ( iLit == -1 ) - return; - // derive the cube-free quotient - Kit_SopDivideByLiteralQuo( cSop, iLit ); // the same cover - Kit_SopMakeCubeFree( cSop ); // the same cover - // call recursively - Kit_SopDivisorZeroKernel_rec( cSop, nLits ); // the same cover -} - -/**Function************************************************************* - - Synopsis [Computes the quick divisor of the cover.] - - Description [Returns 0, if there is no divisor other than trivial.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_SopDivisor( Kit_Sop_t * cResult, Kit_Sop_t * cSop, int nLits, Vec_Int_t * vMemory ) -{ - if ( Kit_SopCubeNum(cSop) <= 1 ) - return 0; - if ( Kit_SopAnyLiteral( cSop, nLits ) == -1 ) - return 0; - // duplicate the cover - Kit_SopDup( cResult, cSop, vMemory ); - // perform the kerneling - Kit_SopDivisorZeroKernel_rec( cResult, nLits ); - assert( Kit_SopCubeNum(cResult) > 0 ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Create the one-literal cover with the best literal from cSop.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_SopBestLiteralCover( Kit_Sop_t * cResult, Kit_Sop_t * cSop, unsigned uCube, int nLits, Vec_Int_t * vMemory ) -{ - int iLitBest; - // get the best literal - iLitBest = Kit_SopBestLiteral( cSop, nLits, uCube ); - // start the cover - cResult->nCubes = 0; - cResult->pCubes = Vec_IntFetch( vMemory, 1 ); - // set the cube - Kit_SopPushCube( cResult, Kit_CubeSetLit(0, iLitBest) ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/kit/kitTruth.c b/src/aig/kit/kitTruth.c deleted file mode 100644 index 5360ad7f..00000000 --- a/src/aig/kit/kitTruth.c +++ /dev/null @@ -1,1729 +0,0 @@ -/**CFile**************************************************************** - - FileName [kitTruth.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [Procedures involving truth tables.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kitTruth.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static unsigned s_VarMasks[5][2] = { - { 0x33333333, 0xAAAAAAAA }, - { 0x55555555, 0xCCCCCCCC }, - { 0x0F0F0F0F, 0xF0F0F0F0 }, - { 0x00FF00FF, 0xFF00FF00 }, - { 0x0000FFFF, 0xFFFF0000 } -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Swaps two adjacent variables in the truth table.] - - Description [Swaps var number Start and var number Start+1 (0-based numbers). - The input truth table is pIn. The output truth table is pOut.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) -{ - static unsigned PMasks[4][3] = { - { 0x99999999, 0x22222222, 0x44444444 }, - { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 }, - { 0xF00FF00F, 0x00F000F0, 0x0F000F00 }, - { 0xFF0000FF, 0x0000FF00, 0x00FF0000 } - }; - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step, Shift; - - assert( iVar < nVars - 1 ); - if ( iVar < 4 ) - { - Shift = (1 << iVar); - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift); - } - else if ( iVar > 4 ) - { - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 4*Step ) - { - for ( i = 0; i < Step; i++ ) - pOut[i] = pIn[i]; - for ( i = 0; i < Step; i++ ) - pOut[Step+i] = pIn[2*Step+i]; - for ( i = 0; i < Step; i++ ) - pOut[2*Step+i] = pIn[Step+i]; - for ( i = 0; i < Step; i++ ) - pOut[3*Step+i] = pIn[3*Step+i]; - pIn += 4*Step; - pOut += 4*Step; - } - } - else // if ( iVar == 4 ) - { - for ( i = 0; i < nWords; i += 2 ) - { - pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); - pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); - } - } -} - -/**Function************************************************************* - - Synopsis [Swaps two adjacent variables in the truth table.] - - Description [Swaps var number Start and var number Start+1 (0-based numbers). - The input truth table is pIn. The output truth table is pOut.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int Start ) -{ - int nWords = (nVars <= 5)? 1 : (1 << (nVars-5)); - int i, k, Step; - - assert( Start < nVars - 1 ); - switch ( Start ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0x99999999) | ((pIn[i] & 0x22222222) << 1) | ((pIn[i] & 0x44444444) >> 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0xC3C3C3C3) | ((pIn[i] & 0x0C0C0C0C) << 2) | ((pIn[i] & 0x30303030) >> 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0xF00FF00F) | ((pIn[i] & 0x00F000F0) << 4) | ((pIn[i] & 0x0F000F00) >> 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0xFF0000FF) | ((pIn[i] & 0x0000FF00) << 8) | ((pIn[i] & 0x00FF0000) >> 8); - return; - case 4: - for ( i = 0; i < nWords; i += 2 ) - { - pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); - pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); - } - return; - default: - Step = (1 << (Start - 5)); - for ( k = 0; k < nWords; k += 4*Step ) - { - for ( i = 0; i < Step; i++ ) - pOut[i] = pIn[i]; - for ( i = 0; i < Step; i++ ) - pOut[Step+i] = pIn[2*Step+i]; - for ( i = 0; i < Step; i++ ) - pOut[2*Step+i] = pIn[Step+i]; - for ( i = 0; i < Step; i++ ) - pOut[3*Step+i] = pIn[3*Step+i]; - pIn += 4*Step; - pOut += 4*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Expands the truth table according to the phase.] - - Description [The input and output truth tables are in pIn/pOut. The current number - of variables is nVars. The total number of variables in nVarsAll. The last argument - (Phase) contains shows where the variables should go.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ) -{ - unsigned * pTemp; - int i, k, Var = nVars - 1, Counter = 0; - for ( i = nVarsAll - 1; i >= 0; i-- ) - if ( Phase & (1 << i) ) - { - for ( k = Var; k < i; k++ ) - { - Kit_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - Counter++; - } - Var--; - } - assert( Var == -1 ); - // swap if it was moved an even number of times - if ( fReturnIn ^ !(Counter & 1) ) - Kit_TruthCopy( pOut, pIn, nVarsAll ); -} - -/**Function************************************************************* - - Synopsis [Shrinks the truth table according to the phase.] - - Description [The input and output truth tables are in pIn/pOut. The current number - of variables is nVars. The total number of variables in nVarsAll. The last argument - (Phase) contains shows what variables should remain.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase, int fReturnIn ) -{ - unsigned * pTemp; - int i, k, Var = 0, Counter = 0; - for ( i = 0; i < nVarsAll; i++ ) - if ( Phase & (1 << i) ) - { - for ( k = i-1; k >= Var; k-- ) - { - Kit_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - Counter++; - } - Var++; - } - assert( Var == nVars ); - // swap if it was moved an even number of times - if ( fReturnIn ^ !(Counter & 1) ) - Kit_TruthCopy( pOut, pIn, nVarsAll ); -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if TT depends on the given variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) ) - return 1; - return 0; - case 1: - for ( i = 0; i < nWords; i++ ) - if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) ) - return 1; - return 0; - case 2: - for ( i = 0; i < nWords; i++ ) - if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) ) - return 1; - return 0; - case 3: - for ( i = 0; i < nWords; i++ ) - if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) ) - return 1; - return 0; - case 4: - for ( i = 0; i < nWords; i++ ) - if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) ) - return 1; - return 0; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - if ( pTruth[i] != pTruth[Step+i] ) - return 1; - pTruth += 2*Step; - } - return 0; - } -} - -/**Function************************************************************* - - Synopsis [Returns the number of support vars.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthSupportSize( unsigned * pTruth, int nVars ) -{ - int i, Counter = 0; - for ( i = 0; i < nVars; i++ ) - Counter += Kit_TruthVarInSupport( pTruth, nVars, i ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns support of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Kit_TruthSupport( unsigned * pTruth, int nVars ) -{ - int i, Support = 0; - for ( i = 0; i < nVars; i++ ) - if ( Kit_TruthVarInSupport( pTruth, nVars, i ) ) - Support |= (1 << i); - return Support; -} - - - -/**Function************************************************************* - - Synopsis [Computes negative cofactor of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0x55555555) | ((pTruth[i] & 0x55555555) << 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0x33333333) | ((pTruth[i] & 0x33333333) << 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0x0F0F0F0F) | ((pTruth[i] & 0x0F0F0F0F) << 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0x00FF00FF) | ((pTruth[i] & 0x00FF00FF) << 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0x0000FFFF) | ((pTruth[i] & 0x0000FFFF) << 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - pTruth[Step+i] = pTruth[i]; - pTruth += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Computes positive cofactor of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0xAAAAAAAA) | ((pTruth[i] & 0xAAAAAAAA) >> 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0xCCCCCCCC) | ((pTruth[i] & 0xCCCCCCCC) >> 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0xF0F0F0F0) | ((pTruth[i] & 0xF0F0F0F0) >> 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0xFF00FF00) | ((pTruth[i] & 0xFF00FF00) >> 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0xFFFF0000) | ((pTruth[i] & 0xFFFF0000) >> 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - pTruth[i] = pTruth[Step+i]; - pTruth += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Computes positive cofactor of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthCofactor0New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0x55555555) | ((pIn[i] & 0x55555555) << 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0x33333333) | ((pIn[i] & 0x33333333) << 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0x0F0F0F0F) | ((pIn[i] & 0x0F0F0F0F) << 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0x00FF00FF) | ((pIn[i] & 0x00FF00FF) << 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i] & 0x0000FFFF) << 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - pOut[i] = pOut[Step+i] = pIn[i]; - pIn += 2*Step; - pOut += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Computes positive cofactor of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthCofactor1New( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0xAAAAAAAA) | ((pIn[i] & 0xAAAAAAAA) >> 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0xCCCCCCCC) | ((pIn[i] & 0xCCCCCCCC) >> 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0xF0F0F0F0) | ((pIn[i] & 0xF0F0F0F0) >> 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0xFF00FF00) | ((pIn[i] & 0xFF00FF00) >> 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - pOut[i] = pOut[Step+i] = pIn[Step+i]; - pIn += 2*Step; - pOut += 2*Step; - } - return; - } -} - - -/**Function************************************************************* - - Synopsis [Existentially quantifies the variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthExist( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pTruth[i] |= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pTruth[i] |= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pTruth[i] |= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pTruth[i] |= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pTruth[i] |= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - pTruth[i] |= pTruth[Step+i]; - pTruth[Step+i] = pTruth[i]; - } - pTruth += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Existentially quantifies the variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthExistNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] | ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] | ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] | ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] | ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] | ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - pRes[i] = pTruth[i] | pTruth[Step+i]; - pRes[Step+i] = pRes[i]; - } - pRes += 2*Step; - pTruth += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Existantially quantifies the set of variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthExistSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ) -{ - int v; - Kit_TruthCopy( pRes, pTruth, nVars ); - for ( v = 0; v < nVars; v++ ) - if ( uMask & (1 << v) ) - Kit_TruthExist( pRes, nVars, v ); -} - -/**Function************************************************************* - - Synopsis [Unversally quantifies the variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthForall( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pTruth[i] &= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pTruth[i] &= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pTruth[i] &= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pTruth[i] &= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pTruth[i] &= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - pTruth[i] &= pTruth[Step+i]; - pTruth[Step+i] = pTruth[i]; - } - pTruth += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Universally quantifies the variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthForallNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] & (((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1)); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] & (((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2)); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] & (((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4)); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] & (((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8)); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] & (((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16)); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - pRes[i] = pTruth[i] & pTruth[Step+i]; - pRes[Step+i] = pRes[i]; - } - pRes += 2*Step; - pTruth += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Universally quantifies the variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthUniqueNew( unsigned * pRes, unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1)); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2)); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4)); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8)); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pRes[i] = pTruth[i] ^ (((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16)); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - pRes[i] = pTruth[i] ^ pTruth[Step+i]; - pRes[Step+i] = pRes[i]; - } - pRes += 2*Step; - pTruth += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Universally quantifies the set of variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthForallSet( unsigned * pRes, unsigned * pTruth, int nVars, unsigned uMask ) -{ - int v; - Kit_TruthCopy( pRes, pTruth, nVars ); - for ( v = 0; v < nVars; v++ ) - if ( uMask & (1 << v) ) - Kit_TruthForall( pRes, nVars, v ); -} - - -/**Function************************************************************* - - Synopsis [Multiplexes two functions with the given variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthMuxVar( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - pOut[i] = pCof0[i]; - pOut[Step+i] = pCof1[Step+i]; - } - pOut += 2*Step; - pCof0 += 2*Step; - pCof1 += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Multiplexes two functions with the given variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthMuxVarPhase( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar, int fCompl0 ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - - if ( fCompl0 == 0 ) - { - Kit_TruthMuxVar( pOut, pCof0, pCof1, nVars, iVar ); - return; - } - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (~pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (~pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (~pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (~pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (~pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - pOut[i] = ~pCof0[i]; - pOut[Step+i] = pCof1[Step+i]; - } - pOut += 2*Step; - pCof0 += 2*Step; - pCof1 += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Checks symmetry of two variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) -{ - static unsigned uTemp0[16], uTemp1[16]; - assert( nVars <= 9 ); - // compute Cof01 - Kit_TruthCopy( uTemp0, pTruth, nVars ); - Kit_TruthCofactor0( uTemp0, nVars, iVar0 ); - Kit_TruthCofactor1( uTemp0, nVars, iVar1 ); - // compute Cof10 - Kit_TruthCopy( uTemp1, pTruth, nVars ); - Kit_TruthCofactor1( uTemp1, nVars, iVar0 ); - Kit_TruthCofactor0( uTemp1, nVars, iVar1 ); - // compare - return Kit_TruthIsEqual( uTemp0, uTemp1, nVars ); -} - -/**Function************************************************************* - - Synopsis [Checks antisymmetry of two variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) -{ - static unsigned uTemp0[16], uTemp1[16]; - assert( nVars <= 9 ); - // compute Cof00 - Kit_TruthCopy( uTemp0, pTruth, nVars ); - Kit_TruthCofactor0( uTemp0, nVars, iVar0 ); - Kit_TruthCofactor0( uTemp0, nVars, iVar1 ); - // compute Cof11 - Kit_TruthCopy( uTemp1, pTruth, nVars ); - Kit_TruthCofactor1( uTemp1, nVars, iVar0 ); - Kit_TruthCofactor1( uTemp1, nVars, iVar1 ); - // compare - return Kit_TruthIsEqual( uTemp0, uTemp1, nVars ); -} - -/**Function************************************************************* - - Synopsis [Changes phase of the function w.r.t. one variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Step; - unsigned Temp; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ((pTruth[i] & 0x55555555) << 1) | ((pTruth[i] & 0xAAAAAAAA) >> 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ((pTruth[i] & 0x33333333) << 2) | ((pTruth[i] & 0xCCCCCCCC) >> 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ((pTruth[i] & 0x0F0F0F0F) << 4) | ((pTruth[i] & 0xF0F0F0F0) >> 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ((pTruth[i] & 0x00FF00FF) << 8) | ((pTruth[i] & 0xFF00FF00) >> 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ((pTruth[i] & 0x0000FFFF) << 16) | ((pTruth[i] & 0xFFFF0000) >> 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - Temp = pTruth[i]; - pTruth[i] = pTruth[Step+i]; - pTruth[Step+i] = Temp; - } - pTruth += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Computes minimum overlap in supports of cofactors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ) -{ - static unsigned uCofactor[16]; - int i, ValueCur, ValueMin, VarMin; - unsigned uSupp0, uSupp1; - int nVars0, nVars1; - assert( nVars <= 9 ); - ValueMin = 32; - VarMin = -1; - for ( i = 0; i < nVars; i++ ) - { - // get negative cofactor - Kit_TruthCopy( uCofactor, pTruth, nVars ); - Kit_TruthCofactor0( uCofactor, nVars, i ); - uSupp0 = Kit_TruthSupport( uCofactor, nVars ); - nVars0 = Kit_WordCountOnes( uSupp0 ); -//Kit_PrintBinary( stdout, &uSupp0, 8 ); printf( "\n" ); - // get positive cofactor - Kit_TruthCopy( uCofactor, pTruth, nVars ); - Kit_TruthCofactor1( uCofactor, nVars, i ); - uSupp1 = Kit_TruthSupport( uCofactor, nVars ); - nVars1 = Kit_WordCountOnes( uSupp1 ); -//Kit_PrintBinary( stdout, &uSupp1, 8 ); printf( "\n" ); - // get the number of common vars - ValueCur = Kit_WordCountOnes( uSupp0 & uSupp1 ); - if ( ValueMin > ValueCur && nVars0 <= 5 && nVars1 <= 5 ) - { - ValueMin = ValueCur; - VarMin = i; - } - if ( ValueMin == 0 ) - break; - } - if ( pVarMin ) - *pVarMin = VarMin; - return ValueMin; -} - - -/**Function************************************************************* - - Synopsis [Find the best cofactoring variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthBestCofVar( unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 ) -{ - int i, iBestVar, nSuppSizeCur0, nSuppSizeCur1, nSuppSizeCur, nSuppSizeMin; - if ( Kit_TruthIsConst0(pTruth, nVars) || Kit_TruthIsConst1(pTruth, nVars) ) - return -1; - // iterate through variables - iBestVar = -1; - nSuppSizeMin = KIT_INFINITY; - for ( i = 0; i < nVars; i++ ) - { - // cofactor the functiona and get support sizes - Kit_TruthCofactor0New( pCof0, pTruth, nVars, i ); - Kit_TruthCofactor1New( pCof1, pTruth, nVars, i ); - nSuppSizeCur0 = Kit_TruthSupportSize( pCof0, nVars ); - nSuppSizeCur1 = Kit_TruthSupportSize( pCof1, nVars ); - nSuppSizeCur = nSuppSizeCur0 + nSuppSizeCur1; - // compare this variable with other variables - if ( nSuppSizeMin > nSuppSizeCur ) - { - nSuppSizeMin = nSuppSizeCur; - iBestVar = i; - } - } - assert( iBestVar != -1 ); - // cofactor w.r.t. this variable - Kit_TruthCofactor0New( pCof0, pTruth, nVars, iBestVar ); - Kit_TruthCofactor1New( pCof1, pTruth, nVars, iBestVar ); - return iBestVar; -} - - -/**Function************************************************************* - - Synopsis [Counts the number of 1's in each cofactor.] - - Description [The resulting numbers are stored in the array of shorts, - whose length is 2*nVars. The number of 1's is counted in a different - space than the original function. For example, if the function depends - on k variables, the cofactors are assumed to depend on k-1 variables.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ) -{ - int nWords = Kit_TruthWordNum( nVars ); - int i, k, Counter; - memset( pStore, 0, sizeof(short) * 2 * nVars ); - if ( nVars <= 5 ) - { - if ( nVars > 0 ) - { - pStore[2*0+0] = Kit_WordCountOnes( pTruth[0] & 0x55555555 ); - pStore[2*0+1] = Kit_WordCountOnes( pTruth[0] & 0xAAAAAAAA ); - } - if ( nVars > 1 ) - { - pStore[2*1+0] = Kit_WordCountOnes( pTruth[0] & 0x33333333 ); - pStore[2*1+1] = Kit_WordCountOnes( pTruth[0] & 0xCCCCCCCC ); - } - if ( nVars > 2 ) - { - pStore[2*2+0] = Kit_WordCountOnes( pTruth[0] & 0x0F0F0F0F ); - pStore[2*2+1] = Kit_WordCountOnes( pTruth[0] & 0xF0F0F0F0 ); - } - if ( nVars > 3 ) - { - pStore[2*3+0] = Kit_WordCountOnes( pTruth[0] & 0x00FF00FF ); - pStore[2*3+1] = Kit_WordCountOnes( pTruth[0] & 0xFF00FF00 ); - } - if ( nVars > 4 ) - { - pStore[2*4+0] = Kit_WordCountOnes( pTruth[0] & 0x0000FFFF ); - pStore[2*4+1] = Kit_WordCountOnes( pTruth[0] & 0xFFFF0000 ); - } - return; - } - // nVars >= 6 - // count 1's for all other variables - for ( k = 0; k < nWords; k++ ) - { - Counter = Kit_WordCountOnes( pTruth[k] ); - for ( i = 5; i < nVars; i++ ) - if ( k & (1 << (i-5)) ) - pStore[2*i+1] += Counter; - else - pStore[2*i+0] += Counter; - } - // count 1's for the first five variables - for ( k = 0; k < nWords/2; k++ ) - { - pStore[2*0+0] += Kit_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) ); - pStore[2*0+1] += Kit_WordCountOnes( (pTruth[0] & 0xAAAAAAAA) | ((pTruth[1] & 0xAAAAAAAA) >> 1) ); - pStore[2*1+0] += Kit_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) ); - pStore[2*1+1] += Kit_WordCountOnes( (pTruth[0] & 0xCCCCCCCC) | ((pTruth[1] & 0xCCCCCCCC) >> 2) ); - pStore[2*2+0] += Kit_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) ); - pStore[2*2+1] += Kit_WordCountOnes( (pTruth[0] & 0xF0F0F0F0) | ((pTruth[1] & 0xF0F0F0F0) >> 4) ); - pStore[2*3+0] += Kit_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) ); - pStore[2*3+1] += Kit_WordCountOnes( (pTruth[0] & 0xFF00FF00) | ((pTruth[1] & 0xFF00FF00) >> 8) ); - pStore[2*4+0] += Kit_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) ); - pStore[2*4+1] += Kit_WordCountOnes( (pTruth[0] & 0xFFFF0000) | ((pTruth[1] & 0xFFFF0000) >> 16) ); - pTruth += 2; - } -} - -/**Function************************************************************* - - Synopsis [Counts the number of 1's in each cofactor.] - - Description [Verifies the above procedure.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthCountOnesInCofsSlow( unsigned * pTruth, int nVars, short * pStore, unsigned * pAux ) -{ - int i; - for ( i = 0; i < nVars; i++ ) - { - Kit_TruthCofactor0New( pAux, pTruth, nVars, i ); - pStore[2*i+0] = Kit_TruthCountOnes( pAux, nVars ) / 2; - Kit_TruthCofactor1New( pAux, pTruth, nVars, i ); - pStore[2*i+1] = Kit_TruthCountOnes( pAux, nVars ) / 2; - } -} - -/**Function************************************************************* - - Synopsis [Canonicize the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Kit_TruthHash( unsigned * pIn, int nWords ) -{ - // The 1,024 smallest prime numbers used to compute the hash value - // http://www.math.utah.edu/~alfeld/math/primelist.html - static int HashPrimes[1024] = { 2, 3, 5, - 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, - 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, - 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, - 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, - 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, - 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, - 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, - 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, - 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, - 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, - 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, - 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, - 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, - 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, - 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, - 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, - 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, - 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, - 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, - 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, - 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, - 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, - 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, - 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, - 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, - 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, - 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, - 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, - 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, - 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, - 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, - 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, - 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, - 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, - 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, - 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, - 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, - 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, - 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, - 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, - 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, - 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, - 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, - 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, - 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, - 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, - 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, - 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, - 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, - 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, - 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, - 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, - 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, - 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, - 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, - 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, - 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, - 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, - 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, - 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, - 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, - 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, - 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, - 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, - 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, - 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, - 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, - 8147, 8161 }; - int i; - unsigned uHashKey; - assert( nWords <= 1024 ); - uHashKey = 0; - for ( i = 0; i < nWords; i++ ) - uHashKey ^= HashPrimes[i] * pIn[i]; - return uHashKey; -} - - -/**Function************************************************************* - - Synopsis [Canonicize the truth table.] - - Description [Returns the phase. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Kit_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ) -{ -// short pStore2[32]; - unsigned * pIn = pInOut, * pOut = pAux, * pTemp; - int nWords = Kit_TruthWordNum( nVars ); - int i, Temp, fChange, Counter;//, nOnes;//, k, j, w, Limit; - unsigned uCanonPhase; - - // canonicize output - uCanonPhase = 0; -/* - nOnes = Kit_TruthCountOnes(pIn, nVars); - if ( (nOnes > nWords * 16) )//|| ((nOnes == nWords * 16) && (pIn[0] & 1)) ) - { - uCanonPhase |= (1 << nVars); - Kit_TruthNot( pIn, pIn, nVars ); - } -*/ - // collect the minterm counts - Kit_TruthCountOnesInCofs( pIn, nVars, pStore ); -// Kit_TruthCountOnesInCofsSlow( pIn, nVars, pStore2, pAux ); -// for ( i = 0; i < 2*nVars; i++ ) -// { -// assert( pStore[i] == pStore2[i] ); -// } - - // canonicize phase - for ( i = 0; i < nVars; i++ ) - { - if ( pStore[2*i+0] >= pStore[2*i+1] ) - continue; - uCanonPhase |= (1 << i); - Temp = pStore[2*i+0]; - pStore[2*i+0] = pStore[2*i+1]; - pStore[2*i+1] = Temp; - Kit_TruthChangePhase( pIn, nVars, i ); - } - -// Kit_PrintHexadecimal( stdout, pIn, nVars ); -// printf( "\n" ); - - // permute - Counter = 0; - do { - fChange = 0; - for ( i = 0; i < nVars-1; i++ ) - { - if ( pStore[2*i] >= pStore[2*(i+1)] ) - continue; - Counter++; - fChange = 1; - - Temp = pCanonPerm[i]; - pCanonPerm[i] = pCanonPerm[i+1]; - pCanonPerm[i+1] = Temp; - - Temp = pStore[2*i]; - pStore[2*i] = pStore[2*(i+1)]; - pStore[2*(i+1)] = Temp; - - Temp = pStore[2*i+1]; - pStore[2*i+1] = pStore[2*(i+1)+1]; - pStore[2*(i+1)+1] = Temp; - - // if the polarity of variables is different, swap them - if ( ((uCanonPhase & (1 << i)) > 0) != ((uCanonPhase & (1 << (i+1))) > 0) ) - { - uCanonPhase ^= (1 << i); - uCanonPhase ^= (1 << (i+1)); - } - - Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - } - } while ( fChange ); - -/* - Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " ); - for ( i = 0; i < nVars; i++ ) - printf( "%d=%d/%d ", pCanonPerm[i], pStore[2*i], pStore[2*i+1] ); - printf( " C = %d\n", Counter ); - Extra_PrintHexadecimal( stdout, pIn, nVars ); - printf( "\n" ); -*/ - -/* - // process symmetric variable groups - uSymms = 0; - for ( i = 0; i < nVars-1; i++ ) - { - if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric - continue; - if ( pStore[2*i] != pStore[2*i+1] ) - continue; - if ( Kit_TruthVarsSymm( pIn, nVars, i, i+1 ) ) - continue; - if ( Kit_TruthVarsAntiSymm( pIn, nVars, i, i+1 ) ) - Kit_TruthChangePhase( pIn, nVars, i+1 ); - } -*/ - -/* - // process symmetric variable groups - uSymms = 0; - for ( i = 0; i < nVars-1; i++ ) - { - if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric - continue; - // i and i+1 can be symmetric - // find the end of this group - for ( k = i+1; k < nVars; k++ ) - if ( pStore[2*i] != pStore[2*k] ) - break; - Limit = k; - assert( i < Limit-1 ); - // go through the variables in this group - for ( j = i + 1; j < Limit; j++ ) - { - // check symmetry - if ( Kit_TruthVarsSymm( pIn, nVars, i, j ) ) - { - uSymms |= (1 << j); - continue; - } - // they are phase-unknown - if ( pStore[2*i] == pStore[2*i+1] ) - { - if ( Kit_TruthVarsAntiSymm( pIn, nVars, i, j ) ) - { - Kit_TruthChangePhase( pIn, nVars, j ); - uCanonPhase ^= (1 << j); - uSymms |= (1 << j); - continue; - } - } - - // they are not symmetric - move j as far as it goes in the group - for ( k = j; k < Limit-1; k++ ) - { - Counter++; - - Temp = pCanonPerm[k]; - pCanonPerm[k] = pCanonPerm[k+1]; - pCanonPerm[k+1] = Temp; - - assert( pStore[2*k] == pStore[2*(k+1)] ); - Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, k ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - } - Limit--; - j--; - } - i = Limit - 1; - } -*/ - - // swap if it was moved an even number of times - if ( Counter & 1 ) - Kit_TruthCopy( pOut, pIn, nVars ); - return uCanonPhase; -} - - -/**Function************************************************************* - - Synopsis [Fast counting minterms in the cofactors of a function.] - - Description [Returns the total number of minterms in the function. - The resulting array (pRes) contains the number of minterms in 0-cofactor - w.r.t. each variables. The additional array (pBytes) is used for internal - storage. It should have the size equal to the number of truth table bytes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Kit_TruthCountMinterms( unsigned * pTruth, int nVars, int * pRes, int * pBytes ) -{ - // the number of 1s if every byte as well as in the 0-cofactors w.r.t. three variables - static unsigned Table[256] = { - 0x00000000, 0x01010101, 0x01010001, 0x02020102, 0x01000101, 0x02010202, 0x02010102, 0x03020203, - 0x01000001, 0x02010102, 0x02010002, 0x03020103, 0x02000102, 0x03010203, 0x03010103, 0x04020204, - 0x00010101, 0x01020202, 0x01020102, 0x02030203, 0x01010202, 0x02020303, 0x02020203, 0x03030304, - 0x01010102, 0x02020203, 0x02020103, 0x03030204, 0x02010203, 0x03020304, 0x03020204, 0x04030305, - 0x00010001, 0x01020102, 0x01020002, 0x02030103, 0x01010102, 0x02020203, 0x02020103, 0x03030204, - 0x01010002, 0x02020103, 0x02020003, 0x03030104, 0x02010103, 0x03020204, 0x03020104, 0x04030205, - 0x00020102, 0x01030203, 0x01030103, 0x02040204, 0x01020203, 0x02030304, 0x02030204, 0x03040305, - 0x01020103, 0x02030204, 0x02030104, 0x03040205, 0x02020204, 0x03030305, 0x03030205, 0x04040306, - 0x00000101, 0x01010202, 0x01010102, 0x02020203, 0x01000202, 0x02010303, 0x02010203, 0x03020304, - 0x01000102, 0x02010203, 0x02010103, 0x03020204, 0x02000203, 0x03010304, 0x03010204, 0x04020305, - 0x00010202, 0x01020303, 0x01020203, 0x02030304, 0x01010303, 0x02020404, 0x02020304, 0x03030405, - 0x01010203, 0x02020304, 0x02020204, 0x03030305, 0x02010304, 0x03020405, 0x03020305, 0x04030406, - 0x00010102, 0x01020203, 0x01020103, 0x02030204, 0x01010203, 0x02020304, 0x02020204, 0x03030305, - 0x01010103, 0x02020204, 0x02020104, 0x03030205, 0x02010204, 0x03020305, 0x03020205, 0x04030306, - 0x00020203, 0x01030304, 0x01030204, 0x02040305, 0x01020304, 0x02030405, 0x02030305, 0x03040406, - 0x01020204, 0x02030305, 0x02030205, 0x03040306, 0x02020305, 0x03030406, 0x03030306, 0x04040407, - 0x00000001, 0x01010102, 0x01010002, 0x02020103, 0x01000102, 0x02010203, 0x02010103, 0x03020204, - 0x01000002, 0x02010103, 0x02010003, 0x03020104, 0x02000103, 0x03010204, 0x03010104, 0x04020205, - 0x00010102, 0x01020203, 0x01020103, 0x02030204, 0x01010203, 0x02020304, 0x02020204, 0x03030305, - 0x01010103, 0x02020204, 0x02020104, 0x03030205, 0x02010204, 0x03020305, 0x03020205, 0x04030306, - 0x00010002, 0x01020103, 0x01020003, 0x02030104, 0x01010103, 0x02020204, 0x02020104, 0x03030205, - 0x01010003, 0x02020104, 0x02020004, 0x03030105, 0x02010104, 0x03020205, 0x03020105, 0x04030206, - 0x00020103, 0x01030204, 0x01030104, 0x02040205, 0x01020204, 0x02030305, 0x02030205, 0x03040306, - 0x01020104, 0x02030205, 0x02030105, 0x03040206, 0x02020205, 0x03030306, 0x03030206, 0x04040307, - 0x00000102, 0x01010203, 0x01010103, 0x02020204, 0x01000203, 0x02010304, 0x02010204, 0x03020305, - 0x01000103, 0x02010204, 0x02010104, 0x03020205, 0x02000204, 0x03010305, 0x03010205, 0x04020306, - 0x00010203, 0x01020304, 0x01020204, 0x02030305, 0x01010304, 0x02020405, 0x02020305, 0x03030406, - 0x01010204, 0x02020305, 0x02020205, 0x03030306, 0x02010305, 0x03020406, 0x03020306, 0x04030407, - 0x00010103, 0x01020204, 0x01020104, 0x02030205, 0x01010204, 0x02020305, 0x02020205, 0x03030306, - 0x01010104, 0x02020205, 0x02020105, 0x03030206, 0x02010205, 0x03020306, 0x03020206, 0x04030307, - 0x00020204, 0x01030305, 0x01030205, 0x02040306, 0x01020305, 0x02030406, 0x02030306, 0x03040407, - 0x01020205, 0x02030306, 0x02030206, 0x03040307, 0x02020306, 0x03030407, 0x03030307, 0x04040408 - }; - unsigned uSum; - unsigned char * pTruthC, * pLimit; - int i, iVar, Step, nWords, nBytes, nTotal; - - assert( nVars <= 20 ); - - // clear storage - memset( pRes, 0, sizeof(int) * nVars ); - - // count the number of one's in 0-cofactors of the first three variables - nTotal = uSum = 0; - nWords = Kit_TruthWordNum( nVars ); - nBytes = nWords * 4; - pTruthC = (unsigned char *)pTruth; - pLimit = pTruthC + nBytes; - for ( ; pTruthC < pLimit; pTruthC++ ) - { - uSum += Table[*pTruthC]; - *pBytes++ = (Table[*pTruthC] & 0xff); - if ( (uSum & 0xff) > 246 ) - { - nTotal += (uSum & 0xff); - pRes[0] += ((uSum >> 8) & 0xff); - pRes[2] += ((uSum >> 16) & 0xff); - pRes[3] += ((uSum >> 24) & 0xff); - uSum = 0; - } - } - if ( uSum ) - { - nTotal += (uSum & 0xff); - pRes[0] += ((uSum >> 8) & 0xff); - pRes[1] += ((uSum >> 16) & 0xff); - pRes[2] += ((uSum >> 24) & 0xff); - } - - // count all other variables - for ( iVar = 3, Step = 1; Step < nBytes; Step *= 2, iVar++ ) - for ( i = 0; i < nBytes; i += Step + Step ) - { - pRes[iVar] += pBytes[i]; - pBytes[i] += pBytes[i+Step]; - } - assert( pBytes[0] == nTotal ); - assert( iVar == nVars ); - return nTotal; -} - -/**Function************************************************************* - - Synopsis [Prints the hex unsigned into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ) -{ - int nDigits, Digit, k; - // write the number into the file - nDigits = (1 << nVars) / 4; - for ( k = nDigits - 1; k >= 0; k-- ) - { - Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15); - if ( Digit < 10 ) - fprintf( pFile, "%d", Digit ); - else - fprintf( pFile, "%c", 'a' + Digit-10 ); - } -// fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Fast counting minterms for the functions.] - - Description [Returns 0 if the function is a constant.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Kit_TruthCountMintermsPrecomp() -{ - int bit_count[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 - }; - unsigned i, uWord; - for ( i = 0; i < 256; i++ ) - { - if ( i % 8 == 0 ) - printf( "\n" ); - uWord = bit_count[i]; - uWord |= (bit_count[i & 0x55] << 8); - uWord |= (bit_count[i & 0x33] << 16); - uWord |= (bit_count[i & 0x0f] << 24); - printf( "0x" ); - Kit_PrintHexadecimal( stdout, &uWord, 5 ); - printf( ", " ); - } -} - -/**Function************************************************************* - - Synopsis [Dumps truth table into a file.] - - Description [Generates script file for reading into ABC.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Kit_TruthDumpToFile( unsigned * pTruth, int nVars, int nFile ) -{ - static char pFileName[100]; - FILE * pFile; - sprintf( pFileName, "tt\\s%04d", nFile ); - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "rt " ); - Extra_PrintHexadecimal( pFile, pTruth, nVars ); - fprintf( pFile, "; bdd; sop; ps\n" ); - fclose( pFile ); - return pFileName; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/kit/kit_.c b/src/aig/kit/kit_.c deleted file mode 100644 index 5c68ee3c..00000000 --- a/src/aig/kit/kit_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [kit_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Computation kit.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Dec 6, 2006.] - - Revision [$Id: kit_.c,v 1.00 2006/12/06 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/kit/module.make b/src/aig/kit/module.make deleted file mode 100644 index ea62381b..00000000 --- a/src/aig/kit/module.make +++ /dev/null @@ -1,10 +0,0 @@ -SRC += src/aig/kit/kitAig.c \ - src/aig/kit/kitBdd.c \ - src/aig/kit/kitCloud.c src/aig/kit/cloud.c \ - src/aig/kit/kitDsd.c \ - src/aig/kit/kitFactor.c \ - src/aig/kit/kitGraph.c \ - src/aig/kit/kitHop.c \ - src/aig/kit/kitIsop.c \ - src/aig/kit/kitSop.c \ - src/aig/kit/kitTruth.c diff --git a/src/aig/mem/mem.c b/src/aig/mem/mem.c deleted file mode 100644 index f5bfbfd8..00000000 --- a/src/aig/mem/mem.c +++ /dev/null @@ -1,604 +0,0 @@ -/**CFile**************************************************************** - - FileName [esopMem.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Cover manipulation package.] - - Synopsis [Memory managers.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: esopMem.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include -#include -#include -#include "mem.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Mem_Fixed_t_ -{ - // information about individual entries - int nEntrySize; // the size of one entry - int nEntriesAlloc; // the total number of entries allocated - int nEntriesUsed; // the number of entries in use - int nEntriesMax; // the max number of entries in use - char * pEntriesFree; // the linked list of free entries - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -struct Mem_Flex_t_ -{ - // information about individual entries - int nEntriesUsed; // the number of entries allocated - char * pCurrent; // the current pointer to free memory - char * pEnd; // the first entry outside the free memory - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -struct Mem_Step_t_ -{ - int nMems; // the number of fixed memory managers employed - Mem_Fixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc - int nMapSize; // the size of the memory array - Mem_Fixed_t ** pMap; // maps the number of bytes into its memory manager -}; - -#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#define REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates memory pieces of fixed size.] - - Description [The size of the chunk is computed as the minimum of - 1024 entries and 64K. Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mem_Fixed_t * Mem_FixedStart( int nEntrySize ) -{ - Mem_Fixed_t * p; - - p = ALLOC( Mem_Fixed_t, 1 ); - memset( p, 0, sizeof(Mem_Fixed_t) ); - - p->nEntrySize = nEntrySize; - p->nEntriesAlloc = 0; - p->nEntriesUsed = 0; - p->pEntriesFree = NULL; - - if ( nEntrySize * (1 << 10) < (1<<16) ) - p->nChunkSize = (1 << 10); - else - p->nChunkSize = (1<<16) / nEntrySize; - if ( p->nChunkSize < 8 ) - p->nChunkSize = 8; - - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", - p->nEntrySize, p->nChunkSize, p->nChunks ); - printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", - p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Mem_FixedEntryFetch( Mem_Fixed_t * p ) -{ - char * pTemp; - int i; - - // check if there are still free entries - if ( p->nEntriesUsed == p->nEntriesAlloc ) - { // need to allocate more entries - assert( p->pEntriesFree == NULL ); - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); - p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; - // transform these entries into a linked list - pTemp = p->pEntriesFree; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pEntriesFree; - // add to the number of entries allocated - p->nEntriesAlloc += p->nChunkSize; - } - // incrememt the counter of used entries - p->nEntriesUsed++; - if ( p->nEntriesMax < p->nEntriesUsed ) - p->nEntriesMax = p->nEntriesUsed; - // return the first entry in the free entry list - pTemp = p->pEntriesFree; - p->pEntriesFree = *((char **)pTemp); - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry ) -{ - // decrement the counter of used entries - p->nEntriesUsed--; - // add the entry to the linked list of free entries - *((char **)pEntry) = p->pEntriesFree; - p->pEntriesFree = pEntry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Relocates all the memory except the first chunk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_FixedRestart( Mem_Fixed_t * p ) -{ - int i; - char * pTemp; - - // deallocate all chunks except the first one - for ( i = 1; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - p->nChunks = 1; - // transform these entries into a linked list - pTemp = p->pChunks[0]; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // set the free entry list - p->pEntriesFree = p->pChunks[0]; - // set the correct statistics - p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; - p->nMemoryUsed = 0; - p->nEntriesAlloc = p->nChunkSize; - p->nEntriesUsed = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mem_FixedReadMemUsage( Mem_Fixed_t * p ) -{ - return p->nMemoryAlloc; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p ) -{ - return p->nEntriesMax; -} - - - -/**Function************************************************************* - - Synopsis [Allocates entries of flexible size.] - - Description [Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mem_Flex_t * Mem_FlexStart() -{ - Mem_Flex_t * p; - - p = ALLOC( Mem_Flex_t, 1 ); - memset( p, 0, sizeof(Mem_Flex_t) ); - - p->nEntriesUsed = 0; - p->pCurrent = NULL; - p->pEnd = NULL; - - p->nChunkSize = (1 << 14); - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_FlexStop( Mem_Flex_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", - p->nChunkSize, p->nChunks ); - printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", - p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes ) -{ - char * pTemp; - // check if there are still free entries - if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) - { // need to allocate more entries - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - if ( nBytes > p->nChunkSize ) - { - // resize the chunk size if more memory is requested than it can give - // (ideally, this should never happen) - p->nChunkSize = 2 * nBytes; - } - p->pCurrent = ALLOC( char, p->nChunkSize ); - p->pEnd = p->pCurrent + p->nChunkSize; - p->nMemoryAlloc += p->nChunkSize; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pCurrent; - } - assert( p->pCurrent + nBytes <= p->pEnd ); - // increment the counter of used entries - p->nEntriesUsed++; - // keep track of the memory used - p->nMemoryUsed += nBytes; - // return the next entry - pTemp = p->pCurrent; - p->pCurrent += nBytes; - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Relocates all the memory except the first chunk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_FlexRestart( Mem_Flex_t * p ) -{ - int i; - if ( p->nChunks == 0 ) - return; - // deallocate all chunks except the first one - for ( i = 1; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - p->nChunks = 1; - p->nMemoryAlloc = p->nChunkSize; - // transform these entries into a linked list - p->pCurrent = p->pChunks[0]; - p->pEnd = p->pCurrent + p->nChunkSize; - p->nEntriesUsed = 0; - p->nMemoryUsed = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mem_FlexReadMemUsage( Mem_Flex_t * p ) -{ - return p->nMemoryUsed; -} - - - - - -/**Function************************************************************* - - Synopsis [Starts the hierarchical memory manager.] - - Description [This manager can allocate entries of any size. - Iternally they are mapped into the entries with the number of bytes - equal to the power of 2. The smallest entry size is 8 bytes. The - next one is 16 bytes etc. So, if the user requests 6 bytes, he gets - 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. - The input parameters "nSteps" says how many fixed memory managers - are employed internally. Calling this procedure with nSteps equal - to 10 results in 10 hierarchically arranged internal memory managers, - which can allocate up to 4096 (1Kb) entries. Requests for larger - entries are handed over to malloc() and then free()ed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mem_Step_t * Mem_StepStart( int nSteps ) -{ - Mem_Step_t * p; - int i, k; - p = ALLOC( Mem_Step_t, 1 ); - memset( p, 0, sizeof(Mem_Step_t) ); - p->nMems = nSteps; - // start the fixed memory managers - p->pMems = ALLOC( Mem_Fixed_t *, p->nMems ); - for ( i = 0; i < p->nMems; i++ ) - p->pMems[i] = Mem_FixedStart( (8<nMapSize = (4<nMems); - p->pMap = ALLOC( Mem_Fixed_t *, p->nMapSize+1 ); - p->pMap[0] = NULL; - for ( k = 1; k <= 4; k++ ) - p->pMap[k] = p->pMems[0]; - for ( i = 0; i < p->nMems; i++ ) - for ( k = (4<pMap[k] = p->pMems[i]; -//for ( i = 1; i < 100; i ++ ) -//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_StepStop( Mem_Step_t * p, int fVerbose ) -{ - int i; - for ( i = 0; i < p->nMems; i++ ) - Mem_FixedStop( p->pMems[i], fVerbose ); -// if ( p->pLargeChunks ) -// { -// for ( i = 0; i < p->nLargeChunks; i++ ) -// free( p->pLargeChunks[i] ); -// free( p->pLargeChunks ); -// } - free( p->pMems ); - free( p->pMap ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Creates the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes ) -{ - if ( nBytes == 0 ) - return NULL; - if ( nBytes > p->nMapSize ) - { -// printf( "Allocating %d bytes.\n", nBytes ); -/* - if ( p->nLargeChunks == p->nLargeChunksAlloc ) - { - if ( p->nLargeChunksAlloc == 0 ) - p->nLargeChunksAlloc = 5; - p->nLargeChunksAlloc *= 2; - p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); - } - p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes ); - return p->pLargeChunks[ p->nLargeChunks - 1 ]; -*/ - return ALLOC( char, nBytes ); - } - return Mem_FixedEntryFetch( p->pMap[nBytes] ); -} - - -/**Function************************************************************* - - Synopsis [Recycles the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes ) -{ - if ( nBytes == 0 ) - return; - if ( nBytes > p->nMapSize ) - { - free( pEntry ); - return; - } - Mem_FixedEntryRecycle( p->pMap[nBytes], pEntry ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mem_StepReadMemUsage( Mem_Step_t * p ) -{ - int i, nMemTotal = 0; - for ( i = 0; i < p->nMems; i++ ) - nMemTotal += p->pMems[i]->nMemoryAlloc; - return nMemTotal; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/aig/mem/mem.h b/src/aig/mem/mem.h deleted file mode 100644 index d43e5fc3..00000000 --- a/src/aig/mem/mem.h +++ /dev/null @@ -1,72 +0,0 @@ -/**CFile**************************************************************** - - FileName [mem.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Memory management.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mem.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __MEM_H__ -#define __MEM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Mem_Fixed_t_ Mem_Fixed_t; -typedef struct Mem_Flex_t_ Mem_Flex_t; -typedef struct Mem_Step_t_ Mem_Step_t; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== mem.c ===========================================================*/ -// fixed-size-block memory manager -extern Mem_Fixed_t * Mem_FixedStart( int nEntrySize ); -extern void Mem_FixedStop( Mem_Fixed_t * p, int fVerbose ); -extern char * Mem_FixedEntryFetch( Mem_Fixed_t * p ); -extern void Mem_FixedEntryRecycle( Mem_Fixed_t * p, char * pEntry ); -extern void Mem_FixedRestart( Mem_Fixed_t * p ); -extern int Mem_FixedReadMemUsage( Mem_Fixed_t * p ); -extern int Mem_FixedReadMaxEntriesUsed( Mem_Fixed_t * p ); -// flexible-size-block memory manager -extern Mem_Flex_t * Mem_FlexStart(); -extern void Mem_FlexStop( Mem_Flex_t * p, int fVerbose ); -extern char * Mem_FlexEntryFetch( Mem_Flex_t * p, int nBytes ); -extern void Mem_FlexRestart( Mem_Flex_t * p ); -extern int Mem_FlexReadMemUsage( Mem_Flex_t * p ); -// hierarchical memory manager -extern Mem_Step_t * Mem_StepStart( int nSteps ); -extern void Mem_StepStop( Mem_Step_t * p, int fVerbose ); -extern char * Mem_StepEntryFetch( Mem_Step_t * p, int nBytes ); -extern void Mem_StepEntryRecycle( Mem_Step_t * p, char * pEntry, int nBytes ); -extern int Mem_StepReadMemUsage( Mem_Step_t * p ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/mem/module.make b/src/aig/mem/module.make deleted file mode 100644 index ae6fcbe4..00000000 --- a/src/aig/mem/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += src/aig/mem/mem.c diff --git a/src/aig/rwt/module.make b/src/aig/rwt/module.make deleted file mode 100644 index 439d576f..00000000 --- a/src/aig/rwt/module.make +++ /dev/null @@ -1,3 +0,0 @@ -SRC += src/aig/rwt/rwtDec.c \ - src/aig/rwt/rwtMan.c \ - src/aig/rwt/rwtUtil.c diff --git a/src/aig/rwt/rwt.h b/src/aig/rwt/rwt.h deleted file mode 100644 index 9199ff2a..00000000 --- a/src/aig/rwt/rwt.h +++ /dev/null @@ -1,156 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __RWT_H__ -#define __RWT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "mem.h" -#include "extra.h" -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -#define RWT_LIMIT 1048576/4 // ((1 << 20) -#define RWT_MIN(a,b) (((a) < (b))? (a) : (b)) -#define RWT_MAX(a,b) (((a) > (b))? (a) : (b)) - -typedef struct Rwt_Man_t_ Rwt_Man_t; -typedef struct Rwt_Node_t_ Rwt_Node_t; - -struct Rwt_Man_t_ -{ - // internal lookups - int nFuncs; // number of four var functions - unsigned short * puCanons; // canonical forms - char * pPhases; // canonical phases - char * pPerms; // canonical permutations - unsigned char * pMap; // mapping of functions into class numbers - unsigned short * pMapInv; // mapping of classes into functions - char * pPractical; // practical NPN classes - char ** pPerms4; // four-var permutations - // node space - Vec_Ptr_t * vForest; // all the nodes - Rwt_Node_t ** pTable; // the hash table of nodes by their canonical form - Vec_Vec_t * vClasses; // the nodes of the equivalence classes - Mem_Fixed_t * pMmNode; // memory for nodes and cuts - // statistical variables - int nTravIds; // the counter of traversal IDs - int nConsidered; // the number of nodes considered - int nAdded; // the number of nodes added to lists - int nClasses; // the number of NN classes - // the result of resynthesis - int fCompl; // indicates if the output of FF should be complemented - void * pCut; // the decomposition tree (temporary) - void * pGraph; // the decomposition tree (temporary) - char * pPerm; // permutation used for the best cut - Vec_Ptr_t * vFanins; // the fanins array (temporary) - Vec_Ptr_t * vFaninsCur; // the fanins array (temporary) - Vec_Int_t * vLevNums; // the array of levels (temporary) - Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary) - // node statistics - int nNodesConsidered; - int nNodesRewritten; - int nNodesGained; - int nScores[222]; - int nCutsGood; - int nCutsBad; - int nSubgraphs; - // runtime statistics - int timeStart; - int timeTruth; - int timeCut; - int timeRes; - int timeEval; - int timeMffc; - int timeUpdate; - int timeTotal; -}; - -struct Rwt_Node_t_ // 24 bytes -{ - int Id; // ID - int TravId; // traversal ID - unsigned uTruth : 16; // truth table - unsigned Volume : 8; // volume - unsigned Level : 6; // level - unsigned fUsed : 1; // mark - unsigned fExor : 1; // mark - Rwt_Node_t * p0; // first child - Rwt_Node_t * p1; // second child - Rwt_Node_t * pNext; // next in the table -}; - -// manipulation of complemented attributes -static inline int Rwt_IsComplement( Rwt_Node_t * p ) { return (int)(((unsigned long)p) & 01); } -static inline Rwt_Node_t * Rwt_Regular( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned long)(p) & ~01); } -static inline Rwt_Node_t * Rwt_Not( Rwt_Node_t * p ) { return (Rwt_Node_t *)((unsigned long)(p) ^ 01); } -static inline Rwt_Node_t * Rwt_NotCond( Rwt_Node_t * p, int c ) { return (Rwt_Node_t *)((unsigned long)(p) ^ (c)); } - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== rwrDec.c ========================================================*/ -extern void Rwt_ManPreprocess( Rwt_Man_t * p ); -/*=== rwrMan.c ========================================================*/ -extern Rwt_Man_t * Rwt_ManStart( int fPrecompute ); -extern void Rwt_ManStop( Rwt_Man_t * p ); -extern void Rwt_ManPrintStats( Rwt_Man_t * p ); -extern void Rwt_ManPrintStatsFile( Rwt_Man_t * p ); -extern void * Rwt_ManReadDecs( Rwt_Man_t * p ); -extern Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p ); -extern int Rwt_ManReadCompl( Rwt_Man_t * p ); -extern void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time ); -extern void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time ); -extern void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time ); -/*=== rwrUtil.c ========================================================*/ -extern void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose ); -extern char * Rwt_ManGetPractical( Rwt_Man_t * p ); -extern Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute ); -extern void Rwt_ManIncTravId( Rwt_Man_t * p ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/aig/rwt/rwtDec.c b/src/aig/rwt/rwtDec.c deleted file mode 100644 index 98019629..00000000 --- a/src/aig/rwt/rwtDec.c +++ /dev/null @@ -1,150 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwtDec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Evaluation and decomposition procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwtDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwt.h" -#include "deco.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode ); -static Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Preprocesses computed library of subgraphs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManPreprocess( Rwt_Man_t * p ) -{ - Dec_Graph_t * pGraph; - Rwt_Node_t * pNode; - int i, k; - // put the nodes into the structure - p->pMapInv = ALLOC( unsigned short, 222 ); - memset( p->pMapInv, 0, sizeof(unsigned short) * 222 ); - p->vClasses = Vec_VecStart( 222 ); - for ( i = 0; i < p->nFuncs; i++ ) - { - if ( p->pTable[i] == NULL ) - continue; - // consider all implementations of this function - for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext ) - { - assert( pNode->uTruth == p->pTable[i]->uTruth ); - assert( p->pMap[pNode->uTruth] >= 0 && p->pMap[pNode->uTruth] < 222 ); - Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode ); - p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth]; - } - } - // compute decomposition forms for each node and verify them - Vec_VecForEachEntry( p->vClasses, pNode, i, k ) - { - pGraph = Rwt_NodePreprocess( p, pNode ); - pNode->pNext = (Rwt_Node_t *)pGraph; -// assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) ); - } -} - -/**Function************************************************************* - - Synopsis [Preprocesses subgraphs rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Rwt_NodePreprocess( Rwt_Man_t * p, Rwt_Node_t * pNode ) -{ - Dec_Graph_t * pGraph; - Dec_Edge_t eRoot; - assert( !Rwt_IsComplement(pNode) ); - // consider constant - if ( pNode->uTruth == 0 ) - return Dec_GraphCreateConst0(); - // consider the case of elementary var - if ( pNode->uTruth == 0x00FF ) - return Dec_GraphCreateLeaf( 3, 4, 1 ); - // start the subgraphs - pGraph = Dec_GraphCreate( 4 ); - // collect the nodes - Rwt_ManIncTravId( p ); - eRoot = Rwt_TravCollect_rec( p, pNode, pGraph ); - Dec_GraphSetRoot( pGraph, eRoot ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Rwt_TravCollect_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, Dec_Graph_t * pGraph ) -{ - Dec_Edge_t eNode0, eNode1, eNode; - // elementary variable - if ( pNode->fUsed ) - return Dec_EdgeCreate( pNode->Id - 1, 0 ); - // previously visited node - if ( pNode->TravId == p->nTravIds ) - return Dec_IntToEdge( pNode->Volume ); - pNode->TravId = p->nTravIds; - // solve for children - eNode0 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p0), pGraph ); - if ( Rwt_IsComplement(pNode->p0) ) - eNode0.fCompl = !eNode0.fCompl; - eNode1 = Rwt_TravCollect_rec( p, Rwt_Regular(pNode->p1), pGraph ); - if ( Rwt_IsComplement(pNode->p1) ) - eNode1.fCompl = !eNode1.fCompl; - // create the decomposition node(s) - if ( pNode->fExor ) - eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 ); - else - eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); - // save the result - pNode->Volume = Dec_EdgeToInt( eNode ); - return eNode; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/rwt/rwtMan.c b/src/aig/rwt/rwtMan.c deleted file mode 100644 index 869043a4..00000000 --- a/src/aig/rwt/rwtMan.c +++ /dev/null @@ -1,358 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwtMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Rewriting manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwtMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwt.h" -#include "deco.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static unsigned short * s_puCanons = NULL; -static char * s_pPhases = NULL; -static char * s_pPerms = NULL; -static unsigned char * s_pMap = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts residual rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManGlobalStart() -{ - if ( s_puCanons == NULL ) - Extra_Truth4VarNPN( &s_puCanons, &s_pPhases, &s_pPerms, &s_pMap ); -} - -/**Function************************************************************* - - Synopsis [Starts residual rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManGlobalStop() -{ - FREE( s_puCanons ); - FREE( s_pPhases ); - FREE( s_pPerms ); - FREE( s_pMap ); -} - -/**Function************************************************************* - - Synopsis [Starts rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rwt_Man_t * Rwt_ManStart( int fPrecompute ) -{ - Rwt_Man_t * p; - int clk = clock(); -clk = clock(); - p = ALLOC( Rwt_Man_t, 1 ); - memset( p, 0, sizeof(Rwt_Man_t) ); - p->nFuncs = (1<<16); - // copy the global tables - Rwt_ManGlobalStart(); - p->puCanons = s_puCanons; - p->pPhases = s_pPhases; - p->pPerms = s_pPerms; - p->pMap = s_pMap; - // initialize practical NPN classes - p->pPractical = Rwt_ManGetPractical( p ); - // create the table - p->pTable = ALLOC( Rwt_Node_t *, p->nFuncs ); - memset( p->pTable, 0, sizeof(Rwt_Node_t *) * p->nFuncs ); - // create the elementary nodes - p->pMmNode = Mem_FixedStart( sizeof(Rwt_Node_t) ); - p->vForest = Vec_PtrAlloc( 100 ); - Rwt_ManAddVar( p, 0x0000, fPrecompute ); // constant 0 - Rwt_ManAddVar( p, 0xAAAA, fPrecompute ); // var A - Rwt_ManAddVar( p, 0xCCCC, fPrecompute ); // var B - Rwt_ManAddVar( p, 0xF0F0, fPrecompute ); // var C - Rwt_ManAddVar( p, 0xFF00, fPrecompute ); // var D - p->nClasses = 5; - // other stuff - p->nTravIds = 1; - p->pPerms4 = Extra_Permutations( 4 ); - p->vLevNums = Vec_IntAlloc( 50 ); - p->vFanins = Vec_PtrAlloc( 50 ); - p->vFaninsCur = Vec_PtrAlloc( 50 ); - p->vNodesTemp = Vec_PtrAlloc( 50 ); - if ( fPrecompute ) - { // precompute subgraphs -// Rwt_ManPrecompute( p ); -// Rwt_ManPrint( p ); -// Rwt_ManWriteToArray( p ); - } - else - { // load saved subgraphs - Rwt_ManLoadFromArray( p, 0 ); -// Rwt_ManPrint( p ); - Rwt_ManPreprocess( p ); - } -p->timeStart = clock() - clk; - return p; -} - -/**Function************************************************************* - - Synopsis [Stops rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManStop( Rwt_Man_t * p ) -{ - if ( p->vClasses ) - { - Rwt_Node_t * pNode; - int i, k; - Vec_VecForEachEntry( p->vClasses, pNode, i, k ) - Dec_GraphFree( (Dec_Graph_t *)pNode->pNext ); - } - if ( p->vClasses ) Vec_VecFree( p->vClasses ); - Vec_PtrFree( p->vNodesTemp ); - Vec_PtrFree( p->vForest ); - Vec_IntFree( p->vLevNums ); - Vec_PtrFree( p->vFanins ); - Vec_PtrFree( p->vFaninsCur ); - Mem_FixedStop( p->pMmNode, 0 ); - FREE( p->pMapInv ); - free( p->pTable ); - free( p->pPractical ); - free( p->pPerms4 ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManPrintStats( Rwt_Man_t * p ) -{ - int i, Counter = 0; - for ( i = 0; i < 222; i++ ) - Counter += (p->nScores[i] > 0); - - printf( "Rewriting statistics:\n" ); - printf( "Total cuts tries = %8d.\n", p->nCutsGood ); - printf( "Bad cuts found = %8d.\n", p->nCutsBad ); - printf( "Total subgraphs = %8d.\n", p->nSubgraphs ); - printf( "Used NPN classes = %8d.\n", Counter ); - printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); - printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten ); - printf( "Calculated gain = %8d.\n", p->nNodesGained ); - PRT( "Start ", p->timeStart ); - PRT( "Cuts ", p->timeCut ); - PRT( "Truth ", p->timeTruth ); - PRT( "Resynthesis ", p->timeRes ); - PRT( " Mffc ", p->timeMffc ); - PRT( " Eval ", p->timeEval ); - PRT( "Update ", p->timeUpdate ); - PRT( "TOTAL ", p->timeTotal ); - -/* - printf( "The scores are:\n" ); - for ( i = 0; i < 222; i++ ) - if ( p->nScores[i] > 0 ) - { - extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); - printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] ); - Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) ); - } - printf( "\n" ); -*/ -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManPrintStatsFile( Rwt_Man_t * p ) -{ - FILE * pTable; - pTable = fopen( "stats.txt", "a+" ); - fprintf( pTable, "%d ", p->nCutsGood ); - fprintf( pTable, "%d ", p->nSubgraphs ); - fprintf( pTable, "%d ", p->nNodesRewritten ); - fprintf( pTable, "%d", p->nNodesGained ); - fprintf( pTable, "\n" ); - fclose( pTable ); -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Rwt_ManReadDecs( Rwt_Man_t * p ) -{ - return p->pGraph; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Rwt_ManReadLeaves( Rwt_Man_t * p ) -{ - return p->vFanins; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwt_ManReadCompl( Rwt_Man_t * p ) -{ - return p->fCompl; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManAddTimeCuts( Rwt_Man_t * p, int Time ) -{ - p->timeCut += Time; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManAddTimeUpdate( Rwt_Man_t * p, int Time ) -{ - p->timeUpdate += Time; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManAddTimeTotal( Rwt_Man_t * p, int Time ) -{ - p->timeTotal += Time; -} - - -/**Function************************************************************* - - Synopsis [Precomputes AIG subgraphs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_Precompute() -{ - Rwt_Man_t * p; - p = Rwt_ManStart( 1 ); - Rwt_ManStop( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/aig/rwt/rwtUtil.c b/src/aig/rwt/rwtUtil.c deleted file mode 100644 index af3e1893..00000000 --- a/src/aig/rwt/rwtUtil.c +++ /dev/null @@ -1,665 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwtUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Various utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwtUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// precomputed data -#ifdef _WIN32 -unsigned short s_RwtPracticalClasses[]; -unsigned short s_RwtAigSubgraphs[]; -#else -static unsigned short s_RwtPracticalClasses[]; -static unsigned short s_RwtAigSubgraphs[]; -#endif - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Adds the node to the end of the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ListAddToTail( Rwt_Node_t ** ppList, Rwt_Node_t * pNode ) -{ - Rwt_Node_t * pTemp; - // find the last one - for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext ) - ppList = &pTemp->pNext; - // attach at the end - *ppList = pNode; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rwt_Node_t * Rwt_ManAddVar( Rwt_Man_t * p, unsigned uTruth, int fPrecompute ) -{ - Rwt_Node_t * pNew; - pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode ); - pNew->Id = p->vForest->nSize; - pNew->TravId = 0; - pNew->uTruth = uTruth; - pNew->Level = 0; - pNew->Volume = 0; - pNew->fUsed = 1; - pNew->fExor = 0; - pNew->p0 = NULL; - pNew->p1 = NULL; - pNew->pNext = NULL; - Vec_PtrPush( p->vForest, pNew ); - if ( fPrecompute ) - Rwt_ListAddToTail( p->pTable + uTruth, pNew ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rwt_Node_t * Rwt_ManAddNode( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1, int fExor, int Level, int Volume ) -{ - Rwt_Node_t * pNew; - unsigned uTruth; - // compute truth table, leve, volume - p->nConsidered++; - if ( fExor ) - uTruth = (p0->uTruth ^ p1->uTruth); - else - uTruth = (Rwt_IsComplement(p0)? ~Rwt_Regular(p0)->uTruth : Rwt_Regular(p0)->uTruth) & - (Rwt_IsComplement(p1)? ~Rwt_Regular(p1)->uTruth : Rwt_Regular(p1)->uTruth) & 0xFFFF; - // create the new node - pNew = (Rwt_Node_t *)Mem_FixedEntryFetch( p->pMmNode ); - pNew->Id = p->vForest->nSize; - pNew->TravId = 0; - pNew->uTruth = uTruth; - pNew->Level = Level; - pNew->Volume = Volume; - pNew->fUsed = 0; - pNew->fExor = fExor; - pNew->p0 = p0; - pNew->p1 = p1; - pNew->pNext = NULL; - Vec_PtrPush( p->vForest, pNew ); - // do not add if the node is not essential - if ( uTruth != p->puCanons[uTruth] ) - return pNew; - - // add to the list - p->nAdded++; - if ( p->pTable[uTruth] == NULL ) - p->nClasses++; - Rwt_ListAddToTail( p->pTable + uTruth, pNew ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_Trav_rec( Rwt_Man_t * p, Rwt_Node_t * pNode, int * pVolume ) -{ - if ( pNode->fUsed || pNode->TravId == p->nTravIds ) - return; - pNode->TravId = p->nTravIds; - (*pVolume)++; - if ( pNode->fExor ) - (*pVolume)++; - Rwt_Trav_rec( p, Rwt_Regular(pNode->p0), pVolume ); - Rwt_Trav_rec( p, Rwt_Regular(pNode->p1), pVolume ); -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManIncTravId( Rwt_Man_t * p ) -{ - Rwt_Node_t * pNode; - int i; - if ( p->nTravIds++ < 0x8FFFFFFF ) - return; - Vec_PtrForEachEntry( p->vForest, pNode, i ) - pNode->TravId = 0; - p->nTravIds = 1; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwt_ManNodeVolume( Rwt_Man_t * p, Rwt_Node_t * p0, Rwt_Node_t * p1 ) -{ - int Volume = 0; - Rwt_ManIncTravId( p ); - Rwt_Trav_rec( p, p0, &Volume ); - Rwt_Trav_rec( p, p1, &Volume ); - return Volume; -} - -/**Function************************************************************* - - Synopsis [Loads data.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_ManLoadFromArray( Rwt_Man_t * p, int fVerbose ) -{ - unsigned short * pArray = s_RwtAigSubgraphs; - Rwt_Node_t * p0, * p1; - unsigned Entry0, Entry1; - int Level, Volume, nEntries, fExor; - int i, clk = clock(); - - // reconstruct the forest - for ( i = 0; ; i++ ) - { - Entry0 = pArray[2*i + 0]; - Entry1 = pArray[2*i + 1]; - if ( Entry0 == 0 && Entry1 == 0 ) - break; - // get EXOR flag - fExor = (Entry0 & 1); - Entry0 >>= 1; - // get the nodes - p0 = p->vForest->pArray[Entry0 >> 1]; - p1 = p->vForest->pArray[Entry1 >> 1]; - // compute the level and volume of the new nodes - Level = 1 + RWT_MAX( p0->Level, p1->Level ); - Volume = 1 + Rwt_ManNodeVolume( p, p0, p1 ); - // set the complemented attributes - p0 = Rwt_NotCond( p0, (Entry0 & 1) ); - p1 = Rwt_NotCond( p1, (Entry1 & 1) ); - // add the node -// Rwt_ManTryNode( p, p0, p1, Level, Volume ); - Rwt_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor ); - } - nEntries = i - 1; - if ( fVerbose ) - { - printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded ); - printf( "The number of nodes loaded = %d. ", nEntries ); PRT( "Loading", clock() - clk ); - } -} - -/**Function************************************************************* - - Synopsis [Create practical classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Rwt_ManGetPractical( Rwt_Man_t * p ) -{ - char * pPractical; - int i; - pPractical = ALLOC( char, p->nFuncs ); - memset( pPractical, 0, sizeof(char) * p->nFuncs ); - pPractical[0] = 1; - for ( i = 1; ; i++ ) - { - if ( s_RwtPracticalClasses[i] == 0 ) - break; - pPractical[ s_RwtPracticalClasses[i] ] = 1; - } - return pPractical; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -// the following 135 practical NPN classes of 4-variable functions were computed -// by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks -static unsigned short s_RwtPracticalClasses[] = -{ - 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b, - 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff, - 0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c, - 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, - 0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab, - 0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe, - 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368, - 0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5, - 0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669, - 0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2, - 0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8, - 0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4, - 0x1ee1, 0x3cc3, 0x6996, 0x0000 -}; - -static unsigned short s_RwtAigSubgraphs[] = -{ - 0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002, - 0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002, - 0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004, - 0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002, - 0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004, - 0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006, - 0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007, - 0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009, - 0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007, - 0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005, - 0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006, - 0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008, - 0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006, - 0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008, - 0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006, - 0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004, - 0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009, - 0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e, - 0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005, - 0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f, - 0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009, - 0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e, - 0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005, - 0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008, - 0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013, - 0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008, - 0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012, - 0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003, - 0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009, - 0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013, - 0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002, - 0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d, - 0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c, - 0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007, - 0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012, - 0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002, - 0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008, - 0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f, - 0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019, - 0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002, - 0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008, - 0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011, - 0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017, - 0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d, - 0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009, - 0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019, - 0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024, - 0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004, - 0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b, - 0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021, - 0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024, - 0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009, - 0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024, - 0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004, - 0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d, - 0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020, - 0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024, - 0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027, - 0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f, - 0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d, - 0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024, - 0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006, - 0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015, - 0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f, - 0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002, - 0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016, - 0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025, - 0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b, - 0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a, - 0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003, - 0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f, - 0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018, - 0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b, - 0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003, - 0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006, - 0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019, - 0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022, - 0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f, - 0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004, - 0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f, - 0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017, - 0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f, - 0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002, - 0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011, - 0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037, - 0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010, - 0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b, - 0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002, - 0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005, - 0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d, - 0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011, - 0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012, - 0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039, - 0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005, - 0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011, - 0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017, - 0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b, - 0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009, - 0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037, - 0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010, - 0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030, - 0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009, - 0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d, - 0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008, - 0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010, - 0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030, - 0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044, - 0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011, - 0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043, - 0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017, - 0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a, - 0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f, - 0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f, - 0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023, - 0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007, - 0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033, - 0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b, - 0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037, - 0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d, - 0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067, - 0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038, - 0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d, - 0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006, - 0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025, - 0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014, - 0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f, - 0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008, - 0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d, - 0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058, - 0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008, - 0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d, - 0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059, - 0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b, - 0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b, - 0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019, - 0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043, - 0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061, - 0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007, - 0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004, - 0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045, - 0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d, - 0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009, - 0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044, - 0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044, - 0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097, - 0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f, - 0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048, - 0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a, - 0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009, - 0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044, - 0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a, - 0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029, - 0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a, - 0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013, - 0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5, - 0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f, - 0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095, - 0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009, - 0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f, - 0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013, - 0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095, - 0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030, - 0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6, - 0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e, - 0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061, - 0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc, - 0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044, - 0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a, - 0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008, - 0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8, - 0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095, - 0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004, - 0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029, - 0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068, - 0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c, - 0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029, - 0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c, - 0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013, - 0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067, - 0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf, - 0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d, - 0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003, - 0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f, - 0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099, - 0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf, - 0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f, - 0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176, - 0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3, - 0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b, - 0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f, - 0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008, - 0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095, - 0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b, - 0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec, - 0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3, - 0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009, - 0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009, - 0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a, - 0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030, - 0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009, - 0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033, - 0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e, - 0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158, - 0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a, - 0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d, - 0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168, - 0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e, - 0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133, - 0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b, - 0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f, - 0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da, - 0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d, - 0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef, - 0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181, - 0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027, - 0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a, - 0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f, - 0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181, - 0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205, - 0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033, - 0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225, - 0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0, - 0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1, - 0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d, - 0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006, - 0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a, - 0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b, - 0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033, - 0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231, - 0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4, - 0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e, - 0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec, - 0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e, - 0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3, - 0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a, - 0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef, - 0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175, - 0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0, - 0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f, - 0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3, - 0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e, - 0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086, - 0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5, - 0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e, - 0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181, - 0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0, - 0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095, - 0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b, - 0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276, - 0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4, - 0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006, - 0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3, - 0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d, - 0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103, - 0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234, - 0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d, - 0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106, - 0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8, - 0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044, - 0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0, - 0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a, - 0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6, - 0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238, - 0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e, - 0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067, - 0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020, - 0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021, - 0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183, - 0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268, - 0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc, - 0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213, - 0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023, - 0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b, - 0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da, - 0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287, - 0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce, - 0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf, - 0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338, - 0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328, - 0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003, - 0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330, - 0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282, - 0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a, - 0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9, - 0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247, - 0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d, - 0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce, - 0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0, - 0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004, - 0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315, - 0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d, - 0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd, - 0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb, - 0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f, - 0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173, - 0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029, - 0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3, - 0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053, - 0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030, - 0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021, - 0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2, - 0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9, - 0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285, - 0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b, - 0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a, - 0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315, - 0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f, - 0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c, - 0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e, - 0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089, - 0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021, - 0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354, - 0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f, - 0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095, - 0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3, - 0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e, - 0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009, - 0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009, - 0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b, - 0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381, - 0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008, - 0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb, - 0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5, - 0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027, - 0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030, - 0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb, - 0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a, - 0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009, - 0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027, - 0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d, - 0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271, - 0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f, - 0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009, - 0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009, - 0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f, - 0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9, - 0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235, - 0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d, - 0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085, - 0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3, - 0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043, - 0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7, - 0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f, - 0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059, - 0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d, - 0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009, - 0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b, - 0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061, - 0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9, - 0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027, - 0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019, - 0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1, - 0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b, - 0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7, - 0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb, - 0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d, - 0x0000,0x0000 -}; - - diff --git a/src/base/abc/abc.h b/src/base/abc/abc.h deleted file mode 100644 index 2e2b379b..00000000 --- a/src/base/abc/abc.h +++ /dev/null @@ -1,929 +0,0 @@ -/**CFile**************************************************************** - - FileName [abc.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abc.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __ABC_H__ -#define __ABC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include - -#include "cuddInt.h" -#include "hop.h" -#include "extra.h" -#include "vec.h" -#include "stmm.h" -#include "nm.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// network types -typedef enum { - ABC_NTK_NONE = 0, // 0: unknown - ABC_NTK_NETLIST, // 1: network with PIs/POs, latches, nodes, and nets - ABC_NTK_LOGIC, // 2: network with PIs/POs, latches, and nodes - ABC_NTK_STRASH, // 3: structurally hashed AIG (two input AND gates with c-attributes on edges) - ABC_NTK_OTHER // 4: unused -} Abc_NtkType_t; - -// network functionality -typedef enum { - ABC_FUNC_NONE = 0, // 0: unknown - ABC_FUNC_SOP, // 1: sum-of-products - ABC_FUNC_BDD, // 2: binary decision diagrams - ABC_FUNC_AIG, // 3: and-inverter graphs - ABC_FUNC_MAP, // 4: standard cell library - ABC_FUNC_BLIFMV, // 5: BLIF-MV node functions - ABC_FUNC_BLACKBOX, // 6: black box about which nothing is known - ABC_FUNC_OTHER // 7: unused -} Abc_NtkFunc_t; - -// Supported type/functionality combinations: -/*------------------------------------------| -| | SOP | BDD | AIG | Map | -|-----------|-------|-------|-------|-------| -| Netlist | x | | x | x | -|-----------|-------|-------|-------|-------| -| Logic | x | x | x | x | -|-----------|-------|-------|-------|-------| -| Strash | | | x | | ---------------------------------------------|*/ - -// object types -typedef enum { - ABC_OBJ_NONE = 0, // 0: unknown - ABC_OBJ_CONST1, // 1: constant 1 node (AIG only) - ABC_OBJ_PIO, // 2: inout terminal - ABC_OBJ_PI, // 3: primary input terminal - ABC_OBJ_PO, // 4: primary output terminal - ABC_OBJ_BI, // 5: box input terminal - ABC_OBJ_BO, // 6: box output terminal - ABC_OBJ_ASSERT, // 7: assertion terminal - ABC_OBJ_NET, // 8: net - ABC_OBJ_NODE, // 9: node - ABC_OBJ_LATCH, // 10: latch - ABC_OBJ_WHITEBOX, // 11: box with known contents - ABC_OBJ_BLACKBOX, // 12: box with unknown contents - ABC_OBJ_NUMBER // 13: unused -} Abc_ObjType_t; - -// latch initial values -typedef enum { - ABC_INIT_NONE = 0, // 0: unknown - ABC_INIT_ZERO, // 1: zero - ABC_INIT_ONE, // 2: one - ABC_INIT_DC, // 3: don't-care - ABC_INIT_OTHER // 4: unused -} Abc_InitType_t; - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//typedef int bool; -#ifndef __cplusplus -#ifndef bool -#define bool int -#endif -#endif - -#ifndef SINT64 -#define SINT64 - -#ifdef _WIN32 -typedef signed __int64 sint64; // compatible with MS VS 6.0 -#else -typedef long long sint64; -#endif - -#endif - -typedef struct Abc_Lib_t_ Abc_Lib_t; -typedef struct Abc_Ntk_t_ Abc_Ntk_t; -typedef struct Abc_Obj_t_ Abc_Obj_t; -typedef struct Abc_Aig_t_ Abc_Aig_t; -typedef struct Abc_ManTime_t_ Abc_ManTime_t; -typedef struct Abc_ManCut_t_ Abc_ManCut_t; -typedef struct Abc_Time_t_ Abc_Time_t; - -struct Abc_Time_t_ -{ - float Rise; - float Fall; - float Worst; -}; - -struct Abc_Obj_t_ // 12 words -{ - // high-level information - Abc_Ntk_t * pNtk; // the host network - int Id; // the object ID - int TravId; // the traversal ID (if changed, update Abc_NtkIncrementTravId) - // internal information - unsigned Type : 4; // the object type - unsigned fMarkA : 1; // the multipurpose mark - unsigned fMarkB : 1; // the multipurpose mark - unsigned fMarkC : 1; // the multipurpose mark - unsigned fPhase : 1; // the flag to mark the phase of equivalent node - unsigned fExor : 1; // marks AIG node that is a root of EXOR - unsigned fPersist: 1; // marks the persistant AIG node - unsigned fCompl0 : 1; // complemented attribute of the first fanin in the AIG - unsigned fCompl1 : 1; // complemented attribute of the second fanin in the AIG - unsigned Level : 20; // the level of the node - // connectivity - Vec_Int_t vFanins; // the array of fanins - Vec_Int_t vFanouts; // the array of fanouts - // miscellaneous - void * pData; // the network specific data (SOP, BDD, gate, equiv class, etc) - Abc_Obj_t * pNext; // the next pointer in the hash table - Abc_Obj_t * pCopy; // the copy of this object - Hop_Obj_t * pEquiv; // pointer to the HAIG node -}; - -struct Abc_Ntk_t_ -{ - // general information - Abc_NtkType_t ntkType; // type of the network - Abc_NtkFunc_t ntkFunc; // functionality of the network - char * pName; // the network name - char * pSpec; // the name of the spec file if present - Nm_Man_t * pManName; // name manager (stores names of objects) - // components of the network - Vec_Ptr_t * vObjs; // the array of all objects (net, nodes, latches, etc) - Vec_Ptr_t * vPis; // the array of primary inputs - Vec_Ptr_t * vPos; // the array of primary outputs - Vec_Ptr_t * vCis; // the array of combinational inputs (PIs, latches) - Vec_Ptr_t * vCos; // the array of combinational outputs (POs, asserts, latches) - Vec_Ptr_t * vPios; // the array of PIOs - Vec_Ptr_t * vAsserts; // the array of assertions - Vec_Ptr_t * vBoxes; // the array of boxes - // the number of living objects - int nObjs; // the number of live objs - int nObjCounts[ABC_OBJ_NUMBER]; // the number of objects by type - // the backup network and the step number - Abc_Ntk_t * pNetBackup; // the pointer to the previous backup network - int iStep; // the generation number for the given network - // hierarchy - Abc_Lib_t * pDesign; - short fHieVisited; // flag to mark the visited network - short fHiePath; // flag to mark the network on the path - // miscellaneous data members - int nTravIds; // the unique traversal IDs of nodes - Extra_MmFixed_t * pMmObj; // memory manager for objects - Extra_MmStep_t * pMmStep; // memory manager for arrays - void * pManFunc; // functionality manager (AIG manager, BDD manager, or memory manager for SOPs) -// Abc_Lib_t * pVerLib; // for structural verilog designs - Abc_ManTime_t * pManTime; // the timing manager (for mapped networks) stores arrival/required times for all nodes - void * pManCut; // the cut manager (for AIGs) stores information about the cuts computed for the nodes - int LevelMax; // maximum number of levels - Vec_Int_t * vLevelsR; // level in the reverse topological order (for AIGs) - Vec_Ptr_t * vSupps; // CO support information - int * pModel; // counter-example (for miters) - Abc_Ntk_t * pExdc; // the EXDC network (if given) - void * pData; // misc - Abc_Ntk_t * pCopy; - Hop_Man_t * pHaig; // history AIG - // node attributes - Vec_Ptr_t * vAttrs; // managers of various node attributes (node functionality, global BDDs, etc) -}; - -struct Abc_Lib_t_ -{ - char * pName; // the name of the library - void * pManFunc; // functionality manager for the nodes - Vec_Ptr_t * vTops; // the array of top-level modules - Vec_Ptr_t * vModules; // the array of modules - st_table * tModules; // the table hashing module names into their networks - Abc_Lib_t * pLibrary; // the library used to map this design - void * pGenlib; // the genlib library used to map this design -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// maximum/minimum operators -#define ABC_MIN(a,b) (((a) < (b))? (a) : (b)) -#define ABC_MAX(a,b) (((a) > (b))? (a) : (b)) -#define ABC_ABS(a) (((a) >= 0)? (a) :-(a)) -#define ABC_INFINITY (100000000) - -// transforming floats into ints and back -static inline int Abc_Float2Int( float Val ) { return *((int *)&Val); } -static inline float Abc_Int2Float( int Num ) { return *((float *)&Num); } -static inline int Abc_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } -static inline int Abc_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -static inline int Abc_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } -static inline void Abc_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } -static inline void Abc_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } -static inline unsigned Abc_InfoRandomWord() { return ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())); } // #define RAND_MAX 0x7fff -static inline void Abc_InfoRandom( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = Abc_InfoRandomWord(); } -static inline void Abc_InfoClear( unsigned * p, int nWords ) { memset( p, 0, sizeof(unsigned) * nWords ); } -static inline void Abc_InfoFill( unsigned * p, int nWords ) { memset( p, 0xff, sizeof(unsigned) * nWords );} -static inline void Abc_InfoNot( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = ~p[i]; } -static inline int Abc_InfoIsZero( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( p[i] ) return 0; return 1; } -static inline int Abc_InfoIsOne( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~p[i] ) return 0; return 1; } -static inline void Abc_InfoCopy( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = q[i]; } -static inline void Abc_InfoAnd( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] &= q[i]; } -static inline void Abc_InfoOr( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= q[i]; } -static inline void Abc_InfoXor( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] ^= q[i]; } -static inline int Abc_InfoIsOrOne( unsigned * p, unsigned * q, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i]) ) return 0; return 1; } -static inline int Abc_InfoIsOrOne3( unsigned * p, unsigned * q, unsigned * r, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i] | r[i]) ) return 0; return 1; } - -// checking the network type -static inline bool Abc_NtkIsNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_NETLIST; } -static inline bool Abc_NtkIsLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_LOGIC; } -static inline bool Abc_NtkIsStrash( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_STRASH; } - -static inline bool Abc_NtkHasSop( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP; } -static inline bool Abc_NtkHasBdd( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD; } -static inline bool Abc_NtkHasAig( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG; } -static inline bool Abc_NtkHasMapping( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP; } -static inline bool Abc_NtkHasBlifMv( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV; } -static inline bool Abc_NtkHasBlackbox( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLACKBOX; } - -static inline bool Abc_NtkIsSopNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_NETLIST; } -static inline bool Abc_NtkIsAigNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_NETLIST; } -static inline bool Abc_NtkIsMappedNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_NETLIST; } -static inline bool Abc_NtkIsBlifMvNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV && pNtk->ntkType == ABC_NTK_NETLIST; } -static inline bool Abc_NtkIsSopLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_LOGIC ; } -static inline bool Abc_NtkIsBddLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD && pNtk->ntkType == ABC_NTK_LOGIC ; } -static inline bool Abc_NtkIsAigLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_LOGIC ; } -static inline bool Abc_NtkIsMappedLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_LOGIC ; } - -// reading data members of the network -static inline char * Abc_NtkName( Abc_Ntk_t * pNtk ) { return pNtk->pName; } -static inline char * Abc_NtkSpec( Abc_Ntk_t * pNtk ) { return pNtk->pSpec; } -static inline int Abc_NtkTravId( Abc_Ntk_t * pNtk ) { return pNtk->nTravIds; } -static inline Abc_Ntk_t * Abc_NtkExdc( Abc_Ntk_t * pNtk ) { return pNtk->pExdc; } -static inline Abc_Ntk_t * Abc_NtkBackup( Abc_Ntk_t * pNtk ) { return pNtk->pNetBackup; } -static inline int Abc_NtkStep ( Abc_Ntk_t * pNtk ) { return pNtk->iStep; } - -// setting data members of the network -static inline void Abc_NtkSetName ( Abc_Ntk_t * pNtk, char * pName ) { pNtk->pName = pName; } -static inline void Abc_NtkSetSpec ( Abc_Ntk_t * pNtk, char * pName ) { pNtk->pSpec = pName; } -static inline void Abc_NtkSetBackup( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNetBackup ) { pNtk->pNetBackup = pNetBackup; } -static inline void Abc_NtkSetStep ( Abc_Ntk_t * pNtk, int iStep ) { pNtk->iStep = iStep; } - -// getting the number of objects -static inline int Abc_NtkObjNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjs; } -static inline int Abc_NtkObjNumMax( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vObjs); } -static inline int Abc_NtkPiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPis); } -static inline int Abc_NtkPoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPos); } -static inline int Abc_NtkCiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCis); } -static inline int Abc_NtkCoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCos); } -static inline int Abc_NtkAssertNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vAsserts); } -static inline int Abc_NtkBoxNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vBoxes); } -static inline int Abc_NtkBiNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BI]; } -static inline int Abc_NtkBoNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BO]; } -static inline int Abc_NtkNetNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NET]; } -static inline int Abc_NtkNodeNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NODE]; } -static inline int Abc_NtkLatchNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_LATCH]; } -static inline int Abc_NtkWhiteboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_WHITEBOX]; } -static inline int Abc_NtkBlackboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BLACKBOX]; } -static inline bool Abc_NtkIsComb( Abc_Ntk_t * pNtk ) { return Abc_NtkLatchNum(pNtk) == 0; } -static inline bool Abc_NtkHasOnlyLatchBoxes(Abc_Ntk_t * pNtk ){ return Abc_NtkLatchNum(pNtk) == Abc_NtkBoxNum(pNtk); } - -// creating simple objects -extern Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); -static inline Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PI ); } -static inline Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PO ); } -static inline Abc_Obj_t * Abc_NtkCreateBi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BI ); } -static inline Abc_Obj_t * Abc_NtkCreateBo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BO ); } -static inline Abc_Obj_t * Abc_NtkCreateAssert( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_ASSERT ); } -static inline Abc_Obj_t * Abc_NtkCreateNet( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NET ); } -static inline Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NODE ); } -static inline Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_LATCH ); } -static inline Abc_Obj_t * Abc_NtkCreateWhitebox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_WHITEBOX ); } -static inline Abc_Obj_t * Abc_NtkCreateBlackbox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BLACKBOX ); } - -// reading objects -static inline Abc_Obj_t * Abc_NtkObj( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vObjs, i ); } -static inline Abc_Obj_t * Abc_NtkPi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i ); } -static inline Abc_Obj_t * Abc_NtkPo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i ); } -static inline Abc_Obj_t * Abc_NtkCi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i ); } -static inline Abc_Obj_t * Abc_NtkCo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i ); } -static inline Abc_Obj_t * Abc_NtkAssert( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vAsserts, i );} -static inline Abc_Obj_t * Abc_NtkBox( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i ); } - -// working with complemented attributes of objects -static inline bool Abc_ObjIsComplement( Abc_Obj_t * p ) { return (bool)((unsigned long)p & (unsigned long)01); } -static inline Abc_Obj_t * Abc_ObjRegular( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned long)p & ~(unsigned long)01); } -static inline Abc_Obj_t * Abc_ObjNot( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned long)p ^ (unsigned long)01); } -static inline Abc_Obj_t * Abc_ObjNotCond( Abc_Obj_t * p, int c ) { return (Abc_Obj_t *)((unsigned long)p ^ (unsigned long)(c!=0)); } - -// reading data members of the object -static inline unsigned Abc_ObjType( Abc_Obj_t * pObj ) { return pObj->Type; } -static inline unsigned Abc_ObjId( Abc_Obj_t * pObj ) { return pObj->Id; } -static inline int Abc_ObjTravId( Abc_Obj_t * pObj ) { return pObj->TravId; } -static inline int Abc_ObjLevel( Abc_Obj_t * pObj ) { return pObj->Level; } -static inline Vec_Int_t * Abc_ObjFaninVec( Abc_Obj_t * pObj ) { return &pObj->vFanins; } -static inline Vec_Int_t * Abc_ObjFanoutVec( Abc_Obj_t * pObj ) { return &pObj->vFanouts; } -static inline Abc_Obj_t * Abc_ObjCopy( Abc_Obj_t * pObj ) { return pObj->pCopy; } -static inline Abc_Ntk_t * Abc_ObjNtk( Abc_Obj_t * pObj ) { return pObj->pNtk; } -static inline void * Abc_ObjData( Abc_Obj_t * pObj ) { return pObj->pData; } -static inline Hop_Obj_t * Abc_ObjEquiv( Abc_Obj_t * pObj ) { return pObj->pEquiv; } -static inline Abc_Obj_t * Abc_ObjCopyCond( Abc_Obj_t * pObj ) { return Abc_ObjRegular(pObj)->pCopy? Abc_ObjNotCond(Abc_ObjRegular(pObj)->pCopy, Abc_ObjIsComplement(pObj)) : NULL; } - -// setting data members of the network -static inline void Abc_ObjSetLevel( Abc_Obj_t * pObj, int Level ) { pObj->Level = Level; } -static inline void Abc_ObjSetCopy( Abc_Obj_t * pObj, Abc_Obj_t * pCopy ) { pObj->pCopy = pCopy; } -static inline void Abc_ObjSetData( Abc_Obj_t * pObj, void * pData ) { pObj->pData = pData; } - -// checking the object type -static inline bool Abc_ObjIsPio( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PIO; } -static inline bool Abc_ObjIsPi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI; } -static inline bool Abc_ObjIsPo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO; } -static inline bool Abc_ObjIsBi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BI; } -static inline bool Abc_ObjIsBo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BO; } -static inline bool Abc_ObjIsAssert( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_ASSERT; } -static inline bool Abc_ObjIsCi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_BO; } -static inline bool Abc_ObjIsCo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_BI || pObj->Type == ABC_OBJ_ASSERT; } -static inline bool Abc_ObjIsTerm( Abc_Obj_t * pObj ) { return Abc_ObjIsCi(pObj) || Abc_ObjIsCo(pObj); } -static inline bool Abc_ObjIsNet( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NET; } -static inline bool Abc_ObjIsNode( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NODE; } -static inline bool Abc_ObjIsLatch( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH; } -static inline bool Abc_ObjIsBox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH || pObj->Type == ABC_OBJ_WHITEBOX || pObj->Type == ABC_OBJ_BLACKBOX; } -static inline bool Abc_ObjIsWhitebox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_WHITEBOX;} -static inline bool Abc_ObjIsBlackbox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BLACKBOX;} -static inline void Abc_ObjBlackboxToWhitebox( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBlackbox(pObj) ); pObj->Type = ABC_OBJ_WHITEBOX; pObj->pNtk->nObjCounts[ABC_OBJ_BLACKBOX]--; pObj->pNtk->nObjCounts[ABC_OBJ_WHITEBOX]++; } - -// working with fanin/fanout edges -static inline int Abc_ObjFaninNum( Abc_Obj_t * pObj ) { return pObj->vFanins.nSize; } -static inline int Abc_ObjFanoutNum( Abc_Obj_t * pObj ) { return pObj->vFanouts.nSize; } -static inline int Abc_ObjFaninId( Abc_Obj_t * pObj, int i) { return pObj->vFanins.pArray[i]; } -static inline int Abc_ObjFaninId0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0]; } -static inline int Abc_ObjFaninId1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1]; } -static inline int Abc_ObjFanoutEdgeNum( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { assert( Abc_NtkHasAig(pObj->pNtk) ); if ( Abc_ObjFaninId0(pFanout) == pObj->Id ) return 0; if ( Abc_ObjFaninId1(pFanout) == pObj->Id ) return 1; assert( 0 ); return -1; } -static inline Abc_Obj_t * Abc_ObjFanout( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[i] ]; } -static inline Abc_Obj_t * Abc_ObjFanout0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[0] ]; } -static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[i] ]; } -static inline Abc_Obj_t * Abc_ObjFanin0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[0] ]; } -static inline Abc_Obj_t * Abc_ObjFanin1( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[1] ]; } -static inline Abc_Obj_t * Abc_ObjFanin0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanin0(pObj) : pObj); } -static inline Abc_Obj_t * Abc_ObjFanout0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanout0(pObj) : pObj); } -static inline bool Abc_ObjFaninC0( Abc_Obj_t * pObj ) { return pObj->fCompl0; } -static inline bool Abc_ObjFaninC1( Abc_Obj_t * pObj ) { return pObj->fCompl1; } -static inline bool Abc_ObjFaninC( Abc_Obj_t * pObj, int i ) { assert( i >=0 && i < 2 ); return i? pObj->fCompl1 : pObj->fCompl0; } -static inline void Abc_ObjSetFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1 = 1; else pObj->fCompl0 = 1; } -static inline void Abc_ObjXorFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1^= 1; else pObj->fCompl0^= 1; } -static inline Abc_Obj_t * Abc_ObjChild( Abc_Obj_t * pObj, int i ) { return Abc_ObjNotCond( Abc_ObjFanin(pObj,i), Abc_ObjFaninC(pObj,i) );} -static inline Abc_Obj_t * Abc_ObjChild0( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) ); } -static inline Abc_Obj_t * Abc_ObjChild1( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj), Abc_ObjFaninC1(pObj) ); } -static inline Abc_Obj_t * Abc_ObjChildCopy( Abc_Obj_t * pObj, int i ){ return Abc_ObjNotCond( Abc_ObjFanin(pObj,i)->pCopy, Abc_ObjFaninC(pObj,i) ); } -static inline Abc_Obj_t * Abc_ObjChild0Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); } -static inline Abc_Obj_t * Abc_ObjChild1Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ); } -static inline Abc_Obj_t * Abc_ObjChild0Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin0(pObj)->pData, Abc_ObjFaninC0(pObj) ); } -static inline Abc_Obj_t * Abc_ObjChild1Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin1(pObj)->pData, Abc_ObjFaninC1(pObj) ); } -static inline Hop_Obj_t * Abc_ObjChild0Equiv( Abc_Obj_t * pObj ) { return Hop_NotCond( Abc_ObjFanin0(pObj)->pEquiv, Abc_ObjFaninC0(pObj) ); } -static inline Hop_Obj_t * Abc_ObjChild1Equiv( Abc_Obj_t * pObj ) { return Hop_NotCond( Abc_ObjFanin1(pObj)->pEquiv, Abc_ObjFaninC1(pObj) ); } - -// checking the AIG node types -static inline bool Abc_AigNodeIsConst( Abc_Obj_t * pNode ) { assert(Abc_NtkIsStrash(Abc_ObjRegular(pNode)->pNtk)); return Abc_ObjRegular(pNode)->Type == ABC_OBJ_CONST1; } -static inline bool Abc_AigNodeIsAnd( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return Abc_ObjFaninNum(pNode) == 2; } -static inline bool Abc_AigNodeIsChoice( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return pNode->pData != NULL && Abc_ObjFanoutNum(pNode) > 0; } - -// handling persistent nodes -static inline int Abc_NodeIsPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); return pNode->fPersist; } -static inline void Abc_NodeSetPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 1; } -static inline void Abc_NodeClearPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 0; } - -// working with the traversal ID -static inline void Abc_NodeSetTravId( Abc_Obj_t * pNode, int TravId ) { pNode->TravId = TravId; } -static inline void Abc_NodeSetTravIdCurrent( Abc_Obj_t * pNode ) { pNode->TravId = pNode->pNtk->nTravIds; } -static inline void Abc_NodeSetTravIdPrevious( Abc_Obj_t * pNode ) { pNode->TravId = pNode->pNtk->nTravIds - 1; } -static inline bool Abc_NodeIsTravIdCurrent( Abc_Obj_t * pNode ) { return (bool)(pNode->TravId == pNode->pNtk->nTravIds); } -static inline bool Abc_NodeIsTravIdPrevious( Abc_Obj_t * pNode ) { return (bool)(pNode->TravId == pNode->pNtk->nTravIds - 1); } - -// checking initial state of the latches -static inline void Abc_LatchSetInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_NONE; } -static inline void Abc_LatchSetInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ZERO; } -static inline void Abc_LatchSetInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ONE; } -static inline void Abc_LatchSetInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_DC; } -static inline bool Abc_LatchIsInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_NONE; } -static inline bool Abc_LatchIsInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ZERO; } -static inline bool Abc_LatchIsInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ONE; } -static inline bool Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_DC; } -static inline int Abc_LatchInit( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return (int)pLatch->pData; } - -// global BDDs of the nodes -static inline void * Abc_NtkGlobalBdd( Abc_Ntk_t * pNtk ) { return (void *)Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD); } -static inline DdManager * Abc_NtkGlobalBddMan( Abc_Ntk_t * pNtk ) { return (DdManager *)Vec_AttMan( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); } -static inline DdNode ** Abc_NtkGlobalBddArray( Abc_Ntk_t * pNtk ) { return (DdNode **)Vec_AttArray( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); } -static inline DdNode * Abc_ObjGlobalBdd( Abc_Obj_t * pObj ) { return (DdNode *)Vec_AttEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id ); } -static inline void Abc_ObjSetGlobalBdd( Abc_Obj_t * pObj, DdNode * bF ) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id, bF ); } - -// MV variables of the nodes -static inline void * Abc_NtkMvVar( Abc_Ntk_t * pNtk ) { return Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_MVVAR); } -static inline void * Abc_NtkMvVarMan( Abc_Ntk_t * pNtk ) { return Abc_NtkMvVar(pNtk)? Vec_AttMan( (Vec_Att_t *)Abc_NtkMvVar(pNtk) ) : NULL; } -static inline void * Abc_ObjMvVar( Abc_Obj_t * pObj ) { return Abc_NtkMvVar(pObj->pNtk)? Vec_AttEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id ) : NULL; } -static inline int Abc_ObjMvVarNum( Abc_Obj_t * pObj ) { return (Abc_NtkMvVar(pObj->pNtk) && Abc_ObjMvVar(pObj))? *((int*)Abc_ObjMvVar(pObj)) : 2; } -static inline void Abc_ObjSetMvVar( Abc_Obj_t * pObj, void * pV) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id, pV ); } - -// outputs the runtime in seconds -#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// objects of the network -#define Abc_NtkForEachObj( pNtk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pObj) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ - if ( (pObj) == NULL ) {} else -#define Abc_NtkForEachNet( pNtk, pNet, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNet) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ - if ( (pNet) == NULL || !Abc_ObjIsNet(pNet) ) {} else -#define Abc_NtkForEachNode( pNtk, pNode, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ - if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) ) {} else -#define Abc_NtkForEachGate( pNtk, pNode, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ - if ( (pNode) == NULL || !Abc_ObjIsGate(pNode) ) {} else -#define Abc_AigForEachAnd( pNtk, pNode, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ - if ( (pNode) == NULL || !Abc_AigNodeIsAnd(pNode) ) {} else -// various boxes -#define Abc_NtkForEachBox( pNtk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) -#define Abc_NtkForEachLatch( pNtk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ - if ( !Abc_ObjIsLatch(pObj) ) {} else -#define Abc_NtkForEachLatchInput( pNtk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \ - if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanin0(Abc_NtkBox(pNtk, i))), 1)) ) {} else -#define Abc_NtkForEachLatchOutput( pNtk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \ - if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanout0(Abc_NtkBox(pNtk, i))), 1)) ) {} else -#define Abc_NtkForEachWhitebox( pNtk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ - if ( !Abc_ObjIsWhitebox(pObj) ) {} else -#define Abc_NtkForEachBlackbox( pNtk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ - if ( !Abc_ObjIsBlackbox(pObj) ) {} else -// inputs and outputs -#define Abc_NtkForEachPi( pNtk, pPi, i ) \ - for ( i = 0; (i < Abc_NtkPiNum(pNtk)) && (((pPi) = Abc_NtkPi(pNtk, i)), 1); i++ ) -#define Abc_NtkForEachCi( pNtk, pCi, i ) \ - for ( i = 0; (i < Abc_NtkCiNum(pNtk)) && (((pCi) = Abc_NtkCi(pNtk, i)), 1); i++ ) -#define Abc_NtkForEachPo( pNtk, pPo, i ) \ - for ( i = 0; (i < Abc_NtkPoNum(pNtk)) && (((pPo) = Abc_NtkPo(pNtk, i)), 1); i++ ) -#define Abc_NtkForEachCo( pNtk, pCo, i ) \ - for ( i = 0; (i < Abc_NtkCoNum(pNtk)) && (((pCo) = Abc_NtkCo(pNtk, i)), 1); i++ ) -#define Abc_NtkForEachAssert( pNtk, pObj, i ) \ - for ( i = 0; (i < Vec_PtrSize((pNtk)->vAsserts)) && (((pObj) = Abc_NtkAssert(pNtk, i)), 1); i++ ) -// fanin and fanouts -#define Abc_ObjForEachFanin( pObj, pFanin, i ) \ - for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((pFanin) = Abc_ObjFanin(pObj, i)), 1); i++ ) -#define Abc_ObjForEachFanout( pObj, pFanout, i ) \ - for ( i = 0; (i < Abc_ObjFanoutNum(pObj)) && (((pFanout) = Abc_ObjFanout(pObj, i)), 1); i++ ) -// cubes and literals -#define Abc_SopForEachCube( pSop, nFanins, pCube ) \ - for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) -#define Abc_CubeForEachVar( pCube, Value, i ) \ - for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ ) - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== abcAig.c ==========================================================*/ -extern Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtk ); -extern void Abc_AigFree( Abc_Aig_t * pMan ); -extern int Abc_AigCleanup( Abc_Aig_t * pMan ); -extern bool Abc_AigCheck( Abc_Aig_t * pMan ); -extern int Abc_AigLevel( Abc_Ntk_t * pNtk ); -extern Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ); -extern Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); -extern Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); -extern Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType ); -extern Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType ); -extern Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); -extern Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); -extern Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ); -extern void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool fUpdateLevel ); -extern void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld ); -extern void Abc_AigRehash( Abc_Aig_t * pMan ); -extern bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ); -extern bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ); -extern void Abc_AigPrintNode( Abc_Obj_t * pNode ); -extern bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ); -extern void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan ); -extern void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk ); -extern Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets ); -extern void Abc_AigUpdateStop( Abc_Aig_t * pMan ); -extern void Abc_AigUpdateReset( Abc_Aig_t * pMan ); -/*=== abcAttach.c ==========================================================*/ -extern int Abc_NtkAttach( Abc_Ntk_t * pNtk ); -/*=== abcBlifMv.c ==========================================================*/ -extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ); -extern void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ); -extern void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues ); -extern Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic ); -extern int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk ); -extern char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ); -extern int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ); -/*=== abcBalance.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel ); -/*=== abcCheck.c ==========================================================*/ -extern bool Abc_NtkCheck( Abc_Ntk_t * pNtk ); -extern bool Abc_NtkCheckRead( Abc_Ntk_t * pNtk ); -extern bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ); -extern bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); -extern bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb ); -extern int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ); -extern int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ); -extern int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ); -extern int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ); -/*=== abcCollapse.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ); -/*=== abcCut.c ==========================================================*/ -extern void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); -extern void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); -extern void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fFirst ); -extern void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ); -extern void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ); -/*=== abcDfs.c ==========================================================*/ -extern Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll ); -extern Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); -extern Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ); -extern Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); -extern Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); -extern Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk ); -extern Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ); -extern Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ); -extern Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll ); -extern bool Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk ); -extern Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk ); -extern Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); -extern Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ); -extern Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi ); -extern int Abc_NtkLevel( Abc_Ntk_t * pNtk ); -extern int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ); -extern bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ); -extern Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ); -/*=== abcFanio.c ==========================================================*/ -extern void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); -extern void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); -extern void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ); -extern void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew ); -extern Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ); -extern void Abc_ObjTransferFanout( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); -extern void Abc_ObjReplace( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); -extern int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ); -/*=== abcFraig.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ); -extern void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ); -extern Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk ); -extern int Abc_NtkFraigStore( Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_NtkFraigRestore(); -extern void Abc_NtkFraigStoreClean(); -/*=== abcFunc.c ==========================================================*/ -extern int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ); -extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop ); -extern char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode ); -extern int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ); -extern void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ); -extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); -extern void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ); -extern int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ); -extern int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ); -extern unsigned * Abc_ConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst ); -extern int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ); -extern int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fDirect ); -extern int Abc_NtkToBdd( Abc_Ntk_t * pNtk ); -extern int Abc_NtkToAig( Abc_Ntk_t * pNtk ); -/*=== abcHaig.c ==========================================================*/ -extern int Abc_NtkHaigStart( Abc_Ntk_t * pNtk ); -extern int Abc_NtkHaigStop( Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_NtkHaigUse( Abc_Ntk_t * pNtk ); -/*=== abcHie.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL ); -/*=== abcLatch.c ==========================================================*/ -extern bool Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ); -extern int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ); -extern int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ); -extern Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk ); -extern void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ); -extern Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init ); -extern void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk ); - /*=== abcLib.c ==========================================================*/ -extern Abc_Lib_t * Abc_LibCreate( char * pName ); -extern void Abc_LibFree( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk ); -extern void Abc_LibPrint( Abc_Lib_t * pLib ); -extern int Abc_LibAddModel( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_LibFindModelByName( Abc_Lib_t * pLib, char * pName ); -extern int Abc_LibFindTopLevelModels( Abc_Lib_t * pLib ); -extern Abc_Ntk_t * Abc_LibDeriveRoot( Abc_Lib_t * pLib ); -/*=== abcMiter.c ==========================================================*/ -extern int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ); -extern int Abc_NodeMinimumBase( Abc_Obj_t * pNode ); -extern int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ); -extern int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ); -/*=== abcMiter.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ); -extern void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pNode ); -extern Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 ); -extern Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ); -extern Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ); -extern Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ); -extern Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ); -extern int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ); -extern void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ); -extern Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial ); -/*=== abcNames.c ====================================================*/ -extern char * Abc_ObjName( Abc_Obj_t * pNode ); -extern char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix ); -extern char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ); -extern char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits ); -extern void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); -extern void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); -extern Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ); -extern Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ); -extern void Abc_NodeFreeNames( Vec_Ptr_t * vNames ); -extern char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos ); -extern int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); -extern void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ); -extern void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ); -extern void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ); -extern void Abc_NtkAddDummyAssertNames( Abc_Ntk_t * pNtk ); -extern void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ); -extern void Abc_NtkShortNames( Abc_Ntk_t * pNtk ); -/*=== abcNetlist.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ); -/*=== abcNtbdd.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ); -extern Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ); -extern DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fVerbose ); -extern DdManager * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ); -extern int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ); -/*=== abcNtk.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ); -extern Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); -extern Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); -extern void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); -extern Abc_Ntk_t * Abc_NtkStartRead( char * pName ); -extern void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ); -extern Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis ); -extern void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ); -extern Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ); -extern Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ); -extern Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); -extern Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ); -extern void Abc_NtkDelete( Abc_Ntk_t * pNtk ); -extern void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ); -extern void Abc_NtkMakeComb( Abc_Ntk_t * pNtk ); -/*=== abcObj.c ==========================================================*/ -extern Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); -extern void Abc_ObjRecycle( Abc_Obj_t * pObj ); -extern Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); -extern void Abc_NtkDeleteObj( Abc_Obj_t * pObj ); -extern void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes ); -extern void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ); -extern Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName ); -extern Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName ); -extern Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pNode ); -extern Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ); -extern Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ); -extern Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName ); -extern Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ); -extern Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ); -extern Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ); -extern Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ); -extern Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); -extern Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); -extern Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); -extern Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); -extern Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); -extern Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ); -extern bool Abc_NodeIsConst( Abc_Obj_t * pNode ); -extern bool Abc_NodeIsConst0( Abc_Obj_t * pNode ); -extern bool Abc_NodeIsConst1( Abc_Obj_t * pNode ); -extern bool Abc_NodeIsBuf( Abc_Obj_t * pNode ); -extern bool Abc_NodeIsInv( Abc_Obj_t * pNode ); -extern void Abc_NodeComplement( Abc_Obj_t * pNode ); -/*=== abcPrint.c ==========================================================*/ -extern void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ); -extern void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk ); -extern void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ); -extern void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk ); -extern void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ); -extern void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ); -extern void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ); -extern void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes ); -extern void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ); -extern void Abc_NtkPrintSkews( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintAll ); -extern void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ); -/*=== abcProve.c ==========================================================*/ -extern int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pParams ); -extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ); -/*=== abcRec.c ==========================================================*/ -extern void Abc_NtkRecStart( Abc_Ntk_t * pNtk, int nVars, int nCuts ); -extern void Abc_NtkRecStop(); -extern void Abc_NtkRecAdd( Abc_Ntk_t * pNtk ); -extern void Abc_NtkRecPs(); -extern void Abc_NtkRecFilter( int iVar, int iPlus ); -extern Abc_Ntk_t * Abc_NtkRecUse(); -extern int Abc_NtkRecIsRunning(); -extern int Abc_NtkRecVarNum(); -extern Vec_Int_t * Abc_NtkRecMemory(); -extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ); -/*=== abcReconv.c ==========================================================*/ -extern Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ); -extern void Abc_NtkManCutStop( Abc_ManCut_t * p ); -extern Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p ); -extern Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p ); -extern Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p ); -extern Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain ); -extern void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited, int fIncludeFanins ); -extern DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited ); -extern DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited ); -extern Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, int LevelMax ); -/*=== abcRefs.c ==========================================================*/ -extern int Abc_NodeMffcSize( Abc_Obj_t * pNode ); -extern int Abc_NodeMffcSizeSupp( Abc_Obj_t * pNode ); -extern int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ); -extern int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ); -extern int Abc_NodeMffcLabel( Abc_Obj_t * pNode ); -extern void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ); -extern int Abc_NodeDeref_rec( Abc_Obj_t * pNode ); -extern int Abc_NodeRef_rec( Abc_Obj_t * pNode ); -/*=== abcRefactor.c ==========================================================*/ -extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); -/*=== abcRewrite.c ==========================================================*/ -extern int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ); -/*=== abcSat.c ==========================================================*/ -extern int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects ); -extern void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes ); -/*=== abcSop.c ==========================================================*/ -extern char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName ); -extern char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars ); -extern char * Abc_SopCreateConst0( Extra_MmFlex_t * pMan ); -extern char * Abc_SopCreateConst1( Extra_MmFlex_t * pMan ); -extern char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 ); -extern char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ); -extern char * Abc_SopCreateNand( Extra_MmFlex_t * pMan, int nVars ); -extern char * Abc_SopCreateOr( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ); -extern char * Abc_SopCreateOrMultiCube( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ); -extern char * Abc_SopCreateNor( Extra_MmFlex_t * pMan, int nVars ); -extern char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars ); -extern char * Abc_SopCreateXorSpecial( Extra_MmFlex_t * pMan, int nVars ); -extern char * Abc_SopCreateNxor( Extra_MmFlex_t * pMan, int nVars ); -extern char * Abc_SopCreateMux( Extra_MmFlex_t * pMan ); -extern char * Abc_SopCreateInv( Extra_MmFlex_t * pMan ); -extern char * Abc_SopCreateBuf( Extra_MmFlex_t * pMan ); -extern char * Abc_SopCreateFromTruth( Extra_MmFlex_t * pMan, int nVars, unsigned * pTruth ); -extern char * Abc_SopCreateFromIsop( Extra_MmFlex_t * pMan, int nVars, Vec_Int_t * vCover ); -extern int Abc_SopGetCubeNum( char * pSop ); -extern int Abc_SopGetLitNum( char * pSop ); -extern int Abc_SopGetVarNum( char * pSop ); -extern int Abc_SopGetPhase( char * pSop ); -extern int Abc_SopGetIthCareLit( char * pSop, int i ); -extern void Abc_SopComplement( char * pSop ); -extern bool Abc_SopIsComplement( char * pSop ); -extern bool Abc_SopIsConst0( char * pSop ); -extern bool Abc_SopIsConst1( char * pSop ); -extern bool Abc_SopIsBuf( char * pSop ); -extern bool Abc_SopIsInv( char * pSop ); -extern bool Abc_SopIsAndType( char * pSop ); -extern bool Abc_SopIsOrType( char * pSop ); -extern int Abc_SopIsExorType( char * pSop ); -extern bool Abc_SopCheck( char * pSop, int nFanins ); -extern char * Abc_SopFromTruthBin( char * pTruth ); -extern char * Abc_SopFromTruthHex( char * pTruth ); -extern char * Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues ); -extern char * Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues ); -extern char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues ); -extern char * Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues ); -/*=== abcStrash.c ==========================================================*/ -extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord ); -extern Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int fRecord ); -extern int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ); -extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); -/*=== abcSweep.c ==========================================================*/ -extern int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ); -extern int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ); -extern int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose ); -/*=== abcTiming.c ==========================================================*/ -extern Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ); -extern Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ); -extern Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk ); -extern Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ); -extern void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ); -extern void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ); -extern void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ); -extern void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ); -extern void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk ); -extern void Abc_ManTimeStop( Abc_ManTime_t * p ); -extern void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ); -extern void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtk ); -extern float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk ); -extern Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk ); -extern float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk ); -extern int Abc_ObjLevelNew( Abc_Obj_t * pObj ); -extern int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ); -extern int Abc_ObjRequiredLevel( Abc_Obj_t * pObj ); -extern int Abc_ObjReverseLevel( Abc_Obj_t * pObj ); -extern void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR ); -extern void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease ); -extern void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ); -extern void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); -extern void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); -extern void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); -/*=== abcUtil.c ==========================================================*/ -extern void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ); -extern void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk ); -extern void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk ); -extern double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ); -extern int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk ); -extern void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ); -extern void Abc_NtkCleanData( Abc_Ntk_t * pNtk ); -extern void Abc_NtkCleanEquiv( Abc_Ntk_t * pNtk ); -extern int Abc_NtkCountCopy( Abc_Ntk_t * pNtk ); -extern Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ); -extern void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ); -extern void Abc_NtkCleanNext( Abc_Ntk_t * pNtk ); -extern void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk ); -extern Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode ); -extern Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode ); -extern Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ); -extern bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ); -extern int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDuplicate ); -extern void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ); -extern bool Abc_NodeIsExorType( Abc_Obj_t * pNode ); -extern bool Abc_NodeIsMuxType( Abc_Obj_t * pNode ); -extern bool Abc_NodeIsMuxControlType( Abc_Obj_t * pNode ); -extern Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ); -extern int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2 ); -extern void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); -extern void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); -extern Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk ); -extern int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); -extern int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); -extern Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ); -extern Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ); -extern Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk ); -extern void Abc_NtkReassignIds( Abc_Ntk_t * pNtk ); -extern int Abc_ObjPointerCompare( void ** pp1, void ** pp2 ); -extern void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ); -/*=== abcVerify.c ==========================================================*/ -extern int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames ); -extern int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/base/abc/abcAig.c b/src/base/abc/abcAig.c deleted file mode 100644 index 16f66dc6..00000000 --- a/src/base/abc/abcAig.c +++ /dev/null @@ -1,1476 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcAig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Simple structural hashing package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -/* - AIG is an And-Inv Graph with structural hashing. - It is always structurally hashed. It means that at any time: - - for each AND gate, there are no other AND gates with the same children - - the constants are propagated - - there is no single-input nodes (inverters/buffers) - Additionally the following invariants are satisfied: - - there are no dangling nodes (the nodes without fanout) - - the level of each AND gate reflects the levels of this fanins - - the EXOR-status of each node is up-to-date - - the AND nodes are in the topological order - - the constant 1 node has always number 0 in the object list - The operations that are performed on AIGs: - - building new nodes (Abc_AigAnd) - - performing elementary Boolean operations (Abc_AigOr, Abc_AigXor, etc) - - replacing one node by another (Abc_AigReplace) - - propagating constants (Abc_AigReplace) - When AIG is duplicated, the new graph is structurally hashed too. - If this repeated hashing leads to fewer nodes, it means the original - AIG was not strictly hashed (one of the conditions above is violated). -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the simple AIG manager -struct Abc_Aig_t_ -{ - Abc_Ntk_t * pNtkAig; // the AIG network - Abc_Obj_t * pConst1; // the constant 1 object (not a node!) - Abc_Obj_t ** pBins; // the table bins - int nBins; // the size of the table - int nEntries; // the total number of entries in the table - Vec_Ptr_t * vNodes; // the temporary array of nodes - Vec_Ptr_t * vStackReplaceOld; // the nodes to be replaced - Vec_Ptr_t * vStackReplaceNew; // the nodes to be used for replacement - Vec_Vec_t * vLevels; // the nodes to be updated - Vec_Vec_t * vLevelsR; // the nodes to be updated - Vec_Ptr_t * vAddedCells; // the added nodes - Vec_Ptr_t * vUpdatedNets; // the nodes whose fanouts have changed - - int nStrash0; - int nStrash1; - int nStrash5; - int nStrash2; -}; - -// iterators through the entries in the linked lists of nodes -#define Abc_AigBinForEachEntry( pBin, pEnt ) \ - for ( pEnt = pBin; \ - pEnt; \ - pEnt = pEnt->pNext ) -#define Abc_AigBinForEachEntrySafe( pBin, pEnt, pEnt2 ) \ - for ( pEnt = pBin, \ - pEnt2 = pEnt? pEnt->pNext: NULL; \ - pEnt; \ - pEnt = pEnt2, \ - pEnt2 = pEnt? pEnt->pNext: NULL ) - -// hash key for the structural hash table -//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; } -//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)((a)->Id + (b)->Id) * ((a)->Id + (b)->Id + 1) / 2) % TableSize; } - -// hashing the node -static unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) -{ - unsigned Key = 0; - Key ^= Abc_ObjRegular(p0)->Id * 7937; - Key ^= Abc_ObjRegular(p1)->Id * 2971; - Key ^= Abc_ObjIsComplement(p0) * 911; - Key ^= Abc_ObjIsComplement(p1) * 353; - return Key % TableSize; -} - -// structural hash table procedures -static Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); -static Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd ); -static void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis ); -static void Abc_AigResize( Abc_Aig_t * pMan ); -// incremental AIG procedures -static void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ); -static void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ); -static void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ); -static void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ); -static void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the local AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig ) -{ - Abc_Aig_t * pMan; - // start the manager - pMan = ALLOC( Abc_Aig_t, 1 ); - memset( pMan, 0, sizeof(Abc_Aig_t) ); - // allocate the table - pMan->nBins = Cudd_PrimeCopy( 10000 ); - pMan->pBins = ALLOC( Abc_Obj_t *, pMan->nBins ); - memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); - pMan->vNodes = Vec_PtrAlloc( 100 ); - pMan->vLevels = Vec_VecAlloc( 100 ); - pMan->vLevelsR = Vec_VecAlloc( 100 ); - pMan->vStackReplaceOld = Vec_PtrAlloc( 100 ); - pMan->vStackReplaceNew = Vec_PtrAlloc( 100 ); - // create the constant node - assert( pNtkAig->vObjs->nSize == 0 ); - pMan->pConst1 = Abc_NtkCreateObj( pNtkAig, ABC_OBJ_NODE ); - pMan->pConst1->Type = ABC_OBJ_CONST1; - pMan->pConst1->fPhase = 1; - pNtkAig->nObjCounts[ABC_OBJ_NODE]--; - // save the current network - pMan->pNtkAig = pNtkAig; - return pMan; -} - -/**Function************************************************************* - - Synopsis [Deallocates the local AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigFree( Abc_Aig_t * pMan ) -{ - assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 ); - assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 ); - // free the table - if ( pMan->vAddedCells ) - Vec_PtrFree( pMan->vAddedCells ); - if ( pMan->vUpdatedNets ) - Vec_PtrFree( pMan->vUpdatedNets ); - Vec_VecFree( pMan->vLevels ); - Vec_VecFree( pMan->vLevelsR ); - Vec_PtrFree( pMan->vStackReplaceOld ); - Vec_PtrFree( pMan->vStackReplaceNew ); - Vec_PtrFree( pMan->vNodes ); - free( pMan->pBins ); - free( pMan ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of dangling nodes removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_AigCleanup( Abc_Aig_t * pMan ) -{ - Vec_Ptr_t * vDangles; - Abc_Obj_t * pAnd; - int i, nNodesOld; -// printf( "Strash0 = %d. Strash1 = %d. Strash100 = %d. StrashM = %d.\n", -// pMan->nStrash0, pMan->nStrash1, pMan->nStrash5, pMan->nStrash2 ); - nNodesOld = pMan->nEntries; - // collect the AND nodes that do not fanout - vDangles = Vec_PtrAlloc( 100 ); - for ( i = 0; i < pMan->nBins; i++ ) - Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) - if ( Abc_ObjFanoutNum(pAnd) == 0 ) - Vec_PtrPush( vDangles, pAnd ); - // process the dangling nodes and their MFFCs - Vec_PtrForEachEntry( vDangles, pAnd, i ) - Abc_AigDeleteNode( pMan, pAnd ); - Vec_PtrFree( vDangles ); - return nNodesOld - pMan->nEntries; -} - -/**Function************************************************************* - - Synopsis [Makes sure that every node in the table is in the network and vice versa.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_AigCheck( Abc_Aig_t * pMan ) -{ - Abc_Obj_t * pObj, * pAnd; - int i, nFanins, Counter; - Abc_NtkForEachNode( pMan->pNtkAig, pObj, i ) - { - nFanins = Abc_ObjFaninNum(pObj); - if ( nFanins == 0 ) - { - if ( !Abc_AigNodeIsConst(pObj) ) - { - printf( "Abc_AigCheck: The AIG has non-standard constant nodes.\n" ); - return 0; - } - continue; - } - if ( nFanins == 1 ) - { - printf( "Abc_AigCheck: The AIG has single input nodes.\n" ); - return 0; - } - if ( nFanins > 2 ) - { - printf( "Abc_AigCheck: The AIG has non-standard nodes.\n" ); - return 0; - } - if ( pObj->Level != 1 + ABC_MAX( Abc_ObjFanin0(pObj)->Level, Abc_ObjFanin1(pObj)->Level ) ) - printf( "Abc_AigCheck: Node \"%s\" has level that does not agree with the fanin levels.\n", Abc_ObjName(pObj) ); - pAnd = Abc_AigAndLookup( pMan, Abc_ObjChild0(pObj), Abc_ObjChild1(pObj) ); - if ( pAnd != pObj ) - printf( "Abc_AigCheck: Node \"%s\" is not in the structural hashing table.\n", Abc_ObjName(pObj) ); - } - // count the number of nodes in the table - Counter = 0; - for ( i = 0; i < pMan->nBins; i++ ) - Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) - Counter++; - if ( Counter != Abc_NtkNodeNum(pMan->pNtkAig) ) - { - printf( "Abc_AigCheck: The number of nodes in the structural hashing table is wrong.\n" ); - return 0; - } - // if the node is a choice node, nodes in its class should not have fanouts - Abc_NtkForEachNode( pMan->pNtkAig, pObj, i ) - if ( Abc_AigNodeIsChoice(pObj) ) - for ( pAnd = pObj->pData; pAnd; pAnd = pAnd->pData ) - if ( Abc_ObjFanoutNum(pAnd) > 0 ) - { - printf( "Abc_AigCheck: Representative %s", Abc_ObjName(pAnd) ); - printf( " of choice node %s has %d fanouts.\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pAnd) ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes the number of logic levels not counting PIs/POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_AigLevel( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, LevelsMax; - assert( Abc_NtkIsStrash(pNtk) ); - // perform the traversal - LevelsMax = 0; - Abc_NtkForEachCo( pNtk, pNode, i ) - if ( LevelsMax < (int)Abc_ObjFanin0(pNode)->Level ) - LevelsMax = (int)Abc_ObjFanin0(pNode)->Level; - return LevelsMax; -} - - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) -{ - Abc_Obj_t * pAnd; - unsigned Key; - // check if it is a good time for table resizing - if ( pMan->nEntries > 2 * pMan->nBins ) - Abc_AigResize( pMan ); - // order the arguments - if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) - pAnd = p0, p0 = p1, p1 = pAnd; - // create the new node - pAnd = Abc_NtkCreateNode( pMan->pNtkAig ); - Abc_ObjAddFanin( pAnd, p0 ); - Abc_ObjAddFanin( pAnd, p1 ); - // set the level of the new node - pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); - pAnd->fExor = Abc_NodeIsExorType(pAnd); - pAnd->fPhase = (Abc_ObjIsComplement(p0) ^ Abc_ObjRegular(p0)->fPhase) & (Abc_ObjIsComplement(p1) ^ Abc_ObjRegular(p1)->fPhase); - // add the node to the corresponding linked list in the table - Key = Abc_HashKey2( p0, p1, pMan->nBins ); - pAnd->pNext = pMan->pBins[Key]; - pMan->pBins[Key] = pAnd; - pMan->nEntries++; - // create the cuts if defined -// if ( pAnd->pNtk->pManCut ) -// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd ); - pAnd->pCopy = NULL; - // add the node to the list of updated nodes - if ( pMan->vAddedCells ) - Vec_PtrPush( pMan->vAddedCells, pAnd ); - // create HAIG - if ( pAnd->pNtk->pHaig ) - pAnd->pEquiv = Hop_And( pAnd->pNtk->pHaig, Abc_ObjChild0Equiv(pAnd), Abc_ObjChild1Equiv(pAnd) ); - return pAnd; -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd ) -{ - Abc_Obj_t * pTemp; - unsigned Key; - assert( !Abc_ObjIsComplement(pAnd) ); - // order the arguments - if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) - pTemp = p0, p0 = p1, p1 = pTemp; - // create the new node - Abc_ObjAddFanin( pAnd, p0 ); - Abc_ObjAddFanin( pAnd, p1 ); - // set the level of the new node - pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); - pAnd->fExor = Abc_NodeIsExorType(pAnd); - // add the node to the corresponding linked list in the table - Key = Abc_HashKey2( p0, p1, pMan->nBins ); - pAnd->pNext = pMan->pBins[Key]; - pMan->pBins[Key] = pAnd; - pMan->nEntries++; - // create the cuts if defined -// if ( pAnd->pNtk->pManCut ) -// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd ); - pAnd->pCopy = NULL; - // add the node to the list of updated nodes -// if ( pMan->vAddedCells ) -// Vec_PtrPush( pMan->vAddedCells, pAnd ); - // create HAIG - if ( pAnd->pNtk->pHaig ) - pAnd->pEquiv = Hop_And( pAnd->pNtk->pHaig, Abc_ObjChild0Equiv(pAnd), Abc_ObjChild1Equiv(pAnd) ); - return pAnd; -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) -{ - Abc_Obj_t * pAnd, * pConst1; - unsigned Key; - assert( Abc_ObjRegular(p0)->pNtk->pManFunc == pMan ); - assert( Abc_ObjRegular(p1)->pNtk->pManFunc == pMan ); - // check for trivial cases - pConst1 = Abc_AigConst1(pMan->pNtkAig); - if ( p0 == p1 ) - return p0; - if ( p0 == Abc_ObjNot(p1) ) - return Abc_ObjNot(pConst1); - if ( Abc_ObjRegular(p0) == pConst1 ) - { - if ( p0 == pConst1 ) - return p1; - return Abc_ObjNot(pConst1); - } - if ( Abc_ObjRegular(p1) == pConst1 ) - { - if ( p1 == pConst1 ) - return p0; - return Abc_ObjNot(pConst1); - } -/* - { - int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) ); - int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) ); - if ( nFans0 == 0 || nFans1 == 0 ) - pMan->nStrash0++; - else if ( nFans0 == 1 || nFans1 == 1 ) - pMan->nStrash1++; - else if ( nFans0 <= 100 && nFans1 <= 100 ) - pMan->nStrash5++; - else - pMan->nStrash2++; - } -*/ - { - int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) ); - int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) ); - if ( nFans0 == 0 || nFans1 == 0 ) - return NULL; - } - - // order the arguments - if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) - pAnd = p0, p0 = p1, p1 = pAnd; - // get the hash key for these two nodes - Key = Abc_HashKey2( p0, p1, pMan->nBins ); - // find the matching node in the table - Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd ) - if ( p0 == Abc_ObjChild0(pAnd) && p1 == Abc_ObjChild1(pAnd) ) - { -// assert( Abc_ObjFanoutNum(Abc_ObjRegular(p0)) && Abc_ObjFanoutNum(p1) ); - return pAnd; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType ) -{ - Abc_Obj_t * pNode1, * pNode2, * pNode; - // set the flag to zero - if ( pType ) *pType = 0; - // check the case of XOR(a,b) = OR(ab, a'b')' - if ( (pNode1 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), Abc_ObjNot(p1))) && - (pNode2 = Abc_AigAndLookup(pMan, p0, p1)) ) - { - pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); - if ( pNode && pType ) *pType = 1; - return pNode; - } - // check the case of XOR(a,b) = OR(a'b, ab') - if ( (pNode1 = Abc_AigAndLookup(pMan, p0, Abc_ObjNot(p1))) && - (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), p1)) ) - { - pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); - return pNode? Abc_ObjNot(pNode) : NULL; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType ) -{ - Abc_Obj_t * pNode1, * pNode2, * pNode; - // set the flag to zero - if ( pType ) *pType = 0; - // check the case of MUX(c,t,e) = OR(ct', c'e')' - if ( (pNode1 = Abc_AigAndLookup(pMan, pC, Abc_ObjNot(pT))) && - (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), Abc_ObjNot(pE))) ) - { - pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); - if ( pNode && pType ) *pType = 1; - return pNode; - } - // check the case of MUX(c,t,e) = OR(ct, c'e) - if ( (pNode1 = Abc_AigAndLookup(pMan, pC, pT)) && - (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), pE)) ) - { - pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); - return pNode? Abc_ObjNot(pNode) : NULL; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Deletes an AIG node from the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis ) -{ - Abc_Obj_t * pAnd, * pAnd0, * pAnd1, ** ppPlace; - unsigned Key; - assert( !Abc_ObjIsComplement(pThis) ); - assert( Abc_ObjIsNode(pThis) ); - assert( Abc_ObjFaninNum(pThis) == 2 ); - assert( pMan->pNtkAig == pThis->pNtk ); - // get the hash key for these two nodes - pAnd0 = Abc_ObjRegular( Abc_ObjChild0(pThis) ); - pAnd1 = Abc_ObjRegular( Abc_ObjChild1(pThis) ); - Key = Abc_HashKey2( Abc_ObjChild0(pThis), Abc_ObjChild1(pThis), pMan->nBins ); - // find the matching node in the table - ppPlace = pMan->pBins + Key; - Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd ) - { - if ( pAnd != pThis ) - { - ppPlace = &pAnd->pNext; - continue; - } - *ppPlace = pAnd->pNext; - break; - } - assert( pAnd == pThis ); - pMan->nEntries--; - // delete the cuts if defined - if ( pThis->pNtk->pManCut ) - Abc_NodeFreeCuts( pThis->pNtk->pManCut, pThis ); -} - -/**Function************************************************************* - - Synopsis [Resizes the hash table of AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigResize( Abc_Aig_t * pMan ) -{ - Abc_Obj_t ** pBinsNew; - Abc_Obj_t * pEnt, * pEnt2; - int nBinsNew, Counter, i, clk; - unsigned Key; - -clk = clock(); - // get the new table size - nBinsNew = Cudd_PrimeCopy( 3 * pMan->nBins ); - // allocate a new array - pBinsNew = ALLOC( Abc_Obj_t *, nBinsNew ); - memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * nBinsNew ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < pMan->nBins; i++ ) - Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 ) - { - Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), nBinsNew ); - pEnt->pNext = pBinsNew[Key]; - pBinsNew[Key] = pEnt; - Counter++; - } - assert( Counter == pMan->nEntries ); -// printf( "Increasing the structural table size from %6d to %6d. ", pMan->nBins, nBinsNew ); -// PRT( "Time", clock() - clk ); - // replace the table and the parameters - free( pMan->pBins ); - pMan->pBins = pBinsNew; - pMan->nBins = nBinsNew; -} - -/**Function************************************************************* - - Synopsis [Resizes the hash table of AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigRehash( Abc_Aig_t * pMan ) -{ - Abc_Obj_t ** pBinsNew; - Abc_Obj_t * pEnt, * pEnt2; - int * pArray; - unsigned Key; - int Counter, Temp, i; - - // allocate a new array - pBinsNew = ALLOC( Abc_Obj_t *, pMan->nBins ); - memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < pMan->nBins; i++ ) - Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 ) - { - // swap the fanins if needed - pArray = pEnt->vFanins.pArray; - if ( pArray[0] > pArray[1] ) - { - Temp = pArray[0]; - pArray[0] = pArray[1]; - pArray[1] = Temp; - Temp = pEnt->fCompl0; - pEnt->fCompl0 = pEnt->fCompl1; - pEnt->fCompl1 = Temp; - } - // rehash the node - Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), pMan->nBins ); - pEnt->pNext = pBinsNew[Key]; - pBinsNew[Key] = pEnt; - Counter++; - } - assert( Counter == pMan->nEntries ); - // replace the table and the parameters - free( pMan->pBins ); - pMan->pBins = pBinsNew; -} - - - - - - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ) -{ - assert( Abc_NtkIsStrash(pNtk) ); - return ((Abc_Aig_t *)pNtk->pManFunc)->pConst1; -} - -/**Function************************************************************* - - Synopsis [Performs canonicization step.] - - Description [The argument nodes can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) -{ - Abc_Obj_t * pAnd; - if ( (pAnd = Abc_AigAndLookup( pMan, p0, p1 )) ) - return pAnd; - return Abc_AigAndCreate( pMan, p0, p1 ); -} - -/**Function************************************************************* - - Synopsis [Implements Boolean OR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) -{ - return Abc_ObjNot( Abc_AigAnd( pMan, Abc_ObjNot(p0), Abc_ObjNot(p1) ) ); -} - -/**Function************************************************************* - - Synopsis [Implements Boolean XOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) -{ - return Abc_AigOr( pMan, Abc_AigAnd(pMan, p0, Abc_ObjNot(p1)), - Abc_AigAnd(pMan, p1, Abc_ObjNot(p0)) ); -} - -/**Function************************************************************* - - Synopsis [Implements the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigMiter_rec( Abc_Aig_t * pMan, Abc_Obj_t ** ppObjs, int nObjs ) -{ - Abc_Obj_t * pObj1, * pObj2; - if ( nObjs == 1 ) - return ppObjs[0]; - pObj1 = Abc_AigMiter_rec( pMan, ppObjs, nObjs/2 ); - pObj2 = Abc_AigMiter_rec( pMan, ppObjs + nObjs/2, nObjs - nObjs/2 ); - return Abc_AigOr( pMan, pObj1, pObj2 ); -} - -/**Function************************************************************* - - Synopsis [Implements the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ) -{ - int i; - if ( vPairs->nSize == 0 ) - return Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) ); - assert( vPairs->nSize % 2 == 0 ); - // go through the cubes of the node's SOP - for ( i = 0; i < vPairs->nSize; i += 2 ) - vPairs->pArray[i/2] = Abc_AigXor( pMan, vPairs->pArray[i], vPairs->pArray[i+1] ); - vPairs->nSize = vPairs->nSize/2; - return Abc_AigMiter_rec( pMan, (Abc_Obj_t **)vPairs->pArray, vPairs->nSize ); -} - -/**Function************************************************************* - - Synopsis [Implements the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_AigMiter2( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ) -{ - Abc_Obj_t * pMiter, * pXor; - int i; - assert( vPairs->nSize % 2 == 0 ); - // go through the cubes of the node's SOP - pMiter = Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) ); - for ( i = 0; i < vPairs->nSize; i += 2 ) - { - pXor = Abc_AigXor( pMan, vPairs->pArray[i], vPairs->pArray[i+1] ); - pMiter = Abc_AigOr( pMan, pMiter, pXor ); - } - return pMiter; -} - - - - -/**Function************************************************************* - - Synopsis [Replaces one AIG node by the other.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, bool fUpdateLevel ) -{ - assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 ); - assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 ); - Vec_PtrPush( pMan->vStackReplaceOld, pOld ); - Vec_PtrPush( pMan->vStackReplaceNew, pNew ); - assert( !Abc_ObjIsComplement(pOld) ); - // create HAIG - if ( pOld->pNtk->pHaig ) - Hop_ObjCreateChoice( pOld->pEquiv, Abc_ObjRegular(pNew)->pEquiv ); - // process the replacements - while ( Vec_PtrSize(pMan->vStackReplaceOld) ) - { - pOld = Vec_PtrPop( pMan->vStackReplaceOld ); - pNew = Vec_PtrPop( pMan->vStackReplaceNew ); - Abc_AigReplace_int( pMan, pOld, pNew, fUpdateLevel ); - } - if ( fUpdateLevel ) - { - Abc_AigUpdateLevel_int( pMan ); - if ( pMan->pNtkAig->vLevelsR ) - Abc_AigUpdateLevelR_int( pMan ); - } -} - -/**Function************************************************************* - - Synopsis [Performs internal replacement step.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ) -{ - Abc_Obj_t * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout; - int k, v, iFanin; - // make sure the old node is regular and has fanouts - // (the new node can be complemented and can have fanouts) - assert( !Abc_ObjIsComplement(pOld) ); - assert( Abc_ObjFanoutNum(pOld) > 0 ); - // look at the fanouts of old node - Abc_NodeCollectFanouts( pOld, pMan->vNodes ); - Vec_PtrForEachEntry( pMan->vNodes, pFanout, k ) - { - if ( Abc_ObjIsCo(pFanout) ) - { - Abc_ObjPatchFanin( pFanout, pOld, pNew ); - continue; - } - // find the old node as a fanin of this fanout - iFanin = Vec_IntFind( &pFanout->vFanins, pOld->Id ); - assert( iFanin == 0 || iFanin == 1 ); - // get the new fanin - pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) ); - assert( Abc_ObjRegular(pFanin1) != pFanout ); - // get another fanin - pFanin2 = Abc_ObjChild( pFanout, iFanin ^ 1 ); - assert( Abc_ObjRegular(pFanin2) != pFanout ); - // check if the node with these fanins exists - if ( (pFanoutNew = Abc_AigAndLookup( pMan, pFanin1, pFanin2 )) ) - { // such node exists (it may be a constant) - // schedule replacement of the old fanout by the new fanout - Vec_PtrPush( pMan->vStackReplaceOld, pFanout ); - Vec_PtrPush( pMan->vStackReplaceNew, pFanoutNew ); - continue; - } - // such node does not exist - modify the old fanout node - // (this way the change will not propagate all the way to the COs) - assert( Abc_ObjRegular(pFanin1) != Abc_ObjRegular(pFanin2) ); - - // if the node is in the level structure, remove it - if ( pFanout->fMarkA ) - Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout ); - // if the node is in the level structure, remove it - if ( pFanout->fMarkB ) - Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanout ); - - // remove the old fanout node from the structural hashing table - Abc_AigAndDelete( pMan, pFanout ); - // remove the fanins of the old fanout - Abc_ObjRemoveFanins( pFanout ); - // recreate the old fanout with new fanins and add it to the table - Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout ); - assert( Abc_AigNodeIsAcyclic(pFanout, pFanout) ); - - if ( fUpdateLevel ) - { - // schedule the updated fanout for updating direct level - assert( pFanout->fMarkA == 0 ); - pFanout->fMarkA = 1; - Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout ); - // schedule the updated fanout for updating reverse level - if ( pMan->pNtkAig->vLevelsR ) - { - assert( pFanout->fMarkB == 0 ); - pFanout->fMarkB = 1; - Vec_VecPush( pMan->vLevelsR, Abc_ObjReverseLevel(pFanout), pFanout ); - } - } - - // the fanout has changed, update EXOR status of its fanouts - Abc_ObjForEachFanout( pFanout, pFanoutFanout, v ) - if ( Abc_AigNodeIsAnd(pFanoutFanout) ) - pFanoutFanout->fExor = Abc_NodeIsExorType(pFanoutFanout); - } - // if the node has no fanouts left, remove its MFFC - if ( Abc_ObjFanoutNum(pOld) == 0 ) - Abc_AigDeleteNode( pMan, pOld ); -} - -/**Function************************************************************* - - Synopsis [Performs internal deletion step.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pNode0, * pNode1, * pTemp; - int i, k; - - // make sure the node is regular and dangling - assert( !Abc_ObjIsComplement(pNode) ); - assert( Abc_ObjIsNode(pNode) ); - assert( Abc_ObjFaninNum(pNode) == 2 ); - assert( Abc_ObjFanoutNum(pNode) == 0 ); - - // when deleting an old node that is scheduled for replacement, remove it from the replacement queue - Vec_PtrForEachEntry( pMan->vStackReplaceOld, pTemp, i ) - if ( pNode == pTemp ) - { - // remove the entry from the replacement array - for ( k = i; k < pMan->vStackReplaceOld->nSize - 1; k++ ) - { - pMan->vStackReplaceOld->pArray[k] = pMan->vStackReplaceOld->pArray[k+1]; - pMan->vStackReplaceNew->pArray[k] = pMan->vStackReplaceNew->pArray[k+1]; - } - pMan->vStackReplaceOld->nSize--; - pMan->vStackReplaceNew->nSize--; - } - - // when deleting a new node that should replace another node, do not delete - Vec_PtrForEachEntry( pMan->vStackReplaceNew, pTemp, i ) - if ( pNode == Abc_ObjRegular(pTemp) ) - return; - - // remember the node's fanins - pNode0 = Abc_ObjFanin0( pNode ); - pNode1 = Abc_ObjFanin1( pNode ); - - // add the node to the list of updated nodes - if ( pMan->vUpdatedNets ) - { - Vec_PtrPushUnique( pMan->vUpdatedNets, pNode0 ); - Vec_PtrPushUnique( pMan->vUpdatedNets, pNode1 ); - } - - // remove the node from the table - Abc_AigAndDelete( pMan, pNode ); - // if the node is in the level structure, remove it - if ( pNode->fMarkA ) - Abc_AigRemoveFromLevelStructure( pMan->vLevels, pNode ); - if ( pNode->fMarkB ) - Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pNode ); - // remove the node from the network - Abc_NtkDeleteObj( pNode ); - - // call recursively for the fanins - if ( Abc_ObjIsNode(pNode0) && pNode0->vFanouts.nSize == 0 ) - Abc_AigDeleteNode( pMan, pNode0 ); - if ( Abc_ObjIsNode(pNode1) && pNode1->vFanouts.nSize == 0 ) - Abc_AigDeleteNode( pMan, pNode1 ); -} - - -/**Function************************************************************* - - Synopsis [Updates the level of the node after it has changed.] - - Description [This procedure is based on the observation that - after the node's level has changed, the fanouts levels can change too, - but the new fanout levels are always larger than the node's level. - As a result, we can accumulate the nodes to be updated in the queue - and process them in the increasing order of levels.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ) -{ - Abc_Obj_t * pNode, * pFanout; - Vec_Ptr_t * vVec; - int LevelNew, i, k, v; - - // go through the nodes and update the level of their fanouts - Vec_VecForEachLevel( pMan->vLevels, vVec, i ) - { - if ( Vec_PtrSize(vVec) == 0 ) - continue; - Vec_PtrForEachEntry( vVec, pNode, k ) - { - if ( pNode == NULL ) - continue; - assert( Abc_ObjIsNode(pNode) ); - assert( (int)pNode->Level == i ); - // clean the mark - assert( pNode->fMarkA == 1 ); - pNode->fMarkA = 0; - // iterate through the fanouts - Abc_ObjForEachFanout( pNode, pFanout, v ) - { - if ( Abc_ObjIsCo(pFanout) ) - continue; - // get the new level of this fanout - LevelNew = 1 + ABC_MAX( Abc_ObjFanin0(pFanout)->Level, Abc_ObjFanin1(pFanout)->Level ); - assert( LevelNew > i ); - if ( (int)pFanout->Level == LevelNew ) // no change - continue; - // if the fanout is present in the data structure, pull it out - if ( pFanout->fMarkA ) - Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout ); - // update the fanout level - pFanout->Level = LevelNew; - // add the fanout to the data structure to update its fanouts - assert( pFanout->fMarkA == 0 ); - pFanout->fMarkA = 1; - Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout ); - } - } - Vec_PtrClear( vVec ); - } -} - -/**Function************************************************************* - - Synopsis [Updates the level of the node after it has changed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ) -{ - Abc_Obj_t * pNode, * pFanin, * pFanout; - Vec_Ptr_t * vVec; - int LevelNew, i, k, v, j; - - // go through the nodes and update the level of their fanouts - Vec_VecForEachLevel( pMan->vLevelsR, vVec, i ) - { - if ( Vec_PtrSize(vVec) == 0 ) - continue; - Vec_PtrForEachEntry( vVec, pNode, k ) - { - if ( pNode == NULL ) - continue; - assert( Abc_ObjIsNode(pNode) ); - assert( Abc_ObjReverseLevel(pNode) == i ); - // clean the mark - assert( pNode->fMarkB == 1 ); - pNode->fMarkB = 0; - // iterate through the fanins - Abc_ObjForEachFanin( pNode, pFanin, v ) - { - if ( Abc_ObjIsCi(pFanin) ) - continue; - // get the new reverse level of this fanin - LevelNew = 0; - Abc_ObjForEachFanout( pFanin, pFanout, j ) - if ( LevelNew < Abc_ObjReverseLevel(pFanout) ) - LevelNew = Abc_ObjReverseLevel(pFanout); - LevelNew += 1; - assert( LevelNew > i ); - if ( Abc_ObjReverseLevel(pFanin) == LevelNew ) // no change - continue; - // if the fanin is present in the data structure, pull it out - if ( pFanin->fMarkB ) - Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanin ); - // update the reverse level - Abc_ObjSetReverseLevel( pFanin, LevelNew ); - // add the fanin to the data structure to update its fanins - assert( pFanin->fMarkB == 0 ); - pFanin->fMarkB = 1; - Vec_VecPush( pMan->vLevelsR, LevelNew, pFanin ); - } - } - Vec_PtrClear( vVec ); - } -} - -/**Function************************************************************* - - Synopsis [Removes the node from the level structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vVecTemp; - Abc_Obj_t * pTemp; - int m; - assert( pNode->fMarkA ); - vVecTemp = Vec_VecEntry( vStruct, pNode->Level ); - Vec_PtrForEachEntry( vVecTemp, pTemp, m ) - { - if ( pTemp != pNode ) - continue; - Vec_PtrWriteEntry( vVecTemp, m, NULL ); - break; - } - assert( m < Vec_PtrSize(vVecTemp) ); // found - pNode->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Removes the node from the level structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vVecTemp; - Abc_Obj_t * pTemp; - int m; - assert( pNode->fMarkB ); - vVecTemp = Vec_VecEntry( vStruct, Abc_ObjReverseLevel(pNode) ); - Vec_PtrForEachEntry( vVecTemp, pTemp, m ) - { - if ( pTemp != pNode ) - continue; - Vec_PtrWriteEntry( vVecTemp, m, NULL ); - break; - } - assert( m < Vec_PtrSize(vVecTemp) ); // found - pNode->fMarkB = 0; -} - - - - -/**Function************************************************************* - - Synopsis [Returns 1 if the node has at least one complemented fanout.] - - Description [A fanout is complemented if the fanout's fanin edge pointing - to the given node is complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanout; - int i, iFanin; - Abc_ObjForEachFanout( pNode, pFanout, i ) - { - iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); - assert( iFanin >= 0 ); - if ( Abc_ObjFaninC( pFanout, iFanin ) ) - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node has at least one complemented fanout.] - - Description [A fanout is complemented if the fanout's fanin edge pointing - to the given node is complemented. Only the fanouts with current TravId - are counted.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanout; - int i, iFanin; - Abc_ObjForEachFanout( pNode, pFanout, i ) - { - if ( !Abc_NodeIsTravIdCurrent(pFanout) ) - continue; - iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); - assert( iFanin >= 0 ); - if ( Abc_ObjFaninC( pFanout, iFanin ) ) - return 1; - } - return 0; -} - - -/**Function************************************************************* - - Synopsis [Prints the AIG node for debugging purposes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigPrintNode( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pNodeR = Abc_ObjRegular(pNode); - if ( Abc_ObjIsCi(pNodeR) ) - { - printf( "CI %4s%s.\n", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" ); - return; - } - if ( Abc_AigNodeIsConst(pNodeR) ) - { - printf( "Constant 1 %s.\n", Abc_ObjIsComplement(pNode)? "(complemented)" : "" ); - return; - } - // print the node's function - printf( "%7s%s", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" ); - printf( " = " ); - printf( "%7s%s", Abc_ObjName(Abc_ObjFanin0(pNodeR)), Abc_ObjFaninC0(pNodeR)? "\'" : "" ); - printf( " * " ); - printf( "%7s%s", Abc_ObjName(Abc_ObjFanin1(pNodeR)), Abc_ObjFaninC1(pNodeR)? "\'" : "" ); - printf( "\n" ); -} - - -/**Function************************************************************* - - Synopsis [Check if the node has a combination loop of depth 1 or 2.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ) -{ - Abc_Obj_t * pFanin0, * pFanin1; - Abc_Obj_t * pChild00, * pChild01; - Abc_Obj_t * pChild10, * pChild11; - if ( !Abc_AigNodeIsAnd(pNode) ) - return 1; - pFanin0 = Abc_ObjFanin0(pNode); - pFanin1 = Abc_ObjFanin1(pNode); - if ( pRoot == pFanin0 || pRoot == pFanin1 ) - return 0; - if ( Abc_ObjIsCi(pFanin0) ) - { - pChild00 = NULL; - pChild01 = NULL; - } - else - { - pChild00 = Abc_ObjFanin0(pFanin0); - pChild01 = Abc_ObjFanin1(pFanin0); - if ( pRoot == pChild00 || pRoot == pChild01 ) - return 0; - } - if ( Abc_ObjIsCi(pFanin1) ) - { - pChild10 = NULL; - pChild11 = NULL; - } - else - { - pChild10 = Abc_ObjFanin0(pFanin1); - pChild11 = Abc_ObjFanin1(pFanin1); - if ( pRoot == pChild10 || pRoot == pChild11 ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Resizes the hash table of AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan ) -{ - Abc_Obj_t * pEnt; - int i; - for ( i = 0; i < pMan->nBins; i++ ) - Abc_AigBinForEachEntry( pMan->pBins[i], pEnt ) - { - if ( Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id > Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id ) - { -// int i0 = Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id; -// int i1 = Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id; - printf( "Node %d has incorrect ordering of fanins.\n", pEnt->Id ); - } - } -} - -/**Function************************************************************* - - Synopsis [Sets the correct phase of the nodes.] - - Description [The AIG nodes should be in the DFS order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - assert( Abc_NtkIsDfsOrdered(pNtk) ); - Abc_AigConst1(pNtk)->fPhase = 1; - Abc_NtkForEachPi( pNtk, pObj, i ) - pObj->fPhase = 0; - Abc_NtkForEachLatchOutput( pNtk, pObj, i ) - pObj->fPhase = Abc_LatchIsInit1(pObj); - Abc_AigForEachAnd( pNtk, pObj, i ) - pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)) & (Abc_ObjFanin1(pObj)->fPhase ^ Abc_ObjFaninC1(pObj)); - Abc_NtkForEachPo( pNtk, pObj, i ) - pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)); - Abc_NtkForEachLatchInput( pNtk, pObj, i ) - pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)); -} - - - -/**Function************************************************************* - - Synopsis [Start the update list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets ) -{ - assert( pMan->vAddedCells == NULL ); - pMan->vAddedCells = Vec_PtrAlloc( 1000 ); - pMan->vUpdatedNets = Vec_PtrAlloc( 1000 ); - *pvUpdatedNets = pMan->vUpdatedNets; - return pMan->vAddedCells; -} - -/**Function************************************************************* - - Synopsis [Start the update list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigUpdateStop( Abc_Aig_t * pMan ) -{ - assert( pMan->vAddedCells != NULL ); - Vec_PtrFree( pMan->vAddedCells ); - Vec_PtrFree( pMan->vUpdatedNets ); - pMan->vAddedCells = NULL; - pMan->vUpdatedNets = NULL; -} - -/**Function************************************************************* - - Synopsis [Start the update list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigUpdateReset( Abc_Aig_t * pMan ) -{ - assert( pMan->vAddedCells != NULL ); - Vec_PtrClear( pMan->vAddedCells ); - Vec_PtrClear( pMan->vUpdatedNets ); -} - -/**Function************************************************************* - - Synopsis [Start the update list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_AigCountNext( Abc_Aig_t * pMan ) -{ - Abc_Obj_t * pAnd; - int i, Counter = 0, CounterTotal = 0; - // count how many nodes have pNext set - for ( i = 0; i < pMan->nBins; i++ ) - Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) - { - Counter += (pAnd->pNext != NULL); - CounterTotal++; - } - printf( "Counter = %d. Nodes = %d. Ave = %6.2f\n", Counter, CounterTotal, 1.0 * CounterTotal/pMan->nBins ); - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcBlifMv.c b/src/base/abc/abcBlifMv.c deleted file mode 100644 index 48ec58c0..00000000 --- a/src/base/abc/abcBlifMv.c +++ /dev/null @@ -1,970 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcBlifMv.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures to process BLIF-MV networks and AIGs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the Mv-Var manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ) -{ - Vec_Att_t * pAttMan; - assert( Abc_NtkMvVar(pNtk) == NULL ); - pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, Extra_MmFlexStart(), Extra_MmFlexStop, NULL, NULL ); - Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_MVVAR, pAttMan ); -//printf( "allocing attr\n" ); -} - -/**Function************************************************************* - - Synopsis [Stops the Mv-Var manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ) -{ - void * pUserMan; - pUserMan = Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, 0 ); - Extra_MmFlexStop( pUserMan ); -} - -/**Function************************************************************* - - Synopsis [Duplicate the MV variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues ) -{ - Extra_MmFlex_t * pFlex; - struct temp - { - int nValues; - char ** pNames; - } * pVarStruct; - assert( nValues > 1 ); - // skip binary signals - if ( nValues == 2 ) - return; - // skip already assigned signals - if ( Abc_ObjMvVar(pObj) != NULL ) - return; - // create the structure - pFlex = Abc_NtkMvVarMan( pObj->pNtk ); - pVarStruct = (void *)Extra_MmFlexEntryFetch( pFlex, sizeof(struct temp) ); - pVarStruct->nValues = nValues; - pVarStruct->pNames = NULL; - Abc_ObjSetMvVar( pObj, pVarStruct ); -} - -/**Function************************************************************* - - Synopsis [Strashes the BLIF-MV netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Abc_StringGetNumber( char ** ppStr ) -{ - char * pStr = *ppStr; - int Number = 0; - assert( *pStr >= '0' && *pStr <= '9' ); - for ( ; *pStr >= '0' && *pStr <= '9'; pStr++ ) - Number = 10 * Number + *pStr - '0'; - *ppStr = pStr; - return Number; -} - -/**Function************************************************************* - - Synopsis [Strashes one node in the BLIF-MV netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeStrashBlifMv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) -{ - char * pSop; - Abc_Obj_t ** pValues, ** pValuesF, ** pValuesF2; - Abc_Obj_t * pTemp, * pTemp2, * pFanin, * pFanin2, * pNet; - int k, v, Def, DefIndex, Index, nValues, nValuesF, nValuesF2; - - // start the output values - assert( Abc_ObjIsNode(pObj) ); - pNet = Abc_ObjFanout0(pObj); - nValues = Abc_ObjMvVarNum(pNet); - pValues = ALLOC( Abc_Obj_t *, nValues ); - for ( k = 0; k < nValues; k++ ) - pValues[k] = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); - - // get the BLIF-MV formula - pSop = pObj->pData; - // skip the value line -// while ( *pSop++ != '\n' ); - - // handle the constant - if ( Abc_ObjFaninNum(pObj) == 0 ) - { - // skip the default if present - if ( *pSop == 'd' ) - while ( *pSop++ != '\n' ); - // skip space if present - if ( *pSop == ' ' ) - pSop++; - Index = Abc_StringGetNumber( &pSop ); - assert( Index < nValues ); - pValues[Index] = Abc_AigConst1(pNtkNew); - // save the values in the fanout net - pNet->pCopy = (Abc_Obj_t *)pValues; - return 1; - } - - // parse the default line - Def = DefIndex = -1; - if ( *pSop == 'd' ) - { - pSop++; - if ( *pSop == '=' ) - { - pSop++; - DefIndex = Abc_StringGetNumber( &pSop ); - assert( DefIndex < Abc_ObjFaninNum(pObj) ); - } - else if ( *pSop == '-' ) - { - pSop++; - Def = 0; - } - else - { - Def = Abc_StringGetNumber( &pSop ); - assert( Def < nValues ); - } - assert( *pSop == '\n' ); - pSop++; - } - - // convert the values - while ( *pSop ) - { - // extract the values for each cube - pTemp = Abc_AigConst1(pNtkNew); - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - if ( *pSop == '-' ) - { - pSop += 2; - continue; - } - if ( *pSop == '!' ) - { - printf( "Abc_NodeStrashBlifMv(): Cannot handle complement in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); - return 0; - } - if ( *pSop == '{' ) - { - printf( "Abc_NodeStrashBlifMv(): Cannot handle braces in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); - return 0; - } - // get the value set - nValuesF = Abc_ObjMvVarNum(pFanin); - pValuesF = (Abc_Obj_t **)pFanin->pCopy; - if ( *pSop == '(' ) - { - pSop++; - pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); - while ( *pSop != ')' ) - { - Index = Abc_StringGetNumber( &pSop ); - assert( Index < nValuesF ); - pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, pValuesF[Index] ); - assert( *pSop == ')' || *pSop == ',' ); - if ( *pSop == ',' ) - pSop++; - } - assert( *pSop == ')' ); - pSop++; - } - else if ( *pSop == '=' ) - { - pSop++; - // get the fanin index - Index = Abc_StringGetNumber( &pSop ); - assert( Index < Abc_ObjFaninNum(pObj) ); - assert( Index != k ); - // get the fanin - pFanin2 = Abc_ObjFanin( pObj, Index ); - nValuesF2 = Abc_ObjMvVarNum(pFanin2); - pValuesF2 = (Abc_Obj_t **)pFanin2->pCopy; - // create the sum of products of values - assert( nValuesF == nValuesF2 ); - pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); - for ( v = 0; v < nValues; v++ ) - pTemp2 = Abc_AigOr( pNtkNew->pManFunc, pTemp2, Abc_AigAnd(pNtkNew->pManFunc, pValuesF[v], pValuesF2[v]) ); - } - else - { - Index = Abc_StringGetNumber( &pSop ); - assert( Index < nValuesF ); - pTemp2 = pValuesF[Index]; - } - // compute the compute - pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, pTemp2 ); - // advance the reading point - assert( *pSop == ' ' ); - pSop++; - } - // check if the output value is an equal construct - if ( *pSop == '=' ) - { - pSop++; - // get the output value - Index = Abc_StringGetNumber( &pSop ); - assert( Index < Abc_ObjFaninNum(pObj) ); - // add values of the given fanin with the given cube - pFanin = Abc_ObjFanin( pObj, Index ); - nValuesF = Abc_ObjMvVarNum(pFanin); - pValuesF = (Abc_Obj_t **)pFanin->pCopy; - assert( nValuesF == nValues ); // should be guaranteed by the parser - for ( k = 0; k < nValuesF; k++ ) - pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) ); - } - else - { - // get the output value - Index = Abc_StringGetNumber( &pSop ); - assert( Index < nValues ); - pValues[Index] = Abc_AigOr( pNtkNew->pManFunc, pValues[Index], pTemp ); - } - // advance the reading point - assert( *pSop == '\n' ); - pSop++; - } - - // compute the default value - if ( Def >= 0 || DefIndex >= 0 ) - { - pTemp = Abc_AigConst1(pNtkNew); - for ( k = 0; k < nValues; k++ ) - { - if ( k == Def ) - continue; - pTemp = Abc_AigAnd( pNtkNew->pManFunc, pTemp, Abc_ObjNot(pValues[k]) ); - } - - // assign the default value - if ( Def >= 0 ) - pValues[Def] = pTemp; - else - { - assert( DefIndex >= 0 ); - // add values of the given fanin with the given cube - pFanin = Abc_ObjFanin( pObj, DefIndex ); - nValuesF = Abc_ObjMvVarNum(pFanin); - pValuesF = (Abc_Obj_t **)pFanin->pCopy; - assert( nValuesF == nValues ); // should be guaranteed by the parser - for ( k = 0; k < nValuesF; k++ ) - pValues[k] = Abc_AigOr( pNtkNew->pManFunc, pValues[k], Abc_AigAnd(pNtkNew->pManFunc, pTemp, pValuesF[k]) ); - } - - } - - // save the values in the fanout net - pNet->pCopy = (Abc_Obj_t *)pValues; - return 1; -} - -/**Function************************************************************* - - Synopsis [Assigns name with index.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index ) -{ - char Suffix[16]; - assert( Abc_ObjIsTerm(pObj) ); - assert( Abc_ObjIsNet(pNet) ); - sprintf( Suffix, "[%d]", Index ); - Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix ); -} - -/**Function************************************************************* - - Synopsis [Strashes the BLIF-MV netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ) -{ - int fUsePositional = 0; - Vec_Ptr_t * vNodes; - Abc_Obj_t ** pBits; - Abc_Obj_t ** pValues; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pTemp, * pBit, * pNet; - int i, k, v, nValues, nValuesMax, nBits; - - assert( Abc_NtkIsNetlist(pNtk) ); - assert( Abc_NtkHasBlifMv(pNtk) ); - assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); - assert( Abc_NtkBlackboxNum(pNtk) == 0 ); - - // get the largest number of values - nValuesMax = 2; - Abc_NtkForEachNet( pNtk, pObj, i ) - { - nValues = Abc_ObjMvVarNum(pObj); - if ( nValuesMax < nValues ) - nValuesMax = nValues; - } - nBits = Extra_Base2Log( nValuesMax ); - pBits = ALLOC( Abc_Obj_t *, nBits ); - - // clean the node copy fields - Abc_NtkCleanCopy( pNtk ); - // collect the nodes - vNodes = Abc_NtkDfs( pNtk, 0 ); - - // start the network - pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - // duplicate the name and the spec - pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); -// pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName ); - - // encode the CI nets - Abc_NtkIncrementTravId( pNtk ); - if ( fUsePositional ) - { - Abc_NtkForEachCi( pNtk, pObj, i ) - { - pNet = Abc_ObjFanout0(pObj); - nValues = Abc_ObjMvVarNum(pNet); - pValues = ALLOC( Abc_Obj_t *, nValues ); - // create PIs for the values - for ( v = 0; v < nValues; v++ ) - { - pValues[v] = Abc_NtkCreatePi( pNtkNew ); - Abc_NtkConvertAssignName( pValues[v], pNet, v ); - } - // save the values in the fanout net - pNet->pCopy = (Abc_Obj_t *)pValues; - // mark the net - Abc_NodeSetTravIdCurrent( pNet ); - } - } - else - { - Abc_NtkForEachCi( pNtk, pObj, i ) - { - pNet = Abc_ObjFanout0(pObj); - nValues = Abc_ObjMvVarNum(pNet); - pValues = ALLOC( Abc_Obj_t *, nValues ); - // create PIs for the encoding bits - nBits = Extra_Base2Log( nValues ); - for ( k = 0; k < nBits; k++ ) - { - pBits[k] = Abc_NtkCreatePi( pNtkNew ); - Abc_NtkConvertAssignName( pBits[k], pNet, k ); - } - // encode the values - for ( v = 0; v < nValues; v++ ) - { - pValues[v] = Abc_AigConst1(pNtkNew); - for ( k = 0; k < nBits; k++ ) - { - pBit = Abc_ObjNotCond( pBits[k], (v&(1<pManFunc, pValues[v], pBit ); - } - } - // save the values in the fanout net - pNet->pCopy = (Abc_Obj_t *)pValues; - // mark the net - Abc_NodeSetTravIdCurrent( pNet ); - } - } - - // process nodes in the topological order - Vec_PtrForEachEntry( vNodes, pObj, i ) - if ( !Abc_NodeStrashBlifMv( pNtkNew, pObj ) ) - { - Abc_NtkDelete( pNtkNew ); - return NULL; - } - Vec_PtrFree( vNodes ); - - // encode the CO nets - if ( fUsePositional ) - { - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pNet = Abc_ObjFanin0(pObj); - // skip marked nets - if ( Abc_NodeIsTravIdCurrent(pNet) ) - continue; - Abc_NodeSetTravIdCurrent( pNet ); - nValues = Abc_ObjMvVarNum(pNet); - pValues = (Abc_Obj_t **)pNet->pCopy; - for ( v = 0; v < nValues; v++ ) - { - pTemp = Abc_NtkCreatePo( pNtkNew ); - Abc_ObjAddFanin( pTemp, pValues[v] ); - Abc_NtkConvertAssignName( pTemp, pNet, v ); - } - } - } - else - { - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pNet = Abc_ObjFanin0(pObj); - // skip marked nets - if ( Abc_NodeIsTravIdCurrent(pNet) ) - continue; - Abc_NodeSetTravIdCurrent( pNet ); - nValues = Abc_ObjMvVarNum(pNet); - pValues = (Abc_Obj_t **)pNet->pCopy; - nBits = Extra_Base2Log( nValues ); - for ( k = 0; k < nBits; k++ ) - { - pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); - for ( v = 0; v < nValues; v++ ) - if ( v & (1<pManFunc, pBit, pValues[v] ); - pTemp = Abc_NtkCreatePo( pNtkNew ); - Abc_ObjAddFanin( pTemp, pBit ); - Abc_NtkConvertAssignName( pTemp, pNet, k ); - } - } - } - - // cleanup - free( pBits ); - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( pObj->pCopy ) - free( pObj->pCopy ); - - // remove dangling nodes - i = Abc_AigCleanup(pNtkNew->pManFunc); -// printf( "Cleanup removed %d nodes.\n", i ); -// Abc_NtkReassignIds( pNtkNew ); - - // check integrity - if ( !Abc_NtkCheck( pNtkNew ) ) - { - fprintf( stdout, "Abc_NtkStrashBlifMv(): Network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Extract the MV-skeleton of the BLIF-MV network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkSkeletonBlifMv( Abc_Ntk_t * pNtk ) -{ - int fUsePositional = 0; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pNet, * pNetNew, * pNodeNew, * pTermNew, * pBoxNew; - int i, k, v, nValues, nBits; - - assert( Abc_NtkIsNetlist(pNtk) ); - assert( Abc_NtkHasBlifMv(pNtk) ); - assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); - assert( Abc_NtkBlackboxNum(pNtk) == 0 ); - - // clean the node copy fields - Abc_NtkCleanCopy( pNtk ); - - // start the network - pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); - // duplicate the name and the spec - pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); - pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName ); - // create the internal box (it is important to put it first!) - pBoxNew = Abc_NtkCreateWhitebox( pNtkNew ); - // create PIs and their nets - Abc_NtkForEachPi( pNtk, pObj, i ) - { - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - pNet = Abc_ObjFanout0(pObj); - Abc_NtkDupObj( pNtkNew, pNet, 1 ); - Abc_ObjAddFanin( pNet->pCopy, pObj->pCopy ); - } - // create POs and their nets - Abc_NtkForEachPo( pNtk, pObj, i ) - { - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - pNet = Abc_ObjFanin0(pObj); - if ( pNet->pCopy == NULL ) - Abc_NtkDupObj( pNtkNew, pNet, 1 ); - Abc_ObjAddFanin( pObj->pCopy, pNet->pCopy ); - } - // create latches - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - Abc_NtkDupBox( pNtkNew, pObj, 0 ); - // latch outputs - pNet = Abc_ObjFanout0(Abc_ObjFanout0(pObj)); - assert( pNet->pCopy == NULL ); - Abc_NtkDupObj( pNtkNew, pNet, 1 ); - Abc_ObjAddFanin( pNet->pCopy, Abc_ObjFanout0(pObj)->pCopy ); - // latch inputs - pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); - if ( pNet->pCopy == NULL ) - Abc_NtkDupObj( pNtkNew, pNet, 1 ); - Abc_ObjAddFanin( Abc_ObjFanin0(pObj)->pCopy, pNet->pCopy ); - } - - // encode the CI nets - Abc_NtkIncrementTravId( pNtk ); - if ( fUsePositional ) - { - Abc_NtkForEachCi( pNtk, pObj, i ) - { - pNet = Abc_ObjFanout0(pObj); - nValues = Abc_ObjMvVarNum(pNet); - for ( v = 0; v < nValues; v++ ) - { - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - pNodeNew->pData = Abc_SopEncoderPos( pNtkNew->pManFunc, v, nValues ); - pNetNew = Abc_NtkCreateNet( pNtkNew ); - pTermNew = Abc_NtkCreateBi( pNtkNew ); - Abc_ObjAddFanin( pNodeNew, pNet->pCopy ); - Abc_ObjAddFanin( pNetNew, pNodeNew ); - Abc_ObjAddFanin( pTermNew, pNetNew ); - Abc_ObjAddFanin( pBoxNew, pTermNew ); - } - // mark the net - Abc_NodeSetTravIdCurrent( pNet ); - } - } - else - { - Abc_NtkForEachCi( pNtk, pObj, i ) - { - pNet = Abc_ObjFanout0(pObj); - nValues = Abc_ObjMvVarNum(pNet); - nBits = Extra_Base2Log( nValues ); - for ( k = 0; k < nBits; k++ ) - { - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - pNodeNew->pData = Abc_SopEncoderLog( pNtkNew->pManFunc, k, nValues ); - pNetNew = Abc_NtkCreateNet( pNtkNew ); - pTermNew = Abc_NtkCreateBi( pNtkNew ); - Abc_ObjAddFanin( pNodeNew, pNet->pCopy ); - Abc_ObjAddFanin( pNetNew, pNodeNew ); - Abc_ObjAddFanin( pTermNew, pNetNew ); - Abc_ObjAddFanin( pBoxNew, pTermNew ); - } - // mark the net - Abc_NodeSetTravIdCurrent( pNet ); - } - } - - // encode the CO nets - if ( fUsePositional ) - { - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pNet = Abc_ObjFanin0(pObj); - // skip marked nets - if ( Abc_NodeIsTravIdCurrent(pNet) ) - continue; - Abc_NodeSetTravIdCurrent( pNet ); - nValues = Abc_ObjMvVarNum(pNet); - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - pNodeNew->pData = Abc_SopDecoderPos( pNtkNew->pManFunc, nValues ); - for ( v = 0; v < nValues; v++ ) - { - pTermNew = Abc_NtkCreateBo( pNtkNew ); - pNetNew = Abc_NtkCreateNet( pNtkNew ); - Abc_ObjAddFanin( pTermNew, pBoxNew ); - Abc_ObjAddFanin( pNetNew, pTermNew ); - Abc_ObjAddFanin( pNodeNew, pNetNew ); - } - Abc_ObjAddFanin( pNet->pCopy, pNodeNew ); - } - } - else - { - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pNet = Abc_ObjFanin0(pObj); - // skip marked nets - if ( Abc_NodeIsTravIdCurrent(pNet) ) - continue; - Abc_NodeSetTravIdCurrent( pNet ); - nValues = Abc_ObjMvVarNum(pNet); - nBits = Extra_Base2Log( nValues ); - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - pNodeNew->pData = Abc_SopDecoderLog( pNtkNew->pManFunc, nValues ); - for ( k = 0; k < nBits; k++ ) - { - pTermNew = Abc_NtkCreateBo( pNtkNew ); - pNetNew = Abc_NtkCreateNet( pNtkNew ); - Abc_ObjAddFanin( pTermNew, pBoxNew ); - Abc_ObjAddFanin( pNetNew, pTermNew ); - Abc_ObjAddFanin( pNodeNew, pNetNew ); - } - Abc_ObjAddFanin( pNet->pCopy, pNodeNew ); - } - } - - // if it is a BLIF-MV netlist transfer the values of all nets - if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) - { - if ( Abc_NtkMvVar( pNtkNew ) == NULL ) - Abc_NtkStartMvVars( pNtkNew ); - Abc_NtkForEachNet( pNtk, pObj, i ) - if ( pObj->pCopy ) - Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); - } - - // check integrity - if ( !Abc_NtkCheck( pNtkNew ) ) - { - fprintf( stdout, "Abc_NtkSkeletonBlifMv(): Network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Inserts processed network into original base MV network.] - - Description [The original network remembers the interface of combinational - logic (PIs/POs/latches names and values). The processed network may - be binary or multi-valued (currently, multi-value is not supported). - The resulting network has the same interface as the original network - while the internal logic is the same as that of the processed network.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic ) -{ - Abc_Ntk_t * pNtkSkel, * pNtkNew; - Abc_Obj_t * pBox; - - assert( Abc_NtkIsNetlist(pNtkBase) ); - assert( Abc_NtkHasBlifMv(pNtkBase) ); - assert( Abc_NtkWhiteboxNum(pNtkBase) == 0 ); - assert( Abc_NtkBlackboxNum(pNtkBase) == 0 ); - - assert( Abc_NtkIsNetlist(pNtkLogic) ); - assert( Abc_NtkHasBlifMv(pNtkLogic) ); - assert( Abc_NtkWhiteboxNum(pNtkLogic) == 0 ); - assert( Abc_NtkBlackboxNum(pNtkLogic) == 0 ); - - // extract the skeleton of the old network - pNtkSkel = Abc_NtkSkeletonBlifMv( pNtkBase ); - - // set the implementation of the box to be the same as the processed network - assert( Abc_NtkWhiteboxNum(pNtkSkel) == 1 ); - pBox = Abc_NtkBox( pNtkSkel, 0 ); - assert( Abc_ObjIsWhitebox(pBox) ); - assert( pBox->pData == NULL ); - assert( Abc_ObjFaninNum(pBox) == Abc_NtkPiNum(pNtkLogic) ); - assert( Abc_ObjFanoutNum(pBox) == Abc_NtkPoNum(pNtkLogic) ); - pBox->pData = pNtkLogic; - - // flatten the hierarchy to insert the processed network - pNtkNew = Abc_NtkFlattenLogicHierarchy( pNtkSkel ); - pBox->pData = NULL; - Abc_NtkDelete( pNtkSkel ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Converts SOP netlist into BLIF-MV netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk ) -{ - Extra_MmFlex_t * pMmFlex; - Abc_Obj_t * pNode; - Vec_Str_t * vCube; - char * pSop0, * pSop1, * pBlifMv, * pCube, * pCur; - int Value, nCubes, nSize, i, k; - - assert( Abc_NtkIsNetlist(pNtk) ); - if ( !Abc_NtkToBdd(pNtk) ) - { - printf( "Converting logic functions to BDDs has failed.\n" ); - return 0; - } - - pMmFlex = Extra_MmFlexStart(); - vCube = Vec_StrAlloc( 100 ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // convert BDD into cubes for on-set and off-set - Abc_NodeBddToCnf( pNode, pMmFlex, vCube, 0, &pSop0, &pSop1 ); - // allocate room for the MV-SOP - nCubes = Abc_SopGetCubeNum(pSop0) + Abc_SopGetCubeNum(pSop1); - nSize = nCubes*(2*Abc_ObjFaninNum(pNode) + 2)+1; - pBlifMv = Extra_MmFlexEntryFetch( pMmFlex, nSize ); - // add the cubes - pCur = pBlifMv; - Abc_SopForEachCube( pSop0, Abc_ObjFaninNum(pNode), pCube ) - { - Abc_CubeForEachVar( pCube, Value, k ) - { - *pCur++ = Value; - *pCur++ = ' '; - } - *pCur++ = '0'; - *pCur++ = '\n'; - } - Abc_SopForEachCube( pSop1, Abc_ObjFaninNum(pNode), pCube ) - { - Abc_CubeForEachVar( pCube, Value, k ) - { - *pCur++ = Value; - *pCur++ = ' '; - } - *pCur++ = '1'; - *pCur++ = '\n'; - } - *pCur++ = 0; - assert( pCur - pBlifMv == nSize ); - // update the node representation - Cudd_RecursiveDeref( pNtk->pManFunc, pNode->pData ); - pNode->pData = pBlifMv; - } - - // update the functionality type - pNtk->ntkFunc = ABC_FUNC_BLIFMV; - Cudd_Quit( pNtk->pManFunc ); - pNtk->pManFunc = pMmFlex; - - Vec_StrFree( vCube ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Converts SOP into MV-SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) -{ - char * pMvSop, * pCur; - unsigned uCube; - int nCubes, nSize, Value, i, k; - // consider the case of the constant node - if ( Vec_IntSize(vSop0) == 0 || Vec_IntSize(vSop1) == 0 ) - { - // (temporary) create a tautology cube - pMvSop = ALLOC( char, nVars + 3 ); - for ( k = 0; k < nVars; k++ ) - pMvSop[k] = '-'; - pMvSop[nVars] = '0' + (int)(Vec_IntSize(vSop1) > 0); - pMvSop[nVars+1] = '\n'; - pMvSop[nVars+2] = 0; - return pMvSop; - } - // find the total number of cubes - nCubes = Vec_IntSize(vSop0) + Vec_IntSize(vSop1); - // find the size of the MVSOP represented as a C-string - // (each cube has nVars variables + one output literal + end-of-line, - // and the string is zero-terminated) - nSize = nCubes * (nVars + 2) + 1; - // allocate memory - pMvSop = pCur = ALLOC( char, nSize ); - // fill in the negative polarity cubes - Vec_IntForEachEntry( vSop0, uCube, i ) - { - for ( k = 0; k < nVars; k++ ) - { - Value = (uCube >> (2*k)) & 3; - if ( Value == 1 ) - *pCur++ = '0'; - else if ( Value == 2 ) - *pCur++ = '1'; - else if ( Value == 0 ) - *pCur++ = '-'; - else - assert( 0 ); - } - *pCur++ = '0'; - *pCur++ = '\n'; - } - // fill in the positive polarity cubes - Vec_IntForEachEntry( vSop1, uCube, i ) - { - for ( k = 0; k < nVars; k++ ) - { - Value = (uCube >> (2*k)) & 3; - if ( Value == 1 ) - *pCur++ = '0'; - else if ( Value == 2 ) - *pCur++ = '1'; - else if ( Value == 0 ) - *pCur++ = '-'; - else - assert( 0 ); - } - *pCur++ = '1'; - *pCur++ = '\n'; - } - *pCur++ = 0; - assert( pCur - pMvSop == nSize ); - return pMvSop; -} - - -/**Function************************************************************* - - Synopsis [A prototype of internal cost evaluation procedure.] - - Description [This procedure takes the number of variables (nVars), - the array of values of the inputs and the output (pVarValues) - (note that this array has nVars+1 entries), and an MV-SOP represented - as a C-string with one charater for each literal, including inputs - and output. Each cube is terminated with the new-line character ('\n'). - The string is zero-terminated.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeEvalMvCostInternal( int nVars, int * pVarValues, char * pMvSop ) -{ - // for now, return the number of cubes in the MV-SOP - int Counter = 0; - while ( *pMvSop ) Counter += (*pMvSop++ == '\n'); - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Evaluates the cost of the cut.] - - Description [The Boolean function of the cut is specified by two SOPs, - which represent the negative/positive polarities of the cut function. - Converts these two SOPs into a mutually-agreed-upon representation - to be passed to the internal cost-evaluation procedure (see the above - prototype Abc_NodeEvalMvCostInternal).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) -{ - char * pMvSop; - int * pVarValues; - int i, RetValue; - // collect the input and output values (currently, they are binary) - pVarValues = ALLOC( int, nVars + 1 ); - for ( i = 0; i <= nVars; i++ ) - pVarValues[i] = 2; - // prepare MV-SOP for evaluation - pMvSop = Abc_NodeConvertSopToMvSop( nVars, vSop0, vSop1 ); - // have a look at the MV-SOP: -// printf( "%s\n", pMvSop ); - // get the result of internal cost evaluation - RetValue = Abc_NodeEvalMvCostInternal( nVars, pVarValues, pMvSop ); - // cleanup - free( pVarValues ); - free( pMvSop ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcCheck.c b/src/base/abc/abcCheck.c deleted file mode 100644 index 3072e40f..00000000 --- a/src/base/abc/abcCheck.c +++ /dev/null @@ -1,939 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcCheck.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Consistency checking procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "main.h" -//#include "seq.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk ); -static bool Abc_NtkCheckPis( Abc_Ntk_t * pNtk ); -static bool Abc_NtkCheckPos( Abc_Ntk_t * pNtk ); -//static bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); -static bool Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ); -static bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); -static bool Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ); - -static bool Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); -static bool Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); -static bool Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); - -static inline char * Abc_ObjNameNet( Abc_Obj_t * pObj ) { return (Abc_ObjIsNode(pObj) && Abc_NtkIsNetlist(pObj->pNtk)) ? Abc_ObjName(Abc_ObjFanout0(pObj)) : Abc_ObjName(pObj); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks the integrity of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkCheck( Abc_Ntk_t * pNtk ) -{ - return !Abc_FrameIsFlagEnabled( "check" ) || Abc_NtkDoCheck( pNtk ); -} - -/**Function************************************************************* - - Synopsis [Checks the integrity of the network after reading.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkCheckRead( Abc_Ntk_t * pNtk ) -{ - return !Abc_FrameIsFlagEnabled( "checkread" ) || Abc_NtkDoCheck( pNtk ); -} - -/**Function************************************************************* - - Synopsis [Checks the integrity of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj, * pNet, * pNode; - int i; - - // check network types - if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) - { - fprintf( stdout, "NetworkCheck: Unknown network type.\n" ); - return 0; - } - if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasBlackbox(pNtk) ) - { - fprintf( stdout, "NetworkCheck: Unknown functionality type.\n" ); - return 0; - } - if ( Abc_NtkHasMapping(pNtk) ) - { - if ( pNtk->pManFunc != Abc_FrameReadLibGen() ) - { - fprintf( stdout, "NetworkCheck: The library of the mapped network is not the global library.\n" ); - return 0; - } - } - - if ( Abc_NtkHasOnlyLatchBoxes(pNtk) ) - { - // check CI/CO numbers - if ( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCiNum(pNtk) ) - { - fprintf( stdout, "NetworkCheck: Number of CIs does not match number of PIs and latches.\n" ); - fprintf( stdout, "One possible reason is that latches are added twice:\n" ); - fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" ); - return 0; - } - if ( Abc_NtkPoNum(pNtk) + Abc_NtkAssertNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCoNum(pNtk) ) - { - fprintf( stdout, "NetworkCheck: Number of COs does not match number of POs, asserts, and latches.\n" ); - fprintf( stdout, "One possible reason is that latches are added twice:\n" ); - fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" ); - return 0; - } - } - - // check the names - if ( !Abc_NtkCheckNames( pNtk ) ) - return 0; - - // check PIs and POs - Abc_NtkCleanCopy( pNtk ); - if ( !Abc_NtkCheckPis( pNtk ) ) - return 0; - if ( !Abc_NtkCheckPos( pNtk ) ) - return 0; - - if ( Abc_NtkHasBlackbox(pNtk) ) - return 1; - - // check the connectivity of objects - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_NtkCheckObj( pNtk, pObj ) ) - return 0; - - // if it is a netlist change nets and latches - if ( Abc_NtkIsNetlist(pNtk) ) - { - if ( Abc_NtkNetNum(pNtk) == 0 ) - { - fprintf( stdout, "NetworkCheck: Netlist has no nets.\n" ); - return 0; - } - // check the nets - Abc_NtkForEachNet( pNtk, pNet, i ) - if ( !Abc_NtkCheckNet( pNtk, pNet ) ) - return 0; - } - else - { - if ( Abc_NtkNetNum(pNtk) != 0 ) - { - fprintf( stdout, "NetworkCheck: A network that is not a netlist has nets.\n" ); - return 0; - } - } - - // check the nodes - if ( Abc_NtkIsStrash(pNtk) ) - Abc_AigCheck( pNtk->pManFunc ); - else - { - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( !Abc_NtkCheckNode( pNtk, pNode ) ) - return 0; - } - - // check the latches - Abc_NtkForEachLatch( pNtk, pNode, i ) - if ( !Abc_NtkCheckLatch( pNtk, pNode ) ) - return 0; - - // finally, check for combinational loops -// clk = clock(); - if ( !Abc_NtkIsAcyclic( pNtk ) ) - { - fprintf( stdout, "NetworkCheck: Network contains a combinational loop.\n" ); - return 0; - } -// PRT( "Acyclic ", clock() - clk ); - - // check the EXDC network if present - if ( pNtk->pExdc ) - Abc_NtkCheck( pNtk->pExdc ); -/* - // check the hierarchy - if ( Abc_NtkIsNetlist(pNtk) && pNtk->tName2Model ) - { - stmm_generator * gen; - Abc_Ntk_t * pNtkTemp; - char * pName; - // check other networks - stmm_foreach_item( pNtk->tName2Model, gen, &pName, (char **)&pNtkTemp ) - { - pNtkTemp->fHiePath = pNtkTemp->fHieVisited = 0; - if ( !Abc_NtkCheck( pNtkTemp ) ) - return 0; - } - // check acyclic dependency of the models - if ( !Abc_NtkIsAcyclicHierarchy( pNtk ) ) - { - fprintf( stdout, "NetworkCheck: Network hierarchical dependences contains a cycle.\n" ); - return 0; - } - } -*/ - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks the names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkCheckNames( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - Vec_Int_t * vNameIds; - char * pName; - int i, NameId; - - if ( Abc_NtkIsNetlist(pNtk) ) - return 1; - - // check that each CI/CO has a name - Abc_NtkForEachCi( pNtk, pObj, i ) - { - pObj = Abc_ObjFanout0Ntk(pObj); - if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) - { - fprintf( stdout, "NetworkCheck: CI with ID %d is in the network but not in the name table.\n", pObj->Id ); - return 0; - } - } - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pObj = Abc_ObjFanin0Ntk(pObj); - if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) - { - fprintf( stdout, "NetworkCheck: CO with ID %d is in the network but not in the name table.\n", pObj->Id ); - return 0; - } - } - - // return the array of all IDs, which have names - vNameIds = Nm_ManReturnNameIds( pNtk->pManName ); - // make sure that these IDs correspond to live objects - Vec_IntForEachEntry( vNameIds, NameId, i ) - { - if ( Vec_PtrEntry( pNtk->vObjs, NameId ) == NULL ) - { - Vec_IntFree( vNameIds ); - pName = Nm_ManFindNameById(pObj->pNtk->pManName, NameId); - fprintf( stdout, "NetworkCheck: Object with ID %d is deleted but its name \"%s\" remains in the name table.\n", NameId, pName ); - return 0; - } - } - Vec_IntFree( vNameIds ); - - // make sure the CI names are unique - if ( !Abc_NtkCheckUniqueCiNames(pNtk) ) - return 0; - - // make sure the CO names are unique - if ( !Abc_NtkCheckUniqueCoNames(pNtk) ) - return 0; - - // make sure that if a CO has the same name as a CI, they point directly - if ( !Abc_NtkCheckUniqueCioNames(pNtk) ) - return 0; - - return 1; -} - - -/**Function************************************************************* - - Synopsis [Checks the PIs of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkCheckPis( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - - // check that PIs are indeed PIs - Abc_NtkForEachPi( pNtk, pObj, i ) - { - if ( !Abc_ObjIsPi(pObj) ) - { - fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is in the PI list but is not a PI.\n", Abc_ObjName(pObj), pObj->Id ); - return 0; - } - if ( pObj->pData ) - { - fprintf( stdout, "NetworkCheck: A PI \"%s\" has a logic function.\n", Abc_ObjName(pObj) ); - return 0; - } - if ( Abc_ObjFaninNum(pObj) > 0 ) - { - fprintf( stdout, "NetworkCheck: A PI \"%s\" has fanins.\n", Abc_ObjName(pObj) ); - return 0; - } - pObj->pCopy = (Abc_Obj_t *)1; - } - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( pObj->pCopy == NULL && Abc_ObjIsPi(pObj) ) - { - fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is a PI but is not in the PI list.\n", Abc_ObjName(pObj), pObj->Id ); - return 0; - } - pObj->pCopy = NULL; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks the POs of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkCheckPos( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - - // check that POs are indeed POs - Abc_NtkForEachPo( pNtk, pObj, i ) - { - if ( !Abc_ObjIsPo(pObj) ) - { - fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in the PO list but is not a PO.\n", Abc_ObjName(pObj), pObj->Id ); - return 0; - } - if ( pObj->pData ) - { - fprintf( stdout, "NetworkCheck: A PO \"%s\" has a logic function.\n", Abc_ObjName(pObj) ); - return 0; - } - if ( Abc_ObjFaninNum(pObj) != 1 ) - { - fprintf( stdout, "NetworkCheck: A PO \"%s\" does not have one fanin.\n", Abc_ObjName(pObj) ); - return 0; - } - if ( Abc_ObjFanoutNum(pObj) > 0 ) - { - fprintf( stdout, "NetworkCheck: A PO \"%s\" has fanouts.\n", Abc_ObjName(pObj) ); - return 0; - } - pObj->pCopy = (Abc_Obj_t *)1; - } - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( pObj->pCopy == NULL && Abc_ObjIsPo(pObj) ) - { - fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in a PO but is not in the PO list.\n", Abc_ObjName(pObj), pObj->Id ); - return 0; - } - pObj->pCopy = NULL; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Checks the connectivity of the object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin, * pFanout; - int i, Value = 1; - int k; - - // check the network - if ( pObj->pNtk != pNtk ) - { - fprintf( stdout, "NetworkCheck: Object \"%s\" does not belong to the network.\n", Abc_ObjName(pObj) ); - return 0; - } - // check the object ID - if ( pObj->Id < 0 || (int)pObj->Id >= Abc_NtkObjNumMax(pNtk) ) - { - fprintf( stdout, "NetworkCheck: Object \"%s\" has incorrect ID.\n", Abc_ObjName(pObj) ); - return 0; - } - - if ( !Abc_FrameIsFlagEnabled("checkfio") ) - return Value; - - // go through the fanins of the object and make sure fanins have this object as a fanout - Abc_ObjForEachFanin( pObj, pFanin, i ) - { - if ( Vec_IntFind( &pFanin->vFanouts, pObj->Id ) == -1 ) - { - fprintf( stdout, "NodeCheck: Object \"%s\" has fanin ", Abc_ObjName(pObj) ); - fprintf( stdout, "\"%s\" but the fanin does not have it as a fanout.\n", Abc_ObjName(pFanin) ); - Value = 0; - } - } - // go through the fanouts of the object and make sure fanouts have this object as a fanin - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - if ( Vec_IntFind( &pFanout->vFanins, pObj->Id ) == -1 ) - { - fprintf( stdout, "NodeCheck: Object \"%s\" has fanout ", Abc_ObjName(pObj) ); - fprintf( stdout, "\"%s\" but the fanout does not have it as a fanin.\n", Abc_ObjName(pFanout) ); - Value = 0; - } - } - - // make sure fanins are not duplicated - for ( i = 0; i < pObj->vFanins.nSize; i++ ) - for ( k = i + 1; k < pObj->vFanins.nSize; k++ ) - if ( pObj->vFanins.pArray[k] == pObj->vFanins.pArray[i] ) - { - printf( "Warning: Node %s has", Abc_ObjName(pObj) ); - printf( " duplicated fanin %s.\n", Abc_ObjName(Abc_ObjFanin(pObj,k)) ); - } - - // save time: do not check large fanout lists - if ( pObj->vFanouts.nSize > 100 ) - return Value; - - // make sure fanouts are not duplicated - for ( i = 0; i < pObj->vFanouts.nSize; i++ ) - for ( k = i + 1; k < pObj->vFanouts.nSize; k++ ) - if ( pObj->vFanouts.pArray[k] == pObj->vFanouts.pArray[i] ) - { - printf( "Warning: Node %s has", Abc_ObjName(pObj) ); - printf( " duplicated fanout %s.\n", Abc_ObjName(Abc_ObjFanout(pObj,k)) ); - } - - return Value; -} - -/**Function************************************************************* - - Synopsis [Checks the integrity of a net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ) -{ - if ( Abc_ObjFaninNum(pNet) == 0 ) - { - fprintf( stdout, "NetworkCheck: Net \"%s\" is not driven.\n", Abc_ObjName(pNet) ); - return 0; - } - if ( Abc_ObjFaninNum(pNet) > 1 ) - { - fprintf( stdout, "NetworkCheck: Net \"%s\" has more than one driver.\n", Abc_ObjName(pNet) ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks the integrity of a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) -{ - // detect internal nodes that do not have nets - if ( Abc_NtkIsNetlist(pNtk) && Abc_ObjFanoutNum(pNode) == 0 ) - { - fprintf( stdout, "Node (id = %d) has no net to drive.\n", pNode->Id ); - return 0; - } - // the node should have a function assigned unless it is an AIG - if ( pNode->pData == NULL ) - { - fprintf( stdout, "NodeCheck: An internal node \"%s\" does not have a logic function.\n", Abc_ObjNameNet(pNode) ); - return 0; - } - // the netlist and SOP logic network should have SOPs - if ( Abc_NtkHasSop(pNtk) ) - { - if ( !Abc_SopCheck( pNode->pData, Abc_ObjFaninNum(pNode) ) ) - { - fprintf( stdout, "NodeCheck: SOP check for node \"%s\" has failed.\n", Abc_ObjNameNet(pNode) ); - return 0; - } - } - else if ( Abc_NtkHasBdd(pNtk) ) - { - int nSuppSize = Cudd_SupportSize(pNtk->pManFunc, pNode->pData); - if ( nSuppSize > Abc_ObjFaninNum(pNode) ) - { - fprintf( stdout, "NodeCheck: BDD of the node \"%s\" has incorrect support size.\n", Abc_ObjNameNet(pNode) ); - return 0; - } - } - else if ( !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasAig(pNtk) ) - { - assert( 0 ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks the integrity of a latch.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ) -{ - int Value = 1; - // check whether the object is a latch - if ( !Abc_ObjIsLatch(pLatch) ) - { - fprintf( stdout, "NodeCheck: Latch \"%s\" is in a latch list but is not a latch.\n", Abc_ObjName(pLatch) ); - Value = 0; - } - // make sure the latch has a reasonable return value - if ( (int)pLatch->pData < ABC_INIT_ZERO || (int)pLatch->pData > ABC_INIT_DC ) - { - fprintf( stdout, "NodeCheck: Latch \"%s\" has incorrect reset value (%d).\n", - Abc_ObjName(pLatch), (int)pLatch->pData ); - Value = 0; - } - // make sure the latch has only one fanin - if ( Abc_ObjFaninNum(pLatch) != 1 ) - { - fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanins.\n", Abc_ObjName(pLatch), Abc_ObjFaninNum(pLatch) ); - Value = 0; - } - // make sure the latch has only one fanout - if ( Abc_ObjFanoutNum(pLatch) != 1 ) - { - fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanouts.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) ); - Value = 0; - } - // make sure the latch input has only one fanin - if ( Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) != 1 ) - { - fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanins.\n", - Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) ); - Value = 0; - } - // make sure the latch input has only one fanout - if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) != 1 ) - { - fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanouts.\n", - Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) ); - Value = 0; - } - // make sure the latch output has only one fanin - if ( Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) != 1 ) - { - fprintf( stdout, "NodeCheck: Output of latch \"%s\" has wrong number (%d) of fanins.\n", - Abc_ObjName(Abc_ObjFanout0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) ); - Value = 0; - } - return Value; -} - - - - -/**Function************************************************************* - - Synopsis [Compares the PIs of the two networks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) -{ - Abc_Obj_t * pObj1; - int i; - if ( Abc_NtkPiNum(pNtk1) != Abc_NtkPiNum(pNtk2) ) - { - printf( "Networks have different number of primary inputs.\n" ); - return 0; - } - // for each PI of pNet1 find corresponding PI of pNet2 and reorder them - Abc_NtkForEachPi( pNtk1, pObj1, i ) - { - if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ) != 0 ) - { - printf( "Primary input #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", - i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ); - return 0; - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Compares the POs of the two networks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) -{ - Abc_Obj_t * pObj1; - int i; - if ( Abc_NtkPoNum(pNtk1) != Abc_NtkPoNum(pNtk2) ) - { - printf( "Networks have different number of primary outputs.\n" ); - return 0; - } - // for each PO of pNet1 find corresponding PO of pNet2 and reorder them - Abc_NtkForEachPo( pNtk1, pObj1, i ) - { - if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ) != 0 ) - { - printf( "Primary output #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", - i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ); - return 0; - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Compares the latches of the two networks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkCompareBoxes( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) -{ - Abc_Obj_t * pObj1; - int i; - assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); - assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); - if ( !fComb ) - return 1; - if ( Abc_NtkBoxNum(pNtk1) != Abc_NtkBoxNum(pNtk2) ) - { - printf( "Networks have different number of latches.\n" ); - return 0; - } - // for each PI of pNet1 find corresponding PI of pNet2 and reorder them - Abc_NtkForEachBox( pNtk1, pObj1, i ) - { - if ( strcmp( Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ) != 0 ) - { - printf( "Box #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", - i, Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ); - return 0; - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Compares the signals of the networks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb ) -{ - Abc_NtkOrderObjsByName( pNtk1, fComb ); - Abc_NtkOrderObjsByName( pNtk2, fComb ); - if ( !Abc_NtkComparePis( pNtk1, pNtk2, fComb ) ) - return 0; - if ( !fOnlyPis ) - { - if ( !Abc_NtkCompareBoxes( pNtk1, pNtk2, fComb ) ) - return 0; - if ( !Abc_NtkComparePos( pNtk1, pNtk2, fComb ) ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 0 if the network hierachy contains a cycle.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkIsAcyclicHierarchy_rec( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNext; - Abc_Obj_t * pObj; - int i; - // return if visited - if ( pNtk->fHieVisited ) - return 1; - pNtk->fHieVisited = 1; - // return if black box - if ( Abc_NtkHasBlackbox(pNtk) ) - return 1; - assert( Abc_NtkIsNetlist(pNtk) ); - // go through all the children networks - Abc_NtkForEachBox( pNtk, pObj, i ) - { - if ( Abc_ObjIsLatch(pObj) ) - continue; - pNtkNext = pObj->pData; - assert( pNtkNext != NULL ); - if ( pNtkNext->fHiePath ) - return 0; - pNtk->fHiePath = 1; - if ( !Abc_NtkIsAcyclicHierarchy_rec( pNtkNext ) ) - return 0; - pNtk->fHiePath = 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 0 if the network hierachy contains a cycle.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pTemp; - int i, RetValue; - assert( Abc_NtkIsNetlist(pNtk) && pNtk->pDesign ); - // clear the modules - Vec_PtrForEachEntry( pNtk->pDesign->vModules, pTemp, i ) - pTemp->fHieVisited = pTemp->fHiePath = 0; - // traverse - pNtk->fHiePath = 1; - RetValue = Abc_NtkIsAcyclicHierarchy_rec( pNtk ); - pNtk->fHiePath = 0; - // clear the modules - Vec_PtrForEachEntry( pNtk->pDesign->vModules, pTemp, i ) - pTemp->fHieVisited = pTemp->fHiePath = 0; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Returns 0 if CI names are repeated.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkNamesCompare( char ** pName1, char ** pName2 ) -{ - return strcmp( *pName1, *pName2 ); -} - -/**Function************************************************************* - - Synopsis [Returns 0 if CI names are repeated.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNames; - Abc_Obj_t * pObj; - int i, fRetValue = 1; - assert( !Abc_NtkIsNetlist(pNtk) ); - vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) ); - Abc_NtkForEachCi( pNtk, pObj, i ) - Vec_PtrPush( vNames, Abc_ObjName(pObj) ); - Vec_PtrSort( vNames, Abc_NtkNamesCompare ); - for ( i = 1; i < Abc_NtkCiNum(pNtk); i++ ) - if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) ) - { - printf( "Abc_NtkCheck: Repeated CI names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ); - fRetValue = 0; - } - Vec_PtrFree( vNames ); - return fRetValue; -} - -/**Function************************************************************* - - Synopsis [Returns 0 if CO names are repeated.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNames; - Abc_Obj_t * pObj; - int i, fRetValue = 1; - assert( !Abc_NtkIsNetlist(pNtk) ); - vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - Vec_PtrPush( vNames, Abc_ObjName(pObj) ); - Vec_PtrSort( vNames, Abc_NtkNamesCompare ); - for ( i = 1; i < Abc_NtkCoNum(pNtk); i++ ) - { -// printf( "%s\n", Vec_PtrEntry(vNames,i) ); - if ( !strcmp( Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ) ) - { - printf( "Abc_NtkCheck: Repeated CO names: %s and %s.\n", Vec_PtrEntry(vNames,i-1), Vec_PtrEntry(vNames,i) ); - fRetValue = 0; - } - } - Vec_PtrFree( vNames ); - return fRetValue; -} - -/**Function************************************************************* - - Synopsis [Returns 0 if there is a pair of CI/CO with the same name and logic in between.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj, * pObjCi; - int i, nCiId, fRetValue = 1; - assert( !Abc_NtkIsNetlist(pNtk) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - nCiId = Nm_ManFindIdByNameTwoTypes( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); - if ( nCiId == -1 ) - continue; - pObjCi = Abc_NtkObj( pNtk, nCiId ); - assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) ); - if ( Abc_ObjFanin0(pObj) != pObjCi ) - { - printf( "Abc_NtkCheck: A CI/CO pair share the name (%s) but do not link directly.\n", Abc_ObjName(pObj) ); - fRetValue = 0; - } - } - return fRetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcDfs.c b/src/base/abc/abcDfs.c deleted file mode 100644 index 39e985c0..00000000 --- a/src/base/abc/abcDfs.c +++ /dev/null @@ -1,1264 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcDfs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures that use depth-first search.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanin; - int i; - assert( !Abc_ObjIsNet(pNode) ); - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // skip the CI - if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) - return; - assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) ); - // visit the transitive fanin of the node - Abc_ObjForEachFanin( pNode, pFanin, i ) - { -// pFanin = Abc_ObjFanin( pNode, Abc_ObjFaninNum(pNode)-1-i ); - Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); - } - // add the node after the fanins have been added - Vec_PtrPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Returns the DFS ordered array of logic nodes.] - - Description [Collects only the internal nodes, leaving CIs and CO. - However it marks with the current TravId both CIs and COs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i; - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - Abc_NodeSetTravIdCurrent( pObj ); - Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); - } - // collect dangling nodes if asked to - if ( fCollectAll ) - { - Abc_NtkForEachNode( pNtk, pObj, i ) - if ( !Abc_NodeIsTravIdCurrent(pObj) ) - Abc_NtkDfs_rec( pObj, vNodes ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Returns the DFS ordered array of logic nodes.] - - Description [Collects only the internal nodes, leaving out PIs, POs and latches.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) -{ - Vec_Ptr_t * vNodes; - int i; - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrAlloc( 100 ); - // go through the PO nodes and call for each of them - for ( i = 0; i < nNodes; i++ ) - { - if ( Abc_ObjIsCo(ppNodes[i]) ) - { - Abc_NodeSetTravIdCurrent(ppNodes[i]); - Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(ppNodes[i])), vNodes ); - } - else if ( Abc_ObjIsNode(ppNodes[i]) ) - Abc_NtkDfs_rec( ppNodes[i], vNodes ); - } - return vNodes; -} - - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanout; - int i; - assert( !Abc_ObjIsNet(pNode) ); - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // skip the CI - if ( Abc_ObjIsCo(pNode) ) - return; - assert( Abc_ObjIsNode( pNode ) ); - // visit the transitive fanin of the node - pNode = Abc_ObjFanout0Ntk(pNode); - Abc_ObjForEachFanout( pNode, pFanout, i ) - Abc_NtkDfsReverse_rec( pFanout, vNodes ); - // add the node after the fanins have been added - Vec_PtrPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Returns the reverse DFS ordered array of logic nodes.] - - Description [Collects only the internal nodes, leaving out CIs/COs. - However it marks both CIs and COs with the current TravId.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pFanout; - int i, k; - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachCi( pNtk, pObj, i ) - { - Abc_NodeSetTravIdCurrent( pObj ); - pObj = Abc_ObjFanout0Ntk(pObj); - Abc_ObjForEachFanout( pObj, pFanout, k ) - Abc_NtkDfsReverse_rec( pFanout, vNodes ); - } - // add constant nodes in the end - if ( !Abc_NtkIsStrash(pNtk) ) - Abc_NtkForEachNode( pNtk, pObj, i ) - if ( Abc_NodeIsConst(pObj) ) - Vec_PtrPush( vNodes, pObj ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDfsReverseNodes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanout; - int i; - assert( !Abc_ObjIsNet(pNode) ); - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // skip the CI - if ( Abc_ObjIsCo(pNode) ) - return; - assert( Abc_ObjIsNode( pNode ) ); - // visit the transitive fanin of the node - pNode = Abc_ObjFanout0Ntk(pNode); - Abc_ObjForEachFanout( pNode, pFanout, i ) - Abc_NtkDfsReverseNodes_rec( pFanout, vNodes ); - // add the node after the fanins have been added -// Vec_PtrPush( vNodes, pNode ); - Vec_PtrFillExtra( vNodes, pNode->Level + 1, NULL ); - pNode->pCopy = Vec_PtrEntry( vNodes, pNode->Level ); - Vec_PtrWriteEntry( vNodes, pNode->Level, pNode ); -} - -/**Function************************************************************* - - Synopsis [Returns the levelized array of TFO nodes.] - - Description [Collects the levelized array of internal nodes, leaving out CIs/COs. - However it marks both CIs and COs with the current TravId.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pFanout; - int i, k; - assert( Abc_NtkIsStrash(pNtk) ); - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrStart( Abc_AigLevel(pNtk) + 1 ); - for ( i = 0; i < nNodes; i++ ) - { - pObj = ppNodes[i]; - assert( Abc_ObjIsCi(pObj) ); - Abc_NodeSetTravIdCurrent( pObj ); - pObj = Abc_ObjFanout0Ntk(pObj); - Abc_ObjForEachFanout( pObj, pFanout, k ) - Abc_NtkDfsReverseNodes_rec( pFanout, vNodes ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Returns the levelized array of TFO nodes.] - - Description [Collects the levelized array of internal nodes, leaving out CIs/COs. - However it marks both CIs and COs with the current TravId. - Collects only the nodes whose support does not exceed the set of given CI nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pFanout, * pFanin; - int i, k, m, nLevels; - // set the levels - nLevels = Abc_NtkLevel( pNtk ); - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrStart( nLevels + 2 ); - for ( i = 0; i < nNodes; i++ ) - { - pObj = ppNodes[i]; - assert( Abc_ObjIsCi(pObj) ); - Abc_NodeSetTravIdCurrent( pObj ); - // add to the array - assert( pObj->Level == 0 ); - pObj->pCopy = Vec_PtrEntry( vNodes, pObj->Level ); - Vec_PtrWriteEntry( vNodes, pObj->Level, pObj ); - } - // iterate through the levels - for ( i = 0; i <= nLevels; i++ ) - { - // iterate through the nodes on each level - for ( pObj = Vec_PtrEntry(vNodes, i); pObj; pObj = pObj->pCopy ) - { - // iterate through the fanouts of each node - Abc_ObjForEachFanout( pObj, pFanout, k ) - { - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pFanout) ) - continue; - // visit the fanins of this fanout - Abc_ObjForEachFanin( pFanout, pFanin, m ) - { - if ( !Abc_NodeIsTravIdCurrent(pFanin) ) - break; - } - if ( m < Abc_ObjFaninNum(pFanout) ) - continue; - // all fanins are already collected - - // mark the node as visited - Abc_NodeSetTravIdCurrent( pFanout ); - // handle the COs - if ( Abc_ObjIsCo(pFanout) ) - pFanout->Level = nLevels + 1; - // add to the array - pFanout->pCopy = Vec_PtrEntry( vNodes, pFanout->Level ); - Vec_PtrWriteEntry( vNodes, pFanout->Level, pFanout ); - // handle the COs - if ( Abc_ObjIsCo(pFanout) ) - pFanout->Level = 0; - } - } - } - return vNodes; -} - - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDfsSeq_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanin; - int i; - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // visit the transitive fanin of the node - Abc_ObjForEachFanin( pNode, pFanin, i ) - Abc_NtkDfsSeq_rec( pFanin, vNodes ); - // add the node after the fanins have been added - Vec_PtrPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of nodes and latches reachable from POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i; - assert( !Abc_NtkIsNetlist(pNtk) ); - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_NtkDfsSeq_rec( pObj, vNodes ); - // mark the PIs - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_NtkDfsSeq_rec( pObj, vNodes ); - return vNodes; -} - - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDfsSeqReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanout; - int i; - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // visit the transitive fanin of the node - Abc_ObjForEachFanout( pNode, pFanout, i ) - Abc_NtkDfsSeqReverse_rec( pFanout, vNodes ); - // add the node after the fanins have been added - Vec_PtrPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of nodes and latches reachable from POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i; - assert( !Abc_NtkIsNetlist(pNtk) ); - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_NtkDfsSeqReverse_rec( pObj, vNodes ); - // mark the logic feeding into POs - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_NtkDfsSeq_rec( pObj, vNodes ); - return vNodes; -} - - -/**Function************************************************************* - - Synopsis [Iterative version of the DFS procedure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDfs_iter( Vec_Ptr_t * vStack, Abc_Obj_t * pRoot, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pNode, * pFanin; - int iFanin; - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pRoot ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pRoot ); - // skip the CI - if ( Abc_ObjIsCi(pRoot) || (Abc_NtkIsStrash(pRoot->pNtk) && Abc_AigNodeIsConst(pRoot)) ) - return; - // add the CI - Vec_PtrClear( vStack ); - Vec_PtrPush( vStack, pRoot ); - Vec_PtrPush( vStack, (void *)0 ); - while ( Vec_PtrSize(vStack) > 0 ) - { - // get the node and its fanin - iFanin = (int)Vec_PtrPop(vStack); - pNode = Vec_PtrPop(vStack); - assert( !Abc_ObjIsNet(pNode) ); - // add it to the array of nodes if we finished - if ( iFanin == Abc_ObjFaninNum(pNode) ) - { - Vec_PtrPush( vNodes, pNode ); - continue; - } - // explore the next fanin - Vec_PtrPush( vStack, pNode ); - Vec_PtrPush( vStack, (void *)(iFanin+1) ); - // get the fanin - pFanin = Abc_ObjFanin0Ntk( Abc_ObjFanin(pNode,iFanin) ); - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pFanin ) ) - continue; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pFanin ); - // skip the CI - if ( Abc_ObjIsCi(pFanin) || (Abc_NtkIsStrash(pFanin->pNtk) && Abc_AigNodeIsConst(pFanin)) ) - continue; - Vec_PtrPush( vStack, pFanin ); - Vec_PtrPush( vStack, (void *)0 ); - } -} - -/**Function************************************************************* - - Synopsis [Returns the DFS ordered array of logic nodes.] - - Description [Collects only the internal nodes, leaving CIs and CO. - However it marks with the current TravId both CIs and COs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ) -{ - Vec_Ptr_t * vNodes, * vStack; - Abc_Obj_t * pObj; - int i; - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrAlloc( 1000 ); - vStack = Vec_PtrAlloc( 1000 ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - Abc_NodeSetTravIdCurrent( pObj ); - Abc_NtkDfs_iter( vStack, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); - } - // collect dangling nodes if asked to - if ( fCollectAll ) - { - Abc_NtkForEachNode( pNtk, pObj, i ) - if ( !Abc_NodeIsTravIdCurrent(pObj) ) - Abc_NtkDfs_iter( vStack, pObj, vNodes ); - } - Vec_PtrFree( vStack ); - return vNodes; -} - - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDfsHie_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanin; - int i; - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pObj ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pObj ); - // visit the transitive fanin of the node - Abc_ObjForEachFanin( pObj, pFanin, i ) - Abc_NtkDfsHie_rec( pFanin, vNodes ); - // add the node after the fanins have been added - Vec_PtrPush( vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Returns the DFS ordered array of all objects.] - - Description [This procedure collects everything from POs to PIs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i; - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_NtkDfsHie_rec( pObj, vNodes ); - // collect dangling nodes if asked to - if ( fCollectAll ) - { - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_NodeIsTravIdCurrent(pObj) ) - Abc_NtkDfs_rec( pObj, vNodes ); - } - return vNodes; -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if the ordering of nodes is DFS.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode, * pFanin; - int i, k; - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // mark the CIs - Abc_NtkForEachCi( pNtk, pNode, i ) - Abc_NodeSetTravIdCurrent( pNode ); - // go through the nodes - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // check the fanins of the node - Abc_ObjForEachFanin( pNode, pFanin, k ) - if ( !Abc_NodeIsTravIdCurrent(pFanin) ) - return 0; - // check the choices of the node - if ( Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsChoice(pNode) ) - for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData ) - if ( !Abc_NodeIsTravIdCurrent(pFanin) ) - return 0; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanin; - int i; - assert( !Abc_ObjIsNet(pNode) ); - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // collect the CI - if ( Abc_ObjIsCi(pNode) || Abc_ObjFaninNum(pNode) == 0 ) - { - Vec_PtrPush( vNodes, pNode ); - return; - } - assert( Abc_ObjIsNode( pNode ) ); - // visit the transitive fanin of the node - Abc_ObjForEachFanin( pNode, pFanin, i ) - Abc_NtkNodeSupport_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); -} - -/**Function************************************************************* - - Synopsis [Returns the set of CI nodes in the support of the given nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode; - int i; - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrAlloc( 100 ); - // go through the PO nodes and call for each of them - Abc_NtkForEachCo( pNtk, pNode, i ) - Abc_NtkNodeSupport_rec( Abc_ObjFanin0(pNode), vNodes ); - // add unused CIs - Abc_NtkForEachCi( pNtk, pNode, i ) - if ( !Abc_NodeIsTravIdCurrent( pNode ) ) - Vec_PtrPush( vNodes, pNode ); - assert( Vec_PtrSize(vNodes) == Abc_NtkCiNum(pNtk) ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Returns the set of CI nodes in the support of the given nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) -{ - Vec_Ptr_t * vNodes; - int i; - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrAlloc( 100 ); - // go through the PO nodes and call for each of them - for ( i = 0; i < nNodes; i++ ) - if ( Abc_ObjIsCo(ppNodes[i]) ) - Abc_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes ); - else - Abc_NtkNodeSupport_rec( ppNodes[i], vNodes ); - return vNodes; -} - - -/**Function************************************************************* - - Synopsis [Performs DFS for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanin; - int i; - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // skip the PI - if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) ) - return; - assert( Abc_ObjIsNode( pNode ) ); - // visit the transitive fanin of the node - Abc_ObjForEachFanin( pNode, pFanin, i ) - Abc_AigDfs_rec( pFanin, vNodes ); - // visit the equivalent nodes - if ( Abc_AigNodeIsChoice( pNode ) ) - for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData ) - Abc_AigDfs_rec( pFanin, vNodes ); - // add the node after the fanins have been added - Vec_PtrPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Returns the DFS ordered array of logic nodes.] - - Description [Collects only the internal nodes, leaving out CIs/COs. - However it marks both CIs and COs with the current TravId.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode; - int i; - assert( Abc_NtkIsStrash(pNtk) ); - // set the traversal ID - Abc_NtkIncrementTravId( pNtk ); - // start the array of nodes - vNodes = Vec_PtrAlloc( 100 ); - // go through the PO nodes and call for each of them - Abc_NtkForEachCo( pNtk, pNode, i ) - { - Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes ); - Abc_NodeSetTravIdCurrent( pNode ); - if ( fCollectCos ) - Vec_PtrPush( vNodes, pNode ); - } - // collect dangling nodes if asked to - if ( fCollectAll ) - { - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( !Abc_NodeIsTravIdCurrent(pNode) ) - Abc_AigDfs_rec( pNode, vNodes ); - } - return vNodes; -} - - -/**Function************************************************************* - - Synopsis [Collects nodes in the DFS manner by level.] - - Description [The number of levels should be set!!!] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels ) -{ - Abc_Obj_t * pFanout; - int i; - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // skip the terminals - if ( Abc_ObjIsCo(pNode) ) - return; - assert( Abc_ObjIsNode(pNode) ); - // add the node to the structure - Vec_VecPush( vLevels, pNode->Level, pNode ); - // visit the TFO - Abc_ObjForEachFanout( pNode, pFanout, i ) - Abc_DfsLevelizedTfo_rec( pFanout, vLevels ); -} - -/**Function************************************************************* - - Synopsis [Collects nodes in the DFS manner by level.] - - Description [The number of levels should be set!!!] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi ) -{ - Vec_Vec_t * vLevels; - Abc_Obj_t * pFanout; - int i; - assert( fTfi == 0 ); - assert( !Abc_NtkIsNetlist(pNode->pNtk) ); - // set the traversal ID - Abc_NtkIncrementTravId( pNode->pNtk ); - vLevels = Vec_VecAlloc( 100 ); - if ( Abc_ObjIsNode(pNode) ) - Abc_DfsLevelizedTfo_rec( pNode, vLevels ); - else - { - assert( Abc_ObjIsCi(pNode) ); - Abc_NodeSetTravIdCurrent( pNode ); - Abc_ObjForEachFanout( pNode, pFanout, i ) - Abc_DfsLevelizedTfo_rec( pFanout, vLevels ); - } - return vLevels; -} - - -/**Function************************************************************* - - Synopsis [Recursively counts the number of logic levels of one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkLevel_rec( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pNext; - int i, Level; - assert( !Abc_ObjIsNet(pNode) ); - // skip the PI - if ( Abc_ObjIsCi(pNode) ) - return pNode->Level; - assert( Abc_ObjIsNode( pNode ) ); - // if this node is already visited, return - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return pNode->Level; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // visit the transitive fanin - pNode->Level = 0; - Abc_ObjForEachFanin( pNode, pNext, i ) - { - Level = Abc_NtkLevel_rec( Abc_ObjFanin0Ntk(pNext) ); - if ( pNode->Level < (unsigned)Level ) - pNode->Level = Level; - } - if ( Abc_ObjFaninNum(pNode) > 0 ) - pNode->Level++; - return pNode->Level; -} - -/**Function************************************************************* - - Synopsis [Recursively counts the number of logic levels of one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkLevelReverse_rec( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pNext; - int i, Level; - assert( !Abc_ObjIsNet(pNode) ); - // skip the PI - if ( Abc_ObjIsCo(pNode) ) - return pNode->Level; - assert( Abc_ObjIsNode( pNode ) ); - // if this node is already visited, return - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return pNode->Level; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // visit the transitive fanin - pNode->Level = 0; - Abc_ObjForEachFanout( pNode, pNext, i ) - { - Level = Abc_NtkLevelReverse_rec( Abc_ObjFanout0Ntk(pNext) ); - if ( pNode->Level < (unsigned)Level ) - pNode->Level = Level; - } - if ( Abc_ObjFaninNum(pNode) > 0 ) - pNode->Level++; - return pNode->Level; -} - -/**Function************************************************************* - - Synopsis [Computes the number of logic levels not counting PIs/POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkLevel( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, LevelsMax; - // set the CI levels to zero - Abc_NtkForEachCi( pNtk, pNode, i ) - pNode->Level = 0; - // perform the traversal - LevelsMax = 0; - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Abc_NtkLevel_rec( pNode ); - if ( LevelsMax < (int)pNode->Level ) - LevelsMax = (int)pNode->Level; - } - return LevelsMax; -} - -/**Function************************************************************* - - Synopsis [Computes the number of logic levels not counting PIs/POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, LevelsMax; - // set the CO levels to zero - Abc_NtkForEachCo( pNtk, pNode, i ) - pNode->Level = 0; - // perform the traversal - LevelsMax = 0; - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Abc_NtkLevelReverse_rec( pNode ); - if ( LevelsMax < (int)pNode->Level ) - LevelsMax = (int)pNode->Level; - } - return LevelsMax; -} - - -/**Function************************************************************* - - Synopsis [Recursively detects combinational loops.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode ) -{ - Abc_Ntk_t * pNtk = pNode->pNtk; - Abc_Obj_t * pFanin; - int fAcyclic, i; - assert( !Abc_ObjIsNet(pNode) ); - if ( Abc_ObjIsCi(pNode) || Abc_ObjIsBox(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) - return 1; - assert( Abc_ObjIsNode(pNode) ); - // make sure the node is not visited - assert( !Abc_NodeIsTravIdPrevious(pNode) ); - // check if the node is part of the combinational loop - if ( Abc_NodeIsTravIdCurrent(pNode) ) - { - fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) ); - fprintf( stdout, "Node \"%s\" is encountered twice on the following path to the COs:\n", Abc_ObjName(pNode) ); - return 0; - } - // mark this node as a node on the current path - Abc_NodeSetTravIdCurrent( pNode ); - // visit the transitive fanin - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - pFanin = Abc_ObjFanin0Ntk(pFanin); - // make sure there is no mixing of networks - assert( pFanin->pNtk == pNode->pNtk ); - // check if the fanin is visited - if ( Abc_NodeIsTravIdPrevious(pFanin) ) - continue; - // traverse the fanin's cone searching for the loop - if ( fAcyclic = Abc_NtkIsAcyclic_rec(pFanin) ) - continue; - // return as soon as the loop is detected - fprintf( stdout, " %s ->", Abc_ObjName(pFanin) ); - return 0; - } - // visit choices - if ( Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsChoice(pNode) ) - { - for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData ) - { - // check if the fanin is visited - if ( Abc_NodeIsTravIdPrevious(pFanin) ) - continue; - // traverse the fanin's cone searching for the loop - if ( fAcyclic = Abc_NtkIsAcyclic_rec(pFanin) ) - continue; - // return as soon as the loop is detected - fprintf( stdout, " %s", Abc_ObjName(pFanin) ); - fprintf( stdout, " (choice of %s) -> ", Abc_ObjName(pNode) ); - return 0; - } - } - // mark this node as a visited node - Abc_NodeSetTravIdPrevious( pNode ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Detects combinational loops.] - - Description [This procedure is based on the idea suggested by Donald Chai. - As we traverse the network and visit the nodes, we need to distinquish - three types of nodes: (1) those that are visited for the first time, - (2) those that have been visited in this traversal but are currently not - on the traversal path, (3) those that have been visited and are currently - on the travesal path. When the node of type (3) is encountered, it means - that there is a combinational loop. To mark the three types of nodes, - two new values of the traversal IDs are used.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int fAcyclic, i; - // set the traversal ID for this DFS ordering - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkIncrementTravId( pNtk ); - // pNode->TravId == pNet->nTravIds means "pNode is on the path" - // pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path" - // pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited" - // traverse the network to detect cycles - fAcyclic = 1; - Abc_NtkForEachCo( pNtk, pNode, i ) - { - pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode)); - if ( Abc_NodeIsTravIdPrevious(pNode) ) - continue; - // traverse the output logic cone - if ( fAcyclic = Abc_NtkIsAcyclic_rec(pNode) ) - continue; - // stop as soon as the first loop is detected - fprintf( stdout, " CO \"%s\"\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - break; - } - return fAcyclic; -} - - -/**Function************************************************************* - - Synopsis [Analyses choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeSetChoiceLevel_rec( Abc_Obj_t * pNode, int fMaximum ) -{ - Abc_Obj_t * pTemp; - int Level1, Level2, Level, LevelE; - // skip the visited node - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return (int)pNode->pCopy; - Abc_NodeSetTravIdCurrent( pNode ); - // compute levels of the children nodes - Level1 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pNode), fMaximum ); - Level2 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin1(pNode), fMaximum ); - Level = 1 + ABC_MAX( Level1, Level2 ); - if ( pNode->pData ) - { - LevelE = Abc_NodeSetChoiceLevel_rec( pNode->pData, fMaximum ); - if ( fMaximum ) - Level = ABC_MAX( Level, LevelE ); - else - Level = ABC_MIN( Level, LevelE ); - // set the level of all equivalent nodes to be the same minimum - for ( pTemp = pNode->pData; pTemp; pTemp = pTemp->pData ) - pTemp->pCopy = (void *)Level; - } - pNode->pCopy = (void *)Level; - return Level; -} - -/**Function************************************************************* - - Synopsis [Resets the levels of the nodes in the choice graph.] - - Description [Makes the level of the choice nodes to be equal to the - maximum of the level of the nodes in the equivalence class. This way - sorting by level leads to the reverse topological order, which is - needed for the required time computation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_AigSetChoiceLevels( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i, LevelMax, LevelCur; - assert( Abc_NtkIsStrash(pNtk) ); - // set the new travid counter - Abc_NtkIncrementTravId( pNtk ); - // set levels of the CI and constant - Abc_NtkForEachCi( pNtk, pObj, i ) - { - Abc_NodeSetTravIdCurrent( pObj ); - pObj->pCopy = NULL; - } - pObj = Abc_AigConst1( pNtk ); - Abc_NodeSetTravIdCurrent( pObj ); - pObj->pCopy = NULL; - // set levels of all other nodes - LevelMax = 0; - Abc_NtkForEachCo( pNtk, pObj, i ) - { - LevelCur = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pObj), 1 ); - LevelMax = ABC_MAX( LevelMax, LevelCur ); - } - return LevelMax; -} - -/**Function************************************************************* - - Synopsis [Returns nodes by level from the smallest to the largest.] - - Description [Correctly handles the case of choice nodes, by first - spreading them out across several levels and then collecting.] - - SideEffects [What happens with dangling nodes???] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ) -{ - Vec_Ptr_t * vNodes, * vLevels; - Abc_Obj_t * pNode, ** ppHead; - int LevelMax, i; - assert( Abc_NtkIsStrash(pNtk) ); - // set the correct levels - Abc_NtkCleanCopy( pNtk ); - LevelMax = Abc_AigSetChoiceLevels( pNtk ); - // relink nodes by level - vLevels = Vec_PtrStart( LevelMax + 1 ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - ppHead = ((Abc_Obj_t **)vLevels->pArray) + (int)pNode->pCopy; - pNode->pCopy = *ppHead; - *ppHead = pNode; - } - // recollect nodes - vNodes = Vec_PtrStart( Abc_NtkNodeNum(pNtk) ); - Vec_PtrForEachEntryStart( vLevels, pNode, i, !fCollectCis ) - for ( ; pNode; pNode = pNode->pCopy ) - Vec_PtrPush( vNodes, pNode ); - Vec_PtrFree( vLevels ); - return vNodes; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcFanio.c b/src/base/abc/abcFanio.c deleted file mode 100644 index c8536695..00000000 --- a/src/base/abc/abcFanio.c +++ /dev/null @@ -1,336 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcFanio.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Various procedures to connect fanins/fanouts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntPushMem( Extra_MmStep_t * pMemMan, Vec_Int_t * p, int Entry ) -{ - if ( p->nSize == p->nCap ) - { - int * pArray; - int i; - - if ( p->nSize == 0 ) - p->nCap = 1; - if ( pMemMan ) - pArray = (int *)Extra_MmStepEntryFetch( pMemMan, p->nCap * 8 ); - else - pArray = ALLOC( int, p->nCap * 2 ); - if ( p->pArray ) - { - for ( i = 0; i < p->nSize; i++ ) - pArray[i] = p->pArray[i]; - if ( pMemMan ) - Extra_MmStepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 ); - else - free( p->pArray ); - } - p->nCap *= 2; - p->pArray = pArray; - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [Creates fanout/fanin relationship between the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) -{ - Abc_Obj_t * pFaninR = Abc_ObjRegular(pFanin); - assert( !Abc_ObjIsComplement(pObj) ); - assert( pObj->pNtk == pFaninR->pNtk ); - assert( pObj->Id >= 0 && pFaninR->Id >= 0 ); - Vec_IntPushMem( pObj->pNtk->pMmStep, &pObj->vFanins, pFaninR->Id ); - Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninR->vFanouts, pObj->Id ); - if ( Abc_ObjIsComplement(pFanin) ) - Abc_ObjSetFaninC( pObj, Abc_ObjFaninNum(pObj)-1 ); - if ( Abc_ObjIsNet(pObj) && Abc_ObjFaninNum(pObj) > 1 ) - { - int x = 0; - } -// printf( "Adding fanin of %s ", Abc_ObjName(pObj) ); -// printf( "to be %s\n", Abc_ObjName(pFanin) ); -} - - -/**Function************************************************************* - - Synopsis [Destroys fanout/fanin relationship between the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) -{ - assert( !Abc_ObjIsComplement(pObj) ); - assert( !Abc_ObjIsComplement(pFanin) ); - assert( pObj->pNtk == pFanin->pNtk ); - assert( pObj->Id >= 0 && pFanin->Id >= 0 ); - if ( !Vec_IntRemove( &pObj->vFanins, pFanin->Id ) ) - { - printf( "The obj %d is not found among the fanins of obj %d ...\n", pFanin->Id, pObj->Id ); - return; - } - if ( !Vec_IntRemove( &pFanin->vFanouts, pObj->Id ) ) - { - printf( "The obj %d is not found among the fanouts of obj %d ...\n", pObj->Id, pFanin->Id ); - return; - } -} - - -/**Function************************************************************* - - Synopsis [Destroys fanout/fanin relationship between the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ) -{ - Vec_Int_t * vFaninsOld; - Abc_Obj_t * pFanin; - int k; - // remove old fanins - vFaninsOld = &pObj->vFanins; - for ( k = vFaninsOld->nSize - 1; k >= 0; k-- ) - { - pFanin = Abc_NtkObj( pObj->pNtk, vFaninsOld->pArray[k] ); - Abc_ObjDeleteFanin( pObj, pFanin ); - } - pObj->fCompl0 = 0; - pObj->fCompl1 = 0; - assert( vFaninsOld->nSize == 0 ); -} - -/**Function************************************************************* - - Synopsis [Replaces a fanin of the node.] - - Description [The node is pObj. An old fanin of this node (pFaninOld) has to be - replaced by a new fanin (pFaninNew). Assumes that the node and the old fanin - are not complemented. The new fanin can be complemented. In this case, the - polarity of the new fanin will change, compared to the polarity of the old fanin.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew ) -{ - Abc_Obj_t * pFaninNewR = Abc_ObjRegular(pFaninNew); - int iFanin;//, nLats;//, fCompl; - assert( !Abc_ObjIsComplement(pObj) ); - assert( !Abc_ObjIsComplement(pFaninOld) ); - assert( pFaninOld != pFaninNewR ); -// assert( pObj != pFaninOld ); -// assert( pObj != pFaninNewR ); - assert( pObj->pNtk == pFaninOld->pNtk ); - assert( pObj->pNtk == pFaninNewR->pNtk ); - if ( (iFanin = Vec_IntFind( &pObj->vFanins, pFaninOld->Id )) == -1 ) - { - printf( "Node %s is not among", Abc_ObjName(pFaninOld) ); - printf( " the fanins of node %s...\n", Abc_ObjName(pObj) ); - return; - } - - // remember the attributes of the old fanin -// fCompl = Abc_ObjFaninC(pObj, iFanin); - // replace the old fanin entry by the new fanin entry (removes attributes) - Vec_IntWriteEntry( &pObj->vFanins, iFanin, pFaninNewR->Id ); - // set the attributes of the new fanin -// if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) ) -// Abc_ObjSetFaninC( pObj, iFanin ); - if ( Abc_ObjIsComplement(pFaninNew) ) - Abc_ObjXorFaninC( pObj, iFanin ); - -// if ( Abc_NtkIsSeq(pObj->pNtk) && (nLats = Seq_ObjFaninL(pObj, iFanin)) ) -// Seq_ObjSetFaninL( pObj, iFanin, nLats ); - // update the fanout of the fanin - if ( !Vec_IntRemove( &pFaninOld->vFanouts, pObj->Id ) ) - { - printf( "Node %s is not among", Abc_ObjName(pObj) ); - printf( " the fanouts of its old fanin %s...\n", Abc_ObjName(pFaninOld) ); -// return; - } - Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, pObj->Id ); -} - -/**Function************************************************************* - - Synopsis [Inserts one-input node of the type specified between the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ) -{ - Abc_Obj_t * pNodeNew; - int iFanoutIndex, iFaninIndex; - // find pNodeOut among the fanouts of pNodeIn - if ( (iFanoutIndex = Vec_IntFind( &pNodeIn->vFanouts, pNodeOut->Id )) == -1 ) - { - printf( "Node %s is not among", Abc_ObjName(pNodeOut) ); - printf( " the fanouts of node %s...\n", Abc_ObjName(pNodeIn) ); - return NULL; - } - // find pNodeIn among the fanins of pNodeOut - if ( (iFaninIndex = Vec_IntFind( &pNodeOut->vFanins, pNodeIn->Id )) == -1 ) - { - printf( "Node %s is not among", Abc_ObjName(pNodeIn) ); - printf( " the fanins of node %s...\n", Abc_ObjName(pNodeOut) ); - return NULL; - } - // create the new node - pNodeNew = Abc_NtkCreateObj( pNodeIn->pNtk, Type ); - // add pNodeIn as fanin and pNodeOut as fanout - Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanins, pNodeIn->Id ); - Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanouts, pNodeOut->Id ); - // update the fanout of pNodeIn - Vec_IntWriteEntry( &pNodeIn->vFanouts, iFanoutIndex, pNodeNew->Id ); - // update the fanin of pNodeOut - Vec_IntWriteEntry( &pNodeOut->vFanins, iFaninIndex, pNodeNew->Id ); - return pNodeNew; -} - -/**Function************************************************************* - - Synopsis [Transfers fanout from the old node to the new node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjTransferFanout( Abc_Obj_t * pNodeFrom, Abc_Obj_t * pNodeTo ) -{ - Vec_Ptr_t * vFanouts; - int nFanoutsOld, i; - assert( !Abc_ObjIsComplement(pNodeFrom) ); - assert( !Abc_ObjIsComplement(pNodeTo) ); - assert( !Abc_ObjIsPo(pNodeFrom) && !Abc_ObjIsPo(pNodeTo) ); - assert( pNodeFrom->pNtk == pNodeTo->pNtk ); - assert( pNodeFrom != pNodeTo ); - assert( Abc_ObjFanoutNum(pNodeFrom) > 0 ); - // get the fanouts of the old node - nFanoutsOld = Abc_ObjFanoutNum(pNodeTo); - vFanouts = Vec_PtrAlloc( nFanoutsOld ); - Abc_NodeCollectFanouts( pNodeFrom, vFanouts ); - // patch the fanin of each of them - for ( i = 0; i < vFanouts->nSize; i++ ) - Abc_ObjPatchFanin( vFanouts->pArray[i], pNodeFrom, pNodeTo ); - assert( Abc_ObjFanoutNum(pNodeFrom) == 0 ); - assert( Abc_ObjFanoutNum(pNodeTo) == nFanoutsOld + vFanouts->nSize ); - Vec_PtrFree( vFanouts ); -} - -/**Function************************************************************* - - Synopsis [Replaces the node by a new node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjReplace( Abc_Obj_t * pNodeOld, Abc_Obj_t * pNodeNew ) -{ - assert( !Abc_ObjIsComplement(pNodeOld) ); - assert( !Abc_ObjIsComplement(pNodeNew) ); - assert( pNodeOld->pNtk == pNodeNew->pNtk ); - assert( pNodeOld != pNodeNew ); - assert( Abc_ObjFanoutNum(pNodeOld) > 0 ); - // transfer the fanouts to the old node - Abc_ObjTransferFanout( pNodeOld, pNodeNew ); - // remove the old node - Abc_NtkDeleteObj_rec( pNodeOld, 1 ); -} - -/**Function************************************************************* - - Synopsis [Returns the index of the fanin in the fanin list of the fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ) -{ - Abc_Obj_t * pObj; - int i; - Abc_ObjForEachFanin( pFanout, pObj, i ) - if ( pObj == pFanin ) - return i; - return -1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcFunc.c b/src/base/abc/abcFunc.c deleted file mode 100644 index f3297d8f..00000000 --- a/src/base/abc/abcFunc.c +++ /dev/null @@ -1,1154 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcFunc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Transformations between different functionality representations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcFunc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "main.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define ABC_MUX_CUBES 100000 - -static int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); -static DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot); -static Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Converts the network from SOP to BDD representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - DdManager * dd; - int nFaninsMax, i; - - assert( Abc_NtkHasSop(pNtk) ); - - // start the functionality manager - nFaninsMax = Abc_NtkGetFaninMax( pNtk ); - if ( nFaninsMax == 0 ) - printf( "Warning: The network has only constant nodes.\n" ); - - dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - - // convert each node from SOP to BDD - Abc_NtkForEachNode( pNtk, pNode, i ) - { - assert( pNode->pData ); - pNode->pData = Abc_ConvertSopToBdd( dd, pNode->pData ); - if ( pNode->pData == NULL ) - { - printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" ); - return 0; - } - Cudd_Ref( pNode->pData ); - } - - Extra_MmFlexStop( pNtk->pManFunc ); - pNtk->pManFunc = dd; - - // update the network type - pNtk->ntkFunc = ABC_FUNC_BDD; - return 1; -} - -/**Function************************************************************* - - Synopsis [Converts the node from SOP to BDD representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop ) -{ - DdNode * bSum, * bCube, * bTemp, * bVar; - char * pCube; - int nVars, Value, v; - - // start the cover - nVars = Abc_SopGetVarNum(pSop); - bSum = Cudd_ReadLogicZero(dd); Cudd_Ref( bSum ); - if ( Abc_SopIsExorType(pSop) ) - { - for ( v = 0; v < nVars; v++ ) - { - bSum = Cudd_bddXor( dd, bTemp = bSum, Cudd_bddIthVar(dd, v) ); Cudd_Ref( bSum ); - Cudd_RecursiveDeref( dd, bTemp ); - } - } - else - { - // check the logic function of the node - Abc_SopForEachCube( pSop, nVars, pCube ) - { - bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); - Abc_CubeForEachVar( pCube, Value, v ) - { - if ( Value == '0' ) - bVar = Cudd_Not( Cudd_bddIthVar( dd, v ) ); - else if ( Value == '1' ) - bVar = Cudd_bddIthVar( dd, v ); - else - continue; - bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - bSum = Cudd_bddOr( dd, bTemp = bSum, bCube ); - Cudd_Ref( bSum ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bCube ); - } - } - // complement the result if necessary - bSum = Cudd_NotCond( bSum, !Abc_SopGetPhase(pSop) ); - Cudd_Deref( bSum ); - return bSum; -} - -/**Function************************************************************* - - Synopsis [Removes complemented SOP covers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) -{ - DdManager * dd; - DdNode * bFunc; - Vec_Str_t * vCube; - Abc_Obj_t * pNode; - int nFaninsMax, fFound, i; - - assert( Abc_NtkHasSop(pNtk) ); - - // check if there are nodes with complemented SOPs - fFound = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( Abc_SopIsComplement(pNode->pData) ) - { - fFound = 1; - break; - } - if ( !fFound ) - return; - - // start the BDD package - nFaninsMax = Abc_NtkGetFaninMax( pNtk ); - if ( nFaninsMax == 0 ) - printf( "Warning: The network has only constant nodes.\n" ); - dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - - // change the cover of negated nodes - vCube = Vec_StrAlloc( 100 ); - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( Abc_SopIsComplement(pNode->pData) ) - { - bFunc = Abc_ConvertSopToBdd( dd, pNode->pData ); Cudd_Ref( bFunc ); - pNode->pData = Abc_ConvertBddToSop( pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, 1 ); - Cudd_RecursiveDeref( dd, bFunc ); - assert( !Abc_SopIsComplement(pNode->pData) ); - } - Vec_StrFree( vCube ); - Extra_StopManager( dd ); -} - - - - - -/**Function************************************************************* - - Synopsis [Converts the network from BDD to SOP representation.] - - Description [If the flag is set to 1, forces the direct phase of all covers.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fDirect ) -{ - Abc_Obj_t * pNode; - Extra_MmFlex_t * pManNew; - DdManager * dd = pNtk->pManFunc; - DdNode * bFunc; - Vec_Str_t * vCube; - int i, fMode; - - if ( fDirect ) - fMode = 1; - else - fMode = -1; - - assert( Abc_NtkHasBdd(pNtk) ); - if ( dd->size > 0 ) - Cudd_zddVarsFromBddVars( dd, 2 ); - // create the new manager - pManNew = Extra_MmFlexStart(); - - // go through the objects - vCube = Vec_StrAlloc( 100 ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - assert( pNode->pData ); - bFunc = pNode->pData; - pNode->pNext = (Abc_Obj_t *)Abc_ConvertBddToSop( pManNew, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, fMode ); - if ( pNode->pNext == NULL ) - { - Extra_MmFlexStop( pManNew ); - Abc_NtkCleanNext( pNtk ); -// printf( "Converting from BDDs to SOPs has failed.\n" ); - Vec_StrFree( vCube ); - return 0; - } - } - Vec_StrFree( vCube ); - - // update the network type - pNtk->ntkFunc = ABC_FUNC_SOP; - // set the new manager - pNtk->pManFunc = pManNew; - // transfer from next to data - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Cudd_RecursiveDeref( dd, pNode->pData ); - pNode->pData = pNode->pNext; - pNode->pNext = NULL; - } - - // check for remaining references in the package - Extra_StopManager( dd ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Converts the node from BDD to SOP representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode ) -{ - int fVerify = 0; - char * pSop; - DdNode * bFuncNew, * bCover, * zCover, * zCover0, * zCover1; - int nCubes, nCubes0, nCubes1, fPhase; - - assert( bFuncOn == bFuncOnDc || Cudd_bddLeq( dd, bFuncOn, bFuncOnDc ) ); - if ( Cudd_IsConstant(bFuncOn) || Cudd_IsConstant(bFuncOnDc) ) - { - if ( fMode == -1 ) // if the phase is not known, write constant 1 - fMode = 1; - Vec_StrFill( vCube, nFanins, '-' ); - Vec_StrPush( vCube, '\0' ); - if ( pMan ) - pSop = Extra_MmFlexEntryFetch( pMan, nFanins + 4 ); - else - pSop = ALLOC( char, nFanins + 4 ); - if ( bFuncOn == Cudd_ReadOne(dd) ) - sprintf( pSop, "%s %d\n", vCube->pArray, fMode ); - else - sprintf( pSop, "%s %d\n", vCube->pArray, !fMode ); - return pSop; - } - - - if ( fMode == -1 ) - { // try both phases - assert( fAllPrimes == 0 ); - - // get the ZDD of the negative polarity - bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover0 ); - Cudd_Ref( zCover0 ); - Cudd_Ref( bCover ); - Cudd_RecursiveDeref( dd, bCover ); - nCubes0 = Abc_CountZddCubes( dd, zCover0 ); - - // get the ZDD of the positive polarity - bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover1 ); - Cudd_Ref( zCover1 ); - Cudd_Ref( bCover ); - Cudd_RecursiveDeref( dd, bCover ); - nCubes1 = Abc_CountZddCubes( dd, zCover1 ); - - // compare the number of cubes - if ( nCubes1 <= nCubes0 ) - { // use positive polarity - nCubes = nCubes1; - zCover = zCover1; - Cudd_RecursiveDerefZdd( dd, zCover0 ); - fPhase = 1; - } - else - { // use negative polarity - nCubes = nCubes0; - zCover = zCover0; - Cudd_RecursiveDerefZdd( dd, zCover1 ); - fPhase = 0; - } - } - else if ( fMode == 0 ) - { - // get the ZDD of the negative polarity - if ( fAllPrimes ) - { - zCover = Extra_zddPrimes( dd, Cudd_Not(bFuncOnDc) ); - Cudd_Ref( zCover ); - } - else - { - bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover ); - Cudd_Ref( zCover ); - Cudd_Ref( bCover ); - Cudd_RecursiveDeref( dd, bCover ); - } - nCubes = Abc_CountZddCubes( dd, zCover ); - fPhase = 0; - } - else if ( fMode == 1 ) - { - // get the ZDD of the positive polarity - if ( fAllPrimes ) - { - zCover = Extra_zddPrimes( dd, bFuncOnDc ); - Cudd_Ref( zCover ); - } - else - { - bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover ); - Cudd_Ref( zCover ); - Cudd_Ref( bCover ); - Cudd_RecursiveDeref( dd, bCover ); - } - nCubes = Abc_CountZddCubes( dd, zCover ); - fPhase = 1; - } - else - { - assert( 0 ); - } - - if ( nCubes > ABC_MUX_CUBES ) - { - Cudd_RecursiveDerefZdd( dd, zCover ); - printf( "The number of cubes exceeded the predefined limit (%d).\n", ABC_MUX_CUBES ); - return NULL; - } - - // allocate memory for the cover - if ( pMan ) - pSop = Extra_MmFlexEntryFetch( pMan, (nFanins + 3) * nCubes + 1 ); - else - pSop = ALLOC( char, (nFanins + 3) * nCubes + 1 ); - pSop[(nFanins + 3) * nCubes] = 0; - // create the SOP - Vec_StrFill( vCube, nFanins, '-' ); - Vec_StrPush( vCube, '\0' ); - Abc_ConvertZddToSop( dd, zCover, pSop, nFanins, vCube, fPhase ); - Cudd_RecursiveDerefZdd( dd, zCover ); - - // verify - if ( fVerify ) - { - bFuncNew = Abc_ConvertSopToBdd( dd, pSop ); Cudd_Ref( bFuncNew ); - if ( bFuncOn == bFuncOnDc ) - { - if ( bFuncNew != bFuncOn ) - printf( "Verification failed.\n" ); - } - else - { - if ( !Cudd_bddLeq(dd, bFuncOn, bFuncNew) || !Cudd_bddLeq(dd, bFuncNew, bFuncOnDc) ) - printf( "Verification failed.\n" ); - } - Cudd_RecursiveDeref( dd, bFuncNew ); - } - return pSop; -} - -/**Function************************************************************* - - Synopsis [Derive the SOP from the ZDD representation of the cubes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ConvertZddToSop_rec( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase, int * pnCubes ) -{ - DdNode * zC0, * zC1, * zC2; - int Index; - - if ( zCover == dd->zero ) - return; - if ( zCover == dd->one ) - { - char * pCube; - pCube = pSop + (*pnCubes) * (nFanins + 3); - sprintf( pCube, "%s %d\n", vCube->pArray, fPhase ); - (*pnCubes)++; - return; - } - Index = zCover->index/2; - assert( Index < nFanins ); - extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 ); - vCube->pArray[Index] = '0'; - Abc_ConvertZddToSop_rec( dd, zC0, pSop, nFanins, vCube, fPhase, pnCubes ); - vCube->pArray[Index] = '1'; - Abc_ConvertZddToSop_rec( dd, zC1, pSop, nFanins, vCube, fPhase, pnCubes ); - vCube->pArray[Index] = '-'; - Abc_ConvertZddToSop_rec( dd, zC2, pSop, nFanins, vCube, fPhase, pnCubes ); -} - -/**Function************************************************************* - - Synopsis [Derive the BDD for the function in the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ) -{ - int nCubes = 0; - Abc_ConvertZddToSop_rec( dd, zCover, pSop, nFanins, vCube, fPhase, &nCubes ); - return nCubes; -} - - -/**Function************************************************************* - - Synopsis [Computes the SOPs of the negative and positive phase of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Extra_MmFlex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ) -{ - assert( Abc_NtkHasBdd(pNode->pNtk) ); - *ppSop0 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 0 ); - *ppSop1 = Abc_ConvertBddToSop( pMmMan, pNode->pNtk->pManFunc, pNode->pData, pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 1 ); -} - - - - -/**Function************************************************************* - - Synopsis [Count the number of paths in the ZDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_CountZddCubes_rec( DdManager * dd, DdNode * zCover, int * pnCubes ) -{ - DdNode * zC0, * zC1, * zC2; - if ( zCover == dd->zero ) - return; - if ( zCover == dd->one ) - { - (*pnCubes)++; - return; - } - if ( (*pnCubes) > ABC_MUX_CUBES ) - return; - extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 ); - Abc_CountZddCubes_rec( dd, zC0, pnCubes ); - Abc_CountZddCubes_rec( dd, zC1, pnCubes ); - Abc_CountZddCubes_rec( dd, zC2, pnCubes ); -} - -/**Function************************************************************* - - Synopsis [Count the number of paths in the ZDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ) -{ - int nCubes = 0; - Abc_CountZddCubes_rec( dd, zCover, &nCubes ); - return nCubes; -} - - -/**Function************************************************************* - - Synopsis [Converts the network from SOP to AIG representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - Hop_Man_t * pMan; - int i; - - assert( Abc_NtkHasSop(pNtk) ); - - // start the functionality manager - pMan = Hop_ManStart(); - - // convert each node from SOP to BDD - Abc_NtkForEachNode( pNtk, pNode, i ) - { - assert( pNode->pData ); - pNode->pData = Abc_ConvertSopToAig( pMan, pNode->pData ); - if ( pNode->pData == NULL ) - { - printf( "Abc_NtkSopToAig: Error while converting SOP into AIG.\n" ); - return 0; - } - } - Extra_MmFlexStop( pNtk->pManFunc ); - pNtk->pManFunc = pMan; - - // update the network type - pNtk->ntkFunc = ABC_FUNC_AIG; - return 1; -} - - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Abc_ConvertSopToAigInternal( Hop_Man_t * pMan, char * pSop ) -{ - Hop_Obj_t * pAnd, * pSum; - int i, Value, nFanins; - char * pCube; - // get the number of variables - nFanins = Abc_SopGetVarNum(pSop); - // go through the cubes of the node's SOP - pSum = Hop_ManConst0(pMan); - Abc_SopForEachCube( pSop, nFanins, pCube ) - { - // create the AND of literals - pAnd = Hop_ManConst1(pMan); - Abc_CubeForEachVar( pCube, Value, i ) - { - if ( Value == '1' ) - pAnd = Hop_And( pMan, pAnd, Hop_IthVar(pMan,i) ); - else if ( Value == '0' ) - pAnd = Hop_And( pMan, pAnd, Hop_Not(Hop_IthVar(pMan,i)) ); - } - // add to the sum of cubes - pSum = Hop_Or( pMan, pSum, pAnd ); - } - // decide whether to complement the result - if ( Abc_SopIsComplement(pSop) ) - pSum = Hop_Not(pSum); - return pSum; -} - -/**Function************************************************************* - - Synopsis [Converts the network from AIG to BDD representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ) -{ - extern Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop ); - int fUseFactor = 1; - // consider the constant node - if ( Abc_SopGetVarNum(pSop) == 0 ) - return Hop_NotCond( Hop_ManConst1(pMan), Abc_SopIsConst0(pSop) ); - // consider the special case of EXOR function - if ( Abc_SopIsExorType(pSop) ) - return Hop_NotCond( Hop_CreateExor(pMan, Abc_SopGetVarNum(pSop)), Abc_SopIsComplement(pSop) ); - // decide when to use factoring - if ( fUseFactor && Abc_SopGetVarNum(pSop) > 2 && Abc_SopGetCubeNum(pSop) > 1 ) - return Dec_GraphFactorSop( pMan, pSop ); - return Abc_ConvertSopToAigInternal( pMan, pSop ); -} - -/**Function************************************************************* - - Synopsis [Converts the network from AIG to BDD representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - Hop_Man_t * pMan; - DdManager * dd; - int nFaninsMax, i; - - assert( Abc_NtkHasAig(pNtk) ); - - // start the functionality manager - nFaninsMax = Abc_NtkGetFaninMax( pNtk ); - if ( nFaninsMax == 0 ) - printf( "Warning: The network has only constant nodes.\n" ); - - dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - - // set the mapping of elementary AIG nodes into the elementary BDD nodes - pMan = pNtk->pManFunc; - assert( Hop_ManPiNum(pMan) >= nFaninsMax ); - for ( i = 0; i < nFaninsMax; i++ ) - { - Hop_ManPi(pMan, i)->pData = Cudd_bddIthVar(dd, i); - Cudd_Ref( Hop_ManPi(pMan, i)->pData ); - } - - // convert each node from SOP to BDD - Abc_NtkForEachNode( pNtk, pNode, i ) - { - assert( pNode->pData ); - pNode->pData = Abc_ConvertAigToBdd( dd, pNode->pData ); - if ( pNode->pData == NULL ) - { - printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" ); - return 0; - } - Cudd_Ref( pNode->pData ); - } - - // dereference intermediate BDD nodes - for ( i = 0; i < nFaninsMax; i++ ) - Cudd_RecursiveDeref( dd, Hop_ManPi(pMan, i)->pData ); - - Hop_ManStop( pNtk->pManFunc ); - pNtk->pManFunc = dd; - - // update the network type - pNtk->ntkFunc = ABC_FUNC_BDD; - return 1; -} - -/**Function************************************************************* - - Synopsis [Construct BDDs and mark AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ConvertAigToBdd_rec1( DdManager * dd, Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) - return; - Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin0(pObj) ); - Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin1(pObj) ); - pObj->pData = Cudd_bddAnd( dd, (DdNode *)Hop_ObjChild0Copy(pObj), (DdNode *)Hop_ObjChild1Copy(pObj) ); - Cudd_Ref( pObj->pData ); - assert( !Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Dereference BDDs and unmark AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ConvertAigToBdd_rec2( DdManager * dd, Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) - return; - Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin0(pObj) ); - Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin1(pObj) ); - Cudd_RecursiveDeref( dd, pObj->pData ); - pObj->pData = NULL; - assert( Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjClearMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Converts the network from AIG to BDD representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot ) -{ - DdNode * bFunc; - // check the case of a constant - if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) - return Cudd_NotCond( Cudd_ReadOne(dd), Hop_IsComplement(pRoot) ); - // construct BDD - Abc_ConvertAigToBdd_rec1( dd, Hop_Regular(pRoot) ); - // hold on to the result - bFunc = Cudd_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); Cudd_Ref( bFunc ); - // dereference BDD - Abc_ConvertAigToBdd_rec2( dd, Hop_Regular(pRoot) ); - // return the result - Cudd_Deref( bFunc ); - return bFunc; -} - - - -/**Function************************************************************* - - Synopsis [Construct BDDs and mark AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ConvertAigToTruth_rec1( Hop_Obj_t * pObj ) -{ - int Counter = 0; - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) - return 0; - Counter += Abc_ConvertAigToTruth_rec1( Hop_ObjFanin0(pObj) ); - Counter += Abc_ConvertAigToTruth_rec1( Hop_ObjFanin1(pObj) ); - assert( !Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjSetMarkA( pObj ); - return Counter + 1; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Abc_ConvertAigToTruth_rec2( Hop_Obj_t * pObj, Vec_Int_t * vTruth, int nWords ) -{ - unsigned * pTruth, * pTruth0, * pTruth1; - int i; - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) - return pObj->pData; - // compute the truth tables of the fanins - pTruth0 = Abc_ConvertAigToTruth_rec2( Hop_ObjFanin0(pObj), vTruth, nWords ); - pTruth1 = Abc_ConvertAigToTruth_rec2( Hop_ObjFanin1(pObj), vTruth, nWords ); - // creat the truth table of the node - pTruth = Vec_IntFetch( vTruth, nWords ); - if ( Hop_ObjIsExor(pObj) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] ^ pTruth1[i]; - else if ( !Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] & pTruth1[i]; - else if ( !Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = pTruth0[i] & ~pTruth1[i]; - else if ( Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ~pTruth0[i] & pTruth1[i]; - else // if ( Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) ) - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; - assert( Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjClearMarkA( pObj ); - pObj->pData = pTruth; - return pTruth; -} - -/**Function************************************************************* - - Synopsis [Computes truth table of the node.] - - Description [Assumes that the structural support is no more than 8 inputs. - Uses array vTruth to store temporary truth tables. The returned pointer should - be used immediately.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Abc_ConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst ) -{ - static unsigned uTruths[8][8] = { // elementary truth tables - { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, - { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, - { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, - { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, - { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, - { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, - { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, - { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } - }; - Hop_Obj_t * pObj; - unsigned * pTruth, * pTruth2; - int i, nWords, nNodes; - Vec_Ptr_t * vTtElems; - - // if the number of variables is more than 8, allocate truth tables - if ( nVars > 8 ) - vTtElems = Vec_PtrAllocTruthTables( nVars ); - else - vTtElems = NULL; - - // clear the data fields and set marks - nNodes = Abc_ConvertAigToTruth_rec1( pRoot ); - // prepare memory - nWords = Hop_TruthWordNum( nVars ); - Vec_IntClear( vTruth ); - Vec_IntGrow( vTruth, nWords * (nNodes+1) ); - pTruth = Vec_IntFetch( vTruth, nWords ); - // check the case of a constant - if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) - { - assert( nNodes == 0 ); - if ( Hop_IsComplement(pRoot) ) - Extra_TruthClear( pTruth, nVars ); - else - Extra_TruthFill( pTruth, nVars ); - return pTruth; - } - // set elementary truth tables at the leaves - assert( nVars <= Hop_ManPiNum(p) ); -// assert( Hop_ManPiNum(p) <= 8 ); - if ( fMsbFirst ) - { - Hop_ManForEachPi( p, pObj, i ) - { - if ( vTtElems ) - pObj->pData = Vec_PtrEntry(vTtElems, nVars-1-i); - else - pObj->pData = (void *)uTruths[nVars-1-i]; - } - } - else - { - Hop_ManForEachPi( p, pObj, i ) - { - if ( vTtElems ) - pObj->pData = Vec_PtrEntry(vTtElems, i); - else - pObj->pData = (void *)uTruths[i]; - } - } - // clear the marks and compute the truth table - pTruth2 = Abc_ConvertAigToTruth_rec2( pRoot, vTruth, nWords ); - // copy the result - Extra_TruthCopy( pTruth, pTruth2, nVars ); - if ( vTtElems ) - Vec_PtrFree( vTtElems ); - return pTruth; -} - - -/**Function************************************************************* - - Synopsis [Construct BDDs and mark AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ConvertAigToAig_rec( Abc_Ntk_t * pNtkAig, Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) - return; - Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin0(pObj) ); - Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin1(pObj) ); - pObj->pData = Abc_AigAnd( pNtkAig->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); - assert( !Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Converts the network from AIG to BDD representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObjOld ) -{ - Hop_Man_t * pHopMan; - Hop_Obj_t * pRoot; - Abc_Obj_t * pFanin; - int i; - // get the local AIG - pHopMan = pObjOld->pNtk->pManFunc; - pRoot = pObjOld->pData; - // check the case of a constant - if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) - return Abc_ObjNotCond( Abc_AigConst1(pNtkAig), Hop_IsComplement(pRoot) ); - // assign the fanin nodes - Abc_ObjForEachFanin( pObjOld, pFanin, i ) - { - assert( pFanin->pCopy != NULL ); - Hop_ManPi(pHopMan, i)->pData = pFanin->pCopy; - } - // construct the AIG - Abc_ConvertAigToAig_rec( pNtkAig, Hop_Regular(pRoot) ); - Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); - // return the result - return Abc_ObjNotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); -} - - -/**Function************************************************************* - - Synopsis [Unmaps the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ) -{ - extern void * Abc_FrameReadLibGen(); - Abc_Obj_t * pNode; - char * pSop; - int i; - - assert( Abc_NtkHasMapping(pNtk) ); - // update the functionality manager - assert( pNtk->pManFunc == Abc_FrameReadLibGen() ); - pNtk->pManFunc = Extra_MmFlexStart(); - pNtk->ntkFunc = ABC_FUNC_SOP; - // update the nodes - Abc_NtkForEachNode( pNtk, pNode, i ) - { - pSop = Mio_GateReadSop(pNode->pData); - assert( Abc_SopGetVarNum(pSop) == Abc_ObjFaninNum(pNode) ); - pNode->pData = Abc_SopRegister( pNtk->pManFunc, pSop ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Converts SOP functions into BLIF-MV functions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkSopToBlifMv( Abc_Ntk_t * pNtk ) -{ - return 1; -} - -/**Function************************************************************* - - Synopsis [Convers logic network to the SOP form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fDirect ) -{ - assert( !Abc_NtkIsStrash(pNtk) ); - if ( Abc_NtkHasSop(pNtk) ) - { - if ( !fDirect ) - return 1; - if ( !Abc_NtkSopToBdd(pNtk) ) - return 0; - return Abc_NtkBddToSop(pNtk, fDirect); - } - if ( Abc_NtkHasMapping(pNtk) ) - return Abc_NtkMapToSop(pNtk); - if ( Abc_NtkHasBdd(pNtk) ) - return Abc_NtkBddToSop(pNtk, fDirect); - if ( Abc_NtkHasAig(pNtk) ) - { - if ( !Abc_NtkAigToBdd(pNtk) ) - return 0; - return Abc_NtkBddToSop(pNtk, fDirect); - } - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Convers logic network to the SOP form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkToBdd( Abc_Ntk_t * pNtk ) -{ - assert( !Abc_NtkIsStrash(pNtk) ); - if ( Abc_NtkHasBdd(pNtk) ) - return 1; - if ( Abc_NtkHasMapping(pNtk) ) - { - Abc_NtkMapToSop(pNtk); - return Abc_NtkSopToBdd(pNtk); - } - if ( Abc_NtkHasSop(pNtk) ) - return Abc_NtkSopToBdd(pNtk); - if ( Abc_NtkHasAig(pNtk) ) - return Abc_NtkAigToBdd(pNtk); - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Convers logic network to the SOP form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkToAig( Abc_Ntk_t * pNtk ) -{ - assert( !Abc_NtkIsStrash(pNtk) ); - if ( Abc_NtkHasAig(pNtk) ) - return 1; - if ( Abc_NtkHasMapping(pNtk) ) - { - Abc_NtkMapToSop(pNtk); - return Abc_NtkSopToAig(pNtk); - } - if ( Abc_NtkHasBdd(pNtk) ) - { - if ( !Abc_NtkBddToSop(pNtk,0) ) - return 0; - return Abc_NtkSopToAig(pNtk); - } - if ( Abc_NtkHasSop(pNtk) ) - return Abc_NtkSopToAig(pNtk); - assert( 0 ); - return 0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcHie.c b/src/base/abc/abcHie.c deleted file mode 100644 index 56333a36..00000000 --- a/src/base/abc/abcHie.c +++ /dev/null @@ -1,492 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcHie.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures to handle hierarchy.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Recursively flattens logic hierarchy of the netlist.] - - Description [When this procedure is called, the PI/PO nets of the old - netlist point to the corresponding nets of the flattened netlist.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFlattenLogicHierarchy_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter ) -{ - char Suffix[1000] = {0}; - Abc_Ntk_t * pNtkModel; - Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin; - int i, k; - - // process the blackbox - if ( Abc_NtkHasBlackbox(pNtk) ) - { - // duplicate the blackbox - assert( Abc_NtkBoxNum(pNtk) == 1 ); - pObj = Abc_NtkBox( pNtk, 0 ); - Abc_NtkDupBox( pNtkNew, pObj, 1 ); - pObj->pCopy->pData = pNtk; - - // connect blackbox fanins to the PI nets - assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) ); - Abc_NtkForEachPi( pNtk, pTerm, i ) - Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy ); - - // connect blackbox fanouts to the PO nets - assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) ); - Abc_NtkForEachPo( pNtk, pTerm, i ) - Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) ); - return; - } - - (*pCounter)++; - - // create the prefix, which will be appended to the internal names - if ( *pCounter ) - sprintf( Suffix, "_%s_%d", Abc_NtkName(pNtk), *pCounter ); - - // duplicate nets of all boxes, including latches - Abc_NtkForEachBox( pNtk, pObj, i ) - { - Abc_ObjForEachFanin( pObj, pTerm, k ) - { - pNet = Abc_ObjFanin0(pTerm); - if ( pNet->pCopy ) - continue; - pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) ); - } - Abc_ObjForEachFanout( pObj, pTerm, k ) - { - pNet = Abc_ObjFanout0(pTerm); - if ( pNet->pCopy ) - continue; - pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) ); - } - } - - // mark objects that will not be used - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachPi( pNtk, pTerm, i ) - Abc_NodeSetTravIdCurrent( pTerm ); - Abc_NtkForEachPo( pNtk, pTerm, i ) - Abc_NodeSetTravIdCurrent( pTerm ); - Abc_NtkForEachBox( pNtk, pObj, i ) - { - if ( Abc_ObjIsLatch(pObj) ) - continue; - Abc_NodeSetTravIdCurrent( pObj ); - Abc_ObjForEachFanin( pObj, pTerm, k ) - Abc_NodeSetTravIdCurrent( pTerm ); - Abc_ObjForEachFanout( pObj, pTerm, k ) - Abc_NodeSetTravIdCurrent( pTerm ); - } - - // duplicate objects that do not have prototypes yet - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( Abc_NodeIsTravIdCurrent(pObj) ) - continue; - if ( pObj->pCopy ) - continue; - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - } - - // connect objects - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_NodeIsTravIdCurrent(pObj) ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - if ( !Abc_NodeIsTravIdCurrent(pFanin) ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - - // call recursively - Abc_NtkForEachBox( pNtk, pObj, i ) - { - if ( Abc_ObjIsLatch(pObj) ) - continue; - pNtkModel = pObj->pData; - // check the match between the number of actual and formal parameters - assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) ); - assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) ); - // clean the node copy fields - Abc_NtkCleanCopy( pNtkModel ); - // map PIs/POs - Abc_ObjForEachFanin( pObj, pTerm, k ) - Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy; - Abc_ObjForEachFanout( pObj, pTerm, k ) - Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy; - // call recursively - Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtkModel, pCounter ); - } - - // if it is a BLIF-MV netlist transfer the values of all nets - if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) - { - if ( Abc_NtkMvVar( pNtkNew ) == NULL ) - Abc_NtkStartMvVars( pNtkNew ); - Abc_NtkForEachNet( pNtk, pObj, i ) - Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); - } -} - -/**Function************************************************************* - - Synopsis [Flattens the logic hierarchy of the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pTerm, * pNet; - int i, Counter; - extern Abc_Lib_t * Abc_LibDupBlackboxes( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave ); - - assert( Abc_NtkIsNetlist(pNtk) ); - // start the network - pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); - // duplicate the name and the spec - pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); - pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); - - // clean the node copy fields - Abc_NtkCleanCopy( pNtk ); - - // duplicate PIs/POs and their nets - Abc_NtkForEachPi( pNtk, pTerm, i ) - { - Abc_NtkDupObj( pNtkNew, pTerm, 0 ); - pNet = Abc_ObjFanout0( pTerm ); - pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); - Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy ); - } - Abc_NtkForEachPo( pNtk, pTerm, i ) - { - Abc_NtkDupObj( pNtkNew, pTerm, 0 ); - pNet = Abc_ObjFanin0( pTerm ); - pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); - Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy ); - } - - // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes - Counter = -1; - Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtk, &Counter ); - printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n", - Counter, Abc_NtkBlackboxNum(pNtkNew) ); - - if ( pNtk->pDesign ) - { - // pass on the design - assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk ); - pNtkNew->pDesign = Abc_LibDupBlackboxes( pNtk->pDesign, pNtkNew ); - // update the pointers - Abc_NtkForEachBlackbox( pNtkNew, pTerm, i ) - pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy; - } - - // copy the timing information -// Abc_ManTimeDup( pNtk, pNtkNew ); - // duplicate EXDC - if ( pNtk->pExdc ) - printf( "EXDC is not transformed.\n" ); - if ( !Abc_NtkCheck( pNtkNew ) ) - { - fprintf( stdout, "Abc_NtkFlattenLogicHierarchy(): Network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Extracts blackboxes by making them into additional PIs/POs.] - - Description [The input netlist has not logic hierarchy. The resulting - netlist has additional PIs/POs for each blackbox input/output.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pNet, * pFanin, * pTerm; - int i, k; - - assert( Abc_NtkIsNetlist(pNtk) ); - assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); - - // start the network - pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); - // duplicate the name and the spec - pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); - pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); - - // clean the node copy fields - Abc_NtkCleanCopy( pNtk ); - - // mark the nodes that should not be connected - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachBlackbox( pNtk, pObj, i ) - Abc_NodeSetTravIdCurrent( pObj ); - Abc_NtkForEachCi( pNtk, pTerm, i ) - Abc_NodeSetTravIdCurrent( pTerm ); - Abc_NtkForEachCo( pNtk, pTerm, i ) - Abc_NodeSetTravIdCurrent( pTerm ); - // unmark PIs and LIs/LOs - Abc_NtkForEachPi( pNtk, pTerm, i ) - Abc_NodeSetTravIdPrevious( pTerm ); - Abc_NtkForEachLatchInput( pNtk, pTerm, i ) - Abc_NodeSetTravIdPrevious( pTerm ); - Abc_NtkForEachLatchOutput( pNtk, pTerm, i ) - Abc_NodeSetTravIdPrevious( pTerm ); - // copy the box outputs - Abc_NtkForEachBlackbox( pNtk, pObj, i ) - Abc_ObjForEachFanout( pObj, pTerm, k ) - pTerm->pCopy = Abc_NtkCreatePi( pNtkNew ); - - // duplicate other objects - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_NodeIsTravIdCurrent(pObj) ) - Abc_NtkDupObj( pNtkNew, pObj, Abc_ObjIsNet(pObj) ); - - // connect all objects - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_NodeIsTravIdCurrent(pObj) ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - - // create unique PO for each net feeding into blackboxes or POs - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachCo( pNtk, pTerm, i ) - { - // skip latch inputs - assert( Abc_ObjFanoutNum(pTerm) <= 1 ); - if ( Abc_ObjFanoutNum(pTerm) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pTerm)) ) - continue; - // check if the net is visited - pNet = Abc_ObjFanin0(pTerm); - if ( Abc_NodeIsTravIdCurrent(pNet) ) - continue; - // create PO - Abc_NodeSetTravIdCurrent( pNet ); - Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNet->pCopy ); - } - - // check integrity - if ( !Abc_NtkCheck( pNtkNew ) ) - { - fprintf( stdout, "Abc_NtkConvertBlackboxes(): Network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Inserts blackboxes into the netlist.] - - Description [The first arg is the netlist with blackboxes without logic hierarchy. - The second arg is a non-hierarchical netlist derived from the above netlist after processing. - This procedure create a new netlist, which is comparable to the original netlist with - blackboxes, except that it contains logic nodes from the netlist after processing.] - - SideEffects [This procedure silently assumes that blackboxes appear - only in the top-level model. If they appear in other models as well, - the name of the model and its number were appended to the names of - blackbox inputs/outputs.] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL ) -{ - Abc_Lib_t * pDesign; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObjH, * pObjL, * pNetH, * pNetL, * pTermH; - int i, k; - - assert( Abc_NtkIsNetlist(pNtkH) ); - assert( Abc_NtkWhiteboxNum(pNtkH) == 0 ); - assert( Abc_NtkBlackboxNum(pNtkH) > 0 ); - - assert( Abc_NtkIsNetlist(pNtkL) ); - assert( Abc_NtkWhiteboxNum(pNtkL) == 0 ); - assert( Abc_NtkBlackboxNum(pNtkL) == 0 ); - - // prepare the logic network for copying - Abc_NtkCleanCopy( pNtkL ); - - // start the network - pNtkNew = Abc_NtkAlloc( pNtkL->ntkType, pNtkL->ntkFunc, 1 ); - // duplicate the name and the spec - pNtkNew->pName = Extra_UtilStrsav( pNtkH->pName ); - pNtkNew->pSpec = Extra_UtilStrsav( pNtkH->pSpec ); - - // make sure every PI/PO has a PI/PO in the processed network - Abc_NtkForEachPi( pNtkH, pObjH, i ) - { - pNetH = Abc_ObjFanout0(pObjH); - pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); - if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) ) - { - printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the PI %s.\n", Abc_ObjName(pNetH) ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - if ( pNetL->pCopy ) - { - printf( "Error in Abc_NtkInsertNewLogic(): Primary input %s is repeated twice.\n", Abc_ObjName(pNetH) ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - // create the new net - pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); - Abc_NtkDupObj( pNtkNew, Abc_ObjFanin0(pNetL), 0 ); - } - - // make sure every BB has a PI/PO in the processed network - Abc_NtkForEachBlackbox( pNtkH, pObjH, i ) - { - // duplicate the box - Abc_NtkDupBox( pNtkNew, pObjH, 0 ); - pObjH->pCopy->pData = pObjH->pData; - // create PIs - Abc_ObjForEachFanout( pObjH, pTermH, k ) - { - pNetH = Abc_ObjFanout0( pTermH ); - pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); - if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) ) - { - printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the inpout %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - if ( pNetL->pCopy ) - { - printf( "Error in Abc_NtkInsertNewLogic(): Box output %s is repeated twice.\n", Abc_ObjName(pNetH) ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - // create net and map the PI - pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); - Abc_ObjFanin0(pNetL)->pCopy = pTermH->pCopy; - } - } - - Abc_NtkForEachPo( pNtkH, pObjH, i ) - { - pNetH = Abc_ObjFanin0(pObjH); - pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); - if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) ) - { - printf( "Error in Abc_NtkInsertNewLogic(): There is no PO corresponding to the PO %s.\n", Abc_ObjName(pNetH) ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - if ( pNetL->pCopy ) - continue; - // create the new net - pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); - Abc_NtkDupObj( pNtkNew, Abc_ObjFanout0(pNetL), 0 ); - } - Abc_NtkForEachBlackbox( pNtkH, pObjH, i ) - { - Abc_ObjForEachFanin( pObjH, pTermH, k ) - { - char * pName; - pNetH = Abc_ObjFanin0( pTermH ); - pName = Abc_ObjName(pNetH); - pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); - if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) ) - { - printf( "There is no PO corresponding to the input %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - // create net and map the PO - if ( pNetL->pCopy ) - { - if ( Abc_ObjFanout0(pNetL)->pCopy == NULL ) - Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy; - else - Abc_ObjAddFanin( pTermH->pCopy, pNetL->pCopy ); - continue; - } - pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); - Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy; - } - } - - // duplicate other objects of the logic network - Abc_NtkForEachObj( pNtkL, pObjL, i ) - if ( pObjL->pCopy == NULL && !Abc_ObjIsPo(pObjL) ) // skip POs feeding into PIs - Abc_NtkDupObj( pNtkNew, pObjL, Abc_ObjIsNet(pObjL) ); - - // connect objects - Abc_NtkForEachObj( pNtkL, pObjL, i ) - Abc_ObjForEachFanin( pObjL, pNetL, k ) - if ( pObjL->pCopy ) - Abc_ObjAddFanin( pObjL->pCopy, pNetL->pCopy ); - - // transfer the design - pDesign = pNtkH->pDesign; pNtkH->pDesign = NULL; - assert( Vec_PtrEntry( pDesign->vModules, 0 ) == pNtkH ); - Vec_PtrWriteEntry( pDesign->vModules, 0, pNtkNew ); - pNtkNew->pDesign = pDesign; - -//Abc_NtkPrintStats( stdout, pNtkH, 0 ); -//Abc_NtkPrintStats( stdout, pNtkNew, 0 ); - - // check integrity - if ( !Abc_NtkCheck( pNtkNew ) ) - { - fprintf( stdout, "Abc_NtkInsertNewLogic(): Network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcInt.h b/src/base/abc/abcInt.h deleted file mode 100644 index 0e35e774..00000000 --- a/src/base/abc/abcInt.h +++ /dev/null @@ -1,52 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __ABC_INT_H__ -#define __ABC_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -#define ABC_NUM_STEPS 10 - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcLatch.c b/src/base/abc/abcLatch.c deleted file mode 100644 index d96bbfac..00000000 --- a/src/base/abc/abcLatch.c +++ /dev/null @@ -1,326 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcLatch.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures working with latches.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcLatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks if latches form self-loop.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkLatchIsSelfFeed_rec( Abc_Obj_t * pLatch, Abc_Obj_t * pLatchRoot ) -{ - Abc_Obj_t * pFanin; - assert( Abc_ObjIsLatch(pLatch) ); - if ( pLatch == pLatchRoot ) - return 1; - pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); - if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) - return 0; - return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); -} - -/**Function************************************************************* - - Synopsis [Checks if latches form self-loop.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ) -{ - Abc_Obj_t * pFanin; - assert( Abc_ObjIsLatch(pLatch) ); - pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); - if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) - return 0; - return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); -} - -/**Function************************************************************* - - Synopsis [Checks if latches form self-loop.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pLatch; - int i, Counter; - Counter = 0; - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { -// if ( Abc_NtkLatchIsSelfFeed(pLatch) && Abc_ObjFanoutNum(pLatch) > 1 ) -// printf( "Fanouts = %d.\n", Abc_ObjFanoutNum(pLatch) ); - Counter += Abc_NtkLatchIsSelfFeed( pLatch ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Replaces self-feeding latches by latches with constant inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pLatch, * pConst1; - int i, Counter; - Counter = 0; - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - if ( Abc_NtkLatchIsSelfFeed( pLatch ) ) - { - if ( Abc_NtkIsStrash(pNtk) ) - pConst1 = Abc_AigConst1(pNtk); - else - pConst1 = Abc_NtkCreateNodeConst1(pNtk); - Abc_ObjPatchFanin( Abc_ObjFanin0(pLatch), Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pConst1 ); - Counter++; - } - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Pipelines the network with latches.] - - Description [] - - SideEffects [Does not check the names of the added latches!!!] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pLatch, * pFanin, * pFanout; - int i, k, nTotal, nDigits; - if ( nLatches < 1 ) - return; - nTotal = nLatches * Abc_NtkPiNum(pNtk); - nDigits = Extra_Base10Log( nTotal ); - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachPi( pNtk, pObj, i ) - { - // remember current fanins of the PI - Abc_NodeCollectFanouts( pObj, vNodes ); - // create the latches - for ( pFanin = pObj, k = 0; k < nLatches; k++, pFanin = pLatch ) - { - pLatch = Abc_NtkCreateLatch( pNtk ); - Abc_ObjAddFanin( pLatch, pFanin ); - Abc_LatchSetInitDc( pLatch ); - // create the name of the new latch - Abc_ObjAssignName( pLatch, Abc_ObjNameDummy("LL", i*nLatches + k, nDigits), NULL ); - } - // patch the PI fanouts - Vec_PtrForEachEntry( vNodes, pFanout, k ) - Abc_ObjPatchFanin( pFanout, pObj, pFanin ); - } - Vec_PtrFree( vNodes ); - Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk ) -{ - Vec_Int_t * vValues; - Abc_Obj_t * pLatch; - int i; - vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - Vec_IntPush( vValues, Abc_LatchIsInit1(pLatch) ); - return vValues; -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ) -{ - Abc_Obj_t * pLatch; - int i; - Abc_NtkForEachLatch( pNtk, pLatch, i ) - pLatch->pData = (void *)(vValues? (Vec_IntEntry(vValues,i)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC); -} - -/**Function************************************************************* - - Synopsis [Creates latch with the given initial value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init ) -{ - Abc_Obj_t * pLatchOut, * pLatch, * pLatchIn; - pLatchOut = Abc_NtkCreateBo(pNtk); - pLatch = Abc_NtkCreateLatch(pNtk); - pLatchIn = Abc_NtkCreateBi(pNtk); - Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_lo" ); - Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_li" ); - Abc_ObjAddFanin( pLatchOut, pLatch ); - Abc_ObjAddFanin( pLatch, pLatchIn ); - Abc_ObjAddFanin( pLatchIn, pDriver ); - pLatch->pData = (void *)Init; - return pLatchOut; -} - -/**Function************************************************************* - - Synopsis [Creates MUX.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkNodeConvertToMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0, Abc_Obj_t * pMux ) -{ - assert( Abc_NtkIsLogic(pNtk) ); - Abc_ObjAddFanin( pMux, pNodeC ); - Abc_ObjAddFanin( pMux, pNode1 ); - Abc_ObjAddFanin( pMux, pNode0 ); - if ( Abc_NtkHasSop(pNtk) ) - pMux->pData = Abc_SopRegister( pNtk->pManFunc, "11- 1\n0-1 1\n" ); - else if ( Abc_NtkHasBdd(pNtk) ) - pMux->pData = Cudd_bddIte(pNtk->pManFunc,Cudd_bddIthVar(pNtk->pManFunc,0),Cudd_bddIthVar(pNtk->pManFunc,1),Cudd_bddIthVar(pNtk->pManFunc,2)), Cudd_Ref( pMux->pData ); - else if ( Abc_NtkHasAig(pNtk) ) - pMux->pData = Hop_Mux(pNtk->pManFunc,Hop_IthVar(pNtk->pManFunc,0),Hop_IthVar(pNtk->pManFunc,1),Hop_IthVar(pNtk->pManFunc,2)); - else - assert( 0 ); -} - -/**Function************************************************************* - - Synopsis [Converts registers with DC values into additional PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pCtrl, * pLatch, * pMux, * pPi; - Abc_InitType_t Init = ABC_INIT_ZERO; - int i, fFound = 0, Counter; - // check if there are latches with DC values - Abc_NtkForEachLatch( pNtk, pLatch, i ) - if ( Abc_LatchIsInitDc(pLatch) ) - { - fFound = 1; - break; - } - if ( !fFound ) - return; - // add control latch - pCtrl = Abc_NtkAddLatch( pNtk, Abc_NtkCreateNodeConst1(pNtk), Init ); - // add fanouts for each latch with DC values - Counter = 0; - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - if ( !Abc_LatchIsInitDc(pLatch) ) - continue; - // change latch value - pLatch->pData = (void *)Init; - // if the latch output has the same name as a PO, rename it - if ( Abc_NodeFindCoFanout( Abc_ObjFanout0(pLatch) ) ) - { - Nm_ManDeleteIdName( pLatch->pNtk->pManName, Abc_ObjFanout0(pLatch)->Id ); - Abc_ObjAssignName( Abc_ObjFanout0(pLatch), Abc_ObjName(pLatch), "_lo" ); - } - // create new PIs - pPi = Abc_NtkCreatePi( pNtk ); - Abc_ObjAssignName( pPi, Abc_ObjName(pLatch), "_pi" ); - // create a new node and transfer fanout from latch output to the new node - pMux = Abc_NtkCreateNode( pNtk ); - Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pMux ); - // convert the node into a mux - Abc_NtkNodeConvertToMux( pNtk, pCtrl, Abc_ObjFanout0(pLatch), pPi, pMux ); - Counter++; - } - printf( "The number of converted latches with DC values = %d.\n", Counter ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcLib.c b/src/base/abc/abcLib.c deleted file mode 100644 index f5b90e90..00000000 --- a/src/base/abc/abcLib.c +++ /dev/null @@ -1,455 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcLib.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Functions to manipulate verilog libraries.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Create the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Lib_t * Abc_LibCreate( char * pName ) -{ - Abc_Lib_t * p; - p = ALLOC( Abc_Lib_t, 1 ); - memset( p, 0, sizeof(Abc_Lib_t) ); - p->pName = Extra_UtilStrsav( pName ); - p->tModules = st_init_table( strcmp, st_strhash ); - p->vTops = Vec_PtrAlloc( 100 ); - p->vModules = Vec_PtrAlloc( 100 ); - p->pManFunc = Hop_ManStart(); - p->pLibrary = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_LibFree( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave ) -{ - Abc_Ntk_t * pNtk; - int i; - if ( pLib->pName ) - free( pLib->pName ); - if ( pLib->pManFunc ) - Hop_ManStop( pLib->pManFunc ); - if ( pLib->tModules ) - st_free_table( pLib->tModules ); - if ( pLib->vModules ) - { - Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) - { -// pNtk->pManFunc = NULL; - if ( pNtk == pNtkSave ) - continue; - pNtk->pManFunc = NULL; - pNtk->pDesign = NULL; - Abc_NtkDelete( pNtk ); - } - Vec_PtrFree( pLib->vModules ); - } - if ( pLib->vTops ) - Vec_PtrFree( pLib->vTops ); - free( pLib ); -} - -/**Function************************************************************* - - Synopsis [Frees the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Lib_t * Abc_LibDupBlackboxes( Abc_Lib_t * pLib, Abc_Ntk_t * pNtkSave ) -{ - Abc_Lib_t * pLibNew; - Abc_Ntk_t * pNtkTemp; - int i; - assert( Vec_PtrSize(pLib->vTops) > 0 ); - assert( Vec_PtrSize(pLib->vModules) > 1 ); - pLibNew = Abc_LibCreate( pLib->pName ); -// pLibNew->pManFunc = pNtkSave->pManFunc; - Vec_PtrPush( pLibNew->vTops, pNtkSave ); - Vec_PtrPush( pLibNew->vModules, pNtkSave ); - Vec_PtrForEachEntry( pLib->vModules, pNtkTemp, i ) - if ( Abc_NtkHasBlackbox( pNtkTemp ) ) - Vec_PtrPush( pLibNew->vModules, Abc_NtkDup(pNtkTemp) ); - return pLibNew; -} - - -/**Function************************************************************* - - Synopsis [Prints the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_LibPrint( Abc_Lib_t * pLib ) -{ - Abc_Ntk_t * pNtk; - Abc_Obj_t * pObj; - int i, k; - printf( "Models of design %s:\n", pLib->pName ); - Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) - { - printf( "%2d : %20s ", i+1, pNtk->pName ); - printf( "nd = %6d lat = %6d whitebox = %3d blackbox = %3d\n", - Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk), - Abc_NtkWhiteboxNum(pNtk), Abc_NtkBlackboxNum(pNtk) ); - if ( Abc_NtkBlackboxNum(pNtk) == 0 ) - continue; - Abc_NtkForEachWhitebox( pNtk, pObj, k ) - printf( " %20s (whitebox)\n", Abc_NtkName(pObj->pData) ); - Abc_NtkForEachBlackbox( pNtk, pObj, k ) - printf( " %20s (blackbox)\n", Abc_NtkName(pObj->pData) ); - } -} - -/**Function************************************************************* - - Synopsis [Create the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_LibAddModel( Abc_Lib_t * pLib, Abc_Ntk_t * pNtk ) -{ - if ( st_is_member( pLib->tModules, (char *)pNtk->pName ) ) - return 0; - st_insert( pLib->tModules, (char *)pNtk->pName, (char *)pNtk ); - Vec_PtrPush( pLib->vModules, pNtk ); - pNtk->pDesign = pLib; - return 1; -} - -/**Function************************************************************* - - Synopsis [Create the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_LibFindModelByName( Abc_Lib_t * pLib, char * pName ) -{ - Abc_Ntk_t * pNtk; - if ( !st_is_member( pLib->tModules, (char *)pName ) ) - return NULL; - st_lookup( pLib->tModules, (char *)pName, (char **)&pNtk ); - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Frees the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_LibDeriveRoot( Abc_Lib_t * pLib ) -{ - Abc_Ntk_t * pNtk; - if ( Vec_PtrSize(pLib->vModules) > 1 ) - { - printf( "The design includes more than one module and is currently not used.\n" ); - return NULL; - } - pNtk = Vec_PtrEntry( pLib->vModules, 0 ); Vec_PtrClear( pLib->vModules ); - pNtk->pManFunc = pLib->pManFunc; pLib->pManFunc = NULL; - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Detects the top-level models.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_LibFindTopLevelModels( Abc_Lib_t * pLib ) -{ - Abc_Ntk_t * pNtk, * pNtkBox; - Abc_Obj_t * pObj; - int i, k; - assert( Vec_PtrSize( pLib->vModules ) > 0 ); - // clear the models - Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) - pNtk->fHieVisited = 0; - // mark all the models reachable from other models - Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) - { - Abc_NtkForEachBox( pNtk, pObj, k ) - { - if ( Abc_ObjIsLatch(pObj) ) - continue; - if ( pObj->pData == NULL ) - continue; - pNtkBox = pObj->pData; - pNtkBox->fHieVisited = 1; - } - } - // collect the models that are not marked - Vec_PtrClear( pLib->vTops ); - Vec_PtrForEachEntry( pLib->vModules, pNtk, i ) - { - if ( pNtk->fHieVisited == 0 ) - Vec_PtrPush( pLib->vTops, pNtk ); - else - pNtk->fHieVisited = 0; - } - return Vec_PtrSize( pLib->vTops ); -} - - -/**Function************************************************************* - - Synopsis [Surround boxes without content (black boxes) with BIs/BOs.] - - Description [Returns the number of black boxes converted.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_LibDeriveBlackBoxes( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib ) -{ -/* - Abc_Obj_t * pObj, * pFanin, * pFanout; - int i, k; - assert( Abc_NtkIsNetlist(pNtk) ); - // collect blackbox nodes - assert( Vec_PtrSize(pNtk->vBoxes) == 0 ); - Vec_PtrClear( pNtk->vBoxes ); - Abc_NtkForEachBox( pNtk, pObj, i ) - if ( Abc_NtkNodeNum(pObj->pData) == 0 ) - Vec_PtrPush( pNtk->vBoxes, pObj ); - // return if there is no black boxes without content - if ( Vec_PtrSize(pNtk->vBoxes) == 0 ) - return 0; - // print the boxes - printf( "Black boxes are: " ); - Abc_NtkForEachBox( pNtk, pObj, i ) - printf( " %s", ((Abc_Ntk_t *)pObj->pData)->pName ); - printf( "\n" ); - // iterate through the boxes and add BIs/BOs - Abc_NtkForEachBox( pNtk, pObj, i ) - { - // go through the fanin nets - Abc_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjInsertBetween( pFanin, pObj, ABC_OBJ_BI ); - // go through the fanout nets - Abc_ObjForEachFanout( pObj, pFanout, k ) - { - Abc_ObjInsertBetween( pObj, pFanout, ABC_OBJ_BO ); - // if the name is not given assign name - if ( pFanout->pData == NULL ) - { - pFanout->pData = Abc_ObjName( pFanout ); - Nm_ManStoreIdName( pNtk->pManName, pFanout->Id, pFanout->pData, NULL ); - } - } - } - return Vec_PtrSize(pNtk->vBoxes); -*/ - return 0; -} - -/**Function************************************************************* - - Synopsis [Derive the AIG of the logic in the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeStrashUsingNetwork_rec( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i; - assert( !Abc_ObjIsNet(pObj) ); - if ( pObj->pCopy ) - return; - // call for the fanins - Abc_ObjForEachFanin( pObj, pFanin, i ) - Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) ); - // compute for the node - pObj->pCopy = Abc_NodeStrash( pNtkAig, pObj, 0 ); - // set for the fanout net - Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; -} - -/**Function************************************************************* - - Synopsis [Derive the AIG of the logic in the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeStrashUsingNetwork( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pBox ) -{ - Abc_Ntk_t * pNtkGate; - Abc_Obj_t * pObj; - unsigned * pPolarity; - int i, fCompl; - assert( Abc_ObjIsBox(pBox) ); - pNtkGate = pBox->pData; - pPolarity = (unsigned *)pBox->pNext; - assert( Abc_NtkIsNetlist(pNtkGate) ); - assert( Abc_NtkLatchNum(pNtkGate) == 0 ); - Abc_NtkCleanCopy( pNtkGate ); - // set the PI values - Abc_NtkForEachPi( pNtkGate, pObj, i ) - { - fCompl = (pPolarity && Abc_InfoHasBit(pPolarity, i)); - pObj->pCopy = Abc_ObjNotCond( Abc_ObjFanin(pBox,i)->pCopy, fCompl ); - Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; - } - // build recursively and set the PO values - Abc_NtkForEachPo( pNtkGate, pObj, i ) - { - Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) ); - Abc_ObjFanout(pBox,i)->pCopy = Abc_ObjFanin0(pObj)->pCopy; - } -//printf( "processing %d\n", pBox->Id ); -} - -/**Function************************************************************* - - Synopsis [Derive the AIG of the logic in the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_LibDeriveAig( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib ) -{ - ProgressBar * pProgress; - Vec_Ptr_t * vNodes; - Abc_Ntk_t * pNtkAig; - Abc_Obj_t * pObj; - int i, nBoxes; - // explicitly derive black boxes - assert( Abc_NtkIsNetlist(pNtk) ); - nBoxes = Abc_LibDeriveBlackBoxes( pNtk, pLib ); - if ( nBoxes ) - printf( "Detected and transformed %d black boxes.\n", nBoxes ); - // create the new network with black boxes in place - pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // transer to the nets - Abc_NtkForEachCi( pNtk, pObj, i ) - Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; - // build the AIG for the remaining logic in the netlist - vNodes = Abc_NtkDfs( pNtk, 0 ); - pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - if ( Abc_ObjIsNode(pObj) ) - { - pObj->pCopy = Abc_NodeStrash( pNtkAig, pObj, 0 ); - Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; - continue; - } - Abc_NodeStrashUsingNetwork( pNtkAig, pObj ); - } - Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vNodes ); - // deallocate memory manager, which remembers the phase - if ( pNtk->pData ) - { - Extra_MmFlexStop( pNtk->pData ); - pNtk->pData = NULL; - } - // set the COs -// Abc_NtkFinalize( pNtk, pNtkAig ); - Abc_NtkForEachCo( pNtk, pObj, i ) - Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); - Abc_AigCleanup( pNtkAig->pManFunc ); - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkAig ) ) - { - printf( "Abc_LibDeriveAig: The network check has failed.\n" ); - return 0; - } - return pNtkAig; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcMinBase.c b/src/base/abc/abcMinBase.c deleted file mode 100644 index 13f422f4..00000000 --- a/src/base/abc/abcMinBase.c +++ /dev/null @@ -1,256 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcMinBase.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Makes nodes of the network minimum base.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcMinBase.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Makes nodes minimum base.] - - Description [Returns the number of changed nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, Counter; - assert( Abc_NtkIsBddLogic(pNtk) ); - Counter = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - Counter += Abc_NodeMinimumBase( pNode ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Makes one node minimum base.] - - Description [Returns 1 if the node is changed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) -{ - Vec_Str_t * vSupport; - Vec_Ptr_t * vFanins; - DdNode * bTemp; - int i, nVars; - - assert( Abc_NtkIsBddLogic(pNode->pNtk) ); - assert( Abc_ObjIsNode(pNode) ); - - // compute support - vSupport = Vec_StrAlloc( 10 ); - nVars = Abc_NodeSupport( Cudd_Regular(pNode->pData), vSupport, Abc_ObjFaninNum(pNode) ); - if ( nVars == Abc_ObjFaninNum(pNode) ) - { - Vec_StrFree( vSupport ); - return 0; - } - - // remove unused fanins - vFanins = Vec_PtrAlloc( Abc_ObjFaninNum(pNode) ); - Abc_NodeCollectFanins( pNode, vFanins ); - for ( i = 0; i < vFanins->nSize; i++ ) - if ( vSupport->pArray[i] == 0 ) - Abc_ObjDeleteFanin( pNode, vFanins->pArray[i] ); - assert( nVars == Abc_ObjFaninNum(pNode) ); - - // update the function of the node - pNode->pData = Extra_bddRemapUp( pNode->pNtk->pManFunc, bTemp = pNode->pData ); Cudd_Ref( pNode->pData ); - Cudd_RecursiveDeref( pNode->pNtk->pManFunc, bTemp ); - Vec_PtrFree( vFanins ); - Vec_StrFree( vSupport ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Makes nodes of the network fanin-dup-free.] - - Description [Returns the number of pairs of duplicated fanins.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, Counter; - assert( Abc_NtkIsBddLogic(pNtk) ); - Counter = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - Counter += Abc_NodeRemoveDupFanins( pNode ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Removes one pair of duplicated fanins if present.] - - Description [Returns 1 if the node is changed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeRemoveDupFanins_int( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin1, * pFanin2; - int i, k; - assert( Abc_NtkIsBddLogic(pNode->pNtk) ); - assert( Abc_ObjIsNode(pNode) ); - // make sure fanins are not duplicated - Abc_ObjForEachFanin( pNode, pFanin2, i ) - { - Abc_ObjForEachFanin( pNode, pFanin1, k ) - { - if ( k >= i ) - break; - if ( pFanin1 == pFanin2 ) - { - DdManager * dd = pNode->pNtk->pManFunc; - DdNode * bVar1 = Cudd_bddIthVar( dd, i ); - DdNode * bVar2 = Cudd_bddIthVar( dd, k ); - DdNode * bTrans, * bTemp; - bTrans = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bTrans ); - pNode->pData = Cudd_bddAndAbstract( dd, bTemp = pNode->pData, bTrans, bVar2 ); Cudd_Ref( pNode->pData ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bTrans ); - Abc_NodeMinimumBase( pNode ); - return 1; - } - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Removes duplicated fanins if present.] - - Description [Returns the number of fanins removed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ) -{ - int Counter = 0; - while ( Abc_NodeRemoveDupFanins_int(pNode) ) - Counter++; - return Counter; -} -/**Function************************************************************* - - Synopsis [Computes support of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeSupport_rec( DdNode * bFunc, Vec_Str_t * vSupport ) -{ - if ( cuddIsConstant(bFunc) || Cudd_IsComplement(bFunc->next) ) - return; - vSupport->pArray[ bFunc->index ] = 1; - Abc_NodeSupport_rec( cuddT(bFunc), vSupport ); - Abc_NodeSupport_rec( Cudd_Regular(cuddE(bFunc)), vSupport ); - bFunc->next = Cudd_Not(bFunc->next); -} - -/**Function************************************************************* - - Synopsis [Computes support of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeSupportClear_rec( DdNode * bFunc ) -{ - if ( !Cudd_IsComplement(bFunc->next) ) - return; - bFunc->next = Cudd_Regular(bFunc->next); - if ( cuddIsConstant(bFunc) ) - return; - Abc_NodeSupportClear_rec( cuddT(bFunc) ); - Abc_NodeSupportClear_rec( Cudd_Regular(cuddE(bFunc)) ); -} - -/**Function************************************************************* - - Synopsis [Computes support of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ) -{ - int Counter, i; - // compute the support by marking the BDD - Vec_StrFill( vSupport, nVars, 0 ); - Abc_NodeSupport_rec( bFunc, vSupport ); - // clear the marak - Abc_NodeSupportClear_rec( bFunc ); - // get the number of support variables - Counter = 0; - for ( i = 0; i < nVars; i++ ) - Counter += vSupport->pArray[i]; - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcNames.c b/src/base/abc/abcNames.c deleted file mode 100644 index 91964dfa..00000000 --- a/src/base/abc/abcNames.c +++ /dev/null @@ -1,467 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcNames.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures working with net and node names.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcNames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the unique name for the object.] - - Description [If the name previously did not exist, creates a new unique - name but does not assign this name to the object. The temporary unique - name is stored in a static buffer inside this procedure. It is important - that the name is used before the function is called again!] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_ObjName( Abc_Obj_t * pObj ) -{ - return Nm_ManCreateUniqueName( pObj->pNtk->pManName, pObj->Id ); -} - -/**Function************************************************************* - - Synopsis [Assigns the given name to the object.] - - Description [The object should not have a name assigned. The same - name may be used for several objects, which they share the same net - in the original netlist. (For example, latch output and primary output - may have the same name.) This procedure returns the pointer to the - internally stored representation of the given name.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix ) -{ - assert( pName != NULL ); - return Nm_ManStoreIdName( pObj->pNtk->pManName, pObj->Id, pObj->Type, pName, pSuffix ); -} - -/**Function************************************************************* - - Synopsis [Gets the long name of the node.] - - Description [This name is the output net's name.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ) -{ - static char Buffer[500]; - sprintf( Buffer, "%s%s", Abc_ObjName(pObj), pSuffix ); - return Buffer; -} - -/**Function************************************************************* - - Synopsis [Returns the dummy PI name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits ) -{ - static char Buffer[100]; - sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); - return Buffer; -} - -/**Function************************************************************* - - Synopsis [Tranfers names to the old network.] - - Description [Assumes that the new nodes are attached using pObj->pCopy.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) -{ - Abc_Obj_t * pObj; - int i; - assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); - assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); - assert( Abc_NtkBoxNum(pNtk) == Abc_NtkBoxNum(pNtkNew) ); - assert( Abc_NtkAssertNum(pNtk) == Abc_NtkAssertNum(pNtkNew) ); - assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); - assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); - // copy the CI/CO/box names - Abc_NtkForEachCi( pNtk, pObj, i ) - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); - Abc_NtkForEachCo( pNtk, pObj, i ) - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); - Abc_NtkForEachBox( pNtk, pObj, i ) - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); -} - -/**Function************************************************************* - - Synopsis [Tranfers names to the old network.] - - Description [Assumes that the new nodes are attached using pObj->pCopy.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) -{ - Abc_Obj_t * pObj; - int i; - assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); - assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); - assert( Abc_NtkAssertNum(pNtk) == Abc_NtkAssertNum(pNtkNew) ); - assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); - assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); - // copy the CI/CO/box name and skip latches and theirs inputs/outputs - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFaninNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ) - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); - Abc_NtkForEachCo( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); - Abc_NtkForEachBox( pNtk, pObj, i ) - if ( !Abc_ObjIsLatch(pObj) ) - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); -} - -/**Function************************************************************* - - Synopsis [Gets fanin node names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pFanin; - int i; - vNodes = Vec_PtrAlloc( 100 ); - Abc_ObjForEachFanin( pNode, pFanin, i ) - Vec_PtrPush( vNodes, Extra_UtilStrsav(Abc_ObjName(pFanin)) ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Gets fanin node names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ) -{ - Vec_Ptr_t * vNames; - char Buffer[5]; - int i; - - vNames = Vec_PtrAlloc( nNames ); - for ( i = 0; i < nNames; i++ ) - { - if ( nNames < 26 ) - { - Buffer[0] = 'a' + i; - Buffer[1] = 0; - } - else - { - Buffer[0] = 'a' + i%26; - Buffer[1] = '0' + i/26; - Buffer[2] = 0; - } - Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); - } - return vNames; -} - -/**Function************************************************************* - - Synopsis [Gets fanin node names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeFreeNames( Vec_Ptr_t * vNames ) -{ - int i; - if ( vNames == NULL ) - return; - for ( i = 0; i < vNames->nSize; i++ ) - free( vNames->pArray[i] ); - Vec_PtrFree( vNames ); -} - -/**Function************************************************************* - - Synopsis [Collects the CI or CO names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos ) -{ - Abc_Obj_t * pObj; - char ** ppNames; - int i; - if ( fCollectCos ) - { - ppNames = ALLOC( char *, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - ppNames[i] = Abc_ObjName(pObj); - } - else - { - ppNames = ALLOC( char *, Abc_NtkCiNum(pNtk) ); - Abc_NtkForEachCi( pNtk, pObj, i ) - ppNames[i] = Abc_ObjName(pObj); - } - return ppNames; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) -{ - int Diff = strcmp( (char *)(*pp1)->pCopy, (char *)(*pp2)->pCopy ); - if ( Diff < 0 ) - return -1; - if ( Diff > 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Orders PIs/POs/latches alphabetically.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ) -{ - Abc_Obj_t * pObj; - int i; - assert( Abc_NtkAssertNum(pNtk) == 0 ); - assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); - // temporarily store the names in the copy field - Abc_NtkForEachPi( pNtk, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); - Abc_NtkForEachPo( pNtk, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); - Abc_NtkForEachBox( pNtk, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(Abc_ObjFanout0(pObj)); - // order objects alphabetically - qsort( (void *)Vec_PtrArray(pNtk->vPis), Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), - (int (*)(const void *, const void *)) Abc_NodeCompareNames ); - qsort( (void *)Vec_PtrArray(pNtk->vPos), Vec_PtrSize(pNtk->vPos), sizeof(Abc_Obj_t *), - (int (*)(const void *, const void *)) Abc_NodeCompareNames ); - // if the comparison if combinational (latches as PIs/POs), order them too - if ( fComb ) - qsort( (void *)Vec_PtrArray(pNtk->vBoxes), Vec_PtrSize(pNtk->vBoxes), sizeof(Abc_Obj_t *), - (int (*)(const void *, const void *)) Abc_NodeCompareNames ); - // order CIs/COs first PIs/POs(Asserts) then latches - Abc_NtkOrderCisCos( pNtk ); - // clean the copy fields - Abc_NtkForEachPi( pNtk, pObj, i ) - pObj->pCopy = NULL; - Abc_NtkForEachPo( pNtk, pObj, i ) - pObj->pCopy = NULL; - Abc_NtkForEachBox( pNtk, pObj, i ) - pObj->pCopy = NULL; -} - -/**Function************************************************************* - - Synopsis [Adds dummy names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int nDigits, i; - nDigits = Extra_Base10Log( Abc_NtkPiNum(pNtk) ); - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjAssignName( pObj, Abc_ObjNameDummy("pi", i, nDigits), NULL ); -} - -/**Function************************************************************* - - Synopsis [Adds dummy names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int nDigits, i; - nDigits = Extra_Base10Log( Abc_NtkPoNum(pNtk) ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_ObjAssignName( pObj, Abc_ObjNameDummy("po", i, nDigits), NULL ); -} - -/**Function************************************************************* - - Synopsis [Adds dummy names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAddDummyAssertNames( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int nDigits, i; - nDigits = Extra_Base10Log( Abc_NtkAssertNum(pNtk) ); - Abc_NtkForEachAssert( pNtk, pObj, i ) - Abc_ObjAssignName( pObj, Abc_ObjNameDummy("a", i, nDigits), NULL ); -} - -/**Function************************************************************* - - Synopsis [Adds dummy names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int nDigits, i; - assert( !Abc_NtkIsNetlist(pNtk) ); - nDigits = Extra_Base10Log( Abc_NtkLatchNum(pNtk) ); - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - Abc_ObjAssignName( pObj, Abc_ObjNameDummy("l", i, nDigits), NULL ); - Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjNameDummy("li", i, nDigits), NULL ); - Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjNameDummy("lo", i, nDigits), NULL ); - } -/* - nDigits = Extra_Base10Log( Abc_NtkBlackboxNum(pNtk) ); - Abc_NtkForEachBlackbox( pNtk, pObj, i ) - { - pName = Abc_ObjAssignName( pObj, Abc_ObjNameDummy("B", i, nDigits), NULL ); - nDigitsF = Extra_Base10Log( Abc_ObjFaninNum(pObj) ); - Abc_ObjForEachFanin( pObj, pTerm, k ) - Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("i", k, nDigitsF) ); - nDigitsF = Extra_Base10Log( Abc_ObjFanoutNum(pObj) ); - Abc_ObjForEachFanout( pObj, pTerm, k ) - Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("o", k, nDigitsF) ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Replaces names by short names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkShortNames( Abc_Ntk_t * pNtk ) -{ - Nm_ManFree( pNtk->pManName ); - pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) ); - Abc_NtkAddDummyPiNames( pNtk ); - Abc_NtkAddDummyPoNames( pNtk ); - Abc_NtkAddDummyAssertNames( pNtk ); - Abc_NtkAddDummyBoxNames( pNtk ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcNetlist.c b/src/base/abc/abcNetlist.c deleted file mode 100644 index 26b88c68..00000000 --- a/src/base/abc/abcNetlist.c +++ /dev/null @@ -1,411 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcNetlist.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Transforms netlist into a logic network and vice versa.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcNetlist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -//#include "seq.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk ); -static Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ); -static Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ); -static Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transform the netlist into a logic network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFanin; - int i, k; - // consider the case of the AIG - if ( Abc_NtkIsStrash(pNtk) ) - return Abc_NtkAigToLogicSop( pNtk ); - assert( Abc_NtkIsNetlist(pNtk) ); - // consider simple case when there is hierarchy -// assert( pNtk->pDesign == NULL ); - assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); - assert( Abc_NtkBlackboxNum(pNtk) == 0 ); - // start the network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, pNtk->ntkFunc ); - // duplicate the nodes - Abc_NtkForEachNode( pNtk, pObj, i ) - Abc_NtkDupObj(pNtkNew, pObj, 0); - // reconnect the internal nodes in the new network - Abc_NtkForEachNode( pNtk, pObj, i ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pFanin)->pCopy ); - // collect the CO nodes - Abc_NtkFinalize( pNtk, pNtkNew ); - // fix the problem with CO pointing directly to CIs - Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); - // duplicate EXDC - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkToLogic( pNtk->pExdc ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkToLogic(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Transform the logic network into a netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew, * pNtkTemp; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); - if ( Abc_NtkIsStrash(pNtk) ) - { - pNtkTemp = Abc_NtkAigToLogicSop(pNtk); - pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); - Abc_NtkDelete( pNtkTemp ); - return pNtkNew; - } - return Abc_NtkLogicToNetlist( pNtk ); -} - -/**Function************************************************************* - - Synopsis [Converts the AIG into the netlist.] - - Description [This procedure does not copy the choices.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew, * pNtkTemp; - assert( Abc_NtkIsStrash(pNtk) ); - pNtkTemp = Abc_NtkAigToLogicSopBench( pNtk ); - pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); - Abc_NtkDelete( pNtkTemp ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Transform the logic network into a netlist.] - - Description [The logic network given to this procedure should - have exactly the same structure as the resulting netlist. The COs - can only point to CIs if they have identical names. Otherwise, - they should have a node between them, even if this node is - inverter or buffer.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pNet, * pDriver, * pFanin; - int i, k; - - assert( Abc_NtkIsLogic(pNtk) ); - - // remove dangling nodes - Abc_NtkCleanup( pNtk, 0 ); - - // make sure the CO names are unique - Abc_NtkCheckUniqueCiNames( pNtk ); - Abc_NtkCheckUniqueCoNames( pNtk ); - Abc_NtkCheckUniqueCioNames( pNtk ); - -// assert( Abc_NtkLogicHasSimpleCos(pNtk) ); - if ( !Abc_NtkLogicHasSimpleCos(pNtk) ) - { - printf( "Abc_NtkLogicToNetlist() warning: The network is converted to have simple COs.\n" ); - Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); - } - - // start the netlist by creating PI/PO/Latch objects - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc ); - // create the CI nets and remember them in the new CI nodes - Abc_NtkForEachCi( pNtk, pObj, i ) - { - pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); - Abc_ObjAddFanin( pNet, pObj->pCopy ); - pObj->pCopy->pCopy = pNet; - } - // duplicate all nodes - Abc_NtkForEachNode( pNtk, pObj, i ) - Abc_NtkDupObj(pNtkNew, pObj, 0); - // first add the nets to the CO drivers - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pDriver = Abc_ObjFanin0(pObj); - if ( Abc_ObjIsCi(pDriver) ) - { - assert( !strcmp( Abc_ObjName(pDriver), Abc_ObjName(pObj) ) ); - Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); - continue; - } - assert( Abc_ObjIsNode(pDriver) ); - // if the CO driver has no net, create it - if ( pDriver->pCopy->pCopy == NULL ) - { - // create the CO net and connect it to CO - pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); - Abc_ObjAddFanin( pObj->pCopy, pNet ); - // connect the CO net to the new driver and remember it in the new driver - Abc_ObjAddFanin( pNet, pDriver->pCopy ); - pDriver->pCopy->pCopy = pNet; - } - else - { - assert( !strcmp( Abc_ObjName(pDriver->pCopy->pCopy), Abc_ObjName(pObj) ) ); - Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); - } - } - // create the missing nets - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( pObj->pCopy->pCopy ) // the net of the new object is already created - continue; - // create the new net - pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create ridiculous names net line "n48", where 48 is the ID of the node - Abc_ObjAddFanin( pNet, pObj->pCopy ); - pObj->pCopy->pCopy = pNet; - } - // connect nodes to the fanins nets - Abc_NtkForEachNode( pNtk, pObj, i ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); - // duplicate EXDC - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkLogicToNetlist(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Converts the AIG into the logic network with SOPs.] - - Description [Correctly handles the case of choice nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFanin, * pNodeNew; - Vec_Int_t * vInts; - int i, k; - assert( Abc_NtkIsStrash(pNtk) ); - // start the network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); - // if the constant node is used, duplicate it - pObj = Abc_AigConst1(pNtk); - if ( Abc_ObjFanoutNum(pObj) > 0 ) - pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); - // duplicate the nodes and create node functions - Abc_NtkForEachNode( pNtk, pObj, i ) - { - Abc_NtkDupObj(pNtkNew, pObj, 0); - pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); - } - // create the choice nodes - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( !Abc_AigNodeIsChoice(pObj) ) - continue; - // create an OR gate - pNodeNew = Abc_NtkCreateNode(pNtkNew); - // add fanins - vInts = Vec_IntAlloc( 10 ); - for ( pFanin = pObj; pFanin; pFanin = pFanin->pData ) - { - Vec_IntPush( vInts, (int)(pObj->fPhase != pFanin->fPhase) ); - Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); - } - // create the logic function - pNodeNew->pData = Abc_SopCreateOrMultiCube( pNtkNew->pManFunc, Vec_IntSize(vInts), Vec_IntArray(vInts) ); - // set the new node - pObj->pCopy->pCopy = pNodeNew; - Vec_IntFree( vInts ); - } - // connect the internal nodes - Abc_NtkForEachNode( pNtk, pObj, i ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - if ( pFanin->pCopy->pCopy ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); - else - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - // connect the COs -// Abc_NtkFinalize( pNtk, pNtkNew ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pFanin = Abc_ObjFanin0(pObj); - if ( pFanin->pCopy->pCopy ) - pNodeNew = Abc_ObjNotCond(pFanin->pCopy->pCopy, Abc_ObjFaninC0(pObj)); - else - pNodeNew = Abc_ObjNotCond(pFanin->pCopy, Abc_ObjFaninC0(pObj)); - Abc_ObjAddFanin( pObj->pCopy, pNodeNew ); - } - - // fix the problem with complemented and duplicated CO edges - Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); - // duplicate the EXDC Ntk - if ( pNtk->pExdc ) - { - if ( Abc_NtkIsStrash(pNtk->pExdc) ) - pNtkNew->pExdc = Abc_NtkAigToLogicSop( pNtk->pExdc ); - else - pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - } - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkAigToLogicSop(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Converts the AIG into the logic network with SOPs for bench writing.] - - Description [This procedure does not copy the choices.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFanin; - Vec_Ptr_t * vNodes; - int i, k; - assert( Abc_NtkIsStrash(pNtk) ); - if ( Abc_NtkGetChoiceNum(pNtk) ) - printf( "Warning: Choice nodes are skipped.\n" ); - // start the network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); - // collect the nodes to be used (marks all nodes with current TravId) - vNodes = Abc_NtkDfs( pNtk, 0 ); - // create inverters for the CI and remember them - pObj = Abc_AigConst1(pNtk); - if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) - { - pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); - pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); - } - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) - pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); - // duplicate the nodes, create node functions, and inverters - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - pObj->pCopy->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, 2, NULL ); - if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) - pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); - } - // connect the objects - Vec_PtrForEachEntry( vNodes, pObj, i ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - if ( Abc_ObjFaninC( pObj, k ) ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); - else - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - } - Vec_PtrFree( vNodes ); - // connect the COs - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pFanin = Abc_ObjFanin0(pObj); - if ( Abc_ObjFaninC0( pObj ) ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); - else - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - } - // fix the problem with complemented and duplicated CO edges - Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); - // duplicate the EXDC Ntk - if ( pNtk->pExdc ) - printf( "Warning: The EXDc network is skipped.\n" ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkAigToLogicSopBench(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Adds buffers for each PO.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj, * pFanin, * pFaninNew; - int i; - assert( Abc_NtkIsStrash(pNtk) ); - Abc_NtkForEachPo( pNtk, pObj, i ) - { - pFanin = Abc_ObjChild0(pObj); - pFaninNew = Abc_NtkCreateNode(pNtk); - Abc_ObjAddFanin( pFaninNew, pFanin ); - Abc_ObjPatchFanin( pObj, pFanin, pFaninNew ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcNtk.c b/src/base/abc/abcNtk.c deleted file mode 100644 index cd87c05e..00000000 --- a/src/base/abc/abcNtk.c +++ /dev/null @@ -1,1230 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcNtk.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Network creation/duplication/deletion procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcNtk.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "abcInt.h" -#include "main.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates a new Ntk.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ) -{ - Abc_Ntk_t * pNtk; - pNtk = ALLOC( Abc_Ntk_t, 1 ); - memset( pNtk, 0, sizeof(Abc_Ntk_t) ); - pNtk->ntkType = Type; - pNtk->ntkFunc = Func; - // start the object storage - pNtk->vObjs = Vec_PtrAlloc( 100 ); - pNtk->vAsserts = Vec_PtrAlloc( 100 ); - pNtk->vPios = Vec_PtrAlloc( 100 ); - pNtk->vPis = Vec_PtrAlloc( 100 ); - pNtk->vPos = Vec_PtrAlloc( 100 ); - pNtk->vCis = Vec_PtrAlloc( 100 ); - pNtk->vCos = Vec_PtrAlloc( 100 ); - pNtk->vBoxes = Vec_PtrAlloc( 100 ); - // start the memory managers - pNtk->pMmObj = fUseMemMan? Extra_MmFixedStart( sizeof(Abc_Obj_t) ) : NULL; - pNtk->pMmStep = fUseMemMan? Extra_MmStepStart( ABC_NUM_STEPS ) : NULL; - // get ready to assign the first Obj ID - pNtk->nTravIds = 1; - // start the functionality manager - if ( Abc_NtkIsStrash(pNtk) ) - pNtk->pManFunc = Abc_AigAlloc( pNtk ); - else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) - pNtk->pManFunc = Extra_MmFlexStart(); - else if ( Abc_NtkHasBdd(pNtk) ) - pNtk->pManFunc = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - else if ( Abc_NtkHasAig(pNtk) ) - pNtk->pManFunc = Hop_ManStart(); - else if ( Abc_NtkHasMapping(pNtk) ) - pNtk->pManFunc = Abc_FrameReadLibGen(); - else if ( !Abc_NtkHasBlackbox(pNtk) ) - assert( 0 ); - // name manager - pNtk->pManName = Nm_ManCreate( 200 ); - // attribute manager - pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM ); - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Starts a new network using existing network as a model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj; - int fCopyNames, i; - if ( pNtk == NULL ) - return NULL; - // decide whether to copy the names - fCopyNames = ( Type != ABC_NTK_NETLIST ); - // start the network - pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); - // duplicate the name and the spec - pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); - pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); - // clean the node copy fields - Abc_NtkCleanCopy( pNtk ); - // map the constant nodes - if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); - // clone CIs/CIs/boxes - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); - Abc_NtkForEachAssert( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); - Abc_NtkForEachBox( pNtk, pObj, i ) - Abc_NtkDupBox( pNtkNew, pObj, fCopyNames ); - // transfer the names -// Abc_NtkTrasferNames( pNtk, pNtkNew ); - Abc_ManTimeDup( pNtk, pNtkNew ); - // check that the CI/CO/latches are copied correctly - assert( Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkNew) ); - assert( Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkNew) ); - assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Starts a new network using existing network as a model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj; - int i; - if ( pNtk == NULL ) - return NULL; - assert( Type != ABC_NTK_NETLIST ); - // start the network - pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); - // duplicate the name and the spec - pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); - pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); - // clean the node copy fields - Abc_NtkCleanCopy( pNtk ); - // map the constant nodes - if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); - // clone CIs/CIs/boxes - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 1 ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 1 ); - Abc_NtkForEachAssert( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 1 ); - Abc_NtkForEachBox( pNtk, pObj, i ) - { - if ( Abc_ObjIsLatch(pObj) ) - continue; - Abc_NtkDupBox(pNtkNew, pObj, 1); - } - // transfer the names -// Abc_NtkTrasferNamesNoLatches( pNtk, pNtkNew ); - Abc_ManTimeDup( pNtk, pNtkNew ); - // check that the CI/CO/latches are copied correctly - assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); - assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Finalizes the network using the existing network as a model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) -{ - Abc_Obj_t * pObj, * pDriver, * pDriverNew; - int i; - // set the COs of the strashed network - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) ); - pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj)); - Abc_ObjAddFanin( pObj->pCopy, pDriverNew ); - } -} - -/**Function************************************************************* - - Synopsis [Starts a new network using existing network as a model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkStartRead( char * pName ) -{ - Abc_Ntk_t * pNtkNew; - // allocate the empty network - pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); - // set the specs - pNtkNew->pName = Extra_FileNameGeneric(pName); - pNtkNew->pSpec = Extra_UtilStrsav(pName); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Finalizes the network using the existing network as a model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pBox, * pObj, * pTerm, * pNet; - int i; - if ( Abc_NtkHasBlackbox(pNtk) && Abc_NtkBoxNum(pNtk) == 0 ) - { - pBox = Abc_NtkCreateBlackbox(pNtk); - Abc_NtkForEachPi( pNtk, pObj, i ) - { - pTerm = Abc_NtkCreateBi(pNtk); - Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) ); - Abc_ObjAddFanin( pBox, pTerm ); - } - Abc_NtkForEachPo( pNtk, pObj, i ) - { - pTerm = Abc_NtkCreateBo(pNtk); - Abc_ObjAddFanin( pTerm, pBox ); - Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm ); - } - return; - } - assert( Abc_NtkIsNetlist(pNtk) ); - - // check if constant 0 net is used - pNet = Abc_NtkFindNet( pNtk, "1\'b0" ); - if ( pNet ) - { - if ( Abc_ObjFanoutNum(pNet) == 0 ) - Abc_NtkDeleteObj(pNet); - else if ( Abc_ObjFaninNum(pNet) == 0 ) - Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) ); - } - // check if constant 1 net is used - pNet = Abc_NtkFindNet( pNtk, "1\'b1" ); - if ( pNet ) - { - if ( Abc_ObjFanoutNum(pNet) == 0 ) - Abc_NtkDeleteObj(pNet); - else if ( Abc_ObjFaninNum(pNet) == 0 ) - Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) ); - } - // fix the net drivers - Abc_NtkFixNonDrivenNets( pNtk ); - - // reorder the CI/COs to PI/POs first - Abc_NtkOrderCisCos( pNtk ); -} - -/**Function************************************************************* - - Synopsis [Duplicate the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFanin; - int i, k; - if ( pNtk == NULL ) - return NULL; - // start the network - pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); - // copy the internal nodes - if ( Abc_NtkIsStrash(pNtk) ) - { - // copy the AND gates - Abc_AigForEachAnd( pNtk, pObj, i ) - pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - // relink the choice nodes - Abc_AigForEachAnd( pNtk, pObj, i ) - if ( pObj->pData ) - pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy; - // relink the CO nodes - Abc_NtkForEachCo( pNtk, pObj, i ) - Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); - // get the number of nodes before and after - if ( Abc_NtkNodeNum(pNtk) != Abc_NtkNodeNum(pNtkNew) ) - printf( "Warning: Structural hashing during duplication reduced %d nodes (this is a minor bug).\n", - Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNtkNew) ); - } - else - { - // duplicate the nets and nodes (CIs/COs/latches already dupped) - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( pObj->pCopy == NULL ) - Abc_NtkDupObj(pNtkNew, pObj, 0); - // reconnect all objects (no need to transfer attributes on edges) - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - } - // duplicate the EXDC Ntk - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); - pNtk->pCopy = pNtkNew; - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Duplicate the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk ) -{ - char Buffer[500]; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFanin; - int i, k; - assert( Abc_NtkIsLogic(pNtk) ); - - // start the network - pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); - sprintf( Buffer, "%s%s", pNtk->pName, "_2x" ); - pNtkNew->pName = Extra_UtilStrsav(Buffer); - - // clean the node copy fields - Abc_NtkCleanCopy( pNtk ); - // clone CIs/CIs/boxes - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_NtkForEachAssert( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_NtkForEachBox( pNtk, pObj, i ) - Abc_NtkDupBox( pNtkNew, pObj, 0 ); - // copy the internal nodes - // duplicate the nets and nodes (CIs/COs/latches already dupped) - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( pObj->pCopy == NULL ) - Abc_NtkDupObj(pNtkNew, pObj, 0); - // reconnect all objects (no need to transfer attributes on edges) - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - - // clean the node copy fields - Abc_NtkCleanCopy( pNtk ); - // clone CIs/CIs/boxes - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_NtkForEachAssert( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_NtkForEachBox( pNtk, pObj, i ) - Abc_NtkDupBox( pNtkNew, pObj, 0 ); - // copy the internal nodes - // duplicate the nets and nodes (CIs/COs/latches already dupped) - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( pObj->pCopy == NULL ) - Abc_NtkDupObj(pNtkNew, pObj, 0); - // reconnect all objects (no need to transfer attributes on edges) - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - - // assign names - Abc_NtkForEachCi( pNtk, pObj, i ) - { - Abc_ObjAssignName( Abc_NtkCi(pNtkNew, i), "1_", Abc_ObjName(pObj) ); - Abc_ObjAssignName( Abc_NtkCi(pNtkNew, Abc_NtkCiNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); - } - Abc_NtkForEachCo( pNtk, pObj, i ) - { - Abc_ObjAssignName( Abc_NtkCo(pNtkNew, i), "1_", Abc_ObjName(pObj) ); - Abc_ObjAssignName( Abc_NtkCo(pNtkNew, Abc_NtkCoNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); - } - - // perform the final check - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Attaches the second network at the bottom of the first.] - - Description [Returns the first network. Deletes the second network.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom ) -{ - Abc_Obj_t * pObj, * pFanin, * pBuffer; - Vec_Ptr_t * vNodes; - int i, k; - assert( pNtkBottom != NULL ); - if ( pNtkTop == NULL ) - return pNtkBottom; - // make sure the networks are combinational - assert( Abc_NtkPiNum(pNtkTop) == Abc_NtkCiNum(pNtkTop) ); - assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkCiNum(pNtkBottom) ); - // make sure the POs of the bottom correspond to the PIs of the top - assert( Abc_NtkPoNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); - assert( Abc_NtkPiNum(pNtkBottom) < Abc_NtkPiNum(pNtkTop) ); - // add buffers for the PIs of the top - save results in the POs of the bottom - Abc_NtkForEachPi( pNtkTop, pObj, i ) - { - pBuffer = Abc_NtkCreateNodeBuf( pNtkTop, NULL ); - Abc_ObjTransferFanout( pObj, pBuffer ); - Abc_NtkPo(pNtkBottom, i)->pCopy = pBuffer; - } - // remove useless PIs of the top - for ( i = Abc_NtkPiNum(pNtkTop) - 1; i >= Abc_NtkPiNum(pNtkBottom); i-- ) - Abc_NtkDeleteObj( Abc_NtkPi(pNtkTop, i) ); - assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); - // copy the bottom network - Abc_NtkForEachPi( pNtkBottom, pObj, i ) - Abc_NtkPi(pNtkBottom, i)->pCopy = Abc_NtkPi(pNtkTop, i); - // construct all nodes - vNodes = Abc_NtkDfs( pNtkBottom, 0 ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - Abc_NtkDupObj(pNtkTop, pObj, 0); - Abc_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - } - Vec_PtrFree( vNodes ); - // connect the POs - Abc_NtkForEachPo( pNtkBottom, pObj, i ) - Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); - // delete old network - Abc_NtkDelete( pNtkBottom ); - // return the network - if ( !Abc_NtkCheck( pNtkTop ) ) - fprintf( stdout, "Abc_NtkAttachBottom(): Network check has failed.\n" ); - return pNtkTop; -} - -/**Function************************************************************* - - Synopsis [Creates the network composed of one logic cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ) -{ - Abc_Ntk_t * pNtkNew; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; - char Buffer[1000]; - int i, k; - - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); - assert( Abc_ObjIsNode(pNode) ); - - // start the network - pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); - // set the name - sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); - pNtkNew->pName = Extra_UtilStrsav(Buffer); - - // establish connection between the constant nodes - if ( Abc_NtkIsStrash(pNtk) ) - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); - - // collect the nodes in the TFI of the output (mark the TFI) - vNodes = Abc_NtkDfsNodes( pNtk, &pNode, 1 ); - // create the PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - { - if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS - { - pObj->pCopy = Abc_NtkCreatePi(pNtkNew); - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); - } - } - // add the PO corresponding to this output - pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); - Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); - // copy the nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - // if it is an AIG, add to the hash table - if ( Abc_NtkIsStrash(pNtk) ) - { - pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - } - else - { - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - } - } - // connect the internal nodes to the new CO - Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); - Vec_PtrFree( vNodes ); - - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Creates the network composed of several logic cones.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis ) -{ - Abc_Ntk_t * pNtkNew; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; - char Buffer[1000]; - int i, k; - - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); - - // start the network - pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); - // set the name - sprintf( Buffer, "%s_part", pNtk->pName ); - pNtkNew->pName = Extra_UtilStrsav(Buffer); - - // establish connection between the constant nodes - if ( Abc_NtkIsStrash(pNtk) ) - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); - - // collect the nodes in the TFI of the output (mark the TFI) - vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); - - // create the PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - { - if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS - { - pObj->pCopy = Abc_NtkCreatePi(pNtkNew); - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); - } - } - - // copy the nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - // if it is an AIG, add to the hash table - if ( Abc_NtkIsStrash(pNtk) ) - { - pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - } - else - { - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - } - } - Vec_PtrFree( vNodes ); - - // add the POs corresponding to the root nodes - Vec_PtrForEachEntry( vRoots, pObj, i ) - { - // create the PO node - pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); - // connect the internal nodes to the new CO - if ( Abc_ObjIsCo(pObj) ) - Abc_ObjAddFanin( pNodeCoNew, Abc_ObjChild0Copy(pObj) ); - else - Abc_ObjAddFanin( pNodeCoNew, pObj->pCopy ); - // assign the name - Abc_ObjAssignName( pNodeCoNew, Abc_ObjName(pObj), NULL ); - } - - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateConeArray(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Adds new nodes to the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i, iNodeId; - - assert( Abc_NtkIsStrash(pNtkNew) ); - assert( Abc_NtkIsStrash(pNtk) ); - - // collect the nodes in the TFI of the output (mark the TFI) - vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); - - // establish connection between the constant nodes - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); - - // create the PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - { - // skip CIs that are not used - if ( !Abc_NodeIsTravIdCurrent(pObj) ) - continue; - // find the corresponding CI in the new network - iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); - if ( iNodeId == -1 ) - { - pObj->pCopy = Abc_NtkCreatePi(pNtkNew); - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); - } - else - pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); - } - - // copy the nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - Vec_PtrFree( vNodes ); - - // do not add the COs - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkAppendToCone(): Network check has failed.\n" ); -} - -/**Function************************************************************* - - Synopsis [Creates the network composed of MFFC of one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; - Vec_Ptr_t * vCone, * vSupp; - char Buffer[1000]; - int i, k; - - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); - assert( Abc_ObjIsNode(pNode) ); - - // start the network - pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); - // set the name - sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); - pNtkNew->pName = Extra_UtilStrsav(Buffer); - - // establish connection between the constant nodes - if ( Abc_NtkIsStrash(pNtk) ) - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); - - // collect the nodes in MFFC - vCone = Vec_PtrAlloc( 100 ); - vSupp = Vec_PtrAlloc( 100 ); - Abc_NodeDeref_rec( pNode ); - Abc_NodeMffsConeSupp( pNode, vCone, vSupp ); - Abc_NodeRef_rec( pNode ); - // create the PIs - Vec_PtrForEachEntry( vSupp, pObj, i ) - { - pObj->pCopy = Abc_NtkCreatePi(pNtkNew); - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); - } - // create the PO - pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); - Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); - // copy the nodes - Vec_PtrForEachEntry( vCone, pObj, i ) - { - // if it is an AIG, add to the hash table - if ( Abc_NtkIsStrash(pNtk) ) - { - pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - } - else - { - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_ObjForEachFanin( pObj, pFanin, k ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - } - } - // connect the topmost node - Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); - Vec_PtrFree( vCone ); - Vec_PtrFree( vSupp ); - - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateMffc(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Creates the miter composed of one multi-output cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ) -{ - Vec_Ptr_t * vNodes; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFinal, * pOther, * pNodePo; - int i; - - assert( Abc_NtkIsLogic(pNtk) ); - - // start the network - Abc_NtkCleanCopy( pNtk ); - pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); - - // collect the nodes in the TFI of the output - vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)vRoots->pArray, vRoots->nSize ); - // create the PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - { - pObj->pCopy = Abc_NtkCreatePi(pNtkNew); - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); - } - // copy the nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pCopy = Abc_NodeStrash( pNtkNew, pObj, 0 ); - Vec_PtrFree( vNodes ); - - // add the PO - pFinal = Abc_AigConst1( pNtkNew ); - Vec_PtrForEachEntry( vRoots, pObj, i ) - { - if ( Abc_ObjIsCo(pObj) ) - pOther = Abc_ObjFanin0(pObj)->pCopy; - else - pOther = pObj->pCopy; - if ( Vec_IntEntry(vValues, i) == 0 ) - pOther = Abc_ObjNot(pOther); - pFinal = Abc_AigAnd( pNtkNew->pManFunc, pFinal, pOther ); - } - - // add the PO corresponding to this output - pNodePo = Abc_NtkCreatePo( pNtkNew ); - Abc_ObjAddFanin( pNodePo, pFinal ); - Abc_ObjAssignName( pNodePo, "miter", NULL ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateTarget(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Creates the network composed of one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pFanin, * pNodePo; - int i; - // start the network - pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); - pNtkNew->pName = Extra_UtilStrsav(Abc_ObjName(pNode)); - // add the PIs corresponding to the fanins of the node - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - pFanin->pCopy = Abc_NtkCreatePi( pNtkNew ); - Abc_ObjAssignName( pFanin->pCopy, Abc_ObjName(pFanin), NULL ); - } - // duplicate and connect the node - pNode->pCopy = Abc_NtkDupObj( pNtkNew, pNode, 0 ); - Abc_ObjForEachFanin( pNode, pFanin, i ) - Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy ); - // create the only PO - pNodePo = Abc_NtkCreatePo( pNtkNew ); - Abc_ObjAddFanin( pNodePo, pNode->pCopy ); - Abc_ObjAssignName( pNodePo, Abc_ObjName(pNode), NULL ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Creates the network composed of one node with the given SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pFanin, * pNode, * pNodePo; - Vec_Ptr_t * vNames; - int i, nVars; - // start the network - pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); - pNtkNew->pName = Extra_UtilStrsav("ex"); - // create PIs - Vec_PtrPush( pNtkNew->vObjs, NULL ); - nVars = Abc_SopGetVarNum( pSop ); - vNames = Abc_NodeGetFakeNames( nVars ); - for ( i = 0; i < nVars; i++ ) - Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Vec_PtrEntry(vNames, i), NULL ); - Abc_NodeFreeNames( vNames ); - // create the node, add PIs as fanins, set the function - pNode = Abc_NtkCreateNode( pNtkNew ); - Abc_NtkForEachPi( pNtkNew, pFanin, i ) - Abc_ObjAddFanin( pNode, pFanin ); - pNode->pData = Abc_SopRegister( pNtkNew->pManFunc, pSop ); - // create the only PO - pNodePo = Abc_NtkCreatePo(pNtkNew); - Abc_ObjAddFanin( pNodePo, pNode ); - Abc_ObjAssignName( pNodePo, "F", NULL ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkCreateWithNode(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Deletes the Ntk.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDelete( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - void * pAttrMan; - int TotalMemory, i; - int LargePiece = (4 << ABC_NUM_STEPS); - if ( pNtk == NULL ) - return; - // free the HAIG - if ( pNtk->pHaig ) - Abc_NtkHaigStop( pNtk ); - // free EXDC Ntk - if ( pNtk->pExdc ) - Abc_NtkDelete( pNtk->pExdc ); - // dereference the BDDs - if ( Abc_NtkHasBdd(pNtk) ) - { - Abc_NtkForEachNode( pNtk, pObj, i ) - Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData ); - } - // make sure all the marks are clean - Abc_NtkForEachObj( pNtk, pObj, i ) - { - // free large fanout arrays - if ( pNtk->pMmObj && pObj->vFanouts.nCap * 4 > LargePiece ) - FREE( pObj->vFanouts.pArray ); - // these flags should be always zero - // if this is not true, something is wrong somewhere - assert( pObj->fMarkA == 0 ); - assert( pObj->fMarkB == 0 ); - assert( pObj->fMarkC == 0 ); - } - // free the nodes - if ( pNtk->pMmStep == NULL ) - { - Abc_NtkForEachObj( pNtk, pObj, i ) - { - FREE( pObj->vFanouts.pArray ); - FREE( pObj->vFanins.pArray ); - } - } - if ( pNtk->pMmObj == NULL ) - { - Abc_NtkForEachObj( pNtk, pObj, i ) - free( pObj ); - } - - // free the arrays - Vec_PtrFree( pNtk->vPios ); - Vec_PtrFree( pNtk->vPis ); - Vec_PtrFree( pNtk->vPos ); - Vec_PtrFree( pNtk->vCis ); - Vec_PtrFree( pNtk->vCos ); - Vec_PtrFree( pNtk->vAsserts ); - Vec_PtrFree( pNtk->vObjs ); - Vec_PtrFree( pNtk->vBoxes ); - if ( pNtk->vLevelsR ) Vec_IntFree( pNtk->vLevelsR ); - if ( pNtk->pModel ) free( pNtk->pModel ); - TotalMemory = 0; - TotalMemory += pNtk->pMmObj? Extra_MmFixedReadMemUsage(pNtk->pMmObj) : 0; - TotalMemory += pNtk->pMmStep? Extra_MmStepReadMemUsage(pNtk->pMmStep) : 0; -// fprintf( stdout, "The total memory allocated internally by the network = %0.2f Mb.\n", ((double)TotalMemory)/(1<<20) ); - // free the storage - if ( pNtk->pMmObj ) - Extra_MmFixedStop( pNtk->pMmObj ); - if ( pNtk->pMmStep ) - Extra_MmStepStop ( pNtk->pMmStep ); - // name manager - Nm_ManFree( pNtk->pManName ); - // free the timing manager - if ( pNtk->pManTime ) - Abc_ManTimeStop( pNtk->pManTime ); - // start the functionality manager - if ( Abc_NtkIsStrash(pNtk) ) - Abc_AigFree( pNtk->pManFunc ); - else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) - Extra_MmFlexStop( pNtk->pManFunc ); - else if ( Abc_NtkHasBdd(pNtk) ) - Extra_StopManager( pNtk->pManFunc ); - else if ( Abc_NtkHasAig(pNtk) ) - { if ( pNtk->pManFunc ) Hop_ManStop( pNtk->pManFunc ); } - else if ( Abc_NtkHasMapping(pNtk) ) - pNtk->pManFunc = NULL; - else if ( !Abc_NtkHasBlackbox(pNtk) ) - assert( 0 ); - // free the hierarchy - if ( pNtk->pDesign ) - { - Abc_LibFree( pNtk->pDesign, pNtk ); - pNtk->pDesign = NULL; - } -// if ( pNtk->pBlackBoxes ) -// Vec_IntFree( pNtk->pBlackBoxes ); - // free node attributes - Vec_PtrForEachEntry( pNtk->vAttrs, pAttrMan, i ) - if ( pAttrMan ) - { -//printf( "deleting attr\n" ); - Vec_AttFree( pAttrMan, 1 ); - } - Vec_PtrFree( pNtk->vAttrs ); - FREE( pNtk->pName ); - FREE( pNtk->pSpec ); - free( pNtk ); -} - -/**Function************************************************************* - - Synopsis [Reads the verilog file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNets; - Abc_Obj_t * pNet, * pNode; - int i; - - if ( Abc_NtkNodeNum(pNtk) == 0 && Abc_NtkBoxNum(pNtk) == 0 ) - return; - - // check for non-driven nets - vNets = Vec_PtrAlloc( 100 ); - Abc_NtkForEachNet( pNtk, pNet, i ) - { - if ( Abc_ObjFaninNum(pNet) > 0 ) - continue; - // add the constant 0 driver - pNode = Abc_NtkCreateNodeConst0( pNtk ); - // add the fanout net - Abc_ObjAddFanin( pNet, pNode ); - // add the net to those for which the warning will be printed - Vec_PtrPush( vNets, pNet ); - } - - // print the warning - if ( vNets->nSize > 0 ) - { - printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName ); - Vec_PtrForEachEntry( vNets, pNet, i ) - { - printf( "%s%s", (i? ", ": ""), Abc_ObjName(pNet) ); - if ( i == 3 ) - { - if ( Vec_PtrSize(vNets) > 3 ) - printf( " ..." ); - break; - } - } - printf( "\n" ); - } - Vec_PtrFree( vNets ); -} - - -/**Function************************************************************* - - Synopsis [Converts the network to combinational.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMakeComb( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - - if ( Abc_NtkIsComb(pNtk) ) - return; - - assert( !Abc_NtkIsNetlist(pNtk) ); - assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); - - // detach the latches -// Abc_NtkForEachLatch( pNtk, pObj, i ) - Vec_PtrForEachEntryReverse( pNtk->vBoxes, pObj, i ) - Abc_NtkDeleteObj( pObj ); - assert( Abc_NtkLatchNum(pNtk) == 0 ); - assert( Abc_NtkBoxNum(pNtk) == 0 ); - - // move CIs to become PIs - Vec_PtrClear( pNtk->vPis ); - Abc_NtkForEachCi( pNtk, pObj, i ) - { - if ( Abc_ObjIsBo(pObj) ) - { - pObj->Type = ABC_OBJ_PI; - pNtk->nObjCounts[ABC_OBJ_PI]++; - pNtk->nObjCounts[ABC_OBJ_BO]--; - } - Vec_PtrPush( pNtk->vPis, pObj ); - } - assert( Abc_NtkBoNum(pNtk) == 0 ); - - // move COs to become POs - Vec_PtrClear( pNtk->vPos ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - if ( Abc_ObjIsBi(pObj) ) - { - pObj->Type = ABC_OBJ_PO; - pNtk->nObjCounts[ABC_OBJ_PO]++; - pNtk->nObjCounts[ABC_OBJ_BI]--; - } - Vec_PtrPush( pNtk->vPos, pObj ); - } - assert( Abc_NtkBiNum(pNtk) == 0 ); - - if ( !Abc_NtkCheck( pNtk ) ) - fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" ); -} - - -/**Function************************************************************* - - Synopsis [Removes POs with suppsize less than 2 and PIs without fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i, k, m; - - // filter POs - k = m = 0; - Abc_NtkForEachCo( pNtk, pObj, i ) - { - if ( Abc_ObjIsPo(pObj) ) - { - // remove constant nodes and PI pointers - if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 0 ) - { - Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); - if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 && !Abc_ObjIsPi(Abc_ObjFanin0(pObj)) ) - Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); - pNtk->vObjs->pArray[pObj->Id] = NULL; - pObj->Id = (1<<26)-1; - pNtk->nObjCounts[pObj->Type]--; - pNtk->nObjs--; - Abc_ObjRecycle( pObj ); - continue; - } - // remove buffers/inverters of PIs - if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 1 ) - { - if ( Abc_ObjIsPi(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) ) - { - Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); - if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 ) - Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); - pNtk->vObjs->pArray[pObj->Id] = NULL; - pObj->Id = (1<<26)-1; - pNtk->nObjCounts[pObj->Type]--; - pNtk->nObjs--; - Abc_ObjRecycle( pObj ); - continue; - } - } - Vec_PtrWriteEntry( pNtk->vPos, m++, pObj ); - } - Vec_PtrWriteEntry( pNtk->vCos, k++, pObj ); - } - Vec_PtrShrink( pNtk->vPos, m ); - Vec_PtrShrink( pNtk->vCos, k ); - - // filter PIs - k = m = 0; - Abc_NtkForEachCi( pNtk, pObj, i ) - { - if ( Abc_ObjIsPi(pObj) ) - { - if ( Abc_ObjFanoutNum(pObj) == 0 ) - { - pNtk->vObjs->pArray[pObj->Id] = NULL; - pObj->Id = (1<<26)-1; - pNtk->nObjCounts[pObj->Type]--; - pNtk->nObjs--; - Abc_ObjRecycle( pObj ); - continue; - } - Vec_PtrWriteEntry( pNtk->vPis, m++, pObj ); - } - Vec_PtrWriteEntry( pNtk->vCis, k++, pObj ); - } - Vec_PtrShrink( pNtk->vPis, m ); - Vec_PtrShrink( pNtk->vCis, k ); - - return Abc_NtkDup( pNtk ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcObj.c b/src/base/abc/abcObj.c deleted file mode 100644 index 7a995c71..00000000 --- a/src/base/abc/abcObj.c +++ /dev/null @@ -1,976 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcObj.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Object creation/duplication/deletion procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcObj.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "abcInt.h" -#include "main.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates a new object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) -{ - Abc_Obj_t * pObj; - if ( pNtk->pMmObj ) - pObj = (Abc_Obj_t *)Extra_MmFixedEntryFetch( pNtk->pMmObj ); - else - pObj = (Abc_Obj_t *)ALLOC( Abc_Obj_t, 1 ); - memset( pObj, 0, sizeof(Abc_Obj_t) ); - pObj->pNtk = pNtk; - pObj->Type = Type; - pObj->Id = -1; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Recycles the object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjRecycle( Abc_Obj_t * pObj ) -{ - Abc_Ntk_t * pNtk = pObj->pNtk; - int LargePiece = (4 << ABC_NUM_STEPS); - // free large fanout arrays - if ( pNtk->pMmStep && pObj->vFanouts.nCap * 4 > LargePiece ) - FREE( pObj->vFanouts.pArray ); - if ( pNtk->pMmStep == NULL ) - { - FREE( pObj->vFanouts.pArray ); - FREE( pObj->vFanins.pArray ); - } - // clean the memory to make deleted object distinct from the live one - memset( pObj, 0, sizeof(Abc_Obj_t) ); - // recycle the object - if ( pNtk->pMmObj ) - Extra_MmFixedEntryRecycle( pNtk->pMmObj, (char *)pObj ); - else - free( pObj ); -} - -/**Function************************************************************* - - Synopsis [Adds the node to the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) -{ - Abc_Obj_t * pObj; - // create new object, assign ID, and add to the array - pObj = Abc_ObjAlloc( pNtk, Type ); - pObj->Id = pNtk->vObjs->nSize; - Vec_PtrPush( pNtk->vObjs, pObj ); - pNtk->nObjCounts[Type]++; - pNtk->nObjs++; - // perform specialized operations depending on the object type - switch (Type) - { - case ABC_OBJ_NONE: - assert(0); - break; - case ABC_OBJ_CONST1: - assert(0); - break; - case ABC_OBJ_PIO: - assert(0); - break; - case ABC_OBJ_PI: - Vec_PtrPush( pNtk->vPis, pObj ); - Vec_PtrPush( pNtk->vCis, pObj ); - break; - case ABC_OBJ_PO: - Vec_PtrPush( pNtk->vPos, pObj ); - Vec_PtrPush( pNtk->vCos, pObj ); - break; - case ABC_OBJ_BI: - if ( pNtk->vCos ) Vec_PtrPush( pNtk->vCos, pObj ); - break; - case ABC_OBJ_BO: - if ( pNtk->vCis ) Vec_PtrPush( pNtk->vCis, pObj ); - break; - case ABC_OBJ_ASSERT: - Vec_PtrPush( pNtk->vAsserts, pObj ); - Vec_PtrPush( pNtk->vCos, pObj ); - break; - case ABC_OBJ_NET: - case ABC_OBJ_NODE: - break; - case ABC_OBJ_LATCH: - pObj->pData = (void *)ABC_INIT_NONE; - case ABC_OBJ_WHITEBOX: - case ABC_OBJ_BLACKBOX: - if ( pNtk->vBoxes ) Vec_PtrPush( pNtk->vBoxes, pObj ); - break; - default: - assert(0); - break; - } - return pObj; -} - -/**Function************************************************************* - - Synopsis [Deletes the object from the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDeleteObj( Abc_Obj_t * pObj ) -{ - Abc_Ntk_t * pNtk = pObj->pNtk; - Vec_Ptr_t * vNodes; - int i; - assert( !Abc_ObjIsComplement(pObj) ); - // remove from the table of names - if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) ) - Nm_ManDeleteIdName(pObj->pNtk->pManName, pObj->Id); - // delete fanins and fanouts - vNodes = Vec_PtrAlloc( 100 ); - Abc_NodeCollectFanouts( pObj, vNodes ); - for ( i = 0; i < vNodes->nSize; i++ ) - Abc_ObjDeleteFanin( vNodes->pArray[i], pObj ); - Abc_NodeCollectFanins( pObj, vNodes ); - for ( i = 0; i < vNodes->nSize; i++ ) - Abc_ObjDeleteFanin( pObj, vNodes->pArray[i] ); - Vec_PtrFree( vNodes ); - // remove from the list of objects - Vec_PtrWriteEntry( pNtk->vObjs, pObj->Id, NULL ); - pObj->Id = (1<<26)-1; - pNtk->nObjCounts[pObj->Type]--; - pNtk->nObjs--; - // perform specialized operations depending on the object type - switch (pObj->Type) - { - case ABC_OBJ_NONE: - assert(0); - break; - case ABC_OBJ_CONST1: - assert(0); - break; - case ABC_OBJ_PIO: - assert(0); - break; - case ABC_OBJ_PI: - Vec_PtrRemove( pNtk->vPis, pObj ); - Vec_PtrRemove( pNtk->vCis, pObj ); - break; - case ABC_OBJ_PO: - Vec_PtrRemove( pNtk->vPos, pObj ); - Vec_PtrRemove( pNtk->vCos, pObj ); - break; - case ABC_OBJ_BI: - if ( pNtk->vCos ) Vec_PtrRemove( pNtk->vCos, pObj ); - break; - case ABC_OBJ_BO: - if ( pNtk->vCis ) Vec_PtrRemove( pNtk->vCis, pObj ); - break; - case ABC_OBJ_ASSERT: - Vec_PtrRemove( pNtk->vAsserts, pObj ); - Vec_PtrRemove( pNtk->vCos, pObj ); - break; - case ABC_OBJ_NET: - break; - case ABC_OBJ_NODE: - if ( Abc_NtkHasBdd(pNtk) ) - Cudd_RecursiveDeref( pNtk->pManFunc, pObj->pData ); - pObj->pData = NULL; - break; - case ABC_OBJ_LATCH: - case ABC_OBJ_WHITEBOX: - case ABC_OBJ_BLACKBOX: - if ( pNtk->vBoxes ) Vec_PtrRemove( pNtk->vBoxes, pObj ); - break; - default: - assert(0); - break; - } - // recycle the object memory - Abc_ObjRecycle( pObj ); -} - -/**Function************************************************************* - - Synopsis [Deletes the node and MFFC of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes ) -{ - Vec_Ptr_t * vNodes; - int i; - assert( !Abc_ObjIsComplement(pObj) ); - assert( !Abc_ObjIsPi(pObj) ); - assert( Abc_ObjFanoutNum(pObj) == 0 ); - // delete fanins and fanouts - vNodes = Vec_PtrAlloc( 100 ); - Abc_NodeCollectFanins( pObj, vNodes ); - Abc_NtkDeleteObj( pObj ); - if ( fOnlyNodes ) - { - Vec_PtrForEachEntry( vNodes, pObj, i ) - if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) - Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); - } - else - { - Vec_PtrForEachEntry( vNodes, pObj, i ) - if ( !Abc_ObjIsPi(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) - Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); - } - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Deletes the node and MFFC of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ) -{ - Vec_Ptr_t * vNodes; - int i; - assert( !Abc_ObjIsComplement(pObj) ); - assert( Abc_ObjFanoutNum(pObj) == 0 ); - // delete fanins and fanouts - vNodes = Vec_PtrAlloc( 100 ); - Abc_NodeCollectFanins( pObj, vNodes ); - Abc_NtkDeleteObj( pObj ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - if ( !Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) - Abc_NtkDeleteAll_rec( pObj ); - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Duplicate the Obj.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName ) -{ - Abc_Obj_t * pObjNew; - // create the new object - pObjNew = Abc_NtkCreateObj( pNtkNew, pObj->Type ); - // transfer names of the terminal objects - if ( fCopyName ) - { - if ( Abc_ObjIsCi(pObj) ) - { - if ( !Abc_NtkIsNetlist(pNtkNew) ) - Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); - } - else if ( Abc_ObjIsCo(pObj) ) - { - if ( !Abc_NtkIsNetlist(pNtkNew) ) - { - if ( Abc_ObjIsPo(pObj) ) - Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); - else - { - assert( Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ); - Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); - } - } - } - else if ( Abc_ObjIsBox(pObj) || Abc_ObjIsNet(pObj) ) - Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); - } - // copy functionality/names - if ( Abc_ObjIsNode(pObj) ) // copy the function if functionality is compatible - { - if ( pNtkNew->ntkFunc == pObj->pNtk->ntkFunc ) - { - if ( Abc_NtkIsStrash(pNtkNew) ) - {} - else if ( Abc_NtkHasSop(pNtkNew) || Abc_NtkHasBlifMv(pNtkNew) ) - pObjNew->pData = Abc_SopRegister( pNtkNew->pManFunc, pObj->pData ); - else if ( Abc_NtkHasBdd(pNtkNew) ) - pObjNew->pData = Cudd_bddTransfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData), Cudd_Ref(pObjNew->pData); - else if ( Abc_NtkHasAig(pNtkNew) ) - pObjNew->pData = Hop_Transfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData, Abc_ObjFaninNum(pObj)); - else if ( Abc_NtkHasMapping(pNtkNew) ) - pObjNew->pData = pObj->pData; - else assert( 0 ); - } - } - else if ( Abc_ObjIsNet(pObj) ) // copy the name - { - } - else if ( Abc_ObjIsLatch(pObj) ) // copy the reset value - pObjNew->pData = pObj->pData; - // transfer HAIG -// pObjNew->pEquiv = pObj->pEquiv; - // remember the new node in the old node - pObj->pCopy = pObjNew; - return pObjNew; -} - -/**Function************************************************************* - - Synopsis [Duplicates the latch with its input/output terminals.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName ) -{ - Abc_Obj_t * pTerm, * pBoxNew; - int i; - assert( Abc_ObjIsBox(pBox) ); - // duplicate the box - pBoxNew = Abc_NtkDupObj( pNtkNew, pBox, fCopyName ); - // duplicate the fanins and connect them - Abc_ObjForEachFanin( pBox, pTerm, i ) - Abc_ObjAddFanin( pBoxNew, Abc_NtkDupObj(pNtkNew, pTerm, fCopyName) ); - // duplicate the fanouts and connect them - Abc_ObjForEachFanout( pBox, pTerm, i ) - Abc_ObjAddFanin( Abc_NtkDupObj(pNtkNew, pTerm, fCopyName), pBoxNew ); - return pBoxNew; -} - -/**Function************************************************************* - - Synopsis [Clones the objects in the same network but does not assign its function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pClone, * pFanin; - int i; - pClone = Abc_NtkCreateObj( pObj->pNtk, pObj->Type ); - Abc_ObjForEachFanin( pObj, pFanin, i ) - Abc_ObjAddFanin( pClone, pFanin ); - return pClone; -} - - -/**Function************************************************************* - - Synopsis [Returns the net with the given name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ) -{ - Abc_Obj_t * pObj; - int Num; - // try to find the terminal - Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO ); - if ( Num >= 0 ) - return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); - Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI ); - if ( Num >= 0 ) - return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); - Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NODE ); - if ( Num >= 0 ) - return Abc_NtkObj( pNtk, Num ); - // find the internal node - if ( pName[0] != 'n' ) - { - printf( "Name \"%s\" is not found among CO or node names (internal names often look as \"n\").\n", pName ); - return NULL; - } - Num = atoi( pName + 1 ); - if ( Num < 0 || Num >= Abc_NtkObjNumMax(pNtk) ) - { - printf( "The node \"%s\" with ID %d is not in the current network.\n", pName, Num ); - return NULL; - } - pObj = Abc_NtkObj( pNtk, Num ); - if ( pObj == NULL ) - { - printf( "The node \"%s\" with ID %d has been removed from the current network.\n", pName, Num ); - return NULL; - } - if ( !Abc_ObjIsNode(pObj) ) - { - printf( "Object with ID %d is not a node.\n", Num ); - return NULL; - } - return pObj; -} - -/**Function************************************************************* - - Synopsis [Returns the net with the given name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ) -{ - Abc_Obj_t * pNet; - int ObjId; - assert( Abc_NtkIsNetlist(pNtk) ); - ObjId = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NET ); - if ( ObjId == -1 ) - return NULL; - pNet = Abc_NtkObj( pNtk, ObjId ); - return pNet; -} - -/**Function************************************************************* - - Synopsis [Returns CI with the given name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName ) -{ - int Num; - assert( !Abc_NtkIsNetlist(pNtk) ); - Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PI ); - if ( Num >= 0 ) - return Abc_NtkObj( pNtk, Num ); - Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BO ); - if ( Num >= 0 ) - return Abc_NtkObj( pNtk, Num ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Returns CO with the given name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ) -{ - int Num; - assert( !Abc_NtkIsNetlist(pNtk) ); - Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO ); - if ( Num >= 0 ) - return Abc_NtkObj( pNtk, Num ); - Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI ); - if ( Num >= 0 ) - return Abc_NtkObj( pNtk, Num ); - return NULL; -} - - -/**Function************************************************************* - - Synopsis [Finds or creates the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ) -{ - Abc_Obj_t * pNet; - assert( Abc_NtkIsNetlist(pNtk) ); - if ( pName && (pNet = Abc_NtkFindNet( pNtk, pName )) ) - return pNet; -//printf( "Creating net %s.\n", pName ); - // create a new net - pNet = Abc_NtkCreateNet( pNtk ); - if ( pName ) - Nm_ManStoreIdName( pNtk->pManName, pNet->Id, pNet->Type, pName, NULL ); - return pNet; -} - -/**Function************************************************************* - - Synopsis [Creates constant 0 node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - pNode = Abc_NtkCreateNode( pNtk ); - if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) - pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" ); - else if ( Abc_NtkHasBdd(pNtk) ) - pNode->pData = Cudd_ReadLogicZero(pNtk->pManFunc), Cudd_Ref( pNode->pData ); - else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Hop_ManConst0(pNtk->pManFunc); - else if ( Abc_NtkHasMapping(pNtk) ) - pNode->pData = Mio_LibraryReadConst0(Abc_FrameReadLibGen()); - else if ( !Abc_NtkHasBlackbox(pNtk) ) - assert( 0 ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates constant 1 node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - pNode = Abc_NtkCreateNode( pNtk ); - if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) - pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 1\n" ); - else if ( Abc_NtkHasBdd(pNtk) ) - pNode->pData = Cudd_ReadOne(pNtk->pManFunc), Cudd_Ref( pNode->pData ); - else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Hop_ManConst1(pNtk->pManFunc); - else if ( Abc_NtkHasMapping(pNtk) ) - pNode->pData = Mio_LibraryReadConst1(Abc_FrameReadLibGen()); - else if ( !Abc_NtkHasBlackbox(pNtk) ) - assert( 0 ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates inverter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) -{ - Abc_Obj_t * pNode; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - pNode = Abc_NtkCreateNode( pNtk ); - if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin ); - if ( Abc_NtkHasSop(pNtk) ) - pNode->pData = Abc_SopRegister( pNtk->pManFunc, "0 1\n" ); - else if ( Abc_NtkHasBdd(pNtk) ) - pNode->pData = Cudd_Not(Cudd_bddIthVar(pNtk->pManFunc,0)), Cudd_Ref( pNode->pData ); - else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Hop_Not(Hop_IthVar(pNtk->pManFunc,0)); - else if ( Abc_NtkHasMapping(pNtk) ) - pNode->pData = Mio_LibraryReadInv(Abc_FrameReadLibGen()); - else - assert( 0 ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates buffer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) -{ - Abc_Obj_t * pNode; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - pNode = Abc_NtkCreateNode( pNtk ); - if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin ); - if ( Abc_NtkHasSop(pNtk) ) - pNode->pData = Abc_SopRegister( pNtk->pManFunc, "1 1\n" ); - else if ( Abc_NtkHasBdd(pNtk) ) - pNode->pData = Cudd_bddIthVar(pNtk->pManFunc,0), Cudd_Ref( pNode->pData ); - else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Hop_IthVar(pNtk->pManFunc,0); - else if ( Abc_NtkHasMapping(pNtk) ) - pNode->pData = Mio_LibraryReadBuf(Abc_FrameReadLibGen()); - else - assert( 0 ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates AND.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) -{ - Abc_Obj_t * pNode; - int i; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - pNode = Abc_NtkCreateNode( pNtk ); - for ( i = 0; i < vFanins->nSize; i++ ) - Abc_ObjAddFanin( pNode, vFanins->pArray[i] ); - if ( Abc_NtkHasSop(pNtk) ) - pNode->pData = Abc_SopCreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins), NULL ); - else if ( Abc_NtkHasBdd(pNtk) ) - pNode->pData = Extra_bddCreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); - else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Vec_PtrSize(vFanins) ); - else - assert( 0 ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates OR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) -{ - Abc_Obj_t * pNode; - int i; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - pNode = Abc_NtkCreateNode( pNtk ); - for ( i = 0; i < vFanins->nSize; i++ ) - Abc_ObjAddFanin( pNode, vFanins->pArray[i] ); - if ( Abc_NtkHasSop(pNtk) ) - pNode->pData = Abc_SopCreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins), NULL ); - else if ( Abc_NtkHasBdd(pNtk) ) - pNode->pData = Extra_bddCreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); - else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Hop_CreateOr( pNtk->pManFunc, Vec_PtrSize(vFanins) ); - else - assert( 0 ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates EXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) -{ - Abc_Obj_t * pNode; - int i; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - pNode = Abc_NtkCreateNode( pNtk ); - for ( i = 0; i < vFanins->nSize; i++ ) - Abc_ObjAddFanin( pNode, vFanins->pArray[i] ); - if ( Abc_NtkHasSop(pNtk) ) - pNode->pData = Abc_SopCreateXorSpecial( pNtk->pManFunc, Vec_PtrSize(vFanins) ); - else if ( Abc_NtkHasBdd(pNtk) ) - pNode->pData = Extra_bddCreateExor( pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref(pNode->pData); - else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Hop_CreateExor( pNtk->pManFunc, Vec_PtrSize(vFanins) ); - else - assert( 0 ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates MUX.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ) -{ - Abc_Obj_t * pNode; - assert( Abc_NtkIsLogic(pNtk) ); - pNode = Abc_NtkCreateNode( pNtk ); - Abc_ObjAddFanin( pNode, pNodeC ); - Abc_ObjAddFanin( pNode, pNode1 ); - Abc_ObjAddFanin( pNode, pNode0 ); - if ( Abc_NtkHasSop(pNtk) ) - pNode->pData = Abc_SopRegister( pNtk->pManFunc, "11- 1\n0-1 1\n" ); - else if ( Abc_NtkHasBdd(pNtk) ) - pNode->pData = Cudd_bddIte(pNtk->pManFunc,Cudd_bddIthVar(pNtk->pManFunc,0),Cudd_bddIthVar(pNtk->pManFunc,1),Cudd_bddIthVar(pNtk->pManFunc,2)), Cudd_Ref( pNode->pData ); - else if ( Abc_NtkHasAig(pNtk) ) - pNode->pData = Hop_Mux(pNtk->pManFunc,Hop_IthVar(pNtk->pManFunc,0),Hop_IthVar(pNtk->pManFunc,1),Hop_IthVar(pNtk->pManFunc,2)); - else - assert( 0 ); - return pNode; -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is a constant 0 node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NodeIsConst( Abc_Obj_t * pNode ) -{ - assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) ); - return Abc_ObjIsNode(pNode) && Abc_ObjFaninNum(pNode) == 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is a constant 0 node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NodeIsConst0( Abc_Obj_t * pNode ) -{ - Abc_Ntk_t * pNtk = pNode->pNtk; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - assert( Abc_ObjIsNode(pNode) ); - if ( !Abc_NodeIsConst(pNode) ) - return 0; - if ( Abc_NtkHasSop(pNtk) ) - return Abc_SopIsConst0(pNode->pData); - if ( Abc_NtkHasBdd(pNtk) ) - return Cudd_IsComplement(pNode->pData); - if ( Abc_NtkHasAig(pNtk) ) - return Hop_IsComplement(pNode->pData); - if ( Abc_NtkHasMapping(pNtk) ) - return pNode->pData == Mio_LibraryReadConst0(Abc_FrameReadLibGen()); - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is a constant 1 node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NodeIsConst1( Abc_Obj_t * pNode ) -{ - Abc_Ntk_t * pNtk = pNode->pNtk; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - assert( Abc_ObjIsNode(pNode) ); - if ( !Abc_NodeIsConst(pNode) ) - return 0; - if ( Abc_NtkHasSop(pNtk) ) - return Abc_SopIsConst1(pNode->pData); - if ( Abc_NtkHasBdd(pNtk) ) - return !Cudd_IsComplement(pNode->pData); - if ( Abc_NtkHasAig(pNtk) ) - return !Hop_IsComplement(pNode->pData); - if ( Abc_NtkHasMapping(pNtk) ) - return pNode->pData == Mio_LibraryReadConst1(Abc_FrameReadLibGen()); - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is a buffer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NodeIsBuf( Abc_Obj_t * pNode ) -{ - Abc_Ntk_t * pNtk = pNode->pNtk; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - assert( Abc_ObjIsNode(pNode) ); - if ( Abc_ObjFaninNum(pNode) != 1 ) - return 0; - if ( Abc_NtkHasSop(pNtk) ) - return Abc_SopIsBuf(pNode->pData); - if ( Abc_NtkHasBdd(pNtk) ) - return !Cudd_IsComplement(pNode->pData); - if ( Abc_NtkHasAig(pNtk) ) - return !Hop_IsComplement(pNode->pData); - if ( Abc_NtkHasMapping(pNtk) ) - return pNode->pData == Mio_LibraryReadBuf(Abc_FrameReadLibGen()); - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is an inverter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NodeIsInv( Abc_Obj_t * pNode ) -{ - Abc_Ntk_t * pNtk = pNode->pNtk; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); - assert( Abc_ObjIsNode(pNode) ); - if ( Abc_ObjFaninNum(pNode) != 1 ) - return 0; - if ( Abc_NtkHasSop(pNtk) ) - return Abc_SopIsInv(pNode->pData); - if ( Abc_NtkHasBdd(pNtk) ) - return Cudd_IsComplement(pNode->pData); - if ( Abc_NtkHasAig(pNtk) ) - return Hop_IsComplement(pNode->pData); - if ( Abc_NtkHasMapping(pNtk) ) - return pNode->pData == Mio_LibraryReadInv(Abc_FrameReadLibGen()); - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Complements the local functions of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeComplement( Abc_Obj_t * pNode ) -{ - assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) ); - assert( Abc_ObjIsNode(pNode) ); - if ( Abc_NtkHasSop(pNode->pNtk) ) - Abc_SopComplement( pNode->pData ); - else if ( Abc_NtkHasBdd(pNode->pNtk) ) - pNode->pData = Cudd_Not( pNode->pData ); - else if ( Abc_NtkHasAig(pNode->pNtk) ) - pNode->pData = Hop_Not( pNode->pData ); - else - assert( 0 ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/abc/abcRefs.c b/src/base/abc/abcRefs.c deleted file mode 100644 index 604c5ffa..00000000 --- a/src/base/abc/abcRefs.c +++ /dev/null @@ -1,452 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcRefs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures using reference counting of the AIG nodes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcRefs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel ); -static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the MFFC size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeMffcSize( Abc_Obj_t * pNode ) -{ - int nConeSize1, nConeSize2; -// assert( Abc_NtkIsStrash(pNode->pNtk) ); -// assert( !Abc_ObjIsComplement( pNode ) ); - assert( Abc_ObjIsNode( pNode ) ); - if ( Abc_ObjFaninNum(pNode) == 0 ) - return 0; - nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference - nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference - assert( nConeSize1 == nConeSize2 ); - assert( nConeSize1 > 0 ); - return nConeSize1; -} - -/**Function************************************************************* - - Synopsis [Returns the MFFC size while stopping at the complemented edges.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ) -{ - int nConeSize1, nConeSize2; - assert( Abc_NtkIsStrash(pNode->pNtk) ); - assert( !Abc_ObjIsComplement( pNode ) ); - assert( Abc_ObjIsNode( pNode ) ); - if ( Abc_ObjFaninNum(pNode) == 0 ) - return 0; - nConeSize1 = Abc_NodeRefDerefStop( pNode, 0 ); // dereference - nConeSize2 = Abc_NodeRefDerefStop( pNode, 1 ); // reference - assert( nConeSize1 == nConeSize2 ); - assert( nConeSize1 > 0 ); - return nConeSize1; -} - -/**Function************************************************************* - - Synopsis [Labels MFFC with the current traversal ID.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ) -{ - int nConeSize1, nConeSize2; - assert( Abc_NtkIsStrash(pNode->pNtk) ); - assert( !Abc_ObjIsComplement( pNode ) ); - assert( Abc_ObjIsNode( pNode ) ); - if ( Abc_ObjFaninNum(pNode) == 0 ) - return 0; - nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1 ); // dereference - nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference - assert( nConeSize1 == nConeSize2 ); - assert( nConeSize1 > 0 ); - return nConeSize1; -} - -/**Function************************************************************* - - Synopsis [References/references the node and returns MFFC size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel ) -{ - Abc_Obj_t * pNode0, * pNode1; - int Counter; - // label visited nodes - if ( fLabel ) - Abc_NodeSetTravIdCurrent( pNode ); - // skip the CI - if ( Abc_ObjIsCi(pNode) ) - return 0; - // process the internal node - pNode0 = Abc_ObjFanin0(pNode); - pNode1 = Abc_ObjFanin1(pNode); - Counter = 1; - if ( fReference ) - { - if ( pNode0->vFanouts.nSize++ == 0 ) - Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); - if ( pNode1->vFanouts.nSize++ == 0 ) - Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); - } - else - { - assert( pNode0->vFanouts.nSize > 0 ); - assert( pNode1->vFanouts.nSize > 0 ); - if ( --pNode0->vFanouts.nSize == 0 ) - Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); - if ( --pNode1->vFanouts.nSize == 0 ) - Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); - } - return Counter; -} - - -/**Function************************************************************* - - Synopsis [References/references the node and returns MFFC size.] - - Description [Stops at the complemented edges.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, bool fReference ) -{ - Abc_Obj_t * pNode0, * pNode1; - int Counter; - // skip the CI - if ( Abc_ObjIsCi(pNode) ) - return 0; - // process the internal node - pNode0 = Abc_ObjFanin0(pNode); - pNode1 = Abc_ObjFanin1(pNode); - Counter = 1; - if ( fReference ) - { - if ( pNode0->vFanouts.nSize++ == 0 && !Abc_ObjFaninC0(pNode) ) - Counter += Abc_NodeRefDerefStop( pNode0, fReference ); - if ( pNode1->vFanouts.nSize++ == 0 && !Abc_ObjFaninC1(pNode) ) - Counter += Abc_NodeRefDerefStop( pNode1, fReference ); - } - else - { - assert( pNode0->vFanouts.nSize > 0 ); - assert( pNode1->vFanouts.nSize > 0 ); - if ( --pNode0->vFanouts.nSize == 0 && !Abc_ObjFaninC0(pNode) ) - Counter += Abc_NodeRefDerefStop( pNode0, fReference ); - if ( --pNode1->vFanouts.nSize == 0 && !Abc_ObjFaninC1(pNode) ) - Counter += Abc_NodeRefDerefStop( pNode1, fReference ); - } - return Counter; -} - - - - -/**Function************************************************************* - - Synopsis [Dereferences the node's MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeDeref_rec( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin; - int i, Counter = 1; - if ( Abc_ObjIsCi(pNode) ) - return 0; - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - assert( pFanin->vFanouts.nSize > 0 ); - if ( --pFanin->vFanouts.nSize == 0 ) - Counter += Abc_NodeDeref_rec( pFanin ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [References the node's MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeRef_rec( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin; - int i, Counter = 1; - if ( Abc_ObjIsCi(pNode) ) - return 0; - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - if ( pFanin->vFanouts.nSize++ == 0 ) - Counter += Abc_NodeRef_rec( pFanin ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeMffsConeSupp_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost ) -{ - Abc_Obj_t * pFanin; - int i; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pNode) ) - return; - Abc_NodeSetTravIdCurrent(pNode); - // add to the new support nodes - if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) ) - { - if ( vSupp ) Vec_PtrPush( vSupp, pNode ); - return; - } - // recur on the children - Abc_ObjForEachFanin( pNode, pFanin, i ) - Abc_NodeMffsConeSupp_rec( pFanin, vCone, vSupp, 0 ); - // collect the internal node - if ( vCone ) Vec_PtrPush( vCone, pNode ); -// printf( "%d ", pNode->Id ); -} - -/**Function************************************************************* - - Synopsis [Collects the support of the derefed MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeMffsConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ) -{ - assert( Abc_ObjIsNode(pNode) ); - assert( !Abc_ObjIsComplement(pNode) ); - if ( vCone ) Vec_PtrClear( vCone ); - if ( vSupp ) Vec_PtrClear( vSupp ); - Abc_NtkIncrementTravId( pNode->pNtk ); - Abc_NodeMffsConeSupp_rec( pNode, vCone, vSupp, 1 ); -// printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Collects the support of the derefed MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vCone, * vSupp; - Abc_Obj_t * pObj; - int i; - vCone = Vec_PtrAlloc( 100 ); - vSupp = Vec_PtrAlloc( 100 ); - Abc_NodeDeref_rec( pNode ); - Abc_NodeMffsConeSupp( pNode, vCone, vSupp ); - Abc_NodeRef_rec( pNode ); - printf( "Node = %6s : Supp = %3d Cone = %3d (", - Abc_ObjName(pNode), Vec_PtrSize(vSupp), Vec_PtrSize(vCone) ); - Vec_PtrForEachEntry( vCone, pObj, i ) - printf( " %s", Abc_ObjName(pObj) ); - printf( " )\n" ); - Vec_PtrFree( vCone ); - Vec_PtrFree( vSupp ); -} - -/**Function************************************************************* - - Synopsis [Collects the internal nodes of the MFFC limited by cut.] - - Description [] - - SideEffects [Increments the trav ID and marks visited nodes.] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeMffsInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside ) -{ - Abc_Obj_t * pObj; - int i, Count1, Count2; - // increment the fanout counters for the leaves - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->vFanouts.nSize++; - // dereference the node - Count1 = Abc_NodeDeref_rec( pNode ); - // collect the nodes inside the MFFC - Abc_NodeMffsConeSupp( pNode, vInside, NULL ); - // reference it back - Count2 = Abc_NodeRef_rec( pNode ); - assert( Count1 == Count2 ); - // remove the extra counters - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->vFanouts.nSize--; - return Count1; -} - -/**Function************************************************************* - - Synopsis [Collects the internal nodes of the MFFC limited by cut.] - - Description [] - - SideEffects [Increments the trav ID and marks visited nodes.] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NodeMffsInsideCollect( Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vInside; - int Count1, Count2; - // dereference the node - Count1 = Abc_NodeDeref_rec( pNode ); - // collect the nodes inside the MFFC - vInside = Vec_PtrAlloc( 10 ); - Abc_NodeMffsConeSupp( pNode, vInside, NULL ); - // reference it back - Count2 = Abc_NodeRef_rec( pNode ); - assert( Count1 == Count2 ); - return vInside; -} - -/**Function************************************************************* - - Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeMffcLabel_rec( Abc_Obj_t * pNode, int fTopmost ) -{ - Abc_Obj_t * pFanin; - int i; - // add to the new support nodes - if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) ) - return; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pNode) ) - return; - Abc_NodeSetTravIdCurrent(pNode); - // recur on the children - Abc_ObjForEachFanin( pNode, pFanin, i ) - Abc_NodeMffcLabel_rec( pFanin, 0 ); - // collect the internal node -// printf( "%d ", pNode->Id ); -} - -/**Function************************************************************* - - Synopsis [Collects the internal nodes of the MFFC limited by cut.] - - Description [] - - SideEffects [Increments the trav ID and marks visited nodes.] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeMffcLabel( Abc_Obj_t * pNode ) -{ - int Count1, Count2; - // dereference the node - Count1 = Abc_NodeDeref_rec( pNode ); - // collect the nodes inside the MFFC - Abc_NtkIncrementTravId( pNode->pNtk ); - Abc_NodeMffcLabel_rec( pNode, 1 ); - // reference it back - Count2 = Abc_NodeRef_rec( pNode ); - assert( Count1 == Count2 ); - return Count1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcShow.c b/src/base/abc/abcShow.c deleted file mode 100644 index 40d1dcad..00000000 --- a/src/base/abc/abcShow.c +++ /dev/null @@ -1,318 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcShow.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Visualization procedures using DOT software and GSView.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcShow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifdef WIN32 -#include -#endif - -#include "abc.h" -#include "main.h" -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern void Abc_ShowFile( char * FileNameDot ); -static void Abc_ShowGetFileName( char * pName, char * pBuffer ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Visualizes BDD of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeShowBdd( Abc_Obj_t * pNode ) -{ - FILE * pFile; - Vec_Ptr_t * vNamesIn; - char FileNameDot[200]; - char * pNameOut; - - assert( Abc_NtkIsBddLogic(pNode->pNtk) ); - // create the file name - Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot ); - // check that the file can be opened - if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); - return; - } - - // set the node names - vNamesIn = Abc_NodeGetFaninNames( pNode ); - pNameOut = Abc_ObjName(pNode); - Cudd_DumpDot( pNode->pNtk->pManFunc, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); - Abc_NodeFreeNames( vNamesIn ); - Abc_NtkCleanCopy( pNode->pNtk ); - fclose( pFile ); - - // visualize the file - Abc_ShowFile( FileNameDot ); -} - -/**Function************************************************************* - - Synopsis [Visualizes a reconvergence driven cut at the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) -{ - FILE * pFile; - char FileNameDot[200]; - Abc_ManCut_t * p; - Vec_Ptr_t * vCutSmall; - Vec_Ptr_t * vCutLarge; - Vec_Ptr_t * vInside; - Vec_Ptr_t * vNodesTfo; - Abc_Obj_t * pTemp; - int i; - - assert( Abc_NtkIsStrash(pNode->pNtk) ); - - // start the cut computation manager - p = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, ABC_INFINITY ); - // get the recovergence driven cut - vCutSmall = Abc_NodeFindCut( p, pNode, 1 ); - // get the containing cut - vCutLarge = Abc_NtkManCutReadCutLarge( p ); - // get the array for the inside nodes - vInside = Abc_NtkManCutReadVisited( p ); - // get the inside nodes of the containing cone - Abc_NodeConeCollect( &pNode, 1, vCutLarge, vInside, 1 ); - - // add the nodes in the TFO - vNodesTfo = Abc_NodeCollectTfoCands( p, pNode, vCutSmall, ABC_INFINITY ); - Vec_PtrForEachEntry( vNodesTfo, pTemp, i ) - Vec_PtrPushUnique( vInside, pTemp ); - - // create the file name - Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot ); - // check that the file can be opened - if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); - return; - } - // add the root node to the cone (for visualization) - Vec_PtrPush( vCutSmall, pNode ); - // write the DOT file - Io_WriteDotNtk( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0, 0 ); - // stop the cut computation manager - Abc_NtkManCutStop( p ); - - // visualize the file - Abc_ShowFile( FileNameDot ); -} - -/**Function************************************************************* - - Synopsis [Visualizes AIG with choices.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse ) -{ - FILE * pFile; - Abc_Obj_t * pNode; - Vec_Ptr_t * vNodes; - char FileNameDot[200]; - int i; - - assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); - if ( Abc_NtkIsStrash(pNtk) && Abc_NtkGetChoiceNum(pNtk) ) - { - printf( "Temporarily visualization of AIGs with choice nodes is disabled.\n" ); - return; - } - // convert to logic SOP - if ( Abc_NtkIsLogic(pNtk) ) - Abc_NtkToSop( pNtk, 0 ); - // create the file name - Abc_ShowGetFileName( pNtk->pName, FileNameDot ); - // check that the file can be opened - if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); - return; - } - fclose( pFile ); - - // collect all nodes in the network - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachObj( pNtk, pNode, i ) - Vec_PtrPush( vNodes, pNode ); - // write the DOT file - if ( fSeq ) - Io_WriteDotSeq( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); - else - Io_WriteDotNtk( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); - Vec_PtrFree( vNodes ); - - // visualize the file - Abc_ShowFile( FileNameDot ); -} - - -/**Function************************************************************* - - Synopsis [Shows the given DOT file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ShowFile( char * FileNameDot ) -{ - FILE * pFile; - char * FileGeneric; - char FileNamePs[200]; - char CommandDot[1000]; - char * pDotName; - char * pDotNameWin = "dot.exe"; - char * pDotNameUnix = "dot"; - char * pGsNameWin = "gsview32.exe"; - char * pGsNameUnix = "gv"; - int RetValue; - - // get DOT names from the resource file - if ( Abc_FrameReadFlag("dotwin") ) - pDotNameWin = Abc_FrameReadFlag("dotwin"); - if ( Abc_FrameReadFlag("dotunix") ) - pDotNameUnix = Abc_FrameReadFlag("dotunix"); - -#ifdef WIN32 - pDotName = pDotNameWin; -#else - pDotName = pDotNameUnix; -#endif - - // check if the input DOT file is okay - if ( (pFile = fopen( FileNameDot, "r" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); - return; - } - fclose( pFile ); - - // create the PostScript file name - FileGeneric = Extra_FileNameGeneric( FileNameDot ); - sprintf( FileNamePs, "%s.ps", FileGeneric ); - free( FileGeneric ); - - // generate the PostScript file using DOT - sprintf( CommandDot, "%s -Tps -o %s %s", pDotName, FileNamePs, FileNameDot ); - RetValue = system( CommandDot ); - if ( RetValue == -1 ) - { - fprintf( stdout, "Command \"%s\" did not succeed.\n", CommandDot ); - return; - } - // check that the input PostScript file is okay - if ( (pFile = fopen( FileNamePs, "r" )) == NULL ) - { - fprintf( stdout, "Cannot open intermediate file \"%s\".\n", FileNamePs ); - return; - } - fclose( pFile ); - - - // get GSVIEW names from the resource file - if ( Abc_FrameReadFlag("gsviewwin") ) - pGsNameWin = Abc_FrameReadFlag("gsviewwin"); - if ( Abc_FrameReadFlag("gsviewunix") ) - pGsNameUnix = Abc_FrameReadFlag("gsviewunix"); - - // spawn the viewer -#ifdef WIN32 - _unlink( FileNameDot ); - if ( _spawnl( _P_NOWAIT, pGsNameWin, pGsNameWin, FileNamePs, NULL ) == -1 ) - if ( _spawnl( _P_NOWAIT, "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", - "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", FileNamePs, NULL ) == -1 ) - { - fprintf( stdout, "Cannot find \"%s\".\n", pGsNameWin ); - return; - } -#else - { - char CommandPs[1000]; - unlink( FileNameDot ); - sprintf( CommandPs, "%s %s &", pGsNameUnix, FileNamePs ); - if ( system( CommandPs ) == -1 ) - { - fprintf( stdout, "Cannot execute \"%s\".\n", CommandPs ); - return; - } - } -#endif -} - -/**Function************************************************************* - - Synopsis [Derives the DOT file name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ShowGetFileName( char * pName, char * pBuffer ) -{ - char * pCur; - // creat the file name - sprintf( pBuffer, "%s.dot", pName ); - // get rid of not-alpha-numeric characters - for ( pCur = pBuffer; *pCur; pCur++ ) - if ( !((*pCur >= '0' && *pCur <= '9') || (*pCur >= 'a' && *pCur <= 'z') || - (*pCur >= 'A' && *pCur <= 'Z') || (*pCur == '.')) ) - *pCur = '_'; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcSop.c b/src/base/abc/abcSop.c deleted file mode 100644 index 106901ab..00000000 --- a/src/base/abc/abcSop.c +++ /dev/null @@ -1,1075 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcSop.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Implementation of a simple SOP representation of nodes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcSop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -/* - The SOPs in this package are represented using char * strings. - For example, the SOP of the node: - - .names c d0 d1 MUX - 01- 1 - 1-1 1 - - is the string: "01- 1\n1-1 1\n" where '\n' is a single char. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Registers the cube string with the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName ) -{ - char * pRegName; - if ( pName == NULL ) return NULL; - pRegName = Extra_MmFlexEntryFetch( pMan, strlen(pName) + 1 ); - strcpy( pRegName, pName ); - return pRegName; -} - -/**Function************************************************************* - - Synopsis [Creates the constant 1 cover with the given number of variables and cubes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars ) -{ - char * pSopCover, * pCube; - int i, Length; - - Length = nCubes * (nVars + 3); - pSopCover = Extra_MmFlexEntryFetch( pMan, Length + 1 ); - memset( pSopCover, '-', Length ); - pSopCover[Length] = 0; - - for ( i = 0; i < nCubes; i++ ) - { - pCube = pSopCover + i * (nVars + 3); - pCube[nVars + 0] = ' '; - pCube[nVars + 1] = '1'; - pCube[nVars + 2] = '\n'; - } - return pSopCover; -} - -/**Function************************************************************* - - Synopsis [Creates the constant 1 cover with 0 variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateConst1( Extra_MmFlex_t * pMan ) -{ - return Abc_SopRegister( pMan, " 1\n" ); -} - -/**Function************************************************************* - - Synopsis [Creates the constant 1 cover with 0 variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateConst0( Extra_MmFlex_t * pMan ) -{ - return Abc_SopRegister( pMan, " 0\n" ); -} - -/**Function************************************************************* - - Synopsis [Creates the AND2 cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateAnd2( Extra_MmFlex_t * pMan, int fCompl0, int fCompl1 ) -{ - char Buffer[6]; - Buffer[0] = '1' - fCompl0; - Buffer[1] = '1' - fCompl1; - Buffer[2] = ' '; - Buffer[3] = '1'; - Buffer[4] = '\n'; - Buffer[5] = 0; - return Abc_SopRegister( pMan, Buffer ); -} - -/**Function************************************************************* - - Synopsis [Creates the multi-input AND cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateAnd( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) -{ - char * pSop; - int i; - pSop = Abc_SopStart( pMan, 1, nVars ); - for ( i = 0; i < nVars; i++ ) - pSop[i] = '1' - (pfCompl? pfCompl[i] : 0); - pSop[nVars + 1] = '1'; - return pSop; -} - -/**Function************************************************************* - - Synopsis [Creates the multi-input NAND cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateNand( Extra_MmFlex_t * pMan, int nVars ) -{ - char * pSop; - int i; - pSop = Abc_SopStart( pMan, 1, nVars ); - for ( i = 0; i < nVars; i++ ) - pSop[i] = '1'; - pSop[nVars + 1] = '0'; - return pSop; -} - -/**Function************************************************************* - - Synopsis [Creates the multi-input OR cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateOr( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) -{ - char * pSop; - int i; - pSop = Abc_SopStart( pMan, 1, nVars ); - for ( i = 0; i < nVars; i++ ) - pSop[i] = '0' + (pfCompl? pfCompl[i] : 0); - pSop[nVars + 1] = '0'; - return pSop; -} - -/**Function************************************************************* - - Synopsis [Creates the multi-input OR cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateOrMultiCube( Extra_MmFlex_t * pMan, int nVars, int * pfCompl ) -{ - char * pSop, * pCube; - int i; - pSop = Abc_SopStart( pMan, nVars, nVars ); - i = 0; - Abc_SopForEachCube( pSop, nVars, pCube ) - { - pCube[i] = '1' - (pfCompl? pfCompl[i] : 0); - i++; - } - return pSop; -} - -/**Function************************************************************* - - Synopsis [Creates the multi-input NOR cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateNor( Extra_MmFlex_t * pMan, int nVars ) -{ - char * pSop; - int i; - pSop = Abc_SopStart( pMan, 1, nVars ); - for ( i = 0; i < nVars; i++ ) - pSop[i] = '0'; - return pSop; -} - -/**Function************************************************************* - - Synopsis [Creates the multi-input XOR cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateXor( Extra_MmFlex_t * pMan, int nVars ) -{ - assert( nVars == 2 ); - return Abc_SopRegister(pMan, "01 1\n10 1\n"); -} - -/**Function************************************************************* - - Synopsis [Creates the multi-input XOR cover (special case).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateXorSpecial( Extra_MmFlex_t * pMan, int nVars ) -{ - char * pSop; - pSop = Abc_SopCreateAnd( pMan, nVars, NULL ); - pSop[nVars+1] = 'x'; - assert( pSop[nVars+2] == '\n' ); - return pSop; -} - -/**Function************************************************************* - - Synopsis [Creates the multi-input XNOR cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateNxor( Extra_MmFlex_t * pMan, int nVars ) -{ - assert( nVars == 2 ); - return Abc_SopRegister(pMan, "11 1\n00 1\n"); -} - -/**Function************************************************************* - - Synopsis [Creates the MUX cover.] - - Description [The first input of MUX is the control. The second input - is DATA1. The third input is DATA0.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateMux( Extra_MmFlex_t * pMan ) -{ - return Abc_SopRegister(pMan, "11- 1\n0-1 1\n"); -} - -/**Function************************************************************* - - Synopsis [Creates the inv cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateInv( Extra_MmFlex_t * pMan ) -{ - return Abc_SopRegister(pMan, "0 1\n"); -} - -/**Function************************************************************* - - Synopsis [Creates the buf cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateBuf( Extra_MmFlex_t * pMan ) -{ - return Abc_SopRegister(pMan, "1 1\n"); -} - -/**Function************************************************************* - - Synopsis [Creates the arbitrary cover from the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateFromTruth( Extra_MmFlex_t * pMan, int nVars, unsigned * pTruth ) -{ - char * pSop, * pCube; - int nMints, Counter, i, k; - // count the number of true minterms - Counter = 0; - nMints = (1 << nVars); - for ( i = 0; i < nMints; i++ ) - Counter += ((pTruth[i>>5] & (1 << (i&31))) > 0); - // SOP is not well-defined if the truth table is constant 0 - assert( Counter > 0 ); - if ( Counter == 0 ) - return NULL; - // start the cover - pSop = Abc_SopStart( pMan, Counter, nVars ); - // create true minterms - Counter = 0; - for ( i = 0; i < nMints; i++ ) - if ( (pTruth[i>>5] & (1 << (i&31))) > 0 ) - { - pCube = pSop + Counter * (nVars + 3); - for ( k = 0; k < nVars; k++ ) - pCube[k] = '0' + ((i & (1 << k)) > 0); - Counter++; - } - return pSop; -} - -/**Function************************************************************* - - Synopsis [Creates the cover from the ISOP computed from TT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopCreateFromIsop( Extra_MmFlex_t * pMan, int nVars, Vec_Int_t * vCover ) -{ - char * pSop, * pCube; - int i, k, Entry, Literal; - assert( Vec_IntSize(vCover) > 0 ); - if ( Vec_IntSize(vCover) == 0 ) - return NULL; - // start the cover - pSop = Abc_SopStart( pMan, Vec_IntSize(vCover), nVars ); - // create cubes - Vec_IntForEachEntry( vCover, Entry, i ) - { - pCube = pSop + i * (nVars + 3); - for ( k = 0; k < nVars; k++ ) - { - Literal = 3 & (Entry >> (k << 1)); - if ( Literal == 1 ) - pCube[k] = '0'; - else if ( Literal == 2 ) - pCube[k] = '1'; - else if ( Literal != 0 ) - assert( 0 ); - } - } - return pSop; -} - -/**Function************************************************************* - - Synopsis [Reads the number of cubes in the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_SopGetCubeNum( char * pSop ) -{ - char * pCur; - int nCubes = 0; - if ( pSop == NULL ) - return 0; - for ( pCur = pSop; *pCur; pCur++ ) - nCubes += (*pCur == '\n'); - return nCubes; -} - -/**Function************************************************************* - - Synopsis [Reads the number of SOP literals in the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_SopGetLitNum( char * pSop ) -{ - char * pCur; - int nLits = 0; - if ( pSop == NULL ) - return 0; - for ( pCur = pSop; *pCur; pCur++ ) - { - nLits -= (*pCur == '\n'); - nLits += (*pCur == '0' || *pCur == '1'); - } - return nLits; -} - -/**Function************************************************************* - - Synopsis [Reads the number of variables in the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_SopGetVarNum( char * pSop ) -{ - char * pCur; - for ( pCur = pSop; *pCur != '\n'; pCur++ ); - return pCur - pSop - 2; -} - -/**Function************************************************************* - - Synopsis [Reads the phase of the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_SopGetPhase( char * pSop ) -{ - int nVars = Abc_SopGetVarNum( pSop ); - if ( pSop[nVars+1] == '0' || pSop[nVars+1] == 'n' ) - return 0; - if ( pSop[nVars+1] == '1' || pSop[nVars+1] == 'x' ) - return 1; - assert( 0 ); - return -1; -} - -/**Function************************************************************* - - Synopsis [Returns the i-th literal of the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_SopGetIthCareLit( char * pSop, int i ) -{ - char * pCube; - int nVars; - nVars = Abc_SopGetVarNum( pSop ); - Abc_SopForEachCube( pSop, nVars, pCube ) - if ( pCube[i] != '-' ) - return pCube[i] - '0'; - return -1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_SopComplement( char * pSop ) -{ - char * pCur; - for ( pCur = pSop; *pCur; pCur++ ) - if ( *pCur == '\n' ) - { - if ( *(pCur - 1) == '0' ) - *(pCur - 1) = '1'; - else if ( *(pCur - 1) == '1' ) - *(pCur - 1) = '0'; - else if ( *(pCur - 1) == 'x' ) - *(pCur - 1) = 'n'; - else if ( *(pCur - 1) == 'n' ) - *(pCur - 1) = 'x'; - else - assert( 0 ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_SopIsComplement( char * pSop ) -{ - char * pCur; - for ( pCur = pSop; *pCur; pCur++ ) - if ( *pCur == '\n' ) - return (int)(*(pCur - 1) == '0' || *(pCur - 1) == 'n'); - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Checks if the cover is constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_SopIsConst0( char * pSop ) -{ - return pSop[0] == ' ' && pSop[1] == '0'; -} - -/**Function************************************************************* - - Synopsis [Checks if the cover is constant 1.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_SopIsConst1( char * pSop ) -{ - return pSop[0] == ' ' && pSop[1] == '1'; -} - -/**Function************************************************************* - - Synopsis [Checks if the cover is constant 1.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_SopIsBuf( char * pSop ) -{ - if ( pSop[4] != 0 ) - return 0; - if ( (pSop[0] == '1' && pSop[2] == '1') || (pSop[0] == '0' && pSop[2] == '0') ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Checks if the cover is constant 1.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_SopIsInv( char * pSop ) -{ - if ( pSop[4] != 0 ) - return 0; - if ( (pSop[0] == '0' && pSop[2] == '1') || (pSop[0] == '1' && pSop[2] == '0') ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Checks if the cover is AND with possibly complemented inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_SopIsAndType( char * pSop ) -{ - char * pCur; - if ( Abc_SopGetCubeNum(pSop) != 1 ) - return 0; - for ( pCur = pSop; *pCur != ' '; pCur++ ) - if ( *pCur == '-' ) - return 0; - if ( pCur[1] != '1' ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks if the cover is OR with possibly complemented inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_SopIsOrType( char * pSop ) -{ - char * pCube, * pCur; - int nVars, nLits; - nVars = Abc_SopGetVarNum( pSop ); - if ( nVars != Abc_SopGetCubeNum(pSop) ) - return 0; - Abc_SopForEachCube( pSop, nVars, pCube ) - { - // count the number of literals in the cube - nLits = 0; - for ( pCur = pCube; *pCur != ' '; pCur++ ) - nLits += ( *pCur != '-' ); - if ( nLits != 1 ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_SopIsExorType( char * pSop ) -{ - char * pCur; - for ( pCur = pSop; *pCur; pCur++ ) - if ( *pCur == '\n' ) - return (int)(*(pCur - 1) == 'x' || *(pCur - 1) == 'n'); - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_SopCheck( char * pSop, int nFanins ) -{ - char * pCubes, * pCubesOld; - int fFound0 = 0, fFound1 = 0; - - // check the logic function of the node - for ( pCubes = pSop; *pCubes; pCubes++ ) - { - // get the end of the next cube - for ( pCubesOld = pCubes; *pCubes != ' '; pCubes++ ); - // compare the distance - if ( pCubes - pCubesOld != nFanins ) - { - fprintf( stdout, "Abc_SopCheck: SOP has a mismatch between its cover size (%d) and its fanin number (%d).\n", - pCubes - pCubesOld, nFanins ); - return 0; - } - // check the output values for this cube - pCubes++; - if ( *pCubes == '0' ) - fFound0 = 1; - else if ( *pCubes == '1' ) - fFound1 = 1; - else if ( *pCubes != 'x' && *pCubes != 'n' ) - { - fprintf( stdout, "Abc_SopCheck: SOP has a strange character (%c) in the output part of its cube.\n", *pCubes ); - return 0; - } - // check the last symbol (new line) - pCubes++; - if ( *pCubes != '\n' ) - { - fprintf( stdout, "Abc_SopCheck: SOP has a cube without new line in the end.\n" ); - return 0; - } - } - if ( fFound0 && fFound1 ) - { - fprintf( stdout, "Abc_SopCheck: SOP has cubes in both phases.\n" ); - return 0; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Derives SOP from the truth table representation.] - - Description [Truth table is expected to be in the hexadecimal notation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopFromTruthBin( char * pTruth ) -{ - char * pSopCover, * pCube; - int nTruthSize, nVars, Digit, Length, Mint, i, b; - Vec_Int_t * vMints; - - // get the number of variables - nTruthSize = strlen(pTruth); - nVars = Extra_Base2Log( nTruthSize ); - if ( nTruthSize != (1 << (nVars)) ) - { - printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars ); - return NULL; - } - - // collect the on-set minterms - vMints = Vec_IntAlloc( 100 ); - for ( i = 0; i < nTruthSize; i++ ) - { - if ( pTruth[i] >= '0' && pTruth[i] <= '1' ) - Digit = pTruth[i] - '0'; - else - { - printf( "String %s does not look like a binary representation of the truth table.\n", pTruth ); - return NULL; - } - if ( Digit == 1 ) - Vec_IntPush( vMints, nTruthSize - 1 - i ); - } - if ( Vec_IntSize( vMints ) == 0 || Vec_IntSize( vMints ) == nTruthSize ) - { - Vec_IntFree( vMints ); - printf( "Cannot create constant function.\n" ); - return NULL; - } - - // create the SOP representation of the minterms - Length = Vec_IntSize(vMints) * (nVars + 3); - pSopCover = ALLOC( char, Length + 1 ); - pSopCover[Length] = 0; - Vec_IntForEachEntry( vMints, Mint, i ) - { - pCube = pSopCover + i * (nVars + 3); - for ( b = 0; b < nVars; b++ ) - if ( Mint & (1 << (nVars-1-b)) ) -// if ( Mint & (1 << b) ) - pCube[b] = '1'; - else - pCube[b] = '0'; - pCube[nVars + 0] = ' '; - pCube[nVars + 1] = '1'; - pCube[nVars + 2] = '\n'; - } - Vec_IntFree( vMints ); - return pSopCover; -} - -/**Function************************************************************* - - Synopsis [Derives SOP from the truth table representation.] - - Description [Truth table is expected to be in the hexadecimal notation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopFromTruthHex( char * pTruth ) -{ - char * pSopCover, * pCube; - int nTruthSize, nVars, Digit, Length, Mint, i, b; - Vec_Int_t * vMints; - - // get the number of variables - nTruthSize = strlen(pTruth); - nVars = Extra_Base2Log( nTruthSize ) + 2; - if ( nTruthSize != (1 << (nVars-2)) ) - { - printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars ); - return NULL; - } - - // collect the on-set minterms - vMints = Vec_IntAlloc( 100 ); - for ( i = 0; i < nTruthSize; i++ ) - { - if ( pTruth[i] >= '0' && pTruth[i] <= '9' ) - Digit = pTruth[i] - '0'; - else if ( pTruth[i] >= 'a' && pTruth[i] <= 'f' ) - Digit = 10 + pTruth[i] - 'a'; - else if ( pTruth[i] >= 'A' && pTruth[i] <= 'F' ) - Digit = 10 + pTruth[i] - 'A'; - else - { - printf( "String %s does not look like a hexadecimal representation of the truth table.\n", pTruth ); - return NULL; - } - for ( b = 0; b < 4; b++ ) - if ( Digit & (1 << b) ) - Vec_IntPush( vMints, 4*(nTruthSize-1-i)+b ); - } - - // create the SOP representation of the minterms - Length = Vec_IntSize(vMints) * (nVars + 3); - pSopCover = ALLOC( char, Length + 1 ); - pSopCover[Length] = 0; - Vec_IntForEachEntry( vMints, Mint, i ) - { - pCube = pSopCover + i * (nVars + 3); - for ( b = 0; b < nVars; b++ ) -// if ( Mint & (1 << (nVars-1-b)) ) - if ( Mint & (1 << b) ) - pCube[b] = '1'; - else - pCube[b] = '0'; - pCube[nVars + 0] = ' '; - pCube[nVars + 1] = '1'; - pCube[nVars + 2] = '\n'; - } - Vec_IntFree( vMints ); - return pSopCover; -} - -/**Function************************************************************* - - Synopsis [Creates one encoder node.] - - Description [Produces MV-SOP for BLIF-MV representation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopEncoderPos( Extra_MmFlex_t * pMan, int iValue, int nValues ) -{ - char Buffer[32]; - assert( iValue < nValues ); - sprintf( Buffer, "d0\n%d 1\n", iValue ); - return Abc_SopRegister( pMan, Buffer ); -} - -/**Function************************************************************* - - Synopsis [Creates one encoder node.] - - Description [Produces MV-SOP for BLIF-MV representation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopEncoderLog( Extra_MmFlex_t * pMan, int iBit, int nValues ) -{ - char * pResult; - Vec_Str_t * vSop; - int v, Counter, fFirst = 1, nBits = Extra_Base2Log(nValues); - assert( iBit < nBits ); - // count the number of literals - Counter = 0; - for ( v = 0; v < nValues; v++ ) - Counter += ( (v & (1 << iBit)) > 0 ); - // create the cover - vSop = Vec_StrAlloc( 100 ); - Vec_StrPrintStr( vSop, "d0\n" ); - if ( Counter > 1 ) - Vec_StrPrintStr( vSop, "(" ); - for ( v = 0; v < nValues; v++ ) - if ( v & (1 << iBit) ) - { - if ( fFirst ) - fFirst = 0; - else - Vec_StrPush( vSop, ',' ); - Vec_StrPrintNum( vSop, v ); - } - if ( Counter > 1 ) - Vec_StrPrintStr( vSop, ")" ); - Vec_StrPrintStr( vSop, " 1\n" ); - Vec_StrPush( vSop, 0 ); - pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); - Vec_StrFree( vSop ); - return pResult; -} - -/**Function************************************************************* - - Synopsis [Creates the decoder node.] - - Description [Produces MV-SOP for BLIF-MV representation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopDecoderPos( Extra_MmFlex_t * pMan, int nValues ) -{ - char * pResult; - Vec_Str_t * vSop; - int i, k; - assert( nValues > 1 ); - vSop = Vec_StrAlloc( 100 ); - for ( i = 0; i < nValues; i++ ) - { - for ( k = 0; k < nValues; k++ ) - { - if ( k == i ) - Vec_StrPrintStr( vSop, "1 " ); - else - Vec_StrPrintStr( vSop, "- " ); - } - Vec_StrPrintNum( vSop, i ); - Vec_StrPush( vSop, '\n' ); - } - Vec_StrPush( vSop, 0 ); - pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); - Vec_StrFree( vSop ); - return pResult; -} - -/**Function************************************************************* - - Synopsis [Creates the decover node.] - - Description [Produces MV-SOP for BLIF-MV representation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopDecoderLog( Extra_MmFlex_t * pMan, int nValues ) -{ - char * pResult; - Vec_Str_t * vSop; - int i, b, nBits = Extra_Base2Log(nValues); - assert( nValues > 1 && nValues <= (1< 0) ); - Vec_StrPush( vSop, ' ' ); - } - Vec_StrPrintNum( vSop, i ); - Vec_StrPush( vSop, '\n' ); - } - Vec_StrPush( vSop, 0 ); - pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); - Vec_StrFree( vSop ); - return pResult; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abcUtil.c b/src/base/abc/abcUtil.c deleted file mode 100644 index b4a97223..00000000 --- a/src/base/abc/abcUtil.c +++ /dev/null @@ -1,1764 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Various utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "main.h" -#include "mio.h" -#include "dec.h" -//#include "seq.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Frees one attribute manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ) -{ - void * pUserMan; - Vec_Att_t * pAttrMan; - pAttrMan = Vec_PtrEntry( pNtk->vAttrs, Attr ); - Vec_PtrWriteEntry( pNtk->vAttrs, Attr, NULL ); - pUserMan = Vec_AttFree( pAttrMan, fFreeMan ); - return pUserMan; -} - -/**Function************************************************************* - - Synopsis [Increments the current traversal ID of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - if ( pNtk->nTravIds >= (1<<30)-1 ) - { - pNtk->nTravIds = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->TravId = 0; - } - pNtk->nTravIds++; -} - -/**Function************************************************************* - - Synopsis [Order CI/COs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj, * pTerm; - int i, k; - Vec_PtrClear( pNtk->vCis ); - Vec_PtrClear( pNtk->vCos ); - Abc_NtkForEachPi( pNtk, pObj, i ) - Vec_PtrPush( pNtk->vCis, pObj ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Vec_PtrPush( pNtk->vCos, pObj ); - Abc_NtkForEachAssert( pNtk, pObj, i ) - Vec_PtrPush( pNtk->vCos, pObj ); - Abc_NtkForEachBox( pNtk, pObj, i ) - { - if ( Abc_ObjIsLatch(pObj) ) - continue; - Abc_ObjForEachFanin( pObj, pTerm, k ) - Vec_PtrPush( pNtk->vCos, pTerm ); - Abc_ObjForEachFanout( pObj, pTerm, k ) - Vec_PtrPush( pNtk->vCis, pTerm ); - } - Abc_NtkForEachBox( pNtk, pObj, i ) - { - if ( !Abc_ObjIsLatch(pObj) ) - continue; - Abc_ObjForEachFanin( pObj, pTerm, k ) - Vec_PtrPush( pNtk->vCos, pTerm ); - Abc_ObjForEachFanout( pObj, pTerm, k ) - Vec_PtrPush( pNtk->vCis, pTerm ); - } -} - -/**Function************************************************************* - - Synopsis [Reads the number of cubes of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, nCubes = 0; - assert( Abc_NtkHasSop(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - if ( Abc_NodeIsConst(pNode) ) - continue; - assert( pNode->pData ); - nCubes += Abc_SopGetCubeNum( pNode->pData ); - } - return nCubes; -} - -/**Function************************************************************* - - Synopsis [Reads the number of cubes of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, nCubes, nCubePairs = 0; - assert( Abc_NtkHasSop(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - if ( Abc_NodeIsConst(pNode) ) - continue; - assert( pNode->pData ); - nCubes = Abc_SopGetCubeNum( pNode->pData ); - nCubePairs += nCubes * (nCubes - 1) / 2; - } - return nCubePairs; -} - -/**Function************************************************************* - - Synopsis [Reads the number of literals in the SOPs of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, nLits = 0; - assert( Abc_NtkHasSop(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - assert( pNode->pData ); - nLits += Abc_SopGetLitNum( pNode->pData ); - } - return nLits; -} - -/**Function************************************************************* - - Synopsis [Counts the number of literals in the factored forms.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk ) -{ - Dec_Graph_t * pFactor; - Abc_Obj_t * pNode; - int nNodes, i; - assert( Abc_NtkHasSop(pNtk) ); - nNodes = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - { - if ( Abc_NodeIsConst(pNode) ) - continue; - pFactor = Dec_Factor( pNode->pData ); - nNodes += 1 + Dec_GraphNodeNum(pFactor); - Dec_GraphFree( pFactor ); - } - return nNodes; -} - -/**Function************************************************************* - - Synopsis [Reads the number of BDD nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, nNodes = 0; - assert( Abc_NtkIsBddLogic(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - assert( pNode->pData ); - if ( Abc_ObjFaninNum(pNode) < 2 ) - continue; - nNodes += pNode->pData? -1 + Cudd_DagSize( pNode->pData ) : 0; - } - return nNodes; -} - -/**Function************************************************************* - - Synopsis [Reads the number of BDD nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, nNodes = 0; - assert( Abc_NtkIsAigLogic(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - assert( pNode->pData ); - if ( Abc_ObjFaninNum(pNode) < 2 ) - continue; -//printf( "%d ", Hop_DagSize( pNode->pData ) ); - nNodes += pNode->pData? Hop_DagSize( pNode->pData ) : 0; - } - return nNodes; -} - -/**Function************************************************************* - - Synopsis [Reads the number of BDD nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - DdNode * bCover, * zCover, * bFunc; - DdManager * dd = pNtk->pManFunc; - int i, nClauses = 0; - assert( Abc_NtkIsBddLogic(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - assert( pNode->pData ); - bFunc = pNode->pData; - - bCover = Cudd_zddIsop( dd, bFunc, bFunc, &zCover ); - Cudd_Ref( bCover ); - Cudd_Ref( zCover ); - nClauses += Abc_CountZddCubes( dd, zCover ); - Cudd_RecursiveDeref( dd, bCover ); - Cudd_RecursiveDerefZdd( dd, zCover ); - - bCover = Cudd_zddIsop( dd, Cudd_Not(bFunc), Cudd_Not(bFunc), &zCover ); - Cudd_Ref( bCover ); - Cudd_Ref( zCover ); - nClauses += Abc_CountZddCubes( dd, zCover ); - Cudd_RecursiveDeref( dd, bCover ); - Cudd_RecursiveDerefZdd( dd, zCover ); - } - return nClauses; -} - -/**Function************************************************************* - - Synopsis [Computes the area of the mapped circuit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - double TotalArea; - int i; - assert( Abc_NtkHasMapping(pNtk) ); - TotalArea = 0.0; - Abc_NtkForEachNode( pNtk, pNode, i ) - { -// assert( pNode->pData ); - if ( pNode->pData == NULL ) - { - printf( "Node without mapping is encountered.\n" ); - continue; - } - TotalArea += Mio_GateReadArea( pNode->pData ); - } - return TotalArea; -} - -/**Function************************************************************* - - Synopsis [Counts the number of exors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, Counter = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - Counter += pNode->fExor; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of exors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, Counter = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - Counter += Abc_NodeIsMuxType(pNode); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if it is an AIG with choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, Counter; - if ( !Abc_NtkIsStrash(pNtk) ) - return 0; - Counter = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - Counter += Abc_AigNodeIsChoice( pNode ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Reads the maximum number of fanins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, nFaninsMax = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - { - if ( nFaninsMax < Abc_ObjFaninNum(pNode) ) - nFaninsMax = Abc_ObjFaninNum(pNode); - } - return nFaninsMax; -} - -/**Function************************************************************* - - Synopsis [Reads the total number of all fanins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, nFanins = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - nFanins += Abc_ObjFaninNum(pNode); - return nFanins; -} - -/**Function************************************************************* - - Synopsis [Cleans the copy field of all objects.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pCopy = NULL; -} - -/**Function************************************************************* - - Synopsis [Cleans the copy field of all objects.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCleanData( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pData = NULL; -} - -/**Function************************************************************* - - Synopsis [Cleans the copy field of all objects.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCleanEquiv( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pEquiv = NULL; -} - -/**Function************************************************************* - - Synopsis [Counts the number of nodes having non-trivial copies.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCountCopy( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i, Counter = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( Abc_ObjIsNode(pObj) ) - Counter += (pObj->pCopy != NULL); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Saves copy field of the objects.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vCopies; - Abc_Obj_t * pObj; - int i; - vCopies = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachObj( pNtk, pObj, i ) - Vec_PtrWriteEntry( vCopies, i, pObj->pCopy ); - return vCopies; -} - -/**Function************************************************************* - - Synopsis [Loads copy field of the objects.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pCopy = Vec_PtrEntry( vCopies, i ); -} - -/**Function************************************************************* - - Synopsis [Cleans the copy field of all objects.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCleanNext( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pNext = NULL; -} - -/**Function************************************************************* - - Synopsis [Cleans the copy field of all objects.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Checks if the internal node has CO fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanout; - int i; - Abc_ObjForEachFanout( pNode, pFanout, i ) - if ( Abc_ObjIsCo(pFanout) ) - return pFanout; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Checks if the internal node has CO fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanout; - int i; - Abc_ObjForEachFanout( pNode, pFanout, i ) - if ( !Abc_ObjIsCo(pFanout) ) - return pFanout; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Checks if the internal node has CO drivers with the same name.] - - Description [Checks if the internal node can borrow its name from CO fanouts. - This is possible if all COs with non-complemented fanin edge pointing to this - node have the same name.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanout, * pFanoutCo; - int i; - pFanoutCo = NULL; - Abc_ObjForEachFanout( pNode, pFanout, i ) - { - if ( !Abc_ObjIsCo(pFanout) ) - continue; - if ( Abc_ObjFaninC0(pFanout) ) - continue; - if ( pFanoutCo == NULL ) - { - assert( Abc_ObjFaninNum(pFanout) == 1 ); - assert( Abc_ObjFanin0(pFanout) == pNode ); - pFanoutCo = pFanout; - continue; - } - if ( strcmp( Abc_ObjName(pFanoutCo), Abc_ObjName(pFanout) ) ) // they have diff names - return NULL; - } - return pFanoutCo; -} - -/**Function************************************************************* - - Synopsis [Fixes the CO driver problem.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFixCoDriverProblem( Abc_Obj_t * pDriver, Abc_Obj_t * pNodeCo, int fDuplicate ) -{ - Abc_Ntk_t * pNtk = pDriver->pNtk; - Abc_Obj_t * pDriverNew, * pFanin; - int k; - if ( fDuplicate && !Abc_ObjIsCi(pDriver) ) - { - pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); - Abc_ObjForEachFanin( pDriver, pFanin, k ) - Abc_ObjAddFanin( pDriverNew, pFanin ); - if ( Abc_ObjFaninC0(pNodeCo) ) - { - // change polarity of the duplicated driver - Abc_NodeComplement( pDriverNew ); - Abc_ObjXorFaninC( pNodeCo, 0 ); - } - } - else - { - // add inverters and buffers when necessary - if ( Abc_ObjFaninC0(pNodeCo) ) - { - pDriverNew = Abc_NtkCreateNodeInv( pNtk, pDriver ); - Abc_ObjXorFaninC( pNodeCo, 0 ); - } - else - pDriverNew = Abc_NtkCreateNodeBuf( pNtk, pDriver ); - } - // update the fanin of the PO node - Abc_ObjPatchFanin( pNodeCo, pDriver, pDriverNew ); - assert( Abc_ObjFanoutNum(pDriverNew) == 1 ); - // remove the old driver if it dangles - // (this happens when the duplicated driver had only one complemented fanout) - if ( Abc_ObjFanoutNum(pDriver) == 0 ) - Abc_NtkDeleteObj( pDriver ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if COs of a logic network are simple.] - - Description [The COs of a logic network are simple under three conditions: - (1) The edge from CO to its driver is not complemented. - (2) If CI is a driver of a CO, they have the same name.] - (3) If two COs share the same driver, they have the same name.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode, * pDriver; - int i; - assert( Abc_NtkIsLogic(pNtk) ); - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - // if the driver is complemented, this is an error - pDriver = Abc_ObjFanin0(pNode); - if ( Abc_ObjFaninC0(pNode) ) - return 0; - // if the driver is a CI and has different name, this is an error - if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) - return 0; - // if the driver is visited for the first time, remember the CO name - if ( !Abc_NodeIsTravIdCurrent(pDriver) ) - { - pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); - Abc_NodeSetTravIdCurrent(pDriver); - continue; - } - // the driver has second CO - if they have different name, this is an error - if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Transforms the network to have simple COs.] - - Description [The COs of a logic network are simple under three conditions: - (1) The edge from CO to its driver is not complemented. - (2) If CI is a driver of a CO, they have the same name.] - (3) If two COs share the same driver, they have the same name. - In some cases, such as FPGA mapping, we prevent the increase in delay - by duplicating the driver nodes, rather than adding invs/bufs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDuplicate ) -{ - Abc_Obj_t * pNode, * pDriver; - int i, nDupGates = 0; - assert( Abc_NtkIsLogic(pNtk) ); - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - // if the driver is complemented, this is an error - pDriver = Abc_ObjFanin0(pNode); - if ( Abc_ObjFaninC0(pNode) ) - { - Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); - nDupGates++; - continue; - } - // if the driver is a CI and has different name, this is an error - if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) - { - Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); - nDupGates++; - continue; - } - // if the driver is visited for the first time, remember the CO name - if ( !Abc_NodeIsTravIdCurrent(pDriver) ) - { - pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); - Abc_NodeSetTravIdCurrent(pDriver); - continue; - } - // the driver has second CO - if they have different name, this is an error - if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names - { - Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); - nDupGates++; - continue; - } - } - assert( Abc_NtkLogicHasSimpleCos(pNtk) ); - return nDupGates; -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pNode1, * pNode2; - int i; - if ( Vec_PtrPushUnique(p, pNode) ) - return; - // find the p of the node - for ( i = p->nSize-1; i > 0; i-- ) - { - pNode1 = p->pArray[i ]; - pNode2 = p->pArray[i-1]; - if ( Abc_ObjRegular(pNode1)->Level <= Abc_ObjRegular(pNode2)->Level ) - break; - p->pArray[i ] = pNode2; - p->pArray[i-1] = pNode1; - } -} - - - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of EXOR/NEXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NodeIsExorType( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pNode0, * pNode1; - // check that the node is regular - assert( !Abc_ObjIsComplement(pNode) ); - // if the node is not AND, this is not EXOR - if ( !Abc_AigNodeIsAnd(pNode) ) - return 0; - // if the children are not complemented, this is not EXOR - if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) ) - return 0; - // get children - pNode0 = Abc_ObjFanin0(pNode); - pNode1 = Abc_ObjFanin1(pNode); - // if the children are not ANDs, this is not EXOR - if ( Abc_ObjFaninNum(pNode0) != 2 || Abc_ObjFaninNum(pNode1) != 2 ) - return 0; - // otherwise, the node is EXOR iff its grand-children are the same - return (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) || Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1)) && - (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) || Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1)); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NodeIsMuxType( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pNode0, * pNode1; - // check that the node is regular - assert( !Abc_ObjIsComplement(pNode) ); - // if the node is not AND, this is not MUX - if ( !Abc_AigNodeIsAnd(pNode) ) - return 0; - // if the children are not complemented, this is not MUX - if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) ) - return 0; - // get children - pNode0 = Abc_ObjFanin0(pNode); - pNode1 = Abc_ObjFanin1(pNode); - // if the children are not ANDs, this is not MUX - if ( Abc_ObjFaninNum(pNode0) != 2 || Abc_ObjFaninNum(pNode1) != 2 ) - return 0; - // otherwise the node is MUX iff it has a pair of equal grandchildren - return (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1))) || - (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1))) || - (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1))) || - (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1))); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the control type of the MUX.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NodeIsMuxControlType( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pNode0, * pNode1; - // check that the node is regular - assert( !Abc_ObjIsComplement(pNode) ); - // skip the node that do not have two fanouts - if ( Abc_ObjFanoutNum(pNode) != 2 ) - return 0; - // get the fanouts - pNode0 = Abc_ObjFanout( pNode, 0 ); - pNode1 = Abc_ObjFanout( pNode, 1 ); - // if they have more than one fanout, we are not interested - if ( Abc_ObjFanoutNum(pNode0) != 1 || Abc_ObjFanoutNum(pNode1) != 1 ) - return 0; - // if the fanouts have the same fanout, this is MUX or EXOR (or a redundant gate (CA)(CB)) - return Abc_ObjFanout0(pNode0) == Abc_ObjFanout0(pNode1); -} - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are control and data inputs of a MUX.] - - Description [If the node is a MUX, returns the control variable C. - Assigns nodes T and E to be the then and else variables of the MUX. - Node C is never complemented. Nodes T and E can be complemented. - This function also recognizes EXOR/NEXOR gates as MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ) -{ - Abc_Obj_t * pNode0, * pNode1; - assert( !Abc_ObjIsComplement(pNode) ); - assert( Abc_NodeIsMuxType(pNode) ); - // get children - pNode0 = Abc_ObjFanin0(pNode); - pNode1 = Abc_ObjFanin1(pNode); - // find the control variable -// if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) - if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Abc_ObjFaninC0(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); - return Abc_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); - return Abc_ObjChild0(pNode0);//pNode1->p1; - } - } -// else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) - else if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p1) ) - if ( Abc_ObjFaninC0(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); - return Abc_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); - *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); - return Abc_ObjChild0(pNode0);//pNode1->p1; - } - } -// else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) - else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Abc_ObjFaninC1(pNode0) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); - *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); - return Abc_ObjChild0(pNode1);//pNode2->p1; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); - return Abc_ObjChild1(pNode0);//pNode1->p2; - } - } -// else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) - else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1)) ) - { -// if ( Fraig_IsComplement(pNode1->p2) ) - if ( Abc_ObjFaninC1(pNode0) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); - *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); - return Abc_ObjChild1(pNode1);//pNode2->p2; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); - *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); - return Abc_ObjChild1(pNode0);//pNode1->p2; - } - } - assert( 0 ); // this is not MUX - return NULL; -} - -/**Function************************************************************* - - Synopsis [Prepares two network for a two-argument command similar to "verify".] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, - Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2 ) -{ - int fCheck = 1; - FILE * pFile; - Abc_Ntk_t * pNtk1, * pNtk2; - int util_optind = 0; - - *pfDelete1 = 0; - *pfDelete2 = 0; - if ( argc == util_optind ) - { // use the spec - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty current network.\n" ); - return 0; - } - if ( pNtk->pSpec == NULL ) - { - fprintf( pErr, "The external spec is not given.\n" ); - return 0; - } - pFile = fopen( pNtk->pSpec, "r" ); - if ( pFile == NULL ) - { - fprintf( pErr, "Cannot open the external spec file \"%s\".\n", pNtk->pSpec ); - return 0; - } - else - fclose( pFile ); - pNtk1 = pNtk; - pNtk2 = Io_Read( pNtk->pSpec, Io_ReadFileType(pNtk->pSpec), fCheck ); - if ( pNtk2 == NULL ) - return 0; - *pfDelete2 = 1; - } - else if ( argc == util_optind + 1 ) - { - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty current network.\n" ); - return 0; - } - pNtk1 = pNtk; - pNtk2 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck ); - if ( pNtk2 == NULL ) - return 0; - *pfDelete2 = 1; - } - else if ( argc == util_optind + 2 ) - { - pNtk1 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck ); - if ( pNtk1 == NULL ) - return 0; - pNtk2 = Io_Read( argv[util_optind+1], Io_ReadFileType(argv[util_optind+1]), fCheck ); - if ( pNtk2 == NULL ) - { - Abc_NtkDelete( pNtk1 ); - return 0; - } - *pfDelete1 = 1; - *pfDelete2 = 1; - } - else - { - fprintf( pErr, "Wrong number of arguments.\n" ); - return 0; - } - *ppNtk1 = pNtk1; - *ppNtk2 = pNtk2; - return 1; -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if it is an AIG with choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanin; - int i; - Vec_PtrClear(vNodes); - Abc_ObjForEachFanin( pNode, pFanin, i ) - Vec_PtrPush( vNodes, pFanin ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if it is an AIG with choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanout; - int i; - Vec_PtrClear(vNodes); - Abc_ObjForEachFanout( pNode, pFanout, i ) - Vec_PtrPush( vNodes, pFanout ); -} - -/**Function************************************************************* - - Synopsis [Collects all latches in the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vLatches; - Abc_Obj_t * pObj; - int i; - vLatches = Vec_PtrAlloc( 10 ); - Abc_NtkForEachObj( pNtk, pObj, i ) - Vec_PtrPush( vLatches, pObj ); - return vLatches; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in increasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) -{ - int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level; - if ( Diff < 0 ) - return -1; - if ( Diff > 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) -{ - int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level; - if ( Diff > 0 ) - return -1; - if ( Diff < 0 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Creates the array of fanout counters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ) -{ - Vec_Int_t * vFanNums; - Abc_Obj_t * pObj; - int i; - vFanNums = Vec_IntAlloc( 0 ); - Vec_IntFill( vFanNums, Abc_NtkObjNumMax(pNtk), -1 ); - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) ) - Vec_IntWriteEntry( vFanNums, i, Abc_ObjFanoutNum(pObj) ); - return vFanNums; -} - -/**Function************************************************************* - - Synopsis [Collects all objects into one array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode; - int i; - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachObj( pNtk, pNode, i ) - Vec_PtrPush( vNodes, pNode ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Returns the array of CI IDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk ) -{ - Vec_Int_t * vCiIds; - Abc_Obj_t * pObj; - int i; - vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) ); - Abc_NtkForEachCi( pNtk, pObj, i ) - Vec_IntPush( vCiIds, pObj->Id ); - return vCiIds; -} - -/**Function************************************************************* - - Synopsis [Puts the nodes into the DFS order and reassign their IDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkReassignIds( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Vec_Ptr_t * vObjsNew; - Abc_Obj_t * pNode, * pTemp, * pConst1; - int i, k; - assert( Abc_NtkIsStrash(pNtk) ); -//printf( "Total = %d. Current = %d.\n", Abc_NtkObjNumMax(pNtk), Abc_NtkObjNum(pNtk) ); - // start the array of objects with new IDs - vObjsNew = Vec_PtrAlloc( pNtk->nObjs ); - // put constant node first - pConst1 = Abc_AigConst1(pNtk); - assert( pConst1->Id == 0 ); - Vec_PtrPush( vObjsNew, pConst1 ); - // put PI nodes next - Abc_NtkForEachPi( pNtk, pNode, i ) - { - pNode->Id = Vec_PtrSize( vObjsNew ); - Vec_PtrPush( vObjsNew, pNode ); - } - // put PO nodes next - Abc_NtkForEachPo( pNtk, pNode, i ) - { - pNode->Id = Vec_PtrSize( vObjsNew ); - Vec_PtrPush( vObjsNew, pNode ); - } - // put assert nodes next - Abc_NtkForEachAssert( pNtk, pNode, i ) - { - pNode->Id = Vec_PtrSize( vObjsNew ); - Vec_PtrPush( vObjsNew, pNode ); - } - // put latches and their inputs/outputs next - Abc_NtkForEachBox( pNtk, pNode, i ) - { - pNode->Id = Vec_PtrSize( vObjsNew ); - Vec_PtrPush( vObjsNew, pNode ); - Abc_ObjForEachFanin( pNode, pTemp, k ) - { - pTemp->Id = Vec_PtrSize( vObjsNew ); - Vec_PtrPush( vObjsNew, pTemp ); - } - Abc_ObjForEachFanout( pNode, pTemp, k ) - { - pTemp->Id = Vec_PtrSize( vObjsNew ); - Vec_PtrPush( vObjsNew, pTemp ); - } - } - // finally, internal nodes in the DFS order - vNodes = Abc_AigDfs( pNtk, 1, 0 ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( pNode == pConst1 ) - continue; - pNode->Id = Vec_PtrSize( vObjsNew ); - Vec_PtrPush( vObjsNew, pNode ); - } - Vec_PtrFree( vNodes ); - assert( Vec_PtrSize(vObjsNew) == pNtk->nObjs ); - - // update the fanin/fanout arrays - Abc_NtkForEachObj( pNtk, pNode, i ) - { - Abc_ObjForEachFanin( pNode, pTemp, k ) - pNode->vFanins.pArray[k] = pTemp->Id; - Abc_ObjForEachFanout( pNode, pTemp, k ) - pNode->vFanouts.pArray[k] = pTemp->Id; - } - - // replace the array of objs - Vec_PtrFree( pNtk->vObjs ); - pNtk->vObjs = vObjsNew; - - // rehash the AIG - Abc_AigRehash( pNtk->pManFunc ); - - // update the name manager!!! -} - -/**Function************************************************************* - - Synopsis [Detect cases when non-trivial FF matching is possible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDetectMatching( Abc_Ntk_t * pNtk ) -{ -/* - Abc_Obj_t * pLatch, * pFanin; - int i, nTFFs, nJKFFs; - nTFFs = nJKFFs = 0; - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - pFanin = Abc_ObjFanin0(pLatch); - if ( Abc_ObjFaninNum(pFanin) != 2 ) - continue; - if ( Abc_NodeIsExorType(pLatch) ) - { - if ( Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch || - Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch ) - nTFFs++; - } - if ( Abc_ObjFaninNum( Abc_ObjFanin0(pFanin) ) != 2 || - Abc_ObjFaninNum( Abc_ObjFanin1(pFanin) ) != 2 ) - continue; - - if ( (Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch || - Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch) && - (Abc_ObjFanin0(Abc_ObjFanin1(pFanin)) == pLatch || - Abc_ObjFanin1(Abc_ObjFanin1(pFanin)) == pLatch) ) - { - nJKFFs++; - } - } - printf( "D = %6d. T = %6d. JK = %6d. (%6.2f %%)\n", - Abc_NtkLatchNum(pNtk), nTFFs, nJKFFs, 100.0 * nJKFFs / Abc_NtkLatchNum(pNtk) ); -*/ -} - - -/**Function************************************************************* - - Synopsis [Compares the pointers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ObjPointerCompare( void ** pp1, void ** pp2 ) -{ - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Adjusts the copy pointers.] - - Description [This procedure assumes that the network was transformed - into another network, which was in turn transformed into yet another - network. It makes the pCopy pointers of the original network point to - the objects of the yet another network.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_ObjIsNet(pObj) ) - pObj->pCopy = pObj->pCopy? Abc_ObjCopyCond(pObj->pCopy) : NULL; -} - - -/**Function************************************************************* - - Synopsis [Increaments the cut counter.] - - Description [Returns 1 if it becomes equal to the ref counter.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Abc_ObjCrossCutInc( Abc_Obj_t * pObj ) -{ -// pObj->pCopy = (void *)(((int)pObj->pCopy)++); - int Value = (int)pObj->pCopy; - pObj->pCopy = (void *)(Value + 1); - return (int)pObj->pCopy == Abc_ObjFanoutNum(pObj); -} - -/**Function************************************************************* - - Synopsis [Computes cross-cut of the circuit.] - - Description [Returns 1 if it is the last visit to the node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCrossCut_rec( Abc_Obj_t * pObj, int * pnCutSize, int * pnCutSizeMax ) -{ - Abc_Obj_t * pFanin; - int i, nDecrem = 0; - int fReverse = 0; - if ( Abc_ObjIsCi(pObj) ) - return 0; - // if visited, increment visit counter - if ( Abc_NodeIsTravIdCurrent( pObj ) ) - return Abc_ObjCrossCutInc( pObj ); - Abc_NodeSetTravIdCurrent( pObj ); - // visit the fanins - if ( !Abc_ObjIsCi(pObj) ) - { - if ( fReverse ) - { - Abc_ObjForEachFanin( pObj, pFanin, i ) - { - pFanin = Abc_ObjFanin( pObj, Abc_ObjFaninNum(pObj) - 1 - i ); - nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax ); - } - } - else - { - Abc_ObjForEachFanin( pObj, pFanin, i ) - nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax ); - } - } - // count the node - (*pnCutSize)++; - if ( *pnCutSizeMax < *pnCutSize ) - *pnCutSizeMax = *pnCutSize; - (*pnCutSize) -= nDecrem; - return Abc_ObjCrossCutInc( pObj ); -} - -/**Function************************************************************* - - Synopsis [Computes cross-cut of the circuit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCrossCut( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int nCutSize = 0, nCutSizeMax = 0; - int i; - Abc_NtkCleanCopy( pNtk ); - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - Abc_NtkCrossCut_rec( pObj, &nCutSize, &nCutSizeMax ); - nCutSize--; - } - assert( nCutSize == 0 ); - printf( "Max cross cut size = %6d. Ratio = %6.2f %%\n", nCutSizeMax, 100.0 * nCutSizeMax/Abc_NtkObjNum(pNtk) ); - return nCutSizeMax; -} - - -/**Function************************************************************* - - Synopsis [Prints all 3-var functions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrint256() -{ - FILE * pFile; - unsigned i; - pFile = fopen( "4varfs.txt", "w" ); - for ( i = 1; i < (1<<16)-1; i++ ) - { - fprintf( pFile, "read_truth " ); - Extra_PrintBinary( pFile, &i, 16 ); - fprintf( pFile, "; clp; st; w 1.blif; map; cec 1.blif\n" ); - } - fclose( pFile ); -} - - -static int * pSupps; - -/**Function************************************************************* - - Synopsis [Compares the supergates by their level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCompareConesCompare( int * pNum1, int * pNum2 ) -{ - if ( pSupps[*pNum1] > pSupps[*pNum2] ) - return -1; - if ( pSupps[*pNum1] < pSupps[*pNum2] ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Analyze choice node support.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCompareCones( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vSupp, * vNodes, * vReverse; - Abc_Obj_t * pObj, * pTemp; - int Iter, i, k, Counter, CounterCos, CounterCosNew; - int * pPerms; - - // sort COs by support size - pPerms = ALLOC( int, Abc_NtkCoNum(pNtk) ); - pSupps = ALLOC( int, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pPerms[i] = i; - vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); - pSupps[i] = Vec_PtrSize(vSupp); - Vec_PtrFree( vSupp ); - } - qsort( (void *)pPerms, Abc_NtkCoNum(pNtk), sizeof(int), (int (*)(const void *, const void *)) Abc_NtkCompareConesCompare ); - - // consider COs in this order - Iter = 0; - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pObj = Abc_NtkCo( pNtk, pPerms[i] ); - if ( pObj->fMarkA ) - continue; - Iter++; - - vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); - vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); - vReverse = Abc_NtkDfsReverseNodesContained( pNtk, (Abc_Obj_t **)Vec_PtrArray(vSupp), Vec_PtrSize(vSupp) ); - // count the number of nodes in the reverse cone - Counter = 0; - for ( k = 1; k < Vec_PtrSize(vReverse) - 1; k++ ) - for ( pTemp = Vec_PtrEntry(vReverse, k); pTemp; pTemp = pTemp->pCopy ) - Counter++; - CounterCos = CounterCosNew = 0; - for ( pTemp = Vec_PtrEntryLast(vReverse); pTemp; pTemp = pTemp->pCopy ) - { - assert( Abc_ObjIsCo(pTemp) ); - CounterCos++; - if ( pTemp->fMarkA == 0 ) - CounterCosNew++; - pTemp->fMarkA = 1; - } - // print statistics - printf( "%4d CO %5d : Supp = %5d. Lev = %3d. Cone = %5d. Rev = %5d. COs = %3d (%3d).\n", - Iter, pPerms[i], Vec_PtrSize(vSupp), Abc_ObjLevel(Abc_ObjFanin0(pObj)), Vec_PtrSize(vNodes), Counter, CounterCos, CounterCosNew ); - - // free arrays - Vec_PtrFree( vSupp ); - Vec_PtrFree( vNodes ); - Vec_PtrFree( vReverse ); - - if ( Vec_PtrSize(vSupp) < 10 ) - break; - } - Abc_NtkForEachCo( pNtk, pObj, i ) - pObj->fMarkA = 0; - - free( pPerms ); - free( pSupps ); -} - -/**Function************************************************************* - - Synopsis [Analyze choice node support.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vSupp; - Abc_Obj_t * pObj, * pTemp; - int i, nNodesOld; - assert( Abc_NtkIsStrash(pNtk) ); - Abc_AigForEachAnd( pNtk, pObj, i ) - { - if ( !Abc_AigNodeIsChoice(pObj) ) - continue; - - vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); - nNodesOld = Vec_PtrSize(vSupp); - Vec_PtrFree( vSupp ); - - for ( pTemp = pObj->pData; pTemp; pTemp = pTemp->pData ) - { - vSupp = Abc_NtkNodeSupport( pNtk, &pTemp, 1 ); - if ( nNodesOld != Vec_PtrSize(vSupp) ) - printf( "Choice orig = %3d Choice new = %3d\n", nNodesOld, Vec_PtrSize(vSupp) ); - Vec_PtrFree( vSupp ); - } - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/abc_.c b/src/base/abc/abc_.c deleted file mode 100644 index 50558bdb..00000000 --- a/src/base/abc/abc_.c +++ /dev/null @@ -1,47 +0,0 @@ -/**CFile**************************************************************** - - FileName [abc_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abc/module.make b/src/base/abc/module.make deleted file mode 100644 index 7b34d8f6..00000000 --- a/src/base/abc/module.make +++ /dev/null @@ -1,18 +0,0 @@ -SRC += src/base/abc/abcAig.c \ - src/base/abc/abcBlifMv.c \ - src/base/abc/abcCheck.c \ - src/base/abc/abcDfs.c \ - src/base/abc/abcFanio.c \ - src/base/abc/abcFunc.c \ - src/base/abc/abcHie.c \ - src/base/abc/abcLatch.c \ - src/base/abc/abcLib.c \ - src/base/abc/abcMinBase.c \ - src/base/abc/abcNames.c \ - src/base/abc/abcNetlist.c \ - src/base/abc/abcNtk.c \ - src/base/abc/abcObj.c \ - src/base/abc/abcRefs.c \ - src/base/abc/abcShow.c \ - src/base/abc/abcSop.c \ - src/base/abc/abcUtil.c diff --git a/src/base/abci/abc.c b/src/base/abci/abc.c deleted file mode 100644 index 18fbad38..00000000 --- a/src/base/abci/abc.c +++ /dev/null @@ -1,12764 +0,0 @@ -/**CFile**************************************************************** - - FileName [abc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Command file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "mainInt.h" -#include "fraig.h" -#include "fxu.h" -#include "cut.h" -#include "fpga.h" -#include "if.h" -#include "res.h" -#include "lpk.h" -#include "aig.h" -#include "dar.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Abc_CommandPrintStats ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintExdc ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintIo ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintLatch ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintFanio ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintMffc ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintFactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintLevel ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintSupport ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintSymms ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintUnate ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintAuto ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintKMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintGates ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintSharing ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintXCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPrintDsd ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandCollapse ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandBalance ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandMulti ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRenode ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandFastExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDisjoint ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandImfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandLutpack ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRestructure ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandResubstitute ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDemiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandOrPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAndPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAppend ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandFrames ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSop ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandReorder ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandOrder ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandMuxes ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandCone ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandNode ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandTopmost ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandTrim ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandExdcFree ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandExdcGet ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandExdcSet ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); -//static int Abc_CommandXyz ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDouble ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandQuaVar ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandQuaRel ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandQuaReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandIStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandICut ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandIRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDCompress2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDrwsat ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandIRewriteSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandIResyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandISat ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandIFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandCSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandIProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandHaig ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandMini ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandQbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandFraigTrust ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandFraigStore ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandFraigRestore ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandFraigClean ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandFraigSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandFraigDress ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandHaigStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandHaigStop ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandHaigUse ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandRecStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRecStop ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRecAdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRecPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRecUse ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandAttach ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSuperChoiceLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandFpgaFast ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandIf ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandScut ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandInit ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandZero ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandUndc ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandPipe ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandUnseq ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSeqFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSeqMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandLcorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandCycle ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandXsim ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandDebug ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -static int Abc_CommandTraceStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int Abc_CommandTraceCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_Init( Abc_Frame_t * pAbc ) -{ -// Abc_NtkBddImplicationTest(); - - Cmd_CommandAdd( pAbc, "Printing", "print_stats", Abc_CommandPrintStats, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_exdc", Abc_CommandPrintExdc, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_io", Abc_CommandPrintIo, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_latch", Abc_CommandPrintLatch, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_fanio", Abc_CommandPrintFanio, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_mffc", Abc_CommandPrintMffc, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_symm", Abc_CommandPrintSymms, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_unate", Abc_CommandPrintUnate, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_auto", Abc_CommandPrintAuto, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_kmap", Abc_CommandPrintKMap, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_gates", Abc_CommandPrintGates, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_sharing", Abc_CommandPrintSharing, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_xcut", Abc_CommandPrintXCut, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "print_dsd", Abc_CommandPrintDsd, 0 ); - - Cmd_CommandAdd( pAbc, "Printing", "show", Abc_CommandShow, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 ); - Cmd_CommandAdd( pAbc, "Printing", "show_cut", Abc_CommandShowCut, 0 ); - - Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "balance", Abc_CommandBalance, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "multi", Abc_CommandMulti, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "renode", Abc_CommandRenode, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "cleanup", Abc_CommandCleanup, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "sweep", Abc_CommandSweep, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "fx", Abc_CommandFastExtract, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "dsd", Abc_CommandDisjoint, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "imfs", Abc_CommandImfs, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "lutpack", Abc_CommandLutpack, 1 ); - - Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 ); -// Cmd_CommandAdd( pAbc, "Synthesis", "restructure", Abc_CommandRestructure, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "resub", Abc_CommandResubstitute, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 ); - Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); - - Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 ); - Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 ); - Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 ); - Cmd_CommandAdd( pAbc, "Various", "demiter", Abc_CommandDemiter, 1 ); - Cmd_CommandAdd( pAbc, "Various", "orpos", Abc_CommandOrPos, 1 ); - Cmd_CommandAdd( pAbc, "Various", "andpos", Abc_CommandAndPos, 1 ); - Cmd_CommandAdd( pAbc, "Various", "append", Abc_CommandAppend, 1 ); - Cmd_CommandAdd( pAbc, "Various", "frames", Abc_CommandFrames, 1 ); - Cmd_CommandAdd( pAbc, "Various", "sop", Abc_CommandSop, 0 ); - Cmd_CommandAdd( pAbc, "Various", "bdd", Abc_CommandBdd, 0 ); - Cmd_CommandAdd( pAbc, "Various", "aig", Abc_CommandAig, 0 ); - Cmd_CommandAdd( pAbc, "Various", "reorder", Abc_CommandReorder, 0 ); - Cmd_CommandAdd( pAbc, "Various", "order", Abc_CommandOrder, 0 ); - Cmd_CommandAdd( pAbc, "Various", "muxes", Abc_CommandMuxes, 1 ); - Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 ); - Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandCone, 1 ); - Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandNode, 1 ); - Cmd_CommandAdd( pAbc, "Various", "topmost", Abc_CommandTopmost, 1 ); - Cmd_CommandAdd( pAbc, "Various", "trim", Abc_CommandTrim, 1 ); - Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 ); - Cmd_CommandAdd( pAbc, "Various", "exdc_free", Abc_CommandExdcFree, 1 ); - Cmd_CommandAdd( pAbc, "Various", "exdc_get", Abc_CommandExdcGet, 1 ); - Cmd_CommandAdd( pAbc, "Various", "exdc_set", Abc_CommandExdcSet, 1 ); - Cmd_CommandAdd( pAbc, "Various", "cut", Abc_CommandCut, 0 ); - Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 ); - Cmd_CommandAdd( pAbc, "Various", "gen", Abc_CommandGen, 0 ); -// Cmd_CommandAdd( pAbc, "Various", "xyz", Abc_CommandXyz, 1 ); - Cmd_CommandAdd( pAbc, "Various", "double", Abc_CommandDouble, 1 ); - Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 ); - - Cmd_CommandAdd( pAbc, "Various", "qvar", Abc_CommandQuaVar, 1 ); - Cmd_CommandAdd( pAbc, "Various", "qrel", Abc_CommandQuaRel, 1 ); - Cmd_CommandAdd( pAbc, "Various", "qreach", Abc_CommandQuaReach, 1 ); - - Cmd_CommandAdd( pAbc, "New AIG", "istrash", Abc_CommandIStrash, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "icut", Abc_CommandICut, 0 ); - Cmd_CommandAdd( pAbc, "New AIG", "irw", Abc_CommandIRewrite, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "drw", Abc_CommandDRewrite, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "drf", Abc_CommandDRefactor, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "dcompress2", Abc_CommandDCompress2, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "dchoice", Abc_CommandDChoice, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "drwsat", Abc_CommandDrwsat, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "irws", Abc_CommandIRewriteSeq, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "iresyn", Abc_CommandIResyn, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "isat", Abc_CommandISat, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "ifraig", Abc_CommandIFraig, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "dfraig", Abc_CommandDFraig, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "csweep", Abc_CommandCSweep, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "iprove", Abc_CommandIProve, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "haig", Abc_CommandHaig, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "mini", Abc_CommandMini, 1 ); - Cmd_CommandAdd( pAbc, "New AIG", "_bmc", Abc_CommandBmc, 0 ); - Cmd_CommandAdd( pAbc, "New AIG", "qbf", Abc_CommandQbf, 0 ); - - Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 ); - Cmd_CommandAdd( pAbc, "Fraiging", "fraig_trust", Abc_CommandFraigTrust, 1 ); - Cmd_CommandAdd( pAbc, "Fraiging", "fraig_store", Abc_CommandFraigStore, 0 ); - Cmd_CommandAdd( pAbc, "Fraiging", "fraig_restore", Abc_CommandFraigRestore, 1 ); - Cmd_CommandAdd( pAbc, "Fraiging", "fraig_clean", Abc_CommandFraigClean, 0 ); - Cmd_CommandAdd( pAbc, "Fraiging", "fraig_sweep", Abc_CommandFraigSweep, 1 ); - Cmd_CommandAdd( pAbc, "Fraiging", "dress", Abc_CommandFraigDress, 1 ); - - Cmd_CommandAdd( pAbc, "Choicing", "haig_start", Abc_CommandHaigStart, 0 ); - Cmd_CommandAdd( pAbc, "Choicing", "haig_stop", Abc_CommandHaigStop, 0 ); - Cmd_CommandAdd( pAbc, "Choicing", "haig_use", Abc_CommandHaigUse, 1 ); - - Cmd_CommandAdd( pAbc, "Choicing", "rec_start", Abc_CommandRecStart, 0 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_stop", Abc_CommandRecStop, 0 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_add", Abc_CommandRecAdd, 0 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_ps", Abc_CommandRecPs, 0 ); - Cmd_CommandAdd( pAbc, "Choicing", "rec_use", Abc_CommandRecUse, 1 ); - - Cmd_CommandAdd( pAbc, "SC mapping", "map", Abc_CommandMap, 1 ); - Cmd_CommandAdd( pAbc, "SC mapping", "unmap", Abc_CommandUnmap, 1 ); - Cmd_CommandAdd( pAbc, "SC mapping", "attach", Abc_CommandAttach, 1 ); - Cmd_CommandAdd( pAbc, "SC mapping", "sc", Abc_CommandSuperChoice, 1 ); - Cmd_CommandAdd( pAbc, "SC mapping", "scl", Abc_CommandSuperChoiceLut, 1 ); - - Cmd_CommandAdd( pAbc, "FPGA mapping", "fpga", Abc_CommandFpga, 1 ); - Cmd_CommandAdd( pAbc, "FPGA mapping", "ffpga", Abc_CommandFpgaFast, 1 ); - Cmd_CommandAdd( pAbc, "FPGA mapping", "if", Abc_CommandIf, 1 ); - -// Cmd_CommandAdd( pAbc, "Sequential", "scut", Abc_CommandScut, 0 ); - Cmd_CommandAdd( pAbc, "Sequential", "init", Abc_CommandInit, 1 ); - Cmd_CommandAdd( pAbc, "Sequential", "zero", Abc_CommandZero, 1 ); - Cmd_CommandAdd( pAbc, "Sequential", "undc", Abc_CommandUndc, 1 ); -// Cmd_CommandAdd( pAbc, "Sequential", "pipe", Abc_CommandPipe, 1 ); - Cmd_CommandAdd( pAbc, "Sequential", "retime", Abc_CommandRetime, 1 ); -// Cmd_CommandAdd( pAbc, "Sequential", "sfpga", Abc_CommandSeqFpga, 1 ); -// Cmd_CommandAdd( pAbc, "Sequential", "smap", Abc_CommandSeqMap, 1 ); - Cmd_CommandAdd( pAbc, "Sequential", "ssweep", Abc_CommandSeqSweep, 1 ); - Cmd_CommandAdd( pAbc, "Sequential", "lcorr", Abc_CommandLcorr, 1 ); - Cmd_CommandAdd( pAbc, "Sequential", "scleanup", Abc_CommandSeqCleanup, 1 ); - Cmd_CommandAdd( pAbc, "Sequential", "cycle", Abc_CommandCycle, 1 ); - Cmd_CommandAdd( pAbc, "Sequential", "xsim", Abc_CommandXsim, 0 ); - - Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 ); - Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 ); - Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 ); - Cmd_CommandAdd( pAbc, "Verification", "dprove", Abc_CommandDProve, 0 ); - Cmd_CommandAdd( pAbc, "Verification", "sat", Abc_CommandSat, 0 ); - Cmd_CommandAdd( pAbc, "Verification", "dsat", Abc_CommandDSat, 0 ); - Cmd_CommandAdd( pAbc, "Verification", "prove", Abc_CommandProve, 1 ); - Cmd_CommandAdd( pAbc, "Verification", "debug", Abc_CommandDebug, 0 ); - -// Cmd_CommandAdd( pAbc, "Verification", "trace_start", Abc_CommandTraceStart, 0 ); -// Cmd_CommandAdd( pAbc, "Verification", "trace_check", Abc_CommandTraceCheck, 0 ); - -// Rwt_Man4ExploreStart(); -// Map_Var3Print(); -// Map_Var4Test(); - -// Abc_NtkPrint256(); -// Kit_TruthCountMintermsPrecomp(); -// Kit_DsdPrecompute4Vars(); - - { - extern void Dar_LibStart(); - Dar_LibStart(); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_End() -{ -// Dar_LibDumpPriorities(); - - { - extern void Cnf_ClearMemory(); - Cnf_ClearMemory(); - } - { - extern void Dar_LibStop(); - Dar_LibStop(); - } - - Abc_NtkFraigStoreClean(); -// Rwt_Man4ExplorePrint(); - -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - bool fShort; - int c; - int fFactor; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set the defaults - fShort = 1; - fFactor = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "sfh" ) ) != EOF ) - { - switch ( c ) - { - case 's': - fShort ^= 1; - break; - case 'f': - fFactor ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" ); - return 1; - } - Abc_NtkPrintStats( pOut, pNtk, fFactor ); - return 0; - -usage: - fprintf( pErr, "usage: print_stats [-fh]\n" ); - fprintf( pErr, "\t prints the network statistics\n" ); - fprintf( pErr, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkTemp; - double Percentage; - bool fShort; - int c; - int fPrintDc; - - extern double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set the defaults - fShort = 1; - fPrintDc = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "sdh" ) ) != EOF ) - { - switch ( c ) - { - case 's': - fShort ^= 1; - break; - case 'd': - fPrintDc ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( Abc_FrameReadErr(pAbc), "Empty network.\n" ); - return 1; - } - if ( pNtk->pExdc == NULL ) - { - fprintf( Abc_FrameReadErr(pAbc), "Network has no EXDC.\n" ); - return 1; - } - - if ( fPrintDc ) - { - if ( !Abc_NtkIsStrash(pNtk->pExdc) ) - { - pNtkTemp = Abc_NtkStrash(pNtk->pExdc, 0, 0, 0); - Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtkTemp, 0) ) ); - Abc_NtkDelete( pNtkTemp ); - } - else - Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtk->pExdc, 0) ) ); - - printf( "EXDC network statistics: " ); - printf( "(" ); - if ( Percentage > 0.05 && Percentage < 99.95 ) - printf( "%.2f", Percentage ); - else if ( Percentage > 0.000005 && Percentage < 99.999995 ) - printf( "%.6f", Percentage ); - else - printf( "%f", Percentage ); - printf( " %% don't-cares)\n" ); - } - else - printf( "EXDC network statistics: \n" ); - Abc_NtkPrintStats( pOut, pNtk->pExdc, 0 ); - return 0; - -usage: - fprintf( pErr, "usage: print_exdc [-dh]\n" ); - fprintf( pErr, "\t prints the EXDC network statistics\n" ); - fprintf( pErr, "\t-d : toggles printing don't-care percentage [default = %s]\n", fPrintDc? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( argc > globalUtilOptind + 1 ) - { - fprintf( pErr, "Wrong number of auguments.\n" ); - goto usage; - } - - if ( argc == globalUtilOptind + 1 ) - { - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); - if ( pNode == NULL ) - { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); - return 1; - } - Abc_NodePrintFanio( pOut, pNode ); - return 0; - } - // print the nodes - Abc_NtkPrintIo( pOut, pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: print_io [-h] \n" ); - fprintf( pErr, "\t prints the PIs/POs or fanins/fanouts of a node\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\tnode : the node to print fanins/fanouts\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - // print the nodes - Abc_NtkPrintLatch( pOut, pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: print_latch [-h]\n" ); - fprintf( pErr, "\t prints information about latches\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - // print the nodes - Abc_NtkPrintFanio( pOut, pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: print_fanio [-h]\n" ); - fprintf( pErr, "\t prints the statistics about fanins/fanouts of all nodes\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintMffc( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - extern void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - // print the nodes - Abc_NtkPrintMffc( pOut, pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: print_mffc [-h]\n" ); - fprintf( pErr, "\t prints the MFFC of each node in the network\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode; - int c; - int fUseRealNames; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUseRealNames = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) - { - switch ( c ) - { - case 'n': - fUseRealNames ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsSopLogic(pNtk) ) - { - fprintf( pErr, "Printing factored forms can be done for SOP networks.\n" ); - return 1; - } - - if ( argc > globalUtilOptind + 1 ) - { - fprintf( pErr, "Wrong number of auguments.\n" ); - goto usage; - } - - if ( argc == globalUtilOptind + 1 ) - { - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); - if ( pNode == NULL ) - { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); - return 1; - } - Abc_NodePrintFactor( pOut, pNode, fUseRealNames ); - return 0; - } - // print the nodes - Abc_NtkPrintFactor( pOut, pNtk, fUseRealNames ); - return 0; - -usage: - fprintf( pErr, "usage: print_factor [-nh] \n" ); - fprintf( pErr, "\t prints the factored forms of nodes\n" ); - fprintf( pErr, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\tnode : (optional) one node to consider\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode; - int c; - int fListNodes; - int fProfile; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fListNodes = 0; - fProfile = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF ) - { - switch ( c ) - { - case 'n': - fListNodes ^= 1; - break; - case 'p': - fProfile ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !fProfile && !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); - return 1; - } - - if ( argc > globalUtilOptind + 1 ) - { - fprintf( pErr, "Wrong number of auguments.\n" ); - goto usage; - } - - if ( argc == globalUtilOptind + 1 ) - { - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); - if ( pNode == NULL ) - { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); - return 1; - } - Abc_NodePrintLevel( pOut, pNode ); - return 0; - } - // process all COs - Abc_NtkPrintLevel( pOut, pNtk, fProfile, fListNodes ); - return 0; - -usage: - fprintf( pErr, "usage: print_level [-nph] \n" ); - fprintf( pErr, "\t prints information about node level and cone size\n" ); - fprintf( pErr, "\t-n : toggles printing nodes by levels [default = %s]\n", fListNodes? "yes": "no" ); - fprintf( pErr, "\t-p : toggles printing level profile [default = %s]\n", fProfile? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\tnode : (optional) one node to consider\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Vec_Ptr_t * vSuppFun; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fStruct; - int fVerbose; - extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ); - extern void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fStruct = 1; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) - { - switch ( c ) - { - case 's': - fStruct ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - // print support information - if ( fStruct ) - { - Abc_NtkPrintStrSupports( pNtk ); - return 0; - } - - if ( !Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); - return 1; - } - vSuppFun = Sim_ComputeFunSupp( pNtk, fVerbose ); - free( vSuppFun->pArray[0] ); - Vec_PtrFree( vSuppFun ); - return 0; - -usage: - fprintf( pErr, "usage: print_supp [-svh]\n" ); - fprintf( pErr, "\t prints the supports of the CO nodes\n" ); - fprintf( pErr, "\t-s : toggle printing structural support only [default = %s].\n", fStruct? "yes": "no" ); - fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fUseBdds; - int fNaive; - int fReorder; - int fVerbose; - extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUseBdds = 0; - fNaive = 0; - fReorder = 1; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "bnrvh" ) ) != EOF ) - { - switch ( c ) - { - case 'b': - fUseBdds ^= 1; - break; - case 'n': - fNaive ^= 1; - break; - case 'r': - fReorder ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "This command works only for combinational networks (run \"comb\").\n" ); - return 1; - } - if ( Abc_NtkIsStrash(pNtk) ) - Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); - else - { - pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); - Abc_NtkDelete( pNtk ); - } - return 0; - -usage: - fprintf( pErr, "usage: print_symm [-bnrvh]\n" ); - fprintf( pErr, "\t computes symmetries of the PO functions\n" ); - fprintf( pErr, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" ); - fprintf( pErr, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" ); - fprintf( pErr, "\t-r : enable dynamic BDD variable reordering [default = %s].\n", fReorder? "yes": "no" ); - fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintUnate( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fUseBdds; - int fUseNaive; - int fVerbose; - extern void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUseBdds = 1; - fUseNaive = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF ) - { - switch ( c ) - { - case 'b': - fUseBdds ^= 1; - break; - case 'n': - fUseNaive ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); - return 1; - } - Abc_NtkPrintUnate( pNtk, fUseBdds, fUseNaive, fVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: print_unate [-bnvh]\n" ); - fprintf( pErr, "\t computes unate variables of the PO functions\n" ); - fprintf( pErr, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" ); - fprintf( pErr, "\t-n : toggle naive BDD-based computation [default = %s].\n", fUseNaive? "yes": "no" ); - fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int Output; - int fNaive; - int fVerbose; - extern void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Output = -1; - fNaive = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Onvh" ) ) != EOF ) - { - switch ( c ) - { - case 'O': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" ); - goto usage; - } - Output = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( Output < 0 ) - goto usage; - break; - case 'n': - fNaive ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for AIGs (run \"strash\").\n" ); - return 1; - } - - - Abc_NtkAutoPrint( pNtk, Output, fNaive, fVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: print_auto [-O num] [-nvh]\n" ); - fprintf( pErr, "\t computes autosymmetries of the PO functions\n" ); - fprintf( pErr, "\t-O num : (optional) the 0-based number of the output [default = all]\n"); - fprintf( pErr, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" ); - fprintf( pErr, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode; - int c; - int fUseRealNames; - - extern void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUseRealNames = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) - { - switch ( c ) - { - case 'n': - fUseRealNames ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "Visualization of Karnaugh maps works for logic networks.\n" ); - return 1; - } - if ( argc > globalUtilOptind + 1 ) - { - fprintf( pErr, "Wrong number of auguments.\n" ); - goto usage; - } - if ( argc == globalUtilOptind ) - { - pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); - if ( !Abc_ObjIsNode(pNode) ) - { - fprintf( pErr, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) ); - return 1; - } - } - else - { - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); - if ( pNode == NULL ) - { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); - return 1; - } - } - Abc_NtkToBdd(pNtk); - Abc_NodePrintKMap( pNode, fUseRealNames ); - return 0; - -usage: - fprintf( pErr, "usage: print_kmap [-nh] \n" ); - fprintf( pErr, " shows the truth table of the node\n" ); - fprintf( pErr, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\tnode : the node to consider (default = the driver of the first PO)\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fUseLibrary; - - extern void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUseLibrary = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) - { - switch ( c ) - { - case 'l': - fUseLibrary ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkHasAig(pNtk) ) - { - fprintf( pErr, "Printing gates does not work for AIGs and sequential AIGs.\n" ); - return 1; - } - - Abc_NtkPrintGates( pNtk, fUseLibrary ); - return 0; - -usage: - fprintf( pErr, "usage: print_gates [-lh]\n" ); - fprintf( pErr, "\t prints statistics about gates used in the network\n" ); - fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fUseLibrary; - - extern void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUseLibrary = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) - { - switch ( c ) - { - case 'l': - fUseLibrary ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - Abc_NtkPrintSharing( pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: print_sharing [-h]\n" ); - fprintf( pErr, "\t prints the number of shared nodes in the TFI cones of the COs\n" ); -// fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fUseLibrary; - - extern int Abc_NtkCrossCut( Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUseLibrary = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) - { - switch ( c ) - { - case 'l': - fUseLibrary ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - Abc_NtkCrossCut( pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: print_xcut [-h]\n" ); - fprintf( pErr, "\t prints the size of the cross cut of the current network\n" ); -// fprintf( pErr, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPrintDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fCofactor; - int nCofLevel; - - extern void Kit_DsdTest( unsigned * pTruth, int nVars ); - extern void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nCofLevel = 1; - fCofactor = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Nch" ) ) != EOF ) - { - switch ( c ) - { - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - nCofLevel = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nCofLevel < 0 ) - goto usage; - break; - case 'c': - fCofactor ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - // get the truth table of the first output - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "Currently works only for logic networks.\n" ); - return 1; - } - Abc_NtkToAig( pNtk ); - // convert it to truth table - { - Abc_Obj_t * pObj = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); - Vec_Int_t * vMemory = Vec_IntAlloc(0); - unsigned * pTruth; - if ( !Abc_ObjIsNode(pObj) ) - { - fprintf( pErr, "The fanin of the first PO node does not have a logic function.\n" ); - return 1; - } - if ( Abc_ObjFaninNum(pObj) > 16 ) - { - fprintf( pErr, "Currently works only for up to 16 inputs.\n" ); - return 1; - } - pTruth = Abc_ConvertAigToTruth( pNtk->pManFunc, Hop_Regular(pObj->pData), Abc_ObjFaninNum(pObj), vMemory, 0 ); - if ( Hop_IsComplement(pObj->pData) ) - Extra_TruthNot( pTruth, pTruth, Abc_ObjFaninNum(pObj) ); - Extra_PrintBinary( stdout, pTruth, 1 << Abc_ObjFaninNum(pObj) ); - printf( "\n" ); - if ( fCofactor ) - Kit_DsdPrintCofactors( pTruth, Abc_ObjFaninNum(pObj), nCofLevel, 1 ); - else - Kit_DsdTest( pTruth, Abc_ObjFaninNum(pObj) ); - Vec_IntFree( vMemory ); - } - return 0; - -usage: - fprintf( pErr, "usage: print_dsd [-ch] [-N num]\n" ); - fprintf( pErr, "\t print DSD formula for a single-output function with less than 16 variables\n" ); - fprintf( pErr, "\t-c : toggle recursive cofactoring [default = %s]\n", fCofactor? "yes": "no" ); - fprintf( pErr, "\t-N num : the number of levels to cofactor [default = %d]\n", nCofLevel ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fSeq; - int fGateNames; - int fUseReverse; - extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fSeq = 0; - fGateNames = 0; - fUseReverse = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "rsgh" ) ) != EOF ) - { - switch ( c ) - { - case 'r': - fUseReverse ^= 1; - break; - case 's': - fSeq ^= 1; - break; - case 'g': - fGateNames ^= 1; - break; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse ); - return 0; - -usage: - fprintf( pErr, "usage: show [-srgh]\n" ); - fprintf( pErr, " visualizes the network structure using DOT and GSVIEW\n" ); -#ifdef WIN32 - fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); - fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); -#endif - fprintf( pErr, "\t-s : toggles visualization of sequential networks [default = %s].\n", fSeq? "yes": "no" ); - fprintf( pErr, "\t-r : toggles ordering nodes in reverse order [default = %s].\n", fUseReverse? "yes": "no" ); - fprintf( pErr, "\t-g : toggles printing gate names for mapped network [default = %s].\n", fGateNames? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode; - int c; - extern void Abc_NodeShowBdd( Abc_Obj_t * pNode ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsBddLogic(pNtk) ) - { - fprintf( pErr, "Visualizing BDDs can only be done for logic BDD networks (run \"bdd\").\n" ); - return 1; - } - - if ( argc > globalUtilOptind + 1 ) - { - fprintf( pErr, "Wrong number of auguments.\n" ); - goto usage; - } - if ( argc == globalUtilOptind ) - { - pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); - if ( !Abc_ObjIsNode(pNode) ) - { - fprintf( pErr, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) ); - return 1; - } - } - else - { - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); - if ( pNode == NULL ) - { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); - return 1; - } - } - Abc_NodeShowBdd( pNode ); - return 0; - -usage: - fprintf( pErr, "usage: show_bdd [-h] \n" ); - fprintf( pErr, " visualizes the BDD of a node using DOT and GSVIEW\n" ); -#ifdef WIN32 - fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); - fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); -#endif - fprintf( pErr, "\tnode : the node to consider [default = the driver of the first PO]\n"); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode; - int c; - int nNodeSizeMax; - int nConeSizeMax; - extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nNodeSizeMax = 10; - nConeSizeMax = ABC_INFINITY; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NCh" ) ) != EOF ) - { - switch ( c ) - { - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - nNodeSizeMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nNodeSizeMax < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nConeSizeMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nConeSizeMax < 0 ) - goto usage; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Visualizing cuts only works for AIGs (run \"strash\").\n" ); - return 1; - } - if ( argc != globalUtilOptind + 1 ) - { - fprintf( pErr, "Wrong number of auguments.\n" ); - goto usage; - } - - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); - if ( pNode == NULL ) - { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); - return 1; - } - Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax ); - return 0; - -usage: - fprintf( pErr, "usage: show_cut [-N num] [-C num] [-h] \n" ); - fprintf( pErr, " visualizes the cut of a node using DOT and GSVIEW\n" ); -#ifdef WIN32 - fprintf( pErr, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); - fprintf( pErr, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); -#endif - fprintf( pErr, "\t-N num : the max size of the cut to be computed [default = %d]\n", nNodeSizeMax ); - fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax ); - fprintf( pErr, "\tnode : the node to consider\n"); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int fVerbose; - int fBddSizeMax; - int fDualRail; - int fReorder; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fVerbose = 1; - fReorder = 1; - fDualRail = 0; - fBddSizeMax = 50000000; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Brdvh" ) ) != EOF ) - { - switch ( c ) - { - case 'B': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-B\" should be followed by an integer.\n" ); - goto usage; - } - fBddSizeMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( fBddSizeMax < 0 ) - goto usage; - break; - case 'd': - fDualRail ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'r': - fReorder ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Can only collapse a logic network or an AIG.\n" ); - return 1; - } - - // get the new network - if ( Abc_NtkIsStrash(pNtk) ) - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); - else - { - pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fVerbose ); - Abc_NtkDelete( pNtk ); - } - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Collapsing has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: collapse [-B num] [-rdvh]\n" ); - fprintf( pErr, "\t collapses the network by constructing global BDDs\n" ); - fprintf( pErr, "\t-B num : limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax ); - fprintf( pErr, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); - fprintf( pErr, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" ); - fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int fAllNodes; - int fRecord; - int fCleanup; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fAllNodes = 0; - fCleanup = 1; - fRecord = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "acrh" ) ) != EOF ) - { - switch ( c ) - { - case 'a': - fAllNodes ^= 1; - break; - case 'c': - fCleanup ^= 1; - break; - case 'r': - fRecord ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - // get the new network - pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup, fRecord ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Strashing has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: strash [-acrh]\n" ); - fprintf( pErr, "\t transforms combinational logic into an AIG\n" ); - fprintf( pErr, "\t-a : toggles between using all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "DFS" ); - fprintf( pErr, "\t-c : toggles cleanup to remove the dagling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" ); - fprintf( pErr, "\t-r : enables using the record of AIG subgraphs [default = %s]\n", fRecord? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; - int c; - bool fDuplicate; - bool fSelective; - bool fUpdateLevel; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fDuplicate = 0; - fSelective = 0; - fUpdateLevel = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ldsh" ) ) != EOF ) - { - switch ( c ) - { - case 'l': - fUpdateLevel ^= 1; - break; - case 'd': - fDuplicate ^= 1; - break; - case 's': - fSelective ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - // get the new network - if ( Abc_NtkIsStrash(pNtk) ) - { - pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel ); - } - else - { - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - if ( pNtkTemp == NULL ) - { - fprintf( pErr, "Strashing before balancing has failed.\n" ); - return 1; - } - pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective, fUpdateLevel ); - Abc_NtkDelete( pNtkTemp ); - } - - // check if balancing worked - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Balancing has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: balance [-ldsh]\n" ); - fprintf( pErr, "\t transforms the current network into a well-balanced AIG\n" ); - fprintf( pErr, "\t-l : toggle minimizing the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); - fprintf( pErr, "\t-s : toggle duplication on the critical paths [default = %s]\n", fSelective? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int nThresh, nFaninMax, c; - int fCnf; - int fMulti; - int fSimple; - int fFactor; - extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nThresh = 1; - nFaninMax = 20; - fCnf = 0; - fMulti = 1; - fSimple = 0; - fFactor = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "TFmcsfh" ) ) != EOF ) - { - switch ( c ) - { - case 'T': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); - goto usage; - } - nThresh = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nThresh < 0 ) - goto usage; - break; - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - nFaninMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFaninMax < 0 ) - goto usage; - break; - case 'c': - fCnf ^= 1; - break; - case 'm': - fMulti ^= 1; - break; - case 's': - fSimple ^= 1; - break; - case 'f': - fFactor ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); - return 1; - } - - // get the new network - pNtkRes = Abc_NtkMulti( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Renoding has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: multi [-T num] [-F num] [-msfch]\n" ); - fprintf( pErr, "\t transforms an AIG into a logic network by creating larger nodes\n" ); - fprintf( pErr, "\t-F num : the maximum fanin size after renoding [default = %d]\n", nFaninMax ); - fprintf( pErr, "\t-T num : the threshold for AIG node duplication [default = %d]\n", nThresh ); - fprintf( pErr, "\t (an AIG node is the root of a new node after renoding\n" ); - fprintf( pErr, "\t if this leads to duplication of no more than %d AIG nodes,\n", nThresh ); - fprintf( pErr, "\t that is, if [(numFanouts(Node)-1) * size(MFFC(Node))] <= %d)\n", nThresh ); - fprintf( pErr, "\t-m : creates multi-input AND graph [default = %s]\n", fMulti? "yes": "no" ); - fprintf( pErr, "\t-s : creates a simple AIG (no renoding) [default = %s]\n", fSimple? "yes": "no" ); - fprintf( pErr, "\t-f : creates a factor-cut network [default = %s]\n", fFactor? "yes": "no" ); - fprintf( pErr, "\t-c : performs renoding to derive the CNF [default = %s]\n", fCnf? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int nLutSize, nCutsMax, c; - int nFlowIters, nAreaIters; - int fArea; - int fUseBdds; - int fUseSops; - int fUseCnfs; - int fUseMv; - int fVerbose; - extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nLutSize = 8; - nCutsMax = 4; - nFlowIters = 1; - nAreaIters = 1; - fArea = 0; - fUseBdds = 0; - fUseSops = 0; - fUseCnfs = 0; - fUseMv = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscivh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - nLutSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLutSize < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nCutsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nCutsMax < 0 ) - goto usage; - break; - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by a positive integer.\n" ); - goto usage; - } - nFlowIters = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFlowIters < 0 ) - goto usage; - break; - case 'A': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-A\" should be followed by a positive integer.\n" ); - goto usage; - } - nAreaIters = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nAreaIters < 0 ) - goto usage; - break; - case 'a': - fArea ^= 1; - break; - case 'b': - fUseBdds ^= 1; - break; - case 's': - fUseSops ^= 1; - break; - case 'c': - fUseCnfs ^= 1; - break; - case 'i': - fUseMv ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( fUseBdds + fUseSops + fUseCnfs + fUseMv > 1 ) - { - fprintf( pErr, "Cannot optimize two parameters at the same time.\n" ); - return 1; - } - - if ( nLutSize < 3 || nLutSize > IF_MAX_FUNC_LUTSIZE ) - { - fprintf( pErr, "Incorrect LUT size (%d).\n", nLutSize ); - return 1; - } - - if ( nCutsMax < 1 || nCutsMax >= (1<<12) ) - { - fprintf( pErr, "Incorrect number of cuts.\n" ); - return 1; - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); - return 1; - } - - // get the new network - pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fUseMv, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Renoding has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: renode [-K num] [-C num] [-F num] [-A num] [-sbciav]\n" ); - fprintf( pErr, "\t transforms the AIG into a logic network with larger nodes\n" ); - fprintf( pErr, "\t while minimizing the number of FF literals of the node SOPs\n" ); - fprintf( pErr, "\t-K num : the max cut size for renoding (2 < num < %d) [default = %d]\n", IF_MAX_FUNC_LUTSIZE+1, nLutSize ); - fprintf( pErr, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCutsMax ); - fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", nFlowIters ); - fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", nAreaIters ); - fprintf( pErr, "\t-s : toggles minimizing SOP cubes instead of FF lits [default = %s]\n", fUseSops? "yes": "no" ); - fprintf( pErr, "\t-b : toggles minimizing BDD nodes instead of FF lits [default = %s]\n", fUseBdds? "yes": "no" ); - fprintf( pErr, "\t-c : toggles minimizing CNF clauses instead of FF lits [default = %s]\n", fUseCnfs? "yes": "no" ); - fprintf( pErr, "\t-i : toggles minimizing MV-SOP instead of FF lits [default = %s]\n", fUseMv? "yes": "no" ); - fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", fArea? "yes": "no" ); - fprintf( pErr, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Cleanup cannot be performed on the AIG.\n" ); - return 1; - } - // modify the current network - Abc_NtkCleanup( pNtk, 1 ); - return 0; - -usage: - fprintf( pErr, "usage: cleanup [-h]\n" ); - fprintf( pErr, "\t removes dangling nodes\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "The classical (SIS-like) sweep can only be performed on a logic network.\n" ); - return 1; - } - // modify the current network - Abc_NtkSweep( pNtk, 0 ); - return 0; - -usage: - fprintf( pErr, "usage: sweep [-h]\n" ); - fprintf( pErr, "\t removes dangling nodes; propagates constant, buffers, inverters\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - FILE * pOut, * pErr; - Fxu_Data_t * p = NULL; - int c; - extern bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); - extern void Abc_NtkFxuFreeInfo( Fxu_Data_t * p ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // allocate the structure - p = ALLOC( Fxu_Data_t, 1 ); - memset( p, 0, sizeof(Fxu_Data_t) ); - // set the defaults - p->nSingleMax = 20000; - p->nPairsMax = 30000; - p->nNodesExt = 10000; - p->fOnlyS = 0; - p->fOnlyD = 0; - p->fUse0 = 0; - p->fUseCompl = 1; - p->fVerbose = 0; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "SDNsdzcvh")) != EOF ) - { - switch (c) - { - case 'S': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" ); - goto usage; - } - p->nSingleMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( p->nSingleMax < 0 ) - goto usage; - break; - case 'D': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); - goto usage; - } - p->nPairsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( p->nPairsMax < 0 ) - goto usage; - break; - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - p->nNodesExt = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( p->nNodesExt < 0 ) - goto usage; - break; - case 's': - p->fOnlyS ^= 1; - break; - case 'd': - p->fOnlyD ^= 1; - break; - case 'z': - p->fUse0 ^= 1; - break; - case 'c': - p->fUseCompl ^= 1; - break; - case 'v': - p->fVerbose ^= 1; - break; - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - Abc_NtkFxuFreeInfo( p ); - return 1; - } - - if ( Abc_NtkNodeNum(pNtk) == 0 ) - { - fprintf( pErr, "The network does not have internal nodes.\n" ); - Abc_NtkFxuFreeInfo( p ); - return 1; - } - - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "Fast extract can only be applied to a logic network (run \"renode\").\n" ); - Abc_NtkFxuFreeInfo( p ); - return 1; - } - - - // the nodes to be merged are linked into the special linked list - Abc_NtkFastExtract( pNtk, p ); - Abc_NtkFxuFreeInfo( p ); - return 0; - -usage: - fprintf( pErr, "usage: fx [-S num] [-D num] [-N num] [-sdzcvh]\n"); - fprintf( pErr, "\t performs unate fast extract on the current network\n"); - fprintf( pErr, "\t-S num : max number of single-cube divisors to consider [default = %d]\n", p->nSingleMax ); - fprintf( pErr, "\t-D num : max number of double-cube divisors to consider [default = %d]\n", p->nPairsMax ); - fprintf( pErr, "\t-N num : the maximum number of divisors to extract [default = %d]\n", p->nNodesExt ); - fprintf( pErr, "\t-s : use only single-cube divisors [default = %s]\n", p->fOnlyS? "yes": "no" ); - fprintf( pErr, "\t-d : use only double-cube divisors [default = %s]\n", p->fOnlyD? "yes": "no" ); - fprintf( pErr, "\t-z : use zero-weight divisors [default = %s]\n", p->fUse0? "yes": "no" ); - fprintf( pErr, "\t-c : use complement in the binary case [default = %s]\n", p->fUseCompl? "yes": "no" ); - fprintf( pErr, "\t-v : print verbose information [default = %s]\n", p->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - Abc_NtkFxuFreeInfo( p ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes, * pNtkNew; - int fGlobal, fRecursive, fVerbose, fPrint, fShort, c; - - extern Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ); - extern int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fGlobal = 1; - fRecursive = 0; - fVerbose = 0; - fPrint = 0; - fShort = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "grvpsh" ) ) != EOF ) - { - switch ( c ) - { - case 'g': - fGlobal ^= 1; - break; - case 'r': - fRecursive ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'p': - fPrint ^= 1; - break; - case 's': - fShort ^= 1; - break; - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( fGlobal ) - { -// fprintf( stdout, "Performing DSD of global functions of the network.\n" ); - // get the new network - if ( !Abc_NtkIsStrash(pNtk) ) - { - pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkRes = Abc_NtkDsdGlobal( pNtkNew, fVerbose, fPrint, fShort ); - Abc_NtkDelete( pNtkNew ); - } - else - { - pNtkRes = Abc_NtkDsdGlobal( pNtk, fVerbose, fPrint, fShort ); - } - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Global DSD has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - } - else if ( fRecursive ) - { - if ( !Abc_NtkIsBddLogic( pNtk ) ) - { - fprintf( pErr, "This command is only applicable to logic BDD networks.\n" ); - return 1; - } - fprintf( stdout, "Performing recursive DSD and MUX decomposition of local functions.\n" ); - if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) ) - fprintf( pErr, "Recursive DSD has failed.\n" ); - } - else - { - if ( !Abc_NtkIsBddLogic( pNtk ) ) - { - fprintf( pErr, "This command is only applicable to logic BDD networks (run \"bdd\").\n" ); - return 1; - } - fprintf( stdout, "Performing simple non-recursive DSD of local functions.\n" ); - if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) ) - fprintf( pErr, "Simple DSD of local functions has failed.\n" ); - } - return 0; - -usage: - fprintf( pErr, "usage: dsd [-grvpsh]\n" ); - fprintf( pErr, "\t decomposes the network using disjoint-support decomposition\n" ); - fprintf( pErr, "\t-g : toggle DSD of global and local functions [default = %s]\n", fGlobal? "global": "local" ); - fprintf( pErr, "\t-r : toggle recursive DSD/MUX and simple DSD [default = %s]\n", fRecursive? "recursive DSD/MUX": "simple DSD" ); - fprintf( pErr, "\t-v : prints DSD statistics and runtime [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-p : prints DSD structure to the standard output [default = %s]\n", fPrint? "yes": "no" ); - fprintf( pErr, "\t-s : use short PI names when printing DSD structure [default = %s]\n", fShort? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandImfs( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - Res_Par_t Pars, * pPars = &Pars; - int c; - -// printf( "Implementation of this command is not finished.\n" ); -// return 1; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - pPars->nWindow = 62; - pPars->nGrowthLevel = 1; - pPars->nCands = 5; - pPars->nSimWords = 4; - pPars->fArea = 0; - pPars->fVerbose = 0; - pPars->fVeryVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "WSCLavwh" ) ) != EOF ) - { - switch ( c ) - { - case 'W': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nWindow = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nWindow < 1 || pPars->nWindow > 99 ) - goto usage; - break; - case 'S': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nSimWords = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nSimWords < 1 || pPars->nSimWords > 256 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nCands = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nCands < 0 || pPars->nCands > ABC_INFINITY ) - goto usage; - break; - case 'L': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) - goto usage; - break; - case 'a': - pPars->fArea ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'w': - pPars->fVeryVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "This command can only be applied to a logic network.\n" ); - return 1; - } - - // modify the current network - if ( !Abc_NtkResynthesize( pNtk, pPars ) ) - { - fprintf( pErr, "Resynthesis has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: imfs [-W ] [-L ] [-C ] [-S ] [-avwh]\n" ); - fprintf( pErr, "\t performs resubstitution-based resynthesis with interpolation\n" ); - fprintf( pErr, "\t-W : fanin/fanout levels (NxM) of the window (00 <= NM <= 99) [default = %d%d]\n", pPars->nWindow/10, pPars->nWindow%10 ); - fprintf( pErr, "\t-L : the largest increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); - fprintf( pErr, "\t-C : the max number of resub candidates (1 <= n) [default = %d]\n", pPars->nCands ); - fprintf( pErr, "\t-S : the number of simulation words (1 <= n <= 256) [default = %d]\n", pPars->nSimWords ); - fprintf( pErr, "\t-a : toggle optimization for area only [default = %s]\n", pPars->fArea? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-w : toggle printout subgraph statistics [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - Lpk_Par_t Pars, * pPars = &Pars; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - memset( pPars, 0, sizeof(Lpk_Par_t) ); - pPars->nLutsMax = 4; // (N) the maximum number of LUTs in the structure - pPars->nLutsOver = 3; // (Q) the maximum number of LUTs not in the MFFC - pPars->nVarsShared = 0; // (S) the maximum number of shared variables (crossbars) - pPars->nGrowthLevel = 0; // (L) the maximum number of increased levels - pPars->fSatur = 1; - pPars->fZeroCost = 0; - pPars->fFirst = 0; - pPars->fOldAlgo = 0; - pPars->fVerbose = 0; - pPars->fVeryVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NQSLszfovwh" ) ) != EOF ) - { - switch ( c ) - { - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nLutsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nLutsMax < 2 || pPars->nLutsMax > 8 ) - goto usage; - break; - case 'Q': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-Q\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nLutsOver = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nLutsOver < 0 || pPars->nLutsOver > 8 ) - goto usage; - break; - case 'S': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-S\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nVarsShared = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 4 ) - goto usage; - break; - case 'L': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) - goto usage; - break; - case 's': - pPars->fSatur ^= 1; - break; - case 'z': - pPars->fZeroCost ^= 1; - break; - case 'f': - pPars->fFirst ^= 1; - break; - case 'o': - pPars->fOldAlgo ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'w': - pPars->fVeryVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "This command can only be applied to a logic network.\n" ); - return 1; - } - if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 3 ) - { - fprintf( pErr, "The number of shared variables (%d) is not in the range 0 <= S <= 3.\n", pPars->nVarsShared ); - return 1; - } - - // modify the current network - if ( !Lpk_Resynthesize( pNtk, pPars ) ) - { - fprintf( pErr, "Resynthesis has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: lutpack [-N ] [-Q ] [-S ] [-L ] [-szfovwh]\n" ); - fprintf( pErr, "\t performs \"rewriting\" for LUT networks\n" ); - fprintf( pErr, "\t-N : the max number of LUTs in the structure (2 <= num) [default = %d]\n", pPars->nLutsMax ); - fprintf( pErr, "\t-Q : the max number of LUTs not in MFFC (0 <= num) [default = %d]\n", pPars->nLutsOver ); - fprintf( pErr, "\t-S : the max number of LUT inputs shared (0 <= num <= 3) [default = %d]\n", pPars->nVarsShared ); - fprintf( pErr, "\t-L : max level increase after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); - fprintf( pErr, "\t-s : toggle iteration till saturation [default = %s]\n", pPars->fSatur? "yes": "no" ); - fprintf( pErr, "\t-z : toggle zero-cost replacements [default = %s]\n", pPars->fZeroCost? "yes": "no" ); - fprintf( pErr, "\t-f : toggle using only first node and first cut [default = %s]\n", pPars->fFirst? "yes": "no" ); - fprintf( pErr, "\t-o : toggle using old implementation [default = %s]\n", pPars->fOldAlgo? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-w : toggle detailed printout of decomposed functions [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - bool fUpdateLevel; - bool fPrecompute; - bool fUseZeros; - bool fVerbose; - bool fVeryVerbose; - bool fPlaceEnable; - // external functions - extern void Rwr_Precompute(); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUpdateLevel = 1; - fPrecompute = 0; - fUseZeros = 0; - fVerbose = 0; - fVeryVerbose = 0; - fPlaceEnable = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwh" ) ) != EOF ) - { - switch ( c ) - { - case 'l': - fUpdateLevel ^= 1; - break; - case 'x': - fPrecompute ^= 1; - break; - case 'z': - fUseZeros ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'w': - fVeryVerbose ^= 1; - break; - case 'p': - fPlaceEnable ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( fPrecompute ) - { - Rwr_Precompute(); - return 0; - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); - return 1; - } - if ( Abc_NtkGetChoiceNum(pNtk) ) - { - fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); - return 1; - } - - // modify the current network - if ( !Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ) ) - { - fprintf( pErr, "Rewriting has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: rewrite [-lzvwh]\n" ); - fprintf( pErr, "\t performs technology-independent rewriting of the AIG\n" ); - fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-w : toggle printout subgraph statistics [default = %s]\n", fVeryVerbose? "yes": "no" ); -// fprintf( pErr, "\t-p : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int nNodeSizeMax; - int nConeSizeMax; - bool fUpdateLevel; - bool fUseZeros; - bool fUseDcs; - bool fVerbose; - extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nNodeSizeMax = 10; - nConeSizeMax = 16; - fUpdateLevel = 1; - fUseZeros = 0; - fUseDcs = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NClzdvh" ) ) != EOF ) - { - switch ( c ) - { - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - nNodeSizeMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nNodeSizeMax < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nConeSizeMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nConeSizeMax < 0 ) - goto usage; - break; - case 'l': - fUpdateLevel ^= 1; - break; - case 'z': - fUseZeros ^= 1; - break; - case 'd': - fUseDcs ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); - return 1; - } - if ( Abc_NtkGetChoiceNum(pNtk) ) - { - fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); - return 1; - } - - if ( fUseDcs && nNodeSizeMax >= nConeSizeMax ) - { - fprintf( pErr, "For don't-care to work, containing cone should be larger than collapsed node.\n" ); - return 1; - } - - // modify the current network - if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ) ) - { - fprintf( pErr, "Refactoring has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: refactor [-N num] [-C num] [-lzdvh]\n" ); - fprintf( pErr, "\t performs technology-independent refactoring of the AIG\n" ); - fprintf( pErr, "\t-N num : the max support of the collapsed node [default = %d]\n", nNodeSizeMax ); - fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax ); - fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); - fprintf( pErr, "\t-d : toggle using don't-cares [default = %s]\n", fUseDcs? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int nCutsMax; - bool fUpdateLevel; - bool fUseZeros; - bool fVerbose; - extern int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutsMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nCutsMax = 5; - fUpdateLevel = 0; - fUseZeros = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Klzvh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); - goto usage; - } - nCutsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nCutsMax < 0 ) - goto usage; - break; - case 'l': - fUpdateLevel ^= 1; - break; - case 'z': - fUseZeros ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( nCutsMax < 4 || nCutsMax > CUT_SIZE_MAX ) - { - fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", 4, CUT_SIZE_MAX ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); - return 1; - } - if ( Abc_NtkGetChoiceNum(pNtk) ) - { - fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); - return 1; - } - - // modify the current network - if ( !Abc_NtkRestructure( pNtk, nCutsMax, fUpdateLevel, fUseZeros, fVerbose ) ) - { - fprintf( pErr, "Refactoring has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: restructure [-K num] [-lzvh]\n" ); - fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" ); - fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, nCutsMax ); - fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int RS_CUT_MIN = 4; - int RS_CUT_MAX = 16; - int c; - int nCutsMax; - int nNodesMax; - int nLevelsOdc; - bool fUpdateLevel; - bool fUseZeros; - bool fVerbose; - bool fVeryVerbose; - extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nLevelsOdc, bool fUpdateLevel, bool fVerbose, bool fVeryVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nCutsMax = 8; - nNodesMax = 1; - nLevelsOdc = 0; - fUpdateLevel = 1; - fUseZeros = 0; - fVerbose = 0; - fVeryVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KNFlzvwh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); - goto usage; - } - nCutsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nCutsMax < 0 ) - goto usage; - break; - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - nNodesMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nNodesMax < 0 ) - goto usage; - break; - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - nLevelsOdc = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLevelsOdc < 0 ) - goto usage; - break; - case 'l': - fUpdateLevel ^= 1; - break; - case 'z': - fUseZeros ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'w': - fVeryVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX ) - { - fprintf( pErr, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX ); - return 1; - } - if ( nNodesMax < 0 || nNodesMax > 3 ) - { - fprintf( pErr, "Can only resubstitute at most 3 nodes.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); - return 1; - } - if ( Abc_NtkGetChoiceNum(pNtk) ) - { - fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); - return 1; - } - - // modify the current network - if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) ) - { - fprintf( pErr, "Refactoring has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: resub [-K num] [-N num] [-F num] [-lzvwh]\n" ); - fprintf( pErr, "\t performs technology-independent restructuring of the AIG\n" ); - fprintf( pErr, "\t-K num : the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax ); - fprintf( pErr, "\t-N num : the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax ); - fprintf( pErr, "\t-F num : the number of fanout levels for ODC computation [default = %d]\n", nLevelsOdc ); - fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-w : toggle verbose printout of ODC computation [default = %s]\n", fVeryVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandRr( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c, Window; - int nFaninLevels; - int nFanoutLevels; - int fUseFanouts; - int fVerbose; - extern int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nFaninLevels = 3; - nFanoutLevels = 3; - fUseFanouts = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Wfvh" ) ) != EOF ) - { - switch ( c ) - { - case 'W': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-W\" should be followed by an integer.\n" ); - goto usage; - } - Window = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( Window < 0 ) - goto usage; - nFaninLevels = Window / 10; - nFanoutLevels = Window % 10; - break; - case 'f': - fUseFanouts ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command can only be applied to an AIG (run \"strash\").\n" ); - return 1; - } - if ( Abc_NtkGetChoiceNum(pNtk) ) - { - fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); - return 1; - } - - // modify the current network - if ( !Abc_NtkRR( pNtk, nFaninLevels, nFanoutLevels, fUseFanouts, fVerbose ) ) - { - fprintf( pErr, "Redundancy removal has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: rr [-W NM] [-fvh]\n" ); - fprintf( pErr, "\t removes combinational redundancies in the current network\n" ); - fprintf( pErr, "\t-W NM : window size: TFI (N) and TFO (M) logic levels [default = %d%d]\n", nFaninLevels, nFanoutLevels ); - fprintf( pErr, "\t-f : toggle RR w.r.t. fanouts [default = %s]\n", fUseFanouts? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, nLutSize; - int fCheck; - int fVerbose; - extern Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nLutSize = 12; - fCheck = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Kcvh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); - goto usage; - } - nLutSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLutSize < 0 ) - goto usage; - break; - case 'c': - fCheck ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Can only collapse a logic network or an AIG.\n" ); - return 1; - } - - // get the new network - if ( Abc_NtkIsStrash(pNtk) ) - pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose ); - else - { - pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose ); - Abc_NtkDelete( pNtk ); - } - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Cascade synthesis has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: cascade [-K ] [-cvh]\n" ); - fprintf( pErr, "\t performs LUT cascade synthesis for the current network\n" ); - fprintf( pErr, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize ); - fprintf( pErr, "\t-c : check equivalence after synthesis [default = %s]\n", fCheck? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\t \n"); - fprintf( pErr, " A lookup-table cascade is a programmable architecture developed by\n"); - fprintf( pErr, " Professor Tsutomu Sasao (sasao@cse.kyutech.ac.jp) at Kyushu Institute\n"); - fprintf( pErr, " of Technology. This work received Takeda Techno-Entrepreneurship Award:\n"); - fprintf( pErr, " http://www.lsi-cad.com/sasao/photo/takeda.html\n"); - fprintf( pErr, "\t \n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash( pNtk ) ) - { - fprintf( pErr, "This command is only applicable to strashed networks.\n" ); - return 1; - } - - // get the new network - pNtkRes = Abc_NtkToLogic( pNtk ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Converting to a logic network has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: logic [-h]\n" ); - fprintf( pErr, "\t transforms an AIG into a logic network with SOPs\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandComb( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "The network is already combinational.\n" ); - return 0; - } - - // get the new network - pNtkRes = Abc_NtkDup( pNtk ); - Abc_NtkMakeComb( pNtkRes ); - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: comb [-h]\n" ); - fprintf( pErr, "\t makes the current network combinational by replacing latches by PI/PO pairs\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - char Buffer[32]; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes; - int fDelete1, fDelete2; - char ** pArgvNew; - int nArgcNew; - int c; - int fCheck; - int fComb; - int nPartSize; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fComb = 1; - fCheck = 1; - nPartSize = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Pch" ) ) != EOF ) - { - switch ( c ) - { - case 'P': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); - goto usage; - } - nPartSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nPartSize < 0 ) - goto usage; - break; - case 'c': - fComb ^= 1; - break; - default: - goto usage; - } - } - - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) - return 1; - - // compute the miter - pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb, nPartSize ); - if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); - if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); - - // get the new network - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Miter computation has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - if ( nPartSize == 0 ) - strcpy( Buffer, "unused" ); - else - sprintf( Buffer, "%d", nPartSize ); - fprintf( pErr, "usage: miter [-P num] [-ch] \n" ); - fprintf( pErr, "\t computes the miter of the two circuits\n" ); - fprintf( pErr, "\t-P num : output partition size [default = %s]\n", Buffer ); - fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); - fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); - fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); - fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk;//, * pNtkRes; - int fComb; - int c; - extern int Abc_NtkDemiter( Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fComb ^= 1; - break; - default: - goto usage; - } - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "The network is not strashed.\n" ); - return 1; - } - - if ( Abc_NtkPoNum(pNtk) != 1 ) - { - fprintf( pErr, "The network is not a miter.\n" ); - return 1; - } - - if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) - { - fprintf( pErr, "The miter's PO is not an EXOR.\n" ); - return 1; - } - - // get the new network - if ( !Abc_NtkDemiter( pNtk ) ) - { - fprintf( pErr, "Demitering has failed.\n" ); - return 1; - } - // replace the current network -// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: demiter [-h]\n" ); - fprintf( pErr, "\t removes topmost EXOR from the miter to create two POs\n" ); -// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandOrPos( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk;//, * pNtkRes; - int fComb; - int c; - extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fComb ^= 1; - break; - default: - goto usage; - } - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "The network is not strashed.\n" ); - return 1; - } -/* - if ( Abc_NtkPoNum(pNtk) == 1 ) - { - fprintf( pErr, "The network already has one PO.\n" ); - return 1; - } -*/ -/* - if ( Abc_NtkLatchNum(pNtk) ) - { - fprintf( pErr, "The miter has latches. ORing is not performed.\n" ); - return 1; - } -*/ - // get the new network - if ( !Abc_NtkCombinePos( pNtk, 0 ) ) - { - fprintf( pErr, "ORing the POs has failed.\n" ); - return 1; - } - // replace the current network -// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: orpos [-h]\n" ); - fprintf( pErr, "\t creates single-output miter by ORing the POs of the current network\n" ); -// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAndPos( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk;//, * pNtkRes; - int fComb; - int c; - extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fComb ^= 1; - break; - default: - goto usage; - } - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "The network is not strashed.\n" ); - return 1; - } - - if ( Abc_NtkPoNum(pNtk) == 1 ) - { - fprintf( pErr, "The network already has one PO.\n" ); - return 1; - } - - if ( Abc_NtkLatchNum(pNtk) ) - { - fprintf( pErr, "The miter has latches. ORing is not performed.\n" ); - return 1; - } - - // get the new network - if ( !Abc_NtkCombinePos( pNtk, 1 ) ) - { - fprintf( pErr, "ANDing the POs has failed.\n" ); - return 1; - } - // replace the current network -// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: andpos [-h]\n" ); - fprintf( pErr, "\t creates single-output miter by ANDing the POs of the current network\n" ); -// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAppend( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtk2; - char * FileName; - int fComb; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fComb ^= 1; - break; - default: - goto usage; - } - } - - // get the second network - if ( argc != globalUtilOptind + 1 ) - { - fprintf( pErr, "The network to append is not given.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "The base network should be strashed for the appending to work.\n" ); - return 1; - } - - // read the second network - FileName = argv[globalUtilOptind]; - pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1 ); - if ( pNtk2 == NULL ) - return 1; - - // check if the second network is combinational - if ( Abc_NtkLatchNum(pNtk2) ) - { - fprintf( pErr, "The second network has latches. Appending does not work for such networks.\n" ); - return 1; - } - - // get the new network - if ( !Abc_NtkAppend( pNtk, pNtk2, 1 ) ) - { - Abc_NtkDelete( pNtk2 ); - fprintf( pErr, "Appending the networks failed.\n" ); - return 1; - } - Abc_NtkDelete( pNtk2 ); - // sweep dangling logic - Abc_AigCleanup( pNtk->pManFunc ); - // replace the current network -// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: append [-h] \n" ); - fprintf( pErr, "\t appends a combinational network on top of the current network\n" ); -// fprintf( pErr, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\t : file name with the second network\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkTemp, * pNtkRes; - int fInitial; - int nFrames; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fInitial = 0; - nFrames = 5; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Fih" ) ) != EOF ) - { - switch ( c ) - { - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - nFrames = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFrames <= 0 ) - goto usage; - break; - case 'i': - fInitial ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - // get the new network - if ( !Abc_NtkIsStrash(pNtk) ) - { - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - pNtkRes = Abc_NtkFrames( pNtkTemp, nFrames, fInitial ); - Abc_NtkDelete( pNtkTemp ); - } - else - pNtkRes = Abc_NtkFrames( pNtk, nFrames, fInitial ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Unrolling the network has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: frames [-F num] [-ih]\n" ); - fprintf( pErr, "\t unrolls the network for a number of time frames\n" ); - fprintf( pErr, "\t-F num : the number of frames to unroll [default = %d]\n", nFrames ); - fprintf( pErr, "\t-i : toggles initializing the first frame [default = %s]\n", fInitial? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int fDirect; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fDirect = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'd': - fDirect ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "Converting to SOP is possible only for logic networks.\n" ); - return 1; - } - if ( !Abc_NtkToSop(pNtk, fDirect) ) - { - fprintf( pErr, "Converting to SOP has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: sop [-dh]\n" ); - fprintf( pErr, "\t converts node functions to SOP\n" ); - fprintf( pErr, "\t-d : toggles using both phases or only positive [default = %s]\n", fDirect? "direct": "both" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "Converting to BDD is possible only for logic networks.\n" ); - return 1; - } - if ( Abc_NtkIsBddLogic(pNtk) ) - { - fprintf( pOut, "The logic network is already in the BDD form.\n" ); - return 0; - } - if ( !Abc_NtkToBdd(pNtk) ) - { - fprintf( pErr, "Converting to BDD has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: bdd [-h]\n" ); - fprintf( pErr, "\t converts node functions to BDD\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAig( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "Converting to AIG is possible only for logic networks.\n" ); - return 1; - } - if ( Abc_NtkIsAigLogic(pNtk) ) - { - fprintf( pOut, "The logic network is already in the AIG form.\n" ); - return 0; - } - if ( !Abc_NtkToAig(pNtk) ) - { - fprintf( pErr, "Converting to AIG has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: aig [-h]\n" ); - fprintf( pErr, "\t converts node functions to AIG\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandReorder( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fVerbose; - extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) - { - switch ( c ) - { - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - // get the new network - if ( !Abc_NtkIsBddLogic(pNtk) ) - { - fprintf( pErr, "Variable reordering is possible when node functions are BDDs (run \"bdd\").\n" ); - return 1; - } - Abc_NtkBddReorder( pNtk, fVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: reorder [-vh]\n" ); - fprintf( pErr, "\t reorders local functions of the nodes using sifting\n" ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr, * pFile; - Abc_Ntk_t * pNtk; - char * pFileName; - int c; - int fReverse; - int fVerbose; - extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ); - extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fReverse = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) - { - switch ( c ) - { - case 'r': - fReverse ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } -// if ( Abc_NtkLatchNum(pNtk) > 0 ) -// { -// printf( "Currently this procedure does not work for sequential networks.\n" ); -// return 1; -// } - - // if the var order file is given, implement this order - pFileName = NULL; - if ( argc == globalUtilOptind + 1 ) - { - pFileName = argv[globalUtilOptind]; - pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - fprintf( pErr, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName ); - return 1; - } - fclose( pFile ); - } - if ( pFileName ) - Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose ); - else - Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: order [-rvh] \n" ); - fprintf( pErr, "\t computes a good static CI variable order\n" ); - fprintf( pErr, "\t-r : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\t : (optional) file with the given variable order\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsBddLogic(pNtk) ) - { - fprintf( pErr, "Only a BDD logic network can be converted to MUXes.\n" ); - return 1; - } - - // get the new network - pNtkRes = Abc_NtkBddToMuxes( pNtk ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Converting to MUXes has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: muxes [-h]\n" ); - fprintf( pErr, "\t converts the current network by a network derived by\n" ); - fprintf( pErr, "\t replacing all nodes by DAGs isomorphic to the local BDDs\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fVerbose; - extern int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNet, bool fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) - { - switch ( c ) - { - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkLatchNum(pNtk) == 0 ) - { - fprintf( stdout, "The current network has no latches.\n" ); - return 0; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( stdout, "Extracting sequential don't-cares works only for AIGs (run \"strash\").\n" ); - return 0; - } - if ( !Abc_NtkExtractSequentialDcs( pNtk, fVerbose ) ) - { - fprintf( stdout, "Extracting sequential don't-cares has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: ext_seq_dcs [-vh]\n" ); - fprintf( pErr, "\t create EXDC network using unreachable states\n" ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandCone( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - Abc_Obj_t * pNode, * pNodeCo; - int c; - int fUseAllCis; - int fUseMffc; - int Output; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUseAllCis = 0; - fUseMffc = 0; - Output = -1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Omah" ) ) != EOF ) - { - switch ( c ) - { - case 'O': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-O\" should be followed by an integer.\n" ); - goto usage; - } - Output = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( Output < 0 ) - goto usage; - break; - case 'm': - fUseMffc ^= 1; - case 'a': - fUseAllCis ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Currently can only be applied to the logic network or an AIG.\n" ); - return 1; - } - - if ( argc > globalUtilOptind + 1 ) - { - fprintf( pErr, "Wrong number of auguments.\n" ); - goto usage; - } - - pNodeCo = NULL; - if ( argc == globalUtilOptind + 1 ) - { - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); - if ( pNode == NULL ) - { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); - return 1; - } - if ( fUseMffc ) - pNtkRes = Abc_NtkCreateMffc( pNtk, pNode, argv[globalUtilOptind] ); - else - pNtkRes = Abc_NtkCreateCone( pNtk, pNode, argv[globalUtilOptind], fUseAllCis ); - } - else - { - if ( Output == -1 ) - { - fprintf( pErr, "The node is not specified.\n" ); - return 1; - } - if ( Output >= Abc_NtkCoNum(pNtk) ) - { - fprintf( pErr, "The 0-based output number (%d) is larger than the number of outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) ); - return 1; - } - pNodeCo = Abc_NtkCo( pNtk, Output ); - if ( fUseMffc ) - pNtkRes = Abc_NtkCreateMffc( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo) ); - else - pNtkRes = Abc_NtkCreateCone( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo), fUseAllCis ); - } - if ( pNodeCo && Abc_ObjFaninC0(pNodeCo) ) - printf( "The extracted cone represents the complement function of the CO.\n" ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Writing the logic cone of one node has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: cone [-O num] [-amh] \n" ); - fprintf( pErr, "\t replaces the current network by one logic cone\n" ); - fprintf( pErr, "\t-a : toggle writing all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" ); - fprintf( pErr, "\t-m : toggle writing only MFFC or complete TFI cone [default = %s]\n", fUseMffc? "MFFC": "TFI cone" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\t-O num : (optional) the 0-based number of the CO to extract\n"); - fprintf( pErr, "\tname : (optional) the name of the node to extract\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandNode( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - Abc_Obj_t * pNode; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "Currently can only be applied to a logic network.\n" ); - return 1; - } - - if ( argc != globalUtilOptind + 1 ) - { - fprintf( pErr, "Wrong number of auguments.\n" ); - goto usage; - } - - pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); - if ( pNode == NULL ) - { - fprintf( pErr, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); - return 1; - } - - pNtkRes = Abc_NtkCreateFromNode( pNtk, pNode ); -// pNtkRes = Abc_NtkDeriveFromBdd( pNtk->pManFunc, pNode->pData, NULL, NULL ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Splitting one node has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: node [-h] \n" ); - fprintf( pErr, "\t replaces the current network by the network composed of one node\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\tname : the node name\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandTopmost( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, nLevels; - extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nLevels = 10; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) - { - switch ( c ) - { - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - nLevels = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLevels < 0 ) - goto usage; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); - return 0; - } - - if ( Abc_NtkLatchNum(pNtk) > 0 ) - { - fprintf( stdout, "Currently can only works for combinational circuits.\n" ); - return 0; - } - if ( Abc_NtkPoNum(pNtk) != 1 ) - { - fprintf( stdout, "Currently expects a single-output miter.\n" ); - return 0; - } - - pNtkRes = Abc_NtkTopmost( pNtk, nLevels ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "The command has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: topmost [-N num] [-h]\n" ); - fprintf( pErr, "\t replaces the current network by several of its topmost levels\n" ); - fprintf( pErr, "\t-N num : max number of levels [default = %d]\n", nLevels ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\tname : the node name\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandTrim( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, nLevels; - extern Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nLevels = 10; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) - { - switch ( c ) - { -/* - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - nLevels = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLevels < 0 ) - goto usage; - break; -*/ - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkIsStrash(pNtk) ) - { - fprintf( stdout, "Currently only works for logic circuits.\n" ); - return 0; - } - - pNtkRes = Abc_NtkTrim( pNtk ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "The command has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: trim [-h]\n" ); - fprintf( pErr, "\t removes POs fed by PIs and constants, and PIs w/o fanout\n" ); -// fprintf( pErr, "\t-N num : max number of levels [default = %d]\n", nLevels ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - Abc_NtkShortNames( pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: short_names [-h]\n" ); - fprintf( pErr, "\t replaces PI/PO/latch names by short char strings\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandExdcFree( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( pNtk->pExdc == NULL ) - { - fprintf( pErr, "The network has no EXDC.\n" ); - return 1; - } - - Abc_NtkDelete( pNtk->pExdc ); - pNtk->pExdc = NULL; - - // replace the current network - pNtkRes = Abc_NtkDup( pNtk ); - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: exdc_free [-h]\n" ); - fprintf( pErr, "\t frees the EXDC network of the current network\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandExdcGet( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( pNtk->pExdc == NULL ) - { - fprintf( pErr, "The network has no EXDC.\n" ); - return 1; - } - - // replace the current network - pNtkRes = Abc_NtkDup( pNtk->pExdc ); - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: exdc_get [-h]\n" ); - fprintf( pErr, "\t replaces the current network by the EXDC of the current network\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr, * pFile; - Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; - char * FileName; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( argc != globalUtilOptind + 1 ) - { - goto usage; - } - - // get the input file name - FileName = argv[globalUtilOptind]; - if ( (pFile = fopen( FileName, "r" )) == NULL ) - { - fprintf( pAbc->Err, "Cannot open input file \"%s\". ", FileName ); - if ( FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" ) ) - fprintf( pAbc->Err, "Did you mean \"%s\"?", FileName ); - fprintf( pAbc->Err, "\n" ); - return 1; - } - fclose( pFile ); - - // set the new network - pNtkNew = Io_Read( FileName, Io_ReadFileType(FileName), 1 ); - if ( pNtkNew == NULL ) - { - fprintf( pAbc->Err, "Reading network from file has failed.\n" ); - return 1; - } - - // replace the EXDC - if ( pNtk->pExdc ) - { - Abc_NtkDelete( pNtk->pExdc ); - pNtk->pExdc = NULL; - } - pNtkRes = Abc_NtkDup( pNtk ); - pNtkRes->pExdc = pNtkNew; - - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: exdc_set [-h] \n" ); - fprintf( pErr, "\t sets the network from file as EXDC for the current network\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\t : file with the new EXDC network\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Cut_Params_t Params, * pParams = &Params; - Cut_Man_t * pCutMan; - Cut_Oracle_t * pCutOracle; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fOracle; - extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); - extern void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * pCutOracle ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fOracle = 0; - memset( pParams, 0, sizeof(Cut_Params_t) ); - pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) - pParams->nKeepMax = 1000; // the max number of cuts kept at a node - pParams->fTruth = 0; // compute truth tables - pParams->fFilter = 1; // filter dominated cuts - pParams->fDrop = 0; // drop cuts on the fly - pParams->fDag = 0; // compute DAG cuts - pParams->fTree = 0; // compute tree cuts - pParams->fGlobal = 0; // compute global cuts - pParams->fLocal = 0; // compute local cuts - pParams->fFancy = 0; // compute something fancy - pParams->fMap = 0; // compute mapping delay - pParams->fVerbose = 0; // the verbosiness flag - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzmvoh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nVarsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nVarsMax < 0 ) - goto usage; - break; - case 'M': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nKeepMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nKeepMax < 0 ) - goto usage; - break; - case 't': - pParams->fTruth ^= 1; - break; - case 'f': - pParams->fFilter ^= 1; - break; - case 'd': - pParams->fDrop ^= 1; - break; - case 'x': - pParams->fDag ^= 1; - break; - case 'y': - pParams->fTree ^= 1; - break; - case 'g': - pParams->fGlobal ^= 1; - break; - case 'l': - pParams->fLocal ^= 1; - break; - case 'z': - pParams->fFancy ^= 1; - break; - case 'm': - pParams->fMap ^= 1; - break; - case 'v': - pParams->fVerbose ^= 1; - break; - case 'o': - fOracle ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Cut computation is available only for AIGs (run \"strash\").\n" ); - return 1; - } - if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) - { - fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); - return 1; - } - if ( pParams->fDag && pParams->fTree ) - { - fprintf( pErr, "Cannot compute both DAG cuts and tree cuts at the same time.\n" ); - return 1; - } - - if ( fOracle ) - pParams->fRecord = 1; - pCutMan = Abc_NtkCuts( pNtk, pParams ); - if ( fOracle ) - pCutOracle = Cut_OracleStart( pCutMan ); - Cut_ManStop( pCutMan ); - if ( fOracle ) - { - Abc_NtkCutsOracle( pNtk, pCutOracle ); - Cut_OracleStop( pCutOracle ); - } - return 0; - -usage: - fprintf( pErr, "usage: cut [-K num] [-M num] [-tfdxyzmvh]\n" ); - fprintf( pErr, "\t computes k-feasible cuts for the AIG\n" ); - fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); - fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); - fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); - fprintf( pErr, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" ); - fprintf( pErr, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" ); - fprintf( pErr, "\t-x : toggle computing only DAG cuts [default = %s]\n", pParams->fDag? "yes": "no" ); - fprintf( pErr, "\t-y : toggle computing only tree cuts [default = %s]\n", pParams->fTree? "yes": "no" ); - fprintf( pErr, "\t-g : toggle computing only global cuts [default = %s]\n", pParams->fGlobal? "yes": "no" ); - fprintf( pErr, "\t-l : toggle computing only local cuts [default = %s]\n", pParams->fLocal? "yes": "no" ); - fprintf( pErr, "\t-z : toggle fancy computations [default = %s]\n", pParams->fFancy? "yes": "no" ); - fprintf( pErr, "\t-m : toggle delay-oriented FPGA mapping [default = %s]\n", pParams->fMap? "yes": "no" ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Cut_Params_t Params, * pParams = &Params; - Cut_Man_t * pCutMan; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - memset( pParams, 0, sizeof(Cut_Params_t) ); - pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) - pParams->nKeepMax = 1000; // the max number of cuts kept at a node - pParams->fTruth = 0; // compute truth tables - pParams->fFilter = 1; // filter dominated cuts - pParams->fSeq = 1; // compute sequential cuts - pParams->fVerbose = 0; // the verbosiness flag - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KMtvh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nVarsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nVarsMax < 0 ) - goto usage; - break; - case 'M': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-M\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nKeepMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nKeepMax < 0 ) - goto usage; - break; - case 't': - pParams->fTruth ^= 1; - break; - case 'v': - pParams->fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } -/* - if ( !Abc_NtkIsSeq(pNtk) ) - { - fprintf( pErr, "Sequential cuts can be computed for sequential AIGs (run \"seq\").\n" ); - return 1; - } -*/ - if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) - { - fprintf( pErr, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); - return 1; - } - - pCutMan = Abc_NtkSeqCuts( pNtk, pParams ); - Cut_ManStop( pCutMan ); - return 0; - -usage: - fprintf( pErr, "usage: scut [-K num] [-M num] [-tvh]\n" ); - fprintf( pErr, "\t computes k-feasible cuts for the sequential AIG\n" ); - fprintf( pErr, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); - fprintf( pErr, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); - fprintf( pErr, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandEspresso( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fVerbose; - extern void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) - { - switch ( c ) - { - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "SOP minimization is possible for logic networks (run \"renode\").\n" ); - return 1; - } - Abc_NtkEspresso( pNtk, fVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: espresso [-vh]\n" ); - fprintf( pErr, "\t minimizes SOPs of the local functions using Espresso\n" ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int nVars; - int fAdder; - int fSorter; - int fMesh; - int fFpga; - int fVerbose; - char * FileName; - extern void Abc_GenAdder( char * pFileName, int nVars ); - extern void Abc_GenSorter( char * pFileName, int nVars ); - extern void Abc_GenMesh( char * pFileName, int nVars ); - extern void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars ); - - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nVars = 8; - fAdder = 0; - fSorter = 0; - fMesh = 0; - fFpga = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Nasmfvh" ) ) != EOF ) - { - switch ( c ) - { - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - nVars = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nVars < 0 ) - goto usage; - break; - case 'a': - fAdder ^= 1; - break; - case 's': - fSorter ^= 1; - break; - case 'm': - fMesh ^= 1; - break; - case 'f': - fFpga ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( argc != globalUtilOptind + 1 ) - { - goto usage; - } - - // get the input file name - FileName = argv[globalUtilOptind]; - if ( fAdder ) - Abc_GenAdder( FileName, nVars ); - else if ( fSorter ) - Abc_GenSorter( FileName, nVars ); - else if ( fMesh ) - Abc_GenMesh( FileName, nVars ); - else if ( fFpga ) - Abc_GenFpga( FileName, 4, 3, 10 ); -// Abc_GenFpga( FileName, 2, 2, 3 ); -// Abc_GenFpga( FileName, 3, 2, 5 ); - else - printf( "Type of circuit is not specified.\n" ); - return 0; - -usage: - fprintf( pErr, "usage: gen [-N] [-asmfvh] \n" ); - fprintf( pErr, "\t generates simple circuits\n" ); - fprintf( pErr, "\t-N num : the number of variables [default = %d]\n", nVars ); - fprintf( pErr, "\t-a : generate ripple-carry adder [default = %s]\n", fAdder? "yes": "no" ); - fprintf( pErr, "\t-s : generate a sorter [default = %s]\n", fSorter? "yes": "no" ); - fprintf( pErr, "\t-m : generate a mesh [default = %s]\n", fMesh? "yes": "no" ); - fprintf( pErr, "\t-f : generate a LUT FPGA structure [default = %s]\n", fFpga? "yes": "no" ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\t : output file name\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandXyz( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes;//, * pNtkTemp; - int c; - int nLutMax; - int nPlaMax; - int RankCost; - int fFastMode; - int fRewriting; - int fSynthesis; - int fVerbose; -// extern Abc_Ntk_t * Abc_NtkXyz( Abc_Ntk_t * pNtk, int nPlaMax, bool fEsop, bool fSop, bool fInvs, bool fVerbose ); - extern void * Abc_NtkPlayer( void * pNtk, int nLutMax, int nPlaMax, int RankCost, int fFastMode, int fRewriting, int fSynthesis, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nLutMax = 8; - nPlaMax = 128; - RankCost = 96000; - fFastMode = 1; - fRewriting = 0; - fSynthesis = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "LPRfrsvh" ) ) != EOF ) - { - switch ( c ) - { - case 'L': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - nLutMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLutMax < 0 ) - goto usage; - break; - case 'P': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); - goto usage; - } - nPlaMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nPlaMax < 0 ) - goto usage; - break; - case 'R': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); - goto usage; - } - RankCost = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( RankCost < 0 ) - goto usage; - break; - case 'f': - fFastMode ^= 1; - break; - case 'r': - fRewriting ^= 1; - break; - case 's': - fSynthesis ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Only works for strashed networks.\n" ); - return 1; - } -/* - if ( nLutMax < 2 || nLutMax > 12 || nPlaMax < 8 || nPlaMax > 128 ) - { - fprintf( pErr, "Incorrect LUT/PLA parameters.\n" ); - return 1; - } -*/ - // run the command -// pNtkRes = Abc_NtkXyz( pNtk, nPlaMax, 1, 0, fInvs, fVerbose ); -/* - if ( !Abc_NtkIsStrash(pNtk) ) - { - pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 ); - pNtkRes = Abc_NtkPlayer( pNtkTemp, nLutMax, nPlaMax, RankCost, fFastMode, fRewriting, fSynthesis, fVerbose ); - Abc_NtkDelete( pNtkTemp ); - } - else - pNtkRes = Abc_NtkPlayer( pNtk, nLutMax, nPlaMax, RankCost, fFastMode, fRewriting, fSynthesis, fVerbose ); -*/ - pNtkRes = NULL; - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: xyz [-L num] [-P num] [-R num] [-frsvh]\n" ); - fprintf( pErr, "\t specilized LUT/PLA decomposition\n" ); - fprintf( pErr, "\t-L num : maximum number of LUT inputs (2<=num<=8) [default = %d]\n", nLutMax ); - fprintf( pErr, "\t-P num : maximum number of PLA inputs/cubes (8<=num<=128) [default = %d]\n", nPlaMax ); - fprintf( pErr, "\t-R num : maximum are of one decomposition rank [default = %d]\n", RankCost ); - fprintf( pErr, "\t-f : toggle using fast LUT mapping mode [default = %s]\n", fFastMode? "yes": "no" ); - fprintf( pErr, "\t-r : toggle using one pass of AIG rewriting [default = %s]\n", fRewriting? "yes": "no" ); - fprintf( pErr, "\t-s : toggle using synthesis by AIG rewriting [default = %s]\n", fSynthesis? "yes": "no" ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDouble( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int nFrames; - int fVerbose; - extern Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nFrames = 50; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) - { - switch ( c ) - { - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - nFrames = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFrames < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsSopLogic(pNtk) ) - { - fprintf( pErr, "Only works for logic SOP networks.\n" ); - return 1; - } - - pNtkRes = Abc_NtkDouble( pNtk ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: double [-vh]\n" ); - fprintf( pErr, "\t puts together two parallel copies of the current network\n" ); -// fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int nLevels; - int fVerbose; -// extern Abc_Ntk_t * Abc_NtkNewAig( Abc_Ntk_t * pNtk ); -// extern Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ); -// extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ); -// extern int Pr_ManProofTest( char * pFileName ); - extern void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk ); - extern void Abc_NtkCompareCones( Abc_Ntk_t * pNtk ); - extern Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk ); - extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName ); - extern Abc_Ntk_t * Abc_NtkFilter( Abc_Ntk_t * pNtk ); - extern Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ); - extern Abc_Ntk_t * Abc_NtkPcmTest( Abc_Ntk_t * pNtk, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fVerbose = 0; - nLevels = 1000; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF ) - { - switch ( c ) - { - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - nLevels = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLevels < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } -/* - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkIsSeq(pNtk) ) - { - fprintf( pErr, "Only works for non-sequential networks.\n" ); - return 1; - } -*/ - -// Abc_NtkTestEsop( pNtk ); -// Abc_NtkTestSop( pNtk ); -// printf( "This command is currently not used.\n" ); - // run the command -// pNtkRes = Abc_NtkMiterForCofactors( pNtk, 0, 0, -1 ); -// pNtkRes = Abc_NtkNewAig( pNtk ); - -/* - pNtkRes = NULL; - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); -*/ - -// if ( Cut_CellIsRunning() ) -// Cut_CellDumpToFile(); -// else -// Cut_CellPrecompute(); -// Cut_CellLoad(); -/* - { - Abc_Ntk_t * pNtkRes; - extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); - pNtkRes = Abc_NtkTopmost( pNtk, nLevels ); - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - } -*/ -// Abc_NtkSimulteBuggyMiter( pNtk ); - -// Rwr_Temp(); -// Abc_MvExperiment(); -// Ivy_TruthTest(); - - -// Ivy_TruthEstimateNodesTest(); -/* - pNtkRes = Abc_NtkIvy( pNtk ); -// pNtkRes = Abc_NtkPlayer( pNtk, nLevels, 0 ); -// pNtkRes = NULL; - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); -*/ -// Abc_NtkMaxFlowTest( pNtk ); -// Pr_ManProofTest( "trace.cnf" ); - -// Abc_NtkCompareSupports( pNtk ); -// Abc_NtkCompareCones( pNtk ); -/* - { - extern Vec_Vec_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int fVerbose ); - Vec_Vec_t * vParts; - vParts = Abc_NtkPartitionSmart( pNtk, 1 ); - Vec_VecFree( vParts ); - } -*/ -// Abc_Ntk4VarTable( pNtk ); -// Dar_NtkGenerateArrays( pNtk ); -// Dar_ManDeriveCnfTest2(); -/* - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Network should be strashed. Command has failed.\n" ); - return 1; - } -*/ -/* - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); - return 0; - } -*/ - if ( Abc_NtkIsStrash(pNtk) ) - { - fprintf( stdout, "Currently only works for logic circuits.\n" ); - return 0; - } - -// pNtkRes = Abc_NtkDar( pNtk ); -// pNtkRes = Abc_NtkDarRetime( pNtk, nLevels, 1 ); - pNtkRes = Abc_NtkPcmTest( pNtk, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; -usage: - fprintf( pErr, "usage: test [-h]\n" ); - fprintf( pErr, "\t testbench for new procedures\n" ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandQuaVar( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, iVar, fUniv, fVerbose, RetValue; - extern int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - iVar = 0; - fUniv = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Iuvh" ) ) != EOF ) - { - switch ( c ) - { - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - iVar = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( iVar < 0 ) - goto usage; - break; - case 'u': - fUniv ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkGetChoiceNum( pNtk ) ) - { - fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" ); - return 1; - } - - // get the strashed network - pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); - RetValue = Abc_NtkQuantify( pNtkRes, fUniv, iVar, fVerbose ); - // clean temporary storage for the cofactors - Abc_NtkCleanData( pNtkRes ); - Abc_AigCleanup( pNtkRes->pManFunc ); - // check the result - if ( !RetValue ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: qvar [-I num] [-uvh]\n" ); - fprintf( pErr, "\t quantifies one variable using the AIG\n" ); - fprintf( pErr, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar ); - fprintf( pErr, "\t-u : toggle universal quantification [default = %s]\n", fUniv? "yes": "no" ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandQuaRel( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, iVar, fInputs, fVerbose; - extern Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - iVar = 0; - fInputs = 1; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Iqvh" ) ) != EOF ) - { - switch ( c ) - { - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - iVar = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( iVar < 0 ) - goto usage; - break; - case 'q': - fInputs ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkGetChoiceNum( pNtk ) ) - { - fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" ); - return 1; - } - if ( Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "This command works only for sequential circuits.\n" ); - return 1; - } - - // get the strashed network - if ( !Abc_NtkIsStrash(pNtk) ) - { - pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); - pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose ); - Abc_NtkDelete( pNtk ); - } - else - pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose ); - // check if the result is available - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: qrel [-qvh]\n" ); - fprintf( pErr, "\t computes transition relation of the sequential network\n" ); -// fprintf( pErr, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar ); - fprintf( pErr, "\t-q : perform quantification of inputs [default = %s]\n", fInputs? "yes": "no" ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandQuaReach( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, nIters, fVerbose; - extern Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtk, int nIters, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nIters = 256; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) - { - switch ( c ) - { - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - nIters = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nIters < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkGetChoiceNum( pNtk ) ) - { - fprintf( pErr, "This command cannot be applied to an AIG with choice nodes.\n" ); - return 1; - } - if ( !Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "This command works only for combinational transition relations.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - if ( Abc_NtkPoNum(pNtk) > 1 ) - { - fprintf( pErr, "The transition relation should have one output.\n" ); - return 1; - } - if ( Abc_NtkPiNum(pNtk) % 2 != 0 ) - { - fprintf( pErr, "The transition relation should have an even number of inputs.\n" ); - return 1; - } - - pNtkRes = Abc_NtkReachability( pNtk, nIters, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: qreach [-I num] [-vh]\n" ); - fprintf( pErr, "\t computes unreachable states using AIG-based quantification\n" ); - fprintf( pErr, "\t assumes that the current network is a transition relation\n" ); - fprintf( pErr, "\t assumes that the initial state is composed of all zeros\n" ); - fprintf( pErr, "\t-I num : the number of image computations to perform [default = %d]\n", nIters ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandIStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; - int c; - extern Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 ); - pNtkRes = Abc_NtkIvyStrash( pNtkTemp ); - Abc_NtkDelete( pNtkTemp ); - } - else - pNtkRes = Abc_NtkIvyStrash( pNtk ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: istrash [-h]\n" ); - fprintf( pErr, "\t perform sequential structural hashing\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandICut( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c, nInputs; - extern void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nInputs = 5; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Kh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); - goto usage; - } - nInputs = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nInputs < 0 ) - goto usage; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - - Abc_NtkIvyCuts( pNtk, nInputs ); - return 0; - -usage: - fprintf( pErr, "usage: icut [-K num] [-h]\n" ); - fprintf( pErr, "\t computes sequential cuts of the given size\n" ); - fprintf( pErr, "\t-K num : the number of cut inputs (2 <= num <= 6) [default = %d]\n", nInputs ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandIRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, fUpdateLevel, fUseZeroCost, fVerbose; - extern Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUpdateLevel = 1; - fUseZeroCost = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) - { - switch ( c ) - { - case 'l': - fUpdateLevel ^= 1; - break; - case 'z': - fUseZeroCost ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - - pNtkRes = Abc_NtkIvyRewrite( pNtk, fUpdateLevel, fUseZeroCost, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: irw [-lzvh]\n" ); - fprintf( pErr, "\t perform combinational AIG rewriting\n" ); - fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - Dar_RwrPar_t Pars, * pPars = &Pars; - int c; - - extern Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Dar_ManDefaultRwrParams( pPars ); - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CNflzvwh" ) ) != EOF ) - { - switch ( c ) - { - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nCutsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nCutsMax < 0 ) - goto usage; - break; - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nSubgMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nSubgMax < 0 ) - goto usage; - break; - case 'f': - pPars->fFanout ^= 1; - break; - case 'l': - pPars->fUpdateLevel ^= 1; - break; - case 'z': - pPars->fUseZeros ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'w': - pPars->fVeryVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - pNtkRes = Abc_NtkDRewrite( pNtk, pPars ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: drw [-C num] [-N num] [-flzvwh]\n" ); - fprintf( pErr, "\t performs combinational AIG rewriting\n" ); - fprintf( pErr, "\t-C num : the max number of cuts at a node [default = %d]\n", pPars->nCutsMax ); - fprintf( pErr, "\t-N num : the max number of subgraphs tried [default = %d]\n", pPars->nSubgMax ); - fprintf( pErr, "\t-f : toggle representing fanouts [default = %s]\n", pPars->fFanout? "yes": "no" ); - fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - Dar_RefPar_t Pars, * pPars = &Pars; - int c; - - extern Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Dar_ManDefaultRefParams( pPars ); - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "MKCelzvwh" ) ) != EOF ) - { - switch ( c ) - { - case 'M': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nMffcMin = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nMffcMin < 0 ) - goto usage; - break; - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nLeafMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nLeafMax < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - pPars->nCutsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nCutsMax < 0 ) - goto usage; - break; - case 'e': - pPars->fExtend ^= 1; - break; - case 'l': - pPars->fUpdateLevel ^= 1; - break; - case 'z': - pPars->fUseZeros ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'w': - pPars->fVeryVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - if ( pPars->nLeafMax < 4 || pPars->nLeafMax > 15 ) - { - fprintf( pErr, "This command only works for cut sizes 4 <= K <= 15.\n" ); - return 1; - } - pNtkRes = Abc_NtkDRefactor( pNtk, pPars ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: drf [-M num] [-K num] [-C num] [-elzvwh]\n" ); - fprintf( pErr, "\t performs combinational AIG refactoring\n" ); - fprintf( pErr, "\t-M num : the min MFFC size to attempt refactoring [default = %d]\n", pPars->nMffcMin ); - fprintf( pErr, "\t-K num : the max number of cuts leaves [default = %d]\n", pPars->nLeafMax ); - fprintf( pErr, "\t-C num : the max number of cuts to try at a node [default = %d]\n", pPars->nCutsMax ); - fprintf( pErr, "\t-e : toggle extending tbe cut below MFFC [default = %s]\n", pPars->fExtend? "yes": "no" ); - fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDCompress2( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int fBalance, fVerbose, fUpdateLevel, c; - - extern Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fBalance = 0; - fVerbose = 0; - fUpdateLevel = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "blvh" ) ) != EOF ) - { - switch ( c ) - { - case 'b': - fBalance ^= 1; - break; - case 'l': - fUpdateLevel ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - pNtkRes = Abc_NtkDCompress2( pNtk, fBalance, fUpdateLevel, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: dcompress2 [-blvh]\n" ); - fprintf( pErr, "\t performs combinational AIG optimization\n" ); - fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); - fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int fBalance, fVerbose, fUpdateLevel, c; - - extern Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fBalance = 1; - fUpdateLevel = 1; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "blvh" ) ) != EOF ) - { - switch ( c ) - { - case 'b': - fBalance ^= 1; - break; - case 'l': - fUpdateLevel ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - pNtkRes = Abc_NtkDChoice( pNtk, fBalance, fUpdateLevel, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: dchoice [-blvh]\n" ); - fprintf( pErr, "\t performs partitioned choicing using a new AIG package\n" ); - fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); - fprintf( pErr, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDrwsat( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int fBalance, fVerbose, c; - - extern Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fBalance = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF ) - { - switch ( c ) - { - case 'b': - fBalance ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - pNtkRes = Abc_NtkDrwsat( pNtk, fBalance, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: drwsat [-bvh]\n" ); - fprintf( pErr, "\t performs combinational AIG optimization for SAT\n" ); - fprintf( pErr, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandIRewriteSeq( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, fUpdateLevel, fUseZeroCost, fVerbose; - extern Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUpdateLevel = 0; - fUseZeroCost = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) - { - switch ( c ) - { - case 'l': - fUpdateLevel ^= 1; - break; - case 'z': - fUseZeroCost ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - - pNtkRes = Abc_NtkIvyRewriteSeq( pNtk, fUseZeroCost, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: irws [-zvh]\n" ); - fprintf( pErr, "\t perform sequential AIG rewriting\n" ); -// fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandIResyn( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, fUpdateLevel, fVerbose; - extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUpdateLevel = 1; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) - { - switch ( c ) - { - case 'l': - fUpdateLevel ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - - pNtkRes = Abc_NtkIvyResyn( pNtk, fUpdateLevel, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: iresyn [-lvh]\n" ); - fprintf( pErr, "\t performs combinational resynthesis\n" ); - fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandISat( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, fUpdateLevel, fVerbose; - int nConfLimit; - - extern Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nConfLimit = 100000; - fUpdateLevel = 1; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Clzvh" ) ) != EOF ) - { - switch ( c ) - { - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nConfLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nConfLimit < 0 ) - goto usage; - break; - case 'l': - fUpdateLevel ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - - pNtkRes = Abc_NtkIvySat( pNtk, nConfLimit, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: isat [-C num] [-vh]\n" ); - fprintf( pErr, "\t tries to prove the miter constant 0\n" ); - fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); -// fprintf( pErr, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandIFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, fProve, fVerbose, fDoSparse; - int nConfLimit; - - extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nConfLimit = 100; - fDoSparse = 0; - fProve = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Cspvh" ) ) != EOF ) - { - switch ( c ) - { - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nConfLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nConfLimit < 0 ) - goto usage; - break; - case 's': - fDoSparse ^= 1; - break; - case 'p': - fProve ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - - pNtkRes = Abc_NtkIvyFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: ifraig [-C num] [-spvh]\n" ); - fprintf( pErr, "\t performs fraiging using a new method\n" ); - fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); - fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" ); - fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, nConfLimit, fDoSparse, fProve, fSpeculate, fChoicing, fVerbose; - - extern Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nConfLimit = 100; - fDoSparse = 1; - fProve = 0; - fSpeculate = 0; - fChoicing = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Csprcvh" ) ) != EOF ) - { - switch ( c ) - { - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nConfLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nConfLimit < 0 ) - goto usage; - break; - case 's': - fDoSparse ^= 1; - break; - case 'p': - fProve ^= 1; - break; - case 'r': - fSpeculate ^= 1; - break; - case 'c': - fChoicing ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - - pNtkRes = Abc_NtkDarFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fSpeculate, fChoicing, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: dfraig [-C num] [-sprcvh]\n" ); - fprintf( pErr, "\t performs fraiging using a new method\n" ); - fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); - fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" ); - fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" ); - fprintf( pErr, "\t-r : toggle speculative reduction [default = %s]\n", fSpeculate? "yes": "no" ); - fprintf( pErr, "\t-c : toggle accumulation of choices [default = %s]\n", fChoicing? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandCSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, nCutsMax, nLeafMax, fVerbose; - - extern Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nCutsMax = 8; - nLeafMax = 6; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CKvh" ) ) != EOF ) - { - switch ( c ) - { - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nCutsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nCutsMax < 0 ) - goto usage; - break; - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); - goto usage; - } - nLeafMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLeafMax < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( nCutsMax < 2 ) - { - fprintf( pErr, "The number of cuts cannot be less than 2.\n" ); - return 1; - } - - if ( nLeafMax < 3 || nLeafMax > 16 ) - { - fprintf( pErr, "The number of leaves is infeasible.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - - pNtkRes = Abc_NtkCSweep( pNtk, nCutsMax, nLeafMax, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: csweep [-C num] [-K num] [-vh]\n" ); - fprintf( pErr, "\t performs cut sweeping using a new method\n" ); - fprintf( pErr, "\t-C num : limit on the number of cuts (C >= 2) [default = %d]\n", nCutsMax ); - fprintf( pErr, "\t-K num : limit on the cut size (3 <= K <= 16) [default = %d]\n", nLeafMax ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Prove_Params_t Params, * pParams = &Params; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkTemp; - int c, clk, RetValue; - - extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Prove_ParamsSetDefault( pParams ); - pParams->fUseRewriting = 1; - pParams->fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) - { - switch ( c ) - { - case 'r': - pParams->fUseRewriting ^= 1; - break; - case 'v': - pParams->fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - clk = clock(); - - if ( Abc_NtkIsStrash(pNtk) ) - pNtkTemp = Abc_NtkDup( pNtk ); - else - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - - RetValue = Abc_NtkIvyProve( &pNtkTemp, pParams ); - - // verify that the pattern is correct - if ( RetValue == 0 ) - { - int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel ); - if ( pSimInfo[0] != 1 ) - printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); - free( pSimInfo ); - } - - if ( RetValue == -1 ) - printf( "UNDECIDED " ); - else if ( RetValue == 0 ) - printf( "SATISFIABLE " ); - else - printf( "UNSATISFIABLE " ); - //printf( "\n" ); - - PRT( "Time", clock() - clk ); - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp ); - return 0; - -usage: - fprintf( pErr, "usage: iprove [-rvh]\n" ); - fprintf( pErr, "\t performs CEC using a new method\n" ); - fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", pParams->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandHaig( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, fUseZeroCost, fVerbose, nIters; - extern Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nIters = 2; - fUseZeroCost = 0; - fVerbose = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Izvh" ) ) != EOF ) - { - switch ( c ) - { - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); - goto usage; - } - nIters = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nIters < 0 ) - goto usage; - break; - case 'z': - fUseZeroCost ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for strashed networks.\n" ); - return 1; - } - - pNtkRes = Abc_NtkIvyHaig( pNtk, nIters, fUseZeroCost, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: haig [-Izvh]\n" ); - fprintf( pErr, "\t prints HAIG stats after sequential rewriting\n" ); - fprintf( pErr, "\t-I num : the number of rewriting iterations [default = %d]\n", nIters ); - fprintf( pErr, "\t-z : toggle zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandMini( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - extern Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Only works for combinatinally strashed AIG networks.\n" ); - return 1; - } - - pNtkRes = Abc_NtkMiniBalance( pNtk ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Command has failed.\n" ); - return 0; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: mini [-h]\n" ); - fprintf( pErr, "\t perform balancing using new package\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandBmc( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int nFrames; - int fInit; - int fVerbose; - - extern void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nFrames = 5; - fInit = 0; - fVerbose = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Kivh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); - goto usage; - } - nFrames = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFrames < 0 ) - goto usage; - break; - case 'i': - fInit ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkIsStrash(pNtk) ) - Abc_NtkBmc( pNtk, nFrames, fInit, fVerbose ); - else - { - pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); - Abc_NtkBmc( pNtk, nFrames, fInit, fVerbose ); - Abc_NtkDelete( pNtk ); - } - return 0; - -usage: - fprintf( pErr, "usage: _bmc [-K num] [-ivh]\n" ); - fprintf( pErr, "\t perform bounded model checking\n" ); - fprintf( pErr, "\t-K num : number of time frames [default = %d]\n", nFrames ); - fprintf( pErr, "\t-i : toggle initialization of the first frame [default = %s]\n", fInit? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int nPars; - int fVerbose; - - extern void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nPars = -1; - fVerbose = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Pvh" ) ) != EOF ) - { - switch ( c ) - { - case 'P': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); - goto usage; - } - nPars = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nPars < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "Works only for combinational networks.\n" ); - return 1; - } - if ( Abc_NtkPoNum(pNtk) != 1 ) - { - fprintf( pErr, "The miter should have one primary output.\n" ); - return 1; - } - if ( !(nPars > 0 && nPars < Abc_NtkPiNum(pNtk)) ) - { - fprintf( pErr, "The number of paramter variables is invalid (should be > 0 and < PI num).\n" ); - return 1; - } - if ( Abc_NtkIsStrash(pNtk) ) - Abc_NtkQbf( pNtk, nPars, fVerbose ); - else - { - pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); - Abc_NtkQbf( pNtk, nPars, fVerbose ); - Abc_NtkDelete( pNtk ); - } - return 0; - -usage: - fprintf( pErr, "usage: qbf [-P num] [-vh]\n" ); - fprintf( pErr, "\t solves a quantified boolean formula problem EpVxM(p,x)\n" ); - fprintf( pErr, "\t-P num : number of paramters (should be the first PIs) [default = %d]\n", nPars ); - fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - char Buffer[100]; - Fraig_Params_t Params, * pParams = &Params; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int fAllNodes; - int fExdc; - int c; - int fPartition = 0; - extern void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fExdc = 0; - fAllNodes = 0; - memset( pParams, 0, sizeof(Fraig_Params_t) ); - pParams->nPatsRand = 2048; // the number of words of random simulation info - pParams->nPatsDyna = 2048; // the number of words of dynamic simulation info - pParams->nBTLimit = 100; // the max number of backtracks to perform - pParams->fFuncRed = 1; // performs only one level hashing - pParams->fFeedBack = 1; // enables solver feedback - pParams->fDist1Pats = 1; // enables distance-1 patterns - pParams->fDoSparse = 1; // performs equiv tests for sparse functions - pParams->fChoicing = 0; // enables recording structural choices - pParams->fTryProve = 0; // tries to solve the final miter - pParams->fVerbose = 0; // the verbosiness flag - pParams->fVerboseP = 0; // the verbosiness flag - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "RDCrscptvaeh" ) ) != EOF ) - { - switch ( c ) - { - case 'R': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-R\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nPatsRand = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nPatsRand < 0 ) - goto usage; - break; - case 'D': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-D\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nPatsDyna = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nPatsDyna < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nBTLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nBTLimit < 0 ) - goto usage; - break; - - case 'r': - pParams->fFuncRed ^= 1; - break; - case 's': - pParams->fDoSparse ^= 1; - break; - case 'c': - pParams->fChoicing ^= 1; - break; - case 'p': - pParams->fTryProve ^= 1; - break; - case 'v': - pParams->fVerbose ^= 1; - break; - case 't': - fPartition ^= 1; - break; - case 'a': - fAllNodes ^= 1; - break; - case 'e': - fExdc ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Can only fraig a logic network or an AIG.\n" ); - return 1; - } - - // report the proof - pParams->fVerboseP = pParams->fTryProve; - - // get the new network - if ( fPartition ) - { - pNtkRes = Abc_NtkDup( pNtk ); - if ( Abc_NtkIsStrash(pNtk) ) - Abc_NtkFraigPartitionedTime( pNtk, &Params ); - else - { - pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 ); - Abc_NtkFraigPartitionedTime( pNtk, &Params ); - Abc_NtkDelete( pNtk ); - } - } - else - { - if ( Abc_NtkIsStrash(pNtk) ) - pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc ); - else - { - pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 ); - pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc ); - Abc_NtkDelete( pNtk ); - } - } - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Fraiging has failed.\n" ); - return 1; - } - - if ( pParams->fTryProve ) // report the result - Abc_NtkMiterReport( pNtkRes ); - - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - sprintf( Buffer, "%d", pParams->nBTLimit ); - fprintf( pErr, "usage: fraig [-R num] [-D num] [-C num] [-rscpvtah]\n" ); - fprintf( pErr, "\t transforms a logic network into a functionally reduced AIG\n" ); - fprintf( pErr, "\t-R num : number of random patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsRand ); - fprintf( pErr, "\t-D num : number of systematic patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsDyna ); - fprintf( pErr, "\t-C num : number of backtracks for one SAT problem [default = %s]\n", pParams->nBTLimit==-1? "infinity" : Buffer ); - fprintf( pErr, "\t-r : toggle functional reduction [default = %s]\n", pParams->fFuncRed? "yes": "no" ); - fprintf( pErr, "\t-s : toggle considering sparse functions [default = %s]\n", pParams->fDoSparse? "yes": "no" ); - fprintf( pErr, "\t-c : toggle accumulation of choices [default = %s]\n", pParams->fChoicing? "yes": "no" ); - fprintf( pErr, "\t-p : toggle proving the miter outputs [default = %s]\n", pParams->fTryProve? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", pParams->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" ); - fprintf( pErr, "\t-a : toggle between all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "dfs" ); - fprintf( pErr, "\t-t : toggle using partitioned representation [default = %s]\n", fPartition? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFraigTrust( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int fDuplicate; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fDuplicate = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'd': - fDuplicate ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - // get the new network - pNtkRes = Abc_NtkFraigTrust( pNtk ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Fraiging in the trust mode has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: fraig_trust [-h]\n" ); - fprintf( pErr, "\t transforms the current network into an AIG assuming it is FRAIG with choices\n" ); -// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fDuplicate; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fDuplicate = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'd': - fDuplicate ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - // get the new network - if ( !Abc_NtkFraigStore( pNtk ) ) - { - fprintf( pErr, "Fraig storing has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: fraig_store [-h]\n" ); - fprintf( pErr, "\t saves the current network in the AIG database\n" ); -// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFraigRestore( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int fDuplicate; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fDuplicate = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'd': - fDuplicate ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - // get the new network - pNtkRes = Abc_NtkFraigRestore(); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Fraig restoring has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: fraig_restore [-h]\n" ); - fprintf( pErr, "\t makes the current network by fraiging the AIG database\n" ); -// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fDuplicate; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fDuplicate = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'd': - fDuplicate ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - Abc_NtkFraigStoreClean(); - return 0; - -usage: - fprintf( pErr, "usage: fraig_clean [-h]\n" ); - fprintf( pErr, "\t cleans the internal FRAIG storage\n" ); -// fprintf( pErr, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fUseInv; - int fExdc; - int fVerbose; - int fVeryVerbose; - extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fUseInv = 1; - fExdc = 0; - fVerbose = 0; - fVeryVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ievwh" ) ) != EOF ) - { - switch ( c ) - { - case 'i': - fUseInv ^= 1; - break; - case 'e': - fExdc ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'w': - fVeryVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Cannot sweep AIGs (use \"fraig\").\n" ); - return 1; - } - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "Transform the current network into a logic network.\n" ); - return 1; - } - // modify the current network - if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fExdc, fVerbose, fVeryVerbose ) ) - { - fprintf( pErr, "Sweeping has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: fraig_sweep [-evwh]\n" ); - fprintf( pErr, "\t performs technology-dependent sweep\n" ); - fprintf( pErr, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-w : prints equivalence class information [default = %s]\n", fVeryVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFraigDress( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - char * pFileName; - int c; - int fVerbose; - extern void Abc_NtkDress( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) - { - switch ( c ) - { - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for logic networks.\n" ); - return 1; - } - if ( argc != globalUtilOptind && argc != globalUtilOptind + 1 ) - goto usage; - if ( argc == globalUtilOptind && Abc_NtkSpec(pNtk) == NULL ) - { - fprintf( pErr, "The current network has no spec.\n" ); - return 1; - } - // get the input file name - pFileName = (argc == globalUtilOptind + 1) ? argv[globalUtilOptind] : Abc_NtkSpec(pNtk); - // modify the current network - Abc_NtkDress( pNtk, pFileName, fVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: dress [-vh] \n" ); - fprintf( pErr, "\t transfers internal node names from file to the current network\n" ); - fprintf( pErr, "\t : network with names (if not given, the current network spec is used)\n" ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandHaigStart( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); - return 0; - } - Abc_NtkHaigStart( pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: haig_start [-h]\n" ); - fprintf( pErr, "\t starts constructive accumulation of combinational choices\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandHaigStop( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); - return 0; - } - Abc_NtkHaigStop( pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: haig_stop [-h]\n" ); - fprintf( pErr, "\t cleans the internal storage for combinational choices\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandHaigUse( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); - return 0; - } - // get the new network - pNtkRes = Abc_NtkHaigUse( pNtk ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Transforming internal storage into AIG with choices has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: haig_use [-h]\n" ); - fprintf( pErr, "\t transforms internal storage into an AIG with choices\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandRecStart( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int nVars; - int nCuts; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nVars = 4; - nCuts = 8; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); - goto usage; - } - nVars = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nVars < 1 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nCuts = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nCuts < 1 ) - goto usage; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( !(nVars >= 3 && nVars <= 16) ) - { - fprintf( pErr, "The range of allowed values is 3 <= K <= 16.\n" ); - return 0; - } - if ( Abc_NtkRecIsRunning() ) - { - fprintf( pErr, "The AIG subgraph recording is already started.\n" ); - return 0; - } - if ( pNtk && !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for AIGs; run strashing (\"st\").\n" ); - return 0; - } - Abc_NtkRecStart( pNtk, nVars, nCuts ); - return 0; - -usage: - fprintf( pErr, "usage: rec_start [-K num] [-C num] [-h]\n" ); - fprintf( pErr, "\t starts recording AIG subgraphs (should be called for\n" ); - fprintf( pErr, "\t an empty network or after reading in a previous record)\n" ); - fprintf( pErr, "\t-K num : the largest number of inputs [default = %d]\n", nVars ); - fprintf( pErr, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCuts ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandRecStop( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( !Abc_NtkRecIsRunning() ) - { - fprintf( pErr, "This command works only after calling \"rec_start\".\n" ); - return 0; - } - Abc_NtkRecStop(); - return 0; - -usage: - fprintf( pErr, "usage: rec_stop [-h]\n" ); - fprintf( pErr, "\t cleans the internal storage for AIG subgraphs\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandRecAdd( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works for AIGs.\n" ); - return 0; - } - if ( !Abc_NtkRecIsRunning() ) - { - fprintf( pErr, "This command works for AIGs after calling \"rec_start\".\n" ); - return 0; - } - Abc_NtkRecAdd( pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: rec_add [-h]\n" ); - fprintf( pErr, "\t adds subgraphs from the current network to the set\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandRecPs( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( !Abc_NtkRecIsRunning() ) - { - fprintf( pErr, "This command works for AIGs only after calling \"rec_start\".\n" ); - return 0; - } - Abc_NtkRecPs(); - return 0; - -usage: - fprintf( pErr, "usage: rec_ps [-h]\n" ); - fprintf( pErr, "\t prints statistics about the recorded AIG subgraphs\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandRecUse( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( !Abc_NtkRecIsRunning() ) - { - fprintf( pErr, "This command works for AIGs only after calling \"rec_start\".\n" ); - return 0; - } - // get the new network - pNtkRes = Abc_NtkRecUse(); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Transforming internal AIG subgraphs into an AIG with choices has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: rec_use [-h]\n" ); - fprintf( pErr, "\t transforms internal storage into an AIG with choices\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - char Buffer[100]; - double DelayTarget; - int fRecovery; - int fSweep; - int fSwitching; - int fVerbose; - int c; - extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int fSwitching, int fVerbose ); - extern bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - DelayTarget =-1; - fRecovery = 1; - fSweep = 1; - fSwitching = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Daspvh" ) ) != EOF ) - { - switch ( c ) - { - case 'D': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); - goto usage; - } - DelayTarget = (float)atof(argv[globalUtilOptind]); - globalUtilOptind++; - if ( DelayTarget <= 0.0 ) - goto usage; - break; - case 'a': - fRecovery ^= 1; - break; - case 's': - fSweep ^= 1; - break; - case 'p': - fSwitching ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - if ( pNtk == NULL ) - { - fprintf( pErr, "Strashing before mapping has failed.\n" ); - return 1; - } - pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); - Abc_NtkDelete( pNtkRes ); - if ( pNtk == NULL ) - { - fprintf( pErr, "Balancing before mapping has failed.\n" ); - return 1; - } - fprintf( pOut, "The network was strashed and balanced before mapping.\n" ); - // get the new network - pNtkRes = Abc_NtkMap( pNtk, DelayTarget, fRecovery, fSwitching, fVerbose ); - if ( pNtkRes == NULL ) - { - Abc_NtkDelete( pNtk ); - fprintf( pErr, "Mapping has failed.\n" ); - return 1; - } - Abc_NtkDelete( pNtk ); - } - else - { - // get the new network - pNtkRes = Abc_NtkMap( pNtk, DelayTarget, fRecovery, fSwitching, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Mapping has failed.\n" ); - return 1; - } - } - - if ( fSweep ) - Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 ); - - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - if ( DelayTarget == -1 ) - sprintf( Buffer, "not used" ); - else - sprintf( Buffer, "%.3f", DelayTarget ); - fprintf( pErr, "usage: map [-D float] [-aspvh]\n" ); - fprintf( pErr, "\t performs standard cell mapping of the current network\n" ); - fprintf( pErr, "\t-D float : sets the global required times [default = %s]\n", Buffer ); - fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); - fprintf( pErr, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" ); - fprintf( pErr, "\t-p : optimizes power by minimizing switching [default = %s]\n", fSwitching? "yes": "no" ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandUnmap( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkHasMapping(pNtk) ) - { - fprintf( pErr, "Cannot unmap the network that is not mapped.\n" ); - return 1; - } - - // get the new network - if ( !Abc_NtkMapToSop( pNtk ) ) - { - fprintf( pErr, "Unmapping has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: unmap [-h]\n" ); - fprintf( pErr, "\t replaces the library gates by the logic nodes represented using SOPs\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandAttach( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsSopLogic(pNtk) ) - { - fprintf( pErr, "Can only attach gates if the nodes have SOP representations.\n" ); - return 1; - } - - // get the new network - if ( !Abc_NtkAttach( pNtk ) ) - { - fprintf( pErr, "Attaching gates has failed.\n" ); - return 1; - } - return 0; - -usage: - fprintf( pErr, "usage: attach [-h]\n" ); - fprintf( pErr, "\t replaces the SOP functions by the gates from the library\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSuperChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Superchoicing works only for the AIG representation (run \"strash\").\n" ); - return 1; - } - - // get the new network - pNtkRes = Abc_NtkSuperChoice( pNtk ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Superchoicing has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: sc [-h]\n" ); - fprintf( pErr, "\t performs superchoicing\n" ); - fprintf( pErr, "\t (accumulate: \"r file.blif; rsup; b; sc; f -ac; wb file_sc.blif\")\n" ); - fprintf( pErr, "\t (map without supergate library: \"r file_sc.blif; ft; map\")\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSuperChoiceLut( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int nLutSize; - int nCutSizeMax; - int fVerbose; - extern int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fVerbose = 1; - nLutSize = 4; - nCutSizeMax = 10; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KNh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); - goto usage; - } - nLutSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLutSize < 0 ) - goto usage; - break; - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by a positive integer.\n" ); - goto usage; - } - nCutSizeMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nCutSizeMax < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Superchoicing works only for the AIG representation (run \"strash\").\n" ); - return 1; - } - - // convert the network into the SOP network - pNtkRes = Abc_NtkToLogic( pNtk ); - - // get the new network - if ( !Abc_NtkSuperChoiceLut( pNtkRes, nLutSize, nCutSizeMax, fVerbose ) ) - { - Abc_NtkDelete( pNtkRes ); - fprintf( pErr, "Superchoicing has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: scl [-K num] [-N num] [-vh]\n" ); - fprintf( pErr, "\t performs superchoicing for K-LUTs\n" ); - fprintf( pErr, "\t (accumulate: \"r file.blif; b; scl; f -ac; wb file_sc.blif\")\n" ); - fprintf( pErr, "\t (FPGA map: \"r file_sc.blif; ft; read_lut lutlibK; fpga\")\n" ); - fprintf( pErr, "\t-K num : the number of LUT inputs [default = %d]\n", nLutSize ); - fprintf( pErr, "\t-N num : the max size of the cut [default = %d]\n", nCutSizeMax ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - char Buffer[100]; - char LutSize[100]; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int fRecovery; - int fSwitching; - int fLatchPaths; - int fVerbose; - int nLutSize; - float DelayTarget; - - extern Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fRecovery = 1; - fSwitching = 0; - fLatchPaths = 0; - fVerbose = 0; - DelayTarget =-1; - nLutSize =-1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "aplvhDK" ) ) != EOF ) - { - switch ( c ) - { - case 'a': - fRecovery ^= 1; - break; - case 'p': - fSwitching ^= 1; - break; - case 'l': - fLatchPaths ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - case 'D': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); - goto usage; - } - DelayTarget = (float)atof(argv[globalUtilOptind]); - globalUtilOptind++; - if ( DelayTarget <= 0.0 ) - goto usage; - break; - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); - goto usage; - } - nLutSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLutSize < 0 ) - goto usage; - break; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - // create the new LUT library - if ( nLutSize >= 3 && nLutSize <= 10 ) - Fpga_SetSimpleLutLib( nLutSize ); -/* - else - { - fprintf( pErr, "Cannot perform FPGA mapping with LUT size %d.\n", nLutSize ); - return 1; - } -*/ - if ( !Abc_NtkIsStrash(pNtk) ) - { - // strash and balance the network - pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - if ( pNtk == NULL ) - { - fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); - return 1; - } - pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); - Abc_NtkDelete( pNtkRes ); - if ( pNtk == NULL ) - { - fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); - return 1; - } - fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" ); - // get the new network - pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose ); - if ( pNtkRes == NULL ) - { - Abc_NtkDelete( pNtk ); - fprintf( pErr, "FPGA mapping has failed.\n" ); - return 1; - } - Abc_NtkDelete( pNtk ); - } - else - { - // get the new network - pNtkRes = Abc_NtkFpga( pNtk, DelayTarget, fRecovery, fSwitching, fLatchPaths, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "FPGA mapping has failed.\n" ); - return 1; - } - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - if ( DelayTarget == -1 ) - sprintf( Buffer, "best possible" ); - else - sprintf( Buffer, "%.2f", DelayTarget ); - if ( nLutSize == -1 ) - sprintf( LutSize, "library" ); - else - sprintf( LutSize, "%d", nLutSize ); - fprintf( pErr, "usage: fpga [-D float] [-K num] [-aplvh]\n" ); - fprintf( pErr, "\t performs FPGA mapping of the current network\n" ); - fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); - fprintf( pErr, "\t-p : optimizes power by minimizing switching activity [default = %s]\n", fSwitching? "yes": "no" ); - fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", fLatchPaths? "yes": "no" ); - fprintf( pErr, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer ); - fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < 11) [default = %s]%s\n", LutSize, (nLutSize == -1 ? " (type \"print_lut\")" : "") ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : prints the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandFpgaFast( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - char Buffer[100]; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int fRecovery; - int fVerbose; - int nLutSize; - float DelayTarget; - - extern Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fRecovery = 1; - fVerbose = 0; - DelayTarget =-1; - nLutSize = 5; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "avhDK" ) ) != EOF ) - { - switch ( c ) - { - case 'a': - fRecovery ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - case 'D': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); - goto usage; - } - DelayTarget = (float)atof(argv[globalUtilOptind]); - globalUtilOptind++; - if ( DelayTarget <= 0.0 ) - goto usage; - break; - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); - goto usage; - } - nLutSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLutSize < 0 ) - goto usage; - break; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - // strash and balance the network - pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - if ( pNtk == NULL ) - { - fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); - return 1; - } - pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); - Abc_NtkDelete( pNtkRes ); - if ( pNtk == NULL ) - { - fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); - return 1; - } - fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" ); - // get the new network - pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose ); - if ( pNtkRes == NULL ) - { - Abc_NtkDelete( pNtk ); - fprintf( pErr, "FPGA mapping has failed.\n" ); - return 1; - } - Abc_NtkDelete( pNtk ); - } - else - { - // get the new network - pNtkRes = Abc_NtkFpgaFast( pNtk, nLutSize, fRecovery, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "FPGA mapping has failed.\n" ); - return 1; - } - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - if ( DelayTarget == -1 ) - sprintf( Buffer, "not used" ); - else - sprintf( Buffer, "%.2f", DelayTarget ); - fprintf( pErr, "usage: ffpga [-K num] [-avh]\n" ); - fprintf( pErr, "\t performs fast FPGA mapping of the current network\n" ); - fprintf( pErr, "\t-a : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); -// fprintf( pErr, "\t-D float : sets the required time for the mapping [default = %s]\n", Buffer ); - fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < 32) [default = %d]\n", nLutSize ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : prints the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandIf( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - char Buffer[100]; - char LutSize[100]; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - If_Par_t Pars, * pPars = &Pars; - int c; - extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - memset( pPars, 0, sizeof(If_Par_t) ); - // user-controlable paramters - pPars->nLutSize = -1; - pPars->nCutsMax = 8; - pPars->nFlowIters = 1; - pPars->nAreaIters = 2; - pPars->DelayTarget = -1; - pPars->fPreprocess = 1;// - pPars->fArea = 0; - pPars->fFancy = 0; - pPars->fExpRed = 1;// - pPars->fLatchPaths = 0; - pPars->fSeqMap = 0; - pPars->fVerbose = 0;// - // internal parameters - pPars->fTruth = 0; - pPars->nLatches = pNtk? Abc_NtkLatchNum(pNtk) : 0; - pPars->fLiftLeaves = 0; - pPars->pLutLib = Abc_FrameReadLibLut(); - pPars->pTimesArr = NULL; - pPars->pTimesArr = NULL; - pPars->pFuncCost = NULL; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "KCFADpaflrstvh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by a positive integer.\n" ); - goto usage; - } - pPars->nLutSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nLutSize < 0 ) - goto usage; - // if the LUT size is specified, disable library - pPars->pLutLib = NULL; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by a positive integer.\n" ); - goto usage; - } - pPars->nCutsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nCutsMax < 0 ) - goto usage; - break; - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by a positive integer.\n" ); - goto usage; - } - pPars->nFlowIters = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nFlowIters < 0 ) - goto usage; - break; - case 'A': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-A\" should be followed by a positive integer.\n" ); - goto usage; - } - pPars->nAreaIters = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->nAreaIters < 0 ) - goto usage; - break; - case 'D': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-D\" should be followed by a floating point number.\n" ); - goto usage; - } - pPars->DelayTarget = (float)atof(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pPars->DelayTarget <= 0.0 ) - goto usage; - break; - case 'p': - pPars->fPreprocess ^= 1; - break; - case 'a': - pPars->fArea ^= 1; - break; - case 'f': - pPars->fFancy ^= 1; - break; - case 'l': - pPars->fLatchPaths ^= 1; - break; - case 'r': - pPars->fExpRed ^= 1; - break; - case 's': - pPars->fSeqMap ^= 1; - break; - case 't': - pPars->fLiftLeaves ^= 1; - break; - case 'v': - pPars->fVerbose ^= 1; - break; - case 'h': - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( pPars->fSeqMap && pPars->nLatches == 0 ) - { - fprintf( pErr, "The network has no latches. Use combinational mapping instead of sequential.\n" ); - return 1; - } - - if ( pPars->nLutSize == -1 ) - { - if ( pPars->pLutLib == NULL ) - { - fprintf( pErr, "The LUT library is not given.\n" ); - return 1; - } - // get LUT size from the library - pPars->nLutSize = pPars->pLutLib->LutMax; - } - - if ( pPars->nLutSize < 3 || pPars->nLutSize > IF_MAX_LUTSIZE ) - { - fprintf( pErr, "Incorrect LUT size (%d).\n", pPars->nLutSize ); - return 1; - } - - if ( pPars->nCutsMax < 1 || pPars->nCutsMax >= (1<<12) ) - { - fprintf( pErr, "Incorrect number of cuts.\n" ); - return 1; - } - - if ( Abc_NtkGetChoiceNum( pNtk ) ) - { - printf( "Performing FPGA mapping with choices.\n" ); -// printf( "Currently mapping with choices is not enabled.\n" ); - pPars->fTruth = 1; -// return 1; - } - - if ( pPars->fTruth && pPars->nLutSize > IF_MAX_FUNC_LUTSIZE ) - { - fprintf( pErr, "Mapping with choices requires computing truth tables. In this case, the LUT size cannot be more than %d.\n", IF_MAX_FUNC_LUTSIZE ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - // strash and balance the network - pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); - if ( pNtk == NULL ) - { - fprintf( pErr, "Strashing before FPGA mapping has failed.\n" ); - return 1; - } - pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); - Abc_NtkDelete( pNtkRes ); - if ( pNtk == NULL ) - { - fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); - return 1; - } - fprintf( pOut, "The network was strashed and balanced before FPGA mapping.\n" ); - // get the new network - pNtkRes = Abc_NtkIf( pNtk, pPars ); - if ( pNtkRes == NULL ) - { - Abc_NtkDelete( pNtk ); - fprintf( pErr, "FPGA mapping has failed.\n" ); - return 0; - } - Abc_NtkDelete( pNtk ); - } - else - { - // get the new network - pNtkRes = Abc_NtkIf( pNtk, pPars ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "FPGA mapping has failed.\n" ); - return 0; - } - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - if ( pPars->DelayTarget == -1 ) - sprintf( Buffer, "best possible" ); - else - sprintf( Buffer, "%.2f", pPars->DelayTarget ); - if ( pPars->nLutSize == -1 ) - sprintf( LutSize, "library" ); - else - sprintf( LutSize, "%d", pPars->nLutSize ); - fprintf( pErr, "usage: if [-K num] [-C num] [-F num] [-A num] [-D float] [-pafrsvh]\n" ); - fprintf( pErr, "\t performs FPGA technology mapping of the network\n" ); - fprintf( pErr, "\t-K num : the number of LUT inputs (2 < num < %d) [default = %s]\n", IF_MAX_LUTSIZE+1, LutSize ); - fprintf( pErr, "\t-C num : the max number of priority cuts (0 < num < 2^12) [default = %d]\n", pPars->nCutsMax ); - fprintf( pErr, "\t-F num : the number of area flow recovery iterations (num >= 0) [default = %d]\n", pPars->nFlowIters ); - fprintf( pErr, "\t-A num : the number of exact area recovery iterations (num >= 0) [default = %d]\n", pPars->nAreaIters ); - fprintf( pErr, "\t-D float : sets the delay constraint for the mapping [default = %s]\n", Buffer ); - fprintf( pErr, "\t-p : toggles preprocessing using several starting points [default = %s]\n", pPars->fPreprocess? "yes": "no" ); - fprintf( pErr, "\t-a : toggles area-oriented mapping [default = %s]\n", pPars->fArea? "yes": "no" ); -// fprintf( pErr, "\t-f : toggles one fancy feature [default = %s]\n", pPars->fFancy? "yes": "no" ); - fprintf( pErr, "\t-r : enables expansion/reduction of the best cuts [default = %s]\n", pPars->fExpRed? "yes": "no" ); - fprintf( pErr, "\t-l : optimizes latch paths for delay, other paths for area [default = %s]\n", pPars->fLatchPaths? "yes": "no" ); - fprintf( pErr, "\t-s : toggles sequential mapping [default = %s]\n", pPars->fSeqMap? "yes": "no" ); -// fprintf( pErr, "\t-t : toggles the use of true sequential cuts [default = %s]\n", pPars->fLiftLeaves? "yes": "no" ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : prints the command usage\n"); - return 1; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandInit( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pObj; - int c, i; - int fZeros; - int fOnes; - int fRandom; - int fDontCare; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fZeros = 0; - fOnes = 0; - fRandom = 0; - fDontCare = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "zordh" ) ) != EOF ) - { - switch ( c ) - { - case 'z': - fZeros ^= 1; - break; - case 'o': - fOnes ^= 1; - break; - case 'r': - fRandom ^= 1; - break; - case 'd': - fDontCare ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "The current network is combinational.\n" ); - return 0; - } - - if ( fZeros ) - { - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_LatchSetInit0( pObj ); - } - else if ( fOnes ) - { - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_LatchSetInit1( pObj ); - } - else if ( fRandom ) - { - Abc_NtkForEachLatch( pNtk, pObj, i ) - if ( rand() & 1 ) - Abc_LatchSetInit1( pObj ); - else - Abc_LatchSetInit0( pObj ); - } - else if ( fDontCare ) - { - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_LatchSetInitDc( pObj ); - } - else - printf( "The initial states remain unchanged.\n" ); - return 0; - -usage: - fprintf( pErr, "usage: init [-zordh]\n" ); - fprintf( pErr, "\t resets initial states of all latches\n" ); - fprintf( pErr, "\t-z : set zeros initial states [default = %s]\n", fZeros? "yes": "no" ); - fprintf( pErr, "\t-o : set ones initial states [default = %s]\n", fOnes? "yes": "no" ); - fprintf( pErr, "\t-d : set don't-care initial states [default = %s]\n", fDontCare? "yes": "no" ); - fprintf( pErr, "\t-r : set random initial states [default = %s]\n", fRandom? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandZero( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - - extern Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, bool fCleanup ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "The current network is combinational.\n" ); - return 0; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command works only for AIGs.\n" ); - return 0; - } - - // get the new network - pNtkRes = Abc_NtkRestrashZero( pNtk, 0 ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Converting to sequential AIG has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: zero [-h]\n" ); - fprintf( pErr, "\t converts latches to have const-0 initial value\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandUndc( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "The current network is combinational.\n" ); - return 0; - } - - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "This command works only for logic networks.\n" ); - return 0; - } - - // get the new network - Abc_NtkConvertDcLatches( pNtk ); - return 0; - -usage: - fprintf( pErr, "usage: undc [-h]\n" ); - fprintf( pErr, "\t converts latches with DC init values into free PIs\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandPipe( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int nLatches; - extern void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nLatches = 5; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Lh" ) ) != EOF ) - { - switch ( c ) - { - case 'L': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-L\" should be followed by a positive integer.\n" ); - goto usage; - } - nLatches = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLatches < 0 ) - goto usage; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "The current network is combinational.\n" ); - return 1; - } - - // update the network - Abc_NtkLatchPipe( pNtk, nLatches ); - return 0; - -usage: - fprintf( pErr, "usage: pipe [-L num] [-h]\n" ); - fprintf( pErr, "\t inserts the given number of latches at each PI for pipelining\n" ); - fprintf( pErr, "\t-L num : the number of latches to insert [default = %d]\n", nLatches ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( Abc_NtkLatchNum(pNtk) == 0 ) - { - fprintf( pErr, "The network has no latches.\n" ); - return 0; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Conversion to sequential AIG works only for combinational AIGs (run \"strash\").\n" ); - return 1; - } - - // get the new network -// pNtkRes = Abc_NtkAigToSeq( pNtk ); - pNtkRes = NULL; - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Converting to sequential AIG has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: seq [-h]\n" ); - fprintf( pErr, "\t converts AIG into sequential AIG\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandUnseq( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int fShare; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fShare = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) - { - switch ( c ) - { - case 's': - fShare ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } -/* - if ( !Abc_NtkIsSeq(pNtk) ) - { - fprintf( pErr, "Conversion to combinational AIG works only for sequential AIG (run \"seq\").\n" ); - return 1; - } -*/ - // share the latches on the fanout edges -// if ( fShare ) -// Seq_NtkShareFanouts(pNtk); - - // get the new network -// pNtkRes = Abc_NtkSeqToLogicSop( pNtk ); - pNtkRes = NULL; - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Converting sequential AIG into an SOP logic network has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: unseq [-sh]\n" ); - fprintf( pErr, "\t converts sequential AIG into an SOP logic network\n" ); - fprintf( pErr, "\t-s : toggle sharing latches [default = %s]\n", fShare? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c, nMaxIters; - int fForward; - int fBackward; - int fOneStep; - int fVerbose; - int Mode; - extern int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Mode = 5; - fForward = 0; - fBackward = 0; - fOneStep = 0; - fVerbose = 0; - nMaxIters = 15; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Mfbsvh" ) ) != EOF ) - { - switch ( c ) - { - case 'M': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-M\" should be followed by a positive integer.\n" ); - goto usage; - } - Mode = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( Mode < 0 ) - goto usage; - break; - case 'f': - fForward ^= 1; - break; - case 'b': - fBackward ^= 1; - break; - case 's': - fOneStep ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( fForward && fBackward ) - { - fprintf( pErr, "Only one switch \"-f\" or \"-b\" can be selected at a time.\n" ); - return 1; - } - - if ( !Abc_NtkLatchNum(pNtk) ) - { - fprintf( pErr, "The network has no latches. Retiming is not performed.\n" ); - return 0; - } - - if ( Mode < 0 || Mode > 6 ) - { - fprintf( pErr, "The mode (%d) is incorrect. Retiming is not performed.\n", Mode ); - return 0; - } - - if ( Abc_NtkIsStrash(pNtk) ) - { - if ( Abc_NtkGetChoiceNum(pNtk) ) - { - fprintf( pErr, "Retiming with choice nodes is not implemented.\n" ); - return 0; - } - // convert the network into an SOP network - pNtkRes = Abc_NtkToLogic( pNtk ); - // perform the retiming - Abc_NtkRetime( pNtkRes, Mode, fForward, fBackward, fOneStep, fVerbose ); - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - } - - // get the network in the SOP form - if ( !Abc_NtkToSop(pNtk, 0) ) - { - printf( "Converting to SOPs has failed.\n" ); - return 0; - } - - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "The network is not a logic network. Retiming is not performed.\n" ); - return 0; - } - - // perform the retiming - Abc_NtkRetime( pNtk, Mode, fForward, fBackward, fOneStep, fVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: retime [-M num] [-fbvh]\n" ); - fprintf( pErr, "\t retimes the current network using one of the algorithms:\n" ); - fprintf( pErr, "\t 1: most forward retiming\n" ); - fprintf( pErr, "\t 2: most backward retiming\n" ); - fprintf( pErr, "\t 3: forward and backward min-area retiming\n" ); - fprintf( pErr, "\t 4: forward and backward min-delay retiming\n" ); - fprintf( pErr, "\t 5: mode 3 followed by mode 4\n" ); - fprintf( pErr, "\t 6: Pan's optimum-delay retiming using binary search\n" ); - fprintf( pErr, "\t-M num : the retiming algorithm to use [default = %d]\n", Mode ); - fprintf( pErr, "\t-f : enables forward-only retiming in modes 3,4,5 [default = %s]\n", fForward? "yes": "no" ); - fprintf( pErr, "\t-b : enables backward-only retiming in modes 3,4,5 [default = %s]\n", fBackward? "yes": "no" ); - fprintf( pErr, "\t-s : enables retiming one step only in mode 4 [default = %s]\n", fOneStep? "yes": "no" ); - fprintf( pErr, "\t-v : enables verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -// fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); -// fprintf( pErr, "\t-f : toggle forward retiming (for AIGs) [default = %s]\n", fForward? "yes": "no" ); -// fprintf( pErr, "\t-b : toggle backward retiming (for AIGs) [default = %s]\n", fBackward? "yes": "no" ); -// fprintf( pErr, "\t-i : toggle computation of initial state [default = %s]\n", fInitial? "yes": "no" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; - int c, nMaxIters; - int fVerbose; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nMaxIters = 15; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) - { - switch ( c ) - { - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); - goto usage; - } - nMaxIters = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nMaxIters < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( Abc_NtkHasAig(pNtk) ) - { -/* - // quit if there are choice nodes - if ( Abc_NtkGetChoiceNum(pNtk) ) - { - fprintf( pErr, "Currently cannot map/retime networks with choice nodes.\n" ); - return 0; - } -*/ -// if ( Abc_NtkIsStrash(pNtk) ) -// pNtkNew = Abc_NtkAigToSeq(pNtk); -// else -// pNtkNew = Abc_NtkDup(pNtk); - pNtkNew = NULL; - } - else - { - // strash and balance the network - pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); - if ( pNtkNew == NULL ) - { - fprintf( pErr, "Strashing before FPGA mapping/retiming has failed.\n" ); - return 1; - } - - pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 ); - Abc_NtkDelete( pNtkRes ); - if ( pNtkNew == NULL ) - { - fprintf( pErr, "Balancing before FPGA mapping has failed.\n" ); - return 1; - } - - // convert into a sequential AIG -// pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew ); - pNtkNew = NULL; - Abc_NtkDelete( pNtkRes ); - if ( pNtkNew == NULL ) - { - fprintf( pErr, "Converting into a seq AIG before FPGA mapping/retiming has failed.\n" ); - return 1; - } - - fprintf( pOut, "The network was strashed and balanced before FPGA mapping/retiming.\n" ); - } - - // get the new network -// pNtkRes = Seq_NtkFpgaMapRetime( pNtkNew, nMaxIters, fVerbose ); - pNtkRes = NULL; - if ( pNtkRes == NULL ) - { -// fprintf( pErr, "Sequential FPGA mapping has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return 0; - } - Abc_NtkDelete( pNtkNew ); - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: sfpga [-I num] [-vh]\n" ); - fprintf( pErr, "\t performs integrated sequential FPGA mapping/retiming\n" ); - fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); - fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; - int c, nMaxIters; - int fVerbose; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nMaxIters = 15; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) - { - switch ( c ) - { - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" ); - goto usage; - } - nMaxIters = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nMaxIters < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( Abc_NtkHasAig(pNtk) ) - { -/* - // quit if there are choice nodes - if ( Abc_NtkGetChoiceNum(pNtk) ) - { - fprintf( pErr, "Currently cannot map/retime networks with choice nodes.\n" ); - return 0; - } -*/ -// if ( Abc_NtkIsStrash(pNtk) ) -// pNtkNew = Abc_NtkAigToSeq(pNtk); -// else -// pNtkNew = Abc_NtkDup(pNtk); - pNtkNew = NULL; - } - else - { - // strash and balance the network - pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); - if ( pNtkNew == NULL ) - { - fprintf( pErr, "Strashing before SC mapping/retiming has failed.\n" ); - return 1; - } - - pNtkNew = Abc_NtkBalance( pNtkRes = pNtkNew, 0, 0, 1 ); - Abc_NtkDelete( pNtkRes ); - if ( pNtkNew == NULL ) - { - fprintf( pErr, "Balancing before SC mapping/retiming has failed.\n" ); - return 1; - } - - // convert into a sequential AIG -// pNtkNew = Abc_NtkAigToSeq( pNtkRes = pNtkNew ); - pNtkNew = NULL; - Abc_NtkDelete( pNtkRes ); - if ( pNtkNew == NULL ) - { - fprintf( pErr, "Converting into a seq AIG before SC mapping/retiming has failed.\n" ); - return 1; - } - - fprintf( pOut, "The network was strashed and balanced before SC mapping/retiming.\n" ); - } - - // get the new network -// pNtkRes = Seq_MapRetime( pNtkNew, nMaxIters, fVerbose ); - pNtkRes = NULL; - if ( pNtkRes == NULL ) - { -// fprintf( pErr, "Sequential FPGA mapping has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return 0; - } - Abc_NtkDelete( pNtkNew ); - - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: smap [-I num] [-vh]\n" ); - fprintf( pErr, "\t performs integrated sequential standard-cell mapping/retiming\n" ); - fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters ); - fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSeqSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int nFramesP; - int nFramesK; - int nMaxImps; - int fUseImps; - int fRewrite; - int fLatchCorr; - int fWriteImps; - int fVerbose; - extern Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFrames, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nFramesP = 0; - nFramesK = 1; - nMaxImps = 5000; - fUseImps = 0; - fRewrite = 0; - fLatchCorr = 0; - fWriteImps = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PFIirlevh" ) ) != EOF ) - { - switch ( c ) - { - case 'P': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); - goto usage; - } - nFramesP = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFramesP < 0 ) - goto usage; - break; - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - nFramesK = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFramesK <= 0 ) - goto usage; - break; - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - nMaxImps = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nMaxImps <= 0 ) - goto usage; - break; - case 'i': - fUseImps ^= 1; - break; - case 'r': - fRewrite ^= 1; - break; - case 'l': - fLatchCorr ^= 1; - break; - case 'e': - fWriteImps ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); - return 0; - } - - // get the new network - pNtkRes = Abc_NtkDarSeqSweep( pNtk, nFramesP, nFramesK, nMaxImps, fRewrite, fUseImps, fLatchCorr, fWriteImps, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Sequential sweeping has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: ssweep [-P num] [-F num] [-I num] [-ilrevh]\n" ); - fprintf( pErr, "\t performs sequential sweep using K-step induction\n" ); - fprintf( pErr, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP ); - fprintf( pErr, "\t-F num : number of time frames for induction (1=simple) [default = %d]\n", nFramesK ); - fprintf( pErr, "\t-I num : max number of implications to consider [default = %d]\n", nMaxImps ); - fprintf( pErr, "\t-i : toggle using implications [default = %s]\n", fUseImps? "yes": "no" ); - fprintf( pErr, "\t-l : toggle latch correspondence only [default = %s]\n", fLatchCorr? "yes": "no" ); - fprintf( pErr, "\t-r : toggle AIG rewriting [default = %s]\n", fRewrite? "yes": "no" ); - fprintf( pErr, "\t-e : toggle writing implications as assertions [default = %s]\n", fWriteImps? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandLcorr( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int nFramesP; - int nConfMax; - int fVerbose; - extern Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nFramesP = 0; - nConfMax = 10000; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "PCvh" ) ) != EOF ) - { - switch ( c ) - { - case 'P': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); - goto usage; - } - nFramesP = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFramesP < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nConfMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nConfMax < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( Abc_NtkIsComb(pNtk) ) - { - fprintf( pErr, "The network is combinational (run \"fraig\" or \"fraig_sweep\").\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); - return 0; - } - - // get the new network - pNtkRes = Abc_NtkDarLcorr( pNtk, nFramesP, nConfMax, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Sequential sweeping has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: lcorr [-P num] [-C num] [-vh]\n" ); - fprintf( pErr, "\t computes latch correspondence using 1-step induction\n" ); - fprintf( pErr, "\t-P num : number of time frames to use as the prefix [default = %d]\n", nFramesP ); - fprintf( pErr, "\t-C num : max conflict number when proving latch equivalence [default = %d]\n", nConfMax ); - fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSeqCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkRes; - int c; - int fLatchSweep; - int fAutoSweep; - int fVerbose; - extern Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fLatchSweep = 0; - fAutoSweep = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lavh" ) ) != EOF ) - { - switch ( c ) - { - case 'l': - fLatchSweep ^= 1; - break; - case 'a': - fAutoSweep ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Only works for structrally hashed networks.\n" ); - return 1; - } - if ( !Abc_NtkLatchNum(pNtk) ) - { - fprintf( pErr, "Only works for sequential networks.\n" ); - return 1; - } - // modify the current network - pNtkRes = Abc_NtkDarLatchSweep( pNtk, fLatchSweep, fVerbose ); - if ( pNtkRes == NULL ) - { - fprintf( pErr, "Sequential cleanup has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); - return 0; - -usage: - fprintf( pErr, "usage: scleanup [-lvh]\n" ); - fprintf( pErr, "\t performs sequential cleanup\n" ); - fprintf( pErr, "\t - removes nodes/latches that do not feed into POs\n" ); - fprintf( pErr, "\t - removes stuck-at and identical latches (latch sweep)\n" ); -// fprintf( pErr, "\t - replaces autonomous logic by free PI variables\n" ); - fprintf( pErr, "\t (the latter may change sequential behaviour)\n" ); - fprintf( pErr, "\t-l : toggle sweeping latches [default = %s]\n", fLatchSweep? "yes": "no" ); -// fprintf( pErr, "\t-a : toggle removing autonomous logic [default = %s]\n", fAutoSweep? "yes": "no" ); - fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandCycle( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int nFrames; - int fVerbose; - extern void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); - extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nFrames = 100; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Fvh" ) ) != EOF ) - { - switch ( c ) - { - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - nFrames = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFrames < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsSopLogic(pNtk) ) - { - fprintf( pErr, "Only works for strashed networks or logic SOP networks.\n" ); - return 1; - } - if ( !Abc_NtkLatchNum(pNtk) ) - { - fprintf( pErr, "Only works for sequential networks.\n" ); - return 1; - } - - if ( Abc_NtkIsStrash(pNtk) ) - Abc_NtkCycleInitState( pNtk, nFrames, fVerbose ); - else - Abc_NtkCycleInitStateSop( pNtk, nFrames, fVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: cycle [-F num] [-vh]\n" ); - fprintf( pErr, "\t cycles sequiential circuit for the given number of timeframes\n" ); - fprintf( pErr, "\t to derive a new initial state (which may be on the envelope)\n" ); - fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandXsim( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int nFrames; - int fXInputs; - int fXState; - int fVerbose; - extern void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nFrames = 10; - fXInputs = 0; - fXState = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Fisvh" ) ) != EOF ) - { - switch ( c ) - { - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - nFrames = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFrames < 0 ) - goto usage; - break; - case 'i': - fXInputs ^= 1; - break; - case 's': - fXState ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "Only works for strashed networks.\n" ); - return 1; - } - if ( !Abc_NtkLatchNum(pNtk) ) - { - fprintf( pErr, "Only works for sequential networks.\n" ); - return 1; - } - Abc_NtkXValueSimulate( pNtk, nFrames, fXInputs, fXState, fVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: xsim [-F num] [-isvh]\n" ); - fprintf( pErr, "\t performs X-valued simulation of the AIG\n" ); - fprintf( pErr, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); - fprintf( pErr, "\t-i : toggle X-valued representation of inputs [default = %s]\n", fXInputs? "yes": "no" ); - fprintf( pErr, "\t-s : toggle X-valued representation of state [default = %s]\n", fXState? "yes": "no" ); - fprintf( pErr, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandCec( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - char Buffer[16]; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; - int fDelete1, fDelete2; - char ** pArgvNew; - int nArgcNew; - int c; - int fSat; - int fVerbose; - int nSeconds; - int nPartSize; - int nConfLimit; - int nInsLimit; - int fPartition; - - extern void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ); - extern void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); - extern void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose ); - extern void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fSat = 0; - fVerbose = 0; - nSeconds = 20; - nPartSize = 0; - nConfLimit = 10000; - nInsLimit = 0; - fPartition = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "TCIPpsvh" ) ) != EOF ) - { - switch ( c ) - { - case 'T': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); - goto usage; - } - nSeconds = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nSeconds < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nConfLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nConfLimit < 0 ) - goto usage; - break; - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - nInsLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nInsLimit < 0 ) - goto usage; - break; - case 'P': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-P\" should be followed by an integer.\n" ); - goto usage; - } - nPartSize = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nPartSize < 0 ) - goto usage; - break; - case 'p': - fPartition ^= 1; - break; - case 's': - fSat ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - default: - goto usage; - } - } - - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) - return 1; - - // perform equivalence checking - if ( fPartition ) - Abc_NtkCecFraigPartAuto( pNtk1, pNtk2, nSeconds, fVerbose ); - else if ( nPartSize ) - Abc_NtkCecFraigPart( pNtk1, pNtk2, nSeconds, nPartSize, fVerbose ); - else if ( fSat ) - Abc_NtkCecSat( pNtk1, pNtk2, nConfLimit, nInsLimit ); - else - Abc_NtkCecFraig( pNtk1, pNtk2, nSeconds, fVerbose ); - - if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); - if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); - return 0; - -usage: - if ( nPartSize == 0 ) - strcpy( Buffer, "unused" ); - else - sprintf( Buffer, "%d", nPartSize ); - fprintf( pErr, "usage: cec [-T num] [-C num] [-I num] [-P num] [-psvh] \n" ); - fprintf( pErr, "\t performs combinational equivalence checking\n" ); - fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds ); - fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); - fprintf( pErr, "\t-I num : limit on the number of clause inspections [default = %d]\n", nInsLimit ); - fprintf( pErr, "\t-P num : partition size for multi-output networks [default = %s]\n", Buffer ); - fprintf( pErr, "\t-p : toggle automatic partitioning [default = %s]\n", fPartition? "yes": "no" ); - fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); - fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); - fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); - fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSec( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; - int fDelete1, fDelete2; - char ** pArgvNew; - int nArgcNew; - int c; - int fRetime; - int fSat; - int fVerbose; - int nFrames; - int nSeconds; - int nConfLimit; - int nInsLimit; - - extern void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames ); - extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ); - extern void Abc_NtkSecRetime( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ); - - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fRetime = 0; // verification after retiming - fSat = 0; - fVerbose = 0; - nFrames = 5; - nSeconds = 20; - nConfLimit = 10000; - nInsLimit = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "FTCIsrvh" ) ) != EOF ) - { - switch ( c ) - { - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - nFrames = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFrames <= 0 ) - goto usage; - break; - case 'T': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-T\" should be followed by an integer.\n" ); - goto usage; - } - nSeconds = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nSeconds < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nConfLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nConfLimit < 0 ) - goto usage; - break; - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - nInsLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nInsLimit < 0 ) - goto usage; - break; - case 'r': - fRetime ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 's': - fSat ^= 1; - break; - default: - goto usage; - } - } - - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) - return 1; - - if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) - { - printf( "The network has no latches. Used combinational command \"cec\".\n" ); - return 0; - } - - // perform equivalence checking - if ( fRetime ) - Abc_NtkSecRetime( pNtk1, pNtk2 ); - else if ( fSat ) - Abc_NtkSecSat( pNtk1, pNtk2, nConfLimit, nInsLimit, nFrames ); - else - Abc_NtkSecFraig( pNtk1, pNtk2, nSeconds, nFrames, fVerbose ); - - if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); - if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); - return 0; - -usage: - fprintf( pErr, "usage: sec [-F num] [-T num] [-C num] [-I num] [-srvh] \n" ); - fprintf( pErr, "\t performs bounded sequential equivalence checking\n" ); - fprintf( pErr, "\t-s : toggle \"SAT only\" and \"FRAIG + SAT\" [default = %s]\n", fSat? "SAT only": "FRAIG + SAT" ); - fprintf( pErr, "\t-r : toggles retiming verification [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\t-F num : the number of time frames to use [default = %d]\n", nFrames ); - fprintf( pErr, "\t-T num : approximate runtime limit in seconds [default = %d]\n", nSeconds ); - fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); - fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit ); - fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); - fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); - fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); - fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDSec( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtk1, * pNtk2; - int fDelete1, fDelete2; - char ** pArgvNew; - int nArgcNew; - int c; - int fRetimeFirst; - int fVerbose; - int fVeryVerbose; - int nFrames; - - extern int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nFrames =16; - fRetimeFirst = 1; - fVerbose = 0; - fVeryVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Krwvh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); - goto usage; - } - nFrames = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFrames < 0 ) - goto usage; - break; - case 'r': - fRetimeFirst ^= 1; - break; - case 'w': - fVeryVerbose ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - default: - goto usage; - } - } - - pArgvNew = argv + globalUtilOptind; - nArgcNew = argc - globalUtilOptind; - if ( !Abc_NtkPrepareTwoNtks( pErr, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2 ) ) - return 1; - - if ( Abc_NtkLatchNum(pNtk1) == 0 || Abc_NtkLatchNum(pNtk2) == 0 ) - { - printf( "The network has no latches. Used combinational command \"cec\".\n" ); - return 0; - } - - // perform verification - Abc_NtkDarSec( pNtk1, pNtk2, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); - - if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); - if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); - return 0; - -usage: - fprintf( pErr, "usage: dsec [-K num] [-rwvh] \n" ); - fprintf( pErr, "\t performs inductive sequential equivalence checking\n" ); - fprintf( pErr, "\t-K num : the limit on the depth of induction [default = %d]\n", nFrames ); - fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", fRetimeFirst? "yes": "no" ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", fVeryVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\tfile1 : (optional) the file with the first network\n"); - fprintf( pErr, "\tfile2 : (optional) the file with the second network\n"); - fprintf( pErr, "\t if no files are given, uses the current network and its spec\n"); - fprintf( pErr, "\t if one file is given, uses the current network and the file\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDProve( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int fRetimeFirst; - int fVerbose; - int fVeryVerbose; - int nFrames; - - extern int Abc_NtkDarProve( Abc_Ntk_t * pNtk, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - nFrames = 16; - fRetimeFirst = 1; - fVerbose = 0; - fVeryVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "Krwvh" ) ) != EOF ) - { - switch ( c ) - { - case 'K': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-K\" should be followed by an integer.\n" ); - goto usage; - } - nFrames = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nFrames < 0 ) - goto usage; - break; - case 'r': - fRetimeFirst ^= 1; - break; - case 'w': - fVeryVerbose ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - default: - goto usage; - } - } - - if ( Abc_NtkLatchNum(pNtk) == 0 ) - { - printf( "The network has no latches. Used combinational command \"iprove\".\n" ); - return 0; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - printf( "This command works only for structrally hashed networks. Run \"st\".\n" ); - return 0; - } - - // perform verification - Abc_NtkDarProve( pNtk, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: dprove [-K num] [-rwvh]\n" ); - fprintf( pErr, "\t performs SEC on the sequential miter\n" ); - fprintf( pErr, "\t-K num : the limit on the depth of induction [default = %d]\n", nFrames ); - fprintf( pErr, "\t-r : toggles forward retiming at the beginning [default = %s]\n", fRetimeFirst? "yes": "no" ); - fprintf( pErr, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-w : toggles additional verbose output [default = %s]\n", fVeryVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandSat( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int RetValue; - int fVerbose; - int nConfLimit; - int nInsLimit; - int clk; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fVerbose = 0; - nConfLimit = 100000; - nInsLimit = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF ) - { - switch ( c ) - { - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nConfLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nConfLimit < 0 ) - goto usage; - break; - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - nInsLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nInsLimit < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkLatchNum(pNtk) > 0 ) - { - fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" ); - return 0; - } - - clk = clock(); - if ( Abc_NtkIsStrash(pNtk) ) - { - RetValue = Abc_NtkMiterSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose, NULL, NULL ); - } - else - { - assert( Abc_NtkIsLogic(pNtk) ); - Abc_NtkToBdd( pNtk ); - RetValue = Abc_NtkMiterSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose, NULL, NULL ); - } - - // verify that the pattern is correct - if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 ) - { - //int i; - //Abc_Obj_t * pObj; - int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel ); - if ( pSimInfo[0] != 1 ) - printf( "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" ); - free( pSimInfo ); - /* - // print model - Abc_NtkForEachPi( pNtk, pObj, i ) - { - printf( "%d", (int)(pNtk->pModel[i] > 0) ); - if ( i == 70 ) - break; - } - printf( "\n" ); - */ - } - - if ( RetValue == -1 ) - printf( "UNDECIDED " ); - else if ( RetValue == 0 ) - printf( "SATISFIABLE " ); - else - printf( "UNSATISFIABLE " ); - //printf( "\n" ); - PRT( "Time", clock() - clk ); - return 0; - -usage: - fprintf( pErr, "usage: sat [-C num] [-I num] [-vh]\n" ); - fprintf( pErr, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" ); - fprintf( pErr, "\t derives CNF from the current network and leave it unchanged\n" ); - fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); - fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDSat( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - int RetValue; - int fVerbose; - int nConfLimit; - int nInsLimit; - int clk; - - extern int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ); - - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fVerbose = 0; - nConfLimit = 100000; - nInsLimit = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "CIvh" ) ) != EOF ) - { - switch ( c ) - { - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - nConfLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nConfLimit < 0 ) - goto usage; - break; - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - nInsLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nInsLimit < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkLatchNum(pNtk) > 0 ) - { - fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" ); - return 0; - } - if ( Abc_NtkPoNum(pNtk) != 1 ) - { - fprintf( stdout, "Currently expects a single-output miter.\n" ); - return 0; - } - - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( stdout, "Currently only works for structurally hashed circuits.\n" ); - return 0; - } - - clk = clock(); - RetValue = Abc_NtkDSat( pNtk, (sint64)nConfLimit, (sint64)nInsLimit, fVerbose ); - // verify that the pattern is correct - if ( RetValue == 0 && Abc_NtkPoNum(pNtk) == 1 ) - { - //int i; - //Abc_Obj_t * pObj; - int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtk->pModel ); - if ( pSimInfo[0] != 1 ) - printf( "ERROR in Abc_NtkMiterSat(): Generated counter example is invalid.\n" ); - free( pSimInfo ); - /* - // print model - Abc_NtkForEachPi( pNtk, pObj, i ) - { - printf( "%d", (int)(pNtk->pModel[i] > 0) ); - if ( i == 70 ) - break; - } - printf( "\n" ); - */ - } - - if ( RetValue == -1 ) - printf( "UNDECIDED " ); - else if ( RetValue == 0 ) - printf( "SATISFIABLE " ); - else - printf( "UNSATISFIABLE " ); - //printf( "\n" ); - PRT( "Time", clock() - clk ); - return 0; - -usage: - fprintf( pErr, "usage: dsat [-C num] [-I num] [-vh]\n" ); - fprintf( pErr, "\t solves the combinational miter using SAT solver MiniSat-1.14\n" ); - fprintf( pErr, "\t derives CNF from the current network and leave it unchanged\n" ); - fprintf( pErr, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); - fprintf( pErr, "\t-I num : limit on the number of inspections [default = %d]\n", nInsLimit ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandProve( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkTemp; - Prove_Params_t Params, * pParams = &Params; - int c, clk, RetValue; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Prove_ParamsSetDefault( pParams ); - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "NCFLIrfbvh" ) ) != EOF ) - { - switch ( c ) - { - case 'N': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-N\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nItersMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nItersMax < 0 ) - goto usage; - break; - case 'C': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-C\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nMiteringLimitStart = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nMiteringLimitStart < 0 ) - goto usage; - break; - case 'F': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-F\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nFraigingLimitStart = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nFraigingLimitStart < 0 ) - goto usage; - break; - case 'L': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-L\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nMiteringLimitLast < 0 ) - goto usage; - break; - case 'I': - if ( globalUtilOptind >= argc ) - { - fprintf( pErr, "Command line switch \"-I\" should be followed by an integer.\n" ); - goto usage; - } - pParams->nTotalInspectLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( pParams->nTotalInspectLimit < 0 ) - goto usage; - break; - case 'r': - pParams->fUseRewriting ^= 1; - break; - case 'f': - pParams->fUseFraiging ^= 1; - break; - case 'b': - pParams->fUseBdds ^= 1; - break; - case 'v': - pParams->fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( Abc_NtkLatchNum(pNtk) > 0 ) - { - fprintf( stdout, "Currently can only solve the miter for combinational circuits.\n" ); - return 0; - } - if ( Abc_NtkCoNum(pNtk) != 1 ) - { - fprintf( stdout, "Currently can only solve the miter with one output.\n" ); - return 0; - } - clk = clock(); - - if ( Abc_NtkIsStrash(pNtk) ) - pNtkTemp = Abc_NtkDup( pNtk ); - else - pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); - - RetValue = Abc_NtkMiterProve( &pNtkTemp, pParams ); - - // verify that the pattern is correct - if ( RetValue == 0 ) - { - int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel ); - if ( pSimInfo[0] != 1 ) - printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); - free( pSimInfo ); - } - - if ( RetValue == -1 ) - printf( "UNDECIDED " ); - else if ( RetValue == 0 ) - printf( "SATISFIABLE " ); - else - printf( "UNSATISFIABLE " ); - //printf( "\n" ); - - PRT( "Time", clock() - clk ); - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp ); - return 0; - -usage: - fprintf( pErr, "usage: prove [-N num] [-C num] [-F num] [-L num] [-I num] [-rfbvh]\n" ); - fprintf( pErr, "\t solves combinational miter by rewriting, FRAIGing, and SAT\n" ); - fprintf( pErr, "\t replaces the current network by the cone modified by rewriting\n" ); - fprintf( pErr, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax ); - fprintf( pErr, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart ); - fprintf( pErr, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart ); - fprintf( pErr, "\t-L num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast ); - fprintf( pErr, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit ); - fprintf( pErr, "\t-r : toggle the use of rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" ); - fprintf( pErr, "\t-f : toggle the use of FRAIGing [default = %s]\n", pParams->fUseFraiging? "yes": "no" ); - fprintf( pErr, "\t-b : toggle the use of BDDs [default = %s]\n", pParams->fUseBdds? "yes": "no" ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandDebug( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - extern void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) ); - extern int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pErr, "This command is applicable to logic networks.\n" ); - return 1; - } - - Abc_NtkAutoDebug( pNtk, Abc_NtkRetimeDebug ); - return 0; - -usage: - fprintf( pErr, "usage: debug [-h]\n" ); - fprintf( pErr, "\t performs automated debugging of the given procedure\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandTraceStart( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command is applicable to AIGs.\n" ); - return 1; - } -/* - Abc_HManStart(); - if ( !Abc_HManPopulate( pNtk ) ) - { - fprintf( pErr, "Failed to start the tracing database.\n" ); - return 1; - } -*/ - return 0; - -usage: - fprintf( pErr, "usage: trace_start [-h]\n" ); - fprintf( pErr, "\t starts verification tracing\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandTraceCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - int c; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( pErr, "This command is applicable to AIGs.\n" ); - return 1; - } -/* - if ( !Abc_HManIsRunning(pNtk) ) - { - fprintf( pErr, "The tracing database is not available.\n" ); - return 1; - } - - if ( !Abc_HManVerify( 1, pNtk->Id ) ) - fprintf( pErr, "Verification failed.\n" ); - Abc_HManStop(); -*/ - return 0; - -usage: - fprintf( pErr, "usage: trace_check [-h]\n" ); - fprintf( pErr, "\t checks the current network using verification trace\n" ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcAttach.c b/src/base/abci/abcAttach.c deleted file mode 100644 index d5d2aa16..00000000 --- a/src/base/abci/abcAttach.c +++ /dev/null @@ -1,404 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcAttach.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Attaches the library gates to the current network.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcAttach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "main.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define ATTACH_FULL (~((unsigned)0)) -#define ATTACH_MASK(n) ((~((unsigned)0)) >> (32-(n))) - -static void Abc_AttachSetupTruthTables( unsigned uTruths[][2] ); -static void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthNode ); -static Mio_Gate_t * Abc_AttachFind( Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned * uTruthNode, int * Perm ); -static int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode ); -static int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] ); -static void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm ); - -static char ** s_pPerms = NULL; -static int s_nPerms; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Attaches gates from the current library to the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkAttach( Abc_Ntk_t * pNtk ) -{ - Mio_Library_t * pGenlib; - unsigned ** puTruthGates; - unsigned uTruths[6][2]; - Abc_Obj_t * pNode; - Mio_Gate_t ** ppGates; - int nGates, nFanins, i; - - assert( Abc_NtkIsSopLogic(pNtk) ); - - // check that the library is available - pGenlib = Abc_FrameReadLibGen(); - if ( pGenlib == NULL ) - { - printf( "The current library is not available.\n" ); - return 0; - } - - // start the truth tables - Abc_AttachSetupTruthTables( uTruths ); - - // collect all the gates - ppGates = Mio_CollectRoots( pGenlib, 6, (float)1.0e+20, 1, &nGates ); - - // derive the gate truth tables - puTruthGates = ALLOC( unsigned *, nGates ); - puTruthGates[0] = ALLOC( unsigned, 2 * nGates ); - for ( i = 1; i < nGates; i++ ) - puTruthGates[i] = puTruthGates[i-1] + 2; - for ( i = 0; i < nGates; i++ ) - Mio_DeriveTruthTable( ppGates[i], uTruths, Mio_GateReadInputs(ppGates[i]), 6, puTruthGates[i] ); - - // assign the gates to pNode->pCopy - Abc_NtkCleanCopy( pNtk ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - nFanins = Abc_ObjFaninNum(pNode); - if ( nFanins == 0 ) - { - if ( Abc_SopIsConst1(pNode->pData) ) - pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst1(pGenlib); - else - pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadConst0(pGenlib); - } - else if ( nFanins == 1 ) - { - if ( Abc_SopIsBuf(pNode->pData) ) - pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadBuf(pGenlib); - else - pNode->pCopy = (Abc_Obj_t *)Mio_LibraryReadInv(pGenlib); - } - else if ( nFanins > 6 ) - { - printf( "Cannot attach gate with more than 6 inputs to node %s.\n", Abc_ObjName(pNode) ); - free( puTruthGates[0] ); - free( puTruthGates ); - free( ppGates ); - return 0; - } - else if ( !Abc_NodeAttach( pNode, ppGates, puTruthGates, nGates, uTruths ) ) - { - printf( "Could not attach the library gate to node %s.\n", Abc_ObjName(pNode) ); - free( puTruthGates[0] ); - free( puTruthGates ); - free( ppGates ); - return 0; - } - } - free( puTruthGates[0] ); - free( puTruthGates ); - free( ppGates ); - FREE( s_pPerms ); - - // perform the final transformation - Abc_NtkForEachNode( pNtk, pNode, i ) - { - if ( pNode->pCopy == NULL ) - { - printf( "Some elementary gates (constant, buffer, or inverter) are missing in the library.\n" ); - return 0; - } - } - - // replace SOP representation by the gate representation - Abc_NtkForEachNode( pNtk, pNode, i ) - pNode->pData = pNode->pCopy, pNode->pCopy = NULL; - pNtk->ntkFunc = ABC_FUNC_MAP; - Extra_MmFlexStop( pNtk->pManFunc ); - pNtk->pManFunc = pGenlib; - - printf( "Library gates are successfully attached to the nodes.\n" ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtk ) ) - { - printf( "Abc_NtkAttach: The network check has failed.\n" ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTruthGates, int nGates, unsigned uTruths[][2] ) -{ - int Perm[10]; - int pTempInts[10]; - unsigned uTruthNode[2]; - Abc_Obj_t * pFanin; - Mio_Gate_t * pGate; - int nFanins, i; - - // compute the node's truth table - Abc_AttachComputeTruth( pNode->pData, uTruths, uTruthNode ); - // find the matching gate and permutation - pGate = Abc_AttachFind( ppGates, puTruthGates, nGates, uTruthNode, Perm ); - if ( pGate == NULL ) - return 0; - // permute the fanins - nFanins = Abc_ObjFaninNum(pNode); - Abc_ObjForEachFanin( pNode, pFanin, i ) - pTempInts[i] = pFanin->Id; - for ( i = 0; i < nFanins; i++ ) - pNode->vFanins.pArray[Perm[i]] = pTempInts[i]; - // set the gate - pNode->pCopy = (Abc_Obj_t *)pGate; - return 1; -} - -/**Function************************************************************* - - Synopsis [Sets up the truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AttachSetupTruthTables( unsigned uTruths[][2] ) -{ - int m, v; - for ( v = 0; v < 5; v++ ) - uTruths[v][0] = 0; - // set up the truth tables - for ( m = 0; m < 32; m++ ) - for ( v = 0; v < 5; v++ ) - if ( m & (1 << v) ) - uTruths[v][0] |= (1 << m); - // make adjustments for the case of 6 variables - for ( v = 0; v < 5; v++ ) - uTruths[v][1] = uTruths[v][0]; - uTruths[5][0] = 0; - uTruths[5][1] = ATTACH_FULL; -} - -/**Function************************************************************* - - Synopsis [Compute the truth table of the node's cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_AttachComputeTruth( char * pSop, unsigned uTruthsIn[][2], unsigned * uTruthRes ) -{ -// Mvc_Cube_t * pCube; - unsigned uSignCube[2]; - int Value; -// int nInputs = pCover->nBits/2; - int nInputs = 6; - int nFanins = Abc_SopGetVarNum(pSop); - char * pCube; - int k; - - // make sure that the number of input truth tables in equal to the number of gate inputs - assert( nInputs < 7 ); - - // clean the resulting truth table - uTruthRes[0] = 0; - uTruthRes[1] = 0; - if ( nInputs < 6 ) - { - // consider the case when only one unsigned can be used -// Mvc_CoverForEachCube( pCover, pCube ) - Abc_SopForEachCube( pSop, nFanins, pCube ) - { - uSignCube[0] = ATTACH_FULL; -// Mvc_CubeForEachVarValue( pCover, pCube, Var, Value ) - Abc_CubeForEachVar( pCube, Value, k ) - { - if ( Value == '0' ) - uSignCube[0] &= ~uTruthsIn[k][0]; - else if ( Value == '1' ) - uSignCube[0] &= uTruthsIn[k][0]; - } - uTruthRes[0] |= uSignCube[0]; - } - if ( Abc_SopGetPhase(pSop) == 0 ) - uTruthRes[0] = ~uTruthRes[0]; - if ( nInputs < 5 ) - uTruthRes[0] &= ATTACH_MASK(1<= 0 ) - { - for ( v = 0; v < 6; v++ ) - Perm[v] = v; - return ppGates[iNum]; - } - // get permutations - if ( s_pPerms == NULL ) - { - s_pPerms = Extra_Permutations( 6 ); - s_nPerms = Extra_Factorial( 6 ); - } - // try permutations - for ( i = 0; i < s_nPerms; i++ ) - { - Abc_TruthPermute( s_pPerms[i], 6, uTruthNode, uTruthPerm ); - if ( (iNum = Abc_AttachCompare( puTruthGates, nGates, uTruthPerm )) >= 0 ) - { - for ( v = 0; v < 6; v++ ) - Perm[v] = (int)s_pPerms[i][v]; - return ppGates[iNum]; - } - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Find the gate by truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_AttachCompare( unsigned ** puTruthGates, int nGates, unsigned * uTruthNode ) -{ - int i; - for ( i = 0; i < nGates; i++ ) - if ( puTruthGates[i][0] == uTruthNode[0] && puTruthGates[i][1] == uTruthNode[1] ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [Permutes the 6-input truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_TruthPermute( char * pPerm, int nVars, unsigned * uTruthNode, unsigned * uTruthPerm ) -{ - int nMints, iMintPerm, iMint, v; - uTruthPerm[0] = uTruthPerm[1] = 0; - nMints = (1 << nVars); - for ( iMint = 0; iMint < nMints; iMint++ ) - { - if ( (uTruthNode[iMint>>5] & (1 << (iMint&31))) == 0 ) - continue; - iMintPerm = 0; - for ( v = 0; v < nVars; v++ ) - if ( iMint & (1 << v) ) - iMintPerm |= (1 << pPerm[v]); - uTruthPerm[iMintPerm>>5] |= (1 << (iMintPerm&31)); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcAuto.c b/src/base/abci/abcAuto.c deleted file mode 100644 index 40212c17..00000000 --- a/src/base/abci/abcAuto.c +++ /dev/null @@ -1,239 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcAuto.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Computation of autosymmetries.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcAuto.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive ); -static void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ) -{ - DdManager * dd; // the BDD manager used to hold shared BDDs - DdNode ** pbGlobal; // temporary storage for global BDDs - char ** pInputNames; // pointers to the CI names - char ** pOutputNames; // pointers to the CO names - int nOutputs, nInputs, i; - Vec_Ptr_t * vFuncsGlob; - Abc_Obj_t * pObj; - - // compute the global BDDs - if ( Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose) == NULL ) - return; - - // get information about the network - nInputs = Abc_NtkCiNum(pNtk); - nOutputs = Abc_NtkCoNum(pNtk); -// dd = pNtk->pManGlob; - dd = Abc_NtkGlobalBddMan( pNtk ); - - // complement the global functions - vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); - pbGlobal = (DdNode **)Vec_PtrArray( vFuncsGlob ); - - // get the network names - pInputNames = Abc_NtkCollectCioNames( pNtk, 0 ); - pOutputNames = Abc_NtkCollectCioNames( pNtk, 1 ); - - // print the size of the BDDs - if ( fVerbose ) - printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - - // allocate additional variables - for ( i = 0; i < nInputs; i++ ) - Cudd_bddNewVar( dd ); - assert( Cudd_ReadSize(dd) == 2 * nInputs ); - - // create ZDD variables in the manager - Cudd_zddVarsFromBddVars( dd, 2 ); - - // perform the analysis of the primary output functions for auto-symmetry - if ( Output == -1 ) - Abc_NtkAutoPrintAll( dd, nInputs, pbGlobal, nOutputs, pInputNames, pOutputNames, fNaive ); - else - Abc_NtkAutoPrintOne( dd, nInputs, pbGlobal, Output, pInputNames, pOutputNames, fNaive ); - - // deref the PO functions -// Abc_NtkFreeGlobalBdds( pNtk ); - // stop the global BDD manager -// Extra_StopManager( pNtk->pManGlob ); -// pNtk->pManGlob = NULL; - Abc_NtkFreeGlobalBdds( pNtk, 1 ); - free( pInputNames ); - free( pOutputNames ); - Vec_PtrFree( vFuncsGlob ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAutoPrintAll( DdManager * dd, int nInputs, DdNode * pbOutputs[], int nOutputs, char * pInputNames[], char * pOutputNames[], int fNaive ) -{ - DdNode * bSpace1, * bSpace2, * bCanVars, * bReduced, * zEquations; - double nMints; - int nSupp, SigCounter, o; - - int nAutos; - int nAutoSyms; - int nAutoSymsMax; - int nAutoSymsMaxSupp; - int nAutoSymOuts; - int nSuppSizeMax; - int clk; - - nAutoSymOuts = 0; - nAutoSyms = 0; - nAutoSymsMax = 0; - nAutoSymsMaxSupp = 0; - nSuppSizeMax = 0; - clk = clock(); - - SigCounter = 0; - for ( o = 0; o < nOutputs; o++ ) - { -// bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[o] ); Cudd_Ref( bSpace1 ); - bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[o], pbOutputs[o] ); Cudd_Ref( bSpace1 ); - bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars ); - bReduced = Extra_bddSpaceReduce( dd, pbOutputs[o], bCanVars ); Cudd_Ref( bReduced ); - zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations ); - - nSupp = Cudd_SupportSize( dd, bSpace1 ); - nMints = Cudd_CountMinterm( dd, bSpace1, nSupp ); - nAutos = Extra_Base2LogDouble(nMints); - printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", o, nSupp, nAutos ); - - if ( nAutos > 0 ) - { - nAutoSymOuts++; - nAutoSyms += nAutos; - if ( nAutoSymsMax < nAutos ) - { - nAutoSymsMax = nAutos; - nAutoSymsMaxSupp = nSupp; - } - } - if ( nSuppSizeMax < nSupp ) - nSuppSizeMax = nSupp; - - -//PRB( dd, bCanVars ); -//PRB( dd, bReduced ); -//Cudd_PrintMinterm( dd, bReduced ); -//printf( "The equations are:\n" ); -//Cudd_zddPrintCover( dd, zEquations ); -//printf( "\n" ); -//fflush( stdout ); - - bSpace2 = Extra_bddSpaceFromMatrixPos( dd, zEquations ); Cudd_Ref( bSpace2 ); -//PRB( dd, bSpace1 ); -//PRB( dd, bSpace2 ); - if ( bSpace1 != bSpace2 ) - printf( "Spaces are NOT EQUAL!\n" ); -// else -// printf( "Spaces are equal.\n" ); - - Cudd_RecursiveDeref( dd, bSpace1 ); - Cudd_RecursiveDeref( dd, bSpace2 ); - Cudd_RecursiveDeref( dd, bCanVars ); - Cudd_RecursiveDeref( dd, bReduced ); - Cudd_RecursiveDerefZdd( dd, zEquations ); - } - - printf( "The cumulative statistics for all outputs:\n" ); - printf( "Ins=%3d ", nInputs ); - printf( "InMax=%3d ", nSuppSizeMax ); - printf( "Outs=%3d ", nOutputs ); - printf( "Auto=%3d ", nAutoSymOuts ); - printf( "SumK=%3d ", nAutoSyms ); - printf( "KMax=%2d ", nAutoSymsMax ); - printf( "Supp=%3d ", nAutoSymsMaxSupp ); - printf( "Time=%4.2f ", (float)(clock() - clk)/(float)(CLOCKS_PER_SEC) ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAutoPrintOne( DdManager * dd, int nInputs, DdNode * pbOutputs[], int Output, char * pInputNames[], char * pOutputNames[], int fNaive ) -{ - DdNode * bSpace1, * bCanVars, * bReduced, * zEquations; - double nMints; - int nSupp, SigCounter; - int nAutos; - - SigCounter = 0; - bSpace1 = Extra_bddSpaceFromFunctionFast( dd, pbOutputs[Output] ); Cudd_Ref( bSpace1 ); -// bSpace1 = Extra_bddSpaceFromFunction( dd, pbOutputs[Output], pbOutputs[Output] ); Cudd_Ref( bSpace1 ); - bCanVars = Extra_bddSpaceCanonVars( dd, bSpace1 ); Cudd_Ref( bCanVars ); - bReduced = Extra_bddSpaceReduce( dd, pbOutputs[Output], bCanVars ); Cudd_Ref( bReduced ); - zEquations = Extra_bddSpaceEquations( dd, bSpace1 ); Cudd_Ref( zEquations ); - - nSupp = Cudd_SupportSize( dd, bSpace1 ); - nMints = Cudd_CountMinterm( dd, bSpace1, nSupp ); - nAutos = Extra_Base2LogDouble(nMints); - printf( "Output #%3d: Inputs = %2d. AutoK = %2d.\n", Output, nSupp, nAutos ); - - Cudd_RecursiveDeref( dd, bSpace1 ); - Cudd_RecursiveDeref( dd, bCanVars ); - Cudd_RecursiveDeref( dd, bReduced ); - Cudd_RecursiveDerefZdd( dd, zEquations ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcBalance.c b/src/base/abci/abcBalance.c deleted file mode 100644 index f9b3384e..00000000 --- a/src/base/abci/abcBalance.c +++ /dev/null @@ -1,613 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcBalance.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Performs global balancing of the AIG by the number of levels.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel ); -static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel ); -static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vSuper, int Level, int fDuplicate, bool fSelective ); -static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective ); -static void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ); -static Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode ); - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Balances the AIG network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate, bool fSelective, bool fUpdateLevel ) -{ - extern void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ); - Abc_Ntk_t * pNtkAig; - assert( Abc_NtkIsStrash(pNtk) ); - // compute the required times - if ( fSelective ) - { - Abc_NtkStartReverseLevels( pNtk, 0 ); - Abc_NtkMarkCriticalNodes( pNtk ); - } - // perform balancing - pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // transfer HAIG - Abc_NtkHaigTranfer( pNtk, pNtkAig ); - // perform balancing - Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate, fSelective, fUpdateLevel ); - Abc_NtkFinalize( pNtk, pNtkAig ); - // undo the required times - if ( fSelective ) - { - Abc_NtkStopReverseLevels( pNtk ); - Abc_NtkCleanMarkA( pNtk ); - } - if ( pNtk->pExdc ) - pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); - // make sure everything is okay - if ( !Abc_NtkCheck( pNtkAig ) ) - { - printf( "Abc_NtkBalance: The network check has failed.\n" ); - Abc_NtkDelete( pNtkAig ); - return NULL; - } - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Balances the AIG network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate, bool fSelective, bool fUpdateLevel ) -{ - int fCheck = 1; - ProgressBar * pProgress; - Vec_Vec_t * vStorage; - Abc_Obj_t * pNode, * pDriver; - int i; - - // set the level of PIs of AIG according to the arrival times of the old network - Abc_NtkSetNodeLevelsArrival( pNtk ); - // allocate temporary storage for supergates - vStorage = Vec_VecStart( 10 ); - // perform balancing of POs - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // strash the driver node - pDriver = Abc_ObjFanin0(pNode); - Abc_NodeBalance_rec( pNtkAig, pDriver, vStorage, 0, fDuplicate, fSelective, fUpdateLevel ); - } - Extra_ProgressBarStop( pProgress ); - Vec_VecFree( vStorage ); -} - -/**Function************************************************************* - - Synopsis [Finds the left bound on the next candidate to be paired.] - - Description [The nodes in the array are in the decreasing order of levels. - The last node in the array has the smallest level. By default it would be paired - with the next node on the left. However, it may be possible to pair it with some - other node on the left, in such a way that the new node is shared. This procedure - finds the index of the left-most node, which can be paired with the last node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) -{ - Abc_Obj_t * pNodeRight, * pNodeLeft; - int Current; - // if two or less nodes, pair with the first - if ( Vec_PtrSize(vSuper) < 3 ) - return 0; - // set the pointer to the one before the last - Current = Vec_PtrSize(vSuper) - 2; - pNodeRight = Vec_PtrEntry( vSuper, Current ); - // go through the nodes to the left of this one - for ( Current--; Current >= 0; Current-- ) - { - // get the next node on the left - pNodeLeft = Vec_PtrEntry( vSuper, Current ); - // if the level of this node is different, quit the loop - if ( Abc_ObjRegular(pNodeLeft)->Level != Abc_ObjRegular(pNodeRight)->Level ) - break; - } - Current++; - // get the node, for which the equality holds - pNodeLeft = Vec_PtrEntry( vSuper, Current ); - assert( Abc_ObjRegular(pNodeLeft)->Level == Abc_ObjRegular(pNodeRight)->Level ); - return Current; -} - -/**Function************************************************************* - - Synopsis [Moves closer to the end the node that is best for sharing.] - - Description [If there is no node with sharing, randomly chooses one of - the legal nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeBalancePermute( Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vSuper, int LeftBound ) -{ - Abc_Obj_t * pNode1, * pNode2, * pNode3; - int RightBound, i; - // get the right bound - RightBound = Vec_PtrSize(vSuper) - 2; - assert( LeftBound <= RightBound ); - if ( LeftBound == RightBound ) - return; - // get the two last nodes - pNode1 = Vec_PtrEntry( vSuper, RightBound + 1 ); - pNode2 = Vec_PtrEntry( vSuper, RightBound ); - // find the first node that can be shared - for ( i = RightBound; i >= LeftBound; i-- ) - { - pNode3 = Vec_PtrEntry( vSuper, i ); - if ( Abc_AigAndLookup( pNtkNew->pManFunc, pNode1, pNode3 ) ) - { - if ( pNode3 == pNode2 ) - return; - Vec_PtrWriteEntry( vSuper, i, pNode2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pNode3 ); - return; - } - } -/* - // we did not find the node to share, randomize choice - { - int Choice = rand() % (RightBound - LeftBound + 1); - pNode3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); - if ( pNode3 == pNode2 ) - return; - Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pNode2 ); - Vec_PtrWriteEntry( vSuper, RightBound, pNode3 ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Rebalances the multi-input node rooted at pNodeOld.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, Vec_Vec_t * vStorage, int Level, bool fDuplicate, bool fSelective, bool fUpdateLevel ) -{ - Abc_Aig_t * pMan = pNtkNew->pManFunc; - Abc_Obj_t * pNodeNew, * pNode1, * pNode2; - Vec_Ptr_t * vSuper; - int i, LeftBound; - assert( !Abc_ObjIsComplement(pNodeOld) ); - // return if the result if known - if ( pNodeOld->pCopy ) - return pNodeOld->pCopy; - assert( Abc_ObjIsNode(pNodeOld) ); - // get the implication supergate -// Abc_NodeBalanceConeExor( pNodeOld ); - vSuper = Abc_NodeBalanceCone( pNodeOld, vStorage, Level, fDuplicate, fSelective ); - if ( vSuper->nSize == 0 ) - { // it means that the supergate contains two nodes in the opposite polarity - pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pNtkNew)); - return pNodeOld->pCopy; - } - // for each old node, derive the new well-balanced node - for ( i = 0; i < vSuper->nSize; i++ ) - { - pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), vStorage, Level + 1, fDuplicate, fSelective, fUpdateLevel ); - vSuper->pArray[i] = Abc_ObjNotCond( pNodeNew, Abc_ObjIsComplement(vSuper->pArray[i]) ); - } - if ( vSuper->nSize < 2 ) - printf( "BUG!\n" ); - // sort the new nodes by level in the decreasing order - Vec_PtrSort( vSuper, Abc_NodeCompareLevelsDecrease ); - // balance the nodes - assert( vSuper->nSize > 1 ); - while ( vSuper->nSize > 1 ) - { - // find the left bound on the node to be paired - LeftBound = (!fUpdateLevel)? 0 : Abc_NodeBalanceFindLeft( vSuper ); - // find the node that can be shared (if no such node, randomize choice) - Abc_NodeBalancePermute( pNtkNew, vSuper, LeftBound ); - // pull out the last two nodes - pNode1 = Vec_PtrPop(vSuper); - pNode2 = Vec_PtrPop(vSuper); - Abc_VecObjPushUniqueOrderByLevel( vSuper, Abc_AigAnd(pMan, pNode1, pNode2) ); - } - // make sure the balanced node is not assigned - assert( pNodeOld->pCopy == NULL ); - // mark the old node with the new node - pNodeOld->pCopy = vSuper->pArray[0]; - vSuper->nSize = 0; -// if ( Abc_ObjRegular(pNodeOld->pCopy) == Abc_AigConst1(pNtkNew) ) -// printf( "Constant node\n" ); -// assert( pNodeOld->Level >= Abc_ObjRegular(pNodeOld->pCopy)->Level ); - // update HAIG - if ( Abc_ObjRegular(pNodeOld->pCopy)->pNtk->pHaig ) - Hop_ObjCreateChoice( pNodeOld->pEquiv, Abc_ObjRegular(pNodeOld->pCopy)->pEquiv ); - return pNodeOld->pCopy; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes in the cone delimited by fMarkA==1.] - - Description [Returns -1 if the AND-cone has the same node in both polarities. - Returns 1 if the AND-cone has the same node in the same polarity. Returns 0 - if the AND-cone has no repeated nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, Vec_Vec_t * vStorage, int Level, int fDuplicate, bool fSelective ) -{ - Vec_Ptr_t * vNodes; - int RetValue, i; - assert( !Abc_ObjIsComplement(pNode) ); - // extend the storage - if ( Vec_VecSize( vStorage ) <= Level ) - Vec_VecPush( vStorage, Level, 0 ); - // get the temporary array of nodes - vNodes = Vec_VecEntry( vStorage, Level ); - Vec_PtrClear( vNodes ); - // collect the nodes in the implication supergate - RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate, fSelective ); - assert( vNodes->nSize > 1 ); - // unmark the visited nodes - for ( i = 0; i < vNodes->nSize; i++ ) - Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0; - // if we found the node and its complement in the same implication supergate, - // return empty set of nodes (meaning that we should use constant-0 node) - if ( RetValue == -1 ) - vNodes->nSize = 0; - return vNodes; -} - - -/**Function************************************************************* - - Synopsis [Collects the nodes in the cone delimited by fMarkA==1.] - - Description [Returns -1 if the AND-cone has the same node in both polarities. - Returns 1 if the AND-cone has the same node in the same polarity. Returns 0 - if the AND-cone has no repeated nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate, bool fSelective ) -{ - int RetValue1, RetValue2, i; - // check if the node is visited - if ( Abc_ObjRegular(pNode)->fMarkB ) - { - // check if the node occurs in the same polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == pNode ) - return 1; - // check if the node is present in the opposite polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == Abc_ObjNot(pNode) ) - return -1; - assert( 0 ); - return 0; - } - // if the new node is complemented or a PI, another gate begins - if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || !fDuplicate && !fSelective && (Abc_ObjFanoutNum(pNode) > 1)) ) - { - Vec_PtrPush( vSuper, pNode ); - Abc_ObjRegular(pNode)->fMarkB = 1; - return 0; - } - assert( !Abc_ObjIsComplement(pNode) ); - assert( Abc_ObjIsNode(pNode) ); - // go through the branches - RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate, fSelective ); - RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate, fSelective ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - // return 1 if at least one branch has a duplicate - return RetValue1 || RetValue2; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeBalanceConeExor_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst ) -{ - int RetValue1, RetValue2, i; - // check if the node occurs in the same polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == pNode ) - return 1; - // if the new node is complemented or a PI, another gate begins - if ( !fFirst && (!pNode->fExor || !Abc_ObjIsNode(pNode)) ) - { - Vec_PtrPush( vSuper, pNode ); - return 0; - } - assert( !Abc_ObjIsComplement(pNode) ); - assert( Abc_ObjIsNode(pNode) ); - assert( pNode->fExor ); - // go through the branches - RetValue1 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin0(Abc_ObjFanin0(pNode)), vSuper, 0 ); - RetValue2 = Abc_NodeBalanceConeExor_rec( Abc_ObjFanin1(Abc_ObjFanin0(pNode)), vSuper, 0 ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - // return 1 if at least one branch has a duplicate - return RetValue1 || RetValue2; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NodeBalanceConeExor( Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vSuper; - if ( !pNode->fExor ) - return NULL; - vSuper = Vec_PtrAlloc( 10 ); - Abc_NodeBalanceConeExor_rec( pNode, vSuper, 1 ); - printf( "%d ", Vec_PtrSize(vSuper) ); - Vec_PtrFree( vSuper ); - return NULL; -} - - - -/**Function************************************************************* - - Synopsis [Collects the nodes in the implication supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NodeFindCone_rec( Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNodeC, * pNodeT, * pNodeE; - int RetValue, i; - assert( !Abc_ObjIsComplement(pNode) ); - if ( Abc_ObjIsCi(pNode) ) - return NULL; - // start the new array - vNodes = Vec_PtrAlloc( 4 ); - // if the node is the MUX collect its fanins - if ( Abc_NodeIsMuxType(pNode) ) - { - pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); - Vec_PtrPush( vNodes, Abc_ObjRegular(pNodeC) ); - Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeT) ); - Vec_PtrPushUnique( vNodes, Abc_ObjRegular(pNodeE) ); - } - else - { - // collect the nodes in the implication supergate - RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, 1, 0 ); - assert( vNodes->nSize > 1 ); - // unmark the visited nodes - Vec_PtrForEachEntry( vNodes, pNode, i ) - Abc_ObjRegular(pNode)->fMarkB = 0; - // if we found the node and its complement in the same implication supergate, - // return empty set of nodes (meaning that we should use constant-0 node) - if ( RetValue == -1 ) - vNodes->nSize = 0; - } - // call for the fanin - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - pNode = Abc_ObjRegular(pNode); - if ( pNode->pCopy ) - continue; - pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Attaches the implication supergates to internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i; - Abc_NtkCleanCopy( pNtk ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - pNode = Abc_ObjFanin0(pNode); - if ( pNode->pCopy ) - continue; - pNode->pCopy = (Abc_Obj_t *)Abc_NodeFindCone_rec( pNode ); - } -} - -/**Function************************************************************* - - Synopsis [Attaches the implication supergates to internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i; - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( pNode->pCopy ) - { - Vec_PtrFree( (Vec_Ptr_t *)pNode->pCopy ); - pNode->pCopy = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Compute levels of implication supergates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkBalanceLevel_rec( Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vSuper; - Abc_Obj_t * pFanin; - int i, LevelMax; - assert( !Abc_ObjIsComplement(pNode) ); - if ( pNode->Level > 0 ) - return pNode->Level; - if ( Abc_ObjIsCi(pNode) ) - return 0; - vSuper = (Vec_Ptr_t *)pNode->pCopy; - assert( vSuper != NULL ); - LevelMax = 0; - Vec_PtrForEachEntry( vSuper, pFanin, i ) - { - pFanin = Abc_ObjRegular(pFanin); - Abc_NtkBalanceLevel_rec(pFanin); - if ( LevelMax < (int)pFanin->Level ) - LevelMax = pFanin->Level; - } - pNode->Level = LevelMax + 1; - return pNode->Level; -} - - -/**Function************************************************************* - - Synopsis [Compute levels of implication supergates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkBalanceLevel( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i; - Abc_NtkForEachObj( pNtk, pNode, i ) - pNode->Level = 0; - Abc_NtkForEachCo( pNtk, pNode, i ) - Abc_NtkBalanceLevel_rec( Abc_ObjFanin0(pNode) ); -} - - -/**Function************************************************************* - - Synopsis [Marks the nodes on the critical and near critical paths.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMarkCriticalNodes( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, Counter = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( Abc_ObjRequiredLevel(pNode) - pNode->Level <= 1 ) - pNode->fMarkA = 1, Counter++; - printf( "The number of nodes on the critical paths = %6d (%5.2f %%)\n", Counter, 100.0 * Counter / Abc_NtkNodeNum(pNtk) ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcBmc.c b/src/base/abci/abcBmc.c deleted file mode 100644 index af6d237b..00000000 --- a/src/base/abci/abcBmc.c +++ /dev/null @@ -1,115 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcBmc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Performs bounded model check.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcBmc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ); - -static void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkBmc( Abc_Ntk_t * pNtk, int nFrames, int fInit, int fVerbose ) -{ - Ivy_FraigParams_t Params, * pParams = &Params; - Ivy_Man_t * pMan, * pFrames, * pFraig; - Vec_Ptr_t * vMapping; - // convert to IVY manager - pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); - // generate timeframes - pFrames = Ivy_ManFrames( pMan, Abc_NtkLatchNum(pNtk), nFrames, fInit, &vMapping ); - // fraig the timeframes - Ivy_FraigParamsDefault( pParams ); - pParams->nBTLimitNode = ABC_INFINITY; - pParams->fVerbose = 0; - pParams->fProve = 0; - pFraig = Ivy_FraigPerform( pFrames, pParams ); -printf( "Frames have %6d nodes. ", Ivy_ManNodeNum(pFrames) ); -printf( "Fraig has %6d nodes.\n", Ivy_ManNodeNum(pFraig) ); - // report the classes -// if ( fVerbose ) -// Abc_NtkBmcReport( pMan, pFrames, pFraig, vMapping, nFrames ); - // free stuff - Vec_PtrFree( vMapping ); - Ivy_ManStop( pFraig ); - Ivy_ManStop( pFrames ); - Ivy_ManStop( pMan ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkBmcReport( Ivy_Man_t * pMan, Ivy_Man_t * pFrames, Ivy_Man_t * pFraig, Vec_Ptr_t * vMapping, int nFrames ) -{ - Ivy_Obj_t * pFirst1, * pFirst2, * pFirst3; - int i, f, nIdMax, Prev2, Prev3; - nIdMax = Ivy_ManObjIdMax(pMan); - // check what is the number of nodes in each frame - Prev2 = Prev3 = 0; - for ( f = 0; f < nFrames; f++ ) - { - Ivy_ManForEachNode( pMan, pFirst1, i ) - { - pFirst2 = Ivy_Regular( Vec_PtrEntry(vMapping, f * nIdMax + pFirst1->Id) ); - if ( Ivy_ObjIsConst1(pFirst2) || pFirst2->Type == 0 ) - continue; - pFirst3 = Ivy_Regular( pFirst2->pEquiv ); - if ( Ivy_ObjIsConst1(pFirst3) || pFirst3->Type == 0 ) - continue; - break; - } - if ( f ) - printf( "Frame %3d : Strash = %5d Fraig = %5d\n", f, pFirst2->Id - Prev2, pFirst3->Id - Prev3 ); - Prev2 = pFirst2->Id; - Prev3 = pFirst3->Id; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcCas.c b/src/base/abci/abcCas.c deleted file mode 100644 index 4ed7a774..00000000 --- a/src/base/abci/abcCas.c +++ /dev/null @@ -1,111 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcCas.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Decomposition of shared BDDs into LUT cascade.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcCas.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -/* - This LUT cascade synthesis algorithm is described in the paper: - A. Mishchenko and T. Sasao, "Encoding of Boolean functions and its - application to LUT cascade synthesis", Proc. IWLS '02, pp. 115-120. - http://www.eecs.berkeley.edu/~alanmi/publications/2002/iwls02_enc.pdf -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ) -{ - DdManager * dd; - DdNode ** ppOutputs; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pNode; - char * pFileGeneric; - int fBddSizeMax = 500000; - int fReorder = 1; - int i, clk = clock(); - - assert( Abc_NtkIsStrash(pNtk) ); - // compute the global BDDs - if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL ) - return NULL; - - if ( fVerbose ) - { - DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); - printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - PRT( "BDD construction time", clock() - clk ); - } - - // collect global BDDs - dd = Abc_NtkGlobalBddMan( pNtk ); - ppOutputs = ALLOC( DdNode *, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - ppOutputs[i] = Abc_ObjGlobalBdd(pNode); - - // call the decomposition - pFileGeneric = Extra_FileNameGeneric( pNtk->pSpec ); - if ( !Abc_CascadeExperiment( pFileGeneric, dd, ppOutputs, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), nLutSize, fCheck, fVerbose ) ) - { - // the LUT size is too small - } - - // for now, duplicate the network - pNtkNew = Abc_NtkDup( pNtk ); - - // cleanup - Abc_NtkFreeGlobalBdds( pNtk, 1 ); - free( ppOutputs ); - free( pFileGeneric ); - -// if ( pNtk->pExdc ) -// pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkCollapse: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcClpBdd.c b/src/base/abci/abcClpBdd.c deleted file mode 100644 index 341ff5b0..00000000 --- a/src/base/abci/abcClpBdd.c +++ /dev/null @@ -1,162 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcCollapse.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Collapsing the network into two-levels.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ); -static Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collapses the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fVerbose ) -{ - Abc_Ntk_t * pNtkNew; - int clk = clock(); - - assert( Abc_NtkIsStrash(pNtk) ); - // compute the global BDDs - if ( Abc_NtkBuildGlobalBdds(pNtk, fBddSizeMax, 1, fReorder, fVerbose) == NULL ) - return NULL; - if ( fVerbose ) - { - DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); - printf( "Shared BDD size = %6d nodes. ", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - PRT( "BDD construction time", clock() - clk ); - } - - // create the new network - pNtkNew = Abc_NtkFromGlobalBdds( pNtk ); -// Abc_NtkFreeGlobalBdds( pNtk ); - Abc_NtkFreeGlobalBdds( pNtk, 1 ); - if ( pNtkNew == NULL ) - { -// Cudd_Quit( pNtk->pManGlob ); -// pNtk->pManGlob = NULL; - return NULL; - } -// Extra_StopManager( pNtk->pManGlob ); -// pNtk->pManGlob = NULL; - - // make the network minimum base - Abc_NtkMinimumBase( pNtkNew ); - - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkCollapse: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Derives the network with the given global BDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromGlobalBdds( Abc_Ntk_t * pNtk ) -{ - ProgressBar * pProgress; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pNode, * pDriver, * pNodeNew; -// DdManager * dd = pNtk->pManGlob; - DdManager * dd = Abc_NtkGlobalBddMan( pNtk ); - int i; - // start the new network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); - // make sure the new manager has the same number of inputs - Cudd_bddIthVar( pNtkNew->pManFunc, dd->size-1 ); - // process the POs - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - pDriver = Abc_ObjFanin0(pNode); - if ( Abc_ObjIsCi(pDriver) && !strcmp(Abc_ObjName(pNode), Abc_ObjName(pDriver)) ) - { - Abc_ObjAddFanin( pNode->pCopy, pDriver->pCopy ); - continue; - } -// pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Vec_PtrEntry(pNtk->vFuncsGlob, i) ); - pNodeNew = Abc_NodeFromGlobalBdds( pNtkNew, dd, Abc_ObjGlobalBdd(pNode) ); - Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); - } - Extra_ProgressBarStop( pProgress ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Derives the network with the given global BDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeFromGlobalBdds( Abc_Ntk_t * pNtkNew, DdManager * dd, DdNode * bFunc ) -{ - Abc_Obj_t * pNodeNew, * pTemp; - int i; - // create a new node - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - // add the fanins in the order, in which they appear in the reordered manager - Abc_NtkForEachCi( pNtkNew, pTemp, i ) - Abc_ObjAddFanin( pNodeNew, Abc_NtkCi(pNtkNew, dd->invperm[i]) ); - // transfer the function - pNodeNew->pData = Extra_TransferLevelByLevel( dd, pNtkNew->pManFunc, bFunc ); Cudd_Ref( pNodeNew->pData ); - return pNodeNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcClpSop.c b/src/base/abci/abcClpSop.c deleted file mode 100644 index de92243f..00000000 --- a/src/base/abci/abcClpSop.c +++ /dev/null @@ -1,53 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcCollapse.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Collapsing the network into two-levels.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collapses the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkCollapseSop( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Abc_Ntk_t * pNtkNew; - pNtkNew = NULL; - return pNtkNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcCut.c b/src/base/abci/abcCut.c deleted file mode 100644 index d399ce5f..00000000 --- a/src/base/abci/abcCut.c +++ /dev/null @@ -1,620 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcCut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Interface to cut computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "cut.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ); -static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ); - -extern int nTotal, nGood, nEqual; - -static Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); -static int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) -{ - ProgressBar * pProgress; - Cut_Man_t * p; - Abc_Obj_t * pObj, * pNode; - Vec_Ptr_t * vNodes; - Vec_Int_t * vChoices; - int i; - int clk = clock(); - - extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ); - extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); - - nTotal = nGood = nEqual = 0; - - assert( Abc_NtkIsStrash(pNtk) ); - // start the manager - pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); - p = Cut_ManStart( pParams ); - // compute node attributes if local or global cuts are requested - if ( pParams->fGlobal || pParams->fLocal ) - { - extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); - Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) ); - } - // prepare for cut dropping - if ( pParams->fDrop ) - Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); - // set cuts for PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) > 0 ) - Cut_NodeSetTriv( p, pObj->Id ); - // compute cuts for internal nodes - vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs - vChoices = Vec_IntAlloc( 100 ); - pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - // when we reached a CO, it is time to deallocate the cuts - if ( Abc_ObjIsCo(pObj) ) - { - if ( pParams->fDrop ) - Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); - continue; - } - // skip constant node, it has no cuts -// if ( Abc_NodeIsConst(pObj) ) -// continue; - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // compute the cuts to the internal node - Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree ); - // consider dropping the fanins cuts - if ( pParams->fDrop ) - { - Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); - Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); - } - // add cuts due to choices - if ( Abc_AigNodeIsChoice(pObj) ) - { - Vec_IntClear( vChoices ); - for ( pNode = pObj; pNode; pNode = pNode->pData ) - Vec_IntPush( vChoices, pNode->Id ); - Cut_NodeUnionCuts( p, vChoices ); - } - } - Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vNodes ); - Vec_IntFree( vChoices ); - Cut_ManPrintStats( p ); -PRT( "TOTAL ", clock() - clk ); - printf( "Area = %d.\n", Abc_NtkComputeArea( pNtk, p ) ); -//Abc_NtkPrintCuts( p, pNtk, 0 ); -// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk ); - - // temporary printout of stats - if ( nTotal ) - printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal ); - return p; -} - -/**Function************************************************************* - - Synopsis [Cut computation using the oracle.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p ) -{ - Abc_Obj_t * pObj; - Vec_Ptr_t * vNodes; - int i, clk = clock(); - int fDrop = Cut_OracleReadDrop(p); - - assert( Abc_NtkIsStrash(pNtk) ); - - // prepare cut droppping - if ( fDrop ) - Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); - - // set cuts for PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) > 0 ) - Cut_OracleNodeSetTriv( p, pObj->Id ); - - // compute cuts for internal nodes - vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - // when we reached a CO, it is time to deallocate the cuts - if ( Abc_ObjIsCo(pObj) ) - { - if ( fDrop ) - Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); - continue; - } - // skip constant node, it has no cuts -// if ( Abc_NodeIsConst(pObj) ) -// continue; - // compute the cuts to the internal node - Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), - Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); - // consider dropping the fanins cuts - if ( fDrop ) - { - Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); - Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); - } - } - Vec_PtrFree( vNodes ); -//PRT( "Total", clock() - clk ); -//Abc_NtkPrintCuts_( p, pNtk, 0 ); -} - - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) -{ -/* - Cut_Man_t * p; - Abc_Obj_t * pObj, * pNode; - int i, nIters, fStatus; - Vec_Int_t * vChoices; - int clk = clock(); - - assert( Abc_NtkIsSeq(pNtk) ); - assert( pParams->fSeq ); -// assert( Abc_NtkIsDfsOrdered(pNtk) ); - - // start the manager - pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); - pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk ); - p = Cut_ManStart( pParams ); - - // set cuts for the constant node and the PIs - pObj = Abc_AigConst1(pNtk); - if ( Abc_ObjFanoutNum(pObj) > 0 ) - Cut_NodeSetTriv( p, pObj->Id ); - Abc_NtkForEachPi( pNtk, pObj, i ) - { -//printf( "Setting trivial cut %d.\n", pObj->Id ); - Cut_NodeSetTriv( p, pObj->Id ); - } - // label the cutset nodes and set their number in the array - // assign the elementary cuts to the cutset nodes - Abc_SeqForEachCutsetNode( pNtk, pObj, i ) - { - assert( pObj->fMarkC == 0 ); - pObj->fMarkC = 1; - pObj->pCopy = (Abc_Obj_t *)i; - Cut_NodeSetTriv( p, pObj->Id ); -//printf( "Setting trivial cut %d.\n", pObj->Id ); - } - - // process the nodes - vChoices = Vec_IntAlloc( 100 ); - for ( nIters = 0; nIters < 10; nIters++ ) - { -//printf( "ITERATION %d:\n", nIters ); - // compute the cuts for the internal nodes - Abc_AigForEachAnd( pNtk, pObj, i ) - { - Abc_NodeGetCutsSeq( p, pObj, nIters==0 ); - // add cuts due to choices - if ( Abc_AigNodeIsChoice(pObj) ) - { - Vec_IntClear( vChoices ); - for ( pNode = pObj; pNode; pNode = pNode->pData ) - Vec_IntPush( vChoices, pNode->Id ); - Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 ); - } - } - // merge the new cuts with the old cuts - Abc_NtkForEachPi( pNtk, pObj, i ) - Cut_NodeNewMergeWithOld( p, pObj->Id ); - Abc_AigForEachAnd( pNtk, pObj, i ) - Cut_NodeNewMergeWithOld( p, pObj->Id ); - // for the cutset, transfer temp cuts to new cuts - fStatus = 0; - Abc_SeqForEachCutsetNode( pNtk, pObj, i ) - fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i ); - if ( fStatus == 0 ) - break; - } - Vec_IntFree( vChoices ); - - // if the status is not finished, transfer new to old for the cutset - Abc_SeqForEachCutsetNode( pNtk, pObj, i ) - Cut_NodeNewMergeWithOld( p, pObj->Id ); - - // transfer the old cuts to the new positions - Abc_NtkForEachObj( pNtk, pObj, i ) - Cut_NodeOldTransferToNew( p, pObj->Id ); - - // unlabel the cutset nodes - Abc_SeqForEachCutsetNode( pNtk, pObj, i ) - pObj->fMarkC = 0; -if ( pParams->fVerbose ) -{ - Cut_ManPrintStats( p ); -PRT( "TOTAL ", clock() - clk ); -printf( "Converged after %d iterations.\n", nIters ); -} -//Abc_NtkPrintCuts( p, pNtk, 1 ); - return p; -*/ - return NULL; -} - -/**Function************************************************************* - - Synopsis [Computes area.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkComputeArea( Abc_Ntk_t * pNtk, Cut_Man_t * p ) -{ - Abc_Obj_t * pObj; - int Counter, i; - Counter = 0; - Abc_NtkForEachCo( pNtk, pObj, i ) - Counter += Cut_ManMappingArea_rec( p, Abc_ObjFaninId0(pObj) ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) -{ - void * pList; - if ( pList = Abc_NodeReadCuts( p, pObj ) ) - return pList; - Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree ); - Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree ); - return Abc_NodeGetCuts( p, pObj, fDag, fTree ); -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) -{ - Abc_Obj_t * pFanin; - int fDagNode, fTriv, TreeCode = 0; -// assert( Abc_NtkIsStrash(pObj->pNtk) ); - assert( Abc_ObjFaninNum(pObj) == 2 ); - - - // check if the node is a DAG node - fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)); - // increment the counter of DAG nodes - if ( fDagNode ) Cut_ManIncrementDagNodes( p ); - // add the trivial cut if the node is a DAG node, or if we compute all cuts - fTriv = fDagNode || !fDag; - // check if fanins are DAG nodes - if ( fTree ) - { - pFanin = Abc_ObjFanin0(pObj); - TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)); - pFanin = Abc_ObjFanin1(pObj); - TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1); - } - - - // changes due to the global/local cut computation - { - Cut_Params_t * pParams = Cut_ManReadParams(p); - if ( pParams->fLocal ) - { - Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p); - fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id ); - if ( fDagNode ) Cut_ManIncrementDagNodes( p ); -// fTriv = fDagNode || !pParams->fGlobal; - fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id ); - TreeCode = 0; - pFanin = Abc_ObjFanin0(pObj); - TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id ); - pFanin = Abc_ObjFanin1(pObj); - TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1); - } - } - return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), - Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode ); -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv ) -{ -/* - int CutSetNum; - assert( Abc_NtkIsSeq(pObj->pNtk) ); - assert( Abc_ObjFaninNum(pObj) == 2 ); - fTriv = pObj->fMarkC ? 0 : fTriv; - CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1; - Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), - Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum ); -*/ -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ) -{ - return Cut_NodeReadCutsNew( p, pObj->Id ); -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ) -{ - Cut_NodeFreeCuts( p, pObj->Id ); -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ) -{ - Cut_Man_t * pMan = p; - Cut_Cut_t * pList; - Abc_Obj_t * pObj; - int i; - printf( "Cuts of the network:\n" ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - pList = Abc_NodeReadCuts( p, pObj ); - printf( "Node %s:\n", Abc_ObjName(pObj) ); - Cut_CutPrintList( pList, fSeq ); - } -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ) -{ - Cut_Man_t * pMan = p; - Cut_Cut_t * pList; - Abc_Obj_t * pObj; - pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 ); - pList = Abc_NodeReadCuts( p, pObj ); - printf( "Node %s:\n", Abc_ObjName(pObj) ); - Cut_CutPrintList( pList, fSeq ); -} - - - - -/**Function************************************************************* - - Synopsis [Assigns global attributes randomly.] - - Description [Old code.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) -{ - Vec_Int_t * vAttrs; -// Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj;//, * pTemp; - int i;//, k; - int nNodesTotal = 0, nMffcsTotal = 0; - extern Vec_Ptr_t * Abc_NodeMffsInsideCollect( Abc_Obj_t * pNode ); - - vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); -// Abc_NtkForEachCi( pNtk, pObj, i ) -// Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); - - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( Abc_ObjIsNode(pObj) ) - nNodesTotal++; - if ( Abc_ObjIsCo(pObj) && Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) - nMffcsTotal += Abc_NodeMffcSize( Abc_ObjFanin0(pObj) ); -// if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) ) -// if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) ) - if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) ) - { - int nMffc = Abc_NodeMffcSize(pObj); - nMffcsTotal += Abc_NodeMffcSize(pObj); -// printf( "%d ", nMffc ); - - if ( nMffc > 2 || Abc_ObjFanoutNum(pObj) > 8 ) - Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); - } - } -/* - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( Vec_IntEntry( vAttrs, pObj->Id ) ) - { - vNodes = Abc_NodeMffsInsideCollect( pObj ); - Vec_PtrForEachEntry( vNodes, pTemp, k ) - if ( pTemp != pObj ) - Vec_IntWriteEntry( vAttrs, pTemp->Id, 0 ); - Vec_PtrFree( vNodes ); - } - } -*/ - printf( "Total nodes = %d. Total MFFC nodes = %d.\n", nNodesTotal, nMffcsTotal ); - return vAttrs; -} - -/**Function************************************************************* - - Synopsis [Assigns global attributes randomly.] - - Description [Old code.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkSubDagSize_rec( Abc_Obj_t * pObj, Vec_Int_t * vAttrs ) -{ - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return 0; - Abc_NodeSetTravIdCurrent(pObj); - if ( Vec_IntEntry( vAttrs, pObj->Id ) ) - return 0; - if ( Abc_ObjIsCi(pObj) ) - return 1; - assert( Abc_ObjFaninNum(pObj) == 2 ); - return 1 + Abc_NtkSubDagSize_rec(Abc_ObjFanin0(pObj), vAttrs) + - Abc_NtkSubDagSize_rec(Abc_ObjFanin1(pObj), vAttrs); -} - -/**Function************************************************************* - - Synopsis [Assigns global attributes randomly.] - - Description [Old code.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkGetNodeAttributes2( Abc_Ntk_t * pNtk ) -{ - Vec_Int_t * vAttrs; - Abc_Obj_t * pObj; - int i, nSize; - assert( Abc_NtkIsDfsOrdered(pNtk) ); - vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - // skip no-nodes and nodes without fanouts - if ( pObj->Id == 0 || !(Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) ) - continue; - // the node has more than one fanout - count its sub-DAG size - Abc_NtkIncrementTravId( pNtk ); - nSize = Abc_NtkSubDagSize_rec( pObj, vAttrs ); - if ( nSize > 15 ) - Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); - } - return vAttrs; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcDar.c b/src/base/abci/abcDar.c deleted file mode 100644 index f7616abc..00000000 --- a/src/base/abci/abcDar.c +++ /dev/null @@ -1,1212 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcDar.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [DAG-aware rewriting.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcDar.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "aig.h" -#include "dar.h" -#include "cnf.h" -#include "fra.h" -#include "fraig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Converts the network from the AIG manager into ABC.] - - Description [Assumes that registers are ordered after PIs/POs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fRegisters ) -{ - Aig_Man_t * pMan; - Aig_Obj_t * pObjNew; - Abc_Obj_t * pObj; - int i, nNodes, nDontCares; - // make sure the latches follow PIs/POs - if ( fRegisters ) - { - assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( i < Abc_NtkPiNum(pNtk) ) - assert( Abc_ObjIsPi(pObj) ); - else - assert( Abc_ObjIsBo(pObj) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - if ( i < Abc_NtkPoNum(pNtk) ) - assert( Abc_ObjIsPo(pObj) ); - else - assert( Abc_ObjIsBi(pObj) ); - // print warning about initial values - nDontCares = 0; - Abc_NtkForEachLatch( pNtk, pObj, i ) - if ( Abc_LatchIsInitDc(pObj) ) - { - Abc_LatchSetInit0(pObj); - nDontCares++; - } - if ( nDontCares ) - { - printf( "Warning: %d registers in this network have don't-care init values.\n", nDontCares ); - printf( "The don't-care are assumed to be 0. The result may not verify.\n" ); - printf( "Use command \"print_latch\" to see the init values of registers.\n" ); - printf( "Use command \"init\" to change the values.\n" ); - } - } - // create the manager - pMan = Aig_ManStart( Abc_NtkNodeNum(pNtk) + 100 ); - pMan->pName = Extra_UtilStrsav( pNtk->pName ); - // save the number of registers - if ( fRegisters ) - { - pMan->nRegs = Abc_NtkLatchNum(pNtk); - pMan->vFlopNums = Vec_IntStartNatural( pMan->nRegs ); - } - // transfer the pointers to the basic nodes - Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Aig_ManConst1(pMan); - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)Aig_ObjCreatePi(pMan); - // complement the 1-values registers - if ( fRegisters ) - Abc_NtkForEachLatch( pNtk, pObj, i ) - if ( Abc_LatchIsInit1(pObj) ) - Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy); - // perform the conversion of the internal nodes (assumes DFS ordering) -// pMan->fAddStrash = 1; - Abc_NtkForEachNode( pNtk, pObj, i ) - { - pObj->pCopy = (Abc_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj), (Aig_Obj_t *)Abc_ObjChild1Copy(pObj) ); -// printf( "%d->%d ", pObj->Id, ((Aig_Obj_t *)pObj->pCopy)->Id ); - } - pMan->fAddStrash = 0; - // create the POs - Abc_NtkForEachCo( pNtk, pObj, i ) - Aig_ObjCreatePo( pMan, (Aig_Obj_t *)Abc_ObjChild0Copy(pObj) ); - // complement the 1-valued registers - if ( fRegisters ) - Aig_ManForEachLiSeq( pMan, pObjNew, i ) - if ( Abc_LatchIsInit1(Abc_ObjFanout0(Abc_NtkCo(pNtk,i))) ) - pObjNew->pFanin0 = Aig_Not(pObjNew->pFanin0); - // remove dangling nodes - if ( nNodes = Aig_ManCleanup( pMan ) ) - printf( "Abc_NtkToDar(): Unexpected %d dangling nodes when converting to AIG!\n", nNodes ); -Aig_ManDumpVerilog( pMan, "test.v" ); - if ( !Aig_ManCheck( pMan ) ) - { - printf( "Abc_NtkToDar: AIG check has failed.\n" ); - Aig_ManStop( pMan ); - return NULL; - } - return pMan; -} - -/**Function************************************************************* - - Synopsis [Converts the network from the AIG manager into ABC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromDar( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) -{ - Vec_Ptr_t * vNodes; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObjNew; - Aig_Obj_t * pObj; - int i; -// assert( Aig_ManRegNum(pMan) == Abc_NtkLatchNum(pNtkOld) ); - // perform strashing - pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // transfer the pointers to the basic nodes - Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); - Aig_ManForEachPi( pMan, pObj, i ) - pObj->pData = Abc_NtkCi(pNtkNew, i); - // rebuild the AIG - vNodes = Aig_ManDfs( pMan ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - if ( Aig_ObjIsBuf(pObj) ) - pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); - else - pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); - Vec_PtrFree( vNodes ); - // connect the PO nodes - Aig_ManForEachPo( pMan, pObj, i ) - { - if ( pMan->nAsserts && i == Aig_ManPoNum(pMan) - pMan->nAsserts ) - break; - Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); - } - // if there are assertions, add them - if ( pMan->nAsserts > 0 ) - Aig_ManForEachAssert( pMan, pObj, i ) - { - pObjNew = Abc_NtkCreateAssert(pNtkNew); - Abc_ObjAssignName( pObjNew, "assert_", Abc_ObjName(pObjNew) ); - Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); - } - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Converts the network from the AIG manager into ABC.] - - Description [This procedure should be called after seq sweeping, - which changes the number of registers.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) -{ - Vec_Ptr_t * vNodes; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObjNew, * pLatch; - Aig_Obj_t * pObj, * pObjLo, * pObjLi; - int i; -// assert( Aig_ManRegNum(pMan) != Abc_NtkLatchNum(pNtkOld) ); - // perform strashing - pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // transfer the pointers to the basic nodes - Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); - Aig_ManForEachPiSeq( pMan, pObj, i ) - pObj->pData = Abc_NtkCi(pNtkNew, i); - // create as many latches as there are registers in the manager - Aig_ManForEachLiLoSeq( pMan, pObjLi, pObjLo, i ) - { - pObjNew = Abc_NtkCreateLatch( pNtkNew ); - pObjLi->pData = Abc_NtkCreateBi( pNtkNew ); - pObjLo->pData = Abc_NtkCreateBo( pNtkNew ); - Abc_ObjAddFanin( pObjNew, pObjLi->pData ); - Abc_ObjAddFanin( pObjLo->pData, pObjNew ); - Abc_LatchSetInit0( pObjNew ); - } - if ( pMan->vFlopNums == NULL ) - Abc_NtkAddDummyBoxNames( pNtkNew ); - else - { - assert( Abc_NtkBoxNum(pNtkOld) == Abc_NtkLatchNum(pNtkOld) ); - Abc_NtkForEachLatch( pNtkNew, pObjNew, i ) - { - pLatch = Abc_NtkBox( pNtkOld, Vec_IntEntry( pMan->vFlopNums, i ) ); - Abc_ObjAssignName( pObjNew, Abc_ObjName(pLatch), NULL ); - Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pLatch)), NULL ); - Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pLatch)), NULL ); - } - } - // rebuild the AIG - vNodes = Aig_ManDfs( pMan ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - if ( Aig_ObjIsBuf(pObj) ) - pObj->pData = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); - else - pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); - Vec_PtrFree( vNodes ); - // connect the PO nodes - Aig_ManForEachPo( pMan, pObj, i ) - { - if ( pMan->nAsserts && i == Aig_ManPoNum(pMan) - pMan->nAsserts ) - break; - Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); - } - // if there are assertions, add them - if ( pMan->nAsserts > 0 ) - Aig_ManForEachAssert( pMan, pObj, i ) - { - pObjNew = Abc_NtkCreateAssert(pNtkNew); - Abc_ObjAssignName( pObjNew, "assert_", Abc_ObjName(pObjNew) ); - Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); - } - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Converts the network from the AIG manager into ABC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromDarChoices( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) -{ - Vec_Ptr_t * vNodes; - Abc_Ntk_t * pNtkNew; - Aig_Obj_t * pObj, * pTemp; - int i; - assert( pMan->pEquivs != NULL ); - assert( Aig_ManBufNum(pMan) == 0 ); - // perform strashing - pNtkNew = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // transfer the pointers to the basic nodes - Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); - Aig_ManForEachPi( pMan, pObj, i ) - pObj->pData = Abc_NtkCi(pNtkNew, i); - - // rebuild the AIG - vNodes = Aig_ManDfsChoices( pMan ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Aig_ObjChild0Copy(pObj), (Abc_Obj_t *)Aig_ObjChild1Copy(pObj) ); - if ( pTemp = pMan->pEquivs[pObj->Id] ) - { - Abc_Obj_t * pAbcRepr, * pAbcObj; - assert( pTemp->pData != NULL ); - pAbcRepr = pObj->pData; - pAbcObj = pTemp->pData; - pAbcObj->pData = pAbcRepr->pData; - pAbcRepr->pData = pAbcObj; - } - } -//printf( "Total = %d. Collected = %d.\n", Aig_ManNodeNum(pMan), Vec_PtrSize(vNodes) ); - Vec_PtrFree( vNodes ); - // connect the PO nodes - Aig_ManForEachPo( pMan, pObj, i ) - Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Aig_ObjChild0Copy(pObj) ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkFromDar(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Converts the network from the AIG manager into ABC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromDarSeq( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ) -{ - Vec_Ptr_t * vNodes; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; - Aig_Obj_t * pObj; - int i; -// assert( Aig_ManLatchNum(pMan) > 0 ); - // perform strashing - pNtkNew = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // transfer the pointers to the basic nodes - Aig_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); - Aig_ManForEachPi( pMan, pObj, i ) - pObj->pData = Abc_NtkPi(pNtkNew, i); - // create latches of the new network - Aig_ManForEachObj( pMan, pObj, i ) - { - if ( !Aig_ObjIsLatch(pObj) ) - continue; - pObjNew = Abc_NtkCreateLatch( pNtkNew ); - pFaninNew0 = Abc_NtkCreateBi( pNtkNew ); - pFaninNew1 = Abc_NtkCreateBo( pNtkNew ); - Abc_ObjAddFanin( pObjNew, pFaninNew0 ); - Abc_ObjAddFanin( pFaninNew1, pObjNew ); - Abc_LatchSetInit0( pObjNew ); - pObj->pData = Abc_ObjFanout0( pObjNew ); - } - Abc_NtkAddDummyBoxNames( pNtkNew ); - // rebuild the AIG - vNodes = Aig_ManDfs( pMan ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - // add the first fanin - pObj->pData = pFaninNew0 = (Abc_Obj_t *)Aig_ObjChild0Copy(pObj); - if ( Aig_ObjIsBuf(pObj) ) - continue; - // add the second fanin - pFaninNew1 = (Abc_Obj_t *)Aig_ObjChild1Copy(pObj); - // create the new node - if ( Aig_ObjIsExor(pObj) ) - pObj->pData = pObjNew = Abc_AigXor( pNtkNew->pManFunc, pFaninNew0, pFaninNew1 ); - else - pObj->pData = pObjNew = Abc_AigAnd( pNtkNew->pManFunc, pFaninNew0, pFaninNew1 ); - } - Vec_PtrFree( vNodes ); - // connect the PO nodes - Aig_ManForEachPo( pMan, pObj, i ) - { - pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj ); - Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, i), pFaninNew ); - } - // connect the latches - Aig_ManForEachObj( pMan, pObj, i ) - { - if ( !Aig_ObjIsLatch(pObj) ) - continue; - pFaninNew = (Abc_Obj_t *)Aig_ObjChild0Copy( pObj ); - Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pObj->pData)), pFaninNew ); - } - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Collect latch values.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkGetLatchValues( Abc_Ntk_t * pNtk ) -{ - Vec_Int_t * vInits; - Abc_Obj_t * pLatch; - int i; - vInits = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - assert( Abc_LatchIsInit1(pLatch) == 0 ); - Vec_IntPush( vInits, Abc_LatchIsInit1(pLatch) ); - } - return vInits; -} - -/**Function************************************************************* - - Synopsis [Performs verification after retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkSecRetime( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 ) -{ - int fRemove1, fRemove2; - Aig_Man_t * pMan1, * pMan2; - int * pArray; - - fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0)); - fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0)); - - - pMan1 = Abc_NtkToDar( pNtk1, 0 ); - pMan2 = Abc_NtkToDar( pNtk2, 0 ); - - Aig_ManPrintStats( pMan1 ); - Aig_ManPrintStats( pMan2 ); - -// pArray = Abc_NtkGetLatchValues(pNtk1); - pArray = NULL; - Aig_ManSeqStrash( pMan1, Abc_NtkLatchNum(pNtk1), pArray ); - free( pArray ); - -// pArray = Abc_NtkGetLatchValues(pNtk2); - pArray = NULL; - Aig_ManSeqStrash( pMan2, Abc_NtkLatchNum(pNtk2), pArray ); - free( pArray ); - - Aig_ManPrintStats( pMan1 ); - Aig_ManPrintStats( pMan2 ); - - Aig_ManStop( pMan1 ); - Aig_ManStop( pMan2 ); - - - if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); - if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDar( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkAig = NULL; - Aig_Man_t * pMan; - extern void Fra_ManPartitionTest( Aig_Man_t * p, int nComLim ); - - assert( Abc_NtkIsStrash(pNtk) ); - // convert to the AIG manager - pMan = Abc_NtkToDar( pNtk, 0 ); - if ( pMan == NULL ) - return NULL; - - // perform computation -// Fra_ManPartitionTest( pMan, 4 ); - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Aig_ManStop( pMan ); - - // make sure everything is okay - if ( pNtkAig && !Abc_NtkCheck( pNtkAig ) ) - { - printf( "Abc_NtkDar: The network check has failed.\n" ); - Abc_NtkDelete( pNtkAig ); - return NULL; - } - return pNtkAig; -} - - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose ) -{ - Fra_Par_t Pars, * pPars = &Pars; - Abc_Ntk_t * pNtkAig; - Aig_Man_t * pMan, * pTemp; - pMan = Abc_NtkToDar( pNtk, 0 ); - if ( pMan == NULL ) - return NULL; - Fra_ParamsDefault( pPars ); - pPars->nBTLimitNode = nConfLimit; - pPars->fChoicing = fChoicing; - pPars->fDoSparse = fDoSparse; - pPars->fSpeculate = fSpeculate; - pPars->fProve = fProve; - pPars->fVerbose = fVerbose; - pMan = Fra_FraigPerform( pTemp = pMan, pPars ); - if ( fChoicing ) - pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan ); - else - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Aig_ManStop( pTemp ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose ) -{ - extern Aig_Man_t * Csw_Sweep( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fVerbose ); - Abc_Ntk_t * pNtkAig; - Aig_Man_t * pMan, * pTemp; - pMan = Abc_NtkToDar( pNtk, 0 ); - if ( pMan == NULL ) - return NULL; - pMan = Csw_Sweep( pTemp = pMan, nCutsMax, nLeafMax, fVerbose ); - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Aig_ManStop( pTemp ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars ) -{ - Aig_Man_t * pMan, * pTemp; - Abc_Ntk_t * pNtkAig; - int clk; - assert( Abc_NtkIsStrash(pNtk) ); - pMan = Abc_NtkToDar( pNtk, 0 ); - if ( pMan == NULL ) - return NULL; -// Aig_ManPrintStats( pMan ); -/* -// Aig_ManSupports( pMan ); - { - Vec_Vec_t * vParts; - vParts = Aig_ManPartitionSmart( pMan, 50, 1, NULL ); - Vec_VecFree( vParts ); - } -*/ - Dar_ManRewrite( pMan, pPars ); -// pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel ); -// Aig_ManStop( pTemp ); - -clk = clock(); - pMan = Aig_ManDup( pTemp = pMan, 0 ); - Aig_ManStop( pTemp ); -//PRT( "time", clock() - clk ); - -// Aig_ManPrintStats( pMan ); - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars ) -{ - Aig_Man_t * pMan, * pTemp; - Abc_Ntk_t * pNtkAig; - int clk; - assert( Abc_NtkIsStrash(pNtk) ); - pMan = Abc_NtkToDar( pNtk, 0 ); - if ( pMan == NULL ) - return NULL; -// Aig_ManPrintStats( pMan ); - - Dar_ManRefactor( pMan, pPars ); -// pMan = Dar_ManBalance( pTemp = pMan, pPars->fUpdateLevel ); -// Aig_ManStop( pTemp ); - -clk = clock(); - pMan = Aig_ManDup( pTemp = pMan, 0 ); - Aig_ManStop( pTemp ); -//PRT( "time", clock() - clk ); - -// Aig_ManPrintStats( pMan ); - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDCompress2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ) -{ - Aig_Man_t * pMan, * pTemp; - Abc_Ntk_t * pNtkAig; - int clk; - assert( Abc_NtkIsStrash(pNtk) ); - pMan = Abc_NtkToDar( pNtk, 0 ); - if ( pMan == NULL ) - return NULL; -// Aig_ManPrintStats( pMan ); - -clk = clock(); - pMan = Dar_ManCompress2( pTemp = pMan, fBalance, fUpdateLevel, fVerbose ); - Aig_ManStop( pTemp ); -//PRT( "time", clock() - clk ); - -// Aig_ManPrintStats( pMan ); - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fVerbose ) -{ - Aig_Man_t * pMan, * pTemp; - Abc_Ntk_t * pNtkAig; - assert( Abc_NtkIsStrash(pNtk) ); - pMan = Abc_NtkToDar( pNtk, 0 ); - if ( pMan == NULL ) - return NULL; - pMan = Dar_ManChoice( pTemp = pMan, fBalance, fUpdateLevel, fVerbose ); - Aig_ManStop( pTemp ); - pNtkAig = Abc_NtkFromDarChoices( pNtk, pMan ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose ) -{ - Aig_Man_t * pMan, * pTemp; - Abc_Ntk_t * pNtkAig; - int clk; - assert( Abc_NtkIsStrash(pNtk) ); - pMan = Abc_NtkToDar( pNtk, 0 ); - if ( pMan == NULL ) - return NULL; -// Aig_ManPrintStats( pMan ); - -clk = clock(); - pMan = Dar_ManRwsat( pTemp = pMan, fBalance, fVerbose ); - Aig_ManStop( pTemp ); -//PRT( "time", clock() - clk ); - -// Aig_ManPrintStats( pMan ); - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkConstructFromCnf( Abc_Ntk_t * pNtk, Cnf_Man_t * p, Vec_Ptr_t * vMapped ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pNode, * pNodeNew; - Aig_Obj_t * pObj, * pLeaf; - Cnf_Cut_t * pCut; - Vec_Int_t * vCover; - unsigned uTruth; - int i, k, nDupGates; - // create the new network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); - // make the mapper point to the new network - Aig_ManConst1(p->pManAig)->pData = Abc_NtkCreateNodeConst1(pNtkNew); - Abc_NtkForEachCi( pNtk, pNode, i ) - Aig_ManPi(p->pManAig, i)->pData = pNode->pCopy; - // process the nodes in topological order - vCover = Vec_IntAlloc( 1 << 16 ); - Vec_PtrForEachEntry( vMapped, pObj, i ) - { - // create new node - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - // add fanins according to the cut - pCut = pObj->pData; - Cnf_CutForEachLeaf( p->pManAig, pCut, pLeaf, k ) - Abc_ObjAddFanin( pNodeNew, pLeaf->pData ); - // add logic function - if ( pCut->nFanins < 5 ) - { - uTruth = 0xFFFF & *Cnf_CutTruth(pCut); - Cnf_SopConvertToVector( p->pSops[uTruth], p->pSopSizes[uTruth], vCover ); - pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, pCut->nFanins, vCover ); - } - else - pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, pCut->nFanins, pCut->vIsop[1] ); - // save the node - pObj->pData = pNodeNew; - } - Vec_IntFree( vCover ); - // add the CO drivers - Abc_NtkForEachCo( pNtk, pNode, i ) - { - pObj = Aig_ManPo(p->pManAig, i); - pNodeNew = Abc_ObjNotCond( Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); - Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); - } - - // remove the constant node if not used - pNodeNew = (Abc_Obj_t *)Aig_ManConst1(p->pManAig)->pData; - if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) - Abc_NtkDeleteObj( pNodeNew ); - // minimize the node -// Abc_NtkSweep( pNtkNew, 0 ); - // decouple the PO driver nodes to reduce the number of levels - nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); -// if ( nDupGates && If_ManReadVerbose(pIfMan) ) -// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkConstructFromCnf(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName ) -{ - Vec_Ptr_t * vMapped; - Aig_Man_t * pMan; - Cnf_Man_t * pManCnf; - Cnf_Dat_t * pCnf; - Abc_Ntk_t * pNtkNew = NULL; - assert( Abc_NtkIsStrash(pNtk) ); - - // convert to the AIG manager - pMan = Abc_NtkToDar( pNtk, 0 ); - if ( pMan == NULL ) - return NULL; - if ( !Aig_ManCheck( pMan ) ) - { - printf( "Abc_NtkDarToCnf: AIG check has failed.\n" ); - Aig_ManStop( pMan ); - return NULL; - } - // perform balance - Aig_ManPrintStats( pMan ); - - // derive CNF - pCnf = Cnf_Derive( pMan, 0 ); - pManCnf = Cnf_ManRead(); - - // write the network for verification - vMapped = Cnf_ManScanMapping( pManCnf, 1, 0 ); - pNtkNew = Abc_NtkConstructFromCnf( pNtk, pManCnf, vMapped ); - Vec_PtrFree( vMapped ); - - // write CNF into a file - Cnf_DataWriteIntoFile( pCnf, pFileName, 0 ); - Cnf_DataFree( pCnf ); - Cnf_ClearMemory(); - - Aig_ManStop( pMan ); - return pNtkNew; -} - - -/**Function************************************************************* - - Synopsis [Solves combinational miter using a SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose ) -{ - sat_solver * pSat; - Aig_Man_t * pMan; - Cnf_Dat_t * pCnf; - int status, RetValue, clk = clock(); - Vec_Int_t * vCiIds; - - assert( Abc_NtkIsStrash(pNtk) ); - assert( Abc_NtkLatchNum(pNtk) == 0 ); - assert( Abc_NtkPoNum(pNtk) == 1 ); - - // conver to the manager - pMan = Abc_NtkToDar( pNtk, 0 ); - // derive CNF - pCnf = Cnf_Derive( pMan, 0 ); -// pCnf = Cnf_DeriveSimple( pMan, 0 ); - // convert into the SAT solver - pSat = Cnf_DataWriteIntoSolver( pCnf ); - vCiIds = Cnf_DataCollectPiSatNums( pCnf, pMan ); - Aig_ManStop( pMan ); - Cnf_DataFree( pCnf ); - // solve SAT - if ( pSat == NULL ) - { - Vec_IntFree( vCiIds ); -// printf( "Trivially unsat\n" ); - return 1; - } - - -// printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); -// PRT( "Time", clock() - clk ); - - // simplify the problem - clk = clock(); - status = sat_solver_simplify(pSat); -// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); -// PRT( "Time", clock() - clk ); - if ( status == 0 ) - { - Vec_IntFree( vCiIds ); - sat_solver_delete( pSat ); -// printf( "The problem is UNSATISFIABLE after simplification.\n" ); - return 1; - } - - // solve the miter - clk = clock(); - if ( fVerbose ) - pSat->verbosity = 1; - status = sat_solver_solve( pSat, NULL, NULL, (sint64)nConfLimit, (sint64)nInsLimit, (sint64)0, (sint64)0 ); - if ( status == l_Undef ) - { -// printf( "The problem timed out.\n" ); - RetValue = -1; - } - else if ( status == l_True ) - { -// printf( "The problem is SATISFIABLE.\n" ); - RetValue = 0; - } - else if ( status == l_False ) - { -// printf( "The problem is UNSATISFIABLE.\n" ); - RetValue = 1; - } - else - assert( 0 ); -// PRT( "SAT sat_solver time", clock() - clk ); -// printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts ); - - // if the problem is SAT, get the counterexample - if ( status == l_True ) - { - pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); - } - // free the sat_solver - if ( fVerbose ) - Sat_SolverPrintStats( stdout, pSat ); -//sat_solver_store_write( pSat, "trace.cnf" ); -//sat_solver_store_free( pSat ); - sat_solver_delete( pSat ); - Vec_IntFree( vCiIds ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDarSeqSweep( Abc_Ntk_t * pNtk, int nFramesP, int nFramesK, int nMaxImps, int fRewrite, int fUseImps, int fLatchCorr, int fWriteImps, int fVerbose ) -{ - Fraig_Params_t Params; - Abc_Ntk_t * pNtkAig, * pNtkFraig; - Aig_Man_t * pMan, * pTemp; - int clk = clock(); - - // preprocess the miter by fraiging it - // (note that for each functional class, fraiging leaves one representative; - // so fraiging does not reduce the number of functions represented by nodes - Fraig_ParamsSetDefault( &Params ); - Params.nBTLimit = 100000; -// pNtkFraig = Abc_NtkFraig( pNtk, &Params, 0, 0 ); - pNtkFraig = Abc_NtkDup( pNtk ); -if ( fVerbose ) -{ -PRT( "Initial fraiging time", clock() - clk ); -} - - pMan = Abc_NtkToDar( pNtkFraig, 1 ); - Abc_NtkDelete( pNtkFraig ); - if ( pMan == NULL ) - return NULL; - - pMan = Fra_FraigInduction( pTemp = pMan, nFramesP, nFramesK, nMaxImps, fRewrite, fUseImps, fLatchCorr, fWriteImps, fVerbose, NULL ); - Aig_ManStop( pTemp ); - - if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) - pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); - else - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Computes latch correspondence.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDarLcorr( Abc_Ntk_t * pNtk, int nFramesP, int nConfMax, int fVerbose ) -{ - Aig_Man_t * pMan, * pTemp; - Abc_Ntk_t * pNtkAig; - pMan = Abc_NtkToDar( pNtk, 1 ); - if ( pMan == NULL ) - return NULL; - pMan = Fra_FraigLatchCorrespondence( pTemp = pMan, nFramesP, nConfMax, 0, fVerbose, NULL ); - Aig_ManStop( pTemp ); - if ( Aig_ManRegNum(pMan) < Abc_NtkLatchNum(pNtk) ) - pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); - else - pNtkAig = Abc_NtkFromDar( pNtk, pMan ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDarProve( Abc_Ntk_t * pNtk, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ) -{ - Aig_Man_t * pMan; - int RetValue; - // derive the AIG manager - pMan = Abc_NtkToDar( pNtk, 1 ); - if ( pMan == NULL ) - { - printf( "Converting miter into AIG has failed.\n" ); - return -1; - } - assert( pMan->nRegs > 0 ); - // perform verification - RetValue = Fra_FraigSec( pMan, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); - Aig_ManStop( pMan ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDarSec( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nFrames, int fRetimeFirst, int fVerbose, int fVeryVerbose ) -{ -// Fraig_Params_t Params; - Aig_Man_t * pMan; - Abc_Ntk_t * pMiter;//, * pTemp; - int RetValue; - - // get the miter of the two networks - pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 ); - if ( pMiter == NULL ) - { - printf( "Miter computation has failed.\n" ); - return 0; - } - RetValue = Abc_NtkMiterIsConstant( pMiter ); - if ( RetValue == 0 ) - { - extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); - printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); - // report the error - pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); - Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); - FREE( pMiter->pModel ); - Abc_NtkDelete( pMiter ); - return 0; - } - if ( RetValue == 1 ) - { - Abc_NtkDelete( pMiter ); - printf( "Networks are equivalent after structural hashing.\n" ); - return 1; - } - - // commented out because something became non-inductive -/* - // preprocess the miter by fraiging it - // (note that for each functional class, fraiging leaves one representative; - // so fraiging does not reduce the number of functions represented by nodes - Fraig_ParamsSetDefault( &Params ); - Params.nBTLimit = 100000; - pMiter = Abc_NtkFraig( pTemp = pMiter, &Params, 0, 0 ); - Abc_NtkDelete( pTemp ); - RetValue = Abc_NtkMiterIsConstant( pMiter ); - if ( RetValue == 0 ) - { - extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); - printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); - // report the error - pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); - Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); - FREE( pMiter->pModel ); - Abc_NtkDelete( pMiter ); - return 0; - } - if ( RetValue == 1 ) - { - Abc_NtkDelete( pMiter ); - printf( "Networks are equivalent after structural hashing.\n" ); - return 1; - } -*/ - // derive the AIG manager - pMan = Abc_NtkToDar( pMiter, 1 ); - Abc_NtkDelete( pMiter ); - if ( pMan == NULL ) - { - printf( "Converting miter into AIG has failed.\n" ); - return -1; - } - assert( pMan->nRegs > 0 ); - - // perform verification - RetValue = Fra_FraigSec( pMan, nFrames, fRetimeFirst, fVerbose, fVeryVerbose ); - Aig_ManStop( pMan ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchSweep, int fVerbose ) -{ - Abc_Ntk_t * pNtkAig; - Aig_Man_t * pMan; - pMan = Abc_NtkToDar( pNtk, 1 ); - if ( pMan == NULL ) - return NULL; - Aig_ManSeqCleanup( pMan ); - if ( fLatchSweep ) - { - if ( pMan->nRegs ) - pMan = Aig_ManReduceLaches( pMan, fVerbose ); - if ( pMan->nRegs ) - pMan = Aig_ManConstReduce( pMan, fVerbose ); - } - pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDarRetime( Abc_Ntk_t * pNtk, int nStepsMax, int fVerbose ) -{ - Abc_Ntk_t * pNtkAig; - Aig_Man_t * pMan, * pTemp; - pMan = Abc_NtkToDar( pNtk, 1 ); - if ( pMan == NULL ) - return NULL; -// Aig_ManReduceLachesCount( pMan ); - - pMan = Rtm_ManRetime( pTemp = pMan, 1, nStepsMax, 0 ); - Aig_ManStop( pTemp ); - -// pMan = Aig_ManReduceLaches( pMan, 1 ); -// pMan = Aig_ManConstReduce( pMan, 1 ); - - pNtkAig = Abc_NtkFromDarSeqSweep( pNtk, pMan ); - Aig_ManStop( pMan ); - return pNtkAig; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcDebug.c b/src/base/abci/abcDebug.c deleted file mode 100644 index 95b95d89..00000000 --- a/src/base/abci/abcDebug.c +++ /dev/null @@ -1,208 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcDebug.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Automated debugging procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcDebug.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk ); -static Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtk, int ObjNum, int fConst1 ); - -extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Takes a network and a procedure to test.] - - Description [The network demonstrates the bug in the procedure. - Procedure should return 1 if the bug is demonstrated.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) ) -{ - Abc_Ntk_t * pNtkMod; - char * pFileName = "bug_found.blif"; - int i, nSteps, nIter, ModNum, RandNum = 1, clk, clkTotal = clock(); - assert( Abc_NtkIsLogic(pNtk) ); - srand( 0x123123 ); - // create internal copy of the network - pNtk = Abc_NtkDup(pNtk); - if ( !(*pFuncError)( pNtk ) ) - { - printf( "The original network does not cause the bug. Quitting.\n" ); - Abc_NtkDelete( pNtk ); - return; - } - // perform incremental modifications - for ( nIter = 0; ; nIter++ ) - { - clk = clock(); - // count how many ways of modifying the network exists - nSteps = 2 * Abc_NtkCountFaninsTotal(pNtk); - // try modifying the network as many times - RandNum ^= rand(); - for ( i = 0; i < nSteps; i++ ) - { - // get the shifted number of bug - ModNum = (i + RandNum) % nSteps; - // get the modified network - pNtkMod = Abc_NtkAutoDebugModify( pNtk, ModNum/2, ModNum%2 ); - // write the network - Io_WriteBlifLogic( pNtk, "bug_temp.blif", 1 ); - // check if the bug is still there - if ( (*pFuncError)( pNtkMod ) ) // bug is still there - { - Abc_NtkDelete( pNtk ); - pNtk = pNtkMod; - break; - } - else // no bug - Abc_NtkDelete( pNtkMod ); - } - printf( "Iter %6d : Latches = %6d. Nodes = %6d. Steps = %6d. Error step = %3d. ", - nIter, Abc_NtkLatchNum(pNtk), Abc_NtkNodeNum(pNtk), nSteps, i ); - PRT( "Time", clock() - clk ); - if ( i == nSteps ) // could not modify it while preserving the bug - break; - } - // write out the final network - Io_WriteBlifLogic( pNtk, pFileName, 1 ); - printf( "Final network written into file \"%s\". ", pFileName ); - PRT( "Total time", clock() - clkTotal ); - Abc_NtkDelete( pNtk ); -} - -/**Function************************************************************* - - Synopsis [Counts the total number of fanins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj, * pFanin; - int i, k, Counter = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) ) - continue; - if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 ) - continue; - if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) ) - continue; - Counter++; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns the node and fanin to be modified.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkFindGivenFanin( Abc_Ntk_t * pNtk, int Step, Abc_Obj_t ** ppObj, Abc_Obj_t ** ppFanin ) -{ - Abc_Obj_t * pObj, * pFanin; - int i, k, Counter = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) ) - continue; - if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 ) - continue; - if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) ) - continue; - if ( Counter++ == Step ) - { - *ppObj = pObj; - *ppFanin = pFanin; - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Perform modification with the given number.] - - Description [Modification consists of replacing the node by a constant.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtkInit, int Step, int fConst1 ) -{ - extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ); - Abc_Ntk_t * pNtk; - Abc_Obj_t * pObj, * pFanin, * pConst; - // copy the network - pNtk = Abc_NtkDup( pNtkInit ); - assert( Abc_NtkNodeNum(pNtk) == Abc_NtkNodeNum(pNtkInit) ); - // find the object number - Abc_NtkFindGivenFanin( pNtk, Step, &pObj, &pFanin ); - // consider special case - if ( Abc_ObjIsPo(pObj) && Abc_NodeIsConst(pFanin) ) - { - Abc_NtkDeleteAll_rec( pObj ); - return pNtk; - } - // plug in a constant node - pConst = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); - Abc_ObjTransferFanout( pFanin, pConst ); - Abc_NtkDeleteAll_rec( pFanin ); - - Abc_NtkSweep( pNtk, 0 ); - Abc_NtkCleanupSeq( pNtk, 0, 0, 0 ); - Abc_NtkToSop( pNtk, 0 ); - Abc_NtkCycleInitStateSop( pNtk, 50, 0 ); - return pNtk; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcDress.c b/src/base/abci/abcDress.c deleted file mode 100644 index f8182532..00000000 --- a/src/base/abci/abcDress.c +++ /dev/null @@ -1,209 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcDress.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Transfers names from one netlist to the other.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcDress.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk ); -static void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose ); - -extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transfers names from one netlist to the other.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDress( Abc_Ntk_t * pNtkLogic, char * pFileName, int fVerbose ) -{ - Abc_Ntk_t * pNtkOrig, * pNtkLogicOrig; - Abc_Ntk_t * pMiter, * pMiterFraig; - stmm_table * tMapping; - - assert( Abc_NtkIsLogic(pNtkLogic) ); - - // get the original netlist - pNtkOrig = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 1 ); - if ( pNtkOrig == NULL ) - return; - assert( Abc_NtkIsNetlist(pNtkOrig) ); - - Abc_NtkCleanCopy(pNtkLogic); - Abc_NtkCleanCopy(pNtkOrig); - - // convert it into the logic network - pNtkLogicOrig = Abc_NtkToLogic( pNtkOrig ); - // check that the networks have the same PIs/POs/latches - if ( !Abc_NtkCompareSignals( pNtkLogic, pNtkLogicOrig, 1, 1 ) ) - { - Abc_NtkDelete( pNtkOrig ); - Abc_NtkDelete( pNtkLogicOrig ); - return; - } - - // convert the current logic network into an AIG - pMiter = Abc_NtkStrash( pNtkLogic, 1, 0, 0 ); - - // convert it into the AIG and make the netlist point to the AIG - Abc_NtkAppend( pMiter, pNtkLogicOrig, 1 ); - Abc_NtkTransferCopy( pNtkOrig ); - Abc_NtkDelete( pNtkLogicOrig ); - -if ( fVerbose ) -{ -printf( "After mitering:\n" ); -printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) ); -printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) ); -} - - // fraig the miter (miter nodes point to the fraiged miter) - pMiterFraig = Abc_NtkIvyFraig( pMiter, 100, 1, 0, 1, 0 ); - // make netlists point to the fraiged miter - Abc_NtkTransferCopy( pNtkLogic ); - Abc_NtkTransferCopy( pNtkOrig ); - Abc_NtkDelete( pMiter ); - -if ( fVerbose ) -{ -printf( "After fraiging:\n" ); -printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) ); -printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) ); -} - - // derive mapping from the fraiged nodes into their prototype nodes in the original netlist - tMapping = Abc_NtkDressDeriveMapping( pNtkOrig ); - - // transfer the names to the new netlist - Abc_NtkDressTransferNames( pNtkLogic, tMapping, fVerbose ); - - // clean up - stmm_free_table( tMapping ); - Abc_NtkDelete( pMiterFraig ); - Abc_NtkDelete( pNtkOrig ); -} - -/**Function************************************************************* - - Synopsis [Returns the mapping from the fraig nodes point into the nodes of the netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -stmm_table * Abc_NtkDressDeriveMapping( Abc_Ntk_t * pNtk ) -{ - stmm_table * tResult; - Abc_Obj_t * pNode, * pNodeMap, * pNodeFraig; - int i; - assert( Abc_NtkIsNetlist(pNtk) ); - tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // get the fraiged node - pNodeFraig = Abc_ObjRegular(pNode->pCopy); - // if this node is already mapped, skip - if ( stmm_is_member( tResult, (char *)pNodeFraig ) ) - continue; - // get the mapping of this node - pNodeMap = Abc_ObjNotCond( pNode, Abc_ObjIsComplement(pNode->pCopy) ); - // add the mapping - stmm_insert( tResult, (char *)pNodeFraig, (char *)pNodeMap ); - } - return tResult; -} - -/**Function************************************************************* - - Synopsis [Attaches the names of to the new netlist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDressTransferNames( Abc_Ntk_t * pNtk, stmm_table * tMapping, int fVerbose ) -{ - Abc_Obj_t * pNet, * pNode, * pNodeMap, * pNodeFraig; - char * pName; - int i, Counter = 0, CounterInv = 0, CounterInit = stmm_count(tMapping); - assert( Abc_NtkIsLogic(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // if the node already has a name, quit - pName = Nm_ManFindNameById( pNtk->pManName, pNode->Id ); - if ( pName != NULL ) - continue; - // get the fraiged node - pNodeFraig = Abc_ObjRegular(pNode->pCopy); - // find the matching node of the original netlist - if ( !stmm_lookup( tMapping, (char *)pNodeFraig, (char **)&pNodeMap ) ) - continue; - // find the true match - pNodeMap = Abc_ObjNotCond( pNodeMap, Abc_ObjIsComplement(pNode->pCopy) ); - // get the name - pNet = Abc_ObjFanout0(Abc_ObjRegular(pNodeMap)); - pName = Nm_ManFindNameById( pNet->pNtk->pManName, pNet->Id ); - assert( pName != NULL ); - // set the name - if ( Abc_ObjIsComplement(pNodeMap) ) - { - Abc_ObjAssignName( pNode, pName, "_inv" ); - CounterInv++; - } - else - { - Abc_ObjAssignName( pNode, pName, NULL ); - Counter++; - } - // remove the name - stmm_delete( tMapping, (char **)&pNodeFraig, (char **)&pNodeMap ); - } - if ( fVerbose ) - { - printf( "Total number of names collected = %5d.\n", CounterInit ); - printf( "Total number of names assigned = %5d. (Dir = %5d. Compl = %5d.)\n", - Counter + CounterInv, Counter, CounterInv ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcDsd.c b/src/base/abci/abcDsd.c deleted file mode 100644 index c00a7d7c..00000000 --- a/src/base/abci/abcDsd.c +++ /dev/null @@ -1,551 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcDsd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Decomposes the network using disjoint-support decomposition.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "dsd.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ); -static void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); -static Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters ); - -static Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk ); -static void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive, int * pCounters ); -static bool Abc_NodeIsForDsd( Abc_Obj_t * pNode ); -static int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the DSD network.] - - Description [Takes the strashed network (pNtk), derives global BDDs for - the combinational outputs of this network, and decomposes these BDDs using - disjoint support decomposition. Finally, constructs and return a new - network, which is topologically equivalent to the decomposition tree. - Allocates and frees a new BDD manager and a new DSD manager.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ) -{ - DdManager * dd; - Abc_Ntk_t * pNtkNew; - assert( Abc_NtkIsStrash(pNtk) ); - dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); - if ( dd == NULL ) - return NULL; - if ( fVerbose ) - printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - // transform the result of mapping into a BDD network - pNtkNew = Abc_NtkDsdInternal( pNtk, fVerbose, fPrint, fShort ); - Extra_StopManager( dd ); - if ( pNtkNew == NULL ) - return NULL; - // copy EXDC network - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkDsdGlobal: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Constructs the decomposed network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDsdInternal( Abc_Ntk_t * pNtk, bool fVerbose, bool fPrint, bool fShort ) -{ - char ** ppNamesCi, ** ppNamesCo; - Vec_Ptr_t * vFuncsGlob; - Dsd_Manager_t * pManDsd; - Abc_Ntk_t * pNtkNew; - DdManager * dd; - Abc_Obj_t * pObj; - int i; - - // complement the global functions - vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - Vec_PtrPush( vFuncsGlob, Cudd_NotCond(Abc_ObjGlobalBdd(pObj), Abc_ObjFaninC0(pObj)) ); - - // perform the decomposition - dd = Abc_NtkGlobalBddMan(pNtk); - pManDsd = Dsd_ManagerStart( dd, Abc_NtkCiNum(pNtk), fVerbose ); - Dsd_Decompose( pManDsd, (DdNode **)vFuncsGlob->pArray, Abc_NtkCoNum(pNtk) ); - Vec_PtrFree( vFuncsGlob ); - Abc_NtkFreeGlobalBdds( pNtk, 0 ); - if ( pManDsd == NULL ) - { - Cudd_Quit( dd ); - return NULL; - } - - // start the new network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); - // make sure the new manager has enough inputs - Cudd_bddIthVar( pNtkNew->pManFunc, dd->size-1 ); - // put the results into the new network (save new CO drivers in old CO drivers) - Abc_NtkDsdConstruct( pManDsd, pNtk, pNtkNew ); - // finalize the new network - Abc_NtkFinalize( pNtk, pNtkNew ); - // fix the problem with complemented and duplicated CO edges - Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); - if ( fPrint ) - { - ppNamesCi = Abc_NtkCollectCioNames( pNtk, 0 ); - ppNamesCo = Abc_NtkCollectCioNames( pNtk, 1 ); - Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, fShort, -1 ); - free( ppNamesCi ); - free( ppNamesCo ); - } - - // stop the DSD manager - Dsd_ManagerStop( pManDsd ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Constructs the decomposed network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDsdConstruct( Dsd_Manager_t * pManDsd, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) -{ - Dsd_Node_t ** ppNodesDsd; - Dsd_Node_t * pNodeDsd; - Abc_Obj_t * pNode, * pNodeNew, * pDriver; - int i, nNodesDsd; - - // save the CI nodes in the DSD nodes - Dsd_NodeSetMark( Dsd_ManagerReadConst1(pManDsd), (int)Abc_NtkCreateNodeConst1(pNtkNew) ); - Abc_NtkForEachCi( pNtk, pNode, i ) - { - pNodeDsd = Dsd_ManagerReadInput( pManDsd, i ); - Dsd_NodeSetMark( pNodeDsd, (int)pNode->pCopy ); - } - - // collect DSD nodes in DFS order (leaves and const1 are not collected) - ppNodesDsd = Dsd_TreeCollectNodesDfs( pManDsd, &nNodesDsd ); - for ( i = 0; i < nNodesDsd; i++ ) - Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNtkNew, NULL ); - free( ppNodesDsd ); - - // set the pointers to the CO drivers - Abc_NtkForEachCo( pNtk, pNode, i ) - { - pDriver = Abc_ObjFanin0( pNode ); - if ( !Abc_ObjIsNode(pDriver) ) - continue; - if ( !Abc_AigNodeIsAnd(pDriver) ) - continue; - pNodeDsd = Dsd_ManagerReadRoot( pManDsd, i ); - pNodeNew = (Abc_Obj_t *)Dsd_NodeReadMark( Dsd_Regular(pNodeDsd) ); - assert( !Abc_ObjIsComplement(pNodeNew) ); - pDriver->pCopy = Abc_ObjNotCond( pNodeNew, Dsd_IsComplement(pNodeDsd) ); - } -} - -/**Function************************************************************* - - Synopsis [Performs DSD using the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkDsdConstructNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Abc_Ntk_t * pNtkNew, int * pCounters ) -{ - DdManager * ddDsd = Dsd_ManagerReadDd( pManDsd ); - DdManager * ddNew = pNtkNew->pManFunc; - Dsd_Node_t * pFaninDsd; - Abc_Obj_t * pNodeNew, * pFanin; - DdNode * bLocal, * bTemp, * bVar; - Dsd_Type_t Type; - int i, nDecs; - - // create the new node - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - // add the fanins - Type = Dsd_NodeReadType( pNodeDsd ); - nDecs = Dsd_NodeReadDecsNum( pNodeDsd ); - assert( nDecs > 1 ); - for ( i = 0; i < nDecs; i++ ) - { - pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i ); - pFanin = (Abc_Obj_t *)Dsd_NodeReadMark(Dsd_Regular(pFaninDsd)); - Abc_ObjAddFanin( pNodeNew, pFanin ); - assert( Type == DSD_NODE_OR || !Dsd_IsComplement(pFaninDsd) ); - } - - // create the local function depending on the type of the node - ddNew = pNtkNew->pManFunc; - switch ( Type ) - { - case DSD_NODE_CONST1: - { - bLocal = ddNew->one; Cudd_Ref( bLocal ); - break; - } - case DSD_NODE_OR: - { - bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal ); - for ( i = 0; i < nDecs; i++ ) - { - pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i ); - bVar = Cudd_NotCond( ddNew->vars[i], Dsd_IsComplement(pFaninDsd) ); - bLocal = Cudd_bddOr( ddNew, bTemp = bLocal, bVar ); Cudd_Ref( bLocal ); - Cudd_RecursiveDeref( ddNew, bTemp ); - } - break; - } - case DSD_NODE_EXOR: - { - bLocal = Cudd_Not(ddNew->one); Cudd_Ref( bLocal ); - for ( i = 0; i < nDecs; i++ ) - { - bLocal = Cudd_bddXor( ddNew, bTemp = bLocal, ddNew->vars[i] ); Cudd_Ref( bLocal ); - Cudd_RecursiveDeref( ddNew, bTemp ); - } - break; - } - case DSD_NODE_PRIME: - { - if ( pCounters ) - { - if ( nDecs < 10 ) - pCounters[nDecs]++; - else - pCounters[10]++; - } - bLocal = Dsd_TreeGetPrimeFunction( ddDsd, pNodeDsd ); Cudd_Ref( bLocal ); - bLocal = Extra_TransferLevelByLevel( ddDsd, ddNew, bTemp = bLocal ); Cudd_Ref( bLocal ); -/* -if ( nDecs == 3 ) -{ -Extra_bddPrint( ddDsd, bTemp ); -printf( "\n" ); -} -*/ - Cudd_RecursiveDeref( ddDsd, bTemp ); - // bLocal is now in the new BDD manager - break; - } - default: - { - assert( 0 ); - break; - } - } - pNodeNew->pData = bLocal; - Dsd_NodeSetMark( pNodeDsd, (int)pNodeNew ); - return pNodeNew; -} - - - - - - -/**Function************************************************************* - - Synopsis [Recursively decomposes internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, bool fVerbose, bool fRecursive ) -{ - Dsd_Manager_t * pManDsd; - DdManager * dd = pNtk->pManFunc; - Vec_Ptr_t * vNodes; - int i; - int pCounters[11] = {0}; - - assert( Abc_NtkIsBddLogic(pNtk) ); - - // make the network minimum base - Abc_NtkMinimumBase( pNtk ); - - // start the DSD manager - pManDsd = Dsd_ManagerStart( dd, dd->size, 0 ); - - // collect nodes for decomposition - vNodes = Abc_NtkCollectNodesForDsd( pNtk ); - for ( i = 0; i < vNodes->nSize; i++ ) - Abc_NodeDecompDsdAndMux( vNodes->pArray[i], vNodes, pManDsd, fRecursive, pCounters ); - Vec_PtrFree( vNodes ); - - printf( "Number of non-decomposable functions:\n" ); - for ( i = 3; i < 10; i++ ) - printf( "Inputs = %d. Functions = %6d.\n", i, pCounters[i] ); - printf( "Inputs > %d. Functions = %6d.\n", 9, pCounters[10] ); - - // stop the DSD manager - Dsd_ManagerStop( pManDsd ); - - // make sure everything is okay - if ( !Abc_NtkCheck( pNtk ) ) - { - printf( "Abc_NtkDsdRecursive: The network check has failed.\n" ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Collects the nodes that may need decomposition.] - - Description [The nodes that do not need decomposition are those - whose BDD has more internal nodes than the support size.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkCollectNodesForDsd( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode; - int i; - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - if ( Abc_NodeIsForDsd(pNode) ) - Vec_PtrPush( vNodes, pNode ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Performs decomposition of one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeDecompDsdAndMux( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Dsd_Manager_t * pManDsd, bool fRecursive, int * pCounters ) -{ - DdManager * dd = pNode->pNtk->pManFunc; - Abc_Obj_t * pRoot, * pFanin, * pNode1, * pNode2, * pNodeC; - Dsd_Node_t ** ppNodesDsd, * pNodeDsd, * pFaninDsd; - int i, nNodesDsd, iVar, fCompl; - - // try disjoint support decomposition - pNodeDsd = Dsd_DecomposeOne( pManDsd, pNode->pData ); - fCompl = Dsd_IsComplement( pNodeDsd ); - pNodeDsd = Dsd_Regular( pNodeDsd ); - - // determine what decomposition to use - if ( !fRecursive || Dsd_NodeReadDecsNum(pNodeDsd) != Abc_ObjFaninNum(pNode) ) - { // perform DSD - - // set the inputs - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - pFaninDsd = Dsd_ManagerReadInput( pManDsd, i ); - Dsd_NodeSetMark( pFaninDsd, (int)pFanin ); - } - - // construct the intermediate nodes - ppNodesDsd = Dsd_TreeCollectNodesDfsOne( pManDsd, pNodeDsd, &nNodesDsd ); - for ( i = 0; i < nNodesDsd; i++ ) - { - pRoot = Abc_NtkDsdConstructNode( pManDsd, ppNodesDsd[i], pNode->pNtk, pCounters ); - if ( Abc_NodeIsForDsd(pRoot) && fRecursive ) - Vec_PtrPush( vNodes, pRoot ); - } - free( ppNodesDsd ); - - // remove the current fanins - Abc_ObjRemoveFanins( pNode ); - // add fanin to the root - Abc_ObjAddFanin( pNode, pRoot ); - // update the function to be that of buffer - Cudd_RecursiveDeref( dd, pNode->pData ); - pNode->pData = Cudd_NotCond( dd->vars[0], fCompl ); Cudd_Ref( pNode->pData ); - } - else // perform MUX-decomposition - { - // get the cofactoring variable - iVar = Abc_NodeFindMuxVar( dd, pNode->pData, Abc_ObjFaninNum(pNode) ); - pNodeC = Abc_ObjFanin( pNode, iVar ); - - // get the negative cofactor - pNode1 = Abc_NtkCloneObj( pNode ); - pNode1->pData = Cudd_Cofactor( dd, pNode->pData, Cudd_Not(dd->vars[iVar]) ); Cudd_Ref( pNode1->pData ); - Abc_NodeMinimumBase( pNode1 ); - if ( Abc_NodeIsForDsd(pNode1) ) - Vec_PtrPush( vNodes, pNode1 ); - - // get the positive cofactor - pNode2 = Abc_NtkCloneObj( pNode ); - pNode2->pData = Cudd_Cofactor( dd, pNode->pData, dd->vars[iVar] ); Cudd_Ref( pNode2->pData ); - Abc_NodeMinimumBase( pNode2 ); - if ( Abc_NodeIsForDsd(pNode2) ) - Vec_PtrPush( vNodes, pNode2 ); - - // remove the current fanins - Abc_ObjRemoveFanins( pNode ); - // add new fanins - Abc_ObjAddFanin( pNode, pNodeC ); - Abc_ObjAddFanin( pNode, pNode2 ); - Abc_ObjAddFanin( pNode, pNode1 ); - // update the function to be that of MUX - Cudd_RecursiveDeref( dd, pNode->pData ); - pNode->pData = Cudd_bddIte( dd, dd->vars[0], dd->vars[1], dd->vars[2] ); Cudd_Ref( pNode->pData ); - } -} - -/**Function************************************************************* - - Synopsis [Checks if the node should be decomposed by DSD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NodeIsForDsd( Abc_Obj_t * pNode ) -{ - DdManager * dd = pNode->pNtk->pManFunc; -// DdNode * bFunc, * bFunc0, * bFunc1; - assert( Abc_ObjIsNode(pNode) ); -// if ( Cudd_DagSize(pNode->pData)-1 > Abc_ObjFaninNum(pNode) ) -// return 1; -// return 0; - -/* - // this does not catch things like a(b+c), which should be decomposed - for ( bFunc = Cudd_Regular(pNode->pData); !cuddIsConstant(bFunc); ) - { - bFunc0 = Cudd_Regular( cuddE(bFunc) ); - bFunc1 = cuddT(bFunc); - if ( bFunc0 == b1 ) - bFunc = bFunc1; - else if ( bFunc1 == b1 || bFunc0 == bFunc1 ) - bFunc = bFunc0; - else - return 1; - } -*/ - if ( Abc_ObjFaninNum(pNode) > 2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Determines a cofactoring variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeFindMuxVar( DdManager * dd, DdNode * bFunc, int nVars ) -{ - DdNode * bVar, * bCof0, * bCof1; - int SuppSumMin = 1000000; - int i, nSSD, nSSQ, iVar; - -// printf( "\n\nCofactors:\n\n" ); - iVar = -1; - for ( i = 0; i < nVars; i++ ) - { - bVar = dd->vars[i]; - - bCof0 = Cudd_Cofactor( dd, bFunc, Cudd_Not(bVar) ); Cudd_Ref( bCof0 ); - bCof1 = Cudd_Cofactor( dd, bFunc, bVar ); Cudd_Ref( bCof1 ); - -// nodD = Cudd_DagSize(bCof0); -// nodQ = Cudd_DagSize(bCof1); -// printf( "+%02d: D=%2d. Q=%2d. ", i, nodD, nodQ ); -// printf( "S=%2d. D=%2d. ", nodD + nodQ, abs(nodD-nodQ) ); - - nSSD = Cudd_SupportSize( dd, bCof0 ); - nSSQ = Cudd_SupportSize( dd, bCof1 ); - -// printf( "SD=%2d. SQ=%2d. ", nSSD, nSSQ ); -// printf( "S=%2d. D=%2d. ", nSSD + nSSQ, abs(nSSD - nSSQ) ); -// printf( "Cost=%3d. ", Cost(nodD,nodQ,nSSD,nSSQ) ); -// printf( "\n" ); - - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); - - if ( SuppSumMin > nSSD + nSSQ ) - { - SuppSumMin = nSSD + nSSQ; - iVar = i; - } - } - return iVar; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcEspresso.c b/src/base/abci/abcEspresso.c deleted file mode 100644 index 8f9c7277..00000000 --- a/src/base/abci/abcEspresso.c +++ /dev/null @@ -1,250 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcEspresso.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures to minimize SOPs using Espresso.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcEspresso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "espresso.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NodeEspresso( Abc_Obj_t * pNode ); -static pset_family Abc_SopToEspresso( char * pSop ); -static char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover ); -static pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Minimizes SOP representations using Espresso.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Abc_Obj_t * pNode; - int i; - assert( Abc_NtkIsLogic(pNtk) ); - // convert the network to have SOPs - if ( Abc_NtkHasMapping(pNtk) ) - Abc_NtkMapToSop(pNtk); - else if ( Abc_NtkHasBdd(pNtk) ) - { - if ( !Abc_NtkBddToSop(pNtk, 0) ) - { - printf( "Abc_NtkEspresso(): Converting to SOPs has failed.\n" ); - return; - } - } - // minimize SOPs of all nodes - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( i ) Abc_NodeEspresso( pNode ); -} - -/**Function************************************************************* - - Synopsis [Minimizes SOP representation of one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeEspresso( Abc_Obj_t * pNode ) -{ - extern void define_cube_size( int n ); - pset_family Cover; - int fCompl; - - assert( Abc_ObjIsNode(pNode) ); - // define the cube for this node - define_cube_size( Abc_ObjFaninNum(pNode) ); - // create the Espresso cover - fCompl = Abc_SopIsComplement( pNode->pData ); - Cover = Abc_SopToEspresso( pNode->pData ); - // perform minimization - Cover = Abc_EspressoMinimize( Cover, NULL ); // deletes also cover - // convert back onto the node's SOP representation - pNode->pData = Abc_SopFromEspresso( pNode->pNtk->pManFunc, Cover ); - if ( fCompl ) Abc_SopComplement( pNode->pData ); - sf_free(Cover); -} - -/**Function************************************************************* - - Synopsis [Converts SOP in ABC into SOP representation in Espresso.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -pset_family Abc_SopToEspresso( char * pSop ) -{ - char * pCube; - pset_family Cover; - pset set; - int nCubes, nVars, Value, v; - - if ( pSop == NULL ) - return NULL; - - nVars = Abc_SopGetVarNum(pSop); - nCubes = Abc_SopGetCubeNum(pSop); - assert( cube.size == 2 * nVars ); - - if ( Abc_SopIsConst0(pSop) ) - { - Cover = sf_new(0, cube.size); - return Cover; - } - if ( Abc_SopIsConst1(pSop) ) - { - Cover = sf_new(1, cube.size); - set = GETSET(Cover, Cover->count++); - set_copy( set, cube.fullset ); - return Cover; - } - - // create the cover - Cover = sf_new(nCubes, cube.size); - // fill in the cubes - Abc_SopForEachCube( pSop, nVars, pCube ) - { - set = GETSET(Cover, Cover->count++); - set_copy( set, cube.fullset ); - Abc_CubeForEachVar( pCube, Value, v ) - { - if ( Value == '0' ) - set_remove(set, 2*v+1); - else if ( Value == '1' ) - set_remove(set, 2*v); - } - } - return Cover; -} - -/**Function************************************************************* - - Synopsis [Converts SOP representation in Espresso into SOP in ABC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_SopFromEspresso( Extra_MmFlex_t * pMan, pset_family Cover ) -{ - pset set; - char * pSop, * pCube; - int Lit, nVars, nCubes, i, k; - - nVars = Cover->sf_size/2; - nCubes = Cover->count; - - pSop = Abc_SopStart( pMan, nCubes, nVars ); - - // go through the cubes - i = 0; - Abc_SopForEachCube( pSop, nVars, pCube ) - { - set = GETSET(Cover, i++); - for ( k = 0; k < nVars; k++ ) - { - Lit = GETINPUT(set, k); - if ( Lit == ZERO ) - pCube[k] = '0'; - else if ( Lit == ONE ) - pCube[k] = '1'; - } - } - return pSop; -} - - -/**Function************************************************************* - - Synopsis [Minimizes the cover using Espresso.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -pset_family Abc_EspressoMinimize( pset_family pOnset, pset_family pDcset ) -{ - pset_family pOffset; - int fNewDcset, i; - int fSimple = 0; - int fSparse = 0; - - if ( fSimple ) - { - for ( i = 0; i < cube.num_vars; i++ ) - pOnset = d1merge( pOnset, i ); - pOnset = sf_contain( pOnset ); - return pOnset; - } - - // create the dcset - fNewDcset = (pDcset == NULL); - if ( pDcset == NULL ) - pDcset = sf_new( 1, cube.size ); - pDcset->wsize = pOnset->wsize; - pDcset->sf_size = pOnset->sf_size; - - // derive the offset - if ( pDcset->sf_size == 0 || pDcset->count == 0 ) - pOffset = complement(cube1list(pOnset)); - else - pOffset = complement(cube2list(pOnset, pDcset)); - - // perform minimization - skip_make_sparse = !fSparse; - pOnset = espresso( pOnset, pDcset, pOffset ); - - // free covers - sf_free( pOffset ); - if ( fNewDcset ) - sf_free( pDcset ); - return pOnset; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcExtract.c b/src/base/abci/abcExtract.c deleted file mode 100644 index 52ea03a3..00000000 --- a/src/base/abci/abcExtract.c +++ /dev/null @@ -1,51 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcMvCost.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Calculating the cost of one MV block.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcMvCost.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_MvCostTest( Abc_Ntk_t * pNtk ) -{ - -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcFpga.c b/src/base/abci/abcFpga.c deleted file mode 100644 index 3bc9fbed..00000000 --- a/src/base/abci/abcFpga.c +++ /dev/null @@ -1,278 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcFpga.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Interface with the FPGA mapping package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcFpga.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "fpgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose ); -static Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ); -static Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Interface with the FPGA mapping package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFpga( Abc_Ntk_t * pNtk, float DelayTarget, int fRecovery, int fSwitching, int fLatchPaths, int fVerbose ) -{ - int fShowSwitching = 1; - Abc_Ntk_t * pNtkNew; - Fpga_Man_t * pMan; - Vec_Int_t * vSwitching; - float * pSwitching = NULL; - - assert( Abc_NtkIsStrash(pNtk) ); - - // print a warning about choice nodes - if ( Abc_NtkGetChoiceNum( pNtk ) ) - printf( "Performing FPGA mapping with choices.\n" ); - - // compute switching activity - fShowSwitching |= fSwitching; - if ( fShowSwitching ) - { - extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ); - vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 ); - pSwitching = (float *)vSwitching->pArray; - } - - // perform FPGA mapping - pMan = Abc_NtkToFpga( pNtk, fRecovery, pSwitching, fLatchPaths, fVerbose ); - if ( pSwitching ) Vec_IntFree( vSwitching ); - if ( pMan == NULL ) - return NULL; - Fpga_ManSetSwitching( pMan, fSwitching ); - Fpga_ManSetLatchPaths( pMan, fLatchPaths ); - Fpga_ManSetLatchNum( pMan, Abc_NtkLatchNum(pNtk) ); - Fpga_ManSetDelayTarget( pMan, DelayTarget ); - if ( !Fpga_Mapping( pMan ) ) - { - Fpga_ManFree( pMan ); - return NULL; - } - - // transform the result of mapping into a BDD network - pNtkNew = Abc_NtkFromFpga( pMan, pNtk ); - if ( pNtkNew == NULL ) - return NULL; - Fpga_ManFree( pMan ); - - // make the network minimum base - Abc_NtkMinimumBase( pNtkNew ); - - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkFpga: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Load the network into FPGA manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose ) -{ - Fpga_Man_t * pMan; - ProgressBar * pProgress; - Fpga_Node_t * pNodeFpga; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode, * pFanin, * pPrev; - float * pfArrivals; - int i; - - assert( Abc_NtkIsStrash(pNtk) ); - - // start the mapping manager and set its parameters - pMan = Fpga_ManCreate( Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), fVerbose ); - if ( pMan == NULL ) - return NULL; - Fpga_ManSetAreaRecovery( pMan, fRecovery ); - Fpga_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); - pfArrivals = Abc_NtkGetCiArrivalFloats(pNtk); - if ( fLatchPaths ) - { - for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) - pfArrivals[i] = -FPGA_FLOAT_LARGE; - } - Fpga_ManSetInputArrivals( pMan, pfArrivals ); - - // create PIs and remember them in the old nodes - Abc_NtkCleanCopy( pNtk ); - Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan); - Abc_NtkForEachCi( pNtk, pNode, i ) - { - pNodeFpga = Fpga_ManReadInputs(pMan)[i]; - pNode->pCopy = (Abc_Obj_t *)pNodeFpga; - if ( pSwitching ) - Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] ); - } - - // load the AIG into the mapper - vNodes = Abc_AigDfs( pNtk, 0, 0 ); - pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // add the node to the mapper - pNodeFpga = Fpga_NodeAnd( pMan, - Fpga_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), - Fpga_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); - assert( pNode->pCopy == NULL ); - // remember the node - pNode->pCopy = (Abc_Obj_t *)pNodeFpga; - if ( pSwitching ) - Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] ); - // set up the choice node - if ( Abc_AigNodeIsChoice( pNode ) ) - for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) - { - Fpga_NodeSetNextE( (Fpga_Node_t *)pPrev->pCopy, (Fpga_Node_t *)pFanin->pCopy ); - Fpga_NodeSetRepr( (Fpga_Node_t *)pFanin->pCopy, (Fpga_Node_t *)pNode->pCopy ); - } - } - Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vNodes ); - - // set the primary outputs without copying the phase - Abc_NtkForEachCo( pNtk, pNode, i ) - Fpga_ManReadOutputs(pMan)[i] = (Fpga_Node_t *)Abc_ObjFanin0(pNode)->pCopy; - return pMan; -} - -/**Function************************************************************* - - Synopsis [Creates the mapped network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromFpga( Fpga_Man_t * pMan, Abc_Ntk_t * pNtk ) -{ - ProgressBar * pProgress; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pNode, * pNodeNew; - int i, nDupGates; - // create the new network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); - // make the mapper point to the new network - Fpga_CutsCleanSign( pMan ); - Fpga_ManCleanData0( pMan ); - Abc_NtkForEachCi( pNtk, pNode, i ) - Fpga_NodeSetData0( Fpga_ManReadInputs(pMan)[i], (char *)pNode->pCopy ); - // set the constant node -// if ( Fpga_NodeReadRefs(Fpga_ManReadConst1(pMan)) > 0 ) - Fpga_NodeSetData0( Fpga_ManReadConst1(pMan), (char *)Abc_NtkCreateNodeConst1(pNtkNew) ); - // process the nodes in topological order - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - pNodeNew = Abc_NodeFromFpga_rec( pNtkNew, Fpga_ManReadOutputs(pMan)[i] ); - assert( !Abc_ObjIsComplement(pNodeNew) ); - Abc_ObjFanin0(pNode)->pCopy = pNodeNew; - } - Extra_ProgressBarStop( pProgress ); - // finalize the new network - Abc_NtkFinalize( pNtk, pNtkNew ); - // remove the constant node if not used - pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0(Fpga_ManReadConst1(pMan)); - if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) - Abc_NtkDeleteObj( pNodeNew ); - // decouple the PO driver nodes to reduce the number of levels - nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); -// if ( nDupGates && Fpga_ManReadVerbose(pMan) ) -// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Derive one node after FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeFromFpga_rec( Abc_Ntk_t * pNtkNew, Fpga_Node_t * pNodeFpga ) -{ - Fpga_Cut_t * pCutBest; - Fpga_Node_t ** ppLeaves; - Abc_Obj_t * pNodeNew; - int i, nLeaves; - assert( !Fpga_IsComplement(pNodeFpga) ); - // return if the result if known - pNodeNew = (Abc_Obj_t *)Fpga_NodeReadData0( pNodeFpga ); - if ( pNodeNew ) - return pNodeNew; - assert( Fpga_NodeIsAnd(pNodeFpga) ); - // get the parameters of the best cut - pCutBest = Fpga_NodeReadCutBest( pNodeFpga ); - ppLeaves = Fpga_CutReadLeaves( pCutBest ); - nLeaves = Fpga_CutReadLeavesNum( pCutBest ); - // create a new node - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - for ( i = 0; i < nLeaves; i++ ) - Abc_ObjAddFanin( pNodeNew, Abc_NodeFromFpga_rec(pNtkNew, ppLeaves[i]) ); - // derive the function of this node - pNodeNew->pData = Fpga_TruthsCutBdd( pNtkNew->pManFunc, pCutBest ); Cudd_Ref( pNodeNew->pData ); - Fpga_NodeSetData0( pNodeFpga, (char *)pNodeNew ); - return pNodeNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcFpgaFast.c b/src/base/abci/abcFpgaFast.c deleted file mode 100644 index 356b855e..00000000 --- a/src/base/abci/abcFpgaFast.c +++ /dev/null @@ -1,190 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcFpgaFast.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Fast FPGA mapper.] - - Author [Sungmin Cho] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcFpgaFast.c,v 1.00 2006/09/02 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ); - -static Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ); -static Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes ); - -static inline void Abc_ObjSetIvy2Abc( Ivy_Man_t * p, int IvyId, Abc_Obj_t * pObjAbc ) { assert(Vec_PtrEntry(p->pCopy, IvyId) == NULL); assert(!Abc_ObjIsComplement(pObjAbc)); Vec_PtrWriteEntry( p->pCopy, IvyId, pObjAbc ); } -static inline Abc_Obj_t * Abc_ObjGetIvy2Abc( Ivy_Man_t * p, int IvyId ) { return Vec_PtrEntry( p->pCopy, IvyId ); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs fast FPGA mapping of the network.] - - Description [Takes the AIG to be mapped, the LUT size, and verbosity - flag. Produces the new network by fast FPGA mapping of the current - network. If the current network in ABC in not an AIG, the user should - run command "strash" to make sure that the current network into an AIG - before calling this procedure.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFpgaFast( Abc_Ntk_t * pNtk, int nLutSize, int fRecovery, int fVerbose ) -{ - Ivy_Man_t * pMan; - Abc_Ntk_t * pNtkNew; - // make sure the network is an AIG - assert( Abc_NtkIsStrash(pNtk) ); - // convert the network into the AIG - pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); - // perform fast FPGA mapping - Ivy_FastMapPerform( pMan, nLutSize, fRecovery, fVerbose ); - // convert back into the ABC network - pNtkNew = Ivy_ManFpgaToAbc( pNtk, pMan ); - Ivy_FastMapStop( pMan ); - Ivy_ManStop( pMan ); - // make sure that the final network passes the test - if ( pNtkNew != NULL && !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkFastMap: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Constructs the ABC network after mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Ivy_ManFpgaToAbc( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObjAbc, * pObj; - Ivy_Obj_t * pObjIvy; - Vec_Int_t * vNodes; - int i; - // start mapping from Ivy into Abc - pMan->pCopy = Vec_PtrStart( Ivy_ManObjIdMax(pMan) + 1 ); - // start the new ABC network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); - // transfer the pointers to the basic nodes - Abc_ObjSetIvy2Abc( pMan, Ivy_ManConst1(pMan)->Id, Abc_NtkCreateNodeConst1(pNtkNew) ); - Abc_NtkForEachCi( pNtkNew, pObjAbc, i ) - Abc_ObjSetIvy2Abc( pMan, Ivy_ManPi(pMan, i)->Id, pObjAbc ); - // recursively construct the network - vNodes = Vec_IntAlloc( 100 ); - Ivy_ManForEachPo( pMan, pObjIvy, i ) - { - // get the new ABC node corresponding to the old fanin of the PO in IVY - pObjAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ObjFanin0(pObjIvy), vNodes ); - // consider the case of complemented fanin of the PO - if ( Ivy_ObjFaninC0(pObjIvy) ) // complement - { - if ( Abc_ObjIsCi(pObjAbc) ) - pObjAbc = Abc_NtkCreateNodeInv( pNtkNew, pObjAbc ); - else - { - // clone the node - pObj = Abc_NtkCloneObj( pObjAbc ); - // set complemented functions - pObj->pData = Hop_Not( pObjAbc->pData ); - // return the new node - pObjAbc = pObj; - } - } - Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), pObjAbc ); - } - Vec_IntFree( vNodes ); - Vec_PtrFree( pMan->pCopy ); - pMan->pCopy = NULL; - // remove dangling nodes - Abc_NtkCleanup( pNtkNew, 0 ); - // fix CIs feeding directly into COs - Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Recursively construct the new node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Ivy_ManToAbcFast_rec( Abc_Ntk_t * pNtkNew, Ivy_Man_t * pMan, Ivy_Obj_t * pObjIvy, Vec_Int_t * vNodes ) -{ - Vec_Int_t Supp, * vSupp = &Supp; - Abc_Obj_t * pObjAbc, * pFaninAbc; - Ivy_Obj_t * pNodeIvy; - int i, Entry; - // skip the node if it is a constant or already processed - pObjAbc = Abc_ObjGetIvy2Abc( pMan, pObjIvy->Id ); - if ( pObjAbc ) - return pObjAbc; - assert( Ivy_ObjIsAnd(pObjIvy) || Ivy_ObjIsExor(pObjIvy) ); - // get the support of K-LUT - Ivy_FastMapReadSupp( pMan, pObjIvy, vSupp ); - // create new ABC node and its fanins - pObjAbc = Abc_NtkCreateNode( pNtkNew ); - Vec_IntForEachEntry( vSupp, Entry, i ) - { - pFaninAbc = Ivy_ManToAbcFast_rec( pNtkNew, pMan, Ivy_ManObj(pMan, Entry), vNodes ); - Abc_ObjAddFanin( pObjAbc, pFaninAbc ); - } - // collect the nodes used in the cut - Ivy_ManCollectCut( pMan, pObjIvy, vSupp, vNodes ); - // create the local function - Ivy_ManForEachNodeVec( pMan, vNodes, pNodeIvy, i ) - { - if ( i < Vec_IntSize(vSupp) ) - pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_IthVar( pNtkNew->pManFunc, i ); - else - pNodeIvy->pEquiv = (Ivy_Obj_t *)Hop_And( pNtkNew->pManFunc, (Hop_Obj_t *)Ivy_ObjChild0Equiv(pNodeIvy), (Hop_Obj_t *)Ivy_ObjChild1Equiv(pNodeIvy) ); - } - // set the local function - pObjAbc->pData = (Abc_Obj_t *)pObjIvy->pEquiv; - // set the node - Abc_ObjSetIvy2Abc( pMan, pObjIvy->Id, pObjAbc ); - return pObjAbc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcFraig.c b/src/base/abci/abcFraig.c deleted file mode 100644 index be8a25f1..00000000 --- a/src/base/abci/abcFraig.c +++ /dev/null @@ -1,803 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcFraig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures interfacing with the FRAIG package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcFraig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "fraig.h" -#include "main.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); -static Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); -static Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig ); -static void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs ); -extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc ); -static void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); - -static int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk ); -static void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); -static Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Interfaces the network with the FRAIG package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ) -{ - Fraig_Params_t * pPars = pParams; - Abc_Ntk_t * pNtkNew; - Fraig_Man_t * pMan; - // check if EXDC is present - if ( fExdc && pNtk->pExdc == NULL ) - fExdc = 0, printf( "Warning: Networks has no EXDC.\n" ); - // perform fraiging - pMan = Abc_NtkToFraig( pNtk, pParams, fAllNodes, fExdc ); - // add algebraic choices -// if ( pPars->fChoicing ) -// Fraig_ManAddChoices( pMan, 0, 6 ); - // prove the miter if asked to - if ( pPars->fTryProve ) - Fraig_ManProveMiter( pMan ); - // reconstruct FRAIG in the new network - if ( fExdc ) - pNtkNew = Abc_NtkFromFraig2( pMan, pNtk ); - else - pNtkNew = Abc_NtkFromFraig( pMan, pNtk ); - Fraig_ManFree( pMan ); - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkFraig: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Transforms the strashed network into FRAIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ) -{ - int fInternal = ((Fraig_Params_t *)pParams)->fInternal; - Fraig_Man_t * pMan; - ProgressBar * pProgress; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode; - int i; - - assert( Abc_NtkIsStrash(pNtk) ); - - // create the FRAIG manager - pMan = Fraig_ManCreate( pParams ); - - // map the constant node - Abc_NtkCleanCopy( pNtk ); - Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan); - // create PIs and remember them in the old nodes - Abc_NtkForEachCi( pNtk, pNode, i ) - pNode->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, i); - - // perform strashing - vNodes = Abc_AigDfs( pNtk, fAllNodes, 0 ); - if ( !fInternal ) - pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( Abc_ObjFaninNum(pNode) == 0 ) - continue; - if ( !fInternal ) - Extra_ProgressBarUpdate( pProgress, i, NULL ); - pNode->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan, - Fraig_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), - Fraig_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); - } - if ( !fInternal ) - Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vNodes ); - - // use EXDC to change the mapping of nodes into FRAIG nodes - if ( fExdc ) - Abc_NtkFraigRemapUsingExdc( pMan, pNtk ); - - // set the primary outputs - Abc_NtkForEachCo( pNtk, pNode, i ) - Fraig_ManSetPo( pMan, (Fraig_Node_t *)Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Derives EXDC node for the given network.] - - Description [Assumes that EXDCs of all POs are the same. - Returns the EXDC of the first PO.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtkMain, Abc_Ntk_t * pNtkExdc ) -{ - Abc_Ntk_t * pNtkStrash; - Abc_Obj_t * pObj; - Fraig_Node_t * gResult; - char ** ppNames; - int i, k; - // strash the EXDC network - pNtkStrash = Abc_NtkStrash( pNtkExdc, 0, 0, 0 ); - Abc_NtkCleanCopy( pNtkStrash ); - Abc_AigConst1(pNtkStrash)->pCopy = (Abc_Obj_t *)Fraig_ManReadConst1(pMan); - // set the mapping of the PI nodes - ppNames = Abc_NtkCollectCioNames( pNtkMain, 0 ); - Abc_NtkForEachCi( pNtkStrash, pObj, i ) - { - for ( k = 0; k < Abc_NtkCiNum(pNtkMain); k++ ) - if ( strcmp( Abc_ObjName(pObj), ppNames[k] ) == 0 ) - { - pObj->pCopy = (Abc_Obj_t *)Fraig_ManReadIthVar(pMan, k); - break; - } - assert( pObj->pCopy != NULL ); - } - free( ppNames ); - // build FRAIG for each node - Abc_AigForEachAnd( pNtkStrash, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)Fraig_NodeAnd( pMan, - Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ), - Fraig_NotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ) ); - // get the EXDC to be returned - pObj = Abc_NtkPo( pNtkStrash, 0 ); - gResult = Fraig_NotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); - Abc_NtkDelete( pNtkStrash ); - return gResult; -} - - -/**Function************************************************************* - - Synopsis [Changes mapping of the old nodes into FRAIG nodes using EXDC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFraigRemapUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) -{ - Fraig_Node_t * gNodeNew, * gNodeExdc; - stmm_table * tTable; - stmm_generator * gen; - Abc_Obj_t * pNode, * pNodeBest; - Abc_Obj_t * pClass, ** ppSlot; - Vec_Ptr_t * vNexts; - int i; - - // get the global don't-cares - assert( pNtk->pExdc ); - gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc ); - - // save the next pointers - vNexts = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - Vec_PtrWriteEntry( vNexts, pNode->Id, pNode->pNext ); - - // find the classes of AIG nodes which have FRAIG nodes assigned - Abc_NtkCleanNext( pNtk ); - tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( pNode->pCopy ) - { - gNodeNew = Fraig_NodeAnd( pMan, (Fraig_Node_t *)pNode->pCopy, Fraig_Not(gNodeExdc) ); - if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(gNodeNew), (char ***)&ppSlot ) ) - *ppSlot = NULL; - pNode->pNext = *ppSlot; - *ppSlot = pNode; - } - - // for reach non-trival class, find the node with minimum level, and replace other nodes by it - Abc_AigSetNodePhases( pNtk ); - stmm_foreach_item( tTable, gen, (char **)&gNodeNew, (char **)&pClass ) - { - if ( pClass->pNext == NULL ) - continue; - // find the node with minimum level - pNodeBest = pClass; - for ( pNode = pClass->pNext; pNode; pNode = pNode->pNext ) - if ( pNodeBest->Level > pNode->Level ) - pNodeBest = pNode; - // remap the class nodes - for ( pNode = pClass; pNode; pNode = pNode->pNext ) - pNode->pCopy = Abc_ObjNotCond( pNodeBest->pCopy, pNode->fPhase ^ pNodeBest->fPhase ); - } - stmm_free_table( tTable ); - - // restore the next pointers - Abc_NtkCleanNext( pNtk ); - Abc_NtkForEachNode( pNtk, pNode, i ) - pNode->pNext = Vec_PtrEntry( vNexts, pNode->Id ); - Vec_PtrFree( vNexts ); -} - -/**Function************************************************************* - - Synopsis [Transforms FRAIG into strashed network with choices.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) -{ - ProgressBar * pProgress; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pNode, * pNodeNew; - int i; - // create the new network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // make the mapper point to the new network - Abc_NtkForEachCi( pNtk, pNode, i ) - Fraig_NodeSetData1( Fraig_ManReadIthVar(pMan, i), (Fraig_Node_t *)pNode->pCopy ); - // set the constant node - Fraig_NodeSetData1( Fraig_ManReadConst1(pMan), (Fraig_Node_t *)Abc_AigConst1(pNtkNew) ); - // process the nodes in topological order - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - pNodeNew = Abc_NodeFromFraig_rec( pNtkNew, Fraig_ManReadOutputs(pMan)[i] ); - Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); - } - Extra_ProgressBarStop( pProgress ); - Abc_NtkReassignIds( pNtkNew ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Transforms into AIG one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeFromFraig_rec( Abc_Ntk_t * pNtkNew, Fraig_Node_t * pNodeFraig ) -{ - Abc_Obj_t * pRes, * pRes0, * pRes1, * pResMin, * pResCur; - Fraig_Node_t * pNodeTemp, * pNodeFraigR = Fraig_Regular(pNodeFraig); - void ** ppTail; - // check if the node was already considered - if ( pRes = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeFraigR) ) - return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) ); - // solve the children - pRes0 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadOne(pNodeFraigR) ); - pRes1 = Abc_NodeFromFraig_rec( pNtkNew, Fraig_NodeReadTwo(pNodeFraigR) ); - // derive the new node - pRes = Abc_AigAnd( pNtkNew->pManFunc, pRes0, pRes1 ); - pRes->fPhase = Fraig_NodeReadSimInv( pNodeFraigR ); - // if the node has an equivalence class, find its representative - if ( Fraig_NodeReadRepr(pNodeFraigR) == NULL && Fraig_NodeReadNextE(pNodeFraigR) != NULL ) - { - // go through the FRAIG nodes belonging to this equivalence class - // and find the representative node (the node with the smallest level) - pResMin = pRes; - for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) ) - { - assert( Fraig_NodeReadData1(pNodeTemp) == NULL ); - pResCur = Abc_NodeFromFraig_rec( pNtkNew, pNodeTemp ); - if ( pResMin->Level > pResCur->Level ) - pResMin = pResCur; - } - // link the nodes in such a way that representative goes first - ppTail = &pResMin->pData; - if ( pRes != pResMin ) - { - *ppTail = pRes; - ppTail = &pRes->pData; - } - for ( pNodeTemp = Fraig_NodeReadNextE(pNodeFraigR); pNodeTemp; pNodeTemp = Fraig_NodeReadNextE(pNodeTemp) ) - { - pResCur = (Abc_Obj_t *)Fraig_NodeReadData1(pNodeTemp); - assert( pResCur ); - if ( pResMin == pResCur ) - continue; - *ppTail = pResCur; - ppTail = &pResCur->pData; - } - assert( *ppTail == NULL ); - - // update the phase of the node - pRes = Abc_ObjNotCond( pResMin, (pRes->fPhase ^ pResMin->fPhase) ); - } - Fraig_NodeSetData1( pNodeFraigR, (Fraig_Node_t *)pRes ); - return Abc_ObjNotCond( pRes, Fraig_IsComplement(pNodeFraig) ); -} - -/**Function************************************************************* - - Synopsis [Transforms FRAIG into strashed network without choices.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromFraig2( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) -{ - ProgressBar * pProgress; - stmm_table * tTable; - Vec_Ptr_t * vNodeReprs; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pNode, * pRepr, ** ppSlot; - int i; - - // map the nodes into their lowest level representives - tTable = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); - pNode = Abc_AigConst1(pNtk); - if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) - *ppSlot = pNode; - Abc_NtkForEachCi( pNtk, pNode, i ) - if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) - *ppSlot = pNode; - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( pNode->pCopy ) - { - if ( !stmm_find_or_add( tTable, (char *)Fraig_Regular(pNode->pCopy), (char ***)&ppSlot ) ) - *ppSlot = pNode; - else if ( (*ppSlot)->Level > pNode->Level ) - *ppSlot = pNode; - } - // save representatives for each node - vNodeReprs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( pNode->pCopy ) - { - if ( !stmm_lookup( tTable, (char *)Fraig_Regular(pNode->pCopy), (char **)&pRepr ) ) - assert( 0 ); - if ( pNode != pRepr ) - Vec_PtrWriteEntry( vNodeReprs, pNode->Id, pRepr ); - } - stmm_free_table( tTable ); - - // create the new network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - - // perform strashing - Abc_AigSetNodePhases( pNtk ); - Abc_NtkIncrementTravId( pNtk ); - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs ); - } - Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vNodeReprs ); - - // finalize the network - Abc_NtkFinalize( pNtk, pNtkNew ); - return pNtkNew; -} - - -/**Function************************************************************* - - Synopsis [Transforms into AIG one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFromFraig2_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, Vec_Ptr_t * vNodeReprs ) -{ - Abc_Obj_t * pRepr; - // skip the PIs and constants - if ( Abc_ObjFaninNum(pNode) < 2 ) - return; - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - assert( Abc_ObjIsNode( pNode ) ); - // get the node's representative - if ( pRepr = Vec_PtrEntry(vNodeReprs, pNode->Id) ) - { - Abc_NtkFromFraig2_rec( pNtkNew, pRepr, vNodeReprs ); - pNode->pCopy = Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pNode->fPhase ); - return; - } - Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin0(pNode), vNodeReprs ); - Abc_NtkFromFraig2_rec( pNtkNew, Abc_ObjFanin1(pNode), vNodeReprs ); - pNode->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); -} - - - -/**Function************************************************************* - - Synopsis [Interfaces the network with the FRAIG package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - - if ( !Abc_NtkIsSopLogic(pNtk) ) - { - printf( "Abc_NtkFraigTrust: Trust mode works for netlists and logic SOP networks.\n" ); - return NULL; - } - - if ( !Abc_NtkFraigTrustCheck(pNtk) ) - { - printf( "Abc_NtkFraigTrust: The network does not look like an AIG with choice nodes.\n" ); - return NULL; - } - - // perform strashing - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - Abc_NtkFraigTrustOne( pNtk, pNtkNew ); - Abc_NtkFinalize( pNtk, pNtkNew ); - Abc_NtkReassignIds( pNtkNew ); - - // print a warning about choice nodes - printf( "Warning: The resulting AIG contains %d choice nodes.\n", Abc_NtkGetChoiceNum( pNtkNew ) ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkFraigTrust: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Checks whether the node can be processed in the trust mode.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkFraigTrustCheck( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, nFanins; - Abc_NtkForEachNode( pNtk, pNode, i ) - { - nFanins = Abc_ObjFaninNum(pNode); - if ( nFanins < 2 ) - continue; - if ( nFanins == 2 && Abc_SopIsAndType(pNode->pData) ) - continue; - if ( !Abc_SopIsOrType(pNode->pData) ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Interfaces the network with the FRAIG package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFraigTrustOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) -{ - ProgressBar * pProgress; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode, * pNodeNew, * pObj; - int i; - - // perform strashing - vNodes = Abc_NtkDfs( pNtk, 0 ); - pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // get the node - assert( Abc_ObjIsNode(pNode) ); - // strash the node - pNodeNew = Abc_NodeFraigTrust( pNtkNew, pNode ); - // get the old object - if ( Abc_NtkIsNetlist(pNtk) ) - pObj = Abc_ObjFanout0( pNode ); // the fanout net - else - pObj = pNode; // the node itself - // make sure the node is not yet strashed - assert( pObj->pCopy == NULL ); - // mark the old object with the new AIG node - pObj->pCopy = pNodeNew; - } - Vec_PtrFree( vNodes ); - Extra_ProgressBarStop( pProgress ); -} - -/**Function************************************************************* - - Synopsis [Transforms one node into a FRAIG in the trust mode.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeFraigTrust( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pSum, * pFanin; - void ** ppTail; - int i, nFanins, fCompl; - - assert( Abc_ObjIsNode(pNode) ); - // get the number of node's fanins - nFanins = Abc_ObjFaninNum( pNode ); - assert( nFanins == Abc_SopGetVarNum(pNode->pData) ); - // check if it is a constant - if ( nFanins == 0 ) - return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Abc_SopIsConst0(pNode->pData) ); - if ( nFanins == 1 ) - return Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_SopIsInv(pNode->pData) ); - if ( nFanins == 2 && Abc_SopIsAndType(pNode->pData) ) - return Abc_AigAnd( pNtkNew->pManFunc, - Abc_ObjNotCond( Abc_ObjFanin0(pNode)->pCopy, !Abc_SopGetIthCareLit(pNode->pData,0) ), - Abc_ObjNotCond( Abc_ObjFanin1(pNode)->pCopy, !Abc_SopGetIthCareLit(pNode->pData,1) ) ); - assert( Abc_SopIsOrType(pNode->pData) ); - fCompl = Abc_SopGetIthCareLit(pNode->pData,0); - // get the root of the choice node (the first fanin) - pSum = Abc_ObjFanin0(pNode)->pCopy; - // connect other fanins - ppTail = &pSum->pData; - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - if ( i == 0 ) - continue; - *ppTail = pFanin->pCopy; - ppTail = &pFanin->pCopy->pData; - // set the complemented bit of this cut - if ( fCompl ^ Abc_SopGetIthCareLit(pNode->pData, i) ) - pFanin->pCopy->fPhase = 1; - } - assert( *ppTail == NULL ); - return pSum; -} - - - - -/**Function************************************************************* - - Synopsis [Interfaces the network with the FRAIG package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkFraigStore( Abc_Ntk_t * pNtkAdd ) -{ - Vec_Ptr_t * vStore; - Abc_Ntk_t * pNtk; - // create the network to be stored - pNtk = Abc_NtkStrash( pNtkAdd, 0, 0, 0 ); - if ( pNtk == NULL ) - { - printf( "Abc_NtkFraigStore: Initial strashing has failed.\n" ); - return 0; - } - // get the network currently stored - vStore = Abc_FrameReadStore(); - if ( Vec_PtrSize(vStore) > 0 ) - { - // check that the networks have the same PIs - // reorder PIs of pNtk2 according to pNtk1 - if ( !Abc_NtkCompareSignals( pNtk, Vec_PtrEntry(vStore, 0), 1, 1 ) ) - { - printf( "Trying to store the network with different primary inputs.\n" ); - printf( "The previously stored networks are deleted and this one is added.\n" ); - Abc_NtkFraigStoreClean(); - } - } - Vec_PtrPush( vStore, pNtk ); -// printf( "The number of AIG nodes added to storage = %5d.\n", Abc_NtkNodeNum(pNtk) ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Interfaces the network with the FRAIG package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFraigRestore() -{ - extern Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams ); - Fraig_Params_t Params; - Vec_Ptr_t * vStore; - Abc_Ntk_t * pNtk, * pFraig; - int nWords1, nWords2, nWordsMin; - int clk = clock(); - - // get the stored network - vStore = Abc_FrameReadStore(); - if ( Vec_PtrSize(vStore) == 0 ) - { - printf( "There are no network currently in storage.\n" ); - return NULL; - } -// printf( "Currently stored %d networks will be fraiged.\n", Vec_PtrSize(vStore) ); - pNtk = Vec_PtrEntry( vStore, 0 ); - - // swap the first and last network - // this should lead to the primary choice being "better" because of synthesis - pNtk = Vec_PtrPop( vStore ); - Vec_PtrPush( vStore, Vec_PtrEntry(vStore,0) ); - Vec_PtrWriteEntry( vStore, 0, pNtk ); - - // to determine the number of simulation patterns - // use the following strategy - // at least 64 words (32 words random and 32 words dynamic) - // no more than 256M for one circuit (128M + 128M) - nWords1 = 32; - nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk)); - nWordsMin = ABC_MIN( nWords1, nWords2 ); - - // set parameters for fraiging - Fraig_ParamsSetDefault( &Params ); - Params.nPatsRand = nWordsMin * 32; // the number of words of random simulation info - Params.nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info - Params.nBTLimit = 1000; // the max number of backtracks to perform - Params.fFuncRed = 1; // performs only one level hashing - Params.fFeedBack = 1; // enables solver feedback - Params.fDist1Pats = 1; // enables distance-1 patterns - Params.fDoSparse = 1; // performs equiv tests for sparse functions - Params.fChoicing = 1; // enables recording structural choices - Params.fTryProve = 0; // tries to solve the final miter - Params.fVerbose = 0; // the verbosiness flag - - // perform partitioned computation of structural choices - pFraig = Abc_NtkFraigPartitioned( vStore, &Params ); - Abc_NtkFraigStoreClean(); -//PRT( "Total choicing time", clock() - clk ); - return pFraig; -} - -/**Function************************************************************* - - Synopsis [Interfaces the network with the FRAIG package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFraigStoreClean() -{ - Vec_Ptr_t * vStore; - Abc_Ntk_t * pNtk; - int i; - vStore = Abc_FrameReadStore(); - Vec_PtrForEachEntry( vStore, pNtk, i ) - Abc_NtkDelete( pNtk ); - Vec_PtrClear( vStore ); -} - -/**Function************************************************************* - - Synopsis [Checks the correctness of stored networks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFraigStoreCheck( Abc_Ntk_t * pFraig ) -{ - Abc_Obj_t * pNode0, * pNode1; - int nPoOrig, nPoFinal, nStored; - int i, k; - // check that the PO functions are correct - nPoFinal = Abc_NtkPoNum(pFraig); - nStored = Abc_FrameReadStoreSize(); - assert( nPoFinal % nStored == 0 ); - nPoOrig = nPoFinal / nStored; - for ( i = 0; i < nPoOrig; i++ ) - { - pNode0 = Abc_ObjFanin0( Abc_NtkPo(pFraig, i) ); - for ( k = 1; k < nStored; k++ ) - { - pNode1 = Abc_ObjFanin0( Abc_NtkPo(pFraig, k*nPoOrig+i) ); - if ( pNode0 != pNode1 ) - printf( "Verification for PO #%d of network #%d has failed. The PO function is not used.\n", i+1, k+1 ); - } - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcFxu.c b/src/base/abci/abcFxu.c deleted file mode 100644 index 45515dd1..00000000 --- a/src/base/abci/abcFxu.c +++ /dev/null @@ -1,260 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcFxu.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Interface with the fast extract package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcFxu.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "fxu.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk ); -static void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); -static void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Performs fast_extract on the current network.] - - Description [Takes the network and the maximum number of nodes to extract. - Uses the concurrent double-cube and single cube divisor extraction procedure. - Modifies the network in the end, after extracting all nodes. Note that - Ntk_NetworkSweep() may increase the performance of this procedure because - the single-literal nodes will not be created in the sparse matrix. Returns 1 - if the network has been changed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkFastExtract( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) -{ - assert( Abc_NtkIsLogic(pNtk) ); - // if the network is already in the SOP form, it may come from BLIF file - // and it may not be SCC-free, in which case FXU will not work correctly - if ( Abc_NtkIsSopLogic(pNtk) ) - { // to make sure the SOPs are SCC-free -// Abc_NtkSopToBdd(pNtk); -// Abc_NtkBddToSop(pNtk); - } - // get the network in the SOP form - if ( !Abc_NtkToSop(pNtk, 0) ) - { - printf( "Abc_NtkFastExtract(): Converting to SOPs has failed.\n" ); - return 0; - } - // check if the network meets the requirements - if ( !Abc_NtkFxuCheck(pNtk) ) - { - printf( "Abc_NtkFastExtract: Nodes have duplicated or complemented fanins. FXU is not performed.\n" ); - return 0; - } - // sweep removes useless nodes - Abc_NtkCleanup( pNtk, 0 ); - // collect information about the covers - Abc_NtkFxuCollectInfo( pNtk, p ); - // call the fast extract procedure - if ( Fxu_FastExtract(p) > 0 ) - { - // update the network - Abc_NtkFxuReconstruct( pNtk, p ); - // make sure everything is okay - if ( !Abc_NtkCheck( pNtk ) ) - printf( "Abc_NtkFastExtract: The network check has failed.\n" ); - return 1; - } - else - printf( "Warning: The network has not been changed by \"fx\".\n" ); - return 0; -} - - -/**Function************************************************************* - - Synopsis [Makes sure the nodes do not have complemented and duplicated fanins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode, * pFanin1, * pFanin2; - int n, i, k; - Abc_NtkForEachNode( pNtk, pNode, n ) - { - Abc_ObjForEachFanin( pNode, pFanin1, i ) - { - if ( i < 2 && Abc_ObjFaninC(pNode, i) ) - return 0; - Abc_ObjForEachFanin( pNode, pFanin2, k ) - { - if ( i == k ) - continue; - if ( pFanin1 == pFanin2 ) - return 0; - } - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Collect information about the network for fast_extract.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFxuCollectInfo( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) -{ - Abc_Obj_t * pNode; - int i; - // add information to the manager - p->pManSop = pNtk->pManFunc; - p->vSops = Vec_PtrAlloc(0); - p->vFanins = Vec_PtrAlloc(0); - p->vSopsNew = Vec_PtrAlloc(0); - p->vFaninsNew = Vec_PtrAlloc(0); - Vec_PtrFill( p->vSops, Abc_NtkObjNumMax(pNtk), NULL ); - Vec_PtrFill( p->vFanins, Abc_NtkObjNumMax(pNtk), NULL ); - Vec_PtrFill( p->vSopsNew, Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL ); - Vec_PtrFill( p->vFaninsNew, Abc_NtkObjNumMax(pNtk) + p->nNodesExt, NULL ); - // add SOPs and fanin array - Abc_NtkForEachNode( pNtk, pNode, i ) - { - if ( Abc_SopGetVarNum(pNode->pData) < 2 ) - continue; - if ( Abc_SopGetCubeNum(pNode->pData) < 1 ) - continue; - p->vSops->pArray[i] = pNode->pData; - p->vFanins->pArray[i] = &pNode->vFanins; - } - p->nNodesOld = Abc_NtkObjNumMax(pNtk); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFxuFreeInfo( Fxu_Data_t * p ) -{ - int i; - // free the arrays of new fanins - if ( p->vFaninsNew ) - for ( i = 0; i < p->vFaninsNew->nSize; i++ ) - if ( p->vFaninsNew->pArray[i] ) - Vec_IntFree( p->vFaninsNew->pArray[i] ); - // free the arrays - if ( p->vSops ) Vec_PtrFree( p->vSops ); - if ( p->vSopsNew ) Vec_PtrFree( p->vSopsNew ); - if ( p->vFanins ) Vec_PtrFree( p->vFanins ); - if ( p->vFaninsNew ) Vec_PtrFree( p->vFaninsNew ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Recostructs the network after FX.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFxuReconstruct( Abc_Ntk_t * pNtk, Fxu_Data_t * p ) -{ - Vec_Int_t * vFanins; - Abc_Obj_t * pNode, * pFanin; - int i, k; - - assert( p->vFanins->nSize < p->vFaninsNew->nSize ); - // create the new nodes - for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ ) - { - // start the node - pNode = Abc_NtkCreateNode( pNtk ); - assert( i == (int)pNode->Id ); - } - // update the old nodes - for ( i = 0; i < p->vFanins->nSize; i++ ) - { - // the new array of fanins - vFanins = p->vFaninsNew->pArray[i]; - if ( vFanins == NULL ) - continue; - // remove old fanins - pNode = Abc_NtkObj( pNtk, i ); - Abc_ObjRemoveFanins( pNode ); - // add new fanins - vFanins = p->vFaninsNew->pArray[i]; - for ( k = 0; k < vFanins->nSize; k++ ) - { - pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] ); - Abc_ObjAddFanin( pNode, pFanin ); - } - pNode->pData = p->vSopsNew->pArray[i]; - assert( pNode->pData != NULL ); - } - // set up the new nodes - for ( i = p->vFanins->nSize; i < p->vFanins->nSize + p->nNodesNew; i++ ) - { - // get the new node - pNode = Abc_NtkObj( pNtk, i ); - // add the fanins - vFanins = p->vFaninsNew->pArray[i]; - for ( k = 0; k < vFanins->nSize; k++ ) - { - pFanin = Abc_NtkObj( pNtk, vFanins->pArray[k] ); - Abc_ObjAddFanin( pNode, pFanin ); - } - pNode->pData = p->vSopsNew->pArray[i]; - assert( pNode->pData != NULL ); - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcGen.c b/src/base/abci/abcGen.c deleted file mode 100644 index bfb41374..00000000 --- a/src/base/abci/abcGen.c +++ /dev/null @@ -1,511 +0,0 @@ -/**CFile**************************************************************** - - FileName [abc_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 ); -void Abc_WriteComp( FILE * pFile ); -void Abc_WriteFullAdder( FILE * pFile ); - -void Abc_GenAdder( char * pFileName, int nVars ); -void Abc_GenSorter( char * pFileName, int nVars ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_GenAdder( char * pFileName, int nVars ) -{ - FILE * pFile; - int i; - - assert( nVars > 0 ); - - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "# %d-bit ripple-carry adder generated by ABC on %s\n", nVars, Extra_TimeStamp() ); - fprintf( pFile, ".model Adder%02d\n", nVars ); - - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nVars; i++ ) - fprintf( pFile, " a%02d", i ); - for ( i = 0; i < nVars; i++ ) - fprintf( pFile, " b%02d", i ); - fprintf( pFile, "\n" ); - - fprintf( pFile, ".outputs" ); - for ( i = 0; i <= nVars; i++ ) - fprintf( pFile, " y%02d", i ); - fprintf( pFile, "\n" ); - - fprintf( pFile, ".names c\n" ); - if ( nVars == 1 ) - fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=y01\n" ); - else - { - fprintf( pFile, ".subckt FA a=a00 b=b00 cin=c s=y00 cout=%02d\n", 0 ); - for ( i = 1; i < nVars-1; i++ ) - fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=%02d\n", i, i, i-1, i, i ); - fprintf( pFile, ".subckt FA a=a%02d b=b%02d cin=%02d s=y%02d cout=y%02d\n", i, i, i-1, i, i+1 ); - } - fprintf( pFile, ".end\n" ); - fprintf( pFile, "\n" ); - - Abc_WriteFullAdder( pFile ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_GenSorter( char * pFileName, int nVars ) -{ - FILE * pFile; - int i, k, Counter, nDigits; - - assert( nVars > 1 ); - - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "# %d-bit sorter generated by ABC on %s\n", nVars, Extra_TimeStamp() ); - fprintf( pFile, ".model Sorter%02d\n", nVars ); - - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nVars; i++ ) - fprintf( pFile, " x%02d", i ); - fprintf( pFile, "\n" ); - - fprintf( pFile, ".outputs" ); - for ( i = 0; i < nVars; i++ ) - fprintf( pFile, " y%02d", i ); - fprintf( pFile, "\n" ); - - Counter = 0; - nDigits = Extra_Base10Log( (nVars-2)*nVars ); - if ( nVars == 2 ) - fprintf( pFile, ".subckt Comp a=x00 b=x01 x=y00 y=y01\n" ); - else - { - fprintf( pFile, ".subckt Layer0" ); - for ( k = 0; k < nVars; k++ ) - fprintf( pFile, " x%02d=x%02d", k, k ); - for ( k = 0; k < nVars; k++ ) - fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ ); - fprintf( pFile, "\n" ); - Counter -= nVars; - for ( i = 1; i < nVars-2; i++ ) - { - fprintf( pFile, ".subckt Layer%d", (i&1) ); - for ( k = 0; k < nVars; k++ ) - fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ ); - for ( k = 0; k < nVars; k++ ) - fprintf( pFile, " y%02d=%0*d", k, nDigits, Counter++ ); - fprintf( pFile, "\n" ); - Counter -= nVars; - } - fprintf( pFile, ".subckt Layer%d", (i&1) ); - for ( k = 0; k < nVars; k++ ) - fprintf( pFile, " x%02d=%0*d", k, nDigits, Counter++ ); - for ( k = 0; k < nVars; k++ ) - fprintf( pFile, " y%02d=y%02d", k, k ); - fprintf( pFile, "\n" ); - } - fprintf( pFile, ".end\n" ); - fprintf( pFile, "\n" ); - - Abc_WriteLayer( pFile, nVars, 0 ); - Abc_WriteLayer( pFile, nVars, 1 ); - Abc_WriteComp( pFile ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_WriteLayer( FILE * pFile, int nVars, int fSkip1 ) -{ - int i; - fprintf( pFile, ".model Layer%d\n", fSkip1 ); - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nVars; i++ ) - fprintf( pFile, " x%02d", i ); - fprintf( pFile, "\n" ); - fprintf( pFile, ".outputs" ); - for ( i = 0; i < nVars; i++ ) - fprintf( pFile, " y%02d", i ); - fprintf( pFile, "\n" ); - if ( fSkip1 ) - { - fprintf( pFile, ".names x00 y00\n" ); - fprintf( pFile, "1 1\n" ); - i = 1; - } - else - i = 0; - for ( ; i + 1 < nVars; i += 2 ) - fprintf( pFile, ".subckt Comp a=x%02d b=x%02d x=y%02d y=y%02d\n", i, i+1, i, i+1 ); - if ( i < nVars ) - { - fprintf( pFile, ".names x%02d y%02d\n", i, i ); - fprintf( pFile, "1 1\n" ); - } - fprintf( pFile, ".end\n" ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_WriteComp( FILE * pFile ) -{ - fprintf( pFile, ".model Comp\n" ); - fprintf( pFile, ".inputs a b\n" ); - fprintf( pFile, ".outputs x y\n" ); - fprintf( pFile, ".names a b x\n" ); - fprintf( pFile, "11 1\n" ); - fprintf( pFile, ".names a b y\n" ); - fprintf( pFile, "1- 1\n" ); - fprintf( pFile, "-1 1\n" ); - fprintf( pFile, ".end\n" ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_WriteFullAdder( FILE * pFile ) -{ - fprintf( pFile, ".model FA\n" ); - fprintf( pFile, ".inputs a b cin\n" ); - fprintf( pFile, ".outputs s cout\n" ); - fprintf( pFile, ".names a b k\n" ); - fprintf( pFile, "10 1\n" ); - fprintf( pFile, "01 1\n" ); - fprintf( pFile, ".names k cin s\n" ); - fprintf( pFile, "10 1\n" ); - fprintf( pFile, "01 1\n" ); - fprintf( pFile, ".names a b cin cout\n" ); - fprintf( pFile, "11- 1\n" ); - fprintf( pFile, "1-1 1\n" ); - fprintf( pFile, "-11 1\n" ); - fprintf( pFile, ".end\n" ); - fprintf( pFile, "\n" ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_WriteCell( FILE * pFile ) -{ - fprintf( pFile, ".model cell\n" ); - fprintf( pFile, ".inputs px1 px2 py1 py2 x y\n" ); - fprintf( pFile, ".outputs fx fy\n" ); - fprintf( pFile, ".names x y a\n" ); - fprintf( pFile, "11 1\n" ); - fprintf( pFile, ".names px1 a x nx\n" ); - fprintf( pFile, "11- 1\n" ); - fprintf( pFile, "0-1 1\n" ); - fprintf( pFile, ".names py1 a y ny\n" ); - fprintf( pFile, "11- 1\n" ); - fprintf( pFile, "0-1 1\n" ); - fprintf( pFile, ".names px2 nx fx\n" ); - fprintf( pFile, "10 1\n" ); - fprintf( pFile, "01 1\n" ); - fprintf( pFile, ".names py2 ny fy\n" ); - fprintf( pFile, "10 1\n" ); - fprintf( pFile, "01 1\n" ); - fprintf( pFile, ".end\n" ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_GenMesh( char * pFileName, int nVars ) -{ - FILE * pFile; - int i, k; - - assert( nVars > 0 ); - - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "# %dx%d mesh generated by ABC on %s\n", nVars, nVars, Extra_TimeStamp() ); - fprintf( pFile, ".model mesh%d\n", nVars ); - - for ( i = 0; i < nVars; i++ ) - for ( k = 0; k < nVars; k++ ) - { - fprintf( pFile, ".inputs" ); - fprintf( pFile, " p%d%dx1", i, k ); - fprintf( pFile, " p%d%dx2", i, k ); - fprintf( pFile, " p%d%dy1", i, k ); - fprintf( pFile, " p%d%dy2", i, k ); - fprintf( pFile, "\n" ); - } - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nVars; i++ ) - fprintf( pFile, " v%02d v%02d", 2*i, 2*i+1 ); - fprintf( pFile, "\n" ); - - fprintf( pFile, ".outputs" ); - fprintf( pFile, " fx00" ); - fprintf( pFile, "\n" ); - - for ( i = 0; i < nVars; i++ ) // horizontal - for ( k = 0; k < nVars; k++ ) // vertical - { - fprintf( pFile, ".subckt cell" ); - fprintf( pFile, " px1=p%d%dx1", i, k ); - fprintf( pFile, " px2=p%d%dx2", i, k ); - fprintf( pFile, " py1=p%d%dy1", i, k ); - fprintf( pFile, " py2=p%d%dy2", i, k ); - if ( k == nVars - 1 ) - fprintf( pFile, " x=v%02d", i ); - else - fprintf( pFile, " x=fx%d%d", i, k+1 ); - if ( i == nVars - 1 ) - fprintf( pFile, " y=v%02d", nVars+k ); - else - fprintf( pFile, " y=fy%d%d", i+1, k ); - // outputs - fprintf( pFile, " fx=fx%d%d", i, k ); - fprintf( pFile, " fy=fy%d%d", i, k ); - fprintf( pFile, "\n" ); - } - fprintf( pFile, ".end\n" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - Abc_WriteCell( pFile ); - fclose( pFile ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_WriteKLut( FILE * pFile, int nLutSize ) -{ - int i, iVar, iNext, nPars = (1 << nLutSize); - fprintf( pFile, "\n" ); - fprintf( pFile, ".model lut%d\n", nLutSize ); - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nPars; i++ ) - fprintf( pFile, " p%02d", i ); - fprintf( pFile, "\n" ); - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nLutSize; i++ ) - fprintf( pFile, " i%d", i ); - fprintf( pFile, "\n" ); - fprintf( pFile, ".outputs o\n" ); - fprintf( pFile, ".names n01 o\n" ); - fprintf( pFile, "1 1\n" ); - // write internal MUXes - iVar = 0; - iNext = 2; - for ( i = 1; i < nPars; i++ ) - { - if ( i == iNext ) - { - iNext *= 2; - iVar++; - } - if ( iVar == nLutSize - 1 ) - fprintf( pFile, ".names i%d p%02d p%02d n%02d\n", iVar, 2*(i-nPars/2), 2*(i-nPars/2)+1, i ); - else - fprintf( pFile, ".names i%d n%02d n%02d n%02d\n", iVar, 2*i, 2*i+1, i ); - fprintf( pFile, "01- 1\n" ); - fprintf( pFile, "1-1 1\n" ); - } - fprintf( pFile, ".end\n" ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Generates structure of L K-LUTs implementing an N-var function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars ) -{ - FILE * pFile; - int nVarsLut = (1 << nLutSize); // the number of LUT variables - int nVarsLog = Extra_Base2Log( nVars + nLuts - 1 ); // the number of encoding vars - int nVarsDeg = (1 << nVarsLog); // the number of LUT variables (total) - int nParsLut = nLuts * (1 << nLutSize); // the number of LUT params - int nParsVar = nLuts * nLutSize * nVarsLog; // the number of var params - int i, j, k; - - assert( nVars > 0 ); - - pFile = fopen( pFileName, "w" ); - fprintf( pFile, "# Structure with %d %d-LUTs for %d-var function generated by ABC on %s\n", nLuts, nLutSize, nVars, Extra_TimeStamp() ); - fprintf( pFile, ".model struct%dx%d_%d\n", nLuts, nLutSize, nVars ); - - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nParsLut; i++ ) - fprintf( pFile, " pl%02d", i ); - fprintf( pFile, "\n" ); - - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nParsVar; i++ ) - fprintf( pFile, " pv%02d", i ); - fprintf( pFile, "\n" ); - - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nVars; i++ ) - fprintf( pFile, " v%02d", i ); - fprintf( pFile, "\n" ); - - fprintf( pFile, ".outputs" ); - fprintf( pFile, " v%02d", nVars + nLuts - 1 ); - fprintf( pFile, "\n" ); - fprintf( pFile, ".names Gnd\n" ); - fprintf( pFile, " 0\n" ); - - // generate LUTs - for ( i = 0; i < nLuts; i++ ) - { - fprintf( pFile, ".subckt lut%d", nLutSize ); - // generate config parameters - for ( k = 0; k < nVarsLut; k++ ) - fprintf( pFile, " p%02d=pl%02d", k, i * nVarsLut + k ); - // generate the inputs - for ( k = 0; k < nLutSize; k++ ) - fprintf( pFile, " i%d=s%02d", k, i * nLutSize + k ); - // generate the output - fprintf( pFile, " o=v%02d", nVars + i ); - fprintf( pFile, "\n" ); - } - - // generate LUT inputs - for ( i = 0; i < nLuts; i++ ) - { - for ( j = 0; j < nLutSize; j++ ) - { - fprintf( pFile, ".subckt lut%d", nVarsLog ); - // generate config parameters - for ( k = 0; k < nVarsDeg; k++ ) - { - if ( k < nVars + nLuts - 1 && k < nVars + i ) - fprintf( pFile, " p%02d=v%02d", k, k ); - else - fprintf( pFile, " p%02d=Gnd", k ); - } - // generate the inputs - for ( k = 0; k < nVarsLog; k++ ) - fprintf( pFile, " i%d=pv%02d", k, (i * nLutSize + j) * nVarsLog + k ); - // generate the output - fprintf( pFile, " o=s%02d", i * nLutSize + j ); - fprintf( pFile, "\n" ); - } - } - - fprintf( pFile, ".end\n" ); - fprintf( pFile, "\n" ); - - // generate LUTs - Abc_WriteKLut( pFile, nLutSize ); - if ( nVarsLog != nLutSize ) - Abc_WriteKLut( pFile, nVarsLog ); - fclose( pFile ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcHaig.c b/src/base/abci/abcHaig.c deleted file mode 100644 index d3513bbe..00000000 --- a/src/base/abci/abcHaig.c +++ /dev/null @@ -1,726 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcHaig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Implements history AIG for combinational rewriting.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcHaig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start history AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkHaigStart( Abc_Ntk_t * pNtk ) -{ - Hop_Man_t * p; - Abc_Obj_t * pObj, * pTemp; - int i; - assert( Abc_NtkIsStrash(pNtk) ); - // check if the package is already started - if ( pNtk->pHaig ) - { - Abc_NtkHaigStop( pNtk ); - assert( pNtk->pHaig == NULL ); - printf( "Warning: Previous history AIG was removed.\n" ); - } - // make sure the data is clean - Abc_NtkForEachObj( pNtk, pObj, i ) - assert( pObj->pEquiv == NULL ); - // start the HOP package - p = Hop_ManStart(); - p->vObjs = Vec_PtrAlloc( 4096 ); - Vec_PtrPush( p->vObjs, Hop_ManConst1(p) ); - // map the constant node - Abc_AigConst1(pNtk)->pEquiv = Hop_ManConst1(p); - // map the CIs - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pEquiv = Hop_ObjCreatePi(p); - // map the internal nodes - Abc_NtkForEachNode( pNtk, pObj, i ) - pObj->pEquiv = Hop_And( p, Abc_ObjChild0Equiv(pObj), Abc_ObjChild1Equiv(pObj) ); - // map the choice nodes - if ( Abc_NtkGetChoiceNum( pNtk ) ) - { - // print warning about choice nodes - printf( "Warning: The choice nodes in the original AIG are converted into HAIG.\n" ); - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( !Abc_AigNodeIsChoice( pObj ) ) - continue; - for ( pTemp = pObj->pData; pTemp; pTemp = pTemp->pData ) - Hop_ObjCreateChoice( pObj->pEquiv, pTemp->pEquiv ); - } - } - // make sure everything is okay - if ( !Hop_ManCheck(p) ) - { - printf( "Abc_NtkHaigStart: Check for History AIG has failed.\n" ); - Hop_ManStop(p); - return 0; - } - pNtk->pHaig = p; - return 1; -} - -/**Function************************************************************* - - Synopsis [Stops history AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkHaigStop( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - assert( Abc_NtkIsStrash(pNtk) ); - if ( pNtk->pHaig == NULL ) - { - printf( "Warning: History AIG is not allocated.\n" ); - return 1; - } - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pEquiv = NULL; - Hop_ManStop( pNtk->pHaig ); - pNtk->pHaig = NULL; - return 1; -} - -/**Function************************************************************* - - Synopsis [Transfers the HAIG to the new network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkHaigTranfer( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) -{ - Abc_Obj_t * pObj; - int i; - if ( pNtkOld->pHaig == NULL ) - return; - // transfer the package - assert( pNtkNew->pHaig == NULL ); - pNtkNew->pHaig = pNtkOld->pHaig; - pNtkOld->pHaig = NULL; - // transfer constant pointer - Abc_AigConst1(pNtkOld)->pCopy->pEquiv = Abc_AigConst1(pNtkOld)->pEquiv; - // transfer the CI pointers - Abc_NtkForEachCi( pNtkOld, pObj, i ) - pObj->pCopy->pEquiv = pObj->pEquiv; -} - - - -/**Function************************************************************* - - Synopsis [Collects the nodes in the classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkHaigCollectMembers( Hop_Man_t * p ) -{ - Vec_Ptr_t * vObjs; - Hop_Obj_t * pObj; - int i; - vObjs = Vec_PtrAlloc( 4098 ); - Vec_PtrForEachEntry( p->vObjs, pObj, i ) - { - if ( pObj->pData == NULL ) - continue; - pObj->pData = Hop_ObjRepr( pObj ); - Vec_PtrPush( vObjs, pObj ); - } - return vObjs; -} - -/**Function************************************************************* - - Synopsis [Creates classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkHaigCreateClasses( Vec_Ptr_t * vMembers ) -{ - Vec_Ptr_t * vClasses; - Hop_Obj_t * pObj, * pRepr; - int i; - - // count classes - vClasses = Vec_PtrAlloc( 4098 ); - Vec_PtrForEachEntry( vMembers, pObj, i ) - { - pRepr = pObj->pData; - assert( pRepr->pData == NULL ); - if ( pRepr->fMarkA == 0 ) // new - { - pRepr->fMarkA = 1; - Vec_PtrPush( vClasses, pRepr ); - } - } - - // set representatives as representatives - Vec_PtrForEachEntry( vClasses, pObj, i ) - { - pObj->fMarkA = 0; - pObj->pData = pObj; - } - - // go through the members and update - Vec_PtrForEachEntry( vMembers, pObj, i ) - { - pRepr = pObj->pData; - if ( ((Hop_Obj_t *)pRepr->pData)->Id > pObj->Id ) - pRepr->pData = pObj; - } - - // change representatives of the class - Vec_PtrForEachEntry( vMembers, pObj, i ) - { - pRepr = pObj->pData; - pObj->pData = pRepr->pData; - assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id ); - } - - // update classes - Vec_PtrForEachEntry( vClasses, pObj, i ) - { - pRepr = pObj->pData; - assert( pRepr->pData == pRepr ); -// pRepr->pData = NULL; - Vec_PtrWriteEntry( vClasses, i, pRepr ); - Vec_PtrPush( vMembers, pObj ); - } - - Vec_PtrForEachEntry( vMembers, pObj, i ) - if ( pObj->pData == pObj ) - pObj->pData = NULL; - -/* - Vec_PtrForEachEntry( vMembers, pObj, i ) - { - printf( "ObjId = %4d : ", pObj->Id ); - if ( pObj->pData == NULL ) - { - printf( "NULL" ); - } - else - { - printf( "%4d", ((Hop_Obj_t *)pObj->pData)->Id ); - assert( ((Hop_Obj_t *)pObj->pData)->Id <= pObj->Id ); - } - printf( "\n" ); - } -*/ - return vClasses; -} - -/**Function************************************************************* - - Synopsis [Counts how many data members have non-trivial fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkHaigCountFans( Hop_Man_t * p ) -{ - Hop_Obj_t * pObj; - int i, Counter = 0; - Vec_PtrForEachEntry( p->vObjs, pObj, i ) - { - if ( pObj->pData == NULL ) - continue; - if ( Hop_ObjRefs(pObj) > 0 ) - Counter++; - } - printf( "The number of class members with fanouts = %5d.\n", Counter ); - return Counter; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Hop_Obj_t * Hop_ObjReprHop( Hop_Obj_t * pObj ) -{ - Hop_Obj_t * pRepr; - assert( pObj->pNext != NULL ); - if ( pObj->pData == NULL ) - return pObj->pNext; - pRepr = pObj->pData; - assert( pRepr->pData == pRepr ); - return Hop_NotCond( pRepr->pNext, pObj->fPhase ^ pRepr->fPhase ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Hop_Obj_t * Hop_ObjChild0Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin0(pObj)), Hop_ObjFaninC0(pObj) ); } -static inline Hop_Obj_t * Hop_ObjChild1Hop( Hop_Obj_t * pObj ) { return Hop_NotCond( Hop_ObjReprHop(Hop_ObjFanin1(pObj)), Hop_ObjFaninC1(pObj) ); } - -/**Function************************************************************* - - Synopsis [Stops history AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Man_t * Abc_NtkHaigReconstruct( Hop_Man_t * p ) -{ - Hop_Man_t * pNew; - Hop_Obj_t * pObj; - int i, Counter = 0; - Vec_PtrForEachEntry( p->vObjs, pObj, i ) - pObj->pNext = NULL; - // start the HOP package - pNew = Hop_ManStart(); - pNew->vObjs = Vec_PtrAlloc( p->nCreated ); - Vec_PtrPush( pNew->vObjs, Hop_ManConst1(pNew) ); - // map the constant node - Hop_ManConst1(p)->pNext = Hop_ManConst1(pNew); - // map the CIs - Hop_ManForEachPi( p, pObj, i ) - pObj->pNext = Hop_ObjCreatePi(pNew); - // map the internal nodes - Vec_PtrForEachEntry( p->vObjs, pObj, i ) - { - if ( !Hop_ObjIsNode(pObj) ) - continue; - pObj->pNext = Hop_And( pNew, Hop_ObjChild0Hop(pObj), Hop_ObjChild1Hop(pObj) ); -// assert( !Hop_IsComplement(pObj->pNext) ); - if ( Hop_ManConst1(pNew) == Hop_Regular(pObj->pNext) ) - Counter++; - if ( pObj->pData ) // member of the class - Hop_Regular(pObj->pNext)->pData = Hop_Regular(((Hop_Obj_t *)pObj->pData)->pNext); - } -// printf( " Counter = %d.\n", Counter ); - // transfer the POs - Hop_ManForEachPo( p, pObj, i ) - Hop_ObjCreatePo( pNew, Hop_ObjChild0Hop(pObj) ); - // check the new manager - if ( !Hop_ManCheck(pNew) ) - { - printf( "Abc_NtkHaigReconstruct: Check for History AIG has failed.\n" ); - Hop_ManStop(pNew); - return NULL; - } - return pNew; -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkHaigCheckTfi_rec( Abc_Obj_t * pNode, Abc_Obj_t * pOld ) -{ - if ( pNode == NULL ) - return 0; - if ( pNode == pOld ) - return 1; - // check the trivial cases - if ( Abc_ObjIsCi(pNode) ) - return 0; - assert( Abc_ObjIsNode(pNode) ); - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return 0; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // check the children - if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin0(pNode), pOld ) ) - return 1; - if ( Abc_NtkHaigCheckTfi_rec( Abc_ObjFanin1(pNode), pOld ) ) - return 1; - // check equivalent nodes - return Abc_NtkHaigCheckTfi_rec( pNode->pData, pOld ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkHaigCheckTfi( Abc_Ntk_t * pNtk, Abc_Obj_t * pOld, Abc_Obj_t * pNew ) -{ - assert( !Abc_ObjIsComplement(pOld) ); - assert( !Abc_ObjIsComplement(pNew) ); - Abc_NtkIncrementTravId(pNtk); - return Abc_NtkHaigCheckTfi_rec( pNew, pOld ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Abc_Obj_t * Hop_ObjChild0Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin0(pObj)->pNext, Hop_ObjFaninC0(pObj) ); } -static inline Abc_Obj_t * Hop_ObjChild1Next( Hop_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Hop_ObjFanin1(pObj)->pNext, Hop_ObjFaninC1(pObj) ); } - -/**Function************************************************************* - - Synopsis [Stops history AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkHaigRecreateAig( Abc_Ntk_t * pNtk, Hop_Man_t * p ) -{ - Abc_Ntk_t * pNtkAig; - Abc_Obj_t * pObjOld, * pObjAbcThis, * pObjAbcRepr; - Hop_Obj_t * pObj; - int i; - assert( p->nCreated == Vec_PtrSize(p->vObjs) ); - - // start the new network - pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - - // transfer new nodes to the PIs of HOP - Hop_ManConst1(p)->pNext = (Hop_Obj_t *)Abc_AigConst1( pNtkAig ); - Hop_ManForEachPi( p, pObj, i ) - pObj->pNext = (Hop_Obj_t *)Abc_NtkCi( pNtkAig, i ); - - // construct new nodes - Vec_PtrForEachEntry( p->vObjs, pObj, i ) - { - if ( !Hop_ObjIsNode(pObj) ) - continue; - pObj->pNext = (Hop_Obj_t *)Abc_AigAnd( pNtkAig->pManFunc, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) ); - assert( !Hop_IsComplement(pObj->pNext) ); - } - - // set the COs - Abc_NtkForEachCo( pNtk, pObjOld, i ) - Abc_ObjAddFanin( pObjOld->pCopy, Hop_ObjChild0Next(Hop_ManPo(p,i)) ); - - // construct choice nodes - Vec_PtrForEachEntry( p->vObjs, pObj, i ) - { - // skip the node without choices - if ( pObj->pData == NULL ) - continue; - // skip the representative of the class - if ( pObj->pData == pObj ) - continue; - // do not create choices for constant 1 and PIs - if ( !Hop_ObjIsNode(pObj->pData) ) - continue; - // get the corresponding new nodes - pObjAbcThis = (Abc_Obj_t *)pObj->pNext; - pObjAbcRepr = (Abc_Obj_t *)((Hop_Obj_t *)pObj->pData)->pNext; - // the new node cannot be already in the class - assert( pObjAbcThis->pData == NULL ); - // the new node cannot have fanouts - assert( Abc_ObjFanoutNum(pObjAbcThis) == 0 ); - // these should be different nodes - assert( pObjAbcRepr != pObjAbcThis ); - // do not create choices if there is a path from pObjAbcThis to pObjAbcRepr - if ( !Abc_NtkHaigCheckTfi( pNtkAig, pObjAbcRepr, pObjAbcThis ) ) - { - // find the last node in the class - while ( pObjAbcRepr->pData ) - pObjAbcRepr = pObjAbcRepr->pData; - // add the new node at the end of the list - pObjAbcRepr->pData = pObjAbcThis; - } - } - - // finish the new network -// Abc_NtkFinalize( pNtk, pNtkAig ); -// Abc_AigCleanup( pNtkAig->pManFunc ); - // check correctness of the network - if ( !Abc_NtkCheck( pNtkAig ) ) - { - printf( "Abc_NtkHaigUse: The network check has failed.\n" ); - Abc_NtkDelete( pNtkAig ); - return NULL; - } - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Resets representatives.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkHaigResetReprsOld( Hop_Man_t * pMan ) -{ - Vec_Ptr_t * vMembers, * vClasses; - - // collect members of the classes and make them point to reprs - vMembers = Abc_NtkHaigCollectMembers( pMan ); - printf( "Collected %6d class members.\n", Vec_PtrSize(vMembers) ); - - // create classes - vClasses = Abc_NtkHaigCreateClasses( vMembers ); - printf( "Collected %6d classes. (Ave = %5.2f)\n", Vec_PtrSize(vClasses), - (float)(Vec_PtrSize(vMembers))/Vec_PtrSize(vClasses) ); - - Vec_PtrFree( vMembers ); - Vec_PtrFree( vClasses ); -} - -/**Function************************************************************* - - Synopsis [Resets representatives.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkHaigResetReprs( Hop_Man_t * p ) -{ - Hop_Obj_t * pObj, * pRepr; - int i, nClasses, nMembers, nFanouts, nNormals; - // clear self-classes - Vec_PtrForEachEntry( p->vObjs, pObj, i ) - { - // fix the strange situation of double-loop - pRepr = pObj->pData; - if ( pRepr && pRepr->pData == pObj ) - pRepr->pData = pRepr; - // remove self-loops - if ( pObj->pData == pObj ) - pObj->pData = NULL; - } - // set representatives - Vec_PtrForEachEntry( p->vObjs, pObj, i ) - { - if ( pObj->pData == NULL ) - continue; - // get representative of the node - pRepr = Hop_ObjRepr( pObj ); - pRepr->pData = pRepr; - // set the representative - pObj->pData = pRepr; - } - // make each class point to the smallest topological order - Vec_PtrForEachEntry( p->vObjs, pObj, i ) - { - if ( pObj->pData == NULL ) - continue; - pRepr = Hop_ObjRepr( pObj ); - if ( pRepr->Id > pObj->Id ) - { - pRepr->pData = pObj; - pObj->pData = pObj; - } - else - pObj->pData = pRepr; - } - // count classes, members, and fanouts - and verify - nMembers = nClasses = nFanouts = nNormals = 0; - Vec_PtrForEachEntry( p->vObjs, pObj, i ) - { - if ( pObj->pData == NULL ) - continue; - // count members - nMembers++; - // count the classes and fanouts - if ( pObj->pData == pObj ) - nClasses++; - else if ( Hop_ObjRefs(pObj) > 0 ) - nFanouts++; - else - nNormals++; - // compare representatives - pRepr = Hop_ObjRepr( pObj ); - assert( pObj->pData == pRepr ); - assert( pRepr->Id <= pObj->Id ); - } -// printf( "Nodes = %7d. Member = %7d. Classes = %6d. Fanouts = %6d. Normals = %6d.\n", -// Hop_ManNodeNum(p), nMembers, nClasses, nFanouts, nNormals ); - return nFanouts; -} - -/**Function************************************************************* - - Synopsis [Stops history AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkHaigUse( Abc_Ntk_t * pNtk ) -{ - Hop_Man_t * pMan, * pManTemp; - Abc_Ntk_t * pNtkAig; - Abc_Obj_t * pObj; - int i; - - // check if HAIG is available - assert( Abc_NtkIsStrash(pNtk) ); - if ( pNtk->pHaig == NULL ) - { - printf( "Warning: History AIG is not available.\n" ); - return NULL; - } - // convert HOP package into AIG with choices - // print HAIG stats -// Hop_ManPrintStats( pMan ); // USES DATA!!! - - // add the POs - Abc_NtkForEachCo( pNtk, pObj, i ) - Hop_ObjCreatePo( pNtk->pHaig, Abc_ObjChild0Equiv(pObj) ); - - // clean the old network - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pEquiv = NULL; - pMan = pNtk->pHaig; - pNtk->pHaig = 0; - - // iteratively reconstruct the HOP manager to create choice nodes - while ( Abc_NtkHaigResetReprs( pMan ) ) - { - pMan = Abc_NtkHaigReconstruct( pManTemp = pMan ); - Hop_ManStop( pManTemp ); - } - - // traverse in the topological order and create new AIG - pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan ); - Hop_ManStop( pMan ); - - // free HAIG - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Transform HOP manager into the one without loops.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ) -{ - Abc_Ntk_t * pNtkAig; - Hop_Man_t * pManTemp; - - // iteratively reconstruct the HOP manager to create choice nodes - while ( Abc_NtkHaigResetReprs( pMan ) ) - { - pMan = Abc_NtkHaigReconstruct( pManTemp = pMan ); - Hop_ManStop( pManTemp ); - } - - // traverse in the topological order and create new AIG - pNtkAig = Abc_NtkHaigRecreateAig( pNtk, pMan ); - Hop_ManStop( pMan ); - return pNtkAig; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcIf.c b/src/base/abci/abcIf.c deleted file mode 100644 index bb56c22c..00000000 --- a/src/base/abci/abcIf.c +++ /dev/null @@ -1,497 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcIf.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Interface with the FPGA mapping package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: abcIf.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "if.h" -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); -static Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ); -extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ); -static Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj ); -static Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk ); - -extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Interface with the FPGA mapping package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) -{ - Abc_Ntk_t * pNtkNew; - If_Man_t * pIfMan; - - assert( Abc_NtkIsStrash(pNtk) ); - - // get timing information - pPars->pTimesArr = Abc_NtkGetCiArrivalFloats(pNtk); - pPars->pTimesReq = NULL; - - // set the latch paths - if ( pPars->fLatchPaths && pPars->pTimesArr ) - { - int c; - for ( c = 0; c < Abc_NtkPiNum(pNtk); c++ ) - pPars->pTimesArr[c] = -ABC_INFINITY; - } - - // perform FPGA mapping - pIfMan = Abc_NtkToIf( pNtk, pPars ); - if ( pIfMan == NULL ) - return NULL; - if ( !If_ManPerformMapping( pIfMan ) ) - { - If_ManStop( pIfMan ); - return NULL; - } - - // transform the result of mapping into the new network - pNtkNew = Abc_NtkFromIf( pIfMan, pNtk ); - if ( pNtkNew == NULL ) - return NULL; - If_ManStop( pIfMan ); - - // duplicate EXDC - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkIf: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Load the network into FPGA manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Man_t * Abc_NtkToIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ) -{ - ProgressBar * pProgress; - If_Man_t * pIfMan; - Abc_Obj_t * pNode, * pFanin, * pPrev; - Vec_Ptr_t * vNodes; - int i; - - assert( Abc_NtkIsStrash(pNtk) ); -// vNodes = Abc_NtkFindGoodOrder( pNtk ); - vNodes = Abc_AigDfs( pNtk, 0, 0 ); - - // start the mapping manager and set its parameters - pIfMan = If_ManStart( pPars ); - - // print warning about excessive memory usage - if ( 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30) > 1.0 ) - printf( "Warning: The mapper will allocate %.1f Gb for to represent the subject graph with %d AIG nodes.\n", - 1.0 * Abc_NtkObjNum(pNtk) * pIfMan->nObjBytes / (1<<30), Abc_NtkObjNum(pNtk) ); - - // create PIs and remember them in the old nodes - Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)If_ManConst1( pIfMan ); - Abc_NtkForEachCi( pNtk, pNode, i ) - { - pNode->pCopy = (Abc_Obj_t *)If_ManCreateCi( pIfMan ); -//printf( "AIG CI %2d -> IF CI %2d\n", pNode->Id, ((If_Obj_t *)pNode->pCopy)->Id ); - } - - // load the AIG into the mapper - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); -// Abc_AigForEachAnd( pNtk, pNode, i ) - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, "Initial" ); - // add the node to the mapper - pNode->pCopy = (Abc_Obj_t *)If_ManCreateAnd( pIfMan, - If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), - If_NotCond( (If_Obj_t *)Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); - // set up the choice node - if ( Abc_AigNodeIsChoice( pNode ) ) - { - pIfMan->nChoices++; - for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) - If_ObjSetChoice( (If_Obj_t *)pPrev->pCopy, (If_Obj_t *)pFanin->pCopy ); - If_ManCreateChoice( pIfMan, (If_Obj_t *)pNode->pCopy ); - } -//printf( "AIG node %2d -> IF node %2d\n", pNode->Id, ((If_Obj_t *)pNode->pCopy)->Id ); - } - Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vNodes ); - - // set the primary outputs without copying the phase - Abc_NtkForEachCo( pNtk, pNode, i ) - If_ManCreateCo( pIfMan, If_NotCond( (If_Obj_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ) ); - return pIfMan; -} - -/**Function************************************************************* - - Synopsis [Creates the mapped network.] - - Description [Assuming the copy field of the mapped nodes are NULL.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromIf( If_Man_t * pIfMan, Abc_Ntk_t * pNtk ) -{ - ProgressBar * pProgress; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pNode, * pNodeNew; - Vec_Int_t * vCover; - int i, nDupGates; - // create the new network - if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); - else if ( pIfMan->pPars->fUseSops ) - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); - else - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_AIG ); - // prepare the mapping manager - If_ManCleanNodeCopy( pIfMan ); - If_ManCleanCutData( pIfMan ); - // make the mapper point to the new network - If_ObjSetCopy( If_ManConst1(pIfMan), Abc_NtkCreateNodeConst1(pNtkNew) ); - Abc_NtkForEachCi( pNtk, pNode, i ) - If_ObjSetCopy( If_ManCi(pIfMan, i), pNode->pCopy ); - // process the nodes in topological order - vCover = Vec_IntAlloc( 1 << 16 ); - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, "Final" ); - pNodeNew = Abc_NodeFromIf_rec( pNtkNew, pIfMan, If_ObjFanin0(If_ManCo(pIfMan, i)), vCover ); - pNodeNew = Abc_ObjNotCond( pNodeNew, If_ObjFaninC0(If_ManCo(pIfMan, i)) ); - Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); - } - Extra_ProgressBarStop( pProgress ); - Vec_IntFree( vCover ); - // remove the constant node if not used - pNodeNew = (Abc_Obj_t *)If_ObjCopy( If_ManConst1(pIfMan) ); - if ( Abc_ObjFanoutNum(pNodeNew) == 0 ) - Abc_NtkDeleteObj( pNodeNew ); - // minimize the node - if ( pIfMan->pPars->fUseBdds || pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) - Abc_NtkSweep( pNtkNew, 0 ); - if ( pIfMan->pPars->fUseBdds ) - Abc_NtkBddReorder( pNtkNew, 0 ); - // decouple the PO driver nodes to reduce the number of levels - nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); -// if ( nDupGates && If_ManReadVerbose(pIfMan) ) -// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Derive one node after FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ) -{ - Abc_Obj_t * pNodeNew; - If_Cut_t * pCutBest; - If_Obj_t * pIfLeaf; - int i; - // return if the result if known - pNodeNew = (Abc_Obj_t *)If_ObjCopy( pIfObj ); - if ( pNodeNew ) - return pNodeNew; - assert( pIfObj->Type == IF_AND ); - // get the parameters of the best cut - // create a new node - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - pCutBest = If_ObjCutBest( pIfObj ); - if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) - { - If_CutForEachLeafReverse( pIfMan, pCutBest, pIfLeaf, i ) - Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); - } - else - { - If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, i ) - Abc_ObjAddFanin( pNodeNew, Abc_NodeFromIf_rec(pNtkNew, pIfMan, pIfLeaf, vCover) ); - } - // set the level of the new node - pNodeNew->Level = Abc_ObjLevelNew( pNodeNew ); - // derive the function of this node - if ( pIfMan->pPars->fTruth ) - { - if ( pIfMan->pPars->fUseBdds ) - { - // transform truth table into the BDD - pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 0 ); Cudd_Ref(pNodeNew->pData); - } - else if ( pIfMan->pPars->fUseCnfs || pIfMan->pPars->fUseMv ) - { - // transform truth table into the BDD - pNodeNew->pData = Kit_TruthToBdd( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), 1 ); Cudd_Ref(pNodeNew->pData); - } - else if ( pIfMan->pPars->fUseSops ) - { - // transform truth table into the SOP - int RetValue = Kit_TruthIsop( If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover, 1 ); - assert( RetValue == 0 || RetValue == 1 ); - // check the case of constant cover - if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) - { - assert( RetValue == 0 ); - pNodeNew->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), NULL ); - pNodeNew = (Vec_IntSize(vCover) == 0) ? Abc_NtkCreateNodeConst0(pNtkNew) : Abc_NtkCreateNodeConst1(pNtkNew); - } - else - { - // derive the AIG for that tree - pNodeNew->pData = Abc_SopCreateFromIsop( pNtkNew->pManFunc, If_CutLeaveNum(pCutBest), vCover ); - if ( RetValue ) - Abc_SopComplement( pNodeNew->pData ); - } - } - else - { - extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); - pNodeNew->pData = Kit_TruthToHop( pNtkNew->pManFunc, If_CutTruth(pCutBest), If_CutLeaveNum(pCutBest), vCover ); - } - // complement the node if the cut was complemented - if ( pCutBest->fCompl ) - Abc_NodeComplement( pNodeNew ); - } - else - pNodeNew->pData = Abc_NodeIfToHop( pNtkNew->pManFunc, pIfMan, pIfObj ); - If_ObjSetCopy( pIfObj, pNodeNew ); - return pNodeNew; -} - -/**Function************************************************************* - - Synopsis [Recursively derives the truth table for the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Abc_NodeIfToHop_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited ) -{ - If_Cut_t * pCut; - Hop_Obj_t * gFunc, * gFunc0, * gFunc1; - // get the best cut - pCut = If_ObjCutBest(pIfObj); - // if the cut is visited, return the result - if ( If_CutData(pCut) ) - return If_CutData(pCut); - // compute the functions of the children - gFunc0 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin0, vVisited ); - gFunc1 = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj->pFanin1, vVisited ); - // get the function of the cut - gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pIfObj->fCompl0), Hop_NotCond(gFunc1, pIfObj->fCompl1) ); - assert( If_CutData(pCut) == NULL ); - If_CutSetData( pCut, gFunc ); - // add this cut to the visited list - Vec_PtrPush( vVisited, pCut ); - return gFunc; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table for one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Abc_NodeIfToHop( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj ) -{ - If_Cut_t * pCut; - Hop_Obj_t * gFunc; - If_Obj_t * pLeaf; - int i; - // get the best cut - pCut = If_ObjCutBest(pIfObj); - assert( pCut->nLeaves > 1 ); - // set the leaf variables - If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) - If_CutSetData( If_ObjCutBest(pLeaf), Hop_IthVar(pHopMan, i) ); - // recursively compute the function while collecting visited cuts - Vec_PtrClear( pIfMan->vTemp ); - gFunc = Abc_NodeIfToHop_rec( pHopMan, pIfMan, pIfObj, pIfMan->vTemp ); -// printf( "%d ", Vec_PtrSize(p->vTemp) ); - // clean the cuts - If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) - If_CutSetData( If_ObjCutBest(pLeaf), NULL ); - Vec_PtrForEachEntry( pIfMan->vTemp, pCut, i ) - If_CutSetData( pCut, NULL ); - return gFunc; -} - - -/**Function************************************************************* - - Synopsis [Comparison for two nodes with the flow.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ObjCompareFlow( Abc_Obj_t ** ppNode0, Abc_Obj_t ** ppNode1 ) -{ - float Flow0 = Abc_Int2Float((int)(*ppNode0)->pCopy); - float Flow1 = Abc_Int2Float((int)(*ppNode1)->pCopy); - if ( Flow0 > Flow1 ) - return -1; - if ( Flow0 < Flow1 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Orders AIG nodes so that nodes from larger cones go first.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFindGoodOrder_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - if ( !Abc_ObjIsNode(pNode) ) - return; - assert( Abc_ObjIsNode( pNode ) ); - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // visit the transitive fanin of the node - Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes ); - Abc_NtkFindGoodOrder_rec( Abc_ObjFanin1(pNode), vNodes ); - // add the node after the fanins have been added - Vec_PtrPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Orders AIG nodes so that nodes from larger cones go first.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkFindGoodOrder( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes, * vCos; - Abc_Obj_t * pNode, * pFanin0, * pFanin1; - float Flow0, Flow1; - int i; - - // initialize the flow - Abc_AigConst1(pNtk)->pCopy = NULL; - Abc_NtkForEachCi( pNtk, pNode, i ) - pNode->pCopy = NULL; - // compute the flow - Abc_AigForEachAnd( pNtk, pNode, i ) - { - pFanin0 = Abc_ObjFanin0(pNode); - pFanin1 = Abc_ObjFanin1(pNode); - Flow0 = Abc_Int2Float((int)pFanin0->pCopy)/Abc_ObjFanoutNum(pFanin0); - Flow1 = Abc_Int2Float((int)pFanin1->pCopy)/Abc_ObjFanoutNum(pFanin1); - pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int(Flow0 + Flow1+(float)1.0); - } - // find the flow of the COs - vCos = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - pNode->pCopy = Abc_ObjFanin0(pNode)->pCopy; -// pNode->pCopy = (Abc_Obj_t *)Abc_Float2Int((float)Abc_ObjFanin0(pNode)->Level); - Vec_PtrPush( vCos, pNode ); - } - - // sort nodes in the increasing order of the flow - qsort( (Abc_Obj_t **)Vec_PtrArray(vCos), Abc_NtkCoNum(pNtk), - sizeof(Abc_Obj_t *), (int (*)(const void *, const void *))Abc_ObjCompareFlow ); - // verify sorting - pFanin0 = Vec_PtrEntry(vCos, 0); - pFanin1 = Vec_PtrEntryLast(vCos); - assert( Abc_Int2Float((int)pFanin0->pCopy) >= Abc_Int2Float((int)pFanin1->pCopy) ); - - // collect the nodes in the topological order from the new array - Abc_NtkIncrementTravId( pNtk ); - vNodes = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( vCos, pNode, i ) - { - Abc_NtkFindGoodOrder_rec( Abc_ObjFanin0(pNode), vNodes ); -// printf( "%.2f ", Abc_Int2Float((int)pNode->pCopy) ); - } - Vec_PtrFree( vCos ); - return vNodes; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcIvy.c b/src/base/abci/abcIvy.c deleted file mode 100644 index b878091b..00000000 --- a/src/base/abci/abcIvy.c +++ /dev/null @@ -1,1101 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcIvy.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Strashing of the current network.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcIvy.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "dec.h" -#include "ivy.h" -#include "fraig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan ); -static Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig ); -static Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld ); - -static void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ); -static Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode ); -static Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); -static Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); -static Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ); -extern char * Mio_GateReadSop( void * pGate ); - -typedef int Abc_Edge_t; -static inline Abc_Edge_t Abc_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } -static inline int Abc_EdgeId( Abc_Edge_t Edge ) { return Edge >> 1; } -static inline int Abc_EdgeIsComplement( Abc_Edge_t Edge ) { return Edge & 1; } -static inline Abc_Edge_t Abc_EdgeRegular( Abc_Edge_t Edge ) { return (Edge >> 1) << 1; } -static inline Abc_Edge_t Abc_EdgeNot( Abc_Edge_t Edge ) { return Edge ^ 1; } -static inline Abc_Edge_t Abc_EdgeNotCond( Abc_Edge_t Edge, int fCond ) { return Edge ^ fCond; } -static inline Abc_Edge_t Abc_EdgeFromNode( Abc_Obj_t * pNode ) { return Abc_EdgeCreate( Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ); } -static inline Abc_Obj_t * Abc_EdgeToNode( Abc_Ntk_t * p, Abc_Edge_t Edge ) { return Abc_ObjNotCond( Abc_NtkObj(p, Abc_EdgeId(Edge)), Abc_EdgeIsComplement(Edge) ); } - -static inline Abc_Obj_t * Abc_ObjFanin0Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ); } -static inline Abc_Obj_t * Abc_ObjFanin1Ivy( Abc_Ntk_t * p, Ivy_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_EdgeToNode(p, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ); } - -static Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs ); - -extern int timeRetime; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Prepares the IVY package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Abc_NtkIvyBefore( Abc_Ntk_t * pNtk, int fSeq, int fUseDc ) -{ - Ivy_Man_t * pMan; - int fCleanup = 1; -//timeRetime = clock(); - assert( !Abc_NtkIsNetlist(pNtk) ); - if ( Abc_NtkIsBddLogic(pNtk) ) - { - if ( !Abc_NtkBddToSop(pNtk, 0) ) - { - printf( "Abc_NtkIvyBefore(): Converting to SOPs has failed.\n" ); - return NULL; - } - } - if ( fSeq && Abc_NtkCountSelfFeedLatches(pNtk) ) - { - printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtk) ); -// return NULL; - } - // print warning about choice nodes - if ( Abc_NtkGetChoiceNum( pNtk ) ) - printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" ); - // convert to the AIG manager - pMan = Abc_NtkToIvy( pNtk ); - if ( !Ivy_ManCheck( pMan ) ) - { - printf( "AIG check has failed.\n" ); - Ivy_ManStop( pMan ); - return NULL; - } -// Ivy_ManPrintStats( pMan ); - if ( fSeq ) - { - int nLatches = Abc_NtkLatchNum(pNtk); - Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, fUseDc ); - Ivy_ManMakeSeq( pMan, nLatches, vInit->pArray ); - Vec_IntFree( vInit ); -// Ivy_ManPrintStats( pMan ); - } -//timeRetime = clock() - timeRetime; - return pMan; -} - -/**Function************************************************************* - - Synopsis [Prepares the IVY package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkIvyAfter( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan, int fSeq, int fHaig ) -{ - Abc_Ntk_t * pNtkAig; - int nNodes, fCleanup = 1; - // convert from the AIG manager - if ( fSeq ) - pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan, fHaig ); - else - pNtkAig = Abc_NtkFromIvy( pNtk, pMan ); - // report the cleanup results - if ( !fHaig && fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) - printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); - // duplicate EXDC - if ( pNtk->pExdc ) - pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); - // make sure everything is okay - if ( !Abc_NtkCheck( pNtkAig ) ) - { - printf( "Abc_NtkStrash: The network check has failed.\n" ); - Abc_NtkDelete( pNtkAig ); - return NULL; - } - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkAig; - Ivy_Man_t * pMan; - pMan = Abc_NtkIvyBefore( pNtk, 1, 0 ); - if ( pMan == NULL ) - return NULL; - pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); - Ivy_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkIvyHaig( Abc_Ntk_t * pNtk, int nIters, int fUseZeroCost, int fVerbose ) -{ - Abc_Ntk_t * pNtkAig; - Ivy_Man_t * pMan; - int clk; -// int i; -/* -extern int nMoves; -extern int nMovesS; -extern int nClauses; -extern int timeInv; - -nMoves = 0; -nMovesS = 0; -nClauses = 0; -timeInv = 0; -*/ - pMan = Abc_NtkIvyBefore( pNtk, 1, 1 ); - if ( pMan == NULL ) - return NULL; -//timeRetime = clock(); - -clk = clock(); - Ivy_ManHaigStart( pMan, fVerbose ); -// Ivy_ManRewriteSeq( pMan, 0, 0 ); -// for ( i = 0; i < nIters; i++ ) -// Ivy_ManRewriteSeq( pMan, fUseZeroCost, 0 ); - -//printf( "%d ", Ivy_ManNodeNum(pMan) ); - Ivy_ManRewriteSeq( pMan, 0, 0 ); - Ivy_ManRewriteSeq( pMan, 0, 0 ); - Ivy_ManRewriteSeq( pMan, 1, 0 ); -//printf( "%d ", Ivy_ManNodeNum(pMan) ); -//printf( "%d ", Ivy_ManNodeNum(pMan->pHaig) ); -//PRT( " ", clock() - clk ); -//printf( "\n" ); -/* - printf( "Moves = %d. ", nMoves ); - printf( "MovesS = %d. ", nMovesS ); - printf( "Clauses = %d. ", nClauses ); - PRT( "Time", timeInv ); -*/ -// Ivy_ManRewriteSeq( pMan, 1, 0 ); -//printf( "Haig size = %d.\n", Ivy_ManNodeNum(pMan->pHaig) ); -// Ivy_ManHaigPostprocess( pMan, fVerbose ); -//timeRetime = clock() - timeRetime; - - // write working AIG into the current network -// pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); - // write HAIG into the current network - pNtkAig = Abc_NtkIvyAfter( pNtk, pMan->pHaig, 1, 1 ); - - Ivy_ManHaigStop( pMan ); - Ivy_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs ) -{ - extern void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs ); - Ivy_Man_t * pMan; - pMan = Abc_NtkIvyBefore( pNtk, 1, 0 ); - if ( pMan == NULL ) - return; - Ivy_CutComputeAll( pMan, nInputs ); - Ivy_ManStop( pMan ); -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose ) -{ - Abc_Ntk_t * pNtkAig; - Ivy_Man_t * pMan; - pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); - if ( pMan == NULL ) - return NULL; -//timeRetime = clock(); - Ivy_ManRewritePre( pMan, fUpdateLevel, fUseZeroCost, fVerbose ); -//timeRetime = clock() - timeRetime; - pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); - Ivy_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose ) -{ - Abc_Ntk_t * pNtkAig; - Ivy_Man_t * pMan; - pMan = Abc_NtkIvyBefore( pNtk, 1, 1 ); - if ( pMan == NULL ) - return NULL; -//timeRetime = clock(); - Ivy_ManRewriteSeq( pMan, fUseZeroCost, fVerbose ); -//timeRetime = clock() - timeRetime; -// Ivy_ManRewriteSeq( pMan, 1, 0 ); -// Ivy_ManRewriteSeq( pMan, 1, 0 ); - pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 1, 0 ); - Ivy_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkIvyResyn0( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ) -{ - Abc_Ntk_t * pNtkAig; - Ivy_Man_t * pMan, * pTemp; - pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); - if ( pMan == NULL ) - return NULL; - pMan = Ivy_ManResyn0( pTemp = pMan, fUpdateLevel, fVerbose ); - Ivy_ManStop( pTemp ); - pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); - Ivy_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ) -{ - Abc_Ntk_t * pNtkAig; - Ivy_Man_t * pMan, * pTemp; - pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); - if ( pMan == NULL ) - return NULL; - pMan = Ivy_ManResyn( pTemp = pMan, fUpdateLevel, fVerbose ); - Ivy_ManStop( pTemp ); - pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); - Ivy_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose ) -{ - Ivy_FraigParams_t Params, * pParams = &Params; - Abc_Ntk_t * pNtkAig; - Ivy_Man_t * pMan, * pTemp; - pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); - if ( pMan == NULL ) - return NULL; - Ivy_FraigParamsDefault( pParams ); - pParams->nBTLimitMiter = nConfLimit; - pParams->fVerbose = fVerbose; -// pMan = Ivy_FraigPerform( pTemp = pMan, pParams ); - pMan = Ivy_FraigMiter( pTemp = pMan, pParams ); - Ivy_ManStop( pTemp ); - pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); - Ivy_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Sets the final nodes to point to the original nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkTransferPointers( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig ) -{ - Abc_Obj_t * pObj; - Ivy_Obj_t * pObjIvy, * pObjFraig; - int i; - pObj = Abc_AigConst1(pNtk); - pObj->pCopy = Abc_AigConst1(pNtkAig); - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pCopy = Abc_NtkCi(pNtkAig, i); - Abc_NtkForEachCo( pNtk, pObj, i ) - pObj->pCopy = Abc_NtkCo(pNtkAig, i); - Abc_NtkForEachLatch( pNtk, pObj, i ) - pObj->pCopy = Abc_NtkBox(pNtkAig, i); - Abc_NtkForEachNode( pNtk, pObj, i ) - { - pObjIvy = (Ivy_Obj_t *)pObj->pCopy; - if ( pObjIvy == NULL ) - continue; - pObjFraig = Ivy_ObjEquiv( pObjIvy ); - if ( pObjFraig == NULL ) - continue; - pObj->pCopy = Abc_EdgeToNode( pNtkAig, Ivy_Regular(pObjFraig)->TravId ); - pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, Ivy_IsComplement(pObjFraig) ); - } -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ) -{ - Ivy_FraigParams_t Params, * pParams = &Params; - Abc_Ntk_t * pNtkAig; - Ivy_Man_t * pMan, * pTemp; - pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); - if ( pMan == NULL ) - return NULL; - Ivy_FraigParamsDefault( pParams ); - pParams->nBTLimitNode = nConfLimit; - pParams->fVerbose = fVerbose; - pParams->fProve = fProve; - pParams->fDoSparse = fDoSparse; - pMan = Ivy_FraigPerform( pTemp = pMan, pParams ); - // transfer the pointers - if ( fTransfer == 1 ) - { - Vec_Ptr_t * vCopies; - vCopies = Abc_NtkSaveCopy( pNtk ); - pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); - Abc_NtkLoadCopy( pNtk, vCopies ); - Vec_PtrFree( vCopies ); - Abc_NtkTransferPointers( pNtk, pNtkAig ); - } - else - pNtkAig = Abc_NtkIvyAfter( pNtk, pMan, 0, 0 ); - Ivy_ManStop( pTemp ); - Ivy_ManStop( pMan ); - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ) -{ - Prove_Params_t * pParams = pPars; - Abc_Ntk_t * pNtk = *ppNtk, * pNtkTemp; - Abc_Obj_t * pObj, * pFanin; - Ivy_Man_t * pMan; - int RetValue; - assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); - // experiment with various parameters settings -// pParams->fUseBdds = 1; -// pParams->fBddReorder = 1; -// pParams->nTotalBacktrackLimit = 10000; - - // strash the network if it is not strashed already - if ( !Abc_NtkIsStrash(pNtk) ) - { - pNtk = Abc_NtkStrash( pNtkTemp = pNtk, 0, 1, 0 ); - Abc_NtkDelete( pNtkTemp ); - } - - // check the case when the 0000 simulation pattern detect the bug - pObj = Abc_NtkPo(pNtk,0); - pFanin = Abc_ObjFanin0(pObj); - if ( Abc_ObjFanin0(pObj)->fPhase != (unsigned)Abc_ObjFaninC0(pObj) ) - { - pNtk->pModel = ALLOC( int, Abc_NtkPiNum(pNtk) ); - memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkPiNum(pNtk) ); - return 0; - } - - // if SAT only, solve without iteration - RetValue = Abc_NtkMiterSat( pNtk, 2*(sint64)pParams->nMiteringLimitStart, (sint64)0, 0, NULL, NULL ); - if ( RetValue >= 0 ) - return RetValue; - - // apply AIG rewriting - if ( pParams->fUseRewriting && Abc_NtkNodeNum(pNtk) > 500 ) - { - pParams->fUseRewriting = 0; - pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); - Abc_NtkDelete( pNtkTemp ); - Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); - Abc_NtkDelete( pNtkTemp ); - Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); - } - - // convert ABC network into IVY network - pMan = Abc_NtkIvyBefore( pNtk, 0, 0 ); - - // solve the CEC problem - RetValue = Ivy_FraigProve( &pMan, pParams ); - // convert IVY network into ABC network - pNtk = Abc_NtkIvyAfter( pNtkTemp = pNtk, pMan, 0, 0 ); - Abc_NtkDelete( pNtkTemp ); - // transfer model if given - pNtk->pModel = pMan->pData; pMan->pData = NULL; - Ivy_ManStop( pMan ); - - // try to prove it using brute force SAT - if ( RetValue < 0 && pParams->fUseBdds ) - { - if ( pParams->fVerbose ) - { - printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); - fflush( stdout ); - } - pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); - if ( pNtk ) - { - Abc_NtkDelete( pNtkTemp ); - RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) ); - } - else - pNtk = pNtkTemp; - } - - // return the result - *ppNtk = pNtk; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkIvy( Abc_Ntk_t * pNtk ) -{ -// Abc_Ntk_t * pNtkAig; - Ivy_Man_t * pMan;//, * pTemp; - int fCleanup = 1; -// int nNodes; - int nLatches = Abc_NtkLatchNum(pNtk); - Vec_Int_t * vInit = Abc_NtkCollectLatchValuesIvy( pNtk, 0 ); - - assert( !Abc_NtkIsNetlist(pNtk) ); - if ( Abc_NtkIsBddLogic(pNtk) ) - { - if ( !Abc_NtkBddToSop(pNtk, 0) ) - { - Vec_IntFree( vInit ); - printf( "Abc_NtkIvy(): Converting to SOPs has failed.\n" ); - return NULL; - } - } - if ( Abc_NtkCountSelfFeedLatches(pNtk) ) - { - printf( "Warning: The network has %d self-feeding latches. Quitting.\n", Abc_NtkCountSelfFeedLatches(pNtk) ); - return NULL; - } - - // print warning about choice nodes - if ( Abc_NtkGetChoiceNum( pNtk ) ) - printf( "Warning: The choice nodes in the initial AIG are removed by strashing.\n" ); - - // convert to the AIG manager - pMan = Abc_NtkToIvy( pNtk ); - if ( !Ivy_ManCheck( pMan ) ) - { - Vec_IntFree( vInit ); - printf( "AIG check has failed.\n" ); - Ivy_ManStop( pMan ); - return NULL; - } - -// Ivy_MffcTest( pMan ); -// Ivy_ManPrintStats( pMan ); - -// pMan = Ivy_ManBalance( pTemp = pMan, 1 ); -// Ivy_ManStop( pTemp ); - -// Ivy_ManSeqRewrite( pMan, 0, 0 ); -// Ivy_ManTestCutsAlg( pMan ); -// Ivy_ManTestCutsBool( pMan ); -// Ivy_ManRewriteAlg( pMan, 1, 1 ); - -// pMan = Ivy_ManResyn( pTemp = pMan, 1, 0 ); -// Ivy_ManStop( pTemp ); - -// Ivy_ManTestCutsAll( pMan ); -// Ivy_ManTestCutsTravAll( pMan ); - -// Ivy_ManPrintStats( pMan ); - -// Ivy_ManPrintStats( pMan ); -// Ivy_ManRewritePre( pMan, 1, 0, 0 ); -// Ivy_ManPrintStats( pMan ); -// printf( "\n" ); - -// Ivy_ManPrintStats( pMan ); -// Ivy_ManMakeSeq( pMan, nLatches, pInit ); -// Ivy_ManPrintStats( pMan ); - -// Ivy_ManRequiredLevels( pMan ); - -// Ivy_FastMapPerform( pMan, 8 ); - Ivy_ManStop( pMan ); - return NULL; - - -/* - // convert from the AIG manager - pNtkAig = Abc_NtkFromIvy( pNtk, pMan ); -// pNtkAig = Abc_NtkFromIvySeq( pNtk, pMan ); - Ivy_ManStop( pMan ); - - // report the cleanup results - if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) - printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); - // duplicate EXDC - if ( pNtk->pExdc ) - pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); - // make sure everything is okay - if ( !Abc_NtkCheck( pNtkAig ) ) - { - FREE( pInit ); - printf( "Abc_NtkStrash: The network check has failed.\n" ); - Abc_NtkDelete( pNtkAig ); - return NULL; - } - - FREE( pInit ); - return pNtkAig; -*/ -} - - - -/**Function************************************************************* - - Synopsis [Converts the network from the AIG manager into ABC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromIvy( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan ) -{ - Vec_Int_t * vNodes; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; - Ivy_Obj_t * pNode; - int i; - // perform strashing - pNtk = Abc_NtkStartFrom( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // transfer the pointers to the basic nodes - Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) ); - Abc_NtkForEachCi( pNtkOld, pObj, i ) - Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy ); - // rebuild the AIG - vNodes = Ivy_ManDfs( pMan ); - Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i ) - { - // add the first fanin - pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode ); - if ( Ivy_ObjIsBuf(pNode) ) - { - pNode->TravId = Abc_EdgeFromNode( pFaninNew0 ); - continue; - } - // add the second fanin - pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode ); - // create the new node - if ( Ivy_ObjIsExor(pNode) ) - pObjNew = Abc_AigXor( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); - else - pObjNew = Abc_AigAnd( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); - pNode->TravId = Abc_EdgeFromNode( pObjNew ); - } - // connect the PO nodes - Abc_NtkForEachCo( pNtkOld, pObj, i ) - { - pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) ); - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - } - Vec_IntFree( vNodes ); - if ( !Abc_NtkCheck( pNtk ) ) - fprintf( stdout, "Abc_NtkFromIvy(): Network check has failed.\n" ); - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Converts the network from the AIG manager into ABC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromIvySeq( Abc_Ntk_t * pNtkOld, Ivy_Man_t * pMan, int fHaig ) -{ - Vec_Int_t * vNodes, * vLatches; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pObj, * pObjNew, * pFaninNew, * pFaninNew0, * pFaninNew1; - Ivy_Obj_t * pNode, * pTemp; - int i; -// assert( Ivy_ManLatchNum(pMan) > 0 ); - // perform strashing - pNtk = Abc_NtkStartFromNoLatches( pNtkOld, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // transfer the pointers to the basic nodes - Ivy_ManConst1(pMan)->TravId = Abc_EdgeFromNode( Abc_AigConst1(pNtk) ); - Abc_NtkForEachPi( pNtkOld, pObj, i ) - Ivy_ManPi(pMan, i)->TravId = Abc_EdgeFromNode( pObj->pCopy ); - // create latches of the new network - vNodes = Ivy_ManDfsSeq( pMan, &vLatches ); - Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i ) - { - pObjNew = Abc_NtkCreateLatch( pNtk ); - pFaninNew0 = Abc_NtkCreateBi( pNtk ); - pFaninNew1 = Abc_NtkCreateBo( pNtk ); - Abc_ObjAddFanin( pObjNew, pFaninNew0 ); - Abc_ObjAddFanin( pFaninNew1, pObjNew ); - if ( fHaig || Ivy_ObjInit(pNode) == IVY_INIT_DC ) - Abc_LatchSetInitDc( pObjNew ); - else if ( Ivy_ObjInit(pNode) == IVY_INIT_1 ) - Abc_LatchSetInit1( pObjNew ); - else if ( Ivy_ObjInit(pNode) == IVY_INIT_0 ) - Abc_LatchSetInit0( pObjNew ); - else assert( 0 ); - pNode->TravId = Abc_EdgeFromNode( pFaninNew1 ); - } - Abc_NtkAddDummyBoxNames( pNtk ); - // rebuild the AIG - Ivy_ManForEachNodeVec( pMan, vNodes, pNode, i ) - { - // add the first fanin - pFaninNew0 = Abc_ObjFanin0Ivy( pNtk, pNode ); - if ( Ivy_ObjIsBuf(pNode) ) - { - pNode->TravId = Abc_EdgeFromNode( pFaninNew0 ); - continue; - } - // add the second fanin - pFaninNew1 = Abc_ObjFanin1Ivy( pNtk, pNode ); - // create the new node - if ( Ivy_ObjIsExor(pNode) ) - pObjNew = Abc_AigXor( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); - else - pObjNew = Abc_AigAnd( pNtk->pManFunc, pFaninNew0, pFaninNew1 ); - pNode->TravId = Abc_EdgeFromNode( pObjNew ); - // process the choice nodes - if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 ) - { - pFaninNew = Abc_EdgeToNode( pNtk, pNode->TravId ); -// pFaninNew->fPhase = 0; - assert( !Ivy_IsComplement(pNode->pEquiv) ); - for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) ) - { - pFaninNew1 = Abc_EdgeToNode( pNtk, pTemp->TravId ); -// pFaninNew1->fPhase = Ivy_IsComplement( pTemp->pEquiv ); - pFaninNew->pData = pFaninNew1; - pFaninNew = pFaninNew1; - } - pFaninNew->pData = NULL; -// printf( "Writing choice node %d.\n", pNode->Id ); - } - } - // connect the PO nodes - Abc_NtkForEachPo( pNtkOld, pObj, i ) - { - pFaninNew = Abc_ObjFanin0Ivy( pNtk, Ivy_ManPo(pMan, i) ); - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - } - // connect the latches - Ivy_ManForEachNodeVec( pMan, vLatches, pNode, i ) - { - pFaninNew = Abc_ObjFanin0Ivy( pNtk, pNode ); - Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(pNtk, i)), pFaninNew ); - } - Vec_IntFree( vLatches ); - Vec_IntFree( vNodes ); - if ( !Abc_NtkCheck( pNtk ) ) - fprintf( stdout, "Abc_NtkFromIvySeq(): Network check has failed.\n" ); - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Converts the network from the AIG manager into ABC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Man_t * Abc_NtkToIvy( Abc_Ntk_t * pNtkOld ) -{ - Ivy_Man_t * pMan; - Abc_Obj_t * pObj; - Ivy_Obj_t * pFanin; - int i; - // create the manager - assert( Abc_NtkHasSop(pNtkOld) || Abc_NtkIsStrash(pNtkOld) ); - pMan = Ivy_ManStart(); - // create the PIs - if ( Abc_NtkIsStrash(pNtkOld) ) - Abc_AigConst1(pNtkOld)->pCopy = (Abc_Obj_t *)Ivy_ManConst1(pMan); - Abc_NtkForEachCi( pNtkOld, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)Ivy_ObjCreatePi(pMan); - // perform the conversion of the internal nodes - Abc_NtkStrashPerformAig( pNtkOld, pMan ); - // create the POs - Abc_NtkForEachCo( pNtkOld, pObj, i ) - { - pFanin = (Ivy_Obj_t *)Abc_ObjFanin0(pObj)->pCopy; - pFanin = Ivy_NotCond( pFanin, Abc_ObjFaninC0(pObj) ); - Ivy_ObjCreatePo( pMan, pFanin ); - } - Ivy_ManCleanup( pMan ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Prepares the network for strashing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkStrashPerformAig( Abc_Ntk_t * pNtk, Ivy_Man_t * pMan ) -{ -// ProgressBar * pProgress; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode; - int i; - vNodes = Abc_NtkDfs( pNtk, 0 ); -// pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { -// Extra_ProgressBarUpdate( pProgress, i, NULL ); - pNode->pCopy = (Abc_Obj_t *)Abc_NodeStrashAig( pMan, pNode ); - } -// Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Abc_NodeStrashAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode ) -{ - int fUseFactor = 1; - char * pSop; - Ivy_Obj_t * pFanin0, * pFanin1; - - assert( Abc_ObjIsNode(pNode) ); - - // consider the case when the graph is an AIG - if ( Abc_NtkIsStrash(pNode->pNtk) ) - { - if ( Abc_AigNodeIsConst(pNode) ) - return Ivy_ManConst1(pMan); - pFanin0 = (Ivy_Obj_t *)Abc_ObjFanin0(pNode)->pCopy; - pFanin0 = Ivy_NotCond( pFanin0, Abc_ObjFaninC0(pNode) ); - pFanin1 = (Ivy_Obj_t *)Abc_ObjFanin1(pNode)->pCopy; - pFanin1 = Ivy_NotCond( pFanin1, Abc_ObjFaninC1(pNode) ); - return Ivy_And( pMan, pFanin0, pFanin1 ); - } - - // get the SOP of the node - if ( Abc_NtkHasMapping(pNode->pNtk) ) - pSop = Mio_GateReadSop(pNode->pData); - else - pSop = pNode->pData; - - // consider the constant node - if ( Abc_NodeIsConst(pNode) ) - return Ivy_NotCond( Ivy_ManConst1(pMan), Abc_SopIsConst0(pSop) ); - - // consider the special case of EXOR function - if ( Abc_SopIsExorType(pSop) ) - return Abc_NodeStrashAigExorAig( pMan, pNode, pSop ); - - // decide when to use factoring - if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 ) - return Abc_NodeStrashAigFactorAig( pMan, pNode, pSop ); - return Abc_NodeStrashAigSopAig( pMan, pNode, pSop ); -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Abc_NodeStrashAigSopAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ) -{ - Abc_Obj_t * pFanin; - Ivy_Obj_t * pAnd, * pSum; - char * pCube; - int i, nFanins; - - // get the number of node's fanins - nFanins = Abc_ObjFaninNum( pNode ); - assert( nFanins == Abc_SopGetVarNum(pSop) ); - // go through the cubes of the node's SOP - pSum = Ivy_Not( Ivy_ManConst1(pMan) ); - Abc_SopForEachCube( pSop, nFanins, pCube ) - { - // create the AND of literals - pAnd = Ivy_ManConst1(pMan); - Abc_ObjForEachFanin( pNode, pFanin, i ) // pFanin can be a net - { - if ( pCube[i] == '1' ) - pAnd = Ivy_And( pMan, pAnd, (Ivy_Obj_t *)pFanin->pCopy ); - else if ( pCube[i] == '0' ) - pAnd = Ivy_And( pMan, pAnd, Ivy_Not((Ivy_Obj_t *)pFanin->pCopy) ); - } - // add to the sum of cubes - pSum = Ivy_Or( pMan, pSum, pAnd ); - } - // decide whether to complement the result - if ( Abc_SopIsComplement(pSop) ) - pSum = Ivy_Not(pSum); - return pSum; -} - -/**Function************************************************************* - - Synopsis [Strashed n-input XOR function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Abc_NodeStrashAigExorAig( Ivy_Man_t * pMan, Abc_Obj_t * pNode, char * pSop ) -{ - Abc_Obj_t * pFanin; - Ivy_Obj_t * pSum; - int i, nFanins; - // get the number of node's fanins - nFanins = Abc_ObjFaninNum( pNode ); - assert( nFanins == Abc_SopGetVarNum(pSop) ); - // go through the cubes of the node's SOP - pSum = Ivy_Not( Ivy_ManConst1(pMan) ); - for ( i = 0; i < nFanins; i++ ) - { - pFanin = Abc_ObjFanin( pNode, i ); - pSum = Ivy_Exor( pMan, pSum, (Ivy_Obj_t *)pFanin->pCopy ); - } - if ( Abc_SopIsComplement(pSop) ) - pSum = Ivy_Not(pSum); - return pSum; -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Abc_NodeStrashAigFactorAig( Ivy_Man_t * pMan, Abc_Obj_t * pRoot, char * pSop ) -{ - Dec_Graph_t * pFForm; - Dec_Node_t * pNode; - Ivy_Obj_t * pAnd; - int i; - -// extern Ivy_Obj_t * Dec_GraphToNetworkAig( Ivy_Man_t * pMan, Dec_Graph_t * pGraph ); - extern Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph ); - -// assert( 0 ); - - // perform factoring - pFForm = Dec_Factor( pSop ); - // collect the fanins - Dec_GraphForEachLeaf( pFForm, pNode, i ) - pNode->pFunc = Abc_ObjFanin(pRoot,i)->pCopy; - // perform strashing -// pAnd = Dec_GraphToNetworkAig( pMan, pFForm ); - pAnd = Dec_GraphToNetworkIvy( pMan, pFForm ); -// pAnd = NULL; - - Dec_GraphFree( pFForm ); - return pAnd; -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkCollectLatchValuesIvy( Abc_Ntk_t * pNtk, int fUseDcs ) -{ - Abc_Obj_t * pLatch; - Vec_Int_t * vArray; - int i; - vArray = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - if ( fUseDcs || Abc_LatchIsInitDc(pLatch) ) - Vec_IntPush( vArray, IVY_INIT_DC ); - else if ( Abc_LatchIsInit1(pLatch) ) - Vec_IntPush( vArray, IVY_INIT_1 ); - else if ( Abc_LatchIsInit0(pLatch) ) - Vec_IntPush( vArray, IVY_INIT_0 ); - else assert( 0 ); - } - return vArray; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcLut.c b/src/base/abci/abcLut.c deleted file mode 100644 index afa76cc8..00000000 --- a/src/base/abci/abcLut.c +++ /dev/null @@ -1,786 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcLut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Superchoicing for K-LUTs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "cut.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define SCL_LUT_MAX 6 // the maximum LUT size -#define SCL_VARS_MAX 15 // the maximum number of variables -#define SCL_NODE_MAX 1000 // the maximum number of nodes - -typedef struct Abc_ManScl_t_ Abc_ManScl_t; -struct Abc_ManScl_t_ -{ - // paramers - int nLutSize; // the LUT size - int nCutSizeMax; // the max number of leaves of the cone - int nNodesMax; // the max number of divisors in the cone - int nWords; // the number of machine words in sim info - // structural representation of the cone - Vec_Ptr_t * vLeaves; // leaves of the cut - Vec_Ptr_t * vVolume; // volume of the cut - int pBSet[SCL_VARS_MAX]; // bound set - // functional representation of the cone - unsigned * uTruth; // truth table of the cone - // representation of truth tables - unsigned ** uVars; // elementary truth tables - unsigned ** uSims; // truth tables of the nodes - unsigned ** uCofs; // truth tables of the cofactors -}; - -static Vec_Ptr_t * s_pLeaves = NULL; - -static Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize ); -static Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax ); -static void Abc_ManSclStop( Abc_ManScl_t * p ); -static void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj ); - -static Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * pManScl, Abc_Obj_t * pObj ); -static int Abc_NodeDecomposeStep( Abc_ManScl_t * pManScl ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs superchoicing for K-LUTs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkSuperChoiceLut( Abc_Ntk_t * pNtk, int nLutSize, int nCutSizeMax, int fVerbose ) -{ - ProgressBar * pProgress; - Abc_ManCut_t * pManCut; - Abc_ManScl_t * pManScl; - Cut_Man_t * pManCuts; - Abc_Obj_t * pObj, * pFanin, * pObjTop; - int i, LevelMax, nNodes; - int nNodesTried, nNodesDec, nNodesExist, nNodesUsed; - - assert( Abc_NtkIsSopLogic(pNtk) ); - if ( nLutSize < 3 || nLutSize > SCL_LUT_MAX ) - { - printf( "LUT size (%d) does not belong to the interval: 3 <= LUT size <= %d\n", nLutSize, SCL_LUT_MAX ); - return 0; - } - if ( nCutSizeMax <= nLutSize || nCutSizeMax > SCL_VARS_MAX ) - { - printf( "Cut size (%d) does not belong to the interval: LUT size (%d) < Cut size <= %d\n", nCutSizeMax, nLutSize, SCL_VARS_MAX ); - return 0; - } - - assert( nLutSize <= SCL_LUT_MAX ); - assert( nCutSizeMax <= SCL_VARS_MAX ); - nNodesTried = nNodesDec = nNodesExist = nNodesUsed = 0; - - // set the delays of the CIs - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->Level = 0; - -//Abc_NtkLevel( pNtk ); - - // start the managers - pManScl = Abc_ManSclStart( nLutSize, nCutSizeMax, 1000 ); - pManCuts = Abc_NtkStartCutManForScl( pNtk, nLutSize ); - pManCut = Abc_NtkManCutStart( nCutSizeMax, 100000, 100000, 100000 ); - s_pLeaves = Abc_NtkManCutReadCutSmall( pManCut ); - pManScl->vVolume = Abc_NtkManCutReadVisited( pManCut ); - - // process each internal node (assuming topological order of nodes!!!) - nNodes = Abc_NtkObjNumMax(pNtk); - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { -// if ( i != nNodes-1 ) -// continue; - Extra_ProgressBarUpdate( pProgress, i, NULL ); - if ( i >= nNodes ) - break; - if ( Abc_ObjFaninNum(pObj) != 2 ) - continue; - nNodesTried++; - - // map this node using regular cuts -// pObj->Level = 0; - Abc_NodeLutMap( pManCuts, pObj ); - // compute the cut - pManScl->vLeaves = Abc_NodeFindCut( pManCut, pObj, 0 ); - if ( Vec_PtrSize(pManScl->vLeaves) <= nLutSize ) - continue; - // get the volume of the cut - if ( Vec_PtrSize(pManScl->vVolume) > SCL_NODE_MAX ) - continue; - nNodesDec++; - - // decompose the cut - pObjTop = Abc_NodeSuperChoiceLut( pManScl, pObj ); - if ( pObjTop == NULL ) - continue; - nNodesExist++; - - // if there is no delay improvement, skip; otherwise, update level - if ( pObjTop->Level >= pObj->Level ) - { - Abc_NtkDeleteObj_rec( pObjTop, 1 ); - continue; - } - pObj->Level = pObjTop->Level; - nNodesUsed++; - } - Extra_ProgressBarStop( pProgress ); - - // delete the managers - Abc_ManSclStop( pManScl ); - Abc_NtkManCutStop( pManCut ); - Cut_ManStop( pManCuts ); - - // get the largest arrival time - LevelMax = 0; - Abc_NtkForEachCo( pNtk, pObj, i ) - { - pFanin = Abc_ObjFanin0( pObj ); - // skip inv/buf - if ( Abc_ObjFaninNum(pFanin) == 1 ) - pFanin = Abc_ObjFanin0( pFanin ); - // get the new level - LevelMax = ABC_MAX( LevelMax, (int)pFanin->Level ); - } - - if ( fVerbose ) - printf( "Try = %d. Dec = %d. Exist = %d. Use = %d. SUPER = %d levels of %d-LUTs.\n", - nNodesTried, nNodesDec, nNodesExist, nNodesUsed, LevelMax, nLutSize ); -// if ( fVerbose ) -// printf( "The network is superchoiced for %d levels of %d-LUTs.\n", LevelMax, nLutSize ); - - // clean the data field - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pNext = NULL; - - // check - if ( !Abc_NtkCheck( pNtk ) ) - { - printf( "Abc_NtkSuperChoiceLut: The network check has failed.\n" ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs LUT mapping of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeLutMap( Cut_Man_t * pManCuts, Abc_Obj_t * pObj ) -{ - Cut_Cut_t * pCut; - Abc_Obj_t * pFanin; - int i, DelayMax; - pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCuts, pObj, 0, 0 ); - assert( pCut != NULL ); - assert( pObj->Level == 0 ); - // go through the cuts - pObj->Level = ABC_INFINITY; - for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) - { - DelayMax = 0; - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - { - pFanin = Abc_NtkObj( pObj->pNtk, pCut->pLeaves[i] ); -// assert( Abc_ObjIsCi(pFanin) || pFanin->Level > 0 ); // should hold if node ordering is topological - if ( DelayMax < (int)pFanin->Level ) - DelayMax = pFanin->Level; - } - if ( (int)pObj->Level > DelayMax ) - pObj->Level = DelayMax; - } - assert( pObj->Level < ABC_INFINITY ); - pObj->Level++; -// printf( "%d(%d) ", pObj->Id, pObj->Level ); -} - -/**Function************************************************************* - - Synopsis [Starts the cut manager for rewriting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Man_t * Abc_NtkStartCutManForScl( Abc_Ntk_t * pNtk, int nLutSize ) -{ - static Cut_Params_t Params, * pParams = &Params; - Cut_Man_t * pManCut; - Abc_Obj_t * pObj; - int i; - // start the cut manager - memset( pParams, 0, sizeof(Cut_Params_t) ); - pParams->nVarsMax = nLutSize; // the max cut size ("k" of the k-feasible cuts) - pParams->nKeepMax = 500; // the max number of cuts kept at a node - pParams->fTruth = 0; // compute truth tables - pParams->fFilter = 1; // filter dominated cuts - pParams->fSeq = 0; // compute sequential cuts - pParams->fDrop = 0; // drop cuts on the fly - pParams->fVerbose = 0; // the verbosiness flag - pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); - pManCut = Cut_ManStart( pParams ); - if ( pParams->fDrop ) - Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); - // set cuts for PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) > 0 ) - Cut_NodeSetTriv( pManCut, pObj->Id ); - return pManCut; -} - -/**Function************************************************************* - - Synopsis [Starts the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_ManScl_t * Abc_ManSclStart( int nLutSize, int nCutSizeMax, int nNodesMax ) -{ - Abc_ManScl_t * p; - int i, k; - assert( sizeof(unsigned) == 4 ); - p = ALLOC( Abc_ManScl_t, 1 ); - memset( p, 0, sizeof(Abc_ManScl_t) ); - p->nLutSize = nLutSize; - p->nCutSizeMax = nCutSizeMax; - p->nNodesMax = nNodesMax; - p->nWords = Extra_TruthWordNum(nCutSizeMax); - // allocate simulation info - p->uVars = (unsigned **)Extra_ArrayAlloc( nCutSizeMax, p->nWords, 4 ); - p->uSims = (unsigned **)Extra_ArrayAlloc( nNodesMax, p->nWords, 4 ); - p->uCofs = (unsigned **)Extra_ArrayAlloc( 2 << nLutSize, p->nWords, 4 ); - memset( p->uVars[0], 0, nCutSizeMax * p->nWords * 4 ); - // assign elementary truth tables - for ( k = 0; k < p->nCutSizeMax; k++ ) - for ( i = 0; i < p->nWords * 32; i++ ) - if ( i & (1 << k) ) - p->uVars[k][i>>5] |= (1 << (i&31)); - // other data structures -// p->vBound = Vec_IntAlloc( nCutSizeMax ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManSclStop( Abc_ManScl_t * p ) -{ -// Vec_IntFree( p->vBound ); - free( p->uVars ); - free( p->uSims ); - free( p->uCofs ); - free( p ); -} - - -/**Function************************************************************* - - Synopsis [Performs superchoicing for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Abc_NodeSuperChoiceTruth( Abc_ManScl_t * pManScl ) -{ - Abc_Obj_t * pObj; - unsigned * puData0, * puData1, * puData; - char * pSop; - int i, k; - // set elementary truth tables - Vec_PtrForEachEntry( pManScl->vLeaves, pObj, i ) - pObj->pNext = (Abc_Obj_t *)pManScl->uVars[i]; - // compute truth tables for internal nodes - Vec_PtrForEachEntry( pManScl->vVolume, pObj, i ) - { - // set storage for the node's simulation info - pObj->pNext = (Abc_Obj_t *)pManScl->uSims[i]; - // get pointer to the simulation info - puData = (unsigned *)pObj->pNext; - puData0 = (unsigned *)Abc_ObjFanin0(pObj)->pNext; - puData1 = (unsigned *)Abc_ObjFanin1(pObj)->pNext; - // simulate - pSop = pObj->pData; - if ( pSop[0] == '0' && pSop[1] == '0' ) - for ( k = 0; k < pManScl->nWords; k++ ) - puData[k] = ~puData0[k] & ~puData1[k]; - else if ( pSop[0] == '0' ) - for ( k = 0; k < pManScl->nWords; k++ ) - puData[k] = ~puData0[k] & puData1[k]; - else if ( pSop[1] == '0' ) - for ( k = 0; k < pManScl->nWords; k++ ) - puData[k] = puData0[k] & ~puData1[k]; - else - for ( k = 0; k < pManScl->nWords; k++ ) - puData[k] = puData0[k] & puData1[k]; - } - return puData; -} - -/**Function************************************************************* - - Synopsis [Performs superchoicing for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeSuperChoiceCollect2_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vVolume ) -{ - if ( pObj->fMarkC ) - return; - pObj->fMarkC = 1; - assert( Abc_ObjFaninNum(pObj) == 2 ); - Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin0(pObj), vVolume ); - Abc_NodeSuperChoiceCollect2_rec( Abc_ObjFanin1(pObj), vVolume ); - Vec_PtrPush( vVolume, pObj ); -} - -/**Function************************************************************* - - Synopsis [Performs superchoicing for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeSuperChoiceCollect2( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) -{ - Abc_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->fMarkC = 1; - Vec_PtrClear( vVolume ); - Abc_NodeSuperChoiceCollect2_rec( pRoot, vVolume ); - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->fMarkC = 0; - Vec_PtrForEachEntry( vVolume, pObj, i ) - pObj->fMarkC = 0; -} - -/**Function************************************************************* - - Synopsis [Performs superchoicing for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeSuperChoiceCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) -{ - if ( pObj->fMarkB ) - { - Vec_PtrPush( vLeaves, pObj ); - pObj->fMarkB = 0; - } - if ( pObj->fMarkC ) - return; - pObj->fMarkC = 1; - assert( Abc_ObjFaninNum(pObj) == 2 ); - Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin0(pObj), vLeaves, vVolume ); - Abc_NodeSuperChoiceCollect_rec( Abc_ObjFanin1(pObj), vLeaves, vVolume ); - Vec_PtrPush( vVolume, pObj ); -} - -/**Function************************************************************* - - Synopsis [Performs superchoicing for one node.] - - Description [Orders the leaves topologically.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeSuperChoiceCollect( Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume ) -{ - Abc_Obj_t * pObj; - int i, nLeaves; - nLeaves = Vec_PtrSize(vLeaves); - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->fMarkB = pObj->fMarkC = 1; - Vec_PtrClear( vVolume ); - Vec_PtrClear( vLeaves ); - Abc_NodeSuperChoiceCollect_rec( pRoot, vLeaves, vVolume ); - assert( Vec_PtrSize(vLeaves) == nLeaves ); - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->fMarkC = 0; - Vec_PtrForEachEntry( vVolume, pObj, i ) - pObj->fMarkC = 0; -} - -/**Function************************************************************* - - Synopsis [Performs superchoicing for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeLeavesRemove( Vec_Ptr_t * vLeaves, unsigned uPhase, int nVars ) -{ - int i; - for ( i = nVars - 1; i >= 0; i-- ) - if ( uPhase & (1 << i) ) - Vec_PtrRemove( vLeaves, Vec_PtrEntry(vLeaves, i) ); -} - -/**Function************************************************************* - - Synopsis [Performs superchoicing for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeGetLevel( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i, Level; - Level = 0; - Abc_ObjForEachFanin( pObj, pFanin, i ) - Level = ABC_MAX( Level, (int)pFanin->Level ); - return Level + 1; -} - -/**Function************************************************************* - - Synopsis [Performs superchoicing for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeSuperChoiceLut( Abc_ManScl_t * p, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin, * pObjNew; - int i, nVars, uSupport, nSuppVars; - // collect the cone using DFS (excluding leaves) - Abc_NodeSuperChoiceCollect2( pObj, p->vLeaves, p->vVolume ); - assert( Vec_PtrEntryLast(p->vVolume) == pObj ); - // compute the truth table - p->uTruth = Abc_NodeSuperChoiceTruth( p ); - // get the support of this truth table - nVars = Vec_PtrSize(p->vLeaves); - uSupport = Extra_TruthSupport(p->uTruth, nVars); - nSuppVars = Extra_WordCountOnes(uSupport); - assert( nSuppVars <= nVars ); - if ( nSuppVars == 0 ) - { - pObj->Level = 0; - return NULL; - } - if ( nSuppVars == 1 ) - { - // find the variable - for ( i = 0; i < nVars; i++ ) - if ( uSupport & (1 << i) ) - break; - assert( i < nVars ); - pFanin = Vec_PtrEntry( p->vLeaves, i ); - pObj->Level = pFanin->Level; - return NULL; - } - // support-minimize the truth table - if ( nSuppVars != nVars ) - { - Extra_TruthShrink( p->uCofs[0], p->uTruth, nSuppVars, nVars, uSupport ); - Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars ); - Abc_NodeLeavesRemove( p->vLeaves, ((1 << nVars) - 1) & ~uSupport, nVars ); - } -// return NULL; - // decompose the truth table recursively - while ( Vec_PtrSize(p->vLeaves) > p->nLutSize ) - if ( !Abc_NodeDecomposeStep( p ) ) - { - Vec_PtrForEachEntry( p->vLeaves, pFanin, i ) - if ( Abc_ObjIsNode(pFanin) && Abc_ObjFanoutNum(pFanin) == 0 ) - Abc_NtkDeleteObj_rec( pFanin, 1 ); - return NULL; - } - // create the topmost node - pObjNew = Abc_NtkCreateNode( pObj->pNtk ); - Vec_PtrForEachEntry( p->vLeaves, pFanin, i ) - Abc_ObjAddFanin( pObjNew, pFanin ); - // create the function - pObjNew->pData = Abc_SopCreateFromTruth( pObj->pNtk->pManFunc, Vec_PtrSize(p->vLeaves), p->uTruth ); // need ISOP - pObjNew->Level = Abc_NodeGetLevel( pObjNew ); - return pObjNew; -} - -/**Function************************************************************* - - Synopsis [Procedure used for sorting the nodes in increasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeCompareLevelsInc( int * pp1, int * pp2 ) -{ - Abc_Obj_t * pNode1, * pNode2; - pNode1 = Vec_PtrEntry(s_pLeaves, *pp1); - pNode2 = Vec_PtrEntry(s_pLeaves, *pp2); - if ( pNode1->Level < pNode2->Level ) - return -1; - if ( pNode1->Level > pNode2->Level ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Selects the earliest arriving nodes from the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeDecomposeSort( Abc_Obj_t ** pLeaves, int nVars, int * pBSet, int nLutSize ) -{ - Abc_Obj_t * pTemp[SCL_VARS_MAX]; - int i, k, kBest, LevelMin; - assert( nLutSize < nVars ); - assert( nVars <= SCL_VARS_MAX ); - // copy nodes into the internal storage -// printf( "(" ); - for ( i = 0; i < nVars; i++ ) - { - pTemp[i] = pLeaves[i]; -// printf( " %d", pLeaves[i]->Level ); - } -// printf( " )\n" ); - // choose one node at a time - for ( i = 0; i < nLutSize; i++ ) - { - kBest = -1; - LevelMin = ABC_INFINITY; - for ( k = 0; k < nVars; k++ ) - if ( pTemp[k] && LevelMin > (int)pTemp[k]->Level ) - { - LevelMin = pTemp[k]->Level; - kBest = k; - } - pBSet[i] = kBest; - pTemp[kBest] = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Performs superchoicing for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeDecomposeStep( Abc_ManScl_t * p ) -{ - static char pCofClasses[1<vLeaves, 0))->pNtk; - // find the earliest nodes - nVars = Vec_PtrSize(p->vLeaves); - assert( nVars > p->nLutSize ); -/* - for ( v = 0; v < nVars; v++ ) - p->pBSet[v] = v; - qsort( (void *)p->pBSet, nVars, sizeof(int), - (int (*)(const void *, const void *)) Abc_NodeCompareLevelsInc ); -*/ - Abc_NodeDecomposeSort( (Abc_Obj_t **)Vec_PtrArray(p->vLeaves), Vec_PtrSize(p->vLeaves), p->pBSet, p->nLutSize ); - assert( ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[0]))->Level <= - ((Abc_Obj_t *)Vec_PtrEntry(p->vLeaves, p->pBSet[1]))->Level ); - // cofactor w.r.t. the selected variables - Extra_TruthCopy( p->uCofs[1], p->uTruth, nVars ); - c = 2; - for ( v = 0; v < p->nLutSize; v++ ) - for ( k = 0; k < (1<uCofs[c], p->uCofs[c/2], nVars ); - Extra_TruthCopy( p->uCofs[c+1], p->uCofs[c/2], nVars ); - Extra_TruthCofactor0( p->uCofs[c], nVars, p->pBSet[v] ); - Extra_TruthCofactor1( p->uCofs[c+1], nVars, p->pBSet[v] ); - c += 2; - } - assert( c == (2 << p->nLutSize) ); - // count unique cofactors - nClasses = 0; - nCofs = (1 << p->nLutSize); - for ( i = 0; i < nCofs; i++ ) - { - pTruthCof = p->uCofs[ nCofs + i ]; - for ( k = 0; k < nClasses; k++ ) - { - pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ]; - if ( Extra_TruthIsEqual( pTruthCof, pTruthClass, nVars ) ) - { - pCofClasses[k][ nCofClasses[k]++ ] = i; - break; - } - } - if ( k != nClasses ) - continue; - // not found - pCofClasses[nClasses][0] = i; - nCofClasses[nClasses] = 1; - nClasses++; - if ( nClasses > nCofs/2 ) - return 0; - } - // the number of cofactors is acceptable - nVarsNew = Extra_Base2Log( nClasses ); - assert( nVarsNew < p->nLutSize ); - // create the remainder truth table - // for each class of cofactors, multiply cofactor truth table by its code - Extra_TruthClear( p->uTruth, nVars ); - for ( k = 0; k < nClasses; k++ ) - { - pTruthClass = p->uCofs[ nCofs + pCofClasses[k][0] ]; - for ( v = 0; v < nVarsNew; v++ ) - if ( k & (1 << v) ) - Extra_TruthAnd( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars ); - else - Extra_TruthSharp( pTruthClass, pTruthClass, p->uVars[p->pBSet[v]], nVars ); - Extra_TruthOr( p->uTruth, p->uTruth, pTruthClass, nVars ); - } - // create nodes - pTruth = p->uCofs[0]; - for ( v = 0; v < nVarsNew; v++ ) - { - Extra_TruthClear( pTruth, p->nLutSize ); - for ( k = 0; k < nClasses; k++ ) - if ( k & (1 << v) ) - for ( i = 0; i < nCofClasses[k]; i++ ) - { - pTruthCof = p->uCofs[1]; - Extra_TruthFill( pTruthCof, p->nLutSize ); - for ( w = 0; w < p->nLutSize; w++ ) - if ( pCofClasses[k][i] & (1 << (p->nLutSize-1-w)) ) - Extra_TruthAnd( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize ); - else - Extra_TruthSharp( pTruthCof, pTruthCof, p->uVars[w], p->nLutSize ); - Extra_TruthOr( pTruth, pTruth, pTruthCof, p->nLutSize ); - } - // implement the node - pObjNew = Abc_NtkCreateNode( pNtk ); - for ( i = 0; i < p->nLutSize; i++ ) - { - pFanin = Vec_PtrEntry( p->vLeaves, p->pBSet[i] ); - Abc_ObjAddFanin( pObjNew, pFanin ); - } - // create the function - pObjNew->pData = Abc_SopCreateFromTruth( pNtk->pManFunc, p->nLutSize, pTruth ); // need ISOP - pObjNew->Level = Abc_NodeGetLevel( pObjNew ); - pNodesNew[v] = pObjNew; - } - // put the new nodes back into the list - for ( v = 0; v < nVarsNew; v++ ) - Vec_PtrWriteEntry( p->vLeaves, p->pBSet[v], pNodesNew[v] ); - // compute the variables that should be removed - uPhase = 0; - for ( v = nVarsNew; v < p->nLutSize; v++ ) - uPhase |= (1 << p->pBSet[v]); - // remove entries from the array - Abc_NodeLeavesRemove( p->vLeaves, uPhase, nVars ); - // update truth table - Extra_TruthShrink( p->uCofs[0], p->uTruth, nVars - p->nLutSize + nVarsNew, nVars, ((1 << nVars) - 1) & ~uPhase ); - Extra_TruthCopy( p->uTruth, p->uCofs[0], nVars ); - assert( !Extra_TruthVarInSupport( p->uTruth, nVars, nVars - p->nLutSize + nVarsNew ) ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcMap.c b/src/base/abci/abcMap.c deleted file mode 100644 index d4d50923..00000000 --- a/src/base/abci/abcMap.c +++ /dev/null @@ -1,657 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcMap.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Interface with the SC mapping package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "main.h" -#include "mio.h" -#include "mapper.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ); -static Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk ); -static Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ); -static Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ); -static Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ); - -static Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ); -static void Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ); -static void Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase ); -static Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ); - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Interface with the mapping package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, int fSwitching, int fVerbose ) -{ - int fShowSwitching = 1; - Abc_Ntk_t * pNtkNew; - Map_Man_t * pMan; - Vec_Int_t * vSwitching; - float * pSwitching = NULL; - int clk; - - assert( Abc_NtkIsStrash(pNtk) ); - - // check that the library is available - if ( Abc_FrameReadLibGen() == NULL ) - { - printf( "The current library is not available.\n" ); - return 0; - } - - // derive the supergate library - if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() ) - { - printf( "A simple supergate library is derived from gate library \"%s\".\n", - Mio_LibraryReadName(Abc_FrameReadLibGen()) ); - Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() ); - } - - // print a warning about choice nodes - if ( Abc_NtkGetChoiceNum( pNtk ) ) - printf( "Performing mapping with choices.\n" ); - - // compute switching activity - fShowSwitching |= fSwitching; - if ( fShowSwitching ) - { - extern Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ); - vSwitching = Sim_NtkComputeSwitching( pNtk, 4096 ); - pSwitching = (float *)vSwitching->pArray; - } - - // perform the mapping - pMan = Abc_NtkToMap( pNtk, DelayTarget, fRecovery, pSwitching, fVerbose ); - if ( pSwitching ) Vec_IntFree( vSwitching ); - if ( pMan == NULL ) - return NULL; -clk = clock(); - Map_ManSetSwitching( pMan, fSwitching ); - if ( !Map_Mapping( pMan ) ) - { - Map_ManFree( pMan ); - return NULL; - } -// Map_ManPrintStatsToFile( pNtk->pSpec, Map_ManReadAreaFinal(pMan), Map_ManReadRequiredGlo(pMan), clock()-clk ); - - // reconstruct the network after mapping - pNtkNew = Abc_NtkFromMap( pMan, pNtk ); - if ( pNtkNew == NULL ) - return NULL; - Map_ManFree( pMan ); - - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkMap: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Load the network into manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ) -{ - Map_Man_t * pMan; - ProgressBar * pProgress; - Map_Node_t * pNodeMap; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode, * pFanin, * pPrev; - int i; - - assert( Abc_NtkIsStrash(pNtk) ); - - // start the mapping manager and set its parameters - pMan = Map_ManCreate( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk), Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk), fVerbose ); - if ( pMan == NULL ) - return NULL; - Map_ManSetAreaRecovery( pMan, fRecovery ); - Map_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); - Map_ManSetDelayTarget( pMan, (float)DelayTarget ); - Map_ManSetInputArrivals( pMan, (Map_Time_t *)Abc_NtkGetCiArrivalTimes(pNtk) ); - - // create PIs and remember them in the old nodes - Abc_NtkCleanCopy( pNtk ); - Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan); - Abc_NtkForEachCi( pNtk, pNode, i ) - { - pNodeMap = Map_ManReadInputs(pMan)[i]; - pNode->pCopy = (Abc_Obj_t *)pNodeMap; - if ( pSwitching ) - Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); - } - - // load the AIG into the mapper - vNodes = Abc_AigDfs( pNtk, 0, 0 ); - pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // add the node to the mapper - pNodeMap = Map_NodeAnd( pMan, - Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ), - Map_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ) ); - assert( pNode->pCopy == NULL ); - // remember the node - pNode->pCopy = (Abc_Obj_t *)pNodeMap; - if ( pSwitching ) - Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); - // set up the choice node - if ( Abc_AigNodeIsChoice( pNode ) ) - for ( pPrev = pNode, pFanin = pNode->pData; pFanin; pPrev = pFanin, pFanin = pFanin->pData ) - { - Map_NodeSetNextE( (Map_Node_t *)pPrev->pCopy, (Map_Node_t *)pFanin->pCopy ); - Map_NodeSetRepr( (Map_Node_t *)pFanin->pCopy, (Map_Node_t *)pNode->pCopy ); - } - } - Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vNodes ); - - // set the primary outputs in the required phase - Abc_NtkForEachCo( pNtk, pNode, i ) - Map_ManReadOutputs(pMan)[i] = Map_NotCond( (Map_Node_t *)Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Creates the mapped network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) -{ - ProgressBar * pProgress; - Abc_Ntk_t * pNtkNew; - Map_Node_t * pNodeMap; - Abc_Obj_t * pNode, * pNodeNew; - int i, nDupGates; - // create the new network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP ); - // make the mapper point to the new network - Map_ManCleanData( pMan ); - Abc_NtkForEachCi( pNtk, pNode, i ) - Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy ); - // assign the mapping of the required phase to the POs - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - pNodeMap = Map_ManReadOutputs(pMan)[i]; - pNodeNew = Abc_NodeFromMap_rec( pNtkNew, Map_Regular(pNodeMap), !Map_IsComplement(pNodeMap) ); - assert( !Abc_ObjIsComplement(pNodeNew) ); - Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); - } - Extra_ProgressBarStop( pProgress ); - // decouple the PO driver nodes to reduce the number of levels - nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); -// if ( nDupGates && Map_ManReadVerbose(pMan) ) -// printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Constructs the nodes corrresponding to one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeFromMap_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ) -{ - Abc_Obj_t * pNodeNew, * pNodeInv; - - // check the case of constant node - if ( Map_NodeIsConst(pNodeMap) ) - return fPhase? Abc_NtkCreateNodeConst1(pNtkNew) : Abc_NtkCreateNodeConst0(pNtkNew); - - // check if the phase is already implemented - pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase ); - if ( pNodeNew ) - return pNodeNew; - - // implement the node if the best cut is assigned - if ( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL ) - return Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, fPhase ); - - // if the cut is not assigned, implement the node - assert( Map_NodeReadCutBest(pNodeMap, !fPhase) != NULL || Map_NodeIsConst(pNodeMap) ); - pNodeNew = Abc_NodeFromMapPhase_rec( pNtkNew, pNodeMap, !fPhase ); - - // add the inverter - pNodeInv = Abc_NtkCreateNode( pNtkNew ); - Abc_ObjAddFanin( pNodeInv, pNodeNew ); - pNodeInv->pData = Mio_LibraryReadInv(Map_ManReadGenLib(Map_NodeReadMan(pNodeMap))); - - // set the inverter - Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeInv ); - return pNodeInv; -} - -/**Function************************************************************* - - Synopsis [Constructs the nodes corrresponding to one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeFromMapPhase_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, int fPhase ) -{ - Abc_Obj_t * pNodePIs[10]; - Abc_Obj_t * pNodeNew; - Map_Node_t ** ppLeaves; - Map_Cut_t * pCutBest; - Map_Super_t * pSuperBest; - unsigned uPhaseBest; - int i, fInvPin, nLeaves; - - // make sure the node can be implemented in this phase - assert( Map_NodeReadCutBest(pNodeMap, fPhase) != NULL || Map_NodeIsConst(pNodeMap) ); - // check if the phase is already implemented - pNodeNew = (Abc_Obj_t *)Map_NodeReadData( pNodeMap, fPhase ); - if ( pNodeNew ) - return pNodeNew; - - // get the information about the best cut - pCutBest = Map_NodeReadCutBest( pNodeMap, fPhase ); - pSuperBest = Map_CutReadSuperBest( pCutBest, fPhase ); - uPhaseBest = Map_CutReadPhaseBest( pCutBest, fPhase ); - nLeaves = Map_CutReadLeavesNum( pCutBest ); - ppLeaves = Map_CutReadLeaves( pCutBest ); - - // collect the PI nodes - for ( i = 0; i < nLeaves; i++ ) - { - fInvPin = ((uPhaseBest & (1 << i)) > 0); - pNodePIs[i] = Abc_NodeFromMap_rec( pNtkNew, ppLeaves[i], !fInvPin ); - assert( pNodePIs[i] != NULL ); - } - - // implement the supergate - pNodeNew = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, pSuperBest, pNodePIs, nLeaves ); - Map_NodeSetData( pNodeMap, fPhase, (char *)pNodeNew ); - return pNodeNew; -} - -/**Function************************************************************* - - Synopsis [Constructs the nodes corrresponding to one supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeFromMapSuper_rec( Abc_Ntk_t * pNtkNew, Map_Node_t * pNodeMap, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ) -{ - Mio_Gate_t * pRoot; - Map_Super_t ** ppFanins; - Abc_Obj_t * pNodeNew, * pNodeFanin; - int nFanins, Number, i; - - // get the parameters of the supergate - pRoot = Map_SuperReadRoot(pSuper); - if ( pRoot == NULL ) - { - Number = Map_SuperReadNum(pSuper); - if ( Number < nNodePis ) - { - return pNodePis[Number]; - } - else - { -// assert( 0 ); - /* It might happen that a super gate with 5 inputs is constructed that - * actually depends only on the first four variables; i.e the fifth is a - * don't care -- in that case we connect constant node for the fifth - * (since the cut only has 4 variables). An interesting question is what - * if the first variable (and not the fifth one is the redundant one; - * can that happen?) */ - return Abc_NtkCreateNodeConst0(pNtkNew); - } - } - - // get information about the fanins of the supergate - nFanins = Map_SuperReadFaninNum( pSuper ); - ppFanins = Map_SuperReadFanins( pSuper ); - // create a new node with these fanins - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - for ( i = 0; i < nFanins; i++ ) - { - pNodeFanin = Abc_NodeFromMapSuper_rec( pNtkNew, pNodeMap, ppFanins[i], pNodePis, nNodePis ); - Abc_ObjAddFanin( pNodeNew, pNodeFanin ); - } - pNodeNew->pData = pRoot; - return pNodeNew; -} - - - - - -/**Function************************************************************* - - Synopsis [Interface with the mapping package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - - Map_Man_t * pMan; - - assert( Abc_NtkIsStrash(pNtk) ); - - // check that the library is available - if ( Abc_FrameReadLibGen() == NULL ) - { - printf( "The current library is not available.\n" ); - return 0; - } - - // derive the supergate library - if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() ) - { - printf( "A simple supergate library is derived from gate library \"%s\".\n", - Mio_LibraryReadName(Abc_FrameReadLibGen()) ); - Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() ); - } - - // print a warning about choice nodes - if ( Abc_NtkGetChoiceNum( pNtk ) ) - printf( "Performing mapping with choices.\n" ); - - // perform the mapping - pMan = Abc_NtkToMap( pNtk, -1, 1, NULL, 0 ); - if ( pMan == NULL ) - return NULL; - if ( !Map_Mapping( pMan ) ) - { - Map_ManFree( pMan ); - return NULL; - } - - // reconstruct the network after mapping - pNtkNew = Abc_NtkFromMapSuperChoice( pMan, pNtk ); - if ( pNtkNew == NULL ) - return NULL; - Map_ManFree( pMan ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkMap: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - - -/**Function************************************************************* - - Synopsis [Creates the mapped network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromMapSuperChoice( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) -{ - extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); - ProgressBar * pProgress; - Abc_Ntk_t * pNtkNew, * pNtkNew2; - Abc_Obj_t * pNode; - int i; - - // save the pointer to the mapped nodes - Abc_NtkForEachCi( pNtk, pNode, i ) - pNode->pNext = pNode->pCopy; - Abc_NtkForEachPo( pNtk, pNode, i ) - pNode->pNext = pNode->pCopy; - Abc_NtkForEachNode( pNtk, pNode, i ) - pNode->pNext = pNode->pCopy; - - // duplicate the network - pNtkNew2 = Abc_NtkDup( pNtk ); - pNtkNew = Abc_NtkMulti( pNtkNew2, 0, 20, 0, 0, 1, 0 ); - if ( !Abc_NtkBddToSop( pNtkNew, 0 ) ) - { - printf( "Abc_NtkFromMapSuperChoice(): Converting to SOPs has failed.\n" ); - return NULL; - } - - // set the old network to point to the new network - Abc_NtkForEachCi( pNtk, pNode, i ) - pNode->pCopy = pNode->pCopy->pCopy; - Abc_NtkForEachPo( pNtk, pNode, i ) - pNode->pCopy = pNode->pCopy->pCopy; - Abc_NtkForEachNode( pNtk, pNode, i ) - pNode->pCopy = pNode->pCopy->pCopy; - Abc_NtkDelete( pNtkNew2 ); - - // set the pointers from the mapper to the new nodes - Abc_NtkForEachCi( pNtk, pNode, i ) - { - Map_NodeSetData( Map_ManReadInputs(pMan)[i], 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) ); - Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy ); - } - Abc_NtkForEachNode( pNtk, pNode, i ) - { -// if ( Abc_NodeIsConst(pNode) ) -// continue; - Map_NodeSetData( (Map_Node_t *)pNode->pNext, 0, (char *)Abc_NtkCreateNodeInv(pNtkNew,pNode->pCopy) ); - Map_NodeSetData( (Map_Node_t *)pNode->pNext, 1, (char *)pNode->pCopy ); - } - - // assign the mapping of the required phase to the POs - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); -// if ( Abc_NodeIsConst(pNode) ) -// continue; - Abc_NodeSuperChoice( pNtkNew, pNode ); - } - Extra_ProgressBarStop( pProgress ); - return pNtkNew; -} - - -/**Function************************************************************* - - Synopsis [Creates the mapped network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeSuperChoice( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) -{ - Map_Node_t * pMapNode = (Map_Node_t *)pNode->pNext; - Map_Cut_t * pCuts, * pTemp; - - pCuts = Map_NodeReadCuts(pMapNode); - for ( pTemp = Map_CutReadNext(pCuts); pTemp; pTemp = Map_CutReadNext(pTemp) ) - { - Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 0 ); - Abc_NodeFromMapCutPhase( pNtkNew, pTemp, 1 ); - } -} - - -/**Function************************************************************* - - Synopsis [Constructs the nodes corrresponding to one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeFromMapCutPhase( Abc_Ntk_t * pNtkNew, Map_Cut_t * pCut, int fPhase ) -{ - Abc_Obj_t * pNodePIs[10]; - Map_Node_t ** ppLeaves; - Map_Super_t * pSuperBest; - unsigned uPhaseBest; - int i, fInvPin, nLeaves; - - pSuperBest = Map_CutReadSuperBest( pCut, fPhase ); - if ( pSuperBest == NULL ) - return; - - // get the information about the best cut - uPhaseBest = Map_CutReadPhaseBest( pCut, fPhase ); - nLeaves = Map_CutReadLeavesNum( pCut ); - ppLeaves = Map_CutReadLeaves( pCut ); - - // collect the PI nodes - for ( i = 0; i < nLeaves; i++ ) - { - fInvPin = ((uPhaseBest & (1 << i)) > 0); - pNodePIs[i] = (Abc_Obj_t *)Map_NodeReadData( ppLeaves[i], !fInvPin ); - assert( pNodePIs[i] != NULL ); - } - - // implement the supergate - Abc_NodeFromMapSuperChoice_rec( pNtkNew, pSuperBest, pNodePIs, nLeaves ); -} - - -/**Function************************************************************* - - Synopsis [Constructs the nodes corrresponding to one supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeFromMapSuperChoice_rec( Abc_Ntk_t * pNtkNew, Map_Super_t * pSuper, Abc_Obj_t * pNodePis[], int nNodePis ) -{ - Mio_Gate_t * pRoot; - Map_Super_t ** ppFanins; - Abc_Obj_t * pNodeNew, * pNodeFanin; - int nFanins, Number, i; - - // get the parameters of the supergate - pRoot = Map_SuperReadRoot(pSuper); - if ( pRoot == NULL ) - { - Number = Map_SuperReadNum(pSuper); - if ( Number < nNodePis ) - { - return pNodePis[Number]; - } - else - { -// assert( 0 ); - /* It might happen that a super gate with 5 inputs is constructed that - * actually depends only on the first four variables; i.e the fifth is a - * don't care -- in that case we connect constant node for the fifth - * (since the cut only has 4 variables). An interesting question is what - * if the first variable (and not the fifth one is the redundant one; - * can that happen?) */ - return Abc_NtkCreateNodeConst0(pNtkNew); - } - } - - // get information about the fanins of the supergate - nFanins = Map_SuperReadFaninNum( pSuper ); - ppFanins = Map_SuperReadFanins( pSuper ); - // create a new node with these fanins - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - for ( i = 0; i < nFanins; i++ ) - { - pNodeFanin = Abc_NodeFromMapSuperChoice_rec( pNtkNew, ppFanins[i], pNodePis, nNodePis ); - Abc_ObjAddFanin( pNodeNew, pNodeFanin ); - } - pNodeNew->pData = Abc_SopRegister( pNtkNew->pManFunc, Mio_GateReadSop(pRoot) ); - return pNodeNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcMeasure.c b/src/base/abci/abcMeasure.c deleted file mode 100644 index 6604a0c4..00000000 --- a/src/base/abci/abcMeasure.c +++ /dev/null @@ -1,478 +0,0 @@ -/**CFile**************************************************************** - - FileName [abc_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintMeasures( unsigned * pTruth, int nVars ) -{ - unsigned uCofs[10][32]; - int i, k, nOnes; - - // total pairs - nOnes = Kit_TruthCountOnes( uCofs[0], nVars ); - printf( "Total = %d.\n", nOnes * ((1 << nVars) - nOnes) ); - - // print measures for individual variables - for ( i = 0; i < nVars; i++ ) - { - Kit_TruthUniqueNew( uCofs[0], pTruth, nVars, i ); - nOnes = Kit_TruthCountOnes( uCofs[0], nVars ); - printf( "%7d ", nOnes ); - } - printf( "\n" ); - - // consider pairs - for ( i = 0; i < nVars; i++ ) - for ( k = 0; k < nVars; k++ ) - { - if ( i == k ) - { - printf( " " ); - continue; - } - Kit_TruthCofactor0New( uCofs[0], pTruth, nVars, i ); - Kit_TruthCofactor1New( uCofs[1], pTruth, nVars, i ); - - Kit_TruthCofactor0New( uCofs[2], uCofs[0], nVars, k ); // 00 - Kit_TruthCofactor1New( uCofs[3], uCofs[0], nVars, k ); // 01 - Kit_TruthCofactor0New( uCofs[4], uCofs[1], nVars, k ); // 10 - Kit_TruthCofactor1New( uCofs[5], uCofs[1], nVars, k ); // 11 - - Kit_TruthAndPhase( uCofs[6], uCofs[2], uCofs[5], nVars, 0, 1 ); // 00 & 11' - Kit_TruthAndPhase( uCofs[7], uCofs[2], uCofs[5], nVars, 1, 0 ); // 00' & 11 - Kit_TruthAndPhase( uCofs[8], uCofs[3], uCofs[4], nVars, 0, 1 ); // 01 & 10' - Kit_TruthAndPhase( uCofs[9], uCofs[3], uCofs[4], nVars, 1, 0 ); // 01' & 10 - - nOnes = Kit_TruthCountOnes( uCofs[6], nVars ) + - Kit_TruthCountOnes( uCofs[7], nVars ) + - Kit_TruthCountOnes( uCofs[8], nVars ) + - Kit_TruthCountOnes( uCofs[9], nVars ); - - printf( "%7d ", nOnes ); - if ( k == nVars - 1 ) - printf( "\n" ); - } - printf( "\n" ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_Ntk4VarObjPrint_rec( Abc_Obj_t * pObj ) -{ - if ( pObj == Abc_AigConst1(pObj->pNtk) ) - { - printf( "1" ); - return; - } - if ( Abc_ObjIsPi(pObj) ) - { - printf( "%c", pObj->Id - 1 + 'a' ); - return; - } - - printf( "(" ); - Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) ); - if ( Abc_ObjFaninC0(pObj) ) - printf( "\'" ); - Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin1(pObj) ); - if ( Abc_ObjFaninC1(pObj) ) - printf( "\'" ); - printf( ")" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Abc_Ntk4VarObj( Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pObj; - unsigned uTruth0, uTruth1; - int i; - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - uTruth0 = (unsigned)(Abc_ObjFanin0(pObj)->pCopy); - uTruth1 = (unsigned)(Abc_ObjFanin1(pObj)->pCopy); - if ( Abc_ObjFaninC0(pObj) ) - uTruth0 = ~uTruth0; - if ( Abc_ObjFaninC1(pObj) ) - uTruth1 = ~uTruth1; - pObj->pCopy = (void *)(uTruth0 & uTruth1); - } - return uTruth0 & uTruth1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_Ntk4VarTable( Abc_Ntk_t * pNtk ) -{ - static unsigned u4VarTruths[4] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00 }; - static unsigned u4VarTts[222] = { - 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, - 0x001b, 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, - 0x007f, 0x00ff, 0x0116, 0x0117, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, - 0x012c, 0x012d, 0x012f, 0x013c, 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016a, - 0x016b, 0x016e, 0x016f, 0x017e, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, 0x0186, - 0x0187, 0x0189, 0x018b, 0x018f, 0x0196, 0x0197, 0x0198, 0x0199, 0x019a, 0x019b, - 0x019e, 0x019f, 0x01a8, 0x01a9, 0x01aa, 0x01ab, 0x01ac, 0x01ad, 0x01ae, 0x01af, - 0x01bc, 0x01bd, 0x01be, 0x01bf, 0x01e8, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, - 0x01fe, 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, - 0x035e, 0x035f, 0x0368, 0x0369, 0x036a, 0x036b, 0x036c, 0x036d, 0x036e, 0x036f, - 0x037c, 0x037d, 0x037e, 0x03c0, 0x03c1, 0x03c3, 0x03c5, 0x03c6, 0x03c7, 0x03cf, - 0x03d4, 0x03d5, 0x03d6, 0x03d7, 0x03d8, 0x03d9, 0x03db, 0x03dc, 0x03dd, 0x03de, - 0x03fc, 0x0660, 0x0661, 0x0662, 0x0663, 0x0666, 0x0667, 0x0669, 0x066b, 0x066f, - 0x0672, 0x0673, 0x0676, 0x0678, 0x0679, 0x067a, 0x067b, 0x067e, 0x0690, 0x0691, - 0x0693, 0x0696, 0x0697, 0x069f, 0x06b0, 0x06b1, 0x06b2, 0x06b3, 0x06b4, 0x06b5, - 0x06b6, 0x06b7, 0x06b9, 0x06bd, 0x06f0, 0x06f1, 0x06f2, 0x06f6, 0x06f9, 0x0776, - 0x0778, 0x0779, 0x077a, 0x077e, 0x07b0, 0x07b1, 0x07b4, 0x07b5, 0x07b6, 0x07bc, - 0x07e0, 0x07e1, 0x07e2, 0x07e3, 0x07e6, 0x07e9, 0x07f0, 0x07f1, 0x07f2, 0x07f8, - 0x0ff0, 0x1668, 0x1669, 0x166a, 0x166b, 0x166e, 0x167e, 0x1681, 0x1683, 0x1686, - 0x1687, 0x1689, 0x168b, 0x168e, 0x1696, 0x1697, 0x1698, 0x1699, 0x169a, 0x169b, - 0x169e, 0x16a9, 0x16ac, 0x16ad, 0x16bc, 0x16e9, 0x177e, 0x178e, 0x1796, 0x1798, - 0x179a, 0x17ac, 0x17e8, 0x18e7, 0x19e1, 0x19e3, 0x19e6, 0x1bd8, 0x1be4, 0x1ee1, - 0x3cc3, 0x6996 - }; - int Counters[222] = {0}; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - unsigned uTruth; - int i, k, Count = 0; - - unsigned short * puCanons = NULL; - unsigned char * puMap = NULL; - Extra_Truth4VarNPN( &puCanons, NULL, NULL, &puMap ); - - // set elementary truth tables - assert( Abc_NtkPiNum(pNtk) == 4 ); - Abc_AigConst1(pNtk)->pCopy = (void *)0xFFFFFFFF; - Abc_NtkForEachPi( pNtk, pObj, i ) - pObj->pCopy = (void *)u4VarTruths[i]; - - // create truth tables - Abc_NtkForEachPo( pNtk, pObj, i ) - { - vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); - if ( Vec_PtrSize(vNodes) == 0 ) - uTruth = (unsigned)Abc_ObjFanin0(pObj)->pCopy; - else - uTruth = Abc_Ntk4VarObj( vNodes ); - - if ( (uTruth & 0xFFFF) < (~uTruth & 0xFFFF) ) - uTruth = uTruth & 0xFFFF; - else - uTruth = ~uTruth & 0xFFFF; - - for ( k = 0; k < 222; k++ ) - if ( u4VarTts[k] == uTruth ) - break; - if ( k == 222 ) - continue; -/* -// if ( uTruth == 1725 ) - if ( k == 96 ) - { - printf( "%d : ", Vec_PtrSize(vNodes) ); - Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) ); - printf( "\n" ); - } -*/ - Counters[k]++; - -// Counters[ puMap[uTruth & 0xFFFF] ]++; - Vec_PtrFree( vNodes ); - } - free( puCanons ); - free( puMap ); - - Count = 0; - for ( k = 0; k < 222; k++ ) - { - printf( "%d/%x/%d ", k, u4VarTts[k], Counters[k] ); - Count += Counters[k]; - } - printf( " Total = %d\n", Count ); -} - - - - -/**Function************************************************************* - - Synopsis [Returns 1 if there are no more than 2 unique cofactors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkPrintOneDecompCheckCofList( unsigned * uCofs, int nCofs ) -{ - int i, Ind = -1; - assert( nCofs > 2 ); - for ( i = 1; i < nCofs; i++ ) - { - if ( uCofs[i] == uCofs[0] ) - continue; - if ( Ind == -1 ) - { - Ind = i; - continue; - } - if ( uCofs[i] == uCofs[Ind] ) - continue; - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks all cofactors with the given mask.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkPrintOneDecompCheck( unsigned * uCofs, int nCofs, unsigned uMask ) -{ - unsigned pCofs[32][32]; - int nCofNums[32] = {0}; - int uMasks[32]; - int nGroups = 0; - int i, k; - for ( i = 0; i < nCofs; i++ ) - { - // find group of this cof - for ( k = 0; k < nGroups; k++ ) - if ( (int)(i & uMask) == uMasks[k] ) - break; - if ( k == nGroups ) - { - uMasks[k] = (i & uMask); - nGroups++; - } - // save cof in the group - pCofs[k][ nCofNums[k]++ ] = uCofs[i]; - assert( nCofNums[k] <= 32 ); - assert( nGroups <= 32 ); - } - // check the groups - for ( i = 0; i < nGroups; i++ ) - if ( !Abc_NtkPrintOneDecompCheckCofList(pCofs[i], nCofNums[i]) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintOneDecomp_rec( unsigned * uCofs, int nCofs, int nVars, unsigned uMask, int * pBestSize, unsigned * puBestMask ) -{ - unsigned uMaskNew; - int v, last, Counter = 0; - // find the last variable in the mask - for ( v = 0; v < nVars; v++ ) - if ( uMask & (1< 3 ) - return; - // try adding one variable after the last - for ( v = last + 1; v < nVars; v++ ) - { - uMaskNew = uMask | (1 << v); - if ( !Abc_NtkPrintOneDecompCheck( uCofs, nCofs, uMaskNew ) ) - continue; - if ( *pBestSize < Counter + 1 ) - { - *pBestSize = Counter + 1; - *puBestMask = uMaskNew; - } - // try other masks - Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, uMaskNew, pBestSize, puBestMask ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintOneDecomp( unsigned * pTruth, int nVars ) -{ - int BoundSet = 6; - unsigned uCofs[64], uMask, uBestMask = 0; - int i, nCofs, nMints, nMintShift, BestSize = 1; - - assert( nVars > BoundSet ); - assert( nVars <= BoundSet + 5 ); // at most 5 variable cofactors - - // collect the cofactors - nCofs = (1 << BoundSet); - nMints = (1 << (nVars-BoundSet)); - nMintShift = 0; - uMask = Kit_CubeMask( nMints ); - for ( i = 0; i < nCofs; i++ ) - { - uCofs[i] = (pTruth[nMintShift/32] >> (nMintShift % 32)) & uMask; - nMintShift += nMints; - } - - // try removing variables - for ( i = 0; i < BoundSet; i++ ) - Abc_NtkPrintOneDecomp_rec( uCofs, nCofs, nVars, (1 << i), &BestSize, &uBestMask ); - - printf( "Best size = %d ", BestSize ); - printf( "Best mask = " ); - Extra_PrintBinary( stdout, &uBestMask, nVars ); - printf( "\n" ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintOneDec( unsigned * pTruth, int nVars ) -{ - unsigned uCof[(1<<11)], * pOut = uCof, * pIn = pTruth, * pTemp; - int nDiffs[16]; - int Order[16]; - int i, fChange, Temp, Counter; - - // find the ordering - for ( i = 0; i < nVars; i++ ) - { - Kit_TruthUniqueNew( uCof, pTruth, nVars, i ); - nDiffs[i] = Kit_TruthCountOnes( uCof, nVars ); - Order[i] = i; - } - - // permute truth table to least active variable first - Counter = 0; - do { - fChange = 0; - for ( i = 0; i < nVars-1; i++ ) - { - if ( nDiffs[i] <= nDiffs[i+1] ) - continue; - fChange = 1; - Counter++; - - Temp = nDiffs[i]; - nDiffs[i] = nDiffs[i+1]; - nDiffs[i+1] = Temp; - - Temp = Order[i]; - Order[i] = Order[i+1]; - Order[i+1] = Temp; - - Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - } - } while ( fChange ); - - // swap if it was moved an even number of times - if ( Counter & 1 ) - Extra_TruthCopy( pOut, pIn, nVars ); - - // call the decomposition - Abc_NtkPrintOneDecomp( pTruth, nVars ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcMini.c b/src/base/abci/abcMini.c deleted file mode 100644 index 92985423..00000000 --- a/src/base/abci/abcMini.c +++ /dev/null @@ -1,153 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcMini.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Interface to the minimalistic AIG package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcMini.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk ); -static Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtkOld, Hop_Man_t * pMan ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Gives the current ABC network to AIG manager for processing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiniBalance( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkAig; - Hop_Man_t * pMan, * pTemp; - assert( Abc_NtkIsStrash(pNtk) ); - // convert to the AIG manager - pMan = Abc_NtkToMini( pNtk ); - if ( pMan == NULL ) - return NULL; - if ( !Hop_ManCheck( pMan ) ) - { - printf( "AIG check has failed.\n" ); - Hop_ManStop( pMan ); - return NULL; - } - // perform balance - Hop_ManPrintStats( pMan ); -// Hop_ManDumpBlif( pMan, "aig_temp.blif" ); - pMan = Hop_ManBalance( pTemp = pMan, 1 ); - Hop_ManStop( pTemp ); - Hop_ManPrintStats( pMan ); - // convert from the AIG manager - pNtkAig = Abc_NtkFromMini( pNtk, pMan ); - if ( pNtkAig == NULL ) - return NULL; - Hop_ManStop( pMan ); - // make sure everything is okay - if ( !Abc_NtkCheck( pNtkAig ) ) - { - printf( "Abc_NtkStrash: The network check has failed.\n" ); - Abc_NtkDelete( pNtkAig ); - return NULL; - } - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Converts the network from the AIG manager into ABC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk ) -{ - Hop_Man_t * pMan; - Abc_Obj_t * pObj; - int i; - // create the manager - pMan = Hop_ManStart(); - // transfer the pointers to the basic nodes - Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Hop_ManConst1(pMan); - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)Hop_ObjCreatePi(pMan); - // perform the conversion of the internal nodes (assumes DFS ordering) - Abc_NtkForEachNode( pNtk, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)Hop_And( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj), (Hop_Obj_t *)Abc_ObjChild1Copy(pObj) ); - // create the POs - Abc_NtkForEachCo( pNtk, pObj, i ) - Hop_ObjCreatePo( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj) ); - Hop_ManCleanup( pMan ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Converts the network from the AIG manager into ABC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ) -{ - Vec_Ptr_t * vNodes; - Abc_Ntk_t * pNtkNew; - Hop_Obj_t * pObj; - int i; - // perform strashing - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // transfer the pointers to the basic nodes - Hop_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); - Hop_ManForEachPi( pMan, pObj, i ) - pObj->pData = Abc_NtkCi(pNtkNew, i); - // rebuild the AIG - vNodes = Hop_ManDfs( pMan ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pData = Abc_AigAnd( pNtkNew->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); - Vec_PtrFree( vNodes ); - // connect the PO nodes - Hop_ManForEachPo( pMan, pObj, i ) - Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Hop_ObjChild0Copy(pObj) ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkFromMini(): Network check has failed.\n" ); - return pNtkNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcMiter.c b/src/base/abci/abcMiter.c deleted file mode 100644 index adda6653..00000000 --- a/src/base/abci/abcMiter.c +++ /dev/null @@ -1,1138 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcMiter.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures to derive the miter of two circuits.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcMiter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ); -static void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ); -static void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ); -static void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ); -static void Abc_NtkAddFrame( Abc_Ntk_t * pNetNew, Abc_Ntk_t * pNet, int iFrame ); - -// to be exported -typedef void (*AddFrameMapping)( Abc_Obj_t*, Abc_Obj_t*, int, void*); -extern Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg ); -static void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the miter of two networks.] - - Description [Preprocesses the networks to make sure that they are strashed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ) -{ - Abc_Ntk_t * pTemp = NULL; - int fRemove1, fRemove2; - assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); - assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); - // check that the networks have the same PIs/POs/latches - if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 0, fComb ) ) - return NULL; - // make sure the circuits are strashed - fRemove1 = (!Abc_NtkIsStrash(pNtk1)) && (pNtk1 = Abc_NtkStrash(pNtk1, 0, 0, 0)); - fRemove2 = (!Abc_NtkIsStrash(pNtk2)) && (pNtk2 = Abc_NtkStrash(pNtk2, 0, 0, 0)); - if ( pNtk1 && pNtk2 ) - pTemp = Abc_NtkMiterInt( pNtk1, pNtk2, fComb, nPartSize ); - if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); - if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); - return pTemp; -} - -/**Function************************************************************* - - Synopsis [Derives the miter of two sequential networks.] - - Description [Assumes that the networks are strashed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiterInt( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize ) -{ - char Buffer[1000]; - Abc_Ntk_t * pNtkMiter; - - assert( Abc_NtkIsStrash(pNtk1) ); - assert( Abc_NtkIsStrash(pNtk2) ); - - // start the new network - pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); - pNtkMiter->pName = Extra_UtilStrsav(Buffer); - - // perform strashing - Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); - Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); - Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); - Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, fComb, nPartSize ); - Abc_AigCleanup(pNtkMiter->pManFunc); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkMiter ) ) - { - printf( "Abc_NtkMiter: The network check has failed.\n" ); - Abc_NtkDelete( pNtkMiter ); - return NULL; - } - return pNtkMiter; -} - -/**Function************************************************************* - - Synopsis [Prepares the network for mitering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ) -{ - Abc_Obj_t * pObj, * pObjNew; - int i; - // clean the copy field in all objects -// Abc_NtkCleanCopy( pNtk1 ); -// Abc_NtkCleanCopy( pNtk2 ); - Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter); - Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter); - - if ( fComb ) - { - // create new PIs and remember them in the old PIs - Abc_NtkForEachCi( pNtk1, pObj, i ) - { - pObjNew = Abc_NtkCreatePi( pNtkMiter ); - // remember this PI in the old PIs - pObj->pCopy = pObjNew; - pObj = Abc_NtkCi(pNtk2, i); - pObj->pCopy = pObjNew; - // add name - Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); - } - if ( nPartSize <= 0 ) - { - // create the only PO - pObjNew = Abc_NtkCreatePo( pNtkMiter ); - // add the PO name - Abc_ObjAssignName( pObjNew, "miter", NULL ); - } - } - else - { - // create new PIs and remember them in the old PIs - Abc_NtkForEachPi( pNtk1, pObj, i ) - { - pObjNew = Abc_NtkCreatePi( pNtkMiter ); - // remember this PI in the old PIs - pObj->pCopy = pObjNew; - pObj = Abc_NtkPi(pNtk2, i); - pObj->pCopy = pObjNew; - // add name - Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); - } - if ( nPartSize <= 0 ) - { - // create the only PO - pObjNew = Abc_NtkCreatePo( pNtkMiter ); - // add the PO name - Abc_ObjAssignName( pObjNew, "miter", NULL ); - } - // create the latches - Abc_NtkForEachLatch( pNtk1, pObj, i ) - { - pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 ); - // add names - Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_1" ); - Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_1" ); - Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_1" ); - } - Abc_NtkForEachLatch( pNtk2, pObj, i ) - { - pObjNew = Abc_NtkDupBox( pNtkMiter, pObj, 0 ); - // add name - Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), "_2" ); - Abc_ObjAssignName( Abc_ObjFanin0(pObjNew), Abc_ObjName(Abc_ObjFanin0(pObj)), "_2" ); - Abc_ObjAssignName( Abc_ObjFanout0(pObjNew), Abc_ObjName(Abc_ObjFanout0(pObj)), "_2" ); - } - } -} - -/**Function************************************************************* - - Synopsis [Performs mitering for one network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMiterAddOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter ) -{ - Abc_Obj_t * pNode; - int i; - assert( Abc_NtkIsDfsOrdered(pNtk) ); - Abc_AigForEachAnd( pNtk, pNode, i ) - pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); -} - -/**Function************************************************************* - - Synopsis [Performs mitering for one network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pRoot ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode; - int i; - // map the constant nodes - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkMiter); - // perform strashing - vNodes = Abc_NtkDfsNodes( pNtk, &pRoot, 1 ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - if ( Abc_AigNodeIsAnd(pNode) ) - pNode->pCopy = Abc_AigAnd( pNtkMiter->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); - Vec_PtrFree( vNodes ); -} - - -/**Function************************************************************* - - Synopsis [Finalizes the miter by adding the output part.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMiterFinalize( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize ) -{ - Vec_Ptr_t * vPairs; - Abc_Obj_t * pMiter, * pNode; - int i; - // collect the PO pairs from both networks - vPairs = Vec_PtrAlloc( 100 ); - if ( fComb ) - { - // collect the CO nodes for the miter - Abc_NtkForEachCo( pNtk1, pNode, i ) - { - Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); - pNode = Abc_NtkCo( pNtk2, i ); - Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); - } - } - else - { - // collect the PO nodes for the miter - Abc_NtkForEachPo( pNtk1, pNode, i ) - { - Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); - pNode = Abc_NtkPo( pNtk2, i ); - Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pNode) ); - } - // connect new latches - Abc_NtkForEachLatch( pNtk1, pNode, i ) - Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); - Abc_NtkForEachLatch( pNtk2, pNode, i ) - Abc_ObjAddFanin( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjChild0Copy(Abc_ObjFanin0(pNode)) ); - } - // add the miter - if ( nPartSize <= 0 ) - { - pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairs ); - Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); - Vec_PtrFree( vPairs ); - } - else - { - char Buffer[1024]; - Vec_Ptr_t * vPairsPart; - int nParts, i, k, iCur; - assert( Vec_PtrSize(vPairs) == 2 * Abc_NtkCoNum(pNtk1) ); - // create partitions - nParts = Abc_NtkCoNum(pNtk1) / nPartSize + (int)((Abc_NtkCoNum(pNtk1) % nPartSize) > 0); - vPairsPart = Vec_PtrAlloc( nPartSize ); - for ( i = 0; i < nParts; i++ ) - { - Vec_PtrClear( vPairsPart ); - for ( k = 0; k < nPartSize; k++ ) - { - iCur = i * nPartSize + k; - if ( iCur >= Abc_NtkCoNum(pNtk1) ) - break; - Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur ) ); - Vec_PtrPush( vPairsPart, Vec_PtrEntry(vPairs, 2*iCur+1) ); - } - pMiter = Abc_AigMiter( pNtkMiter->pManFunc, vPairsPart ); - pNode = Abc_NtkCreatePo( pNtkMiter ); - Abc_ObjAddFanin( pNode, pMiter ); - // assign the name to the node - if ( nPartSize == 1 ) - sprintf( Buffer, "%s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) ); - else - sprintf( Buffer, "%d", i ); - Abc_ObjAssignName( pNode, "miter_", Buffer ); - } - Vec_PtrFree( vPairsPart ); - Vec_PtrFree( vPairs ); - } -} - - - -/**Function************************************************************* - - Synopsis [Derives the AND of two miters.] - - Description [The network should have the same names of PIs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 ) -{ - char Buffer[1000]; - Abc_Ntk_t * pNtkMiter; - Abc_Obj_t * pOutput1, * pOutput2; - Abc_Obj_t * pRoot1, * pRoot2, * pMiter; - - assert( Abc_NtkIsStrash(pNtk1) ); - assert( Abc_NtkIsStrash(pNtk2) ); - assert( 1 == Abc_NtkCoNum(pNtk1) ); - assert( 1 == Abc_NtkCoNum(pNtk2) ); - assert( 0 == Abc_NtkLatchNum(pNtk1) ); - assert( 0 == Abc_NtkLatchNum(pNtk2) ); - assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); - assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); - assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); - - // start the new network - pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); -// sprintf( Buffer, "%s_%s_miter", pNtk1->pName, pNtk2->pName ); - sprintf( Buffer, "product" ); - pNtkMiter->pName = Extra_UtilStrsav(Buffer); - - // perform strashing - Abc_NtkMiterPrepare( pNtk1, pNtk2, pNtkMiter, 1, -1 ); - Abc_NtkMiterAddOne( pNtk1, pNtkMiter ); - Abc_NtkMiterAddOne( pNtk2, pNtkMiter ); -// Abc_NtkMiterFinalize( pNtk1, pNtk2, pNtkMiter, 1 ); - pRoot1 = Abc_NtkPo(pNtk1,0); - pRoot2 = Abc_NtkPo(pNtk2,0); - pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot1)->pCopy, Abc_ObjFaninC0(pRoot1) ); - pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot2)->pCopy, Abc_ObjFaninC0(pRoot2) ^ fCompl2 ); - - // create the miter of the two outputs - if ( fOr ) - pMiter = Abc_AigOr( pNtkMiter->pManFunc, pOutput1, pOutput2 ); - else - pMiter = Abc_AigAnd( pNtkMiter->pManFunc, pOutput1, pOutput2 ); - Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkMiter ) ) - { - printf( "Abc_NtkMiterAnd: The network check has failed.\n" ); - Abc_NtkDelete( pNtkMiter ); - return NULL; - } - return pNtkMiter; -} - - -/**Function************************************************************* - - Synopsis [Derives the cofactor of the miter w.r.t. the set of vars.] - - Description [The array of variable values contains -1/0/1 for each PI. - -1 means this PI remains, 0/1 means this PI is set to 0/1.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) -{ - char Buffer[1000]; - Abc_Ntk_t * pNtkMiter; - Abc_Obj_t * pRoot, * pOutput1; - int Value, i; - - assert( Abc_NtkIsStrash(pNtk) ); - assert( 1 == Abc_NtkCoNum(pNtk) ); - assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); - - // start the new network - pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - sprintf( Buffer, "%s_miter", pNtk->pName ); - pNtkMiter->pName = Extra_UtilStrsav(Buffer); - - // get the root output - pRoot = Abc_NtkCo( pNtk, 0 ); - - // perform strashing - Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 ); - // set the first cofactor - Vec_IntForEachEntry( vPiValues, Value, i ) - { - if ( Value == -1 ) - continue; - if ( Value == 0 ) - { - Abc_NtkCi(pNtk, i)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); - continue; - } - if ( Value == 1 ) - { - Abc_NtkCi(pNtk, i)->pCopy = Abc_AigConst1(pNtkMiter); - continue; - } - assert( 0 ); - } - // add the first cofactor - Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); - - // save the output - pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); - - // create the miter of the two outputs - Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pOutput1 ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkMiter ) ) - { - printf( "Abc_NtkMiterCofactor: The network check has failed.\n" ); - Abc_NtkDelete( pNtkMiter ); - return NULL; - } - return pNtkMiter; -} -/**Function************************************************************* - - Synopsis [Derives the miter of two cofactors of one output.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ) -{ - char Buffer[1000]; - Abc_Ntk_t * pNtkMiter; - Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter; - - assert( Abc_NtkIsStrash(pNtk) ); - assert( Out < Abc_NtkCoNum(pNtk) ); - assert( In1 < Abc_NtkCiNum(pNtk) ); - assert( In2 < Abc_NtkCiNum(pNtk) ); - assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); - - // start the new network - pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - sprintf( Buffer, "%s_miter", Abc_ObjName(Abc_NtkCo(pNtk, Out)) ); - pNtkMiter->pName = Extra_UtilStrsav(Buffer); - - // get the root output - pRoot = Abc_NtkCo( pNtk, Out ); - - // perform strashing - Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 ); - // set the first cofactor - Abc_NtkCi(pNtk, In1)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); - if ( In2 >= 0 ) - Abc_NtkCi(pNtk, In2)->pCopy = Abc_AigConst1(pNtkMiter); - // add the first cofactor - Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); - - // save the output - pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; - - // set the second cofactor - Abc_NtkCi(pNtk, In1)->pCopy = Abc_AigConst1(pNtkMiter); - if ( In2 >= 0 ) - Abc_NtkCi(pNtk, In2)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); - // add the second cofactor - Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); - - // save the output - pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; - - // create the miter of the two outputs - pMiter = Abc_AigXor( pNtkMiter->pManFunc, pOutput1, pOutput2 ); - Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkMiter ) ) - { - printf( "Abc_NtkMiter: The network check has failed.\n" ); - Abc_NtkDelete( pNtkMiter ); - return NULL; - } - return pNtkMiter; -} - - -/**Function************************************************************* - - Synopsis [Derives the miter of two cofactors of one output.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ) -{ - Abc_Ntk_t * pNtkMiter; - Abc_Obj_t * pRoot, * pOutput1, * pOutput2, * pMiter; - - assert( Abc_NtkIsStrash(pNtk) ); - assert( 1 == Abc_NtkCoNum(pNtk) ); - assert( In < Abc_NtkCiNum(pNtk) ); - assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); - - // start the new network - pNtkMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - pNtkMiter->pName = Extra_UtilStrsav( Abc_ObjName(Abc_NtkCo(pNtk, 0)) ); - - // get the root output - pRoot = Abc_NtkCo( pNtk, 0 ); - - // perform strashing - Abc_NtkMiterPrepare( pNtk, pNtk, pNtkMiter, 1, -1 ); - // set the first cofactor - Abc_NtkCi(pNtk, In)->pCopy = Abc_ObjNot( Abc_AigConst1(pNtkMiter) ); - // add the first cofactor - Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); - // save the output -// pOutput1 = Abc_ObjFanin0(pRoot)->pCopy; - pOutput1 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); - - // set the second cofactor - Abc_NtkCi(pNtk, In)->pCopy = Abc_AigConst1(pNtkMiter); - // add the second cofactor - Abc_NtkMiterAddCone( pNtk, pNtkMiter, pRoot ); - // save the output -// pOutput2 = Abc_ObjFanin0(pRoot)->pCopy; - pOutput2 = Abc_ObjNotCond( Abc_ObjFanin0(pRoot)->pCopy, Abc_ObjFaninC0(pRoot) ); - - // create the miter of the two outputs - if ( fExist ) - pMiter = Abc_AigOr( pNtkMiter->pManFunc, pOutput1, pOutput2 ); - else - pMiter = Abc_AigAnd( pNtkMiter->pManFunc, pOutput1, pOutput2 ); - Abc_ObjAddFanin( Abc_NtkPo(pNtkMiter,0), pMiter ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkMiter ) ) - { - printf( "Abc_NtkMiter: The network check has failed.\n" ); - Abc_NtkDelete( pNtkMiter ); - return NULL; - } - return pNtkMiter; -} - -/**Function************************************************************* - - Synopsis [Quantifies all the PIs existentially from the only PO of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkTemp; - Abc_Obj_t * pObj; - int i; - assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); - - Abc_NtkForEachPi( pNtk, pObj, i ) - { - if ( Abc_ObjFanoutNum(pObj) == 0 ) - continue; - pNtk = Abc_NtkMiterQuantify( pNtkTemp = pNtk, i, 1 ); - Abc_NtkDelete( pNtkTemp ); - } - - return pNtk; -} - - - - -/**Function************************************************************* - - Synopsis [Checks the status of the miter.] - - Description [Return 0 if the miter is sat for at least one output. - Return 1 if the miter is unsat for all its outputs. Returns -1 if the - miter is undecided for some outputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ) -{ - Abc_Obj_t * pNodePo, * pChild; - int i; - assert( Abc_NtkIsStrash(pMiter) ); - Abc_NtkForEachPo( pMiter, pNodePo, i ) - { - pChild = Abc_ObjChild0( pNodePo ); - if ( Abc_AigNodeIsConst(pChild) ) - { - assert( Abc_ObjRegular(pChild) == Abc_AigConst1(pMiter) ); - if ( !Abc_ObjIsComplement(pChild) ) - { - // if the miter is constant 1, return immediately -// printf( "MITER IS CONSTANT 1!\n" ); - return 0; - } - } - // if the miter is undecided (or satisfiable), return immediately - else - return -1; - } - // return 1, meaning all outputs are constant zero - return 1; -} - -/**Function************************************************************* - - Synopsis [Reports the status of the miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ) -{ - Abc_Obj_t * pChild, * pNode; - int i; - if ( Abc_NtkPoNum(pMiter) == 1 ) - { - pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,0) ); - if ( Abc_AigNodeIsConst(pChild) ) - { - if ( Abc_ObjIsComplement(pChild) ) - printf( "Unsatisfiable.\n" ); - else - printf( "Satisfiable. (Constant 1).\n" ); - } - else - printf( "Satisfiable.\n" ); - } - else - { - Abc_NtkForEachPo( pMiter, pNode, i ) - { - pChild = Abc_ObjChild0( Abc_NtkPo(pMiter,i) ); - printf( "Output #%2d : ", i ); - if ( Abc_AigNodeIsConst(pChild) ) - { - if ( Abc_ObjIsComplement(pChild) ) - printf( "Unsatisfiable.\n" ); - else - printf( "Satisfiable. (Constant 1).\n" ); - } - else - printf( "Satisfiable.\n" ); - } - } -} - - -/**Function************************************************************* - - Synopsis [Derives the timeframes of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial ) -{ - char Buffer[1000]; - ProgressBar * pProgress; - Abc_Ntk_t * pNtkFrames; - Abc_Obj_t * pLatch, * pLatchOut; - int i, Counter; - assert( nFrames > 0 ); - assert( Abc_NtkIsStrash(pNtk) ); - assert( Abc_NtkIsDfsOrdered(pNtk) ); - assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); - // start the new network - pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); - pNtkFrames->pName = Extra_UtilStrsav(Buffer); - // map the constant nodes - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkFrames); - // create new latches (or their initial values) and remember them in the new latches - if ( !fInitial ) - { - Abc_NtkForEachLatch( pNtk, pLatch, i ) - Abc_NtkDupBox( pNtkFrames, pLatch, 1 ); - } - else - { - Counter = 0; - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - pLatchOut = Abc_ObjFanout0(pLatch); - if ( Abc_LatchIsInitNone(pLatch) || Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI - { - pLatchOut->pCopy = Abc_NtkCreatePi(pNtkFrames); - Abc_ObjAssignName( pLatchOut->pCopy, Abc_ObjName(pLatchOut), NULL ); - Counter++; - } - else - pLatchOut->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) ); - } - if ( Counter ) - printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter ); - } - - // create the timeframes - pProgress = Extra_ProgressBarStart( stdout, nFrames ); - for ( i = 0; i < nFrames; i++ ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - Abc_NtkAddFrame( pNtkFrames, pNtk, i ); - } - Extra_ProgressBarStop( pProgress ); - - // connect the new latches to the outputs of the last frame - if ( !fInitial ) - { - // we cannot use pLatch->pCopy here because pLatch->pCopy is used for temporary storage of strashed values - Abc_NtkForEachLatch( pNtk, pLatch, i ) - Abc_ObjAddFanin( Abc_ObjFanin0(pLatch)->pCopy, Abc_ObjFanout0(pLatch)->pCopy ); - } - - // remove dangling nodes - Abc_AigCleanup( pNtkFrames->pManFunc ); - // reorder the latches - Abc_NtkOrderCisCos( pNtkFrames ); - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkFrames ) ) - { - printf( "Abc_NtkFrames: The network check has failed.\n" ); - Abc_NtkDelete( pNtkFrames ); - return NULL; - } - return pNtkFrames; -} - -/**Function************************************************************* - - Synopsis [Adds one time frame to the new network.] - - Description [Assumes that the latches of the old network point - to the outputs of the previous frame of the new network (pLatch->pCopy). - In the end, updates the latches of the old network to point to the - outputs of the current frame of the new network.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAddFrame( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame ) -{ - char Buffer[10]; - Abc_Obj_t * pNode, * pLatch; - int i; - // create the prefix to be added to the node names - sprintf( Buffer, "_%02d", iFrame ); - // add the new PI nodes - Abc_NtkForEachPi( pNtk, pNode, i ) - Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); - // add the internal nodes - Abc_AigForEachAnd( pNtk, pNode, i ) - pNode->pCopy = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); - // add the new POs - Abc_NtkForEachPo( pNtk, pNode, i ) - { - Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); - Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) ); - } - // add the new asserts - Abc_NtkForEachAssert( pNtk, pNode, i ) - { - Abc_ObjAssignName( Abc_NtkDupObj(pNtkFrames, pNode, 0), Abc_ObjName(pNode), Buffer ); - Abc_ObjAddFanin( pNode->pCopy, Abc_ObjChild0Copy(pNode) ); - } - // transfer the implementation of the latch inputs to the latch outputs - Abc_NtkForEachLatch( pNtk, pLatch, i ) - pLatch->pCopy = Abc_ObjChild0Copy(Abc_ObjFanin0(pLatch)); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - Abc_ObjFanout0(pLatch)->pCopy = pLatch->pCopy; -} - - - -/**Function************************************************************* - - Synopsis [Derives the timeframes of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFrames2( Abc_Ntk_t * pNtk, int nFrames, int fInitial, AddFrameMapping addFrameMapping, void* arg ) -{ -/* - char Buffer[1000]; - ProgressBar * pProgress; - Abc_Ntk_t * pNtkFrames; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pLatch, * pLatchNew; - int i, Counter; - assert( nFrames > 0 ); - assert( Abc_NtkIsStrash(pNtk) ); - // start the new network - pNtkFrames = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - sprintf( Buffer, "%s_%d_frames", pNtk->pName, nFrames ); - pNtkFrames->pName = Extra_UtilStrsav(Buffer); - // create new latches (or their initial values) and remember them in the new latches - if ( !fInitial ) - { - Abc_NtkForEachLatch( pNtk, pLatch, i ) { - Abc_NtkDupObj( pNtkFrames, pLatch ); - if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); - } - } - else - { - Counter = 0; - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - if ( Abc_LatchIsInitDc(pLatch) ) // don't-care initial value - create a new PI - { - pLatch->pCopy = Abc_NtkCreatePi(pNtkFrames); - Abc_ObjAssignName( pLatch->pCopy, Abc_ObjName(pLatch), NULL ); - Counter++; - } - else { - pLatch->pCopy = Abc_ObjNotCond( Abc_AigConst1(pNtkFrames), Abc_LatchIsInit0(pLatch) ); - } - - if (addFrameMapping) addFrameMapping(pLatch->pCopy, pLatch, 0, arg); - } - if ( Counter ) - printf( "Warning: %d uninitialized latches are replaced by free PI variables.\n", Counter ); - } - - // create the timeframes - vNodes = Abc_NtkDfs( pNtk, 0 ); - pProgress = Extra_ProgressBarStart( stdout, nFrames ); - for ( i = 0; i < nFrames; i++ ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - Abc_NtkAddFrame2( pNtkFrames, pNtk, i, vNodes, addFrameMapping, arg ); - } - Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vNodes ); - - // connect the new latches to the outputs of the last frame - if ( !fInitial ) - { - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - pLatchNew = Abc_NtkBox(pNtkFrames, i); - Abc_ObjAddFanin( pLatchNew, pLatch->pCopy ); - Abc_ObjAssignName( pLatchNew, Abc_ObjName(pLatch), NULL ); - } - } - Abc_NtkForEachLatch( pNtk, pLatch, i ) - pLatch->pNext = NULL; - - // remove dangling nodes - Abc_AigCleanup( pNtkFrames->pManFunc ); - - // reorder the latches - Abc_NtkOrderCisCos( pNtkFrames ); - - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtkFrames ) ) - { - printf( "Abc_NtkFrames: The network check has failed.\n" ); - Abc_NtkDelete( pNtkFrames ); - return NULL; - } - return pNtkFrames; -*/ - return NULL; -} - -/**Function************************************************************* - - Synopsis [Adds one time frame to the new network.] - - Description [Assumes that the latches of the old network point - to the outputs of the previous frame of the new network (pLatch->pCopy). - In the end, updates the latches of the old network to point to the - outputs of the current frame of the new network.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAddFrame2( Abc_Ntk_t * pNtkFrames, Abc_Ntk_t * pNtk, int iFrame, Vec_Ptr_t * vNodes, AddFrameMapping addFrameMapping, void* arg ) -{ -/* - char Buffer[10]; - Abc_Obj_t * pNode, * pNodeNew, * pLatch; - Abc_Obj_t * pConst1, * pConst1New; - int i; - // get the constant nodes - pConst1 = Abc_AigConst1(pNtk); - pConst1New = Abc_AigConst1(pNtkFrames); - // create the prefix to be added to the node names - sprintf( Buffer, "_%02d", iFrame ); - // add the new PI nodes - Abc_NtkForEachPi( pNtk, pNode, i ) - { - pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode ); - Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer ); - if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); - } - // add the internal nodes - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( pNode == pConst1 ) - pNodeNew = pConst1New; - else - pNodeNew = Abc_AigAnd( pNtkFrames->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); - pNode->pCopy = pNodeNew; - if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); - } - // add the new POs - Abc_NtkForEachPo( pNtk, pNode, i ) - { - pNodeNew = Abc_NtkDupObj( pNtkFrames, pNode ); - Abc_ObjAddFanin( pNodeNew, Abc_ObjChild0Copy(pNode) ); - Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNode), Buffer ); - if (addFrameMapping) addFrameMapping(pNodeNew, pNode, iFrame, arg); - } - // transfer the implementation of the latch drivers to the latches - - // it is important that these two steps are performed it two loops - // and not in the same loop - Abc_NtkForEachLatch( pNtk, pLatch, i ) - pLatch->pNext = Abc_ObjChild0Copy(pLatch); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - pLatch->pCopy = pLatch->pNext; - - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - if (addFrameMapping) { - // don't give Mike complemented pointers because he doesn't like it - if (Abc_ObjIsComplement(pLatch->pCopy)) { - pNodeNew = Abc_NtkCreateNode( pNtkFrames ); - Abc_ObjAddFanin( pNodeNew, pLatch->pCopy ); - assert(Abc_ObjFaninNum(pNodeNew) == 1); - pNodeNew->Level = 1 + Abc_ObjRegular(pLatch->pCopy)->Level; - - pLatch->pNext = pNodeNew; - pLatch->pCopy = pNodeNew; - } - addFrameMapping(pLatch->pCopy, pLatch, iFrame+1, arg); - } - } -*/ -} - - - -/**Function************************************************************* - - Synopsis [Splits the miter into two logic cones combined by an EXOR] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDemiter( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNodeC, * pNodeA, * pNodeB, * pNode; - Abc_Obj_t * pPoNew; - Vec_Ptr_t * vNodes1, * vNodes2; - int nCommon, i; - - assert( Abc_NtkIsStrash(pNtk) ); - assert( Abc_NtkPoNum(pNtk) == 1 ); - if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) - { - printf( "The root of the miter is not an EXOR gate.\n" ); - return 0; - } - pNodeC = Abc_NodeRecognizeMux( Abc_ObjFanin0(Abc_NtkPo(pNtk,0)), &pNodeA, &pNodeB ); - assert( Abc_ObjRegular(pNodeA) == Abc_ObjRegular(pNodeB) ); - if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk,0)) ) - { - pNodeA = Abc_ObjNot(pNodeA); - pNodeB = Abc_ObjNot(pNodeB); - } - - // add the PO corresponding to control input - pPoNew = Abc_NtkCreatePo( pNtk ); - Abc_ObjAddFanin( pPoNew, pNodeC ); - Abc_ObjAssignName( pPoNew, "addOut1", NULL ); - - // add the PO corresponding to other input - pPoNew = Abc_NtkCreatePo( pNtk ); - Abc_ObjAddFanin( pPoNew, pNodeB ); - Abc_ObjAssignName( pPoNew, "addOut2", NULL ); - - // mark the nodes in the first cone - pNodeB = Abc_ObjRegular(pNodeB); - vNodes1 = Abc_NtkDfsNodes( pNtk, &pNodeC, 1 ); - vNodes2 = Abc_NtkDfsNodes( pNtk, &pNodeB, 1 ); - - Vec_PtrForEachEntry( vNodes1, pNode, i ) - pNode->fMarkA = 1; - nCommon = 0; - Vec_PtrForEachEntry( vNodes2, pNode, i ) - nCommon += pNode->fMarkA; - Vec_PtrForEachEntry( vNodes1, pNode, i ) - pNode->fMarkA = 0; - - printf( "First cone = %6d. Second cone = %6d. Common = %6d.\n", vNodes1->nSize, vNodes2->nSize, nCommon ); - Vec_PtrFree( vNodes1 ); - Vec_PtrFree( vNodes2 ); - - // reorder the latches - Abc_NtkOrderCisCos( pNtk ); - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtk ) ) - printf( "Abc_NtkDemiter: The network check has failed.\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes OR or AND of the POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ) -{ - Abc_Obj_t * pNode, * pMiter; - int i; - assert( Abc_NtkIsStrash(pNtk) ); -// assert( Abc_NtkLatchNum(pNtk) == 0 ); - if ( Abc_NtkPoNum(pNtk) == 1 ) - return 1; - // start the result - if ( fAnd ) - pMiter = Abc_AigConst1(pNtk); - else - pMiter = Abc_ObjNot( Abc_AigConst1(pNtk) ); - // perform operations on the POs - Abc_NtkForEachPo( pNtk, pNode, i ) - if ( fAnd ) - pMiter = Abc_AigAnd( pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); - else - pMiter = Abc_AigOr( pNtk->pManFunc, pMiter, Abc_ObjChild0(pNode) ); - // remove the POs and their names - for ( i = Abc_NtkPoNum(pNtk) - 1; i >= 0; i-- ) - Abc_NtkDeleteObj( Abc_NtkPo(pNtk, i) ); - assert( Abc_NtkPoNum(pNtk) == 0 ); - // create the new PO - pNode = Abc_NtkCreatePo( pNtk ); - Abc_ObjAddFanin( pNode, pMiter ); - Abc_ObjAssignName( pNode, "miter", NULL ); - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtk ) ) - { - printf( "Abc_NtkOrPos: The network check has failed.\n" ); - return 0; - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcMulti.c b/src/base/abci/abcMulti.c deleted file mode 100644 index e93360a0..00000000 --- a/src/base/abci/abcMulti.c +++ /dev/null @@ -1,643 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcMulti.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures which transform an AIG into multi-input AND-graph.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcMulti.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); -static Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld ); - -static DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFanins ); -static DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ); - -static void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax ); -static void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk ); -static void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh ); -static void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk ); -static void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk ); -static void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transforms the AIG into nodes.] - - Description [Threhold is the max number of nodes duplicated at a node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ) -{ - Abc_Ntk_t * pNtkNew; - - assert( Abc_NtkIsStrash(pNtk) ); - assert( nThresh >= 0 ); - assert( nFaninMax > 1 ); - - // print a warning about choice nodes - if ( Abc_NtkGetChoiceNum( pNtk ) ) - printf( "Warning: The choice nodes in the AIG are removed by renoding.\n" ); - - // define the boundary - if ( fCnf ) - Abc_NtkMultiSetBoundsCnf( pNtk ); - else if ( fMulti ) - Abc_NtkMultiSetBoundsMulti( pNtk, nThresh ); - else if ( fSimple ) - Abc_NtkMultiSetBoundsSimple( pNtk ); - else if ( fFactor ) - Abc_NtkMultiSetBoundsFactor( pNtk ); - else - Abc_NtkMultiSetBounds( pNtk, nThresh, nFaninMax ); - - // perform renoding for this boundary - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); - Abc_NtkMultiInt( pNtk, pNtkNew ); - Abc_NtkFinalize( pNtk, pNtkNew ); - - // make the network minimum base - Abc_NtkMinimumBase( pNtkNew ); - - // fix the problem with complemented and duplicated CO edges - Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); - - // report the number of CNF objects - if ( fCnf ) - { -// int nClauses = Abc_NtkGetClauseNum(pNtkNew) + 2*Abc_NtkPoNum(pNtkNew) + 2*Abc_NtkLatchNum(pNtkNew); -// printf( "CNF variables = %d. CNF clauses = %d.\n", Abc_NtkNodeNum(pNtkNew), nClauses ); - } -//printf( "Maximum fanin = %d.\n", Abc_NtkGetFaninMax(pNtkNew) ); - - if ( pNtk->pExdc ) - pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); - // make sure everything is okay - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkMulti: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Transforms the AIG into nodes.] - - Description [Threhold is the max number of nodes duplicated at a node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) -{ - ProgressBar * pProgress; - Abc_Obj_t * pNode, * pConst1, * pNodeNew; - int i; - - // set the constant node - pConst1 = Abc_AigConst1(pNtk); - if ( Abc_ObjFanoutNum(pConst1) > 0 ) - { - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData ); - pConst1->pCopy = pNodeNew; - } - - // perform renoding for POs - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) - continue; - Abc_NtkMulti_rec( pNtkNew, Abc_ObjFanin0(pNode) ); - } - Extra_ProgressBarStop( pProgress ); - - // clean the boundaries and data field in the old network - Abc_NtkForEachObj( pNtk, pNode, i ) - { - pNode->fMarkA = 0; - pNode->pData = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Find the best multi-input node rooted at the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkMulti_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld ) -{ - Vec_Ptr_t * vCone; - Abc_Obj_t * pNodeNew; - int i; - - assert( !Abc_ObjIsComplement(pNodeOld) ); - // return if the result if known - if ( pNodeOld->pCopy ) - return pNodeOld->pCopy; - assert( Abc_ObjIsNode(pNodeOld) ); - assert( !Abc_AigNodeIsConst(pNodeOld) ); - assert( pNodeOld->fMarkA ); - -//printf( "%d ", Abc_NodeMffcSizeSupp(pNodeOld) ); - - // collect the renoding cone - vCone = Vec_PtrAlloc( 10 ); - Abc_NtkMultiCone( pNodeOld, vCone ); - - // create a new node - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - for ( i = 0; i < vCone->nSize; i++ ) - Abc_ObjAddFanin( pNodeNew, Abc_NtkMulti_rec(pNtkNew, vCone->pArray[i]) ); - - // derive the function of this node - pNodeNew->pData = Abc_NtkMultiDeriveBdd( pNtkNew->pManFunc, pNodeOld, vCone ); - Cudd_Ref( pNodeNew->pData ); - Vec_PtrFree( vCone ); - - // remember the node - pNodeOld->pCopy = pNodeNew; - return pNodeOld->pCopy; -} - - -/**Function************************************************************* - - Synopsis [Derives the local BDD of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_NtkMultiDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld ) -{ - Abc_Obj_t * pFaninOld; - DdNode * bFunc; - int i; - assert( !Abc_AigNodeIsConst(pNodeOld) ); - assert( Abc_ObjIsNode(pNodeOld) ); - // set the elementary BDD variables for the input nodes - for ( i = 0; i < vFaninsOld->nSize; i++ ) - { - pFaninOld = vFaninsOld->pArray[i]; - pFaninOld->pData = Cudd_bddIthVar( dd, i ); Cudd_Ref( pFaninOld->pData ); - pFaninOld->fMarkC = 1; - } - // call the recursive BDD computation - bFunc = Abc_NtkMultiDeriveBdd_rec( dd, pNodeOld, vFaninsOld ); Cudd_Ref( bFunc ); - // dereference the intermediate nodes - for ( i = 0; i < vFaninsOld->nSize; i++ ) - { - pFaninOld = vFaninsOld->pArray[i]; - Cudd_RecursiveDeref( dd, pFaninOld->pData ); - pFaninOld->fMarkC = 0; - } - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Derives the local BDD of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_NtkMultiDeriveBdd_rec( DdManager * dd, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins ) -{ - DdNode * bFunc, * bFunc0, * bFunc1; - assert( !Abc_ObjIsComplement(pNode) ); - // if the result is available return - if ( pNode->fMarkC ) - { - assert( pNode->pData ); // network has a cycle - return pNode->pData; - } - // mark the node as visited - pNode->fMarkC = 1; - Vec_PtrPush( vFanins, pNode ); - // compute the result for both branches - bFunc0 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,0), vFanins ); Cudd_Ref( bFunc0 ); - bFunc1 = Abc_NtkMultiDeriveBdd_rec( dd, Abc_ObjFanin(pNode,1), vFanins ); Cudd_Ref( bFunc1 ); - bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) ); - bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) ); - // get the final result - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bFunc0 ); - Cudd_RecursiveDeref( dd, bFunc1 ); - // set the result - pNode->pData = bFunc; - assert( pNode->pData ); - return bFunc; -} - - - -/**Function************************************************************* - - Synopsis [Limits the cones to be no more than the given size.] - - Description [Returns 1 if the last cone was limited. Returns 0 if no changes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMultiLimit_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax, int fCanStop, int fFirst ) -{ - int nNodes0, nNodes1; - assert( !Abc_ObjIsComplement(pNode) ); - // check if the node should be added to the fanins - if ( !fFirst && (pNode->fMarkA || !Abc_ObjIsNode(pNode)) ) - { - Vec_PtrPushUnique( vCone, pNode ); - return 0; - } - // if we cannot stop in this branch, collect all nodes - if ( !fCanStop ) - { - Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 0, 0 ); - Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); - return 0; - } - // if we can stop, try the left branch first, and return if we stopped - assert( vCone->nSize == 0 ); - if ( Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,0), vCone, nFaninMax, 1, 0 ) ) - return 1; - // save the number of nodes in the left branch and call for the right branch - nNodes0 = vCone->nSize; - assert( nNodes0 <= nFaninMax ); - Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); - // check the number of nodes - if ( vCone->nSize <= nFaninMax ) - return 0; - // the number of nodes exceeds the limit - - // get the number of nodes in the right branch - vCone->nSize = 0; - Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 0, 0 ); - // if this number exceeds the limit, solve the problem for this branch - if ( vCone->nSize > nFaninMax ) - { - int RetValue; - vCone->nSize = 0; - RetValue = Abc_NtkMultiLimit_rec( Abc_ObjFanin(pNode,1), vCone, nFaninMax, 1, 0 ); - assert( RetValue == 1 ); - return 1; - } - - nNodes1 = vCone->nSize; - assert( nNodes1 <= nFaninMax ); - if ( nNodes0 >= nNodes1 ) - { // the left branch is larger - cut it - assert( Abc_ObjFanin(pNode,0)->fMarkA == 0 ); - Abc_ObjFanin(pNode,0)->fMarkA = 1; - } - else - { // the right branch is larger - cut it - assert( Abc_ObjFanin(pNode,1)->fMarkA == 0 ); - Abc_ObjFanin(pNode,1)->fMarkA = 1; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Limits the cones to be no more than the given size.] - - Description [Returns 1 if the last cone was limited. Returns 0 if no changes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMultiLimit( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, int nFaninMax ) -{ - vCone->nSize = 0; - return Abc_NtkMultiLimit_rec( pNode, vCone, nFaninMax, 1, 1 ); -} - -/**Function************************************************************* - - Synopsis [Sets the expansion boundary for multi-input nodes.] - - Description [The boundary includes the set of PIs and all nodes such that - when expanding over the node we duplicate no more than nThresh nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMultiSetBounds( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax ) -{ - Vec_Ptr_t * vCone = Vec_PtrAlloc(10); - Abc_Obj_t * pNode; - int i, nFanouts, nConeSize; - - // make sure the mark is not set - Abc_NtkForEachObj( pNtk, pNode, i ) - assert( pNode->fMarkA == 0 ); - - // mark the nodes where expansion stops using pNode->fMarkA - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // skip PI/PO nodes -// if ( Abc_NodeIsConst(pNode) ) -// continue; - // mark the nodes with multiple fanouts - nFanouts = Abc_ObjFanoutNum(pNode); - nConeSize = Abc_NodeMffcSize(pNode); - if ( (nFanouts - 1) * nConeSize > nThresh ) - pNode->fMarkA = 1; - } - - // mark the PO drivers - Abc_NtkForEachCo( pNtk, pNode, i ) - Abc_ObjFanin0(pNode)->fMarkA = 1; - - // make sure the fanin limit is met - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // skip PI/PO nodes -// if ( Abc_NodeIsConst(pNode) ) -// continue; - if ( pNode->fMarkA == 0 ) - continue; - // continue cutting branches until it meets the fanin limit - while ( Abc_NtkMultiLimit(pNode, vCone, nFaninMax) ); - assert( vCone->nSize <= nFaninMax ); - } - Vec_PtrFree(vCone); -/* - // make sure the fanin limit is met - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // skip PI/PO nodes -// if ( Abc_NodeIsConst(pNode) ) -// continue; - if ( pNode->fMarkA == 0 ) - continue; - Abc_NtkMultiCone( pNode, vCone ); - assert( vCone->nSize <= nFaninMax ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Sets the expansion boundary for conversion into CNF.] - - Description [The boundary includes the set of PIs, the roots of MUXes, - the nodes with multiple fanouts and the nodes with complemented outputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMultiSetBoundsCnf( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, nMuxes; - - // make sure the mark is not set - Abc_NtkForEachObj( pNtk, pNode, i ) - assert( pNode->fMarkA == 0 ); - - // mark the nodes where expansion stops using pNode->fMarkA - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // skip PI/PO nodes -// if ( Abc_NodeIsConst(pNode) ) -// continue; - // mark the nodes with multiple fanouts - if ( Abc_ObjFanoutNum(pNode) > 1 ) - pNode->fMarkA = 1; - // mark the nodes that are roots of MUXes - if ( Abc_NodeIsMuxType( pNode ) ) - { - pNode->fMarkA = 1; - Abc_ObjFanin0( Abc_ObjFanin0(pNode) )->fMarkA = 1; - Abc_ObjFanin0( Abc_ObjFanin1(pNode) )->fMarkA = 1; - Abc_ObjFanin1( Abc_ObjFanin0(pNode) )->fMarkA = 1; - Abc_ObjFanin1( Abc_ObjFanin1(pNode) )->fMarkA = 1; - } - else // mark the complemented edges - { - if ( Abc_ObjFaninC0(pNode) ) - Abc_ObjFanin0(pNode)->fMarkA = 1; - if ( Abc_ObjFaninC1(pNode) ) - Abc_ObjFanin1(pNode)->fMarkA = 1; - } - } - - // mark the PO drivers - Abc_NtkForEachCo( pNtk, pNode, i ) - Abc_ObjFanin0(pNode)->fMarkA = 1; - - // count the number of MUXes - nMuxes = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // skip PI/PO nodes -// if ( Abc_NodeIsConst(pNode) ) -// continue; - if ( Abc_NodeIsMuxType(pNode) && - Abc_ObjFanin0(pNode)->fMarkA == 0 && - Abc_ObjFanin1(pNode)->fMarkA == 0 ) - nMuxes++; - } -// printf( "The number of MUXes detected = %d (%5.2f %% of logic).\n", nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) ); -} - -/**Function************************************************************* - - Synopsis [Sets the expansion boundary for conversion into multi-input AND graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMultiSetBoundsMulti( Abc_Ntk_t * pNtk, int nThresh ) -{ - Abc_Obj_t * pNode; - int i, nFanouts, nConeSize; - - // make sure the mark is not set - Abc_NtkForEachObj( pNtk, pNode, i ) - assert( pNode->fMarkA == 0 ); - - // mark the nodes where expansion stops using pNode->fMarkA - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // skip PI/PO nodes -// if ( Abc_NodeIsConst(pNode) ) -// continue; - // mark the nodes with multiple fanouts -// if ( Abc_ObjFanoutNum(pNode) > 1 ) -// pNode->fMarkA = 1; - // mark the nodes with multiple fanouts - nFanouts = Abc_ObjFanoutNum(pNode); - nConeSize = Abc_NodeMffcSizeStop(pNode); - if ( (nFanouts - 1) * nConeSize > nThresh ) - pNode->fMarkA = 1; - // mark the children if they are pointed by the complemented edges - if ( Abc_ObjFaninC0(pNode) ) - Abc_ObjFanin0(pNode)->fMarkA = 1; - if ( Abc_ObjFaninC1(pNode) ) - Abc_ObjFanin1(pNode)->fMarkA = 1; - } - - // mark the PO drivers - Abc_NtkForEachCo( pNtk, pNode, i ) - Abc_ObjFanin0(pNode)->fMarkA = 1; -} - -/**Function************************************************************* - - Synopsis [Sets a simple boundary.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMultiSetBoundsSimple( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i; - // make sure the mark is not set - Abc_NtkForEachObj( pNtk, pNode, i ) - assert( pNode->fMarkA == 0 ); - // mark the nodes where expansion stops using pNode->fMarkA - Abc_NtkForEachNode( pNtk, pNode, i ) - pNode->fMarkA = 1; -} - -/**Function************************************************************* - - Synopsis [Sets a factor-cut boundary.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMultiSetBoundsFactor( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i; - // make sure the mark is not set - Abc_NtkForEachObj( pNtk, pNode, i ) - assert( pNode->fMarkA == 0 ); - // mark the nodes where expansion stops using pNode->fMarkA - Abc_NtkForEachNode( pNtk, pNode, i ) - pNode->fMarkA = (pNode->vFanouts.nSize > 1 && !Abc_NodeIsMuxControlType(pNode)); - // mark the PO drivers - Abc_NtkForEachCo( pNtk, pNode, i ) - Abc_ObjFanin0(pNode)->fMarkA = 1; -} - -/**Function************************************************************* - - Synopsis [Collects the fanins of a large node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMultiCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ) -{ - assert( !Abc_ObjIsComplement(pNode) ); - if ( pNode->fMarkA || !Abc_ObjIsNode(pNode) ) - { - Vec_PtrPushUnique( vCone, pNode ); - return; - } - Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone ); - Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone ); -} - -/**Function************************************************************* - - Synopsis [Collects the fanins of a large node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMultiCone( Abc_Obj_t * pNode, Vec_Ptr_t * vCone ) -{ - assert( !Abc_ObjIsComplement(pNode) ); - assert( Abc_ObjIsNode(pNode) ); - vCone->nSize = 0; - Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,0), vCone ); - Abc_NtkMultiCone_rec( Abc_ObjFanin(pNode,1), vCone ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcMv.c b/src/base/abci/abcMv.c deleted file mode 100644 index 2858b8a7..00000000 --- a/src/base/abci/abcMv.c +++ /dev/null @@ -1,369 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcMv.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Multi-valued decomposition.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Mv_Man_t_ Mv_Man_t; -struct Mv_Man_t_ -{ - int nInputs; // the number of 4-valued input variables - int nFuncs; // the number of 4-valued functions - DdManager * dd; // representation of functions - DdNode * bValues[15][4]; // representation of i-sets - DdNode * bValueDcs[15][4]; // representation of i-sets don't-cares - DdNode * bFuncs[15]; // representation of functions -}; - -static void Abc_MvDecompose( Mv_Man_t * p ); -static void Abc_MvPrintStats( Mv_Man_t * p ); -static void Abc_MvRead( Mv_Man_t * p ); -static void Abc_MvDeref( Mv_Man_t * p ); -static DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_MvExperiment() -{ - Mv_Man_t * p; - // get the functions - p = ALLOC( Mv_Man_t, 1 ); - memset( p, 0, sizeof(Mv_Man_t) ); - p->dd = Cudd_Init( 32, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - p->nFuncs = 15; - p->nInputs = 9; - Abc_MvRead( p ); - // process the functions - Abc_MvPrintStats( p ); -// Cudd_ReduceHeap( p->dd, CUDD_REORDER_SYMM_SIFT, 1 ); -// Abc_MvPrintStats( p ); - // try detecting support reducing bound set - Abc_MvDecompose( p ); - - // remove the manager - Abc_MvDeref( p ); - Extra_StopManager( p->dd ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_MvPrintStats( Mv_Man_t * p ) -{ - int i, v; - for ( i = 0; i < 15; i++ ) - { - printf( "%2d : ", i ); - printf( "%3d (%2d) ", Cudd_DagSize(p->bFuncs[i])-1, Cudd_SupportSize(p->dd, p->bFuncs[i]) ); - for ( v = 0; v < 4; v++ ) - printf( "%d = %3d (%2d) ", v, Cudd_DagSize(p->bValues[i][v])-1, Cudd_SupportSize(p->dd, p->bValues[i][v]) ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_MvReadCube( DdManager * dd, char * pLine, int nVars ) -{ - DdNode * bCube, * bVar, * bTemp; - int i; - bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); - for ( i = 0; i < nVars; i++ ) - { - if ( pLine[i] == '-' ) - continue; - else if ( pLine[i] == '0' ) // 0 - bVar = Cudd_Not( Cudd_bddIthVar(dd, 29-i) ); - else if ( pLine[i] == '1' ) // 1 - bVar = Cudd_bddIthVar(dd, 29-i); - else assert(0); - bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bCube ); - return bCube; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_MvRead( Mv_Man_t * p ) -{ - FILE * pFile; - char Buffer[1000], * pLine; - DdNode * bCube, * bTemp, * bProd, * bVar0, * bVar1, * bCubeSum; - int i, v; - - // start the cube - bCubeSum = Cudd_ReadLogicZero(p->dd); Cudd_Ref( bCubeSum ); - - // start the values - for ( i = 0; i < 15; i++ ) - for ( v = 0; v < 4; v++ ) - { - p->bValues[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValues[i][v] ); - p->bValueDcs[i][v] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bValueDcs[i][v] ); - } - - // read the file - pFile = fopen( "input.pla", "r" ); - while ( fgets( Buffer, 1000, pFile ) ) - { - if ( Buffer[0] == '#' ) - continue; - if ( Buffer[0] == '.' ) - { - if ( Buffer[1] == 'e' ) - break; - continue; - } - - // get the cube - bCube = Abc_MvReadCube( p->dd, Buffer, 18 ); Cudd_Ref( bCube ); - - // add it to the values of the output functions - pLine = Buffer + 19; - for ( i = 0; i < 15; i++ ) - { - if ( pLine[2*i] == '-' && pLine[2*i+1] == '-' ) - { - for ( v = 0; v < 4; v++ ) - { - p->bValueDcs[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValueDcs[i][v], bCube ); Cudd_Ref( p->bValueDcs[i][v] ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - continue; - } - else if ( pLine[2*i] == '0' && pLine[2*i+1] == '0' ) // 0 - v = 0; - else if ( pLine[2*i] == '1' && pLine[2*i+1] == '0' ) // 1 - v = 1; - else if ( pLine[2*i] == '0' && pLine[2*i+1] == '1' ) // 2 - v = 2; - else if ( pLine[2*i] == '1' && pLine[2*i+1] == '1' ) // 3 - v = 3; - else assert( 0 ); - // add the value - p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], bCube ); Cudd_Ref( p->bValues[i][v] ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - - // add the cube - bCubeSum = Cudd_bddOr( p->dd, bTemp = bCubeSum, bCube ); Cudd_Ref( bCubeSum ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bCube ); - } - - // add the complement of the domain to all values - for ( i = 0; i < 15; i++ ) - for ( v = 0; v < 4; v++ ) - { - if ( p->bValues[i][v] == Cudd_Not(Cudd_ReadOne(p->dd)) ) - continue; - p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], p->bValueDcs[i][v] ); Cudd_Ref( p->bValues[i][v] ); - Cudd_RecursiveDeref( p->dd, bTemp ); - p->bValues[i][v] = Cudd_bddOr( p->dd, bTemp = p->bValues[i][v], Cudd_Not(bCubeSum) ); Cudd_Ref( p->bValues[i][v] ); - Cudd_RecursiveDeref( p->dd, bTemp ); - } - printf( "Domain = %5.2f %%.\n", 100.0*Cudd_CountMinterm(p->dd, bCubeSum, 32)/Cudd_CountMinterm(p->dd, Cudd_ReadOne(p->dd), 32) ); - Cudd_RecursiveDeref( p->dd, bCubeSum ); - - // create each output function - for ( i = 0; i < 15; i++ ) - { - p->bFuncs[i] = Cudd_ReadLogicZero(p->dd); Cudd_Ref( p->bFuncs[i] ); - for ( v = 0; v < 4; v++ ) - { - bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 30), ((v & 1) == 0) ); - bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 31), ((v & 2) == 0) ); - bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); - bProd = Cudd_bddAnd( p->dd, p->bValues[i][v], bCube ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( p->dd, bCube ); - // add the value - p->bFuncs[i] = Cudd_bddOr( p->dd, bTemp = p->bFuncs[i], bProd ); Cudd_Ref( p->bFuncs[i] ); - Cudd_RecursiveDeref( p->dd, bTemp ); - Cudd_RecursiveDeref( p->dd, bProd ); - } - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_MvDeref( Mv_Man_t * p ) -{ - int i, v; - for ( i = 0; i < 15; i++ ) - for ( v = 0; v < 4; v++ ) - { - Cudd_RecursiveDeref( p->dd, p->bValues[i][v] ); - Cudd_RecursiveDeref( p->dd, p->bValueDcs[i][v] ); - } - for ( i = 0; i < 15; i++ ) - Cudd_RecursiveDeref( p->dd, p->bFuncs[i] ); -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_MvDecompose( Mv_Man_t * p ) -{ - DdNode * bCofs[16], * bVarCube1, * bVarCube2, * bVarCube, * bCube, * bVar0, * bVar1;//, * bRes; - int k, i1, i2, v1, v2;//, c1, c2, Counter; - - bVar0 = Cudd_bddIthVar(p->dd, 30); - bVar1 = Cudd_bddIthVar(p->dd, 31); - bCube = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bCube ); - - for ( k = 0; k < p->nFuncs; k++ ) - { - printf( "FUNCTION %d\n", k ); - for ( i1 = 0; i1 < p->nFuncs; i1++ ) - for ( i2 = i1+1; i2 < p->nFuncs; i2++ ) - { - Vec_Ptr_t * vCofs; - - for ( v1 = 0; v1 < 4; v1++ ) - { - bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1 ), ((v1 & 1) == 0) ); - bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i1-1), ((v1 & 2) == 0) ); - bVarCube1 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube1 ); - for ( v2 = 0; v2 < 4; v2++ ) - { - bVar0 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2 ), ((v2 & 1) == 0) ); - bVar1 = Cudd_NotCond( Cudd_bddIthVar(p->dd, 29-2*i2-1), ((v2 & 2) == 0) ); - bVarCube2 = Cudd_bddAnd( p->dd, bVar0, bVar1 ); Cudd_Ref( bVarCube2 ); - bVarCube = Cudd_bddAnd( p->dd, bVarCube1, bVarCube2 ); Cudd_Ref( bVarCube ); - bCofs[v1 * 4 + v2] = Cudd_Cofactor( p->dd, p->bFuncs[k], bVarCube ); Cudd_Ref( bCofs[v1 * 4 + v2] ); - Cudd_RecursiveDeref( p->dd, bVarCube ); - Cudd_RecursiveDeref( p->dd, bVarCube2 ); - } - Cudd_RecursiveDeref( p->dd, bVarCube1 ); - } -/* - // check the compatibility of cofactors - Counter = 0; - for ( c1 = 0; c1 < 16; c1++ ) - { - for ( c2 = 0; c2 <= c1; c2++ ) - printf( " " ); - for ( c2 = c1+1; c2 < 16; c2++ ) - { - bRes = Cudd_bddAndAbstract( p->dd, bCofs[c1], bCofs[c2], bCube ); Cudd_Ref( bRes ); - if ( bRes == Cudd_ReadOne(p->dd) ) - { - printf( "+" ); - Counter++; - } - else - { - printf( " " ); - } - Cudd_RecursiveDeref( p->dd, bRes ); - } - printf( "\n" ); - } -*/ - - vCofs = Vec_PtrAlloc( 16 ); - for ( v1 = 0; v1 < 4; v1++ ) - for ( v2 = 0; v2 < 4; v2++ ) - Vec_PtrPushUnique( vCofs, bCofs[v1 * 4 + v2] ); - printf( "%d ", Vec_PtrSize(vCofs) ); - Vec_PtrFree( vCofs ); - - // free the cofactors - for ( v1 = 0; v1 < 4; v1++ ) - for ( v2 = 0; v2 < 4; v2++ ) - Cudd_RecursiveDeref( p->dd, bCofs[v1 * 4 + v2] ); - - printf( "\n" ); -// printf( "%2d, %2d : %3d\n", i1, i2, Counter ); - } - } - - Cudd_RecursiveDeref( p->dd, bCube ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcNtbdd.c b/src/base/abci/abcNtbdd.c deleted file mode 100644 index f127811e..00000000 --- a/src/base/abci/abcNtbdd.c +++ /dev/null @@ -1,582 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcNtbdd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures to translate between the BDD and the network.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcNtbdd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); -static Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ); -static Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node ); -static DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Constructs the network isomorphic to the given BDD.] - - Description [Assumes that the BDD depends on the variables whose indexes - correspond to the names in the array (pNamesPi). Otherwise, returns NULL. - The resulting network comes with one node, whose functionality is - equal to the given BDD. To decompose this BDD into the network of - multiplexers use Abc_NtkBddToMuxes(). To decompose this BDD into - an And-Inverter Graph, use Abc_NtkStrash().] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkDeriveFromBdd( DdManager * dd, DdNode * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ) -{ - Abc_Ntk_t * pNtk; - Vec_Ptr_t * vNamesPiFake = NULL; - Abc_Obj_t * pNode, * pNodePi, * pNodePo; - DdNode * bSupp, * bTemp; - char * pName; - int i; - - // supply fake names if real names are not given - if ( pNamePo == NULL ) - pNamePo = "F"; - if ( vNamesPi == NULL ) - { - vNamesPiFake = Abc_NodeGetFakeNames( dd->size ); - vNamesPi = vNamesPiFake; - } - - // make sure BDD depends on the variables whose index - // does not exceed the size of the array with PI names - bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); - for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) - if ( (int)Cudd_NodeReadIndex(bTemp) >= Vec_PtrSize(vNamesPi) ) - break; - Cudd_RecursiveDeref( dd, bSupp ); - if ( bTemp != Cudd_ReadOne(dd) ) - return NULL; - - // start the network - pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 ); - pNtk->pName = Extra_UtilStrsav(pNamePo); - // make sure the new manager has enough inputs - Cudd_bddIthVar( pNtk->pManFunc, Vec_PtrSize(vNamesPi) ); - // add the PIs corresponding to the names - Vec_PtrForEachEntry( vNamesPi, pName, i ) - Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), pName, NULL ); - // create the node - pNode = Abc_NtkCreateNode( pNtk ); - pNode->pData = Cudd_bddTransfer( dd, pNtk->pManFunc, bFunc ); Cudd_Ref(pNode->pData); - Abc_NtkForEachPi( pNtk, pNodePi, i ) - Abc_ObjAddFanin( pNode, pNodePi ); - // create the only PO - pNodePo = Abc_NtkCreatePo( pNtk ); - Abc_ObjAddFanin( pNodePo, pNode ); - Abc_ObjAssignName( pNodePo, pNamePo, NULL ); - // make the network minimum base - Abc_NtkMinimumBase( pNtk ); - if ( vNamesPiFake ) - Abc_NodeFreeNames( vNamesPiFake ); - if ( !Abc_NtkCheck( pNtk ) ) - fprintf( stdout, "Abc_NtkDeriveFromBdd(): Network check has failed.\n" ); - return pNtk; -} - - - -/**Function************************************************************* - - Synopsis [Creates the network isomorphic to the union of local BDDs of the nodes.] - - Description [The nodes of the local BDDs are converted into the network nodes - with logic functions equal to the MUX.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - assert( Abc_NtkIsBddLogic(pNtk) ); - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); - Abc_NtkBddToMuxesPerform( pNtk, pNtkNew ); - Abc_NtkFinalize( pNtk, pNtkNew ); - // make sure everything is okay - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkBddToMuxes: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Converts the network to MUXes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkBddToMuxesPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) -{ - ProgressBar * pProgress; - Abc_Obj_t * pNode, * pNodeNew; - Vec_Ptr_t * vNodes; - int i; - // perform conversion in the topological order - vNodes = Abc_NtkDfs( pNtk, 0 ); - pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // convert one node - assert( Abc_ObjIsNode(pNode) ); - pNodeNew = Abc_NodeBddToMuxes( pNode, pNtkNew ); - // mark the old node with the new one - assert( pNode->pCopy == NULL ); - pNode->pCopy = pNodeNew; - } - Vec_PtrFree( vNodes ); - Extra_ProgressBarStop( pProgress ); -} - -/**Function************************************************************* - - Synopsis [Converts the node to MUXes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeBddToMuxes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew ) -{ - DdManager * dd = pNodeOld->pNtk->pManFunc; - DdNode * bFunc = pNodeOld->pData; - Abc_Obj_t * pFaninOld, * pNodeNew; - st_table * tBdd2Node; - int i; - // create the table mapping BDD nodes into the ABC nodes - tBdd2Node = st_init_table( st_ptrcmp, st_ptrhash ); - // add the constant and the elementary vars - Abc_ObjForEachFanin( pNodeOld, pFaninOld, i ) - st_insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pFaninOld->pCopy ); - // create the new nodes recursively - pNodeNew = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNtkNew, tBdd2Node ); - st_free_table( tBdd2Node ); - if ( Cudd_IsComplement(bFunc) ) - pNodeNew = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew ); - return pNodeNew; -} - -/**Function************************************************************* - - Synopsis [Converts the node to MUXes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Abc_Ntk_t * pNtkNew, st_table * tBdd2Node ) -{ - Abc_Obj_t * pNodeNew, * pNodeNew0, * pNodeNew1, * pNodeNewC; - assert( !Cudd_IsComplement(bFunc) ); - if ( bFunc == b1 ) - return Abc_NtkCreateNodeConst1(pNtkNew); - if ( st_lookup( tBdd2Node, (char *)bFunc, (char **)&pNodeNew ) ) - return pNodeNew; - // solve for the children nodes - pNodeNew0 = Abc_NodeBddToMuxes_rec( dd, Cudd_Regular(cuddE(bFunc)), pNtkNew, tBdd2Node ); - if ( Cudd_IsComplement(cuddE(bFunc)) ) - pNodeNew0 = Abc_NtkCreateNodeInv( pNtkNew, pNodeNew0 ); - pNodeNew1 = Abc_NodeBddToMuxes_rec( dd, cuddT(bFunc), pNtkNew, tBdd2Node ); - if ( !st_lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeNewC ) ) - assert( 0 ); - // create the MUX node - pNodeNew = Abc_NtkCreateNodeMux( pNtkNew, pNodeNewC, pNodeNew1, pNodeNew0 ); - st_insert( tBdd2Node, (char *)bFunc, (char *)pNodeNew ); - return pNodeNew; -} - - -/**Function************************************************************* - - Synopsis [Derives global BDDs for the COs of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInternal, int fReorder, int fVerbose ) -{ - ProgressBar * pProgress; - Abc_Obj_t * pObj, * pFanin; - Vec_Att_t * pAttMan; - DdManager * dd; - DdNode * bFunc; - int i, k, Counter; - - // remove dangling nodes - Abc_AigCleanup( pNtk->pManFunc ); - - // start the manager - assert( Abc_NtkGlobalBdd(pNtk) == NULL ); - dd = Cudd_Init( Abc_NtkCiNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - pAttMan = Vec_AttAlloc( 0, Abc_NtkObjNumMax(pNtk) + 1, dd, Extra_StopManager, NULL, Cudd_RecursiveDeref ); - Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD, pAttMan ); - - // set reordering - if ( fReorder ) - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - - // assign the constant node BDD - pObj = Abc_AigConst1(pNtk); - if ( Abc_ObjFanoutNum(pObj) > 0 ) - { - bFunc = dd->one; - Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc ); - } - // set the elementary variables - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) > 0 ) - { - bFunc = dd->vars[i]; -// bFunc = dd->vars[Abc_NtkCiNum(pNtk) - 1 - i]; - Abc_ObjSetGlobalBdd( pObj, bFunc ); Cudd_Ref( bFunc ); - } - - // collect the global functions of the COs - Counter = 0; - // construct the BDDs - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkNodeNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - bFunc = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin0(pObj), nBddSizeMax, fDropInternal, pProgress, &Counter, fVerbose ); - if ( bFunc == NULL ) - { - if ( fVerbose ) - printf( "Constructing global BDDs is aborted.\n" ); - Abc_NtkFreeGlobalBdds( pNtk, 0 ); - Cudd_Quit( dd ); - return NULL; - } - bFunc = Cudd_NotCond( bFunc, Abc_ObjFaninC0(pObj) ); Cudd_Ref( bFunc ); - Abc_ObjSetGlobalBdd( pObj, bFunc ); - } - Extra_ProgressBarStop( pProgress ); - -/* - // derefence the intermediate BDDs - Abc_NtkForEachNode( pNtk, pObj, i ) - if ( pObj->pCopy ) - { - Cudd_RecursiveDeref( dd, (DdNode *)pObj->pCopy ); - pObj->pCopy = NULL; - } -*/ -/* - // make sure all nodes are derefed - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( pObj->pCopy != NULL ) - printf( "Abc_NtkBuildGlobalBdds() error: Node %d has BDD assigned\n", pObj->Id ); - if ( pObj->vFanouts.nSize > 0 ) - printf( "Abc_NtkBuildGlobalBdds() error: Node %d has refs assigned\n", pObj->Id ); - } -*/ - // reset references - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - pFanin->vFanouts.nSize++; - - // reorder one more time - if ( fReorder ) - { - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); - Cudd_AutodynDisable( dd ); - } -// Cudd_PrintInfo( dd, stdout ); - return dd; -} - -/**Function************************************************************* - - Synopsis [Derives the global BDD for one AIG node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_NodeGlobalBdds_rec( DdManager * dd, Abc_Obj_t * pNode, int nBddSizeMax, int fDropInternal, ProgressBar * pProgress, int * pCounter, int fVerbose ) -{ - DdNode * bFunc, * bFunc0, * bFunc1, * bFuncC; - int fDetectMuxes = 1; - assert( !Abc_ObjIsComplement(pNode) ); - if ( Cudd_ReadKeys(dd)-Cudd_ReadDead(dd) > (unsigned)nBddSizeMax ) - { - Extra_ProgressBarStop( pProgress ); - if ( fVerbose ) - printf( "The number of live nodes reached %d.\n", nBddSizeMax ); - fflush( stdout ); - return NULL; - } - // if the result is available return - if ( Abc_ObjGlobalBdd(pNode) == NULL ) - { - Abc_Obj_t * pNodeC, * pNode0, * pNode1; - pNode0 = Abc_ObjFanin0(pNode); - pNode1 = Abc_ObjFanin1(pNode); - // check for the special case when it is MUX/EXOR - if ( fDetectMuxes && - Abc_ObjGlobalBdd(pNode0) == NULL && Abc_ObjGlobalBdd(pNode1) == NULL && - Abc_ObjIsNode(pNode0) && Abc_ObjFanoutNum(pNode0) == 1 && - Abc_ObjIsNode(pNode1) && Abc_ObjFanoutNum(pNode1) == 1 && - Abc_NodeIsMuxType(pNode) ) - { - // deref the fanins - pNode0->vFanouts.nSize--; - pNode1->vFanouts.nSize--; - // recognize the MUX - pNodeC = Abc_NodeRecognizeMux( pNode, &pNode1, &pNode0 ); - assert( Abc_ObjFanoutNum(pNodeC) > 1 ); - // dereference the control once (the second time it will be derefed when BDDs are computed) - pNodeC->vFanouts.nSize--; - - // compute the result for all branches - bFuncC = Abc_NodeGlobalBdds_rec( dd, pNodeC, nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); - if ( bFuncC == NULL ) - return NULL; - Cudd_Ref( bFuncC ); - bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); - if ( bFunc0 == NULL ) - return NULL; - Cudd_Ref( bFunc0 ); - bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjRegular(pNode1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); - if ( bFunc1 == NULL ) - return NULL; - Cudd_Ref( bFunc1 ); - - // complement the branch BDDs - bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjIsComplement(pNode0) ); - bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjIsComplement(pNode1) ); - // get the final result - bFunc = Cudd_bddIte( dd, bFuncC, bFunc1, bFunc0 ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bFunc0 ); - Cudd_RecursiveDeref( dd, bFunc1 ); - Cudd_RecursiveDeref( dd, bFuncC ); - // add the number of used nodes - (*pCounter) += 3; - } - else - { - // compute the result for both branches - bFunc0 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,0), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); - if ( bFunc0 == NULL ) - return NULL; - Cudd_Ref( bFunc0 ); - bFunc1 = Abc_NodeGlobalBdds_rec( dd, Abc_ObjFanin(pNode,1), nBddSizeMax, fDropInternal, pProgress, pCounter, fVerbose ); - if ( bFunc1 == NULL ) - return NULL; - Cudd_Ref( bFunc1 ); - bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pNode) ); - bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pNode) ); - // get the final result - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bFunc0 ); - Cudd_RecursiveDeref( dd, bFunc1 ); - // add the number of used nodes - (*pCounter)++; - } - // set the result - assert( Abc_ObjGlobalBdd(pNode) == NULL ); - Abc_ObjSetGlobalBdd( pNode, bFunc ); - // increment the progress bar - if ( pProgress ) - Extra_ProgressBarUpdate( pProgress, *pCounter, NULL ); - } - // prepare the return value - bFunc = Abc_ObjGlobalBdd(pNode); - // dereference BDD at the node - if ( --pNode->vFanouts.nSize == 0 && fDropInternal ) - { - Cudd_Deref( bFunc ); - Abc_ObjSetGlobalBdd( pNode, NULL ); - } - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Frees the global BDDs of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdManager * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ) -{ - return Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, fFreeMan ); -} - -/**Function************************************************************* - - Synopsis [Returns the shared size of global BDDs of the COs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vFuncsGlob; - Abc_Obj_t * pObj; - int RetValue, i; - // complement the global functions - vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); - RetValue = Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncsGlob), Vec_PtrSize(vFuncsGlob) ); - Vec_PtrFree( vFuncsGlob ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Computes the BDD of the logic cone of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ) -{ - /* - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pNodeR; - DdManager * dd; - DdNode * bFunc; - double Result; - int i; - pNodeR = Abc_ObjRegular(pNode); - assert( Abc_NtkIsStrash(pNodeR->pNtk) ); - Abc_NtkCleanCopy( pNodeR->pNtk ); - // get the CIs in the support of the node - vNodes = Abc_NtkNodeSupport( pNodeR->pNtk, &pNodeR, 1 ); - // start the manager - dd = Cudd_Init( Vec_PtrSize(vNodes), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - // assign elementary BDDs for the CIs - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)dd->vars[i]; - // build the BDD of the cone - bFunc = Abc_NodeGlobalBdds_rec( dd, pNodeR, 10000000, 1, NULL, NULL, 1 ); Cudd_Ref( bFunc ); - bFunc = Cudd_NotCond( bFunc, pNode != pNodeR ); - // count minterms - Result = Cudd_CountMinterm( dd, bFunc, dd->size ); - // get the percentagle - Result *= 100.0; - for ( i = 0; i < dd->size; i++ ) - Result /= 2; - // clean up - Cudd_Quit( dd ); - Vec_PtrFree( vNodes ); - return Result; - */ - return 0.0; -} - - - - -/**Function************************************************************* - - Synopsis [Experiment with BDD-based representation of implications.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkBddImplicationTest() -{ - DdManager * dd; - DdNode * bImp, * bSum, * bTemp; - int nVars = 200; - int nImps = 200; - int i, clk; -clk = clock(); - dd = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynEnable( dd, CUDD_REORDER_SIFT ); - bSum = b0; Cudd_Ref( bSum ); - for ( i = 0; i < nImps; i++ ) - { - printf( "." ); - bImp = Cudd_bddAnd( dd, dd->vars[rand()%nVars], dd->vars[rand()%nVars] ); Cudd_Ref( bImp ); - bSum = Cudd_bddOr( dd, bTemp = bSum, bImp ); Cudd_Ref( bSum ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bImp ); - } - printf( "The BDD before = %d.\n", Cudd_DagSize(bSum) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SIFT, 1 ); - printf( "The BDD after = %d.\n", Cudd_DagSize(bSum) ); -PRT( "Time", clock() - clk ); - Cudd_RecursiveDeref( dd, bSum ); - Cudd_Quit( dd ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcOdc.c b/src/base/abci/abcOdc.c deleted file mode 100644 index d6e59328..00000000 --- a/src/base/abci/abcOdc.c +++ /dev/null @@ -1,1134 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcOdc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Scalable computation of observability don't-cares.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcOdc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define ABC_DC_MAX_NODES (1<<15) - -typedef unsigned short Odc_Lit_t; - -typedef struct Odc_Obj_t_ Odc_Obj_t; // 16 bytes -struct Odc_Obj_t_ -{ - Odc_Lit_t iFan0; // first fanin - Odc_Lit_t iFan1; // second fanin - Odc_Lit_t iNext; // next node in the hash table - unsigned short TravId; // the traversal ID - unsigned uData; // the computed data - unsigned uMask; // the variable mask -}; - -typedef struct Odc_Man_t_ Odc_Man_t; -struct Odc_Man_t_ -{ - // dont'-care parameters - int nVarsMax; // the max number of cut variables - int nLevels; // the number of ODC levels - int fVerbose; // the verbosiness flag - int fVeryVerbose;// the verbosiness flag to print per-node stats - int nPercCutoff; // cutoff percentage - - // windowing - Abc_Obj_t * pNode; // the node for windowing - Vec_Ptr_t * vLeaves; // the number of the cut - Vec_Ptr_t * vRoots; // the roots of the cut - Vec_Ptr_t * vBranches; // additional inputs - - // internal AIG package - // objects - int nPis; // number of PIs (nVarsMax + 32) - int nObjs; // number of objects (Const1, PIs, ANDs) - int nObjsAlloc; // number of objects allocated - Odc_Obj_t * pObjs; // objects - Odc_Lit_t iRoot; // the root object - unsigned short nTravIds; // the number of travIDs - // structural hashing - Odc_Lit_t * pTable; // hash table - int nTableSize; // hash table size - Vec_Int_t * vUsedSpots; // the used spots - - // truth tables - int nBits; // the number of bits - int nWords; // the number of words - Vec_Ptr_t * vTruths; // truth tables for each node - Vec_Ptr_t * vTruthsElem; // elementary truth tables for the PIs - unsigned * puTruth; // the place where the resulting truth table does - - // statistics - int nWins; // the number of windows processed - int nWinsEmpty; // the number of empty windows - int nSimsEmpty; // the number of empty simulation infos - int nQuantsOver; // the number of quantification overflows - int nWinsFinish; // the number of windows that finished - int nTotalDcs; // total percentage of DCs - - // runtime - int timeClean; // windowing - int timeWin; // windowing - int timeMiter; // computing the miter - int timeSim; // simulation - int timeQuant; // quantification - int timeTruth; // truth table - int timeTotal; // useful runtime - int timeAbort; // aborted runtime -}; - - -// quantity of different objects -static inline int Odc_PiNum( Odc_Man_t * p ) { return p->nPis; } -static inline int Odc_NodeNum( Odc_Man_t * p ) { return p->nObjs - p->nPis - 1; } -static inline int Odc_ObjNum( Odc_Man_t * p ) { return p->nObjs; } - -// complemented attributes of objects -static inline int Odc_IsComplement( Odc_Lit_t Lit ) { return Lit & (Odc_Lit_t)1; } -static inline Odc_Lit_t Odc_Regular( Odc_Lit_t Lit ) { return Lit & ~(Odc_Lit_t)1; } -static inline Odc_Lit_t Odc_Not( Odc_Lit_t Lit ) { return Lit ^ (Odc_Lit_t)1; } -static inline Odc_Lit_t Odc_NotCond( Odc_Lit_t Lit, int c ) { return Lit ^ (Odc_Lit_t)(c!=0); } - -// specialized Literals -static inline Odc_Lit_t Odc_Const0() { return 1; } -static inline Odc_Lit_t Odc_Const1() { return 0; } -static inline Odc_Lit_t Odc_Var( Odc_Man_t * p, int i ) { assert( i >= 0 && i < p->nPis ); return (i+1) << 1; } -static inline int Odc_IsConst( Odc_Lit_t Lit ) { return Lit < (Odc_Lit_t)2; } -static inline int Odc_IsTerm( Odc_Man_t * p, Odc_Lit_t Lit ) { return (int)(Lit>>1) <= p->nPis; } - -// accessing internal storage -static inline Odc_Obj_t * Odc_ObjNew( Odc_Man_t * p ) { assert( p->nObjs < p->nObjsAlloc ); return p->pObjs + p->nObjs++; } -static inline Odc_Lit_t Odc_Obj2Lit( Odc_Man_t * p, Odc_Obj_t * pObj ) { assert( pObj ); return (pObj - p->pObjs) << 1; } -static inline Odc_Obj_t * Odc_Lit2Obj( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) && (int)(Lit>>1) < p->nObjs ); return p->pObjs + (Lit>>1); } - -// fanins and their complements -static inline Odc_Lit_t Odc_ObjChild0( Odc_Obj_t * pObj ) { return pObj->iFan0; } -static inline Odc_Lit_t Odc_ObjChild1( Odc_Obj_t * pObj ) { return pObj->iFan1; } -static inline Odc_Lit_t Odc_ObjFanin0( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan0); } -static inline Odc_Lit_t Odc_ObjFanin1( Odc_Obj_t * pObj ) { return Odc_Regular(pObj->iFan1); } -static inline int Odc_ObjFaninC0( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan0); } -static inline int Odc_ObjFaninC1( Odc_Obj_t * pObj ) { return Odc_IsComplement(pObj->iFan1); } - -// traversal IDs -static inline void Odc_ManIncrementTravId( Odc_Man_t * p ) { p->nTravIds++; } -static inline void Odc_ObjSetTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } -static inline int Odc_ObjIsTravIdCurrent( Odc_Man_t * p, Odc_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); } - -// truth tables -static inline unsigned * Odc_ObjTruth( Odc_Man_t * p, Odc_Lit_t Lit ) { assert( !(Lit & 1) ); return Vec_PtrEntry(p->vTruths, Lit >> 1); } - -// iterators -#define Odc_ForEachPi( p, Lit, i ) \ - for ( i = 0; (i < Odc_PiNum(p)) && (((Lit) = Odc_Var(p, i)), 1); i++ ) -#define Odc_ForEachAnd( p, pObj, i ) \ - for ( i = 1 + Odc_CiNum(p); (i < Odc_ObjNum(p)) && ((pObj) = (p)->pObjs + i); i++ ) - - -// exported functions -extern Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ); -extern void Abc_NtkDontCareClear( Odc_Man_t * p ); -extern void Abc_NtkDontCareFree( Odc_Man_t * p ); -extern int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the don't-care manager.] - - Description [The parameters are the max number of cut variables, - the number of fanout levels used for the ODC computation, and verbosiness.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ) -{ - Odc_Man_t * p; - unsigned * pData; - int i, k; - p = ALLOC( Odc_Man_t, 1 ); - memset( p, 0, sizeof(Odc_Man_t) ); - assert( nVarsMax > 4 && nVarsMax < 16 ); - assert( nLevels > 0 && nLevels < 10 ); - - srand( 0xABC ); - - // dont'-care parameters - p->nVarsMax = nVarsMax; - p->nLevels = nLevels; - p->fVerbose = fVerbose; - p->fVeryVerbose = fVeryVerbose; - p->nPercCutoff = 10; - - // windowing - p->vRoots = Vec_PtrAlloc( 128 ); - p->vBranches = Vec_PtrAlloc( 128 ); - - // internal AIG package - // allocate room for objects - p->nObjsAlloc = ABC_DC_MAX_NODES; - p->pObjs = ALLOC( Odc_Obj_t, p->nObjsAlloc * sizeof(Odc_Obj_t) ); - p->nPis = nVarsMax + 32; - p->nObjs = 1 + p->nPis; - memset( p->pObjs, 0, p->nObjs * sizeof(Odc_Obj_t) ); - // set the PI masks - for ( i = 0; i < 32; i++ ) - p->pObjs[1 + p->nVarsMax + i].uMask = (1 << i); - // allocate hash table - p->nTableSize = p->nObjsAlloc/3 + 1; - p->pTable = ALLOC( Odc_Lit_t, p->nTableSize * sizeof(Odc_Lit_t) ); - memset( p->pTable, 0, p->nTableSize * sizeof(Odc_Lit_t) ); - p->vUsedSpots = Vec_IntAlloc( 1000 ); - - // truth tables - p->nWords = Abc_TruthWordNum( p->nVarsMax ); - p->nBits = p->nWords * 8 * sizeof(unsigned); - p->vTruths = Vec_PtrAllocSimInfo( p->nObjsAlloc, p->nWords ); - p->vTruthsElem = Vec_PtrAllocSimInfo( p->nVarsMax, p->nWords ); - - // set elementary truth tables - Abc_InfoFill( Vec_PtrEntry(p->vTruths, 0), p->nWords ); - for ( k = 0; k < p->nVarsMax; k++ ) - { -// pData = Odc_ObjTruth( p, Odc_Var(p, k) ); - pData = Vec_PtrEntry( p->vTruthsElem, k ); - Abc_InfoClear( pData, p->nWords ); - for ( i = 0; i < p->nBits; i++ ) - if ( i & (1 << k) ) - pData[i>>5] |= (1 << (i&31)); - } - - // set random truth table for the additional inputs - for ( k = p->nVarsMax; k < p->nPis; k++ ) - { - pData = Odc_ObjTruth( p, Odc_Var(p, k) ); - Abc_InfoRandom( pData, p->nWords ); - } - - // set the miter to the unused value - p->iRoot = 0xffff; - return p; -} - -/**Function************************************************************* - - Synopsis [Clears the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDontCareClear( Odc_Man_t * p ) -{ - int clk = clock(); - // clean the structural hashing table - if ( Vec_IntSize(p->vUsedSpots) > p->nTableSize/3 ) // more than one third - memset( p->pTable, 0, sizeof(Odc_Lit_t) * p->nTableSize ); - else - { - int iSpot, i; - Vec_IntForEachEntry( p->vUsedSpots, iSpot, i ) - p->pTable[iSpot] = 0; - } - Vec_IntClear( p->vUsedSpots ); - // reset the number of nodes - p->nObjs = 1 + p->nPis; - // reset the root node - p->iRoot = 0xffff; - -p->timeClean += clock() - clk; -} - -/**Function************************************************************* - - Synopsis [Frees the don't-care manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDontCareFree( Odc_Man_t * p ) -{ - if ( p->fVerbose ) - { - printf( "Wins = %5d. Empty = %5d. SimsEmpty = %5d. QuantOver = %5d. WinsFinish = %5d.\n", - p->nWins, p->nWinsEmpty, p->nSimsEmpty, p->nQuantsOver, p->nWinsFinish ); - printf( "Ave DCs per window = %6.2f %%. Ave DCs per finished window = %6.2f %%.\n", - 1.0*p->nTotalDcs/p->nWins, 1.0*p->nTotalDcs/p->nWinsFinish ); - printf( "Runtime stats of the ODC manager:\n" ); - PRT( "Cleaning ", p->timeClean ); - PRT( "Windowing ", p->timeWin ); - PRT( "Miter ", p->timeMiter ); - PRT( "Simulation ", p->timeSim ); - PRT( "Quantifying ", p->timeQuant ); - PRT( "Truth table ", p->timeTruth ); - PRT( "TOTAL ", p->timeTotal ); - PRT( "Aborted ", p->timeAbort ); - } - Vec_PtrFree( p->vRoots ); - Vec_PtrFree( p->vBranches ); - Vec_PtrFree( p->vTruths ); - Vec_PtrFree( p->vTruthsElem ); - Vec_IntFree( p->vUsedSpots ); - free( p->pObjs ); - free( p->pTable ); - free( p ); -} - - - -/**Function************************************************************* - - Synopsis [Marks the TFO of the collected nodes up to the given level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDontCareWinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanout; - int i; - if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit || pObj == pNode ) - return; - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return; - Abc_NodeSetTravIdCurrent( pObj ); - //////////////////////////////////////// - // try to reduce the runtime - if ( Abc_ObjFanoutNum(pObj) > 100 ) - return; - //////////////////////////////////////// - Abc_ObjForEachFanout( pObj, pFanout, i ) - Abc_NtkDontCareWinSweepLeafTfo_rec( pFanout, nLevelLimit, pNode ); -} - -/**Function************************************************************* - - Synopsis [Marks the TFO of the collected nodes up to the given level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDontCareWinSweepLeafTfo( Odc_Man_t * p ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkIncrementTravId( p->pNode->pNtk ); - Vec_PtrForEachEntry( p->vLeaves, pObj, i ) - Abc_NtkDontCareWinSweepLeafTfo_rec( pObj, p->pNode->Level + p->nLevels, p->pNode ); -} - -/**Function************************************************************* - - Synopsis [Recursively collects the roots.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDontCareWinCollectRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots ) -{ - Abc_Obj_t * pFanout; - int i; - assert( Abc_ObjIsNode(pObj) ); - assert( Abc_NodeIsTravIdCurrent(pObj) ); - // check if the node has all fanouts marked - Abc_ObjForEachFanout( pObj, pFanout, i ) - if ( !Abc_NodeIsTravIdCurrent(pFanout) ) - break; - // if some of the fanouts are unmarked, add the node to the root - if ( i < Abc_ObjFanoutNum(pObj) ) - { - Vec_PtrPushUnique( vRoots, pObj ); - return; - } - // otherwise, call recursively - Abc_ObjForEachFanout( pObj, pFanout, i ) - Abc_NtkDontCareWinCollectRoots_rec( pFanout, vRoots ); -} - -/**Function************************************************************* - - Synopsis [Collects the roots of the window.] - - Description [Roots of the window are the nodes that have at least - one fanout that it not in the TFO of the leaves.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDontCareWinCollectRoots( Odc_Man_t * p ) -{ - assert( !Abc_NodeIsTravIdCurrent(p->pNode) ); - // mark the node with the old traversal ID - Abc_NodeSetTravIdCurrent( p->pNode ); - // collect the roots - Vec_PtrClear( p->vRoots ); - Abc_NtkDontCareWinCollectRoots_rec( p->pNode, p->vRoots ); -} - -/**Function************************************************************* - - Synopsis [Recursively adds missing nodes and leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDontCareWinAddMissing_rec( Odc_Man_t * p, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i; - // skip the already collected leaves and branches - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return 1; - // if this is not an internal node - make it a new branch - if ( !Abc_NodeIsTravIdPrevious(pObj) || Abc_ObjIsCi(pObj) ) //|| (int)pObj->Level <= p->nLevLeaves ) - { - Abc_NodeSetTravIdCurrent( pObj ); - Vec_PtrPush( p->vBranches, pObj ); - return Vec_PtrSize(p->vBranches) <= 32; - } - // visit the fanins of the node - Abc_ObjForEachFanin( pObj, pFanin, i ) - if ( !Abc_NtkDontCareWinAddMissing_rec( p, pFanin ) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Adds to the window nodes and leaves in the TFI of the roots.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDontCareWinAddMissing( Odc_Man_t * p ) -{ - Abc_Obj_t * pObj; - int i; - // set the leaves - Abc_NtkIncrementTravId( p->pNode->pNtk ); - Vec_PtrForEachEntry( p->vLeaves, pObj, i ) - Abc_NodeSetTravIdCurrent( pObj ); - // explore from the roots - Vec_PtrClear( p->vBranches ); - Vec_PtrForEachEntry( p->vRoots, pObj, i ) - if ( !Abc_NtkDontCareWinAddMissing_rec( p, pObj ) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes window for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDontCareWindow( Odc_Man_t * p ) -{ - // mark the TFO of the collected nodes up to the given level (p->pNode->Level + p->nWinTfoMax) - Abc_NtkDontCareWinSweepLeafTfo( p ); - // find the roots of the window - Abc_NtkDontCareWinCollectRoots( p ); - if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode ) - { -// printf( "Empty window\n" ); - return 0; - } - // add the nodes in the TFI of the roots that are not yet in the window - if ( !Abc_NtkDontCareWinAddMissing( p ) ) - { -// printf( "Too many branches (%d)\n", Vec_PtrSize(p->vBranches) ); - return 0; - } - return 1; -} - - - - - -/**Function************************************************************* - - Synopsis [Performing hashing of two AIG Literals.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Odc_HashKey( Odc_Lit_t iFan0, Odc_Lit_t iFan1, int TableSize ) -{ - unsigned Key = 0; - Key ^= Odc_Regular(iFan0) * 7937; - Key ^= Odc_Regular(iFan1) * 2971; - Key ^= Odc_IsComplement(iFan0) * 911; - Key ^= Odc_IsComplement(iFan1) * 353; - return Key % TableSize; -} - -/**Function************************************************************* - - Synopsis [Checks if the given name node already exists in the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Odc_Lit_t * Odc_HashLookup( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) -{ - Odc_Obj_t * pObj; - Odc_Lit_t * pEntry; - unsigned uHashKey; - assert( iFan0 < iFan1 ); - // get the hash key for this node - uHashKey = Odc_HashKey( iFan0, iFan1, p->nTableSize ); - // remember the spot in the hash table that will be used - if ( p->pTable[uHashKey] == 0 ) - Vec_IntPush( p->vUsedSpots, uHashKey ); - // find the entry - for ( pEntry = p->pTable + uHashKey; *pEntry; pEntry = &pObj->iNext ) - { - pObj = Odc_Lit2Obj( p, *pEntry ); - if ( pObj->iFan0 == iFan0 && pObj->iFan1 == iFan1 ) - return pEntry; - } - return pEntry; -} - -/**Function************************************************************* - - Synopsis [Finds node by structural hashing or creates a new node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Odc_Lit_t Odc_And( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) -{ - Odc_Obj_t * pObj; - Odc_Lit_t * pEntry; - unsigned uMask0, uMask1; - int Temp; - // consider trivial cases - if ( iFan0 == iFan1 ) - return iFan0; - if ( iFan0 == Odc_Not(iFan1) ) - return Odc_Const0(); - if ( Odc_Regular(iFan0) == Odc_Const1() ) - return iFan0 == Odc_Const1() ? iFan1 : Odc_Const0(); - if ( Odc_Regular(iFan1) == Odc_Const1() ) - return iFan1 == Odc_Const1() ? iFan0 : Odc_Const0(); - // canonicize the fanin order - if ( iFan0 > iFan1 ) - Temp = iFan0, iFan0 = iFan1, iFan1 = Temp; - // check if a node with these fanins exists - pEntry = Odc_HashLookup( p, iFan0, iFan1 ); - if ( *pEntry ) - return *pEntry; - // create a new node - pObj = Odc_ObjNew( p ); - pObj->iFan0 = iFan0; - pObj->iFan1 = iFan1; - pObj->iNext = 0; - pObj->TravId = 0; - // set the mask - uMask0 = Odc_Lit2Obj(p, Odc_Regular(iFan0))->uMask; - uMask1 = Odc_Lit2Obj(p, Odc_Regular(iFan1))->uMask; - pObj->uMask = uMask0 | uMask1; - // add to the table - *pEntry = Odc_Obj2Lit( p, pObj ); - return *pEntry; -} - -/**Function************************************************************* - - Synopsis [Boolean OR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Odc_Lit_t Odc_Or( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) -{ - return Odc_Not( Odc_And(p, Odc_Not(iFan0), Odc_Not(iFan1)) ); -} - -/**Function************************************************************* - - Synopsis [Boolean XOR.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Odc_Lit_t Odc_Xor( Odc_Man_t * p, Odc_Lit_t iFan0, Odc_Lit_t iFan1 ) -{ - return Odc_Or( p, Odc_And(p, iFan0, Odc_Not(iFan1)), Odc_And(p, Odc_Not(iFan0), iFan1) ); -} - - - - - -/**Function************************************************************* - - Synopsis [Transfers the window into the AIG package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Abc_NtkDontCareTransfer_rec( Odc_Man_t * p, Abc_Obj_t * pNode, Abc_Obj_t * pPivot ) -{ - unsigned uData0, uData1; - Odc_Lit_t uLit0, uLit1, uRes0, uRes1; - assert( !Abc_ObjIsComplement(pNode) ); - // skip visited objects - if ( Abc_NodeIsTravIdCurrent(pNode) ) - return pNode->pCopy; - Abc_NodeSetTravIdCurrent(pNode); - assert( Abc_ObjIsNode(pNode) ); - // consider the case when the node is the pivot - if ( pNode == pPivot ) - return pNode->pCopy = (void *)((Odc_Const1() << 16) | Odc_Const0()); - // compute the cofactors - uData0 = (unsigned)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin0(pNode), pPivot ); - uData1 = (unsigned)Abc_NtkDontCareTransfer_rec( p, Abc_ObjFanin1(pNode), pPivot ); - // find the 0-cofactor - uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Abc_ObjFaninC0(pNode) ); - uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Abc_ObjFaninC1(pNode) ); - uRes0 = Odc_And( p, uLit0, uLit1 ); - // find the 1-cofactor - uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Abc_ObjFaninC0(pNode) ); - uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Abc_ObjFaninC1(pNode) ); - uRes1 = Odc_And( p, uLit0, uLit1 ); - // find the result - return pNode->pCopy = (void *)((uRes1 << 16) | uRes0); -} - -/**Function************************************************************* - - Synopsis [Transfers the window into the AIG package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDontCareTransfer( Odc_Man_t * p ) -{ - Abc_Obj_t * pObj; - Odc_Lit_t uRes0, uRes1; - Odc_Lit_t uLit; - unsigned uData; - int i; - Abc_NtkIncrementTravId( p->pNode->pNtk ); - // set elementary variables at the leaves - Vec_PtrForEachEntry( p->vLeaves, pObj, i ) - { - uLit = Odc_Var( p, i ); - pObj->pCopy = (void *)((uLit << 16) | uLit); - Abc_NodeSetTravIdCurrent(pObj); - } - // set elementary variables at the branched - Vec_PtrForEachEntry( p->vBranches, pObj, i ) - { - uLit = Odc_Var( p, i+p->nVarsMax ); - pObj->pCopy = (void *)((uLit << 16) | uLit); - Abc_NodeSetTravIdCurrent(pObj); - } - // compute the AIG for the window - p->iRoot = Odc_Const0(); - Vec_PtrForEachEntry( p->vRoots, pObj, i ) - { - uData = (unsigned)Abc_NtkDontCareTransfer_rec( p, pObj, p->pNode ); - // get the cofactors - uRes0 = uData & 0xffff; - uRes1 = uData >> 16; - // compute the miter -// assert( uRes0 != uRes1 ); // may be false if the node is redundant w.r.t. this root - uLit = Odc_Xor( p, uRes0, uRes1 ); - p->iRoot = Odc_Or( p, p->iRoot, uLit ); - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Recursively computes the pair of cofactors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Abc_NtkDontCareCofactors_rec( Odc_Man_t * p, Odc_Lit_t Lit, unsigned uMask ) -{ - Odc_Obj_t * pObj; - unsigned uData0, uData1; - Odc_Lit_t uLit0, uLit1, uRes0, uRes1; - assert( !Odc_IsComplement(Lit) ); - // skip visited objects - pObj = Odc_Lit2Obj( p, Lit ); - if ( Odc_ObjIsTravIdCurrent(p, pObj) ) - return pObj->uData; - Odc_ObjSetTravIdCurrent(p, pObj); - // skip objects out of the cone - if ( (pObj->uMask & uMask) == 0 ) - return pObj->uData = ((Lit << 16) | Lit); - // consider the case when the node is the var - if ( pObj->uMask == uMask && Odc_IsTerm(p, Lit) ) - return pObj->uData = ((Odc_Const1() << 16) | Odc_Const0()); - // compute the cofactors - uData0 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin0(pObj), uMask ); - uData1 = Abc_NtkDontCareCofactors_rec( p, Odc_ObjFanin1(pObj), uMask ); - // find the 0-cofactor - uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 & 0xffff), Odc_ObjFaninC0(pObj) ); - uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 & 0xffff), Odc_ObjFaninC1(pObj) ); - uRes0 = Odc_And( p, uLit0, uLit1 ); - // find the 1-cofactor - uLit0 = Odc_NotCond( (Odc_Lit_t)(uData0 >> 16), Odc_ObjFaninC0(pObj) ); - uLit1 = Odc_NotCond( (Odc_Lit_t)(uData1 >> 16), Odc_ObjFaninC1(pObj) ); - uRes1 = Odc_And( p, uLit0, uLit1 ); - // find the result - return pObj->uData = ((uRes1 << 16) | uRes0); -} - -/**Function************************************************************* - - Synopsis [Quantifies the branch variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDontCareQuantify( Odc_Man_t * p ) -{ - Odc_Lit_t uRes0, uRes1; - unsigned uData; - int i; - assert( p->iRoot < 0xffff ); - assert( Vec_PtrSize(p->vBranches) <= 32 ); // the mask size - for ( i = 0; i < Vec_PtrSize(p->vBranches); i++ ) - { - // compute the cofactors w.r.t. this variable - Odc_ManIncrementTravId( p ); - uData = Abc_NtkDontCareCofactors_rec( p, Odc_Regular(p->iRoot), (1 << i) ); - uRes0 = Odc_NotCond( (Odc_Lit_t)(uData & 0xffff), Odc_IsComplement(p->iRoot) ); - uRes1 = Odc_NotCond( (Odc_Lit_t)(uData >> 16), Odc_IsComplement(p->iRoot) ); - // quantify this variable existentially - p->iRoot = Odc_Or( p, uRes0, uRes1 ); - // check the limit - if ( Odc_ObjNum(p) > ABC_DC_MAX_NODES/2 ) - return 0; - } - assert( p->nObjs <= p->nObjsAlloc ); - return 1; -} - - - -/**Function************************************************************* - - Synopsis [Set elementary truth tables for PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDontCareSimulateSetElem2( Odc_Man_t * p ) -{ - unsigned * pData; - int i, k; - for ( k = 0; k < p->nVarsMax; k++ ) - { - pData = Odc_ObjTruth( p, Odc_Var(p, k) ); - Abc_InfoClear( pData, p->nWords ); - for ( i = 0; i < p->nBits; i++ ) - if ( i & (1 << k) ) - pData[i>>5] |= (1 << (i&31)); - } -} - -/**Function************************************************************* - - Synopsis [Set elementary truth tables for PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDontCareSimulateSetElem( Odc_Man_t * p ) -{ - unsigned * pData, * pData2; - int k; - for ( k = 0; k < p->nVarsMax; k++ ) - { - pData = Odc_ObjTruth( p, Odc_Var(p, k) ); - pData2 = Vec_PtrEntry( p->vTruthsElem, k ); - Abc_InfoCopy( pData, pData2, p->nWords ); - } -} - -/**Function************************************************************* - - Synopsis [Set random simulation words for PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDontCareSimulateSetRand( Odc_Man_t * p ) -{ - unsigned * pData; - int w, k, Number; - for ( w = 0; w < p->nWords; w++ ) - { - Number = rand(); - for ( k = 0; k < p->nVarsMax; k++ ) - { - pData = Odc_ObjTruth( p, Odc_Var(p, k) ); - pData[w] = (Number & (1<nWords; w++ ) - if ( puTruth[w] ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDontCareTruthOne( Odc_Man_t * p, Odc_Lit_t Lit ) -{ - Odc_Obj_t * pObj; - unsigned * pInfo, * pInfo1, * pInfo2; - int k, fComp1, fComp2; - assert( !Odc_IsComplement( Lit ) ); - assert( !Odc_IsTerm( p, Lit ) ); - // get the truth tables - pObj = Odc_Lit2Obj( p, Lit ); - pInfo = Odc_ObjTruth( p, Lit ); - pInfo1 = Odc_ObjTruth( p, Odc_ObjFanin0(pObj) ); - pInfo2 = Odc_ObjTruth( p, Odc_ObjFanin1(pObj) ); - fComp1 = Odc_ObjFaninC0( pObj ); - fComp2 = Odc_ObjFaninC1( pObj ); - // simulate - if ( fComp1 && fComp2 ) - for ( k = 0; k < p->nWords; k++ ) - pInfo[k] = ~pInfo1[k] & ~pInfo2[k]; - else if ( fComp1 && !fComp2 ) - for ( k = 0; k < p->nWords; k++ ) - pInfo[k] = ~pInfo1[k] & pInfo2[k]; - else if ( !fComp1 && fComp2 ) - for ( k = 0; k < p->nWords; k++ ) - pInfo[k] = pInfo1[k] & ~pInfo2[k]; - else // if ( fComp1 && fComp2 ) - for ( k = 0; k < p->nWords; k++ ) - pInfo[k] = pInfo1[k] & pInfo2[k]; -} - -/**Function************************************************************* - - Synopsis [Computes the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDontCareSimulate_rec( Odc_Man_t * p, Odc_Lit_t Lit ) -{ - Odc_Obj_t * pObj; - assert( !Odc_IsComplement(Lit) ); - // skip terminals - if ( Odc_IsTerm(p, Lit) ) - return; - // skip visited objects - pObj = Odc_Lit2Obj( p, Lit ); - if ( Odc_ObjIsTravIdCurrent(p, pObj) ) - return; - Odc_ObjSetTravIdCurrent(p, pObj); - // call recursively - Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin0(pObj) ); - Abc_NtkDontCareSimulate_rec( p, Odc_ObjFanin1(pObj) ); - // construct the truth table - Abc_NtkDontCareTruthOne( p, Lit ); -} - -/**Function************************************************************* - - Synopsis [Computes the truth table of the care set.] - - Description [Returns the number of ones in the simulation info.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDontCareSimulate( Odc_Man_t * p, unsigned * puTruth ) -{ - Odc_ManIncrementTravId( p ); - Abc_NtkDontCareSimulate_rec( p, Odc_Regular(p->iRoot) ); - Abc_InfoCopy( puTruth, Odc_ObjTruth(p, Odc_Regular(p->iRoot)), p->nWords ); - if ( Odc_IsComplement(p->iRoot) ) - Abc_InfoNot( puTruth, p->nWords ); - return Extra_TruthCountOnes( puTruth, p->nVarsMax ); -} - -/**Function************************************************************* - - Synopsis [Computes the truth table of the care set.] - - Description [Returns the number of ones in the simulation info.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDontCareSimulateBefore( Odc_Man_t * p, unsigned * puTruth ) -{ - int nIters = 2; - int nRounds, Counter, r; - // decide how many rounds to simulate - nRounds = p->nBits / p->nWords; - Counter = 0; - for ( r = 0; r < nIters; r++ ) - { - Abc_NtkDontCareSimulateSetRand( p ); - Abc_NtkDontCareSimulate( p, puTruth ); - Counter += Abc_NtkDontCareCountMintsWord( p, puTruth ); - } - // normalize - Counter = Counter * nRounds / nIters; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Computes ODCs for the node in terms of the cut variables.] - - Description [Returns the number of don't care minterms in the truth table. - In particular, this procedure returns 0 if there is no don't-cares.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ) -{ - int nMints, RetValue; - int clk, clkTotal = clock(); - - p->nWins++; - - // set the parameters - assert( !Abc_ObjIsComplement(pNode) ); - assert( Abc_ObjIsNode(pNode) ); - assert( Vec_PtrSize(vLeaves) <= p->nVarsMax ); - p->vLeaves = vLeaves; - p->pNode = pNode; - - // compute the window -clk = clock(); - RetValue = Abc_NtkDontCareWindow( p ); -p->timeWin += clock() - clk; - if ( !RetValue ) - { -p->timeAbort += clock() - clkTotal; - Abc_InfoFill( puTruth, p->nWords ); - p->nWinsEmpty++; - return 0; - } - - if ( p->fVeryVerbose ) - { - printf( " %5d : ", pNode->Id ); - printf( "Leaf = %2d ", Vec_PtrSize(p->vLeaves) ); - printf( "Root = %2d ", Vec_PtrSize(p->vRoots) ); - printf( "Bran = %2d ", Vec_PtrSize(p->vBranches) ); - printf( " | " ); - } - - // transfer the window into the AIG package -clk = clock(); - Abc_NtkDontCareTransfer( p ); -p->timeMiter += clock() - clk; - - // simulate to estimate the amount of don't-cares -clk = clock(); - nMints = Abc_NtkDontCareSimulateBefore( p, puTruth ); -p->timeSim += clock() - clk; - if ( p->fVeryVerbose ) - { - printf( "AIG = %5d ", Odc_NodeNum(p) ); - printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits ); - } - - // if there is less then the given percentage of don't-cares, skip - if ( 100.0 * (p->nBits - nMints) / p->nBits < 1.0 * p->nPercCutoff ) - { -p->timeAbort += clock() - clkTotal; - if ( p->fVeryVerbose ) - printf( "Simulation cutoff.\n" ); - Abc_InfoFill( puTruth, p->nWords ); - p->nSimsEmpty++; - return 0; - } - - // quantify external variables -clk = clock(); - RetValue = Abc_NtkDontCareQuantify( p ); -p->timeQuant += clock() - clk; - if ( !RetValue ) - { -p->timeAbort += clock() - clkTotal; - if ( p->fVeryVerbose ) - printf( "=== Overflow! ===\n" ); - Abc_InfoFill( puTruth, p->nWords ); - p->nQuantsOver++; - return 0; - } - - // get the truth table -clk = clock(); - Abc_NtkDontCareSimulateSetElem( p ); - nMints = Abc_NtkDontCareSimulate( p, puTruth ); -p->timeTruth += clock() - clk; - if ( p->fVeryVerbose ) - { - printf( "AIG = %5d ", Odc_NodeNum(p) ); - printf( "%6.2f %% ", 100.0 * (p->nBits - nMints) / p->nBits ); - printf( "\n" ); - } -p->timeTotal += clock() - clkTotal; - p->nWinsFinish++; - p->nTotalDcs += (int)(100.0 * (p->nBits - nMints) / p->nBits); - return nMints; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcOrder.c b/src/base/abci/abcOrder.c deleted file mode 100644 index 04417f77..00000000 --- a/src/base/abci/abcOrder.c +++ /dev/null @@ -1,131 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcOrder.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Exploring static BDD variable orders.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Changes the order of primary inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ) -{ - Vec_Ptr_t * vSupp; - vSupp = Abc_NtkSupport( pNtk ); - Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse ); - Vec_PtrFree( vSupp ); -} - -/**Function************************************************************* - - Synopsis [Implements the given variable order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ) -{ - char Buffer[1000]; - FILE * pFile; - Vec_Ptr_t * vSupp; - Abc_Obj_t * pObj; - pFile = fopen( pFileName, "r" ); - vSupp = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) ); - while ( fscanf( pFile, "%s", Buffer ) == 1 ) - { - pObj = Abc_NtkFindCi( pNtk, Buffer ); - if ( pObj == NULL || !Abc_ObjIsCi(pObj) ) - { - printf( "Name \"%s\" is not a PI name. Cannot use this order.\n", Buffer ); - Vec_PtrFree( vSupp ); - fclose( pFile ); - return; - } - Vec_PtrPush( vSupp, pObj ); - } - fclose( pFile ); - if ( Vec_PtrSize(vSupp) != Abc_NtkCiNum(pNtk) ) - { - printf( "The number of names in the order (%d) is not the same as the number of PIs (%d).\n", Vec_PtrSize(vSupp), Abc_NtkCiNum(pNtk) ); - Vec_PtrFree( vSupp ); - return; - } - Abc_NtkChangeCiOrder( pNtk, vSupp, fReverse ); - Vec_PtrFree( vSupp ); -} - -/**Function************************************************************* - - Synopsis [Changes the order of primary inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkChangeCiOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vSupp, int fReverse ) -{ - Abc_Obj_t * pObj; - int i; - assert( Vec_PtrSize(vSupp) == Abc_NtkCiNum(pNtk) ); - // order CIs using the array - if ( fReverse ) - Vec_PtrForEachEntry( vSupp, pObj, i ) - Vec_PtrWriteEntry( pNtk->vCis, Vec_PtrSize(vSupp)-1-i, pObj ); - else - Vec_PtrForEachEntry( vSupp, pObj, i ) - Vec_PtrWriteEntry( pNtk->vCis, i, pObj ); - // order PIs accordingly - Vec_PtrClear( pNtk->vPis ); - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjIsPi(pObj) ) - Vec_PtrPush( pNtk->vPis, pObj ); -// Abc_NtkForEachCi( pNtk, pObj, i ) -// printf( "%s ", Abc_ObjName(pObj) ); -// printf( "\n" ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcPart.c b/src/base/abci/abcPart.c deleted file mode 100644 index 85c4e918..00000000 --- a/src/base/abci/abcPart.c +++ /dev/null @@ -1,1205 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcPart.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Output partitioning package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcPart.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Supp_Man_t_ Supp_Man_t; -struct Supp_Man_t_ -{ - int nChunkSize; // the size of one chunk of memory (~1 Mb) - int nStepSize; // the step size in saving memory (~64 bytes) - char * pFreeBuf; // the pointer to free memory - int nFreeSize; // the size of remaining free memory - Vec_Ptr_t * vMemory; // the memory allocated - Vec_Ptr_t * vFree; // the vector of free pieces of memory -}; - -typedef struct Supp_One_t_ Supp_One_t; -struct Supp_One_t_ -{ - int nRefs; // the number of references - int nOuts; // the number of outputs - int nOutsAlloc; // the array size - int pOuts[0]; // the array of outputs -}; - -static inline int Supp_SizeType( int nSize, int nStepSize ) { return nSize / nStepSize + ((nSize % nStepSize) > 0); } -static inline char * Supp_OneNext( char * pPart ) { return *((char **)pPart); } -static inline void Supp_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Supp_Man_t * Supp_ManStart( int nChunkSize, int nStepSize ) -{ - Supp_Man_t * p; - p = ALLOC( Supp_Man_t, 1 ); - memset( p, 0, sizeof(Supp_Man_t) ); - p->nChunkSize = nChunkSize; - p->nStepSize = nStepSize; - p->vMemory = Vec_PtrAlloc( 1000 ); - p->vFree = Vec_PtrAlloc( 1000 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Supp_ManStop( Supp_Man_t * p ) -{ - void * pMemory; - int i; - Vec_PtrForEachEntry( p->vMemory, pMemory, i ) - free( pMemory ); - Vec_PtrFree( p->vMemory ); - Vec_PtrFree( p->vFree ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Fetches the memory entry of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Supp_ManFetch( Supp_Man_t * p, int nSize ) -{ - int Type, nSizeReal; - char * pMemory; - assert( nSize > 0 ); - Type = Supp_SizeType( nSize, p->nStepSize ); - Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); - if ( pMemory = Vec_PtrEntry( p->vFree, Type ) ) - { - Vec_PtrWriteEntry( p->vFree, Type, Supp_OneNext(pMemory) ); - return pMemory; - } - nSizeReal = p->nStepSize * Type; - if ( p->nFreeSize < nSizeReal ) - { - p->pFreeBuf = ALLOC( char, p->nChunkSize ); - p->nFreeSize = p->nChunkSize; - Vec_PtrPush( p->vMemory, p->pFreeBuf ); - } - assert( p->nFreeSize >= nSizeReal ); - pMemory = p->pFreeBuf; - p->pFreeBuf += nSizeReal; - p->nFreeSize -= nSizeReal; - return pMemory; -} - -/**Function************************************************************* - - Synopsis [Recycles the memory entry of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Supp_ManRecycle( Supp_Man_t * p, char * pMemory, int nSize ) -{ - int Type; - Type = Supp_SizeType( nSize, p->nStepSize ); - Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); - Supp_OneSetNext( pMemory, Vec_PtrEntry(p->vFree, Type) ); - Vec_PtrWriteEntry( p->vFree, Type, pMemory ); -} - -/**Function************************************************************* - - Synopsis [Fetches the memory entry of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Supp_One_t * Supp_ManFetchEntry( Supp_Man_t * p, int nWords, int nRefs ) -{ - Supp_One_t * pPart; - pPart = (Supp_One_t *)Supp_ManFetch( p, sizeof(Supp_One_t) + sizeof(int) * nWords ); - pPart->nRefs = nRefs; - pPart->nOuts = 0; - pPart->nOutsAlloc = nWords; - return pPart; -} - -/**Function************************************************************* - - Synopsis [Recycles the memory entry of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Supp_ManRecycleEntry( Supp_Man_t * p, Supp_One_t * pEntry ) -{ - assert( pEntry->nOuts <= pEntry->nOutsAlloc ); - assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 ); - Supp_ManRecycle( p, (char *)pEntry, sizeof(Supp_One_t) + sizeof(int) * pEntry->nOutsAlloc ); -} - -/**Function************************************************************* - - Synopsis [Merges two entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Supp_One_t * Supp_ManMergeEntry( Supp_Man_t * pMan, Supp_One_t * p1, Supp_One_t * p2, int nRefs ) -{ - Supp_One_t * p = Supp_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs ); - int * pBeg1 = p1->pOuts; - int * pBeg2 = p2->pOuts; - int * pBeg = p->pOuts; - int * pEnd1 = p1->pOuts + p1->nOuts; - int * pEnd2 = p2->pOuts + p2->nOuts; - while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) - { - if ( *pBeg1 == *pBeg2 ) - *pBeg++ = *pBeg1++, pBeg2++; - else if ( *pBeg1 < *pBeg2 ) - *pBeg++ = *pBeg1++; - else - *pBeg++ = *pBeg2++; - } - while ( pBeg1 < pEnd1 ) - *pBeg++ = *pBeg1++; - while ( pBeg2 < pEnd2 ) - *pBeg++ = *pBeg2++; - p->nOuts = pBeg - p->pOuts; - assert( p->nOuts <= p->nOutsAlloc ); - assert( p->nOuts >= p1->nOuts ); - assert( p->nOuts >= p2->nOuts ); - return p; -} - -/**Function************************************************************* - - Synopsis [Tranfers the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Supp_ManTransferEntry( Supp_One_t * p ) -{ - Vec_Int_t * vSupp; - int i; - vSupp = Vec_IntAlloc( p->nOuts ); - for ( i = 0; i < p->nOuts; i++ ) - Vec_IntPush( vSupp, p->pOuts[i] ); - return vSupp; -} - -/**Function************************************************************* - - Synopsis [Computes supports of the POs in the multi-output AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkDfsNatural( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pNext; - int i, k; - assert( Abc_NtkIsStrash(pNtk) ); - vNodes = Vec_PtrAlloc( Abc_NtkObjNum(pNtk) ); - Abc_NtkIncrementTravId( pNtk ); - // add the constant-1 nodes - pObj = Abc_AigConst1(pNtk); - Abc_NodeSetTravIdCurrent( pObj ); - Vec_PtrPush( vNodes, pObj ); - // add the CIs/nodes/COs in the topological order - Abc_NtkForEachNode( pNtk, pObj, i ) - { - // check the fanins and add CIs - Abc_ObjForEachFanin( pObj, pNext, k ) - if ( Abc_ObjIsCi(pNext) && !Abc_NodeIsTravIdCurrent(pNext) ) - { - Abc_NodeSetTravIdCurrent( pNext ); - Vec_PtrPush( vNodes, pNext ); - } - // add the node - Vec_PtrPush( vNodes, pObj ); - // check the fanouts and add COs - Abc_ObjForEachFanout( pObj, pNext, k ) - if ( Abc_ObjIsCo(pNext) && !Abc_NodeIsTravIdCurrent(pNext) ) - { - Abc_NodeSetTravIdCurrent( pNext ); - Vec_PtrPush( vNodes, pNext ); - } - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes supports of the POs.] - - Description [Returns the ptr-vector of int-vectors.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkComputeSupportsSmart( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vSupports; - Vec_Ptr_t * vNodes; - Vec_Int_t * vSupp; - Supp_Man_t * p; - Supp_One_t * pPart0, * pPart1; - Abc_Obj_t * pObj; - int i; - // set the number of PIs/POs - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pNext = (Abc_Obj_t *)i; - Abc_NtkForEachCo( pNtk, pObj, i ) - pObj->pNext = (Abc_Obj_t *)i; - // start the support computation manager - p = Supp_ManStart( 1 << 20, 1 << 6 ); - // consider objects in the topological order - vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); - Abc_NtkCleanCopy(pNtk); - // order the nodes so that the PIs and POs follow naturally - vNodes = Abc_NtkDfsNatural( pNtk ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - if ( Abc_ObjIsNode(pObj) ) - { - pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy; - pPart1 = (Supp_One_t *)Abc_ObjFanin1(pObj)->pCopy; - pObj->pCopy = (Abc_Obj_t *)Supp_ManMergeEntry( p, pPart0, pPart1, Abc_ObjFanoutNum(pObj) ); - assert( pPart0->nRefs > 0 ); - if ( --pPart0->nRefs == 0 ) - Supp_ManRecycleEntry( p, pPart0 ); - assert( pPart1->nRefs > 0 ); - if ( --pPart1->nRefs == 0 ) - Supp_ManRecycleEntry( p, pPart1 ); - continue; - } - if ( Abc_ObjIsCo(pObj) ) - { - pPart0 = (Supp_One_t *)Abc_ObjFanin0(pObj)->pCopy; - // only save the CO if it is non-trivial - if ( Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) - { - vSupp = Supp_ManTransferEntry(pPart0); - Vec_IntPush( vSupp, (int)pObj->pNext ); - Vec_PtrPush( vSupports, vSupp ); - } - assert( pPart0->nRefs > 0 ); - if ( --pPart0->nRefs == 0 ) - Supp_ManRecycleEntry( p, pPart0 ); - continue; - } - if ( Abc_ObjIsCi(pObj) ) - { - if ( Abc_ObjFanoutNum(pObj) ) - { - pPart0 = (Supp_One_t *)Supp_ManFetchEntry( p, 1, Abc_ObjFanoutNum(pObj) ); - pPart0->pOuts[ pPart0->nOuts++ ] = (int)pObj->pNext; - pObj->pCopy = (Abc_Obj_t *)pPart0; - } - continue; - } - if ( pObj == Abc_AigConst1(pNtk) ) - { - if ( Abc_ObjFanoutNum(pObj) ) - pObj->pCopy = (Abc_Obj_t *)Supp_ManFetchEntry( p, 0, Abc_ObjFanoutNum(pObj) ); - continue; - } - assert( 0 ); - } - Vec_PtrFree( vNodes ); -//printf( "Memory usage = %d Mb.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) ); - Supp_ManStop( p ); - // sort supports by size - Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); - // clear the number of PIs/POs - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pNext = NULL; - Abc_NtkForEachCo( pNtk, pObj, i ) - pObj->pNext = NULL; -/* - Vec_PtrForEachEntry( vSupports, vSupp, i ) - printf( "%d ", Vec_IntSize(vSupp) ); - printf( "\n" ); -*/ - return vSupports; -} - - -/**Function************************************************************* - - Synopsis [Computes supports of the POs using naive method.] - - Description [Returns the ptr-vector of int-vectors.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkComputeSupportsNaive( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vSupp, * vSupports; - Vec_Int_t * vSuppI; - Abc_Obj_t * pObj, * pTemp; - int i, k; - // set the PI numbers - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pNext = (void *)i; - // save the CI numbers - vSupports = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - if ( !Abc_ObjIsNode(Abc_ObjFanin0(pObj)) ) - continue; - vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); - vSuppI = (Vec_Int_t *)vSupp; - Vec_PtrForEachEntry( vSupp, pTemp, k ) - Vec_IntWriteEntry( vSuppI, k, (int)pTemp->pNext ); - Vec_IntSort( vSuppI, 0 ); - // append the number of this output - Vec_IntPush( vSuppI, i ); - // save the support in the vector - Vec_PtrPush( vSupports, vSuppI ); - } - // clean the CI numbers - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pNext = NULL; - // sort supports by size - Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); -/* - Vec_PtrForEachEntry( vSupports, vSuppI, i ) - printf( "%d ", Vec_IntSize(vSuppI) ); - printf( "\n" ); -*/ - return vSupports; -} - -/**Function************************************************************* - - Synopsis [Start bitwise support representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Abc_NtkSuppCharStart( Vec_Int_t * vOne, int nPis ) -{ - unsigned * pBuffer; - int i, Entry; - int nWords = Abc_BitWordNum(nPis); - pBuffer = ALLOC( unsigned, nWords ); - memset( pBuffer, 0, sizeof(unsigned) * nWords ); - Vec_IntForEachEntry( vOne, Entry, i ) - { - assert( Entry < nPis ); - Abc_InfoSetBit( pBuffer, Entry ); - } - return pBuffer; -} - -/**Function************************************************************* - - Synopsis [Add to bitwise support representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis ) -{ - int i, Entry; - Vec_IntForEachEntry( vOne, Entry, i ) - { - assert( Entry < nPis ); - Abc_InfoSetBit( pBuffer, Entry ); - } -} - -/**Function************************************************************* - - Synopsis [Find the common variables using bitwise support representation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne ) -{ - int i, Entry, nCommon = 0; - Vec_IntForEachEntry( vOne, Entry, i ) - nCommon += Abc_InfoHasBit(pBuffer, Entry); - return nCommon; -} - -/**Function************************************************************* - - Synopsis [Find the best partition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsChar, int nSuppSizeLimit, Vec_Int_t * vOne ) -{ -/* - Vec_Int_t * vPartSupp, * vPart; - double Attract, Repulse, Cost, CostBest; - int i, nCommon, iBest; - iBest = -1; - CostBest = 0.0; - Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i ) - { - vPart = Vec_PtrEntry( vPartsAll, i ); - if ( nPartSizeLimit > 0 && Vec_IntSize(vPart) >= nPartSizeLimit ) - continue; - nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne ); - if ( nCommon == 0 ) - continue; - if ( nCommon == Vec_IntSize(vOne) ) - return i; - Attract = 1.0 * nCommon / Vec_IntSize(vOne); - if ( Vec_IntSize(vPartSupp) < 100 ) - Repulse = 1.0; - else - Repulse = log10( Vec_IntSize(vPartSupp) / 10.0 ); - Cost = pow( Attract, pow(Repulse, 5.0) ); - if ( CostBest < Cost ) - { - CostBest = Cost; - iBest = i; - } - } - if ( CostBest < 0.6 ) - return -1; - return iBest; -*/ - - Vec_Int_t * vPartSupp;//, * vPart; - int Attract, Repulse, Value, ValueBest; - int i, nCommon, iBest; -// int nCommon2; - iBest = -1; - ValueBest = 0; - Vec_PtrForEachEntry( vPartSuppsAll, vPartSupp, i ) - { - // skip partitions with too many outputs -// vPart = Vec_PtrEntry( vPartsAll, i ); -// if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit ) -// continue; - // find the number of common variables between this output and the partitions -// nCommon2 = Vec_IntTwoCountCommon( vPartSupp, vOne ); - nCommon = Abc_NtkSuppCharCommon( Vec_PtrEntry(vPartSuppsChar, i), vOne ); -// assert( nCommon2 == nCommon ); - // if no common variables, continue searching - if ( nCommon == 0 ) - continue; - // if all variables are common, the best partition if found - if ( nCommon == Vec_IntSize(vOne) ) - return i; - // skip partitions whose size exceeds the limit - if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit ) - continue; - // figure out might be the good partition for this one - Attract = 1000 * nCommon / Vec_IntSize(vOne); - if ( Vec_IntSize(vPartSupp) < 100 ) - Repulse = 1; - else - Repulse = 1+Extra_Base2Log(Vec_IntSize(vPartSupp)-100); - Value = Attract/Repulse; - if ( ValueBest < Value ) - { - ValueBest = Value; - iBest = i; - } - } - if ( ValueBest < 75 ) - return -1; - return iBest; -} - -/**Function************************************************************* - - Synopsis [Perform the smart partitioning.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPartitionPrint( Abc_Ntk_t * pNtk, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll ) -{ - Vec_Int_t * vOne; - int i, nOutputs, Counter; - - Counter = 0; - Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) - { - nOutputs = Vec_IntSize(Vec_PtrEntry(vPartsAll, i)); - printf( "%d=(%d,%d) ", i, Vec_IntSize(vOne), nOutputs ); - Counter += nOutputs; - if ( i == Vec_PtrSize(vPartsAll) - 1 ) - break; - } -// assert( Counter == Abc_NtkCoNum(pNtk) ); - printf( "\nTotal = %d. Outputs = %d.\n", Counter, Abc_NtkCoNum(pNtk) ); -} - -/**Function************************************************************* - - Synopsis [Perform the smart partitioning.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit ) -{ - Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; - int i, iPart; - - if ( nSuppSizeLimit == 0 ) - nSuppSizeLimit = 200; - - // pack smaller partitions into larger blocks - iPart = 0; - vPart = vPartSupp = NULL; - Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) - { - if ( Vec_IntSize(vOne) < nSuppSizeLimit ) - { - if ( vPartSupp == NULL ) - { - assert( vPart == NULL ); - vPartSupp = Vec_IntDup(vOne); - vPart = Vec_PtrEntry(vPartsAll, i); - } - else - { - vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); - Vec_IntFree( vTemp ); - vPart = Vec_IntTwoMerge( vTemp = vPart, Vec_PtrEntry(vPartsAll, i) ); - Vec_IntFree( vTemp ); - Vec_IntFree( Vec_PtrEntry(vPartsAll, i) ); - } - if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit ) - continue; - } - else - vPart = Vec_PtrEntry(vPartsAll, i); - // add the partition - Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); - vPart = NULL; - if ( vPartSupp ) - { - Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) ); - Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); - vPartSupp = NULL; - } - iPart++; - } - // add the last one - if ( vPart ) - { - Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); - vPart = NULL; - - assert( vPartSupp != NULL ); - Vec_IntFree( Vec_PtrEntry(vPartSuppsAll, iPart) ); - Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); - vPartSupp = NULL; - iPart++; - } - Vec_PtrShrink( vPartsAll, iPart ); - Vec_PtrShrink( vPartsAll, iPart ); -} - -/**Function************************************************************* - - Synopsis [Perform the smart partitioning.] - - Description [Returns the ptr-vector of int-vectors.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nSuppSizeLimit, int fVerbose ) -{ - ProgressBar * pProgress; - Vec_Ptr_t * vPartSuppsChar; - Vec_Ptr_t * vSupps, * vPartsAll, * vPartsAll2, * vPartSuppsAll; - Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; - int i, iPart, iOut, clk, clk2, timeFind = 0; - - // compute the supports for all outputs -clk = clock(); -// vSupps = Abc_NtkComputeSupportsNaive( pNtk ); - vSupps = Abc_NtkComputeSupportsSmart( pNtk ); -if ( fVerbose ) -{ -PRT( "Supps", clock() - clk ); -} - // start char-based support representation - vPartSuppsChar = Vec_PtrAlloc( 1000 ); - - // create partitions -clk = clock(); - vPartsAll = Vec_PtrAlloc( 256 ); - vPartSuppsAll = Vec_PtrAlloc( 256 ); - pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vSupps) ); - Vec_PtrForEachEntry( vSupps, vOne, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); -// if ( i % 1000 == 0 ) -// printf( "CIs = %6d. COs = %6d. Processed = %6d (out of %6d). Parts = %6d.\r", -// Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), i, Vec_PtrSize(vSupps), Vec_PtrSize(vPartsAll) ); - // get the output number - iOut = Vec_IntPop(vOne); - // find closely matching part -clk2 = clock(); - iPart = Abc_NtkPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsChar, nSuppSizeLimit, vOne ); -timeFind += clock() - clk2; - if ( iPart == -1 ) - { - // create new partition - vPart = Vec_IntAlloc( 32 ); - Vec_IntPush( vPart, iOut ); - // create new partition support - vPartSupp = Vec_IntDup( vOne ); - // add this partition and its support - Vec_PtrPush( vPartsAll, vPart ); - Vec_PtrPush( vPartSuppsAll, vPartSupp ); - - Vec_PtrPush( vPartSuppsChar, Abc_NtkSuppCharStart(vOne, Abc_NtkCiNum(pNtk)) ); - } - else - { - // add output to this partition - vPart = Vec_PtrEntry( vPartsAll, iPart ); - Vec_IntPush( vPart, iOut ); - // merge supports - vPartSupp = Vec_PtrEntry( vPartSuppsAll, iPart ); - vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); - Vec_IntFree( vTemp ); - // reinsert new support - Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); - - Abc_NtkSuppCharAdd( Vec_PtrEntry(vPartSuppsChar, iPart), vOne, Abc_NtkCiNum(pNtk) ); - } - } - Extra_ProgressBarStop( pProgress ); - - // stop char-based support representation - Vec_PtrForEachEntry( vPartSuppsChar, vTemp, i ) - free( vTemp ); - Vec_PtrFree( vPartSuppsChar ); - -//printf( "\n" ); -if ( fVerbose ) -{ -PRT( "Parts", clock() - clk ); -//PRT( "Find ", timeFind ); -} - -clk = clock(); - // remember number of supports - Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) - Vec_IntPush( vOne, i ); - // sort the supports in the decreasing order - Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 ); - // reproduce partitions - vPartsAll2 = Vec_PtrAlloc( 256 ); - Vec_PtrForEachEntry( vPartSuppsAll, vOne, i ) - Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) ); - Vec_PtrFree( vPartsAll ); - vPartsAll = vPartsAll2; - - // compact small partitions -// Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll ); - Abc_NtkPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit ); - -if ( fVerbose ) -{ -PRT( "Comps", clock() - clk ); -} - if ( fVerbose ) - printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) ); -// Abc_NtkPartitionPrint( pNtk, vPartsAll, vPartSuppsAll ); - - // cleanup - Vec_VecFree( (Vec_Vec_t *)vSupps ); - Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll ); -/* - // converts from intergers to nodes - Vec_PtrForEachEntry( vPartsAll, vPart, iPart ) - { - vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) ); - Vec_IntForEachEntry( vPart, iOut, i ) - Vec_PtrPush( vPartPtr, Abc_NtkCo(pNtk, iOut) ); - Vec_IntFree( vPart ); - Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr ); - } -*/ - return vPartsAll; -} - -/**Function************************************************************* - - Synopsis [Perform the naive partitioning.] - - Description [Returns the ptr-vector of int-vectors.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkPartitionNaive( Abc_Ntk_t * pNtk, int nPartSize ) -{ - Vec_Ptr_t * vParts; - Abc_Obj_t * pObj; - int nParts, i; - nParts = (Abc_NtkCoNum(pNtk) / nPartSize) + ((Abc_NtkCoNum(pNtk) % nPartSize) > 0); - vParts = (Vec_Ptr_t *)Vec_VecStart( nParts ); - Abc_NtkForEachCo( pNtk, pObj, i ) - Vec_IntPush( Vec_PtrEntry(vParts, i / nPartSize), i ); - return vParts; -} - -/**Function************************************************************* - - Synopsis [Converts from intergers to pointers for the given network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOutsPtr ) -{ - int Out, i; - Vec_PtrClear( vOutsPtr ); - Vec_IntForEachEntry( vOuts, Out, i ) - Vec_PtrPush( vOutsPtr, Abc_NtkCo(pNtk, Out) ); -} - -/**Function************************************************************* - - Synopsis [Returns representative of the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkPartStitchFindRepr_rec( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pRepr; - pRepr = Vec_PtrEntry( vEquiv, pObj->Id ); - if ( pRepr == NULL || pRepr == pObj ) - return pObj; - return Abc_NtkPartStitchFindRepr_rec( vEquiv, pRepr ); -} - -/**Function************************************************************* - - Synopsis [Returns the representative of the fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Abc_Obj_t * Abc_NtkPartStitchCopy0( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFan = Abc_ObjFanin0( pObj ); - Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan ); - return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ Abc_ObjFaninC1(pObj) ); -} -static inline Abc_Obj_t * Abc_NtkPartStitchCopy1( Vec_Ptr_t * vEquiv, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFan = Abc_ObjFanin1( pObj ); - Abc_Obj_t * pRepr = Abc_NtkPartStitchFindRepr_rec( vEquiv, pFan ); - return Abc_ObjNotCond( pRepr->pCopy, pRepr->fPhase ^ pFan->fPhase ^ Abc_ObjFaninC1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Hop_Obj_t * Hop_ObjChild0Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin0(pObj)->pNext, Abc_ObjFaninC0(pObj) ); } -static inline Hop_Obj_t * Hop_ObjChild1Next( Abc_Obj_t * pObj ) { return Hop_NotCond( (Hop_Obj_t *)Abc_ObjFanin1(pObj)->pNext, Abc_ObjFaninC1(pObj) ); } - - -/**Function************************************************************* - - Synopsis [Stitches together several networks with choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Man_t * Abc_NtkPartStartHop( Abc_Ntk_t * pNtk ) -{ - Hop_Man_t * pMan; - Abc_Obj_t * pObj; - int i; - // start the HOP package - pMan = Hop_ManStart(); - pMan->vObjs = Vec_PtrAlloc( Abc_NtkObjNumMax(pNtk) + 1 ); - Vec_PtrPush( pMan->vObjs, Hop_ManConst1(pMan) ); - // map constant node and PIs - Abc_AigConst1(pNtk)->pNext = (Abc_Obj_t *)Hop_ManConst1(pMan); - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pNext = (Abc_Obj_t *)Hop_ObjCreatePi(pMan); - // map the internal nodes - Abc_AigForEachAnd( pNtk, pObj, i ) - { - pObj->pNext = (Abc_Obj_t *)Hop_And( pMan, Hop_ObjChild0Next(pObj), Hop_ObjChild1Next(pObj) ); - assert( !Abc_ObjIsComplement(pObj->pNext) ); - } - // set the choice nodes - Abc_AigForEachAnd( pNtk, pObj, i ) - { - if ( pObj->pCopy ) - ((Hop_Obj_t *)pObj->pNext)->pData = pObj->pCopy->pNext; - } - // transfer the POs - Abc_NtkForEachCo( pNtk, pObj, i ) - Hop_ObjCreatePo( pMan, Hop_ObjChild0Next(pObj) ); - // check the new manager - if ( !Hop_ManCheck(pMan) ) - printf( "Abc_NtkPartStartHop: HOP manager check has failed.\n" ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Stitches together several networks with choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkPartStitchChoices( Abc_Ntk_t * pNtk, Vec_Ptr_t * vParts ) -{ - extern Abc_Ntk_t * Abc_NtkHopRemoveLoops( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ); - - Hop_Man_t * pMan; - Vec_Ptr_t * vNodes; - Abc_Ntk_t * pNtkNew, * pNtkTemp; - Abc_Obj_t * pObj, * pFanin; - int i, k, iNodeId; - - // start a new network similar to the original one - assert( Abc_NtkIsStrash(pNtk) ); - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - - // annotate parts to point to the new network - Vec_PtrForEachEntry( vParts, pNtkTemp, i ) - { - assert( Abc_NtkIsStrash(pNtkTemp) ); - Abc_NtkCleanCopy( pNtkTemp ); - - // map the CI nodes - Abc_AigConst1(pNtkTemp)->pCopy = Abc_AigConst1(pNtkNew); - Abc_NtkForEachCi( pNtkTemp, pObj, k ) - { - iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); - if ( iNodeId == -1 ) - { - printf( "Cannot find CI node %s in the original network.\n", Abc_ObjName(pObj) ); - return NULL; - } - pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); - } - - // add the internal nodes while saving representatives - vNodes = Abc_AigDfs( pNtkTemp, 1, 0 ); - Vec_PtrForEachEntry( vNodes, pObj, k ) - { - pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - assert( !Abc_ObjIsComplement(pObj->pCopy) ); - if ( Abc_AigNodeIsChoice(pObj) ) - for ( pFanin = pObj->pData; pFanin; pFanin = pFanin->pData ) - pFanin->pCopy->pCopy = pObj->pCopy; - } - Vec_PtrFree( vNodes ); - - // map the CO nodes - Abc_NtkForEachCo( pNtkTemp, pObj, k ) - { - iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI ); - if ( iNodeId == -1 ) - { - printf( "Cannot find CO node %s in the original network.\n", Abc_ObjName(pObj) ); - return NULL; - } - pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); - Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); - } - } - - // connect the remaining POs -/* - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pCopy = Abc_NtkCi( pNtkNew, i ); - Abc_NtkForEachCo( pNtk, pObj, i ) - pObj->pCopy = Abc_NtkCo( pNtkNew, i ); -*/ - Abc_NtkForEachCo( pNtk, pObj, i ) - { - if ( Abc_ObjFaninNum(pObj->pCopy) == 0 ) - Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); - } - - // transform into the HOP manager - pMan = Abc_NtkPartStartHop( pNtkNew ); - pNtkNew = Abc_NtkHopRemoveLoops( pNtkTemp = pNtkNew, pMan ); - Abc_NtkDelete( pNtkTemp ); - - // check correctness of the new network - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkPartStitchChoices: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Stitches together several networks with choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkFraigPartitioned( Vec_Ptr_t * vStore, void * pParams ) -{ - extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); - extern void * Abc_FrameGetGlobalFrame(); - - Vec_Ptr_t * vParts, * vFraigs, * vOnePtr; - Vec_Int_t * vOne; - Abc_Ntk_t * pNtk, * pNtk2, * pNtkAig, * pNtkFraig; - int i, k; - - // perform partitioning - pNtk = Vec_PtrEntry( vStore, 0 ); - assert( Abc_NtkIsStrash(pNtk) ); -// vParts = Abc_NtkPartitionNaive( pNtk, 20 ); - vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 ); - - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); - - // fraig each partition - vOnePtr = Vec_PtrAlloc( 1000 ); - vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) ); - Vec_PtrForEachEntry( vParts, vOne, i ) - { - // start the partition - Abc_NtkConvertCos( pNtk, vOne, vOnePtr ); - pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 ); - // add nodes to the partition - Vec_PtrForEachEntryStart( vStore, pNtk2, k, 1 ) - { - Abc_NtkConvertCos( pNtk2, vOne, vOnePtr ); - Abc_NtkAppendToCone( pNtkAig, pNtk2, vOnePtr ); - } - printf( "Fraiging part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", - i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pNtkAig), Abc_NtkPoNum(pNtkAig), - Abc_NtkNodeNum(pNtkAig), Abc_AigLevel(pNtkAig) ); - // fraig the partition - pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 1, 0 ); - Vec_PtrPush( vFraigs, pNtkFraig ); - Abc_NtkDelete( pNtkAig ); - } - printf( " \r" ); - Vec_VecFree( (Vec_Vec_t *)vParts ); - - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); - - // derive the final network - pNtkFraig = Abc_NtkPartStitchChoices( pNtk, vFraigs ); - Vec_PtrForEachEntry( vFraigs, pNtkAig, i ) - Abc_NtkDelete( pNtkAig ); - Vec_PtrFree( vFraigs ); - Vec_PtrFree( vOnePtr ); - return pNtkFraig; -} - -/**Function************************************************************* - - Synopsis [Stitches together several networks with choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams ) -{ - extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); - extern void * Abc_FrameGetGlobalFrame(); - - Vec_Ptr_t * vParts, * vFraigs, * vOnePtr; - Vec_Int_t * vOne; - Abc_Ntk_t * pNtkAig, * pNtkFraig; - int i; - int clk = clock(); - - // perform partitioning - assert( Abc_NtkIsStrash(pNtk) ); -// vParts = Abc_NtkPartitionNaive( pNtk, 20 ); - vParts = Abc_NtkPartitionSmart( pNtk, 300, 0 ); - - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); - - // fraig each partition - vOnePtr = Vec_PtrAlloc( 1000 ); - vFraigs = Vec_PtrAlloc( Vec_PtrSize(vParts) ); - Vec_PtrForEachEntry( vParts, vOne, i ) - { - Abc_NtkConvertCos( pNtk, vOne, vOnePtr ); - pNtkAig = Abc_NtkCreateConeArray( pNtk, vOnePtr, 0 ); - pNtkFraig = Abc_NtkFraig( pNtkAig, pParams, 0, 0 ); - Vec_PtrPush( vFraigs, pNtkFraig ); - Abc_NtkDelete( pNtkAig ); - - printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) ); - } - Vec_VecFree( (Vec_Vec_t *)vParts ); - - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); - - // derive the final network - Vec_PtrForEachEntry( vFraigs, pNtkAig, i ) - Abc_NtkDelete( pNtkAig ); - Vec_PtrFree( vFraigs ); - Vec_PtrFree( vOnePtr ); - PRT( "Partitioned fraiging time", clock() - clk ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcPlace.c b/src/base/abci/abcPlace.c deleted file mode 100644 index 87c99e99..00000000 --- a/src/base/abci/abcPlace.c +++ /dev/null @@ -1,255 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcPlace.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Interface with a placer.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcPlace.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -// placement includes -#include "place_base.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -AbstractCell *abstractCells = NULL; -ConcreteCell *cells = NULL; -ConcreteNet *nets = NULL; -int nAllocSize = 0; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates a new cell.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_PlaceCreateCell( Abc_Obj_t * pObj, int fAnd ) -{ - assert( cells[pObj->Id].m_id == 0 ); - - cells[pObj->Id].m_id = pObj->Id; - cells[pObj->Id].m_label = ""; - cells[pObj->Id].m_parent = &(abstractCells[fAnd]); - cells[pObj->Id].m_fixed = 0; - addConcreteCell(&(cells[pObj->Id])); -} - -/**Function************************************************************* - - Synopsis [Updates the net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_PlaceUpdateNet( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout; - int k; - // free the old array of net terminals - if ( nets[pObj->Id].m_terms ) - free( nets[pObj->Id].m_terms ); - // fill in the net with the new information - nets[pObj->Id].m_id = pObj->Id; - nets[pObj->Id].m_weight = 1.0; - nets[pObj->Id].m_numTerms = Abc_ObjFanoutNum(pObj); //fanout - nets[pObj->Id].m_terms = ALLOC(ConcreteCell*, Abc_ObjFanoutNum(pObj)); - Abc_ObjForEachFanout( pObj, pFanout, k ) - nets[pObj->Id].m_terms[k] = &(cells[pFanout->Id]); - addConcreteNet(&(nets[pObj->Id])); -} - -/**Function************************************************************* - - Synopsis [Returns the placement cost of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins ) -{ - Abc_Obj_t * pObj; -// double x, y; - int i; - Vec_PtrForEachEntry( vFanins, pObj, i ) - { -// pObj->Id - } - return 0.0; -} - -/**Function************************************************************* - - Synopsis [Updates placement after one step of rewriting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets ) -{ - Abc_Obj_t * pObj, * pFanin; - int i, k; - Vec_Ptr_t * vCells, * vNets; - - // start the arrays of new cells and nets - vCells = Vec_PtrAlloc( 16 ); - vNets = Vec_PtrAlloc( 32 ); - - // go through the new nodes - Vec_PtrForEachEntry( vAddedCells, pObj, i ) - { - assert( !Abc_ObjIsComplement(pObj) ); - Abc_PlaceCreateCell( pObj, 1 ); - Abc_PlaceUpdateNet( pObj ); - - // add the new cell and its fanin nets to temporary storage - Vec_PtrPush( vCells, &(cells[pObj->Id]) ); - Abc_ObjForEachFanin( pObj, pFanin, k ) - Vec_PtrPushUnique( vNets, &(nets[pFanin->Id]) ); - } - - // go through the modified nets - Vec_PtrForEachEntry( vUpdatedNets, pObj, i ) - { - assert( !Abc_ObjIsComplement(pObj) ); - if ( Abc_ObjType(pObj) == ABC_OBJ_NONE ) // dead node - continue; - Abc_PlaceUpdateNet( pObj ); - } - - // update the placement -// fastPlace( Vec_PtrSize(vCells), (ConcreteCell **)Vec_PtrArray(vCells), -// Vec_PtrSize(vNets), (ConcreteNet **)Vec_PtrArray(vNets) ); - - // clean up - Vec_PtrFree( vCells ); - Vec_PtrFree( vNets ); -} - -/**Function************************************************************* - - Synopsis [This procedure is called before the writing start.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_PlaceBegin( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - - // allocate and clean internal storage - nAllocSize = 5 * Abc_NtkObjNumMax(pNtk); - cells = REALLOC(ConcreteCell, cells, nAllocSize); - nets = REALLOC(ConcreteNet, nets, nAllocSize); - memset( cells, 0, sizeof(ConcreteCell) * nAllocSize ); - memset( nets, 0, sizeof(ConcreteNet) * nAllocSize ); - - // create AbstractCells - // 1: pad - // 2: and - if (!abstractCells) - abstractCells = ALLOC(AbstractCell,2); - - abstractCells[0].m_height = 1.0; - abstractCells[0].m_width = 1.0; - abstractCells[0].m_label = "pio"; - abstractCells[0].m_pad = 1; - - abstractCells[1].m_height = 1.0; - abstractCells[1].m_width = 1.0; - abstractCells[1].m_label = "and"; - abstractCells[1].m_pad = 0; - - // input pads - Abc_NtkForEachCi( pNtk, pObj, i ) - Abc_PlaceCreateCell( pObj, 0 ); - - // ouput pads - Abc_NtkForEachCo( pNtk, pObj, i ) - Abc_PlaceCreateCell( pObj, 0 ); - - // AND nodes - Abc_AigForEachAnd( pNtk, pObj, i ) - Abc_PlaceCreateCell( pObj, 1 ); - - // all nets - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( !Abc_ObjIsCi(pObj) && !Abc_ObjIsNode(pObj) ) - continue; - Abc_PlaceUpdateNet( pObj ); - } - - globalPreplace((float)0.8); - globalPlace(); -} - -/**Function************************************************************* - - Synopsis [This procedure is called after the writing completes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_PlaceEnd( Abc_Ntk_t * pNtk ) -{ - int i; - - - // clean up - for ( i = 0; i < nAllocSize; i++ ) - FREE( nets[i].m_terms ); - FREE( abstractCells ); - FREE( cells ); - FREE( nets ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcPrint.c b/src/base/abci/abcPrint.c deleted file mode 100644 index 7c3fb33c..00000000 --- a/src/base/abci/abcPrint.c +++ /dev/null @@ -1,949 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcPrint.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Printing statistics.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcPrint.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "dec.h" -#include "main.h" -#include "mio.h" -//#include "seq.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//extern int s_TotalNodes = 0; -//extern int s_TotalChanges = 0; - -int s_MappingTime = 0; -int s_MappingMem = 0; -int s_ResubTime = 0; -int s_ResynTime = 0; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Print the vital stats of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) -{ - int Num; - -// if ( Abc_NtkIsStrash(pNtk) ) -// Abc_AigCountNext( pNtk->pManFunc ); - - fprintf( pFile, "%-13s:", pNtk->pName ); - if ( Abc_NtkAssertNum(pNtk) ) - fprintf( pFile, " i/o/a = %4d/%4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkAssertNum(pNtk) ); - else - fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); - fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) ); - if ( Abc_NtkIsNetlist(pNtk) ) - { - fprintf( pFile, " net = %5d", Abc_NtkNetNum(pNtk) ); - fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); - fprintf( pFile, " wbox = %3d", Abc_NtkWhiteboxNum(pNtk) ); - fprintf( pFile, " bbox = %3d", Abc_NtkBlackboxNum(pNtk) ); - } - else if ( Abc_NtkIsStrash(pNtk) ) - { - fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) ); - if ( Num = Abc_NtkGetChoiceNum(pNtk) ) - fprintf( pFile, " (choice = %d)", Num ); - if ( Num = Abc_NtkGetExorNum(pNtk) ) - fprintf( pFile, " (exor = %d)", Num ); -// if ( Num2 = Abc_NtkGetMuxNum(pNtk) ) -// fprintf( pFile, " (mux = %d)", Num2-Num ); -// if ( Num2 ) -// fprintf( pFile, " (other = %d)", Abc_NtkNodeNum(pNtk)-3*Num2 ); - } - else - { - fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); - fprintf( pFile, " net = %5d", Abc_NtkGetTotalFanins(pNtk) ); - } - - if ( Abc_NtkIsStrash(pNtk) || Abc_NtkIsNetlist(pNtk) ) - { - } - else if ( Abc_NtkHasSop(pNtk) ) - { - - fprintf( pFile, " cube = %5d", Abc_NtkGetCubeNum(pNtk) ); -// fprintf( pFile, " lit(sop) = %5d", Abc_NtkGetLitNum(pNtk) ); - if ( fFactored ) - fprintf( pFile, " lit(fac) = %5d", Abc_NtkGetLitFactNum(pNtk) ); - } - else if ( Abc_NtkHasAig(pNtk) ) - fprintf( pFile, " aig = %5d", Abc_NtkGetAigNodeNum(pNtk) ); - else if ( Abc_NtkHasBdd(pNtk) ) - fprintf( pFile, " bdd = %5d", Abc_NtkGetBddNodeNum(pNtk) ); - else if ( Abc_NtkHasMapping(pNtk) ) - { - fprintf( pFile, " area = %5.2f", Abc_NtkGetMappedArea(pNtk) ); - fprintf( pFile, " delay = %5.2f", Abc_NtkDelayTrace(pNtk) ); - } - else if ( !Abc_NtkHasBlackbox(pNtk) ) - { - assert( 0 ); - } - - if ( Abc_NtkIsStrash(pNtk) ) - fprintf( pFile, " lev = %3d", Abc_AigLevel(pNtk) ); - else - fprintf( pFile, " lev = %3d", Abc_NtkLevel(pNtk) ); - - fprintf( pFile, "\n" ); - -// Abc_NtkCrossCut( pNtk ); - - // print the statistic into a file -/* - { - FILE * pTable; - pTable = fopen( "xs/reg_stats.txt", "a+" ); - fprintf( pTable, "%s ", pNtk->pName ); - fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); - fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ -/* - // print the statistic into a file - { - FILE * pTable; - pTable = fopen( "stats.txt", "a+" ); - fprintf( pTable, "%s ", pNtk->pSpec ); - fprintf( pTable, "%.0f ", Abc_NtkGetMappedArea(pNtk) ); - fprintf( pTable, "%.2f ", Abc_NtkDelayTrace(pNtk) ); - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ - -/* - // print the statistic into a file - { - FILE * pTable; - pTable = fopen( "x/stats_new.txt", "a+" ); - fprintf( pTable, "%s ", pNtk->pName ); -// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); -// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); -// fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); -// fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); -// fprintf( pTable, "%d ", Abc_NtkGetTotalFanins(pNtk) ); -// fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); -// fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) ); - fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) ); -// fprintf( pTable, "%.2f", (float)(s_ResynTime)/(float)(CLOCKS_PER_SEC) ); - fprintf( pTable, "\n" ); - fclose( pTable ); - - s_ResynTime = 0; - } -*/ - -/* - // print the statistic into a file - { - static int Counter = 0; - extern int timeRetime; - FILE * pTable; - Counter++; - pTable = fopen( "a/ret__stats.txt", "a+" ); - fprintf( pTable, "%s ", pNtk->pName ); - fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); - fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); - fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); - fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) ); - if ( Counter % 4 == 0 ) - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ - -/* - // print the statistic into a file - { - static int Counter = 0; - extern int timeRetime; - FILE * pTable; - Counter++; - pTable = fopen( "d/stats.txt", "a+" ); - fprintf( pTable, "%s ", pNtk->pName ); -// fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); -// fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); -// fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); - fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); - fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) ); - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ - -/* - s_TotalNodes += Abc_NtkNodeNum(pNtk); - printf( "Total nodes = %6d %6.2f Mb Changes = %6d.\n", - s_TotalNodes, s_TotalNodes * 20.0 / (1<<20), s_TotalChanges ); -*/ - -// if ( Abc_NtkHasSop(pNtk) ) -// printf( "The total number of cube pairs = %d.\n", Abc_NtkGetCubePairNum(pNtk) ); -} - -/**Function************************************************************* - - Synopsis [Prints PIs/POs and LIs/LOs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - - fprintf( pFile, "Primary inputs (%d): ", Abc_NtkPiNum(pNtk) ); - Abc_NtkForEachPi( pNtk, pObj, i ) - fprintf( pFile, " %s", Abc_ObjName(pObj) ); -// fprintf( pFile, " %s(%d)", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) ); - fprintf( pFile, "\n" ); - - fprintf( pFile, "Primary outputs (%d):", Abc_NtkPoNum(pNtk) ); - Abc_NtkForEachPo( pNtk, pObj, i ) - fprintf( pFile, " %s", Abc_ObjName(pObj) ); - fprintf( pFile, "\n" ); - - fprintf( pFile, "Latches (%d): ", Abc_NtkLatchNum(pNtk) ); - Abc_NtkForEachLatch( pNtk, pObj, i ) - fprintf( pFile, " %s(%s=%s)", Abc_ObjName(pObj), - Abc_ObjName(Abc_ObjFanout0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints statistics about latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pLatch, * pFanin; - int i, Counter0, Counter1, Counter2; - int InitNums[4], Init; - - assert( !Abc_NtkIsNetlist(pNtk) ); - if ( Abc_NtkLatchNum(pNtk) == 0 ) - { - fprintf( pFile, "The network is combinational.\n" ); - return; - } - - for ( i = 0; i < 4; i++ ) - InitNums[i] = 0; - Counter0 = Counter1 = Counter2 = 0; - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - Init = Abc_LatchInit( pLatch ); - assert( Init < 4 ); - InitNums[Init]++; - - pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); - if ( Abc_NtkIsLogic(pNtk) ) - { - if ( !Abc_NodeIsConst(pFanin) ) - continue; - } - else if ( Abc_NtkIsStrash(pNtk) ) - { - if ( !Abc_AigNodeIsConst(pFanin) ) - continue; - } - else - assert( 0 ); - - // the latch input is a constant node - Counter0++; - if ( Abc_LatchIsInitDc(pLatch) ) - { - Counter1++; - continue; - } - // count the number of cases when the constant is equal to the initial value - if ( Abc_NtkIsStrash(pNtk) ) - { - if ( Abc_LatchIsInit1(pLatch) == !Abc_ObjFaninC0(pLatch) ) - Counter2++; - } - else - { - if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(Abc_ObjFanin0(Abc_ObjFanin0(pLatch))) ) - Counter2++; - } - } - fprintf( pFile, "%-15s: ", pNtk->pName ); - fprintf( pFile, "Latch = %6d. No = %4d. Zero = %4d. One = %4d. DC = %4d.\n", - Abc_NtkLatchNum(pNtk), InitNums[0], InitNums[1], InitNums[2], InitNums[3] ); - fprintf( pFile, "Const fanin = %3d. DC init = %3d. Matching init = %3d. ", Counter0, Counter1, Counter2 ); - fprintf( pFile, "Self-feed latches = %2d.\n", -1 ); //Abc_NtkCountSelfFeedLatches(pNtk) ); -} - -/**Function************************************************************* - - Synopsis [Prints the distribution of fanins/fanouts in the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, k, nFanins, nFanouts; - Vec_Int_t * vFanins, * vFanouts; - int nOldSize, nNewSize; - - vFanins = Vec_IntAlloc( 0 ); - vFanouts = Vec_IntAlloc( 0 ); - Vec_IntFill( vFanins, 100, 0 ); - Vec_IntFill( vFanouts, 100, 0 ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - nFanins = Abc_ObjFaninNum(pNode); - if ( Abc_NtkIsNetlist(pNtk) ) - nFanouts = Abc_ObjFanoutNum( Abc_ObjFanout0(pNode) ); - else - nFanouts = Abc_ObjFanoutNum(pNode); -// nFanouts = Abc_NodeMffcSize(pNode); - if ( nFanins > vFanins->nSize || nFanouts > vFanouts->nSize ) - { - nOldSize = vFanins->nSize; - nNewSize = ABC_MAX(nFanins, nFanouts) + 10; - Vec_IntGrow( vFanins, nNewSize ); - Vec_IntGrow( vFanouts, nNewSize ); - for ( k = nOldSize; k < nNewSize; k++ ) - { - Vec_IntPush( vFanins, 0 ); - Vec_IntPush( vFanouts, 0 ); - } - } - vFanins->pArray[nFanins]++; - vFanouts->pArray[nFanouts]++; - } - fprintf( pFile, "The distribution of fanins and fanouts in the network:\n" ); - fprintf( pFile, " Number Nodes with fanin Nodes with fanout\n" ); - for ( k = 0; k < vFanins->nSize; k++ ) - { - if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 ) - continue; - fprintf( pFile, "%5d : ", k ); - if ( vFanins->pArray[k] == 0 ) - fprintf( pFile, " " ); - else - fprintf( pFile, "%12d ", vFanins->pArray[k] ); - fprintf( pFile, " " ); - if ( vFanouts->pArray[k] == 0 ) - fprintf( pFile, " " ); - else - fprintf( pFile, "%12d ", vFanouts->pArray[k] ); - fprintf( pFile, "\n" ); - } - Vec_IntFree( vFanins ); - Vec_IntFree( vFanouts ); -} - -/**Function************************************************************* - - Synopsis [Prints the fanins/fanouts of a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pNode2; - int i; - if ( Abc_ObjIsPo(pNode) ) - pNode = Abc_ObjFanin0(pNode); - - fprintf( pFile, "Node %s", Abc_ObjName(pNode) ); - fprintf( pFile, "\n" ); - - fprintf( pFile, "Fanins (%d): ", Abc_ObjFaninNum(pNode) ); - Abc_ObjForEachFanin( pNode, pNode2, i ) - fprintf( pFile, " %s", Abc_ObjName(pNode2) ); - fprintf( pFile, "\n" ); - - fprintf( pFile, "Fanouts (%d): ", Abc_ObjFaninNum(pNode) ); - Abc_ObjForEachFanout( pNode, pNode2, i ) - fprintf( pFile, " %s", Abc_ObjName(pNode2) ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints the MFFCs of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i; - extern void Abc_NodeMffsConeSuppPrint( Abc_Obj_t * pNode ); - Abc_NtkForEachNode( pNtk, pNode, i ) - Abc_NodeMffsConeSuppPrint( pNode ); -} - -/**Function************************************************************* - - Synopsis [Prints the factored form of one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ) -{ - Abc_Obj_t * pNode; - int i; - assert( Abc_NtkIsSopLogic(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - Abc_NodePrintFactor( pFile, pNode, fUseRealNames ); -} - -/**Function************************************************************* - - Synopsis [Prints the factored form of one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ) -{ - Dec_Graph_t * pGraph; - Vec_Ptr_t * vNamesIn; - if ( Abc_ObjIsCo(pNode) ) - pNode = Abc_ObjFanin0(pNode); - if ( Abc_ObjIsPi(pNode) ) - { - fprintf( pFile, "Skipping the PI node.\n" ); - return; - } - if ( Abc_ObjIsLatch(pNode) ) - { - fprintf( pFile, "Skipping the latch.\n" ); - return; - } - assert( Abc_ObjIsNode(pNode) ); - pGraph = Dec_Factor( pNode->pData ); - if ( fUseRealNames ) - { - vNamesIn = Abc_NodeGetFaninNames(pNode); - Dec_GraphPrint( stdout, pGraph, (char **)vNamesIn->pArray, Abc_ObjName(pNode) ); - Abc_NodeFreeNames( vNamesIn ); - } - else - Dec_GraphPrint( stdout, pGraph, (char **)NULL, Abc_ObjName(pNode) ); - Dec_GraphFree( pGraph ); -} - - -/**Function************************************************************* - - Synopsis [Prints the level stats of the PO node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes ) -{ - Abc_Obj_t * pNode; - int i, k, Length; - - if ( fListNodes ) - { - int nLevels; - nLevels = Abc_NtkLevel(pNtk); - printf( "Nodes by level:\n" ); - for ( i = 0; i <= nLevels; i++ ) - { - printf( "%2d : ", i ); - Abc_NtkForEachNode( pNtk, pNode, k ) - if ( (int)pNode->Level == i ) - printf( " %s", Abc_ObjName(pNode) ); - printf( "\n" ); - } - return; - } - - // print the delay profile - if ( fProfile && Abc_NtkHasMapping(pNtk) ) - { - int nIntervals = 12; - float DelayMax, DelayCur, DelayDelta; - int * pLevelCounts; - int DelayInt, nOutsSum, nOutsTotal; - - // get the max delay and delta - DelayMax = Abc_NtkDelayTrace( pNtk ); - DelayDelta = DelayMax/nIntervals; - // collect outputs by delay - pLevelCounts = ALLOC( int, nIntervals ); - memset( pLevelCounts, 0, sizeof(int) * nIntervals ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - DelayCur = Abc_NodeReadArrival( Abc_ObjFanin0(pNode) )->Worst; - DelayInt = (int)(DelayCur / DelayDelta); - if ( DelayInt >= nIntervals ) - DelayInt = nIntervals - 1; - pLevelCounts[DelayInt]++; - } - - nOutsSum = 0; - nOutsTotal = Abc_NtkCoNum(pNtk); - for ( i = 0; i < nIntervals; i++ ) - { - nOutsSum += pLevelCounts[i]; - printf( "[%8.2f - %8.2f] : COs = %4d. %5.1f %%\n", - DelayDelta * i, DelayDelta * (i+1), pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal ); - } - free( pLevelCounts ); - return; - } - else if ( fProfile ) - { - int LevelMax, * pLevelCounts; - int nOutsSum, nOutsTotal; - - if ( !Abc_NtkIsStrash(pNtk) ) - Abc_NtkLevel(pNtk); - - LevelMax = 0; - Abc_NtkForEachCo( pNtk, pNode, i ) - if ( LevelMax < (int)Abc_ObjFanin0(pNode)->Level ) - LevelMax = Abc_ObjFanin0(pNode)->Level; - pLevelCounts = ALLOC( int, LevelMax + 1 ); - memset( pLevelCounts, 0, sizeof(int) * (LevelMax + 1) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - pLevelCounts[Abc_ObjFanin0(pNode)->Level]++; - - nOutsSum = 0; - nOutsTotal = Abc_NtkCoNum(pNtk); - for ( i = 0; i <= LevelMax; i++ ) - if ( pLevelCounts[i] ) - { - nOutsSum += pLevelCounts[i]; - printf( "Level = %4d. COs = %4d. %5.1f %%\n", i, pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal ); - } - free( pLevelCounts ); - return; - } - assert( Abc_NtkIsStrash(pNtk) ); - - // find the longest name - Length = 0; - Abc_NtkForEachCo( pNtk, pNode, i ) - if ( Length < (int)strlen(Abc_ObjName(pNode)) ) - Length = strlen(Abc_ObjName(pNode)); - if ( Length < 5 ) - Length = 5; - // print stats for each output - Abc_NtkForEachCo( pNtk, pNode, i ) - { - fprintf( pFile, "CO %4d : %*s ", i, Length, Abc_ObjName(pNode) ); - Abc_NodePrintLevel( pFile, pNode ); - } -} - -/**Function************************************************************* - - Synopsis [Prints the factored form of one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pDriver; - Vec_Ptr_t * vNodes; - - pDriver = Abc_ObjIsCo(pNode)? Abc_ObjFanin0(pNode) : pNode; - if ( Abc_ObjIsPi(pDriver) ) - { - fprintf( pFile, "Primary input.\n" ); - return; - } - if ( Abc_ObjIsLatch(pDriver) ) - { - fprintf( pFile, "Latch.\n" ); - return; - } - if ( Abc_NodeIsConst(pDriver) ) - { - fprintf( pFile, "Constant %d.\n", !Abc_ObjFaninC0(pNode) ); - return; - } - // print the level - fprintf( pFile, "Level = %3d. ", pDriver->Level ); - // print the size of MFFC - fprintf( pFile, "Mffc = %5d. ", Abc_NodeMffcSize(pDriver) ); - // print the size of the shole cone - vNodes = Abc_NtkDfsNodes( pNode->pNtk, &pDriver, 1 ); - fprintf( pFile, "Cone = %5d. ", Vec_PtrSize(vNodes) ); - Vec_PtrFree( vNodes ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints the factored form of one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames ) -{ - Vec_Ptr_t * vNamesIn; - if ( fUseRealNames ) - { - vNamesIn = Abc_NodeGetFaninNames(pNode); - Extra_PrintKMap( stdout, pNode->pNtk->pManFunc, pNode->pData, Cudd_Not(pNode->pData), - Abc_ObjFaninNum(pNode), NULL, 0, (char **)vNamesIn->pArray ); - Abc_NodeFreeNames( vNamesIn ); - } - else - Extra_PrintKMap( stdout, pNode->pNtk->pManFunc, pNode->pData, Cudd_Not(pNode->pData), - Abc_ObjFaninNum(pNode), NULL, 0, NULL ); - -} - -/**Function************************************************************* - - Synopsis [Prints statistics about gates used in the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary ) -{ - Abc_Obj_t * pObj; - int fHasBdds, i; - int CountConst, CountBuf, CountInv, CountAnd, CountOr, CountOther, CounterTotal; - char * pSop; - - if ( fUseLibrary && Abc_NtkHasMapping(pNtk) ) - { - stmm_table * tTable; - stmm_generator * gen; - char * pName; - int * pCounter, Counter; - double Area, AreaTotal; - - // count the gates by name - CounterTotal = 0; - tTable = stmm_init_table(strcmp, stmm_strhash); - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( i == 0 ) continue; - if ( !stmm_find_or_add( tTable, Mio_GateReadName(pObj->pData), (char ***)&pCounter ) ) - *pCounter = 0; - (*pCounter)++; - CounterTotal++; - } - // print the gates - AreaTotal = Abc_NtkGetMappedArea(pNtk); - stmm_foreach_item( tTable, gen, (char **)&pName, (char **)&Counter ) - { - Area = Counter * Mio_GateReadArea(Mio_LibraryReadGateByName(pNtk->pManFunc,pName)); - printf( "%-12s = %8d %10.2f %6.2f %%\n", pName, Counter, Area, 100.0 * Area / AreaTotal ); - } - printf( "%-12s = %8d %10.2f %6.2f %%\n", "TOTAL", CounterTotal, AreaTotal, 100.0 ); - stmm_free_table( tTable ); - return; - } - - if ( Abc_NtkIsAigLogic(pNtk) ) - return; - - // transform logic functions from BDD to SOP - if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) - { - if ( !Abc_NtkBddToSop(pNtk, 0) ) - { - printf( "Abc_NtkPrintGates(): Converting to SOPs has failed.\n" ); - return; - } - } - - // get hold of the SOP of the node - CountConst = CountBuf = CountInv = CountAnd = CountOr = CountOther = CounterTotal = 0; - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( i == 0 ) continue; - if ( Abc_NtkHasMapping(pNtk) ) - pSop = Mio_GateReadSop(pObj->pData); - else - pSop = pObj->pData; - // collect the stats - if ( Abc_SopIsConst0(pSop) || Abc_SopIsConst1(pSop) ) - CountConst++; - else if ( Abc_SopIsBuf(pSop) ) - CountBuf++; - else if ( Abc_SopIsInv(pSop) ) - CountInv++; - else if ( !Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop) || Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop) ) - CountAnd++; - else if ( Abc_SopIsComplement(pSop) && Abc_SopIsAndType(pSop) || !Abc_SopIsComplement(pSop) && Abc_SopIsOrType(pSop) ) - CountOr++; - else - CountOther++; - CounterTotal++; - } - printf( "Const = %8d %6.2f %%\n", CountConst , 100.0 * CountConst / CounterTotal ); - printf( "Buffer = %8d %6.2f %%\n", CountBuf , 100.0 * CountBuf / CounterTotal ); - printf( "Inverter = %8d %6.2f %%\n", CountInv , 100.0 * CountInv / CounterTotal ); - printf( "And = %8d %6.2f %%\n", CountAnd , 100.0 * CountAnd / CounterTotal ); - printf( "Or = %8d %6.2f %%\n", CountOr , 100.0 * CountOr / CounterTotal ); - printf( "Other = %8d %6.2f %%\n", CountOther , 100.0 * CountOther / CounterTotal ); - printf( "TOTAL = %8d %6.2f %%\n", CounterTotal, 100.0 * CounterTotal / CounterTotal ); - - // convert the network back into BDDs if this is how it was - if ( fHasBdds ) - Abc_NtkSopToBdd(pNtk); -} - -/**Function************************************************************* - - Synopsis [Prints statistics about gates used in the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes1, * vNodes2; - Abc_Obj_t * pObj1, * pObj2, * pNode1, * pNode2; - int i, k, m, n, Counter; - - // print the template - printf( "Statistics about sharing of logic nodes among the CO pairs.\n" ); - printf( "(CO1,CO2)=NumShared : " ); - // go though the CO pairs - Abc_NtkForEachCo( pNtk, pObj1, i ) - { - vNodes1 = Abc_NtkDfsNodes( pNtk, &pObj1, 1 ); - // mark the nodes - Vec_PtrForEachEntry( vNodes1, pNode1, m ) - pNode1->fMarkA = 1; - // go through the second COs - Abc_NtkForEachCo( pNtk, pObj2, k ) - { - if ( i >= k ) - continue; - vNodes2 = Abc_NtkDfsNodes( pNtk, &pObj2, 1 ); - // count the number of marked - Counter = 0; - Vec_PtrForEachEntry( vNodes2, pNode2, n ) - Counter += pNode2->fMarkA; - // print - printf( "(%d,%d)=%d ", i, k, Counter ); - Vec_PtrFree( vNodes2 ); - } - // unmark the nodes - Vec_PtrForEachEntry( vNodes1, pNode1, m ) - pNode1->fMarkA = 0; - Vec_PtrFree( vNodes1 ); - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints info for each output cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vSupp, * vNodes; - Abc_Obj_t * pObj; - int i; - printf( "Structural support info:\n" ); - Abc_NtkForEachCo( pNtk, pObj, i ) - { - vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); - vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); - printf( "%20s : Cone = %5d. Supp = %5d.\n", - Abc_ObjName(pObj), vNodes->nSize, vSupp->nSize ); - Vec_PtrFree( vNodes ); - Vec_PtrFree( vSupp ); - } -} - -/**Function************************************************************* - - Synopsis [Prints information about the object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i; - fprintf( pFile, "Object %5d : ", pObj->Id ); - switch ( pObj->Type ) - { - case ABC_OBJ_NONE: - fprintf( pFile, "NONE " ); - break; - case ABC_OBJ_CONST1: - fprintf( pFile, "Const1 " ); - break; - case ABC_OBJ_PIO: - fprintf( pFile, "PIO " ); - break; - case ABC_OBJ_PI: - fprintf( pFile, "PI " ); - break; - case ABC_OBJ_PO: - fprintf( pFile, "PO " ); - break; - case ABC_OBJ_BI: - fprintf( pFile, "BI " ); - break; - case ABC_OBJ_BO: - fprintf( pFile, "BO " ); - break; - case ABC_OBJ_ASSERT: - fprintf( pFile, "Assert " ); - break; - case ABC_OBJ_NET: - fprintf( pFile, "Net " ); - break; - case ABC_OBJ_NODE: - fprintf( pFile, "Node " ); - break; - case ABC_OBJ_LATCH: - fprintf( pFile, "Latch " ); - break; - case ABC_OBJ_WHITEBOX: - fprintf( pFile, "Whitebox" ); - break; - case ABC_OBJ_BLACKBOX: - fprintf( pFile, "Blackbox" ); - break; - default: - assert(0); - break; - } - // print the fanins - fprintf( pFile, " Fanins ( " ); - Abc_ObjForEachFanin( pObj, pFanin, i ) - fprintf( pFile, "%d ", pFanin->Id ); - fprintf( pFile, ") " ); -/* - fprintf( pFile, " Fanouts ( " ); - Abc_ObjForEachFanout( pObj, pFanin, i ) - fprintf( pFile, "%d(%c) ", pFanin->Id, Abc_NodeIsTravIdCurrent(pFanin)? '+' : '-' ); - fprintf( pFile, ") " ); -*/ - // print the logic function - if ( Abc_ObjIsNode(pObj) && Abc_NtkIsSopLogic(pObj->pNtk) ) - fprintf( pFile, " %s", pObj->pData ); - else - fprintf( pFile, "\n" ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcProve.c b/src/base/abci/abcProve.c deleted file mode 100644 index a4220216..00000000 --- a/src/base/abci/abcProve.c +++ /dev/null @@ -1,343 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcProve.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Proves the miter using AIG rewriting, FRAIGing, and SAT solving.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcProve.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "fraig.h" -#include "math.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); -extern Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); - -static Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, sint64 nInspLimit, int * pRetValue, int * pNumFails, sint64 * pNumConfs, sint64 * pNumInspects ); -static void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose ); - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Attempts to solve the miter using a number of tricks.] - - Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT. Returns - a simplified version of the original network (or a constant 0 network). - In case the network is not a constant zero and a SAT assignment is found, - pNtk->pModel contains a satisfying assignment.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars ) -{ - Prove_Params_t * pParams = pPars; - Abc_Ntk_t * pNtk, * pNtkTemp; - int RetValue, nIter, nSatFails, Counter, clk, timeStart = clock(); - sint64 nSatConfs, nSatInspects, nInspectLimit; - - // get the starting network - pNtk = *ppNtk; - assert( Abc_NtkIsStrash(pNtk) ); - assert( Abc_NtkPoNum(pNtk) == 1 ); - - if ( pParams->fVerbose ) - { - printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", - pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); - printf( "Mitering = %d (%3.1f). Rewriting = %d (%3.1f). Fraiging = %d (%3.1f).\n", - pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, - pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, - pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti ); - printf( "Mitering last = %d.\n", - pParams->nMiteringLimitLast ); - } - - // if SAT only, solve without iteration - if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) - { - clk = clock(); - RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)0, 0, NULL, NULL ); - Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); - *ppNtk = pNtk; - return RetValue; - } - - // check the current resource limits - for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) - { - if ( pParams->fVerbose ) - { - printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, - (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), - (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); - fflush( stdout ); - } - - // try brute-force SAT - clk = clock(); - nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; - RetValue = Abc_NtkMiterSat( pNtk, (sint64)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (sint64)nInspectLimit, 0, &nSatConfs, &nSatInspects ); - Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); - if ( RetValue >= 0 ) - break; - - // add to the number of backtracks and inspects - pParams->nTotalBacktracksMade += nSatConfs; - pParams->nTotalInspectsMade += nSatInspects; - // check if global resource limit is reached - if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || - (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) - { - printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); - *ppNtk = pNtk; - return -1; - } - - // try rewriting - if ( pParams->fUseRewriting ) - { - clk = clock(); - Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); -// Counter = 1; - while ( 1 ) - { -/* - extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); - pNtk = Abc_NtkIvyResyn( pNtkTemp = pNtk, 0, 0 ); Abc_NtkDelete( pNtkTemp ); - if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) - break; - if ( --Counter == 0 ) - break; -*/ -/* - Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) - break; - if ( --Counter == 0 ) - break; -*/ - Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) - break; - if ( --Counter == 0 ) - break; - Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); - if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) - break; - if ( --Counter == 0 ) - break; - pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); - if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) - break; - if ( --Counter == 0 ) - break; - } - Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, pParams->fVerbose ); - } - - if ( pParams->fUseFraiging ) - { - // try FRAIGing - clk = clock(); - nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; - pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)), nInspectLimit, &RetValue, &nSatFails, &nSatConfs, &nSatInspects ); Abc_NtkDelete( pNtkTemp ); - Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, pParams->fVerbose ); -// printf( "NumFails = %d\n", nSatFails ); - if ( RetValue >= 0 ) - break; - - // add to the number of backtracks and inspects - pParams->nTotalBacktracksMade += nSatConfs; - pParams->nTotalInspectsMade += nSatInspects; - // check if global resource limit is reached - if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || - (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) - { - printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); - *ppNtk = pNtk; - return -1; - } - } - - } - - // try to prove it using brute force SAT - if ( RetValue < 0 && pParams->fUseBdds ) - { - if ( pParams->fVerbose ) - { - printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); - fflush( stdout ); - } - clk = clock(); - pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); - if ( pNtk ) - { - Abc_NtkDelete( pNtkTemp ); - RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) ); - } - else - pNtk = pNtkTemp; - Abc_NtkMiterPrint( pNtk, "BDD building", clk, pParams->fVerbose ); - } - - if ( RetValue < 0 ) - { - if ( pParams->fVerbose ) - { - printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); - fflush( stdout ); - } - clk = clock(); - nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; - RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)nInspectLimit, 0, NULL, NULL ); - Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); - } - - // assign the model if it was proved by rewriting (const 1 miter) - if ( RetValue == 0 && pNtk->pModel == NULL ) - { - pNtk->pModel = ALLOC( int, Abc_NtkCiNum(pNtk) ); - memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) ); - } - *ppNtk = pNtk; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Attempts to solve the miter using a number of tricks.] - - Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiterFraig( Abc_Ntk_t * pNtk, int nBTLimit, sint64 nInspLimit, int * pRetValue, int * pNumFails, sint64 * pNumConfs, sint64 * pNumInspects ) -{ - Abc_Ntk_t * pNtkNew; - Fraig_Params_t Params, * pParams = &Params; - Fraig_Man_t * pMan; - int nWords1, nWords2, nWordsMin, RetValue; - int * pModel; - - // to determine the number of simulation patterns - // use the following strategy - // at least 64 words (32 words random and 32 words dynamic) - // no more than 256M for one circuit (128M + 128M) - nWords1 = 32; - nWords2 = (1<<27) / (Abc_NtkNodeNum(pNtk) + Abc_NtkCiNum(pNtk)); - nWordsMin = ABC_MIN( nWords1, nWords2 ); - - // set the FRAIGing parameters - Fraig_ParamsSetDefault( pParams ); - pParams->nPatsRand = nWordsMin * 32; // the number of words of random simulation info - pParams->nPatsDyna = nWordsMin * 32; // the number of words of dynamic simulation info - pParams->nBTLimit = nBTLimit; // the max number of backtracks - pParams->nSeconds = -1; // the runtime limit - pParams->fTryProve = 0; // do not try to prove the final miter - pParams->fDoSparse = 1; // try proving sparse functions - pParams->fVerbose = 0; - pParams->nInspLimit = nInspLimit; - - // transform the target into a fraig - pMan = Abc_NtkToFraig( pNtk, pParams, 0, 0 ); - Fraig_ManProveMiter( pMan ); - RetValue = Fraig_ManCheckMiter( pMan ); - - // create the network - pNtkNew = Abc_NtkFromFraig( pMan, pNtk ); - - // save model - if ( RetValue == 0 ) - { - pModel = Fraig_ManReadModel( pMan ); - FREE( pNtkNew->pModel ); - pNtkNew->pModel = ALLOC( int, Abc_NtkCiNum(pNtkNew) ); - memcpy( pNtkNew->pModel, pModel, sizeof(int) * Abc_NtkCiNum(pNtkNew) ); - } - - // save the return values - *pRetValue = RetValue; - *pNumFails = Fraig_ManReadSatFails( pMan ); - *pNumConfs = Fraig_ManReadConflicts( pMan ); - *pNumInspects = Fraig_ManReadInspects( pMan ); - - // delete the fraig manager - Fraig_ManFree( pMan ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Attempts to solve the miter using a number of tricks.] - - Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMiterPrint( Abc_Ntk_t * pNtk, char * pString, int clk, int fVerbose ) -{ - if ( !fVerbose ) - return; - printf( "Nodes = %7d. Levels = %4d. ", Abc_NtkNodeNum(pNtk), - Abc_NtkIsStrash(pNtk)? Abc_AigLevel(pNtk) : Abc_NtkLevel(pNtk) ); - PRT( pString, clock() - clk ); -} - - -/**Function************************************************************* - - Synopsis [Implements resynthesis for CEC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkMiterRwsat( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkTemp; - Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); - Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); - return pNtk; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcQbf.c b/src/base/abci/abcQbf.c deleted file mode 100644 index b839f812..00000000 --- a/src/base/abci/abcQbf.c +++ /dev/null @@ -1,260 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcQbf.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Implementation of a simple QBF solver.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcQbf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -/* - Implementation of a simple QBF solver along the lines of - A. Solar-Lezama, L. Tancau, R. Bodik, V. Saraswat, and S. Seshia, - "Combinatorial sketching for finite programs", 12th International - Conference on Architectural Support for Programming Languages and - Operating Systems (ASPLOS 2006), San Jose, CA, October 2006. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ); -static void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars ); -static void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ); -static void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars ); -static void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Solve the QBF problem EpAx[M(p,x)].] - - Description [Variables p go first, followed by variable x. - The number of parameters is nPars. The miter is in pNtk. - The miter expresses EQUALITY of the implementation and spec.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int fVerbose ) -{ - Abc_Ntk_t * pNtkVer, * pNtkSyn, * pNtkSyn2, * pNtkTemp; - Vec_Int_t * vPiValues; - int clkTotal = clock(), clkS, clkV; - int nIters, nIterMax = 500, nInputs, RetValue, fFound = 0; - - assert( Abc_NtkIsStrash(pNtk) ); - assert( Abc_NtkIsComb(pNtk) ); - assert( Abc_NtkPoNum(pNtk) == 1 ); - assert( nPars > 0 && nPars < Abc_NtkPiNum(pNtk) ); - assert( Abc_NtkPiNum(pNtk)-nPars < 32 ); - nInputs = Abc_NtkPiNum(pNtk) - nPars; - - // initialize the synthesized network with 0000-combination - vPiValues = Vec_IntStart( Abc_NtkPiNum(pNtk) ); - Abc_NtkVectorClearPars( vPiValues, nPars ); - pNtkSyn = Abc_NtkMiterCofactor( pNtk, vPiValues ); - if ( fVerbose ) - { - printf( "Iter %2d : ", 0 ); - printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) ); - Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars ); - printf( "\n" ); - } - - // iteratively solve - for ( nIters = 0; nIters < nIterMax; nIters++ ) - { - // solve the synthesis instance -clkS = clock(); - RetValue = Abc_NtkMiterSat( pNtkSyn, 0, 0, 0, NULL, NULL ); -clkS = clock() - clkS; - if ( RetValue == 0 ) - Abc_NtkModelToVector( pNtkSyn, vPiValues ); - if ( RetValue == 1 ) - { - break; - } - if ( RetValue == -1 ) - { - printf( "Synthesis timed out.\n" ); - break; - } - // there is a counter-example - - // construct the verification instance - Abc_NtkVectorClearVars( pNtk, vPiValues, nPars ); - pNtkVer = Abc_NtkMiterCofactor( pNtk, vPiValues ); - // complement the output - Abc_ObjXorFaninC( Abc_NtkPo(pNtkVer,0), 0 ); - - // solve the verification instance -clkV = clock(); - RetValue = Abc_NtkMiterSat( pNtkVer, 0, 0, 0, NULL, NULL ); -clkV = clock() - clkV; - if ( RetValue == 0 ) - Abc_NtkModelToVector( pNtkVer, vPiValues ); - Abc_NtkDelete( pNtkVer ); - if ( RetValue == 1 ) - { - fFound = 1; - break; - } - if ( RetValue == -1 ) - { - printf( "Verification timed out.\n" ); - break; - } - // there is a counter-example - - // create a new synthesis network - Abc_NtkVectorClearPars( vPiValues, nPars ); - pNtkSyn2 = Abc_NtkMiterCofactor( pNtk, vPiValues ); - // add to the synthesis instance - pNtkSyn = Abc_NtkMiterAnd( pNtkTemp = pNtkSyn, pNtkSyn2, 0, 0 ); - Abc_NtkDelete( pNtkSyn2 ); - Abc_NtkDelete( pNtkTemp ); - - if ( fVerbose ) - { - printf( "Iter %2d : ", nIters+1 ); - printf( "AIG = %6d ", Abc_NtkNodeNum(pNtkSyn) ); - Abc_NtkVectorPrintVars( pNtk, vPiValues, nPars ); - printf( " " ); -// PRTn( "Syn", clkS ); - PRT( "Ver", clkV ); - } - } - Abc_NtkDelete( pNtkSyn ); - // report the results - if ( fFound ) - { - printf( "Parameters: " ); - Abc_NtkVectorPrintPars( vPiValues, nPars ); - printf( "\n" ); - printf( "Solved after %d interations. ", nIters ); - } - else if ( nIters == nIterMax ) - printf( "Unsolved after %d interations. ", nIters ); - else - printf( "Implementation does not exist. " ); - PRT( "Total runtime", clock() - clkTotal ); - Vec_IntFree( vPiValues ); -} - - -/**Function************************************************************* - - Synopsis [Translates model into the vector of values.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkModelToVector( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ) -{ - int * pModel, i; - pModel = pNtk->pModel; - for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) - Vec_IntWriteEntry( vPiValues, i, pModel[i] ); -} - -/**Function************************************************************* - - Synopsis [Clears parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkVectorClearPars( Vec_Int_t * vPiValues, int nPars ) -{ - int i; - for ( i = 0; i < nPars; i++ ) - Vec_IntWriteEntry( vPiValues, i, -1 ); -} - -/**Function************************************************************* - - Synopsis [Clears variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkVectorClearVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ) -{ - int i; - for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) - Vec_IntWriteEntry( vPiValues, i, -1 ); -} - -/**Function************************************************************* - - Synopsis [Clears variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkVectorPrintPars( Vec_Int_t * vPiValues, int nPars ) -{ - int i; - for ( i = 0; i < nPars; i++ ) - printf( "%d", Vec_IntEntry(vPiValues,i) ); -} - -/**Function************************************************************* - - Synopsis [Clears variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkVectorPrintVars( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues, int nPars ) -{ - int i; - for ( i = nPars; i < Abc_NtkPiNum(pNtk); i++ ) - printf( "%d", Vec_IntEntry(vPiValues,i) ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcQuant.c b/src/base/abci/abcQuant.c deleted file mode 100644 index 0f2bd72f..00000000 --- a/src/base/abci/abcQuant.c +++ /dev/null @@ -1,419 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcQuant.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [AIG-based variable quantification.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcQuant.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs fast synthesis.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkSynthesize( Abc_Ntk_t ** ppNtk, int fMoreEffort ) -{ - Abc_Ntk_t * pNtk, * pNtkTemp; - - pNtk = *ppNtk; - - Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); - pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); - Abc_NtkDelete( pNtkTemp ); - - if ( fMoreEffort ) - { - Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); - Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); - pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); - Abc_NtkDelete( pNtkTemp ); - } - - *ppNtk = pNtk; -} - -/**Function************************************************************* - - Synopsis [Existentially quantifies one variable.] - - Description [] - - SideEffects [This procedure creates dangling nodes in the AIG.] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pNext, * pFanin; - int i; - assert( Abc_NtkIsStrash(pNtk) ); - assert( iVar < Abc_NtkCiNum(pNtk) ); - - // collect the internal nodes - pObj = Abc_NtkCi( pNtk, iVar ); - vNodes = Abc_NtkDfsReverseNodes( pNtk, &pObj, 1 ); - - // assign the cofactors of the CI node to be constants - pObj->pCopy = Abc_ObjNot( Abc_AigConst1(pNtk) ); - pObj->pData = Abc_AigConst1(pNtk); - - // quantify the nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - for ( pNext = pObj? pObj->pCopy : pObj; pObj; pObj = pNext, pNext = pObj? pObj->pCopy : pObj ) - { - pFanin = Abc_ObjFanin0(pObj); - if ( !Abc_NodeIsTravIdCurrent(pFanin) ) - pFanin->pCopy = pFanin->pData = pFanin; - pFanin = Abc_ObjFanin1(pObj); - if ( !Abc_NodeIsTravIdCurrent(pFanin) ) - pFanin->pCopy = pFanin->pData = pFanin; - pObj->pCopy = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - pObj->pData = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Data(pObj), Abc_ObjChild1Data(pObj) ); - } - } - Vec_PtrFree( vNodes ); - - // update the affected COs - Abc_NtkForEachCo( pNtk, pObj, i ) - { - if ( !Abc_NodeIsTravIdCurrent(pObj) ) - continue; - pFanin = Abc_ObjFanin0(pObj); - // get the result of quantification - if ( fUniv ) - pNext = Abc_AigAnd( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) ); - else - pNext = Abc_AigOr( pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Data(pObj) ); - pNext = Abc_ObjNotCond( pNext, Abc_ObjFaninC0(pObj) ); - if ( Abc_ObjRegular(pNext) == pFanin ) - continue; - // update the fanins of the CO - Abc_ObjPatchFanin( pObj, pFanin, pNext ); -// if ( Abc_ObjFanoutNum(pFanin) == 0 ) -// Abc_AigDeleteNode( pNtk->pManFunc, pFanin ); - } - - // make sure the node has no fanouts -// pObj = Abc_NtkCi( pNtk, iVar ); -// assert( Abc_ObjFanoutNum(pObj) == 0 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Constructs the transition relation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose ) -{ - char Buffer[1000]; - Vec_Ptr_t * vPairs; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pMiter; - int i, nLatches; - int fSynthesis = 1; - - assert( Abc_NtkIsStrash(pNtk) ); - assert( Abc_NtkLatchNum(pNtk) ); - nLatches = Abc_NtkLatchNum(pNtk); - // start the network - pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - // duplicate the name and the spec - sprintf( Buffer, "%s_TR", pNtk->pName ); - pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); -// pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); - Abc_NtkCleanCopy( pNtk ); - // create current state variables - Abc_NtkForEachLatchOutput( pNtk, pObj, i ) - { - pObj->pCopy = Abc_NtkCreatePi(pNtkNew); - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); - } - // create next state variables - Abc_NtkForEachLatchInput( pNtk, pObj, i ) - Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pObj), NULL ); - // create PI variables - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 1 ); - // create the PO - Abc_NtkCreatePo( pNtkNew ); - // restrash the nodes (assuming a topological order of the old network) - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); - Abc_NtkForEachNode( pNtk, pObj, i ) - pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - // create the function of the primary output - assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); - vPairs = Vec_PtrAlloc( 2*nLatches ); - Abc_NtkForEachLatchInput( pNtk, pObj, i ) - { - Vec_PtrPush( vPairs, Abc_ObjChild0Copy(pObj) ); - Vec_PtrPush( vPairs, Abc_NtkPi(pNtkNew, i+nLatches) ); - } - pMiter = Abc_AigMiter( pNtkNew->pManFunc, vPairs ); - Vec_PtrFree( vPairs ); - // add the primary output - Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), Abc_ObjNot(pMiter) ); - Abc_ObjAssignName( Abc_NtkPo(pNtkNew,0), "rel", NULL ); - - // quantify inputs - if ( fInputs ) - { - assert( Abc_NtkPiNum(pNtkNew) == Abc_NtkPiNum(pNtk) + 2*nLatches ); - for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- ) -// for ( i = 2*nLatches; i < Abc_NtkPiNum(pNtkNew); i++ ) - { - Abc_NtkQuantify( pNtkNew, 0, i, fVerbose ); -// if ( fSynthesis && (i % 3 == 2) ) - if ( fSynthesis ) - { - Abc_NtkCleanData( pNtkNew ); - Abc_AigCleanup( pNtkNew->pManFunc ); - Abc_NtkSynthesize( &pNtkNew, 1 ); - } -// printf( "Var = %3d. Nodes = %6d. ", Abc_NtkPiNum(pNtkNew) - 1 - i, Abc_NtkNodeNum(pNtkNew) ); -// printf( "Var = %3d. Nodes = %6d. ", i - 2*nLatches, Abc_NtkNodeNum(pNtkNew) ); - } -// printf( "\n" ); - Abc_NtkCleanData( pNtkNew ); - Abc_AigCleanup( pNtkNew->pManFunc ); - for ( i = Abc_NtkPiNum(pNtkNew) - 1; i >= 2*nLatches; i-- ) - { - pObj = Abc_NtkPi( pNtkNew, i ); - assert( Abc_ObjFanoutNum(pObj) == 0 ); - Abc_NtkDeleteObj( pObj ); - } - } - - // check consistency of the network - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkTransRel: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - - -/**Function************************************************************* - - Synopsis [Performs one image computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkInitialState( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pMiter; - int i, nVars = Abc_NtkPiNum(pNtk)/2; - assert( Abc_NtkIsStrash(pNtk) ); - // start the new network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // compute the all-zero state in terms of the CS variables - pMiter = Abc_AigConst1(pNtkNew); - for ( i = 0; i < nVars; i++ ) - pMiter = Abc_AigAnd( pNtkNew->pManFunc, pMiter, Abc_ObjNot( Abc_NtkPi(pNtkNew, i) ) ); - // add the PO - Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Swaps current state and next state variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkSwapVariables( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pMiter, * pObj, * pObj0, * pObj1; - int i, nVars = Abc_NtkPiNum(pNtk)/2; - assert( Abc_NtkIsStrash(pNtk) ); - // start the new network - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // update the PIs - for ( i = 0; i < nVars; i++ ) - { - pObj0 = Abc_NtkPi( pNtk, i ); - pObj1 = Abc_NtkPi( pNtk, i+nVars ); - pMiter = pObj0->pCopy; - pObj0->pCopy = pObj1->pCopy; - pObj1->pCopy = pMiter; - } - // restrash - Abc_NtkForEachNode( pNtk, pObj, i ) - pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - // add the PO - pMiter = Abc_ObjChild0Copy( Abc_NtkPo(pNtk,0) ); - Abc_ObjAddFanin( Abc_NtkPo(pNtkNew,0), pMiter ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Performs reachability analisys.] - - Description [Assumes that the input is the transition relation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtkRel, int nIters, int fVerbose ) -{ - Abc_Obj_t * pObj; - Abc_Ntk_t * pNtkFront, * pNtkReached, * pNtkNext, * pNtkTemp; - int clk, i, v, nVars, nNodesOld, nNodesNew, nNodesPrev; - int fFixedPoint = 0; - int fSynthesis = 1; - int fMoreEffort = 1; - - assert( Abc_NtkIsStrash(pNtkRel) ); - assert( Abc_NtkLatchNum(pNtkRel) == 0 ); - assert( Abc_NtkPiNum(pNtkRel) % 2 == 0 ); - - // compute the network composed of the initial states - pNtkFront = Abc_NtkInitialState( pNtkRel ); - pNtkReached = Abc_NtkDup( pNtkFront ); -//Abc_NtkShow( pNtkReached, 0, 0, 0 ); - -// if ( fVerbose ) -// printf( "Transition relation = %6d.\n", Abc_NtkNodeNum(pNtkRel) ); - - // perform iterations of reachability analysis - nNodesPrev = Abc_NtkNodeNum(pNtkFront); - nVars = Abc_NtkPiNum(pNtkRel)/2; - for ( i = 0; i < nIters; i++ ) - { - clk = clock(); - // get the set of next states - pNtkNext = Abc_NtkMiterAnd( pNtkRel, pNtkFront, 0, 0 ); - Abc_NtkDelete( pNtkFront ); - // quantify the current state variables - for ( v = 0; v < nVars; v++ ) - { - Abc_NtkQuantify( pNtkNext, 0, v, fVerbose ); - if ( fSynthesis && (v % 3 == 2) ) - { - Abc_NtkCleanData( pNtkNext ); - Abc_AigCleanup( pNtkNext->pManFunc ); - Abc_NtkSynthesize( &pNtkNext, fMoreEffort ); - } - } - Abc_NtkCleanData( pNtkNext ); - Abc_AigCleanup( pNtkNext->pManFunc ); - if ( fSynthesis ) - Abc_NtkSynthesize( &pNtkNext, 1 ); - // map the next states into the current states - pNtkNext = Abc_NtkSwapVariables( pNtkTemp = pNtkNext ); - Abc_NtkDelete( pNtkTemp ); - // check the termination condition - if ( Abc_ObjFanin0(Abc_NtkPo(pNtkNext,0)) == Abc_AigConst1(pNtkNext) ) - { - fFixedPoint = 1; - printf( "Fixed point is reached!\n" ); - Abc_NtkDelete( pNtkNext ); - break; - } - // compute new front - pNtkFront = Abc_NtkMiterAnd( pNtkNext, pNtkReached, 0, 1 ); - Abc_NtkDelete( pNtkNext ); - // add the reached states - pNtkReached = Abc_NtkMiterAnd( pNtkTemp = pNtkReached, pNtkFront, 1, 0 ); - Abc_NtkDelete( pNtkTemp ); - // compress the size of Front - nNodesOld = Abc_NtkNodeNum(pNtkFront); - if ( fSynthesis ) - { - Abc_NtkSynthesize( &pNtkFront, fMoreEffort ); - Abc_NtkSynthesize( &pNtkReached, fMoreEffort ); - } - nNodesNew = Abc_NtkNodeNum(pNtkFront); - // print statistics - if ( fVerbose ) - { - printf( "I = %3d : Reach = %6d Fr = %6d FrM = %6d %7.2f %% ", - i + 1, Abc_NtkNodeNum(pNtkReached), nNodesOld, nNodesNew, 100.0*(nNodesNew-nNodesPrev)/nNodesPrev ); - PRT( "T", clock() - clk ); - } - nNodesPrev = Abc_NtkNodeNum(pNtkFront); - } - if ( !fFixedPoint ) - fprintf( stdout, "Reachability analysis stopped after %d iterations.\n", nIters ); - - // complement the output to represent the set of unreachable states - Abc_ObjXorFaninC( Abc_NtkPo(pNtkReached,0), 0 ); - - // remove next state variables - for ( i = 2*nVars - 1; i >= nVars; i-- ) - { - pObj = Abc_NtkPi( pNtkReached, i ); - assert( Abc_ObjFanoutNum(pObj) == 0 ); - Abc_NtkDeleteObj( pObj ); - } - - // check consistency of the network - if ( !Abc_NtkCheck( pNtkReached ) ) - { - printf( "Abc_NtkReachability: The network check has failed.\n" ); - Abc_NtkDelete( pNtkReached ); - return NULL; - } - return pNtkReached; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcRec.c b/src/base/abci/abcRec.c deleted file mode 100644 index a6ec6981..00000000 --- a/src/base/abci/abcRec.c +++ /dev/null @@ -1,1173 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcRec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Record of semi-canonical AIG subgraphs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcRec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "if.h" -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Abc_ManRec_t_ Abc_ManRec_t; -struct Abc_ManRec_t_ -{ - Abc_Ntk_t * pNtk; // the record - Vec_Ptr_t * vTtElems; // the elementary truth tables - Vec_Ptr_t * vTtNodes; // the node truth tables - Abc_Obj_t ** pBins; // hash table mapping truth tables into nodes - int nBins; // the number of allocated bins - int nVars; // the number of variables - int nVarsInit; // the number of variables requested initially - int nWords; // the number of TT words - int nCuts; // the max number of cuts to use - // temporaries - int * pBytes; // temporary storage for minterms - int * pMints; // temporary storage for minterm counters - unsigned * pTemp1; // temporary truth table - unsigned * pTemp2; // temporary truth table - Vec_Ptr_t * vNodes; // the temporary nodes - Vec_Ptr_t * vTtTemps; // the truth tables for the internal nodes of the cut - Vec_Ptr_t * vLabels; // temporary storage for AIG node labels - Vec_Str_t * vCosts; // temporary storage for costs - Vec_Int_t * vMemory; // temporary memory for truth tables - // statistics - int nTried; // the number of cuts tried - int nFilterSize; // the number of same structures - int nFilterRedund; // the number of same structures - int nFilterVolume; // the number of same structures - int nFilterTruth; // the number of same structures - int nFilterError; // the number of same structures - int nFilterSame; // the number of same structures - int nAdded; // the number of subgraphs added - int nAddedFuncs; // the number of functions added - // rewriting - int nFunsFound; // the found functions - int nFunsNotFound; // the missing functions - // runtime - int timeCollect; // the runtime to canonicize - int timeTruth; // the runtime to canonicize - int timeCanon; // the runtime to canonicize - int timeOther; // the runtime to canonicize - int timeTotal; // the runtime to canonicize -}; - -// the truth table is canonicized in such a way that for (00000) its value is 0 - -static Abc_Obj_t ** Abc_NtkRecTableLookup( Abc_ManRec_t * p, unsigned * pTruth, int nVars ); -static int Abc_NtkRecComputeTruth( Abc_Obj_t * pObj, Vec_Ptr_t * vTtNodes, int nVars ); -static int Abc_NtkRecAddCutCheckCycle_rec( Abc_Obj_t * pRoot, Abc_Obj_t * pObj ); - -static Abc_ManRec_t * s_pMan = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the record for the given network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRecIsRunning() -{ - return s_pMan != NULL; -} - -/**Function************************************************************* - - Synopsis [Starts the record for the given network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRecVarNum() -{ - return (s_pMan != NULL)? s_pMan->nVars : -1; -} - -/**Function************************************************************* - - Synopsis [Starts the record for the given network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkRecMemory() -{ - return s_pMan->vMemory; -} - -/**Function************************************************************* - - Synopsis [Starts the record for the given network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRecStart( Abc_Ntk_t * pNtk, int nVars, int nCuts ) -{ - Abc_ManRec_t * p; - Abc_Obj_t * pObj, ** ppSpot; - char Buffer[10]; - unsigned * pTruth; - int i, RetValue; - int clkTotal = clock(), clk; - - assert( s_pMan == NULL ); - if ( pNtk == NULL ) - { - assert( nVars > 2 && nVars <= 16 ); - pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - pNtk->pName = Extra_UtilStrsav( "record" ); - } - else - { - if ( Abc_NtkGetChoiceNum(pNtk) > 0 ) - { - printf( "The starting record should be a network without choice nodes.\n" ); - return; - } - if ( Abc_NtkPiNum(pNtk) > 16 ) - { - printf( "The starting record should be a network with no more than %d primary inputs.\n", 16 ); - return; - } - if ( Abc_NtkPiNum(pNtk) > nVars ) - printf( "The starting record has %d inputs (warning only).\n", Abc_NtkPiNum(pNtk) ); - pNtk = Abc_NtkDup( pNtk ); - } - // create the primary inputs - for ( i = Abc_NtkPiNum(pNtk); i < nVars; i++ ) - { - pObj = Abc_NtkCreatePi( pNtk ); - Buffer[0] = 'a' + i; - Buffer[1] = 0; - Abc_ObjAssignName( pObj, Buffer, NULL ); - } - Abc_NtkCleanCopy( pNtk ); - Abc_NtkCleanEquiv( pNtk ); - - // start the manager - p = ALLOC( Abc_ManRec_t, 1 ); - memset( p, 0, sizeof(Abc_ManRec_t) ); - p->pNtk = pNtk; - p->nVars = Abc_NtkPiNum(pNtk); - p->nWords = Kit_TruthWordNum( p->nVars ); - p->nCuts = nCuts; - p->nVarsInit = nVars; - - // create elementary truth tables - p->vTtElems = Vec_PtrAlloc( 0 ); assert( p->vTtElems->pArray == NULL ); - p->vTtElems->nSize = p->nVars; - p->vTtElems->nCap = p->nVars; - p->vTtElems->pArray = (void *)Extra_TruthElementary( p->nVars ); - - // allocate room for node truth tables - if ( Abc_NtkObjNum(pNtk) > (1<<14) ) - p->vTtNodes = Vec_PtrAllocSimInfo( 2 * Abc_NtkObjNum(pNtk), p->nWords ); - else - p->vTtNodes = Vec_PtrAllocSimInfo( 1<<14, p->nWords ); - - // create hash table - p->nBins = 50011; - p->pBins = ALLOC( Abc_Obj_t *, p->nBins ); - memset( p->pBins, 0, sizeof(Abc_Obj_t *) * p->nBins ); - - // set elementary tables - Kit_TruthFill( Vec_PtrEntry(p->vTtNodes, 0), p->nVars ); - Abc_NtkForEachPi( pNtk, pObj, i ) - Kit_TruthCopy( Vec_PtrEntry(p->vTtNodes, pObj->Id), Vec_PtrEntry(p->vTtElems, i), p->nVars ); - - // compute the tables -clk = clock(); - Abc_AigForEachAnd( pNtk, pObj, i ) - { - RetValue = Abc_NtkRecComputeTruth( pObj, p->vTtNodes, p->nVars ); - assert( RetValue ); - } -p->timeTruth += clock() - clk; - - // insert the PO nodes into the table - Abc_NtkForEachPo( pNtk, pObj, i ) - { - p->nTried++; - p->nAdded++; - - pObj = Abc_ObjFanin0(pObj); - pTruth = Vec_PtrEntry( p->vTtNodes, pObj->Id ); - - if ( pTruth[0] == 1128481603 ) - { - int x = 0; - } - - // add the resulting truth table to the hash table - ppSpot = Abc_NtkRecTableLookup( p, pTruth, p->nVars ); - assert( pObj->pEquiv == NULL ); - assert( pObj->pCopy == NULL ); - if ( *ppSpot == NULL ) - { - p->nAddedFuncs++; - *ppSpot = pObj; - } - else - { - pObj->pEquiv = (*ppSpot)->pEquiv; - (*ppSpot)->pEquiv = (Hop_Obj_t *)pObj; - if ( !Abc_NtkRecAddCutCheckCycle_rec(*ppSpot, pObj) ) - printf( "Loop!\n" ); - } - } - - // temporaries - p->pBytes = ALLOC( int, 4*p->nWords ); - p->pMints = ALLOC( int, 2*p->nVars ); - p->pTemp1 = ALLOC( unsigned, p->nWords ); - p->pTemp2 = ALLOC( unsigned, p->nWords ); - p->vNodes = Vec_PtrAlloc( 100 ); - p->vTtTemps = Vec_PtrAllocSimInfo( 64, p->nWords ); - p->vMemory = Vec_IntAlloc( Abc_TruthWordNum(p->nVars) * 1000 ); - - // set the manager - s_pMan = p; -p->timeTotal += clock() - clkTotal; -} - -/**Function************************************************************* - - Synopsis [Returns the given record.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRecStop() -{ - assert( s_pMan != NULL ); - if ( s_pMan->pNtk ) - Abc_NtkDelete( s_pMan->pNtk ); - Vec_PtrFree( s_pMan->vTtNodes ); - Vec_PtrFree( s_pMan->vTtElems ); - free( s_pMan->pBins ); - - // temporaries - free( s_pMan->pBytes ); - free( s_pMan->pMints ); - free( s_pMan->pTemp1 ); - free( s_pMan->pTemp2 ); - Vec_PtrFree( s_pMan->vNodes ); - Vec_PtrFree( s_pMan->vTtTemps ); - if ( s_pMan->vLabels ) - Vec_PtrFree( s_pMan->vLabels ); - if ( s_pMan->vCosts ) - Vec_StrFree( s_pMan->vCosts ); - Vec_IntFree( s_pMan->vMemory ); - - free( s_pMan ); - s_pMan = NULL; -} - -/**Function************************************************************* - - Synopsis [Returns the given record.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkRecUse() -{ - Abc_ManRec_t * p = s_pMan; - Abc_Ntk_t * pNtk = p->pNtk; - assert( p != NULL ); - Abc_NtkRecPs(); - p->pNtk = NULL; - Abc_NtkRecStop(); - return pNtk; -} - -static inline void Abc_ObjSetMax( Abc_Obj_t * pObj, int Value ) { assert( pObj->Level < 0xff ); pObj->Level = (Value << 8) | (pObj->Level & 0xff); } -static inline void Abc_ObjClearMax( Abc_Obj_t * pObj ) { pObj->Level = (pObj->Level & 0xff); } -static inline int Abc_ObjGetMax( Abc_Obj_t * pObj ) { return (pObj->Level >> 8) & 0xff; } - -/**Function************************************************************* - - Synopsis [Print statistics about the current record.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRecPs() -{ - int Counter, Counters[17] = {0}; - int CounterS, CountersS[17] = {0}; - Abc_ManRec_t * p = s_pMan; - Abc_Ntk_t * pNtk = p->pNtk; - Abc_Obj_t * pObj, * pEntry, * pTemp; - int i; - - // set the max PI number - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjSetMax( pObj, i+1 ); - Abc_AigForEachAnd( pNtk, pObj, i ) - Abc_ObjSetMax( pObj, ABC_MAX( Abc_ObjGetMax(Abc_ObjFanin0(pObj)), Abc_ObjGetMax(Abc_ObjFanin1(pObj)) ) ); - // go through the table - Counter = CounterS = 0; - for ( i = 0; i < p->nBins; i++ ) - for ( pEntry = p->pBins[i]; pEntry; pEntry = pEntry->pCopy ) - { - Counters[ Abc_ObjGetMax(pEntry) ]++; - Counter++; - for ( pTemp = pEntry; pTemp; pTemp = (Abc_Obj_t *)pTemp->pEquiv ) - { - assert( Abc_ObjGetMax(pTemp) == Abc_ObjGetMax(pEntry) ); - CountersS[ Abc_ObjGetMax(pTemp) ]++; - CounterS++; - } - } -// printf( "Functions = %d. Expected = %d.\n", Counter, p->nAddedFuncs ); -// printf( "Subgraphs = %d. Expected = %d.\n", CounterS, p->nAdded ); - assert( Counter == p->nAddedFuncs ); - assert( CounterS == p->nAdded ); - - // clean - Abc_NtkForEachObj( pNtk, pObj, i ) - { - Abc_ObjClearMax( pObj ); - } - - printf( "The record with %d AND nodes in %d subgraphs for %d functions with %d inputs:\n", - Abc_NtkNodeNum(pNtk), Abc_NtkPoNum(pNtk), p->nAddedFuncs, Abc_NtkPiNum(pNtk) ); - for ( i = 0; i <= 16; i++ ) - { - if ( Counters[i] ) - printf( "Inputs = %2d. Funcs = %8d. Subgrs = %8d. Ratio = %6.2f.\n", i, Counters[i], CountersS[i], 1.0*CountersS[i]/Counters[i] ); - } - - printf( "Subgraphs tried = %8d. (%6.2f %%)\n", p->nTried, !p->nTried? 0 : 100.0*p->nTried/p->nTried ); - printf( "Subgraphs filtered by support size = %8d. (%6.2f %%)\n", p->nFilterSize, !p->nTried? 0 : 100.0*p->nFilterSize/p->nTried ); - printf( "Subgraphs filtered by structural redundancy = %8d. (%6.2f %%)\n", p->nFilterRedund, !p->nTried? 0 : 100.0*p->nFilterRedund/p->nTried ); - printf( "Subgraphs filtered by volume = %8d. (%6.2f %%)\n", p->nFilterVolume, !p->nTried? 0 : 100.0*p->nFilterVolume/p->nTried ); - printf( "Subgraphs filtered by TT redundancy = %8d. (%6.2f %%)\n", p->nFilterTruth, !p->nTried? 0 : 100.0*p->nFilterTruth/p->nTried ); - printf( "Subgraphs filtered by error = %8d. (%6.2f %%)\n", p->nFilterError, !p->nTried? 0 : 100.0*p->nFilterError/p->nTried ); - printf( "Subgraphs filtered by isomorphism = %8d. (%6.2f %%)\n", p->nFilterSame, !p->nTried? 0 : 100.0*p->nFilterSame/p->nTried ); - printf( "Subgraphs added = %8d. (%6.2f %%)\n", p->nAdded, !p->nTried? 0 : 100.0*p->nAdded/p->nTried ); - printf( "Functions added = %8d. (%6.2f %%)\n", p->nAddedFuncs, !p->nTried? 0 : 100.0*p->nAddedFuncs/p->nTried ); - - p->timeOther = p->timeTotal - p->timeCollect - p->timeTruth - p->timeCanon; - PRTP( "Collecting nodes ", p->timeCollect, p->timeTotal ); - PRTP( "Computing truth ", p->timeTruth, p->timeTotal ); - PRTP( "Canonicizing ", p->timeCanon, p->timeTotal ); - PRTP( "Other ", p->timeOther, p->timeTotal ); - PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); - if ( p->nFunsFound ) - printf( "During rewriting found = %d and not found = %d functions.\n", p->nFunsFound, p->nFunsNotFound ); -} - -/**Function************************************************************* - - Synopsis [Filters the current record.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRecFilter( int iVar, int iPlus ) -{ -} - -/**Function************************************************************* - - Synopsis [Returns the hash key.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Abc_NtkRecTableHash( unsigned * pTruth, int nVars, int nBins, int * pPrimes ) -{ - int i, nWords = Kit_TruthWordNum( nVars ); - unsigned uHash = 0; - for ( i = 0; i < nWords; i++ ) - uHash ^= pTruth[i] * pPrimes[i & 0x7]; - return uHash % nBins; -} - -/**Function************************************************************* - - Synopsis [Returns the given record.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t ** Abc_NtkRecTableLookup( Abc_ManRec_t * p, unsigned * pTruth, int nVars ) -{ - static int s_Primes[10] = { 1291, 1699, 2357, 4177, 5147, 5647, 6343, 7103, 7873, 8147 }; - Abc_Obj_t ** ppSpot, * pEntry; - ppSpot = p->pBins + Abc_NtkRecTableHash( pTruth, nVars, p->nBins, s_Primes ); - for ( pEntry = *ppSpot; pEntry; ppSpot = &pEntry->pCopy, pEntry = pEntry->pCopy ) - if ( Kit_TruthIsEqualWithPhase(Vec_PtrEntry(p->vTtNodes, pEntry->Id), pTruth, nVars) ) - return ppSpot; - return ppSpot; -} - -/**Function************************************************************* - - Synopsis [Computes the truth table of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRecComputeTruth( Abc_Obj_t * pObj, Vec_Ptr_t * vTtNodes, int nVars ) -{ - unsigned * pTruth, * pTruth0, * pTruth1; - int RetValue; - assert( Abc_ObjIsNode(pObj) ); - pTruth = Vec_PtrEntry( vTtNodes, pObj->Id ); - pTruth0 = Vec_PtrEntry( vTtNodes, Abc_ObjFaninId0(pObj) ); - pTruth1 = Vec_PtrEntry( vTtNodes, Abc_ObjFaninId1(pObj) ); - Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); - assert( (pTruth[0] & 1) == pObj->fPhase ); - RetValue = ((pTruth[0] & 1) == pObj->fPhase); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Performs renoding as technology mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRecAdd( Abc_Ntk_t * pNtk ) -{ - extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); - extern int Abc_NtkRecAddCut( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut ); - - If_Par_t Pars, * pPars = &Pars; - Abc_Ntk_t * pNtkNew; - int clk = clock(); - - if ( Abc_NtkGetChoiceNum( pNtk ) ) - printf( "Performing renoding with choices.\n" ); - - // set defaults - memset( pPars, 0, sizeof(If_Par_t) ); - // user-controlable paramters - pPars->nLutSize = s_pMan->nVarsInit; - pPars->nCutsMax = s_pMan->nCuts; - pPars->nFlowIters = 0; - pPars->nAreaIters = 0; - pPars->DelayTarget = -1; - pPars->fPreprocess = 0; - pPars->fArea = 1; - pPars->fFancy = 0; - pPars->fExpRed = 0; - pPars->fLatchPaths = 0; - pPars->fSeqMap = 0; - pPars->fVerbose = 0; - // internal parameters - pPars->fTruth = 0; - pPars->fUsePerm = 0; - pPars->nLatches = 0; - pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); - pPars->pTimesArr = NULL; - pPars->pTimesArr = NULL; - pPars->fUseBdds = 0; - pPars->fUseSops = 0; - pPars->fUseCnfs = 0; - pPars->fUseMv = 0; - pPars->pFuncCost = NULL; - pPars->pFuncUser = Abc_NtkRecAddCut; - - // perform recording - pNtkNew = Abc_NtkIf( pNtk, pPars ); - Abc_NtkDelete( pNtkNew ); -s_pMan->timeTotal += clock() - clk; - -// if ( !Abc_NtkCheck( s_pMan->pNtk ) ) -// printf( "Abc_NtkRecAdd: The network check has failed.\n" ); -} - -/**Function************************************************************* - - Synopsis [Adds the cut function to the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRecCollectNodes_rec( If_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - if ( pNode->fMark ) - return; - pNode->fMark = 1; - assert( If_ObjIsAnd(pNode) ); - Abc_NtkRecCollectNodes_rec( If_ObjFanin0(pNode), vNodes ); - Abc_NtkRecCollectNodes_rec( If_ObjFanin1(pNode), vNodes ); - Vec_PtrPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Adds the cut function to the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRecCollectNodes( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut, Vec_Ptr_t * vNodes ) -{ - If_Obj_t * pLeaf; - int i, RetValue = 1; - - // collect the internal nodes of the cut - Vec_PtrClear( vNodes ); - If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) - { - Vec_PtrPush( vNodes, pLeaf ); - assert( pLeaf->fMark == 0 ); - pLeaf->fMark = 1; - } - - // collect other nodes - Abc_NtkRecCollectNodes_rec( pRoot, vNodes ); - - // check if there are leaves, such that both of their fanins are marked - // this indicates a redundant cut - If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) - { - if ( !If_ObjIsAnd(pLeaf) ) - continue; - if ( If_ObjFanin0(pLeaf)->fMark && If_ObjFanin1(pLeaf)->fMark ) - { - RetValue = 0; - break; - } - } - - // clean the mark - Vec_PtrForEachEntry( vNodes, pLeaf, i ) - pLeaf->fMark = 0; -/* - if ( pRoot->Id == 2639 ) - { - // print the cut - Vec_PtrForEachEntry( vNodes, pLeaf, i ) - { - if ( If_ObjIsAnd(pLeaf) ) - printf( "%4d = %c%4d & %c%4d\n", pLeaf->Id, - (If_ObjFaninC0(pLeaf)? '-':'+'), If_ObjFanin0(pLeaf)->Id, - (If_ObjFaninC1(pLeaf)? '-':'+'), If_ObjFanin1(pLeaf)->Id ); - else - printf( "%4d = pi\n", pLeaf->Id ); - } - printf( "\n" ); - } -*/ - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Computes truth tables of nodes in the cut.] - - Description [Returns 0 if the TT does not depend on some cut variables. - Or if the TT can be expressed simpler using other nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRecCutTruth( Vec_Ptr_t * vNodes, int nLeaves, Vec_Ptr_t * vTtTemps, Vec_Ptr_t * vTtElems ) -{ - unsigned * pSims, * pSims0, * pSims1; - unsigned * pTemp = s_pMan->pTemp2; - unsigned uWord; - If_Obj_t * pObj, * pObj2, * pRoot; - int i, k, nLimit, nInputs = s_pMan->nVars; - - assert( Vec_PtrSize(vNodes) > nLeaves ); - - // set the elementary truth tables and compute the truth tables of the nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - pObj->pCopy = Vec_PtrEntry(vTtTemps, i); - pSims = (unsigned *)pObj->pCopy; - if ( i < nLeaves ) - { - Kit_TruthCopy( pSims, Vec_PtrEntry(vTtElems, i), nInputs ); - continue; - } - assert( If_ObjIsAnd(pObj) ); - // get hold of the simulation information - pSims0 = (unsigned *)If_ObjFanin0(pObj)->pCopy; - pSims1 = (unsigned *)If_ObjFanin1(pObj)->pCopy; - // simulate the node - Kit_TruthAndPhase( pSims, pSims0, pSims1, nInputs, If_ObjFaninC0(pObj), If_ObjFaninC1(pObj) ); - } - - // check the support size - pRoot = Vec_PtrEntryLast( vNodes ); - pSims = (unsigned *)pRoot->pCopy; - if ( Kit_TruthSupport(pSims, nInputs) != Kit_BitMask(nLeaves) ) - return 0; - - // make sure none of the nodes has the same simulation info as the output - // check pairwise comparisons - nLimit = Vec_PtrSize(vNodes) - 1; - Vec_PtrForEachEntryStop( vNodes, pObj, i, nLimit ) - { - pSims0 = (unsigned *)pObj->pCopy; - if ( Kit_TruthIsEqualWithPhase(pSims, pSims0, nInputs) ) - return 0; - Vec_PtrForEachEntryStop( vNodes, pObj2, k, i ) - { - if ( (If_ObjFanin0(pRoot) == pObj && If_ObjFanin1(pRoot) == pObj2) || - (If_ObjFanin1(pRoot) == pObj && If_ObjFanin0(pRoot) == pObj2) ) - continue; - pSims1 = (unsigned *)pObj2->pCopy; - - uWord = pSims0[0] & pSims1[0]; - if ( pSims[0] == uWord || pSims[0] == ~uWord ) - { - Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 0 ); - if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) - return 0; - } - - uWord = pSims0[0] & ~pSims1[0]; - if ( pSims[0] == uWord || pSims[0] == ~uWord ) - { - Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 0, 1 ); - if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) - return 0; - } - - uWord = ~pSims0[0] & pSims1[0]; - if ( pSims[0] == uWord || pSims[0] == ~uWord ) - { - Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 0 ); - if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) - return 0; - } - - uWord = ~pSims0[0] & ~pSims1[0]; - if ( pSims[0] == uWord || pSims[0] == ~uWord ) - { - Kit_TruthAndPhase( pTemp, pSims0, pSims1, nInputs, 1, 1 ); - if ( Kit_TruthIsEqualWithPhase(pSims, pTemp, nInputs) ) - return 0; - } - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Adds the cut function to the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRecAddCutCheckCycle_rec( Abc_Obj_t * pRoot, Abc_Obj_t * pObj ) -{ - assert( pRoot->Level > 0 ); - if ( pObj->Level < pRoot->Level ) - return 1; - if ( pObj == pRoot ) - return 0; - if ( !Abc_NtkRecAddCutCheckCycle_rec(pRoot, Abc_ObjFanin0(pObj)) ) - return 0; - if ( !Abc_NtkRecAddCutCheckCycle_rec(pRoot, Abc_ObjFanin1(pObj)) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Adds the cut function to the internal storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRecAddCut( If_Man_t * pIfMan, If_Obj_t * pRoot, If_Cut_t * pCut ) -{ - static int s_MaxSize[16] = { 0 }; - char Buffer[40], Name[20], Truth[20]; - char pCanonPerm[16]; - Abc_Obj_t * pObj, * pFanin0, * pFanin1, ** ppSpot, * pObjPo; - Abc_Ntk_t * pAig = s_pMan->pNtk; - If_Obj_t * pIfObj; - Vec_Ptr_t * vNodes = s_pMan->vNodes; - unsigned * pInOut = s_pMan->pTemp1; - unsigned * pTemp = s_pMan->pTemp2; - unsigned * pTruth; - int i, RetValue, nNodes, nNodesBeg, nInputs = s_pMan->nVars, nLeaves = If_CutLeaveNum(pCut); - unsigned uCanonPhase; - int clk; - - if ( pRoot->Id == 2639 ) - { - int y = 0; - } - - assert( nInputs <= 16 ); - assert( nInputs == (int)pCut->nLimit ); - s_pMan->nTried++; - - // skip small cuts - if ( nLeaves < 3 ) - { - s_pMan->nFilterSize++; - return 1; - } - - // collect internal nodes and skip redundant cuts -clk = clock(); - RetValue = Abc_NtkRecCollectNodes( pIfMan, pRoot, pCut, vNodes ); -s_pMan->timeCollect += clock() - clk; - if ( !RetValue ) - { - s_pMan->nFilterRedund++; - return 1; - } - - // skip cuts with very large volume - if ( Vec_PtrSize(vNodes) > nLeaves + 3*(nLeaves-1) + s_MaxSize[nLeaves] ) - { - s_pMan->nFilterVolume++; - return 1; - } - - // compute truth table and skip the redundant structures -clk = clock(); - RetValue = Abc_NtkRecCutTruth( vNodes, nLeaves, s_pMan->vTtTemps, s_pMan->vTtElems ); -s_pMan->timeTruth += clock() - clk; - if ( !RetValue ) - { - s_pMan->nFilterTruth++; - return 1; - } - - // copy the truth table - Kit_TruthCopy( pInOut, (unsigned *)pRoot->pCopy, nInputs ); - - // set permutation - for ( i = 0; i < nInputs; i++ ) - pCanonPerm[i] = i; - - // semi-canonicize the truth table -clk = clock(); - uCanonPhase = Kit_TruthSemiCanonicize( pInOut, pTemp, nInputs, pCanonPerm, (short *)s_pMan->pMints ); -s_pMan->timeCanon += clock() - clk; - // pCanonPerm and uCanonPhase show what was the variable corresponding to each var in the current truth - - // go through the variables in the new truth table - for ( i = 0; i < nLeaves; i++ ) - { - // get hold of the corresponding leaf - pIfObj = If_ManObj( pIfMan, pCut->pLeaves[pCanonPerm[i]] ); - // get hold of the corresponding new node - pObj = Abc_NtkPi( pAig, i ); - pObj = Abc_ObjNotCond( pObj, (uCanonPhase & (1 << i)) ); - // map them - pIfObj->pCopy = pObj; -/* - if ( pRoot->Id == 2639 ) - { - unsigned uSupp; - printf( "Node %6d : ", pIfObj->Id ); - printf( "Support " ); - uSupp = Kit_TruthSupport(Vec_PtrEntry( s_pMan->vTtNodes, Abc_ObjRegular(pObj)->Id ), nInputs); - Extra_PrintBinary( stdout, &uSupp, nInputs ); - printf( " " ); - Extra_PrintBinary( stdout, Vec_PtrEntry( s_pMan->vTtNodes, Abc_ObjRegular(pObj)->Id ), 1<<6 ); - printf( "\n" ); - } -*/ - } - - // build the node and compute its truth table - nNodesBeg = Abc_NtkObjNumMax( pAig ); - Vec_PtrForEachEntryStart( vNodes, pIfObj, i, nLeaves ) - { - pFanin0 = Abc_ObjNotCond( If_ObjFanin0(pIfObj)->pCopy, If_ObjFaninC0(pIfObj) ); - pFanin1 = Abc_ObjNotCond( If_ObjFanin1(pIfObj)->pCopy, If_ObjFaninC1(pIfObj) ); - - nNodes = Abc_NtkObjNumMax( pAig ); - pObj = Abc_AigAnd( pAig->pManFunc, pFanin0, pFanin1 ); - assert( !Abc_ObjIsComplement(pObj) ); - pIfObj->pCopy = pObj; - - if ( pObj->Id == nNodes ) - { - // increase storage for truth tables - if ( Vec_PtrSize(s_pMan->vTtNodes) <= pObj->Id ) - Vec_PtrDoubleSimInfo(s_pMan->vTtNodes); - // compute the truth table - RetValue = Abc_NtkRecComputeTruth( pObj, s_pMan->vTtNodes, nInputs ); - if ( RetValue == 0 ) - { - s_pMan->nFilterError++; - printf( "T" ); - return 1; - } - } - } - - pTruth = Vec_PtrEntry( s_pMan->vTtNodes, pObj->Id ); - if ( Kit_TruthSupport(pTruth, nInputs) != Kit_BitMask(nLeaves) ) - { - s_pMan->nFilterError++; - printf( "S" ); - return 1; - } - - // compare the truth tables - if ( !Kit_TruthIsEqualWithPhase( pTruth, pInOut, nInputs ) ) - { - s_pMan->nFilterError++; - printf( "F" ); - return 1; - } -// Extra_PrintBinary( stdout, pInOut, 8 ); printf( "\n" ); - - // if not new nodes were added and the node has a CO fanout - if ( nNodesBeg == Abc_NtkObjNumMax(pAig) && Abc_NodeFindCoFanout(pObj) != NULL ) - { - s_pMan->nFilterSame++; - return 1; - } - s_pMan->nAdded++; - - // create PO for this node - pObjPo = Abc_NtkCreatePo(pAig); - Abc_ObjAddFanin( pObjPo, pObj ); - - // assign the name to this PO - sprintf( Name, "%d_%06d", nLeaves, Abc_NtkPoNum(pAig) ); - if ( (nInputs <= 6) && 0 ) - { - Extra_PrintHexadecimalString( Truth, pInOut, nInputs ); - sprintf( Buffer, "%s_%s", Name, Truth ); - } - else - { - sprintf( Buffer, "%s", Name ); - } - Abc_ObjAssignName( pObjPo, Buffer, NULL ); - - // add the resulting truth table to the hash table - ppSpot = Abc_NtkRecTableLookup( s_pMan, pTruth, nInputs ); - assert( pObj->pEquiv == NULL ); - assert( pObj->pCopy == NULL ); - if ( *ppSpot == NULL ) - { - s_pMan->nAddedFuncs++; - *ppSpot = pObj; - } - else - { - pObj->pEquiv = (*ppSpot)->pEquiv; - (*ppSpot)->pEquiv = (Hop_Obj_t *)pObj; - if ( !Abc_NtkRecAddCutCheckCycle_rec(*ppSpot, pObj) ) - printf( "Loop!\n" ); - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Labels the record AIG with the corresponding new AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkRecStrashNodeLabel_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fBuild, Vec_Ptr_t * vLabels ) -{ - Abc_Obj_t * pFanin0New, * pFanin1New, * pLabel; - assert( !Abc_ObjIsComplement(pObj) ); - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pObj ) ) - return Vec_PtrEntry( vLabels, pObj->Id ); - assert( Abc_ObjIsNode(pObj) ); - // mark the node as visited - Abc_NodeSetTravIdCurrent( pObj ); - // label the fanins - pFanin0New = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, Abc_ObjFanin0(pObj), fBuild, vLabels ); - pFanin1New = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, Abc_ObjFanin1(pObj), fBuild, vLabels ); - // label the node if possible - pLabel = NULL; - if ( pFanin0New && pFanin1New ) - { - pFanin0New = Abc_ObjNotCond( pFanin0New, Abc_ObjFaninC0(pObj) ); - pFanin1New = Abc_ObjNotCond( pFanin1New, Abc_ObjFaninC1(pObj) ); - if ( fBuild ) - pLabel = Abc_AigAnd( pNtkNew->pManFunc, pFanin0New, pFanin1New ); - else - pLabel = Abc_AigAndLookup( pNtkNew->pManFunc, pFanin0New, pFanin1New ); - } - Vec_PtrWriteEntry( vLabels, pObj->Id, pLabel ); - return pLabel; -} - -/**Function************************************************************* - - Synopsis [Counts the area of the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRecStrashNodeCount_rec( Abc_Obj_t * pObj, Vec_Str_t * vCosts, Vec_Ptr_t * vLabels ) -{ - int Cost0, Cost1; - if ( Vec_PtrEntry( vLabels, pObj->Id ) ) - return 0; - assert( Abc_ObjIsNode(pObj) ); - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pObj ) ) - return Vec_StrEntry( vCosts, pObj->Id ); - // mark the node as visited - Abc_NodeSetTravIdCurrent( pObj ); - // count for the fanins - Cost0 = Abc_NtkRecStrashNodeCount_rec( Abc_ObjFanin0(pObj), vCosts, vLabels ); - Cost1 = Abc_NtkRecStrashNodeCount_rec( Abc_ObjFanin1(pObj), vCosts, vLabels ); - Vec_StrWriteEntry( vCosts, pObj->Id, (char)(Cost0 + Cost1 + 1) ); - return Cost0 + Cost1 + 1; -} - -/**Function************************************************************* - - Synopsis [Strashes the given node using its local function.] - - Description [Assumes that the fanins are already strashed. - Returns 0 if the function is not found in the table.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ) -{ - char pCanonPerm[16]; - Abc_Ntk_t * pAig = s_pMan->pNtk; - unsigned * pInOut = s_pMan->pTemp1; - unsigned * pTemp = s_pMan->pTemp2; - unsigned * pTruthRec; - Abc_Obj_t * pCand, * pCandMin, * pLeaf, * pFanin, ** ppSpot; - unsigned uCanonPhase; - int i, nLeaves, CostMin, Cost, nOnes, fCompl; - - // check if the record works - nLeaves = Abc_ObjFaninNum(pObj); - assert( nLeaves >= 3 && nLeaves <= s_pMan->nVars ); - pFanin = Abc_ObjFanin0(pObj); - assert( Abc_ObjRegular(pFanin->pCopy)->pNtk == pNtkNew ); - assert( s_pMan != NULL ); - assert( nVars == s_pMan->nVars ); - - // copy the truth table - Kit_TruthCopy( pInOut, pTruth, nVars ); - - // set permutation - for ( i = 0; i < nVars; i++ ) - pCanonPerm[i] = i; - - // canonicize the truth table - uCanonPhase = Kit_TruthSemiCanonicize( pInOut, pTemp, nVars, pCanonPerm, (short *)s_pMan->pMints ); - - // get hold of the curresponding class - ppSpot = Abc_NtkRecTableLookup( s_pMan, pInOut, nVars ); - if ( *ppSpot == NULL ) - { - s_pMan->nFunsNotFound++; -// printf( "The class of a function with %d inputs is not found.\n", nLeaves ); - return 0; - } - s_pMan->nFunsFound++; - - // make sure the truth table is the same - pTruthRec = Vec_PtrEntry( s_pMan->vTtNodes, (*ppSpot)->Id ); - if ( !Kit_TruthIsEqualWithPhase( pTruthRec, pInOut, nVars ) ) - { - assert( 0 ); - return 0; - } - - - // allocate storage for costs - if ( s_pMan->vLabels && Vec_PtrSize(s_pMan->vLabels) < Abc_NtkObjNumMax(pAig) ) - { - Vec_PtrFree( s_pMan->vLabels ); - s_pMan->vLabels = NULL; - } - if ( s_pMan->vLabels == NULL ) - s_pMan->vLabels = Vec_PtrStart( Abc_NtkObjNumMax(pAig) ); - - // go through the variables in the new truth table - Abc_NtkIncrementTravId( pAig ); - for ( i = 0; i < nLeaves; i++ ) - { - // get hold of the corresponding fanin - pFanin = Abc_ObjFanin( pObj, pCanonPerm[i] )->pCopy; - pFanin = Abc_ObjNotCond( pFanin, (uCanonPhase & (1 << i)) ); - // label the PI of the AIG subgraphs with this fanin - pLeaf = Abc_NtkPi( pAig, i ); - Vec_PtrWriteEntry( s_pMan->vLabels, pLeaf->Id, pFanin ); - Abc_NodeSetTravIdCurrent( pLeaf ); - } - - // go through the candidates - and recursively label them - for ( pCand = *ppSpot; pCand; pCand = (Abc_Obj_t *)pCand->pEquiv ) - Abc_NtkRecStrashNodeLabel_rec( pNtkNew, pCand, 0, s_pMan->vLabels ); - - - // allocate storage for costs - if ( s_pMan->vCosts && Vec_StrSize(s_pMan->vCosts) < Abc_NtkObjNumMax(pAig) ) - { - Vec_StrFree( s_pMan->vCosts ); - s_pMan->vCosts = NULL; - } - if ( s_pMan->vCosts == NULL ) - s_pMan->vCosts = Vec_StrStart( Abc_NtkObjNumMax(pAig) ); - - // find the best subgraph - CostMin = ABC_INFINITY; - pCandMin = NULL; - for ( pCand = *ppSpot; pCand; pCand = (Abc_Obj_t *)pCand->pEquiv ) - { - // label the leaves - Abc_NtkIncrementTravId( pAig ); - // count the number of non-labeled nodes - Cost = Abc_NtkRecStrashNodeCount_rec( pCand, s_pMan->vCosts, s_pMan->vLabels ); - if ( CostMin > Cost ) - { -// printf( "%d ", Cost ); - CostMin = Cost; - pCandMin = pCand; - } - } -// printf( "\n" ); - assert( pCandMin != NULL ); - if ( pCandMin == NULL ) - return 0; - - - // label the leaves - Abc_NtkIncrementTravId( pAig ); - for ( i = 0; i < nLeaves; i++ ) - Abc_NodeSetTravIdCurrent( Abc_NtkPi(pAig, i) ); - - // implement the subgraph - pObj->pCopy = Abc_NtkRecStrashNodeLabel_rec( pNtkNew, pCandMin, 1, s_pMan->vLabels ); - assert( Abc_ObjRegular(pObj->pCopy)->pNtk == pNtkNew ); - - // determine phase difference - nOnes = Kit_TruthCountOnes(pTruth, nVars); - fCompl = (nOnes > (1<< nVars)/2); -// assert( fCompl == ((uCanonPhase & (1 << nVars)) > 0) ); - - nOnes = Kit_TruthCountOnes(pTruthRec, nVars); - fCompl ^= (nOnes > (1<< nVars)/2); - // complement - pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, fCompl ); - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcReconv.c b/src/base/abci/abcReconv.c deleted file mode 100644 index e77f055a..00000000 --- a/src/base/abci/abcReconv.c +++ /dev/null @@ -1,762 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcReconv.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Computation of reconvergence-driven cuts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcReconv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Abc_ManCut_t_ -{ - // user specified parameters - int nNodeSizeMax; // the limit on the size of the supernode - int nConeSizeMax; // the limit on the size of the containing cone - int nNodeFanStop; // the limit on the size of the supernode - int nConeFanStop; // the limit on the size of the containing cone - // internal parameters - Vec_Ptr_t * vNodeLeaves; // fanins of the collapsed node (the cut) - Vec_Ptr_t * vConeLeaves; // fanins of the containing cone - Vec_Ptr_t * vVisited; // the visited nodes - Vec_Vec_t * vLevels; // the data structure to compute TFO nodes - Vec_Ptr_t * vNodesTfo; // the nodes in the TFO of the cut -}; - -static int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit ); -static int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit ); -static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Unmarks the TFI cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_NodesMark( Vec_Ptr_t * vVisited ) -{ - Abc_Obj_t * pNode; - int i; - Vec_PtrForEachEntry( vVisited, pNode, i ) - pNode->fMarkA = 1; -} - -/**Function************************************************************* - - Synopsis [Unmarks the TFI cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_NodesUnmark( Vec_Ptr_t * vVisited ) -{ - Abc_Obj_t * pNode; - int i; - Vec_PtrForEachEntry( vVisited, pNode, i ) - pNode->fMarkA = 0; -} - -/**Function************************************************************* - - Synopsis [Unmarks the TFI cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Abc_NodesUnmarkB( Vec_Ptr_t * vVisited ) -{ - Abc_Obj_t * pNode; - int i; - Vec_PtrForEachEntry( vVisited, pNode, i ) - pNode->fMarkB = 0; -} - -/**Function************************************************************* - - Synopsis [Evaluate the cost of removing the node from the set of leaves.] - - Description [Returns the number of new leaves that will be brought in. - Returns large number if the node cannot be removed from the set of leaves.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Abc_NodeGetLeafCostOne( Abc_Obj_t * pNode, int nFaninLimit ) -{ - int Cost; - // make sure the node is in the construction zone - assert( pNode->fMarkB == 1 ); - // cannot expand over the PI node - if ( Abc_ObjIsCi(pNode) ) - return 999; - // get the cost of the cone - Cost = (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB); - // always accept if the number of leaves does not increase - if ( Cost < 2 ) - return Cost; - // skip nodes with many fanouts - if ( Abc_ObjFanoutNum(pNode) > nFaninLimit ) - return 999; - // return the number of nodes that will be on the leaves if this node is removed - return Cost; -} - -/**Function************************************************************* - - Synopsis [Evaluate the cost of removing the node from the set of leaves.] - - Description [Returns the number of new leaves that will be brought in. - Returns large number if the node cannot be removed from the set of leaves.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Abc_NodeGetLeafCostTwo( Abc_Obj_t * pNode, int nFaninLimit, - Abc_Obj_t ** ppLeafToAdd, Abc_Obj_t ** pNodeToMark1, Abc_Obj_t ** pNodeToMark2 ) -{ - Abc_Obj_t * pFanin0, * pFanin1, * pTemp; - Abc_Obj_t * pGrand, * pGrandToAdd; - // make sure the node is in the construction zone - assert( pNode->fMarkB == 1 ); - // cannot expand over the PI node - if ( Abc_ObjIsCi(pNode) ) - return 999; - // skip nodes with many fanouts -// if ( Abc_ObjFanoutNum(pNode) > nFaninLimit ) -// return 999; - // get the children - pFanin0 = Abc_ObjFanin0(pNode); - pFanin1 = Abc_ObjFanin1(pNode); - assert( !pFanin0->fMarkB && !pFanin1->fMarkB ); - // count the number of unique grandchildren that will be included - // return infinite cost if this number if more than 1 - if ( Abc_ObjIsCi(pFanin0) && Abc_ObjIsCi(pFanin1) ) - return 999; - // consider the special case when a non-CI fanin can be dropped - if ( !Abc_ObjIsCi(pFanin0) && Abc_ObjFanin0(pFanin0)->fMarkB && Abc_ObjFanin1(pFanin0)->fMarkB ) - { - *ppLeafToAdd = pFanin1; - *pNodeToMark1 = pFanin0; - *pNodeToMark2 = NULL; - return 1; - } - if ( !Abc_ObjIsCi(pFanin1) && Abc_ObjFanin0(pFanin1)->fMarkB && Abc_ObjFanin1(pFanin1)->fMarkB ) - { - *ppLeafToAdd = pFanin0; - *pNodeToMark1 = pFanin1; - *pNodeToMark2 = NULL; - return 1; - } - - // make the first node CI if any - if ( Abc_ObjIsCi(pFanin1) ) - pTemp = pFanin0, pFanin0 = pFanin1, pFanin1 = pTemp; - // consider the first node - pGrandToAdd = NULL; - if ( Abc_ObjIsCi(pFanin0) ) - { - *pNodeToMark1 = NULL; - pGrandToAdd = pFanin0; - } - else - { - *pNodeToMark1 = pFanin0; - pGrand = Abc_ObjFanin0(pFanin0); - if ( !pGrand->fMarkB ) - { - if ( pGrandToAdd && pGrandToAdd != pGrand ) - return 999; - pGrandToAdd = pGrand; - } - pGrand = Abc_ObjFanin1(pFanin0); - if ( !pGrand->fMarkB ) - { - if ( pGrandToAdd && pGrandToAdd != pGrand ) - return 999; - pGrandToAdd = pGrand; - } - } - // consider the second node - *pNodeToMark2 = pFanin1; - pGrand = Abc_ObjFanin0(pFanin1); - if ( !pGrand->fMarkB ) - { - if ( pGrandToAdd && pGrandToAdd != pGrand ) - return 999; - pGrandToAdd = pGrand; - } - pGrand = Abc_ObjFanin1(pFanin1); - if ( !pGrand->fMarkB ) - { - if ( pGrandToAdd && pGrandToAdd != pGrand ) - return 999; - pGrandToAdd = pGrand; - } - assert( pGrandToAdd != NULL ); - *ppLeafToAdd = pGrandToAdd; - return 1; -} - - -/**Function************************************************************* - - Synopsis [Finds a fanin-limited, reconvergence-driven cut for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain ) -{ - Abc_Obj_t * pNode; - int i; - - assert( !Abc_ObjIsComplement(pRoot) ); - assert( Abc_ObjIsNode(pRoot) ); - - // start the visited nodes and mark them - Vec_PtrClear( p->vVisited ); - Vec_PtrPush( p->vVisited, pRoot ); - Vec_PtrPush( p->vVisited, Abc_ObjFanin0(pRoot) ); - Vec_PtrPush( p->vVisited, Abc_ObjFanin1(pRoot) ); - pRoot->fMarkB = 1; - Abc_ObjFanin0(pRoot)->fMarkB = 1; - Abc_ObjFanin1(pRoot)->fMarkB = 1; - - // start the cut - Vec_PtrClear( p->vNodeLeaves ); - Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin0(pRoot) ); - Vec_PtrPush( p->vNodeLeaves, Abc_ObjFanin1(pRoot) ); - - // compute the cut - while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vNodeLeaves, p->nNodeSizeMax, p->nNodeFanStop ) ); - assert( Vec_PtrSize(p->vNodeLeaves) <= p->nNodeSizeMax ); - - // return if containing cut is not requested - if ( !fContain ) - { - // unmark both fMarkA and fMarkB in tbe TFI - Abc_NodesUnmarkB( p->vVisited ); - return p->vNodeLeaves; - } - -//printf( "\n\n\n" ); - // compute the containing cut - assert( p->nNodeSizeMax < p->nConeSizeMax ); - // copy the current boundary - Vec_PtrClear( p->vConeLeaves ); - Vec_PtrForEachEntry( p->vNodeLeaves, pNode, i ) - Vec_PtrPush( p->vConeLeaves, pNode ); - // compute the containing cut - while ( Abc_NodeBuildCutLevelOne_int( p->vVisited, p->vConeLeaves, p->nConeSizeMax, p->nConeFanStop ) ); - assert( Vec_PtrSize(p->vConeLeaves) <= p->nConeSizeMax ); - // unmark TFI using fMarkA and fMarkB - Abc_NodesUnmarkB( p->vVisited ); - return p->vNodeLeaves; -} - -/**Function************************************************************* - - Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] - - Description [This procedure looks at the current leaves and tries to change - one leaf at a time in such a way that the cut grows as little as possible. - In evaluating the fanins, this procedure looks only at their immediate - predecessors (this is why it is called a one-level construction procedure).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeBuildCutLevelOne_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nSizeLimit, int nFaninLimit ) -{ - Abc_Obj_t * pNode, * pFaninBest, * pNext; - int CostBest, CostCur, i; - // find the best fanin - CostBest = 100; - pFaninBest = NULL; -//printf( "Evaluating fanins of the cut:\n" ); - Vec_PtrForEachEntry( vLeaves, pNode, i ) - { - CostCur = Abc_NodeGetLeafCostOne( pNode, nFaninLimit ); -//printf( " Fanin %s has cost %d.\n", Abc_ObjName(pNode), CostCur ); -// if ( CostBest > CostCur ) // performance improvement: expand the variable with the smallest level - if ( CostBest > CostCur || - (CostBest == CostCur && pNode->Level > pFaninBest->Level) ) - { - CostBest = CostCur; - pFaninBest = pNode; - } - if ( CostBest == 0 ) - break; - } - if ( pFaninBest == NULL ) - return 0; -// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit ); - - assert( CostBest < 3 ); - if ( vLeaves->nSize - 1 + CostBest > nSizeLimit ) - return 0; -// return Abc_NodeBuildCutLevelTwo_int( vVisited, vLeaves, nFaninLimit ); - - assert( Abc_ObjIsNode(pFaninBest) ); - // remove the node from the array - Vec_PtrRemove( vLeaves, pFaninBest ); -//printf( "Removing fanin %s.\n", Abc_ObjName(pFaninBest) ); - - // add the left child to the fanins - pNext = Abc_ObjFanin0(pFaninBest); - if ( !pNext->fMarkB ) - { -//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) ); - pNext->fMarkB = 1; - Vec_PtrPush( vLeaves, pNext ); - Vec_PtrPush( vVisited, pNext ); - } - // add the right child to the fanins - pNext = Abc_ObjFanin1(pFaninBest); - if ( !pNext->fMarkB ) - { -//printf( "Adding fanin %s.\n", Abc_ObjName(pNext) ); - pNext->fMarkB = 1; - Vec_PtrPush( vLeaves, pNext ); - Vec_PtrPush( vVisited, pNext ); - } - assert( vLeaves->nSize <= nSizeLimit ); - // keep doing this - return 1; -} - -/**Function************************************************************* - - Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] - - Description [This procedure looks at the current leaves and tries to change - one leaf at a time in such a way that the cut grows as little as possible. - In evaluating the fanins, this procedure looks across two levels of fanins - (this is why it is called a two-level construction procedure).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeBuildCutLevelTwo_int( Vec_Ptr_t * vVisited, Vec_Ptr_t * vLeaves, int nFaninLimit ) -{ - Abc_Obj_t * pNode, * pLeafToAdd, * pNodeToMark1, * pNodeToMark2; - int CostCur, i; - // find the best fanin - Vec_PtrForEachEntry( vLeaves, pNode, i ) - { - CostCur = Abc_NodeGetLeafCostTwo( pNode, nFaninLimit, &pLeafToAdd, &pNodeToMark1, &pNodeToMark2 ); - if ( CostCur < 2 ) - break; - } - if ( CostCur > 2 ) - return 0; - // remove the node from the array - Vec_PtrRemove( vLeaves, pNode ); - // add the node to the leaves - if ( pLeafToAdd ) - { - assert( !pLeafToAdd->fMarkB ); - pLeafToAdd->fMarkB = 1; - Vec_PtrPush( vLeaves, pLeafToAdd ); - Vec_PtrPush( vVisited, pLeafToAdd ); - } - // mark the other nodes - if ( pNodeToMark1 ) - { - assert( !pNodeToMark1->fMarkB ); - pNodeToMark1->fMarkB = 1; - Vec_PtrPush( vVisited, pNodeToMark1 ); - } - if ( pNodeToMark2 ) - { - assert( !pNodeToMark2->fMarkB ); - pNodeToMark2->fMarkB = 1; - Vec_PtrPush( vVisited, pNodeToMark2 ); - } - // keep doing this - return 1; -} - - -/**Function************************************************************* - - Synopsis [Get the nodes contained in the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited, int fIncludeFanins ) -{ - Abc_Obj_t * pTemp; - int i; - // mark the fanins of the cone - Abc_NodesMark( vLeaves ); - // collect the nodes in the DFS order - Vec_PtrClear( vVisited ); - // add the fanins - if ( fIncludeFanins ) - Vec_PtrForEachEntry( vLeaves, pTemp, i ) - Vec_PtrPush( vVisited, pTemp ); - // add other nodes - for ( i = 0; i < nRoots; i++ ) - Abc_NodeConeMarkCollect_rec( ppRoots[i], vVisited ); - // unmark both sets - Abc_NodesUnmark( vLeaves ); - Abc_NodesUnmark( vVisited ); -} - -/**Function************************************************************* - - Synopsis [Marks the TFI cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited ) -{ - if ( pNode->fMarkA == 1 ) - return; - // visit transitive fanin - if ( Abc_ObjIsNode(pNode) ) - { - Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited ); - Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited ); - } - assert( pNode->fMarkA == 0 ); - pNode->fMarkA = 1; - Vec_PtrPush( vVisited, pNode ); -} - -/**Function************************************************************* - - Synopsis [Returns BDD representing the logic function of the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVisited ) -{ - Abc_Obj_t * pNode; - DdNode * bFunc0, * bFunc1, * bFunc; - int i; - // get the nodes in the cut without fanins in the DFS order - Abc_NodeConeCollect( &pRoot, 1, vLeaves, vVisited, 0 ); - // set the elementary BDDs - Vec_PtrForEachEntry( vLeaves, pNode, i ) - pNode->pCopy = (Abc_Obj_t *)pbVars[i]; - // compute the BDDs for the collected nodes - Vec_PtrForEachEntry( vVisited, pNode, i ) - { - assert( !Abc_ObjIsPi(pNode) ); - bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ); - bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ); - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); - pNode->pCopy = (Abc_Obj_t *)bFunc; - } - Cudd_Ref( bFunc ); - // dereference the intermediate ones - Vec_PtrForEachEntry( vVisited, pNode, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy ); - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Returns BDD representing the transition relation of the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited ) -{ - DdNode * bFunc0, * bFunc1, * bFunc, * bTrans, * bTemp, * bCube, * bResult; - Abc_Obj_t * pNode; - int i; - // get the nodes in the cut without fanins in the DFS order - Abc_NodeConeCollect( (Abc_Obj_t **)vRoots->pArray, vRoots->nSize, vLeaves, vVisited, 0 ); - // set the elementary BDDs - Vec_PtrForEachEntry( vLeaves, pNode, i ) - pNode->pCopy = (Abc_Obj_t *)pbVarsX[i]; - // compute the BDDs for the collected nodes - Vec_PtrForEachEntry( vVisited, pNode, i ) - { - bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) ); - bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) ); - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); - pNode->pCopy = (Abc_Obj_t *)bFunc; - } - // compute the transition relation of the cone - bTrans = b1; Cudd_Ref( bTrans ); - Vec_PtrForEachEntry( vRoots, pNode, i ) - { - bFunc = Cudd_bddXnor( dd, (DdNode *)pNode->pCopy, pbVarsY[i] ); Cudd_Ref( bFunc ); - bTrans = Cudd_bddAnd( dd, bTemp = bTrans, bFunc ); Cudd_Ref( bTrans ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bFunc ); - } - // dereference the intermediate ones - Vec_PtrForEachEntry( vVisited, pNode, i ) - Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy ); - // compute don't-cares - bCube = Extra_bddComputeRangeCube( dd, vRoots->nSize, vRoots->nSize + vLeaves->nSize ); Cudd_Ref( bCube ); - bResult = Cudd_bddExistAbstract( dd, bTrans, bCube ); Cudd_Ref( bResult ); - bResult = Cudd_Not( bResult ); - Cudd_RecursiveDeref( dd, bCube ); - Cudd_RecursiveDeref( dd, bTrans ); - Cudd_Deref( bResult ); - return bResult; -} - -/**Function************************************************************* - - Synopsis [Starts the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ) -{ - Abc_ManCut_t * p; - p = ALLOC( Abc_ManCut_t, 1 ); - memset( p, 0, sizeof(Abc_ManCut_t) ); - p->vNodeLeaves = Vec_PtrAlloc( 100 ); - p->vConeLeaves = Vec_PtrAlloc( 100 ); - p->vVisited = Vec_PtrAlloc( 100 ); - p->vLevels = Vec_VecAlloc( 100 ); - p->vNodesTfo = Vec_PtrAlloc( 100 ); - p->nNodeSizeMax = nNodeSizeMax; - p->nConeSizeMax = nConeSizeMax; - p->nNodeFanStop = nNodeFanStop; - p->nConeFanStop = nConeFanStop; - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkManCutStop( Abc_ManCut_t * p ) -{ - Vec_PtrFree( p->vNodeLeaves ); - Vec_PtrFree( p->vConeLeaves ); - Vec_PtrFree( p->vVisited ); - Vec_VecFree( p->vLevels ); - Vec_PtrFree( p->vNodesTfo ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Returns the leaves of the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p ) -{ - return p->vConeLeaves; -} - -/**Function************************************************************* - - Synopsis [Returns the leaves of the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p ) -{ - return p->vNodeLeaves; -} - -/**Function************************************************************* - - Synopsis [Returns the leaves of the cone.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p ) -{ - return p->vVisited; -} - - - -/**Function************************************************************* - - Synopsis [Collects the TFO of the cut in the topological order.] - - Description [TFO of the cut is defined as a set of nodes, for which the cut - is a cut, that is, every path from the collected nodes to the CIs goes through - a node in the cut. The nodes are collected if their level does not exceed - the given number (LevelMax). The nodes are returned in the topological order. - If the root node is given, its MFFC is marked, so that the collected nodes - do not contain any nodes in the MFFC.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int LevelMax ) -{ - Abc_Ntk_t * pNtk = pRoot->pNtk; - Vec_Ptr_t * vVec; - Abc_Obj_t * pNode, * pFanout; - int i, k, v, LevelMin; - assert( Abc_NtkIsStrash(pNtk) ); - - // assuming that the structure is clean - Vec_VecForEachLevel( p->vLevels, vVec, i ) - assert( vVec->nSize == 0 ); - - // put fanins into the structure while labeling them - Abc_NtkIncrementTravId( pNtk ); - LevelMin = -1; - Vec_PtrForEachEntry( vLeaves, pNode, i ) - { - if ( pNode->Level > (unsigned)LevelMax ) - continue; - Abc_NodeSetTravIdCurrent( pNode ); - Vec_VecPush( p->vLevels, pNode->Level, pNode ); - if ( LevelMin < (int)pNode->Level ) - LevelMin = pNode->Level; - } - assert( LevelMin >= 0 ); - - // mark MFFC - if ( pRoot ) - Abc_NodeMffcLabelAig( pRoot ); - - // go through the levels up - Vec_PtrClear( p->vNodesTfo ); - Vec_VecForEachEntryStart( p->vLevels, pNode, i, k, LevelMin ) - { - if ( i > LevelMax ) - break; - // if the node is not marked, it is not a fanin - if ( !Abc_NodeIsTravIdCurrent(pNode) ) - { - // check if it belongs to the TFO - if ( !Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pNode)) || - !Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pNode)) ) - continue; - // save the node in the TFO and label it - Vec_PtrPush( p->vNodesTfo, pNode ); - Abc_NodeSetTravIdCurrent( pNode ); - } - // go through the fanouts and add them to the structure if they meet the conditions - Abc_ObjForEachFanout( pNode, pFanout, v ) - { - // skip if fanout is a CO or its level exceeds - if ( Abc_ObjIsCo(pFanout) || pFanout->Level > (unsigned)LevelMax ) - continue; - // skip if it is already added or if it is in MFFC - if ( Abc_NodeIsTravIdCurrent(pFanout) ) - continue; - // add it to the structure but do not mark it (until tested later) - Vec_VecPushUnique( p->vLevels, pFanout->Level, pFanout ); - } - } - - // clear the levelized structure - Vec_VecForEachLevelStart( p->vLevels, vVec, i, LevelMin ) - { - if ( i > LevelMax ) - break; - Vec_PtrClear( vVec ); - } - return p->vNodesTfo; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcRefactor.c b/src/base/abci/abcRefactor.c deleted file mode 100644 index d2b77ed2..00000000 --- a/src/base/abci/abcRefactor.c +++ /dev/null @@ -1,379 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcRefactor.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Resynthesis based on collapsing and refactoring.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcRefactor.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Abc_ManRef_t_ Abc_ManRef_t; -struct Abc_ManRef_t_ -{ - // user specified parameters - int nNodeSizeMax; // the limit on the size of the supernode - int nConeSizeMax; // the limit on the size of the containing cone - int fVerbose; // the verbosity flag - // internal data structures - DdManager * dd; // the BDD manager - Vec_Str_t * vCube; // temporary - Vec_Int_t * vForm; // temporary - Vec_Ptr_t * vVisited; // temporary - Vec_Ptr_t * vLeaves; // temporary - // node statistics - int nLastGain; - int nNodesConsidered; - int nNodesRefactored; - int nNodesGained; - int nNodesBeg; - int nNodesEnd; - // runtime statistics - int timeCut; - int timeBdd; - int timeDcs; - int timeSop; - int timeFact; - int timeEval; - int timeRes; - int timeNtk; - int timeTotal; -}; - -static void Abc_NtkManRefPrintStats( Abc_ManRef_t * p ); -static Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose ); -static void Abc_NtkManRefStop( Abc_ManRef_t * p ); -static Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs incremental resynthesis of the AIG.] - - Description [Starting from each node, computes a reconvergence-driven cut, - derives BDD of the cut function, constructs ISOP, factors the ISOP, - and replaces the current implementation of the MFFC of the node by the - new factored form, if the number of AIG nodes is reduced and the total - number of levels of the AIG network is not increated. Returns the - number of AIG nodes saved.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ) -{ - ProgressBar * pProgress; - Abc_ManRef_t * pManRef; - Abc_ManCut_t * pManCut; - Dec_Graph_t * pFForm; - Vec_Ptr_t * vFanins; - Abc_Obj_t * pNode; - int clk, clkStart = clock(); - int i, nNodes; - - assert( Abc_NtkIsStrash(pNtk) ); - // cleanup the AIG - Abc_AigCleanup(pNtk->pManFunc); - // start the managers - pManCut = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, 1000 ); - pManRef = Abc_NtkManRefStart( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose ); - pManRef->vLeaves = Abc_NtkManCutReadCutLarge( pManCut ); - // compute the reverse levels if level update is requested - if ( fUpdateLevel ) - Abc_NtkStartReverseLevels( pNtk, 0 ); - - // resynthesize each node once - pManRef->nNodesBeg = Abc_NtkNodeNum(pNtk); - nNodes = Abc_NtkObjNumMax(pNtk); - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // skip the constant node -// if ( Abc_NodeIsConst(pNode) ) -// continue; - // skip persistant nodes - if ( Abc_NodeIsPersistant(pNode) ) - continue; - // skip the nodes with many fanouts - if ( Abc_ObjFanoutNum(pNode) > 1000 ) - continue; - // stop if all nodes have been tried once - if ( i >= nNodes ) - break; - // compute a reconvergence-driven cut -clk = clock(); - vFanins = Abc_NodeFindCut( pManCut, pNode, fUseDcs ); -pManRef->timeCut += clock() - clk; - // evaluate this cut -clk = clock(); - pFForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ); -pManRef->timeRes += clock() - clk; - if ( pFForm == NULL ) - continue; - // acceptable replacement found, update the graph -clk = clock(); - Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRef->nLastGain ); -pManRef->timeNtk += clock() - clk; - Dec_GraphFree( pFForm ); -// { -// extern int s_TotalChanges; -// s_TotalChanges++; -// } - } - Extra_ProgressBarStop( pProgress ); -pManRef->timeTotal = clock() - clkStart; - pManRef->nNodesEnd = Abc_NtkNodeNum(pNtk); - - // print statistics of the manager - if ( fVerbose ) - Abc_NtkManRefPrintStats( pManRef ); - // delete the managers - Abc_NtkManCutStop( pManCut ); - Abc_NtkManRefStop( pManRef ); - // put the nodes into the DFS order and reassign their IDs - Abc_NtkReassignIds( pNtk ); -// Abc_AigCheckFaninOrder( pNtk->pManFunc ); - // fix the levels - if ( fUpdateLevel ) - Abc_NtkStopReverseLevels( pNtk ); - else - Abc_NtkLevel( pNtk ); - // check - if ( !Abc_NtkCheck( pNtk ) ) - { - printf( "Abc_NtkRefactor: The network check has failed.\n" ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Resynthesizes the node using refactoring.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUpdateLevel, bool fUseZeros, bool fUseDcs, bool fVerbose ) -{ - int fVeryVerbose = 0; - Abc_Obj_t * pFanin; - Dec_Graph_t * pFForm; - DdNode * bNodeFunc; - int nNodesSaved, nNodesAdded, i, clk; - char * pSop; - int Required; - - Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; - - p->nNodesConsidered++; - - // get the function of the cut -clk = clock(); - bNodeFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pNode, vFanins, p->vVisited ); Cudd_Ref( bNodeFunc ); -p->timeBdd += clock() - clk; - - // if don't-care are used, transform the function into ISOP - if ( fUseDcs ) - { - DdNode * bNodeDc, * bNodeOn, * bNodeOnDc; - int nMints, nMintsDc; -clk = clock(); - // get the don't-cares - bNodeDc = Abc_NodeConeDcs( p->dd, p->dd->vars + vFanins->nSize, p->dd->vars, p->vLeaves, vFanins, p->vVisited ); Cudd_Ref( bNodeDc ); - nMints = (1 << vFanins->nSize); - nMintsDc = (int)Cudd_CountMinterm( p->dd, bNodeDc, vFanins->nSize ); -// printf( "Percentage of minterms = %5.2f.\n", 100.0 * nMintsDc / nMints ); - // get the ISF - bNodeOn = Cudd_bddAnd( p->dd, bNodeFunc, Cudd_Not(bNodeDc) ); Cudd_Ref( bNodeOn ); - bNodeOnDc = Cudd_bddOr ( p->dd, bNodeFunc, bNodeDc ); Cudd_Ref( bNodeOnDc ); - Cudd_RecursiveDeref( p->dd, bNodeFunc ); - Cudd_RecursiveDeref( p->dd, bNodeDc ); - // get the ISOP - bNodeFunc = Cudd_bddIsop( p->dd, bNodeOn, bNodeOnDc ); Cudd_Ref( bNodeFunc ); - Cudd_RecursiveDeref( p->dd, bNodeOn ); - Cudd_RecursiveDeref( p->dd, bNodeOnDc ); -p->timeDcs += clock() - clk; - } - - // always accept the case of constant node - if ( Cudd_IsConstant(bNodeFunc) ) - { - p->nLastGain = Abc_NodeMffcSize( pNode ); - p->nNodesGained += p->nLastGain; - p->nNodesRefactored++; - Cudd_RecursiveDeref( p->dd, bNodeFunc ); - if ( Cudd_IsComplement(bNodeFunc) ) - return Dec_GraphCreateConst0(); - return Dec_GraphCreateConst1(); - } - - // get the SOP of the cut -clk = clock(); - pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, 0, p->vCube, -1 ); -p->timeSop += clock() - clk; - - // get the factored form -clk = clock(); - pFForm = Dec_Factor( pSop ); - free( pSop ); -p->timeFact += clock() - clk; - - // mark the fanin boundary - // (can mark only essential fanins, belonging to bNodeFunc!) - Vec_PtrForEachEntry( vFanins, pFanin, i ) - pFanin->vFanouts.nSize++; - // label MFFC with current traversal ID - Abc_NtkIncrementTravId( pNode->pNtk ); - nNodesSaved = Abc_NodeMffcLabelAig( pNode ); - // unmark the fanin boundary and set the fanins as leaves in the form - Vec_PtrForEachEntry( vFanins, pFanin, i ) - { - pFanin->vFanouts.nSize--; - Dec_GraphNode(pFForm, i)->pFunc = pFanin; - } - - // detect how many new nodes will be added (while taking into account reused nodes) -clk = clock(); - nNodesAdded = Dec_GraphToNetworkCount( pNode, pFForm, nNodesSaved, Required ); -p->timeEval += clock() - clk; - // quit if there is no improvement - if ( nNodesAdded == -1 || nNodesAdded == nNodesSaved && !fUseZeros ) - { - Cudd_RecursiveDeref( p->dd, bNodeFunc ); - Dec_GraphFree( pFForm ); - return NULL; - } - - // compute the total gain in the number of nodes - p->nLastGain = nNodesSaved - nNodesAdded; - p->nNodesGained += p->nLastGain; - p->nNodesRefactored++; - - // report the progress - if ( fVeryVerbose ) - { - printf( "Node %6s : ", Abc_ObjName(pNode) ); - printf( "Cone = %2d. ", vFanins->nSize ); - printf( "BDD = %2d. ", Cudd_DagSize(bNodeFunc) ); - printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pFForm) ); - printf( "MFFC = %2d. ", nNodesSaved ); - printf( "Add = %2d. ", nNodesAdded ); - printf( "GAIN = %2d. ", p->nLastGain ); - printf( "\n" ); - } - Cudd_RecursiveDeref( p->dd, bNodeFunc ); - return pFForm; -} - - -/**Function************************************************************* - - Synopsis [Starts the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose ) -{ - Abc_ManRef_t * p; - p = ALLOC( Abc_ManRef_t, 1 ); - memset( p, 0, sizeof(Abc_ManRef_t) ); - p->vCube = Vec_StrAlloc( 100 ); - p->vVisited = Vec_PtrAlloc( 100 ); - p->nNodeSizeMax = nNodeSizeMax; - p->nConeSizeMax = nConeSizeMax; - p->fVerbose = fVerbose; - // start the BDD manager - if ( fUseDcs ) - p->dd = Cudd_Init( p->nNodeSizeMax + p->nConeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - else - p->dd = Cudd_Init( p->nNodeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_zddVarsFromBddVars( p->dd, 2 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkManRefStop( Abc_ManRef_t * p ) -{ - Extra_StopManager( p->dd ); - Vec_PtrFree( p->vVisited ); - Vec_StrFree( p->vCube ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkManRefPrintStats( Abc_ManRef_t * p ) -{ - printf( "Refactoring statistics:\n" ); - printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); - printf( "Nodes refactored = %8d.\n", p->nNodesRefactored ); - printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg ); - PRT( "Cuts ", p->timeCut ); - PRT( "Resynthesis", p->timeRes ); - PRT( " BDD ", p->timeBdd ); - PRT( " DCs ", p->timeDcs ); - PRT( " SOP ", p->timeSop ); - PRT( " FF ", p->timeFact ); - PRT( " Eval ", p->timeEval ); - PRT( "AIG update ", p->timeNtk ); - PRT( "TOTAL ", p->timeTotal ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcRenode.c b/src/base/abci/abcRenode.c deleted file mode 100644 index 8e8e8719..00000000 --- a/src/base/abci/abcRenode.c +++ /dev/null @@ -1,311 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcRenode.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcRenode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "reo.h" -#include "if.h" -#include "kit.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Abc_NtkRenodeEvalAig( If_Cut_t * pCut ); -static int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut ); -static int Abc_NtkRenodeEvalSop( If_Cut_t * pCut ); -static int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut ); -static int Abc_NtkRenodeEvalMv( If_Cut_t * pCut ); - -static reo_man * s_pReo = NULL; -static DdManager * s_pDd = NULL; -static Vec_Int_t * s_vMemory = NULL; -static Vec_Int_t * s_vMemory2 = NULL; - -static int nDsdCounter = 0; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs renoding as technology mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nFaninMax, int nCubeMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose ) -{ - extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); - If_Par_t Pars, * pPars = &Pars; - Abc_Ntk_t * pNtkNew; - - if ( Abc_NtkGetChoiceNum( pNtk ) ) - printf( "Performing renoding with choices.\n" ); - - nDsdCounter = 0; - - // set defaults - memset( pPars, 0, sizeof(If_Par_t) ); - // user-controlable paramters - pPars->nLutSize = nFaninMax; - pPars->nCutsMax = nCubeMax; - pPars->nFlowIters = nFlowIters; - pPars->nAreaIters = nAreaIters; - pPars->DelayTarget = -1; - pPars->fPreprocess = 1; - pPars->fArea = fArea; - pPars->fFancy = 0; - pPars->fExpRed = 0; // - pPars->fLatchPaths = 0; - pPars->fSeqMap = 0; - pPars->fVerbose = fVerbose; - // internal parameters - pPars->fTruth = 1; - pPars->fUsePerm = 1; - pPars->nLatches = 0; - pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); - pPars->pTimesArr = NULL; - pPars->pTimesArr = NULL; - pPars->fUseBdds = fUseBdds; - pPars->fUseSops = fUseSops; - pPars->fUseCnfs = fUseCnfs; - pPars->fUseMv = fUseMv; - if ( fUseBdds ) - pPars->pFuncCost = Abc_NtkRenodeEvalBdd; - else if ( fUseSops ) - pPars->pFuncCost = Abc_NtkRenodeEvalSop; - else if ( fUseCnfs ) - { - pPars->fArea = 1; - pPars->pFuncCost = Abc_NtkRenodeEvalCnf; - } - else if ( fUseMv ) - pPars->pFuncCost = Abc_NtkRenodeEvalMv; - else - pPars->pFuncCost = Abc_NtkRenodeEvalAig; - - // start the manager - if ( fUseBdds ) - { - assert( s_pReo == NULL ); - s_pDd = Cudd_Init( nFaninMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - s_pReo = Extra_ReorderInit( nFaninMax, 100 ); - pPars->pReoMan = s_pReo; - } - else - { - assert( s_vMemory == NULL ); - s_vMemory = Vec_IntAlloc( 1 << 16 ); - s_vMemory2 = Vec_IntAlloc( 1 << 16 ); - } - - // perform mapping/renoding - pNtkNew = Abc_NtkIf( pNtk, pPars ); - - // start the manager - if ( fUseBdds ) - { - Extra_StopManager( s_pDd ); - Extra_ReorderQuit( s_pReo ); - s_pReo = NULL; - s_pDd = NULL; - } - else - { - Vec_IntFree( s_vMemory ); - Vec_IntFree( s_vMemory2 ); - s_vMemory = NULL; - s_vMemory2 = NULL; - } - -// printf( "Decomposed %d functions.\n", nDsdCounter ); - - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Computes the cost based on the factored form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRenodeEvalAig( If_Cut_t * pCut ) -{ - Kit_Graph_t * pGraph; - int i, nNodes; -/* -extern void Kit_DsdTest( unsigned * pTruth, int nVars ); -if ( If_CutLeaveNum(pCut) == 8 ) -{ - nDsdCounter++; - Kit_DsdTest( If_CutTruth(pCut), If_CutLeaveNum(pCut) ); -} -*/ - pGraph = Kit_TruthToGraph( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory ); - if ( pGraph == NULL ) - { - for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) - pCut->pPerm[i] = 100; - return IF_COST_MAX; - } - nNodes = Kit_GraphNodeNum( pGraph ); - for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) - pCut->pPerm[i] = Kit_GraphLeafDepth_rec( pGraph, Kit_GraphNodeLast(pGraph), Kit_GraphNode(pGraph, i) ); - Kit_GraphFree( pGraph ); - return nNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the cost based on the BDD size after reordering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRenodeEvalBdd( If_Cut_t * pCut ) -{ - int pOrder[IF_MAX_LUTSIZE]; - DdNode * bFunc, * bFuncNew; - int i, k, nNodes; - for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) - pCut->pPerm[i] = pOrder[i] = -100; - bFunc = Kit_TruthToBdd( s_pDd, If_CutTruth(pCut), If_CutLeaveNum(pCut), 0 ); Cudd_Ref( bFunc ); - bFuncNew = Extra_Reorder( s_pReo, s_pDd, bFunc, pOrder ); Cudd_Ref( bFuncNew ); - for ( i = k = 0; i < If_CutLeaveNum(pCut); i++ ) - if ( pOrder[i] >= 0 ) - pCut->pPerm[pOrder[i]] = ++k; // double-check this! - nNodes = -1 + Cudd_DagSize( bFuncNew ); - Cudd_RecursiveDeref( s_pDd, bFuncNew ); - Cudd_RecursiveDeref( s_pDd, bFunc ); - return nNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the cost based on ISOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRenodeEvalSop( If_Cut_t * pCut ) -{ - int i, RetValue; - for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) - pCut->pPerm[i] = 1; - RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 1 ); - if ( RetValue == -1 ) - return IF_COST_MAX; - assert( RetValue == 0 || RetValue == 1 ); - return Vec_IntSize( s_vMemory ); -} - -/**Function************************************************************* - - Synopsis [Computes the cost based on two ISOPs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRenodeEvalCnf( If_Cut_t * pCut ) -{ - int i, RetValue, nClauses; - // set internal mapper parameters - for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) - pCut->pPerm[i] = 1; - // compute ISOP for the positive phase - RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); - if ( RetValue == -1 ) - return IF_COST_MAX; - assert( RetValue == 0 || RetValue == 1 ); - nClauses = Vec_IntSize( s_vMemory ); - // compute ISOP for the negative phase - Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); - RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); - Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); - if ( RetValue == -1 ) - return IF_COST_MAX; - assert( RetValue == 0 || RetValue == 1 ); - nClauses += Vec_IntSize( s_vMemory ); - return nClauses; -} - -/**Function************************************************************* - - Synopsis [Computes the cost of MV-SOP of the cut function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRenodeEvalMv( If_Cut_t * pCut ) -{ - int i, RetValue; - // set internal mapper parameters - for ( i = 0; i < If_CutLeaveNum(pCut); i++ ) - pCut->pPerm[i] = 1; - // compute ISOP for the positive phase - RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory, 0 ); - if ( RetValue == -1 ) - return IF_COST_MAX; - assert( RetValue == 0 || RetValue == 1 ); - // compute ISOP for the negative phase - Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); - RetValue = Kit_TruthIsop( If_CutTruth(pCut), If_CutLeaveNum(pCut), s_vMemory2, 0 ); - Kit_TruthNot( If_CutTruth(pCut), If_CutTruth(pCut), If_CutLeaveNum(pCut) ); - if ( RetValue == -1 ) - return IF_COST_MAX; - assert( RetValue == 0 || RetValue == 1 ); - // return the cost of the cut - RetValue = Abc_NodeEvalMvCost( If_CutLeaveNum(pCut), s_vMemory, s_vMemory2 ); - if ( RetValue >= IF_COST_MAX ) - return IF_COST_MAX; - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcReorder.c b/src/base/abci/abcReorder.c deleted file mode 100644 index d6dee49b..00000000 --- a/src/base/abci/abcReorder.c +++ /dev/null @@ -1,100 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcReorder.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Reordering local BDDs of the nodes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcReorder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reorders BDD of the local function of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeBddReorder( reo_man * p, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin; - DdNode * bFunc; - int * pOrder, i; - // create the temporary array for the variable order - pOrder = ALLOC( int, Abc_ObjFaninNum(pNode) ); - for ( i = 0; i < Abc_ObjFaninNum(pNode); i++ ) - pOrder[i] = -1; - // reorder the BDD - bFunc = Extra_Reorder( p, pNode->pNtk->pManFunc, pNode->pData, pOrder ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( pNode->pNtk->pManFunc, pNode->pData ); - pNode->pData = bFunc; - // update the fanin order - Abc_ObjForEachFanin( pNode, pFanin, i ) - pOrder[i] = pNode->vFanins.pArray[ pOrder[i] ]; - Abc_ObjForEachFanin( pNode, pFanin, i ) - pNode->vFanins.pArray[i] = pOrder[i]; - free( pOrder ); -} - -/**Function************************************************************* - - Synopsis [Reorders BDDs of the local functions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ) -{ - reo_man * p; - Abc_Obj_t * pNode; - int i; - p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - if ( Abc_ObjFaninNum(pNode) < 3 ) - continue; - if ( fVerbose ) - fprintf( stdout, "%10s: ", Abc_ObjName(pNode) ); - if ( fVerbose ) - fprintf( stdout, "Before = %5d BDD nodes. ", Cudd_DagSize(pNode->pData) ); - Abc_NodeBddReorder( p, pNode ); - if ( fVerbose ) - fprintf( stdout, "After = %5d BDD nodes.\n", Cudd_DagSize(pNode->pData) ); - } - Extra_ReorderQuit( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcRestruct.c b/src/base/abci/abcRestruct.c deleted file mode 100644 index 326d1543..00000000 --- a/src/base/abci/abcRestruct.c +++ /dev/null @@ -1,1496 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcRestruct.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcRestruct.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "dec.h" -#include "dsd.h" -#include "cut.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define RST_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) - -typedef struct Abc_ManRst_t_ Abc_ManRst_t; -struct Abc_ManRst_t_ -{ - // the network - Abc_Ntk_t * pNtk; // the network for restructuring - // user specified parameters - int nCutMax; // the limit on the size of the supernode - int fUpdateLevel; // turns on watching the number of levels - int fUseZeros; // turns on zero-cost replacements - int fVerbose; // the verbosity flag - // internal data structures - DdManager * dd; // the BDD manager - Dsd_Manager_t * pManDsd; // the DSD manager - Vec_Ptr_t * vVisited; // temporary - Vec_Ptr_t * vLeaves; // temporary - Vec_Ptr_t * vDecs; // temporary - Vec_Ptr_t * vTemp; // temporary - Vec_Int_t * vSims; // temporary - Vec_Int_t * vRands; // temporary - Vec_Int_t * vOnes; // temporary - Vec_Int_t * vBinate; // temporary - Vec_Int_t * vTwos; // temporary - // node statistics - int nLastGain; - int nCutsConsidered; - int nCutsExplored; - int nNodesConsidered; - int nNodesRestructured; - int nNodesGained; - // runtime statistics - int timeCut; - int timeBdd; - int timeDsd; - int timeEval; - int timeRes; - int timeNtk; - int timeTotal; -}; - -static Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ); - -static Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ); -static Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCut ); -static Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded ); - -static Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag ); -static Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ); -static void Abc_NtkManRstStop( Abc_ManRst_t * p ); -static void Abc_NtkManRstPrintStats( Abc_ManRst_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Implements AIG restructuring.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ) -{ - ProgressBar * pProgress; - Abc_ManRst_t * pManRst; - Cut_Man_t * pManCut; - Cut_Cut_t * pCutList; - Dec_Graph_t * pGraph; - Abc_Obj_t * pNode; - int clk, clkStart = clock(); - int fMulti = 1; - int fResub = 0; - int i, nNodes; - - assert( Abc_NtkIsStrash(pNtk) ); - // cleanup the AIG - Abc_AigCleanup(pNtk->pManFunc); - Abc_NtkCleanCopy(pNtk); - - // compute the reverse levels if level update is requested - if ( fUpdateLevel ) - Abc_NtkStartReverseLevels( pNtk, 0 ); - - // start the restructuring manager - pManRst = Abc_NtkManRstStart( nCutMax, fUpdateLevel, fUseZeros, fVerbose ); - pManRst->pNtk = pNtk; - // start the cut manager -clk = clock(); - pManCut = Abc_NtkStartCutManForRestruct( pNtk, nCutMax, fMulti ); -pManRst->timeCut += clock() - clk; -// pNtk->pManCut = pManCut; - - // resynthesize each node once - nNodes = Abc_NtkObjNumMax(pNtk); - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // skip the constant node -// if ( Abc_NodeIsConst(pNode) ) -// continue; - // skip persistant nodes - if ( Abc_NodeIsPersistant(pNode) ) - continue; - // skip the node if it is inside the tree -// if ( Abc_ObjFanoutNum(pNode) < 2 ) -// continue; - // skip the nodes with too many fanouts - if ( Abc_ObjFanoutNum(pNode) > 1000 ) - continue; - // stop if all nodes have been tried once - if ( i >= nNodes ) - break; - // get the cuts for the given node -clk = clock(); - pCutList = Abc_NodeGetCutsRecursive( pManCut, pNode, fMulti, 0 ); -pManRst->timeCut += clock() - clk; - - // perform restructuring -clk = clock(); - if ( fResub ) - pGraph = Abc_NodeResubstitute( pManRst, pNode, pCutList ); - else - pGraph = Abc_NodeRestructure( pManRst, pNode, pCutList ); -pManRst->timeRes += clock() - clk; - if ( pGraph == NULL ) - continue; - - // acceptable replacement found, update the graph -clk = clock(); - Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, pManRst->nLastGain ); -pManRst->timeNtk += clock() - clk; - Dec_GraphFree( pGraph ); - } - Extra_ProgressBarStop( pProgress ); -pManRst->timeTotal = clock() - clkStart; - - // print statistics of the manager -// if ( fVerbose ) - Abc_NtkManRstPrintStats( pManRst ); - // delete the managers - Cut_ManStop( pManCut ); - Abc_NtkManRstStop( pManRst ); - // put the nodes into the DFS order and reassign their IDs - Abc_NtkReassignIds( pNtk ); -// Abc_AigCheckFaninOrder( pNtk->pManFunc ); - // fix the levels - if ( fUpdateLevel ) - Abc_NtkStopReverseLevels( pNtk ); - else - Abc_NtkLevel( pNtk ); - // check - if ( !Abc_NtkCheck( pNtk ) ) - { - printf( "Abc_NtkRefactor: The network check has failed.\n" ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_RestructNodeDivisors( Abc_ManRst_t * p, Abc_Obj_t * pRoot, int nNodesSaved ) -{ - Abc_Obj_t * pNode, * pFanout;//, * pFanin; - int i, k; - // start with the leaves - Vec_PtrClear( p->vDecs ); - Vec_PtrForEachEntry( p->vLeaves, pNode, i ) - { - Vec_PtrPush( p->vDecs, pNode ); - assert( pNode->fMarkC == 0 ); - pNode->fMarkC = 1; - } - // explore the fanouts - Vec_PtrForEachEntry( p->vDecs, pNode, i ) - { - // if the fanout has both fanins in the set, add it - Abc_ObjForEachFanout( pNode, pFanout, k ) - { - if ( pFanout->fMarkC || Abc_ObjIsPo(pFanout) ) - continue; - if ( Abc_ObjFanin0(pFanout)->fMarkC && Abc_ObjFanin1(pFanout)->fMarkC ) - { - Vec_PtrPush( p->vDecs, pFanout ); - pFanout->fMarkC = 1; - } - } - } - // unmark the nodes - Vec_PtrForEachEntry( p->vDecs, pNode, i ) - pNode->fMarkC = 0; -/* - // print the nodes - Vec_PtrForEachEntryStart( p->vDecs, pNode, i, Vec_PtrSize(p->vLeaves) ) - { - printf( "%2d %s = ", i, Abc_NodeIsTravIdCurrent(pNode)? "*" : " " ); - // find the first fanin - Vec_PtrForEachEntry( p->vDecs, pFanin, k ) - if ( Abc_ObjFanin0(pNode) == pFanin ) - break; - if ( k < Vec_PtrSize(p->vLeaves) ) - printf( "%c", 'a' + k ); - else - printf( "%d", k ); - printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); - // find the second fanin - Vec_PtrForEachEntry( p->vDecs, pFanin, k ) - if ( Abc_ObjFanin1(pNode) == pFanin ) - break; - if ( k < Vec_PtrSize(p->vLeaves) ) - printf( "%c", 'a' + k ); - else - printf( "%d", k ); - printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); - printf( "\n" ); - } -*/ - printf( "%d\n", Vec_PtrSize(p->vDecs)-nNodesSaved-Vec_PtrSize(p->vLeaves) ); -} - - -/**Function************************************************************* - - Synopsis [Starts the cut manager for rewriting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_NodeRestructure( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ) -{ - Dec_Graph_t * pGraph; - Cut_Cut_t * pCut; -// int nCuts; - p->nNodesConsidered++; -/* - // count the number of cuts with four inputs or more - nCuts = 0; - for ( pCut = pCutList; pCut; pCut = pCut->pNext ) - nCuts += (int)(pCut->nLeaves > 3); - printf( "-----------------------------------\n" ); - printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts ); -*/ - // go through the interesting cuts - for ( pCut = pCutList; pCut; pCut = pCut->pNext ) - { - if ( pCut->nLeaves < 4 ) - continue; - if ( pGraph = Abc_NodeRestructureCut( p, pNode, pCut ) ) - return pGraph; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Starts the cut manager for rewriting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_NodeRestructureCut( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) -{ - Dec_Graph_t * pGraph; - Dsd_Node_t * pNodeDsd; - Abc_Obj_t * pLeaf; - DdNode * bFunc; - int nNodesSaved, nNodesAdded; - int Required, nMaxSize, clk, i; - int fVeryVerbose = 0; - - p->nCutsConsidered++; - - // get the required time for the node - Required = p->fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY; - - // collect the leaves of the cut - Vec_PtrClear( p->vLeaves ); - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - { - pLeaf = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]); - if ( pLeaf == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes - return NULL; - Vec_PtrPush( p->vLeaves, pLeaf ); - } - - if ( pRoot->Id == 29 ) - { - int x = 0; - } - -clk = clock(); - // collect the internal nodes of the cut -// Abc_NodeConeCollect( &pRoot, 1, p->vLeaves, p->vVisited, 0 ); - // derive the BDD of the cut - bFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pRoot, p->vLeaves, p->vVisited ); Cudd_Ref( bFunc ); -p->timeBdd += clock() - clk; - - // consider the special case, when the function is a constant - if ( Cudd_IsConstant(bFunc) ) - { - p->nLastGain = Abc_NodeMffcSize( pRoot ); - p->nNodesGained += p->nLastGain; - p->nNodesRestructured++; - Cudd_RecursiveDeref( p->dd, bFunc ); - if ( Cudd_IsComplement(bFunc) ) - return Dec_GraphCreateConst0(); - return Dec_GraphCreateConst1(); - } - -clk = clock(); - // try disjoint support decomposition - pNodeDsd = Dsd_DecomposeOne( p->pManDsd, bFunc ); -p->timeDsd += clock() - clk; - - // skip nodes with non-decomposable blocks - Dsd_TreeNodeGetInfoOne( pNodeDsd, NULL, &nMaxSize ); - if ( nMaxSize > 3 ) - { - Cudd_RecursiveDeref( p->dd, bFunc ); - return NULL; - } - - -/* - // skip nodes that cannot be improved - if ( Vec_PtrSize(p->vVisited) <= Dsd_TreeGetAigCost(pNodeDsd) ) - { - Cudd_RecursiveDeref( p->dd, bFunc ); - return NULL; - } -*/ - - p->nCutsExplored++; - - // mark the fanin boundary - // (can mark only essential fanins, belonging to bNodeFunc!) - Vec_PtrForEachEntry( p->vLeaves, pLeaf, i ) - pLeaf->vFanouts.nSize++; - // label MFFC with current traversal ID - Abc_NtkIncrementTravId( pRoot->pNtk ); - nNodesSaved = Abc_NodeMffcLabelAig( pRoot ); - // unmark the fanin boundary and set the fanins as leaves in the form - Vec_PtrForEachEntry( p->vLeaves, pLeaf, i ) - pLeaf->vFanouts.nSize--; -/* - if ( nNodesSaved < 3 ) - { - Cudd_RecursiveDeref( p->dd, bFunc ); - return NULL; - } -*/ - -/* - printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d.\n", - pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd), - nNodesSaved ); - Dsd_NodePrint( stdout, pNodeDsd ); - - Abc_RestructNodeDivisors( p, pRoot ); - - if ( pRoot->Id == 433 ) - { - int x = 0; - } -*/ -// Abc_RestructNodeDivisors( p, pRoot, nNodesSaved ); - - - // detect how many new nodes will be added (while taking into account reused nodes) -clk = clock(); - if ( nMaxSize > 3 ) - pGraph = NULL; - else - pGraph = Abc_NodeEvaluateDsd( p, pNodeDsd, pRoot, Required, nNodesSaved, &nNodesAdded ); -// pGraph = NULL; -p->timeEval += clock() - clk; - - // quit if there is no improvement - if ( pGraph == NULL || nNodesAdded == -1 || nNodesAdded == nNodesSaved && !p->fUseZeros ) - { - Cudd_RecursiveDeref( p->dd, bFunc ); - if ( pGraph ) Dec_GraphFree( pGraph ); - return NULL; - } - -/* - // print stats - printf( "%5d : Cut-size = %d. Old AIG = %2d. New AIG = %2d. Old MFFC = %2d. New MFFC = %2d. Gain = %d.\n", - pRoot->Id, pCut->nLeaves, Vec_PtrSize(p->vVisited), Dsd_TreeGetAigCost(pNodeDsd), - nNodesSaved, nNodesAdded, (nNodesAdded == -1)? 0 : nNodesSaved-nNodesAdded ); -// Dsd_NodePrint( stdout, pNodeDsd ); -// Dec_GraphPrint( stdout, pGraph, NULL, NULL ); -*/ - - // compute the total gain in the number of nodes - p->nLastGain = nNodesSaved - nNodesAdded; - p->nNodesGained += p->nLastGain; - p->nNodesRestructured++; - - // report the progress - if ( fVeryVerbose ) - { - printf( "Node %6s : ", Abc_ObjName(pRoot) ); - printf( "Cone = %2d. ", p->vLeaves->nSize ); - printf( "BDD = %2d. ", Cudd_DagSize(bFunc) ); - printf( "FF = %2d. ", 1 + Dec_GraphNodeNum(pGraph) ); - printf( "MFFC = %2d. ", nNodesSaved ); - printf( "Add = %2d. ", nNodesAdded ); - printf( "GAIN = %2d. ", p->nLastGain ); - printf( "\n" ); - } - Cudd_RecursiveDeref( p->dd, bFunc ); - return pGraph; -} - - -/**Function************************************************************* - - Synopsis [Moves closer to the end the node that is best for sharing.] - - Description [If the flag is set, tries to find an EXOR, otherwise, tries - to find an OR.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeEdgeDsdPermute( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Vec_Int_t * vEdges, int fExor ) -{ - Dec_Edge_t eNode1, eNode2, eNode3; - Abc_Obj_t * pNode1, * pNode2, * pNode3, * pTemp; - int LeftBound = 0, RightBound, i; - // get the right bound - RightBound = Vec_IntSize(vEdges) - 2; - assert( LeftBound <= RightBound ); - if ( LeftBound == RightBound ) - return; - // get the two last nodes - eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound + 1) ); - eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, RightBound ) ); - pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; - pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; - pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); - pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); - // quit if the last node does not exist - if ( pNode1 == NULL ) - return; - // find the first node that can be shared - for ( i = RightBound; i >= LeftBound; i-- ) - { - // get the third node - eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, i) ); - pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc; - pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl ); - if ( pNode3 == NULL ) - continue; - // check if the node exists - if ( fExor ) - { - if ( pNode1 && pNode3 ) - { - pTemp = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode3, NULL ); - if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) - continue; - - if ( pNode3 == pNode2 ) - return; - Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) ); - Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) ); - return; - } - } - else - { - if ( pNode1 && pNode3 ) - { - pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) ); - if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) - continue; - - if ( eNode3.Node == eNode2.Node ) - return; - Vec_IntWriteEntry( vEdges, i, Dec_EdgeToInt(eNode2) ); - Vec_IntWriteEntry( vEdges, RightBound, Dec_EdgeToInt(eNode3) ); - return; - } - } - } -} - -/**Function************************************************************* - - Synopsis [Adds the new edge in the given order.] - - Description [Similar to Vec_IntPushOrder, except in decreasing order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeEdgeDsdPushOrdered( Dec_Graph_t * pGraph, Vec_Int_t * vEdges, int Edge ) -{ - int i, NodeOld, NodeNew; - vEdges->nSize++; - for ( i = vEdges->nSize-2; i >= 0; i-- ) - { - NodeOld = Dec_IntToEdge(vEdges->pArray[i]).Node; - NodeNew = Dec_IntToEdge(Edge).Node; - // use <= because we are trying to push the new (non-existent) nodes as far as possible - if ( Dec_GraphNode(pGraph, NodeOld)->Level <= Dec_GraphNode(pGraph, NodeNew)->Level ) - vEdges->pArray[i+1] = vEdges->pArray[i]; - else - break; - } - vEdges->pArray[i+1] = Edge; -} - -/**Function************************************************************* - - Synopsis [Evaluation one DSD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Abc_NodeEvaluateDsd_rec( Dec_Graph_t * pGraph, Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, int Required, int nNodesSaved, int * pnNodesAdded ) -{ - Dec_Edge_t eNode1, eNode2, eNode3, eResult, eQuit = { 0, 2006 }; - Abc_Obj_t * pNode1, * pNode2, * pNode3, * pNode4, * pTemp; - Dsd_Node_t * pChildDsd; - Dsd_Type_t DecType; - Vec_Int_t * vEdges; - int Level1, Level2, Level3, Level4; - int i, Index, fCompl, Type; - - // remove the complemented attribute - fCompl = Dsd_IsComplement( pNodeDsd ); - pNodeDsd = Dsd_Regular( pNodeDsd ); - - // consider the trivial case - DecType = Dsd_NodeReadType( pNodeDsd ); - if ( DecType == DSD_NODE_BUF ) - { - Index = Dsd_NodeReadFunc(pNodeDsd)->index; - assert( Index < Dec_GraphLeaveNum(pGraph) ); - eResult = Dec_EdgeCreate( Index, fCompl ); - return eResult; - } - assert( DecType == DSD_NODE_OR || DecType == DSD_NODE_EXOR || DecType == DSD_NODE_PRIME ); - - // solve the problem for the children - vEdges = Vec_IntAlloc( Dsd_NodeReadDecsNum(pNodeDsd) ); - Dsd_NodeForEachChild( pNodeDsd, i, pChildDsd ) - { - eResult = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pChildDsd, Required, nNodesSaved, pnNodesAdded ); - if ( eResult.Node == eQuit.Node ) // infeasible - { - Vec_IntFree( vEdges ); - return eQuit; - } - // order the inputs only if this is OR or EXOR - if ( DecType == DSD_NODE_PRIME ) - Vec_IntPush( vEdges, Dec_EdgeToInt(eResult) ); - else - Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eResult) ); - } - // the edges are sorted by the level of their nodes in decreasing order - - - // consider special cases - if ( DecType == DSD_NODE_OR ) - { - // try to balance the nodes by delay - assert( Vec_IntSize(vEdges) > 1 ); - while ( Vec_IntSize(vEdges) > 1 ) - { - // permute the last two entries - if ( Vec_IntSize(vEdges) > 2 ) - Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 0 ); - // get the two last nodes - eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) ); - eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) ); - pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; - pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; - pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); - pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); - // check if the new node exists - pNode3 = NULL; - if ( pNode1 && pNode2 ) - { - pNode3 = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); - pNode3 = !pNode3? NULL : Abc_ObjNot(pNode3); - } - // create the new node - eNode3 = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 ); - // set level - Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; - Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; - Dec_GraphNode( pGraph, eNode3.Node )->Level = 1 + ABC_MAX(Level1, Level2); - // get the new node if possible - if ( pNode3 ) - { - Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl); - Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; - assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level ); - } - if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) ) - { - (*pnNodesAdded)++; - if ( *pnNodesAdded > nNodesSaved ) - { - Vec_IntFree( vEdges ); - return eQuit; - } - } - // add the resulting node to the form - Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) ); - } - // get the last node - eResult = Dec_IntToEdge( Vec_IntPop(vEdges) ); - Vec_IntFree( vEdges ); - // complement the graph if the node was complemented - eResult.fCompl ^= fCompl; - return eResult; - } - if ( DecType == DSD_NODE_EXOR ) - { - // try to balance the nodes by delay - assert( Vec_IntSize(vEdges) > 1 ); - while ( Vec_IntSize(vEdges) > 1 ) - { - // permute the last two entries - if ( Vec_IntSize(vEdges) > 2 ) - Abc_NodeEdgeDsdPermute( pGraph, pManRst, vEdges, 1 ); - // get the two last nodes - eNode1 = Dec_IntToEdge( Vec_IntPop(vEdges) ); - eNode2 = Dec_IntToEdge( Vec_IntPop(vEdges) ); - pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; - pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; - pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); - pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); - // check if the new node exists - Type = 0; - pNode3 = NULL; - if ( pNode1 && pNode2 ) - pNode3 = Abc_AigXorLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, &Type ); - // create the new node - eNode3 = Dec_GraphAddNodeXor( pGraph, eNode1, eNode2, Type ); // should have the same structure as in AIG - // set level - Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; - Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; - Dec_GraphNode( pGraph, eNode3.Node )->Level = 2 + ABC_MAX(Level1, Level2); - // get the new node if possible - if ( pNode3 ) - { - Dec_GraphNode( pGraph, eNode3.Node )->pFunc = Abc_ObjNotCond(pNode3, eNode3.fCompl); - Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; - assert( Required == ABC_INFINITY || Level3 == (int)Abc_ObjRegular(pNode3)->Level ); - } - if ( !pNode3 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode3)) ) - { - (*pnNodesAdded)++; - if ( !pNode1 || !pNode2 ) - (*pnNodesAdded) += 2; - else if ( Type == 0 ) - { - pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) ); - if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) - (*pnNodesAdded)++; - pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode2 ); - if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) - (*pnNodesAdded)++; - } - else - { - pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); - if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) - (*pnNodesAdded)++; - pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 ); - if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) - (*pnNodesAdded)++; - } - if ( *pnNodesAdded > nNodesSaved ) - { - Vec_IntFree( vEdges ); - return eQuit; - } - } - // add the resulting node to the form - Abc_NodeEdgeDsdPushOrdered( pGraph, vEdges, Dec_EdgeToInt(eNode3) ); - } - // get the last node - eResult = Dec_IntToEdge( Vec_IntPop(vEdges) ); - Vec_IntFree( vEdges ); - // complement the graph if the node is complemented - eResult.fCompl ^= fCompl; - return eResult; - } - if ( DecType == DSD_NODE_PRIME ) - { - DdNode * bLocal, * bVar, * bCofT, * bCofE; - bLocal = Dsd_TreeGetPrimeFunction( pManRst->dd, pNodeDsd ); Cudd_Ref( bLocal ); -//Extra_bddPrint( pManRst->dd, bLocal ); - - bVar = pManRst->dd->vars[0]; - bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); - bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); - if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) - { - Cudd_RecursiveDeref( pManRst->dd, bCofE ); - Cudd_RecursiveDeref( pManRst->dd, bCofT ); - bVar = pManRst->dd->vars[1]; - bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); - bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); - if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) - { - Cudd_RecursiveDeref( pManRst->dd, bCofE ); - Cudd_RecursiveDeref( pManRst->dd, bCofT ); - bVar = pManRst->dd->vars[2]; - bCofE = Cudd_Cofactor( pManRst->dd, bLocal, Cudd_Not(bVar) ); Cudd_Ref( bCofE ); - bCofT = Cudd_Cofactor( pManRst->dd, bLocal, bVar ); Cudd_Ref( bCofT ); - if ( !Extra_bddIsVar(bCofE) || !Extra_bddIsVar(bCofT) ) - { - Cudd_RecursiveDeref( pManRst->dd, bCofE ); - Cudd_RecursiveDeref( pManRst->dd, bCofT ); - Cudd_RecursiveDeref( pManRst->dd, bLocal ); - Vec_IntFree( vEdges ); - return eQuit; - } - } - } - Cudd_RecursiveDeref( pManRst->dd, bLocal ); - // we found the control variable (bVar) and the var-cofactors (bCofT, bCofE) - - // find the graph nodes - eNode1 = Dec_IntToEdge( Vec_IntEntry(vEdges, bVar->index) ); - eNode2 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofT)->index) ); - eNode3 = Dec_IntToEdge( Vec_IntEntry(vEdges, Cudd_Regular(bCofE)->index) ); - // add the complements to the graph nodes - eNode2.fCompl ^= Cudd_IsComplement(bCofT); - eNode3.fCompl ^= Cudd_IsComplement(bCofE); - - // because the cofactors are vars, we can just as well deref them here - Cudd_RecursiveDeref( pManRst->dd, bCofE ); - Cudd_RecursiveDeref( pManRst->dd, bCofT ); - - // find the ABC nodes - pNode1 = Dec_GraphNode( pGraph, eNode1.Node )->pFunc; - pNode2 = Dec_GraphNode( pGraph, eNode2.Node )->pFunc; - pNode3 = Dec_GraphNode( pGraph, eNode3.Node )->pFunc; - pNode1 = !pNode1? NULL : Abc_ObjNotCond( pNode1, eNode1.fCompl ); - pNode2 = !pNode2? NULL : Abc_ObjNotCond( pNode2, eNode2.fCompl ); - pNode3 = !pNode3? NULL : Abc_ObjNotCond( pNode3, eNode3.fCompl ); - - // check if the new node exists - Type = 0; - pNode4 = NULL; - if ( pNode1 && pNode2 && pNode3 ) - pNode4 = Abc_AigMuxLookup( pManRst->pNtk->pManFunc, pNode1, pNode2, pNode3, &Type ); - - // create the new node - eResult = Dec_GraphAddNodeMux( pGraph, eNode1, eNode2, eNode3, Type ); // should have the same structure as AIG - - // set level - Level1 = Dec_GraphNode( pGraph, eNode1.Node )->Level; - Level2 = Dec_GraphNode( pGraph, eNode2.Node )->Level; - Level3 = Dec_GraphNode( pGraph, eNode3.Node )->Level; - Dec_GraphNode( pGraph, eResult.Node )->Level = 2 + ABC_MAX( ABC_MAX(Level1, Level2), Level3 ); - // get the new node if possible - if ( pNode4 ) - { - Dec_GraphNode( pGraph, eResult.Node )->pFunc = Abc_ObjNotCond(pNode4, eResult.fCompl); - Level4 = Dec_GraphNode( pGraph, eResult.Node )->Level; - assert( Required == ABC_INFINITY || Level4 == (int)Abc_ObjRegular(pNode4)->Level ); - } - if ( !pNode4 || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pNode4)) ) - { - (*pnNodesAdded)++; - if ( Type == 0 ) - { - if ( !pNode1 || !pNode2 ) - (*pnNodesAdded)++; - else - { - pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, pNode2 ); - if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) - (*pnNodesAdded)++; - } - if ( !pNode1 || !pNode3 ) - (*pnNodesAdded)++; - else - { - pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), pNode3 ); - if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) - (*pnNodesAdded)++; - } - } - else - { - if ( !pNode1 || !pNode2 ) - (*pnNodesAdded)++; - else - { - pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, pNode1, Abc_ObjNot(pNode2) ); - if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) - (*pnNodesAdded)++; - } - if ( !pNode1 || !pNode3 ) - (*pnNodesAdded)++; - else - { - pTemp = Abc_AigAndLookup( pManRst->pNtk->pManFunc, Abc_ObjNot(pNode1), Abc_ObjNot(pNode3) ); - if ( !pTemp || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pTemp)) ) - (*pnNodesAdded)++; - } - } - if ( *pnNodesAdded > nNodesSaved ) - { - Vec_IntFree( vEdges ); - return eQuit; - } - } - - Vec_IntFree( vEdges ); - // complement the graph if the node was complemented - eResult.fCompl ^= fCompl; - return eResult; - } - Vec_IntFree( vEdges ); - return eQuit; -} - -/**Function************************************************************* - - Synopsis [Evaluation one DSD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_NodeEvaluateDsd( Abc_ManRst_t * pManRst, Dsd_Node_t * pNodeDsd, Abc_Obj_t * pRoot, int Required, int nNodesSaved, int * pnNodesAdded ) -{ - Dec_Graph_t * pGraph; - Dec_Edge_t gEdge; - Abc_Obj_t * pLeaf; - Dec_Node_t * pNode; - int i; - - // create the graph and set the leaves - pGraph = Dec_GraphCreate( Vec_PtrSize(pManRst->vLeaves) ); - Dec_GraphForEachLeaf( pGraph, pNode, i ) - { - pLeaf = Vec_PtrEntry( pManRst->vLeaves, i ); - pNode->pFunc = pLeaf; - pNode->Level = pLeaf->Level; - } - - // create the decomposition structure from the DSD - *pnNodesAdded = 0; - gEdge = Abc_NodeEvaluateDsd_rec( pGraph, pManRst, pNodeDsd, Required, nNodesSaved, pnNodesAdded ); - if ( gEdge.Node > 1000 ) // infeasible - { - *pnNodesAdded = -1; - Dec_GraphFree( pGraph ); - return NULL; - } - - // quit if the root node is the same - pLeaf = Dec_GraphNode( pGraph, gEdge.Node )->pFunc; - if ( Abc_ObjRegular(pLeaf) == pRoot ) - { - *pnNodesAdded = -1; - Dec_GraphFree( pGraph ); - return NULL; - } - - Dec_GraphSetRoot( pGraph, gEdge ); - return pGraph; -} - - - -/**Function************************************************************* - - Synopsis [Starts the cut manager for rewriting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Man_t * Abc_NtkStartCutManForRestruct( Abc_Ntk_t * pNtk, int nCutMax, int fDag ) -{ - static Cut_Params_t Params, * pParams = &Params; - Cut_Man_t * pManCut; - Abc_Obj_t * pObj; - int i; - // start the cut manager - memset( pParams, 0, sizeof(Cut_Params_t) ); - pParams->nVarsMax = nCutMax; // the max cut size ("k" of the k-feasible cuts) - pParams->nKeepMax = 250; // the max number of cuts kept at a node - pParams->fTruth = 0; // compute truth tables - pParams->fFilter = 1; // filter dominated cuts - pParams->fSeq = 0; // compute sequential cuts - pParams->fDrop = 0; // drop cuts on the fly - pParams->fDag = fDag; // compute DAG cuts - pParams->fTree = 0; // compute tree cuts - pParams->fVerbose = 0; // the verbosiness flag - pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); - pManCut = Cut_ManStart( pParams ); - if ( pParams->fDrop ) - Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); - // set cuts for PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) > 0 ) - Cut_NodeSetTriv( pManCut, pObj->Id ); - return pManCut; -} - -/**Function************************************************************* - - Synopsis [Starts the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_ManRst_t * Abc_NtkManRstStart( int nCutMax, bool fUpdateLevel, bool fUseZeros, bool fVerbose ) -{ - Abc_ManRst_t * p; - p = ALLOC( Abc_ManRst_t, 1 ); - memset( p, 0, sizeof(Abc_ManRst_t) ); - // set the parameters - p->nCutMax = nCutMax; - p->fUpdateLevel = fUpdateLevel; - p->fUseZeros = fUseZeros; - p->fVerbose = fVerbose; - // start the BDD manager - p->dd = Cudd_Init( p->nCutMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_zddVarsFromBddVars( p->dd, 2 ); - // start the DSD manager - p->pManDsd = Dsd_ManagerStart( p->dd, p->dd->size, 0 ); - // other temp datastructures - p->vVisited = Vec_PtrAlloc( 100 ); - p->vLeaves = Vec_PtrAlloc( 100 ); - p->vDecs = Vec_PtrAlloc( 100 ); - p->vTemp = Vec_PtrAlloc( 100 ); - p->vSims = Vec_IntAlloc( 100 ); - p->vOnes = Vec_IntAlloc( 100 ); - p->vBinate = Vec_IntAlloc( 100 ); - p->vTwos = Vec_IntAlloc( 100 ); - p->vRands = Vec_IntAlloc( 20 ); - - { - int i; - for ( i = 0; i < 20; i++ ) - Vec_IntPush( p->vRands, (int)RST_RANDOM_UNSIGNED ); - } - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkManRstStop( Abc_ManRst_t * p ) -{ - Dsd_ManagerStop( p->pManDsd ); - Extra_StopManager( p->dd ); - Vec_PtrFree( p->vDecs ); - Vec_PtrFree( p->vLeaves ); - Vec_PtrFree( p->vVisited ); - Vec_PtrFree( p->vTemp ); - Vec_IntFree( p->vSims ); - Vec_IntFree( p->vOnes ); - Vec_IntFree( p->vBinate ); - Vec_IntFree( p->vTwos ); - Vec_IntFree( p->vRands ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkManRstPrintStats( Abc_ManRst_t * p ) -{ - printf( "Refactoring statistics:\n" ); - printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); - printf( "Cuts considered = %8d.\n", p->nCutsConsidered ); - printf( "Cuts explored = %8d.\n", p->nCutsExplored ); - printf( "Nodes restructured = %8d.\n", p->nNodesRestructured ); - printf( "Calculated gain = %8d.\n", p->nNodesGained ); - PRT( "Cuts ", p->timeCut ); - PRT( "Resynthesis", p->timeRes ); - PRT( " BDD ", p->timeBdd ); - PRT( " DSD ", p->timeDsd ); - PRT( " Eval ", p->timeEval ); - PRT( "AIG update ", p->timeNtk ); - PRT( "TOTAL ", p->timeTotal ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_Abc_NodeResubCollectDivs( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) -{ - Abc_Obj_t * pNode, * pFanout; - int i, k; - // collect the leaves of the cut - Vec_PtrClear( p->vDecs ); - Abc_NtkIncrementTravId( pRoot->pNtk ); - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - { - pNode = Abc_NtkObj(pRoot->pNtk, pCut->pLeaves[i]); - if ( pNode == NULL ) // the so-called "bad cut phenomenon" is due to removed nodes - return 0; - Vec_PtrPush( p->vDecs, pNode ); - Abc_NodeSetTravIdCurrent( pNode ); - } - // explore the fanouts - Vec_PtrForEachEntry( p->vDecs, pNode, i ) - { - // if the fanout has both fanins in the set, add it - Abc_ObjForEachFanout( pNode, pFanout, k ) - { - if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsPo(pFanout) ) - continue; - if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) ) - { - Vec_PtrPush( p->vDecs, pFanout ); - Abc_NodeSetTravIdCurrent( pFanout ); - } - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeResubMffc_rec( Abc_Obj_t * pNode ) -{ - if ( Abc_NodeIsTravIdCurrent(pNode) ) - return 0; - Abc_NodeSetTravIdCurrent( pNode ); - return 1 + Abc_NodeResubMffc_rec( Abc_ObjFanin0(pNode) ) + - Abc_NodeResubMffc_rec( Abc_ObjFanin1(pNode) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeResubMffc( Abc_ManRst_t * p, Vec_Ptr_t * vDecs, int nLeaves, Abc_Obj_t * pRoot ) -{ - Abc_Obj_t * pObj; - int Counter, i, k; - // increment the traversal ID for the leaves - Abc_NtkIncrementTravId( pRoot->pNtk ); - // label the leaves - Vec_PtrForEachEntryStop( vDecs, pObj, i, nLeaves ) - Abc_NodeSetTravIdCurrent( pObj ); - // make sure the node is in the cone and is no one of the leaves - assert( Abc_NodeIsTravIdPrevious(pRoot) ); - Counter = Abc_NodeResubMffc_rec( pRoot ); - // move the labeled nodes to the end - Vec_PtrClear( p->vTemp ); - k = 0; - Vec_PtrForEachEntryStart( vDecs, pObj, i, nLeaves ) - if ( Abc_NodeIsTravIdCurrent(pObj) ) - Vec_PtrPush( p->vTemp, pObj ); - else - Vec_PtrWriteEntry( vDecs, k++, pObj ); - // add the labeled nodes - Vec_PtrForEachEntry( p->vTemp, pObj, i ) - Vec_PtrWriteEntry( vDecs, k++, pObj ); - assert( k == Vec_PtrSize(p->vDecs) ); - assert( pRoot == Vec_PtrEntryLast(p->vDecs) ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Performs simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeMffcSimulate( Vec_Ptr_t * vDecs, int nLeaves, Vec_Int_t * vRands, Vec_Int_t * vSims ) -{ - Abc_Obj_t * pObj; - unsigned uData0, uData1, uData; - int i; - // initialize random simulation data - Vec_IntClear( vSims ); - Vec_PtrForEachEntryStop( vDecs, pObj, i, nLeaves ) - { - uData = (unsigned)Vec_IntEntry( vRands, i ); - pObj->pData = (void *)uData; - Vec_IntPush( vSims, uData ); - } - // simulate - Vec_PtrForEachEntryStart( vDecs, pObj, i, nLeaves ) - { - uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; - uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData; - uData = (Abc_ObjFaninC0(pObj)? ~uData0 : uData0) & (Abc_ObjFaninC1(pObj)? ~uData1 : uData1); - pObj->pData = (void *)uData; - Vec_IntPush( vSims, uData ); - } -} - -/**Function************************************************************* - - Synopsis [Full equality check.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeCheckFull( Abc_ManRst_t * p, Dec_Graph_t * pGraph ) -{ - return 1; -} -/**Function************************************************************* - - Synopsis [Detect contants.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_NodeMffcConstants( Abc_ManRst_t * p, Vec_Int_t * vSims ) -{ - Dec_Graph_t * pGraph; - unsigned uRoot; - // get the root node - uRoot = (unsigned)Vec_IntEntryLast( vSims ); - // get the graph if the node looks constant - if ( uRoot == 0 ) - pGraph = Dec_GraphCreateConst0(); - else if ( uRoot == ~(unsigned)0 ) - pGraph = Dec_GraphCreateConst1(); - // check the graph - if ( Abc_NodeCheckFull( p, pGraph ) ) - return pGraph; - Dec_GraphFree( pGraph ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Detect single non-overlaps.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_NodeMffcSingleVar( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) -{ - Dec_Graph_t * pGraph; - unsigned uRoot, uNode; - int i; - - Vec_IntClear( vOnes ); - Vec_IntClear( p->vBinate ); - uRoot = (unsigned)Vec_IntEntryLast( vSims ); - for ( i = 0; i < nNodes; i++ ) - { - uNode = (unsigned)Vec_IntEntry( vSims, i ); - if ( uRoot == uNode || uRoot == ~uNode ) - { - pGraph = Dec_GraphCreate( 1 ); - Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, i ); - Dec_GraphSetRoot( pGraph, Dec_IntToEdge( (int)(uRoot == ~uNode) ) ); - // check the graph - if ( Abc_NodeCheckFull( p, pGraph ) ) - return pGraph; - Dec_GraphFree( pGraph ); - } - if ( (uRoot & uNode) == 0 ) - Vec_IntPush( vOnes, i << 1 ); - else if ( (uRoot & ~uNode) == 0 ) - Vec_IntPush( vOnes, (i << 1) + 1 ); - else - Vec_IntPush( p->vBinate, i ); - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Detect single non-overlaps.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_NodeMffcSingleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) -{ - Dec_Graph_t * pGraph; - Dec_Edge_t eNode0, eNode1, eRoot; - unsigned uRoot; - int i, k; - uRoot = (unsigned)Vec_IntEntryLast( vSims ); - for ( i = 0; i < vOnes->nSize; i++ ) - for ( k = i+1; k < vOnes->nSize; k++ ) - if ( ~uRoot == ((unsigned)vOnes->pArray[i] | (unsigned)vOnes->pArray[k]) ) - { - eNode0 = Dec_IntToEdge( vOnes->pArray[i] ^ 1 ); - eNode1 = Dec_IntToEdge( vOnes->pArray[k] ^ 1 ); - pGraph = Dec_GraphCreate( 2 ); - Dec_GraphNode( pGraph, 0 )->pFunc = Vec_PtrEntry( p->vDecs, eNode0.Node ); - Dec_GraphNode( pGraph, 1 )->pFunc = Vec_PtrEntry( p->vDecs, eNode1.Node ); - eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); - Dec_GraphSetRoot( pGraph, eRoot ); - if ( Abc_NodeCheckFull( p, pGraph ) ) - return pGraph; - Dec_GraphFree( pGraph ); - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Detect single non-overlaps.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_NodeMffcDoubleNode( Abc_ManRst_t * p, Vec_Int_t * vSims, int nNodes, Vec_Int_t * vOnes ) -{ -// Dec_Graph_t * pGraph; -// unsigned uRoot, uNode; -// int i; - - - return NULL; -} - -/**Function************************************************************* - - Synopsis [Evaluates resubstution of one cut.] - - Description [Returns the graph to add if any.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_NodeResubEval( Abc_ManRst_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut ) -{ - Dec_Graph_t * pGraph; - int nNodesSaved; - - // collect the nodes in the cut - if ( !Abc_Abc_NodeResubCollectDivs( p, pRoot, pCut ) ) - return NULL; - - // label MFFC and count its size - nNodesSaved = Abc_NodeResubMffc( p, p->vDecs, pCut->nLeaves, pRoot ); - assert( nNodesSaved > 0 ); - - // simulate MFFC - Abc_NodeMffcSimulate( p->vDecs, pCut->nLeaves, p->vRands, p->vSims ); - - // check for constant output - pGraph = Abc_NodeMffcConstants( p, p->vSims ); - if ( pGraph ) - { - p->nNodesGained += nNodesSaved; - p->nNodesRestructured++; - return pGraph; - } - - // check for one literal (fill up the ones array) - pGraph = Abc_NodeMffcSingleVar( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); - if ( pGraph ) - { - p->nNodesGained += nNodesSaved; - p->nNodesRestructured++; - return pGraph; - } - if ( nNodesSaved == 1 ) - return NULL; - - // look for one node - pGraph = Abc_NodeMffcSingleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); - if ( pGraph ) - { - p->nNodesGained += nNodesSaved - 1; - p->nNodesRestructured++; - return pGraph; - } - if ( nNodesSaved == 2 ) - return NULL; - - // look for two nodes - pGraph = Abc_NodeMffcDoubleNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved, p->vOnes ); - if ( pGraph ) - { - p->nNodesGained += nNodesSaved - 2; - p->nNodesRestructured++; - return pGraph; - } - if ( nNodesSaved == 3 ) - return NULL; -/* - // look for MUX/EXOR - pGraph = Abc_NodeMffcMuxNode( p, p->vSims, Vec_IntSize(p->vSims) - nNodesSaved ); - if ( pGraph ) - { - p->nNodesGained += nNodesSaved - 1; - p->nNodesRestructured++; - return pGraph; - } -*/ - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs resubstution.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_NodeResubstitute( Abc_ManRst_t * p, Abc_Obj_t * pNode, Cut_Cut_t * pCutList ) -{ - Dec_Graph_t * pGraph, * pGraphBest = NULL; - Cut_Cut_t * pCut; - int nCuts; - p->nNodesConsidered++; - - // count the number of cuts with four inputs or more - nCuts = 0; - for ( pCut = pCutList; pCut; pCut = pCut->pNext ) - nCuts += (int)(pCut->nLeaves > 3); - printf( "-----------------------------------\n" ); - printf( "Node %6d : Factor-cuts = %5d.\n", pNode->Id, nCuts ); - - // go through the interesting cuts - for ( pCut = pCutList; pCut; pCut = pCut->pNext ) - { - if ( pCut->nLeaves < 4 ) - continue; - pGraph = Abc_NodeResubEval( p, pNode, pCut ); - if ( pGraph == NULL ) - continue; - if ( !pGraphBest || Dec_GraphNodeNum(pGraph) < Dec_GraphNodeNum(pGraphBest) ) - { - if ( pGraphBest ) - Dec_GraphFree(pGraphBest); - pGraphBest = pGraph; - } - else - Dec_GraphFree(pGraph); - } - return pGraphBest; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcResub.c b/src/base/abci/abcResub.c deleted file mode 100644 index 309c328d..00000000 --- a/src/base/abci/abcResub.c +++ /dev/null @@ -1,1951 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcResub.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Resubstitution manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define ABC_RS_DIV1_MAX 150 // the max number of divisors to consider -#define ABC_RS_DIV2_MAX 500 // the max number of pair-wise divisors to consider - -typedef struct Abc_ManRes_t_ Abc_ManRes_t; -struct Abc_ManRes_t_ -{ - // paramers - int nLeavesMax; // the max number of leaves in the cone - int nDivsMax; // the max number of divisors in the cone - // representation of the cone - Abc_Obj_t * pRoot; // the root of the cone - int nLeaves; // the number of leaves - int nDivs; // the number of all divisor (including leaves) - int nMffc; // the size of MFFC - int nLastGain; // the gain the number of nodes - Vec_Ptr_t * vDivs; // the divisors - // representation of the simulation info - int nBits; // the number of simulation bits - int nWords; // the number of unsigneds for siminfo - Vec_Ptr_t * vSims; // simulation info - unsigned * pInfo; // pointer to simulation info - // observability don't-cares - unsigned * pCareSet; - // internal divisor storage - Vec_Ptr_t * vDivs1UP; // the single-node unate divisors - Vec_Ptr_t * vDivs1UN; // the single-node unate divisors - Vec_Ptr_t * vDivs1B; // the single-node binate divisors - Vec_Ptr_t * vDivs2UP0; // the double-node unate divisors - Vec_Ptr_t * vDivs2UP1; // the double-node unate divisors - Vec_Ptr_t * vDivs2UN0; // the double-node unate divisors - Vec_Ptr_t * vDivs2UN1; // the double-node unate divisors - // other data - Vec_Ptr_t * vTemp; // temporary array of nodes - // runtime statistics - int timeCut; - int timeTruth; - int timeRes; - int timeDiv; - int timeMffc; - int timeSim; - int timeRes1; - int timeResD; - int timeRes2; - int timeRes3; - int timeNtk; - int timeTotal; - // improvement statistics - int nUsedNodeC; - int nUsedNode0; - int nUsedNode1Or; - int nUsedNode1And; - int nUsedNode2Or; - int nUsedNode2And; - int nUsedNode2OrAnd; - int nUsedNode2AndOr; - int nUsedNode3OrAnd; - int nUsedNode3AndOr; - int nUsedNodeTotal; - int nTotalDivs; - int nTotalLeaves; - int nTotalGain; - int nNodesBeg; - int nNodesEnd; -}; - -// external procedures -static Abc_ManRes_t* Abc_ManResubStart( int nLeavesMax, int nDivsMax ); -static void Abc_ManResubStop( Abc_ManRes_t * p ); -static Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, bool fUpdateLevel, int fVerbose ); -static void Abc_ManResubCleanup( Abc_ManRes_t * p ); -static void Abc_ManResubPrint( Abc_ManRes_t * p ); - -// other procedures -static int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required ); -static void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords ); -static void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ); - -static void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required ); -static void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required ); -static Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p ); -static Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p ); -static Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required ); -static Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required ); -static Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required ); -static Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required ); - -static Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax ); -static int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ); - -// don't-care manager -extern void * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ); -extern void Abc_NtkDontCareClear( void * p ); -extern void Abc_NtkDontCareFree( void * p ); -extern int Abc_NtkDontCareCompute( void * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ); - -extern int s_ResubTime; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs incremental resynthesis of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutMax, int nStepsMax, int nLevelsOdc, bool fUpdateLevel, bool fVerbose, bool fVeryVerbose ) -{ - ProgressBar * pProgress; - Abc_ManRes_t * pManRes; - Abc_ManCut_t * pManCut; - void * pManOdc = NULL; - Dec_Graph_t * pFForm; - Vec_Ptr_t * vLeaves; - Abc_Obj_t * pNode; - int clk, clkStart = clock(); - int i, nNodes; - - assert( Abc_NtkIsStrash(pNtk) ); - - // cleanup the AIG - Abc_AigCleanup(pNtk->pManFunc); - // start the managers - pManCut = Abc_NtkManCutStart( nCutMax, 100000, 100000, 100000 ); - pManRes = Abc_ManResubStart( nCutMax, ABC_RS_DIV1_MAX ); - if ( nLevelsOdc > 0 ) - pManOdc = Abc_NtkDontCareAlloc( nCutMax, nLevelsOdc, fVerbose, fVeryVerbose ); - - // compute the reverse levels if level update is requested - if ( fUpdateLevel ) - Abc_NtkStartReverseLevels( pNtk, 0 ); - - if ( Abc_NtkLatchNum(pNtk) ) - Abc_NtkForEachLatch(pNtk, pNode, i) - pNode->pNext = pNode->pData; - - // resynthesize each node once - pManRes->nNodesBeg = Abc_NtkNodeNum(pNtk); - nNodes = Abc_NtkObjNumMax(pNtk); - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // skip the constant node -// if ( Abc_NodeIsConst(pNode) ) -// continue; - // skip persistant nodes - if ( Abc_NodeIsPersistant(pNode) ) - continue; - // skip the nodes with many fanouts - if ( Abc_ObjFanoutNum(pNode) > 1000 ) - continue; - // stop if all nodes have been tried once - if ( i >= nNodes ) - break; - - // compute a reconvergence-driven cut -clk = clock(); - vLeaves = Abc_NodeFindCut( pManCut, pNode, 0 ); -// vLeaves = Abc_CutFactorLarge( pNode, nCutMax ); -pManRes->timeCut += clock() - clk; -/* - if ( fVerbose && vLeaves ) - printf( "Node %6d : Leaves = %3d. Volume = %3d.\n", pNode->Id, Vec_PtrSize(vLeaves), Abc_CutVolumeCheck(pNode, vLeaves) ); - if ( vLeaves == NULL ) - continue; -*/ - // get the don't-cares - if ( pManOdc ) - { -clk = clock(); - Abc_NtkDontCareClear( pManOdc ); - Abc_NtkDontCareCompute( pManOdc, pNode, vLeaves, pManRes->pCareSet ); -pManRes->timeTruth += clock() - clk; - } - - // evaluate this cut -clk = clock(); - pFForm = Abc_ManResubEval( pManRes, pNode, vLeaves, nStepsMax, fUpdateLevel, fVerbose ); -// Vec_PtrFree( vLeaves ); -// Abc_ManResubCleanup( pManRes ); -pManRes->timeRes += clock() - clk; - if ( pFForm == NULL ) - continue; - pManRes->nTotalGain += pManRes->nLastGain; -/* - if ( pManRes->nLeaves == 4 && pManRes->nMffc == 2 && pManRes->nLastGain == 1 ) - { - printf( "%6d : L = %2d. V = %2d. Mffc = %2d. Divs = %3d. Up = %3d. Un = %3d. B = %3d.\n", - pNode->Id, pManRes->nLeaves, Abc_CutVolumeCheck(pNode, vLeaves), pManRes->nMffc, pManRes->nDivs, - pManRes->vDivs1UP->nSize, pManRes->vDivs1UN->nSize, pManRes->vDivs1B->nSize ); - Abc_ManResubPrintDivs( pManRes, pNode, vLeaves ); - } -*/ - // acceptable replacement found, update the graph -clk = clock(); - Dec_GraphUpdateNetwork( pNode, pFForm, fUpdateLevel, pManRes->nLastGain ); -pManRes->timeNtk += clock() - clk; - Dec_GraphFree( pFForm ); - } - Extra_ProgressBarStop( pProgress ); -pManRes->timeTotal = clock() - clkStart; - pManRes->nNodesEnd = Abc_NtkNodeNum(pNtk); - - // print statistics - if ( fVerbose ) - Abc_ManResubPrint( pManRes ); - - // delete the managers - Abc_ManResubStop( pManRes ); - Abc_NtkManCutStop( pManCut ); - if ( pManOdc ) Abc_NtkDontCareFree( pManOdc ); - - // clean the data field - Abc_NtkForEachObj( pNtk, pNode, i ) - pNode->pData = NULL; - - if ( Abc_NtkLatchNum(pNtk) ) - Abc_NtkForEachLatch(pNtk, pNode, i) - pNode->pData = pNode->pNext, pNode->pNext = NULL; - - // put the nodes into the DFS order and reassign their IDs - Abc_NtkReassignIds( pNtk ); -// Abc_AigCheckFaninOrder( pNtk->pManFunc ); - // fix the levels - if ( fUpdateLevel ) - Abc_NtkStopReverseLevels( pNtk ); - else - Abc_NtkLevel( pNtk ); - // check - if ( !Abc_NtkCheck( pNtk ) ) - { - printf( "Abc_NtkRefactor: The network check has failed.\n" ); - return 0; - } -s_ResubTime = clock() - clkStart; - return 1; -} - - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_ManRes_t * Abc_ManResubStart( int nLeavesMax, int nDivsMax ) -{ - Abc_ManRes_t * p; - unsigned * pData; - int i, k; - assert( sizeof(unsigned) == 4 ); - p = ALLOC( Abc_ManRes_t, 1 ); - memset( p, 0, sizeof(Abc_ManRes_t) ); - p->nLeavesMax = nLeavesMax; - p->nDivsMax = nDivsMax; - p->vDivs = Vec_PtrAlloc( p->nDivsMax ); - // allocate simulation info - p->nBits = (1 << p->nLeavesMax); - p->nWords = (p->nBits <= 32)? 1 : (p->nBits / 32); - p->pInfo = ALLOC( unsigned, p->nWords * (p->nDivsMax + 1) ); - memset( p->pInfo, 0, sizeof(unsigned) * p->nWords * p->nLeavesMax ); - p->vSims = Vec_PtrAlloc( p->nDivsMax ); - for ( i = 0; i < p->nDivsMax; i++ ) - Vec_PtrPush( p->vSims, p->pInfo + i * p->nWords ); - // assign the care set - p->pCareSet = p->pInfo + p->nDivsMax * p->nWords; - Abc_InfoFill( p->pCareSet, p->nWords ); - // set elementary truth tables - for ( k = 0; k < p->nLeavesMax; k++ ) - { - pData = p->vSims->pArray[k]; - for ( i = 0; i < p->nBits; i++ ) - if ( i & (1 << k) ) - pData[i>>5] |= (1 << (i&31)); - } - // create the remaining divisors - p->vDivs1UP = Vec_PtrAlloc( p->nDivsMax ); - p->vDivs1UN = Vec_PtrAlloc( p->nDivsMax ); - p->vDivs1B = Vec_PtrAlloc( p->nDivsMax ); - p->vDivs2UP0 = Vec_PtrAlloc( p->nDivsMax ); - p->vDivs2UP1 = Vec_PtrAlloc( p->nDivsMax ); - p->vDivs2UN0 = Vec_PtrAlloc( p->nDivsMax ); - p->vDivs2UN1 = Vec_PtrAlloc( p->nDivsMax ); - p->vTemp = Vec_PtrAlloc( p->nDivsMax ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManResubStop( Abc_ManRes_t * p ) -{ - Vec_PtrFree( p->vDivs ); - Vec_PtrFree( p->vSims ); - Vec_PtrFree( p->vDivs1UP ); - Vec_PtrFree( p->vDivs1UN ); - Vec_PtrFree( p->vDivs1B ); - Vec_PtrFree( p->vDivs2UP0 ); - Vec_PtrFree( p->vDivs2UP1 ); - Vec_PtrFree( p->vDivs2UN0 ); - Vec_PtrFree( p->vDivs2UN1 ); - Vec_PtrFree( p->vTemp ); - free( p->pInfo ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManResubPrint( Abc_ManRes_t * p ) -{ - printf( "Used constants = %6d. ", p->nUsedNodeC ); PRT( "Cuts ", p->timeCut ); - printf( "Used replacements = %6d. ", p->nUsedNode0 ); PRT( "Resub ", p->timeRes ); - printf( "Used single ORs = %6d. ", p->nUsedNode1Or ); PRT( " Div ", p->timeDiv ); - printf( "Used single ANDs = %6d. ", p->nUsedNode1And ); PRT( " Mffc ", p->timeMffc ); - printf( "Used double ORs = %6d. ", p->nUsedNode2Or ); PRT( " Sim ", p->timeSim ); - printf( "Used double ANDs = %6d. ", p->nUsedNode2And ); PRT( " 1 ", p->timeRes1 ); - printf( "Used OR-AND = %6d. ", p->nUsedNode2OrAnd ); PRT( " D ", p->timeResD ); - printf( "Used AND-OR = %6d. ", p->nUsedNode2AndOr ); PRT( " 2 ", p->timeRes2 ); - printf( "Used OR-2ANDs = %6d. ", p->nUsedNode3OrAnd ); PRT( "Truth ", p->timeTruth ); //PRT( " 3 ", p->timeRes3 ); - printf( "Used AND-2ORs = %6d. ", p->nUsedNode3AndOr ); PRT( "AIG ", p->timeNtk ); - printf( "TOTAL = %6d. ", p->nUsedNodeC + - p->nUsedNode0 + - p->nUsedNode1Or + - p->nUsedNode1And + - p->nUsedNode2Or + - p->nUsedNode2And + - p->nUsedNode2OrAnd + - p->nUsedNode2AndOr + - p->nUsedNode3OrAnd + - p->nUsedNode3AndOr - ); PRT( "TOTAL ", p->timeTotal ); - printf( "Total leaves = %8d.\n", p->nTotalLeaves ); - printf( "Total divisors = %8d.\n", p->nTotalDivs ); -// printf( "Total gain = %8d.\n", p->nTotalGain ); - printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManResubCollectDivs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vInternal ) -{ - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pNode) ) - return; - Abc_NodeSetTravIdCurrent(pNode); - // collect the fanins - Abc_ManResubCollectDivs_rec( Abc_ObjFanin0(pNode), vInternal ); - Abc_ManResubCollectDivs_rec( Abc_ObjFanin1(pNode), vInternal ); - // collect the internal node - if ( pNode->fMarkA == 0 ) - Vec_PtrPush( vInternal, pNode ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ManResubCollectDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int Required ) -{ - Abc_Obj_t * pNode, * pFanout; - int i, k, Limit, Counter; - - Vec_PtrClear( p->vDivs1UP ); - Vec_PtrClear( p->vDivs1UN ); - Vec_PtrClear( p->vDivs1B ); - - // add the leaves of the cuts to the divisors - Vec_PtrClear( p->vDivs ); - Abc_NtkIncrementTravId( pRoot->pNtk ); - Vec_PtrForEachEntry( vLeaves, pNode, i ) - { - Vec_PtrPush( p->vDivs, pNode ); - Abc_NodeSetTravIdCurrent( pNode ); - } - - // mark nodes in the MFFC - Vec_PtrForEachEntry( p->vTemp, pNode, i ) - pNode->fMarkA = 1; - // collect the cone (without MFFC) - Abc_ManResubCollectDivs_rec( pRoot, p->vDivs ); - // unmark the current MFFC - Vec_PtrForEachEntry( p->vTemp, pNode, i ) - pNode->fMarkA = 0; - - // check if the number of divisors is not exceeded - if ( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp) >= Vec_PtrSize(p->vSims) - p->nLeavesMax ) - return 0; - - // get the number of divisors to collect - Limit = Vec_PtrSize(p->vSims) - p->nLeavesMax - (Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) + Vec_PtrSize(p->vTemp)); - - // explore the fanouts, which are not in the MFFC - Counter = 0; - Vec_PtrForEachEntry( p->vDivs, pNode, i ) - { - if ( Abc_ObjFanoutNum(pNode) > 100 ) - { -// printf( "%d ", Abc_ObjFanoutNum(pNode) ); - continue; - } - // if the fanout has both fanins in the set, add it - Abc_ObjForEachFanout( pNode, pFanout, k ) - { - if ( Abc_NodeIsTravIdCurrent(pFanout) || Abc_ObjIsCo(pFanout) || (int)pFanout->Level > Required ) - continue; - if ( Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pFanout)) && Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pFanout)) ) - { - if ( Abc_ObjFanin0(pFanout) == pRoot || Abc_ObjFanin1(pFanout) == pRoot ) - continue; - Vec_PtrPush( p->vDivs, pFanout ); - Abc_NodeSetTravIdCurrent( pFanout ); - // quit computing divisors if there is too many of them - if ( ++Counter == Limit ) - goto Quits; - } - } - } - -Quits : - // get the number of divisors - p->nDivs = Vec_PtrSize(p->vDivs); - - // add the nodes in the MFFC - Vec_PtrForEachEntry( p->vTemp, pNode, i ) - Vec_PtrPush( p->vDivs, pNode ); - assert( pRoot == Vec_PtrEntryLast(p->vDivs) ); - - assert( Vec_PtrSize(p->vDivs) - Vec_PtrSize(vLeaves) <= Vec_PtrSize(p->vSims) - p->nLeavesMax ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManResubPrintDivs( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ) -{ - Abc_Obj_t * pFanin, * pNode; - int i, k; - // print the nodes - Vec_PtrForEachEntry( p->vDivs, pNode, i ) - { - if ( i < Vec_PtrSize(vLeaves) ) - { - printf( "%6d : %c\n", pNode->Id, 'a'+i ); - continue; - } - printf( "%6d : %2d = ", pNode->Id, i ); - // find the first fanin - Vec_PtrForEachEntry( p->vDivs, pFanin, k ) - if ( Abc_ObjFanin0(pNode) == pFanin ) - break; - if ( k < Vec_PtrSize(vLeaves) ) - printf( "%c", 'a' + k ); - else - printf( "%d", k ); - printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); - // find the second fanin - Vec_PtrForEachEntry( p->vDivs, pFanin, k ) - if ( Abc_ObjFanin1(pNode) == pFanin ) - break; - if ( k < Vec_PtrSize(vLeaves) ) - printf( "%c", 'a' + k ); - else - printf( "%d", k ); - printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); - if ( pNode == pRoot ) - printf( " root" ); - printf( "\n" ); - } - printf( "\n" ); -} - - -/**Function************************************************************* - - Synopsis [Performs simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManResubSimulate( Vec_Ptr_t * vDivs, int nLeaves, Vec_Ptr_t * vSims, int nLeavesMax, int nWords ) -{ - Abc_Obj_t * pObj; - unsigned * puData0, * puData1, * puData; - int i, k; - assert( Vec_PtrSize(vDivs) - nLeaves <= Vec_PtrSize(vSims) - nLeavesMax ); - // simulate - Vec_PtrForEachEntry( vDivs, pObj, i ) - { - if ( i < nLeaves ) - { // initialize the leaf - pObj->pData = Vec_PtrEntry( vSims, i ); - continue; - } - // set storage for the node's simulation info - pObj->pData = Vec_PtrEntry( vSims, i - nLeaves + nLeavesMax ); - // get pointer to the simulation info - puData = pObj->pData; - puData0 = Abc_ObjFanin0(pObj)->pData; - puData1 = Abc_ObjFanin1(pObj)->pData; - // simulate - if ( Abc_ObjFaninC0(pObj) && Abc_ObjFaninC1(pObj) ) - for ( k = 0; k < nWords; k++ ) - puData[k] = ~puData0[k] & ~puData1[k]; - else if ( Abc_ObjFaninC0(pObj) ) - for ( k = 0; k < nWords; k++ ) - puData[k] = ~puData0[k] & puData1[k]; - else if ( Abc_ObjFaninC1(pObj) ) - for ( k = 0; k < nWords; k++ ) - puData[k] = puData0[k] & ~puData1[k]; - else - for ( k = 0; k < nWords; k++ ) - puData[k] = puData0[k] & puData1[k]; - } - // normalize - Vec_PtrForEachEntry( vDivs, pObj, i ) - { - puData = pObj->pData; - pObj->fPhase = (puData[0] & 1); - if ( pObj->fPhase ) - for ( k = 0; k < nWords; k++ ) - puData[k] = ~puData[k]; - } -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubQuit0( Abc_Obj_t * pRoot, Abc_Obj_t * pObj ) -{ - Dec_Graph_t * pGraph; - Dec_Edge_t eRoot; - pGraph = Dec_GraphCreate( 1 ); - Dec_GraphNode( pGraph, 0 )->pFunc = pObj; - eRoot = Dec_EdgeCreate( 0, pObj->fPhase ); - Dec_GraphSetRoot( pGraph, eRoot ); - if ( pRoot->fPhase ) - Dec_GraphComplement( pGraph ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubQuit1( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, int fOrGate ) -{ - Dec_Graph_t * pGraph; - Dec_Edge_t eRoot, eNode0, eNode1; - assert( pObj0 != pObj1 ); - assert( !Abc_ObjIsComplement(pObj0) ); - assert( !Abc_ObjIsComplement(pObj1) ); - pGraph = Dec_GraphCreate( 2 ); - Dec_GraphNode( pGraph, 0 )->pFunc = pObj0; - Dec_GraphNode( pGraph, 1 )->pFunc = pObj1; - eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase ); - eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase ); - if ( fOrGate ) - eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - else - eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); - Dec_GraphSetRoot( pGraph, eRoot ); - if ( pRoot->fPhase ) - Dec_GraphComplement( pGraph ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubQuit21( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate ) -{ - Dec_Graph_t * pGraph; - Dec_Edge_t eRoot, eNode0, eNode1, eNode2; - assert( pObj0 != pObj1 ); - assert( !Abc_ObjIsComplement(pObj0) ); - assert( !Abc_ObjIsComplement(pObj1) ); - assert( !Abc_ObjIsComplement(pObj2) ); - pGraph = Dec_GraphCreate( 3 ); - Dec_GraphNode( pGraph, 0 )->pFunc = pObj0; - Dec_GraphNode( pGraph, 1 )->pFunc = pObj1; - Dec_GraphNode( pGraph, 2 )->pFunc = pObj2; - eNode0 = Dec_EdgeCreate( 0, pObj0->fPhase ); - eNode1 = Dec_EdgeCreate( 1, pObj1->fPhase ); - eNode2 = Dec_EdgeCreate( 2, pObj2->fPhase ); - if ( fOrGate ) - { - eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - eRoot = Dec_GraphAddNodeOr( pGraph, eNode2, eRoot ); - } - else - { - eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); - eRoot = Dec_GraphAddNodeAnd( pGraph, eNode2, eRoot ); - } - Dec_GraphSetRoot( pGraph, eRoot ); - if ( pRoot->fPhase ) - Dec_GraphComplement( pGraph ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubQuit2( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, int fOrGate ) -{ - Dec_Graph_t * pGraph; - Dec_Edge_t eRoot, ePrev, eNode0, eNode1, eNode2; - assert( pObj0 != pObj1 ); - assert( pObj0 != pObj2 ); - assert( pObj1 != pObj2 ); - assert( !Abc_ObjIsComplement(pObj0) ); - pGraph = Dec_GraphCreate( 3 ); - Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0); - Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1); - Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2); - eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ); - if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) - { - eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ); - eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); - ePrev = Dec_GraphAddNodeOr( pGraph, eNode1, eNode2 ); - } - else - { - eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) ); - eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); - ePrev = Dec_GraphAddNodeAnd( pGraph, eNode1, eNode2 ); - } - if ( fOrGate ) - eRoot = Dec_GraphAddNodeOr( pGraph, eNode0, ePrev ); - else - eRoot = Dec_GraphAddNodeAnd( pGraph, eNode0, ePrev ); - Dec_GraphSetRoot( pGraph, eRoot ); - if ( pRoot->fPhase ) - Dec_GraphComplement( pGraph ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubQuit3( Abc_Obj_t * pRoot, Abc_Obj_t * pObj0, Abc_Obj_t * pObj1, Abc_Obj_t * pObj2, Abc_Obj_t * pObj3, int fOrGate ) -{ - Dec_Graph_t * pGraph; - Dec_Edge_t eRoot, ePrev0, ePrev1, eNode0, eNode1, eNode2, eNode3; - assert( pObj0 != pObj1 ); - assert( pObj2 != pObj3 ); - pGraph = Dec_GraphCreate( 4 ); - Dec_GraphNode( pGraph, 0 )->pFunc = Abc_ObjRegular(pObj0); - Dec_GraphNode( pGraph, 1 )->pFunc = Abc_ObjRegular(pObj1); - Dec_GraphNode( pGraph, 2 )->pFunc = Abc_ObjRegular(pObj2); - Dec_GraphNode( pGraph, 3 )->pFunc = Abc_ObjRegular(pObj3); - if ( Abc_ObjIsComplement(pObj0) && Abc_ObjIsComplement(pObj1) ) - { - eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ); - eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ); - ePrev0 = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) ) - { - eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); - eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ); - ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 ); - } - else - { - eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); - eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) ); - ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 ); - } - } - else - { - eNode0 = Dec_EdgeCreate( 0, Abc_ObjRegular(pObj0)->fPhase ^ Abc_ObjIsComplement(pObj0) ); - eNode1 = Dec_EdgeCreate( 1, Abc_ObjRegular(pObj1)->fPhase ^ Abc_ObjIsComplement(pObj1) ); - ePrev0 = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); - if ( Abc_ObjIsComplement(pObj2) && Abc_ObjIsComplement(pObj3) ) - { - eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ); - eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ); - ePrev1 = Dec_GraphAddNodeOr( pGraph, eNode2, eNode3 ); - } - else - { - eNode2 = Dec_EdgeCreate( 2, Abc_ObjRegular(pObj2)->fPhase ^ Abc_ObjIsComplement(pObj2) ); - eNode3 = Dec_EdgeCreate( 3, Abc_ObjRegular(pObj3)->fPhase ^ Abc_ObjIsComplement(pObj3) ); - ePrev1 = Dec_GraphAddNodeAnd( pGraph, eNode2, eNode3 ); - } - } - if ( fOrGate ) - eRoot = Dec_GraphAddNodeOr( pGraph, ePrev0, ePrev1 ); - else - eRoot = Dec_GraphAddNodeAnd( pGraph, ePrev0, ePrev1 ); - Dec_GraphSetRoot( pGraph, eRoot ); - if ( pRoot->fPhase ) - Dec_GraphComplement( pGraph ); - return pGraph; -} - - - - -/**Function************************************************************* - - Synopsis [Derives single-node unate/binate divisors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManResubDivsS( Abc_ManRes_t * p, int Required ) -{ - Abc_Obj_t * pObj; - unsigned * puData, * puDataR; - int i, w; - Vec_PtrClear( p->vDivs1UP ); - Vec_PtrClear( p->vDivs1UN ); - Vec_PtrClear( p->vDivs1B ); - puDataR = p->pRoot->pData; - Vec_PtrForEachEntryStop( p->vDivs, pObj, i, p->nDivs ) - { - if ( (int)pObj->Level > Required - 1 ) - continue; - - puData = pObj->pData; - // check positive containment - for ( w = 0; w < p->nWords; w++ ) -// if ( puData[w] & ~puDataR[w] ) - if ( puData[w] & ~puDataR[w] & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - Vec_PtrPush( p->vDivs1UP, pObj ); - continue; - } - // check negative containment - for ( w = 0; w < p->nWords; w++ ) -// if ( ~puData[w] & puDataR[w] ) - if ( ~puData[w] & puDataR[w] & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - Vec_PtrPush( p->vDivs1UN, pObj ); - continue; - } - // add the node to binates - Vec_PtrPush( p->vDivs1B, pObj ); - } -} - -/**Function************************************************************* - - Synopsis [Derives double-node unate/binate divisors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManResubDivsD( Abc_ManRes_t * p, int Required ) -{ - Abc_Obj_t * pObj0, * pObj1; - unsigned * puData0, * puData1, * puDataR; - int i, k, w; - Vec_PtrClear( p->vDivs2UP0 ); - Vec_PtrClear( p->vDivs2UP1 ); - Vec_PtrClear( p->vDivs2UN0 ); - Vec_PtrClear( p->vDivs2UN1 ); - puDataR = p->pRoot->pData; - Vec_PtrForEachEntry( p->vDivs1B, pObj0, i ) - { - if ( (int)pObj0->Level > Required - 2 ) - continue; - - puData0 = pObj0->pData; - Vec_PtrForEachEntryStart( p->vDivs1B, pObj1, k, i + 1 ) - { - if ( (int)pObj1->Level > Required - 2 ) - continue; - - puData1 = pObj1->pData; - - if ( Vec_PtrSize(p->vDivs2UP0) < ABC_RS_DIV2_MAX ) - { - // get positive unate divisors - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] & puData1[w]) & ~puDataR[w] ) - if ( (puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - Vec_PtrPush( p->vDivs2UP0, pObj0 ); - Vec_PtrPush( p->vDivs2UP1, pObj1 ); - } - for ( w = 0; w < p->nWords; w++ ) -// if ( (~puData0[w] & puData1[w]) & ~puDataR[w] ) - if ( (~puData0[w] & puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) ); - Vec_PtrPush( p->vDivs2UP1, pObj1 ); - } - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] ) - if ( (puData0[w] & ~puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - Vec_PtrPush( p->vDivs2UP0, pObj0 ); - Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) ); - } - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] | puData1[w]) & ~puDataR[w] ) - if ( (puData0[w] | puData1[w]) & ~puDataR[w] & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - Vec_PtrPush( p->vDivs2UP0, Abc_ObjNot(pObj0) ); - Vec_PtrPush( p->vDivs2UP1, Abc_ObjNot(pObj1) ); - } - } - - if ( Vec_PtrSize(p->vDivs2UN0) < ABC_RS_DIV2_MAX ) - { - // get negative unate divisors - for ( w = 0; w < p->nWords; w++ ) -// if ( ~(puData0[w] & puData1[w]) & puDataR[w] ) - if ( ~(puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - Vec_PtrPush( p->vDivs2UN0, pObj0 ); - Vec_PtrPush( p->vDivs2UN1, pObj1 ); - } - for ( w = 0; w < p->nWords; w++ ) -// if ( ~(~puData0[w] & puData1[w]) & puDataR[w] ) - if ( ~(~puData0[w] & puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) ); - Vec_PtrPush( p->vDivs2UN1, pObj1 ); - } - for ( w = 0; w < p->nWords; w++ ) -// if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] ) - if ( ~(puData0[w] & ~puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - Vec_PtrPush( p->vDivs2UN0, pObj0 ); - Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) ); - } - for ( w = 0; w < p->nWords; w++ ) -// if ( ~(puData0[w] | puData1[w]) & puDataR[w] ) - if ( ~(puData0[w] | puData1[w]) & puDataR[w] & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - Vec_PtrPush( p->vDivs2UN0, Abc_ObjNot(pObj0) ); - Vec_PtrPush( p->vDivs2UN1, Abc_ObjNot(pObj1) ); - } - } - } - } -// printf( "%d %d ", Vec_PtrSize(p->vDivs2UP0), Vec_PtrSize(p->vDivs2UN0) ); -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubQuit( Abc_ManRes_t * p ) -{ - Dec_Graph_t * pGraph; - unsigned * upData; - int w; - upData = p->pRoot->pData; - for ( w = 0; w < p->nWords; w++ ) -// if ( upData[w] ) - if ( upData[w] & p->pCareSet[w] ) // care set - break; - if ( w != p->nWords ) - return NULL; - // get constant node graph - if ( p->pRoot->fPhase ) - pGraph = Dec_GraphCreateConst1(); - else - pGraph = Dec_GraphCreateConst0(); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubDivs0( Abc_ManRes_t * p ) -{ - Abc_Obj_t * pObj; - unsigned * puData, * puDataR; - int i, w; - puDataR = p->pRoot->pData; - Vec_PtrForEachEntryStop( p->vDivs, pObj, i, p->nDivs ) - { - puData = pObj->pData; - for ( w = 0; w < p->nWords; w++ ) -// if ( puData[w] != puDataR[w] ) - if ( (puData[w] ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - return Abc_ManResubQuit0( p->pRoot, pObj ); - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubDivs1( Abc_ManRes_t * p, int Required ) -{ - Abc_Obj_t * pObj0, * pObj1; - unsigned * puData0, * puData1, * puDataR; - int i, k, w; - puDataR = p->pRoot->pData; - // check positive unate divisors - Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i ) - { - puData0 = pObj0->pData; - Vec_PtrForEachEntryStart( p->vDivs1UP, pObj1, k, i + 1 ) - { - puData1 = pObj1->pData; - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] | puData1[w]) != puDataR[w] ) - if ( ((puData0[w] | puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - p->nUsedNode1Or++; - return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 1 ); - } - } - } - // check negative unate divisors - Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i ) - { - puData0 = pObj0->pData; - Vec_PtrForEachEntryStart( p->vDivs1UN, pObj1, k, i + 1 ) - { - puData1 = pObj1->pData; - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] & puData1[w]) != puDataR[w] ) - if ( ((puData0[w] & puData1[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - p->nUsedNode1And++; - return Abc_ManResubQuit1( p->pRoot, pObj0, pObj1, 0 ); - } - } - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubDivs12( Abc_ManRes_t * p, int Required ) -{ - Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObjMax, * pObjMin0, * pObjMin1; - unsigned * puData0, * puData1, * puData2, * puDataR; - int i, k, j, w, LevelMax; - puDataR = p->pRoot->pData; - // check positive unate divisors - Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i ) - { - puData0 = pObj0->pData; - Vec_PtrForEachEntryStart( p->vDivs1UP, pObj1, k, i + 1 ) - { - puData1 = pObj1->pData; - Vec_PtrForEachEntryStart( p->vDivs1UP, pObj2, j, k + 1 ) - { - puData2 = pObj2->pData; - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] | puData1[w] | puData2[w]) != puDataR[w] ) - if ( ((puData0[w] | puData1[w] | puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) ); - assert( LevelMax <= Required - 1 ); - - pObjMax = NULL; - if ( (int)pObj0->Level == LevelMax ) - pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2; - if ( (int)pObj1->Level == LevelMax ) - { - if ( pObjMax ) continue; - pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2; - } - if ( (int)pObj2->Level == LevelMax ) - { - if ( pObjMax ) continue; - pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1; - } - - p->nUsedNode2Or++; - return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 1 ); - } - } - } - } - // check negative unate divisors - Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i ) - { - puData0 = pObj0->pData; - Vec_PtrForEachEntryStart( p->vDivs1UN, pObj1, k, i + 1 ) - { - puData1 = pObj1->pData; - Vec_PtrForEachEntryStart( p->vDivs1UN, pObj2, j, k + 1 ) - { - puData2 = pObj2->pData; - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] & puData1[w] & puData2[w]) != puDataR[w] ) - if ( ((puData0[w] & puData1[w] & puData2[w]) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - if ( w == p->nWords ) - { - LevelMax = ABC_MAX( pObj0->Level, ABC_MAX(pObj1->Level, pObj2->Level) ); - assert( LevelMax <= Required - 1 ); - - pObjMax = NULL; - if ( (int)pObj0->Level == LevelMax ) - pObjMax = pObj0, pObjMin0 = pObj1, pObjMin1 = pObj2; - if ( (int)pObj1->Level == LevelMax ) - { - if ( pObjMax ) continue; - pObjMax = pObj1, pObjMin0 = pObj0, pObjMin1 = pObj2; - } - if ( (int)pObj2->Level == LevelMax ) - { - if ( pObjMax ) continue; - pObjMax = pObj2, pObjMin0 = pObj0, pObjMin1 = pObj1; - } - - p->nUsedNode2And++; - return Abc_ManResubQuit21( p->pRoot, pObjMin0, pObjMin1, pObjMax, 0 ); - } - } - } - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubDivs2( Abc_ManRes_t * p, int Required ) -{ - Abc_Obj_t * pObj0, * pObj1, * pObj2; - unsigned * puData0, * puData1, * puData2, * puDataR; - int i, k, w; - puDataR = p->pRoot->pData; - // check positive unate divisors - Vec_PtrForEachEntry( p->vDivs1UP, pObj0, i ) - { - puData0 = pObj0->pData; - Vec_PtrForEachEntry( p->vDivs2UP0, pObj1, k ) - { - pObj2 = Vec_PtrEntry( p->vDivs2UP1, k ); - - puData1 = Abc_ObjRegular(pObj1)->pData; - puData2 = Abc_ObjRegular(pObj2)->pData; - if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) - { - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] | (puData1[w] | puData2[w])) != puDataR[w] ) - if ( ((puData0[w] | (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - } - else if ( Abc_ObjIsComplement(pObj1) ) - { - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] | (~puData1[w] & puData2[w])) != puDataR[w] ) - if ( ((puData0[w] | (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - } - else if ( Abc_ObjIsComplement(pObj2) ) - { - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] | (puData1[w] & ~puData2[w])) != puDataR[w] ) - if ( ((puData0[w] | (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - } - else - { - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] | (puData1[w] & puData2[w])) != puDataR[w] ) - if ( ((puData0[w] | (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - } - if ( w == p->nWords ) - { - p->nUsedNode2OrAnd++; - return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 1 ); - } - } - } - // check negative unate divisors - Vec_PtrForEachEntry( p->vDivs1UN, pObj0, i ) - { - puData0 = pObj0->pData; - Vec_PtrForEachEntry( p->vDivs2UN0, pObj1, k ) - { - pObj2 = Vec_PtrEntry( p->vDivs2UN1, k ); - - puData1 = Abc_ObjRegular(pObj1)->pData; - puData2 = Abc_ObjRegular(pObj2)->pData; - if ( Abc_ObjIsComplement(pObj1) && Abc_ObjIsComplement(pObj2) ) - { - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] & (puData1[w] | puData2[w])) != puDataR[w] ) - if ( ((puData0[w] & (puData1[w] | puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - } - else if ( Abc_ObjIsComplement(pObj1) ) - { - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] & (~puData1[w] & puData2[w])) != puDataR[w] ) - if ( ((puData0[w] & (~puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - } - else if ( Abc_ObjIsComplement(pObj2) ) - { - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] & (puData1[w] & ~puData2[w])) != puDataR[w] ) - if ( ((puData0[w] & (puData1[w] & ~puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - } - else - { - for ( w = 0; w < p->nWords; w++ ) -// if ( (puData0[w] & (puData1[w] & puData2[w])) != puDataR[w] ) - if ( ((puData0[w] & (puData1[w] & puData2[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - } - if ( w == p->nWords ) - { - p->nUsedNode2AndOr++; - return Abc_ManResubQuit2( p->pRoot, pObj0, pObj1, pObj2, 0 ); - } - } - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubDivs3( Abc_ManRes_t * p, int Required ) -{ - Abc_Obj_t * pObj0, * pObj1, * pObj2, * pObj3; - unsigned * puData0, * puData1, * puData2, * puData3, * puDataR; - int i, k, w, Flag; - puDataR = p->pRoot->pData; - // check positive unate divisors - Vec_PtrForEachEntry( p->vDivs2UP0, pObj0, i ) - { - pObj1 = Vec_PtrEntry( p->vDivs2UP1, i ); - puData0 = Abc_ObjRegular(pObj0)->pData; - puData1 = Abc_ObjRegular(pObj1)->pData; - Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2); - - Vec_PtrForEachEntryStart( p->vDivs2UP0, pObj2, k, i + 1 ) - { - pObj3 = Vec_PtrEntry( p->vDivs2UP1, k ); - puData2 = Abc_ObjRegular(pObj2)->pData; - puData3 = Abc_ObjRegular(pObj3)->pData; - - Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3); - assert( Flag < 16 ); - switch( Flag ) - { - case 0: // 0000 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) - if ( (((puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - case 1: // 0001 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) - if ( (((puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - case 2: // 0010 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) - if ( (((puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - case 3: // 0011 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) - if ( (((puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - - case 4: // 0100 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) - if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - case 5: // 0101 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) - if ( (((puData0[w] & ~puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - case 6: // 0110 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) - if ( (((puData0[w] & ~puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - case 7: // 0111 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) - if ( (((puData0[w] & ~puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - - case 8: // 1000 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) - if ( (((~puData0[w] & puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - case 9: // 1001 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) - if ( (((~puData0[w] & puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - case 10: // 1010 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) - if ( (((~puData0[w] & puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - case 11: // 1011 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) - if ( (((~puData0[w] & puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - - case 12: // 1100 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) != puDataR[w] ) - if ( (((puData0[w] | puData1[w]) | (puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) // care set - break; - break; - case 13: // 1101 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) != puDataR[w] ) - if ( (((puData0[w] | puData1[w]) | (puData2[w] & ~puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) - break; - break; - case 14: // 1110 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) != puDataR[w] ) - if ( (((puData0[w] | puData1[w]) | (~puData2[w] & puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) - break; - break; - case 15: // 1111 - for ( w = 0; w < p->nWords; w++ ) -// if ( ((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) != puDataR[w] ) - if ( (((puData0[w] | puData1[w]) | (puData2[w] | puData3[w])) ^ puDataR[w]) & p->pCareSet[w] ) - break; - break; - - } - if ( w == p->nWords ) - { - p->nUsedNode3OrAnd++; - return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 1 ); - } - } - } -/* - // check negative unate divisors - Vec_PtrForEachEntry( p->vDivs2UN0, pObj0, i ) - { - pObj1 = Vec_PtrEntry( p->vDivs2UN1, i ); - puData0 = Abc_ObjRegular(pObj0)->pData; - puData1 = Abc_ObjRegular(pObj1)->pData; - Flag = (Abc_ObjIsComplement(pObj0) << 3) | (Abc_ObjIsComplement(pObj1) << 2); - - Vec_PtrForEachEntryStart( p->vDivs2UN0, pObj2, k, i + 1 ) - { - pObj3 = Vec_PtrEntry( p->vDivs2UN1, k ); - puData2 = Abc_ObjRegular(pObj2)->pData; - puData3 = Abc_ObjRegular(pObj3)->pData; - - Flag = (Flag & 12) | (Abc_ObjIsComplement(pObj2) << 1) | Abc_ObjIsComplement(pObj3); - assert( Flag < 16 ); - switch( Flag ) - { - case 0: // 0000 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) - break; - break; - case 1: // 0001 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) - break; - break; - case 2: // 0010 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) - break; - break; - case 3: // 0011 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) - break; - break; - - case 4: // 0100 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) - break; - break; - case 5: // 0101 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] & ~puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) - break; - break; - case 6: // 0110 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] & ~puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) - break; - break; - case 7: // 0111 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] & ~puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) - break; - break; - - case 8: // 1000 - for ( w = 0; w < p->nWords; w++ ) - if ( ((~puData0[w] & puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) - break; - break; - case 9: // 1001 - for ( w = 0; w < p->nWords; w++ ) - if ( ((~puData0[w] & puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) - break; - break; - case 10: // 1010 - for ( w = 0; w < p->nWords; w++ ) - if ( ((~puData0[w] & puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) - break; - break; - case 11: // 1011 - for ( w = 0; w < p->nWords; w++ ) - if ( ((~puData0[w] & puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) - break; - break; - - case 12: // 1100 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] | puData1[w]) & (puData2[w] & puData3[w])) != puDataR[w] ) - break; - break; - case 13: // 1101 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] | puData1[w]) & (puData2[w] & ~puData3[w])) != puDataR[w] ) - break; - break; - case 14: // 1110 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] | puData1[w]) & (~puData2[w] & puData3[w])) != puDataR[w] ) - break; - break; - case 15: // 1111 - for ( w = 0; w < p->nWords; w++ ) - if ( ((puData0[w] | puData1[w]) & (puData2[w] | puData3[w])) != puDataR[w] ) - break; - break; - - } - if ( w == p->nWords ) - { - p->nUsedNode3AndOr++; - return Abc_ManResubQuit3( p->pRoot, pObj0, pObj1, pObj2, pObj3, 0 ); - } - } - } -*/ - return NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManResubCleanup( Abc_ManRes_t * p ) -{ - Abc_Obj_t * pObj; - int i; - Vec_PtrForEachEntry( p->vDivs, pObj, i ) - pObj->pData = NULL; - Vec_PtrClear( p->vDivs ); - p->pRoot = NULL; -} - -/**Function************************************************************* - - Synopsis [Evaluates resubstution of one cut.] - - Description [Returns the graph to add if any.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Abc_ManResubEval( Abc_ManRes_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves, int nSteps, bool fUpdateLevel, bool fVerbose ) -{ - extern int Abc_NodeMffsInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside ); - Dec_Graph_t * pGraph; - int Required; - int clk; - - Required = fUpdateLevel? Abc_ObjRequiredLevel(pRoot) : ABC_INFINITY; - - assert( nSteps >= 0 ); - assert( nSteps <= 3 ); - p->pRoot = pRoot; - p->nLeaves = Vec_PtrSize(vLeaves); - p->nLastGain = -1; - - // collect the MFFC -clk = clock(); - p->nMffc = Abc_NodeMffsInside( pRoot, vLeaves, p->vTemp ); -p->timeMffc += clock() - clk; - assert( p->nMffc > 0 ); - - // collect the divisor nodes -clk = clock(); - if ( !Abc_ManResubCollectDivs( p, pRoot, vLeaves, Required ) ) - return NULL; - p->timeDiv += clock() - clk; - - p->nTotalDivs += p->nDivs; - p->nTotalLeaves += p->nLeaves; - - // simulate the nodes -clk = clock(); - Abc_ManResubSimulate( p->vDivs, p->nLeaves, p->vSims, p->nLeavesMax, p->nWords ); -p->timeSim += clock() - clk; - -clk = clock(); - // consider constants - if ( pGraph = Abc_ManResubQuit( p ) ) - { - p->nUsedNodeC++; - p->nLastGain = p->nMffc; - return pGraph; - } - - // consider equal nodes - if ( pGraph = Abc_ManResubDivs0( p ) ) - { -p->timeRes1 += clock() - clk; - p->nUsedNode0++; - p->nLastGain = p->nMffc; - return pGraph; - } - if ( nSteps == 0 || p->nMffc == 1 ) - { -p->timeRes1 += clock() - clk; - return NULL; - } - - // get the one level divisors - Abc_ManResubDivsS( p, Required ); - - // consider one node - if ( pGraph = Abc_ManResubDivs1( p, Required ) ) - { -p->timeRes1 += clock() - clk; - p->nLastGain = p->nMffc - 1; - return pGraph; - } -p->timeRes1 += clock() - clk; - if ( nSteps == 1 || p->nMffc == 2 ) - return NULL; - -clk = clock(); - // consider triples - if ( pGraph = Abc_ManResubDivs12( p, Required ) ) - { -p->timeRes2 += clock() - clk; - p->nLastGain = p->nMffc - 2; - return pGraph; - } -p->timeRes2 += clock() - clk; - - // get the two level divisors -clk = clock(); - Abc_ManResubDivsD( p, Required ); -p->timeResD += clock() - clk; - - // consider two nodes -clk = clock(); - if ( pGraph = Abc_ManResubDivs2( p, Required ) ) - { -p->timeRes2 += clock() - clk; - p->nLastGain = p->nMffc - 2; - return pGraph; - } -p->timeRes2 += clock() - clk; - if ( nSteps == 2 || p->nMffc == 3 ) - return NULL; - - // consider two nodes -clk = clock(); - if ( pGraph = Abc_ManResubDivs3( p, Required ) ) - { -p->timeRes3 += clock() - clk; - p->nLastGain = p->nMffc - 3; - return pGraph; - } -p->timeRes3 += clock() - clk; - if ( nSteps == 3 || p->nLeavesMax == 4 ) - return NULL; - return NULL; -} - - - - -/**Function************************************************************* - - Synopsis [Computes the volume and checks if the cut is feasible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CutVolumeCheck_rec( Abc_Obj_t * pObj ) -{ - // quit if the node is visited (or if it is a leaf) - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return 0; - Abc_NodeSetTravIdCurrent(pObj); - // report the error - if ( Abc_ObjIsCi(pObj) ) - printf( "Abc_CutVolumeCheck() ERROR: The set of nodes is not a cut!\n" ); - // count the number of nodes in the leaves - return 1 + Abc_CutVolumeCheck_rec( Abc_ObjFanin0(pObj) ) + - Abc_CutVolumeCheck_rec( Abc_ObjFanin1(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Computes the volume and checks if the cut is feasible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CutVolumeCheck( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) -{ - Abc_Obj_t * pObj; - int i; - // mark the leaves - Abc_NtkIncrementTravId( pNode->pNtk ); - Vec_PtrForEachEntry( vLeaves, pObj, i ) - Abc_NodeSetTravIdCurrent( pObj ); - // traverse the nodes starting from the given one and count them - return Abc_CutVolumeCheck_rec( pNode ); -} - -/**Function************************************************************* - - Synopsis [Computes the factor cut of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_CutFactor_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ) -{ - if ( pObj->fMarkA ) - return; - if ( Abc_ObjIsCi(pObj) || (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)) ) - { - Vec_PtrPush( vLeaves, pObj ); - pObj->fMarkA = 1; - return; - } - Abc_CutFactor_rec( Abc_ObjFanin0(pObj), vLeaves ); - Abc_CutFactor_rec( Abc_ObjFanin1(pObj), vLeaves ); -} - -/**Function************************************************************* - - Synopsis [Computes the factor cut of the node.] - - Description [Factor-cut is the cut at a node in terms of factor-nodes. - Factor-nodes are roots of the node trees (MUXes/EXORs are counted as single nodes). - Factor-cut is unique for the given node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_CutFactor( Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vLeaves; - Abc_Obj_t * pObj; - int i; - assert( !Abc_ObjIsCi(pNode) ); - vLeaves = Vec_PtrAlloc( 10 ); - Abc_CutFactor_rec( Abc_ObjFanin0(pNode), vLeaves ); - Abc_CutFactor_rec( Abc_ObjFanin1(pNode), vLeaves ); - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->fMarkA = 0; - return vLeaves; -} - -/**Function************************************************************* - - Synopsis [Cut computation.] - - Description [This cut computation works as follows: - It starts with the factor cut at the node. If the factor-cut is large, quit. - It supports the set of leaves of the cut under construction and labels all nodes - in the cut under construction, including the leaves. - It computes the factor-cuts of the leaves and checks if it is easible to add any of them. - If it is, it randomly chooses one feasible and continues.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_CutFactorLarge( Abc_Obj_t * pNode, int nLeavesMax ) -{ - Vec_Ptr_t * vLeaves, * vFactors, * vFact, * vNext; - Vec_Int_t * vFeasible; - Abc_Obj_t * pLeaf, * pTemp; - int i, k, Counter, RandLeaf; - int BestCut, BestShare; - assert( Abc_ObjIsNode(pNode) ); - // get one factor-cut - vLeaves = Abc_CutFactor( pNode ); - if ( Vec_PtrSize(vLeaves) > nLeavesMax ) - { - Vec_PtrFree(vLeaves); - return NULL; - } - if ( Vec_PtrSize(vLeaves) == nLeavesMax ) - return vLeaves; - // initialize the factor cuts for the leaves - vFactors = Vec_PtrAlloc( nLeavesMax ); - Abc_NtkIncrementTravId( pNode->pNtk ); - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - { - Abc_NodeSetTravIdCurrent( pLeaf ); - if ( Abc_ObjIsCi(pLeaf) ) - Vec_PtrPush( vFactors, NULL ); - else - Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) ); - } - // construct larger factor cuts - vFeasible = Vec_IntAlloc( nLeavesMax ); - while ( 1 ) - { - BestCut = -1; - // find the next feasible cut to add - Vec_IntClear( vFeasible ); - Vec_PtrForEachEntry( vFactors, vFact, i ) - { - if ( vFact == NULL ) - continue; - // count the number of unmarked leaves of this factor cut - Counter = 0; - Vec_PtrForEachEntry( vFact, pTemp, k ) - Counter += !Abc_NodeIsTravIdCurrent(pTemp); - // if the number of new leaves is smaller than the diff, it is feasible - if ( Counter <= nLeavesMax - Vec_PtrSize(vLeaves) + 1 ) - { - Vec_IntPush( vFeasible, i ); - if ( BestCut == -1 || BestShare < Vec_PtrSize(vFact) - Counter ) - BestCut = i, BestShare = Vec_PtrSize(vFact) - Counter; - } - } - // quit if there is no feasible factor cuts - if ( Vec_IntSize(vFeasible) == 0 ) - break; - // randomly choose one leaf and get its factor cut -// RandLeaf = Vec_IntEntry( vFeasible, rand() % Vec_IntSize(vFeasible) ); - // choose the cut that has most sharing with the other cuts - RandLeaf = BestCut; - - pLeaf = Vec_PtrEntry( vLeaves, RandLeaf ); - vNext = Vec_PtrEntry( vFactors, RandLeaf ); - // unmark this leaf - Abc_NodeSetTravIdPrevious( pLeaf ); - // remove this cut from the leaves and factor cuts - for ( i = RandLeaf; i < Vec_PtrSize(vLeaves)-1; i++ ) - { - Vec_PtrWriteEntry( vLeaves, i, Vec_PtrEntry(vLeaves, i+1) ); - Vec_PtrWriteEntry( vFactors, i, Vec_PtrEntry(vFactors,i+1) ); - } - Vec_PtrShrink( vLeaves, Vec_PtrSize(vLeaves) -1 ); - Vec_PtrShrink( vFactors, Vec_PtrSize(vFactors)-1 ); - // add new leaves, compute their factor cuts - Vec_PtrForEachEntry( vNext, pLeaf, i ) - { - if ( Abc_NodeIsTravIdCurrent(pLeaf) ) - continue; - Abc_NodeSetTravIdCurrent( pLeaf ); - Vec_PtrPush( vLeaves, pLeaf ); - if ( Abc_ObjIsCi(pLeaf) ) - Vec_PtrPush( vFactors, NULL ); - else - Vec_PtrPush( vFactors, Abc_CutFactor(pLeaf) ); - } - Vec_PtrFree( vNext ); - assert( Vec_PtrSize(vLeaves) <= nLeavesMax ); - if ( Vec_PtrSize(vLeaves) == nLeavesMax ) - break; - } - - // remove temporary storage - Vec_PtrForEachEntry( vFactors, vFact, i ) - if ( vFact ) Vec_PtrFree( vFact ); - Vec_PtrFree( vFactors ); - Vec_IntFree( vFeasible ); - return vLeaves; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcRewrite.c b/src/base/abci/abcRewrite.c deleted file mode 100644 index 89b79e5a..00000000 --- a/src/base/abci/abcRewrite.c +++ /dev/null @@ -1,414 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcRewrite.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Technology-independent resynthesis of the AIG based on DAG aware rewriting.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcRewrite.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "rwr.h" -#include "dec.h" - -/* - The ideas realized in this package are inspired by the paper: - Per Bjesse, Arne Boralv, "DAG-aware circuit compression for - formal verification", Proc. ICCAD 2004, pp. 42-49. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ); -static void Abc_NodePrintCuts( Abc_Obj_t * pNode ); -static void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ); - -extern void Abc_PlaceBegin( Abc_Ntk_t * pNtk ); -extern void Abc_PlaceEnd( Abc_Ntk_t * pNtk ); -extern void Abc_PlaceUpdate( Vec_Ptr_t * vAddedCells, Vec_Ptr_t * vUpdatedNets ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs incremental rewriting of the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ) -{ - ProgressBar * pProgress; - Cut_Man_t * pManCut; - Rwr_Man_t * pManRwr; - Abc_Obj_t * pNode; - Vec_Ptr_t * vAddedCells = NULL, * vUpdatedNets = NULL; - Dec_Graph_t * pGraph; - int i, nNodes, nGain, fCompl; - int clk, clkStart = clock(); - - assert( Abc_NtkIsStrash(pNtk) ); - // cleanup the AIG - Abc_AigCleanup(pNtk->pManFunc); -/* - { - Vec_Vec_t * vParts; - vParts = Abc_NtkPartitionSmart( pNtk, 50, 1 ); - Vec_VecFree( vParts ); - } -*/ - - // start placement package - if ( fPlaceEnable ) - { - Abc_PlaceBegin( pNtk ); - vAddedCells = Abc_AigUpdateStart( pNtk->pManFunc, &vUpdatedNets ); - } - - // start the rewriting manager - pManRwr = Rwr_ManStart( 0 ); - if ( pManRwr == NULL ) - return 0; - // compute the reverse levels if level update is requested - if ( fUpdateLevel ) - Abc_NtkStartReverseLevels( pNtk, 0 ); - // start the cut manager -clk = clock(); - pManCut = Abc_NtkStartCutManForRewrite( pNtk ); -Rwr_ManAddTimeCuts( pManRwr, clock() - clk ); - pNtk->pManCut = pManCut; - - if ( fVeryVerbose ) - Rwr_ScoresClean( pManRwr ); - - // resynthesize each node once - pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk); - nNodes = Abc_NtkObjNumMax(pNtk); - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // stop if all nodes have been tried once - if ( i >= nNodes ) - break; - // skip persistant nodes - if ( Abc_NodeIsPersistant(pNode) ) - continue; - // skip the nodes with many fanouts - if ( Abc_ObjFanoutNum(pNode) > 1000 ) - continue; - - // for each cut, try to resynthesize it - nGain = Rwr_NodeRewrite( pManRwr, pManCut, pNode, fUpdateLevel, fUseZeros, fPlaceEnable ); - if ( !(nGain > 0 || nGain == 0 && fUseZeros) ) - continue; - // if we end up here, a rewriting step is accepted - - // get hold of the new subgraph to be added to the AIG - pGraph = Rwr_ManReadDecs(pManRwr); - fCompl = Rwr_ManReadCompl(pManRwr); - - // reset the array of the changed nodes - if ( fPlaceEnable ) - Abc_AigUpdateReset( pNtk->pManFunc ); - - // complement the FF if needed - if ( fCompl ) Dec_GraphComplement( pGraph ); -clk = clock(); - Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain ); -Rwr_ManAddTimeUpdate( pManRwr, clock() - clk ); - if ( fCompl ) Dec_GraphComplement( pGraph ); - - // use the array of changed nodes to update placement - if ( fPlaceEnable ) - Abc_PlaceUpdate( vAddedCells, vUpdatedNets ); - } - Extra_ProgressBarStop( pProgress ); -Rwr_ManAddTimeTotal( pManRwr, clock() - clkStart ); - // print stats - pManRwr->nNodesEnd = Abc_NtkNodeNum(pNtk); - if ( fVerbose ) - Rwr_ManPrintStats( pManRwr ); -// Rwr_ManPrintStatsFile( pManRwr ); - if ( fVeryVerbose ) - Rwr_ScoresReport( pManRwr ); - // delete the managers - Rwr_ManStop( pManRwr ); - Cut_ManStop( pManCut ); - pNtk->pManCut = NULL; - - // start placement package - if ( fPlaceEnable ) - { - Abc_PlaceEnd( pNtk ); - Abc_AigUpdateStop( pNtk->pManFunc ); - } - - // put the nodes into the DFS order and reassign their IDs - { -// int clk = clock(); - Abc_NtkReassignIds( pNtk ); -// PRT( "time", clock() - clk ); - } -// Abc_AigCheckFaninOrder( pNtk->pManFunc ); - // fix the levels - if ( fUpdateLevel ) - Abc_NtkStopReverseLevels( pNtk ); - else - Abc_NtkLevel( pNtk ); - // check - if ( !Abc_NtkCheck( pNtk ) ) - { - printf( "Abc_NtkRewrite: The network check has failed.\n" ); - return 0; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Starts the cut manager for rewriting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Man_t * Abc_NtkStartCutManForRewrite( Abc_Ntk_t * pNtk ) -{ - static Cut_Params_t Params, * pParams = &Params; - Cut_Man_t * pManCut; - Abc_Obj_t * pObj; - int i; - // start the cut manager - memset( pParams, 0, sizeof(Cut_Params_t) ); - pParams->nVarsMax = 4; // the max cut size ("k" of the k-feasible cuts) - pParams->nKeepMax = 250; // the max number of cuts kept at a node - pParams->fTruth = 1; // compute truth tables - pParams->fFilter = 1; // filter dominated cuts - pParams->fSeq = 0; // compute sequential cuts - pParams->fDrop = 0; // drop cuts on the fly - pParams->fVerbose = 0; // the verbosiness flag - pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); - pManCut = Cut_ManStart( pParams ); - if ( pParams->fDrop ) - Cut_ManSetFanoutCounts( pManCut, Abc_NtkFanoutCounts(pNtk) ); - // set cuts for PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) > 0 ) - Cut_NodeSetTriv( pManCut, pObj->Id ); - return pManCut; -} - -/**Function************************************************************* - - Synopsis [Prints the cuts at the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodePrintCuts( Abc_Obj_t * pNode ) -{ - Vec_Ptr_t * vCuts; - Cut_Cut_t * pCut; - int k; - - printf( "\nNode %s\n", Abc_ObjName(pNode) ); - vCuts = (Vec_Ptr_t *)pNode->pCopy; - Vec_PtrForEachEntry( vCuts, pCut, k ) - { - Extra_PrintBinary( stdout, (unsigned *)&pCut->uSign, 16 ); - printf( " " ); - Cut_CutPrint( pCut, 0 ); - printf( "\n" ); - } -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManRewritePrintDivs( Vec_Ptr_t * vDivs, int nLeaves ) -{ - Abc_Obj_t * pFanin, * pNode, * pRoot; - int i, k; - pRoot = Vec_PtrEntryLast(vDivs); - // print the nodes - Vec_PtrForEachEntry( vDivs, pNode, i ) - { - if ( i < nLeaves ) - { - printf( "%6d : %c\n", pNode->Id, 'a'+i ); - continue; - } - printf( "%6d : %2d = ", pNode->Id, i ); - // find the first fanin - Vec_PtrForEachEntry( vDivs, pFanin, k ) - if ( Abc_ObjFanin0(pNode) == pFanin ) - break; - if ( k < nLeaves ) - printf( "%c", 'a' + k ); - else - printf( "%d", k ); - printf( "%s ", Abc_ObjFaninC0(pNode)? "\'" : "" ); - // find the second fanin - Vec_PtrForEachEntry( vDivs, pFanin, k ) - if ( Abc_ObjFanin1(pNode) == pFanin ) - break; - if ( k < nLeaves ) - printf( "%c", 'a' + k ); - else - printf( "%d", k ); - printf( "%s ", Abc_ObjFaninC1(pNode)? "\'" : "" ); - if ( pNode == pRoot ) - printf( " root" ); - printf( "\n" ); - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManShowCutCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vDivs ) -{ - if ( Abc_NodeIsTravIdCurrent(pNode) ) - return; - Abc_NodeSetTravIdCurrent(pNode); - Abc_ManShowCutCone_rec( Abc_ObjFanin0(pNode), vDivs ); - Abc_ManShowCutCone_rec( Abc_ObjFanin1(pNode), vDivs ); - Vec_PtrPush( vDivs, pNode ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManShowCutCone( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) -{ - Abc_Ntk_t * pNtk = pNode->pNtk; - Abc_Obj_t * pObj; - Vec_Ptr_t * vDivs; - int i; - vDivs = Vec_PtrAlloc( 100 ); - Abc_NtkIncrementTravId( pNtk ); - Vec_PtrForEachEntry( vLeaves, pObj, i ) - { - Abc_NodeSetTravIdCurrent( Abc_ObjRegular(pObj) ); - Vec_PtrPush( vDivs, Abc_ObjRegular(pObj) ); - } - Abc_ManShowCutCone_rec( pNode, vDivs ); - Abc_ManRewritePrintDivs( vDivs, Vec_PtrSize(vLeaves) ); - Vec_PtrFree( vDivs ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_RwrExpWithCut_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, int fUseA ) -{ - if ( Vec_PtrFind(vLeaves, pNode) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pNode)) >= 0 ) - { - if ( fUseA ) - Abc_ObjRegular(pNode)->fMarkA = 1; - else - Abc_ObjRegular(pNode)->fMarkB = 1; - return; - } - assert( Abc_ObjIsNode(pNode) ); - Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, fUseA ); - Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, fUseA ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_RwrExpWithCut( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves ) -{ - Abc_Obj_t * pObj; - int i, CountA, CountB; - Abc_RwrExpWithCut_rec( Abc_ObjFanin0(pNode), vLeaves, 1 ); - Abc_RwrExpWithCut_rec( Abc_ObjFanin1(pNode), vLeaves, 0 ); - CountA = CountB = 0; - Vec_PtrForEachEntry( vLeaves, pObj, i ) - { - CountA += Abc_ObjRegular(pObj)->fMarkA; - CountB += Abc_ObjRegular(pObj)->fMarkB; - Abc_ObjRegular(pObj)->fMarkA = 0; - Abc_ObjRegular(pObj)->fMarkB = 0; - } - printf( "(%d,%d:%d) ", CountA, CountB, CountA+CountB-Vec_PtrSize(vLeaves) ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcRr.c b/src/base/abci/abcRr.c deleted file mode 100644 index 92adc718..00000000 --- a/src/base/abci/abcRr.c +++ /dev/null @@ -1,999 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcRr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Redundancy removal.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcRr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "fraig.h" -#include "sim.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Abc_RRMan_t_ Abc_RRMan_t; -struct Abc_RRMan_t_ -{ - // the parameters - Abc_Ntk_t * pNtk; // the network - int nFaninLevels; // the number of fanin levels - int nFanoutLevels; // the number of fanout levels - // the node/fanin/fanout - Abc_Obj_t * pNode; // the node - Abc_Obj_t * pFanin; // the fanin - Abc_Obj_t * pFanout; // the fanout - // the intermediate cones - Vec_Ptr_t * vFaninLeaves; // the leaves of the fanin cone - Vec_Ptr_t * vFanoutRoots; // the roots of the fanout cone - // the window - Vec_Ptr_t * vLeaves; // the leaves of the window - Vec_Ptr_t * vCone; // the internal nodes of the window - Vec_Ptr_t * vRoots; // the roots of the window - Abc_Ntk_t * pWnd; // the window derived for the edge - // the miter - Abc_Ntk_t * pMiter; // the miter derived from the window - Prove_Params_t * pParams; // the miter proving parameters - // statistical variables - int nNodesOld; // the old number of nodes - int nLevelsOld; // the old number of levels - int nEdgesTried; // the number of nodes tried - int nEdgesRemoved; // the number of nodes proved - int timeWindow; // the time to construct the window - int timeMiter; // the time to construct the miter - int timeProve; // the time to prove the miter - int timeUpdate; // the network update time - int timeTotal; // the total runtime -}; - -static Abc_RRMan_t * Abc_RRManStart(); -static void Abc_RRManStop( Abc_RRMan_t * p ); -static void Abc_RRManPrintStats( Abc_RRMan_t * p ); -static void Abc_RRManClean( Abc_RRMan_t * p ); -static int Abc_NtkRRProve( Abc_RRMan_t * p ); -static int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ); -static int Abc_NtkRRWindow( Abc_RRMan_t * p ); - -static int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit ); -static int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ); -static int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ); -static void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit ); -static Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots ); - -static void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk ); -static void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Removes stuck-at redundancies.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose ) -{ - ProgressBar * pProgress; - Abc_RRMan_t * p; - Abc_Obj_t * pNode, * pFanin, * pFanout; - int i, k, m, nNodes, RetValue, clk, clkTotal = clock(); - // start the manager - p = Abc_RRManStart( nFaninLevels, nFanoutLevels ); - p->pNtk = pNtk; - p->nFaninLevels = nFaninLevels; - p->nFanoutLevels = nFanoutLevels; - p->nNodesOld = Abc_NtkNodeNum(pNtk); - p->nLevelsOld = Abc_AigLevel(pNtk); - // remember latch values -// Abc_NtkForEachLatch( pNtk, pNode, i ) -// pNode->pNext = pNode->pData; - // go through the nodes - Abc_NtkCleanCopy(pNtk); - nNodes = Abc_NtkObjNumMax(pNtk); - Abc_NtkRRSimulateStart(pNtk); - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // stop if all nodes have been tried once - if ( i >= nNodes ) - break; - // skip the constant node -// if ( Abc_NodeIsConst(pNode) ) -// continue; - // skip persistant nodes - if ( Abc_NodeIsPersistant(pNode) ) - continue; - // skip the nodes with many fanouts - if ( Abc_ObjFanoutNum(pNode) > 1000 ) - continue; - // construct the window - if ( !fUseFanouts ) - { - Abc_ObjForEachFanin( pNode, pFanin, k ) - { - // skip the nodes with only one fanout (tree nodes) - if ( Abc_ObjFanoutNum(pFanin) == 1 ) - continue; -/* - if ( pFanin->Id == 228 && pNode->Id == 2649 ) - { - int k = 0; - } -*/ - p->nEdgesTried++; - Abc_RRManClean( p ); - p->pNode = pNode; - p->pFanin = pFanin; - p->pFanout = NULL; - - clk = clock(); - RetValue = Abc_NtkRRWindow( p ); - p->timeWindow += clock() - clk; - if ( !RetValue ) - continue; -/* - if ( pFanin->Id == 228 && pNode->Id == 2649 ) - { - Abc_NtkShowAig( p->pWnd, 0 ); - } -*/ - clk = clock(); - RetValue = Abc_NtkRRProve( p ); - p->timeMiter += clock() - clk; - if ( !RetValue ) - continue; -//printf( "%d -> %d (%d)\n", pFanin->Id, pNode->Id, k ); - - clk = clock(); - Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); - p->timeUpdate += clock() - clk; - - p->nEdgesRemoved++; - break; - } - continue; - } - // use the fanouts - Abc_ObjForEachFanin( pNode, pFanin, k ) - Abc_ObjForEachFanout( pNode, pFanout, m ) - { - // skip the nodes with only one fanout (tree nodes) -// if ( Abc_ObjFanoutNum(pFanin) == 1 && Abc_ObjFanoutNum(pNode) == 1 ) -// continue; - - p->nEdgesTried++; - Abc_RRManClean( p ); - p->pNode = pNode; - p->pFanin = pFanin; - p->pFanout = pFanout; - - clk = clock(); - RetValue = Abc_NtkRRWindow( p ); - p->timeWindow += clock() - clk; - if ( !RetValue ) - continue; - - clk = clock(); - RetValue = Abc_NtkRRProve( p ); - p->timeMiter += clock() - clk; - if ( !RetValue ) - continue; - - clk = clock(); - Abc_NtkRRUpdate( pNtk, p->pNode, p->pFanin, p->pFanout ); - p->timeUpdate += clock() - clk; - - p->nEdgesRemoved++; - break; - } - } - Abc_NtkRRSimulateStop(pNtk); - Extra_ProgressBarStop( pProgress ); - p->timeTotal = clock() - clkTotal; - if ( fVerbose ) - Abc_RRManPrintStats( p ); - Abc_RRManStop( p ); - // restore latch values -// Abc_NtkForEachLatch( pNtk, pNode, i ) -// pNode->pData = pNode->pNext, pNode->pNext = NULL; - // put the nodes into the DFS order and reassign their IDs - Abc_NtkReassignIds( pNtk ); - Abc_NtkLevel( pNtk ); - // check - if ( !Abc_NtkCheck( pNtk ) ) - { - printf( "Abc_NtkRR: The network check has failed.\n" ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Start the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_RRMan_t * Abc_RRManStart() -{ - Abc_RRMan_t * p; - p = ALLOC( Abc_RRMan_t, 1 ); - memset( p, 0, sizeof(Abc_RRMan_t) ); - p->vFaninLeaves = Vec_PtrAlloc( 100 ); // the leaves of the fanin cone - p->vFanoutRoots = Vec_PtrAlloc( 100 ); // the roots of the fanout cone - p->vLeaves = Vec_PtrAlloc( 100 ); // the leaves of the window - p->vCone = Vec_PtrAlloc( 100 ); // the internal nodes of the window - p->vRoots = Vec_PtrAlloc( 100 ); // the roots of the window - p->pParams = ALLOC( Prove_Params_t, 1 ); - memset( p->pParams, 0, sizeof(Prove_Params_t) ); - Prove_ParamsSetDefault( p->pParams ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stop the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_RRManStop( Abc_RRMan_t * p ) -{ - Abc_RRManClean( p ); - Vec_PtrFree( p->vFaninLeaves ); - Vec_PtrFree( p->vFanoutRoots ); - Vec_PtrFree( p->vLeaves ); - Vec_PtrFree( p->vCone ); - Vec_PtrFree( p->vRoots ); - free( p->pParams ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Stop the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_RRManPrintStats( Abc_RRMan_t * p ) -{ - double Ratio = 100.0*(p->nNodesOld - Abc_NtkNodeNum(p->pNtk))/p->nNodesOld; - printf( "Redundancy removal statistics:\n" ); - printf( "Edges tried = %6d.\n", p->nEdgesTried ); - printf( "Edges removed = %6d. (%5.2f %%)\n", p->nEdgesRemoved, 100.0*p->nEdgesRemoved/p->nEdgesTried ); - printf( "Node gain = %6d. (%5.2f %%)\n", p->nNodesOld - Abc_NtkNodeNum(p->pNtk), Ratio ); - printf( "Level gain = %6d.\n", p->nLevelsOld - Abc_AigLevel(p->pNtk) ); - PRT( "Windowing ", p->timeWindow ); - PRT( "Miter ", p->timeMiter ); - PRT( " Construct ", p->timeMiter - p->timeProve ); - PRT( " Prove ", p->timeProve ); - PRT( "Update ", p->timeUpdate ); - PRT( "TOTAL ", p->timeTotal ); -} - -/**Function************************************************************* - - Synopsis [Clean the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_RRManClean( Abc_RRMan_t * p ) -{ - p->pNode = NULL; - p->pFanin = NULL; - p->pFanout = NULL; - Vec_PtrClear( p->vFaninLeaves ); - Vec_PtrClear( p->vFanoutRoots ); - Vec_PtrClear( p->vLeaves ); - Vec_PtrClear( p->vCone ); - Vec_PtrClear( p->vRoots ); - if ( p->pWnd ) Abc_NtkDelete( p->pWnd ); - if ( p->pMiter ) Abc_NtkDelete( p->pMiter ); - p->pWnd = NULL; - p->pMiter = NULL; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the miter is constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRRProve( Abc_RRMan_t * p ) -{ - Abc_Ntk_t * pWndCopy; - int RetValue, clk; -// Abc_NtkShowAig( p->pWnd, 0 ); - pWndCopy = Abc_NtkDup( p->pWnd ); - Abc_NtkRRUpdate( pWndCopy, p->pNode->pCopy->pCopy, p->pFanin->pCopy->pCopy, p->pFanout? p->pFanout->pCopy->pCopy : NULL ); - if ( !Abc_NtkIsDfsOrdered(pWndCopy) ) - Abc_NtkReassignIds(pWndCopy); - p->pMiter = Abc_NtkMiter( p->pWnd, pWndCopy, 1, 0 ); - Abc_NtkDelete( pWndCopy ); -clk = clock(); - RetValue = Abc_NtkMiterProve( &p->pMiter, p->pParams ); -p->timeProve += clock() - clk; - if ( RetValue == 1 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Updates the network after redundancy removal.] - - Description [This procedure assumes that non-control value of the fanin - was proved redundant. It is okay to concentrate on non-control values - because the control values can be seen as redundancy of the fanout edge.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRRUpdate( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ) -{ - Abc_Obj_t * pNodeNew, * pFanoutNew; - assert( pFanout == NULL ); - assert( !Abc_ObjIsComplement(pNode) ); - assert( !Abc_ObjIsComplement(pFanin) ); - assert( !Abc_ObjIsComplement(pFanout) ); - // find the node after redundancy removal - if ( pFanin == Abc_ObjFanin0(pNode) ) - pNodeNew = Abc_ObjChild1(pNode); - else if ( pFanin == Abc_ObjFanin1(pNode) ) - pNodeNew = Abc_ObjChild0(pNode); - else assert( 0 ); - // replace - if ( pFanout == NULL ) - { - Abc_AigReplace( pNtk->pManFunc, pNode, pNodeNew, 1 ); - return 1; - } - // find the fanout after redundancy removal - if ( pNode == Abc_ObjFanin0(pFanout) ) - pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC0(pFanout)), Abc_ObjChild1(pFanout) ); - else if ( pNode == Abc_ObjFanin1(pFanout) ) - pFanoutNew = Abc_AigAnd( pNtk->pManFunc, Abc_ObjNotCond(pNodeNew,Abc_ObjFaninC1(pFanout)), Abc_ObjChild0(pFanout) ); - else assert( 0 ); - // replace - Abc_AigReplace( pNtk->pManFunc, pFanout, pFanoutNew, 1 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Constructs window for checking RR.] - - Description [If the window (p->pWnd) with the given scope (p->nFaninLevels, - p->nFanoutLevels) cannot be constructed, returns 0. Otherwise, returns 1. - The levels are measured from the fanin node (pFanin) and the fanout node - (pEdgeFanout), respectively.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRRWindow( Abc_RRMan_t * p ) -{ - Abc_Obj_t * pObj, * pEdgeFanin, * pEdgeFanout; - int i, LevelMin, LevelMax, RetValue; - - // get the edge - pEdgeFanout = p->pFanout? p->pFanout : p->pNode; - pEdgeFanin = p->pFanout? p->pNode : p->pFanin; - // get the minimum and maximum levels of the window - LevelMin = ABC_MAX( 0, ((int)p->pFanin->Level) - p->nFaninLevels ); - LevelMax = (int)pEdgeFanout->Level + p->nFanoutLevels; - - // start the TFI leaves with the fanin - Abc_NtkIncrementTravId( p->pNtk ); - Abc_NodeSetTravIdCurrent( p->pFanin ); - Vec_PtrPush( p->vFaninLeaves, p->pFanin ); - // mark the TFI cone and collect the leaves down to the given level - while ( Abc_NtkRRTfi_int(p->vFaninLeaves, LevelMin) ); - - // mark the leaves with the new TravId - Abc_NtkIncrementTravId( p->pNtk ); - Vec_PtrForEachEntry( p->vFaninLeaves, pObj, i ) - Abc_NodeSetTravIdCurrent( pObj ); - // traverse the TFO cone of the leaves (while skipping the edge) - // (a) mark the nodes in the cone using the current TravId - // (b) collect the nodes that have external fanouts into p->vFanoutRoots - while ( Abc_NtkRRTfo_int(p->vFaninLeaves, p->vFanoutRoots, LevelMax, pEdgeFanin, pEdgeFanout) ); - - // mark the fanout roots - Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i ) - pObj->fMarkA = 1; - // collect roots reachable from the fanout (p->vRoots) - RetValue = Abc_NtkRRTfo_rec( pEdgeFanout, p->vRoots, LevelMax + 1 ); - // unmark the fanout roots - Vec_PtrForEachEntry( p->vFanoutRoots, pObj, i ) - pObj->fMarkA = 0; - - // return if the window is infeasible - if ( RetValue == 0 ) - return 0; - - // collect the DFS-ordered new cone (p->vCone) and new leaves (p->vLeaves) - // using the previous marks coming from the TFO cone - Abc_NtkIncrementTravId( p->pNtk ); - Vec_PtrForEachEntry( p->vRoots, pObj, i ) - Abc_NtkRRTfi_rec( pObj, p->vLeaves, p->vCone, LevelMin ); - - // create a new network - p->pWnd = Abc_NtkWindow( p->pNtk, p->vLeaves, p->vCone, p->vRoots ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Marks the nodes in the TFI and collects their leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRRTfi_int( Vec_Ptr_t * vLeaves, int LevelLimit ) -{ - Abc_Obj_t * pObj, * pNext; - int i, k, LevelMax, nSize; - assert( LevelLimit >= 0 ); - // find the maximum level of leaves - LevelMax = 0; - Vec_PtrForEachEntry( vLeaves, pObj, i ) - if ( LevelMax < (int)pObj->Level ) - LevelMax = pObj->Level; - // if the nodes are all PIs, LevelMax == 0 - if ( LevelMax <= LevelLimit ) - return 0; - // expand the nodes with the minimum level - nSize = Vec_PtrSize(vLeaves); - Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize ) - { - if ( LevelMax != (int)pObj->Level ) - continue; - Abc_ObjForEachFanin( pObj, pNext, k ) - { - if ( Abc_NodeIsTravIdCurrent(pNext) ) - continue; - Abc_NodeSetTravIdCurrent( pNext ); - Vec_PtrPush( vLeaves, pNext ); - } - } - // remove old nodes (cannot remove a PI) - k = 0; - Vec_PtrForEachEntry( vLeaves, pObj, i ) - { - if ( LevelMax == (int)pObj->Level ) - continue; - Vec_PtrWriteEntry( vLeaves, k++, pObj ); - } - Vec_PtrShrink( vLeaves, k ); - if ( Vec_PtrSize(vLeaves) > 2000 ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Marks the nodes in the TFO and collects their roots.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRRTfo_int( Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, int LevelLimit, Abc_Obj_t * pEdgeFanin, Abc_Obj_t * pEdgeFanout ) -{ - Abc_Obj_t * pObj, * pNext; - int i, k, LevelMin, nSize, fObjIsRoot; - // find the minimum level of leaves - LevelMin = ABC_INFINITY; - Vec_PtrForEachEntry( vLeaves, pObj, i ) - if ( LevelMin > (int)pObj->Level ) - LevelMin = pObj->Level; - // if the minimum level exceed the limit, we are done - if ( LevelMin > LevelLimit ) - return 0; - // expand the nodes with the minimum level - nSize = Vec_PtrSize(vLeaves); - Vec_PtrForEachEntryStop( vLeaves, pObj, i, nSize ) - { - if ( LevelMin != (int)pObj->Level ) - continue; - fObjIsRoot = 0; - Abc_ObjForEachFanout( pObj, pNext, k ) - { - // check if the fanout is outside of the cone - if ( Abc_ObjIsCo(pNext) || pNext->Level > (unsigned)LevelLimit ) - { - fObjIsRoot = 1; - continue; - } - // skip the edge under check - if ( pObj == pEdgeFanin && pNext == pEdgeFanout ) - continue; - // skip the visited fanouts - if ( Abc_NodeIsTravIdCurrent(pNext) ) - continue; - Abc_NodeSetTravIdCurrent( pNext ); - Vec_PtrPush( vLeaves, pNext ); - } - if ( fObjIsRoot ) - Vec_PtrPush( vRoots, pObj ); - } - // remove old nodes - k = 0; - Vec_PtrForEachEntry( vLeaves, pObj, i ) - { - if ( LevelMin == (int)pObj->Level ) - continue; - Vec_PtrWriteEntry( vLeaves, k++, pObj ); - } - Vec_PtrShrink( vLeaves, k ); - if ( Vec_PtrSize(vLeaves) > 2000 ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Collects the roots in the TFO of the node.] - - Description [Note that this procedure can be improved by - marking and skipping the visited nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRRTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vRoots, int LevelLimit ) -{ - Abc_Obj_t * pFanout; - int i; - // if we encountered a node outside of the TFO cone of the fanins, quit - if ( Abc_ObjIsCo(pNode) || pNode->Level > (unsigned)LevelLimit ) - return 0; - // if we encountered a node on the boundary, add it to the roots - if ( pNode->fMarkA ) - { - Vec_PtrPushUnique( vRoots, pNode ); - return 1; - } - // mark the node with the current TravId (needed to have all internal nodes marked) - Abc_NodeSetTravIdCurrent( pNode ); - // traverse the fanouts - Abc_ObjForEachFanout( pNode, pFanout, i ) - if ( !Abc_NtkRRTfo_rec( pFanout, vRoots, LevelLimit ) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Collects the leaves and cone of the roots.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRRTfi_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, int LevelLimit ) -{ - Abc_Obj_t * pFanin; - int i; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pNode) ) - return; - // add node to leaves if it is not in TFI cone of the leaves (marked before) or below the limit - if ( !Abc_NodeIsTravIdPrevious(pNode) || (int)pNode->Level <= LevelLimit ) - { - Abc_NodeSetTravIdCurrent( pNode ); - Vec_PtrPush( vLeaves, pNode ); - return; - } - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // call for the node's fanins - Abc_ObjForEachFanin( pNode, pFanin, i ) - Abc_NtkRRTfi_rec( pFanin, vLeaves, vCone, LevelLimit ); - // add the node to the cone in topological order - Vec_PtrPush( vCone, pNode ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkWindow( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vRoots ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj; - int fCheck = 1; - int i; - assert( Abc_NtkIsStrash(pNtk) ); - // start the network - pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); - // duplicate the name and the spec - pNtkNew->pName = Extra_UtilStrsav( "temp" ); - // map the constant nodes - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); - // create and map the PIs - Vec_PtrForEachEntry( vLeaves, pObj, i ) - pObj->pCopy = Abc_NtkCreatePi(pNtkNew); - // copy the AND gates - Vec_PtrForEachEntry( vCone, pObj, i ) - pObj->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - // compare the number of nodes before and after - if ( Vec_PtrSize(vCone) != Abc_NtkNodeNum(pNtkNew) ) - printf( "Warning: Structural hashing during windowing reduced %d nodes (this is a bug).\n", - Vec_PtrSize(vCone) - Abc_NtkNodeNum(pNtkNew) ); - // create the POs - Vec_PtrForEachEntry( vRoots, pObj, i ) - { - assert( !Abc_ObjIsComplement(pObj->pCopy) ); - Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObj->pCopy ); - } - // add the PI/PO names - Abc_NtkAddDummyPiNames( pNtkNew ); - Abc_NtkAddDummyPoNames( pNtkNew ); - Abc_NtkAddDummyAssertNames( pNtkNew ); - // check - if ( fCheck && !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkWindow: The network check has failed.\n" ); - return NULL; - } - return pNtkNew; -} - - -/**Function************************************************************* - - Synopsis [Starts simulation to detect non-redundant edges.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRRSimulateStart( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - unsigned uData, uData0, uData1; - int i; - Abc_AigConst1(pNtk)->pData = (void *)~((unsigned)0); - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pData = (void *)SIM_RANDOM_UNSIGNED; - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( i == 0 ) continue; - uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; - uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData; - uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0; - uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1; - assert( pObj->pData == NULL ); - pObj->pData = (void *)uData; - } -} - -/**Function************************************************************* - - Synopsis [Stops simulation to detect non-redundant edges.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRRSimulateStop( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pData = NULL; -} - - - - - - - -static void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes ); -static void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField ); -static void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField ); - -/**Function************************************************************* - - Synopsis [Simulation to detect non-redundant edges.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Str_t * Abc_NtkRRSimulate( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes, * vField; - Vec_Str_t * vTargets; - Abc_Obj_t * pObj; - unsigned uData, uData0, uData1; - int PrevCi, Phase, i, k; - - // start the candidates - vTargets = Vec_StrStart( Abc_NtkObjNumMax(pNtk) + 1 ); - Abc_NtkForEachNode( pNtk, pObj, i ) - { - Phase = ((Abc_ObjFanoutNum(Abc_ObjFanin1(pObj)) > 1) << 1); - Phase |= (Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) > 1); - Vec_StrWriteEntry( vTargets, pObj->Id, (char)Phase ); - } - - // simulate patters and store them in copy - Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)~((unsigned)0); - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)SIM_RANDOM_UNSIGNED; - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( i == 0 ) continue; - uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; - uData1 = (unsigned)Abc_ObjFanin1(pObj)->pData; - uData = Abc_ObjFaninC0(pObj)? ~uData0 : uData0; - uData &= Abc_ObjFaninC1(pObj)? ~uData1 : uData1; - pObj->pCopy = (Abc_Obj_t *)uData; - } - // store the result in data - Abc_NtkForEachCo( pNtk, pObj, i ) - { - uData0 = (unsigned)Abc_ObjFanin0(pObj)->pData; - if ( Abc_ObjFaninC0(pObj) ) - pObj->pData = (void *)~uData0; - else - pObj->pData = (void *)uData0; - } - - // refine the candidates - for ( PrevCi = 0; PrevCi < Abc_NtkCiNum(pNtk); PrevCi = i ) - { - vNodes = Vec_PtrAlloc( 10 ); - Abc_NtkIncrementTravId( pNtk ); - for ( i = PrevCi; i < Abc_NtkCiNum(pNtk); i++ ) - { - Sim_TraverseNodes_rec( Abc_NtkCi(pNtk, i), vTargets, vNodes ); - if ( Vec_PtrSize(vNodes) > 128 ) - break; - } - // collect the marked nodes in the topological order - vField = Vec_PtrAlloc( 10 ); - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachCo( pNtk, pObj, k ) - Sim_CollectNodes_rec( pObj, vField ); - - // simulate these nodes - Sim_SimulateCollected( vTargets, vNodes, vField ); - // prepare for the next loop - Vec_PtrFree( vNodes ); - } - - // clean - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->pData = NULL; - return vTargets; -} - -/**Function************************************************************* - - Synopsis [Collects nodes starting from the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_TraverseNodes_rec( Abc_Obj_t * pRoot, Vec_Str_t * vTargets, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanout; - char Entry; - int k; - if ( Abc_NodeIsTravIdCurrent(pRoot) ) - return; - Abc_NodeSetTravIdCurrent( pRoot ); - // save the reached targets - Entry = Vec_StrEntry(vTargets, pRoot->Id); - if ( Entry & 1 ) - Vec_PtrPush( vNodes, Abc_ObjNot(pRoot) ); - if ( Entry & 2 ) - Vec_PtrPush( vNodes, pRoot ); - // explore the fanouts - Abc_ObjForEachFanout( pRoot, pFanout, k ) - Sim_TraverseNodes_rec( pFanout, vTargets, vNodes ); -} - -/**Function************************************************************* - - Synopsis [Collects nodes starting from the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_CollectNodes_rec( Abc_Obj_t * pRoot, Vec_Ptr_t * vField ) -{ - Abc_Obj_t * pFanin; - int i; - if ( Abc_NodeIsTravIdCurrent(pRoot) ) - return; - if ( !Abc_NodeIsTravIdPrevious(pRoot) ) - return; - Abc_NodeSetTravIdCurrent( pRoot ); - Abc_ObjForEachFanin( pRoot, pFanin, i ) - Sim_CollectNodes_rec( pFanin, vField ); - if ( !Abc_ObjIsCo(pRoot) ) - pRoot->pData = (void *)Vec_PtrSize(vField); - Vec_PtrPush( vField, pRoot ); -} - -/**Function************************************************************* - - Synopsis [Simulate the given nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SimulateCollected( Vec_Str_t * vTargets, Vec_Ptr_t * vNodes, Vec_Ptr_t * vField ) -{ - Abc_Obj_t * pObj, * pFanin0, * pFanin1, * pDisproved; - Vec_Ptr_t * vSims; - unsigned * pUnsigned, * pUnsignedF; - int i, k, Phase, fCompl; - // get simulation info - vSims = Sim_UtilInfoAlloc( Vec_PtrSize(vField), Vec_PtrSize(vNodes), 0 ); - // simulate the nodes - Vec_PtrForEachEntry( vField, pObj, i ) - { - if ( Abc_ObjIsCi(pObj) ) - { - pUnsigned = Vec_PtrEntry( vSims, i ); - for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) - pUnsigned[k] = (unsigned)pObj->pCopy; - continue; - } - if ( Abc_ObjIsCo(pObj) ) - { - pUnsigned = Vec_PtrEntry( vSims, i ); - pUnsignedF = Vec_PtrEntry( vSims, (int)Abc_ObjFanin0(pObj)->pData ); - if ( Abc_ObjFaninC0(pObj) ) - for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) - pUnsigned[k] = ~pUnsignedF[k]; - else - for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) - pUnsigned[k] = pUnsignedF[k]; - // update targets - for ( k = 0; k < Vec_PtrSize(vNodes); k++ ) - { - if ( pUnsigned[k] == (unsigned)pObj->pData ) - continue; - pDisproved = Vec_PtrEntry( vNodes, k ); - fCompl = Abc_ObjIsComplement(pDisproved); - pDisproved = Abc_ObjRegular(pDisproved); - Phase = Vec_StrEntry( vTargets, pDisproved->Id ); - if ( fCompl ) - Phase = (Phase & 2); - else - Phase = (Phase & 1); - Vec_StrWriteEntry( vTargets, pDisproved->Id, (char)Phase ); - } - continue; - } - // simulate the node - pFanin0 = Abc_ObjFanin0(pObj); - pFanin1 = Abc_ObjFanin1(pObj); - } -} - - - -/* - { - unsigned uData; - if ( pFanin == Abc_ObjFanin0(pNode) ) - { - uData = (unsigned)Abc_ObjFanin1(pNode)->pData; - uData = Abc_ObjFaninC1(pNode)? ~uData : uData; - } - else if ( pFanin == Abc_ObjFanin1(pNode) ) - { - uData = (unsigned)Abc_ObjFanin0(pNode)->pData; - uData = Abc_ObjFaninC0(pNode)? ~uData : uData; - } - uData ^= (unsigned)pNode->pData; -// Extra_PrintBinary( stdout, &uData, 32 ); printf( "\n" ); - if ( Extra_WordCountOnes(uData) > 8 ) - continue; - } -*/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcSat.c b/src/base/abci/abcSat.c deleted file mode 100644 index 58614584..00000000 --- a/src/base/abci/abcSat.c +++ /dev/null @@ -1,884 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Procedures to solve the miter using the internal SAT sat_solver.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "satSolver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes ); -extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); -static nMuxes; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Attempts to solve the miter using an internal SAT sat_solver.] - - Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects ) -{ - sat_solver * pSat; - lbool status; - int RetValue, clk; - - if ( pNumConfs ) - *pNumConfs = 0; - if ( pNumInspects ) - *pNumInspects = 0; - - assert( Abc_NtkLatchNum(pNtk) == 0 ); - -// if ( Abc_NtkPoNum(pNtk) > 1 ) -// fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) ); - - // load clauses into the sat_solver - clk = clock(); - pSat = Abc_NtkMiterSatCreate( pNtk, 0 ); - if ( pSat == NULL ) - return 1; -//printf( "%d \n", pSat->clauses.size ); -//sat_solver_delete( pSat ); -//return 1; - -// printf( "Created SAT problem with %d variable and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); -// PRT( "Time", clock() - clk ); - - // simplify the problem - clk = clock(); - status = sat_solver_simplify(pSat); -// printf( "Simplified the problem to %d variables and %d clauses. ", sat_solver_nvars(pSat), sat_solver_nclauses(pSat) ); -// PRT( "Time", clock() - clk ); - if ( status == 0 ) - { - sat_solver_delete( pSat ); -// printf( "The problem is UNSATISFIABLE after simplification.\n" ); - return 1; - } - - // solve the miter - clk = clock(); - if ( fVerbose ) - pSat->verbosity = 1; - status = sat_solver_solve( pSat, NULL, NULL, (sint64)nConfLimit, (sint64)nInsLimit, (sint64)0, (sint64)0 ); - if ( status == l_Undef ) - { -// printf( "The problem timed out.\n" ); - RetValue = -1; - } - else if ( status == l_True ) - { -// printf( "The problem is SATISFIABLE.\n" ); - RetValue = 0; - } - else if ( status == l_False ) - { -// printf( "The problem is UNSATISFIABLE.\n" ); - RetValue = 1; - } - else - assert( 0 ); -// PRT( "SAT sat_solver time", clock() - clk ); -// printf( "The number of conflicts = %d.\n", (int)pSat->sat_solver_stats.conflicts ); - - // if the problem is SAT, get the counterexample - if ( status == l_True ) - { -// Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk ); - Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); - pNtk->pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); - Vec_IntFree( vCiIds ); - } - // free the sat_solver - if ( fVerbose ) - Sat_SolverPrintStats( stdout, pSat ); - - if ( pNumConfs ) - *pNumConfs = (int)pSat->stats.conflicts; - if ( pNumInspects ) - *pNumInspects = (int)pSat->stats.inspects; - -sat_solver_store_write( pSat, "trace.cnf" ); -sat_solver_store_free( pSat ); - - sat_solver_delete( pSat ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Returns the array of CI IDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ) -{ - Vec_Int_t * vCiIds; - Abc_Obj_t * pObj; - int i; - vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) ); - Abc_NtkForEachCi( pNtk, pObj, i ) - Vec_IntPush( vCiIds, (int)pObj->pCopy ); - return vCiIds; -} - - - -/**Function************************************************************* - - Synopsis [Adds trivial clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkClauseTriv( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) -{ -//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses ); - vVars->nSize = 0; - Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) ); -// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) ); - return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); -} - -/**Function************************************************************* - - Synopsis [Adds trivial clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkClauseTop( sat_solver * pSat, Vec_Ptr_t * vNodes, Vec_Int_t * vVars ) -{ - Abc_Obj_t * pNode; - int i; -//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->sat_solver_stats.clauses ); - vVars->nSize = 0; - Vec_PtrForEachEntry( vNodes, pNode, i ) - Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) ); -// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) ); - return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); -} - -/**Function************************************************************* - - Synopsis [Adds trivial clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkClauseAnd( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, Vec_Int_t * vVars ) -{ - int fComp1, Var, Var1, i; -//printf( "Adding AND %d. (%d) %d\n", pNode->Id, vSuper->nSize+1, (int)pSat->sat_solver_stats.clauses ); - - assert( !Abc_ObjIsComplement( pNode ) ); - assert( Abc_ObjIsNode( pNode ) ); - -// nVars = sat_solver_nvars(pSat); - Var = (int)pNode->pCopy; -// Var = pNode->Id; - -// assert( Var < nVars ); - for ( i = 0; i < vSuper->nSize; i++ ) - { - // get the predecessor nodes - // get the complemented attributes of the nodes - fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]); - // determine the variable numbers - Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy; -// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id; - - // check that the variables are in the SAT manager -// assert( Var1 < nVars ); - - // suppose the AND-gate is A * B = C - // add !A => !C or A + !C - // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 ); - vVars->nSize = 0; - Vec_IntPush( vVars, toLitCond(Var1, fComp1) ); - Vec_IntPush( vVars, toLitCond(Var, 1 ) ); - if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - return 0; - } - - // add A & B => C or !A + !B + C -// fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 ); - vVars->nSize = 0; - for ( i = 0; i < vSuper->nSize; i++ ) - { - // get the predecessor nodes - // get the complemented attributes of the nodes - fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]); - // determine the variable numbers - Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy; -// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id; - // add this variable to the array - Vec_IntPush( vVars, toLitCond(Var1, !fComp1) ); - } - Vec_IntPush( vVars, toLitCond(Var, 0) ); - return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); -} - -/**Function************************************************************* - - Synopsis [Adds trivial clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkClauseMux( sat_solver * pSat, Abc_Obj_t * pNode, Abc_Obj_t * pNodeC, Abc_Obj_t * pNodeT, Abc_Obj_t * pNodeE, Vec_Int_t * vVars ) -{ - int VarF, VarI, VarT, VarE, fCompT, fCompE; -//printf( "Adding mux %d. %d\n", pNode->Id, (int)pSat->sat_solver_stats.clauses ); - - assert( !Abc_ObjIsComplement( pNode ) ); - assert( Abc_NodeIsMuxType( pNode ) ); - // get the variable numbers - VarF = (int)pNode->pCopy; - VarI = (int)pNodeC->pCopy; - VarT = (int)Abc_ObjRegular(pNodeT)->pCopy; - VarE = (int)Abc_ObjRegular(pNodeE)->pCopy; -// VarF = (int)pNode->Id; -// VarI = (int)pNodeC->Id; -// VarT = (int)Abc_ObjRegular(pNodeT)->Id; -// VarE = (int)Abc_ObjRegular(pNodeE)->Id; - - // get the complementation flags - fCompT = Abc_ObjIsComplement(pNodeT); - fCompE = Abc_ObjIsComplement(pNodeE); - - // f = ITE(i, t, e) - // i' + t' + f - // i' + t + f' - // i + e' + f - // i + e + f' - // create four clauses - vVars->nSize = 0; - Vec_IntPush( vVars, toLitCond(VarI, 1) ); - Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) ); - Vec_IntPush( vVars, toLitCond(VarF, 0) ); - if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - return 0; - vVars->nSize = 0; - Vec_IntPush( vVars, toLitCond(VarI, 1) ); - Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) ); - Vec_IntPush( vVars, toLitCond(VarF, 1) ); - if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - return 0; - vVars->nSize = 0; - Vec_IntPush( vVars, toLitCond(VarI, 0) ); - Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) ); - Vec_IntPush( vVars, toLitCond(VarF, 0) ); - if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - return 0; - vVars->nSize = 0; - Vec_IntPush( vVars, toLitCond(VarI, 0) ); - Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) ); - Vec_IntPush( vVars, toLitCond(VarF, 1) ); - if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - return 0; - - if ( VarT == VarE ) - { -// assert( fCompT == !fCompE ); - return 1; - } - - // two additional clauses - // t' & e' -> f' t + e + f' - // t & e -> f t' + e' + f - vVars->nSize = 0; - Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) ); - Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) ); - Vec_IntPush( vVars, toLitCond(VarF, 1) ); - if ( !sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) ) - return 0; - vVars->nSize = 0; - Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) ); - Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) ); - Vec_IntPush( vVars, toLitCond(VarF, 0) ); - return sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCollectSupergate_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fStopAtMux ) -{ - int RetValue1, RetValue2, i; - // check if the node is visited - if ( Abc_ObjRegular(pNode)->fMarkB ) - { - // check if the node occurs in the same polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == pNode ) - return 1; - // check if the node is present in the opposite polarity - for ( i = 0; i < vSuper->nSize; i++ ) - if ( vSuper->pArray[i] == Abc_ObjNot(pNode) ) - return -1; - assert( 0 ); - return 0; - } - // if the new node is complemented or a PI, another gate begins - if ( !fFirst ) - if ( Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || Abc_ObjFanoutNum(pNode) > 1 || fStopAtMux && Abc_NodeIsMuxType(pNode) ) - { - Vec_PtrPush( vSuper, pNode ); - Abc_ObjRegular(pNode)->fMarkB = 1; - return 0; - } - assert( !Abc_ObjIsComplement(pNode) ); - assert( Abc_ObjIsNode(pNode) ); - // go through the branches - RetValue1 = Abc_NtkCollectSupergate_rec( Abc_ObjChild0(pNode), vSuper, 0, fStopAtMux ); - RetValue2 = Abc_NtkCollectSupergate_rec( Abc_ObjChild1(pNode), vSuper, 0, fStopAtMux ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - // return 1 if at least one branch has a duplicate - return RetValue1 || RetValue2; -} - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNodes ) -{ - int RetValue, i; - assert( !Abc_ObjIsComplement(pNode) ); - // collect the nodes in the implication supergate - Vec_PtrClear( vNodes ); - RetValue = Abc_NtkCollectSupergate_rec( pNode, vNodes, 1, fStopAtMux ); - assert( vNodes->nSize > 1 ); - // unmark the visited nodes - for ( i = 0; i < vNodes->nSize; i++ ) - Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0; - // if we found the node and its complement in the same implication supergate, - // return empty set of nodes (meaning that we should use constant-0 node) - if ( RetValue == -1 ) - vNodes->nSize = 0; -} - - -/**Function************************************************************* - - Synopsis [Computes the factor of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkNodeFactor( Abc_Obj_t * pObj, int nLevelMax ) -{ -// nLevelMax = ((nLevelMax)/2)*3; - assert( (int)pObj->Level <= nLevelMax ); -// return (int)(100000000.0 * pow(0.999, nLevelMax - pObj->Level)); - return (int)(100000000.0 * (1 + 0.01 * pObj->Level)); -// return (int)(100000000.0 / ((nLevelMax)/2)*3 - pObj->Level); -} - -/**Function************************************************************* - - Synopsis [Sets up the SAT sat_solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMiterSatCreateInt( sat_solver * pSat, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE; - Vec_Ptr_t * vNodes, * vSuper; - Vec_Int_t * vVars; - int i, k, fUseMuxes = 1; - int clk1 = clock(); -// int fOrderCiVarsFirst = 0; - int nLevelsMax = Abc_AigLevel(pNtk); - int RetValue = 0; - - assert( Abc_NtkIsStrash(pNtk) ); - - // clean the CI node pointers - Abc_NtkForEachCi( pNtk, pNode, i ) - pNode->pCopy = NULL; - - // start the data structures - vNodes = Vec_PtrAlloc( 1000 ); // the nodes corresponding to vars in the sat_solver - vSuper = Vec_PtrAlloc( 100 ); // the nodes belonging to the given implication supergate - vVars = Vec_IntAlloc( 100 ); // the temporary array for variables in the clause - - // add the clause for the constant node - pNode = Abc_AigConst1(pNtk); - pNode->fMarkA = 1; - pNode->pCopy = (Abc_Obj_t *)vNodes->nSize; - Vec_PtrPush( vNodes, pNode ); - Abc_NtkClauseTriv( pSat, pNode, vVars ); -/* - // add the PI variables first - Abc_NtkForEachCi( pNtk, pNode, i ) - { - pNode->fMarkA = 1; - pNode->pCopy = (Abc_Obj_t *)vNodes->nSize; - Vec_PtrPush( vNodes, pNode ); - } -*/ - // collect the nodes that need clauses and top-level assignments - Vec_PtrClear( vSuper ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - // get the fanin - pFanin = Abc_ObjFanin0(pNode); - // create the node's variable - if ( pFanin->fMarkA == 0 ) - { - pFanin->fMarkA = 1; - pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize; - Vec_PtrPush( vNodes, pFanin ); - } - // add the trivial clause - Vec_PtrPush( vSuper, Abc_ObjChild0(pNode) ); - } - if ( !Abc_NtkClauseTop( pSat, vSuper, vVars ) ) - goto Quits; - - - // add the clauses - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - assert( !Abc_ObjIsComplement(pNode) ); - if ( !Abc_AigNodeIsAnd(pNode) ) - continue; -//printf( "%d ", pNode->Id ); - - // add the clauses - if ( fUseMuxes && Abc_NodeIsMuxType(pNode) ) - { - nMuxes++; - - pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); - Vec_PtrClear( vSuper ); - Vec_PtrPush( vSuper, pNodeC ); - Vec_PtrPush( vSuper, pNodeT ); - Vec_PtrPush( vSuper, pNodeE ); - // add the fanin nodes to explore - Vec_PtrForEachEntry( vSuper, pFanin, k ) - { - pFanin = Abc_ObjRegular(pFanin); - if ( pFanin->fMarkA == 0 ) - { - pFanin->fMarkA = 1; - pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize; - Vec_PtrPush( vNodes, pFanin ); - } - } - // add the clauses - if ( !Abc_NtkClauseMux( pSat, pNode, pNodeC, pNodeT, pNodeE, vVars ) ) - goto Quits; - } - else - { - // get the supergate - Abc_NtkCollectSupergate( pNode, fUseMuxes, vSuper ); - // add the fanin nodes to explore - Vec_PtrForEachEntry( vSuper, pFanin, k ) - { - pFanin = Abc_ObjRegular(pFanin); - if ( pFanin->fMarkA == 0 ) - { - pFanin->fMarkA = 1; - pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize; - Vec_PtrPush( vNodes, pFanin ); - } - } - // add the clauses - if ( vSuper->nSize == 0 ) - { - if ( !Abc_NtkClauseTriv( pSat, Abc_ObjNot(pNode), vVars ) ) -// if ( !Abc_NtkClauseTriv( pSat, pNode, vVars ) ) - goto Quits; - } - else - { - if ( !Abc_NtkClauseAnd( pSat, pNode, vSuper, vVars ) ) - goto Quits; - } - } - } -/* - // set preferred variables - if ( fOrderCiVarsFirst ) - { - int * pPrefVars = ALLOC( int, Abc_NtkCiNum(pNtk) ); - int nVars = 0; - Abc_NtkForEachCi( pNtk, pNode, i ) - { - if ( pNode->fMarkA == 0 ) - continue; - pPrefVars[nVars++] = (int)pNode->pCopy; - } - nVars = ABC_MIN( nVars, 10 ); - ASat_SolverSetPrefVars( pSat, pPrefVars, nVars ); - } -*/ - RetValue = 1; -Quits : - // delete - Vec_IntFree( vVars ); - Vec_PtrFree( vNodes ); - Vec_PtrFree( vSuper ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Sets up the SAT sat_solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes ) -{ - sat_solver * pSat; - Abc_Obj_t * pNode; - int RetValue, i, clk = clock(); - - assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsBddLogic(pNtk) ); - if ( Abc_NtkIsBddLogic(pNtk) ) - return Abc_NtkMiterSatCreateLogic(pNtk, fAllPrimes); - - nMuxes = 0; - pSat = sat_solver_new(); -//sat_solver_store_alloc( pSat ); - RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk ); -sat_solver_store_mark_roots( pSat ); - - Abc_NtkForEachObj( pNtk, pNode, i ) - pNode->fMarkA = 0; -// ASat_SolverWriteDimacs( pSat, "temp_sat.cnf", NULL, NULL, 1 ); - if ( RetValue == 0 ) - { - sat_solver_delete(pSat); - return NULL; - } -// printf( "Ands = %6d. Muxes = %6d (%5.2f %%). ", Abc_NtkNodeNum(pNtk), nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) ); -// PRT( "Creating sat_solver", clock() - clk ); - return pSat; -} - - - - -/**Function************************************************************* - - Synopsis [Adds clauses for the internal node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeAddClauses( sat_solver * pSat, char * pSop0, char * pSop1, Abc_Obj_t * pNode, Vec_Int_t * vVars ) -{ - Abc_Obj_t * pFanin; - int i, c, nFanins; - int RetValue; - char * pCube; - - nFanins = Abc_ObjFaninNum( pNode ); - assert( nFanins == Abc_SopGetVarNum( pSop0 ) ); - -// if ( nFanins == 0 ) - if ( Cudd_Regular(pNode->pData) == Cudd_ReadOne(pNode->pNtk->pManFunc) ) - { - vVars->nSize = 0; -// if ( Abc_SopIsConst1(pSop1) ) - if ( !Cudd_IsComplement(pNode->pData) ) - Vec_IntPush( vVars, toLit(pNode->Id) ); - else - Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); - RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); - if ( !RetValue ) - { - printf( "The CNF is trivially UNSAT.\n" ); - return 0; - } - return 1; - } - - // add clauses for the negative phase - for ( c = 0; ; c++ ) - { - // get the cube - pCube = pSop0 + c * (nFanins + 3); - if ( *pCube == 0 ) - break; - // add the clause - vVars->nSize = 0; - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - if ( pCube[i] == '0' ) - Vec_IntPush( vVars, toLit(pFanin->Id) ); - else if ( pCube[i] == '1' ) - Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); - } - Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); - RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); - if ( !RetValue ) - { - printf( "The CNF is trivially UNSAT.\n" ); - return 0; - } - } - - // add clauses for the positive phase - for ( c = 0; ; c++ ) - { - // get the cube - pCube = pSop1 + c * (nFanins + 3); - if ( *pCube == 0 ) - break; - // add the clause - vVars->nSize = 0; - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - if ( pCube[i] == '0' ) - Vec_IntPush( vVars, toLit(pFanin->Id) ); - else if ( pCube[i] == '1' ) - Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); - } - Vec_IntPush( vVars, toLit(pNode->Id) ); - RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); - if ( !RetValue ) - { - printf( "The CNF is trivially UNSAT.\n" ); - return 0; - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Adds clauses for the PO node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeAddClausesTop( sat_solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars ) -{ - Abc_Obj_t * pFanin; - int RetValue; - - pFanin = Abc_ObjFanin0(pNode); - if ( Abc_ObjFaninC0(pNode) ) - { - vVars->nSize = 0; - Vec_IntPush( vVars, toLit(pFanin->Id) ); - Vec_IntPush( vVars, toLit(pNode->Id) ); - RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); - if ( !RetValue ) - { - printf( "The CNF is trivially UNSAT.\n" ); - return 0; - } - - vVars->nSize = 0; - Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); - Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); - RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); - if ( !RetValue ) - { - printf( "The CNF is trivially UNSAT.\n" ); - return 0; - } - } - else - { - vVars->nSize = 0; - Vec_IntPush( vVars, lit_neg(toLit(pFanin->Id)) ); - Vec_IntPush( vVars, toLit(pNode->Id) ); - RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); - if ( !RetValue ) - { - printf( "The CNF is trivially UNSAT.\n" ); - return 0; - } - - vVars->nSize = 0; - Vec_IntPush( vVars, toLit(pFanin->Id) ); - Vec_IntPush( vVars, lit_neg(toLit(pNode->Id)) ); - RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); - if ( !RetValue ) - { - printf( "The CNF is trivially UNSAT.\n" ); - return 0; - } - } - - vVars->nSize = 0; - Vec_IntPush( vVars, toLit(pNode->Id) ); - RetValue = sat_solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ); - if ( !RetValue ) - { - printf( "The CNF is trivially UNSAT.\n" ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Sets up the SAT sat_solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -sat_solver * Abc_NtkMiterSatCreateLogic( Abc_Ntk_t * pNtk, int fAllPrimes ) -{ - sat_solver * pSat; - Extra_MmFlex_t * pMmFlex; - Abc_Obj_t * pNode; - Vec_Str_t * vCube; - Vec_Int_t * vVars; - char * pSop0, * pSop1; - int i; - - assert( Abc_NtkIsBddLogic(pNtk) ); - - // transfer the IDs to the copy field - Abc_NtkForEachPi( pNtk, pNode, i ) - pNode->pCopy = (void *)pNode->Id; - - // start the data structures - pSat = sat_solver_new(); -sat_solver_store_alloc( pSat ); - pMmFlex = Extra_MmFlexStart(); - vCube = Vec_StrAlloc( 100 ); - vVars = Vec_IntAlloc( 100 ); - - // add clauses for each internal nodes - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // derive SOPs for both phases of the node - Abc_NodeBddToCnf( pNode, pMmFlex, vCube, fAllPrimes, &pSop0, &pSop1 ); - // add the clauses to the sat_solver - if ( !Abc_NodeAddClauses( pSat, pSop0, pSop1, pNode, vVars ) ) - { - sat_solver_delete( pSat ); - pSat = NULL; - goto finish; - } - } - // add clauses for each PO - Abc_NtkForEachPo( pNtk, pNode, i ) - { - if ( !Abc_NodeAddClausesTop( pSat, pNode, vVars ) ) - { - sat_solver_delete( pSat ); - pSat = NULL; - goto finish; - } - } -sat_solver_store_mark_roots( pSat ); - -finish: - // delete - Vec_StrFree( vCube ); - Vec_IntFree( vVars ); - Extra_MmFlexStop( pMmFlex ); - return pSat; -} - - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcStrash.c b/src/base/abci/abcStrash.c deleted file mode 100644 index c77f8dea..00000000 --- a/src/base/abci/abcStrash.c +++ /dev/null @@ -1,478 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcStrash.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Strashing of the current network.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "extra.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reapplies structural hashing to the AIG.] - - Description [Because of the structural hashing, this procedure should not - change the number of nodes. It is useful to detect the bugs in the original AIG.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, bool fCleanup ) -{ - extern int timeRetime; - Abc_Ntk_t * pNtkAig; - Abc_Obj_t * pObj; - int i, nNodes;//, RetValue; - assert( Abc_NtkIsStrash(pNtk) ); -//timeRetime = clock(); - // print warning about choice nodes - if ( Abc_NtkGetChoiceNum( pNtk ) ) - printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" ); - // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) - pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // restrash the nodes (assuming a topological order of the old network) - Abc_NtkForEachNode( pNtk, pObj, i ) - pObj->pCopy = Abc_AigAnd( pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - // finalize the network - Abc_NtkFinalize( pNtk, pNtkAig ); - // print warning about self-feed latches -// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) -// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); - // perform cleanup if requested - if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) - printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes ); - // duplicate EXDC - if ( pNtk->pExdc ) - pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); - // make sure everything is okay - if ( !Abc_NtkCheck( pNtkAig ) ) - { - printf( "Abc_NtkStrash: The network check has failed.\n" ); - Abc_NtkDelete( pNtkAig ); - return NULL; - } -//timeRetime = clock() - timeRetime; -// if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) ) -// printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue ); - return pNtkAig; - -} - -/**Function************************************************************* - - Synopsis [Reapplies structural hashing to the AIG.] - - Description [Because of the structural hashing, this procedure should not - change the number of nodes. It is useful to detect the bugs in the original AIG.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, bool fCleanup ) -{ - extern int timeRetime; - Abc_Ntk_t * pNtkAig; - Abc_Obj_t * pObj; - int i, nNodes;//, RetValue; - assert( Abc_NtkIsStrash(pNtk) ); -//timeRetime = clock(); - // print warning about choice nodes - if ( Abc_NtkGetChoiceNum( pNtk ) ) - printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" ); - // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) - pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - // complement the 1-values registers - Abc_NtkForEachLatch( pNtk, pObj, i ) - if ( Abc_LatchIsInit1(pObj) ) - Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy); - // restrash the nodes (assuming a topological order of the old network) - Abc_NtkForEachNode( pNtk, pObj, i ) - pObj->pCopy = Abc_AigAnd( pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - // finalize the network - Abc_NtkFinalize( pNtk, pNtkAig ); - // complement the 1-valued registers - Abc_NtkForEachLatch( pNtkAig, pObj, i ) - if ( Abc_LatchIsInit1(pObj) ) - Abc_ObjXorFaninC( Abc_ObjFanin0(pObj), 0 ); - // set all constant-0 values - Abc_NtkForEachLatch( pNtkAig, pObj, i ) - Abc_LatchSetInit0( pObj ); - - // print warning about self-feed latches -// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) -// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); - // perform cleanup if requested - if ( fCleanup && (nNodes = Abc_AigCleanup(pNtkAig->pManFunc)) ) - printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes ); - // duplicate EXDC - if ( pNtk->pExdc ) - pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); - // make sure everything is okay - if ( !Abc_NtkCheck( pNtkAig ) ) - { - printf( "Abc_NtkStrash: The network check has failed.\n" ); - Abc_NtkDelete( pNtkAig ); - return NULL; - } -//timeRetime = clock() - timeRetime; -// if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) ) -// printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue ); - return pNtkAig; - -} - -/**Function************************************************************* - - Synopsis [Transforms logic network into structurally hashed AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord ) -{ - Abc_Ntk_t * pNtkAig; - int nNodes; - assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); - // consider the special case when the network is already structurally hashed - if ( Abc_NtkIsStrash(pNtk) ) - return Abc_NtkRestrash( pNtk, fCleanup ); - // convert the node representation in the logic network to the AIG form - if ( !Abc_NtkToAig(pNtk) ) - { - printf( "Converting to AIGs has failed.\n" ); - return NULL; - } - // perform strashing -// Abc_NtkCleanCopy( pNtk ); - pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); - Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes, fRecord ); - Abc_NtkFinalize( pNtk, pNtkAig ); - // print warning about self-feed latches -// if ( Abc_NtkCountSelfFeedLatches(pNtkAig) ) -// printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) ); - // perform cleanup if requested - nNodes = fCleanup? Abc_AigCleanup(pNtkAig->pManFunc) : 0; -// if ( nNodes ) -// printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes ); - // duplicate EXDC - if ( pNtk->pExdc ) - pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc ); - // make sure everything is okay - if ( !Abc_NtkCheck( pNtkAig ) ) - { - printf( "Abc_NtkStrash: The network check has failed.\n" ); - Abc_NtkDelete( pNtkAig ); - return NULL; - } - return pNtkAig; -} - -/**Function************************************************************* - - Synopsis [Appends the second network to the first.] - - Description [Modifies the first network by adding the logic of the second. - Performs structural hashing while appending the networks. Does not change - the second network. Returns 0 if the appending failed, 1 otherise.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ) -{ - Abc_Obj_t * pObj; - char * pName; - int i, nNewCis; - // the first network should be an AIG - assert( Abc_NtkIsStrash(pNtk1) ); - assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsStrash(pNtk2) ); - if ( Abc_NtkIsLogic(pNtk2) && !Abc_NtkToAig(pNtk2) ) - { - printf( "Converting to AIGs has failed.\n" ); - return 0; - } - // check that the networks have the same PIs - // reorder PIs of pNtk2 according to pNtk1 - if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1, 1 ) ) - printf( "Abc_NtkAppend(): The union of the network PIs is computed (warning).\n" ); - // perform strashing - nNewCis = 0; - Abc_NtkCleanCopy( pNtk2 ); - if ( Abc_NtkIsStrash(pNtk2) ) - Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtk1); - Abc_NtkForEachCi( pNtk2, pObj, i ) - { - pName = Abc_ObjName(pObj); - pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj)); - if ( pObj->pCopy == NULL ) - { - pObj->pCopy = Abc_NtkDupObj(pNtk1, pObj, 1); - nNewCis++; - } - } - if ( nNewCis ) - printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis ); - // add pNtk2 to pNtk1 while strashing - if ( Abc_NtkIsLogic(pNtk2) ) - Abc_NtkStrashPerform( pNtk2, pNtk1, 1, 0 ); - else - Abc_NtkForEachNode( pNtk2, pObj, i ) - pObj->pCopy = Abc_AigAnd( pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); - // add the COs of the second network - if ( fAddPos ) - { - Abc_NtkForEachPo( pNtk2, pObj, i ) - { - Abc_NtkDupObj( pNtk1, pObj, 0 ); - Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj->pCopy), NULL ); - } - } - else - { - Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew; - int fCompl, iNodeId; - // OR the choices - Abc_NtkForEachCo( pNtk2, pObj, i ) - { - iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI ); - assert( iNodeId >= 0 ); - pObjOld = Abc_NtkObj( pNtk1, iNodeId ); - // derive the new driver - pDriverOld = Abc_ObjChild0( pObjOld ); - pDriverNew = Abc_ObjChild0Copy( pObj ); - pDriverNew = Abc_AigOr( pNtk1->pManFunc, pDriverOld, pDriverNew ); - if ( Abc_ObjRegular(pDriverOld) == Abc_ObjRegular(pDriverNew) ) - continue; - // replace the old driver by the new driver - fCompl = Abc_ObjRegular(pDriverOld)->fPhase ^ Abc_ObjRegular(pDriverNew)->fPhase; - Abc_ObjPatchFanin( pObjOld, Abc_ObjRegular(pDriverOld), Abc_ObjNotCond(Abc_ObjRegular(pDriverNew), fCompl) ); - } - } - // make sure that everything is okay - if ( !Abc_NtkCheck( pNtk1 ) ) - { - printf( "Abc_NtkAppend: The network check has failed.\n" ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Prepares the network for strashing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord ) -{ - ProgressBar * pProgress; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNodeOld; - int i, clk = clock(); - assert( Abc_NtkIsLogic(pNtkOld) ); - assert( Abc_NtkIsStrash(pNtkNew) ); -// vNodes = Abc_NtkDfs( pNtkOld, fAllNodes ); - vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes ); -//printf( "Nodes = %d. ", Vec_PtrSize(vNodes) ); -//PRT( "Time", clock() - clk ); - pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize ); - Vec_PtrForEachEntry( vNodes, pNodeOld, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord ); - } - Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Transfers the AIG from one manager into another.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj ) -{ - assert( !Hop_IsComplement(pObj) ); - if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) - return; - Abc_NodeStrash_rec( pMan, Hop_ObjFanin0(pObj) ); - Abc_NodeStrash_rec( pMan, Hop_ObjFanin1(pObj) ); - pObj->pData = Abc_AigAnd( pMan, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); - assert( !Hop_ObjIsMarkA(pObj) ); // loop detection - Hop_ObjSetMarkA( pObj ); -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node.] - - Description [Assume the network is in the AIG form] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, int fRecord ) -{ - Hop_Man_t * pMan; - Hop_Obj_t * pRoot; - Abc_Obj_t * pFanin; - int i; - assert( Abc_ObjIsNode(pNodeOld) ); - assert( Abc_NtkHasAig(pNodeOld->pNtk) && !Abc_NtkIsStrash(pNodeOld->pNtk) ); - // get the local AIG manager and the local root node - pMan = pNodeOld->pNtk->pManFunc; - pRoot = pNodeOld->pData; - // check the constant case - if ( Abc_NodeIsConst(pNodeOld) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) ) - return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Hop_IsComplement(pRoot) ); - // perform special case-strashing using the record of AIG subgraphs - if ( fRecord && Abc_NtkRecIsRunning() && Abc_ObjFaninNum(pNodeOld) > 2 && Abc_ObjFaninNum(pNodeOld) <= Abc_NtkRecVarNum() ) - { - extern Vec_Int_t * Abc_NtkRecMemory(); - extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars ); - int nVars = Abc_NtkRecVarNum(); - Vec_Int_t * vMemory = Abc_NtkRecMemory(); - unsigned * pTruth = Abc_ConvertAigToTruth( pMan, Hop_Regular(pRoot), nVars, vMemory, 0 ); - assert( Extra_TruthSupportSize(pTruth, nVars) == Abc_ObjFaninNum(pNodeOld) ); // should be swept - if ( Hop_IsComplement(pRoot) ) - Extra_TruthNot( pTruth, pTruth, nVars ); - if ( Abc_NtkRecStrashNode( pNtkNew, pNodeOld, pTruth, nVars ) ) - return pNodeOld->pCopy; - } - // set elementary variables - Abc_ObjForEachFanin( pNodeOld, pFanin, i ) - Hop_IthVar(pMan, i)->pData = pFanin->pCopy; - // strash the AIG of this node - Abc_NodeStrash_rec( pNtkNew->pManFunc, Hop_Regular(pRoot) ); - Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); - // return the final node - return Abc_ObjNotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); -} - - - - - - - -/**Function************************************************************* - - Synopsis [Copies the topmost levels of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut ) -{ - assert( !Abc_ObjIsComplement(pNode) ); - if ( pNode->pCopy ) - return pNode->pCopy; - if ( pNode->Level <= (unsigned)LevelCut ) - return pNode->pCopy = Abc_NtkCreatePi( pNtkNew ); - Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(pNode), LevelCut ); - Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin1(pNode), LevelCut ); - return pNode->pCopy = Abc_AigAnd( pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); -} - -/**Function************************************************************* - - Synopsis [Copies the topmost levels of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObjNew, * pPoNew; - int LevelCut; - assert( Abc_NtkIsStrash(pNtk) ); - assert( Abc_NtkCoNum(pNtk) == 1 ); - // get the cutoff level - LevelCut = ABC_MAX( 0, Abc_AigLevel(pNtk) - nLevels ); - // start the network - pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); - // create PIs below the cut and nodes above the cut - Abc_NtkCleanCopy( pNtk ); - pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(Abc_NtkPo(pNtk, 0)), LevelCut ); - pObjNew = Abc_ObjNotCond( pObjNew, Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) ); - // add the PO node and name - pPoNew = Abc_NtkCreatePo(pNtkNew); - Abc_ObjAddFanin( pPoNew, pObjNew ); - Abc_NtkAddDummyPiNames( pNtkNew ); - Abc_ObjAssignName( pPoNew, Abc_ObjName(Abc_NtkPo(pNtk, 0)), NULL ); - // make sure everything is okay - if ( !Abc_NtkCheck( pNtkNew ) ) - { - printf( "Abc_NtkTopmost: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcSweep.c b/src/base/abci/abcSweep.c deleted file mode 100644 index 1ae8745b..00000000 --- a/src/base/abci/abcSweep.c +++ /dev/null @@ -1,948 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcDsd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Technology dependent sweep.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "fraig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ); -static stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose ); -static void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, bool fVerbose ); -static void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ); -static void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ); -static int Abc_NodeDroppingCost( Abc_Obj_t * pNode ); - -static int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ); -static void Abc_NodeSweep( Abc_Obj_t * pNode, int fVerbose ); -static void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0 ); -static void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Sweping functionally equivalence nodes.] - - Description [Removes gates with equivalent functionality. Works for - both technology-independent and mapped networks. If the flag is set, - allows adding inverters at the gate outputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ) -{ - Fraig_Params_t Params; - Abc_Ntk_t * pNtkAig; - Fraig_Man_t * pMan; - stmm_table * tEquiv; - Abc_Obj_t * pObj; - int i, fUseTrick; - - assert( !Abc_NtkIsStrash(pNtk) ); - - // save gate assignments - fUseTrick = 0; - if ( Abc_NtkIsMappedLogic(pNtk) ) - { - fUseTrick = 1; - Abc_NtkForEachNode( pNtk, pObj, i ) - pObj->pNext = pObj->pData; - } - // derive the AIG - pNtkAig = Abc_NtkStrash( pNtk, 0, 1, 0 ); - // reconstruct gate assignments - if ( fUseTrick ) - { - extern void * Abc_FrameReadLibGen(); - Hop_ManStop( pNtk->pManFunc ); - pNtk->pManFunc = Abc_FrameReadLibGen(); - pNtk->ntkFunc = ABC_FUNC_MAP; - Abc_NtkForEachNode( pNtk, pObj, i ) - pObj->pData = pObj->pNext, pObj->pNext = NULL; - } - - // perform fraiging of the AIG - Fraig_ParamsSetDefault( &Params ); - pMan = Abc_NtkToFraig( pNtkAig, &Params, 0, 0 ); - // cannot use EXDC with FRAIG because it can create classes of equivalent FRAIG nodes - // with representative nodes that do not correspond to the nodes with the current network - - // update FRAIG using EXDC - if ( fExdc ) - { - if ( pNtk->pExdc == NULL ) - printf( "Warning: Networks has no EXDC.\n" ); - else - Abc_NtkFraigSweepUsingExdc( pMan, pNtk ); - } - // assign levels to the nodes of the network - Abc_NtkLevel( pNtk ); - - // collect the classes of equivalent nets - tEquiv = Abc_NtkFraigEquiv( pNtk, fUseInv, fVerbose, fVeryVerbose ); - - // transform the network into the equivalent one - Abc_NtkFraigTransform( pNtk, tEquiv, fUseInv, fVerbose ); - stmm_free_table( tEquiv ); - - // free the manager - Fraig_ManFree( pMan ); - Abc_NtkDelete( pNtkAig ); - - // cleanup the dangling nodes - if ( Abc_NtkHasMapping(pNtk) ) - Abc_NtkCleanup( pNtk, fVerbose ); - else - Abc_NtkSweep( pNtk, fVerbose ); - - // check - if ( !Abc_NtkCheck( pNtk ) ) - { - printf( "Abc_NtkFraigSweep: The network check has failed.\n" ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Sweep the network using EXDC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFraigSweepUsingExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk ) -{ - Fraig_Node_t * gNodeExdc, * gNode, * gNodeRes; - Abc_Obj_t * pNode, * pNodeAig; - int i; - extern Fraig_Node_t * Abc_NtkToFraigExdc( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkExdc ); - - assert( pNtk->pExdc ); - // derive FRAIG node representing don't-cares in the EXDC network - gNodeExdc = Abc_NtkToFraigExdc( pMan, pNtk, pNtk->pExdc ); - // update the node pointers - Abc_NtkForEachNode( pNtk, pNode, i ) - { - // skip the constant input nodes - if ( Abc_ObjFaninNum(pNode) == 0 ) - continue; - // get the strashed node - pNodeAig = pNode->pCopy; - // skip the dangling nodes - if ( pNodeAig == NULL ) - continue; - // get the FRAIG node - gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, Abc_ObjIsComplement(pNodeAig) ); - // perform ANDing with EXDC - gNodeRes = Fraig_NodeAnd( pMan, gNode, Fraig_Not(gNodeExdc) ); - // write the node back - Abc_ObjRegular(pNodeAig)->pCopy = (Abc_Obj_t *)Fraig_NotCond( gNodeRes, Abc_ObjIsComplement(pNodeAig) ); - } -} - -/**Function************************************************************* - - Synopsis [Collects equivalence classses of node in the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -stmm_table * Abc_NtkFraigEquiv( Abc_Ntk_t * pNtk, int fUseInv, int fVerbose, int fVeryVerbose ) -{ - Abc_Obj_t * pList, * pNode, * pNodeAig; - Fraig_Node_t * gNode; - Abc_Obj_t ** ppSlot; - stmm_table * tStrash2Net; - stmm_table * tResult; - stmm_generator * gen; - int c, Counter; - - // create mapping of strashed nodes into the corresponding network nodes - tStrash2Net = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); - Abc_NtkForEachNode( pNtk, pNode, c ) - { - // skip the constant input nodes - if ( Abc_ObjFaninNum(pNode) == 0 ) - continue; - // get the strashed node - pNodeAig = pNode->pCopy; - // skip the dangling nodes - if ( pNodeAig == NULL ) - continue; - // skip the nodes that fanout into COs - if ( Abc_NodeFindCoFanout(pNode) ) - continue; - // get the FRAIG node - gNode = Fraig_NotCond( Abc_ObjRegular(pNodeAig)->pCopy, Abc_ObjIsComplement(pNodeAig) ); - if ( !stmm_find_or_add( tStrash2Net, (char *)Fraig_Regular(gNode), (char ***)&ppSlot ) ) - *ppSlot = NULL; - // add the node to the list - pNode->pNext = *ppSlot; - *ppSlot = pNode; - // mark the node if it is complemented - pNode->fPhase = Fraig_IsComplement(gNode); - } - - // print the classes - c = 0; - Counter = 0; - tResult = stmm_init_table(stmm_ptrcmp,stmm_ptrhash); - stmm_foreach_item( tStrash2Net, gen, (char **)&gNode, (char **)&pList ) - { - // skip the trival classes - if ( pList == NULL || pList->pNext == NULL ) - continue; - // add the non-trival class - stmm_insert( tResult, (char *)pList, NULL ); - // count nodes in the non-trival classes - for ( pNode = pList; pNode; pNode = pNode->pNext ) - Counter++; - - if ( fVeryVerbose ) - { - printf( "Class %2d : {", c ); - for ( pNode = pList; pNode; pNode = pNode->pNext ) - { - pNode->pCopy = NULL; - printf( " %s", Abc_ObjName(pNode) ); - printf( "(%c)", pNode->fPhase? '-' : '+' ); - printf( "(%d)", pNode->Level ); - } - printf( " }\n" ); - c++; - } - } - if ( fVerbose || fVeryVerbose ) - { - printf( "Sweeping stats for network \"%s\":\n", pNtk->pName ); - printf( "Internal nodes = %d. Different functions (up to compl) = %d.\n", Abc_NtkNodeNum(pNtk), stmm_count(tStrash2Net) ); - printf( "Non-trivial classes = %d. Nodes in non-trivial classes = %d.\n", stmm_count(tResult), Counter ); - } - stmm_free_table( tStrash2Net ); - return tResult; -} - - -/**Function************************************************************* - - Synopsis [Transforms the network using the equivalence relation on nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFraigTransform( Abc_Ntk_t * pNtk, stmm_table * tEquiv, int fUseInv, bool fVerbose ) -{ - stmm_generator * gen; - Abc_Obj_t * pList; - if ( stmm_count(tEquiv) == 0 ) - return; - // merge nodes in the classes - if ( Abc_NtkHasMapping( pNtk ) ) - { - Abc_NtkDelayTrace( pNtk ); - stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL ) - Abc_NtkFraigMergeClassMapped( pNtk, pList, fUseInv, fVerbose ); - } - else - { - stmm_foreach_item( tEquiv, gen, (char **)&pList, NULL ) - Abc_NtkFraigMergeClass( pNtk, pList, fUseInv, fVerbose ); - } -} - - -/**Function************************************************************* - - Synopsis [Transforms the list of one-phase equivalent nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFraigMergeClassMapped( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ) -{ - Abc_Obj_t * pListDir, * pListInv; - Abc_Obj_t * pNodeMin, * pNode, * pNext; - float Arrival1, Arrival2; - - assert( pChain ); - assert( pChain->pNext ); - - // divide the nodes into two parts: - // those that need the invertor and those that don't need - pListDir = pListInv = NULL; - for ( pNode = pChain, pNext = pChain->pNext; - pNode; - pNode = pNext, pNext = pNode? pNode->pNext : NULL ) - { - // check to which class the node belongs - if ( pNode->fPhase == 1 ) - { - pNode->pNext = pListDir; - pListDir = pNode; - } - else - { - pNode->pNext = pListInv; - pListInv = pNode; - } - } - - // find the node with the smallest number of logic levels - pNodeMin = pListDir; - for ( pNode = pListDir; pNode; pNode = pNode->pNext ) - { - Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst; - Arrival2 = Abc_NodeReadArrival(pNode )->Worst; -// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 ); -// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 ); - if ( Arrival1 > Arrival2 || - Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level || - Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level && - Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) - pNodeMin = pNode; - } - - // move the fanouts of the direct nodes - for ( pNode = pListDir; pNode; pNode = pNode->pNext ) - if ( pNode != pNodeMin ) - Abc_ObjTransferFanout( pNode, pNodeMin ); - - // find the node with the smallest number of logic levels - pNodeMin = pListInv; - for ( pNode = pListInv; pNode; pNode = pNode->pNext ) - { - Arrival1 = Abc_NodeReadArrival(pNodeMin)->Worst; - Arrival2 = Abc_NodeReadArrival(pNode )->Worst; -// assert( Abc_ObjIsCi(pNodeMin) || Arrival1 > 0 ); -// assert( Abc_ObjIsCi(pNode) || Arrival2 > 0 ); - if ( Arrival1 > Arrival2 || - Arrival1 == Arrival2 && pNodeMin->Level > pNode->Level || - Arrival1 == Arrival2 && pNodeMin->Level == pNode->Level && - Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) - pNodeMin = pNode; - } - - // move the fanouts of the direct nodes - for ( pNode = pListInv; pNode; pNode = pNode->pNext ) - if ( pNode != pNodeMin ) - Abc_ObjTransferFanout( pNode, pNodeMin ); -} - -/**Function************************************************************* - - Synopsis [Process one equivalence class of nodes.] - - Description [This function does not remove the nodes. It only switches - around the connections.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkFraigMergeClass( Abc_Ntk_t * pNtk, Abc_Obj_t * pChain, int fUseInv, int fVerbose ) -{ - Abc_Obj_t * pListDir, * pListInv; - Abc_Obj_t * pNodeMin, * pNodeMinInv; - Abc_Obj_t * pNode, * pNext; - - assert( pChain ); - assert( pChain->pNext ); - - // find the node with the smallest number of logic levels - pNodeMin = pChain; - for ( pNode = pChain->pNext; pNode; pNode = pNode->pNext ) - if ( pNodeMin->Level > pNode->Level || - ( pNodeMin->Level == pNode->Level && - Abc_NodeDroppingCost(pNodeMin) < Abc_NodeDroppingCost(pNode) ) ) - pNodeMin = pNode; - - // divide the nodes into two parts: - // those that need the invertor and those that don't need - pListDir = pListInv = NULL; - for ( pNode = pChain, pNext = pChain->pNext; - pNode; - pNode = pNext, pNext = pNode? pNode->pNext : NULL ) - { - if ( pNode == pNodeMin ) - continue; - // check to which class the node belongs - if ( pNodeMin->fPhase == pNode->fPhase ) - { - pNode->pNext = pListDir; - pListDir = pNode; - } - else - { - pNode->pNext = pListInv; - pListInv = pNode; - } - } - - // move the fanouts of the direct nodes - for ( pNode = pListDir; pNode; pNode = pNode->pNext ) - Abc_ObjTransferFanout( pNode, pNodeMin ); - - // skip if there are no inverted nodes - if ( pListInv == NULL ) - return; - - // add the invertor - pNodeMinInv = Abc_NtkCreateNodeInv( pNtk, pNodeMin ); - - // move the fanouts of the inverted nodes - for ( pNode = pListInv; pNode; pNode = pNode->pNext ) - Abc_ObjTransferFanout( pNode, pNodeMinInv ); -} - - -/**Function************************************************************* - - Synopsis [Returns the number of literals saved if this node becomes useless.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeDroppingCost( Abc_Obj_t * pNode ) -{ - return 1; -} - - - - - -/**Function************************************************************* - - Synopsis [Removes dangling nodes.] - - Description [Returns the number of nodes removed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Vec_Ptr_t * vNodes; - int Counter; - assert( Abc_NtkIsLogic(pNtk) ); - // mark the nodes reachable from the POs - vNodes = Abc_NtkDfs( pNtk, 0 ); - Counter = Abc_NtkReduceNodes( pNtk, vNodes ); - if ( fVerbose ) - printf( "Cleanup removed %d dangling nodes.\n", Counter ); - Vec_PtrFree( vNodes ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Preserves the nodes collected in the array.] - - Description [Returns the number of nodes removed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkReduceNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pNode; - int i, Counter; - assert( Abc_NtkIsLogic(pNtk) ); - // mark the nodes reachable from the POs - Vec_PtrForEachEntry( vNodes, pNode, i ) - pNode->fMarkA = 1; - // remove the non-marked nodes - Counter = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( pNode->fMarkA == 0 ) - { - Abc_NtkDeleteObj( pNode ); - Counter++; - } - // unmark the remaining nodes - Vec_PtrForEachEntry( vNodes, pNode, i ) - pNode->fMarkA = 0; - // check - if ( !Abc_NtkCheck( pNtk ) ) - printf( "Abc_NtkCleanup: The network check has failed.\n" ); - return Counter; -} - - - - -/**Function************************************************************* - - Synopsis [Tranditional sweep of the network.] - - Description [Propagates constant and single-input node, removes dangling nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode, * pFanout, * pDriver; - int i, nNodesOld; - assert( Abc_NtkIsLogic(pNtk) ); - // convert network to BDD representation - if ( !Abc_NtkToBdd(pNtk) ) - { - fprintf( stdout, "Converting to BDD has failed.\n" ); - return 1; - } - // perform cleanup - nNodesOld = Abc_NtkNodeNum(pNtk); - Abc_NtkCleanup( pNtk, 0 ); - // prepare nodes for sweeping - Abc_NtkRemoveDupFanins(pNtk); - Abc_NtkMinimumBase(pNtk); - // collect sweepable nodes - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( Abc_ObjFaninNum(pNode) < 2 ) - Vec_PtrPush( vNodes, pNode ); - // sweep the nodes - while ( Vec_PtrSize(vNodes) > 0 ) - { - // get any sweepable node - pNode = Vec_PtrPop(vNodes); - if ( !Abc_ObjIsNode(pNode) ) - continue; - // get any non-CO fanout of this node - pFanout = Abc_NodeFindNonCoFanout(pNode); - if ( pFanout == NULL ) - continue; - assert( Abc_ObjIsNode(pFanout) ); - // transform the function of the fanout - if ( Abc_ObjFaninNum(pNode) == 0 ) - Abc_NodeConstantInput( pFanout, pNode, Abc_NodeIsConst0(pNode) ); - else - { - assert( Abc_ObjFaninNum(pNode) == 1 ); - pDriver = Abc_ObjFanin0(pNode); - if ( Abc_NodeIsInv(pNode) ) - Abc_NodeComplementInput( pFanout, pNode ); - Abc_ObjPatchFanin( pFanout, pNode, pDriver ); - } - Abc_NodeRemoveDupFanins( pFanout ); - Abc_NodeMinimumBase( pFanout ); - // check if the fanout should be added - if ( Abc_ObjFaninNum(pFanout) < 2 ) - Vec_PtrPush( vNodes, pFanout ); - // check if the node has other fanouts - if ( Abc_ObjFanoutNum(pNode) > 0 ) - Vec_PtrPush( vNodes, pNode ); - else - Abc_NtkDeleteObj_rec( pNode, 1 ); - } - Vec_PtrFree( vNodes ); - // sweep a node into its CO fanout if all of this is true: - // (a) this node is a single-input node - // (b) the driver of the node has only one fanout (this node) - // (c) the driver is a node - Abc_NtkForEachCo( pNtk, pFanout, i ) - { - pNode = Abc_ObjFanin0(pFanout); - if ( Abc_ObjFaninNum(pNode) != 1 ) - continue; - pDriver = Abc_ObjFanin0(pNode); - if ( !(Abc_ObjFanoutNum(pDriver) == 1 && Abc_ObjIsNode(pDriver)) ) - continue; - // trasform this CO - if ( Abc_NodeIsInv(pNode) ) - pDriver->pData = Cudd_Not(pDriver->pData); - Abc_ObjPatchFanin( pFanout, pNode, pDriver ); - } - // perform cleanup - Abc_NtkCleanup( pNtk, 0 ); - // report - if ( fVerbose ) - printf( "Sweep removed %d nodes.\n", nNodesOld - Abc_NtkNodeNum(pNtk) ); - return nNodesOld - Abc_NtkNodeNum(pNtk); -} - - -/**Function************************************************************* - - Synopsis [Replaces the local function by its cofactor.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0 ) -{ - DdManager * dd = pNode->pNtk->pManFunc; - DdNode * bVar, * bTemp; - int iFanin; - assert( Abc_NtkIsBddLogic(pNode->pNtk) ); - if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 ) - { - printf( "Node %s should be among", Abc_ObjName(pFanin) ); - printf( " the fanins of node %s...\n", Abc_ObjName(pNode) ); - return; - } - bVar = Cudd_NotCond( Cudd_bddIthVar(dd, iFanin), fConst0 ); - pNode->pData = Cudd_Cofactor( dd, bTemp = pNode->pData, bVar ); Cudd_Ref( pNode->pData ); - Cudd_RecursiveDeref( dd, bTemp ); -} - -/**Function************************************************************* - - Synopsis [Changes the polarity of one fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) -{ - DdManager * dd = pNode->pNtk->pManFunc; - DdNode * bVar, * bCof0, * bCof1; - int iFanin; - assert( Abc_NtkIsBddLogic(pNode->pNtk) ); - if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 ) - { - printf( "Node %s should be among", Abc_ObjName(pFanin) ); - printf( " the fanins of node %s...\n", Abc_ObjName(pNode) ); - return; - } - bVar = Cudd_bddIthVar( dd, iFanin ); - bCof0 = Cudd_Cofactor( dd, pNode->pData, Cudd_Not(bVar) ); Cudd_Ref( bCof0 ); - bCof1 = Cudd_Cofactor( dd, pNode->pData, bVar ); Cudd_Ref( bCof1 ); - Cudd_RecursiveDeref( dd, pNode->pData ); - pNode->pData = Cudd_bddIte( dd, bVar, bCof0, bCof1 ); Cudd_Ref( pNode->pData ); - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); -} - - - -/**Function************************************************************* - - Synopsis [Removes all objects whose trav ID is not current.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NodeRemoveNonCurrentObjects( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int Counter, i; - int fVerbose = 0; - - // report on the nodes to be deleted - if ( fVerbose ) - { - printf( "These nodes will be deleted: \n" ); - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_NodeIsTravIdCurrent( pObj ) ) - { - printf( " " ); - Abc_ObjPrint( stdout, pObj ); - } - } - - // delete the nodes - Counter = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( !Abc_NodeIsTravIdCurrent( pObj ) ) - { - Abc_NtkDeleteObj( pObj ); - Counter++; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Check if the fanin of this latch is a constant.] - - Description [Returns 0/1 if constant; -1 if not a constant.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkSetTravId_rec( Abc_Obj_t * pObj ) -{ - Abc_NodeSetTravIdCurrent(pObj); - if ( Abc_ObjFaninNum(pObj) == 0 ) - return; - assert( Abc_ObjFaninNum(pObj) == 1 ); - Abc_NtkSetTravId_rec( Abc_ObjFanin0(pObj) ); -} - -/**Function************************************************************* - - Synopsis [Check if the fanin of this latch is a constant.] - - Description [Returns 0/1 if constant; -1 if not a constant.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCheckConstant_rec( Abc_Obj_t * pObj ) -{ - if ( Abc_ObjFaninNum(pObj) == 0 ) - { - if ( !Abc_ObjIsNode(pObj) ) - return -1; - if ( Abc_NodeIsConst0(pObj) ) - return 0; - if ( Abc_NodeIsConst1(pObj) ) - return 1; - assert( 0 ); - return -1; - } - if ( Abc_ObjIsLatch(pObj) || Abc_ObjFaninNum(pObj) > 1 ) - return -1; - if ( !Abc_ObjIsNode(pObj) || Abc_NodeIsBuf(pObj) ) - return Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) ); - if ( Abc_NodeIsInv(pObj) ) - { - int RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pObj) ); - if ( RetValue == 0 ) - return 1; - if ( RetValue == 1 ) - return 0; - return RetValue; - } - assert( 0 ); - return -1; -} - -/**Function************************************************************* - - Synopsis [Removes redundant latches.] - - Description [The redundant latches are of two types: - - Latches fed by a constant which matches the init value of the latch. - - Latches fed by a constant which does not match the init value of the latch - can be all replaced by one latch.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkLatchSweep( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pFanin, * pLatch, * pLatchPivot = NULL; - int Counter, RetValue, i; - Counter = 0; - // go through the latches - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - // check if the latch has constant input - RetValue = Abc_NtkCheckConstant_rec( Abc_ObjFanin0(pLatch) ); - if ( RetValue == -1 ) - continue; - // found a latch with constant fanin - if ( (RetValue == 1 && Abc_LatchIsInit0(pLatch)) || - (RetValue == 0 && Abc_LatchIsInit1(pLatch)) ) - { - // fanin constant differs from the latch init value - if ( pLatchPivot == NULL ) - { - pLatchPivot = pLatch; - continue; - } - if ( Abc_LatchInit(pLatch) != Abc_LatchInit(pLatchPivot) ) // add inverter - pFanin = Abc_NtkCreateNodeInv( pNtk, Abc_ObjFanout0(pLatchPivot) ); - else - pFanin = Abc_ObjFanout0(pLatchPivot); - } - else - pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); - // replace latch - Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pFanin ); - // delete the extra nodes - Abc_NtkDeleteObj_rec( Abc_ObjFanout0(pLatch), 0 ); - Counter++; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Replaces autonumnous logic by free inputs.] - - Description [Assumes that non-autonomous logic is marked with - the current ID.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkReplaceAutonomousLogic( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode, * pFanin; - Vec_Ptr_t * vNodes; - int i, k, Counter; - // collect the nodes that feed into the reachable logic - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachObj( pNtk, pNode, i ) - { - // skip non-visited fanins - if ( !Abc_NodeIsTravIdCurrent(pNode) ) - continue; - // look for non-visited fanins - Abc_ObjForEachFanin( pNode, pFanin, k ) - { - // skip visited fanins - if ( Abc_NodeIsTravIdCurrent(pFanin) ) - continue; - // skip constants and latches fed by constants - if ( Abc_NtkCheckConstant_rec(pFanin) != -1 || - (Abc_ObjIsBo(pFanin) && Abc_NtkCheckConstant_rec(Abc_ObjFanin0(Abc_ObjFanin0(pFanin))) != -1) ) - { - Abc_NtkSetTravId_rec( pFanin ); - continue; - } - assert( !Abc_ObjIsLatch(pFanin) ); - Vec_PtrPush( vNodes, pFanin ); - } - } - Vec_PtrUniqify( vNodes, Abc_ObjPointerCompare ); - // replace these nodes by the PIs - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - pFanin = Abc_NtkCreatePi(pNtk); - Abc_ObjAssignName( pFanin, Abc_ObjName(pFanin), NULL ); - Abc_NodeSetTravIdCurrent( pFanin ); - Abc_ObjTransferFanout( pNode, pFanin ); - } - Counter = Vec_PtrSize(vNodes); - Vec_PtrFree( vNodes ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Sequential cleanup.] - - Description [Performs three tasks: - - Removes logic that does not feed into POs. - - Removes latches driven by constant values equal to the initial state. - - Replaces the autonomous components by additional PI variables.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose ) -{ - Vec_Ptr_t * vNodes; - int Counter; - assert( Abc_NtkIsLogic(pNtk) ); - // mark the nodes reachable from the POs - vNodes = Abc_NtkDfsSeq( pNtk ); - Vec_PtrFree( vNodes ); - // remove the non-marked nodes - Counter = Abc_NodeRemoveNonCurrentObjects( pNtk ); - if ( fVerbose ) - printf( "Cleanup removed %4d dangling objects.\n", Counter ); - // check if some of the latches can be removed - if ( fLatchSweep ) - { - Counter = Abc_NtkLatchSweep( pNtk ); - if ( fVerbose ) - printf( "Cleanup removed %4d redundant latches.\n", Counter ); - } - // detect the autonomous components - if ( fAutoSweep ) - { - vNodes = Abc_NtkDfsSeqReverse( pNtk ); - Vec_PtrFree( vNodes ); - // replace them by PIs - Counter = Abc_NtkReplaceAutonomousLogic( pNtk ); - if ( fVerbose ) - printf( "Cleanup added %4d additional PIs.\n", Counter ); - // remove the non-marked nodes - Counter = Abc_NodeRemoveNonCurrentObjects( pNtk ); - if ( fVerbose ) - printf( "Cleanup removed %4d autonomous objects.\n", Counter ); - } - // check - if ( !Abc_NtkCheck( pNtk ) ) - printf( "Abc_NtkCleanupSeq: The network check has failed.\n" ); - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcSymm.c b/src/base/abci/abcSymm.c deleted file mode 100644 index 0f76065c..00000000 --- a/src/base/abci/abcSymm.c +++ /dev/null @@ -1,229 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcSymm.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Computation of two-variable symmetries.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcSymm.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose ); -static void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose ); -static void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose ); -static void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [The top level procedure to compute symmetries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ) -{ - if ( fUseBdds || fNaive ) - Abc_NtkSymmetriesUsingBdds( pNtk, fNaive, fReorder, fVerbose ); - else - Abc_NtkSymmetriesUsingSandS( pNtk, fVerbose ); -} - -/**Function************************************************************* - - Synopsis [Symmetry computation using simulation and SAT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkSymmetriesUsingSandS( Abc_Ntk_t * pNtk, int fVerbose ) -{ - extern int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose ); - int nSymms = Sim_ComputeTwoVarSymms( pNtk, fVerbose ); - printf( "The total number of symmetries is %d.\n", nSymms ); -} - -/**Function************************************************************* - - Synopsis [Symmetry computation using BDDs (both naive and smart).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkSymmetriesUsingBdds( Abc_Ntk_t * pNtk, int fNaive, int fReorder, int fVerbose ) -{ - DdManager * dd; - int clk, clkBdd, clkSym; - int fGarbCollect = 1; - - // compute the global functions -clk = clock(); - dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, fVerbose ); - printf( "Shared BDD size = %d nodes.\n", Abc_NtkSizeOfGlobalBdds(pNtk) ); - Cudd_AutodynDisable( dd ); - if ( !fGarbCollect ) - Cudd_DisableGarbageCollection( dd ); - Cudd_zddVarsFromBddVars( dd, 2 ); -clkBdd = clock() - clk; - // create the collapsed network -clk = clock(); - Ntk_NetworkSymmsBdd( dd, pNtk, fNaive, fVerbose ); -clkSym = clock() - clk; - // undo the global functions - Abc_NtkFreeGlobalBdds( pNtk, 1 ); -printf( "Statistics of BDD-based symmetry detection:\n" ); -printf( "Algorithm = %s. Reordering = %s. Garbage collection = %s.\n", - fNaive? "naive" : "fast", fReorder? "yes" : "no", fGarbCollect? "yes" : "no" ); -PRT( "Constructing BDDs", clkBdd ); -PRT( "Computing symms ", clkSym ); -PRT( "TOTAL ", clkBdd + clkSym ); -} - -/**Function************************************************************* - - Synopsis [Symmetry computation using BDDs (both naive and smart).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose ) -{ - Extra_SymmInfo_t * pSymms; - Abc_Obj_t * pNode; - DdNode * bFunc; - int nSymms = 0; - int nSupps = 0; - int i; - - // compute symmetry info for each PO - Abc_NtkForEachCo( pNtk, pNode, i ) - { -// bFunc = pNtk->vFuncsGlob->pArray[i]; - bFunc = Abc_ObjGlobalBdd( pNode ); - nSupps += Cudd_SupportSize( dd, bFunc ); - if ( Cudd_IsConstant(bFunc) ) - continue; - if ( fNaive ) - pSymms = Extra_SymmPairsComputeNaive( dd, bFunc ); - else - pSymms = Extra_SymmPairsCompute( dd, bFunc ); - nSymms += pSymms->nSymms; - if ( fVerbose ) - { - printf( "Output %6s (%d): ", Abc_ObjName(pNode), pSymms->nSymms ); - Ntk_NetworkSymmsPrint( pNtk, pSymms ); - } -//Extra_SymmPairsPrint( pSymms ); - Extra_SymmPairsDissolve( pSymms ); - } - printf( "Total number of vars in functional supports = %8d.\n", nSupps ); - printf( "Total number of two-variable symmetries = %8d.\n", nSymms ); -} - -/**Function************************************************************* - - Synopsis [Printing symmetry groups from the symmetry data structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ntk_NetworkSymmsPrint( Abc_Ntk_t * pNtk, Extra_SymmInfo_t * pSymms ) -{ - char ** pInputNames; - int * pVarTaken; - int i, k, nVars, nSize, fStart; - - // get variable names - nVars = Abc_NtkCiNum(pNtk); - pInputNames = Abc_NtkCollectCioNames( pNtk, 0 ); - - // alloc the array of marks - pVarTaken = ALLOC( int, nVars ); - memset( pVarTaken, 0, sizeof(int) * nVars ); - - // print the groups - fStart = 1; - nSize = pSymms->nVars; - for ( i = 0; i < nSize; i++ ) - { - // skip the variable already considered - if ( pVarTaken[i] ) - continue; - // find all the vars symmetric with this one - for ( k = 0; k < nSize; k++ ) - { - if ( k == i ) - continue; - if ( pSymms->pSymms[i][k] == 0 ) - continue; - // vars i and k are symmetric - assert( pVarTaken[k] == 0 ); - // there is a new symmetry pair - if ( fStart == 1 ) - { // start a new symmetry class - fStart = 0; - printf( " { %s", pInputNames[ pSymms->pVars[i] ] ); - // mark the var as taken - pVarTaken[i] = 1; - } - printf( " %s", pInputNames[ pSymms->pVars[k] ] ); - // mark the var as taken - pVarTaken[k] = 1; - } - if ( fStart == 0 ) - { - printf( " }" ); - fStart = 1; - } - } - printf( "\n" ); - - free( pInputNames ); - free( pVarTaken ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcTiming.c b/src/base/abci/abcTiming.c deleted file mode 100644 index 967e4617..00000000 --- a/src/base/abci/abcTiming.c +++ /dev/null @@ -1,905 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcTiming.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Computation of timing info for mapped circuits.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcTiming.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "main.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Abc_ManTime_t_ -{ - Abc_Time_t tArrDef; - Abc_Time_t tReqDef; - Vec_Ptr_t * vArrs; - Vec_Ptr_t * vReqs; -}; - -// static functions -static Abc_ManTime_t * Abc_ManTimeStart(); -static void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive ); -void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk ); - -void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ); - -// accessing the arrival and required times of a node -static inline Abc_Time_t * Abc_NodeArrival( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vArrs->pArray[pNode->Id]; } -static inline Abc_Time_t * Abc_NodeRequired( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vReqs->pArray[pNode->Id]; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the arrival time of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ) -{ - assert( pNode->pNtk->pManTime ); - return Abc_NodeArrival(pNode); -} - -/**Function************************************************************* - - Synopsis [Reads the arrival time of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ) -{ - assert( pNode->pNtk->pManTime ); - return Abc_NodeRequired(pNode); -} - -/**Function************************************************************* - - Synopsis [Reads the arrival time of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk ) -{ - assert( pNtk->pManTime ); - return &pNtk->pManTime->tArrDef; -} - -/**Function************************************************************* - - Synopsis [Reads the arrival time of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ) -{ - assert( pNtk->pManTime ); - return &pNtk->pManTime->tReqDef; -} - -/**Function************************************************************* - - Synopsis [Sets the default arrival time for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ) -{ - if ( Rise == 0.0 && Fall == 0.0 ) - return; - if ( pNtk->pManTime == NULL ) - pNtk->pManTime = Abc_ManTimeStart(); - pNtk->pManTime->tArrDef.Rise = Rise; - pNtk->pManTime->tArrDef.Fall = Fall; - pNtk->pManTime->tArrDef.Worst = ABC_MAX( Rise, Fall ); -} - -/**Function************************************************************* - - Synopsis [Sets the default arrival time for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ) -{ - if ( Rise == 0.0 && Fall == 0.0 ) - return; - if ( pNtk->pManTime == NULL ) - pNtk->pManTime = Abc_ManTimeStart(); - pNtk->pManTime->tReqDef.Rise = Rise; - pNtk->pManTime->tReqDef.Rise = Fall; - pNtk->pManTime->tReqDef.Worst = ABC_MAX( Rise, Fall ); -} - -/**Function************************************************************* - - Synopsis [Sets the arrival time for an object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ) -{ - Vec_Ptr_t * vTimes; - Abc_Time_t * pTime; - if ( pNtk->pManTime == NULL ) - pNtk->pManTime = Abc_ManTimeStart(); - if ( pNtk->pManTime->tArrDef.Rise == Rise && pNtk->pManTime->tArrDef.Fall == Fall ) - return; - Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 ); - // set the arrival time - vTimes = pNtk->pManTime->vArrs; - pTime = vTimes->pArray[ObjId]; - pTime->Rise = Rise; - pTime->Fall = Rise; - pTime->Worst = ABC_MAX( Rise, Fall ); -} - -/**Function************************************************************* - - Synopsis [Sets the arrival time for an object.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ) -{ - Vec_Ptr_t * vTimes; - Abc_Time_t * pTime; - if ( pNtk->pManTime == NULL ) - pNtk->pManTime = Abc_ManTimeStart(); - if ( pNtk->pManTime->tReqDef.Rise == Rise && pNtk->pManTime->tReqDef.Fall == Fall ) - return; - Abc_ManTimeExpand( pNtk->pManTime, ObjId + 1, 1 ); - // set the required time - vTimes = pNtk->pManTime->vReqs; - pTime = vTimes->pArray[ObjId]; - pTime->Rise = Rise; - pTime->Fall = Rise; - pTime->Worst = ABC_MAX( Rise, Fall ); -} - -/**Function************************************************************* - - Synopsis [Finalizes the timing manager after setting arr/req times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - Abc_Time_t ** ppTimes, * pTime; - int i; - if ( pNtk->pManTime == NULL ) - return; - Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 ); - // set the default timing - ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; - Abc_NtkForEachPi( pNtk, pObj, i ) - { - pTime = ppTimes[pObj->Id]; - if ( pTime->Worst != -ABC_INFINITY ) - continue; - *pTime = pNtk->pManTime->tArrDef; - } - // set the default timing - ppTimes = (Abc_Time_t **)pNtk->pManTime->vReqs->pArray; - Abc_NtkForEachPo( pNtk, pObj, i ) - { - pTime = ppTimes[pObj->Id]; - if ( pTime->Worst != -ABC_INFINITY ) - continue; - *pTime = pNtk->pManTime->tReqDef; - } - // set the 0 arrival times for latch outputs and constant nodes - ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; - Abc_NtkForEachLatchOutput( pNtk, pObj, i ) - { - pTime = ppTimes[pObj->Id]; - pTime->Fall = pTime->Rise = pTime->Worst = 0.0; - } -} - -/**Function************************************************************* - - Synopsis [Prepares the timing manager for delay trace.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - Abc_Time_t ** ppTimes, * pTime; - int i; - // if there is no timing manager, allocate and initialize - if ( pNtk->pManTime == NULL ) - { - pNtk->pManTime = Abc_ManTimeStart(); - Abc_NtkTimeInitialize( pNtk ); - return; - } - // if timing manager is given, expand it if necessary - Abc_ManTimeExpand( pNtk->pManTime, Abc_NtkObjNumMax(pNtk), 0 ); - // clean arrivals except for PIs - ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; - Abc_NtkForEachNode( pNtk, pObj, i ) - { - pTime = ppTimes[pObj->Id]; - pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY; - } - Abc_NtkForEachPo( pNtk, pObj, i ) - { - pTime = ppTimes[pObj->Id]; - pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY; - } - // clean required except for POs -} - - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_ManTime_t * Abc_ManTimeStart() -{ - Abc_ManTime_t * p; - p = ALLOC( Abc_ManTime_t, 1 ); - memset( p, 0, sizeof(Abc_ManTime_t) ); - p->vArrs = Vec_PtrAlloc( 0 ); - p->vReqs = Vec_PtrAlloc( 0 ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManTimeStop( Abc_ManTime_t * p ) -{ - if ( p->vArrs->nSize > 0 ) - { - free( p->vArrs->pArray[0] ); - Vec_PtrFree( p->vArrs ); - } - if ( p->vReqs->nSize > 0 ) - { - free( p->vReqs->pArray[0] ); - Vec_PtrFree( p->vReqs ); - } - free( p ); -} - -/**Function************************************************************* - - Synopsis [Duplicates the timing manager with the PI/PO timing info.] - - Description [The PIs/POs of the new network should be allocated.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) -{ - Abc_Obj_t * pObj; - Abc_Time_t ** ppTimesOld, ** ppTimesNew; - int i; - if ( pNtkOld->pManTime == NULL ) - return; - assert( Abc_NtkPiNum(pNtkOld) == Abc_NtkPiNum(pNtkNew) ); - assert( Abc_NtkPoNum(pNtkOld) == Abc_NtkPoNum(pNtkNew) ); - assert( Abc_NtkLatchNum(pNtkOld) == Abc_NtkLatchNum(pNtkNew) ); - // create the new timing manager - pNtkNew->pManTime = Abc_ManTimeStart(); - Abc_ManTimeExpand( pNtkNew->pManTime, Abc_NtkObjNumMax(pNtkNew), 0 ); - // set the default timing - pNtkNew->pManTime->tArrDef = pNtkOld->pManTime->tArrDef; - pNtkNew->pManTime->tReqDef = pNtkOld->pManTime->tReqDef; - // set the CI timing - ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vArrs->pArray; - ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vArrs->pArray; - Abc_NtkForEachCi( pNtkOld, pObj, i ) - *ppTimesNew[ Abc_NtkCi(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ]; - // set the CO timing - ppTimesOld = (Abc_Time_t **)pNtkOld->pManTime->vReqs->pArray; - ppTimesNew = (Abc_Time_t **)pNtkNew->pManTime->vReqs->pArray; - Abc_NtkForEachCo( pNtkOld, pObj, i ) - *ppTimesNew[ Abc_NtkCo(pNtkNew,i)->Id ] = *ppTimesOld[ pObj->Id ]; -} - -/**Function************************************************************* - - Synopsis [Expends the storage for timing information.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManTimeExpand( Abc_ManTime_t * p, int nSize, int fProgressive ) -{ - Vec_Ptr_t * vTimes; - Abc_Time_t * ppTimes, * ppTimesOld, * pTime; - int nSizeOld, nSizeNew, i; - - nSizeOld = p->vArrs->nSize; - if ( nSizeOld >= nSize ) - return; - nSizeNew = fProgressive? 2 * nSize : nSize; - if ( nSizeNew < 100 ) - nSizeNew = 100; - - vTimes = p->vArrs; - Vec_PtrGrow( vTimes, nSizeNew ); - vTimes->nSize = nSizeNew; - ppTimesOld = ( nSizeOld == 0 )? NULL : vTimes->pArray[0]; - ppTimes = REALLOC( Abc_Time_t, ppTimesOld, nSizeNew ); - for ( i = 0; i < nSizeNew; i++ ) - vTimes->pArray[i] = ppTimes + i; - for ( i = nSizeOld; i < nSizeNew; i++ ) - { - pTime = vTimes->pArray[i]; - pTime->Rise = -ABC_INFINITY; - pTime->Fall = -ABC_INFINITY; - pTime->Worst = -ABC_INFINITY; - } - - vTimes = p->vReqs; - Vec_PtrGrow( vTimes, nSizeNew ); - vTimes->nSize = nSizeNew; - ppTimesOld = ( nSizeOld == 0 )? NULL : vTimes->pArray[0]; - ppTimes = REALLOC( Abc_Time_t, ppTimesOld, nSizeNew ); - for ( i = 0; i < nSizeNew; i++ ) - vTimes->pArray[i] = ppTimes + i; - for ( i = nSizeOld; i < nSizeNew; i++ ) - { - pTime = vTimes->pArray[i]; - pTime->Rise = -ABC_INFINITY; - pTime->Fall = -ABC_INFINITY; - pTime->Worst = -ABC_INFINITY; - } -} - - - - - - -/**Function************************************************************* - - Synopsis [Sets the CI node levels according to the arrival info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtkOld ) -{ - Abc_Obj_t * pNodeOld, * pNodeNew; - float tAndDelay; - int i; - if ( pNtkOld->pManTime == NULL ) - return; - if ( Mio_LibraryReadNand2(Abc_FrameReadLibGen()) == NULL ) - return; - tAndDelay = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen()); - Abc_NtkForEachPi( pNtkOld, pNodeOld, i ) - { - pNodeNew = pNodeOld->pCopy; - pNodeNew->Level = (int)(Abc_NodeArrival(pNodeOld)->Worst / tAndDelay); - } -} - -/**Function************************************************************* - - Synopsis [Sets the CI node levels according to the arrival info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk ) -{ - Abc_Time_t * p; - Abc_Obj_t * pNode; - int i; - p = ALLOC( Abc_Time_t, Abc_NtkCiNum(pNtk) ); - memset( p, 0, sizeof(Abc_Time_t) * Abc_NtkCiNum(pNtk) ); - if ( pNtk->pManTime == NULL ) - return p; - // set the PI arrival times - Abc_NtkForEachPi( pNtk, pNode, i ) - p[i] = *Abc_NodeArrival(pNode); - return p; -} - - -/**Function************************************************************* - - Synopsis [Sets the CI node levels according to the arrival info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk ) -{ - float * p; - Abc_Obj_t * pNode; - int i; - p = ALLOC( float, Abc_NtkCiNum(pNtk) ); - memset( p, 0, sizeof(float) * Abc_NtkCiNum(pNtk) ); - if ( pNtk->pManTime == NULL ) - return p; - // set the PI arrival times - Abc_NtkForEachPi( pNtk, pNode, i ) - p[i] = Abc_NodeArrival(pNode)->Worst; - return p; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode, * pDriver; - Vec_Ptr_t * vNodes; - Abc_Time_t * pTime; - float tArrivalMax; - int i; - - assert( Abc_NtkIsMappedLogic(pNtk) ); - - Abc_NtkTimePrepare( pNtk ); - vNodes = Abc_NtkDfs( pNtk, 1 ); - for ( i = 0; i < vNodes->nSize; i++ ) - Abc_NodeDelayTraceArrival( vNodes->pArray[i] ); - Vec_PtrFree( vNodes ); - - // get the latest arrival times - tArrivalMax = -ABC_INFINITY; - Abc_NtkForEachCo( pNtk, pNode, i ) - { - pDriver = Abc_ObjFanin0(pNode); - pTime = Abc_NodeArrival(pDriver); - if ( tArrivalMax < pTime->Worst ) - tArrivalMax = pTime->Worst; - } - return tArrivalMax; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin; - Abc_Time_t * pTimeIn, * pTimeOut; - float tDelayBlockRise, tDelayBlockFall; - Mio_PinPhase_t PinPhase; - Mio_Pin_t * pPin; - int i; - - // start the arrival time of the node - pTimeOut = Abc_NodeArrival(pNode); - pTimeOut->Rise = pTimeOut->Fall = -ABC_INFINITY; - // go through the pins of the gate - pPin = Mio_GateReadPins(pNode->pData); - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - pTimeIn = Abc_NodeArrival(pFanin); - // get the interesting parameters of this pin - PinPhase = Mio_PinReadPhase(pPin); - tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); - tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); - // compute the arrival times of the positive phase - if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present - { - if ( pTimeOut->Rise < pTimeIn->Rise + tDelayBlockRise ) - pTimeOut->Rise = pTimeIn->Rise + tDelayBlockRise; - if ( pTimeOut->Fall < pTimeIn->Fall + tDelayBlockFall ) - pTimeOut->Fall = pTimeIn->Fall + tDelayBlockFall; - } - if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present - { - if ( pTimeOut->Rise < pTimeIn->Fall + tDelayBlockRise ) - pTimeOut->Rise = pTimeIn->Fall + tDelayBlockRise; - if ( pTimeOut->Fall < pTimeIn->Rise + tDelayBlockFall ) - pTimeOut->Fall = pTimeIn->Rise + tDelayBlockFall; - } - pPin = Mio_PinReadNext(pPin); - } - pTimeOut->Worst = ABC_MAX( pTimeOut->Rise, pTimeOut->Fall ); -} - - - - -/**Function************************************************************* - - Synopsis [Computes the level of the node using its fanin levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ObjLevelNew( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i, Level = 0; - Abc_ObjForEachFanin( pObj, pFanin, i ) - Level = ABC_MAX( Level, Abc_ObjLevel(pFanin) ); - return Level + 1; -} - -/**Function************************************************************* - - Synopsis [Computes the reverse level of the node using its fanout levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout; - int i, LevelCur, Level = 0; - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - LevelCur = Abc_ObjReverseLevel( pFanout ); - Level = ABC_MAX( Level, LevelCur ); - } - return Level + 1; -} - -/**Function************************************************************* - - Synopsis [Returns required level of the node.] - - Description [Converts the reverse levels of the node into its required - level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ObjRequiredLevel( Abc_Obj_t * pObj ) -{ - Abc_Ntk_t * pNtk = pObj->pNtk; - assert( pNtk->vLevelsR ); - return pNtk->LevelMax + 1 - Abc_ObjReverseLevel(pObj); -} - -/**Function************************************************************* - - Synopsis [Returns the reverse level of the node.] - - Description [The reverse level is the level of the node in reverse - topological order, starting from the COs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ObjReverseLevel( Abc_Obj_t * pObj ) -{ - Abc_Ntk_t * pNtk = pObj->pNtk; - assert( pNtk->vLevelsR ); - Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); - return Vec_IntEntry(pNtk->vLevelsR, pObj->Id); -} - -/**Function************************************************************* - - Synopsis [Sets the reverse level of the node.] - - Description [The reverse level is the level of the node in reverse - topological order, starting from the COs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR ) -{ - Abc_Ntk_t * pNtk = pObj->pNtk; - assert( pNtk->vLevelsR ); - Vec_IntFillExtra( pNtk->vLevelsR, pObj->Id + 1, 0 ); - Vec_IntWriteEntry( pNtk->vLevelsR, pObj->Id, LevelR ); -} - -/**Function************************************************************* - - Synopsis [Prepares for the computation of required levels.] - - Description [This procedure should be called before the required times - are used. It starts internal data structures, which records the level - from the COs of the network nodes in reverse topologogical order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i; - // remember the maximum number of direct levels - pNtk->LevelMax = Abc_NtkLevel(pNtk) + nMaxLevelIncrease; - // start the reverse levels - pNtk->vLevelsR = Vec_IntAlloc( 0 ); - Vec_IntFill( pNtk->vLevelsR, 1 + Abc_NtkObjNumMax(pNtk), 0 ); - // compute levels in reverse topological order - vNodes = Abc_NtkDfsReverse( pNtk ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - Abc_ObjSetReverseLevel( pObj, Abc_ObjReverseLevelNew(pObj) ); - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Cleans the data structures used to compute required levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ) -{ - assert( pNtk->vLevelsR ); - Vec_IntFree( pNtk->vLevelsR ); - pNtk->vLevelsR = NULL; - pNtk->LevelMax = 0; - -} - -/**Function************************************************************* - - Synopsis [Incrementally updates level of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) -{ - Abc_Obj_t * pFanout, * pTemp; - int LevelOld, Lev, k, m; - // check if level has changed - LevelOld = Abc_ObjLevel(pObjNew); - if ( LevelOld == Abc_ObjLevelNew(pObjNew) ) - return; - // start the data structure for level update - // we cannot fail to visit a node when using this structure because the - // nodes are stored by their _old_ levels, which are assumed to be correct - Vec_VecClear( vLevels ); - Vec_VecPush( vLevels, LevelOld, pObjNew ); - pObjNew->fMarkA = 1; - // recursively update level - Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld ) - { - pTemp->fMarkA = 0; - assert( Abc_ObjLevel(pTemp) == Lev ); - Abc_ObjSetLevel( pTemp, Abc_ObjLevelNew(pTemp) ); - // if the level did not change, no need to check the fanout levels - if ( Abc_ObjLevel(pTemp) == Lev ) - continue; - // schedule fanout for level update - Abc_ObjForEachFanout( pTemp, pFanout, m ) - { - if ( !Abc_ObjIsCo(pFanout) && !pFanout->fMarkA ) - { - assert( Abc_ObjLevel(pFanout) >= Lev ); - Vec_VecPush( vLevels, Abc_ObjLevel(pFanout), pFanout ); - pFanout->fMarkA = 1; - } - } - } -} - -/**Function************************************************************* - - Synopsis [Incrementally updates level of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) -{ - Abc_Obj_t * pFanin, * pTemp; - int LevelOld, LevFanin, Lev, k, m; - // check if level has changed - LevelOld = Abc_ObjReverseLevel(pObjNew); - if ( LevelOld == Abc_ObjReverseLevelNew(pObjNew) ) - return; - // start the data structure for level update - // we cannot fail to visit a node when using this structure because the - // nodes are stored by their _old_ levels, which are assumed to be correct - Vec_VecClear( vLevels ); - Vec_VecPush( vLevels, LevelOld, pObjNew ); - pObjNew->fMarkA = 1; - // recursively update level - Vec_VecForEachEntryStart( vLevels, pTemp, Lev, k, LevelOld ) - { - pTemp->fMarkA = 0; - LevelOld = Abc_ObjReverseLevel(pTemp); - assert( LevelOld == Lev ); - Abc_ObjSetReverseLevel( pTemp, Abc_ObjReverseLevelNew(pTemp) ); - // if the level did not change, no need to check the fanout levels - if ( Abc_ObjReverseLevel(pTemp) == Lev ) - continue; - // schedule fanins for level update - Abc_ObjForEachFanin( pTemp, pFanin, m ) - { - if ( !Abc_ObjIsCi(pFanin) && !pFanin->fMarkA ) - { - LevFanin = Abc_ObjReverseLevel( pFanin ); - assert( LevFanin >= Lev ); - Vec_VecPush( vLevels, LevFanin, pFanin ); - pFanin->fMarkA = 1; - } - } - } -} - -/**Function************************************************************* - - Synopsis [Replaces the node and incrementally updates levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ) -{ - // replace the old node by the new node - pObjNew->Level = pObj->Level; - Abc_ObjReplace( pObj, pObjNew ); - // update the level of the node - Abc_NtkUpdateLevel( pObjNew, vLevels ); - Abc_ObjSetReverseLevel( pObjNew, 0 ); - Abc_NtkUpdateReverseLevel( pObjNew, vLevels ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcUnate.c b/src/base/abci/abcUnate.c deleted file mode 100644 index 20804d19..00000000 --- a/src/base/abci/abcUnate.c +++ /dev/null @@ -1,155 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcUnate.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcUnate.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose ); -static void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Detects unate variables of the multi-output function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose ) -{ - if ( fUseBdds || fUseNaive ) - Abc_NtkPrintUnateBdd( pNtk, fUseNaive, fVerbose ); - else - Abc_NtkPrintUnateSat( pNtk, fVerbose ); -} - -/**Function************************************************************* - - Synopsis [Detects unate variables using BDDs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintUnateBdd( Abc_Ntk_t * pNtk, int fUseNaive, int fVerbose ) -{ - Abc_Obj_t * pNode; - Extra_UnateInfo_t * p; - DdManager * dd; // the BDD manager used to hold shared BDDs -// DdNode ** pbGlobal; // temporary storage for global BDDs - int TotalSupps = 0; - int TotalUnate = 0; - int i, clk = clock(); - int clkBdd, clkUnate; - - // compute the global BDDs - dd = Abc_NtkBuildGlobalBdds(pNtk, 10000000, 1, 1, fVerbose); - if ( dd == NULL ) - return; -clkBdd = clock() - clk; - - // get information about the network -// dd = pNtk->pManGlob; -// dd = Abc_NtkGlobalBddMan( pNtk ); -// pbGlobal = (DdNode **)Vec_PtrArray( pNtk->vFuncsGlob ); - - // print the size of the BDDs - printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - - // perform naive BDD-based computation - if ( fUseNaive ) - { - Abc_NtkForEachCo( pNtk, pNode, i ) - { -// p = Extra_UnateComputeSlow( dd, pbGlobal[i] ); - p = Extra_UnateComputeSlow( dd, Abc_ObjGlobalBdd(pNode) ); - if ( fVerbose ) - Extra_UnateInfoPrint( p ); - TotalSupps += p->nVars; - TotalUnate += p->nUnate; - Extra_UnateInfoDissolve( p ); - } - } - // perform smart BDD-based computation - else - { - // create ZDD variables in the manager - Cudd_zddVarsFromBddVars( dd, 2 ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { -// p = Extra_UnateComputeFast( dd, pbGlobal[i] ); - p = Extra_UnateComputeFast( dd, Abc_ObjGlobalBdd(pNode) ); - if ( fVerbose ) - Extra_UnateInfoPrint( p ); - TotalSupps += p->nVars; - TotalUnate += p->nUnate; - Extra_UnateInfoDissolve( p ); - } - } -clkUnate = clock() - clk - clkBdd; - - // print stats - printf( "Ins/Outs = %4d/%4d. Total supp = %5d. Total unate = %5d.\n", - Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), TotalSupps, TotalUnate ); - PRT( "Glob BDDs", clkBdd ); - PRT( "Unateness", clkUnate ); - PRT( "Total ", clock() - clk ); - - // deref the PO functions -// Abc_NtkFreeGlobalBdds( pNtk ); - // stop the global BDD manager -// Extra_StopManager( pNtk->pManGlob ); -// pNtk->pManGlob = NULL; - Abc_NtkFreeGlobalBdds( pNtk, 1 ); -} - -/**Function************************************************************* - - Synopsis [Detects unate variables using SAT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintUnateSat( Abc_Ntk_t * pNtk, int fVerbose ) -{ -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcUnreach.c b/src/base/abci/abcUnreach.c deleted file mode 100644 index ea0a4cd2..00000000 --- a/src/base/abci/abcUnreach.c +++ /dev/null @@ -1,349 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcUnreach.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Computes unreachable states for small benchmarks.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcUnreach.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ); -static DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ); -static DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bRelation, DdNode * bInitial, bool fVerbose ); -static Abc_Ntk_t * Abc_NtkConstructExdc ( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Extracts sequential DCs of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose ) -{ - int fReorder = 1; - DdManager * dd; - DdNode * bRelation, * bInitial, * bUnreach; - - // remove EXDC network if present - if ( pNtk->pExdc ) - { - Abc_NtkDelete( pNtk->pExdc ); - pNtk->pExdc = NULL; - } - - // compute the global BDDs of the latches - dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose ); - if ( dd == NULL ) - return 0; - if ( fVerbose ) - printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); - - // create the transition relation (dereferenced global BDDs) - bRelation = Abc_NtkTransitionRelation( dd, pNtk, fVerbose ); Cudd_Ref( bRelation ); - // create the initial state and the variable map - bInitial = Abc_NtkInitStateAndVarMap( dd, pNtk, fVerbose ); Cudd_Ref( bInitial ); - // compute the unreachable states - bUnreach = Abc_NtkComputeUnreachable( dd, pNtk, bRelation, bInitial, fVerbose ); Cudd_Ref( bUnreach ); - Cudd_RecursiveDeref( dd, bRelation ); - Cudd_RecursiveDeref( dd, bInitial ); - - // reorder and disable reordering - if ( fReorder ) - { - if ( fVerbose ) - fprintf( stdout, "BDD nodes in the unreachable states before reordering %d.\n", Cudd_DagSize(bUnreach) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); - Cudd_AutodynDisable( dd ); - if ( fVerbose ) - fprintf( stdout, "BDD nodes in the unreachable states after reordering %d.\n", Cudd_DagSize(bUnreach) ); - } - - // allocate ZDD variables - Cudd_zddVarsFromBddVars( dd, 2 ); - // create the EXDC network representing the unreachable states - if ( pNtk->pExdc ) - Abc_NtkDelete( pNtk->pExdc ); - pNtk->pExdc = Abc_NtkConstructExdc( dd, pNtk, bUnreach ); - Cudd_RecursiveDeref( dd, bUnreach ); - Extra_StopManager( dd ); -// pNtk->pManGlob = NULL; - - // make sure that everything is okay - if ( pNtk->pExdc && !Abc_NtkCheck( pNtk->pExdc ) ) - { - printf( "Abc_NtkExtractSequentialDcs: The network check has failed.\n" ); - Abc_NtkDelete( pNtk->pExdc ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes the transition relation of the network.] - - Description [Assumes that the global BDDs are computed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) -{ - DdNode * bRel, * bTemp, * bProd, * bVar, * bInputs; - Abc_Obj_t * pNode; - int fReorder = 1; - int i; - - // extand the BDD manager to represent NS variables - assert( dd->size == Abc_NtkCiNum(pNtk) ); - Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 ); - - // enable reordering - if ( fReorder ) - Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); - else - Cudd_AutodynDisable( dd ); - - // compute the transition relation - bRel = b1; Cudd_Ref( bRel ); - Abc_NtkForEachLatch( pNtk, pNode, i ) - { - bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i ); -// bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd ); - bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd ); - bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - } - // free the global BDDs -// Abc_NtkFreeGlobalBdds( pNtk ); - Abc_NtkFreeGlobalBdds( pNtk, 0 ); - - // quantify the PI variables - bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs ); - bRel = Cudd_bddExistAbstract( dd, bTemp = bRel, bInputs ); Cudd_Ref( bRel ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bInputs ); - - // reorder and disable reordering - if ( fReorder ) - { - if ( fVerbose ) - fprintf( stdout, "BDD nodes in the transition relation before reordering %d.\n", Cudd_DagSize(bRel) ); - Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); - Cudd_AutodynDisable( dd ); - if ( fVerbose ) - fprintf( stdout, "BDD nodes in the transition relation after reordering %d.\n", Cudd_DagSize(bRel) ); - } - Cudd_Deref( bRel ); - return bRel; -} - -/**Function************************************************************* - - Synopsis [Computes the initial state and sets up the variable map.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) -{ - DdNode ** pbVarsX, ** pbVarsY; - DdNode * bTemp, * bProd, * bVar; - Abc_Obj_t * pLatch; - int i; - - // set the variable mapping for Cudd_bddVarMap() - pbVarsX = ALLOC( DdNode *, dd->size ); - pbVarsY = ALLOC( DdNode *, dd->size ); - bProd = b1; Cudd_Ref( bProd ); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - pbVarsX[i] = dd->vars[ Abc_NtkPiNum(pNtk) + i ]; - pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ]; - // get the initial value of the latch - bVar = Cudd_NotCond( pbVarsX[i], !Abc_LatchIsInit1(pLatch) ); - bProd = Cudd_bddAnd( dd, bTemp = bProd, bVar ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Abc_NtkLatchNum(pNtk) ); - FREE( pbVarsX ); - FREE( pbVarsY ); - - Cudd_Deref( bProd ); - return bProd; -} - -/**Function************************************************************* - - Synopsis [Computes the set of unreachable states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bTrans, DdNode * bInitial, bool fVerbose ) -{ - DdNode * bRelation, * bReached, * bCubeCs; - DdNode * bCurrent, * bNext, * bTemp; - int nIters, nMints; - - // perform reachability analisys - bCurrent = bInitial; Cudd_Ref( bCurrent ); - bReached = bInitial; Cudd_Ref( bReached ); - bRelation = bTrans; Cudd_Ref( bRelation ); - bCubeCs = Extra_bddComputeRangeCube( dd, Abc_NtkPiNum(pNtk), Abc_NtkCiNum(pNtk) ); Cudd_Ref( bCubeCs ); - for ( nIters = 1; ; nIters++ ) - { - // compute the next states - bNext = Cudd_bddAndAbstract( dd, bRelation, bCurrent, bCubeCs ); Cudd_Ref( bNext ); - Cudd_RecursiveDeref( dd, bCurrent ); - // remap these states into the current state vars - bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext ); - Cudd_RecursiveDeref( dd, bTemp ); - // check if there are any new states - if ( Cudd_bddLeq( dd, bNext, bReached ) ) - break; - // get the new states - bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); - // minimize the new states with the reached states -// bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent ); -// Cudd_RecursiveDeref( dd, bTemp ); - // add to the reached states - bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bNext ); - // minimize the transition relation -// bRelation = Cudd_bddConstrain( dd, bTemp = bRelation, Cudd_Not(bReached) ); Cudd_Ref( bRelation ); -// Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_RecursiveDeref( dd, bRelation ); - Cudd_RecursiveDeref( dd, bCubeCs ); - Cudd_RecursiveDeref( dd, bNext ); - // report the stats - if ( fVerbose ) - { - nMints = (int)Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) ); - fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters ); - fprintf( stdout, "The number of minterms in the reachable state set = %d. (%6.2f %%)\n", nMints, 100.0*nMints/(1<pName = Extra_UtilStrsav( "exdc" ); - pNtkNew->pSpec = NULL; - - // create PIs corresponding to LOs - Abc_NtkForEachLatchOutput( pNtk, pNode, i ) - Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pNode), NULL ); - // cannot ADD POs here because pLatch->pCopy point to the PIs - - // create a new node - pNodeNew = Abc_NtkCreateNode(pNtkNew); - // add the fanins corresponding to latch outputs - Abc_NtkForEachLatchOutput( pNtk, pNode, i ) - Abc_ObjAddFanin( pNodeNew, pNode->pCopy ); - - // create the logic function - pPermute = ALLOC( int, dd->size ); - for ( i = 0; i < dd->size; i++ ) - pPermute[i] = -1; - Abc_NtkForEachLatch( pNtk, pNode, i ) - pPermute[Abc_NtkPiNum(pNtk) + i] = i; - // remap the functions - pNodeNew->pData = Extra_TransferPermute( dd, pNtkNew->pManFunc, bUnreach, pPermute ); Cudd_Ref( pNodeNew->pData ); - free( pPermute ); - Abc_NodeMinimumBase( pNodeNew ); - - // for each CO, create PO (skip POs equal to CIs because of name conflict) - Abc_NtkForEachPo( pNtk, pNode, i ) - if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) - Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL ); - Abc_NtkForEachLatchInput( pNtk, pNode, i ) - Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL ); - - // link to the POs of the network - Abc_NtkForEachPo( pNtk, pNode, i ) - if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) - Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); - Abc_NtkForEachLatchInput( pNtk, pNode, i ) - Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); - - // remove the extra nodes - Abc_AigCleanup( pNtkNew->pManFunc ); - - // fix the problem with complemented and duplicated CO edges - Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); - - // transform the network to the SOP representation - if ( !Abc_NtkBddToSop( pNtkNew, 0 ) ) - { - printf( "Abc_NtkConstructExdc(): Converting to SOPs has failed.\n" ); - return NULL; - } - return pNtkNew; -// return NULL; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcVerify.c b/src/base/abci/abcVerify.c deleted file mode 100644 index 9c9bbcfd..00000000 --- a/src/base/abci/abcVerify.c +++ /dev/null @@ -1,1018 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcVerify.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Combinational and sequential verification for two networks.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcVerify.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "fraig.h" -#include "sim.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel ); -extern void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Verifies combinational equivalence by brute-force SAT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit ) -{ - extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); - Abc_Ntk_t * pMiter; - Abc_Ntk_t * pCnf; - int RetValue; - - // get the miter of the two networks - pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 ); - if ( pMiter == NULL ) - { - printf( "Miter computation has failed.\n" ); - return; - } - RetValue = Abc_NtkMiterIsConstant( pMiter ); - if ( RetValue == 0 ) - { - printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); - // report the error - pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); - Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); - FREE( pMiter->pModel ); - Abc_NtkDelete( pMiter ); - return; - } - if ( RetValue == 1 ) - { - Abc_NtkDelete( pMiter ); - printf( "Networks are equivalent after structural hashing.\n" ); - return; - } - - // convert the miter into a CNF - pCnf = Abc_NtkMulti( pMiter, 0, 100, 1, 0, 0, 0 ); - Abc_NtkDelete( pMiter ); - if ( pCnf == NULL ) - { - printf( "Renoding for CNF has failed.\n" ); - return; - } - - // solve the CNF using the SAT solver - RetValue = Abc_NtkMiterSat( pCnf, (sint64)nConfLimit, (sint64)nInsLimit, 0, NULL, NULL ); - if ( RetValue == -1 ) - printf( "Networks are undecided (SAT solver timed out).\n" ); - else if ( RetValue == 0 ) - printf( "Networks are NOT EQUIVALENT after SAT.\n" ); - else - printf( "Networks are equivalent after SAT.\n" ); - if ( pCnf->pModel ) - Abc_NtkVerifyReportError( pNtk1, pNtk2, pCnf->pModel ); - FREE( pCnf->pModel ); - Abc_NtkDelete( pCnf ); -} - - -/**Function************************************************************* - - Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ) -{ - Prove_Params_t Params, * pParams = &Params; -// Fraig_Params_t Params; -// Fraig_Man_t * pMan; - Abc_Ntk_t * pMiter; - int RetValue; - - // get the miter of the two networks - pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 0 ); - if ( pMiter == NULL ) - { - printf( "Miter computation has failed.\n" ); - return; - } - RetValue = Abc_NtkMiterIsConstant( pMiter ); - if ( RetValue == 0 ) - { - printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); - // report the error - pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); - Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); - FREE( pMiter->pModel ); - Abc_NtkDelete( pMiter ); - return; - } - if ( RetValue == 1 ) - { - printf( "Networks are equivalent after structural hashing.\n" ); - Abc_NtkDelete( pMiter ); - return; - } -/* - // convert the miter into a FRAIG - Fraig_ParamsSetDefault( &Params ); - Params.fVerbose = fVerbose; - Params.nSeconds = nSeconds; -// Params.fFuncRed = 0; -// Params.nPatsRand = 0; -// Params.nPatsDyna = 0; - pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 ); - Fraig_ManProveMiter( pMan ); - - // analyze the result - RetValue = Fraig_ManCheckMiter( pMan ); - // report the result - if ( RetValue == -1 ) - printf( "Networks are undecided (SAT solver timed out on the final miter).\n" ); - else if ( RetValue == 1 ) - printf( "Networks are equivalent after fraiging.\n" ); - else if ( RetValue == 0 ) - { - printf( "Networks are NOT EQUIVALENT after fraiging.\n" ); - Abc_NtkVerifyReportError( pNtk1, pNtk2, Fraig_ManReadModel(pMan) ); - } - else assert( 0 ); - // delete the fraig manager - Fraig_ManFree( pMan ); - // delete the miter - Abc_NtkDelete( pMiter ); -*/ - // solve the CNF using the SAT solver - Prove_ParamsSetDefault( pParams ); - pParams->nItersMax = 5; -// RetValue = Abc_NtkMiterProve( &pMiter, pParams ); -// pParams->fVerbose = 1; - RetValue = Abc_NtkIvyProve( &pMiter, pParams ); - if ( RetValue == -1 ) - printf( "Networks are undecided (resource limits is reached).\n" ); - else if ( RetValue == 0 ) - { - int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiter, pMiter->pModel ); - if ( pSimInfo[0] != 1 ) - printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); - else - printf( "Networks are NOT EQUIVALENT.\n" ); - free( pSimInfo ); - } - else - printf( "Networks are equivalent.\n" ); - if ( pMiter->pModel ) - Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); - Abc_NtkDelete( pMiter ); -} - -/**Function************************************************************* - - Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose ) -{ - extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); - extern void * Abc_FrameGetGlobalFrame(); - - Prove_Params_t Params, * pParams = &Params; - Abc_Ntk_t * pMiter, * pMiterPart; - Abc_Obj_t * pObj; - int i, RetValue, Status, nOutputs; - - // solve the CNF using the SAT solver - Prove_ParamsSetDefault( pParams ); - pParams->nItersMax = 5; - // pParams->fVerbose = 1; - - assert( nPartSize > 0 ); - - // get the miter of the two networks - pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, nPartSize ); - if ( pMiter == NULL ) - { - printf( "Miter computation has failed.\n" ); - return; - } - RetValue = Abc_NtkMiterIsConstant( pMiter ); - if ( RetValue == 0 ) - { - printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); - // report the error - pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); - Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); - FREE( pMiter->pModel ); - Abc_NtkDelete( pMiter ); - return; - } - if ( RetValue == 1 ) - { - printf( "Networks are equivalent after structural hashing.\n" ); - Abc_NtkDelete( pMiter ); - return; - } - - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); - - // solve the problem iteratively for each output of the miter - Status = 1; - nOutputs = 0; - Abc_NtkForEachPo( pMiter, pObj, i ) - { - if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pMiter) ) - { - if ( Abc_ObjFaninC0(pObj) ) // complemented -> const 0 - RetValue = 1; - else - RetValue = 0; - pMiterPart = NULL; - } - else - { - // get the cone of this output - pMiterPart = Abc_NtkCreateCone( pMiter, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 0 ); - if ( Abc_ObjFaninC0(pObj) ) - Abc_ObjXorFaninC( Abc_NtkPo(pMiterPart,0), 0 ); - // solve the cone - // RetValue = Abc_NtkMiterProve( &pMiterPart, pParams ); - RetValue = Abc_NtkIvyProve( &pMiterPart, pParams ); - } - - if ( RetValue == -1 ) - { - printf( "Networks are undecided (resource limits is reached).\r" ); - Status = -1; - } - else if ( RetValue == 0 ) - { - int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel ); - if ( pSimInfo[0] != 1 ) - printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); - else - printf( "Networks are NOT EQUIVALENT. \n" ); - free( pSimInfo ); - Status = 0; - break; - } - else - { - printf( "Finished part %5d (out of %5d)\r", i+1, Abc_NtkPoNum(pMiter) ); - nOutputs += nPartSize; - } -// if ( pMiter->pModel ) -// Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); - if ( pMiterPart ) - Abc_NtkDelete( pMiterPart ); - } - - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); - - if ( Status == 1 ) - printf( "Networks are equivalent. \n" ); - else if ( Status == -1 ) - printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) ); - Abc_NtkDelete( pMiter ); -} - -/**Function************************************************************* - - Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ) -{ - extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); - extern Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nPartSizeLimit, int fVerbose ); - extern void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOnePtr ); - extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); - extern void * Abc_FrameGetGlobalFrame(); - - Vec_Ptr_t * vParts, * vOnePtr; - Vec_Int_t * vOne; - Prove_Params_t Params, * pParams = &Params; - Abc_Ntk_t * pMiter, * pMiterPart; - int i, RetValue, Status, nOutputs; - - // solve the CNF using the SAT solver - Prove_ParamsSetDefault( pParams ); - pParams->nItersMax = 5; - // pParams->fVerbose = 1; - - // get the miter of the two networks - pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 1 ); - if ( pMiter == NULL ) - { - printf( "Miter computation has failed.\n" ); - return; - } - RetValue = Abc_NtkMiterIsConstant( pMiter ); - if ( RetValue == 0 ) - { - printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); - // report the error - pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); - Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); - FREE( pMiter->pModel ); - Abc_NtkDelete( pMiter ); - return; - } - if ( RetValue == 1 ) - { - printf( "Networks are equivalent after structural hashing.\n" ); - Abc_NtkDelete( pMiter ); - return; - } - - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); - - // partition the outputs - vParts = Abc_NtkPartitionSmart( pMiter, 300, 0 ); - - // fraig each partition - Status = 1; - nOutputs = 0; - vOnePtr = Vec_PtrAlloc( 1000 ); - Vec_PtrForEachEntry( vParts, vOne, i ) - { - // get this part of the miter - Abc_NtkConvertCos( pMiter, vOne, vOnePtr ); - pMiterPart = Abc_NtkCreateConeArray( pMiter, vOnePtr, 0 ); - Abc_NtkCombinePos( pMiterPart, 0 ); - // check the miter for being constant - RetValue = Abc_NtkMiterIsConstant( pMiterPart ); - if ( RetValue == 0 ) - { - printf( "Networks are NOT EQUIVALENT after partitioning.\n" ); - Abc_NtkDelete( pMiterPart ); - break; - } - if ( RetValue == 1 ) - { - Abc_NtkDelete( pMiterPart ); - continue; - } - printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", - i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pMiterPart), Abc_NtkPoNum(pMiterPart), - Abc_NtkNodeNum(pMiterPart), Abc_AigLevel(pMiterPart) ); - // solve the problem - RetValue = Abc_NtkIvyProve( &pMiterPart, pParams ); - if ( RetValue == -1 ) - { - printf( "Networks are undecided (resource limits is reached).\r" ); - Status = -1; - } - else if ( RetValue == 0 ) - { - int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel ); - if ( pSimInfo[0] != 1 ) - printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); - else - printf( "Networks are NOT EQUIVALENT. \n" ); - free( pSimInfo ); - Status = 0; - Abc_NtkDelete( pMiterPart ); - break; - } - else - { -// printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) ); - nOutputs += Vec_IntSize(vOne); - } - Abc_NtkDelete( pMiterPart ); - } - printf( " \r" ); - Vec_VecFree( (Vec_Vec_t *)vParts ); - Vec_PtrFree( vOnePtr ); - - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); - - if ( Status == 1 ) - printf( "Networks are equivalent. \n" ); - else if ( Status == -1 ) - printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) ); - Abc_NtkDelete( pMiter ); -} - -/**Function************************************************************* - - Synopsis [Verifies sequential equivalence by brute-force SAT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkSecSat( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConfLimit, int nInsLimit, int nFrames ) -{ - extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); - Abc_Ntk_t * pMiter; - Abc_Ntk_t * pFrames; - Abc_Ntk_t * pCnf; - int RetValue; - - // get the miter of the two networks - pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 ); - if ( pMiter == NULL ) - { - printf( "Miter computation has failed.\n" ); - return; - } - RetValue = Abc_NtkMiterIsConstant( pMiter ); - if ( RetValue == 0 ) - { - Abc_NtkDelete( pMiter ); - printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); - return; - } - if ( RetValue == 1 ) - { - Abc_NtkDelete( pMiter ); - printf( "Networks are equivalent after structural hashing.\n" ); - return; - } - - // create the timeframes - pFrames = Abc_NtkFrames( pMiter, nFrames, 1 ); - Abc_NtkDelete( pMiter ); - if ( pFrames == NULL ) - { - printf( "Frames computation has failed.\n" ); - return; - } - RetValue = Abc_NtkMiterIsConstant( pFrames ); - if ( RetValue == 0 ) - { - Abc_NtkDelete( pFrames ); - printf( "Networks are NOT EQUIVALENT after framing.\n" ); - return; - } - if ( RetValue == 1 ) - { - Abc_NtkDelete( pFrames ); - printf( "Networks are equivalent after framing.\n" ); - return; - } - - // convert the miter into a CNF - pCnf = Abc_NtkMulti( pFrames, 0, 100, 1, 0, 0, 0 ); - Abc_NtkDelete( pFrames ); - if ( pCnf == NULL ) - { - printf( "Renoding for CNF has failed.\n" ); - return; - } - - // solve the CNF using the SAT solver - RetValue = Abc_NtkMiterSat( pCnf, (sint64)nConfLimit, (sint64)nInsLimit, 0, NULL, NULL ); - if ( RetValue == -1 ) - printf( "Networks are undecided (SAT solver timed out).\n" ); - else if ( RetValue == 0 ) - printf( "Networks are NOT EQUIVALENT after SAT.\n" ); - else - printf( "Networks are equivalent after SAT.\n" ); - Abc_NtkDelete( pCnf ); -} - -/**Function************************************************************* - - Synopsis [Verifies combinational equivalence by fraiging followed by SAT] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ) -{ - Fraig_Params_t Params; - Fraig_Man_t * pMan; - Abc_Ntk_t * pMiter; - Abc_Ntk_t * pFrames; - int RetValue; - - // get the miter of the two networks - pMiter = Abc_NtkMiter( pNtk1, pNtk2, 0, 0 ); - if ( pMiter == NULL ) - { - printf( "Miter computation has failed.\n" ); - return 0; - } - RetValue = Abc_NtkMiterIsConstant( pMiter ); - if ( RetValue == 0 ) - { - printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); - // report the error - pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, nFrames ); - Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pMiter->pModel, nFrames ); - FREE( pMiter->pModel ); - Abc_NtkDelete( pMiter ); - return 0; - } - if ( RetValue == 1 ) - { - Abc_NtkDelete( pMiter ); - printf( "Networks are equivalent after structural hashing.\n" ); - return 1; - } - - // create the timeframes - pFrames = Abc_NtkFrames( pMiter, nFrames, 1 ); - Abc_NtkDelete( pMiter ); - if ( pFrames == NULL ) - { - printf( "Frames computation has failed.\n" ); - return 0; - } - RetValue = Abc_NtkMiterIsConstant( pFrames ); - if ( RetValue == 0 ) - { - printf( "Networks are NOT EQUIVALENT after framing.\n" ); - // report the error - pFrames->pModel = Abc_NtkVerifyGetCleanModel( pFrames, 1 ); -// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, pFrames->pModel, nFrames ); - FREE( pFrames->pModel ); - Abc_NtkDelete( pFrames ); - return 0; - } - if ( RetValue == 1 ) - { - Abc_NtkDelete( pFrames ); - printf( "Networks are equivalent after framing.\n" ); - return 1; - } - - // convert the miter into a FRAIG - Fraig_ParamsSetDefault( &Params ); - Params.fVerbose = fVerbose; - Params.nSeconds = nSeconds; -// Params.fFuncRed = 0; -// Params.nPatsRand = 0; -// Params.nPatsDyna = 0; - pMan = Abc_NtkToFraig( pFrames, &Params, 0, 0 ); - Fraig_ManProveMiter( pMan ); - - // analyze the result - RetValue = Fraig_ManCheckMiter( pMan ); - // report the result - if ( RetValue == -1 ) - printf( "Networks are undecided (SAT solver timed out on the final miter).\n" ); - else if ( RetValue == 1 ) - printf( "Networks are equivalent after fraiging.\n" ); - else if ( RetValue == 0 ) - { - printf( "Networks are NOT EQUIVALENT after fraiging.\n" ); -// Abc_NtkVerifyReportErrorSeq( pNtk1, pNtk2, Fraig_ManReadModel(pMan), nFrames ); - } - else assert( 0 ); - // delete the fraig manager - Fraig_ManFree( pMan ); - // delete the miter - Abc_NtkDelete( pFrames ); - return RetValue == 1; -} - -/**Function************************************************************* - - Synopsis [Returns a dummy pattern full of zeros.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames ) -{ - int * pModel = ALLOC( int, Abc_NtkCiNum(pNtk) * nFrames ); - memset( pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) * nFrames ); - return pModel; -} - -/**Function************************************************************* - - Synopsis [Returns the PO values under the given input pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel ) -{ - Abc_Obj_t * pNode; - int * pValues, Value0, Value1, i; - int fStrashed = 0; - if ( !Abc_NtkIsStrash(pNtk) ) - { - pNtk = Abc_NtkStrash(pNtk, 0, 0, 0); - fStrashed = 1; - } -/* - printf( "Counter example: " ); - Abc_NtkForEachCi( pNtk, pNode, i ) - printf( " %d", pModel[i] ); - printf( "\n" ); -*/ - // increment the trav ID - Abc_NtkIncrementTravId( pNtk ); - // set the CI values - Abc_AigConst1(pNtk)->pCopy = (void *)1; - Abc_NtkForEachCi( pNtk, pNode, i ) - pNode->pCopy = (void *)pModel[i]; - // simulate in the topological order - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Value0 = ((int)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode); - Value1 = ((int)Abc_ObjFanin1(pNode)->pCopy) ^ Abc_ObjFaninC1(pNode); - pNode->pCopy = (void *)(Value0 & Value1); - } - // fill the output values - pValues = ALLOC( int, Abc_NtkCoNum(pNtk) ); - Abc_NtkForEachCo( pNtk, pNode, i ) - pValues[i] = ((int)Abc_ObjFanin0(pNode)->pCopy) ^ Abc_ObjFaninC0(pNode); - if ( fStrashed ) - Abc_NtkDelete( pNtk ); - return pValues; -} - - -/**Function************************************************************* - - Synopsis [Reports mismatch between the two networks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkVerifyReportError( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNode; - int * pValues1, * pValues2; - int nErrors, nPrinted, i, iNode = -1; - - assert( Abc_NtkCiNum(pNtk1) == Abc_NtkCiNum(pNtk2) ); - assert( Abc_NtkCoNum(pNtk1) == Abc_NtkCoNum(pNtk2) ); - // get the CO values under this model - pValues1 = Abc_NtkVerifySimulatePattern( pNtk1, pModel ); - pValues2 = Abc_NtkVerifySimulatePattern( pNtk2, pModel ); - // count the mismatches - nErrors = 0; - for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) - nErrors += (int)( pValues1[i] != pValues2[i] ); - printf( "Verification failed for at least %d outputs: ", nErrors ); - // print the first 3 outputs - nPrinted = 0; - for ( i = 0; i < Abc_NtkCoNum(pNtk1); i++ ) - if ( pValues1[i] != pValues2[i] ) - { - if ( iNode == -1 ) - iNode = i; - printf( " %s", Abc_ObjName(Abc_NtkCo(pNtk1,i)) ); - if ( ++nPrinted == 3 ) - break; - } - if ( nPrinted != nErrors ) - printf( " ..." ); - printf( "\n" ); - // report mismatch for the first output - if ( iNode >= 0 ) - { - printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", - Abc_ObjName(Abc_NtkCo(pNtk1,iNode)), pValues1[iNode], pValues2[iNode] ); - printf( "Input pattern: " ); - // collect PIs in the cone - pNode = Abc_NtkCo(pNtk1,iNode); - vNodes = Abc_NtkNodeSupport( pNtk1, &pNode, 1 ); - // set the PI numbers - Abc_NtkForEachCi( pNtk1, pNode, i ) - pNode->pCopy = (void*)i; - // print the model - pNode = Vec_PtrEntry( vNodes, 0 ); - if ( Abc_ObjIsCi(pNode) ) - { - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - assert( Abc_ObjIsCi(pNode) ); - printf( " %s=%d", Abc_ObjName(pNode), pModel[(int)pNode->pCopy] ); - } - } - printf( "\n" ); - Vec_PtrFree( vNodes ); - } - free( pValues1 ); - free( pValues2 ); -} - - -/**Function************************************************************* - - Synopsis [Computes the COs in the support of the PO in the given frame.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkGetSeqPoSupp( Abc_Ntk_t * pNtk, int iFrame, int iNumPo ) -{ - Abc_Ntk_t * pFrames; - Abc_Obj_t * pObj, * pNodePo; - Vec_Ptr_t * vSupp; - int i, k; - // get the timeframes of the network - pFrames = Abc_NtkFrames( pNtk, iFrame + 1, 0 ); -//Abc_NtkShowAig( pFrames ); - - // get the PO of the timeframes - pNodePo = Abc_NtkPo( pFrames, iFrame * Abc_NtkPoNum(pNtk) + iNumPo ); - // set the support - vSupp = Abc_NtkNodeSupport( pFrames, &pNodePo, 1 ); - // mark the support of the frames - Abc_NtkForEachCi( pFrames, pObj, i ) - pObj->pCopy = NULL; - Vec_PtrForEachEntry( vSupp, pObj, i ) - pObj->pCopy = (void *)1; - // mark the support of the network if the support of the timeframes is marked - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pCopy = NULL; - Abc_NtkForEachLatch( pNtk, pObj, i ) - if ( Abc_NtkBox(pFrames, i)->pCopy ) - pObj->pCopy = (void *)1; - Abc_NtkForEachPi( pNtk, pObj, i ) - for ( k = 0; k <= iFrame; k++ ) - if ( Abc_NtkPi(pFrames, k*Abc_NtkPiNum(pNtk) + i)->pCopy ) - pObj->pCopy = (void *)1; - // free stuff - Vec_PtrFree( vSupp ); - Abc_NtkDelete( pFrames ); -} - -/**Function************************************************************* - - Synopsis [Reports mismatch between the two sequential networks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkVerifyReportErrorSeq( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int * pModel, int nFrames ) -{ - Vec_Ptr_t * vInfo1, * vInfo2; - Abc_Obj_t * pObj, * pObjError, * pObj1, * pObj2; - int ValueError1, ValueError2; - unsigned * pPats1, * pPats2; - int i, o, k, nErrors, iFrameError, iNodePo, nPrinted; - int fRemove1 = 0, fRemove2 = 0; - - if ( !Abc_NtkIsStrash(pNtk1) ) - fRemove1 = 1, pNtk1 = Abc_NtkStrash( pNtk1, 0, 0, 0 ); - if ( !Abc_NtkIsStrash(pNtk2) ) - fRemove2 = 1, pNtk2 = Abc_NtkStrash( pNtk2, 0, 0, 0 ); - - // simulate sequential circuits - vInfo1 = Sim_SimulateSeqModel( pNtk1, nFrames, pModel ); - vInfo2 = Sim_SimulateSeqModel( pNtk2, nFrames, pModel ); - - // look for a discrepancy in the PO values - nErrors = 0; - pObjError = NULL; - for ( i = 0; i < nFrames; i++ ) - { - if ( pObjError ) - break; - Abc_NtkForEachPo( pNtk1, pObj1, o ) - { - pObj2 = Abc_NtkPo( pNtk2, o ); - pPats1 = Sim_SimInfoGet(vInfo1, pObj1); - pPats2 = Sim_SimInfoGet(vInfo2, pObj2); - if ( pPats1[i] == pPats2[i] ) - continue; - nErrors++; - if ( pObjError == NULL ) - { - pObjError = pObj1; - iFrameError = i; - iNodePo = o; - ValueError1 = (pPats1[i] > 0); - ValueError2 = (pPats2[i] > 0); - } - } - } - - if ( pObjError == NULL ) - { - printf( "No output mismatches detected.\n" ); - Sim_UtilInfoFree( vInfo1 ); - Sim_UtilInfoFree( vInfo2 ); - if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); - if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); - return; - } - - printf( "Verification failed for at least %d output%s of frame %d: ", nErrors, (nErrors>1? "s":""), iFrameError+1 ); - // print the first 3 outputs - nPrinted = 0; - Abc_NtkForEachPo( pNtk1, pObj1, o ) - { - pObj2 = Abc_NtkPo( pNtk2, o ); - pPats1 = Sim_SimInfoGet(vInfo1, pObj1); - pPats2 = Sim_SimInfoGet(vInfo2, pObj2); - if ( pPats1[iFrameError] == pPats2[iFrameError] ) - continue; - printf( " %s", Abc_ObjName(pObj1) ); - if ( ++nPrinted == 3 ) - break; - } - if ( nPrinted != nErrors ) - printf( " ..." ); - printf( "\n" ); - - // mark CIs of the networks in the cone of influence of this output - Abc_NtkGetSeqPoSupp( pNtk1, iFrameError, iNodePo ); - Abc_NtkGetSeqPoSupp( pNtk2, iFrameError, iNodePo ); - - // report mismatch for the first output - printf( "Output %s: Value in Network1 = %d. Value in Network2 = %d.\n", - Abc_ObjName(pObjError), ValueError1, ValueError2 ); - - printf( "The cone of influence of output %s in Network1:\n", Abc_ObjName(pObjError) ); - printf( "PIs: " ); - Abc_NtkForEachPi( pNtk1, pObj, i ) - if ( pObj->pCopy ) - printf( "%s ", Abc_ObjName(pObj) ); - printf( "\n" ); - printf( "Latches: " ); - Abc_NtkForEachLatch( pNtk1, pObj, i ) - if ( pObj->pCopy ) - printf( "%s ", Abc_ObjName(pObj) ); - printf( "\n" ); - - printf( "The cone of influence of output %s in Network2:\n", Abc_ObjName(pObjError) ); - printf( "PIs: " ); - Abc_NtkForEachPi( pNtk2, pObj, i ) - if ( pObj->pCopy ) - printf( "%s ", Abc_ObjName(pObj) ); - printf( "\n" ); - printf( "Latches: " ); - Abc_NtkForEachLatch( pNtk2, pObj, i ) - if ( pObj->pCopy ) - printf( "%s ", Abc_ObjName(pObj) ); - printf( "\n" ); - - // print the patterns - for ( i = 0; i <= iFrameError; i++ ) - { - printf( "Frame %d: ", i+1 ); - - printf( "PI(1):" ); - Abc_NtkForEachPi( pNtk1, pObj, k ) - if ( pObj->pCopy ) - printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 ); - printf( " " ); - printf( "L(1):" ); - Abc_NtkForEachLatch( pNtk1, pObj, k ) - if ( pObj->pCopy ) - printf( "%d", Sim_SimInfoGet(vInfo1, pObj)[i] > 0 ); - printf( " " ); - printf( "%s(1):", Abc_ObjName(pObjError) ); - printf( "%d", Sim_SimInfoGet(vInfo1, pObjError)[i] > 0 ); - - printf( " " ); - - printf( "PI(2):" ); - Abc_NtkForEachPi( pNtk2, pObj, k ) - if ( pObj->pCopy ) - printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 ); - printf( " " ); - printf( "L(2):" ); - Abc_NtkForEachLatch( pNtk2, pObj, k ) - if ( pObj->pCopy ) - printf( "%d", Sim_SimInfoGet(vInfo2, pObj)[i] > 0 ); - printf( " " ); - printf( "%s(2):", Abc_ObjName(pObjError) ); - printf( "%d", Sim_SimInfoGet(vInfo2, pObjError)[i] > 0 ); - - printf( "\n" ); - } - Abc_NtkForEachCi( pNtk1, pObj, i ) - pObj->pCopy = NULL; - Abc_NtkForEachCi( pNtk2, pObj, i ) - pObj->pCopy = NULL; - - Sim_UtilInfoFree( vInfo1 ); - Sim_UtilInfoFree( vInfo2 ); - if ( fRemove1 ) Abc_NtkDelete( pNtk1 ); - if ( fRemove2 ) Abc_NtkDelete( pNtk2 ); -} - -/**Function************************************************************* - - Synopsis [Simulates buggy miter emailed by Mike.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkSimulteBuggyMiter( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - int * pModel1, * pModel2, * pResult1, * pResult2; - char * vPiValues1 = "01001011100000000011010110101000000"; - char * vPiValues2 = "11001101011101011111110100100010001"; - - assert( strlen(vPiValues1) == (unsigned)Abc_NtkPiNum(pNtk) ); - assert( 1 == Abc_NtkPoNum(pNtk) ); - - pModel1 = ALLOC( int, Abc_NtkCiNum(pNtk) ); - Abc_NtkForEachPi( pNtk, pObj, i ) - pModel1[i] = vPiValues1[i] - '0'; - Abc_NtkForEachLatch( pNtk, pObj, i ) - pModel1[Abc_NtkPiNum(pNtk)+i] = ((int)pObj->pData) - 1; - - pResult1 = Abc_NtkVerifySimulatePattern( pNtk, pModel1 ); - printf( "Value = %d\n", pResult1[0] ); - - pModel2 = ALLOC( int, Abc_NtkCiNum(pNtk) ); - Abc_NtkForEachPi( pNtk, pObj, i ) - pModel2[i] = vPiValues2[i] - '0'; - Abc_NtkForEachLatch( pNtk, pObj, i ) - pModel2[Abc_NtkPiNum(pNtk)+i] = pResult1[Abc_NtkPoNum(pNtk)+i]; - - pResult2 = Abc_NtkVerifySimulatePattern( pNtk, pModel2 ); - printf( "Value = %d\n", pResult2[0] ); - - free( pModel1 ); - free( pModel2 ); - free( pResult1 ); - free( pResult2 ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abcXsim.c b/src/base/abci/abcXsim.c deleted file mode 100644 index 5d9e4634..00000000 --- a/src/base/abci/abcXsim.c +++ /dev/null @@ -1,227 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcXsim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Using X-valued simulation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcXsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define XVS0 ABC_INIT_ZERO -#define XVS1 ABC_INIT_ONE -#define XVSX ABC_INIT_DC - -static inline void Abc_ObjSetXsim( Abc_Obj_t * pObj, int Value ) { pObj->pCopy = (void *)Value; } -static inline int Abc_ObjGetXsim( Abc_Obj_t * pObj ) { return (int)pObj->pCopy; } -static inline int Abc_XsimInv( int Value ) -{ - if ( Value == XVS0 ) - return XVS1; - if ( Value == XVS1 ) - return XVS0; - assert( Value == XVSX ); - return XVSX; -} -static inline int Abc_XsimAnd( int Value0, int Value1 ) -{ - if ( Value0 == XVS0 || Value1 == XVS0 ) - return XVS0; - if ( Value0 == XVSX || Value1 == XVSX ) - return XVSX; - assert( Value0 == XVS1 && Value1 == XVS1 ); - return XVS1; -} -static inline int Abc_XsimRand2() -{ - return (rand() & 1) ? XVS1 : XVS0; -} -static inline int Abc_XsimRand3() -{ - int RetValue; - do { - RetValue = rand() & 3; - } while ( RetValue == 0 ); - return RetValue; -} -static inline int Abc_ObjGetXsimFanin0( Abc_Obj_t * pObj ) -{ - int RetValue; - RetValue = Abc_ObjGetXsim(Abc_ObjFanin0(pObj)); - return Abc_ObjFaninC0(pObj)? Abc_XsimInv(RetValue) : RetValue; -} -static inline int Abc_ObjGetXsimFanin1( Abc_Obj_t * pObj ) -{ - int RetValue; - RetValue = Abc_ObjGetXsim(Abc_ObjFanin1(pObj)); - return Abc_ObjFaninC1(pObj)? Abc_XsimInv(RetValue) : RetValue; -} -static inline void Abc_XsimPrint( FILE * pFile, int Value ) -{ - if ( Value == XVS0 ) - { - fprintf( pFile, "0" ); - return; - } - if ( Value == XVS1 ) - { - fprintf( pFile, "1" ); - return; - } - assert( Value == XVSX ); - fprintf( pFile, "x" ); -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs X-valued simulation of the sequential network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fXInputs, int fXState, int fVerbose ) -{ - Abc_Obj_t * pObj; - int i, f; - assert( Abc_NtkIsStrash(pNtk) ); - srand( 0x12341234 ); - // start simulation - Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); - if ( fXInputs ) - { - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjSetXsim( pObj, XVSX ); - } - else - { - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); - } - if ( fXState ) - { - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_ObjSetXsim( Abc_ObjFanout0(pObj), XVSX ); - } - else - { - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) ); - } - // simulate and print the result - fprintf( stdout, "Frame : Inputs : Latches : Outputs\n" ); - for ( f = 0; f < nFrames; f++ ) - { - Abc_AigForEachAnd( pNtk, pObj, i ) - Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); - // print out - fprintf( stdout, "%2d : ", f ); - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); - fprintf( stdout, " : " ); - Abc_NtkForEachLatch( pNtk, pObj, i ) - { -// if ( Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) != XVSX ) -// printf( " %s=", Abc_ObjName(pObj) ); - Abc_XsimPrint( stdout, Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) ); - } - fprintf( stdout, " : " ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); - if ( Abc_NtkAssertNum(pNtk) ) - { - fprintf( stdout, " : " ); - Abc_NtkForEachAssert( pNtk, pObj, i ) - Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); - } - fprintf( stdout, "\n" ); - // assign input values - if ( fXInputs ) - { - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjSetXsim( pObj, XVSX ); - } - else - { - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); - } - // transfer the latch values - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); - } -} - -/**Function************************************************************* - - Synopsis [Cycles the circuit to create a new initial state.] - - Description [Simulates the circuit with random input for the given - number of timeframes to get a better initial state.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ) -{ - Abc_Obj_t * pObj; - int i, f; - assert( Abc_NtkIsStrash(pNtk) ); - srand( 0x12341234 ); - // initialize the values - Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchIsInit1(pObj)? XVS1 : XVS0 ); - // simulate for the given number of timeframes - for ( f = 0; f < nFrames; f++ ) - { - Abc_AigForEachAnd( pNtk, pObj, i ) - Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); - Abc_NtkForEachCo( pNtk, pObj, i ) - Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); - // assign input values - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); - // transfer the latch values - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); - } - // set the final values - Abc_NtkForEachLatch( pNtk, pObj, i ) - pObj->pData = (void *)Abc_ObjGetXsim(Abc_ObjFanout0(pObj)); -} - -/////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abc_.c b/src/base/abci/abc_.c deleted file mode 100644 index 75ec88c3..00000000 --- a/src/base/abci/abc_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [abc_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/abci/abc_new.h b/src/base/abci/abc_new.h deleted file mode 100644 index 3460bb38..00000000 --- a/src/base/abci/abc_new.h +++ /dev/null @@ -1,23 +0,0 @@ -struct Abc_Obj_t_ // 6 words -{ - Abc_Obj_t * pCopy; // the copy of this object - Abc_Ntk_t * pNtk; // the host network - int Id; // the object ID - int TravId; // the traversal ID - int nRefs; // the number of fanouts - unsigned Type : 4; // the object type - unsigned fMarkA : 1; // the multipurpose mark - unsigned fMarkB : 1; // the multipurpose mark - unsigned fPhase : 1; // the flag to mark the phase of equivalent node - unsigned fPersist: 1; // marks the persistant AIG node - unsigned nFanins : 24; // the level of the node - Abc_Obj_t * Fanins[0]; // the array of fanins -}; - -struct Abc_Pin_t_ // 4 words -{ - Abc_Pin_t * pNext; - Abc_Pin_t * pPrev; - Abc_Obj_t * pFanin; - Abc_Obj_t * pFanout; -}; diff --git a/src/base/abci/module.make b/src/base/abci/module.make deleted file mode 100644 index f6c73102..00000000 --- a/src/base/abci/module.make +++ /dev/null @@ -1,55 +0,0 @@ -SRC += src/base/abci/abc.c \ - src/base/abci/abcAttach.c \ - src/base/abci/abcAuto.c \ - src/base/abci/abcBalance.c \ - src/base/abci/abcBmc.c \ - src/base/abci/abcCas.c \ - src/base/abci/abcClpBdd.c \ - src/base/abci/abcClpSop.c \ - src/base/abci/abcCut.c \ - src/base/abci/abcDar.c \ - src/base/abci/abcDebug.c \ - src/base/abci/abcDress.c \ - src/base/abci/abcDsd.c \ - src/base/abci/abcEspresso.c \ - src/base/abci/abcExtract.c \ - src/base/abci/abcFpga.c \ - src/base/abci/abcFpgaFast.c \ - src/base/abci/abcFraig.c \ - src/base/abci/abcFxu.c \ - src/base/abci/abcGen.c \ - src/base/abci/abcHaig.c \ - src/base/abci/abcIf.c \ - src/base/abci/abcIvy.c \ - src/base/abci/abcLut.c \ - src/base/abci/abcMap.c \ - src/base/abci/abcMini.c \ - src/base/abci/abcMiter.c \ - src/base/abci/abcMulti.c \ - src/base/abci/abcNtbdd.c \ - src/base/abci/abcOdc.c \ - src/base/abci/abcOrder.c \ - src/base/abci/abcPart.c \ - src/base/abci/abcPlace.c \ - src/base/abci/abcPrint.c \ - src/base/abci/abcProve.c \ - src/base/abci/abcQbf.c \ - src/base/abci/abcQuant.c \ - src/base/abci/abcRec.c \ - src/base/abci/abcReconv.c \ - src/base/abci/abcRefactor.c \ - src/base/abci/abcRenode.c \ - src/base/abci/abcReorder.c \ - src/base/abci/abcRestruct.c \ - src/base/abci/abcResub.c \ - src/base/abci/abcRewrite.c \ - src/base/abci/abcRr.c \ - src/base/abci/abcSat.c \ - src/base/abci/abcStrash.c \ - src/base/abci/abcSweep.c \ - src/base/abci/abcSymm.c \ - src/base/abci/abcTiming.c \ - src/base/abci/abcUnate.c \ - src/base/abci/abcUnreach.c \ - src/base/abci/abcVerify.c \ - src/base/abci/abcXsim.c diff --git a/src/base/cmd/cmd.c b/src/base/cmd/cmd.c deleted file mode 100644 index 2dc03d5c..00000000 --- a/src/base/cmd/cmd.c +++ /dev/null @@ -1,1674 +0,0 @@ -/**CFile**************************************************************** - - FileName [cmd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Command file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cmd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifdef WIN32 -#include -#endif - -#include "mainInt.h" -#include "cmdInt.h" -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int CmdCommandTime ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandEcho ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandQuit ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandWhich ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandHistory ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandAlias ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandUnalias ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandHelp ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandSource ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandSetVariable ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandUnsetVariable ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandUndo ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandRecall ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandEmpty ( Abc_Frame_t * pAbc, int argc, char ** argv ); -#ifdef WIN32 -static int CmdCommandLs ( Abc_Frame_t * pAbc, int argc, char ** argv ); -#endif -static int CmdCommandSis ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandMvsis ( Abc_Frame_t * pAbc, int argc, char ** argv ); -static int CmdCommandCapo ( Abc_Frame_t * pAbc, int argc, char ** argv ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function******************************************************************** - - Synopsis [Initializes the command package.] - - SideEffects [Commands are added to the command table.] - - SeeAlso [Cmd_End] - -******************************************************************************/ -void Cmd_Init( Abc_Frame_t * pAbc ) -{ - pAbc->tCommands = st_init_table(strcmp, st_strhash); - pAbc->tAliases = st_init_table(strcmp, st_strhash); - pAbc->tFlags = st_init_table(strcmp, st_strhash); - pAbc->aHistory = Vec_PtrAlloc( 100 ); - - Cmd_CommandAdd( pAbc, "Basic", "time", CmdCommandTime, 0); - Cmd_CommandAdd( pAbc, "Basic", "echo", CmdCommandEcho, 0); - Cmd_CommandAdd( pAbc, "Basic", "quit", CmdCommandQuit, 0); - Cmd_CommandAdd( pAbc, "Basic", "history", CmdCommandHistory, 0); - Cmd_CommandAdd( pAbc, "Basic", "alias", CmdCommandAlias, 0); - Cmd_CommandAdd( pAbc, "Basic", "unalias", CmdCommandUnalias, 0); - Cmd_CommandAdd( pAbc, "Basic", "help", CmdCommandHelp, 0); - Cmd_CommandAdd( pAbc, "Basic", "source", CmdCommandSource, 0); - Cmd_CommandAdd( pAbc, "Basic", "set", CmdCommandSetVariable, 0); - Cmd_CommandAdd( pAbc, "Basic", "unset", CmdCommandUnsetVariable, 0); - Cmd_CommandAdd( pAbc, "Basic", "undo", CmdCommandUndo, 0); - Cmd_CommandAdd( pAbc, "Basic", "recall", CmdCommandRecall, 0); - Cmd_CommandAdd( pAbc, "Basic", "empty", CmdCommandEmpty, 0); -#ifdef WIN32 - Cmd_CommandAdd( pAbc, "Basic", "ls", CmdCommandLs, 0 ); -#endif - - Cmd_CommandAdd( pAbc, "Various", "sis", CmdCommandSis, 1); - Cmd_CommandAdd( pAbc, "Various", "mvsis", CmdCommandMvsis, 1); - Cmd_CommandAdd( pAbc, "Various", "capo", CmdCommandCapo, 0); -} - -/**Function******************************************************************** - - Synopsis [Ends the command package.] - - Description [Ends the command package. Tables are freed.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Cmd_End( Abc_Frame_t * pAbc ) -{ - st_generator * gen; - char * pKey, * pValue; - int i; - -// st_free_table( pAbc->tCommands, (void (*)()) 0, CmdCommandFree ); -// st_free_table( pAbc->tAliases, (void (*)()) 0, CmdCommandAliasFree ); -// st_free_table( pAbc->tFlags, free, free ); - - st_foreach_item( pAbc->tCommands, gen, (char **)&pKey, (char **)&pValue ) - CmdCommandFree( (Abc_Command *)pValue ); - st_free_table( pAbc->tCommands ); - - st_foreach_item( pAbc->tAliases, gen, (char **)&pKey, (char **)&pValue ) - CmdCommandAliasFree( (Abc_Alias *)pValue ); - st_free_table( pAbc->tAliases ); - - st_foreach_item( pAbc->tFlags, gen, (char **)&pKey, (char **)&pValue ) - free( pKey ), free( pValue ); - st_free_table( pAbc->tFlags ); - - for ( i = 0; i < pAbc->aHistory->nSize; i++ ) - free( pAbc->aHistory->pArray[i] ); - Vec_PtrFree( pAbc->aHistory ); -} - - - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandTime( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( argc != globalUtilOptind ) - { - goto usage; - } - - pAbc->TimeTotal += pAbc->TimeCommand; - fprintf( pAbc->Out, "elapse: %3.2f seconds, total: %3.2f seconds\n", - (float)pAbc->TimeCommand / CLOCKS_PER_SEC, (float)pAbc->TimeTotal / CLOCKS_PER_SEC ); -/* - { - FILE * pTable; - pTable = fopen( "runtimes.txt", "a+" ); - fprintf( pTable, "%4.2f\n", (float)pAbc->TimeCommand / CLOCKS_PER_SEC ); - fclose( pTable ); - } -*/ - pAbc->TimeCommand = 0; - return 0; - - usage: - fprintf( pAbc->Err, "usage: time [-h]\n" ); - fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); - return 1; -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandEcho( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - int i; - int c; - int n = 1; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "hn" ) ) != EOF ) - { - switch ( c ) - { - case 'n': - n = 0; - break; - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - for ( i = globalUtilOptind; i < argc; i++ ) - fprintf( pAbc->Out, "%s ", argv[i] ); - if ( n ) - fprintf( pAbc->Out, "\n" ); - else - fflush ( pAbc->Out ); - return 0; - - usage: - fprintf( pAbc->Err, "usage: echo [-h] string \n" ); - fprintf( pAbc->Err, " -n \t\tsuppress newline at the end\n" ); - fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); - return ( 1 ); -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandQuit( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "hs" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - break; - case 's': - return -2; - break; - default: - goto usage; - } - } - - if ( argc != globalUtilOptind ) - goto usage; - return -1; - - usage: - fprintf( pAbc->Err, "usage: quit [-h] [-s]\n" ); - fprintf( pAbc->Err, " -h print the command usage\n" ); - fprintf( pAbc->Err, - " -s frees all the memory before quitting\n" ); - return 1; -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandWhich( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - return 0; -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandHistory( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - int i, c, num, size; - - num = 20; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default : - goto usage; - } - } - if ( argc > 2 ) - goto usage; - - // get the number of commands to print - if ( argc == globalUtilOptind + 1 ) - num = atoi(argv[globalUtilOptind]); - // print the commands - size = pAbc->aHistory->nSize; - num = ( num < size ) ? num : size; - for ( i = size - num; i < size; i++ ) - fprintf( pAbc->Out, "%s", pAbc->aHistory->pArray[i] ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: history [-h] \n" ); - fprintf( pAbc->Err, " prints the latest command entered on the command line\n" ); - fprintf( pAbc->Err, " -h : print the command usage\n" ); - fprintf( pAbc->Err, "num : print the last num commands\n" ); - return ( 1 ); -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandAlias( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char *key, *value; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - - if ( argc == 1 ) - { - CmdPrintTable( pAbc->tAliases, 1 ); - return 0; - - } - else if ( argc == 2 ) - { - if ( st_lookup( pAbc->tAliases, argv[1], &value ) ) - CmdCommandAliasPrint( pAbc, ( Abc_Alias * ) value ); - return 0; - } - - // delete any existing alias - key = argv[1]; - if ( st_delete( pAbc->tAliases, &key, &value ) ) - CmdCommandAliasFree( ( Abc_Alias * ) value ); - CmdCommandAliasAdd( pAbc, argv[1], argc - 2, argv + 2 ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: alias [-h] [command [string]]\n" ); - fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); - return ( 1 ); -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandUnalias( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - int i; - char *key, *value; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - if ( argc < 2 ) - { - goto usage; - } - - for ( i = 1; i < argc; i++ ) - { - key = argv[i]; - if ( st_delete( pAbc->tAliases, &key, &value ) ) - { - CmdCommandAliasFree( ( Abc_Alias * ) value ); - } - } - return 0; - - usage: - fprintf( pAbc->Err, "usage: unalias [-h] alias_names\n" ); - fprintf( pAbc->Err, " -h \t\tprint the command usage\n" ); - return 1; -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandHelp( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - bool fPrintAll; - int c; - - fPrintAll = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) - { - switch ( c ) - { - case 'a': - case 'v': - fPrintAll ^= 1; - break; - break; - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - if ( argc != globalUtilOptind ) - goto usage; - - CmdCommandPrint( pAbc, fPrintAll ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: help [-a] [-h]\n" ); - fprintf( pAbc->Err, " prints the list of available commands by group\n" ); - fprintf( pAbc->Err, " -a toggle printing hidden commands [default = %s]\n", fPrintAll? "yes": "no" ); - fprintf( pAbc->Err, " -h print the command usage\n" ); - return 1; -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandSource( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - int c, echo, prompt, silent, interactive, quit_count, lp_count; - int status = 0; /* initialize so that lint doesn't complain */ - int lp_file_index, did_subst; - char *prompt_string, *real_filename, line[MAX_STR], *command; - FILE *fp; - - interactive = silent = prompt = echo = 0; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ipsxh" ) ) != EOF ) - { - switch ( c ) - { - case 'i': /* a hack to distinguish EOF from stdin */ - interactive = 1; - break; - case 'p': - prompt ^= 1; - break; - case 's': - silent ^= 1; - break; - case 'x': - echo ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - /* added to avoid core-dumping when no script file is specified */ - if ( argc == globalUtilOptind ) - { - goto usage; - } - - lp_file_index = globalUtilOptind; - lp_count = 0; - - /* - * FIX (Tom, 5/7/95): I'm not sure what the purpose of this outer do loop - * is. In particular, lp_file_index is never modified in the loop, so it - * looks it would just read the same file over again. Also, SIS had - * lp_count initialized to -1, and hence, any file sourced by SIS (if -l or - * -t options on "source" were used in SIS) would actually be executed - * twice. - */ - do - { - lp_count++; /* increment the loop counter */ - - fp = CmdFileOpen( pAbc, argv[lp_file_index], "r", &real_filename, silent ); - if ( fp == NULL ) - { - FREE( real_filename ); - return !silent; /* error return if not silent */ - } - - quit_count = 0; - do - { - if ( prompt ) - { - prompt_string = Cmd_FlagReadByName( pAbc, "prompt" ); - if ( prompt_string == NULL ) - prompt_string = "abc> "; - - } - else - { - prompt_string = NULL; - } - - /* clear errors -- e.g., EOF reached from stdin */ - clearerr( fp ); - - /* read another command line */ -// if (CmdFgetsFilec(line, MAX_STR, fp, prompt_string) == NULL) { -// Abc_UtilsPrintPrompt(prompt_string); -// fflush(stdout); - if ( fgets( line, MAX_STR, fp ) == NULL ) - { - if ( interactive ) - { - if ( quit_count++ < 5 ) - { - fprintf( pAbc->Err, "\nUse \"quit\" to leave ABC.\n" ); - continue; - } - status = -1; /* fake a 'quit' */ - } - else - { - status = 0; /* successful end of 'source' ; loop? */ - } - break; - } - quit_count = 0; - - if ( echo ) - { - fprintf( pAbc->Out, "abc - > %s", line ); - } - command = CmdHistorySubstitution( pAbc, line, &did_subst ); - if ( command == NULL ) - { - status = 1; - break; - } - if ( did_subst ) - { - if ( interactive ) - { - fprintf( pAbc->Out, "%s\n", command ); - } - } - if ( command != line ) - { - ( void ) strcpy( line, command ); - } - if ( interactive && *line != '\0' ) - { - Cmd_HistoryAddCommand( pAbc, Extra_UtilStrsav(line) ); - if ( pAbc->Hst != NULL ) - { - fprintf( pAbc->Hst, "%s\n", line ); - ( void ) fflush( pAbc->Hst ); - } - } - - status = Cmd_CommandExecute( pAbc, line ); - } - while ( status == 0 ); - - if ( fp != stdin ) - { - if ( status > 0 ) - { - fprintf( pAbc->Err, - "** cmd error: aborting 'source %s'\n", - real_filename ); - } - ( void ) fclose( fp ); - } - FREE( real_filename ); - - } - while ( ( status == 0 ) && ( lp_count <= 0 ) ); - - return status; - - usage: - fprintf( pAbc->Err, "usage: source [-psxh] \n" ); - fprintf( pAbc->Err, "\t-p supply prompt before reading each line [default = %s]\n", prompt? "yes": "no" ); - fprintf( pAbc->Err, "\t-s silently ignore nonexistant file [default = %s]\n", silent? "yes": "no" ); - fprintf( pAbc->Err, "\t-x echo each line as it is executed [default = %s]\n", echo? "yes": "no" ); - fprintf( pAbc->Err, "\t-h print the command usage\n" ); - return 1; -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandSetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char *flag_value, *key, *value; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc == 0 || argc > 3 ) - { - goto usage; - } - else if ( argc == 1 ) - { - CmdPrintTable( pAbc->tFlags, 0 ); - return 0; - } - else - { - key = argv[1]; - if ( st_delete( pAbc->tFlags, &key, &value ) ) - { - FREE( key ); - FREE( value ); - } - - flag_value = argc == 2 ? Extra_UtilStrsav( "" ) : Extra_UtilStrsav( argv[2] ); -// flag_value = argc == 2 ? NULL : Extra_UtilStrsav(argv[2]); - st_insert( pAbc->tFlags, Extra_UtilStrsav(argv[1]), flag_value ); - - if ( strcmp( argv[1], "abcout" ) == 0 ) - { - if ( pAbc->Out != stdout ) - fclose( pAbc->Out ); - if ( strcmp( flag_value, "" ) == 0 ) - flag_value = "-"; - pAbc->Out = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); - if ( pAbc->Out == NULL ) - pAbc->Out = stdout; -#if HAVE_SETVBUF - setvbuf( pAbc->Out, ( char * ) NULL, _IOLBF, 0 ); -#endif - } - if ( strcmp( argv[1], "abcerr" ) == 0 ) - { - if ( pAbc->Err != stderr ) - fclose( pAbc->Err ); - if ( strcmp( flag_value, "" ) == 0 ) - flag_value = "-"; - pAbc->Err = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); - if ( pAbc->Err == NULL ) - pAbc->Err = stderr; -#if HAVE_SETVBUF - setvbuf( pAbc->Err, ( char * ) NULL, _IOLBF, 0 ); -#endif - } - if ( strcmp( argv[1], "history" ) == 0 ) - { - if ( pAbc->Hst != NULL ) - fclose( pAbc->Hst ); - if ( strcmp( flag_value, "" ) == 0 ) - pAbc->Hst = NULL; - else - { - pAbc->Hst = CmdFileOpen( pAbc, flag_value, "w", NULL, 0 ); - if ( pAbc->Hst == NULL ) - pAbc->Hst = NULL; - } - } - return 0; - } - - usage: - fprintf( pAbc->Err, "usage: set [-h] \n" ); - fprintf( pAbc->Err, "\t sets the value of parameter \n" ); - fprintf( pAbc->Err, "\t-h : print the command usage\n" ); - return 1; - -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandUnsetVariable( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - int i; - char *key, *value; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - if ( argc < 2 ) - { - goto usage; - } - - for ( i = 1; i < argc; i++ ) - { - key = argv[i]; - if ( st_delete( pAbc->tFlags, &key, &value ) ) - { - FREE( key ); - FREE( value ); - } - } - return 0; - - - usage: - fprintf( pAbc->Err, "usage: unset [-h] \n" ); - fprintf( pAbc->Err, "\t removes the value of parameter \n" ); - fprintf( pAbc->Err, "\t-h : print the command usage\n" ); - return 1; -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - if ( pAbc->pNtkCur == NULL ) - { - fprintf( pAbc->Out, "Empty network.\n" ); - return 0; - } - - // if there are no arguments on the command line - // set the current network to be the network from the previous step - if ( argc == 1 ) - return CmdCommandRecall( pAbc, argc, argv ); - - fprintf( pAbc->Err, "usage: undo\n" ); - fprintf( pAbc->Err, " sets the current network to be the previously saved network\n" ); - return 1; - -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandRecall( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - Abc_Ntk_t * pNtk; - int iStep, iStepFound; - int nNetsToSave, c; - char * pValue; - int iStepStart, iStepStop; - - if ( pAbc->pNtkCur == NULL ) - { - fprintf( pAbc->Out, "Empty network.\n" ); - return 0; - } - - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - // get the number of networks to save - pValue = Cmd_FlagReadByName( pAbc, "savesteps" ); - // if the value of steps to save is not set, assume 1-level undo - if ( pValue == NULL ) - nNetsToSave = 1; - else - nNetsToSave = atoi(pValue); - - // if there are no arguments on the command line - // set the current network to be the network from the previous step - if ( argc == 1 ) - { - // get the previously saved network - pNtk = Abc_NtkBackup(pAbc->pNtkCur); - if ( pNtk == NULL ) - fprintf( pAbc->Out, "There is no previously saved network.\n" ); - else // set the current network to be the copy of the previous one - Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pNtk) ); - return 0; - } - if ( argc == 2 ) // the second argument is the number of the step to return to - { - // read the number of the step to return to - iStep = atoi(argv[1]); - // check whether it is reasonable - if ( iStep >= pAbc->nSteps ) - { - iStepStart = pAbc->nSteps - nNetsToSave; - if ( iStepStart <= 0 ) - iStepStart = 1; - iStepStop = pAbc->nSteps; - if ( iStepStop <= 0 ) - iStepStop = 1; - if ( iStepStart == iStepStop ) - fprintf( pAbc->Out, "Can only recall step %d.\n", iStepStop ); - else - fprintf( pAbc->Out, "Can only recall steps %d-%d.\n", iStepStart, iStepStop ); - } - else if ( iStep < 0 ) - fprintf( pAbc->Out, "Cannot recall step %d.\n", iStep ); - else if ( iStep == 0 ) - Abc_FrameDeleteAllNetworks( pAbc ); - else - { - // scroll backward through the list of networks - // to determine if such a network exist - iStepFound = 0; - for ( pNtk = pAbc->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk) ) - if ( (iStepFound = Abc_NtkStep(pNtk)) == iStep ) - break; - if ( pNtk == NULL ) - { - iStepStart = iStepFound; - if ( iStepStart <= 0 ) - iStepStart = 1; - iStepStop = pAbc->nSteps; - if ( iStepStop <= 0 ) - iStepStop = 1; - if ( iStepStart == iStepStop ) - fprintf( pAbc->Out, "Can only recall step %d.\n", iStepStop ); - else - fprintf( pAbc->Out, "Can only recall steps %d-%d.\n", iStepStart, iStepStop ); - } - else - Abc_FrameSetCurrentNetwork( pAbc, Abc_NtkDup(pNtk) ); - } - return 0; - } - -usage: - - fprintf( pAbc->Err, "usage: recall -h \n" ); - fprintf( pAbc->Err, " set the current network to be one of the previous networks\n" ); - fprintf( pAbc->Err, " : level to return to [default = previous]\n" ); - fprintf( pAbc->Err, " -h : print the command usage\n"); - return 1; -} - - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandEmpty( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - int c; - - if ( pAbc->pNtkCur == NULL ) - { - fprintf( pAbc->Out, "Empty network.\n" ); - return 0; - } - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - - Abc_FrameDeleteAllNetworks( pAbc ); - Abc_FrameRestart( pAbc ); - return 0; -usage: - - fprintf( pAbc->Err, "usage: empty [-h]\n" ); - fprintf( pAbc->Err, " removes all the currently stored networks\n" ); - fprintf( pAbc->Err, " -h : print the command usage\n"); - return 1; -} - - -#if 0 - -/**Function******************************************************************** - - Synopsis [Donald's version.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandUndo( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - Abc_Ntk_t * pNtkTemp; - int id, c; - - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - break; - default: - goto usage; - } - } - if (globalUtilOptind <= argc) { - pNtkTemp = pAbc->pNtk; - pAbc->pNtk = pAbc->pNtkSaved; - pAbc->pNtkSaved = pNtkTemp; - } - id = atoi(argv[globalUtilOptind]); - pNtkTemp = Cmd_HistoryGetSnapshot(pAbc, id); - if (!pNtkTemp) - fprintf( pAbc->Err, "Snapshot %d does not exist\n", id); - else - pAbc->pNtk = Abc_NtkDup(pNtkTemp, Abc_NtkMan(pNtkTemp)); - - return 0; -usage: - fprintf( pAbc->Err, "usage: undo\n" ); - fprintf( pAbc->Err, " swaps the current network and the backup network\n" ); - return 1; -} - -#endif - - -#ifdef WIN32 -/**Function************************************************************* - - Synopsis [Command to print the contents of the current directory (Windows).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -#include - -// these structures are defined in but are for some reason invisible -typedef unsigned long _fsize_t; // Could be 64 bits for Win32 - -struct _finddata_t { - unsigned attrib; - time_t time_create; // -1 for FAT file systems - time_t time_access; // -1 for FAT file systems - time_t time_write; - _fsize_t size; - char name[260]; -}; - -extern long _findfirst( char *filespec, struct _finddata_t *fileinfo ); -extern int _findnext( long handle, struct _finddata_t *fileinfo ); -extern int _findclose( long handle ); - -int CmdCommandLs( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - struct _finddata_t c_file; - long hFile; - int fLong = 0; - int fOnlyBLIF = 0; - char Buffer[25]; - int Counter = 0; - int fPrintedNewLine; - char c; - - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "lb") ) != EOF ) - { - switch (c) - { - case 'l': - fLong = 1; - break; - case 'b': - fOnlyBLIF = 1; - break; - default: - goto usage; - } - } - - // find first .mv file in current directory - if( (hFile = _findfirst( ((fOnlyBLIF)? "*.mv": "*.*"), &c_file )) == -1L ) - { - if ( fOnlyBLIF ) - fprintf( pAbc->Out, "No *.mv files in the current directory.\n" ); - else - fprintf( pAbc->Out, "No files in the current directory.\n" ); - } - else - { - if ( fLong ) - { - fprintf( pAbc->Out, " File Date Size | File Date Size \n" ); - fprintf( pAbc->Out, " ----------------------------------------------------------------------------- \n" ); - do - { - strcpy( Buffer, ctime( &(c_file.time_write) ) ); - Buffer[16] = 0; - fprintf( pAbc->Out, " %-17s %.24s%7ld", c_file.name, Buffer+4, c_file.size ); - if ( ++Counter % 2 == 0 ) - { - fprintf( pAbc->Out, "\n" ); - fPrintedNewLine = 1; - } - else - { - fprintf( pAbc->Out, " |" ); - fPrintedNewLine = 0; - } - } - while( _findnext( hFile, &c_file ) == 0 ); - } - else - { - do - { - fprintf( pAbc->Out, " %-18s", c_file.name ); - if ( ++Counter % 4 == 0 ) - { - fprintf( pAbc->Out, "\n" ); - fPrintedNewLine = 1; - } - else - { - fprintf( pAbc->Out, " " ); - fPrintedNewLine = 0; - } - } - while( _findnext( hFile, &c_file ) == 0 ); - } - if ( !fPrintedNewLine ) - fprintf( pAbc->Out, "\n" ); - _findclose( hFile ); - } - return 0; - -usage: - fprintf( pAbc->Err, "Usage: ls [-l] [-b]\n" ); - fprintf( pAbc->Err, " print the file names in the current directory\n" ); - fprintf( pAbc->Err, " -l : print in the long format [default = short]\n" ); - fprintf( pAbc->Err, " -b : print only .mv files [default = all]\n" ); - return 1; -} -#endif - - - -#ifdef WIN32 -#define unlink _unlink -#endif - -/**Function******************************************************************** - - Synopsis [Calls SIS internally.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandSis( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - FILE * pFile; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkNew, * pNetlist; - char * pNameWin = "sis.exe"; - char * pNameUnix = "sis"; - char Command[1000], Buffer[100]; - char * pSisName; - int i; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - goto usage; - } - - if ( strcmp( argv[0], "sis" ) != 0 ) - { - fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); - goto usage; - } - - if ( argc == 1 ) - goto usage; - if ( strcmp( argv[1], "-h" ) == 0 ) - goto usage; - if ( strcmp( argv[1], "-?" ) == 0 ) - goto usage; - - // get the names from the resource file - if ( Cmd_FlagReadByName(pAbc, "siswin") ) - pNameWin = Cmd_FlagReadByName(pAbc, "siswin"); - if ( Cmd_FlagReadByName(pAbc, "sisunix") ) - pNameUnix = Cmd_FlagReadByName(pAbc, "sisunix"); - - // check if SIS is available - if ( (pFile = fopen( pNameWin, "r" )) ) - pSisName = pNameWin; - else if ( (pFile = fopen( pNameUnix, "r" )) ) - pSisName = pNameUnix; - else if ( pFile == NULL ) - { - fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pNameWin, pNameUnix ); - goto usage; - } - fclose( pFile ); - - if ( Abc_NtkIsMappedLogic(pNtk) ) - { - Abc_NtkMapToSop(pNtk); - printf( "The current network is unmapped before calling SIS.\n" ); - } - - // write out the current network - if ( Abc_NtkIsLogic(pNtk) ) - Abc_NtkToSop(pNtk, 0); - pNetlist = Abc_NtkToNetlist(pNtk); - if ( pNetlist == NULL ) - { - fprintf( pErr, "Cannot produce the intermediate network.\n" ); - goto usage; - } - Io_WriteBlif( pNetlist, "_sis_in.blif", 1 ); - Abc_NtkDelete( pNetlist ); - - // create the file for sis - sprintf( Command, "%s -x -c ", pSisName ); - strcat ( Command, "\"" ); - strcat ( Command, "read_blif _sis_in.blif" ); - strcat ( Command, "; " ); - for ( i = 1; i < argc; i++ ) - { - sprintf( Buffer, " %s", argv[i] ); - strcat( Command, Buffer ); - } - strcat( Command, "; " ); - strcat( Command, "write_blif _sis_out.blif" ); - strcat( Command, "\"" ); - - // call SIS - if ( system( Command ) ) - { - fprintf( pErr, "The following command has returned non-zero exit status:\n" ); - fprintf( pErr, "\"%s\"\n", Command ); - unlink( "_sis_in.blif" ); - goto usage; - } - - // read in the SIS output - if ( (pFile = fopen( "_sis_out.blif", "r" )) == NULL ) - { - fprintf( pErr, "Cannot open SIS output file \"%s\".\n", "_sis_out.blif" ); - unlink( "_sis_in.blif" ); - goto usage; - } - fclose( pFile ); - - // set the new network - pNtkNew = Io_Read( "_sis_out.blif", IO_FILE_BLIF, 1 ); - // set the original spec of the new network - if ( pNtk->pSpec ) - { - FREE( pNtkNew->pSpec ); - pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); - - // remove temporary networks - unlink( "_sis_in.blif" ); - unlink( "_sis_out.blif" ); - return 0; - -usage: - fprintf( pErr, "\n" ); - fprintf( pErr, "Usage: sis [-h] \n"); - fprintf( pErr, " invokes SIS command for the current ABC network\n" ); - fprintf( pErr, " (the executable of SIS should be in the same directory)\n" ); - fprintf( pErr, " -h : print the command usage\n" ); - fprintf( pErr, " : a SIS command (or a semicolon-separated list of commands in quotes)\n" ); - fprintf( pErr, " Example 1: sis eliminate 0\n" ); - fprintf( pErr, " Example 2: sis \"ps; rd; fx; ps\"\n" ); - fprintf( pErr, " Example 3: sis source script.rugged\n" ); - return 1; // error exit -} - - -/**Function******************************************************************** - - Synopsis [Calls SIS internally.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandMvsis( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - FILE * pFile; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNtkNew, * pNetlist; - char Command[1000], Buffer[100]; - char * pNameWin = "mvsis.exe"; - char * pNameUnix = "mvsis"; - char * pMvsisName; - int i; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - goto usage; - } - - if ( strcmp( argv[0], "mvsis" ) != 0 ) - { - fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); - goto usage; - } - - if ( argc == 1 ) - goto usage; - if ( strcmp( argv[1], "-h" ) == 0 ) - goto usage; - if ( strcmp( argv[1], "-?" ) == 0 ) - goto usage; - - // get the names from the resource file - if ( Cmd_FlagReadByName(pAbc, "mvsiswin") ) - pNameWin = Cmd_FlagReadByName(pAbc, "mvsiswin"); - if ( Cmd_FlagReadByName(pAbc, "mvsisunix") ) - pNameUnix = Cmd_FlagReadByName(pAbc, "mvsisunix"); - - // check if MVSIS is available - if ( (pFile = fopen( pNameWin, "r" )) ) - pMvsisName = pNameWin; - else if ( (pFile = fopen( pNameUnix, "r" )) ) - pMvsisName = pNameUnix; - else if ( pFile == NULL ) - { - fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pNameWin, pNameUnix ); - goto usage; - } - fclose( pFile ); - - if ( Abc_NtkIsMappedLogic(pNtk) ) - { - Abc_NtkMapToSop(pNtk); - printf( "The current network is unmapped before calling MVSIS.\n" ); - } - - // write out the current network - if ( Abc_NtkIsLogic(pNtk) ) - Abc_NtkToSop(pNtk, 0); - pNetlist = Abc_NtkToNetlist(pNtk); - if ( pNetlist == NULL ) - { - fprintf( pErr, "Cannot produce the intermediate network.\n" ); - goto usage; - } - Io_WriteBlif( pNetlist, "_mvsis_in.blif", 1 ); - Abc_NtkDelete( pNetlist ); - - // create the file for MVSIS - sprintf( Command, "%s -x -c ", pMvsisName ); - strcat ( Command, "\"" ); - strcat ( Command, "read_blif _mvsis_in.blif" ); - strcat ( Command, "; " ); - for ( i = 1; i < argc; i++ ) - { - sprintf( Buffer, " %s", argv[i] ); - strcat( Command, Buffer ); - } - strcat( Command, "; " ); - strcat( Command, "write_blif _mvsis_out.blif" ); - strcat( Command, "\"" ); - - // call MVSIS - if ( system( Command ) ) - { - fprintf( pErr, "The following command has returned non-zero exit status:\n" ); - fprintf( pErr, "\"%s\"\n", Command ); - unlink( "_mvsis_in.blif" ); - goto usage; - } - - // read in the MVSIS output - if ( (pFile = fopen( "_mvsis_out.blif", "r" )) == NULL ) - { - fprintf( pErr, "Cannot open MVSIS output file \"%s\".\n", "_mvsis_out.blif" ); - unlink( "_mvsis_in.blif" ); - goto usage; - } - fclose( pFile ); - - // set the new network - pNtkNew = Io_Read( "_mvsis_out.blif", IO_FILE_BLIF, 1 ); - // set the original spec of the new network - if ( pNtk->pSpec ) - { - FREE( pNtkNew->pSpec ); - pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); - - // remove temporary networks - unlink( "_mvsis_in.blif" ); - unlink( "_mvsis_out.blif" ); - return 0; - -usage: - fprintf( pErr, "\n" ); - fprintf( pErr, "Usage: mvsis [-h] \n"); - fprintf( pErr, " invokes MVSIS command for the current ABC network\n" ); - fprintf( pErr, " (the executable of MVSIS should be in the same directory)\n" ); - fprintf( pErr, " -h : print the command usage\n" ); - fprintf( pErr, " : a MVSIS command (or a semicolon-separated list of commands in quotes)\n" ); - fprintf( pErr, " Example 1: mvsis fraig_sweep\n" ); - fprintf( pErr, " Example 2: mvsis \"ps; fxu; ps\"\n" ); - fprintf( pErr, " Example 3: mvsis source mvsis.rugged\n" ); - return 1; // error exit -} - - -/**Function******************************************************************** - - Synopsis [Calls Capo internally.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int CmdCommandCapo( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - FILE * pFile; - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk, * pNetlist; - char Command[1000], Buffer[100]; - char * pProgNameCapoWin = "capo.exe"; - char * pProgNameCapoUnix = "capo"; - char * pProgNameGnuplotWin = "wgnuplot.exe"; - char * pProgNameGnuplotUnix = "gnuplot"; - char * pProgNameCapo; - char * pProgNameGnuplot; - char * pPlotFileName; - int i; - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - goto usage; - } - - if ( strcmp( argv[0], "capo" ) != 0 ) - { - fprintf( pErr, "Wrong command: \"%s\".\n", argv[0] ); - goto usage; - } - - if ( argc > 1 ) - { - if ( strcmp( argv[1], "-h" ) == 0 ) - goto usage; - if ( strcmp( argv[1], "-?" ) == 0 ) - goto usage; - } - - // get the names from the resource file - if ( Cmd_FlagReadByName(pAbc, "capowin") ) - pProgNameCapoWin = Cmd_FlagReadByName(pAbc, "capowin"); - if ( Cmd_FlagReadByName(pAbc, "capounix") ) - pProgNameCapoUnix = Cmd_FlagReadByName(pAbc, "capounix"); - - // check if capo is available - if ( (pFile = fopen( pProgNameCapoWin, "r" )) ) - pProgNameCapo = pProgNameCapoWin; - else if ( (pFile = fopen( pProgNameCapoUnix, "r" )) ) - pProgNameCapo = pProgNameCapoUnix; - else if ( pFile == NULL ) - { - fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameCapoWin, pProgNameCapoUnix ); - goto usage; - } - fclose( pFile ); - - if ( Abc_NtkIsMappedLogic(pNtk) ) - { - Abc_NtkMapToSop(pNtk); - printf( "The current network is unmapped before calling Capo.\n" ); - } - - // write out the current network - if ( Abc_NtkIsLogic(pNtk) ) - Abc_NtkToSop(pNtk, 0); - pNetlist = Abc_NtkToNetlist(pNtk); - if ( pNetlist == NULL ) - { - fprintf( pErr, "Cannot produce the intermediate network.\n" ); - goto usage; - } - Io_WriteBlif( pNetlist, "_capo_in.blif", 1 ); - Abc_NtkDelete( pNetlist ); - - // create the file for Capo - sprintf( Command, "%s -f _capo_in.blif -log out.txt ", pProgNameCapo ); - pPlotFileName = NULL; - for ( i = 1; i < argc; i++ ) - { - sprintf( Buffer, " %s", argv[i] ); - strcat( Command, Buffer ); - if ( !strcmp( argv[i], "-plot" ) ) - pPlotFileName = argv[i+1]; - } - - // call Capo - if ( system( Command ) ) - { - fprintf( pErr, "The following command has returned non-zero exit status:\n" ); - fprintf( pErr, "\"%s\"\n", Command ); - unlink( "_capo_in.blif" ); - goto usage; - } - // remove temporary networks - unlink( "_capo_in.blif" ); - if ( pPlotFileName == NULL ) - return 0; - - // get the file name - sprintf( Buffer, "%s.plt", pPlotFileName ); - pPlotFileName = Buffer; - - // read in the Capo plotting output - if ( (pFile = fopen( pPlotFileName, "r" )) == NULL ) - { - fprintf( pErr, "Cannot open the plot file \"%s\".\n\n", pPlotFileName ); - goto usage; - } - fclose( pFile ); - - // get the names from the plotting software - if ( Cmd_FlagReadByName(pAbc, "gnuplotwin") ) - pProgNameGnuplotWin = Cmd_FlagReadByName(pAbc, "gnuplotwin"); - if ( Cmd_FlagReadByName(pAbc, "gnuplotunix") ) - pProgNameGnuplotUnix = Cmd_FlagReadByName(pAbc, "gnuplotunix"); - - // check if Gnuplot is available - if ( (pFile = fopen( pProgNameGnuplotWin, "r" )) ) - pProgNameGnuplot = pProgNameGnuplotWin; - else if ( (pFile = fopen( pProgNameGnuplotUnix, "r" )) ) - pProgNameGnuplot = pProgNameGnuplotUnix; - else if ( pFile == NULL ) - { - fprintf( pErr, "Cannot find \"%s\" or \"%s\" in the current directory.\n", pProgNameGnuplotWin, pProgNameGnuplotUnix ); - goto usage; - } - fclose( pFile ); - - // spawn the viewer -#ifdef WIN32 - if ( _spawnl( _P_NOWAIT, pProgNameGnuplot, pProgNameGnuplot, pPlotFileName, NULL ) == -1 ) - { - fprintf( stdout, "Cannot find \"%s\".\n", pProgNameGnuplot ); - goto usage; - } -#else - { - sprintf( Command, "%s %s ", pProgNameGnuplot, pPlotFileName ); - if ( system( Command ) == -1 ) - { - fprintf( stdout, "Cannot execute \"%s\".\n", Command ); - goto usage; - } - } -#endif - - // remove temporary networks -// unlink( pPlotFileName ); - return 0; - -usage: - fprintf( pErr, "\n" ); - fprintf( pErr, "Usage: capo [-h] \n"); - fprintf( pErr, " peforms placement of the current network using Capo\n" ); - fprintf( pErr, " a Capo binary should be present in the same directory\n" ); - fprintf( pErr, " (if plotting, the Gnuplot binary should also be present)\n" ); - fprintf( pErr, " -h : print the command usage\n" ); - fprintf( pErr, " : a Capo command\n" ); - fprintf( pErr, " Example 1: capo\n" ); - fprintf( pErr, " (performs placement with default options)\n" ); - fprintf( pErr, " Example 2: capo -AR -WS -save\n" ); - fprintf( pErr, " (specifies the aspect ratio [default = 1.0] and\n" ); - fprintf( pErr, " the whitespace percentage [0%%; 100%%) [default = 15%%])\n" ); - fprintf( pErr, " Example 3: capo -plot \n" ); - fprintf( pErr, " (produces and visualize it using Gnuplot)\n" ); - fprintf( pErr, " Example 4: capo -help\n" ); - fprintf( pErr, " (prints the default usage message of the Capo binary)\n" ); - fprintf( pErr, " Please refer to the Capo webpage for additional information:\n" ); - fprintf( pErr, " http://vlsicad.eecs.umich.edu/BK/PDtools/\n" ); - return 1; // error exit -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/cmd/cmd.h b/src/base/cmd/cmd.h deleted file mode 100644 index 030b77e8..00000000 --- a/src/base/cmd/cmd.h +++ /dev/null @@ -1,73 +0,0 @@ -/**CFile**************************************************************** - - FileName [cmd.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [External declarations of the command package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cmd.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CMD_H__ -#define __CMD_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct MvCommand Abc_Command; // one command -typedef struct MvAlias Abc_Alias; // one alias - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== cmd.c ===========================================================*/ -extern void Cmd_Init(); -extern void Cmd_End(); -/*=== cmdApi.c ========================================================*/ -extern void Cmd_CommandAdd( Abc_Frame_t * pAbc, char * sGroup, char * sName, void * pFunc, int fChanges ); -extern int Cmd_CommandExecute( Abc_Frame_t * pAbc, char * sCommand ); -/*=== cmdFlag.c ========================================================*/ -extern char * Cmd_FlagReadByName( Abc_Frame_t * pAbc, char * flag ); -extern void Cmd_FlagDeleteByName( Abc_Frame_t * pAbc, char * key ); -extern void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * value ); -/*=== cmdHist.c ========================================================*/ -extern void Cmd_HistoryAddCommand( Abc_Frame_t * pAbc, char * command ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/cmd/cmdAlias.c b/src/base/cmd/cmdAlias.c deleted file mode 100644 index 0ec3feea..00000000 --- a/src/base/cmd/cmdAlias.c +++ /dev/null @@ -1,120 +0,0 @@ -/**CFile**************************************************************** - - FileName [cmdAlias.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures dealing with aliases in the command package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cmdAlias.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cmdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** argv ) -{ - Abc_Alias * pAlias; - int fStatus, i; - - pAlias = ALLOC(Abc_Alias, 1); - pAlias->sName = Extra_UtilStrsav(sName); - pAlias->argc = argc; - pAlias->argv = ALLOC(char *, pAlias->argc); - for(i = 0; i < argc; i++) - pAlias->argv[i] = Extra_UtilStrsav(argv[i]); - fStatus = st_insert( pAbc->tAliases, pAlias->sName, (char *) pAlias ); - assert(!fStatus); -} - -/**Function******************************************************************** - - Synopsis [required] - - Description [optional] - - SideEffects [required] - - SeeAlso [optional] - -******************************************************************************/ -void CmdCommandAliasPrint( Abc_Frame_t * pAbc, Abc_Alias * pAlias ) -{ - int i; - fprintf(pAbc->Out, "%-15s", pAlias->sName); - for(i = 0; i < pAlias->argc; i++) - fprintf( pAbc->Out, " %s", pAlias->argv[i] ); - fprintf( pAbc->Out, "\n" ); -} - -/**Function******************************************************************** - - Synopsis [required] - - Description [optional] - - SideEffects [required] - - SeeAlso [optional] - -******************************************************************************/ -char * CmdCommandAliasLookup( Abc_Frame_t * pAbc, char * sCommand ) -{ - Abc_Alias * pAlias; - char * value; - if (!st_lookup( pAbc->tAliases, sCommand, &value)) - return sCommand; - pAlias = (Abc_Alias *) value; - return pAlias->argv[0]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void CmdCommandAliasFree( Abc_Alias * pAlias ) -{ - CmdFreeArgv( pAlias->argc, pAlias->argv ); - FREE(pAlias->sName); - FREE(pAlias); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/cmd/cmdApi.c b/src/base/cmd/cmdApi.c deleted file mode 100644 index 7167e22b..00000000 --- a/src/base/cmd/cmdApi.c +++ /dev/null @@ -1,104 +0,0 @@ -/**CFile**************************************************************** - - FileName [cmdApi.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [External procedures of the command package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cmdApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mainInt.h" -#include "cmdInt.h" -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cmd_CommandAdd( Abc_Frame_t * pAbc, char * sGroup, char * sName, void * pFunc, int fChanges ) -{ - char * key, * value; - Abc_Command * pCommand; - int fStatus; - - key = sName; - if ( st_delete( pAbc->tCommands, &key, &value ) ) - { - // delete existing definition for this command - fprintf( pAbc->Err, "Cmd warning: redefining '%s'\n", sName ); - CmdCommandFree( (Abc_Command *)value ); - } - - // create the new command - pCommand = ALLOC( Abc_Command, 1 ); - pCommand->sName = Extra_UtilStrsav( sName ); - pCommand->sGroup = Extra_UtilStrsav( sGroup ); - pCommand->pFunc = pFunc; - pCommand->fChange = fChanges; - fStatus = st_insert( pAbc->tCommands, sName, (char *)pCommand ); - assert( !fStatus ); // the command should not be in the table -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cmd_CommandExecute( Abc_Frame_t * pAbc, char * sCommand ) -{ - int fStatus = 0, argc, loop; - char * sCommandNext, **argv; - - if ( !pAbc->fAutoexac ) - Cmd_HistoryAddCommand(pAbc, sCommand); - sCommandNext = sCommand; - do - { - sCommandNext = CmdSplitLine( pAbc, sCommandNext, &argc, &argv ); - loop = 0; - fStatus = CmdApplyAlias( pAbc, &argc, &argv, &loop ); - if ( fStatus == 0 ) - fStatus = CmdCommandDispatch( pAbc, argc, argv ); - CmdFreeArgv( argc, argv ); - } - while ( fStatus == 0 && *sCommandNext != '\0' ); - return fStatus; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/cmd/cmdFlag.c b/src/base/cmd/cmdFlag.c deleted file mode 100644 index 993f2a49..00000000 --- a/src/base/cmd/cmdFlag.c +++ /dev/null @@ -1,104 +0,0 @@ -/**CFile**************************************************************** - - FileName [cmdFlag.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures working with flags.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cmdFlag.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mainInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function******************************************************************** - - Synopsis [Looks up value of flag in table of named values.] - - Description [The command parser maintains a table of named values. These - are manipulated using the 'set' and 'unset' commands. The value of the - named flag is returned, or NULL is returned if the flag has not been set.] - - SideEffects [] - -******************************************************************************/ -char * Cmd_FlagReadByName( Abc_Frame_t * pAbc, char * flag ) -{ - char * value; - if ( st_lookup(pAbc->tFlags, flag, &value) ) - return value; - return NULL; -} - - -/**Function******************************************************************** - - Synopsis [Updates a set value by calling instead of set command.] - - Description [Updates a set value by calling instead of set command.] - - SideEffects [] - -******************************************************************************/ -void Cmd_FlagUpdateValue( Abc_Frame_t * pAbc, char * key, char * value ) -{ - char * oldValue, * newValue; - if ( !key ) - return; - if ( value ) - newValue = Extra_UtilStrsav(value); - else - newValue = Extra_UtilStrsav(""); -// newValue = NULL; - if ( st_delete(pAbc->tFlags, &key, &oldValue) ) - FREE(oldValue); - st_insert( pAbc->tFlags, key, newValue ); -} - - -/**Function******************************************************************** - - Synopsis [Deletes a set value by calling instead of unset command.] - - Description [Deletes a set value by calling instead of unset command.] - - SideEffects [] - -******************************************************************************/ -void Cmd_FlagDeleteByName( Abc_Frame_t * pAbc, char * key ) -{ - char *value; - if ( !key ) - return; - if ( st_delete( pAbc->tFlags, &key, &value ) ) - { - FREE(key); - FREE(value); - } -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/cmd/cmdHist.c b/src/base/cmd/cmdHist.c deleted file mode 100644 index fae9382d..00000000 --- a/src/base/cmd/cmdHist.c +++ /dev/null @@ -1,55 +0,0 @@ -/**CFile**************************************************************** - - FileName [cmdHist.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures working with history.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cmdHist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mainInt.h" -#include "cmd.h" -#include "cmdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cmd_HistoryAddCommand( Abc_Frame_t * p, char * command ) -{ - static char Buffer[MAX_STR]; - strcpy( Buffer, command ); - if ( command[strlen(command)-1] != '\n' ) - strcat( Buffer, "\n" ); - Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/base/cmd/cmdInt.h b/src/base/cmd/cmdInt.h deleted file mode 100644 index c082bd94..00000000 --- a/src/base/cmd/cmdInt.h +++ /dev/null @@ -1,83 +0,0 @@ -/**CFile**************************************************************** - - FileName [cmdInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Internal declarations of the command package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cmdInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CMD_INT_H__ -#define __CMD_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "mainInt.h" -#include "cmd.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -struct MvCommand -{ - char * sName; // the command name - char * sGroup; // the group name - void * pFunc; // the function to execute the command - int fChange; // set to 1 to mark that the network is changed -}; - -struct MvAlias -{ - char * sName; // the alias name - int argc; // the number of alias parts - char ** argv; // the alias parts -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== cmdAlias.c =============-========================================*/ -extern void CmdCommandAliasAdd( Abc_Frame_t * pAbc, char * sName, int argc, char ** argv ); -extern void CmdCommandAliasPrint( Abc_Frame_t * pAbc, Abc_Alias * pAlias ); -extern char * CmdCommandAliasLookup( Abc_Frame_t * pAbc, char * sCommand ); -extern void CmdCommandAliasFree( Abc_Alias * p ); -/*=== cmdUtils.c =======================================================*/ -extern int CmdCommandDispatch( Abc_Frame_t * pAbc, int argc, char ** argv ); -extern char * CmdSplitLine( Abc_Frame_t * pAbc, char * sCommand, int * argc, char *** argv ); -extern int CmdApplyAlias( Abc_Frame_t * pAbc, int * argc, char *** argv, int * loop ); -extern char * CmdHistorySubstitution( Abc_Frame_t * pAbc, char * line, int * changed ); -extern FILE * CmdFileOpen( Abc_Frame_t * pAbc, char * sFileName, char * sMode, char ** pFileNameReal, int silent ); -extern void CmdFreeArgv( int argc, char ** argv ); -extern void CmdCommandFree( Abc_Command * pCommand ); -extern void CmdCommandPrint( Abc_Frame_t * pAbc, bool fPrintAll ); -extern void CmdPrintTable( st_table * tTable, int fAliases ); - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#endif - diff --git a/src/base/cmd/cmdUtils.c b/src/base/cmd/cmdUtils.c deleted file mode 100644 index 47e54bb3..00000000 --- a/src/base/cmd/cmdUtils.c +++ /dev/null @@ -1,649 +0,0 @@ -/**CFile**************************************************************** - - FileName [cmdUtils.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Various utilities of the command package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cmdUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mainInt.h" -#include "abc.h" -#include "cmdInt.h" -#include // proper declaration of isspace - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int cmdCheckShellEscape( Abc_Frame_t * pAbc, int argc, char ** argv) -{ - if (argv[0][0] == '!') - { - const int size = 4096; - int i; - char buffer[4096]; - strncpy (buffer, &argv[0][1], size); - for (i = 1; i < argc; ++i) - { - strncat (buffer, " ", size); - strncat (buffer, argv[i], size); - } - if (buffer[0] == 0) - strncpy (buffer, "/bin/sh", size); - system (buffer); - - // NOTE: Since we reconstruct the cmdline by concatenating - // the parts, we lose information. So a command like - // `!ls "file name"` will be sent to the system as - // `ls file name` which is a BUG - - return 1; - } - else - { - return 0; - } -} - -/**Function************************************************************* - - Synopsis [Executes one command.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int CmdCommandDispatch( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - Abc_Ntk_t * pNetCopy; - int (*pFunc) ( Abc_Frame_t *, int, char ** ); - Abc_Command * pCommand; - char * value; - int fError; - int clk; - - if ( argc == 0 ) - return 0; - - if ( cmdCheckShellEscape( pAbc, argc, argv ) == 1 ) - return 0; - - // get the command - if ( !st_lookup( pAbc->tCommands, argv[0], (char **)&pCommand ) ) - { // the command is not in the table - fprintf( pAbc->Err, "** cmd error: unknown command '%s'\n", argv[0] ); - return 1; - } - - // get the backup network if the command is going to change the network - if ( pCommand->fChange ) - { - if ( pAbc->pNtkCur && Abc_FrameIsFlagEnabled( "backup" ) ) - { - pNetCopy = Abc_NtkDup( pAbc->pNtkCur ); - Abc_FrameSetCurrentNetwork( pAbc, pNetCopy ); - // swap the current network and the backup network - // to prevent the effect of resetting the short names - Abc_FrameSwapCurrentAndBackup( pAbc ); - } - } - - // execute the command - clk = Extra_CpuTime(); - pFunc = (int (*)(Abc_Frame_t *, int, char **))pCommand->pFunc; - fError = (*pFunc)( pAbc, argc, argv ); - pAbc->TimeCommand += (Extra_CpuTime() - clk); - - // automatic execution of arbitrary command after each command - // usually this is a passive command ... - if ( fError == 0 && !pAbc->fAutoexac ) - { - if ( st_lookup( pAbc->tFlags, "autoexec", &value ) ) - { - pAbc->fAutoexac = 1; - fError = Cmd_CommandExecute( pAbc, value ); - pAbc->fAutoexac = 0; - } - } - return fError; -} - -/**Function************************************************************* - - Synopsis [Splits the command line string into individual commands.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * CmdSplitLine( Abc_Frame_t * pAbc, char *sCommand, int *argc, char ***argv ) -{ - char *p, *start, c; - int i, j; - char *new_arg; - Vec_Ptr_t * vArgs; - int single_quote, double_quote; - - vArgs = Vec_PtrAlloc( 10 ); - - p = sCommand; - for ( ;; ) - { - // skip leading white space - while ( isspace( ( int ) *p ) ) - { - p++; - } - - // skip until end of this token - single_quote = double_quote = 0; - for ( start = p; ( c = *p ) != '\0'; p++ ) - { - if ( c == ';' || c == '#' || isspace( ( int ) c ) ) - { - if ( !single_quote && !double_quote ) - { - break; - } - } - if ( c == '\'' ) - { - single_quote = !single_quote; - } - if ( c == '"' ) - { - double_quote = !double_quote; - } - } - if ( single_quote || double_quote ) - { - ( void ) fprintf( pAbc->Err, "** cmd warning: ignoring unbalanced quote ...\n" ); - } - if ( start == p ) - break; - - new_arg = ALLOC( char, p - start + 1 ); - j = 0; - for ( i = 0; i < p - start; i++ ) - { - c = start[i]; - if ( ( c != '\'' ) && ( c != '\"' ) ) - { - new_arg[j++] = isspace( ( int ) c ) ? ' ' : start[i]; - } - } - new_arg[j] = '\0'; - Vec_PtrPush( vArgs, new_arg ); - } - - *argc = vArgs->nSize; - *argv = (char **)Vec_PtrReleaseArray( vArgs ); - Vec_PtrFree( vArgs ); - if ( *p == ';' ) - { - p++; - } - else if ( *p == '#' ) - { - for ( ; *p != 0; p++ ); // skip to end of line - } - return p; -} - -/**Function************************************************************* - - Synopsis [Replaces parts of the command line string by aliases if given.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int CmdApplyAlias( Abc_Frame_t * pAbc, int *argcp, char ***argvp, int *loop ) -{ - int i, argc, stopit, added, offset, did_subst, subst, fError, newc, j; - char *arg, **argv, **newv; - Abc_Alias *alias; - - argc = *argcp; - argv = *argvp; - stopit = 0; - for ( ; *loop < 200; ( *loop )++ ) - { - if ( argc == 0 ) - return 0; - if ( stopit != 0 || st_lookup( pAbc->tAliases, argv[0], (char **) &alias ) == 0 ) - { - return 0; - } - if ( strcmp( argv[0], alias->argv[0] ) == 0 ) - { - stopit = 1; - } - FREE( argv[0] ); - added = alias->argc - 1; - - /* shift all the arguments to the right */ - if ( added != 0 ) - { - argv = REALLOC( char *, argv, argc + added ); - for ( i = argc - 1; i >= 1; i-- ) - { - argv[i + added] = argv[i]; - } - for ( i = 1; i <= added; i++ ) - { - argv[i] = NULL; - } - argc += added; - } - subst = 0; - for ( i = 0, offset = 0; i < alias->argc; i++, offset++ ) - { - arg = CmdHistorySubstitution( pAbc, alias->argv[i], &did_subst ); - if ( arg == NULL ) - { - *argcp = argc; - *argvp = argv; - return ( 1 ); - } - if ( did_subst != 0 ) - { - subst = 1; - } - fError = 0; - do - { - arg = CmdSplitLine( pAbc, arg, &newc, &newv ); - /* - * If there's a complete `;' terminated command in `arg', - * when split_line() returns arg[0] != '\0'. - */ - if ( arg[0] == '\0' ) - { /* just a bunch of words */ - break; - } - fError = CmdApplyAlias( pAbc, &newc, &newv, loop ); - if ( fError == 0 ) - { - fError = CmdCommandDispatch( pAbc, newc, newv ); - } - CmdFreeArgv( newc, newv ); - } - while ( fError == 0 ); - if ( fError != 0 ) - { - *argcp = argc; - *argvp = argv; - return ( 1 ); - } - added = newc - 1; - if ( added != 0 ) - { - argv = REALLOC( char *, argv, argc + added ); - for ( j = argc - 1; j > offset; j-- ) - { - argv[j + added] = argv[j]; - } - argc += added; - } - for ( j = 0; j <= added; j++ ) - { - argv[j + offset] = newv[j]; - } - FREE( newv ); - offset += added; - } - if ( subst == 1 ) - { - for ( i = offset; i < argc; i++ ) - { - FREE( argv[i] ); - } - argc = offset; - } - *argcp = argc; - *argvp = argv; - } - - fprintf( pAbc->Err, "** cmd warning: alias loop\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs history substitution (now, disabled).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * CmdHistorySubstitution( Abc_Frame_t * pAbc, char *line, int *changed ) -{ - // as of today, no history substitution - *changed = 0; - return line; -} - -/**Function************************************************************* - - Synopsis [Opens the file with path (now, disabled).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -FILE * CmdFileOpen( Abc_Frame_t * pAbc, char *sFileName, char *sMode, char **pFileNameReal, int silent ) -{ - char * sRealName, * sPathUsr, * sPathLib, * sPathAll; - FILE * pFile; - - if (strcmp(sFileName, "-") == 0) { - if (strcmp(sMode, "w") == 0) { - sRealName = Extra_UtilStrsav( "stdout" ); - pFile = stdout; - } - else { - sRealName = Extra_UtilStrsav( "stdin" ); - pFile = stdin; - } - } - else { - sRealName = NULL; - if (strcmp(sMode, "r") == 0) { - - /* combine both pathes if exist */ - sPathUsr = Cmd_FlagReadByName(pAbc,"open_path"); - sPathLib = Cmd_FlagReadByName(pAbc,"lib_path"); - - if ( sPathUsr == NULL && sPathLib == NULL ) { - sPathAll = NULL; - } - else if ( sPathUsr == NULL ) { - sPathAll = Extra_UtilStrsav( sPathLib ); - } - else if ( sPathLib == NULL ) { - sPathAll = Extra_UtilStrsav( sPathUsr ); - } - else { - sPathAll = ALLOC( char, strlen(sPathLib)+strlen(sPathUsr)+5 ); - sprintf( sPathAll, "%s:%s",sPathUsr, sPathLib ); - } - if ( sPathAll != NULL ) { - sRealName = Extra_UtilFileSearch(sFileName, sPathAll, "r"); - FREE( sPathAll ); - } - } - if (sRealName == NULL) { - sRealName = Extra_UtilTildeExpand(sFileName); - } - if ((pFile = fopen(sRealName, sMode)) == NULL) { - if (! silent) { - perror(sRealName); - } - } - } - if ( pFileNameReal ) - *pFileNameReal = sRealName; - else - FREE(sRealName); - - return pFile; -} - -/**Function************************************************************* - - Synopsis [Frees the previously allocated argv array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void CmdFreeArgv( int argc, char **argv ) -{ - int i; - for ( i = 0; i < argc; i++ ) - FREE( argv[i] ); - FREE( argv ); -} - -/**Function************************************************************* - - Synopsis [Frees the previously allocated command.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void CmdCommandFree( Abc_Command * pCommand ) -{ - free( pCommand->sGroup ); - free( pCommand->sName ); - free( pCommand ); -} - - -/**Function************************************************************* - - Synopsis [Prints commands alphabetically by group.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void CmdCommandPrint( Abc_Frame_t * pAbc, bool fPrintAll ) -{ - char *key, *value; - st_generator * gen; - Abc_Command ** ppCommands; - Abc_Command * pCommands; - int nCommands, i; - char * sGroupCur; - int LenghtMax, nColumns, iCom = 0; - - // put all commands into one array - nCommands = st_count( pAbc->tCommands ); - ppCommands = ALLOC( Abc_Command *, nCommands ); - i = 0; - st_foreach_item( pAbc->tCommands, gen, &key, &value ) - { - pCommands = (Abc_Command *)value; - if ( fPrintAll || pCommands->sName[0] != '_' ) - ppCommands[i++] = pCommands; - } - nCommands = i; - - // sort command by group and then by name, alphabetically - qsort( (void *)ppCommands, nCommands, sizeof(Abc_Command *), - (int (*)(const void *, const void *)) CmdCommandPrintCompare ); - assert( CmdCommandPrintCompare( ppCommands, ppCommands + nCommands - 1 ) <= 0 ); - - // get the longest command name - LenghtMax = 0; - for ( i = 0; i < nCommands; i++ ) - if ( LenghtMax < (int)strlen(ppCommands[i]->sName) ) - LenghtMax = (int)strlen(ppCommands[i]->sName); - // get the number of columns - nColumns = 79 / (LenghtMax + 2); - - // print the starting message - fprintf( pAbc->Out, " Welcome to ABC!" ); - - // print the command by group - sGroupCur = NULL; - for ( i = 0; i < nCommands; i++ ) - if ( sGroupCur && strcmp( sGroupCur, ppCommands[i]->sGroup ) == 0 ) - { // this command belongs to the same group as the previous one - if ( iCom++ % nColumns == 0 ) - fprintf( pAbc->Out, "\n" ); - // print this command - fprintf( pAbc->Out, " %-*s", LenghtMax, ppCommands[i]->sName ); - } - else - { // this command starts the new group of commands - // start the new group - fprintf( pAbc->Out, "\n" ); - fprintf( pAbc->Out, "\n" ); - fprintf( pAbc->Out, "%s commands:\n", ppCommands[i]->sGroup ); - // print this command - fprintf( pAbc->Out, " %-*s", LenghtMax, ppCommands[i]->sName ); - // remember current command group - sGroupCur = ppCommands[i]->sGroup; - // reset the command counter - iCom = 1; - } - fprintf( pAbc->Out, "\n" ); - FREE( ppCommands ); -} - -/**Function************************************************************* - - Synopsis [Comparision function used for sorting commands.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int CmdCommandPrintCompare( Abc_Command ** ppC1, Abc_Command ** ppC2 ) -{ - Abc_Command * pC1 = *ppC1; - Abc_Command * pC2 = *ppC2; - int RetValue; - - RetValue = strcmp( pC1->sGroup, pC2->sGroup ); - if ( RetValue < 0 ) - return -1; - if ( RetValue > 0 ) - return 1; - // the command belong to the same group - - // put commands with "_" at the end of the list - if ( pC1->sName[0] != '_' && pC2->sName[0] == '_' ) - return -1; - if ( pC1->sName[0] == '_' && pC2->sName[0] != '_' ) - return 1; - - RetValue = strcmp( pC1->sName, pC2->sName ); - if ( RetValue < 0 ) - return -1; - if ( RetValue > 0 ) - return 1; - // should not be two indentical commands - assert( 0 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Comparision function used for sorting commands.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int CmdNamePrintCompare( char ** ppC1, char ** ppC2 ) -{ - return strcmp( *ppC1, *ppC2 ); -} - -/**Function************************************************************* - - Synopsis [Comparision function used for sorting commands.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void CmdPrintTable( st_table * tTable, int fAliases ) -{ - st_generator * gen; - char ** ppNames; - char * key, * value; - int nNames, i; - - // collect keys in the array - ppNames = ALLOC( char *, st_count(tTable) ); - nNames = 0; - st_foreach_item( tTable, gen, &key, &value ) - ppNames[nNames++] = key; - - // sort array by name - qsort( (void *)ppNames, nNames, sizeof(char *), - (int (*)(const void *, const void *))CmdNamePrintCompare ); - - // print in this order - for ( i = 0; i < nNames; i++ ) - { - st_lookup( tTable, ppNames[i], &value ); - if ( fAliases ) - CmdCommandAliasPrint( Abc_FrameGetGlobalFrame(), (Abc_Alias *)value ); - else - fprintf( stdout, "%-15s %-15s\n", ppNames[i], value ); - } - free( ppNames ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/base/cmd/module.make b/src/base/cmd/module.make deleted file mode 100644 index 1eca3f65..00000000 --- a/src/base/cmd/module.make +++ /dev/null @@ -1,6 +0,0 @@ -SRC += src/base/cmd/cmd.c \ - src/base/cmd/cmdAlias.c \ - src/base/cmd/cmdApi.c \ - src/base/cmd/cmdFlag.c \ - src/base/cmd/cmdHist.c \ - src/base/cmd/cmdUtils.c diff --git a/src/base/func/funcBlifMv.c b/src/base/func/funcBlifMv.c deleted file mode 100644 index 0e395066..00000000 --- a/src/base/func/funcBlifMv.c +++ /dev/null @@ -1,62 +0,0 @@ -/**CFile**************************************************************** - - FileName [funcBlifMv.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Implementation of BLIF-MV representation of the nodes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: funcBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" - -/* - The BLIF-MV tables are represented using char * strings. - For example, the representation of the table - - .table c d0 d1 x - .default 0 - 0 - - =d0 - 1 - 1 1 - - is the string: "2 2 2 2\n0\n0 - - =1\n1 - 1 1\n" where '\n' is a single char. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Abc_ConvertBlifMvToAig( Hop_Man_t * pMan, char * pSop ) -{ -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/io.c b/src/base/io/io.c deleted file mode 100644 index ca4cab95..00000000 --- a/src/base/io/io.c +++ /dev/null @@ -1,1954 +0,0 @@ -/**CFile**************************************************************** - - FileName [io.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Command file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: io.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" -#include "mainInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int IoCommandRead ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadAiger ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadBench ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadDsd ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadEdif ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadInit ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadPla ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadTruth ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadVer ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandReadVerLib ( Abc_Frame_t * pAbc, int argc, char **argv ); - -static int IoCommandWrite ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteHie ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteAiger ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteBaf ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteBlif ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteBlifMv ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteBench ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteCnf ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteDot ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteEqn ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteGml ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteList ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWritePla ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ); -static int IoCommandWriteVerLib ( Abc_Frame_t * pAbc, int argc, char **argv ); - -extern int glo_fMapped; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_Init( Abc_Frame_t * pAbc ) -{ - Cmd_CommandAdd( pAbc, "I/O", "read", IoCommandRead, 1 ); - Cmd_CommandAdd( pAbc, "I/O", "read_aiger", IoCommandReadAiger, 1 ); - Cmd_CommandAdd( pAbc, "I/O", "read_baf", IoCommandReadBaf, 1 ); - Cmd_CommandAdd( pAbc, "I/O", "read_blif", IoCommandReadBlif, 1 ); - Cmd_CommandAdd( pAbc, "I/O", "read_blif_mv", IoCommandReadBlif, 1 ); - Cmd_CommandAdd( pAbc, "I/O", "read_bench", IoCommandReadBench, 1 ); - Cmd_CommandAdd( pAbc, "I/O", "read_dsd", IoCommandReadDsd, 1 ); -// Cmd_CommandAdd( pAbc, "I/O", "read_edif", IoCommandReadEdif, 1 ); - Cmd_CommandAdd( pAbc, "I/O", "read_eqn", IoCommandReadEqn, 1 ); - Cmd_CommandAdd( pAbc, "I/O", "read_init", IoCommandReadInit, 1 ); - Cmd_CommandAdd( pAbc, "I/O", "read_pla", IoCommandReadPla, 1 ); - Cmd_CommandAdd( pAbc, "I/O", "read_truth", IoCommandReadTruth, 1 ); - Cmd_CommandAdd( pAbc, "I/O", "read_verilog", IoCommandReadVerilog, 1 ); -// Cmd_CommandAdd( pAbc, "I/O", "read_ver", IoCommandReadVer, 1 ); -// Cmd_CommandAdd( pAbc, "I/O", "read_verlib", IoCommandReadVerLib, 0 ); - - Cmd_CommandAdd( pAbc, "I/O", "write", IoCommandWrite, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_hie", IoCommandWriteHie, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_aiger", IoCommandWriteAiger, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_baf", IoCommandWriteBaf, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_blif", IoCommandWriteBlif, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_blif_mv", IoCommandWriteBlifMv, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_bench", IoCommandWriteBench, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_cellnet", IoCommandWriteCellNet, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_counter", IoCommandWriteCounter, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_cnf", IoCommandWriteCnf, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_dot", IoCommandWriteDot, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_eqn", IoCommandWriteEqn, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_gml", IoCommandWriteGml, 0 ); -// Cmd_CommandAdd( pAbc, "I/O", "write_list", IoCommandWriteList, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_pla", IoCommandWritePla, 0 ); - Cmd_CommandAdd( pAbc, "I/O", "write_verilog", IoCommandWriteVerilog, 0 ); -// Cmd_CommandAdd( pAbc, "I/O", "write_verlib", IoCommandWriteVerLib, 0 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_End() -{ -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandRead( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int fCheck; - int c; - - fCheck = 1; - glo_fMapped = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "mch" ) ) != EOF ) - { - switch ( c ) - { - case 'm': - glo_fMapped ^= 1; - break; - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pFileName = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Io_Read( pFileName, Io_ReadFileType(pFileName), fCheck ); - if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read [-mch] \n" ); - fprintf( pAbc->Err, "\t replaces the current network by the network read from \n" ); - fprintf( pAbc->Err, "\t by calling the parser that matches the extension of \n" ); - fprintf( pAbc->Err, "\t (to read a hierarchical design, use \"read_hie\")\n" ); - fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadAiger( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int fCheck; - int c; - - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pFileName = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Io_Read( pFileName, IO_FILE_AIGER, fCheck ); - if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_aiger [-ch] \n" ); - fprintf( pAbc->Err, "\t read the network in the AIGER format (http://fmv.jku.at/aiger)\n" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadBaf( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int fCheck; - int c; - - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pFileName = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Io_Read( pFileName, IO_FILE_BAF, fCheck ); - if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_baf [-ch] \n" ); - fprintf( pAbc->Err, "\t read the network in Binary Aig Format (BAF)\n" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadBlif( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int fReadAsAig; - int fCheck; - int c; - extern Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck ); - - fCheck = 1; - fReadAsAig = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ach" ) ) != EOF ) - { - switch ( c ) - { - case 'a': - fReadAsAig ^= 1; - break; - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pFileName = argv[globalUtilOptind]; - // read the file using the corresponding file reader - if ( fReadAsAig ) - pNtk = Io_ReadBlifAsAig( pFileName, fCheck ); - else -// pNtk = Io_Read( pFileName, IO_FILE_BLIF, fCheck ); - { - Abc_Ntk_t * pTemp; - pNtk = Io_ReadBlif( pFileName, fCheck ); - pNtk = Abc_NtkToLogic( pTemp = pNtk ); - Abc_NtkDelete( pTemp ); - } - - if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_blif [-ach] \n" ); - fprintf( pAbc->Err, "\t read the network in binary BLIF format\n" ); - fprintf( pAbc->Err, "\t-a : toggle creating AIG while reading the file [default = %s]\n", fReadAsAig? "yes":"no" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadBlifMv( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int fCheck; - int c; - - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pFileName = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Io_Read( pFileName, IO_FILE_BLIFMV, fCheck ); - if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_blif_mv [-ch] \n" ); - fprintf( pAbc->Err, "\t read the network in BLIF-MV format\n" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadBench( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int fCheck; - int c; - - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pFileName = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Io_Read( pFileName, IO_FILE_BENCH, fCheck ); - if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_bench [-ch] \n" ); - fprintf( pAbc->Err, "\t read the network in BENCH format\n" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pString; - int fCheck; - int c; - extern Abc_Ntk_t * Io_ReadDsd( char * pFormula ); - - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pString = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Io_ReadDsd( pString ); - if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_dsd [-h] \n" ); - fprintf( pAbc->Err, "\t parses a formula representing DSD of a function\n" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tformula : the formula representing disjoint-support decomposition (DSD)\n" ); - fprintf( pAbc->Err, "\t Example of a formula: !(a*(b+CA(!d,e*f,c))*79B3(g,h,i,k))\n" ); - fprintf( pAbc->Err, "\t where \'!\' is an INV, \'*\' is an AND, \'+\' is an XOR, \n" ); - fprintf( pAbc->Err, "\t CA and 79B3 are hexadecimal representations of truth tables\n" ); - fprintf( pAbc->Err, "\t (in this case CA=11001010 is truth table of MUX(Data0,Data1,Ctrl))\n" ); - fprintf( pAbc->Err, "\t The lower chars (a,b,c,etc) are reserved for elementary variables.\n" ); - fprintf( pAbc->Err, "\t The upper chars (A,B,C,etc) are reserved for hexadecimal digits.\n" ); - fprintf( pAbc->Err, "\t No spaces are allowed in formulas. In parantheses, LSB goes first.\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadEdif( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int fCheck; - int c; - - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pFileName = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Io_Read( pFileName, IO_FILE_EDIF, fCheck ); - if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_edif [-ch] \n" ); - fprintf( pAbc->Err, "\t read the network in EDIF (works only for ISCAS benchmarks)\n" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadEqn( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int fCheck; - int c; - - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pFileName = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Io_Read( pFileName, IO_FILE_EQN, fCheck ); - if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_eqn [-ch] \n" ); - fprintf( pAbc->Err, "\t read the network in equation format\n" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadInit( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNtk; - char * pFileName; - int c; - extern void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - // get the input file name - pFileName = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Abc_NtkDup( pNtk ); - Io_ReadBenchInit( pNtk, pFileName ); - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_init [-h] \n" ); - fprintf( pAbc->Err, "\t reads initial state of the network in BENCH format\n" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadPla( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int fCheck; - int c; - - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pFileName = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Io_Read( pFileName, IO_FILE_PLA, fCheck ); - if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_pla [-ch] \n" ); - fprintf( pAbc->Err, "\t read the network in PLA\n" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pSopCover; - int fHex; - int c; - - fHex = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF ) - { - switch ( c ) - { - case 'x': - fHex ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( argc != globalUtilOptind + 1 ) - { - goto usage; - } - - // convert truth table to SOP - if ( fHex ) - pSopCover = Abc_SopFromTruthHex(argv[globalUtilOptind]); - else - pSopCover = Abc_SopFromTruthBin(argv[globalUtilOptind]); - if ( pSopCover == NULL ) - { - fprintf( pAbc->Err, "Reading truth table has failed.\n" ); - return 1; - } - - pNtk = Abc_NtkCreateWithNode( pSopCover ); - free( pSopCover ); - if ( pNtk == NULL ) - { - fprintf( pAbc->Err, "Deriving the network has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_truth [-xh] \n" ); - fprintf( pAbc->Err, "\t creates network with node having given truth table\n" ); - fprintf( pAbc->Err, "\t-x : toggles between bin and hex representation [default = %s]\n", fHex? "hex":"bin" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\ttruth : truth table with most signficant bit first (e.g. 1000 for AND(a,b))\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadVerilog( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int fCheck; - int c; - - fCheck = 1; - glo_fMapped = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "mch" ) ) != EOF ) - { - switch ( c ) - { - case 'm': - glo_fMapped ^= 1; - break; - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pFileName = argv[globalUtilOptind]; - // read the file using the corresponding file reader - pNtk = Io_Read( pFileName, IO_FILE_VERILOG, fCheck ); - if ( pNtk == NULL ) - return 1; - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_verilog [-mch] \n" ); - fprintf( pAbc->Err, "\t read the network in Verilog (IWLS 2002/2005 subset)\n" ); - fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog [default = %s]\n", glo_fMapped? "yes":"no" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadVer( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Ntk_t * pNtk, * pNtkNew; - Abc_Lib_t * pDesign; - char * pFileName; - FILE * pFile; - int fCheck; - int c; - extern Abc_Ntk_t * Abc_LibDeriveAig( Abc_Ntk_t * pNtk, Abc_Lib_t * pLib ); - extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); - - printf( "Stand-alone structural Verilog reader is available as command \"read_verilog\".\n" ); - return 0; - - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( argc != globalUtilOptind + 1 ) - { - goto usage; - } - - // get the input file name - pFileName = argv[globalUtilOptind]; - if ( (pFile = fopen( pFileName, "r" )) == NULL ) - { - fprintf( pAbc->Err, "Cannot open input file \"%s\". ", pFileName ); - if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) - fprintf( pAbc->Err, "Did you mean \"%s\"?", pFileName ); - fprintf( pAbc->Err, "\n" ); - return 1; - } - fclose( pFile ); - - // set the new network - pDesign = Ver_ParseFile( pFileName, Abc_FrameReadLibVer(), fCheck, 1 ); - if ( pDesign == NULL ) - { - fprintf( pAbc->Err, "Reading network from the verilog file has failed.\n" ); - return 1; - } - - // derive root design - pNtk = Abc_LibDeriveRoot( pDesign ); - Abc_LibFree( pDesign, NULL ); - if ( pNtk == NULL ) - { - fprintf( pAbc->Err, "Deriving root module has failed.\n" ); - return 1; - } - - // derive the AIG network from this design - pNtkNew = Abc_LibDeriveAig( pNtk, Abc_FrameReadLibVer() ); - Abc_NtkDelete( pNtk ); - if ( pNtkNew == NULL ) - { - fprintf( pAbc->Err, "Converting root module to AIG has failed.\n" ); - return 1; - } - // replace the current network - Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_ver [-ch] \n" ); - fprintf( pAbc->Err, "\t read a network in structural verilog (using current library)\n" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandReadVerLib( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - Abc_Lib_t * pLibrary; - char * pFileName; - FILE * pFile; - int fCheck; - int c; - extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); - - fCheck = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) - { - switch ( c ) - { - case 'c': - fCheck ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( argc != globalUtilOptind + 1 ) - { - goto usage; - } - - // get the input file name - pFileName = argv[globalUtilOptind]; - if ( (pFile = fopen( pFileName, "r" )) == NULL ) - { - fprintf( pAbc->Err, "Cannot open input file \"%s\". ", pFileName ); - if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) - fprintf( pAbc->Err, "Did you mean \"%s\"?", pFileName ); - fprintf( pAbc->Err, "\n" ); - return 1; - } - fclose( pFile ); - - // set the new network - pLibrary = Ver_ParseFile( pFileName, NULL, fCheck, 0 ); - if ( pLibrary == NULL ) - { - fprintf( pAbc->Err, "Reading library from the verilog file has failed.\n" ); - return 1; - } - printf( "The library contains %d gates.\n", st_count(pLibrary->tModules) ); - // free old library - if ( Abc_FrameReadLibVer() ) - Abc_LibFree( Abc_FrameReadLibVer(), NULL ); - // read new library - Abc_FrameSetLibVer( pLibrary ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: read_verlib [-ch] \n" ); - fprintf( pAbc->Err, "\t read a gate library in structural verilog\n" ); - fprintf( pAbc->Err, "\t-c : toggle network check after reading [default = %s]\n", fCheck? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : prints the command summary\n" ); - fprintf( pAbc->Err, "\tfile : the name of a file to read\n" ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWrite( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write [-h] \n" ); - fprintf( pAbc->Err, "\t writes the current network into by calling\n" ); - fprintf( pAbc->Err, "\t the writer that matches the extension of \n" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteHie( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pBaseName, * pFileName; - int c; - - glo_fMapped = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "mh" ) ) != EOF ) - { - switch ( c ) - { - case 'm': - glo_fMapped ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 2 ) - goto usage; - // get the output file name - pBaseName = argv[globalUtilOptind]; - pFileName = argv[globalUtilOptind+1]; - // call the corresponding file writer -// Io_Write( pAbc->pNtkCur, pFileName, Io_ReadFileType(pFileName) ); - Io_WriteHie( pAbc->pNtkCur, pBaseName, pFileName ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_hie [-h] \n" ); - fprintf( pAbc->Err, "\t writes the current network into by calling\n" ); - fprintf( pAbc->Err, "\t the hierarchical writer that matches the extension of \n" ); - fprintf( pAbc->Err, "\t-m : toggle reading mapped Verilog for [default = %s]\n", glo_fMapped? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\torig : the name of the original file with the hierarchical design\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteAiger( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int fWriteSymbols; - int c; - - fWriteSymbols = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) - { - switch ( c ) - { - case 's': - fWriteSymbols ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - if ( fWriteSymbols ) - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_AIGER ); - else - { - if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) - { - fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); - return 1; - } - Io_WriteAiger( pAbc->pNtkCur, pFileName, 0 ); - } - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_aiger [-sh] \n" ); - fprintf( pAbc->Err, "\t write the network in the AIGER format (http://fmv.jku.at/aiger)\n" ); - fprintf( pAbc->Err, "\t-s : toggle saving I/O names [default = %s]\n", fWriteSymbols? "yes" : "no" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .aig)\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteBaf( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BAF ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_baf [-h] \n" ); - fprintf( pAbc->Err, "\t write the network into a BLIF file\n" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .baf)\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteBlif( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIF ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_blif [-h] \n" ); - fprintf( pAbc->Err, "\t write the network into a BLIF file\n" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .blif)\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteBlifMv( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BLIFMV ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_blif_mv [-h] \n" ); - fprintf( pAbc->Err, "\t write the network into a BLIF-MV file\n" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .blif)\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteBench( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int fUseLuts; - int c; - - fUseLuts = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) - { - switch ( c ) - { - case 'l': - fUseLuts ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - if ( !fUseLuts ) - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_BENCH ); - else - { - Abc_Ntk_t * pNtkTemp; - pNtkTemp = Abc_NtkToNetlist( pAbc->pNtkCur ); - Abc_NtkToAig( pNtkTemp ); - Io_WriteBenchLut( pNtkTemp, pFileName ); - Abc_NtkDelete( pNtkTemp ); - } - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_bench [-lh] \n" ); - fprintf( pAbc->Err, "\t write the network in BENCH format\n" ); - fprintf( pAbc->Err, "\t-l : toggle using LUTs in the output [default = %s]\n", fUseLuts? "yes" : "no" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write (extension .bench)\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteCellNet( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int c; - extern void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName ); - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - pNtk = pAbc->pNtkCur; - if ( pNtk == NULL ) - { - fprintf( pAbc->Out, "Empty network.\n" ); - return 0; - } - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - if ( !Abc_NtkIsLogic(pNtk) ) - { - fprintf( pAbc->Out, "The network should be a logic network (if it an AIG, use command \"logic\")\n" ); - return 0; - } - Io_WriteCellNet( pNtk, pFileName ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_cellnet [-h] \n" ); - fprintf( pAbc->Err, "\t write the network is the cellnet format\n" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteCnf( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int c; - int fAllPrimes; - int fNewAlgo; - extern Abc_Ntk_t * Abc_NtkDarToCnf( Abc_Ntk_t * pNtk, char * pFileName ); - - fNewAlgo = 1; - fAllPrimes = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nph" ) ) != EOF ) - { - switch ( c ) - { - case 'n': - fNewAlgo ^= 1; - break; - case 'p': - fAllPrimes ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // check if the feature will be used - if ( Abc_NtkIsStrash(pAbc->pNtkCur) && fAllPrimes ) - { - fAllPrimes = 0; - printf( "Warning: Selected option to write all primes has no effect when deriving CNF from AIG.\n" ); - } - // call the corresponding file writer - if ( fNewAlgo ) - Abc_NtkDarToCnf( pAbc->pNtkCur, pFileName ); - else if ( fAllPrimes ) - Io_WriteCnf( pAbc->pNtkCur, pFileName, 1 ); - else - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_CNF ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_cnf [-nph] \n" ); - fprintf( pAbc->Err, "\t write the miter cone into a CNF file\n" ); - fprintf( pAbc->Err, "\t-n : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes" : "no" ); - fprintf( pAbc->Err, "\t-p : toggle using all primes to enhance implicativity [default = %s]\n", fAllPrimes? "yes" : "no" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteDot( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_DOT ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_dot [-h] \n" ); - fprintf( pAbc->Err, "\t write the current network into a DOT file\n" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteCounter( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - Abc_Ntk_t * pNtk; - char * pFileName; - int c; - int fNames; - - fNames = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) - { - switch ( c ) - { - case 'n': - fNames ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - pNtk = pAbc->pNtkCur; - if ( pNtk == NULL ) - { - fprintf( pAbc->Out, "Empty network.\n" ); - return 0; - } - - if ( argc != globalUtilOptind + 1 ) - { - goto usage; - } - // get the input file name - pFileName = argv[globalUtilOptind]; - - if ( pNtk->pModel == NULL ) - { - fprintf( pAbc->Out, "Counter-example is not available.\n" ); - return 0; - } - - // write the counter-example into the file - { - Abc_Obj_t * pObj; - FILE * pFile = fopen( pFileName, "w" ); - int i; - if ( pFile == NULL ) - { - fprintf( stdout, "IoCommandWriteCounter(): Cannot open the output file \"%s\".\n", pFileName ); - return 1; - } - if ( fNames ) - { - Abc_NtkForEachPi( pNtk, pObj, i ) - fprintf( pFile, "%s=%c ", Abc_ObjName(pObj), '0'+(pNtk->pModel[i]==1) ); - } - else - { - Abc_NtkForEachPi( pNtk, pObj, i ) - fprintf( pFile, "%c", '0'+(pNtk->pModel[i]==1) ); - } - fprintf( pFile, "\n" ); - fclose( pFile ); - } - - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_counter [-nh] \n" ); - fprintf( pAbc->Err, "\t writes the counter-example derived by \"prove\" or \"sat\"\n" ); - fprintf( pAbc->Err, "\t the file contains values for each PI in the natural order\n" ); - fprintf( pAbc->Err, "\t-n : write input names into the file [default = %s]\n", fNames? "yes": "no" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteEqn( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_EQN ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_eqn [-h] \n" ); - fprintf( pAbc->Err, "\t write the current network in the equation format\n" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteGml( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_GML ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_gml [-h] \n" ); - fprintf( pAbc->Err, "\t write network using graph representation formal GML\n" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteList( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int fUseHost; - int c; - - printf( "This command currently does not work.\n" ); - return 0; - - fUseHost = 1; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) - { - switch ( c ) - { - case 'n': - fUseHost ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - if ( pAbc->pNtkCur == NULL ) - { - fprintf( pAbc->Out, "Empty network.\n" ); - return 0; - } -/* - if ( !Abc_NtkIsSeq(pAbc->pNtkCur) ) - { - fprintf( stdout, "IoCommandWriteList(): Can write adjacency list for sequential AIGs only.\n" ); - return 0; - } -*/ - // get the input file name - pFileName = argv[globalUtilOptind]; - // write the file - Io_WriteList( pAbc->pNtkCur, pFileName, fUseHost ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_list [-nh] \n" ); - fprintf( pAbc->Err, "\t write network using graph representation formal GML\n" ); - fprintf( pAbc->Err, "\t-n : toggle writing host node [default = %s]\n", fUseHost? "yes":"no" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWritePla( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_PLA ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_pla [-h] \n" ); - fprintf( pAbc->Err, "\t write the collapsed network into a PLA file\n" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteVerilog( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - char * pFileName; - int c; - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the output file name - pFileName = argv[globalUtilOptind]; - // call the corresponding file writer - Io_Write( pAbc->pNtkCur, pFileName, IO_FILE_VERILOG ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_verilog [-h] \n" ); - fprintf( pAbc->Err, "\t write the current network in Verilog format\n" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int IoCommandWriteVerLib( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - Abc_Lib_t * pLibrary; - char * pFileName; - int c; - extern void Io_WriteVerilogLibrary( Abc_Lib_t * pLibrary, char * pFileName ); - - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) - { - switch ( c ) - { - case 'h': - goto usage; - default: - goto usage; - } - } - if ( argc != globalUtilOptind + 1 ) - goto usage; - // get the input file name - pFileName = argv[globalUtilOptind]; - // derive the netlist - pLibrary = Abc_FrameReadLibVer(); - if ( pLibrary == NULL ) - { - fprintf( pAbc->Out, "Verilog library is not specified.\n" ); - return 0; - } -// Io_WriteVerilogLibrary( pLibrary, pFileName ); - return 0; - -usage: - fprintf( pAbc->Err, "usage: write_verlib [-h] \n" ); - fprintf( pAbc->Err, "\t write the current verilog library\n" ); - fprintf( pAbc->Err, "\t-h : print the help massage\n" ); - fprintf( pAbc->Err, "\tfile : the name of the file to write\n" ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/io.h b/src/base/io/io.h deleted file mode 100644 index 45762b77..00000000 --- a/src/base/io/io.h +++ /dev/null @@ -1,146 +0,0 @@ -/**CFile**************************************************************** - - FileName [io.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: io.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __IO_H__ -#define __IO_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// network functionality -typedef enum { - IO_FILE_NONE = 0, - IO_FILE_AIGER, - IO_FILE_BAF, - IO_FILE_BLIF, - IO_FILE_BLIFMV, - IO_FILE_BENCH, - IO_FILE_CNF, - IO_FILE_DOT, - IO_FILE_EDIF, - IO_FILE_EQN, - IO_FILE_GML, - IO_FILE_LIST, - IO_FILE_PLA, - IO_FILE_VERILOG, - IO_FILE_UNKNOWN -} Io_FileType_t; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define IO_WRITE_LINE_LENGTH 78 // the output line length - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== abcReadAiger.c ==========================================================*/ -extern Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ); -/*=== abcReadBaf.c ============================================================*/ -extern Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck ); -/*=== abcReadBlif.c ===========================================================*/ -extern Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ); -/*=== abcReadBlifMv.c =========================================================*/ -extern Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck ); -/*=== abcReadBench.c ==========================================================*/ -extern Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ); -/*=== abcReadEdif.c ===========================================================*/ -extern Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ); -/*=== abcReadEqn.c ============================================================*/ -extern Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ); -/*=== abcReadPla.c ============================================================*/ -extern Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck ); -/*=== abcReadVerilog.c ========================================================*/ -extern Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ); -/*=== abcWriteAiger.c =========================================================*/ -extern void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols ); -/*=== abcWriteBaf.c ===========================================================*/ -extern void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName ); -/*=== abcWriteBlif.c ==========================================================*/ -extern void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); -extern void Io_WriteBlif( Abc_Ntk_t * pNtk, char * pFileName, int fWriteLatches ); -extern void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ); -/*=== abcWriteBlifMv.c ==========================================================*/ -extern void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ); -/*=== abcWriteBench.c =========================================================*/ -extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); -extern int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * FileName ); -/*=== abcWriteCnf.c ===========================================================*/ -extern int Io_WriteCnf( Abc_Ntk_t * pNtk, char * FileName, int fAllPrimes ); -/*=== abcWriteDot.c ===========================================================*/ -extern void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ); -extern void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); -extern void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ); -/*=== abcWriteEqn.c ===========================================================*/ -extern void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ); -/*=== abcWriteGml.c ===========================================================*/ -extern void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ); -/*=== abcWriteList.c ==========================================================*/ -extern void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ); -/*=== abcWritePla.c ===========================================================*/ -extern int Io_WritePla( Abc_Ntk_t * pNtk, char * FileName ); -/*=== abcWriteVerilog.c =======================================================*/ -extern void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * FileName ); -/*=== abcUtil.c ===============================================================*/ -extern Io_FileType_t Io_ReadFileType( char * pFileName ); -extern Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck ); -extern Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck ); -extern void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ); -extern void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName ); -extern Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName ); -extern Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName ); -extern Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName ); -extern Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ); -extern Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv ); -extern Abc_Obj_t * Io_ReadCreateResetMux( Abc_Ntk_t * pNtk, char * pResetLO, char * pDataLI, int fBlifMv ); -extern Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs ); -extern Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, bool fConst1 ); -extern Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ); -extern Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ); -extern FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ); - - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/io/ioInt.h b/src/base/io/ioInt.h deleted file mode 100644 index 3daf3c75..00000000 --- a/src/base/io/ioInt.h +++ /dev/null @@ -1,49 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __IO_INT_H__ -#define __IO_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/io/ioReadAiger.c b/src/base/io/ioReadAiger.c deleted file mode 100644 index d3c4c878..00000000 --- a/src/base/io/ioReadAiger.c +++ /dev/null @@ -1,310 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioReadAiger.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to read binary AIGER format developed by - Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - December 16, 2006.] - - Revision [$Id: ioReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -unsigned Io_ReadAigerDecode( char ** ppPos ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the AIG in the binary AIGER format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadAiger( char * pFileName, int fCheck ) -{ - ProgressBar * pProgress; - FILE * pFile; - Vec_Ptr_t * vNodes, * vTerms; - Abc_Obj_t * pObj, * pNode0, * pNode1; - Abc_Ntk_t * pNtkNew; - int nTotal, nInputs, nOutputs, nLatches, nAnds, nFileSize, iTerm, nDigits, i; - char * pContents, * pDrivers, * pSymbols, * pCur, * pName, * pType; - unsigned uLit0, uLit1, uLit; - - // read the file into the buffer - nFileSize = Extra_FileSize( pFileName ); - pFile = fopen( pFileName, "rb" ); - pContents = ALLOC( char, nFileSize ); - fread( pContents, nFileSize, 1, pFile ); - fclose( pFile ); - - // check if the input file format is correct - if ( strncmp(pContents, "aig", 3) != 0 ) - { - fprintf( stdout, "Wrong input file format.\n" ); - return NULL; - } - - // allocate the empty AIG - pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - pName = Extra_FileNameGeneric( pFileName ); - pNtkNew->pName = Extra_UtilStrsav( pName ); - pNtkNew->pSpec = Extra_UtilStrsav( pFileName ); - free( pName ); - - - // read the file type - pCur = pContents; while ( *pCur++ != ' ' ); - // read the number of objects - nTotal = atoi( pCur ); while ( *pCur++ != ' ' ); - // read the number of inputs - nInputs = atoi( pCur ); while ( *pCur++ != ' ' ); - // read the number of latches - nLatches = atoi( pCur ); while ( *pCur++ != ' ' ); - // read the number of outputs - nOutputs = atoi( pCur ); while ( *pCur++ != ' ' ); - // read the number of nodes - nAnds = atoi( pCur ); while ( *pCur++ != '\n' ); - // check the parameters - if ( nTotal != nInputs + nLatches + nAnds ) - { - fprintf( stdout, "The paramters are wrong.\n" ); - return NULL; - } - - // prepare the array of nodes - vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); - Vec_PtrPush( vNodes, Abc_ObjNot( Abc_AigConst1(pNtkNew) ) ); - - // create the PIs - for ( i = 0; i < nInputs; i++ ) - { - pObj = Abc_NtkCreatePi(pNtkNew); - Vec_PtrPush( vNodes, pObj ); - } - // create the POs - for ( i = 0; i < nOutputs; i++ ) - { - pObj = Abc_NtkCreatePo(pNtkNew); - } - // create the latches - nDigits = Extra_Base10Log( nLatches ); - for ( i = 0; i < nLatches; i++ ) - { - pObj = Abc_NtkCreateLatch(pNtkNew); - Abc_LatchSetInit0( pObj ); - pNode0 = Abc_NtkCreateBi(pNtkNew); - pNode1 = Abc_NtkCreateBo(pNtkNew); - Abc_ObjAddFanin( pObj, pNode0 ); - Abc_ObjAddFanin( pNode1, pObj ); - Vec_PtrPush( vNodes, pNode1 ); - // assign names to latch and its input -// Abc_ObjAssignName( pObj, Abc_ObjNameDummy("_L", i, nDigits), NULL ); -// printf( "Creating latch %s with input %d and output %d.\n", Abc_ObjName(pObj), pNode0->Id, pNode1->Id ); - } - - // remember the beginning of latch/PO literals - pDrivers = pCur; - - // scroll to the beginning of the binary data - for ( i = 0; i < nLatches + nOutputs; ) - if ( *pCur++ == '\n' ) - i++; - - // create the AND gates - pProgress = Extra_ProgressBarStart( stdout, nAnds ); - for ( i = 0; i < nAnds; i++ ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - uLit = ((i + 1 + nInputs + nLatches) << 1); - uLit1 = uLit - Io_ReadAigerDecode( &pCur ); - uLit0 = uLit1 - Io_ReadAigerDecode( &pCur ); -// assert( uLit1 > uLit0 ); - pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); - pNode1 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); - assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches ); - Vec_PtrPush( vNodes, Abc_AigAnd(pNtkNew->pManFunc, pNode0, pNode1) ); - } - Extra_ProgressBarStop( pProgress ); - - // remember the place where symbols begin - pSymbols = pCur; - - // read the latch driver literals - pCur = pDrivers; - Abc_NtkForEachLatchInput( pNtkNew, pObj, i ) - { - uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); - pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); - Abc_ObjAddFanin( pObj, pNode0 ); - -// printf( "Adding input %d to latch input %d.\n", pNode0->Id, pObj->Id ); - - } - // read the PO driver literals - Abc_NtkForEachPo( pNtkNew, pObj, i ) - { - uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); - pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); - Abc_ObjAddFanin( pObj, pNode0 ); - } - - // read the names if present - pCur = pSymbols; - if ( *pCur != 'c' ) - { - int Counter = 0; - while ( pCur < pContents + nFileSize && *pCur != 'c' ) - { - // get the terminal type - pType = pCur; - if ( *pCur == 'i' ) - vTerms = pNtkNew->vPis; - else if ( *pCur == 'l' ) - vTerms = pNtkNew->vBoxes; - else if ( *pCur == 'o' ) - vTerms = pNtkNew->vPos; - else - { - fprintf( stdout, "Wrong terminal type.\n" ); - return NULL; - } - // get the terminal number - iTerm = atoi( ++pCur ); while ( *pCur++ != ' ' ); - // get the node - if ( iTerm >= Vec_PtrSize(vTerms) ) - { - fprintf( stdout, "The number of terminal is out of bound.\n" ); - return NULL; - } - pObj = Vec_PtrEntry( vTerms, iTerm ); - if ( *pType == 'l' ) - pObj = Abc_ObjFanout0(pObj); - // assign the name - pName = pCur; while ( *pCur++ != '\n' ); - // assign this name - *(pCur-1) = 0; - Abc_ObjAssignName( pObj, pName, NULL ); - if ( *pType == 'l' ) - { - Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" ); - Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" ); - } - // mark the node as named - pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); - } - - // assign the remaining names - Abc_NtkForEachPi( pNtkNew, pObj, i ) - { - if ( pObj->pCopy ) continue; - Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); - Counter++; - } - Abc_NtkForEachLatchOutput( pNtkNew, pObj, i ) - { - if ( pObj->pCopy ) continue; - Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); - Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(pObj), "L" ); - Abc_ObjAssignName( Abc_ObjFanin0(Abc_ObjFanin0(pObj)), Abc_ObjName(pObj), "_in" ); - Counter++; - } - Abc_NtkForEachPo( pNtkNew, pObj, i ) - { - if ( pObj->pCopy ) continue; - Abc_ObjAssignName( pObj, Abc_ObjName(pObj), NULL ); - Counter++; - } - if ( Counter ) - printf( "Io_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter ); - } - else - { -// printf( "Io_ReadAiger(): I/O/register names are not given. Generating short names.\n" ); - Abc_NtkShortNames( pNtkNew ); - } - - // read the name of the model if given - if ( *pCur == 'c' ) - { - if ( !strncmp( pCur + 2, ".model", 6 ) ) - { - char * pTemp; - for ( pTemp = pCur + 9; *pTemp && *pTemp != '\n'; pTemp++ ); - *pTemp = 0; - free( pNtkNew->pName ); - pNtkNew->pName = Extra_UtilStrsav( pCur + 9 ); - } - } - - - // skipping the comments - free( pContents ); - Vec_PtrFree( vNodes ); - - // remove the extra nodes - Abc_AigCleanup( pNtkNew->pManFunc ); - - // check the result - if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) ) - { - printf( "Io_ReadAiger: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; -} - - -/**Function************************************************************* - - Synopsis [Extracts one unsigned AIG edge from the input buffer.] - - Description [This procedure is a slightly modified version of Armin Biere's - procedure "unsigned decode (FILE * file)". ] - - SideEffects [Updates the current reading position.] - - SeeAlso [] - -***********************************************************************/ -unsigned Io_ReadAigerDecode( char ** ppPos ) -{ - unsigned x = 0, i = 0; - unsigned char ch; - -// while ((ch = getnoneofch (file)) & 0x80) - while ((ch = *(*ppPos)++) & 0x80) - x |= (ch & 0x7f) << (7 * i++); - - return x | (ch << (7 * i)); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioReadBaf.c b/src/base/io/ioReadBaf.c deleted file mode 100644 index 8dce54af..00000000 --- a/src/base/io/ioReadBaf.c +++ /dev/null @@ -1,171 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioReadBaf.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to read AIG in the binary format.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioReadBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the AIG in the binary format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadBaf( char * pFileName, int fCheck ) -{ - ProgressBar * pProgress; - FILE * pFile; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pNode0, * pNode1; - Abc_Ntk_t * pNtkNew; - int nInputs, nOutputs, nLatches, nAnds, nFileSize, Num, i; - char * pContents, * pName, * pCur; - unsigned * pBufferNode; - - // read the file into the buffer - nFileSize = Extra_FileSize( pFileName ); - pFile = fopen( pFileName, "rb" ); - pContents = ALLOC( char, nFileSize ); - fread( pContents, nFileSize, 1, pFile ); - fclose( pFile ); - - // skip the comments (comment lines begin with '#' and end with '\n') - for ( pCur = pContents; *pCur == '#'; ) - while ( *pCur++ != '\n' ); - - // read the name - pName = pCur; while ( *pCur++ ); - // read the number of inputs - nInputs = atoi( pCur ); while ( *pCur++ ); - // read the number of outputs - nOutputs = atoi( pCur ); while ( *pCur++ ); - // read the number of latches - nLatches = atoi( pCur ); while ( *pCur++ ); - // read the number of nodes - nAnds = atoi( pCur ); while ( *pCur++ ); - - // allocate the empty AIG - pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - pNtkNew->pName = Extra_UtilStrsav( pName ); - pNtkNew->pSpec = Extra_UtilStrsav( pFileName ); - - // prepare the array of nodes - vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); - Vec_PtrPush( vNodes, Abc_AigConst1(pNtkNew) ); - - // create the PIs - for ( i = 0; i < nInputs; i++ ) - { - pObj = Abc_NtkCreatePi(pNtkNew); - Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); - Vec_PtrPush( vNodes, pObj ); - } - // create the POs - for ( i = 0; i < nOutputs; i++ ) - { - pObj = Abc_NtkCreatePo(pNtkNew); - Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); - } - // create the latches - for ( i = 0; i < nLatches; i++ ) - { - pObj = Abc_NtkCreateLatch(pNtkNew); - Abc_ObjAssignName( pObj, pCur, NULL ); while ( *pCur++ ); - - pNode0 = Abc_NtkCreateBi(pNtkNew); - Abc_ObjAssignName( pNode0, pCur, NULL ); while ( *pCur++ ); - - pNode1 = Abc_NtkCreateBo(pNtkNew); - Abc_ObjAssignName( pNode1, pCur, NULL ); while ( *pCur++ ); - Vec_PtrPush( vNodes, pNode1 ); - - Abc_ObjAddFanin( pObj, pNode0 ); - Abc_ObjAddFanin( pNode1, pObj ); - } - - // get the pointer to the beginning of the node array - pBufferNode = (int *)(pContents + (nFileSize - (2 * nAnds + nOutputs + nLatches) * sizeof(int)) ); - // make sure we are at the place where the nodes begin - if ( pBufferNode != (int *)pCur ) - { - free( pContents ); - Vec_PtrFree( vNodes ); - Abc_NtkDelete( pNtkNew ); - printf( "Warning: Internal reader error.\n" ); - return NULL; - } - - // create the AND gates - pProgress = Extra_ProgressBarStart( stdout, nAnds ); - for ( i = 0; i < nAnds; i++ ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, pBufferNode[2*i+0] >> 1), pBufferNode[2*i+0] & 1 ); - pNode1 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, pBufferNode[2*i+1] >> 1), pBufferNode[2*i+1] & 1 ); - Vec_PtrPush( vNodes, Abc_AigAnd(pNtkNew->pManFunc, pNode0, pNode1) ); - } - Extra_ProgressBarStop( pProgress ); - - // read the POs - Abc_NtkForEachCo( pNtkNew, pObj, i ) - { - Num = pBufferNode[2*nAnds+i]; - if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) - { - Abc_ObjSetData( Abc_ObjFanout0(pObj), (void *)(Num & 3) ); - Num >>= 2; - } - pNode0 = Abc_ObjNotCond( Vec_PtrEntry(vNodes, Num >> 1), Num & 1 ); - Abc_ObjAddFanin( pObj, pNode0 ); - } - free( pContents ); - Vec_PtrFree( vNodes ); - - // remove the extra nodes -// Abc_AigCleanup( pNtkNew->pManFunc ); - - // check the result - if ( fCheck && !Abc_NtkCheckRead( pNtkNew ) ) - { - printf( "Io_ReadBaf: The network check has failed.\n" ); - Abc_NtkDelete( pNtkNew ); - return NULL; - } - return pNtkNew; - -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioReadBench.c b/src/base/io/ioReadBench.c deleted file mode 100644 index 007147bc..00000000 --- a/src/base/io/ioReadBench.c +++ /dev/null @@ -1,360 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioReadBench.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to read BENCH files.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioReadBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the network from a BENCH file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadBench( char * pFileName, int fCheck ) -{ - Extra_FileReader_t * p; - Abc_Ntk_t * pNtk; - - // start the file - p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t,()=" ); - if ( p == NULL ) - return NULL; - - // read the network - pNtk = Io_ReadBenchNetwork( p ); - Extra_FileReaderFree( p ); - if ( pNtk == NULL ) - return NULL; - - // make sure that everything is okay with the network structure - if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) - { - printf( "Io_ReadBench: The network check has failed.\n" ); - Abc_NtkDelete( pNtk ); - return NULL; - } - return pNtk; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadBenchNetwork( Extra_FileReader_t * p ) -{ - ProgressBar * pProgress; - Vec_Ptr_t * vTokens; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode, * pNet; - Vec_Str_t * vString; - unsigned uTruth[8]; - char * pType, ** ppNames, * pString; - int iLine, nNames, nDigits, fLutsPresent = 0; - - // allocate the empty network - pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); - - // go through the lines of the file - vString = Vec_StrAlloc( 100 ); - pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); - for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) - { - Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); - - if ( vTokens->nSize == 1 ) - { - printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); - Vec_StrFree( vString ); - Abc_NtkDelete( pNtk ); - return NULL; - } - - // get the type of the line - if ( strncmp( vTokens->pArray[0], "INPUT", 5 ) == 0 ) - Io_ReadCreatePi( pNtk, vTokens->pArray[1] ); - else if ( strncmp( vTokens->pArray[0], "OUTPUT", 5 ) == 0 ) - Io_ReadCreatePo( pNtk, vTokens->pArray[1] ); - else - { - // get the node name and the node type - pType = vTokens->pArray[1]; - if ( strncmp(pType, "DFF", 3) == 0 ) // works for both DFF and DFFRSE - { - pNode = Io_ReadCreateLatch( pNtk, vTokens->pArray[2], vTokens->pArray[0] ); -// Abc_LatchSetInit0( pNode ); - if ( pType[3] == '0' ) - Abc_LatchSetInit0( pNode ); - else if ( pType[3] == '1' ) - Abc_LatchSetInit1( pNode ); - else - Abc_LatchSetInitDc( pNode ); - } - else if ( strcmp(pType, "LUT") == 0 ) - { - fLutsPresent = 1; - ppNames = (char **)vTokens->pArray + 3; - nNames = vTokens->nSize - 3; - // check the number of inputs - if ( nNames > 8 ) - { - printf( "%s: Currently cannot read truth tables with more than 8 inputs (%d).\n", Extra_FileReaderGetFileName(p), nNames ); - Vec_StrFree( vString ); - Abc_NtkDelete( pNtk ); - return NULL; - } - // get the hex string - pString = vTokens->pArray[2]; - if ( strncmp( pString, "0x", 2 ) ) - { - printf( "%s: The LUT signature (%s) does not look like a hexadecimal beginning with \"0x\".\n", Extra_FileReaderGetFileName(p), pString ); - Vec_StrFree( vString ); - Abc_NtkDelete( pNtk ); - return NULL; - } - pString += 2; - // pad the string with zero's if needed - nDigits = (1 << nNames) / 4; - if ( nDigits == 0 ) - nDigits = 1; - if ( strlen(pString) < (unsigned)nDigits ) - { - Vec_StrFill( vString, nDigits - strlen(pString), '0' ); - Vec_StrPrintStr( vString, pString ); - Vec_StrPush( vString, 0 ); - pString = Vec_StrArray( vString ); - } - // read the hex number from the string - if ( !Extra_ReadHexadecimal( uTruth, pString, nNames ) ) - { - printf( "%s: Reading hexadecimal number (%s) has failed.\n", Extra_FileReaderGetFileName(p), pString ); - Vec_StrFree( vString ); - Abc_NtkDelete( pNtk ); - return NULL; - } - // check if the node is a constant node - if ( Extra_TruthIsConst0(uTruth, nNames) ) - { - pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, 0 ); - Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 0\n" ) ); - } - else if ( Extra_TruthIsConst1(uTruth, nNames) ) - { - pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, 0 ); - Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 1\n" ) ); - } - else - { - // create the node - pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, nNames ); - assert( nNames > 0 ); - if ( nNames > 1 ) - Abc_ObjSetData( pNode, Abc_SopCreateFromTruth(pNtk->pManFunc, nNames, uTruth) ); - else if ( pString[0] == '2' ) - Abc_ObjSetData( pNode, Abc_SopCreateBuf(pNtk->pManFunc) ); - else if ( pString[0] == '1' ) - Abc_ObjSetData( pNode, Abc_SopCreateInv(pNtk->pManFunc) ); - else - { - printf( "%s: Reading truth table (%s) of single-input node has failed.\n", Extra_FileReaderGetFileName(p), pString ); - Vec_StrFree( vString ); - Abc_NtkDelete( pNtk ); - return NULL; - } - } - } - else - { - // create a new node and add it to the network - ppNames = (char **)vTokens->pArray + 2; - nNames = vTokens->nSize - 2; - pNode = Io_ReadCreateNode( pNtk, vTokens->pArray[0], ppNames, nNames ); - // assign the cover - if ( strcmp(pType, "AND") == 0 ) - Abc_ObjSetData( pNode, Abc_SopCreateAnd(pNtk->pManFunc, nNames, NULL) ); - else if ( strcmp(pType, "OR") == 0 ) - Abc_ObjSetData( pNode, Abc_SopCreateOr(pNtk->pManFunc, nNames, NULL) ); - else if ( strcmp(pType, "NAND") == 0 ) - Abc_ObjSetData( pNode, Abc_SopCreateNand(pNtk->pManFunc, nNames) ); - else if ( strcmp(pType, "NOR") == 0 ) - Abc_ObjSetData( pNode, Abc_SopCreateNor(pNtk->pManFunc, nNames) ); - else if ( strcmp(pType, "XOR") == 0 ) - Abc_ObjSetData( pNode, Abc_SopCreateXor(pNtk->pManFunc, nNames) ); - else if ( strcmp(pType, "NXOR") == 0 || strcmp(pType, "XNOR") == 0 ) - Abc_ObjSetData( pNode, Abc_SopCreateNxor(pNtk->pManFunc, nNames) ); - else if ( strncmp(pType, "BUF", 3) == 0 ) - Abc_ObjSetData( pNode, Abc_SopCreateBuf(pNtk->pManFunc) ); - else if ( strcmp(pType, "NOT") == 0 ) - Abc_ObjSetData( pNode, Abc_SopCreateInv(pNtk->pManFunc) ); - else if ( strncmp(pType, "MUX", 3) == 0 ) - Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, "1-0 1\n-11 1\n") ); - else if ( strncmp(pType, "gnd", 3) == 0 ) - Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 0\n" ) ); - else if ( strncmp(pType, "vdd", 3) == 0 ) - Abc_ObjSetData( pNode, Abc_SopRegister( pNtk->pManFunc, " 1\n" ) ); - else - { - printf( "Io_ReadBenchNetwork(): Cannot determine gate type \"%s\" in line %d.\n", pType, Extra_FileReaderGetLineNumber(p, 0) ); - Vec_StrFree( vString ); - Abc_NtkDelete( pNtk ); - return NULL; - } - } - } - } - Extra_ProgressBarStop( pProgress ); - Vec_StrFree( vString ); - - // check if constant 0 is present - if ( (pNet = Abc_NtkFindNet( pNtk, "gnd" )) ) - { - if ( Abc_ObjFaninNum(pNet) == 0 ) - Io_ReadCreateConst( pNtk, "gnd", 0 ); - } - if ( (pNet = Abc_NtkFindNet( pNtk, "1" )) ) - { - if ( Abc_ObjFaninNum(pNet) == 0 ) - { - printf( "Io_ReadBenchNetwork(): Adding constant 0 fanin to non-driven net \"1\".\n" ); - Io_ReadCreateConst( pNtk, "1", 0 ); - } - } - // check if constant 1 is present - if ( (pNet = Abc_NtkFindNet( pNtk, "vdd" )) ) - { - if ( Abc_ObjFaninNum(pNet) == 0 ) - Io_ReadCreateConst( pNtk, "vdd", 1 ); - } - if ( (pNet = Abc_NtkFindNet( pNtk, "2" )) ) - { - if ( Abc_ObjFaninNum(pNet) == 0 ) - { - printf( "Io_ReadBenchNetwork(): Adding constant 1 fanin to non-driven net \"2\".\n" ); - Io_ReadCreateConst( pNtk, "2", 1 ); - } - } - - Abc_NtkFinalizeRead( pNtk ); - - // if LUTs are present, collapse the truth tables into cubes - if ( fLutsPresent ) - { - if ( !Abc_NtkToBdd(pNtk) ) - { - printf( "Io_ReadBenchNetwork(): Converting to BDD has failed.\n" ); - Abc_NtkDelete( pNtk ); - return NULL; - } - if ( !Abc_NtkToSop(pNtk, 0) ) - { - printf( "Io_ReadBenchNetwork(): Converting to SOP has failed.\n" ); - Abc_NtkDelete( pNtk ); - return NULL; - } - } - return pNtk; -} - - -/**Function************************************************************* - - Synopsis [Reads initial state in BENCH format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName ) -{ - char pBuffer[1000]; - FILE * pFile; - char * pToken; - Abc_Obj_t * pObj; - int Num; - pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - printf( "Io_ReadBenchInit(): Failed to open file \"%s\".\n", pFileName ); - return; - } - while ( fgets( pBuffer, 999, pFile ) ) - { - pToken = strtok( pBuffer, " \n\t\r" ); - // find the latch output - Num = Nm_ManFindIdByName( pNtk->pManName, pToken, ABC_OBJ_BO ); - if ( Num < 0 ) - { - printf( "Io_ReadBenchInit(): Cannot find register with output %s.\n", pToken ); - continue; - } - pObj = Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); - if ( !Abc_ObjIsLatch(pObj) ) - { - printf( "Io_ReadBenchInit(): The signal is not a register output %s.\n", pToken ); - continue; - } - // assign the new init state - pToken = strtok( NULL, " \n\t\r" ); - if ( pToken[0] == '0' ) - Abc_LatchSetInit0( pObj ); - else if ( pToken[0] == '1' ) - Abc_LatchSetInit1( pObj ); - else if ( pToken[0] == '2' ) - Abc_LatchSetInitDc( pObj ); - else - { - printf( "Io_ReadBenchInit(): The signal %s has unknown initial value (%s).\n", - Abc_ObjName(Abc_ObjFanout0(pObj)), pToken ); - continue; - } - } - fclose( pFile ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - diff --git a/src/base/io/ioReadBlif.c b/src/base/io/ioReadBlif.c deleted file mode 100644 index d0750178..00000000 --- a/src/base/io/ioReadBlif.c +++ /dev/null @@ -1,1105 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioReadBlif.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to read BLIF files.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioReadBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" -#include "main.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Io_ReadBlif_t_ Io_ReadBlif_t; // all reading info -struct Io_ReadBlif_t_ -{ - // general info about file - char * pFileName; // the name of the file - Extra_FileReader_t * pReader; // the input file reader - // current processing info - Abc_Ntk_t * pNtkMaster; // the primary network - Abc_Ntk_t * pNtkCur; // the primary network - int LineCur; // the line currently parsed - // temporary storage for tokens - Vec_Ptr_t * vTokens; // the current tokens - Vec_Ptr_t * vNewTokens; // the temporary storage for the tokens - Vec_Str_t * vCubes; // the temporary storage for the tokens - // the error message - FILE * Output; // the output stream - char sError[1000]; // the error string generated during parsing - int fError; // set to 1 when error occurs -}; - -static Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ); -static void Io_ReadBlifFree( Io_ReadBlif_t * p ); -static void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ); -static Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ); -static char * Io_ReadBlifCleanName( char * pName ); - -static Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ); -static Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ); -static int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); -static int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); -static int Io_ReadBlifNetworkAsserts( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); -static int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); -static int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ); -static int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); -static int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); -static int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); -static int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ); -static int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the (hierarchical) network from the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadBlif( char * pFileName, int fCheck ) -{ - Io_ReadBlif_t * p; - Abc_Ntk_t * pNtk; - - // start the file - p = Io_ReadBlifFile( pFileName ); - if ( p == NULL ) - return NULL; - - // read the hierarchical network - pNtk = Io_ReadBlifNetwork( p ); - if ( pNtk == NULL ) - { - Io_ReadBlifFree( p ); - return NULL; - } - pNtk->pSpec = Extra_UtilStrsav( pFileName ); - Abc_NtkTimeInitialize( pNtk ); - Io_ReadBlifFree( p ); - - // make sure that everything is okay with the network structure - if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) - { - printf( "Io_ReadBlif: The network check has failed.\n" ); - Abc_NtkDelete( pNtk ); - return NULL; - } - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Iteratively reads several networks in the hierarchical design.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadBlifNetwork( Io_ReadBlif_t * p ) -{ - Abc_Ntk_t * pNtk, * pNtkMaster; - - // read the name of the master network - p->vTokens = Io_ReadBlifGetTokens(p); - if ( p->vTokens == NULL || strcmp( p->vTokens->pArray[0], ".model" ) ) - { - p->LineCur = 0; - sprintf( p->sError, "Wrong input file format." ); - Io_ReadBlifPrintErrorMessage( p ); - return NULL; - } - - // read networks (with EXDC) - pNtkMaster = NULL; - while ( p->vTokens ) - { - // read the network and its EXDC if present - pNtk = Io_ReadBlifNetworkOne( p ); - if ( pNtk == NULL ) - break; - if ( p->vTokens && strcmp(p->vTokens->pArray[0], ".exdc") == 0 ) - { - pNtk->pExdc = Io_ReadBlifNetworkOne( p ); - Abc_NtkFinalizeRead( pNtk->pExdc ); - if ( pNtk->pExdc == NULL ) - break; - } - // add this network as part of the hierarchy - if ( pNtkMaster == NULL ) // no master network so far - { - p->pNtkMaster = pNtkMaster = pNtk; - continue; - } -/* - // make sure hierarchy does not have the network with this name - if ( pNtkMaster->tName2Model && stmm_is_member( pNtkMaster->tName2Model, pNtk->pName ) ) - { - p->LineCur = 0; - sprintf( p->sError, "Model %s is multiply defined in the file.", pNtk->pName ); - Io_ReadBlifPrintErrorMessage( p ); - Abc_NtkDelete( pNtk ); - Abc_NtkDelete( pNtkMaster ); - pNtkMaster = NULL; - return NULL; - } - // add the network to the hierarchy - if ( pNtkMaster->tName2Model == NULL ) - pNtkMaster->tName2Model = stmm_init_table(strcmp, stmm_strhash); - stmm_insert( pNtkMaster->tName2Model, pNtk->pName, (char *)pNtk ); -*/ - } -/* - // if there is a hierarchy, connect the boxes - if ( pNtkMaster && pNtkMaster->tName2Model ) - { - if ( Io_ReadBlifNetworkConnectBoxes( p, pNtkMaster ) ) - { - Abc_NtkDelete( pNtkMaster ); - return NULL; - } - } - else -*/ - if ( !p->fError ) - Abc_NtkFinalizeRead( pNtkMaster ); - // return the master network - return pNtkMaster; -} - -/**Function************************************************************* - - Synopsis [Reads one (main or exdc) network from the BLIF file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadBlifNetworkOne( Io_ReadBlif_t * p ) -{ - ProgressBar * pProgress; - Abc_Ntk_t * pNtk; - char * pDirective; - int iLine, fTokensReady, fStatus; - - // make sure the tokens are present - assert( p->vTokens != NULL ); - - // create the new network - p->pNtkCur = pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); - // read the model name - if ( strcmp( p->vTokens->pArray[0], ".model" ) == 0 ) - pNtk->pName = Extra_UtilStrsav( p->vTokens->pArray[1] ); - else if ( strcmp( p->vTokens->pArray[0], ".exdc" ) != 0 ) - { - printf( "%s: File parsing skipped after line %d (\"%s\").\n", p->pFileName, - Extra_FileReaderGetLineNumber(p->pReader, 0), p->vTokens->pArray[0] ); - Abc_NtkDelete(pNtk); - p->pNtkCur = NULL; - return NULL; - } - - // read the inputs/outputs - if ( p->pNtkMaster == NULL ) - pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p->pReader) ); - fTokensReady = fStatus = 0; - for ( iLine = 0; fTokensReady || (p->vTokens = Io_ReadBlifGetTokens(p)); iLine++ ) - { - if ( p->pNtkMaster == NULL && iLine % 1000 == 0 ) - Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p->pReader), NULL ); - - // consider different line types - fTokensReady = 0; - pDirective = p->vTokens->pArray[0]; - if ( !strcmp( pDirective, ".names" ) ) - { fStatus = Io_ReadBlifNetworkNames( p, &p->vTokens ); fTokensReady = 1; } - else if ( !strcmp( pDirective, ".gate" ) ) - fStatus = Io_ReadBlifNetworkGate( p, p->vTokens ); - else if ( !strcmp( pDirective, ".latch" ) ) - fStatus = Io_ReadBlifNetworkLatch( p, p->vTokens ); - else if ( !strcmp( pDirective, ".inputs" ) ) - fStatus = Io_ReadBlifNetworkInputs( p, p->vTokens ); - else if ( !strcmp( pDirective, ".outputs" ) ) - fStatus = Io_ReadBlifNetworkOutputs( p, p->vTokens ); - else if ( !strcmp( pDirective, ".asserts" ) ) - fStatus = Io_ReadBlifNetworkAsserts( p, p->vTokens ); - else if ( !strcmp( pDirective, ".input_arrival" ) ) - fStatus = Io_ReadBlifNetworkInputArrival( p, p->vTokens ); - else if ( !strcmp( pDirective, ".default_input_arrival" ) ) - fStatus = Io_ReadBlifNetworkDefaultInputArrival( p, p->vTokens ); -// else if ( !strcmp( pDirective, ".subckt" ) ) -// fStatus = Io_ReadBlifNetworkSubcircuit( p, p->vTokens ); - else if ( !strcmp( pDirective, ".exdc" ) ) - break; - else if ( !strcmp( pDirective, ".end" ) ) - { - p->vTokens = Io_ReadBlifGetTokens(p); - break; - } - else if ( !strcmp( pDirective, ".blackbox" ) ) - { - pNtk->ntkType = ABC_NTK_NETLIST; - pNtk->ntkFunc = ABC_FUNC_BLACKBOX; - Extra_MmFlexStop( pNtk->pManFunc ); - pNtk->pManFunc = NULL; - } - else - printf( "%s (line %d): Skipping directive \"%s\".\n", p->pFileName, - Extra_FileReaderGetLineNumber(p->pReader, 0), pDirective ); - if ( p->vTokens == NULL ) // some files do not have ".end" in the end - break; - if ( fStatus == 1 ) - { - Extra_ProgressBarStop( pProgress ); - Abc_NtkDelete( pNtk ); - return NULL; - } - } - if ( p->pNtkMaster == NULL ) - Extra_ProgressBarStop( pProgress ); - return pNtk; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkInputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) -{ - int i; - for ( i = 1; i < vTokens->nSize; i++ ) - Io_ReadCreatePi( p->pNtkCur, vTokens->pArray[i] ); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkOutputs( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) -{ - int i; - for ( i = 1; i < vTokens->nSize; i++ ) - Io_ReadCreatePo( p->pNtkCur, vTokens->pArray[i] ); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkAsserts( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) -{ - int i; - for ( i = 1; i < vTokens->nSize; i++ ) - Io_ReadCreateAssert( p->pNtkCur, vTokens->pArray[i] ); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkLatch( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) -{ - Abc_Ntk_t * pNtk = p->pNtkCur; - Abc_Obj_t * pLatch; - int ResetValue; - if ( vTokens->nSize < 3 ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "The .latch line does not have enough tokens." ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - // create the latch - pLatch = Io_ReadCreateLatch( pNtk, vTokens->pArray[1], vTokens->pArray[2] ); - // get the latch reset value - if ( vTokens->nSize == 3 ) - Abc_LatchSetInitDc( pLatch ); - else - { - ResetValue = atoi(vTokens->pArray[vTokens->nSize-1]); - if ( ResetValue != 0 && ResetValue != 1 && ResetValue != 2 ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "The .latch line has an unknown reset value (%s).", vTokens->pArray[3] ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - if ( ResetValue == 0 ) - Abc_LatchSetInit0( pLatch ); - else if ( ResetValue == 1 ) - Abc_LatchSetInit1( pLatch ); - else if ( ResetValue == 2 ) - Abc_LatchSetInitDc( pLatch ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ) -{ - Vec_Ptr_t * vTokens = *pvTokens; - Abc_Ntk_t * pNtk = p->pNtkCur; - Abc_Obj_t * pNode; - char * pToken, Char, ** ppNames; - int nFanins, nNames; - - // create a new node and add it to the network - if ( vTokens->nSize < 2 ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "The .names line has less than two tokens." ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - - // create the node - ppNames = (char **)vTokens->pArray + 1; - nNames = vTokens->nSize - 2; - pNode = Io_ReadCreateNode( pNtk, ppNames[nNames], ppNames, nNames ); - - // derive the functionality of the node - p->vCubes->nSize = 0; - nFanins = vTokens->nSize - 2; - if ( nFanins == 0 ) - { - while ( vTokens = Io_ReadBlifGetTokens(p) ) - { - pToken = vTokens->pArray[0]; - if ( pToken[0] == '.' ) - break; - // read the cube - if ( vTokens->nSize != 1 ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "The number of tokens in the constant cube is wrong." ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - // create the cube - Char = ((char *)vTokens->pArray[0])[0]; - Vec_StrPush( p->vCubes, ' ' ); - Vec_StrPush( p->vCubes, Char ); - Vec_StrPush( p->vCubes, '\n' ); - } - } - else - { - while ( vTokens = Io_ReadBlifGetTokens(p) ) - { - pToken = vTokens->pArray[0]; - if ( pToken[0] == '.' ) - break; - // read the cube - if ( vTokens->nSize != 2 ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "The number of tokens in the cube is wrong." ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - // create the cube - Vec_StrAppend( p->vCubes, vTokens->pArray[0] ); - // check the char - Char = ((char *)vTokens->pArray[1])[0]; - if ( Char != '0' && Char != '1' && Char != 'x' && Char != 'n' ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "The output character in the constant cube is wrong." ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - Vec_StrPush( p->vCubes, ' ' ); - Vec_StrPush( p->vCubes, Char ); - Vec_StrPush( p->vCubes, '\n' ); - } - } - // if there is nothing there - if ( p->vCubes->nSize == 0 ) - { - // create an empty cube - Vec_StrPush( p->vCubes, ' ' ); - Vec_StrPush( p->vCubes, '0' ); - Vec_StrPush( p->vCubes, '\n' ); - } - Vec_StrPush( p->vCubes, 0 ); - - // set the pointer to the functionality of the node - Abc_ObjSetData( pNode, Abc_SopRegister(pNtk->pManFunc, p->vCubes->pArray) ); - - // check the size - if ( Abc_ObjFaninNum(pNode) != Abc_SopGetVarNum(Abc_ObjData(pNode)) ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "The number of fanins (%d) of node %s is different from SOP size (%d).", - Abc_ObjFaninNum(pNode), Abc_ObjName(Abc_ObjFanout(pNode,0)), Abc_SopGetVarNum(Abc_ObjData(pNode)) ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - - // return the last array of tokens - *pvTokens = vTokens; - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) -{ - Mio_Library_t * pGenlib; - Mio_Gate_t * pGate; - Abc_Obj_t * pNode; - char ** ppNames; - int i, nNames; - - // check that the library is available - pGenlib = Abc_FrameReadLibGen(); - if ( pGenlib == NULL ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "The current library is not available." ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - - // create a new node and add it to the network - if ( vTokens->nSize < 2 ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "The .gate line has less than two tokens." ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - - // get the gate - pGate = Mio_LibraryReadGateByName( pGenlib, vTokens->pArray[1] ); - if ( pGate == NULL ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "Cannot find gate \"%s\" in the library.", vTokens->pArray[1] ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - - // if this is the first line with gate, update the network type - if ( Abc_NtkNodeNum(p->pNtkCur) == 0 ) - { - assert( p->pNtkCur->ntkFunc == ABC_FUNC_SOP ); - p->pNtkCur->ntkFunc = ABC_FUNC_MAP; - Extra_MmFlexStop( p->pNtkCur->pManFunc ); - p->pNtkCur->pManFunc = pGenlib; - } - - // remove the formal parameter names - for ( i = 2; i < vTokens->nSize; i++ ) - { - vTokens->pArray[i] = Io_ReadBlifCleanName( vTokens->pArray[i] ); - if ( vTokens->pArray[i] == NULL ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "Invalid gate input assignment." ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - } - - // create the node - ppNames = (char **)vTokens->pArray + 2; - nNames = vTokens->nSize - 3; - pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames ); - - // set the pointer to the functionality of the node - Abc_ObjSetData( pNode, pGate ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Creates a multi-input multi-output box in the hierarchical design.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) -{ - Abc_Obj_t * pBox; - Vec_Ptr_t * vNames; - char * pName; - int i; - - // create a new node and add it to the network - if ( vTokens->nSize < 3 ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "The .subcircuit line has less than three tokens." ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - - // store the names of formal/actual inputs/outputs of the box - vNames = Vec_PtrAlloc( 10 ); - Vec_PtrForEachEntryStart( vTokens, pName, i, 1 ) -// Vec_PtrPush( vNames, Abc_NtkRegisterName(p->pNtkCur, pName) ); - Vec_PtrPush( vNames, Extra_UtilStrsav(pName) ); // memory leak!!! - - // create a new box and add it to the network - pBox = Abc_NtkCreateBlackbox( p->pNtkCur ); - // set the pointer to the node names - Abc_ObjSetData( pBox, vNames ); - // remember the line of the file - pBox->pCopy = (void *)Extra_FileReaderGetLineNumber(p->pReader, 0); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Io_ReadBlifCleanName( char * pName ) -{ - int i, Length; - Length = strlen(pName); - for ( i = 0; i < Length; i++ ) - if ( pName[i] == '=' ) - return pName + i + 1; - return NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) -{ - Abc_Obj_t * pNet; - char * pFoo1, * pFoo2; - double TimeRise, TimeFall; - - // make sure this is indeed the .inputs line - assert( strncmp( vTokens->pArray[0], ".input_arrival", 14 ) == 0 ); - if ( vTokens->nSize != 4 ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "Wrong number of arguments on .input_arrival line." ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - pNet = Abc_NtkFindNet( p->pNtkCur, vTokens->pArray[1] ); - if ( pNet == NULL ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "Cannot find object corresponding to %s on .input_arrival line.", vTokens->pArray[1] ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - TimeRise = strtod( vTokens->pArray[2], &pFoo1 ); - TimeFall = strtod( vTokens->pArray[3], &pFoo2 ); - if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .input_arrival line.", vTokens->pArray[2], vTokens->pArray[3] ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - // set the arrival time - Abc_NtkTimeSetArrival( p->pNtkCur, Abc_ObjFanin0(pNet)->Id, (float)TimeRise, (float)TimeFall ); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkDefaultInputArrival( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) -{ - char * pFoo1, * pFoo2; - double TimeRise, TimeFall; - - // make sure this is indeed the .inputs line - assert( strncmp( vTokens->pArray[0], ".default_input_arrival", 23 ) == 0 ); - if ( vTokens->nSize != 3 ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "Wrong number of arguments on .default_input_arrival line." ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - TimeRise = strtod( vTokens->pArray[1], &pFoo1 ); - TimeFall = strtod( vTokens->pArray[2], &pFoo2 ); - if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) - { - p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); - sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .default_input_arrival line.", vTokens->pArray[1], vTokens->pArray[2] ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - // set the arrival time - Abc_NtkTimeSetDefaultArrival( p->pNtkCur, (float)TimeRise, (float)TimeFall ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Prints the error message including the file name and line number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_ReadBlifPrintErrorMessage( Io_ReadBlif_t * p ) -{ - p->fError = 1; - if ( p->LineCur == 0 ) // the line number is not given - fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); - else // print the error message with the line number - fprintf( p->Output, "%s (line %d): %s\n", p->pFileName, p->LineCur, p->sError ); -} - -/**Function************************************************************* - - Synopsis [Gets the tokens taking into account the line breaks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) -{ - Vec_Ptr_t * vTokens; - char * pLastToken; - int i; - - // get rid of the old tokens - if ( p->vNewTokens->nSize > 0 ) - { - for ( i = 0; i < p->vNewTokens->nSize; i++ ) - free( p->vNewTokens->pArray[i] ); - p->vNewTokens->nSize = 0; - } - - // get the new tokens - vTokens = Extra_FileReaderGetTokens(p->pReader); - if ( vTokens == NULL ) - return vTokens; - - // check if there is a transfer to another line - pLastToken = vTokens->pArray[vTokens->nSize - 1]; - if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' ) - return vTokens; - - // remove the slash - pLastToken[ strlen(pLastToken)-1 ] = 0; - if ( pLastToken[0] == 0 ) - vTokens->nSize--; - // load them into the new array - for ( i = 0; i < vTokens->nSize; i++ ) - Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); - - // load as long as there is the line break - while ( 1 ) - { - // get the new tokens - vTokens = Extra_FileReaderGetTokens(p->pReader); - if ( vTokens->nSize == 0 ) - return p->vNewTokens; - // check if there is a transfer to another line - pLastToken = vTokens->pArray[vTokens->nSize - 1]; - if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' ) - { - // remove the slash - pLastToken[ strlen(pLastToken)-1 ] = 0; - if ( pLastToken[0] == 0 ) - vTokens->nSize--; - // load them into the new array - for ( i = 0; i < vTokens->nSize; i++ ) - Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); - continue; - } - // otherwise, load them and break - for ( i = 0; i < vTokens->nSize; i++ ) - Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav(vTokens->pArray[i]) ); - break; - } - return p->vNewTokens; -} - -/**Function************************************************************* - - Synopsis [Starts the reading data structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Io_ReadBlif_t * Io_ReadBlifFile( char * pFileName ) -{ - Extra_FileReader_t * pReader; - Io_ReadBlif_t * p; - - // start the reader - pReader = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t" ); - - if ( pReader == NULL ) - return NULL; - - // start the reading data structure - p = ALLOC( Io_ReadBlif_t, 1 ); - memset( p, 0, sizeof(Io_ReadBlif_t) ); - p->pFileName = pFileName; - p->pReader = pReader; - p->Output = stdout; - p->vNewTokens = Vec_PtrAlloc( 100 ); - p->vCubes = Vec_StrAlloc( 100 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the data structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_ReadBlifFree( Io_ReadBlif_t * p ) -{ - Extra_FileReaderFree( p->pReader ); - Vec_PtrFree( p->vNewTokens ); - Vec_StrFree( p->vCubes ); - free( p ); -} - - -/**Function************************************************************* - - Synopsis [Connect one box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkConnectBoxesOneBox( Io_ReadBlif_t * p, Abc_Obj_t * pBox, stmm_table * tName2Model ) -{ - Vec_Ptr_t * pNames; - Abc_Ntk_t * pNtkModel; - Abc_Obj_t * pObj, * pNet; - char * pName, * pActual; - int i, Length, Start; - - // get the model for this box - pNames = pBox->pData; - if ( !stmm_lookup( tName2Model, Vec_PtrEntry(pNames, 0), (char **)&pNtkModel ) ) - { - p->LineCur = (int)pBox->pCopy; - sprintf( p->sError, "Cannot find the model for subcircuit %s.", Vec_PtrEntry(pNames, 0) ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - - // create the fanins of the box - Abc_NtkForEachPi( pNtkModel, pObj, i ) - pObj->pCopy = NULL; - if ( Abc_NtkPiNum(pNtkModel) == 0 ) - Start = 1; - else - { - Vec_PtrForEachEntryStart( pNames, pName, i, 1 ) - { - pActual = Io_ReadBlifCleanName(pName); - if ( pActual == NULL ) - { - p->LineCur = (int)pBox->pCopy; - sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - Length = pActual - pName - 1; - pName[Length] = 0; - // find the PI net with this name - pObj = Abc_NtkFindNet( pNtkModel, pName ); - if ( pObj == NULL ) - { - p->LineCur = (int)pBox->pCopy; - sprintf( p->sError, "Cannot find formal input \"%s\" as an PI of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - // get the PI - pObj = Abc_ObjFanin0(pObj); - // quit if this is not a PI net - if ( !Abc_ObjIsPi(pObj) ) - { - pName[Length] = '='; - Start = i; - break; - } - // remember the actual name in the net - if ( pObj->pCopy != NULL ) - { - p->LineCur = (int)pBox->pCopy; - sprintf( p->sError, "Formal input \"%s\" is used more than once.", pName ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - pObj->pCopy = (void *)pActual; - // quit if we processed all PIs - if ( i == Abc_NtkPiNum(pNtkModel) ) - { - Start = i+1; - break; - } - } - } - // create the fanins of the box - Abc_NtkForEachPi( pNtkModel, pObj, i ) - { - pActual = (void *)pObj->pCopy; - if ( pActual == NULL ) - { - p->LineCur = (int)pBox->pCopy; - sprintf( p->sError, "Formal input \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); - Abc_ObjAddFanin( pBox, pNet ); - } - Abc_NtkForEachPi( pNtkModel, pObj, i ) - pObj->pCopy = NULL; - - // create the fanouts of the box - Abc_NtkForEachPo( pNtkModel, pObj, i ) - pObj->pCopy = NULL; - Vec_PtrForEachEntryStart( pNames, pName, i, Start ) - { - pActual = Io_ReadBlifCleanName(pName); - if ( pActual == NULL ) - { - p->LineCur = (int)pBox->pCopy; - sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - Length = pActual - pName - 1; - pName[Length] = 0; - // find the PO net with this name - pObj = Abc_NtkFindNet( pNtkModel, pName ); - if ( pObj == NULL ) - { - p->LineCur = (int)pBox->pCopy; - sprintf( p->sError, "Cannot find formal output \"%s\" as an PO of model \"%s\".", pName, Vec_PtrEntry(pNames, 0) ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - // get the PO - pObj = Abc_ObjFanout0(pObj); - if ( pObj->pCopy != NULL ) - { - p->LineCur = (int)pBox->pCopy; - sprintf( p->sError, "Formal output \"%s\" is used more than once.", pName ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - pObj->pCopy = (void *)pActual; - } - // create the fanouts of the box - Abc_NtkForEachPo( pNtkModel, pObj, i ) - { - pActual = (void *)pObj->pCopy; - if ( pActual == NULL ) - { - p->LineCur = (int)pBox->pCopy; - sprintf( p->sError, "Formal output \"%s\" of model %s is not driven.", pName, Vec_PtrEntry(pNames, 0) ); - Io_ReadBlifPrintErrorMessage( p ); - return 1; - } - pNet = Abc_NtkFindOrCreateNet( pBox->pNtk, pActual ); - Abc_ObjAddFanin( pNet, pBox ); - } - Abc_NtkForEachPo( pNtkModel, pObj, i ) - pObj->pCopy = NULL; - - // remove the array of names, assign the pointer to the model - Vec_PtrForEachEntry( pBox->pData, pName, i ) - free( pName ); - Vec_PtrFree( pBox->pData ); - pBox->pData = pNtkModel; - return 0; -} - -/**Function************************************************************* - - Synopsis [Connect the boxes in the hierarchy of networks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkConnectBoxesOne( Io_ReadBlif_t * p, Abc_Ntk_t * pNtk, stmm_table * tName2Model ) -{ - Abc_Obj_t * pBox; - int i; - // go through the boxes - Abc_NtkForEachBlackbox( pNtk, pBox, i ) - if ( Io_ReadBlifNetworkConnectBoxesOneBox( p, pBox, tName2Model ) ) - return 1; - Abc_NtkFinalizeRead( pNtk ); - return 0; -} - -#if 0 - -/**Function************************************************************* - - Synopsis [Connect the boxes in the hierarchy of networks.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadBlifNetworkConnectBoxes( Io_ReadBlif_t * p, Abc_Ntk_t * pNtkMaster ) -{ - stmm_generator * gen; - Abc_Ntk_t * pNtk; - char * pName; - // connect the master network - if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtkMaster, pNtkMaster->tName2Model ) ) - return 1; - // connect other networks - stmm_foreach_item( pNtkMaster->tName2Model, gen, &pName, (char **)&pNtk ) - if ( Io_ReadBlifNetworkConnectBoxesOne( p, pNtk, pNtkMaster->tName2Model ) ) - return 1; - return 0; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioReadBlifAig.c b/src/base/io/ioReadBlifAig.c deleted file mode 100644 index c448bab6..00000000 --- a/src/base/io/ioReadBlifAig.c +++ /dev/null @@ -1,1013 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioReadBlifAig.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to read BLIF file into AIG.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - December 23, 2006.] - - Revision [$Id: ioReadBlifAig.c,v 1.00 2006/12/23 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "extra.h" -#include "vecPtr.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// latch initial values -typedef enum { - IO_BLIF_INIT_NONE = 0, // 0: unknown - IO_BLIF_INIT_ZERO, // 1: zero - IO_BLIF_INIT_ONE, // 2: one - IO_BLIF_INIT_DC // 3: don't-care -} Io_BlifInit_t; - -typedef struct Io_BlifObj_t_ Io_BlifObj_t; // parsing object -struct Io_BlifObj_t_ -{ - unsigned fPi : 1; // the object is a primary input - unsigned fPo : 1; // the object is a primary output - unsigned fLi : 1; // the object is a latch input - unsigned fLo : 1; // the object is a latch output - unsigned fDef : 1; // the object is defined as a table (node, PO, LI) - unsigned fLoop : 1; // flag for loop detection - unsigned Init : 2; // the latch initial state - unsigned Offset : 24; // temporary number - char * pName; // the name of this object - void * pEquiv; // the AIG node representing this line - Io_BlifObj_t * pNext; // the next obj in the hash table -}; - -typedef struct Io_BlifMan_t_ Io_BlifMan_t; // parsing manager -struct Io_BlifMan_t_ -{ - // general info about file - char * pFileName; // the name of the file - char * pBuffer; // the begining of the file buffer - Vec_Ptr_t * vLines; // the line beginnings - // temporary objects - Io_BlifObj_t * pObjects; // the storage for objects - int nObjects; // the number of objects allocated - int iObjNext; // the next free object - // file lines - char * pModel; // .model line - Vec_Ptr_t * vInputs; // .inputs lines - Vec_Ptr_t * vOutputs; // .outputs lines - Vec_Ptr_t * vLatches; // .latches lines - Vec_Ptr_t * vNames; // .names lines - // network objects - Vec_Ptr_t * vPis; // the PI structures - Vec_Ptr_t * vPos; // the PO structures - Vec_Ptr_t * vLis; // the LI structures - Vec_Ptr_t * vLos; // the LO structures - // mapping of names into objects - Io_BlifObj_t ** pTable; // the hash table - int nTableSize; // the hash table size - // current processing info - Abc_Ntk_t * pAig; // the network under construction - Vec_Ptr_t * vTokens; // the current tokens - char sError[512]; // the error string generated during parsing - // statistics - int nTablesRead; // the number of processed tables - int nTablesLeft; // the number of dangling tables -}; - -// static functions -static Io_BlifMan_t * Io_BlifAlloc(); -static void Io_BlifFree( Io_BlifMan_t * p ); -static char * Io_BlifLoadFile( char * pFileName ); -static void Io_BlifReadPreparse( Io_BlifMan_t * p ); -static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p ); -static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine ); -static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine ); -static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine ); -static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine ); -static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine ); -static int Io_BlifParseConstruct( Io_BlifMan_t * p ); -static int Io_BlifCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the network from the BLIF file as an AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadBlifAsAig( char * pFileName, int fCheck ) -{ - FILE * pFile; - Io_BlifMan_t * p; - Abc_Ntk_t * pAig; - - // check that the file is available - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Io_Blif(): The file is unavailable (absent or open).\n" ); - return 0; - } - fclose( pFile ); - - // start the file reader - p = Io_BlifAlloc(); - p->pFileName = pFileName; - p->pBuffer = Io_BlifLoadFile( pFileName ); - if ( p->pBuffer == NULL ) - { - Io_BlifFree( p ); - return NULL; - } - // prepare the file for parsing - Io_BlifReadPreparse( p ); - // construct the network - pAig = Io_BlifParse( p ); - if ( p->sError[0] ) - fprintf( stdout, "%s\n", p->sError ); - if ( pAig == NULL ) - return NULL; - Io_BlifFree( p ); - - // make sure that everything is okay with the network structure - if ( fCheck && !Abc_NtkCheckRead( pAig ) ) - { - printf( "Io_Blif: The network check has failed.\n" ); - Abc_NtkDelete( pAig ); - return NULL; - } - return pAig; -} - -/**Function************************************************************* - - Synopsis [Allocates the BLIF parsing structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Io_BlifMan_t * Io_BlifAlloc() -{ - Io_BlifMan_t * p; - p = ALLOC( Io_BlifMan_t, 1 ); - memset( p, 0, sizeof(Io_BlifMan_t) ); - p->vLines = Vec_PtrAlloc( 512 ); - p->vInputs = Vec_PtrAlloc( 512 ); - p->vOutputs = Vec_PtrAlloc( 512 ); - p->vLatches = Vec_PtrAlloc( 512 ); - p->vNames = Vec_PtrAlloc( 512 ); - p->vTokens = Vec_PtrAlloc( 512 ); - p->vPis = Vec_PtrAlloc( 512 ); - p->vPos = Vec_PtrAlloc( 512 ); - p->vLis = Vec_PtrAlloc( 512 ); - p->vLos = Vec_PtrAlloc( 512 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the BLIF parsing structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_BlifFree( Io_BlifMan_t * p ) -{ - if ( p->pAig ) - Abc_NtkDelete( p->pAig ); - if ( p->pBuffer ) free( p->pBuffer ); - if ( p->pObjects ) free( p->pObjects ); - if ( p->pTable ) free( p->pTable ); - Vec_PtrFree( p->vLines ); - Vec_PtrFree( p->vInputs ); - Vec_PtrFree( p->vOutputs ); - Vec_PtrFree( p->vLatches ); - Vec_PtrFree( p->vNames ); - Vec_PtrFree( p->vTokens ); - Vec_PtrFree( p->vPis ); - Vec_PtrFree( p->vPos ); - Vec_PtrFree( p->vLis ); - Vec_PtrFree( p->vLos ); - free( p ); -} - - -/**Function************************************************************* - - Synopsis [Hashing for character strings.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static unsigned Io_BlifHashString( char * pName, int TableSize ) -{ - static int s_Primes[10] = { - 1291, 1699, 2357, 4177, 5147, - 5647, 6343, 7103, 7873, 8147 - }; - unsigned i, Key = 0; - for ( i = 0; pName[i] != '\0'; i++ ) - Key ^= s_Primes[i%10]*pName[i]*pName[i]; - return Key % TableSize; -} - -/**Function************************************************************* - - Synopsis [Checks if the given name exists in the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Io_BlifObj_t ** Io_BlifHashLookup( Io_BlifMan_t * p, char * pName ) -{ - Io_BlifObj_t ** ppEntry; - for ( ppEntry = p->pTable + Io_BlifHashString(pName, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) - if ( !strcmp((*ppEntry)->pName, pName) ) - return ppEntry; - return ppEntry; -} - -/**Function************************************************************* - - Synopsis [Finds or add the given name to the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Io_BlifObj_t * Io_BlifHashFindOrAdd( Io_BlifMan_t * p, char * pName ) -{ - Io_BlifObj_t ** ppEntry; - ppEntry = Io_BlifHashLookup( p, pName ); - if ( *ppEntry == NULL ) - { - assert( p->iObjNext < p->nObjects ); - *ppEntry = p->pObjects + p->iObjNext++; - (*ppEntry)->pName = pName; - } - return *ppEntry; -} - - -/**Function************************************************************* - - Synopsis [Collects the already split tokens.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_BlifCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput ) -{ - char * pCur; - Vec_PtrClear( vTokens ); - for ( pCur = pInput; pCur < pOutput; pCur++ ) - { - if ( *pCur == 0 ) - continue; - Vec_PtrPush( vTokens, pCur ); - while ( *++pCur ); - } -} - -/**Function************************************************************* - - Synopsis [Splits the line into tokens.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_BlifSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) -{ - char * pCur; - // clear spaces - for ( pCur = pLine; *pCur != Stop; pCur++ ) - if ( Io_BlifCharIsSpace(*pCur) ) - *pCur = 0; - // collect tokens - Io_BlifCollectTokens( vTokens, pLine, pCur ); -} - -/**Function************************************************************* - - Synopsis [Returns the 1-based number of the line in which the token occurs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_BlifGetLine( Io_BlifMan_t * p, char * pToken ) -{ - char * pLine; - int i; - Vec_PtrForEachEntry( p->vLines, pLine, i ) - if ( pToken < pLine ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [Conservatively estimates the number of primary inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_BlifEstimatePiNum( Io_BlifMan_t * p ) -{ - char * pCur; - int i, fSpaces; - int Counter = 0; - Vec_PtrForEachEntry( p->vInputs, pCur, i ) - for ( fSpaces = 0; *pCur; pCur++ ) - { - if ( Io_BlifCharIsSpace(*pCur) ) - { - if ( !fSpaces ) - Counter++; - fSpaces = 1; - } - else - fSpaces = 0; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Conservatively estimates the number of AIG nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_BlifEstimateAndNum( Io_BlifMan_t * p ) -{ - Io_BlifObj_t * pObj; - char * pCur; - int i, CounterOne, Counter = 0; - for ( i = 0; i < p->iObjNext; i++ ) - { - pObj = p->pObjects + i; - if ( !pObj->fDef ) - continue; - CounterOne = 0; - for ( pCur = pObj->pName + strlen(pObj->pName); *pCur != '.'; pCur++ ) - if ( *pCur == '0' || *pCur == '1' ) - CounterOne++; - if ( CounterOne ) - Counter += CounterOne - 1; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Reads the file into a character buffer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static char * Io_BlifLoadFile( char * pFileName ) -{ - FILE * pFile; - int nFileSize; - char * pContents; - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Io_BlifLoadFile(): The file is unavailable (absent or open).\n" ); - return NULL; - } - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - if ( nFileSize == 0 ) - { - printf( "Io_BlifLoadFile(): The file is empty.\n" ); - return NULL; - } - pContents = ALLOC( char, nFileSize + 10 ); - rewind( pFile ); - fread( pContents, nFileSize, 1, pFile ); - fclose( pFile ); - // finish off the file with the spare .end line - // some benchmarks suddenly break off without this line - strcpy( pContents + nFileSize, "\n.end\n" ); - return pContents; -} - -/**Function************************************************************* - - Synopsis [Prepares the parsing.] - - Description [Performs several preliminary operations: - - Cuts the file buffer into separate lines. - - Removes comments and line extenders. - - Sorts lines by directives. - - Estimates the number of objects. - - Allocates room for the objects. - - Allocates room for the hash table.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_BlifReadPreparse( Io_BlifMan_t * p ) -{ - char * pCur, * pPrev; - int i, fComment = 0; - // parse the buffer into lines and remove comments - Vec_PtrPush( p->vLines, p->pBuffer ); - for ( pCur = p->pBuffer; *pCur; pCur++ ) - { - if ( *pCur == '\n' ) - { - *pCur = 0; - fComment = 0; - Vec_PtrPush( p->vLines, pCur + 1 ); - } - else if ( *pCur == '#' ) - fComment = 1; - // remove comments - if ( fComment ) - *pCur = 0; - } - - // unfold the line extensions and sort lines by directive - Vec_PtrForEachEntry( p->vLines, pCur, i ) - { - if ( *pCur == 0 ) - continue; - // find previous non-space character - for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- ) - if ( !Io_BlifCharIsSpace(*pPrev) ) - break; - // if it is the line extender, overwrite it with spaces - if ( *pPrev == '\\' ) - { - for ( ; *pPrev; pPrev++ ) - *pPrev = ' '; - *pPrev = ' '; - continue; - } - // skip spaces at the beginning of the line - while ( Io_BlifCharIsSpace(*pCur++) ); - // parse directives - if ( *(pCur-1) != '.' ) - continue; - if ( !strncmp(pCur, "names", 5) ) - Vec_PtrPush( p->vNames, pCur ); - else if ( !strncmp(pCur, "latch", 5) ) - Vec_PtrPush( p->vLatches, pCur ); - else if ( !strncmp(pCur, "inputs", 6) ) - Vec_PtrPush( p->vInputs, pCur ); - else if ( !strncmp(pCur, "outputs", 7) ) - Vec_PtrPush( p->vOutputs, pCur ); - else if ( !strncmp(pCur, "model", 5) ) - p->pModel = pCur; - else if ( !strncmp(pCur, "end", 3) || !strncmp(pCur, "exdc", 4) ) - break; - else - { - pCur--; - if ( pCur[strlen(pCur)-1] == '\r' ) - pCur[strlen(pCur)-1] = 0; - fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_BlifGetLine(p, pCur), pCur ); - } - } - - // count the number of objects - p->nObjects = Io_BlifEstimatePiNum(p) + Vec_PtrSize(p->vLatches) + Vec_PtrSize(p->vNames) + 512; - - // allocate memory for objects - p->pObjects = ALLOC( Io_BlifObj_t, p->nObjects ); - memset( p->pObjects, 0, p->nObjects * sizeof(Io_BlifObj_t) ); - - // allocate memory for the hash table - p->nTableSize = p->nObjects/2 + 1; - p->pTable = ALLOC( Io_BlifObj_t *, p->nTableSize ); - memset( p->pTable, 0, p->nTableSize * sizeof(Io_BlifObj_t *) ); -} - - -/**Function************************************************************* - - Synopsis [Reads the AIG in the binary AIGER format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Abc_Ntk_t * Io_BlifParse( Io_BlifMan_t * p ) -{ - Abc_Ntk_t * pAig; - char * pLine; - int i; - // parse the model - if ( !Io_BlifParseModel( p, p->pModel ) ) - return NULL; - // parse the inputs - Vec_PtrForEachEntry( p->vInputs, pLine, i ) - if ( !Io_BlifParseInputs( p, pLine ) ) - return NULL; - // parse the outputs - Vec_PtrForEachEntry( p->vOutputs, pLine, i ) - if ( !Io_BlifParseOutputs( p, pLine ) ) - return NULL; - // parse the latches - Vec_PtrForEachEntry( p->vLatches, pLine, i ) - if ( !Io_BlifParseLatch( p, pLine ) ) - return NULL; - // parse the nodes - Vec_PtrForEachEntry( p->vNames, pLine, i ) - if ( !Io_BlifParseNames( p, pLine ) ) - return NULL; - // reconstruct the network from the parsed data - if ( !Io_BlifParseConstruct( p ) ) - return NULL; - // return the network - pAig = p->pAig; - p->pAig = NULL; - return pAig; -} - -/**Function************************************************************* - - Synopsis [Parses the model line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_BlifParseModel( Io_BlifMan_t * p, char * pLine ) -{ - char * pToken; - Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry( p->vTokens, 0 ); - assert( !strcmp(pToken, "model") ); - if ( Vec_PtrSize(p->vTokens) != 2 ) - { - sprintf( p->sError, "Line %d: Model line has %d entries while it should have 2.", Io_BlifGetLine(p, pToken), Vec_PtrSize(p->vTokens) ); - return 0; - } - p->pModel = Vec_PtrEntry( p->vTokens, 1 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the inputs line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_BlifParseInputs( Io_BlifMan_t * p, char * pLine ) -{ - Io_BlifObj_t * pObj; - char * pToken; - int i; - Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry(p->vTokens, 0); - assert( !strcmp(pToken, "inputs") ); - Vec_PtrForEachEntryStart( p->vTokens, pToken, i, 1 ) - { - pObj = Io_BlifHashFindOrAdd( p, pToken ); - if ( pObj->fPi ) - { - sprintf( p->sError, "Line %d: Primary input (%s) is defined more than once.", Io_BlifGetLine(p, pToken), pToken ); - return 0; - } - pObj->fPi = 1; - Vec_PtrPush( p->vPis, pObj ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the outputs line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_BlifParseOutputs( Io_BlifMan_t * p, char * pLine ) -{ - Io_BlifObj_t * pObj; - char * pToken; - int i; - Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry(p->vTokens, 0); - assert( !strcmp(pToken, "outputs") ); - Vec_PtrForEachEntryStart( p->vTokens, pToken, i, 1 ) - { - pObj = Io_BlifHashFindOrAdd( p, pToken ); - if ( pObj->fPo ) - fprintf( stdout, "Line %d: Primary output (%s) is defined more than once (warning only).\n", Io_BlifGetLine(p, pToken), pToken ); - pObj->fPo = 1; - Vec_PtrPush( p->vPos, pObj ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the latches line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_BlifParseLatch( Io_BlifMan_t * p, char * pLine ) -{ - Io_BlifObj_t * pObj; - char * pToken; - int Init; - Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry(p->vTokens,0); - assert( !strcmp(pToken, "latch") ); - if ( Vec_PtrSize(p->vTokens) < 3 ) - { - sprintf( p->sError, "Line %d: Latch does not have input name and output name.", Io_BlifGetLine(p, pToken) ); - return 0; - } - // get initial value - if ( Vec_PtrSize(p->vTokens) > 3 ) - Init = atoi( Vec_PtrEntry(p->vTokens,3) ); - else - Init = 2; - if ( Init < 0 || Init > 2 ) - { - sprintf( p->sError, "Line %d: Initial state of the latch is incorrect (%s).", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,3) ); - return 0; - } - if ( Init == 0 ) - Init = IO_BLIF_INIT_ZERO; - else if ( Init == 1 ) - Init = IO_BLIF_INIT_ONE; - else // if ( Init == 2 ) - Init = IO_BLIF_INIT_DC; - // get latch input - pObj = Io_BlifHashFindOrAdd( p, Vec_PtrEntry(p->vTokens,1) ); - pObj->fLi = 1; - Vec_PtrPush( p->vLis, pObj ); - pObj->Init = Init; - // get latch output - pObj = Io_BlifHashFindOrAdd( p, Vec_PtrEntry(p->vTokens,2) ); - if ( pObj->fPi ) - { - sprintf( p->sError, "Line %d: Primary input (%s) is also defined latch output.", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,2) ); - return 0; - } - if ( pObj->fLo ) - { - sprintf( p->sError, "Line %d: Latch output (%s) is defined as the output of another latch.", Io_BlifGetLine(p, pToken), Vec_PtrEntry(p->vTokens,2) ); - return 0; - } - pObj->fLo = 1; - Vec_PtrPush( p->vLos, pObj ); - pObj->Init = Init; - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the nodes line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_BlifParseNames( Io_BlifMan_t * p, char * pLine ) -{ - Io_BlifObj_t * pObj; - char * pName; - Io_BlifSplitIntoTokens( p->vTokens, pLine, '\0' ); - assert( !strcmp(Vec_PtrEntry(p->vTokens,0), "names") ); - pName = Vec_PtrEntryLast( p->vTokens ); - pObj = Io_BlifHashFindOrAdd( p, pName ); - if ( pObj->fPi ) - { - sprintf( p->sError, "Line %d: Primary input (%s) has a table.", Io_BlifGetLine(p, pName), pName ); - return 0; - } - if ( pObj->fLo ) - { - sprintf( p->sError, "Line %d: Latch output (%s) has a table.", Io_BlifGetLine(p, pName), pName ); - return 0; - } - if ( pObj->fDef ) - { - sprintf( p->sError, "Line %d: Signal (%s) is defined more than once.", Io_BlifGetLine(p, pName), pName ); - return 0; - } - pObj->fDef = 1; - // remember offset to the first fanin name - pObj->pName = pName; - pObj->Offset = pObj->pName - (char *)Vec_PtrEntry(p->vTokens,1); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Constructs the AIG from the file parsing info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Abc_Obj_t * Io_BlifParseTable( Io_BlifMan_t * p, char * pTable, Vec_Ptr_t * vFanins ) -{ - char * pProduct, * pOutput; - Abc_Obj_t * pRes, * pCube; - int i, k, Polarity = -1; - - p->nTablesRead++; - // get the tokens - Io_BlifSplitIntoTokens( p->vTokens, pTable, '.' ); - if ( Vec_PtrSize(p->vTokens) == 0 ) - return Abc_ObjNot( Abc_AigConst1(p->pAig) ); - if ( Vec_PtrSize(p->vTokens) == 1 ) - { - pOutput = Vec_PtrEntry( p->vTokens, 0 ); - if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) - { - sprintf( p->sError, "Line %d: Constant table has wrong output value (%s).", Io_BlifGetLine(p, pOutput), pOutput ); - return NULL; - } - return Abc_ObjNotCond( Abc_AigConst1(p->pAig), pOutput[0] == '0' ); - } - pProduct = Vec_PtrEntry( p->vTokens, 0 ); - if ( Vec_PtrSize(p->vTokens) % 2 == 1 ) - { - sprintf( p->sError, "Line %d: Table has odd number of tokens (%d).", Io_BlifGetLine(p, pProduct), Vec_PtrSize(p->vTokens) ); - return NULL; - } - // parse the table - pRes = Abc_ObjNot( Abc_AigConst1(p->pAig) ); - for ( i = 0; i < Vec_PtrSize(p->vTokens)/2; i++ ) - { - pProduct = Vec_PtrEntry( p->vTokens, 2*i + 0 ); - pOutput = Vec_PtrEntry( p->vTokens, 2*i + 1 ); - if ( strlen(pProduct) != (unsigned)Vec_PtrSize(vFanins) ) - { - sprintf( p->sError, "Line %d: Cube (%s) has size different from the fanin count (%d).", Io_BlifGetLine(p, pProduct), pProduct, Vec_PtrSize(vFanins) ); - return NULL; - } - if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) - { - sprintf( p->sError, "Line %d: Output value (%s) is incorrect.", Io_BlifGetLine(p, pProduct), pOutput ); - return NULL; - } - if ( Polarity == -1 ) - Polarity = pOutput[0] - '0'; - else if ( Polarity != pOutput[0] - '0' ) - { - sprintf( p->sError, "Line %d: Output value (%s) differs from the value in the first line of the table (%d).", Io_BlifGetLine(p, pProduct), pOutput, Polarity ); - return NULL; - } - // parse one product product - pCube = Abc_AigConst1(p->pAig); - for ( k = 0; pProduct[k]; k++ ) - { - if ( pProduct[k] == '0' ) - pCube = Abc_AigAnd( p->pAig->pManFunc, pCube, Abc_ObjNot(Vec_PtrEntry(vFanins,k)) ); - else if ( pProduct[k] == '1' ) - pCube = Abc_AigAnd( p->pAig->pManFunc, pCube, Vec_PtrEntry(vFanins,k) ); - else if ( pProduct[k] != '-' ) - { - sprintf( p->sError, "Line %d: Product term (%s) contains character (%c).", Io_BlifGetLine(p, pProduct), pProduct, pProduct[k] ); - return NULL; - } - } - pRes = Abc_AigOr( p->pAig->pManFunc, pRes, pCube ); - } - pRes = Abc_ObjNotCond( pRes, Polarity == 0 ); - return pRes; -} - -/**Function************************************************************* - - Synopsis [Constructs the AIG from the file parsing info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Abc_Obj_t * Io_BlifParseConstruct_rec( Io_BlifMan_t * p, char * pName ) -{ - Vec_Ptr_t * vFanins; - Abc_Obj_t * pFaninAbc; - Io_BlifObj_t * pObjIo; - char * pNameFanin; - int i; - // get the IO object with this name - pObjIo = *Io_BlifHashLookup( p, pName ); - if ( pObjIo == NULL ) - { - sprintf( p->sError, "Line %d: Signal (%s) is not defined as a table.", Io_BlifGetLine(p, pName), pName ); - return NULL; - } - // loop detection - if ( pObjIo->fLoop ) - { - sprintf( p->sError, "Line %d: Signal (%s) appears twice on a combinational path.", Io_BlifGetLine(p, pName), pName ); - return NULL; - } - // check if the AIG is already constructed - if ( pObjIo->pEquiv ) - return pObjIo->pEquiv; - // mark this node on the path - pObjIo->fLoop = 1; - // construct the AIGs for the fanins - vFanins = Vec_PtrAlloc( 8 ); - Io_BlifCollectTokens( vFanins, pObjIo->pName - pObjIo->Offset, pObjIo->pName ); - Vec_PtrForEachEntry( vFanins, pNameFanin, i ) - { - pFaninAbc = Io_BlifParseConstruct_rec( p, pNameFanin ); - if ( pFaninAbc == NULL ) - { - Vec_PtrFree( vFanins ); - return NULL; - } - Vec_PtrWriteEntry( vFanins, i, pFaninAbc ); - } - // construct the node - pObjIo->pEquiv = Io_BlifParseTable( p, pObjIo->pName + strlen(pObjIo->pName), vFanins ); - Vec_PtrFree( vFanins ); - // unmark this node on the path - pObjIo->fLoop = 0; - // remember the new node - return pObjIo->pEquiv; -} - -/**Function************************************************************* - - Synopsis [Constructs the AIG from the file parsing info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_BlifParseConstruct( Io_BlifMan_t * p ) -{ - Abc_Ntk_t * pAig; - Io_BlifObj_t * pObjIo, * pObjIoInput; - Abc_Obj_t * pObj, * pLatch; - int i; - // allocate the empty AIG - pAig = p->pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - pAig->pName = Extra_UtilStrsav( p->pModel ); - pAig->pSpec = Extra_UtilStrsav( p->pFileName ); - // create PIs - Vec_PtrForEachEntry( p->vPis, pObjIo, i ) - { - pObj = Abc_NtkCreatePi( pAig ); - Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); - pObjIo->pEquiv = pObj; - } - // create POs - Vec_PtrForEachEntry( p->vPos, pObjIo, i ) - { - pObj = Abc_NtkCreatePo( pAig ); - Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); - } - // create latches - Vec_PtrForEachEntry( p->vLos, pObjIo, i ) - { - // add the latch input terminal - pObj = Abc_NtkCreateBi( pAig ); - pObjIoInput = Vec_PtrEntry( p->vLis, i ); - Abc_ObjAssignName( pObj, pObjIoInput->pName, NULL ); - - // add the latch box - pLatch = Abc_NtkCreateLatch( pAig ); - pLatch->pData = (void *)pObjIo->Init; - Abc_ObjAssignName( pLatch, pObjIo->pName, "L" ); - Abc_ObjAddFanin( pLatch, pObj ); - - // add the latch output terminal - pObj = Abc_NtkCreateBo( pAig ); - Abc_ObjAssignName( pObj, pObjIo->pName, NULL ); - Abc_ObjAddFanin( pObj, pLatch ); - // set the value of the latch output -// pObjIo->pEquiv = Abc_ObjNotCond( pObj, pObjIo->Init ); - pObjIo->pEquiv = pObj; - } - // traverse the nodes from the POs - Vec_PtrForEachEntry( p->vPos, pObjIo, i ) - { - pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName ); - if ( pObj == NULL ) - return 0; - Abc_ObjAddFanin( Abc_NtkPo(p->pAig, i), pObj ); - } - // traverse the nodes from the latch inputs - Vec_PtrForEachEntry( p->vLis, pObjIo, i ) - { - pObj = Io_BlifParseConstruct_rec( p, pObjIo->pName ); - if ( pObj == NULL ) - return 0; -// pObj = Abc_ObjNotCond( pObj, pObjIo->Init ); - Abc_ObjAddFanin( Abc_ObjFanin0(Abc_NtkBox(p->pAig, i)), pObj ); - } - p->nTablesLeft = Vec_PtrSize(p->vNames) - p->nTablesRead; - if ( p->nTablesLeft ) - printf( "The number of dangling tables = %d.\n", p->nTablesLeft ); - printf( "AND nodes = %6d. Estimate = %6d.\n", Abc_NtkNodeNum(p->pAig), Io_BlifEstimateAndNum(p) ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioReadBlifMv.c b/src/base/io/ioReadBlifMv.c deleted file mode 100644 index 18578cbb..00000000 --- a/src/base/io/ioReadBlifMv.c +++ /dev/null @@ -1,1696 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioReadBlifMv.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to read BLIF-MV file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 8, 2007.] - - Revision [$Id: ioReadBlifMv.c,v 1.00 2007/01/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "extra.h" -#include "vecPtr.h" -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define IO_BLIFMV_MAXVALUES 256 - -typedef struct Io_MvVar_t_ Io_MvVar_t; // parsing var -typedef struct Io_MvMod_t_ Io_MvMod_t; // parsing model -typedef struct Io_MvMan_t_ Io_MvMan_t; // parsing manager - -struct Io_MvVar_t_ -{ - int nValues; // the number of values - char ** pNames; // the value names -}; - -struct Io_MvMod_t_ -{ - // file lines - char * pName; // .model line - Vec_Ptr_t * vInputs; // .inputs lines - Vec_Ptr_t * vOutputs; // .outputs lines - Vec_Ptr_t * vLatches; // .latch lines - Vec_Ptr_t * vResets; // .reset lines - Vec_Ptr_t * vNames; // .names lines - Vec_Ptr_t * vSubckts; // .subckt lines - Vec_Ptr_t * vMvs; // .mv lines - int fBlackBox; // indicates blackbox model - // the resulting network - Abc_Ntk_t * pNtk; - Abc_Obj_t * pResetLatch; - // the parent manager - Io_MvMan_t * pMan; -}; - -struct Io_MvMan_t_ -{ - // general info about file - int fBlifMv; // the file is BLIF-MV - int fUseReset; // the reset circuitry is added - char * pFileName; // the name of the file - char * pBuffer; // the contents of the file - Vec_Ptr_t * vLines; // the line beginnings - // the results of reading - Abc_Lib_t * pDesign; // the design under construction - int nNDnodes; // the counter of ND nodes - // intermediate storage for models - Vec_Ptr_t * vModels; // vector of models - Io_MvMod_t * pLatest; // the current model - // current processing info - Vec_Ptr_t * vTokens; // the current tokens - Vec_Ptr_t * vTokens2; // the current tokens - Vec_Str_t * vFunc; // the local function - // error reporting - char sError[512]; // the error string generated during parsing - // statistics - int nTablesRead; // the number of processed tables - int nTablesLeft; // the number of dangling tables -}; - -// static functions -static Io_MvMan_t * Io_MvAlloc(); -static void Io_MvFree( Io_MvMan_t * p ); -static Io_MvMod_t * Io_MvModAlloc(); -static void Io_MvModFree( Io_MvMod_t * p ); -static char * Io_MvLoadFile( char * pFileName ); -static void Io_MvReadPreparse( Io_MvMan_t * p ); -static void Io_MvReadInterfaces( Io_MvMan_t * p ); -static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p ); -static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine ); -static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine ); -static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine ); -static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine ); -static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ); -static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine ); -static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset ); -static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine ); -static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens ); -static Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar ); - -static int Io_MvCharIsSpace( char s ) { return s == ' ' || s == '\t' || s == '\r' || s == '\n'; } -static int Io_MvCharIsMvSymb( char s ) { return s == '(' || s == ')' || s == '{' || s == '}' || s == '-' || s == ',' || s == '!'; } - -extern void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the network from the BLIF or BLIF-MV file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadBlifMv( char * pFileName, int fBlifMv, int fCheck ) -{ - FILE * pFile; - Io_MvMan_t * p; - Abc_Ntk_t * pNtk; - Abc_Lib_t * pDesign; - char * pDesignName; - int RetValue, i; - - // check that the file is available - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Io_ReadBlifMv(): The file is unavailable (absent or open).\n" ); - return 0; - } - fclose( pFile ); - - // start the file reader - p = Io_MvAlloc(); - p->fBlifMv = fBlifMv; - p->fUseReset = 0; - p->pFileName = pFileName; - p->pBuffer = Io_MvLoadFile( pFileName ); - if ( p->pBuffer == NULL ) - { - Io_MvFree( p ); - return NULL; - } - // set the design name - pDesignName = Extra_FileNameGeneric( pFileName ); - p->pDesign = Abc_LibCreate( pDesignName ); - free( pDesignName ); - // free the HOP manager - Hop_ManStop( p->pDesign->pManFunc ); - p->pDesign->pManFunc = NULL; - // prepare the file for parsing - Io_MvReadPreparse( p ); - // parse interfaces of each network - Io_MvReadInterfaces( p ); - // construct the network - pDesign = Io_MvParse( p ); - if ( p->sError[0] ) - fprintf( stdout, "%s\n", p->sError ); - if ( pDesign == NULL ) - return NULL; - Io_MvFree( p ); -// pDesign should be linked to all models of the design - - // make sure that everything is okay with the network structure - if ( fCheck ) - { - Vec_PtrForEachEntry( pDesign->vModules, pNtk, i ) - { - if ( !Abc_NtkCheckRead( pNtk ) ) - { - printf( "Io_ReadBlifMv: The network check has failed for network %s.\n", pNtk->pName ); - Abc_LibFree( pDesign, NULL ); - return NULL; - } - } - } - -//Abc_LibPrint( pDesign ); - - // detect top-level model - RetValue = Abc_LibFindTopLevelModels( pDesign ); - pNtk = Vec_PtrEntry( pDesign->vTops, 0 ); - if ( RetValue > 1 ) - printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n", - Vec_PtrSize(pDesign->vTops), pNtk->pName ); - - // extract the master network - pNtk->pDesign = pDesign; - pDesign->pManFunc = NULL; - - // verify the design for cyclic dependence - assert( Vec_PtrSize(pDesign->vModules) > 0 ); - if ( Vec_PtrSize(pDesign->vModules) == 1 ) - { -// printf( "Warning: The design is not hierarchical.\n" ); - Abc_LibFree( pDesign, pNtk ); - pNtk->pDesign = NULL; - pNtk->pSpec = Extra_UtilStrsav( pFileName ); - } - else - Abc_NtkIsAcyclicHierarchy( pNtk ); - -//Io_WriteBlifMv( pNtk, "_temp_.mv" ); - if ( pNtk->pSpec == NULL ) - pNtk->pSpec = Extra_UtilStrsav( pFileName ); - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Allocates the BLIF parsing structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Io_MvMan_t * Io_MvAlloc() -{ - Io_MvMan_t * p; - p = ALLOC( Io_MvMan_t, 1 ); - memset( p, 0, sizeof(Io_MvMan_t) ); - p->vLines = Vec_PtrAlloc( 512 ); - p->vModels = Vec_PtrAlloc( 512 ); - p->vTokens = Vec_PtrAlloc( 512 ); - p->vTokens2 = Vec_PtrAlloc( 512 ); - p->vFunc = Vec_StrAlloc( 512 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the BLIF parsing structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_MvFree( Io_MvMan_t * p ) -{ - Io_MvMod_t * pMod; - int i; - if ( p->pDesign ) - Abc_LibFree( p->pDesign, NULL ); - if ( p->pBuffer ) - free( p->pBuffer ); - if ( p->vLines ) - Vec_PtrFree( p->vLines ); - if ( p->vModels ) - { - Vec_PtrForEachEntry( p->vModels, pMod, i ) - Io_MvModFree( pMod ); - Vec_PtrFree( p->vModels ); - } - Vec_PtrFree( p->vTokens ); - Vec_PtrFree( p->vTokens2 ); - Vec_StrFree( p->vFunc ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Allocates the BLIF parsing structure for one model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Io_MvMod_t * Io_MvModAlloc() -{ - Io_MvMod_t * p; - p = ALLOC( Io_MvMod_t, 1 ); - memset( p, 0, sizeof(Io_MvMod_t) ); - p->vInputs = Vec_PtrAlloc( 512 ); - p->vOutputs = Vec_PtrAlloc( 512 ); - p->vLatches = Vec_PtrAlloc( 512 ); - p->vResets = Vec_PtrAlloc( 512 ); - p->vNames = Vec_PtrAlloc( 512 ); - p->vSubckts = Vec_PtrAlloc( 512 ); - p->vMvs = Vec_PtrAlloc( 512 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates the BLIF parsing structure for one model.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_MvModFree( Io_MvMod_t * p ) -{ -// if ( p->pNtk ) -// Abc_NtkDelete( p->pNtk ); - Vec_PtrFree( p->vInputs ); - Vec_PtrFree( p->vOutputs ); - Vec_PtrFree( p->vLatches ); - Vec_PtrFree( p->vResets ); - Vec_PtrFree( p->vNames ); - Vec_PtrFree( p->vSubckts ); - Vec_PtrFree( p->vMvs ); - free( p ); -} - - - -/**Function************************************************************* - - Synopsis [Counts the number of given chars.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvCountChars( char * pLine, char Char ) -{ - char * pCur; - int Counter = 0; - for ( pCur = pLine; *pCur; pCur++ ) - if ( *pCur == Char ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns the place where the arrow is hiding.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static char * Io_MvFindArrow( char * pLine ) -{ - char * pCur; - for ( pCur = pLine; *(pCur+1); pCur++ ) - if ( *pCur == '-' && *(pCur+1) == '>' ) - { - *pCur = ' '; - *(pCur+1) = ' '; - return pCur; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Collects the already split tokens.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_MvCollectTokens( Vec_Ptr_t * vTokens, char * pInput, char * pOutput ) -{ - char * pCur; - Vec_PtrClear( vTokens ); - for ( pCur = pInput; pCur < pOutput; pCur++ ) - { - if ( *pCur == 0 ) - continue; - Vec_PtrPush( vTokens, pCur ); - while ( *++pCur ); - } -} - -/**Function************************************************************* - - Synopsis [Splits the line into tokens.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_MvSplitIntoTokens( Vec_Ptr_t * vTokens, char * pLine, char Stop ) -{ - char * pCur; - // clear spaces - for ( pCur = pLine; *pCur != Stop; pCur++ ) - if ( Io_MvCharIsSpace(*pCur) ) - *pCur = 0; - // collect tokens - Io_MvCollectTokens( vTokens, pLine, pCur ); -} - -/**Function************************************************************* - - Synopsis [Splits the line into tokens when .default may be present.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_MvSplitIntoTokensMv( Vec_Ptr_t * vTokens, char * pLine ) -{ - char * pCur; - // clear spaces - for ( pCur = pLine; *pCur != '.' || *(pCur+1) == 'd'; pCur++ ) - if ( Io_MvCharIsSpace(*pCur) ) - *pCur = 0; - // collect tokens - Io_MvCollectTokens( vTokens, pLine, pCur ); -} - -/**Function************************************************************* - - Synopsis [Splits the line into tokens.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_MvSplitIntoTokensAndClear( Vec_Ptr_t * vTokens, char * pLine, char Stop, char Char ) -{ - char * pCur; - // clear spaces - for ( pCur = pLine; *pCur != Stop; pCur++ ) - if ( Io_MvCharIsSpace(*pCur) || *pCur == Char ) - *pCur = 0; - // collect tokens - Io_MvCollectTokens( vTokens, pLine, pCur ); -} - -/**Function************************************************************* - - Synopsis [Returns the 1-based number of the line in which the token occurs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvGetLine( Io_MvMan_t * p, char * pToken ) -{ - char * pLine; - int i; - Vec_PtrForEachEntry( p->vLines, pLine, i ) - if ( pToken < pLine ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [Reads the file into a character buffer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static char * Io_MvLoadFile( char * pFileName ) -{ - FILE * pFile; - int nFileSize; - char * pContents; - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Io_MvLoadFile(): The file is unavailable (absent or open).\n" ); - return NULL; - } - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - if ( nFileSize == 0 ) - { - printf( "Io_MvLoadFile(): The file is empty.\n" ); - return NULL; - } - pContents = ALLOC( char, nFileSize + 10 ); - rewind( pFile ); - fread( pContents, nFileSize, 1, pFile ); - fclose( pFile ); - // finish off the file with the spare .end line - // some benchmarks suddenly break off without this line - strcpy( pContents + nFileSize, "\n.end\n" ); - return pContents; -} - -/**Function************************************************************* - - Synopsis [Prepares the parsing.] - - Description [Performs several preliminary operations: - - Cuts the file buffer into separate lines. - - Removes comments and line extenders. - - Sorts lines by directives. - - Estimates the number of objects. - - Allocates room for the objects. - - Allocates room for the hash table.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_MvReadPreparse( Io_MvMan_t * p ) -{ - char * pCur, * pPrev; - int i, fComment = 0; - // parse the buffer into lines and remove comments - Vec_PtrPush( p->vLines, p->pBuffer ); - for ( pCur = p->pBuffer; *pCur; pCur++ ) - { - if ( *pCur == '\n' ) - { - *pCur = 0; -// if ( *(pCur-1) == '\r' ) -// *(pCur-1) = 0; - fComment = 0; - Vec_PtrPush( p->vLines, pCur + 1 ); - } - else if ( *pCur == '#' ) - fComment = 1; - // remove comments - if ( fComment ) - *pCur = 0; - } - - // unfold the line extensions and sort lines by directive - Vec_PtrForEachEntry( p->vLines, pCur, i ) - { - if ( *pCur == 0 ) - continue; - // find previous non-space character - for ( pPrev = pCur - 2; pPrev >= p->pBuffer; pPrev-- ) - if ( !Io_MvCharIsSpace(*pPrev) ) - break; - // if it is the line extender, overwrite it with spaces - if ( *pPrev == '\\' ) - { - for ( ; *pPrev; pPrev++ ) - *pPrev = ' '; - *pPrev = ' '; - continue; - } - // skip spaces at the beginning of the line - while ( Io_MvCharIsSpace(*pCur++) ); - // parse directives - if ( *(pCur-1) != '.' ) - continue; - if ( !strncmp(pCur, "names", 5) || !strncmp(pCur, "table", 5) || !strncmp(pCur, "gate", 4) ) - Vec_PtrPush( p->pLatest->vNames, pCur ); - else if ( p->fBlifMv && (!strncmp(pCur, "def ", 4) || !strncmp(pCur, "default ", 8)) ) - continue; - else if ( !strncmp(pCur, "latch", 5) ) - Vec_PtrPush( p->pLatest->vLatches, pCur ); - else if ( !strncmp(pCur, "r ", 2) || !strncmp(pCur, "reset ", 6) ) - Vec_PtrPush( p->pLatest->vResets, pCur ); - else if ( !strncmp(pCur, "inputs", 6) ) - Vec_PtrPush( p->pLatest->vInputs, pCur ); - else if ( !strncmp(pCur, "outputs", 7) ) - Vec_PtrPush( p->pLatest->vOutputs, pCur ); - else if ( !strncmp(pCur, "subckt", 6) ) - Vec_PtrPush( p->pLatest->vSubckts, pCur ); - else if ( p->fBlifMv && !strncmp(pCur, "mv", 2) ) - Vec_PtrPush( p->pLatest->vMvs, pCur ); - else if ( !strncmp(pCur, "blackbox", 8) ) - p->pLatest->fBlackBox = 1; - else if ( !strncmp(pCur, "model", 5) ) - { - p->pLatest = Io_MvModAlloc(); - p->pLatest->pName = pCur; - p->pLatest->pMan = p; - } - else if ( !strncmp(pCur, "end", 3) ) - { - if ( p->pLatest ) - Vec_PtrPush( p->vModels, p->pLatest ); - p->pLatest = NULL; - } - else if ( !strncmp(pCur, "exdc", 4) ) - { - fprintf( stdout, "Line %d: Skipping EXDC network.\n", Io_MvGetLine(p, pCur) ); - break; - } - else - { - pCur--; - if ( pCur[strlen(pCur)-1] == '\r' ) - pCur[strlen(pCur)-1] = 0; - fprintf( stdout, "Line %d: Skipping line \"%s\".\n", Io_MvGetLine(p, pCur), pCur ); - } - } -} - -/**Function************************************************************* - - Synopsis [Parses interfaces of the models.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Io_MvReadInterfaces( Io_MvMan_t * p ) -{ - Io_MvMod_t * pMod; - char * pLine; - int i, k; - // iterate through the models - Vec_PtrForEachEntry( p->vModels, pMod, i ) - { - // parse the model - if ( !Io_MvParseLineModel( pMod, pMod->pName ) ) - return; - // add model to the design - if ( !Abc_LibAddModel( p->pDesign, pMod->pNtk ) ) - { - sprintf( p->sError, "Line %d: Model %s is defined twice.", Io_MvGetLine(p, pMod->pName), pMod->pName ); - return; - } - // parse the inputs - Vec_PtrForEachEntry( pMod->vInputs, pLine, k ) - if ( !Io_MvParseLineInputs( pMod, pLine ) ) - return; - // parse the outputs - Vec_PtrForEachEntry( pMod->vOutputs, pLine, k ) - if ( !Io_MvParseLineOutputs( pMod, pLine ) ) - return; - } -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Abc_Lib_t * Io_MvParse( Io_MvMan_t * p ) -{ - Abc_Lib_t * pDesign; - Io_MvMod_t * pMod; - char * pLine; - int i, k; - // iterate through the models - Vec_PtrForEachEntry( p->vModels, pMod, i ) - { - // check if there any MV lines - if ( Vec_PtrSize(pMod->vMvs) > 0 ) - Abc_NtkStartMvVars( pMod->pNtk ); - // parse the mv lines - Vec_PtrForEachEntry( pMod->vMvs, pLine, k ) - if ( !Io_MvParseLineMv( pMod, pLine ) ) - return NULL; - // if reset lines are used there should be the same number of them as latches - if ( Vec_PtrSize(pMod->vResets) > 0 ) - { - if ( Vec_PtrSize(pMod->vLatches) != Vec_PtrSize(pMod->vResets) ) - { - sprintf( p->sError, "Line %d: Model %s has different number of latches (%d) and reset nodes (%d).", - Io_MvGetLine(p, pMod->pName), Abc_NtkName(pMod->pNtk), Vec_PtrSize(pMod->vLatches), Vec_PtrSize(pMod->vResets) ); - return NULL; - } - // create binary latch with 1-data and 0-init - if ( p->fUseReset ) - pMod->pResetLatch = Io_ReadCreateResetLatch( pMod->pNtk, p->fBlifMv ); - } - // parse the latches - Vec_PtrForEachEntry( pMod->vLatches, pLine, k ) - if ( !Io_MvParseLineLatch( pMod, pLine ) ) - return NULL; - // parse the reset lines - if ( p->fUseReset ) - Vec_PtrForEachEntry( pMod->vResets, pLine, k ) - if ( !Io_MvParseLineNamesMv( pMod, pLine, 1 ) ) - return NULL; - // parse the nodes - if ( p->fBlifMv ) - { - Vec_PtrForEachEntry( pMod->vNames, pLine, k ) - if ( !Io_MvParseLineNamesMv( pMod, pLine, 0 ) ) - return NULL; - } - else - { - Vec_PtrForEachEntry( pMod->vNames, pLine, k ) - if ( !Io_MvParseLineNamesBlif( pMod, pLine ) ) - return NULL; - } - // parse the subcircuits - Vec_PtrForEachEntry( pMod->vSubckts, pLine, k ) - if ( !Io_MvParseLineSubckt( pMod, pLine ) ) - return NULL; - // finalize the network - Abc_NtkFinalizeRead( pMod->pNtk ); - } - if ( p->nNDnodes ) -// printf( "Warning: The parser added %d PIs to replace non-deterministic nodes.\n", p->nNDnodes ); - printf( "Warning: The parser added %d constant 0 nodes to replace non-deterministic nodes.\n", p->nNDnodes ); - // return the network - pDesign = p->pDesign; - p->pDesign = NULL; - return pDesign; -} - -/**Function************************************************************* - - Synopsis [Parses the model line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvParseLineModel( Io_MvMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - char * pToken; - Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry( vTokens, 0 ); - assert( !strcmp(pToken, "model") ); - if ( Vec_PtrSize(vTokens) != 2 ) - { - sprintf( p->pMan->sError, "Line %d: Model line has %d entries while it should have 2.", Io_MvGetLine(p->pMan, pToken), Vec_PtrSize(vTokens) ); - return 0; - } - if ( p->fBlackBox ) - p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, 1 ); - else if ( p->pMan->fBlifMv ) - p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLIFMV, 1 ); - else - p->pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); - p->pNtk->pName = Extra_UtilStrsav( Vec_PtrEntry(vTokens, 1) ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the inputs line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvParseLineInputs( Io_MvMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - char * pToken; - int i; - Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry(vTokens, 0); - assert( !strcmp(pToken, "inputs") ); - Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) - Io_ReadCreatePi( p->pNtk, pToken ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the outputs line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvParseLineOutputs( Io_MvMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - char * pToken; - int i; - Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry(vTokens, 0); - assert( !strcmp(pToken, "outputs") ); - Vec_PtrForEachEntryStart( vTokens, pToken, i, 1 ) - Io_ReadCreatePo( p->pNtk, pToken ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the latches line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvParseLineLatch( Io_MvMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - Abc_Obj_t * pObj, * pNet; - char * pToken; - int Init; - Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); - pToken = Vec_PtrEntry(vTokens,0); - assert( !strcmp(pToken, "latch") ); - if ( Vec_PtrSize(vTokens) < 3 ) - { - sprintf( p->pMan->sError, "Line %d: Latch does not have input name and output name.", Io_MvGetLine(p->pMan, pToken) ); - return 0; - } - // create latch - if ( p->pResetLatch == NULL ) - { - pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Vec_PtrEntry(vTokens,2) ); - // get initial value - if ( p->pMan->fBlifMv ) - Abc_LatchSetInit0( pObj ); - else - { - if ( Vec_PtrSize(vTokens) > 3 ) - Init = atoi( Vec_PtrEntry(vTokens,3) ); - else - Init = 2; - if ( Init < 0 || Init > 2 ) - { - sprintf( p->pMan->sError, "Line %d: Initial state of the latch is incorrect \"%s\".", Io_MvGetLine(p->pMan, pToken), Vec_PtrEntry(vTokens,3) ); - return 0; - } - if ( Init == 0 ) - Abc_LatchSetInit0( pObj ); - else if ( Init == 1 ) - Abc_LatchSetInit1( pObj ); - else // if ( Init == 2 ) - Abc_LatchSetInitDc( pObj ); - } - } - else - { - // get the net corresponding to the output of the latch - pNet = Abc_NtkFindOrCreateNet( p->pNtk, Vec_PtrEntry(vTokens,2) ); - // get the net corresponding to the latch output (feeding into reset MUX) - pNet = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pNet, "_out") ); - // create latch - pObj = Io_ReadCreateLatch( p->pNtk, Vec_PtrEntry(vTokens,1), Abc_ObjName(pNet) ); - Abc_LatchSetInit0( pObj ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the subckt line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvParseLineSubckt( Io_MvMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - Abc_Ntk_t * pModel; - Abc_Obj_t * pBox, * pNet, * pTerm; - char * pToken, * pName, ** ppNames; - int nEquals, i, k; - - // split the line into tokens - nEquals = Io_MvCountChars( pLine, '=' ); - Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', '=' ); - pToken = Vec_PtrEntry(vTokens,0); - assert( !strcmp(pToken, "subckt") ); - - // get the model for this box - pName = Vec_PtrEntry(vTokens,1); - pModel = Abc_LibFindModelByName( p->pMan->pDesign, pName ); - if ( pModel == NULL ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find the model for subcircuit %s.", Io_MvGetLine(p->pMan, pToken), pName ); - return 0; - } - - // check if the number of tokens is correct - if ( nEquals != Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) ) - { - sprintf( p->pMan->sError, "Line %d: The number of ports (%d) in .subckt differs from the sum of PIs and POs of the model (%d).", - Io_MvGetLine(p->pMan, pToken), nEquals, Abc_NtkPiNum(pModel) + Abc_NtkPoNum(pModel) ); - return 0; - } - - // get the names - ppNames = (char **)Vec_PtrArray(vTokens) + 2 + p->pMan->fBlifMv; - - // create the box with these terminals - if ( Abc_NtkHasBlackbox(pModel) ) - pBox = Abc_NtkCreateBlackbox( p->pNtk ); - else - pBox = Abc_NtkCreateWhitebox( p->pNtk ); - pBox->pData = pModel; - if ( p->pMan->fBlifMv ) - Abc_ObjAssignName( pBox, Vec_PtrEntry(vTokens,2), NULL ); - Abc_NtkForEachPi( pModel, pTerm, i ) - { - // find this terminal among the formal inputs of the subcircuit - pName = Abc_ObjName(Abc_ObjFanout0(pTerm)); - for ( k = 0; k < nEquals; k++ ) - if ( !strcmp( ppNames[2*k], pName ) ) - break; - if ( k == nEquals ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find PI \"%s\" of the model \"%s\" as a formal input of the subcircuit.", - Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) ); - return 0; - } - // create the BI with the actual name - pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); - pTerm = Abc_NtkCreateBi( p->pNtk ); - Abc_ObjAddFanin( pBox, pTerm ); - Abc_ObjAddFanin( pTerm, pNet ); - } - Abc_NtkForEachPo( pModel, pTerm, i ) - { - // find this terminal among the formal outputs of the subcircuit - pName = Abc_ObjName(Abc_ObjFanin0(pTerm)); - for ( k = 0; k < nEquals; k++ ) - if ( !strcmp( ppNames[2*k], pName ) ) - break; - if ( k == nEquals ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find PO \"%s\" of the modell \"%s\" as a formal output of the subcircuit.", - Io_MvGetLine(p->pMan, pToken), pName, Abc_NtkName(pModel) ); - return 0; - } - // create the BI with the actual name - pNet = Abc_NtkFindOrCreateNet( p->pNtk, ppNames[2*k+1] ); - pTerm = Abc_NtkCreateBo( p->pNtk ); - Abc_ObjAddFanin( pNet, pTerm ); - Abc_ObjAddFanin( pTerm, pBox ); - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Parses the mv line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvParseLineMv( Io_MvMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - Abc_Obj_t * pObj; - Io_MvVar_t * pVar; - Extra_MmFlex_t * pFlex; - char * pName; - int nCommas, nValues, i, k; - // count commas and get the tokens - nCommas = Io_MvCountChars( pLine, ',' ); - Io_MvSplitIntoTokensAndClear( vTokens, pLine, '\0', ',' ); - pName = Vec_PtrEntry(vTokens,0); - assert( !strcmp(pName, "mv") ); - // get the number of values - if ( Vec_PtrSize(vTokens) <= nCommas + 2 ) - { - sprintf( p->pMan->sError, "Line %d: The number of values in not specified in .mv line.", Io_MvGetLine(p->pMan, pName), pName ); - return 0; - } - nValues = atoi( Vec_PtrEntry(vTokens,nCommas+2) ); - if ( nValues < 2 || nValues > IO_BLIFMV_MAXVALUES ) - { - sprintf( p->pMan->sError, "Line %d: The number of values (%d) is incorrect (should be >= 2 and <= %d).", - Io_MvGetLine(p->pMan, pName), nValues, IO_BLIFMV_MAXVALUES ); - return 0; - } - // if there is no symbolic values, quit - if ( nValues == 2 && Vec_PtrSize(vTokens) == nCommas + 3 ) - return 1; - if ( Vec_PtrSize(vTokens) > nCommas + 3 && Vec_PtrSize(vTokens) - (nCommas + 3) != nValues ) - { - sprintf( p->pMan->sError, "Line %d: Wrong number (%d) of symbolic value names (should be %d).", - Io_MvGetLine(p->pMan, pName), Vec_PtrSize(vTokens) - (nCommas + 3), nValues ); - return 0; - } - // go through variables - pFlex = Abc_NtkMvVarMan( p->pNtk ); - for ( i = 0; i <= nCommas; i++ ) - { - pName = Vec_PtrEntry( vTokens, i+1 ); - pObj = Abc_NtkFindOrCreateNet( p->pNtk, pName ); - // allocate variable - pVar = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) ); - pVar->nValues = nValues; - pVar->pNames = NULL; - // create names - if ( Vec_PtrSize(vTokens) > nCommas + 3 ) - { - pVar->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * nValues ); - Vec_PtrForEachEntryStart( vTokens, pName, k, nCommas + 3 ) - { - pVar->pNames[k-(nCommas + 3)] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pName) + 1 ); - strcpy( pVar->pNames[k-(nCommas + 3)], pName ); - } - } - // save the variable - Abc_ObjSetMvVar( pObj, pVar ); - } - // make sure the names are unique - if ( pVar->pNames ) - { - for ( i = 0; i < nValues; i++ ) - for ( k = i+1; k < nValues; k++ ) - if ( !strcmp(pVar->pNames[i], pVar->pNames[k]) ) - { - pName = Vec_PtrEntry(vTokens,0); - sprintf( p->pMan->sError, "Line %d: Symbolic value name \"%s\" is repeated in .mv line.", - Io_MvGetLine(p->pMan, pName), pVar->pNames[i] ); - return 0; - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Writes the values into the BLIF-MV representation for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvWriteValues( Abc_Obj_t * pNode, Vec_Str_t * vFunc ) -{ - char Buffer[10]; - Abc_Obj_t * pFanin; - int i; - // add the fanin number of values - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - sprintf( Buffer, "%d", Abc_ObjMvVarNum(pFanin) ); - Vec_StrAppend( vFunc, Buffer ); - Vec_StrPush( vFunc, ' ' ); - } - // add the node number of values - sprintf( Buffer, "%d", Abc_ObjMvVarNum(Abc_ObjFanout0(pNode)) ); - Vec_StrAppend( vFunc, Buffer ); - Vec_StrPush( vFunc, '\n' ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Translated one literal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvParseLiteralMv( Io_MvMod_t * p, Abc_Obj_t * pNode, char * pToken, Vec_Str_t * vFunc, int iLit ) -{ - char Buffer[10]; - Io_MvVar_t * pVar; - Abc_Obj_t * pFanin, * pNet; - char * pCur, * pNext; - int i; - // consider the equality literal - if ( pToken[0] == '=' ) - { - // find the fanins - Abc_ObjForEachFanin( pNode, pFanin, i ) - if ( !strcmp( Abc_ObjName(pFanin), pToken + 1 ) ) - break; - if ( i == Abc_ObjFaninNum(pNode) ) - { - sprintf( p->pMan->sError, "Line %d: Node name in the table \"%s\" cannot be found on .names line.", - Io_MvGetLine(p->pMan, pToken), pToken + 1 ); - return 0; - } - Vec_StrPush( vFunc, '=' ); - sprintf( Buffer, "%d", i ); - Vec_StrAppend( vFunc, Buffer ); - Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); - return 1; - } - // consider regular literal - assert( iLit < Abc_ObjFaninNum(pNode) ); - pNet = iLit >= 0 ? Abc_ObjFanin(pNode, iLit) : Abc_ObjFanout0(pNode); - pVar = Abc_ObjMvVar( pNet ); - // if the var is absent or has no symbolic values quit - if ( pVar == NULL || pVar->pNames == NULL ) - { - Vec_StrAppend( vFunc, pToken ); - Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); - return 1; - } - // parse the literal using symbolic values - for ( pCur = pToken; *pCur; pCur++ ) - { - if ( Io_MvCharIsMvSymb(*pCur) ) - { - Vec_StrPush( vFunc, *pCur ); - continue; - } - // find the next MvSymb char - for ( pNext = pCur+1; *pNext; pNext++ ) - if ( Io_MvCharIsMvSymb(*pNext) ) - break; - // look for the value name - for ( i = 0; i < pVar->nValues; i++ ) - if ( !strncmp( pVar->pNames[i], pCur, pNext-pCur ) ) - break; - if ( i == pVar->nValues ) - { - *pNext = 0; - sprintf( p->pMan->sError, "Line %d: Cannot find value name \"%s\" among the value names of variable \"%s\".", - Io_MvGetLine(p->pMan, pToken), pCur, Abc_ObjName(pNet) ); - return 0; - } - // value name is found - sprintf( Buffer, "%d", i ); - Vec_StrAppend( vFunc, Buffer ); - // update the pointer - pCur = pNext - 1; - } - Vec_StrPush( vFunc, (char)((iLit == -1)? '\n' : ' ') ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Constructs the MV-SOP cover from the file parsing info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static char * Io_MvParseTableMv( Io_MvMod_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut ) -{ - Vec_Str_t * vFunc = p->pMan->vFunc; - char * pFirst, * pToken; - int iStart, i; - // prepare the place for the cover - Vec_StrClear( vFunc ); - // write the number of values -// Io_MvWriteValues( pNode, vFunc ); - // get the first token - pFirst = Vec_PtrEntry( vTokens2, 0 ); - if ( pFirst[0] == '.' ) - { - // write the default literal - Vec_StrPush( vFunc, 'd' ); - pToken = Vec_PtrEntry(vTokens2, 1 + iOut); - if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) ) - return NULL; - iStart = 1 + nOutputs; - } - else - iStart = 0; - // write the remaining literals - while ( iStart < Vec_PtrSize(vTokens2) ) - { - // input literals - for ( i = 0; i < nInputs; i++ ) - { - pToken = Vec_PtrEntry( vTokens2, iStart + i ); - if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, i ) ) - return NULL; - } - // output literal - pToken = Vec_PtrEntry( vTokens2, iStart + nInputs + iOut ); - if ( !Io_MvParseLiteralMv( p, pNode, pToken, vFunc, -1 ) ) - return NULL; - // update the counter - iStart += nInputs + nOutputs; - } - Vec_StrPush( vFunc, '\0' ); - return Vec_StrArray( vFunc ); -} - -/**Function************************************************************* - - Synopsis [Adds reset circuitry corresponding to latch with pName.] - - Description [Returns the reset node's net.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static Abc_Obj_t * Io_MvParseAddResetCircuit( Io_MvMod_t * p, char * pName ) -{ - char Buffer[50]; - Abc_Obj_t * pNode, * pData0Net, * pData1Net, * pResetLONet, * pOutNet; - Io_MvVar_t * pVar; - // make sure the reset latch exists - assert( p->pResetLatch != NULL ); - // get the reset net - pResetLONet = Abc_ObjFanout0(Abc_ObjFanout0(p->pResetLatch)); - // get the output net - pOutNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); - // get the data nets - pData0Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_reset") ); - pData1Net = Abc_NtkFindOrCreateNet( p->pNtk, Abc_ObjNameSuffix(pOutNet, "_out") ); - // duplicate MV variables - if ( Abc_NtkMvVar(p->pNtk) ) - { - pVar = Abc_ObjMvVar( pOutNet ); - Abc_ObjSetMvVar( pData0Net, Abc_NtkMvVarDup(p->pNtk, pVar) ); - Abc_ObjSetMvVar( pData1Net, Abc_NtkMvVarDup(p->pNtk, pVar) ); - } - // create the node - pNode = Abc_NtkCreateNode( p->pNtk ); - // create the output net - Abc_ObjAddFanin( pOutNet, pNode ); - // create the function - if ( p->pMan->fBlifMv ) - { -// Vec_Att_t * p = Abc_NtkMvVar( pNtk ); - int nValues = Abc_ObjMvVarNum(pOutNet); -// sprintf( Buffer, "2 %d %d %d\n1 - - =1\n0 - - =2\n", nValues, nValues, nValues ); - sprintf( Buffer, "1 - - =1\n0 - - =2\n" ); - pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, Buffer ); - } - else - pNode->pData = Abc_SopCreateMux( p->pNtk->pManFunc ); - // add nets - Abc_ObjAddFanin( pNode, pResetLONet ); - Abc_ObjAddFanin( pNode, pData1Net ); - Abc_ObjAddFanin( pNode, pData0Net ); - return pData0Net; -} - -/**Function************************************************************* - - Synopsis [Parses the nodes line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvParseLineNamesMvOne( Io_MvMod_t * p, Vec_Ptr_t * vTokens, Vec_Ptr_t * vTokens2, int nInputs, int nOutputs, int iOut, int fReset ) -{ - Abc_Obj_t * pNet, * pNode; - char * pName; - // get the output name - pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + iOut ); - // create the node - if ( fReset ) - { - pNet = Abc_NtkFindNet( p->pNtk, pName ); - if ( pNet == NULL ) - { - sprintf( p->pMan->sError, "Line %d: Latch with output signal \"%s\" does not exist.", Io_MvGetLine(p->pMan, pName), pName ); - return 0; - } -/* - if ( !Abc_ObjIsBo(Abc_ObjFanin0(pNet)) ) - { - sprintf( p->pMan->sError, "Line %d: Reset line \"%s\" defines signal that is not a latch output.", Io_MvGetLine(p->pMan, pName), pName ); - return 0; - } -*/ - // construct the reset circuit and get the reset net feeding into it - pNet = Io_MvParseAddResetCircuit( p, pName ); - // create fanins - pNode = Io_ReadCreateNode( p->pNtk, Abc_ObjName(pNet), (char **)(vTokens->pArray + 1), nInputs ); - assert( nInputs == Vec_PtrSize(vTokens) - 2 ); - } - else - { - pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); - if ( Abc_ObjFaninNum(pNet) > 0 ) - { - sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName ); - return 0; - } - pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), nInputs ); - } - // create the cover - pNode->pData = Io_MvParseTableMv( p, pNode, vTokens2, nInputs, nOutputs, iOut ); - if ( pNode->pData == NULL ) - return 0; - pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData ); -//printf( "Finished parsing node \"%s\" with table:\n%s\n", pName, pNode->pData ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses the nodes line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvParseLineNamesMv( Io_MvMod_t * p, char * pLine, int fReset ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - Vec_Ptr_t * vTokens2 = p->pMan->vTokens2; - Abc_Obj_t * pNet; - char * pName, * pFirst, * pArrow; - int nInputs, nOutputs, nLiterals, nLines, i; - assert( p->pMan->fBlifMv ); - // get the arrow if it is present - pArrow = Io_MvFindArrow( pLine ); - if ( !p->pMan->fBlifMv && pArrow ) - { - sprintf( p->pMan->sError, "Line %d: Multi-output node symbol (->) in binary BLIF file.", Io_MvGetLine(p->pMan, pLine) ); - return 0; - } - // split names line into tokens - Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); - if ( fReset ) - assert( !strcmp(Vec_PtrEntry(vTokens,0), "r") || !strcmp(Vec_PtrEntry(vTokens,0), "reset") ); - else - assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") || !strcmp(Vec_PtrEntry(vTokens,0), "table") ); - // find the number of inputs and outputs - nInputs = Vec_PtrSize(vTokens) - 2; - nOutputs = 1; - if ( pArrow != NULL ) - { - for ( i = Vec_PtrSize(vTokens) - 2; i >= 1; i-- ) - if ( pArrow < (char*)Vec_PtrEntry(vTokens,i) ) - { - nInputs--; - nOutputs++; - } - } - // split table into tokens - pName = Vec_PtrEntryLast( vTokens ); - Io_MvSplitIntoTokensMv( vTokens2, pName + strlen(pName) ); - pFirst = Vec_PtrEntry( vTokens2, 0 ); - if ( pFirst[0] == '.' ) - { - assert( pFirst[1] == 'd' ); - nLiterals = Vec_PtrSize(vTokens2) - 1 - nOutputs; - } - else - nLiterals = Vec_PtrSize(vTokens2); - // check the number of lines - if ( nLiterals % (nInputs + nOutputs) != 0 ) - { - sprintf( p->pMan->sError, "Line %d: Wrong number of literals in the table of node \"%s\". (Spaces inside literals are not allowed.)", Io_MvGetLine(p->pMan, pFirst), pName ); - return 0; - } - // check for the ND table - nLines = nLiterals / (nInputs + nOutputs); - if ( nInputs == 0 && nLines > 1 ) - { - // add the outputs to the PIs - for ( i = 0; i < nOutputs; i++ ) - { - pName = Vec_PtrEntry( vTokens, Vec_PtrSize(vTokens) - nOutputs + i ); - // get the net corresponding to this node - pNet = Abc_NtkFindOrCreateNet(p->pNtk, pName); - if ( fReset ) - { - assert( p->pResetLatch != NULL ); - // construct the reset circuit and get the reset net feeding into it - pNet = Io_MvParseAddResetCircuit( p, pName ); - } - // add the new PI node -// Abc_ObjAddFanin( pNet, Abc_NtkCreatePi(p->pNtk) ); -// fprintf( stdout, "Io_ReadBlifMv(): Adding PI for internal non-deterministic node \"%s\".\n", pName ); - p->pMan->nNDnodes++; - Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(p->pNtk) ); - } - return 1; - } - // iterate through the outputs - for ( i = 0; i < nOutputs; i++ ) - { - if ( !Io_MvParseLineNamesMvOne( p, vTokens, vTokens2, nInputs, nOutputs, i, fReset ) ) - return 0; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Constructs the SOP cover from the file parsing info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static char * Io_MvParseTableBlif( Io_MvMod_t * p, char * pTable, int nFanins ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - Vec_Str_t * vFunc = p->pMan->vFunc; - char * pProduct, * pOutput; - int i, Polarity = -1; - - p->pMan->nTablesRead++; - // get the tokens - Io_MvSplitIntoTokens( vTokens, pTable, '.' ); - if ( Vec_PtrSize(vTokens) == 0 ) - return Abc_SopCreateConst0( p->pNtk->pManFunc ); - if ( Vec_PtrSize(vTokens) == 1 ) - { - pOutput = Vec_PtrEntry( vTokens, 0 ); - if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) - { - sprintf( p->pMan->sError, "Line %d: Constant table has wrong output value \"%s\".", Io_MvGetLine(p->pMan, pOutput), pOutput ); - return NULL; - } - return pOutput[0] == '0' ? Abc_SopCreateConst0(p->pNtk->pManFunc) : Abc_SopCreateConst1(p->pNtk->pManFunc); - } - pProduct = Vec_PtrEntry( vTokens, 0 ); - if ( Vec_PtrSize(vTokens) % 2 == 1 ) - { - sprintf( p->pMan->sError, "Line %d: Table has odd number of tokens (%d).", Io_MvGetLine(p->pMan, pProduct), Vec_PtrSize(vTokens) ); - return NULL; - } - // parse the table - Vec_StrClear( vFunc ); - for ( i = 0; i < Vec_PtrSize(vTokens)/2; i++ ) - { - pProduct = Vec_PtrEntry( vTokens, 2*i + 0 ); - pOutput = Vec_PtrEntry( vTokens, 2*i + 1 ); - if ( strlen(pProduct) != (unsigned)nFanins ) - { - sprintf( p->pMan->sError, "Line %d: Cube \"%s\" has size different from the fanin count (%d).", Io_MvGetLine(p->pMan, pProduct), pProduct, nFanins ); - return NULL; - } - if ( ((pOutput[0] - '0') & 0x8E) || pOutput[1] ) - { - sprintf( p->pMan->sError, "Line %d: Output value \"%s\" is incorrect.", Io_MvGetLine(p->pMan, pProduct), pOutput ); - return NULL; - } - if ( Polarity == -1 ) - Polarity = pOutput[0] - '0'; - else if ( Polarity != pOutput[0] - '0' ) - { - sprintf( p->pMan->sError, "Line %d: Output value \"%s\" differs from the value in the first line of the table (%d).", Io_MvGetLine(p->pMan, pProduct), pOutput, Polarity ); - return NULL; - } - // parse one product - Vec_StrAppend( vFunc, pProduct ); - Vec_StrPush( vFunc, ' ' ); - Vec_StrPush( vFunc, pOutput[0] ); - Vec_StrPush( vFunc, '\n' ); - } - Vec_StrPush( vFunc, '\0' ); - return Vec_StrArray( vFunc ); -} - -/**Function************************************************************* - - Synopsis [Parses the nodes line.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvParseLineNamesBlif( Io_MvMod_t * p, char * pLine ) -{ - Vec_Ptr_t * vTokens = p->pMan->vTokens; - Abc_Obj_t * pNet, * pNode; - char * pName; - assert( !p->pMan->fBlifMv ); - Io_MvSplitIntoTokens( vTokens, pLine, '\0' ); - // parse the mapped node - if ( !strcmp(Vec_PtrEntry(vTokens,0), "gate") ) - return Io_MvParseLineGateBlif( p, vTokens ); - // parse the regular name line - assert( !strcmp(Vec_PtrEntry(vTokens,0), "names") ); - pName = Vec_PtrEntryLast( vTokens ); - pNet = Abc_NtkFindOrCreateNet( p->pNtk, pName ); - if ( Abc_ObjFaninNum(pNet) > 0 ) - { - sprintf( p->pMan->sError, "Line %d: Signal \"%s\" is defined more than once.", Io_MvGetLine(p->pMan, pName), pName ); - return 0; - } - // create fanins - pNode = Io_ReadCreateNode( p->pNtk, pName, (char **)(vTokens->pArray + 1), Vec_PtrSize(vTokens) - 2 ); - // parse the table of this node - pNode->pData = Io_MvParseTableBlif( p, pName + strlen(pName), Abc_ObjFaninNum(pNode) ); - if ( pNode->pData == NULL ) - return 0; - pNode->pData = Abc_SopRegister( p->pNtk->pManFunc, pNode->pData ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Duplicate the MV variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Io_MvVar_t * Abc_NtkMvVarDup( Abc_Ntk_t * pNtk, Io_MvVar_t * pVar ) -{ - Extra_MmFlex_t * pFlex; - Io_MvVar_t * pVarDup; - int i; - if ( pVar == NULL ) - return NULL; - pFlex = Abc_NtkMvVarMan( pNtk ); - assert( pFlex != NULL ); - pVarDup = (Io_MvVar_t *)Extra_MmFlexEntryFetch( pFlex, sizeof(Io_MvVar_t) ); - pVarDup->nValues = pVar->nValues; - pVarDup->pNames = NULL; - if ( pVar->pNames == NULL ) - return pVarDup; - pVarDup->pNames = (char **)Extra_MmFlexEntryFetch( pFlex, sizeof(char *) * pVar->nValues ); - for ( i = 0; i < pVar->nValues; i++ ) - { - pVarDup->pNames[i] = (char *)Extra_MmFlexEntryFetch( pFlex, strlen(pVar->pNames[i]) + 1 ); - strcpy( pVarDup->pNames[i], pVar->pNames[i] ); - } - return pVarDup; -} - - -#include "mio.h" -#include "main.h" - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static char * Io_ReadBlifCleanName( char * pName ) -{ - int i, Length; - Length = strlen(pName); - for ( i = 0; i < Length; i++ ) - if ( pName[i] == '=' ) - return pName + i + 1; - return NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Io_MvParseLineGateBlif( Io_MvMod_t * p, Vec_Ptr_t * vTokens ) -{ - Mio_Library_t * pGenlib; - Mio_Gate_t * pGate; - Abc_Obj_t * pNode; - char ** ppNames, * pName; - int i, nNames; - - pName = vTokens->pArray[0]; - - // check that the library is available - pGenlib = Abc_FrameReadLibGen(); - if ( pGenlib == NULL ) - { - sprintf( p->pMan->sError, "Line %d: The current library is not available.", Io_MvGetLine(p->pMan, pName) ); - return 0; - } - - // create a new node and add it to the network - if ( vTokens->nSize < 2 ) - { - sprintf( p->pMan->sError, "Line %d: The .gate line has less than two tokens.", Io_MvGetLine(p->pMan, pName) ); - return 0; - } - - // get the gate - pGate = Mio_LibraryReadGateByName( pGenlib, vTokens->pArray[1] ); - if ( pGate == NULL ) - { - sprintf( p->pMan->sError, "Line %d: Cannot find gate \"%s\" in the library.", Io_MvGetLine(p->pMan, pName), vTokens->pArray[1] ); - return 0; - } - - // if this is the first line with gate, update the network type - if ( Abc_NtkNodeNum(p->pNtk) == 0 ) - { - assert( p->pNtk->ntkFunc == ABC_FUNC_SOP ); - p->pNtk->ntkFunc = ABC_FUNC_MAP; - Extra_MmFlexStop( p->pNtk->pManFunc ); - p->pNtk->pManFunc = pGenlib; - } - - // remove the formal parameter names - for ( i = 2; i < vTokens->nSize; i++ ) - { - vTokens->pArray[i] = Io_ReadBlifCleanName( vTokens->pArray[i] ); - if ( vTokens->pArray[i] == NULL ) - { - sprintf( p->pMan->sError, "Line %d: Invalid gate input assignment.", Io_MvGetLine(p->pMan, pName) ); - return 0; - } - } - - // create the node - ppNames = (char **)vTokens->pArray + 2; - nNames = vTokens->nSize - 3; - pNode = Io_ReadCreateNode( p->pNtk, ppNames[nNames], ppNames, nNames ); - - // set the pointer to the functionality of the node - Abc_ObjSetData( pNode, pGate ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioReadDsd.c b/src/base/io/ioReadDsd.c deleted file mode 100644 index 1ab726e5..00000000 --- a/src/base/io/ioReadDsd.c +++ /dev/null @@ -1,308 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioReadDsd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedure to read network from file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioReadDsd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Finds the end of the part.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Io_ReadDsdFindEnd( char * pCur ) -{ - char * pEnd; - int nParts = 0; - assert( *pCur == '(' ); - for ( pEnd = pCur; *pEnd; pEnd++ ) - { - if ( *pEnd == '(' ) - nParts++; - else if ( *pEnd == ')' ) - nParts--; - if ( nParts == 0 ) - return pEnd; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Splits the formula into parts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadDsdStrSplit( char * pCur, char * pParts[], int * pTypeXor ) -{ - int fAnd = 0, fXor = 0, fPri = 0, nParts = 0; - assert( *pCur ); - // process the parts - while ( 1 ) - { - // save the current part - pParts[nParts++] = pCur; - // skip the complement - if ( *pCur == '!' ) - pCur++; - // skip var - if ( *pCur >= 'a' && *pCur <= 'z' ) - pCur++; - else - { - // skip hex truth table - while ( (*pCur >= '0' && *pCur <= '9') || (*pCur >= 'A' && *pCur <= 'F') ) - pCur++; - // process parantheses - if ( *pCur != '(' ) - { - printf( "Cannot find the opening paranthesis.\n" ); - break; - } - // find the corresponding closing paranthesis - pCur = Io_ReadDsdFindEnd( pCur ); - if ( pCur == NULL ) - { - printf( "Cannot find the closing paranthesis.\n" ); - break; - } - pCur++; - } - // check the end - if ( *pCur == 0 ) - break; - // check symbol - if ( *pCur != '*' && *pCur != '+' && *pCur != ',' ) - { - printf( "Wrong separating symbol.\n" ); - break; - } - // remember the symbol - fAnd |= (*pCur == '*'); - fXor |= (*pCur == '+'); - fPri |= (*pCur == ','); - *pCur++ = 0; - } - // check separating symbols - if ( fAnd + fXor + fPri > 1 ) - { - printf( "Different types of separating symbol ennPartsed.\n" ); - return 0; - } - *pTypeXor = fXor; - return nParts; -} - -/**Function************************************************************* - - Synopsis [Recursively parses the formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Io_ReadDsd_rec( Abc_Ntk_t * pNtk, char * pCur, char * pSop ) -{ - Abc_Obj_t * pObj, * pFanin; - char * pEnd, * pParts[32]; - int i, nParts, TypeExor; - - // consider complemented formula - if ( *pCur == '!' ) - { - pObj = Io_ReadDsd_rec( pNtk, pCur + 1, NULL ); - return Abc_NtkCreateNodeInv( pNtk, pObj ); - } - if ( *pCur == '(' ) - { - assert( pCur[strlen(pCur)-1] == ')' ); - pCur[strlen(pCur)-1] = 0; - nParts = Io_ReadDsdStrSplit( pCur+1, pParts, &TypeExor ); - if ( nParts == 0 ) - { - Abc_NtkDelete( pNtk ); - return NULL; - } - pObj = Abc_NtkCreateNode( pNtk ); - if ( pSop ) - { -// for ( i = nParts - 1; i >= 0; i-- ) - for ( i = 0; i < nParts; i++ ) - { - pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL ); - if ( pFanin == NULL ) - return NULL; - Abc_ObjAddFanin( pObj, pFanin ); - } - } - else - { - for ( i = 0; i < nParts; i++ ) - { - pFanin = Io_ReadDsd_rec( pNtk, pParts[i], NULL ); - if ( pFanin == NULL ) - return NULL; - Abc_ObjAddFanin( pObj, pFanin ); - } - } - if ( pSop ) - pObj->pData = Abc_SopRegister( pNtk->pManFunc, pSop ); - else if ( TypeExor ) - pObj->pData = Abc_SopCreateXorSpecial( pNtk->pManFunc, nParts ); - else - pObj->pData = Abc_SopCreateAnd( pNtk->pManFunc, nParts, NULL ); - return pObj; - } - if ( *pCur >= 'a' && *pCur <= 'z' ) - { - assert( *(pCur+1) == 0 ); - return Abc_NtkPi( pNtk, *pCur - 'a' ); - } - - // skip hex truth table - pEnd = pCur; - while ( (*pEnd >= '0' && *pEnd <= '9') || (*pEnd >= 'A' && *pEnd <= 'F') ) - pEnd++; - if ( *pEnd != '(' ) - { - printf( "Cannot find the end of hexidecimal truth table.\n" ); - return NULL; - } - - // parse the truth table - *pEnd = 0; - pSop = Abc_SopFromTruthHex( pCur ); - *pEnd = '('; - pObj = Io_ReadDsd_rec( pNtk, pEnd, pSop ); - free( pSop ); - return pObj; -} - -/**Function************************************************************* - - Synopsis [Derives the DSD network of the formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadDsd( char * pForm ) -{ - Abc_Ntk_t * pNtk; - Abc_Obj_t * pObj, * pTop; - Vec_Ptr_t * vNames; - char * pCur, * pFormCopy; - int i, nInputs; - - // count the number of elementary variables - nInputs = 0; - for ( pCur = pForm; *pCur; pCur++ ) - if ( *pCur >= 'a' && *pCur <= 'z' ) - nInputs = ABC_MAX( nInputs, *pCur - 'a' ); - nInputs++; - - // create the network - pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); - pNtk->pName = Extra_UtilStrsav( "dsd" ); - - // create PIs - vNames = Abc_NodeGetFakeNames( nInputs ); - for ( i = 0; i < nInputs; i++ ) - Abc_ObjAssignName( Abc_NtkCreatePi(pNtk), Vec_PtrEntry(vNames, i), NULL ); - Abc_NodeFreeNames( vNames ); - - // transform the formula by inserting parantheses - // this transforms strings like PRIME(a,b,cd) into (PRIME((a),(b),(cd))) - pCur = pFormCopy = ALLOC( char, 3 * strlen(pForm) + 10 ); - *pCur++ = '('; - for ( ; *pForm; pForm++ ) - if ( *pForm == '(' ) - { - *pCur++ = '('; - *pCur++ = '('; - } - else if ( *pForm == ')' ) - { - *pCur++ = ')'; - *pCur++ = ')'; - } - else if ( *pForm == ',' ) - { - *pCur++ = ')'; - *pCur++ = ','; - *pCur++ = '('; - } - else - *pCur++ = *pForm; - *pCur++ = ')'; - *pCur = 0; - - // parse the formula - pObj = Io_ReadDsd_rec( pNtk, pFormCopy, NULL ); - free( pFormCopy ); - if ( pObj == NULL ) - return NULL; - - // create output - pTop = Abc_NtkCreatePo(pNtk); - Abc_ObjAssignName( pTop, "F", NULL ); - Abc_ObjAddFanin( pTop, pObj ); - - // create the only PO - if ( !Abc_NtkCheck( pNtk ) ) - { - fprintf( stdout, "Io_ReadDsd(): Network check has failed.\n" ); - Abc_NtkDelete( pNtk ); - return NULL; - } - return pNtk; -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - diff --git a/src/base/io/ioReadEdif.c b/src/base/io/ioReadEdif.c deleted file mode 100644 index 188e5b8c..00000000 --- a/src/base/io/ioReadEdif.c +++ /dev/null @@ -1,235 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioReadEdif.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedure to read ISCAS benchmarks in EDIF.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioReadEdif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the network from an EDIF file.] - - Description [Works only for the ISCAS benchmarks.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadEdif( char * pFileName, int fCheck ) -{ - Extra_FileReader_t * p; - Abc_Ntk_t * pNtk; - - printf( "Currently this parser does not work!\n" ); - return NULL; - - // start the file - p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t()" ); - if ( p == NULL ) - return NULL; - - // read the network - pNtk = Io_ReadEdifNetwork( p ); - Extra_FileReaderFree( p ); - if ( pNtk == NULL ) - return NULL; - - // make sure that everything is okay with the network structure - if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) - { - printf( "Io_ReadEdif: The network check has failed.\n" ); - Abc_NtkDelete( pNtk ); - return NULL; - } - return pNtk; -} -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadEdifNetwork( Extra_FileReader_t * p ) -{ - ProgressBar * pProgress; - Vec_Ptr_t * vTokens; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pNet, * pObj, * pFanout; - char * pGateName, * pNetName; - int fTokensReady, iLine, i; - - // read the first line - vTokens = Extra_FileReaderGetTokens(p); - if ( strcmp( vTokens->pArray[0], "edif" ) != 0 ) - { - printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); - return NULL; - } - - // allocate the empty network - pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); - - // go through the lines of the file - fTokensReady = 0; - pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); - for ( iLine = 1; fTokensReady || (vTokens = Extra_FileReaderGetTokens(p)); iLine++ ) - { - Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); - - // get the type of the line - fTokensReady = 0; - if ( strcmp( vTokens->pArray[0], "instance" ) == 0 ) - { - pNetName = vTokens->pArray[1]; - pNet = Abc_NtkFindOrCreateNet( pNtk, pNetName ); - vTokens = Extra_FileReaderGetTokens(p); - vTokens = Extra_FileReaderGetTokens(p); - pGateName = vTokens->pArray[1]; - if ( strncmp( pGateName, "Flip", 4 ) == 0 ) - { - pObj = Abc_NtkCreateLatch( pNtk ); - Abc_LatchSetInit0( pObj ); - } - else - { - pObj = Abc_NtkCreateNode( pNtk ); -// pObj->pData = Abc_NtkRegisterName( pNtk, pGateName ); - pObj->pData = Extra_UtilStrsav( pGateName ); // memory leak!!! - } - Abc_ObjAddFanin( pNet, pObj ); - } - else if ( strcmp( vTokens->pArray[0], "net" ) == 0 ) - { - pNetName = vTokens->pArray[1]; - if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) - continue; - if ( strcmp( pNetName + strlen(pNetName) - 4, "_out" ) == 0 ) - pNetName[strlen(pNetName) - 4] = 0; - pNet = Abc_NtkFindNet( pNtk, pNetName ); - assert( pNet ); - vTokens = Extra_FileReaderGetTokens(p); - vTokens = Extra_FileReaderGetTokens(p); - vTokens = Extra_FileReaderGetTokens(p); - while ( strcmp( vTokens->pArray[0], "portRef" ) == 0 ) - { - if ( strcmp( pNetName, vTokens->pArray[3] ) != 0 ) - { - pFanout = Abc_NtkFindNet( pNtk, vTokens->pArray[3] ); - Abc_ObjAddFanin( Abc_ObjFanin0(pFanout), pNet ); - } - vTokens = Extra_FileReaderGetTokens(p); - } - fTokensReady = 1; - } - else if ( strcmp( vTokens->pArray[0], "library" ) == 0 ) - { - vTokens = Extra_FileReaderGetTokens(p); - vTokens = Extra_FileReaderGetTokens(p); - vTokens = Extra_FileReaderGetTokens(p); - vTokens = Extra_FileReaderGetTokens(p); - vTokens = Extra_FileReaderGetTokens(p); - while ( strcmp( vTokens->pArray[0], "port" ) == 0 ) - { - pNetName = vTokens->pArray[1]; - if ( strcmp( pNetName, "CK" ) == 0 || strcmp( pNetName, "RESET" ) == 0 ) - { - vTokens = Extra_FileReaderGetTokens(p); - continue; - } - if ( strcmp( pNetName + strlen(pNetName) - 3, "_PO" ) == 0 ) - pNetName[strlen(pNetName) - 3] = 0; - if ( strcmp( vTokens->pArray[3], "INPUT" ) == 0 ) - Io_ReadCreatePi( pNtk, vTokens->pArray[1] ); - else if ( strcmp( vTokens->pArray[3], "OUTPUT" ) == 0 ) - Io_ReadCreatePo( pNtk, vTokens->pArray[1] ); - else - { - printf( "%s (line %d): Wrong interface specification.\n", Extra_FileReaderGetFileName(p), iLine ); - Abc_NtkDelete( pNtk ); - return NULL; - } - vTokens = Extra_FileReaderGetTokens(p); - } - } - else if ( strcmp( vTokens->pArray[0], "design" ) == 0 ) - { - free( pNtk->pName ); - pNtk->pName = Extra_UtilStrsav( vTokens->pArray[3] ); - break; - } - } - Extra_ProgressBarStop( pProgress ); - - // assign logic functions - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( strncmp( pObj->pData, "And", 3 ) == 0 ) - Abc_ObjSetData( pObj, Abc_SopCreateAnd(pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); - else if ( strncmp( pObj->pData, "Or", 2 ) == 0 ) - Abc_ObjSetData( pObj, Abc_SopCreateOr(pNtk->pManFunc, Abc_ObjFaninNum(pObj), NULL) ); - else if ( strncmp( pObj->pData, "Nand", 4 ) == 0 ) - Abc_ObjSetData( pObj, Abc_SopCreateNand(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); - else if ( strncmp( pObj->pData, "Nor", 3 ) == 0 ) - Abc_ObjSetData( pObj, Abc_SopCreateNor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); - else if ( strncmp( pObj->pData, "Exor", 4 ) == 0 ) - Abc_ObjSetData( pObj, Abc_SopCreateXor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); - else if ( strncmp( pObj->pData, "Exnor", 5 ) == 0 ) - Abc_ObjSetData( pObj, Abc_SopCreateNxor(pNtk->pManFunc, Abc_ObjFaninNum(pObj)) ); - else if ( strncmp( pObj->pData, "Inv", 3 ) == 0 ) - Abc_ObjSetData( pObj, Abc_SopCreateInv(pNtk->pManFunc) ); - else if ( strncmp( pObj->pData, "Buf", 3 ) == 0 ) - Abc_ObjSetData( pObj, Abc_SopCreateBuf(pNtk->pManFunc) ); - else - { - printf( "%s: Unknown gate type \"%s\".\n", Extra_FileReaderGetFileName(p), pObj->pData ); - Abc_NtkDelete( pNtk ); - return NULL; - } - } - // check if constants have been added -// if ( pNet = Abc_NtkFindNet( pNtk, "VDD" ) ) -// Io_ReadCreateConst( pNtk, "VDD", 1 ); -// if ( pNet = Abc_NtkFindNet( pNtk, "GND" ) ) -// Io_ReadCreateConst( pNtk, "GND", 0 ); - - Abc_NtkFinalizeRead( pNtk ); - return pNtk; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - diff --git a/src/base/io/ioReadEqn.c b/src/base/io/ioReadEqn.c deleted file mode 100644 index e04f2b1a..00000000 --- a/src/base/io/ioReadEqn.c +++ /dev/null @@ -1,239 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioReadEqn.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to read equation format files.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioReadEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ); -static void Io_ReadEqnStrCompact( char * pStr ); -static int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ); -static void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the network from a BENCH file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadEqn( char * pFileName, int fCheck ) -{ - Extra_FileReader_t * p; - Abc_Ntk_t * pNtk; - - // start the file - p = Extra_FileReaderAlloc( pFileName, "#", ";", "=" ); - if ( p == NULL ) - return NULL; - - // read the network - pNtk = Io_ReadEqnNetwork( p ); - Extra_FileReaderFree( p ); - if ( pNtk == NULL ) - return NULL; - - // make sure that everything is okay with the network structure - if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) - { - printf( "Io_ReadEqn: The network check has failed.\n" ); - Abc_NtkDelete( pNtk ); - return NULL; - } - return pNtk; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadEqnNetwork( Extra_FileReader_t * p ) -{ - ProgressBar * pProgress; - Vec_Ptr_t * vTokens; - Vec_Ptr_t * vVars; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pNode; - char * pNodeName, * pFormula, * pFormulaCopy, * pVarName; - int iLine, i; - - // allocate the empty network - pNtk = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_AIG, 1 ); - // set the specs - pNtk->pName = Extra_FileNameGeneric(Extra_FileReaderGetFileName(p)); - pNtk->pSpec = Extra_UtilStrsav(Extra_FileReaderGetFileName(p)); - - // go through the lines of the file - vVars = Vec_PtrAlloc( 100 ); - pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); - for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) - { - Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); - - // check if the first token contains anything - Io_ReadEqnStrCompact( vTokens->pArray[0] ); - if ( strlen(vTokens->pArray[0]) == 0 ) - break; - - // if the number of tokens is different from two, error - if ( vTokens->nSize != 2 ) - { - printf( "%s: Wrong input file format.\n", Extra_FileReaderGetFileName(p) ); - Abc_NtkDelete( pNtk ); - return NULL; - } - - // get the type of the line - if ( strncmp( vTokens->pArray[0], "INORDER", 7 ) == 0 ) - { - Io_ReadEqnStrCutAt( vTokens->pArray[1], " \n\r\t", 0, vVars ); - Vec_PtrForEachEntry( vVars, pVarName, i ) - Io_ReadCreatePi( pNtk, pVarName ); - } - else if ( strncmp( vTokens->pArray[0], "OUTORDER", 8 ) == 0 ) - { - Io_ReadEqnStrCutAt( vTokens->pArray[1], " \n\r\t", 0, vVars ); - Vec_PtrForEachEntry( vVars, pVarName, i ) - Io_ReadCreatePo( pNtk, pVarName ); - } - else - { - extern Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ); - - // get hold of the node name and its formula - pNodeName = vTokens->pArray[0]; - pFormula = vTokens->pArray[1]; - // compact the formula - Io_ReadEqnStrCompact( pFormula ); - - // consider the case of the constant node - if ( pFormula[1] == 0 && (pFormula[0] == '0' || pFormula[0] == '1') ) - { - pFormulaCopy = NULL; - Vec_PtrClear( vVars ); - } - else - { - // make a copy of formula for names - pFormulaCopy = Extra_UtilStrsav( pFormula ); - // find the names of the fanins of this node - Io_ReadEqnStrCutAt( pFormulaCopy, "!*+()", 1, vVars ); - } - // create the node - pNode = Io_ReadCreateNode( pNtk, pNodeName, (char **)Vec_PtrArray(vVars), Vec_PtrSize(vVars) ); - // derive the function - pNode->pData = Parse_FormulaParserEqn( stdout, pFormula, vVars, pNtk->pManFunc ); - // remove the cubes - FREE( pFormulaCopy ); - } - } - Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vVars ); - Abc_NtkFinalizeRead( pNtk ); - return pNtk; -} - - - -/**Function************************************************************* - - Synopsis [Compacts the string by throwing away space-like chars.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_ReadEqnStrCompact( char * pStr ) -{ - char * pCur, * pNew; - for ( pNew = pCur = pStr; *pCur; pCur++ ) - if ( !(*pCur == ' ' || *pCur == '\n' || *pCur == '\r' || *pCur == '\t') ) - *pNew++ = *pCur; - *pNew = 0; -} - -/**Function************************************************************* - - Synopsis [Determines unique variables in the string.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_ReadEqnStrFind( Vec_Ptr_t * vTokens, char * pName ) -{ - char * pToken; - int i; - Vec_PtrForEachEntry( vTokens, pToken, i ) - if ( strcmp( pToken, pName ) == 0 ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [Cuts the string into pieces using stop chars.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_ReadEqnStrCutAt( char * pStr, char * pStop, int fUniqueOnly, Vec_Ptr_t * vTokens ) -{ - char * pToken; - Vec_PtrClear( vTokens ); - for ( pToken = strtok( pStr, pStop ); pToken; pToken = strtok( NULL, pStop ) ) - if ( !fUniqueOnly || Io_ReadEqnStrFind( vTokens, pToken ) == -1 ) - Vec_PtrPush( vTokens, pToken ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - diff --git a/src/base/io/ioReadPla.c b/src/base/io/ioReadPla.c deleted file mode 100644 index fdfdb4f6..00000000 --- a/src/base/io/ioReadPla.c +++ /dev/null @@ -1,250 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioReadPla.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedure to read network from file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioReadPla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the network from a PLA file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadPla( char * pFileName, int fCheck ) -{ - Extra_FileReader_t * p; - Abc_Ntk_t * pNtk; - - // start the file - p = Extra_FileReaderAlloc( pFileName, "#", "\n\r", " \t|" ); - if ( p == NULL ) - return NULL; - - // read the network - pNtk = Io_ReadPlaNetwork( p ); - Extra_FileReaderFree( p ); - if ( pNtk == NULL ) - return NULL; - - // make sure that everything is okay with the network structure - if ( fCheck && !Abc_NtkCheckRead( pNtk ) ) - { - printf( "Io_ReadPla: The network check has failed.\n" ); - Abc_NtkDelete( pNtk ); - return NULL; - } - return pNtk; -} -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ) -{ - ProgressBar * pProgress; - Vec_Ptr_t * vTokens; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pTermPi, * pTermPo, * pNode; - Vec_Str_t ** ppSops; - char Buffer[100]; - int nInputs = -1, nOutputs = -1, nProducts = -1; - char * pCubeIn, * pCubeOut; - int i, k, iLine, nDigits, nCubes; - - // allocate the empty network - pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); - - // go through the lines of the file - nCubes = 0; - pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); - for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) - { - Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); - - // if it is the end of file, quit the loop - if ( strcmp( vTokens->pArray[0], ".e" ) == 0 ) - break; - - if ( vTokens->nSize == 1 ) - { - printf( "%s (line %d): Wrong number of token.\n", - Extra_FileReaderGetFileName(p), iLine+1 ); - Abc_NtkDelete( pNtk ); - return NULL; - } - - if ( strcmp( vTokens->pArray[0], ".i" ) == 0 ) - nInputs = atoi(vTokens->pArray[1]); - else if ( strcmp( vTokens->pArray[0], ".o" ) == 0 ) - nOutputs = atoi(vTokens->pArray[1]); - else if ( strcmp( vTokens->pArray[0], ".p" ) == 0 ) - nProducts = atoi(vTokens->pArray[1]); - else if ( strcmp( vTokens->pArray[0], ".ilb" ) == 0 ) - { - if ( vTokens->nSize - 1 != nInputs ) - printf( "Warning: Mismatch between the number of PIs on the .i line (%d) and the number of PIs on the .ilb line (%d).\n", nInputs, vTokens->nSize - 1 ); - for ( i = 1; i < vTokens->nSize; i++ ) - Io_ReadCreatePi( pNtk, vTokens->pArray[i] ); - } - else if ( strcmp( vTokens->pArray[0], ".ob" ) == 0 ) - { - if ( vTokens->nSize - 1 != nOutputs ) - printf( "Warning: Mismatch between the number of POs on the .o line (%d) and the number of POs on the .ob line (%d).\n", nOutputs, vTokens->nSize - 1 ); - for ( i = 1; i < vTokens->nSize; i++ ) - Io_ReadCreatePo( pNtk, vTokens->pArray[i] ); - } - else - { - // check if the input/output names are given - if ( Abc_NtkPiNum(pNtk) == 0 ) - { - if ( nInputs == -1 ) - { - printf( "%s: The number of inputs is not specified.\n", Extra_FileReaderGetFileName(p) ); - Abc_NtkDelete( pNtk ); - return NULL; - } - nDigits = Extra_Base10Log( nInputs ); - for ( i = 0; i < nInputs; i++ ) - { - sprintf( Buffer, "x%0*d", nDigits, i ); - Io_ReadCreatePi( pNtk, Buffer ); - } - } - if ( Abc_NtkPoNum(pNtk) == 0 ) - { - if ( nOutputs == -1 ) - { - printf( "%s: The number of outputs is not specified.\n", Extra_FileReaderGetFileName(p) ); - Abc_NtkDelete( pNtk ); - return NULL; - } - nDigits = Extra_Base10Log( nOutputs ); - for ( i = 0; i < nOutputs; i++ ) - { - sprintf( Buffer, "z%0*d", nDigits, i ); - Io_ReadCreatePo( pNtk, Buffer ); - } - } - if ( Abc_NtkNodeNum(pNtk) == 0 ) - { // first time here - // create the PO drivers and add them - // start the SOP covers - ppSops = ALLOC( Vec_Str_t *, nOutputs ); - Abc_NtkForEachPo( pNtk, pTermPo, i ) - { - ppSops[i] = Vec_StrAlloc( 100 ); - // create the node - pNode = Abc_NtkCreateNode(pNtk); - // connect the node to the PO net - Abc_ObjAddFanin( Abc_ObjFanin0Ntk(pTermPo), pNode ); - // connect the node to the PI nets - Abc_NtkForEachPi( pNtk, pTermPi, k ) - Abc_ObjAddFanin( pNode, Abc_ObjFanout0Ntk(pTermPi) ); - } - } - // read the cubes - if ( vTokens->nSize != 2 ) - { - printf( "%s (line %d): Input and output cubes are not specified.\n", - Extra_FileReaderGetFileName(p), iLine+1 ); - Abc_NtkDelete( pNtk ); - return NULL; - } - pCubeIn = vTokens->pArray[0]; - pCubeOut = vTokens->pArray[1]; - if ( strlen(pCubeIn) != (unsigned)nInputs ) - { - printf( "%s (line %d): Input cube length (%d) differs from the number of inputs (%d).\n", - Extra_FileReaderGetFileName(p), iLine+1, strlen(pCubeIn), nInputs ); - Abc_NtkDelete( pNtk ); - return NULL; - } - if ( strlen(pCubeOut) != (unsigned)nOutputs ) - { - printf( "%s (line %d): Output cube length (%d) differs from the number of outputs (%d).\n", - Extra_FileReaderGetFileName(p), iLine+1, strlen(pCubeOut), nOutputs ); - Abc_NtkDelete( pNtk ); - return NULL; - } - for ( i = 0; i < nOutputs; i++ ) - { - if ( pCubeOut[i] == '1' ) - { - Vec_StrAppend( ppSops[i], pCubeIn ); - Vec_StrAppend( ppSops[i], " 1\n" ); - } - } - nCubes++; - } - } - Extra_ProgressBarStop( pProgress ); - if ( nProducts != -1 && nCubes != nProducts ) - printf( "Warning: Mismatch between the number of cubes (%d) and the number on .p line (%d).\n", - nCubes, nProducts ); - - // add the SOP covers - Abc_NtkForEachPo( pNtk, pTermPo, i ) - { - pNode = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pTermPo) ); - if ( ppSops[i]->nSize == 0 ) - { - Abc_ObjRemoveFanins(pNode); - pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 0\n" ); - Vec_StrFree( ppSops[i] ); - continue; - } - Vec_StrPush( ppSops[i], 0 ); - pNode->pData = Abc_SopRegister( pNtk->pManFunc, ppSops[i]->pArray ); - Vec_StrFree( ppSops[i] ); - } - free( ppSops ); - Abc_NtkFinalizeRead( pNtk ); - return pNtk; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - diff --git a/src/base/io/ioReadVerilog.c b/src/base/io/ioReadVerilog.c deleted file mode 100644 index c64e330c..00000000 --- a/src/base/io/ioReadVerilog.c +++ /dev/null @@ -1,90 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioReadVerilog.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedure to read network from file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioReadVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads hierarchical design from the Verilog file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadVerilog( char * pFileName, int fCheck ) -{ - Abc_Ntk_t * pNtk; - Abc_Lib_t * pDesign; - int RetValue; - - // parse the verilog file - pDesign = Ver_ParseFile( pFileName, NULL, fCheck, 1 ); - if ( pDesign == NULL ) - return NULL; - - // detect top-level model - RetValue = Abc_LibFindTopLevelModels( pDesign ); - pNtk = Vec_PtrEntry( pDesign->vTops, 0 ); - if ( RetValue > 1 ) - printf( "Warning: The design has %d root-level modules. The first one (%s) will be used.\n", - Vec_PtrSize(pDesign->vTops), pNtk->pName ); - - // extract the master network - pNtk->pDesign = pDesign; - pDesign->pManFunc = NULL; - - // verify the design for cyclic dependence - assert( Vec_PtrSize(pDesign->vModules) > 0 ); - if ( Vec_PtrSize(pDesign->vModules) == 1 ) - { -// printf( "Warning: The design is not hierarchical.\n" ); - Abc_LibFree( pDesign, pNtk ); - pNtk->pDesign = NULL; - pNtk->pSpec = Extra_UtilStrsav( pFileName ); - } - else - { - // check that there is no cyclic dependency - Abc_NtkIsAcyclicHierarchy( pNtk ); - } - -//Io_WriteVerilog( pNtk, "_temp.v" ); - return pNtk; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - diff --git a/src/base/io/ioUtil.c b/src/base/io/ioUtil.c deleted file mode 100644 index 94ec4316..00000000 --- a/src/base/io/ioUtil.c +++ /dev/null @@ -1,752 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write the network in BENCH format.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the file type.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Io_FileType_t Io_ReadFileType( char * pFileName ) -{ - char * pExt; - if ( pFileName == NULL ) - return IO_FILE_NONE; - pExt = Extra_FileNameExtension( pFileName ); - if ( pExt == NULL ) - return IO_FILE_NONE; - if ( !strcmp( pExt, "aig" ) ) - return IO_FILE_AIGER; - if ( !strcmp( pExt, "baf" ) ) - return IO_FILE_BAF; - if ( !strcmp( pExt, "blif" ) ) - return IO_FILE_BLIF; - if ( !strcmp( pExt, "bench" ) ) - return IO_FILE_BENCH; - if ( !strcmp( pExt, "cnf" ) ) - return IO_FILE_CNF; - if ( !strcmp( pExt, "dot" ) ) - return IO_FILE_DOT; - if ( !strcmp( pExt, "edif" ) ) - return IO_FILE_EDIF; - if ( !strcmp( pExt, "eqn" ) ) - return IO_FILE_EQN; - if ( !strcmp( pExt, "gml" ) ) - return IO_FILE_GML; - if ( !strcmp( pExt, "list" ) ) - return IO_FILE_LIST; - if ( !strcmp( pExt, "mv" ) ) - return IO_FILE_BLIFMV; - if ( !strcmp( pExt, "pla" ) ) - return IO_FILE_PLA; - if ( !strcmp( pExt, "v" ) ) - return IO_FILE_VERILOG; - return IO_FILE_UNKNOWN; -} - -/**Function************************************************************* - - Synopsis [Read the network from a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_ReadNetlist( char * pFileName, Io_FileType_t FileType, int fCheck ) -{ - FILE * pFile; - Abc_Ntk_t * pNtk; - if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN ) - { - fprintf( stdout, "The generic file reader requires a known file extension.\n" ); - return NULL; - } - // check if the file exists - pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Cannot open input file \"%s\". ", pFileName ); - if ( pFileName = Extra_FileGetSimilarName( pFileName, ".blif", ".bench", ".pla", ".baf", ".aig" ) ) - fprintf( stdout, "Did you mean \"%s\"?", pFileName ); - fprintf( stdout, "\n" ); - return NULL; - } - fclose( pFile ); - // read the AIG - if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF ) - { - if ( FileType == IO_FILE_AIGER ) - pNtk = Io_ReadAiger( pFileName, fCheck ); - else // if ( FileType == IO_FILE_BAF ) - pNtk = Io_ReadBaf( pFileName, fCheck ); - if ( pNtk == NULL ) - { - fprintf( stdout, "Reading AIG from file has failed.\n" ); - return NULL; - } - return pNtk; - } - // read the new netlist - if ( FileType == IO_FILE_BLIF ) -// pNtk = Io_ReadBlif( pFileName, fCheck ); - pNtk = Io_ReadBlifMv( pFileName, 0, fCheck ); - else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) - pNtk = Io_ReadBlifMv( pFileName, 1, fCheck ); - else if ( FileType == IO_FILE_BENCH ) - pNtk = Io_ReadBench( pFileName, fCheck ); - else if ( FileType == IO_FILE_EDIF ) - pNtk = Io_ReadEdif( pFileName, fCheck ); - else if ( FileType == IO_FILE_EQN ) - pNtk = Io_ReadEqn( pFileName, fCheck ); - else if ( FileType == IO_FILE_PLA ) - pNtk = Io_ReadPla( pFileName, fCheck ); - else if ( FileType == IO_FILE_VERILOG ) - pNtk = Io_ReadVerilog( pFileName, fCheck ); - else - { - fprintf( stderr, "Unknown file format.\n" ); - return NULL; - } - if ( pNtk == NULL ) - { - fprintf( stdout, "Reading network from file has failed.\n" ); - return NULL; - } - if ( Abc_NtkBlackboxNum(pNtk) || Abc_NtkWhiteboxNum(pNtk) ) - fprintf( stdout, "Warning: The network contains hierarchy.\n" ); - return pNtk; -} - - -/**Function************************************************************* - - Synopsis [Read the network from a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Io_Read( char * pFileName, Io_FileType_t FileType, int fCheck ) -{ - Abc_Ntk_t * pNtk, * pTemp; - // get the netlist - pNtk = Io_ReadNetlist( pFileName, FileType, fCheck ); - if ( pNtk == NULL ) - return NULL; - if ( !Abc_NtkIsNetlist(pNtk) ) - return pNtk; - // flatten logic hierarchy - assert( Abc_NtkIsNetlist(pNtk) ); - if ( Abc_NtkWhiteboxNum(pNtk) > 0 ) - { - pNtk = Abc_NtkFlattenLogicHierarchy( pTemp = pNtk ); - Abc_NtkDelete( pTemp ); - if ( pNtk == NULL ) - { - fprintf( stdout, "Flattening logic hierarchy has failed.\n" ); - return NULL; - } - } - // convert blackboxes - if ( Abc_NtkBlackboxNum(pNtk) > 0 ) - { - printf( "Hierarchy reader converted %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtk) ); - pNtk = Abc_NtkConvertBlackboxes( pTemp = pNtk ); - Abc_NtkDelete( pTemp ); - if ( pNtk == NULL ) - { - fprintf( stdout, "Converting blackboxes has failed.\n" ); - return NULL; - } - } - // consider the case of BLIF-MV - if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) - { -//Abc_NtkPrintStats( stdout, pNtk, 0 ); -// Io_WriteBlifMv( pNtk, "_temp_.mv" ); - pNtk = Abc_NtkStrashBlifMv( pTemp = pNtk ); - Abc_NtkDelete( pTemp ); - if ( pNtk == NULL ) - { - fprintf( stdout, "Converting BLIF-MV to AIG has failed.\n" ); - return NULL; - } - return pNtk; - } - // convert the netlist into the logic network - pNtk = Abc_NtkToLogic( pTemp = pNtk ); - Abc_NtkDelete( pTemp ); - if ( pNtk == NULL ) - { - fprintf( stdout, "Converting netlist to logic network after reading has failed.\n" ); - return NULL; - } - return pNtk; -} - -/**Function************************************************************* - - Synopsis [Write the network into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_Write( Abc_Ntk_t * pNtk, char * pFileName, Io_FileType_t FileType ) -{ - Abc_Ntk_t * pNtkTemp, * pNtkCopy; - // check if the current network is available - if ( pNtk == NULL ) - { - fprintf( stdout, "Empty network.\n" ); - return; - } - // check if the file extension if given - if ( FileType == IO_FILE_NONE || FileType == IO_FILE_UNKNOWN ) - { - fprintf( stdout, "The generic file writer requires a known file extension.\n" ); - return; - } - // write the AIG formats - if ( FileType == IO_FILE_AIGER || FileType == IO_FILE_BAF ) - { - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( stdout, "Writing this format is only possible for structurally hashed AIGs.\n" ); - return; - } - if ( FileType == IO_FILE_AIGER ) - Io_WriteAiger( pNtk, pFileName, 1 ); - else // if ( FileType == IO_FILE_BAF ) - Io_WriteBaf( pNtk, pFileName ); - return; - } - // write non-netlist types - if ( FileType == IO_FILE_CNF ) - { - Io_WriteCnf( pNtk, pFileName, 0 ); - return; - } - if ( FileType == IO_FILE_DOT ) - { - Io_WriteDot( pNtk, pFileName ); - return; - } - if ( FileType == IO_FILE_GML ) - { - Io_WriteGml( pNtk, pFileName ); - return; - } -/* - if ( FileType == IO_FILE_BLIFMV ) - { - Io_WriteBlifMv( pNtk, pFileName ); - return; - } -*/ - // convert logic network into netlist - if ( FileType == IO_FILE_PLA ) - { - if ( Abc_NtkLevel(pNtk) > 1 ) - { - fprintf( stdout, "PLA writing is available for collapsed networks.\n" ); - return; - } - if ( Abc_NtkIsComb(pNtk) ) - pNtkTemp = Abc_NtkToNetlist( pNtk ); - else - { - fprintf( stdout, "Latches are writen into the PLA file at PI/PO pairs.\n" ); - pNtkCopy = Abc_NtkDup( pNtk ); - Abc_NtkMakeComb( pNtkCopy ); - pNtkTemp = Abc_NtkToNetlist( pNtk ); - Abc_NtkDelete( pNtkCopy ); - } - if ( !Abc_NtkToSop( pNtk, 1 ) ) - return; - } - else if ( FileType == IO_FILE_BENCH ) - { - if ( !Abc_NtkIsStrash(pNtk) ) - { - fprintf( stdout, "Writing traditional BENCH is available for AIGs only (use \"write_bench\").\n" ); - return; - } - pNtkTemp = Abc_NtkToNetlistBench( pNtk ); - } - else - pNtkTemp = Abc_NtkToNetlist( pNtk ); - - if ( pNtkTemp == NULL ) - { - fprintf( stdout, "Converting to netlist has failed.\n" ); - return; - } - - if ( FileType == IO_FILE_BLIF ) - { - if ( !Abc_NtkHasSop(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) - Abc_NtkToSop( pNtkTemp, 0 ); - Io_WriteBlif( pNtkTemp, pFileName, 1 ); - } - else if ( FileType == IO_FILE_BLIFMV ) - { - if ( !Abc_NtkConvertToBlifMv( pNtkTemp ) ) - return; - Io_WriteBlifMv( pNtkTemp, pFileName ); - } - else if ( FileType == IO_FILE_BENCH ) - Io_WriteBench( pNtkTemp, pFileName ); - else if ( FileType == IO_FILE_PLA ) - Io_WritePla( pNtkTemp, pFileName ); - else if ( FileType == IO_FILE_EQN ) - { - if ( !Abc_NtkHasAig(pNtkTemp) ) - Abc_NtkToAig( pNtkTemp ); - Io_WriteEqn( pNtkTemp, pFileName ); - } - else if ( FileType == IO_FILE_VERILOG ) - { - if ( !Abc_NtkHasAig(pNtkTemp) && !Abc_NtkHasMapping(pNtkTemp) ) - Abc_NtkToAig( pNtkTemp ); - Io_WriteVerilog( pNtkTemp, pFileName ); - } - else - fprintf( stderr, "Unknown file format.\n" ); - Abc_NtkDelete( pNtkTemp ); -} - -/**Function************************************************************* - - Synopsis [Write the network into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteHie( Abc_Ntk_t * pNtk, char * pBaseName, char * pFileName ) -{ - Abc_Ntk_t * pNtkTemp, * pNtkResult, * pNtkBase = NULL; - // check if the current network is available - if ( pNtk == NULL ) - { - fprintf( stdout, "Empty network.\n" ); - return; - } - - // read the base network - assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); - if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIF ) - pNtkBase = Io_ReadBlifMv( pBaseName, 0, 1 ); - else if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) - pNtkBase = Io_ReadBlifMv( pBaseName, 1, 1 ); - else if ( Io_ReadFileType(pBaseName) == IO_FILE_VERILOG ) - pNtkBase = Io_ReadVerilog( pBaseName, 1 ); - else - fprintf( stderr, "Unknown input file format.\n" ); - if ( pNtkBase == NULL ) - return; - - // flatten logic hierarchy if present - if ( Abc_NtkWhiteboxNum(pNtkBase) > 0 ) - { - pNtkBase = Abc_NtkFlattenLogicHierarchy( pNtkTemp = pNtkBase ); - if ( pNtkBase == NULL ) - return; - Abc_NtkDelete( pNtkTemp ); - } - - // reintroduce the boxes into the netlist - if ( Io_ReadFileType(pBaseName) == IO_FILE_BLIFMV ) - { - if ( Abc_NtkBlackboxNum(pNtkBase) > 0 ) - { - printf( "Hierarchy writer does not support BLIF-MV with blackboxes.\n" ); - Abc_NtkDelete( pNtkBase ); - return; - } - // convert the current network to BLIF-MV - assert( !Abc_NtkIsNetlist(pNtk) ); - pNtkResult = Abc_NtkToNetlist( pNtk ); - if ( !Abc_NtkConvertToBlifMv( pNtkResult ) ) - return; - // reintroduce the network - pNtkResult = Abc_NtkInsertBlifMv( pNtkBase, pNtkTemp = pNtkResult ); - Abc_NtkDelete( pNtkTemp ); - } - else if ( Abc_NtkBlackboxNum(pNtkBase) > 0 ) - { - // derive the netlist - pNtkResult = Abc_NtkToNetlist( pNtk ); - pNtkResult = Abc_NtkInsertNewLogic( pNtkBase, pNtkTemp = pNtkResult ); - Abc_NtkDelete( pNtkTemp ); - if ( pNtkResult ) - printf( "Hierarchy writer reintroduced %d instances of blackboxes.\n", Abc_NtkBlackboxNum(pNtkBase) ); - } - else - { - printf( "Warning: The output network does not contain blackboxes.\n" ); - pNtkResult = Abc_NtkToNetlist( pNtk ); - } - Abc_NtkDelete( pNtkBase ); - if ( pNtkResult == NULL ) - return; - - // write the resulting network - if ( Io_ReadFileType(pFileName) == IO_FILE_BLIF ) - { - if ( !Abc_NtkHasSop(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) ) - Abc_NtkToSop( pNtkResult, 0 ); - Io_WriteBlif( pNtkResult, pFileName, 1 ); - } - else if ( Io_ReadFileType(pFileName) == IO_FILE_VERILOG ) - { - if ( !Abc_NtkHasAig(pNtkResult) && !Abc_NtkHasMapping(pNtkResult) ) - Abc_NtkToAig( pNtkResult ); - Io_WriteVerilog( pNtkResult, pFileName ); - } - else if ( Io_ReadFileType(pFileName) == IO_FILE_BLIFMV ) - { - Io_WriteBlifMv( pNtkResult, pFileName ); - } - else - fprintf( stderr, "Unknown output file format.\n" ); - - Abc_NtkDelete( pNtkResult ); -} - -/**Function************************************************************* - - Synopsis [Creates PI terminal and net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Io_ReadCreatePi( Abc_Ntk_t * pNtk, char * pName ) -{ - Abc_Obj_t * pNet, * pTerm; - // get the PI net - pNet = Abc_NtkFindNet( pNtk, pName ); - if ( pNet ) - printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); - pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); - // add the PI node - pTerm = Abc_NtkCreatePi( pNtk ); - Abc_ObjAddFanin( pNet, pTerm ); - return pTerm; -} - -/**Function************************************************************* - - Synopsis [Creates PO terminal and net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Io_ReadCreatePo( Abc_Ntk_t * pNtk, char * pName ) -{ - Abc_Obj_t * pNet, * pTerm; - // get the PO net - pNet = Abc_NtkFindNet( pNtk, pName ); - if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) - printf( "Warning: PO \"%s\" appears twice in the list.\n", pName ); - pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); - // add the PO node - pTerm = Abc_NtkCreatePo( pNtk ); - Abc_ObjAddFanin( pTerm, pNet ); - return pTerm; -} - -/**Function************************************************************* - - Synopsis [Creates PO terminal and net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Io_ReadCreateAssert( Abc_Ntk_t * pNtk, char * pName ) -{ - Abc_Obj_t * pNet, * pTerm; - // get the PO net - pNet = Abc_NtkFindNet( pNtk, pName ); - if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) - printf( "Warning: Assert \"%s\" appears twice in the list.\n", pName ); - pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); - // add the PO node - pTerm = Abc_NtkCreateAssert( pNtk ); - Abc_ObjAddFanin( pTerm, pNet ); - return pTerm; -} - -/**Function************************************************************* - - Synopsis [Create a latch with the given input/output.] - - Description [By default, the latch value is unknown (ABC_INIT_NONE).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Io_ReadCreateLatch( Abc_Ntk_t * pNtk, char * pNetLI, char * pNetLO ) -{ - Abc_Obj_t * pLatch, * pTerm, * pNet; - // get the LI net - pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLI ); - // add the BO terminal - pTerm = Abc_NtkCreateBi( pNtk ); - Abc_ObjAddFanin( pTerm, pNet ); - // add the latch box - pLatch = Abc_NtkCreateLatch( pNtk ); - Abc_ObjAddFanin( pLatch, pTerm ); - // add the BI terminal - pTerm = Abc_NtkCreateBo( pNtk ); - Abc_ObjAddFanin( pTerm, pLatch ); - // get the LO net - pNet = Abc_NtkFindOrCreateNet( pNtk, pNetLO ); - Abc_ObjAddFanin( pNet, pTerm ); - // set latch name - Abc_ObjAssignName( pLatch, pNetLO, "L" ); - return pLatch; -} - -/**Function************************************************************* - - Synopsis [Create the reset latch with data=1 and init=0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv ) -{ - Abc_Obj_t * pLatch, * pNode; - Abc_Obj_t * pNetLI, * pNetLO; - // create latch with 0 init value -// pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" ); - pNetLI = Abc_NtkCreateNet( pNtk ); - pNetLO = Abc_NtkCreateNet( pNtk ); - Abc_ObjAssignName( pNetLI, Abc_ObjName(pNetLI), NULL ); - Abc_ObjAssignName( pNetLO, Abc_ObjName(pNetLO), NULL ); - pLatch = Io_ReadCreateLatch( pNtk, Abc_ObjName(pNetLI), Abc_ObjName(pNetLO) ); - // set the initial value - Abc_LatchSetInit0( pLatch ); - // feed the latch with constant1- node -// pNode = Abc_NtkCreateNode( pNtk ); -// pNode->pData = Abc_SopRegister( pNtk->pManFunc, "2\n1\n" ); - pNode = Abc_NtkCreateNodeConst1( pNtk ); - Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pNode ); - return pLatch; -} - -/**Function************************************************************* - - Synopsis [Create node and the net driven by it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Io_ReadCreateNode( Abc_Ntk_t * pNtk, char * pNameOut, char * pNamesIn[], int nInputs ) -{ - Abc_Obj_t * pNet, * pNode; - int i; - // create a new node - pNode = Abc_NtkCreateNode( pNtk ); - // add the fanin nets - for ( i = 0; i < nInputs; i++ ) - { - pNet = Abc_NtkFindOrCreateNet( pNtk, pNamesIn[i] ); - Abc_ObjAddFanin( pNode, pNet ); - } - // add the fanout net - pNet = Abc_NtkFindOrCreateNet( pNtk, pNameOut ); - Abc_ObjAddFanin( pNet, pNode ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Create a constant 0 node driving the net with this name.] - - Description [Assumes that the net already exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Io_ReadCreateConst( Abc_Ntk_t * pNtk, char * pName, bool fConst1 ) -{ - Abc_Obj_t * pNet, * pTerm; - pTerm = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); - pNet = Abc_NtkFindNet(pNtk, pName); assert( pNet ); - Abc_ObjAddFanin( pNet, pTerm ); - return pTerm; -} - -/**Function************************************************************* - - Synopsis [Create an inverter or buffer for the given net.] - - Description [Assumes that the nets already exist.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Io_ReadCreateInv( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ) -{ - Abc_Obj_t * pNet, * pNode; - pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet ); - pNode = Abc_NtkCreateNodeInv(pNtk, pNet); - pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet ); - Abc_ObjAddFanin( pNet, pNode ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Create an inverter or buffer for the given net.] - - Description [Assumes that the nets already exist.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Io_ReadCreateBuf( Abc_Ntk_t * pNtk, char * pNameIn, char * pNameOut ) -{ - Abc_Obj_t * pNet, * pNode; - pNet = Abc_NtkFindNet(pNtk, pNameIn); assert( pNet ); - pNode = Abc_NtkCreateNodeBuf(pNtk, pNet); - pNet = Abc_NtkFindNet(pNtk, pNameOut); assert( pNet ); - Abc_ObjAddFanin( pNet, pNode ); - return pNet; -} - - -/**Function************************************************************* - - Synopsis [Provide an fopen replacement with path lookup] - - Description [Provide an fopen replacement where the path stored - in pathvar MVSIS variable is used to look up the path - for name. Returns NULL if file cannot be opened.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -FILE * Io_FileOpen( const char * FileName, const char * PathVar, const char * Mode, int fVerbose ) -{ - char * t = 0, * c = 0, * i; - extern char * Abc_FrameReadFlag( char * pFlag ); - - if ( PathVar == 0 ) - { - return fopen( FileName, Mode ); - } - else - { - if ( c = Abc_FrameReadFlag( (char*)PathVar ) ) - { - char ActualFileName[4096]; - FILE * fp = 0; - t = Extra_UtilStrsav( c ); - for (i = strtok( t, ":" ); i != 0; i = strtok( 0, ":") ) - { -#ifdef WIN32 - _snprintf ( ActualFileName, 4096, "%s/%s", i, FileName ); -#else - snprintf ( ActualFileName, 4096, "%s/%s", i, FileName ); -#endif - if ( ( fp = fopen ( ActualFileName, Mode ) ) ) - { - if ( fVerbose ) - fprintf ( stdout, "Using file %s\n", ActualFileName ); - free( t ); - return fp; - } - } - free( t ); - return 0; - } - else - { - return fopen( FileName, Mode ); - } - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteAiger.c b/src/base/io/ioWriteAiger.c deleted file mode 100644 index ff34b177..00000000 --- a/src/base/io/ioWriteAiger.c +++ /dev/null @@ -1,291 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWriteAiger.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write binary AIGER format developed by - Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - December 16, 2006.] - - Revision [$Id: ioWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/* - The following is taken from the AIGER format description, - which can be found at http://fmv.jku.at/aiger -*/ - - -/* - The AIGER And-Inverter Graph (AIG) Format Version 20061129 - ---------------------------------------------------------- - Armin Biere, Johannes Kepler University, 2006 - - This report describes the AIG file format as used by the AIGER library. - The purpose of this report is not only to motivate and document the - format, but also to allow independent implementations of writers and - readers by giving precise and unambiguous definitions. - - ... - -Introduction - - The name AIGER contains as one part the acronym AIG of And-Inverter - Graphs and also if pronounced in German sounds like the name of the - 'Eiger', a mountain in the Swiss alps. This choice should emphasize the - origin of this format. It was first openly discussed at the Alpine - Verification Meeting 2006 in Ascona as a way to provide a simple, compact - file format for a model checking competition affiliated to CAV 2007. - - ... - -Binary Format Definition - - The binary format is semantically a subset of the ASCII format with a - slightly different syntax. The binary format may need to reencode - literals, but translating a file in binary format into ASCII format and - then back in to binary format will result in the same file. - - The main differences of the binary format to the ASCII format are as - follows. After the header the list of input literals and all the - current state literals of a latch can be omitted. Furthermore the - definitions of the AND gates are binary encoded. However, the symbol - table and the comment section are as in the ASCII format. - - The header of an AIGER file in binary format has 'aig' as format - identifier, but otherwise is identical to the ASCII header. The standard - file extension for the binary format is therefore '.aig'. - - A header for the binary format is still in ASCII encoding: - - aig M I L O A - - Constants, variables and literals are handled in the same way as in the - ASCII format. The first simplifying restriction is on the variable - indices of inputs and latches. The variable indices of inputs come first, - followed by the pseudo-primary inputs of the latches and then the variable - indices of all LHS of AND gates: - - input variable indices 1, 2, ... , I - latch variable indices I+1, I+2, ... , (I+L) - AND variable indices I+L+1, I+L+2, ... , (I+L+A) == M - - The corresponding unsigned literals are - - input literals 2, 4, ... , 2*I - latch literals 2*I+2, 2*I+4, ... , 2*(I+L) - AND literals 2*(I+L)+2, 2*(I+L)+4, ... , 2*(I+L+A) == 2*M - - All literals have to be defined, and therefore 'M = I + L + A'. With this - restriction it becomes possible that the inputs and the current state - literals of the latches do not have to be listed explicitly. Therefore, - after the header only the list of 'L' next state literals follows, one per - latch on a single line, and then the 'O' outputs, again one per line. - - In the binary format we assume that the AND gates are ordered and respect - the child parent relation. AND gates with smaller literals on the LHS - come first. Therefore we can assume that the literals on the right-hand - side of a definition of an AND gate are smaller than the LHS literal. - Furthermore we can sort the literals on the RHS, such that the larger - literal comes first. A definition thus consists of three literals - - lhs rhs0 rhs1 - - with 'lhs' even and 'lhs > rhs0 >= rhs1'. Also the variable indices are - pairwise different to avoid combinational self loops. Since the LHS - indices of the definitions are all consecutive (as even integers), - the binary format does not have to keep 'lhs'. In addition, we can use - the order restriction and only write the differences 'delta0' and 'delta1' - instead of 'rhs0' and 'rhs1', with - - delta0 = lhs - rhs0, delta1 = rhs0 - rhs1 - - The differences will all be strictly positive, and in practice often very - small. We can take advantage of this fact by the simple little-endian - encoding of unsigned integers of the next section. After the binary delta - encoding of the RHSs of all AND gates, the optional symbol table and - optional comment section start in the same format as in the ASCII case. - - ... - -*/ - -static unsigned Io_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } -static unsigned Io_ObjAigerNum( Abc_Obj_t * pObj ) { return (unsigned)pObj->pCopy; } -static void Io_ObjSetAigerNum( Abc_Obj_t * pObj, unsigned Num ) { pObj->pCopy = (void *)Num; } - -int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes the AIG in the binary AIGER format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteAiger( Abc_Ntk_t * pNtk, char * pFileName, int fWriteSymbols ) -{ - ProgressBar * pProgress; - FILE * pFile; - Abc_Obj_t * pObj, * pDriver; - int i, nNodes, Pos, nBufferSize; - unsigned char * pBuffer; - unsigned uLit0, uLit1, uLit; - - assert( Abc_NtkIsStrash(pNtk) ); - // start the output stream - pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); - return; - } - Abc_NtkForEachLatch( pNtk, pObj, i ) - if ( !Abc_LatchIsInit0(pObj) ) - { - fprintf( stdout, "Io_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" ); - return; - } - - // set the node numbers to be used in the output file - nNodes = 0; - Io_ObjSetAigerNum( Abc_AigConst1(pNtk), nNodes++ ); - Abc_NtkForEachCi( pNtk, pObj, i ) - Io_ObjSetAigerNum( pObj, nNodes++ ); - Abc_AigForEachAnd( pNtk, pObj, i ) - Io_ObjSetAigerNum( pObj, nNodes++ ); - - // write the header "M I L O A" where M = I + L + A - fprintf( pFile, "aig %u %u %u %u %u\n", - Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) + Abc_NtkNodeNum(pNtk), - Abc_NtkPiNum(pNtk), - Abc_NtkLatchNum(pNtk), - Abc_NtkPoNum(pNtk), - Abc_NtkNodeNum(pNtk) ); - - // if the driver node is a constant, we need to complement the literal below - // because, in the AIGER format, literal 0/1 is represented as number 0/1 - // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0 - - // write latch drivers - Abc_NtkForEachLatchInput( pNtk, pObj, i ) - { - pDriver = Abc_ObjFanin0(pObj); - fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); - } - - // write PO drivers - Abc_NtkForEachPo( pNtk, pObj, i ) - { - pDriver = Abc_ObjFanin0(pObj); - fprintf( pFile, "%u\n", Io_ObjMakeLit( Io_ObjAigerNum(pDriver), Abc_ObjFaninC0(pObj) ^ (Io_ObjAigerNum(pDriver) == 0) ) ); - } - - // write the nodes into the buffer - Pos = 0; - nBufferSize = 6 * Abc_NtkNodeNum(pNtk) + 100; // skeptically assuming 3 chars per one AIG edge - pBuffer = ALLOC( char, nBufferSize ); - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); - Abc_AigForEachAnd( pNtk, pObj, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - uLit = Io_ObjMakeLit( Io_ObjAigerNum(pObj), 0 ); - uLit0 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin0(pObj)), Abc_ObjFaninC0(pObj) ); - uLit1 = Io_ObjMakeLit( Io_ObjAigerNum(Abc_ObjFanin1(pObj)), Abc_ObjFaninC1(pObj) ); - assert( uLit0 < uLit1 ); - Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); - Pos = Io_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); - if ( Pos > nBufferSize - 10 ) - { - printf( "Io_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); - fclose( pFile ); - return; - } - } - assert( Pos < nBufferSize ); - Extra_ProgressBarStop( pProgress ); - - // write the buffer - fwrite( pBuffer, 1, Pos, pFile ); - free( pBuffer ); - - // write the symbol table - if ( fWriteSymbols ) - { - // write PIs - Abc_NtkForEachPi( pNtk, pObj, i ) - fprintf( pFile, "i%d %s\n", i, Abc_ObjName(pObj) ); - // write latches - Abc_NtkForEachLatch( pNtk, pObj, i ) - fprintf( pFile, "l%d %s\n", i, Abc_ObjName(Abc_ObjFanout0(pObj)) ); - // write POs - Abc_NtkForEachPo( pNtk, pObj, i ) - fprintf( pFile, "o%d %s\n", i, Abc_ObjName(pObj) ); - } - - // write the comment - fprintf( pFile, "c\n" ); - if ( pNtk->pName && strlen(pNtk->pName) > 0 ) - fprintf( pFile, ".model %s\n", pNtk->pName ); - fprintf( pFile, "This file was produced by ABC on %s\n", Extra_TimeStamp() ); - fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Adds one unsigned AIG edge to the output buffer.] - - Description [This procedure is a slightly modified version of Armin Biere's - procedure "void encode (FILE * file, unsigned x)" ] - - SideEffects [Returns the current writing position.] - - SeeAlso [] - -***********************************************************************/ -int Io_WriteAigerEncode( char * pBuffer, int Pos, unsigned x ) -{ - unsigned char ch; - while (x & ~0x7f) - { - ch = (x & 0x7f) | 0x80; -// putc (ch, file); - pBuffer[Pos++] = ch; - x >>= 7; - } - ch = x; -// putc (ch, file); - pBuffer[Pos++] = ch; - return Pos; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteBaf.c b/src/base/io/ioWriteBaf.c deleted file mode 100644 index fc0229a4..00000000 --- a/src/base/io/ioWriteBaf.c +++ /dev/null @@ -1,168 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWriteBaf.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write AIG in the binary format.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioWriteBaf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/* - Binary Aig Format - - The motivation for this format is to have - - compact binary representation of large AIGs (~10x more compact than BLIF) - - consequently, fast reading/writing of large AIGs (~10x faster than BLIF) - - representation for all tech-ind info related to an AIG - - human-readable file header - - The header: - (1) May contain several lines of human-readable comments. - Each comment line begins with symbol '#' and ends with symbol '\n'. - (2) Always contains the following data. - - benchmark name - - number of primary inputs - - number of primary outputs - - number of latches - - number of AIG nodes (excluding the constant 1 node) - Each entry is followed by 0-byte (character '\0'): - (3) Next follow the names of the PIs, POs, and latches in this order. - Each name is followed by 0-byte (character '\0'). - Inside each set of names (PIs, POs, latches) there should be no - identical names but the PO names may coincide with PI/latch names. - - The body: - (1) First part of the body contains binary information about the internal AIG nodes. - Each internal AIG node is represented using two edges (each edge is a 4-byte integer). - Each integer is the fanin ID followed by 1-bit representation of the complemented attribute. - (For example, complemented edge to node 10 will be represented as 2*10 + 1 = 21.) - The IDs of the nodes are created as follows: Constant 1 node has ID=0. - CIs (PIs and latch outputs) have 1-based IDs assigned in that order. - Each node in the array of the internal AIG nodes has the ID assigned in that order. - The constant 1 node is not written into the file. - (2) Second part of the body contains binary information about the edges connecting - the COs (POs and latch inputs) to the internal AIG nodes. - Each edge is a 4-byte integer the same way as a node fanin. - The latch initial value (2 bits) is stored in this integer. -*/ - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes the AIG in the binary format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteBaf( Abc_Ntk_t * pNtk, char * pFileName ) -{ - ProgressBar * pProgress; - FILE * pFile; - Abc_Obj_t * pObj; - int i, nNodes, nAnds, nBufferSize; - unsigned * pBufferNode; - assert( Abc_NtkIsStrash(pNtk) ); - // start the output stream - pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WriteBaf(): Cannot open the output file \"%s\".\n", pFileName ); - return; - } - - // write the comment - fprintf( pFile, "# BAF (Binary Aig Format) for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); - - // write the network name - fprintf( pFile, "%s%c", pNtk->pName, 0 ); - // write the number of PIs - fprintf( pFile, "%d%c", Abc_NtkPiNum(pNtk), 0 ); - // write the number of POs - fprintf( pFile, "%d%c", Abc_NtkPoNum(pNtk), 0 ); - // write the number of latches - fprintf( pFile, "%d%c", Abc_NtkLatchNum(pNtk), 0 ); - // write the number of internal nodes - fprintf( pFile, "%d%c", Abc_NtkNodeNum(pNtk), 0 ); - - // write PIs - Abc_NtkForEachPi( pNtk, pObj, i ) - fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); - // write POs - Abc_NtkForEachPo( pNtk, pObj, i ) - fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); - // write latches - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - fprintf( pFile, "%s%c", Abc_ObjName(pObj), 0 ); - fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanin0(pObj)), 0 ); - fprintf( pFile, "%s%c", Abc_ObjName(Abc_ObjFanout0(pObj)), 0 ); - } - - // set the node numbers to be used in the output file - Abc_NtkCleanCopy( pNtk ); - nNodes = 1; - Abc_NtkForEachCi( pNtk, pObj, i ) - pObj->pCopy = (void *)nNodes++; - Abc_AigForEachAnd( pNtk, pObj, i ) - pObj->pCopy = (void *)nNodes++; - - // write the nodes into the buffer - nAnds = 0; - nBufferSize = Abc_NtkNodeNum(pNtk) * 2 + Abc_NtkCoNum(pNtk); - pBufferNode = ALLOC( int, nBufferSize ); - pProgress = Extra_ProgressBarStart( stdout, nBufferSize ); - Abc_AigForEachAnd( pNtk, pObj, i ) - { - Extra_ProgressBarUpdate( pProgress, nAnds, NULL ); - pBufferNode[nAnds++] = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj); - pBufferNode[nAnds++] = (((int)Abc_ObjFanin1(pObj)->pCopy) << 1) | Abc_ObjFaninC1(pObj); - } - - // write the COs into the buffer - Abc_NtkForEachCo( pNtk, pObj, i ) - { - Extra_ProgressBarUpdate( pProgress, nAnds, NULL ); - pBufferNode[nAnds] = (((int)Abc_ObjFanin0(pObj)->pCopy) << 1) | Abc_ObjFaninC0(pObj); - if ( Abc_ObjFanoutNum(pObj) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) - pBufferNode[nAnds] = (pBufferNode[nAnds] << 2) | ((unsigned)Abc_ObjData(Abc_ObjFanout0(pObj)) & 3); - nAnds++; - } - Extra_ProgressBarStop( pProgress ); - assert( nBufferSize == nAnds ); - - // write the buffer - fwrite( pBufferNode, 1, sizeof(int) * nBufferSize, pFile ); - fclose( pFile ); - free( pBufferNode ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteBench.c b/src/base/io/ioWriteBench.c deleted file mode 100644 index 4b766a47..00000000 --- a/src/base/io/ioWriteBench.c +++ /dev/null @@ -1,335 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWriteBench.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write the network in BENCH format.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioWriteBench.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk ); - -static int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ); -static int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode ); - -static int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk ); -static int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes the network in BENCH format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_WriteBench( Abc_Ntk_t * pNtk, char * pFileName ) -{ - Abc_Ntk_t * pExdc; - FILE * pFile; - assert( Abc_NtkIsSopNetlist(pNtk) ); - if ( !Io_WriteBenchCheckNames(pNtk) ) - { - fprintf( stdout, "Io_WriteBench(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" ); - return 0; - } - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" ); - return 0; - } - fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); - // write the network - Io_WriteBenchOne( pFile, pNtk ); - // write EXDC network if it exists - pExdc = Abc_NtkExdc( pNtk ); - if ( pExdc ) - printf( "Io_WriteBench: EXDC is not written (warning).\n" ); - // finalize the file - fclose( pFile ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Writes the network in BENCH format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_WriteBenchOne( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - ProgressBar * pProgress; - Abc_Obj_t * pNode; - int i; - - // write the PIs/POs/latches - Abc_NtkForEachPi( pNtk, pNode, i ) - fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - Abc_NtkForEachPo( pNtk, pNode, i ) - fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); - Abc_NtkForEachLatch( pNtk, pNode, i ) - fprintf( pFile, "%-11s = DFF(%s)\n", - Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); - - // write internal nodes - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - Io_WriteBenchOneNode( pFile, pNode ); - } - Extra_ProgressBarStop( pProgress ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Writes the network in BENCH format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_WriteBenchOneNode( FILE * pFile, Abc_Obj_t * pNode ) -{ - int nFanins; - - assert( Abc_ObjIsNode(pNode) ); - nFanins = Abc_ObjFaninNum(pNode); - if ( nFanins == 0 ) - { // write the constant 1 node - assert( Abc_NodeIsConst1(pNode) ); - fprintf( pFile, "%-11s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - fprintf( pFile, " = vdd\n" ); - } - else if ( nFanins == 1 ) - { // write the interver/buffer - if ( Abc_NodeIsBuf(pNode) ) - { - fprintf( pFile, "%-11s = BUFF(", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); - } - else - { - fprintf( pFile, "%-11s = NOT(", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); - } - } - else - { // write the AND gate - fprintf( pFile, "%-11s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - fprintf( pFile, " = AND(%s, ", Abc_ObjName(Abc_ObjFanin0(pNode)) ); - fprintf( pFile, "%s)\n", Abc_ObjName(Abc_ObjFanin1(pNode)) ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Writes the network in BENCH format with LUTs and DFFRSE.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_WriteBenchLut( Abc_Ntk_t * pNtk, char * pFileName ) -{ - Abc_Ntk_t * pExdc; - FILE * pFile; - assert( Abc_NtkIsAigNetlist(pNtk) ); - if ( !Io_WriteBenchCheckNames(pNtk) ) - { - fprintf( stdout, "Io_WriteBenchLut(): Signal names in this benchmark contain parantheses making them impossible to reproduce in the BENCH format. Use \"short_names\".\n" ); - return 0; - } - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WriteBench(): Cannot open the output file.\n" ); - return 0; - } - fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); - // write the network - Io_WriteBenchLutOne( pFile, pNtk ); - // write EXDC network if it exists - pExdc = Abc_NtkExdc( pNtk ); - if ( pExdc ) - printf( "Io_WriteBench: EXDC is not written (warning).\n" ); - // finalize the file - fclose( pFile ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Writes the network in BENCH format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_WriteBenchLutOne( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - ProgressBar * pProgress; - Abc_Obj_t * pNode; - Vec_Int_t * vMemory; - int i; - - // write the PIs/POs/latches - Abc_NtkForEachPi( pNtk, pNode, i ) - fprintf( pFile, "INPUT(%s)\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - Abc_NtkForEachPo( pNtk, pNode, i ) - fprintf( pFile, "OUTPUT(%s)\n", Abc_ObjName(Abc_ObjFanin0(pNode)) ); - Abc_NtkForEachLatch( pNtk, pNode, i ) - fprintf( pFile, "%-11s = DFFRSE( %s, gnd, gnd, gnd, gnd )\n", - Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pNode))), Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pNode))) ); -//Abc_NtkLevel(pNtk); - // write internal nodes - vMemory = Vec_IntAlloc( 10000 ); - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - Io_WriteBenchLutOneNode( pFile, pNode, vMemory ); - } - Extra_ProgressBarStop( pProgress ); - Vec_IntFree( vMemory ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Writes the network in BENCH format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_WriteBenchLutOneNode( FILE * pFile, Abc_Obj_t * pNode, Vec_Int_t * vTruth ) -{ - Abc_Obj_t * pFanin; - unsigned * pTruth; - int i, nFanins; - assert( Abc_ObjIsNode(pNode) ); - nFanins = Abc_ObjFaninNum(pNode); - assert( nFanins <= 8 ); - // compute the truth table - pTruth = Abc_ConvertAigToTruth( pNode->pNtk->pManFunc, Hop_Regular(pNode->pData), nFanins, vTruth, 0 ); - if ( Hop_IsComplement(pNode->pData) ) - Extra_TruthNot( pTruth, pTruth, nFanins ); - // consider simple cases - if ( Extra_TruthIsConst0(pTruth, nFanins) ) - { - fprintf( pFile, "%-11s = gnd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - return 1; - } - if ( Extra_TruthIsConst1(pTruth, nFanins) ) - { - fprintf( pFile, "%-11s = vdd\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - return 1; - } - if ( nFanins == 1 ) - { - fprintf( pFile, "%-11s = LUT 0x%d ( %s )\n", - Abc_ObjName(Abc_ObjFanout0(pNode)), - Abc_NodeIsBuf(pNode)? 2 : 1, - Abc_ObjName(Abc_ObjFanin0(pNode)) ); - return 1; - } - // write it in the hexadecimal form - fprintf( pFile, "%-11s = LUT 0x", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - Extra_PrintHexadecimal( pFile, pTruth, nFanins ); -/* - { -extern void Kit_DsdTest( unsigned * pTruth, int nVars ); -Abc_ObjForEachFanin( pNode, pFanin, i ) -printf( "%c%d ", 'a'+i, Abc_ObjFanin0(pFanin)->Level ); -printf( "\n" ); -Kit_DsdTest( pTruth, nFanins ); - } - if ( pNode->Id % 1000 == 0 ) - { - int x = 0; - } -*/ - // write the fanins - fprintf( pFile, " (" ); - Abc_ObjForEachFanin( pNode, pFanin, i ) - fprintf( pFile, " %s%s", Abc_ObjName(pFanin), ((i==nFanins-1)? "" : ",") ); - fprintf( pFile, " )\n" ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if the names cannot be written into the bench file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_WriteBenchCheckNames( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - char * pName; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - for ( pName = Nm_ManFindNameById(pNtk->pManName, i); pName && *pName; pName++ ) - if ( *pName == '(' || *pName == ')' ) - return 0; - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteBlif.c b/src/base/io/ioWriteBlif.c deleted file mode 100644 index c0c29d65..00000000 --- a/src/base/io/ioWriteBlif.c +++ /dev/null @@ -1,591 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWriteBlif.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write BLIF files.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioWriteBlif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" -#include "main.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); -static void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); -static void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); -static void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ); -static void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ); -static void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ); -static void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode ); -static void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ); -static void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Write the network into a BLIF file with the given name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteBlifLogic( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) -{ - Abc_Ntk_t * pNtkTemp; - // derive the netlist - pNtkTemp = Abc_NtkToNetlist(pNtk); - if ( pNtkTemp == NULL ) - { - fprintf( stdout, "Writing BLIF has failed.\n" ); - return; - } - Io_WriteBlif( pNtkTemp, FileName, fWriteLatches ); - Abc_NtkDelete( pNtkTemp ); -} - -/**Function************************************************************* - - Synopsis [Write the network into a BLIF file with the given name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteBlif( Abc_Ntk_t * pNtk, char * FileName, int fWriteLatches ) -{ - FILE * pFile; - Abc_Ntk_t * pNtkTemp; - int i; - assert( Abc_NtkIsNetlist(pNtk) ); - // start writing the file - pFile = fopen( FileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WriteBlif(): Cannot open the output file.\n" ); - return; - } - fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); - // write the master network - Io_NtkWrite( pFile, pNtk, fWriteLatches ); - // make sure there is no logic hierarchy - assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); - // write the hierarchy if present - if ( Abc_NtkBlackboxNum(pNtk) > 0 ) - { - Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i ) - { - if ( pNtkTemp == pNtk ) - continue; - fprintf( pFile, "\n\n" ); - Io_NtkWrite( pFile, pNtkTemp, fWriteLatches ); - } - } - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Write the network into a BLIF file with the given name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWrite( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) -{ - Abc_Ntk_t * pExdc; - assert( Abc_NtkIsNetlist(pNtk) ); - // write the model name - fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); - // write the network - Io_NtkWriteOne( pFile, pNtk, fWriteLatches ); - // write EXDC network if it exists - pExdc = Abc_NtkExdc( pNtk ); - if ( pExdc ) - { - fprintf( pFile, "\n" ); - fprintf( pFile, ".exdc\n" ); - Io_NtkWriteOne( pFile, pExdc, fWriteLatches ); - } - // finalize the file - fprintf( pFile, ".end\n" ); -} - -/**Function************************************************************* - - Synopsis [Write one network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteOne( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) -{ - ProgressBar * pProgress; - Abc_Obj_t * pNode, * pLatch; - int i, Length; - - // write the PIs - fprintf( pFile, ".inputs" ); - Io_NtkWritePis( pFile, pNtk, fWriteLatches ); - fprintf( pFile, "\n" ); - - // write the POs - fprintf( pFile, ".outputs" ); - Io_NtkWritePos( pFile, pNtk, fWriteLatches ); - fprintf( pFile, "\n" ); - - // write the assertions - if ( Abc_NtkAssertNum(pNtk) ) - { - fprintf( pFile, ".asserts" ); - Io_NtkWriteAsserts( pFile, pNtk ); - fprintf( pFile, "\n" ); - } - - // write the blackbox - if ( Abc_NtkHasBlackbox( pNtk ) ) - { - fprintf( pFile, ".blackbox\n" ); - return; - } - - // write the timing info - Io_WriteTimingInfo( pFile, pNtk ); - - // write the latches - if ( fWriteLatches && !Abc_NtkIsComb(pNtk) ) - { - fprintf( pFile, "\n" ); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - Io_NtkWriteLatch( pFile, pLatch ); - fprintf( pFile, "\n" ); - } - - // write the subcircuits - assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); - if ( Abc_NtkBlackboxNum(pNtk) > 0 ) - { - fprintf( pFile, "\n" ); - Abc_NtkForEachBlackbox( pNtk, pNode, i ) - Io_NtkWriteSubckt( pFile, pNode ); - fprintf( pFile, "\n" ); - } - - // write each internal node - Length = Abc_NtkHasMapping(pNtk)? Mio_LibraryReadGateNameMax(pNtk->pManFunc) : 0; - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - Io_NtkWriteNode( pFile, pNode, Length ); - } - Extra_ProgressBarStop( pProgress ); -} - - -/**Function************************************************************* - - Synopsis [Writes the primary input list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWritePis( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) -{ - Abc_Obj_t * pTerm, * pNet; - int LineLength; - int AddedLength; - int NameCounter; - int i; - - LineLength = 7; - NameCounter = 0; - - if ( fWriteLatches ) - { - Abc_NtkForEachPi( pNtk, pTerm, i ) - { - pNet = Abc_ObjFanout0(pTerm); - // get the line length after this name is written - AddedLength = strlen(Abc_ObjName(pNet)) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", Abc_ObjName(pNet) ); - LineLength += AddedLength; - NameCounter++; - } - } - else - { - Abc_NtkForEachCi( pNtk, pTerm, i ) - { - pNet = Abc_ObjFanout0(pTerm); - // get the line length after this name is written - AddedLength = strlen(Abc_ObjName(pNet)) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", Abc_ObjName(pNet) ); - LineLength += AddedLength; - NameCounter++; - } - } -} - -/**Function************************************************************* - - Synopsis [Writes the primary input list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWritePos( FILE * pFile, Abc_Ntk_t * pNtk, int fWriteLatches ) -{ - Abc_Obj_t * pTerm, * pNet; - int LineLength; - int AddedLength; - int NameCounter; - int i; - - LineLength = 8; - NameCounter = 0; - - if ( fWriteLatches ) - { - Abc_NtkForEachPo( pNtk, pTerm, i ) - { - pNet = Abc_ObjFanin0(pTerm); - // get the line length after this name is written - AddedLength = strlen(Abc_ObjName(pNet)) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", Abc_ObjName(pNet) ); - LineLength += AddedLength; - NameCounter++; - } - } - else - { - Abc_NtkForEachCo( pNtk, pTerm, i ) - { - if ( Abc_ObjIsAssert(pTerm) ) - continue; - pNet = Abc_ObjFanin0(pTerm); - // get the line length after this name is written - AddedLength = strlen(Abc_ObjName(pNet)) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", Abc_ObjName(pNet) ); - LineLength += AddedLength; - NameCounter++; - } - } -} - -/**Function************************************************************* - - Synopsis [Writes the assertion list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteAsserts( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pTerm, * pNet; - int LineLength; - int AddedLength; - int NameCounter; - int i; - - LineLength = 8; - NameCounter = 0; - - Abc_NtkForEachAssert( pNtk, pTerm, i ) - { - pNet = Abc_ObjFanin0(pTerm); - // get the line length after this name is written - AddedLength = strlen(Abc_ObjName(pNet)) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", Abc_ObjName(pNet) ); - LineLength += AddedLength; - NameCounter++; - } -} - -/**Function************************************************************* - - Synopsis [Write the latch into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteSubckt( FILE * pFile, Abc_Obj_t * pNode ) -{ - Abc_Ntk_t * pModel = pNode->pData; - Abc_Obj_t * pTerm; - int i; - // write the subcircuit -// fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) ); - fprintf( pFile, ".subckt %s", Abc_NtkName(pModel) ); - // write pairs of the formal=actual names - Abc_NtkForEachPi( pModel, pTerm, i ) - { - fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); - pTerm = Abc_ObjFanin( pNode, i ); - fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); - } - Abc_NtkForEachPo( pModel, pTerm, i ) - { - fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); - pTerm = Abc_ObjFanout( pNode, i ); - fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); - } - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Write the latch into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteLatch( FILE * pFile, Abc_Obj_t * pLatch ) -{ - Abc_Obj_t * pNetLi, * pNetLo; - int Reset; - pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); - pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); - Reset = (int)Abc_ObjData( pLatch ); - // write the latch line - fprintf( pFile, ".latch" ); - fprintf( pFile, " %10s", Abc_ObjName(pNetLi) ); - fprintf( pFile, " %10s", Abc_ObjName(pNetLo) ); - fprintf( pFile, " %d\n", Reset-1 ); -} - - -/**Function************************************************************* - - Synopsis [Write the node into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteNode( FILE * pFile, Abc_Obj_t * pNode, int Length ) -{ - if ( Abc_NtkHasMapping(pNode->pNtk) ) - { - // write the .gate line - fprintf( pFile, ".gate" ); - Io_NtkWriteNodeGate( pFile, pNode, Length ); - fprintf( pFile, "\n" ); - } - else - { - // write the .names line - fprintf( pFile, ".names" ); - Io_NtkWriteNodeFanins( pFile, pNode ); - fprintf( pFile, "\n" ); - // write the cubes - fprintf( pFile, "%s", Abc_ObjData(pNode) ); - } -} - -/**Function************************************************************* - - Synopsis [Writes the primary input list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteNodeGate( FILE * pFile, Abc_Obj_t * pNode, int Length ) -{ - Mio_Gate_t * pGate = pNode->pData; - Mio_Pin_t * pGatePin; - int i; - // write the node - fprintf( pFile, " %-*s ", Length, Mio_GateReadName(pGate) ); - for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) - fprintf( pFile, "%s=%s ", Mio_PinReadName(pGatePin), Abc_ObjName( Abc_ObjFanin(pNode,i) ) ); - assert ( i == Abc_ObjFaninNum(pNode) ); - fprintf( pFile, "%s=%s", Mio_GateReadOutName(pGate), Abc_ObjName( Abc_ObjFanout0(pNode) ) ); -} - -/**Function************************************************************* - - Synopsis [Writes the primary input list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteNodeFanins( FILE * pFile, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pNet; - int LineLength; - int AddedLength; - int NameCounter; - char * pName; - int i; - - LineLength = 6; - NameCounter = 0; - Abc_ObjForEachFanin( pNode, pNet, i ) - { - // get the fanin name - pName = Abc_ObjName(pNet); - // get the line length after the fanin name is written - AddedLength = strlen(pName) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", pName ); - LineLength += AddedLength; - NameCounter++; - } - - // get the output name - pName = Abc_ObjName(Abc_ObjFanout0(pNode)); - // get the line length after the output name is written - AddedLength = strlen(pName) + 1; - if ( NameCounter && LineLength + AddedLength > 75 ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", pName ); -} - -/**Function************************************************************* - - Synopsis [Writes the timing info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteTimingInfo( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - Abc_Time_t * pTime, * pTimeDef; - int i; - - if ( pNtk->pManTime == NULL ) - return; - - pTimeDef = Abc_NtkReadDefaultArrival( pNtk ); - fprintf( pFile, ".default_input_arrival %g %g\n", pTimeDef->Rise, pTimeDef->Fall ); - Abc_NtkForEachPi( pNtk, pNode, i ) - { - pTime = Abc_NodeReadArrival(pNode); - if ( pTime->Rise == pTimeDef->Rise && pTime->Fall == pTimeDef->Fall ) - continue; - fprintf( pFile, ".input_arrival %s %g %g\n", Abc_ObjName(pNode), pTime->Rise, pTime->Fall ); - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteBlifMv.c b/src/base/io/ioWriteBlifMv.c deleted file mode 100644 index 775a2e07..00000000 --- a/src/base/io/ioWriteBlifMv.c +++ /dev/null @@ -1,519 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWriteBlifMv.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write BLIF-MV files.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioWriteBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" -#include "main.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode ); -static void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode ); -static void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch ); -static void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode ); -static void Io_NtkWriteBlifMvValues( FILE * pFile, Abc_Obj_t * pNode ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Write the network into a BLIF file with the given name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteBlifMv( Abc_Ntk_t * pNtk, char * FileName ) -{ - FILE * pFile; - Abc_Ntk_t * pNtkTemp; - int i; - assert( Abc_NtkIsNetlist(pNtk) ); - assert( Abc_NtkHasBlifMv(pNtk) ); - // start writing the file - pFile = fopen( FileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WriteBlifMv(): Cannot open the output file.\n" ); - return; - } - fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); - // write the master network - Io_NtkWriteBlifMv( pFile, pNtk ); - // write the remaining networks - if ( pNtk->pDesign ) - { - Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNtkTemp, i ) - { - if ( pNtkTemp == pNtk ) - continue; - fprintf( pFile, "\n\n" ); - Io_NtkWriteBlifMv( pFile, pNtkTemp ); - } - } - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Write the network into a BLIF file with the given name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteBlifMv( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - assert( Abc_NtkIsNetlist(pNtk) ); - // write the model name - fprintf( pFile, ".model %s\n", Abc_NtkName(pNtk) ); - // write the network - Io_NtkWriteBlifMvOne( pFile, pNtk ); - // write EXDC network if it exists - if ( Abc_NtkExdc(pNtk) ) - printf( "Io_NtkWriteBlifMv(): EXDC is not written.\n" ); - // finalize the file - fprintf( pFile, ".end\n\n\n" ); -} - -/**Function************************************************************* - - Synopsis [Write one network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteBlifMvOne( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - ProgressBar * pProgress; - Abc_Obj_t * pNode, * pTerm, * pLatch; - int i; - - // write the PIs - fprintf( pFile, ".inputs" ); - Io_NtkWriteBlifMvPis( pFile, pNtk ); - fprintf( pFile, "\n" ); - - // write the POs - fprintf( pFile, ".outputs" ); - Io_NtkWriteBlifMvPos( pFile, pNtk ); - fprintf( pFile, "\n" ); - - // write the assertions - if ( Abc_NtkAssertNum(pNtk) ) - { - fprintf( pFile, ".asserts" ); - Io_NtkWriteBlifMvAsserts( pFile, pNtk ); - fprintf( pFile, "\n" ); - } - - // write the MV directives - fprintf( pFile, "\n" ); - Abc_NtkForEachCi( pNtk, pTerm, i ) - if ( Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) > 2 ) - fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanout0(pTerm)) ); - Abc_NtkForEachCo( pNtk, pTerm, i ) - if ( Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) > 2 ) - fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanin0(pTerm)), Abc_ObjMvVarNum(Abc_ObjFanin0(pTerm)) ); - - // write the blackbox - if ( Abc_NtkHasBlackbox( pNtk ) ) - { - fprintf( pFile, ".blackbox\n" ); - return; - } - - // write the timing info -// Io_WriteTimingInfo( pFile, pNtk ); - - // write the latches - if ( !Abc_NtkIsComb(pNtk) ) - { - fprintf( pFile, "\n" ); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - Io_NtkWriteBlifMvLatch( pFile, pLatch ); - fprintf( pFile, "\n" ); - } -/* - // write the subcircuits - assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); - if ( Abc_NtkBlackboxNum(pNtk) > 0 ) - { - fprintf( pFile, "\n" ); - Abc_NtkForEachBlackbox( pNtk, pNode, i ) - Io_NtkWriteBlifMvSubckt( pFile, pNode ); - fprintf( pFile, "\n" ); - } -*/ - if ( Abc_NtkBlackboxNum(pNtk) > 0 || Abc_NtkWhiteboxNum(pNtk) > 0 ) - { - fprintf( pFile, "\n" ); - Abc_NtkForEachBox( pNtk, pNode, i ) - { - if ( Abc_ObjIsLatch(pNode) ) - continue; - Io_NtkWriteBlifMvSubckt( pFile, pNode ); - } - fprintf( pFile, "\n" ); - } - - // write each internal node - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - Io_NtkWriteBlifMvNode( pFile, pNode ); - } - Extra_ProgressBarStop( pProgress ); -} - - -/**Function************************************************************* - - Synopsis [Writes the primary input list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteBlifMvPis( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pTerm, * pNet; - int LineLength; - int AddedLength; - int NameCounter; - int i; - - LineLength = 7; - NameCounter = 0; - - Abc_NtkForEachPi( pNtk, pTerm, i ) - { - pNet = Abc_ObjFanout0(pTerm); - // get the line length after this name is written - AddedLength = strlen(Abc_ObjName(pNet)) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", Abc_ObjName(pNet) ); - LineLength += AddedLength; - NameCounter++; - } -} - -/**Function************************************************************* - - Synopsis [Writes the primary input list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteBlifMvPos( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pTerm, * pNet; - int LineLength; - int AddedLength; - int NameCounter; - int i; - - LineLength = 8; - NameCounter = 0; - - Abc_NtkForEachPo( pNtk, pTerm, i ) - { - pNet = Abc_ObjFanin0(pTerm); - // get the line length after this name is written - AddedLength = strlen(Abc_ObjName(pNet)) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", Abc_ObjName(pNet) ); - LineLength += AddedLength; - NameCounter++; - } -} - -/**Function************************************************************* - - Synopsis [Writes the assertion list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteBlifMvAsserts( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pTerm, * pNet; - int LineLength; - int AddedLength; - int NameCounter; - int i; - - LineLength = 8; - NameCounter = 0; - - Abc_NtkForEachAssert( pNtk, pTerm, i ) - { - pNet = Abc_ObjFanin0(pTerm); - // get the line length after this name is written - AddedLength = strlen(Abc_ObjName(pNet)) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", Abc_ObjName(pNet) ); - LineLength += AddedLength; - NameCounter++; - } -} - -/**Function************************************************************* - - Synopsis [Write the latch into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteBlifMvLatch( FILE * pFile, Abc_Obj_t * pLatch ) -{ - Abc_Obj_t * pNetLi, * pNetLo; - int Reset; - pNetLi = Abc_ObjFanin0( Abc_ObjFanin0(pLatch) ); - pNetLo = Abc_ObjFanout0( Abc_ObjFanout0(pLatch) ); - Reset = (int)Abc_ObjData( pLatch ); - // write the latch line - fprintf( pFile, ".latch" ); - fprintf( pFile, " %10s", Abc_ObjName(pNetLi) ); - fprintf( pFile, " %10s", Abc_ObjName(pNetLo) ); - fprintf( pFile, "\n" ); - // write the reset node - fprintf( pFile, ".reset %s\n", Abc_ObjName(pNetLo) ); - fprintf( pFile, "%d\n", Reset-1 ); -} - -/**Function************************************************************* - - Synopsis [Write the latch into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteBlifMvSubckt( FILE * pFile, Abc_Obj_t * pNode ) -{ - Abc_Ntk_t * pModel = pNode->pData; - Abc_Obj_t * pTerm; - int i; - // write the MV directives - fprintf( pFile, "\n" ); - Abc_ObjForEachFanin( pNode, pTerm, i ) - if ( Abc_ObjMvVarNum(pTerm) > 2 ) - fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) ); - Abc_ObjForEachFanout( pNode, pTerm, i ) - if ( Abc_ObjMvVarNum(pTerm) > 2 ) - fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pTerm), Abc_ObjMvVarNum(pTerm) ); - // write the subcircuit - fprintf( pFile, ".subckt %s %s", Abc_NtkName(pModel), Abc_ObjName(pNode) ); - // write pairs of the formal=actual names - Abc_NtkForEachPi( pModel, pTerm, i ) - { - fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); - pTerm = Abc_ObjFanin( pNode, i ); - fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); - } - Abc_NtkForEachPo( pModel, pTerm, i ) - { - fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pTerm)) ); - pTerm = Abc_ObjFanout( pNode, i ); - fprintf( pFile, "=%s", Abc_ObjName(Abc_ObjFanout0(pTerm)) ); - } - fprintf( pFile, "\n" ); -} - - -/**Function************************************************************* - - Synopsis [Write the node into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteBlifMvNode( FILE * pFile, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin; - char * pCur; - int nValues, iFanin, i; - - // write .mv directives for the fanins - fprintf( pFile, "\n" ); - Abc_ObjForEachFanin( pNode, pFanin, i ) - { -// nValues = atoi(pCur); - nValues = Abc_ObjMvVarNum( pFanin ); - if ( nValues > 2 ) - fprintf( pFile, ".mv %s %d\n", Abc_ObjName(pFanin), nValues ); -// while ( *pCur++ != ' ' ); - } - - // write .mv directives for the node -// nValues = atoi(pCur); - nValues = Abc_ObjMvVarNum( Abc_ObjFanout0(pNode) ); - if ( nValues > 2 ) - fprintf( pFile, ".mv %s %d\n", Abc_ObjName(Abc_ObjFanout0(pNode)), nValues ); -// while ( *pCur++ != '\n' ); - - // write the .names line - fprintf( pFile, ".table" ); - Io_NtkWriteBlifMvNodeFanins( pFile, pNode ); - fprintf( pFile, "\n" ); - - // write the cubes - pCur = Abc_ObjData(pNode); - if ( *pCur == 'd' ) - { - fprintf( pFile, ".default " ); - pCur++; - } - // write the literals - for ( ; *pCur; pCur++ ) - { - fprintf( pFile, "%c", *pCur ); - if ( *pCur != '=' ) - continue; - // get the number - iFanin = atoi( pCur+1 ); - fprintf( pFile, "%s", Abc_ObjName(Abc_ObjFanin(pNode,iFanin)) ); - // scroll on to the next symbol - while ( *pCur != ' ' && *pCur != '\n' ) - pCur++; - pCur--; - } -} - -/**Function************************************************************* - - Synopsis [Writes the primary input list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteBlifMvNodeFanins( FILE * pFile, Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pNet; - int LineLength; - int AddedLength; - int NameCounter; - char * pName; - int i; - - LineLength = 6; - NameCounter = 0; - Abc_ObjForEachFanin( pNode, pNet, i ) - { - // get the fanin name - pName = Abc_ObjName(pNet); - // get the line length after the fanin name is written - AddedLength = strlen(pName) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", pName ); - LineLength += AddedLength; - NameCounter++; - } - - // get the output name - pName = Abc_ObjName(Abc_ObjFanout0(pNode)); - // get the line length after the output name is written - AddedLength = strlen(pName) + 1; - if ( NameCounter && LineLength + AddedLength > 75 ) - { // write the line extender - fprintf( pFile, " \\\n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", pName ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteCnf.c b/src/base/io/ioWriteCnf.c deleted file mode 100644 index e1b2d956..00000000 --- a/src/base/io/ioWriteCnf.c +++ /dev/null @@ -1,115 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWriteCnf.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to output CNF of the miter cone.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioWriteCnf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" -#include "satSolver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * s_pNtk = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Write the miter cone into a CNF file for the SAT solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_WriteCnf( Abc_Ntk_t * pNtk, char * pFileName, int fAllPrimes ) -{ - sat_solver * pSat; - if ( Abc_NtkIsStrash(pNtk) ) - printf( "Io_WriteCnf() warning: Generating CNF by applying heuristic AIG to CNF conversion.\n" ); - else - printf( "Io_WriteCnf() warning: Generating CNF by convering logic nodes into CNF clauses.\n" ); - if ( Abc_NtkPoNum(pNtk) != 1 ) - { - fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter (the network with one PO).\n" ); - return 0; - } - if ( Abc_NtkLatchNum(pNtk) != 0 ) - { - fprintf( stdout, "Io_WriteCnf(): Currently can only process the miter for combinational circuits.\n" ); - return 0; - } - if ( Abc_NtkNodeNum(pNtk) == 0 ) - { - fprintf( stdout, "The network has no logic nodes. No CNF file is generaled.\n" ); - return 0; - } - // convert to logic BDD network - if ( Abc_NtkIsLogic(pNtk) ) - Abc_NtkToBdd( pNtk ); - // create solver with clauses - pSat = Abc_NtkMiterSatCreate( pNtk, fAllPrimes ); - if ( pSat == NULL ) - { - fprintf( stdout, "The problem is trivially UNSAT. No CNF file is generated.\n" ); - return 1; - } - // write the clauses - s_pNtk = pNtk; - Sat_SolverWriteDimacs( pSat, pFileName, 0, 0, 1 ); - s_pNtk = NULL; - // free the solver - sat_solver_delete( pSat ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Output the mapping of PIs into variable numbers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteCnfOutputPiMapping( FILE * pFile, int incrementVars ) -{ - extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk ); - Abc_Ntk_t * pNtk = s_pNtk; - Vec_Int_t * vCiIds; - Abc_Obj_t * pObj; - int i; - vCiIds = Abc_NtkGetCiSatVarNums( pNtk ); - fprintf( pFile, "c PI variable numbers: \n" ); - Abc_NtkForEachCi( pNtk, pObj, i ) - fprintf( pFile, "c %s %d\n", Abc_ObjName(pObj), Vec_IntEntry(vCiIds, i) + (int)(incrementVars > 0) ); - Vec_IntFree( vCiIds ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteDot.c b/src/base/io/ioWriteDot.c deleted file mode 100644 index 8ae3cc42..00000000 --- a/src/base/io/ioWriteDot.c +++ /dev/null @@ -1,809 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWriteDot.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write the graph structure of AIG in DOT.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioWriteDot.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" -#include "main.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static char * Abc_NtkPrintSop( char * pSop ); -static int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes the graph structure of network for DOT.] - - Description [Useful for graph visualization using tools such as GraphViz: - http://www.graphviz.org/] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteDot( Abc_Ntk_t * pNtk, char * FileName ) -{ - Vec_Ptr_t * vNodes; - vNodes = Abc_NtkCollectObjects( pNtk ); - Io_WriteDotNtk( pNtk, vNodes, NULL, FileName, 0, 0 ); - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Writes the graph structure of network for DOT.] - - Description [Useful for graph visualization using tools such as GraphViz: - http://www.graphviz.org/] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) -{ - FILE * pFile; - Abc_Obj_t * pNode, * pFanin; - char * pSopString; - int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; - int Limit = 300; - - assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); - - if ( vNodes->nSize < 1 ) - { - printf( "The set has no nodes. DOT file is not written.\n" ); - return; - } - - if ( vNodes->nSize > Limit ) - { - printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); - return; - } - - // start the stream - if ( (pFile = fopen( pFileName, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); - return; - } - - // transform logic functions from BDD to SOP - if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) - { - if ( !Abc_NtkBddToSop(pNtk, 0) ) - { - printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); - return; - } - } - - // mark the nodes from the set - Vec_PtrForEachEntry( vNodes, pNode, i ) - pNode->fMarkC = 1; - if ( vNodesShow ) - Vec_PtrForEachEntry( vNodesShow, pNode, i ) - pNode->fMarkB = 1; - - // get the levels of nodes - LevelMax = Abc_NtkLevel( pNtk ); - if ( fUseReverse ) - { - LevelMin = Abc_NtkLevelReverse( pNtk ); - assert( LevelMax == LevelMin ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - if ( Abc_ObjIsNode(pNode) ) - pNode->Level = LevelMax - pNode->Level + 1; - } - - // find the largest and the smallest levels - LevelMin = 10000; - LevelMax = -1; - fHasCos = 0; - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( Abc_ObjIsCo(pNode) ) - { - fHasCos = 1; - continue; - } - if ( LevelMin > (int)pNode->Level ) - LevelMin = pNode->Level; - if ( LevelMax < (int)pNode->Level ) - LevelMax = pNode->Level; - } - - // set the level of the CO nodes - if ( fHasCos ) - { - LevelMax++; - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( Abc_ObjIsCo(pNode) ) - pNode->Level = LevelMax; - } - } - - // write the DOT header - fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "digraph network {\n" ); - fprintf( pFile, "size = \"7.5,10\";\n" ); -// fprintf( pFile, "size = \"10,8.5\";\n" ); -// fprintf( pFile, "size = \"14,11\";\n" ); -// fprintf( pFile, "page = \"8,11\";\n" ); -// fprintf( pFile, "ranksep = 0.5;\n" ); -// fprintf( pFile, "nodesep = 0.5;\n" ); - fprintf( pFile, "center = true;\n" ); -// fprintf( pFile, "orientation = landscape;\n" ); -// fprintf( pFile, "edge [fontsize = 10];\n" ); -// fprintf( pFile, "edge [dir = none];\n" ); - fprintf( pFile, "edge [dir = back];\n" ); - fprintf( pFile, "\n" ); - - // labels on the left of the picture - fprintf( pFile, "{\n" ); - fprintf( pFile, " node [shape = plaintext];\n" ); - fprintf( pFile, " edge [style = invis];\n" ); - fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); - fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); - // generate node names with labels - for ( Level = LevelMax; Level >= LevelMin; Level-- ) - { - // the visible node name - fprintf( pFile, " Level%d", Level ); - fprintf( pFile, " [label = " ); - // label name - fprintf( pFile, "\"" ); - fprintf( pFile, "\"" ); - fprintf( pFile, "];\n" ); - } - - // genetate the sequence of visible/invisible nodes to mark levels - fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); - for ( Level = LevelMax; Level >= LevelMin; Level-- ) - { - // the visible node name - fprintf( pFile, " Level%d", Level ); - // the connector - if ( Level != LevelMin ) - fprintf( pFile, " ->" ); - else - fprintf( pFile, ";" ); - } - fprintf( pFile, "\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate title box on top - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - fprintf( pFile, " LevelTitle1;\n" ); - fprintf( pFile, " title1 [shape=plaintext,\n" ); - fprintf( pFile, " fontsize=20,\n" ); - fprintf( pFile, " fontname = \"Times-Roman\",\n" ); - fprintf( pFile, " label=\"" ); - fprintf( pFile, "%s", "Network structure visualized by ABC" ); - fprintf( pFile, "\\n" ); - fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); - fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); - fprintf( pFile, "\"\n" ); - fprintf( pFile, " ];\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate statistics box - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - fprintf( pFile, " LevelTitle2;\n" ); - fprintf( pFile, " title2 [shape=plaintext,\n" ); - fprintf( pFile, " fontsize=18,\n" ); - fprintf( pFile, " fontname = \"Times-Roman\",\n" ); - fprintf( pFile, " label=\"" ); - if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) - fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); - else - fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); - fprintf( pFile, "\\n" ); - fprintf( pFile, "\"\n" ); - fprintf( pFile, " ];\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate the POs - if ( fHasCos ) - { - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", LevelMax ); - // generate the PO nodes - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( !Abc_ObjIsCo(pNode) ) - continue; - fprintf( pFile, " Node%d [label = \"%s%s\"", - pNode->Id, - (Abc_ObjIsBi(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)):Abc_ObjName(pNode)), - (Abc_ObjIsBi(pNode)? "_in":"") ); - fprintf( pFile, ", shape = %s", (Abc_ObjIsBi(pNode)? "box":"invtriangle") ); - if ( pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - } - - // generate nodes of each rank - for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- ) - { - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", Level ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( (int)pNode->Level != Level ) - continue; - if ( Abc_ObjFaninNum(pNode) == 0 ) - continue; -// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); - if ( Abc_NtkIsStrash(pNtk) ) - pSopString = ""; - else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) - pSopString = Mio_GateReadName(pNode->pData); - else if ( Abc_NtkHasMapping(pNtk) ) - pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); - else - pSopString = Abc_NtkPrintSop(pNode->pData); - fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); - - fprintf( pFile, ", shape = ellipse" ); - if ( pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - } - - // generate the PI nodes if any - if ( LevelMin == 0 ) - { - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", LevelMin ); - // generate the PO nodes - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( !Abc_ObjIsCi(pNode) ) - { - // check if the costant node is present - if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) - { - fprintf( pFile, " Node%d [label = \"Const%d\"", pNode->Id, Abc_NtkIsStrash(pNode->pNtk) || Abc_NodeIsConst1(pNode) ); - fprintf( pFile, ", shape = ellipse" ); - if ( pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - continue; - } - fprintf( pFile, " Node%d [label = \"%s\"", - pNode->Id, - (Abc_ObjIsBo(pNode)? Abc_ObjName(Abc_ObjFanin0(pNode)):Abc_ObjName(pNode)) ); - fprintf( pFile, ", shape = %s", (Abc_ObjIsBo(pNode)? "box":"triangle") ); - if ( pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - } - - // generate invisible edges from the square down - fprintf( pFile, "title1 -> title2 [style = invis];\n" ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( (int)pNode->Level != LevelMax ) - continue; - fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); - } - - // generate edges - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( Abc_ObjIsLatch(pNode) ) - continue; - Abc_ObjForEachFanin( pNode, pFanin, k ) - { - if ( Abc_ObjIsLatch(pFanin) ) - continue; - fCompl = 0; - if ( Abc_NtkIsStrash(pNtk) ) - fCompl = Abc_ObjFaninC(pNode, k); - // generate the edge from this node to the next - fprintf( pFile, "Node%d", pNode->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d", pFanin->Id ); - fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); -// fprintf( pFile, ", label = \"%c\"", 'a' + k ); - fprintf( pFile, "]" ); - fprintf( pFile, ";\n" ); - } - } - - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - fclose( pFile ); - - // unmark the nodes from the set - Vec_PtrForEachEntry( vNodes, pNode, i ) - pNode->fMarkC = 0; - if ( vNodesShow ) - Vec_PtrForEachEntry( vNodesShow, pNode, i ) - pNode->fMarkB = 0; - - // convert the network back into BDDs if this is how it was - if ( fHasBdds ) - Abc_NtkSopToBdd(pNtk); -} - - -/**Function************************************************************* - - Synopsis [Writes the graph structure of network for DOT.] - - Description [Useful for graph visualization using tools such as GraphViz: - http://www.graphviz.org/] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteDotSeq( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) -{ - FILE * pFile; - Abc_Obj_t * pNode, * pFanin; - char * pSopString; - int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; - int Limit = 300; - - assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); - - if ( vNodes->nSize < 1 ) - { - printf( "The set has no nodes. DOT file is not written.\n" ); - return; - } - - if ( vNodes->nSize > Limit ) - { - printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); - return; - } - - // start the stream - if ( (pFile = fopen( pFileName, "w" )) == NULL ) - { - fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); - return; - } - - // transform logic functions from BDD to SOP - if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) - { - if ( !Abc_NtkBddToSop(pNtk, 0) ) - { - printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); - return; - } - } - - // mark the nodes from the set - Vec_PtrForEachEntry( vNodes, pNode, i ) - pNode->fMarkC = 1; - if ( vNodesShow ) - Vec_PtrForEachEntry( vNodesShow, pNode, i ) - pNode->fMarkB = 1; - - // get the levels of nodes - LevelMax = Abc_NtkLevel( pNtk ); - if ( fUseReverse ) - { - LevelMin = Abc_NtkLevelReverse( pNtk ); - assert( LevelMax == LevelMin ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - if ( Abc_ObjIsNode(pNode) ) - pNode->Level = LevelMax - pNode->Level + 1; - } - - // find the largest and the smallest levels - LevelMin = 10000; - LevelMax = -1; - fHasCos = 0; - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( Abc_ObjIsCo(pNode) ) - { - fHasCos = 1; - continue; - } - if ( LevelMin > (int)pNode->Level ) - LevelMin = pNode->Level; - if ( LevelMax < (int)pNode->Level ) - LevelMax = pNode->Level; - } - - // set the level of the CO nodes - if ( fHasCos ) - { - LevelMax++; - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( Abc_ObjIsCo(pNode) ) - pNode->Level = LevelMax; - } - } - - // write the DOT header - fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "digraph network {\n" ); - fprintf( pFile, "size = \"7.5,10\";\n" ); -// fprintf( pFile, "size = \"10,8.5\";\n" ); -// fprintf( pFile, "size = \"14,11\";\n" ); -// fprintf( pFile, "page = \"8,11\";\n" ); -// fprintf( pFile, "ranksep = 0.5;\n" ); -// fprintf( pFile, "nodesep = 0.5;\n" ); - fprintf( pFile, "center = true;\n" ); -// fprintf( pFile, "orientation = landscape;\n" ); -// fprintf( pFile, "edge [fontsize = 10];\n" ); -// fprintf( pFile, "edge [dir = none];\n" ); - fprintf( pFile, "edge [dir = back];\n" ); - fprintf( pFile, "\n" ); - - // labels on the left of the picture - fprintf( pFile, "{\n" ); - fprintf( pFile, " node [shape = plaintext];\n" ); - fprintf( pFile, " edge [style = invis];\n" ); - fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); - fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); - // generate node names with labels - for ( Level = LevelMax; Level >= LevelMin; Level-- ) - { - // the visible node name - fprintf( pFile, " Level%d", Level ); - fprintf( pFile, " [label = " ); - // label name - fprintf( pFile, "\"" ); - fprintf( pFile, "\"" ); - fprintf( pFile, "];\n" ); - } - - // genetate the sequence of visible/invisible nodes to mark levels - fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); - for ( Level = LevelMax; Level >= LevelMin; Level-- ) - { - // the visible node name - fprintf( pFile, " Level%d", Level ); - // the connector - if ( Level != LevelMin ) - fprintf( pFile, " ->" ); - else - fprintf( pFile, ";" ); - } - fprintf( pFile, "\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate title box on top - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - fprintf( pFile, " LevelTitle1;\n" ); - fprintf( pFile, " title1 [shape=plaintext,\n" ); - fprintf( pFile, " fontsize=20,\n" ); - fprintf( pFile, " fontname = \"Times-Roman\",\n" ); - fprintf( pFile, " label=\"" ); - fprintf( pFile, "%s", "Network structure visualized by ABC" ); - fprintf( pFile, "\\n" ); - fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); - fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); - fprintf( pFile, "\"\n" ); - fprintf( pFile, " ];\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate statistics box - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - fprintf( pFile, " LevelTitle2;\n" ); - fprintf( pFile, " title2 [shape=plaintext,\n" ); - fprintf( pFile, " fontsize=18,\n" ); - fprintf( pFile, " fontname = \"Times-Roman\",\n" ); - fprintf( pFile, " label=\"" ); - if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) - fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); - else - fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); - fprintf( pFile, "\\n" ); - fprintf( pFile, "\"\n" ); - fprintf( pFile, " ];\n" ); - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate the POs - if ( fHasCos ) - { - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", LevelMax ); - // generate the PO nodes - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( !Abc_ObjIsPo(pNode) ) - continue; - fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); - fprintf( pFile, ", shape = %s", "invtriangle" ); - if ( pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - } - - // generate nodes of each rank - for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- ) - { - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", Level ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - if ( (int)pNode->Level != Level ) - continue; -// fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); - if ( Abc_NtkIsStrash(pNtk) ) - pSopString = ""; - else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) - pSopString = Mio_GateReadName(pNode->pData); - else if ( Abc_NtkHasMapping(pNtk) ) - pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); - else - pSopString = Abc_NtkPrintSop(pNode->pData); - fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); - - fprintf( pFile, ", shape = ellipse" ); - if ( pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - } - - // generate the PI nodes if any - if ( LevelMin == 0 ) - { - fprintf( pFile, "{\n" ); - fprintf( pFile, " rank = same;\n" ); - // the labeling node of this level - fprintf( pFile, " Level%d;\n", LevelMin ); - // generate the PO nodes - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( pNode->Level > 0 ) - continue; - if ( !Abc_ObjIsPi(pNode) ) - { - // check if the costant node is present - if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) - { - fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); - fprintf( pFile, ", shape = ellipse" ); - if ( pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - continue; - } - fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); - fprintf( pFile, ", shape = %s", "triangle" ); - if ( pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - } - -// fprintf( pFile, "{\n" ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( !Abc_ObjIsLatch(pNode) ) - continue; - fprintf( pFile, "Node%d [label = \"%s\"", pNode->Id, Abc_ObjName(pNode) ); - fprintf( pFile, ", shape = box" ); - if ( pNode->fMarkB ) - fprintf( pFile, ", style = filled" ); - fprintf( pFile, ", color = coral, fillcolor = coral" ); - fprintf( pFile, "];\n" ); - } -// fprintf( pFile, "}" ); -// fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - - // generate invisible edges from the square down - fprintf( pFile, "title1 -> title2 [style = invis];\n" ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( (int)pNode->Level != LevelMax ) - continue; - if ( !Abc_ObjIsPo(pNode) ) - continue; - fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); - } - - // generate edges - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( Abc_ObjIsBi(pNode) || Abc_ObjIsBo(pNode) ) - continue; - Abc_ObjForEachFanin( pNode, pFanin, k ) - { - fCompl = 0; - if ( Abc_NtkIsStrash(pNtk) ) - { - if ( Abc_ObjIsBi(pFanin) ) - fCompl = Abc_ObjFaninC(pFanin, k); - else - fCompl = Abc_ObjFaninC(pNode, k); - } - if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) - pFanin = Abc_ObjFanin0(pFanin); - if ( Abc_ObjIsBi(pFanin) || Abc_ObjIsBo(pFanin) ) - pFanin = Abc_ObjFanin0(pFanin); - if ( !pFanin->fMarkC ) - continue; - - // generate the edge from this node to the next - fprintf( pFile, "Node%d", pNode->Id ); - fprintf( pFile, " -> " ); - fprintf( pFile, "Node%d", pFanin->Id ); - fprintf( pFile, " [style = %s", fCompl? "dotted" : "bold" ); -// fprintf( pFile, ", label = \"%c\"", 'a' + k ); - fprintf( pFile, "]" ); - fprintf( pFile, ";\n" ); - } - } - - fprintf( pFile, "}" ); - fprintf( pFile, "\n" ); - fprintf( pFile, "\n" ); - fclose( pFile ); - - // unmark the nodes from the set - Vec_PtrForEachEntry( vNodes, pNode, i ) - pNode->fMarkC = 0; - if ( vNodesShow ) - Vec_PtrForEachEntry( vNodesShow, pNode, i ) - pNode->fMarkB = 0; - - // convert the network back into BDDs if this is how it was - if ( fHasBdds ) - Abc_NtkSopToBdd(pNtk); -} - - -/**Function************************************************************* - - Synopsis [Computes the printable SOP form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_NtkPrintSop( char * pSop ) -{ - static char Buffer[1000]; - char * pGet, * pSet; - pSet = Buffer; - for ( pGet = pSop; *pGet; pGet++ ) - { - if ( *pGet == '\n' ) - { - *pSet++ = '\\'; - *pSet++ = 'n'; - } - else - *pSet++ = *pGet; - } - *(pSet-2) = 0; - return Buffer; -} - -/**Function************************************************************* - - Synopsis [Computes the printable SOP form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkCountLogicNodes( Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pObj; - int i, Counter = 0; - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - if ( !Abc_ObjIsNode(pObj) ) - continue; - if ( Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 ) - continue; - Counter ++; - } - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteEqn.c b/src/base/io/ioWriteEqn.c deleted file mode 100644 index 95c54577..00000000 --- a/src/base/io/ioWriteEqn.c +++ /dev/null @@ -1,252 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWriteEqn.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write equation representation of the network.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioWriteEqn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ); -static int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes the logic network in the equation format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteEqn( Abc_Ntk_t * pNtk, char * pFileName ) -{ - FILE * pFile; - - assert( Abc_NtkIsAigNetlist(pNtk) ); - if ( Abc_NtkLatchNum(pNtk) > 0 ) - printf( "Warning: only combinational portion is being written.\n" ); - - // check that the names are fine for the EQN format - if ( !Io_NtkWriteEqnCheck(pNtk) ) - return; - - // start the output stream - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WriteEqn(): Cannot open the output file \"%s\".\n", pFileName ); - return; - } - fprintf( pFile, "# Equations for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); - - // write the equations for the network - Io_NtkWriteEqnOne( pFile, pNtk ); - fprintf( pFile, "\n" ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Write one network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Vec_Vec_t * vLevels; - ProgressBar * pProgress; - Abc_Obj_t * pNode, * pFanin; - int i, k; - - // write the PIs - fprintf( pFile, "INORDER =" ); - Io_NtkWriteEqnCis( pFile, pNtk ); - fprintf( pFile, ";\n" ); - - // write the POs - fprintf( pFile, "OUTORDER =" ); - Io_NtkWriteEqnCos( pFile, pNtk ); - fprintf( pFile, ";\n" ); - - // write each internal node - vLevels = Vec_VecAlloc( 10 ); - pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - fprintf( pFile, "%s = ", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - // set the input names - Abc_ObjForEachFanin( pNode, pFanin, k ) - Hop_IthVar(pNtk->pManFunc, k)->pData = Abc_ObjName(pFanin); - // write the formula - Hop_ObjPrintEqn( pFile, pNode->pData, vLevels, 0 ); - fprintf( pFile, ";\n" ); - } - Extra_ProgressBarStop( pProgress ); - Vec_VecFree( vLevels ); -} - - -/**Function************************************************************* - - Synopsis [Writes the primary input list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteEqnCis( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pTerm, * pNet; - int LineLength; - int AddedLength; - int NameCounter; - int i; - - LineLength = 9; - NameCounter = 0; - - Abc_NtkForEachCi( pNtk, pTerm, i ) - { - pNet = Abc_ObjFanout0(pTerm); - // get the line length after this name is written - AddedLength = strlen(Abc_ObjName(pNet)) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", Abc_ObjName(pNet) ); - LineLength += AddedLength; - NameCounter++; - } -} - -/**Function************************************************************* - - Synopsis [Writes the primary input list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_NtkWriteEqnCos( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pTerm, * pNet; - int LineLength; - int AddedLength; - int NameCounter; - int i; - - LineLength = 10; - NameCounter = 0; - - Abc_NtkForEachCo( pNtk, pTerm, i ) - { - pNet = Abc_ObjFanin0(pTerm); - // get the line length after this name is written - AddedLength = strlen(Abc_ObjName(pNet)) + 1; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, " \n" ); - // reset the line length - LineLength = 0; - NameCounter = 0; - } - fprintf( pFile, " %s", Abc_ObjName(pNet) ); - LineLength += AddedLength; - NameCounter++; - } -} - -/**Function************************************************************* - - Synopsis [Make sure the network does not have offending names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_NtkWriteEqnCheck( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - char * pName; - int i, k, Length; - int RetValue = 1; - - // make sure the network does not have proper names, such as "0" or "1" or containing parantheses - Abc_NtkForEachObj( pNtk, pObj, i ) - { - pName = Nm_ManFindNameById(pNtk->pManName, i); - if ( pName == NULL ) - continue; - Length = strlen(pName); - if ( pName[0] == '0' || pName[0] == '1' ) - { - RetValue = 0; - break; - } - for ( k = 0; k < Length; k++ ) - if ( pName[k] == '(' || pName[k] == ')' || pName[k] == '!' || pName[k] == '*' || pName[k] == '+' ) - { - RetValue = 0; - break; - } - if ( k < Length ) - break; - } - if ( RetValue == 0 ) - { - printf( "The network cannot be written in the EQN format because object %d has name \"%s\".\n", i, pName ); - printf( "Consider renaming the objects using command \"short_names\" and trying again.\n" ); - } - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteGml.c b/src/base/io/ioWriteGml.c deleted file mode 100644 index dc897300..00000000 --- a/src/base/io/ioWriteGml.c +++ /dev/null @@ -1,116 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWriteGml.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write the graph structure of AIG in GML.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioWriteGml.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes the graph structure of AIG in GML.] - - Description [Useful for graph visualization using tools such as yEd: - http://www.yworks.com/] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ) -{ - FILE * pFile; - Abc_Obj_t * pObj, * pFanin; - int i, k; - - assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); - - // start the output stream - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WriteGml(): Cannot open the output file \"%s\".\n", pFileName ); - return; - } - fprintf( pFile, "# GML for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); - fprintf( pFile, "graph [\n" ); - - // output the POs - fprintf( pFile, "\n" ); - Abc_NtkForEachPo( pNtk, pObj, i ) - { - fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); - fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FFFF\" ]\n" ); // blue - fprintf( pFile, " ]\n" ); - } - // output the PIs - fprintf( pFile, "\n" ); - Abc_NtkForEachPi( pNtk, pObj, i ) - { - fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); - fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FF00\" ]\n" ); // green - fprintf( pFile, " ]\n" ); - } - // output the latches - fprintf( pFile, "\n" ); - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); - fprintf( pFile, " graphics [ type \"rectangle\" fill \"#FF0000\" ]\n" ); // red - fprintf( pFile, " ]\n" ); - } - // output the nodes - fprintf( pFile, "\n" ); - Abc_NtkForEachNode( pNtk, pObj, i ) - { - fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); - fprintf( pFile, " graphics [ type \"ellipse\" fill \"#CCCCFF\" ]\n" ); // grey - fprintf( pFile, " ]\n" ); - } - - // output the edges - fprintf( pFile, "\n" ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - fprintf( pFile, " edge [ source %5d target %5d\n", pObj->Id, pFanin->Id ); - fprintf( pFile, " graphics [ type \"line\" arrow \"first\" ]\n" ); - fprintf( pFile, " ]\n" ); - } - } - - fprintf( pFile, "]\n" ); - fprintf( pFile, "\n" ); - fclose( pFile ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteList.c b/src/base/io/ioWriteList.c deleted file mode 100644 index 71af7c53..00000000 --- a/src/base/io/ioWriteList.c +++ /dev/null @@ -1,288 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWriteList.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write the graph structure of sequential AIG.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioWriteList.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -/* --------- Original Message -------- -Subject: Re: abc release and retiming -Date: Sun, 13 Nov 2005 20:31:18 -0500 (EST) -From: Luca Carloni -To: Alan Mishchenko - -Alan, - -My graph-representation file format is based on an adjacency list -representation and is indeed quite simple, in fact maybe too simple... I -used it in order to reason on relatively small weighed direct graphs. I -simply list all vertices, one per line and for each vertex "V_source" I -list all vertices that are "sinks" with respect to it, i.e. such that -there is a distinct arc between "V_source" and each of them (in -paranthesis I list the name of the edge and its weight (number of latency -on that path). For instance, if you look at the following graph, you have -that vertex "v_5" is connected to vertex "v_6" through a directed arc -called "v_5_to_v_6" whose latency is equal to 3, i.e. there are three -flip-flops on this arc. Still, notice that I sometime interpret the graph -also as the representation of a LIS where each node corresponds to a -shell encapsulating a sequential core module (i.e. a module which does not -contain any combinational path between its inputs and its outputs). With -this representation an arc of latency 3 is interpreted as a wire where two -relay stations have been inserted in addition to the flip-flop terminating -the output of the core module. - -Finally, notice that the name of the arc does not necessarily have to be -"v_5_to_v_6", but it could have been something like "arc_222" or "xyz" as -long as it is a unique name in the graph. - -Thanks, -Luca - -Example of graph representation ------------------------------------------------------------------------------ -v_5 > v_6 ([v_5_to_v_6] = 3), v_12 ([v_5_to_v_12] = 2). -v_2 > v_4 ([v_2_to_v_4] = 1), v_10_s0 ([v_2_to_v_10_s0] = 6), v_12 ([v_2_to_v_12] = 3). -v_9 > v_10_s0 ([v_9_to_v_10_s0] = 5), v_12 ([v_9_to_v_12] = 2). -v_12 > v_13 ([v_12_to_v_13] = 5). -v_13 > v_14 ([v_13_to_v_14] = 1). -v_6 > v_7 ([v_6_to_v_7] = 2). -v_4 > v_5 ([v_4_to_v_5] = 2). -v_1 > v_2 ([v_1_to_v_2] = 1). -v_7 > v_8 ([v_7_to_v_8] = 2). -t > . -v_14 > t ([v_14_to_t] = 1), v_5 ([v_14_to_v_5] = 1). -v_8 > v_9 ([v_8_to_v_9] = 2). -s > v_1 ([s_to_v_1] = 1). -v_10_s0 > v_10_s1 ([v_10_s0_to_v_10_s1] = 1). -v_10_s1 > v_4 ([v_10_s1__v_4] = 1), v_8 ([v_10_s1__v_8] = 1). ------------------------------------------------------------------------------ -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj ); -static void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes the adjacency list for a sequential AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteList( Abc_Ntk_t * pNtk, char * pFileName, int fUseHost ) -{ - FILE * pFile; - Abc_Obj_t * pObj; - int i; - -// assert( Abc_NtkIsSeq(pNtk) ); - - // start the output stream - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WriteList(): Cannot open the output file \"%s\".\n", pFileName ); - return; - } - - fprintf( pFile, "# Adjacency list for sequential AIG \"%s\"\n", pNtk->pName ); - fprintf( pFile, "# written by ABC on %s\n", Extra_TimeStamp() ); - - // write the constant node - if ( Abc_ObjFanoutNum( Abc_AigConst1(pNtk) ) > 0 ) - Io_WriteListEdge( pFile, Abc_AigConst1(pNtk) ); - - // write the PI edges - Abc_NtkForEachPi( pNtk, pObj, i ) - Io_WriteListEdge( pFile, pObj ); - - // write the internal nodes - Abc_AigForEachAnd( pNtk, pObj, i ) - Io_WriteListEdge( pFile, pObj ); - - // write the host node - if ( fUseHost ) - Io_WriteListHost( pFile, pNtk ); - else - Abc_NtkForEachPo( pNtk, pObj, i ) - Io_WriteListEdge( pFile, pObj ); - - fprintf( pFile, "\n" ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Writes the adjacency list for one edge in a sequential AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteListEdge( FILE * pFile, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout; - int i; - fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - fprintf( pFile, " %s", Abc_ObjName(pFanout) ); - fprintf( pFile, " ([%s_to_", Abc_ObjName(pObj) ); -// fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), Seq_ObjFanoutL(pObj, pFanout) ); - fprintf( pFile, "%s] = %d)", Abc_ObjName(pFanout), 0 ); - if ( i != Abc_ObjFanoutNum(pObj) - 1 ) - fprintf( pFile, "," ); - } - fprintf( pFile, "." ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes the adjacency list for one edge in a sequential AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteListHost( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - - Abc_NtkForEachPo( pNtk, pObj, i ) - { - fprintf( pFile, "%-10s > ", Abc_ObjName(pObj) ); - fprintf( pFile, " %s ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), "HOST", 0 ); - fprintf( pFile, "." ); - fprintf( pFile, "\n" ); - } - - fprintf( pFile, "%-10s > ", "HOST" ); - Abc_NtkForEachPi( pNtk, pObj, i ) - { - fprintf( pFile, " %s", Abc_ObjName(pObj) ); - fprintf( pFile, " ([%s_to_%s] = %d)", "HOST", Abc_ObjName(pObj), 0 ); - if ( i != Abc_NtkPiNum(pNtk) - 1 ) - fprintf( pFile, "," ); - } - fprintf( pFile, "." ); - fprintf( pFile, "\n" ); -} - - -/**Function************************************************************* - - Synopsis [Writes the adjacency list for a sequential AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteCellNet( Abc_Ntk_t * pNtk, char * pFileName ) -{ - FILE * pFile; - Abc_Obj_t * pObj, * pFanout; - int i, k; - - assert( Abc_NtkIsLogic(pNtk) ); - - // start the output stream - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WriteCellNet(): Cannot open the output file \"%s\".\n", pFileName ); - return; - } - - fprintf( pFile, "# CellNet file for network \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); - - // the only tricky part with writing is handling latches: - // each latch comes with (a) single-input latch-input node, (b) latch proper, (c) single-input latch-output node - // we arbitrarily decide to use the interger ID of the latch-input node to represent the latch in the file - // (this ID is used for both the cell and the net driven by that cell) - - // write the PIs - Abc_NtkForEachPi( pNtk, pObj, i ) - fprintf( pFile, "cell %d is 0\n", pObj->Id ); - // write the POs - Abc_NtkForEachPo( pNtk, pObj, i ) - fprintf( pFile, "cell %d is 1\n", pObj->Id ); - // write the latches (use the ID of latch input) - Abc_NtkForEachLatch( pNtk, pObj, i ) - fprintf( pFile, "cell %d is 2\n", Abc_ObjFanin0(pObj)->Id ); - // write the logic nodes - Abc_NtkForEachNode( pNtk, pObj, i ) - fprintf( pFile, "cell %d is %d\n", pObj->Id, 3+Abc_ObjFaninNum(pObj) ); - - // write the nets driven by PIs - Abc_NtkForEachPi( pNtk, pObj, i ) - { - fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id ); - Abc_ObjForEachFanout( pObj, pFanout, k ) - fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); - fprintf( pFile, "\n" ); - } - // write the nets driven by latches - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - fprintf( pFile, "net %d %d 0", Abc_ObjFanin0(pObj)->Id, Abc_ObjFanin0(pObj)->Id ); - pObj = Abc_ObjFanout0(pObj); - Abc_ObjForEachFanout( pObj, pFanout, k ) - fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); - fprintf( pFile, "\n" ); - } - // write the nets driven by nodes - Abc_NtkForEachNode( pNtk, pObj, i ) - { - fprintf( pFile, "net %d %d 0", pObj->Id, pObj->Id ); - Abc_ObjForEachFanout( pObj, pFanout, k ) - fprintf( pFile, " %d %d", pFanout->Id, 1 + Abc_ObjFanoutFaninNum(pFanout, pObj) ); - fprintf( pFile, "\n" ); - } - - fprintf( pFile, "\n" ); - fclose( pFile ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWritePla.c b/src/base/io/ioWritePla.c deleted file mode 100644 index b119751c..00000000 --- a/src/base/io/ioWritePla.c +++ /dev/null @@ -1,197 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWritePla.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to write the network in BENCH format.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioWritePla.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes the network in PLA format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_WritePla( Abc_Ntk_t * pNtk, char * pFileName ) -{ - Abc_Ntk_t * pExdc; - FILE * pFile; - - assert( Abc_NtkIsSopNetlist(pNtk) ); - assert( Abc_NtkLevel(pNtk) == 1 ); - - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WritePla(): Cannot open the output file.\n" ); - return 0; - } - fprintf( pFile, "# Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); - // write the network - Io_WritePlaOne( pFile, pNtk ); - // write EXDC network if it exists - pExdc = Abc_NtkExdc( pNtk ); - if ( pExdc ) - printf( "Io_WritePla: EXDC is not written (warning).\n" ); - // finalize the file - fclose( pFile ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Writes the network in PLA format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_WritePlaOne( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - ProgressBar * pProgress; - Abc_Obj_t * pNode, * pFanin, * pDriver; - char * pCubeIn, * pCubeOut, * pCube; - int i, k, nProducts, nInputs, nOutputs, nFanins; - - nProducts = 0; - Abc_NtkForEachCo( pNtk, pNode, i ) - { - pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); - if ( !Abc_ObjIsNode(pDriver) ) - { - nProducts++; - continue; - } - if ( Abc_NodeIsConst(pDriver) ) - { - if ( Abc_NodeIsConst1(pDriver) ) - nProducts++; - continue; - } - nProducts += Abc_SopGetCubeNum(pDriver->pData); - } - - // collect the parameters - nInputs = Abc_NtkCiNum(pNtk); - nOutputs = Abc_NtkCoNum(pNtk); - pCubeIn = ALLOC( char, nInputs + 1 ); - pCubeOut = ALLOC( char, nOutputs + 1 ); - memset( pCubeIn, '-', nInputs ); pCubeIn[nInputs] = 0; - memset( pCubeOut, '0', nOutputs ); pCubeOut[nOutputs] = 0; - - // write the header - fprintf( pFile, ".i %d\n", nInputs ); - fprintf( pFile, ".o %d\n", nOutputs ); - fprintf( pFile, ".ilb" ); - Abc_NtkForEachCi( pNtk, pNode, i ) - fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - fprintf( pFile, "\n" ); - fprintf( pFile, ".ob" ); - Abc_NtkForEachCo( pNtk, pNode, i ) - fprintf( pFile, " %s", Abc_ObjName(Abc_ObjFanin0(pNode)) ); - fprintf( pFile, "\n" ); - fprintf( pFile, ".p %d\n", nProducts ); - - // mark the CI nodes - Abc_NtkForEachCi( pNtk, pNode, i ) - pNode->pCopy = (Abc_Obj_t *)i; - - // write the cubes - pProgress = Extra_ProgressBarStart( stdout, nOutputs ); - Abc_NtkForEachCo( pNtk, pNode, i ) - { - // prepare the output cube - if ( i - 1 >= 0 ) - pCubeOut[i-1] = '0'; - pCubeOut[i] = '1'; - - // consider special cases of nodes - pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pNode) ); - if ( !Abc_ObjIsNode(pDriver) ) - { - assert( Abc_ObjIsCi(pDriver) ); - pCubeIn[(int)pDriver->pCopy] = '1' - Abc_ObjFaninC0(pNode); - fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); - pCubeIn[(int)pDriver->pCopy] = '-'; - continue; - } - if ( Abc_NodeIsConst(pDriver) ) - { - if ( Abc_NodeIsConst1(pDriver) ) - fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); - continue; - } - - // make sure the cover is not complemented - assert( !Abc_SopIsComplement( pDriver->pData ) ); - - // write the cubes - nFanins = Abc_ObjFaninNum(pDriver); - Abc_SopForEachCube( pDriver->pData, nFanins, pCube ) - { - Abc_ObjForEachFanin( pDriver, pFanin, k ) - { - pFanin = Abc_ObjFanin0Ntk(pFanin); - assert( (int)pFanin->pCopy < nInputs ); - pCubeIn[(int)pFanin->pCopy] = pCube[k]; - } - fprintf( pFile, "%s %s\n", pCubeIn, pCubeOut ); - } - // clean the cube for future writing - Abc_ObjForEachFanin( pDriver, pFanin, k ) - { - pFanin = Abc_ObjFanin0Ntk(pFanin); - assert( Abc_ObjIsCi(pFanin) ); - pCubeIn[(int)pFanin->pCopy] = '-'; - } - Extra_ProgressBarUpdate( pProgress, i, NULL ); - } - Extra_ProgressBarStop( pProgress ); - fprintf( pFile, ".e\n" ); - - // clean the CI nodes - Abc_NtkForEachCi( pNtk, pNode, i ) - pNode->pCopy = NULL; - free( pCubeIn ); - free( pCubeOut ); - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteVerilog.c b/src/base/io/ioWriteVerilog.c deleted file mode 100644 index a4eeb78f..00000000 --- a/src/base/io/ioWriteVerilog.c +++ /dev/null @@ -1,636 +0,0 @@ -/**CFile**************************************************************** - - FileName [ioWriteVerilog.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedures to output a special subset of Verilog.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: ioWriteVerilog.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" -#include "main.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); -static void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); -static void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); -static void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ); -static void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ); -static void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ); -static int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ); -static char * Io_WriteVerilogGetName( char * pName ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Write verilog.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteVerilog( Abc_Ntk_t * pNtk, char * pFileName ) -{ - Abc_Ntk_t * pNetlist; - FILE * pFile; - int i; - // can only write nodes represented using local AIGs - if ( !Abc_NtkIsAigNetlist(pNtk) && !Abc_NtkIsMappedNetlist(pNtk) ) - { - printf( "Io_WriteVerilog(): Can produce Verilog for mapped or AIG netlists only.\n" ); - return; - } - // start the output stream - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - fprintf( stdout, "Io_WriteVerilog(): Cannot open the output file \"%s\".\n", pFileName ); - return; - } - - // write the equations for the network - fprintf( pFile, "// Benchmark \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); - fprintf( pFile, "\n" ); - - // write modules - if ( pNtk->pDesign ) - { - // write the network first - Io_WriteVerilogInt( pFile, pNtk ); - // write other things - Vec_PtrForEachEntry( pNtk->pDesign->vModules, pNetlist, i ) - { - assert( Abc_NtkIsNetlist(pNetlist) ); - if ( pNetlist == pNtk ) - continue; - fprintf( pFile, "\n" ); - Io_WriteVerilogInt( pFile, pNetlist ); - } - } - else - { - Io_WriteVerilogInt( pFile, pNtk ); - } - - fprintf( pFile, "\n" ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Writes verilog.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteVerilogInt( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - // write inputs and outputs -// fprintf( pFile, "module %s ( gclk,\n ", Abc_NtkName(pNtk) ); - fprintf( pFile, "module %s ( ", Abc_NtkName(pNtk) ); - // add the clock signal if it does not exist - if ( Abc_NtkLatchNum(pNtk) > 0 && Nm_ManFindIdByName(pNtk->pManName, "clock", ABC_OBJ_PI) == -1 ) - fprintf( pFile, "clock, " ); - // write other primary inputs - fprintf( pFile, "\n " ); - if ( Abc_NtkPiNum(pNtk) > 0 ) - { - Io_WriteVerilogPis( pFile, pNtk, 3 ); - fprintf( pFile, ",\n " ); - } - if ( Abc_NtkPoNum(pNtk) > 0 ) - Io_WriteVerilogPos( pFile, pNtk, 3 ); - fprintf( pFile, " );\n" ); - // write inputs, outputs, registers, and wires - if ( Abc_NtkPiNum(pNtk) > 0 ) - { -// fprintf( pFile, " input gclk," ); - fprintf( pFile, " input " ); - Io_WriteVerilogPis( pFile, pNtk, 10 ); - fprintf( pFile, ";\n" ); - } - if ( Abc_NtkPoNum(pNtk) > 0 ) - { - fprintf( pFile, " output" ); - Io_WriteVerilogPos( pFile, pNtk, 5 ); - fprintf( pFile, ";\n" ); - } - // if this is not a blackbox, write internal signals - if ( !Abc_NtkHasBlackbox(pNtk) ) - { - if ( Abc_NtkLatchNum(pNtk) > 0 ) - { - fprintf( pFile, " reg" ); - Io_WriteVerilogRegs( pFile, pNtk, 4 ); - fprintf( pFile, ";\n" ); - } - if ( Io_WriteVerilogWiresCount(pNtk) > 0 ) - { - fprintf( pFile, " wire" ); - Io_WriteVerilogWires( pFile, pNtk, 4 ); - fprintf( pFile, ";\n" ); - } - // write nodes - Io_WriteVerilogObjects( pFile, pNtk ); - // write registers - if ( Abc_NtkLatchNum(pNtk) > 0 ) - Io_WriteVerilogLatches( pFile, pNtk ); - } - // finalize the file - fprintf( pFile, "endmodule\n\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes the primary inputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteVerilogPis( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) -{ - Abc_Obj_t * pTerm, * pNet; - int LineLength; - int AddedLength; - int NameCounter; - int i; - - LineLength = Start; - NameCounter = 0; - Abc_NtkForEachPi( pNtk, pTerm, i ) - { - pNet = Abc_ObjFanout0(pTerm); - // get the line length after this name is written - AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, "\n " ); - // reset the line length - LineLength = 3; - NameCounter = 0; - } - fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPiNum(pNtk)-1)? "" : "," ); - LineLength += AddedLength; - NameCounter++; - } -} - -/**Function************************************************************* - - Synopsis [Writes the primary outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteVerilogPos( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) -{ - Abc_Obj_t * pTerm, * pNet, * pSkip; - int LineLength; - int AddedLength; - int NameCounter; - int i; - int nskip; - - pSkip = 0; - nskip = 0; - - LineLength = Start; - NameCounter = 0; - Abc_NtkForEachPo( pNtk, pTerm, i ) - { - pNet = Abc_ObjFanin0(pTerm); - - if ( Abc_ObjIsPi(Abc_ObjFanin0(pNet)) ) - { - // Skip this output since it is a feedthrough -- the same - // name will appear as an input and an output which other - // tools reading verilog do not like. - - nskip++; - pSkip = pNet; // save an example of skipped net - continue; - } - - // get the line length after this name is written - AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, "\n " ); - // reset the line length - LineLength = 3; - NameCounter = 0; - } - fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (i==Abc_NtkPoNum(pNtk)-1)? "" : "," ); - LineLength += AddedLength; - NameCounter++; - } - - if (nskip != 0) - { - assert (pSkip); - printf( "Io_WriteVerilogPos(): Omitted %d feedthrough nets from output list of module (e.g. %s).\n", nskip, Abc_ObjName(pSkip) ); - return; - } - -} - -/**Function************************************************************* - - Synopsis [Writes the wires.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteVerilogWires( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) -{ - Abc_Obj_t * pObj, * pNet, * pBox, * pTerm; - int LineLength; - int AddedLength; - int NameCounter; - int i, k, Counter, nNodes; - - // count the number of wires - nNodes = Io_WriteVerilogWiresCount( pNtk ); - - // write the wires - Counter = 0; - LineLength = Start; - NameCounter = 0; - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( i == 0 ) - continue; - pNet = Abc_ObjFanout0(pObj); - if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) - continue; - Counter++; - // get the line length after this name is written - AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, "\n " ); - // reset the line length - LineLength = 3; - NameCounter = 0; - } - fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); - LineLength += AddedLength; - NameCounter++; - } - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); - Counter++; - // get the line length after this name is written - AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, "\n " ); - // reset the line length - LineLength = 3; - NameCounter = 0; - } - fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); - LineLength += AddedLength; - NameCounter++; - } - Abc_NtkForEachBox( pNtk, pBox, i ) - { - if ( Abc_ObjIsLatch(pBox) ) - continue; - Abc_ObjForEachFanin( pBox, pTerm, k ) - { - pNet = Abc_ObjFanin0(pTerm); - Counter++; - // get the line length after this name is written - AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, "\n " ); - // reset the line length - LineLength = 3; - NameCounter = 0; - } - fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); - LineLength += AddedLength; - NameCounter++; - } - Abc_ObjForEachFanout( pBox, pTerm, k ) - { - pNet = Abc_ObjFanout0(pTerm); - if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) - continue; - Counter++; - // get the line length after this name is written - AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, "\n " ); - // reset the line length - LineLength = 3; - NameCounter = 0; - } - fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); - LineLength += AddedLength; - NameCounter++; - } - } - assert( Counter == nNodes ); -} - -/**Function************************************************************* - - Synopsis [Writes the regs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteVerilogRegs( FILE * pFile, Abc_Ntk_t * pNtk, int Start ) -{ - Abc_Obj_t * pLatch, * pNet; - int LineLength; - int AddedLength; - int NameCounter; - int i, Counter, nNodes; - - // count the number of latches - nNodes = Abc_NtkLatchNum(pNtk); - - // write the wires - Counter = 0; - LineLength = Start; - NameCounter = 0; - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - pNet = Abc_ObjFanout0(Abc_ObjFanout0(pLatch)); - Counter++; - // get the line length after this name is written - AddedLength = strlen(Io_WriteVerilogGetName(Abc_ObjName(pNet))) + 2; - if ( NameCounter && LineLength + AddedLength + 3 > IO_WRITE_LINE_LENGTH ) - { // write the line extender - fprintf( pFile, "\n " ); - // reset the line length - LineLength = 3; - NameCounter = 0; - } - fprintf( pFile, " %s%s", Io_WriteVerilogGetName(Abc_ObjName(pNet)), (Counter==nNodes)? "" : "," ); - LineLength += AddedLength; - NameCounter++; - } -} - -/**Function************************************************************* - - Synopsis [Writes the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteVerilogLatches( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pLatch; - int i; - if ( Abc_NtkLatchNum(pNtk) == 0 ) - return; - // write the latches -// fprintf( pFile, " always @(posedge %s) begin\n", Io_WriteVerilogGetName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0))) ); -// fprintf( pFile, " always begin\n" ); - fprintf( pFile, " always @ (posedge clock) begin\n" ); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - fprintf( pFile, " %s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); - fprintf( pFile, " <= %s;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin0(pLatch)))) ); - } - fprintf( pFile, " end\n" ); - // check if there are initial values - Abc_NtkForEachLatch( pNtk, pLatch, i ) - if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO || Abc_LatchInit(pLatch) == ABC_INIT_ONE ) - break; - if ( i == Abc_NtkLatchNum(pNtk) ) - return; - // write the initial values - fprintf( pFile, " initial begin\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_NtkPi(pNtk,0)))) ); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - if ( Abc_LatchInit(pLatch) == ABC_INIT_ZERO ) - fprintf( pFile, " %s <= 1\'b0;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); - else if ( Abc_LatchInit(pLatch) == ABC_INIT_ONE ) - fprintf( pFile, " %s <= 1\'b1;\n", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout0(pLatch)))) ); - } - fprintf( pFile, " end\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes the nodes and boxes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_WriteVerilogObjects( FILE * pFile, Abc_Ntk_t * pNtk ) -{ - Vec_Vec_t * vLevels; - Abc_Ntk_t * pNtkBox; - Abc_Obj_t * pObj, * pTerm, * pFanin; - Hop_Obj_t * pFunc; - int i, k, Counter, nDigits, Length; - - // write boxes - nDigits = Extra_Base10Log( Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); - Counter = 0; - Abc_NtkForEachBox( pNtk, pObj, i ) - { - if ( Abc_ObjIsLatch(pObj) ) - continue; - pNtkBox = pObj->pData; - fprintf( pFile, " %s box%0*d", pNtkBox->pName, nDigits, Counter++ ); - fprintf( pFile, "(" ); - Abc_NtkForEachPi( pNtkBox, pTerm, k ) - { - fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pTerm))) ); - fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(Abc_ObjFanin(pObj,k)))) ); - } - Abc_NtkForEachPo( pNtkBox, pTerm, k ) - { - fprintf( pFile, ".%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanin0(pTerm))) ); - fprintf( pFile, "(%s)%s", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(Abc_ObjFanout(pObj,k)))), k==Abc_NtkPoNum(pNtkBox)-1? "":", " ); - } - fprintf( pFile, ");\n" ); - } - // write nodes - if ( Abc_NtkHasMapping(pNtk) ) - { - Length = Mio_LibraryReadGateNameMax(pNtk->pManFunc); - nDigits = Extra_Base10Log( Abc_NtkNodeNum(pNtk) ); - Counter = 0; - Abc_NtkForEachNode( pNtk, pObj, k ) - { - Mio_Gate_t * pGate = pObj->pData; - Mio_Pin_t * pGatePin; - // write the node - fprintf( pFile, " %-*s g%0*d", Length, Mio_GateReadName(pGate), nDigits, Counter++ ); - fprintf( pFile, "(" ); - for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) - { - fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_PinReadName(pGatePin)) ); - fprintf( pFile, "(%s), ", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanin(pObj,i) )) ); - } - assert ( i == Abc_ObjFaninNum(pObj) ); - fprintf( pFile, ".%s", Io_WriteVerilogGetName(Mio_GateReadOutName(pGate)) ); - fprintf( pFile, "(%s)", Io_WriteVerilogGetName(Abc_ObjName( Abc_ObjFanout0(pObj) )) ); - fprintf( pFile, ");\n" ); - } - } - else - { - vLevels = Vec_VecAlloc( 10 ); - Abc_NtkForEachNode( pNtk, pObj, i ) - { - pFunc = pObj->pData; - fprintf( pFile, " assign %s = ", Io_WriteVerilogGetName(Abc_ObjName(Abc_ObjFanout0(pObj))) ); - // set the input names - Abc_ObjForEachFanin( pObj, pFanin, k ) - Hop_IthVar(pNtk->pManFunc, k)->pData = Extra_UtilStrsav(Io_WriteVerilogGetName(Abc_ObjName(pFanin))); - // write the formula - Hop_ObjPrintVerilog( pFile, pFunc, vLevels, 0 ); - fprintf( pFile, ";\n" ); - // clear the input names - Abc_ObjForEachFanin( pObj, pFanin, k ) - free( Hop_IthVar(pNtk->pManFunc, k)->pData ); - } - Vec_VecFree( vLevels ); - } -} - -/**Function************************************************************* - - Synopsis [Counts the number of wires.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Io_WriteVerilogWiresCount( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj, * pNet, * pBox; - int i, k, nWires; - nWires = Abc_NtkLatchNum(pNtk); - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( i == 0 ) - continue; - pNet = Abc_ObjFanout0(pObj); - if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) - continue; - nWires++; - } - Abc_NtkForEachBox( pNtk, pBox, i ) - { - if ( Abc_ObjIsLatch(pBox) ) - continue; - nWires += Abc_ObjFaninNum(pBox); - Abc_ObjForEachFanout( pBox, pObj, k ) - { - pNet = Abc_ObjFanout0(pObj); - if ( Abc_ObjFanoutNum(pNet) > 0 && Abc_ObjIsCo(Abc_ObjFanout0(pNet)) ) - continue; - nWires++; - } - } - return nWires; -} - -/**Function************************************************************* - - Synopsis [Prepares the name for writing the Verilog file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Io_WriteVerilogGetName( char * pName ) -{ - static char Buffer[500]; - int Length, i; - Length = strlen(pName); - // consider the case of a signal having name "0" or "1" - if ( !(Length == 1 && (pName[0] == '0' || pName[0] == '1')) ) - { - for ( i = 0; i < Length; i++ ) - if ( !((pName[i] >= 'a' && pName[i] <= 'z') || - (pName[i] >= 'A' && pName[i] <= 'Z') || - (pName[i] >= '0' && pName[i] <= '9') || pName[i] == '_') ) - break; - if ( i == Length ) - return pName; - } - // create Verilog style name - Buffer[0] = '\\'; - for ( i = 0; i < Length; i++ ) - Buffer[i+1] = pName[i]; - Buffer[Length+1] = ' '; - Buffer[Length+2] = 0; - return Buffer; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/io/ioWriteVerilog.zip b/src/base/io/ioWriteVerilog.zip deleted file mode 100644 index 19e68a89..00000000 Binary files a/src/base/io/ioWriteVerilog.zip and /dev/null differ diff --git a/src/base/io/io_.c b/src/base/io/io_.c deleted file mode 100644 index 62dd60e5..00000000 --- a/src/base/io/io_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [io_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Command processing package.] - - Synopsis [Procedure to read network from file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: io_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - diff --git a/src/base/io/module.make b/src/base/io/module.make deleted file mode 100644 index bb35a7fc..00000000 --- a/src/base/io/module.make +++ /dev/null @@ -1,25 +0,0 @@ -SRC += src/base/io/io.c \ - src/base/io/ioReadAiger.c \ - src/base/io/ioReadBaf.c \ - src/base/io/ioReadBench.c \ - src/base/io/ioReadBlif.c \ - src/base/io/ioReadBlifAig.c \ - src/base/io/ioReadBlifMv.c \ - src/base/io/ioReadDsd.c \ - src/base/io/ioReadEdif.c \ - src/base/io/ioReadEqn.c \ - src/base/io/ioReadPla.c \ - src/base/io/ioReadVerilog.c \ - src/base/io/ioUtil.c \ - src/base/io/ioWriteAiger.c \ - src/base/io/ioWriteBaf.c \ - src/base/io/ioWriteBench.c \ - src/base/io/ioWriteBlif.c \ - src/base/io/ioWriteBlifMv.c \ - src/base/io/ioWriteCnf.c \ - src/base/io/ioWriteDot.c \ - src/base/io/ioWriteEqn.c \ - src/base/io/ioWriteGml.c \ - src/base/io/ioWriteList.c \ - src/base/io/ioWritePla.c \ - src/base/io/ioWriteVerilog.c diff --git a/src/base/main/libSupport.c b/src/base/main/libSupport.c deleted file mode 100644 index 471ea09e..00000000 --- a/src/base/main/libSupport.c +++ /dev/null @@ -1,193 +0,0 @@ -/**CFile**************************************************************** - - FileName [libSupport.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The main package.] - - Synopsis [Support for external libaries.] - - Author [Mike Case] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: libSupport.c,v 1.1 2005/09/06 19:59:51 casem Exp $] - -***********************************************************************/ - -#include "mainInt.h" -#include -#include - -#ifndef WIN32 -# include -# include -# include -#endif - -#define MAX_LIBS 256 -static void* libHandles[MAX_LIBS+1]; // will be null terminated - -typedef void (*lib_init_end_func) (Abc_Frame_t * pAbc); - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// This will find all the ABC library extensions in the current directory and load them all. -//////////////////////////////////////////////////////////////////////////////////////////////////// -void open_libs() { - int curr_lib = 0; - -#ifdef WIN32 -// printf("Warning: open_libs WIN32 not implemented.\n"); -#else - DIR* dirp; - struct dirent* dp; - char *env, *init_p, *p; - int done; - - env = getenv ("ABC_LIB_PATH"); - if (env == NULL) { -// printf("Warning: ABC_LIB_PATH not defined. Looking into the current directory.\n"); - init_p = malloc (2*sizeof(char)); - init_p[0]='.'; init_p[1] = 0; - } else { - init_p = malloc ((strlen(env)+1)*sizeof(char)); - strcpy (init_p, env); - } - - // Extract directories and read libraries - done = 0; - p = init_p; - while (!done) { - char *endp = strchr (p,':'); - if (endp == NULL) done = 1; // last directory in the list - else *endp = 0; // end of string - - dirp = opendir(p); - if (dirp == NULL) { -// printf("Warning: directory in ABC_LIB_PATH does not exist (%s).\n", p); - continue; - } - - while ((dp = readdir(dirp)) != NULL) { - if ((strncmp("libabc_", dp->d_name, 7) == 0) && - (strcmp(".so", dp->d_name + strlen(dp->d_name) - 3) == 0)) { - - // make sure we don't overflow the handle array - if (curr_lib >= MAX_LIBS) { - printf("Warning: maximum number of ABC libraries (%d) exceeded. Not loading %s.\n", - MAX_LIBS, - dp->d_name); - } - - // attempt to load it - else { - char* szPrefixed = malloc((strlen(dp->d_name) + strlen(p) + 2) * - sizeof(char)); - sprintf(szPrefixed, "%s/", p); - strcat(szPrefixed, dp->d_name); - libHandles[curr_lib] = dlopen(szPrefixed, RTLD_NOW | RTLD_LOCAL); - - // did the load succeed? - if (libHandles[curr_lib] != 0) { - printf("Loaded ABC library: %s (Abc library extension #%d)\n", szPrefixed, curr_lib); - curr_lib++; - } else { - printf("Warning: failed to load ABC library %s:\n\t%s\n", szPrefixed, dlerror()); - } - - free(szPrefixed); - } - } - } - closedir(dirp); - p = endp+1; - } - - free(init_p); -#endif - - // null terminate the list of handles - libHandles[curr_lib] = 0; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// This will close all open ABC library extensions -//////////////////////////////////////////////////////////////////////////////////////////////////// -void close_libs() { -#ifdef WIN32 - printf("Warning: close_libs WIN32 not implemented.\n"); -#else - int i; - for (i = 0; libHandles[i] != 0; i++) { - if (dlclose(libHandles[i]) != 0) { - printf("Warning: failed to close library %d\n", i); - } - libHandles[i] = 0; - } -#endif -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// This will get a pointer to a function inside of an open library -//////////////////////////////////////////////////////////////////////////////////////////////////// -void* get_fnct_ptr(int lib_num, char* sym_name) { -#ifdef WIN32 - printf("Warning: get_fnct_ptr WIN32 not implemented.\n"); - return 0; -#else - return dlsym(libHandles[lib_num], sym_name); -#endif -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// This will call an initialization function in every open library. -//////////////////////////////////////////////////////////////////////////////////////////////////// -void call_inits(Abc_Frame_t* pAbc) { - int i; - lib_init_end_func init_func; - for (i = 0; libHandles[i] != 0; i++) { - init_func = (lib_init_end_func) get_fnct_ptr(i, "abc_init"); - if (init_func == 0) { - printf("Warning: Failed to initialize library %d.\n", i); - } else { - (*init_func)(pAbc); - } - } -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// This will call a shutdown function in every open library. -//////////////////////////////////////////////////////////////////////////////////////////////////// -void call_ends(Abc_Frame_t* pAbc) { - int i; - lib_init_end_func end_func; - for (i = 0; libHandles[i] != 0; i++) { - end_func = (lib_init_end_func) get_fnct_ptr(i, "abc_end"); - if (end_func == 0) { - printf("Warning: Failed to end library %d.\n", i); - } else { - (*end_func)(pAbc); - } - } -} - -void Libs_Init(Abc_Frame_t * pAbc) -{ - open_libs(); - call_inits(pAbc); -} - -void Libs_End(Abc_Frame_t * pAbc) -{ - call_ends(pAbc); - - // It's good practice to close our libraries at this point, but this can mess up any backtrace printed by Valgind. - // close_libs(); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/base/main/main.c b/src/base/main/main.c deleted file mode 100644 index 8f43c605..00000000 --- a/src/base/main/main.c +++ /dev/null @@ -1,317 +0,0 @@ -/**CFile**************************************************************** - - FileName [main.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The main package.] - - Synopsis [Here everything starts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: main.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mainInt.h" - -// this line should be included in the library project -//#define _LIB - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int TypeCheck( Abc_Frame_t * pAbc, char * s); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#ifndef _LIB - -/**Function************************************************************* - - Synopsis [The main() procedure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int main( int argc, char * argv[] ) -{ - Abc_Frame_t * pAbc; - char sCommandUsr[500], sCommandTmp[100], sReadCmd[20], sWriteCmd[20], c; - char * sCommand, * sOutFile, * sInFile; - int fStatus = 0; - bool fBatch, fInitSource, fInitRead, fFinalWrite; - - // added to detect memory leaks: -#ifdef _DEBUG - _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); -#endif - -// Npn_Experiment(); -// Npn_Generate(); - - // get global frame (singleton pattern) - // will be initialized on first call - pAbc = Abc_FrameGetGlobalFrame(); - - // default options - fBatch = 0; - fInitSource = 1; - fInitRead = 0; - fFinalWrite = 0; - sInFile = sOutFile = NULL; - sprintf( sReadCmd, "read" ); - sprintf( sWriteCmd, "write" ); - - Extra_UtilGetoptReset(); - while ((c = Extra_UtilGetopt(argc, argv, "c:hf:F:o:st:T:x")) != EOF) { - switch(c) { - case 'c': - strcpy( sCommandUsr, globalUtilOptarg ); - fBatch = 1; - break; - - case 'f': - sprintf(sCommandUsr, "source %s", globalUtilOptarg); - fBatch = 1; - break; - - case 'F': - sprintf(sCommandUsr, "source -x %s", globalUtilOptarg); - fBatch = 1; - break; - - case 'h': - goto usage; - break; - - case 'o': - sOutFile = globalUtilOptarg; - fFinalWrite = 1; - break; - - case 's': - fInitSource = 0; - break; - - case 't': - if ( TypeCheck( pAbc, globalUtilOptarg ) ) - { - if ( !strcmp(globalUtilOptarg, "none") == 0 ) - { - fInitRead = 1; - sprintf( sReadCmd, "read_%s", globalUtilOptarg ); - } - } - else { - goto usage; - } - fBatch = 1; - break; - - case 'T': - if ( TypeCheck( pAbc, globalUtilOptarg ) ) - { - if (!strcmp(globalUtilOptarg, "none") == 0) - { - fFinalWrite = 1; - sprintf( sWriteCmd, "write_%s", globalUtilOptarg); - } - } - else { - goto usage; - } - fBatch = 1; - break; - - case 'x': - fFinalWrite = 0; - fInitRead = 0; - fBatch = 1; - break; - - default: - goto usage; - } - } - - if ( fBatch ) - { - pAbc->fBatchMode = 1; - - if (argc - globalUtilOptind == 0) - { - sInFile = NULL; - } - else if (argc - globalUtilOptind == 1) - { - fInitRead = 1; - sInFile = argv[globalUtilOptind]; - } - else - { - Abc_UtilsPrintUsage( pAbc, argv[0] ); - } - - // source the resource file - if ( fInitSource ) - { - Abc_UtilsSource( pAbc ); - } - - fStatus = 0; - if ( fInitRead && sInFile ) - { - sprintf( sCommandTmp, "%s %s", sReadCmd, sInFile ); - fStatus = Cmd_CommandExecute( pAbc, sCommandTmp ); - } - - if ( fStatus == 0 ) - { - /* cmd line contains `source ' */ - fStatus = Cmd_CommandExecute( pAbc, sCommandUsr ); - if ( (fStatus == 0 || fStatus == -1) && fFinalWrite && sOutFile ) - { - sprintf( sCommandTmp, "%s %s", sWriteCmd, sOutFile ); - fStatus = Cmd_CommandExecute( pAbc, sCommandTmp ); - } - } - - } - else - { - // start interactive mode - // print the hello line - Abc_UtilsPrintHello( pAbc ); - - // source the resource file - if ( fInitSource ) - { - Abc_UtilsSource( pAbc ); - } - - // execute commands given by the user - while ( !feof(stdin) ) - { - // print command line prompt and - // get the command from the user - sCommand = Abc_UtilsGetUsersInput( pAbc ); - - // execute the user's command - fStatus = Cmd_CommandExecute( pAbc, sCommand ); - - // stop if the user quitted or an error occurred - if ( fStatus == -1 || fStatus == -2 ) - break; - } - } - - // if the memory should be freed, quit packages - if ( fStatus < 0 ) - { - Abc_Stop(); - } - return 0; - -usage: - Abc_UtilsPrintHello( pAbc ); - Abc_UtilsPrintUsage( pAbc, argv[0] ); - return 1; -} - -#endif - -/**Function************************************************************* - - Synopsis [Initialization procedure for the library project.] - - Description [Note that when Abc_Start() is run in a static library - project, it does not load the resource file by default. As a result, - ABC is not set up the same way, as when it is run on a command line. - For example, some error messages while parsing files will not be - produced, and intermediate networks will not be checked for consistancy. - One possibility is to load the resource file after Abc_Start() as follows: - Abc_UtilsSource( Abc_FrameGetGlobalFrame() );] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_Start() -{ - Abc_Frame_t * pAbc; - // added to detect memory leaks: -#ifdef _DEBUG - _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); -#endif - // start the glocal frame - pAbc = Abc_FrameGetGlobalFrame(); - // source the resource file -// Abc_UtilsSource( pAbc ); -} - -/**Function************************************************************* - - Synopsis [Deallocation procedure for the library project.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_Stop() -{ - Abc_Frame_t * pAbc; - pAbc = Abc_FrameGetGlobalFrame(); - // perform uninitializations - Abc_FrameEnd( pAbc ); - // stop the framework - Abc_FrameDeallocate( pAbc ); -} - -/**Function******************************************************************** - - Synopsis [Returns 1 if s is a file type recognized, else returns 0.] - - Description [Returns 1 if s is a file type recognized by ABC, else returns 0. - Recognized types are "blif", "bench", "pla", and "none".] - - SideEffects [] - -******************************************************************************/ -static int TypeCheck( Abc_Frame_t * pAbc, char * s ) -{ - if (strcmp(s, "blif") == 0) - return 1; - else if (strcmp(s, "bench") == 0) - return 1; - else if (strcmp(s, "pla") == 0) - return 1; - else if (strcmp(s, "none") == 0) - return 1; - else { - fprintf( pAbc->Err, "unknown type %s\n", s ); - return 0; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/main/main.h b/src/base/main/main.h deleted file mode 100644 index 4433a8b4..00000000 --- a/src/base/main/main.h +++ /dev/null @@ -1,122 +0,0 @@ -/**CFile**************************************************************** - - FileName [main.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The main package.] - - Synopsis [External declarations of the main package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: main.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __MAIN_H__ -#define __MAIN_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// TYPEDEFS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// the framework containing all data -typedef struct Abc_Frame_t_ Abc_Frame_t; - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -// this include should be the first one in the list -// it is used to catch memory leaks on Windows -#include "leaks.h" - -// data structure packages -#include "extra.h" -#include "vec.h" -#include "st.h" - -// core packages -#include "abc.h" -#include "cmd.h" -#include "io.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== main.c ===========================================================*/ -extern void Abc_Start(); -extern void Abc_Stop(); - -/*=== mainFrame.c ===========================================================*/ -extern Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p ); -extern FILE * Abc_FrameReadOut( Abc_Frame_t * p ); -extern FILE * Abc_FrameReadErr( Abc_Frame_t * p ); -extern bool Abc_FrameReadMode( Abc_Frame_t * p ); -extern bool Abc_FrameSetMode( Abc_Frame_t * p, bool fNameMode ); -extern void Abc_FrameRestart( Abc_Frame_t * p ); -extern bool Abc_FrameShowProgress( Abc_Frame_t * p ); - -extern void Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet ); -extern void Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p ); -extern void Abc_FrameReplaceCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNet ); -extern void Abc_FrameUnmapAllNetworks( Abc_Frame_t * p ); -extern void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p ); - -extern void Abc_FrameSetGlobalFrame( Abc_Frame_t * p ); -extern Abc_Frame_t * Abc_FrameGetGlobalFrame(); - -extern Vec_Ptr_t * Abc_FrameReadStore(); -extern int Abc_FrameReadStoreSize(); -extern void * Abc_FrameReadLibLut(); -extern void * Abc_FrameReadLibGen(); -extern void * Abc_FrameReadLibSuper(); -extern void * Abc_FrameReadLibVer(); -extern void * Abc_FrameReadManDd(); -extern void * Abc_FrameReadManDec(); -extern char * Abc_FrameReadFlag( char * pFlag ); -extern bool Abc_FrameIsFlagEnabled( char * pFlag ); - -extern void Abc_FrameSetNtkStore( Abc_Ntk_t * pNtk ); -extern void Abc_FrameSetNtkStoreSize( int nStored ); -extern void Abc_FrameSetLibLut( void * pLib ); -extern void Abc_FrameSetLibGen( void * pLib ); -extern void Abc_FrameSetLibSuper( void * pLib ); -extern void Abc_FrameSetLibVer( void * pLib ); -extern void Abc_FrameSetFlag( char * pFlag, char * pValue ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/base/main/mainFrame.c b/src/base/main/mainFrame.c deleted file mode 100644 index eae8b7a6..00000000 --- a/src/base/main/mainFrame.c +++ /dev/null @@ -1,503 +0,0 @@ -/**CFile**************************************************************** - - FileName [mainFrame.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The main package.] - - Synopsis [The global framework resides in this file.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mainFrame.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mainInt.h" -#include "abc.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Frame_t * s_GlobalFrame = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [APIs to access parameters in the flobal frame.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_FrameReadStore() { return s_GlobalFrame->vStore; } -int Abc_FrameReadStoreSize() { return Vec_PtrSize(s_GlobalFrame->vStore); } -void * Abc_FrameReadLibLut() { return s_GlobalFrame->pLibLut; } -void * Abc_FrameReadLibGen() { return s_GlobalFrame->pLibGen; } -void * Abc_FrameReadLibSuper() { return s_GlobalFrame->pLibSuper; } -void * Abc_FrameReadLibVer() { return s_GlobalFrame->pLibVer; } -void * Abc_FrameReadManDd() { if ( s_GlobalFrame->dd == NULL ) s_GlobalFrame->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); return s_GlobalFrame->dd; } -void * Abc_FrameReadManDec() { if ( s_GlobalFrame->pManDec == NULL ) s_GlobalFrame->pManDec = Dec_ManStart(); return s_GlobalFrame->pManDec; } -char * Abc_FrameReadFlag( char * pFlag ) { return Cmd_FlagReadByName( s_GlobalFrame, pFlag ); } - -void Abc_FrameSetLibLut( void * pLib ) { s_GlobalFrame->pLibLut = pLib; } -void Abc_FrameSetLibGen( void * pLib ) { s_GlobalFrame->pLibGen = pLib; } -void Abc_FrameSetLibSuper( void * pLib ) { s_GlobalFrame->pLibSuper = pLib; } -void Abc_FrameSetLibVer( void * pLib ) { s_GlobalFrame->pLibVer = pLib; } -void Abc_FrameSetFlag( char * pFlag, char * pValue ) { Cmd_FlagUpdateValue( s_GlobalFrame, pFlag, pValue ); } - -/**Function************************************************************* - - Synopsis [Returns 1 if the flag is enabled without value or with value 1.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_FrameIsFlagEnabled( char * pFlag ) -{ - char * pValue; - // if flag is not defined, it is not enabled - pValue = Abc_FrameReadFlag( pFlag ); - if ( pValue == NULL ) - return 0; - // if flag is defined but value is not empty (no parameter) or "1", it is not enabled - if ( strcmp(pValue, "") && strcmp(pValue, "1") ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Frame_t * Abc_FrameAllocate() -{ - Abc_Frame_t * p; - extern void define_cube_size( int n ); - extern void set_espresso_flags(); - // allocate and clean - p = ALLOC( Abc_Frame_t, 1 ); - memset( p, 0, sizeof(Abc_Frame_t) ); - // get version - p->sVersion = Abc_UtilsGetVersion( p ); - // set streams - p->Err = stderr; - p->Out = stdout; - p->Hst = NULL; - // set the starting step - p->nSteps = 1; - p->fBatchMode = 0; - // networks to be used by choice - p->vStore = Vec_PtrAlloc( 16 ); - // initialize decomposition manager - define_cube_size(20); - set_espresso_flags(); - // initialize the trace manager -// Abc_HManStart(); - return p; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FrameDeallocate( Abc_Frame_t * p ) -{ - extern void Rwt_ManGlobalStop(); - extern void undefine_cube_size(); -// extern void Ivy_TruthManStop(); -// Abc_HManStop(); - undefine_cube_size(); - Rwt_ManGlobalStop(); -// Ivy_TruthManStop(); - if ( p->pLibVer ) Abc_LibFree( p->pLibVer, NULL ); - if ( p->pManDec ) Dec_ManStop( p->pManDec ); - if ( p->dd ) Extra_StopManager( p->dd ); - if ( p->vStore ) Vec_PtrFree( p->vStore ); - Abc_FrameDeleteAllNetworks( p ); - free( p ); - s_GlobalFrame = NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FrameRestart( Abc_Frame_t * p ) -{ -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_FrameShowProgress( Abc_Frame_t * p ) -{ - return Abc_FrameIsFlagEnabled( "progressbar" ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_FrameReadNtk( Abc_Frame_t * p ) -{ - return p->pNtkCur; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -FILE * Abc_FrameReadOut( Abc_Frame_t * p ) -{ - return p->Out; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -FILE * Abc_FrameReadErr( Abc_Frame_t * p ) -{ - return p->Err; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_FrameReadMode( Abc_Frame_t * p ) -{ - int fShortNames; - char * pValue; - pValue = Cmd_FlagReadByName( p, "namemode" ); - if ( pValue == NULL ) - fShortNames = 0; - else - fShortNames = atoi(pValue); - return fShortNames; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_FrameSetMode( Abc_Frame_t * p, bool fNameMode ) -{ - char Buffer[2]; - bool fNameModeOld; - fNameModeOld = Abc_FrameReadMode( p ); - Buffer[0] = '0' + fNameMode; - Buffer[1] = 0; - Cmd_FlagUpdateValue( p, "namemode", (char *)Buffer ); - return fNameModeOld; -} - - -/**Function************************************************************* - - Synopsis [Sets the given network to be the current one.] - - Description [Takes the network and makes it the current network. - The previous current network is attached to the given network as - a backup copy. In the stack of backup networks contains too many - networks (defined by the paramater "savesteps"), the bottom - most network is deleted.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FrameSetCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNtkNew ) -{ - Abc_Ntk_t * pNtk, * pNtk2, * pNtk3; - int nNetsPresent; - int nNetsToSave; - char * pValue; - - // link it to the previous network - Abc_NtkSetBackup( pNtkNew, p->pNtkCur ); - // set the step of this network - Abc_NtkSetStep( pNtkNew, ++p->nSteps ); - // set this network to be the current network - p->pNtkCur = pNtkNew; - - // remove any extra network that may happen to be in the stack - pValue = Cmd_FlagReadByName( p, "savesteps" ); - // if the value of steps to save is not set, assume 1-level undo - if ( pValue == NULL ) - nNetsToSave = 1; - else - nNetsToSave = atoi(pValue); - - // count the network, remember the last one, and the one before the last one - nNetsPresent = 0; - pNtk2 = pNtk3 = NULL; - for ( pNtk = p->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk2) ) - { - nNetsPresent++; - pNtk3 = pNtk2; - pNtk2 = pNtk; - } - - // remove the earliest backup network if it is more steps away than we store - if ( nNetsPresent - 1 > nNetsToSave ) - { // delete the last network - Abc_NtkDelete( pNtk2 ); - // clean the pointer of the network before the last one - Abc_NtkSetBackup( pNtk3, NULL ); - } -} - -/**Function************************************************************* - - Synopsis [This procedure swaps the current and the backup network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FrameSwapCurrentAndBackup( Abc_Frame_t * p ) -{ - Abc_Ntk_t * pNtkCur, * pNtkBack, * pNtkBack2; - int iStepCur, iStepBack; - - pNtkCur = p->pNtkCur; - pNtkBack = Abc_NtkBackup( pNtkCur ); - iStepCur = Abc_NtkStep ( pNtkCur ); - - // if there is no backup nothing to reset - if ( pNtkBack == NULL ) - return; - - // remember the backup of the backup - pNtkBack2 = Abc_NtkBackup( pNtkBack ); - iStepBack = Abc_NtkStep ( pNtkBack ); - - // set pNtkCur to be the next after the backup's backup - Abc_NtkSetBackup( pNtkCur, pNtkBack2 ); - Abc_NtkSetStep ( pNtkCur, iStepBack ); - - // set pNtkCur to be the next after the backup - Abc_NtkSetBackup( pNtkBack, pNtkCur ); - Abc_NtkSetStep ( pNtkBack, iStepCur ); - - // set the current network - p->pNtkCur = pNtkBack; -} - - -/**Function************************************************************* - - Synopsis [Replaces the current network by the given one.] - - Description [This procedure does not modify the stack of saved - networks.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FrameReplaceCurrentNetwork( Abc_Frame_t * p, Abc_Ntk_t * pNtk ) -{ - if ( pNtk == NULL ) - return; - - // transfer the parameters to the new network - if ( p->pNtkCur && Abc_FrameIsFlagEnabled( "backup" ) ) - { - Abc_NtkSetBackup( pNtk, Abc_NtkBackup(p->pNtkCur) ); - Abc_NtkSetStep( pNtk, Abc_NtkStep(p->pNtkCur) ); - // delete the current network - Abc_NtkDelete( p->pNtkCur ); - } - else - { - Abc_NtkSetBackup( pNtk, NULL ); - Abc_NtkSetStep( pNtk, ++p->nSteps ); - // delete the current network if present but backup is disabled - if ( p->pNtkCur ) - Abc_NtkDelete( p->pNtkCur ); - } - // set the new current network - p->pNtkCur = pNtk; -} - -/**Function************************************************************* - - Synopsis [Removes library binding of all currently stored networks.] - - Description [This procedure is called when the library is freed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FrameUnmapAllNetworks( Abc_Frame_t * p ) -{ - Abc_Ntk_t * pNtk; - for ( pNtk = p->pNtkCur; pNtk; pNtk = Abc_NtkBackup(pNtk) ) - if ( Abc_NtkHasMapping(pNtk) ) - Abc_NtkMapToSop( pNtk ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FrameDeleteAllNetworks( Abc_Frame_t * p ) -{ - Abc_Ntk_t * pNtk, * pNtk2; - // delete all the currently saved networks - for ( pNtk = p->pNtkCur, - pNtk2 = pNtk? Abc_NtkBackup(pNtk): NULL; - pNtk; - pNtk = pNtk2, - pNtk2 = pNtk? Abc_NtkBackup(pNtk): NULL ) - Abc_NtkDelete( pNtk ); - // set the current network empty - p->pNtkCur = NULL; -// fprintf( p->Out, "All networks have been deleted.\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FrameSetGlobalFrame( Abc_Frame_t * p ) -{ - s_GlobalFrame = p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Frame_t * Abc_FrameGetGlobalFrame() -{ - if ( s_GlobalFrame == 0 ) - { - // start the framework - s_GlobalFrame = Abc_FrameAllocate(); - // perform initializations - Abc_FrameInit( s_GlobalFrame ); - } - return s_GlobalFrame; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/main/mainInit.c b/src/base/main/mainInit.c deleted file mode 100644 index 03953e5b..00000000 --- a/src/base/main/mainInit.c +++ /dev/null @@ -1,100 +0,0 @@ -/**CFile**************************************************************** - - FileName [mainInit.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The main package.] - - Synopsis [Initialization procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mainInit.c,v 1.3 2005/09/14 22:53:37 casem Exp $] - -***********************************************************************/ - -#include "mainInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern void Abc_Init( Abc_Frame_t * pAbc ); -extern void Abc_End ( Abc_Frame_t * pAbc ); -extern void Io_Init( Abc_Frame_t * pAbc ); -extern void Io_End ( Abc_Frame_t * pAbc ); -extern void Cmd_Init( Abc_Frame_t * pAbc ); -extern void Cmd_End ( Abc_Frame_t * pAbc ); -extern void Fpga_Init( Abc_Frame_t * pAbc ); -extern void Fpga_End ( Abc_Frame_t * pAbc ); -extern void Map_Init( Abc_Frame_t * pAbc ); -extern void Map_End ( Abc_Frame_t * pAbc ); -extern void Mio_Init( Abc_Frame_t * pAbc ); -extern void Mio_End ( Abc_Frame_t * pAbc ); -extern void Super_Init( Abc_Frame_t * pAbc ); -extern void Super_End ( Abc_Frame_t * pAbc ); -extern void Libs_Init(Abc_Frame_t * pAbc); -extern void Libs_End(Abc_Frame_t * pAbc); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts all the packages.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FrameInit( Abc_Frame_t * pAbc ) -{ - Cmd_Init( pAbc ); - Io_Init( pAbc ); - Abc_Init( pAbc ); - Fpga_Init( pAbc ); - Map_Init( pAbc ); - Mio_Init( pAbc ); - Super_Init( pAbc ); - Libs_Init( pAbc ); -} - - -/**Function************************************************************* - - Synopsis [Stops all the packages.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_FrameEnd( Abc_Frame_t * pAbc ) -{ - Abc_End( pAbc ); - Io_End( pAbc ); - Cmd_End( pAbc ); - Fpga_End( pAbc ); - Map_End( pAbc ); - Mio_End( pAbc ); - Super_End( pAbc ); - Libs_End( pAbc ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/main/mainInt.h b/src/base/main/mainInt.h deleted file mode 100644 index 09ad96f3..00000000 --- a/src/base/main/mainInt.h +++ /dev/null @@ -1,109 +0,0 @@ -/**CFile**************************************************************** - - FileName [mainInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The main package.] - - Synopsis [Internal declarations of the main package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mainInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __MAIN_INT_H__ -#define __MAIN_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "main.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// the current version -#define ABC_VERSION "UC Berkeley, ABC 1.01" - -// the maximum length of an input line -#define MAX_STR 32768 - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Abc_Frame_t_ -{ - // general info - char * sVersion; // the name of the current version - // commands, aliases, etc - st_table * tCommands; // the command table - st_table * tAliases; // the alias table - st_table * tFlags; // the flag table - Vec_Ptr_t * aHistory; // the command history - // the functionality - Abc_Ntk_t * pNtkCur; // the current network - int nSteps; // the counter of different network processed - int fAutoexac; // marks the autoexec mode - int fBatchMode; // are we invoked in batch mode? - // output streams - FILE * Out; - FILE * Err; - FILE * Hst; - // used for runtime measurement - int TimeCommand; // the runtime of the last command - int TimeTotal; // the total runtime of all commands - // temporary storage for structural choices - Vec_Ptr_t * vStore; // networks to be used by choice - // decomposition package - void * pManDec; // decomposition manager - DdManager * dd; // temporary BDD package - // libraries for mapping - void * pLibLut; // the current LUT library - void * pLibGen; // the current genlib - void * pLibSuper; // the current supergate library - void * pLibVer; // the current Verilog library -}; - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== mvMain.c ===========================================================*/ -extern int main( int argc, char * argv[] ); -/*=== mvInit.c ===================================================*/ -extern void Abc_FrameInit( Abc_Frame_t * pAbc ); -extern void Abc_FrameEnd( Abc_Frame_t * pAbc ); -/*=== mvFrame.c =====================================================*/ -extern Abc_Frame_t * Abc_FrameAllocate(); -extern void Abc_FrameDeallocate( Abc_Frame_t * p ); -/*=== mvUtils.c =====================================================*/ -extern char * Abc_UtilsGetVersion( Abc_Frame_t * pAbc ); -extern char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc ); -extern void Abc_UtilsPrintHello( Abc_Frame_t * pAbc ); -extern void Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName ); -extern void Abc_UtilsSource( Abc_Frame_t * pAbc ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/base/main/mainUtils.c b/src/base/main/mainUtils.c deleted file mode 100644 index 2cd4e337..00000000 --- a/src/base/main/mainUtils.c +++ /dev/null @@ -1,237 +0,0 @@ -/**CFile**************************************************************** - - FileName [mainUtils.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [The main package.] - - Synopsis [Miscellaneous utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: mainUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mainInt.h" - -#ifndef _WIN32 -#include "readline/readline.h" -#endif - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// -static char * DateReadFromDateString(char * datestr); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_UtilsGetVersion( Abc_Frame_t * pAbc ) -{ - static char Version[1000]; - sprintf(Version, "%s (compiled %s %s)", ABC_VERSION, __DATE__, __TIME__); - return Version; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc ) -{ - static char Buffer[1000], Prompt[1000]; - sprintf( Prompt, "abc %02d> ", pAbc->nSteps ); -#ifdef _WIN32 - fprintf( pAbc->Out, "%s", Prompt ); - fgets( Buffer, 999, stdin ); - return Buffer; -#else - static char* line = NULL; - if (line != NULL) free(line); - line = readline(Prompt); - if (line == NULL){ printf("***EOF***\n"); exit(0); } - add_history(line); - return line; -#endif -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_UtilsPrintHello( Abc_Frame_t * pAbc ) -{ - fprintf( pAbc->Out, "%s\n", pAbc->sVersion ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName ) -{ - fprintf( pAbc->Err, "\n" ); - fprintf( pAbc->Err, - "usage: %s [-c cmd] [-f script] [-h] [-o file] [-s] [-t type] [-T type] [-x] [file]\n", - ProgName); - fprintf( pAbc->Err, " -c cmd\texecute commands `cmd'\n"); - fprintf( pAbc->Err, " -F script\texecute commands from a script file and echo commands\n"); - fprintf( pAbc->Err, " -f script\texecute commands from a script file\n"); - fprintf( pAbc->Err, " -h\t\tprint the command usage\n"); - fprintf( pAbc->Err, " -o file\tspecify output filename to store the result\n"); - fprintf( pAbc->Err, " -s\t\tdo not read any initialization file\n"); - fprintf( pAbc->Err, " -t type\tspecify input type (blif_mv (default), blif_mvs, blif, or none)\n"); - fprintf( pAbc->Err, " -T type\tspecify output type (blif_mv (default), blif_mvs, blif, or none)\n"); - fprintf( pAbc->Err, " -x\t\tequivalent to '-t none -T none'\n"); - fprintf( pAbc->Err, "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_UtilsSource( Abc_Frame_t * pAbc ) -{ -#ifdef WIN32 - if ( Cmd_CommandExecute(pAbc, "source abc.rc") ) - { - if ( Cmd_CommandExecute(pAbc, "source ..\\abc.rc") == 0 ) - printf( "Loaded \"abc.rc\" from the parent directory.\n" ); - else if ( Cmd_CommandExecute(pAbc, "source ..\\..\\abc.rc") == 0 ) - printf( "Loaded \"abc.rc\" from the grandparent directory.\n" ); - } -#else - { - char * sPath1, * sPath2; - - // If .rc is present in both the home and current directories, then read - // it from the home directory. Otherwise, read it from wherever it's located. - sPath1 = Extra_UtilFileSearch(".rc", "~/", "r"); - sPath2 = Extra_UtilFileSearch(".rc", ".", "r"); - - if ( sPath1 && sPath2 ) { - /* ~/.rc == .rc : Source the file only once */ - (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc"); - } - else { - if (sPath1) { - (void) Cmd_CommandExecute(pAbc, "source -s ~/.rc"); - } - if (sPath2) { - (void) Cmd_CommandExecute(pAbc, "source -s .rc"); - } - } - if ( sPath1 ) FREE(sPath1); - if ( sPath2 ) FREE(sPath2); - - /* execute the abc script which can be open with the "open_path" */ - Cmd_CommandExecute( pAbc, "source -s abc.rc" ); - } -#endif //WIN32 - { - // reset command history - char * pName; - int i; - Vec_PtrForEachEntry( pAbc->aHistory, pName, i ) - free( pName ); - pAbc->aHistory->nSize = 0; - } -} - -/**Function******************************************************************** - - Synopsis [Returns the date in a brief format assuming its coming from - the program `date'.] - - Description [optional] - - SideEffects [] - -******************************************************************************/ -char * -DateReadFromDateString( - char * datestr) -{ - static char result[25]; - char day[10]; - char month[10]; - char zone[10]; - char *at; - int date; - int hour; - int minute; - int second; - int year; - - if (sscanf(datestr, "%s %s %2d %2d:%2d:%2d %s %4d", - day, month, &date, &hour, &minute, &second, zone, &year) == 8) { - if (hour >= 12) { - if (hour >= 13) hour -= 12; - at = "PM"; - } - else { - if (hour == 0) hour = 12; - at = "AM"; - } - (void) sprintf(result, "%d-%3s-%02d at %d:%02d %s", - date, month, year % 100, hour, minute, at); - return result; - } - else { - return datestr; - } -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/main/module.make b/src/base/main/module.make deleted file mode 100644 index 367f89f6..00000000 --- a/src/base/main/module.make +++ /dev/null @@ -1,5 +0,0 @@ -SRC += src/base/main/main.c \ - src/base/main/mainFrame.c \ - src/base/main/mainInit.c \ - src/base/main/libSupport.c \ - src/base/main/mainUtils.c diff --git a/src/base/seq/module.make b/src/base/seq/module.make deleted file mode 100644 index c7716180..00000000 --- a/src/base/seq/module.make +++ /dev/null @@ -1,14 +0,0 @@ -SRC += src/base/seq/seqAigCore.c \ - src/base/seq/seqAigIter.c \ - src/base/seq/seqCreate.c \ - src/base/seq/seqFpgaCore.c \ - src/base/seq/seqFpgaIter.c \ - src/base/seq/seqLatch.c \ - src/base/seq/seqMan.c \ - src/base/seq/seqMapCore.c \ - src/base/seq/seqMapIter.c \ - src/base/seq/seqMaxMeanCycle.c \ - src/base/seq/seqRetCore.c \ - src/base/seq/seqRetIter.c \ - src/base/seq/seqShare.c \ - src/base/seq/seqUtil.c diff --git a/src/base/seq/seq.h b/src/base/seq/seq.h deleted file mode 100644 index d3c9abda..00000000 --- a/src/base/seq/seq.h +++ /dev/null @@ -1,101 +0,0 @@ -/**CFile**************************************************************** - - FileName [seq.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seq.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __SEQ_H__ -#define __SEQ_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Abc_Seq_t_ Abc_Seq_t; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== seqAigCore.c ===========================================================*/ -extern void Seq_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk, int nMaxIters, int fInitial, int fVerbose ); -extern void Seq_NtkSeqRetimeForward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose ); -extern void Seq_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose ); -/*=== seqFpgaCore.c ===============================================================*/ -extern Abc_Ntk_t * Seq_NtkFpgaMapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose ); -/*=== seqMapCore.c ===============================================================*/ -extern Abc_Ntk_t * Seq_MapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose ); -/*=== seqRetCore.c ===========================================================*/ -extern Abc_Ntk_t * Seq_NtkRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fInitial, int fVerbose ); -/*=== seqLatch.c ===============================================================*/ -extern void Seq_NodeDupLats( Abc_Obj_t * pObjNew, Abc_Obj_t * pObj, int Edge ); -extern int Seq_NodeCompareLats( Abc_Obj_t * pObj1, int Edge1, Abc_Obj_t * pObj2, int Edge2 ); -/*=== seqMan.c ===============================================================*/ -extern Abc_Seq_t * Seq_Create( Abc_Ntk_t * pNtk ); -extern void Seq_Resize( Abc_Seq_t * p, int nMaxId ); -extern void Seq_Delete( Abc_Seq_t * p ); -/*=== seqMaxMeanCycle.c ======================================================*/ -extern float Seq_NtkHoward( Abc_Ntk_t * pNtk, int fVerbose ); -extern void Seq_NtkSkewForward( Abc_Ntk_t * pNtk, float period, int fMinimize ); -/*=== abcSeq.c ===============================================================*/ -extern Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk ); -extern Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk ); -extern bool Abc_NtkSeqCheck( Abc_Ntk_t * pNtk ); -/*=== seqShare.c =============================================================*/ -extern void Seq_NtkShareFanouts( Abc_Ntk_t * pNtk ); -extern void Seq_NtkShareLatches( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk ); -extern void Seq_NtkShareLatchesMapping( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapAnds, int fFpga ); -extern void Seq_NtkShareLatchesClean( Abc_Ntk_t * pNtk ); -/*=== seqUtil.c ==============================================================*/ -extern char * Seq_ObjFaninGetInitPrintable( Abc_Obj_t * pObj, int Edge ); -extern void Seq_NtkLatchSetValues( Abc_Ntk_t * pNtk, Abc_InitType_t Init ); -extern int Seq_NtkLatchNum( Abc_Ntk_t * pNtk ); -extern int Seq_NtkLatchNumMax( Abc_Ntk_t * pNtk ); -extern int Seq_NtkLatchNumShared( Abc_Ntk_t * pNtk ); -extern void Seq_NtkLatchGetInitNums( Abc_Ntk_t * pNtk, int * pInits ); -extern int Seq_NtkLatchGetEqualFaninNum( Abc_Ntk_t * pNtk ); -extern int Seq_NtkCountNodesAboveLimit( Abc_Ntk_t * pNtk, int Limit ); -extern int Seq_MapComputeAreaFlows( Abc_Ntk_t * pNtk, int fVerbose ); -extern Vec_Ptr_t * Seq_NtkReachNodes( Abc_Ntk_t * pNtk, int fFromPos ); -extern int Seq_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/seq/seqAigCore.c b/src/base/seq/seqAigCore.c deleted file mode 100644 index 42fa14a2..00000000 --- a/src/base/seq/seqAigCore.c +++ /dev/null @@ -1,977 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqRetCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [The core of retiming procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqRetCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/* - Retiming can be represented in three equivalent forms: - - as a set of integer lags for each node (array of chars by node ID) - - as a set of node numbers with lag for each, fwd and bwd (two arrays of Seq_RetStep_t_) - - as a set of latch moves over the nodes, fwd and bwd (two arrays of node pointers Abc_Obj_t *) -*/ - -static void Abc_ObjRetimeForward( Abc_Obj_t * pObj ); -static int Abc_ObjRetimeBackward( Abc_Obj_t * pObj, Abc_Ntk_t * pNtk, stmm_table * tTable, Vec_Int_t * vValues ); -static void Abc_ObjRetimeBackwardUpdateEdge( Abc_Obj_t * pObj, int Edge, stmm_table * tTable ); -static void Abc_NtkRetimeSetInitialValues( Abc_Ntk_t * pNtk, stmm_table * tTable, int * pModel ); - -static void Seq_NtkImplementRetimingForward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves ); -static int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int fVerbose ); -static void Abc_ObjRetimeForward( Abc_Obj_t * pObj ); -static int Abc_ObjRetimeBackward( Abc_Obj_t * pObj, Abc_Ntk_t * pNtk, stmm_table * tTable, Vec_Int_t * vValues ); -static void Abc_ObjRetimeBackwardUpdateEdge( Abc_Obj_t * pObj, int Edge, stmm_table * tTable ); -static void Abc_NtkRetimeSetInitialValues( Abc_Ntk_t * pNtk, stmm_table * tTable, int * pModel ); - -static Vec_Ptr_t * Abc_NtkUtilRetimingTry( Abc_Ntk_t * pNtk, bool fForward ); -static Vec_Ptr_t * Abc_NtkUtilRetimingGetMoves( Abc_Ntk_t * pNtk, Vec_Int_t * vSteps, bool fForward ); -static Vec_Int_t * Abc_NtkUtilRetimingSplit( Vec_Str_t * vLags, int fForward ); -static void Abc_ObjRetimeForwardTry( Abc_Obj_t * pObj, int nLatches ); -static void Abc_ObjRetimeBackwardTry( Abc_Obj_t * pObj, int nLatches ); - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs performs optimal delay retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk, int nMaxIters, int fInitial, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - int RetValue; - if ( !fInitial ) - Seq_NtkLatchSetValues( pNtk, ABC_INIT_DC ); - // get the retiming lags - p->nMaxIters = nMaxIters; - if ( !Seq_AigRetimeDelayLags( pNtk, fVerbose ) ) - return; - // implement this retiming - RetValue = Seq_NtkImplementRetiming( pNtk, p->vLags, fVerbose ); - if ( RetValue == 0 ) - printf( "Retiming completed but initial state computation has failed.\n" ); -} - -/**Function************************************************************* - - Synopsis [Performs most forward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkSeqRetimeForward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose ) -{ - Vec_Ptr_t * vMoves; - Abc_Obj_t * pNode; - int i; - if ( !fInitial ) - Seq_NtkLatchSetValues( pNtk, ABC_INIT_DC ); - // get the forward moves - vMoves = Abc_NtkUtilRetimingTry( pNtk, 1 ); - // undo the forward moves - Vec_PtrForEachEntryReverse( vMoves, pNode, i ) - Abc_ObjRetimeBackwardTry( pNode, 1 ); - // implement this forward retiming - Seq_NtkImplementRetimingForward( pNtk, vMoves ); - Vec_PtrFree( vMoves ); -} - -/**Function************************************************************* - - Synopsis [Performs most backward retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose ) -{ - Vec_Ptr_t * vMoves; - Abc_Obj_t * pNode; - int i, RetValue; - if ( !fInitial ) - Seq_NtkLatchSetValues( pNtk, ABC_INIT_DC ); - // get the backward moves - vMoves = Abc_NtkUtilRetimingTry( pNtk, 0 ); - // undo the backward moves - Vec_PtrForEachEntryReverse( vMoves, pNode, i ) - Abc_ObjRetimeForwardTry( pNode, 1 ); - // implement this backward retiming - RetValue = Seq_NtkImplementRetimingBackward( pNtk, vMoves, fVerbose ); - Vec_PtrFree( vMoves ); - if ( RetValue == 0 ) - printf( "Retiming completed but initial state computation has failed.\n" ); -} - - - - -/**Function************************************************************* - - Synopsis [Implements the retiming on the sequential AIG.] - - Description [Split the retiming into forward and backward.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkImplementRetiming( Abc_Ntk_t * pNtk, Vec_Str_t * vLags, int fVerbose ) -{ - Vec_Int_t * vSteps; - Vec_Ptr_t * vMoves; - int RetValue; - - // forward retiming - vSteps = Abc_NtkUtilRetimingSplit( vLags, 1 ); - // translate each set of steps into moves - if ( fVerbose ) - printf( "The number of forward steps = %6d.\n", Vec_IntSize(vSteps) ); - vMoves = Abc_NtkUtilRetimingGetMoves( pNtk, vSteps, 1 ); - if ( fVerbose ) - printf( "The number of forward moves = %6d.\n", Vec_PtrSize(vMoves) ); - // implement this retiming - Seq_NtkImplementRetimingForward( pNtk, vMoves ); - Vec_IntFree( vSteps ); - Vec_PtrFree( vMoves ); - - // backward retiming - vSteps = Abc_NtkUtilRetimingSplit( vLags, 0 ); - // translate each set of steps into moves - if ( fVerbose ) - printf( "The number of backward steps = %6d.\n", Vec_IntSize(vSteps) ); - vMoves = Abc_NtkUtilRetimingGetMoves( pNtk, vSteps, 0 ); - if ( fVerbose ) - printf( "The number of backward moves = %6d.\n", Vec_PtrSize(vMoves) ); - // implement this retiming - RetValue = Seq_NtkImplementRetimingBackward( pNtk, vMoves, fVerbose ); - Vec_IntFree( vSteps ); - Vec_PtrFree( vMoves ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Implements the given retiming on the sequential AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkImplementRetimingForward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves ) -{ - Abc_Obj_t * pNode; - int i; - Vec_PtrForEachEntry( vMoves, pNode, i ) - Abc_ObjRetimeForward( pNode ); -} - -/**Function************************************************************* - - Synopsis [Retimes node forward by one latch.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjRetimeForward( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout; - int Init0, Init1, Init, i; - assert( Abc_ObjFaninNum(pObj) == 2 ); - assert( Seq_ObjFaninL0(pObj) >= 1 ); - assert( Seq_ObjFaninL1(pObj) >= 1 ); - // remove the init values from the fanins - Init0 = Seq_NodeDeleteFirst( pObj, 0 ); - Init1 = Seq_NodeDeleteFirst( pObj, 1 ); - assert( Init0 != ABC_INIT_NONE ); - assert( Init1 != ABC_INIT_NONE ); - // take into account the complements in the node - if ( Abc_ObjFaninC0(pObj) ) - { - if ( Init0 == ABC_INIT_ZERO ) - Init0 = ABC_INIT_ONE; - else if ( Init0 == ABC_INIT_ONE ) - Init0 = ABC_INIT_ZERO; - } - if ( Abc_ObjFaninC1(pObj) ) - { - if ( Init1 == ABC_INIT_ZERO ) - Init1 = ABC_INIT_ONE; - else if ( Init1 == ABC_INIT_ONE ) - Init1 = ABC_INIT_ZERO; - } - // compute the value at the output of the node - if ( Init0 == ABC_INIT_ZERO || Init1 == ABC_INIT_ZERO ) - Init = ABC_INIT_ZERO; - else if ( Init0 == ABC_INIT_ONE && Init1 == ABC_INIT_ONE ) - Init = ABC_INIT_ONE; - else - Init = ABC_INIT_DC; - - // make sure the label is clean - Abc_ObjForEachFanout( pObj, pFanout, i ) - assert( pFanout->fMarkC == 0 ); - // add the init values to the fanouts - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - if ( pFanout->fMarkC ) - continue; - pFanout->fMarkC = 1; - if ( Abc_ObjFaninId0(pFanout) != Abc_ObjFaninId1(pFanout) ) - Seq_NodeInsertLast( pFanout, Abc_ObjFanoutEdgeNum(pObj, pFanout), Init ); - else - { - assert( Abc_ObjFanin0(pFanout) == pObj ); - Seq_NodeInsertLast( pFanout, 0, Init ); - Seq_NodeInsertLast( pFanout, 1, Init ); - } - } - // clean the label - Abc_ObjForEachFanout( pObj, pFanout, i ) - pFanout->fMarkC = 0; -} - - -/**Function************************************************************* - - Synopsis [Implements the given retiming on the sequential AIG.] - - Description [Returns 0 of initial state computation fails.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int fVerbose ) -{ - Seq_RetEdge_t RetEdge; - stmm_table * tTable; - stmm_generator * gen; - Vec_Int_t * vValues; - Abc_Ntk_t * pNtkProb, * pNtkMiter, * pNtkCnf; - Abc_Obj_t * pNode, * pNodeNew; - int * pModel, RetValue, i, clk; - - // return if the retiming is trivial - if ( Vec_PtrSize(vMoves) == 0 ) - return 1; - - // create the network for the initial state computation - // start the table and the array of PO values - pNtkProb = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); - tTable = stmm_init_table( stmm_numcmp, stmm_numhash ); - vValues = Vec_IntAlloc( 100 ); - - // perform the backward moves and build the network for initial state computation - RetValue = 0; - Vec_PtrForEachEntry( vMoves, pNode, i ) - RetValue |= Abc_ObjRetimeBackward( pNode, pNtkProb, tTable, vValues ); - - // add the PIs corresponding to the white spots - stmm_foreach_item( tTable, gen, (char **)&RetEdge, (char **)&pNodeNew ) - Abc_ObjAddFanin( pNodeNew, Abc_NtkCreatePi(pNtkProb) ); - - // add the PI/PO names - Abc_NtkAddDummyPiNames( pNtkProb ); - Abc_NtkAddDummyPoNames( pNtkProb ); - Abc_NtkAddDummyAssertNames( pNtkProb ); - - // make sure everything is okay with the network structure - if ( !Abc_NtkDoCheck( pNtkProb ) ) - { - printf( "Seq_NtkImplementRetimingBackward: The internal network check has failed.\n" ); - Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL ); - Abc_NtkDelete( pNtkProb ); - stmm_free_table( tTable ); - Vec_IntFree( vValues ); - return 0; - } - - // check if conflict is found - if ( RetValue ) - { - printf( "Seq_NtkImplementRetimingBackward: A top level conflict is detected. DC latch values are used.\n" ); - Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL ); - Abc_NtkDelete( pNtkProb ); - stmm_free_table( tTable ); - Vec_IntFree( vValues ); - return 0; - } - - // get the miter cone - pNtkMiter = Abc_NtkCreateTarget( pNtkProb, pNtkProb->vCos, vValues ); - Abc_NtkDelete( pNtkProb ); - Vec_IntFree( vValues ); - - if ( fVerbose ) - printf( "The number of ANDs in the AIG = %5d.\n", Abc_NtkNodeNum(pNtkMiter) ); - - // transform the miter into a logic network for efficient CNF construction -// pNtkCnf = Abc_Ntk_Renode( pNtkMiter, 0, 100, 1, 0, 0 ); -// Abc_NtkDelete( pNtkMiter ); - pNtkCnf = pNtkMiter; - - // solve the miter -clk = clock(); -// RetValue = Abc_NtkMiterSat_OldAndRusty( pNtkCnf, 30, 0 ); - RetValue = Abc_NtkMiterSat( pNtkCnf, (sint64)500000, (sint64)50000000, 0, 0, NULL, NULL ); -if ( fVerbose ) -if ( clock() - clk > 100 ) -{ -PRT( "SAT solving time", clock() - clk ); -} - pModel = pNtkCnf->pModel; pNtkCnf->pModel = NULL; - Abc_NtkDelete( pNtkCnf ); - - // analyze the result - if ( RetValue == -1 || RetValue == 1 ) - { - Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL ); - if ( RetValue == 1 ) - printf( "Seq_NtkImplementRetimingBackward: The problem is unsatisfiable. DC latch values are used.\n" ); - else - printf( "Seq_NtkImplementRetimingBackward: The SAT problem timed out. DC latch values are used.\n" ); - stmm_free_table( tTable ); - return 0; - } - - // set the values of the latches - Abc_NtkRetimeSetInitialValues( pNtk, tTable, pModel ); - stmm_free_table( tTable ); - free( pModel ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Retimes node backward by one latch.] - - Description [Constructs the problem for initial state computation. - Returns 1 if the conflict is found.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ObjRetimeBackward( Abc_Obj_t * pObj, Abc_Ntk_t * pNtkNew, stmm_table * tTable, Vec_Int_t * vValues ) -{ - Abc_Obj_t * pFanout; - Abc_InitType_t Init, Value; - Seq_RetEdge_t RetEdge; - Abc_Obj_t * pNodeNew, * pFanoutNew, * pBuffer; - int i, Edge, fMet0, fMet1, fMetN; - - // make sure the node can be retimed - assert( Seq_ObjFanoutLMin(pObj) > 0 ); - // get the fanout values - fMet0 = fMet1 = fMetN = 0; - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - if ( Abc_ObjFaninId0(pFanout) == pObj->Id ) - { - Init = Seq_NodeGetInitLast( pFanout, 0 ); - if ( Init == ABC_INIT_ZERO ) - fMet0 = 1; - else if ( Init == ABC_INIT_ONE ) - fMet1 = 1; - else if ( Init == ABC_INIT_NONE ) - fMetN = 1; - } - if ( Abc_ObjFaninId1(pFanout) == pObj->Id ) - { - Init = Seq_NodeGetInitLast( pFanout, 1 ); - if ( Init == ABC_INIT_ZERO ) - fMet0 = 1; - else if ( Init == ABC_INIT_ONE ) - fMet1 = 1; - else if ( Init == ABC_INIT_NONE ) - fMetN = 1; - } - } - - // consider the case when all fanout latches have don't-care values - // the new values on the fanin edges will be don't-cares - if ( !fMet0 && !fMet1 && !fMetN ) - { - // make sure the label is clean - Abc_ObjForEachFanout( pObj, pFanout, i ) - assert( pFanout->fMarkC == 0 ); - // update the fanout edges - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - if ( pFanout->fMarkC ) - continue; - pFanout->fMarkC = 1; - if ( Abc_ObjFaninId0(pFanout) == pObj->Id ) - Seq_NodeDeleteLast( pFanout, 0 ); - if ( Abc_ObjFaninId1(pFanout) == pObj->Id ) - Seq_NodeDeleteLast( pFanout, 1 ); - } - // clean the label - Abc_ObjForEachFanout( pObj, pFanout, i ) - pFanout->fMarkC = 0; - // update the fanin edges - Abc_ObjRetimeBackwardUpdateEdge( pObj, 0, tTable ); - Abc_ObjRetimeBackwardUpdateEdge( pObj, 1, tTable ); - Seq_NodeInsertFirst( pObj, 0, ABC_INIT_DC ); - Seq_NodeInsertFirst( pObj, 1, ABC_INIT_DC ); - return 0; - } - // the initial values on the fanout edges contain 0, 1, or unknown - // the new values on the fanin edges will be unknown - - // add new AND-gate to the network - pNodeNew = Abc_NtkCreateNode( pNtkNew ); - pNodeNew->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); - - // add PO fanouts if any - if ( fMet0 ) - { - Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNodeNew ); - Vec_IntPush( vValues, 0 ); - } - if ( fMet1 ) - { - Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNodeNew ); - Vec_IntPush( vValues, 1 ); - } - - // make sure the label is clean - Abc_ObjForEachFanout( pObj, pFanout, i ) - assert( pFanout->fMarkC == 0 ); - // perform the changes - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - if ( pFanout->fMarkC ) - continue; - pFanout->fMarkC = 1; - if ( Abc_ObjFaninId0(pFanout) == pObj->Id ) - { - Edge = 0; - Value = Seq_NodeDeleteLast( pFanout, Edge ); - if ( Value == ABC_INIT_NONE ) - { - // value is unknown, remove it from the table - RetEdge.iNode = pFanout->Id; - RetEdge.iEdge = Edge; - RetEdge.iLatch = Seq_ObjFaninL( pFanout, Edge ); // after edge is removed - if ( !stmm_delete( tTable, (char **)&RetEdge, (char **)&pFanoutNew ) ) - assert( 0 ); - // create the fanout of the AND gate - Abc_ObjAddFanin( pFanoutNew, pNodeNew ); - } - } - if ( Abc_ObjFaninId1(pFanout) == pObj->Id ) - { - Edge = 1; - Value = Seq_NodeDeleteLast( pFanout, Edge ); - if ( Value == ABC_INIT_NONE ) - { - // value is unknown, remove it from the table - RetEdge.iNode = pFanout->Id; - RetEdge.iEdge = Edge; - RetEdge.iLatch = Seq_ObjFaninL( pFanout, Edge ); // after edge is removed - if ( !stmm_delete( tTable, (char **)&RetEdge, (char **)&pFanoutNew ) ) - assert( 0 ); - // create the fanout of the AND gate - Abc_ObjAddFanin( pFanoutNew, pNodeNew ); - } - } - } - // clean the label - Abc_ObjForEachFanout( pObj, pFanout, i ) - pFanout->fMarkC = 0; - - // update the fanin edges - Abc_ObjRetimeBackwardUpdateEdge( pObj, 0, tTable ); - Abc_ObjRetimeBackwardUpdateEdge( pObj, 1, tTable ); - Seq_NodeInsertFirst( pObj, 0, ABC_INIT_NONE ); - Seq_NodeInsertFirst( pObj, 1, ABC_INIT_NONE ); - - // add the buffer - pBuffer = Abc_NtkCreateNode( pNtkNew ); - pBuffer->pData = Abc_SopCreateBuf( pNtkNew->pManFunc ); - Abc_ObjAddFanin( pNodeNew, pBuffer ); - // point to it from the table - RetEdge.iNode = pObj->Id; - RetEdge.iEdge = 0; - RetEdge.iLatch = 0; - if ( stmm_insert( tTable, (char *)Seq_RetEdge2Int(RetEdge), (char *)pBuffer ) ) - assert( 0 ); - - // add the buffer - pBuffer = Abc_NtkCreateNode( pNtkNew ); - pBuffer->pData = Abc_SopCreateBuf( pNtkNew->pManFunc ); - Abc_ObjAddFanin( pNodeNew, pBuffer ); - // point to it from the table - RetEdge.iNode = pObj->Id; - RetEdge.iEdge = 1; - RetEdge.iLatch = 0; - if ( stmm_insert( tTable, (char *)Seq_RetEdge2Int(RetEdge), (char *)pBuffer ) ) - assert( 0 ); - - // report conflict is found - return fMet0 && fMet1; -} - -/**Function************************************************************* - - Synopsis [Generates the printable edge label with the initial state.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjRetimeBackwardUpdateEdge( Abc_Obj_t * pObj, int Edge, stmm_table * tTable ) -{ - Abc_Obj_t * pFanoutNew; - Seq_RetEdge_t RetEdge; - Abc_InitType_t Init; - int nLatches, i; - - // get the number of latches on the edge - nLatches = Seq_ObjFaninL( pObj, Edge ); - for ( i = nLatches - 1; i >= 0; i-- ) - { - // get the value of this latch - Init = Seq_NodeGetInitOne( pObj, Edge, i ); - if ( Init != ABC_INIT_NONE ) - continue; - // get the retiming edge - RetEdge.iNode = pObj->Id; - RetEdge.iEdge = Edge; - RetEdge.iLatch = i; - // remove entry from table and add it with a different key - if ( !stmm_delete( tTable, (char **)&RetEdge, (char **)&pFanoutNew ) ) - assert( 0 ); - RetEdge.iLatch++; - if ( stmm_insert( tTable, (char *)Seq_RetEdge2Int(RetEdge), (char *)pFanoutNew ) ) - assert( 0 ); - } -} - -/**Function************************************************************* - - Synopsis [Sets the initial values.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeSetInitialValues( Abc_Ntk_t * pNtk, stmm_table * tTable, int * pModel ) -{ - Abc_Obj_t * pNode; - stmm_generator * gen; - Seq_RetEdge_t RetEdge; - Abc_InitType_t Init; - int i; - - i = 0; - stmm_foreach_item( tTable, gen, (char **)&RetEdge, NULL ) - { - pNode = Abc_NtkObj( pNtk, RetEdge.iNode ); - Init = pModel? (pModel[i]? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC; - Seq_NodeSetInitOne( pNode, RetEdge.iEdge, RetEdge.iLatch, Init ); - i++; - } -} - - - -/**Function************************************************************* - - Synopsis [Performs forward retiming of the sequential AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkUtilRetimingTry( Abc_Ntk_t * pNtk, bool fForward ) -{ - Vec_Ptr_t * vNodes, * vMoves; - Abc_Obj_t * pNode, * pFanout, * pFanin; - int i, k, nLatches; - assert( Abc_NtkIsSeq( pNtk ) ); - // assume that all nodes can be retimed - vNodes = Vec_PtrAlloc( 100 ); - Abc_AigForEachAnd( pNtk, pNode, i ) - { - Vec_PtrPush( vNodes, pNode ); - pNode->fMarkA = 1; - } - // process the nodes - vMoves = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { -// printf( "(%d,%d) ", Seq_ObjFaninL0(pNode), Seq_ObjFaninL0(pNode) ); - // unmark the node as processed - pNode->fMarkA = 0; - // get the number of latches to retime - if ( fForward ) - nLatches = Seq_ObjFaninLMin(pNode); - else - nLatches = Seq_ObjFanoutLMin(pNode); - if ( nLatches == 0 ) - continue; - assert( nLatches > 0 ); - // retime the latches forward - if ( fForward ) - Abc_ObjRetimeForwardTry( pNode, nLatches ); - else - Abc_ObjRetimeBackwardTry( pNode, nLatches ); - // write the moves - for ( k = 0; k < nLatches; k++ ) - Vec_PtrPush( vMoves, pNode ); - // schedule fanouts for updating - if ( fForward ) - { - Abc_ObjForEachFanout( pNode, pFanout, k ) - { - if ( Abc_ObjFaninNum(pFanout) != 2 || pFanout->fMarkA ) - continue; - pFanout->fMarkA = 1; - Vec_PtrPush( vNodes, pFanout ); - } - } - else - { - Abc_ObjForEachFanin( pNode, pFanin, k ) - { - if ( Abc_ObjFaninNum(pFanin) != 2 || pFanin->fMarkA ) - continue; - pFanin->fMarkA = 1; - Vec_PtrPush( vNodes, pFanin ); - } - } - } - Vec_PtrFree( vNodes ); - // make sure the marks are clean the the retiming is final - Abc_AigForEachAnd( pNtk, pNode, i ) - { - assert( pNode->fMarkA == 0 ); - if ( fForward ) - assert( Seq_ObjFaninLMin(pNode) == 0 ); - else - assert( Seq_ObjFanoutLMin(pNode) == 0 ); - } - return vMoves; -} - -/**Function************************************************************* - - Synopsis [Translates retiming steps into retiming moves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkUtilRetimingGetMoves( Abc_Ntk_t * pNtk, Vec_Int_t * vSteps, bool fForward ) -{ - Seq_RetStep_t RetStep; - Vec_Ptr_t * vMoves; - Abc_Obj_t * pNode; - int i, k, iNode, nLatches, Number; - int fChange; - assert( Abc_NtkIsSeq( pNtk ) ); - -/* - // try implementing all the moves at once - Vec_IntForEachEntry( vSteps, Number, i ) - { - // get the retiming step - RetStep = Seq_Int2RetStep( Number ); - // get the node to be retimed - pNode = Abc_NtkObj( pNtk, RetStep.iNode ); - assert( RetStep.nLatches > 0 ); - nLatches = RetStep.nLatches; - - if ( fForward ) - Abc_ObjRetimeForwardTry( pNode, nLatches ); - else - Abc_ObjRetimeBackwardTry( pNode, nLatches ); - } - // now look if any node has wrong number of latches - Abc_AigForEachAnd( pNtk, pNode, i ) - { - if ( Seq_ObjFaninL0(pNode) < 0 ) - printf( "Wrong 0node %d.\n", pNode->Id ); - if ( Seq_ObjFaninL1(pNode) < 0 ) - printf( "Wrong 1node %d.\n", pNode->Id ); - } - // try implementing all the moves at once - Vec_IntForEachEntry( vSteps, Number, i ) - { - // get the retiming step - RetStep = Seq_Int2RetStep( Number ); - // get the node to be retimed - pNode = Abc_NtkObj( pNtk, RetStep.iNode ); - assert( RetStep.nLatches > 0 ); - nLatches = RetStep.nLatches; - - if ( !fForward ) - Abc_ObjRetimeForwardTry( pNode, nLatches ); - else - Abc_ObjRetimeBackwardTry( pNode, nLatches ); - } -*/ - - // process the nodes - vMoves = Vec_PtrAlloc( 100 ); - while ( Vec_IntSize(vSteps) > 0 ) - { - iNode = 0; - fChange = 0; - Vec_IntForEachEntry( vSteps, Number, i ) - { - // get the retiming step - RetStep = Seq_Int2RetStep( Number ); - // get the node to be retimed - pNode = Abc_NtkObj( pNtk, RetStep.iNode ); - assert( RetStep.nLatches > 0 ); - // get the number of latches that can be retimed - if ( fForward ) - nLatches = Seq_ObjFaninLMin(pNode); - else - nLatches = Seq_ObjFanoutLMin(pNode); - if ( nLatches == 0 ) - { - Vec_IntWriteEntry( vSteps, iNode++, Seq_RetStep2Int(RetStep) ); - continue; - } - assert( nLatches > 0 ); - fChange = 1; - // get the number of latches to be retimed over this node - nLatches = ABC_MIN( nLatches, (int)RetStep.nLatches ); - // retime the latches forward - if ( fForward ) - Abc_ObjRetimeForwardTry( pNode, nLatches ); - else - Abc_ObjRetimeBackwardTry( pNode, nLatches ); - // write the moves - for ( k = 0; k < nLatches; k++ ) - Vec_PtrPush( vMoves, pNode ); - // subtract the retiming performed - RetStep.nLatches -= nLatches; - // store the node if it is not retimed completely - if ( RetStep.nLatches > 0 ) - Vec_IntWriteEntry( vSteps, iNode++, Seq_RetStep2Int(RetStep) ); - } - // reduce the array - Vec_IntShrink( vSteps, iNode ); - if ( !fChange ) - { - printf( "Warning: %d strange steps (a minor bug to be fixed later).\n", Vec_IntSize(vSteps) ); -/* - Vec_IntForEachEntry( vSteps, Number, i ) - { - RetStep = Seq_Int2RetStep( Number ); - printf( "%d(%d) ", RetStep.iNode, RetStep.nLatches ); - } - printf( "\n" ); -*/ - break; - } - } - // undo the tentative retiming - if ( fForward ) - { - Vec_PtrForEachEntryReverse( vMoves, pNode, i ) - Abc_ObjRetimeBackwardTry( pNode, 1 ); - } - else - { - Vec_PtrForEachEntryReverse( vMoves, pNode, i ) - Abc_ObjRetimeForwardTry( pNode, 1 ); - } - return vMoves; -} - - -/**Function************************************************************* - - Synopsis [Splits retiming into forward and backward.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkUtilRetimingSplit( Vec_Str_t * vLags, int fForward ) -{ - Vec_Int_t * vNodes; - Seq_RetStep_t RetStep; - int Value, i; - vNodes = Vec_IntAlloc( 100 ); - Vec_StrForEachEntry( vLags, Value, i ) - { - if ( Value < 0 && fForward ) - { - RetStep.iNode = i; - RetStep.nLatches = -Value; - Vec_IntPush( vNodes, Seq_RetStep2Int(RetStep) ); - } - else if ( Value > 0 && !fForward ) - { - RetStep.iNode = i; - RetStep.nLatches = Value; - Vec_IntPush( vNodes, Seq_RetStep2Int(RetStep) ); - } - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Retime node forward without initial states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjRetimeForwardTry( Abc_Obj_t * pObj, int nLatches ) -{ - Abc_Obj_t * pFanout; - int i; - // make sure it is an AND gate - assert( Abc_ObjFaninNum(pObj) == 2 ); - // make sure it has enough latches -// assert( Seq_ObjFaninL0(pObj) >= nLatches ); -// assert( Seq_ObjFaninL1(pObj) >= nLatches ); - // subtract these latches on the fanin side - Seq_ObjAddFaninL0( pObj, -nLatches ); - Seq_ObjAddFaninL1( pObj, -nLatches ); - // make sure the label is clean - Abc_ObjForEachFanout( pObj, pFanout, i ) - assert( pFanout->fMarkC == 0 ); - // add these latches on the fanout side - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - if ( pFanout->fMarkC ) - continue; - pFanout->fMarkC = 1; - if ( Abc_ObjFaninId0(pFanout) != Abc_ObjFaninId1(pFanout) ) - Seq_ObjAddFanoutL( pObj, pFanout, nLatches ); - else - { - assert( Abc_ObjFanin0(pFanout) == pObj ); - Seq_ObjAddFaninL0( pFanout, nLatches ); - Seq_ObjAddFaninL1( pFanout, nLatches ); - } - } - // clean the label - Abc_ObjForEachFanout( pObj, pFanout, i ) - pFanout->fMarkC = 0; -} - -/**Function************************************************************* - - Synopsis [Retime node backward without initial states.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ObjRetimeBackwardTry( Abc_Obj_t * pObj, int nLatches ) -{ - Abc_Obj_t * pFanout; - int i; - // make sure it is an AND gate - assert( Abc_ObjFaninNum(pObj) == 2 ); - // make sure the label is clean - Abc_ObjForEachFanout( pObj, pFanout, i ) - assert( pFanout->fMarkC == 0 ); - // subtract these latches on the fanout side - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - if ( pFanout->fMarkC ) - continue; - pFanout->fMarkC = 1; -// assert( Abc_ObjFanoutL(pObj, pFanout) >= nLatches ); - if ( Abc_ObjFaninId0(pFanout) != Abc_ObjFaninId1(pFanout) ) - Seq_ObjAddFanoutL( pObj, pFanout, -nLatches ); - else - { - assert( Abc_ObjFanin0(pFanout) == pObj ); - Seq_ObjAddFaninL0( pFanout, -nLatches ); - Seq_ObjAddFaninL1( pFanout, -nLatches ); - } - } - // clean the label - Abc_ObjForEachFanout( pObj, pFanout, i ) - pFanout->fMarkC = 0; - // add these latches on the fanin side - Seq_ObjAddFaninL0( pObj, nLatches ); - Seq_ObjAddFaninL1( pObj, nLatches ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/seq/seqAigIter.c b/src/base/seq/seqAigIter.c deleted file mode 100644 index 392638b8..00000000 --- a/src/base/seq/seqAigIter.c +++ /dev/null @@ -1,268 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqRetIter.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [The iterative L-Value computation for retiming procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqRetIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the internal procedures -static int Seq_RetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose ); -static int Seq_RetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose ); -static int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Retimes AIG for optimal delay using Pan's algorithm.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_AigRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Abc_Obj_t * pNode; - int i, FiMax, RetValue, clk, clkIter; - char NodeLag; - - assert( Abc_NtkIsSeq( pNtk ) ); - - // get the upper bound on the clock period - FiMax = 2 + Seq_NtkLevelMax(pNtk); - - // make sure this clock period is feasible - if ( !Seq_RetimeForPeriod( pNtk, FiMax, fVerbose ) ) - { - Vec_StrFill( p->vLags, p->nSize, 0 ); - printf( "Error: The upper bound on the clock period cannot be computed.\n" ); - printf( "The reason for this error may be the presence in the circuit of logic\n" ); - printf( "that is not reachable from the PIs. Mapping/retiming is not performed.\n" ); - return 0; - } - - // search for the optimal clock period between 0 and nLevelMax -clk = clock(); - p->FiBestInt = Seq_RetimeSearch_rec( pNtk, 0, FiMax, fVerbose ); -clkIter = clock() - clk; - - // recompute the best l-values - RetValue = Seq_RetimeForPeriod( pNtk, p->FiBestInt, fVerbose ); - assert( RetValue ); - - // fix the problem with non-converged delays - Abc_AigForEachAnd( pNtk, pNode, i ) - if ( Seq_NodeGetLValue(pNode) < -ABC_INFINITY/2 ) - Seq_NodeSetLValue( pNode, 0 ); - - // write the retiming lags - Vec_StrFill( p->vLags, p->nSize, 0 ); - Abc_AigForEachAnd( pNtk, pNode, i ) - { - NodeLag = Seq_NodeComputeLag( Seq_NodeGetLValue(pNode), p->FiBestInt ); - Seq_NodeSetLag( pNode, NodeLag ); - } - - // print the result - if ( fVerbose ) - printf( "The best clock period is %3d.\n", p->FiBestInt ); - -/* - printf( "lvalues and lags : " ); - Abc_AigForEachAnd( pNtk, pNode, i ) - printf( "%d=%d(%d) ", pNode->Id, Seq_NodeGetLValue(pNode), Seq_NodeGetLag(pNode) ); - printf( "\n" ); -*/ -/* - { - FILE * pTable; - pTable = fopen( "stats.txt", "a+" ); - fprintf( pTable, "%s ", pNtk->pName ); - fprintf( pTable, "%d ", FiBest ); - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ -/* - { - FILE * pTable; - pTable = fopen( "stats.txt", "a+" ); - fprintf( pTable, "%s ", pNtk->pName ); - fprintf( pTable, "%.2f ", (float)(p->timeCuts)/(float)(CLOCKS_PER_SEC) ); - fprintf( pTable, "%.2f ", (float)(clkIter)/(float)(CLOCKS_PER_SEC) ); - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ - return 1; - -} - -/**Function************************************************************* - - Synopsis [Performs binary search for the optimal clock period.] - - Description [Assumes that FiMin is infeasible while FiMax is feasible.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_RetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose ) -{ - int Median; - assert( FiMin < FiMax ); - if ( FiMin + 1 == FiMax ) - return FiMax; - Median = FiMin + (FiMax - FiMin)/2; - if ( Seq_RetimeForPeriod( pNtk, Median, fVerbose ) ) - return Seq_RetimeSearch_rec( pNtk, FiMin, Median, fVerbose ); // Median is feasible - else - return Seq_RetimeSearch_rec( pNtk, Median, FiMax, fVerbose ); // Median is infeasible -} - -/**Function************************************************************* - - Synopsis [Returns 1 if retiming with this clock period is feasible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_RetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Abc_Obj_t * pObj; - int i, c, RetValue, fChange, Counter; - char * pReason = ""; - - // set l-values of all nodes to be minus infinity - Vec_IntFill( p->vLValues, p->nSize, -ABC_INFINITY ); - - // set l-values of constants and PIs - pObj = Abc_NtkObj( pNtk, 0 ); - Seq_NodeSetLValue( pObj, 0 ); - Abc_NtkForEachPi( pNtk, pObj, i ) - Seq_NodeSetLValue( pObj, 0 ); - - // update all values iteratively - Counter = 0; - for ( c = 0; c < p->nMaxIters; c++ ) - { - fChange = 0; - Abc_AigForEachAnd( pNtk, pObj, i ) - { - Counter++; - if ( Seq_NodeCutMan(pObj) ) - RetValue = Seq_FpgaNodeUpdateLValue( pObj, Fi ); - else - RetValue = Seq_RetimeNodeUpdateLValue( pObj, Fi ); - if ( RetValue == SEQ_UPDATE_YES ) - fChange = 1; - } - Abc_NtkForEachPo( pNtk, pObj, i ) - { - if ( Seq_NodeCutMan(pObj) ) - RetValue = Seq_FpgaNodeUpdateLValue( pObj, Fi ); - else - RetValue = Seq_RetimeNodeUpdateLValue( pObj, Fi ); - if ( RetValue == SEQ_UPDATE_FAIL ) - break; - } - if ( RetValue == SEQ_UPDATE_FAIL ) - break; - if ( fChange == 0 ) - break; - } - if ( c == p->nMaxIters ) - { - RetValue = SEQ_UPDATE_FAIL; - pReason = "(timeout)"; - } - else - c++; - // report the results - if ( fVerbose ) - { - if ( RetValue == SEQ_UPDATE_FAIL ) - printf( "Period = %3d. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason ); - else - printf( "Period = %3d. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter ); - } -/* - // check if any AND gates have infinite delay - Counter = 0; - Abc_AigForEachAnd( pNtk, pObj, i ) - Counter += (Seq_NodeGetLValue(pObj) < -ABC_INFINITY/2); - if ( Counter > 0 ) - printf( "Warning: %d internal nodes have wrong l-values!\n", Counter ); -*/ - return RetValue != SEQ_UPDATE_FAIL; -} - -/**Function************************************************************* - - Synopsis [Computes the l-value of the node.] - - Description [The node can be internal or a PO.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi ) -{ - int lValueNew, lValueOld, lValue0, lValue1; - assert( !Abc_ObjIsPi(pObj) ); - assert( Abc_ObjFaninNum(pObj) > 0 ); - lValue0 = Seq_NodeGetLValue(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj); - if ( Abc_ObjIsPo(pObj) ) - return (lValue0 > Fi)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO; - if ( Abc_ObjFaninNum(pObj) == 2 ) - lValue1 = Seq_NodeGetLValue(Abc_ObjFanin1(pObj)) - Fi * Seq_ObjFaninL1(pObj); - else - lValue1 = -ABC_INFINITY; - lValueNew = 1 + ABC_MAX( lValue0, lValue1 ); - lValueOld = Seq_NodeGetLValue(pObj); -// if ( lValueNew == lValueOld ) - if ( lValueNew <= lValueOld ) - return SEQ_UPDATE_NO; - Seq_NodeSetLValue( pObj, lValueNew ); - return SEQ_UPDATE_YES; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/seq/seqCreate.c b/src/base/seq/seqCreate.c deleted file mode 100644 index 16c7cc92..00000000 --- a/src/base/seq/seqCreate.c +++ /dev/null @@ -1,482 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqCreate.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [Transformations to and from the sequential AIG.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqCreate.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" - -/* - A sequential network is similar to AIG in that it contains only - AND gates. However, the AND-gates are currently not hashed. - - When converting AIG into sequential AIG: - - Const1/PIs/POs remain the same as in the original AIG. - - Instead of the latches, a new cutset is added, which is currently - defined as a set of AND gates that have a latch among their fanouts. - - The edges of a sequential AIG are labeled with latch attributes - in addition to the complementation attibutes. - - The attributes contain information about the number of latches - and their initial states. - - The number of latches is stored directly on the edges. The initial - states are stored in the sequential AIG manager. - - In the current version of the code, the sequential AIG is static - in the sense that the new AIG nodes are never created. - The retiming (or retiming/mapping) is performed by moving the - latches over the static nodes of the AIG. - The new initial state after backward retiming is computed - by setting up and solving a SAT problem. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Obj_t * Abc_NodeAigToSeq( Abc_Obj_t * pObjNew, Abc_Obj_t * pObj, int Edge, Vec_Int_t * vInitValues ); -static void Abc_NtkAigCutsetCopy( Abc_Ntk_t * pNtk ); -static Abc_Obj_t * Abc_NodeSeqToLogic( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanin, Seq_Lat_t * pRing, int nLatches ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Converts combinational AIG with latches into sequential AIG.] - - Description [The const/PI/PO nodes are duplicated. The internal - nodes are duplicated in the topological order. The dangling nodes - are not duplicated. The choice nodes are duplicated.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFaninNew; - Vec_Int_t * vInitValues; - Abc_InitType_t Init; - int i, k, RetValue; - - // make sure it is an AIG without self-feeding latches - assert( Abc_NtkIsStrash(pNtk) ); - assert( Abc_NtkIsDfsOrdered(pNtk) ); - - if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtk) ) - printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue ); - assert( Abc_NtkCountSelfFeedLatches(pNtk) == 0 ); - - // start the network - pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG, 1 ); - // duplicate the name and the spec - pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); - pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); - - // map the constant nodes - Abc_NtkCleanCopy( pNtk ); - Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); - - // copy all objects, except the latches and constant - Vec_PtrFill( pNtkNew->vObjs, Abc_NtkObjNumMax(pNtk), NULL ); - Vec_PtrWriteEntry( pNtkNew->vObjs, 0, Abc_AigConst1(pNtk)->pCopy ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( i == 0 || Abc_ObjIsLatch(pObj) ) - continue; - pObj->pCopy = Abc_ObjAlloc( pNtkNew, pObj->Type ); - pObj->pCopy->Id = pObj->Id; // the ID is the same for both - pObj->pCopy->fPhase = pObj->fPhase; // used to work with choices - pObj->pCopy->Level = pObj->Level; // used for upper bound on clock cycle - Vec_PtrWriteEntry( pNtkNew->vObjs, pObj->pCopy->Id, pObj->pCopy ); - pNtkNew->nObjs++; - } - pNtkNew->nObjCounts[ABC_OBJ_NODE] = pNtk->nObjCounts[ABC_OBJ_NODE]; - - // create PI/PO and their names - Abc_NtkForEachPi( pNtk, pObj, i ) - { - Vec_PtrPush( pNtkNew->vPis, pObj->pCopy ); - Vec_PtrPush( pNtkNew->vCis, pObj->pCopy ); - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); - } - Abc_NtkForEachPo( pNtk, pObj, i ) - { - Vec_PtrPush( pNtkNew->vPos, pObj->pCopy ); - Vec_PtrPush( pNtkNew->vCos, pObj->pCopy ); - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); - } - Abc_NtkForEachAssert( pNtk, pObj, i ) - { - Vec_PtrPush( pNtkNew->vAsserts, pObj->pCopy ); - Vec_PtrPush( pNtkNew->vCos, pObj->pCopy ); - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); - } - - // relink the choice nodes - Abc_AigForEachAnd( pNtk, pObj, i ) - if ( pObj->pData ) - pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy; - - // start the storage for initial states - Seq_Resize( pNtkNew->pManFunc, Abc_NtkObjNumMax(pNtkNew) ); - // reconnect the internal nodes - vInitValues = Vec_IntAlloc( 100 ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - // skip constants, PIs, and latches - if ( Abc_ObjFaninNum(pObj) == 0 || Abc_ObjIsLatch(pObj) ) - continue; - // process the first fanin - Vec_IntClear( vInitValues ); - pFaninNew = Abc_NodeAigToSeq( pObj->pCopy, pObj, 0, vInitValues ); - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - // store the initial values - Vec_IntForEachEntry( vInitValues, Init, k ) - Seq_NodeInsertFirst( pObj->pCopy, 0, Init ); - // skip single-input nodes - if ( Abc_ObjFaninNum(pObj) == 1 ) - continue; - // process the second fanin - Vec_IntClear( vInitValues ); - pFaninNew = Abc_NodeAigToSeq( pObj->pCopy, pObj, 1, vInitValues ); - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - // store the initial values - Vec_IntForEachEntry( vInitValues, Init, k ) - Seq_NodeInsertFirst( pObj->pCopy, 1, Init ); - } - Vec_IntFree( vInitValues ); - - // set the cutset composed of latch drivers - Abc_NtkAigCutsetCopy( pNtk ); - Seq_NtkLatchGetEqualFaninNum( pNtkNew ); - - // copy EXDC and check correctness - if ( pNtk->pExdc ) - fprintf( stdout, "Warning: EXDC is not copied when converting to sequential AIG.\n" ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkAigToSeq(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Determines the fanin that is transparent for latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeAigToSeq( Abc_Obj_t * pObjNew, Abc_Obj_t * pObj, int Edge, Vec_Int_t * vInitValues ) -{ - Abc_Obj_t * pFanin, * pFaninNew; - Abc_InitType_t Init; - // get the given fanin of the node - pFanin = Abc_ObjFanin( pObj, Edge ); - // if fanin is the internal node, return its copy in the corresponding polarity - if ( !Abc_ObjIsLatch(pFanin) ) - return Abc_ObjNotCond( pFanin->pCopy, Abc_ObjFaninC(pObj, Edge) ); - // fanin is a latch - // get the new fanins - pFaninNew = Abc_NodeAigToSeq( pObjNew, pFanin, 0, vInitValues ); - // get the initial state - Init = Abc_LatchInit(pFanin); - // complement the initial state if the inv is retimed over the latch - if ( Abc_ObjIsComplement(pFaninNew) ) - { - if ( Init == ABC_INIT_ZERO ) - Init = ABC_INIT_ONE; - else if ( Init == ABC_INIT_ONE ) - Init = ABC_INIT_ZERO; - else if ( Init != ABC_INIT_DC ) - assert( 0 ); - } - // record the initial state - Vec_IntPush( vInitValues, Init ); - return Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC(pObj, Edge) ); -} - -/**Function************************************************************* - - Synopsis [Collects the cut set nodes.] - - Description [These are internal AND gates that have latch fanouts.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkAigCutsetCopy( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pLatch, * pDriver, * pDriverNew; - int i; - Abc_NtkIncrementTravId(pNtk); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - pDriver = Abc_ObjFanin0(pLatch); - if ( Abc_NodeIsTravIdCurrent(pDriver) || !Abc_AigNodeIsAnd(pDriver) ) - continue; - Abc_NodeSetTravIdCurrent(pDriver); - pDriverNew = pDriver->pCopy; - Vec_PtrPush( pDriverNew->pNtk->vCutSet, pDriverNew ); - } -} - -/**Function************************************************************* - - Synopsis [Converts a sequential AIG into a logic SOP network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFaninNew; - Seq_Lat_t * pRing; - int i; - - assert( Abc_NtkIsSeq(pNtk) ); - // start the network without latches - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); - // duplicate the nodes - Abc_AigForEachAnd( pNtk, pObj, i ) - { - Abc_NtkDupObj(pNtkNew, pObj, 0); - pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); - } - // share and create the latches - Seq_NtkShareLatches( pNtkNew, pNtk ); - // connect the objects - Abc_AigForEachAnd( pNtk, pObj, i ) - { - if ( pRing = Seq_NodeGetRing(pObj,0) ) - pFaninNew = pRing->pLatch; - else - pFaninNew = Abc_ObjFanin0(pObj)->pCopy; - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - - if ( pRing = Seq_NodeGetRing(pObj,1) ) - pFaninNew = pRing->pLatch; - else - pFaninNew = Abc_ObjFanin1(pObj)->pCopy; - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - } - // connect the POs - Abc_NtkForEachPo( pNtk, pObj, i ) - { - if ( pRing = Seq_NodeGetRing(pObj,0) ) - pFaninNew = pRing->pLatch; - else - pFaninNew = Abc_ObjFanin0(pObj)->pCopy; - pFaninNew = Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC0(pObj) ); - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - } - // clean the latch pointers - Seq_NtkShareLatchesClean( pNtk ); - - // add the latches and their names - Abc_NtkAddDummyBoxNames( pNtkNew ); - Abc_NtkOrderCisCos( pNtkNew ); - // fix the problem with complemented and duplicated CO edges - Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkSeqToLogicSop(): Network check has failed.\n" ); - return pNtkNew; -} - - -/**Function************************************************************* - - Synopsis [Converts a sequential AIG into a logic SOP network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkSeqToLogicSop_old( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFaninNew; - int i; - - assert( Abc_NtkIsSeq(pNtk) ); - // start the network without latches - pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); - - // duplicate the nodes, create node functions - Abc_NtkForEachNode( pNtk, pObj, i ) - { - // skip the constant - if ( Abc_ObjFaninNum(pObj) == 0 ) - continue; - // duplicate the node - Abc_NtkDupObj(pNtkNew, pObj, 0); - if ( Abc_ObjFaninNum(pObj) == 1 ) - { - assert( !Abc_ObjFaninC0(pObj) ); - pObj->pCopy->pData = Abc_SopCreateBuf( pNtkNew->pManFunc ); - continue; - } - pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); - } - // connect the objects - Abc_NtkForEachObj( pNtk, pObj, i ) - { - assert( (int)pObj->Id == i ); - // skip PIs and the constant - if ( Abc_ObjFaninNum(pObj) == 0 ) - continue; - // create the edge - pFaninNew = Abc_NodeSeqToLogic( pNtkNew, Abc_ObjFanin0(pObj), Seq_NodeGetRing(pObj,0), Seq_ObjFaninL0(pObj) ); - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - if ( Abc_ObjFaninNum(pObj) == 1 ) - { - // create the complemented edge - if ( Abc_ObjFaninC0(pObj) ) - Abc_ObjSetFaninC( pObj->pCopy, 0 ); - continue; - } - // create the edge - pFaninNew = Abc_NodeSeqToLogic( pNtkNew, Abc_ObjFanin1(pObj), Seq_NodeGetRing(pObj,1), Seq_ObjFaninL1(pObj) ); - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - // the complemented edges are subsumed by the node function - } - // add the latches and their names - Abc_NtkAddDummyBoxNames( pNtkNew ); - Abc_NtkOrderCisCos( pNtkNew ); - // fix the problem with complemented and duplicated CO edges - Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkSeqToLogicSop(): Network check has failed.\n" ); - return pNtkNew; -} - - -/**Function************************************************************* - - Synopsis [Creates latches on one edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NodeSeqToLogic( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pFanin, Seq_Lat_t * pRing, int nLatches ) -{ - Abc_Obj_t * pLatch; - if ( nLatches == 0 ) - { - assert( pFanin->pCopy ); - return pFanin->pCopy; - } - pFanin = Abc_NodeSeqToLogic( pNtkNew, pFanin, Seq_LatNext(pRing), nLatches - 1 ); - pLatch = Abc_NtkCreateLatch( pNtkNew ); - pLatch->pData = (void *)Seq_LatInit( pRing ); - Abc_ObjAddFanin( pLatch, pFanin ); - return pLatch; -} - -/**Function************************************************************* - - Synopsis [Makes sure that every node in the table is in the network and vice versa.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Abc_NtkSeqCheck( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i, nFanins; - Abc_NtkForEachNode( pNtk, pObj, i ) - { - nFanins = Abc_ObjFaninNum(pObj); - if ( nFanins == 0 ) - { - if ( pObj != Abc_AigConst1(pNtk) ) - { - printf( "Abc_SeqCheck: The AIG has non-standard constant nodes.\n" ); - return 0; - } - continue; - } - if ( nFanins == 1 ) - { - printf( "Abc_SeqCheck: The AIG has single input nodes.\n" ); - return 0; - } - if ( nFanins > 2 ) - { - printf( "Abc_SeqCheck: The AIG has non-standard nodes.\n" ); - return 0; - } - } - // check the correctness of the internal representation of the initial states - Abc_NtkForEachObj( pNtk, pObj, i ) - { - nFanins = Abc_ObjFaninNum(pObj); - if ( nFanins == 0 ) - continue; - if ( nFanins == 1 ) - { - if ( Seq_NodeCountLats(pObj, 0) != Seq_ObjFaninL0(pObj) ) - { - printf( "Abc_SeqCheck: Node %d has mismatch in the number of latches.\n", Abc_ObjName(pObj) ); - return 0; - } - } - // look at both inputs - if ( Seq_NodeCountLats(pObj, 0) != Seq_ObjFaninL0(pObj) ) - { - printf( "Abc_SeqCheck: The first fanin of node %d has mismatch in the number of latches.\n", Abc_ObjName(pObj) ); - return 0; - } - if ( Seq_NodeCountLats(pObj, 1) != Seq_ObjFaninL1(pObj) ) - { - printf( "Abc_SeqCheck: The second fanin of node %d has mismatch in the number of latches.\n", Abc_ObjName(pObj) ); - return 0; - } - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/seq/seqFpgaCore.c b/src/base/seq/seqFpgaCore.c deleted file mode 100644 index b106ded2..00000000 --- a/src/base/seq/seqFpgaCore.c +++ /dev/null @@ -1,643 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqFpgaCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [The core of FPGA mapping/retiming package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqFpgaCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * Seq_NtkFpgaDup( Abc_Ntk_t * pNtk ); -static int Seq_NtkFpgaInitCompatible( Abc_Ntk_t * pNtk, int fVerbose ); -static Abc_Ntk_t * Seq_NtkSeqFpgaMapped( Abc_Ntk_t * pNtkNew ); -static int Seq_FpgaMappingCount( Abc_Ntk_t * pNtk ); -static int Seq_FpgaMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves ); -static Abc_Obj_t * Seq_FpgaMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int LagCut, Vec_Ptr_t * vLeaves ); -static DdNode * Seq_FpgaMappingBdd_rec( DdManager * dd, Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves ); -static void Seq_FpgaMappingEdges_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, Vec_Ptr_t * vLeaves, Vec_Vec_t * vMapEdges ); -static void Seq_FpgaMappingConnect_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ); -static DdNode * Seq_FpgaMappingConnectBdd_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs FPGA mapping and retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Seq_NtkFpgaMapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Abc_Ntk_t * pNtkNew; - Abc_Ntk_t * pNtkMap; - int RetValue; - - // get the LUT library - p->nVarsMax = Fpga_LutLibReadVarMax( Abc_FrameReadLibLut() ); - p->nMaxIters = nMaxIters; - - // find the best mapping and retiming for all nodes (p->vLValues, p->vBestCuts, p->vLags) - if ( !Seq_FpgaMappingDelays( pNtk, fVerbose ) ) - return NULL; - if ( RetValue = Abc_NtkGetChoiceNum(pNtk) ) - { - printf( "The network has %d choices. The resulting network is not derived (this is temporary).\n", RetValue ); - printf( "The mininum clock period computed is %d.\n", p->FiBestInt ); - return NULL; - } - - // duplicate the nodes contained in multiple cuts - pNtkNew = Seq_NtkFpgaDup( pNtk ); -// return pNtkNew; - - // implement the retiming - RetValue = Seq_NtkImplementRetiming( pNtkNew, ((Abc_Seq_t *)pNtkNew->pManFunc)->vLags, fVerbose ); - if ( RetValue == 0 ) - printf( "Retiming completed but initial state computation has failed.\n" ); -// return pNtkNew; - - // check the compatibility of initial states computed - if ( RetValue = Seq_NtkFpgaInitCompatible( pNtkNew, fVerbose ) ) - printf( "The number of LUTs with incompatible edges = %d.\n", RetValue ); - - // create the final mapped network - pNtkMap = Seq_NtkSeqFpgaMapped( pNtkNew ); - Abc_NtkDelete( pNtkNew ); - if ( RetValue ) - printf( "The number of LUTs with more than %d inputs = %d.\n", - p->nVarsMax, Seq_NtkCountNodesAboveLimit(pNtkMap, p->nVarsMax) ); - return pNtkMap; -} - -/**Function************************************************************* - - Synopsis [Derives the network by duplicating some of the nodes.] - - Description [Information about mapping is given as mapping nodes (p->vMapAnds) - and best cuts for each node (p->vMapCuts).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Seq_NtkFpgaDup( Abc_Ntk_t * pNtk ) -{ - Abc_Seq_t * pNew, * p = pNtk->pManFunc; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pLeaf; - Vec_Ptr_t * vLeaves; - unsigned SeqEdge; - int i, k, nObjsNew, Lag; - - assert( Abc_NtkIsSeq(pNtk) ); - - // start the expanded network - pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); - - // start the new sequential AIG manager - nObjsNew = 1 + Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk) + Seq_FpgaMappingCount(pNtk); - Seq_Resize( pNtkNew->pManFunc, nObjsNew ); - - // duplicate the nodes in the mapping - Vec_PtrForEachEntry( p->vMapAnds, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - - // recursively construct the internals of each node - Vec_PtrForEachEntry( p->vMapAnds, pObj, i ) - { - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - Seq_FpgaMappingBuild_rec( pNtkNew, pNtk, pObj->Id << 8, 1, Seq_NodeGetLag(pObj), vLeaves ); - } - assert( nObjsNew == pNtkNew->nObjs ); - - // set the POs - Abc_NtkFinalize( pNtk, pNtkNew ); - // duplicate the latches on the PO edges - Abc_NtkForEachPo( pNtk, pObj, i ) - Seq_NodeDupLats( pObj->pCopy, pObj, 0 ); - - // transfer the mapping info to the new manager - Vec_PtrForEachEntry( p->vMapAnds, pObj, i ) - { - // get the leaves of the cut - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - // convert the leaf nodes - Vec_PtrForEachEntry( vLeaves, pLeaf, k ) - { - SeqEdge = (unsigned)pLeaf; - pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - Lag = (SeqEdge & 255) + Seq_NodeGetLag(pObj) - Seq_NodeGetLag(pLeaf); - assert( Lag >= 0 ); - // translate the old leaf into the leaf in the new network - Vec_PtrWriteEntry( vLeaves, k, (void *)((pLeaf->pCopy->Id << 8) | Lag) ); -// printf( "%d -> %d\n", pLeaf->Id, pLeaf->pCopy->Id ); - } - // convert the root node - Vec_PtrWriteEntry( p->vMapAnds, i, pObj->pCopy ); - } - pNew = pNtkNew->pManFunc; - pNew->nVarsMax = p->nVarsMax; - pNew->vMapAnds = p->vMapAnds; p->vMapAnds = NULL; - pNew->vMapCuts = p->vMapCuts; p->vMapCuts = NULL; - - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Seq_NtkFpgaDup(): Network check has failed.\n" ); - return pNtkNew; -} - - -/**Function************************************************************* - - Synopsis [Checks if the initial states are compatible.] - - Description [Checks of all the initial states on the fanins edges - of the cut have compatible number of latches and initial states. - If this is not true, then the mapped network with the does not have initial - state. Returns the number of LUTs with incompatible edges.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkFpgaInitCompatible( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Abc_Obj_t * pAnd, * pLeaf, * pFanout0, * pFanout1; - Vec_Vec_t * vTotalEdges; - Vec_Ptr_t * vLeaves, * vEdges; - int i, k, m, Edge0, Edge1, nLatchAfter, nLatches1, nLatches2; - unsigned SeqEdge; - int CountBad = 0, CountAll = 0; - - vTotalEdges = Vec_VecStart( p->nVarsMax ); - // go through all the nodes (cuts) used in the mapping - Vec_PtrForEachEntry( p->vMapAnds, pAnd, i ) - { -// printf( "*** Node %d.\n", pAnd->Id ); - - // get the cut of this gate - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - - // get the edges pointing to the leaves - Vec_VecClear( vTotalEdges ); - Seq_FpgaMappingEdges_rec( pNtk, pAnd->Id << 8, NULL, vLeaves, vTotalEdges ); - - // for each leaf, consider its edges - Vec_PtrForEachEntry( vLeaves, pLeaf, k ) - { - SeqEdge = (unsigned)pLeaf; - pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - nLatchAfter = SeqEdge & 255; - if ( nLatchAfter == 0 ) - continue; - - // go through the edges - vEdges = Vec_VecEntry( vTotalEdges, k ); - pFanout0 = NULL; - Vec_PtrForEachEntry( vEdges, pFanout1, m ) - { - Edge1 = Abc_ObjIsComplement(pFanout1); - pFanout1 = Abc_ObjRegular(pFanout1); -//printf( "Fanin = %d. Fanout = %d.\n", pLeaf->Id, pFanout1->Id ); - - // make sure this is the same fanin - if ( Edge1 ) - assert( pLeaf == Abc_ObjFanin1(pFanout1) ); - else - assert( pLeaf == Abc_ObjFanin0(pFanout1) ); - - // save the first one - if ( pFanout0 == NULL ) - { - pFanout0 = pFanout1; - Edge0 = Edge1; - continue; - } - // compare the rings - // if they have different number of latches, this is the bug - nLatches1 = Seq_NodeCountLats(pFanout0, Edge0); - nLatches2 = Seq_NodeCountLats(pFanout1, Edge1); - assert( nLatches1 == nLatches2 ); - assert( nLatches1 == nLatchAfter ); - assert( nLatches1 > 0 ); - - // if they have different initial states, this is the problem - if ( !Seq_NodeCompareLats(pFanout0, Edge0, pFanout1, Edge1) ) - { - CountBad++; - break; - } - CountAll++; - } - } - } - if ( fVerbose ) - printf( "The number of pairs of edges checked = %d.\n", CountAll ); - Vec_VecFree( vTotalEdges ); - return CountBad; -} - -/**Function************************************************************* - - Synopsis [Derives the final mapped network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Seq_NtkSeqFpgaMapped( Abc_Ntk_t * pNtk ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Abc_Ntk_t * pNtkMap; - Vec_Ptr_t * vLeaves; - Abc_Obj_t * pObj, * pFaninNew; - Seq_Lat_t * pRing; - int i; - - assert( Abc_NtkIsSeq(pNtk) ); - - // start the network - pNtkMap = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); - - // duplicate the nodes used in the mapping - Vec_PtrForEachEntry( p->vMapAnds, pObj, i ) - pObj->pCopy = Abc_NtkCreateNode( pNtkMap ); - - // create and share the latches - Seq_NtkShareLatchesMapping( pNtkMap, pNtk, p->vMapAnds, 1 ); - - // connect the nodes - Vec_PtrForEachEntry( p->vMapAnds, pObj, i ) - { - // get the leaves of this gate - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - // get the BDD of the node - pObj->pCopy->pData = Seq_FpgaMappingConnectBdd_rec( pNtk, pObj->Id << 8, NULL, -1, pObj, vLeaves ); - Cudd_Ref( pObj->pCopy->pData ); - // complement the BDD of the cut if it came from the opposite polarity choice cut -// if ( Vec_StrEntry(p->vPhase, i) ) -// pObj->pCopy->pData = Cudd_Not( pObj->pCopy->pData ); - } - - // set the POs - Abc_NtkForEachPo( pNtk, pObj, i ) - { - if ( pRing = Seq_NodeGetRing(pObj,0) ) - pFaninNew = pRing->pLatch; - else - pFaninNew = Abc_ObjFanin0(pObj)->pCopy; - pFaninNew = Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC0(pObj) ); - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - } - - // add the latches and their names - Abc_NtkAddDummyBoxNames( pNtkMap ); - Abc_NtkOrderCisCos( pNtkMap ); - // fix the problem with complemented and duplicated CO edges - Abc_NtkLogicMakeSimpleCos( pNtkMap, 1 ); - // make the network minimum base - Abc_NtkMinimumBase( pNtkMap ); - if ( !Abc_NtkCheck( pNtkMap ) ) - fprintf( stdout, "Seq_NtkSeqFpgaMapped(): Network check has failed.\n" ); - return pNtkMap; -} - - -/**Function************************************************************* - - Synopsis [Counts the number of nodes in the bag.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_FpgaMappingCount( Abc_Ntk_t * pNtk ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Vec_Ptr_t * vLeaves; - Abc_Obj_t * pAnd; - int i, Counter = 0; - Vec_PtrForEachEntry( p->vMapAnds, pAnd, i ) - { - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - Counter += Seq_FpgaMappingCount_rec( pNtk, pAnd->Id << 8, vLeaves ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of nodes in the bag.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_FpgaMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves ) -{ - Abc_Obj_t * pObj, * pLeaf; - unsigned SeqEdge0, SeqEdge1; - int Lag, i; - // get the object and the lag - pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - Lag = SeqEdge & 255; - // if the node is the fanin of the cut, return - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - if ( SeqEdge == (unsigned)pLeaf ) - return 0; - // continue unfolding - assert( Abc_AigNodeIsAnd(pObj) ); - // get new sequential edges - assert( Lag + Seq_ObjFaninL0(pObj) < 255 ); - assert( Lag + Seq_ObjFaninL1(pObj) < 255 ); - SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj); - SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj); - // call for the children - return 1 + Seq_FpgaMappingCount_rec( pNtk, SeqEdge0, vLeaves ) + - Seq_FpgaMappingCount_rec( pNtk, SeqEdge1, vLeaves ); -} - -/**Function************************************************************* - - Synopsis [Collects the edges pointing to the leaves of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Seq_FpgaMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int LagCut, Vec_Ptr_t * vLeaves ) -{ - Abc_Obj_t * pObj, * pObjNew, * pLeaf, * pFaninNew0, * pFaninNew1; - unsigned SeqEdge0, SeqEdge1; - int Lag, i; - // get the object and the lag - pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - Lag = SeqEdge & 255; - // if the node is the fanin of the cut, return - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - if ( SeqEdge == (unsigned)pLeaf ) - return pObj->pCopy; - // continue unfolding - assert( Abc_AigNodeIsAnd(pObj) ); - // get new sequential edges - assert( Lag + Seq_ObjFaninL0(pObj) < 255 ); - assert( Lag + Seq_ObjFaninL1(pObj) < 255 ); - SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj); - SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj); - // call for the children - pObjNew = fTop? pObj->pCopy : Abc_NtkCreateNode( pNtkNew ); - // solve subproblems - pFaninNew0 = Seq_FpgaMappingBuild_rec( pNtkNew, pNtk, SeqEdge0, 0, LagCut, vLeaves ); - pFaninNew1 = Seq_FpgaMappingBuild_rec( pNtkNew, pNtk, SeqEdge1, 0, LagCut, vLeaves ); - // add the fanins to the node - Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew0, Abc_ObjFaninC0(pObj) ) ); - Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew1, Abc_ObjFaninC1(pObj) ) ); - Seq_NodeDupLats( pObjNew, pObj, 0 ); - Seq_NodeDupLats( pObjNew, pObj, 1 ); - // set the lag of the new node equal to the internal lag plus mapping/retiming lag - Seq_NodeSetLag( pObjNew, (char)(Lag + LagCut) ); -// Seq_NodeSetLag( pObjNew, (char)(Lag) ); - return pObjNew; -} - -/**Function************************************************************* - - Synopsis [Derives the BDD of the selected cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Seq_FpgaMappingBdd_rec( DdManager * dd, Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves ) -{ - Abc_Obj_t * pObj, * pLeaf; - DdNode * bFunc0, * bFunc1, * bFunc; - unsigned SeqEdge0, SeqEdge1; - int Lag, i; - // get the object and the lag - pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - Lag = SeqEdge & 255; - // if the node is the fanin of the cut, return - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - if ( SeqEdge == (unsigned)pLeaf ) - return Cudd_bddIthVar( dd, i ); - // continue unfolding - assert( Abc_AigNodeIsAnd(pObj) ); - // get new sequential edges - assert( Lag + Seq_ObjFaninL0(pObj) < 255 ); - assert( Lag + Seq_ObjFaninL1(pObj) < 255 ); - SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj); - SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj); - // call for the children - bFunc0 = Seq_FpgaMappingBdd_rec( dd, pNtk, SeqEdge0, vLeaves ); Cudd_Ref( bFunc0 ); - bFunc1 = Seq_FpgaMappingBdd_rec( dd, pNtk, SeqEdge1, vLeaves ); Cudd_Ref( bFunc1 ); - bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pObj) ); - bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pObj) ); - // get the BDD of the node - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bFunc0 ); - Cudd_RecursiveDeref( dd, bFunc1 ); - // return the BDD - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Collects the edges pointing to the leaves of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_FpgaMappingEdges_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, Vec_Ptr_t * vLeaves, Vec_Vec_t * vMapEdges ) -{ - Abc_Obj_t * pObj, * pLeaf; - unsigned SeqEdge0, SeqEdge1; - int Lag, i; - // get the object and the lag - pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - Lag = SeqEdge & 255; - // if the node is the fanin of the cut, return - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - { - if ( SeqEdge == (unsigned)pLeaf ) - { - assert( pPrev != NULL ); - Vec_VecPush( vMapEdges, i, pPrev ); - return; - } - } - // continue unfolding - assert( Abc_AigNodeIsAnd(pObj) ); - // get new sequential edges - assert( Lag + Seq_ObjFaninL0(pObj) < 255 ); - assert( Lag + Seq_ObjFaninL1(pObj) < 255 ); - SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj); - SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj); - // call for the children - Seq_FpgaMappingEdges_rec( pNtk, SeqEdge0, pObj , vLeaves, vMapEdges ); - Seq_FpgaMappingEdges_rec( pNtk, SeqEdge1, Abc_ObjNot(pObj), vLeaves, vMapEdges ); -} - -/**Function************************************************************* - - Synopsis [Collects the edges pointing to the leaves of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_FpgaMappingConnect_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ) -{ - Seq_Lat_t * pRing; - Abc_Obj_t * pObj, * pLeaf, * pFanin, * pFaninNew; - unsigned SeqEdge0, SeqEdge1; - int Lag, i, k; - // get the object and the lag - pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - Lag = SeqEdge & 255; - // if the node is the fanin of the cut, add the connection and return - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - { - if ( SeqEdge == (unsigned)pLeaf ) - { - assert( pPrev != NULL ); - if ( pRing = Seq_NodeGetRing(pPrev,Edge) ) - pFaninNew = pRing->pLatch; - else - pFaninNew = Abc_ObjFanin(pPrev,Edge)->pCopy; - // check if the root already has this fanin - Abc_ObjForEachFanin( pRoot, pFanin, k ) - if ( pFanin == pFaninNew ) - return; - Abc_ObjAddFanin( pRoot->pCopy, pFaninNew ); - return; - } - } - // continue unfolding - assert( Abc_AigNodeIsAnd(pObj) ); - // get new sequential edges - assert( Lag + Seq_ObjFaninL0(pObj) < 255 ); - assert( Lag + Seq_ObjFaninL1(pObj) < 255 ); - SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj); - SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj); - // call for the children - Seq_FpgaMappingConnect_rec( pNtk, SeqEdge0, pObj, 0, pRoot, vLeaves ); - Seq_FpgaMappingConnect_rec( pNtk, SeqEdge1, pObj, 1, pRoot, vLeaves ); -} - -/**Function************************************************************* - - Synopsis [Collects the edges pointing to the leaves of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Seq_FpgaMappingConnectBdd_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ) -{ - Seq_Lat_t * pRing; - Abc_Obj_t * pObj, * pLeaf, * pFanin, * pFaninNew; - unsigned SeqEdge0, SeqEdge1; - DdManager * dd = pRoot->pCopy->pNtk->pManFunc; - DdNode * bFunc, * bFunc0, * bFunc1; - int Lag, i, k; - // get the object and the lag - pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - Lag = SeqEdge & 255; - // if the node is the fanin of the cut, add the connection and return - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - { - if ( SeqEdge == (unsigned)pLeaf ) - { - assert( pPrev != NULL ); - if ( pRing = Seq_NodeGetRing(pPrev,Edge) ) - pFaninNew = pRing->pLatch; - else - pFaninNew = Abc_ObjFanin(pPrev,Edge)->pCopy; - // check if the root already has this fanin - Abc_ObjForEachFanin( pRoot->pCopy, pFanin, k ) - if ( pFanin == pFaninNew ) - return Cudd_bddIthVar( dd, k ); - Abc_ObjAddFanin( pRoot->pCopy, pFaninNew ); - return Cudd_bddIthVar( dd, k ); - } - } - // continue unfolding - assert( Abc_AigNodeIsAnd(pObj) ); - // get new sequential edges - assert( Lag + Seq_ObjFaninL0(pObj) < 255 ); - assert( Lag + Seq_ObjFaninL1(pObj) < 255 ); - SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj); - SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj); - // call for the children - bFunc0 = Seq_FpgaMappingConnectBdd_rec( pNtk, SeqEdge0, pObj, 0, pRoot, vLeaves ); Cudd_Ref( bFunc0 ); - bFunc1 = Seq_FpgaMappingConnectBdd_rec( pNtk, SeqEdge1, pObj, 1, pRoot, vLeaves ); Cudd_Ref( bFunc1 ); - bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pObj) ); - bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pObj) ); - // get the BDD of the node - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bFunc0 ); - Cudd_RecursiveDeref( dd, bFunc1 ); - // return the BDD - Cudd_Deref( bFunc ); - return bFunc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/seq/seqFpgaIter.c b/src/base/seq/seqFpgaIter.c deleted file mode 100644 index a300b362..00000000 --- a/src/base/seq/seqFpgaIter.c +++ /dev/null @@ -1,270 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqFpgaIter.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [Iterative delay computation in FPGA mapping/retiming package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqFpgaIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" -#include "main.h" -#include "fpga.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Seq_FpgaMappingCollectNode_rec( Abc_Obj_t * pAnd, Vec_Ptr_t * vMapping, Vec_Vec_t * vMapCuts ); -static Cut_Cut_t * Seq_FpgaMappingSelectCut( Abc_Obj_t * pAnd ); - -extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); -extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the retiming lags for FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_FpgaMappingDelays( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Cut_Params_t Params, * pParams = &Params; - Abc_Obj_t * pObj; - int i, clk; - - // set defaults for cut computation - memset( pParams, 0, sizeof(Cut_Params_t) ); - pParams->nVarsMax = p->nVarsMax; // the max cut size ("k" of the k-feasible cuts) - pParams->nKeepMax = 1000; // the max number of cuts kept at a node - pParams->fTruth = 0; // compute truth tables - pParams->fFilter = 1; // filter dominated cuts - pParams->fSeq = 1; // compute sequential cuts - pParams->fVerbose = fVerbose; // the verbosiness flag - - // compute the cuts -clk = clock(); - p->pCutMan = Abc_NtkSeqCuts( pNtk, pParams ); -// pParams->fSeq = 0; -// p->pCutMan = Abc_NtkCuts( pNtk, pParams ); -p->timeCuts = clock() - clk; - - if ( fVerbose ) - Cut_ManPrintStats( p->pCutMan ); - - // compute area flows -// Seq_MapComputeAreaFlows( pNtk, fVerbose ); - - // compute the delays -clk = clock(); - if ( !Seq_AigRetimeDelayLags( pNtk, fVerbose ) ) - return 0; - p->timeDelay = clock() - clk; - - // collect the nodes and cuts used in the mapping - p->vMapAnds = Vec_PtrAlloc( 1000 ); - p->vMapCuts = Vec_VecAlloc( 1000 ); - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Seq_FpgaMappingCollectNode_rec( Abc_ObjFanin0(pObj), p->vMapAnds, p->vMapCuts ); - - if ( fVerbose ) - printf( "The number of LUTs = %d.\n", Vec_PtrSize(p->vMapAnds) ); - - // remove the cuts - Cut_ManStop( p->pCutMan ); - p->pCutMan = NULL; - return 1; -} - -/**Function************************************************************* - - Synopsis [Derives the parameters of the best mapping/retiming for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_FpgaMappingCollectNode_rec( Abc_Obj_t * pAnd, Vec_Ptr_t * vMapping, Vec_Vec_t * vMapCuts ) -{ - Abc_Obj_t * pFanin; - Cut_Cut_t * pCutBest; - int k; - - // skip if this is a non-PI node - if ( !Abc_AigNodeIsAnd(pAnd) ) - return; - // skip a visited node - if ( Abc_NodeIsTravIdCurrent(pAnd) ) - return; - Abc_NodeSetTravIdCurrent(pAnd); - - // visit the fanins of the node - pCutBest = Seq_FpgaMappingSelectCut( pAnd ); - for ( k = 0; k < (int)pCutBest->nLeaves; k++ ) - { - pFanin = Abc_NtkObj( pAnd->pNtk, pCutBest->pLeaves[k] >> 8 ); - Seq_FpgaMappingCollectNode_rec( pFanin, vMapping, vMapCuts ); - } - - // add this node - Vec_PtrPush( vMapping, pAnd ); - for ( k = 0; k < (int)pCutBest->nLeaves; k++ ) - Vec_VecPush( vMapCuts, Vec_PtrSize(vMapping)-1, (void *)pCutBest->pLeaves[k] ); -} - -/**Function************************************************************* - - Synopsis [Selects the best cut to represent the node in the mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Seq_FpgaMappingSelectCut( Abc_Obj_t * pAnd ) -{ - Abc_Obj_t * pFanin; - Cut_Cut_t * pCut, * pCutBest, * pList; - float CostCur, CostMin = ABC_INFINITY; - int ArrivalCut, ArrivalMin, i; - // get the arrival time of the best non-trivial cut - ArrivalMin = Seq_NodeGetLValue( pAnd ); - // iterate through the cuts and select the one with the minimum cost - pList = Abc_NodeReadCuts( Seq_NodeCutMan(pAnd), pAnd ); - CostMin = ABC_INFINITY; - pCutBest = NULL; - for ( pCut = pList->pNext; pCut; pCut = pCut->pNext ) - { - ArrivalCut = *((int *)&pCut->uSign); -// assert( ArrivalCut >= ArrivalMin ); - if ( ArrivalCut > ArrivalMin ) - continue; - CostCur = 0.0; - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - { - pFanin = Abc_NtkObj( pAnd->pNtk, pCut->pLeaves[i] >> 8 ); - if ( Abc_ObjIsPi(pFanin) ) - continue; - if ( Abc_NodeIsTravIdCurrent(pFanin) ) - continue; - CostCur += (float)(1.0 / Abc_ObjFanoutNum(pFanin)); -// CostCur += Seq_NodeGetFlow( pFanin ); - } - if ( CostMin > CostCur ) - { - CostMin = CostCur; - pCutBest = pCut; - } - } - assert( pCutBest != NULL ); - return pCutBest; -} - - -/**Function************************************************************* - - Synopsis [Computes the l-value of the cut.] - - Description [The node should be internal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Seq_FpgaCutUpdateLValue( Cut_Cut_t * pCut, Abc_Obj_t * pObj, int Fi ) -{ - Abc_Obj_t * pFanin; - int i, lValueMax, lValueCur; - assert( Abc_AigNodeIsAnd(pObj) ); - lValueMax = -ABC_INFINITY; - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - { -// lValue0 = Seq_NodeGetLValue(Abc_ObjFanin0(pObj)) - Fi * Abc_ObjFaninL0(pObj); - pFanin = Abc_NtkObj(pObj->pNtk, pCut->pLeaves[i] >> 8); - lValueCur = Seq_NodeGetLValue(pFanin) - Fi * (pCut->pLeaves[i] & 255); - if ( lValueMax < lValueCur ) - lValueMax = lValueCur; - } - lValueMax += 1; - *((int *)&pCut->uSign) = lValueMax; - return lValueMax; -} - -/**Function************************************************************* - - Synopsis [Computes the l-value of the node.] - - Description [The node can be internal or a PO.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_FpgaNodeUpdateLValue( Abc_Obj_t * pObj, int Fi ) -{ - Cut_Cut_t * pCut, * pList; - int lValueNew, lValueOld, lValueCut; - assert( !Abc_ObjIsPi(pObj) ); - assert( Abc_ObjFaninNum(pObj) > 0 ); - if ( Abc_ObjIsPo(pObj) ) - { - lValueNew = Seq_NodeGetLValue(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj); - return (lValueNew > Fi)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO; - } - // get the arrival time of the best non-trivial cut - pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj ); - // skip the choice nodes - if ( pList == NULL ) - return SEQ_UPDATE_NO; - lValueNew = ABC_INFINITY; - for ( pCut = pList->pNext; pCut; pCut = pCut->pNext ) - { - lValueCut = Seq_FpgaCutUpdateLValue( pCut, pObj, Fi ); - if ( lValueNew > lValueCut ) - lValueNew = lValueCut; - } - // compare the arrival time with the previous arrival time - lValueOld = Seq_NodeGetLValue(pObj); -// if ( lValueNew == lValueOld ) - if ( lValueNew <= lValueOld ) - return SEQ_UPDATE_NO; - Seq_NodeSetLValue( pObj, lValueNew ); -//printf( "%d -> %d ", lValueOld, lValueNew ); - return SEQ_UPDATE_YES; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/seq/seqInt.h b/src/base/seq/seqInt.h deleted file mode 100644 index 221efc91..00000000 --- a/src/base/seq/seqInt.h +++ /dev/null @@ -1,256 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __SEQ_INT_H__ -#define __SEQ_INT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "abc.h" -#include "cut.h" -#include "main.h" -#include "mio.h" -#include "mapper.h" -#include "fpga.h" -#include "seq.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -#define SEQ_FULL_MASK 0xFFFFFFFF - -// node status after updating its arrival time -enum { SEQ_UPDATE_FAIL, SEQ_UPDATE_NO, SEQ_UPDATE_YES }; - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -// manager of sequential AIG -struct Abc_Seq_t_ -{ - // sequential information - Abc_Ntk_t * pNtk; // the network - int nSize; // the number of entries in all internal arrays - Vec_Int_t * vNums; // the number of latches on each edge in the AIG - Vec_Ptr_t * vInits; // the initial states for each edge in the AIG - Extra_MmFixed_t * pMmInits; // memory manager for latch structures used to remember init states - int fVerbose; // the verbose flag - float fEpsilon; // the accuracy for delay computation - int fStandCells; // the flag denoting standard cell mapping - int nMaxIters; // the max number of iterations - int FiBestInt; // the best clock period - float FiBestFloat; // the best clock period - // K-feasible cuts - int nVarsMax; // the max cut size - Cut_Man_t * pCutMan; // cut manager - Map_SuperLib_t * pSuperLib; // the current supergate library - // sequential arrival time computation - Vec_Int_t * vAFlows; // the area flow of each cut - Vec_Int_t * vLValues; // the arrival times (L-Values of nodes) - Vec_Int_t * vLValuesN; // the arrival times (L-Values of nodes) - Vec_Str_t * vLags; // the lags of the mapped nodes - Vec_Str_t * vLagsN; // the lags of the mapped nodes - Vec_Str_t * vUses; // the phase usage - // representation of the mapping - Vec_Ptr_t * vMapAnds; // nodes visible in the mapping - Vec_Vec_t * vMapCuts; // best cuts for each node - Vec_Vec_t * vMapDelays; // the delay of each fanin - Vec_Vec_t * vMapFanins; // the delay of each fanin - // runtime stats - int timeCuts; // runtime to compute the cuts - int timeDelay; // runtime to compute the L-values - int timeRet; // runtime to retime the resulting network - int timeNtk; // runtime to create the final network - -}; - -// data structure to store initial state -typedef struct Seq_Lat_t_ Seq_Lat_t; -struct Seq_Lat_t_ -{ - Seq_Lat_t * pNext; // the next Lat in the ring - Seq_Lat_t * pPrev; // the prev Lat in the ring - Abc_Obj_t * pLatch; // the real latch corresponding to Lat -}; - -// representation of latch on the edge -typedef struct Seq_RetEdge_t_ Seq_RetEdge_t; -struct Seq_RetEdge_t_ // 1 word -{ - unsigned iNode : 24; // the ID of the node - unsigned iEdge : 1; // the edge of the node - unsigned iLatch : 7; // the latch number counting from the node -}; - -// representation of one retiming step -typedef struct Seq_RetStep_t_ Seq_RetStep_t; -struct Seq_RetStep_t_ // 1 word -{ - unsigned iNode : 24; // the ID of the node - unsigned nLatches : 8; // the number of latches to retime -}; - -// representation of one mapping match -typedef struct Seq_Match_t_ Seq_Match_t; -struct Seq_Match_t_ // 3 words -{ - Abc_Obj_t * pAnd; // the AND gate used in the mapping - Cut_Cut_t * pCut; // the cut used to map it - Map_Super_t * pSuper; // the supergate used to implement the cut - unsigned fCompl : 1; // the polarity of the AND gate - unsigned fCutInv : 1; // the polarity of the cut - unsigned PolUse : 2; // the polarity use of this node - unsigned uPhase : 14; // the phase assignment at the boundary - unsigned uPhaseR : 14; // the real phase assignment at the boundary -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// transforming retedges into ints and back -static inline int Seq_RetEdge2Int( Seq_RetEdge_t Val ) { return *((int *)&Val); } -static inline Seq_RetEdge_t Seq_Int2RetEdge( int Num ) { return *((Seq_RetEdge_t *)&Num); } -// transforming retsteps into ints and back -static inline int Seq_RetStep2Int( Seq_RetStep_t Val ) { return *((int *)&Val); } -static inline Seq_RetStep_t Seq_Int2RetStep( int Num ) { return *((Seq_RetStep_t *)&Num); } - -// manipulating the number of latches on each edge -static inline Vec_Int_t * Seq_ObjLNums( Abc_Obj_t * pObj ) { return ((Abc_Seq_t*)pObj->pNtk->pManFunc)->vNums; } -static inline int Seq_ObjFaninL( Abc_Obj_t * pObj, int i ) { return Vec_IntEntry(Seq_ObjLNums(pObj), 2*pObj->Id + i); } -static inline int Seq_ObjFaninL0( Abc_Obj_t * pObj ) { return Vec_IntEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 0); } -static inline int Seq_ObjFaninL1( Abc_Obj_t * pObj ) { return Vec_IntEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 1); } -static inline void Seq_ObjSetFaninL( Abc_Obj_t * pObj, int i, int nLats ) { Vec_IntWriteEntry(Seq_ObjLNums(pObj), 2*pObj->Id + i, nLats); } -static inline void Seq_ObjSetFaninL0( Abc_Obj_t * pObj, int nLats ) { Vec_IntWriteEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 0, nLats); } -static inline void Seq_ObjSetFaninL1( Abc_Obj_t * pObj, int nLats ) { Vec_IntWriteEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 1, nLats); } -static inline void Seq_ObjAddFaninL( Abc_Obj_t * pObj, int i, int nLats ) { Vec_IntAddToEntry(Seq_ObjLNums(pObj), 2*pObj->Id + i, nLats); } -static inline void Seq_ObjAddFaninL0( Abc_Obj_t * pObj, int nLats ) { Vec_IntAddToEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 0, nLats); } -static inline void Seq_ObjAddFaninL1( Abc_Obj_t * pObj, int nLats ) { Vec_IntAddToEntry(Seq_ObjLNums(pObj), 2*pObj->Id + 1, nLats); } -static inline int Seq_ObjFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { return Seq_ObjFaninL( pFanout, Abc_ObjFanoutEdgeNum(pObj,pFanout) ); } -static inline void Seq_ObjSetFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats ) { Seq_ObjSetFaninL( pFanout, Abc_ObjFanoutEdgeNum(pObj,pFanout), nLats ); } -static inline void Seq_ObjAddFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats ) { Seq_ObjAddFaninL( pFanout, Abc_ObjFanoutEdgeNum(pObj,pFanout), nLats ); } -static inline int Seq_ObjFaninLMin( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return ABC_MIN( Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj) ); } -static inline int Seq_ObjFaninLMax( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return ABC_MAX( Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj) ); } - -// reading l-values and lags -static inline Vec_Int_t * Seq_NodeLValues( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLValues; } -static inline Vec_Int_t * Seq_NodeLValuesN( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLValuesN; } -static inline int Seq_NodeGetLValue( Abc_Obj_t * pNode ) { return Vec_IntEntry( Seq_NodeLValues(pNode), (pNode)->Id ); } -static inline void Seq_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { Vec_IntWriteEntry( Seq_NodeLValues(pNode), (pNode)->Id, Value ); } -static inline float Seq_NodeGetLValueP( Abc_Obj_t * pNode ) { return Abc_Int2Float( Vec_IntEntry( Seq_NodeLValues(pNode), (pNode)->Id ) ); } -static inline float Seq_NodeGetLValueN( Abc_Obj_t * pNode ) { return Abc_Int2Float( Vec_IntEntry( Seq_NodeLValuesN(pNode), (pNode)->Id ) ); } -static inline void Seq_NodeSetLValueP( Abc_Obj_t * pNode, float Value ) { Vec_IntWriteEntry( Seq_NodeLValues(pNode), (pNode)->Id, Abc_Float2Int(Value) ); } -static inline void Seq_NodeSetLValueN( Abc_Obj_t * pNode, float Value ) { Vec_IntWriteEntry( Seq_NodeLValuesN(pNode), (pNode)->Id, Abc_Float2Int(Value) ); } - -// reading area flows -static inline Vec_Int_t * Seq_NodeFlow( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vAFlows; } -static inline float Seq_NodeGetFlow( Abc_Obj_t * pNode ) { return Abc_Int2Float( Vec_IntEntry( Seq_NodeFlow(pNode), (pNode)->Id ) ); } -static inline void Seq_NodeSetFlow( Abc_Obj_t * pNode, float Value ) { Vec_IntWriteEntry( Seq_NodeFlow(pNode), (pNode)->Id, Abc_Float2Int(Value) ); } - -// reading the contents of the lat -static inline Abc_InitType_t Seq_LatInit( Seq_Lat_t * pLat ) { return ((unsigned)pLat->pPrev) & 3; } -static inline Seq_Lat_t * Seq_LatNext( Seq_Lat_t * pLat ) { return pLat->pNext; } -static inline Seq_Lat_t * Seq_LatPrev( Seq_Lat_t * pLat ) { return (void *)(((unsigned)pLat->pPrev) & (SEQ_FULL_MASK << 2)); } - -// setting the contents of the lat -static inline void Seq_LatSetInit( Seq_Lat_t * pLat, Abc_InitType_t Init ) { pLat->pPrev = (void *)( (3 & Init) | (((unsigned)pLat->pPrev) & (SEQ_FULL_MASK << 2)) ); } -static inline void Seq_LatSetNext( Seq_Lat_t * pLat, Seq_Lat_t * pNext ) { pLat->pNext = pNext; } -static inline void Seq_LatSetPrev( Seq_Lat_t * pLat, Seq_Lat_t * pPrev ) { Abc_InitType_t Init = Seq_LatInit(pLat); pLat->pPrev = pPrev; Seq_LatSetInit(pLat, Init); } - -// accessing retiming lags -static inline Cut_Man_t * Seq_NodeCutMan( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->pCutMan; } -static inline Vec_Str_t * Seq_NodeLags( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLags; } -static inline Vec_Str_t * Seq_NodeLagsN( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vLagsN; } -static inline char Seq_NodeGetLag( Abc_Obj_t * pNode ) { return Vec_StrEntry( Seq_NodeLags(pNode), (pNode)->Id ); } -static inline char Seq_NodeGetLagN( Abc_Obj_t * pNode ) { return Vec_StrEntry( Seq_NodeLagsN(pNode), (pNode)->Id ); } -static inline void Seq_NodeSetLag( Abc_Obj_t * pNode, char Value ) { Vec_StrWriteEntry( Seq_NodeLags(pNode), (pNode)->Id, (Value) ); } -static inline void Seq_NodeSetLagN( Abc_Obj_t * pNode, char Value ) { Vec_StrWriteEntry( Seq_NodeLagsN(pNode), (pNode)->Id, (Value) ); } -static inline int Seq_NodeComputeLag( int LValue, int Fi ) { return (LValue + 1024*Fi)/Fi - 1024 - (int)(LValue % Fi == 0); } -static inline int Seq_NodeComputeLagFloat( float LValue, float Fi ) { return ((int)ceil(LValue/Fi)) - 1; } - -// phase usage -static inline Vec_Str_t * Seq_NodeUses( Abc_Obj_t * pNode ) { return ((Abc_Seq_t *)(pNode)->pNtk->pManFunc)->vUses; } -static inline char Seq_NodeGetUses( Abc_Obj_t * pNode ) { return Vec_StrEntry( Seq_NodeUses(pNode), (pNode)->Id ); } -static inline void Seq_NodeSetUses( Abc_Obj_t * pNode, char Value ) { Vec_StrWriteEntry( Seq_NodeUses(pNode), (pNode)->Id, (Value) ); } - -// accessing initial states -static inline Vec_Ptr_t * Seq_NodeLats( Abc_Obj_t * pObj ) { return ((Abc_Seq_t*)pObj->pNtk->pManFunc)->vInits; } -static inline Seq_Lat_t * Seq_NodeGetRing( Abc_Obj_t * pObj, int Edge ) { return Vec_PtrEntry( Seq_NodeLats(pObj), (pObj->Id<<1)+Edge ); } -static inline void Seq_NodeSetRing( Abc_Obj_t * pObj, int Edge, Seq_Lat_t * pLat ) { Vec_PtrWriteEntry( Seq_NodeLats(pObj), (pObj->Id<<1)+Edge, pLat ); } -static inline Seq_Lat_t * Seq_NodeCreateLat( Abc_Obj_t * pObj ) { Seq_Lat_t * p = (Seq_Lat_t *)Extra_MmFixedEntryFetch( ((Abc_Seq_t*)pObj->pNtk->pManFunc)->pMmInits ); p->pNext = p->pPrev = NULL; p->pLatch = NULL; return p; } -static inline void Seq_NodeRecycleLat( Abc_Obj_t * pObj, Seq_Lat_t * pLat ) { Extra_MmFixedEntryRecycle( ((Abc_Seq_t*)pObj->pNtk->pManFunc)->pMmInits, (char *)pLat ); } - -// getting hold of the structure storing initial states of the latches -static inline Seq_Lat_t * Seq_NodeGetLatFirst( Abc_Obj_t * pObj, int Edge ) { return Seq_NodeGetRing(pObj, Edge); } -static inline Seq_Lat_t * Seq_NodeGetLatLast( Abc_Obj_t * pObj, int Edge ) { return Seq_LatPrev( Seq_NodeGetRing(pObj, Edge) ); } -static inline Seq_Lat_t * Seq_NodeGetLat( Abc_Obj_t * pObj, int Edge, int iLat ) { int c; Seq_Lat_t * pLat = Seq_NodeGetRing(pObj, Edge); for ( c = 0; c != iLat; c++ ) pLat = pLat->pNext; return pLat; } -static inline int Seq_NodeCountLats( Abc_Obj_t * pObj, int Edge ) { int c; Seq_Lat_t * pLat, * pRing = Seq_NodeGetRing(pObj, Edge); if ( pRing == NULL ) return 0; for ( c = 0, pLat = pRing; !c || pLat != pRing; c++ ) pLat = pLat->pNext; return c; } -static inline void Seq_NodeCleanLats( Abc_Obj_t * pObj, int Edge ) { int c; Seq_Lat_t * pLat, * pRing = Seq_NodeGetRing(pObj, Edge); if ( pRing == NULL ) return ; for ( c = 0, pLat = pRing; !c || pLat != pRing; c++ ) pLat->pLatch = NULL, pLat = pLat->pNext; return; } - -// getting/setting initial states of the latches -static inline Abc_InitType_t Seq_NodeGetInitOne( Abc_Obj_t * pObj, int Edge, int iLat ) { return Seq_LatInit( Seq_NodeGetLat(pObj, Edge, iLat) ); } -static inline Abc_InitType_t Seq_NodeGetInitFirst( Abc_Obj_t * pObj, int Edge ) { return Seq_LatInit( Seq_NodeGetLatFirst(pObj, Edge) ); } -static inline Abc_InitType_t Seq_NodeGetInitLast( Abc_Obj_t * pObj, int Edge ) { return Seq_LatInit( Seq_NodeGetLatLast(pObj, Edge) ); } -static inline void Seq_NodeSetInitOne( Abc_Obj_t * pObj, int Edge, int iLat, Abc_InitType_t Init ) { Seq_LatSetInit( Seq_NodeGetLat(pObj, Edge, iLat), Init ); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== seqAigIter.c =============================================================*/ -extern int Seq_AigRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose ); -extern int Seq_NtkImplementRetiming( Abc_Ntk_t * pNtk, Vec_Str_t * vLags, int fVerbose ); -/*=== seqFpgaIter.c ============================================================*/ -extern int Seq_FpgaMappingDelays( Abc_Ntk_t * pNtk, int fVerbose ); -extern int Seq_FpgaNodeUpdateLValue( Abc_Obj_t * pObj, int Fi ); -/*=== seqMapIter.c ============================================================*/ -extern int Seq_MapRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose ); -/*=== seqRetIter.c =============================================================*/ -extern int Seq_NtkRetimeDelayLags( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtk, int fVerbose ); -/*=== seqLatch.c ===============================================================*/ -extern void Seq_NodeInsertFirst( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init ); -extern void Seq_NodeInsertLast( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init ); -extern Abc_InitType_t Seq_NodeDeleteFirst( Abc_Obj_t * pObj, int Edge ); -extern Abc_InitType_t Seq_NodeDeleteLast( Abc_Obj_t * pObj, int Edge ); -/*=== seqUtil.c ================================================================*/ -extern int Seq_NtkLevelMax( Abc_Ntk_t * pNtk ); -extern int Seq_ObjFanoutLMax( Abc_Obj_t * pObj ); -extern int Seq_ObjFanoutLMin( Abc_Obj_t * pObj ); -extern int Seq_ObjFanoutLSum( Abc_Obj_t * pObj ); -extern int Seq_ObjFaninLSum( Abc_Obj_t * pObj ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/seq/seqLatch.c b/src/base/seq/seqLatch.c deleted file mode 100644 index cb3e1e36..00000000 --- a/src/base/seq/seqLatch.c +++ /dev/null @@ -1,223 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqLatch.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [Manipulation of latch data structures representing initial states.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqLatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Insert the first Lat on the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NodeInsertFirst( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init ) -{ - Seq_Lat_t * pLat, * pRing, * pPrev; - pRing = Seq_NodeGetRing( pObj, Edge ); - pLat = Seq_NodeCreateLat( pObj ); - if ( pRing == NULL ) - { - Seq_LatSetPrev( pLat, pLat ); - Seq_LatSetNext( pLat, pLat ); - Seq_NodeSetRing( pObj, Edge, pLat ); - } - else - { - pPrev = Seq_LatPrev( pRing ); - Seq_LatSetPrev( pLat, pPrev ); - Seq_LatSetNext( pPrev, pLat ); - Seq_LatSetPrev( pRing, pLat ); - Seq_LatSetNext( pLat, pRing ); - Seq_NodeSetRing( pObj, Edge, pLat ); // rotate the ring to make pLat the first - } - Seq_LatSetInit( pLat, Init ); - Seq_ObjAddFaninL( pObj, Edge, 1 ); - assert( pLat->pLatch == NULL ); -} - -/**Function************************************************************* - - Synopsis [Insert the last Lat on the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NodeInsertLast( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init ) -{ - Seq_Lat_t * pLat, * pRing, * pPrev; - pRing = Seq_NodeGetRing( pObj, Edge ); - pLat = Seq_NodeCreateLat( pObj ); - if ( pRing == NULL ) - { - Seq_LatSetPrev( pLat, pLat ); - Seq_LatSetNext( pLat, pLat ); - Seq_NodeSetRing( pObj, Edge, pLat ); - } - else - { - pPrev = Seq_LatPrev( pRing ); - Seq_LatSetPrev( pLat, pPrev ); - Seq_LatSetNext( pPrev, pLat ); - Seq_LatSetPrev( pRing, pLat ); - Seq_LatSetNext( pLat, pRing ); - } - Seq_LatSetInit( pLat, Init ); - Seq_ObjAddFaninL( pObj, Edge, 1 ); -} - -/**Function************************************************************* - - Synopsis [Delete the first Lat on the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_InitType_t Seq_NodeDeleteFirst( Abc_Obj_t * pObj, int Edge ) -{ - Abc_InitType_t Init; - Seq_Lat_t * pLat, * pRing, * pPrev, * pNext; - pRing = Seq_NodeGetRing( pObj, Edge ); - pLat = pRing; // consider the first latch - if ( pLat->pNext == pLat ) - Seq_NodeSetRing( pObj, Edge, NULL ); - else - { - pPrev = Seq_LatPrev( pLat ); - pNext = Seq_LatNext( pLat ); - Seq_LatSetPrev( pNext, pPrev ); - Seq_LatSetNext( pPrev, pNext ); - Seq_NodeSetRing( pObj, Edge, pNext ); // rotate the ring - } - Init = Seq_LatInit( pLat ); - Seq_NodeRecycleLat( pObj, pLat ); - Seq_ObjAddFaninL( pObj, Edge, -1 ); - return Init; -} - -/**Function************************************************************* - - Synopsis [Delete the last Lat on the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_InitType_t Seq_NodeDeleteLast( Abc_Obj_t * pObj, int Edge ) -{ - Abc_InitType_t Init; - Seq_Lat_t * pLat, * pRing, * pPrev, * pNext; - pRing = Seq_NodeGetRing( pObj, Edge ); - pLat = Seq_LatPrev( pRing ); // consider the last latch - if ( pLat->pNext == pLat ) - Seq_NodeSetRing( pObj, Edge, NULL ); - else - { - pPrev = Seq_LatPrev( pLat ); - pNext = Seq_LatNext( pLat ); - Seq_LatSetPrev( pNext, pPrev ); - Seq_LatSetNext( pPrev, pNext ); - } - Init = Seq_LatInit( pLat ); - Seq_NodeRecycleLat( pObj, pLat ); - Seq_ObjAddFaninL( pObj, Edge, -1 ); - return Init; -} - -/**Function************************************************************* - - Synopsis [Insert the last Lat on the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NodeDupLats( Abc_Obj_t * pObjNew, Abc_Obj_t * pObj, int Edge ) -{ - Seq_Lat_t * pRing, * pLat; - int i, nLatches; - pRing = Seq_NodeGetRing( pObj, Edge ); - if ( pRing == NULL ) - return; - nLatches = Seq_NodeCountLats( pObj, Edge ); - for ( i = 0, pLat = pRing; i < nLatches; i++, pLat = pLat->pNext ) - Seq_NodeInsertLast( pObjNew, Edge, Seq_LatInit(pLat) ); -} - -/**Function************************************************************* - - Synopsis [Insert the last Lat on the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NodeCompareLats( Abc_Obj_t * pObj1, int Edge1, Abc_Obj_t * pObj2, int Edge2 ) -{ - Seq_Lat_t * pRing1, * pRing2, * pLat1, * pLat2; - int i, nLatches1, nLatches2; - - nLatches1 = Seq_NodeCountLats( pObj1, Edge1 ); - nLatches2 = Seq_NodeCountLats( pObj2, Edge2 ); - if ( nLatches1 != nLatches2 ) - return 0; - - pRing1 = Seq_NodeGetRing( pObj1, Edge1 ); - pRing2 = Seq_NodeGetRing( pObj2, Edge2 ); - for ( i = 0, pLat1 = pRing1, pLat2 = pRing2; i < nLatches1; i++, pLat1 = pLat1->pNext, pLat2 = pLat2->pNext ) - if ( Seq_LatInit(pLat1) != Seq_LatInit(pLat2) ) - return 0; - - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/seq/seqMan.c b/src/base/seq/seqMan.c deleted file mode 100644 index bdfb2630..00000000 --- a/src/base/seq/seqMan.c +++ /dev/null @@ -1,133 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [Manager of sequential AIG containing.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates sequential AIG manager.] - - Description [The manager contains all the data structures needed to - represent sequential AIG and compute stand-alone retiming as well as - the integrated mapping/retiming of the sequential AIG.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Seq_t * Seq_Create( Abc_Ntk_t * pNtk ) -{ - Abc_Seq_t * p; - // start the manager - p = ALLOC( Abc_Seq_t, 1 ); - memset( p, 0, sizeof(Abc_Seq_t) ); - p->pNtk = pNtk; - p->nSize = 1000; - p->nMaxIters = 15; - p->pMmInits = Extra_MmFixedStart( sizeof(Seq_Lat_t) ); - p->fEpsilon = (float)0.001; - // create internal data structures - p->vNums = Vec_IntStart( 2 * p->nSize ); - p->vInits = Vec_PtrStart( 2 * p->nSize ); - p->vLValues = Vec_IntStart( p->nSize ); - p->vLags = Vec_StrStart( p->nSize ); - p->vLValuesN = Vec_IntStart( p->nSize ); - p->vAFlows = Vec_IntStart( p->nSize ); - p->vLagsN = Vec_StrStart( p->nSize ); - p->vUses = Vec_StrStart( p->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates sequential AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_Resize( Abc_Seq_t * p, int nMaxId ) -{ - if ( p->nSize > nMaxId ) - return; - p->nSize = nMaxId + 1; - Vec_IntFill( p->vNums, 2 * p->nSize, 0 ); - Vec_PtrFill( p->vInits, 2 * p->nSize, NULL ); - Vec_IntFill( p->vLValues, p->nSize, 0 ); - Vec_StrFill( p->vLags, p->nSize, 0 ); - Vec_IntFill( p->vLValuesN, p->nSize, 0 ); - Vec_IntFill( p->vAFlows, p->nSize, 0 ); - Vec_StrFill( p->vLagsN, p->nSize, 0 ); - Vec_StrFill( p->vUses, p->nSize, 0 ); -} - - -/**Function************************************************************* - - Synopsis [Deallocates sequential AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_Delete( Abc_Seq_t * p ) -{ - if ( p->fStandCells && p->vMapAnds ) - { - void * pVoid; int i; - Vec_PtrForEachEntry( p->vMapAnds, pVoid, i ) - free( pVoid ); - } - if ( p->vMapDelays ) Vec_VecFree( p->vMapDelays ); // the nodes used in the mapping - if ( p->vMapFanins ) Vec_VecFree( p->vMapFanins ); // the cuts used in the mapping - if ( p->vMapAnds ) Vec_PtrFree( p->vMapAnds ); // the nodes used in the mapping - if ( p->vMapCuts ) Vec_VecFree( p->vMapCuts ); // the cuts used in the mapping - if ( p->vLValues ) Vec_IntFree( p->vLValues ); // the arrival times (L-Values of nodes) - if ( p->vLags ) Vec_StrFree( p->vLags ); // the lags of the mapped nodes - if ( p->vLValuesN ) Vec_IntFree( p->vLValuesN ); // the arrival times (L-Values of nodes) - if ( p->vAFlows ) Vec_IntFree( p->vAFlows ); // the arrival times (L-Values of nodes) - if ( p->vLagsN ) Vec_StrFree( p->vLagsN ); // the lags of the mapped nodes - if ( p->vUses ) Vec_StrFree( p->vUses ); // the uses of phases - if ( p->vInits ) Vec_PtrFree( p->vInits ); // the initial values of the latches - if ( p->vNums ) Vec_IntFree( p->vNums ); // the numbers of latches - Extra_MmFixedStop( p->pMmInits ); - free( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/seq/seqMapCore.c b/src/base/seq/seqMapCore.c deleted file mode 100644 index c465f31f..00000000 --- a/src/base/seq/seqMapCore.c +++ /dev/null @@ -1,652 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqMapCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [The core of SC mapping/retiming package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqMapCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" -#include "main.h" -#include "mio.h" -#include "mapper.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern Abc_Ntk_t * Seq_NtkMapDup( Abc_Ntk_t * pNtk ); -extern int Seq_NtkMapInitCompatible( Abc_Ntk_t * pNtk, int fVerbose ); -extern Abc_Ntk_t * Seq_NtkSeqMapMapped( Abc_Ntk_t * pNtk ); - -static int Seq_MapMappingCount( Abc_Ntk_t * pNtk ); -static int Seq_MapMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves ); -static Abc_Obj_t * Seq_MapMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int fCompl, int LagCut, Vec_Ptr_t * vLeaves, unsigned uPhase ); -static DdNode * Seq_MapMappingBdd_rec( DdManager * dd, Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves ); -static void Seq_MapMappingEdges_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, Vec_Ptr_t * vLeaves, Vec_Vec_t * vMapEdges ); -static void Seq_MapMappingConnect_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ); -static DdNode * Seq_MapMappingConnectBdd_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs Map mapping and retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Seq_MapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Abc_Ntk_t * pNtkNew; - Abc_Ntk_t * pNtkMap; - int RetValue; - - // derive the supergate library - if ( Abc_FrameReadLibSuper() == NULL && Abc_FrameReadLibGen() ) - { - printf( "A simple supergate library is derived from gate library \"%s\".\n", - Mio_LibraryReadName(Abc_FrameReadLibGen()) ); - Map_SuperLibDeriveFromGenlib( Abc_FrameReadLibGen() ); - } - p->pSuperLib = Abc_FrameReadLibSuper(); - p->nVarsMax = Map_SuperLibReadVarsMax(p->pSuperLib); - p->nMaxIters = nMaxIters; - p->fStandCells = 1; - - // find the best mapping and retiming for all nodes (p->vLValues, p->vBestCuts, p->vLags) - if ( !Seq_MapRetimeDelayLags( pNtk, fVerbose ) ) - return NULL; - if ( RetValue = Abc_NtkGetChoiceNum(pNtk) ) - { - printf( "The network has %d choices. The resulting network is not derived (this is temporary).\n", RetValue ); - printf( "The mininum clock period computed is %5.2f.\n", p->FiBestFloat ); - return NULL; - } - printf( "The mininum clock period computed is %5.2f.\n", p->FiBestFloat ); - printf( "The resulting network is derived as BDD logic network (this is temporary).\n" ); - - // duplicate the nodes contained in multiple cuts - pNtkNew = Seq_NtkMapDup( pNtk ); - - // implement the retiming - RetValue = Seq_NtkImplementRetiming( pNtkNew, ((Abc_Seq_t *)pNtkNew->pManFunc)->vLags, fVerbose ); - if ( RetValue == 0 ) - printf( "Retiming completed but initial state computation has failed.\n" ); - - // check the compatibility of initial states computed - if ( RetValue = Seq_NtkMapInitCompatible( pNtkNew, fVerbose ) ) - printf( "The number of LUTs with incompatible edges = %d.\n", RetValue ); -// return pNtkNew; - - // create the final mapped network - pNtkMap = Seq_NtkSeqMapMapped( pNtkNew ); - Abc_NtkDelete( pNtkNew ); - return pNtkMap; -} - -/**Function************************************************************* - - Synopsis [Derives the network by duplicating some of the nodes.] - - Description [Information about mapping is given as mapping nodes (p->vMapAnds) - and best cuts for each node (p->vMapCuts).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Seq_NtkMapDup( Abc_Ntk_t * pNtk ) -{ - Abc_Seq_t * pNew, * p = pNtk->pManFunc; - Seq_Match_t * pMatch; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFanin, * pFaninNew, * pLeaf; - Vec_Ptr_t * vLeaves; - unsigned SeqEdge; - int i, k, nObjsNew, Lag; - - assert( Abc_NtkIsSeq(pNtk) ); - - // start the expanded network - pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); - Abc_NtkCleanNext(pNtk); - - // start the new sequential AIG manager - nObjsNew = 1 + Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk) + Seq_MapMappingCount(pNtk); - Seq_Resize( pNtkNew->pManFunc, nObjsNew ); - - // duplicate the nodes in the mapping - Vec_PtrForEachEntry( p->vMapAnds, pMatch, i ) - { -// Abc_NtkDupObj( pNtkNew, pMatch->pAnd ); - if ( !pMatch->fCompl ) - pMatch->pAnd->pCopy = Abc_NtkCreateNode( pNtkNew ); - else - pMatch->pAnd->pNext = Abc_NtkCreateNode( pNtkNew ); - } - - // compute the real phase assignment - Vec_PtrForEachEntry( p->vMapAnds, pMatch, i ) - { - pMatch->uPhaseR = 0; - // get the leaves of the cut - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - // convert the leaf nodes - Vec_PtrForEachEntry( vLeaves, pLeaf, k ) - { - SeqEdge = (unsigned)pLeaf; - pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - - // set the phase - if ( pMatch->uPhase & (1 << k) ) // neg is required - { - if ( pLeaf->pNext ) // neg is available - pMatch->uPhaseR |= (1 << k); // neg is used -// else -// Seq_NodeSetLag( pLeaf, Seq_NodeGetLagN(pLeaf) ); - } - else // pos is required - { - if ( pLeaf->pCopy == NULL ) // pos is not available - pMatch->uPhaseR |= (1 << k); // neg is used -// else -// Seq_NodeSetLagN( pLeaf, Seq_NodeGetLag(pLeaf) ); - } - } - } - - - // recursively construct the internals of each node - Vec_PtrForEachEntry( p->vMapAnds, pMatch, i ) - { -// if ( pMatch->pSuper == NULL ) -// { -// int x = 0; -// } - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - if ( !pMatch->fCompl ) - Seq_MapMappingBuild_rec( pNtkNew, pNtk, pMatch->pAnd->Id << 8, 1, pMatch->fCompl, Seq_NodeGetLag(pMatch->pAnd), vLeaves, pMatch->uPhaseR ); - else - Seq_MapMappingBuild_rec( pNtkNew, pNtk, pMatch->pAnd->Id << 8, 1, pMatch->fCompl, Seq_NodeGetLagN(pMatch->pAnd), vLeaves, pMatch->uPhaseR ); - } - assert( nObjsNew == pNtkNew->nObjs ); - - // set the POs -// Abc_NtkFinalize( pNtk, pNtkNew ); - Abc_NtkForEachPo( pNtk, pObj, i ) - { - pFanin = Abc_ObjFanin0(pObj); - if ( Abc_ObjFaninC0(pObj) ) - pFaninNew = pFanin->pNext ? pFanin->pNext : pFanin->pCopy; - else - pFaninNew = pFanin->pCopy ? pFanin->pCopy : pFanin->pNext; - pFaninNew = Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC0(pObj) ); - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - } - - // duplicate the latches on the PO edges - Abc_NtkForEachPo( pNtk, pObj, i ) - Seq_NodeDupLats( pObj->pCopy, pObj, 0 ); - - // transfer the mapping info to the new manager - Vec_PtrForEachEntry( p->vMapAnds, pMatch, i ) - { - // get the leaves of the cut - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - // convert the leaf nodes - Vec_PtrForEachEntry( vLeaves, pLeaf, k ) - { - SeqEdge = (unsigned)pLeaf; - pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - -// Lag = (SeqEdge & 255) + Seq_NodeGetLag(pMatch->pAnd) - Seq_NodeGetLag(pLeaf); - Lag = (SeqEdge & 255) + - (pMatch->fCompl? Seq_NodeGetLagN(pMatch->pAnd) : Seq_NodeGetLag(pMatch->pAnd)) - - (((pMatch->uPhaseR & (1 << k)) > 0)? Seq_NodeGetLagN(pLeaf) : Seq_NodeGetLag(pLeaf) ); - - assert( Lag >= 0 ); - - // translate the old leaf into the leaf in the new network -// if ( pMatch->uPhase & (1 << k) ) // negative phase is required -// pFaninNew = pLeaf->pNext? pLeaf->pNext : pLeaf->pCopy; -// else // positive phase is required -// pFaninNew = pLeaf->pCopy? pLeaf->pCopy : pLeaf->pNext; - - // translate the old leaf into the leaf in the new network - if ( pMatch->uPhaseR & (1 << k) ) // negative phase is required - pFaninNew = pLeaf->pNext; - else // positive phase is required - pFaninNew = pLeaf->pCopy; - - Vec_PtrWriteEntry( vLeaves, k, (void *)((pFaninNew->Id << 8) | Lag) ); -// printf( "%d -> %d\n", pLeaf->Id, pLeaf->pCopy->Id ); - - // UPDATE PHASE!!! leaving only those bits that require inverters - } - // convert the root node -// Vec_PtrWriteEntry( p->vMapAnds, i, pObj->pCopy ); - pMatch->pAnd = pMatch->fCompl? pMatch->pAnd->pNext : pMatch->pAnd->pCopy; - } - pNew = pNtkNew->pManFunc; - pNew->nVarsMax = p->nVarsMax; - pNew->vMapAnds = p->vMapAnds; p->vMapAnds = NULL; - pNew->vMapCuts = p->vMapCuts; p->vMapCuts = NULL; - pNew->fStandCells = p->fStandCells; p->fStandCells = 0; - - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Seq_NtkMapDup(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Checks if the initial states are compatible.] - - Description [Checks of all the initial states on the fanins edges - of the cut have compatible number of latches and initial states. - If this is not true, then the mapped network with the does not have initial - state. Returns the number of LUTs with incompatible edges.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkMapInitCompatible( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Seq_Match_t * pMatch; - Abc_Obj_t * pAnd, * pLeaf, * pFanout0, * pFanout1; - Vec_Vec_t * vTotalEdges; - Vec_Ptr_t * vLeaves, * vEdges; - int i, k, m, Edge0, Edge1, nLatchAfter, nLatches1, nLatches2; - unsigned SeqEdge; - int CountBad = 0, CountAll = 0; - - vTotalEdges = Vec_VecStart( p->nVarsMax ); - // go through all the nodes (cuts) used in the mapping - Vec_PtrForEachEntry( p->vMapAnds, pMatch, i ) - { - pAnd = pMatch->pAnd; -// printf( "*** Node %d.\n", pAnd->Id ); - - // get the cut of this gate - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - - // get the edges pointing to the leaves - Vec_VecClear( vTotalEdges ); - Seq_MapMappingEdges_rec( pNtk, pAnd->Id << 8, NULL, vLeaves, vTotalEdges ); - - // for each leaf, consider its edges - Vec_PtrForEachEntry( vLeaves, pLeaf, k ) - { - SeqEdge = (unsigned)pLeaf; - pLeaf = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - nLatchAfter = SeqEdge & 255; - if ( nLatchAfter == 0 ) - continue; - - // go through the edges - vEdges = Vec_VecEntry( vTotalEdges, k ); - pFanout0 = NULL; - Vec_PtrForEachEntry( vEdges, pFanout1, m ) - { - Edge1 = Abc_ObjIsComplement(pFanout1); - pFanout1 = Abc_ObjRegular(pFanout1); -//printf( "Fanin = %d. Fanout = %d.\n", pLeaf->Id, pFanout1->Id ); - - // make sure this is the same fanin - if ( Edge1 ) - assert( pLeaf == Abc_ObjFanin1(pFanout1) ); - else - assert( pLeaf == Abc_ObjFanin0(pFanout1) ); - - // save the first one - if ( pFanout0 == NULL ) - { - pFanout0 = pFanout1; - Edge0 = Edge1; - continue; - } - // compare the rings - // if they have different number of latches, this is the bug - nLatches1 = Seq_NodeCountLats(pFanout0, Edge0); - nLatches2 = Seq_NodeCountLats(pFanout1, Edge1); - assert( nLatches1 == nLatches2 ); - assert( nLatches1 == nLatchAfter ); - assert( nLatches1 > 0 ); - - // if they have different initial states, this is the problem - if ( !Seq_NodeCompareLats(pFanout0, Edge0, pFanout1, Edge1) ) - { - CountBad++; - break; - } - CountAll++; - } - } - } - if ( fVerbose ) - printf( "The number of pairs of edges checked = %d.\n", CountAll ); - Vec_VecFree( vTotalEdges ); - return CountBad; -} - -/**Function************************************************************* - - Synopsis [Derives the final mapped network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Seq_NtkSeqMapMapped( Abc_Ntk_t * pNtk ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Seq_Match_t * pMatch; - Abc_Ntk_t * pNtkMap; - Vec_Ptr_t * vLeaves; - Abc_Obj_t * pObj, * pFaninNew; - Seq_Lat_t * pRing; - int i; - - assert( Abc_NtkIsSeq(pNtk) ); - - // start the network - pNtkMap = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_BDD ); - - // duplicate the nodes used in the mapping - Vec_PtrForEachEntry( p->vMapAnds, pMatch, i ) - pMatch->pAnd->pCopy = Abc_NtkCreateNode( pNtkMap ); - - // create and share the latches - Seq_NtkShareLatchesMapping( pNtkMap, pNtk, p->vMapAnds, 0 ); - - // connect the nodes - Vec_PtrForEachEntry( p->vMapAnds, pMatch, i ) - { - pObj = pMatch->pAnd; - // get the leaves of this gate - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - // get the BDD of the node - pObj->pCopy->pData = Seq_MapMappingConnectBdd_rec( pNtk, pObj->Id << 8, NULL, -1, pObj, vLeaves ); - Cudd_Ref( pObj->pCopy->pData ); - // complement the BDD of the cut if it came from the opposite polarity choice cut -// if ( Vec_StrEntry(p->vPhase, i) ) -// pObj->pCopy->pData = Cudd_Not( pObj->pCopy->pData ); - } - - // set the POs - Abc_NtkForEachPo( pNtk, pObj, i ) - { - if ( pRing = Seq_NodeGetRing(pObj,0) ) - pFaninNew = pRing->pLatch; - else - pFaninNew = Abc_ObjFanin0(pObj)->pCopy; - pFaninNew = Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC0(pObj) ); - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - } - - // add the latches and their names - Abc_NtkAddDummyBoxNames( pNtkMap ); - Abc_NtkOrderCisCos( pNtkMap ); - // fix the problem with complemented and duplicated CO edges - Abc_NtkLogicMakeSimpleCos( pNtkMap, 1 ); - // make the network minimum base - Abc_NtkMinimumBase( pNtkMap ); - if ( !Abc_NtkCheck( pNtkMap ) ) - fprintf( stdout, "Seq_NtkSeqFpgaMapped(): Network check has failed.\n" ); - return pNtkMap; -} - - - -/**Function************************************************************* - - Synopsis [Counts the number of nodes in the bag.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_MapMappingCount( Abc_Ntk_t * pNtk ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Vec_Ptr_t * vLeaves; - Seq_Match_t * pMatch; - int i, Counter = 0; - Vec_PtrForEachEntry( p->vMapAnds, pMatch, i ) - { - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - Counter += Seq_MapMappingCount_rec( pNtk, pMatch->pAnd->Id << 8, vLeaves ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of nodes in the bag.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_MapMappingCount_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Vec_Ptr_t * vLeaves ) -{ - Abc_Obj_t * pObj, * pLeaf; - unsigned SeqEdge0, SeqEdge1; - int Lag, i; - // get the object and the lag - pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - Lag = SeqEdge & 255; - // if the node is the fanin of the cut, return - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - if ( SeqEdge == (unsigned)pLeaf ) - return 0; - // continue unfolding - assert( Abc_AigNodeIsAnd(pObj) ); - // get new sequential edges - assert( Lag + Seq_ObjFaninL0(pObj) < 255 ); - assert( Lag + Seq_ObjFaninL1(pObj) < 255 ); - SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj); - SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj); - // call for the children - return 1 + Seq_MapMappingCount_rec( pNtk, SeqEdge0, vLeaves ) + - Seq_MapMappingCount_rec( pNtk, SeqEdge1, vLeaves ); -} - -/**Function************************************************************* - - Synopsis [Collects the edges pointing to the leaves of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Seq_MapMappingBuild_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, unsigned SeqEdge, int fTop, int fCompl, int LagCut, Vec_Ptr_t * vLeaves, unsigned uPhase ) -{ - Abc_Obj_t * pObj, * pObjNew, * pLeaf, * pFaninNew0, * pFaninNew1; - unsigned SeqEdge0, SeqEdge1; - int Lag, i; - // get the object and the lag - pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - Lag = SeqEdge & 255; - // if the node is the fanin of the cut, return - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - if ( SeqEdge == (unsigned)pLeaf ) - { -// if ( uPhase & (1 << i) ) // negative phase is required -// return pObj->pNext? pObj->pNext : pObj->pCopy; -// else // positive phase is required -// return pObj->pCopy? pObj->pCopy : pObj->pNext; - - if ( uPhase & (1 << i) ) // negative phase is required - return pObj->pNext; - else // positive phase is required - return pObj->pCopy; - } - // continue unfolding - assert( Abc_AigNodeIsAnd(pObj) ); - // get new sequential edges - assert( Lag + Seq_ObjFaninL0(pObj) < 255 ); - assert( Lag + Seq_ObjFaninL1(pObj) < 255 ); - SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj); - SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj); - // call for the children - pObjNew = fTop? (fCompl? pObj->pNext : pObj->pCopy) : Abc_NtkCreateNode( pNtkNew ); - // solve subproblems - pFaninNew0 = Seq_MapMappingBuild_rec( pNtkNew, pNtk, SeqEdge0, 0, fCompl, LagCut, vLeaves, uPhase ); - pFaninNew1 = Seq_MapMappingBuild_rec( pNtkNew, pNtk, SeqEdge1, 0, fCompl, LagCut, vLeaves, uPhase ); - // add the fanins to the node - Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew0, Abc_ObjFaninC0(pObj) ) ); - Abc_ObjAddFanin( pObjNew, Abc_ObjNotCond( pFaninNew1, Abc_ObjFaninC1(pObj) ) ); - Seq_NodeDupLats( pObjNew, pObj, 0 ); - Seq_NodeDupLats( pObjNew, pObj, 1 ); - // set the lag of the new node equal to the internal lag plus mapping/retiming lag - Seq_NodeSetLag( pObjNew, (char)(Lag + LagCut) ); -// Seq_NodeSetLag( pObjNew, (char)(Lag) ); - return pObjNew; -} - - -/**Function************************************************************* - - Synopsis [Collects the edges pointing to the leaves of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_MapMappingEdges_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, Vec_Ptr_t * vLeaves, Vec_Vec_t * vMapEdges ) -{ - Abc_Obj_t * pObj, * pLeaf; - unsigned SeqEdge0, SeqEdge1; - int Lag, i; - // get the object and the lag - pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - Lag = SeqEdge & 255; - // if the node is the fanin of the cut, return - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - { - if ( SeqEdge == (unsigned)pLeaf ) - { - assert( pPrev != NULL ); - Vec_VecPush( vMapEdges, i, pPrev ); - return; - } - } - // continue unfolding - assert( Abc_AigNodeIsAnd(pObj) ); - // get new sequential edges - assert( Lag + Seq_ObjFaninL0(pObj) < 255 ); - assert( Lag + Seq_ObjFaninL1(pObj) < 255 ); - SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj); - SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj); - // call for the children - Seq_MapMappingEdges_rec( pNtk, SeqEdge0, pObj , vLeaves, vMapEdges ); - Seq_MapMappingEdges_rec( pNtk, SeqEdge1, Abc_ObjNot(pObj), vLeaves, vMapEdges ); -} - -/**Function************************************************************* - - Synopsis [Collects the edges pointing to the leaves of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Seq_MapMappingConnectBdd_rec( Abc_Ntk_t * pNtk, unsigned SeqEdge, Abc_Obj_t * pPrev, int Edge, Abc_Obj_t * pRoot, Vec_Ptr_t * vLeaves ) -{ - Seq_Lat_t * pRing; - Abc_Obj_t * pObj, * pLeaf, * pFanin, * pFaninNew; - unsigned SeqEdge0, SeqEdge1; - DdManager * dd = pRoot->pCopy->pNtk->pManFunc; - DdNode * bFunc, * bFunc0, * bFunc1; - int Lag, i, k; - // get the object and the lag - pObj = Abc_NtkObj( pNtk, SeqEdge >> 8 ); - Lag = SeqEdge & 255; - // if the node is the fanin of the cut, add the connection and return - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - { - if ( SeqEdge == (unsigned)pLeaf ) - { - assert( pPrev != NULL ); - if ( pRing = Seq_NodeGetRing(pPrev,Edge) ) - pFaninNew = pRing->pLatch; - else - pFaninNew = Abc_ObjFanin(pPrev,Edge)->pCopy; - - // check if the root already has this fanin - Abc_ObjForEachFanin( pRoot->pCopy, pFanin, k ) - if ( pFanin == pFaninNew ) - return Cudd_bddIthVar( dd, k ); - Abc_ObjAddFanin( pRoot->pCopy, pFaninNew ); - return Cudd_bddIthVar( dd, k ); - } - } - // continue unfolding - assert( Abc_AigNodeIsAnd(pObj) ); - // get new sequential edges - assert( Lag + Seq_ObjFaninL0(pObj) < 255 ); - assert( Lag + Seq_ObjFaninL1(pObj) < 255 ); - SeqEdge0 = (Abc_ObjFanin0(pObj)->Id << 8) + Lag + Seq_ObjFaninL0(pObj); - SeqEdge1 = (Abc_ObjFanin1(pObj)->Id << 8) + Lag + Seq_ObjFaninL1(pObj); - // call for the children - bFunc0 = Seq_MapMappingConnectBdd_rec( pNtk, SeqEdge0, pObj, 0, pRoot, vLeaves ); Cudd_Ref( bFunc0 ); - bFunc1 = Seq_MapMappingConnectBdd_rec( pNtk, SeqEdge1, pObj, 1, pRoot, vLeaves ); Cudd_Ref( bFunc1 ); - bFunc0 = Cudd_NotCond( bFunc0, Abc_ObjFaninC0(pObj) ); - bFunc1 = Cudd_NotCond( bFunc1, Abc_ObjFaninC1(pObj) ); - // get the BDD of the node - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bFunc0 ); - Cudd_RecursiveDeref( dd, bFunc1 ); - // return the BDD - Cudd_Deref( bFunc ); - return bFunc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/seq/seqMapIter.c b/src/base/seq/seqMapIter.c deleted file mode 100644 index 30333cea..00000000 --- a/src/base/seq/seqMapIter.c +++ /dev/null @@ -1,623 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqMapIter.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [Iterative delay computation in SC mapping/retiming package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqMapIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" -#include "main.h" -#include "mio.h" -#include "mapperInt.h" - -// the internal procedures -static float Seq_MapRetimeDelayLagsInternal( Abc_Ntk_t * pNtk, int fVerbose ); -static float Seq_MapRetimeSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose ); -static int Seq_MapRetimeForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose ); -static int Seq_MapNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, float DelayInv ); -static float Seq_MapCollectNode_rec( Abc_Obj_t * pAnd, float FiBest, Vec_Ptr_t * vMapping, Vec_Vec_t * vMapCuts ); -static void Seq_MapCanonicizeTruthTables( Abc_Ntk_t * pNtk ); - -extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the retiming lags for FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_MapRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Cut_Params_t Params, * pParams = &Params; - Abc_Obj_t * pObj; - float TotalArea; - int i, clk; - - // set defaults for cut computation - memset( pParams, 0, sizeof(Cut_Params_t) ); - pParams->nVarsMax = p->nVarsMax; // the max cut size ("k" of the k-feasible cuts) - pParams->nKeepMax = 1000; // the max number of cuts kept at a node - pParams->fTruth = 1; // compute truth tables - pParams->fFilter = 1; // filter dominated cuts - pParams->fSeq = 1; // compute sequential cuts - pParams->fVerbose = fVerbose; // the verbosiness flag - - // compute the cuts -clk = clock(); - p->pCutMan = Abc_NtkSeqCuts( pNtk, pParams ); -p->timeCuts = clock() - clk; - if ( fVerbose ) - Cut_ManPrintStats( p->pCutMan ); - - // compute canonical forms of the truth tables of the cuts - Seq_MapCanonicizeTruthTables( pNtk ); - - // compute area flows -// Seq_MapComputeAreaFlows( pNtk, fVerbose ); - - // compute the delays -clk = clock(); - p->FiBestFloat = Seq_MapRetimeDelayLagsInternal( pNtk, fVerbose ); - if ( p->FiBestFloat == 0.0 ) - return 0; -p->timeDelay = clock() - clk; -/* - { - FILE * pTable; - pTable = fopen( "stats.txt", "a+" ); - fprintf( pTable, "%s ", pNtk->pName ); - fprintf( pTable, "%.2f ", p->FiBestFloat ); - fprintf( pTable, "%.2f ", (float)(p->timeCuts)/(float)(CLOCKS_PER_SEC) ); - fprintf( pTable, "%.2f ", (float)(p->timeDelay)/(float)(CLOCKS_PER_SEC) ); - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ - // clean the marks - Abc_NtkForEachObj( pNtk, pObj, i ) - assert( !pObj->fMarkA && !pObj->fMarkB ); - - // collect the nodes and cuts used in the mapping - p->vMapAnds = Vec_PtrAlloc( 1000 ); - p->vMapCuts = Vec_VecAlloc( 1000 ); - TotalArea = 0.0; - Abc_NtkForEachPo( pNtk, pObj, i ) - TotalArea += Seq_MapCollectNode_rec( Abc_ObjChild0(pObj), p->FiBestFloat, p->vMapAnds, p->vMapCuts ); - - // clean the marks - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->fMarkA = pObj->fMarkB = 0; - - if ( fVerbose ) - printf( "Total area = %6.2f.\n", TotalArea ); - - // remove the cuts - Cut_ManStop( p->pCutMan ); - p->pCutMan = NULL; - return 1; -} - -/**Function************************************************************* - - Synopsis [Retimes AIG for optimal delay using Pan's algorithm.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Seq_MapRetimeDelayLagsInternal( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Abc_Obj_t * pNode; - float FiMax, FiBest, Delta; - int i, RetValue; - char NodeLag; - - assert( Abc_NtkIsSeq( pNtk ) ); - - // assign the accuracy for min-period computation - Delta = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen()); - if ( Delta == 0.0 ) - { - Delta = Mio_LibraryReadDelayAnd2Max(Abc_FrameReadLibGen()); - if ( Delta == 0.0 ) - { - printf( "Cannot retime/map if the library does not have NAND2 or AND2.\n" ); - return 0.0; - } - } - - // get the upper bound on the clock period - FiMax = Delta * (5 + Seq_NtkLevelMax(pNtk)); - Delta /= 2; - - // make sure this clock period is feasible - if ( !Seq_MapRetimeForPeriod( pNtk, FiMax, fVerbose ) ) - { - Vec_StrFill( p->vLags, p->nSize, 0 ); - Vec_StrFill( p->vLagsN, p->nSize, 0 ); - printf( "Error: The upper bound on the clock period cannot be computed.\n" ); - printf( "The reason for this error may be the presence in the circuit of logic\n" ); - printf( "that is not reachable from the PIs. Mapping/retiming is not performed.\n" ); - return 0; - } - - // search for the optimal clock period between 0 and nLevelMax - FiBest = Seq_MapRetimeSearch_rec( pNtk, 0.0, FiMax, Delta, fVerbose ); - - // recompute the best l-values - RetValue = Seq_MapRetimeForPeriod( pNtk, FiBest, fVerbose ); - assert( RetValue ); - - // fix the problem with non-converged delays - Abc_AigForEachAnd( pNtk, pNode, i ) - { - if ( Seq_NodeGetLValueP(pNode) < -ABC_INFINITY/2 ) - Seq_NodeSetLValueP( pNode, 0 ); - if ( Seq_NodeGetLValueN(pNode) < -ABC_INFINITY/2 ) - Seq_NodeSetLValueN( pNode, 0 ); - } - - // write the retiming lags for both phases of each node - Vec_StrFill( p->vLags, p->nSize, 0 ); - Vec_StrFill( p->vLagsN, p->nSize, 0 ); - Abc_AigForEachAnd( pNtk, pNode, i ) - { - NodeLag = Seq_NodeComputeLagFloat( Seq_NodeGetLValueP(pNode), FiBest ); - Seq_NodeSetLag( pNode, NodeLag ); - NodeLag = Seq_NodeComputeLagFloat( Seq_NodeGetLValueN(pNode), FiBest ); - Seq_NodeSetLagN( pNode, NodeLag ); -//printf( "%6d=(%d,%d) ", pNode->Id, Seq_NodeGetLag(pNode), Seq_NodeGetLagN(pNode) ); -// if ( Seq_NodeGetLag(pNode) != Seq_NodeGetLagN(pNode) ) -// { -//printf( "%6d=(%d,%d) ", pNode->Id, Seq_NodeGetLag(pNode), Seq_NodeGetLagN(pNode) ); -// } - } -//printf( "\n\n" ); - - // print the result - if ( fVerbose ) - printf( "The best clock period after mapping/retiming is %6.2f.\n", FiBest ); - return FiBest; -} - -/**Function************************************************************* - - Synopsis [Performs binary search for the optimal clock period.] - - Description [Assumes that FiMin is infeasible while FiMax is feasible.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Seq_MapRetimeSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose ) -{ - float Median; - assert( FiMin < FiMax ); - if ( FiMin + Delta >= FiMax ) - return FiMax; - Median = FiMin + (FiMax - FiMin)/2; - if ( Seq_MapRetimeForPeriod( pNtk, Median, fVerbose ) ) - return Seq_MapRetimeSearch_rec( pNtk, FiMin, Median, Delta, fVerbose ); // Median is feasible - else - return Seq_MapRetimeSearch_rec( pNtk, Median, FiMax, Delta, fVerbose ); // Median is infeasible -} - -/**Function************************************************************* - - Synopsis [Returns 1 if retiming with this clock period is feasible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_MapRetimeForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Abc_Obj_t * pObj; - float DelayInv = Mio_LibraryReadDelayInvMax(Abc_FrameReadLibGen()); - int i, c, RetValue, fChange, Counter; - char * pReason = ""; - - // set l-values of all nodes to be minus infinity - Vec_IntFill( p->vLValues, p->nSize, Abc_Float2Int( (float)-ABC_INFINITY ) ); - Vec_IntFill( p->vLValuesN, p->nSize, Abc_Float2Int( (float)-ABC_INFINITY ) ); - Vec_StrFill( p->vUses, p->nSize, 0 ); - - // set l-values of constants and PIs - pObj = Abc_NtkObj( pNtk, 0 ); - Seq_NodeSetLValueP( pObj, 0.0 ); - Seq_NodeSetLValueN( pObj, 0.0 ); - Abc_NtkForEachPi( pNtk, pObj, i ) - { - Seq_NodeSetLValueP( pObj, 0.0 ); - Seq_NodeSetLValueN( pObj, DelayInv ); - } - - // update all values iteratively - Counter = 0; - for ( c = 0; c < p->nMaxIters; c++ ) - { - fChange = 0; - Abc_AigForEachAnd( pNtk, pObj, i ) - { - Counter++; - RetValue = Seq_MapNodeUpdateLValue( pObj, Fi, DelayInv ); - if ( RetValue == SEQ_UPDATE_YES ) - fChange = 1; - } - Abc_NtkForEachPo( pNtk, pObj, i ) - { - RetValue = Seq_MapNodeUpdateLValue( pObj, Fi, DelayInv ); - if ( RetValue == SEQ_UPDATE_FAIL ) - break; - } - if ( RetValue == SEQ_UPDATE_FAIL ) - break; - if ( fChange == 0 ) - break; -//printf( "\n\n" ); - } - if ( c == p->nMaxIters ) - { - RetValue = SEQ_UPDATE_FAIL; - pReason = "(timeout)"; - } - else - c++; - - // report the results - if ( fVerbose ) - { - if ( RetValue == SEQ_UPDATE_FAIL ) - printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason ); - else - printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter ); - } - return RetValue != SEQ_UPDATE_FAIL; -} - - - -/**Function************************************************************* - - Synopsis [Computes the l-value of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Seq_MapSuperGetArrival( Abc_Obj_t * pObj, float Fi, Seq_Match_t * pMatch, float DelayMax ) -{ - Abc_Seq_t * p = pObj->pNtk->pManFunc; - Abc_Obj_t * pFanin; - float lValueCur, lValueMax; - int i; - lValueMax = -ABC_INFINITY; - for ( i = pMatch->pCut->nLeaves - 1; i >= 0; i-- ) - { - // get the arrival time of the fanin - pFanin = Abc_NtkObj( pObj->pNtk, pMatch->pCut->pLeaves[i] >> 8 ); - if ( pMatch->uPhase & (1 << i) ) - lValueCur = Seq_NodeGetLValueN(pFanin) - Fi * (pMatch->pCut->pLeaves[i] & 255); - else - lValueCur = Seq_NodeGetLValueP(pFanin) - Fi * (pMatch->pCut->pLeaves[i] & 255); - // add the arrival time of this pin - if ( lValueMax < lValueCur + pMatch->pSuper->tDelaysR[i].Worst ) - lValueMax = lValueCur + pMatch->pSuper->tDelaysR[i].Worst; - if ( lValueMax < lValueCur + pMatch->pSuper->tDelaysF[i].Worst ) - lValueMax = lValueCur + pMatch->pSuper->tDelaysF[i].Worst; - if ( lValueMax > DelayMax + p->fEpsilon ) - return ABC_INFINITY; - } - return lValueMax; -} - -/**Function************************************************************* - - Synopsis [Computes the l-value of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Seq_MapNodeComputeCut( Abc_Obj_t * pObj, Cut_Cut_t * pCut, int fCompl, float Fi, Seq_Match_t * pMatchBest ) -{ - Seq_Match_t Match, * pMatchCur = &Match; - Abc_Seq_t * p = pObj->pNtk->pManFunc; - Map_Super_t * pSuper, * pSuperList; - unsigned uCanon[2]; - float lValueBest, lValueCur; - int i; - assert( pCut->nLeaves < 6 ); - // get the canonical truth table of this cut - uCanon[0] = uCanon[1] = (fCompl? pCut->uCanon0 : pCut->uCanon1); - if ( uCanon[0] == 0 || ~uCanon[0] == 0 ) - { - if ( pMatchBest ) - { - memset( pMatchBest, 0, sizeof(Seq_Match_t) ); - pMatchBest->pCut = pCut; - } - return (float)0.0; - } - // match the given phase of the cut - pSuperList = Map_SuperTableLookupC( p->pSuperLib, uCanon ); - // compute the arrival times of each supergate - lValueBest = ABC_INFINITY; - for ( pSuper = pSuperList; pSuper; pSuper = pSuper->pNext ) - { - // create the match - pMatchCur->pCut = pCut; - pMatchCur->pSuper = pSuper; - // get the phase - for ( i = 0; i < (int)pSuper->nPhases; i++ ) - { - pMatchCur->uPhase = (fCompl? pCut->Num0 : pCut->Num1) ^ pSuper->uPhases[i]; - // find the arrival time of this match - lValueCur = Seq_MapSuperGetArrival( pObj, Fi, pMatchCur, lValueBest ); - if ( lValueBest > lValueCur )//&& lValueCur > -ABC_INFINITY/2 ) - { - lValueBest = lValueCur; - if ( pMatchBest ) - *pMatchBest = *pMatchCur; - } - } - } -// assert( lValueBest < ABC_INFINITY/2 ); - return lValueBest; -} - -/**Function************************************************************* - - Synopsis [Computes the l-value of the node.] - - Description [The node can be internal or a PO.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Seq_MapNodeComputePhase( Abc_Obj_t * pObj, int fCompl, float Fi, Seq_Match_t * pMatchBest ) -{ - Seq_Match_t Match, * pMatchCur = &Match; - Cut_Cut_t * pList, * pCut; - float lValueBest, lValueCut; - // get the list of cuts - pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj ); - // get the arrival time of the best non-trivial cut - lValueBest = ABC_INFINITY; - for ( pCut = pList->pNext; pCut; pCut = pCut->pNext ) - { - lValueCut = Seq_MapNodeComputeCut( pObj, pCut, fCompl, Fi, pMatchBest? pMatchCur : NULL ); - if ( lValueBest > lValueCut ) - { - lValueBest = lValueCut; - if ( pMatchBest ) - *pMatchBest = *pMatchCur; - } - } -// assert( lValueBest < ABC_INFINITY/2 ); - return lValueBest; -} - -/**Function************************************************************* - - Synopsis [Computes the l-value of the node.] - - Description [The node can be internal or a PO.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_MapNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, float DelayInv ) -{ - Abc_Seq_t * p = pObj->pNtk->pManFunc; - Cut_Cut_t * pList; - char Use; - float lValueOld0, lValueOld1, lValue0, lValue1, lValue; - assert( !Abc_ObjIsPi(pObj) ); - assert( Abc_ObjFaninNum(pObj) > 0 ); - // consider the case of the PO - if ( Abc_ObjIsPo(pObj) ) - { - if ( Abc_ObjFaninC0(pObj) ) // PO requires negative polarity - lValue = Seq_NodeGetLValueN(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj); - else - lValue = Seq_NodeGetLValueP(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj); - return (lValue > Fi + p->fEpsilon)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO; - } - // get the cuts - pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj ); - if ( pList == NULL ) - return SEQ_UPDATE_NO; - // compute the arrival time of both phases - lValue0 = Seq_MapNodeComputePhase( pObj, 1, Fi, NULL ); - lValue1 = Seq_MapNodeComputePhase( pObj, 0, Fi, NULL ); - // consider the case when negative phase is too slow - if ( lValue0 > lValue1 + DelayInv + p->fEpsilon ) - lValue0 = lValue1 + DelayInv, Use = 2; - else if ( lValue1 > lValue0 + DelayInv + p->fEpsilon ) - lValue1 = lValue0 + DelayInv, Use = 1; - else - Use = 3; - // set the uses of the phases - Seq_NodeSetUses( pObj, Use ); - // get the old arrival times - lValueOld0 = Seq_NodeGetLValueN(pObj); - lValueOld1 = Seq_NodeGetLValueP(pObj); - // compare - if ( lValue0 <= lValueOld0 + p->fEpsilon && lValue1 <= lValueOld1 + p->fEpsilon ) - return SEQ_UPDATE_NO; - assert( lValue0 < ABC_INFINITY/2 ); - assert( lValue1 < ABC_INFINITY/2 ); - // update the values - if ( lValue0 > lValueOld0 + p->fEpsilon ) - Seq_NodeSetLValueN( pObj, lValue0 ); - if ( lValue1 > lValueOld1 + p->fEpsilon ) - Seq_NodeSetLValueP( pObj, lValue1 ); -//printf( "%6d=(%4.2f,%4.2f) ", pObj->Id, Seq_NodeGetLValueP(pObj), Seq_NodeGetLValueN(pObj) ); - return SEQ_UPDATE_YES; -} - - - -/**Function************************************************************* - - Synopsis [Derives the parameters of the best mapping/retiming for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Seq_MapCollectNode_rec( Abc_Obj_t * pAnd, float FiBest, Vec_Ptr_t * vMapping, Vec_Vec_t * vMapCuts ) -{ - Seq_Match_t * pMatch; - Abc_Obj_t * pFanin; - int k, fCompl, Use; - float AreaInv = Mio_LibraryReadAreaInv(Abc_FrameReadLibGen()); - float Area; - - // get the polarity of the node - fCompl = Abc_ObjIsComplement(pAnd); - pAnd = Abc_ObjRegular(pAnd); - - // skip visited nodes - if ( !fCompl ) - { // need the positive polarity - if ( pAnd->fMarkA ) - return 0.0; - pAnd->fMarkA = 1; - } - else - { // need the negative polarity - if ( pAnd->fMarkB ) - return 0.0; - pAnd->fMarkB = 1; - } - - // skip if this is a PI or a constant - if ( !Abc_AigNodeIsAnd(pAnd) ) - { - if ( Abc_ObjIsPi(pAnd) && fCompl ) - return AreaInv; - return 0.0; - } - - // check the uses of this node - Use = Seq_NodeGetUses( pAnd ); - if ( !fCompl && Use == 1 ) // the pos phase is required; only the neg phase is used - { - Area = Seq_MapCollectNode_rec( Abc_ObjNot(pAnd), FiBest, vMapping, vMapCuts ); - return Area + AreaInv; - } - if ( fCompl && Use == 2 ) // the neg phase is required; only the pos phase is used - { - Area = Seq_MapCollectNode_rec( pAnd, FiBest, vMapping, vMapCuts ); - return Area + AreaInv; - } - // both phases are used; the needed one can be selected - - // get the best match - pMatch = ALLOC( Seq_Match_t, 1 ); - memset( pMatch, 1, sizeof(Seq_Match_t) ); - Seq_MapNodeComputePhase( pAnd, fCompl, FiBest, pMatch ); - pMatch->pAnd = pAnd; - pMatch->fCompl = fCompl; - pMatch->fCutInv = pMatch->pCut->fCompl; - pMatch->PolUse = Use; - - // call for the fanin cuts - Area = pMatch->pSuper? pMatch->pSuper->Area : (float)0.0; - for ( k = 0; k < (int)pMatch->pCut->nLeaves; k++ ) - { - pFanin = Abc_NtkObj( pAnd->pNtk, pMatch->pCut->pLeaves[k] >> 8 ); - if ( pMatch->uPhase & (1 << k) ) - pFanin = Abc_ObjNot( pFanin ); - Area += Seq_MapCollectNode_rec( pFanin, FiBest, vMapping, vMapCuts ); - } - - // add this node - Vec_PtrPush( vMapping, pMatch ); - for ( k = 0; k < (int)pMatch->pCut->nLeaves; k++ ) - Vec_VecPush( vMapCuts, Vec_PtrSize(vMapping)-1, (void *)pMatch->pCut->pLeaves[k] ); - - // the cut will become unavailable when the cuts are deallocated - pMatch->pCut = NULL; - - return Area; -} - -/**Function************************************************************* - - Synopsis [Computes the canonical versions of the truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_MapCanonicizeTruthTables( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - Cut_Cut_t * pCut, * pList; - int i; - Abc_AigForEachAnd( pNtk, pObj, i ) - { - pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj ); - if ( pList == NULL ) - continue; - for ( pCut = pList->pNext; pCut; pCut = pCut->pNext ) - Cut_TruthNCanonicize( pCut ); - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/base/seq/seqMaxMeanCycle.c b/src/base/seq/seqMaxMeanCycle.c deleted file mode 100644 index 46d73cbd..00000000 --- a/src/base/seq/seqMaxMeanCycle.c +++ /dev/null @@ -1,567 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqMaxMeanCycle.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [Efficient computation of maximum mean cycle times.] - - Author [Aaron P. Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 15, 2006.] - - Revision [$Id: seqMaxMeanCycle.c,v 1.00 2005/05/15 00:00:00 ahurst Exp $] - -***********************************************************************/ - -#include "seqInt.h" -#include "hash.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Abc_ManTime_t_ -{ - Abc_Time_t tArrDef; - Abc_Time_t tReqDef; - Vec_Ptr_t * vArrs; - Vec_Ptr_t * vReqs; -}; - -typedef struct Seq_HowardData_t_ -{ - char visited; - int mark; - int policy; - float cycle; - float skew; - float delay; -} Seq_HowardData_t; - -// accessing the arrival and required times of a node -static inline Abc_Time_t * Abc_NodeArrival( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vArrs->pArray[pNode->Id]; } -static inline Abc_Time_t * Abc_NodeRequired( Abc_Obj_t * pNode ) { return pNode->pNtk->pManTime->vReqs->pArray[pNode->Id]; } - -Hash_Ptr_t * Seq_NtkPathDelays( Abc_Ntk_t * pNtk, int fVerbose ); -void Seq_NtkMergePios( Abc_Ntk_t * pNtk, Hash_Ptr_t * hFwdDelays, int fVerbose ); - -void Seq_NtkHowardLoop( Abc_Ntk_t * pNtk, Hash_Ptr_t * hFwdDelays, - Hash_Ptr_t * hNodeData, int node, - int *howardDepth, float *howardDelay, int *howardSink, - float *maxMeanCycle); -void Abc_NtkDfsReverse_rec2( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Vec_Ptr_t * vEndpoints ); - -#define Seq_NtkGetPathDelay( hFwdDelays, from, to ) \ - (Hash_PtrExists(hFwdDelays, from)?Hash_FltEntry( ((Hash_Flt_t *)Hash_PtrEntry(hFwdDelays, from, 0)), to, 0):0 ) - -#define HOWARD_EPSILON 1e-3 -#define ZERO_SLOP 1e-5 -#define REMOVE_ZERO_SLOP( x ) \ - (x = (x > -ZERO_SLOP && x < ZERO_SLOP)?0:x) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes maximum mean cycle time.] - - Description [Uses Howard's algorithm.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Seq_NtkHoward( Abc_Ntk_t * pNtk, int fVerbose ) { - - Abc_Obj_t * pObj; - Hash_Ptr_t * hFwdDelays; - Hash_Flt_t * hOutgoing; - Hash_Ptr_Entry_t * pSourceEntry, * pNodeEntry; - Hash_Flt_Entry_t * pSinkEntry; - int i, j, iteration = 0; - int source, sink; - int fChanged; - int howardDepth, howardSink = 0; - float delay, howardDelay, t; - float maxMeanCycle = -ABC_INFINITY; - Hash_Ptr_t * hNodeData; - Seq_HowardData_t * pNodeData, * pSourceData, * pSinkData; - - // gather timing constraints - hFwdDelays = Seq_NtkPathDelays( pNtk, fVerbose ); - Seq_NtkMergePios( pNtk, hFwdDelays, fVerbose ); - - // initialize data, create initial policy - hNodeData = Hash_PtrAlloc( hFwdDelays->nSize ); - Hash_PtrForEachEntry( hFwdDelays, pSourceEntry, i ) { - Hash_PtrWriteEntry( hNodeData, pSourceEntry->key, - (pNodeData = ALLOC(Seq_HowardData_t, 1)) ); - pNodeData->skew = 0.0; - pNodeData->policy = 0; - hOutgoing = (Hash_Flt_t *)(pSourceEntry->data); - assert(hOutgoing); - - Hash_FltForEachEntry( hOutgoing, pSinkEntry, j ) { - sink = pSinkEntry->key; - delay = pSinkEntry->data; - if (delay > pNodeData->skew) { - pNodeData->policy = sink; - pNodeData->skew = delay; - } - } - } - - // iteratively refine policy - do { - iteration++; - fChanged = 0; - howardDelay = 0.0; - howardDepth = 0; - - // reset data - Hash_PtrForEachEntry( hNodeData, pNodeEntry, i ) { - pNodeData = (Seq_HowardData_t *)pNodeEntry->data; - pNodeData->skew = -ABC_INFINITY; - pNodeData->cycle = -ABC_INFINITY; - pNodeData->mark = 0; - pNodeData->visited = 0; - } - - // find loops in policy graph - Hash_PtrForEachEntry( hNodeData, pNodeEntry, i ) { - pNodeData = (Seq_HowardData_t *)(pNodeEntry->data); - assert(pNodeData); - if (!pNodeData->visited) - Seq_NtkHowardLoop( pNtk, hFwdDelays, - hNodeData, pNodeEntry->key, - &howardDepth, &howardDelay, &howardSink, &maxMeanCycle); - } - - if (!howardSink) { - return -1; - } - - // improve policy by tightening loops - Hash_PtrForEachEntry( hFwdDelays, pSourceEntry, i ) { - source = pSourceEntry->key; - pSourceData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, source, 0 ); - assert(pSourceData); - hOutgoing = (Hash_Flt_t *)(pSourceEntry->data); - assert(hOutgoing); - Hash_FltForEachEntry( hOutgoing, pSinkEntry, j ) { - sink = pSinkEntry->key; - pSinkData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, sink, 0 ); - assert(pSinkData); - delay = pSinkEntry->data; - - if (pSinkData->cycle > pSourceData->cycle + HOWARD_EPSILON) { - fChanged = 1; - pSourceData->cycle = pSinkData->cycle; - pSourceData->policy = sink; - } - } - } - - // improve policy by correcting skews - if (!fChanged) { - Hash_PtrForEachEntry( hFwdDelays, pSourceEntry, i ) { - source = pSourceEntry->key; - pSourceData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, source, 0 ); - assert(pSourceData); - hOutgoing = (Hash_Flt_t *)(pSourceEntry->data); - assert(hOutgoing); - Hash_FltForEachEntry( hOutgoing, pSinkEntry, j ) { - sink = pSinkEntry->key; - pSinkData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, sink, 0 ); - assert(pSinkData); - delay = pSinkEntry->data; - - if (pSinkData->cycle < 0.0 || pSinkData->cycle < pSourceData->cycle) - continue; - - t = delay - pSinkData->cycle + pSinkData->skew; - if (t > pSourceData->skew + HOWARD_EPSILON) { - fChanged = 1; - pSourceData->skew = t; - pSourceData->policy = sink; - } - } - } - } - - if (fVerbose) printf("Iteration %d \t Period = %.2f\n", iteration, maxMeanCycle); - } while (fChanged); - - // set global skew, mmct - pNodeData = Hash_PtrEntry( hNodeData, -1, 0 ); - pNtk->globalSkew = -pNodeData->skew; - pNtk->maxMeanCycle = maxMeanCycle; - - // set endpoint skews - Vec_FltGrow( pNtk->vSkews, Abc_NtkLatchNum( pNtk ) ); - pNtk->vSkews->nSize = Abc_NtkLatchNum( pNtk ); - Abc_NtkForEachLatch( pNtk, pObj, i ) { - pNodeData = Hash_PtrEntry( hNodeData, pObj->Id, 0 ); - // skews are set based on latch # NOT id # - Abc_NtkSetLatSkew( pNtk, i, pNodeData->skew ); - } - - // free node data - Hash_PtrForEachEntry( hNodeData, pNodeEntry, i ) { - pNodeData = (Seq_HowardData_t *)(pNodeEntry->data); - FREE( pNodeData ); - } - Hash_PtrFree(hNodeData); - - // free delay data - Hash_PtrForEachEntry( hFwdDelays, pSourceEntry, i ) { - Hash_FltFree( (Hash_Flt_t *)(pSourceEntry->data) ); - } - Hash_PtrFree(hFwdDelays); - - return maxMeanCycle; -} - -/**Function************************************************************* - - Synopsis [Computes the mean cycle times of current policy graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkHowardLoop( Abc_Ntk_t * pNtk, Hash_Ptr_t * hFwdDelays, - Hash_Ptr_t * hNodeData, int node, - int *howardDepth, float *howardDelay, int *howardSink, - float *maxMeanCycle) { - - Seq_HowardData_t * pNodeData, *pToData; - float delay, t; - - pNodeData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, node, 0 ); - assert(pNodeData); - pNodeData->visited = 1; - pNodeData->mark = ++(*howardDepth); - pNodeData->delay = (*howardDelay); - if (pNodeData->policy) { - pToData = (Seq_HowardData_t *)Hash_PtrEntry( hNodeData, pNodeData->policy, 0 ); - assert(pToData); - delay = Seq_NtkGetPathDelay( hFwdDelays, node, pNodeData->policy ); - assert(delay > 0.0); - (*howardDelay) += delay; - if (pToData->mark) { - t = (*howardDelay - pToData->delay) / (*howardDepth - pToData->mark + 1); - pNodeData->cycle = t; - pNodeData->skew = 0.0; - if (*maxMeanCycle < t) { - *maxMeanCycle = t; - *howardSink = pNodeData->policy; - } - } else { - if(!pToData->visited) { - Seq_NtkHowardLoop(pNtk, hFwdDelays, hNodeData, pNodeData->policy, - howardDepth, howardDelay, howardSink, maxMeanCycle); - } - if(pToData->cycle > 0) { - t = delay - pToData->cycle + pToData->skew; - pNodeData->skew = t; - pNodeData->cycle = pToData->cycle; - } - } - } - *howardDelay = pNodeData->delay; - pNodeData->mark = 0; - --(*howardDepth); -} - -/**Function************************************************************* - - Synopsis [Computes the register-to-register delays.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hash_Ptr_t * Seq_NtkPathDelays( Abc_Ntk_t * pNtk, int fVerbose ) { - - Abc_Time_t * pTime, ** ppTimes; - Abc_Obj_t * pObj, * pDriver, * pStart, * pFanout; - Vec_Ptr_t * vNodes, * vEndpoints; - int i, j, nPaths = 0; - Hash_Flt_t * hOutgoing; - Hash_Ptr_t * hFwdDelays; - float nMaxPath = 0, nSumPath = 0; - - extern void Abc_NtkTimePrepare( Abc_Ntk_t * pNtk ); - extern void Abc_NodeDelayTraceArrival( Abc_Obj_t * pNode ); - - if (fVerbose) printf("Gathering path delays...\n"); - - hFwdDelays = Hash_PtrAlloc( Abc_NtkCiNum( pNtk ) ); - - assert( Abc_NtkIsMappedLogic(pNtk) ); - - Abc_NtkTimePrepare( pNtk ); - ppTimes = (Abc_Time_t **)pNtk->pManTime->vArrs->pArray; - vNodes = Vec_PtrAlloc( 100 ); - vEndpoints = Vec_PtrAlloc( 100 ); - - // set the initial times (i.e. ignore all inputs) - Abc_NtkForEachObj( pNtk, pObj, i) { - pTime = ppTimes[pObj->Id]; - pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY; - } - - // starting at each Ci, compute timing forward - Abc_NtkForEachCi( pNtk, pStart, j ) { - - hOutgoing = Hash_FltAlloc( 10 ); - Hash_PtrWriteEntry( hFwdDelays, pStart->Id, (void *)(hOutgoing) ); - - // seed the starting point of interest - pTime = ppTimes[pStart->Id]; - pTime->Fall = pTime->Rise = pTime->Worst = 0.0; - - // find a DFS ordering from the start - Abc_NtkIncrementTravId( pNtk ); - Abc_NodeSetTravIdCurrent( pStart ); - pObj = Abc_ObjFanout0Ntk(pStart); - Abc_ObjForEachFanout( pObj, pFanout, i ) - Abc_NtkDfsReverse_rec2( pFanout, vNodes, vEndpoints ); - if ( Abc_ObjIsCo( pStart ) ) - Vec_PtrPush( vEndpoints, pStart ); - - // do timing analysis - for ( i = vNodes->nSize-1; i >= 0; --i ) - Abc_NodeDelayTraceArrival( vNodes->pArray[i] ); - - // there is a path to each set of Co endpoints - Vec_PtrForEachEntry( vEndpoints, pObj, i ) - { - assert(pObj); - assert( Abc_ObjIsCo( pObj ) ); - pDriver = Abc_ObjFanin0(pObj); - pTime = Abc_NodeArrival(pDriver); - if ( pTime->Worst > 0 ) { - Hash_FltWriteEntry( hOutgoing, pObj->Id, pTime->Worst ); - nPaths++; - // if (fVerbose) printf("\tpath %d,%d delay = %f\n", pStart->Id, pObj->Id, pTime->Worst); - nSumPath += pTime->Worst; - if (pTime->Worst > nMaxPath) - nMaxPath = pTime->Worst; - } - } - - // clear the times that were altered - for ( i = 0; i < vNodes->nSize; i++ ) { - pObj = (Abc_Obj_t *)(vNodes->pArray[i]); - pTime = ppTimes[pObj->Id]; - pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY; - } - pTime = ppTimes[pStart->Id]; - pTime->Fall = pTime->Rise = pTime->Worst = -ABC_INFINITY; - - Vec_PtrClear( vNodes ); - Vec_PtrClear( vEndpoints ); - } - - Vec_PtrFree( vNodes ); - - // rezero Cis (note: these should be restored to values if they were nonzero) - Abc_NtkForEachCi( pNtk, pObj, i) { - pTime = ppTimes[pObj->Id]; - pTime->Fall = pTime->Rise = pTime->Worst = 0.0; - } - - if (fVerbose) printf("Num. paths = %d\tMax. Path Delay = %.2f\tAvg. Path Delay = %.2f\n", nPaths, nMaxPath, nSumPath / nPaths); - return hFwdDelays; -} - - -/**Function************************************************************* - - Synopsis [Merges all the Pios together into one ID = -1.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkMergePios( Abc_Ntk_t * pNtk, Hash_Ptr_t * hFwdDelays, - int fVerbose ) { - - Abc_Obj_t * pObj; - Hash_Flt_Entry_t * pSinkEntry; - Hash_Ptr_Entry_t * pSourceEntry; - Hash_Flt_t * hOutgoing, * hPioSource; - int i, j; - int source, sink, nMerges = 0; - float delay = 0, max_delay = 0; - Vec_Int_t * vFreeList; - - vFreeList = Vec_IntAlloc( 10 ); - - // create a new "-1" source entry for the Pios - hPioSource = Hash_FltAlloc( 100 ); - Hash_PtrWriteEntry( hFwdDelays, -1, (void *)(hPioSource) ); - - // merge all edges with a Pio as a source - Abc_NtkForEachPi( pNtk, pObj, i ) { - source = pObj->Id; - hOutgoing = (Hash_Flt_t *)Hash_PtrEntry( hFwdDelays, source, 0 ); - if (!hOutgoing) continue; - - Hash_PtrForEachEntry( hOutgoing, pSinkEntry, j ) { - nMerges++; - sink = pSinkEntry->key; - delay = pSinkEntry->data; - if (Hash_FltEntry( hPioSource, sink, 1 ) < delay) { - Hash_FltWriteEntry( hPioSource, sink, delay ); - } - } - - Hash_FltFree( hOutgoing ); - Hash_PtrRemove( hFwdDelays, source ); - } - - // merge all edges with a Pio as a sink - Hash_PtrForEachEntry( hFwdDelays, pSourceEntry, i ) { - hOutgoing = (Hash_Flt_t *)(pSourceEntry->data); - Hash_FltForEachEntry( hOutgoing, pSinkEntry, j ) { - sink = pSinkEntry->key; - delay = pSinkEntry->data; - - max_delay = -ABC_INFINITY; - if (Abc_ObjIsPo( Abc_NtkObj( pNtk, sink ) )) { - nMerges++; - if (delay > max_delay) - max_delay = delay; - Vec_IntPush( vFreeList, sink ); - } - } - if (max_delay != -ABC_INFINITY) - Hash_FltWriteEntry( hOutgoing, -1, delay ); - // do freeing - while( vFreeList->nSize > 0 ) { - Hash_FltRemove( hOutgoing, Vec_IntPop( vFreeList ) ); - } - } - - if (fVerbose) printf("Merged %d paths into one Pio node\n", nMerges); - -} - -/**Function************************************************************* - - Synopsis [This is a modification of routine from abcDfs.c] - - Description [Recursive DFS from a starting point. Keeps the endpoints.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkDfsReverse_rec2( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes, Vec_Ptr_t * vEndpoints ) -{ - Abc_Obj_t * pFanout; - int i; - assert( !Abc_ObjIsNet(pNode) ); - // if this node is already visited, skip - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return; - // mark the node as visited - Abc_NodeSetTravIdCurrent( pNode ); - // terminate at the Co - if ( Abc_ObjIsCo(pNode) ) { - Vec_PtrPush( vEndpoints, pNode ); - return; - } - assert( Abc_ObjIsNode( pNode ) ); - // visit the transitive fanin of the node - pNode = Abc_ObjFanout0Ntk(pNode); - Abc_ObjForEachFanout( pNode, pFanout, i ) - Abc_NtkDfsReverse_rec2( pFanout, vNodes, vEndpoints ); - // add the node after the fanins have been added - Vec_PtrPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Converts all skews into forward skews 0vSkews->nSize >= Abc_NtkLatchNum( pNtk )-1 ); - - if (fMinimize) { - // search all offsets for the one that minimizes sum of skews - while(currentOffset < period) { - currentSum = 0; - nextStep = period; - Abc_NtkForEachLatch( pNtk, pObj, i ) { - skew = Abc_NtkGetLatSkew( pNtk, i ) + currentOffset; - skew = (float)(skew - period*floor(skew/period)); - currentSum += skew; - if (skew > ZERO_SLOP && skew < nextStep) { - nextStep = skew; - } - } - - if (currentSum < bestSum) { - bestSum = currentSum; - bestOffset = currentOffset; - } - currentOffset += nextStep; - } - printf("Offseting all skews by %.2f\n", bestOffset); - } - - // convert global skew into forward skew - pNtk->globalSkew = pNtk->globalSkew - bestOffset; - pNtk->globalSkew = (float)(pNtk->globalSkew - period*floor(pNtk->globalSkew/period)); - assert(pNtk->globalSkew>= 0 && pNtk->globalSkew < period); - - // convert endpoint skews into forward skews - Abc_NtkForEachLatch( pNtk, pObj, i ) { - skew = Abc_NtkGetLatSkew( pNtk, i ) + bestOffset; - skew = (float)(skew - period*floor(skew/period)); - REMOVE_ZERO_SLOP( skew ); - assert(skew >=0 && skew < period); - - Abc_NtkSetLatSkew( pNtk, i, skew ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/base/seq/seqRetCore.c b/src/base/seq/seqRetCore.c deleted file mode 100644 index 27638644..00000000 --- a/src/base/seq/seqRetCore.c +++ /dev/null @@ -1,492 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqRetCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [The core of FPGA mapping/retiming package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqRetCore.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * Seq_NtkRetimeDerive( Abc_Ntk_t * pNtk, int fVerbose ); -static Abc_Obj_t * Seq_NodeRetimeDerive( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, char * pSop, Vec_Ptr_t * vFanins ); -static Abc_Ntk_t * Seq_NtkRetimeReconstruct( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkSeq ); -static Abc_Obj_t * Seq_EdgeReconstruct_rec( Abc_Obj_t * pGoal, Abc_Obj_t * pNode ); -static Abc_Obj_t * Seq_EdgeReconstructPO( Abc_Obj_t * pNode ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs FPGA mapping and retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Seq_NtkRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fInitial, int fVerbose ) -{ - Abc_Seq_t * p; - Abc_Ntk_t * pNtkSeq, * pNtkNew; - int RetValue; - assert( !Abc_NtkHasAig(pNtk) ); - // derive the isomorphic seq AIG - pNtkSeq = Seq_NtkRetimeDerive( pNtk, fVerbose ); - p = pNtkSeq->pManFunc; - p->nMaxIters = nMaxIters; - - if ( !fInitial ) - Seq_NtkLatchSetValues( pNtkSeq, ABC_INIT_DC ); - // find the best mapping and retiming - if ( !Seq_NtkRetimeDelayLags( pNtk, pNtkSeq, fVerbose ) ) - return NULL; - - // implement the retiming - RetValue = Seq_NtkImplementRetiming( pNtkSeq, p->vLags, fVerbose ); - if ( RetValue == 0 ) - printf( "Retiming completed but initial state computation has failed.\n" ); -//return pNtkSeq; - - // create the final mapped network - pNtkNew = Seq_NtkRetimeReconstruct( pNtk, pNtkSeq ); - Abc_NtkDelete( pNtkSeq ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Derives the isomorphic seq AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Seq_NtkRetimeDerive( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Abc_Seq_t * p; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFanin, * pMirror; - Vec_Ptr_t * vMapAnds, * vMirrors; - Vec_Vec_t * vMapFanins; - int i, k, RetValue, fHasBdds; - char * pSop; - - // make sure it is an AIG without self-feeding latches - assert( !Abc_NtkHasAig(pNtk) ); - if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtk) ) - printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue ); - assert( Abc_NtkCountSelfFeedLatches(pNtk) == 0 ); - - // remove the dangling nodes - Abc_NtkCleanup( pNtk, fVerbose ); - - // transform logic functions from BDD to SOP - if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) - { - if ( !Abc_NtkBddToSop(pNtk, 0) ) - { - printf( "Seq_NtkRetimeDerive(): Converting to SOPs has failed.\n" ); - return NULL; - } - } - - // start the network - pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG, 1 ); - // duplicate the name and the spec - pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); - pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); - - // map the constant nodes - Abc_NtkCleanCopy( pNtk ); - // clone the PIs/POs/latches - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - // copy the names - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); - - // create one AND for each logic node in the topological order - vMapAnds = Abc_NtkDfs( pNtk, 0 ); - Vec_PtrForEachEntry( vMapAnds, pObj, i ) - { - if ( pObj->Id == 0 ) - { - pObj->pCopy = Abc_AigConst1(pNtkNew); - continue; - } - pObj->pCopy = Abc_NtkCreateNode( pNtkNew ); - } - - // make the new seq AIG point to the old network through pNext - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( pObj->pCopy ) pObj->pCopy->pNext = pObj; - - // make latches point to the latch fanins - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - assert( !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ); - pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; - } - - // create internal AND nodes w/o strashing for each logic node (including constants) - vMapFanins = Vec_VecStart( Vec_PtrSize(vMapAnds) ); - Vec_PtrForEachEntry( vMapAnds, pObj, i ) - { - // get the SOP of the node - if ( Abc_NtkHasMapping(pNtk) ) - pSop = Mio_GateReadSop(pObj->pData); - else - pSop = pObj->pData; - pFanin = Seq_NodeRetimeDerive( pNtkNew, pObj, pSop, Vec_VecEntry(vMapFanins, i) ); - Abc_ObjAddFanin( pObj->pCopy, pFanin ); - Abc_ObjAddFanin( pObj->pCopy, pFanin ); - } - // connect the POs - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); - - // start the storage for initial states - p = pNtkNew->pManFunc; - Seq_Resize( p, Abc_NtkObjNumMax(pNtkNew) ); - - // add the sequential edges - Vec_PtrForEachEntry( vMapAnds, pObj, i ) - { - vMirrors = Vec_VecEntry( vMapFanins, i ); - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - pMirror = Vec_PtrEntry( vMirrors, k ); - if ( Abc_ObjIsLatch(pFanin) ) - { - Seq_NodeInsertFirst( pMirror, 0, Abc_LatchInit(pFanin) ); - Seq_NodeInsertFirst( pMirror, 1, Abc_LatchInit(pFanin) ); - } - } - } - // add the sequential edges to the POs - Abc_NtkForEachPo( pNtk, pObj, i ) - { - pFanin = Abc_ObjFanin0(pObj); - if ( Abc_ObjIsLatch(pFanin) ) - Seq_NodeInsertFirst( pObj->pCopy, 0, Abc_LatchInit(pFanin) ); - } - - - // save the fanin/delay info - p->vMapAnds = vMapAnds; - p->vMapFanins = vMapFanins; - p->vMapCuts = Vec_VecStart( Vec_PtrSize(p->vMapAnds) ); - p->vMapDelays = Vec_VecStart( Vec_PtrSize(p->vMapAnds) ); - Vec_PtrForEachEntry( p->vMapAnds, pObj, i ) - { - // change the node to be the new one - Vec_PtrWriteEntry( p->vMapAnds, i, pObj->pCopy ); - // collect the new fanins of this node - Abc_ObjForEachFanin( pObj, pFanin, k ) - Vec_VecPush( p->vMapCuts, i, (void *)( (pFanin->pCopy->Id << 8) | Abc_ObjIsLatch(pFanin) ) ); - // collect the delay info - if ( !Abc_NtkHasMapping(pNtk) ) - { - Abc_ObjForEachFanin( pObj, pFanin, k ) - Vec_VecPush( p->vMapDelays, i, (void *)Abc_Float2Int(1.0) ); - } - else - { - Mio_Pin_t * pPin = Mio_GateReadPins(pObj->pData); - float Max, tDelayBlockRise, tDelayBlockFall; - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); - tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); - Max = ABC_MAX( tDelayBlockRise, tDelayBlockFall ); - Vec_VecPush( p->vMapDelays, i, (void *)Abc_Float2Int(Max) ); - pPin = Mio_PinReadNext(pPin); - } - } - } - - // set the cutset composed of latch drivers -// Abc_NtkAigCutsetCopy( pNtk ); -// Seq_NtkLatchGetEqualFaninNum( pNtkNew ); - - // convert the network back into BDDs if this is how it was - if ( fHasBdds ) - Abc_NtkSopToBdd(pNtk); - - // copy EXDC and check correctness - if ( pNtk->pExdc ) - fprintf( stdout, "Warning: EXDC is not copied when converting to sequential AIG.\n" ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Seq_NtkRetimeDerive(): Network check has failed.\n" ); - return pNtkNew; -} - - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Seq_NodeRetimeDerive( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pRoot, char * pSop, Vec_Ptr_t * vFanins ) -{ - Dec_Graph_t * pFForm; - Dec_Node_t * pNode; - Abc_Obj_t * pResult, * pFanin, * pMirror; - int i, nFanins; - - // get the number of node's fanins - nFanins = Abc_ObjFaninNum( pRoot ); - assert( nFanins == Abc_SopGetVarNum(pSop) ); - if ( nFanins < 2 ) - { - if ( Abc_SopIsConst1(pSop) ) - pFanin = Abc_AigConst1(pNtkNew); - else if ( Abc_SopIsConst0(pSop) ) - pFanin = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); - else if ( Abc_SopIsBuf(pSop) ) - pFanin = Abc_ObjFanin0(pRoot)->pCopy; - else if ( Abc_SopIsInv(pSop) ) - pFanin = Abc_ObjNot( Abc_ObjFanin0(pRoot)->pCopy ); - else - assert( 0 ); - // create the node with these fanins - pMirror = Abc_NtkCreateNode( pNtkNew ); - Abc_ObjAddFanin( pMirror, pFanin ); - Abc_ObjAddFanin( pMirror, pFanin ); - Vec_PtrPush( vFanins, pMirror ); - return pMirror; - } - - // perform factoring - pFForm = Dec_Factor( pSop ); - // collect the fanins - Dec_GraphForEachLeaf( pFForm, pNode, i ) - { - pFanin = Abc_ObjFanin(pRoot,i)->pCopy; - pMirror = Abc_NtkCreateNode( pNtkNew ); - Abc_ObjAddFanin( pMirror, pFanin ); - Abc_ObjAddFanin( pMirror, pFanin ); - Vec_PtrPush( vFanins, pMirror ); - pNode->pFunc = pMirror; - } - // perform strashing - pResult = Dec_GraphToNetworkNoStrash( pNtkNew, pFForm ); - Dec_GraphFree( pFForm ); - return pResult; -} - - -/**Function************************************************************* - - Synopsis [Reconstructs the network after retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Seq_NtkRetimeReconstruct( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkSeq ) -{ - Abc_Seq_t * p = pNtkSeq->pManFunc; - Seq_Lat_t * pRing0, * pRing1; - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pFanin, * pFaninNew, * pMirror; - Vec_Ptr_t * vMirrors; - int i, k; - - assert( !Abc_NtkIsSeq(pNtkOld) ); - assert( Abc_NtkIsSeq(pNtkSeq) ); - - // transfer the pointers pNtkOld->pNtkSeq from pCopy to pNext - Abc_NtkForEachObj( pNtkOld, pObj, i ) - pObj->pNext = pObj->pCopy; - - // start the final network - pNtkNew = Abc_NtkStartFrom( pNtkSeq, pNtkOld->ntkType, pNtkOld->ntkFunc ); - - // transfer the pointers to the old network - if ( Abc_AigConst1(pNtkOld) ) - Abc_AigConst1(pNtkOld)->pCopy = Abc_AigConst1(pNtkNew); - Abc_NtkForEachPi( pNtkOld, pObj, i ) - pObj->pCopy = pObj->pNext->pCopy; - Abc_NtkForEachPo( pNtkOld, pObj, i ) - pObj->pCopy = pObj->pNext->pCopy; - - // copy the internal nodes of the old network into the new network - // transfer the pointers pNktOld->pNtkNew to pNtkSeq->pNtkNew - Abc_NtkForEachNode( pNtkOld, pObj, i ) - { - if ( i == 0 ) continue; - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - pObj->pNext->pCopy = pObj->pCopy; - } - Abc_NtkForEachLatch( pNtkOld, pObj, i ) - pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; - - // share the latches - Seq_NtkShareLatches( pNtkNew, pNtkSeq ); - - // connect the objects -// Abc_NtkForEachNode( pNtkOld, pObj, i ) - Vec_PtrForEachEntry( p->vMapAnds, pObj, i ) - { - // pObj is from pNtkSeq - transform to pNtkOld - pObj = pObj->pNext; - // iterate through the fanins of this node in the old network - vMirrors = Vec_VecEntry( p->vMapFanins, i ); - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - pMirror = Vec_PtrEntry( vMirrors, k ); - assert( Seq_ObjFaninL0(pMirror) == Seq_ObjFaninL1(pMirror) ); - pRing0 = Seq_NodeGetRing( pMirror, 0 ); - pRing1 = Seq_NodeGetRing( pMirror, 1 ); - if ( pRing0 == NULL ) - { - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - continue; - } -// assert( pRing0->pLatch == pRing1->pLatch ); - if ( pRing0->pLatch->pData > pRing1->pLatch->pData ) - Abc_ObjAddFanin( pObj->pCopy, pRing0->pLatch ); - else - Abc_ObjAddFanin( pObj->pCopy, pRing1->pLatch ); - } - } - - // connect the POs - Abc_NtkForEachPo( pNtkOld, pObj, i ) - { - pFanin = Abc_ObjFanin0(pObj); - pRing0 = Seq_NodeGetRing( Abc_NtkPo(pNtkSeq, i), 0 ); - if ( pRing0 ) - pFaninNew = pRing0->pLatch; - else - pFaninNew = pFanin->pCopy; - assert( pFaninNew != NULL ); - Abc_ObjAddFanin( pObj->pCopy, pFaninNew ); - } - - // clean the result of latch sharing - Seq_NtkShareLatchesClean( pNtkSeq ); - - // add the latches and their names - Abc_NtkAddDummyBoxNames( pNtkNew ); - Abc_NtkOrderCisCos( pNtkNew ); - // fix the problem with complemented and duplicated CO edges - Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Seq_NtkRetimeReconstruct(): Network check has failed.\n" ); - return pNtkNew; - -} - -/**Function************************************************************* - - Synopsis [Reconstructs the network after retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Seq_EdgeReconstruct_rec( Abc_Obj_t * pGoal, Abc_Obj_t * pNode ) -{ - Seq_Lat_t * pRing; - Abc_Obj_t * pFanin, * pRes = NULL; - - if ( !Abc_AigNodeIsAnd(pNode) ) - return NULL; - - // consider the first fanin - pFanin = Abc_ObjFanin0(pNode); - if ( pFanin->pCopy == NULL ) // internal node - pRes = Seq_EdgeReconstruct_rec( pGoal, pFanin ); - else if ( pFanin == pGoal ) - { - if ( pRing = Seq_NodeGetRing( pNode, 0 ) ) - pRes = pRing->pLatch; - else - pRes = pFanin->pCopy; - } - if ( pRes != NULL ) - return pRes; - - // consider the second fanin - pFanin = Abc_ObjFanin1(pNode); - if ( pFanin->pCopy == NULL ) // internal node - pRes = Seq_EdgeReconstruct_rec( pGoal, pFanin ); - else if ( pFanin == pGoal ) - { - if ( pRing = Seq_NodeGetRing( pNode, 1 ) ) - pRes = pRing->pLatch; - else - pRes = pFanin->pCopy; - } - return pRes; -} - -/**Function************************************************************* - - Synopsis [Reconstructs the network after retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Seq_EdgeReconstructPO( Abc_Obj_t * pNode ) -{ - Seq_Lat_t * pRing; - assert( Abc_ObjIsPo(pNode) ); - if ( pRing = Seq_NodeGetRing( pNode, 0 ) ) - return pRing->pLatch; - else - return Abc_ObjFanin0(pNode)->pCopy; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/seq/seqRetIter.c b/src/base/seq/seqRetIter.c deleted file mode 100644 index 99c50914..00000000 --- a/src/base/seq/seqRetIter.c +++ /dev/null @@ -1,403 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqRetIter.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [Iterative delay computation in FPGA mapping/retiming package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqRetIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" -#include "main.h" -#include "fpga.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static float Seq_NtkMappingSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose ); -static int Seq_NtkMappingForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose ); -static int Seq_NtkNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vDelays ); -static void Seq_NodeRetimeSetLag_rec( Abc_Obj_t * pNode, char Lag ); - -static void Seq_NodePrintInfo( Abc_Obj_t * pNode ); -static void Seq_NodePrintInfoPlus( Abc_Obj_t * pNode ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the retiming lags for arbitrary network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkRetimeDelayLags( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtk, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Abc_Obj_t * pNode; - float FiMax, Delta; - int i, RetValue; - char NodeLag; - - assert( Abc_NtkIsSeq( pNtk ) ); - - // the root AND gates and node delay should be assigned - assert( p->vMapAnds ); - assert( p->vMapCuts ); - assert( p->vMapDelays ); - assert( p->vMapFanins ); - - // guess the upper bound on the clock period - if ( Abc_NtkHasMapping(pNtkOld) ) - { - // assign the accuracy for min-period computation - Delta = Mio_LibraryReadDelayNand2Max(Abc_FrameReadLibGen()); - if ( Delta == 0.0 ) - { - Delta = Mio_LibraryReadDelayAnd2Max(Abc_FrameReadLibGen()); - if ( Delta == 0.0 ) - { - printf( "Cannot retime/map if the library does not have NAND2 or AND2.\n" ); - return 0; - } - } - // get the upper bound on the clock period - FiMax = Delta * 2 + Abc_NtkDelayTrace(pNtkOld); - Delta /= 2; - } - else - { - FiMax = (float)2.0 + Abc_NtkGetLevelNum(pNtkOld); - Delta = 1; - } - - // make sure this clock period is feasible - if ( !Seq_NtkMappingForPeriod( pNtk, FiMax, fVerbose ) ) - { - printf( "Error: The upper bound on the clock period cannot be computed.\n" ); - printf( "The reason for this error may be the presence in the circuit of logic\n" ); - printf( "that is not reachable from the PIs. Mapping/retiming is not performed.\n" ); - return 0; - } - - // search for the optimal clock period between 0 and nLevelMax - p->FiBestFloat = Seq_NtkMappingSearch_rec( pNtk, 0.0, FiMax, Delta, fVerbose ); - - // recompute the best l-values - RetValue = Seq_NtkMappingForPeriod( pNtk, p->FiBestFloat, fVerbose ); - assert( RetValue ); - - // fix the problem with non-converged delays - Vec_PtrForEachEntry( p->vMapAnds, pNode, i ) - if ( Seq_NodeGetLValueP(pNode) < -ABC_INFINITY/2 ) - Seq_NodeSetLValueP( pNode, 0 ); - - // experiment by adding an epsilon to all LValues -// Vec_PtrForEachEntry( p->vMapAnds, pNode, i ) -// Seq_NodeSetLValueP( pNode, Seq_NodeGetLValueP(pNode) - p->fEpsilon ); - - // save the retiming lags - // mark the nodes - Vec_PtrForEachEntry( p->vMapAnds, pNode, i ) - pNode->fMarkA = 1; - // process the nodes - Vec_StrFill( p->vLags, p->nSize, 0 ); - Vec_PtrForEachEntry( p->vMapAnds, pNode, i ) - { - if ( Vec_PtrSize( Vec_VecEntry(p->vMapCuts, i) ) == 0 ) - { - Seq_NodeSetLag( pNode, 0 ); - continue; - } - NodeLag = Seq_NodeComputeLagFloat( Seq_NodeGetLValueP(pNode), p->FiBestFloat ); - Seq_NodeRetimeSetLag_rec( pNode, NodeLag ); - } - // unmark the nodes - Vec_PtrForEachEntry( p->vMapAnds, pNode, i ) - pNode->fMarkA = 0; - - // print the result - if ( fVerbose ) - printf( "The best clock period is %6.2f.\n", p->FiBestFloat ); -/* - { - FILE * pTable; - pTable = fopen( "stats.txt", "a+" ); - fprintf( pTable, "%s ", pNtk->pName ); - fprintf( pTable, "%.2f ", FiBest ); - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ -// Seq_NodePrintInfo( Abc_NtkObj(pNtk, 847) ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs binary search for the optimal clock period.] - - Description [Assumes that FiMin is infeasible while FiMax is feasible.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Seq_NtkMappingSearch_rec( Abc_Ntk_t * pNtk, float FiMin, float FiMax, float Delta, int fVerbose ) -{ - float Median; - assert( FiMin < FiMax ); - if ( FiMin + Delta >= FiMax ) - return FiMax; - Median = FiMin + (FiMax - FiMin)/2; - if ( Seq_NtkMappingForPeriod( pNtk, Median, fVerbose ) ) - return Seq_NtkMappingSearch_rec( pNtk, FiMin, Median, Delta, fVerbose ); // Median is feasible - else - return Seq_NtkMappingSearch_rec( pNtk, Median, FiMax, Delta, fVerbose ); // Median is infeasible -} - -/**Function************************************************************* - - Synopsis [Returns 1 if retiming with this clock period is feasible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkMappingForPeriod( Abc_Ntk_t * pNtk, float Fi, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Vec_Ptr_t * vLeaves, * vDelays; - Abc_Obj_t * pObj; - int i, c, RetValue, fChange, Counter; - char * pReason = ""; - - // set l-values of all nodes to be minus infinity - Vec_IntFill( p->vLValues, p->nSize, Abc_Float2Int( (float)-ABC_INFINITY ) ); - - // set l-values of constants and PIs - pObj = Abc_NtkObj( pNtk, 0 ); - Seq_NodeSetLValueP( pObj, 0.0 ); - Abc_NtkForEachPi( pNtk, pObj, i ) - Seq_NodeSetLValueP( pObj, 0.0 ); - - // update all values iteratively - Counter = 0; - for ( c = 0; c < p->nMaxIters; c++ ) - { - fChange = 0; - Vec_PtrForEachEntry( p->vMapAnds, pObj, i ) - { - Counter++; - vLeaves = Vec_VecEntry( p->vMapCuts, i ); - vDelays = Vec_VecEntry( p->vMapDelays, i ); - if ( Vec_PtrSize(vLeaves) == 0 ) - { - Seq_NodeSetLValueP( pObj, 0.0 ); - continue; - } - RetValue = Seq_NtkNodeUpdateLValue( pObj, Fi, vLeaves, vDelays ); - if ( RetValue == SEQ_UPDATE_YES ) - fChange = 1; - } - Abc_NtkForEachPo( pNtk, pObj, i ) - { - RetValue = Seq_NtkNodeUpdateLValue( pObj, Fi, NULL, NULL ); - if ( RetValue == SEQ_UPDATE_FAIL ) - break; - } - if ( RetValue == SEQ_UPDATE_FAIL ) - break; - if ( fChange == 0 ) - break; - } - if ( c == p->nMaxIters ) - { - RetValue = SEQ_UPDATE_FAIL; - pReason = "(timeout)"; - } - else - c++; - - // report the results - if ( fVerbose ) - { - if ( RetValue == SEQ_UPDATE_FAIL ) - printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason ); - else - printf( "Period = %6.2f. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter ); - } - return RetValue != SEQ_UPDATE_FAIL; -} - -/**Function************************************************************* - - Synopsis [Computes the l-value of the node.] - - Description [The node can be internal or a PO.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkNodeUpdateLValue( Abc_Obj_t * pObj, float Fi, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vDelays ) -{ - Abc_Seq_t * p = pObj->pNtk->pManFunc; - float lValueOld, lValueNew, lValueCur, lValuePin; - unsigned SeqEdge; - Abc_Obj_t * pLeaf; - int i; - - assert( !Abc_ObjIsPi(pObj) ); - assert( Abc_ObjFaninNum(pObj) > 0 ); - // consider the case of the PO - if ( Abc_ObjIsPo(pObj) ) - { - lValueCur = Seq_NodeGetLValueP(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj); - return (lValueCur > Fi + p->fEpsilon)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO; - } - // get the new arrival time of the cut output - lValueNew = -ABC_INFINITY; - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - { - SeqEdge = (unsigned)pLeaf; - pLeaf = Abc_NtkObj( pObj->pNtk, SeqEdge >> 8 ); - lValueCur = Seq_NodeGetLValueP(pLeaf) - Fi * (SeqEdge & 255); - lValuePin = Abc_Int2Float( (int)Vec_PtrEntry(vDelays, i) ); - if ( lValueNew < lValuePin + lValueCur ) - lValueNew = lValuePin + lValueCur; - } - // compare - lValueOld = Seq_NodeGetLValueP( pObj ); - if ( lValueNew <= lValueOld + p->fEpsilon ) - return SEQ_UPDATE_NO; - // update the values - if ( lValueNew > lValueOld + p->fEpsilon ) - Seq_NodeSetLValueP( pObj, lValueNew ); - return SEQ_UPDATE_YES; -} - - - -/**Function************************************************************* - - Synopsis [Add sequential edges.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NodeRetimeSetLag_rec( Abc_Obj_t * pNode, char Lag ) -{ - Abc_Obj_t * pFanin; - if ( !Abc_AigNodeIsAnd(pNode) ) - return; - Seq_NodeSetLag( pNode, Lag ); - // consider the first fanin - pFanin = Abc_ObjFanin0(pNode); - if ( pFanin->fMarkA == 0 ) // internal node - Seq_NodeRetimeSetLag_rec( pFanin, Lag ); - // consider the second fanin - pFanin = Abc_ObjFanin1(pNode); - if ( pFanin->fMarkA == 0 ) // internal node - Seq_NodeRetimeSetLag_rec( pFanin, Lag ); -} - - -/**Function************************************************************* - - Synopsis [Add sequential edges.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NodePrintInfo( Abc_Obj_t * pNode ) -{ - Abc_Seq_t * p = pNode->pNtk->pManFunc; - Abc_Obj_t * pFanin, * pObj, * pLeaf; - Vec_Ptr_t * vLeaves; - unsigned SeqEdge; - int i, Number; - - // print the node - printf( " Node = %6d. LValue = %7.2f. Lag = %2d.\n", - pNode->Id, Seq_NodeGetLValueP(pNode), Seq_NodeGetLag(pNode) ); - - // find the number - Vec_PtrForEachEntry( p->vMapAnds, pObj, Number ) - if ( pObj == pNode ) - break; - - // get the leaves - vLeaves = Vec_VecEntry( p->vMapCuts, Number ); - - // print the leaves - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - { - SeqEdge = (unsigned)pLeaf; - pFanin = Abc_NtkObj( pNode->pNtk, SeqEdge >> 8 ); - // print the leaf - printf( " Fanin%d(%d) = %6d. LValue = %7.2f. Lag = %2d.\n", i, SeqEdge & 255, - pFanin->Id, Seq_NodeGetLValueP(pFanin), Seq_NodeGetLag(pFanin) ); - } -} - -/**Function************************************************************* - - Synopsis [Add sequential edges.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NodePrintInfoPlus( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanout; - int i; - printf( "CENTRAL NODE:\n" ); - Seq_NodePrintInfo( pNode ); - Abc_ObjForEachFanout( pNode, pFanout, i ) - { - printf( "FANOUT%d:\n", i ); - Seq_NodePrintInfo( pFanout ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/seq/seqShare.c b/src/base/seq/seqShare.c deleted file mode 100644 index 742de46b..00000000 --- a/src/base/seq/seqShare.c +++ /dev/null @@ -1,388 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqShare.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [Latch sharing at the fanout stems.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqShare.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Seq_NodeShareFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); -static void Seq_NodeShareOne( Abc_Obj_t * pNode, Abc_InitType_t Init, Vec_Ptr_t * vNodes ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transforms the sequential AIG to take fanout sharing into account.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkShareFanouts( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i; - vNodes = Vec_PtrAlloc( 10 ); - // share the PI latches - Abc_NtkForEachPi( pNtk, pObj, i ) - Seq_NodeShareFanouts( pObj, vNodes ); - // share the node latches - Abc_NtkForEachNode( pNtk, pObj, i ) - Seq_NodeShareFanouts( pObj, vNodes ); - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Transforms the node to take fanout sharing into account.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NodeShareFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanout; - Abc_InitType_t Type; - int nLatches[4], i; - // skip the node with only one fanout - if ( Abc_ObjFanoutNum(pNode) < 2 ) - return; - // clean the the fanout counters - for ( i = 0; i < 4; i++ ) - nLatches[i] = 0; - // find the number of fanouts having latches of each type - Abc_ObjForEachFanout( pNode, pFanout, i ) - { - if ( Seq_ObjFanoutL(pNode, pFanout) == 0 ) - continue; - Type = Seq_NodeGetInitLast( pFanout, Abc_ObjFanoutEdgeNum(pNode, pFanout) ); - nLatches[Type]++; - } - // decide what to do - if ( nLatches[ABC_INIT_ZERO] > 1 && nLatches[ABC_INIT_ONE] > 1 ) // 0-group and 1-group - { - Seq_NodeShareOne( pNode, ABC_INIT_ZERO, vNodes ); // shares 0 and DC - Seq_NodeShareOne( pNode, ABC_INIT_ONE, vNodes ); // shares 1 and DC - } - else if ( nLatches[ABC_INIT_ZERO] > 1 ) // 0-group - Seq_NodeShareOne( pNode, ABC_INIT_ZERO, vNodes ); // shares 0 and DC - else if ( nLatches[ABC_INIT_ONE] > 1 ) // 1-group - Seq_NodeShareOne( pNode, ABC_INIT_ONE, vNodes ); // shares 1 and DC - else if ( nLatches[ABC_INIT_DC] > 1 ) // DC-group - { - if ( nLatches[ABC_INIT_ZERO] > 0 ) - Seq_NodeShareOne( pNode, ABC_INIT_ZERO, vNodes ); // shares 0 and DC - else - Seq_NodeShareOne( pNode, ABC_INIT_ONE, vNodes ); // shares 1 and DC - } -} - -/**Function************************************************************* - - Synopsis [Transforms the node to take fanout sharing into account.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NodeShareOne( Abc_Obj_t * pNode, Abc_InitType_t Init, Vec_Ptr_t * vNodes ) -{ - Vec_Int_t * vNums = Seq_ObjLNums( pNode ); - Vec_Ptr_t * vInits = Seq_NodeLats( pNode ); - Abc_Obj_t * pFanout, * pBuffer; - Abc_InitType_t Type, InitNew; - int i; - // collect the fanouts that satisfy the property (have initial value Init or DC) - InitNew = ABC_INIT_DC; - Vec_PtrClear( vNodes ); - Abc_ObjForEachFanout( pNode, pFanout, i ) - { - if ( Seq_ObjFanoutL(pNode, pFanout) == 0 ) - continue; - Type = Seq_NodeGetInitLast( pFanout, Abc_ObjFanoutEdgeNum(pNode, pFanout) ); - if ( Type == Init ) - InitNew = Init; - if ( Type == Init || Type == ABC_INIT_DC ) - { - Vec_PtrPush( vNodes, pFanout ); - Seq_NodeDeleteLast( pFanout, Abc_ObjFanoutEdgeNum(pNode, pFanout) ); - } - } - // create the new buffer - pBuffer = Abc_NtkCreateNode( pNode->pNtk ); - Abc_ObjAddFanin( pBuffer, pNode ); - - // grow storage for initial states - Vec_PtrGrow( vInits, 2 * pBuffer->Id + 2 ); - for ( i = Vec_PtrSize(vInits); i < 2 * (int)pBuffer->Id + 2; i++ ) - Vec_PtrPush( vInits, NULL ); - // grow storage for numbers of latches - Vec_IntGrow( vNums, 2 * pBuffer->Id + 2 ); - for ( i = Vec_IntSize(vNums); i < 2 * (int)pBuffer->Id + 2; i++ ) - Vec_IntPush( vNums, 0 ); - // insert the new latch - Seq_NodeInsertFirst( pBuffer, 0, InitNew ); - - // redirect the fanouts - Vec_PtrForEachEntry( vNodes, pFanout, i ) - Abc_ObjPatchFanin( pFanout, pNode, pBuffer ); -} - - - - - -/**Function************************************************************* - - Synopsis [Maps virtual latches into real latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Seq_NtkShareLatchesKey( Abc_Obj_t * pObj, Abc_InitType_t Init ) -{ - return (pObj->Id << 2) | Init; -} - -/**Function************************************************************* - - Synopsis [Maps virtual latches into real latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Seq_NtkShareLatches_rec( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj, Seq_Lat_t * pRing, int nLatch, stmm_table * tLatchMap ) -{ - Abc_Obj_t * pLatch, * pFanin; - Abc_InitType_t Init; - unsigned Key; - if ( nLatch == 0 ) - return pObj; - assert( pRing->pLatch == NULL ); - // get the latch on the previous level - pFanin = Seq_NtkShareLatches_rec( pNtk, pObj, Seq_LatNext(pRing), nLatch - 1, tLatchMap ); - - // get the initial state - Init = Seq_LatInit( pRing ); - // check if the latch with this initial state exists - Key = Seq_NtkShareLatchesKey( pFanin, Init ); - if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) ) - return pRing->pLatch = pLatch; - - // does not exist - if ( Init != ABC_INIT_DC ) - { - // check if the don't-care exists - Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_DC ); - if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) ) // yes - { - // update the table - stmm_delete( tLatchMap, (char **)&Key, (char **)&pLatch ); - Key = Seq_NtkShareLatchesKey( pFanin, Init ); - stmm_insert( tLatchMap, (char *)Key, (char *)pLatch ); - // change don't-care to the given value - pLatch->pData = (void *)Init; - return pRing->pLatch = pLatch; - } - - // add the latch with this value - pLatch = Abc_NtkCreateLatch( pNtk ); - pLatch->pData = (void *)Init; - Abc_ObjAddFanin( pLatch, pFanin ); - // add it to the table - Key = Seq_NtkShareLatchesKey( pFanin, Init ); - stmm_insert( tLatchMap, (char *)Key, (char *)pLatch ); - return pRing->pLatch = pLatch; - } - // the init value is the don't-care - - // check if care values exist - Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_ZERO ); - if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) ) - { - Seq_LatSetInit( pRing, ABC_INIT_ZERO ); - return pRing->pLatch = pLatch; - } - Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_ONE ); - if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) ) - { - Seq_LatSetInit( pRing, ABC_INIT_ONE ); - return pRing->pLatch = pLatch; - } - - // create the don't-care latch - pLatch = Abc_NtkCreateLatch( pNtk ); - pLatch->pData = (void *)ABC_INIT_DC; - Abc_ObjAddFanin( pLatch, pFanin ); - // add it to the table - Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_DC ); - stmm_insert( tLatchMap, (char *)Key, (char *)pLatch ); - return pRing->pLatch = pLatch; -} - -/**Function************************************************************* - - Synopsis [Maps virtual latches into real latches.] - - Description [Creates new latches and assigns them to virtual latches - on the edges of a sequential AIG. The nodes of the new network should - be created before this procedure is called.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkShareLatches( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj, * pFanin; - stmm_table * tLatchMap; - int i; - assert( Abc_NtkIsSeq( pNtk ) ); - tLatchMap = stmm_init_table( stmm_ptrcmp, stmm_ptrhash ); - Abc_AigForEachAnd( pNtk, pObj, i ) - { - pFanin = Abc_ObjFanin0(pObj); - Seq_NtkShareLatches_rec( pNtkNew, pFanin->pCopy, Seq_NodeGetRing(pObj,0), Seq_NodeCountLats(pObj,0), tLatchMap ); - pFanin = Abc_ObjFanin1(pObj); - Seq_NtkShareLatches_rec( pNtkNew, pFanin->pCopy, Seq_NodeGetRing(pObj,1), Seq_NodeCountLats(pObj,1), tLatchMap ); - } - Abc_NtkForEachPo( pNtk, pObj, i ) - Seq_NtkShareLatches_rec( pNtkNew, Abc_ObjFanin0(pObj)->pCopy, Seq_NodeGetRing(pObj,0), Seq_NodeCountLats(pObj,0), tLatchMap ); - stmm_free_table( tLatchMap ); -} - -/**Function************************************************************* - - Synopsis [Maps virtual latches into real latches.] - - Description [Creates new latches and assigns them to virtual latches - on the edges of a sequential AIG. The nodes of the new network should - be created before this procedure is called.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkShareLatchesMapping( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapAnds, int fFpga ) -{ - Seq_Match_t * pMatch; - Abc_Obj_t * pObj, * pFanout; - stmm_table * tLatchMap; - Vec_Ptr_t * vNodes; - int i, k; - assert( Abc_NtkIsSeq( pNtk ) ); - - // start the table - tLatchMap = stmm_init_table( stmm_ptrcmp, stmm_ptrhash ); - - // create the array of all nodes with sharable fanouts - vNodes = Vec_PtrAlloc( 100 ); - Vec_PtrPush( vNodes, Abc_AigConst1(pNtk) ); - Abc_NtkForEachPi( pNtk, pObj, i ) - Vec_PtrPush( vNodes, pObj ); - if ( fFpga ) - { - Vec_PtrForEachEntry( vMapAnds, pObj, i ) - Vec_PtrPush( vNodes, pObj ); - } - else - { - Vec_PtrForEachEntry( vMapAnds, pMatch, i ) - Vec_PtrPush( vNodes, pMatch->pAnd ); - } - - // process nodes used in the mapping - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - // make sure the label is clean - Abc_ObjForEachFanout( pObj, pFanout, k ) - assert( pFanout->fMarkC == 0 ); - Abc_ObjForEachFanout( pObj, pFanout, k ) - { - if ( pFanout->fMarkC ) - continue; - pFanout->fMarkC = 1; - if ( Abc_ObjFaninId0(pFanout) == pObj->Id ) - Seq_NtkShareLatches_rec( pNtkNew, pObj->pCopy, Seq_NodeGetRing(pFanout,0), Seq_NodeCountLats(pFanout,0), tLatchMap ); - if ( Abc_ObjFaninId1(pFanout) == pObj->Id ) - Seq_NtkShareLatches_rec( pNtkNew, pObj->pCopy, Seq_NodeGetRing(pFanout,1), Seq_NodeCountLats(pFanout,1), tLatchMap ); - } - // clean the label - Abc_ObjForEachFanout( pObj, pFanout, k ) - pFanout->fMarkC = 0; - } - stmm_free_table( tLatchMap ); - // return to the old array - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Clean the latches after sharing them.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkShareLatchesClean( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - assert( Abc_NtkIsSeq( pNtk ) ); - Abc_AigForEachAnd( pNtk, pObj, i ) - { - Seq_NodeCleanLats( pObj, 0 ); - Seq_NodeCleanLats( pObj, 1 ); - } - Abc_NtkForEachPo( pNtk, pObj, i ) - Seq_NodeCleanLats( pObj, 0 ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/base/seq/seqUtil.c b/src/base/seq/seqUtil.c deleted file mode 100644 index 55b9df8e..00000000 --- a/src/base/seq/seqUtil.c +++ /dev/null @@ -1,597 +0,0 @@ -/**CFile**************************************************************** - - FileName [seqUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Construction and manipulation of sequential AIGs.] - - Synopsis [Various utilities working with sequential AIGs.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: seqUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "seqInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the maximum latch number on any of the fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkLevelMax( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pNode; - int i, Result; - assert( Abc_NtkIsSeq(pNtk) ); - Result = 0; - Abc_NtkForEachPo( pNtk, pNode, i ) - { - pNode = Abc_ObjFanin0(pNode); - if ( Result < (int)pNode->Level ) - Result = pNode->Level; - } - Abc_SeqForEachCutsetNode( pNtk, pNode, i ) - { - if ( Result < (int)pNode->Level ) - Result = pNode->Level; - } - return Result; -} - -/**Function************************************************************* - - Synopsis [Returns the maximum latch number on any of the fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_ObjFanoutLMax( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout; - int i, nLatchCur, nLatchRes; - if ( Abc_ObjFanoutNum(pObj) == 0 ) - return 0; - nLatchRes = 0; - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - nLatchCur = Seq_ObjFanoutL(pObj, pFanout); - if ( nLatchRes < nLatchCur ) - nLatchRes = nLatchCur; - } - assert( nLatchRes >= 0 ); - return nLatchRes; -} - -/**Function************************************************************* - - Synopsis [Returns the minimum latch number on any of the fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_ObjFanoutLMin( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout; - int i, nLatchCur, nLatchRes; - if ( Abc_ObjFanoutNum(pObj) == 0 ) - return 0; - nLatchRes = ABC_INFINITY; - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - nLatchCur = Seq_ObjFanoutL(pObj, pFanout); - if ( nLatchRes > nLatchCur ) - nLatchRes = nLatchCur; - } - assert( nLatchRes < ABC_INFINITY ); - return nLatchRes; -} - -/**Function************************************************************* - - Synopsis [Returns the sum of latches on the fanout edges.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_ObjFanoutLSum( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout; - int i, nSum = 0; - Abc_ObjForEachFanout( pObj, pFanout, i ) - nSum += Seq_ObjFanoutL(pObj, pFanout); - return nSum; -} - -/**Function************************************************************* - - Synopsis [Returns the sum of latches on the fanin edges.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_ObjFaninLSum( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i, nSum = 0; - Abc_ObjForEachFanin( pObj, pFanin, i ) - nSum += Seq_ObjFaninL(pObj, i); - return nSum; -} - -/**Function************************************************************* - - Synopsis [Generates the printable edge label with the initial state.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Seq_ObjFaninGetInitPrintable( Abc_Obj_t * pObj, int Edge ) -{ - static char Buffer[1000]; - Abc_InitType_t Init; - int nLatches, i; - nLatches = Seq_ObjFaninL( pObj, Edge ); - for ( i = 0; i < nLatches; i++ ) - { - Init = Seq_LatInit( Seq_NodeGetLat(pObj, Edge, i) ); - if ( Init == ABC_INIT_NONE ) - Buffer[i] = '_'; - else if ( Init == ABC_INIT_ZERO ) - Buffer[i] = '0'; - else if ( Init == ABC_INIT_ONE ) - Buffer[i] = '1'; - else if ( Init == ABC_INIT_DC ) - Buffer[i] = 'x'; - else assert( 0 ); - } - Buffer[nLatches] = 0; - return Buffer; -} - -/**Function************************************************************* - - Synopsis [Sets the given value to all the latches of the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NodeLatchSetValues( Abc_Obj_t * pObj, int Edge, Abc_InitType_t Init ) -{ - Seq_Lat_t * pLat, * pRing; - int c; - pRing = Seq_NodeGetRing(pObj, Edge); - if ( pRing == NULL ) - return; - for ( c = 0, pLat = pRing; !c || pLat != pRing; c++, pLat = pLat->pNext ) - Seq_LatSetInit( pLat, Init ); -} - -/**Function************************************************************* - - Synopsis [Sets the given value to all the latches of the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkLatchSetValues( Abc_Ntk_t * pNtk, Abc_InitType_t Init ) -{ - Abc_Obj_t * pObj; - int i; - assert( Abc_NtkIsSeq( pNtk ) ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Seq_NodeLatchSetValues( pObj, 0, Init ); - Abc_NtkForEachNode( pNtk, pObj, i ) - { - Seq_NodeLatchSetValues( pObj, 0, Init ); - Seq_NodeLatchSetValues( pObj, 1, Init ); - } -} - - -/**Function************************************************************* - - Synopsis [Counts the number of latches in the sequential AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkLatchNum( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i, Counter; - assert( Abc_NtkIsSeq( pNtk ) ); - Counter = 0; - Abc_NtkForEachNode( pNtk, pObj, i ) - Counter += Seq_ObjFaninLSum( pObj ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Counter += Seq_ObjFaninLSum( pObj ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of latches in the sequential AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkLatchNumMax( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i, Max, Cur; - assert( Abc_NtkIsSeq( pNtk ) ); - Max = 0; - Abc_AigForEachAnd( pNtk, pObj, i ) - { - Cur = Seq_ObjFaninLMax( pObj ); - if ( Max < Cur ) - Max = Cur; - } - Abc_NtkForEachPo( pNtk, pObj, i ) - { - Cur = Seq_ObjFaninL0( pObj ); - if ( Max < Cur ) - Max = Cur; - } - return Max; -} - -/**Function************************************************************* - - Synopsis [Counts the number of latches in the sequential AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkLatchNumShared( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i, Counter; - assert( Abc_NtkIsSeq( pNtk ) ); - Counter = 0; - Abc_NtkForEachPi( pNtk, pObj, i ) - Counter += Seq_ObjFanoutLMax( pObj ); - Abc_NtkForEachNode( pNtk, pObj, i ) - Counter += Seq_ObjFanoutLMax( pObj ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of latches in the sequential AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_ObjLatchGetInitNums( Abc_Obj_t * pObj, int Edge, int * pInits ) -{ - Abc_InitType_t Init; - int nLatches, i; - nLatches = Seq_ObjFaninL( pObj, Edge ); - for ( i = 0; i < nLatches; i++ ) - { - Init = Seq_NodeGetInitOne( pObj, Edge, i ); - pInits[Init]++; - } -} - -/**Function************************************************************* - - Synopsis [Counts the number of latches in the sequential AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkLatchGetInitNums( Abc_Ntk_t * pNtk, int * pInits ) -{ - Abc_Obj_t * pObj; - int i; - assert( Abc_NtkIsSeq( pNtk ) ); - for ( i = 0; i < 4; i++ ) - pInits[i] = 0; - Abc_NtkForEachPo( pNtk, pObj, i ) - Seq_ObjLatchGetInitNums( pObj, 0, pInits ); - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( Abc_ObjFaninNum(pObj) > 0 ) - Seq_ObjLatchGetInitNums( pObj, 0, pInits ); - if ( Abc_ObjFaninNum(pObj) > 1 ) - Seq_ObjLatchGetInitNums( pObj, 1, pInits ); - } -} - -/**Function************************************************************* - - Synopsis [Report nodes with equal fanins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkLatchGetEqualFaninNum( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i, Counter; - assert( Abc_NtkIsSeq( pNtk ) ); - Counter = 0; - Abc_AigForEachAnd( pNtk, pObj, i ) - if ( Abc_ObjFaninId0(pObj) == Abc_ObjFaninId1(pObj) ) - Counter++; - if ( Counter ) - printf( "The number of nodes with equal fanins = %d.\n", Counter ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns the maximum latch number on any of the fanouts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkCountNodesAboveLimit( Abc_Ntk_t * pNtk, int Limit ) -{ - Abc_Obj_t * pNode; - int i, Counter; - assert( !Abc_NtkIsSeq(pNtk) ); - Counter = 0; - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( Abc_ObjFaninNum(pNode) > Limit ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Computes area flows.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_MapComputeAreaFlows( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Abc_Seq_t * p = pNtk->pManFunc; - Abc_Obj_t * pObj; - float AFlow; - int i, c; - - assert( Abc_NtkIsSeq(pNtk) ); - - Vec_IntFill( p->vAFlows, p->nSize, Abc_Float2Int( (float)0.0 ) ); - - // update all values iteratively - for ( c = 0; c < 7; c++ ) - { - Abc_AigForEachAnd( pNtk, pObj, i ) - { - AFlow = (float)1.0 + Seq_NodeGetFlow( Abc_ObjFanin0(pObj) ) + Seq_NodeGetFlow( Abc_ObjFanin1(pObj) ); - AFlow /= Abc_ObjFanoutNum(pObj); - pObj->pNext = (void *)Abc_Float2Int( AFlow ); - } - Abc_AigForEachAnd( pNtk, pObj, i ) - { - AFlow = Abc_Int2Float( (int)pObj->pNext ); - pObj->pNext = NULL; - Seq_NodeSetFlow( pObj, AFlow ); - -// printf( "%5d : %6.1f\n", pObj->Id, Seq_NodeGetFlow(pObj) ); - } -// printf( "\n" ); - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Collects all the internal nodes reachable from POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkReachNodesFromPos_rec( Abc_Obj_t * pAnd, Vec_Ptr_t * vNodes ) -{ - // skip if this is a non-PI node - if ( !Abc_AigNodeIsAnd(pAnd) ) - return; - // skip a visited node - if ( Abc_NodeIsTravIdCurrent(pAnd) ) - return; - Abc_NodeSetTravIdCurrent(pAnd); - // visit the fanin nodes - Seq_NtkReachNodesFromPos_rec( Abc_ObjFanin0(pAnd), vNodes ); - Seq_NtkReachNodesFromPos_rec( Abc_ObjFanin1(pAnd), vNodes ); - // add this node - Vec_PtrPush( vNodes, pAnd ); -} - -/**Function************************************************************* - - Synopsis [Collects all the internal nodes reachable from POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Seq_NtkReachNodesFromPis_rec( Abc_Obj_t * pAnd, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pFanout; - int k; - // skip if this is a non-PI node - if ( !Abc_AigNodeIsAnd(pAnd) ) - return; - // skip a visited node - if ( Abc_NodeIsTravIdCurrent(pAnd) ) - return; - Abc_NodeSetTravIdCurrent(pAnd); - // visit the fanin nodes - Abc_ObjForEachFanout( pAnd, pFanout, k ) - Seq_NtkReachNodesFromPis_rec( pFanout, vNodes ); - // add this node - Vec_PtrPush( vNodes, pAnd ); -} - -/**Function************************************************************* - - Synopsis [Collects all the internal nodes reachable from POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Seq_NtkReachNodes( Abc_Ntk_t * pNtk, int fFromPos ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pFanout; - int i, k; - assert( Abc_NtkIsSeq(pNtk) ); - vNodes = Vec_PtrAlloc( 1000 ); - Abc_NtkIncrementTravId( pNtk ); - if ( fFromPos ) - { - // traverse the cone of each PO - Abc_NtkForEachPo( pNtk, pObj, i ) - Seq_NtkReachNodesFromPos_rec( Abc_ObjFanin0(pObj), vNodes ); - } - else - { - // tranvers the reverse cone of the constant node - pObj = Abc_AigConst1( pNtk ); - Abc_ObjForEachFanout( pObj, pFanout, k ) - Seq_NtkReachNodesFromPis_rec( pFanout, vNodes ); - // tranvers the reverse cone of the PIs - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjForEachFanout( pObj, pFanout, k ) - Seq_NtkReachNodesFromPis_rec( pFanout, vNodes ); - } - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Perform sequential cleanup.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Seq_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Vec_Ptr_t * vNodesPo, * vNodesPi; - int Counter = 0; - assert( Abc_NtkIsSeq(pNtk) ); - // collect the nodes reachable from POs and PIs - vNodesPo = Seq_NtkReachNodes( pNtk, 1 ); - vNodesPi = Seq_NtkReachNodes( pNtk, 0 ); - printf( "Total nodes = %6d. Reachable from POs = %6d. Reachable from PIs = %6d.\n", - Abc_NtkNodeNum(pNtk), Vec_PtrSize(vNodesPo), Vec_PtrSize(vNodesPi) ); - if ( Abc_NtkNodeNum(pNtk) > Vec_PtrSize(vNodesPo) ) - { -// Counter = Abc_NtkReduceNodes( pNtk, vNodesPo ); - Counter = 0; - if ( fVerbose ) - printf( "Cleanup removed %d nodes that are not reachable from the POs.\n", Counter ); - } - Vec_PtrFree( vNodesPo ); - Vec_PtrFree( vNodesPi ); - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/temp.c b/src/base/temp.c deleted file mode 100644 index 55709247..00000000 --- a/src/base/temp.c +++ /dev/null @@ -1,83 +0,0 @@ - -/**Function************************************************************* - - Synopsis [Command procedure to allow for static BDD variable ordering.] - - Description [This procedure should be integrated in "abc\src\base\abci\abc.c" - similar to how procedure Abc_CommandReorder() is currently integrated.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv ) -{ - FILE * pOut, * pErr, * pFile; - Abc_Ntk_t * pNtk; - char * pFileName; - int c; - int fReverse; - int fVerbose; - extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ); - extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ); - - pNtk = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set defaults - fReverse = 0; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) - { - switch ( c ) - { - case 'r': - fReverse ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - default: - goto usage; - } - } - - if ( pNtk == NULL ) - { - fprintf( pErr, "Empty network.\n" ); - return 1; - } - - // if the var order file is given, implement this order - pFileName = NULL; - if ( argc == globalUtilOptind + 1 ) - { - pFileName = argv[globalUtilOptind]; - pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - fprintf( pErr, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName ); - return 1; - } - fclose( pFile ); - } - if ( pFileName ) - Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose ); - else - Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose ); - return 0; - -usage: - fprintf( pErr, "usage: order [-rvh] \n" ); - fprintf( pErr, "\t computes a good static CI variable order\n" ); - fprintf( pErr, "\t-r : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" ); - fprintf( pErr, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\t : (optional) file with the given variable order\n" ); - return 1; -} diff --git a/src/base/ver/module.make b/src/base/ver/module.make deleted file mode 100644 index 2cc37803..00000000 --- a/src/base/ver/module.make +++ /dev/null @@ -1,4 +0,0 @@ -SRC += src/base/ver/verCore.c \ - src/base/ver/verFormula.c \ - src/base/ver/verParse.c \ - src/base/ver/verStream.c diff --git a/src/base/ver/ver.h b/src/base/ver/ver.h deleted file mode 100644 index 9c538ac4..00000000 --- a/src/base/ver/ver.h +++ /dev/null @@ -1,118 +0,0 @@ -/**CFile**************************************************************** - - FileName [ver.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: ver.h,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VER_H__ -#define __VER_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Ver_Man_t_ Ver_Man_t; -typedef struct Ver_Stream_t_ Ver_Stream_t; - -struct Ver_Man_t_ -{ - // internal parameters - int fMapped; // mapped verilog - int fUseMemMan; // allocate memory manager in the networks - int fCheck; // checks network for currectness - // input file stream - char * pFileName; - Ver_Stream_t * pReader; - int fNameLast; - ProgressBar * pProgress; - // current design - Abc_Lib_t * pDesign; - st_table * tName2Suffix; - // error handling - FILE * Output; - int fTopLevel; - int fError; - char sError[2000]; - // intermediate structures - Vec_Ptr_t * vNames; - Vec_Ptr_t * vStackFn; - Vec_Int_t * vStackOp; - Vec_Int_t * vPerm; -}; - - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== verCore.c ========================================================*/ -extern Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ); -extern void Ver_ParsePrintErrorMessage( Ver_Man_t * p ); -/*=== verFormula.c ========================================================*/ -extern void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ); -extern void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ); -/*=== verParse.c ========================================================*/ -extern int Ver_ParseSkipComments( Ver_Man_t * p ); -extern char * Ver_ParseGetName( Ver_Man_t * p ); -/*=== verStream.c ========================================================*/ -extern Ver_Stream_t * Ver_StreamAlloc( char * pFileName ); -extern void Ver_StreamFree( Ver_Stream_t * p ); -extern char * Ver_StreamGetFileName( Ver_Stream_t * p ); -extern int Ver_StreamGetFileSize( Ver_Stream_t * p ); -extern int Ver_StreamGetCurPosition( Ver_Stream_t * p ); -extern int Ver_StreamGetLineNumber( Ver_Stream_t * p ); - -extern int Ver_StreamIsOkey( Ver_Stream_t * p ); -extern char Ver_StreamScanChar( Ver_Stream_t * p ); -extern char Ver_StreamPopChar( Ver_Stream_t * p ); -extern void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ); -extern void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ); -extern char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/base/ver/verCore.c b/src/base/ver/verCore.c deleted file mode 100644 index 6d7d230e..00000000 --- a/src/base/ver/verCore.c +++ /dev/null @@ -1,2839 +0,0 @@ -/**CFile**************************************************************** - - FileName [verCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Parses several flavors of structural Verilog.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: verCore.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" -#include "mio.h" -#include "main.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// types of verilog signals -typedef enum { - VER_SIG_NONE = 0, - VER_SIG_INPUT, - VER_SIG_OUTPUT, - VER_SIG_INOUT, - VER_SIG_REG, - VER_SIG_WIRE -} Ver_SignalType_t; - -// types of verilog gates -typedef enum { - VER_GATE_AND = 0, - VER_GATE_OR, - VER_GATE_XOR, - VER_GATE_BUF, - VER_GATE_NAND, - VER_GATE_NOR, - VER_GATE_XNOR, - VER_GATE_NOT -} Ver_GateType_t; - -static Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib ); -static void Ver_ParseStop( Ver_Man_t * p ); -static void Ver_ParseFreeData( Ver_Man_t * p ); -static void Ver_ParseInternal( Ver_Man_t * p ); -static int Ver_ParseModule( Ver_Man_t * p ); -static int Ver_ParseSignal( Ver_Man_t * p, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType ); -static int Ver_ParseAlways( Ver_Man_t * p, Abc_Ntk_t * pNtk ); -static int Ver_ParseInitial( Ver_Man_t * p, Abc_Ntk_t * pNtk ); -static int Ver_ParseAssign( Ver_Man_t * p, Abc_Ntk_t * pNtk ); -static int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType ); -static int Ver_ParseGate( Ver_Man_t * p, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate ); -static int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox ); -static int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox ); -static int Ver_ParseAttachBoxes( Ver_Man_t * pMan ); - -static Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ); -static Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ); -static Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO ); -static Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ); - -static void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan ); - -static inline int Ver_NtkIsDefined( Abc_Ntk_t * pNtkBox ) { assert( pNtkBox->pName ); return Abc_NtkPiNum(pNtkBox) || Abc_NtkPoNum(pNtkBox); } -static inline int Ver_ObjIsConnected( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBox(pObj) ); return Abc_ObjFaninNum(pObj) || Abc_ObjFanoutNum(pObj); } - -int glo_fMapped = 0; // this is bad! - -typedef struct Ver_Bundle_t_ Ver_Bundle_t; -struct Ver_Bundle_t_ -{ - char * pNameFormal; // the name of the formal net - Vec_Ptr_t * vNetsActual; // the vector of actual nets (MSB to LSB) -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start parser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ver_Man_t * Ver_ParseStart( char * pFileName, Abc_Lib_t * pGateLib ) -{ - Ver_Man_t * p; - p = ALLOC( Ver_Man_t, 1 ); - memset( p, 0, sizeof(Ver_Man_t) ); - p->pFileName = pFileName; - p->pReader = Ver_StreamAlloc( pFileName ); - if ( p->pReader == NULL ) - return NULL; - p->Output = stdout; - p->vNames = Vec_PtrAlloc( 100 ); - p->vStackFn = Vec_PtrAlloc( 100 ); - p->vStackOp = Vec_IntAlloc( 100 ); - p->vPerm = Vec_IntAlloc( 100 ); - // create the design library and assign the technology library - p->pDesign = Abc_LibCreate( pFileName ); - p->pDesign->pLibrary = pGateLib; - p->pDesign->pGenlib = Abc_FrameReadLibGen(); - return p; -} - -/**Function************************************************************* - - Synopsis [Stop parser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParseStop( Ver_Man_t * p ) -{ - if ( p->pProgress ) - Extra_ProgressBarStop( p->pProgress ); - Ver_StreamFree( p->pReader ); - Vec_PtrFree( p->vNames ); - Vec_PtrFree( p->vStackFn ); - Vec_IntFree( p->vStackOp ); - Vec_IntFree( p->vPerm ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [File parser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Lib_t * Ver_ParseFile( char * pFileName, Abc_Lib_t * pGateLib, int fCheck, int fUseMemMan ) -{ - Ver_Man_t * p; - Abc_Lib_t * pDesign; - // start the parser - p = Ver_ParseStart( pFileName, pGateLib ); - p->fMapped = glo_fMapped; - p->fCheck = fCheck; - p->fUseMemMan = fUseMemMan; - if ( glo_fMapped ) - { - Hop_ManStop(p->pDesign->pManFunc); - p->pDesign->pManFunc = NULL; - } - // parse the file - Ver_ParseInternal( p ); - // save the result - pDesign = p->pDesign; - p->pDesign = NULL; - // stop the parser - Ver_ParseStop( p ); - return pDesign; -} - -/**Function************************************************************* - - Synopsis [File parser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParseInternal( Ver_Man_t * pMan ) -{ - Abc_Ntk_t * pNtk; - char * pToken; - int i; - - // preparse the modeles - pMan->pProgress = Extra_ProgressBarStart( stdout, Ver_StreamGetFileSize(pMan->pReader) ); - while ( 1 ) - { - // get the next token - pToken = Ver_ParseGetName( pMan ); - if ( pToken == NULL ) - break; - if ( strcmp( pToken, "module" ) ) - { - sprintf( pMan->sError, "Cannot read \"module\" directive." ); - Ver_ParsePrintErrorMessage( pMan ); - return; - } - // parse the module - if ( !Ver_ParseModule(pMan) ) - return; - } - Extra_ProgressBarStop( pMan->pProgress ); - pMan->pProgress = NULL; - - // process defined and undefined boxes - if ( !Ver_ParseAttachBoxes( pMan ) ) - return; - - // connect the boxes and check - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - { - // fix the dangling nets - Abc_NtkFinalizeRead( pNtk ); - // check the network for correctness - if ( pMan->fCheck && !Abc_NtkCheckRead( pNtk ) ) - { - pMan->fTopLevel = 1; - sprintf( pMan->sError, "The network check has failed for network %s.", pNtk->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return; - } - } -} - -/**Function************************************************************* - - Synopsis [File parser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParseFreeData( Ver_Man_t * p ) -{ - if ( p->pDesign ) - { - Abc_LibFree( p->pDesign, NULL ); - p->pDesign = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Prints the error message including the file name and line number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParsePrintErrorMessage( Ver_Man_t * p ) -{ - p->fError = 1; - if ( p->fTopLevel ) // the line number is not given - fprintf( p->Output, "%s: %s\n", p->pFileName, p->sError ); - else // print the error message with the line number - fprintf( p->Output, "%s (line %d): %s\n", - p->pFileName, Ver_StreamGetLineNumber(p->pReader), p->sError ); - // free the data - Ver_ParseFreeData( p ); -} - -/**Function************************************************************* - - Synopsis [Finds the network by name or create a new blackbox network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Ver_ParseFindOrCreateNetwork( Ver_Man_t * pMan, char * pName ) -{ - Abc_Ntk_t * pNtkNew; - // check if the network exists - if ( pNtkNew = Abc_LibFindModelByName( pMan->pDesign, pName ) ) - return pNtkNew; -//printf( "Creating network %s.\n", pName ); - // create new network - pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_BLACKBOX, pMan->fUseMemMan ); - pNtkNew->pName = Extra_UtilStrsav( pName ); - pNtkNew->pSpec = NULL; - // add module to the design - Abc_LibAddModel( pMan->pDesign, pNtkNew ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Finds the network by name or create a new blackbox network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Ver_ParseFindNet( Abc_Ntk_t * pNtk, char * pName ) -{ - Abc_Obj_t * pObj; - if ( pObj = Abc_NtkFindNet(pNtk, pName) ) - return pObj; - if ( !strcmp( pName, "1\'b0" ) || !strcmp( pName, "1\'bx" ) ) - return Abc_NtkFindOrCreateNet( pNtk, "1\'b0" ); - if ( !strcmp( pName, "1\'b1" ) ) - return Abc_NtkFindOrCreateNet( pNtk, "1\'b1" ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Converts the network from the blackbox type into a different one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseConvertNetwork( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, int fMapped ) -{ - if ( fMapped ) - { - // convert from the blackbox into the network with local functions representated by AIGs - if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) - { - // change network type - assert( pNtk->pManFunc == NULL ); - pNtk->ntkFunc = ABC_FUNC_MAP; - pNtk->pManFunc = pMan->pDesign->pGenlib; - } - else if ( pNtk->ntkFunc != ABC_FUNC_MAP ) - { - sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - } - else - { - // convert from the blackbox into the network with local functions representated by AIGs - if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) - { - // change network type - assert( pNtk->pManFunc == NULL ); - pNtk->ntkFunc = ABC_FUNC_AIG; - pNtk->pManFunc = pMan->pDesign->pManFunc; - } - else if ( pNtk->ntkFunc != ABC_FUNC_AIG ) - { - sprintf( pMan->sError, "The network %s appears to have both gates and assign statements. Currently such network are not allowed. One way to fix this problem might be to replace assigns by buffers from the library.", pNtk->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses one Verilog module.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseModule( Ver_Man_t * pMan ) -{ - Mio_Gate_t * pGate; - Ver_Stream_t * p = pMan->pReader; - Abc_Ntk_t * pNtk, * pNtkTemp; - char * pWord, Symbol; - int RetValue; - - // get the network name - pWord = Ver_ParseGetName( pMan ); - - // get the network with this name - pNtk = Ver_ParseFindOrCreateNetwork( pMan, pWord ); - - // make sure we stopped at the opening paranthesis - if ( Ver_StreamPopChar(p) != '(' ) - { - sprintf( pMan->sError, "Cannot find \"(\" after \"module\" in network %s.", pNtk->pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // skip to the end of parantheses - do { - if ( Ver_ParseGetName( pMan ) == NULL ) - return 0; - Symbol = Ver_StreamPopChar(p); - } while ( Symbol == ',' ); - assert( Symbol == ')' ); - if ( !Ver_ParseSkipComments( pMan ) ) - return 0; - Symbol = Ver_StreamPopChar(p); - if ( Symbol != ';' ) - { - sprintf( pMan->sError, "Expected closing paranthesis after \"module\"." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // parse the inputs/outputs/registers/wires/inouts - while ( 1 ) - { - Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - if ( !strcmp( pWord, "input" ) ) - RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INPUT ); - else if ( !strcmp( pWord, "output" ) ) - RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_OUTPUT ); - else if ( !strcmp( pWord, "reg" ) ) - RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_REG ); - else if ( !strcmp( pWord, "wire" ) ) - RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_WIRE ); - else if ( !strcmp( pWord, "inout" ) ) - RetValue = Ver_ParseSignal( pMan, pNtk, VER_SIG_INOUT ); - else - break; - if ( RetValue == 0 ) - return 0; - } - - // parse the remaining statements - while ( 1 ) - { - Extra_ProgressBarUpdate( pMan->pProgress, Ver_StreamGetCurPosition(p), NULL ); - - if ( !strcmp( pWord, "and" ) ) - RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_AND ); - else if ( !strcmp( pWord, "or" ) ) - RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_OR ); - else if ( !strcmp( pWord, "xor" ) ) - RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XOR ); - else if ( !strcmp( pWord, "buf" ) ) - RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_BUF ); - else if ( !strcmp( pWord, "nand" ) ) - RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NAND ); - else if ( !strcmp( pWord, "nor" ) ) - RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOR ); - else if ( !strcmp( pWord, "xnor" ) ) - RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_XNOR ); - else if ( !strcmp( pWord, "not" ) ) - RetValue = Ver_ParseGateStandard( pMan, pNtk, VER_GATE_NOT ); - - else if ( !strcmp( pWord, "assign" ) ) - RetValue = Ver_ParseAssign( pMan, pNtk ); - else if ( !strcmp( pWord, "always" ) ) - RetValue = Ver_ParseAlways( pMan, pNtk ); - else if ( !strcmp( pWord, "initial" ) ) - RetValue = Ver_ParseInitial( pMan, pNtk ); - else if ( !strcmp( pWord, "endmodule" ) ) - break; - else if ( pMan->pDesign->pGenlib && (pGate = Mio_LibraryReadGateByName(pMan->pDesign->pGenlib, pWord)) ) // current design - RetValue = Ver_ParseGate( pMan, pNtk, pGate ); -// else if ( pMan->pDesign->pLibrary && st_lookup(pMan->pDesign->pLibrary->tModules, pWord, (char**)&pNtkTemp) ) // gate library -// RetValue = Ver_ParseGate( pMan, pNtkTemp ); - else // assume this is the box used in the current design - { - pNtkTemp = Ver_ParseFindOrCreateNetwork( pMan, pWord ); - RetValue = Ver_ParseBox( pMan, pNtk, pNtkTemp ); - } - if ( RetValue == 0 ) - return 0; - // skip the comments - if ( !Ver_ParseSkipComments( pMan ) ) - return 0; - // get new word - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - } - - // convert from the blackbox into the network with local functions representated by AIGs - if ( pNtk->ntkFunc == ABC_FUNC_BLACKBOX ) - { - if ( Abc_NtkNodeNum(pNtk) > 0 || Abc_NtkBoxNum(pNtk) > 0 ) - { - if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) - return 0; - } - else - { - Abc_Obj_t * pObj, * pBox, * pTerm; - int i; - pBox = Abc_NtkCreateBlackbox(pNtk); - Abc_NtkForEachPi( pNtk, pObj, i ) - { - pTerm = Abc_NtkCreateBi(pNtk); - Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) ); - Abc_ObjAddFanin( pBox, pTerm ); - } - Abc_NtkForEachPo( pNtk, pObj, i ) - { - pTerm = Abc_NtkCreateBo(pNtk); - Abc_ObjAddFanin( pTerm, pBox ); - Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm ); - } - } - } - - // remove the table if needed - Ver_ParseRemoveSuffixTable( pMan ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Lookups the suffix of the signal of the form [m:n].] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseLookupSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb ) -{ - unsigned Value; - *pnMsb = *pnLsb = -1; - if ( pMan->tName2Suffix == NULL ) - return 1; - if ( !st_lookup( pMan->tName2Suffix, (char *)pWord, (char **)&Value ) ) - return 1; - *pnMsb = (Value >> 8) & 0xff; - *pnLsb = Value & 0xff; - return 1; -} - -/**Function************************************************************* - - Synopsis [Lookups the suffix of the signal of the form [m:n].] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseInsertsSuffix( Ver_Man_t * pMan, char * pWord, int nMsb, int nLsb ) -{ - unsigned Value; - if ( pMan->tName2Suffix == NULL ) - pMan->tName2Suffix = st_init_table( strcmp, st_strhash ); - if ( st_is_member( pMan->tName2Suffix, pWord ) ) - return 1; - assert( nMsb >= 0 && nMsb < 128 ); - assert( nLsb >= 0 && nLsb < 128 ); - Value = (nMsb << 8) | nLsb; - st_insert( pMan->tName2Suffix, Extra_UtilStrsav(pWord), (char *)Value ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Lookups the suffic of the signal of the form [m:n].] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParseRemoveSuffixTable( Ver_Man_t * pMan ) -{ - st_generator * gen; - char * pKey, * pValue; - if ( pMan->tName2Suffix == NULL ) - return; - st_foreach_item( pMan->tName2Suffix, gen, (char **)&pKey, (char **)&pValue ) - free( pKey ); - st_free_table( pMan->tName2Suffix ); - pMan->tName2Suffix = NULL; -} - -/**Function************************************************************* - - Synopsis [Determine signal prefix of the form [Beg:End].] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseSignalPrefix( Ver_Man_t * pMan, char ** ppWord, int * pnMsb, int * pnLsb ) -{ - char * pWord = *ppWord; - int nMsb, nLsb; - assert( pWord[0] == '[' ); - // get the beginning - nMsb = atoi( pWord + 1 ); - // find the splitter - while ( *pWord && *pWord != ':' && *pWord != ']' ) - pWord++; - if ( *pWord == 0 ) - { - sprintf( pMan->sError, "Cannot find closing bracket in this line." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - if ( *pWord == ']' ) - nLsb = nMsb; - else - { - assert( *pWord == ':' ); - nLsb = atoi( pWord + 1 ); - // find the closing paranthesis - while ( *pWord && *pWord != ']' ) - pWord++; - if ( *pWord == 0 ) - { - sprintf( pMan->sError, "Cannot find closing bracket in this line." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - assert( *pWord == ']' ); - pWord++; - } - assert( nMsb >= 0 && nLsb >= 0 ); - // return - *ppWord = pWord; - *pnMsb = nMsb; - *pnLsb = nLsb; - return 1; -} - -/**Function************************************************************* - - Synopsis [Determine signal suffix of the form [m:n].] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseSignalSuffix( Ver_Man_t * pMan, char * pWord, int * pnMsb, int * pnLsb ) -{ - char * pCur; - int Length; - Length = strlen(pWord); - assert( pWord[Length-1] == ']' ); - // walk backward - for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- ) - if ( *pCur == ':' || *pCur == '[' ) - break; - if ( pCur == pWord ) - { - sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - if ( *pCur == '[' ) - { - *pnMsb = *pnLsb = atoi(pCur+1); - *pCur = 0; - return 1; - } - assert( *pCur == ':' ); - // get the end of the interval - *pnLsb = atoi(pCur+1); - // find the beginning - for ( pCur = pWord + Length - 2; pCur != pWord; pCur-- ) - if ( *pCur == '[' ) - break; - if ( pCur == pWord ) - { - sprintf( pMan->sError, "Cannot find opening bracket in signal name %s.", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - assert( *pCur == '[' ); - // get the beginning of the interval - *pnMsb = atoi(pCur+1); - // cut the word - *pCur = 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns the values of constant bits.] - - Description [The resulting bits are in MSB to LSB order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseConstant( Ver_Man_t * pMan, char * pWord ) -{ - int nBits, i; - assert( pWord[0] >= '1' && pWord[1] <= '9' ); - nBits = atoi(pWord); - // find the next symbol \' - while ( *pWord && *pWord != '\'' ) - pWord++; - if ( *pWord == 0 ) - { - sprintf( pMan->sError, "Cannot find symbol \' in the constant." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - assert( *pWord == '\'' ); - pWord++; - if ( *pWord != 'b' ) - { - sprintf( pMan->sError, "Currently can only handle binary constants." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - pWord++; - // scan the bits - Vec_PtrClear( pMan->vNames ); - for ( i = 0; i < nBits; i++ ) - { - if ( pWord[i] != '0' && pWord[i] != '1' && pWord[i] != 'x' ) - { - sprintf( pMan->sError, "Having problem parsing the binary constant." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - if ( pWord[i] == 'x' ) - Vec_PtrPush( pMan->vNames, (void *)0 ); - else - Vec_PtrPush( pMan->vNames, (void *)(pWord[i]-'0') ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [The signals are added in the order from LSB to MSB.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseSignal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_SignalType_t SigType ) -{ - Ver_Stream_t * p = pMan->pReader; - char Buffer[1000], Symbol, * pWord; - int nMsb, nLsb, Bit, Limit, i; - nMsb = nLsb = -1; - while ( 1 ) - { - // get the next word - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - - // check if the range is specified - if ( pWord[0] == '[' && !pMan->fNameLast ) - { - assert( nMsb == -1 && nLsb == -1 ); - Ver_ParseSignalPrefix( pMan, &pWord, &nMsb, &nLsb ); - // check the case when there is space between bracket and the next word - if ( *pWord == 0 ) - { - // get the signal name - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - } - } - - // create signals - if ( nMsb == -1 && nLsb == -1 ) - { - if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT ) - Ver_ParseCreatePi( pNtk, pWord ); - if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT ) - Ver_ParseCreatePo( pNtk, pWord ); - if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG ) - Abc_NtkFindOrCreateNet( pNtk, pWord ); - } - else - { - assert( nMsb >= 0 && nLsb >= 0 ); - // add to the hash table - Ver_ParseInsertsSuffix( pMan, pWord, nMsb, nLsb ); - // add signals from Lsb to Msb - Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1; - for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 ) - { - sprintf( Buffer, "%s[%d]", pWord, Bit ); - if ( SigType == VER_SIG_INPUT || SigType == VER_SIG_INOUT ) - Ver_ParseCreatePi( pNtk, Buffer ); - if ( SigType == VER_SIG_OUTPUT || SigType == VER_SIG_INOUT ) - Ver_ParseCreatePo( pNtk, Buffer ); - if ( SigType == VER_SIG_WIRE || SigType == VER_SIG_REG ) - Abc_NtkFindOrCreateNet( pNtk, Buffer ); - } - } - - Symbol = Ver_StreamPopChar(p); - if ( Symbol == ',' ) - continue; - if ( Symbol == ';' ) - return 1; - break; - } - sprintf( pMan->sError, "Cannot parse signal line (expected , or ;)." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseAlways( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) -{ - Ver_Stream_t * p = pMan->pReader; - Abc_Obj_t * pNet, * pNet2; - int fStopAfterOne; - char * pWord, * pWord2; - char Symbol; - // parse the directive - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - if ( pWord[0] == '@' ) - { - Ver_StreamSkipToChars( p, ")" ); - Ver_StreamPopChar(p); - // parse the directive - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - } - // decide how many statements to parse - fStopAfterOne = 0; - if ( strcmp( pWord, "begin" ) ) - fStopAfterOne = 1; - // iterate over the initial states - while ( 1 ) - { - if ( !fStopAfterOne ) - { - // get the name of the output signal - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // look for the end of directive - if ( !strcmp( pWord, "end" ) ) - break; - } - // get the fanout net - pNet = Ver_ParseFindNet( pNtk, pWord ); - if ( pNet == NULL ) - { - sprintf( pMan->sError, "Cannot read the always statement for %s (output wire is not defined).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // get the equality sign - Symbol = Ver_StreamPopChar(p); - if ( Symbol != '<' && Symbol != '=' ) - { - sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - if ( Symbol == '<' ) - Ver_StreamPopChar(p); - // skip the comments - if ( !Ver_ParseSkipComments( pMan ) ) - return 0; - // get the second name - pWord2 = Ver_ParseGetName( pMan ); - if ( pWord2 == NULL ) - return 0; - // check if the name is complemented - if ( pWord2[0] == '~' ) - { - pNet2 = Ver_ParseFindNet( pNtk, pWord2+1 ); - pNet2 = Ver_ParseCreateInv( pNtk, pNet2 ); - } - else - pNet2 = Ver_ParseFindNet( pNtk, pWord2 ); - if ( pNet2 == NULL ) - { - sprintf( pMan->sError, "Cannot read the always statement for %s (input wire is not defined).", pWord2 ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // create the latch - Ver_ParseCreateLatch( pNtk, pNet2, pNet ); - // remove the last symbol - Symbol = Ver_StreamPopChar(p); - assert( Symbol == ';' ); - // quit if only one directive - if ( fStopAfterOne ) - break; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseInitial( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) -{ - Ver_Stream_t * p = pMan->pReader; - Abc_Obj_t * pNode, * pNet; - int fStopAfterOne; - char * pWord, * pEquation; - char Symbol; - // parse the directive - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // decide how many statements to parse - fStopAfterOne = 0; - if ( strcmp( pWord, "begin" ) ) - fStopAfterOne = 1; - // iterate over the initial states - while ( 1 ) - { - if ( !fStopAfterOne ) - { - // get the name of the output signal - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // look for the end of directive - if ( !strcmp( pWord, "end" ) ) - break; - } - // get the fanout net - pNet = Ver_ParseFindNet( pNtk, pWord ); - if ( pNet == NULL ) - { - sprintf( pMan->sError, "Cannot read the initial statement for %s (output wire is not defined).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // get the equality sign - Symbol = Ver_StreamPopChar(p); - if ( Symbol != '<' && Symbol != '=' ) - { - sprintf( pMan->sError, "Cannot read the assign statement for %s (expected <= or =).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - if ( Symbol == '<' ) - Ver_StreamPopChar(p); - // skip the comments - if ( !Ver_ParseSkipComments( pMan ) ) - return 0; - // get the second name - pEquation = Ver_StreamGetWord( p, ";" ); - if ( pEquation == NULL ) - return 0; - // find the corresponding latch - if ( Abc_ObjFaninNum(pNet) == 0 ) - { - sprintf( pMan->sError, "Cannot find the latch to assign the initial value." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - pNode = Abc_ObjFanin0(Abc_ObjFanin0(pNet)); - assert( Abc_ObjIsLatch(pNode) ); - // set the initial state - if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") ) - Abc_LatchSetInit0( pNode ); - else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") ) - Abc_LatchSetInit1( pNode ); -// else if ( !strcmp(pEquation, "2") ) -// Abc_LatchSetInitDc( pNode ); - else - { - sprintf( pMan->sError, "Incorrect initial value of the latch %s.", Abc_ObjName(pNet) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // remove the last symbol - Symbol = Ver_StreamPopChar(p); - assert( Symbol == ';' ); - // quit if only one directive - if ( fStopAfterOne ) - break; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseAssign( Ver_Man_t * pMan, Abc_Ntk_t * pNtk ) -{ - char Buffer[1000], Buffer2[1000]; - Ver_Stream_t * p = pMan->pReader; - Abc_Obj_t * pNode, * pNet; - char * pWord, * pName, * pEquation; - Hop_Obj_t * pFunc; - char Symbol; - int i, Bit, Limit, Length, fReduction; - int nMsb, nLsb; - -// if ( Ver_StreamGetLineNumber(p) == 2756 ) -// { -// int x = 0; -// } - - // convert from the blackbox into the network with local functions representated by AIGs - if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) - return 0; - - while ( 1 ) - { - // get the name of the output signal - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // check for vector-inputs - if ( !Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ) ) - return 0; - // handle special case of constant assignment - if ( nMsb >= 0 && nLsb >= 0 ) - { - // save the fanout name - strcpy( Buffer, pWord ); - // get the equality sign - if ( Ver_StreamPopChar(p) != '=' ) - { - sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // get the constant - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // check if it is indeed a constant - if ( !(pWord[0] >= '0' && pWord[0] <= '9') ) - { - sprintf( pMan->sError, "Currently can only assign vector-signal \"%s\" to be a constant.", Buffer ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // get individual bits of the constant - if ( !Ver_ParseConstant( pMan, pWord ) ) - return 0; - // check that the constant has the same size - Limit = nMsb > nLsb? nMsb - nLsb + 1: nLsb - nMsb + 1; - if ( Limit != Vec_PtrSize(pMan->vNames) ) - { - sprintf( pMan->sError, "The constant size (%d) is different from the signal\"%s\" size (%d).", - Vec_PtrSize(pMan->vNames), Buffer, Limit ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // iterate through the bits - for ( i = 0, Bit = nLsb; i < Limit; i++, Bit = nMsb > nLsb ? Bit + 1: Bit - 1 ) - { - // get the fanin net - if ( Vec_PtrEntry( pMan->vNames, Limit-1-i ) ) - pNet = Ver_ParseFindNet( pNtk, "1\'b1" ); - else - pNet = Ver_ParseFindNet( pNtk, "1\'b0" ); - assert( pNet != NULL ); - - // create the buffer - pNode = Abc_NtkCreateNodeBuf( pNtk, pNet ); - - // get the fanout net - sprintf( Buffer2, "%s[%d]", Buffer, Bit ); - pNet = Ver_ParseFindNet( pNtk, Buffer2 ); - if ( pNet == NULL ) - { - sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Abc_ObjAddFanin( pNet, pNode ); - } - // go to the end of the line - Ver_ParseSkipComments( pMan ); - } - else - { - // consider the case of reduction operations - fReduction = 0; - if ( pWord[0] == '{' && !pMan->fNameLast ) - fReduction = 1; - if ( fReduction ) - { - pWord++; - pWord[strlen(pWord)-1] = 0; - assert( pWord[0] != '\\' ); - } - // get the fanout net - pNet = Ver_ParseFindNet( pNtk, pWord ); - if ( pNet == NULL ) - { - sprintf( pMan->sError, "Cannot read the assign statement for %s (output wire is not defined).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // get the equality sign - if ( Ver_StreamPopChar(p) != '=' ) - { - sprintf( pMan->sError, "Cannot read the assign statement for %s (expected equality sign).", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // skip the comments - if ( !Ver_ParseSkipComments( pMan ) ) - return 0; - // get the second name - if ( fReduction ) - pEquation = Ver_StreamGetWord( p, ";" ); - else - pEquation = Ver_StreamGetWord( p, ",;" ); - if ( pEquation == NULL ) - { - sprintf( pMan->sError, "Cannot read the equation for %s.", Abc_ObjName(pNet) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // consider the case of mapped network - Vec_PtrClear( pMan->vNames ); - if ( pMan->fMapped ) - { - if ( !strcmp( pEquation, "1\'b0" ) ) - pFunc = (Hop_Obj_t *)Mio_LibraryReadConst0(Abc_FrameReadLibGen()); - else if ( !strcmp( pEquation, "1\'b1" ) ) - pFunc = (Hop_Obj_t *)Mio_LibraryReadConst1(Abc_FrameReadLibGen()); - else - { - // "assign foo = \bar ;" - if ( *pEquation == '\\' ) - { - pEquation++; - pEquation[strlen(pEquation) - 1] = 0; - } - if ( Ver_ParseFindNet(pNtk, pEquation) == NULL ) - { - sprintf( pMan->sError, "Cannot read Verilog with non-trivial assignments in the mapped netlist." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Vec_PtrPush( pMan->vNames, (void *)strlen(pEquation) ); - Vec_PtrPush( pMan->vNames, pEquation ); - // get the buffer - pFunc = (Hop_Obj_t *)Mio_LibraryReadBuf(Abc_FrameReadLibGen()); - if ( pFunc == NULL ) - { - sprintf( pMan->sError, "Reading assign statement for node %s has failed because the genlib library has no buffer.", Abc_ObjName(pNet) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - } - } - else - { - if ( !strcmp(pEquation, "0") || !strcmp(pEquation, "1\'b0") || !strcmp(pEquation, "1\'bx") ) - pFunc = Hop_ManConst0(pNtk->pManFunc); - else if ( !strcmp(pEquation, "1") || !strcmp(pEquation, "1\'b1") ) - pFunc = Hop_ManConst1(pNtk->pManFunc); - else if ( fReduction ) - pFunc = Ver_FormulaReduction( pEquation, pNtk->pManFunc, pMan->vNames, pMan->sError ); - else - pFunc = Ver_FormulaParser( pEquation, pNtk->pManFunc, pMan->vNames, pMan->vStackFn, pMan->vStackOp, pMan->sError ); - if ( pFunc == NULL ) - { - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - } - - // create the node with the given inputs - pNode = Abc_NtkCreateNode( pNtk ); - pNode->pData = pFunc; - Abc_ObjAddFanin( pNet, pNode ); - // connect to fanin nets - for ( i = 0; i < Vec_PtrSize(pMan->vNames)/2; i++ ) - { - // get the name of this signal - Length = (int)Vec_PtrEntry( pMan->vNames, 2*i ); - pName = Vec_PtrEntry( pMan->vNames, 2*i + 1 ); - pName[Length] = 0; - // find the corresponding net - pNet = Ver_ParseFindNet( pNtk, pName ); - if ( pNet == NULL ) - { - sprintf( pMan->sError, "Cannot read the assign statement for %s (input wire %s is not defined).", pWord, pName ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Abc_ObjAddFanin( pNode, pNet ); - } - } - - Symbol = Ver_StreamPopChar(p); - if ( Symbol == ',' ) - continue; - if ( Symbol == ';' ) - return 1; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t GateType ) -{ - Ver_Stream_t * p = pMan->pReader; - Abc_Obj_t * pNet, * pNode; - char * pWord, Symbol; - - // convert from the blackbox into the network with local functions representated by AIGs - if ( !Ver_ParseConvertNetwork( pMan, pNtk, pMan->fMapped ) ) - return 0; - - // this is gate name - throw it away - if ( Ver_StreamPopChar(p) != '(' ) - { - sprintf( pMan->sError, "Cannot parse a standard gate (expected opening paranthesis)." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - - // create the node - pNode = Abc_NtkCreateNode( pNtk ); - - // parse pairs of formal/actural inputs - while ( 1 ) - { - // parse the output name - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // get the net corresponding to this output - pNet = Ver_ParseFindNet( pNtk, pWord ); - if ( pNet == NULL ) - { - sprintf( pMan->sError, "Net is missing in gate %s.", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // if this is the first net, add it as an output - if ( Abc_ObjFanoutNum(pNode) == 0 ) - Abc_ObjAddFanin( pNet, pNode ); - else - Abc_ObjAddFanin( pNode, pNet ); - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - Symbol = Ver_StreamPopChar(p); - if ( Symbol == ')' ) - break; - // skip comma - if ( Symbol != ',' ) - { - sprintf( pMan->sError, "Cannot parse a standard gate %s (expected closing paranthesis).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - } - if ( (GateType == VER_GATE_BUF || GateType == VER_GATE_NOT) && Abc_ObjFaninNum(pNode) != 1 ) - { - sprintf( pMan->sError, "Buffer or interver with multiple fanouts %s (currently not supported).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - if ( Ver_StreamPopChar(p) != ';' ) - { - sprintf( pMan->sError, "Cannot read standard gate %s (expected closing semicolumn).", Abc_ObjName(Abc_ObjFanout0(pNode)) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // add logic function - if ( GateType == VER_GATE_AND || GateType == VER_GATE_NAND ) - pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); - else if ( GateType == VER_GATE_OR || GateType == VER_GATE_NOR ) - pNode->pData = Hop_CreateOr( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); - else if ( GateType == VER_GATE_XOR || GateType == VER_GATE_XNOR ) - pNode->pData = Hop_CreateExor( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); - else if ( GateType == VER_GATE_BUF || GateType == VER_GATE_NOT ) - pNode->pData = Hop_CreateAnd( pNtk->pManFunc, Abc_ObjFaninNum(pNode) ); - if ( GateType == VER_GATE_NAND || GateType == VER_GATE_NOR || GateType == VER_GATE_XNOR || GateType == VER_GATE_NOT ) - pNode->pData = Hop_Not( pNode->pData ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns the index of the given pin the gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_FindGateInput( Mio_Gate_t * pGate, char * pName ) -{ - Mio_Pin_t * pGatePin; - int i; - for ( i = 0, pGatePin = Mio_GateReadPins(pGate); pGatePin != NULL; pGatePin = Mio_PinReadNext(pGatePin), i++ ) - if ( strcmp(pName, Mio_PinReadName(pGatePin)) == 0 ) - return i; - if ( strcmp(pName, Mio_GateReadOutName(pGate)) == 0 ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseGate( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Mio_Gate_t * pGate ) -{ - Ver_Stream_t * p = pMan->pReader; - Abc_Obj_t * pNetActual, * pNode; - char * pWord, Symbol; - int Input, i, nFanins = Mio_GateReadInputs(pGate); - - // convert from the blackbox into the network with local functions representated by gates - if ( 1 != pMan->fMapped ) - { - sprintf( pMan->sError, "The network appears to be mapped. Use \"r -m\" to read mapped Verilog." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // update the network type if needed - if ( !Ver_ParseConvertNetwork( pMan, pNtk, 1 ) ) - return 0; - - // parse the directive and set the pointers to the PIs/POs of the gate - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // this is gate name - throw it away - if ( Ver_StreamPopChar(p) != '(' ) - { - sprintf( pMan->sError, "Cannot parse gate %s (expected opening paranthesis).", Mio_GateReadName(pGate) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - - // start the node - pNode = Abc_NtkCreateNode( pNtk ); - pNode->pData = pGate; - - // parse pairs of formal/actural inputs - Vec_IntClear( pMan->vPerm ); - while ( 1 ) - { - // process one pair of formal/actual parameters - if ( Ver_StreamPopChar(p) != '.' ) - { - sprintf( pMan->sError, "Cannot parse gate %s (expected .).", Mio_GateReadName(pGate) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // parse the formal name - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - - // find the corresponding pin of the gate - Input = Ver_FindGateInput( pGate, pWord ); - if ( Input == -1 ) - { - sprintf( pMan->sError, "Formal input name %s cannot be found in the gate %s.", pWord, Mio_GateReadOutName(pGate) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // open the paranthesis - if ( Ver_StreamPopChar(p) != '(' ) - { - sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected opening paranthesis).", pWord, Mio_GateReadName(pGate) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // parse the actual name - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // check if the name is complemented - assert( pWord[0] != '~' ); -/* - fCompl = (pWord[0] == '~'); - if ( fCompl ) - { - fComplUsed = 1; - pWord++; - if ( pNtk->pData == NULL ) - pNtk->pData = Extra_MmFlexStart(); - } -*/ - // get the actual net - pNetActual = Ver_ParseFindNet( pNtk, pWord ); - if ( pNetActual == NULL ) - { - sprintf( pMan->sError, "Actual net %s is missing.", pWord ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // close the paranthesis - if ( Ver_StreamPopChar(p) != ')' ) - { - sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Mio_GateReadName(pGate) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // add the fanin - if ( Input < nFanins ) - { - Vec_IntPush( pMan->vPerm, Input ); - Abc_ObjAddFanin( pNode, pNetActual ); // fanin - } - else - Abc_ObjAddFanin( pNetActual, pNode ); // fanout - - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - Symbol = Ver_StreamPopChar(p); - if ( Symbol == ')' ) - break; - - // skip comma - if ( Symbol != ',' ) - { - sprintf( pMan->sError, "Cannot formal parameter %s of gate %s (expected closing paranthesis).", pWord, Mio_GateReadName(pGate) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - } - - // check that the gate as the same number of input - if ( !(Abc_ObjFaninNum(pNode) == nFanins && Abc_ObjFanoutNum(pNode) == 1) ) - { - sprintf( pMan->sError, "Parsing of gate %s has failed.", Mio_GateReadName(pGate) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - if ( Ver_StreamPopChar(p) != ';' ) - { - sprintf( pMan->sError, "Cannot read gate %s (expected closing semicolumn).", Mio_GateReadName(pGate) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // check if we need to permute the inputs - Vec_IntForEachEntry( pMan->vPerm, Input, i ) - if ( Input != i ) - break; - if ( i < Vec_IntSize(pMan->vPerm) ) - { - // add the fanin numnbers to the end of the permuation array - for ( i = 0; i < nFanins; i++ ) - Vec_IntPush( pMan->vPerm, Abc_ObjFaninId(pNode, i) ); - // write the fanin numbers into their corresponding places (according to the gate) - for ( i = 0; i < nFanins; i++ ) - Vec_IntWriteEntry( &pNode->vFanins, Vec_IntEntry(pMan->vPerm, i), Vec_IntEntry(pMan->vPerm, i+nFanins) ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Parses one directive.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseBox( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkBox ) -{ - char Buffer[1000]; - Ver_Stream_t * p = pMan->pReader; - Ver_Bundle_t * pBundle; - Vec_Ptr_t * vBundles; - Abc_Obj_t * pNetActual; - Abc_Obj_t * pNode; - char * pWord, Symbol; - int fCompl, fFormalIsGiven; - int i, k, Bit, Limit, nMsb, nLsb, fQuit, flag; - - // gate the name of the box - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - - // create a box with this name - pNode = Abc_NtkCreateBlackbox( pNtk ); - pNode->pData = pNtkBox; - Abc_ObjAssignName( pNode, pWord, NULL ); - - // continue parsing the box - if ( Ver_StreamPopChar(p) != '(' ) - { - sprintf( pMan->sError, "Cannot parse box %s (expected opening paranthesis).", Abc_ObjName(pNode) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - - // parse pairs of formal/actual inputs - vBundles = Vec_PtrAlloc( 16 ); - pNode->pCopy = (Abc_Obj_t *)vBundles; - while ( 1 ) - { - // allocate the bundle (formal name + array of actual nets) - pBundle = ALLOC( Ver_Bundle_t, 1 ); - pBundle->pNameFormal = NULL; - pBundle->vNetsActual = Vec_PtrAlloc( 4 ); - Vec_PtrPush( vBundles, pBundle ); - - // process one pair of formal/actual parameters - fFormalIsGiven = 0; - if ( Ver_StreamScanChar(p) == '.' ) - { - fFormalIsGiven = 1; - if ( Ver_StreamPopChar(p) != '.' ) - { - sprintf( pMan->sError, "Cannot parse box %s (expected .).", Abc_ObjName(pNode) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - // parse the formal name - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - - // save the name - pBundle->pNameFormal = Extra_UtilStrsav( pWord ); - - // open the paranthesis - if ( Ver_StreamPopChar(p) != '(' ) - { - sprintf( pMan->sError, "Cannot formal parameter %s of box %s (expected opening paranthesis).", pWord, Abc_ObjName(pNode)); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - } - - // check if this is the beginning of {} expression - Symbol = Ver_StreamScanChar(p); - - // consider the case of vector-inputs - if ( Symbol == '{' ) - { - // skip this char - Ver_StreamPopChar(p); - - // read actual names - i = 0; - fQuit = 0; - while ( 1 ) - { - // parse the formal name - Ver_ParseSkipComments( pMan ); - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - - // check if the last char is a closing brace - if ( pWord[strlen(pWord)-1] == '}' ) - { - pWord[strlen(pWord)-1] = 0; - fQuit = 1; - } - if ( pWord[0] == 0 ) - break; - - // check for constant - if ( pWord[0] >= '1' && pWord[0] <= '9' ) - { - if ( !Ver_ParseConstant( pMan, pWord ) ) - return 0; - // add constant MSB to LSB - for ( k = 0; k < Vec_PtrSize(pMan->vNames); k++, i++ ) - { - // get the actual net - sprintf( Buffer, "1\'b%d", (int)(Vec_PtrEntry(pMan->vNames,k) != NULL) ); - pNetActual = Ver_ParseFindNet( pNtk, Buffer ); - if ( pNetActual == NULL ) - { - sprintf( pMan->sError, "Actual net \"%s\" is missing in gate \"%s\".", Buffer, Abc_ObjName(pNode) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Vec_PtrPush( pBundle->vNetsActual, pNetActual ); - } - } - else - { - // get the suffix of the form [m:n] - if ( pWord[strlen(pWord)-1] == ']' && !pMan->fNameLast ) - Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb ); - else - Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ); - - // generate signals - if ( nMsb == -1 && nLsb == -1 ) - { - // get the actual net - pNetActual = Ver_ParseFindNet( pNtk, pWord ); - if ( pNetActual == NULL ) - { - if ( !strncmp(pWord, "Open_", 5) || - !strncmp(pWord, "dct_unconnected", 15) ) - pNetActual = Abc_NtkCreateNet( pNtk ); - else - { - sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - } - Vec_PtrPush( pBundle->vNetsActual, pNetActual ); - i++; - } - else - { - // go from MSB to LSB - assert( nMsb >= 0 && nLsb >= 0 ); - Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1; - for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--, i++ ) - { - // get the actual net - sprintf( Buffer, "%s[%d]", pWord, Bit ); - pNetActual = Ver_ParseFindNet( pNtk, Buffer ); - if ( pNetActual == NULL ) - { - if ( !strncmp(pWord, "Open_", 5) || - !strncmp(pWord, "dct_unconnected", 15) ) - pNetActual = Abc_NtkCreateNet( pNtk ); - else - { - sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - } - Vec_PtrPush( pBundle->vNetsActual, pNetActual ); - } - } - } - - if ( fQuit ) - break; - - // skip comma - Ver_ParseSkipComments( pMan ); - Symbol = Ver_StreamPopChar(p); - if ( Symbol == '}' ) - break; - if ( Symbol != ',' ) - { - sprintf( pMan->sError, "Cannot parse formal parameter %s of gate %s (expected comma).", pWord, Abc_ObjName(pNode) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - } - } - else - { - // get the next word - pWord = Ver_ParseGetName( pMan ); - if ( pWord == NULL ) - return 0; - // consider the case of empty name - fCompl = 0; - if ( pWord[0] == 0 ) - { - pNetActual = Abc_NtkCreateNet( pNtk ); - Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) ); - } - else - { - // get the actual net - flag=0; - pNetActual = Ver_ParseFindNet( pNtk, pWord ); - if ( pNetActual == NULL ) - { - Ver_ParseLookupSuffix( pMan, pWord, &nMsb, &nLsb ); - if ( nMsb == -1 && nLsb == -1 ) - { - Ver_ParseSignalSuffix( pMan, pWord, &nMsb, &nLsb ); - if ( nMsb == -1 && nLsb == -1 ) - { - if ( !strncmp(pWord, "Open_", 5) || - !strncmp(pWord, "dct_unconnected", 15) ) - { - pNetActual = Abc_NtkCreateNet( pNtk ); - Vec_PtrPush( pBundle->vNetsActual, pNetActual ); - } - else - { - sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - } - else - { - flag=1; - } - } - else - { - flag=1; - } - if (flag) - { - Limit = (nMsb > nLsb) ? nMsb - nLsb + 1: nLsb - nMsb + 1; - for ( Bit = nMsb, k = Limit - 1; k >= 0; Bit = (nMsb > nLsb ? Bit - 1: Bit + 1), k--) - { - // get the actual net - sprintf( Buffer, "%s[%d]", pWord, Bit ); - pNetActual = Ver_ParseFindNet( pNtk, Buffer ); - if ( pNetActual == NULL ) - { - if ( !strncmp(pWord, "Open_", 5) || - !strncmp(pWord, "dct_unconnected", 15)) - pNetActual = Abc_NtkCreateNet( pNtk ); - else - { - sprintf( pMan->sError, "Actual net \"%s\" is missing in box \"%s\".", pWord, Abc_ObjName(pNode) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - } - Vec_PtrPush( pBundle->vNetsActual, pNetActual ); - } - } - } - else - { - Vec_PtrPush( pBundle->vNetsActual, Abc_ObjNotCond( pNetActual, fCompl ) ); - } - } - } - - if ( fFormalIsGiven ) - { - // close the paranthesis - Ver_ParseSkipComments( pMan ); - if ( Ver_StreamPopChar(p) != ')' ) - { - sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected closing paranthesis).", pWord, Abc_ObjName(pNode) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - } - - // check if it is the end of gate - Symbol = Ver_StreamPopChar(p); - if ( Symbol == ')' ) - break; - // skip comma - if ( Symbol != ',' ) - { - sprintf( pMan->sError, "Cannot parse formal parameter %s of box %s (expected comma).", pWord, Abc_ObjName(pNode) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - Ver_ParseSkipComments( pMan ); - } - - // check if it is the end of gate - Ver_ParseSkipComments( pMan ); - if ( Ver_StreamPopChar(p) != ';' ) - { - sprintf( pMan->sError, "Cannot read box %s (expected closing semicolumn).", Abc_ObjName(pNode) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - - return 1; -} - -/**Function************************************************************* - - Synopsis [Connects one box to the network] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParseFreeBundle( Ver_Bundle_t * pBundle ) -{ - FREE( pBundle->pNameFormal ); - Vec_PtrFree( pBundle->vNetsActual ); - free( pBundle ); -} - -/**Function************************************************************* - - Synopsis [Connects one box to the network] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseConnectBox( Ver_Man_t * pMan, Abc_Obj_t * pBox ) -{ - Vec_Ptr_t * vBundles = (Vec_Ptr_t *)pBox->pCopy; - Abc_Ntk_t * pNtk = pBox->pNtk; - Abc_Ntk_t * pNtkBox = pBox->pData; - Abc_Obj_t * pTerm, * pTermNew, * pNetAct; - Ver_Bundle_t * pBundle; - char * pNameFormal; - int i, k, j, iBundle, Length; - - assert( !Ver_ObjIsConnected(pBox) ); - assert( Ver_NtkIsDefined(pNtkBox) ); - assert( !Abc_NtkHasBlackbox(pNtkBox) || Abc_NtkBoxNum(pNtkBox) == 1 ); -/* - // clean the PI/PO nets - Abc_NtkForEachPi( pNtkBox, pTerm, i ) - Abc_ObjFanout0(pTerm)->pCopy = NULL; - Abc_NtkForEachPo( pNtkBox, pTerm, i ) - Abc_ObjFanin0(pTerm)->pCopy = NULL; -*/ - // check if some of them do not have formal names - Vec_PtrForEachEntry( vBundles, pBundle, k ) - if ( pBundle->pNameFormal == NULL ) - break; - if ( k < Vec_PtrSize(vBundles) ) - { - printf( "Warning: The instance %s of network %s will be connected without using formal names.\n", pNtkBox->pName, Abc_ObjName(pBox) ); - // add all actual nets in the bundles - iBundle = 0; - Vec_PtrForEachEntry( vBundles, pBundle, j ) - iBundle += Vec_PtrSize(pBundle->vNetsActual); - - // check the number of actual nets is the same as the number of formal nets - if ( iBundle != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) - { - sprintf( pMan->sError, "The number of actual IOs (%d) is different from the number of formal IOs (%d) when instantiating network %s in box %s.", - Vec_PtrSize(vBundles), Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox), pNtkBox->pName, Abc_ObjName(pBox) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // connect bundles in the natural order - iBundle = 0; - Abc_NtkForEachPi( pNtkBox, pTerm, i ) - { - pBundle = Vec_PtrEntry( vBundles, iBundle++ ); - // the bundle is found - add the connections - using order LSB to MSB - Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) - { - pTermNew = Abc_NtkCreateBi( pNtk ); - Abc_ObjAddFanin( pBox, pTermNew ); - Abc_ObjAddFanin( pTermNew, pNetAct ); - i++; - } - i--; - } - // create fanins of the box - Abc_NtkForEachPo( pNtkBox, pTerm, i ) - { - pBundle = Vec_PtrEntry( vBundles, iBundle++ ); - // the bundle is found - add the connections - using order LSB to MSB - Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) - { - pTermNew = Abc_NtkCreateBo( pNtk ); - Abc_ObjAddFanin( pTermNew, pBox ); - Abc_ObjAddFanin( pNetAct, pTermNew ); - i++; - } - i--; - } - - // free the bundling - Vec_PtrForEachEntry( vBundles, pBundle, k ) - Ver_ParseFreeBundle( pBundle ); - Vec_PtrFree( vBundles ); - pBox->pCopy = NULL; - return 1; - } - - // bundles arrive in any order - but inside each bundle the order is MSB to LSB - // make sure every formal PI has a corresponding net - Abc_NtkForEachPi( pNtkBox, pTerm, i ) - { - // get the name of this formal net - pNameFormal = Abc_ObjName( Abc_ObjFanout0(pTerm) ); - // try to find the bundle with this formal net - pBundle = NULL; - Vec_PtrForEachEntry( vBundles, pBundle, k ) - if ( !strcmp(pBundle->pNameFormal, pNameFormal) ) - break; - assert( pBundle != NULL ); - // if the bundle is not found, try without parantheses - if ( k == Vec_PtrSize(vBundles) ) - { - pBundle = NULL; - Length = strlen(pNameFormal); - if ( pNameFormal[Length-1] == ']' ) - { - // find the opening brace - for ( Length--; Length >= 0; Length-- ) - if ( pNameFormal[Length] == '[' ) - break; - // compare names before brace - if ( Length > 0 ) - { - Vec_PtrForEachEntry( vBundles, pBundle, j ) - if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) ) - break; - if ( j == Vec_PtrSize(vBundles) ) - pBundle = NULL; - } - } - if ( pBundle == NULL ) - { - sprintf( pMan->sError, "Cannot find an actual net for the formal net %s when instantiating network %s in box %s.", - pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - } - // the bundle is found - add the connections - using order LSB to MSB - Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) - { - pTermNew = Abc_NtkCreateBi( pNtk ); - Abc_ObjAddFanin( pBox, pTermNew ); - Abc_ObjAddFanin( pTermNew, pNetAct ); - i++; - } - i--; - } - - // connect those formal POs that do have nets - Abc_NtkForEachPo( pNtkBox, pTerm, i ) - { - // get the name of this PI - pNameFormal = Abc_ObjName( Abc_ObjFanin0(pTerm) ); - // try to find this formal net in the bundle - pBundle = NULL; - Vec_PtrForEachEntry( vBundles, pBundle, k ) - if ( !strcmp(pBundle->pNameFormal, pNameFormal) ) - break; - assert( pBundle != NULL ); - // if the name is not found, try without parantheses - if ( k == Vec_PtrSize(vBundles) ) - { - pBundle = NULL; - Length = strlen(pNameFormal); - if ( pNameFormal[Length-1] == ']' ) - { - // find the opening brace - for ( Length--; Length >= 0; Length-- ) - if ( pNameFormal[Length] == '[' ) - break; - // compare names before brace - if ( Length > 0 ) - { - Vec_PtrForEachEntry( vBundles, pBundle, j ) - if ( !strncmp(pBundle->pNameFormal, pNameFormal, Length) ) - break; - if ( j == Vec_PtrSize(vBundles) ) - pBundle = NULL; - } - } - if ( pBundle == NULL ) - { -// printf( "Warning: The formal output %s is not driven when instantiating network %s in box %s.", -// pNameFormal, pNtkBox->pName, Abc_ObjName(pBox) ); - continue; - } - } - // the bundle is found - add the connections - Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, k ) - { - if ( !strcmp(Abc_ObjName(pNetAct), "1\'b0") || !strcmp(Abc_ObjName(pNetAct), "1\'b1") ) - { - sprintf( pMan->sError, "It looks like formal output %s is driving a constant net (%s) when instantiating network %s in box %s.", - pBundle->pNameFormal, Abc_ObjName(pNetAct), pNtkBox->pName, Abc_ObjName(pBox) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - pTermNew = Abc_NtkCreateBo( pNtk ); - Abc_ObjAddFanin( pTermNew, pBox ); - Abc_ObjAddFanin( pNetAct, pTermNew ); - i++; - } - i--; - } - - // free the bundling - Vec_PtrForEachEntry( vBundles, pBundle, k ) - Ver_ParseFreeBundle( pBundle ); - Vec_PtrFree( vBundles ); - pBox->pCopy = NULL; - return 1; -} - - -/**Function************************************************************* - - Synopsis [Connects the defined boxes.] - - Description [Returns 2 if there are any undef boxes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseConnectDefBoxes( Ver_Man_t * pMan ) -{ - Abc_Ntk_t * pNtk; - Abc_Obj_t * pBox; - int i, k, RetValue = 1; - // go through all the modules - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - { - // go through all the boxes of this module - Abc_NtkForEachBox( pNtk, pBox, k ) - { - if ( Abc_ObjIsLatch(pBox) ) - continue; - // skip internal boxes of the blackboxes - if ( pBox->pData == NULL ) - continue; - // if the network is undefined, it will be connected later - if ( !Ver_NtkIsDefined(pBox->pData) ) - { - RetValue = 2; - continue; - } - // connect the box - if ( !Ver_ParseConnectBox( pMan, pBox ) ) - return 0; - // if the network is a true blackbox, skip - if ( Abc_NtkHasBlackbox(pBox->pData) ) - continue; - // convert the box to the whitebox - Abc_ObjBlackboxToWhitebox( pBox ); - } - } - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Collects the undef boxes and maps them into their instances.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Ver_ParseCollectUndefBoxes( Ver_Man_t * pMan ) -{ - Vec_Ptr_t * vUndefs; - Abc_Ntk_t * pNtk, * pNtkBox; - Abc_Obj_t * pBox; - int i, k; - // clear the module structures - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - pNtk->pData = NULL; - // go through all the blackboxes - vUndefs = Vec_PtrAlloc( 16 ); - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - { - Abc_NtkForEachBlackbox( pNtk, pBox, k ) - { - pNtkBox = pBox->pData; - if ( pNtkBox == NULL ) - continue; - if ( Ver_NtkIsDefined(pNtkBox) ) - continue; - if ( pNtkBox->pData == NULL ) - { - // save the box - Vec_PtrPush( vUndefs, pNtkBox ); - pNtkBox->pData = Vec_PtrAlloc( 16 ); - } - // save the instance - Vec_PtrPush( pNtkBox->pData, pBox ); - } - } - return vUndefs; -} - -/**Function************************************************************* - - Synopsis [Reports how many times each type of undefined box occurs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParseReportUndefBoxes( Ver_Man_t * pMan ) -{ - Abc_Ntk_t * pNtk; - Abc_Obj_t * pBox; - int i, k, nBoxes; - // clean - nBoxes = 0; - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - { - pNtk->fHiePath = 0; - if ( !Ver_NtkIsDefined(pNtk) ) - nBoxes++; - } - // count - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - Abc_NtkForEachBlackbox( pNtk, pBox, k ) - if ( pBox->pData && !Ver_NtkIsDefined(pBox->pData) ) - ((Abc_Ntk_t *)pBox->pData)->fHiePath++; - // print the stats - printf( "Warning: The design contains %d undefined objects interpreted as blackboxes:\n", nBoxes ); - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - if ( !Ver_NtkIsDefined(pNtk) ) - printf( "%s (%d) ", Abc_NtkName(pNtk), pNtk->fHiePath ); - printf( "\n" ); - // clean - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - pNtk->fHiePath = 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if there are non-driven nets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseCheckNondrivenNets( Vec_Ptr_t * vUndefs ) -{ - Abc_Ntk_t * pNtk; - Ver_Bundle_t * pBundle; - Abc_Obj_t * pBox, * pNet; - int i, k, j, m; - // go through undef box types - Vec_PtrForEachEntry( vUndefs, pNtk, i ) - // go through instances of this type - Vec_PtrForEachEntry( pNtk->pData, pBox, k ) - // go through the bundles of this instance - Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) - // go through the actual nets of this bundle - if ( pBundle ) - Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m ) - { - char * pName = Abc_ObjName(pNet); - if ( Abc_ObjFaninNum(pNet) == 0 ) // non-driven - if ( strcmp(Abc_ObjName(pNet), "1\'b0") && strcmp(Abc_ObjName(pNet), "1\'b1") ) // diff from a const - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Checks if formal nets with the given name are driven in any of the instances of undef boxes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseFormalNetsAreDriven( Abc_Ntk_t * pNtk, char * pNameFormal ) -{ - Ver_Bundle_t * pBundle; - Abc_Obj_t * pBox, * pNet; - int k, j, m; - // go through instances of this type - Vec_PtrForEachEntry( pNtk->pData, pBox, k ) - { - // find a bundle with the given name in this instance - Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) - if ( pBundle && !strcmp( pBundle->pNameFormal, pNameFormal ) ) - break; - // skip non-driven bundles - if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) - continue; - // check if all nets are driven in this bundle - Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m ) - if ( Abc_ObjFaninNum(pNet) > 0 ) - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns the non-driven bundle that is given distance from the end.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ver_Bundle_t * Ver_ParseGetNondrivenBundle( Abc_Ntk_t * pNtk, int Counter ) -{ - Ver_Bundle_t * pBundle; - Abc_Obj_t * pBox, * pNet; - int k, m; - // go through instances of this type - Vec_PtrForEachEntry( pNtk->pData, pBox, k ) - { - if ( Counter >= Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) - continue; - // get the bundle given distance away - pBundle = Vec_PtrEntry( (Vec_Ptr_t *)pBox->pCopy, Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) - 1 - Counter ); - if ( pBundle == NULL ) - continue; - // go through the actual nets of this bundle - Vec_PtrForEachEntry( pBundle->vNetsActual, pNet, m ) - if ( !Abc_ObjFaninNum(pNet) && !Ver_ParseFormalNetsAreDriven(pNtk, pBundle->pNameFormal) ) // non-driven - return pBundle; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Drives the bundle in the given undef box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseDriveFormal( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_Bundle_t * pBundle0 ) -{ - char Buffer[200]; - char * pName; - Ver_Bundle_t * pBundle; - Abc_Obj_t * pBox, * pTerm, * pTermNew, * pNetAct, * pNetFormal; - int k, j, m; - - // drive this net in the undef box - Vec_PtrForEachEntry( pBundle0->vNetsActual, pNetAct, m ) - { - // create the formal net - if ( Vec_PtrSize(pBundle0->vNetsActual) == 1 ) - sprintf( Buffer, "%s", pBundle0->pNameFormal ); - else - sprintf( Buffer, "%s[%d]", pBundle0->pNameFormal, m ); - assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL ); - pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer ); - // connect it to the box - pTerm = Abc_NtkCreateBo( pNtk ); - assert( Abc_NtkBoxNum(pNtk) <= 1 ); - pBox = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk); - Abc_ObjAddFanin( Abc_NtkCreatePo(pNtk), pNetFormal ); - Abc_ObjAddFanin( pNetFormal, pTerm ); - Abc_ObjAddFanin( pTerm, pBox ); - } - - // go through instances of this type - pName = Extra_UtilStrsav(pBundle0->pNameFormal); - Vec_PtrForEachEntry( pNtk->pData, pBox, k ) - { - // find a bundle with the given name in this instance - Vec_PtrForEachEntryReverse( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) - if ( pBundle && !strcmp( pBundle->pNameFormal, pName ) ) - break; - // skip non-driven bundles - if ( j == Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) - continue; - // check if any nets are driven in this bundle - Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m ) - if ( Abc_ObjFaninNum(pNetAct) > 0 ) - { - sprintf( pMan->sError, "Internal error while trying to connect undefined boxes. It is likely that the algorithm currently used has its limitations." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - // drive the nets by the undef box - Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m ) - { - pTermNew = Abc_NtkCreateBo( pNetAct->pNtk ); - Abc_ObjAddFanin( pTermNew, pBox ); - Abc_ObjAddFanin( pNetAct, pTermNew ); - } - // remove the bundle - Ver_ParseFreeBundle( pBundle ); - Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL ); - } - free( pName ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Drives the bundle in the given undef box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseDriveInputs( Ver_Man_t * pMan, Vec_Ptr_t * vUndefs ) -{ - char Buffer[200]; - Ver_Bundle_t * pBundle; - Abc_Ntk_t * pNtk; - Abc_Obj_t * pBox, * pBox2, * pTerm, * pTermNew, * pNetFormal, * pNetAct; - int i, k, j, m, CountCur, CountTotal = -1; - // iterate through the undef boxes - Vec_PtrForEachEntry( vUndefs, pNtk, i ) - { - // count the number of unconnected bundles for instances of this type of box - CountTotal = -1; - Vec_PtrForEachEntry( pNtk->pData, pBox, k ) - { - CountCur = 0; - Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) - CountCur += (pBundle != NULL); - if ( CountTotal == -1 ) - CountTotal = CountCur; - else if ( CountTotal != CountCur ) - { - sprintf( pMan->sError, "The number of formal inputs (%d) is different from the expected one (%d) when instantiating network %s in box %s.", - CountCur, CountTotal, pNtk->pName, Abc_ObjName(pBox) ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; - } - } - - // create formals - pBox = Vec_PtrEntry( pNtk->pData, 0 ); - Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) - { - if ( pBundle == NULL ) - continue; - Vec_PtrForEachEntry( pBundle->vNetsActual, pNetAct, m ) - { - // find create the formal net - if ( Vec_PtrSize(pBundle->vNetsActual) == 1 ) - sprintf( Buffer, "%s", pBundle->pNameFormal ); - else - sprintf( Buffer, "%s[%d]", pBundle->pNameFormal, m ); - assert( Abc_NtkFindNet( pNtk, Buffer ) == NULL ); - pNetFormal = Abc_NtkFindOrCreateNet( pNtk, Buffer ); - // connect - pTerm = Abc_NtkCreateBi( pNtk ); - assert( Abc_NtkBoxNum(pNtk) <= 1 ); - pBox2 = Abc_NtkBoxNum(pNtk)? Abc_NtkBox(pNtk,0) : Abc_NtkCreateBlackbox(pNtk); - Abc_ObjAddFanin( pNetFormal, Abc_NtkCreatePi(pNtk) ); - Abc_ObjAddFanin( pTerm, pNetFormal ); - Abc_ObjAddFanin( pBox2, pTerm ); - } - } - - // go through all the boxes - Vec_PtrForEachEntry( pNtk->pData, pBox, k ) - { - // go through all the bundles - Vec_PtrForEachEntry( (Vec_Ptr_t *)pBox->pCopy, pBundle, j ) - { - if ( pBundle == NULL ) - continue; - // drive the nets by the undef box - Vec_PtrForEachEntryReverse( pBundle->vNetsActual, pNetAct, m ) - { - pTermNew = Abc_NtkCreateBi( pNetAct->pNtk ); - Abc_ObjAddFanin( pBox, pTermNew ); - Abc_ObjAddFanin( pTermNew, pNetAct ); - } - // remove the bundle - Ver_ParseFreeBundle( pBundle ); - Vec_PtrWriteEntry( (Vec_Ptr_t *)pBox->pCopy, j, NULL ); - } - - // free the bundles - Vec_PtrFree( (Vec_Ptr_t *)pBox->pCopy ); - pBox->pCopy = NULL; - } - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Returns the max size of any undef box.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseMaxBoxSize( Vec_Ptr_t * vUndefs ) -{ - Abc_Ntk_t * pNtk; - Abc_Obj_t * pBox; - int i, k, nMaxSize = 0; - // go through undef box types - Vec_PtrForEachEntry( vUndefs, pNtk, i ) - // go through instances of this type - Vec_PtrForEachEntry( pNtk->pData, pBox, k ) - // check the number of bundles of this instance - if ( nMaxSize < Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy) ) - nMaxSize = Vec_PtrSize((Vec_Ptr_t *)pBox->pCopy); - return nMaxSize; -} - -/**Function************************************************************* - - Synopsis [Prints the comprehensive report into a log file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_ParsePrintLog( Ver_Man_t * pMan ) -{ - Abc_Ntk_t * pNtk, * pNtkBox; - Abc_Obj_t * pBox; - FILE * pFile; - char * pNameGeneric; - char Buffer[1000]; - int i, k; - - // open the log file - pNameGeneric = Extra_FileNameGeneric( pMan->pFileName ); - sprintf( Buffer, "%s.log", pNameGeneric ); - free( pNameGeneric ); - pFile = fopen( Buffer, "w" ); - - // count the total number of instances and how many times they occur - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - pNtk->fHieVisited = 0; - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - Abc_NtkForEachBox( pNtk, pBox, k ) - { - if ( Abc_ObjIsLatch(pBox) ) - continue; - pNtkBox = pBox->pData; - if ( pNtkBox == NULL ) - continue; - pNtkBox->fHieVisited++; - } - // print each box and its stats - fprintf( pFile, "The hierarhical design %s contains %d modules:\n", pMan->pFileName, Vec_PtrSize(pMan->pDesign->vModules) ); - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - { - fprintf( pFile, "%-24s : ", Abc_NtkName(pNtk) ); - if ( !Ver_NtkIsDefined(pNtk) ) - fprintf( pFile, "undefbox" ); - else if ( Abc_NtkHasBlackbox(pNtk) ) - fprintf( pFile, "blackbox" ); - else - fprintf( pFile, "logicbox" ); - fprintf( pFile, " instantiated %6d times ", pNtk->fHieVisited ); -// fprintf( pFile, "\n " ); - fprintf( pFile, " pi = %4d", Abc_NtkPiNum(pNtk) ); - fprintf( pFile, " po = %4d", Abc_NtkPiNum(pNtk) ); - fprintf( pFile, " nd = %8d", Abc_NtkNodeNum(pNtk) ); - fprintf( pFile, " lat = %6d", Abc_NtkLatchNum(pNtk) ); - fprintf( pFile, " box = %6d", Abc_NtkBoxNum(pNtk)-Abc_NtkLatchNum(pNtk) ); - fprintf( pFile, "\n" ); - } - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - pNtk->fHieVisited = 0; - - // report instances with dangling outputs - if ( Vec_PtrSize(pMan->pDesign->vModules) > 1 ) - { - Vec_Ptr_t * vBundles; - Ver_Bundle_t * pBundle; - int j, nActNets, Counter = 0, CounterBoxes = 0; - // count the number of instances with dangling outputs - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - { - Abc_NtkForEachBox( pNtk, pBox, k ) - { - if ( Abc_ObjIsLatch(pBox) ) - continue; - vBundles = (Vec_Ptr_t *)pBox->pCopy; - pNtkBox = pBox->pData; - if ( pNtkBox == NULL ) - continue; - if ( !Ver_NtkIsDefined(pNtkBox) ) - continue; - // count the number of actual nets - nActNets = 0; - Vec_PtrForEachEntry( vBundles, pBundle, j ) - nActNets += Vec_PtrSize(pBundle->vNetsActual); - // the box is defined and will be connected - if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) - Counter++; - } - } - if ( Counter == 0 ) - fprintf( pFile, "The outputs of all box instances are connected.\n" ); - else - { - fprintf( pFile, "\n" ); - fprintf( pFile, "The outputs of %d box instances are not connected:\n", Counter ); - // enumerate through the boxes - Vec_PtrForEachEntry( pMan->pDesign->vModules, pNtk, i ) - { - Abc_NtkForEachBox( pNtk, pBox, k ) - { - if ( Abc_ObjIsLatch(pBox) ) - continue; - vBundles = (Vec_Ptr_t *)pBox->pCopy; - pNtkBox = pBox->pData; - if ( pNtkBox == NULL ) - continue; - if ( !Ver_NtkIsDefined(pNtkBox) ) - continue; - // count the number of actual nets - nActNets = 0; - Vec_PtrForEachEntry( vBundles, pBundle, j ) - nActNets += Vec_PtrSize(pBundle->vNetsActual); - // the box is defined and will be connected - if ( nActNets != Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ) - fprintf( pFile, "In module \"%s\" instance \"%s\" of box \"%s\" has different numbers of actual/formal nets (%d/%d).\n", - Abc_NtkName(pNtk), Abc_ObjName(pBox), Abc_NtkName(pNtkBox), nActNets, Abc_NtkPiNum(pNtkBox) + Abc_NtkPoNum(pNtkBox) ); - } - } - } - } - fclose( pFile ); - printf( "Hierarchy statistics can be found in log file \"%s\".\n", Buffer ); -} - - -/**Function************************************************************* - - Synopsis [Attaches the boxes to the network.] - - Description [This procedure is called after the design is parsed. - At that point, all the defined models have their PIs present. - They are connected first. Next undef boxes are processed (if present). - Iteratively, one bundle is selected to be driven by the undef boxes in such - a way that there is no conflict (if it is driven by an instance of the box, - no other net will be driven twice by the same formal net of some other instance - of the same box). In the end, all the remaining nets that cannot be driven - by the undef boxes are connected to the undef boxes as inputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseAttachBoxes( Ver_Man_t * pMan ) -{ - Abc_Ntk_t * pNtk; - Ver_Bundle_t * pBundle; - Vec_Ptr_t * vUndefs; - int i, RetValue, Counter, nMaxBoxSize; - - // print the log file - Ver_ParsePrintLog( pMan ); - - // connect defined boxes - RetValue = Ver_ParseConnectDefBoxes( pMan ); - if ( RetValue < 2 ) - return RetValue; - - // report the boxes - Ver_ParseReportUndefBoxes( pMan ); - - // collect undef box types and their actual instances - vUndefs = Ver_ParseCollectUndefBoxes( pMan ); - assert( Vec_PtrSize( vUndefs ) > 0 ); - - // go through all undef box types - Counter = 0; - nMaxBoxSize = Ver_ParseMaxBoxSize( vUndefs ); - while ( Ver_ParseCheckNondrivenNets(vUndefs) && Counter < nMaxBoxSize ) - { - // go through undef box types - pBundle = NULL; - Vec_PtrForEachEntry( vUndefs, pNtk, i ) - if ( pBundle = Ver_ParseGetNondrivenBundle( pNtk, Counter ) ) - break; - if ( pBundle == NULL ) - { - Counter++; - continue; - } - // drive this bundle by this box - if ( !Ver_ParseDriveFormal( pMan, pNtk, pBundle ) ) - return 0; - } - - // make all the remaining bundles the drivers of undefs - if ( !Ver_ParseDriveInputs( pMan, vUndefs ) ) - return 0; - - // cleanup - Vec_PtrForEachEntry( vUndefs, pNtk, i ) - { - Vec_PtrFree( pNtk->pData ); - pNtk->pData = NULL; - } - Vec_PtrFree( vUndefs ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Creates PI terminal and net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Ver_ParseCreatePi( Abc_Ntk_t * pNtk, char * pName ) -{ - Abc_Obj_t * pNet, * pTerm; - // get the PI net -// pNet = Ver_ParseFindNet( pNtk, pName ); -// if ( pNet ) -// printf( "Warning: PI \"%s\" appears twice in the list.\n", pName ); - pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); - // add the PI node - pTerm = Abc_NtkCreatePi( pNtk ); - Abc_ObjAddFanin( pNet, pTerm ); - return pTerm; -} - -/**Function************************************************************* - - Synopsis [Creates PO terminal and net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Ver_ParseCreatePo( Abc_Ntk_t * pNtk, char * pName ) -{ - Abc_Obj_t * pNet, * pTerm; - // get the PO net -// pNet = Ver_ParseFindNet( pNtk, pName ); -// if ( pNet && Abc_ObjFaninNum(pNet) == 0 ) -// printf( "Warning: PO \"%s\" appears twice in the list.\n", pName ); - pNet = Abc_NtkFindOrCreateNet( pNtk, pName ); - // add the PO node - pTerm = Abc_NtkCreatePo( pNtk ); - Abc_ObjAddFanin( pTerm, pNet ); - return pTerm; -} - -/**Function************************************************************* - - Synopsis [Create a latch with the given input/output.] - - Description [By default, the latch value is a don't-care.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Ver_ParseCreateLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pNetLI, Abc_Obj_t * pNetLO ) -{ - Abc_Obj_t * pLatch, * pTerm; - // add the BO terminal - pTerm = Abc_NtkCreateBi( pNtk ); - Abc_ObjAddFanin( pTerm, pNetLI ); - // add the latch box - pLatch = Abc_NtkCreateLatch( pNtk ); - Abc_ObjAddFanin( pLatch, pTerm ); - // add the BI terminal - pTerm = Abc_NtkCreateBo( pNtk ); - Abc_ObjAddFanin( pTerm, pLatch ); - // get the LO net - Abc_ObjAddFanin( pNetLO, pTerm ); - // set latch name - Abc_ObjAssignName( pLatch, Abc_ObjName(pNetLO), "L" ); - Abc_LatchSetInitDc( pLatch ); - return pLatch; -} - -/**Function************************************************************* - - Synopsis [Creates inverter and returns its net.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Ver_ParseCreateInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ) -{ - Abc_Obj_t * pObj; - pObj = Abc_NtkCreateNodeInv( pNtk, pNet ); - pNet = Abc_NtkCreateNet( pNtk ); - Abc_ObjAddFanin( pNet, pObj ); - return pNet; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/ver/verCore.zip b/src/base/ver/verCore.zip deleted file mode 100644 index cdfcf5a4..00000000 Binary files a/src/base/ver/verCore.zip and /dev/null differ diff --git a/src/base/ver/verFormula.c b/src/base/ver/verFormula.c deleted file mode 100644 index 19a2c523..00000000 --- a/src/base/ver/verFormula.c +++ /dev/null @@ -1,474 +0,0 @@ -/**CFile**************************************************************** - - FileName [verFormula.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Formula parser to read Verilog assign statements.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: verFormula.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the list of operation symbols to be used in expressions -#define VER_PARSE_SYM_OPEN '(' // opening paranthesis -#define VER_PARSE_SYM_CLOSE ')' // closing paranthesis -#define VER_PARSE_SYM_CONST0 '0' // constant 0 -#define VER_PARSE_SYM_CONST1 '1' // constant 1 -#define VER_PARSE_SYM_NEGBEF1 '!' // negation before the variable -#define VER_PARSE_SYM_NEGBEF2 '~' // negation before the variable -#define VER_PARSE_SYM_AND '&' // logic AND -#define VER_PARSE_SYM_OR '|' // logic OR -#define VER_PARSE_SYM_XOR '^' // logic XOR -#define VER_PARSE_SYM_MUX1 '?' // first symbol of MUX -#define VER_PARSE_SYM_MUX2 ':' // second symbol of MUX - -// the list of opcodes (also specifying operation precedence) -#define VER_PARSE_OPER_NEG 7 // negation (highest precedence) -#define VER_PARSE_OPER_AND 6 // logic AND -#define VER_PARSE_OPER_XOR 5 // logic EXOR (a'b | ab') -#define VER_PARSE_OPER_OR 4 // logic OR -#define VER_PARSE_OPER_EQU 3 // equvalence (a'b'| ab ) -#define VER_PARSE_OPER_MUX 2 // MUX(a,b,c) (ab | a'c ) -#define VER_PARSE_OPER_MARK 1 // OpStack token standing for an opening paranthesis - -// these are values of the internal Flag -#define VER_PARSE_FLAG_START 1 // after the opening parenthesis -#define VER_PARSE_FLAG_VAR 2 // after operation is received -#define VER_PARSE_FLAG_OPER 3 // after operation symbol is received -#define VER_PARSE_FLAG_ERROR 4 // when error is detected - -static Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ); -static int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Parser of the formula encountered in assign statements.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Ver_FormulaParser( char * pFormula, void * pMan, Vec_Ptr_t * vNames, Vec_Ptr_t * vStackFn, Vec_Int_t * vStackOp, char * pErrorMessage ) -{ - char * pTemp; - Hop_Obj_t * bFunc, * bTemp; - int nParans, Flag; - int Oper, Oper1, Oper2; - int v; - - // clear the stacks and the names - Vec_PtrClear( vNames ); - Vec_PtrClear( vStackFn ); - Vec_IntClear( vStackOp ); - - if ( !strcmp(pFormula, "0") || !strcmp(pFormula, "1\'b0") ) - return Hop_ManConst0(pMan); - if ( !strcmp(pFormula, "1") || !strcmp(pFormula, "1\'b1") ) - return Hop_ManConst1(pMan); - - // make sure that the number of opening and closing parantheses is the same - nParans = 0; - for ( pTemp = pFormula; *pTemp; pTemp++ ) - if ( *pTemp == '(' ) - nParans++; - else if ( *pTemp == ')' ) - nParans--; - if ( nParans != 0 ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): Different number of opening and closing parantheses ()." ); - return NULL; - } - - // add parantheses - pTemp = pFormula + strlen(pFormula) + 2; - *pTemp-- = 0; *pTemp = ')'; - while ( --pTemp != pFormula ) - *pTemp = *(pTemp - 1); - *pTemp = '('; - - // perform parsing - Flag = VER_PARSE_FLAG_START; - for ( pTemp = pFormula; *pTemp; pTemp++ ) - { - switch ( *pTemp ) - { - // skip all spaces, tabs, and end-of-lines - case ' ': - case '\t': - case '\r': - case '\n': - continue; -/* - // treat Constant 0 as a variable - case VER_PARSE_SYM_CONST0: - Vec_PtrPush( vStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( Hop_ManConst0(pMan) ); - if ( Flag == VER_PARSE_FLAG_VAR ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 0." ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - Flag = VER_PARSE_FLAG_VAR; - break; - - // the same for Constant 1 - case VER_PARSE_SYM_CONST1: - Vec_PtrPush( vStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( Hop_ManConst1(pMan) ); - if ( Flag == VER_PARSE_FLAG_VAR ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): No operation symbol before constant 1." ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - Flag = VER_PARSE_FLAG_VAR; - break; -*/ - case VER_PARSE_SYM_NEGBEF1: - case VER_PARSE_SYM_NEGBEF2: - if ( Flag == VER_PARSE_FLAG_VAR ) - {// if NEGBEF follows a variable, AND is assumed - sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before negation." ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - Vec_IntPush( vStackOp, VER_PARSE_OPER_NEG ); - break; - - case VER_PARSE_SYM_AND: - case VER_PARSE_SYM_OR: - case VER_PARSE_SYM_XOR: - case VER_PARSE_SYM_MUX1: - case VER_PARSE_SYM_MUX2: - if ( Flag != VER_PARSE_FLAG_VAR ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR." ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - if ( *pTemp == VER_PARSE_SYM_AND ) - Vec_IntPush( vStackOp, VER_PARSE_OPER_AND ); - else if ( *pTemp == VER_PARSE_SYM_OR ) - Vec_IntPush( vStackOp, VER_PARSE_OPER_OR ); - else if ( *pTemp == VER_PARSE_SYM_XOR ) - Vec_IntPush( vStackOp, VER_PARSE_OPER_XOR ); - else if ( *pTemp == VER_PARSE_SYM_MUX1 ) - Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); -// else if ( *pTemp == VER_PARSE_SYM_MUX2 ) -// Vec_IntPush( vStackOp, VER_PARSE_OPER_MUX ); - Flag = VER_PARSE_FLAG_OPER; - break; - - case VER_PARSE_SYM_OPEN: - if ( Flag == VER_PARSE_FLAG_VAR ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): Variable before a paranthesis." ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - Vec_IntPush( vStackOp, VER_PARSE_OPER_MARK ); - // after an opening bracket, it feels like starting over again - Flag = VER_PARSE_FLAG_START; - break; - - case VER_PARSE_SYM_CLOSE: - if ( Vec_IntSize( vStackOp ) ) - { - while ( 1 ) - { - if ( !Vec_IntSize( vStackOp ) ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - Oper = Vec_IntPop( vStackOp ); - if ( Oper == VER_PARSE_OPER_MARK ) - break; - // skip the second MUX operation -// if ( Oper == VER_PARSE_OPER_MUX2 ) -// { -// Oper = Vec_IntPop( vStackOp ); -// assert( Oper == VER_PARSE_OPER_MUX1 ); -// } - - // perform the given operation - if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper ) == NULL ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); - return NULL; - } - } - } - else - { - sprintf( pErrorMessage, "Parse_FormulaParser(): There is no opening paranthesis\n" ); - Flag = VER_PARSE_FLAG_ERROR; - break; - } - if ( Flag != VER_PARSE_FLAG_ERROR ) - Flag = VER_PARSE_FLAG_VAR; - break; - - - default: - // scan the next name - v = Ver_FormulaParserFindVar( pTemp, vNames ); - if ( *pTemp == '\\' ) - pTemp++; - pTemp += (int)Vec_PtrEntry( vNames, 2*v ) - 1; - - // assume operation AND, if vars follow one another - if ( Flag == VER_PARSE_FLAG_VAR ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): Incorrect state." ); - return NULL; - } - bTemp = Hop_IthVar( pMan, v ); - Vec_PtrPush( vStackFn, bTemp ); // Cudd_Ref( bTemp ); - Flag = VER_PARSE_FLAG_VAR; - break; - } - - if ( Flag == VER_PARSE_FLAG_ERROR ) - break; // error exit - else if ( Flag == VER_PARSE_FLAG_START ) - continue; // go on parsing - else if ( Flag == VER_PARSE_FLAG_VAR ) - while ( 1 ) - { // check if there are negations in the OpStack - if ( !Vec_IntSize(vStackOp) ) - break; - Oper = Vec_IntPop( vStackOp ); - if ( Oper != VER_PARSE_OPER_NEG ) - { - Vec_IntPush( vStackOp, Oper ); - break; - } - else - { -// Vec_PtrPush( vStackFn, Cudd_Not(Vec_PtrPop(vStackFn)) ); - Vec_PtrPush( vStackFn, Hop_Not(Vec_PtrPop(vStackFn)) ); - } - } - else // if ( Flag == VER_PARSE_FLAG_OPER ) - while ( 1 ) - { // execute all the operations in the OpStack - // with precedence higher or equal than the last one - Oper1 = Vec_IntPop( vStackOp ); // the last operation - if ( !Vec_IntSize(vStackOp) ) - { // if it is the only operation, push it back - Vec_IntPush( vStackOp, Oper1 ); - break; - } - Oper2 = Vec_IntPop( vStackOp ); // the operation before the last one - if ( Oper2 >= Oper1 && !(Oper1 == Oper2 && Oper1 == VER_PARSE_OPER_MUX) ) - { // if Oper2 precedence is higher or equal, execute it - if ( Ver_FormulaParserTopOper( pMan, vStackFn, Oper2 ) == NULL ) - { - sprintf( pErrorMessage, "Parse_FormulaParser(): Unknown operation\n" ); - return NULL; - } - Vec_IntPush( vStackOp, Oper1 ); // push the last operation back - } - else - { // if Oper2 precedence is lower, push them back and done - Vec_IntPush( vStackOp, Oper2 ); - Vec_IntPush( vStackOp, Oper1 ); - break; - } - } - } - - if ( Flag != VER_PARSE_FLAG_ERROR ) - { - if ( Vec_PtrSize(vStackFn) ) - { - bFunc = Vec_PtrPop(vStackFn); - if ( !Vec_PtrSize(vStackFn) ) - if ( !Vec_IntSize(vStackOp) ) - { -// Cudd_Deref( bFunc ); - return bFunc; - } - else - sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the operation stack\n" ); - else - sprintf( pErrorMessage, "Parse_FormulaParser(): Something is left in the function stack\n" ); - } - else - sprintf( pErrorMessage, "Parse_FormulaParser(): The input string is empty\n" ); - } -// Cudd_Ref( bFunc ); -// Cudd_RecursiveDeref( dd, bFunc ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs the operation on the top entries in the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ) -{ - Hop_Obj_t * bArg0, * bArg1, * bArg2, * bFunc; - // perform the given operation - bArg2 = Vec_PtrPop( vStackFn ); - bArg1 = Vec_PtrPop( vStackFn ); - if ( Oper == VER_PARSE_OPER_AND ) - bFunc = Hop_And( pMan, bArg1, bArg2 ); - else if ( Oper == VER_PARSE_OPER_XOR ) - bFunc = Hop_Exor( pMan, bArg1, bArg2 ); - else if ( Oper == VER_PARSE_OPER_OR ) - bFunc = Hop_Or( pMan, bArg1, bArg2 ); - else if ( Oper == VER_PARSE_OPER_EQU ) - bFunc = Hop_Not( Hop_Exor( pMan, bArg1, bArg2 ) ); - else if ( Oper == VER_PARSE_OPER_MUX ) - { - bArg0 = Vec_PtrPop( vStackFn ); -// bFunc = Cudd_bddIte( dd, bArg0, bArg1, bArg2 ); Cudd_Ref( bFunc ); - bFunc = Hop_Mux( pMan, bArg0, bArg1, bArg2 ); -// Cudd_RecursiveDeref( dd, bArg0 ); -// Cudd_Deref( bFunc ); - } - else - return NULL; -// Cudd_Ref( bFunc ); -// Cudd_RecursiveDeref( dd, bArg1 ); -// Cudd_RecursiveDeref( dd, bArg2 ); - Vec_PtrPush( vStackFn, bFunc ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Returns the index of the new variable found.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_FormulaParserFindVar( char * pString, Vec_Ptr_t * vNames ) -{ - char * pTemp, * pTemp2; - int nLength, nLength2, i; - // start the string - pTemp = pString; - // find the end of the string delimited by other characters - if ( *pTemp == '\\' ) - { - pString++; - while ( *pTemp && *pTemp != ' ' ) - pTemp++; - } - else - { - while ( *pTemp && *pTemp != ' ' && *pTemp != '\t' && *pTemp != '\r' && *pTemp != '\n' && *pTemp != ',' && *pTemp != '}' && - *pTemp != VER_PARSE_SYM_OPEN && *pTemp != VER_PARSE_SYM_CLOSE && - *pTemp != VER_PARSE_SYM_NEGBEF1 && *pTemp != VER_PARSE_SYM_NEGBEF2 && - *pTemp != VER_PARSE_SYM_AND && *pTemp != VER_PARSE_SYM_OR && *pTemp != VER_PARSE_SYM_XOR && - *pTemp != VER_PARSE_SYM_MUX1 && *pTemp != VER_PARSE_SYM_MUX2 ) - pTemp++; - } - // look for this string in the array - nLength = pTemp - pString; - for ( i = 0; i < Vec_PtrSize(vNames)/2; i++ ) - { - nLength2 = (int)Vec_PtrEntry( vNames, 2*i + 0 ); - if ( nLength2 != nLength ) - continue; - pTemp2 = Vec_PtrEntry( vNames, 2*i + 1 ); - if ( strncmp( pString, pTemp2, nLength ) ) - continue; - return i; - } - // could not find - add and return the number - Vec_PtrPush( vNames, (void *)nLength ); - Vec_PtrPush( vNames, pString ); - return i; -} - -/**Function************************************************************* - - Synopsis [Returns the AIG representation of the reduction formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Ver_FormulaReduction( char * pFormula, void * pMan, Vec_Ptr_t * vNames, char * pErrorMessage ) -{ - Hop_Obj_t * pRes; - int v, fCompl; - char Symbol; - - // get the operation - Symbol = *pFormula++; - fCompl = ( Symbol == '~' ); - if ( fCompl ) - Symbol = *pFormula++; - // check the operation - if ( Symbol != '&' && Symbol != '|' && Symbol != '^' ) - { - sprintf( pErrorMessage, "Ver_FormulaReduction(): Unknown operation (%c)\n", Symbol ); - return NULL; - } - // skip the brace - while ( *pFormula++ != '{' ); - // parse the names - Vec_PtrClear( vNames ); - while ( *pFormula != '}' ) - { - v = Ver_FormulaParserFindVar( pFormula, vNames ); - pFormula += (int)Vec_PtrEntry( vNames, 2*v ); - while ( *pFormula == ' ' || *pFormula == ',' ) - pFormula++; - } - // compute the function - if ( Symbol == '&' ) - pRes = Hop_CreateAnd( pMan, Vec_PtrSize(vNames)/2 ); - else if ( Symbol == '|' ) - pRes = Hop_CreateOr( pMan, Vec_PtrSize(vNames)/2 ); - else if ( Symbol == '^' ) - pRes = Hop_CreateExor( pMan, Vec_PtrSize(vNames)/2 ); - return Hop_NotCond( pRes, fCompl ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/ver/verParse.c b/src/base/ver/verParse.c deleted file mode 100644 index 9462fc8b..00000000 --- a/src/base/ver/verParse.c +++ /dev/null @@ -1,117 +0,0 @@ -/**CFile**************************************************************** - - FileName [verParse.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Performs some Verilog parsing tasks.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: verParse.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Skips the comments of they are present.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_ParseSkipComments( Ver_Man_t * pMan ) -{ - Ver_Stream_t * p = pMan->pReader; - char Symbol; - // skip spaces - Ver_StreamSkipChars( p, " \t\n\r" ); - if ( !Ver_StreamIsOkey(pMan->pReader) ) - return 1; - // read the first symbol - Symbol = Ver_StreamScanChar( p ); - if ( Symbol != '/' ) - return 1; - Ver_StreamPopChar( p ); - // read the second symbol - Symbol = Ver_StreamScanChar( p ); - if ( Symbol == '/' ) - { // skip till the end of line - Ver_StreamSkipToChars( p, "\n" ); - return Ver_ParseSkipComments( pMan ); - } - if ( Symbol == '*' ) - { // skip till the next occurance of */ - Ver_StreamPopChar( p ); - do { - Ver_StreamSkipToChars( p, "*" ); - Ver_StreamPopChar( p ); - } while ( Ver_StreamScanChar( p ) != '/' ); - Ver_StreamPopChar( p ); - return Ver_ParseSkipComments( pMan ); - } - sprintf( pMan->sError, "Cannot parse after symbol \"/\"." ); - Ver_ParsePrintErrorMessage( pMan ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Parses a Verilog name that can be being with a slash.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ver_ParseGetName( Ver_Man_t * pMan ) -{ - Ver_Stream_t * p = pMan->pReader; - char Symbol; - char * pWord; - pMan->fNameLast = 0; - if ( !Ver_StreamIsOkey(p) ) - return NULL; - if ( !Ver_ParseSkipComments( pMan ) ) - return NULL; - Symbol = Ver_StreamScanChar( p ); - if ( Symbol == '\\' ) - { - pMan->fNameLast = 1; - Ver_StreamPopChar( p ); - pWord = Ver_StreamGetWord( p, " \r\n" ); - } - else - pWord = Ver_StreamGetWord( p, " \t\n\r(),;" ); - if ( !Ver_ParseSkipComments( pMan ) ) - return NULL; - return pWord; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/ver/verStream.c b/src/base/ver/verStream.c deleted file mode 100644 index eed322b9..00000000 --- a/src/base/ver/verStream.c +++ /dev/null @@ -1,440 +0,0 @@ -/**CFile**************************************************************** - - FileName [verStream.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Input file stream, which knows nothing about Verilog.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: verStream.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define VER_BUFFER_SIZE 1048576 // 1M - size of the data chunk stored in memory -#define VER_OFFSET_SIZE 4096 // 4K - load new data when less than this is left -#define VER_WORD_SIZE 4096 // 4K - the largest token that can be returned - -#define VER_MINIMUM(a,b) (((a) < (b))? (a) : (b)) - -struct Ver_Stream_t_ -{ - // the input file - char * pFileName; // the input file name - FILE * pFile; // the input file pointer - int nFileSize; // the total number of bytes in the file - int nFileRead; // the number of bytes currently read from file - int nLineCounter; // the counter of lines processed - // temporary storage for data - char * pBuffer; // the buffer - int nBufferSize; // the size of the buffer - char * pBufferCur; // the current reading position - char * pBufferEnd; // the first position not used by currently loaded data - char * pBufferStop; // the position where loading new data will be done - // tokens given to the user - char pChars[VER_WORD_SIZE+5]; // temporary storage for a word (plus end-of-string and two parantheses) - int nChars; // the total number of characters in the word - // status of the parser - int fStop; // this flag goes high when the end of file is reached -}; - -static void Ver_StreamReload( Ver_Stream_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the file reader for the given file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ver_Stream_t * Ver_StreamAlloc( char * pFileName ) -{ - Ver_Stream_t * p; - FILE * pFile; - int nCharsToRead; - // check if the file can be opened - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Ver_StreamAlloc(): Cannot open input file \"%s\".\n", pFileName ); - return NULL; - } - // start the file reader - p = ALLOC( Ver_Stream_t, 1 ); - memset( p, 0, sizeof(Ver_Stream_t) ); - p->pFileName = pFileName; - p->pFile = pFile; - // get the file size, in bytes - fseek( pFile, 0, SEEK_END ); - p->nFileSize = ftell( pFile ); - rewind( pFile ); - // allocate the buffer - p->pBuffer = ALLOC( char, VER_BUFFER_SIZE+1 ); - p->nBufferSize = VER_BUFFER_SIZE; - p->pBufferCur = p->pBuffer; - // determine how many chars to read - nCharsToRead = VER_MINIMUM(p->nFileSize, VER_BUFFER_SIZE); - // load the first part into the buffer - fread( p->pBuffer, nCharsToRead, 1, p->pFile ); - p->nFileRead = nCharsToRead; - // set the ponters to the end and the stopping point - p->pBufferEnd = p->pBuffer + nCharsToRead; - p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; - // start the arrays - p->nLineCounter = 1; // 1-based line counting - return p; -} - -/**Function************************************************************* - - Synopsis [Loads new data into the file reader.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_StreamReload( Ver_Stream_t * p ) -{ - int nCharsUsed, nCharsToRead; - assert( !p->fStop ); - assert( p->pBufferCur > p->pBufferStop ); - assert( p->pBufferCur < p->pBufferEnd ); - // figure out how many chars are still not processed - nCharsUsed = p->pBufferEnd - p->pBufferCur; - // move the remaining data to the beginning of the buffer - memmove( p->pBuffer, p->pBufferCur, nCharsUsed ); - p->pBufferCur = p->pBuffer; - // determine how many chars we will read - nCharsToRead = VER_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead ); - // read the chars - fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile ); - p->nFileRead += nCharsToRead; - // set the ponters to the end and the stopping point - p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead; - p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + VER_BUFFER_SIZE - VER_OFFSET_SIZE; -} - -/**Function************************************************************* - - Synopsis [Stops the file reader.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_StreamFree( Ver_Stream_t * p ) -{ - if ( p->pFile ) - fclose( p->pFile ); - FREE( p->pBuffer ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Returns the file size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ver_StreamGetFileName( Ver_Stream_t * p ) -{ - return p->pFileName; -} - -/**Function************************************************************* - - Synopsis [Returns the file size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_StreamGetFileSize( Ver_Stream_t * p ) -{ - return p->nFileSize; -} - -/**Function************************************************************* - - Synopsis [Returns the current reading position.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_StreamGetCurPosition( Ver_Stream_t * p ) -{ - return p->nFileRead - (p->pBufferEnd - p->pBufferCur); -} - -/**Function************************************************************* - - Synopsis [Returns the line number for the given token.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_StreamGetLineNumber( Ver_Stream_t * p ) -{ - return p->nLineCounter; -} - - - -/**Function************************************************************* - - Synopsis [Returns current symbol.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Ver_StreamIsOkey( Ver_Stream_t * p ) -{ - return !p->fStop; -} - -/**Function************************************************************* - - Synopsis [Returns current symbol.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char Ver_StreamScanChar( Ver_Stream_t * p ) -{ - assert( !p->fStop ); - return *p->pBufferCur; -} - -/**Function************************************************************* - - Synopsis [Returns current symbol and moves to the next.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char Ver_StreamPopChar( Ver_Stream_t * p ) -{ - assert( !p->fStop ); - // check if the new data should to be loaded - if ( p->pBufferCur > p->pBufferStop ) - Ver_StreamReload( p ); - // check if there are symbols left - if ( p->pBufferCur == p->pBufferEnd ) // end of file - { - p->fStop = 1; - return -1; - } - // count the lines - if ( *p->pBufferCur == '\n' ) - p->nLineCounter++; - return *p->pBufferCur++; -} - -/**Function************************************************************* - - Synopsis [Skips the current symbol and all symbols from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ) -{ - char * pChar, * pTemp; - assert( !p->fStop ); - assert( pCharsToSkip != NULL ); - // check if the new data should to be loaded - if ( p->pBufferCur > p->pBufferStop ) - Ver_StreamReload( p ); - // skip the symbols - for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) - { - // skip symbols as long as they are in the list - for ( pTemp = pCharsToSkip; *pTemp; pTemp++ ) - if ( *pChar == *pTemp ) - break; - if ( *pTemp == 0 ) // pChar is not found in the list - { - p->pBufferCur = pChar; - return; - } - // count the lines - if ( *pChar == '\n' ) - p->nLineCounter++; - } - // the file is finished or the last part continued - // through VER_OFFSET_SIZE chars till the end of the buffer - if ( p->pBufferStop == p->pBufferEnd ) // end of file - { - p->fStop = 1; - return; - } - printf( "Ver_StreamSkipSymbol() failed to parse the file \"%s\".\n", p->pFileName ); -} - -/**Function************************************************************* - - Synopsis [Skips all symbols until encountering one from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ) -{ - char * pChar, * pTemp; - assert( !p->fStop ); - assert( pCharsToStop != NULL ); - // check if the new data should to be loaded - if ( p->pBufferCur > p->pBufferStop ) - Ver_StreamReload( p ); - // skip the symbols - for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) - { - // skip symbols as long as they are NOT in the list - for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) - if ( *pChar == *pTemp ) - break; - if ( *pTemp == 0 ) // pChar is not found in the list - { - // count the lines - if ( *pChar == '\n' ) - p->nLineCounter++; - continue; - } - // the symbol is found - move position and return - p->pBufferCur = pChar; - return; - } - // the file is finished or the last part continued - // through VER_OFFSET_SIZE chars till the end of the buffer - if ( p->pBufferStop == p->pBufferEnd ) // end of file - { - p->fStop = 1; - return; - } - printf( "Ver_StreamSkipToSymbol() failed to parse the file \"%s\".\n", p->pFileName ); -} - -/**Function************************************************************* - - Synopsis [Returns current word delimited by the set of symbols.] - - Description [Modifies the stream by inserting 0 at the first encounter - of one of the symbols in the list.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ) -{ - char * pChar, * pTemp; - if ( p->fStop ) - return NULL; - assert( pCharsToStop != NULL ); - // check if the new data should to be loaded - if ( p->pBufferCur > p->pBufferStop ) - Ver_StreamReload( p ); - // skip the symbols - p->nChars = 0; - for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) - { - // skip symbols as long as they are NOT in the list - for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) - if ( *pChar == *pTemp ) - break; - if ( *pTemp == 0 ) // pChar is not found in the list - { - p->pChars[p->nChars++] = *pChar; - if ( p->nChars == VER_WORD_SIZE ) - return NULL; - // count the lines - if ( *pChar == '\n' ) - p->nLineCounter++; - continue; - } - // the symbol is found - move the position, set the word end, return the word - p->pBufferCur = pChar; - p->pChars[p->nChars] = 0; - return p->pChars; - } - // the file is finished or the last part continued - // through VER_OFFSET_SIZE chars till the end of the buffer - if ( p->pBufferStop == p->pBufferEnd ) // end of file - { - p->fStop = 1; - p->pChars[p->nChars] = 0; - return p->pChars; - } - printf( "Ver_StreamGetWord() failed to parse the file \"%s\".\n", p->pFileName ); - return NULL; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/ver/verWords.c b/src/base/ver/verWords.c deleted file mode 100644 index f9d27010..00000000 --- a/src/base/ver/verWords.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [verWords.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Handles keywords that are currently supported.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: verWords.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/base/ver/ver_.c b/src/base/ver/ver_.c deleted file mode 100644 index 76599dac..00000000 --- a/src/base/ver/ver_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [ver_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Verilog parser.] - - Synopsis [Parses several flavors of structural Verilog.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 19, 2006.] - - Revision [$Id: ver_.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "ver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/bdd/cas/cas.h b/src/bdd/cas/cas.h deleted file mode 100644 index fcc9f890..00000000 --- a/src/bdd/cas/cas.h +++ /dev/null @@ -1,62 +0,0 @@ -/**CFile**************************************************************** - - FileName [cas.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cas.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CAS_H__ -#define __CAS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -#define MAXINPUTS 1024 -#define MAXOUTPUTS 1024 - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== zzz.c ==========================================================*/ - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/cas/casCore.c b/src/bdd/cas/casCore.c deleted file mode 100644 index 579235b1..00000000 --- a/src/bdd/cas/casCore.c +++ /dev/null @@ -1,1263 +0,0 @@ -/**CFile**************************************************************** - - FileName [casCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] - - Synopsis [Entrance into the implementation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Spring 2002.] - - Revision [$Id: casCore.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include -#include -#include - -#include "extra.h" -#include "cas.h" - -//////////////////////////////////////////////////////////////////////// -/// static functions /// -//////////////////////////////////////////////////////////////////////// - -DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose ); -DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ); -DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew ); - -extern int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose ); - -void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName ); - -DdNode * Cudd_bddTransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); - -//////////////////////////////////////////////////////////////////////// -/// static varibles /// -//////////////////////////////////////////////////////////////////////// - -//static FILE * pTable = NULL; -//static long s_RemappingTime = 0; - -//////////////////////////////////////////////////////////////////////// -/// debugging macros /// -//////////////////////////////////////////////////////////////////////// - -#define PRD(p) printf( "\nDECOMPOSITION TREE:\n\n" ); PrintDecEntry( (p), 0 ) -#define PRB(f) printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" ) -#define PRK(f,n) Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" ) -#define PRK2(f,g,n) Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" ) - - -//////////////////////////////////////////////////////////////////////// -/// EXTERNAL FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_CascadeExperiment( char * pFileGeneric, DdManager * dd, DdNode ** pOutputs, int nInputs, int nOutputs, int nLutSize, int fCheck, int fVerbose ) -{ - int i; - int nVars = nInputs; - int nOuts = nOutputs; - long clk1; - - int nVarsEnc; // the number of additional variables to encode outputs - DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars - - int nNames; // the total number of all inputs - char * pNames[MAXINPUTS]; // the temporary storage for the input (and output encoding) names - - DdNode * aFunc; // the encoded 0-1 BDD containing all the outputs - - char FileNameIni[100]; - char FileNameFin[100]; - char Buffer[100]; - - -//pTable = fopen( "stats.txt", "a+" ); -//fprintf( pTable, "%s ", pFileGeneric ); -//fprintf( pTable, "%d ", nVars ); -//fprintf( pTable, "%d ", nOuts ); - - - // assign the file names - strcpy( FileNameIni, pFileGeneric ); - strcat( FileNameIni, "_ENC.blif" ); - - strcpy( FileNameFin, pFileGeneric ); - strcat( FileNameFin, "_LUT.blif" ); - - - // create the variables to encode the outputs - nVarsEnc = Extra_Base2Log( nOuts ); - for ( i = 0; i < nVarsEnc; i++ ) - pbVarsEnc[i] = Cudd_bddNewVarAtLevel( dd, i ); - - - // store the input names - nNames = nVars + nVarsEnc; - for ( i = 0; i < nVars; i++ ) - { -// pNames[i] = Extra_UtilStrsav( pFunc->pInputNames[i] ); - sprintf( Buffer, "pi%03d", i ); - pNames[i] = Extra_UtilStrsav( Buffer ); - } - // set the encoding variable name - for ( ; i < nNames; i++ ) - { - sprintf( Buffer, "OutEnc_%02d", i-nVars ); - pNames[i] = Extra_UtilStrsav( Buffer ); - } - - - // print the variable order -// printf( "\n" ); -// printf( "Variable order is: " ); -// for ( i = 0; i < dd->size; i++ ) -// printf( " %d", dd->invperm[i] ); -// printf( "\n" ); - - // derive the single-output function - clk1 = clock(); - aFunc = GetSingleOutputFunction( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc, fVerbose ); Cudd_Ref( aFunc ); -// aFunc = GetSingleOutputFunctionRemapped( dd, pOutputs, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( aFunc ); -// if ( fVerbose ) -// printf( "Single-output function computation time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - -//fprintf( pTable, "%d ", Cudd_SharingSize( pOutputs, nOutputs ) ); -//fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pOutputs, nOutputs) ); - - // dispose of the multiple-output function -// Extra_Dissolve( pFunc ); - - // reorder the single output function -// if ( fVerbose ) -// printf( "Reordering variables...\n"); - clk1 = clock(); -// if ( fVerbose ) -// printf( "Node count before = %6d\n", Cudd_DagSize( aFunc ) ); -// Cudd_ReduceHeap(dd, CUDD_REORDER_SIFT,1); - Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); - Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(dd, CUDD_REORDER_SYMM_SIFT,1); - if ( fVerbose ) - printf( "MTBDD reordered = %6d nodes\n", Cudd_DagSize( aFunc ) ); - if ( fVerbose ) - printf( "Variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); -// printf( "\n" ); -// printf( "Variable order is: " ); -// for ( i = 0; i < dd->size; i++ ) -// printf( " %d", dd->invperm[i] ); -// printf( "\n" ); -//fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) ); -//fprintf( pTable, "%d ", Extra_ProfileWidthMax(dd, aFunc) ); - - // write the single-output function into BLIF for verification - clk1 = clock(); - if ( fCheck ) - WriteSingleOutputFunctionBlif( dd, aFunc, pNames, nNames, FileNameIni ); -// if ( fVerbose ) -// printf( "Single-output function writing time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - -/* - /////////////////////////////////////////////////////////////////// - // verification of single output function - clk1 = clock(); - { - BFunc g_Func; - DdNode * aRes; - - g_Func.dd = dd; - g_Func.FileInput = Extra_UtilStrsav(FileNameIni); - - if ( Extra_ReadFile( &g_Func ) == 0 ) - { - printf( "\nSomething did not work out while reading the input file for verification\n"); - Extra_Dissolve( &g_Func ); - return; - } - - aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); - - if ( aRes != aFunc ) - printf( "\nVerification FAILED!\n"); - else - printf( "\nVerification okay!\n"); - - Cudd_RecursiveDeref( dd, aRes ); - - // delocate - Extra_Dissolve( &g_Func ); - } - printf( "Preliminary verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - /////////////////////////////////////////////////////////////////// -*/ - - if ( !CreateDecomposedNetwork( dd, aFunc, pNames, nNames, FileNameFin, nLutSize, fCheck, fVerbose ) ) - return 0; - -/* - /////////////////////////////////////////////////////////////////// - // verification of the decomposed LUT network - clk1 = clock(); - { - BFunc g_Func; - DdNode * aRes; - - g_Func.dd = dd; - g_Func.FileInput = Extra_UtilStrsav(FileNameFin); - - if ( Extra_ReadFile( &g_Func ) == 0 ) - { - printf( "\nSomething did not work out while reading the input file for verification\n"); - Extra_Dissolve( &g_Func ); - return; - } - - aRes = Cudd_BddToAdd( dd, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); - - if ( aRes != aFunc ) - printf( "\nFinal verification FAILED!\n"); - else - printf( "\nFinal verification okay!\n"); - - Cudd_RecursiveDeref( dd, aRes ); - - // delocate - Extra_Dissolve( &g_Func ); - } - printf( "Final verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - /////////////////////////////////////////////////////////////////// -*/ - - // verify the results - if ( fCheck ) - { - extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); - extern void * Abc_FrameGetGlobalFrame(); - char Command[200]; - sprintf( Command, "cec %s %s", FileNameIni, FileNameFin ); - Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); - } - - Cudd_RecursiveDeref( dd, aFunc ); - - // release the names - for ( i = 0; i < nNames; i++ ) - free( pNames[i] ); - - -//fprintf( pTable, "\n" ); -//fclose( pTable ); - - return 1; -} - -#if 0 - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Experiment2( BFunc * pFunc ) -{ - int i, x, RetValue; - int nVars = pFunc->nInputs; - int nOuts = pFunc->nOutputs; - DdManager * dd = pFunc->dd; - long clk1; - -// int nVarsEnc; // the number of additional variables to encode outputs -// DdNode * pbVarsEnc[MAXOUTPUTS]; // the BDDs of the encoding vars - - int nNames; // the total number of all inputs - char * pNames[MAXINPUTS]; // the temporary storage for the input (and output encoding) names - - DdNode * aFunc; // the encoded 0-1 BDD containing all the outputs - - char FileNameIni[100]; - char FileNameFin[100]; - char Buffer[100]; - - DdManager * DdNew; - -//pTable = fopen( "stats.txt", "a+" ); -//fprintf( pTable, "%s ", pFunc->FileGeneric ); -//fprintf( pTable, "%d ", nVars ); -//fprintf( pTable, "%d ", nOuts ); - - - // assign the file names - strcpy( FileNameIni, pFunc->FileGeneric ); - strcat( FileNameIni, "_ENC.blif" ); - - strcpy( FileNameFin, pFunc->FileGeneric ); - strcat( FileNameFin, "_LUT.blif" ); - - // derive the single-output function IN THE NEW MANAGER - clk1 = clock(); -// aFunc = GetSingleOutputFunction( dd, pFunc->pOutputs, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( aFunc ); - aFunc = GetSingleOutputFunctionRemappedNewDD( dd, pFunc->pOutputs, nOuts, &DdNew ); Cudd_Ref( aFunc ); - printf( "Single-output function derivation time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); -// s_RemappingTime = clock() - clk1; - - // dispose of the multiple-output function - Extra_Dissolve( pFunc ); - - // reorder the single output function - printf( "\nReordering variables in the new manager...\n"); - clk1 = clock(); - printf( "Node count before = %d\n", Cudd_DagSize( aFunc ) ); -// Cudd_ReduceHeap(DdNew, CUDD_REORDER_SIFT,1); - Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(DdNew, CUDD_REORDER_SYMM_SIFT,1); - printf( "Node count after = %d\n", Cudd_DagSize( aFunc ) ); - printf( "Variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - printf( "\n" ); - -//fprintf( pTable, "%d ", Cudd_DagSize( aFunc ) ); -//fprintf( pTable, "%d ", Extra_ProfileWidthMax(DdNew, aFunc) ); - - - // create the names to be used with the new manager - nNames = DdNew->size; - for ( x = 0; x < nNames; x++ ) - { - sprintf( Buffer, "v%02d", x ); - pNames[x] = Extra_UtilStrsav( Buffer ); - } - - - - // write the single-output function into BLIF for verification - clk1 = clock(); - WriteSingleOutputFunctionBlif( DdNew, aFunc, pNames, nNames, FileNameIni ); - printf( "Single-output function writing time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - - - /////////////////////////////////////////////////////////////////// - // verification of single output function - clk1 = clock(); - { - BFunc g_Func; - DdNode * aRes; - - g_Func.dd = DdNew; - g_Func.FileInput = Extra_UtilStrsav(FileNameIni); - - if ( Extra_ReadFile( &g_Func ) == 0 ) - { - printf( "\nSomething did not work out while reading the input file for verification\n"); - Extra_Dissolve( &g_Func ); - return; - } - - aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); - - if ( aRes != aFunc ) - printf( "\nVerification FAILED!\n"); - else - printf( "\nVerification okay!\n"); - - Cudd_RecursiveDeref( DdNew, aRes ); - - // delocate - Extra_Dissolve( &g_Func ); - } - printf( "Preliminary verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - /////////////////////////////////////////////////////////////////// - - - CreateDecomposedNetwork( DdNew, aFunc, pNames, nNames, FileNameFin, nLutSize, 0 ); - -/* - /////////////////////////////////////////////////////////////////// - // verification of the decomposed LUT network - clk1 = clock(); - { - BFunc g_Func; - DdNode * aRes; - - g_Func.dd = DdNew; - g_Func.FileInput = Extra_UtilStrsav(FileNameFin); - - if ( Extra_ReadFile( &g_Func ) == 0 ) - { - printf( "\nSomething did not work out while reading the input file for verification\n"); - Extra_Dissolve( &g_Func ); - return; - } - - aRes = Cudd_BddToAdd( DdNew, g_Func.pOutputs[0] ); Cudd_Ref( aRes ); - - if ( aRes != aFunc ) - printf( "\nFinal verification FAILED!\n"); - else - printf( "\nFinal verification okay!\n"); - - Cudd_RecursiveDeref( DdNew, aRes ); - - // delocate - Extra_Dissolve( &g_Func ); - } - printf( "Final verification time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - /////////////////////////////////////////////////////////////////// -*/ - - - Cudd_RecursiveDeref( DdNew, aFunc ); - - // release the names - for ( i = 0; i < nNames; i++ ) - free( pNames[i] ); - - - - ///////////////////////////////////////////////////////////////////// - // check for remaining references in the package - RetValue = Cudd_CheckZeroRef( DdNew ); - printf( "\nThe number of referenced nodes in the new manager = %d\n", RetValue ); - Cudd_Quit( DdNew ); - -//fprintf( pTable, "\n" ); -//fclose( pTable ); - -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// SINGLE OUTPUT FUNCTION /// -//////////////////////////////////////////////////////////////////////// - -// the bit count for the first 256 integer numbers -static unsigned char BitCount8[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; - -///////////////////////////////////////////////////////////// -static int s_SuppSize[MAXOUTPUTS]; -int CompareSupports( int *ptrX, int *ptrY ) -{ - return ( s_SuppSize[*ptrY] - s_SuppSize[*ptrX] ); -} -///////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////// -static int s_MintOnes[MAXOUTPUTS]; -int CompareMinterms( int *ptrX, int *ptrY ) -{ - return ( s_MintOnes[*ptrY] - s_MintOnes[*ptrX] ); -} -///////////////////////////////////////////////////////////// - -int GrayCode ( int BinCode ) -{ - return BinCode ^ ( BinCode >> 1 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc, int fVerbose ) -{ - int i; - DdNode * bResult, * aResult; - DdNode * bCube, * bTemp, * bProd; - - int Order[MAXOUTPUTS]; -// int OrderMint[MAXOUTPUTS]; - - // sort the output according to their support size - for ( i = 0; i < nOuts; i++ ) - { - s_SuppSize[i] = Cudd_SupportSize( dd, pbOuts[i] ); -// s_MintOnes[i] = BitCount8[i]; - Order[i] = i; -// OrderMint[i] = i; - } - - // order the outputs - qsort( (void*)Order, nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareSupports ); - // order the outputs -// qsort( (void*)OrderMint, nOuts, sizeof(int), (int(*)(const void*, const void*)) CompareMinterms ); - - - bResult = b0; Cudd_Ref( bResult ); - for ( i = 0; i < nOuts; i++ ) - { -// bCube = Cudd_bddBitsToCube( dd, OrderMint[i], nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); -// bProd = Cudd_bddAnd( dd, bCube, pbOuts[Order[nOuts-1-i]] ); Cudd_Ref( bProd ); - bCube = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc, 1 ); Cudd_Ref( bCube ); - bProd = Cudd_bddAnd( dd, bCube, pbOuts[Order[i]] ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bCube ); - - bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - } - - // convert to the ADD -if ( fVerbose ) -printf( "Single BDD size = %6d nodes\n", Cudd_DagSize(bResult) ); - aResult = Cudd_BddToAdd( dd, bResult ); Cudd_Ref( aResult ); - Cudd_RecursiveDeref( dd, bResult ); -if ( fVerbose ) -printf( "MTBDD = %6d nodes\n", Cudd_DagSize(aResult) ); - Cudd_Deref( aResult ); - return aResult; -} -/* -DdNode * GetSingleOutputFunction( DdManager * dd, DdNode ** pbOuts, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ) -{ - int i; - DdNode * bResult, * aResult; - DdNode * bCube, * bTemp, * bProd; - - bResult = b0; Cudd_Ref( bResult ); - for ( i = 0; i < nOuts; i++ ) - { -// bCube = Extra_bddBitsToCube( dd, i, nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); - bCube = Extra_bddBitsToCube( dd, nOuts-1-i, nVarsEnc, pbVarsEnc ); Cudd_Ref( bCube ); - bProd = Cudd_bddAnd( dd, bCube, pbOuts[i] ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bCube ); - - bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - } - - // conver to the ADD - aResult = Cudd_BddToAdd( dd, bResult ); Cudd_Ref( aResult ); - Cudd_RecursiveDeref( dd, bResult ); - - Cudd_Deref( aResult ); - return aResult; -} -*/ - - -//////////////////////////////////////////////////////////////////////// -/// INPUT REMAPPING /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * GetSingleOutputFunctionRemapped( DdManager * dd, DdNode ** pOutputs, int nOuts, DdNode ** pbVarsEnc, int nVarsEnc ) -// returns the ADD of the remapped function -{ - static int Permute[MAXINPUTS]; - static DdNode * pRemapped[MAXOUTPUTS]; - - DdNode * bSupp, * bTemp; - int i, Counter; - int nSuppPrev = -1; - DdNode * bFunc; - DdNode * aFunc; - - Cudd_AutodynDisable(dd); - - // perform the remapping - for ( i = 0; i < nOuts; i++ ) - { - // get support - bSupp = Cudd_Support( dd, pOutputs[i] ); Cudd_Ref( bSupp ); - - // create the variable map - Counter = 0; - for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) - Permute[bTemp->index] = Counter++; - - // transfer the BDD and remap it - pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute ); Cudd_Ref( pRemapped[i] ); - - // remove support - Cudd_RecursiveDeref( dd, bSupp ); - } - - // perform the encoding - bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( bFunc ); - - // convert to ADD - aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc ); - Cudd_RecursiveDeref( dd, bFunc ); - - // deref the intermediate results - for ( i = 0; i < nOuts; i++ ) - Cudd_RecursiveDeref( dd, pRemapped[i] ); - - Cudd_Deref( aFunc ); - return aFunc; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * GetSingleOutputFunctionRemappedNewDD( DdManager * dd, DdNode ** pOutputs, int nOuts, DdManager ** DdNew ) -// returns the ADD of the remapped function -{ - static int Permute[MAXINPUTS]; - static DdNode * pRemapped[MAXOUTPUTS]; - - static DdNode * pbVarsEnc[MAXINPUTS]; - int nVarsEnc; - - DdManager * ddnew; - - DdNode * bSupp, * bTemp; - int i, v, Counter; - int nSuppPrev = -1; - DdNode * bFunc; - - // these are in the new manager - DdNode * bFuncNew; - DdNode * aFuncNew; - - int nVarsMax = 0; - - // perform the remapping and write the DDs into the new manager - for ( i = 0; i < nOuts; i++ ) - { - // get support - bSupp = Cudd_Support( dd, pOutputs[i] ); Cudd_Ref( bSupp ); - - // create the variable map - // to remap the DD into the upper part of the manager - Counter = 0; - for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) - Permute[bTemp->index] = dd->invperm[Counter++]; - - // transfer the BDD and remap it - pRemapped[i] = Cudd_bddPermute( dd, pOutputs[i], Permute ); Cudd_Ref( pRemapped[i] ); - - // remove support - Cudd_RecursiveDeref( dd, bSupp ); - - - // determine the largest support size - if ( nVarsMax < Counter ) - nVarsMax = Counter; - } - - // select the encoding variables to follow immediately after the original variables - nVarsEnc = Extra_Base2Log(nOuts); -/* - for ( v = 0; v < nVarsEnc; v++ ) - if ( nVarsMax + v < dd->size ) - pbVarsEnc[v] = dd->var[ dd->invperm[nVarsMax+v] ]; - else - pbVarsEnc[v] = Cudd_bddNewVar( dd ); -*/ - // create the new variables on top of the manager - for ( v = 0; v < nVarsEnc; v++ ) - pbVarsEnc[v] = Cudd_bddNewVarAtLevel( dd, v ); - -//fprintf( pTable, "%d ", Cudd_SharingSize( pRemapped, nOuts ) ); -//fprintf( pTable, "%d ", Extra_ProfileWidthSharingMax(dd, pRemapped, nOuts) ); - - - // perform the encoding - bFunc = Extra_bddEncodingBinary( dd, pRemapped, nOuts, pbVarsEnc, nVarsEnc ); Cudd_Ref( bFunc ); - - - // find the cross-manager permutation - // the variable from the level v in the old manager - // should become a variable number v in the new manager - for ( v = 0; v < nVarsMax + nVarsEnc; v++ ) - Permute[dd->invperm[v]] = v; - - - /////////////////////////////////////////////////////////////////////////////// - // start the new manager - ddnew = Cudd_Init( nVarsMax + nVarsEnc, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); -// Cudd_AutodynDisable(ddnew); - Cudd_AutodynEnable(dd, CUDD_REORDER_SYMM_SIFT); - - // transfer it to the new manager - bFuncNew = Cudd_bddTransferPermute( dd, ddnew, bFunc, Permute ); Cudd_Ref( bFuncNew ); - /////////////////////////////////////////////////////////////////////////////// - - - // deref the intermediate results in the old manager - Cudd_RecursiveDeref( dd, bFunc ); - for ( i = 0; i < nOuts; i++ ) - Cudd_RecursiveDeref( dd, pRemapped[i] ); - - - /////////////////////////////////////////////////////////////////////////////// - // convert to ADD in the new manager - aFuncNew = Cudd_BddToAdd( ddnew, bFuncNew ); Cudd_Ref( aFuncNew ); - Cudd_RecursiveDeref( ddnew, bFuncNew ); - - // return the manager - *DdNew = ddnew; - /////////////////////////////////////////////////////////////////////////////// - - Cudd_Deref( aFuncNew ); - return aFuncNew; -} - -//////////////////////////////////////////////////////////////////////// -/// BLIF WRITING FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void WriteSingleOutputFunctionBlif( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName ) -{ - int i; - FILE * pFile; - - // start the file - pFile = fopen( FileName, "w" ); - fprintf( pFile, ".model %s\n", FileName ); - - fprintf( pFile, ".inputs" ); - for ( i = 0; i < nNames; i++ ) - fprintf( pFile, " %s", pNames[i] ); - fprintf( pFile, "\n" ); - fprintf( pFile, ".outputs F" ); - fprintf( pFile, "\n" ); - - // write the DD into the file - WriteDDintoBLIFfile( pFile, aFunc, "F", "", pNames ); - - fprintf( pFile, ".end\n" ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ) -// writes the main part of the BLIF file -// Func is a BDD or a 0-1 ADD to be written -// OutputName is the name of the output -// Prefix is attached to each intermendiate signal to make it unique -// InputNames are the names of the input signals -// (some part of the code is borrowed from Cudd_DumpDot()) -{ - int i; - st_table * visited; - st_generator * gen = NULL; - long refAddr, diff, mask; - DdNode * Node, * Else, * ElseR, * Then; - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table( st_ptrcmp, st_ptrhash ); - - /* Collect all the nodes of this DD in the symbol table. */ - cuddCollectNodes( Cudd_Regular(Func), visited ); - - /* Find how many most significant hex digits are identical - ** in the addresses of all the nodes. Build a mask based - ** on this knowledge, so that digits that carry no information - ** will not be printed. This is done in two steps. - ** 1. We scan the symbol table to find the bits that differ - ** in at least 2 addresses. - ** 2. We choose one of the possible masks. There are 8 possible - ** masks for 32-bit integer, and 16 possible masks for 64-bit - ** integers. - */ - - /* Find the bits that are different. */ - refAddr = ( long )Cudd_Regular(Func); - diff = 0; - gen = st_init_gen( visited ); - while ( st_gen( gen, ( char ** ) &Node, NULL ) ) - { - diff |= refAddr ^ ( long ) Node; - } - st_free_gen( gen ); - gen = NULL; - - /* Choose the mask. */ - for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 ) - { - mask = ( 1 << i ) - 1; - if ( diff <= mask ) - break; - } - - - // write the buffer for the output - fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(Func) ) / sizeof(DdNode), OutputName ); - fprintf( pFile, "%s 1\n", (Cudd_IsComplement(Func))? "0": "1" ); - - - gen = st_init_gen( visited ); - while ( st_gen( gen, ( char ** ) &Node, NULL ) ) - { - if ( Node->index == CUDD_MAXINDEX ) - { - // write the terminal node - fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" ); - continue; - } - - Else = cuddE(Node); - ElseR = Cudd_Regular(Else); - Then = cuddT(Node); - - assert( InputNames[Node->index] ); - if ( Else == ElseR ) - { // no inverter - fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index], - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)Then ) / sizeof(DdNode), - Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, "01- 1\n" ); - fprintf( pFile, "1-1 1\n" ); - } - else - { // inverter - int * pSlot; - fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index], - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)Then ) / sizeof(DdNode), - Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, "01- 1\n" ); - fprintf( pFile, "1-1 1\n" ); - - // if the inverter is written, skip - if ( !st_find( visited, (char *)ElseR, (char ***)&pSlot ) ) - assert( 0 ); - if ( *pSlot ) - continue; - *pSlot = 1; - - fprintf( pFile, ".names %s%lx %s%lx_i\n", - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode) ); - fprintf( pFile, "0 1\n" ); - } - } - st_free_gen( gen ); - gen = NULL; - st_free_table( visited ); -} - - - - -static DdManager * s_ddmin; - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ) -// writes the main part of the BLIF file -// Func is a BDD or a 0-1 ADD to be written -// OutputName is the name of the output -// Prefix is attached to each intermendiate signal to make it unique -// InputNames are the names of the input signals -// (some part of the code is borrowed from Cudd_DumpDot()) -{ - int i; - st_table * visited; - st_generator * gen = NULL; - long refAddr, diff, mask; - DdNode * Node, * Else, * ElseR, * Then; - - - /////////////////////////////////////////////////////////////// - DdNode * bFmin; - int clk1; - - if ( s_ddmin == NULL ) - s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); - - clk1 = clock(); - bFmin = Cudd_bddTransfer( dd, s_ddmin, Func ); Cudd_Ref( bFmin ); - - // reorder - printf( "Nodes before = %d. ", Cudd_DagSize(bFmin) ); - Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); -// Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT_CONV,1); - printf( "Nodes after = %d. \n", Cudd_DagSize(bFmin) ); - /////////////////////////////////////////////////////////////// - - - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table( st_ptrcmp, st_ptrhash ); - - /* Collect all the nodes of this DD in the symbol table. */ - cuddCollectNodes( Cudd_Regular(bFmin), visited ); - - /* Find how many most significant hex digits are identical - ** in the addresses of all the nodes. Build a mask based - ** on this knowledge, so that digits that carry no information - ** will not be printed. This is done in two steps. - ** 1. We scan the symbol table to find the bits that differ - ** in at least 2 addresses. - ** 2. We choose one of the possible masks. There are 8 possible - ** masks for 32-bit integer, and 16 possible masks for 64-bit - ** integers. - */ - - /* Find the bits that are different. */ - refAddr = ( long )Cudd_Regular(bFmin); - diff = 0; - gen = st_init_gen( visited ); - while ( st_gen( gen, ( char ** ) &Node, NULL ) ) - { - diff |= refAddr ^ ( long ) Node; - } - st_free_gen( gen ); - gen = NULL; - - /* Choose the mask. */ - for ( i = 0; ( unsigned ) i < 8 * sizeof( long ); i += 4 ) - { - mask = ( 1 << i ) - 1; - if ( diff <= mask ) - break; - } - - - // write the buffer for the output - fprintf( pFile, ".names %s%lx %s\n", Prefix, ( mask & (long)Cudd_Regular(bFmin) ) / sizeof(DdNode), OutputName ); - fprintf( pFile, "%s 1\n", (Cudd_IsComplement(bFmin))? "0": "1" ); - - - gen = st_init_gen( visited ); - while ( st_gen( gen, ( char ** ) &Node, NULL ) ) - { - if ( Node->index == CUDD_MAXINDEX ) - { - // write the terminal node - fprintf( pFile, ".names %s%lx\n", Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, " %s\n", (cuddV(Node) == 0.0)? "0": "1" ); - continue; - } - - Else = cuddE(Node); - ElseR = Cudd_Regular(Else); - Then = cuddT(Node); - - assert( InputNames[Node->index] ); - if ( Else == ElseR ) - { // no inverter - fprintf( pFile, ".names %s %s%lx %s%lx %s%lx\n", InputNames[Node->index], - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)Then ) / sizeof(DdNode), - Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, "01- 1\n" ); - fprintf( pFile, "1-1 1\n" ); - } - else - { // inverter - fprintf( pFile, ".names %s %s%lx_i %s%lx %s%lx\n", InputNames[Node->index], - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)Then ) / sizeof(DdNode), - Prefix, ( mask & (long)Node ) / sizeof(DdNode) ); - fprintf( pFile, "01- 1\n" ); - fprintf( pFile, "1-1 1\n" ); - - fprintf( pFile, ".names %s%lx %s%lx_i\n", - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode), - Prefix, ( mask & (long)ElseR ) / sizeof(DdNode) ); - fprintf( pFile, "0 1\n" ); - } - } - st_free_gen( gen ); - gen = NULL; - st_free_table( visited ); - - - ////////////////////////////////////////////////// - Cudd_RecursiveDeref( s_ddmin, bFmin ); - ////////////////////////////////////////////////// -} - - - - -//////////////////////////////////////////////////////////////////////// -/// TRANSFER WITH MAPPING /// -//////////////////////////////////////////////////////////////////////// -static DdNode * cuddBddTransferPermuteRecur -ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, st_table * table, int * Permute )); - -static DdNode * cuddBddTransferPermute -ARGS((DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute)); - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. The orders of the - variables in the two managers may be different. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise. The i-th entry in the array Permute tells what is the index - of the i-th variable from the old manager in the new manager.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_bddTransferPermute( DdManager * ddSource, - DdManager * ddDestination, DdNode * f, int * Permute ) -{ - DdNode *res; - do - { - ddDestination->reordered = 0; - res = cuddBddTransferPermute( ddSource, ddDestination, f, Permute ); - } - while ( ddDestination->reordered == 1 ); - return ( res ); - -} /* end of Cudd_bddTransferPermute */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddTransferPermute] - -******************************************************************************/ -DdNode * -cuddBddTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ) -{ - DdNode *res; - st_table *table = NULL; - st_generator *gen = NULL; - DdNode *key, *value; - - table = st_init_table( st_ptrcmp, st_ptrhash ); - if ( table == NULL ) - goto failure; - res = cuddBddTransferPermuteRecur( ddS, ddD, f, table, Permute ); - if ( res != NULL ) - cuddRef( res ); - - /* Dereference all elements in the table and dispose of the table. - ** This must be done also if res is NULL to avoid leaks in case of - ** reordering. */ - gen = st_init_gen( table ); - if ( gen == NULL ) - goto failure; - while ( st_gen( gen, ( char ** ) &key, ( char ** ) &value ) ) - { - Cudd_RecursiveDeref( ddD, value ); - } - st_free_gen( gen ); - gen = NULL; - st_free_table( table ); - table = NULL; - - if ( res != NULL ) - cuddDeref( res ); - return ( res ); - - failure: - if ( table != NULL ) - st_free_table( table ); - if ( gen != NULL ) - st_free_gen( gen ); - return ( NULL ); - -} /* end of cuddBddTransferPermute */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddTransferPermute.] - - Description [Performs the recursive step of Cudd_bddTransferPermute. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddBddTransferPermute] - -******************************************************************************/ -static DdNode * -cuddBddTransferPermuteRecur( DdManager * ddS, - DdManager * ddD, DdNode * f, st_table * table, int * Permute ) -{ - DdNode *ft, *fe, *t, *e, *var, *res; - DdNode *one, *zero; - int index; - int comple = 0; - - statLine( ddD ); - one = DD_ONE( ddD ); - comple = Cudd_IsComplement( f ); - - /* Trivial cases. */ - if ( Cudd_IsConstant( f ) ) - return ( Cudd_NotCond( one, comple ) ); - - /* Make canonical to increase the utilization of the cache. */ - f = Cudd_NotCond( f, comple ); - /* Now f is a regular pointer to a non-constant node. */ - - /* Check the cache. */ - if ( st_lookup( table, ( char * ) f, ( char ** ) &res ) ) - return ( Cudd_NotCond( res, comple ) ); - - /* Recursive step. */ - index = Permute[f->index]; - ft = cuddT( f ); - fe = cuddE( f ); - - t = cuddBddTransferPermuteRecur( ddS, ddD, ft, table, Permute ); - if ( t == NULL ) - { - return ( NULL ); - } - cuddRef( t ); - - e = cuddBddTransferPermuteRecur( ddS, ddD, fe, table, Permute ); - if ( e == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - return ( NULL ); - } - cuddRef( e ); - - zero = Cudd_Not( one ); - var = cuddUniqueInter( ddD, index, one, zero ); - if ( var == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - res = cuddBddIteRecur( ddD, var, t, e ); - if ( res == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - cuddRef( res ); - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - - if ( st_add_direct( table, ( char * ) f, ( char * ) res ) == - ST_OUT_OF_MEM ) - { - Cudd_RecursiveDeref( ddD, res ); - return ( NULL ); - } - return ( Cudd_NotCond( res, comple ) ); - -} /* end of cuddBddTransferPermuteRecur */ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - - diff --git a/src/bdd/cas/casDec.c b/src/bdd/cas/casDec.c deleted file mode 100644 index a1eb5f36..00000000 --- a/src/bdd/cas/casDec.c +++ /dev/null @@ -1,508 +0,0 @@ -/**CFile**************************************************************** - - FileName [casDec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [CASCADE: Decomposition of shared BDDs into a LUT cascade.] - - Synopsis [BDD-based decomposition with encoding.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Spring 2002.] - - Revision [$Id: casDec.c,v 1.0 2002/01/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include -#include -#include - -#include "extra.h" -#include "cas.h" - -//////////////////////////////////////////////////////////////////////// -/// type definitions /// -//////////////////////////////////////////////////////////////////////// - -typedef struct -{ - int nIns; // the number of LUT variables - int nInsP; // the number of inputs coming from the previous LUT - int nCols; // the number of columns in this LUT - int nMulti; // the column multiplicity, [log2(nCols)] - int nSimple; // the number of outputs implemented as direct connections to inputs of the previous block - int Level; // the starting level in the ADD in this LUT - -// DdNode ** pbVarsIn[32]; // the BDDs of the elementary input variables -// DdNode ** pbVarsOut[32]; // the BDDs of the elementary output variables - -// char * pNamesIn[32]; // the names of input variables -// char * pNamesOut[32]; // the names of output variables - - DdNode ** pbCols; // the array of columns represented by BDDs - DdNode ** pbCodes; // the array of codes (in terms of pbVarsOut) - DdNode ** paNodes; // the array of starting ADD nodes on the next level (also referenced) - - DdNode * bRelation; // the relation after encoding - - // the relation depends on the three groups of variables: - // (1) variables on top represent the outputs of the previous cascade - // (2) variables in the middle represent the primary inputs - // (3) variables below (CVars) represent the codes - // - // the replacement is done after computing the relation -} LUT; - - -//////////////////////////////////////////////////////////////////////// -/// static functions /// -//////////////////////////////////////////////////////////////////////// - -// the LUT-2-BLIF writing function -void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName ); - -// the function to write a DD (BDD or ADD) as a network of MUXES -extern void WriteDDintoBLIFfile( FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); -extern void WriteDDintoBLIFfileReorder( DdManager * dd, FILE * pFile, DdNode * Func, char * OutputName, char * Prefix, char ** InputNames ); - -//////////////////////////////////////////////////////////////////////// -/// static varibles /// -//////////////////////////////////////////////////////////////////////// - -static int s_LutSize = 15; -static int s_nFuncVars; - -long s_EncodingTime; - -long s_EncSearchTime; -long s_EncComputeTime; - -//////////////////////////////////// -// temporary output variables -//FILE * pTable; -//long s_ReadingTime; -//long s_RemappingTime; -//////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// debugging macros /// -//////////////////////////////////////////////////////////////////////// - -#define PRB(f) printf( #f " = " ); Cudd_bddPrint(dd,f); printf( "\n" ) -#define PRK(f,n) Cudd_PrintKMap(stdout,dd,(f),Cudd_Not(f),(n),NULL,0); printf( "K-map for function" #f "\n\n" ) -#define PRK2(f,g,n) Cudd_PrintKMap(stdout,dd,(f),(g),(n),NULL,0); printf( "K-map for function <" #f ", " #g ">\n\n" ) - - -//////////////////////////////////////////////////////////////////////// -/// EXTERNAL FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -int CreateDecomposedNetwork( DdManager * dd, DdNode * aFunc, char ** pNames, int nNames, char * FileName, int nLutSize, int fCheck, int fVerbose ) -// aFunc is a 0-1 ADD for the given function -// pNames (nNames) are the input variable names -// FileName is the name of the output file for the LUT network -// dynamic variable reordering should be disabled when this function is running -{ - static LUT * pLuts[MAXINPUTS]; // the LUT cascade - static int Profile[MAXINPUTS]; // the profile filled in with the info about the BDD width - static int Permute[MAXINPUTS]; // the array to store a temporary permutation of variables - - LUT * p; // the current LUT - int i, v; - - DdNode * bCVars[32]; // these are variables for the codes - - int nVarsRem; // the number of remaining variables - int PrevMulti; // column multiplicity on the previous level - int fLastLut; // flag to signal the last LUT - int nLuts; - int nLutsTotal = 0; - int nLutOutputs = 0; - int nLutOutputsOrig = 0; - - long clk1; - - s_LutSize = nLutSize; - - s_nFuncVars = nNames; - - // get the profile - clk1 = clock(); - Extra_ProfileWidth( dd, aFunc, Profile, -1 ); - - -// for ( v = 0; v < nNames; v++ ) -// printf( "Level = %2d, Width = %2d\n", v+1, Profile[v] ); - - -//printf( "\n" ); - - // mark-up the LUTs - // assuming that the manager has exactly nNames vars (new vars have not been introduced yet) - nVarsRem = nNames; // the number of remaining variables - PrevMulti = 0; // column multiplicity on the previous level - fLastLut = 0; - nLuts = 0; - do - { - p = (LUT*) malloc( sizeof(LUT) ); - memset( p, 0, sizeof(LUT) ); - - if ( nVarsRem + PrevMulti <= s_LutSize ) // this is the last LUT - { - p->nIns = nVarsRem + PrevMulti; - p->nInsP = PrevMulti; - p->nCols = 2; - p->nMulti = 1; - p->Level = nNames-nVarsRem; - - nVarsRem = 0; - PrevMulti = 1; - - fLastLut = 1; - } - else // this is not the last LUT - { - p->nIns = s_LutSize; - p->nInsP = PrevMulti; - p->nCols = Profile[nNames-(nVarsRem-(s_LutSize-PrevMulti))]; - p->nMulti = Extra_Base2Log(p->nCols); - p->Level = nNames-nVarsRem; - - nVarsRem = nVarsRem-(s_LutSize-PrevMulti); - PrevMulti = p->nMulti; - } - - if ( p->nMulti >= s_LutSize ) - { - printf( "The LUT size is too small\n" ); - return 0; - } - - nLutOutputsOrig += p->nMulti; - - -//if ( fVerbose ) -//printf( "Stage %2d: In = %3d, InP = %3d, Cols = %5d, Multi = %2d, Level = %2d\n", -// nLuts+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->Level ); - - - // there should be as many columns, codes, and nodes, as there are columns on this level - p->pbCols = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); - p->pbCodes = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); - p->paNodes = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); - - pLuts[nLuts] = p; - nLuts++; - } - while ( !fLastLut ); - - -//if ( fVerbose ) -//printf( "The number of cascades = %d\n", nLuts ); - - -//fprintf( pTable, "%d ", nLuts ); - - - // add the new variables at the bottom - for ( i = 0; i < s_LutSize; i++ ) - bCVars[i] = Cudd_bddNewVar(dd); - - // for each LUT - assign the LUT and encode the columns - s_EncodingTime = 0; - for ( i = 0; i < nLuts; i++ ) - { - int RetValue; - DdNode * bVars[32]; - int nVars; - DdNode * bVarsInCube; - DdNode * bVarsCCube; - DdNode * bVarsCube; - int CutLevel; - - p = pLuts[i]; - - // compute the columns of this LUT starting from the given set of nodes with the given codes - // (these codes have been remapped to depend on the topmost variables in the manager) - // for the first LUT, start with the constant 1 BDD - CutLevel = p->Level + p->nIns - p->nInsP; - if ( i == 0 ) - RetValue = Extra_bddNodePathsUnderCutArray( - dd, &aFunc, &(b1), 1, - p->paNodes, p->pbCols, CutLevel ); - else - RetValue = Extra_bddNodePathsUnderCutArray( - dd, pLuts[i-1]->paNodes, pLuts[i-1]->pbCodes, pLuts[i-1]->nCols, - p->paNodes, p->pbCols, CutLevel ); - assert( RetValue == p->nCols ); - // at this point, we have filled out p->paNodes[] and p->pbCols[] of this LUT - // pLuts[i-1]->paNodes depended on normal vars - // pLuts[i-1]->pbCodes depended on the topmost variables - // the resulting p->paNodes depend on normal ADD nodes - // the resulting p->pbCols depend on normal vars and topmost variables in the manager - - // perform the encoding - - // create the cube of these variables - // collect the topmost variables of the manager - nVars = p->nInsP; - for ( v = 0; v < nVars; v++ ) - bVars[v] = dd->vars[ dd->invperm[v] ]; - bVarsCCube = Extra_bddBitsToCube( dd, (1<nIns - p->nInsP; - for ( v = 0; v < nVars; v++ ) - bVars[v] = dd->vars[ dd->invperm[p->Level+v] ]; - bVarsInCube = Extra_bddBitsToCube( dd, (1<nMulti == 1 ); - assert( p->nCols == 2 ); - assert( Cudd_IsConstant( p->paNodes[0] ) ); - assert( Cudd_IsConstant( p->paNodes[1] ) ); - - bVar = ( p->paNodes[0] == a1 )? bCVars[0]: Cudd_Not( bCVars[0] ); - p->bRelation = Cudd_bddIte( dd, bVar, p->pbCols[0], p->pbCols[1] ); Cudd_Ref( p->bRelation ); - } - else - { - long clk2 = clock(); -// p->bRelation = PerformTheEncoding( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple ); Cudd_Ref( p->bRelation ); - p->bRelation = Extra_bddEncodingNonStrict( dd, p->pbCols, p->nCols, bVarsCube, bCVars, p->nMulti, &p->nSimple ); Cudd_Ref( p->bRelation ); - s_EncodingTime += clock() - clk2; - } - - // update the number of LUT outputs - nLutOutputs += (p->nMulti - p->nSimple); - nLutsTotal += p->nMulti; - -//if ( fVerbose ) -//printf( "Stage %2d: Simple = %d\n", i+1, p->nSimple ); - -if ( fVerbose ) -printf( "Stage %3d: In = %3d InP = %3d Cols = %5d Multi = %2d Simple = %2d Level = %3d\n", - i+1, p->nIns, p->nInsP, p->nCols, p->nMulti, p->nSimple, p->Level ); - - // get the codes from the relation (these are not necessarily cubes) - { - int c; - for ( c = 0; c < p->nCols; c++ ) - { - p->pbCodes[c] = Cudd_bddAndAbstract( dd, p->bRelation, p->pbCols[c], bVarsCube ); Cudd_Ref( p->pbCodes[c] ); - } - } - - Cudd_RecursiveDeref( dd, bVarsCube ); - - // remap the codes to depend on the topmost varibles of the manager - // useful as a preparation for the next step - { - DdNode ** pbTemp; - int k, v; - - pbTemp = (DdNode **) malloc( p->nCols * sizeof(DdNode *) ); - - // create the identical permutation - for ( v = 0; v < dd->size; v++ ) - Permute[v] = v; - - // use the topmost variables of the manager - // to represent the previous level codes - for ( v = 0; v < p->nMulti; v++ ) - Permute[bCVars[v]->index] = dd->invperm[v]; - - Extra_bddPermuteArray( dd, p->pbCodes, pbTemp, p->nCols, Permute ); - // the array pbTemp comes already referenced - - // deref the old codes and assign the new ones - for ( k = 0; k < p->nCols; k++ ) - { - Cudd_RecursiveDeref( dd, p->pbCodes[k] ); - p->pbCodes[k] = pbTemp[k]; - } - free( pbTemp ); - } - } - if ( fVerbose ) - printf( "LUTs: Total = %5d. Final = %5d. Simple = %5d. (%6.2f %%) ", - nLutsTotal, nLutOutputs, nLutsTotal-nLutOutputs, 100.0*(nLutsTotal-nLutOutputs)/nLutsTotal ); - if ( fVerbose ) - printf( "Memory = %6.2f Mb\n", 1.0*nLutOutputs*(1<nCols; v++ ) - { - Cudd_RecursiveDeref( dd, p->pbCols[v] ); - Cudd_RecursiveDeref( dd, p->pbCodes[v] ); - Cudd_RecursiveDeref( dd, p->paNodes[v] ); - } - Cudd_RecursiveDeref( dd, p->bRelation ); - - free( p->pbCols ); - free( p->pbCodes ); - free( p->paNodes ); - free( p ); - } - - return 1; -} - -void WriteLUTSintoBLIFfile( FILE * pFile, DdManager * dd, LUT ** pLuts, int nLuts, DdNode ** bCVars, char ** pNames, int nNames, char * FileName ) -{ - int i, v, o; - static char * pNamesLocalIn[MAXINPUTS]; - static char * pNamesLocalOut[MAXINPUTS]; - static char Buffer[100]; - DdNode * bCube, * bCof, * bFunc; - LUT * p; - - // go through all the LUTs - for ( i = 0; i < nLuts; i++ ) - { - // get the pointer to the LUT - p = pLuts[i]; - - if ( i == nLuts -1 ) - { - assert( p->nMulti == 1 ); - } - - - fprintf( pFile, "#----------------- LUT #%d ----------------------\n", i ); - - - // fill in the names for the current LUT - - // write the outputs of the previous LUT - if ( i != 0 ) - for ( v = 0; v < p->nInsP; v++ ) - { - sprintf( Buffer, "LUT%02d_%02d", i-1, v ); - pNamesLocalIn[dd->invperm[v]] = Extra_UtilStrsav( Buffer ); - } - // write the primary inputs of the current LUT - for ( v = 0; v < p->nIns - p->nInsP; v++ ) - pNamesLocalIn[dd->invperm[p->Level+v]] = Extra_UtilStrsav( pNames[dd->invperm[p->Level+v]] ); - // write the outputs of the current LUT - for ( v = 0; v < p->nMulti; v++ ) - { - sprintf( Buffer, "LUT%02d_%02d", i, v ); - if ( i != nLuts - 1 ) - pNamesLocalOut[v] = Extra_UtilStrsav( Buffer ); - else - pNamesLocalOut[v] = Extra_UtilStrsav( "F" ); - } - - - // write LUT outputs - - // get the prefix - sprintf( Buffer, "L%02d_", i ); - - // get the cube of encoding variables - bCube = Extra_bddBitsToCube( dd, (1<nMulti)-1, p->nMulti, bCVars, 1 ); Cudd_Ref( bCube ); - - // write each output of the LUT - for ( o = 0; o < p->nMulti; o++ ) - { - // get the cofactor of this output - bCof = Cudd_Cofactor( dd, p->bRelation, bCVars[o] ); Cudd_Ref( bCof ); - // quantify the remaining variables to get the function - bFunc = Cudd_bddExistAbstract( dd, bCof, bCube ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bCof ); - - // write BLIF - sprintf( Buffer, "L%02d_%02d_", i, o ); - -// WriteDDintoBLIFfileReorder( dd, pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn ); - // does not work well; the advantage is marginal (30%), the run time is huge... - - WriteDDintoBLIFfile( pFile, bFunc, pNamesLocalOut[o], Buffer, pNamesLocalIn ); - Cudd_RecursiveDeref( dd, bFunc ); - } - Cudd_RecursiveDeref( dd, bCube ); - - // clean up the previous local names - for ( v = 0; v < dd->size; v++ ) - { - if ( pNamesLocalIn[v] ) - free( pNamesLocalIn[v] ); - pNamesLocalIn[v] = NULL; - } - for ( v = 0; v < p->nMulti; v++ ) - free( pNamesLocalOut[v] ); - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - - - diff --git a/src/bdd/cas/module.make b/src/bdd/cas/module.make deleted file mode 100644 index 7830e47f..00000000 --- a/src/bdd/cas/module.make +++ /dev/null @@ -1,3 +0,0 @@ -SRC += src/bdd/cas/casCore.c \ - src/bdd/cas/casDec.c - diff --git a/src/bdd/cudd/cuBdd.make b/src/bdd/cudd/cuBdd.make deleted file mode 100644 index b16a27b3..00000000 --- a/src/bdd/cudd/cuBdd.make +++ /dev/null @@ -1,41 +0,0 @@ -CSRC_cu += cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \ - cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \ - cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c \ - cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \ - cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c cuddExact.c \ - cuddExport.c cuddGenCof.c cuddGenetic.c \ - cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \ - cuddLCache.c cuddLevelQ.c \ - cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \ - cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \ - cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \ - cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \ - cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c cuddZddPort.c \ - cuddZddReord.c cuddZddSetop.c cuddZddSymm.c cuddZddUtil.c -HEADERS_cu += cudd.h cuddInt.h -MISC += testcudd.c r7x8.1.mat doc/cudd.ps doc/cuddAllAbs.html doc/cuddAllDet.html \ - doc/cuddExtAbs.html doc/cuddExtDet.html doc/cuddIntro.css \ - doc/cuddIntro.html doc/footnode.html doc/img1.gif doc/img2.gif \ - doc/img3.gif doc/img4.gif doc/img5.gif doc/index.html \ - doc/node1.html doc/node2.html doc/node3.html doc/node4.html \ - doc/node5.html doc/node6.html doc/node7.html doc/node8.html \ - doc/icons/change_begin.gif \ - doc/icons/change_delete.gif \ - doc/icons/change_end.gif \ - doc/icons/contents_motif.gif \ - doc/icons/cross_ref_motif.gif \ - doc/icons/foot_motif.gif \ - doc/icons/image.gif \ - doc/icons/index_motif.gif \ - doc/icons/next_group_motif.gif \ - doc/icons/next_group_motif_gr.gif \ - doc/icons/next_motif.gif \ - doc/icons/next_motif_gr.gif \ - doc/icons/previous_group_motif.gif \ - doc/icons/previous_group_motif_gr.gif \ - doc/icons/previous_motif.gif \ - doc/icons/previous_motif_gr.gif \ - doc/icons/up_motif.gif \ - doc/icons/up_motif_gr.gif - -DEPENDENCYFILES = $(CSRC_cu) diff --git a/src/bdd/cudd/cudd.h b/src/bdd/cudd/cudd.h deleted file mode 100644 index a31fcdae..00000000 --- a/src/bdd/cudd/cudd.h +++ /dev/null @@ -1,959 +0,0 @@ -/**CHeaderFile***************************************************************** - - FileName [cudd.h] - - PackageName [cudd] - - Synopsis [The University of Colorado decision diagram package.] - - Description [External functions and data strucures of the CUDD package. -

          -
        • To turn on the gathering of statistics, define DD_STATS. -
        • To link with mis, define DD_MIS. -
        - Modified by Abelardo Pardo to interface it to VIS. - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: cudd.h,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $] - -******************************************************************************/ - -#ifndef _CUDD -#define _CUDD - -/*---------------------------------------------------------------------------*/ -/* Nested includes */ -/*---------------------------------------------------------------------------*/ - -#include "mtr.h" -#include "epd.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define CUDD_VERSION "2.3.1" - -#ifndef SIZEOF_VOID_P -#define SIZEOF_VOID_P 4 -#endif -#ifndef SIZEOF_INT -#define SIZEOF_INT 4 -#endif -#ifndef SIZEOF_LONG -#define SIZEOF_LONG 4 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define CUDD_VALUE_TYPE double -#define CUDD_OUT_OF_MEM -1 -/* The sizes of the subtables and the cache must be powers of two. */ -#define CUDD_UNIQUE_SLOTS 256 /* initial size of subtables */ -#define CUDD_CACHE_SLOTS 262144 /* default size of the cache */ - -/* Constants for residue functions. */ -#define CUDD_RESIDUE_DEFAULT 0 -#define CUDD_RESIDUE_MSB 1 -#define CUDD_RESIDUE_TC 2 - -/* CUDD_MAXINDEX is defined in such a way that on 32-bit and 64-bit -** machines one can cast an index to (int) without generating a negative -** number. -*/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define CUDD_MAXINDEX (((DdHalfWord) ~0) >> 1) -#else -#define CUDD_MAXINDEX ((DdHalfWord) ~0) -#endif - -/* CUDD_CONST_INDEX is the index of constant nodes. Currently this -** is a synonim for CUDD_MAXINDEX. */ -#define CUDD_CONST_INDEX CUDD_MAXINDEX - -/* These constants define the digits used in the representation of -** arbitrary precision integers. The two configurations tested use 8 -** and 16 bits for each digit. The typedefs should be in agreement -** with these definitions. -*/ -#define DD_APA_BITS 16 -#define DD_APA_BASE (1 << DD_APA_BITS) -#define DD_APA_MASK (DD_APA_BASE - 1) -#define DD_APA_HEXPRINT "%04x" - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/**Enum************************************************************************ - - Synopsis [Type of reordering algorithm.] - - Description [Type of reordering algorithm.] - -******************************************************************************/ -typedef enum { - CUDD_REORDER_SAME, - CUDD_REORDER_NONE, - CUDD_REORDER_RANDOM, - CUDD_REORDER_RANDOM_PIVOT, - CUDD_REORDER_SIFT, - CUDD_REORDER_SIFT_CONVERGE, - CUDD_REORDER_SYMM_SIFT, - CUDD_REORDER_SYMM_SIFT_CONV, - CUDD_REORDER_WINDOW2, - CUDD_REORDER_WINDOW3, - CUDD_REORDER_WINDOW4, - CUDD_REORDER_WINDOW2_CONV, - CUDD_REORDER_WINDOW3_CONV, - CUDD_REORDER_WINDOW4_CONV, - CUDD_REORDER_GROUP_SIFT, - CUDD_REORDER_GROUP_SIFT_CONV, - CUDD_REORDER_ANNEALING, - CUDD_REORDER_GENETIC, - CUDD_REORDER_LINEAR, - CUDD_REORDER_LINEAR_CONVERGE, - CUDD_REORDER_LAZY_SIFT, - CUDD_REORDER_EXACT -} Cudd_ReorderingType; - - -/**Enum************************************************************************ - - Synopsis [Type of aggregation methods.] - - Description [Type of aggregation methods.] - -******************************************************************************/ -typedef enum { - CUDD_NO_CHECK, - CUDD_GROUP_CHECK, - CUDD_GROUP_CHECK2, - CUDD_GROUP_CHECK3, - CUDD_GROUP_CHECK4, - CUDD_GROUP_CHECK5, - CUDD_GROUP_CHECK6, - CUDD_GROUP_CHECK7, - CUDD_GROUP_CHECK8, - CUDD_GROUP_CHECK9 -} Cudd_AggregationType; - - -/**Enum************************************************************************ - - Synopsis [Type of hooks.] - - Description [Type of hooks.] - -******************************************************************************/ -typedef enum { - CUDD_PRE_GC_HOOK, - CUDD_POST_GC_HOOK, - CUDD_PRE_REORDERING_HOOK, - CUDD_POST_REORDERING_HOOK -} Cudd_HookType; - - -/**Enum************************************************************************ - - Synopsis [Type of error codes.] - - Description [Type of error codes.] - -******************************************************************************/ -typedef enum { - CUDD_NO_ERROR, - CUDD_MEMORY_OUT, - CUDD_TOO_MANY_NODES, - CUDD_MAX_MEM_EXCEEDED, - CUDD_INVALID_ARG, - CUDD_INTERNAL_ERROR -} Cudd_ErrorType; - - -/**Enum************************************************************************ - - Synopsis [Group type for lazy sifting.] - - Description [Group type for lazy sifting.] - -******************************************************************************/ -typedef enum { - CUDD_LAZY_NONE, - CUDD_LAZY_SOFT_GROUP, - CUDD_LAZY_HARD_GROUP, - CUDD_LAZY_UNGROUP -} Cudd_LazyGroupType; - - -/**Enum************************************************************************ - - Synopsis [Variable type.] - - Description [Variable type. Currently used only in lazy sifting.] - -******************************************************************************/ -typedef enum { - CUDD_VAR_PRIMARY_INPUT, - CUDD_VAR_PRESENT_STATE, - CUDD_VAR_NEXT_STATE -} Cudd_VariableType; - - -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -typedef unsigned int DdHalfWord; -#else -typedef unsigned short DdHalfWord; -#endif - -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - -typedef struct DdNode DdNode; - -typedef struct DdChildren { - struct DdNode *T; - struct DdNode *E; -} DdChildren; - -/* The DdNode structure is the only one exported out of the package */ -struct DdNode { - DdHalfWord index; - DdHalfWord ref; /* reference count */ - DdNode *next; /* next pointer for unique table */ - union { - CUDD_VALUE_TYPE value; /* for constant nodes */ - DdChildren kids; /* for internal nodes */ - } type; -}; - -#ifdef __osf__ -#pragma pointer_size restore -#endif - -typedef struct DdManager DdManager; - -typedef struct DdGen DdGen; - -/* These typedefs for arbitrary precision arithmetic should agree with -** the corresponding constant definitions above. */ -typedef unsigned short int DdApaDigit; -typedef unsigned long int DdApaDoubleDigit; -typedef DdApaDigit * DdApaNumber; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**Macro*********************************************************************** - - Synopsis [Returns 1 if the node is a constant node.] - - Description [Returns 1 if the node is a constant node (rather than an - internal node). All constant nodes have the same index - (CUDD_CONST_INDEX). The pointer passed to Cudd_IsConstant may be either - regular or complemented.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -#define Cudd_IsConstant(node) ((Cudd_Regular(node))->index == CUDD_CONST_INDEX) - - -/**Macro*********************************************************************** - - Synopsis [Complements a DD.] - - Description [Complements a DD by flipping the complement attribute of - the pointer (the least significant bit).] - - SideEffects [none] - - SeeAlso [Cudd_NotCond] - -******************************************************************************/ -#define Cudd_Not(node) ((DdNode *)((long)(node) ^ 01)) - - -/**Macro*********************************************************************** - - Synopsis [Complements a DD if a condition is true.] - - Description [Complements a DD if condition c is true; c should be - either 0 or 1, because it is used directly (for efficiency). If in - doubt on the values c may take, use "(c) ? Cudd_Not(node) : node".] - - SideEffects [none] - - SeeAlso [Cudd_Not] - -******************************************************************************/ -#define Cudd_NotCond(node,c) ((DdNode *)((long)(node) ^ (c))) - - -/**Macro*********************************************************************** - - Synopsis [Returns the regular version of a pointer.] - - Description [] - - SideEffects [none] - - SeeAlso [Cudd_Complement Cudd_IsComplement] - -******************************************************************************/ -#define Cudd_Regular(node) ((DdNode *)((unsigned long)(node) & ~01)) - - -/**Macro*********************************************************************** - - Synopsis [Returns the complemented version of a pointer.] - - Description [] - - SideEffects [none] - - SeeAlso [Cudd_Regular Cudd_IsComplement] - -******************************************************************************/ -#define Cudd_Complement(node) ((DdNode *)((unsigned long)(node) | 01)) - - -/**Macro*********************************************************************** - - Synopsis [Returns 1 if a pointer is complemented.] - - Description [] - - SideEffects [none] - - SeeAlso [Cudd_Regular Cudd_Complement] - -******************************************************************************/ -#define Cudd_IsComplement(node) ((int) ((long) (node) & 01)) - - -/**Macro*********************************************************************** - - Synopsis [Returns the then child of an internal node.] - - Description [Returns the then child of an internal node. If - node is a constant node, the result is unpredictable.] - - SideEffects [none] - - SeeAlso [Cudd_E Cudd_V] - -******************************************************************************/ -#define Cudd_T(node) ((Cudd_Regular(node))->type.kids.T) - - -/**Macro*********************************************************************** - - Synopsis [Returns the else child of an internal node.] - - Description [Returns the else child of an internal node. If - node is a constant node, the result is unpredictable.] - - SideEffects [none] - - SeeAlso [Cudd_T Cudd_V] - -******************************************************************************/ -#define Cudd_E(node) ((Cudd_Regular(node))->type.kids.E) - - -/**Macro*********************************************************************** - - Synopsis [Returns the value of a constant node.] - - Description [Returns the value of a constant node. If - node is an internal node, the result is unpredictable.] - - SideEffects [none] - - SeeAlso [Cudd_T Cudd_E] - -******************************************************************************/ -#define Cudd_V(node) ((Cudd_Regular(node))->type.value) - - -/**Macro*********************************************************************** - - Synopsis [Returns the current position in the order of variable - index.] - - Description [Returns the current position in the order of variable - index. This macro is obsolete and is kept for compatibility. New - applications should use Cudd_ReadPerm instead.] - - SideEffects [none] - - SeeAlso [Cudd_ReadPerm] - -******************************************************************************/ -#define Cudd_ReadIndex(dd,index) (Cudd_ReadPerm(dd,index)) - - -/**Macro*********************************************************************** - - Synopsis [Iterates over the cubes of a decision diagram.] - - Description [Iterates over the cubes of a decision diagram f. -
          -
        • DdManager *manager; -
        • DdNode *f; -
        • DdGen *gen; -
        • int *cube; -
        • CUDD_VALUE_TYPE value; -
        - Cudd_ForeachCube allocates and frees the generator. Therefore the - application should not try to do that. Also, the cube is freed at the - end of Cudd_ForeachCube and hence is not available outside of the loop.

        - CAUTION: It is assumed that dynamic reordering will not occur while - there are open generators. It is the user's responsibility to make sure - that dynamic reordering does not occur. As long as new nodes are not created - during generation, and dynamic reordering is not called explicitly, - dynamic reordering will not occur. Alternatively, it is sufficient to - disable dynamic reordering. It is a mistake to dispose of a diagram - on which generation is ongoing.] - - SideEffects [none] - - SeeAlso [Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube Cudd_GenFree - Cudd_IsGenEmpty Cudd_AutodynDisable] - -******************************************************************************/ -#define Cudd_ForeachCube(manager, f, gen, cube, value)\ - for((gen) = Cudd_FirstCube(manager, f, &cube, &value);\ - Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ - (void) Cudd_NextCube(gen, &cube, &value)) - - -/**Macro*********************************************************************** - - Synopsis [Iterates over the nodes of a decision diagram.] - - Description [Iterates over the nodes of a decision diagram f. -

          -
        • DdManager *manager; -
        • DdNode *f; -
        • DdGen *gen; -
        • DdNode *node; -
        - The nodes are returned in a seemingly random order. - Cudd_ForeachNode allocates and frees the generator. Therefore the - application should not try to do that.

        - CAUTION: It is assumed that dynamic reordering will not occur while - there are open generators. It is the user's responsibility to make sure - that dynamic reordering does not occur. As long as new nodes are not created - during generation, and dynamic reordering is not called explicitly, - dynamic reordering will not occur. Alternatively, it is sufficient to - disable dynamic reordering. It is a mistake to dispose of a diagram - on which generation is ongoing.] - - SideEffects [none] - - SeeAlso [Cudd_ForeachCube Cudd_FirstNode Cudd_NextNode Cudd_GenFree - Cudd_IsGenEmpty Cudd_AutodynDisable] - -******************************************************************************/ -#define Cudd_ForeachNode(manager, f, gen, node)\ - for((gen) = Cudd_FirstNode(manager, f, &node);\ - Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ - (void) Cudd_NextNode(gen, &node)) - - -/**Macro*********************************************************************** - - Synopsis [Iterates over the paths of a ZDD.] - - Description [Iterates over the paths of a ZDD f. -

          -
        • DdManager *manager; -
        • DdNode *f; -
        • DdGen *gen; -
        • int *path; -
        - Cudd_zddForeachPath allocates and frees the generator. Therefore the - application should not try to do that. Also, the path is freed at the - end of Cudd_zddForeachPath and hence is not available outside of the loop.

        - CAUTION: It is assumed that dynamic reordering will not occur while - there are open generators. It is the user's responsibility to make sure - that dynamic reordering does not occur. As long as new nodes are not created - during generation, and dynamic reordering is not called explicitly, - dynamic reordering will not occur. Alternatively, it is sufficient to - disable dynamic reordering. It is a mistake to dispose of a diagram - on which generation is ongoing.] - - SideEffects [none] - - SeeAlso [Cudd_zddFirstPath Cudd_zddNextPath Cudd_GenFree - Cudd_IsGenEmpty Cudd_AutodynDisable] - -******************************************************************************/ -#define Cudd_zddForeachPath(manager, f, gen, path)\ - for((gen) = Cudd_zddFirstPath(manager, f, &path);\ - Cudd_IsGenEmpty(gen) ? Cudd_GenFree(gen) : TRUE;\ - (void) Cudd_zddNextPath(gen, &path)) - - -/* These are potential duplicates. */ -#ifndef EXTERN -# ifdef __cplusplus -# define EXTERN extern "C" -# else -# define EXTERN extern -# endif -#endif -#ifndef ARGS -# if defined(__STDC__) || defined(__cplusplus) -# define ARGS(protos) protos /* ANSI C */ -# else /* !(__STDC__ || __cplusplus) */ -# define ARGS(protos) () /* K&R C */ -# endif /* !(__STDC__ || __cplusplus) */ -#endif - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Function prototypes */ -/*---------------------------------------------------------------------------*/ - -EXTERN DdNode * Cudd_addNewVar ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_addNewVarAtLevel ARGS((DdManager *dd, int level)); -EXTERN DdNode * Cudd_bddNewVar ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_bddNewVarAtLevel ARGS((DdManager *dd, int level)); -EXTERN DdNode * Cudd_addIthVar ARGS((DdManager *dd, int i)); -EXTERN DdNode * Cudd_bddIthVar ARGS((DdManager *dd, int i)); -EXTERN DdNode * Cudd_zddIthVar ARGS((DdManager *dd, int i)); -EXTERN int Cudd_zddVarsFromBddVars ARGS((DdManager *dd, int multiplicity)); -EXTERN DdNode * Cudd_addConst ARGS((DdManager *dd, CUDD_VALUE_TYPE c)); -EXTERN int Cudd_IsNonConstant ARGS((DdNode *f)); -EXTERN void Cudd_AutodynEnable ARGS((DdManager *unique, Cudd_ReorderingType method)); -EXTERN void Cudd_AutodynDisable ARGS((DdManager *unique)); -EXTERN int Cudd_ReorderingStatus ARGS((DdManager *unique, Cudd_ReorderingType *method)); -EXTERN void Cudd_AutodynEnableZdd ARGS((DdManager *unique, Cudd_ReorderingType method)); -EXTERN void Cudd_AutodynDisableZdd ARGS((DdManager *unique)); -EXTERN int Cudd_ReorderingStatusZdd ARGS((DdManager *unique, Cudd_ReorderingType *method)); -EXTERN int Cudd_zddRealignmentEnabled ARGS((DdManager *unique)); -EXTERN void Cudd_zddRealignEnable ARGS((DdManager *unique)); -EXTERN void Cudd_zddRealignDisable ARGS((DdManager *unique)); -EXTERN int Cudd_bddRealignmentEnabled ARGS((DdManager *unique)); -EXTERN void Cudd_bddRealignEnable ARGS((DdManager *unique)); -EXTERN void Cudd_bddRealignDisable ARGS((DdManager *unique)); -EXTERN DdNode * Cudd_ReadOne ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_ReadZddOne ARGS((DdManager *dd, int i)); -EXTERN DdNode * Cudd_ReadZero ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_ReadLogicZero ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_ReadPlusInfinity ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_ReadMinusInfinity ARGS((DdManager *dd)); -EXTERN DdNode * Cudd_ReadBackground ARGS((DdManager *dd)); -EXTERN void Cudd_SetBackground ARGS((DdManager *dd, DdNode *bck)); -EXTERN unsigned int Cudd_ReadCacheSlots ARGS((DdManager *dd)); -EXTERN double Cudd_ReadCacheUsedSlots ARGS((DdManager * dd)); -EXTERN double Cudd_ReadCacheLookUps ARGS((DdManager *dd)); -EXTERN double Cudd_ReadCacheHits ARGS((DdManager *dd)); -EXTERN double Cudd_ReadRecursiveCalls ARGS ((DdManager * dd)); -EXTERN unsigned int Cudd_ReadMinHit ARGS((DdManager *dd)); -EXTERN void Cudd_SetMinHit ARGS((DdManager *dd, unsigned int hr)); -EXTERN unsigned int Cudd_ReadLooseUpTo ARGS((DdManager *dd)); -EXTERN void Cudd_SetLooseUpTo ARGS((DdManager *dd, unsigned int lut)); -EXTERN unsigned int Cudd_ReadMaxCache ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_ReadMaxCacheHard ARGS((DdManager *dd)); -EXTERN void Cudd_SetMaxCacheHard ARGS((DdManager *dd, unsigned int mc)); -EXTERN int Cudd_ReadSize ARGS((DdManager *dd)); -EXTERN int Cudd_ReadZddSize ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_ReadSlots ARGS((DdManager *dd)); -EXTERN double Cudd_ReadUsedSlots ARGS((DdManager * dd)); -EXTERN double Cudd_ExpectedUsedSlots ARGS((DdManager * dd)); -EXTERN unsigned int Cudd_ReadKeys ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_ReadDead ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_ReadMinDead ARGS((DdManager *dd)); -EXTERN int Cudd_ReadReorderings ARGS((DdManager *dd)); -EXTERN long Cudd_ReadReorderingTime ARGS((DdManager * dd)); -EXTERN int Cudd_ReadGarbageCollections ARGS((DdManager * dd)); -EXTERN long Cudd_ReadGarbageCollectionTime ARGS((DdManager * dd)); -EXTERN double Cudd_ReadNodesFreed ARGS((DdManager * dd)); -EXTERN double Cudd_ReadNodesDropped ARGS((DdManager * dd)); -EXTERN double Cudd_ReadUniqueLookUps ARGS((DdManager * dd)); -EXTERN double Cudd_ReadUniqueLinks ARGS((DdManager * dd)); -EXTERN int Cudd_ReadSiftMaxVar ARGS((DdManager *dd)); -EXTERN void Cudd_SetSiftMaxVar ARGS((DdManager *dd, int smv)); -EXTERN int Cudd_ReadSiftMaxSwap ARGS((DdManager *dd)); -EXTERN void Cudd_SetSiftMaxSwap ARGS((DdManager *dd, int sms)); -EXTERN double Cudd_ReadMaxGrowth ARGS((DdManager *dd)); -EXTERN void Cudd_SetMaxGrowth ARGS((DdManager *dd, double mg)); -EXTERN double Cudd_ReadMaxGrowthAlternate ARGS((DdManager * dd)); -EXTERN void Cudd_SetMaxGrowthAlternate ARGS((DdManager * dd, double mg)); -EXTERN int Cudd_ReadReorderingCycle ARGS((DdManager * dd)); -EXTERN void Cudd_SetReorderingCycle ARGS((DdManager * dd, int cycle)); -EXTERN MtrNode * Cudd_ReadTree ARGS((DdManager *dd)); -EXTERN void Cudd_SetTree ARGS((DdManager *dd, MtrNode *tree)); -EXTERN void Cudd_FreeTree ARGS((DdManager *dd)); -EXTERN MtrNode * Cudd_ReadZddTree ARGS((DdManager *dd)); -EXTERN void Cudd_SetZddTree ARGS((DdManager *dd, MtrNode *tree)); -EXTERN void Cudd_FreeZddTree ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_NodeReadIndex ARGS((DdNode *node)); -EXTERN int Cudd_ReadPerm ARGS((DdManager *dd, int i)); -EXTERN int Cudd_ReadPermZdd ARGS((DdManager *dd, int i)); -EXTERN int Cudd_ReadInvPerm ARGS((DdManager *dd, int i)); -EXTERN int Cudd_ReadInvPermZdd ARGS((DdManager *dd, int i)); -EXTERN DdNode * Cudd_ReadVars ARGS((DdManager *dd, int i)); -EXTERN CUDD_VALUE_TYPE Cudd_ReadEpsilon ARGS((DdManager *dd)); -EXTERN void Cudd_SetEpsilon ARGS((DdManager *dd, CUDD_VALUE_TYPE ep)); -EXTERN Cudd_AggregationType Cudd_ReadGroupcheck ARGS((DdManager *dd)); -EXTERN void Cudd_SetGroupcheck ARGS((DdManager *dd, Cudd_AggregationType gc)); -EXTERN int Cudd_GarbageCollectionEnabled ARGS((DdManager *dd)); -EXTERN void Cudd_EnableGarbageCollection ARGS((DdManager *dd)); -EXTERN void Cudd_DisableGarbageCollection ARGS((DdManager *dd)); -EXTERN int Cudd_DeadAreCounted ARGS((DdManager *dd)); -EXTERN void Cudd_TurnOnCountDead ARGS((DdManager *dd)); -EXTERN void Cudd_TurnOffCountDead ARGS((DdManager *dd)); -EXTERN int Cudd_ReadRecomb ARGS((DdManager *dd)); -EXTERN void Cudd_SetRecomb ARGS((DdManager *dd, int recomb)); -EXTERN int Cudd_ReadSymmviolation ARGS((DdManager *dd)); -EXTERN void Cudd_SetSymmviolation ARGS((DdManager *dd, int symmviolation)); -EXTERN int Cudd_ReadArcviolation ARGS((DdManager *dd)); -EXTERN void Cudd_SetArcviolation ARGS((DdManager *dd, int arcviolation)); -EXTERN int Cudd_ReadPopulationSize ARGS((DdManager *dd)); -EXTERN void Cudd_SetPopulationSize ARGS((DdManager *dd, int populationSize)); -EXTERN int Cudd_ReadNumberXovers ARGS((DdManager *dd)); -EXTERN void Cudd_SetNumberXovers ARGS((DdManager *dd, int numberXovers)); -EXTERN long Cudd_ReadMemoryInUse ARGS((DdManager *dd)); -EXTERN int Cudd_PrintInfo ARGS((DdManager *dd, FILE *fp)); -EXTERN long Cudd_ReadPeakNodeCount ARGS((DdManager *dd)); -EXTERN int Cudd_ReadPeakLiveNodeCount ARGS((DdManager * dd)); -EXTERN long Cudd_ReadNodeCount ARGS((DdManager *dd)); -EXTERN long Cudd_zddReadNodeCount ARGS((DdManager *dd)); -EXTERN int Cudd_AddHook ARGS((DdManager *dd, int (*f)(DdManager *, char *, void *), Cudd_HookType where)); -EXTERN int Cudd_RemoveHook ARGS((DdManager *dd, int (*f)(DdManager *, char *, void *), Cudd_HookType where)); -EXTERN int Cudd_IsInHook ARGS((DdManager * dd, int (*f)(DdManager *, char *, void *), Cudd_HookType where)); -EXTERN int Cudd_StdPreReordHook ARGS((DdManager *dd, char *str, void *data)); -EXTERN int Cudd_StdPostReordHook ARGS((DdManager *dd, char *str, void *data)); -EXTERN int Cudd_EnableReorderingReporting ARGS((DdManager *dd)); -EXTERN int Cudd_DisableReorderingReporting ARGS((DdManager *dd)); -EXTERN int Cudd_ReorderingReporting ARGS((DdManager *dd)); -EXTERN Cudd_ErrorType Cudd_ReadErrorCode ARGS((DdManager *dd)); -EXTERN void Cudd_ClearErrorCode ARGS((DdManager *dd)); -EXTERN FILE * Cudd_ReadStdout ARGS((DdManager *dd)); -EXTERN void Cudd_SetStdout ARGS((DdManager *dd, FILE *fp)); -EXTERN FILE * Cudd_ReadStderr ARGS((DdManager *dd)); -EXTERN void Cudd_SetStderr ARGS((DdManager *dd, FILE *fp)); -EXTERN unsigned int Cudd_ReadNextReordering ARGS((DdManager *dd)); -EXTERN void Cudd_SetNextReordering ARGS((DdManager *dd, unsigned int next)); -EXTERN double Cudd_ReadSwapSteps ARGS((DdManager *dd)); -EXTERN unsigned int Cudd_ReadMaxLive ARGS((DdManager *dd)); -EXTERN void Cudd_SetMaxLive ARGS((DdManager *dd, unsigned int maxLive)); -EXTERN long Cudd_ReadMaxMemory ARGS((DdManager *dd)); -EXTERN void Cudd_SetMaxMemory ARGS((DdManager *dd, long maxMemory)); -EXTERN int Cudd_bddBindVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddUnbindVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddVarIsBound ARGS((DdManager *dd, int index)); -EXTERN DdNode * Cudd_addExistAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * Cudd_addUnivAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * Cudd_addOrAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * Cudd_addApply ARGS((DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_addPlus ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addTimes ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addThreshold ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addSetNZ ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addDivide ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addMinus ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addMinimum ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addMaximum ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addOneZeroMaximum ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addDiff ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addAgreement ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addOr ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addNand ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addNor ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addXor ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addXnor ARGS((DdManager *dd, DdNode **f, DdNode **g)); -EXTERN DdNode * Cudd_addMonadicApply ARGS((DdManager * dd, DdNode * (*op)(DdManager *, DdNode *), DdNode * f)); -EXTERN DdNode * Cudd_addLog ARGS((DdManager * dd, DdNode * f)); -EXTERN DdNode * Cudd_addFindMax ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_addFindMin ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_addIthBit ARGS((DdManager *dd, DdNode *f, int bit)); -EXTERN DdNode * Cudd_addScalarInverse ARGS((DdManager *dd, DdNode *f, DdNode *epsilon)); -EXTERN DdNode * Cudd_addIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * Cudd_addIteConstant ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * Cudd_addEvalConst ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN int Cudd_addLeq ARGS((DdManager * dd, DdNode * f, DdNode * g)); -EXTERN DdNode * Cudd_addCmpl ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_addNegate ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_addRoundOff ARGS((DdManager *dd, DdNode *f, int N)); -EXTERN DdNode * Cudd_addWalsh ARGS((DdManager *dd, DdNode **x, DdNode **y, int n)); -EXTERN DdNode * Cudd_addResidue ARGS((DdManager *dd, int n, int m, int options, int top)); -EXTERN DdNode * Cudd_bddAndAbstract ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); -EXTERN int Cudd_ApaNumberOfDigits ARGS((int binaryDigits)); -EXTERN DdApaNumber Cudd_NewApaNumber ARGS((int digits)); -EXTERN void Cudd_ApaCopy ARGS((int digits, DdApaNumber source, DdApaNumber dest)); -EXTERN DdApaDigit Cudd_ApaAdd ARGS((int digits, DdApaNumber a, DdApaNumber b, DdApaNumber sum)); -EXTERN DdApaDigit Cudd_ApaSubtract ARGS((int digits, DdApaNumber a, DdApaNumber b, DdApaNumber diff)); -EXTERN DdApaDigit Cudd_ApaShortDivision ARGS((int digits, DdApaNumber dividend, DdApaDigit divisor, DdApaNumber quotient)); -EXTERN unsigned int Cudd_ApaIntDivision ARGS((int digits, DdApaNumber dividend, unsigned int divisor, DdApaNumber quotient)); -EXTERN void Cudd_ApaShiftRight ARGS((int digits, DdApaDigit in, DdApaNumber a, DdApaNumber b)); -EXTERN void Cudd_ApaSetToLiteral ARGS((int digits, DdApaNumber number, DdApaDigit literal)); -EXTERN void Cudd_ApaPowerOfTwo ARGS((int digits, DdApaNumber number, int power)); -EXTERN int Cudd_ApaCompare ARGS((int digitsFirst, DdApaNumber first, int digitsSecond, DdApaNumber second)); -EXTERN int Cudd_ApaCompareRatios ARGS ((int digitsFirst, DdApaNumber firstNum, unsigned int firstDen, int digitsSecond, DdApaNumber secondNum, unsigned int secondDen)); -EXTERN int Cudd_ApaPrintHex ARGS((FILE *fp, int digits, DdApaNumber number)); -EXTERN int Cudd_ApaPrintDecimal ARGS((FILE *fp, int digits, DdApaNumber number)); -EXTERN int Cudd_ApaPrintExponential ARGS((FILE * fp, int digits, DdApaNumber number, int precision)); -EXTERN DdApaNumber Cudd_ApaCountMinterm ARGS((DdManager *manager, DdNode *node, int nvars, int *digits)); -EXTERN int Cudd_ApaPrintMinterm ARGS((FILE *fp, DdManager *dd, DdNode *node, int nvars)); -EXTERN int Cudd_ApaPrintMintermExp ARGS((FILE * fp, DdManager * dd, DdNode * node, int nvars, int precision)); -EXTERN int Cudd_ApaPrintDensity ARGS((FILE * fp, DdManager * dd, DdNode * node, int nvars)); -EXTERN DdNode * Cudd_UnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality)); -EXTERN DdNode * Cudd_OverApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality)); -EXTERN DdNode * Cudd_RemapUnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, double quality)); -EXTERN DdNode * Cudd_RemapOverApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, double quality)); -EXTERN DdNode * Cudd_BiasedUnderApprox ARGS((DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0)); -EXTERN DdNode * Cudd_BiasedOverApprox ARGS((DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0)); -EXTERN DdNode * Cudd_bddExistAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * Cudd_bddXorExistAbstract ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); -EXTERN DdNode * Cudd_bddUnivAbstract ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * Cudd_bddBooleanDiff ARGS((DdManager *manager, DdNode *f, int x)); -EXTERN int Cudd_bddVarIsDependent ARGS((DdManager *dd, DdNode *f, DdNode *var)); -EXTERN double Cudd_bddCorrelation ARGS((DdManager *manager, DdNode *f, DdNode *g)); -EXTERN double Cudd_bddCorrelationWeights ARGS((DdManager *manager, DdNode *f, DdNode *g, double *prob)); -EXTERN DdNode * Cudd_bddIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * Cudd_bddIteConstant ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * Cudd_bddIntersect ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddAnd ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddOr ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddNand ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddNor ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddXor ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddXnor ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN int Cudd_bddLeq ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_addBddThreshold ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE value)); -EXTERN DdNode * Cudd_addBddStrictThreshold ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE value)); -EXTERN DdNode * Cudd_addBddInterval ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE lower, CUDD_VALUE_TYPE upper)); -EXTERN DdNode * Cudd_addBddIthBit ARGS((DdManager *dd, DdNode *f, int bit)); -EXTERN DdNode * Cudd_BddToAdd ARGS((DdManager *dd, DdNode *B)); -EXTERN DdNode * Cudd_addBddPattern ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_bddTransfer ARGS((DdManager *ddSource, DdManager *ddDestination, DdNode *f)); -EXTERN int Cudd_DebugCheck ARGS((DdManager *table)); -EXTERN int Cudd_CheckKeys ARGS((DdManager *table)); -EXTERN DdNode * Cudd_bddClippingAnd ARGS((DdManager *dd, DdNode *f, DdNode *g, int maxDepth, int direction)); -EXTERN DdNode * Cudd_bddClippingAndAbstract ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *cube, int maxDepth, int direction)); -EXTERN DdNode * Cudd_Cofactor ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_bddCompose ARGS((DdManager *dd, DdNode *f, DdNode *g, int v)); -EXTERN DdNode * Cudd_addCompose ARGS((DdManager *dd, DdNode *f, DdNode *g, int v)); -EXTERN DdNode * Cudd_addPermute ARGS((DdManager *manager, DdNode *node, int *permut)); -EXTERN DdNode * Cudd_addSwapVariables ARGS((DdManager *dd, DdNode *f, DdNode **x, DdNode **y, int n)); -EXTERN DdNode * Cudd_bddPermute ARGS((DdManager *manager, DdNode *node, int *permut)); -EXTERN DdNode * Cudd_bddVarMap ARGS((DdManager *manager, DdNode *f)); -EXTERN int Cudd_SetVarMap ARGS((DdManager *manager, DdNode **x, DdNode **y, int n)); -EXTERN DdNode * Cudd_bddSwapVariables ARGS((DdManager *dd, DdNode *f, DdNode **x, DdNode **y, int n)); -EXTERN DdNode * Cudd_bddAdjPermuteX ARGS((DdManager *dd, DdNode *B, DdNode **x, int n)); -EXTERN DdNode * Cudd_addVectorCompose ARGS((DdManager *dd, DdNode *f, DdNode **vector)); -EXTERN DdNode * Cudd_addGeneralVectorCompose ARGS((DdManager *dd, DdNode *f, DdNode **vectorOn, DdNode **vectorOff)); -EXTERN DdNode * Cudd_addNonSimCompose ARGS((DdManager *dd, DdNode *f, DdNode **vector)); -EXTERN DdNode * Cudd_bddVectorCompose ARGS((DdManager *dd, DdNode *f, DdNode **vector)); -EXTERN int Cudd_bddApproxConjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***conjuncts)); -EXTERN int Cudd_bddApproxDisjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***disjuncts)); -EXTERN int Cudd_bddIterConjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***conjuncts)); -EXTERN int Cudd_bddIterDisjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***disjuncts)); -EXTERN int Cudd_bddGenConjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***conjuncts)); -EXTERN int Cudd_bddGenDisjDecomp ARGS((DdManager *dd, DdNode *f, DdNode ***disjuncts)); -EXTERN int Cudd_bddVarConjDecomp ARGS((DdManager *dd, DdNode * f, DdNode ***conjuncts)); -EXTERN int Cudd_bddVarDisjDecomp ARGS((DdManager *dd, DdNode * f, DdNode ***disjuncts)); -EXTERN DdNode * Cudd_FindEssential ARGS((DdManager *dd, DdNode *f)); -EXTERN int Cudd_bddIsVarEssential ARGS((DdManager *manager, DdNode *f, int id, int phase)); -EXTERN int Cudd_DumpBlif ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, char *mname, FILE *fp)); -EXTERN int Cudd_DumpBlifBody ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN int Cudd_DumpDot ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN int Cudd_DumpDaVinci ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN int Cudd_DumpDDcal ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN int Cudd_DumpFactoredForm ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN DdNode * Cudd_bddConstrain ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * Cudd_bddRestrict ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * Cudd_addConstrain ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode ** Cudd_bddConstrainDecomp ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_addRestrict ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode ** Cudd_bddCharToVect ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_bddLICompaction ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * Cudd_bddSqueeze ARGS((DdManager *dd, DdNode *l, DdNode *u)); -EXTERN DdNode * Cudd_bddMinimize ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * Cudd_SubsetCompress ARGS((DdManager *dd, DdNode *f, int nvars, int threshold)); -EXTERN DdNode * Cudd_SupersetCompress ARGS((DdManager *dd, DdNode *f, int nvars, int threshold)); -EXTERN MtrNode * Cudd_MakeTreeNode ARGS((DdManager *dd, unsigned int low, unsigned int size, unsigned int type)); -EXTERN int Cudd_addHarwell ARGS((FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, DdNode ***xn, DdNode ***yn_, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy, int pr)); -EXTERN DdManager * Cudd_Init ARGS((unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory)); -EXTERN void Cudd_Quit ARGS((DdManager *unique)); -EXTERN int Cudd_PrintLinear ARGS((DdManager *table)); -EXTERN int Cudd_ReadLinear ARGS((DdManager *table, int x, int y)); -EXTERN DdNode * Cudd_bddLiteralSetIntersection ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_addMatrixMultiply ARGS((DdManager *dd, DdNode *A, DdNode *B, DdNode **z, int nz)); -EXTERN DdNode * Cudd_addTimesPlus ARGS((DdManager *dd, DdNode *A, DdNode *B, DdNode **z, int nz)); -EXTERN DdNode * Cudd_addTriangle ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode **z, int nz)); -EXTERN DdNode * Cudd_addOuterSum ARGS((DdManager *dd, DdNode *M, DdNode *r, DdNode *c)); -EXTERN DdNode * Cudd_PrioritySelect ARGS((DdManager *dd, DdNode *R, DdNode **x, DdNode **y, DdNode **z, DdNode *Pi, int n, DdNode * (*)(DdManager *, int, DdNode **, DdNode **, DdNode **))); -EXTERN DdNode * Cudd_Xgty ARGS((DdManager *dd, int N, DdNode **z, DdNode **x, DdNode **y)); -EXTERN DdNode * Cudd_Xeqy ARGS((DdManager *dd, int N, DdNode **x, DdNode **y)); -EXTERN DdNode * Cudd_addXeqy ARGS((DdManager *dd, int N, DdNode **x, DdNode **y)); -EXTERN DdNode * Cudd_Dxygtdxz ARGS((DdManager *dd, int N, DdNode **x, DdNode **y, DdNode **z)); -EXTERN DdNode * Cudd_Dxygtdyz ARGS((DdManager *dd, int N, DdNode **x, DdNode **y, DdNode **z)); -EXTERN DdNode * Cudd_CProjection ARGS((DdManager *dd, DdNode *R, DdNode *Y)); -EXTERN DdNode * Cudd_addHamming ARGS((DdManager *dd, DdNode **xVars, DdNode **yVars, int nVars)); -EXTERN int Cudd_MinHammingDist ARGS((DdManager *dd, DdNode *f, int *minterm, int upperBound)); -EXTERN DdNode * Cudd_bddClosestCube ARGS((DdManager *dd, DdNode * f, DdNode *g, int *distance)); -EXTERN int Cudd_addRead ARGS((FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, DdNode ***xn, DdNode ***yn_, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy)); -EXTERN int Cudd_bddRead ARGS((FILE *fp, DdManager *dd, DdNode **E, DdNode ***x, DdNode ***y, int *nx, int *ny, int *m, int *n, int bx, int sx, int by, int sy)); -EXTERN void Cudd_Ref ARGS((DdNode *n)); -EXTERN void Cudd_RecursiveDeref ARGS((DdManager *table, DdNode *n)); -EXTERN void Cudd_IterDerefBdd ARGS((DdManager *table, DdNode *n)); -EXTERN void Cudd_DelayedDerefBdd ARGS((DdManager * table, DdNode * n)); -EXTERN void Cudd_RecursiveDerefZdd ARGS((DdManager *table, DdNode *n)); -EXTERN void Cudd_Deref ARGS((DdNode *node)); -EXTERN int Cudd_CheckZeroRef ARGS((DdManager *manager)); -EXTERN int Cudd_ReduceHeap ARGS((DdManager *table, Cudd_ReorderingType heuristic, int minsize)); -EXTERN int Cudd_ShuffleHeap ARGS((DdManager *table, int *permutation)); -EXTERN DdNode * Cudd_Eval ARGS((DdManager *dd, DdNode *f, int *inputs)); -EXTERN DdNode * Cudd_ShortestPath ARGS((DdManager *manager, DdNode *f, int *weight, int *support, int *length)); -EXTERN DdNode * Cudd_LargestCube ARGS((DdManager *manager, DdNode *f, int *length)); -EXTERN int Cudd_ShortestLength ARGS((DdManager *manager, DdNode *f, int *weight)); -EXTERN DdNode * Cudd_Decreasing ARGS((DdManager *dd, DdNode *f, int i)); -EXTERN DdNode * Cudd_Increasing ARGS((DdManager *dd, DdNode *f, int i)); -EXTERN int Cudd_EquivDC ARGS((DdManager *dd, DdNode *F, DdNode *G, DdNode *D)); -EXTERN int Cudd_bddLeqUnless ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *D)); -EXTERN int Cudd_EqualSupNorm ARGS((DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE tolerance, int pr)); -EXTERN DdNode * Cudd_bddMakePrime ARGS ((DdManager *dd, DdNode *cube, DdNode *f)); -EXTERN double * Cudd_CofMinterm ARGS((DdManager *dd, DdNode *node)); -EXTERN DdNode * Cudd_SolveEqn ARGS((DdManager * bdd, DdNode *F, DdNode *Y, DdNode **G, int **yIndex, int n)); -EXTERN DdNode * Cudd_VerifySol ARGS((DdManager * bdd, DdNode *F, DdNode **G, int *yIndex, int n)); -EXTERN DdNode * Cudd_SplitSet ARGS((DdManager *manager, DdNode *S, DdNode **xVars, int n, double m)); -EXTERN DdNode * Cudd_SubsetHeavyBranch ARGS((DdManager *dd, DdNode *f, int numVars, int threshold)); -EXTERN DdNode * Cudd_SupersetHeavyBranch ARGS((DdManager *dd, DdNode *f, int numVars, int threshold)); -EXTERN DdNode * Cudd_SubsetShortPaths ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)); -EXTERN DdNode * Cudd_SupersetShortPaths ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)); -EXTERN void Cudd_SymmProfile ARGS((DdManager *table, int lower, int upper)); -EXTERN unsigned int Cudd_Prime ARGS((unsigned int p)); -EXTERN int Cudd_PrintMinterm ARGS((DdManager *manager, DdNode *node)); -EXTERN int Cudd_bddPrintCover ARGS((DdManager *dd, DdNode *l, DdNode *u)); -EXTERN int Cudd_PrintDebug ARGS((DdManager *dd, DdNode *f, int n, int pr)); -EXTERN int Cudd_DagSize ARGS((DdNode *node)); -EXTERN int Cudd_EstimateCofactor ARGS((DdManager *dd, DdNode * node, int i, int phase)); -EXTERN int Cudd_EstimateCofactorSimple ARGS((DdNode * node, int i)); -EXTERN int Cudd_SharingSize ARGS((DdNode **nodeArray, int n)); -EXTERN double Cudd_CountMinterm ARGS((DdManager *manager, DdNode *node, int nvars)); -EXTERN int Cudd_EpdCountMinterm ARGS((DdManager *manager, DdNode *node, int nvars, EpDouble *epd)); -EXTERN double Cudd_CountPath ARGS((DdNode *node)); -EXTERN double Cudd_CountPathsToNonZero ARGS((DdNode *node)); -EXTERN DdNode * Cudd_Support ARGS((DdManager *dd, DdNode *f)); -EXTERN int * Cudd_SupportIndex ARGS((DdManager *dd, DdNode *f)); -EXTERN int Cudd_SupportSize ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * Cudd_VectorSupport ARGS((DdManager *dd, DdNode **F, int n)); -EXTERN int * Cudd_VectorSupportIndex ARGS((DdManager *dd, DdNode **F, int n)); -EXTERN int Cudd_VectorSupportSize ARGS((DdManager *dd, DdNode **F, int n)); -EXTERN int Cudd_ClassifySupport ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode **common, DdNode **onlyF, DdNode **onlyG)); -EXTERN int Cudd_CountLeaves ARGS((DdNode *node)); -EXTERN int Cudd_bddPickOneCube ARGS((DdManager *ddm, DdNode *node, char *string)); -EXTERN DdNode * Cudd_bddPickOneMinterm ARGS((DdManager *dd, DdNode *f, DdNode **vars, int n)); -EXTERN DdNode ** Cudd_bddPickArbitraryMinterms ARGS((DdManager *dd, DdNode *f, DdNode **vars, int n, int k)); -EXTERN DdNode * Cudd_SubsetWithMaskVars ARGS((DdManager *dd, DdNode *f, DdNode **vars, int nvars, DdNode **maskVars, int mvars)); -EXTERN DdGen * Cudd_FirstCube ARGS((DdManager *dd, DdNode *f, int **cube, CUDD_VALUE_TYPE *value)); -EXTERN int Cudd_NextCube ARGS((DdGen *gen, int **cube, CUDD_VALUE_TYPE *value)); -EXTERN DdNode * Cudd_bddComputeCube ARGS((DdManager *dd, DdNode **vars, int *phase, int n)); -EXTERN DdNode * Cudd_addComputeCube ARGS((DdManager *dd, DdNode **vars, int *phase, int n)); -EXTERN DdNode * Cudd_CubeArrayToBdd ARGS((DdManager *dd, int *array)); -EXTERN int Cudd_BddToCubeArray ARGS((DdManager *dd, DdNode *cube, int *array)); -EXTERN DdGen * Cudd_FirstNode ARGS((DdManager *dd, DdNode *f, DdNode **node)); -EXTERN int Cudd_NextNode ARGS((DdGen *gen, DdNode **node)); -EXTERN int Cudd_GenFree ARGS((DdGen *gen)); -EXTERN int Cudd_IsGenEmpty ARGS((DdGen *gen)); -EXTERN DdNode * Cudd_IndicesToCube ARGS((DdManager *dd, int *array, int n)); -EXTERN void Cudd_PrintVersion ARGS((FILE *fp)); -EXTERN double Cudd_AverageDistance ARGS((DdManager *dd)); -EXTERN long Cudd_Random ARGS(()); -EXTERN void Cudd_Srandom ARGS((long seed)); -EXTERN double Cudd_Density ARGS((DdManager *dd, DdNode *f, int nvars)); -EXTERN void Cudd_OutOfMem ARGS((long size)); -EXTERN int Cudd_zddCount ARGS((DdManager *zdd, DdNode *P)); -EXTERN double Cudd_zddCountDouble ARGS((DdManager *zdd, DdNode *P)); -EXTERN DdNode * Cudd_zddProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddUnateProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddWeakDiv ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddDivide ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddWeakDivF ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddDivideF ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * Cudd_zddComplement ARGS((DdManager *dd, DdNode *node)); -EXTERN MtrNode * Cudd_MakeZddTreeNode ARGS((DdManager *dd, unsigned int low, unsigned int size, unsigned int type)); -EXTERN DdNode * Cudd_zddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U, DdNode **zdd_I)); -EXTERN DdNode * Cudd_bddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U)); -EXTERN DdNode * Cudd_MakeBddFromZddCover ARGS((DdManager *dd, DdNode *node)); -EXTERN int Cudd_zddDagSize ARGS((DdNode *p_node)); -EXTERN double Cudd_zddCountMinterm ARGS((DdManager *zdd, DdNode *node, int path)); -EXTERN void Cudd_zddPrintSubtable ARGS((DdManager *table)); -EXTERN DdNode * Cudd_zddPortFromBdd ARGS((DdManager *dd, DdNode *B)); -EXTERN DdNode * Cudd_zddPortToBdd ARGS((DdManager *dd, DdNode *f)); -EXTERN int Cudd_zddReduceHeap ARGS((DdManager *table, Cudd_ReorderingType heuristic, int minsize)); -EXTERN int Cudd_zddShuffleHeap ARGS((DdManager *table, int *permutation)); -EXTERN DdNode * Cudd_zddIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * Cudd_zddUnion ARGS((DdManager *dd, DdNode *P, DdNode *Q)); -EXTERN DdNode * Cudd_zddIntersect ARGS((DdManager *dd, DdNode *P, DdNode *Q)); -EXTERN DdNode * Cudd_zddDiff ARGS((DdManager *dd, DdNode *P, DdNode *Q)); -EXTERN DdNode * Cudd_zddDiffConst ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); -EXTERN DdNode * Cudd_zddSubset1 ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN DdNode * Cudd_zddSubset0 ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN DdNode * Cudd_zddChange ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN void Cudd_zddSymmProfile ARGS((DdManager *table, int lower, int upper)); -EXTERN int Cudd_zddPrintMinterm ARGS((DdManager *zdd, DdNode *node)); -EXTERN int Cudd_zddPrintCover ARGS((DdManager *zdd, DdNode *node)); -EXTERN int Cudd_zddPrintDebug ARGS((DdManager *zdd, DdNode *f, int n, int pr)); -EXTERN DdGen * Cudd_zddFirstPath ARGS((DdManager *zdd, DdNode *f, int **path)); -EXTERN int Cudd_zddNextPath ARGS((DdGen *gen, int **path)); -EXTERN char * Cudd_zddCoverPathToString ARGS((DdManager *zdd, int *path, char *str)); -EXTERN int Cudd_zddDumpDot ARGS((DdManager *dd, int n, DdNode **f, char **inames, char **onames, FILE *fp)); -EXTERN int Cudd_bddSetPiVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetPsVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetNsVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsPiVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsPsVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsNsVar ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetPairIndex ARGS((DdManager *dd, int index, int pairIndex)); -EXTERN int Cudd_bddReadPairIndex ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetVarToBeGrouped ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetVarHardGroup ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddResetVarToBeGrouped ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsVarToBeGrouped ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddSetVarToBeUngrouped ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsVarToBeUngrouped ARGS((DdManager *dd, int index)); -EXTERN int Cudd_bddIsVarHardGroup ARGS((DdManager *dd, int index)); - -/**AutomaticEnd***************************************************************/ - -#endif /* _CUDD */ diff --git a/src/bdd/cudd/cudd.make b/src/bdd/cudd/cudd.make deleted file mode 100644 index 7cb342a2..00000000 --- a/src/bdd/cudd/cudd.make +++ /dev/null @@ -1,42 +0,0 @@ -CSRC += cuddAPI.c cuddAddAbs.c cuddAddApply.c cuddAddFind.c cuddAddIte.c \ - cuddAddInv.c cuddAddNeg.c cuddAddWalsh.c cuddAndAbs.c \ - cuddAnneal.c cuddApa.c cuddApprox.c cuddBddAbs.c cuddBddCorr.c\ - cuddBddIte.c cuddBridge.c cuddCache.c cuddCheck.c cuddClip.c \ - cuddCof.c cuddCompose.c cuddDecomp.c cuddEssent.c cuddExact.c \ - cuddExport.c cuddGenCof.c cuddGenetic.c \ - cuddGroup.c cuddHarwell.c cuddInit.c cuddInteract.c \ - cuddLCache.c cuddLevelQ.c \ - cuddLinear.c cuddLiteral.c cuddMatMult.c cuddPriority.c \ - cuddRead.c cuddRef.c cuddReorder.c cuddSat.c cuddSign.c \ - cuddSolve.c cuddSplit.c cuddSubsetHB.c cuddSubsetSP.c cuddSymmetry.c \ - cuddTable.c cuddUtil.c cuddWindow.c cuddZddCount.c cuddZddFuncs.c \ - cuddZddGroup.c cuddZddIsop.c cuddZddLin.c cuddZddMisc.c cuddZddPort.c \ - cuddZddReord.c cuddZddSetop.c cuddZddSymm.c cuddZddUtil.c - -HEADERS += cudd.h cuddInt.h -MISC += testcudd.c r7x8.1.mat doc/cudd.ps doc/cuddAllAbs.html doc/cuddAllDet.html \ - doc/cuddExtAbs.html doc/cuddExtDet.html doc/cuddIntro.css \ - doc/cuddIntro.html doc/footnode.html doc/img1.gif doc/img2.gif \ - doc/img3.gif doc/img4.gif doc/img5.gif doc/index.html \ - doc/node1.html doc/node2.html doc/node3.html doc/node4.html \ - doc/node5.html doc/node6.html doc/node7.html doc/node8.html \ - doc/icons/change_begin.gif \ - doc/icons/change_delete.gif \ - doc/icons/change_end.gif \ - doc/icons/contents_motif.gif \ - doc/icons/cross_ref_motif.gif \ - doc/icons/foot_motif.gif \ - doc/icons/image.gif \ - doc/icons/index_motif.gif \ - doc/icons/next_group_motif.gif \ - doc/icons/next_group_motif_gr.gif \ - doc/icons/next_motif.gif \ - doc/icons/next_motif_gr.gif \ - doc/icons/previous_group_motif.gif \ - doc/icons/previous_group_motif_gr.gif \ - doc/icons/previous_motif.gif \ - doc/icons/previous_motif_gr.gif \ - doc/icons/up_motif.gif \ - doc/icons/up_motif_gr.gif - -DEPENDENCYFILES = $(CSRC) diff --git a/src/bdd/cudd/cuddAPI.c b/src/bdd/cudd/cuddAPI.c deleted file mode 100644 index a16b82cf..00000000 --- a/src/bdd/cudd/cuddAPI.c +++ /dev/null @@ -1,4409 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAPI.c] - - PackageName [cudd] - - Synopsis [Application interface functions.] - - Description [External procedures included in this module: -

          -
        • Cudd_addNewVar() -
        • Cudd_addNewVarAtLevel() -
        • Cudd_bddNewVar() -
        • Cudd_bddNewVarAtLevel() -
        • Cudd_addIthVar() -
        • Cudd_bddIthVar() -
        • Cudd_zddIthVar() -
        • Cudd_zddVarsFromBddVars() -
        • Cudd_addConst() -
        • Cudd_IsNonConstant() -
        • Cudd_AutodynEnable() -
        • Cudd_AutodynDisable() -
        • Cudd_ReorderingStatus() -
        • Cudd_AutodynEnableZdd() -
        • Cudd_AutodynDisableZdd() -
        • Cudd_ReorderingStatusZdd() -
        • Cudd_zddRealignmentEnabled() -
        • Cudd_zddRealignEnable() -
        • Cudd_zddRealignDisable() -
        • Cudd_bddRealignmentEnabled() -
        • Cudd_bddRealignEnable() -
        • Cudd_bddRealignDisable() -
        • Cudd_ReadOne() -
        • Cudd_ReadZddOne() -
        • Cudd_ReadZero() -
        • Cudd_ReadLogicZero() -
        • Cudd_ReadPlusInfinity() -
        • Cudd_ReadMinusInfinity() -
        • Cudd_ReadBackground() -
        • Cudd_SetBackground() -
        • Cudd_ReadCacheSlots() -
        • Cudd_ReadCacheUsedSlots() -
        • Cudd_ReadCacheLookUps() -
        • Cudd_ReadCacheHits() -
        • Cudd_ReadMinHit() -
        • Cudd_SetMinHit() -
        • Cudd_ReadLooseUpTo() -
        • Cudd_SetLooseUpTo() -
        • Cudd_ReadMaxCache() -
        • Cudd_ReadMaxCacheHard() -
        • Cudd_SetMaxCacheHard() -
        • Cudd_ReadSize() -
        • Cudd_ReadSlots() -
        • Cudd_ReadUsedSlots() -
        • Cudd_ExpectedUsedSlots() -
        • Cudd_ReadKeys() -
        • Cudd_ReadDead() -
        • Cudd_ReadMinDead() -
        • Cudd_ReadReorderings() -
        • Cudd_ReadReorderingTime() -
        • Cudd_ReadGarbageCollections() -
        • Cudd_ReadGarbageCollectionTime() -
        • Cudd_ReadNodesFreed() -
        • Cudd_ReadNodesDropped() -
        • Cudd_ReadUniqueLookUps() -
        • Cudd_ReadUniqueLinks() -
        • Cudd_ReadSiftMaxVar() -
        • Cudd_SetSiftMaxVar() -
        • Cudd_ReadMaxGrowth() -
        • Cudd_SetMaxGrowth() -
        • Cudd_ReadMaxGrowthAlternate() -
        • Cudd_SetMaxGrowthAlternate() -
        • Cudd_ReadReorderingCycle() -
        • Cudd_SetReorderingCycle() -
        • Cudd_ReadTree() -
        • Cudd_SetTree() -
        • Cudd_FreeTree() -
        • Cudd_ReadZddTree() -
        • Cudd_SetZddTree() -
        • Cudd_FreeZddTree() -
        • Cudd_NodeReadIndex() -
        • Cudd_ReadPerm() -
        • Cudd_ReadInvPerm() -
        • Cudd_ReadVars() -
        • Cudd_ReadEpsilon() -
        • Cudd_SetEpsilon() -
        • Cudd_ReadGroupCheck() -
        • Cudd_SetGroupcheck() -
        • Cudd_GarbageCollectionEnabled() -
        • Cudd_EnableGarbageCollection() -
        • Cudd_DisableGarbageCollection() -
        • Cudd_DeadAreCounted() -
        • Cudd_TurnOnCountDead() -
        • Cudd_TurnOffCountDead() -
        • Cudd_ReadRecomb() -
        • Cudd_SetRecomb() -
        • Cudd_ReadSymmviolation() -
        • Cudd_SetSymmviolation() -
        • Cudd_ReadArcviolation() -
        • Cudd_SetArcviolation() -
        • Cudd_ReadPopulationSize() -
        • Cudd_SetPopulationSize() -
        • Cudd_ReadNumberXovers() -
        • Cudd_SetNumberXovers() -
        • Cudd_ReadMemoryInUse() -
        • Cudd_PrintInfo() -
        • Cudd_ReadPeakNodeCount() -
        • Cudd_ReadPeakLiveNodeCount() -
        • Cudd_ReadNodeCount() -
        • Cudd_zddReadNodeCount() -
        • Cudd_AddHook() -
        • Cudd_RemoveHook() -
        • Cudd_IsInHook() -
        • Cudd_StdPreReordHook() -
        • Cudd_StdPostReordHook() -
        • Cudd_EnableReorderingReporting() -
        • Cudd_DisableReorderingReporting() -
        • Cudd_ReorderingReporting() -
        • Cudd_ReadErrorCode() -
        • Cudd_ClearErrorCode() -
        • Cudd_ReadStdout() -
        • Cudd_SetStdout() -
        • Cudd_ReadStderr() -
        • Cudd_SetStderr() -
        • Cudd_ReadNextReordering() -
        • Cudd_SetNextReordering() -
        • Cudd_ReadSwapSteps() -
        • Cudd_ReadMaxLive() -
        • Cudd_SetMaxLive() -
        • Cudd_ReadMaxMemory() -
        • Cudd_SetMaxMemory() -
        • Cudd_bddBindVar() -
        • Cudd_bddUnbindVar() -
        • Cudd_bddVarIsBound() -
        • Cudd_bddSetPiVar() -
        • Cudd_bddSetPsVar() -
        • Cudd_bddSetNsVar() -
        • Cudd_bddIsPiVar() -
        • Cudd_bddIsPsVar() -
        • Cudd_bddIsNsVar() -
        • Cudd_bddSetPairIndex() -
        • Cudd_bddReadPairIndex() -
        • Cudd_bddSetVarToBeGrouped() -
        • Cudd_bddSetVarHardGroup() -
        • Cudd_bddResetVarToBeGrouped() -
        • Cudd_bddIsVarToBeGrouped() -
        • Cudd_bddSetVarToBeUngrouped() -
        • Cudd_bddIsVarToBeUngrouped() -
        • Cudd_bddIsVarHardGroup() -
        - Static procedures included in this module: -
          -
        • fixVarTree() -
        ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAPI.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void fixVarTree ARGS((MtrNode *treenode, int *perm, int size)); -static int addMultiplicityGroups ARGS((DdManager *dd, MtrNode *treenode, int multiplicity, char *vmask, char *lmask)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Returns a new ADD variable.] - - Description [Creates a new ADD variable. The new variable has an - index equal to the largest previous index plus 1. Returns a - pointer to the new variable if successful; NULL otherwise. - An ADD variable differs from a BDD variable because it points to the - arithmetic zero, instead of having a complement pointer to 1. ] - - SideEffects [None] - - SeeAlso [Cudd_bddNewVar Cudd_addIthVar Cudd_addConst - Cudd_addNewVarAtLevel] - -******************************************************************************/ -DdNode * -Cudd_addNewVar( - DdManager * dd) -{ - DdNode *res; - - if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); - do { - dd->reordered = 0; - res = cuddUniqueInter(dd,dd->size,DD_ONE(dd),DD_ZERO(dd)); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_addNewVar */ - - -/**Function******************************************************************** - - Synopsis [Returns a new ADD variable at a specified level.] - - Description [Creates a new ADD variable. The new variable has an - index equal to the largest previous index plus 1 and is positioned at - the specified level in the order. Returns a pointer to the new - variable if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel] - -******************************************************************************/ -DdNode * -Cudd_addNewVarAtLevel( - DdManager * dd, - int level) -{ - DdNode *res; - - if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); - if (level >= dd->size) return(Cudd_addIthVar(dd,level)); - if (!cuddInsertSubtables(dd,1,level)) return(NULL); - do { - dd->reordered = 0; - res = cuddUniqueInter(dd,dd->size - 1,DD_ONE(dd),DD_ZERO(dd)); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_addNewVarAtLevel */ - - -/**Function******************************************************************** - - Synopsis [Returns a new BDD variable.] - - Description [Creates a new BDD variable. The new variable has an - index equal to the largest previous index plus 1. Returns a - pointer to the new variable if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel] - -******************************************************************************/ -DdNode * -Cudd_bddNewVar( - DdManager * dd) -{ - DdNode *res; - - if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); - res = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one)); - - return(res); - -} /* end of Cudd_bddNewVar */ - - -/**Function******************************************************************** - - Synopsis [Returns a new BDD variable at a specified level.] - - Description [Creates a new BDD variable. The new variable has an - index equal to the largest previous index plus 1 and is positioned at - the specified level in the order. Returns a pointer to the new - variable if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddNewVar Cudd_bddIthVar Cudd_addNewVarAtLevel] - -******************************************************************************/ -DdNode * -Cudd_bddNewVarAtLevel( - DdManager * dd, - int level) -{ - DdNode *res; - - if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) return(NULL); - if (level >= dd->size) return(Cudd_bddIthVar(dd,level)); - if (!cuddInsertSubtables(dd,1,level)) return(NULL); - res = dd->vars[dd->size - 1]; - - return(res); - -} /* end of Cudd_bddNewVarAtLevel */ - - -/**Function******************************************************************** - - Synopsis [Returns the ADD variable with index i.] - - Description [Retrieves the ADD variable with index i if it already - exists, or creates a new ADD variable. Returns a pointer to the - variable if successful; NULL otherwise. An ADD variable differs from - a BDD variable because it points to the arithmetic zero, instead of - having a complement pointer to 1. ] - - SideEffects [None] - - SeeAlso [Cudd_addNewVar Cudd_bddIthVar Cudd_addConst - Cudd_addNewVarAtLevel] - -******************************************************************************/ -DdNode * -Cudd_addIthVar( - DdManager * dd, - int i) -{ - DdNode *res; - - if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); - do { - dd->reordered = 0; - res = cuddUniqueInter(dd,i,DD_ONE(dd),DD_ZERO(dd)); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_addIthVar */ - - -/**Function******************************************************************** - - Synopsis [Returns the BDD variable with index i.] - - Description [Retrieves the BDD variable with index i if it already - exists, or creates a new BDD variable. Returns a pointer to the - variable if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel - Cudd_ReadVars] - -******************************************************************************/ -DdNode * -Cudd_bddIthVar( - DdManager * dd, - int i) -{ - DdNode *res; - - if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); - if (i < dd->size) { - res = dd->vars[i]; - } else { - res = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); - } - - return(res); - -} /* end of Cudd_bddIthVar */ - - -/**Function******************************************************************** - - Synopsis [Returns the ZDD variable with index i.] - - Description [Retrieves the ZDD variable with index i if it already - exists, or creates a new ZDD variable. Returns a pointer to the - variable if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddIthVar Cudd_addIthVar] - -******************************************************************************/ -DdNode * -Cudd_zddIthVar( - DdManager * dd, - int i) -{ - DdNode *res; - DdNode *zvar; - DdNode *lower; - int j; - - if ((unsigned int) i >= CUDD_MAXINDEX - 1) return(NULL); - - /* The i-th variable function has the following structure: - ** at the level corresponding to index i there is a node whose "then" - ** child points to the universe, and whose "else" child points to zero. - ** Above that level there are nodes with identical children. - */ - - /* First we build the node at the level of index i. */ - lower = (i < dd->sizeZ - 1) ? dd->univ[dd->permZ[i]+1] : DD_ONE(dd); - do { - dd->reordered = 0; - zvar = cuddUniqueInterZdd(dd, i, lower, DD_ZERO(dd)); - } while (dd->reordered == 1); - - if (zvar == NULL) - return(NULL); - cuddRef(zvar); - - /* Now we add the "filler" nodes above the level of index i. */ - for (j = dd->permZ[i] - 1; j >= 0; j--) { - do { - dd->reordered = 0; - res = cuddUniqueInterZdd(dd, dd->invpermZ[j], zvar, zvar); - } while (dd->reordered == 1); - if (res == NULL) { - Cudd_RecursiveDerefZdd(dd,zvar); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDerefZdd(dd,zvar); - zvar = res; - } - cuddDeref(zvar); - return(zvar); - -} /* end of Cudd_zddIthVar */ - - -/**Function******************************************************************** - - Synopsis [Creates one or more ZDD variables for each BDD variable.] - - Description [Creates one or more ZDD variables for each BDD - variable. If some ZDD variables already exist, only the missing - variables are created. Parameter multiplicity allows the caller to - control how many variables are created for each BDD variable in - existence. For instance, if ZDDs are used to represent covers, two - ZDD variables are required for each BDD variable. The order of the - BDD variables is transferred to the ZDD variables. If a variable - group tree exists for the BDD variables, a corresponding ZDD - variable group tree is created by expanding the BDD variable - tree. In any case, the ZDD variables derived from the same BDD - variable are merged in a ZDD variable group. If a ZDD variable group - tree exists, it is freed. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel] - -******************************************************************************/ -int -Cudd_zddVarsFromBddVars( - DdManager * dd /* DD manager */, - int multiplicity /* how many ZDD variables are created for each BDD variable */) -{ - int res; - int i, j; - int allnew; - int *permutation; - - if (multiplicity < 1) return(0); - allnew = dd->sizeZ == 0; - if (dd->size * multiplicity > dd->sizeZ) { - res = cuddResizeTableZdd(dd,dd->size * multiplicity - 1); - if (res == 0) return(0); - } - /* Impose the order of the BDD variables to the ZDD variables. */ - if (allnew) { - for (i = 0; i < dd->size; i++) { - for (j = 0; j < multiplicity; j++) { - dd->permZ[i * multiplicity + j] = - dd->perm[i] * multiplicity + j; - dd->invpermZ[dd->permZ[i * multiplicity + j]] = - i * multiplicity + j; - } - } - for (i = 0; i < dd->sizeZ; i++) { - dd->univ[i]->index = dd->invpermZ[i]; - } - } else { - permutation = ALLOC(int,dd->sizeZ); - if (permutation == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < dd->size; i++) { - for (j = 0; j < multiplicity; j++) { - permutation[i * multiplicity + j] = - dd->invperm[i] * multiplicity + j; - } - } - for (i = dd->size * multiplicity; i < dd->sizeZ; i++) { - permutation[i] = i; - } - res = Cudd_zddShuffleHeap(dd, permutation); - FREE(permutation); - if (res == 0) return(0); - } - /* Copy and expand the variable group tree if it exists. */ - if (dd->treeZ != NULL) { - Cudd_FreeZddTree(dd); - } - if (dd->tree != NULL) { - dd->treeZ = Mtr_CopyTree(dd->tree, multiplicity); - if (dd->treeZ == NULL) return(0); - } else if (multiplicity > 1) { - dd->treeZ = Mtr_InitGroupTree(0, dd->sizeZ); - if (dd->treeZ == NULL) return(0); - dd->treeZ->index = dd->invpermZ[0]; - } - /* Create groups for the ZDD variables derived from the same BDD variable. - */ - if (multiplicity > 1) { - char *vmask, *lmask; - - vmask = ALLOC(char, dd->size); - if (vmask == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - lmask = ALLOC(char, dd->size); - if (lmask == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < dd->size; i++) { - vmask[i] = lmask[i] = 0; - } - res = addMultiplicityGroups(dd,dd->treeZ,multiplicity,vmask,lmask); - FREE(vmask); - FREE(lmask); - if (res == 0) return(0); - } - return(1); - -} /* end of Cudd_zddVarsFromBddVars */ - - -/**Function******************************************************************** - - Synopsis [Returns the ADD for constant c.] - - Description [Retrieves the ADD for constant c if it already - exists, or creates a new ADD. Returns a pointer to the - ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addNewVar Cudd_addIthVar] - -******************************************************************************/ -DdNode * -Cudd_addConst( - DdManager * dd, - CUDD_VALUE_TYPE c) -{ - return(cuddUniqueConst(dd,c)); - -} /* end of Cudd_addConst */ - - -/**Function******************************************************************** - - Synopsis [Returns 1 if a DD node is not constant.] - - Description [Returns 1 if a DD node is not constant. This function is - useful to test the results of Cudd_bddIteConstant, Cudd_addIteConstant, - Cudd_addEvalConst. These results may be a special value signifying - non-constant. In the other cases the macro Cudd_IsConstant can be used.] - - SideEffects [None] - - SeeAlso [Cudd_IsConstant Cudd_bddIteConstant Cudd_addIteConstant - Cudd_addEvalConst] - -******************************************************************************/ -int -Cudd_IsNonConstant( - DdNode *f) -{ - return(f == DD_NON_CONSTANT || !Cudd_IsConstant(f)); - -} /* end of Cudd_IsNonConstant */ - - -/**Function******************************************************************** - - Synopsis [Enables automatic dynamic reordering of BDDs and ADDs.] - - Description [Enables automatic dynamic reordering of BDDs and - ADDs. Parameter method is used to determine the method used for - reordering. If CUDD_REORDER_SAME is passed, the method is - unchanged.] - - SideEffects [None] - - SeeAlso [Cudd_AutodynDisable Cudd_ReorderingStatus - Cudd_AutodynEnableZdd] - -******************************************************************************/ -void -Cudd_AutodynEnable( - DdManager * unique, - Cudd_ReorderingType method) -{ - unique->autoDyn = 1; - if (method != CUDD_REORDER_SAME) { - unique->autoMethod = method; - } -#ifndef DD_NO_DEATH_ROW - /* If reordering is enabled, using the death row causes too many - ** invocations. Hence, we shrink the death row to just one entry. - */ - cuddClearDeathRow(unique); - unique->deathRowDepth = 1; - unique->deadMask = unique->deathRowDepth - 1; - if ((unsigned) unique->nextDead > unique->deadMask) { - unique->nextDead = 0; - } - unique->deathRow = REALLOC(DdNodePtr, unique->deathRow, - unique->deathRowDepth); -#endif - return; - -} /* end of Cudd_AutodynEnable */ - - -/**Function******************************************************************** - - Synopsis [Disables automatic dynamic reordering.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_AutodynEnable Cudd_ReorderingStatus - Cudd_AutodynDisableZdd] - -******************************************************************************/ -void -Cudd_AutodynDisable( - DdManager * unique) -{ - unique->autoDyn = 0; - return; - -} /* end of Cudd_AutodynDisable */ - - -/**Function******************************************************************** - - Synopsis [Reports the status of automatic dynamic reordering of BDDs - and ADDs.] - - Description [Reports the status of automatic dynamic reordering of - BDDs and ADDs. Parameter method is set to the reordering method - currently selected. Returns 1 if automatic reordering is enabled; 0 - otherwise.] - - SideEffects [Parameter method is set to the reordering method currently - selected.] - - SeeAlso [Cudd_AutodynEnable Cudd_AutodynDisable - Cudd_ReorderingStatusZdd] - -******************************************************************************/ -int -Cudd_ReorderingStatus( - DdManager * unique, - Cudd_ReorderingType * method) -{ - *method = unique->autoMethod; - return(unique->autoDyn); - -} /* end of Cudd_ReorderingStatus */ - - -/**Function******************************************************************** - - Synopsis [Enables automatic dynamic reordering of ZDDs.] - - Description [Enables automatic dynamic reordering of ZDDs. Parameter - method is used to determine the method used for reordering ZDDs. If - CUDD_REORDER_SAME is passed, the method is unchanged.] - - SideEffects [None] - - SeeAlso [Cudd_AutodynDisableZdd Cudd_ReorderingStatusZdd - Cudd_AutodynEnable] - -******************************************************************************/ -void -Cudd_AutodynEnableZdd( - DdManager * unique, - Cudd_ReorderingType method) -{ - unique->autoDynZ = 1; - if (method != CUDD_REORDER_SAME) { - unique->autoMethodZ = method; - } - return; - -} /* end of Cudd_AutodynEnableZdd */ - - -/**Function******************************************************************** - - Synopsis [Disables automatic dynamic reordering of ZDDs.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_AutodynEnableZdd Cudd_ReorderingStatusZdd - Cudd_AutodynDisable] - -******************************************************************************/ -void -Cudd_AutodynDisableZdd( - DdManager * unique) -{ - unique->autoDynZ = 0; - return; - -} /* end of Cudd_AutodynDisableZdd */ - - -/**Function******************************************************************** - - Synopsis [Reports the status of automatic dynamic reordering of ZDDs.] - - Description [Reports the status of automatic dynamic reordering of - ZDDs. Parameter method is set to the ZDD reordering method currently - selected. Returns 1 if automatic reordering is enabled; 0 - otherwise.] - - SideEffects [Parameter method is set to the ZDD reordering method currently - selected.] - - SeeAlso [Cudd_AutodynEnableZdd Cudd_AutodynDisableZdd - Cudd_ReorderingStatus] - -******************************************************************************/ -int -Cudd_ReorderingStatusZdd( - DdManager * unique, - Cudd_ReorderingType * method) -{ - *method = unique->autoMethodZ; - return(unique->autoDynZ); - -} /* end of Cudd_ReorderingStatusZdd */ - - -/**Function******************************************************************** - - Synopsis [Tells whether the realignment of ZDD order to BDD order is - enabled.] - - Description [Returns 1 if the realignment of ZDD order to BDD order is - enabled; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddRealignEnable Cudd_zddRealignDisable - Cudd_bddRealignEnable Cudd_bddRealignDisable] - -******************************************************************************/ -int -Cudd_zddRealignmentEnabled( - DdManager * unique) -{ - return(unique->realign); - -} /* end of Cudd_zddRealignmentEnabled */ - - -/**Function******************************************************************** - - Synopsis [Enables realignment of ZDD order to BDD order.] - - Description [Enables realignment of the ZDD variable order to the - BDD variable order after the BDDs and ADDs have been reordered. The - number of ZDD variables must be a multiple of the number of BDD - variables for realignment to make sense. If this condition is not met, - Cudd_ReduceHeap will return 0. Let M be the - ratio of the two numbers. For the purpose of realignment, the ZDD - variables from M*i to (M+1)*i-1 are - reagarded as corresponding to BDD variable i. Realignment - is initially disabled.] - - SideEffects [None] - - SeeAlso [Cudd_ReduceHeap Cudd_zddRealignDisable - Cudd_zddRealignmentEnabled Cudd_bddRealignDisable - Cudd_bddRealignmentEnabled] - -******************************************************************************/ -void -Cudd_zddRealignEnable( - DdManager * unique) -{ - unique->realign = 1; - return; - -} /* end of Cudd_zddRealignEnable */ - - -/**Function******************************************************************** - - Synopsis [Disables realignment of ZDD order to BDD order.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddRealignEnable Cudd_zddRealignmentEnabled - Cudd_bddRealignEnable Cudd_bddRealignmentEnabled] - -******************************************************************************/ -void -Cudd_zddRealignDisable( - DdManager * unique) -{ - unique->realign = 0; - return; - -} /* end of Cudd_zddRealignDisable */ - - -/**Function******************************************************************** - - Synopsis [Tells whether the realignment of BDD order to ZDD order is - enabled.] - - Description [Returns 1 if the realignment of BDD order to ZDD order is - enabled; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddRealignEnable Cudd_bddRealignDisable - Cudd_zddRealignEnable Cudd_zddRealignDisable] - -******************************************************************************/ -int -Cudd_bddRealignmentEnabled( - DdManager * unique) -{ - return(unique->realignZ); - -} /* end of Cudd_bddRealignmentEnabled */ - - -/**Function******************************************************************** - - Synopsis [Enables realignment of BDD order to ZDD order.] - - Description [Enables realignment of the BDD variable order to the - ZDD variable order after the ZDDs have been reordered. The - number of ZDD variables must be a multiple of the number of BDD - variables for realignment to make sense. If this condition is not met, - Cudd_zddReduceHeap will return 0. Let M be the - ratio of the two numbers. For the purpose of realignment, the ZDD - variables from M*i to (M+1)*i-1 are - reagarded as corresponding to BDD variable i. Realignment - is initially disabled.] - - SideEffects [None] - - SeeAlso [Cudd_zddReduceHeap Cudd_bddRealignDisable - Cudd_bddRealignmentEnabled Cudd_zddRealignDisable - Cudd_zddRealignmentEnabled] - -******************************************************************************/ -void -Cudd_bddRealignEnable( - DdManager * unique) -{ - unique->realignZ = 1; - return; - -} /* end of Cudd_bddRealignEnable */ - - -/**Function******************************************************************** - - Synopsis [Disables realignment of ZDD order to BDD order.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_bddRealignEnable Cudd_bddRealignmentEnabled - Cudd_zddRealignEnable Cudd_zddRealignmentEnabled] - -******************************************************************************/ -void -Cudd_bddRealignDisable( - DdManager * unique) -{ - unique->realignZ = 0; - return; - -} /* end of Cudd_bddRealignDisable */ - - -/**Function******************************************************************** - - Synopsis [Returns the one constant of the manager.] - - Description [Returns the one constant of the manager. The one - constant is common to ADDs and BDDs.] - - SideEffects [None] - - SeeAlso [Cudd_ReadZero Cudd_ReadLogicZero Cudd_ReadZddOne] - -******************************************************************************/ -DdNode * -Cudd_ReadOne( - DdManager * dd) -{ - return(dd->one); - -} /* end of Cudd_ReadOne */ - - -/**Function******************************************************************** - - Synopsis [Returns the ZDD for the constant 1 function.] - - Description [Returns the ZDD for the constant 1 function. - The representation of the constant 1 function as a ZDD depends on - how many variables it (nominally) depends on. The index of the - topmost variable in the support is given as argument i.] - - SideEffects [None] - - SeeAlso [Cudd_ReadOne] - -******************************************************************************/ -DdNode * -Cudd_ReadZddOne( - DdManager * dd, - int i) -{ - if (i < 0) - return(NULL); - return(i < dd->sizeZ ? dd->univ[i] : DD_ONE(dd)); - -} /* end of Cudd_ReadZddOne */ - - - -/**Function******************************************************************** - - Synopsis [Returns the zero constant of the manager.] - - Description [Returns the zero constant of the manager. The zero - constant is the arithmetic zero, rather than the logic zero. The - latter is the complement of the one constant.] - - SideEffects [None] - - SeeAlso [Cudd_ReadOne Cudd_ReadLogicZero] - -******************************************************************************/ -DdNode * -Cudd_ReadZero( - DdManager * dd) -{ - return(DD_ZERO(dd)); - -} /* end of Cudd_ReadZero */ - - -/**Function******************************************************************** - - Synopsis [Returns the logic zero constant of the manager.] - - Description [Returns the zero constant of the manager. The logic zero - constant is the complement of the one constant, and is distinct from - the arithmetic zero.] - - SideEffects [None] - - SeeAlso [Cudd_ReadOne Cudd_ReadZero] - -******************************************************************************/ -DdNode * -Cudd_ReadLogicZero( - DdManager * dd) -{ - return(Cudd_Not(DD_ONE(dd))); - -} /* end of Cudd_ReadLogicZero */ - - -/**Function******************************************************************** - - Synopsis [Reads the plus-infinity constant from the manager.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_ReadPlusInfinity( - DdManager * dd) -{ - return(dd->plusinfinity); - -} /* end of Cudd_ReadPlusInfinity */ - - -/**Function******************************************************************** - - Synopsis [Reads the minus-infinity constant from the manager.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_ReadMinusInfinity( - DdManager * dd) -{ - return(dd->minusinfinity); - -} /* end of Cudd_ReadMinusInfinity */ - - -/**Function******************************************************************** - - Synopsis [Reads the background constant of the manager.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_ReadBackground( - DdManager * dd) -{ - return(dd->background); - -} /* end of Cudd_ReadBackground */ - - -/**Function******************************************************************** - - Synopsis [Sets the background constant of the manager.] - - Description [Sets the background constant of the manager. It assumes - that the DdNode pointer bck is already referenced.] - - SideEffects [None] - -******************************************************************************/ -void -Cudd_SetBackground( - DdManager * dd, - DdNode * bck) -{ - dd->background = bck; - -} /* end of Cudd_SetBackground */ - - -/**Function******************************************************************** - - Synopsis [Reads the number of slots in the cache.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadCacheUsedSlots] - -******************************************************************************/ -unsigned int -Cudd_ReadCacheSlots( - DdManager * dd) -{ - return(dd->cacheSlots); - -} /* end of Cudd_ReadCacheSlots */ - - -/**Function******************************************************************** - - Synopsis [Reads the fraction of used slots in the cache.] - - Description [Reads the fraction of used slots in the cache. The unused - slots are those in which no valid data is stored. Garbage collection, - variable reordering, and cache resizing may cause used slots to become - unused.] - - SideEffects [None] - - SeeAlso [Cudd_ReadCacheSlots] - -******************************************************************************/ -double -Cudd_ReadCacheUsedSlots( - DdManager * dd) -{ - unsigned long used = 0; - int slots = dd->cacheSlots; - DdCache *cache = dd->cache; - int i; - - for (i = 0; i < slots; i++) { - used += cache[i].h != 0; - } - - return((double)used / (double) dd->cacheSlots); - -} /* end of Cudd_ReadCacheUsedSlots */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of cache look-ups.] - - Description [Returns the number of cache look-ups.] - - SideEffects [None] - - SeeAlso [Cudd_ReadCacheHits] - -******************************************************************************/ -double -Cudd_ReadCacheLookUps( - DdManager * dd) -{ - return(dd->cacheHits + dd->cacheMisses + - dd->totCachehits + dd->totCacheMisses); - -} /* end of Cudd_ReadCacheLookUps */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of cache hits.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadCacheLookUps] - -******************************************************************************/ -double -Cudd_ReadCacheHits( - DdManager * dd) -{ - return(dd->cacheHits + dd->totCachehits); - -} /* end of Cudd_ReadCacheHits */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of recursive calls.] - - Description [Returns the number of recursive calls if the package is - compiled with DD_COUNT defined.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -double -Cudd_ReadRecursiveCalls( - DdManager * dd) -{ -#ifdef DD_COUNT - return(dd->recursiveCalls); -#else - return(-1.0); -#endif - -} /* end of Cudd_ReadRecursiveCalls */ - - - -/**Function******************************************************************** - - Synopsis [Reads the hit rate that causes resizinig of the computed - table.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetMinHit] - -******************************************************************************/ -unsigned int -Cudd_ReadMinHit( - DdManager * dd) -{ - /* Internally, the package manipulates the ratio of hits to - ** misses instead of the ratio of hits to accesses. */ - return((unsigned int) (0.5 + 100 * dd->minHit / (1 + dd->minHit))); - -} /* end of Cudd_ReadMinHit */ - - -/**Function******************************************************************** - - Synopsis [Sets the hit rate that causes resizinig of the computed - table.] - - Description [Sets the minHit parameter of the manager. This - parameter controls the resizing of the computed table. If the hit - rate is larger than the specified value, and the cache is not - already too large, then its size is doubled.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMinHit] - -******************************************************************************/ -void -Cudd_SetMinHit( - DdManager * dd, - unsigned int hr) -{ - /* Internally, the package manipulates the ratio of hits to - ** misses instead of the ratio of hits to accesses. */ - dd->minHit = (double) hr / (100.0 - (double) hr); - -} /* end of Cudd_SetMinHit */ - - -/**Function******************************************************************** - - Synopsis [Reads the looseUpTo parameter of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetLooseUpTo Cudd_ReadMinHit Cudd_ReadMinDead] - -******************************************************************************/ -unsigned int -Cudd_ReadLooseUpTo( - DdManager * dd) -{ - return(dd->looseUpTo); - -} /* end of Cudd_ReadLooseUpTo */ - - -/**Function******************************************************************** - - Synopsis [Sets the looseUpTo parameter of the manager.] - - Description [Sets the looseUpTo parameter of the manager. This - parameter of the manager controls the threshold beyond which no fast - growth of the unique table is allowed. The threshold is given as a - number of slots. If the value passed to this function is 0, the - function determines a suitable value based on the available memory.] - - SideEffects [None] - - SeeAlso [Cudd_ReadLooseUpTo Cudd_SetMinHit] - -******************************************************************************/ -void -Cudd_SetLooseUpTo( - DdManager * dd, - unsigned int lut) -{ - if (lut == 0) { - long datalimit = getSoftDataLimit(); - lut = (unsigned int) (datalimit / (sizeof(DdNode) * - DD_MAX_LOOSE_FRACTION)); - } - dd->looseUpTo = lut; - -} /* end of Cudd_SetLooseUpTo */ - - -/**Function******************************************************************** - - Synopsis [Returns the soft limit for the cache size.] - - Description [Returns the soft limit for the cache size. The soft limit] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxCache] - -******************************************************************************/ -unsigned int -Cudd_ReadMaxCache( - DdManager * dd) -{ - return(2 * dd->cacheSlots + dd->cacheSlack); - -} /* end of Cudd_ReadMaxCache */ - - -/**Function******************************************************************** - - Synopsis [Reads the maxCacheHard parameter of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetMaxCacheHard Cudd_ReadMaxCache] - -******************************************************************************/ -unsigned int -Cudd_ReadMaxCacheHard( - DdManager * dd) -{ - return(dd->maxCacheHard); - -} /* end of Cudd_ReadMaxCache */ - - -/**Function******************************************************************** - - Synopsis [Sets the maxCacheHard parameter of the manager.] - - Description [Sets the maxCacheHard parameter of the manager. The - cache cannot grow larger than maxCacheHard entries. This parameter - allows an application to control the trade-off of memory versus - speed. If the value passed to this function is 0, the function - determines a suitable maximum cache size based on the available memory.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxCacheHard Cudd_SetMaxCache] - -******************************************************************************/ -void -Cudd_SetMaxCacheHard( - DdManager * dd, - unsigned int mc) -{ - if (mc == 0) { - long datalimit = getSoftDataLimit(); - mc = (unsigned int) (datalimit / (sizeof(DdCache) * - DD_MAX_CACHE_FRACTION)); - } - dd->maxCacheHard = mc; - -} /* end of Cudd_SetMaxCacheHard */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of BDD variables in existance.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadZddSize] - -******************************************************************************/ -int -Cudd_ReadSize( - DdManager * dd) -{ - return(dd->size); - -} /* end of Cudd_ReadSize */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of ZDD variables in existance.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadSize] - -******************************************************************************/ -int -Cudd_ReadZddSize( - DdManager * dd) -{ - return(dd->sizeZ); - -} /* end of Cudd_ReadZddSize */ - - -/**Function******************************************************************** - - Synopsis [Returns the total number of slots of the unique table.] - - Description [Returns the total number of slots of the unique table. - This number ismainly for diagnostic purposes.] - - SideEffects [None] - -******************************************************************************/ -unsigned int -Cudd_ReadSlots( - DdManager * dd) -{ - return(dd->slots); - -} /* end of Cudd_ReadSlots */ - - -/**Function******************************************************************** - - Synopsis [Reads the fraction of used slots in the unique table.] - - Description [Reads the fraction of used slots in the unique - table. The unused slots are those in which no valid data is - stored. Garbage collection, variable reordering, and subtable - resizing may cause used slots to become unused.] - - SideEffects [None] - - SeeAlso [Cudd_ReadSlots] - -******************************************************************************/ -double -Cudd_ReadUsedSlots( - DdManager * dd) -{ - unsigned long used = 0; - int i, j; - int size = dd->size; - DdNodePtr *nodelist; - DdSubtable *subtable; - DdNode *node; - DdNode *sentinel = &(dd->sentinel); - - /* Scan each BDD/ADD subtable. */ - for (i = 0; i < size; i++) { - subtable = &(dd->subtables[i]); - nodelist = subtable->nodelist; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - if (node != sentinel) { - used++; - } - } - } - - /* Scan the ZDD subtables. */ - size = dd->sizeZ; - - for (i = 0; i < size; i++) { - subtable = &(dd->subtableZ[i]); - nodelist = subtable->nodelist; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - if (node != NULL) { - used++; - } - } - } - - /* Constant table. */ - subtable = &(dd->constants); - nodelist = subtable->nodelist; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - if (node != NULL) { - used++; - } - } - - return((double)used / (double) dd->slots); - -} /* end of Cudd_ReadUsedSlots */ - - -/**Function******************************************************************** - - Synopsis [Computes the expected fraction of used slots in the unique - table.] - - Description [Computes the fraction of slots in the unique table that - should be in use. This expected value is based on the assumption - that the hash function distributes the keys randomly; it can be - compared with the result of Cudd_ReadUsedSlots to monitor the - performance of the unique table hash function.] - - SideEffects [None] - - SeeAlso [Cudd_ReadSlots Cudd_ReadUsedSlots] - -******************************************************************************/ -double -Cudd_ExpectedUsedSlots( - DdManager * dd) -{ - int i; - int size = dd->size; - DdSubtable *subtable; - double empty = 0.0; - - /* To each subtable we apply the corollary to Theorem 8.5 (occupancy - ** distribution) from Sedgewick and Flajolet's Analysis of Algorithms. - ** The corollary says that for a a table with M buckets and a load ratio - ** of r, the expected number of empty buckets is asymptotically given - ** by M * exp(-r). - */ - - /* Scan each BDD/ADD subtable. */ - for (i = 0; i < size; i++) { - subtable = &(dd->subtables[i]); - empty += (double) subtable->slots * - exp(-(double) subtable->keys / (double) subtable->slots); - } - - /* Scan the ZDD subtables. */ - size = dd->sizeZ; - - for (i = 0; i < size; i++) { - subtable = &(dd->subtableZ[i]); - empty += (double) subtable->slots * - exp(-(double) subtable->keys / (double) subtable->slots); - } - - /* Constant table. */ - subtable = &(dd->constants); - empty += (double) subtable->slots * - exp(-(double) subtable->keys / (double) subtable->slots); - - return(1.0 - empty / (double) dd->slots); - -} /* end of Cudd_ExpectedUsedSlots */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of nodes in the unique table.] - - Description [Returns the total number of nodes currently in the unique - table, including the dead nodes.] - - SideEffects [None] - - SeeAlso [Cudd_ReadDead] - -******************************************************************************/ -unsigned int -Cudd_ReadKeys( - DdManager * dd) -{ - return(dd->keys); - -} /* end of Cudd_ReadKeys */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of dead nodes in the unique table.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadKeys] - -******************************************************************************/ -unsigned int -Cudd_ReadDead( - DdManager * dd) -{ - return(dd->dead); - -} /* end of Cudd_ReadDead */ - - -/**Function******************************************************************** - - Synopsis [Reads the minDead parameter of the manager.] - - Description [Reads the minDead parameter of the manager. The minDead - parameter is used by the package to decide whether to collect garbage - or resize a subtable of the unique table when the subtable becomes - too full. The application can indirectly control the value of minDead - by setting the looseUpTo parameter.] - - SideEffects [None] - - SeeAlso [Cudd_ReadDead Cudd_ReadLooseUpTo Cudd_SetLooseUpTo] - -******************************************************************************/ -unsigned int -Cudd_ReadMinDead( - DdManager * dd) -{ - return(dd->minDead); - -} /* end of Cudd_ReadMinDead */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of times reordering has occurred.] - - Description [Returns the number of times reordering has occurred in the - manager. The number includes both the calls to Cudd_ReduceHeap from - the application program and those automatically performed by the - package. However, calls that do not even initiate reordering are not - counted. A call may not initiate reordering if there are fewer than - minsize live nodes in the manager, or if CUDD_REORDER_NONE is specified - as reordering method. The calls to Cudd_ShuffleHeap are not counted.] - - SideEffects [None] - - SeeAlso [Cudd_ReduceHeap Cudd_ReadReorderingTime] - -******************************************************************************/ -int -Cudd_ReadReorderings( - DdManager * dd) -{ - return(dd->reorderings); - -} /* end of Cudd_ReadReorderings */ - - -/**Function******************************************************************** - - Synopsis [Returns the time spent in reordering.] - - Description [Returns the number of milliseconds spent reordering - variables since the manager was initialized. The time spent in collecting - garbage before reordering is included.] - - SideEffects [None] - - SeeAlso [Cudd_ReadReorderings] - -******************************************************************************/ -long -Cudd_ReadReorderingTime( - DdManager * dd) -{ - return(dd->reordTime); - -} /* end of Cudd_ReadReorderingTime */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of times garbage collection has occurred.] - - Description [Returns the number of times garbage collection has - occurred in the manager. The number includes both the calls from - reordering procedures and those caused by requests to create new - nodes.] - - SideEffects [None] - - SeeAlso [Cudd_ReadGarbageCollectionTime] - -******************************************************************************/ -int -Cudd_ReadGarbageCollections( - DdManager * dd) -{ - return(dd->garbageCollections); - -} /* end of Cudd_ReadGarbageCollections */ - - -/**Function******************************************************************** - - Synopsis [Returns the time spent in garbage collection.] - - Description [Returns the number of milliseconds spent doing garbage - collection since the manager was initialized.] - - SideEffects [None] - - SeeAlso [Cudd_ReadGarbageCollections] - -******************************************************************************/ -long -Cudd_ReadGarbageCollectionTime( - DdManager * dd) -{ - return(dd->GCTime); - -} /* end of Cudd_ReadGarbageCollectionTime */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of nodes freed.] - - Description [Returns the number of nodes returned to the free list if the - keeping of this statistic is enabled; -1 otherwise. This statistic is - enabled only if the package is compiled with DD_STATS defined.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNodesDropped] - -******************************************************************************/ -double -Cudd_ReadNodesFreed( - DdManager * dd) -{ -#ifdef DD_STATS - return(dd->nodesFreed); -#else - return(-1.0); -#endif - -} /* end of Cudd_ReadNodesFreed */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of nodes dropped.] - - Description [Returns the number of nodes killed by dereferencing if the - keeping of this statistic is enabled; -1 otherwise. This statistic is - enabled only if the package is compiled with DD_STATS defined.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNodesFreed] - -******************************************************************************/ -double -Cudd_ReadNodesDropped( - DdManager * dd) -{ -#ifdef DD_STATS - return(dd->nodesDropped); -#else - return(-1.0); -#endif - -} /* end of Cudd_ReadNodesDropped */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of look-ups in the unique table.] - - Description [Returns the number of look-ups in the unique table if the - keeping of this statistic is enabled; -1 otherwise. This statistic is - enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.] - - SideEffects [None] - - SeeAlso [Cudd_ReadUniqueLinks] - -******************************************************************************/ -double -Cudd_ReadUniqueLookUps( - DdManager * dd) -{ -#ifdef DD_UNIQUE_PROFILE - return(dd->uniqueLookUps); -#else - return(-1.0); -#endif - -} /* end of Cudd_ReadUniqueLookUps */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of links followed in the unique table.] - - Description [Returns the number of links followed during look-ups in the - unique table if the keeping of this statistic is enabled; -1 otherwise. - If an item is found in the first position of its collision list, the - number of links followed is taken to be 0. If it is in second position, - the number of links is 1, and so on. This statistic is enabled only if - the package is compiled with DD_UNIQUE_PROFILE defined.] - - SideEffects [None] - - SeeAlso [Cudd_ReadUniqueLookUps] - -******************************************************************************/ -double -Cudd_ReadUniqueLinks( - DdManager * dd) -{ -#ifdef DD_UNIQUE_PROFILE - return(dd->uniqueLinks); -#else - return(-1.0); -#endif - -} /* end of Cudd_ReadUniqueLinks */ - - -/**Function******************************************************************** - - Synopsis [Reads the siftMaxVar parameter of the manager.] - - Description [Reads the siftMaxVar parameter of the manager. This - parameter gives the maximum number of variables that will be sifted - for each invocation of sifting.] - - SideEffects [None] - - SeeAlso [Cudd_ReadSiftMaxSwap Cudd_SetSiftMaxVar] - -******************************************************************************/ -int -Cudd_ReadSiftMaxVar( - DdManager * dd) -{ - return(dd->siftMaxVar); - -} /* end of Cudd_ReadSiftMaxVar */ - - -/**Function******************************************************************** - - Synopsis [Sets the siftMaxVar parameter of the manager.] - - Description [Sets the siftMaxVar parameter of the manager. This - parameter gives the maximum number of variables that will be sifted - for each invocation of sifting.] - - SideEffects [None] - - SeeAlso [Cudd_SetSiftMaxSwap Cudd_ReadSiftMaxVar] - -******************************************************************************/ -void -Cudd_SetSiftMaxVar( - DdManager * dd, - int smv) -{ - dd->siftMaxVar = smv; - -} /* end of Cudd_SetSiftMaxVar */ - - -/**Function******************************************************************** - - Synopsis [Reads the siftMaxSwap parameter of the manager.] - - Description [Reads the siftMaxSwap parameter of the manager. This - parameter gives the maximum number of swaps that will be attempted - for each invocation of sifting. The real number of swaps may exceed - the set limit because the package will always complete the sifting - of the variable that causes the limit to be reached.] - - SideEffects [None] - - SeeAlso [Cudd_ReadSiftMaxVar Cudd_SetSiftMaxSwap] - -******************************************************************************/ -int -Cudd_ReadSiftMaxSwap( - DdManager * dd) -{ - return(dd->siftMaxSwap); - -} /* end of Cudd_ReadSiftMaxSwap */ - - -/**Function******************************************************************** - - Synopsis [Sets the siftMaxSwap parameter of the manager.] - - Description [Sets the siftMaxSwap parameter of the manager. This - parameter gives the maximum number of swaps that will be attempted - for each invocation of sifting. The real number of swaps may exceed - the set limit because the package will always complete the sifting - of the variable that causes the limit to be reached.] - - SideEffects [None] - - SeeAlso [Cudd_SetSiftMaxVar Cudd_ReadSiftMaxSwap] - -******************************************************************************/ -void -Cudd_SetSiftMaxSwap( - DdManager * dd, - int sms) -{ - dd->siftMaxSwap = sms; - -} /* end of Cudd_SetSiftMaxSwap */ - - -/**Function******************************************************************** - - Synopsis [Reads the maxGrowth parameter of the manager.] - - Description [Reads the maxGrowth parameter of the manager. This - parameter determines how much the number of nodes can grow during - sifting of a variable. Overall, sifting never increases the size of - the decision diagrams. This parameter only refers to intermediate - results. A lower value will speed up sifting, possibly at the - expense of quality.] - - SideEffects [None] - - SeeAlso [Cudd_SetMaxGrowth Cudd_ReadMaxGrowthAlternate] - -******************************************************************************/ -double -Cudd_ReadMaxGrowth( - DdManager * dd) -{ - return(dd->maxGrowth); - -} /* end of Cudd_ReadMaxGrowth */ - - -/**Function******************************************************************** - - Synopsis [Sets the maxGrowth parameter of the manager.] - - Description [Sets the maxGrowth parameter of the manager. This - parameter determines how much the number of nodes can grow during - sifting of a variable. Overall, sifting never increases the size of - the decision diagrams. This parameter only refers to intermediate - results. A lower value will speed up sifting, possibly at the - expense of quality.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate] - -******************************************************************************/ -void -Cudd_SetMaxGrowth( - DdManager * dd, - double mg) -{ - dd->maxGrowth = mg; - -} /* end of Cudd_SetMaxGrowth */ - - -/**Function******************************************************************** - - Synopsis [Reads the maxGrowthAlt parameter of the manager.] - - Description [Reads the maxGrowthAlt parameter of the manager. This - parameter is analogous to the maxGrowth paramter, and is used every - given number of reorderings instead of maxGrowth. The number of - reorderings is set with Cudd_SetReorderingCycle. If the number of - reorderings is 0 (default) maxGrowthAlt is never used.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate - Cudd_SetReorderingCycle Cudd_ReadReorderingCycle] - -******************************************************************************/ -double -Cudd_ReadMaxGrowthAlternate( - DdManager * dd) -{ - return(dd->maxGrowthAlt); - -} /* end of Cudd_ReadMaxGrowthAlternate */ - - -/**Function******************************************************************** - - Synopsis [Sets the maxGrowthAlt parameter of the manager.] - - Description [Sets the maxGrowthAlt parameter of the manager. This - parameter is analogous to the maxGrowth paramter, and is used every - given number of reorderings instead of maxGrowth. The number of - reorderings is set with Cudd_SetReorderingCycle. If the number of - reorderings is 0 (default) maxGrowthAlt is never used.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowth - Cudd_SetReorderingCycle Cudd_ReadReorderingCycle] - -******************************************************************************/ -void -Cudd_SetMaxGrowthAlternate( - DdManager * dd, - double mg) -{ - dd->maxGrowthAlt = mg; - -} /* end of Cudd_SetMaxGrowthAlternate */ - - -/**Function******************************************************************** - - Synopsis [Reads the reordCycle parameter of the manager.] - - Description [Reads the reordCycle parameter of the manager. This - parameter determines how often the alternate threshold on maximum - growth is used in reordering.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate - Cudd_SetReorderingCycle] - -******************************************************************************/ -int -Cudd_ReadReorderingCycle( - DdManager * dd) -{ - return(dd->reordCycle); - -} /* end of Cudd_ReadReorderingCycle */ - - -/**Function******************************************************************** - - Synopsis [Sets the reordCycle parameter of the manager.] - - Description [Sets the reordCycle parameter of the manager. This - parameter determines how often the alternate threshold on maximum - growth is used in reordering.] - - SideEffects [None] - - SeeAlso [Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate - Cudd_ReadReorderingCycle] - -******************************************************************************/ -void -Cudd_SetReorderingCycle( - DdManager * dd, - int cycle) -{ - dd->reordCycle = cycle; - -} /* end of Cudd_SetReorderingCycle */ - - -/**Function******************************************************************** - - Synopsis [Returns the variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetTree Cudd_FreeTree Cudd_ReadZddTree] - -******************************************************************************/ -MtrNode * -Cudd_ReadTree( - DdManager * dd) -{ - return(dd->tree); - -} /* end of Cudd_ReadTree */ - - -/**Function******************************************************************** - - Synopsis [Sets the variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_FreeTree Cudd_ReadTree Cudd_SetZddTree] - -******************************************************************************/ -void -Cudd_SetTree( - DdManager * dd, - MtrNode * tree) -{ - if (dd->tree != NULL) { - Mtr_FreeTree(dd->tree); - } - dd->tree = tree; - if (tree == NULL) return; - - fixVarTree(tree, dd->perm, dd->size); - return; - -} /* end of Cudd_SetTree */ - - -/**Function******************************************************************** - - Synopsis [Frees the variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetTree Cudd_ReadTree Cudd_FreeZddTree] - -******************************************************************************/ -void -Cudd_FreeTree( - DdManager * dd) -{ - if (dd->tree != NULL) { - Mtr_FreeTree(dd->tree); - dd->tree = NULL; - } - return; - -} /* end of Cudd_FreeTree */ - - -/**Function******************************************************************** - - Synopsis [Returns the variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetZddTree Cudd_FreeZddTree Cudd_ReadTree] - -******************************************************************************/ -MtrNode * -Cudd_ReadZddTree( - DdManager * dd) -{ - return(dd->treeZ); - -} /* end of Cudd_ReadZddTree */ - - -/**Function******************************************************************** - - Synopsis [Sets the ZDD variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_FreeZddTree Cudd_ReadZddTree Cudd_SetTree] - -******************************************************************************/ -void -Cudd_SetZddTree( - DdManager * dd, - MtrNode * tree) -{ - if (dd->treeZ != NULL) { - Mtr_FreeTree(dd->treeZ); - } - dd->treeZ = tree; - if (tree == NULL) return; - - fixVarTree(tree, dd->permZ, dd->sizeZ); - return; - -} /* end of Cudd_SetZddTree */ - - -/**Function******************************************************************** - - Synopsis [Frees the variable group tree of the manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_SetZddTree Cudd_ReadZddTree Cudd_FreeTree] - -******************************************************************************/ -void -Cudd_FreeZddTree( - DdManager * dd) -{ - if (dd->treeZ != NULL) { - Mtr_FreeTree(dd->treeZ); - dd->treeZ = NULL; - } - return; - -} /* end of Cudd_FreeZddTree */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of the node.] - - Description [Returns the index of the node. The node pointer can be - either regular or complemented.] - - SideEffects [None] - - SeeAlso [Cudd_ReadIndex] - -******************************************************************************/ -unsigned int -Cudd_NodeReadIndex( - DdNode * node) -{ - return((unsigned int) Cudd_Regular(node)->index); - -} /* end of Cudd_NodeReadIndex */ - - -/**Function******************************************************************** - - Synopsis [Returns the current position of the i-th variable in the - order.] - - Description [Returns the current position of the i-th variable in - the order. If the index is CUDD_CONST_INDEX, returns - CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns - -1.] - - SideEffects [None] - - SeeAlso [Cudd_ReadInvPerm Cudd_ReadPermZdd] - -******************************************************************************/ -int -Cudd_ReadPerm( - DdManager * dd, - int i) -{ - if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); - if (i < 0 || i >= dd->size) return(-1); - return(dd->perm[i]); - -} /* end of Cudd_ReadPerm */ - - -/**Function******************************************************************** - - Synopsis [Returns the current position of the i-th ZDD variable in the - order.] - - Description [Returns the current position of the i-th ZDD variable - in the order. If the index is CUDD_CONST_INDEX, returns - CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns - -1.] - - SideEffects [None] - - SeeAlso [Cudd_ReadInvPermZdd Cudd_ReadPerm] - -******************************************************************************/ -int -Cudd_ReadPermZdd( - DdManager * dd, - int i) -{ - if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); - if (i < 0 || i >= dd->sizeZ) return(-1); - return(dd->permZ[i]); - -} /* end of Cudd_ReadPermZdd */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of the variable currently in the i-th - position of the order.] - - Description [Returns the index of the variable currently in the i-th - position of the order. If the index is CUDD_CONST_INDEX, returns - CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.] - - SideEffects [None] - - SeeAlso [Cudd_ReadPerm Cudd_ReadInvPermZdd] - -******************************************************************************/ -int -Cudd_ReadInvPerm( - DdManager * dd, - int i) -{ - if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); - if (i < 0 || i >= dd->size) return(-1); - return(dd->invperm[i]); - -} /* end of Cudd_ReadInvPerm */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of the ZDD variable currently in the i-th - position of the order.] - - Description [Returns the index of the ZDD variable currently in the - i-th position of the order. If the index is CUDD_CONST_INDEX, returns - CUDD_CONST_INDEX; otherwise, if the index is out of bounds returns -1.] - - SideEffects [None] - - SeeAlso [Cudd_ReadPerm Cudd_ReadInvPermZdd] - -******************************************************************************/ -int -Cudd_ReadInvPermZdd( - DdManager * dd, - int i) -{ - if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX); - if (i < 0 || i >= dd->sizeZ) return(-1); - return(dd->invpermZ[i]); - -} /* end of Cudd_ReadInvPermZdd */ - - -/**Function******************************************************************** - - Synopsis [Returns the i-th element of the vars array.] - - Description [Returns the i-th element of the vars array if it falls - within the array bounds; NULL otherwise. If i is the index of an - existing variable, this function produces the same result as - Cudd_bddIthVar. However, if the i-th var does not exist yet, - Cudd_bddIthVar will create it, whereas Cudd_ReadVars will not.] - - SideEffects [None] - - SeeAlso [Cudd_bddIthVar] - -******************************************************************************/ -DdNode * -Cudd_ReadVars( - DdManager * dd, - int i) -{ - if (i < 0 || i > dd->size) return(NULL); - return(dd->vars[i]); - -} /* end of Cudd_ReadVars */ - - -/**Function******************************************************************** - - Synopsis [Reads the epsilon parameter of the manager.] - - Description [Reads the epsilon parameter of the manager. The epsilon - parameter control the comparison between floating point numbers.] - - SideEffects [None] - - SeeAlso [Cudd_SetEpsilon] - -******************************************************************************/ -CUDD_VALUE_TYPE -Cudd_ReadEpsilon( - DdManager * dd) -{ - return(dd->epsilon); - -} /* end of Cudd_ReadEpsilon */ - - -/**Function******************************************************************** - - Synopsis [Sets the epsilon parameter of the manager to ep.] - - Description [Sets the epsilon parameter of the manager to ep. The epsilon - parameter control the comparison between floating point numbers.] - - SideEffects [None] - - SeeAlso [Cudd_ReadEpsilon] - -******************************************************************************/ -void -Cudd_SetEpsilon( - DdManager * dd, - CUDD_VALUE_TYPE ep) -{ - dd->epsilon = ep; - -} /* end of Cudd_SetEpsilon */ - - -/**Function******************************************************************** - - Synopsis [Reads the groupcheck parameter of the manager.] - - Description [Reads the groupcheck parameter of the manager. The - groupcheck parameter determines the aggregation criterion in group - sifting.] - - SideEffects [None] - - SeeAlso [Cudd_SetGroupcheck] - -******************************************************************************/ -Cudd_AggregationType -Cudd_ReadGroupcheck( - DdManager * dd) -{ - return(dd->groupcheck); - -} /* end of Cudd_ReadGroupCheck */ - - -/**Function******************************************************************** - - Synopsis [Sets the parameter groupcheck of the manager to gc.] - - Description [Sets the parameter groupcheck of the manager to gc. The - groupcheck parameter determines the aggregation criterion in group - sifting.] - - SideEffects [None] - - SeeAlso [Cudd_ReadGroupCheck] - -******************************************************************************/ -void -Cudd_SetGroupcheck( - DdManager * dd, - Cudd_AggregationType gc) -{ - dd->groupcheck = gc; - -} /* end of Cudd_SetGroupcheck */ - - -/**Function******************************************************************** - - Synopsis [Tells whether garbage collection is enabled.] - - Description [Returns 1 if garbage collection is enabled; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_EnableGarbageCollection Cudd_DisableGarbageCollection] - -******************************************************************************/ -int -Cudd_GarbageCollectionEnabled( - DdManager * dd) -{ - return(dd->gcEnabled); - -} /* end of Cudd_GarbageCollectionEnabled */ - - -/**Function******************************************************************** - - Synopsis [Enables garbage collection.] - - Description [Enables garbage collection. Garbage collection is - initially enabled. Therefore it is necessary to call this function - only if garbage collection has been explicitly disabled.] - - SideEffects [None] - - SeeAlso [Cudd_DisableGarbageCollection Cudd_GarbageCollectionEnabled] - -******************************************************************************/ -void -Cudd_EnableGarbageCollection( - DdManager * dd) -{ - dd->gcEnabled = 1; - -} /* end of Cudd_EnableGarbageCollection */ - - -/**Function******************************************************************** - - Synopsis [Disables garbage collection.] - - Description [Disables garbage collection. Garbage collection is - initially enabled. This function may be called to disable it. - However, garbage collection will still occur when a new node must be - created and no memory is left, or when garbage collection is required - for correctness. (E.g., before reordering.)] - - SideEffects [None] - - SeeAlso [Cudd_EnableGarbageCollection Cudd_GarbageCollectionEnabled] - -******************************************************************************/ -void -Cudd_DisableGarbageCollection( - DdManager * dd) -{ - dd->gcEnabled = 0; - -} /* end of Cudd_DisableGarbageCollection */ - - -/**Function******************************************************************** - - Synopsis [Tells whether dead nodes are counted towards triggering - reordering.] - - Description [Tells whether dead nodes are counted towards triggering - reordering. Returns 1 if dead nodes are counted; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_TurnOnCountDead Cudd_TurnOffCountDead] - -******************************************************************************/ -int -Cudd_DeadAreCounted( - DdManager * dd) -{ - return(dd->countDead == 0 ? 1 : 0); - -} /* end of Cudd_DeadAreCounted */ - - -/**Function******************************************************************** - - Synopsis [Causes the dead nodes to be counted towards triggering - reordering.] - - Description [Causes the dead nodes to be counted towards triggering - reordering. This causes more frequent reorderings. By default dead - nodes are not counted.] - - SideEffects [Changes the manager.] - - SeeAlso [Cudd_TurnOffCountDead Cudd_DeadAreCounted] - -******************************************************************************/ -void -Cudd_TurnOnCountDead( - DdManager * dd) -{ - dd->countDead = 0; - -} /* end of Cudd_TurnOnCountDead */ - - -/**Function******************************************************************** - - Synopsis [Causes the dead nodes not to be counted towards triggering - reordering.] - - Description [Causes the dead nodes not to be counted towards - triggering reordering. This causes less frequent reorderings. By - default dead nodes are not counted. Therefore there is no need to - call this function unless Cudd_TurnOnCountDead has been previously - called.] - - SideEffects [Changes the manager.] - - SeeAlso [Cudd_TurnOnCountDead Cudd_DeadAreCounted] - -******************************************************************************/ -void -Cudd_TurnOffCountDead( - DdManager * dd) -{ - dd->countDead = ~0; - -} /* end of Cudd_TurnOffCountDead */ - - -/**Function******************************************************************** - - Synopsis [Returns the current value of the recombination parameter used - in group sifting.] - - Description [Returns the current value of the recombination - parameter used in group sifting. A larger (positive) value makes the - aggregation of variables due to the second difference criterion more - likely. A smaller (negative) value makes aggregation less likely.] - - SideEffects [None] - - SeeAlso [Cudd_SetRecomb] - -******************************************************************************/ -int -Cudd_ReadRecomb( - DdManager * dd) -{ - return(dd->recomb); - -} /* end of Cudd_ReadRecomb */ - - -/**Function******************************************************************** - - Synopsis [Sets the value of the recombination parameter used in group - sifting.] - - Description [Sets the value of the recombination parameter used in - group sifting. A larger (positive) value makes the aggregation of - variables due to the second difference criterion more likely. A - smaller (negative) value makes aggregation less likely. The default - value is 0.] - - SideEffects [Changes the manager.] - - SeeAlso [Cudd_ReadRecomb] - -******************************************************************************/ -void -Cudd_SetRecomb( - DdManager * dd, - int recomb) -{ - dd->recomb = recomb; - -} /* end of Cudd_SetRecomb */ - - -/**Function******************************************************************** - - Synopsis [Returns the current value of the symmviolation parameter used - in group sifting.] - - Description [Returns the current value of the symmviolation - parameter. This parameter is used in group sifting to decide how - many violations to the symmetry conditions f10 = f01 or - f11 = f00 are tolerable when checking for aggregation - due to extended symmetry. The value should be between 0 and 100. A - small value causes fewer variables to be aggregated. The default - value is 0.] - - SideEffects [None] - - SeeAlso [Cudd_SetSymmviolation] - -******************************************************************************/ -int -Cudd_ReadSymmviolation( - DdManager * dd) -{ - return(dd->symmviolation); - -} /* end of Cudd_ReadSymmviolation */ - - -/**Function******************************************************************** - - Synopsis [Sets the value of the symmviolation parameter used - in group sifting.] - - Description [Sets the value of the symmviolation - parameter. This parameter is used in group sifting to decide how - many violations to the symmetry conditions f10 = f01 or - f11 = f00 are tolerable when checking for aggregation - due to extended symmetry. The value should be between 0 and 100. A - small value causes fewer variables to be aggregated. The default - value is 0.] - - SideEffects [Changes the manager.] - - SeeAlso [Cudd_ReadSymmviolation] - -******************************************************************************/ -void -Cudd_SetSymmviolation( - DdManager * dd, - int symmviolation) -{ - dd->symmviolation = symmviolation; - -} /* end of Cudd_SetSymmviolation */ - - -/**Function******************************************************************** - - Synopsis [Returns the current value of the arcviolation parameter used - in group sifting.] - - Description [Returns the current value of the arcviolation - parameter. This parameter is used in group sifting to decide how - many arcs into y not coming from x are - tolerable when checking for aggregation due to extended - symmetry. The value should be between 0 and 100. A small value - causes fewer variables to be aggregated. The default value is 0.] - - SideEffects [None] - - SeeAlso [Cudd_SetArcviolation] - -******************************************************************************/ -int -Cudd_ReadArcviolation( - DdManager * dd) -{ - return(dd->arcviolation); - -} /* end of Cudd_ReadArcviolation */ - - -/**Function******************************************************************** - - Synopsis [Sets the value of the arcviolation parameter used - in group sifting.] - - Description [Sets the value of the arcviolation - parameter. This parameter is used in group sifting to decide how - many arcs into y not coming from x are - tolerable when checking for aggregation due to extended - symmetry. The value should be between 0 and 100. A small value - causes fewer variables to be aggregated. The default value is 0.] - - SideEffects [None] - - SeeAlso [Cudd_ReadArcviolation] - -******************************************************************************/ -void -Cudd_SetArcviolation( - DdManager * dd, - int arcviolation) -{ - dd->arcviolation = arcviolation; - -} /* end of Cudd_SetArcviolation */ - - -/**Function******************************************************************** - - Synopsis [Reads the current size of the population used by the - genetic algorithm for reordering.] - - Description [Reads the current size of the population used by the - genetic algorithm for variable reordering. A larger population size will - cause the genetic algorithm to take more time, but will generally - produce better results. The default value is 0, in which case the - package uses three times the number of variables as population size, - with a maximum of 120.] - - SideEffects [None] - - SeeAlso [Cudd_SetPopulationSize] - -******************************************************************************/ -int -Cudd_ReadPopulationSize( - DdManager * dd) -{ - return(dd->populationSize); - -} /* end of Cudd_ReadPopulationSize */ - - -/**Function******************************************************************** - - Synopsis [Sets the size of the population used by the - genetic algorithm for reordering.] - - Description [Sets the size of the population used by the - genetic algorithm for variable reordering. A larger population size will - cause the genetic algorithm to take more time, but will generally - produce better results. The default value is 0, in which case the - package uses three times the number of variables as population size, - with a maximum of 120.] - - SideEffects [Changes the manager.] - - SeeAlso [Cudd_ReadPopulationSize] - -******************************************************************************/ -void -Cudd_SetPopulationSize( - DdManager * dd, - int populationSize) -{ - dd->populationSize = populationSize; - -} /* end of Cudd_SetPopulationSize */ - - -/**Function******************************************************************** - - Synopsis [Reads the current number of crossovers used by the - genetic algorithm for reordering.] - - Description [Reads the current number of crossovers used by the - genetic algorithm for variable reordering. A larger number of crossovers will - cause the genetic algorithm to take more time, but will generally - produce better results. The default value is 0, in which case the - package uses three times the number of variables as number of crossovers, - with a maximum of 60.] - - SideEffects [None] - - SeeAlso [Cudd_SetNumberXovers] - -******************************************************************************/ -int -Cudd_ReadNumberXovers( - DdManager * dd) -{ - return(dd->numberXovers); - -} /* end of Cudd_ReadNumberXovers */ - - -/**Function******************************************************************** - - Synopsis [Sets the number of crossovers used by the - genetic algorithm for reordering.] - - Description [Sets the number of crossovers used by the genetic - algorithm for variable reordering. A larger number of crossovers - will cause the genetic algorithm to take more time, but will - generally produce better results. The default value is 0, in which - case the package uses three times the number of variables as number - of crossovers, with a maximum of 60.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNumberXovers] - -******************************************************************************/ -void -Cudd_SetNumberXovers( - DdManager * dd, - int numberXovers) -{ - dd->numberXovers = numberXovers; - -} /* end of Cudd_SetNumberXovers */ - -/**Function******************************************************************** - - Synopsis [Returns the memory in use by the manager measured in bytes.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -long -Cudd_ReadMemoryInUse( - DdManager * dd) -{ - return(dd->memused); - -} /* end of Cudd_ReadMemoryInUse */ - - -/**Function******************************************************************** - - Synopsis [Prints out statistics and settings for a CUDD manager.] - - Description [Prints out statistics and settings for a CUDD manager. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_PrintInfo( - DdManager * dd, - FILE * fp) -{ - int retval; - Cudd_ReorderingType autoMethod, autoMethodZ; - - /* Modifiable parameters. */ - retval = fprintf(fp,"**** CUDD modifiable parameters ****\n"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Hard limit for cache size: %u\n", - Cudd_ReadMaxCacheHard(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache hit threshold for resizing: %u%%\n", - Cudd_ReadMinHit(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Garbage collection enabled: %s\n", - Cudd_GarbageCollectionEnabled(dd) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Limit for fast unique table growth: %u\n", - Cudd_ReadLooseUpTo(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp, - "Maximum number of variables sifted per reordering: %d\n", - Cudd_ReadSiftMaxVar(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp, - "Maximum number of variable swaps per reordering: %d\n", - Cudd_ReadSiftMaxSwap(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Maximum growth while sifting a variable: %g\n", - Cudd_ReadMaxGrowth(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Dynamic reordering of BDDs enabled: %s\n", - Cudd_ReorderingStatus(dd,&autoMethod) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Default BDD reordering method: %d\n", autoMethod); - if (retval == EOF) return(0); - retval = fprintf(fp,"Dynamic reordering of ZDDs enabled: %s\n", - Cudd_ReorderingStatusZdd(dd,&autoMethodZ) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Default ZDD reordering method: %d\n", autoMethodZ); - if (retval == EOF) return(0); - retval = fprintf(fp,"Realignment of ZDDs to BDDs enabled: %s\n", - Cudd_zddRealignmentEnabled(dd) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Realignment of BDDs to ZDDs enabled: %s\n", - Cudd_bddRealignmentEnabled(dd) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Dead nodes counted in triggering reordering: %s\n", - Cudd_DeadAreCounted(dd) ? "yes" : "no"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Group checking criterion: %d\n", - Cudd_ReadGroupcheck(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Recombination threshold: %d\n", Cudd_ReadRecomb(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Symmetry violation threshold: %d\n", - Cudd_ReadSymmviolation(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Arc violation threshold: %d\n", - Cudd_ReadArcviolation(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"GA population size: %d\n", - Cudd_ReadPopulationSize(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of crossovers for GA: %d\n", - Cudd_ReadNumberXovers(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Next reordering threshold: %u\n", - Cudd_ReadNextReordering(dd)); - if (retval == EOF) return(0); - - /* Non-modifiable parameters. */ - retval = fprintf(fp,"**** CUDD non-modifiable parameters ****\n"); - if (retval == EOF) return(0); - retval = fprintf(fp,"Memory in use: %ld\n", Cudd_ReadMemoryInUse(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Peak number of nodes: %ld\n", - Cudd_ReadPeakNodeCount(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Peak number of live nodes: %d\n", - Cudd_ReadPeakLiveNodeCount(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of BDD variables: %d\n", dd->size); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of ZDD variables: %d\n", dd->sizeZ); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache entries: %u\n", dd->cacheSlots); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache look-ups: %.0f\n", - Cudd_ReadCacheLookUps(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache hits: %.0f\n", - Cudd_ReadCacheHits(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache insertions: %.0f\n", - dd->cacheinserts); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache collisions: %.0f\n", - dd->cachecollisions); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of cache deletions: %.0f\n", - dd->cachedeletions); - if (retval == EOF) return(0); - retval = cuddCacheProfile(dd,fp); - if (retval == 0) return(0); - retval = fprintf(fp,"Soft limit for cache size: %u\n", - Cudd_ReadMaxCache(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of buckets in unique table: %u\n", dd->slots); - if (retval == EOF) return(0); - retval = fprintf(fp,"Used buckets in unique table: %.2f%% (expected %.2f%%)\n", - 100.0 * Cudd_ReadUsedSlots(dd), - 100.0 * Cudd_ExpectedUsedSlots(dd)); - if (retval == EOF) return(0); -#ifdef DD_UNIQUE_PROFILE - retval = fprintf(fp,"Unique lookups: %.0f\n", dd->uniqueLookUps); - if (retval == EOF) return(0); - retval = fprintf(fp,"Unique links: %.0f (%g per lookup)\n", - dd->uniqueLinks, dd->uniqueLinks / dd->uniqueLookUps); - if (retval == EOF) return(0); -#endif - retval = fprintf(fp,"Number of BDD and ADD nodes: %u\n", dd->keys); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of ZDD nodes: %u\n", dd->keysZ); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of dead BDD and ADD nodes: %u\n", dd->dead); - if (retval == EOF) return(0); - retval = fprintf(fp,"Number of dead ZDD nodes: %u\n", dd->deadZ); - if (retval == EOF) return(0); - retval = fprintf(fp,"Total number of nodes allocated: %.0f\n", - dd->allocated); - if (retval == EOF) return(0); - retval = fprintf(fp,"Total number of nodes reclaimed: %.0f\n", - dd->reclaimed); - if (retval == EOF) return(0); -#if DD_STATS - retval = fprintf(fp,"Nodes freed: %.0f\n", dd->nodesFreed); - if (retval == EOF) return(0); - retval = fprintf(fp,"Nodes dropped: %.0f\n", dd->nodesDropped); - if (retval == EOF) return(0); -#endif -#if DD_COUNT - retval = fprintf(fp,"Number of recursive calls: %.0f\n", - Cudd_ReadRecursiveCalls(dd)); - if (retval == EOF) return(0); -#endif - retval = fprintf(fp,"Garbage collections so far: %d\n", - Cudd_ReadGarbageCollections(dd)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Time for garbage collection: %.2f sec\n", - ((double)Cudd_ReadGarbageCollectionTime(dd)/1000.0)); - if (retval == EOF) return(0); - retval = fprintf(fp,"Reorderings so far: %d\n", dd->reorderings); - if (retval == EOF) return(0); - retval = fprintf(fp,"Time for reordering: %.2f sec\n", - ((double)Cudd_ReadReorderingTime(dd)/1000.0)); - if (retval == EOF) return(0); -#if DD_COUNT - retval = fprintf(fp,"Node swaps in reordering: %.0f\n", - Cudd_ReadSwapSteps(dd)); - if (retval == EOF) return(0); -#endif - - return(1); - -} /* end of Cudd_PrintInfo */ - - -/**Function******************************************************************** - - Synopsis [Reports the peak number of nodes.] - - Description [Reports the peak number of nodes. This number includes - node on the free list. At the peak, the number of nodes on the free - list is guaranteed to be less than DD_MEM_CHUNK.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNodeCount Cudd_PrintInfo] - -******************************************************************************/ -long -Cudd_ReadPeakNodeCount( - DdManager * dd) -{ - long count = 0; - DdNodePtr *scan = dd->memoryList; - - while (scan != NULL) { - count += DD_MEM_CHUNK; - scan = (DdNodePtr *) *scan; - } - return(count); - -} /* end of Cudd_ReadPeakNodeCount */ - - -/**Function******************************************************************** - - Synopsis [Reports the peak number of live nodes.] - - Description [Reports the peak number of live nodes. This count is kept - only if CUDD is compiled with DD_STATS defined. If DD_STATS is not - defined, this function returns -1.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNodeCount Cudd_PrintInfo Cudd_ReadPeakNodeCount] - -******************************************************************************/ -int -Cudd_ReadPeakLiveNodeCount( - DdManager * dd) -{ - unsigned int live = dd->keys - dd->dead; - - if (live > dd->peakLiveNodes) { - dd->peakLiveNodes = live; - } - return((int)dd->peakLiveNodes); - -} /* end of Cudd_ReadPeakLiveNodeCount */ - - -/**Function******************************************************************** - - Synopsis [Reports the number of nodes in BDDs and ADDs.] - - Description [Reports the number of live nodes in BDDs and ADDs. This - number does not include the isolated projection functions and the - unused constants. These nodes that are not counted are not part of - the DDs manipulated by the application.] - - SideEffects [None] - - SeeAlso [Cudd_ReadPeakNodeCount Cudd_zddReadNodeCount] - -******************************************************************************/ -long -Cudd_ReadNodeCount( - DdManager * dd) -{ - long count; - int i; - -#ifndef DD_NO_DEATH_ROW - cuddClearDeathRow(dd); -#endif - - count = dd->keys - dd->dead; - - /* Count isolated projection functions. Their number is subtracted - ** from the node count because they are not part of the BDDs. - */ - for (i=0; i < dd->size; i++) { - if (dd->vars[i]->ref == 1) count--; - } - /* Subtract from the count the unused constants. */ - if (DD_ZERO(dd)->ref == 1) count--; - if (DD_PLUS_INFINITY(dd)->ref == 1) count--; - if (DD_MINUS_INFINITY(dd)->ref == 1) count--; - - return(count); - -} /* end of Cudd_ReadNodeCount */ - - - -/**Function******************************************************************** - - Synopsis [Reports the number of nodes in ZDDs.] - - Description [Reports the number of nodes in ZDDs. This - number always includes the two constants 1 and 0.] - - SideEffects [None] - - SeeAlso [Cudd_ReadPeakNodeCount Cudd_ReadNodeCount] - -******************************************************************************/ -long -Cudd_zddReadNodeCount( - DdManager * dd) -{ - return(dd->keysZ - dd->deadZ + 2); - -} /* end of Cudd_zddReadNodeCount */ - - -/**Function******************************************************************** - - Synopsis [Adds a function to a hook.] - - Description [Adds a function to a hook. A hook is a list of - application-provided functions called on certain occasions by the - package. Returns 1 if the function is successfully added; 2 if the - function was already in the list; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_RemoveHook] - -******************************************************************************/ -int -Cudd_AddHook( - DdManager * dd, - int (*f)(DdManager *, char *, void *) , - Cudd_HookType where) -{ - DdHook **hook, *nextHook, *newHook; - - switch (where) { - case CUDD_PRE_GC_HOOK: - hook = &(dd->preGCHook); - break; - case CUDD_POST_GC_HOOK: - hook = &(dd->postGCHook); - break; - case CUDD_PRE_REORDERING_HOOK: - hook = &(dd->preReorderingHook); - break; - case CUDD_POST_REORDERING_HOOK: - hook = &(dd->postReorderingHook); - break; - default: - return(0); - } - /* Scan the list and find whether the function is already there. - ** If so, just return. */ - nextHook = *hook; - while (nextHook != NULL) { - if (nextHook->f == f) { - return(2); - } - hook = &(nextHook->next); - nextHook = nextHook->next; - } - /* The function was not in the list. Create a new item and append it - ** to the end of the list. */ - newHook = ALLOC(DdHook,1); - if (newHook == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newHook->next = NULL; - newHook->f = f; - *hook = newHook; - return(1); - -} /* end of Cudd_AddHook */ - - -/**Function******************************************************************** - - Synopsis [Removes a function from a hook.] - - Description [Removes a function from a hook. A hook is a list of - application-provided functions called on certain occasions by the - package. Returns 1 if successful; 0 the function was not in the list.] - - SideEffects [None] - - SeeAlso [Cudd_AddHook] - -******************************************************************************/ -int -Cudd_RemoveHook( - DdManager * dd, - int (*f)(DdManager *, char *, void *) , - Cudd_HookType where) -{ - DdHook **hook, *nextHook; - - switch (where) { - case CUDD_PRE_GC_HOOK: - hook = &(dd->preGCHook); - break; - case CUDD_POST_GC_HOOK: - hook = &(dd->postGCHook); - break; - case CUDD_PRE_REORDERING_HOOK: - hook = &(dd->preReorderingHook); - break; - case CUDD_POST_REORDERING_HOOK: - hook = &(dd->postReorderingHook); - break; - default: - return(0); - } - nextHook = *hook; - while (nextHook != NULL) { - if (nextHook->f == f) { - *hook = nextHook->next; - FREE(nextHook); - return(1); - } - hook = &(nextHook->next); - nextHook = nextHook->next; - } - - return(0); - -} /* end of Cudd_RemoveHook */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a function is in a hook.] - - Description [Checks whether a function is in a hook. A hook is a list of - application-provided functions called on certain occasions by the - package. Returns 1 if the function is found; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_AddHook Cudd_RemoveHook] - -******************************************************************************/ -int -Cudd_IsInHook( - DdManager * dd, - int (*f)(DdManager *, char *, void *) , - Cudd_HookType where) -{ - DdHook *hook; - - switch (where) { - case CUDD_PRE_GC_HOOK: - hook = dd->preGCHook; - break; - case CUDD_POST_GC_HOOK: - hook = dd->postGCHook; - break; - case CUDD_PRE_REORDERING_HOOK: - hook = dd->preReorderingHook; - break; - case CUDD_POST_REORDERING_HOOK: - hook = dd->postReorderingHook; - break; - default: - return(0); - } - /* Scan the list and find whether the function is already there. */ - while (hook != NULL) { - if (hook->f == f) { - return(1); - } - hook = hook->next; - } - return(0); - -} /* end of Cudd_IsInHook */ - - -/**Function******************************************************************** - - Synopsis [Sample hook function to call before reordering.] - - Description [Sample hook function to call before reordering. - Prints on the manager's stdout reordering method and initial size. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_StdPostReordHook] - -******************************************************************************/ -int -Cudd_StdPreReordHook( - DdManager *dd, - char *str, - void *data) -{ - Cudd_ReorderingType method = (Cudd_ReorderingType) (ptruint) data; - int retval; - - retval = fprintf(dd->out,"%s reordering with ", str); - if (retval == EOF) return(0); - switch (method) { - case CUDD_REORDER_SIFT_CONVERGE: - case CUDD_REORDER_SYMM_SIFT_CONV: - case CUDD_REORDER_GROUP_SIFT_CONV: - case CUDD_REORDER_WINDOW2_CONV: - case CUDD_REORDER_WINDOW3_CONV: - case CUDD_REORDER_WINDOW4_CONV: - case CUDD_REORDER_LINEAR_CONVERGE: - retval = fprintf(dd->out,"converging "); - if (retval == EOF) return(0); - break; - default: - break; - } - switch (method) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - retval = fprintf(dd->out,"random"); - break; - case CUDD_REORDER_SIFT: - case CUDD_REORDER_SIFT_CONVERGE: - retval = fprintf(dd->out,"sifting"); - break; - case CUDD_REORDER_SYMM_SIFT: - case CUDD_REORDER_SYMM_SIFT_CONV: - retval = fprintf(dd->out,"symmetric sifting"); - break; - case CUDD_REORDER_LAZY_SIFT: - retval = fprintf(dd->out,"lazy sifting"); - break; - case CUDD_REORDER_GROUP_SIFT: - case CUDD_REORDER_GROUP_SIFT_CONV: - retval = fprintf(dd->out,"group sifting"); - break; - case CUDD_REORDER_WINDOW2: - case CUDD_REORDER_WINDOW3: - case CUDD_REORDER_WINDOW4: - case CUDD_REORDER_WINDOW2_CONV: - case CUDD_REORDER_WINDOW3_CONV: - case CUDD_REORDER_WINDOW4_CONV: - retval = fprintf(dd->out,"window"); - break; - case CUDD_REORDER_ANNEALING: - retval = fprintf(dd->out,"annealing"); - break; - case CUDD_REORDER_GENETIC: - retval = fprintf(dd->out,"genetic"); - break; - case CUDD_REORDER_LINEAR: - case CUDD_REORDER_LINEAR_CONVERGE: - retval = fprintf(dd->out,"linear sifting"); - break; - case CUDD_REORDER_EXACT: - retval = fprintf(dd->out,"exact"); - break; - default: - return(0); - } - if (retval == EOF) return(0); - - retval = fprintf(dd->out,": from %ld to ... ", strcmp(str, "BDD") == 0 ? - Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd)); - if (retval == EOF) return(0); - fflush(dd->out); - return(1); - -} /* end of Cudd_StdPreReordHook */ - - -/**Function******************************************************************** - - Synopsis [Sample hook function to call after reordering.] - - Description [Sample hook function to call after reordering. - Prints on the manager's stdout final size and reordering time. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_StdPreReordHook] - -******************************************************************************/ -int -Cudd_StdPostReordHook( - DdManager *dd, - char *str, - void *data) -{ - long initialTime = (long) data; - int retval; - long finalTime = util_cpu_time(); - double totalTimeSec = (double)(finalTime - initialTime) / 1000.0; - - retval = fprintf(dd->out,"%ld nodes in %g sec\n", strcmp(str, "BDD") == 0 ? - Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd), - totalTimeSec); - if (retval == EOF) return(0); - retval = fflush(dd->out); - if (retval == EOF) return(0); - return(1); - -} /* end of Cudd_StdPostReordHook */ - - -/**Function******************************************************************** - - Synopsis [Enables reporting of reordering stats.] - - Description [Enables reporting of reordering stats. - Returns 1 if successful; 0 otherwise.] - - SideEffects [Installs functions in the pre-reordering and post-reordering - hooks.] - - SeeAlso [Cudd_DisableReorderingReporting Cudd_ReorderingReporting] - -******************************************************************************/ -int -Cudd_EnableReorderingReporting( - DdManager *dd) -{ - if (!Cudd_AddHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) { - return(0); - } - if (!Cudd_AddHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) { - return(0); - } - return(1); - -} /* end of Cudd_EnableReorderingReporting */ - - -/**Function******************************************************************** - - Synopsis [Disables reporting of reordering stats.] - - Description [Disables reporting of reordering stats. - Returns 1 if successful; 0 otherwise.] - - SideEffects [Removes functions from the pre-reordering and post-reordering - hooks.] - - SeeAlso [Cudd_EnableReorderingReporting Cudd_ReorderingReporting] - -******************************************************************************/ -int -Cudd_DisableReorderingReporting( - DdManager *dd) -{ - if (!Cudd_RemoveHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) { - return(0); - } - if (!Cudd_RemoveHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) { - return(0); - } - return(1); - -} /* end of Cudd_DisableReorderingReporting */ - - -/**Function******************************************************************** - - Synopsis [Returns 1 if reporting of reordering stats is enabled.] - - Description [Returns 1 if reporting of reordering stats is enabled; - 0 otherwise.] - - SideEffects [none] - - SeeAlso [Cudd_EnableReorderingReporting Cudd_DisableReorderingReporting] - -******************************************************************************/ -int -Cudd_ReorderingReporting( - DdManager *dd) -{ - return(Cudd_IsInHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)); - -} /* end of Cudd_ReorderingReporting */ - - -/**Function******************************************************************** - - Synopsis [Returns the code of the last error.] - - Description [Returns the code of the last error. The error codes are - defined in cudd.h.] - - SideEffects [None] - - SeeAlso [Cudd_ClearErrorCode] - -******************************************************************************/ -Cudd_ErrorType -Cudd_ReadErrorCode( - DdManager *dd) -{ - return(dd->errorCode); - -} /* end of Cudd_ReadErrorCode */ - - -/**Function******************************************************************** - - Synopsis [Clear the error code of a manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadErrorCode] - -******************************************************************************/ -void -Cudd_ClearErrorCode( - DdManager *dd) -{ - dd->errorCode = CUDD_NO_ERROR; - -} /* end of Cudd_ClearErrorCode */ - - -/**Function******************************************************************** - - Synopsis [Reads the stdout of a manager.] - - Description [Reads the stdout of a manager. This is the file pointer to - which messages normally going to stdout are written. It is initialized - to stdout. Cudd_SetStdout allows the application to redirect it.] - - SideEffects [None] - - SeeAlso [Cudd_SetStdout Cudd_ReadStderr] - -******************************************************************************/ -FILE * -Cudd_ReadStdout( - DdManager *dd) -{ - return(dd->out); - -} /* end of Cudd_ReadStdout */ - - -/**Function******************************************************************** - - Synopsis [Sets the stdout of a manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadStdout Cudd_SetStderr] - -******************************************************************************/ -void -Cudd_SetStdout( - DdManager *dd, - FILE *fp) -{ - dd->out = fp; - -} /* end of Cudd_SetStdout */ - - -/**Function******************************************************************** - - Synopsis [Reads the stderr of a manager.] - - Description [Reads the stderr of a manager. This is the file pointer to - which messages normally going to stderr are written. It is initialized - to stderr. Cudd_SetStderr allows the application to redirect it.] - - SideEffects [None] - - SeeAlso [Cudd_SetStderr Cudd_ReadStdout] - -******************************************************************************/ -FILE * -Cudd_ReadStderr( - DdManager *dd) -{ - return(dd->err); - -} /* end of Cudd_ReadStderr */ - - -/**Function******************************************************************** - - Synopsis [Sets the stderr of a manager.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_ReadStderr Cudd_SetStdout] - -******************************************************************************/ -void -Cudd_SetStderr( - DdManager *dd, - FILE *fp) -{ - dd->err = fp; - -} /* end of Cudd_SetStderr */ - - -/**Function******************************************************************** - - Synopsis [Returns the threshold for the next dynamic reordering.] - - Description [Returns the threshold for the next dynamic reordering. - The threshold is in terms of number of nodes and is in effect only - if reordering is enabled. The count does not include the dead nodes, - unless the countDead parameter of the manager has been changed from - its default setting.] - - SideEffects [None] - - SeeAlso [Cudd_SetNextReordering] - -******************************************************************************/ -unsigned int -Cudd_ReadNextReordering( - DdManager *dd) -{ - return(dd->nextDyn); - -} /* end of Cudd_ReadNextReordering */ - - -/**Function******************************************************************** - - Synopsis [Sets the threshold for the next dynamic reordering.] - - Description [Sets the threshold for the next dynamic reordering. - The threshold is in terms of number of nodes and is in effect only - if reordering is enabled. The count does not include the dead nodes, - unless the countDead parameter of the manager has been changed from - its default setting.] - - SideEffects [None] - - SeeAlso [Cudd_ReadNextReordering] - -******************************************************************************/ -void -Cudd_SetNextReordering( - DdManager *dd, - unsigned int next) -{ - dd->nextDyn = next; - -} /* end of Cudd_SetNextReordering */ - - -/**Function******************************************************************** - - Synopsis [Reads the number of elementary reordering steps.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -double -Cudd_ReadSwapSteps( - DdManager *dd) -{ -#ifdef DD_COUNT - return(dd->swapSteps); -#else - return(-1); -#endif - -} /* end of Cudd_ReadSwapSteps */ - - -/**Function******************************************************************** - - Synopsis [Reads the maximum allowed number of live nodes.] - - Description [Reads the maximum allowed number of live nodes. When this - number is exceeded, the package returns NULL.] - - SideEffects [none] - - SeeAlso [Cudd_SetMaxLive] - -******************************************************************************/ -unsigned int -Cudd_ReadMaxLive( - DdManager *dd) -{ - return(dd->maxLive); - -} /* end of Cudd_ReadMaxLive */ - - -/**Function******************************************************************** - - Synopsis [Sets the maximum allowed number of live nodes.] - - Description [Sets the maximum allowed number of live nodes. When this - number is exceeded, the package returns NULL.] - - SideEffects [none] - - SeeAlso [Cudd_ReadMaxLive] - -******************************************************************************/ -void -Cudd_SetMaxLive( - DdManager *dd, - unsigned int maxLive) -{ - dd->maxLive = maxLive; - -} /* end of Cudd_SetMaxLive */ - - -/**Function******************************************************************** - - Synopsis [Reads the maximum allowed memory.] - - Description [Reads the maximum allowed memory. When this - number is exceeded, the package returns NULL.] - - SideEffects [none] - - SeeAlso [Cudd_SetMaxMemory] - -******************************************************************************/ -long -Cudd_ReadMaxMemory( - DdManager *dd) -{ - return(dd->maxmemhard); - -} /* end of Cudd_ReadMaxMemory */ - - -/**Function******************************************************************** - - Synopsis [Sets the maximum allowed memory.] - - Description [Sets the maximum allowed memory. When this - number is exceeded, the package returns NULL.] - - SideEffects [none] - - SeeAlso [Cudd_ReadMaxMemory] - -******************************************************************************/ -void -Cudd_SetMaxMemory( - DdManager *dd, - long maxMemory) -{ - dd->maxmemhard = maxMemory; - -} /* end of Cudd_SetMaxMemory */ - - -/**Function******************************************************************** - - Synopsis [Prevents sifting of a variable.] - - Description [This function sets a flag to prevent sifting of a - variable. Returns 1 if successful; 0 otherwise (i.e., invalid - variable index).] - - SideEffects [Changes the "bindVar" flag in DdSubtable.] - - SeeAlso [Cudd_bddUnbindVar] - -******************************************************************************/ -int -Cudd_bddBindVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].bindVar = 1; - return(1); - -} /* end of Cudd_bddBindVar */ - - -/**Function******************************************************************** - - Synopsis [Allows the sifting of a variable.] - - Description [This function resets the flag that prevents the sifting - of a variable. In successive variable reorderings, the variable will - NOT be skipped, that is, sifted. Initially all variables can be - sifted. It is necessary to call this function only to re-enable - sifting after a call to Cudd_bddBindVar. Returns 1 if successful; 0 - otherwise (i.e., invalid variable index).] - - SideEffects [Changes the "bindVar" flag in DdSubtable.] - - SeeAlso [Cudd_bddBindVar] - -******************************************************************************/ -int -Cudd_bddUnbindVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].bindVar = 0; - return(1); - -} /* end of Cudd_bddUnbindVar */ - - -/**Function******************************************************************** - - Synopsis [Tells whether a variable can be sifted.] - - Description [This function returns 1 if a variable is enabled for - sifting. Initially all variables can be sifted. This function returns - 0 only if there has been a previous call to Cudd_bddBindVar for that - variable not followed by a call to Cudd_bddUnbindVar. The function returns - 0 also in the case in which the index of the variable is out of bounds.] - - SideEffects [none] - - SeeAlso [Cudd_bddBindVar Cudd_bddUnbindVar] - -******************************************************************************/ -int -Cudd_bddVarIsBound( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return(0); - return(dd->subtables[dd->perm[index]].bindVar); - -} /* end of Cudd_bddVarIsBound */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable type to primary input.] - - Description [Sets a variable type to primary input. The variable type is - used by lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetPsVar Cudd_bddSetNsVar Cudd_bddIsPiVar] - -******************************************************************************/ -int -Cudd_bddSetPiVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return (0); - dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRIMARY_INPUT; - return(1); - -} /* end of Cudd_bddSetPiVar */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable type to present state.] - - Description [Sets a variable type to present state. The variable type is - used by lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetPiVar Cudd_bddSetNsVar Cudd_bddIsPsVar] - -******************************************************************************/ -int -Cudd_bddSetPsVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return (0); - dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRESENT_STATE; - return(1); - -} /* end of Cudd_bddSetPsVar */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable type to next state.] - - Description [Sets a variable type to next state. The variable type is - used by lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetPiVar Cudd_bddSetPsVar Cudd_bddIsNsVar] - -******************************************************************************/ -int -Cudd_bddSetNsVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return (0); - dd->subtables[dd->perm[index]].varType = CUDD_VAR_NEXT_STATE; - return(1); - -} /* end of Cudd_bddSetNsVar */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is primary input.] - - Description [Checks whether a variable is primary input. Returns 1 if - the variable's type is primary input; 0 if the variable exists but is - not a primary input; -1 if the variable does not exist.] - - SideEffects [none] - - SeeAlso [Cudd_bddSetPiVar Cudd_bddIsPsVar Cudd_bddIsNsVar] - -******************************************************************************/ -int -Cudd_bddIsPiVar( - DdManager *dd /* manager */, - int index /* variable index */) -{ - if (index >= dd->size || index < 0) return -1; - return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRIMARY_INPUT); - -} /* end of Cudd_bddIsPiVar */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is present state.] - - Description [Checks whether a variable is present state. Returns 1 if - the variable's type is present state; 0 if the variable exists but is - not a present state; -1 if the variable does not exist.] - - SideEffects [none] - - SeeAlso [Cudd_bddSetPsVar Cudd_bddIsPiVar Cudd_bddIsNsVar] - -******************************************************************************/ -int -Cudd_bddIsPsVar( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return -1; - return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRESENT_STATE); - -} /* end of Cudd_bddIsPsVar */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is next state.] - - Description [Checks whether a variable is next state. Returns 1 if - the variable's type is present state; 0 if the variable exists but is - not a present state; -1 if the variable does not exist.] - - SideEffects [none] - - SeeAlso [Cudd_bddSetNsVar Cudd_bddIsPiVar Cudd_bddIsPsVar] - -******************************************************************************/ -int -Cudd_bddIsNsVar( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return -1; - return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_NEXT_STATE); - -} /* end of Cudd_bddIsNsVar */ - - -/**Function******************************************************************** - - Synopsis [Sets a corresponding pair index for a given index.] - - Description [Sets a corresponding pair index for a given index. - These pair indices are present and next state variable. Returns 1 if - successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddReadPairIndex] - -******************************************************************************/ -int -Cudd_bddSetPairIndex( - DdManager *dd /* manager */, - int index /* variable index */, - int pairIndex /* corresponding variable index */) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].pairIndex = pairIndex; - return(1); - -} /* end of Cudd_bddSetPairIndex */ - - -/**Function******************************************************************** - - Synopsis [Reads a corresponding pair index for a given index.] - - Description [Reads a corresponding pair index for a given index. - These pair indices are present and next state variable. Returns the - corresponding variable index if the variable exists; -1 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetPairIndex] - -******************************************************************************/ -int -Cudd_bddReadPairIndex( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return -1; - return dd->subtables[dd->perm[index]].pairIndex; - -} /* end of Cudd_bddReadPairIndex */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable to be grouped.] - - Description [Sets a variable to be grouped. This function is used for - lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetVarHardGroup Cudd_bddResetVarToBeGrouped] - -******************************************************************************/ -int -Cudd_bddSetVarToBeGrouped( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - if (dd->subtables[dd->perm[index]].varToBeGrouped <= CUDD_LAZY_SOFT_GROUP) { - dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_SOFT_GROUP; - } - return(1); - -} /* end of Cudd_bddSetVarToBeGrouped */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable to be a hard group.] - - Description [Sets a variable to be a hard group. This function is used - for lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetVarToBeGrouped Cudd_bddResetVarToBeGrouped - Cudd_bddIsVarHardGroup] - -******************************************************************************/ -int -Cudd_bddSetVarHardGroup( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_HARD_GROUP; - return(1); - -} /* end of Cudd_bddSetVarHardGrouped */ - - -/**Function******************************************************************** - - Synopsis [Resets a variable not to be grouped.] - - Description [Resets a variable not to be grouped. This function is - used for lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddSetVarToBeGrouped Cudd_bddSetVarHardGroup] - -******************************************************************************/ -int -Cudd_bddResetVarToBeGrouped( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - if (dd->subtables[dd->perm[index]].varToBeGrouped <= - CUDD_LAZY_SOFT_GROUP) { - dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_NONE; - } - return(1); - -} /* end of Cudd_bddResetVarToBeGrouped */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is set to be grouped.] - - Description [Checks whether a variable is set to be grouped. This - function is used for lazy sifting.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_bddIsVarToBeGrouped( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(-1); - if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP) - return(0); - else - return(dd->subtables[dd->perm[index]].varToBeGrouped); - -} /* end of Cudd_bddIsVarToBeGrouped */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable to be ungrouped.] - - Description [Sets a variable to be ungrouped. This function is used - for lazy sifting. Returns 1 if successful; 0 otherwise.] - - SideEffects [modifies the manager] - - SeeAlso [Cudd_bddIsVarToBeUngrouped] - -******************************************************************************/ -int -Cudd_bddSetVarToBeUngrouped( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_UNGROUP; - return(1); - -} /* end of Cudd_bddSetVarToBeGrouped */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is set to be ungrouped.] - - Description [Checks whether a variable is set to be ungrouped. This - function is used for lazy sifting. Returns 1 if the variable is marked - to be ungrouped; 0 if the variable exists, but it is not marked to be - ungrouped; -1 if the variable does not exist.] - - SideEffects [none] - - SeeAlso [Cudd_bddSetVarToBeUngrouped] - -******************************************************************************/ -int -Cudd_bddIsVarToBeUngrouped( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(-1); - return dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP; - -} /* end of Cudd_bddIsVarToBeGrouped */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is set to be in a hard group.] - - Description [Checks whether a variable is set to be in a hard group. This - function is used for lazy sifting. Returns 1 if the variable is marked - to be in a hard group; 0 if the variable exists, but it is not marked to be - in a hard group; -1 if the variable does not exist.] - - SideEffects [none] - - SeeAlso [Cudd_bddSetVarHardGroup] - -******************************************************************************/ -int -Cudd_bddIsVarHardGroup( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(-1); - if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_HARD_GROUP) - return(1); - return(0); - -} /* end of Cudd_bddIsVarToBeGrouped */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Fixes a variable group tree.] - - Description [] - - SideEffects [Changes the variable group tree.] - - SeeAlso [] - -******************************************************************************/ -static void -fixVarTree( - MtrNode * treenode, - int * perm, - int size) -{ - treenode->index = treenode->low; - treenode->low = ((int) treenode->index < size) ? - perm[treenode->index] : treenode->index; - if (treenode->child != NULL) - fixVarTree(treenode->child, perm, size); - if (treenode->younger != NULL) - fixVarTree(treenode->younger, perm, size); - return; - -} /* end of fixVarTree */ - - -/**Function******************************************************************** - - Synopsis [Adds multiplicity groups to a ZDD variable group tree.] - - Description [Adds multiplicity groups to a ZDD variable group tree. - Returns 1 if successful; 0 otherwise. This function creates the groups - for set of ZDD variables (whose cardinality is given by parameter - multiplicity) that are created for each BDD variable in - Cudd_zddVarsFromBddVars. The crux of the matter is to determine the index - each new group. (The index of the first variable in the group.) - We first build all the groups for the children of a node, and then deal - with the ZDD variables that are directly attached to the node. The problem - for these is that the tree itself does not provide information on their - position inside the group. While we deal with the children of the node, - therefore, we keep track of all the positions they occupy. The remaining - positions in the tree can be freely used. Also, we keep track of all the - variables placed in the children. All the remaining variables are directly - attached to the group. We can then place any pair of variables not yet - grouped in any pair of available positions in the node.] - - SideEffects [Changes the variable group tree.] - - SeeAlso [Cudd_zddVarsFromBddVars] - -******************************************************************************/ -static int -addMultiplicityGroups( - DdManager *dd /* manager */, - MtrNode *treenode /* current tree node */, - int multiplicity /* how many ZDD vars per BDD var */, - char *vmask /* variable pairs for which a group has been already built */, - char *lmask /* levels for which a group has already been built*/) -{ - int startV, stopV, startL; - int i, j; - MtrNode *auxnode = treenode; - - while (auxnode != NULL) { - if (auxnode->child != NULL) { - addMultiplicityGroups(dd,auxnode->child,multiplicity,vmask,lmask); - } - /* Build remaining groups. */ - startV = dd->permZ[auxnode->index] / multiplicity; - startL = auxnode->low / multiplicity; - stopV = startV + auxnode->size / multiplicity; - /* Walk down vmask starting at startV and build missing groups. */ - for (i = startV, j = startL; i < stopV; i++) { - if (vmask[i] == 0) { - MtrNode *node; - while (lmask[j] == 1) j++; - node = Mtr_MakeGroup(auxnode, j * multiplicity, multiplicity, - MTR_FIXED); - if (node == NULL) { - return(0); - } - node->index = dd->invpermZ[i * multiplicity]; - vmask[i] = 1; - lmask[j] = 1; - } - } - auxnode = auxnode->younger; - } - return(1); - -} /* end of addMultiplicityGroups */ - diff --git a/src/bdd/cudd/cuddAddAbs.c b/src/bdd/cudd/cuddAddAbs.c deleted file mode 100644 index b256ad0f..00000000 --- a/src/bdd/cudd/cuddAddAbs.c +++ /dev/null @@ -1,566 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddAbs.c] - - PackageName [cudd] - - Synopsis [Quantification functions for ADDs.] - - Description [External procedures included in this module: -
          -
        • Cudd_addExistAbstract() -
        • Cudd_addUnivAbstract() -
        • Cudd_addOrAbstract() -
        - Internal procedures included in this module: -
          -
        • cuddAddExistAbstractRecur() -
        • cuddAddUnivAbstractRecur() -
        • cuddAddOrAbstractRecur() -
        - Static procedures included in this module: -
          -
        • addCheckPositiveCube() -
        ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddAbs.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - -static DdNode *two; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int addCheckPositiveCube ARGS((DdManager *manager, DdNode *cube)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Existentially Abstracts all the variables in cube from f.] - - Description [Abstracts all the variables in cube from f by summing - over all possible values taken by the variables. Returns the - abstracted ADD.] - - SideEffects [None] - - SeeAlso [Cudd_addUnivAbstract Cudd_bddExistAbstract - Cudd_addOrAbstract] - -******************************************************************************/ -DdNode * -Cudd_addExistAbstract( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *res; - - two = cuddUniqueConst(manager,(CUDD_VALUE_TYPE) 2); - if (two == NULL) return(NULL); - cuddRef(two); - - if (addCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err,"Error: Can only abstract cubes"); - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddAddExistAbstractRecur(manager, f, cube); - } while (manager->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(manager,two); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,two); - cuddDeref(res); - - return(res); - -} /* end of Cudd_addExistAbstract */ - - -/**Function******************************************************************** - - Synopsis [Universally Abstracts all the variables in cube from f.] - - Description [Abstracts all the variables in cube from f by taking - the product over all possible values taken by the variable. Returns - the abstracted ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addExistAbstract Cudd_bddUnivAbstract - Cudd_addOrAbstract] - -******************************************************************************/ -DdNode * -Cudd_addUnivAbstract( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *res; - - if (addCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err,"Error: Can only abstract cubes"); - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddAddUnivAbstractRecur(manager, f, cube); - } while (manager->reordered == 1); - - return(res); - -} /* end of Cudd_addUnivAbstract */ - - -/**Function******************************************************************** - - Synopsis [Disjunctively abstracts all the variables in cube from the - 0-1 ADD f.] - - Description [Abstracts all the variables in cube from the 0-1 ADD f - by taking the disjunction over all possible values taken by the - variables. Returns the abstracted ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addUnivAbstract Cudd_addExistAbstract] - -******************************************************************************/ -DdNode * -Cudd_addOrAbstract( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *res; - - if (addCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err,"Error: Can only abstract cubes"); - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddAddOrAbstractRecur(manager, f, cube); - } while (manager->reordered == 1); - return(res); - -} /* end of Cudd_addOrAbstract */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addExistAbstract.] - - Description [Performs the recursive step of Cudd_addExistAbstract. - Returns the ADD obtained by abstracting the variables of cube from f, - if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddAddExistAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *T, *E, *res, *res1, *res2, *zero; - - statLine(manager); - zero = DD_ZERO(manager); - - /* Cube is guaranteed to be a cube at this point. */ - if (f == zero || cuddIsConstant(cube)) { - return(f); - } - - /* Abstract a variable that does not appear in f => multiply by 2. */ - if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { - res1 = cuddAddExistAbstractRecur(manager, f, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - /* Use the "internal" procedure to be alerted in case of - ** dynamic reordering. If dynamic reordering occurs, we - ** have to abort the entire abstraction. - */ - res = cuddAddApplyRecur(manager,Cudd_addTimes,res1,two); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - cuddDeref(res); - return(res); - } - - if ((res = cuddCacheLookup2(manager, Cudd_addExistAbstract, f, cube)) != NULL) { - return(res); - } - - T = cuddT(f); - E = cuddE(f); - - /* If the two indices are the same, so are their levels. */ - if (f->index == cube->index) { - res1 = cuddAddExistAbstractRecur(manager, T, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddAddExistAbstractRecur(manager, E, cuddT(cube)); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = cuddAddApplyRecur(manager, Cudd_addPlus, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res); - cuddDeref(res); - return(res); - } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ - res1 = cuddAddExistAbstractRecur(manager, T, cube); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddAddExistAbstractRecur(manager, E, cube); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = (res1 == res2) ? res1 : - cuddUniqueInter(manager, (int) f->index, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - cuddCacheInsert2(manager, Cudd_addExistAbstract, f, cube, res); - return(res); - } - -} /* end of cuddAddExistAbstractRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addUnivAbstract.] - - Description [Performs the recursive step of Cudd_addUnivAbstract. - Returns the ADD obtained by abstracting the variables of cube from f, - if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddAddUnivAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *T, *E, *res, *res1, *res2, *one, *zero; - - statLine(manager); - one = DD_ONE(manager); - zero = DD_ZERO(manager); - - /* Cube is guaranteed to be a cube at this point. - ** zero and one are the only constatnts c such that c*c=c. - */ - if (f == zero || f == one || cube == one) { - return(f); - } - - /* Abstract a variable that does not appear in f. */ - if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { - res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - /* Use the "internal" procedure to be alerted in case of - ** dynamic reordering. If dynamic reordering occurs, we - ** have to abort the entire abstraction. - */ - res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - cuddDeref(res); - return(res); - } - - if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) { - return(res); - } - - T = cuddT(f); - E = cuddE(f); - - /* If the two indices are the same, so are their levels. */ - if (f->index == cube->index) { - res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube)); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); - cuddDeref(res); - return(res); - } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ - res1 = cuddAddUnivAbstractRecur(manager, T, cube); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddAddUnivAbstractRecur(manager, E, cube); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = (res1 == res2) ? res1 : - cuddUniqueInter(manager, (int) f->index, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); - return(res); - } - -} /* end of cuddAddUnivAbstractRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addOrAbstract.] - - Description [Performs the recursive step of Cudd_addOrAbstract. - Returns the ADD obtained by abstracting the variables of cube from f, - if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddAddOrAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *T, *E, *res, *res1, *res2, *one; - - statLine(manager); - one = DD_ONE(manager); - - /* Cube is guaranteed to be a cube at this point. */ - if (cuddIsConstant(f) || cube == one) { - return(f); - } - - /* Abstract a variable that does not appear in f. */ - if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { - res1 = cuddAddOrAbstractRecur(manager, f, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - /* Use the "internal" procedure to be alerted in case of - ** dynamic reordering. If dynamic reordering occurs, we - ** have to abort the entire abstraction. - */ - res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res1); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - cuddDeref(res); - return(res); - } - - if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) { - return(res); - } - - T = cuddT(f); - E = cuddE(f); - - /* If the two indices are the same, so are their levels. */ - if (f->index == cube->index) { - res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - if (res1 != one) { - res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube)); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - } else { - res = res1; - } - cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); - cuddDeref(res); - return(res); - } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ - res1 = cuddAddOrAbstractRecur(manager, T, cube); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddAddOrAbstractRecur(manager, E, cube); - if (res2 == NULL) { - Cudd_RecursiveDeref(manager,res1); - return(NULL); - } - cuddRef(res2); - res = (res1 == res2) ? res1 : - cuddUniqueInter(manager, (int) f->index, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(manager,res1); - Cudd_RecursiveDeref(manager,res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); - return(res); - } - -} /* end of cuddAddOrAbstractRecur */ - - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Checks whether cube is an ADD representing the product - of positive literals.] - - Description [Checks whether cube is an ADD representing the product of - positive literals. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -addCheckPositiveCube( - DdManager * manager, - DdNode * cube) -{ - if (Cudd_IsComplement(cube)) return(0); - if (cube == DD_ONE(manager)) return(1); - if (cuddIsConstant(cube)) return(0); - if (cuddE(cube) == DD_ZERO(manager)) { - return(addCheckPositiveCube(manager, cuddT(cube))); - } - return(0); - -} /* end of addCheckPositiveCube */ - diff --git a/src/bdd/cudd/cuddAddApply.c b/src/bdd/cudd/cuddAddApply.c deleted file mode 100644 index 60c06de6..00000000 --- a/src/bdd/cudd/cuddAddApply.c +++ /dev/null @@ -1,917 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddApply.c] - - PackageName [cudd] - - Synopsis [Apply functions for ADDs and their operators.] - - Description [External procedures included in this module: -
          -
        • Cudd_addApply() -
        • Cudd_addMonadicApply() -
        • Cudd_addPlus() -
        • Cudd_addTimes() -
        • Cudd_addThreshold() -
        • Cudd_addSetNZ() -
        • Cudd_addDivide() -
        • Cudd_addMinus() -
        • Cudd_addMinimum() -
        • Cudd_addMaximum() -
        • Cudd_addOneZeroMaximum() -
        • Cudd_addDiff() -
        • Cudd_addAgreement() -
        • Cudd_addOr() -
        • Cudd_addNand() -
        • Cudd_addNor() -
        • Cudd_addXor() -
        • Cudd_addXnor() -
        - Internal procedures included in this module: -
          -
        • cuddAddApplyRecur() -
        • cuddAddMonadicApplyRecur() -
        ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at Boulder. - The University of Colorado at Boulder makes no warranty about the - suitability of this software for any purpose. It is presented on an - AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddApply.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Applies op to the corresponding discriminants of f and g.] - - Description [Applies op to the corresponding discriminants of f and g. - Returns a pointer to the result if succssful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes - Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum - Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement - Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor] - -******************************************************************************/ -DdNode * -Cudd_addApply( - DdManager * dd, - DdNode * (*op)(DdManager *, DdNode **, DdNode **), - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddApplyRecur(dd,op,f,g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addApply */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point addition.] - - Description [Integer and floating point addition. Returns NULL if not - a terminal case; f+g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addPlus( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *res; - DdNode *F, *G; - CUDD_VALUE_TYPE value; - - F = *f; G = *g; - if (F == DD_ZERO(dd)) return(G); - if (G == DD_ZERO(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - value = cuddV(F)+cuddV(G); - res = cuddUniqueConst(dd,value); - return(res); - } - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addPlus */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point multiplication.] - - Description [Integer and floating point multiplication. Returns NULL - if not a terminal case; f * g otherwise. This function can be used also - to take the AND of two 0-1 ADDs.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addTimes( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *res; - DdNode *F, *G; - CUDD_VALUE_TYPE value; - - F = *f; G = *g; - if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd)); - if (F == DD_ONE(dd)) return(G); - if (G == DD_ONE(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - value = cuddV(F)*cuddV(G); - res = cuddUniqueConst(dd,value); - return(res); - } - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addTimes */ - - -/**Function******************************************************************** - - Synopsis [f if f>=g; 0 if f<g.] - - Description [Threshold operator for Apply (f if f >=g; 0 if f<g). - Returns NULL if not a terminal case; f op g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addThreshold( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G || F == DD_PLUS_INFINITY(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - if (cuddV(F) >= cuddV(G)) { - return(F); - } else { - return(DD_ZERO(dd)); - } - } - return(NULL); - -} /* end of Cudd_addThreshold */ - - -/**Function******************************************************************** - - Synopsis [This operator sets f to the value of g wherever g != 0.] - - Description [This operator sets f to the value of g wherever g != 0. - Returns NULL if not a terminal case; f op g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addSetNZ( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(F); - if (F == DD_ZERO(dd)) return(G); - if (G == DD_ZERO(dd)) return(F); - if (cuddIsConstant(G)) return(G); - return(NULL); - -} /* end of Cudd_addSetNZ */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point division.] - - Description [Integer and floating point division. Returns NULL if not - a terminal case; f / g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addDivide( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *res; - DdNode *F, *G; - CUDD_VALUE_TYPE value; - - F = *f; G = *g; - /* We would like to use F == G -> F/G == 1, but F and G may - ** contain zeroes. */ - if (F == DD_ZERO(dd)) return(DD_ZERO(dd)); - if (G == DD_ONE(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - value = cuddV(F)/cuddV(G); - res = cuddUniqueConst(dd,value); - return(res); - } - return(NULL); - -} /* end of Cudd_addDivide */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point subtraction.] - - Description [Integer and floating point subtraction. Returns NULL if - not a terminal case; f - g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addMinus( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *res; - DdNode *F, *G; - CUDD_VALUE_TYPE value; - - F = *f; G = *g; - if (F == G) return(DD_ZERO(dd)); - if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G)); - if (G == DD_ZERO(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - value = cuddV(F)-cuddV(G); - res = cuddUniqueConst(dd,value); - return(res); - } - return(NULL); - -} /* end of Cudd_addMinus */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point min.] - - Description [Integer and floating point min for Cudd_addApply. - Returns NULL if not a terminal case; min(f,g) otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addMinimum( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == DD_PLUS_INFINITY(dd)) return(G); - if (G == DD_PLUS_INFINITY(dd)) return(F); - if (F == G) return(F); -#if 0 - /* These special cases probably do not pay off. */ - if (F == DD_MINUS_INFINITY(dd)) return(F); - if (G == DD_MINUS_INFINITY(dd)) return(G); -#endif - if (cuddIsConstant(F) && cuddIsConstant(G)) { - if (cuddV(F) <= cuddV(G)) { - return(F); - } else { - return(G); - } - } - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addMinimum */ - - -/**Function******************************************************************** - - Synopsis [Integer and floating point max.] - - Description [Integer and floating point max for Cudd_addApply. - Returns NULL if not a terminal case; max(f,g) otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addMaximum( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(F); - if (F == DD_MINUS_INFINITY(dd)) return(G); - if (G == DD_MINUS_INFINITY(dd)) return(F); -#if 0 - /* These special cases probably do not pay off. */ - if (F == DD_PLUS_INFINITY(dd)) return(F); - if (G == DD_PLUS_INFINITY(dd)) return(G); -#endif - if (cuddIsConstant(F) && cuddIsConstant(G)) { - if (cuddV(F) >= cuddV(G)) { - return(F); - } else { - return(G); - } - } - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addMaximum */ - - -/**Function******************************************************************** - - Synopsis [Returns 1 if f > g and 0 otherwise.] - - Description [Returns 1 if f > g and 0 otherwise. Used in - conjunction with Cudd_addApply. Returns NULL if not a terminal - case.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addOneZeroMaximum( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - - if (*f == *g) return(DD_ZERO(dd)); - if (*g == DD_PLUS_INFINITY(dd)) - return DD_ZERO(dd); - if (cuddIsConstant(*f) && cuddIsConstant(*g)) { - if (cuddV(*f) > cuddV(*g)) { - return(DD_ONE(dd)); - } else { - return(DD_ZERO(dd)); - } - } - - return(NULL); - -} /* end of Cudd_addOneZeroMaximum */ - - -/**Function******************************************************************** - - Synopsis [Returns plusinfinity if f=g; returns min(f,g) if f!=g.] - - Description [Returns NULL if not a terminal case; f op g otherwise, - where f op g is plusinfinity if f=g; min(f,g) if f!=g.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addDiff( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(DD_PLUS_INFINITY(dd)); - if (F == DD_PLUS_INFINITY(dd)) return(G); - if (G == DD_PLUS_INFINITY(dd)) return(F); - if (cuddIsConstant(F) && cuddIsConstant(G)) { - if (cuddV(F) != cuddV(G)) { - if (cuddV(F) < cuddV(G)) { - return(F); - } else { - return(G); - } - } else { - return(DD_PLUS_INFINITY(dd)); - } - } - return(NULL); - -} /* end of Cudd_addDiff */ - - -/**Function******************************************************************** - - Synopsis [f if f==g; background if f!=g.] - - Description [Returns NULL if not a terminal case; f op g otherwise, - where f op g is f if f==g; background if f!=g.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addAgreement( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(F); - if (F == dd->background) return(F); - if (G == dd->background) return(G); - if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background); - return(NULL); - -} /* end of Cudd_addAgreement */ - - -/**Function******************************************************************** - - Synopsis [Disjunction of two 0-1 ADDs.] - - Description [Disjunction of two 0-1 ADDs. Returns NULL - if not a terminal case; f OR g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addOr( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd)); - if (cuddIsConstant(F)) return(G); - if (cuddIsConstant(G)) return(F); - if (F == G) return(F); - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addOr */ - - -/**Function******************************************************************** - - Synopsis [NAND of two 0-1 ADDs.] - - Description [NAND of two 0-1 ADDs. Returns NULL - if not a terminal case; f NAND g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addNand( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd)); - if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addNand */ - - -/**Function******************************************************************** - - Synopsis [NOR of two 0-1 ADDs.] - - Description [NOR of two 0-1 ADDs. Returns NULL - if not a terminal case; f NOR g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addNor( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd)); - if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd)); - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addNor */ - - -/**Function******************************************************************** - - Synopsis [XOR of two 0-1 ADDs.] - - Description [XOR of two 0-1 ADDs. Returns NULL - if not a terminal case; f XOR g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addXor( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(DD_ZERO(dd)); - if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd)); - if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd)); - if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addXor */ - - -/**Function******************************************************************** - - Synopsis [XNOR of two 0-1 ADDs.] - - Description [XNOR of two 0-1 ADDs. Returns NULL - if not a terminal case; f XNOR g otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addXnor( - DdManager * dd, - DdNode ** f, - DdNode ** g) -{ - DdNode *F, *G; - - F = *f; G = *g; - if (F == G) return(DD_ONE(dd)); - if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd)); - if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd)); - if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd)); - if (F > G) { /* swap f and g */ - *f = G; - *g = F; - } - return(NULL); - -} /* end of Cudd_addXnor */ - - -/**Function******************************************************************** - - Synopsis [Applies op to the discriminants of f.] - - Description [Applies op to the discriminants of f. - Returns a pointer to the result if succssful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addApply Cudd_addLog] - -******************************************************************************/ -DdNode * -Cudd_addMonadicApply( - DdManager * dd, - DdNode * (*op)(DdManager *, DdNode *), - DdNode * f) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddMonadicApplyRecur(dd,op,f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addMonadicApply */ - - -/**Function******************************************************************** - - Synopsis [Natural logarithm of an ADD.] - - Description [Natural logarithm of an ADDs. Returns NULL - if not a terminal case; log(f) otherwise. The discriminants of f must - be positive double's.] - - SideEffects [None] - - SeeAlso [Cudd_addMonadicApply] - -******************************************************************************/ -DdNode * -Cudd_addLog( - DdManager * dd, - DdNode * f) -{ - if (cuddIsConstant(f)) { - CUDD_VALUE_TYPE value = log(cuddV(f)); - DdNode *res = cuddUniqueConst(dd,value); - return(res); - } - return(NULL); - -} /* end of Cudd_addLog */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addApply.] - - Description [Performs the recursive step of Cudd_addApply. Returns a - pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddAddMonadicApplyRecur] - -******************************************************************************/ -DdNode * -cuddAddApplyRecur( - DdManager * dd, - DdNode * (*op)(DdManager *, DdNode **, DdNode **), - DdNode * f, - DdNode * g) -{ - DdNode *res, - *fv, *fvn, *gv, *gvn, - *T, *E; - unsigned int ford, gord; - unsigned int index; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - - /* Check terminal cases. Op may swap f and g to increase the - * cache hit rate. - */ - statLine(dd); - res = (*op)(dd,&f,&g); - if (res != NULL) return(res); - - /* Check cache. */ - cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) op; - res = cuddCacheLookup2(dd,cacheOp,f,g); - if (res != NULL) return(res); - - /* Recursive step. */ - ford = cuddI(dd,f->index); - gord = cuddI(dd,g->index); - if (ford <= gord) { - index = f->index; - fv = cuddT(f); - fvn = cuddE(f); - } else { - index = g->index; - fv = fvn = f; - } - if (gord <= ford) { - gv = cuddT(g); - gvn = cuddE(g); - } else { - gv = gvn = g; - } - - T = cuddAddApplyRecur(dd,op,fv,gv); - if (T == NULL) return(NULL); - cuddRef(T); - - E = cuddAddApplyRecur(dd,op,fvn,gvn); - if (E == NULL) { - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - - res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert2(dd,cacheOp,f,g,res); - - return(res); - -} /* end of cuddAddApplyRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addMonadicApply.] - - Description [Performs the recursive step of Cudd_addMonadicApply. Returns a - pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddAddApplyRecur] - -******************************************************************************/ -DdNode * -cuddAddMonadicApplyRecur( - DdManager * dd, - DdNode * (*op)(DdManager *, DdNode *), - DdNode * f) -{ - DdNode *res, *ft, *fe, *T, *E; - unsigned int ford; - unsigned int index; - - /* Check terminal cases. */ - statLine(dd); - res = (*op)(dd,f); - if (res != NULL) return(res); - - /* Check cache. */ - res = cuddCacheLookup1(dd,op,f); - if (res != NULL) return(res); - - /* Recursive step. */ - ford = cuddI(dd,f->index); - index = f->index; - ft = cuddT(f); - fe = cuddE(f); - - T = cuddAddMonadicApplyRecur(dd,op,ft); - if (T == NULL) return(NULL); - cuddRef(T); - - E = cuddAddMonadicApplyRecur(dd,op,fe); - if (E == NULL) { - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - - res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert1(dd,op,f,res); - - return(res); - -} /* end of cuddAddMonadicApplyRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddAddFind.c b/src/bdd/cudd/cuddAddFind.c deleted file mode 100644 index 0469b014..00000000 --- a/src/bdd/cudd/cuddAddFind.c +++ /dev/null @@ -1,283 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddFind.c] - - PackageName [cudd] - - Synopsis [Functions to find maximum and minimum in an ADD and to - extract the i-th bit.] - - Description [External procedures included in this module: -
          -
        • Cudd_addFindMax() -
        • Cudd_addFindMin() -
        • Cudd_addIthBit() -
        - Static functions included in this module: -
          -
        • addDoIthBit() -
        ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddFind.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * addDoIthBit ARGS((DdManager *dd, DdNode *f, DdNode *index)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Finds the maximum discriminant of f.] - - Description [Returns a pointer to a constant ADD.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_addFindMax( - DdManager * dd, - DdNode * f) -{ - DdNode *t, *e, *res; - - statLine(dd); - if (cuddIsConstant(f)) { - return(f); - } - - res = cuddCacheLookup1(dd,Cudd_addFindMax,f); - if (res != NULL) { - return(res); - } - - t = Cudd_addFindMax(dd,cuddT(f)); - if (t == DD_PLUS_INFINITY(dd)) return(t); - - e = Cudd_addFindMax(dd,cuddE(f)); - - res = (cuddV(t) >= cuddV(e)) ? t : e; - - cuddCacheInsert1(dd,Cudd_addFindMax,f,res); - - return(res); - -} /* end of Cudd_addFindMax */ - - -/**Function******************************************************************** - - Synopsis [Finds the minimum discriminant of f.] - - Description [Returns a pointer to a constant ADD.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_addFindMin( - DdManager * dd, - DdNode * f) -{ - DdNode *t, *e, *res; - - statLine(dd); - if (cuddIsConstant(f)) { - return(f); - } - - res = cuddCacheLookup1(dd,Cudd_addFindMin,f); - if (res != NULL) { - return(res); - } - - t = Cudd_addFindMin(dd,cuddT(f)); - if (t == DD_MINUS_INFINITY(dd)) return(t); - - e = Cudd_addFindMin(dd,cuddE(f)); - - res = (cuddV(t) <= cuddV(e)) ? t : e; - - cuddCacheInsert1(dd,Cudd_addFindMin,f,res); - - return(res); - -} /* end of Cudd_addFindMin */ - - -/**Function******************************************************************** - - Synopsis [Extracts the i-th bit from an ADD.] - - Description [Produces an ADD from another ADD by replacing all - discriminants whose i-th bit is equal to 1 with 1, and all other - discriminants with 0. The i-th bit refers to the integer - representation of the leaf value. If the value is has a fractional - part, it is ignored. Repeated calls to this procedure allow one to - transform an integer-valued ADD into an array of ADDs, one for each - bit of the leaf values. Returns a pointer to the resulting ADD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddIthBit] - -******************************************************************************/ -DdNode * -Cudd_addIthBit( - DdManager * dd, - DdNode * f, - int bit) -{ - DdNode *res; - DdNode *index; - - /* Use a constant node to remember the bit, so that we can use the - ** global cache. - */ - index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit); - if (index == NULL) return(NULL); - cuddRef(index); - - do { - dd->reordered = 0; - res = addDoIthBit(dd, f, index); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd, index); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, index); - cuddDeref(res); - return(res); - -} /* end of Cudd_addIthBit */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addIthBit.] - - Description [Performs the recursive step for Cudd_addIthBit. - Returns a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -addDoIthBit( - DdManager * dd, - DdNode * f, - DdNode * index) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int mask, value; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - mask = 1 << ((int) cuddV(index)); - value = (int) cuddV(f); - return((value & mask) == 0 ? DD_ZERO(dd) : DD_ONE(dd)); - } - - /* Check cache. */ - res = cuddCacheLookup2(dd,addDoIthBit,f,index); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = addDoIthBit(dd,fv,index); - if (T == NULL) return(NULL); - cuddRef(T); - - E = addDoIthBit(dd,fvn,index); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert2(dd,addDoIthBit,f,index,res); - - return(res); - -} /* end of addDoIthBit */ - diff --git a/src/bdd/cudd/cuddAddInv.c b/src/bdd/cudd/cuddAddInv.c deleted file mode 100644 index fc4a340b..00000000 --- a/src/bdd/cudd/cuddAddInv.c +++ /dev/null @@ -1,172 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddInv.c] - - PackageName [cudd] - - Synopsis [Function to compute the scalar inverse of an ADD.] - - Description [External procedures included in this module: -
          -
        • Cudd_addScalarInverse() -
        - Internal procedures included in this module: -
          -
        • cuddAddScalarInverseRecur() -
        ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddInv.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the scalar inverse of an ADD.] - - Description [Computes an n ADD where the discriminants are the - multiplicative inverses of the corresponding discriminants of the - argument ADD. Returns a pointer to the resulting ADD in case of - success. Returns NULL if any discriminants smaller than epsilon is - encountered.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_addScalarInverse( - DdManager * dd, - DdNode * f, - DdNode * epsilon) -{ - DdNode *res; - - if (!cuddIsConstant(epsilon)) { - (void) fprintf(dd->err,"Invalid epsilon\n"); - return(NULL); - } - do { - dd->reordered = 0; - res = cuddAddScalarInverseRecur(dd,f,epsilon); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addScalarInverse */ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of addScalarInverse.] - - Description [Returns a pointer to the resulting ADD in case of - success. Returns NULL if any discriminants smaller than epsilon is - encountered.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -cuddAddScalarInverseRecur( - DdManager * dd, - DdNode * f, - DdNode * epsilon) -{ - DdNode *t, *e, *res; - CUDD_VALUE_TYPE value; - - statLine(dd); - if (cuddIsConstant(f)) { - if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL); - value = 1.0 / cuddV(f); - res = cuddUniqueConst(dd,value); - return(res); - } - - res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon); - if (res != NULL) return(res); - - t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon); - if (t == NULL) return(NULL); - cuddRef(t); - - e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddRef(e); - - res = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - - cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res); - - return(res); - -} /* end of cuddAddScalarInverseRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddAddIte.c b/src/bdd/cudd/cuddAddIte.c deleted file mode 100644 index 71f8070f..00000000 --- a/src/bdd/cudd/cuddAddIte.c +++ /dev/null @@ -1,613 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddIte.c] - - PackageName [cudd] - - Synopsis [ADD ITE function and satellites.] - - Description [External procedures included in this module: -
          -
        • Cudd_addIte() -
        • Cudd_addIteConstant() -
        • Cudd_addEvalConst() -
        • Cudd_addCmpl() -
        • Cudd_addLeq() -
        - Internal procedures included in this module: -
          -
        • cuddAddIteRecur() -
        • cuddAddCmplRecur() -
        - Static procedures included in this module: -
          -
        • addVarToConst() -
        ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddIte.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void addVarToConst ARGS((DdNode *f, DdNode **gp, DdNode **hp, DdNode *one, DdNode *zero)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements ITE(f,g,h).] - - Description [Implements ITE(f,g,h). This procedure assumes that f is - a 0-1 ADD. Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addIteConstant Cudd_addApply] - -******************************************************************************/ -DdNode * -Cudd_addIte( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddIteRecur(dd,f,g,h); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addIte */ - - -/**Function******************************************************************** - - Synopsis [Implements ITEconstant for ADDs.] - - Description [Implements ITEconstant for ADDs. f must be a 0-1 ADD. - Returns a pointer to the resulting ADD (which may or may not be - constant) or DD_NON_CONSTANT. No new nodes are created. This function - can be used, for instance, to check that g has a constant value - (specified by h) whenever f is 1. If the constant value is unknown, - then one should use Cudd_addEvalConst.] - - SideEffects [None] - - SeeAlso [Cudd_addIte Cudd_addEvalConst Cudd_bddIteConstant] - -******************************************************************************/ -DdNode * -Cudd_addIteConstant( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *one,*zero; - DdNode *Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*r,*t,*e; - unsigned int topf,topg,toph,v; - - statLine(dd); - /* Trivial cases. */ - if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */ - return(g); - } - if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ - return(h); - } - - /* From now on, f is known not to be a constant. */ - addVarToConst(f,&g,&h,one,zero); - - /* Check remaining one variable cases. */ - if (g == h) { /* ITE(F,G,G) = G */ - return(g); - } - if (cuddIsConstant(g) && cuddIsConstant(h)) { - return(DD_NON_CONSTANT); - } - - topf = cuddI(dd,f->index); - topg = cuddI(dd,g->index); - toph = cuddI(dd,h->index); - v = ddMin(topg,toph); - - /* ITE(F,G,H) = (x,G,H) (non constant) if F = (x,1,0), x < top(G,H). */ - if (topf < v && cuddIsConstant(cuddT(f)) && cuddIsConstant(cuddE(f))) { - return(DD_NON_CONSTANT); - } - - /* Check cache. */ - r = cuddConstantLookup(dd,DD_ADD_ITE_CONSTANT_TAG,f,g,h); - if (r != NULL) { - return(r); - } - - /* Compute cofactors. */ - if (topf <= v) { - v = ddMin(topf,v); /* v = top_var(F,G,H) */ - Fv = cuddT(f); Fnv = cuddE(f); - } else { - Fv = Fnv = f; - } - if (topg == v) { - Gv = cuddT(g); Gnv = cuddE(g); - } else { - Gv = Gnv = g; - } - if (toph == v) { - Hv = cuddT(h); Hnv = cuddE(h); - } else { - Hv = Hnv = h; - } - - /* Recursive step. */ - t = Cudd_addIteConstant(dd,Fv,Gv,Hv); - if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) { - cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - e = Cudd_addIteConstant(dd,Fnv,Gnv,Hnv); - if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) { - cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, t); - return(t); - -} /* end of Cudd_addIteConstant */ - - -/**Function******************************************************************** - - Synopsis [Checks whether ADD g is constant whenever ADD f is 1.] - - Description [Checks whether ADD g is constant whenever ADD f is 1. f - must be a 0-1 ADD. Returns a pointer to the resulting ADD (which may - or may not be constant) or DD_NON_CONSTANT. If f is identically 0, - the check is assumed to be successful, and the background value is - returned. No new nodes are created.] - - SideEffects [None] - - SeeAlso [Cudd_addIteConstant Cudd_addLeq] - -******************************************************************************/ -DdNode * -Cudd_addEvalConst( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *zero; - DdNode *Fv,*Fnv,*Gv,*Gnv,*r,*t,*e; - unsigned int topf,topg; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); -#endif - - statLine(dd); - /* Terminal cases. */ - if (f == DD_ONE(dd) || cuddIsConstant(g)) { - return(g); - } - if (f == (zero = DD_ZERO(dd))) { - return(dd->background); - } - -#ifdef DD_DEBUG - assert(!cuddIsConstant(f)); -#endif - /* From now on, f and g are known not to be constants. */ - - topf = cuddI(dd,f->index); - topg = cuddI(dd,g->index); - - /* Check cache. */ - r = cuddConstantLookup(dd,DD_ADD_EVAL_CONST_TAG,f,g,g); - if (r != NULL) { - return(r); - } - - /* Compute cofactors. */ - if (topf <= topg) { - Fv = cuddT(f); Fnv = cuddE(f); - } else { - Fv = Fnv = f; - } - if (topg <= topf) { - Gv = cuddT(g); Gnv = cuddE(g); - } else { - Gv = Gnv = g; - } - - /* Recursive step. */ - if (Fv != zero) { - t = Cudd_addEvalConst(dd,Fv,Gv); - if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) { - cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - if (Fnv != zero) { - e = Cudd_addEvalConst(dd,Fnv,Gnv); - if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) { - cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - } - cuddCacheInsert2(dd,Cudd_addEvalConst,f,g,t); - return(t); - } else { /* Fnv must be != zero */ - e = Cudd_addEvalConst(dd,Fnv,Gnv); - cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, e); - return(e); - } - -} /* end of Cudd_addEvalConst */ - - -/**Function******************************************************************** - - Synopsis [Computes the complement of an ADD a la C language.] - - Description [Computes the complement of an ADD a la C language: The - complement of 0 is 1 and the complement of everything else is 0. - Returns a pointer to the resulting ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addNegate] - -******************************************************************************/ -DdNode * -Cudd_addCmpl( - DdManager * dd, - DdNode * f) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddCmplRecur(dd,f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addCmpl */ - - -/**Function******************************************************************** - - Synopsis [Determines whether f is less than or equal to g.] - - Description [Returns 1 if f is less than or equal to g; 0 otherwise. - No new nodes are created. This procedure works for arbitrary ADDs. - For 0-1 ADDs Cudd_addEvalConst is more efficient.] - - SideEffects [None] - - SeeAlso [Cudd_addIteConstant Cudd_addEvalConst Cudd_bddLeq] - -******************************************************************************/ -int -Cudd_addLeq( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *tmp, *fv, *fvn, *gv, *gvn; - unsigned int topf, topg, res; - - /* Terminal cases. */ - if (f == g) return(1); - - statLine(dd); - if (cuddIsConstant(f)) { - if (cuddIsConstant(g)) return(cuddV(f) <= cuddV(g)); - if (f == DD_MINUS_INFINITY(dd)) return(1); - if (f == DD_PLUS_INFINITY(dd)) return(0); /* since f != g */ - } - if (g == DD_PLUS_INFINITY(dd)) return(1); - if (g == DD_MINUS_INFINITY(dd)) return(0); /* since f != g */ - - /* Check cache. */ - tmp = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, - DdNode *))Cudd_addLeq,f,g); - if (tmp != NULL) { - return(tmp == DD_ONE(dd)); - } - - /* Compute cofactors. One of f and g is not constant. */ - topf = cuddI(dd,f->index); - topg = cuddI(dd,g->index); - if (topf <= topg) { - fv = cuddT(f); fvn = cuddE(f); - } else { - fv = fvn = f; - } - if (topg <= topf) { - gv = cuddT(g); gvn = cuddE(g); - } else { - gv = gvn = g; - } - - res = Cudd_addLeq(dd,fvn,gvn) && Cudd_addLeq(dd,fv,gv); - - /* Store result in cache and return. */ - cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *)) - Cudd_addLeq,f,g,Cudd_NotCond(DD_ONE(dd),res==0)); - return(res); - -} /* end of Cudd_addLeq */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_addIte(f,g,h).] - - Description [Implements the recursive step of Cudd_addIte(f,g,h). - Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addIte] - -******************************************************************************/ -DdNode * -cuddAddIteRecur( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *one,*zero; - DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e; - unsigned int topf,topg,toph,v; - int index; - - statLine(dd); - /* Trivial cases. */ - - /* One variable cases. */ - if (f == (one = DD_ONE(dd))) { /* ITE(1,G,H) = G */ - return(g); - } - if (f == (zero = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ - return(h); - } - - /* From now on, f is known to not be a constant. */ - addVarToConst(f,&g,&h,one,zero); - - /* Check remaining one variable cases. */ - if (g == h) { /* ITE(F,G,G) = G */ - return(g); - } - - if (g == one) { /* ITE(F,1,0) = F */ - if (h == zero) return(f); - } - - topf = cuddI(dd,f->index); - topg = cuddI(dd,g->index); - toph = cuddI(dd,h->index); - v = ddMin(topg,toph); - - /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */ - if (topf < v && cuddT(f) == one && cuddE(f) == zero) { - r = cuddUniqueInter(dd,(int)f->index,g,h); - return(r); - } - if (topf < v && cuddT(f) == zero && cuddE(f) == one) { - r = cuddUniqueInter(dd,(int)f->index,h,g); - return(r); - } - - /* Check cache. */ - r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h); - if (r != NULL) { - return(r); - } - - /* Compute cofactors. */ - if (topf <= v) { - v = ddMin(topf,v); /* v = top_var(F,G,H) */ - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - } else { - Fv = Fnv = f; - } - if (topg == v) { - index = g->index; - Gv = cuddT(g); Gnv = cuddE(g); - } else { - Gv = Gnv = g; - } - if (toph == v) { - index = h->index; - Hv = cuddT(h); Hnv = cuddE(h); - } else { - Hv = Hnv = h; - } - - /* Recursive step. */ - t = cuddAddIteRecur(dd,Fv,Gv,Hv); - if (t == NULL) return(NULL); - cuddRef(t); - - e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv); - if (e == NULL) { - Cudd_RecursiveDeref(dd,t); - return(NULL); - } - cuddRef(e); - - r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); - if (r == NULL) { - Cudd_RecursiveDeref(dd,t); - Cudd_RecursiveDeref(dd,e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r); - - return(r); - -} /* end of cuddAddIteRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addCmpl.] - - Description [Performs the recursive step of Cudd_addCmpl. Returns a - pointer to the resulting ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addCmpl] - -******************************************************************************/ -DdNode * -cuddAddCmplRecur( - DdManager * dd, - DdNode * f) -{ - DdNode *one,*zero; - DdNode *r,*Fv,*Fnv,*t,*e; - - statLine(dd); - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - if (cuddIsConstant(f)) { - if (f == zero) { - return(one); - } else { - return(zero); - } - } - r = cuddCacheLookup1(dd,Cudd_addCmpl,f); - if (r != NULL) { - return(r); - } - Fv = cuddT(f); - Fnv = cuddE(f); - t = cuddAddCmplRecur(dd,Fv); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddAddCmplRecur(dd,Fnv); - if (e == NULL) { - Cudd_RecursiveDeref(dd,t); - return(NULL); - } - cuddRef(e); - r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - cuddCacheInsert1(dd,Cudd_addCmpl,f,r); - return(r); - -} /* end of cuddAddCmplRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Replaces variables with constants if possible (part of - canonical form).] - - Description [] - - SideEffects [None] - -******************************************************************************/ -static void -addVarToConst( - DdNode * f, - DdNode ** gp, - DdNode ** hp, - DdNode * one, - DdNode * zero) -{ - DdNode *g = *gp; - DdNode *h = *hp; - - if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ - *gp = one; - } - - if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ - *hp = zero; - } - -} /* end of addVarToConst */ diff --git a/src/bdd/cudd/cuddAddNeg.c b/src/bdd/cudd/cuddAddNeg.c deleted file mode 100644 index bdb08ddc..00000000 --- a/src/bdd/cudd/cuddAddNeg.c +++ /dev/null @@ -1,262 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddNeg.c] - - PackageName [cudd] - - Synopsis [function to compute the negation of an ADD.] - - Description [External procedures included in this module: -
          -
        • Cudd_addNegate() -
        • Cudd_addRoundOff() -
        - Internal procedures included in this module: -
          -
        • cuddAddNegateRecur() -
        • cuddAddRoundOffRecur() -
        ] - - Author [Fabio Somenzi, Balakrishna Kumthekar] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddNeg.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes the additive inverse of an ADD.] - - Description [Computes the additive inverse of an ADD. Returns a pointer - to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addCmpl] - -******************************************************************************/ -DdNode * -Cudd_addNegate( - DdManager * dd, - DdNode * f) -{ - DdNode *res; - - do { - res = cuddAddNegateRecur(dd,f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addNegate */ - - -/**Function******************************************************************** - - Synopsis [Rounds off the discriminants of an ADD.] - - Description [Rounds off the discriminants of an ADD. The discriminants are - rounded off to N digits after the decimal. Returns a pointer to the result - ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_addRoundOff( - DdManager * dd, - DdNode * f, - int N) -{ - DdNode *res; - double trunc = pow(10.0,(double)N); - - do { - res = cuddAddRoundOffRecur(dd,f,trunc); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addRoundOff */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_addNegate.] - - Description [Implements the recursive step of Cudd_addNegate. - Returns a pointer to the result.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -cuddAddNegateRecur( - DdManager * dd, - DdNode * f) -{ - DdNode *res, - *fv, *fvn, - *T, *E; - - statLine(dd); - /* Check terminal cases. */ - if (cuddIsConstant(f)) { - res = cuddUniqueConst(dd,-cuddV(f)); - return(res); - } - - /* Check cache */ - res = cuddCacheLookup1(dd,Cudd_addNegate,f); - if (res != NULL) return(res); - - /* Recursive Step */ - fv = cuddT(f); - fvn = cuddE(f); - T = cuddAddNegateRecur(dd,fv); - if (T == NULL) return(NULL); - cuddRef(T); - - E = cuddAddNegateRecur(dd,fvn); - if (E == NULL) { - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert1(dd,Cudd_addNegate,f,res); - - return(res); - -} /* end of cuddAddNegateRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_addRoundOff.] - - Description [Implements the recursive step of Cudd_addRoundOff. - Returns a pointer to the result.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -cuddAddRoundOffRecur( - DdManager * dd, - DdNode * f, - double trunc) -{ - - DdNode *res, *fv, *fvn, *T, *E; - double n; - DdNode *(*cacheOp)(DdManager *, DdNode *); - - statLine(dd); - if (cuddIsConstant(f)) { - n = ceil(cuddV(f)*trunc)/trunc; - res = cuddUniqueConst(dd,n); - return(res); - } - cacheOp = (DdNode *(*)(DdManager *, DdNode *)) Cudd_addRoundOff; - res = cuddCacheLookup1(dd,cacheOp,f); - if (res != NULL) { - return(res); - } - /* Recursive Step */ - fv = cuddT(f); - fvn = cuddE(f); - T = cuddAddRoundOffRecur(dd,fv,trunc); - if (T == NULL) { - return(NULL); - } - cuddRef(T); - E = cuddAddRoundOffRecur(dd,fvn,trunc); - if (E == NULL) { - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert1(dd,cacheOp,f,res); - return(res); - -} /* end of cuddAddRoundOffRecur */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddAddWalsh.c b/src/bdd/cudd/cuddAddWalsh.c deleted file mode 100644 index c6a67e34..00000000 --- a/src/bdd/cudd/cuddAddWalsh.c +++ /dev/null @@ -1,364 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAddWalsh.c] - - PackageName [cudd] - - Synopsis [Functions that generate Walsh matrices and residue - functions in ADD form.] - - Description [External procedures included in this module: -
          -
        • Cudd_addWalsh() -
        • Cudd_addResidue() -
        - Static procedures included in this module: -
          -
        • addWalshInt() -
        ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAddWalsh.c,v 1.1.1.1 2003/02/24 22:23:50 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * addWalshInt ARGS((DdManager *dd, DdNode **x, DdNode **y, int n)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Generates a Walsh matrix in ADD form.] - - Description [Generates a Walsh matrix in ADD form. Returns a pointer - to the matrixi if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_addWalsh( - DdManager * dd, - DdNode ** x, - DdNode ** y, - int n) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = addWalshInt(dd, x, y, n); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addWalsh */ - - -/**Function******************************************************************** - - Synopsis [Builds an ADD for the residue modulo m of an n-bit - number.] - - Description [Builds an ADD for the residue modulo m of an n-bit - number. The modulus must be at least 2, and the number of bits at - least 1. Parameter options specifies whether the MSB should be on top - or the LSB; and whther the number whose residue is computed is in - two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT - specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB - specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's - complement residue. To request MSB on top and two's complement residue - simultaneously, one can OR the two macros: - CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC. - Cudd_addResidue returns a pointer to the resulting ADD if successful; - NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_addResidue( - DdManager * dd /* manager */, - int n /* number of bits */, - int m /* modulus */, - int options /* options */, - int top /* index of top variable */) -{ - int msbLsb; /* MSB on top (1) or LSB on top (0) */ - int tc; /* two's complement (1) or unsigned (0) */ - int i, j, k, t, residue, thisOne, previous, index; - DdNode **array[2], *var, *tmp, *res; - - /* Sanity check. */ - if (n < 1 && m < 2) return(NULL); - - msbLsb = options & CUDD_RESIDUE_MSB; - tc = options & CUDD_RESIDUE_TC; - - /* Allocate and initialize working arrays. */ - array[0] = ALLOC(DdNode *,m); - if (array[0] == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - array[1] = ALLOC(DdNode *,m); - if (array[1] == NULL) { - FREE(array[0]); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < m; i++) { - array[0][i] = array[1][i] = NULL; - } - - /* Initialize residues. */ - for (i = 0; i < m; i++) { - tmp = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) i); - if (tmp == NULL) { - for (j = 0; j < i; j++) { - Cudd_RecursiveDeref(dd,array[1][j]); - } - FREE(array[0]); - FREE(array[1]); - return(NULL); - } - cuddRef(tmp); - array[1][i] = tmp; - } - - /* Main iteration. */ - residue = 1; /* residue of 2**0 */ - for (k = 0; k < n; k++) { - /* Choose current and previous arrays. */ - thisOne = k & 1; - previous = thisOne ^ 1; - /* Build an ADD projection function. */ - if (msbLsb) { - index = top+n-k-1; - } else { - index = top+k; - } - var = cuddUniqueInter(dd,index,DD_ONE(dd),DD_ZERO(dd)); - if (var == NULL) { - for (j = 0; j < m; j++) { - Cudd_RecursiveDeref(dd,array[previous][j]); - } - FREE(array[0]); - FREE(array[1]); - return(NULL); - } - cuddRef(var); - for (i = 0; i < m; i ++) { - t = (i + residue) % m; - tmp = Cudd_addIte(dd,var,array[previous][t],array[previous][i]); - if (tmp == NULL) { - for (j = 0; j < i; j++) { - Cudd_RecursiveDeref(dd,array[thisOne][j]); - } - for (j = 0; j < m; j++) { - Cudd_RecursiveDeref(dd,array[previous][j]); - } - FREE(array[0]); - FREE(array[1]); - return(NULL); - } - cuddRef(tmp); - array[thisOne][i] = tmp; - } - /* One layer completed. Free the other array for the next iteration. */ - for (i = 0; i < m; i++) { - Cudd_RecursiveDeref(dd,array[previous][i]); - } - Cudd_RecursiveDeref(dd,var); - /* Update residue of 2**k. */ - residue = (2 * residue) % m; - /* Adjust residue for MSB, if this is a two's complement number. */ - if (tc && (k == n - 1)) { - residue = (m - residue) % m; - } - } - - /* We are only interested in the 0-residue node of the top layer. */ - for (i = 1; i < m; i++) { - Cudd_RecursiveDeref(dd,array[(n - 1) & 1][i]); - } - res = array[(n - 1) & 1][0]; - - FREE(array[0]); - FREE(array[1]); - - cuddDeref(res); - return(res); - -} /* end of Cudd_addResidue */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_addWalsh.] - - Description [Generates a Walsh matrix in ADD form. Returns a pointer - to the matrixi if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -static DdNode * -addWalshInt( - DdManager * dd, - DdNode ** x, - DdNode ** y, - int n) -{ - DdNode *one, *minusone; - DdNode *t, *u, *t1, *u1, *v, *w; - int i; - - one = DD_ONE(dd); - if (n == 0) return(one); - - /* Build bottom part of ADD outside loop */ - minusone = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) -1); - if (minusone == NULL) return(NULL); - cuddRef(minusone); - v = Cudd_addIte(dd, y[n-1], minusone, one); - if (v == NULL) { - Cudd_RecursiveDeref(dd, minusone); - return(NULL); - } - cuddRef(v); - u = Cudd_addIte(dd, x[n-1], v, one); - if (u == NULL) { - Cudd_RecursiveDeref(dd, minusone); - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - if (n>1) { - w = Cudd_addIte(dd, y[n-1], one, minusone); - if (w == NULL) { - Cudd_RecursiveDeref(dd, minusone); - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(w); - t = Cudd_addIte(dd, x[n-1], w, minusone); - if (t == NULL) { - Cudd_RecursiveDeref(dd, minusone); - Cudd_RecursiveDeref(dd, u); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(t); - Cudd_RecursiveDeref(dd, w); - } - cuddDeref(minusone); /* minusone is in the result; it won't die */ - - /* Loop to build the rest of the ADD */ - for (i=n-2; i>=0; i--) { - t1 = t; u1 = u; - v = Cudd_addIte(dd, y[i], t1, u1); - if (v == NULL) { - Cudd_RecursiveDeref(dd, u1); - Cudd_RecursiveDeref(dd, t1); - return(NULL); - } - cuddRef(v); - u = Cudd_addIte(dd, x[i], v, u1); - if (u == NULL) { - Cudd_RecursiveDeref(dd, u1); - Cudd_RecursiveDeref(dd, t1); - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - if (i>0) { - w = Cudd_addIte(dd, y[i], u1, t1); - if (u == NULL) { - Cudd_RecursiveDeref(dd, u1); - Cudd_RecursiveDeref(dd, t1); - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(w); - t = Cudd_addIte(dd, x[i], w, t1); - if (u == NULL) { - Cudd_RecursiveDeref(dd, u1); - Cudd_RecursiveDeref(dd, t1); - Cudd_RecursiveDeref(dd, u); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(t); - Cudd_RecursiveDeref(dd, w); - } - Cudd_RecursiveDeref(dd, u1); - Cudd_RecursiveDeref(dd, t1); - } - - cuddDeref(u); - return(u); - -} /* end of addWalshInt */ diff --git a/src/bdd/cudd/cuddAndAbs.c b/src/bdd/cudd/cuddAndAbs.c deleted file mode 100644 index 5ec47beb..00000000 --- a/src/bdd/cudd/cuddAndAbs.c +++ /dev/null @@ -1,306 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAndAbs.c] - - PackageName [cudd] - - Synopsis [Combined AND and existential abstraction for BDDs] - - Description [External procedures included in this module: -
          -
        • Cudd_bddAndAbstract() -
        - Internal procedures included in this module: -
          -
        • cuddBddAndAbstractRecur() -
        ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAndAbs.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Takes the AND of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Takes the AND of two BDDs and simultaneously abstracts - the variables in cube. The variables are existentially abstracted. - Returns a pointer to the result is successful; NULL otherwise. - Cudd_bddAndAbstract implements the semiring matrix multiplication - algorithm for the boolean semiring.] - - SideEffects [None] - - SeeAlso [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd] - -******************************************************************************/ -DdNode * -Cudd_bddAndAbstract( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube) -{ - DdNode *res; - - do { - manager->reordered = 0; - res = cuddBddAndAbstractRecur(manager, f, g, cube); - } while (manager->reordered == 1); - return(res); - -} /* end of Cudd_bddAndAbstract */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Takes the AND of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Takes the AND of two BDDs and simultaneously abstracts - the variables in cube. The variables are existentially abstracted. - Returns a pointer to the result is successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddAndAbstract] - -******************************************************************************/ -DdNode * -cuddBddAndAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube) -{ - DdNode *F, *ft, *fe, *G, *gt, *ge; - DdNode *one, *zero, *r, *t, *e; - unsigned int topf, topg, topcube, top, index; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); - if (f == one && g == one) return(one); - - if (cube == one) { - return(cuddBddAndRecur(manager, f, g)); - } - if (f == one || f == g) { - return(cuddBddExistAbstractRecur(manager, g, cube)); - } - if (g == one) { - return(cuddBddExistAbstractRecur(manager, f, cube)); - } - /* At this point f, g, and cube are not constant. */ - - if (f > g) { /* Try to increase cache efficiency. */ - DdNode *tmp = f; - f = g; - g = tmp; - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - F = Cudd_Regular(f); - G = Cudd_Regular(g); - topf = manager->perm[F->index]; - topg = manager->perm[G->index]; - top = ddMin(topf, topg); - topcube = manager->perm[cube->index]; - - while (topcube < top) { - cube = cuddT(cube); - if (cube == one) { - return(cuddBddAndRecur(manager, f, g)); - } - topcube = manager->perm[cube->index]; - } - /* Now, topcube >= top. */ - - /* Check cache. */ - if (F->ref != 1 || G->ref != 1) { - r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube); - if (r != NULL) { - return(r); - } - } - - if (topf == top) { - index = F->index; - ft = cuddT(F); - fe = cuddE(F); - if (Cudd_IsComplement(f)) { - ft = Cudd_Not(ft); - fe = Cudd_Not(fe); - } - } else { - index = G->index; - ft = fe = f; - } - - if (topg == top) { - gt = cuddT(G); - ge = cuddE(G); - if (Cudd_IsComplement(g)) { - gt = Cudd_Not(gt); - ge = Cudd_Not(ge); - } - } else { - gt = ge = g; - } - - if (topcube == top) { /* quantify */ - DdNode *Cube = cuddT(cube); - t = cuddBddAndAbstractRecur(manager, ft, gt, Cube); - if (t == NULL) return(NULL); - /* Special case: 1 OR anything = 1. Hence, no need to compute - ** the else branch if t is 1. Likewise t + t * anything == t. - ** Notice that t == fe implies that fe does not depend on the - ** variables in Cube. Likewise for t == ge. - */ - if (t == one || t == fe || t == ge) { - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, - f, g, cube, t); - return(t); - } - cuddRef(t); - /* Special case: t + !t * anything == t + anything. */ - if (t == Cudd_Not(fe)) { - e = cuddBddExistAbstractRecur(manager, ge, Cube); - } else if (t == Cudd_Not(ge)) { - e = cuddBddExistAbstractRecur(manager, fe, Cube); - } else { - e = cuddBddAndAbstractRecur(manager, fe, ge, Cube); - } - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - if (t == e) { - r = t; - cuddDeref(t); - } else { - cuddRef(e); - r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - cuddRef(r); - Cudd_DelayedDerefBdd(manager, t); - Cudd_DelayedDerefBdd(manager, e); - cuddDeref(r); - } - } else { - t = cuddBddAndAbstractRecur(manager, ft, gt, cube); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddBddAndAbstractRecur(manager, fe, ge, cube); - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - if (t == e) { - r = t; - cuddDeref(t); - } else { - cuddRef(e); - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager, (int) index, - Cudd_Not(t), Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - } - cuddDeref(e); - cuddDeref(t); - } - } - - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r); - return (r); - -} /* end of cuddBddAndAbstractRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddAnneal.c b/src/bdd/cudd/cuddAnneal.c deleted file mode 100644 index 3d8b56b9..00000000 --- a/src/bdd/cudd/cuddAnneal.c +++ /dev/null @@ -1,788 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddAnneal.c] - - PackageName [cudd] - - Synopsis [Reordering of DDs based on simulated annealing] - - Description [Internal procedures included in this file: -
          -
        • cuddAnnealing() -
        - Static procedures included in this file: -
          -
        • stopping_criterion() -
        • random_generator() -
        • ddExchange() -
        • ddJumpingAux() -
        • ddJumpingUp() -
        • ddJumpingDown() -
        • siftBackwardProb() -
        • copyOrder() -
        • restoreOrder() -
        - ] - - SeeAlso [] - - Author [Jae-Young Jang, Jorgen Sivesind] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/* Annealing parameters */ -#define BETA 0.6 -#define ALPHA 0.90 -#define EXC_PROB 0.4 -#define JUMP_UP_PROB 0.36 -#define MAXGEN_RATIO 15.0 -#define STOP_TEMP 1.0 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddAnneal.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -#ifdef DD_STATS -extern int ddTotalNumberSwapping; -extern int ddTotalNISwaps; -static int tosses; -static int acceptances; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int stopping_criterion ARGS((int c1, int c2, int c3, int c4, double temp)); -static double random_generator ARGS(()); -static int ddExchange ARGS((DdManager *table, int x, int y, double temp)); -static int ddJumpingAux ARGS((DdManager *table, int x, int x_low, int x_high, double temp)); -static Move * ddJumpingUp ARGS((DdManager *table, int x, int x_low, int initial_size)); -static Move * ddJumpingDown ARGS((DdManager *table, int x, int x_high, int initial_size)); -static int siftBackwardProb ARGS((DdManager *table, Move *moves, int size, double temp)); -static void copyOrder ARGS((DdManager *table, int *array, int lower, int upper)); -static int restoreOrder ARGS((DdManager *table, int *array, int lower, int upper)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Get new variable-order by simulated annealing algorithm.] - - Description [Get x, y by random selection. Choose either - exchange or jump randomly. In case of jump, choose between jump_up - and jump_down randomly. Do exchange or jump and get optimal case. - Loop until there is no improvement or temperature reaches - minimum. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddAnnealing( - DdManager * table, - int lower, - int upper) -{ - int nvars; - int size; - int x,y; - int result; - int c1, c2, c3, c4; - int BestCost; - int *BestOrder; - double NewTemp, temp; - double rand1; - int innerloop, maxGen; - int ecount, ucount, dcount; - - nvars = upper - lower + 1; - - result = cuddSifting(table,lower,upper); -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); -#endif - if (result == 0) return(0); - - size = table->keys - table->isolated; - - /* Keep track of the best order. */ - BestCost = size; - BestOrder = ALLOC(int,nvars); - if (BestOrder == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - copyOrder(table,BestOrder,lower,upper); - - temp = BETA * size; - maxGen = (int) (MAXGEN_RATIO * nvars); - - c1 = size + 10; - c2 = c1 + 10; - c3 = size; - c4 = c2 + 10; - ecount = ucount = dcount = 0; - - while (!stopping_criterion(c1, c2, c3, c4, temp)) { -#ifdef DD_STATS - (void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t", - temp,size,maxGen); - tosses = acceptances = 0; -#endif - for (innerloop = 0; innerloop < maxGen; innerloop++) { - /* Choose x, y randomly. */ - x = (int) Cudd_Random() % nvars; - do { - y = (int) Cudd_Random() % nvars; - } while (x == y); - x += lower; - y += lower; - if (x > y) { - int tmp = x; - x = y; - y = tmp; - } - - /* Choose move with roulette wheel. */ - rand1 = random_generator(); - if (rand1 < EXC_PROB) { - result = ddExchange(table,x,y,temp); /* exchange */ - ecount++; -#if 0 - (void) fprintf(table->out, - "Exchange of %d and %d: size = %d\n", - x,y,table->keys - table->isolated); -#endif - } else if (rand1 < EXC_PROB + JUMP_UP_PROB) { - result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */ - ucount++; -#if 0 - (void) fprintf(table->out, - "Jump up of %d to %d: size = %d\n", - y,x,table->keys - table->isolated); -#endif - } else { - result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */ - dcount++; -#if 0 - (void) fprintf(table->out, - "Jump down of %d to %d: size = %d\n", - x,y,table->keys - table->isolated); -#endif - } - - if (!result) { - FREE(BestOrder); - return(0); - } - - size = table->keys - table->isolated; /* keep current size */ - if (size < BestCost) { /* update best order */ - BestCost = size; - copyOrder(table,BestOrder,lower,upper); - } - } - c1 = c2; - c2 = c3; - c3 = c4; - c4 = size; - NewTemp = ALPHA * temp; - if (NewTemp >= 1.0) { - maxGen = (int)(log(NewTemp) / log(temp) * maxGen); - } - temp = NewTemp; /* control variable */ -#ifdef DD_STATS - (void) fprintf(table->out,"uphill = %d\taccepted = %d\n", - tosses,acceptances); - fflush(table->out); -#endif - } - - result = restoreOrder(table,BestOrder,lower,upper); - FREE(BestOrder); - if (!result) return(0); -#ifdef DD_STATS - fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount); - fprintf(table->out,"#:N_JUMPUP %8d : total jumps up\n",ucount); - fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount); -#endif - return(1); - -} /* end of cuddAnnealing */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Checks termination condition.] - - Description [If temperature is STOP_TEMP or there is no improvement - then terminates. Returns 1 if the termination criterion is met; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -stopping_criterion( - int c1, - int c2, - int c3, - int c4, - double temp) -{ - if (STOP_TEMP < temp) { - return(0); - } else if ((c1 == c2) && (c1 == c3) && (c1 == c4)) { - return(1); - } else { - return(0); - } - -} /* end of stopping_criterion */ - - -/**Function******************************************************************** - - Synopsis [Random number generator.] - - Description [Returns a double precision value between 0.0 and 1.0.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static double -random_generator( - ) -{ - return((double)(Cudd_Random() / 2147483561.0)); - -} /* end of random_generator */ - - -/**Function******************************************************************** - - Synopsis [This function is for exchanging two variables, x and y.] - - Description [This is the same funcion as ddSwapping except for - comparison expression. Use probability function, exp(-size_change/temp).] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddExchange( - DdManager * table, - int x, - int y, - double temp) -{ - Move *move,*moves; - int tmp; - int x_ref,y_ref; - int x_next,y_next; - int size, result; - int initial_size, limit_size; - - x_ref = x; - y_ref = y; - - x_next = cuddNextHigh(table,x); - y_next = cuddNextLow(table,y); - moves = NULL; - initial_size = limit_size = table->keys - table->isolated; - - for (;;) { - if (x_next == y_next) { - size = cuddSwapInPlace(table,x,x_next); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - size = cuddSwapInPlace(table,y_next,y); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - size = cuddSwapInPlace(table,x,x_next); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; - x = y; - y = tmp; - } else if (x == y_next) { - size = cuddSwapInPlace(table,x,x_next); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - tmp = x; - x = y; - y = tmp; - } else { - size = cuddSwapInPlace(table,x,x_next); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - size = cuddSwapInPlace(table,y_next,y); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - x = x_next; - y = y_next; - } - - x_next = cuddNextHigh(table,x); - y_next = cuddNextLow(table,y); - if (x_next > y_ref) break; - - if ((double) size > DD_MAX_REORDER_GROWTH * (double) limit_size) { - break; - } else if (size < limit_size) { - limit_size = size; - } - } - - if (y_next>=x_ref) { - size = cuddSwapInPlace(table,y_next,y); - if (size == 0) goto ddExchangeOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddExchangeOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - } - - /* move backward and stop at best position or accept uphill move */ - result = siftBackwardProb(table,moves,initial_size,temp); - if (!result) goto ddExchangeOutOfMem; - - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(1); - -ddExchangeOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table,(DdNode *) moves); - moves = move; - } - return(0); - -} /* end of ddExchange */ - - -/**Function******************************************************************** - - Synopsis [Moves a variable to a specified position.] - - Description [If x==x_low, it executes jumping_down. If x==x_high, it - executes jumping_up. This funcion is similar to ddSiftingAux. Returns - 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddJumpingAux( - DdManager * table, - int x, - int x_low, - int x_high, - double temp) -{ - Move *move; - Move *moves; /* list of moves */ - int initial_size; - int result; - - initial_size = table->keys - table->isolated; - -#ifdef DD_DEBUG - assert(table->subtables[x].keys > 0); -#endif - - moves = NULL; - - if (cuddNextLow(table,x) < x_low) { - if (cuddNextHigh(table,x) > x_high) return(1); - moves = ddJumpingDown(table,x,x_high,initial_size); - /* after that point x --> x_high unless early termination */ - if (moves == NULL) goto ddJumpingAuxOutOfMem; - /* move backward and stop at best position or accept uphill move */ - result = siftBackwardProb(table,moves,initial_size,temp); - if (!result) goto ddJumpingAuxOutOfMem; - } else if (cuddNextHigh(table,x) > x_high) { - moves = ddJumpingUp(table,x,x_low,initial_size); - /* after that point x --> x_low unless early termination */ - if (moves == NULL) goto ddJumpingAuxOutOfMem; - /* move backward and stop at best position or accept uphill move */ - result = siftBackwardProb(table,moves,initial_size,temp); - if (!result) goto ddJumpingAuxOutOfMem; - } else { - (void) fprintf(table->err,"Unexpected condition in ddJumping\n"); - goto ddJumpingAuxOutOfMem; - } - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(1); - -ddJumpingAuxOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(0); - -} /* end of ddJumpingAux */ - - -/**Function******************************************************************** - - Synopsis [This function is for jumping up.] - - Description [This is a simplified version of ddSiftingUp. It does not - use lower bounding. Returns the set of moves in case of success; NULL - if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -ddJumpingUp( - DdManager * table, - int x, - int x_low, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - - moves = NULL; - y = cuddNextLow(table,x); - while (y >= x_low) { - size = cuddSwapInPlace(table,y,x); - if (size == 0) goto ddJumpingUpOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddJumpingUpOutOfMem; - move->x = y; - move->y = x; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > table->maxGrowth * (double) limit_size) { - break; - } else if (size < limit_size) { - limit_size = size; - } - x = y; - y = cuddNextLow(table,x); - } - return(moves); - -ddJumpingUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(NULL); - -} /* end of ddJumpingUp */ - - -/**Function******************************************************************** - - Synopsis [This function is for jumping down.] - - Description [This is a simplified version of ddSiftingDown. It does not - use lower bounding. Returns the set of moves in case of success; NULL - if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -ddJumpingDown( - DdManager * table, - int x, - int x_high, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - - moves = NULL; - y = cuddNextHigh(table,x); - while (y <= x_high) { - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddJumpingDownOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddJumpingDownOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > table->maxGrowth * (double) limit_size) { - break; - } else if (size < limit_size) { - limit_size = size; - } - x = y; - y = cuddNextHigh(table,x); - } - return(moves); - -ddJumpingDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(NULL); - -} /* end of ddJumpingDown */ - - -/**Function******************************************************************** - - Synopsis [Returns the DD to the best position encountered during - sifting if there was improvement.] - - Description [Otherwise, "tosses a coin" to decide whether to keep - the current configuration or return the DD to the original - one. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -siftBackwardProb( - DdManager * table, - Move * moves, - int size, - double temp) -{ - Move *move; - int res; - int best_size = size; - double coin, threshold; - - /* Look for best size during the last sifting */ - for (move = moves; move != NULL; move = move->next) { - if (move->size < best_size) { - best_size = move->size; - } - } - - /* If best_size equals size, the last sifting did not produce any - ** improvement. We now toss a coin to decide whether to retain - ** this change or not. - */ - if (best_size == size) { - coin = random_generator(); -#ifdef DD_STATS - tosses++; -#endif - threshold = exp(-((double)(table->keys - table->isolated - size))/temp); - if (coin < threshold) { -#ifdef DD_STATS - acceptances++; -#endif - return(1); - } - } - - /* Either there was improvement, or we have decided not to - ** accept the uphill move. Go to best position. - */ - res = table->keys - table->isolated; - for (move = moves; move != NULL; move = move->next) { - if (res == best_size) return(1); - res = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - - return(1); - -} /* end of sift_backward_prob */ - - -/**Function******************************************************************** - - Synopsis [Copies the current variable order to array.] - - Description [Copies the current variable order to array. - At the same time inverts the permutation.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -copyOrder( - DdManager * table, - int * array, - int lower, - int upper) -{ - int i; - int nvars; - - nvars = upper - lower + 1; - for (i = 0; i < nvars; i++) { - array[i] = table->invperm[i+lower]; - } - -} /* end of copyOrder */ - - -/**Function******************************************************************** - - Synopsis [Restores the variable order in array by a series of sifts up.] - - Description [Restores the variable order in array by a series of sifts up. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -restoreOrder( - DdManager * table, - int * array, - int lower, - int upper) -{ - int i, x, y, size; - int nvars = upper - lower + 1; - - for (i = 0; i < nvars; i++) { - x = table->perm[array[i]]; -#ifdef DD_DEBUG - assert(x >= lower && x <= upper); -#endif - y = cuddNextLow(table,x); - while (y >= i + lower) { - size = cuddSwapInPlace(table,y,x); - if (size == 0) return(0); - x = y; - y = cuddNextLow(table,x); - } - } - - return(1); - -} /* end of restoreOrder */ - diff --git a/src/bdd/cudd/cuddApa.c b/src/bdd/cudd/cuddApa.c deleted file mode 100644 index 47ab51e8..00000000 --- a/src/bdd/cudd/cuddApa.c +++ /dev/null @@ -1,930 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddApa.c] - - PackageName [cudd] - - Synopsis [Arbitrary precision arithmetic functions.] - - Description [External procedures included in this module: -
          -
        • -
        - Internal procedures included in this module: -
          -
        • () -
        - Static procedures included in this module: -
          -
        • () -
        ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddApa.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -static DdNode *background, *zero; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdApaNumber cuddApaCountMintermAux ARGS((DdNode * node, int digits, DdApaNumber max, DdApaNumber min, st_table * table)); -static enum st_retval cuddApaStCountfree ARGS((char * key, char * value, char * arg)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Finds the number of digits for an arbitrary precision - integer.] - - Description [Finds the number of digits for an arbitrary precision - integer given the maximum number of binary digits. The number of - binary digits should be positive. Returns the number of digits if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_ApaNumberOfDigits( - int binaryDigits) -{ - int digits; - - digits = binaryDigits / DD_APA_BITS; - if ((digits * DD_APA_BITS) != binaryDigits) - digits++; - return(digits); - -} /* end of Cudd_ApaNumberOfDigits */ - - -/**Function******************************************************************** - - Synopsis [Allocates memory for an arbitrary precision integer.] - - Description [Allocates memory for an arbitrary precision - integer. Returns a pointer to the allocated memory if successful; - NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdApaNumber -Cudd_NewApaNumber( - int digits) -{ - return(ALLOC(DdApaDigit, digits)); - -} /* end of Cudd_NewApaNumber */ - - -/**Function******************************************************************** - - Synopsis [Makes a copy of an arbitrary precision integer.] - - Description [Makes a copy of an arbitrary precision integer.] - - SideEffects [Changes parameter dest.] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_ApaCopy( - int digits, - DdApaNumber source, - DdApaNumber dest) -{ - int i; - - for (i = 0; i < digits; i++) { - dest[i] = source[i]; - } - -} /* end of Cudd_ApaCopy */ - - -/**Function******************************************************************** - - Synopsis [Adds two arbitrary precision integers.] - - Description [Adds two arbitrary precision integers. Returns the - carry out of the most significant digit.] - - SideEffects [The result of the sum is stored in parameter sum.] - - SeeAlso [] - -******************************************************************************/ -DdApaDigit -Cudd_ApaAdd( - int digits, - DdApaNumber a, - DdApaNumber b, - DdApaNumber sum) -{ - int i; - DdApaDoubleDigit partial = 0; - - for (i = digits - 1; i >= 0; i--) { - partial = a[i] + b[i] + DD_MSDIGIT(partial); - sum[i] = (DdApaDigit) DD_LSDIGIT(partial); - } - return(DD_MSDIGIT(partial)); - -} /* end of Cudd_ApaAdd */ - - -/**Function******************************************************************** - - Synopsis [Subtracts two arbitrary precision integers.] - - Description [Subtracts two arbitrary precision integers. Returns the - borrow out of the most significant digit.] - - SideEffects [The result of the subtraction is stored in parameter - diff.] - - SeeAlso [] - -******************************************************************************/ -DdApaDigit -Cudd_ApaSubtract( - int digits, - DdApaNumber a, - DdApaNumber b, - DdApaNumber diff) -{ - int i; - DdApaDoubleDigit partial = DD_APA_BASE; - - for (i = digits - 1; i >= 0; i--) { - partial = a[i] - b[i] + DD_MSDIGIT(partial) + DD_APA_MASK; - diff[i] = (DdApaDigit) DD_LSDIGIT(partial); - } - return(DD_MSDIGIT(partial) - 1); - -} /* end of Cudd_ApaSubtract */ - - -/**Function******************************************************************** - - Synopsis [Divides an arbitrary precision integer by a digit.] - - Description [Divides an arbitrary precision integer by a digit.] - - SideEffects [The quotient is returned in parameter quotient.] - - SeeAlso [] - -******************************************************************************/ -DdApaDigit -Cudd_ApaShortDivision( - int digits, - DdApaNumber dividend, - DdApaDigit divisor, - DdApaNumber quotient) -{ - int i; - DdApaDigit remainder; - DdApaDoubleDigit partial; - - remainder = 0; - for (i = 0; i < digits; i++) { - partial = remainder * DD_APA_BASE + dividend[i]; - quotient[i] = (DdApaDigit) (partial/(DdApaDoubleDigit)divisor); - remainder = (DdApaDigit) (partial % divisor); - } - - return(remainder); - -} /* end of Cudd_ApaShortDivision */ - - -/**Function******************************************************************** - - Synopsis [Divides an arbitrary precision integer by an integer.] - - Description [Divides an arbitrary precision integer by a 32-bit - unsigned integer. Returns the remainder of the division. This - procedure relies on the assumption that the number of bits of a - DdApaDigit plus the number of bits of an unsigned int is less the - number of bits of the mantissa of a double. This guarantees that the - product of a DdApaDigit and an unsigned int can be represented - without loss of precision by a double. On machines where this - assumption is not satisfied, this procedure will malfunction.] - - SideEffects [The quotient is returned in parameter quotient.] - - SeeAlso [Cudd_ApaShortDivision] - -******************************************************************************/ -unsigned int -Cudd_ApaIntDivision( - int digits, - DdApaNumber dividend, - unsigned int divisor, - DdApaNumber quotient) -{ - int i; - double partial; - unsigned int remainder = 0; - double ddiv = (double) divisor; - - for (i = 0; i < digits; i++) { - partial = (double) remainder * DD_APA_BASE + dividend[i]; - quotient[i] = (DdApaDigit) (partial / ddiv); - remainder = (unsigned int) (partial - ((double)quotient[i] * ddiv)); - } - - return(remainder); - -} /* end of Cudd_ApaIntDivision */ - - -/**Function******************************************************************** - - Synopsis [Shifts right an arbitrary precision integer by one binary - place.] - - Description [Shifts right an arbitrary precision integer by one - binary place. The most significant binary digit of the result is - taken from parameter in.] - - SideEffects [The result is returned in parameter b.] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_ApaShiftRight( - int digits, - DdApaDigit in, - DdApaNumber a, - DdApaNumber b) -{ - int i; - - for (i = digits - 1; i > 0; i--) { - b[i] = (a[i] >> 1) | ((a[i-1] & 1) << (DD_APA_BITS - 1)); - } - b[0] = (a[0] >> 1) | (in << (DD_APA_BITS - 1)); - -} /* end of Cudd_ApaShiftRight */ - - -/**Function******************************************************************** - - Synopsis [Sets an arbitrary precision integer to a one-digit literal.] - - Description [Sets an arbitrary precision integer to a one-digit literal.] - - SideEffects [The result is returned in parameter number.] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_ApaSetToLiteral( - int digits, - DdApaNumber number, - DdApaDigit literal) -{ - int i; - - for (i = 0; i < digits - 1; i++) - number[i] = 0; - number[digits - 1] = literal; - -} /* end of Cudd_ApaSetToLiteral */ - - -/**Function******************************************************************** - - Synopsis [Sets an arbitrary precision integer to a power of two.] - - Description [Sets an arbitrary precision integer to a power of - two. If the power of two is too large to be represented, the number - is set to 0.] - - SideEffects [The result is returned in parameter number.] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_ApaPowerOfTwo( - int digits, - DdApaNumber number, - int power) -{ - int i; - int index; - - for (i = 0; i < digits; i++) - number[i] = 0; - i = digits - 1 - power / DD_APA_BITS; - if (i < 0) return; - index = power & (DD_APA_BITS - 1); - number[i] = 1 << index; - -} /* end of Cudd_ApaPowerOfTwo */ - - -/**Function******************************************************************** - - Synopsis [Compares two arbitrary precision integers.] - - Description [Compares two arbitrary precision integers. Returns 1 if - the first number is larger; 0 if they are equal; -1 if the second - number is larger.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_ApaCompare( - int digitsFirst, - DdApaNumber first, - int digitsSecond, - DdApaNumber second) -{ - int i; - int firstNZ, secondNZ; - - /* Find first non-zero in both numbers. */ - for (firstNZ = 0; firstNZ < digitsFirst; firstNZ++) - if (first[firstNZ] != 0) break; - for (secondNZ = 0; secondNZ < digitsSecond; secondNZ++) - if (second[secondNZ] != 0) break; - if (digitsFirst - firstNZ > digitsSecond - secondNZ) return(1); - else if (digitsFirst - firstNZ < digitsSecond - secondNZ) return(-1); - for (i = 0; i < digitsFirst - firstNZ; i++) { - if (first[firstNZ + i] > second[secondNZ + i]) return(1); - else if (first[firstNZ + i] < second[secondNZ + i]) return(-1); - } - return(0); - -} /* end of Cudd_ApaCompare */ - - -/**Function******************************************************************** - - Synopsis [Compares the ratios of two arbitrary precision integers to two - unsigned ints.] - - Description [Compares the ratios of two arbitrary precision integers - to two unsigned ints. Returns 1 if the first number is larger; 0 if - they are equal; -1 if the second number is larger.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_ApaCompareRatios( - int digitsFirst, - DdApaNumber firstNum, - unsigned int firstDen, - int digitsSecond, - DdApaNumber secondNum, - unsigned int secondDen) -{ - int result; - DdApaNumber first, second; - unsigned int firstRem, secondRem; - - first = Cudd_NewApaNumber(digitsFirst); - firstRem = Cudd_ApaIntDivision(digitsFirst,firstNum,firstDen,first); - second = Cudd_NewApaNumber(digitsSecond); - secondRem = Cudd_ApaIntDivision(digitsSecond,secondNum,secondDen,second); - result = Cudd_ApaCompare(digitsFirst,first,digitsSecond,second); - if (result == 0) { - if ((double)firstRem/firstDen > (double)secondRem/secondDen) - return(1); - else if ((double)firstRem/firstDen < (double)secondRem/secondDen) - return(-1); - } - return(result); - -} /* end of Cudd_ApaCompareRatios */ - - -/**Function******************************************************************** - - Synopsis [Prints an arbitrary precision integer in hexadecimal format.] - - Description [Prints an arbitrary precision integer in hexadecimal format. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ApaPrintDecimal Cudd_ApaPrintExponential] - -******************************************************************************/ -int -Cudd_ApaPrintHex( - FILE * fp, - int digits, - DdApaNumber number) -{ - int i, result; - - for (i = 0; i < digits; i++) { - result = fprintf(fp,DD_APA_HEXPRINT,number[i]); - if (result == EOF) - return(0); - } - return(1); - -} /* end of Cudd_ApaPrintHex */ - - -/**Function******************************************************************** - - Synopsis [Prints an arbitrary precision integer in decimal format.] - - Description [Prints an arbitrary precision integer in decimal format. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintExponential] - -******************************************************************************/ -int -Cudd_ApaPrintDecimal( - FILE * fp, - int digits, - DdApaNumber number) -{ - int i, result; - DdApaDigit remainder; - DdApaNumber work; - unsigned char *decimal; - int leadingzero; - int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1; - - work = Cudd_NewApaNumber(digits); - if (work == NULL) - return(0); - decimal = ALLOC(unsigned char, decimalDigits); - if (decimal == NULL) { - FREE(work); - return(0); - } - Cudd_ApaCopy(digits,number,work); - for (i = decimalDigits - 1; i >= 0; i--) { - remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work); - decimal[i] = remainder; - } - FREE(work); - - leadingzero = 1; - for (i = 0; i < decimalDigits; i++) { - leadingzero = leadingzero && (decimal[i] == 0); - if ((!leadingzero) || (i == (decimalDigits - 1))) { - result = fprintf(fp,"%1d",decimal[i]); - if (result == EOF) { - FREE(decimal); - return(0); - } - } - } - FREE(decimal); - return(1); - -} /* end of Cudd_ApaPrintDecimal */ - - -/**Function******************************************************************** - - Synopsis [Prints an arbitrary precision integer in exponential format.] - - Description [Prints an arbitrary precision integer in exponential format. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintDecimal] - -******************************************************************************/ -int -Cudd_ApaPrintExponential( - FILE * fp, - int digits, - DdApaNumber number, - int precision) -{ - int i, first, last, result; - DdApaDigit remainder; - DdApaNumber work; - unsigned char *decimal; - int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1; - - work = Cudd_NewApaNumber(digits); - if (work == NULL) - return(0); - decimal = ALLOC(unsigned char, decimalDigits); - if (decimal == NULL) { - FREE(work); - return(0); - } - Cudd_ApaCopy(digits,number,work); - first = decimalDigits - 1; - for (i = decimalDigits - 1; i >= 0; i--) { - remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work); - decimal[i] = remainder; - if (remainder != 0) first = i; /* keep track of MS non-zero */ - } - FREE(work); - last = ddMin(first + precision, decimalDigits); - - for (i = first; i < last; i++) { - result = fprintf(fp,"%s%1d",i == first+1 ? "." : "", decimal[i]); - if (result == EOF) { - FREE(decimal); - return(0); - } - } - FREE(decimal); - result = fprintf(fp,"e+%d",decimalDigits - first - 1); - if (result == EOF) { - return(0); - } - return(1); - -} /* end of Cudd_ApaPrintExponential */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms of a DD.] - - Description [Counts the number of minterms of a DD. The function is - assumed to depend on nvars variables. The minterm count is - represented as an arbitrary precision unsigned integer, to allow for - any number of variables CUDD supports. Returns a pointer to the - array representing the number of minterms of the function rooted at - node if successful; NULL otherwise.] - - SideEffects [The number of digits of the result is returned in - parameter digits.] - - SeeAlso [Cudd_CountMinterm] - -******************************************************************************/ -DdApaNumber -Cudd_ApaCountMinterm( - DdManager * manager, - DdNode * node, - int nvars, - int * digits) -{ - DdApaNumber max, min; - st_table *table; - DdApaNumber i,count; - - background = manager->background; - zero = Cudd_Not(manager->one); - - *digits = Cudd_ApaNumberOfDigits(nvars+1); - max = Cudd_NewApaNumber(*digits); - if (max == NULL) { - return(NULL); - } - Cudd_ApaPowerOfTwo(*digits,max,nvars); - min = Cudd_NewApaNumber(*digits); - if (min == NULL) { - FREE(max); - return(NULL); - } - Cudd_ApaSetToLiteral(*digits,min,0); - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) { - FREE(max); - FREE(min); - return(NULL); - } - i = cuddApaCountMintermAux(Cudd_Regular(node),*digits,max,min,table); - if (i == NULL) { - FREE(max); - FREE(min); - st_foreach(table, cuddApaStCountfree, NULL); - st_free_table(table); - return(NULL); - } - count = Cudd_NewApaNumber(*digits); - if (count == NULL) { - FREE(max); - FREE(min); - st_foreach(table, cuddApaStCountfree, NULL); - st_free_table(table); - if (Cudd_Regular(node)->ref == 1) FREE(i); - return(NULL); - } - if (Cudd_IsComplement(node)) { - (void) Cudd_ApaSubtract(*digits,max,i,count); - } else { - Cudd_ApaCopy(*digits,i,count); - } - FREE(max); - FREE(min); - st_foreach(table, cuddApaStCountfree, NULL); - st_free_table(table); - if (Cudd_Regular(node)->ref == 1) FREE(i); - return(count); - -} /* end of Cudd_ApaCountMinterm */ - - -/**Function******************************************************************** - - Synopsis [Prints the number of minterms of a BDD or ADD using - arbitrary precision arithmetic.] - - Description [Prints the number of minterms of a BDD or ADD using - arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ApaPrintMintermExp] - -******************************************************************************/ -int -Cudd_ApaPrintMinterm( - FILE * fp, - DdManager * dd, - DdNode * node, - int nvars) -{ - int digits; - int result; - DdApaNumber count; - - count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); - if (count == NULL) - return(0); - result = Cudd_ApaPrintDecimal(fp,digits,count); - FREE(count); - if (fprintf(fp,"\n") == EOF) { - return(0); - } - return(result); - -} /* end of Cudd_ApaPrintMinterm */ - - -/**Function******************************************************************** - - Synopsis [Prints the number of minterms of a BDD or ADD in exponential - format using arbitrary precision arithmetic.] - - Description [Prints the number of minterms of a BDD or ADD in - exponential format using arbitrary precision arithmetic. Parameter - precision controls the number of signficant digits printed. Returns - 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ApaPrintMinterm] - -******************************************************************************/ -int -Cudd_ApaPrintMintermExp( - FILE * fp, - DdManager * dd, - DdNode * node, - int nvars, - int precision) -{ - int digits; - int result; - DdApaNumber count; - - count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); - if (count == NULL) - return(0); - result = Cudd_ApaPrintExponential(fp,digits,count,precision); - FREE(count); - if (fprintf(fp,"\n") == EOF) { - return(0); - } - return(result); - -} /* end of Cudd_ApaPrintMintermExp */ - - -/**Function******************************************************************** - - Synopsis [Prints the density of a BDD or ADD using - arbitrary precision arithmetic.] - - Description [Prints the density of a BDD or ADD using - arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_ApaPrintDensity( - FILE * fp, - DdManager * dd, - DdNode * node, - int nvars) -{ - int digits; - int result; - DdApaNumber count,density; - unsigned int size, remainder, fractional; - - count = Cudd_ApaCountMinterm(dd,node,nvars,&digits); - if (count == NULL) - return(0); - size = Cudd_DagSize(node); - density = Cudd_NewApaNumber(digits); - remainder = Cudd_ApaIntDivision(digits,count,size,density); - result = Cudd_ApaPrintDecimal(fp,digits,density); - FREE(count); - FREE(density); - fractional = (unsigned int)((double)remainder / size * 1000000); - if (fprintf(fp,".%u\n", fractional) == EOF) { - return(0); - } - return(result); - -} /* end of Cudd_ApaPrintDensity */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_ApaCountMinterm.] - - Description [Performs the recursive step of Cudd_ApaCountMinterm. - It is based on the following identity. Let |f| be the - number of minterms of f. Then: - - |f| = (|f0|+|f1|)/2 - - where f0 and f1 are the two cofactors of f. - Uses the identity |f'| = max - |f|. - The procedure expects the argument "node" to be a regular pointer, and - guarantees this condition is met in the recursive calls. - For efficiency, the result of a call is cached only if the node has - a reference count greater than 1. - Returns the number of minterms of the function rooted at node.] - - SideEffects [None] - -******************************************************************************/ -static DdApaNumber -cuddApaCountMintermAux( - DdNode * node, - int digits, - DdApaNumber max, - DdApaNumber min, - st_table * table) -{ - DdNode *Nt, *Ne; - DdApaNumber mint, mint1, mint2; - DdApaDigit carryout; - - if (cuddIsConstant(node)) { - if (node == background || node == zero) { - return(min); - } else { - return(max); - } - } - if (node->ref > 1 && st_lookup(table, (char *)node, (char **)&mint)) { - return(mint); - } - - Nt = cuddT(node); Ne = cuddE(node); - - mint1 = cuddApaCountMintermAux(Nt, digits, max, min, table); - if (mint1 == NULL) return(NULL); - mint2 = cuddApaCountMintermAux(Cudd_Regular(Ne), digits, max, min, table); - if (mint2 == NULL) { - if (Nt->ref == 1) FREE(mint1); - return(NULL); - } - mint = Cudd_NewApaNumber(digits); - if (mint == NULL) { - if (Nt->ref == 1) FREE(mint1); - if (Cudd_Regular(Ne)->ref == 1) FREE(mint2); - return(NULL); - } - if (Cudd_IsComplement(Ne)) { - (void) Cudd_ApaSubtract(digits,max,mint2,mint); - carryout = Cudd_ApaAdd(digits,mint1,mint,mint); - } else { - carryout = Cudd_ApaAdd(digits,mint1,mint2,mint); - } - Cudd_ApaShiftRight(digits,carryout,mint,mint); - /* If the refernce count of a child is 1, its minterm count - ** hasn't been stored in table. Therefore, it must be explicitly - ** freed here. */ - if (Nt->ref == 1) FREE(mint1); - if (Cudd_Regular(Ne)->ref == 1) FREE(mint2); - - if (node->ref > 1) { - if (st_insert(table, (char *)node, (char *)mint) == ST_OUT_OF_MEM) { - FREE(mint); - return(NULL); - } - } - return(mint); - -} /* end of cuddApaCountMintermAux */ - - -/**Function******************************************************************** - - Synopsis [Frees the memory used to store the minterm counts recorded - in the visited table.] - - Description [Frees the memory used to store the minterm counts - recorded in the visited table. Returns ST_CONTINUE.] - - SideEffects [None] - -******************************************************************************/ -static enum st_retval -cuddApaStCountfree( - char * key, - char * value, - char * arg) -{ - DdApaNumber d; - - d = (DdApaNumber) value; - FREE(d); - return(ST_CONTINUE); - -} /* end of cuddApaStCountfree */ - - diff --git a/src/bdd/cudd/cuddApprox.c b/src/bdd/cudd/cuddApprox.c deleted file mode 100644 index debcf48b..00000000 --- a/src/bdd/cudd/cuddApprox.c +++ /dev/null @@ -1,2192 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddApprox.c] - - PackageName [cudd] - - Synopsis [Procedures to approximate a given BDD.] - - Description [External procedures provided by this module: -
          -
        • Cudd_UnderApprox() -
        • Cudd_OverApprox() -
        • Cudd_RemapUnderApprox() -
        • Cudd_RemapOverApprox() -
        • Cudd_BiasedUnderApprox() -
        • Cudd_BiasedOverApprox() -
        - Internal procedures included in this module: -
          -
        • cuddUnderApprox() -
        • cuddRemapUnderApprox() -
        • cuddBiasedUnderApprox() -
        - Static procedures included in this module: -
          -
        • gatherInfoAux() -
        • gatherInfo() -
        • computeSavings() -
        • UAmarkNodes() -
        • UAbuildSubset() -
        • updateRefs() -
        • RAmarkNodes() -
        • BAmarkNodes() -
        • RAbuildSubset() -
        - ] - - SeeAlso [cuddSubsetHB.c cuddSubsetSP.c cuddGenCof.c] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no - warranty about the suitability of this software for any - purpose. It is presented on an AS IS basis.] - -******************************************************************************/ - -#ifdef __STDC__ -#include -#else -#define DBL_MAX_EXP 1024 -#endif -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define NOTHING 0 -#define REPLACE_T 1 -#define REPLACE_E 2 -#define REPLACE_N 3 -#define REPLACE_TT 4 -#define REPLACE_TE 5 - -#define DONT_CARE 0 -#define CARE 1 -#define TOTAL_CARE 2 -#define CARE_ERROR 3 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/* Data structure to store the information on each node. It keeps the -** number of minterms of the function rooted at this node in terms of -** the number of variables specified by the user; the number of -** minterms of the complement; the impact of the number of minterms of -** this function on the number of minterms of the root function; the -** reference count of the node from within the root function; the -** reference count of the node from an internal node; and the flag -** that says whether the node should be replaced and how. */ -typedef struct NodeData { - double mintermsP; /* minterms for the regular node */ - double mintermsN; /* minterms for the complemented node */ - int functionRef; /* references from within this function */ - char care; /* node intersects care set */ - char replace; /* replacement decision */ - short int parity; /* 1: even; 2: odd; 3: both */ - DdNode *resultP; /* result for even parity */ - DdNode *resultN; /* result for odd parity */ -} NodeData; - -typedef struct ApproxInfo { - DdNode *one; /* one constant */ - DdNode *zero; /* BDD zero constant */ - NodeData *page; /* per-node information */ - st_table *table; /* hash table to access the per-node info */ - int index; /* index of the current node */ - double max; /* max number of minterms */ - int size; /* how many nodes are left */ - double minterms; /* how many minterms are left */ -} ApproxInfo; - -/* Item of the queue used in the levelized traversal of the BDD. */ -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif -typedef struct GlobalQueueItem { - struct GlobalQueueItem *next; - struct GlobalQueueItem *cnext; - DdNode *node; - double impactP; - double impactN; -} GlobalQueueItem; - -typedef struct LocalQueueItem { - struct LocalQueueItem *next; - struct LocalQueueItem *cnext; - DdNode *node; - int localRef; -} LocalQueueItem; -#ifdef __osf__ -#pragma pointer_size restore -#endif - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddApprox.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void updateParity ARGS((DdNode *node, ApproxInfo *info, int newparity)); -static NodeData * gatherInfoAux ARGS((DdNode *node, ApproxInfo *info, int parity)); -static ApproxInfo * gatherInfo ARGS((DdManager *dd, DdNode *node, int numVars, int parity)); -static int computeSavings ARGS((DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue)); -static int updateRefs ARGS((DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue)); -static int UAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, int safe, double quality)); -static DdNode * UAbuildSubset ARGS((DdManager *dd, DdNode *node, ApproxInfo *info)); -static int RAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality)); -static int BAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality1, double quality0)); -static DdNode * RAbuildSubset ARGS((DdManager *dd, DdNode *node, ApproxInfo *info)); -static int BAapplyBias ARGS((DdManager *dd, DdNode *f, DdNode *b, ApproxInfo *info, DdHashTable *cache)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Extracts a dense subset from a BDD with Shiple's - underapproximation method.] - - Description [Extracts a dense subset from a BDD. This procedure uses - a variant of Tom Shiple's underapproximation method. The main - difference from the original method is that density is used as cost - function. Returns a pointer to the BDD of the subset if - successful. NULL if the procedure runs out of memory. The parameter - numVars is the maximum number of variables to be used in minterm - calculation. The optimal number should be as close as possible to - the size of the support of f. However, it is safe to pass the value - returned by Cudd_ReadSize for numVars when the number of variables - is under 1023. If numVars is larger than 1023, it will cause - overflow. If a 0 parameter is passed then the procedure will compute - a value which will avoid overflow but will cause underflow with 2046 - variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_UnderApprox( - DdManager * dd /* manager */, - DdNode * f /* function to be subset */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - int safe /* enforce safe approximation */, - double quality /* minimum improvement for accepted changes */) -{ - DdNode *subset; - - do { - dd->reordered = 0; - subset = cuddUnderApprox(dd, f, numVars, threshold, safe, quality); - } while (dd->reordered == 1); - - return(subset); - -} /* end of Cudd_UnderApprox */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense superset from a BDD with Shiple's - underapproximation method.] - - Description [Extracts a dense superset from a BDD. The procedure is - identical to the underapproximation procedure except for the fact that it - works on the complement of the given function. Extracting the subset - of the complement function is equivalent to extracting the superset - of the function. - Returns a pointer to the BDD of the superset if successful. NULL if - intermediate result causes the procedure to run out of memory. The - parameter numVars is the maximum number of variables to be used in - minterm calculation. The optimal number - should be as close as possible to the size of the support of f. - However, it is safe to pass the value returned by Cudd_ReadSize for - numVars when the number of variables is under 1023. If numVars is - larger than 1023, it will overflow. If a 0 parameter is passed then - the procedure will compute a value which will avoid overflow but - will cause underflow with 2046 variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_OverApprox( - DdManager * dd /* manager */, - DdNode * f /* function to be superset */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - int safe /* enforce safe approximation */, - double quality /* minimum improvement for accepted changes */) -{ - DdNode *subset, *g; - - g = Cudd_Not(f); - do { - dd->reordered = 0; - subset = cuddUnderApprox(dd, g, numVars, threshold, safe, quality); - } while (dd->reordered == 1); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_OverApprox */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense subset from a BDD with the remapping - underapproximation method.] - - Description [Extracts a dense subset from a BDD. This procedure uses - a remapping technique and density as the cost function. - Returns a pointer to the BDD of the subset if - successful. NULL if the procedure runs out of memory. The parameter - numVars is the maximum number of variables to be used in minterm - calculation. The optimal number should be as close as possible to - the size of the support of f. However, it is safe to pass the value - returned by Cudd_ReadSize for numVars when the number of variables - is under 1023. If numVars is larger than 1023, it will cause - overflow. If a 0 parameter is passed then the procedure will compute - a value which will avoid overflow but will cause underflow with 2046 - variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_RemapUnderApprox( - DdManager * dd /* manager */, - DdNode * f /* function to be subset */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - double quality /* minimum improvement for accepted changes */) -{ - DdNode *subset; - - do { - dd->reordered = 0; - subset = cuddRemapUnderApprox(dd, f, numVars, threshold, quality); - } while (dd->reordered == 1); - - return(subset); - -} /* end of Cudd_RemapUnderApprox */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense superset from a BDD with the remapping - underapproximation method.] - - Description [Extracts a dense superset from a BDD. The procedure is - identical to the underapproximation procedure except for the fact that it - works on the complement of the given function. Extracting the subset - of the complement function is equivalent to extracting the superset - of the function. - Returns a pointer to the BDD of the superset if successful. NULL if - intermediate result causes the procedure to run out of memory. The - parameter numVars is the maximum number of variables to be used in - minterm calculation. The optimal number - should be as close as possible to the size of the support of f. - However, it is safe to pass the value returned by Cudd_ReadSize for - numVars when the number of variables is under 1023. If numVars is - larger than 1023, it will overflow. If a 0 parameter is passed then - the procedure will compute a value which will avoid overflow but - will cause underflow with 2046 variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_RemapOverApprox( - DdManager * dd /* manager */, - DdNode * f /* function to be superset */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - double quality /* minimum improvement for accepted changes */) -{ - DdNode *subset, *g; - - g = Cudd_Not(f); - do { - dd->reordered = 0; - subset = cuddRemapUnderApprox(dd, g, numVars, threshold, quality); - } while (dd->reordered == 1); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_RemapOverApprox */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense subset from a BDD with the biased - underapproximation method.] - - Description [Extracts a dense subset from a BDD. This procedure uses - a biased remapping technique and density as the cost function. The bias - is a function. This procedure tries to approximate where the bias is 0 - and preserve the given function where the bias is 1. - Returns a pointer to the BDD of the subset if - successful. NULL if the procedure runs out of memory. The parameter - numVars is the maximum number of variables to be used in minterm - calculation. The optimal number should be as close as possible to - the size of the support of f. However, it is safe to pass the value - returned by Cudd_ReadSize for numVars when the number of variables - is under 1023. If numVars is larger than 1023, it will cause - overflow. If a 0 parameter is passed then the procedure will compute - a value which will avoid overflow but will cause underflow with 2046 - variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch Cudd_UnderApprox - Cudd_RemapUnderApprox Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_BiasedUnderApprox( - DdManager *dd /* manager */, - DdNode *f /* function to be subset */, - DdNode *b /* bias function */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - double quality1 /* minimum improvement for accepted changes when b=1 */, - double quality0 /* minimum improvement for accepted changes when b=0 */) -{ - DdNode *subset; - - do { - dd->reordered = 0; - subset = cuddBiasedUnderApprox(dd, f, b, numVars, threshold, quality1, - quality0); - } while (dd->reordered == 1); - - return(subset); - -} /* end of Cudd_BiasedUnderApprox */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense superset from a BDD with the biased - underapproximation method.] - - Description [Extracts a dense superset from a BDD. The procedure is - identical to the underapproximation procedure except for the fact that it - works on the complement of the given function. Extracting the subset - of the complement function is equivalent to extracting the superset - of the function. - Returns a pointer to the BDD of the superset if successful. NULL if - intermediate result causes the procedure to run out of memory. The - parameter numVars is the maximum number of variables to be used in - minterm calculation. The optimal number - should be as close as possible to the size of the support of f. - However, it is safe to pass the value returned by Cudd_ReadSize for - numVars when the number of variables is under 1023. If numVars is - larger than 1023, it will overflow. If a 0 parameter is passed then - the procedure will compute a value which will avoid overflow but - will cause underflow with 2046 variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SupersetHeavyBranch Cudd_SupersetShortPaths - Cudd_RemapOverApprox Cudd_BiasedUnderApprox Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_BiasedOverApprox( - DdManager *dd /* manager */, - DdNode *f /* function to be superset */, - DdNode *b /* bias function */, - int numVars /* number of variables in the support of f */, - int threshold /* when to stop approximation */, - double quality1 /* minimum improvement for accepted changes when b=1*/, - double quality0 /* minimum improvement for accepted changes when b=0 */) -{ - DdNode *subset, *g; - - g = Cudd_Not(f); - do { - dd->reordered = 0; - subset = cuddBiasedUnderApprox(dd, g, b, numVars, threshold, quality1, - quality0); - } while (dd->reordered == 1); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_BiasedOverApprox */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Applies Tom Shiple's underappoximation algorithm.] - - Description [Applies Tom Shiple's underappoximation algorithm. Proceeds - in three phases: -
          -
        • collect information on each node in the BDD; this is done via DFS. -
        • traverse the BDD in top-down fashion and compute for each node - whether its elimination increases density. -
        • traverse the BDD via DFS and actually perform the elimination. -
        - Returns the approximated BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_UnderApprox] - -******************************************************************************/ -DdNode * -cuddUnderApprox( - DdManager * dd /* DD manager */, - DdNode * f /* current DD */, - int numVars /* maximum number of variables */, - int threshold /* threshold under which approximation stops */, - int safe /* enforce safe approximation */, - double quality /* minimum improvement for accepted changes */) -{ - ApproxInfo *info; - DdNode *subset; - int result; - - if (f == NULL) { - fprintf(dd->err, "Cannot subset, nil object\n"); - return(NULL); - } - - if (Cudd_IsConstant(f)) { - return(f); - } - - /* Create table where node data are accessible via a hash table. */ - info = gatherInfo(dd, f, numVars, safe); - if (info == NULL) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - /* Mark nodes that should be replaced by zero. */ - result = UAmarkNodes(dd, f, info, threshold, safe, quality); - if (result == 0) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - FREE(info->page); - st_free_table(info->table); - FREE(info); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - /* Build the result. */ - subset = UAbuildSubset(dd, f, info); -#if 1 - if (subset && info->size < Cudd_DagSize(subset)) - (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", - info->size, Cudd_DagSize(subset)); -#endif - FREE(info->page); - st_free_table(info->table); - FREE(info); - -#ifdef DD_DEBUG - if (subset != NULL) { - cuddRef(subset); -#if 0 - (void) Cudd_DebugCheck(dd); - (void) Cudd_CheckKeys(dd); -#endif - if (!Cudd_bddLeq(dd, subset, f)) { - (void) fprintf(dd->err, "Wrong subset\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - } - cuddDeref(subset); - } -#endif - return(subset); - -} /* end of cuddUnderApprox */ - - -/**Function******************************************************************** - - Synopsis [Applies the remapping underappoximation algorithm.] - - Description [Applies the remapping underappoximation algorithm. - Proceeds in three phases: -
          -
        • collect information on each node in the BDD; this is done via DFS. -
        • traverse the BDD in top-down fashion and compute for each node - whether remapping increases density. -
        • traverse the BDD via DFS and actually perform the elimination. -
        - Returns the approximated BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_RemapUnderApprox] - -******************************************************************************/ -DdNode * -cuddRemapUnderApprox( - DdManager * dd /* DD manager */, - DdNode * f /* current DD */, - int numVars /* maximum number of variables */, - int threshold /* threshold under which approximation stops */, - double quality /* minimum improvement for accepted changes */) -{ - ApproxInfo *info; - DdNode *subset; - int result; - - if (f == NULL) { - fprintf(dd->err, "Cannot subset, nil object\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - if (Cudd_IsConstant(f)) { - return(f); - } - - /* Create table where node data are accessible via a hash table. */ - info = gatherInfo(dd, f, numVars, TRUE); - if (info == NULL) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - /* Mark nodes that should be replaced by zero. */ - result = RAmarkNodes(dd, f, info, threshold, quality); - if (result == 0) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - FREE(info->page); - st_free_table(info->table); - FREE(info); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - /* Build the result. */ - subset = RAbuildSubset(dd, f, info); -#if 1 - if (subset && info->size < Cudd_DagSize(subset)) - (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", - info->size, Cudd_DagSize(subset)); -#endif - FREE(info->page); - st_free_table(info->table); - FREE(info); - -#ifdef DD_DEBUG - if (subset != NULL) { - cuddRef(subset); -#if 0 - (void) Cudd_DebugCheck(dd); - (void) Cudd_CheckKeys(dd); -#endif - if (!Cudd_bddLeq(dd, subset, f)) { - (void) fprintf(dd->err, "Wrong subset\n"); - } - cuddDeref(subset); - dd->errorCode = CUDD_INTERNAL_ERROR; - } -#endif - return(subset); - -} /* end of cuddRemapUnderApprox */ - - -/**Function******************************************************************** - - Synopsis [Applies the biased remapping underappoximation algorithm.] - - Description [Applies the biased remapping underappoximation algorithm. - Proceeds in three phases: -
          -
        • collect information on each node in the BDD; this is done via DFS. -
        • traverse the BDD in top-down fashion and compute for each node - whether remapping increases density. -
        • traverse the BDD via DFS and actually perform the elimination. -
        - Returns the approximated BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_BiasedUnderApprox] - -******************************************************************************/ -DdNode * -cuddBiasedUnderApprox( - DdManager *dd /* DD manager */, - DdNode *f /* current DD */, - DdNode *b /* bias function */, - int numVars /* maximum number of variables */, - int threshold /* threshold under which approximation stops */, - double quality1 /* minimum improvement for accepted changes when b=1 */, - double quality0 /* minimum improvement for accepted changes when b=1 */) -{ - ApproxInfo *info; - DdNode *subset; - int result; - DdHashTable *cache; - - if (f == NULL) { - fprintf(dd->err, "Cannot subset, nil object\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - if (Cudd_IsConstant(f)) { - return(f); - } - - /* Create table where node data are accessible via a hash table. */ - info = gatherInfo(dd, f, numVars, TRUE); - if (info == NULL) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - cache = cuddHashTableInit(dd,2,2); - result = BAapplyBias(dd, Cudd_Regular(f), b, info, cache); - if (result == CARE_ERROR) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - cuddHashTableQuit(cache); - FREE(info->page); - st_free_table(info->table); - FREE(info); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - cuddHashTableQuit(cache); - - /* Mark nodes that should be replaced by zero. */ - result = BAmarkNodes(dd, f, info, threshold, quality1, quality0); - if (result == 0) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - FREE(info->page); - st_free_table(info->table); - FREE(info); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - /* Build the result. */ - subset = RAbuildSubset(dd, f, info); -#if 1 - if (subset && info->size < Cudd_DagSize(subset)) - (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n", - info->size, Cudd_DagSize(subset)); -#endif - FREE(info->page); - st_free_table(info->table); - FREE(info); - -#ifdef DD_DEBUG - if (subset != NULL) { - cuddRef(subset); -#if 0 - (void) Cudd_DebugCheck(dd); - (void) Cudd_CheckKeys(dd); -#endif - if (!Cudd_bddLeq(dd, subset, f)) { - (void) fprintf(dd->err, "Wrong subset\n"); - } - cuddDeref(subset); - dd->errorCode = CUDD_INTERNAL_ERROR; - } -#endif - return(subset); - -} /* end of cuddBiasedUnderApprox */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Recursively update the parity of the paths reaching a node.] - - Description [Recursively update the parity of the paths reaching a node. - Assumes that node is regular and propagates the invariant.] - - SideEffects [None] - - SeeAlso [gatherInfoAux] - -******************************************************************************/ -static void -updateParity( - DdNode * node /* function to analyze */, - ApproxInfo * info /* info on BDD */, - int newparity /* new parity for node */) -{ - NodeData *infoN; - DdNode *E; - - if (!st_lookup(info->table, (char *)node, (char **)&infoN)) return; - if ((infoN->parity & newparity) != 0) return; - infoN->parity |= newparity; - if (Cudd_IsConstant(node)) return; - updateParity(cuddT(node),info,newparity); - E = cuddE(node); - if (Cudd_IsComplement(E)) { - updateParity(Cudd_Not(E),info,3-newparity); - } else { - updateParity(E,info,newparity); - } - return; - -} /* end of updateParity */ - - -/**Function******************************************************************** - - Synopsis [Recursively counts minterms and computes reference counts - of each node in the BDD.] - - Description [Recursively counts minterms and computes reference - counts of each node in the BDD. Similar to the cuddCountMintermAux - which recursively counts the number of minterms for the dag rooted - at each node in terms of the total number of variables (max). It assumes - that the node pointer passed to it is regular and it maintains the - invariant.] - - SideEffects [None] - - SeeAlso [gatherInfo] - -******************************************************************************/ -static NodeData * -gatherInfoAux( - DdNode * node /* function to analyze */, - ApproxInfo * info /* info on BDD */, - int parity /* gather parity information */) -{ - DdNode *N, *Nt, *Ne; - NodeData *infoN, *infoT, *infoE; - - N = Cudd_Regular(node); - - /* Check whether entry for this node exists. */ - if (st_lookup(info->table, (char *)N, (char **)&infoN)) { - if (parity) { - /* Update parity and propagate. */ - updateParity(N, info, 1 + (int) Cudd_IsComplement(node)); - } - return(infoN); - } - - /* Compute the cofactors. */ - Nt = Cudd_NotCond(cuddT(N), N != node); - Ne = Cudd_NotCond(cuddE(N), N != node); - - infoT = gatherInfoAux(Nt, info, parity); - if (infoT == NULL) return(NULL); - infoE = gatherInfoAux(Ne, info, parity); - if (infoE == NULL) return(NULL); - - infoT->functionRef++; - infoE->functionRef++; - - /* Point to the correct location in the page. */ - infoN = &(info->page[info->index++]); - infoN->parity |= 1 + (short) Cudd_IsComplement(node); - - infoN->mintermsP = infoT->mintermsP/2; - infoN->mintermsN = infoT->mintermsN/2; - if (Cudd_IsComplement(Ne) ^ Cudd_IsComplement(node)) { - infoN->mintermsP += infoE->mintermsN/2; - infoN->mintermsN += infoE->mintermsP/2; - } else { - infoN->mintermsP += infoE->mintermsP/2; - infoN->mintermsN += infoE->mintermsN/2; - } - - /* Insert entry for the node in the table. */ - if (st_insert(info->table,(char *)N, (char *)infoN) == ST_OUT_OF_MEM) { - return(NULL); - } - return(infoN); - -} /* end of gatherInfoAux */ - - -/**Function******************************************************************** - - Synopsis [Gathers information about each node.] - - Description [Counts minterms and computes reference counts of each - node in the BDD . The minterm count is separately computed for the - node and its complement. This is to avoid cancellation - errors. Returns a pointer to the data structure holding the - information gathered if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddUnderApprox gatherInfoAux] - -******************************************************************************/ -static ApproxInfo * -gatherInfo( - DdManager * dd /* manager */, - DdNode * node /* function to be analyzed */, - int numVars /* number of variables node depends on */, - int parity /* gather parity information */) -{ - ApproxInfo *info; - NodeData *infoTop; - - /* If user did not give numVars value, set it to the maximum - ** exponent that the pow function can take. The -1 is due to the - ** discrepancy in the value that pow takes and the value that - ** log gives. - */ - if (numVars == 0) { - numVars = DBL_MAX_EXP - 1; - } - - info = ALLOC(ApproxInfo,1); - if (info == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - info->max = pow(2.0,(double) numVars); - info->one = DD_ONE(dd); - info->zero = Cudd_Not(info->one); - info->size = Cudd_DagSize(node); - /* All the information gathered will be stored in a contiguous - ** piece of memory, which is allocated here. This can be done - ** efficiently because we have counted the number of nodes of the - ** BDD. info->index points to the next available entry in the array - ** that stores the per-node information. */ - info->page = ALLOC(NodeData,info->size); - if (info->page == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(info); - return(NULL); - } - memset(info->page, 0, info->size * sizeof(NodeData)); /* clear all page */ - info->table = st_init_table(st_ptrcmp,st_ptrhash); - if (info->table == NULL) { - FREE(info->page); - FREE(info); - return(NULL); - } - /* We visit the DAG in post-order DFS. Hence, the constant node is - ** in first position, and the root of the DAG is in last position. */ - - /* Info for the constant node: Initialize only fields different from 0. */ - if (st_insert(info->table, (char *)info->one, (char *)info->page) == ST_OUT_OF_MEM) { - FREE(info->page); - FREE(info); - st_free_table(info->table); - return(NULL); - } - info->page[0].mintermsP = info->max; - info->index = 1; - - infoTop = gatherInfoAux(node,info,parity); - if (infoTop == NULL) { - FREE(info->page); - st_free_table(info->table); - FREE(info); - return(NULL); - } - if (Cudd_IsComplement(node)) { - info->minterms = infoTop->mintermsN; - } else { - info->minterms = infoTop->mintermsP; - } - - infoTop->functionRef = 1; - return(info); - -} /* end of gatherInfo */ - - -/**Function******************************************************************** - - Synopsis [Counts the nodes that would be eliminated if a given node - were replaced by zero.] - - Description [Counts the nodes that would be eliminated if a given - node were replaced by zero. This procedure uses a queue passed by - the caller for efficiency: since the queue is left empty at the - endof the search, it can be reused as is by the next search. Returns - the count (always striclty positive) if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddUnderApprox] - -******************************************************************************/ -static int -computeSavings( - DdManager * dd, - DdNode * f, - DdNode * skip, - ApproxInfo * info, - DdLevelQueue * queue) -{ - NodeData *infoN; - LocalQueueItem *item; - DdNode *node; - int savings = 0; - - node = Cudd_Regular(f); - skip = Cudd_Regular(skip); - /* Insert the given node in the level queue. Its local reference - ** count is set equal to the function reference count so that the - ** search will continue from it when it is retrieved. */ - item = (LocalQueueItem *) - cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); - if (item == NULL) - return(0); - (void) st_lookup(info->table, (char *)node, (char **)&infoN); - item->localRef = infoN->functionRef; - - /* Process the queue. */ - while (queue->first != NULL) { - item = (LocalQueueItem *) queue->first; - node = item->node; - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); - if (node == skip) continue; - (void) st_lookup(info->table, (char *)node, (char **)&infoN); - if (item->localRef != infoN->functionRef) { - /* This node is shared. */ - continue; - } - savings++; - if (!cuddIsConstant(cuddT(node))) { - item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), - cuddI(dd,cuddT(node)->index)); - if (item == NULL) return(0); - item->localRef++; - } - if (!Cudd_IsConstant(cuddE(node))) { - item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), - cuddI(dd,Cudd_Regular(cuddE(node))->index)); - if (item == NULL) return(0); - item->localRef++; - } - } - -#ifdef DD_DEBUG - /* At the end of a local search the queue should be empty. */ - assert(queue->size == 0); -#endif - return(savings); - -} /* end of computeSavings */ - - -/**Function******************************************************************** - - Synopsis [Update function reference counts.] - - Description [Update function reference counts to account for replacement. - Returns the number of nodes saved if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [UAmarkNodes RAmarkNodes] - -******************************************************************************/ -static int -updateRefs( - DdManager * dd, - DdNode * f, - DdNode * skip, - ApproxInfo * info, - DdLevelQueue * queue) -{ - NodeData *infoN; - LocalQueueItem *item; - DdNode *node; - int savings = 0; - - node = Cudd_Regular(f); - /* Insert the given node in the level queue. Its function reference - ** count is set equal to 0 so that the search will continue from it - ** when it is retrieved. */ - item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); - if (item == NULL) - return(0); - (void) st_lookup(info->table, (char *)node, (char **)&infoN); - infoN->functionRef = 0; - - if (skip != NULL) { - /* Increase the function reference count of the node to be skipped - ** by 1 to account for the node pointing to it that will be created. */ - skip = Cudd_Regular(skip); - (void) st_lookup(info->table, (char *)skip, (char **)&infoN); - infoN->functionRef++; - } - - /* Process the queue. */ - while (queue->first != NULL) { - item = (LocalQueueItem *) queue->first; - node = item->node; - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); - (void) st_lookup(info->table, (char *)node, (char **)&infoN); - if (infoN->functionRef != 0) { - /* This node is shared or must be skipped. */ - continue; - } - savings++; - if (!cuddIsConstant(cuddT(node))) { - item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), - cuddI(dd,cuddT(node)->index)); - if (item == NULL) return(0); - (void) st_lookup(info->table, (char *)cuddT(node), - (char **)&infoN); - infoN->functionRef--; - } - if (!Cudd_IsConstant(cuddE(node))) { - item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), - cuddI(dd,Cudd_Regular(cuddE(node))->index)); - if (item == NULL) return(0); - (void) st_lookup(info->table, (char *)Cudd_Regular(cuddE(node)), - (char **)&infoN); - infoN->functionRef--; - } - } - -#ifdef DD_DEBUG - /* At the end of a local search the queue should be empty. */ - assert(queue->size == 0); -#endif - return(savings); - -} /* end of updateRefs */ - - -/**Function******************************************************************** - - Synopsis [Marks nodes for replacement by zero.] - - Description [Marks nodes for replacement by zero. Returns 1 if successful; - 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddUnderApprox] - -******************************************************************************/ -static int -UAmarkNodes( - DdManager * dd /* manager */, - DdNode * f /* function to be analyzed */, - ApproxInfo * info /* info on BDD */, - int threshold /* when to stop approximating */, - int safe /* enforce safe approximation */, - double quality /* minimum improvement for accepted changes */) -{ - DdLevelQueue *queue; - DdLevelQueue *localQueue; - NodeData *infoN; - GlobalQueueItem *item; - DdNode *node; - double numOnset; - double impactP, impactN; - int savings; - -#if 0 - (void) printf("initial size = %d initial minterms = %g\n", - info->size, info->minterms); -#endif - queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); - if (queue == NULL) { - return(0); - } - localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), - dd->initSlots); - if (localQueue == NULL) { - cuddLevelQueueQuit(queue); - return(0); - } - node = Cudd_Regular(f); - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); - if (item == NULL) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - if (Cudd_IsComplement(f)) { - item->impactP = 0.0; - item->impactN = 1.0; - } else { - item->impactP = 1.0; - item->impactN = 0.0; - } - while (queue->first != NULL) { - /* If the size of the subset is below the threshold, quit. */ - if (info->size <= threshold) - break; - item = (GlobalQueueItem *) queue->first; - node = item->node; - node = Cudd_Regular(node); - (void) st_lookup(info->table, (char *)node, (char **)&infoN); - if (safe && infoN->parity == 3) { - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); - continue; - } - impactP = item->impactP; - impactN = item->impactN; - numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; - savings = computeSavings(dd,node,NULL,info,localQueue); - if (savings == 0) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); -#if 0 - (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", - node, impactP, impactN, numOnset, savings); -#endif - if ((1 - numOnset / info->minterms) > - quality * (1 - (double) savings / info->size)) { - infoN->replace = TRUE; - info->size -= savings; - info->minterms -=numOnset; -#if 0 - (void) printf("replace: new size = %d new minterms = %g\n", - info->size, info->minterms); -#endif - savings -= updateRefs(dd,node,NULL,info,localQueue); - assert(savings == 0); - continue; - } - if (!cuddIsConstant(cuddT(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), - cuddI(dd,cuddT(node)->index)); - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - if (!Cudd_IsConstant(cuddE(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), - cuddI(dd,Cudd_Regular(cuddE(node))->index)); - if (Cudd_IsComplement(cuddE(node))) { - item->impactP += impactN/2.0; - item->impactN += impactP/2.0; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - } - - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(1); - -} /* end of UAmarkNodes */ - - -/**Function******************************************************************** - - Synopsis [Builds the subset BDD.] - - Description [Builds the subset BDD. Based on the info table, - replaces selected nodes by zero. Returns a pointer to the result if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddUnderApprox] - -******************************************************************************/ -static DdNode * -UAbuildSubset( - DdManager * dd /* DD manager */, - DdNode * node /* current node */, - ApproxInfo * info /* node info */) -{ - - DdNode *Nt, *Ne, *N, *t, *e, *r; - NodeData *infoN; - - if (Cudd_IsConstant(node)) - return(node); - - N = Cudd_Regular(node); - - if (st_lookup(info->table, (char *)N, (char **)&infoN)) { - if (infoN->replace == TRUE) { - return(info->zero); - } - if (N == node ) { - if (infoN->resultP != NULL) { - return(infoN->resultP); - } - } else { - if (infoN->resultN != NULL) { - return(infoN->resultN); - } - } - } else { - (void) fprintf(dd->err, - "Something is wrong, ought to be in info table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - - Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node)); - Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node)); - - t = UAbuildSubset(dd, Nt, info); - if (t == NULL) { - return(NULL); - } - cuddRef(t); - - e = UAbuildSubset(dd, Ne, info); - if (e == NULL) { - Cudd_RecursiveDeref(dd,t); - return(NULL); - } - cuddRef(e); - - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - - if (N == node) { - infoN->resultP = r; - } else { - infoN->resultN = r; - } - - return(r); - -} /* end of UAbuildSubset */ - - -/**Function******************************************************************** - - Synopsis [Marks nodes for remapping.] - - Description [Marks nodes for remapping. Returns 1 if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddRemapUnderApprox] - -******************************************************************************/ -static int -RAmarkNodes( - DdManager * dd /* manager */, - DdNode * f /* function to be analyzed */, - ApproxInfo * info /* info on BDD */, - int threshold /* when to stop approximating */, - double quality /* minimum improvement for accepted changes */) -{ - DdLevelQueue *queue; - DdLevelQueue *localQueue; - NodeData *infoN, *infoT, *infoE; - GlobalQueueItem *item; - DdNode *node, *T, *E; - DdNode *shared; /* grandchild shared by the two children of node */ - double numOnset; - double impact, impactP, impactN; - double minterms; - int savings; - int replace; - -#if 0 - (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n", - info->size, info->minterms); -#endif - queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); - if (queue == NULL) { - return(0); - } - localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), - dd->initSlots); - if (localQueue == NULL) { - cuddLevelQueueQuit(queue); - return(0); - } - /* Enqueue regular pointer to root and initialize impact. */ - node = Cudd_Regular(f); - item = (GlobalQueueItem *) - cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); - if (item == NULL) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - if (Cudd_IsComplement(f)) { - item->impactP = 0.0; - item->impactN = 1.0; - } else { - item->impactP = 1.0; - item->impactN = 0.0; - } - /* The nodes retrieved here are guaranteed to be non-terminal. - ** The initial node is not terminal because constant nodes are - ** dealt with in the calling procedure. Subsequent nodes are inserted - ** only if they are not terminal. */ - while (queue->first != NULL) { - /* If the size of the subset is below the threshold, quit. */ - if (info->size <= threshold) - break; - item = (GlobalQueueItem *) queue->first; - node = item->node; -#ifdef DD_DEBUG - assert(item->impactP >= 0 && item->impactP <= 1.0); - assert(item->impactN >= 0 && item->impactN <= 1.0); - assert(!Cudd_IsComplement(node)); - assert(!Cudd_IsConstant(node)); -#endif - if (!st_lookup(info->table, (char *)node, (char **)&infoN)) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } -#ifdef DD_DEBUG - assert(infoN->parity >= 1 && infoN->parity <= 3); -#endif - if (infoN->parity == 3) { - /* This node can be reached through paths of different parity. - ** It is not safe to replace it, because remapping will give - ** an incorrect result, while replacement by 0 may cause node - ** splitting. */ - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); - continue; - } - T = cuddT(node); - E = cuddE(node); - shared = NULL; - impactP = item->impactP; - impactN = item->impactN; - if (Cudd_bddLeq(dd,T,E)) { - /* Here we know that E is regular. */ -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(E)); -#endif - (void) st_lookup(info->table, (char *)T, (char **)&infoT); - (void) st_lookup(info->table, (char *)E, (char **)&infoE); - if (infoN->parity == 1) { - impact = impactP; - minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0; - if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { - savings = 1 + computeSavings(dd,E,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_E; - } else { -#ifdef DD_DEBUG - assert(infoN->parity == 2); -#endif - impact = impactN; - minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0; - if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { - savings = 1 + computeSavings(dd,T,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_T; - } - numOnset = impact * minterms; - } else if (Cudd_bddLeq(dd,E,T)) { - /* Here E may be complemented. */ - DdNode *Ereg = Cudd_Regular(E); - (void) st_lookup(info->table, (char *)T, (char **)&infoT); - (void) st_lookup(info->table, (char *)Ereg, (char **)&infoE); - if (infoN->parity == 1) { - impact = impactP; - minterms = infoT->mintermsP/2.0 - - ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0; - if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { - savings = 1 + computeSavings(dd,T,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_T; - } else { -#ifdef DD_DEBUG - assert(infoN->parity == 2); -#endif - impact = impactN; - minterms = ((E == Ereg) ? infoE->mintermsN : - infoE->mintermsP)/2.0 - infoT->mintermsN/2.0; - if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { - savings = 1 + computeSavings(dd,E,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_E; - } - numOnset = impact * minterms; - } else { - DdNode *Ereg = Cudd_Regular(E); - DdNode *TT = cuddT(T); - DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E)); - if (T->index == Ereg->index && TT == ET) { - shared = TT; - replace = REPLACE_TT; - } else { - DdNode *TE = cuddE(T); - DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E)); - if (T->index == Ereg->index && TE == EE) { - shared = TE; - replace = REPLACE_TE; - } else { - replace = REPLACE_N; - } - } - numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; - savings = computeSavings(dd,node,shared,info,localQueue); - if (shared != NULL) { - NodeData *infoS; - (void) st_lookup(info->table, (char *)Cudd_Regular(shared), - (char **)&infoS); - if (Cudd_IsComplement(shared)) { - numOnset -= (infoS->mintermsN * impactP + - infoS->mintermsP * impactN)/2.0; - } else { - numOnset -= (infoS->mintermsP * impactP + - infoS->mintermsN * impactN)/2.0; - } - savings--; - } - } - - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); -#if 0 - if (replace == REPLACE_T || replace == REPLACE_E) - (void) printf("node %p: impact = %g numOnset = %g savings %d\n", - node, impact, numOnset, savings); - else - (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", - node, impactP, impactN, numOnset, savings); -#endif - if ((1 - numOnset / info->minterms) > - quality * (1 - (double) savings / info->size)) { - infoN->replace = replace; - info->size -= savings; - info->minterms -=numOnset; -#if 0 - (void) printf("remap(%d): new size = %d new minterms = %g\n", - replace, info->size, info->minterms); -#endif - if (replace == REPLACE_N) { - savings -= updateRefs(dd,node,NULL,info,localQueue); - } else if (replace == REPLACE_T) { - savings -= updateRefs(dd,node,E,info,localQueue); - } else if (replace == REPLACE_E) { - savings -= updateRefs(dd,node,T,info,localQueue); - } else { -#ifdef DD_DEBUG - assert(replace == REPLACE_TT || replace == REPLACE_TE); -#endif - savings -= updateRefs(dd,node,shared,info,localQueue) - 1; - } - assert(savings == 0); - } else { - replace = NOTHING; - } - if (replace == REPLACE_N) continue; - if ((replace == REPLACE_E || replace == NOTHING) && - !cuddIsConstant(cuddT(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), - cuddI(dd,cuddT(node)->index)); - if (replace == REPLACE_E) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - if ((replace == REPLACE_T || replace == NOTHING) && - !Cudd_IsConstant(cuddE(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), - cuddI(dd,Cudd_Regular(cuddE(node))->index)); - if (Cudd_IsComplement(cuddE(node))) { - if (replace == REPLACE_T) { - item->impactP += impactN; - item->impactN += impactP; - } else { - item->impactP += impactN/2.0; - item->impactN += impactP/2.0; - } - } else { - if (replace == REPLACE_T) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - } - if ((replace == REPLACE_TT || replace == REPLACE_TE) && - !Cudd_IsConstant(shared)) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared), - cuddI(dd,Cudd_Regular(shared)->index)); - if (Cudd_IsComplement(shared)) { - if (replace == REPLACE_T) { - item->impactP += impactN; - item->impactN += impactP; - } else { - item->impactP += impactN/2.0; - item->impactN += impactP/2.0; - } - } else { - if (replace == REPLACE_T) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - } - } - - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(1); - -} /* end of RAmarkNodes */ - - -/**Function******************************************************************** - - Synopsis [Marks nodes for remapping.] - - Description [Marks nodes for remapping. Returns 1 if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddRemapUnderApprox] - -******************************************************************************/ -static int -BAmarkNodes( - DdManager *dd /* manager */, - DdNode *f /* function to be analyzed */, - ApproxInfo *info /* info on BDD */, - int threshold /* when to stop approximating */, - double quality1 /* minimum improvement for accepted changes when b=1 */, - double quality0 /* minimum improvement for accepted changes when b=0 */) -{ - DdLevelQueue *queue; - DdLevelQueue *localQueue; - NodeData *infoN, *infoT, *infoE; - GlobalQueueItem *item; - DdNode *node, *T, *E; - DdNode *shared; /* grandchild shared by the two children of node */ - double numOnset; - double impact, impactP, impactN; - double minterms; - double quality; - int savings; - int replace; - -#if 0 - (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n", - info->size, info->minterms); -#endif - queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size); - if (queue == NULL) { - return(0); - } - localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem), - dd->initSlots); - if (localQueue == NULL) { - cuddLevelQueueQuit(queue); - return(0); - } - /* Enqueue regular pointer to root and initialize impact. */ - node = Cudd_Regular(f); - item = (GlobalQueueItem *) - cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index)); - if (item == NULL) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - if (Cudd_IsComplement(f)) { - item->impactP = 0.0; - item->impactN = 1.0; - } else { - item->impactP = 1.0; - item->impactN = 0.0; - } - /* The nodes retrieved here are guaranteed to be non-terminal. - ** The initial node is not terminal because constant nodes are - ** dealt with in the calling procedure. Subsequent nodes are inserted - ** only if they are not terminal. */ - while (queue->first != NULL) { - /* If the size of the subset is below the threshold, quit. */ - if (info->size <= threshold) - break; - item = (GlobalQueueItem *) queue->first; - node = item->node; -#ifdef DD_DEBUG - assert(item->impactP >= 0 && item->impactP <= 1.0); - assert(item->impactN >= 0 && item->impactN <= 1.0); - assert(!Cudd_IsComplement(node)); - assert(!Cudd_IsConstant(node)); -#endif - if (!st_lookup(info->table, (char *)node, (char **)&infoN)) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - quality = infoN->care ? quality1 : quality0; -#ifdef DD_DEBUG - assert(infoN->parity >= 1 && infoN->parity <= 3); -#endif - if (infoN->parity == 3) { - /* This node can be reached through paths of different parity. - ** It is not safe to replace it, because remapping will give - ** an incorrect result, while replacement by 0 may cause node - ** splitting. */ - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); - continue; - } - T = cuddT(node); - E = cuddE(node); - shared = NULL; - impactP = item->impactP; - impactN = item->impactN; - if (Cudd_bddLeq(dd,T,E)) { - /* Here we know that E is regular. */ -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(E)); -#endif - (void) st_lookup(info->table, (char *)T, (char **)&infoT); - (void) st_lookup(info->table, (char *)E, (char **)&infoE); - if (infoN->parity == 1) { - impact = impactP; - minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0; - if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { - savings = 1 + computeSavings(dd,E,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_E; - } else { -#ifdef DD_DEBUG - assert(infoN->parity == 2); -#endif - impact = impactN; - minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0; - if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { - savings = 1 + computeSavings(dd,T,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_T; - } - numOnset = impact * minterms; - } else if (Cudd_bddLeq(dd,E,T)) { - /* Here E may be complemented. */ - DdNode *Ereg = Cudd_Regular(E); - (void) st_lookup(info->table, (char *)T, (char **)&infoT); - (void) st_lookup(info->table, (char *)Ereg, (char **)&infoE); - if (infoN->parity == 1) { - impact = impactP; - minterms = infoT->mintermsP/2.0 - - ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0; - if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) { - savings = 1 + computeSavings(dd,T,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_T; - } else { -#ifdef DD_DEBUG - assert(infoN->parity == 2); -#endif - impact = impactN; - minterms = ((E == Ereg) ? infoE->mintermsN : - infoE->mintermsP)/2.0 - infoT->mintermsN/2.0; - if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) { - savings = 1 + computeSavings(dd,E,NULL,info,localQueue); - if (savings == 1) { - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(0); - } - } else { - savings = 1; - } - replace = REPLACE_E; - } - numOnset = impact * minterms; - } else { - DdNode *Ereg = Cudd_Regular(E); - DdNode *TT = cuddT(T); - DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E)); - if (T->index == Ereg->index && TT == ET) { - shared = TT; - replace = REPLACE_TT; - } else { - DdNode *TE = cuddE(T); - DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E)); - if (T->index == Ereg->index && TE == EE) { - shared = TE; - replace = REPLACE_TE; - } else { - replace = REPLACE_N; - } - } - numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN; - savings = computeSavings(dd,node,shared,info,localQueue); - if (shared != NULL) { - NodeData *infoS; - (void) st_lookup(info->table, (char *)Cudd_Regular(shared), - (char **)&infoS); - if (Cudd_IsComplement(shared)) { - numOnset -= (infoS->mintermsN * impactP + - infoS->mintermsP * impactN)/2.0; - } else { - numOnset -= (infoS->mintermsP * impactP + - infoS->mintermsN * impactN)/2.0; - } - savings--; - } - } - - cuddLevelQueueDequeue(queue,cuddI(dd,node->index)); -#if 0 - if (replace == REPLACE_T || replace == REPLACE_E) - (void) printf("node %p: impact = %g numOnset = %g savings %d\n", - node, impact, numOnset, savings); - else - (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n", - node, impactP, impactN, numOnset, savings); -#endif - if ((1 - numOnset / info->minterms) > - quality * (1 - (double) savings / info->size)) { - infoN->replace = replace; - info->size -= savings; - info->minterms -=numOnset; -#if 0 - (void) printf("remap(%d): new size = %d new minterms = %g\n", - replace, info->size, info->minterms); -#endif - if (replace == REPLACE_N) { - savings -= updateRefs(dd,node,NULL,info,localQueue); - } else if (replace == REPLACE_T) { - savings -= updateRefs(dd,node,E,info,localQueue); - } else if (replace == REPLACE_E) { - savings -= updateRefs(dd,node,T,info,localQueue); - } else { -#ifdef DD_DEBUG - assert(replace == REPLACE_TT || replace == REPLACE_TE); -#endif - savings -= updateRefs(dd,node,shared,info,localQueue) - 1; - } - assert(savings == 0); - } else { - replace = NOTHING; - } - if (replace == REPLACE_N) continue; - if ((replace == REPLACE_E || replace == NOTHING) && - !cuddIsConstant(cuddT(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node), - cuddI(dd,cuddT(node)->index)); - if (replace == REPLACE_E) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - if ((replace == REPLACE_T || replace == NOTHING) && - !Cudd_IsConstant(cuddE(node))) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)), - cuddI(dd,Cudd_Regular(cuddE(node))->index)); - if (Cudd_IsComplement(cuddE(node))) { - if (replace == REPLACE_T) { - item->impactP += impactN; - item->impactN += impactP; - } else { - item->impactP += impactN/2.0; - item->impactN += impactP/2.0; - } - } else { - if (replace == REPLACE_T) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - } - if ((replace == REPLACE_TT || replace == REPLACE_TE) && - !Cudd_IsConstant(shared)) { - item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared), - cuddI(dd,Cudd_Regular(shared)->index)); - if (Cudd_IsComplement(shared)) { - if (replace == REPLACE_T) { - item->impactP += impactN; - item->impactN += impactP; - } else { - item->impactP += impactN/2.0; - item->impactN += impactP/2.0; - } - } else { - if (replace == REPLACE_T) { - item->impactP += impactP; - item->impactN += impactN; - } else { - item->impactP += impactP/2.0; - item->impactN += impactN/2.0; - } - } - } - } - - cuddLevelQueueQuit(queue); - cuddLevelQueueQuit(localQueue); - return(1); - -} /* end of BAmarkNodes */ - - -/**Function******************************************************************** - - Synopsis [Builds the subset BDD for cuddRemapUnderApprox.] - - Description [Builds the subset BDDfor cuddRemapUnderApprox. Based - on the info table, performs remapping or replacement at selected - nodes. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [cuddRemapUnderApprox] - -******************************************************************************/ -static DdNode * -RAbuildSubset( - DdManager * dd /* DD manager */, - DdNode * node /* current node */, - ApproxInfo * info /* node info */) -{ - DdNode *Nt, *Ne, *N, *t, *e, *r; - NodeData *infoN; - - if (Cudd_IsConstant(node)) - return(node); - - N = Cudd_Regular(node); - - Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node)); - Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node)); - - if (st_lookup(info->table, (char *)N, (char **)&infoN)) { - if (N == node ) { - if (infoN->resultP != NULL) { - return(infoN->resultP); - } - } else { - if (infoN->resultN != NULL) { - return(infoN->resultN); - } - } - if (infoN->replace == REPLACE_T) { - r = RAbuildSubset(dd, Ne, info); - return(r); - } else if (infoN->replace == REPLACE_E) { - r = RAbuildSubset(dd, Nt, info); - return(r); - } else if (infoN->replace == REPLACE_N) { - return(info->zero); - } else if (infoN->replace == REPLACE_TT) { - DdNode *Ntt = Cudd_NotCond(cuddT(cuddT(N)), - Cudd_IsComplement(node)); - int index = cuddT(N)->index; - DdNode *e = info->zero; - DdNode *t = RAbuildSubset(dd, Ntt, info); - if (t == NULL) { - return(NULL); - } - cuddRef(t); - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - } - cuddDeref(t); - return(r); - } else if (infoN->replace == REPLACE_TE) { - DdNode *Nte = Cudd_NotCond(cuddE(cuddT(N)), - Cudd_IsComplement(node)); - int index = cuddT(N)->index; - DdNode *t = info->one; - DdNode *e = RAbuildSubset(dd, Nte, info); - if (e == NULL) { - return(NULL); - } - cuddRef(e); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - r =Cudd_Not(r); - cuddDeref(e); - return(r); - } - } else { - (void) fprintf(dd->err, - "Something is wrong, ought to be in info table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - - t = RAbuildSubset(dd, Nt, info); - if (t == NULL) { - return(NULL); - } - cuddRef(t); - - e = RAbuildSubset(dd, Ne, info); - if (e == NULL) { - Cudd_RecursiveDeref(dd,t); - return(NULL); - } - cuddRef(e); - - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - - if (N == node) { - infoN->resultP = r; - } else { - infoN->resultN = r; - } - - return(r); - -} /* end of RAbuildSubset */ - - -/**Function******************************************************************** - - Synopsis [Finds don't care nodes.] - - Description [Finds don't care nodes by traversing f and b in parallel. - Returns the care status of the visited f node if successful; CARE_ERROR - otherwise.] - - SideEffects [None] - - SeeAlso [cuddBiasedUnderApprox] - -******************************************************************************/ -static int -BAapplyBias( - DdManager *dd, - DdNode *f, - DdNode *b, - ApproxInfo *info, - DdHashTable *cache) -{ - DdNode *one, *zero, *res; - DdNode *Ft, *Fe, *B, *Bt, *Be; - unsigned int topf, topb; - NodeData *infoF; - int careT, careE; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - if (!st_lookup(info->table, (char *) f, (char **)&infoF)) - return(CARE_ERROR); - if (f == one) return(TOTAL_CARE); - if (b == zero) return(infoF->care); - if (infoF->care == TOTAL_CARE) return(TOTAL_CARE); - - if ((f->ref != 1 || Cudd_Regular(b)->ref != 1) && - (res = cuddHashTableLookup2(cache,f,b)) != NULL) { - if (res->ref == 0) { - cache->manager->dead++; - cache->manager->constants.dead++; - } - return(infoF->care); - } - - topf = dd->perm[f->index]; - B = Cudd_Regular(b); - topb = cuddI(dd,B->index); - if (topf <= topb) { - Ft = cuddT(f); Fe = cuddE(f); - } else { - Ft = Fe = f; - } - if (topb <= topf) { - /* We know that b is not constant because f is not. */ - Bt = cuddT(B); Be = cuddE(B); - if (Cudd_IsComplement(b)) { - Bt = Cudd_Not(Bt); - Be = Cudd_Not(Be); - } - } else { - Bt = Be = b; - } - - careT = BAapplyBias(dd, Ft, Bt, info, cache); - if (careT == CARE_ERROR) - return(CARE_ERROR); - careE = BAapplyBias(dd, Cudd_Regular(Fe), Be, info, cache); - if (careE == CARE_ERROR) - return(CARE_ERROR); - if (careT == TOTAL_CARE && careE == TOTAL_CARE) { - infoF->care = TOTAL_CARE; - } else { - infoF->care = CARE; - } - - if (f->ref != 1 || Cudd_Regular(b)->ref != 1) { - ptrint fanout = (ptrint) f->ref * Cudd_Regular(b)->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert2(cache,f,b,one,fanout)) { - return(CARE_ERROR); - } - } - return(infoF->care); - -} /* end of BAapplyBias */ diff --git a/src/bdd/cudd/cuddBddAbs.c b/src/bdd/cudd/cuddBddAbs.c deleted file mode 100644 index 9552464e..00000000 --- a/src/bdd/cudd/cuddBddAbs.c +++ /dev/null @@ -1,689 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddBddAbs.c] - - PackageName [cudd] - - Synopsis [Quantification functions for BDDs.] - - Description [External procedures included in this module: -
          -
        • Cudd_bddExistAbstract() -
        • Cudd_bddXorExistAbstract() -
        • Cudd_bddUnivAbstract() -
        • Cudd_bddBooleanDiff() -
        • Cudd_bddVarIsDependent() -
        - Internal procedures included in this module: -
          -
        • cuddBddExistAbstractRecur() -
        • cuddBddXorExistAbstractRecur() -
        • cuddBddBooleanDiffRecur() -
        - Static procedures included in this module: -
          -
        • bddCheckPositiveCube() -
        - ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddBddAbs.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int bddCheckPositiveCube ARGS((DdManager *manager, DdNode *cube)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Existentially abstracts all the variables in cube from f.] - - Description [Existentially abstracts all the variables in cube from f. - Returns the abstracted BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddUnivAbstract Cudd_addExistAbstract] - -******************************************************************************/ -DdNode * -Cudd_bddExistAbstract( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *res; - - if (bddCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err, - "Error: Can only abstract positive cubes\n"); - manager->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddBddExistAbstractRecur(manager, f, cube); - } while (manager->reordered == 1); - - return(res); - -} /* end of Cudd_bddExistAbstract */ - - -/**Function******************************************************************** - - Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Takes the exclusive OR of two BDDs and simultaneously abstracts - the variables in cube. The variables are existentially abstracted. Returns a - pointer to the result is successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddUnivAbstract Cudd_bddExistAbstract Cudd_bddAndAbstract] - -******************************************************************************/ -DdNode * -Cudd_bddXorExistAbstract( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube) -{ - DdNode *res; - - if (bddCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err, - "Error: Can only abstract positive cubes\n"); - manager->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddBddXorExistAbstractRecur(manager, f, g, cube); - } while (manager->reordered == 1); - - return(res); - -} /* end of Cudd_bddXorExistAbstract */ - - -/**Function******************************************************************** - - Synopsis [Universally abstracts all the variables in cube from f.] - - Description [Universally abstracts all the variables in cube from f. - Returns the abstracted BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddExistAbstract Cudd_addUnivAbstract] - -******************************************************************************/ -DdNode * -Cudd_bddUnivAbstract( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *res; - - if (bddCheckPositiveCube(manager, cube) == 0) { - (void) fprintf(manager->err, - "Error: Can only abstract positive cubes\n"); - manager->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - do { - manager->reordered = 0; - res = cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube); - } while (manager->reordered == 1); - if (res != NULL) res = Cudd_Not(res); - - return(res); - -} /* end of Cudd_bddUnivAbstract */ - - -/**Function******************************************************************** - - Synopsis [Computes the boolean difference of f with respect to x.] - - Description [Computes the boolean difference of f with respect to the - variable with index x. Returns the BDD of the boolean difference if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_bddBooleanDiff( - DdManager * manager, - DdNode * f, - int x) -{ - DdNode *res, *var; - - /* If the variable is not currently in the manager, f cannot - ** depend on it. - */ - if (x >= manager->size) return(Cudd_Not(DD_ONE(manager))); - var = manager->vars[x]; - - do { - manager->reordered = 0; - res = cuddBddBooleanDiffRecur(manager, Cudd_Regular(f), var); - } while (manager->reordered == 1); - - return(res); - -} /* end of Cudd_bddBooleanDiff */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variable is dependent on others in a - function.] - - Description [Checks whether a variable is dependent on others in a - function. Returns 1 if the variable is dependent; 0 otherwise. No - new nodes are created.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_bddVarIsDependent( - DdManager *dd, /* manager */ - DdNode *f, /* function */ - DdNode *var /* variable */) -{ - DdNode *F, *res, *zero, *ft, *fe; - unsigned topf, level; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - int retval; - - zero = Cudd_Not(DD_ONE(dd)); - if (Cudd_IsConstant(f)) return(f == zero); - - /* From now on f is not constant. */ - F = Cudd_Regular(f); - topf = (unsigned) dd->perm[F->index]; - level = (unsigned) dd->perm[var->index]; - - /* Check terminal case. If topf > index of var, f does not depend on var. - ** Therefore, var is not dependent in f. */ - if (topf > level) { - return(0); - } - - cacheOp = - (DdNode *(*)(DdManager *, DdNode *, DdNode *)) Cudd_bddVarIsDependent; - res = cuddCacheLookup2(dd,cacheOp,f,var); - if (res != NULL) { - return(res != zero); - } - - /* Compute cofactors. */ - ft = Cudd_NotCond(cuddT(F), f != F); - fe = Cudd_NotCond(cuddE(F), f != F); - - if (topf == level) { - retval = Cudd_bddLeq(dd,ft,Cudd_Not(fe)); - } else { - retval = Cudd_bddVarIsDependent(dd,ft,var) && - Cudd_bddVarIsDependent(dd,fe,var); - } - - cuddCacheInsert2(dd,cacheOp,f,var,Cudd_NotCond(zero,retval)); - - return(retval); - -} /* Cudd_bddVarIsDependent */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive steps of Cudd_bddExistAbstract.] - - Description [Performs the recursive steps of Cudd_bddExistAbstract. - Returns the BDD obtained by abstracting the variables - of cube from f if successful; NULL otherwise. It is also used by - Cudd_bddUnivAbstract.] - - SideEffects [None] - - SeeAlso [Cudd_bddExistAbstract Cudd_bddUnivAbstract] - -******************************************************************************/ -DdNode * -cuddBddExistAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * cube) -{ - DdNode *F, *T, *E, *res, *res1, *res2, *one; - - statLine(manager); - one = DD_ONE(manager); - F = Cudd_Regular(f); - - /* Cube is guaranteed to be a cube at this point. */ - if (cube == one || F == one) { - return(f); - } - /* From now on, f and cube are non-constant. */ - - /* Abstract a variable that does not appear in f. */ - while (manager->perm[F->index] > manager->perm[cube->index]) { - cube = cuddT(cube); - if (cube == one) return(f); - } - - /* Check the cache. */ - if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) { - return(res); - } - - /* Compute the cofactors of f. */ - T = cuddT(F); E = cuddE(F); - if (f != F) { - T = Cudd_Not(T); E = Cudd_Not(E); - } - - /* If the two indices are the same, so are their levels. */ - if (F->index == cube->index) { - if (T == one || E == one || T == Cudd_Not(E)) { - return(one); - } - res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube)); - if (res1 == NULL) return(NULL); - if (res1 == one) { - if (F->ref != 1) - cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one); - return(one); - } - cuddRef(res1); - res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube)); - if (res2 == NULL) { - Cudd_IterDerefBdd(manager,res1); - return(NULL); - } - cuddRef(res2); - res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2)); - if (res == NULL) { - Cudd_IterDerefBdd(manager, res1); - Cudd_IterDerefBdd(manager, res2); - return(NULL); - } - res = Cudd_Not(res); - cuddRef(res); - Cudd_IterDerefBdd(manager, res1); - Cudd_IterDerefBdd(manager, res2); - if (F->ref != 1) - cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); - cuddDeref(res); - return(res); - } else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */ - res1 = cuddBddExistAbstractRecur(manager, T, cube); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddBddExistAbstractRecur(manager, E, cube); - if (res2 == NULL) { - Cudd_IterDerefBdd(manager, res1); - return(NULL); - } - cuddRef(res2); - /* ITE takes care of possible complementation of res1 and of the - ** case in which res1 == res2. */ - res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2); - if (res == NULL) { - Cudd_IterDerefBdd(manager, res1); - Cudd_IterDerefBdd(manager, res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - if (F->ref != 1) - cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); - return(res); - } - -} /* end of cuddBddExistAbstractRecur */ - - -/**Function******************************************************************** - - Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Takes the exclusive OR of two BDDs and simultaneously abstracts - the variables in cube. The variables are existentially abstracted. Returns a - pointer to the result is successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddAndAbstract] - -******************************************************************************/ -DdNode * -cuddBddXorExistAbstractRecur( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube) -{ - DdNode *F, *fv, *fnv, *G, *gv, *gnv; - DdNode *one, *zero, *r, *t, *e, *Cube; - unsigned int topf, topg, topcube, top, index; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == g) { - return(zero); - } - if (f == Cudd_Not(g)) { - return(one); - } - if (cube == one) { - return(cuddBddXorRecur(manager, f, g)); - } - if (f == one) { - return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube)); - } - if (g == one) { - return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube)); - } - if (f == zero) { - return(cuddBddExistAbstractRecur(manager, g, cube)); - } - if (g == zero) { - return(cuddBddExistAbstractRecur(manager, f, cube)); - } - - /* At this point f, g, and cube are not constant. */ - - if (f > g) { /* Try to increase cache efficiency. */ - DdNode *tmp = f; - f = g; - g = tmp; - } - - /* Check cache. */ - r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube); - if (r != NULL) { - return(r); - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - F = Cudd_Regular(f); - topf = manager->perm[F->index]; - G = Cudd_Regular(g); - topg = manager->perm[G->index]; - top = ddMin(topf, topg); - topcube = manager->perm[cube->index]; - - if (topcube < top) { - return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube))); - } - /* Now, topcube >= top. */ - - if (topf == top) { - index = F->index; - fv = cuddT(F); - fnv = cuddE(F); - if (Cudd_IsComplement(f)) { - fv = Cudd_Not(fv); - fnv = Cudd_Not(fnv); - } - } else { - index = G->index; - fv = fnv = f; - } - - if (topg == top) { - gv = cuddT(G); - gnv = cuddE(G); - if (Cudd_IsComplement(g)) { - gv = Cudd_Not(gv); - gnv = Cudd_Not(gnv); - } - } else { - gv = gnv = g; - } - - if (topcube == top) { - Cube = cuddT(cube); - } else { - Cube = cube; - } - - t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube); - if (t == NULL) return(NULL); - - /* Special case: 1 OR anything = 1. Hence, no need to compute - ** the else branch if t is 1. - */ - if (t == one && topcube == top) { - cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one); - return(one); - } - cuddRef(t); - - e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube); - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - cuddRef(e); - - if (topcube == top) { /* abstract */ - r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - cuddRef(r); - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - cuddDeref(r); - } else if (t == e) { - r = t; - cuddDeref(t); - cuddDeref(e); - } else { - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - } - cuddDeref(e); - cuddDeref(t); - } - cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r); - return (r); - -} /* end of cuddBddXorExistAbstractRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive steps of Cudd_bddBoleanDiff.] - - Description [Performs the recursive steps of Cudd_bddBoleanDiff. - Returns the BDD obtained by XORing the cofactors of f with respect to - var if successful; NULL otherwise. Exploits the fact that dF/dx = - dF'/dx.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddBddBooleanDiffRecur( - DdManager * manager, - DdNode * f, - DdNode * var) -{ - DdNode *T, *E, *res, *res1, *res2; - - statLine(manager); - if (cuddI(manager,f->index) > manager->perm[var->index]) { - /* f does not depend on var. */ - return(Cudd_Not(DD_ONE(manager))); - } - - /* From now on, f is non-constant. */ - - /* If the two indices are the same, so are their levels. */ - if (f->index == var->index) { - res = cuddBddXorRecur(manager, cuddT(f), cuddE(f)); - return(res); - } - - /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */ - - /* Check the cache. */ - res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var); - if (res != NULL) { - return(res); - } - - /* Compute the cofactors of f. */ - T = cuddT(f); E = cuddE(f); - - res1 = cuddBddBooleanDiffRecur(manager, T, var); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var); - if (res2 == NULL) { - Cudd_IterDerefBdd(manager, res1); - return(NULL); - } - cuddRef(res2); - /* ITE takes care of possible complementation of res1 and of the - ** case in which res1 == res2. */ - res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2); - if (res == NULL) { - Cudd_IterDerefBdd(manager, res1); - Cudd_IterDerefBdd(manager, res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res); - return(res); - -} /* end of cuddBddBooleanDiffRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Checks whether cube is an BDD representing the product of - positive literals.] - - Description [Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -bddCheckPositiveCube( - DdManager * manager, - DdNode * cube) -{ - if (Cudd_IsComplement(cube)) return(0); - if (cube == DD_ONE(manager)) return(1); - if (cuddIsConstant(cube)) return(0); - if (cuddE(cube) == Cudd_Not(DD_ONE(manager))) { - return(bddCheckPositiveCube(manager, cuddT(cube))); - } - return(0); - -} /* end of bddCheckPositiveCube */ - diff --git a/src/bdd/cudd/cuddBddCorr.c b/src/bdd/cudd/cuddBddCorr.c deleted file mode 100644 index c99324a8..00000000 --- a/src/bdd/cudd/cuddBddCorr.c +++ /dev/null @@ -1,481 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddBddCorr.c] - - PackageName [cudd] - - Synopsis [Correlation between BDDs.] - - Description [External procedures included in this module: -
          -
        • Cudd_bddCorrelation() -
        • Cudd_bddCorrelationWeights() -
        - Static procedures included in this module: -
          -
        • bddCorrelationAux() -
        • bddCorrelationWeightsAux() -
        • CorrelCompare() -
        • CorrelHash() -
        • CorrelCleanUp() -
        - ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -typedef struct hashEntry { - DdNode *f; - DdNode *g; -} HashEntry; - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddBddCorr.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -#ifdef CORREL_STATS -static int num_calls; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static double bddCorrelationAux ARGS((DdManager *dd, DdNode *f, DdNode *g, st_table *table)); -static double bddCorrelationWeightsAux ARGS((DdManager *dd, DdNode *f, DdNode *g, double *prob, st_table *table)); -static int CorrelCompare ARGS((const char *key1, const char *key2)); -static int CorrelHash ARGS((char *key, int modulus)); -static enum st_retval CorrelCleanUp ARGS((char *key, char *value, char *arg)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the correlation of f and g.] - - Description [Computes the correlation of f and g. If f == g, their - correlation is 1. If f == g', their correlation is 0. Returns the - fraction of minterms in the ON-set of the EXNOR of f and g. If it - runs out of memory, returns (double)CUDD_OUT_OF_MEM.] - - SideEffects [None] - - SeeAlso [Cudd_bddCorrelationWeights] - -******************************************************************************/ -double -Cudd_bddCorrelation( - DdManager * manager, - DdNode * f, - DdNode * g) -{ - - st_table *table; - double correlation; - -#ifdef CORREL_STATS - num_calls = 0; -#endif - - table = st_init_table(CorrelCompare,CorrelHash); - if (table == NULL) return((double)CUDD_OUT_OF_MEM); - correlation = bddCorrelationAux(manager,f,g,table); - st_foreach(table, CorrelCleanUp, NIL(char)); - st_free_table(table); - return(correlation); - -} /* end of Cudd_bddCorrelation */ - - -/**Function******************************************************************** - - Synopsis [Computes the correlation of f and g for given input - probabilities.] - - Description [Computes the correlation of f and g for given input - probabilities. On input, prob\[i\] is supposed to contain the - probability of the i-th input variable to be 1. - If f == g, their correlation is 1. If f == g', their - correlation is 0. Returns the probability that f and g have the same - value. If it runs out of memory, returns (double)CUDD_OUT_OF_MEM. The - correlation of f and the constant one gives the probability of f.] - - SideEffects [None] - - SeeAlso [Cudd_bddCorrelation] - -******************************************************************************/ -double -Cudd_bddCorrelationWeights( - DdManager * manager, - DdNode * f, - DdNode * g, - double * prob) -{ - - st_table *table; - double correlation; - -#ifdef CORREL_STATS - num_calls = 0; -#endif - - table = st_init_table(CorrelCompare,CorrelHash); - if (table == NULL) return((double)CUDD_OUT_OF_MEM); - correlation = bddCorrelationWeightsAux(manager,f,g,prob,table); - st_foreach(table, CorrelCleanUp, NIL(char)); - st_free_table(table); - return(correlation); - -} /* end of Cudd_bddCorrelationWeights */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddCorrelation.] - - Description [Performs the recursive step of Cudd_bddCorrelation. - Returns the fraction of minterms in the ON-set of the EXNOR of f and - g.] - - SideEffects [None] - - SeeAlso [bddCorrelationWeightsAux] - -******************************************************************************/ -static double -bddCorrelationAux( - DdManager * dd, - DdNode * f, - DdNode * g, - st_table * table) -{ - DdNode *Fv, *Fnv, *G, *Gv, *Gnv; - double min, *pmin, min1, min2, *dummy; - HashEntry *entry; - unsigned int topF, topG; - - statLine(dd); -#ifdef CORREL_STATS - num_calls++; -#endif - - /* Terminal cases: only work for BDDs. */ - if (f == g) return(1.0); - if (f == Cudd_Not(g)) return(0.0); - - /* Standardize call using the following properties: - ** (f EXNOR g) = (g EXNOR f) - ** (f' EXNOR g') = (f EXNOR g). - */ - if (f > g) { - DdNode *tmp = f; - f = g; g = tmp; - } - if (Cudd_IsComplement(f)) { - f = Cudd_Not(f); - g = Cudd_Not(g); - } - /* From now on, f is regular. */ - - entry = ALLOC(HashEntry,1); - if (entry == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(CUDD_OUT_OF_MEM); - } - entry->f = f; entry->g = g; - - /* We do not use the fact that - ** correlation(f,g') = 1 - correlation(f,g) - ** to minimize the risk of cancellation. - */ - if (st_lookup(table, (char *)entry, (char **)&dummy)) { - min = *dummy; - FREE(entry); - return(min); - } - - G = Cudd_Regular(g); - topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); - if (topF <= topG) { Fv = cuddT(f); Fnv = cuddE(f); } else { Fv = Fnv = f; } - if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } - - if (g != G) { - Gv = Cudd_Not(Gv); - Gnv = Cudd_Not(Gnv); - } - - min1 = bddCorrelationAux(dd, Fv, Gv, table) / 2.0; - if (min1 == (double)CUDD_OUT_OF_MEM) { - FREE(entry); - return(CUDD_OUT_OF_MEM); - } - min2 = bddCorrelationAux(dd, Fnv, Gnv, table) / 2.0; - if (min2 == (double)CUDD_OUT_OF_MEM) { - FREE(entry); - return(CUDD_OUT_OF_MEM); - } - min = (min1+min2); - - pmin = ALLOC(double,1); - if (pmin == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return((double)CUDD_OUT_OF_MEM); - } - *pmin = min; - - if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) { - FREE(entry); - FREE(pmin); - return((double)CUDD_OUT_OF_MEM); - } - return(min); - -} /* end of bddCorrelationAux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddCorrelationWeigths.] - - Description [] - - SideEffects [None] - - SeeAlso [bddCorrelationAux] - -******************************************************************************/ -static double -bddCorrelationWeightsAux( - DdManager * dd, - DdNode * f, - DdNode * g, - double * prob, - st_table * table) -{ - DdNode *Fv, *Fnv, *G, *Gv, *Gnv; - double min, *pmin, min1, min2, *dummy; - HashEntry *entry; - int topF, topG, index; - - statLine(dd); -#ifdef CORREL_STATS - num_calls++; -#endif - - /* Terminal cases: only work for BDDs. */ - if (f == g) return(1.0); - if (f == Cudd_Not(g)) return(0.0); - - /* Standardize call using the following properties: - ** (f EXNOR g) = (g EXNOR f) - ** (f' EXNOR g') = (f EXNOR g). - */ - if (f > g) { - DdNode *tmp = f; - f = g; g = tmp; - } - if (Cudd_IsComplement(f)) { - f = Cudd_Not(f); - g = Cudd_Not(g); - } - /* From now on, f is regular. */ - - entry = ALLOC(HashEntry,1); - if (entry == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return((double)CUDD_OUT_OF_MEM); - } - entry->f = f; entry->g = g; - - /* We do not use the fact that - ** correlation(f,g') = 1 - correlation(f,g) - ** to minimize the risk of cancellation. - */ - if (st_lookup(table, (char *)entry, (char **)&dummy)) { - min = *dummy; - FREE(entry); - return(min); - } - - G = Cudd_Regular(g); - topF = cuddI(dd,f->index); topG = cuddI(dd,G->index); - if (topF <= topG) { - Fv = cuddT(f); Fnv = cuddE(f); - index = f->index; - } else { - Fv = Fnv = f; - index = G->index; - } - if (topG <= topF) { Gv = cuddT(G); Gnv = cuddE(G); } else { Gv = Gnv = G; } - - if (g != G) { - Gv = Cudd_Not(Gv); - Gnv = Cudd_Not(Gnv); - } - - min1 = bddCorrelationWeightsAux(dd, Fv, Gv, prob, table) * prob[index]; - if (min1 == (double)CUDD_OUT_OF_MEM) { - FREE(entry); - return((double)CUDD_OUT_OF_MEM); - } - min2 = bddCorrelationWeightsAux(dd, Fnv, Gnv, prob, table) * (1.0 - prob[index]); - if (min2 == (double)CUDD_OUT_OF_MEM) { - FREE(entry); - return((double)CUDD_OUT_OF_MEM); - } - min = (min1+min2); - - pmin = ALLOC(double,1); - if (pmin == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return((double)CUDD_OUT_OF_MEM); - } - *pmin = min; - - if (st_insert(table,(char *)entry, (char *)pmin) == ST_OUT_OF_MEM) { - FREE(entry); - FREE(pmin); - return((double)CUDD_OUT_OF_MEM); - } - return(min); - -} /* end of bddCorrelationWeightsAux */ - - -/**Function******************************************************************** - - Synopsis [Compares two hash table entries.] - - Description [Compares two hash table entries. Returns 0 if they are - identical; 1 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -CorrelCompare( - const char * key1, - const char * key2) -{ - HashEntry *entry1; - HashEntry *entry2; - - entry1 = (HashEntry *) key1; - entry2 = (HashEntry *) key2; - if (entry1->f != entry2->f || entry1->g != entry2->g) return(1); - - return(0); - -} /* end of CorrelCompare */ - - -/**Function******************************************************************** - - Synopsis [Hashes a hash table entry.] - - Description [Hashes a hash table entry. It is patterned after - st_strhash. Returns a value between 0 and modulus.] - - SideEffects [None] - -******************************************************************************/ -static int -CorrelHash( - char * key, - int modulus) -{ - HashEntry *entry; - int val = 0; - - entry = (HashEntry *) key; -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 - val = ((int) ((long)entry->f))*997 + ((int) ((long)entry->g)); -#else - val = ((int) entry->f)*997 + ((int) entry->g); -#endif - - return ((val < 0) ? -val : val) % modulus; - -} /* end of CorrelHash */ - - -/**Function******************************************************************** - - Synopsis [Frees memory associated with hash table.] - - Description [Frees memory associated with hash table. Returns - ST_CONTINUE.] - - SideEffects [None] - -******************************************************************************/ -static enum st_retval -CorrelCleanUp( - char * key, - char * value, - char * arg) -{ - double *d; - HashEntry *entry; - - entry = (HashEntry *) key; - FREE(entry); - d = (double *)value; - FREE(d); - return ST_CONTINUE; - -} /* end of CorrelCleanUp */ - diff --git a/src/bdd/cudd/cuddBddIte.c b/src/bdd/cudd/cuddBddIte.c deleted file mode 100644 index b44e40de..00000000 --- a/src/bdd/cudd/cuddBddIte.c +++ /dev/null @@ -1,1254 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddBddIte.c] - - PackageName [cudd] - - Synopsis [BDD ITE function and satellites.] - - Description [External procedures included in this module: -
          -
        • Cudd_bddIte() -
        • Cudd_bddIteConstant() -
        • Cudd_bddIntersect() -
        • Cudd_bddAnd() -
        • Cudd_bddOr() -
        • Cudd_bddNand() -
        • Cudd_bddNor() -
        • Cudd_bddXor() -
        • Cudd_bddXnor() -
        • Cudd_bddLeq() -
        - Internal procedures included in this module: -
          -
        • cuddBddIteRecur() -
        • cuddBddIntersectRecur() -
        • cuddBddAndRecur() -
        • cuddBddXorRecur() -
        - Static procedures included in this module: -
          -
        • bddVarToConst() -
        • bddVarToCanonical() -
        • bddVarToCanonicalSimple() -
        ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddBddIte.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void bddVarToConst ARGS((DdNode *f, DdNode **gp, DdNode **hp, DdNode *one)); -static int bddVarToCanonical ARGS((DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp)); -static int bddVarToCanonicalSimple ARGS((DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements ITE(f,g,h).] - - Description [Implements ITE(f,g,h). Returns a pointer to the - resulting BDD if successful; NULL if the intermediate result blows - up.] - - SideEffects [None] - - SeeAlso [Cudd_addIte Cudd_bddIteConstant Cudd_bddIntersect] - -******************************************************************************/ -DdNode * -Cudd_bddIte( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddIteRecur(dd,f,g,h); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddIte */ - - -/**Function******************************************************************** - - Synopsis [Implements ITEconstant(f,g,h).] - - Description [Implements ITEconstant(f,g,h). Returns a pointer to the - resulting BDD (which may or may not be constant) or DD_NON_CONSTANT. - No new nodes are created.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_bddIntersect Cudd_bddLeq Cudd_addIteConstant] - -******************************************************************************/ -DdNode * -Cudd_bddIteConstant( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e; - DdNode *one = DD_ONE(dd); - DdNode *zero = Cudd_Not(one); - int comple; - unsigned int topf, topg, toph, v; - - statLine(dd); - /* Trivial cases. */ - if (f == one) /* ITE(1,G,H) => G */ - return(g); - - if (f == zero) /* ITE(0,G,H) => H */ - return(h); - - /* f now not a constant. */ - bddVarToConst(f, &g, &h, one); /* possibly convert g or h */ - /* to constants */ - - if (g == h) /* ITE(F,G,G) => G */ - return(g); - - if (Cudd_IsConstant(g) && Cudd_IsConstant(h)) - return(DD_NON_CONSTANT); /* ITE(F,1,0) or ITE(F,0,1) */ - /* => DD_NON_CONSTANT */ - - if (g == Cudd_Not(h)) - return(DD_NON_CONSTANT); /* ITE(F,G,G') => DD_NON_CONSTANT */ - /* if F != G and F != G' */ - - comple = bddVarToCanonical(dd, &f, &g, &h, &topf, &topg, &toph); - - /* Cache lookup. */ - r = cuddConstantLookup(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h); - if (r != NULL) { - return(Cudd_NotCond(r,comple && r != DD_NON_CONSTANT)); - } - - v = ddMin(topg, toph); - - /* ITE(F,G,H) = (v,G,H) (non constant) if F = (v,1,0), v < top(G,H). */ - if (topf < v && cuddT(f) == one && cuddE(f) == zero) { - return(DD_NON_CONSTANT); - } - - /* Compute cofactors. */ - if (topf <= v) { - v = ddMin(topf, v); /* v = top_var(F,G,H) */ - Fv = cuddT(f); Fnv = cuddE(f); - } else { - Fv = Fnv = f; - } - - if (topg == v) { - Gv = cuddT(g); Gnv = cuddE(g); - } else { - Gv = Gnv = g; - } - - if (toph == v) { - H = Cudd_Regular(h); - Hv = cuddT(H); Hnv = cuddE(H); - if (Cudd_IsComplement(h)) { - Hv = Cudd_Not(Hv); - Hnv = Cudd_Not(Hnv); - } - } else { - Hv = Hnv = h; - } - - /* Recursion. */ - t = Cudd_bddIteConstant(dd, Fv, Gv, Hv); - if (t == DD_NON_CONSTANT || !Cudd_IsConstant(t)) { - cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - e = Cudd_bddIteConstant(dd, Fnv, Gnv, Hnv); - if (e == DD_NON_CONSTANT || !Cudd_IsConstant(e) || t != e) { - cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT); - return(DD_NON_CONSTANT); - } - cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, t); - return(Cudd_NotCond(t,comple)); - -} /* end of Cudd_bddIteConstant */ - - -/**Function******************************************************************** - - Synopsis [Returns a function included in the intersection of f and g.] - - Description [Computes a function included in the intersection of f and - g. (That is, a witness that the intersection is not empty.) - Cudd_bddIntersect tries to build as few new nodes as possible. If the - only result of interest is whether f and g intersect, - Cudd_bddLeq should be used instead.] - - SideEffects [None] - - SeeAlso [Cudd_bddLeq Cudd_bddIteConstant] - -******************************************************************************/ -DdNode * -Cudd_bddIntersect( - DdManager * dd /* manager */, - DdNode * f /* first operand */, - DdNode * g /* second operand */) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddIntersectRecur(dd,f,g); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_bddIntersect */ - - -/**Function******************************************************************** - - Synopsis [Computes the conjunction of two BDDs f and g.] - - Description [Computes the conjunction of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect - Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor] - -******************************************************************************/ -DdNode * -Cudd_bddAnd( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddAndRecur(dd,f,g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddAnd */ - - -/**Function******************************************************************** - - Synopsis [Computes the disjunction of two BDDs f and g.] - - Description [Computes the disjunction of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddNand Cudd_bddNor - Cudd_bddXor Cudd_bddXnor] - -******************************************************************************/ -DdNode * -Cudd_bddOr( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g)); - } while (dd->reordered == 1); - res = Cudd_NotCond(res,res != NULL); - return(res); - -} /* end of Cudd_bddOr */ - - -/**Function******************************************************************** - - Synopsis [Computes the NAND of two BDDs f and g.] - - Description [Computes the NAND of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNor - Cudd_bddXor Cudd_bddXnor] - -******************************************************************************/ -DdNode * -Cudd_bddNand( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddAndRecur(dd,f,g); - } while (dd->reordered == 1); - res = Cudd_NotCond(res,res != NULL); - return(res); - -} /* end of Cudd_bddNand */ - - -/**Function******************************************************************** - - Synopsis [Computes the NOR of two BDDs f and g.] - - Description [Computes the NOR of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNand - Cudd_bddXor Cudd_bddXnor] - -******************************************************************************/ -DdNode * -Cudd_bddNor( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g)); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddNor */ - - -/**Function******************************************************************** - - Synopsis [Computes the exclusive OR of two BDDs f and g.] - - Description [Computes the exclusive OR of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr - Cudd_bddNand Cudd_bddNor Cudd_bddXnor] - -******************************************************************************/ -DdNode * -Cudd_bddXor( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddXorRecur(dd,f,g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddXor */ - - -/**Function******************************************************************** - - Synopsis [Computes the exclusive NOR of two BDDs f and g.] - - Description [Computes the exclusive NOR of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr - Cudd_bddNand Cudd_bddNor Cudd_bddXor] - -******************************************************************************/ -DdNode * -Cudd_bddXnor( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddXorRecur(dd,f,Cudd_Not(g)); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddXnor */ - - -/**Function******************************************************************** - - Synopsis [Determines whether f is less than or equal to g.] - - Description [Returns 1 if f is less than or equal to g; 0 otherwise. - No new nodes are created.] - - SideEffects [None] - - SeeAlso [Cudd_bddIteConstant Cudd_addEvalConst] - -******************************************************************************/ -int -Cudd_bddLeq( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *one, *zero, *tmp, *F, *fv, *fvn, *gv, *gvn; - unsigned int topf, topg, res; - - statLine(dd); - /* Terminal cases and normalization. */ - if (f == g) return(1); - - if (Cudd_IsComplement(g)) { - /* Special case: if f is regular and g is complemented, - ** f(1,...,1) = 1 > 0 = g(1,...,1). - */ - if (!Cudd_IsComplement(f)) return(0); - /* Both are complemented: Swap and complement because - ** f <= g <=> g' <= f' and we want the second argument to be regular. - */ - tmp = g; - g = Cudd_Not(f); - f = Cudd_Not(tmp); - } else if (Cudd_IsComplement(f) && g < f) { - tmp = g; - g = Cudd_Not(f); - f = Cudd_Not(tmp); - } - - /* Now g is regular and, if f is not regular, f < g. */ - one = DD_ONE(dd); - if (g == one) return(1); /* no need to test against zero */ - if (f == one) return(0); /* since at this point g != one */ - if (Cudd_Not(f) == g) return(0); /* because neither is constant */ - zero = Cudd_Not(one); - if (f == zero) return(1); - - /* Here neither f nor g is constant. */ - - /* Check cache. */ - tmp = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, - DdNode *))Cudd_bddLeq,f,g); - if (tmp != NULL) { - return(tmp == one); - } - - /* Compute cofactors. */ - F = Cudd_Regular(f); - topf = dd->perm[F->index]; - topg = dd->perm[g->index]; - if (topf <= topg) { - fv = cuddT(F); fvn = cuddE(F); - if (f != F) { - fv = Cudd_Not(fv); - fvn = Cudd_Not(fvn); - } - } else { - fv = fvn = f; - } - if (topg <= topf) { - gv = cuddT(g); gvn = cuddE(g); - } else { - gv = gvn = g; - } - - /* Recursive calls. Since we want to maximize the probability of - ** the special case f(1,...,1) > g(1,...,1), we consider the negative - ** cofactors first. Indeed, the complementation parity of the positive - ** cofactors is the same as the one of the parent functions. - */ - res = Cudd_bddLeq(dd,fvn,gvn) && Cudd_bddLeq(dd,fv,gv); - - /* Store result in cache and return. */ - cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_bddLeq,f,g,(res ? one : zero)); - return(res); - -} /* end of Cudd_bddLeq */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddIte.] - - Description [Implements the recursive step of Cudd_bddIte. Returns a - pointer to the resulting BDD. NULL if the intermediate result blows - up or if reordering occurs.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddBddIteRecur( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *one, *zero, *res; - DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e; - unsigned int topf, topg, toph, v; - int index; - int comple; - - statLine(dd); - /* Terminal cases. */ - - /* One variable cases. */ - if (f == (one = DD_ONE(dd))) /* ITE(1,G,H) = G */ - return(g); - - if (f == (zero = Cudd_Not(one))) /* ITE(0,G,H) = H */ - return(h); - - /* From now on, f is known not to be a constant. */ - if (g == one || f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ - if (h == zero) { /* ITE(F,1,0) = F */ - return(f); - } else { - res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h)); - return(Cudd_NotCond(res,res != NULL)); - } - } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */ - if (h == one) { /* ITE(F,0,1) = !F */ - return(Cudd_Not(f)); - } else { - res = cuddBddAndRecur(dd,Cudd_Not(f),h); - return(res); - } - } - if (h == zero || f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ - res = cuddBddAndRecur(dd,f,g); - return(res); - } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */ - res = cuddBddAndRecur(dd,f,Cudd_Not(g)); - return(Cudd_NotCond(res,res != NULL)); - } - - /* Check remaining one variable case. */ - if (g == h) { /* ITE(F,G,G) = G */ - return(g); - } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */ - res = cuddBddXorRecur(dd,f,h); - return(res); - } - - /* From here, there are no constants. */ - comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph); - - /* f & g are now regular pointers */ - - v = ddMin(topg, toph); - - /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */ - if (topf < v && cuddT(f) == one && cuddE(f) == zero) { - r = cuddUniqueInter(dd, (int) f->index, g, h); - return(Cudd_NotCond(r,comple && r != NULL)); - } - - /* Check cache. */ - r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - /* Compute cofactors. */ - if (topf <= v) { - v = ddMin(topf, v); /* v = top_var(F,G,H) */ - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - } else { - Fv = Fnv = f; - } - if (topg == v) { - index = g->index; - Gv = cuddT(g); Gnv = cuddE(g); - } else { - Gv = Gnv = g; - } - if (toph == v) { - H = Cudd_Regular(h); - index = H->index; - Hv = cuddT(H); Hnv = cuddE(H); - if (Cudd_IsComplement(h)) { - Hv = Cudd_Not(Hv); - Hnv = Cudd_Not(Hnv); - } - } else { - Hv = Hnv = h; - } - - /* Recursive step. */ - t = cuddBddIteRecur(dd,Fv,Gv,Hv); - if (t == NULL) return(NULL); - cuddRef(t); - - e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv); - if (e == NULL) { - Cudd_IterDerefBdd(dd,t); - return(NULL); - } - cuddRef(e); - - r = (t == e) ? t : cuddUniqueInter(dd,index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(dd,t); - Cudd_IterDerefBdd(dd,e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r); - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddIteRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddIntersect.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_bddIntersect] - -******************************************************************************/ -DdNode * -cuddBddIntersectRecur( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - DdNode *F, *G, *t, *e; - DdNode *fv, *fnv, *gv, *gnv; - DdNode *one, *zero; - unsigned int index, topf, topg; - - statLine(dd); - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); - if (f == g || g == one) return(f); - if (f == one) return(g); - - /* At this point f and g are not constant. */ - if (f > g) { DdNode *tmp = f; f = g; g = tmp; } - res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g); - if (res != NULL) return(res); - - /* Find splitting variable. Here we can skip the use of cuddI, - ** because the operands are known to be non-constant. - */ - F = Cudd_Regular(f); - topf = dd->perm[F->index]; - G = Cudd_Regular(g); - topg = dd->perm[G->index]; - - /* Compute cofactors. */ - if (topf <= topg) { - index = F->index; - fv = cuddT(F); - fnv = cuddE(F); - if (Cudd_IsComplement(f)) { - fv = Cudd_Not(fv); - fnv = Cudd_Not(fnv); - } - } else { - index = G->index; - fv = fnv = f; - } - - if (topg <= topf) { - gv = cuddT(G); - gnv = cuddE(G); - if (Cudd_IsComplement(g)) { - gv = Cudd_Not(gv); - gnv = Cudd_Not(gnv); - } - } else { - gv = gnv = g; - } - - /* Compute partial results. */ - t = cuddBddIntersectRecur(dd,fv,gv); - if (t == NULL) return(NULL); - cuddRef(t); - if (t != zero) { - e = zero; - } else { - e = cuddBddIntersectRecur(dd,fnv,gnv); - if (e == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - cuddRef(e); - - if (t == e) { /* both equal zero */ - res = t; - } else if (Cudd_IsComplement(t)) { - res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (res == NULL) { - Cudd_IterDerefBdd(dd, t); - Cudd_IterDerefBdd(dd, e); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = cuddUniqueInter(dd,(int)index,t,e); - if (res == NULL) { - Cudd_IterDerefBdd(dd, t); - Cudd_IterDerefBdd(dd, e); - return(NULL); - } - } - cuddDeref(e); - cuddDeref(t); - - cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res); - - return(res); - -} /* end of cuddBddIntersectRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddAnd.] - - Description [Implements the recursive step of Cudd_bddAnd by taking - the conjunction of two BDDs. Returns a pointer to the result is - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddAnd] - -******************************************************************************/ -DdNode * -cuddBddAndRecur( - DdManager * manager, - DdNode * f, - DdNode * g) -{ - DdNode *F, *fv, *fnv, *G, *gv, *gnv; - DdNode *one, *r, *t, *e; - unsigned int topf, topg, index; - - statLine(manager); - one = DD_ONE(manager); - - /* Terminal cases. */ - F = Cudd_Regular(f); - G = Cudd_Regular(g); - if (F == G) { - if (f == g) return(f); - else return(Cudd_Not(one)); - } - if (F == one) { - if (f == one) return(g); - else return(f); - } - if (G == one) { - if (g == one) return(f); - else return(g); - } - - /* At this point f and g are not constant. */ - if (f > g) { /* Try to increase cache efficiency. */ - DdNode *tmp = f; - f = g; - g = tmp; - F = Cudd_Regular(f); - G = Cudd_Regular(g); - } - - /* Check cache. */ - if (F->ref != 1 || G->ref != 1) { - r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g); - if (r != NULL) return(r); - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - topf = manager->perm[F->index]; - topg = manager->perm[G->index]; - - /* Compute cofactors. */ - if (topf <= topg) { - index = F->index; - fv = cuddT(F); - fnv = cuddE(F); - if (Cudd_IsComplement(f)) { - fv = Cudd_Not(fv); - fnv = Cudd_Not(fnv); - } - } else { - index = G->index; - fv = fnv = f; - } - - if (topg <= topf) { - gv = cuddT(G); - gnv = cuddE(G); - if (Cudd_IsComplement(g)) { - gv = Cudd_Not(gv); - gnv = Cudd_Not(gnv); - } - } else { - gv = gnv = g; - } - - t = cuddBddAndRecur(manager, fv, gv); - if (t == NULL) return(NULL); - cuddRef(t); - - e = cuddBddAndRecur(manager, fnv, gnv); - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - cuddRef(e); - - if (t == e) { - r = t; - } else { - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - } - } - cuddDeref(e); - cuddDeref(t); - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r); - return(r); - -} /* end of cuddBddAndRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddXor.] - - Description [Implements the recursive step of Cudd_bddXor by taking - the exclusive OR of two BDDs. Returns a pointer to the result is - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddXor] - -******************************************************************************/ -DdNode * -cuddBddXorRecur( - DdManager * manager, - DdNode * f, - DdNode * g) -{ - DdNode *fv, *fnv, *G, *gv, *gnv; - DdNode *one, *zero, *r, *t, *e; - unsigned int topf, topg, index; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == g) return(zero); - if (f == Cudd_Not(g)) return(one); - if (f > g) { /* Try to increase cache efficiency and simplify tests. */ - DdNode *tmp = f; - f = g; - g = tmp; - } - if (g == zero) return(f); - if (g == one) return(Cudd_Not(f)); - if (Cudd_IsComplement(f)) { - f = Cudd_Not(f); - g = Cudd_Not(g); - } - /* Now the first argument is regular. */ - if (f == one) return(Cudd_Not(g)); - - /* At this point f and g are not constant. */ - - /* Check cache. */ - r = cuddCacheLookup2(manager, Cudd_bddXor, f, g); - if (r != NULL) return(r); - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - topf = manager->perm[f->index]; - G = Cudd_Regular(g); - topg = manager->perm[G->index]; - - /* Compute cofactors. */ - if (topf <= topg) { - index = f->index; - fv = cuddT(f); - fnv = cuddE(f); - } else { - index = G->index; - fv = fnv = f; - } - - if (topg <= topf) { - gv = cuddT(G); - gnv = cuddE(G); - if (Cudd_IsComplement(g)) { - gv = Cudd_Not(gv); - gnv = Cudd_Not(gnv); - } - } else { - gv = gnv = g; - } - - t = cuddBddXorRecur(manager, fv, gv); - if (t == NULL) return(NULL); - cuddRef(t); - - e = cuddBddXorRecur(manager, fnv, gnv); - if (e == NULL) { - Cudd_IterDerefBdd(manager, t); - return(NULL); - } - cuddRef(e); - - if (t == e) { - r = t; - } else { - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_IterDerefBdd(manager, t); - Cudd_IterDerefBdd(manager, e); - return(NULL); - } - } - } - cuddDeref(e); - cuddDeref(t); - cuddCacheInsert2(manager, Cudd_bddXor, f, g, r); - return(r); - -} /* end of cuddBddXorRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Replaces variables with constants if possible.] - - Description [This function performs part of the transformation to - standard form by replacing variables with constants if possible.] - - SideEffects [None] - - SeeAlso [bddVarToCanonical bddVarToCanonicalSimple] - -******************************************************************************/ -static void -bddVarToConst( - DdNode * f, - DdNode ** gp, - DdNode ** hp, - DdNode * one) -{ - DdNode *g = *gp; - DdNode *h = *hp; - - if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ - *gp = one; - } else if (f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */ - *gp = Cudd_Not(one); - } - if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ - *hp = Cudd_Not(one); - } else if (f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */ - *hp = one; - } - -} /* end of bddVarToConst */ - - -/**Function******************************************************************** - - Synopsis [Picks unique member from equiv expressions.] - - Description [Reduces 2 variable expressions to canonical form.] - - SideEffects [None] - - SeeAlso [bddVarToConst bddVarToCanonicalSimple] - -******************************************************************************/ -static int -bddVarToCanonical( - DdManager * dd, - DdNode ** fp, - DdNode ** gp, - DdNode ** hp, - unsigned int * topfp, - unsigned int * topgp, - unsigned int * tophp) -{ - register DdNode *F, *G, *H, *r, *f, *g, *h; - register unsigned int topf, topg, toph; - DdNode *one = dd->one; - int comple, change; - - f = *fp; - g = *gp; - h = *hp; - F = Cudd_Regular(f); - G = Cudd_Regular(g); - H = Cudd_Regular(h); - topf = cuddI(dd,F->index); - topg = cuddI(dd,G->index); - toph = cuddI(dd,H->index); - - change = 0; - - if (G == one) { /* ITE(F,c,H) */ - if ((topf > toph) || (topf == toph && f > h)) { - r = h; - h = f; - f = r; /* ITE(F,1,H) = ITE(H,1,F) */ - if (g != one) { /* g == zero */ - f = Cudd_Not(f); /* ITE(F,0,H) = ITE(!H,0,!F) */ - h = Cudd_Not(h); - } - change = 1; - } - } else if (H == one) { /* ITE(F,G,c) */ - if ((topf > topg) || (topf == topg && f > g)) { - r = g; - g = f; - f = r; /* ITE(F,G,0) = ITE(G,F,0) */ - if (h == one) { - f = Cudd_Not(f); /* ITE(F,G,1) = ITE(!G,!F,1) */ - g = Cudd_Not(g); - } - change = 1; - } - } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = ITE(G,F,!F) */ - if ((topf > topg) || (topf == topg && f > g)) { - r = f; - f = g; - g = r; - h = Cudd_Not(r); - change = 1; - } - } - /* adjust pointers so that the first 2 arguments to ITE are regular */ - if (Cudd_IsComplement(f) != 0) { /* ITE(!F,G,H) = ITE(F,H,G) */ - f = Cudd_Not(f); - r = g; - g = h; - h = r; - change = 1; - } - comple = 0; - if (Cudd_IsComplement(g) != 0) { /* ITE(F,!G,H) = !ITE(F,G,!H) */ - g = Cudd_Not(g); - h = Cudd_Not(h); - change = 1; - comple = 1; - } - if (change != 0) { - *fp = f; - *gp = g; - *hp = h; - } - *topfp = cuddI(dd,f->index); - *topgp = cuddI(dd,g->index); - *tophp = cuddI(dd,Cudd_Regular(h)->index); - - return(comple); - -} /* end of bddVarToCanonical */ - - -/**Function******************************************************************** - - Synopsis [Picks unique member from equiv expressions.] - - Description [Makes sure the first two pointers are regular. This - mat require the complementation of the result, which is signaled by - returning 1 instead of 0. This function is simpler than the general - case because it assumes that no two arguments are the same or - complementary, and no argument is constant.] - - SideEffects [None] - - SeeAlso [bddVarToConst bddVarToCanonical] - -******************************************************************************/ -static int -bddVarToCanonicalSimple( - DdManager * dd, - DdNode ** fp, - DdNode ** gp, - DdNode ** hp, - unsigned int * topfp, - unsigned int * topgp, - unsigned int * tophp) -{ - register DdNode *r, *f, *g, *h; - int comple, change; - - f = *fp; - g = *gp; - h = *hp; - - change = 0; - - /* adjust pointers so that the first 2 arguments to ITE are regular */ - if (Cudd_IsComplement(f)) { /* ITE(!F,G,H) = ITE(F,H,G) */ - f = Cudd_Not(f); - r = g; - g = h; - h = r; - change = 1; - } - comple = 0; - if (Cudd_IsComplement(g)) { /* ITE(F,!G,H) = !ITE(F,G,!H) */ - g = Cudd_Not(g); - h = Cudd_Not(h); - change = 1; - comple = 1; - } - if (change) { - *fp = f; - *gp = g; - *hp = h; - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - *topfp = dd->perm[f->index]; - *topgp = dd->perm[g->index]; - *tophp = dd->perm[Cudd_Regular(h)->index]; - - return(comple); - -} /* end of bddVarToCanonicalSimple */ - diff --git a/src/bdd/cudd/cuddBridge.c b/src/bdd/cudd/cuddBridge.c deleted file mode 100644 index ccc0893f..00000000 --- a/src/bdd/cudd/cuddBridge.c +++ /dev/null @@ -1,981 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddBridge.c] - - PackageName [cudd] - - Synopsis [Translation from BDD to ADD and vice versa and transfer between - different managers.] - - Description [External procedures included in this file: -
          -
        • Cudd_addBddThreshold() -
        • Cudd_addBddStrictThreshold() -
        • Cudd_addBddInterval() -
        • Cudd_addBddIthBit() -
        • Cudd_BddToAdd() -
        • Cudd_addBddPattern() -
        • Cudd_bddTransfer() -
        - Internal procedures included in this file: -
          -
        • cuddBddTransfer() -
        • cuddAddBddDoPattern() -
        - Static procedures included in this file: -
          -
        • addBddDoThreshold() -
        • addBddDoStrictThreshold() -
        • addBddDoInterval() -
        • addBddDoIthBit() -
        • ddBddToAddRecur() -
        • cuddBddTransferRecur() -
        - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddBridge.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * addBddDoThreshold ARGS((DdManager *dd, DdNode *f, DdNode *val)); -static DdNode * addBddDoStrictThreshold ARGS((DdManager *dd, DdNode *f, DdNode *val)); -static DdNode * addBddDoInterval ARGS((DdManager *dd, DdNode *f, DdNode *l, DdNode *u)); -static DdNode * addBddDoIthBit ARGS((DdManager *dd, DdNode *f, DdNode *index)); -static DdNode * ddBddToAddRecur ARGS((DdManager *dd, DdNode *B)); -static DdNode * cuddBddTransferRecur ARGS((DdManager *ddS, DdManager *ddD, DdNode *f, st_table *table)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Converts an ADD to a BDD.] - - Description [Converts an ADD to a BDD by replacing all - discriminants greater than or equal to value with 1, and all other - discriminants with 0. Returns a pointer to the resulting BDD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd - Cudd_addBddStrictThreshold] - -******************************************************************************/ -DdNode * -Cudd_addBddThreshold( - DdManager * dd, - DdNode * f, - CUDD_VALUE_TYPE value) -{ - DdNode *res; - DdNode *val; - - val = cuddUniqueConst(dd,value); - if (val == NULL) return(NULL); - cuddRef(val); - - do { - dd->reordered = 0; - res = addBddDoThreshold(dd, f, val); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd, val); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, val); - cuddDeref(res); - return(res); - -} /* end of Cudd_addBddThreshold */ - - -/**Function******************************************************************** - - Synopsis [Converts an ADD to a BDD.] - - Description [Converts an ADD to a BDD by replacing all - discriminants STRICTLY greater than value with 1, and all other - discriminants with 0. Returns a pointer to the resulting BDD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd - Cudd_addBddThreshold] - -******************************************************************************/ -DdNode * -Cudd_addBddStrictThreshold( - DdManager * dd, - DdNode * f, - CUDD_VALUE_TYPE value) -{ - DdNode *res; - DdNode *val; - - val = cuddUniqueConst(dd,value); - if (val == NULL) return(NULL); - cuddRef(val); - - do { - dd->reordered = 0; - res = addBddDoStrictThreshold(dd, f, val); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd, val); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, val); - cuddDeref(res); - return(res); - -} /* end of Cudd_addBddStrictThreshold */ - - -/**Function******************************************************************** - - Synopsis [Converts an ADD to a BDD.] - - Description [Converts an ADD to a BDD by replacing all - discriminants greater than or equal to lower and less than or equal to - upper with 1, and all other discriminants with 0. Returns a pointer to - the resulting BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddThreshold Cudd_addBddStrictThreshold - Cudd_addBddPattern Cudd_BddToAdd] - -******************************************************************************/ -DdNode * -Cudd_addBddInterval( - DdManager * dd, - DdNode * f, - CUDD_VALUE_TYPE lower, - CUDD_VALUE_TYPE upper) -{ - DdNode *res; - DdNode *l; - DdNode *u; - - /* Create constant nodes for the interval bounds, so that we can use - ** the global cache. - */ - l = cuddUniqueConst(dd,lower); - if (l == NULL) return(NULL); - cuddRef(l); - u = cuddUniqueConst(dd,upper); - if (u == NULL) { - Cudd_RecursiveDeref(dd,l); - return(NULL); - } - cuddRef(u); - - do { - dd->reordered = 0; - res = addBddDoInterval(dd, f, l, u); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd, l); - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, l); - Cudd_RecursiveDeref(dd, u); - cuddDeref(res); - return(res); - -} /* end of Cudd_addBddInterval */ - - -/**Function******************************************************************** - - Synopsis [Converts an ADD to a BDD by extracting the i-th bit from - the leaves.] - - Description [Converts an ADD to a BDD by replacing all - discriminants whose i-th bit is equal to 1 with 1, and all other - discriminants with 0. The i-th bit refers to the integer - representation of the leaf value. If the value is has a fractional - part, it is ignored. Repeated calls to this procedure allow one to - transform an integer-valued ADD into an array of BDDs, one for each - bit of the leaf values. Returns a pointer to the resulting BDD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd] - -******************************************************************************/ -DdNode * -Cudd_addBddIthBit( - DdManager * dd, - DdNode * f, - int bit) -{ - DdNode *res; - DdNode *index; - - index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit); - if (index == NULL) return(NULL); - cuddRef(index); - - do { - dd->reordered = 0; - res = addBddDoIthBit(dd, f, index); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd, index); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, index); - cuddDeref(res); - return(res); - -} /* end of Cudd_addBddIthBit */ - - -/**Function******************************************************************** - - Synopsis [Converts a BDD to a 0-1 ADD.] - - Description [Converts a BDD to a 0-1 ADD. Returns a pointer to the - resulting ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addBddPattern Cudd_addBddThreshold Cudd_addBddInterval - Cudd_addBddStrictThreshold] - -******************************************************************************/ -DdNode * -Cudd_BddToAdd( - DdManager * dd, - DdNode * B) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = ddBddToAddRecur(dd, B); - } while (dd->reordered ==1); - return(res); - -} /* end of Cudd_BddToAdd */ - - -/**Function******************************************************************** - - Synopsis [Converts an ADD to a BDD.] - - Description [Converts an ADD to a BDD by replacing all - discriminants different from 0 with 1. Returns a pointer to the - resulting BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_BddToAdd Cudd_addBddThreshold Cudd_addBddInterval - Cudd_addBddStrictThreshold] - -******************************************************************************/ -DdNode * -Cudd_addBddPattern( - DdManager * dd, - DdNode * f) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddBddDoPattern(dd, f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addBddPattern */ - - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. The orders of the - variables in the two managers may be different. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_bddTransfer( - DdManager * ddSource, - DdManager * ddDestination, - DdNode * f) -{ - DdNode *res; - do { - ddDestination->reordered = 0; - res = cuddBddTransfer(ddSource, ddDestination, f); - } while (ddDestination->reordered == 1); - return(res); - -} /* end of Cudd_bddTransfer */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddTransfer] - -******************************************************************************/ -DdNode * -cuddBddTransfer( - DdManager * ddS, - DdManager * ddD, - DdNode * f) -{ - DdNode *res; - st_table *table = NULL; - st_generator *gen = NULL; - DdNode *key, *value; - - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) goto failure; - res = cuddBddTransferRecur(ddS, ddD, f, table); - if (res != NULL) cuddRef(res); - - /* Dereference all elements in the table and dispose of the table. - ** This must be done also if res is NULL to avoid leaks in case of - ** reordering. */ - gen = st_init_gen(table); - if (gen == NULL) goto failure; - while (st_gen(gen, (char **) &key, (char **) &value)) { - Cudd_RecursiveDeref(ddD, value); - } - st_free_gen(gen); gen = NULL; - st_free_table(table); table = NULL; - - if (res != NULL) cuddDeref(res); - return(res); - -failure: - if (table != NULL) st_free_table(table); - if (gen != NULL) st_free_gen(gen); - return(NULL); - -} /* end of cuddBddTransfer */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addBddPattern.] - - Description [Performs the recursive step for Cudd_addBddPattern. Returns a - pointer to the resulting BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddAddBddDoPattern( - DdManager * dd, - DdNode * f) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - return(Cudd_NotCond(DD_ONE(dd),f == DD_ZERO(dd))); - } - - /* Check cache. */ - res = cuddCacheLookup1(dd,Cudd_addBddPattern,f); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = cuddAddBddDoPattern(dd,fv); - if (T == NULL) return(NULL); - cuddRef(T); - - E = cuddAddBddDoPattern(dd,fvn); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - if (Cudd_IsComplement(T)) { - res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert1(dd,Cudd_addBddPattern,f,res); - - return(res); - -} /* end of cuddAddBddDoPattern */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addBddThreshold.] - - Description [Performs the recursive step for Cudd_addBddThreshold. - Returns a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [addBddDoStrictThreshold] - -******************************************************************************/ -static DdNode * -addBddDoThreshold( - DdManager * dd, - DdNode * f, - DdNode * val) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(val))); - } - - /* Check cache. */ - res = cuddCacheLookup2(dd,addBddDoThreshold,f,val); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = addBddDoThreshold(dd,fv,val); - if (T == NULL) return(NULL); - cuddRef(T); - - E = addBddDoThreshold(dd,fvn,val); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - if (Cudd_IsComplement(T)) { - res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert2(dd,addBddDoThreshold,f,val,res); - - return(res); - -} /* end of addBddDoThreshold */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addBddStrictThreshold.] - - Description [Performs the recursive step for Cudd_addBddStrictThreshold. - Returns a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [addBddDoThreshold] - -******************************************************************************/ -static DdNode * -addBddDoStrictThreshold( - DdManager * dd, - DdNode * f, - DdNode * val) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - return(Cudd_NotCond(DD_ONE(dd),cuddV(f) <= cuddV(val))); - } - - /* Check cache. */ - res = cuddCacheLookup2(dd,addBddDoStrictThreshold,f,val); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = addBddDoStrictThreshold(dd,fv,val); - if (T == NULL) return(NULL); - cuddRef(T); - - E = addBddDoStrictThreshold(dd,fvn,val); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - if (Cudd_IsComplement(T)) { - res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert2(dd,addBddDoStrictThreshold,f,val,res); - - return(res); - -} /* end of addBddDoStrictThreshold */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addBddInterval.] - - Description [Performs the recursive step for Cudd_addBddInterval. - Returns a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [addBddDoThreshold addBddDoStrictThreshold] - -******************************************************************************/ -static DdNode * -addBddDoInterval( - DdManager * dd, - DdNode * f, - DdNode * l, - DdNode * u) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - return(Cudd_NotCond(DD_ONE(dd),cuddV(f) < cuddV(l) || cuddV(f) > cuddV(u))); - } - - /* Check cache. */ - res = cuddCacheLookup(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = addBddDoInterval(dd,fv,l,u); - if (T == NULL) return(NULL); - cuddRef(T); - - E = addBddDoInterval(dd,fvn,l,u); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - if (Cudd_IsComplement(T)) { - res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert(dd,DD_ADD_BDD_DO_INTERVAL_TAG,f,l,u,res); - - return(res); - -} /* end of addBddDoInterval */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_addBddIthBit.] - - Description [Performs the recursive step for Cudd_addBddIthBit. - Returns a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -addBddDoIthBit( - DdManager * dd, - DdNode * f, - DdNode * index) -{ - DdNode *res, *T, *E; - DdNode *fv, *fvn; - int mask, value; - int v; - - statLine(dd); - /* Check terminal case. */ - if (cuddIsConstant(f)) { - mask = 1 << ((int) cuddV(index)); - value = (int) cuddV(f); - return(Cudd_NotCond(DD_ONE(dd),(value & mask) == 0)); - } - - /* Check cache. */ - res = cuddCacheLookup2(dd,addBddDoIthBit,f,index); - if (res != NULL) return(res); - - /* Recursive step. */ - v = f->index; - fv = cuddT(f); fvn = cuddE(f); - - T = addBddDoIthBit(dd,fv,index); - if (T == NULL) return(NULL); - cuddRef(T); - - E = addBddDoIthBit(dd,fvn,index); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - if (Cudd_IsComplement(T)) { - res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - res = Cudd_Not(res); - } else { - res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - cuddDeref(T); - cuddDeref(E); - - /* Store result. */ - cuddCacheInsert2(dd,addBddDoIthBit,f,index,res); - - return(res); - -} /* end of addBddDoIthBit */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step for Cudd_BddToAdd.] - - Description [Performs the recursive step for Cudd_BddToAdd. Returns a - pointer to the resulting ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -ddBddToAddRecur( - DdManager * dd, - DdNode * B) -{ - DdNode *one; - DdNode *res, *res1, *T, *E, *Bt, *Be; - int complement = 0; - - statLine(dd); - one = DD_ONE(dd); - - if (Cudd_IsConstant(B)) { - if (B == one) { - res = one; - } else { - res = DD_ZERO(dd); - } - return(res); - } - /* Check visited table */ - res = cuddCacheLookup1(dd,ddBddToAddRecur,B); - if (res != NULL) return(res); - - if (Cudd_IsComplement(B)) { - complement = 1; - Bt = cuddT(Cudd_Regular(B)); - Be = cuddE(Cudd_Regular(B)); - } else { - Bt = cuddT(B); - Be = cuddE(B); - } - - T = ddBddToAddRecur(dd, Bt); - if (T == NULL) return(NULL); - cuddRef(T); - - E = ddBddToAddRecur(dd, Be); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - - /* No need to check for T == E, because it is guaranteed not to happen. */ - res = cuddUniqueInter(dd, (int) Cudd_Regular(B)->index, T, E); - if (res == NULL) { - Cudd_RecursiveDeref(dd ,T); - Cudd_RecursiveDeref(dd ,E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - - if (complement) { - cuddRef(res); - res1 = cuddAddCmplRecur(dd, res); - if (res1 == NULL) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - cuddRef(res1); - Cudd_RecursiveDeref(dd, res); - res = res1; - cuddDeref(res); - } - - /* Store result. */ - cuddCacheInsert1(dd,ddBddToAddRecur,B,res); - - return(res); - -} /* end of ddBddToAddRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddTransfer.] - - Description [Performs the recursive step of Cudd_bddTransfer. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddBddTransfer] - -******************************************************************************/ -static DdNode * -cuddBddTransferRecur( - DdManager * ddS, - DdManager * ddD, - DdNode * f, - st_table * table) -{ - DdNode *ft, *fe, *t, *e, *var, *res; - DdNode *one, *zero; - int index; - int comple = 0; - - statLine(ddD); - one = DD_ONE(ddD); - comple = Cudd_IsComplement(f); - - /* Trivial cases. */ - if (Cudd_IsConstant(f)) return(Cudd_NotCond(one, comple)); - - /* Make canonical to increase the utilization of the cache. */ - f = Cudd_NotCond(f,comple); - /* Now f is a regular pointer to a non-constant node. */ - - /* Check the cache. */ - if(st_lookup(table, (char *)f, (char **) &res)) - return(Cudd_NotCond(res,comple)); - - /* Recursive step. */ - index = f->index; - ft = cuddT(f); fe = cuddE(f); - - t = cuddBddTransferRecur(ddS, ddD, ft, table); - if (t == NULL) { - return(NULL); - } - cuddRef(t); - - e = cuddBddTransferRecur(ddS, ddD, fe, table); - if (e == NULL) { - Cudd_RecursiveDeref(ddD, t); - return(NULL); - } - cuddRef(e); - - zero = Cudd_Not(one); - var = cuddUniqueInter(ddD,index,one,zero); - if (var == NULL) { - Cudd_RecursiveDeref(ddD, t); - Cudd_RecursiveDeref(ddD, e); - return(NULL); - } - res = cuddBddIteRecur(ddD,var,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(ddD, t); - Cudd_RecursiveDeref(ddD, e); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(ddD, t); - Cudd_RecursiveDeref(ddD, e); - - if (st_add_direct(table, (char *) f, (char *) res) == ST_OUT_OF_MEM) { - Cudd_RecursiveDeref(ddD, res); - return(NULL); - } - return(Cudd_NotCond(res,comple)); - -} /* end of cuddBddTransferRecur */ - diff --git a/src/bdd/cudd/cuddCache.c b/src/bdd/cudd/cuddCache.c deleted file mode 100644 index d9e40921..00000000 --- a/src/bdd/cudd/cuddCache.c +++ /dev/null @@ -1,1023 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddCache.c] - - PackageName [cudd] - - Synopsis [Functions for cache insertion and lookup.] - - Description [Internal procedures included in this module: -
          -
        • cuddInitCache() -
        • cuddCacheInsert() -
        • cuddCacheInsert2() -
        • cuddCacheLookup() -
        • cuddCacheLookupZdd() -
        • cuddCacheLookup2() -
        • cuddCacheLookup2Zdd() -
        • cuddConstantLookup() -
        • cuddCacheProfile() -
        • cuddCacheResize() -
        • cuddCacheFlush() -
        • cuddComputeFloorLog2() -
        - Static procedures included in this module: -
          -
        ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#ifdef DD_CACHE_PROFILE -#define DD_HYSTO_BINS 8 -#endif - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddCache.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Initializes the computed table.] - - Description [Initializes the computed table. It is called by - Cudd_Init. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Init] - -******************************************************************************/ -int -cuddInitCache( - DdManager * unique /* unique table */, - unsigned int cacheSize /* initial size of the cache */, - unsigned int maxCacheSize /* cache size beyond which no resizing occurs */) -{ - int i; - unsigned int logSize; -#ifndef DD_CACHE_PROFILE - DdNodePtr *mem; - ptruint offset; -#endif - - /* Round cacheSize to largest power of 2 not greater than the requested - ** initial cache size. */ - logSize = cuddComputeFloorLog2(ddMax(cacheSize,unique->slots/2)); - cacheSize = 1 << logSize; - unique->acache = ALLOC(DdCache,cacheSize+1); - if (unique->acache == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - /* If the size of the cache entry is a power of 2, we want to - ** enforce alignment to that power of two. This happens when - ** DD_CACHE_PROFILE is not defined. */ -#ifdef DD_CACHE_PROFILE - unique->cache = unique->acache; - unique->memused += (cacheSize) * sizeof(DdCache); -#else - mem = (DdNodePtr *) unique->acache; - offset = (ptruint) mem & (sizeof(DdCache) - 1); - mem += (sizeof(DdCache) - offset) / sizeof(DdNodePtr); - unique->cache = (DdCache *) mem; - assert(((ptruint) unique->cache & (sizeof(DdCache) - 1)) == 0); - unique->memused += (cacheSize+1) * sizeof(DdCache); -#endif - unique->cacheSlots = cacheSize; - unique->cacheShift = sizeof(int) * 8 - logSize; - unique->maxCacheHard = maxCacheSize; - /* If cacheSlack is non-negative, we can resize. */ - unique->cacheSlack = (int) ddMin(maxCacheSize, - DD_MAX_CACHE_TO_SLOTS_RATIO*unique->slots) - - 2 * (int) cacheSize; - Cudd_SetMinHit(unique,DD_MIN_HIT); - /* Initialize to avoid division by 0 and immediate resizing. */ - unique->cacheMisses = (double) (int) (cacheSize * unique->minHit + 1); - unique->cacheHits = 0; - unique->totCachehits = 0; - /* The sum of cacheMisses and totCacheMisses is always correct, - ** even though cacheMisses is larger than it should for the reasons - ** explained above. */ - unique->totCacheMisses = -unique->cacheMisses; - unique->cachecollisions = 0; - unique->cacheinserts = 0; - unique->cacheLastInserts = 0; - unique->cachedeletions = 0; - - /* Initialize the cache */ - for (i = 0; (unsigned) i < cacheSize; i++) { - unique->cache[i].h = 0; /* unused slots */ - unique->cache[i].data = NULL; /* invalid entry */ -#ifdef DD_CACHE_PROFILE - unique->cache[i].count = 0; -#endif - } - - return(1); - -} /* end of cuddInitCache */ - - -/**Function******************************************************************** - - Synopsis [Inserts a result in the cache.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddCacheInsert2 cuddCacheInsert1] - -******************************************************************************/ -void -cuddCacheInsert( - DdManager * table, - ptruint op, - DdNode * f, - DdNode * g, - DdNode * h, - DdNode * data) -{ - int posn; - register DdCache *entry; - ptruint uf, ug, uh; - - uf = (ptruint) f | (op & 0xe); - ug = (ptruint) g | (op >> 4); - uh = (ptruint) h; - - posn = ddCHash2(uh,uf,ug,table->cacheShift); - entry = &table->cache[posn]; - - table->cachecollisions += entry->data != NULL; - table->cacheinserts++; - - entry->f = (DdNode *) uf; - entry->g = (DdNode *) ug; - entry->h = uh; - entry->data = data; -#ifdef DD_CACHE_PROFILE - entry->count++; -#endif - -} /* end of cuddCacheInsert */ - - -/**Function******************************************************************** - - Synopsis [Inserts a result in the cache for a function with two - operands.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddCacheInsert cuddCacheInsert1] - -******************************************************************************/ -void -cuddCacheInsert2( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *, DdNode *), - DdNode * f, - DdNode * g, - DdNode * data) -{ - int posn; - register DdCache *entry; - - posn = ddCHash2(op,f,g,table->cacheShift); - entry = &table->cache[posn]; - - if (entry->data != NULL) { - table->cachecollisions++; - } - table->cacheinserts++; - - entry->f = f; - entry->g = g; - entry->h = (ptruint) op; - entry->data = data; -#ifdef DD_CACHE_PROFILE - entry->count++; -#endif - -} /* end of cuddCacheInsert2 */ - - -/**Function******************************************************************** - - Synopsis [Inserts a result in the cache for a function with two - operands.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddCacheInsert cuddCacheInsert2] - -******************************************************************************/ -void -cuddCacheInsert1( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *), - DdNode * f, - DdNode * data) -{ - int posn; - register DdCache *entry; - - posn = ddCHash2(op,f,f,table->cacheShift); - entry = &table->cache[posn]; - - if (entry->data != NULL) { - table->cachecollisions++; - } - table->cacheinserts++; - - entry->f = f; - entry->g = f; - entry->h = (ptruint) op; - entry->data = data; -#ifdef DD_CACHE_PROFILE - entry->count++; -#endif - -} /* end of cuddCacheInsert1 */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f, - g, and h.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookup2 cuddCacheLookup1] - -******************************************************************************/ -DdNode * -cuddCacheLookup( - DdManager * table, - ptruint op, - DdNode * f, - DdNode * g, - DdNode * h) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - ptruint uf, ug, uh; - - uf = (ptruint) f | (op & 0xe); - ug = (ptruint) g | (op >> 4); - uh = (ptruint) h; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(uh,uf,ug,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && - en->h==uh) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaim(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookup */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f, - g, and h.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookup2Zdd cuddCacheLookup1Zdd] - -******************************************************************************/ -DdNode * -cuddCacheLookupZdd( - DdManager * table, - ptruint op, - DdNode * f, - DdNode * g, - DdNode * h) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - ptruint uf, ug, uh; - - uf = (ptruint) f | (op & 0xe); - ug = (ptruint) g | (op >> 4); - uh = (ptruint) h; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(uh,uf,ug,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==(DdNodePtr)uf && en->g==(DdNodePtr)ug && - en->h==uh) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaimZdd(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookupZdd */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f - and g.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookup cuddCacheLookup1] - -******************************************************************************/ -DdNode * -cuddCacheLookup2( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *, DdNode *), - DdNode * f, - DdNode * g) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(op,f,g,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaim(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookup2 */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookup cuddCacheLookup2] - -******************************************************************************/ -DdNode * -cuddCacheLookup1( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *), - DdNode * f) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(op,f,f,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==f && en->h==(ptruint)op) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaim(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookup1 */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f - and g.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookupZdd cuddCacheLookup1Zdd] - -******************************************************************************/ -DdNode * -cuddCacheLookup2Zdd( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *, DdNode *), - DdNode * f, - DdNode * g) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(op,f,g,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==f && en->g==g && en->h==(ptruint)op) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaimZdd(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookup2Zdd */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f.] - - Description [Returns the result if found; it returns NULL if no - result is found.] - - SideEffects [None] - - SeeAlso [cuddCacheLookupZdd cuddCacheLookup2Zdd] - -******************************************************************************/ -DdNode * -cuddCacheLookup1Zdd( - DdManager * table, - DdNode * (*op)(DdManager *, DdNode *), - DdNode * f) -{ - int posn; - DdCache *en,*cache; - DdNode *data; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - - posn = ddCHash2(op,f,f,table->cacheShift); - en = &cache[posn]; - if (en->data != NULL && en->f==f && en->h==(ptruint)op) { - data = Cudd_Regular(en->data); - table->cacheHits++; - if (data->ref == 0) { - cuddReclaimZdd(table,data); - } - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddCacheLookup1Zdd */ - - -/**Function******************************************************************** - - Synopsis [Looks up in the cache for the result of op applied to f, - g, and h.] - - Description [Looks up in the cache for the result of op applied to f, - g, and h. Assumes that the calling procedure (e.g., - Cudd_bddIteConstant) is only interested in whether the result is - constant or not. Returns the result if found (possibly - DD_NON_CONSTANT); otherwise it returns NULL.] - - SideEffects [None] - - SeeAlso [cuddCacheLookup] - -******************************************************************************/ -DdNode * -cuddConstantLookup( - DdManager * table, - ptruint op, - DdNode * f, - DdNode * g, - DdNode * h) -{ - int posn; - DdCache *en,*cache; - ptruint uf, ug, uh; - - uf = (ptruint) f | (op & 0xe); - ug = (ptruint) g | (op >> 4); - uh = (ptruint) h; - - cache = table->cache; -#ifdef DD_DEBUG - if (cache == NULL) { - return(NULL); - } -#endif - posn = ddCHash2(uh,uf,ug,table->cacheShift); - en = &cache[posn]; - - /* We do not reclaim here because the result should not be - * referenced, but only tested for being a constant. - */ - if (en->data != NULL && - en->f == (DdNodePtr)uf && en->g == (DdNodePtr)ug && en->h == uh) { - table->cacheHits++; - return(en->data); - } - - /* Cache miss: decide whether to resize. */ - table->cacheMisses++; - - if (table->cacheSlack >= 0 && - table->cacheHits > table->cacheMisses * table->minHit) { - cuddCacheResize(table); - } - - return(NULL); - -} /* end of cuddConstantLookup */ - - -/**Function******************************************************************** - - Synopsis [Computes and prints a profile of the cache usage.] - - Description [Computes and prints a profile of the cache usage. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddCacheProfile( - DdManager * table, - FILE * fp) -{ - DdCache *cache = table->cache; - int slots = table->cacheSlots; - int nzeroes = 0; - int i, retval; - double exUsed; - -#ifdef DD_CACHE_PROFILE - double count, mean, meansq, stddev, expected; - long max, min; - int imax, imin; - double *hystogramQ, *hystogramR; /* histograms by quotient and remainder */ - int nbins = DD_HYSTO_BINS; - int bin; - long thiscount; - double totalcount, exStddev; - - meansq = mean = expected = 0.0; - max = min = (long) cache[0].count; - imax = imin = 0; - totalcount = 0.0; - - hystogramQ = ALLOC(double, nbins); - if (hystogramQ == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - hystogramR = ALLOC(double, nbins); - if (hystogramR == NULL) { - FREE(hystogramQ); - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < nbins; i++) { - hystogramQ[i] = 0; - hystogramR[i] = 0; - } - - for (i = 0; i < slots; i++) { - thiscount = (long) cache[i].count; - if (thiscount > max) { - max = thiscount; - imax = i; - } - if (thiscount < min) { - min = thiscount; - imin = i; - } - if (thiscount == 0) { - nzeroes++; - } - count = (double) thiscount; - mean += count; - meansq += count * count; - totalcount += count; - expected += count * (double) i; - bin = (i * nbins) / slots; - hystogramQ[bin] += (double) thiscount; - bin = i % nbins; - hystogramR[bin] += (double) thiscount; - } - mean /= (double) slots; - meansq /= (double) slots; - - /* Compute the standard deviation from both the data and the - ** theoretical model for a random distribution. */ - stddev = sqrt(meansq - mean*mean); - exStddev = sqrt((1 - 1/(double) slots) * totalcount / (double) slots); - - retval = fprintf(fp,"Cache average accesses = %g\n", mean); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache access standard deviation = %g ", stddev); - if (retval == EOF) return(0); - retval = fprintf(fp,"(expected = %g)\n", exStddev); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin); - if (retval == EOF) return(0); - exUsed = 100.0 * (1.0 - exp(-totalcount / (double) slots)); - retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n", - 100.0 - (double) nzeroes * 100.0 / (double) slots, - exUsed); - if (retval == EOF) return(0); - - if (totalcount > 0) { - expected /= totalcount; - retval = fprintf(fp,"Cache access hystogram for %d bins", nbins); - if (retval == EOF) return(0); - retval = fprintf(fp," (expected bin value = %g)\nBy quotient:", - expected); - if (retval == EOF) return(0); - for (i = nbins - 1; i>=0; i--) { - retval = fprintf(fp," %.0f", hystogramQ[i]); - if (retval == EOF) return(0); - } - retval = fprintf(fp,"\nBy residue: "); - if (retval == EOF) return(0); - for (i = nbins - 1; i>=0; i--) { - retval = fprintf(fp," %.0f", hystogramR[i]); - if (retval == EOF) return(0); - } - retval = fprintf(fp,"\n"); - if (retval == EOF) return(0); - } - - FREE(hystogramQ); - FREE(hystogramR); -#else - for (i = 0; i < slots; i++) { - nzeroes += cache[i].h == 0; - } - exUsed = 100.0 * - (1.0 - exp(-(table->cacheinserts - table->cacheLastInserts) / - (double) slots)); - retval = fprintf(fp,"Cache used slots = %.2f%% (expected %.2f%%)\n", - 100.0 - (double) nzeroes * 100.0 / (double) slots, - exUsed); - if (retval == EOF) return(0); -#endif - return(1); - -} /* end of cuddCacheProfile */ - - -/**Function******************************************************************** - - Synopsis [Resizes the cache.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddCacheResize( - DdManager * table) -{ - DdCache *cache, *oldcache, *oldacache, *entry, *old; - int i; - int posn, shift; - unsigned int slots, oldslots; - double offset; - int moved = 0; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); -#ifndef DD_CACHE_PROFILE - ptruint misalignment; - DdNodePtr *mem; -#endif - - oldcache = table->cache; - oldacache = table->acache; - oldslots = table->cacheSlots; - slots = table->cacheSlots = oldslots << 1; - -#ifdef DD_VERBOSE - (void) fprintf(table->err,"Resizing the cache from %d to %d entries\n", - oldslots, slots); - (void) fprintf(table->err, - "\thits = %g\tmisses = %g\thit ratio = %5.3f\n", - table->cacheHits, table->cacheMisses, - table->cacheHits / (table->cacheHits + table->cacheMisses)); -#endif - - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - table->acache = cache = ALLOC(DdCache,slots+1); - MMoutOfMemory = saveHandler; - /* If we fail to allocate the new table we just give up. */ - if (cache == NULL) { -#ifdef DD_VERBOSE - (void) fprintf(table->err,"Resizing failed. Giving up.\n"); -#endif - table->cacheSlots = oldslots; - table->acache = oldacache; - /* Do not try to resize again. */ - table->maxCacheHard = oldslots - 1; - table->cacheSlack = - (oldslots + 1); - return; - } - /* If the size of the cache entry is a power of 2, we want to - ** enforce alignment to that power of two. This happens when - ** DD_CACHE_PROFILE is not defined. */ -#ifdef DD_CACHE_PROFILE - table->cache = cache; -#else - mem = (DdNodePtr *) cache; - misalignment = (ptruint) mem & (sizeof(DdCache) - 1); - mem += (sizeof(DdCache) - misalignment) / sizeof(DdNodePtr); - table->cache = cache = (DdCache *) mem; - assert(((ptruint) table->cache & (sizeof(DdCache) - 1)) == 0); -#endif - shift = --(table->cacheShift); - table->memused += (slots - oldslots) * sizeof(DdCache); - table->cacheSlack -= slots; /* need these many slots to double again */ - - /* Clear new cache. */ - for (i = 0; (unsigned) i < slots; i++) { - cache[i].data = NULL; - cache[i].h = 0; -#ifdef DD_CACHE_PROFILE - cache[i].count = 0; -#endif - } - - /* Copy from old cache to new one. */ - for (i = 0; (unsigned) i < oldslots; i++) { - old = &oldcache[i]; - if (old->data != NULL) { - posn = ddCHash2(old->h,old->f,old->g,shift); - entry = &cache[posn]; - entry->f = old->f; - entry->g = old->g; - entry->h = old->h; - entry->data = old->data; -#ifdef DD_CACHE_PROFILE - entry->count = 1; -#endif - moved++; - } - } - - FREE(oldacache); - - /* Reinitialize measurements so as to avoid division by 0 and - ** immediate resizing. - */ - offset = (double) (int) (slots * table->minHit + 1); - table->totCacheMisses += table->cacheMisses - offset; - table->cacheMisses = offset; - table->totCachehits += table->cacheHits; - table->cacheHits = 0; - table->cacheLastInserts = table->cacheinserts - (double) moved; - -} /* end of cuddCacheResize */ - - -/**Function******************************************************************** - - Synopsis [Flushes the cache.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddCacheFlush( - DdManager * table) -{ - int i, slots; - DdCache *cache; - - slots = table->cacheSlots; - cache = table->cache; - for (i = 0; i < slots; i++) { - table->cachedeletions += cache[i].data != NULL; - cache[i].data = NULL; - } - table->cacheLastInserts = table->cacheinserts; - - return; - -} /* end of cuddCacheFlush */ - - -/**Function******************************************************************** - - Synopsis [Returns the floor of the logarithm to the base 2.] - - Description [Returns the floor of the logarithm to the base 2. - The input value is assumed to be greater than 0.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddComputeFloorLog2( - unsigned int value) -{ - int floorLog = 0; -#ifdef DD_DEBUG - assert(value > 0); -#endif - while (value > 1) { - floorLog++; - value >>= 1; - } - return(floorLog); - -} /* end of cuddComputeFloorLog2 */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddCheck.c b/src/bdd/cudd/cuddCheck.c deleted file mode 100644 index aec8246d..00000000 --- a/src/bdd/cudd/cuddCheck.c +++ /dev/null @@ -1,851 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddCheck.c] - - PackageName [cudd] - - Synopsis [Functions to check consistency of data structures.] - - Description [External procedures included in this module: -
          -
        • Cudd_DebugCheck() -
        • Cudd_CheckKeys() -
        - Internal procedures included in this module: -
          -
        • cuddHeapProfile() -
        • cuddPrintNode() -
        • cuddPrintVarGroups() -
        - Static procedures included in this module: -
          -
        • debugFindParent() -
        - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddCheck.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void debugFindParent ARGS((DdManager *table, DdNode *node)); -#if 0 -static void debugCheckParent ARGS((DdManager *table, DdNode *node)); -#endif - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Checks for inconsistencies in the DD heap.] - - Description [Checks for inconsistencies in the DD heap: -
          -
        • node has illegal index -
        • live node has dead children -
        • node has illegal Then or Else pointers -
        • BDD/ADD node has identical children -
        • ZDD node has zero then child -
        • wrong number of total nodes -
        • wrong number of dead nodes -
        • ref count error at node -
        - Returns 0 if no inconsistencies are found; DD_OUT_OF_MEM if there is - not enough memory; 1 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_CheckKeys] - -******************************************************************************/ -int -Cudd_DebugCheck( - DdManager * table) -{ - unsigned int i; - int j,count; - int slots; - DdNodePtr *nodelist; - DdNode *f; - DdNode *sentinel = &(table->sentinel); - st_table *edgeTable; /* stores internal ref count for each node */ - st_generator *gen; - int flag = 0; - int totalNode; - int deadNode; - int index; - - - edgeTable = st_init_table(st_ptrcmp,st_ptrhash); - if (edgeTable == NULL) return(CUDD_OUT_OF_MEM); - - /* Check the BDD/ADD subtables. */ - for (i = 0; i < (unsigned) table->size; i++) { - index = table->invperm[i]; - if (i != (unsigned) table->perm[index]) { - (void) fprintf(table->err, - "Permutation corrupted: invperm[%d] = %d\t perm[%d] = %d\n", - i, index, index, table->perm[index]); - } - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - - totalNode = 0; - deadNode = 0; - for (j = 0; j < slots; j++) { /* for each subtable slot */ - f = nodelist[j]; - while (f != sentinel) { - totalNode++; - if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) { - if ((int) f->index != index) { - (void) fprintf(table->err, - "Error: node has illegal index\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if ((unsigned) cuddI(table,cuddT(f)->index) <= i || - (unsigned) cuddI(table,Cudd_Regular(cuddE(f))->index) - <= i) { - (void) fprintf(table->err, - "Error: node has illegal children\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if (Cudd_Regular(cuddT(f)) != cuddT(f)) { - (void) fprintf(table->err, - "Error: node has illegal form\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if (cuddT(f) == cuddE(f)) { - (void) fprintf(table->err, - "Error: node has identical children\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if (cuddT(f)->ref == 0 || Cudd_Regular(cuddE(f))->ref == 0) { - (void) fprintf(table->err, - "Error: live node has dead children\n"); - cuddPrintNode(f,table->err); - flag =1; - } - /* Increment the internal reference count for the - ** then child of the current node. - */ - if (st_lookup(edgeTable,(char *)cuddT(f),(char **)&count)) { - count++; - } else { - count = 1; - } - if (st_insert(edgeTable,(char *)cuddT(f), - (char *)(long)count) == ST_OUT_OF_MEM) { - st_free_table(edgeTable); - return(CUDD_OUT_OF_MEM); - } - - /* Increment the internal reference count for the - ** else child of the current node. - */ - if (st_lookup(edgeTable,(char *)Cudd_Regular(cuddE(f)),(char **)&count)) { - count++; - } else { - count = 1; - } - if (st_insert(edgeTable,(char *)Cudd_Regular(cuddE(f)), - (char *)(long)count) == ST_OUT_OF_MEM) { - st_free_table(edgeTable); - return(CUDD_OUT_OF_MEM); - } - } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) { - deadNode++; -#if 0 - debugCheckParent(table,f); -#endif - } else { - fprintf(table->err, - "Error: node has illegal Then or Else pointers\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - - f = f->next; - } /* for each element of the collision list */ - } /* for each subtable slot */ - - if ((unsigned) totalNode != table->subtables[i].keys) { - fprintf(table->err,"Error: wrong number of total nodes\n"); - flag = 1; - } - if ((unsigned) deadNode != table->subtables[i].dead) { - fprintf(table->err,"Error: wrong number of dead nodes\n"); - flag = 1; - } - } /* for each BDD/ADD subtable */ - - /* Check the ZDD subtables. */ - for (i = 0; i < (unsigned) table->sizeZ; i++) { - index = table->invpermZ[i]; - if (i != (unsigned) table->permZ[index]) { - (void) fprintf(table->err, - "Permutation corrupted: invpermZ[%d] = %d\t permZ[%d] = %d in ZDD\n", - i, index, index, table->permZ[index]); - } - nodelist = table->subtableZ[i].nodelist; - slots = table->subtableZ[i].slots; - - totalNode = 0; - deadNode = 0; - for (j = 0; j < slots; j++) { /* for each subtable slot */ - f = nodelist[j]; - while (f != NULL) { - totalNode++; - if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref != 0) { - if ((int) f->index != index) { - (void) fprintf(table->err, - "Error: ZDD node has illegal index\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if (Cudd_IsComplement(cuddT(f)) || - Cudd_IsComplement(cuddE(f))) { - (void) fprintf(table->err, - "Error: ZDD node has complemented children\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if ((unsigned) cuddIZ(table,cuddT(f)->index) <= i || - (unsigned) cuddIZ(table,cuddE(f)->index) <= i) { - (void) fprintf(table->err, - "Error: ZDD node has illegal children\n"); - cuddPrintNode(f,table->err); - cuddPrintNode(cuddT(f),table->err); - cuddPrintNode(cuddE(f),table->err); - flag = 1; - } - if (cuddT(f) == DD_ZERO(table)) { - (void) fprintf(table->err, - "Error: ZDD node has zero then child\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - if (cuddT(f)->ref == 0 || cuddE(f)->ref == 0) { - (void) fprintf(table->err, - "Error: ZDD live node has dead children\n"); - cuddPrintNode(f,table->err); - flag =1; - } - /* Increment the internal reference count for the - ** then child of the current node. - */ - if (st_lookup(edgeTable,(char *)cuddT(f),(char **)&count)) { - count++; - } else { - count = 1; - } - if (st_insert(edgeTable,(char *)cuddT(f), - (char *)(long)count) == ST_OUT_OF_MEM) { - st_free_table(edgeTable); - return(CUDD_OUT_OF_MEM); - } - - /* Increment the internal reference count for the - ** else child of the current node. - */ - if (st_lookup(edgeTable,(char *)cuddE(f),(char **)&count)) { - count++; - } else { - count = 1; - } - if (st_insert(edgeTable,(char *)cuddE(f), - (char *)(long)count) == ST_OUT_OF_MEM) { - st_free_table(edgeTable); - table->errorCode = CUDD_MEMORY_OUT; - return(CUDD_OUT_OF_MEM); - } - } else if (cuddT(f) != NULL && cuddE(f) != NULL && f->ref == 0) { - deadNode++; -#if 0 - debugCheckParent(table,f); -#endif - } else { - fprintf(table->err, - "Error: ZDD node has illegal Then or Else pointers\n"); - cuddPrintNode(f,table->err); - flag = 1; - } - - f = f->next; - } /* for each element of the collision list */ - } /* for each subtable slot */ - - if ((unsigned) totalNode != table->subtableZ[i].keys) { - fprintf(table->err, - "Error: wrong number of total nodes in ZDD\n"); - flag = 1; - } - if ((unsigned) deadNode != table->subtableZ[i].dead) { - fprintf(table->err, - "Error: wrong number of dead nodes in ZDD\n"); - flag = 1; - } - } /* for each ZDD subtable */ - - /* Check the constant table. */ - nodelist = table->constants.nodelist; - slots = table->constants.slots; - - totalNode = 0; - deadNode = 0; - for (j = 0; j < slots; j++) { - f = nodelist[j]; - while (f != NULL) { - totalNode++; - if (f->ref != 0) { - if (f->index != CUDD_CONST_INDEX) { - fprintf(table->err,"Error: node has illegal index\n"); -#if SIZEOF_VOID_P == 8 - fprintf(table->err, - " node 0x%lx, id = %d, ref = %d, value = %g\n", - (unsigned long)f,f->index,f->ref,cuddV(f)); -#else - fprintf(table->err, - " node 0x%x, id = %d, ref = %d, value = %g\n", - (unsigned)f,f->index,f->ref,cuddV(f)); -#endif - flag = 1; - } - } else { - deadNode++; - } - f = f->next; - } - } - if ((unsigned) totalNode != table->constants.keys) { - (void) fprintf(table->err, - "Error: wrong number of total nodes in constants\n"); - flag = 1; - } - if ((unsigned) deadNode != table->constants.dead) { - (void) fprintf(table->err, - "Error: wrong number of dead nodes in constants\n"); - flag = 1; - } - gen = st_init_gen(edgeTable); - while (st_gen(gen,(char **)&f,(char **)&count)) { - if (count > (int)(f->ref) && f->ref != DD_MAXREF) { -#if SIZEOF_VOID_P == 8 - fprintf(table->err,"ref count error at node 0x%lx, count = %d, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n",(unsigned long)f,count,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f)); -#else - fprintf(table->err,"ref count error at node 0x%x, count = %d, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",(unsigned)f,count,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f)); -#endif - debugFindParent(table,f); - flag = 1; - } - } - st_free_gen(gen); - st_free_table(edgeTable); - - return (flag); - -} /* end of Cudd_DebugCheck */ - - -/**Function******************************************************************** - - Synopsis [Checks for several conditions that should not occur.] - - Description [Checks for the following conditions: -
          -
        • Wrong sizes of subtables. -
        • Wrong number of keys found in unique subtable. -
        • Wrong number of dead found in unique subtable. -
        • Wrong number of keys found in the constant table -
        • Wrong number of dead found in the constant table -
        • Wrong number of total slots found -
        • Wrong number of maximum keys found -
        • Wrong number of total dead found -
        - Reports the average length of non-empty lists. Returns the number of - subtables for which the number of keys is wrong.] - - SideEffects [None] - - SeeAlso [Cudd_DebugCheck] - -******************************************************************************/ -int -Cudd_CheckKeys( - DdManager * table) -{ - int size; - int i,j; - DdNodePtr *nodelist; - DdNode *node; - DdNode *sentinel = &(table->sentinel); - DdSubtable *subtable; - int keys; - int dead; - int count = 0; - int totalKeys = 0; - int totalSlots = 0; - int totalDead = 0; - int nonEmpty = 0; - unsigned int slots; - int logSlots; - int shift; - - size = table->size; - - for (i = 0; i < size; i++) { - subtable = &(table->subtables[i]); - nodelist = subtable->nodelist; - keys = subtable->keys; - dead = subtable->dead; - totalKeys += keys; - slots = subtable->slots; - shift = subtable->shift; - logSlots = sizeof(int) * 8 - shift; - if (((slots >> logSlots) << logSlots) != slots) { - (void) fprintf(table->err, - "Unique table %d is not the right power of 2\n", i); - (void) fprintf(table->err, - " slots = %u shift = %d\n", slots, shift); - } - totalSlots += slots; - totalDead += dead; - for (j = 0; (unsigned) j < slots; j++) { - node = nodelist[j]; - if (node != sentinel) { - nonEmpty++; - } - while (node != sentinel) { - keys--; - if (node->ref == 0) { - dead--; - } - node = node->next; - } - } - if (keys != 0) { - (void) fprintf(table->err, "Wrong number of keys found \ -in unique table %d (difference=%d)\n", i, keys); - count++; - } - if (dead != 0) { - (void) fprintf(table->err, "Wrong number of dead found \ -in unique table no. %d (difference=%d)\n", i, dead); - } - } /* for each BDD/ADD subtable */ - - /* Check the ZDD subtables. */ - size = table->sizeZ; - - for (i = 0; i < size; i++) { - subtable = &(table->subtableZ[i]); - nodelist = subtable->nodelist; - keys = subtable->keys; - dead = subtable->dead; - totalKeys += keys; - totalSlots += subtable->slots; - totalDead += dead; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - if (node != NULL) { - nonEmpty++; - } - while (node != NULL) { - keys--; - if (node->ref == 0) { - dead--; - } - node = node->next; - } - } - if (keys != 0) { - (void) fprintf(table->err, "Wrong number of keys found \ -in ZDD unique table no. %d (difference=%d)\n", i, keys); - count++; - } - if (dead != 0) { - (void) fprintf(table->err, "Wrong number of dead found \ -in ZDD unique table no. %d (difference=%d)\n", i, dead); - } - } /* for each ZDD subtable */ - - /* Check the constant table. */ - subtable = &(table->constants); - nodelist = subtable->nodelist; - keys = subtable->keys; - dead = subtable->dead; - totalKeys += keys; - totalSlots += subtable->slots; - totalDead += dead; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - if (node != NULL) { - nonEmpty++; - } - while (node != NULL) { - keys--; - if (node->ref == 0) { - dead--; - } - node = node->next; - } - } - if (keys != 0) { - (void) fprintf(table->err, "Wrong number of keys found \ -in the constant table (difference=%d)\n", keys); - count++; - } - if (dead != 0) { - (void) fprintf(table->err, "Wrong number of dead found \ -in the constant table (difference=%d)\n", dead); - } - if ((unsigned) totalKeys != table->keys + table->keysZ) { - (void) fprintf(table->err, "Wrong number of total keys found \ -(difference=%d)\n", totalKeys-table->keys); - } - if ((unsigned) totalSlots != table->slots) { - (void) fprintf(table->err, "Wrong number of total slots found \ -(difference=%d)\n", totalSlots-table->slots); - } - if (table->minDead != (unsigned) (table->gcFrac * table->slots)) { - (void) fprintf(table->err, "Wrong number of minimum dead found \ -(%d vs. %d)\n", table->minDead, - (unsigned) (table->gcFrac * (double) table->slots)); - } - if ((unsigned) totalDead != table->dead + table->deadZ) { - (void) fprintf(table->err, "Wrong number of total dead found \ -(difference=%d)\n", totalDead-table->dead); - } - (void)printf("Average length of non-empty lists = %g\n", - (double) table->keys / (double) nonEmpty); - - return(count); - -} /* end of Cudd_CheckKeys */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints information about the heap.] - - Description [Prints to the manager's stdout the number of live nodes for each - level of the DD heap that contains at least one live node. It also - prints a summary containing: -
          -
        • total number of tables; -
        • number of tables with live nodes; -
        • table with the largest number of live nodes; -
        • number of nodes in that table. -
        - If more than one table contains the maximum number of live nodes, - only the one of lowest index is reported. Returns 1 in case of success - and 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddHeapProfile( - DdManager * dd) -{ - int ntables = dd->size; - DdSubtable *subtables = dd->subtables; - int i, /* loop index */ - nodes, /* live nodes in i-th layer */ - retval, /* return value of fprintf */ - largest = -1, /* index of the table with most live nodes */ - maxnodes = -1, /* maximum number of live nodes in a table */ - nonempty = 0; /* number of tables with live nodes */ - - /* Print header. */ -#if SIZEOF_VOID_P == 8 - retval = fprintf(dd->out,"*** DD heap profile for 0x%lx ***\n", - (unsigned long) dd); -#else - retval = fprintf(dd->out,"*** DD heap profile for 0x%x ***\n", - (unsigned) dd); -#endif - if (retval == EOF) return 0; - - /* Print number of live nodes for each nonempty table. */ - for (i=0; iout,"%5d: %5d nodes\n", i, nodes); - if (retval == EOF) return 0; - if (nodes > maxnodes) { - maxnodes = nodes; - largest = i; - } - } - } - - nodes = dd->constants.keys - dd->constants.dead; - if (nodes) { - nonempty++; - retval = fprintf(dd->out,"const: %5d nodes\n", nodes); - if (retval == EOF) return 0; - if (nodes > maxnodes) { - maxnodes = nodes; - largest = CUDD_CONST_INDEX; - } - } - - /* Print summary. */ - retval = fprintf(dd->out,"Summary: %d tables, %d non-empty, largest: %d ", - ntables+1, nonempty, largest); - if (retval == EOF) return 0; - retval = fprintf(dd->out,"(with %d nodes)\n", maxnodes); - if (retval == EOF) return 0; - - return(1); - -} /* end of cuddHeapProfile */ - - -/**Function******************************************************************** - - Synopsis [Prints out information on a node.] - - Description [Prints out information on a node.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddPrintNode( - DdNode * f, - FILE *fp) -{ - f = Cudd_Regular(f); -#if SIZEOF_VOID_P == 8 - (void) fprintf(fp," node 0x%lx, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n",(unsigned long)f,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f)); -#else - (void) fprintf(fp," node 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",(unsigned)f,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f)); -#endif - -} /* end of cuddPrintNode */ - - - -/**Function******************************************************************** - - Synopsis [Prints the variable groups as a parenthesized list.] - - Description [Prints the variable groups as a parenthesized list. - For each group the level range that it represents is printed. After - each group, the group's flags are printed, preceded by a `|'. For - each flag (except MTR_TERMINAL) a character is printed. -
          -
        • F: MTR_FIXED -
        • N: MTR_NEWNODE -
        • S: MTR_SOFT -
        - The second argument, silent, if different from 0, causes - Cudd_PrintVarGroups to only check the syntax of the group tree.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddPrintVarGroups( - DdManager * dd /* manager */, - MtrNode * root /* root of the group tree */, - int zdd /* 0: BDD; 1: ZDD */, - int silent /* flag to check tree syntax only */) -{ - MtrNode *node; - int level; - - assert(root != NULL); - assert(root->younger == NULL || root->younger->elder == root); - assert(root->elder == NULL || root->elder->younger == root); - if (zdd) { - level = dd->permZ[root->index]; - } else { - level = dd->perm[root->index]; - } - if (!silent) (void) printf("(%d",level); - if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) { - if (!silent) (void) printf(","); - } else { - node = root->child; - while (node != NULL) { - assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size)); - assert(node->parent == root); - cuddPrintVarGroups(dd,node,zdd,silent); - node = node->younger; - } - } - if (!silent) { - (void) printf("%d", level + root->size - 1); - if (root->flags != MTR_DEFAULT) { - (void) printf("|"); - if (MTR_TEST(root,MTR_FIXED)) (void) printf("F"); - if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N"); - if (MTR_TEST(root,MTR_SOFT)) (void) printf("S"); - } - (void) printf(")"); - if (root->parent == NULL) (void) printf("\n"); - } - assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0); - return; - -} /* end of cuddPrintVarGroups */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Searches the subtables above node for its parents.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -debugFindParent( - DdManager * table, - DdNode * node) -{ - int i,j; - int slots; - DdNodePtr *nodelist; - DdNode *f; - - for (i = 0; i < cuddI(table,node->index); i++) { - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - - for (j=0;jout,"parent is at 0x%lx, id = %d, ref = %d, then = 0x%lx, else = 0x%lx\n", - (unsigned long)f,f->index,f->ref,(unsigned long)cuddT(f),(unsigned long)cuddE(f)); -#else - (void) fprintf(table->out,"parent is at 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n", - (unsigned)f,f->index,f->ref,(unsigned)cuddT(f),(unsigned)cuddE(f)); -#endif - } - f = f->next; - } - } - } - -} /* end of debugFindParent */ - - -#if 0 -/**Function******************************************************************** - - Synopsis [Reports an error if a (dead) node has a non-dead parent.] - - Description [Searches all the subtables above node. Very expensive. - The same check is now implemented more efficiently in ddDebugCheck.] - - SideEffects [None] - - SeeAlso [debugFindParent] - -******************************************************************************/ -static void -debugCheckParent( - DdManager * table, - DdNode * node) -{ - int i,j; - int slots; - DdNode **nodelist,*f; - - for (i = 0; i < cuddI(table,node->index); i++) { - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - - for (j=0;jref != 0) { - (void) fprintf(table->err, - "error with zero ref count\n"); - (void) fprintf(table->err,"parent is 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",f,f->index,f->ref,cuddT(f),cuddE(f)); - (void) fprintf(table->err,"child is 0x%x, id = %d, ref = %d, then = 0x%x, else = 0x%x\n",node,node->index,node->ref,cuddT(node),cuddE(node)); - } - f = f->next; - } - } - } -} -#endif diff --git a/src/bdd/cudd/cuddClip.c b/src/bdd/cudd/cuddClip.c deleted file mode 100644 index 4da296ef..00000000 --- a/src/bdd/cudd/cuddClip.c +++ /dev/null @@ -1,531 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddClip.c] - - PackageName [cudd] - - Synopsis [Clipping functions.] - - Description [External procedures included in this module: -
          -
        • Cudd_bddClippingAnd() -
        • Cudd_bddClippingAndAbstract() -
        - Internal procedures included in this module: -
          -
        • cuddBddClippingAnd() -
        • cuddBddClippingAndAbstract() -
        - Static procedures included in this module: -
          -
        • cuddBddClippingAndRecur() -
        • cuddBddClipAndAbsRecur() -
        - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddClip.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * cuddBddClippingAndRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, int distance, int direction)); -static DdNode * cuddBddClipAndAbsRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube, int distance, int direction)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Approximates the conjunction of two BDDs f and g.] - - Description [Approximates the conjunction of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddAnd] - -******************************************************************************/ -DdNode * -Cudd_bddClippingAnd( - DdManager * dd /* manager */, - DdNode * f /* first conjunct */, - DdNode * g /* second conjunct */, - int maxDepth /* maximum recursion depth */, - int direction /* under (0) or over (1) approximation */) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddClippingAnd(dd,f,g,maxDepth,direction); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddClippingAnd */ - - -/**Function******************************************************************** - - Synopsis [Approximates the conjunction of two BDDs f and g and - simultaneously abstracts the variables in cube.] - - Description [Approximates the conjunction of two BDDs f and g and - simultaneously abstracts the variables in cube. The variables are - existentially abstracted. Returns a pointer to the resulting BDD if - successful; NULL if the intermediate result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddAndAbstract Cudd_bddClippingAnd] - -******************************************************************************/ -DdNode * -Cudd_bddClippingAndAbstract( - DdManager * dd /* manager */, - DdNode * f /* first conjunct */, - DdNode * g /* second conjunct */, - DdNode * cube /* cube of variables to be abstracted */, - int maxDepth /* maximum recursion depth */, - int direction /* under (0) or over (1) approximation */) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddClippingAndAbstract(dd,f,g,cube,maxDepth,direction); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddClippingAndAbstract */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Approximates the conjunction of two BDDs f and g.] - - Description [Approximates the conjunction of two BDDs f and g. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddClippingAnd] - -******************************************************************************/ -DdNode * -cuddBddClippingAnd( - DdManager * dd /* manager */, - DdNode * f /* first conjunct */, - DdNode * g /* second conjunct */, - int maxDepth /* maximum recursion depth */, - int direction /* under (0) or over (1) approximation */) -{ - DdNode *res; - - res = cuddBddClippingAndRecur(dd,f,g,maxDepth,direction); - - return(res); - -} /* end of cuddBddClippingAnd */ - - -/**Function******************************************************************** - - Synopsis [Approximates the conjunction of two BDDs f and g and - simultaneously abstracts the variables in cube.] - - Description [Approximates the conjunction of two BDDs f and g and - simultaneously abstracts the variables in cube. Returns a - pointer to the resulting BDD if successful; NULL if the intermediate - result blows up.] - - SideEffects [None] - - SeeAlso [Cudd_bddClippingAndAbstract] - -******************************************************************************/ -DdNode * -cuddBddClippingAndAbstract( - DdManager * dd /* manager */, - DdNode * f /* first conjunct */, - DdNode * g /* second conjunct */, - DdNode * cube /* cube of variables to be abstracted */, - int maxDepth /* maximum recursion depth */, - int direction /* under (0) or over (1) approximation */) -{ - DdNode *res; - - res = cuddBddClipAndAbsRecur(dd,f,g,cube,maxDepth,direction); - - return(res); - -} /* end of cuddBddClippingAndAbstract */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddClippingAnd.] - - Description [Implements the recursive step of Cudd_bddClippingAnd by taking - the conjunction of two BDDs. Returns a pointer to the result is - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddBddClippingAnd] - -******************************************************************************/ -static DdNode * -cuddBddClippingAndRecur( - DdManager * manager, - DdNode * f, - DdNode * g, - int distance, - int direction) -{ - DdNode *F, *ft, *fe, *G, *gt, *ge; - DdNode *one, *zero, *r, *t, *e; - unsigned int topf, topg, index; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); - if (f == g || g == one) return(f); - if (f == one) return(g); - if (distance == 0) { - /* One last attempt at returning the right result. We sort of - ** cheat by calling Cudd_bddLeq. */ - if (Cudd_bddLeq(manager,f,g)) return(f); - if (Cudd_bddLeq(manager,g,f)) return(g); - if (direction == 1) { - if (Cudd_bddLeq(manager,f,Cudd_Not(g)) || - Cudd_bddLeq(manager,g,Cudd_Not(f))) return(zero); - } - return(Cudd_NotCond(one,(direction == 0))); - } - - /* At this point f and g are not constant. */ - distance--; - - /* Check cache. Try to increase cache efficiency by sorting the - ** pointers. */ - if (f > g) { - DdNode *tmp = f; - f = g; g = tmp; - } - F = Cudd_Regular(f); - G = Cudd_Regular(g); - cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) - (direction ? Cudd_bddClippingAnd : cuddBddClippingAnd); - if (F->ref != 1 || G->ref != 1) { - r = cuddCacheLookup2(manager, cacheOp, f, g); - if (r != NULL) return(r); - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - topf = manager->perm[F->index]; - topg = manager->perm[G->index]; - - /* Compute cofactors. */ - if (topf <= topg) { - index = F->index; - ft = cuddT(F); - fe = cuddE(F); - if (Cudd_IsComplement(f)) { - ft = Cudd_Not(ft); - fe = Cudd_Not(fe); - } - } else { - index = G->index; - ft = fe = f; - } - - if (topg <= topf) { - gt = cuddT(G); - ge = cuddE(G); - if (Cudd_IsComplement(g)) { - gt = Cudd_Not(gt); - ge = Cudd_Not(ge); - } - } else { - gt = ge = g; - } - - t = cuddBddClippingAndRecur(manager, ft, gt, distance, direction); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddBddClippingAndRecur(manager, fe, ge, distance, direction); - if (e == NULL) { - Cudd_RecursiveDeref(manager, t); - return(NULL); - } - cuddRef(e); - - if (t == e) { - r = t; - } else { - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (r == NULL) { - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - return(NULL); - } - } - } - cuddDeref(e); - cuddDeref(t); - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert2(manager, cacheOp, f, g, r); - return(r); - -} /* end of cuddBddClippingAndRecur */ - - -/**Function******************************************************************** - - Synopsis [Approximates the AND of two BDDs and simultaneously abstracts the - variables in cube.] - - Description [Approximates the AND of two BDDs and simultaneously - abstracts the variables in cube. The variables are existentially - abstracted. Returns a pointer to the result is successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddClippingAndAbstract] - -******************************************************************************/ -static DdNode * -cuddBddClipAndAbsRecur( - DdManager * manager, - DdNode * f, - DdNode * g, - DdNode * cube, - int distance, - int direction) -{ - DdNode *F, *ft, *fe, *G, *gt, *ge; - DdNode *one, *zero, *r, *t, *e, *Cube; - unsigned int topf, topg, topcube, top, index; - ptruint cacheTag; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); - if (f == one && g == one) return(one); - if (cube == one) { - return(cuddBddClippingAndRecur(manager, f, g, distance, direction)); - } - if (f == one || f == g) { - return (cuddBddExistAbstractRecur(manager, g, cube)); - } - if (g == one) { - return (cuddBddExistAbstractRecur(manager, f, cube)); - } - if (distance == 0) return(Cudd_NotCond(one,(direction == 0))); - - /* At this point f, g, and cube are not constant. */ - distance--; - - /* Check cache. */ - if (f > g) { /* Try to increase cache efficiency. */ - DdNode *tmp = f; - f = g; g = tmp; - } - F = Cudd_Regular(f); - G = Cudd_Regular(g); - cacheTag = direction ? DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG : - DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG; - if (F->ref != 1 || G->ref != 1) { - r = cuddCacheLookup(manager, cacheTag, - f, g, cube); - if (r != NULL) { - return(r); - } - } - - /* Here we can skip the use of cuddI, because the operands are known - ** to be non-constant. - */ - topf = manager->perm[F->index]; - topg = manager->perm[G->index]; - top = ddMin(topf, topg); - topcube = manager->perm[cube->index]; - - if (topcube < top) { - return(cuddBddClipAndAbsRecur(manager, f, g, cuddT(cube), - distance, direction)); - } - /* Now, topcube >= top. */ - - if (topf == top) { - index = F->index; - ft = cuddT(F); - fe = cuddE(F); - if (Cudd_IsComplement(f)) { - ft = Cudd_Not(ft); - fe = Cudd_Not(fe); - } - } else { - index = G->index; - ft = fe = f; - } - - if (topg == top) { - gt = cuddT(G); - ge = cuddE(G); - if (Cudd_IsComplement(g)) { - gt = Cudd_Not(gt); - ge = Cudd_Not(ge); - } - } else { - gt = ge = g; - } - - if (topcube == top) { - Cube = cuddT(cube); - } else { - Cube = cube; - } - - t = cuddBddClipAndAbsRecur(manager, ft, gt, Cube, distance, direction); - if (t == NULL) return(NULL); - - /* Special case: 1 OR anything = 1. Hence, no need to compute - ** the else branch if t is 1. - */ - if (t == one && topcube == top) { - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert(manager, cacheTag, f, g, cube, one); - return(one); - } - cuddRef(t); - - e = cuddBddClipAndAbsRecur(manager, fe, ge, Cube, distance, direction); - if (e == NULL) { - Cudd_RecursiveDeref(manager, t); - return(NULL); - } - cuddRef(e); - - if (topcube == top) { /* abstract */ - r = cuddBddClippingAndRecur(manager, Cudd_Not(t), Cudd_Not(e), - distance, (direction == 0)); - if (r == NULL) { - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - return(NULL); - } - r = Cudd_Not(r); - cuddRef(r); - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - cuddDeref(r); - } else if (t == e) { - r = t; - cuddDeref(t); - cuddDeref(e); - } else { - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); - if (r == NULL) { - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(manager,(int)index,t,e); - if (r == NULL) { - Cudd_RecursiveDeref(manager, t); - Cudd_RecursiveDeref(manager, e); - return(NULL); - } - } - cuddDeref(e); - cuddDeref(t); - } - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert(manager, cacheTag, f, g, cube, r); - return (r); - -} /* end of cuddBddClipAndAbsRecur */ - diff --git a/src/bdd/cudd/cuddCof.c b/src/bdd/cudd/cuddCof.c deleted file mode 100644 index f79e3f91..00000000 --- a/src/bdd/cudd/cuddCof.c +++ /dev/null @@ -1,300 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddCof.c] - - PackageName [cudd] - - Synopsis [Cofactoring functions.] - - Description [External procedures included in this module: -
          -
        • Cudd_Cofactor() -
        - Internal procedures included in this module: -
          -
        • cuddGetBranches() -
        • cuddCheckCube() -
        • cuddCofactorRecur() -
        - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddCof.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the cofactor of f with respect to g.] - - Description [Computes the cofactor of f with respect to g; g must be - the BDD or the ADD of a cube. Returns a pointer to the cofactor if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain Cudd_bddRestrict] - -******************************************************************************/ -DdNode * -Cudd_Cofactor( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res,*zero; - - zero = Cudd_Not(DD_ONE(dd)); - if (g == zero || g == DD_ZERO(dd)) { - (void) fprintf(dd->err,"Cudd_Cofactor: Invalid restriction 1\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - do { - dd->reordered = 0; - res = cuddCofactorRecur(dd,f,g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_Cofactor */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the children of g.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddGetBranches( - DdNode * g, - DdNode ** g1, - DdNode ** g0) -{ - DdNode *G = Cudd_Regular(g); - - *g1 = cuddT(G); - *g0 = cuddE(G); - if (Cudd_IsComplement(g)) { - *g1 = Cudd_Not(*g1); - *g0 = Cudd_Not(*g0); - } - -} /* end of cuddGetBranches */ - - -/**Function******************************************************************** - - Synopsis [Checks whether g is the BDD of a cube.] - - Description [Checks whether g is the BDD of a cube. Returns 1 in case - of success; 0 otherwise. The constant 1 is a valid cube, but all other - constant functions cause cuddCheckCube to return 0.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddCheckCube( - DdManager * dd, - DdNode * g) -{ - DdNode *g1,*g0,*one,*zero; - - one = DD_ONE(dd); - if (g == one) return(1); - if (Cudd_IsConstant(g)) return(0); - - zero = Cudd_Not(one); - cuddGetBranches(g,&g1,&g0); - - if (g0 == zero) { - return(cuddCheckCube(dd, g1)); - } - if (g1 == zero) { - return(cuddCheckCube(dd, g0)); - } - return(0); - -} /* end of cuddCheckCube */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_Cofactor.] - - Description [Performs the recursive step of Cudd_Cofactor. Returns a - pointer to the cofactor if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Cofactor] - -******************************************************************************/ -DdNode * -cuddCofactorRecur( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r; - unsigned int topf,topg; - int comple; - - statLine(dd); - F = Cudd_Regular(f); - if (cuddIsConstant(F)) return(f); - - one = DD_ONE(dd); - - /* The invariant g != 0 is true on entry to this procedure and is - ** recursively maintained by it. Therefore it suffices to test g - ** against one to make sure it is not constant. - */ - if (g == one) return(f); - /* From now on, f and g are known not to be constants. */ - - comple = f != F; - r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - topf = dd->perm[F->index]; - G = Cudd_Regular(g); - topg = dd->perm[G->index]; - - /* We take the cofactors of F because we are going to rely on - ** the fact that the cofactors of the complement are the complements - ** of the cofactors to better utilize the cache. Variable comple - ** remembers whether we have to complement the result or not. - */ - if (topf <= topg) { - f1 = cuddT(F); f0 = cuddE(F); - } else { - f1 = f0 = F; - } - if (topg <= topf) { - g1 = cuddT(G); g0 = cuddE(G); - if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); } - } else { - g1 = g0 = g; - } - - zero = Cudd_Not(one); - if (topf >= topg) { - if (g0 == zero || g0 == DD_ZERO(dd)) { - r = cuddCofactorRecur(dd, f1, g1); - } else if (g1 == zero || g1 == DD_ZERO(dd)) { - r = cuddCofactorRecur(dd, f0, g0); - } else { - (void) fprintf(dd->out, - "Cudd_Cofactor: Invalid restriction 2\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - if (r == NULL) return(NULL); - } else /* if (topf < topg) */ { - t = cuddCofactorRecur(dd, f1, g); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddCofactorRecur(dd, f0, g); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddRef(e); - - if (t == e) { - r = t; - } else if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e)); - if (r != NULL) - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(dd,(int)F->index,t,e); - } - if (r == NULL) { - Cudd_RecursiveDeref(dd ,e); - Cudd_RecursiveDeref(dd ,t); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r); - - return(Cudd_NotCond(r,comple)); - -} /* end of cuddCofactorRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddCompose.c b/src/bdd/cudd/cuddCompose.c deleted file mode 100644 index 8c858051..00000000 --- a/src/bdd/cudd/cuddCompose.c +++ /dev/null @@ -1,1722 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddCompose.c] - - PackageName [cudd] - - Synopsis [Functional composition and variable permutation of DDs.] - - Description [External procedures included in this module: -
          -
        • Cudd_bddCompose() -
        • Cudd_addCompose() -
        • Cudd_addPermute() -
        • Cudd_addSwapVariables() -
        • Cudd_bddPermute() -
        • Cudd_bddVarMap() -
        • Cudd_SetVarMap() -
        • Cudd_bddSwapVariables() -
        • Cudd_bddAdjPermuteX() -
        • Cudd_addVectorCompose() -
        • Cudd_addGeneralVectorCompose() -
        • Cudd_addNonSimCompose() -
        • Cudd_bddVectorCompose() -
        - Internal procedures included in this module: -
          -
        • cuddBddComposeRecur() -
        • cuddAddComposeRecur() -
        - Static procedures included in this module: -
          -
        • cuddAddPermuteRecur() -
        • cuddBddPermuteRecur() -
        • cuddBddVarMapRecur() -
        • cuddAddVectorComposeRecur() -
        • cuddAddGeneralVectorComposeRecur() -
        • cuddAddNonSimComposeRecur() -
        • cuddBddVectorComposeRecur() -
        • ddIsIthAddVar() -
        • ddIsIthAddVarPair() -
        - The permutation functions use a local cache because the results to - be remembered depend on the permutation being applied. Since the - permutation is just an array, it cannot be stored in the global - cache. There are different procedured for BDDs and ADDs. This is - because bddPermuteRecur uses cuddBddIteRecur. If this were changed, - the procedures could be merged.] - - Author [Fabio Somenzi and Kavita Ravi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddCompose.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -#ifdef DD_DEBUG -static int addPermuteRecurHits; -static int bddPermuteRecurHits; -static int bddVectorComposeHits; -static int addVectorComposeHits; - -static int addGeneralVectorComposeHits; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * cuddAddPermuteRecur ARGS((DdManager *manager, DdHashTable *table, DdNode *node, int *permut)); -static DdNode * cuddBddPermuteRecur ARGS((DdManager *manager, DdHashTable *table, DdNode *node, int *permut)); -static DdNode * cuddBddVarMapRecur ARGS((DdManager *manager, DdNode *f)); -static DdNode * cuddAddVectorComposeRecur ARGS((DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest)); -static DdNode * cuddAddNonSimComposeRecur ARGS((DdManager *dd, DdNode *f, DdNode **vector, DdNode *key, DdNode *cube, int lastsub)); -static DdNode * cuddBddVectorComposeRecur ARGS((DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest)); -DD_INLINE static int ddIsIthAddVar ARGS((DdManager *dd, DdNode *f, unsigned int i)); - -static DdNode * cuddAddGeneralVectorComposeRecur ARGS((DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vectorOn, DdNode **vectorOff, int deepest)); -DD_INLINE static int ddIsIthAddVarPair ARGS((DdManager *dd, DdNode *f, DdNode *g, unsigned int i)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Substitutes g for x_v in the BDD for f.] - - Description [Substitutes g for x_v in the BDD for f. v is the index of the - variable to be substituted. Cudd_bddCompose passes the corresponding - projection function to the recursive procedure, so that the cache may - be used. Returns the composed BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addCompose] - -******************************************************************************/ -DdNode * -Cudd_bddCompose( - DdManager * dd, - DdNode * f, - DdNode * g, - int v) -{ - DdNode *proj, *res; - - /* Sanity check. */ - if (v < 0 || v > dd->size) return(NULL); - - proj = dd->vars[v]; - do { - dd->reordered = 0; - res = cuddBddComposeRecur(dd,f,g,proj); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddCompose */ - - -/**Function******************************************************************** - - Synopsis [Substitutes g for x_v in the ADD for f.] - - Description [Substitutes g for x_v in the ADD for f. v is the index of the - variable to be substituted. g must be a 0-1 ADD. Cudd_bddCompose passes - the corresponding projection function to the recursive procedure, so - that the cache may be used. Returns the composed ADD if successful; - NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddCompose] - -******************************************************************************/ -DdNode * -Cudd_addCompose( - DdManager * dd, - DdNode * f, - DdNode * g, - int v) -{ - DdNode *proj, *res; - - /* Sanity check. */ - if (v < 0 || v > dd->size) return(NULL); - - proj = dd->vars[v]; - do { - dd->reordered = 0; - res = cuddAddComposeRecur(dd,f,g,proj); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addCompose */ - - -/**Function******************************************************************** - - Synopsis [Permutes the variables of an ADD.] - - Description [Given a permutation in array permut, creates a new ADD - with permuted variables. There should be an entry in array permut - for each variable in the manager. The i-th entry of permut holds the - index of the variable that is to substitute the i-th - variable. Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute Cudd_addSwapVariables] - -******************************************************************************/ -DdNode * -Cudd_addPermute( - DdManager * manager, - DdNode * node, - int * permut) -{ - DdHashTable *table; - DdNode *res; - - do { - manager->reordered = 0; - table = cuddHashTableInit(manager,1,2); - if (table == NULL) return(NULL); - /* Recursively solve the problem. */ - res = cuddAddPermuteRecur(manager,table,node,permut); - if (res != NULL) cuddRef(res); - /* Dispose of local cache. */ - cuddHashTableQuit(table); - } while (manager->reordered == 1); - - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_addPermute */ - - -/**Function******************************************************************** - - Synopsis [Swaps two sets of variables of the same size (x and y) in - the ADD f.] - - Description [Swaps two sets of variables of the same size (x and y) in - the ADD f. The size is given by n. The two sets of variables are - assumed to be disjoint. Returns a pointer to the resulting ADD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] - -******************************************************************************/ -DdNode * -Cudd_addSwapVariables( - DdManager * dd, - DdNode * f, - DdNode ** x, - DdNode ** y, - int n) -{ - DdNode *swapped; - int i, j, k; - int *permut; - - permut = ALLOC(int,dd->size); - if (permut == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < dd->size; i++) permut[i] = i; - for (i = 0; i < n; i++) { - j = x[i]->index; - k = y[i]->index; - permut[j] = k; - permut[k] = j; - } - - swapped = Cudd_addPermute(dd,f,permut); - FREE(permut); - - return(swapped); - -} /* end of Cudd_addSwapVariables */ - - -/**Function******************************************************************** - - Synopsis [Permutes the variables of a BDD.] - - Description [Given a permutation in array permut, creates a new BDD - with permuted variables. There should be an entry in array permut - for each variable in the manager. The i-th entry of permut holds the - index of the variable that is to substitute the i-th variable. - Returns a pointer to the resulting BDD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] - -******************************************************************************/ -DdNode * -Cudd_bddPermute( - DdManager * manager, - DdNode * node, - int * permut) -{ - DdHashTable *table; - DdNode *res; - - do { - manager->reordered = 0; - table = cuddHashTableInit(manager,1,2); - if (table == NULL) return(NULL); - res = cuddBddPermuteRecur(manager,table,node,permut); - if (res != NULL) cuddRef(res); - /* Dispose of local cache. */ - cuddHashTableQuit(table); - - } while (manager->reordered == 1); - - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_bddPermute */ - - -/**Function******************************************************************** - - Synopsis [Remaps the variables of a BDD using the default variable map.] - - Description [Remaps the variables of a BDD using the default - variable map. A typical use of this function is to swap two sets of - variables. The variable map must be registered with Cudd_SetVarMap. - Returns a pointer to the resulting BDD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute Cudd_bddSwapVariables Cudd_SetVarMap] - -******************************************************************************/ -DdNode * -Cudd_bddVarMap( - DdManager * manager /* DD manager */, - DdNode * f /* function in which to remap variables */) -{ - DdNode *res; - - if (manager->map == NULL) return(NULL); - do { - manager->reordered = 0; - res = cuddBddVarMapRecur(manager, f); - } while (manager->reordered == 1); - - return(res); - -} /* end of Cudd_bddVarMap */ - - -/**Function******************************************************************** - - Synopsis [Registers a variable mapping with the manager.] - - Description [Registers with the manager a variable mapping described - by two sets of variables. This variable mapping is then used by - functions like Cudd_bddVarMap. This function is convenient for - those applications that perform the same mapping several times. - However, if several different permutations are used, it may be more - efficient not to rely on the registered mapping, because changing - mapping causes the cache to be cleared. (The initial setting, - however, does not clear the cache.) The two sets of variables (x and - y) must have the same size (x and y). The size is given by n. The - two sets of variables are normally disjoint, but this restriction is - not imposeded by the function. When new variables are created, the - map is automatically extended (each new variable maps to - itself). The typical use, however, is to wait until all variables - are created, and then create the map. Returns 1 if the mapping is - successfully registered with the manager; 0 otherwise.] - - SideEffects [Modifies the manager. May clear the cache.] - - SeeAlso [Cudd_bddVarMap Cudd_bddPermute Cudd_bddSwapVariables] - -******************************************************************************/ -int -Cudd_SetVarMap ( - DdManager *manager /* DD manager */, - DdNode **x /* first array of variables */, - DdNode **y /* second array of variables */, - int n /* length of both arrays */) -{ - int i; - - if (manager->map != NULL) { - cuddCacheFlush(manager); - } else { - manager->map = ALLOC(int,manager->maxSize); - if (manager->map == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return(0); - } - manager->memused += sizeof(int) * manager->maxSize; - } - /* Initialize the map to the identity. */ - for (i = 0; i < manager->size; i++) { - manager->map[i] = i; - } - /* Create the map. */ - for (i = 0; i < n; i++) { - manager->map[x[i]->index] = y[i]->index; - manager->map[y[i]->index] = x[i]->index; - } - return(1); - -} /* end of Cudd_SetVarMap */ - - -/**Function******************************************************************** - - Synopsis [Swaps two sets of variables of the same size (x and y) in - the BDD f.] - - Description [Swaps two sets of variables of the same size (x and y) - in the BDD f. The size is given by n. The two sets of variables are - assumed to be disjoint. Returns a pointer to the resulting BDD if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute Cudd_addSwapVariables] - -******************************************************************************/ -DdNode * -Cudd_bddSwapVariables( - DdManager * dd, - DdNode * f, - DdNode ** x, - DdNode ** y, - int n) -{ - DdNode *swapped; - int i, j, k; - int *permut; - - permut = ALLOC(int,dd->size); - if (permut == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < dd->size; i++) permut[i] = i; - for (i = 0; i < n; i++) { - j = x[i]->index; - k = y[i]->index; - permut[j] = k; - permut[k] = j; - } - - swapped = Cudd_bddPermute(dd,f,permut); - FREE(permut); - - return(swapped); - -} /* end of Cudd_bddSwapVariables */ - - -/**Function******************************************************************** - - Synopsis [Rearranges a set of variables in the BDD B.] - - Description [Rearranges a set of variables in the BDD B. The size of - the set is given by n. This procedure is intended for the - `randomization' of the priority functions. Returns a pointer to the - BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute Cudd_bddSwapVariables - Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_PrioritySelect] - -******************************************************************************/ -DdNode * -Cudd_bddAdjPermuteX( - DdManager * dd, - DdNode * B, - DdNode ** x, - int n) -{ - DdNode *swapped; - int i, j, k; - int *permut; - - permut = ALLOC(int,dd->size); - if (permut == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < dd->size; i++) permut[i] = i; - for (i = 0; i < n-2; i += 3) { - j = x[i]->index; - k = x[i+1]->index; - permut[j] = k; - permut[k] = j; - } - - swapped = Cudd_bddPermute(dd,B,permut); - FREE(permut); - - return(swapped); - -} /* end of Cudd_bddAdjPermuteX */ - - -/**Function******************************************************************** - - Synopsis [Composes an ADD with a vector of 0-1 ADDs.] - - Description [Given a vector of 0-1 ADDs, creates a new ADD by - substituting the 0-1 ADDs for the variables of the ADD f. There - should be an entry in vector for each variable in the manager. - If no substitution is sought for a given variable, the corresponding - projection function should be specified in the vector. - This function implements simultaneous composition. - Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addNonSimCompose Cudd_addPermute Cudd_addCompose - Cudd_bddVectorCompose] - -******************************************************************************/ -DdNode * -Cudd_addVectorCompose( - DdManager * dd, - DdNode * f, - DdNode ** vector) -{ - DdHashTable *table; - DdNode *res; - int deepest; - int i; - - do { - dd->reordered = 0; - /* Initialize local cache. */ - table = cuddHashTableInit(dd,1,2); - if (table == NULL) return(NULL); - - /* Find deepest real substitution. */ - for (deepest = dd->size - 1; deepest >= 0; deepest--) { - i = dd->invperm[deepest]; - if (!ddIsIthAddVar(dd,vector[i],i)) { - break; - } - } - - /* Recursively solve the problem. */ - res = cuddAddVectorComposeRecur(dd,table,f,vector,deepest); - if (res != NULL) cuddRef(res); - - /* Dispose of local cache. */ - cuddHashTableQuit(table); - } while (dd->reordered == 1); - - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_addVectorCompose */ - - -/**Function******************************************************************** - - Synopsis [Composes an ADD with a vector of ADDs.] - - Description [Given a vector of ADDs, creates a new ADD by substituting the - ADDs for the variables of the ADD f. vectorOn contains ADDs to be substituted - for the x_v and vectorOff the ADDs to be substituted for x_v'. There should - be an entry in vector for each variable in the manager. If no substitution - is sought for a given variable, the corresponding projection function should - be specified in the vector. This function implements simultaneous - composition. Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addVectorCompose Cudd_addNonSimCompose Cudd_addPermute - Cudd_addCompose Cudd_bddVectorCompose] - -******************************************************************************/ -DdNode * -Cudd_addGeneralVectorCompose( - DdManager * dd, - DdNode * f, - DdNode ** vectorOn, - DdNode ** vectorOff) -{ - DdHashTable *table; - DdNode *res; - int deepest; - int i; - - do { - dd->reordered = 0; - /* Initialize local cache. */ - table = cuddHashTableInit(dd,1,2); - if (table == NULL) return(NULL); - - /* Find deepest real substitution. */ - for (deepest = dd->size - 1; deepest >= 0; deepest--) { - i = dd->invperm[deepest]; - if (!ddIsIthAddVarPair(dd,vectorOn[i],vectorOff[i],i)) { - break; - } - } - - /* Recursively solve the problem. */ - res = cuddAddGeneralVectorComposeRecur(dd,table,f,vectorOn, - vectorOff,deepest); - if (res != NULL) cuddRef(res); - - /* Dispose of local cache. */ - cuddHashTableQuit(table); - } while (dd->reordered == 1); - - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_addGeneralVectorCompose */ - - -/**Function******************************************************************** - - Synopsis [Composes an ADD with a vector of 0-1 ADDs.] - - Description [Given a vector of 0-1 ADDs, creates a new ADD by - substituting the 0-1 ADDs for the variables of the ADD f. There - should be an entry in vector for each variable in the manager. - This function implements non-simultaneous composition. If any of the - functions being composed depends on any of the variables being - substituted, then the result depends on the order of composition, - which in turn depends on the variable order: The variables farther from - the roots in the order are substituted first. - Returns a pointer to the resulting ADD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addVectorCompose Cudd_addPermute Cudd_addCompose] - -******************************************************************************/ -DdNode * -Cudd_addNonSimCompose( - DdManager * dd, - DdNode * f, - DdNode ** vector) -{ - DdNode *cube, *key, *var, *tmp, *piece; - DdNode *res; - int i, lastsub; - - /* The cache entry for this function is composed of three parts: - ** f itself, the replacement relation, and the cube of the - ** variables being substituted. - ** The replacement relation is the product of the terms (yi EXNOR gi). - ** This apporach allows us to use the global cache for this function, - ** with great savings in memory with respect to using arrays for the - ** cache entries. - ** First we build replacement relation and cube of substituted - ** variables from the vector specifying the desired composition. - */ - key = DD_ONE(dd); - cuddRef(key); - cube = DD_ONE(dd); - cuddRef(cube); - for (i = (int) dd->size - 1; i >= 0; i--) { - if (ddIsIthAddVar(dd,vector[i],(unsigned int)i)) { - continue; - } - var = Cudd_addIthVar(dd,i); - if (var == NULL) { - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(var); - /* Update cube. */ - tmp = Cudd_addApply(dd,Cudd_addTimes,var,cube); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,cube); - Cudd_RecursiveDeref(dd,var); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,cube); - cube = tmp; - /* Update replacement relation. */ - piece = Cudd_addApply(dd,Cudd_addXnor,var,vector[i]); - if (piece == NULL) { - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,var); - return(NULL); - } - cuddRef(piece); - Cudd_RecursiveDeref(dd,var); - tmp = Cudd_addApply(dd,Cudd_addTimes,key,piece); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,piece); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,piece); - key = tmp; - } - - /* Now try composition, until no reordering occurs. */ - do { - /* Find real substitution with largest index. */ - for (lastsub = dd->size - 1; lastsub >= 0; lastsub--) { - if (!ddIsIthAddVar(dd,vector[lastsub],(unsigned int)lastsub)) { - break; - } - } - - /* Recursively solve the problem. */ - dd->reordered = 0; - res = cuddAddNonSimComposeRecur(dd,f,vector,key,cube,lastsub+1); - if (res != NULL) cuddRef(res); - - } while (dd->reordered == 1); - - Cudd_RecursiveDeref(dd,key); - Cudd_RecursiveDeref(dd,cube); - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_addNonSimCompose */ - - -/**Function******************************************************************** - - Synopsis [Composes a BDD with a vector of BDDs.] - - Description [Given a vector of BDDs, creates a new BDD by - substituting the BDDs for the variables of the BDD f. There - should be an entry in vector for each variable in the manager. - If no substitution is sought for a given variable, the corresponding - projection function should be specified in the vector. - This function implements simultaneous composition. - Returns a pointer to the resulting BDD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute Cudd_bddCompose Cudd_addVectorCompose] - -******************************************************************************/ -DdNode * -Cudd_bddVectorCompose( - DdManager * dd, - DdNode * f, - DdNode ** vector) -{ - DdHashTable *table; - DdNode *res; - int deepest; - int i; - - do { - dd->reordered = 0; - /* Initialize local cache. */ - table = cuddHashTableInit(dd,1,2); - if (table == NULL) return(NULL); - - /* Find deepest real substitution. */ - for (deepest = dd->size - 1; deepest >= 0; deepest--) { - i = dd->invperm[deepest]; - if (vector[i] != dd->vars[i]) { - break; - } - } - - /* Recursively solve the problem. */ - res = cuddBddVectorComposeRecur(dd,table,f,vector, deepest); - if (res != NULL) cuddRef(res); - - /* Dispose of local cache. */ - cuddHashTableQuit(table); - } while (dd->reordered == 1); - - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_bddVectorCompose */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddCompose.] - - Description [Performs the recursive step of Cudd_bddCompose. - Exploits the fact that the composition of f' with g - produces the complement of the composition of f with g to better - utilize the cache. Returns the composed BDD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddCompose] - -******************************************************************************/ -DdNode * -cuddBddComposeRecur( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * proj) -{ - DdNode *F, *G, *f1, *f0, *g1, *g0, *r, *t, *e; - unsigned int v, topf, topg, topindex; - int comple; - - statLine(dd); - v = dd->perm[proj->index]; - F = Cudd_Regular(f); - topf = cuddI(dd,F->index); - - /* Terminal case. Subsumes the test for constant f. */ - if (topf > v) return(f); - - /* We solve the problem for a regular pointer, and then complement - ** the result if the pointer was originally complemented. - */ - comple = Cudd_IsComplement(f); - - /* Check cache. */ - r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - if (topf == v) { - /* Compose. */ - f1 = cuddT(F); - f0 = cuddE(F); - r = cuddBddIteRecur(dd, g, f1, f0); - if (r == NULL) return(NULL); - } else { - /* Compute cofactors of f and g. Remember the index of the top - ** variable. - */ - G = Cudd_Regular(g); - topg = cuddI(dd,G->index); - if (topf > topg) { - topindex = G->index; - f1 = f0 = F; - } else { - topindex = F->index; - f1 = cuddT(F); - f0 = cuddE(F); - } - if (topg > topf) { - g1 = g0 = g; - } else { - g1 = cuddT(G); - g0 = cuddE(G); - if (g != G) { - g1 = Cudd_Not(g1); - g0 = Cudd_Not(g0); - } - } - /* Recursive step. */ - t = cuddBddComposeRecur(dd, f1, g1, proj); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddBddComposeRecur(dd, f0, g0, proj); - if (e == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - cuddRef(e); - - r = cuddBddIteRecur(dd, dd->vars[topindex], t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, t); - Cudd_IterDerefBdd(dd, e); - return(NULL); - } - cuddRef(r); - Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */ - Cudd_IterDerefBdd(dd, e); - cuddDeref(r); - } - - cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r); - - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddComposeRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addCompose.] - - Description [Performs the recursive step of Cudd_addCompose. - Returns the composed BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addCompose] - -******************************************************************************/ -DdNode * -cuddAddComposeRecur( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * proj) -{ - DdNode *f1, *f0, *g1, *g0, *r, *t, *e; - unsigned int v, topf, topg, topindex; - - statLine(dd); - v = dd->perm[proj->index]; - topf = cuddI(dd,f->index); - - /* Terminal case. Subsumes the test for constant f. */ - if (topf > v) return(f); - - /* Check cache. */ - r = cuddCacheLookup(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj); - if (r != NULL) { - return(r); - } - - if (topf == v) { - /* Compose. */ - f1 = cuddT(f); - f0 = cuddE(f); - r = cuddAddIteRecur(dd, g, f1, f0); - if (r == NULL) return(NULL); - } else { - /* Compute cofactors of f and g. Remember the index of the top - ** variable. - */ - topg = cuddI(dd,g->index); - if (topf > topg) { - topindex = g->index; - f1 = f0 = f; - } else { - topindex = f->index; - f1 = cuddT(f); - f0 = cuddE(f); - } - if (topg > topf) { - g1 = g0 = g; - } else { - g1 = cuddT(g); - g0 = cuddE(g); - } - /* Recursive step. */ - t = cuddAddComposeRecur(dd, f1, g1, proj); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddAddComposeRecur(dd, f0, g0, proj); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddRef(e); - - if (t == e) { - r = t; - } else { - r = cuddUniqueInter(dd, (int) topindex, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj,r); - - return(r); - -} /* end of cuddAddComposeRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_addPermute.] - - Description [ Recursively puts the ADD in the order given in the - array permut. Checks for trivial cases to terminate recursion, then - splits on the children of this node. Once the solutions for the - children are obtained, it puts into the current position the node - from the rest of the ADD that should be here. Then returns this ADD. - The key here is that the node being visited is NOT put in its proper - place by this instance, but rather is switched when its proper - position is reached in the recursion tree.

        - The DdNode * that is returned is the same ADD as passed in as node, - but in the new order.] - - SideEffects [None] - - SeeAlso [Cudd_addPermute cuddBddPermuteRecur] - -******************************************************************************/ -static DdNode * -cuddAddPermuteRecur( - DdManager * manager /* DD manager */, - DdHashTable * table /* computed table */, - DdNode * node /* ADD to be reordered */, - int * permut /* permutation array */) -{ - DdNode *T,*E; - DdNode *res,*var; - int index; - - statLine(manager); - /* Check for terminal case of constant node. */ - if (cuddIsConstant(node)) { - return(node); - } - - /* If problem already solved, look up answer and return. */ - if (node->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) { -#ifdef DD_DEBUG - addPermuteRecurHits++; -#endif - return(res); - } - - /* Split and recur on children of this node. */ - T = cuddAddPermuteRecur(manager,table,cuddT(node),permut); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddAddPermuteRecur(manager,table,cuddE(node),permut); - if (E == NULL) { - Cudd_RecursiveDeref(manager, T); - return(NULL); - } - cuddRef(E); - - /* Move variable that should be in this position to this position - ** by creating a single var ADD for that variable, and calling - ** cuddAddIteRecur with the T and E we just created. - */ - index = permut[node->index]; - var = cuddUniqueInter(manager,index,DD_ONE(manager),DD_ZERO(manager)); - if (var == NULL) return(NULL); - cuddRef(var); - res = cuddAddIteRecur(manager,var,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(manager,var); - Cudd_RecursiveDeref(manager, T); - Cudd_RecursiveDeref(manager, E); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(manager,var); - Cudd_RecursiveDeref(manager, T); - Cudd_RecursiveDeref(manager, E); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again. - */ - if (node->ref != 1) { - ptrint fanout = (ptrint) node->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert1(table,node,res,fanout)) { - Cudd_RecursiveDeref(manager, res); - return(NULL); - } - } - cuddDeref(res); - return(res); - -} /* end of cuddAddPermuteRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddPermute.] - - Description [ Recursively puts the BDD in the order given in the array permut. - Checks for trivial cases to terminate recursion, then splits on the - children of this node. Once the solutions for the children are - obtained, it puts into the current position the node from the rest of - the BDD that should be here. Then returns this BDD. - The key here is that the node being visited is NOT put in its proper - place by this instance, but rather is switched when its proper position - is reached in the recursion tree.

        - The DdNode * that is returned is the same BDD as passed in as node, - but in the new order.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute cuddAddPermuteRecur] - -******************************************************************************/ -static DdNode * -cuddBddPermuteRecur( - DdManager * manager /* DD manager */, - DdHashTable * table /* computed table */, - DdNode * node /* BDD to be reordered */, - int * permut /* permutation array */) -{ - DdNode *N,*T,*E; - DdNode *res; - int index; - - statLine(manager); - N = Cudd_Regular(node); - - /* Check for terminal case of constant node. */ - if (cuddIsConstant(N)) { - return(node); - } - - /* If problem already solved, look up answer and return. */ - if (N->ref != 1 && (res = cuddHashTableLookup1(table,N)) != NULL) { -#ifdef DD_DEBUG - bddPermuteRecurHits++; -#endif - return(Cudd_NotCond(res,N != node)); - } - - /* Split and recur on children of this node. */ - T = cuddBddPermuteRecur(manager,table,cuddT(N),permut); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddBddPermuteRecur(manager,table,cuddE(N),permut); - if (E == NULL) { - Cudd_IterDerefBdd(manager, T); - return(NULL); - } - cuddRef(E); - - /* Move variable that should be in this position to this position - ** by retrieving the single var BDD for that variable, and calling - ** cuddBddIteRecur with the T and E we just created. - */ - index = permut[N->index]; - res = cuddBddIteRecur(manager,manager->vars[index],T,E); - if (res == NULL) { - Cudd_IterDerefBdd(manager, T); - Cudd_IterDerefBdd(manager, E); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(manager, T); - Cudd_IterDerefBdd(manager, E); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again. - */ - if (N->ref != 1) { - ptrint fanout = (ptrint) N->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert1(table,N,res,fanout)) { - Cudd_IterDerefBdd(manager, res); - return(NULL); - } - } - cuddDeref(res); - return(Cudd_NotCond(res,N != node)); - -} /* end of cuddBddPermuteRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddVarMap.] - - Description [Implements the recursive step of Cudd_bddVarMap. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddVarMap] - -******************************************************************************/ -static DdNode * -cuddBddVarMapRecur( - DdManager *manager /* DD manager */, - DdNode *f /* BDD to be remapped */) -{ - DdNode *F, *T, *E; - DdNode *res; - int index; - - statLine(manager); - F = Cudd_Regular(f); - - /* Check for terminal case of constant node. */ - if (cuddIsConstant(F)) { - return(f); - } - - /* If problem already solved, look up answer and return. */ - if (F->ref != 1 && - (res = cuddCacheLookup1(manager,Cudd_bddVarMap,F)) != NULL) { - return(Cudd_NotCond(res,F != f)); - } - - /* Split and recur on children of this node. */ - T = cuddBddVarMapRecur(manager,cuddT(F)); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddBddVarMapRecur(manager,cuddE(F)); - if (E == NULL) { - Cudd_IterDerefBdd(manager, T); - return(NULL); - } - cuddRef(E); - - /* Move variable that should be in this position to this position - ** by retrieving the single var BDD for that variable, and calling - ** cuddBddIteRecur with the T and E we just created. - */ - index = manager->map[F->index]; - res = cuddBddIteRecur(manager,manager->vars[index],T,E); - if (res == NULL) { - Cudd_IterDerefBdd(manager, T); - Cudd_IterDerefBdd(manager, E); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(manager, T); - Cudd_IterDerefBdd(manager, E); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again. - */ - if (F->ref != 1) { - cuddCacheInsert1(manager,Cudd_bddVarMap,F,res); - } - cuddDeref(res); - return(Cudd_NotCond(res,F != f)); - -} /* end of cuddBddVarMapRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addVectorCompose.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -cuddAddVectorComposeRecur( - DdManager * dd /* DD manager */, - DdHashTable * table /* computed table */, - DdNode * f /* ADD in which to compose */, - DdNode ** vector /* functions to substitute */, - int deepest /* depth of deepest substitution */) -{ - DdNode *T,*E; - DdNode *res; - - statLine(dd); - /* If we are past the deepest substitution, return f. */ - if (cuddI(dd,f->index) > deepest) { - return(f); - } - - if ((res = cuddHashTableLookup1(table,f)) != NULL) { -#ifdef DD_DEBUG - addVectorComposeHits++; -#endif - return(res); - } - - /* Split and recur on children of this node. */ - T = cuddAddVectorComposeRecur(dd,table,cuddT(f),vector,deepest); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddAddVectorComposeRecur(dd,table,cuddE(f),vector,deepest); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - - /* Retrieve the 0-1 ADD for the current top variable and call - ** cuddAddIteRecur with the T and E we just created. - */ - res = cuddAddIteRecur(dd,vector[f->index],T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again - */ - if (f->ref != 1) { - ptrint fanout = (ptrint) f->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert1(table,f,res,fanout)) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - } - cuddDeref(res); - return(res); - -} /* end of cuddAddVectorComposeRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addGeneralVectorCompose.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -cuddAddGeneralVectorComposeRecur( - DdManager * dd /* DD manager */, - DdHashTable * table /* computed table */, - DdNode * f /* ADD in which to compose */, - DdNode ** vectorOn /* functions to substitute for x_i */, - DdNode ** vectorOff /* functions to substitute for x_i' */, - int deepest /* depth of deepest substitution */) -{ - DdNode *T,*E,*t,*e; - DdNode *res; - - /* If we are past the deepest substitution, return f. */ - if (cuddI(dd,f->index) > deepest) { - return(f); - } - - if ((res = cuddHashTableLookup1(table,f)) != NULL) { -#ifdef DD_DEBUG - addGeneralVectorComposeHits++; -#endif - return(res); - } - - /* Split and recur on children of this node. */ - T = cuddAddGeneralVectorComposeRecur(dd,table,cuddT(f), - vectorOn,vectorOff,deepest); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddAddGeneralVectorComposeRecur(dd,table,cuddE(f), - vectorOn,vectorOff,deepest); - if (E == NULL) { - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - cuddRef(E); - - /* Retrieve the compose ADDs for the current top variable and call - ** cuddAddApplyRecur with the T and E we just created. - */ - t = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOn[f->index],T); - if (t == NULL) { - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - return(NULL); - } - cuddRef(t); - e = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOff[f->index],E); - if (e == NULL) { - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - Cudd_RecursiveDeref(dd,t); - return(NULL); - } - cuddRef(e); - res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - Cudd_RecursiveDeref(dd,t); - Cudd_RecursiveDeref(dd,e); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - Cudd_RecursiveDeref(dd,t); - Cudd_RecursiveDeref(dd,e); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again - */ - if (f->ref != 1) { - ptrint fanout = (ptrint) f->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert1(table,f,res,fanout)) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - } - cuddDeref(res); - return(res); - -} /* end of cuddAddGeneralVectorComposeRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addNonSimCompose.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -cuddAddNonSimComposeRecur( - DdManager * dd, - DdNode * f, - DdNode ** vector, - DdNode * key, - DdNode * cube, - int lastsub) -{ - DdNode *f1, *f0, *key1, *key0, *cube1, *var; - DdNode *T,*E; - DdNode *r; - unsigned int top, topf, topk, topc; - unsigned int index; - int i; - DdNode **vect1; - DdNode **vect0; - - statLine(dd); - /* If we are past the deepest substitution, return f. */ - if (cube == DD_ONE(dd) || cuddIsConstant(f)) { - return(f); - } - - /* If problem already solved, look up answer and return. */ - r = cuddCacheLookup(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube); - if (r != NULL) { - return(r); - } - - /* Find top variable. we just need to look at f, key, and cube, - ** because all the varibles in the gi are in key. - */ - topf = cuddI(dd,f->index); - topk = cuddI(dd,key->index); - top = ddMin(topf,topk); - topc = cuddI(dd,cube->index); - top = ddMin(top,topc); - index = dd->invperm[top]; - - /* Compute the cofactors. */ - if (topf == top) { - f1 = cuddT(f); - f0 = cuddE(f); - } else { - f1 = f0 = f; - } - if (topc == top) { - cube1 = cuddT(cube); - /* We want to eliminate vector[index] from key. Otherwise - ** cache performance is severely affected. Hence we - ** existentially quantify the variable with index "index" from key. - */ - var = Cudd_addIthVar(dd, (int) index); - if (var == NULL) { - return(NULL); - } - cuddRef(var); - key1 = cuddAddExistAbstractRecur(dd, key, var); - if (key1 == NULL) { - Cudd_RecursiveDeref(dd,var); - return(NULL); - } - cuddRef(key1); - Cudd_RecursiveDeref(dd,var); - key0 = key1; - } else { - cube1 = cube; - if (topk == top) { - key1 = cuddT(key); - key0 = cuddE(key); - } else { - key1 = key0 = key; - } - cuddRef(key1); - } - - /* Allocate two new vectors for the cofactors of vector. */ - vect1 = ALLOC(DdNode *,lastsub); - if (vect1 == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd,key1); - return(NULL); - } - vect0 = ALLOC(DdNode *,lastsub); - if (vect0 == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd,key1); - FREE(vect1); - return(NULL); - } - - /* Cofactor the gi. Eliminate vect1[index] and vect0[index], because - ** we do not need them. - */ - for (i = 0; i < lastsub; i++) { - DdNode *gi = vector[i]; - if (gi == NULL) { - vect1[i] = vect0[i] = NULL; - } else if (gi->index == index) { - vect1[i] = cuddT(gi); - vect0[i] = cuddE(gi); - } else { - vect1[i] = vect0[i] = gi; - } - } - vect1[index] = vect0[index] = NULL; - - /* Recur on children. */ - T = cuddAddNonSimComposeRecur(dd,f1,vect1,key1,cube1,lastsub); - FREE(vect1); - if (T == NULL) { - Cudd_RecursiveDeref(dd,key1); - FREE(vect0); - return(NULL); - } - cuddRef(T); - E = cuddAddNonSimComposeRecur(dd,f0,vect0,key0,cube1,lastsub); - FREE(vect0); - if (E == NULL) { - Cudd_RecursiveDeref(dd,key1); - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - Cudd_RecursiveDeref(dd,key1); - - /* Retrieve the 0-1 ADD for the current top variable from vector, - ** and call cuddAddIteRecur with the T and E we just created. - */ - r = cuddAddIteRecur(dd,vector[index],T,E); - if (r == NULL) { - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - cuddDeref(r); - - /* Store answer to trim recursion. */ - cuddCacheInsert(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube,r); - - return(r); - -} /* end of cuddAddNonSimComposeRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddVectorCompose.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -cuddBddVectorComposeRecur( - DdManager * dd /* DD manager */, - DdHashTable * table /* computed table */, - DdNode * f /* BDD in which to compose */, - DdNode ** vector /* functions to be composed */, - int deepest /* depth of the deepest substitution */) -{ - DdNode *F,*T,*E; - DdNode *res; - - statLine(dd); - F = Cudd_Regular(f); - - /* If we are past the deepest substitution, return f. */ - if (cuddI(dd,F->index) > deepest) { - return(f); - } - - /* If problem already solved, look up answer and return. */ - if ((res = cuddHashTableLookup1(table,F)) != NULL) { -#ifdef DD_DEBUG - bddVectorComposeHits++; -#endif - return(Cudd_NotCond(res,F != f)); - } - - /* Split and recur on children of this node. */ - T = cuddBddVectorComposeRecur(dd,table,cuddT(F),vector, deepest); - if (T == NULL) return(NULL); - cuddRef(T); - E = cuddBddVectorComposeRecur(dd,table,cuddE(F),vector, deepest); - if (E == NULL) { - Cudd_IterDerefBdd(dd, T); - return(NULL); - } - cuddRef(E); - - /* Call cuddBddIteRecur with the BDD that replaces the current top - ** variable and the T and E we just created. - */ - res = cuddBddIteRecur(dd,vector[F->index],T,E); - if (res == NULL) { - Cudd_IterDerefBdd(dd, T); - Cudd_IterDerefBdd(dd, E); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(dd, T); - Cudd_IterDerefBdd(dd, E); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again. - */ - if (F->ref != 1) { - ptrint fanout = (ptrint) F->ref; - cuddSatDec(fanout); - if (!cuddHashTableInsert1(table,F,res,fanout)) { - Cudd_IterDerefBdd(dd, res); - return(NULL); - } - } - cuddDeref(res); - return(Cudd_NotCond(res,F != f)); - -} /* end of cuddBddVectorComposeRecur */ - - -/**Function******************************************************************** - - Synopsis [Comparison of a function to the i-th ADD variable.] - - Description [Comparison of a function to the i-th ADD variable. Returns 1 if - the function is the i-th ADD variable; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DD_INLINE -static int -ddIsIthAddVar( - DdManager * dd, - DdNode * f, - unsigned int i) -{ - return(f->index == i && cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd)); - -} /* end of ddIsIthAddVar */ - - -/**Function******************************************************************** - - Synopsis [Comparison of a pair of functions to the i-th ADD variable.] - - Description [Comparison of a pair of functions to the i-th ADD - variable. Returns 1 if the functions are the i-th ADD variable and its - complement; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DD_INLINE -static int -ddIsIthAddVarPair( - DdManager * dd, - DdNode * f, - DdNode * g, - unsigned int i) -{ - return(f->index == i && g->index == i && - cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd) && - cuddT(g) == DD_ZERO(dd) && cuddE(g) == DD_ONE(dd)); - -} /* end of ddIsIthAddVarPair */ diff --git a/src/bdd/cudd/cuddDecomp.c b/src/bdd/cudd/cuddDecomp.c deleted file mode 100644 index 4fde7392..00000000 --- a/src/bdd/cudd/cuddDecomp.c +++ /dev/null @@ -1,2150 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddDecomp.c] - - PackageName [cudd] - - Synopsis [Functions for BDD decomposition.] - - Description [External procedures included in this file: -

          -
        • Cudd_bddApproxConjDecomp() -
        • Cudd_bddApproxDisjDecomp() -
        • Cudd_bddIterConjDecomp() -
        • Cudd_bddIterDisjDecomp() -
        • Cudd_bddGenConjDecomp() -
        • Cudd_bddGenDisjDecomp() -
        • Cudd_bddVarConjDecomp() -
        • Cudd_bddVarDisjDecomp() -
        - Static procedures included in this module: -
          -
        • cuddConjunctsAux() -
        • CreateBotDist() -
        • BuildConjuncts() -
        • ConjunctsFree() -
        ] - - Author [Kavita Ravi, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ -#define DEPTH 5 -#define THRESHOLD 10 -#define NONE 0 -#define PAIR_ST 1 -#define PAIR_CR 2 -#define G_ST 3 -#define G_CR 4 -#define H_ST 5 -#define H_CR 6 -#define BOTH_G 7 -#define BOTH_H 8 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ -typedef struct Conjuncts { - DdNode *g; - DdNode *h; -} Conjuncts; - -typedef struct NodeStat { - int distance; - int localRef; -} NodeStat; - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddDecomp.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -static DdNode *one, *zero; -long lastTimeG; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -#define FactorsNotStored(factors) ((int)((long)(factors) & 01)) - -#define FactorsComplement(factors) ((Conjuncts *)((long)(factors) | 01)) - -#define FactorsUncomplement(factors) ((Conjuncts *)((long)(factors) ^ 01)) - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static NodeStat * CreateBotDist ARGS((DdNode * node, st_table * distanceTable)); -static double CountMinterms ARGS((DdNode * node, double max, st_table * mintermTable, FILE *fp)); -static void ConjunctsFree ARGS((DdManager * dd, Conjuncts * factors)); -static int PairInTables ARGS((DdNode * g, DdNode * h, st_table * ghTable)); -static Conjuncts * CheckTablesCacheAndReturn ARGS((DdNode * node, DdNode * g, DdNode * h, st_table * ghTable, st_table * cacheTable)); -static Conjuncts * PickOnePair ARGS((DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st_table * ghTable, st_table * cacheTable)); -static Conjuncts * CheckInTables ARGS((DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st_table * ghTable, st_table * cacheTable, int * outOfMem)); -static Conjuncts * ZeroCase ARGS((DdManager * dd, DdNode * node, Conjuncts * factorsNv, st_table * ghTable, st_table * cacheTable, int switched)); -static Conjuncts * BuildConjuncts ARGS((DdManager * dd, DdNode * node, st_table * distanceTable, st_table * cacheTable, int approxDistance, int maxLocalRef, st_table * ghTable, st_table * mintermTable)); -static int cuddConjunctsAux ARGS((DdManager * dd, DdNode * f, DdNode ** c1, DdNode ** c2)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs two-way conjunctive decomposition of a BDD.] - - Description [Performs two-way conjunctive decomposition of a - BDD. This procedure owes its name to the use of supersetting to - obtain an initial factor of the given function. Returns the number - of conjuncts produced, that is, 2 if successful; 1 if no meaningful - decomposition was found; 0 otherwise. The conjuncts produced by this - procedure tend to be imbalanced.] - - SideEffects [The factors are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the conjuncts are already - referenced. If the function returns 0, the array for the conjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddApproxDisjDecomp Cudd_bddIterConjDecomp - Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox - Cudd_bddSqueeze Cudd_bddLICompaction] - -******************************************************************************/ -int -Cudd_bddApproxConjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** conjuncts /* address of the first factor */) -{ - DdNode *superset1, *superset2, *glocal, *hlocal; - int nvars = Cudd_SupportSize(dd,f); - - /* Find a tentative first factor by overapproximation and minimization. */ - superset1 = Cudd_RemapOverApprox(dd,f,nvars,0,1.0); - if (superset1 == NULL) return(0); - cuddRef(superset1); - superset2 = Cudd_bddSqueeze(dd,f,superset1); - if (superset2 == NULL) { - Cudd_RecursiveDeref(dd,superset1); - return(0); - } - cuddRef(superset2); - Cudd_RecursiveDeref(dd,superset1); - - /* Compute the second factor by minimization. */ - hlocal = Cudd_bddLICompaction(dd,f,superset2); - if (hlocal == NULL) { - Cudd_RecursiveDeref(dd,superset2); - return(0); - } - cuddRef(hlocal); - - /* Refine the first factor by minimization. If h turns out to be f, this - ** step guarantees that g will be 1. */ - glocal = Cudd_bddLICompaction(dd,superset2,hlocal); - if (glocal == NULL) { - Cudd_RecursiveDeref(dd,superset2); - Cudd_RecursiveDeref(dd,hlocal); - return(0); - } - cuddRef(glocal); - Cudd_RecursiveDeref(dd,superset2); - - if (glocal != DD_ONE(dd)) { - if (hlocal != DD_ONE(dd)) { - *conjuncts = ALLOC(DdNode *,2); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - (*conjuncts)[1] = hlocal; - return(2); - } else { - Cudd_RecursiveDeref(dd,hlocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - return(1); - } - } else { - Cudd_RecursiveDeref(dd,glocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = hlocal; - return(1); - } - -} /* end of Cudd_bddApproxConjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way disjunctive decomposition of a BDD.] - - Description [Performs two-way disjunctive decomposition of a BDD. - Returns the number of disjuncts produced, that is, 2 if successful; - 1 if no meaningful decomposition was found; 0 otherwise. The - disjuncts produced by this procedure tend to be imbalanced.] - - SideEffects [The two disjuncts are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the disjuncts are already - referenced. If the function returns 0, the array for the disjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddApproxConjDecomp Cudd_bddIterDisjDecomp - Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp] - -******************************************************************************/ -int -Cudd_bddApproxDisjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** disjuncts /* address of the array of the disjuncts */) -{ - int result, i; - - result = Cudd_bddApproxConjDecomp(dd,Cudd_Not(f),disjuncts); - for (i = 0; i < result; i++) { - (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); - } - return(result); - -} /* end of Cudd_bddApproxDisjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way conjunctive decomposition of a BDD.] - - Description [Performs two-way conjunctive decomposition of a - BDD. This procedure owes its name to the iterated use of - supersetting to obtain a factor of the given function. Returns the - number of conjuncts produced, that is, 2 if successful; 1 if no - meaningful decomposition was found; 0 otherwise. The conjuncts - produced by this procedure tend to be imbalanced.] - - SideEffects [The factors are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the conjuncts are already - referenced. If the function returns 0, the array for the conjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddIterDisjDecomp Cudd_bddApproxConjDecomp - Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox - Cudd_bddSqueeze Cudd_bddLICompaction] - -******************************************************************************/ -int -Cudd_bddIterConjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** conjuncts /* address of the array of conjuncts */) -{ - DdNode *superset1, *superset2, *old[2], *res[2]; - int sizeOld, sizeNew; - int nvars = Cudd_SupportSize(dd,f); - - old[0] = DD_ONE(dd); - cuddRef(old[0]); - old[1] = f; - cuddRef(old[1]); - sizeOld = Cudd_SharingSize(old,2); - - do { - /* Find a tentative first factor by overapproximation and - ** minimization. */ - superset1 = Cudd_RemapOverApprox(dd,old[1],nvars,0,1.0); - if (superset1 == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - return(0); - } - cuddRef(superset1); - superset2 = Cudd_bddSqueeze(dd,old[1],superset1); - if (superset2 == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - Cudd_RecursiveDeref(dd,superset1); - return(0); - } - cuddRef(superset2); - Cudd_RecursiveDeref(dd,superset1); - res[0] = Cudd_bddAnd(dd,old[0],superset2); - if (res[0] == NULL) { - Cudd_RecursiveDeref(dd,superset2); - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - return(0); - } - cuddRef(res[0]); - Cudd_RecursiveDeref(dd,superset2); - if (res[0] == old[0]) { - Cudd_RecursiveDeref(dd,res[0]); - break; /* avoid infinite loop */ - } - - /* Compute the second factor by minimization. */ - res[1] = Cudd_bddLICompaction(dd,old[1],res[0]); - if (res[1] == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - return(0); - } - cuddRef(res[1]); - - sizeNew = Cudd_SharingSize(res,2); - if (sizeNew <= sizeOld) { - Cudd_RecursiveDeref(dd,old[0]); - old[0] = res[0]; - Cudd_RecursiveDeref(dd,old[1]); - old[1] = res[1]; - sizeOld = sizeNew; - } else { - Cudd_RecursiveDeref(dd,res[0]); - Cudd_RecursiveDeref(dd,res[1]); - break; - } - - } while (1); - - /* Refine the first factor by minimization. If h turns out to - ** be f, this step guarantees that g will be 1. */ - superset1 = Cudd_bddLICompaction(dd,old[0],old[1]); - if (superset1 == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - return(0); - } - cuddRef(superset1); - Cudd_RecursiveDeref(dd,old[0]); - old[0] = superset1; - - if (old[0] != DD_ONE(dd)) { - if (old[1] != DD_ONE(dd)) { - *conjuncts = ALLOC(DdNode *,2); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - Cudd_RecursiveDeref(dd,old[1]); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = old[0]; - (*conjuncts)[1] = old[1]; - return(2); - } else { - Cudd_RecursiveDeref(dd,old[1]); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,old[0]); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = old[0]; - return(1); - } - } else { - Cudd_RecursiveDeref(dd,old[0]); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,old[1]); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = old[1]; - return(1); - } - -} /* end of Cudd_bddIterConjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way disjunctive decomposition of a BDD.] - - Description [Performs two-way disjunctive decomposition of a BDD. - Returns the number of disjuncts produced, that is, 2 if successful; - 1 if no meaningful decomposition was found; 0 otherwise. The - disjuncts produced by this procedure tend to be imbalanced.] - - SideEffects [The two disjuncts are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the disjuncts are already - referenced. If the function returns 0, the array for the disjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddIterConjDecomp Cudd_bddApproxDisjDecomp - Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp] - -******************************************************************************/ -int -Cudd_bddIterDisjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** disjuncts /* address of the array of the disjuncts */) -{ - int result, i; - - result = Cudd_bddIterConjDecomp(dd,Cudd_Not(f),disjuncts); - for (i = 0; i < result; i++) { - (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); - } - return(result); - -} /* end of Cudd_bddIterDisjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way conjunctive decomposition of a BDD.] - - Description [Performs two-way conjunctive decomposition of a - BDD. This procedure owes its name to the fact tht it generalizes the - decomposition based on the cofactors with respect to one - variable. Returns the number of conjuncts produced, that is, 2 if - successful; 1 if no meaningful decomposition was found; 0 - otherwise. The conjuncts produced by this procedure tend to be - balanced.] - - SideEffects [The two factors are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the conjuncts are already - referenced. If the function returns 0, the array for the conjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddGenDisjDecomp Cudd_bddApproxConjDecomp - Cudd_bddIterConjDecomp Cudd_bddVarConjDecomp] - -******************************************************************************/ -int -Cudd_bddGenConjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** conjuncts /* address of the array of conjuncts */) -{ - int result; - DdNode *glocal, *hlocal; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - do { - dd->reordered = 0; - result = cuddConjunctsAux(dd, f, &glocal, &hlocal); - } while (dd->reordered == 1); - - if (result == 0) { - return(0); - } - - if (glocal != one) { - if (hlocal != one) { - *conjuncts = ALLOC(DdNode *,2); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - (*conjuncts)[1] = hlocal; - return(2); - } else { - Cudd_RecursiveDeref(dd,hlocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - return(1); - } - } else { - Cudd_RecursiveDeref(dd,glocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = hlocal; - return(1); - } - -} /* end of Cudd_bddGenConjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way disjunctive decomposition of a BDD.] - - Description [Performs two-way disjunctive decomposition of a BDD. - Returns the number of disjuncts produced, that is, 2 if successful; - 1 if no meaningful decomposition was found; 0 otherwise. The - disjuncts produced by this procedure tend to be balanced.] - - SideEffects [The two disjuncts are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the disjuncts are already - referenced. If the function returns 0, the array for the disjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddGenConjDecomp Cudd_bddApproxDisjDecomp - Cudd_bddIterDisjDecomp Cudd_bddVarDisjDecomp] - -******************************************************************************/ -int -Cudd_bddGenDisjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** disjuncts /* address of the array of the disjuncts */) -{ - int result, i; - - result = Cudd_bddGenConjDecomp(dd,Cudd_Not(f),disjuncts); - for (i = 0; i < result; i++) { - (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); - } - return(result); - -} /* end of Cudd_bddGenDisjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way conjunctive decomposition of a BDD.] - - Description [Conjunctively decomposes one BDD according to a - variable. If f is the function of the BDD and - x is the variable, the decomposition is - (f+x)(f+x'). The variable is chosen so as to balance - the sizes of the two conjuncts and to keep them small. Returns the - number of conjuncts produced, that is, 2 if successful; 1 if no - meaningful decomposition was found; 0 otherwise.] - - SideEffects [The two factors are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the conjuncts are already - referenced. If the function returns 0, the array for the conjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddVarDisjDecomp Cudd_bddGenConjDecomp - Cudd_bddApproxConjDecomp Cudd_bddIterConjDecomp] - -*****************************************************************************/ -int -Cudd_bddVarConjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** conjuncts /* address of the array of conjuncts */) -{ - int best; - int min; - DdNode *support, *scan, *var, *glocal, *hlocal; - - /* Find best cofactoring variable. */ - support = Cudd_Support(dd,f); - if (support == NULL) return(0); - if (Cudd_IsConstant(support)) { - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = f; - cuddRef((*conjuncts)[0]); - return(1); - } - cuddRef(support); - min = 1000000000; - best = -1; - scan = support; - while (!Cudd_IsConstant(scan)) { - int i = scan->index; - int est1 = Cudd_EstimateCofactor(dd,f,i,1); - int est0 = Cudd_EstimateCofactor(dd,f,i,0); - /* Minimize the size of the larger of the two cofactors. */ - int est = (est1 > est0) ? est1 : est0; - if (est < min) { - min = est; - best = i; - } - scan = cuddT(scan); - } -#ifdef DD_DEBUG - assert(best >= 0 && best < dd->size); -#endif - Cudd_RecursiveDeref(dd,support); - - var = Cudd_bddIthVar(dd,best); - glocal = Cudd_bddOr(dd,f,var); - if (glocal == NULL) { - return(0); - } - cuddRef(glocal); - hlocal = Cudd_bddOr(dd,f,Cudd_Not(var)); - if (hlocal == NULL) { - Cudd_RecursiveDeref(dd,glocal); - return(0); - } - cuddRef(hlocal); - - if (glocal != DD_ONE(dd)) { - if (hlocal != DD_ONE(dd)) { - *conjuncts = ALLOC(DdNode *,2); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - (*conjuncts)[1] = hlocal; - return(2); - } else { - Cudd_RecursiveDeref(dd,hlocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,glocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = glocal; - return(1); - } - } else { - Cudd_RecursiveDeref(dd,glocal); - *conjuncts = ALLOC(DdNode *,1); - if (*conjuncts == NULL) { - Cudd_RecursiveDeref(dd,hlocal); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - (*conjuncts)[0] = hlocal; - return(1); - } - -} /* end of Cudd_bddVarConjDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs two-way disjunctive decomposition of a BDD.] - - Description [Performs two-way disjunctive decomposition of a BDD - according to a variable. If f is the function of the - BDD and x is the variable, the decomposition is - f*x + f*x'. The variable is chosen so as to balance - the sizes of the two disjuncts and to keep them small. Returns the - number of disjuncts produced, that is, 2 if successful; 1 if no - meaningful decomposition was found; 0 otherwise.] - - SideEffects [The two disjuncts are returned in an array as side effects. - The array is allocated by this function. It is the caller's responsibility - to free it. On successful completion, the disjuncts are already - referenced. If the function returns 0, the array for the disjuncts is - not allocated. If the function returns 1, the only factor equals the - function to be decomposed.] - - SeeAlso [Cudd_bddVarConjDecomp Cudd_bddApproxDisjDecomp - Cudd_bddIterDisjDecomp Cudd_bddGenDisjDecomp] - -******************************************************************************/ -int -Cudd_bddVarDisjDecomp( - DdManager * dd /* manager */, - DdNode * f /* function to be decomposed */, - DdNode *** disjuncts /* address of the array of the disjuncts */) -{ - int result, i; - - result = Cudd_bddVarConjDecomp(dd,Cudd_Not(f),disjuncts); - for (i = 0; i < result; i++) { - (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]); - } - return(result); - -} /* end of Cudd_bddVarDisjDecomp */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Get longest distance of node from constant.] - - Description [Get longest distance of node from constant. Returns the - distance of the root from the constant if successful; CUDD_OUT_OF_MEM - otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static NodeStat * -CreateBotDist( - DdNode * node, - st_table * distanceTable) -{ - DdNode *N, *Nv, *Nnv; - int distance, distanceNv, distanceNnv; - NodeStat *nodeStat, *nodeStatNv, *nodeStatNnv; - -#if 0 - if (Cudd_IsConstant(node)) { - return(0); - } -#endif - - /* Return the entry in the table if found. */ - N = Cudd_Regular(node); - if (st_lookup(distanceTable, (char *)N, (char **)&nodeStat)) { - nodeStat->localRef++; - return(nodeStat); - } - - Nv = cuddT(N); - Nnv = cuddE(N); - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - /* Recur on the children. */ - nodeStatNv = CreateBotDist(Nv, distanceTable); - if (nodeStatNv == NULL) return(NULL); - distanceNv = nodeStatNv->distance; - - nodeStatNnv = CreateBotDist(Nnv, distanceTable); - if (nodeStatNnv == NULL) return(NULL); - distanceNnv = nodeStatNnv->distance; - /* Store max distance from constant; note sometimes this distance - ** may be to 0. - */ - distance = (distanceNv > distanceNnv) ? (distanceNv+1) : (distanceNnv + 1); - - nodeStat = ALLOC(NodeStat, 1); - if (nodeStat == NULL) { - return(0); - } - nodeStat->distance = distance; - nodeStat->localRef = 1; - - if (st_insert(distanceTable, (char *)N, (char *)nodeStat) == - ST_OUT_OF_MEM) { - return(0); - - } - return(nodeStat); - -} /* end of CreateBotDist */ - - -/**Function******************************************************************** - - Synopsis [Count the number of minterms of each node ina a BDD and - store it in a hash table.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static double -CountMinterms( - DdNode * node, - double max, - st_table * mintermTable, - FILE *fp) -{ - DdNode *N, *Nv, *Nnv; - double min, minNv, minNnv; - double *dummy; - - N = Cudd_Regular(node); - - if (cuddIsConstant(N)) { - if (node == zero) { - return(0); - } else { - return(max); - } - } - - /* Return the entry in the table if found. */ - if (st_lookup(mintermTable, (char *)node, (char **)&dummy)) { - min = *dummy; - return(min); - } - - Nv = cuddT(N); - Nnv = cuddE(N); - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - /* Recur on the children. */ - minNv = CountMinterms(Nv, max, mintermTable, fp); - if (minNv == -1.0) return(-1.0); - minNnv = CountMinterms(Nnv, max, mintermTable, fp); - if (minNnv == -1.0) return(-1.0); - min = minNv / 2.0 + minNnv / 2.0; - /* store - */ - - dummy = ALLOC(double, 1); - if (dummy == NULL) return(-1.0); - *dummy = min; - if (st_insert(mintermTable, (char *)node, (char *)dummy) == ST_OUT_OF_MEM) { - (void) fprintf(fp, "st table insert failed\n"); - } - return(min); - -} /* end of CountMinterms */ - - -/**Function******************************************************************** - - Synopsis [Free factors structure] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -ConjunctsFree( - DdManager * dd, - Conjuncts * factors) -{ - Cudd_RecursiveDeref(dd, factors->g); - Cudd_RecursiveDeref(dd, factors->h); - FREE(factors); - return; - -} /* end of ConjunctsFree */ - - -/**Function******************************************************************** - - Synopsis [Check whether the given pair is in the tables.] - - Description [.Check whether the given pair is in the tables. gTable - and hTable are combined. - absence in both is indicated by 0, - presence in gTable is indicated by 1, - presence in hTable by 2 and - presence in both by 3. - The values returned by this function are PAIR_ST, - PAIR_CR, G_ST, G_CR, H_ST, H_CR, BOTH_G, BOTH_H, NONE. - PAIR_ST implies g in gTable and h in hTable - PAIR_CR implies g in hTable and h in gTable - G_ST implies g in gTable and h not in any table - G_CR implies g in hTable and h not in any table - H_ST implies h in hTable and g not in any table - H_CR implies h in gTable and g not in any table - BOTH_G implies both in gTable - BOTH_H implies both in hTable - NONE implies none in table; ] - - SideEffects [] - - SeeAlso [CheckTablesCacheAndReturn CheckInTables] - -******************************************************************************/ -static int -PairInTables( - DdNode * g, - DdNode * h, - st_table * ghTable) -{ - int valueG, valueH, gPresent, hPresent; - - valueG = valueH = gPresent = hPresent = 0; - - gPresent = st_lookup_int(ghTable, (char *)Cudd_Regular(g), &valueG); - hPresent = st_lookup_int(ghTable, (char *)Cudd_Regular(h), &valueH); - - if (!gPresent && !hPresent) return(NONE); - - if (!hPresent) { - if (valueG & 1) return(G_ST); - if (valueG & 2) return(G_CR); - } - if (!gPresent) { - if (valueH & 1) return(H_CR); - if (valueH & 2) return(H_ST); - } - /* both in tables */ - if ((valueG & 1) && (valueH & 2)) return(PAIR_ST); - if ((valueG & 2) && (valueH & 1)) return(PAIR_CR); - - if (valueG & 1) { - return(BOTH_G); - } else { - return(BOTH_H); - } - -} /* end of PairInTables */ - - -/**Function******************************************************************** - - Synopsis [Check the tables for the existence of pair and return one - combination, cache the result.] - - Description [Check the tables for the existence of pair and return - one combination, cache the result. The assumption is that one of the - conjuncts is already in the tables.] - - SideEffects [g and h referenced for the cache] - - SeeAlso [ZeroCase] - -******************************************************************************/ -static Conjuncts * -CheckTablesCacheAndReturn( - DdNode * node, - DdNode * g, - DdNode * h, - st_table * ghTable, - st_table * cacheTable) -{ - int pairValue; - int value; - Conjuncts *factors; - - value = 0; - /* check tables */ - pairValue = PairInTables(g, h, ghTable); - assert(pairValue != NONE); - /* if both dont exist in table, we know one exists(either g or h). - * Therefore store the other and proceed - */ - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) return(NULL); - if ((pairValue == BOTH_H) || (pairValue == H_ST)) { - if (g != one) { - value = 0; - if (st_lookup_int(ghTable, (char *)Cudd_Regular(g), &value)) { - value |= 1; - } else { - value = 1; - } - if (st_insert(ghTable, (char *)Cudd_Regular(g), - (char *)(long)value) == ST_OUT_OF_MEM) { - return(NULL); - } - } - factors->g = g; - factors->h = h; - } else if ((pairValue == BOTH_G) || (pairValue == G_ST)) { - if (h != one) { - value = 0; - if (st_lookup_int(ghTable, (char *)Cudd_Regular(h), &value)) { - value |= 2; - } else { - value = 2; - } - if (st_insert(ghTable, (char *)Cudd_Regular(h), - (char *)(long)value) == ST_OUT_OF_MEM) { - return(NULL); - } - } - factors->g = g; - factors->h = h; - } else if (pairValue == H_CR) { - if (g != one) { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(g), - (char *)(long)value) == ST_OUT_OF_MEM) { - return(NULL); - } - } - factors->g = h; - factors->h = g; - } else if (pairValue == G_CR) { - if (h != one) { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(h), - (char *)(long)value) == ST_OUT_OF_MEM) { - return(NULL); - } - } - factors->g = h; - factors->h = g; - } else if (pairValue == PAIR_CR) { - /* pair exists in table */ - factors->g = h; - factors->h = g; - } else if (pairValue == PAIR_ST) { - factors->g = g; - factors->h = h; - } - - /* cache the result for this node */ - if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - - return(factors); - -} /* end of CheckTablesCacheAndReturn */ - -/**Function******************************************************************** - - Synopsis [Check the tables for the existence of pair and return one - combination, store in cache.] - - Description [Check the tables for the existence of pair and return - one combination, store in cache. The pair that has more pointers to - it is picked. An approximation of the number of local pointers is - made by taking the reference count of the pairs sent. ] - - SideEffects [] - - SeeAlso [ZeroCase BuildConjuncts] - -******************************************************************************/ -static Conjuncts * -PickOnePair( - DdNode * node, - DdNode * g1, - DdNode * h1, - DdNode * g2, - DdNode * h2, - st_table * ghTable, - st_table * cacheTable) -{ - int value; - Conjuncts *factors; - int oneRef, twoRef; - - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) return(NULL); - - /* count the number of pointers to pair 2 */ - if (h2 == one) { - twoRef = (Cudd_Regular(g2))->ref; - } else if (g2 == one) { - twoRef = (Cudd_Regular(h2))->ref; - } else { - twoRef = ((Cudd_Regular(g2))->ref + (Cudd_Regular(h2))->ref)/2; - } - - /* count the number of pointers to pair 1 */ - if (h1 == one) { - oneRef = (Cudd_Regular(g1))->ref; - } else if (g1 == one) { - oneRef = (Cudd_Regular(h1))->ref; - } else { - oneRef = ((Cudd_Regular(g1))->ref + (Cudd_Regular(h1))->ref)/2; - } - - /* pick the pair with higher reference count */ - if (oneRef >= twoRef) { - factors->g = g1; - factors->h = h1; - } else { - factors->g = g2; - factors->h = h2; - } - - /* - * Store computed factors in respective tables to encourage - * recombination. - */ - if (factors->g != one) { - /* insert g in htable */ - value = 0; - if (st_lookup_int(ghTable, (char *)Cudd_Regular(factors->g), &value)) { - if (value == 2) { - value |= 1; - if (st_insert(ghTable, (char *)Cudd_Regular(factors->g), - (char *)(long)value) == ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - } - } else { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(factors->g), - (char *)(long)value) == ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - } - } - - if (factors->h != one) { - /* insert h in htable */ - value = 0; - if (st_lookup_int(ghTable, (char *)Cudd_Regular(factors->h), &value)) { - if (value == 1) { - value |= 2; - if (st_insert(ghTable, (char *)Cudd_Regular(factors->h), - (char *)(long)value) == ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - } - } else { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(factors->h), - (char *)(long)value) == ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - } - } - - /* Store factors in cache table for later use. */ - if (st_insert(cacheTable, (char *)node, (char *)factors) == - ST_OUT_OF_MEM) { - FREE(factors); - return(NULL); - } - - return(factors); - -} /* end of PickOnePair */ - - -/**Function******************************************************************** - - Synopsis [Check if the two pairs exist in the table, If any of the - conjuncts do exist, store in the cache and return the corresponding pair.] - - Description [Check if the two pairs exist in the table. If any of - the conjuncts do exist, store in the cache and return the - corresponding pair.] - - SideEffects [] - - SeeAlso [ZeroCase BuildConjuncts] - -******************************************************************************/ -static Conjuncts * -CheckInTables( - DdNode * node, - DdNode * g1, - DdNode * h1, - DdNode * g2, - DdNode * h2, - st_table * ghTable, - st_table * cacheTable, - int * outOfMem) -{ - int pairValue1, pairValue2; - Conjuncts *factors; - int value; - - *outOfMem = 0; - - /* check existence of pair in table */ - pairValue1 = PairInTables(g1, h1, ghTable); - pairValue2 = PairInTables(g2, h2, ghTable); - - /* if none of the 4 exist in the gh tables, return NULL */ - if ((pairValue1 == NONE) && (pairValue2 == NONE)) { - return NULL; - } - - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) { - *outOfMem = 1; - return NULL; - } - - /* pairs that already exist in the table get preference. */ - if (pairValue1 == PAIR_ST) { - factors->g = g1; - factors->h = h1; - } else if (pairValue2 == PAIR_ST) { - factors->g = g2; - factors->h = h2; - } else if (pairValue1 == PAIR_CR) { - factors->g = h1; - factors->h = g1; - } else if (pairValue2 == PAIR_CR) { - factors->g = h2; - factors->h = g2; - } else if (pairValue1 == G_ST) { - /* g exists in the table, h is not found in either table */ - factors->g = g1; - factors->h = h1; - if (h1 != one) { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(h1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue1 == BOTH_G) { - /* g and h are found in the g table */ - factors->g = g1; - factors->h = h1; - if (h1 != one) { - value = 3; - if (st_insert(ghTable, (char *)Cudd_Regular(h1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue1 == H_ST) { - /* h exists in the table, g is not found in either table */ - factors->g = g1; - factors->h = h1; - if (g1 != one) { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(g1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue1 == BOTH_H) { - /* g and h are found in the h table */ - factors->g = g1; - factors->h = h1; - if (g1 != one) { - value = 3; - if (st_insert(ghTable, (char *)Cudd_Regular(g1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == G_ST) { - /* g exists in the table, h is not found in either table */ - factors->g = g2; - factors->h = h2; - if (h2 != one) { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(h2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == BOTH_G) { - /* g and h are found in the g table */ - factors->g = g2; - factors->h = h2; - if (h2 != one) { - value = 3; - if (st_insert(ghTable, (char *)Cudd_Regular(h2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == H_ST) { - /* h exists in the table, g is not found in either table */ - factors->g = g2; - factors->h = h2; - if (g2 != one) { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(g2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == BOTH_H) { - /* g and h are found in the h table */ - factors->g = g2; - factors->h = h2; - if (g2 != one) { - value = 3; - if (st_insert(ghTable, (char *)Cudd_Regular(g2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue1 == G_CR) { - /* g found in h table and h in none */ - factors->g = h1; - factors->h = g1; - if (h1 != one) { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(h1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue1 == H_CR) { - /* h found in g table and g in none */ - factors->g = h1; - factors->h = g1; - if (g1 != one) { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(g1), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == G_CR) { - /* g found in h table and h in none */ - factors->g = h2; - factors->h = g2; - if (h2 != one) { - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(h2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } else if (pairValue2 == H_CR) { - /* h found in g table and g in none */ - factors->g = h2; - factors->h = g2; - if (g2 != one) { - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(g2), - (char *)(long)value) == ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - } - } - - /* Store factors in cache table for later use. */ - if (st_insert(cacheTable, (char *)node, (char *)factors) == - ST_OUT_OF_MEM) { - *outOfMem = 1; - FREE(factors); - return(NULL); - } - return factors; -} /* end of CheckInTables */ - - - -/**Function******************************************************************** - - Synopsis [If one child is zero, do explicitly what Restrict does or better] - - Description [If one child is zero, do explicitly what Restrict does or better. - First separate a variable and its child in the base case. In case of a cube - times a function, separate the cube and function. As a last resort, look in - tables.] - - SideEffects [Frees the BDDs in factorsNv. factorsNv itself is not freed - because it is freed above.] - - SeeAlso [BuildConjuncts] - -******************************************************************************/ -static Conjuncts * -ZeroCase( - DdManager * dd, - DdNode * node, - Conjuncts * factorsNv, - st_table * ghTable, - st_table * cacheTable, - int switched) -{ - int topid; - DdNode *g, *h, *g1, *g2, *h1, *h2, *x, *N, *G, *H, *Gv, *Gnv; - DdNode *Hv, *Hnv; - int value; - int outOfMem; - Conjuncts *factors; - - /* get var at this node */ - N = Cudd_Regular(node); - topid = N->index; - x = dd->vars[topid]; - x = (switched) ? Cudd_Not(x): x; - cuddRef(x); - - /* Seprate variable and child */ - if (factorsNv->g == one) { - Cudd_RecursiveDeref(dd, factorsNv->g); - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, x); - return(NULL); - } - factors->g = x; - factors->h = factorsNv->h; - /* cache the result*/ - if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, x); - FREE(factors); - return NULL; - } - - /* store x in g table, the other node is already in the table */ - if (st_lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) { - value |= 1; - } else { - value = 1; - } - if (st_insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - return NULL; - } - return(factors); - } - - /* Seprate variable and child */ - if (factorsNv->h == one) { - Cudd_RecursiveDeref(dd, factorsNv->h); - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, x); - return(NULL); - } - factors->g = factorsNv->g; - factors->h = x; - /* cache the result. */ - if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, x); - FREE(factors); - return(NULL); - } - /* store x in h table, the other node is already in the table */ - if (st_lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) { - value |= 2; - } else { - value = 2; - } - if (st_insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - return NULL; - } - return(factors); - } - - G = Cudd_Regular(factorsNv->g); - Gv = cuddT(G); - Gnv = cuddE(G); - Gv = Cudd_NotCond(Gv, Cudd_IsComplement(node)); - Gnv = Cudd_NotCond(Gnv, Cudd_IsComplement(node)); - /* if the child below is a variable */ - if ((Gv == zero) || (Gnv == zero)) { - h = factorsNv->h; - g = cuddBddAndRecur(dd, x, factorsNv->g); - if (g != NULL) cuddRef(g); - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, x); - if (g == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->h); - return NULL; - } - /* CheckTablesCacheAndReturn responsible for allocating - * factors structure., g,h referenced for cache store the - */ - factors = CheckTablesCacheAndReturn(node, - g, - h, - ghTable, - cacheTable); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g); - Cudd_RecursiveDeref(dd, h); - } - return(factors); - } - - H = Cudd_Regular(factorsNv->h); - Hv = cuddT(H); - Hnv = cuddE(H); - Hv = Cudd_NotCond(Hv, Cudd_IsComplement(node)); - Hnv = Cudd_NotCond(Hnv, Cudd_IsComplement(node)); - /* if the child below is a variable */ - if ((Hv == zero) || (Hnv == zero)) { - g = factorsNv->g; - h = cuddBddAndRecur(dd, x, factorsNv->h); - if (h!= NULL) cuddRef(h); - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, x); - if (h == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - return NULL; - } - /* CheckTablesCacheAndReturn responsible for allocating - * factors structure.g,h referenced for table store - */ - factors = CheckTablesCacheAndReturn(node, - g, - h, - ghTable, - cacheTable); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g); - Cudd_RecursiveDeref(dd, h); - } - return(factors); - } - - /* build g1 = x*g; h1 = h */ - /* build g2 = g; h2 = x*h */ - Cudd_RecursiveDeref(dd, x); - h1 = factorsNv->h; - g1 = cuddBddAndRecur(dd, x, factorsNv->g); - if (g1 != NULL) cuddRef(g1); - if (g1 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNv->h); - return NULL; - } - - g2 = factorsNv->g; - h2 = cuddBddAndRecur(dd, x, factorsNv->h); - if (h2 != NULL) cuddRef(h2); - if (h2 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNv->g); - return NULL; - } - - /* check whether any pair is in tables */ - factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem); - if (outOfMem) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - return NULL; - } - if (factors != NULL) { - if ((factors->g == g1) || (factors->g == h1)) { - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - } - return factors; - } - - /* check for each pair in tables and choose one */ - factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - /* now free what was created and not used */ - if ((factors->g == g1) || (factors->g == h1)) { - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - } - } - - return(factors); -} /* end of ZeroCase */ - - -/**Function******************************************************************** - - Synopsis [Builds the conjuncts recursively, bottom up.] - - Description [Builds the conjuncts recursively, bottom up. Constants - are returned as (f, f). The cache is checked for previously computed - result. The decomposition points are determined by the local - reference count of this node and the longest distance from the - constant. At the decomposition point, the factors returned are (f, - 1). Recur on the two children. The order is determined by the - heavier branch. Combine the factors of the two children and pick the - one that already occurs in the gh table. Occurence in g is indicated - by value 1, occurence in h by 2, occurence in both 3.] - - SideEffects [] - - SeeAlso [cuddConjunctsAux] - -******************************************************************************/ -static Conjuncts * -BuildConjuncts( - DdManager * dd, - DdNode * node, - st_table * distanceTable, - st_table * cacheTable, - int approxDistance, - int maxLocalRef, - st_table * ghTable, - st_table * mintermTable) -{ - int topid, distance; - Conjuncts *factorsNv, *factorsNnv, *factors; - Conjuncts *dummy; - DdNode *N, *Nv, *Nnv, *temp, *g1, *g2, *h1, *h2, *topv; - double minNv = 0.0, minNnv = 0.0; - double *doubleDummy; - int switched =0; - int outOfMem; - int freeNv = 0, freeNnv = 0, freeTemp; - NodeStat *nodeStat; - int value; - - /* if f is constant, return (f,f) */ - if (Cudd_IsConstant(node)) { - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - factors->g = node; - factors->h = node; - return(FactorsComplement(factors)); - } - - /* If result (a pair of conjuncts) in cache, return the factors. */ - if (st_lookup(cacheTable, (char *)node, (char **)&dummy)) { - factors = dummy; - return(factors); - } - - /* check distance and local reference count of this node */ - N = Cudd_Regular(node); - if (!st_lookup(distanceTable, (char *)N, (char **)&nodeStat)) { - (void) fprintf(dd->err, "Not in table, Something wrong\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - distance = nodeStat->distance; - - /* at or below decomposition point, return (f, 1) */ - if (((nodeStat->localRef > maxLocalRef*2/3) && - (distance < approxDistance*2/3)) || - (distance <= approxDistance/4)) { - factors = ALLOC(Conjuncts, 1); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - /* alternate assigning (f,1) */ - value = 0; - if (st_lookup_int(ghTable, (char *)Cudd_Regular(node), &value)) { - if (value == 3) { - if (!lastTimeG) { - factors->g = node; - factors->h = one; - lastTimeG = 1; - } else { - factors->g = one; - factors->h = node; - lastTimeG = 0; - } - } else if (value == 1) { - factors->g = node; - factors->h = one; - } else { - factors->g = one; - factors->h = node; - } - } else if (!lastTimeG) { - factors->g = node; - factors->h = one; - lastTimeG = 1; - value = 1; - if (st_insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(factors); - return NULL; - } - } else { - factors->g = one; - factors->h = node; - lastTimeG = 0; - value = 2; - if (st_insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == ST_OUT_OF_MEM) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(factors); - return NULL; - } - } - return(FactorsComplement(factors)); - } - - /* get the children and recur */ - Nv = cuddT(N); - Nnv = cuddE(N); - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - /* Choose which subproblem to solve first based on the number of - * minterms. We go first where there are more minterms. - */ - if (!Cudd_IsConstant(Nv)) { - if (!st_lookup(mintermTable, (char *)Nv, (char **)&doubleDummy)) { - (void) fprintf(dd->err, "Not in table: Something wrong\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - minNv = *doubleDummy; - } - - if (!Cudd_IsConstant(Nnv)) { - if (!st_lookup(mintermTable, (char *)Nnv, (char **)&doubleDummy)) { - (void) fprintf(dd->err, "Not in table: Something wrong\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - minNnv = *doubleDummy; - } - - if (minNv < minNnv) { - temp = Nv; - Nv = Nnv; - Nnv = temp; - switched = 1; - } - - /* build gt, ht recursively */ - if (Nv != zero) { - factorsNv = BuildConjuncts(dd, Nv, distanceTable, - cacheTable, approxDistance, maxLocalRef, - ghTable, mintermTable); - if (factorsNv == NULL) return(NULL); - freeNv = FactorsNotStored(factorsNv); - factorsNv = (freeNv) ? FactorsUncomplement(factorsNv) : factorsNv; - cuddRef(factorsNv->g); - cuddRef(factorsNv->h); - - /* Deal with the zero case */ - if (Nnv == zero) { - /* is responsible for freeing factorsNv */ - factors = ZeroCase(dd, node, factorsNv, ghTable, - cacheTable, switched); - if (freeNv) FREE(factorsNv); - return(factors); - } - } - - /* build ge, he recursively */ - if (Nnv != zero) { - factorsNnv = BuildConjuncts(dd, Nnv, distanceTable, - cacheTable, approxDistance, maxLocalRef, - ghTable, mintermTable); - if (factorsNnv == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNv->h); - if (freeNv) FREE(factorsNv); - return(NULL); - } - freeNnv = FactorsNotStored(factorsNnv); - factorsNnv = (freeNnv) ? FactorsUncomplement(factorsNnv) : factorsNnv; - cuddRef(factorsNnv->g); - cuddRef(factorsNnv->h); - - /* Deal with the zero case */ - if (Nv == zero) { - /* is responsible for freeing factorsNv */ - factors = ZeroCase(dd, node, factorsNnv, ghTable, - cacheTable, switched); - if (freeNnv) FREE(factorsNnv); - return(factors); - } - } - - /* construct the 2 pairs */ - /* g1 = x*gt + x'*ge; h1 = x*ht + x'*he; */ - /* g2 = x*gt + x'*he; h2 = x*ht + x'*ge */ - if (switched) { - factors = factorsNnv; - factorsNnv = factorsNv; - factorsNv = factors; - freeTemp = freeNv; - freeNv = freeNnv; - freeNnv = freeTemp; - } - - /* Build the factors for this node. */ - topid = N->index; - topv = dd->vars[topid]; - - g1 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->g); - if (g1 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNnv->g); - Cudd_RecursiveDeref(dd, factorsNnv->h); - if (freeNv) FREE(factorsNv); - if (freeNnv) FREE(factorsNnv); - return(NULL); - } - - cuddRef(g1); - - h1 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->h); - if (h1 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNnv->g); - Cudd_RecursiveDeref(dd, factorsNnv->h); - Cudd_RecursiveDeref(dd, g1); - if (freeNv) FREE(factorsNv); - if (freeNnv) FREE(factorsNnv); - return(NULL); - } - - cuddRef(h1); - - g2 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->h); - if (g2 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNnv->g); - Cudd_RecursiveDeref(dd, factorsNnv->h); - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - if (freeNv) FREE(factorsNv); - if (freeNnv) FREE(factorsNnv); - return(NULL); - } - cuddRef(g2); - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNnv->h); - - h2 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->g); - if (h2 == NULL) { - Cudd_RecursiveDeref(dd, factorsNv->g); - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNnv->g); - Cudd_RecursiveDeref(dd, factorsNnv->h); - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - Cudd_RecursiveDeref(dd, g2); - if (freeNv) FREE(factorsNv); - if (freeNnv) FREE(factorsNnv); - return(NULL); - } - cuddRef(h2); - Cudd_RecursiveDeref(dd, factorsNv->h); - Cudd_RecursiveDeref(dd, factorsNnv->g); - if (freeNv) FREE(factorsNv); - if (freeNnv) FREE(factorsNnv); - - /* check for each pair in tables and choose one */ - factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem); - if (outOfMem) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - return(NULL); - } - if (factors != NULL) { - if ((factors->g == g1) || (factors->g == h1)) { - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - } - return(factors); - } - - /* if not in tables, pick one pair */ - factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable); - if (factors == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - /* now free what was created and not used */ - if ((factors->g == g1) || (factors->g == h1)) { - Cudd_RecursiveDeref(dd, g2); - Cudd_RecursiveDeref(dd, h2); - } else { - Cudd_RecursiveDeref(dd, g1); - Cudd_RecursiveDeref(dd, h1); - } - } - - return(factors); - -} /* end of BuildConjuncts */ - - -/**Function******************************************************************** - - Synopsis [Procedure to compute two conjunctive factors of f and place in *c1 and *c2.] - - Description [Procedure to compute two conjunctive factors of f and - place in *c1 and *c2. Sets up the required data - table of distances - from the constant and local reference count. Also minterm table. ] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -static int -cuddConjunctsAux( - DdManager * dd, - DdNode * f, - DdNode ** c1, - DdNode ** c2) -{ - st_table *distanceTable = NULL; - st_table *cacheTable = NULL; - st_table *mintermTable = NULL; - st_table *ghTable = NULL; - st_generator *stGen; - char *key, *value; - Conjuncts *factors; - int distance, approxDistance; - double max, minterms; - int freeFactors; - NodeStat *nodeStat; - int maxLocalRef; - - /* initialize */ - *c1 = NULL; - *c2 = NULL; - - /* initialize distances table */ - distanceTable = st_init_table(st_ptrcmp,st_ptrhash); - if (distanceTable == NULL) goto outOfMem; - - /* make the entry for the constant */ - nodeStat = ALLOC(NodeStat, 1); - if (nodeStat == NULL) goto outOfMem; - nodeStat->distance = 0; - nodeStat->localRef = 1; - if (st_insert(distanceTable, (char *)one, (char *)nodeStat) == ST_OUT_OF_MEM) { - goto outOfMem; - } - - /* Count node distances from constant. */ - nodeStat = CreateBotDist(f, distanceTable); - if (nodeStat == NULL) goto outOfMem; - - /* set the distance for the decomposition points */ - approxDistance = (DEPTH < nodeStat->distance) ? nodeStat->distance : DEPTH; - distance = nodeStat->distance; - - if (distance < approxDistance) { - /* Too small to bother. */ - *c1 = f; - *c2 = DD_ONE(dd); - cuddRef(*c1); cuddRef(*c2); - stGen = st_init_gen(distanceTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - FREE(value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(distanceTable); - return(1); - } - - /* record the maximum local reference count */ - maxLocalRef = 0; - stGen = st_init_gen(distanceTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - nodeStat = (NodeStat *)value; - maxLocalRef = (nodeStat->localRef > maxLocalRef) ? - nodeStat->localRef : maxLocalRef; - } - st_free_gen(stGen); stGen = NULL; - - - /* Count minterms for each node. */ - max = pow(2.0, (double)Cudd_SupportSize(dd,f)); /* potential overflow */ - mintermTable = st_init_table(st_ptrcmp,st_ptrhash); - if (mintermTable == NULL) goto outOfMem; - minterms = CountMinterms(f, max, mintermTable, dd->err); - if (minterms == -1.0) goto outOfMem; - - lastTimeG = Cudd_Random() & 1; - cacheTable = st_init_table(st_ptrcmp, st_ptrhash); - if (cacheTable == NULL) goto outOfMem; - ghTable = st_init_table(st_ptrcmp, st_ptrhash); - if (ghTable == NULL) goto outOfMem; - - /* Build conjuncts. */ - factors = BuildConjuncts(dd, f, distanceTable, cacheTable, - approxDistance, maxLocalRef, ghTable, mintermTable); - if (factors == NULL) goto outOfMem; - - /* free up tables */ - stGen = st_init_gen(distanceTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - FREE(value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(distanceTable); distanceTable = NULL; - st_free_table(ghTable); ghTable = NULL; - - stGen = st_init_gen(mintermTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - FREE(value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(mintermTable); mintermTable = NULL; - - freeFactors = FactorsNotStored(factors); - factors = (freeFactors) ? FactorsUncomplement(factors) : factors; - if (factors != NULL) { - *c1 = factors->g; - *c2 = factors->h; - cuddRef(*c1); - cuddRef(*c2); - if (freeFactors) FREE(factors); - -#if 0 - if ((*c1 == f) && (!Cudd_IsConstant(f))) { - assert(*c2 == one); - } - if ((*c2 == f) && (!Cudd_IsConstant(f))) { - assert(*c1 == one); - } - - if ((*c1 != one) && (!Cudd_IsConstant(f))) { - assert(!Cudd_bddLeq(dd, *c2, *c1)); - } - if ((*c2 != one) && (!Cudd_IsConstant(f))) { - assert(!Cudd_bddLeq(dd, *c1, *c2)); - } -#endif - } - - stGen = st_init_gen(cacheTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - ConjunctsFree(dd, (Conjuncts *)value); - } - st_free_gen(stGen); stGen = NULL; - - st_free_table(cacheTable); cacheTable = NULL; - - return(1); - -outOfMem: - if (distanceTable != NULL) { - stGen = st_init_gen(distanceTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - FREE(value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(distanceTable); distanceTable = NULL; - } - if (mintermTable != NULL) { - stGen = st_init_gen(mintermTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - FREE(value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(mintermTable); mintermTable = NULL; - } - if (ghTable != NULL) st_free_table(ghTable); - if (cacheTable != NULL) { - stGen = st_init_gen(cacheTable); - if (stGen == NULL) goto outOfMem; - while(st_gen(stGen, (char **)&key, (char **)&value)) { - ConjunctsFree(dd, (Conjuncts *)value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(cacheTable); cacheTable = NULL; - } - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - -} /* end of cuddConjunctsAux */ diff --git a/src/bdd/cudd/cuddEssent.c b/src/bdd/cudd/cuddEssent.c deleted file mode 100644 index db4b8b49..00000000 --- a/src/bdd/cudd/cuddEssent.c +++ /dev/null @@ -1,279 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddEssent.c] - - PackageName [cudd] - - Synopsis [Functions for the detection of essential variables.] - - Description [External procedures included in this file: -
          -
        • Cudd_FindEssential() -
        • Cudd_bddIsVarEssential() -
        - Static procedures included in this module: -
          -
        • ddFindEssentialRecur() -
        ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddEssent.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * ddFindEssentialRecur ARGS((DdManager *dd, DdNode *f)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Finds the essential variables of a DD.] - - Description [Returns the cube of the essential variables. A positive - literal means that the variable must be set to 1 for the function to be - 1. A negative literal means that the variable must be set to 0 for the - function to be 1. Returns a pointer to the cube BDD if successful; - NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddIsVarEssential] - -******************************************************************************/ -DdNode * -Cudd_FindEssential( - DdManager * dd, - DdNode * f) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = ddFindEssentialRecur(dd,f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_FindEssential */ - - -/**Function******************************************************************** - - Synopsis [Determines whether a given variable is essential with a - given phase in a BDD.] - - Description [Determines whether a given variable is essential with a - given phase in a BDD. Uses Cudd_bddIteConstant. Returns 1 if phase == 1 - and f-->x_id, or if phase == 0 and f-->x_id'.] - - SideEffects [None] - - SeeAlso [Cudd_FindEssential] - -******************************************************************************/ -int -Cudd_bddIsVarEssential( - DdManager * manager, - DdNode * f, - int id, - int phase) -{ - DdNode *var; - int res; - DdNode *one, *zero; - - one = DD_ONE(manager); - zero = Cudd_Not(one); - - var = cuddUniqueInter(manager, id, one, zero); - - var = Cudd_NotCond(var,phase == 0); - - res = Cudd_bddIteConstant(manager, Cudd_Not(f), one, var) == one; - - return(res); - -} /* end of Cudd_bddIsVarEssential */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_FindEssential.] - - Description [Implements the recursive step of Cudd_FindEssential. - Returns a pointer to the cube BDD if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -static DdNode * -ddFindEssentialRecur( - DdManager * dd, - DdNode * f) -{ - DdNode *T, *E, *F; - DdNode *essT, *essE, *res; - int index; - DdNode *one, *lzero, *azero; - - one = DD_ONE(dd); - F = Cudd_Regular(f); - /* If f is constant the set of essential variables is empty. */ - if (cuddIsConstant(F)) return(one); - - res = cuddCacheLookup1(dd,Cudd_FindEssential,f); - if (res != NULL) { - return(res); - } - - lzero = Cudd_Not(one); - azero = DD_ZERO(dd); - /* Find cofactors: here f is non-constant. */ - T = cuddT(F); - E = cuddE(F); - if (Cudd_IsComplement(f)) { - T = Cudd_Not(T); E = Cudd_Not(E); - } - - index = F->index; - if (Cudd_IsConstant(T) && T != lzero && T != azero) { - /* if E is zero, index is essential, otherwise there are no - ** essentials, because index is not essential and no other variable - ** can be, since setting index = 1 makes the function constant and - ** different from 0. - */ - if (E == lzero || E == azero) { - res = dd->vars[index]; - } else { - res = one; - } - } else if (T == lzero || T == azero) { - if (Cudd_IsConstant(E)) { /* E cannot be zero here */ - res = Cudd_Not(dd->vars[index]); - } else { /* E == non-constant */ - /* find essentials in the else branch */ - essE = ddFindEssentialRecur(dd,E); - if (essE == NULL) { - return(NULL); - } - cuddRef(essE); - - /* add index to the set with negative phase */ - res = cuddUniqueInter(dd,index,one,Cudd_Not(essE)); - if (res == NULL) { - Cudd_RecursiveDeref(dd,essE); - return(NULL); - } - res = Cudd_Not(res); - cuddDeref(essE); - } - } else { /* T == non-const */ - if (E == lzero || E == azero) { - /* find essentials in the then branch */ - essT = ddFindEssentialRecur(dd,T); - if (essT == NULL) { - return(NULL); - } - cuddRef(essT); - - /* add index to the set with positive phase */ - /* use And because essT may be complemented */ - res = cuddBddAndRecur(dd,dd->vars[index],essT); - if (res == NULL) { - Cudd_RecursiveDeref(dd,essT); - return(NULL); - } - cuddDeref(essT); - } else if (!Cudd_IsConstant(E)) { - /* if E is a non-zero constant there are no essentials - ** because T is non-constant. - */ - essT = ddFindEssentialRecur(dd,T); - if (essT == NULL) { - return(NULL); - } - if (essT == one) { - res = one; - } else { - cuddRef(essT); - essE = ddFindEssentialRecur(dd,E); - if (essE == NULL) { - Cudd_RecursiveDeref(dd,essT); - return(NULL); - } - cuddRef(essE); - - /* res = intersection(essT, essE) */ - res = cuddBddLiteralSetIntersectionRecur(dd,essT,essE); - if (res == NULL) { - Cudd_RecursiveDeref(dd,essT); - Cudd_RecursiveDeref(dd,essE); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd,essT); - Cudd_RecursiveDeref(dd,essE); - cuddDeref(res); - } - } else { /* E is a non-zero constant */ - res = one; - } - } - - cuddCacheInsert1(dd,Cudd_FindEssential, f, res); - return(res); - -} /* end of ddFindEssentialRecur */ - diff --git a/src/bdd/cudd/cuddExact.c b/src/bdd/cudd/cuddExact.c deleted file mode 100644 index 6852be68..00000000 --- a/src/bdd/cudd/cuddExact.c +++ /dev/null @@ -1,1004 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddExact.c] - - PackageName [cudd] - - Synopsis [Functions for exact variable reordering.] - - Description [External procedures included in this file: -
          -
        - Internal procedures included in this module: -
          -
        • cuddExact() -
        - Static procedures included in this module: -
          -
        • getMaxBinomial() -
        • gcd() -
        • getMatrix() -
        • freeMatrix() -
        • getLevelKeys() -
        • ddShuffle() -
        • ddSiftUp() -
        • updateUB() -
        • ddCountRoots() -
        • ddClearGlobal() -
        • computeLB() -
        • updateEntry() -
        • pushDown() -
        • initSymmInfo() -
        ] - - Author [Cheng Hua, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddExact.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -#ifdef DD_STATS -static int ddTotalShuffles; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int getMaxBinomial ARGS((int n)); -static int gcd ARGS((int x, int y)); -static DdHalfWord ** getMatrix ARGS((int rows, int cols)); -static void freeMatrix ARGS((DdHalfWord **matrix)); -static int getLevelKeys ARGS((DdManager *table, int l)); -static int ddShuffle ARGS((DdManager *table, DdHalfWord *permutation, int lower, int upper)); -static int ddSiftUp ARGS((DdManager *table, int x, int xLow)); -static int updateUB ARGS((DdManager *table, int oldBound, DdHalfWord *bestOrder, int lower, int upper)); -static int ddCountRoots ARGS((DdManager *table, int lower, int upper)); -static void ddClearGlobal ARGS((DdManager *table, int lower, int maxlevel)); -static int computeLB ARGS((DdManager *table, DdHalfWord *order, int roots, int cost, int lower, int upper, int level)); -static int updateEntry ARGS((DdManager *table, DdHalfWord *order, int level, int cost, DdHalfWord **orders, int *costs, int subsets, char *mask, int lower, int upper)); -static void pushDown ARGS((DdHalfWord *order, int j, int level)); -static DdHalfWord * initSymmInfo ARGS((DdManager *table, int lower, int upper)); -static int checkSymmInfo ARGS((DdManager *table, DdHalfWord *symmInfo, int index, int level)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Exact variable ordering algorithm.] - - Description [Exact variable ordering algorithm. Finds an optimum - order for the variables between lower and upper. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddExact( - DdManager * table, - int lower, - int upper) -{ - int k, i, j; - int maxBinomial, oldSubsets, newSubsets; - int subsetCost; - int size; /* number of variables to be reordered */ - int unused, nvars, level, result; - int upperBound, lowerBound, cost; - int roots; - char *mask = NULL; - DdHalfWord *symmInfo = NULL; - DdHalfWord **newOrder = NULL; - DdHalfWord **oldOrder = NULL; - int *newCost = NULL; - int *oldCost = NULL; - DdHalfWord **tmpOrder; - int *tmpCost; - DdHalfWord *bestOrder = NULL; - DdHalfWord *order; -#ifdef DD_STATS - int ddTotalSubsets; -#endif - - /* Restrict the range to be reordered by excluding unused variables - ** at the two ends. */ - while (table->subtables[lower].keys == 1 && - table->vars[table->invperm[lower]]->ref == 1 && - lower < upper) - lower++; - while (table->subtables[upper].keys == 1 && - table->vars[table->invperm[upper]]->ref == 1 && - lower < upper) - upper--; - if (lower == upper) return(1); /* trivial problem */ - - /* Apply symmetric sifting to get a good upper bound and to extract - ** symmetry information. */ - result = cuddSymmSiftingConv(table,lower,upper); - if (result == 0) goto cuddExactOutOfMem; - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - ddTotalShuffles = 0; - ddTotalSubsets = 0; -#endif - - /* Initialization. */ - nvars = table->size; - size = upper - lower + 1; - /* Count unused variable among those to be reordered. This is only - ** used to compute maxBinomial. */ - unused = 0; - for (i = lower + 1; i < upper; i++) { - if (table->subtables[i].keys == 1 && - table->vars[table->invperm[i]]->ref == 1) - unused++; - } - - /* Find the maximum number of subsets we may have to store. */ - maxBinomial = getMaxBinomial(size - unused); - if (maxBinomial == -1) goto cuddExactOutOfMem; - - newOrder = getMatrix(maxBinomial, size); - if (newOrder == NULL) goto cuddExactOutOfMem; - - newCost = ALLOC(int, maxBinomial); - if (newCost == NULL) goto cuddExactOutOfMem; - - oldOrder = getMatrix(maxBinomial, size); - if (oldOrder == NULL) goto cuddExactOutOfMem; - - oldCost = ALLOC(int, maxBinomial); - if (oldCost == NULL) goto cuddExactOutOfMem; - - bestOrder = ALLOC(DdHalfWord, size); - if (bestOrder == NULL) goto cuddExactOutOfMem; - - mask = ALLOC(char, nvars); - if (mask == NULL) goto cuddExactOutOfMem; - - symmInfo = initSymmInfo(table, lower, upper); - if (symmInfo == NULL) goto cuddExactOutOfMem; - - roots = ddCountRoots(table, lower, upper); - - /* Initialize the old order matrix for the empty subset and the best - ** order to the current order. The cost for the empty subset includes - ** the cost of the levels between upper and the constants. These levels - ** are not going to change. Hence, we count them only once. - */ - oldSubsets = 1; - for (i = 0; i < size; i++) { - oldOrder[0][i] = bestOrder[i] = (DdHalfWord) table->invperm[i+lower]; - } - subsetCost = table->constants.keys; - for (i = upper + 1; i < nvars; i++) - subsetCost += getLevelKeys(table,i); - oldCost[0] = subsetCost; - /* The upper bound is initialized to the current size of the BDDs. */ - upperBound = table->keys - table->isolated; - - /* Now consider subsets of increasing size. */ - for (k = 1; k <= size; k++) { -#if DD_STATS - (void) fprintf(table->out,"Processing subsets of size %d\n", k); - fflush(table->out); -#endif - newSubsets = 0; - level = size - k; /* offset of first bottom variable */ - - for (i = 0; i < oldSubsets; i++) { /* for each subset of size k-1 */ - order = oldOrder[i]; - cost = oldCost[i]; - lowerBound = computeLB(table, order, roots, cost, lower, upper, - level); - if (lowerBound >= upperBound) - continue; - /* Impose new order. */ - result = ddShuffle(table, order, lower, upper); - if (result == 0) goto cuddExactOutOfMem; - upperBound = updateUB(table,upperBound,bestOrder,lower,upper); - /* For each top bottom variable. */ - for (j = level; j >= 0; j--) { - /* Skip unused variables. */ - if (table->subtables[j+lower-1].keys == 1 && - table->vars[table->invperm[j+lower-1]]->ref == 1) continue; - /* Find cost under this order. */ - subsetCost = cost + getLevelKeys(table, lower + level); - newSubsets = updateEntry(table, order, level, subsetCost, - newOrder, newCost, newSubsets, mask, - lower, upper); - if (j == 0) - break; - if (checkSymmInfo(table, symmInfo, order[j-1], level) == 0) - continue; - pushDown(order,j-1,level); - /* Impose new order. */ - result = ddShuffle(table, order, lower, upper); - if (result == 0) goto cuddExactOutOfMem; - upperBound = updateUB(table,upperBound,bestOrder,lower,upper); - } /* for each bottom variable */ - } /* for each subset of size k */ - - /* New orders become old orders in preparation for next iteration. */ - tmpOrder = oldOrder; tmpCost = oldCost; - oldOrder = newOrder; oldCost = newCost; - newOrder = tmpOrder; newCost = tmpCost; -#ifdef DD_STATS - ddTotalSubsets += newSubsets; -#endif - oldSubsets = newSubsets; - } - result = ddShuffle(table, bestOrder, lower, upper); - if (result == 0) goto cuddExactOutOfMem; -#ifdef DD_STATS -#ifdef DD_VERBOSE - (void) fprintf(table->out,"\n"); -#endif - (void) fprintf(table->out,"#:S_EXACT %8d: total subsets\n", - ddTotalSubsets); - (void) fprintf(table->out,"#:H_EXACT %8d: total shuffles", - ddTotalShuffles); -#endif - - freeMatrix(newOrder); - freeMatrix(oldOrder); - FREE(bestOrder); - FREE(oldCost); - FREE(newCost); - FREE(symmInfo); - FREE(mask); - return(1); - -cuddExactOutOfMem: - - if (newOrder != NULL) freeMatrix(newOrder); - if (oldOrder != NULL) freeMatrix(oldOrder); - if (bestOrder != NULL) FREE(bestOrder); - if (oldCost != NULL) FREE(oldCost); - if (newCost != NULL) FREE(newCost); - if (symmInfo != NULL) FREE(symmInfo); - if (mask != NULL) FREE(mask); - table->errorCode = CUDD_MEMORY_OUT; - return(0); - -} /* end of cuddExact */ - - -/**Function******************************************************************** - - Synopsis [Returns the maximum value of (n choose k) for a given n.] - - Description [Computes the maximum value of (n choose k) for a given - n. The maximum value occurs for k = n/2 when n is even, or k = - (n-1)/2 when n is odd. The algorithm used in this procedure is - quite inefficient, but it avoids intermediate overflow problems. - Returns the computed value if successful; -1 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -getMaxBinomial( - int n) -{ - int *numerator; - int i, j, k, y, g, result; - - k = (n & ~1) >> 1; - - numerator = ALLOC(int,k); - if (numerator == NULL) return(-1); - - for (i = 0; i < k; i++) - numerator[i] = n - i; - - for (i = k; i > 1; i--) { - y = i; - for (j = 0; j < k; j++) { - if (numerator[j] == 1) continue; - g = gcd(numerator[j], y); - if (g != 1) { - numerator[j] /= g; - if (y == g) break; - y /= g; - } - } - } - - result = 1; - for (i = 0; i < k; i++) - result *= numerator[i]; - - FREE(numerator); - return(result); - -} /* end of getMaxBinomial */ - - -/**Function******************************************************************** - - Synopsis [Returns the gcd of two integers.] - - Description [Returns the gcd of two integers. Uses the binary GCD - algorithm described in Cormen, Leiserson, and Rivest.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -gcd( - int x, - int y) -{ - int a; - int b; - int lsbMask; - - /* GCD(n,0) = n. */ - if (x == 0) return(y); - if (y == 0) return(x); - - a = x; b = y; lsbMask = 1; - - /* Here both a and b are != 0. The iteration maintains this invariant. - ** Hence, we only need to check for when they become equal. - */ - while (a != b) { - if (a & lsbMask) { - if (b & lsbMask) { /* both odd */ - if (a < b) { - b = (b - a) >> 1; - } else { - a = (a - b) >> 1; - } - } else { /* a odd, b even */ - b >>= 1; - } - } else { - if (b & lsbMask) { /* a even, b odd */ - a >>= 1; - } else { /* both even */ - lsbMask <<= 1; - } - } - } - - return(a); - -} /* end of gcd */ - - -/**Function******************************************************************** - - Synopsis [Allocates a two-dimensional matrix of ints.] - - Description [Allocates a two-dimensional matrix of ints. - Returns the pointer to the matrix if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [freeMatrix] - -******************************************************************************/ -static DdHalfWord ** -getMatrix( - int rows /* number of rows */, - int cols /* number of columns */) -{ - DdHalfWord **matrix; - int i; - - if (cols*rows == 0) return(NULL); - matrix = ALLOC(DdHalfWord *, rows); - if (matrix == NULL) return(NULL); - matrix[0] = ALLOC(DdHalfWord, cols*rows); - if (matrix[0] == NULL) return(NULL); - for (i = 1; i < rows; i++) { - matrix[i] = matrix[i-1] + cols; - } - return(matrix); - -} /* end of getMatrix */ - - -/**Function******************************************************************** - - Synopsis [Frees a two-dimensional matrix allocated by getMatrix.] - - Description [] - - SideEffects [None] - - SeeAlso [getMatrix] - -******************************************************************************/ -static void -freeMatrix( - DdHalfWord ** matrix) -{ - FREE(matrix[0]); - FREE(matrix); - return; - -} /* end of freeMatrix */ - - -/**Function******************************************************************** - - Synopsis [Returns the number of nodes at one level of a unique table.] - - Description [Returns the number of nodes at one level of a unique table. - The projection function, if isolated, is not counted.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -getLevelKeys( - DdManager * table, - int l) -{ - int isolated; - int x; /* x is an index */ - - x = table->invperm[l]; - isolated = table->vars[x]->ref == 1; - - return(table->subtables[l].keys - isolated); - -} /* end of getLevelKeys */ - - -/**Function******************************************************************** - - Synopsis [Reorders variables according to a given permutation.] - - Description [Reorders variables according to a given permutation. - The i-th permutation array contains the index of the variable that - should be brought to the i-th level. ddShuffle assumes that no - dead nodes are present and that the interaction matrix is properly - initialized. The reordering is achieved by a series of upward sifts. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddShuffle( - DdManager * table, - DdHalfWord * permutation, - int lower, - int upper) -{ - DdHalfWord index; - int level; - int position; - int numvars; - int result; -#ifdef DD_STATS - long localTime; - int initialSize; -#ifdef DD_VERBOSE - int finalSize; -#endif - int previousSize; -#endif - -#ifdef DD_STATS - localTime = util_cpu_time(); - initialSize = table->keys - table->isolated; -#endif - - numvars = table->size; - -#if 0 - (void) fprintf(table->out,"%d:", ddTotalShuffles); - for (level = 0; level < numvars; level++) { - (void) fprintf(table->out," %d", table->invperm[level]); - } - (void) fprintf(table->out,"\n"); -#endif - - for (level = 0; level <= upper - lower; level++) { - index = permutation[level]; - position = table->perm[index]; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddSiftUp(table,position,level+lower); - if (!result) return(0); - } - -#ifdef DD_STATS - ddTotalShuffles++; -#ifdef DD_VERBOSE - finalSize = table->keys - table->isolated; - if (finalSize < initialSize) { - (void) fprintf(table->out,"-"); - } else if (finalSize > initialSize) { - (void) fprintf(table->out,"+"); - } else { - (void) fprintf(table->out,"="); - } - if ((ddTotalShuffles & 63) == 0) (void) fprintf(table->out,"\n"); - fflush(table->out); -#endif -#endif - - return(1); - -} /* end of ddShuffle */ - - -/**Function******************************************************************** - - Synopsis [Moves one variable up.] - - Description [Takes a variable from position x and sifts it up to - position xLow; xLow should be less than or equal to x. - Returns 1 if successful; 0 otherwise] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddSiftUp( - DdManager * table, - int x, - int xLow) -{ - int y; - int size; - - y = cuddNextLow(table,x); - while (y >= xLow) { - size = cuddSwapInPlace(table,y,x); - if (size == 0) { - return(0); - } - x = y; - y = cuddNextLow(table,x); - } - return(1); - -} /* end of ddSiftUp */ - - -/**Function******************************************************************** - - Synopsis [Updates the upper bound and saves the best order seen so far.] - - Description [Updates the upper bound and saves the best order seen so far. - Returns the current value of the upper bound.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -updateUB( - DdManager * table, - int oldBound, - DdHalfWord * bestOrder, - int lower, - int upper) -{ - int i; - int newBound = table->keys - table->isolated; - - if (newBound < oldBound) { -#ifdef DD_STATS - (void) fprintf(table->out,"New upper bound = %d\n", newBound); - fflush(table->out); -#endif - for (i = lower; i <= upper; i++) - bestOrder[i-lower] = (DdHalfWord) table->invperm[i]; - return(newBound); - } else { - return(oldBound); - } - -} /* end of updateUB */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of roots.] - - Description [Counts the number of roots at the levels between lower and - upper. The computation is based on breadth-first search. - A node is a root if it is not reachable from any previously visited node. - (All the nodes at level lower are therefore considered roots.) - The visited flag uses the LSB of the next pointer. Returns the root - count. The roots that are constant nodes are always ignored.] - - SideEffects [None] - - SeeAlso [ddClearGlobal] - -******************************************************************************/ -static int -ddCountRoots( - DdManager * table, - int lower, - int upper) -{ - int i,j; - DdNode *f; - DdNodePtr *nodelist; - DdNode *sentinel = &(table->sentinel); - int slots; - int roots = 0; - int maxlevel = lower; - - for (i = lower; i <= upper; i++) { - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - for (j = 0; j < slots; j++) { - f = nodelist[j]; - while (f != sentinel) { - /* A node is a root of the DAG if it cannot be - ** reached by nodes above it. If a node was never - ** reached during the previous depth-first searches, - ** then it is a root, and we start a new depth-first - ** search from it. - */ - if (!Cudd_IsComplement(f->next)) { - if (f != table->vars[f->index]) { - roots++; - } - } - if (!Cudd_IsConstant(cuddT(f))) { - cuddT(f)->next = Cudd_Complement(cuddT(f)->next); - if (table->perm[cuddT(f)->index] > maxlevel) - maxlevel = table->perm[cuddT(f)->index]; - } - if (!Cudd_IsConstant(cuddE(f))) { - Cudd_Regular(cuddE(f))->next = - Cudd_Complement(Cudd_Regular(cuddE(f))->next); - if (table->perm[Cudd_Regular(cuddE(f))->index] > maxlevel) - maxlevel = table->perm[Cudd_Regular(cuddE(f))->index]; - } - f = Cudd_Regular(f->next); - } - } - } - ddClearGlobal(table, lower, maxlevel); - - return(roots); - -} /* end of ddCountRoots */ - - -/**Function******************************************************************** - - Synopsis [Scans the DD and clears the LSB of the next pointers.] - - Description [Scans the DD and clears the LSB of the next pointers. - The LSB of the next pointers are used as markers to tell whether a - node was reached. Once the roots are counted, these flags are - reset.] - - SideEffects [None] - - SeeAlso [ddCountRoots] - -******************************************************************************/ -static void -ddClearGlobal( - DdManager * table, - int lower, - int maxlevel) -{ - int i,j; - DdNode *f; - DdNodePtr *nodelist; - DdNode *sentinel = &(table->sentinel); - int slots; - - for (i = lower; i <= maxlevel; i++) { - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - for (j = 0; j < slots; j++) { - f = nodelist[j]; - while (f != sentinel) { - f->next = Cudd_Regular(f->next); - f = f->next; - } - } - } - -} /* end of ddClearGlobal */ - - -/**Function******************************************************************** - - Synopsis [Computes a lower bound on the size of a BDD.] - - Description [Computes a lower bound on the size of a BDD from the - following factors: -
          -
        • size of the lower part of it; -
        • size of the part of the upper part not subjected to reordering; -
        • number of roots in the part of the BDD subjected to reordering; -
        • variable in the support of the roots in the upper part of the - BDD subjected to reordering. -
            ] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -computeLB( - DdManager * table /* manager */, - DdHalfWord * order /* optimal order for the subset */, - int roots /* roots between lower and upper */, - int cost /* minimum cost for the subset */, - int lower /* lower level to be reordered */, - int upper /* upper level to be reordered */, - int level /* offset for the current top bottom var */ - ) -{ - int i; - int lb = cost; - int lb1 = 0; - int lb2; - int support; - DdHalfWord ref; - - /* The levels not involved in reordering are not going to change. - ** Add their sizes to the lower bound. - */ - for (i = 0; i < lower; i++) { - lb += getLevelKeys(table,i); - } - /* If a variable is in the support, then there is going - ** to be at least one node labeled by that variable. - */ - for (i = lower; i <= lower+level; i++) { - support = table->subtables[i].keys > 1 || - table->vars[order[i-lower]]->ref > 1; - lb1 += support; - } - - /* Estimate the number of nodes required to connect the roots to - ** the nodes in the bottom part. */ - if (lower+level+1 < table->size) { - if (lower+level < upper) - ref = table->vars[order[level+1]]->ref; - else - ref = table->vars[table->invperm[upper+1]]->ref; - lb2 = table->subtables[lower+level+1].keys - - (ref > (DdHalfWord) 1) - roots; - } else { - lb2 = 0; - } - - lb += lb1 > lb2 ? lb1 : lb2; - - return(lb); - -} /* end of computeLB */ - - -/**Function******************************************************************** - - Synopsis [Updates entry for a subset.] - - Description [Updates entry for a subset. Finds the subset, if it exists. - If the new order for the subset has lower cost, or if the subset did not - exist, it stores the new order and cost. Returns the number of subsets - currently in the table.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -updateEntry( - DdManager * table, - DdHalfWord * order, - int level, - int cost, - DdHalfWord ** orders, - int * costs, - int subsets, - char * mask, - int lower, - int upper) -{ - int i, j; - int size = upper - lower + 1; - - /* Build a mask that says what variables are in this subset. */ - for (i = lower; i <= upper; i++) - mask[table->invperm[i]] = 0; - for (i = level; i < size; i++) - mask[order[i]] = 1; - - /* Check each subset until a match is found or all subsets are examined. */ - for (i = 0; i < subsets; i++) { - DdHalfWord *subset = orders[i]; - for (j = level; j < size; j++) { - if (mask[subset[j]] == 0) - break; - } - if (j == size) /* no mismatches: success */ - break; - } - if (i == subsets || cost < costs[i]) { /* add or replace */ - for (j = 0; j < size; j++) - orders[i][j] = order[j]; - costs[i] = cost; - subsets += (i == subsets); - } - return(subsets); - -} /* end of updateEntry */ - - -/**Function******************************************************************** - - Synopsis [Pushes a variable in the order down to position "level."] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -pushDown( - DdHalfWord * order, - int j, - int level) -{ - int i; - DdHalfWord tmp; - - tmp = order[j]; - for (i = j; i < level; i++) { - order[i] = order[i+1]; - } - order[level] = tmp; - return; - -} /* end of pushDown */ - - -/**Function******************************************************************** - - Synopsis [Gathers symmetry information.] - - Description [Translates the symmetry information stored in the next - field of each subtable from level to indices. This procedure is called - immediately after symmetric sifting, so that the next fields are correct. - By translating this informaton in terms of indices, we make it independent - of subsequent reorderings. The format used is that of the next fields: - a circular list where each variable points to the next variable in the - same symmetry group. Only the entries between lower and upper are - considered. The procedure returns a pointer to an array - holding the symmetry information if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [checkSymmInfo] - -******************************************************************************/ -static DdHalfWord * -initSymmInfo( - DdManager * table, - int lower, - int upper) -{ - int level, index, next, nextindex; - DdHalfWord *symmInfo; - - symmInfo = ALLOC(DdHalfWord, table->size); - if (symmInfo == NULL) return(NULL); - - for (level = lower; level <= upper; level++) { - index = table->invperm[level]; - next = table->subtables[level].next; - nextindex = table->invperm[next]; - symmInfo[index] = nextindex; - } - return(symmInfo); - -} /* end of initSymmInfo */ - - -/**Function******************************************************************** - - Synopsis [Check symmetry condition.] - - Description [Returns 1 if a variable is the one with the highest index - among those belonging to a symmetry group that are in the top part of - the BDD. The top part is given by level.] - - SideEffects [None] - - SeeAlso [initSymmInfo] - -******************************************************************************/ -static int -checkSymmInfo( - DdManager * table, - DdHalfWord * symmInfo, - int index, - int level) -{ - int i; - - i = symmInfo[index]; - while (i != index) { - if (index < i && table->perm[i] <= level) - return(0); - i = symmInfo[i]; - } - return(1); - -} /* end of checkSymmInfo */ - diff --git a/src/bdd/cudd/cuddExport.c b/src/bdd/cudd/cuddExport.c deleted file mode 100644 index d148be42..00000000 --- a/src/bdd/cudd/cuddExport.c +++ /dev/null @@ -1,1289 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddExport.c] - - PackageName [cudd] - - Synopsis [Export functions.] - - Description [External procedures included in this module: -
              -
            • Cudd_DumpBlif() -
            • Cudd_DumpBlifBody() -
            • Cudd_DumpDot() -
            • Cudd_DumpDaVinci() -
            • Cudd_DumpDDcal() -
            • Cudd_DumpFactoredForm() -
            - Internal procedures included in this module: -
              -
            - Static procedures included in this module: -
              -
            • ddDoDumpBlif() -
            • ddDoDumpDaVinci() -
            • ddDoDumpDDcal() -
            • ddDoDumpFactoredForm() -
            ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddExport.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddDoDumpBlif ARGS((DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names)); -static int ddDoDumpDaVinci ARGS((DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, long mask)); -static int ddDoDumpDDcal ARGS((DdManager *dd, DdNode *f, FILE *fp, st_table *visited, char **names, long mask)); -static int ddDoDumpFactoredForm ARGS((DdManager *dd, DdNode *f, FILE *fp, char **names)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Writes a blif file representing the argument BDDs.] - - Description [Writes a blif file representing the argument BDDs as a - network of multiplexers. One multiplexer is written for each BDD - node. It returns 1 in case of success; 0 otherwise (e.g., - out-of-memory, file system full, or an ADD with constants different - from 0 and 1). Cudd_DumpBlif does not close the file: This is the - caller responsibility. Cudd_DumpBlif uses a minimal unique subset of - the hexadecimal address of a node as name for it. If the argument - inames is non-null, it is assumed to hold the pointers to the names - of the inputs. Similarly for onames.] - - SideEffects [None] - - SeeAlso [Cudd_DumpBlifBody Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal - Cudd_DumpDaVinci Cudd_DumpFactoredForm] - -******************************************************************************/ -int -Cudd_DumpBlif( - DdManager * dd /* manager */, - int n /* number of output nodes to be dumped */, - DdNode ** f /* array of output nodes to be dumped */, - char ** inames /* array of input names (or NULL) */, - char ** onames /* array of output names (or NULL) */, - char * mname /* model name (or NULL) */, - FILE * fp /* pointer to the dump file */) -{ - DdNode *support = NULL; - DdNode *scan; - int *sorted = NULL; - int nvars = dd->size; - int retval; - int i; - - /* Build a bit array with the support of f. */ - sorted = ALLOC(int,nvars); - if (sorted == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - goto failure; - } - for (i = 0; i < nvars; i++) sorted[i] = 0; - - /* Take the union of the supports of each output function. */ - support = Cudd_VectorSupport(dd,f,n); - if (support == NULL) goto failure; - cuddRef(support); - scan = support; - while (!cuddIsConstant(scan)) { - sorted[scan->index] = 1; - scan = cuddT(scan); - } - Cudd_RecursiveDeref(dd,support); - support = NULL; /* so that we do not try to free it in case of failure */ - - /* Write the header (.model .inputs .outputs). */ - if (mname == NULL) { - retval = fprintf(fp,".model DD\n.inputs"); - } else { - retval = fprintf(fp,".model %s\n.inputs",mname); - } - if (retval == EOF) return(0); - - /* Write the input list by scanning the support array. */ - for (i = 0; i < nvars; i++) { - if (sorted[i]) { - if (inames == NULL) { - retval = fprintf(fp," %d", i); - } else { - retval = fprintf(fp," %s", inames[i]); - } - if (retval == EOF) goto failure; - } - } - FREE(sorted); - sorted = NULL; - - /* Write the .output line. */ - retval = fprintf(fp,"\n.outputs"); - if (retval == EOF) goto failure; - for (i = 0; i < n; i++) { - if (onames == NULL) { - retval = fprintf(fp," f%d", i); - } else { - retval = fprintf(fp," %s", onames[i]); - } - if (retval == EOF) goto failure; - } - retval = fprintf(fp,"\n"); - if (retval == EOF) goto failure; - - retval = Cudd_DumpBlifBody(dd, n, f, inames, onames, fp); - if (retval == 0) goto failure; - - /* Write trailer and return. */ - retval = fprintf(fp,".end\n"); - if (retval == EOF) goto failure; - - return(1); - -failure: - if (sorted != NULL) FREE(sorted); - if (support != NULL) Cudd_RecursiveDeref(dd,support); - return(0); - -} /* end of Cudd_DumpBlif */ - - -/**Function******************************************************************** - - Synopsis [Writes a blif body representing the argument BDDs.] - - Description [Writes a blif body representing the argument BDDs as a - network of multiplexers. One multiplexer is written for each BDD - node. It returns 1 in case of success; 0 otherwise (e.g., - out-of-memory, file system full, or an ADD with constants different - from 0 and 1). Cudd_DumpBlif does not close the file: This is the - caller responsibility. Cudd_DumpBlif uses a minimal unique subset of - the hexadecimal address of a node as name for it. If the argument - inames is non-null, it is assumed to hold the pointers to the names - of the inputs. Similarly for onames. This function prints out only - .names part.] - - SideEffects [None] - - SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpDDcal - Cudd_DumpDaVinci Cudd_DumpFactoredForm] - -******************************************************************************/ -int -Cudd_DumpBlifBody( - DdManager * dd /* manager */, - int n /* number of output nodes to be dumped */, - DdNode ** f /* array of output nodes to be dumped */, - char ** inames /* array of input names (or NULL) */, - char ** onames /* array of output names (or NULL) */, - FILE * fp /* pointer to the dump file */) -{ - st_table *visited = NULL; - int retval; - int i; - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - if (visited == NULL) goto failure; - - /* Call the function that really gets the job done. */ - for (i = 0; i < n; i++) { - retval = ddDoDumpBlif(dd,Cudd_Regular(f[i]),fp,visited,inames); - if (retval == 0) goto failure; - } - - /* To account for the possible complement on the root, - ** we put either a buffer or an inverter at the output of - ** the multiplexer representing the top node. - */ - for (i = 0; i < n; i++) { - if (onames == NULL) { - retval = fprintf(fp, -#if SIZEOF_VOID_P == 8 - ".names %lx f%d\n", (unsigned long) f[i] / (unsigned long) sizeof(DdNode), i); -#else - ".names %x f%d\n", (unsigned) f[i] / (unsigned) sizeof(DdNode), i); -#endif - } else { - retval = fprintf(fp, -#if SIZEOF_VOID_P == 8 - ".names %lx %s\n", (unsigned long) f[i] / (unsigned long) sizeof(DdNode), onames[i]); -#else - ".names %x %s\n", (unsigned) f[i] / (unsigned) sizeof(DdNode), onames[i]); -#endif - } - if (retval == EOF) goto failure; - if (Cudd_IsComplement(f[i])) { - retval = fprintf(fp,"0 1\n"); - } else { - retval = fprintf(fp,"1 1\n"); - } - if (retval == EOF) goto failure; - } - - st_free_table(visited); - return(1); - -failure: - if (visited != NULL) st_free_table(visited); - return(0); - -} /* end of Cudd_DumpBlifBody */ - - -/**Function******************************************************************** - - Synopsis [Writes a dot file representing the argument DDs.] - - Description [Writes a file representing the argument DDs in a format - suitable for the graph drawing program dot. - It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, - file system full). - Cudd_DumpDot does not close the file: This is the caller - responsibility. Cudd_DumpDot uses a minimal unique subset of the - hexadecimal address of a node as name for it. - If the argument inames is non-null, it is assumed to hold the pointers - to the names of the inputs. Similarly for onames. - Cudd_DumpDot uses the following convention to draw arcs: -
              -
            • solid line: THEN arcs; -
            • dotted line: complement arcs; -
            • dashed line: regular ELSE arcs. -
            - The dot options are chosen so that the drawing fits on a letter-size - sheet. - ] - - SideEffects [None] - - SeeAlso [Cudd_DumpBlif Cudd_PrintDebug Cudd_DumpDDcal - Cudd_DumpDaVinci Cudd_DumpFactoredForm] - -******************************************************************************/ -int -Cudd_DumpDot( - DdManager * dd /* manager */, - int n /* number of output nodes to be dumped */, - DdNode ** f /* array of output nodes to be dumped */, - char ** inames /* array of input names (or NULL) */, - char ** onames /* array of output names (or NULL) */, - FILE * fp /* pointer to the dump file */) -{ - DdNode *support = NULL; - DdNode *scan; - int *sorted = NULL; - int nvars = dd->size; - st_table *visited = NULL; - st_generator *gen = NULL; - int retval; - int i, j; - int slots; - DdNodePtr *nodelist; - long refAddr, diff, mask; - - /* Build a bit array with the support of f. */ - sorted = ALLOC(int,nvars); - if (sorted == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - goto failure; - } - for (i = 0; i < nvars; i++) sorted[i] = 0; - - /* Take the union of the supports of each output function. */ - support = Cudd_VectorSupport(dd,f,n); - if (support == NULL) goto failure; - cuddRef(support); - scan = support; - while (!cuddIsConstant(scan)) { - sorted[scan->index] = 1; - scan = cuddT(scan); - } - Cudd_RecursiveDeref(dd,support); - support = NULL; /* so that we do not try to free it in case of failure */ - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - if (visited == NULL) goto failure; - - /* Collect all the nodes of this DD in the symbol table. */ - for (i = 0; i < n; i++) { - retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); - if (retval == 0) goto failure; - } - - /* Find how many most significant hex digits are identical - ** in the addresses of all the nodes. Build a mask based - ** on this knowledge, so that digits that carry no information - ** will not be printed. This is done in two steps. - ** 1. We scan the symbol table to find the bits that differ - ** in at least 2 addresses. - ** 2. We choose one of the possible masks. There are 8 possible - ** masks for 32-bit integer, and 16 possible masks for 64-bit - ** integers. - */ - - /* Find the bits that are different. */ - refAddr = (long) Cudd_Regular(f[0]); - diff = 0; - gen = st_init_gen(visited); - if (gen == NULL) goto failure; - while (st_gen(gen, (char **) &scan, NULL)) { - diff |= refAddr ^ (long) scan; - } - st_free_gen(gen); gen = NULL; - - /* Choose the mask. */ - for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) { - mask = (1 << i) - 1; - if (diff <= mask) break; - } - - /* Write the header and the global attributes. */ - retval = fprintf(fp,"digraph \"DD\" {\n"); - if (retval == EOF) return(0); - retval = fprintf(fp, - "size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n"); - if (retval == EOF) return(0); - - /* Write the input name subgraph by scanning the support array. */ - retval = fprintf(fp,"{ node [shape = plaintext];\n"); - if (retval == EOF) goto failure; - retval = fprintf(fp," edge [style = invis];\n"); - if (retval == EOF) goto failure; - /* We use a name ("CONST NODES") with an embedded blank, because - ** it is unlikely to appear as an input name. - */ - retval = fprintf(fp," \"CONST NODES\" [style = invis];\n"); - if (retval == EOF) goto failure; - for (i = 0; i < nvars; i++) { - if (sorted[dd->invperm[i]]) { - if (inames == NULL || inames[dd->invperm[i]] == NULL) { - retval = fprintf(fp,"\" %d \" -> ", dd->invperm[i]); - } else { - retval = fprintf(fp,"\" %s \" -> ", inames[dd->invperm[i]]); - } - if (retval == EOF) goto failure; - } - } - retval = fprintf(fp,"\"CONST NODES\"; \n}\n"); - if (retval == EOF) goto failure; - - /* Write the output node subgraph. */ - retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n"); - if (retval == EOF) goto failure; - for (i = 0; i < n; i++) { - if (onames == NULL) { - retval = fprintf(fp,"\"F%d\"", i); - } else { - retval = fprintf(fp,"\" %s \"", onames[i]); - } - if (retval == EOF) goto failure; - if (i == n - 1) { - retval = fprintf(fp,"; }\n"); - } else { - retval = fprintf(fp," -> "); - } - if (retval == EOF) goto failure; - } - - /* Write rank info: All nodes with the same index have the same rank. */ - for (i = 0; i < nvars; i++) { - if (sorted[dd->invperm[i]]) { - retval = fprintf(fp,"{ rank = same; "); - if (retval == EOF) goto failure; - if (inames == NULL || inames[dd->invperm[i]] == NULL) { - retval = fprintf(fp,"\" %d \";\n", dd->invperm[i]); - } else { - retval = fprintf(fp,"\" %s \";\n", inames[dd->invperm[i]]); - } - if (retval == EOF) goto failure; - nodelist = dd->subtables[i].nodelist; - slots = dd->subtables[i].slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (st_is_member(visited,(char *) scan)) { - retval = fprintf(fp,"\"%lx\";\n", (mask & (long) scan) / sizeof(DdNode)); - if (retval == EOF) goto failure; - } - scan = scan->next; - } - } - retval = fprintf(fp,"}\n"); - if (retval == EOF) goto failure; - } - } - - /* All constants have the same rank. */ - retval = fprintf(fp, - "{ rank = same; \"CONST NODES\";\n{ node [shape = box]; "); - if (retval == EOF) goto failure; - nodelist = dd->constants.nodelist; - slots = dd->constants.slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (st_is_member(visited,(char *) scan)) { - retval = fprintf(fp,"\"%lx\";\n", (mask & (long) scan) / sizeof(DdNode)); - if (retval == EOF) goto failure; - } - scan = scan->next; - } - } - retval = fprintf(fp,"}\n}\n"); - if (retval == EOF) goto failure; - - /* Write edge info. */ - /* Edges from the output nodes. */ - for (i = 0; i < n; i++) { - if (onames == NULL) { - retval = fprintf(fp,"\"F%d\"", i); - } else { - retval = fprintf(fp,"\" %s \"", onames[i]); - } - if (retval == EOF) goto failure; - /* Account for the possible complement on the root. */ - if (Cudd_IsComplement(f[i])) { - retval = fprintf(fp," -> \"%lx\" [style = dotted];\n", - (mask & (long) f[i]) / sizeof(DdNode)); - } else { - retval = fprintf(fp," -> \"%lx\" [style = solid];\n", - (mask & (long) f[i]) / sizeof(DdNode)); - } - if (retval == EOF) goto failure; - } - - /* Edges from internal nodes. */ - for (i = 0; i < nvars; i++) { - if (sorted[dd->invperm[i]]) { - nodelist = dd->subtables[i].nodelist; - slots = dd->subtables[i].slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (st_is_member(visited,(char *) scan)) { - retval = fprintf(fp, - "\"%lx\" -> \"%lx\";\n", - (mask & (long) scan) / sizeof(DdNode), - (mask & (long) cuddT(scan)) / sizeof(DdNode)); - if (retval == EOF) goto failure; - if (Cudd_IsComplement(cuddE(scan))) { - retval = fprintf(fp, - "\"%lx\" -> \"%lx\" [style = dotted];\n", - (mask & (long) scan) / sizeof(DdNode), - (mask & (long) cuddE(scan)) / sizeof(DdNode)); - } else { - retval = fprintf(fp, - "\"%lx\" -> \"%lx\" [style = dashed];\n", - (mask & (long) scan) / sizeof(DdNode), - (mask & (long) cuddE(scan)) / sizeof(DdNode)); - } - if (retval == EOF) goto failure; - } - scan = scan->next; - } - } - } - } - - /* Write constant labels. */ - nodelist = dd->constants.nodelist; - slots = dd->constants.slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (st_is_member(visited,(char *) scan)) { - retval = fprintf(fp,"\"%lx\" [label = \"%g\"];\n", - (mask & (long) scan) / sizeof(DdNode), cuddV(scan)); - if (retval == EOF) goto failure; - } - scan = scan->next; - } - } - - /* Write trailer and return. */ - retval = fprintf(fp,"}\n"); - if (retval == EOF) goto failure; - - st_free_table(visited); - FREE(sorted); - return(1); - -failure: - if (sorted != NULL) FREE(sorted); - if (support != NULL) Cudd_RecursiveDeref(dd,support); - if (visited != NULL) st_free_table(visited); - return(0); - -} /* end of Cudd_DumpDot */ - - -/**Function******************************************************************** - - Synopsis [Writes a daVinci file representing the argument BDDs.] - - Description [Writes a daVinci file representing the argument BDDs. - It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or - file system full). Cudd_DumpDaVinci does not close the file: This - is the caller responsibility. Cudd_DumpDaVinci uses a minimal unique - subset of the hexadecimal address of a node as name for it. If the - argument inames is non-null, it is assumed to hold the pointers to - the names of the inputs. Similarly for onames.] - - SideEffects [None] - - SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDDcal - Cudd_DumpFactoredForm] - -******************************************************************************/ -int -Cudd_DumpDaVinci( - DdManager * dd /* manager */, - int n /* number of output nodes to be dumped */, - DdNode ** f /* array of output nodes to be dumped */, - char ** inames /* array of input names (or NULL) */, - char ** onames /* array of output names (or NULL) */, - FILE * fp /* pointer to the dump file */) -{ - DdNode *support = NULL; - DdNode *scan; - st_table *visited = NULL; - int retval; - int i; - st_generator *gen; - long refAddr, diff, mask; - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - if (visited == NULL) goto failure; - - /* Collect all the nodes of this DD in the symbol table. */ - for (i = 0; i < n; i++) { - retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); - if (retval == 0) goto failure; - } - - /* Find how many most significant hex digits are identical - ** in the addresses of all the nodes. Build a mask based - ** on this knowledge, so that digits that carry no information - ** will not be printed. This is done in two steps. - ** 1. We scan the symbol table to find the bits that differ - ** in at least 2 addresses. - ** 2. We choose one of the possible masks. There are 8 possible - ** masks for 32-bit integer, and 16 possible masks for 64-bit - ** integers. - */ - - /* Find the bits that are different. */ - refAddr = (long) Cudd_Regular(f[0]); - diff = 0; - gen = st_init_gen(visited); - while (st_gen(gen, (char **) &scan, NULL)) { - diff |= refAddr ^ (long) scan; - } - st_free_gen(gen); - - /* Choose the mask. */ - for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) { - mask = (1 << i) - 1; - if (diff <= mask) break; - } - st_free_table(visited); - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - if (visited == NULL) goto failure; - - retval = fprintf(fp, "["); - if (retval == EOF) goto failure; - /* Call the function that really gets the job done. */ - for (i = 0; i < n; i++) { - if (onames == NULL) { - retval = fprintf(fp, - "l(\"f%d\",n(\"root\",[a(\"OBJECT\",\"f%d\")],", - i,i); - } else { - retval = fprintf(fp, - "l(\"%s\",n(\"root\",[a(\"OBJECT\",\"%s\")],", - onames[i], onames[i]); - } - if (retval == EOF) goto failure; - retval = fprintf(fp, "[e(\"edge\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],", - Cudd_IsComplement(f[i]) ? "red" : "blue"); - if (retval == EOF) goto failure; - retval = ddDoDumpDaVinci(dd,Cudd_Regular(f[i]),fp,visited,inames,mask); - if (retval == 0) goto failure; - retval = fprintf(fp, ")]))%s", i == n-1 ? "" : ","); - if (retval == EOF) goto failure; - } - - /* Write trailer and return. */ - retval = fprintf(fp, "]\n"); - if (retval == EOF) goto failure; - - st_free_table(visited); - return(1); - -failure: - if (support != NULL) Cudd_RecursiveDeref(dd,support); - if (visited != NULL) st_free_table(visited); - return(0); - -} /* end of Cudd_DumpDaVinci */ - - -/**Function******************************************************************** - - Synopsis [Writes a DDcal file representing the argument BDDs.] - - Description [Writes a DDcal file representing the argument BDDs. - It returns 1 in case of success; 0 otherwise (e.g., out-of-memory or - file system full). Cudd_DumpDDcal does not close the file: This - is the caller responsibility. Cudd_DumpDDcal uses a minimal unique - subset of the hexadecimal address of a node as name for it. If the - argument inames is non-null, it is assumed to hold the pointers to - the names of the inputs. Similarly for onames.] - - SideEffects [None] - - SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci - Cudd_DumpFactoredForm] - -******************************************************************************/ -int -Cudd_DumpDDcal( - DdManager * dd /* manager */, - int n /* number of output nodes to be dumped */, - DdNode ** f /* array of output nodes to be dumped */, - char ** inames /* array of input names (or NULL) */, - char ** onames /* array of output names (or NULL) */, - FILE * fp /* pointer to the dump file */) -{ - DdNode *support = NULL; - DdNode *scan; - int *sorted = NULL; - int nvars = dd->size; - st_table *visited = NULL; - int retval; - int i; - st_generator *gen; - long refAddr, diff, mask; - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - if (visited == NULL) goto failure; - - /* Collect all the nodes of this DD in the symbol table. */ - for (i = 0; i < n; i++) { - retval = cuddCollectNodes(Cudd_Regular(f[i]),visited); - if (retval == 0) goto failure; - } - - /* Find how many most significant hex digits are identical - ** in the addresses of all the nodes. Build a mask based - ** on this knowledge, so that digits that carry no information - ** will not be printed. This is done in two steps. - ** 1. We scan the symbol table to find the bits that differ - ** in at least 2 addresses. - ** 2. We choose one of the possible masks. There are 8 possible - ** masks for 32-bit integer, and 16 possible masks for 64-bit - ** integers. - */ - - /* Find the bits that are different. */ - refAddr = (long) Cudd_Regular(f[0]); - diff = 0; - gen = st_init_gen(visited); - while (st_gen(gen, (char **) &scan, NULL)) { - diff |= refAddr ^ (long) scan; - } - st_free_gen(gen); - - /* Choose the mask. */ - for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) { - mask = (1 << i) - 1; - if (diff <= mask) break; - } - st_free_table(visited); - - /* Build a bit array with the support of f. */ - sorted = ALLOC(int,nvars); - if (sorted == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - goto failure; - } - for (i = 0; i < nvars; i++) sorted[i] = 0; - - /* Take the union of the supports of each output function. */ - support = Cudd_VectorSupport(dd,f,n); - if (support == NULL) goto failure; - cuddRef(support); - scan = support; - while (!cuddIsConstant(scan)) { - sorted[scan->index] = 1; - scan = cuddT(scan); - } - Cudd_RecursiveDeref(dd,support); - support = NULL; /* so that we do not try to free it in case of failure */ - for (i = 0; i < nvars; i++) { - if (sorted[dd->invperm[i]]) { - if (inames == NULL || inames[dd->invperm[i]] == NULL) { - retval = fprintf(fp,"v%d", dd->invperm[i]); - } else { - retval = fprintf(fp,"%s", inames[dd->invperm[i]]); - } - if (retval == EOF) goto failure; - } - retval = fprintf(fp,"%s", i == nvars - 1 ? "\n" : " * "); - if (retval == EOF) goto failure; - } - FREE(sorted); - sorted = NULL; - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - if (visited == NULL) goto failure; - - /* Call the function that really gets the job done. */ - for (i = 0; i < n; i++) { - retval = ddDoDumpDDcal(dd,Cudd_Regular(f[i]),fp,visited,inames,mask); - if (retval == 0) goto failure; - if (onames == NULL) { - retval = fprintf(fp, "f%d = ", i); - } else { - retval = fprintf(fp, "%s = ", onames[i]); - } - if (retval == EOF) goto failure; - retval = fprintf(fp, "n%lx%s\n", - ((long) f[i] & mask) / sizeof(DdNode), - Cudd_IsComplement(f[i]) ? "'" : ""); - if (retval == EOF) goto failure; - } - - /* Write trailer and return. */ - retval = fprintf(fp, "["); - if (retval == EOF) goto failure; - for (i = 0; i < n; i++) { - if (onames == NULL) { - retval = fprintf(fp, "f%d", i); - } else { - retval = fprintf(fp, "%s", onames[i]); - } - retval = fprintf(fp, "%s", i == n-1 ? "" : " "); - if (retval == EOF) goto failure; - } - retval = fprintf(fp, "]\n"); - if (retval == EOF) goto failure; - - st_free_table(visited); - return(1); - -failure: - if (sorted != NULL) FREE(sorted); - if (support != NULL) Cudd_RecursiveDeref(dd,support); - if (visited != NULL) st_free_table(visited); - return(0); - -} /* end of Cudd_DumpDDcal */ - - -/**Function******************************************************************** - - Synopsis [Writes factored forms representing the argument BDDs.] - - Description [Writes factored forms representing the argument BDDs. - The format of the factored form is the one used in the genlib files - for technology mapping in sis. It returns 1 in case of success; 0 - otherwise (e.g., file system full). Cudd_DumpFactoredForm does not - close the file: This is the caller responsibility. Caution must be - exercised because a factored form may be exponentially larger than - the argument BDD. If the argument inames is non-null, it is assumed - to hold the pointers to the names of the inputs. Similarly for - onames.] - - SideEffects [None] - - SeeAlso [Cudd_DumpDot Cudd_PrintDebug Cudd_DumpBlif Cudd_DumpDaVinci - Cudd_DumpDDcal] - -******************************************************************************/ -int -Cudd_DumpFactoredForm( - DdManager * dd /* manager */, - int n /* number of output nodes to be dumped */, - DdNode ** f /* array of output nodes to be dumped */, - char ** inames /* array of input names (or NULL) */, - char ** onames /* array of output names (or NULL) */, - FILE * fp /* pointer to the dump file */) -{ - int retval; - int i; - - /* Call the function that really gets the job done. */ - for (i = 0; i < n; i++) { - if (onames == NULL) { - retval = fprintf(fp, "f%d = ", i); - } else { - retval = fprintf(fp, "%s = ", onames[i]); - } - if (retval == EOF) return(0); - if (f[i] == DD_ONE(dd)) { - retval = fprintf(fp, "CONST1"); - if (retval == EOF) return(0); - } else if (f[i] == Cudd_Not(DD_ONE(dd)) || f[i] == DD_ZERO(dd)) { - retval = fprintf(fp, "CONST0"); - if (retval == EOF) return(0); - } else { - retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? "!(" : ""); - if (retval == EOF) return(0); - retval = ddDoDumpFactoredForm(dd,Cudd_Regular(f[i]),fp,inames); - if (retval == 0) return(0); - retval = fprintf(fp, "%s", Cudd_IsComplement(f[i]) ? ")" : ""); - if (retval == EOF) return(0); - } - retval = fprintf(fp, "%s", i == n-1 ? "" : "\n"); - if (retval == EOF) return(0); - } - - return(1); - -} /* end of Cudd_DumpFactoredForm */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_DumpBlif.] - - Description [Performs the recursive step of Cudd_DumpBlif. Traverses - the BDD f and writes a multiplexer-network description to the file - pointed by fp in blif format. f is assumed to be a regular pointer - and ddDoDumpBlif guarantees this assumption in the recursive calls.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddDoDumpBlif( - DdManager * dd, - DdNode * f, - FILE * fp, - st_table * visited, - char ** names) -{ - DdNode *T, *E; - int retval; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); -#endif - - /* If already visited, nothing to do. */ - if (st_is_member(visited, (char *) f) == 1) - return(1); - - /* Check for abnormal condition that should never happen. */ - if (f == NULL) - return(0); - - /* Mark node as visited. */ - if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) - return(0); - - /* Check for special case: If constant node, generate constant 1. */ - if (f == DD_ONE(dd)) { -#if SIZEOF_VOID_P == 8 - retval = fprintf(fp, ".names %lx\n1\n",(unsigned long) f / (unsigned long) sizeof(DdNode)); -#else - retval = fprintf(fp, ".names %x\n1\n",(unsigned) f / (unsigned) sizeof(DdNode)); -#endif - if (retval == EOF) { - return(0); - } else { - return(1); - } - } - - /* Check whether this is an ADD. We deal with 0-1 ADDs, but not - ** with the general case. - */ - if (f == DD_ZERO(dd)) { -#if SIZEOF_VOID_P == 8 - retval = fprintf(fp, ".names %lx\n",(unsigned long) f / (unsigned long) sizeof(DdNode)); -#else - retval = fprintf(fp, ".names %x\n",(unsigned) f / (unsigned) sizeof(DdNode)); -#endif - if (retval == EOF) { - return(0); - } else { - return(1); - } - } - if (cuddIsConstant(f)) - return(0); - - /* Recursive calls. */ - T = cuddT(f); - retval = ddDoDumpBlif(dd,T,fp,visited,names); - if (retval != 1) return(retval); - E = Cudd_Regular(cuddE(f)); - retval = ddDoDumpBlif(dd,E,fp,visited,names); - if (retval != 1) return(retval); - - /* Write multiplexer taking complement arc into account. */ - if (names != NULL) { - retval = fprintf(fp,".names %s", names[f->index]); - } else { - retval = fprintf(fp,".names %d", f->index); - } - if (retval == EOF) - return(0); - -#if SIZEOF_VOID_P == 8 - if (Cudd_IsComplement(cuddE(f))) { - retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-0 1\n", - (unsigned long) T / (unsigned long) sizeof(DdNode), - (unsigned long) E / (unsigned long) sizeof(DdNode), - (unsigned long) f / (unsigned long) sizeof(DdNode)); - } else { - retval = fprintf(fp," %lx %lx %lx\n11- 1\n0-1 1\n", - (unsigned long) T / (unsigned long) sizeof(DdNode), - (unsigned long) E / (unsigned long) sizeof(DdNode), - (unsigned long) f / (unsigned long) sizeof(DdNode)); - } -#else - if (Cudd_IsComplement(cuddE(f))) { - retval = fprintf(fp," %x %x %x\n11- 1\n0-0 1\n", - (unsigned) T / (unsigned) sizeof(DdNode), - (unsigned) E / (unsigned) sizeof(DdNode), - (unsigned) f / (unsigned) sizeof(DdNode)); - } else { - retval = fprintf(fp," %x %x %x\n11- 1\n0-1 1\n", - (unsigned) T / (unsigned) sizeof(DdNode), - (unsigned) E / (unsigned) sizeof(DdNode), - (unsigned) f / (unsigned) sizeof(DdNode)); - } -#endif - if (retval == EOF) { - return(0); - } else { - return(1); - } - -} /* end of ddDoDumpBlif */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_DumpDaVinci.] - - Description [Performs the recursive step of Cudd_DumpDaVinci. Traverses - the BDD f and writes a term expression to the file - pointed by fp in daVinci format. f is assumed to be a regular pointer - and ddDoDumpDaVinci guarantees this assumption in the recursive calls.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddDoDumpDaVinci( - DdManager * dd, - DdNode * f, - FILE * fp, - st_table * visited, - char ** names, - long mask) -{ - DdNode *T, *E; - int retval; - long id; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); -#endif - - id = ((long) f & mask) / sizeof(DdNode); - - /* If already visited, insert a reference. */ - if (st_is_member(visited, (char *) f) == 1) { - retval = fprintf(fp,"r(\"%lx\")", id); - if (retval == EOF) { - return(0); - } else { - return(1); - } - } - - /* Check for abnormal condition that should never happen. */ - if (f == NULL) - return(0); - - /* Mark node as visited. */ - if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) - return(0); - - /* Check for special case: If constant node, generate constant 1. */ - if (Cudd_IsConstant(f)) { - retval = fprintf(fp, "l(\"%lx\",n(\"constant\",[a(\"OBJECT\",\"%g\")],[]))", id, cuddV(f)); - if (retval == EOF) { - return(0); - } else { - return(1); - } - } - - /* Recursive calls. */ - if (names != NULL) { - retval = fprintf(fp, - "l(\"%lx\",n(\"internal\",[a(\"OBJECT\",\"%s\"),", - id, names[f->index]); - } else { - retval = fprintf(fp, - "l(\"%lx\",n(\"internal\",[a(\"OBJECT\",\"%d\"),", - id, f->index); - } - retval = fprintf(fp, "a(\"_GO\",\"ellipse\")],[e(\"then\",[a(\"EDGECOLOR\",\"blue\"),a(\"_DIR\",\"none\")],"); - if (retval == EOF) return(0); - T = cuddT(f); - retval = ddDoDumpDaVinci(dd,T,fp,visited,names,mask); - if (retval != 1) return(retval); - retval = fprintf(fp, "),e(\"else\",[a(\"EDGECOLOR\",\"%s\"),a(\"_DIR\",\"none\")],", - Cudd_IsComplement(cuddE(f)) ? "red" : "green"); - if (retval == EOF) return(0); - E = Cudd_Regular(cuddE(f)); - retval = ddDoDumpDaVinci(dd,E,fp,visited,names,mask); - if (retval != 1) return(retval); - - retval = fprintf(fp,")]))"); - if (retval == EOF) { - return(0); - } else { - return(1); - } - -} /* end of ddDoDumpDaVinci */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_DumpDDcal.] - - Description [Performs the recursive step of Cudd_DumpDDcal. Traverses - the BDD f and writes a line for each node to the file - pointed by fp in DDcal format. f is assumed to be a regular pointer - and ddDoDumpDDcal guarantees this assumption in the recursive calls.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddDoDumpDDcal( - DdManager * dd, - DdNode * f, - FILE * fp, - st_table * visited, - char ** names, - long mask) -{ - DdNode *T, *E; - int retval; - long id, idT, idE; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); -#endif - - id = ((long) f & mask) / sizeof(DdNode); - - /* If already visited, do nothing. */ - if (st_is_member(visited, (char *) f) == 1) { - return(1); - } - - /* Check for abnormal condition that should never happen. */ - if (f == NULL) - return(0); - - /* Mark node as visited. */ - if (st_insert(visited, (char *) f, NULL) == ST_OUT_OF_MEM) - return(0); - - /* Check for special case: If constant node, assign constant. */ - if (Cudd_IsConstant(f)) { - if (f != DD_ONE(dd) && f != DD_ZERO(dd)) - return(0); - retval = fprintf(fp, "n%lx = %g\n", id, cuddV(f)); - if (retval == EOF) { - return(0); - } else { - return(1); - } - } - - /* Recursive calls. */ - T = cuddT(f); - retval = ddDoDumpDDcal(dd,T,fp,visited,names,mask); - if (retval != 1) return(retval); - E = Cudd_Regular(cuddE(f)); - retval = ddDoDumpDDcal(dd,E,fp,visited,names,mask); - if (retval != 1) return(retval); - idT = ((long) T & mask) / sizeof(DdNode); - idE = ((long) E & mask) / sizeof(DdNode); - if (names != NULL) { - retval = fprintf(fp, "n%lx = %s * n%lx + %s' * n%lx%s\n", - id, names[f->index], idT, names[f->index], - idE, Cudd_IsComplement(cuddE(f)) ? "'" : ""); - } else { - retval = fprintf(fp, "n%lx = v%d * n%lx + v%d' * n%lx%s\n", - id, f->index, idT, f->index, - idE, Cudd_IsComplement(cuddE(f)) ? "'" : ""); - } - if (retval == EOF) { - return(0); - } else { - return(1); - } - -} /* end of ddDoDumpDDcal */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_DumpFactoredForm.] - - Description [Performs the recursive step of - Cudd_DumpFactoredForm. Traverses the BDD f and writes a factored - form for each node to the file pointed by fp in terms of the - factored forms of the children. Constants are propagated, and - absorption is applied. f is assumed to be a regular pointer and - ddDoDumpFActoredForm guarantees this assumption in the recursive - calls.] - - SideEffects [None] - - SeeAlso [Cudd_DumpFactoredForm] - -******************************************************************************/ -static int -ddDoDumpFactoredForm( - DdManager * dd, - DdNode * f, - FILE * fp, - char ** names) -{ - DdNode *T, *E; - int retval; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); - assert(!Cudd_IsConstant(f)); -#endif - - /* Check for abnormal condition that should never happen. */ - if (f == NULL) - return(0); - - /* Recursive calls. */ - T = cuddT(f); - E = cuddE(f); - if (T != DD_ZERO(dd)) { - if (E != DD_ONE(dd)) { - if (names != NULL) { - retval = fprintf(fp, "%s", names[f->index]); - } else { - retval = fprintf(fp, "x%d", f->index); - } - if (retval == EOF) return(0); - } - if (T != DD_ONE(dd)) { - retval = fprintf(fp, "%s(", E != DD_ONE(dd) ? " * " : ""); - if (retval == EOF) return(0); - retval = ddDoDumpFactoredForm(dd,T,fp,names); - if (retval != 1) return(retval); - retval = fprintf(fp, ")"); - if (retval == EOF) return(0); - } - if (E == Cudd_Not(DD_ONE(dd)) || E == DD_ZERO(dd)) return(1); - retval = fprintf(fp, " + "); - if (retval == EOF) return(0); - } - E = Cudd_Regular(E); - if (T != DD_ONE(dd)) { - if (names != NULL) { - retval = fprintf(fp, "!%s", names[f->index]); - } else { - retval = fprintf(fp, "!x%d", f->index); - } - if (retval == EOF) return(0); - } - if (E != DD_ONE(dd)) { - retval = fprintf(fp, "%s%s(", T != DD_ONE(dd) ? " * " : "", - E != cuddE(f) ? "!" : ""); - if (retval == EOF) return(0); - retval = ddDoDumpFactoredForm(dd,E,fp,names); - if (retval != 1) return(retval); - retval = fprintf(fp, ")"); - if (retval == EOF) return(0); - } - return(1); - -} /* end of ddDoDumpFactoredForm */ - diff --git a/src/bdd/cudd/cuddGenCof.c b/src/bdd/cudd/cuddGenCof.c deleted file mode 100644 index 142ee27e..00000000 --- a/src/bdd/cudd/cuddGenCof.c +++ /dev/null @@ -1,1968 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddGenCof.c] - - PackageName [cudd] - - Synopsis [Generalized cofactors for BDDs and ADDs.] - - Description [External procedures included in this module: -
              -
            • Cudd_bddConstrain() -
            • Cudd_bddRestrict() -
            • Cudd_addConstrain() -
            • Cudd_bddConstrainDecomp() -
            • Cudd_addRestrict() -
            • Cudd_bddCharToVect() -
            • Cudd_bddLICompaction() -
            • Cudd_bddSqueeze() -
            • Cudd_SubsetCompress() -
            • Cudd_SupersetCompress() -
            - Internal procedures included in this module: -
              -
            • cuddBddConstrainRecur() -
            • cuddBddRestrictRecur() -
            • cuddAddConstrainRecur() -
            • cuddAddRestrictRecur() -
            • cuddBddLICompaction() -
            - Static procedures included in this module: -
              -
            • cuddBddConstrainDecomp() -
            • cuddBddCharToVect() -
            • cuddBddLICMarkEdges() -
            • cuddBddLICBuildResult() -
            • cuddBddSqueeze() -
            - ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/* Codes for edge markings in Cudd_bddLICompaction. The codes are defined -** so that they can be bitwise ORed to implement the code priority scheme. -*/ -#define DD_LIC_DC 0 -#define DD_LIC_1 1 -#define DD_LIC_0 2 -#define DD_LIC_NL 3 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/* Key for the cache used in the edge marking phase. */ -typedef struct MarkCacheKey { - DdNode *f; - DdNode *c; -} MarkCacheKey; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddGenCof.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int cuddBddConstrainDecomp ARGS((DdManager *dd, DdNode *f, DdNode **decomp)); -static DdNode * cuddBddCharToVect ARGS((DdManager *dd, DdNode *f, DdNode *x)); -static int cuddBddLICMarkEdges ARGS((DdManager *dd, DdNode *f, DdNode *c, st_table *table, st_table *cache)); -static DdNode * cuddBddLICBuildResult ARGS((DdManager *dd, DdNode *f, st_table *cache, st_table *table)); -static int MarkCacheHash ARGS((char *ptr, int modulus)); -static int MarkCacheCompare ARGS((const char *ptr1, const char *ptr2)); -static enum st_retval MarkCacheCleanUp ARGS((char *key, char *value, char *arg)); -static DdNode * cuddBddSqueeze ARGS((DdManager *dd, DdNode *l, DdNode *u)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes f constrain c.] - - Description [Computes f constrain c (f @ c). - Uses a canonical form: (f' @ c) = ( f @ c)'. (Note: this is not true - for c.) List of special cases: -
              -
            • f @ 0 = 0 -
            • f @ 1 = f -
            • 0 @ c = 0 -
            • 1 @ c = 1 -
            • f @ f = 1 -
            • f @ f'= 0 -
            - Returns a pointer to the result if successful; NULL otherwise. Note that if - F=(f1,...,fn) and reordering takes place while computing F @ c, then the - image restriction property (Img(F,c) = Img(F @ c)) is lost.] - - SideEffects [None] - - SeeAlso [Cudd_bddRestrict Cudd_addConstrain] - -******************************************************************************/ -DdNode * -Cudd_bddConstrain( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddConstrainRecur(dd,f,c); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddConstrain */ - - -/**Function******************************************************************** - - Synopsis [BDD restrict according to Coudert and Madre's algorithm - (ICCAD90).] - - Description [BDD restrict according to Coudert and Madre's algorithm - (ICCAD90). Returns the restricted BDD if successful; otherwise NULL. - If application of restrict results in a BDD larger than the input - BDD, the input BDD is returned.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain Cudd_addRestrict] - -******************************************************************************/ -DdNode * -Cudd_bddRestrict( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *suppF, *suppC, *commonSupport; - DdNode *cplus, *res; - int retval; - int sizeF, sizeRes; - - /* Check terminal cases here to avoid computing supports in trivial cases. - ** This also allows us notto check later for the case c == 0, in which - ** there is no common support. */ - if (c == Cudd_Not(DD_ONE(dd))) return(Cudd_Not(DD_ONE(dd))); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(DD_ONE(dd)); - if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd))); - - /* Check if supports intersect. */ - retval = Cudd_ClassifySupport(dd,f,c,&commonSupport,&suppF,&suppC); - if (retval == 0) { - return(NULL); - } - cuddRef(commonSupport); cuddRef(suppF); cuddRef(suppC); - Cudd_IterDerefBdd(dd,suppF); - - if (commonSupport == DD_ONE(dd)) { - Cudd_IterDerefBdd(dd,commonSupport); - Cudd_IterDerefBdd(dd,suppC); - return(f); - } - Cudd_IterDerefBdd(dd,commonSupport); - - /* Abstract from c the variables that do not appear in f. */ - cplus = Cudd_bddExistAbstract(dd, c, suppC); - if (cplus == NULL) { - Cudd_IterDerefBdd(dd,suppC); - return(NULL); - } - cuddRef(cplus); - Cudd_IterDerefBdd(dd,suppC); - - do { - dd->reordered = 0; - res = cuddBddRestrictRecur(dd, f, cplus); - } while (dd->reordered == 1); - if (res == NULL) { - Cudd_IterDerefBdd(dd,cplus); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(dd,cplus); - /* Make restric safe by returning the smaller of the input and the - ** result. */ - sizeF = Cudd_DagSize(f); - sizeRes = Cudd_DagSize(res); - if (sizeF <= sizeRes) { - Cudd_IterDerefBdd(dd, res); - return(f); - } else { - cuddDeref(res); - return(res); - } - -} /* end of Cudd_bddRestrict */ - - -/**Function******************************************************************** - - Synopsis [Computes f constrain c for ADDs.] - - Description [Computes f constrain c (f @ c), for f an ADD and c a 0-1 - ADD. List of special cases: -
              -
            • F @ 0 = 0 -
            • F @ 1 = F -
            • 0 @ c = 0 -
            • 1 @ c = 1 -
            • F @ F = 1 -
            - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain] - -******************************************************************************/ -DdNode * -Cudd_addConstrain( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddConstrainRecur(dd,f,c); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addConstrain */ - - -/**Function******************************************************************** - - Synopsis [BDD conjunctive decomposition as in McMillan's CAV96 paper.] - - Description [BDD conjunctive decomposition as in McMillan's CAV96 - paper. The decomposition is canonical only for a given variable - order. If canonicity is required, variable ordering must be disabled - after the decomposition has been computed. Returns an array with one - entry for each BDD variable in the manager if successful; otherwise - NULL. The components of the solution have their reference counts - already incremented (unlike the results of most other functions in - the package.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain Cudd_bddExistAbstract] - -******************************************************************************/ -DdNode ** -Cudd_bddConstrainDecomp( - DdManager * dd, - DdNode * f) -{ - DdNode **decomp; - int res; - int i; - - /* Create an initialize decomposition array. */ - decomp = ALLOC(DdNode *,dd->size); - if (decomp == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < dd->size; i++) { - decomp[i] = NULL; - } - do { - dd->reordered = 0; - /* Clean up the decomposition array in case reordering took place. */ - for (i = 0; i < dd->size; i++) { - if (decomp[i] != NULL) { - Cudd_IterDerefBdd(dd, decomp[i]); - decomp[i] = NULL; - } - } - res = cuddBddConstrainDecomp(dd,f,decomp); - } while (dd->reordered == 1); - if (res == 0) { - FREE(decomp); - return(NULL); - } - /* Missing components are constant ones. */ - for (i = 0; i < dd->size; i++) { - if (decomp[i] == NULL) { - decomp[i] = DD_ONE(dd); - cuddRef(decomp[i]); - } - } - return(decomp); - -} /* end of Cudd_bddConstrainDecomp */ - - -/**Function******************************************************************** - - Synopsis [ADD restrict according to Coudert and Madre's algorithm - (ICCAD90).] - - Description [ADD restrict according to Coudert and Madre's algorithm - (ICCAD90). Returns the restricted ADD if successful; otherwise NULL. - If application of restrict results in an ADD larger than the input - ADD, the input ADD is returned.] - - SideEffects [None] - - SeeAlso [Cudd_addConstrain Cudd_bddRestrict] - -******************************************************************************/ -DdNode * -Cudd_addRestrict( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *supp_f, *supp_c; - DdNode *res, *commonSupport; - int intersection; - int sizeF, sizeRes; - - /* Check if supports intersect. */ - supp_f = Cudd_Support(dd, f); - if (supp_f == NULL) { - return(NULL); - } - cuddRef(supp_f); - supp_c = Cudd_Support(dd, c); - if (supp_c == NULL) { - Cudd_RecursiveDeref(dd,supp_f); - return(NULL); - } - cuddRef(supp_c); - commonSupport = Cudd_bddLiteralSetIntersection(dd, supp_f, supp_c); - if (commonSupport == NULL) { - Cudd_RecursiveDeref(dd,supp_f); - Cudd_RecursiveDeref(dd,supp_c); - return(NULL); - } - cuddRef(commonSupport); - Cudd_RecursiveDeref(dd,supp_f); - Cudd_RecursiveDeref(dd,supp_c); - intersection = commonSupport != DD_ONE(dd); - Cudd_RecursiveDeref(dd,commonSupport); - - if (intersection) { - do { - dd->reordered = 0; - res = cuddAddRestrictRecur(dd, f, c); - } while (dd->reordered == 1); - sizeF = Cudd_DagSize(f); - sizeRes = Cudd_DagSize(res); - if (sizeF <= sizeRes) { - cuddRef(res); - Cudd_RecursiveDeref(dd, res); - return(f); - } else { - return(res); - } - } else { - return(f); - } - -} /* end of Cudd_addRestrict */ - - -/**Function******************************************************************** - - Synopsis [Computes a vector whose image equals a non-zero function.] - - Description [Computes a vector of BDDs whose image equals a non-zero - function. - The result depends on the variable order. The i-th component of the vector - depends only on the first i variables in the order. Each BDD in the vector - is not larger than the BDD of the given characteristic function. This - function is based on the description of char-to-vect in "Verification of - Sequential Machines Using Boolean Functional Vectors" by O. Coudert, C. - Berthet and J. C. Madre. - Returns a pointer to an array containing the result if successful; NULL - otherwise. The size of the array equals the number of variables in the - manager. The components of the solution have their reference counts - already incremented (unlike the results of most other functions in - the package.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain] - -******************************************************************************/ -DdNode ** -Cudd_bddCharToVect( - DdManager * dd, - DdNode * f) -{ - int i, j; - DdNode **vect; - DdNode *res = NULL; - - if (f == Cudd_Not(DD_ONE(dd))) return(NULL); - - vect = ALLOC(DdNode *, dd->size); - if (vect == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - do { - dd->reordered = 0; - for (i = 0; i < dd->size; i++) { - res = cuddBddCharToVect(dd,f,dd->vars[dd->invperm[i]]); - if (res == NULL) { - /* Clean up the vector array in case reordering took place. */ - for (j = 0; j < i; j++) { - Cudd_IterDerefBdd(dd, vect[dd->invperm[j]]); - } - break; - } - cuddRef(res); - vect[dd->invperm[i]] = res; - } - } while (dd->reordered == 1); - if (res == NULL) { - FREE(vect); - return(NULL); - } - return(vect); - -} /* end of Cudd_bddCharToVect */ - - -/**Function******************************************************************** - - Synopsis [Performs safe minimization of a BDD.] - - Description [Performs safe minimization of a BDD. Given the BDD - f of a function to be minimized and a BDD - c representing the care set, Cudd_bddLICompaction - produces the BDD of a function that agrees with f - wherever c is 1. Safe minimization means that the size - of the result is guaranteed not to exceed the size of - f. This function is based on the DAC97 paper by Hong et - al.. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddRestrict] - -******************************************************************************/ -DdNode * -Cudd_bddLICompaction( - DdManager * dd /* manager */, - DdNode * f /* function to be minimized */, - DdNode * c /* constraint (care set) */) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddLICompaction(dd,f,c); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddLICompaction */ - - -/**Function******************************************************************** - - Synopsis [Finds a small BDD in a function interval.] - - Description [Finds a small BDD in a function interval. Given BDDs - l and u, representing the lower bound and - upper bound of a function interval, Cudd_bddSqueeze produces the BDD - of a function within the interval with a small BDD. Returns a - pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction] - -******************************************************************************/ -DdNode * -Cudd_bddSqueeze( - DdManager * dd /* manager */, - DdNode * l /* lower bound */, - DdNode * u /* upper bound */) -{ - DdNode *res; - int sizeRes, sizeL, sizeU; - - do { - dd->reordered = 0; - res = cuddBddSqueeze(dd,l,u); - } while (dd->reordered == 1); - if (res == NULL) return(NULL); - /* We now compare the result with the bounds and return the smallest. - ** We first compare to u, so that in case l == 0 and u == 1, we return - ** 0 as in other minimization algorithms. */ - sizeRes = Cudd_DagSize(res); - sizeU = Cudd_DagSize(u); - if (sizeU <= sizeRes) { - cuddRef(res); - Cudd_IterDerefBdd(dd,res); - res = u; - sizeRes = sizeU; - } - sizeL = Cudd_DagSize(l); - if (sizeL <= sizeRes) { - cuddRef(res); - Cudd_IterDerefBdd(dd,res); - res = l; - sizeRes = sizeL; - } - return(res); - -} /* end of Cudd_bddSqueeze */ - - -/**Function******************************************************************** - - Synopsis [Finds a small BDD that agrees with f over - c.] - - Description [Finds a small BDD that agrees with f over - c. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction Cudd_bddSqueeze] - -******************************************************************************/ -DdNode * -Cudd_bddMinimize( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *cplus, *res; - - if (c == Cudd_Not(DD_ONE(dd))) return(c); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(DD_ONE(dd)); - if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd))); - - cplus = Cudd_RemapOverApprox(dd,c,0,0,1.0); - if (cplus == NULL) return(NULL); - cuddRef(cplus); - res = Cudd_bddLICompaction(dd,f,cplus); - if (res == NULL) { - Cudd_IterDerefBdd(dd,cplus); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(dd,cplus); - cuddDeref(res); - return(res); - -} /* end of Cudd_bddMinimize */ - - -/**Function******************************************************************** - - Synopsis [Find a dense subset of BDD f.] - - Description [Finds a dense subset of BDD f. Density is - the ratio of number of minterms to number of nodes. Uses several - techniques in series. It is more expensive than other subsetting - procedures, but often produces better results. See - Cudd_SubsetShortPaths for a description of the threshold and nvars - parameters. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetRemap Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch - Cudd_bddSqueeze] - -******************************************************************************/ -DdNode * -Cudd_SubsetCompress( - DdManager * dd /* manager */, - DdNode * f /* BDD whose subset is sought */, - int nvars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the subset */) -{ - DdNode *res, *tmp1, *tmp2; - - tmp1 = Cudd_SubsetShortPaths(dd, f, nvars, threshold, 0); - if (tmp1 == NULL) return(NULL); - cuddRef(tmp1); - tmp2 = Cudd_RemapUnderApprox(dd,tmp1,nvars,0,1.0); - if (tmp2 == NULL) { - Cudd_IterDerefBdd(dd,tmp1); - return(NULL); - } - cuddRef(tmp2); - Cudd_IterDerefBdd(dd,tmp1); - res = Cudd_bddSqueeze(dd,tmp2,f); - if (res == NULL) { - Cudd_IterDerefBdd(dd,tmp2); - return(NULL); - } - cuddRef(res); - Cudd_IterDerefBdd(dd,tmp2); - cuddDeref(res); - return(res); - -} /* end of Cudd_SubsetCompress */ - - -/**Function******************************************************************** - - Synopsis [Find a dense superset of BDD f.] - - Description [Finds a dense superset of BDD f. Density is - the ratio of number of minterms to number of nodes. Uses several - techniques in series. It is more expensive than other supersetting - procedures, but often produces better results. See - Cudd_SupersetShortPaths for a description of the threshold and nvars - parameters. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetCompress Cudd_SupersetRemap Cudd_SupersetShortPaths - Cudd_SupersetHeavyBranch Cudd_bddSqueeze] - -******************************************************************************/ -DdNode * -Cudd_SupersetCompress( - DdManager * dd /* manager */, - DdNode * f /* BDD whose superset is sought */, - int nvars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the superset */) -{ - DdNode *subset; - - subset = Cudd_SubsetCompress(dd, Cudd_Not(f),nvars,threshold); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_SupersetCompress */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddConstrain.] - - Description [Performs the recursive step of Cudd_bddConstrain. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrain] - -******************************************************************************/ -DdNode * -cuddBddConstrainRecur( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r; - DdNode *one, *zero; - unsigned int topf, topc; - int index; - int comple = 0; - - statLine(dd); - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Trivial cases. */ - if (c == one) return(f); - if (c == zero) return(zero); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(one); - if (f == Cudd_Not(c)) return(zero); - - /* Make canonical to increase the utilization of the cache. */ - if (Cudd_IsComplement(f)) { - f = Cudd_Not(f); - comple = 1; - } - /* Now f is a regular pointer to a non-constant node; c is also - ** non-constant, but may be complemented. - */ - - /* Check the cache. */ - r = cuddCacheLookup2(dd, Cudd_bddConstrain, f, c); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - /* Recursive step. */ - topf = dd->perm[f->index]; - topc = dd->perm[Cudd_Regular(c)->index]; - if (topf <= topc) { - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - } else { - index = Cudd_Regular(c)->index; - Fv = Fnv = f; - } - if (topc <= topf) { - Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); - if (Cudd_IsComplement(c)) { - Cv = Cudd_Not(Cv); - Cnv = Cudd_Not(Cnv); - } - } else { - Cv = Cnv = c; - } - - if (!Cudd_IsConstant(Cv)) { - t = cuddBddConstrainRecur(dd, Fv, Cv); - if (t == NULL) - return(NULL); - } else if (Cv == one) { - t = Fv; - } else { /* Cv == zero: return Fnv @ Cnv */ - if (Cnv == one) { - r = Fnv; - } else { - r = cuddBddConstrainRecur(dd, Fnv, Cnv); - if (r == NULL) - return(NULL); - } - return(Cudd_NotCond(r,comple)); - } - cuddRef(t); - - if (!Cudd_IsConstant(Cnv)) { - e = cuddBddConstrainRecur(dd, Fnv, Cnv); - if (e == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } else if (Cnv == one) { - e = Fnv; - } else { /* Cnv == zero: return Fv @ Cv previously computed */ - cuddDeref(t); - return(Cudd_NotCond(t,comple)); - } - cuddRef(e); - - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert2(dd, Cudd_bddConstrain, f, c, r); - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddConstrainRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddRestrict.] - - Description [Performs the recursive step of Cudd_bddRestrict. - Returns the restricted BDD if successful; otherwise NULL.] - - SideEffects [None] - - SeeAlso [Cudd_bddRestrict] - -******************************************************************************/ -DdNode * -cuddBddRestrictRecur( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero; - unsigned int topf, topc; - int index; - int comple = 0; - - statLine(dd); - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Trivial cases */ - if (c == one) return(f); - if (c == zero) return(zero); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(one); - if (f == Cudd_Not(c)) return(zero); - - /* Make canonical to increase the utilization of the cache. */ - if (Cudd_IsComplement(f)) { - f = Cudd_Not(f); - comple = 1; - } - /* Now f is a regular pointer to a non-constant node; c is also - ** non-constant, but may be complemented. - */ - - /* Check the cache. */ - r = cuddCacheLookup2(dd, Cudd_bddRestrict, f, c); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - topf = dd->perm[f->index]; - topc = dd->perm[Cudd_Regular(c)->index]; - - if (topc < topf) { /* abstract top variable from c */ - DdNode *d, *s1, *s2; - - /* Find complements of cofactors of c. */ - if (Cudd_IsComplement(c)) { - s1 = cuddT(Cudd_Regular(c)); - s2 = cuddE(Cudd_Regular(c)); - } else { - s1 = Cudd_Not(cuddT(c)); - s2 = Cudd_Not(cuddE(c)); - } - /* Take the OR by applying DeMorgan. */ - d = cuddBddAndRecur(dd, s1, s2); - if (d == NULL) return(NULL); - d = Cudd_Not(d); - cuddRef(d); - r = cuddBddRestrictRecur(dd, f, d); - if (r == NULL) { - Cudd_IterDerefBdd(dd, d); - return(NULL); - } - cuddRef(r); - Cudd_IterDerefBdd(dd, d); - cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r); - cuddDeref(r); - return(Cudd_NotCond(r,comple)); - } - - /* Recursive step. Here topf <= topc. */ - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - if (topc == topf) { - Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); - if (Cudd_IsComplement(c)) { - Cv = Cudd_Not(Cv); - Cnv = Cudd_Not(Cnv); - } - } else { - Cv = Cnv = c; - } - - if (!Cudd_IsConstant(Cv)) { - t = cuddBddRestrictRecur(dd, Fv, Cv); - if (t == NULL) return(NULL); - } else if (Cv == one) { - t = Fv; - } else { /* Cv == zero: return(Fnv @ Cnv) */ - if (Cnv == one) { - r = Fnv; - } else { - r = cuddBddRestrictRecur(dd, Fnv, Cnv); - if (r == NULL) return(NULL); - } - return(Cudd_NotCond(r,comple)); - } - cuddRef(t); - - if (!Cudd_IsConstant(Cnv)) { - e = cuddBddRestrictRecur(dd, Fnv, Cnv); - if (e == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } else if (Cnv == one) { - e = Fnv; - } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ - cuddDeref(t); - return(Cudd_NotCond(t,comple)); - } - cuddRef(e); - - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r); - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddRestrictRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addConstrain.] - - Description [Performs the recursive step of Cudd_addConstrain. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addConstrain] - -******************************************************************************/ -DdNode * -cuddAddConstrainRecur( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r; - DdNode *one, *zero; - unsigned int topf, topc; - int index; - - statLine(dd); - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - /* Trivial cases. */ - if (c == one) return(f); - if (c == zero) return(zero); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(one); - - /* Now f and c are non-constant. */ - - /* Check the cache. */ - r = cuddCacheLookup2(dd, Cudd_addConstrain, f, c); - if (r != NULL) { - return(r); - } - - /* Recursive step. */ - topf = dd->perm[f->index]; - topc = dd->perm[c->index]; - if (topf <= topc) { - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - } else { - index = c->index; - Fv = Fnv = f; - } - if (topc <= topf) { - Cv = cuddT(c); Cnv = cuddE(c); - } else { - Cv = Cnv = c; - } - - if (!Cudd_IsConstant(Cv)) { - t = cuddAddConstrainRecur(dd, Fv, Cv); - if (t == NULL) - return(NULL); - } else if (Cv == one) { - t = Fv; - } else { /* Cv == zero: return Fnv @ Cnv */ - if (Cnv == one) { - r = Fnv; - } else { - r = cuddAddConstrainRecur(dd, Fnv, Cnv); - if (r == NULL) - return(NULL); - } - return(r); - } - cuddRef(t); - - if (!Cudd_IsConstant(Cnv)) { - e = cuddAddConstrainRecur(dd, Fnv, Cnv); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - } else if (Cnv == one) { - e = Fnv; - } else { /* Cnv == zero: return Fv @ Cv previously computed */ - cuddDeref(t); - return(t); - } - cuddRef(e); - - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert2(dd, Cudd_addConstrain, f, c, r); - return(r); - -} /* end of cuddAddConstrainRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addRestrict.] - - Description [Performs the recursive step of Cudd_addRestrict. - Returns the restricted ADD if successful; otherwise NULL.] - - SideEffects [None] - - SeeAlso [Cudd_addRestrict] - -******************************************************************************/ -DdNode * -cuddAddRestrictRecur( - DdManager * dd, - DdNode * f, - DdNode * c) -{ - DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero; - unsigned int topf, topc; - int index; - - statLine(dd); - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - /* Trivial cases */ - if (c == one) return(f); - if (c == zero) return(zero); - if (Cudd_IsConstant(f)) return(f); - if (f == c) return(one); - - /* Now f and c are non-constant. */ - - /* Check the cache. */ - r = cuddCacheLookup2(dd, Cudd_addRestrict, f, c); - if (r != NULL) { - return(r); - } - - topf = dd->perm[f->index]; - topc = dd->perm[c->index]; - - if (topc < topf) { /* abstract top variable from c */ - DdNode *d, *s1, *s2; - - /* Find cofactors of c. */ - s1 = cuddT(c); - s2 = cuddE(c); - /* Take the OR by applying DeMorgan. */ - d = cuddAddApplyRecur(dd, Cudd_addOr, s1, s2); - if (d == NULL) return(NULL); - cuddRef(d); - r = cuddAddRestrictRecur(dd, f, d); - if (r == NULL) { - Cudd_RecursiveDeref(dd, d); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDeref(dd, d); - cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r); - cuddDeref(r); - return(r); - } - - /* Recursive step. Here topf <= topc. */ - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - if (topc == topf) { - Cv = cuddT(c); Cnv = cuddE(c); - } else { - Cv = Cnv = c; - } - - if (!Cudd_IsConstant(Cv)) { - t = cuddAddRestrictRecur(dd, Fv, Cv); - if (t == NULL) return(NULL); - } else if (Cv == one) { - t = Fv; - } else { /* Cv == zero: return(Fnv @ Cnv) */ - if (Cnv == one) { - r = Fnv; - } else { - r = cuddAddRestrictRecur(dd, Fnv, Cnv); - if (r == NULL) return(NULL); - } - return(r); - } - cuddRef(t); - - if (!Cudd_IsConstant(Cnv)) { - e = cuddAddRestrictRecur(dd, Fnv, Cnv); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - } else if (Cnv == one) { - e = Fnv; - } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ - cuddDeref(t); - return(t); - } - cuddRef(e); - - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_RecursiveDeref(dd, e); - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - - cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r); - return(r); - -} /* end of cuddAddRestrictRecur */ - - - -/**Function******************************************************************** - - Synopsis [Performs safe minimization of a BDD.] - - Description [Performs safe minimization of a BDD. Given the BDD - f of a function to be minimized and a BDD - c representing the care set, Cudd_bddLICompaction - produces the BDD of a function that agrees with f - wherever c is 1. Safe minimization means that the size - of the result is guaranteed not to exceed the size of - f. This function is based on the DAC97 paper by Hong et - al.. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction] - -******************************************************************************/ -DdNode * -cuddBddLICompaction( - DdManager * dd /* manager */, - DdNode * f /* function to be minimized */, - DdNode * c /* constraint (care set) */) -{ - st_table *marktable, *markcache, *buildcache; - DdNode *res, *zero; - - zero = Cudd_Not(DD_ONE(dd)); - if (c == zero) return(zero); - - /* We need to use local caches for both steps of this operation. - ** The results of the edge marking step are only valid as long as the - ** edge markings themselves are available. However, the edge markings - ** are lost at the end of one invocation of Cudd_bddLICompaction. - ** Hence, the cache entries for the edge marking step must be - ** invalidated at the end of this function. - ** For the result of the building step we argue as follows. The result - ** for a node and a given constrain depends on the BDD in which the node - ** appears. Hence, the same node and constrain may give different results - ** in successive invocations. - */ - marktable = st_init_table(st_ptrcmp,st_ptrhash); - if (marktable == NULL) { - return(NULL); - } - markcache = st_init_table(MarkCacheCompare,MarkCacheHash); - if (markcache == NULL) { - st_free_table(marktable); - return(NULL); - } - if (cuddBddLICMarkEdges(dd,f,c,marktable,markcache) == CUDD_OUT_OF_MEM) { - st_foreach(markcache, MarkCacheCleanUp, NULL); - st_free_table(marktable); - st_free_table(markcache); - return(NULL); - } - st_foreach(markcache, MarkCacheCleanUp, NULL); - st_free_table(markcache); - buildcache = st_init_table(st_ptrcmp,st_ptrhash); - if (buildcache == NULL) { - st_free_table(marktable); - return(NULL); - } - res = cuddBddLICBuildResult(dd,f,buildcache,marktable); - st_free_table(buildcache); - st_free_table(marktable); - return(res); - -} /* end of cuddBddLICompaction */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddConstrainDecomp.] - - Description [Performs the recursive step of Cudd_bddConstrainDecomp. - Returns f super (i) if successful; otherwise NULL.] - - SideEffects [None] - - SeeAlso [Cudd_bddConstrainDecomp] - -******************************************************************************/ -static int -cuddBddConstrainDecomp( - DdManager * dd, - DdNode * f, - DdNode ** decomp) -{ - DdNode *F, *fv, *fvn; - DdNode *fAbs; - DdNode *result; - int ok; - - if (Cudd_IsConstant(f)) return(1); - /* Compute complements of cofactors. */ - F = Cudd_Regular(f); - fv = cuddT(F); - fvn = cuddE(F); - if (F == f) { - fv = Cudd_Not(fv); - fvn = Cudd_Not(fvn); - } - /* Compute abstraction of top variable. */ - fAbs = cuddBddAndRecur(dd, fv, fvn); - if (fAbs == NULL) { - return(0); - } - cuddRef(fAbs); - fAbs = Cudd_Not(fAbs); - /* Recursively find the next abstraction and the components of the - ** decomposition. */ - ok = cuddBddConstrainDecomp(dd, fAbs, decomp); - if (ok == 0) { - Cudd_IterDerefBdd(dd,fAbs); - return(0); - } - /* Compute the component of the decomposition corresponding to the - ** top variable and store it in the decomposition array. */ - result = cuddBddConstrainRecur(dd, f, fAbs); - if (result == NULL) { - Cudd_IterDerefBdd(dd,fAbs); - return(0); - } - cuddRef(result); - decomp[F->index] = result; - Cudd_IterDerefBdd(dd, fAbs); - return(1); - -} /* end of cuddBddConstrainDecomp */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddCharToVect.] - - Description [Performs the recursive step of Cudd_bddCharToVect. - This function maintains the invariant that f is non-zero. - Returns the i-th component of the vector if successful; otherwise NULL.] - - SideEffects [None] - - SeeAlso [Cudd_bddCharToVect] - -******************************************************************************/ -static DdNode * -cuddBddCharToVect( - DdManager * dd, - DdNode * f, - DdNode * x) -{ - unsigned int topf; - unsigned int level; - int comple; - - DdNode *one, *zero, *res, *F, *fT, *fE, *T, *E; - - statLine(dd); - /* Check the cache. */ - res = cuddCacheLookup2(dd, cuddBddCharToVect, f, x); - if (res != NULL) { - return(res); - } - - F = Cudd_Regular(f); - - topf = cuddI(dd,F->index); - level = dd->perm[x->index]; - - if (topf > level) return(x); - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - comple = F != f; - fT = Cudd_NotCond(cuddT(F),comple); - fE = Cudd_NotCond(cuddE(F),comple); - - if (topf == level) { - if (fT == zero) return(zero); - if (fE == zero) return(one); - return(x); - } - - /* Here topf < level. */ - if (fT == zero) return(cuddBddCharToVect(dd, fE, x)); - if (fE == zero) return(cuddBddCharToVect(dd, fT, x)); - - T = cuddBddCharToVect(dd, fT, x); - if (T == NULL) { - return(NULL); - } - cuddRef(T); - E = cuddBddCharToVect(dd, fE, x); - if (E == NULL) { - Cudd_IterDerefBdd(dd,T); - return(NULL); - } - cuddRef(E); - res = cuddBddIteRecur(dd, dd->vars[F->index], T, E); - if (res == NULL) { - Cudd_IterDerefBdd(dd,T); - Cudd_IterDerefBdd(dd,E); - return(NULL); - } - cuddDeref(T); - cuddDeref(E); - cuddCacheInsert2(dd, cuddBddCharToVect, f, x, res); - return(res); - -} /* end of cuddBddCharToVect */ - - -/**Function******************************************************************** - - Synopsis [Performs the edge marking step of Cudd_bddLICompaction.] - - Description [Performs the edge marking step of Cudd_bddLICompaction. - Returns the LUB of the markings of the two outgoing edges of f - if successful; otherwise CUDD_OUT_OF_MEM.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction cuddBddLICBuildResult] - -******************************************************************************/ -static int -cuddBddLICMarkEdges( - DdManager * dd, - DdNode * f, - DdNode * c, - st_table * table, - st_table * cache) -{ - DdNode *Fv, *Fnv, *Cv, *Cnv; - DdNode *one, *zero; - unsigned int topf, topc; - int index; - int comple; - int resT, resE, res, retval; - char **slot; - MarkCacheKey *key; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Terminal cases. */ - if (c == zero) return(DD_LIC_DC); - if (f == one) return(DD_LIC_1); - if (f == zero) return(DD_LIC_0); - - /* Make canonical to increase the utilization of the cache. */ - comple = Cudd_IsComplement(f); - f = Cudd_Regular(f); - /* Now f is a regular pointer to a non-constant node; c may be - ** constant, or it may be complemented. - */ - - /* Check the cache. */ - key = ALLOC(MarkCacheKey, 1); - if (key == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(CUDD_OUT_OF_MEM); - } - key->f = f; key->c = c; - if (st_lookup(cache, (char *)key, (char **)&res)) { - FREE(key); - if (comple) { - if (res == DD_LIC_0) res = DD_LIC_1; - else if (res == DD_LIC_1) res = DD_LIC_0; - } - return(res); - } - - /* Recursive step. */ - topf = dd->perm[f->index]; - topc = cuddI(dd,Cudd_Regular(c)->index); - if (topf <= topc) { - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - } else { - index = Cudd_Regular(c)->index; - Fv = Fnv = f; - } - if (topc <= topf) { - /* We know that c is not constant because f is not. */ - Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c)); - if (Cudd_IsComplement(c)) { - Cv = Cudd_Not(Cv); - Cnv = Cudd_Not(Cnv); - } - } else { - Cv = Cnv = c; - } - - resT = cuddBddLICMarkEdges(dd, Fv, Cv, table, cache); - if (resT == CUDD_OUT_OF_MEM) { - FREE(key); - return(CUDD_OUT_OF_MEM); - } - resE = cuddBddLICMarkEdges(dd, Fnv, Cnv, table, cache); - if (resE == CUDD_OUT_OF_MEM) { - FREE(key); - return(CUDD_OUT_OF_MEM); - } - - /* Update edge markings. */ - if (topf <= topc) { - retval = st_find_or_add(table, (char *)f, (char ***)&slot); - if (retval == 0) { - *slot = (char *) (ptrint)((resT << 2) | resE); - } else if (retval == 1) { - *slot = (char *) (ptrint)((int)((ptrint) *slot) | (resT << 2) | resE); - } else { - FREE(key); - return(CUDD_OUT_OF_MEM); - } - } - - /* Cache result. */ - res = resT | resE; - if (st_insert(cache, (char *)key, (char *)(ptrint)res) == ST_OUT_OF_MEM) { - FREE(key); - return(CUDD_OUT_OF_MEM); - } - - /* Take into account possible complementation. */ - if (comple) { - if (res == DD_LIC_0) res = DD_LIC_1; - else if (res == DD_LIC_1) res = DD_LIC_0; - } - return(res); - -} /* end of cuddBddLICMarkEdges */ - - -/**Function******************************************************************** - - Synopsis [Builds the result of Cudd_bddLICompaction.] - - Description [Builds the results of Cudd_bddLICompaction. - Returns a pointer to the minimized BDD if successful; otherwise NULL.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction cuddBddLICMarkEdges] - -******************************************************************************/ -static DdNode * -cuddBddLICBuildResult( - DdManager * dd, - DdNode * f, - st_table * cache, - st_table * table) -{ - DdNode *Fv, *Fnv, *r, *t, *e; - DdNode *one, *zero; - unsigned int topf; - int index; - int comple; - int markT, markE, markings; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - if (Cudd_IsConstant(f)) return(f); - /* Make canonical to increase the utilization of the cache. */ - comple = Cudd_IsComplement(f); - f = Cudd_Regular(f); - - /* Check the cache. */ - if (st_lookup(cache, (char *)f, (char **)&r)) { - return(Cudd_NotCond(r,comple)); - } - - /* Retrieve the edge markings. */ - if (st_lookup(table, (char *)f, (char **)&markings) == 0) - return(NULL); - markT = markings >> 2; - markE = markings & 3; - - topf = dd->perm[f->index]; - index = f->index; - Fv = cuddT(f); Fnv = cuddE(f); - - if (markT == DD_LIC_NL) { - t = cuddBddLICBuildResult(dd,Fv,cache,table); - if (t == NULL) { - return(NULL); - } - } else if (markT == DD_LIC_1) { - t = one; - } else { - t = zero; - } - cuddRef(t); - if (markE == DD_LIC_NL) { - e = cuddBddLICBuildResult(dd,Fnv,cache,table); - if (e == NULL) { - Cudd_IterDerefBdd(dd,t); - return(NULL); - } - } else if (markE == DD_LIC_1) { - e = one; - } else { - e = zero; - } - cuddRef(e); - - if (markT == DD_LIC_DC && markE != DD_LIC_DC) { - r = e; - } else if (markT != DD_LIC_DC && markE == DD_LIC_DC) { - r = t; - } else { - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - } - cuddDeref(t); - cuddDeref(e); - - if (st_insert(cache, (char *)f, (char *)r) == ST_OUT_OF_MEM) { - cuddRef(r); - Cudd_IterDerefBdd(dd,r); - return(NULL); - } - - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddLICBuildResult */ - - -/**Function******************************************************************** - - Synopsis [Hash function for the computed table of cuddBddLICMarkEdges.] - - Description [Hash function for the computed table of - cuddBddLICMarkEdges. Returns the bucket number.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction] - -******************************************************************************/ -static int -MarkCacheHash( - char * ptr, - int modulus) -{ - int val = 0; - MarkCacheKey *entry; - - entry = (MarkCacheKey *) ptr; - - val = (int) (ptrint) entry->f; - val = val * 997 + (int) (ptrint) entry->c; - - return ((val < 0) ? -val : val) % modulus; - -} /* end of MarkCacheHash */ - - -/**Function******************************************************************** - - Synopsis [Comparison function for the computed table of - cuddBddLICMarkEdges.] - - Description [Comparison function for the computed table of - cuddBddLICMarkEdges. Returns 0 if the two nodes of the key are equal; 1 - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction] - -******************************************************************************/ -static int -MarkCacheCompare( - const char * ptr1, - const char * ptr2) -{ - MarkCacheKey *entry1, *entry2; - - entry1 = (MarkCacheKey *) ptr1; - entry2 = (MarkCacheKey *) ptr2; - - return((entry1->f != entry2->f) || (entry1->c != entry2->c)); - -} /* end of MarkCacheCompare */ - - - -/**Function******************************************************************** - - Synopsis [Frees memory associated with computed table of - cuddBddLICMarkEdges.] - - Description [Frees memory associated with computed table of - cuddBddLICMarkEdges. Returns ST_CONTINUE.] - - SideEffects [None] - - SeeAlso [Cudd_bddLICompaction] - -******************************************************************************/ -static enum st_retval -MarkCacheCleanUp( - char * key, - char * value, - char * arg) -{ - MarkCacheKey *entry; - - entry = (MarkCacheKey *) key; - FREE(entry); - return ST_CONTINUE; - -} /* end of MarkCacheCleanUp */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddSqueeze.] - - Description [Performs the recursive step of Cudd_bddSqueeze. This - procedure exploits the fact that if we complement and swap the - bounds of the interval we obtain a valid solution by taking the - complement of the solution to the original problem. Therefore, we - can enforce the condition that the upper bound is always regular. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddSqueeze] - -******************************************************************************/ -static DdNode * -cuddBddSqueeze( - DdManager * dd, - DdNode * l, - DdNode * u) -{ - DdNode *one, *zero, *r, *lt, *le, *ut, *ue, *t, *e; -#if 0 - DdNode *ar; -#endif - int comple = 0; - unsigned int topu, topl; - int index; - - statLine(dd); - if (l == u) { - return(l); - } - one = DD_ONE(dd); - zero = Cudd_Not(one); - /* The only case when l == zero && u == one is at the top level, - ** where returning either one or zero is OK. In all other cases - ** the procedure will detect such a case and will perform - ** remapping. Therefore the order in which we test l and u at this - ** point is immaterial. */ - if (l == zero) return(l); - if (u == one) return(u); - - /* Make canonical to increase the utilization of the cache. */ - if (Cudd_IsComplement(u)) { - DdNode *temp; - temp = Cudd_Not(l); - l = Cudd_Not(u); - u = temp; - comple = 1; - } - /* At this point u is regular and non-constant; l is non-constant, but - ** may be complemented. */ - - /* Here we could check the relative sizes. */ - - /* Check the cache. */ - r = cuddCacheLookup2(dd, Cudd_bddSqueeze, l, u); - if (r != NULL) { - return(Cudd_NotCond(r,comple)); - } - - /* Recursive step. */ - topu = dd->perm[u->index]; - topl = dd->perm[Cudd_Regular(l)->index]; - if (topu <= topl) { - index = u->index; - ut = cuddT(u); ue = cuddE(u); - } else { - index = Cudd_Regular(l)->index; - ut = ue = u; - } - if (topl <= topu) { - lt = cuddT(Cudd_Regular(l)); le = cuddE(Cudd_Regular(l)); - if (Cudd_IsComplement(l)) { - lt = Cudd_Not(lt); - le = Cudd_Not(le); - } - } else { - lt = le = l; - } - - /* If one interval is contained in the other, use the smaller - ** interval. This corresponds to one-sided matching. */ - if ((lt == zero || Cudd_bddLeq(dd,lt,le)) && - (ut == one || Cudd_bddLeq(dd,ue,ut))) { /* remap */ - r = cuddBddSqueeze(dd, le, ue); - if (r == NULL) - return(NULL); - return(Cudd_NotCond(r,comple)); - } else if ((le == zero || Cudd_bddLeq(dd,le,lt)) && - (ue == one || Cudd_bddLeq(dd,ut,ue))) { /* remap */ - r = cuddBddSqueeze(dd, lt, ut); - if (r == NULL) - return(NULL); - return(Cudd_NotCond(r,comple)); - } else if ((le == zero || Cudd_bddLeq(dd,le,Cudd_Not(ut))) && - (ue == one || Cudd_bddLeq(dd,Cudd_Not(lt),ue))) { /* c-remap */ - t = cuddBddSqueeze(dd, lt, ut); - cuddRef(t); - if (Cudd_IsComplement(t)) { - r = cuddUniqueInter(dd, index, Cudd_Not(t), t); - if (r == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = cuddUniqueInter(dd, index, t, Cudd_Not(t)); - if (r == NULL) { - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - cuddDeref(t); - if (r == NULL) - return(NULL); - cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); - return(Cudd_NotCond(r,comple)); - } else if ((lt == zero || Cudd_bddLeq(dd,lt,Cudd_Not(ue))) && - (ut == one || Cudd_bddLeq(dd,Cudd_Not(le),ut))) { /* c-remap */ - e = cuddBddSqueeze(dd, le, ue); - cuddRef(e); - if (Cudd_IsComplement(e)) { - r = cuddUniqueInter(dd, index, Cudd_Not(e), e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - return(NULL); - } - } else { - r = cuddUniqueInter(dd, index, e, Cudd_Not(e)); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - return(NULL); - } - r = Cudd_Not(r); - } - cuddDeref(e); - if (r == NULL) - return(NULL); - cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); - return(Cudd_NotCond(r,comple)); - } - -#if 0 - /* If the two intervals intersect, take a solution from - ** the intersection of the intervals. This guarantees that the - ** splitting variable will not appear in the result. - ** This approach corresponds to two-sided matching, and is very - ** expensive. */ - if (Cudd_bddLeq(dd,lt,ue) && Cudd_bddLeq(dd,le,ut)) { - DdNode *au, *al; - au = cuddBddAndRecur(dd,ut,ue); - if (au == NULL) - return(NULL); - cuddRef(au); - al = cuddBddAndRecur(dd,Cudd_Not(lt),Cudd_Not(le)); - if (al == NULL) { - Cudd_IterDerefBdd(dd,au); - return(NULL); - } - cuddRef(al); - al = Cudd_Not(al); - ar = cuddBddSqueeze(dd, al, au); - if (ar == NULL) { - Cudd_IterDerefBdd(dd,au); - Cudd_IterDerefBdd(dd,al); - return(NULL); - } - cuddRef(ar); - Cudd_IterDerefBdd(dd,au); - Cudd_IterDerefBdd(dd,al); - } else { - ar = NULL; - } -#endif - - t = cuddBddSqueeze(dd, lt, ut); - if (t == NULL) { - return(NULL); - } - cuddRef(t); - e = cuddBddSqueeze(dd, le, ue); - if (e == NULL) { - Cudd_IterDerefBdd(dd,t); - return(NULL); - } - cuddRef(e); - - if (Cudd_IsComplement(t)) { - t = Cudd_Not(t); - e = Cudd_Not(e); - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - r = Cudd_Not(r); - } else { - r = (t == e) ? t : cuddUniqueInter(dd, index, t, e); - if (r == NULL) { - Cudd_IterDerefBdd(dd, e); - Cudd_IterDerefBdd(dd, t); - return(NULL); - } - } - cuddDeref(t); - cuddDeref(e); - -#if 0 - /* Check whether there is a result obtained by abstraction and whether - ** it is better than the one obtained by recursion. */ - cuddRef(r); - if (ar != NULL) { - if (Cudd_DagSize(ar) <= Cudd_DagSize(r)) { - Cudd_IterDerefBdd(dd, r); - r = ar; - } else { - Cudd_IterDerefBdd(dd, ar); - } - } - cuddDeref(r); -#endif - - cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r); - return(Cudd_NotCond(r,comple)); - -} /* end of cuddBddSqueeze */ diff --git a/src/bdd/cudd/cuddGenetic.c b/src/bdd/cudd/cuddGenetic.c deleted file mode 100644 index 9fe03dad..00000000 --- a/src/bdd/cudd/cuddGenetic.c +++ /dev/null @@ -1,921 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddGenetic.c] - - PackageName [cudd] - - Synopsis [Genetic algorithm for variable reordering.] - - Description [Internal procedures included in this file: -
              -
            • cuddGa() -
            - Static procedures included in this module: -
              -
            • make_random() -
            • sift_up() -
            • build_dd() -
            • largest() -
            • rand_int() -
            • array_hash() -
            • array_compare() -
            • find_best() -
            • find_average_fitness() -
            • PMX() -
            • roulette() -
            - - The genetic algorithm implemented here is as follows. We start with - the current DD order. We sift this order and use this as the - reference DD. We only keep 1 DD around for the entire process and - simply rearrange the order of this DD, storing the various orders - and their corresponding DD sizes. We generate more random orders to - build an initial population. This initial population is 3 times the - number of variables, with a maximum of 120. Each random order is - built (from the reference DD) and its size stored. Each random - order is also sifted to keep the DD sizes fairly small. Then a - crossover is performed between two orders (picked randomly) and the - two resulting DDs are built and sifted. For each new order, if its - size is smaller than any DD in the population, it is inserted into - the population and the DD with the largest number of nodes is thrown - out. The crossover process happens up to 50 times, and at this point - the DD in the population with the smallest size is chosen as the - result. This DD must then be built from the reference DD.] - - SeeAlso [] - - Author [Curt Musfeldt, Alan Shuler, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddGenetic.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -static int popsize; /* the size of the population */ -static int numvars; /* the number of input variables in the ckt. */ -/* storedd stores the population orders and sizes. This table has two -** extra rows and one extras column. The two extra rows are used for the -** offspring produced by a crossover. Each row stores one order and its -** size. The order is stored by storing the indices of variables in the -** order in which they appear in the order. The table is in reality a -** one-dimensional array which is accessed via a macro to give the illusion -** it is a two-dimensional structure. -*/ -static int *storedd; -static st_table *computed; /* hash table to identify existing orders */ -static int *repeat; /* how many times an order is present */ -static int large; /* stores the index of the population with - ** the largest number of nodes in the DD */ -static int result; -static int cross; /* the number of crossovers to perform */ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/* macro used to access the population table as if it were a -** two-dimensional structure. -*/ -#define STOREDD(i,j) storedd[(i)*(numvars+1)+(j)] - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int make_random ARGS((DdManager *table, int lower)); -static int sift_up ARGS((DdManager *table, int x, int x_low)); -static int build_dd ARGS((DdManager *table, int num, int lower, int upper)); -static int largest ARGS(()); -static int rand_int ARGS((int a)); -static int array_hash ARGS((char *array, int modulus)); -static int array_compare ARGS((const char *array1, const char *array2)); -static int find_best ARGS(()); -static double find_average_fitness ARGS(()); -static int PMX ARGS((int maxvar)); -static int roulette ARGS((int *p1, int *p2)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Genetic algorithm for DD reordering.] - - Description [Genetic algorithm for DD reordering. - The two children of a crossover will be stored in - storedd[popsize] and storedd[popsize+1] --- the last two slots in the - storedd array. (This will make comparisons and replacement easy.) - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddGa( - DdManager * table /* manager */, - int lower /* lowest level to be reordered */, - int upper /* highest level to be reorderded */) -{ - int i,n,m; /* dummy/loop vars */ - int index; - double average_fitness; - int small; /* index of smallest DD in population */ - - /* Do an initial sifting to produce at least one reasonable individual. */ - if (!cuddSifting(table,lower,upper)) return(0); - - /* Get the initial values. */ - numvars = upper - lower + 1; /* number of variables to be reordered */ - if (table->populationSize == 0) { - popsize = 3 * numvars; /* population size is 3 times # of vars */ - if (popsize > 120) { - popsize = 120; /* Maximum population size is 120 */ - } - } else { - popsize = table->populationSize; /* user specified value */ - } - if (popsize < 4) popsize = 4; /* enforce minimum population size */ - - /* Allocate population table. */ - storedd = ALLOC(int,(popsize+2)*(numvars+1)); - if (storedd == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - - /* Initialize the computed table. This table is made up of two data - ** structures: A hash table with the key given by the order, which says - ** if a given order is present in the population; and the repeat - ** vector, which says how many copies of a given order are stored in - ** the population table. If there are multiple copies of an order, only - ** one has a repeat count greater than 1. This copy is the one pointed - ** by the computed table. - */ - repeat = ALLOC(int,popsize); - if (repeat == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - FREE(storedd); - return(0); - } - for (i = 0; i < popsize; i++) { - repeat[i] = 0; - } - computed = st_init_table(array_compare,array_hash); - if (computed == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - FREE(storedd); - FREE(repeat); - return(0); - } - - /* Copy the current DD and its size to the population table. */ - for (i = 0; i < numvars; i++) { - STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */ - } - STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */ - - /* Store the initial order in the computed table. */ - if (st_insert(computed,(char *)storedd,(char *) 0) == ST_OUT_OF_MEM) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - repeat[0]++; - - /* Insert the reverse order as second element of the population. */ - for (i = 0; i < numvars; i++) { - STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */ - } - - /* Now create the random orders. make_random fills the population - ** table with random permutations. The successive loop builds and sifts - ** the DDs for the reverse order and each random permutation, and stores - ** the results in the computed table. - */ - if (!make_random(table,lower)) { - table->errorCode = CUDD_MEMORY_OUT; - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - for (i = 1; i < popsize; i++) { - result = build_dd(table,i,lower,upper); /* build and sift order */ - if (!result) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - if (st_lookup(computed,(char *)&STOREDD(i,0),(char **)&index)) { - repeat[index]++; - } else { - if (st_insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) == - ST_OUT_OF_MEM) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - repeat[i]++; - } - } - -#if 0 -#ifdef DD_STATS - /* Print the initial population. */ - (void) fprintf(table->out,"Initial population after sifting\n"); - for (m = 0; m < popsize; m++) { - for (i = 0; i < numvars; i++) { - (void) fprintf(table->out," %2d",STOREDD(m,i)); - } - (void) fprintf(table->out," : %3d (%d)\n", - STOREDD(m,numvars),repeat[m]); - } -#endif -#endif - - small = find_best(); - average_fitness = find_average_fitness(); -#ifdef DD_STATS - (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); -#endif - - /* Decide how many crossovers should be tried. */ - if (table->numberXovers == 0) { - cross = 3*numvars; - if (cross > 60) { /* do a maximum of 50 crossovers */ - cross = 60; - } - } else { - cross = table->numberXovers; /* use user specified value */ - } - - /* Perform the crossovers to get the best order. */ - for (m = 0; m < cross; m++) { - if (!PMX(table->size)) { /* perform one crossover */ - table->errorCode = CUDD_MEMORY_OUT; - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - /* The offsprings are left in the last two entries of the - ** population table. These are now considered in turn. - */ - for (i = popsize; i <= popsize+1; i++) { - result = build_dd(table,i,lower,upper); /* build and sift child */ - if (!result) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - large = largest(); /* find the largest DD in population */ - - /* If the new child is smaller than the largest DD in the current - ** population, enter it into the population in place of the - ** largest DD. - */ - if (STOREDD(i,numvars) < STOREDD(large,numvars)) { - /* Look up the largest DD in the computed table. - ** Decrease its repetition count. If the repetition count - ** goes to 0, remove the largest DD from the computed table. - */ - result = st_lookup(computed,(char *)&STOREDD(large,0),(char - **)&index); - if (!result) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - repeat[index]--; - if (repeat[index] == 0) { - int *pointer = &STOREDD(index,0); - result = st_delete(computed, (char **)&pointer,NULL); - if (!result) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - } - /* Copy the new individual to the entry of the - ** population table just made available and update the - ** computed table. - */ - for (n = 0; n <= numvars; n++) { - STOREDD(large,n) = STOREDD(i,n); - } - if (st_lookup(computed,(char *)&STOREDD(large,0),(char - **)&index)) { - repeat[index]++; - } else { - if (st_insert(computed,(char *)&STOREDD(large,0), - (char *)(long)large) == ST_OUT_OF_MEM) { - FREE(storedd); - FREE(repeat); - st_free_table(computed); - return(0); - } - repeat[large]++; - } - } - } - } - - /* Find the smallest DD in the population and build it; - ** that will be the result. - */ - small = find_best(); - - /* Print stats on the final population. */ -#ifdef DD_STATS - average_fitness = find_average_fitness(); - (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness); -#endif - - /* Clean up, build the result DD, and return. */ - st_free_table(computed); - computed = NULL; - result = build_dd(table,small,lower,upper); - FREE(storedd); - FREE(repeat); - return(result); - -} /* end of cuddGa */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Generates the random sequences for the initial population.] - - Description [Generates the random sequences for the initial population. - The sequences are permutations of the indices between lower and - upper in the current order.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -make_random( - DdManager * table, - int lower) -{ - int i,j; /* loop variables */ - int *used; /* is a number already in a permutation */ - int next; /* next random number without repetitions */ - - used = ALLOC(int,numvars); - if (used == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } -#if 0 -#ifdef DD_STATS - (void) fprintf(table->out,"Initial population before sifting\n"); - for (i = 0; i < 2; i++) { - for (j = 0; j < numvars; j++) { - (void) fprintf(table->out," %2d",STOREDD(i,j)); - } - (void) fprintf(table->out,"\n"); - } -#endif -#endif - for (i = 2; i < popsize; i++) { - for (j = 0; j < numvars; j++) { - used[j] = 0; - } - /* Generate a permutation of {0...numvars-1} and use it to - ** permute the variables in the layesr from lower to upper. - */ - for (j = 0; j < numvars; j++) { - do { - next = rand_int(numvars-1); - } while (used[next] != 0); - used[next] = 1; - STOREDD(i,j) = table->invperm[next+lower]; - } -#if 0 -#ifdef DD_STATS - /* Print the order just generated. */ - for (j = 0; j < numvars; j++) { - (void) fprintf(table->out," %2d",STOREDD(i,j)); - } - (void) fprintf(table->out,"\n"); -#endif -#endif - } - FREE(used); - return(1); - -} /* end of make_random */ - - -/**Function******************************************************************** - - Synopsis [Moves one variable up.] - - Description [Takes a variable from position x and sifts it up to - position x_low; x_low should be less than x. Returns 1 if successful; - 0 otherwise] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -sift_up( - DdManager * table, - int x, - int x_low) -{ - int y; - int size; - - y = cuddNextLow(table,x); - while (y >= x_low) { - size = cuddSwapInPlace(table,y,x); - if (size == 0) { - return(0); - } - x = y; - y = cuddNextLow(table,x); - } - return(1); - -} /* end of sift_up */ - - -/**Function******************************************************************** - - Synopsis [Builds a DD from a given order.] - - Description [Builds a DD from a given order. This procedure also - sifts the final order and inserts into the array the size in nodes - of the result. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -build_dd( - DdManager * table, - int num /* the index of the individual to be built */, - int lower, - int upper) -{ - int i,j; /* loop vars */ - int position; - int index; - int limit; /* how large the DD for this order can grow */ - int size; - - /* Check the computed table. If the order already exists, it - ** suffices to copy the size from the existing entry. - */ - if (computed && st_lookup(computed,(char *)&STOREDD(num,0),(char **)&index)) { - STOREDD(num,numvars) = STOREDD(index,numvars); -#ifdef DD_STATS - (void) fprintf(table->out,"\nCache hit for index %d", index); -#endif - return(1); - } - - /* Stop if the DD grows 20 times larges than the reference size. */ - limit = 20 * STOREDD(0,numvars); - - /* Sift up the variables so as to build the desired permutation. - ** First the variable that has to be on top is sifted to the top. - ** Then the variable that has to occupy the secon position is sifted - ** up to the second position, and so on. - */ - for (j = 0; j < numvars; j++) { - i = STOREDD(num,j); - position = table->perm[i]; - result = sift_up(table,position,j+lower); - if (!result) return(0); - size = table->keys - table->isolated; - if (size > limit) break; - } - - /* Sift the DD just built. */ -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); -#endif - result = cuddSifting(table,lower,upper); - if (!result) return(0); - - /* Copy order and size to table. */ - for (j = 0; j < numvars; j++) { - STOREDD(num,j) = table->invperm[lower+j]; - } - STOREDD(num,numvars) = table->keys - table->isolated; /* size of new DD */ - return(1); - -} /* end of build_dd */ - - -/**Function******************************************************************** - - Synopsis [Finds the largest DD in the population.] - - Description [Finds the largest DD in the population. If an order is - repeated, it avoids choosing the copy that is in the computed table - (it has repeat[i] > 1).] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -largest( - ) -{ - int i; /* loop var */ - int big; /* temporary holder to return result */ - - big = 0; - while (repeat[big] > 1) big++; - for (i = big + 1; i < popsize; i++) { - if (STOREDD(i,numvars) >= STOREDD(big,numvars) && repeat[i] <= 1) { - big = i; - } - } - return(big); - -} /* end of largest */ - - -/**Function******************************************************************** - - Synopsis [Generates a random number between 0 and the integer a.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -rand_int( - int a) -{ - return(Cudd_Random() % (a+1)); - -} /* end of rand_int */ - - -/**Function******************************************************************** - - Synopsis [Hash function for the computed table.] - - Description [Hash function for the computed table. Returns the bucket - number.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -array_hash( - char * array, - int modulus) -{ - int val = 0; - int i; - int *intarray; - - intarray = (int *) array; - - for (i = 0; i < numvars; i++) { - val = val * 997 + intarray[i]; - } - - return ((val < 0) ? -val : val) % modulus; - -} /* end of array_hash */ - - -/**Function******************************************************************** - - Synopsis [Comparison function for the computed table.] - - Description [Comparison function for the computed table. Returns 0 if - the two arrays are equal; 1 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -array_compare( - const char * array1, - const char * array2) -{ - int i; - int *intarray1, *intarray2; - - intarray1 = (int *) array1; - intarray2 = (int *) array2; - - for (i = 0; i < numvars; i++) { - if (intarray1[i] != intarray2[i]) return(1); - } - return(0); - -} /* end of array_compare */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of the fittest individual.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -find_best( - ) -{ - int i,small; - - small = 0; - for (i = 1; i < popsize; i++) { - if (STOREDD(i,numvars) < STOREDD(small,numvars)) { - small = i; - } - } - return(small); - -} /* end of find_best */ - - -/**Function******************************************************************** - - Synopsis [Returns the average fitness of the population.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static double -find_average_fitness( - ) -{ - int i; - int total_fitness = 0; - double average_fitness; - - for (i = 0; i < popsize; i++) { - total_fitness += STOREDD(i,numvars); - } - average_fitness = (double) total_fitness / (double) popsize; - return(average_fitness); - -} /* end of find_average_fitness */ - - -/**Function******************************************************************** - - Synopsis [Performs the crossover between two parents.] - - Description [Performs the crossover between two randomly chosen - parents, and creates two children, x1 and x2. Uses the Partially - Matched Crossover operator.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -PMX( - int maxvar) -{ - int cut1,cut2; /* the two cut positions (random) */ - int mom,dad; /* the two randomly chosen parents */ - int *inv1; /* inverse permutations for repair algo */ - int *inv2; - int i; /* loop vars */ - int u,v; /* aux vars */ - - inv1 = ALLOC(int,maxvar); - if (inv1 == NULL) { - return(0); - } - inv2 = ALLOC(int,maxvar); - if (inv2 == NULL) { - FREE(inv1); - return(0); - } - - /* Choose two orders from the population using roulette wheel. */ - if (!roulette(&mom,&dad)) { - FREE(inv1); - FREE(inv2); - return(0); - } - - /* Choose two random cut positions. A cut in position i means that - ** the cut immediately precedes position i. If cut1 < cut2, we - ** exchange the middle of the two orderings; otherwise, we - ** exchange the beginnings and the ends. - */ - cut1 = rand_int(numvars-1); - do { - cut2 = rand_int(numvars-1); - } while (cut1 == cut2); - -#if 0 - /* Print out the parents. */ - (void) fprintf(table->out, - "Crossover of %d (mom) and %d (dad) between %d and %d\n", - mom,dad,cut1,cut2); - for (i = 0; i < numvars; i++) { - if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); - (void) fprintf(table->out,"%2d ",STOREDD(mom,i)); - } - (void) fprintf(table->out,"\n"); - for (i = 0; i < numvars; i++) { - if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); - (void) fprintf(table->out,"%2d ",STOREDD(dad,i)); - } - (void) fprintf(table->out,"\n"); -#endif - - /* Initialize the inverse permutations: -1 means yet undetermined. */ - for (i = 0; i < maxvar; i++) { - inv1[i] = -1; - inv2[i] = -1; - } - - /* Copy the portions whithin the cuts. */ - for (i = cut1; i != cut2; i = (i == numvars-1) ? 0 : i+1) { - STOREDD(popsize,i) = STOREDD(dad,i); - inv1[STOREDD(popsize,i)] = i; - STOREDD(popsize+1,i) = STOREDD(mom,i); - inv2[STOREDD(popsize+1,i)] = i; - } - - /* Now apply the repair algorithm outside the cuts. */ - for (i = cut2; i != cut1; i = (i == numvars-1 ) ? 0 : i+1) { - v = i; - do { - u = STOREDD(mom,v); - v = inv1[u]; - } while (v != -1); - STOREDD(popsize,i) = u; - inv1[u] = i; - v = i; - do { - u = STOREDD(dad,v); - v = inv2[u]; - } while (v != -1); - STOREDD(popsize+1,i) = u; - inv2[u] = i; - } - -#if 0 - /* Print the results of crossover. */ - for (i = 0; i < numvars; i++) { - if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); - (void) fprintf(table->out,"%2d ",STOREDD(popsize,i)); - } - (void) fprintf(table->out,"\n"); - for (i = 0; i < numvars; i++) { - if (i == cut1 || i == cut2) (void) fprintf(table->out,"|"); - (void) fprintf(table->out,"%2d ",STOREDD(popsize+1,i)); - } - (void) fprintf(table->out,"\n"); -#endif - - FREE(inv1); - FREE(inv2); - return(1); - -} /* end of PMX */ - - -/**Function******************************************************************** - - Synopsis [Selects two parents with the roulette wheel method.] - - Description [Selects two distinct parents with the roulette wheel method.] - - SideEffects [The indices of the selected parents are returned as side - effects.] - - SeeAlso [] - -******************************************************************************/ -static int -roulette( - int * p1, - int * p2) -{ - double *wheel; - double spin; - int i; - - wheel = ALLOC(double,popsize); - if (wheel == NULL) { - return(0); - } - - /* The fitness of an individual is the reciprocal of its size. */ - wheel[0] = 1.0 / (double) STOREDD(0,numvars); - - for (i = 1; i < popsize; i++) { - wheel[i] = wheel[i-1] + 1.0 / (double) STOREDD(i,numvars); - } - - /* Get a random number between 0 and wheel[popsize-1] (that is, - ** the sum of all fitness values. 2147483561 is the largest number - ** returned by Cudd_Random. - */ - spin = wheel[numvars-1] * (double) Cudd_Random() / 2147483561.0; - - /* Find the lucky element by scanning the wheel. */ - for (i = 0; i < popsize; i++) { - if (spin <= wheel[i]) break; - } - *p1 = i; - - /* Repeat the process for the second parent, making sure it is - ** distinct from the first. - */ - do { - spin = wheel[popsize-1] * (double) Cudd_Random() / 2147483561.0; - for (i = 0; i < popsize; i++) { - if (spin <= wheel[i]) break; - } - } while (i == *p1); - *p2 = i; - - FREE(wheel); - return(1); - -} /* end of roulette */ - diff --git a/src/bdd/cudd/cuddGroup.c b/src/bdd/cudd/cuddGroup.c deleted file mode 100644 index 81c05d2c..00000000 --- a/src/bdd/cudd/cuddGroup.c +++ /dev/null @@ -1,2142 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddGroup.c] - - PackageName [cudd] - - Synopsis [Functions for group sifting.] - - Description [External procedures included in this file: -
              -
            • Cudd_MakeTreeNode() -
            - Internal procedures included in this file: -
              -
            • cuddTreeSifting() -
            - Static procedures included in this module: -
              -
            • ddTreeSiftingAux() -
            • ddCountInternalMtrNodes() -
            • ddReorderChildren() -
            • ddFindNodeHiLo() -
            • ddUniqueCompareGroup() -
            • ddGroupSifting() -
            • ddCreateGroup() -
            • ddGroupSiftingAux() -
            • ddGroupSiftingUp() -
            • ddGroupSiftingDown() -
            • ddGroupMove() -
            • ddGroupMoveBackward() -
            • ddGroupSiftingBackward() -
            • ddMergeGroups() -
            • ddDissolveGroup() -
            • ddNoCheck() -
            • ddSecDiffCheck() -
            • ddExtSymmCheck() -
            • ddVarGroupCheck() -
            • ddSetVarHandled() -
            • ddResetVarHandled() -
            • ddIsVarHandled() -
            ] - - Author [Shipra Panda, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/* Constants for lazy sifting */ -#define DD_NORMAL_SIFT 0 -#define DD_LAZY_SIFT 1 - -/* Constants for sifting up and down */ -#define DD_SIFT_DOWN 0 -#define DD_SIFT_UP 1 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddGroup.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -static int *entry; -extern int ddTotalNumberSwapping; -#ifdef DD_STATS -extern int ddTotalNISwaps; -static int extsymmcalls; -static int extsymm; -static int secdiffcalls; -static int secdiff; -static int secdiffmisfire; -#endif -#ifdef DD_DEBUG -static int pr = 0; /* flag to enable printing while debugging */ - /* by depositing a 1 into it */ -#endif -static int originalSize; -static int originalLevel; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddTreeSiftingAux ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); -#ifdef DD_STATS -static int ddCountInternalMtrNodes ARGS((DdManager *table, MtrNode *treenode)); -#endif -static int ddReorderChildren ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); -static void ddFindNodeHiLo ARGS((DdManager *table, MtrNode *treenode, int *lower, int *upper)); -static int ddUniqueCompareGroup ARGS((int *ptrX, int *ptrY)); -static int ddGroupSifting ARGS((DdManager *table, int lower, int upper, int (*checkFunction)(DdManager *, int, int), int lazyFlag)); -static void ddCreateGroup ARGS((DdManager *table, int x, int y)); -static int ddGroupSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh, int (*checkFunction)(DdManager *, int, int), int lazyFlag)); -static int ddGroupSiftingUp ARGS((DdManager *table, int y, int xLow, int (*checkFunction)(DdManager *, int, int), Move **moves)); -static int ddGroupSiftingDown ARGS((DdManager *table, int x, int xHigh, int (*checkFunction)(DdManager *, int, int), Move **moves)); -static int ddGroupMove ARGS((DdManager *table, int x, int y, Move **moves)); -static int ddGroupMoveBackward ARGS((DdManager *table, int x, int y)); -static int ddGroupSiftingBackward ARGS((DdManager *table, Move *moves, int size, int upFlag, int lazyFlag)); -static void ddMergeGroups ARGS((DdManager *table, MtrNode *treenode, int low, int high)); -static void ddDissolveGroup ARGS((DdManager *table, int x, int y)); -static int ddNoCheck ARGS((DdManager *table, int x, int y)); -static int ddSecDiffCheck ARGS((DdManager *table, int x, int y)); -static int ddExtSymmCheck ARGS((DdManager *table, int x, int y)); -static int ddVarGroupCheck ARGS((DdManager * table, int x, int y)); -static int ddSetVarHandled ARGS((DdManager *dd, int index)); -static int ddResetVarHandled ARGS((DdManager *dd, int index)); -static int ddIsVarHandled ARGS((DdManager *dd, int index)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Creates a new variable group.] - - Description [Creates a new variable group. The group starts at - variable and contains size variables. The parameter low is the index - of the first variable. If the variable already exists, its current - position in the order is known to the manager. If the variable does - not exist yet, the position is assumed to be the same as the index. - The group tree is created if it does not exist yet. - Returns a pointer to the group if successful; NULL otherwise.] - - SideEffects [The variable tree is changed.] - - SeeAlso [Cudd_MakeZddTreeNode] - -******************************************************************************/ -MtrNode * -Cudd_MakeTreeNode( - DdManager * dd /* manager */, - unsigned int low /* index of the first group variable */, - unsigned int size /* number of variables in the group */, - unsigned int type /* MTR_DEFAULT or MTR_FIXED */) -{ - MtrNode *group; - MtrNode *tree; - unsigned int level; - - /* If the variable does not exist yet, the position is assumed to be - ** the same as the index. Therefore, applications that rely on - ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new - ** variables have to create the variables before they group them. - */ - level = (low < (unsigned int) dd->size) ? dd->perm[low] : low; - - if (level + size - 1> (int) MTR_MAXHIGH) - return(NULL); - - /* If the tree does not exist yet, create it. */ - tree = dd->tree; - if (tree == NULL) { - dd->tree = tree = Mtr_InitGroupTree(0, dd->size); - if (tree == NULL) - return(NULL); - tree->index = dd->invperm[0]; - } - - /* Extend the upper bound of the tree if necessary. This allows the - ** application to create groups even before the variables are created. - */ - tree->size = ddMax(tree->size, ddMax(level + size, (unsigned) dd->size)); - - /* Create the group. */ - group = Mtr_MakeGroup(tree, level, size, type); - if (group == NULL) - return(NULL); - - /* Initialize the index field to the index of the variable currently - ** in position low. This field will be updated by the reordering - ** procedure to provide a handle to the group once it has been moved. - */ - group->index = (MtrHalfWord) low; - - return(group); - -} /* end of Cudd_MakeTreeNode */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Tree sifting algorithm.] - - Description [Tree sifting algorithm. Assumes that a tree representing - a group hierarchy is passed as a parameter. It then reorders each - group in postorder fashion by calling ddTreeSiftingAux. Assumes that - no dead nodes are present. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddTreeSifting( - DdManager * table /* DD table */, - Cudd_ReorderingType method /* reordering method for the groups of leaves */) -{ - int i; - int nvars; - int result; - int tempTree; - - /* If no tree is provided we create a temporary one in which all - ** variables are in a single group. After reordering this tree is - ** destroyed. - */ - tempTree = table->tree == NULL; - if (tempTree) { - table->tree = Mtr_InitGroupTree(0,table->size); - table->tree->index = table->invperm[0]; - } - nvars = table->size; - -#ifdef DD_DEBUG - if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:"); - Mtr_PrintGroups(table->tree,pr <= 0); -#endif - -#ifdef DD_STATS - extsymmcalls = 0; - extsymm = 0; - secdiffcalls = 0; - secdiff = 0; - secdiffmisfire = 0; - - (void) fprintf(table->out,"\n"); - if (!tempTree) - (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", - ddCountInternalMtrNodes(table,table->tree)); -#endif - - /* Initialize the group of each subtable to itself. Initially - ** there are no groups. Groups are created according to the tree - ** structure in postorder fashion. - */ - for (i = 0; i < nvars; i++) - table->subtables[i].next = i; - - - /* Reorder. */ - result = ddTreeSiftingAux(table, table->tree, method); - -#ifdef DD_STATS /* print stats */ - if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && - (table->groupcheck == CUDD_GROUP_CHECK7 || - table->groupcheck == CUDD_GROUP_CHECK5)) { - (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); - (void) fprintf(table->out,"extsymm = %d",extsymm); - } - if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && - table->groupcheck == CUDD_GROUP_CHECK7) { - (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); - (void) fprintf(table->out,"secdiff = %d\n",secdiff); - (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); - } -#endif - - if (tempTree) - Cudd_FreeTree(table); - return(result); - -} /* end of cuddTreeSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Visits the group tree and reorders each group.] - - Description [Recursively visits the group tree and reorders each - group in postorder fashion. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddTreeSiftingAux( - DdManager * table, - MtrNode * treenode, - Cudd_ReorderingType method) -{ - MtrNode *auxnode; - int res; - Cudd_AggregationType saveCheck; - -#ifdef DD_DEBUG - Mtr_PrintGroups(treenode,1); -#endif - - auxnode = treenode; - while (auxnode != NULL) { - if (auxnode->child != NULL) { - if (!ddTreeSiftingAux(table, auxnode->child, method)) - return(0); - saveCheck = table->groupcheck; - table->groupcheck = CUDD_NO_CHECK; - if (method != CUDD_REORDER_LAZY_SIFT) - res = ddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT); - else - res = ddReorderChildren(table, auxnode, CUDD_REORDER_LAZY_SIFT); - table->groupcheck = saveCheck; - - if (res == 0) - return(0); - } else if (auxnode->size > 1) { - if (!ddReorderChildren(table, auxnode, method)) - return(0); - } - auxnode = auxnode->younger; - } - - return(1); - -} /* end of ddTreeSiftingAux */ - - -#ifdef DD_STATS -/**Function******************************************************************** - - Synopsis [Counts the number of internal nodes of the group tree.] - - Description [Counts the number of internal nodes of the group tree. - Returns the count.] - - SideEffects [None] - -******************************************************************************/ -static int -ddCountInternalMtrNodes( - DdManager * table, - MtrNode * treenode) -{ - MtrNode *auxnode; - int count,nodeCount; - - - nodeCount = 0; - auxnode = treenode; - while (auxnode != NULL) { - if (!(MTR_TEST(auxnode,MTR_TERMINAL))) { - nodeCount++; - count = ddCountInternalMtrNodes(table,auxnode->child); - nodeCount += count; - } - auxnode = auxnode->younger; - } - - return(nodeCount); - -} /* end of ddCountInternalMtrNodes */ -#endif - - -/**Function******************************************************************** - - Synopsis [Reorders the children of a group tree node according to - the options.] - - Description [Reorders the children of a group tree node according to - the options. After reordering puts all the variables in the group - and/or its descendents in a single group. This allows hierarchical - reordering. If the variables in the group do not exist yet, simply - does nothing. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddReorderChildren( - DdManager * table, - MtrNode * treenode, - Cudd_ReorderingType method) -{ - int lower; - int upper; - int result; - unsigned int initialSize; - - ddFindNodeHiLo(table,treenode,&lower,&upper); - /* If upper == -1 these variables do not exist yet. */ - if (upper == -1) - return(1); - - if (treenode->flags == MTR_FIXED) { - result = 1; - } else { -#ifdef DD_STATS - (void) fprintf(table->out," "); -#endif - switch (method) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - result = cuddSwapping(table,lower,upper,method); - break; - case CUDD_REORDER_SIFT: - result = cuddSifting(table,lower,upper); - break; - case CUDD_REORDER_SIFT_CONVERGE: - do { - initialSize = table->keys - table->isolated; - result = cuddSifting(table,lower,upper); - if (initialSize <= table->keys - table->isolated) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - case CUDD_REORDER_SYMM_SIFT: - result = cuddSymmSifting(table,lower,upper); - break; - case CUDD_REORDER_SYMM_SIFT_CONV: - result = cuddSymmSiftingConv(table,lower,upper); - break; - case CUDD_REORDER_GROUP_SIFT: - if (table->groupcheck == CUDD_NO_CHECK) { - result = ddGroupSifting(table,lower,upper,ddNoCheck, - DD_NORMAL_SIFT); - } else if (table->groupcheck == CUDD_GROUP_CHECK5) { - result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, - DD_NORMAL_SIFT); - } else if (table->groupcheck == CUDD_GROUP_CHECK7) { - result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, - DD_NORMAL_SIFT); - } else { - (void) fprintf(table->err, - "Unknown group ckecking method\n"); - result = 0; - } - break; - case CUDD_REORDER_GROUP_SIFT_CONV: - do { - initialSize = table->keys - table->isolated; - if (table->groupcheck == CUDD_NO_CHECK) { - result = ddGroupSifting(table,lower,upper,ddNoCheck, - DD_NORMAL_SIFT); - } else if (table->groupcheck == CUDD_GROUP_CHECK5) { - result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, - DD_NORMAL_SIFT); - } else if (table->groupcheck == CUDD_GROUP_CHECK7) { - result = ddGroupSifting(table,lower,upper,ddExtSymmCheck, - DD_NORMAL_SIFT); - } else { - (void) fprintf(table->err, - "Unknown group ckecking method\n"); - result = 0; - } -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); -#endif - result = cuddWindowReorder(table,lower,upper, - CUDD_REORDER_WINDOW4); - if (initialSize <= table->keys - table->isolated) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - case CUDD_REORDER_WINDOW2: - case CUDD_REORDER_WINDOW3: - case CUDD_REORDER_WINDOW4: - case CUDD_REORDER_WINDOW2_CONV: - case CUDD_REORDER_WINDOW3_CONV: - case CUDD_REORDER_WINDOW4_CONV: - result = cuddWindowReorder(table,lower,upper,method); - break; - case CUDD_REORDER_ANNEALING: - result = cuddAnnealing(table,lower,upper); - break; - case CUDD_REORDER_GENETIC: - result = cuddGa(table,lower,upper); - break; - case CUDD_REORDER_LINEAR: - result = cuddLinearAndSifting(table,lower,upper); - break; - case CUDD_REORDER_LINEAR_CONVERGE: - do { - initialSize = table->keys - table->isolated; - result = cuddLinearAndSifting(table,lower,upper); - if (initialSize <= table->keys - table->isolated) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - case CUDD_REORDER_EXACT: - result = cuddExact(table,lower,upper); - break; - case CUDD_REORDER_LAZY_SIFT: - result = ddGroupSifting(table,lower,upper,ddVarGroupCheck, - DD_LAZY_SIFT); - break; - default: - return(0); - } - } - - /* Create a single group for all the variables that were sifted, - ** so that they will be treated as a single block by successive - ** invocations of ddGroupSifting. - */ - ddMergeGroups(table,treenode,lower,upper); - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"ddReorderChildren:"); -#endif - - return(result); - -} /* end of ddReorderChildren */ - - -/**Function******************************************************************** - - Synopsis [Finds the lower and upper bounds of the group represented - by treenode.] - - Description [Finds the lower and upper bounds of the group - represented by treenode. From the index and size fields we need to - derive the current positions, and find maximum and minimum.] - - SideEffects [The bounds are returned as side effects.] - - SeeAlso [] - -******************************************************************************/ -static void -ddFindNodeHiLo( - DdManager * table, - MtrNode * treenode, - int * lower, - int * upper) -{ - int low; - int high; - - /* Check whether no variables in this group already exist. - ** If so, return immediately. The calling procedure will know from - ** the values of upper that no reordering is needed. - */ - if ((int) treenode->low >= table->size) { - *lower = table->size; - *upper = -1; - return; - } - - *lower = low = (unsigned int) table->perm[treenode->index]; - high = (int) (low + treenode->size - 1); - - if (high >= table->size) { - /* This is the case of a partially existing group. The aim is to - ** reorder as many variables as safely possible. If the tree - ** node is terminal, we just reorder the subset of the group - ** that is currently in existence. If the group has - ** subgroups, then we only reorder those subgroups that are - ** fully instantiated. This way we avoid breaking up a group. - */ - MtrNode *auxnode = treenode->child; - if (auxnode == NULL) { - *upper = (unsigned int) table->size - 1; - } else { - /* Search the subgroup that strands the table->size line. - ** If the first group starts at 0 and goes past table->size - ** upper will get -1, thus correctly signaling that no reordering - ** should take place. - */ - while (auxnode != NULL) { - int thisLower = table->perm[auxnode->low]; - int thisUpper = thisLower + auxnode->size - 1; - if (thisUpper >= table->size && thisLower < table->size) - *upper = (unsigned int) thisLower - 1; - auxnode = auxnode->younger; - } - } - } else { - /* Normal case: All the variables of the group exist. */ - *upper = (unsigned int) high; - } - -#ifdef DD_DEBUG - /* Make sure that all variables in group are contiguous. */ - assert(treenode->size >= *upper - *lower + 1); -#endif - - return; - -} /* end of ddFindNodeHiLo */ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the variables - according to the number of keys in the subtables. Returns the - difference in number of keys between the two variables being - compared.] - - SideEffects [None] - -******************************************************************************/ -static int -ddUniqueCompareGroup( - int * ptrX, - int * ptrY) -{ -#if 0 - if (entry[*ptrY] == entry[*ptrX]) { - return((*ptrX) - (*ptrY)); - } -#endif - return(entry[*ptrY] - entry[*ptrX]); - -} /* end of ddUniqueCompareGroup */ - - -/**Function******************************************************************** - - Synopsis [Sifts from treenode->low to treenode->high.] - - Description [Sifts from treenode->low to treenode->high. If - croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the - end of the initial sifting. If a group is created, it is then sifted - again. After sifting one variable, the group that contains it is - dissolved. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupSifting( - DdManager * table, - int lower, - int upper, - int (*checkFunction)(DdManager *, int, int), - int lazyFlag) -{ - int *var; - int i,j,x,xInit; - int nvars; - int classes; - int result; - int *sifted; - int merged; - int dissolve; -#ifdef DD_STATS - unsigned previousSize; -#endif - int xindex; - - nvars = table->size; - - /* Order variables to sift. */ - entry = NULL; - sifted = NULL; - var = ALLOC(int,nvars); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddGroupSiftingOutOfMem; - } - entry = ALLOC(int,nvars); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddGroupSiftingOutOfMem; - } - sifted = ALLOC(int,nvars); - if (sifted == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddGroupSiftingOutOfMem; - } - - /* Here we consider only one representative for each group. */ - for (i = 0, classes = 0; i < nvars; i++) { - sifted[i] = 0; - x = table->perm[i]; - if ((unsigned) x >= table->subtables[x].next) { - entry[i] = table->subtables[x].keys; - var[classes] = i; - classes++; - } - } - - qsort((void *)var,classes,sizeof(int), - (int (*)(const void *, const void *)) ddUniqueCompareGroup); - - if (lazyFlag) { - for (i = 0; i < nvars; i ++) { - ddResetVarHandled(table, i); - } - } - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - xindex = var[i]; - if (sifted[xindex] == 1) /* variable already sifted as part of group */ - continue; - x = table->perm[xindex]; /* find current level of this variable */ - - if (x < lower || x > upper || table->subtables[x].bindVar == 1) - continue; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif -#ifdef DD_DEBUG - /* x is bottom of group */ - assert((unsigned) x >= table->subtables[x].next); -#endif - if ((unsigned) x == table->subtables[x].next) { - dissolve = 1; - result = ddGroupSiftingAux(table,x,lower,upper,checkFunction, - lazyFlag); - } else { - dissolve = 0; - result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag); - } - if (!result) goto ddGroupSiftingOutOfMem; - - /* check for aggregation */ - merged = 0; - if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) { - x = table->perm[xindex]; /* find current level */ - if ((unsigned) x == table->subtables[x].next) { /* not part of a group */ - if (x != upper && sifted[table->invperm[x+1]] == 0 && - (unsigned) x+1 == table->subtables[x+1].next) { - if (ddSecDiffCheck(table,x,x+1)) { - merged =1; - ddCreateGroup(table,x,x+1); - } - } - if (x != lower && sifted[table->invperm[x-1]] == 0 && - (unsigned) x-1 == table->subtables[x-1].next) { - if (ddSecDiffCheck(table,x-1,x)) { - merged =1; - ddCreateGroup(table,x-1,x); - } - } - } - } - - if (merged) { /* a group was created */ - /* move x to bottom of group */ - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - /* sift */ - result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag); - if (!result) goto ddGroupSiftingOutOfMem; -#ifdef DD_STATS - if (table->keys < previousSize + table->isolated) { - (void) fprintf(table->out,"_"); - } else if (table->keys > previousSize + table->isolated) { - (void) fprintf(table->out,"^"); - } else { - (void) fprintf(table->out,"*"); - } - fflush(table->out); - } else { - if (table->keys < previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > previousSize + table->isolated) { - (void) fprintf(table->out,"+"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - /* Mark variables in the group just sifted. */ - x = table->perm[xindex]; - if ((unsigned) x != table->subtables[x].next) { - xInit = x; - do { - j = table->invperm[x]; - sifted[j] = 1; - x = table->subtables[x].next; - } while (x != xInit); - - /* Dissolve the group if it was created. */ - if (lazyFlag == 0 && dissolve) { - do { - j = table->subtables[x].next; - table->subtables[x].next = x; - x = j; - } while (x != xInit); - } - } - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:"); -#endif - - if (lazyFlag) ddSetVarHandled(table, xindex); - } /* for */ - - FREE(sifted); - FREE(var); - FREE(entry); - - return(1); - -ddGroupSiftingOutOfMem: - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - if (sifted != NULL) FREE(sifted); - - return(0); - -} /* end of ddGroupSifting */ - - -/**Function******************************************************************** - - Synopsis [Creates a group encompassing variables from x to y in the - DD table.] - - Description [Creates a group encompassing variables from x to y in the - DD table. In the current implementation it must be y == x+1. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static void -ddCreateGroup( - DdManager * table, - int x, - int y) -{ - int gybot; - -#ifdef DD_DEBUG - assert(y == x+1); -#endif - - /* Find bottom of second group. */ - gybot = y; - while ((unsigned) gybot < table->subtables[gybot].next) - gybot = table->subtables[gybot].next; - - /* Link groups. */ - table->subtables[x].next = y; - table->subtables[gybot].next = x; - - return; - -} /* ddCreateGroup */ - - -/**Function******************************************************************** - - Synopsis [Sifts one variable up and down until it has taken all - positions. Checks for aggregation.] - - Description [Sifts one variable up and down until it has taken all - positions. Checks for aggregation. There may be at most two sweeps, - even if the group grows. Assumes that x is either an isolated - variable, or it is the bottom of a group. All groups may not have - been found. The variable being moved is returned to the best position - seen during sifting. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupSiftingAux( - DdManager * table, - int x, - int xLow, - int xHigh, - int (*checkFunction)(DdManager *, int, int), - int lazyFlag) -{ - Move *move; - Move *moves; /* list of moves */ - int initialSize; - int result; - int y; - int topbot; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out, - "ddGroupSiftingAux from %d to %d\n",xLow,xHigh); - assert((unsigned) x >= table->subtables[x].next); /* x is bottom of group */ -#endif - - initialSize = table->keys - table->isolated; - moves = NULL; - - originalSize = initialSize; /* for lazy sifting */ - - /* If we have a singleton, we check for aggregation in both - ** directions before we sift. - */ - if ((unsigned) x == table->subtables[x].next) { - /* Will go down first, unless x == xHigh: - ** Look for aggregation above x. - */ - for (y = x; y > xLow; y--) { - if (!checkFunction(table,y-1,y)) - break; - topbot = table->subtables[y-1].next; /* find top of y-1's group */ - table->subtables[y-1].next = y; - table->subtables[x].next = topbot; /* x is bottom of group so its */ - /* next is top of y-1's group */ - y = topbot + 1; /* add 1 for y--; new y is top of group */ - } - /* Will go up first unless x == xlow: - ** Look for aggregation below x. - */ - for (y = x; y < xHigh; y++) { - if (!checkFunction(table,y,y+1)) - break; - /* find bottom of y+1's group */ - topbot = y + 1; - while ((unsigned) topbot < table->subtables[topbot].next) { - topbot = table->subtables[topbot].next; - } - table->subtables[topbot].next = table->subtables[y].next; - table->subtables[y].next = y + 1; - y = topbot - 1; /* subtract 1 for y++; new y is bottom of group */ - } - } - - /* Now x may be in the middle of a group. - ** Find bottom of x's group. - */ - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - - originalLevel = x; /* for lazy sifting */ - - if (x == xLow) { /* Sift down */ -#ifdef DD_DEBUG - /* x must be a singleton */ - assert((unsigned) x == table->subtables[x].next); -#endif - if (x == xHigh) return(1); /* just one variable */ - - if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - /* move backward and stop at best position */ - result = ddGroupSiftingBackward(table,moves,initialSize, - DD_SIFT_DOWN,lazyFlag); -#ifdef DD_DEBUG - assert(table->keys - table->isolated <= (unsigned) initialSize); -#endif - if (!result) goto ddGroupSiftingAuxOutOfMem; - - } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ -#ifdef DD_DEBUG - /* x is bottom of group */ - assert((unsigned) x >= table->subtables[x].next); -#endif - /* Find top of x's group */ - x = table->subtables[x].next; - - if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - /* at this point x == xLow, unless early term */ - - /* move backward and stop at best position */ - result = ddGroupSiftingBackward(table,moves,initialSize, - DD_SIFT_UP,lazyFlag); -#ifdef DD_DEBUG - assert(table->keys - table->isolated <= (unsigned) initialSize); -#endif - if (!result) goto ddGroupSiftingAuxOutOfMem; - - } else if (x - xLow > xHigh - x) { /* must go down first: shorter */ - if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - /* Find top of group */ - if (moves) { - x = moves->y; - } - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - x = table->subtables[x].next; -#ifdef DD_DEBUG - /* x should be the top of a group */ - assert((unsigned) x <= table->subtables[x].next); -#endif - - if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - - /* move backward and stop at best position */ - result = ddGroupSiftingBackward(table,moves,initialSize, - DD_SIFT_UP,lazyFlag); -#ifdef DD_DEBUG - assert(table->keys - table->isolated <= (unsigned) initialSize); -#endif - if (!result) goto ddGroupSiftingAuxOutOfMem; - - } else { /* moving up first: shorter */ - /* Find top of x's group */ - x = table->subtables[x].next; - - if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - if (moves) { - x = moves->x; - } - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; -#ifdef DD_DEBUG - /* x is bottom of a group */ - assert((unsigned) x >= table->subtables[x].next); -#endif - - if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves)) - goto ddGroupSiftingAuxOutOfMem; - - /* move backward and stop at best position */ - result = ddGroupSiftingBackward(table,moves,initialSize, - DD_SIFT_DOWN,lazyFlag); -#ifdef DD_DEBUG - assert(table->keys - table->isolated <= (unsigned) initialSize); -#endif - if (!result) goto ddGroupSiftingAuxOutOfMem; - } - - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(1); - -ddGroupSiftingAuxOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(0); - -} /* end of ddGroupSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts up a variable until either it reaches position xLow - or the size of the DD heap increases too much.] - - Description [Sifts up a variable until either it reaches position - xLow or the size of the DD heap increases too much. Assumes that y is - the top of a group (or a singleton). Checks y for aggregation to the - adjacent variables. Records all the moves that are appended to the - list of moves received as input and returned as a side effect. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupSiftingUp( - DdManager * table, - int y, - int xLow, - int (*checkFunction)(DdManager *, int, int), - Move ** moves) -{ - Move *move; - int x; - int size; - int i; - int gxtop,gybot; - int limitSize; - int xindex, yindex; - int zindex; - int z; - int isolated; - int L; /* lower bound on DD size */ -#ifdef DD_DEBUG - int checkL; -#endif - - yindex = table->invperm[y]; - - /* Initialize the lower bound. - ** The part of the DD below the bottom of y's group will not change. - ** The part of the DD above y that does not interact with any - ** variable of y's group will not change. - ** The rest may vanish in the best case, except for - ** the nodes at level xLow, which will not vanish, regardless. - ** What we use here is not really a lower bound, because we ignore - ** the interactions with all variables except y. - */ - limitSize = L = table->keys - table->isolated; - gybot = y; - while ((unsigned) gybot < table->subtables[gybot].next) - gybot = table->subtables[gybot].next; - for (z = xLow + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - L -= table->subtables[z].keys - isolated; - } - } - - originalLevel = y; /* for lazy sifting */ - - x = cuddNextLow(table,y); - while (x >= xLow && L <= limitSize) { -#ifdef DD_DEBUG - gybot = y; - while ((unsigned) gybot < table->subtables[gybot].next) - gybot = table->subtables[gybot].next; - checkL = table->keys - table->isolated; - for (z = xLow + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - checkL -= table->subtables[z].keys - isolated; - } - } - if (pr > 0 && L != checkL) { - (void) fprintf(table->out, - "Inaccurate lower bound: L = %d checkL = %d\n", - L, checkL); - } -#endif - gxtop = table->subtables[x].next; - if (checkFunction(table,x,y)) { - /* Group found, attach groups */ - table->subtables[x].next = y; - i = table->subtables[y].next; - while (table->subtables[i].next != (unsigned) y) - i = table->subtables[i].next; - table->subtables[i].next = gxtop; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddGroupSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_NEWNODE; - move->size = table->keys - table->isolated; - move->next = *moves; - *moves = move; - } else if (table->subtables[x].next == (unsigned) x && - table->subtables[y].next == (unsigned) y) { - /* x and y are self groups */ - xindex = table->invperm[x]; - size = cuddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtables[x].next == (unsigned) x); - assert(table->subtables[y].next == (unsigned) y); -#endif - if (size == 0) goto ddGroupSiftingUpOutOfMem; - /* Update the lower bound. */ - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L += table->subtables[y].keys - isolated; - } - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddGroupSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_DEFAULT; - move->size = size; - move->next = *moves; - *moves = move; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out, - "ddGroupSiftingUp (2 single groups):\n"); -#endif - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } else { /* Group move */ - size = ddGroupMove(table,x,y,moves); - if (size == 0) goto ddGroupSiftingUpOutOfMem; - /* Update the lower bound. */ - z = (*moves)->y; - do { - zindex = table->invperm[z]; - if (cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - L += table->subtables[z].keys - isolated; - } - z = table->subtables[z].next; - } while (z != (int) (*moves)->y); - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } - y = gxtop; - x = cuddNextLow(table,y); - } - - return(1); - -ddGroupSiftingUpOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - return(0); - -} /* end of ddGroupSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts down a variable until it reaches position xHigh.] - - Description [Sifts down a variable until it reaches position xHigh. - Assumes that x is the bottom of a group (or a singleton). Records - all the moves. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupSiftingDown( - DdManager * table, - int x, - int xHigh, - int (*checkFunction)(DdManager *, int, int), - Move ** moves) -{ - Move *move; - int y; - int size; - int limitSize; - int gxtop,gybot; - int R; /* upper bound on node decrease */ - int xindex, yindex; - int isolated, allVars; - int z; - int zindex; -#ifdef DD_DEBUG - int checkR; -#endif - - /* If the group consists of simple variables, there is no point in - ** sifting it down. This check is redundant if the projection functions - ** do not have external references, because the computation of the - ** lower bound takes care of the problem. It is necessary otherwise to - ** prevent the sifting down of simple variables. */ - y = x; - allVars = 1; - do { - if (table->subtables[y].keys != 1) { - allVars = 0; - break; - } - y = table->subtables[y].next; - } while (table->subtables[y].next != (unsigned) x); - if (allVars) - return(1); - - /* Initialize R. */ - xindex = table->invperm[x]; - gxtop = table->subtables[x].next; - limitSize = size = table->keys - table->isolated; - R = 0; - for (z = xHigh; z > gxtop; z--) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R += table->subtables[z].keys - isolated; - } - } - - originalLevel = x; /* for lazy sifting */ - - y = cuddNextHigh(table,x); - while (y <= xHigh && size - R < limitSize) { -#ifdef DD_DEBUG - gxtop = table->subtables[x].next; - checkR = 0; - for (z = xHigh; z > gxtop; z--) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - checkR += table->subtables[z].keys - isolated; - } - } - assert(R >= checkR); -#endif - /* Find bottom of y group. */ - gybot = table->subtables[y].next; - while (table->subtables[gybot].next != (unsigned) y) - gybot = table->subtables[gybot].next; - - if (checkFunction(table,x,y)) { - /* Group found: attach groups and record move. */ - gxtop = table->subtables[x].next; - table->subtables[x].next = y; - table->subtables[gybot].next = gxtop; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto ddGroupSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_NEWNODE; - move->size = table->keys - table->isolated; - move->next = *moves; - *moves = move; - } else if (table->subtables[x].next == (unsigned) x && - table->subtables[y].next == (unsigned) y) { - /* x and y are self groups */ - /* Update upper bound on node decrease. */ - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R -= table->subtables[y].keys - isolated; - } - size = cuddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtables[x].next == (unsigned) x); - assert(table->subtables[y].next == (unsigned) y); -#endif - if (size == 0) goto ddGroupSiftingDownOutOfMem; - - /* Record move. */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddGroupSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_DEFAULT; - move->size = size; - move->next = *moves; - *moves = move; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out, - "ddGroupSiftingDown (2 single groups):\n"); -#endif - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - - x = y; - y = cuddNextHigh(table,x); - } else { /* Group move */ - /* Update upper bound on node decrease: first phase. */ - gxtop = table->subtables[x].next; - z = gxtop + 1; - do { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R -= table->subtables[z].keys - isolated; - } - z++; - } while (z <= gybot); - size = ddGroupMove(table,x,y,moves); - if (size == 0) goto ddGroupSiftingDownOutOfMem; - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - - /* Update upper bound on node decrease: second phase. */ - gxtop = table->subtables[gybot].next; - for (z = gxtop + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R += table->subtables[z].keys - isolated; - } - } - } - x = gybot; - y = cuddNextHigh(table,x); - } - - return(1); - -ddGroupSiftingDownOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - - return(0); - -} /* end of ddGroupSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Swaps two groups and records the move.] - - Description [Swaps two groups and records the move. Returns the - number of keys in the DD table in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupMove( - DdManager * table, - int x, - int y, - Move ** moves) -{ - Move *move; - int size; - int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - int swapx,swapy; -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - int initialSize,bestSize; -#endif - -#if DD_DEBUG - /* We assume that x < y */ - assert(x < y); -#endif - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtables[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtables[ybot].next) - ybot = table->subtables[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - initialSize = bestSize = table->keys - table->isolated; -#endif - /* Sift the variables of the second group up through the first group */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddGroupMoveOutOfMem; -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if (size < bestSize) - bestSize = size; -#endif - swapx = x; swapy = y; - y = x; - x = cuddNextLow(table,y); - } - y = ytop + i; - x = cuddNextLow(table,y); - } -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if ((bestSize < initialSize) && (bestSize < size)) - (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size); -#endif - - /* fix groups */ - y = xtop; /* ytop is now where xtop used to be */ - for (i = 0; i < ysize - 1; i++) { - table->subtables[y].next = cuddNextHigh(table,y); - y = cuddNextHigh(table,y); - } - table->subtables[y].next = xtop; /* y is bottom of its group, join */ - /* it to top of its group */ - x = cuddNextHigh(table,y); - newxtop = x; - for (i = 0; i < xsize - 1; i++) { - table->subtables[x].next = cuddNextHigh(table,x); - x = cuddNextHigh(table,x); - } - table->subtables[x].next = newxtop; /* x is bottom of its group, join */ - /* it to top of its group */ -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"ddGroupMove:\n"); -#endif - - /* Store group move */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddGroupMoveOutOfMem; - move->x = swapx; - move->y = swapy; - move->flags = MTR_DEFAULT; - move->size = table->keys - table->isolated; - move->next = *moves; - *moves = move; - - return(table->keys - table->isolated); - -ddGroupMoveOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - return(0); - -} /* end of ddGroupMove */ - - -/**Function******************************************************************** - - Synopsis [Undoes the swap two groups.] - - Description [Undoes the swap two groups. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupMoveBackward( - DdManager * table, - int x, - int y) -{ - int size; - int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - - -#if DD_DEBUG - /* We assume that x < y */ - assert(x < y); -#endif - - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtables[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtables[ybot].next) - ybot = table->subtables[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - - /* Sift the variables of the second group up through the first group */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddSwapInPlace(table,x,y); - if (size == 0) - return(0); - y = x; - x = cuddNextLow(table,y); - } - y = ytop + i; - x = cuddNextLow(table,y); - } - - /* fix groups */ - y = xtop; - for (i = 0; i < ysize - 1; i++) { - table->subtables[y].next = cuddNextHigh(table,y); - y = cuddNextHigh(table,y); - } - table->subtables[y].next = xtop; /* y is bottom of its group, join */ - /* to its top */ - x = cuddNextHigh(table,y); - newxtop = x; - for (i = 0; i < xsize - 1; i++) { - table->subtables[x].next = cuddNextHigh(table,x); - x = cuddNextHigh(table,x); - } - table->subtables[x].next = newxtop; /* x is bottom of its group, join */ - /* to its top */ -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"ddGroupMoveBackward:\n"); -#endif - - return(1); - -} /* end of ddGroupMoveBackward */ - - -/**Function******************************************************************** - - Synopsis [Determines the best position for a variables and returns - it there.] - - Description [Determines the best position for a variables and returns - it there. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddGroupSiftingBackward( - DdManager * table, - Move * moves, - int size, - int upFlag, - int lazyFlag) -{ - Move *move; - int res; - Move *end_move; - int diff, tmp_diff; - int index, pairlev; - - if (lazyFlag) { - end_move = NULL; - - /* Find the minimum size, and the earliest position at which it - ** was achieved. */ - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - end_move = move; - } else if (move->size == size) { - if (end_move == NULL) end_move = move; - } - } - - /* Find among the moves that give minimum size the one that - ** minimizes the distance from the corresponding variable. */ - if (moves != NULL) { - diff = Cudd_ReadSize(table) + 1; - index = (upFlag == 1) ? - table->invperm[moves->x] : table->invperm[moves->y]; - pairlev = table->perm[Cudd_bddReadPairIndex(table, index)]; - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) { - if (upFlag == 1) { - tmp_diff = (move->x > pairlev) ? - move->x - pairlev : pairlev - move->x; - } else { - tmp_diff = (move->y > pairlev) ? - move->y - pairlev : pairlev - move->y; - } - if (tmp_diff < diff) { - diff = tmp_diff; - end_move = move; - } - } - } - } - } else { - /* Find the minimum size. */ - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - } - - /* In case of lazy sifting, end_move identifies the position at - ** which we want to stop. Otherwise, we stop as soon as we meet - ** the minimum size. */ - for (move = moves; move != NULL; move = move->next) { - if (lazyFlag) { - if (move == end_move) return(1); - } else { - if (move->size == size) return(1); - } - if ((table->subtables[move->x].next == move->x) && - (table->subtables[move->y].next == move->y)) { - res = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n"); - assert(table->subtables[move->x].next == move->x); - assert(table->subtables[move->y].next == move->y); -#endif - } else { /* Group move necessary */ - if (move->flags == MTR_NEWNODE) { - ddDissolveGroup(table,(int)move->x,(int)move->y); - } else { - res = ddGroupMoveBackward(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - } - - } - - return(1); - -} /* end of ddGroupSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Merges groups in the DD table.] - - Description [Creates a single group from low to high and adjusts the - index field of the tree node.] - - SideEffects [None] - -******************************************************************************/ -static void -ddMergeGroups( - DdManager * table, - MtrNode * treenode, - int low, - int high) -{ - int i; - MtrNode *auxnode; - int saveindex; - int newindex; - - /* Merge all variables from low to high in one group, unless - ** this is the topmost group. In such a case we do not merge lest - ** we lose the symmetry information. */ - if (treenode != table->tree) { - for (i = low; i < high; i++) - table->subtables[i].next = i+1; - table->subtables[high].next = low; - } - - /* Adjust the index fields of the tree nodes. If a node is the - ** first child of its parent, then the parent may also need adjustment. */ - saveindex = treenode->index; - newindex = table->invperm[low]; - auxnode = treenode; - do { - auxnode->index = newindex; - if (auxnode->parent == NULL || - (int) auxnode->parent->index != saveindex) - break; - auxnode = auxnode->parent; - } while (1); - return; - -} /* end of ddMergeGroups */ - - -/**Function******************************************************************** - - Synopsis [Dissolves a group in the DD table.] - - Description [x and y are variables in a group to be cut in two. The cut - is to pass between x and y.] - - SideEffects [None] - -******************************************************************************/ -static void -ddDissolveGroup( - DdManager * table, - int x, - int y) -{ - int topx; - int boty; - - /* find top and bottom of the two groups */ - boty = y; - while ((unsigned) boty < table->subtables[boty].next) - boty = table->subtables[boty].next; - - topx = table->subtables[boty].next; - - table->subtables[boty].next = y; - table->subtables[x].next = topx; - - return; - -} /* end of ddDissolveGroup */ - - -/**Function******************************************************************** - - Synopsis [Pretends to check two variables for aggregation.] - - Description [Pretends to check two variables for aggregation. Always - returns 0.] - - SideEffects [None] - -******************************************************************************/ -static int -ddNoCheck( - DdManager * table, - int x, - int y) -{ - return(0); - -} /* end of ddNoCheck */ - - -/**Function******************************************************************** - - Synopsis [Checks two variables for aggregation.] - - Description [Checks two variables for aggregation. The check is based - on the second difference of the number of nodes as a function of the - layer. If the second difference is lower than a given threshold - (typically negative) then the two variables should be aggregated. - Returns 1 if the two variables pass the test; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSecDiffCheck( - DdManager * table, - int x, - int y) -{ - double Nx,Nx_1; - double Sx; - double threshold; - int xindex,yindex; - - if (x==0) return(0); - -#ifdef DD_STATS - secdiffcalls++; -#endif - Nx = (double) table->subtables[x].keys; - Nx_1 = (double) table->subtables[x-1].keys; - Sx = (table->subtables[y].keys/Nx) - (Nx/Nx_1); - - threshold = table->recomb / 100.0; - if (Sx < threshold) { - xindex = table->invperm[x]; - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - (void) fprintf(table->out, - "Second difference for %d = %g Pos(%d)\n", - table->invperm[x],Sx,x); -#endif -#ifdef DD_STATS - secdiff++; -#endif - return(1); - } else { -#ifdef DD_STATS - secdiffmisfire++; -#endif - return(0); - } - - } - return(0); - -} /* end of ddSecDiffCheck */ - - -/**Function******************************************************************** - - Synopsis [Checks for extended symmetry of x and y.] - - Description [Checks for extended symmetry of x and y. Returns 1 in - case of extended symmetry; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddExtSymmCheck( - DdManager * table, - int x, - int y) -{ - DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10; - DdNode *one; - int comple; /* f0 is complemented */ - int notproj; /* f is not a projection function */ - int arccount; /* number of arcs from layer x to layer y */ - int TotalRefCount; /* total reference count of layer y minus 1 */ - int counter; /* number of nodes of layer x that are allowed */ - /* to violate extended symmetry conditions */ - int arccounter; /* number of arcs into layer y that are allowed */ - /* to come from layers other than x */ - int i; - int xindex; - int yindex; - int res; - int slots; - DdNodePtr *list; - DdNode *sentinel = &(table->sentinel); - - xindex = table->invperm[x]; - yindex = table->invperm[y]; - - /* If the two variables do not interact, we do not want to merge them. */ - if (!cuddTestInteract(table,xindex,yindex)) - return(0); - -#ifdef DD_DEBUG - /* Checks that x and y do not contain just the projection functions. - ** With the test on interaction, these test become redundant, - ** because an isolated projection function does not interact with - ** any other variable. - */ - if (table->subtables[x].keys == 1) { - assert(table->vars[xindex]->ref != 1); - } - if (table->subtables[y].keys == 1) { - assert(table->vars[yindex]->ref != 1); - } -#endif - -#ifdef DD_STATS - extsymmcalls++; -#endif - - arccount = 0; - counter = (int) (table->subtables[x].keys * - (table->symmviolation/100.0) + 0.5); - one = DD_ONE(table); - - slots = table->subtables[x].slots; - list = table->subtables[x].nodelist; - for (i = 0; i < slots; i++) { - f = list[i]; - while (f != sentinel) { - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); - f0 = Cudd_Regular(cuddE(f)); - comple = Cudd_IsComplement(cuddE(f)); - notproj = f1 != one || f0 != one || f->ref != (DdHalfWord) 1; - if (f1->index == yindex) { - arccount++; - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - if ((int) f0->index != yindex) { - /* If f is an isolated projection function it is - ** allowed to bypass layer y. - */ - if (notproj) { - if (counter == 0) - return(0); - counter--; /* f bypasses layer y */ - } - } - f11 = f10 = f1; - } - if ((int) f0->index == yindex) { - arccount++; - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = f00 = f0; - } - if (comple) { - f01 = Cudd_Not(f01); - f00 = Cudd_Not(f00); - } - - /* Unless we are looking at a projection function - ** without external references except the one from the - ** table, we insist that f01 == f10 or f11 == f00 - */ - if (notproj) { - if (f01 != f10 && f11 != f00) { - if (counter == 0) - return(0); - counter--; - } - } - - f = f->next; - } /* while */ - } /* for */ - - /* Calculate the total reference counts of y */ - TotalRefCount = -1; /* -1 for projection function */ - slots = table->subtables[y].slots; - list = table->subtables[y].nodelist; - for (i = 0; i < slots; i++) { - f = list[i]; - while (f != sentinel) { - TotalRefCount += f->ref; - f = f->next; - } - } - - arccounter = (int) (table->subtables[y].keys * - (table->arcviolation/100.0) + 0.5); - res = arccount >= TotalRefCount - arccounter; - -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if (res) { - (void) fprintf(table->out, - "Found extended symmetry! x = %d\ty = %d\tPos(%d,%d)\n", - xindex,yindex,x,y); - } -#endif - -#ifdef DD_STATS - if (res) - extsymm++; -#endif - return(res); - -} /* end ddExtSymmCheck */ - - -/**Function******************************************************************** - - Synopsis [Checks for grouping of x and y.] - - Description [Checks for grouping of x and y. Returns 1 in - case of grouping; 0 otherwise. This function is used for lazy sifting.] - - SideEffects [None] - -******************************************************************************/ -static int -ddVarGroupCheck( - DdManager * table, - int x, - int y) -{ - int xindex = table->invperm[x]; - int yindex = table->invperm[y]; - - if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0); - - if (Cudd_bddReadPairIndex(table, xindex) == yindex) { - if (ddIsVarHandled(table, xindex) || - ddIsVarHandled(table, yindex)) { - if (Cudd_bddIsVarToBeGrouped(table, xindex) || - Cudd_bddIsVarToBeGrouped(table, yindex) ) { - if (table->keys - table->isolated <= originalSize) { - return(1); - } - } - } - } - - return(0); - -} /* end of ddVarGroupCheck */ - - -/**Function******************************************************************** - - Synopsis [Sets a variable to already handled.] - - Description [Sets a variable to already handled. This function is used - for lazy sifting.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static int -ddSetVarHandled( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].varHandled = 1; - return(1); - -} /* end of ddSetVarHandled */ - - -/**Function******************************************************************** - - Synopsis [Resets a variable to be processed.] - - Description [Resets a variable to be processed. This function is used - for lazy sifting.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static int -ddResetVarHandled( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(0); - dd->subtables[dd->perm[index]].varHandled = 0; - return(1); - -} /* end of ddResetVarHandled */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a variables is already handled.] - - Description [Checks whether a variables is already handled. This - function is used for lazy sifting.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static int -ddIsVarHandled( - DdManager *dd, - int index) -{ - if (index >= dd->size || index < 0) return(-1); - return dd->subtables[dd->perm[index]].varHandled; - -} /* end of ddIsVarHandled */ diff --git a/src/bdd/cudd/cuddHarwell.c b/src/bdd/cudd/cuddHarwell.c deleted file mode 100644 index 063f1922..00000000 --- a/src/bdd/cudd/cuddHarwell.c +++ /dev/null @@ -1,541 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddHarwell.c] - - PackageName [cudd] - - Synopsis [Function to read a matrix in Harwell format.] - - Description [External procedures included in this module: -
              -
            • Cudd_addHarwell() -
            - ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddHarwell.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Reads in a matrix in the format of the Harwell-Boeing - benchmark suite.] - - Description [Reads in a matrix in the format of the Harwell-Boeing - benchmark suite. The variables are ordered as follows: -
            - x\[0\] y\[0\] x\[1\] y\[1\] ... -
            - 0 is the most significant bit. On input, nx and ny hold the numbers - of row and column variables already in existence. On output, they - hold the numbers of row and column variables actually used by the - matrix. m and n are set to the numbers of rows and columns of the - matrix. Their values on input are immaterial. Returns 1 on - success; 0 otherwise. The ADD for the sparse matrix is returned in - E, and its reference count is > 0.] - - SideEffects [None] - - SeeAlso [Cudd_addRead Cudd_bddRead] - -******************************************************************************/ -int -Cudd_addHarwell( - FILE * fp /* pointer to the input file */, - DdManager * dd /* DD manager */, - DdNode ** E /* characteristic function of the graph */, - DdNode *** x /* array of row variables */, - DdNode *** y /* array of column variables */, - DdNode *** xn /* array of complemented row variables */, - DdNode *** yn_ /* array of complemented column variables */, - int * nx /* number or row variables */, - int * ny /* number or column variables */, - int * m /* number of rows */, - int * n /* number of columns */, - int bx /* first index of row variables */, - int sx /* step of row variables */, - int by /* first index of column variables */, - int sy /* step of column variables */, - int pr /* verbosity level */) -{ - DdNode *one, *zero; - DdNode *w; - DdNode *cubex, *cubey, *minterm1; - int u, v, err, i, j, nv; - double val; - DdNode **lx, **ly, **lxn, **lyn; /* local copies of x, y, xn, yn_ */ - int lnx, lny; /* local copies of nx and ny */ - char title[73], key[9], mxtype[4], rhstyp[4]; - int totcrd, ptrcrd, indcrd, valcrd, rhscrd, - nrow, ncol, nnzero, neltvl, - nrhs, nrhsix; - int *colptr, *rowind; -#if 0 - int nguess, nexact; - int *rhsptr, *rhsind; -#endif - - if (*nx < 0 || *ny < 0) return(0); - - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - /* Read the header */ - err = fscanf(fp, "%72c %8c", title, key); - if (err == EOF) { - return(0); - } else if (err != 2) { - return(0); - } - title[72] = (char) 0; - key[8] = (char) 0; - - err = fscanf(fp, "%d %d %d %d %d", &totcrd, &ptrcrd, &indcrd, - &valcrd, &rhscrd); - if (err == EOF) { - return(0); - } else if (err != 5) { - return(0); - } - - err = fscanf(fp, "%3s %d %d %d %d", mxtype, &nrow, &ncol, - &nnzero, &neltvl); - if (err == EOF) { - return(0); - } else if (err != 5) { - return(0); - } - - /* Skip FORTRAN formats */ - if (rhscrd == 0) { - err = fscanf(fp, "%*s %*s %*s \n"); - } else { - err = fscanf(fp, "%*s %*s %*s %*s \n"); - } - if (err == EOF) { - return(0); - } else if (err != 0) { - return(0); - } - - /* Print out some stuff if requested to be verbose */ - if (pr>0) { - (void) fprintf(dd->out,"%s: type %s, %d rows, %d columns, %d entries\n", key, - mxtype, nrow, ncol, nnzero); - if (pr>1) (void) fprintf(dd->out,"%s\n", title); - } - - /* Check matrix type */ - if (mxtype[0] != 'R' || mxtype[1] != 'U' || mxtype[2] != 'A') { - (void) fprintf(dd->err,"%s: Illegal matrix type: %s\n", - key, mxtype); - return(0); - } - if (neltvl != 0) return(0); - - /* Read optional 5-th line */ - if (rhscrd != 0) { - err = fscanf(fp, "%3c %d %d", rhstyp, &nrhs, &nrhsix); - if (err == EOF) { - return(0); - } else if (err != 3) { - return(0); - } - rhstyp[3] = (char) 0; - if (rhstyp[0] != 'F') { - (void) fprintf(dd->err, - "%s: Sparse right-hand side not yet supported\n", key); - return(0); - } - if (pr>0) (void) fprintf(dd->out,"%d right-hand side(s)\n", nrhs); - } else { - nrhs = 0; - } - - /* Compute the number of variables */ - - /* row and column numbers start from 0 */ - u = nrow - 1; - for (i=0; u > 0; i++) { - u >>= 1; - } - lnx = i; - if (nrhs == 0) { - v = ncol - 1; - } else { - v = 2* (ddMax(ncol, nrhs) - 1); - } - for (i=0; v > 0; i++) { - v >>= 1; - } - lny = i; - - /* Allocate or reallocate arrays for variables as needed */ - if (*nx == 0) { - if (lnx > 0) { - *x = lx = ALLOC(DdNode *,lnx); - if (lx == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *xn = lxn = ALLOC(DdNode *,lnx); - if (lxn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } else { - *x = *xn = NULL; - } - } else if (lnx > *nx) { - *x = lx = REALLOC(DdNode *, *x, lnx); - if (lx == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *xn = lxn = REALLOC(DdNode *, *xn, lnx); - if (lxn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } else { - lx = *x; - lxn = *xn; - } - if (*ny == 0) { - if (lny >0) { - *y = ly = ALLOC(DdNode *,lny); - if (ly == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *yn_ = lyn = ALLOC(DdNode *,lny); - if (lyn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } else { - *y = *yn_ = NULL; - } - } else if (lny > *ny) { - *y = ly = REALLOC(DdNode *, *y, lny); - if (ly == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *yn_ = lyn = REALLOC(DdNode *, *yn_, lny); - if (lyn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } else { - ly = *y; - lyn = *yn_; - } - - /* Create new variables as needed */ - for (i= *nx,nv=bx+(*nx)*sx; i < lnx; i++,nv+=sx) { - do { - dd->reordered = 0; - lx[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (lx[i] == NULL) return(0); - cuddRef(lx[i]); - do { - dd->reordered = 0; - lxn[i] = cuddUniqueInter(dd, nv, zero, one); - } while (dd->reordered == 1); - if (lxn[i] == NULL) return(0); - cuddRef(lxn[i]); - } - for (i= *ny,nv=by+(*ny)*sy; i < lny; i++,nv+=sy) { - do { - dd->reordered = 0; - ly[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (ly[i] == NULL) return(0); - cuddRef(ly[i]); - do { - dd->reordered = 0; - lyn[i] = cuddUniqueInter(dd, nv, zero, one); - } while (dd->reordered == 1); - if (lyn[i] == NULL) return(0); - cuddRef(lyn[i]); - } - - /* Update matrix parameters */ - *nx = lnx; - *ny = lny; - *m = nrow; - if (nrhs == 0) { - *n = ncol; - } else { - *n = (1 << (lny - 1)) + nrhs; - } - - /* Read structure data */ - colptr = ALLOC(int, ncol+1); - if (colptr == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - rowind = ALLOC(int, nnzero); - if (rowind == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - - for (i=0; ierr,"%s: Unexpected colptr[0] (%d)\n", - key,colptr[0]); - FREE(colptr); - FREE(rowind); - return(0); - } - for (i=0; i=0; nv--) { - if (v & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - FREE(colptr); - FREE(rowind); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, cubey); - cubey = w; - v >>= 1; - } - for (i=colptr[j]; i=0; nv--) { - if (u & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - Cudd_RecursiveDeref(dd, cubex); - FREE(colptr); - FREE(rowind); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, cubex); - cubex = w; - u >>= 1; - } - minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex); - if (minterm1 == NULL) { - Cudd_RecursiveDeref(dd, cubey); - Cudd_RecursiveDeref(dd, cubex); - FREE(colptr); - FREE(rowind); - return(0); - } - cuddRef(minterm1); - Cudd_RecursiveDeref(dd, cubex); - w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1); - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - FREE(colptr); - FREE(rowind); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - Cudd_RecursiveDeref(dd, *E); - *E = w; - } - Cudd_RecursiveDeref(dd, cubey); - } - FREE(colptr); - FREE(rowind); - - /* Read right-hand sides */ - for (j=0; j=0; nv--) { - if (v & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, cubey, ly[nv]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, cubey, lyn[nv]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, cubey); - cubey = w; - v >>= 1; - } - for (i=0; i=0; nv--) { - if (u & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, cubex, lx[nv]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, cubex, lxn[nv]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - Cudd_RecursiveDeref(dd, cubex); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, cubex); - cubex = w; - u >>= 1; - } - minterm1 = Cudd_addApply(dd, Cudd_addTimes, cubey, cubex); - if (minterm1 == NULL) { - Cudd_RecursiveDeref(dd, cubey); - Cudd_RecursiveDeref(dd, cubex); - return(0); - } - cuddRef(minterm1); - Cudd_RecursiveDeref(dd, cubex); - w = Cudd_addApply(dd, Cudd_addPlus, *E, minterm1); - if (w == NULL) { - Cudd_RecursiveDeref(dd, cubey); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - Cudd_RecursiveDeref(dd, *E); - *E = w; - } - Cudd_RecursiveDeref(dd, cubey); - } - - return(1); - -} /* end of Cudd_addHarwell */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddInit.c b/src/bdd/cudd/cuddInit.c deleted file mode 100644 index 8e06a425..00000000 --- a/src/bdd/cudd/cuddInit.c +++ /dev/null @@ -1,283 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddInit.c] - - PackageName [cudd] - - Synopsis [Functions to initialize and shut down the DD manager.] - - Description [External procedures included in this module: -
              -
            • Cudd_Init() -
            • Cudd_Quit() -
            - Internal procedures included in this module: -
              -
            • cuddZddInitUniv() -
            • cuddZddFreeUniv() -
            - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#define CUDD_MAIN -#include "cuddInt.h" -#undef CUDD_MAIN - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddInit.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Creates a new DD manager.] - - Description [Creates a new DD manager, initializes the table, the - basic constants and the projection functions. If maxMemory is 0, - Cudd_Init decides suitable values for the maximum size of the cache - and for the limit for fast unique table growth based on the available - memory. Returns a pointer to the manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Quit] - -******************************************************************************/ -DdManager * -Cudd_Init( - unsigned int numVars /* initial number of BDD variables (i.e., subtables) */, - unsigned int numVarsZ /* initial number of ZDD variables (i.e., subtables) */, - unsigned int numSlots /* initial size of the unique tables */, - unsigned int cacheSize /* initial size of the cache */, - unsigned long maxMemory /* target maximum memory occupation */) -{ - DdManager *unique; - int i,result; - DdNode *one, *zero; - unsigned int maxCacheSize; - unsigned int looseUpTo; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - if (maxMemory == 0) { - maxMemory = getSoftDataLimit(); - } - looseUpTo = (unsigned int) ((maxMemory / sizeof(DdNode)) / - DD_MAX_LOOSE_FRACTION); - unique = cuddInitTable(numVars,numVarsZ,numSlots,looseUpTo); - unique->maxmem = (unsigned) maxMemory / 10 * 9; - if (unique == NULL) return(NULL); - maxCacheSize = (unsigned int) ((maxMemory / sizeof(DdCache)) / - DD_MAX_CACHE_FRACTION); - result = cuddInitCache(unique,cacheSize,maxCacheSize); - if (result == 0) return(NULL); - - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - unique->stash = ALLOC(char,(maxMemory / DD_STASH_FRACTION) + 4); - MMoutOfMemory = saveHandler; - if (unique->stash == NULL) { - (void) fprintf(unique->err,"Unable to set aside memory\n"); - } - - /* Initialize constants. */ - unique->one = cuddUniqueConst(unique,1.0); - if (unique->one == NULL) return(0); - cuddRef(unique->one); - unique->zero = cuddUniqueConst(unique,0.0); - if (unique->zero == NULL) return(0); - cuddRef(unique->zero); -#ifdef HAVE_IEEE_754 - if (DD_PLUS_INF_VAL != DD_PLUS_INF_VAL * 3 || - DD_PLUS_INF_VAL != DD_PLUS_INF_VAL / 3) { - (void) fprintf(unique->err,"Warning: Crippled infinite values\n"); - (void) fprintf(unique->err,"Recompile without -DHAVE_IEEE_754\n"); - } -#endif - unique->plusinfinity = cuddUniqueConst(unique,DD_PLUS_INF_VAL); - if (unique->plusinfinity == NULL) return(0); - cuddRef(unique->plusinfinity); - unique->minusinfinity = cuddUniqueConst(unique,DD_MINUS_INF_VAL); - if (unique->minusinfinity == NULL) return(0); - cuddRef(unique->minusinfinity); - unique->background = unique->zero; - - /* The logical zero is different from the CUDD_VALUE_TYPE zero! */ - one = unique->one; - zero = Cudd_Not(one); - /* Create the projection functions. */ - unique->vars = ALLOC(DdNodePtr,unique->maxSize); - if (unique->vars == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < unique->size; i++) { - unique->vars[i] = cuddUniqueInter(unique,i,one,zero); - if (unique->vars[i] == NULL) return(0); - cuddRef(unique->vars[i]); - } - - if (unique->sizeZ) - cuddZddInitUniv(unique); - - unique->memused += sizeof(DdNode *) * unique->maxSize; - - return(unique); - -} /* end of Cudd_Init */ - - -/**Function******************************************************************** - - Synopsis [Deletes resources associated with a DD manager.] - - Description [Deletes resources associated with a DD manager and - resets the global statistical counters. (Otherwise, another manaqger - subsequently created would inherit the stats of this one.)] - - SideEffects [None] - - SeeAlso [Cudd_Init] - -******************************************************************************/ -void -Cudd_Quit( - DdManager * unique) -{ - if (unique->stash != NULL) FREE(unique->stash); - cuddFreeTable(unique); - -} /* end of Cudd_Quit */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Initializes the ZDD universe.] - - Description [Initializes the ZDD universe. Returns 1 if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddZddFreeUniv] - -******************************************************************************/ -int -cuddZddInitUniv( - DdManager * zdd) -{ - DdNode *p, *res; - int i; - - zdd->univ = ALLOC(DdNodePtr, zdd->sizeZ); - if (zdd->univ == NULL) { - zdd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - - res = DD_ONE(zdd); - cuddRef(res); - for (i = zdd->sizeZ - 1; i >= 0; i--) { - unsigned int index = zdd->invpermZ[i]; - p = res; - res = cuddUniqueInterZdd(zdd, index, p, p); - if (res == NULL) { - Cudd_RecursiveDerefZdd(zdd,p); - FREE(zdd->univ); - return(0); - } - cuddRef(res); - cuddDeref(p); - zdd->univ[i] = res; - } - -#ifdef DD_VERBOSE - cuddZddP(zdd, zdd->univ[0]); -#endif - - return(1); - -} /* end of cuddZddInitUniv */ - - -/**Function******************************************************************** - - Synopsis [Frees the ZDD universe.] - - Description [Frees the ZDD universe.] - - SideEffects [None] - - SeeAlso [cuddZddInitUniv] - -******************************************************************************/ -void -cuddZddFreeUniv( - DdManager * zdd) -{ - if (zdd->univ) { - Cudd_RecursiveDerefZdd(zdd, zdd->univ[0]); - FREE(zdd->univ); - } - -} /* end of cuddZddFreeUniv */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddInt.h b/src/bdd/cudd/cuddInt.h deleted file mode 100644 index a5d0cf16..00000000 --- a/src/bdd/cudd/cuddInt.h +++ /dev/null @@ -1,1133 +0,0 @@ -/**CHeaderFile***************************************************************** - - FileName [cuddInt.h] - - PackageName [cudd] - - Synopsis [Internal data structures of the CUDD package.] - - Description [] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: cuddInt.h,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $] - -******************************************************************************/ - -#ifndef _CUDDINT -#define _CUDDINT - - -/*---------------------------------------------------------------------------*/ -/* Nested includes */ -/*---------------------------------------------------------------------------*/ - -#ifdef DD_MIS -#include "array.h" -#include "list.h" -#include "st.h" -#include "espresso.h" -#include "node.h" -#ifdef SIS -#include "graph.h" -#include "astg.h" -#endif -#include "network.h" -#endif - -#include -#include "cudd.h" -#include "st.h" - -#if defined(__GNUC__) -# define DD_INLINE __inline__ -# if (__GNUC__ >2 || __GNUC_MINOR__ >=7) -# define DD_UNUSED __attribute__ ((__unused__)) -# else -# define DD_UNUSED -# endif -#else -# if defined(__cplusplus) -# define DD_INLINE inline -# else -# define DD_INLINE -# endif -# define DD_UNUSED -#endif - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_MAXREF ((DdHalfWord) ~0) - -#define DD_DEFAULT_RESIZE 10 /* how many extra variables */ - /* should be added when resizing */ -#define DD_MEM_CHUNK 1022 - -/* These definitions work for CUDD_VALUE_TYPE == double */ -#define DD_ONE_VAL (1.0) -#define DD_ZERO_VAL (0.0) -#define DD_EPSILON (1.0e-12) - -/* The definitions of +/- infinity in terms of HUGE_VAL work on -** the DECstations and on many other combinations of OS/compiler. -*/ -#ifdef HAVE_IEEE_754 -# define DD_PLUS_INF_VAL (HUGE_VAL) -#else -# define DD_PLUS_INF_VAL (10e301) -# define DD_CRI_HI_MARK (10e150) -# define DD_CRI_LO_MARK (-(DD_CRI_HI_MARK)) -#endif -#define DD_MINUS_INF_VAL (-(DD_PLUS_INF_VAL)) - -#define DD_NON_CONSTANT ((DdNode *) 1) /* for Cudd_bddIteConstant */ - -/* Unique table and cache management constants. */ -#define DD_MAX_SUBTABLE_DENSITY 4 /* tells when to resize a subtable */ -/* gc when this percent are dead (measured w.r.t. slots, not keys) -** The first limit (LO) applies normally. The second limit applies when -** the package believes more space for the unique table (i.e., more dead -** nodes) would improve performance, and the unique table is not already -** too large. The third limit applies when memory is low. -*/ -#define DD_GC_FRAC_LO DD_MAX_SUBTABLE_DENSITY * 0.25 -#define DD_GC_FRAC_HI DD_MAX_SUBTABLE_DENSITY * 1.0 -#define DD_GC_FRAC_MIN 0.2 -#define DD_MIN_HIT 30 /* resize cache when hit ratio - above this percentage (default) */ -#define DD_MAX_LOOSE_FRACTION 5 /* 1 / (max fraction of memory used for - unique table in fast growth mode) */ -#define DD_MAX_CACHE_FRACTION 3 /* 1 / (max fraction of memory used for - computed table if resizing enabled) */ -#define DD_STASH_FRACTION 64 /* 1 / (fraction of memory set - aside for emergencies) */ -#define DD_MAX_CACHE_TO_SLOTS_RATIO 4 /* used to limit the cache size */ - -/* Variable ordering default parameter values. */ -#define DD_SIFT_MAX_VAR 1000 -#define DD_SIFT_MAX_SWAPS 2000000 -#define DD_DEFAULT_RECOMB 0 -#define DD_MAX_REORDER_GROWTH 1.2 -#define DD_FIRST_REORDER 4004 /* 4 for the constants */ -#define DD_DYN_RATIO 2 /* when to dynamically reorder */ - -/* Primes for cache hash functions. */ -#define DD_P1 12582917 -#define DD_P2 4256249 -#define DD_P3 741457 -#define DD_P4 1618033999 - -/* Cache tags for 3-operand operators. These tags are stored in the -** least significant bits of the cache operand pointers according to -** the following scheme. The tag consists of two hex digits. Both digits -** must be even, so that they do not interfere with complementation bits. -** The least significant one is stored in Bits 3:1 of the f operand in the -** cache entry. Bit 1 is always 1, so that we can differentiate -** three-operand operations from one- and two-operand operations. -** Therefore, the least significant digit is one of {2,6,a,e}. The most -** significant digit occupies Bits 3:1 of the g operand in the cache -** entry. It can by any even digit between 0 and e. This gives a total -** of 5 bits for the tag proper, which means a maximum of 32 three-operand -** operations. */ -#define DD_ADD_ITE_TAG 0x02 -#define DD_BDD_AND_ABSTRACT_TAG 0x06 -#define DD_BDD_XOR_EXIST_ABSTRACT_TAG 0x0a -#define DD_BDD_ITE_TAG 0x0e -#define DD_ADD_BDD_DO_INTERVAL_TAG 0x22 -#define DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG 0x26 -#define DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG 0x2a -#define DD_BDD_COMPOSE_RECUR_TAG 0x2e -#define DD_ADD_COMPOSE_RECUR_TAG 0x42 -#define DD_ADD_NON_SIM_COMPOSE_TAG 0x46 -#define DD_EQUIV_DC_TAG 0x4a -#define DD_ZDD_ITE_TAG 0x4e -#define DD_ADD_ITE_CONSTANT_TAG 0x62 -#define DD_ADD_EVAL_CONST_TAG 0x66 -#define DD_BDD_ITE_CONSTANT_TAG 0x6a -#define DD_ADD_OUT_SUM_TAG 0x6e -#define DD_BDD_LEQ_UNLESS_TAG 0x82 -#define DD_ADD_TRIANGLE_TAG 0x86 - -/* Generator constants. */ -#define CUDD_GEN_CUBES 0 -#define CUDD_GEN_NODES 1 -#define CUDD_GEN_ZDD_PATHS 2 -#define CUDD_GEN_EMPTY 0 -#define CUDD_GEN_NONEMPTY 1 - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -struct DdGen { - DdManager *manager; - int type; - int status; - union { - struct { - int *cube; - CUDD_VALUE_TYPE value; - } cubes; - struct { - st_table *visited; - st_generator *stGen; - } nodes; - } gen; - struct { - int sp; - DdNode **stack; - } stack; - DdNode *node; -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/* Hooks in CUDD are functions that the application registers with the -** manager so that they are called at appropriate times. The functions -** are passed the manager as argument; they should return 1 if -** successful and 0 otherwise. -*/ -typedef struct DdHook { /* hook list element */ - int (*f) ARGS((DdManager *, char *, void *)); /* function to be called */ - struct DdHook *next; /* next element in the list */ -} DdHook; - -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -typedef long ptrint; -typedef unsigned long ptruint; -#else -typedef int ptrint; -typedef unsigned int ptruint; -#endif - -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - -typedef DdNode *DdNodePtr; - -/* Generic local cache item. */ -typedef struct DdLocalCacheItem { - DdNode *value; -#ifdef DD_CACHE_PROFILE - ptrint count; -#endif - DdNode *key[1]; -} DdLocalCacheItem; - -/* Local cache. */ -typedef struct DdLocalCache { - DdLocalCacheItem *item; - unsigned int itemsize; - unsigned int keysize; - unsigned int slots; - int shift; - double lookUps; - double minHit; - double hits; - unsigned int maxslots; - DdManager *manager; - struct DdLocalCache *next; -} DdLocalCache; - -/* Generic hash item. */ -typedef struct DdHashItem { - struct DdHashItem *next; - ptrint count; - DdNode *value; - DdNode *key[1]; -} DdHashItem; - -/* Local hash table */ -typedef struct DdHashTable { - unsigned int keysize; - unsigned int itemsize; - DdHashItem **bucket; - DdHashItem *nextFree; - DdHashItem **memoryList; - unsigned int numBuckets; - int shift; - unsigned int size; - unsigned int maxsize; - DdManager *manager; -} DdHashTable; - -typedef struct DdCache { - DdNode *f,*g; /* DDs */ - ptruint h; /* either operator or DD */ - DdNode *data; /* already constructed DD */ -#ifdef DD_CACHE_PROFILE - ptrint count; -#endif -} DdCache; - -typedef struct DdSubtable { /* subtable for one index */ - DdNode **nodelist; /* hash table */ - int shift; /* shift for hash function */ - unsigned int slots; /* size of the hash table */ - unsigned int keys; /* number of nodes stored in this table */ - unsigned int maxKeys; /* slots * DD_MAX_SUBTABLE_DENSITY */ - unsigned int dead; /* number of dead nodes in this table */ - unsigned int next; /* index of next variable in group */ - int bindVar; /* flag to bind this variable to its level */ - /* Fields for lazy sifting. */ - Cudd_VariableType varType; /* variable type (ps, ns, pi) */ - int pairIndex; /* corresponding variable index (ps <-> ns) */ - int varHandled; /* flag: 1 means variable is already handled */ - Cudd_LazyGroupType varToBeGrouped; /* tells what grouping to apply */ -} DdSubtable; - -struct DdManager { /* specialized DD symbol table */ - /* Constants */ - DdNode sentinel; /* for collision lists */ - DdNode *one; /* constant 1 */ - DdNode *zero; /* constant 0 */ - DdNode *plusinfinity; /* plus infinity */ - DdNode *minusinfinity; /* minus infinity */ - DdNode *background; /* background value */ - /* Computed Table */ - DdCache *acache; /* address of allocated memory for cache */ - DdCache *cache; /* the cache-based computed table */ - unsigned int cacheSlots; /* total number of cache entries */ - int cacheShift; /* shift value for cache hash function */ - double cacheMisses; /* number of cache misses (since resizing) */ - double cacheHits; /* number of cache hits (since resizing) */ - double minHit; /* hit percentage above which to resize */ - int cacheSlack; /* slots still available for resizing */ - unsigned int maxCacheHard; /* hard limit for cache size */ - /* Unique Table */ - int size; /* number of unique subtables */ - int sizeZ; /* for ZDD */ - int maxSize; /* max number of subtables before resizing */ - int maxSizeZ; /* for ZDD */ - DdSubtable *subtables; /* array of unique subtables */ - DdSubtable *subtableZ; /* for ZDD */ - DdSubtable constants; /* unique subtable for the constants */ - unsigned int slots; /* total number of hash buckets */ - unsigned int keys; /* total number of BDD and ADD nodes */ - unsigned int keysZ; /* total number of ZDD nodes */ - unsigned int dead; /* total number of dead BDD and ADD nodes */ - unsigned int deadZ; /* total number of dead ZDD nodes */ - unsigned int maxLive; /* maximum number of live nodes */ - unsigned int minDead; /* do not GC if fewer than these dead */ - double gcFrac; /* gc when this fraction is dead */ - int gcEnabled; /* gc is enabled */ - unsigned int looseUpTo; /* slow growth beyond this limit */ - /* (measured w.r.t. slots, not keys) */ - unsigned int initSlots; /* initial size of a subtable */ - DdNode **stack; /* stack for iterative procedures */ - double allocated; /* number of nodes allocated */ - /* (not during reordering) */ - double reclaimed; /* number of nodes brought back from the dead */ - int isolated; /* isolated projection functions */ - int *perm; /* current variable perm. (index to level) */ - int *permZ; /* for ZDD */ - int *invperm; /* current inv. var. perm. (level to index) */ - int *invpermZ; /* for ZDD */ - DdNode **vars; /* projection functions */ - int *map; /* variable map for fast swap */ - DdNode **univ; /* ZDD 1 for each variable */ - int linearSize; /* number of rows and columns of linear */ - long *interact; /* interacting variable matrix */ - long *linear; /* linear transform matrix */ - /* Memory Management */ - DdNode **memoryList; /* memory manager for symbol table */ - DdNode *nextFree; /* list of free nodes */ - char *stash; /* memory reserve */ -#ifndef DD_NO_DEATH_ROW - DdNode **deathRow; /* queue for dereferencing */ - int deathRowDepth; /* number of slots in the queue */ - int nextDead; /* index in the queue */ - unsigned deadMask; /* mask for circular index update */ -#endif - /* General Parameters */ - CUDD_VALUE_TYPE epsilon; /* tolerance on comparisons */ - /* Dynamic Reordering Parameters */ - int reordered; /* flag set at the end of reordering */ - int reorderings; /* number of calls to Cudd_ReduceHeap */ - int siftMaxVar; /* maximum number of vars sifted */ - int siftMaxSwap; /* maximum number of swaps per sifting */ - double maxGrowth; /* maximum growth during reordering */ - double maxGrowthAlt; /* alternate maximum growth for reordering */ - int reordCycle; /* how often to apply alternate threshold */ - int autoDyn; /* automatic dynamic reordering flag (BDD) */ - int autoDynZ; /* automatic dynamic reordering flag (ZDD) */ - Cudd_ReorderingType autoMethod; /* default reordering method */ - Cudd_ReorderingType autoMethodZ; /* default reordering method (ZDD) */ - int realign; /* realign ZDD order after BDD reordering */ - int realignZ; /* realign BDD order after ZDD reordering */ - unsigned int nextDyn; /* reorder if this size is reached */ - unsigned int countDead; /* if 0, count deads to trigger reordering */ - MtrNode *tree; /* Variable group tree (BDD) */ - MtrNode *treeZ; /* Variable group tree (ZDD) */ - Cudd_AggregationType groupcheck; /* Used during group sifting */ - int recomb; /* Used during group sifting */ - int symmviolation; /* Used during group sifting */ - int arcviolation; /* Used during group sifting */ - int populationSize; /* population size for GA */ - int numberXovers; /* number of crossovers for GA */ - DdLocalCache *localCaches; /* local caches currently in existence */ -#ifdef __osf__ -#pragma pointer_size restore -#endif - char *hooks; /* application-specific field (used by vis) */ - DdHook *preGCHook; /* hooks to be called before GC */ - DdHook *postGCHook; /* hooks to be called after GC */ - DdHook *preReorderingHook; /* hooks to be called before reordering */ - DdHook *postReorderingHook; /* hooks to be called after reordering */ - FILE *out; /* stdout for this manager */ - FILE *err; /* stderr for this manager */ -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - Cudd_ErrorType errorCode; /* info on last error */ - /* Statistical counters. */ - long memused; /* total memory allocated for the manager */ - long maxmem; /* target maximum memory */ - long maxmemhard; /* hard limit for maximum memory */ - int garbageCollections; /* number of garbage collections */ - long GCTime; /* total time spent in garbage collection */ - long reordTime; /* total time spent in reordering */ - double totCachehits; /* total number of cache hits */ - double totCacheMisses; /* total number of cache misses */ - double cachecollisions; /* number of cache collisions */ - double cacheinserts; /* number of cache insertions */ - double cacheLastInserts; /* insertions at the last cache resizing */ - double cachedeletions; /* number of deletions during garbage coll. */ -#ifdef DD_STATS - double nodesFreed; /* number of nodes returned to the free list */ - double nodesDropped; /* number of nodes killed by dereferencing */ -#endif - unsigned int peakLiveNodes; /* maximum number of live nodes */ -#ifdef DD_UNIQUE_PROFILE - double uniqueLookUps; /* number of unique table lookups */ - double uniqueLinks; /* total distance traveled in coll. chains */ -#endif -#ifdef DD_COUNT - double recursiveCalls; /* number of recursive calls */ -#ifdef DD_STATS - double nextSample; /* when to write next line of stats */ -#endif - double swapSteps; /* number of elementary reordering steps */ -#endif -#ifdef DD_MIS - /* mis/verif compatibility fields */ - array_t *iton; /* maps ids in ddNode to node_t */ - array_t *order; /* copy of order_list */ - lsHandle handle; /* where it is in network BDD list */ - network_t *network; - st_table *local_order; /* for local BDDs */ - int nvars; /* variables used so far */ - int threshold; /* for pseudo var threshold value*/ -#endif -}; - -typedef struct Move { - DdHalfWord x; - DdHalfWord y; - unsigned int flags; - int size; - struct Move *next; -} Move; - -/* Generic level queue item. */ -typedef struct DdQueueItem { - struct DdQueueItem *next; - struct DdQueueItem *cnext; - void *key; -} DdQueueItem; - -/* Level queue. */ -typedef struct DdLevelQueue { - void *first; - DdQueueItem **last; - DdQueueItem *freelist; - DdQueueItem **buckets; - int levels; - int itemsize; - int size; - int maxsize; - int numBuckets; - int shift; -} DdLevelQueue; - -#ifdef __osf__ -#pragma pointer_size restore -#endif - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**Macro*********************************************************************** - - Synopsis [Adds node to the head of the free list.] - - Description [Adds node to the head of the free list. Does not - deallocate memory chunks that become free. This function is also - used by the dynamic reordering functions.] - - SideEffects [None] - - SeeAlso [cuddAllocNode cuddDynamicAllocNode] - -******************************************************************************/ -#define cuddDeallocNode(unique,node) \ - (node)->next = (unique)->nextFree; \ - (unique)->nextFree = node; - - -/**Macro*********************************************************************** - - Synopsis [Increases the reference count of a node, if it is not - saturated.] - - Description [Increases the reference count of a node, if it is not - saturated. This being a macro, it is faster than Cudd_Ref, but it - cannot be used in constructs like cuddRef(a = b()).] - - SideEffects [none] - - SeeAlso [Cudd_Ref] - -******************************************************************************/ -#define cuddRef(n) cuddSatInc(Cudd_Regular(n)->ref) - - -/**Macro*********************************************************************** - - Synopsis [Decreases the reference count of a node, if it is not - saturated.] - - Description [Decreases the reference count of node. It is primarily - used in recursive procedures to decrease the ref count of a result - node before returning it. This accomplishes the goal of removing the - protection applied by a previous cuddRef. This being a macro, it is - faster than Cudd_Deref, but it cannot be used in constructs like - cuddDeref(a = b()).] - - SideEffects [none] - - SeeAlso [Cudd_Deref] - -******************************************************************************/ -#define cuddDeref(n) cuddSatDec(Cudd_Regular(n)->ref) - - -/**Macro*********************************************************************** - - Synopsis [Returns 1 if the node is a constant node.] - - Description [Returns 1 if the node is a constant node (rather than an - internal node). All constant nodes have the same index - (CUDD_CONST_INDEX). The pointer passed to cuddIsConstant must be regular.] - - SideEffects [none] - - SeeAlso [Cudd_IsConstant] - -******************************************************************************/ -#define cuddIsConstant(node) ((node)->index == CUDD_CONST_INDEX) - - -/**Macro*********************************************************************** - - Synopsis [Returns the then child of an internal node.] - - Description [Returns the then child of an internal node. If - node is a constant node, the result is unpredictable. - The pointer passed to cuddT must be regular.] - - SideEffects [none] - - SeeAlso [Cudd_T] - -******************************************************************************/ -#define cuddT(node) ((node)->type.kids.T) - - -/**Macro*********************************************************************** - - Synopsis [Returns the else child of an internal node.] - - Description [Returns the else child of an internal node. If - node is a constant node, the result is unpredictable. - The pointer passed to cuddE must be regular.] - - SideEffects [none] - - SeeAlso [Cudd_E] - -******************************************************************************/ -#define cuddE(node) ((node)->type.kids.E) - - -/**Macro*********************************************************************** - - Synopsis [Returns the value of a constant node.] - - Description [Returns the value of a constant node. If - node is an internal node, the result is unpredictable. - The pointer passed to cuddV must be regular.] - - SideEffects [none] - - SeeAlso [Cudd_V] - -******************************************************************************/ -#define cuddV(node) ((node)->type.value) - - -/**Macro*********************************************************************** - - Synopsis [Finds the current position of variable index in the - order.] - - Description [Finds the current position of variable index in the - order. This macro duplicates the functionality of Cudd_ReadPerm, - but it does not check for out-of-bounds indices and it is more - efficient.] - - SideEffects [none] - - SeeAlso [Cudd_ReadPerm] - -******************************************************************************/ -#define cuddI(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->perm[(index)]) - - -/**Macro*********************************************************************** - - Synopsis [Finds the current position of ZDD variable index in the - order.] - - Description [Finds the current position of ZDD variable index in the - order. This macro duplicates the functionality of Cudd_ReadPermZdd, - but it does not check for out-of-bounds indices and it is more - efficient.] - - SideEffects [none] - - SeeAlso [Cudd_ReadPermZdd] - -******************************************************************************/ -#define cuddIZ(dd,index) (((index)==CUDD_CONST_INDEX)?(int)(index):(dd)->permZ[(index)]) - - -/**Macro*********************************************************************** - - Synopsis [Hash function for the unique table.] - - Description [] - - SideEffects [none] - - SeeAlso [ddCHash ddCHash2] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define ddHash(f,g,s) \ -((((unsigned)(unsigned long)(f) * DD_P1 + \ - (unsigned)(unsigned long)(g)) * DD_P2) >> (s)) -#else -#define ddHash(f,g,s) \ -((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Hash function for the cache.] - - Description [] - - SideEffects [none] - - SeeAlso [ddHash ddCHash2] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define ddCHash(o,f,g,h,s) \ -((((((unsigned)(unsigned long)(f) + (unsigned)(unsigned long)(o)) * DD_P1 + \ - (unsigned)(unsigned long)(g)) * DD_P2 + \ - (unsigned)(unsigned long)(h)) * DD_P3) >> (s)) -#else -#define ddCHash(o,f,g,h,s) \ -((((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2 + \ - (unsigned)(h)) * DD_P3) >> (s)) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Hash function for the cache for functions with two - operands.] - - Description [] - - SideEffects [none] - - SeeAlso [ddHash ddCHash] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define ddCHash2(o,f,g,s) \ -(((((unsigned)(unsigned long)(f) + (unsigned)(unsigned long)(o)) * DD_P1 + \ - (unsigned)(unsigned long)(g)) * DD_P2) >> (s)) -#else -#define ddCHash2(o,f,g,s) \ -(((((unsigned)(f) + (unsigned)(o)) * DD_P1 + (unsigned)(g)) * DD_P2) >> (s)) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Clears the 4 least significant bits of a pointer.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -#define cuddClean(p) ((DdNode *)((ptruint)(p) & ~0xf)) - - -/**Macro*********************************************************************** - - Synopsis [Computes the minimum of two numbers.] - - Description [] - - SideEffects [none] - - SeeAlso [ddMax] - -******************************************************************************/ -#define ddMin(x,y) (((y) < (x)) ? (y) : (x)) - - -/**Macro*********************************************************************** - - Synopsis [Computes the maximum of two numbers.] - - Description [] - - SideEffects [none] - - SeeAlso [ddMin] - -******************************************************************************/ -#define ddMax(x,y) (((y) > (x)) ? (y) : (x)) - - -/**Macro*********************************************************************** - - Synopsis [Computes the absolute value of a number.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -#define ddAbs(x) (((x)<0) ? -(x) : (x)) - - -/**Macro*********************************************************************** - - Synopsis [Returns 1 if the absolute value of the difference of the two - arguments x and y is less than e.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -#define ddEqualVal(x,y,e) (ddAbs((x)-(y))<(e)) - - -/**Macro*********************************************************************** - - Synopsis [Saturating increment operator.] - - Description [] - - SideEffects [none] - - SeeAlso [cuddSatDec] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define cuddSatInc(x) ((x)++) -#else -#define cuddSatInc(x) ((x) += (x) != (DdHalfWord)DD_MAXREF) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Saturating decrement operator.] - - Description [] - - SideEffects [none] - - SeeAlso [cuddSatInc] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define cuddSatDec(x) ((x)--) -#else -#define cuddSatDec(x) ((x) -= (x) != (DdHalfWord)DD_MAXREF) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Returns the constant 1 node.] - - Description [] - - SideEffects [none] - - SeeAlso [DD_ZERO DD_PLUS_INFINITY DD_MINUS_INFINITY] - -******************************************************************************/ -#define DD_ONE(dd) ((dd)->one) - - -/**Macro*********************************************************************** - - Synopsis [Returns the arithmetic 0 constant node.] - - Description [Returns the arithmetic 0 constant node. This is different - from the logical zero. The latter is obtained by - Cudd_Not(DD_ONE(dd)).] - - SideEffects [none] - - SeeAlso [DD_ONE Cudd_Not DD_PLUS_INFINITY DD_MINUS_INFINITY] - -******************************************************************************/ -#define DD_ZERO(dd) ((dd)->zero) - - -/**Macro*********************************************************************** - - Synopsis [Returns the plus infinity constant node.] - - Description [] - - SideEffects [none] - - SeeAlso [DD_ONE DD_ZERO DD_MINUS_INFINITY] - -******************************************************************************/ -#define DD_PLUS_INFINITY(dd) ((dd)->plusinfinity) - - -/**Macro*********************************************************************** - - Synopsis [Returns the minus infinity constant node.] - - Description [] - - SideEffects [none] - - SeeAlso [DD_ONE DD_ZERO DD_PLUS_INFINITY] - -******************************************************************************/ -#define DD_MINUS_INFINITY(dd) ((dd)->minusinfinity) - - -/**Macro*********************************************************************** - - Synopsis [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL.] - - Description [Enforces DD_MINUS_INF_VAL <= x <= DD_PLUS_INF_VAL. - Furthermore, if x <= DD_MINUS_INF_VAL/2, x is set to - DD_MINUS_INF_VAL. Similarly, if DD_PLUS_INF_VAL/2 <= x, x is set to - DD_PLUS_INF_VAL. Normally this macro is a NOOP. However, if - HAVE_IEEE_754 is not defined, it makes sure that a value does not - get larger than infinity in absolute value, and once it gets to - infinity, stays there. If the value overflows before this macro is - applied, no recovery is possible.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -#ifdef HAVE_IEEE_754 -#define cuddAdjust(x) -#else -#define cuddAdjust(x) ((x) = ((x) >= DD_CRI_HI_MARK) ? DD_PLUS_INF_VAL : (((x) <= DD_CRI_LO_MARK) ? DD_MINUS_INF_VAL : (x))) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Extract the least significant digit of a double digit.] - - Description [Extract the least significant digit of a double digit. Used - in the manipulation of arbitrary precision integers.] - - SideEffects [None] - - SeeAlso [DD_MSDIGIT] - -******************************************************************************/ -#define DD_LSDIGIT(x) ((x) & DD_APA_MASK) - - -/**Macro*********************************************************************** - - Synopsis [Extract the most significant digit of a double digit.] - - Description [Extract the most significant digit of a double digit. Used - in the manipulation of arbitrary precision integers.] - - SideEffects [None] - - SeeAlso [DD_LSDIGIT] - -******************************************************************************/ -#define DD_MSDIGIT(x) ((x) >> DD_APA_BITS) - - -/**Macro*********************************************************************** - - Synopsis [Outputs a line of stats.] - - Description [Outputs a line of stats if DD_COUNT and DD_STATS are - defined. Increments the number of recursive calls if DD_COUNT is - defined.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -#ifdef DD_COUNT -#ifdef DD_STATS -#define statLine(dd) dd->recursiveCalls++; \ -if (dd->recursiveCalls == dd->nextSample) {(void) fprintf(dd->err, \ -"@%.0f: %u nodes %u live %.0f dropped %.0f reclaimed\n", dd->recursiveCalls, \ -dd->keys, dd->keys - dd->dead, dd->nodesDropped, dd->reclaimed); \ -dd->nextSample += 250000;} -#else -#define statLine(dd) dd->recursiveCalls++; -#endif -#else -#define statLine(dd) -#endif - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Function prototypes */ -/*---------------------------------------------------------------------------*/ - -EXTERN DdNode * cuddAddExistAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * cuddAddUnivAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * cuddAddOrAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * cuddAddApplyRecur ARGS((DdManager *dd, DdNode * (*)(DdManager *, DdNode **, DdNode **), DdNode *f, DdNode *g)); -EXTERN DdNode * cuddAddMonadicApplyRecur ARGS((DdManager * dd, DdNode * (*op)(DdManager *, DdNode *), DdNode * f)); -EXTERN DdNode * cuddAddScalarInverseRecur ARGS((DdManager *dd, DdNode *f, DdNode *epsilon)); -EXTERN DdNode * cuddAddIteRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddAddCmplRecur ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * cuddAddNegateRecur ARGS((DdManager *dd, DdNode *f)); -EXTERN DdNode * cuddAddRoundOffRecur ARGS((DdManager *dd, DdNode *f, double trunc)); -EXTERN DdNode * cuddUnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int safe, double quality)); -EXTERN DdNode * cuddRemapUnderApprox ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, double quality)); -EXTERN DdNode * cuddBiasedUnderApprox ARGS((DdManager *dd, DdNode *f, DdNode *b, int numVars, int threshold, double quality1, double quality0)); -EXTERN DdNode * cuddBddAndAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); -EXTERN int cuddAnnealing ARGS((DdManager *table, int lower, int upper)); -EXTERN DdNode * cuddBddExistAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *cube)); -EXTERN DdNode * cuddBddXorExistAbstractRecur ARGS((DdManager *manager, DdNode *f, DdNode *g, DdNode *cube)); -EXTERN DdNode * cuddBddBooleanDiffRecur ARGS((DdManager *manager, DdNode *f, DdNode *var)); -EXTERN DdNode * cuddBddIteRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddBddIntersectRecur ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddBddAndRecur ARGS((DdManager *manager, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddBddXorRecur ARGS((DdManager *manager, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddBddTransfer ARGS((DdManager *ddS, DdManager *ddD, DdNode *f)); -EXTERN DdNode * cuddAddBddDoPattern ARGS((DdManager *dd, DdNode *f)); -EXTERN int cuddInitCache ARGS((DdManager *unique, unsigned int cacheSize, unsigned int maxCacheSize)); -EXTERN void cuddCacheInsert ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h, DdNode *data)); -EXTERN void cuddCacheInsert2 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g, DdNode *data)); -EXTERN void cuddCacheInsert1 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f, DdNode *data)); -EXTERN DdNode * cuddCacheLookup ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddCacheLookupZdd ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddCacheLookup2 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g)); -EXTERN DdNode * cuddCacheLookup1 ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f)); -EXTERN DdNode * cuddCacheLookup2Zdd ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *, DdNode *), DdNode *f, DdNode *g)); -EXTERN DdNode * cuddCacheLookup1Zdd ARGS((DdManager *table, DdNode * (*)(DdManager *, DdNode *), DdNode *f)); -EXTERN DdNode * cuddConstantLookup ARGS((DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)); -EXTERN int cuddCacheProfile ARGS((DdManager *table, FILE *fp)); -EXTERN void cuddCacheResize ARGS((DdManager *table)); -EXTERN void cuddCacheFlush ARGS((DdManager *table)); -EXTERN int cuddComputeFloorLog2 ARGS((unsigned int value)); -EXTERN int cuddHeapProfile ARGS((DdManager *dd)); -EXTERN void cuddPrintNode ARGS((DdNode *f, FILE *fp)); -EXTERN void cuddPrintVarGroups ARGS((DdManager * dd, MtrNode * root, int zdd, int silent)); -EXTERN DdNode * cuddBddClippingAnd ARGS((DdManager *dd, DdNode *f, DdNode *g, int maxDepth, int direction)); -EXTERN DdNode * cuddBddClippingAndAbstract ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *cube, int maxDepth, int direction)); -EXTERN void cuddGetBranches ARGS((DdNode *g, DdNode **g1, DdNode **g0)); -EXTERN int cuddCheckCube ARGS((DdManager *dd, DdNode *g)); -EXTERN DdNode * cuddCofactorRecur ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddBddComposeRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *proj)); -EXTERN DdNode * cuddAddComposeRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *proj)); -EXTERN int cuddExact ARGS((DdManager *table, int lower, int upper)); -EXTERN DdNode * cuddBddConstrainRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * cuddBddRestrictRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * cuddAddConstrainRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * cuddAddRestrictRecur ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN DdNode * cuddBddLICompaction ARGS((DdManager *dd, DdNode *f, DdNode *c)); -EXTERN int cuddGa ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddTreeSifting ARGS((DdManager *table, Cudd_ReorderingType method)); -EXTERN int cuddZddInitUniv ARGS((DdManager *zdd)); -EXTERN void cuddZddFreeUniv ARGS((DdManager *zdd)); -EXTERN void cuddSetInteract ARGS((DdManager *table, int x, int y)); -EXTERN int cuddTestInteract ARGS((DdManager *table, int x, int y)); -EXTERN int cuddInitInteract ARGS((DdManager *table)); -EXTERN DdLocalCache * cuddLocalCacheInit ARGS((DdManager *manager, unsigned int keySize, unsigned int cacheSize, unsigned int maxCacheSize)); -EXTERN void cuddLocalCacheQuit ARGS((DdLocalCache *cache)); -EXTERN void cuddLocalCacheInsert ARGS((DdLocalCache *cache, DdNodePtr *key, DdNode *value)); -EXTERN DdNode * cuddLocalCacheLookup ARGS((DdLocalCache *cache, DdNodePtr *key)); -EXTERN void cuddLocalCacheClearDead ARGS((DdManager *manager)); -EXTERN int cuddIsInDeathRow ARGS((DdManager *dd, DdNode *f)); -EXTERN int cuddTimesInDeathRow ARGS((DdManager *dd, DdNode *f)); -EXTERN void cuddLocalCacheClearAll ARGS((DdManager *manager)); -#ifdef DD_CACHE_PROFILE -EXTERN int cuddLocalCacheProfile ARGS((DdLocalCache *cache)); -#endif -EXTERN DdHashTable * cuddHashTableInit ARGS((DdManager *manager, unsigned int keySize, unsigned int initSize)); -EXTERN void cuddHashTableQuit ARGS((DdHashTable *hash)); -EXTERN int cuddHashTableInsert ARGS((DdHashTable *hash, DdNodePtr *key, DdNode *value, ptrint count)); -EXTERN DdNode * cuddHashTableLookup ARGS((DdHashTable *hash, DdNodePtr *key)); -EXTERN int cuddHashTableInsert1 ARGS((DdHashTable *hash, DdNode *f, DdNode *value, ptrint count)); -EXTERN DdNode * cuddHashTableLookup1 ARGS((DdHashTable *hash, DdNode *f)); -EXTERN int cuddHashTableInsert2 ARGS((DdHashTable *hash, DdNode *f, DdNode *g, DdNode *value, ptrint count)); -EXTERN DdNode * cuddHashTableLookup2 ARGS((DdHashTable *hash, DdNode *f, DdNode *g)); -EXTERN int cuddHashTableInsert3 ARGS((DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h, DdNode *value, ptrint count)); -EXTERN DdNode * cuddHashTableLookup3 ARGS((DdHashTable *hash, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdLevelQueue * cuddLevelQueueInit ARGS((int levels, int itemSize, int numBuckets)); -EXTERN void cuddLevelQueueQuit ARGS((DdLevelQueue *queue)); -EXTERN void * cuddLevelQueueEnqueue ARGS((DdLevelQueue *queue, void *key, int level)); -EXTERN void cuddLevelQueueDequeue ARGS((DdLevelQueue *queue, int level)); -EXTERN int cuddLinearAndSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN DdNode * cuddBddLiteralSetIntersectionRecur ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddCProjectionRecur ARGS((DdManager *dd, DdNode *R, DdNode *Y, DdNode *Ysupp)); -EXTERN DdNode * cuddBddClosestCube ARGS((DdManager *dd, DdNode *f, DdNode *g, CUDD_VALUE_TYPE bound)); -EXTERN void cuddReclaim ARGS((DdManager *table, DdNode *n)); -EXTERN void cuddReclaimZdd ARGS((DdManager *table, DdNode *n)); -EXTERN void cuddClearDeathRow ARGS((DdManager *table)); -EXTERN void cuddShrinkDeathRow ARGS((DdManager *table)); -EXTERN DdNode * cuddDynamicAllocNode ARGS((DdManager *table)); -EXTERN int cuddSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddSwapping ARGS((DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)); -EXTERN int cuddNextHigh ARGS((DdManager *table, int x)); -EXTERN int cuddNextLow ARGS((DdManager *table, int x)); -EXTERN int cuddSwapInPlace ARGS((DdManager *table, int x, int y)); -EXTERN int cuddBddAlignToZdd ARGS((DdManager *table)); -EXTERN DdNode * cuddBddMakePrime ARGS((DdManager *dd, DdNode *cube, DdNode *f)); -EXTERN DdNode * cuddSolveEqnRecur ARGS((DdManager *bdd, DdNode *F, DdNode *Y, DdNode **G, int n, int *yIndex, int i)); -EXTERN DdNode * cuddVerifySol ARGS((DdManager *bdd, DdNode *F, DdNode **G, int *yIndex, int n)); -#ifdef ST_INCLUDED -EXTERN DdNode* cuddSplitSetRecur ARGS((DdManager *manager, st_table *mtable, int *varSeen, DdNode *p, double n, double max, int index)); -#endif -EXTERN DdNode * cuddSubsetHeavyBranch ARGS((DdManager *dd, DdNode *f, int numVars, int threshold)); -EXTERN DdNode * cuddSubsetShortPaths ARGS((DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)); -EXTERN int cuddSymmCheck ARGS((DdManager *table, int x, int y)); -EXTERN int cuddSymmSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddSymmSiftingConv ARGS((DdManager *table, int lower, int upper)); -EXTERN DdNode * cuddAllocNode ARGS((DdManager *unique)); -EXTERN DdManager * cuddInitTable ARGS((unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int looseUpTo)); -EXTERN void cuddFreeTable ARGS((DdManager *unique)); -EXTERN int cuddGarbageCollect ARGS((DdManager *unique, int clearCache)); -EXTERN int cuddGarbageCollectZdd ARGS((DdManager *unique, int clearCache)); -EXTERN DdNode * cuddZddGetNode ARGS((DdManager *zdd, int id, DdNode *T, DdNode *E)); -EXTERN DdNode * cuddZddGetNodeIVO ARGS((DdManager *dd, int index, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddUniqueInter ARGS((DdManager *unique, int index, DdNode *T, DdNode *E)); -EXTERN DdNode * cuddUniqueInterIVO ARGS((DdManager *unique, int index, DdNode *T, DdNode *E)); -EXTERN DdNode * cuddUniqueInterZdd ARGS((DdManager *unique, int index, DdNode *T, DdNode *E)); -EXTERN DdNode * cuddUniqueConst ARGS((DdManager *unique, CUDD_VALUE_TYPE value)); -EXTERN void cuddRehash ARGS((DdManager *unique, int i)); -EXTERN void cuddShrinkSubtable ARGS((DdManager *unique, int i)); -EXTERN int cuddInsertSubtables ARGS((DdManager *unique, int n, int level)); -EXTERN int cuddDestroySubtables ARGS((DdManager *unique, int n)); -EXTERN int cuddResizeTableZdd ARGS((DdManager *unique, int index)); -EXTERN void cuddSlowTableGrowth ARGS((DdManager *unique)); -EXTERN int cuddP ARGS((DdManager *dd, DdNode *f)); -#ifdef ST_INCLUDED -EXTERN enum st_retval cuddStCountfree ARGS((char *key, char *value, char *arg)); -EXTERN int cuddCollectNodes ARGS((DdNode *f, st_table *visited)); -#endif -EXTERN int cuddWindowReorder ARGS((DdManager *table, int low, int high, Cudd_ReorderingType submethod)); -EXTERN DdNode * cuddZddProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddZddUnateProduct ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddZddWeakDiv ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddZddWeakDivF ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddZddDivide ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN DdNode * cuddZddDivideF ARGS((DdManager *dd, DdNode *f, DdNode *g)); -EXTERN int cuddZddGetCofactors3 ARGS((DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0, DdNode **fd)); -EXTERN int cuddZddGetCofactors2 ARGS((DdManager *dd, DdNode *f, int v, DdNode **f1, DdNode **f0)); -EXTERN DdNode * cuddZddComplement ARGS((DdManager *dd, DdNode *node)); -EXTERN int cuddZddGetPosVarIndex(DdManager * dd, int index); -EXTERN int cuddZddGetNegVarIndex(DdManager * dd, int index); -EXTERN int cuddZddGetPosVarLevel(DdManager * dd, int index); -EXTERN int cuddZddGetNegVarLevel(DdManager * dd, int index); -EXTERN int cuddZddTreeSifting ARGS((DdManager *table, Cudd_ReorderingType method)); -EXTERN DdNode * cuddZddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U, DdNode **zdd_I)); -EXTERN DdNode * cuddBddIsop ARGS((DdManager *dd, DdNode *L, DdNode *U)); -EXTERN DdNode * cuddMakeBddFromZddCover ARGS((DdManager *dd, DdNode *node)); -EXTERN int cuddZddLinearSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddZddAlignToBdd ARGS((DdManager *table)); -EXTERN int cuddZddNextHigh ARGS((DdManager *table, int x)); -EXTERN int cuddZddNextLow ARGS((DdManager *table, int x)); -EXTERN int cuddZddUniqueCompare ARGS((int *ptr_x, int *ptr_y)); -EXTERN int cuddZddSwapInPlace ARGS((DdManager *table, int x, int y)); -EXTERN int cuddZddSwapping ARGS((DdManager *table, int lower, int upper, Cudd_ReorderingType heuristic)); -EXTERN int cuddZddSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN DdNode * cuddZddIte ARGS((DdManager *dd, DdNode *f, DdNode *g, DdNode *h)); -EXTERN DdNode * cuddZddUnion ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); -EXTERN DdNode * cuddZddIntersect ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); -EXTERN DdNode * cuddZddDiff ARGS((DdManager *zdd, DdNode *P, DdNode *Q)); -EXTERN DdNode * cuddZddChangeAux ARGS((DdManager *zdd, DdNode *P, DdNode *zvar)); -EXTERN DdNode * cuddZddSubset1 ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN DdNode * cuddZddSubset0 ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN DdNode * cuddZddChange ARGS((DdManager *dd, DdNode *P, int var)); -EXTERN int cuddZddSymmCheck ARGS((DdManager *table, int x, int y)); -EXTERN int cuddZddSymmSifting ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddZddSymmSiftingConv ARGS((DdManager *table, int lower, int upper)); -EXTERN int cuddZddP ARGS((DdManager *zdd, DdNode *f)); - -/**AutomaticEnd***************************************************************/ - -#endif /* _CUDDINT */ diff --git a/src/bdd/cudd/cuddInteract.c b/src/bdd/cudd/cuddInteract.c deleted file mode 100644 index 96613639..00000000 --- a/src/bdd/cudd/cuddInteract.c +++ /dev/null @@ -1,402 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddInteract.c] - - PackageName [cudd] - - Synopsis [Functions to manipulate the variable interaction matrix.] - - Description [Internal procedures included in this file: -
              -
            • cuddSetInteract() -
            • cuddTestInteract() -
            • cuddInitInteract() -
            - Static procedures included in this file: -
              -
            • ddSuppInteract() -
            • ddClearLocal() -
            • ddUpdateInteract() -
            • ddClearGlobal() -
            - The interaction matrix tells whether two variables are - both in the support of some function of the DD. The main use of the - interaction matrix is in the in-place swapping. Indeed, if two - variables do not interact, there is no arc connecting the two layers; - therefore, the swap can be performed in constant time, without - scanning the subtables. Another use of the interaction matrix is in - the computation of the lower bounds for sifting. Finally, the - interaction matrix can be used to speed up aggregation checks in - symmetric and group sifting.

            - The computation of the interaction matrix is done with a series of - depth-first searches. The searches start from those nodes that have - only external references. The matrix is stored as a packed array of bits; - since it is symmetric, only the upper triangle is kept in memory. - As a final remark, we note that there may be variables that do - intercat, but that for a given variable order have no arc connecting - their layers when they are adjacent.] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#if SIZEOF_LONG == 8 -#define BPL 64 -#define LOGBPL 6 -#else -#define BPL 32 -#define LOGBPL 5 -#endif - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddInteract.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void ddSuppInteract ARGS((DdNode *f, int *support)); -static void ddClearLocal ARGS((DdNode *f)); -static void ddUpdateInteract ARGS((DdManager *table, int *support)); -static void ddClearGlobal ARGS((DdManager *table)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Set interaction matrix entries.] - - Description [Given a pair of variables 0 <= x < y < table->size, - sets the corresponding bit of the interaction matrix to 1.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddSetInteract( - DdManager * table, - int x, - int y) -{ - int posn, word, bit; - -#ifdef DD_DEBUG - assert(x < y); - assert(y < table->size); - assert(x >= 0); -#endif - - posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1; - word = posn >> LOGBPL; - bit = posn & (BPL-1); - table->interact[word] |= 1L << bit; - -} /* end of cuddSetInteract */ - - -/**Function******************************************************************** - - Synopsis [Test interaction matrix entries.] - - Description [Given a pair of variables 0 <= x < y < table->size, - tests whether the corresponding bit of the interaction matrix is 1. - Returns the value of the bit.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddTestInteract( - DdManager * table, - int x, - int y) -{ - int posn, word, bit, result; - - if (x > y) { - int tmp = x; - x = y; - y = tmp; - } -#ifdef DD_DEBUG - assert(x < y); - assert(y < table->size); - assert(x >= 0); -#endif - - posn = ((((table->size << 1) - x - 3) * x) >> 1) + y - 1; - word = posn >> LOGBPL; - bit = posn & (BPL-1); - result = (table->interact[word] >> bit) & 1L; - return(result); - -} /* end of cuddTestInteract */ - - -/**Function******************************************************************** - - Synopsis [Initializes the interaction matrix.] - - Description [Initializes the interaction matrix. The interaction - matrix is implemented as a bit vector storing the upper triangle of - the symmetric interaction matrix. The bit vector is kept in an array - of long integers. The computation is based on a series of depth-first - searches, one for each root of the DAG. Two flags are needed: The - local visited flag uses the LSB of the then pointer. The global - visited flag uses the LSB of the next pointer. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddInitInteract( - DdManager * table) -{ - int i,j,k; - int words; - long *interact; - int *support; - DdNode *f; - DdNode *sentinel = &(table->sentinel); - DdNodePtr *nodelist; - int slots; - int n = table->size; - - words = ((n * (n-1)) >> (1 + LOGBPL)) + 1; - table->interact = interact = ALLOC(long,words); - if (interact == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < words; i++) { - interact[i] = 0; - } - - support = ALLOC(int,n); - if (support == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - FREE(interact); - return(0); - } - - for (i = 0; i < n; i++) { - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - for (j = 0; j < slots; j++) { - f = nodelist[j]; - while (f != sentinel) { - /* A node is a root of the DAG if it cannot be - ** reached by nodes above it. If a node was never - ** reached during the previous depth-first searches, - ** then it is a root, and we start a new depth-first - ** search from it. - */ - if (!Cudd_IsComplement(f->next)) { - for (k = 0; k < n; k++) { - support[k] = 0; - } - ddSuppInteract(f,support); - ddClearLocal(f); - ddUpdateInteract(table,support); - } - f = Cudd_Regular(f->next); - } - } - } - ddClearGlobal(table); - - FREE(support); - return(1); - -} /* end of cuddInitInteract */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Find the support of f.] - - Description [Performs a DFS from f. Uses the LSB of the then pointer - as visited flag.] - - SideEffects [Accumulates in support the variables on which f depends.] - - SeeAlso [] - -******************************************************************************/ -static void -ddSuppInteract( - DdNode * f, - int * support) -{ - if (cuddIsConstant(f) || Cudd_IsComplement(cuddT(f))) { - return; - } - - support[f->index] = 1; - ddSuppInteract(cuddT(f),support); - ddSuppInteract(Cudd_Regular(cuddE(f)),support); - /* mark as visited */ - cuddT(f) = Cudd_Complement(cuddT(f)); - f->next = Cudd_Complement(f->next); - return; - -} /* end of ddSuppInteract */ - - -/**Function******************************************************************** - - Synopsis [Performs a DFS from f, clearing the LSB of the then pointers.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -ddClearLocal( - DdNode * f) -{ - if (cuddIsConstant(f) || !Cudd_IsComplement(cuddT(f))) { - return; - } - /* clear visited flag */ - cuddT(f) = Cudd_Regular(cuddT(f)); - ddClearLocal(cuddT(f)); - ddClearLocal(Cudd_Regular(cuddE(f))); - return; - -} /* end of ddClearLocal */ - - -/**Function******************************************************************** - - Synopsis [Marks as interacting all pairs of variables that appear in - support.] - - Description [If support[i] == support[j] == 1, sets the (i,j) entry - of the interaction matrix to 1.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -ddUpdateInteract( - DdManager * table, - int * support) -{ - int i,j; - int n = table->size; - - for (i = 0; i < n-1; i++) { - if (support[i] == 1) { - for (j = i+1; j < n; j++) { - if (support[j] == 1) { - cuddSetInteract(table,i,j); - } - } - } - } - -} /* end of ddUpdateInteract */ - - -/**Function******************************************************************** - - Synopsis [Scans the DD and clears the LSB of the next pointers.] - - Description [The LSB of the next pointers are used as markers to tell - whether a node was reached by at least one DFS. Once the interaction - matrix is built, these flags are reset.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -ddClearGlobal( - DdManager * table) -{ - int i,j; - DdNode *f; - DdNode *sentinel = &(table->sentinel); - DdNodePtr *nodelist; - int slots; - - for (i = 0; i < table->size; i++) { - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - for (j = 0; j < slots; j++) { - f = nodelist[j]; - while (f != sentinel) { - f->next = Cudd_Regular(f->next); - f = f->next; - } - } - } - -} /* end of ddClearGlobal */ - diff --git a/src/bdd/cudd/cuddLCache.c b/src/bdd/cudd/cuddLCache.c deleted file mode 100644 index 8bd37ba0..00000000 --- a/src/bdd/cudd/cuddLCache.c +++ /dev/null @@ -1,1428 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddLCache.c] - - PackageName [cudd] - - Synopsis [Functions for local caches.] - - Description [Internal procedures included in this module: -

              -
            • cuddLocalCacheInit() -
            • cuddLocalCacheQuit() -
            • cuddLocalCacheInsert() -
            • cuddLocalCacheLookup() -
            • cuddLocalCacheClearDead() -
            • cuddLocalCacheClearAll() -
            • cuddLocalCacheProfile() -
            • cuddHashTableInit() -
            • cuddHashTableQuit() -
            • cuddHashTableInsert() -
            • cuddHashTableLookup() -
            • cuddHashTableInsert2() -
            • cuddHashTableLookup2() -
            • cuddHashTableInsert3() -
            • cuddHashTableLookup3() -
            - Static procedures included in this module: -
              -
            • cuddLocalCacheResize() -
            • ddLCHash() -
            • cuddLocalCacheAddToList() -
            • cuddLocalCacheRemoveFromList() -
            • cuddHashTableResize() -
            • cuddHashTableAlloc() -
            ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_MAX_HASHTABLE_DENSITY 2 /* tells when to resize a table */ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddLCache.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**Macro*********************************************************************** - - Synopsis [Computes hash function for keys of two operands.] - - Description [] - - SideEffects [None] - - SeeAlso [ddLCHash3 ddLCHash] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define ddLCHash2(f,g,shift) \ -((((unsigned)(unsigned long)(f) * DD_P1 + \ - (unsigned)(unsigned long)(g)) * DD_P2) >> (shift)) -#else -#define ddLCHash2(f,g,shift) \ -((((unsigned)(f) * DD_P1 + (unsigned)(g)) * DD_P2) >> (shift)) -#endif - - -/**Macro*********************************************************************** - - Synopsis [Computes hash function for keys of three operands.] - - Description [] - - SideEffects [None] - - SeeAlso [ddLCHash2 ddLCHash] - -******************************************************************************/ -#define ddLCHash3(f,g,h,shift) ddCHash2(f,g,h,shift) - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void cuddLocalCacheResize ARGS((DdLocalCache *cache)); -DD_INLINE static unsigned int ddLCHash ARGS((DdNodePtr *key, unsigned int keysize, int shift)); -static void cuddLocalCacheAddToList ARGS((DdLocalCache *cache)); -static void cuddLocalCacheRemoveFromList ARGS((DdLocalCache *cache)); -static int cuddHashTableResize ARGS((DdHashTable *hash)); -DD_INLINE static DdHashItem * cuddHashTableAlloc ARGS((DdHashTable *hash)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Initializes a local computed table.] - - Description [Initializes a computed table. Returns a pointer the - the new local cache in case of success; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddInitCache] - -******************************************************************************/ -DdLocalCache * -cuddLocalCacheInit( - DdManager * manager /* manager */, - unsigned int keySize /* size of the key (number of operands) */, - unsigned int cacheSize /* Initial size of the cache */, - unsigned int maxCacheSize /* Size of the cache beyond which no resizing occurs */) -{ - DdLocalCache *cache; - int logSize; - - cache = ALLOC(DdLocalCache,1); - if (cache == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - cache->manager = manager; - cache->keysize = keySize; - cache->itemsize = (keySize + 1) * sizeof(DdNode *); -#ifdef DD_CACHE_PROFILE - cache->itemsize += sizeof(ptrint); -#endif - logSize = cuddComputeFloorLog2(ddMax(cacheSize,manager->slots/2)); - cacheSize = 1 << logSize; - cache->item = (DdLocalCacheItem *) - ALLOC(char, cacheSize * cache->itemsize); - if (cache->item == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - FREE(cache); - return(NULL); - } - cache->slots = cacheSize; - cache->shift = sizeof(int) * 8 - logSize; - cache->maxslots = ddMin(maxCacheSize,manager->slots); - cache->minHit = manager->minHit; - /* Initialize to avoid division by 0 and immediate resizing. */ - cache->lookUps = (double) (int) (cacheSize * cache->minHit + 1); - cache->hits = 0; - manager->memused += cacheSize * cache->itemsize + sizeof(DdLocalCache); - - /* Initialize the cache. */ - memset(cache->item, 0, cacheSize * cache->itemsize); - - /* Add to manager's list of local caches for GC. */ - cuddLocalCacheAddToList(cache); - - return(cache); - -} /* end of cuddLocalCacheInit */ - - -/**Function******************************************************************** - - Synopsis [Shuts down a local computed table.] - - Description [Initializes the computed table. It is called by - Cudd_Init. Returns a pointer the the new local cache in case of - success; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddLocalCacheInit] - -******************************************************************************/ -void -cuddLocalCacheQuit( - DdLocalCache * cache /* cache to be shut down */) -{ - cache->manager->memused -= - cache->slots * cache->itemsize + sizeof(DdLocalCache); - cuddLocalCacheRemoveFromList(cache); - FREE(cache->item); - FREE(cache); - - return; - -} /* end of cuddLocalCacheQuit */ - - -/**Function******************************************************************** - - Synopsis [Inserts a result in a local cache.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddLocalCacheInsert( - DdLocalCache * cache, - DdNodePtr * key, - DdNode * value) -{ - unsigned int posn; - DdLocalCacheItem *entry; - - posn = ddLCHash(key,cache->keysize,cache->shift); - entry = (DdLocalCacheItem *) ((char *) cache->item + - posn * cache->itemsize); - memcpy(entry->key,key,cache->keysize * sizeof(DdNode *)); - entry->value = value; -#ifdef DD_CACHE_PROFILE - entry->count++; -#endif - -} /* end of cuddLocalCacheInsert */ - - -/**Function******************************************************************** - - Synopsis [Looks up in a local cache.] - - Description [Looks up in a local cache. Returns the result if found; - it returns NULL if no result is found.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddLocalCacheLookup( - DdLocalCache * cache, - DdNodePtr * key) -{ - unsigned int posn; - DdLocalCacheItem *entry; - DdNode *value; - - cache->lookUps++; - posn = ddLCHash(key,cache->keysize,cache->shift); - entry = (DdLocalCacheItem *) ((char *) cache->item + - posn * cache->itemsize); - if (entry->value != NULL && - memcmp(key,entry->key,cache->keysize*sizeof(DdNode *)) == 0) { - cache->hits++; - value = Cudd_Regular(entry->value); - if (value->ref == 0) { - cuddReclaim(cache->manager,value); - } - return(entry->value); - } - - /* Cache miss: decide whether to resize */ - - if (cache->slots < cache->maxslots && - cache->hits > cache->lookUps * cache->minHit) { - cuddLocalCacheResize(cache); - } - - return(NULL); - -} /* end of cuddLocalCacheLookup */ - - -/**Function******************************************************************** - - Synopsis [Clears the dead entries of the local caches of a manager.] - - Description [Clears the dead entries of the local caches of a manager. - Used during garbage collection.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddLocalCacheClearDead( - DdManager * manager) -{ - DdLocalCache *cache = manager->localCaches; - unsigned int keysize; - unsigned int itemsize; - unsigned int slots; - DdLocalCacheItem *item; - DdNodePtr *key; - unsigned int i, j; - - while (cache != NULL) { - keysize = cache->keysize; - itemsize = cache->itemsize; - slots = cache->slots; - item = cache->item; - for (i = 0; i < slots; i++) { - if (item->value != NULL && Cudd_Regular(item->value)->ref == 0) { - item->value = NULL; - } else { - key = item->key; - for (j = 0; j < keysize; j++) { - if (Cudd_Regular(key[j])->ref == 0) { - item->value = NULL; - break; - } - } - } - item = (DdLocalCacheItem *) ((char *) item + itemsize); - } - cache = cache->next; - } - return; - -} /* end of cuddLocalCacheClearDead */ - - -/**Function******************************************************************** - - Synopsis [Clears the local caches of a manager.] - - Description [Clears the local caches of a manager. - Used before reordering.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddLocalCacheClearAll( - DdManager * manager) -{ - DdLocalCache *cache = manager->localCaches; - - while (cache != NULL) { - memset(cache->item, 0, cache->slots * cache->itemsize); - cache = cache->next; - } - return; - -} /* end of cuddLocalCacheClearAll */ - - -#ifdef DD_CACHE_PROFILE - -#define DD_HYSTO_BINS 8 - -/**Function******************************************************************** - - Synopsis [Computes and prints a profile of a local cache usage.] - - Description [Computes and prints a profile of a local cache usage. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddLocalCacheProfile( - DdLocalCache * cache) -{ - double count, mean, meansq, stddev, expected; - long max, min; - int imax, imin; - int i, retval, slots; - long *hystogram; - int nbins = DD_HYSTO_BINS; - int bin; - long thiscount; - double totalcount; - int nzeroes; - DdLocalCacheItem *entry; - FILE *fp = cache->manager->out; - - slots = cache->slots; - - meansq = mean = expected = 0.0; - max = min = (long) cache->item[0].count; - imax = imin = nzeroes = 0; - totalcount = 0.0; - - hystogram = ALLOC(long, nbins); - if (hystogram == NULL) { - return(0); - } - for (i = 0; i < nbins; i++) { - hystogram[i] = 0; - } - - for (i = 0; i < slots; i++) { - entry = (DdLocalCacheItem *) ((char *) cache->item + - i * cache->itemsize); - thiscount = (long) entry->count; - if (thiscount > max) { - max = thiscount; - imax = i; - } - if (thiscount < min) { - min = thiscount; - imin = i; - } - if (thiscount == 0) { - nzeroes++; - } - count = (double) thiscount; - mean += count; - meansq += count * count; - totalcount += count; - expected += count * (double) i; - bin = (i * nbins) / slots; - hystogram[bin] += thiscount; - } - mean /= (double) slots; - meansq /= (double) slots; - stddev = sqrt(meansq - mean*mean); - - retval = fprintf(fp,"Cache stats: slots = %d average = %g ", slots, mean); - if (retval == EOF) return(0); - retval = fprintf(fp,"standard deviation = %g\n", stddev); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache max accesses = %ld for slot %d\n", max, imax); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache min accesses = %ld for slot %d\n", min, imin); - if (retval == EOF) return(0); - retval = fprintf(fp,"Cache unused slots = %d\n", nzeroes); - if (retval == EOF) return(0); - - if (totalcount) { - expected /= totalcount; - retval = fprintf(fp,"Cache access hystogram for %d bins", nbins); - if (retval == EOF) return(0); - retval = fprintf(fp," (expected bin value = %g)\n# ", expected); - if (retval == EOF) return(0); - for (i = nbins - 1; i>=0; i--) { - retval = fprintf(fp,"%ld ", hystogram[i]); - if (retval == EOF) return(0); - } - retval = fprintf(fp,"\n"); - if (retval == EOF) return(0); - } - - FREE(hystogram); - return(1); - -} /* end of cuddLocalCacheProfile */ -#endif - - -/**Function******************************************************************** - - Synopsis [Initializes a hash table.] - - Description [Initializes a hash table. Returns a pointer to the new - table if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddHashTableQuit] - -******************************************************************************/ -DdHashTable * -cuddHashTableInit( - DdManager * manager, - unsigned int keySize, - unsigned int initSize) -{ - DdHashTable *hash; - int logSize; - -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - hash = ALLOC(DdHashTable, 1); - if (hash == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - hash->keysize = keySize; - hash->manager = manager; - hash->memoryList = NULL; - hash->nextFree = NULL; - hash->itemsize = (keySize + 1) * sizeof(DdNode *) + - sizeof(ptrint) + sizeof(DdHashItem *); - /* We have to guarantee that the shift be < 32. */ - if (initSize < 2) initSize = 2; - logSize = cuddComputeFloorLog2(initSize); - hash->numBuckets = 1 << logSize; - hash->shift = sizeof(int) * 8 - logSize; - hash->bucket = ALLOC(DdHashItem *, hash->numBuckets); - if (hash->bucket == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - FREE(hash); - return(NULL); - } - memset(hash->bucket, 0, hash->numBuckets * sizeof(DdHashItem *)); - hash->size = 0; - hash->maxsize = hash->numBuckets * DD_MAX_HASHTABLE_DENSITY; -#ifdef __osf__ -#pragma pointer_size restore -#endif - return(hash); - -} /* end of cuddHashTableInit */ - - -/**Function******************************************************************** - - Synopsis [Shuts down a hash table.] - - Description [Shuts down a hash table, dereferencing all the values.] - - SideEffects [None] - - SeeAlso [cuddHashTableInit] - -******************************************************************************/ -void -cuddHashTableQuit( - DdHashTable * hash) -{ -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - unsigned int i; - DdManager *dd = hash->manager; - DdHashItem *bucket; - DdHashItem **memlist, **nextmem; - unsigned int numBuckets = hash->numBuckets; - - for (i = 0; i < numBuckets; i++) { - bucket = hash->bucket[i]; - while (bucket != NULL) { - Cudd_RecursiveDeref(dd, bucket->value); - bucket = bucket->next; - } - } - - memlist = hash->memoryList; - while (memlist != NULL) { - nextmem = (DdHashItem **) memlist[0]; - FREE(memlist); - memlist = nextmem; - } - - FREE(hash->bucket); - FREE(hash); -#ifdef __osf__ -#pragma pointer_size restore -#endif - - return; - -} /* end of cuddHashTableQuit */ - - -/**Function******************************************************************** - - Synopsis [Inserts an item in a hash table.] - - Description [Inserts an item in a hash table when the key has more than - three pointers. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [[cuddHashTableInsert1 cuddHashTableInsert2 cuddHashTableInsert3 - cuddHashTableLookup] - -******************************************************************************/ -int -cuddHashTableInsert( - DdHashTable * hash, - DdNodePtr * key, - DdNode * value, - ptrint count) -{ - int result; - unsigned int posn; - DdHashItem *item; - unsigned int i; - -#ifdef DD_DEBUG - assert(hash->keysize > 3); -#endif - - if (hash->size > hash->maxsize) { - result = cuddHashTableResize(hash); - if (result == 0) return(0); - } - item = cuddHashTableAlloc(hash); - if (item == NULL) return(0); - hash->size++; - item->value = value; - cuddRef(value); - item->count = count; - for (i = 0; i < hash->keysize; i++) { - item->key[i] = key[i]; - } - posn = ddLCHash(key,hash->keysize,hash->shift); - item->next = hash->bucket[posn]; - hash->bucket[posn] = item; - - return(1); - -} /* end of cuddHashTableInsert */ - - -/**Function******************************************************************** - - Synopsis [Looks up a key in a hash table.] - - Description [Looks up a key consisting of more than three pointers - in a hash table. Returns the value associated to the key if there - is an entry for the given key in the table; NULL otherwise. If the - entry is present, its reference counter is decremented if not - saturated. If the counter reaches 0, the value of the entry is - dereferenced, and the entry is returned to the free list.] - - SideEffects [None] - - SeeAlso [cuddHashTableLookup1 cuddHashTableLookup2 cuddHashTableLookup3 - cuddHashTableInsert] - -******************************************************************************/ -DdNode * -cuddHashTableLookup( - DdHashTable * hash, - DdNodePtr * key) -{ - unsigned int posn; - DdHashItem *item, *prev; - unsigned int i, keysize; - -#ifdef DD_DEBUG - assert(hash->keysize > 3); -#endif - - posn = ddLCHash(key,hash->keysize,hash->shift); - item = hash->bucket[posn]; - prev = NULL; - - keysize = hash->keysize; - while (item != NULL) { - DdNodePtr *key2 = item->key; - int equal = 1; - for (i = 0; i < keysize; i++) { - if (key[i] != key2[i]) { - equal = 0; - break; - } - } - if (equal) { - DdNode *value = item->value; - cuddSatDec(item->count); - if (item->count == 0) { - cuddDeref(value); - if (prev == NULL) { - hash->bucket[posn] = item->next; - } else { - prev->next = item->next; - } - item->next = hash->nextFree; - hash->nextFree = item; - hash->size--; - } - return(value); - } - prev = item; - item = item->next; - } - return(NULL); - -} /* end of cuddHashTableLookup */ - - -/**Function******************************************************************** - - Synopsis [Inserts an item in a hash table.] - - Description [Inserts an item in a hash table when the key is one pointer. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddHashTableInsert cuddHashTableInsert2 cuddHashTableInsert3 - cuddHashTableLookup1] - -******************************************************************************/ -int -cuddHashTableInsert1( - DdHashTable * hash, - DdNode * f, - DdNode * value, - ptrint count) -{ - int result; - unsigned int posn; - DdHashItem *item; - -#ifdef DD_DEBUG - assert(hash->keysize == 1); -#endif - - if (hash->size > hash->maxsize) { - result = cuddHashTableResize(hash); - if (result == 0) return(0); - } - item = cuddHashTableAlloc(hash); - if (item == NULL) return(0); - hash->size++; - item->value = value; - cuddRef(value); - item->count = count; - item->key[0] = f; - posn = ddLCHash2(f,f,hash->shift); - item->next = hash->bucket[posn]; - hash->bucket[posn] = item; - - return(1); - -} /* end of cuddHashTableInsert1 */ - - -/**Function******************************************************************** - - Synopsis [Looks up a key consisting of one pointer in a hash table.] - - Description [Looks up a key consisting of one pointer in a hash table. - Returns the value associated to the key if there is an entry for the given - key in the table; NULL otherwise. If the entry is present, its reference - counter is decremented if not saturated. If the counter reaches 0, the - value of the entry is dereferenced, and the entry is returned to the free - list.] - - SideEffects [None] - - SeeAlso [cuddHashTableLookup cuddHashTableLookup2 cuddHashTableLookup3 - cuddHashTableInsert1] - -******************************************************************************/ -DdNode * -cuddHashTableLookup1( - DdHashTable * hash, - DdNode * f) -{ - unsigned int posn; - DdHashItem *item, *prev; - -#ifdef DD_DEBUG - assert(hash->keysize == 1); -#endif - - posn = ddLCHash2(f,f,hash->shift); - item = hash->bucket[posn]; - prev = NULL; - - while (item != NULL) { - DdNodePtr *key = item->key; - if (f == key[0]) { - DdNode *value = item->value; - cuddSatDec(item->count); - if (item->count == 0) { - cuddDeref(value); - if (prev == NULL) { - hash->bucket[posn] = item->next; - } else { - prev->next = item->next; - } - item->next = hash->nextFree; - hash->nextFree = item; - hash->size--; - } - return(value); - } - prev = item; - item = item->next; - } - return(NULL); - -} /* end of cuddHashTableLookup1 */ - - -/**Function******************************************************************** - - Synopsis [Inserts an item in a hash table.] - - Description [Inserts an item in a hash table when the key is - composed of two pointers. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert3 - cuddHashTableLookup2] - -******************************************************************************/ -int -cuddHashTableInsert2( - DdHashTable * hash, - DdNode * f, - DdNode * g, - DdNode * value, - ptrint count) -{ - int result; - unsigned int posn; - DdHashItem *item; - -#ifdef DD_DEBUG - assert(hash->keysize == 2); -#endif - - if (hash->size > hash->maxsize) { - result = cuddHashTableResize(hash); - if (result == 0) return(0); - } - item = cuddHashTableAlloc(hash); - if (item == NULL) return(0); - hash->size++; - item->value = value; - cuddRef(value); - item->count = count; - item->key[0] = f; - item->key[1] = g; - posn = ddLCHash2(f,g,hash->shift); - item->next = hash->bucket[posn]; - hash->bucket[posn] = item; - - return(1); - -} /* end of cuddHashTableInsert2 */ - - -/**Function******************************************************************** - - Synopsis [Looks up a key consisting of two pointers in a hash table.] - - Description [Looks up a key consisting of two pointer in a hash table. - Returns the value associated to the key if there is an entry for the given - key in the table; NULL otherwise. If the entry is present, its reference - counter is decremented if not saturated. If the counter reaches 0, the - value of the entry is dereferenced, and the entry is returned to the free - list.] - - SideEffects [None] - - SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup3 - cuddHashTableInsert2] - -******************************************************************************/ -DdNode * -cuddHashTableLookup2( - DdHashTable * hash, - DdNode * f, - DdNode * g) -{ - unsigned int posn; - DdHashItem *item, *prev; - -#ifdef DD_DEBUG - assert(hash->keysize == 2); -#endif - - posn = ddLCHash2(f,g,hash->shift); - item = hash->bucket[posn]; - prev = NULL; - - while (item != NULL) { - DdNodePtr *key = item->key; - if ((f == key[0]) && (g == key[1])) { - DdNode *value = item->value; - cuddSatDec(item->count); - if (item->count == 0) { - cuddDeref(value); - if (prev == NULL) { - hash->bucket[posn] = item->next; - } else { - prev->next = item->next; - } - item->next = hash->nextFree; - hash->nextFree = item; - hash->size--; - } - return(value); - } - prev = item; - item = item->next; - } - return(NULL); - -} /* end of cuddHashTableLookup2 */ - - -/**Function******************************************************************** - - Synopsis [Inserts an item in a hash table.] - - Description [Inserts an item in a hash table when the key is - composed of three pointers. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddHashTableInsert cuddHashTableInsert1 cuddHashTableInsert2 - cuddHashTableLookup3] - -******************************************************************************/ -int -cuddHashTableInsert3( - DdHashTable * hash, - DdNode * f, - DdNode * g, - DdNode * h, - DdNode * value, - ptrint count) -{ - int result; - unsigned int posn; - DdHashItem *item; - -#ifdef DD_DEBUG - assert(hash->keysize == 3); -#endif - - if (hash->size > hash->maxsize) { - result = cuddHashTableResize(hash); - if (result == 0) return(0); - } - item = cuddHashTableAlloc(hash); - if (item == NULL) return(0); - hash->size++; - item->value = value; - cuddRef(value); - item->count = count; - item->key[0] = f; - item->key[1] = g; - item->key[2] = h; - posn = ddLCHash3(f,g,h,hash->shift); - item->next = hash->bucket[posn]; - hash->bucket[posn] = item; - - return(1); - -} /* end of cuddHashTableInsert3 */ - - -/**Function******************************************************************** - - Synopsis [Looks up a key consisting of three pointers in a hash table.] - - Description [Looks up a key consisting of three pointers in a hash table. - Returns the value associated to the key if there is an entry for the given - key in the table; NULL otherwise. If the entry is present, its reference - counter is decremented if not saturated. If the counter reaches 0, the - value of the entry is dereferenced, and the entry is returned to the free - list.] - - SideEffects [None] - - SeeAlso [cuddHashTableLookup cuddHashTableLookup1 cuddHashTableLookup2 - cuddHashTableInsert3] - -******************************************************************************/ -DdNode * -cuddHashTableLookup3( - DdHashTable * hash, - DdNode * f, - DdNode * g, - DdNode * h) -{ - unsigned int posn; - DdHashItem *item, *prev; - -#ifdef DD_DEBUG - assert(hash->keysize == 3); -#endif - - posn = ddLCHash3(f,g,h,hash->shift); - item = hash->bucket[posn]; - prev = NULL; - - while (item != NULL) { - DdNodePtr *key = item->key; - if ((f == key[0]) && (g == key[1]) && (h == key[2])) { - DdNode *value = item->value; - cuddSatDec(item->count); - if (item->count == 0) { - cuddDeref(value); - if (prev == NULL) { - hash->bucket[posn] = item->next; - } else { - prev->next = item->next; - } - item->next = hash->nextFree; - hash->nextFree = item; - hash->size--; - } - return(value); - } - prev = item; - item = item->next; - } - return(NULL); - -} /* end of cuddHashTableLookup3 */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Resizes a local cache.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -cuddLocalCacheResize( - DdLocalCache * cache) -{ - DdLocalCacheItem *item, *olditem, *entry, *old; - int i, shift; - unsigned int posn; - unsigned int slots, oldslots; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - olditem = cache->item; - oldslots = cache->slots; - slots = cache->slots = oldslots << 1; - -#ifdef DD_VERBOSE - (void) fprintf(cache->manager->err, - "Resizing local cache from %d to %d entries\n", - oldslots, slots); - (void) fprintf(cache->manager->err, - "\thits = %.0f\tlookups = %.0f\thit ratio = %5.3f\n", - cache->hits, cache->lookUps, cache->hits / cache->lookUps); -#endif - - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - cache->item = item = - (DdLocalCacheItem *) ALLOC(char, slots * cache->itemsize); - MMoutOfMemory = saveHandler; - /* If we fail to allocate the new table we just give up. */ - if (item == NULL) { -#ifdef DD_VERBOSE - (void) fprintf(cache->manager->err,"Resizing failed. Giving up.\n"); -#endif - cache->slots = oldslots; - cache->item = olditem; - /* Do not try to resize again. */ - cache->maxslots = oldslots - 1; - return; - } - shift = --(cache->shift); - cache->manager->memused += (slots - oldslots) * cache->itemsize; - - /* Clear new cache. */ - memset(item, 0, slots * cache->itemsize); - - /* Copy from old cache to new one. */ - for (i = 0; (unsigned) i < oldslots; i++) { - old = (DdLocalCacheItem *) ((char *) olditem + i * cache->itemsize); - if (old->value != NULL) { - posn = ddLCHash(old->key,cache->keysize,slots); - entry = (DdLocalCacheItem *) ((char *) item + - posn * cache->itemsize); - memcpy(entry->key,old->key,cache->keysize*sizeof(DdNode *)); - entry->value = old->value; - } - } - - FREE(olditem); - - /* Reinitialize measurements so as to avoid division by 0 and - ** immediate resizing. - */ - cache->lookUps = (double) (int) (slots * cache->minHit + 1); - cache->hits = 0; - -} /* end of cuddLocalCacheResize */ - - -/**Function******************************************************************** - - Synopsis [Computes the hash value for a local cache.] - - Description [Computes the hash value for a local cache. Returns the - bucket index.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DD_INLINE -static unsigned int -ddLCHash( - DdNodePtr * key, - unsigned int keysize, - int shift) -{ - unsigned int val = (unsigned int) (ptrint) key[0]; - unsigned int i; - - for (i = 1; i < keysize; i++) { - val = val * DD_P1 + (int) (ptrint) key[i]; - } - - return(val >> shift); - -} /* end of ddLCHash */ - - -/**Function******************************************************************** - - Synopsis [Inserts a local cache in the manager list.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -cuddLocalCacheAddToList( - DdLocalCache * cache) -{ - DdManager *manager = cache->manager; - - cache->next = manager->localCaches; - manager->localCaches = cache; - return; - -} /* end of cuddLocalCacheAddToList */ - - -/**Function******************************************************************** - - Synopsis [Removes a local cache from the manager list.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -cuddLocalCacheRemoveFromList( - DdLocalCache * cache) -{ - DdManager *manager = cache->manager; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - DdLocalCache **prevCache, *nextCache; -#ifdef __osf__ -#pragma pointer_size restore -#endif - - prevCache = &(manager->localCaches); - nextCache = manager->localCaches; - - while (nextCache != NULL) { - if (nextCache == cache) { - *prevCache = nextCache->next; - return; - } - prevCache = &(nextCache->next); - nextCache = nextCache->next; - } - return; /* should never get here */ - -} /* end of cuddLocalCacheRemoveFromList */ - - -/**Function******************************************************************** - - Synopsis [Resizes a hash table.] - - Description [Resizes a hash table. Returns 1 if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddHashTableInsert] - -******************************************************************************/ -static int -cuddHashTableResize( - DdHashTable * hash) -{ - int j; - unsigned int posn; - DdHashItem *item; - DdHashItem *next; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - DdNode **key; - int numBuckets; - DdHashItem **buckets; - DdHashItem **oldBuckets = hash->bucket; -#ifdef __osf__ -#pragma pointer_size restore -#endif - int shift; - int oldNumBuckets = hash->numBuckets; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - /* Compute the new size of the table. */ - numBuckets = oldNumBuckets << 1; - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - buckets = ALLOC(DdHashItem *, numBuckets); - MMoutOfMemory = saveHandler; - if (buckets == NULL) { - hash->maxsize <<= 1; - return(1); - } - - hash->bucket = buckets; - hash->numBuckets = numBuckets; - shift = --(hash->shift); - hash->maxsize <<= 1; - memset(buckets, 0, numBuckets * sizeof(DdHashItem *)); -#ifdef __osf__ -#pragma pointer_size restore -#endif - if (hash->keysize == 1) { - for (j = 0; j < oldNumBuckets; j++) { - item = oldBuckets[j]; - while (item != NULL) { - next = item->next; - key = item->key; - posn = ddLCHash2(key[0], key[0], shift); - item->next = buckets[posn]; - buckets[posn] = item; - item = next; - } - } - } else if (hash->keysize == 2) { - for (j = 0; j < oldNumBuckets; j++) { - item = oldBuckets[j]; - while (item != NULL) { - next = item->next; - key = item->key; - posn = ddLCHash2(key[0], key[1], shift); - item->next = buckets[posn]; - buckets[posn] = item; - item = next; - } - } - } else if (hash->keysize == 3) { - for (j = 0; j < oldNumBuckets; j++) { - item = oldBuckets[j]; - while (item != NULL) { - next = item->next; - key = item->key; - posn = ddLCHash3(key[0], key[1], key[2], shift); - item->next = buckets[posn]; - buckets[posn] = item; - item = next; - } - } - } else { - for (j = 0; j < oldNumBuckets; j++) { - item = oldBuckets[j]; - while (item != NULL) { - next = item->next; - posn = ddLCHash(item->key, hash->keysize, shift); - item->next = buckets[posn]; - buckets[posn] = item; - item = next; - } - } - } - FREE(oldBuckets); - return(1); - -} /* end of cuddHashTableResize */ - - -/**Function******************************************************************** - - Synopsis [Fast storage allocation for items in a hash table.] - - Description [Fast storage allocation for items in a hash table. The - first 4 bytes of a chunk contain a pointer to the next block; the - rest contains DD_MEM_CHUNK spaces for hash items. Returns a pointer to - a new item if successful; NULL is memory is full.] - - SideEffects [None] - - SeeAlso [cuddAllocNode cuddDynamicAllocNode] - -******************************************************************************/ -DD_INLINE -static DdHashItem * -cuddHashTableAlloc( - DdHashTable * hash) -{ - int i; - unsigned int itemsize = hash->itemsize; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - DdHashItem **mem, *thisOne, *next, *item; - - if (hash->nextFree == NULL) { - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize); - MMoutOfMemory = saveHandler; -#ifdef __osf__ -#pragma pointer_size restore -#endif - if (mem == NULL) { - if (hash->manager->stash != NULL) { - FREE(hash->manager->stash); - hash->manager->stash = NULL; - /* Inhibit resizing of tables. */ - hash->manager->maxCacheHard = hash->manager->cacheSlots - 1; - hash->manager->cacheSlack = -(hash->manager->cacheSlots + 1); - for (i = 0; i < hash->manager->size; i++) { - hash->manager->subtables[i].maxKeys <<= 2; - } - hash->manager->gcFrac = 0.2; - hash->manager->minDead = - (unsigned) (0.2 * (double) hash->manager->slots); -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - mem = (DdHashItem **) ALLOC(char,(DD_MEM_CHUNK+1) * itemsize); -#ifdef __osf__ -#pragma pointer_size restore -#endif - } - if (mem == NULL) { - (*MMoutOfMemory)((DD_MEM_CHUNK + 1) * itemsize); - hash->manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - } - - mem[0] = (DdHashItem *) hash->memoryList; - hash->memoryList = mem; - - thisOne = (DdHashItem *) ((char *) mem + itemsize); - hash->nextFree = thisOne; - for (i = 1; i < DD_MEM_CHUNK; i++) { - next = (DdHashItem *) ((char *) thisOne + itemsize); - thisOne->next = next; - thisOne = next; - } - - thisOne->next = NULL; - - } - item = hash->nextFree; - hash->nextFree = item->next; - return(item); - -} /* end of cuddHashTableAlloc */ diff --git a/src/bdd/cudd/cuddLevelQ.c b/src/bdd/cudd/cuddLevelQ.c deleted file mode 100644 index 3cc8e8d8..00000000 --- a/src/bdd/cudd/cuddLevelQ.c +++ /dev/null @@ -1,533 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddLevelQ.c] - - PackageName [cudd] - - Synopsis [Procedure to manage level queues.] - - Description [The functions in this file allow an application to - easily manipulate a queue where nodes are prioritized by level. The - emphasis is on efficiency. Therefore, the queue items can have - variable size. If the application does not need to attach - information to the nodes, it can declare the queue items to be of - type DdQueueItem. Otherwise, it can declare them to be of a - structure type such that the first three fields are data - pointers. The third pointer points to the node. The first two - pointers are used by the level queue functions. The remaining fields - are initialized to 0 when a new item is created, and are then left - to the exclusive use of the application. On the DEC Alphas the three - pointers must be 32-bit pointers when CUDD is compiled with 32-bit - pointers. The level queue functions make sure that each node - appears at most once in the queue. They do so by keeping a hash - table where the node is used as key. Queue items are recycled via a - free list for efficiency. - - Internal procedures provided by this module: -
              -
            • cuddLevelQueueInit() -
            • cuddLevelQueueQuit() -
            • cuddLevelQueueEnqueue() -
            • cuddLevelQueueDequeue() -
            - Static procedures included in this module: -
              -
            • hashLookup() -
            • hashInsert() -
            • hashDelete() -
            • hashResize() -
            - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no - warranty about the suitability of this software for any - purpose. It is presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddLevelQ.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**Macro*********************************************************************** - - Synopsis [Hash function for the table of a level queue.] - - Description [Hash function for the table of a level queue.] - - SideEffects [None] - - SeeAlso [hashInsert hashLookup hashDelete] - -******************************************************************************/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define lqHash(key,shift) \ -(((unsigned)(unsigned long)(key) * DD_P1) >> (shift)) -#else -#define lqHash(key,shift) \ -(((unsigned)(key) * DD_P1) >> (shift)) -#endif - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdQueueItem * hashLookup ARGS((DdLevelQueue *queue, void *key)); -static int hashInsert ARGS((DdLevelQueue *queue, DdQueueItem *item)); -static void hashDelete ARGS((DdLevelQueue *queue, DdQueueItem *item)); -static int hashResize ARGS((DdLevelQueue *queue)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Initializes a level queue.] - - Description [Initializes a level queue. A level queue is a queue - where inserts are based on the levels of the nodes. Within each - level the policy is FIFO. Level queues are useful in traversing a - BDD top-down. Queue items are kept in a free list when dequeued for - efficiency. Returns a pointer to the new queue if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueQuit cuddLevelQueueEnqueue cuddLevelQueueDequeue] - -******************************************************************************/ -DdLevelQueue * -cuddLevelQueueInit( - int levels /* number of levels */, - int itemSize /* size of the item */, - int numBuckets /* initial number of hash buckets */) -{ - DdLevelQueue *queue; - int logSize; - - queue = ALLOC(DdLevelQueue,1); - if (queue == NULL) - return(NULL); -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - /* Keep pointers to the insertion points for all levels. */ - queue->last = ALLOC(DdQueueItem *, levels); -#ifdef __osf__ -#pragma pointer_size restore -#endif - if (queue->last == NULL) { - FREE(queue); - return(NULL); - } - /* Use a hash table to test for uniqueness. */ - if (numBuckets < 2) numBuckets = 2; - logSize = cuddComputeFloorLog2(numBuckets); - queue->numBuckets = 1 << logSize; - queue->shift = sizeof(int) * 8 - logSize; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - queue->buckets = ALLOC(DdQueueItem *, queue->numBuckets); -#ifdef __osf__ -#pragma pointer_size restore -#endif - if (queue->buckets == NULL) { - FREE(queue->last); - FREE(queue); - return(NULL); - } -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - memset(queue->last, 0, levels * sizeof(DdQueueItem *)); - memset(queue->buckets, 0, queue->numBuckets * sizeof(DdQueueItem *)); -#ifdef __osf__ -#pragma pointer_size restore -#endif - queue->first = NULL; - queue->freelist = NULL; - queue->levels = levels; - queue->itemsize = itemSize; - queue->size = 0; - queue->maxsize = queue->numBuckets * DD_MAX_SUBTABLE_DENSITY; - return(queue); - -} /* end of cuddLevelQueueInit */ - - -/**Function******************************************************************** - - Synopsis [Shuts down a level queue.] - - Description [Shuts down a level queue and releases all the - associated memory.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueInit] - -******************************************************************************/ -void -cuddLevelQueueQuit( - DdLevelQueue * queue) -{ - DdQueueItem *item; - - while (queue->freelist != NULL) { - item = queue->freelist; - queue->freelist = item->next; - FREE(item); - } - while (queue->first != NULL) { - item = (DdQueueItem *) queue->first; - queue->first = item->next; - FREE(item); - } - FREE(queue->buckets); - FREE(queue->last); - FREE(queue); - return; - -} /* end of cuddLevelQueueQuit */ - - -/**Function******************************************************************** - - Synopsis [Inserts a new key in a level queue.] - - Description [Inserts a new key in a level queue. A new entry is - created in the queue only if the node is not already - enqueued. Returns a pointer to the queue item if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueInit cuddLevelQueueDequeue] - -******************************************************************************/ -void * -cuddLevelQueueEnqueue( - DdLevelQueue * queue /* level queue */, - void * key /* key to be enqueued */, - int level /* level at which to insert */) -{ - int plevel; - DdQueueItem *item; - -#ifdef DD_DEBUG - assert(level < queue->levels); -#endif - /* Check whether entry for this node exists. */ - item = hashLookup(queue,key); - if (item != NULL) return(item); - - /* Get a free item from either the free list or the memory manager. */ - if (queue->freelist == NULL) { - item = (DdQueueItem *) ALLOC(char, queue->itemsize); - if (item == NULL) - return(NULL); - } else { - item = queue->freelist; - queue->freelist = item->next; - } - /* Initialize. */ - memset(item, 0, queue->itemsize); - item->key = key; - /* Update stats. */ - queue->size++; - - if (queue->last[level]) { - /* There are already items for this level in the queue. */ - item->next = queue->last[level]->next; - queue->last[level]->next = item; - } else { - /* There are no items at the current level. Look for the first - ** non-empty level preceeding this one. */ - plevel = level; - while (plevel != 0 && queue->last[plevel] == NULL) - plevel--; - if (queue->last[plevel] == NULL) { - /* No element precedes this one in the queue. */ - item->next = (DdQueueItem *) queue->first; - queue->first = item; - } else { - item->next = queue->last[plevel]->next; - queue->last[plevel]->next = item; - } - } - queue->last[level] = item; - - /* Insert entry for the key in the hash table. */ - if (hashInsert(queue,item) == 0) { - return(NULL); - } - return(item); - -} /* end of cuddLevelQueueEnqueue */ - - -/**Function******************************************************************** - - Synopsis [Remove an item from the front of a level queue.] - - Description [Remove an item from the front of a level queue.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueEnqueue] - -******************************************************************************/ -void -cuddLevelQueueDequeue( - DdLevelQueue * queue, - int level) -{ - DdQueueItem *item = (DdQueueItem *) queue->first; - - /* Delete from the hash table. */ - hashDelete(queue,item); - - /* Since we delete from the front, if this is the last item for - ** its level, there are no other items for the same level. */ - if (queue->last[level] == item) - queue->last[level] = NULL; - - queue->first = item->next; - /* Put item on the free list. */ - item->next = queue->freelist; - queue->freelist = item; - /* Update stats. */ - queue->size--; - return; - -} /* end of cuddLevelQueueDequeue */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Looks up a key in the hash table of a level queue.] - - Description [Looks up a key in the hash table of a level queue. Returns - a pointer to the item with the given key if the key is found; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueEnqueue hashInsert] - -******************************************************************************/ -static DdQueueItem * -hashLookup( - DdLevelQueue * queue, - void * key) -{ - int posn; - DdQueueItem *item; - - posn = lqHash(key,queue->shift); - item = queue->buckets[posn]; - - while (item != NULL) { - if (item->key == key) { - return(item); - } - item = item->cnext; - } - return(NULL); - -} /* end of hashLookup */ - - -/**Function******************************************************************** - - Synopsis [Inserts an item in the hash table of a level queue.] - - Description [Inserts an item in the hash table of a level queue. Returns - 1 if successful; 0 otherwise. No check is performed to see if an item with - the same key is already in the hash table.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueEnqueue] - -******************************************************************************/ -static int -hashInsert( - DdLevelQueue * queue, - DdQueueItem * item) -{ - int result; - int posn; - - if (queue->size > queue->maxsize) { - result = hashResize(queue); - if (result == 0) return(0); - } - - posn = lqHash(item->key,queue->shift); - item->cnext = queue->buckets[posn]; - queue->buckets[posn] = item; - - return(1); - -} /* end of hashInsert */ - - -/**Function******************************************************************** - - Synopsis [Removes an item from the hash table of a level queue.] - - Description [Removes an item from the hash table of a level queue. - Nothing is done if the item is not in the table.] - - SideEffects [None] - - SeeAlso [cuddLevelQueueDequeue hashInsert] - -******************************************************************************/ -static void -hashDelete( - DdLevelQueue * queue, - DdQueueItem * item) -{ - int posn; - DdQueueItem *prevItem; - - posn = lqHash(item->key,queue->shift); - prevItem = queue->buckets[posn]; - - if (prevItem == NULL) return; - if (prevItem == item) { - queue->buckets[posn] = prevItem->cnext; - return; - } - - while (prevItem->cnext != NULL) { - if (prevItem->cnext == item) { - prevItem->cnext = item->cnext; - return; - } - prevItem = prevItem->cnext; - } - return; - -} /* end of hashDelete */ - - -/**Function******************************************************************** - - Synopsis [Resizes the hash table of a level queue.] - - Description [Resizes the hash table of a level queue. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [hashInsert] - -******************************************************************************/ -static int -hashResize( - DdLevelQueue * queue) -{ - int j; - int posn; - DdQueueItem *item; - DdQueueItem *next; - int numBuckets; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - DdQueueItem **buckets; - DdQueueItem **oldBuckets = queue->buckets; -#ifdef __osf__ -#pragma pointer_size restore -#endif - int shift; - int oldNumBuckets = queue->numBuckets; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - /* Compute the new size of the subtable. */ - numBuckets = oldNumBuckets << 1; - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - buckets = queue->buckets = ALLOC(DdQueueItem *, numBuckets); - if (buckets == NULL) { - queue->maxsize <<= 1; - return(1); - } - - queue->numBuckets = numBuckets; - shift = --(queue->shift); - queue->maxsize <<= 1; - memset(buckets, 0, numBuckets * sizeof(DdQueueItem *)); -#ifdef __osf__ -#pragma pointer_size restore -#endif - for (j = 0; j < oldNumBuckets; j++) { - item = oldBuckets[j]; - while (item != NULL) { - next = item->cnext; - posn = lqHash(item->key, shift); - item->cnext = buckets[posn]; - buckets[posn] = item; - item = next; - } - } - FREE(oldBuckets); - return(1); - -} /* end of hashResize */ diff --git a/src/bdd/cudd/cuddLinear.c b/src/bdd/cudd/cuddLinear.c deleted file mode 100644 index 7f6b3678..00000000 --- a/src/bdd/cudd/cuddLinear.c +++ /dev/null @@ -1,1333 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddLinear.c] - - PackageName [cudd] - - Synopsis [Functions for DD reduction by linear transformations.] - - Description [ Internal procedures included in this module: -
              -
            • cuddLinearAndSifting() -
            - Static procedures included in this module: -
              -
            • ddLinearUniqueCompare() -
            • ddLinearAndSiftingAux() -
            • ddLinearAndSiftingUp() -
            • ddLinearAndSiftingDown() -
            • ddLinearAndSiftingBackward() -
            • ddUndoMoves() -
            • ddUpdateInteractionMatrix() -
            • cuddLinearInPlace() -
            • cuddInitLinear() -
            • cuddResizeLinear() -
            • cuddXorLinear() -
            ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define CUDD_SWAP_MOVE 0 -#define CUDD_LINEAR_TRANSFORM_MOVE 1 -#define CUDD_INVERSE_TRANSFORM_MOVE 2 -#if SIZEOF_LONG == 8 -#define BPL 64 -#define LOGBPL 6 -#else -#define BPL 32 -#define LOGBPL 5 -#endif - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddLinear.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -static int *entry; - -#ifdef DD_STATS -extern int ddTotalNumberSwapping; -extern int ddTotalNISwaps; -static int ddTotalNumberLinearTr; -#endif - -#ifdef DD_DEBUG -static int zero = 0; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddLinearUniqueCompare ARGS((int *ptrX, int *ptrY)); -static int ddLinearAndSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static Move * ddLinearAndSiftingUp ARGS((DdManager *table, int y, int xLow, Move *prevMoves)); -static Move * ddLinearAndSiftingDown ARGS((DdManager *table, int x, int xHigh, Move *prevMoves)); -static int ddLinearAndSiftingBackward ARGS((DdManager *table, int size, Move *moves)); -static Move* ddUndoMoves ARGS((DdManager *table, Move *moves)); -static int cuddLinearInPlace ARGS((DdManager *table, int x, int y)); -static void ddUpdateInteractionMatrix ARGS((DdManager *table, int xindex, int yindex)); -static int cuddInitLinear ARGS((DdManager *table)); -static int cuddResizeLinear ARGS((DdManager *table)); -static void cuddXorLinear ARGS((DdManager *table, int x, int y)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints the linear transform matrix.] - - Description [Prints the linear transform matrix. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_PrintLinear( - DdManager * table) -{ - int i,j,k; - int retval; - int nvars = table->linearSize; - int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; - long word; - - for (i = 0; i < nvars; i++) { - for (j = 0; j < wordsPerRow; j++) { - word = table->linear[i*wordsPerRow + j]; - for (k = 0; k < BPL; k++) { - retval = fprintf(table->out,"%ld",word & 1); - if (retval == 0) return(0); - word >>= 1; - } - } - retval = fprintf(table->out,"\n"); - if (retval == 0) return(0); - } - return(1); - -} /* end of Cudd_PrintLinear */ - - -/**Function******************************************************************** - - Synopsis [Reads an entry of the linear transform matrix.] - - Description [Reads an entry of the linear transform matrix.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_ReadLinear( - DdManager * table /* CUDD manager */, - int x /* row index */, - int y /* column index */) -{ - int nvars = table->size; - int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; - long word; - int bit; - int result; - - assert(table->size == table->linearSize); - - word = wordsPerRow * x + (y >> LOGBPL); - bit = y & (BPL-1); - result = (int) ((table->linear[word] >> bit) & 1); - return(result); - -} /* end of Cudd_ReadLinear */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [BDD reduction based on combination of sifting and linear - transformations.] - - Description [BDD reduction based on combination of sifting and linear - transformations. Assumes that no dead nodes are present. -
              -
            1. Order all the variables according to the number of entries - in each unique table. -
            2. Sift the variable up and down, remembering each time the - total size of the DD heap. At each position, linear transformation - of the two adjacent variables is tried and is accepted if it reduces - the size of the DD. -
            3. Select the best permutation. -
            4. Repeat 3 and 4 for all variables. -
            - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddLinearAndSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; -#ifdef DD_STATS - int previousSize; -#endif - -#ifdef DD_STATS - ddTotalNumberLinearTr = 0; -#endif - - size = table->size; - - var = NULL; - entry = NULL; - if (table->linear == NULL) { - result = cuddInitLinear(table); - if (result == 0) goto cuddLinearAndSiftingOutOfMem; -#if 0 - (void) fprintf(table->out,"\n"); - result = Cudd_PrintLinear(table); - if (result == 0) goto cuddLinearAndSiftingOutOfMem; -#endif - } else if (table->size != table->linearSize) { - result = cuddResizeLinear(table); - if (result == 0) goto cuddLinearAndSiftingOutOfMem; -#if 0 - (void) fprintf(table->out,"\n"); - result = Cudd_PrintLinear(table); - if (result == 0) goto cuddLinearAndSiftingOutOfMem; -#endif - } - - /* Find order in which to sift variables. */ - entry = ALLOC(int,size); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddLinearAndSiftingOutOfMem; - } - var = ALLOC(int,size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddLinearAndSiftingOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->perm[i]; - entry[i] = table->subtables[x].keys; - var[i] = i; - } - - qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddLinearUniqueCompare); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { - x = table->perm[var[i]]; - if (x < lower || x > upper) continue; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddLinearAndSiftingAux(table,x,lower,upper); - if (!result) goto cuddLinearAndSiftingOutOfMem; -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"+"); /* should never happen */ - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif -#ifdef DD_DEBUG - (void) Cudd_DebugCheck(table); -#endif - } - - FREE(var); - FREE(entry); - -#ifdef DD_STATS - (void) fprintf(table->out,"\n#:L_LINSIFT %8d: linear trans.", - ddTotalNumberLinearTr); -#endif - - return(1); - -cuddLinearAndSiftingOutOfMem: - - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddLinearAndSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the - variables according to the number of keys in the subtables. - Returns the difference in number of keys between the two - variables being compared.] - - SideEffects [None] - -******************************************************************************/ -static int -ddLinearUniqueCompare( - int * ptrX, - int * ptrY) -{ -#if 0 - if (entry[*ptrY] == entry[*ptrX]) { - return((*ptrX) - (*ptrY)); - } -#endif - return(entry[*ptrY] - entry[*ptrX]); - -} /* end of ddLinearUniqueCompare */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. At each step a linear transformation is tried, and, if it - decreases the size of the DD, it is accepted. Finds the best position - and does the required changes. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddLinearAndSiftingAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - - Move *move; - Move *moveUp; /* list of up moves */ - Move *moveDown; /* list of down moves */ - int initialSize; - int result; - - initialSize = table->keys - table->isolated; - - moveDown = NULL; - moveUp = NULL; - - if (x == xLow) { - moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); - /* At this point x --> xHigh unless bounding occurred. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddLinearAndSiftingBackward(table,initialSize,moveDown); - if (!result) goto ddLinearAndSiftingAuxOutOfMem; - - } else if (x == xHigh) { - moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); - /* At this point x --> xLow unless bounding occurred. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddLinearAndSiftingBackward(table,initialSize,moveUp); - if (!result) goto ddLinearAndSiftingAuxOutOfMem; - - } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ - moveDown = ddLinearAndSiftingDown(table,x,xHigh,NULL); - /* At this point x --> xHigh unless bounding occurred. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - moveUp = ddUndoMoves(table,moveDown); -#ifdef DD_DEBUG - assert(moveUp == NULL || moveUp->x == x); -#endif - moveUp = ddLinearAndSiftingUp(table,x,xLow,moveUp); - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddLinearAndSiftingBackward(table,initialSize,moveUp); - if (!result) goto ddLinearAndSiftingAuxOutOfMem; - - } else { /* must go up first: shorter */ - moveUp = ddLinearAndSiftingUp(table,x,xLow,NULL); - /* At this point x --> xLow unless bounding occurred. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - moveDown = ddUndoMoves(table,moveUp); -#ifdef DD_DEBUG - assert(moveDown == NULL || moveDown->y == x); -#endif - moveDown = ddLinearAndSiftingDown(table,x,xHigh,moveDown); - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddLinearAndSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddLinearAndSiftingBackward(table,initialSize,moveDown); - if (!result) goto ddLinearAndSiftingAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - - return(1); - -ddLinearAndSiftingAuxOutOfMem: - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - - return(0); - -} /* end of ddLinearAndSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable up and applies linear transformations.] - - Description [Sifts a variable up and applies linear transformations. - Moves y up until either it reaches the bound (xLow) or the size of - the DD heap increases too much. Returns the set of moves in case of - success; NULL if memory is full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddLinearAndSiftingUp( - DdManager * table, - int y, - int xLow, - Move * prevMoves) -{ - Move *moves; - Move *move; - int x; - int size, newsize; - int limitSize; - int xindex, yindex; - int isolated; - int L; /* lower bound on DD size */ -#ifdef DD_DEBUG - int checkL; - int z; - int zindex; -#endif - - moves = prevMoves; - yindex = table->invperm[y]; - - /* Initialize the lower bound. - ** The part of the DD below y will not change. - ** The part of the DD above y that does not interact with y will not - ** change. The rest may vanish in the best case, except for - ** the nodes at level xLow, which will not vanish, regardless. - */ - limitSize = L = table->keys - table->isolated; - for (x = xLow + 1; x < y; x++) { - xindex = table->invperm[x]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L -= table->subtables[x].keys - isolated; - } - } - isolated = table->vars[yindex]->ref == 1; - L -= table->subtables[y].keys - isolated; - - x = cuddNextLow(table,y); - while (x >= xLow && L <= limitSize) { - xindex = table->invperm[x]; -#ifdef DD_DEBUG - checkL = table->keys - table->isolated; - for (z = xLow + 1; z < y; z++) { - zindex = table->invperm[z]; - if (cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - checkL -= table->subtables[z].keys - isolated; - } - } - isolated = table->vars[yindex]->ref == 1; - checkL -= table->subtables[y].keys - isolated; - if (L != checkL) { - (void) fprintf(table->out, "checkL(%d) != L(%d)\n",checkL,L); - } -#endif - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddLinearAndSiftingUpOutOfMem; - newsize = cuddLinearInPlace(table,x,y); - if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddLinearAndSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->next = moves; - moves = move; - move->flags = CUDD_SWAP_MOVE; - if (newsize >= size) { - /* Undo transformation. The transformation we apply is - ** its own inverse. Hence, we just apply the transformation - ** again. - */ - newsize = cuddLinearInPlace(table,x,y); - if (newsize == 0) goto ddLinearAndSiftingUpOutOfMem; -#ifdef DD_DEBUG - if (newsize != size) { - (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); - } -#endif - } else if (cuddTestInteract(table,xindex,yindex)) { - size = newsize; - move->flags = CUDD_LINEAR_TRANSFORM_MOVE; - ddUpdateInteractionMatrix(table,xindex,yindex); - } - move->size = size; - /* Update the lower bound. */ - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L += table->subtables[y].keys - isolated; - } - if ((double) size > (double) limitSize * table->maxGrowth) break; - if (size < limitSize) limitSize = size; - y = x; - x = cuddNextLow(table,y); - } - return(moves); - -ddLinearAndSiftingUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of ddLinearAndSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable down and applies linear transformations.] - - Description [Sifts a variable down and applies linear - transformations. Moves x down until either it reaches the bound - (xHigh) or the size of the DD heap increases too much. Returns the - set of moves in case of success; NULL if memory is full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddLinearAndSiftingDown( - DdManager * table, - int x, - int xHigh, - Move * prevMoves) -{ - Move *moves; - Move *move; - int y; - int size, newsize; - int R; /* upper bound on node decrease */ - int limitSize; - int xindex, yindex; - int isolated; -#ifdef DD_DEBUG - int checkR; - int z; - int zindex; -#endif - - moves = prevMoves; - /* Initialize R */ - xindex = table->invperm[x]; - limitSize = size = table->keys - table->isolated; - R = 0; - for (y = xHigh; y > x; y--) { - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R += table->subtables[y].keys - isolated; - } - } - - y = cuddNextHigh(table,x); - while (y <= xHigh && size - R < limitSize) { -#ifdef DD_DEBUG - checkR = 0; - for (z = xHigh; z > x; z--) { - zindex = table->invperm[z]; - if (cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - checkR += table->subtables[z].keys - isolated; - } - } - if (R != checkR) { - (void) fprintf(table->out, "checkR(%d) != R(%d)\n",checkR,R); - } -#endif - /* Update upper bound on node decrease. */ - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R -= table->subtables[y].keys - isolated; - } - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddLinearAndSiftingDownOutOfMem; - newsize = cuddLinearInPlace(table,x,y); - if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddLinearAndSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->next = moves; - moves = move; - move->flags = CUDD_SWAP_MOVE; - if (newsize >= size) { - /* Undo transformation. The transformation we apply is - ** its own inverse. Hence, we just apply the transformation - ** again. - */ - newsize = cuddLinearInPlace(table,x,y); - if (newsize == 0) goto ddLinearAndSiftingDownOutOfMem; - if (newsize != size) { - (void) fprintf(table->out,"Change in size after identity transformation! From %d to %d\n",size,newsize); - } - } else if (cuddTestInteract(table,xindex,yindex)) { - size = newsize; - move->flags = CUDD_LINEAR_TRANSFORM_MOVE; - ddUpdateInteractionMatrix(table,xindex,yindex); - } - move->size = size; - if ((double) size > (double) limitSize * table->maxGrowth) break; - if (size < limitSize) limitSize = size; - x = y; - y = cuddNextHigh(table,x); - } - return(moves); - -ddLinearAndSiftingDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of ddLinearAndSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the DD heap to the order - giving the minimum size.] - - Description [Given a set of moves, returns the DD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddLinearAndSiftingBackward( - DdManager * table, - int size, - Move * moves) -{ - Move *move; - int res; - - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) return(1); - if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { - res = cuddLinearInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - res = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) { - res = cuddLinearInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - } - - return(1); - -} /* end of ddLinearAndSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the DD heap to the order - in effect before the moves.] - - Description [Given a set of moves, returns the DD heap to the - order in effect before the moves. Returns 1 in case of success; - 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static Move* -ddUndoMoves( - DdManager * table, - Move * moves) -{ - Move *invmoves = NULL; - Move *move; - Move *invmove; - int size; - - for (move = moves; move != NULL; move = move->next) { - invmove = (Move *) cuddDynamicAllocNode(table); - if (invmove == NULL) goto ddUndoMovesOutOfMem; - invmove->x = move->x; - invmove->y = move->y; - invmove->next = invmoves; - invmoves = invmove; - if (move->flags == CUDD_SWAP_MOVE) { - invmove->flags = CUDD_SWAP_MOVE; - size = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto ddUndoMovesOutOfMem; - } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { - invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE; - size = cuddLinearInPlace(table,(int)move->x,(int)move->y); - if (!size) goto ddUndoMovesOutOfMem; - size = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto ddUndoMovesOutOfMem; - } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */ -#ifdef DD_DEBUG - (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n"); -#endif - invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE; - size = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto ddUndoMovesOutOfMem; - size = cuddLinearInPlace(table,(int)move->x,(int)move->y); - if (!size) goto ddUndoMovesOutOfMem; - } - invmove->size = size; - } - - return(invmoves); - -ddUndoMovesOutOfMem: - while (invmoves != NULL) { - move = invmoves->next; - cuddDeallocNode(table, (DdNode *) invmoves); - invmoves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of ddUndoMoves */ - - -/**Function******************************************************************** - - Synopsis [Linearly combines two adjacent variables.] - - Description [Linearly combines two adjacent variables. Specifically, - replaces the top variable with the exclusive nor of the two variables. - It assumes that no dead nodes are present on entry to this - procedure. The procedure then guarantees that no dead nodes will be - present when it terminates. cuddLinearInPlace assumes that x < - y. Returns the number of keys in the table if successful; 0 - otherwise.] - - SideEffects [The two subtables corrresponding to variables x and y are - modified. The global counters of the unique table are also affected.] - - SeeAlso [cuddSwapInPlace] - -******************************************************************************/ -static int -cuddLinearInPlace( - DdManager * table, - int x, - int y) -{ - DdNodePtr *xlist, *ylist; - int xindex, yindex; - int xslots, yslots; - int xshift, yshift; - int oldxkeys, oldykeys; - int newxkeys, newykeys; - int comple, newcomplement; - int i; - int posn; - int isolated; - DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; - DdNode *g,*next,*last; - DdNodePtr *previousP; - DdNode *tmp; - DdNode *sentinel = &(table->sentinel); -#if DD_DEBUG - int count, idcheck; -#endif - -#ifdef DD_DEBUG - assert(x < y); - assert(cuddNextHigh(table,x) == y); - assert(table->subtables[x].keys != 0); - assert(table->subtables[y].keys != 0); - assert(table->subtables[x].dead == 0); - assert(table->subtables[y].dead == 0); -#endif - - xindex = table->invperm[x]; - yindex = table->invperm[y]; - - if (cuddTestInteract(table,xindex,yindex)) { -#ifdef DD_STATS - ddTotalNumberLinearTr++; -#endif - /* Get parameters of x subtable. */ - xlist = table->subtables[x].nodelist; - oldxkeys = table->subtables[x].keys; - xslots = table->subtables[x].slots; - xshift = table->subtables[x].shift; - - /* Get parameters of y subtable. */ - ylist = table->subtables[y].nodelist; - oldykeys = table->subtables[y].keys; - yslots = table->subtables[y].slots; - yshift = table->subtables[y].shift; - - newxkeys = 0; - newykeys = oldykeys; - - /* Check whether the two projection functions involved in this - ** swap are isolated. At the end, we'll be able to tell how many - ** isolated projection functions are there by checking only these - ** two functions again. This is done to eliminate the isolated - ** projection functions from the node count. - */ - isolated = - ((table->vars[xindex]->ref == 1) + - (table->vars[yindex]->ref == 1)); - - /* The nodes in the x layer are put in a chain. - ** The chain is handled as a FIFO; g points to the beginning and - ** last points to the end. - */ - g = NULL; - for (i = 0; i < xslots; i++) { - f = xlist[i]; - if (f == sentinel) continue; - xlist[i] = sentinel; - if (g == NULL) { - g = f; - } else { - last->next = f; - } - while ((next = f->next) != sentinel) { - f = next; - } /* while there are elements in the collision chain */ - last = f; - } /* for each slot of the x subtable */ - last->next = NULL; - -#ifdef DD_COUNT - table->swapSteps += oldxkeys; -#endif - /* Take care of the x nodes that must be re-expressed. - ** They form a linked list pointed by g. - */ - f = g; - while (f != NULL) { - next = f->next; - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(f1))); -#endif - if ((int) f1->index == yindex) { - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - f11 = f10 = f1; - } -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(f11))); -#endif - f0 = cuddE(f); - comple = Cudd_IsComplement(f0); - f0 = Cudd_Regular(f0); - if ((int) f0->index == yindex) { - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = f00 = f0; - } - if (comple) { - f01 = Cudd_Not(f01); - f00 = Cudd_Not(f00); - } - /* Decrease ref count of f1. */ - cuddSatDec(f1->ref); - /* Create the new T child. */ - if (f11 == f00) { - newf1 = f11; - cuddSatInc(newf1->ref); - } else { - /* Check ylist for triple (yindex,f11,f00). */ - posn = ddHash(f11, f00, yshift); - /* For each element newf1 in collision list ylist[posn]. */ - previousP = &(ylist[posn]); - newf1 = *previousP; - while (f11 < cuddT(newf1)) { - previousP = &(newf1->next); - newf1 = *previousP; - } - while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) { - previousP = &(newf1->next); - newf1 = *previousP; - } - if (cuddT(newf1) == f11 && cuddE(newf1) == f00) { - cuddSatInc(newf1->ref); - } else { /* no match */ - newf1 = cuddDynamicAllocNode(table); - if (newf1 == NULL) - goto cuddLinearOutOfMem; - newf1->index = yindex; newf1->ref = 1; - cuddT(newf1) = f11; - cuddE(newf1) = f00; - /* Insert newf1 in the collision list ylist[posn]; - ** increase the ref counts of f11 and f00. - */ - newykeys++; - newf1->next = *previousP; - *previousP = newf1; - cuddSatInc(f11->ref); - tmp = Cudd_Regular(f00); - cuddSatInc(tmp->ref); - } - } - cuddT(f) = newf1; -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(newf1))); -#endif - - /* Do the same for f0, keeping complement dots into account. */ - /* decrease ref count of f0 */ - tmp = Cudd_Regular(f0); - cuddSatDec(tmp->ref); - /* create the new E child */ - if (f01 == f10) { - newf0 = f01; - tmp = Cudd_Regular(newf0); - cuddSatInc(tmp->ref); - } else { - /* make sure f01 is regular */ - newcomplement = Cudd_IsComplement(f01); - if (newcomplement) { - f01 = Cudd_Not(f01); - f10 = Cudd_Not(f10); - } - /* Check ylist for triple (yindex,f01,f10). */ - posn = ddHash(f01, f10, yshift); - /* For each element newf0 in collision list ylist[posn]. */ - previousP = &(ylist[posn]); - newf0 = *previousP; - while (f01 < cuddT(newf0)) { - previousP = &(newf0->next); - newf0 = *previousP; - } - while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) { - previousP = &(newf0->next); - newf0 = *previousP; - } - if (cuddT(newf0) == f01 && cuddE(newf0) == f10) { - cuddSatInc(newf0->ref); - } else { /* no match */ - newf0 = cuddDynamicAllocNode(table); - if (newf0 == NULL) - goto cuddLinearOutOfMem; - newf0->index = yindex; newf0->ref = 1; - cuddT(newf0) = f01; - cuddE(newf0) = f10; - /* Insert newf0 in the collision list ylist[posn]; - ** increase the ref counts of f01 and f10. - */ - newykeys++; - newf0->next = *previousP; - *previousP = newf0; - cuddSatInc(f01->ref); - tmp = Cudd_Regular(f10); - cuddSatInc(tmp->ref); - } - if (newcomplement) { - newf0 = Cudd_Not(newf0); - } - } - cuddE(f) = newf0; - - /* Re-insert the modified f in xlist. - ** The modified f does not already exists in xlist. - ** (Because of the uniqueness of the cofactors.) - */ - posn = ddHash(newf1, newf0, xshift); - newxkeys++; - previousP = &(xlist[posn]); - tmp = *previousP; - while (newf1 < cuddT(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - f->next = *previousP; - *previousP = f; - f = next; - } /* while f != NULL */ - - /* GC the y layer. */ - - /* For each node f in ylist. */ - for (i = 0; i < yslots; i++) { - previousP = &(ylist[i]); - f = *previousP; - while (f != sentinel) { - next = f->next; - if (f->ref == 0) { - tmp = cuddT(f); - cuddSatDec(tmp->ref); - tmp = Cudd_Regular(cuddE(f)); - cuddSatDec(tmp->ref); - cuddDeallocNode(table,f); - newykeys--; - } else { - *previousP = f; - previousP = &(f->next); - } - f = next; - } /* while f */ - *previousP = sentinel; - } /* for every collision list */ - -#if DD_DEBUG -#if 0 - (void) fprintf(table->out,"Linearly combining %d and %d\n",x,y); -#endif - count = 0; - idcheck = 0; - for (i = 0; i < yslots; i++) { - f = ylist[i]; - while (f != sentinel) { - count++; - if (f->index != (DdHalfWord) yindex) - idcheck++; - f = f->next; - } - } - if (count != newykeys) { - fprintf(table->err,"Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",oldykeys,newykeys,count); - } - if (idcheck != 0) - fprintf(table->err,"Error in id's of ylist\twrong id's = %d\n",idcheck); - count = 0; - idcheck = 0; - for (i = 0; i < xslots; i++) { - f = xlist[i]; - while (f != sentinel) { - count++; - if (f->index != (DdHalfWord) xindex) - idcheck++; - f = f->next; - } - } - if (count != newxkeys || newxkeys != oldxkeys) { - fprintf(table->err,"Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",oldxkeys,newxkeys,count); - } - if (idcheck != 0) - fprintf(table->err,"Error in id's of xlist\twrong id's = %d\n",idcheck); -#endif - - isolated += (table->vars[xindex]->ref == 1) + - (table->vars[yindex]->ref == 1); - table->isolated += isolated; - - /* Set the appropriate fields in table. */ - table->subtables[y].keys = newykeys; - - /* Here we should update the linear combination table - ** to record that x <- x EXNOR y. This is done by complementing - ** the (x,y) entry of the table. - */ - - table->keys += newykeys - oldykeys; - - cuddXorLinear(table,xindex,yindex); - } - -#ifdef DD_DEBUG - if (zero) { - (void) Cudd_DebugCheck(table); - } -#endif - - return(table->keys - table->isolated); - -cuddLinearOutOfMem: - (void) fprintf(table->err,"Error: cuddLinearInPlace out of memory\n"); - - return (0); - -} /* end of cuddLinearInPlace */ - - -/**Function******************************************************************** - - Synopsis [Updates the interaction matrix.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static void -ddUpdateInteractionMatrix( - DdManager * table, - int xindex, - int yindex) -{ - int i; - for (i = 0; i < yindex; i++) { - if (i != xindex && cuddTestInteract(table,i,yindex)) { - if (i < xindex) { - cuddSetInteract(table,i,xindex); - } else { - cuddSetInteract(table,xindex,i); - } - } - } - for (i = yindex+1; i < table->size; i++) { - if (i != xindex && cuddTestInteract(table,yindex,i)) { - if (i < xindex) { - cuddSetInteract(table,i,xindex); - } else { - cuddSetInteract(table,xindex,i); - } - } - } - -} /* end of ddUpdateInteractionMatrix */ - - -/**Function******************************************************************** - - Synopsis [Initializes the linear transform matrix.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static int -cuddInitLinear( - DdManager * table) -{ - int words; - int wordsPerRow; - int nvars; - int word; - int bit; - int i; - long *linear; - - nvars = table->size; - wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; - words = wordsPerRow * nvars; - table->linear = linear = ALLOC(long,words); - if (linear == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - table->memused += words * sizeof(long); - table->linearSize = nvars; - for (i = 0; i < words; i++) linear[i] = 0; - for (i = 0; i < nvars; i++) { - word = wordsPerRow * i + (i >> LOGBPL); - bit = i & (BPL-1); - linear[word] = 1 << bit; - } - return(1); - -} /* end of cuddInitLinear */ - - -/**Function******************************************************************** - - Synopsis [Resizes the linear transform matrix.] - - Description [] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static int -cuddResizeLinear( - DdManager * table) -{ - int words,oldWords; - int wordsPerRow,oldWordsPerRow; - int nvars,oldNvars; - int word,oldWord; - int bit; - int i,j; - long *linear,*oldLinear; - - oldNvars = table->linearSize; - oldWordsPerRow = ((oldNvars - 1) >> LOGBPL) + 1; - oldWords = oldWordsPerRow * oldNvars; - oldLinear = table->linear; - - nvars = table->size; - wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; - words = wordsPerRow * nvars; - table->linear = linear = ALLOC(long,words); - if (linear == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - table->memused += (words - oldWords) * sizeof(long); - for (i = 0; i < words; i++) linear[i] = 0; - - /* Copy old matrix. */ - for (i = 0; i < oldNvars; i++) { - for (j = 0; j < oldWordsPerRow; j++) { - oldWord = oldWordsPerRow * i + j; - word = wordsPerRow * i + j; - linear[word] = oldLinear[oldWord]; - } - } - FREE(oldLinear); - - /* Add elements to the diagonal. */ - for (i = oldNvars; i < nvars; i++) { - word = wordsPerRow * i + (i >> LOGBPL); - bit = i & (BPL-1); - linear[word] = 1 << bit; - } - table->linearSize = nvars; - - return(1); - -} /* end of cuddResizeLinear */ - - -/**Function******************************************************************** - - Synopsis [XORs two rows of the linear transform matrix.] - - Description [XORs two rows of the linear transform matrix and replaces - the first row with the result.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static void -cuddXorLinear( - DdManager * table, - int x, - int y) -{ - int i; - int nvars = table->size; - int wordsPerRow = ((nvars - 1) >> LOGBPL) + 1; - int xstart = wordsPerRow * x; - int ystart = wordsPerRow * y; - long *linear = table->linear; - - for (i = 0; i < wordsPerRow; i++) { - linear[xstart+i] ^= linear[ystart+i]; - } - -} /* end of cuddXorLinear */ - diff --git a/src/bdd/cudd/cuddLiteral.c b/src/bdd/cudd/cuddLiteral.c deleted file mode 100644 index 43740690..00000000 --- a/src/bdd/cudd/cuddLiteral.c +++ /dev/null @@ -1,237 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddLiteral.c] - - PackageName [cudd] - - Synopsis [Functions for manipulation of literal sets represented by - BDDs.] - - Description [External procedures included in this file: -
              -
            • Cudd_bddLiteralSetIntersection() -
            - Internal procedures included in this file: -
              -
            • cuddBddLiteralSetIntersectionRecur() -
            ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddLiteral.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the intesection of two sets of literals - represented as BDDs.] - - Description [Computes the intesection of two sets of literals - represented as BDDs. Each set is represented as a cube of the - literals in the set. The empty set is represented by the constant 1. - No variable can be simultaneously present in both phases in a set. - Returns a pointer to the BDD representing the intersected sets, if - successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -Cudd_bddLiteralSetIntersection( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddLiteralSetIntersectionRecur(dd,f,g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddLiteralSetIntersection */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of - Cudd_bddLiteralSetIntersection.] - - Description [Performs the recursive step of - Cudd_bddLiteralSetIntersection. Scans the cubes for common variables, - and checks whether they agree in phase. Returns a pointer to the - resulting cube if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -cuddBddLiteralSetIntersectionRecur( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res, *tmp; - DdNode *F, *G; - DdNode *fc, *gc; - DdNode *one; - DdNode *zero; - unsigned int topf, topg, comple; - int phasef, phaseg; - - statLine(dd); - if (f == g) return(f); - - F = Cudd_Regular(f); - G = Cudd_Regular(g); - one = DD_ONE(dd); - - /* Here f != g. If F == G, then f and g are complementary. - ** Since they are two cubes, this case only occurs when f == v, - ** g == v', and v is a variable or its complement. - */ - if (F == G) return(one); - - zero = Cudd_Not(one); - topf = cuddI(dd,F->index); - topg = cuddI(dd,G->index); - /* Look for a variable common to both cubes. If there are none, this - ** loop will stop when the constant node is reached in both cubes. - */ - while (topf != topg) { - if (topf < topg) { /* move down on f */ - comple = f != F; - f = cuddT(F); - if (comple) f = Cudd_Not(f); - if (f == zero) { - f = cuddE(F); - if (comple) f = Cudd_Not(f); - } - F = Cudd_Regular(f); - topf = cuddI(dd,F->index); - } else if (topg < topf) { - comple = g != G; - g = cuddT(G); - if (comple) g = Cudd_Not(g); - if (g == zero) { - g = cuddE(G); - if (comple) g = Cudd_Not(g); - } - G = Cudd_Regular(g); - topg = cuddI(dd,G->index); - } - } - - /* At this point, f == one <=> g == 1. It suffices to test one of them. */ - if (f == one) return(one); - - res = cuddCacheLookup2(dd,Cudd_bddLiteralSetIntersection,f,g); - if (res != NULL) { - return(res); - } - - /* Here f and g are both non constant and have the same top variable. */ - comple = f != F; - fc = cuddT(F); - phasef = 1; - if (comple) fc = Cudd_Not(fc); - if (fc == zero) { - fc = cuddE(F); - phasef = 0; - if (comple) fc = Cudd_Not(fc); - } - comple = g != G; - gc = cuddT(G); - phaseg = 1; - if (comple) gc = Cudd_Not(gc); - if (gc == zero) { - gc = cuddE(G); - phaseg = 0; - if (comple) gc = Cudd_Not(gc); - } - - tmp = cuddBddLiteralSetIntersectionRecur(dd,fc,gc); - if (tmp == NULL) { - return(NULL); - } - - if (phasef != phaseg) { - res = tmp; - } else { - cuddRef(tmp); - if (phasef == 0) { - res = cuddBddAndRecur(dd,Cudd_Not(dd->vars[F->index]),tmp); - } else { - res = cuddBddAndRecur(dd,dd->vars[F->index],tmp); - } - if (res == NULL) { - Cudd_RecursiveDeref(dd,tmp); - return(NULL); - } - cuddDeref(tmp); /* Just cuddDeref, because it is included in result */ - } - - cuddCacheInsert2(dd,Cudd_bddLiteralSetIntersection,f,g,res); - - return(res); - -} /* end of cuddBddLiteralSetIntersectionRecur */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddMatMult.c b/src/bdd/cudd/cuddMatMult.c deleted file mode 100644 index 345e7921..00000000 --- a/src/bdd/cudd/cuddMatMult.c +++ /dev/null @@ -1,680 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddMatMult.c] - - PackageName [cudd] - - Synopsis [Matrix multiplication functions.] - - Description [External procedures included in this module: -
              -
            • Cudd_addMatrixMultiply() -
            • Cudd_addTimesPlus() -
            • Cudd_addTriangle() -
            • Cudd_addOuterSum() -
            - Static procedures included in this module: -
              -
            • addMMRecur() -
            • addTriangleRecur() -
            • cuddAddOuterSumRecur() -
            ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddMatMult.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * addMMRecur ARGS((DdManager *dd, DdNode *A, DdNode *B, int topP, int *vars)); -static DdNode * addTriangleRecur ARGS((DdManager *dd, DdNode *f, DdNode *g, int *vars, DdNode *cube)); -static DdNode * cuddAddOuterSumRecur ARGS((DdManager *dd, DdNode *M, DdNode *r, DdNode *c)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Calculates the product of two matrices represented as - ADDs.] - - Description [Calculates the product of two matrices, A and B, - represented as ADDs. This procedure implements the quasiring multiplication - algorithm. A is assumed to depend on variables x (rows) and z - (columns). B is assumed to depend on variables z (rows) and y - (columns). The product of A and B then depends on x (rows) and y - (columns). Only the z variables have to be explicitly identified; - they are the "summation" variables. Returns a pointer to the - result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addTimesPlus Cudd_addTriangle Cudd_bddAndAbstract] - -******************************************************************************/ -DdNode * -Cudd_addMatrixMultiply( - DdManager * dd, - DdNode * A, - DdNode * B, - DdNode ** z, - int nz) -{ - int i, nvars, *vars; - DdNode *res; - - /* Array vars says what variables are "summation" variables. */ - nvars = dd->size; - vars = ALLOC(int,nvars); - if (vars == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < nvars; i++) { - vars[i] = 0; - } - for (i = 0; i < nz; i++) { - vars[z[i]->index] = 1; - } - - do { - dd->reordered = 0; - res = addMMRecur(dd,A,B,-1,vars); - } while (dd->reordered == 1); - FREE(vars); - return(res); - -} /* end of Cudd_addMatrixMultiply */ - - -/**Function******************************************************************** - - Synopsis [Calculates the product of two matrices represented as - ADDs.] - - Description [Calculates the product of two matrices, A and B, - represented as ADDs, using the CMU matrix by matrix multiplication - procedure by Clarke et al.. Matrix A has x's as row variables and z's - as column variables, while matrix B has z's as row variables and y's - as column variables. Returns the pointer to the result if successful; - NULL otherwise. The resulting matrix has x's as row variables and y's - as column variables.] - - SideEffects [None] - - SeeAlso [Cudd_addMatrixMultiply] - -******************************************************************************/ -DdNode * -Cudd_addTimesPlus( - DdManager * dd, - DdNode * A, - DdNode * B, - DdNode ** z, - int nz) -{ - DdNode *w, *cube, *tmp, *res; - int i; - tmp = Cudd_addApply(dd,Cudd_addTimes,A,B); - if (tmp == NULL) return(NULL); - Cudd_Ref(tmp); - Cudd_Ref(cube = DD_ONE(dd)); - for (i = nz-1; i >= 0; i--) { - w = Cudd_addIte(dd,z[i],cube,DD_ZERO(dd)); - if (w == NULL) { - Cudd_RecursiveDeref(dd,tmp); - return(NULL); - } - Cudd_Ref(w); - Cudd_RecursiveDeref(dd,cube); - cube = w; - } - res = Cudd_addExistAbstract(dd,tmp,cube); - if (res == NULL) { - Cudd_RecursiveDeref(dd,tmp); - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - Cudd_Ref(res); - Cudd_RecursiveDeref(dd,cube); - Cudd_RecursiveDeref(dd,tmp); - Cudd_Deref(res); - return(res); - -} /* end of Cudd_addTimesPlus */ - - -/**Function******************************************************************** - - Synopsis [Performs the triangulation step for the shortest path - computation.] - - Description [Implements the semiring multiplication algorithm used in - the triangulation step for the shortest path computation. f - is assumed to depend on variables x (rows) and z (columns). g is - assumed to depend on variables z (rows) and y (columns). The product - of f and g then depends on x (rows) and y (columns). Only the z - variables have to be explicitly identified; they are the - "abstraction" variables. Returns a pointer to the result if - successful; NULL otherwise. ] - - SideEffects [None] - - SeeAlso [Cudd_addMatrixMultiply Cudd_bddAndAbstract] - -******************************************************************************/ -DdNode * -Cudd_addTriangle( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode ** z, - int nz) -{ - int i, nvars, *vars; - DdNode *res, *cube; - - nvars = dd->size; - vars = ALLOC(int, nvars); - if (vars == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < nvars; i++) vars[i] = -1; - for (i = 0; i < nz; i++) vars[z[i]->index] = i; - cube = Cudd_addComputeCube(dd, z, NULL, nz); - if (cube == NULL) { - FREE(vars); - return(NULL); - } - cuddRef(cube); - - do { - dd->reordered = 0; - res = addTriangleRecur(dd, f, g, vars, cube); - } while (dd->reordered == 1); - if (res != NULL) cuddRef(res); - Cudd_RecursiveDeref(dd,cube); - if (res != NULL) cuddDeref(res); - FREE(vars); - return(res); - -} /* end of Cudd_addTriangle */ - - -/**Function******************************************************************** - - Synopsis [Takes the minimum of a matrix and the outer sum of two vectors.] - - Description [Takes the pointwise minimum of a matrix and the outer - sum of two vectors. This procedure is used in the Floyd-Warshall - all-pair shortest path algorithm. Returns a pointer to the result if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_addOuterSum( - DdManager *dd, - DdNode *M, - DdNode *r, - DdNode *c) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddAddOuterSumRecur(dd, M, r, c); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_addOuterSum */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addMatrixMultiply.] - - Description [Performs the recursive step of Cudd_addMatrixMultiply. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -static DdNode * -addMMRecur( - DdManager * dd, - DdNode * A, - DdNode * B, - int topP, - int * vars) -{ - DdNode *zero, - *At, /* positive cofactor of first operand */ - *Ae, /* negative cofactor of first operand */ - *Bt, /* positive cofactor of second operand */ - *Be, /* negative cofactor of second operand */ - *t, /* positive cofactor of result */ - *e, /* negative cofactor of result */ - *scaled, /* scaled result */ - *add_scale, /* ADD representing the scaling factor */ - *res; - int i; /* loop index */ - double scale; /* scaling factor */ - int index; /* index of the top variable */ - CUDD_VALUE_TYPE value; - unsigned int topA, topB, topV; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - - statLine(dd); - zero = DD_ZERO(dd); - - if (A == zero || B == zero) { - return(zero); - } - - if (cuddIsConstant(A) && cuddIsConstant(B)) { - /* Compute the scaling factor. It is 2^k, where k is the - ** number of summation variables below the current variable. - ** Indeed, these constants represent blocks of 2^k identical - ** constant values in both A and B. - */ - value = cuddV(A) * cuddV(B); - for (i = 0; i < dd->size; i++) { - if (vars[i]) { - if (dd->perm[i] > topP) { - value *= (CUDD_VALUE_TYPE) 2; - } - } - } - res = cuddUniqueConst(dd, value); - return(res); - } - - /* Standardize to increase cache efficiency. Clearly, A*B != B*A - ** in matrix multiplication. However, which matrix is which is - ** determined by the variables appearing in the ADDs and not by - ** which one is passed as first argument. - */ - if (A > B) { - DdNode *tmp = A; - A = B; - B = tmp; - } - - topA = cuddI(dd,A->index); topB = cuddI(dd,B->index); - topV = ddMin(topA,topB); - - cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) addMMRecur; - res = cuddCacheLookup2(dd,cacheOp,A,B); - if (res != NULL) { - /* If the result is 0, there is no need to normalize. - ** Otherwise we count the number of z variables between - ** the current depth and the top of the ADDs. These are - ** the missing variables that determine the size of the - ** constant blocks. - */ - if (res == zero) return(res); - scale = 1.0; - for (i = 0; i < dd->size; i++) { - if (vars[i]) { - if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { - scale *= 2; - } - } - } - if (scale > 1.0) { - cuddRef(res); - add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); - if (add_scale == NULL) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - cuddRef(add_scale); - scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); - if (scaled == NULL) { - Cudd_RecursiveDeref(dd, add_scale); - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - cuddRef(scaled); - Cudd_RecursiveDeref(dd, add_scale); - Cudd_RecursiveDeref(dd, res); - res = scaled; - cuddDeref(res); - } - return(res); - } - - /* compute the cofactors */ - if (topV == topA) { - At = cuddT(A); - Ae = cuddE(A); - } else { - At = Ae = A; - } - if (topV == topB) { - Bt = cuddT(B); - Be = cuddE(B); - } else { - Bt = Be = B; - } - - t = addMMRecur(dd, At, Bt, (int)topV, vars); - if (t == NULL) return(NULL); - cuddRef(t); - e = addMMRecur(dd, Ae, Be, (int)topV, vars); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddRef(e); - - index = dd->invperm[topV]; - if (vars[index] == 0) { - /* We have split on either the rows of A or the columns - ** of B. We just need to connect the two subresults, - ** which correspond to two submatrices of the result. - */ - res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - cuddRef(res); - cuddDeref(t); - cuddDeref(e); - } else { - /* we have simultaneously split on the columns of A and - ** the rows of B. The two subresults must be added. - */ - res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - } - - cuddCacheInsert2(dd,cacheOp,A,B,res); - - /* We have computed (and stored in the computed table) a minimal - ** result; that is, a result that assumes no summation variables - ** between the current depth of the recursion and its top - ** variable. We now take into account the z variables by properly - ** scaling the result. - */ - if (res != zero) { - scale = 1.0; - for (i = 0; i < dd->size; i++) { - if (vars[i]) { - if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { - scale *= 2; - } - } - } - if (scale > 1.0) { - add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); - if (add_scale == NULL) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - cuddRef(add_scale); - scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); - if (scaled == NULL) { - Cudd_RecursiveDeref(dd, res); - Cudd_RecursiveDeref(dd, add_scale); - return(NULL); - } - cuddRef(scaled); - Cudd_RecursiveDeref(dd, add_scale); - Cudd_RecursiveDeref(dd, res); - res = scaled; - } - } - cuddDeref(res); - return(res); - -} /* end of addMMRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addTriangle.] - - Description [Performs the recursive step of Cudd_addTriangle. Returns - a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - -******************************************************************************/ -static DdNode * -addTriangleRecur( - DdManager * dd, - DdNode * f, - DdNode * g, - int * vars, - DdNode *cube) -{ - DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res; - CUDD_VALUE_TYPE value; - int top, topf, topg, index; - - statLine(dd); - if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) { - return(DD_PLUS_INFINITY(dd)); - } - - if (cuddIsConstant(f) && cuddIsConstant(g)) { - value = cuddV(f) + cuddV(g); - res = cuddUniqueConst(dd, value); - return(res); - } - if (f < g) { - DdNode *tmp = f; - f = g; - g = tmp; - } - - if (f->ref != 1 || g->ref != 1) { - res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube); - if (res != NULL) { - return(res); - } - } - - topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); - top = ddMin(topf,topg); - - if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;} - if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;} - - t = addTriangleRecur(dd, fv, gv, vars, cube); - if (t == NULL) return(NULL); - cuddRef(t); - e = addTriangleRecur(dd, fvn, gvn, vars, cube); - if (e == NULL) { - Cudd_RecursiveDeref(dd, t); - return(NULL); - } - cuddRef(e); - - index = dd->invperm[top]; - if (vars[index] < 0) { - res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } else { - res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e); - if (res == NULL) { - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, t); - Cudd_RecursiveDeref(dd, e); - cuddDeref(res); - } - - if (f->ref != 1 || g->ref != 1) { - cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res); - } - - return(res); - -} /* end of addTriangleRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_addOuterSum.] - - Description [Performs the recursive step of Cudd_addOuterSum. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -cuddAddOuterSumRecur( - DdManager *dd, - DdNode *M, - DdNode *r, - DdNode *c) -{ - DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re; - int topM, topc, topr; - int v, index; - - statLine(dd); - /* Check special cases. */ - if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M); - - if (cuddIsConstant(c) && cuddIsConstant(r)) { - R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r)); - cuddRef(R); - if (cuddIsConstant(M)) { - if (cuddV(R) <= cuddV(M)) { - cuddDeref(R); - return(R); - } else { - Cudd_RecursiveDeref(dd,R); - return(M); - } - } else { - P = Cudd_addApply(dd,Cudd_addMinimum,R,M); - cuddRef(P); - Cudd_RecursiveDeref(dd,R); - cuddDeref(P); - return(P); - } - } - - /* Check the cache. */ - R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c); - if (R != NULL) return(R); - - topM = cuddI(dd,M->index); topr = cuddI(dd,r->index); - topc = cuddI(dd,c->index); - v = ddMin(topM,ddMin(topr,topc)); - - /* Compute cofactors. */ - if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; } - if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; } - if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; } - - /* Recursively solve. */ - Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct); - if (Rt == NULL) return(NULL); - cuddRef(Rt); - Re = cuddAddOuterSumRecur(dd,Me,re,ce); - if (Re == NULL) { - Cudd_RecursiveDeref(dd, Rt); - return(NULL); - } - cuddRef(Re); - index = dd->invperm[v]; - R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re); - if (R == NULL) { - Cudd_RecursiveDeref(dd, Rt); - Cudd_RecursiveDeref(dd, Re); - return(NULL); - } - cuddDeref(Rt); - cuddDeref(Re); - - /* Store the result in the cache. */ - cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R); - - return(R); - -} /* end of cuddAddOuterSumRecur */ diff --git a/src/bdd/cudd/cuddPriority.c b/src/bdd/cudd/cuddPriority.c deleted file mode 100644 index 788fc712..00000000 --- a/src/bdd/cudd/cuddPriority.c +++ /dev/null @@ -1,1475 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddPriority.c] - - PackageName [cudd] - - Synopsis [Priority functions.] - - Description [External procedures included in this file: -
              -
            • Cudd_PrioritySelect() -
            • Cudd_Xgty() -
            • Cudd_Xeqy() -
            • Cudd_addXeqy() -
            • Cudd_Dxygtdxz() -
            • Cudd_Dxygtdyz() -
            • Cudd_CProjection() -
            • Cudd_addHamming() -
            • Cudd_MinHammingDist() -
            • Cudd_bddClosestCube() -
            - Internal procedures included in this module: -
              -
            • cuddCProjectionRecur() -
            • cuddBddClosestCube() -
            - Static procedures included in this module: -
              -
            • cuddMinHammingDistRecur() -
            • separateCube() -
            • createResult() -
            - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddPriority.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ -static int cuddMinHammingDistRecur ARGS((DdNode * f, int *minterm, DdHashTable * table, int upperBound)); -static DdNode * separateCube ARGS((DdManager *dd, DdNode *f, CUDD_VALUE_TYPE *distance)); -static DdNode * createResult ARGS((DdManager *dd, unsigned int index, unsigned int phase, DdNode *cube, CUDD_VALUE_TYPE distance)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Selects pairs from R using a priority function.] - - Description [Selects pairs from a relation R(x,y) (given as a BDD) - in such a way that a given x appears in one pair only. Uses a - priority function to determine which y should be paired to a given x. - Cudd_PrioritySelect returns a pointer to - the selected function if successful; NULL otherwise. - Three of the arguments--x, y, and z--are vectors of BDD variables. - The first two are the variables on which R depends. The third vectore - is a vector of auxiliary variables, used during the computation. This - vector is optional. If a NULL value is passed instead, - Cudd_PrioritySelect will create the working variables on the fly. - The sizes of x and y (and z if it is not NULL) should equal n. - The priority function Pi can be passed as a BDD, or can be built by - Cudd_PrioritySelect. If NULL is passed instead of a DdNode *, - parameter Pifunc is used by Cudd_PrioritySelect to build a BDD for the - priority function. (Pifunc is a pointer to a C function.) If Pi is not - NULL, then Pifunc is ignored. Pifunc should have the same interface as - the standard priority functions (e.g., Cudd_Dxygtdxz). - Cudd_PrioritySelect and Cudd_CProjection can sometimes be used - interchangeably. Specifically, calling Cudd_PrioritySelect with - Cudd_Xgty as Pifunc produces the same result as calling - Cudd_CProjection with the all-zero minterm as reference minterm. - However, depending on the application, one or the other may be - preferable: -
              -
            • When extracting representatives from an equivalence relation, - Cudd_CProjection has the advantage of nor requiring the auxiliary - variables. -
            • When computing matchings in general bipartite graphs, - Cudd_PrioritySelect normally obtains better results because it can use - more powerful matching schemes (e.g., Cudd_Dxygtdxz). -
            - ] - - SideEffects [If called with z == NULL, will create new variables in - the manager.] - - SeeAlso [Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_Xgty - Cudd_bddAdjPermuteX Cudd_CProjection] - -******************************************************************************/ -DdNode * -Cudd_PrioritySelect( - DdManager * dd /* manager */, - DdNode * R /* BDD of the relation */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */, - DdNode ** z /* array of z variables (optional: may be NULL) */, - DdNode * Pi /* BDD of the priority function (optional: may be NULL) */, - int n /* size of x, y, and z */, - DdNode * (*Pifunc)(DdManager *, int, DdNode **, DdNode **, DdNode **) /* function used to build Pi if it is NULL */) -{ - DdNode *res = NULL; - DdNode *zcube = NULL; - DdNode *Rxz, *Q; - int createdZ = 0; - int createdPi = 0; - int i; - - /* Create z variables if needed. */ - if (z == NULL) { - if (Pi != NULL) return(NULL); - z = ALLOC(DdNode *,n); - if (z == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - createdZ = 1; - for (i = 0; i < n; i++) { - if (dd->size >= (int) CUDD_MAXINDEX - 1) goto endgame; - z[i] = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one)); - if (z[i] == NULL) goto endgame; - } - } - - /* Create priority function BDD if needed. */ - if (Pi == NULL) { - Pi = Pifunc(dd,n,x,y,z); - if (Pi == NULL) goto endgame; - createdPi = 1; - cuddRef(Pi); - } - - /* Initialize abstraction cube. */ - zcube = DD_ONE(dd); - cuddRef(zcube); - for (i = n - 1; i >= 0; i--) { - DdNode *tmpp; - tmpp = Cudd_bddAnd(dd,z[i],zcube); - if (tmpp == NULL) goto endgame; - cuddRef(tmpp); - Cudd_RecursiveDeref(dd,zcube); - zcube = tmpp; - } - - /* Compute subset of (x,y) pairs. */ - Rxz = Cudd_bddSwapVariables(dd,R,y,z,n); - if (Rxz == NULL) goto endgame; - cuddRef(Rxz); - Q = Cudd_bddAndAbstract(dd,Rxz,Pi,zcube); - if (Q == NULL) { - Cudd_RecursiveDeref(dd,Rxz); - goto endgame; - } - cuddRef(Q); - Cudd_RecursiveDeref(dd,Rxz); - res = Cudd_bddAnd(dd,R,Cudd_Not(Q)); - if (res == NULL) { - Cudd_RecursiveDeref(dd,Q); - goto endgame; - } - cuddRef(res); - Cudd_RecursiveDeref(dd,Q); - -endgame: - if (zcube != NULL) Cudd_RecursiveDeref(dd,zcube); - if (createdZ) { - FREE(z); - } - if (createdPi) { - Cudd_RecursiveDeref(dd,Pi); - } - if (res != NULL) cuddDeref(res); - return(res); - -} /* Cudd_PrioritySelect */ - - -/**Function******************************************************************** - - Synopsis [Generates a BDD for the function x > y.] - - Description [This function generates a BDD for the function x > y. - Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and - y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. - The BDD is built bottom-up. - It has 3*N-1 internal nodes, if the variables are ordered as follows: - x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. - Argument z is not used by Cudd_Xgty: it is included to make it - call-compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz.] - - SideEffects [None] - - SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Dxygtdyz] - -******************************************************************************/ -DdNode * -Cudd_Xgty( - DdManager * dd /* DD manager */, - int N /* number of x and y variables */, - DdNode ** z /* array of z variables: unused */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */) -{ - DdNode *u, *v, *w; - int i; - - /* Build bottom part of BDD outside loop. */ - u = Cudd_bddAnd(dd, x[N-1], Cudd_Not(y[N-1])); - if (u == NULL) return(NULL); - cuddRef(u); - - /* Loop to build the rest of the BDD. */ - for (i = N-2; i >= 0; i--) { - v = Cudd_bddAnd(dd, y[i], Cudd_Not(u)); - if (v == NULL) { - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(v); - w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u); - if (w == NULL) { - Cudd_RecursiveDeref(dd, u); - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, u); - u = Cudd_bddIte(dd, x[i], Cudd_Not(v), w); - if (u == NULL) { - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - - } - cuddDeref(u); - return(u); - -} /* end of Cudd_Xgty */ - - -/**Function******************************************************************** - - Synopsis [Generates a BDD for the function x==y.] - - Description [This function generates a BDD for the function x==y. - Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and - y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. - The BDD is built bottom-up. - It has 3*N-1 internal nodes, if the variables are ordered as follows: - x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ] - - SideEffects [None] - - SeeAlso [Cudd_addXeqy] - -******************************************************************************/ -DdNode * -Cudd_Xeqy( - DdManager * dd /* DD manager */, - int N /* number of x and y variables */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */) -{ - DdNode *u, *v, *w; - int i; - - /* Build bottom part of BDD outside loop. */ - u = Cudd_bddIte(dd, x[N-1], y[N-1], Cudd_Not(y[N-1])); - if (u == NULL) return(NULL); - cuddRef(u); - - /* Loop to build the rest of the BDD. */ - for (i = N-2; i >= 0; i--) { - v = Cudd_bddAnd(dd, y[i], u); - if (v == NULL) { - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(v); - w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u); - if (w == NULL) { - Cudd_RecursiveDeref(dd, u); - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, u); - u = Cudd_bddIte(dd, x[i], v, w); - if (u == NULL) { - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - } - cuddDeref(u); - return(u); - -} /* end of Cudd_Xeqy */ - - -/**Function******************************************************************** - - Synopsis [Generates an ADD for the function x==y.] - - Description [This function generates an ADD for the function x==y. - Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and - y\[0\] y\[1\] ... y\[N-1\], with 0 the most significant bit. - The ADD is built bottom-up. - It has 3*N-1 internal nodes, if the variables are ordered as follows: - x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ] - - SideEffects [None] - - SeeAlso [Cudd_Xeqy] - -******************************************************************************/ -DdNode * -Cudd_addXeqy( - DdManager * dd /* DD manager */, - int N /* number of x and y variables */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */) -{ - DdNode *one, *zero; - DdNode *u, *v, *w; - int i; - - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - /* Build bottom part of ADD outside loop. */ - v = Cudd_addIte(dd, y[N-1], one, zero); - if (v == NULL) return(NULL); - cuddRef(v); - w = Cudd_addIte(dd, y[N-1], zero, one); - if (w == NULL) { - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(w); - u = Cudd_addIte(dd, x[N-1], v, w); - if (w == NULL) { - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - - /* Loop to build the rest of the ADD. */ - for (i = N-2; i >= 0; i--) { - v = Cudd_addIte(dd, y[i], u, zero); - if (v == NULL) { - Cudd_RecursiveDeref(dd, u); - return(NULL); - } - cuddRef(v); - w = Cudd_addIte(dd, y[i], zero, u); - if (w == NULL) { - Cudd_RecursiveDeref(dd, u); - Cudd_RecursiveDeref(dd, v); - return(NULL); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, u); - u = Cudd_addIte(dd, x[i], v, w); - if (w == NULL) { - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - return(NULL); - } - cuddRef(u); - Cudd_RecursiveDeref(dd, v); - Cudd_RecursiveDeref(dd, w); - } - cuddDeref(u); - return(u); - -} /* end of Cudd_addXeqy */ - - -/**Function******************************************************************** - - Synopsis [Generates a BDD for the function d(x,y) > d(x,z).] - - Description [This function generates a BDD for the function d(x,y) - > d(x,z); - x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\], - y\[0\] y\[1\] ... y\[N-1\], and z\[0\] z\[1\] ... z\[N-1\], - with 0 the most significant bit. - The distance d(x,y) is defined as: - \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}). - The BDD is built bottom-up. - It has 7*N-3 internal nodes, if the variables are ordered as follows: - x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ] - - SideEffects [None] - - SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdyz Cudd_Xgty Cudd_bddAdjPermuteX] - -******************************************************************************/ -DdNode * -Cudd_Dxygtdxz( - DdManager * dd /* DD manager */, - int N /* number of x, y, and z variables */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */, - DdNode ** z /* array of z variables */) -{ - DdNode *one, *zero; - DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1; - int i; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Build bottom part of BDD outside loop. */ - y1_ = Cudd_bddIte(dd, y[N-1], one, Cudd_Not(z[N-1])); - if (y1_ == NULL) return(NULL); - cuddRef(y1_); - y2 = Cudd_bddIte(dd, y[N-1], z[N-1], one); - if (y2 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - return(NULL); - } - cuddRef(y2); - x1 = Cudd_bddIte(dd, x[N-1], y1_, y2); - if (x1 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - return(NULL); - } - cuddRef(x1); - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - - /* Loop to build the rest of the BDD. */ - for (i = N-2; i >= 0; i--) { - z1 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1)); - if (z1 == NULL) { - Cudd_RecursiveDeref(dd, x1); - return(NULL); - } - cuddRef(z1); - z2 = Cudd_bddIte(dd, z[i], x1, one); - if (z2 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - return(NULL); - } - cuddRef(z2); - z3 = Cudd_bddIte(dd, z[i], one, x1); - if (z3 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - return(NULL); - } - cuddRef(z3); - z4 = Cudd_bddIte(dd, z[i], x1, zero); - if (z4 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - return(NULL); - } - cuddRef(z4); - Cudd_RecursiveDeref(dd, x1); - y1_ = Cudd_bddIte(dd, y[i], z2, Cudd_Not(z1)); - if (y1_ == NULL) { - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - return(NULL); - } - cuddRef(y1_); - y2 = Cudd_bddIte(dd, y[i], z4, z3); - if (y2 == NULL) { - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - Cudd_RecursiveDeref(dd, y1_); - return(NULL); - } - cuddRef(y2); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - x1 = Cudd_bddIte(dd, x[i], y1_, y2); - if (x1 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - return(NULL); - } - cuddRef(x1); - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - } - cuddDeref(x1); - return(Cudd_Not(x1)); - -} /* end of Cudd_Dxygtdxz */ - - -/**Function******************************************************************** - - Synopsis [Generates a BDD for the function d(x,y) > d(y,z).] - - Description [This function generates a BDD for the function d(x,y) - > d(y,z); - x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\], - y\[0\] y\[1\] ... y\[N-1\], and z\[0\] z\[1\] ... z\[N-1\], - with 0 the most significant bit. - The distance d(x,y) is defined as: - \sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}). - The BDD is built bottom-up. - It has 7*N-3 internal nodes, if the variables are ordered as follows: - x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ] - - SideEffects [None] - - SeeAlso [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Xgty Cudd_bddAdjPermuteX] - -******************************************************************************/ -DdNode * -Cudd_Dxygtdyz( - DdManager * dd /* DD manager */, - int N /* number of x, y, and z variables */, - DdNode ** x /* array of x variables */, - DdNode ** y /* array of y variables */, - DdNode ** z /* array of z variables */) -{ - DdNode *one, *zero; - DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1; - int i; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - /* Build bottom part of BDD outside loop. */ - y1_ = Cudd_bddIte(dd, y[N-1], one, z[N-1]); - if (y1_ == NULL) return(NULL); - cuddRef(y1_); - y2 = Cudd_bddIte(dd, y[N-1], z[N-1], zero); - if (y2 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - return(NULL); - } - cuddRef(y2); - x1 = Cudd_bddIte(dd, x[N-1], y1_, Cudd_Not(y2)); - if (x1 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - return(NULL); - } - cuddRef(x1); - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - - /* Loop to build the rest of the BDD. */ - for (i = N-2; i >= 0; i--) { - z1 = Cudd_bddIte(dd, z[i], x1, zero); - if (z1 == NULL) { - Cudd_RecursiveDeref(dd, x1); - return(NULL); - } - cuddRef(z1); - z2 = Cudd_bddIte(dd, z[i], x1, one); - if (z2 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - return(NULL); - } - cuddRef(z2); - z3 = Cudd_bddIte(dd, z[i], one, x1); - if (z3 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - return(NULL); - } - cuddRef(z3); - z4 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1)); - if (z4 == NULL) { - Cudd_RecursiveDeref(dd, x1); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - return(NULL); - } - cuddRef(z4); - Cudd_RecursiveDeref(dd, x1); - y1_ = Cudd_bddIte(dd, y[i], z2, z1); - if (y1_ == NULL) { - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - return(NULL); - } - cuddRef(y1_); - y2 = Cudd_bddIte(dd, y[i], z4, Cudd_Not(z3)); - if (y2 == NULL) { - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - Cudd_RecursiveDeref(dd, y1_); - return(NULL); - } - cuddRef(y2); - Cudd_RecursiveDeref(dd, z1); - Cudd_RecursiveDeref(dd, z2); - Cudd_RecursiveDeref(dd, z3); - Cudd_RecursiveDeref(dd, z4); - x1 = Cudd_bddIte(dd, x[i], y1_, Cudd_Not(y2)); - if (x1 == NULL) { - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - return(NULL); - } - cuddRef(x1); - Cudd_RecursiveDeref(dd, y1_); - Cudd_RecursiveDeref(dd, y2); - } - cuddDeref(x1); - return(Cudd_Not(x1)); - -} /* end of Cudd_Dxygtdyz */ - - -/**Function******************************************************************** - - Synopsis [Computes the compatible projection of R w.r.t. cube Y.] - - Description [Computes the compatible projection of relation R with - respect to cube Y. Returns a pointer to the c-projection if - successful; NULL otherwise. For a comparison between Cudd_CProjection - and Cudd_PrioritySelect, see the documentation of the latter.] - - SideEffects [None] - - SeeAlso [Cudd_PrioritySelect] - -******************************************************************************/ -DdNode * -Cudd_CProjection( - DdManager * dd, - DdNode * R, - DdNode * Y) -{ - DdNode *res; - DdNode *support; - - if (cuddCheckCube(dd,Y) == 0) { - (void) fprintf(dd->err, - "Error: The third argument of Cudd_CProjection should be a cube\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - /* Compute the support of Y, which is used by the abstraction step - ** in cuddCProjectionRecur. - */ - support = Cudd_Support(dd,Y); - if (support == NULL) return(NULL); - cuddRef(support); - - do { - dd->reordered = 0; - res = cuddCProjectionRecur(dd,R,Y,support); - } while (dd->reordered == 1); - - if (res == NULL) { - Cudd_RecursiveDeref(dd,support); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd,support); - cuddDeref(res); - - return(res); - -} /* end of Cudd_CProjection */ - - -/**Function******************************************************************** - - Synopsis [Computes the Hamming distance ADD.] - - Description [Computes the Hamming distance ADD. Returns an ADD that - gives the Hamming distance between its two arguments if successful; - NULL otherwise. The two vectors xVars and yVars identify the variables - that form the two arguments.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_addHamming( - DdManager * dd, - DdNode ** xVars, - DdNode ** yVars, - int nVars) -{ - DdNode *result,*tempBdd; - DdNode *tempAdd,*temp; - int i; - - result = DD_ZERO(dd); - cuddRef(result); - - for (i = 0; i < nVars; i++) { - tempBdd = Cudd_bddIte(dd,xVars[i],Cudd_Not(yVars[i]),yVars[i]); - if (tempBdd == NULL) { - Cudd_RecursiveDeref(dd,result); - return(NULL); - } - cuddRef(tempBdd); - tempAdd = Cudd_BddToAdd(dd,tempBdd); - if (tempAdd == NULL) { - Cudd_RecursiveDeref(dd,tempBdd); - Cudd_RecursiveDeref(dd,result); - return(NULL); - } - cuddRef(tempAdd); - Cudd_RecursiveDeref(dd,tempBdd); - temp = Cudd_addApply(dd,Cudd_addPlus,tempAdd,result); - if (temp == NULL) { - Cudd_RecursiveDeref(dd,tempAdd); - Cudd_RecursiveDeref(dd,result); - return(NULL); - } - cuddRef(temp); - Cudd_RecursiveDeref(dd,tempAdd); - Cudd_RecursiveDeref(dd,result); - result = temp; - } - - cuddDeref(result); - return(result); - -} /* end of Cudd_addHamming */ - - -/**Function******************************************************************** - - Synopsis [Returns the minimum Hamming distance between f and minterm.] - - Description [Returns the minimum Hamming distance between the - minterms of a function f and a reference minterm. The function is - given as a BDD; the minterm is given as an array of integers, one - for each variable in the manager. Returns the minimum distance if - it is less than the upper bound; the upper bound if the minimum - distance is at least as large; CUDD_OUT_OF_MEM in case of failure.] - - SideEffects [None] - - SeeAlso [Cudd_addHamming Cudd_bddClosestCube] - -******************************************************************************/ -int -Cudd_MinHammingDist( - DdManager *dd /* DD manager */, - DdNode *f /* function to examine */, - int *minterm /* reference minterm */, - int upperBound /* distance above which an approximate answer is OK */) -{ - DdHashTable *table; - CUDD_VALUE_TYPE epsilon; - int res; - - table = cuddHashTableInit(dd,1,2); - if (table == NULL) { - return(CUDD_OUT_OF_MEM); - } - epsilon = Cudd_ReadEpsilon(dd); - Cudd_SetEpsilon(dd,(CUDD_VALUE_TYPE)0.0); - res = cuddMinHammingDistRecur(f,minterm,table,upperBound); - cuddHashTableQuit(table); - Cudd_SetEpsilon(dd,epsilon); - - return(res); - -} /* end of Cudd_MinHammingDist */ - - -/**Function******************************************************************** - - Synopsis [Finds a cube of f at minimum Hamming distance from g.] - - Description [Finds a cube of f at minimum Hamming distance from the - minterms of g. All the minterms of the cube are at the minimum - distance. If the distance is 0, the cube belongs to the - intersection of f and g. Returns the cube if successful; NULL - otherwise.] - - SideEffects [The distance is returned as a side effect.] - - SeeAlso [Cudd_MinHammingDist] - -******************************************************************************/ -DdNode * -Cudd_bddClosestCube( - DdManager *dd, - DdNode * f, - DdNode *g, - int *distance) -{ - DdNode *res, *acube; - CUDD_VALUE_TYPE rdist; - - /* Compute the cube and distance as a single ADD. */ - do { - dd->reordered = 0; - res = cuddBddClosestCube(dd,f,g,CUDD_CONST_INDEX + 1.0); - } while (dd->reordered == 1); - if (res == NULL) return(NULL); - cuddRef(res); - - /* Unpack distance and cube. */ - do { - dd->reordered = 0; - acube = separateCube(dd, res, &rdist); - } while (dd->reordered == 1); - if (acube == NULL) { - Cudd_RecursiveDeref(dd, res); - return(NULL); - } - cuddRef(acube); - Cudd_RecursiveDeref(dd, res); - - /* Convert cube from ADD to BDD. */ - do { - dd->reordered = 0; - res = cuddAddBddDoPattern(dd, acube); - } while (dd->reordered == 1); - if (res == NULL) { - Cudd_RecursiveDeref(dd, acube); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, acube); - - *distance = (int) rdist; - cuddDeref(res); - return(res); - -} /* end of Cudd_bddClosestCube */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CProjection.] - - Description [Performs the recursive step of Cudd_CProjection. Returns - the projection if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_CProjection] - -******************************************************************************/ -DdNode * -cuddCProjectionRecur( - DdManager * dd, - DdNode * R, - DdNode * Y, - DdNode * Ysupp) -{ - DdNode *res, *res1, *res2, *resA; - DdNode *r, *y, *RT, *RE, *YT, *YE, *Yrest, *Ra, *Ran, *Gamma, *Alpha; - unsigned int topR, topY, top, index; - DdNode *one = DD_ONE(dd); - - statLine(dd); - if (Y == one) return(R); - -#ifdef DD_DEBUG - assert(!Cudd_IsConstant(Y)); -#endif - - if (R == Cudd_Not(one)) return(R); - - res = cuddCacheLookup2(dd, Cudd_CProjection, R, Y); - if (res != NULL) return(res); - - r = Cudd_Regular(R); - topR = cuddI(dd,r->index); - y = Cudd_Regular(Y); - topY = cuddI(dd,y->index); - - top = ddMin(topR, topY); - - /* Compute the cofactors of R */ - if (topR == top) { - index = r->index; - RT = cuddT(r); - RE = cuddE(r); - if (r != R) { - RT = Cudd_Not(RT); RE = Cudd_Not(RE); - } - } else { - RT = RE = R; - } - - if (topY > top) { - /* Y does not depend on the current top variable. - ** We just need to compute the results on the two cofactors of R - ** and make them the children of a node labeled r->index. - */ - res1 = cuddCProjectionRecur(dd,RT,Y,Ysupp); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res2 = cuddCProjectionRecur(dd,RE,Y,Ysupp); - if (res2 == NULL) { - Cudd_RecursiveDeref(dd,res1); - return(NULL); - } - cuddRef(res2); - res = cuddBddIteRecur(dd, dd->vars[index], res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,res2); - return(NULL); - } - /* If we have reached this point, res1 and res2 are now - ** incorporated in res. cuddDeref is therefore sufficient. - */ - cuddDeref(res1); - cuddDeref(res2); - } else { - /* Compute the cofactors of Y */ - index = y->index; - YT = cuddT(y); - YE = cuddE(y); - if (y != Y) { - YT = Cudd_Not(YT); YE = Cudd_Not(YE); - } - if (YT == Cudd_Not(one)) { - Alpha = Cudd_Not(dd->vars[index]); - Yrest = YE; - Ra = RE; - Ran = RT; - } else { - Alpha = dd->vars[index]; - Yrest = YT; - Ra = RT; - Ran = RE; - } - Gamma = cuddBddExistAbstractRecur(dd,Ra,cuddT(Ysupp)); - if (Gamma == NULL) return(NULL); - if (Gamma == one) { - res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res = cuddBddAndRecur(dd, Alpha, res1); - if (res == NULL) { - Cudd_RecursiveDeref(dd,res1); - return(NULL); - } - cuddDeref(res1); - } else if (Gamma == Cudd_Not(one)) { - res1 = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); - if (res1 == NULL) return(NULL); - cuddRef(res1); - res = cuddBddAndRecur(dd, Cudd_Not(Alpha), res1); - if (res == NULL) { - Cudd_RecursiveDeref(dd,res1); - return(NULL); - } - cuddDeref(res1); - } else { - cuddRef(Gamma); - resA = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); - if (resA == NULL) { - Cudd_RecursiveDeref(dd,Gamma); - return(NULL); - } - cuddRef(resA); - res2 = cuddBddAndRecur(dd, Cudd_Not(Gamma), resA); - if (res2 == NULL) { - Cudd_RecursiveDeref(dd,Gamma); - Cudd_RecursiveDeref(dd,resA); - return(NULL); - } - cuddRef(res2); - Cudd_RecursiveDeref(dd,Gamma); - Cudd_RecursiveDeref(dd,resA); - res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); - if (res1 == NULL) { - Cudd_RecursiveDeref(dd,res2); - return(NULL); - } - cuddRef(res1); - res = cuddBddIteRecur(dd, Alpha, res1, res2); - if (res == NULL) { - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,res2); - return(NULL); - } - cuddDeref(res1); - cuddDeref(res2); - } - } - - cuddCacheInsert2(dd,Cudd_CProjection,R,Y,res); - - return(res); - -} /* end of cuddCProjectionRecur */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddClosestCube.] - - Description [Performs the recursive step of Cudd_bddClosestCube. - Returns the cube if succesful; NULL otherwise. The procedure uses a - four-way recursion to examine all four combinations of cofactors of - f and g. The most interesting feature of this function is the - scheme used for caching the results in the global computed table. - Since we have a cube and a distance, we combine them to form an ADD. - The combination replaces the zero child of the top node of the cube - with the negative of the distance. (The use of the negative is to - avoid ambiguity with 1.) The degenerate cases (zero and one) are - treated specially because the distance is known (0 for one, and - infinity for zero).] - - SideEffects [None] - - SeeAlso [Cudd_bddClosestCube] - -******************************************************************************/ -DdNode * -cuddBddClosestCube( - DdManager *dd, - DdNode *f, - DdNode *g, - CUDD_VALUE_TYPE bound) -{ - DdNode *res, *F, *G, *ft, *fe, *gt, *ge, *tt, *ee; - DdNode *ctt, *cee, *cte, *cet; - CUDD_VALUE_TYPE minD, dtt, dee, dte, det; - DdNode *one = DD_ONE(dd); - DdNode *lzero = Cudd_Not(one); - DdNode *azero = DD_ZERO(dd); - unsigned int topf, topg, index; - - statLine(dd); - if (bound < (f == Cudd_Not(g))) return(azero); - /* Terminal cases. */ - if (g == lzero || f == lzero) return(azero); - if (f == one && g == one) return(one); - - /* Check cache. */ - F = Cudd_Regular(f); - G = Cudd_Regular(g); - if (F->ref != 1 || G->ref != 1) { - res = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, - DdNode *)) Cudd_bddClosestCube, f, g); - if (res != NULL) return(res); - } - - topf = cuddI(dd,F->index); - topg = cuddI(dd,G->index); - - /* Compute cofactors. */ - if (topf <= topg) { - index = F->index; - ft = cuddT(F); - fe = cuddE(F); - if (Cudd_IsComplement(f)) { - ft = Cudd_Not(ft); - fe = Cudd_Not(fe); - } - } else { - index = G->index; - ft = fe = f; - } - - if (topg <= topf) { - gt = cuddT(G); - ge = cuddE(G); - if (Cudd_IsComplement(g)) { - gt = Cudd_Not(gt); - ge = Cudd_Not(ge); - } - } else { - gt = ge = g; - } - - tt = cuddBddClosestCube(dd,ft,gt,bound); - if (tt == NULL) return(NULL); - cuddRef(tt); - ctt = separateCube(dd,tt,&dtt); - if (ctt == NULL) { - Cudd_RecursiveDeref(dd, tt); - return(NULL); - } - cuddRef(ctt); - Cudd_RecursiveDeref(dd, tt); - minD = dtt; - bound = ddMin(bound,minD); - - ee = cuddBddClosestCube(dd,fe,ge,bound); - if (ee == NULL) { - Cudd_RecursiveDeref(dd, ctt); - return(NULL); - } - cuddRef(ee); - cee = separateCube(dd,ee,&dee); - if (cee == NULL) { - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, ee); - return(NULL); - } - cuddRef(cee); - Cudd_RecursiveDeref(dd, ee); - minD = ddMin(dtt, dee); - bound = ddMin(bound,minD-1); - - if (minD > 0 && topf == topg) { - DdNode *te = cuddBddClosestCube(dd,ft,ge,bound-1); - if (te == NULL) { - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, cee); - return(NULL); - } - cuddRef(te); - cte = separateCube(dd,te,&dte); - if (cte == NULL) { - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, cee); - Cudd_RecursiveDeref(dd, te); - return(NULL); - } - cuddRef(cte); - Cudd_RecursiveDeref(dd, te); - dte += 1.0; - minD = ddMin(minD, dte); - } else { - cte = azero; - cuddRef(cte); - dte = CUDD_CONST_INDEX + 1.0; - } - bound = ddMin(bound,minD-1); - - if (minD > 0 && topf == topg) { - DdNode *et = cuddBddClosestCube(dd,fe,gt,bound-1); - if (et == NULL) { - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, cee); - Cudd_RecursiveDeref(dd, cte); - return(NULL); - } - cuddRef(et); - cet = separateCube(dd,et,&det); - if (cet == NULL) { - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, cee); - Cudd_RecursiveDeref(dd, cte); - Cudd_RecursiveDeref(dd, et); - return(NULL); - } - cuddRef(cet); - Cudd_RecursiveDeref(dd, et); - det += 1.0; - minD = ddMin(minD, det); - } else { - cet = azero; - cuddRef(cet); - det = CUDD_CONST_INDEX + 1.0; - } - - if (minD == dtt) { - if (dtt == dee && ctt == cee) { - res = createResult(dd,CUDD_CONST_INDEX,1,ctt,dtt); - } else { - res = createResult(dd,index,1,ctt,dtt); - } - } else if (minD == dee) { - res = createResult(dd,index,0,cee,dee); - } else if (minD == dte) { - res = createResult(dd,index,(topf <= topg),cte,dte); - } else { - res = createResult(dd,index,(topf > topg),cet,det); - } - cuddRef(res); - Cudd_RecursiveDeref(dd, ctt); - Cudd_RecursiveDeref(dd, cee); - Cudd_RecursiveDeref(dd, cte); - Cudd_RecursiveDeref(dd, cet); - - if (F->ref != 1 || G->ref != 1) - cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, - DdNode *)) Cudd_bddClosestCube, f, g, res); - - cuddDeref(res); - return(res); - -} /* end of cuddBddClosestCube */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_MinHammingDist.] - - Description [Performs the recursive step of Cudd_MinHammingDist. - It is based on the following identity. Let H(f) be the - minimum Hamming distance of the minterms of f from the reference - minterm. Then: - - H(f) = min(H(f0)+h0,H(f1)+h1) - - where f0 and f1 are the two cofactors of f with respect to its top - variable; h0 is 1 if the minterm assigns 1 to the top variable of f; - h1 is 1 if the minterm assigns 0 to the top variable of f. - The upper bound on the distance is used to bound the depth of the - recursion. - Returns the minimum distance unless it exceeds the upper bound or - computation fails.] - - SideEffects [None] - - SeeAlso [Cudd_MinHammingDist] - -******************************************************************************/ -static int -cuddMinHammingDistRecur( - DdNode * f, - int *minterm, - DdHashTable * table, - int upperBound) -{ - DdNode *F, *Ft, *Fe; - double h, hT, hE; - DdNode *zero, *res; - DdManager *dd = table->manager; - - statLine(dd); - if (upperBound == 0) return(0); - - F = Cudd_Regular(f); - - if (cuddIsConstant(F)) { - zero = Cudd_Not(DD_ONE(dd)); - if (f == dd->background || f == zero) { - return(upperBound); - } else { - return(0); - } - } - if ((res = cuddHashTableLookup1(table,f)) != NULL) { - h = cuddV(res); - if (res->ref == 0) { - dd->dead++; - dd->constants.dead++; - } - return((int) h); - } - - Ft = cuddT(F); Fe = cuddE(F); - if (Cudd_IsComplement(f)) { - Ft = Cudd_Not(Ft); Fe = Cudd_Not(Fe); - } - if (minterm[F->index] == 0) { - DdNode *temp = Ft; - Ft = Fe; Fe = temp; - } - - hT = cuddMinHammingDistRecur(Ft,minterm,table,upperBound); - if (hT == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); - if (hT == 0) { - hE = upperBound; - } else { - hE = cuddMinHammingDistRecur(Fe,minterm,table,upperBound - 1); - if (hE == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); - } - h = ddMin(hT, hE + 1); - - if (F->ref != 1) { - ptrint fanout = (ptrint) F->ref; - cuddSatDec(fanout); - res = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) h); - if (!cuddHashTableInsert1(table,f,res,fanout)) { - cuddRef(res); Cudd_RecursiveDeref(dd, res); - return(CUDD_OUT_OF_MEM); - } - } - - return((int) h); - -} /* end of cuddMinHammingDistRecur */ - - -/**Function******************************************************************** - - Synopsis [Separates cube from distance.] - - Description [Separates cube from distance. Returns the cube if - successful; NULL otherwise.] - - SideEffects [The distance is returned as a side effect.] - - SeeAlso [cuddBddClosestCube createResult] - -******************************************************************************/ -static DdNode * -separateCube( - DdManager *dd, - DdNode *f, - CUDD_VALUE_TYPE *distance) -{ - DdNode *cube, *t; - - /* One and zero are special cases because the distance is implied. */ - if (Cudd_IsConstant(f)) { - *distance = (f == DD_ONE(dd)) ? 0.0 : - (1.0 + (CUDD_VALUE_TYPE) CUDD_CONST_INDEX); - return(f); - } - - /* Find out which branch points to the distance and replace the top - ** node with one pointing to zero instead. */ - t = cuddT(f); - if (Cudd_IsConstant(t) && cuddV(t) <= 0) { -#ifdef DD_DEBUG - assert(!Cudd_IsConstant(cuddE(f)) || cuddE(f) == DD_ONE(dd)); -#endif - *distance = -cuddV(t); - cube = cuddUniqueInter(dd, f->index, DD_ZERO(dd), cuddE(f)); - } else { -#ifdef DD_DEBUG - assert(!Cudd_IsConstant(t) || t == DD_ONE(dd)); -#endif - *distance = -cuddV(cuddE(f)); - cube = cuddUniqueInter(dd, f->index, t, DD_ZERO(dd)); - } - - return(cube); - -} /* end of separateCube */ - - -/**Function******************************************************************** - - Synopsis [Builds a result for cache storage.] - - Description [Builds a result for cache storage. Returns a pointer - to the resulting ADD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddBddClosestCube separateCube] - -******************************************************************************/ -static DdNode * -createResult( - DdManager *dd, - unsigned int index, - unsigned int phase, - DdNode *cube, - CUDD_VALUE_TYPE distance) -{ - DdNode *res, *constant; - - /* Special case. The cube is either one or zero, and we do not - ** add any variables. Hence, the result is also one or zero, - ** and the distance remains implied by teh value of the constant. */ - if (index == CUDD_CONST_INDEX && Cudd_IsConstant(cube)) return(cube); - - constant = cuddUniqueConst(dd,-distance); - if (constant == NULL) return(NULL); - cuddRef(constant); - - if (index == CUDD_CONST_INDEX) { - /* Replace the top node. */ - if (cuddT(cube) == DD_ZERO(dd)) { - res = cuddUniqueInter(dd,cube->index,constant,cuddE(cube)); - } else { - res = cuddUniqueInter(dd,cube->index,cuddT(cube),constant); - } - } else { - /* Add a new top node. */ -#ifdef DD_DEBUG - assert(cuddI(dd,index) < cuddI(dd,cube->index)); -#endif - if (phase) { - res = cuddUniqueInter(dd,index,cube,constant); - } else { - res = cuddUniqueInter(dd,index,constant,cube); - } - } - if (res == NULL) { - Cudd_RecursiveDeref(dd, constant); - return(NULL); - } - cuddDeref(constant); /* safe because constant is part of res */ - - return(res); - -} /* end of createResult */ diff --git a/src/bdd/cudd/cuddRead.c b/src/bdd/cudd/cuddRead.c deleted file mode 100644 index 2c4a86d8..00000000 --- a/src/bdd/cudd/cuddRead.c +++ /dev/null @@ -1,490 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddRead.c] - - PackageName [cudd] - - Synopsis [Functions to read in a matrix] - - Description [External procedures included in this module: -
              -
            • Cudd_addRead() -
            • Cudd_bddRead() -
            ] - - SeeAlso [cudd_addHarwell.c] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddRead.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Reads in a sparse matrix.] - - Description [Reads in a sparse matrix specified in a simple format. - The first line of the input contains the numbers of rows and columns. - The remaining lines contain the elements of the matrix, one per line. - Given a background value - (specified by the background field of the manager), only the values - different from it are explicitly listed. Each foreground element is - described by two integers, i.e., the row and column number, and a - real number, i.e., the value.

            - Cudd_addRead produces an ADD that depends on two sets of variables: x - and y. The x variables (x\[0\] ... x\[nx-1\]) encode the row index and - the y variables (y\[0\] ... y\[ny-1\]) encode the column index. - x\[0\] and y\[0\] are the most significant bits in the indices. - The variables may already exist or may be created by the function. - The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.

            - On input, nx and ny hold the numbers - of row and column variables already in existence. On output, they - hold the numbers of row and column variables actually used by the - matrix. When Cudd_addRead creates the variable arrays, - the index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy. - When some variables already exist Cudd_addRead expects the indices - of the existing x variables to be bx+i*sx, and the indices of the - existing y variables to be by+i*sy.

            - m and n are set to the numbers of rows and columns of the - matrix. Their values on input are immaterial. - The ADD for the - sparse matrix is returned in E, and its reference count is > 0. - Cudd_addRead returns 1 in case of success; 0 otherwise.] - - SideEffects [nx and ny are set to the numbers of row and column - variables. m and n are set to the numbers of rows and columns. x and y - are possibly extended to represent the array of row and column - variables. Similarly for xn and yn_, which hold on return from - Cudd_addRead the complements of the row and column variables.] - - SeeAlso [Cudd_addHarwell Cudd_bddRead] - -******************************************************************************/ -int -Cudd_addRead( - FILE * fp /* input file pointer */, - DdManager * dd /* DD manager */, - DdNode ** E /* characteristic function of the graph */, - DdNode *** x /* array of row variables */, - DdNode *** y /* array of column variables */, - DdNode *** xn /* array of complemented row variables */, - DdNode *** yn_ /* array of complemented column variables */, - int * nx /* number or row variables */, - int * ny /* number or column variables */, - int * m /* number of rows */, - int * n /* number of columns */, - int bx /* first index of row variables */, - int sx /* step of row variables */, - int by /* first index of column variables */, - int sy /* step of column variables */) -{ - DdNode *one, *zero; - DdNode *w, *neW; - DdNode *minterm1; - int u, v, err, i, nv; - int lnx, lny; - CUDD_VALUE_TYPE val; - DdNode **lx, **ly, **lxn, **lyn; - - one = DD_ONE(dd); - zero = DD_ZERO(dd); - - err = fscanf(fp, "%d %d", &u, &v); - if (err == EOF) { - return(0); - } else if (err != 2) { - return(0); - } - - *m = u; - /* Compute the number of x variables. */ - lx = *x; lxn = *xn; - u--; /* row and column numbers start from 0 */ - for (lnx=0; u > 0; lnx++) { - u >>= 1; - } - /* Here we rely on the fact that REALLOC of a null pointer is - ** translates to an ALLOC. - */ - if (lnx > *nx) { - *x = lx = REALLOC(DdNode *, *x, lnx); - if (lx == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *xn = lxn = REALLOC(DdNode *, *xn, lnx); - if (lxn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } - - *n = v; - /* Compute the number of y variables. */ - ly = *y; lyn = *yn_; - v--; /* row and column numbers start from 0 */ - for (lny=0; v > 0; lny++) { - v >>= 1; - } - /* Here we rely on the fact that REALLOC of a null pointer is - ** translates to an ALLOC. - */ - if (lny > *ny) { - *y = ly = REALLOC(DdNode *, *y, lny); - if (ly == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - *yn_ = lyn = REALLOC(DdNode *, *yn_, lny); - if (lyn == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } - - /* Create all new variables. */ - for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) { - do { - dd->reordered = 0; - lx[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (lx[i] == NULL) return(0); - cuddRef(lx[i]); - do { - dd->reordered = 0; - lxn[i] = cuddUniqueInter(dd, nv, zero, one); - } while (dd->reordered == 1); - if (lxn[i] == NULL) return(0); - cuddRef(lxn[i]); - } - for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) { - do { - dd->reordered = 0; - ly[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (ly[i] == NULL) return(0); - cuddRef(ly[i]); - do { - dd->reordered = 0; - lyn[i] = cuddUniqueInter(dd, nv, zero, one); - } while (dd->reordered == 1); - if (lyn[i] == NULL) return(0); - cuddRef(lyn[i]); - } - *nx = lnx; - *ny = lny; - - *E = dd->background; /* this call will never cause reordering */ - cuddRef(*E); - - while (! feof(fp)) { - err = fscanf(fp, "%d %d %lf", &u, &v, &val); - if (err == EOF) { - break; - } else if (err != 3) { - return(0); - } else if (u >= *m || v >= *n || u < 0 || v < 0) { - return(0); - } - - minterm1 = one; cuddRef(minterm1); - - /* Build minterm1 corresponding to this arc */ - for (i = lnx - 1; i>=0; i--) { - if (u & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lx[i]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lxn[i]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - minterm1 = w; - u >>= 1; - } - for (i = lny - 1; i>=0; i--) { - if (v & 1) { - w = Cudd_addApply(dd, Cudd_addTimes, minterm1, ly[i]); - } else { - w = Cudd_addApply(dd, Cudd_addTimes, minterm1, lyn[i]); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - minterm1 = w; - v >>= 1; - } - /* Create new constant node if necessary. - ** This call will never cause reordering. - */ - neW = cuddUniqueConst(dd, val); - if (neW == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - cuddRef(neW); - - w = Cudd_addIte(dd, minterm1, neW, *E); - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - Cudd_RecursiveDeref(dd, neW); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - Cudd_RecursiveDeref(dd, neW); - Cudd_RecursiveDeref(dd, *E); - *E = w; - } - return(1); - -} /* end of Cudd_addRead */ - - -/**Function******************************************************************** - - Synopsis [Reads in a graph (without labels) given as a list of arcs.] - - Description [Reads in a graph (without labels) given as an adjacency - matrix. The first line of the input contains the numbers of rows and - columns of the adjacency matrix. The remaining lines contain the arcs - of the graph, one per line. Each arc is described by two integers, - i.e., the row and column number, or the indices of the two endpoints. - Cudd_bddRead produces a BDD that depends on two sets of variables: x - and y. The x variables (x\[0\] ... x\[nx-1\]) encode - the row index and the y variables (y\[0\] ... y\[ny-1\]) encode the - column index. x\[0\] and y\[0\] are the most significant bits in the - indices. - The variables may already exist or may be created by the function. - The index of x\[i\] is bx+i*sx, and the index of y\[i\] is by+i*sy.

            - On input, nx and ny hold the numbers of row and column variables already - in existence. On output, they hold the numbers of row and column - variables actually used by the matrix. When Cudd_bddRead creates the - variable arrays, the index of x\[i\] is bx+i*sx, and the index of - y\[i\] is by+i*sy. When some variables already exist, Cudd_bddRead - expects the indices of the existing x variables to be bx+i*sx, and the - indices of the existing y variables to be by+i*sy.

            - m and n are set to the numbers of rows and columns of the - matrix. Their values on input are immaterial. The BDD for the graph - is returned in E, and its reference count is > 0. Cudd_bddRead returns - 1 in case of success; 0 otherwise.] - - SideEffects [nx and ny are set to the numbers of row and column - variables. m and n are set to the numbers of rows and columns. x and y - are possibly extended to represent the array of row and column - variables.] - - SeeAlso [Cudd_addHarwell Cudd_addRead] - -******************************************************************************/ -int -Cudd_bddRead( - FILE * fp /* input file pointer */, - DdManager * dd /* DD manager */, - DdNode ** E /* characteristic function of the graph */, - DdNode *** x /* array of row variables */, - DdNode *** y /* array of column variables */, - int * nx /* number or row variables */, - int * ny /* number or column variables */, - int * m /* number of rows */, - int * n /* number of columns */, - int bx /* first index of row variables */, - int sx /* step of row variables */, - int by /* first index of column variables */, - int sy /* step of column variables */) -{ - DdNode *one, *zero; - DdNode *w; - DdNode *minterm1; - int u, v, err, i, nv; - int lnx, lny; - DdNode **lx, **ly; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - err = fscanf(fp, "%d %d", &u, &v); - if (err == EOF) { - return(0); - } else if (err != 2) { - return(0); - } - - *m = u; - /* Compute the number of x variables. */ - lx = *x; - u--; /* row and column numbers start from 0 */ - for (lnx=0; u > 0; lnx++) { - u >>= 1; - } - if (lnx > *nx) { - *x = lx = REALLOC(DdNode *, *x, lnx); - if (lx == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } - - *n = v; - /* Compute the number of y variables. */ - ly = *y; - v--; /* row and column numbers start from 0 */ - for (lny=0; v > 0; lny++) { - v >>= 1; - } - if (lny > *ny) { - *y = ly = REALLOC(DdNode *, *y, lny); - if (ly == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - } - - /* Create all new variables. */ - for (i = *nx, nv = bx + (*nx) * sx; i < lnx; i++, nv += sx) { - do { - dd->reordered = 0; - lx[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (lx[i] == NULL) return(0); - cuddRef(lx[i]); - } - for (i = *ny, nv = by + (*ny) * sy; i < lny; i++, nv += sy) { - do { - dd->reordered = 0; - ly[i] = cuddUniqueInter(dd, nv, one, zero); - } while (dd->reordered == 1); - if (ly[i] == NULL) return(0); - cuddRef(ly[i]); - } - *nx = lnx; - *ny = lny; - - *E = zero; /* this call will never cause reordering */ - cuddRef(*E); - - while (! feof(fp)) { - err = fscanf(fp, "%d %d", &u, &v); - if (err == EOF) { - break; - } else if (err != 2) { - return(0); - } else if (u >= *m || v >= *n || u < 0 || v < 0) { - return(0); - } - - minterm1 = one; cuddRef(minterm1); - - /* Build minterm1 corresponding to this arc. */ - for (i = lnx - 1; i>=0; i--) { - if (u & 1) { - w = Cudd_bddAnd(dd, minterm1, lx[i]); - } else { - w = Cudd_bddAnd(dd, minterm1, Cudd_Not(lx[i])); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd,minterm1); - minterm1 = w; - u >>= 1; - } - for (i = lny - 1; i>=0; i--) { - if (v & 1) { - w = Cudd_bddAnd(dd, minterm1, ly[i]); - } else { - w = Cudd_bddAnd(dd, minterm1, Cudd_Not(ly[i])); - } - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - minterm1 = w; - v >>= 1; - } - - w = Cudd_bddAnd(dd, Cudd_Not(minterm1), Cudd_Not(*E)); - if (w == NULL) { - Cudd_RecursiveDeref(dd, minterm1); - return(0); - } - w = Cudd_Not(w); - cuddRef(w); - Cudd_RecursiveDeref(dd, minterm1); - Cudd_RecursiveDeref(dd, *E); - *E = w; - } - return(1); - -} /* end of Cudd_bddRead */ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddRef.c b/src/bdd/cudd/cuddRef.c deleted file mode 100644 index a9241f3d..00000000 --- a/src/bdd/cudd/cuddRef.c +++ /dev/null @@ -1,781 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddRef.c] - - PackageName [cudd] - - Synopsis [Functions that manipulate the reference counts.] - - Description [External procedures included in this module: -

              -
            • Cudd_Ref() -
            • Cudd_RecursiveDeref() -
            • Cudd_IterDerefBdd() -
            • Cudd_DelayedDerefBdd() -
            • Cudd_RecursiveDerefZdd() -
            • Cudd_Deref() -
            • Cudd_CheckZeroRef() -
            - Internal procedures included in this module: -
              -
            • cuddReclaim() -
            • cuddReclaimZdd() -
            • cuddClearDeathRow() -
            • cuddShrinkDeathRow() -
            • cuddIsInDeathRow() -
            • cuddTimesInDeathRow() -
            - ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddRef.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Increases the reference count of a node, if it is not - saturated.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_RecursiveDeref Cudd_Deref] - -******************************************************************************/ -void -Cudd_Ref( - DdNode * n) -{ - - n = Cudd_Regular(n); - - cuddSatInc(n->ref); - -} /* end of Cudd_Ref */ - - -/**Function******************************************************************** - - Synopsis [Decreases the reference count of node n.] - - Description [Decreases the reference count of node n. If n dies, - recursively decreases the reference counts of its children. It is - used to dispose of a DD that is no longer needed.] - - SideEffects [None] - - SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDerefZdd] - -******************************************************************************/ -void -Cudd_RecursiveDeref( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack = table->stack; - int SP = 1; - - unsigned int live = table->keys - table->dead; - if (live > table->peakLiveNodes) { - table->peakLiveNodes = live; - } - - N = Cudd_Regular(n); - - do { -#ifdef DD_DEBUG - assert(N->ref != 0); -#endif - - if (N->ref == 1) { - N->ref = 0; - table->dead++; -#ifdef DD_STATS - table->nodesDropped++; -#endif - if (cuddIsConstant(N)) { - table->constants.dead++; - N = stack[--SP]; - } else { - ord = table->perm[N->index]; - stack[SP++] = Cudd_Regular(cuddE(N)); - table->subtables[ord].dead++; - N = cuddT(N); - } - } else { - cuddSatDec(N->ref); - N = stack[--SP]; - } - } while (SP != 0); - -} /* end of Cudd_RecursiveDeref */ - - -/**Function******************************************************************** - - Synopsis [Decreases the reference count of BDD node n.] - - Description [Decreases the reference count of node n. If n dies, - recursively decreases the reference counts of its children. It is - used to dispose of a BDD that is no longer needed. It is more - efficient than Cudd_RecursiveDeref, but it cannot be used on - ADDs. The greater efficiency comes from being able to assume that no - constant node will ever die as a result of a call to this - procedure.] - - SideEffects [None] - - SeeAlso [Cudd_RecursiveDeref Cudd_DelayedDerefBdd] - -******************************************************************************/ -void -Cudd_IterDerefBdd( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack = table->stack; - int SP = 1; - - unsigned int live = table->keys - table->dead; - if (live > table->peakLiveNodes) { - table->peakLiveNodes = live; - } - - N = Cudd_Regular(n); - - do { -#ifdef DD_DEBUG - assert(N->ref != 0); -#endif - - if (N->ref == 1) { - N->ref = 0; - table->dead++; -#ifdef DD_STATS - table->nodesDropped++; -#endif - ord = table->perm[N->index]; - stack[SP++] = Cudd_Regular(cuddE(N)); - table->subtables[ord].dead++; - N = cuddT(N); - } else { - cuddSatDec(N->ref); - N = stack[--SP]; - } - } while (SP != 0); - -} /* end of Cudd_IterDerefBdd */ - - -/**Function******************************************************************** - - Synopsis [Decreases the reference count of BDD node n.] - - Description [Enqueues node n for later dereferencing. If the queue - is full decreases the reference count of the oldest node N to make - room for n. If N dies, recursively decreases the reference counts of - its children. It is used to dispose of a BDD that is currently not - needed, but may be useful again in the near future. The dereferencing - proper is done as in Cudd_IterDerefBdd.] - - SideEffects [None] - - SeeAlso [Cudd_RecursiveDeref Cudd_IterDerefBdd] - -******************************************************************************/ -void -Cudd_DelayedDerefBdd( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack; - int SP; - - unsigned int live = table->keys - table->dead; - if (live > table->peakLiveNodes) { - table->peakLiveNodes = live; - } - - n = Cudd_Regular(n); -#ifdef DD_DEBUG - assert(n->ref != 0); -#endif - -#ifdef DD_NO_DEATH_ROW - N = n; -#else - if (cuddIsConstant(n) || n->ref > 1) { -#ifdef DD_DEBUG - assert(n->ref != 1 && (!cuddIsConstant(n) || n == DD_ONE(table))); -#endif - cuddSatDec(n->ref); - return; - } - - N = table->deathRow[table->nextDead]; - - if (N != NULL) { -#endif -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(N)); -#endif - stack = table->stack; - SP = 1; - do { -#ifdef DD_DEBUG - assert(N->ref != 0); -#endif - if (N->ref == 1) { - N->ref = 0; - table->dead++; -#ifdef DD_STATS - table->nodesDropped++; -#endif - ord = table->perm[N->index]; - stack[SP++] = Cudd_Regular(cuddE(N)); - table->subtables[ord].dead++; - N = cuddT(N); - } else { - cuddSatDec(N->ref); - N = stack[--SP]; - } - } while (SP != 0); -#ifndef DD_NO_DEATH_ROW - } - table->deathRow[table->nextDead] = n; - - /* Udate insertion point. */ - table->nextDead++; - table->nextDead &= table->deadMask; -#if 0 - if (table->nextDead == table->deathRowDepth) { - if (table->deathRowDepth < table->looseUpTo / 2) { - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long) = MMoutOfMemory; - DdNodePtr *newRow; - MMoutOfMemory = Cudd_OutOfMem; - newRow = REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth); - MMoutOfMemory = saveHandler; - if (newRow == NULL) { - table->nextDead = 0; - } else { - int i; - table->memused += table->deathRowDepth; - i = table->deathRowDepth; - table->deathRowDepth <<= 1; - for (; i < table->deathRowDepth; i++) { - newRow[i] = NULL; - } - table->deadMask = table->deathRowDepth - 1; - table->deathRow = newRow; - } - } else { - table->nextDead = 0; - } - } -#endif -#endif - -} /* end of Cudd_DelayedDerefBdd */ - - -/**Function******************************************************************** - - Synopsis [Decreases the reference count of ZDD node n.] - - Description [Decreases the reference count of ZDD node n. If n dies, - recursively decreases the reference counts of its children. It is - used to dispose of a ZDD that is no longer needed.] - - SideEffects [None] - - SeeAlso [Cudd_Deref Cudd_Ref Cudd_RecursiveDeref] - -******************************************************************************/ -void -Cudd_RecursiveDerefZdd( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack = table->stack; - int SP = 1; - - N = n; - - do { -#ifdef DD_DEBUG - assert(N->ref != 0); -#endif - - cuddSatDec(N->ref); - - if (N->ref == 0) { - table->deadZ++; -#ifdef DD_STATS - table->nodesDropped++; -#endif -#ifdef DD_DEBUG - assert(!cuddIsConstant(N)); -#endif - ord = table->permZ[N->index]; - stack[SP++] = cuddE(N); - table->subtableZ[ord].dead++; - N = cuddT(N); - } else { - N = stack[--SP]; - } - } while (SP != 0); - -} /* end of Cudd_RecursiveDerefZdd */ - - -/**Function******************************************************************** - - Synopsis [Decreases the reference count of node.] - - Description [Decreases the reference count of node. It is primarily - used in recursive procedures to decrease the ref count of a result - node before returning it. This accomplishes the goal of removing the - protection applied by a previous Cudd_Ref.] - - SideEffects [None] - - SeeAlso [Cudd_RecursiveDeref Cudd_RecursiveDerefZdd Cudd_Ref] - -******************************************************************************/ -void -Cudd_Deref( - DdNode * node) -{ - node = Cudd_Regular(node); - cuddSatDec(node->ref); - -} /* end of Cudd_Deref */ - - -/**Function******************************************************************** - - Synopsis [Checks the unique table for nodes with non-zero reference - counts.] - - Description [Checks the unique table for nodes with non-zero - reference counts. It is normally called before Cudd_Quit to make sure - that there are no memory leaks due to missing Cudd_RecursiveDeref's. - Takes into account that reference counts may saturate and that the - basic constants and the projection functions are referenced by the - manager. Returns the number of nodes with non-zero reference count. - (Except for the cases mentioned above.)] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_CheckZeroRef( - DdManager * manager) -{ - int size; - int i, j; - int remain; /* the expected number of remaining references to one */ - DdNodePtr *nodelist; - DdNode *node; - DdNode *sentinel = &(manager->sentinel); - DdSubtable *subtable; - int count = 0; - int index; - -#ifndef DD_NO_DEATH_ROW - cuddClearDeathRow(manager); -#endif - - /* First look at the BDD/ADD subtables. */ - remain = 1; /* reference from the manager */ - size = manager->size; - remain += 2 * size; /* reference from the BDD projection functions */ - - for (i = 0; i < size; i++) { - subtable = &(manager->subtables[i]); - nodelist = subtable->nodelist; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - while (node != sentinel) { - if (node->ref != 0 && node->ref != DD_MAXREF) { - index = (int) node->index; - if (node != manager->vars[index]) { - count++; - } else { - if (node->ref != 1) { - count++; - } - } - } - node = node->next; - } - } - } - - /* Then look at the ZDD subtables. */ - size = manager->sizeZ; - if (size) /* references from ZDD universe */ - remain += 2; - - for (i = 0; i < size; i++) { - subtable = &(manager->subtableZ[i]); - nodelist = subtable->nodelist; - for (j = 0; (unsigned) j < subtable->slots; j++) { - node = nodelist[j]; - while (node != NULL) { - if (node->ref != 0 && node->ref != DD_MAXREF) { - index = (int) node->index; - if (node == manager->univ[manager->permZ[index]]) { - if (node->ref > 2) { - count++; - } - } else { - count++; - } - } - node = node->next; - } - } - } - - /* Now examine the constant table. Plusinfinity, minusinfinity, and - ** zero are referenced by the manager. One is referenced by the - ** manager, by the ZDD universe, and by all projection functions. - ** All other nodes should have no references. - */ - nodelist = manager->constants.nodelist; - for (j = 0; (unsigned) j < manager->constants.slots; j++) { - node = nodelist[j]; - while (node != NULL) { - if (node->ref != 0 && node->ref != DD_MAXREF) { - if (node == manager->one) { - if ((int) node->ref != remain) { - count++; - } - } else if (node == manager->zero || - node == manager->plusinfinity || - node == manager->minusinfinity) { - if (node->ref != 1) { - count++; - } - } else { - count++; - } - } - node = node->next; - } - } - return(count); - -} /* end of Cudd_CheckZeroRef */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Brings children of a dead node back.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddReclaimZdd] - -******************************************************************************/ -void -cuddReclaim( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack = table->stack; - int SP = 1; - double initialDead = table->dead; - - N = Cudd_Regular(n); - -#ifdef DD_DEBUG - assert(N->ref == 0); -#endif - - do { - if (N->ref == 0) { - N->ref = 1; - table->dead--; - if (cuddIsConstant(N)) { - table->constants.dead--; - N = stack[--SP]; - } else { - ord = table->perm[N->index]; - stack[SP++] = Cudd_Regular(cuddE(N)); - table->subtables[ord].dead--; - N = cuddT(N); - } - } else { - cuddSatInc(N->ref); - N = stack[--SP]; - } - } while (SP != 0); - - N = Cudd_Regular(n); - cuddSatDec(N->ref); - table->reclaimed += initialDead - table->dead; - -} /* end of cuddReclaim */ - - -/**Function******************************************************************** - - Synopsis [Brings children of a dead ZDD node back.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddReclaim] - -******************************************************************************/ -void -cuddReclaimZdd( - DdManager * table, - DdNode * n) -{ - DdNode *N; - int ord; - DdNodePtr *stack = table->stack; - int SP = 1; - - N = n; - -#ifdef DD_DEBUG - assert(N->ref == 0); -#endif - - do { - cuddSatInc(N->ref); - - if (N->ref == 1) { - table->deadZ--; - table->reclaimed++; -#ifdef DD_DEBUG - assert(!cuddIsConstant(N)); -#endif - ord = table->permZ[N->index]; - stack[SP++] = cuddE(N); - table->subtableZ[ord].dead--; - N = cuddT(N); - } else { - N = stack[--SP]; - } - } while (SP != 0); - - cuddSatDec(n->ref); - -} /* end of cuddReclaimZdd */ - - -/**Function******************************************************************** - - Synopsis [Shrinks the death row.] - - Description [Shrinks the death row by a factor of four.] - - SideEffects [None] - - SeeAlso [cuddClearDeathRow] - -******************************************************************************/ -void -cuddShrinkDeathRow( - DdManager *table) -{ -#ifndef DD_NO_DEATH_ROW - int i; - - if (table->deathRowDepth > 3) { - for (i = table->deathRowDepth/4; i < table->deathRowDepth; i++) { - if (table->deathRow[i] == NULL) break; - Cudd_IterDerefBdd(table,table->deathRow[i]); - table->deathRow[i] = NULL; - } - table->deathRowDepth /= 4; - table->deadMask = table->deathRowDepth - 2; - if ((unsigned) table->nextDead > table->deadMask) { - table->nextDead = 0; - } - table->deathRow = REALLOC(DdNodePtr, table->deathRow, - table->deathRowDepth); - } -#endif - -} /* end of cuddShrinkDeathRow */ - - -/**Function******************************************************************** - - Synopsis [Clears the death row.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_DelayedDerefBdd Cudd_IterDerefBdd Cudd_CheckZeroRef - cuddGarbageCollect] - -******************************************************************************/ -void -cuddClearDeathRow( - DdManager *table) -{ -#ifndef DD_NO_DEATH_ROW - int i; - - for (i = 0; i < table->deathRowDepth; i++) { - if (table->deathRow[i] == NULL) break; - Cudd_IterDerefBdd(table,table->deathRow[i]); - table->deathRow[i] = NULL; - } -#ifdef DD_DEBUG - for (; i < table->deathRowDepth; i++) { - assert(table->deathRow[i] == NULL); - } -#endif - table->nextDead = 0; -#endif - -} /* end of cuddClearDeathRow */ - - -/**Function******************************************************************** - - Synopsis [Checks whether a node is in the death row.] - - Description [Checks whether a node is in the death row. Returns the - position of the first occurrence if the node is present; -1 - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow] - -******************************************************************************/ -int -cuddIsInDeathRow( - DdManager *dd, - DdNode *f) -{ -#ifndef DD_NO_DEATH_ROW - int i; - - for (i = 0; i < dd->deathRowDepth; i++) { - if (f == dd->deathRow[i]) { - return(i); - } - } -#endif - - return(-1); - -} /* end of cuddIsInDeathRow */ - - -/**Function******************************************************************** - - Synopsis [Counts how many times a node is in the death row.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_DelayedDerefBdd cuddClearDeathRow cuddIsInDeathRow] - -******************************************************************************/ -int -cuddTimesInDeathRow( - DdManager *dd, - DdNode *f) -{ - int count = 0; -#ifndef DD_NO_DEATH_ROW - int i; - - for (i = 0; i < dd->deathRowDepth; i++) { - count += f == dd->deathRow[i]; - } -#endif - - return(count); - -} /* end of cuddTimesInDeathRow */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ diff --git a/src/bdd/cudd/cuddReorder.c b/src/bdd/cudd/cuddReorder.c deleted file mode 100644 index 1387196f..00000000 --- a/src/bdd/cudd/cuddReorder.c +++ /dev/null @@ -1,2090 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddReorder.c] - - PackageName [cudd] - - Synopsis [Functions for dynamic variable reordering.] - - Description [External procedures included in this file: -
              -
            • Cudd_ReduceHeap() -
            • Cudd_ShuffleHeap() -
            - Internal procedures included in this module: -
              -
            • cuddDynamicAllocNode() -
            • cuddSifting() -
            • cuddSwapping() -
            • cuddNextHigh() -
            • cuddNextLow() -
            • cuddSwapInPlace() -
            • cuddBddAlignToZdd() -
            - Static procedures included in this module: -
              -
            • ddUniqueCompare() -
            • ddSwapAny() -
            • ddSiftingAux() -
            • ddSiftingUp() -
            • ddSiftingDown() -
            • ddSiftingBackward() -
            • ddReorderPreprocess() -
            • ddReorderPostprocess() -
            • ddShuffle() -
            • ddSiftUp() -
            • bddFixTree() -
            ] - - Author [Shipra Panda, Bernard Plessier, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_MAX_SUBTABLE_SPARSITY 8 -#define DD_SHRINK_FACTOR 2 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static int *entry; - -int ddTotalNumberSwapping; -#ifdef DD_STATS -int ddTotalNISwaps; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddUniqueCompare ARGS((int *ptrX, int *ptrY)); -static Move * ddSwapAny ARGS((DdManager *table, int x, int y)); -static int ddSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static Move * ddSiftingUp ARGS((DdManager *table, int y, int xLow)); -static Move * ddSiftingDown ARGS((DdManager *table, int x, int xHigh)); -static int ddSiftingBackward ARGS((DdManager *table, int size, Move *moves)); -static int ddReorderPreprocess ARGS((DdManager *table)); -static int ddReorderPostprocess ARGS((DdManager *table)); -static int ddShuffle ARGS((DdManager *table, int *permutation)); -static int ddSiftUp ARGS((DdManager *table, int x, int xLow)); -static void bddFixTree ARGS((DdManager *table, MtrNode *treenode)); -static int ddUpdateMtrTree ARGS((DdManager *table, MtrNode *treenode, int *perm, int *invperm)); -static int ddCheckPermuation ARGS((DdManager *table, MtrNode *treenode, int *perm, int *invperm)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Main dynamic reordering routine.] - - Description [Main dynamic reordering routine. - Calls one of the possible reordering procedures: -
              -
            • Swapping -
            • Sifting -
            • Symmetric Sifting -
            • Group Sifting -
            • Window Permutation -
            • Simulated Annealing -
            • Genetic Algorithm -
            • Dynamic Programming (exact) -
            - - For sifting, symmetric sifting, group sifting, and window - permutation it is possible to request reordering to convergence.

            - - The core of all methods is the reordering procedure - cuddSwapInPlace() which swaps two adjacent variables and is based - on Rudell's paper. - Returns 1 in case of success; 0 otherwise. In the case of symmetric - sifting (with and without convergence) returns 1 plus the number of - symmetric variables, in case of success.] - - SideEffects [Changes the variable order for all diagrams and clears - the cache.] - -******************************************************************************/ -int -Cudd_ReduceHeap( - DdManager * table /* DD manager */, - Cudd_ReorderingType heuristic /* method used for reordering */, - int minsize /* bound below which no reordering occurs */) -{ - DdHook *hook; - int result; - unsigned int nextDyn; -#ifdef DD_STATS - unsigned int initialSize; - unsigned int finalSize; -#endif - long localTime; - - /* Don't reorder if there are too many dead nodes. */ - if (table->keys - table->dead < (unsigned) minsize) - return(1); - - if (heuristic == CUDD_REORDER_SAME) { - heuristic = table->autoMethod; - } - if (heuristic == CUDD_REORDER_NONE) { - return(1); - } - - /* This call to Cudd_ReduceHeap does initiate reordering. Therefore - ** we count it. - */ - table->reorderings++; - - localTime = util_cpu_time(); - - /* Run the hook functions. */ - hook = table->preReorderingHook; - while (hook != NULL) { - int res = (hook->f)(table, "BDD", (void *)heuristic); - if (res == 0) return(0); - hook = hook->next; - } - - if (!ddReorderPreprocess(table)) return(0); - ddTotalNumberSwapping = 0; - - if (table->keys > table->peakLiveNodes) { - table->peakLiveNodes = table->keys; - } -#ifdef DD_STATS - initialSize = table->keys - table->isolated; - ddTotalNISwaps = 0; - - switch(heuristic) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - (void) fprintf(table->out,"#:I_RANDOM "); - break; - case CUDD_REORDER_SIFT: - case CUDD_REORDER_SIFT_CONVERGE: - case CUDD_REORDER_SYMM_SIFT: - case CUDD_REORDER_SYMM_SIFT_CONV: - case CUDD_REORDER_GROUP_SIFT: - case CUDD_REORDER_GROUP_SIFT_CONV: - (void) fprintf(table->out,"#:I_SIFTING "); - break; - case CUDD_REORDER_WINDOW2: - case CUDD_REORDER_WINDOW3: - case CUDD_REORDER_WINDOW4: - case CUDD_REORDER_WINDOW2_CONV: - case CUDD_REORDER_WINDOW3_CONV: - case CUDD_REORDER_WINDOW4_CONV: - (void) fprintf(table->out,"#:I_WINDOW "); - break; - case CUDD_REORDER_ANNEALING: - (void) fprintf(table->out,"#:I_ANNEAL "); - break; - case CUDD_REORDER_GENETIC: - (void) fprintf(table->out,"#:I_GENETIC "); - break; - case CUDD_REORDER_LINEAR: - case CUDD_REORDER_LINEAR_CONVERGE: - (void) fprintf(table->out,"#:I_LINSIFT "); - break; - case CUDD_REORDER_EXACT: - (void) fprintf(table->out,"#:I_EXACT "); - break; - default: - return(0); - } - (void) fprintf(table->out,"%8d: initial size",initialSize); -#endif - - /* See if we should use alternate threshold for maximum growth. */ - if (table->reordCycle && table->reorderings % table->reordCycle == 0) { - double saveGrowth = table->maxGrowth; - table->maxGrowth = table->maxGrowthAlt; - result = cuddTreeSifting(table,heuristic); - table->maxGrowth = saveGrowth; - } else { - result = cuddTreeSifting(table,heuristic); - } - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - finalSize = table->keys - table->isolated; - (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); - (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", - ((double)(util_cpu_time() - localTime)/1000.0)); - (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", - ddTotalNumberSwapping); - (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps); -#endif - - if (result == 0) - return(0); - - if (!ddReorderPostprocess(table)) - return(0); - - if (table->realign) { - if (!cuddZddAlignToBdd(table)) - return(0); - } - - nextDyn = (table->keys - table->constants.keys + 1) * - DD_DYN_RATIO + table->constants.keys; - if (table->reorderings < 20 || nextDyn > table->nextDyn) - table->nextDyn = nextDyn; - else - table->nextDyn += 20; - table->reordered = 1; - - /* Run hook functions. */ - hook = table->postReorderingHook; - while (hook != NULL) { - int res = (hook->f)(table, "BDD", (void *)localTime); - if (res == 0) return(0); - hook = hook->next; - } - /* Update cumulative reordering time. */ - table->reordTime += util_cpu_time() - localTime; - - return(result); - -} /* end of Cudd_ReduceHeap */ - - -/**Function******************************************************************** - - Synopsis [Reorders variables according to given permutation.] - - Description [Reorders variables according to given permutation. - The i-th entry of the permutation array contains the index of the variable - that should be brought to the i-th level. The size of the array should be - equal or greater to the number of variables currently in use. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [Changes the variable order for all diagrams and clears - the cache.] - - SeeAlso [Cudd_ReduceHeap] - -******************************************************************************/ -int -Cudd_ShuffleHeap( - DdManager * table /* DD manager */, - int * permutation /* required variable permutation */) -{ - - int result; - int i; - int identity = 1; - int *perm; - - /* Don't waste time in case of identity permutation. */ - for (i = 0; i < table->size; i++) { - if (permutation[i] != table->invperm[i]) { - identity = 0; - break; - } - } - if (identity == 1) { - return(1); - } - if (!ddReorderPreprocess(table)) return(0); - if (table->keys > table->peakLiveNodes) { - table->peakLiveNodes = table->keys; - } - - perm = ALLOC(int, table->size); - for (i = 0; i < table->size; i++) - perm[permutation[i]] = i; - if (!ddCheckPermuation(table,table->tree,perm,permutation)) { - FREE(perm); - return(0); - } - if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) { - FREE(perm); - return(0); - } - FREE(perm); - - result = ddShuffle(table,permutation); - - if (!ddReorderPostprocess(table)) return(0); - - return(result); - -} /* end of Cudd_ShuffleHeap */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Dynamically allocates a Node.] - - Description [Dynamically allocates a Node. This procedure is similar - to cuddAllocNode in Cudd_Table.c, but it does not attempt garbage - collection, because during reordering there are no dead nodes. - Returns a pointer to a new node if successful; NULL is memory is - full.] - - SideEffects [None] - - SeeAlso [cuddAllocNode] - -******************************************************************************/ -DdNode * -cuddDynamicAllocNode( - DdManager * table) -{ - int i; - DdNodePtr *mem; - DdNode *list, *node; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - if (table->nextFree == NULL) { /* free list is empty */ - /* Try to allocate a new block. */ - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1); - MMoutOfMemory = saveHandler; - if (mem == NULL && table->stash != NULL) { - FREE(table->stash); - table->stash = NULL; - /* Inhibit resizing of tables. */ - table->maxCacheHard = table->cacheSlots - 1; - table->cacheSlack = -(table->cacheSlots + 1); - for (i = 0; i < table->size; i++) { - table->subtables[i].maxKeys <<= 2; - } - mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); - } - if (mem == NULL) { - /* Out of luck. Call the default handler to do - ** whatever it specifies for a failed malloc. If this - ** handler returns, then set error code, print - ** warning, and return. */ - (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); - table->errorCode = CUDD_MEMORY_OUT; -#ifdef DD_VERBOSE - (void) fprintf(table->err, - "cuddDynamicAllocNode: out of memory"); - (void) fprintf(table->err,"Memory in use = %ld\n", - table->memused); -#endif - return(NULL); - } else { /* successful allocation; slice memory */ - unsigned long offset; - table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); - mem[0] = (DdNode *) table->memoryList; - table->memoryList = mem; - - /* Here we rely on the fact that the size of a DdNode is a - ** power of 2 and a multiple of the size of a pointer. - ** If we align one node, all the others will be aligned - ** as well. */ - offset = (unsigned long) mem & (sizeof(DdNode) - 1); - mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); -#ifdef DD_DEBUG - assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0); -#endif - list = (DdNode *) mem; - - i = 1; - do { - list[i - 1].next = &list[i]; - } while (++i < DD_MEM_CHUNK); - - list[DD_MEM_CHUNK - 1].next = NULL; - - table->nextFree = &list[0]; - } - } /* if free list empty */ - - node = table->nextFree; - table->nextFree = node->next; - return (node); - -} /* end of cuddDynamicAllocNode */ - - -/**Function******************************************************************** - - Synopsis [Implementation of Rudell's sifting algorithm.] - - Description [Implementation of Rudell's sifting algorithm. - Assumes that no dead nodes are present. -

              -
            1. Order all the variables according to the number of entries - in each unique table. -
            2. Sift the variable up and down, remembering each time the - total size of the DD heap. -
            3. Select the best permutation. -
            4. Repeat 3 and 4 for all variables. -
            - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; -#ifdef DD_STATS - int previousSize; -#endif - - size = table->size; - - /* Find order in which to sift variables. */ - var = NULL; - entry = ALLOC(int,size); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddSiftingOutOfMem; - } - var = ALLOC(int,size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddSiftingOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->perm[i]; - entry[i] = table->subtables[x].keys; - var[i] = i; - } - - qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddUniqueCompare); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->perm[var[i]]; - - if (x < lower || x > upper || table->subtables[x].bindVar == 1) - continue; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddSiftingAux(table, x, lower, upper); - if (!result) goto cuddSiftingOutOfMem; -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"+"); /* should never happen */ - (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - FREE(var); - FREE(entry); - - return(1); - -cuddSiftingOutOfMem: - - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddSifting */ - - -/**Function******************************************************************** - - Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.] - - Description [Implementation of Plessier's algorithm that reorders - variables by a sequence of (non-adjacent) swaps. -
              -
            1. Select two variables (RANDOM or HEURISTIC). -
            2. Permute these variables. -
            3. If the nodes have decreased accept the permutation. -
            4. Otherwise reconstruct the original heap. -
            5. Loop. -
            - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddSwapping( - DdManager * table, - int lower, - int upper, - Cudd_ReorderingType heuristic) -{ - int i, j; - int max, keys; - int nvars; - int x, y; - int iterate; - int previousSize; - Move *moves, *move; - int pivot; - int modulo; - int result; - -#ifdef DD_DEBUG - /* Sanity check */ - assert(lower >= 0 && upper < table->size && lower <= upper); -#endif - - nvars = upper - lower + 1; - iterate = nvars; - - for (i = 0; i < iterate; i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { - max = -1; - for (j = lower; j <= upper; j++) { - if ((keys = table->subtables[j].keys) > max) { - max = keys; - pivot = j; - } - } - - modulo = upper - pivot; - if (modulo == 0) { - y = pivot; - } else{ - y = pivot + 1 + ((int) Cudd_Random() % modulo); - } - - modulo = pivot - lower - 1; - if (modulo < 1) { - x = lower; - } else{ - do { - x = (int) Cudd_Random() % modulo; - } while (x == y); - } - } else { - x = ((int) Cudd_Random() % nvars) + lower; - do { - y = ((int) Cudd_Random() % nvars) + lower; - } while (x == y); - } - previousSize = table->keys - table->isolated; - moves = ddSwapAny(table,x,y); - if (moves == NULL) goto cuddSwappingOutOfMem; - result = ddSiftingBackward(table,previousSize,moves); - if (!result) goto cuddSwappingOutOfMem; - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif -#if 0 - (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n", - table->keys - table->isolated); -#endif - } - - return(1); - -cuddSwappingOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(0); - -} /* end of cuddSwapping */ - - -/**Function******************************************************************** - - Synopsis [Finds the next subtable with a larger index.] - - Description [Finds the next subtable with a larger index. Returns the - index.] - - SideEffects [None] - - SeeAlso [cuddNextLow] - -******************************************************************************/ -int -cuddNextHigh( - DdManager * table, - int x) -{ - return(x+1); - -} /* end of cuddNextHigh */ - - -/**Function******************************************************************** - - Synopsis [Finds the next subtable with a smaller index.] - - Description [Finds the next subtable with a smaller index. Returns the - index.] - - SideEffects [None] - - SeeAlso [cuddNextHigh] - -******************************************************************************/ -int -cuddNextLow( - DdManager * table, - int x) -{ - return(x-1); - -} /* end of cuddNextLow */ - - -/**Function******************************************************************** - - Synopsis [Swaps two adjacent variables.] - - Description [Swaps two adjacent variables. It assumes that no dead - nodes are present on entry to this procedure. The procedure then - guarantees that no dead nodes will be present when it terminates. - cuddSwapInPlace assumes that x < y. Returns the number of keys in - the table if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddSwapInPlace( - DdManager * table, - int x, - int y) -{ - DdNodePtr *xlist, *ylist; - int xindex, yindex; - int xslots, yslots; - int xshift, yshift; - int oldxkeys, oldykeys; - int newxkeys, newykeys; - int comple, newcomplement; - int i; - Cudd_VariableType varType; - Cudd_LazyGroupType groupType; - int posn; - int isolated; - DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0; - DdNode *g,*next; - DdNodePtr *previousP; - DdNode *tmp; - DdNode *sentinel = &(table->sentinel); - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - -#if DD_DEBUG - int count,idcheck; -#endif - -#ifdef DD_DEBUG - assert(x < y); - assert(cuddNextHigh(table,x) == y); - assert(table->subtables[x].keys != 0); - assert(table->subtables[y].keys != 0); - assert(table->subtables[x].dead == 0); - assert(table->subtables[y].dead == 0); -#endif - - ddTotalNumberSwapping++; - - /* Get parameters of x subtable. */ - xindex = table->invperm[x]; - xlist = table->subtables[x].nodelist; - oldxkeys = table->subtables[x].keys; - xslots = table->subtables[x].slots; - xshift = table->subtables[x].shift; - - /* Get parameters of y subtable. */ - yindex = table->invperm[y]; - ylist = table->subtables[y].nodelist; - oldykeys = table->subtables[y].keys; - yslots = table->subtables[y].slots; - yshift = table->subtables[y].shift; - - if (!cuddTestInteract(table,xindex,yindex)) { -#ifdef DD_STATS - ddTotalNISwaps++; -#endif - newxkeys = oldxkeys; - newykeys = oldykeys; - } else { - newxkeys = 0; - newykeys = oldykeys; - - /* Check whether the two projection functions involved in this - ** swap are isolated. At the end, we'll be able to tell how many - ** isolated projection functions are there by checking only these - ** two functions again. This is done to eliminate the isolated - ** projection functions from the node count. - */ - isolated = - ((table->vars[xindex]->ref == 1) + - (table->vars[yindex]->ref == 1)); - - /* The nodes in the x layer that do not depend on - ** y will stay there; the others are put in a chain. - ** The chain is handled as a LIFO; g points to the beginning. - */ - g = NULL; - if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) && - oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) { - for (i = 0; i < xslots; i++) { - previousP = &(xlist[i]); - f = *previousP; - while (f != sentinel) { - next = f->next; - f1 = cuddT(f); f0 = cuddE(f); - if (f1->index != (DdHalfWord) yindex && - Cudd_Regular(f0)->index != (DdHalfWord) yindex) { - /* stays */ - newxkeys++; - *previousP = f; - previousP = &(f->next); - } else { - f->index = yindex; - f->next = g; - g = f; - } - f = next; - } /* while there are elements in the collision chain */ - *previousP = sentinel; - } /* for each slot of the x subtable */ - } else { /* resize xlist */ - DdNode *h = NULL; - DdNodePtr *newxlist; - unsigned int newxslots; - int newxshift; - /* Empty current xlist. Nodes that stay go to list h; - ** nodes that move go to list g. */ - for (i = 0; i < xslots; i++) { - f = xlist[i]; - while (f != sentinel) { - next = f->next; - f1 = cuddT(f); f0 = cuddE(f); - if (f1->index != (DdHalfWord) yindex && - Cudd_Regular(f0)->index != (DdHalfWord) yindex) { - /* stays */ - f->next = h; - h = f; - newxkeys++; - } else { - f->index = yindex; - f->next = g; - g = f; - } - f = next; - } /* while there are elements in the collision chain */ - } /* for each slot of the x subtable */ - /* Decide size of new subtable. */ - if (oldxkeys > DD_MAX_SUBTABLE_DENSITY * xslots) { - newxshift = xshift - 1; - newxslots = xslots << 1; - } else { - newxshift = xshift + 1; - newxslots = xslots >> 1; - } - /* Try to allocate new table. Be ready to back off. */ - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - newxlist = ALLOC(DdNodePtr, newxslots); - MMoutOfMemory = saveHandler; - if (newxlist == NULL) { - (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i); - newxlist = xlist; - newxslots = xslots; - newxshift = xshift; - } else { - table->slots += (newxslots - xslots); - table->minDead = (unsigned) - (table->gcFrac * (double) table->slots); - table->cacheSlack = (int) - ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO - * table->slots) - 2 * (int) table->cacheSlots; - table->memused += (newxslots - xslots) * sizeof(DdNodePtr); - FREE(xlist); - xslots = newxslots; - xshift = newxshift; - xlist = newxlist; - } - /* Initialize new subtable. */ - for (i = 0; i < xslots; i++) { - xlist[i] = sentinel; - } - /* Move nodes that were parked in list h to their new home. */ - f = h; - while (f != NULL) { - next = f->next; - f1 = cuddT(f); - f0 = cuddE(f); - /* Check xlist for pair (f11,f01). */ - posn = ddHash(f1, f0, xshift); - /* For each element tmp in collision list xlist[posn]. */ - previousP = &(xlist[posn]); - tmp = *previousP; - while (f1 < cuddT(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - f->next = *previousP; - *previousP = f; - f = next; - } - } - -#ifdef DD_COUNT - table->swapSteps += oldxkeys - newxkeys; -#endif - /* Take care of the x nodes that must be re-expressed. - ** They form a linked list pointed by g. Their index has been - ** already changed to yindex. - */ - f = g; - while (f != NULL) { - next = f->next; - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(f1))); -#endif - if ((int) f1->index == yindex) { - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - f11 = f10 = f1; - } -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(f11))); -#endif - f0 = cuddE(f); - comple = Cudd_IsComplement(f0); - f0 = Cudd_Regular(f0); - if ((int) f0->index == yindex) { - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = f00 = f0; - } - if (comple) { - f01 = Cudd_Not(f01); - f00 = Cudd_Not(f00); - } - /* Decrease ref count of f1. */ - cuddSatDec(f1->ref); - /* Create the new T child. */ - if (f11 == f01) { - newf1 = f11; - cuddSatInc(newf1->ref); - } else { - /* Check xlist for triple (xindex,f11,f01). */ - posn = ddHash(f11, f01, xshift); - /* For each element newf1 in collision list xlist[posn]. */ - previousP = &(xlist[posn]); - newf1 = *previousP; - while (f11 < cuddT(newf1)) { - previousP = &(newf1->next); - newf1 = *previousP; - } - while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) { - previousP = &(newf1->next); - newf1 = *previousP; - } - if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { - cuddSatInc(newf1->ref); - } else { /* no match */ - newf1 = cuddDynamicAllocNode(table); - if (newf1 == NULL) - goto cuddSwapOutOfMem; - newf1->index = xindex; newf1->ref = 1; - cuddT(newf1) = f11; - cuddE(newf1) = f01; - /* Insert newf1 in the collision list xlist[posn]; - ** increase the ref counts of f11 and f01. - */ - newxkeys++; - newf1->next = *previousP; - *previousP = newf1; - cuddSatInc(f11->ref); - tmp = Cudd_Regular(f01); - cuddSatInc(tmp->ref); - } - } - cuddT(f) = newf1; -#ifdef DD_DEBUG - assert(!(Cudd_IsComplement(newf1))); -#endif - - /* Do the same for f0, keeping complement dots into account. */ - /* Decrease ref count of f0. */ - tmp = Cudd_Regular(f0); - cuddSatDec(tmp->ref); - /* Create the new E child. */ - if (f10 == f00) { - newf0 = f00; - tmp = Cudd_Regular(newf0); - cuddSatInc(tmp->ref); - } else { - /* make sure f10 is regular */ - newcomplement = Cudd_IsComplement(f10); - if (newcomplement) { - f10 = Cudd_Not(f10); - f00 = Cudd_Not(f00); - } - /* Check xlist for triple (xindex,f10,f00). */ - posn = ddHash(f10, f00, xshift); - /* For each element newf0 in collision list xlist[posn]. */ - previousP = &(xlist[posn]); - newf0 = *previousP; - while (f10 < cuddT(newf0)) { - previousP = &(newf0->next); - newf0 = *previousP; - } - while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) { - previousP = &(newf0->next); - newf0 = *previousP; - } - if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { - cuddSatInc(newf0->ref); - } else { /* no match */ - newf0 = cuddDynamicAllocNode(table); - if (newf0 == NULL) - goto cuddSwapOutOfMem; - newf0->index = xindex; newf0->ref = 1; - cuddT(newf0) = f10; - cuddE(newf0) = f00; - /* Insert newf0 in the collision list xlist[posn]; - ** increase the ref counts of f10 and f00. - */ - newxkeys++; - newf0->next = *previousP; - *previousP = newf0; - cuddSatInc(f10->ref); - tmp = Cudd_Regular(f00); - cuddSatInc(tmp->ref); - } - if (newcomplement) { - newf0 = Cudd_Not(newf0); - } - } - cuddE(f) = newf0; - - /* Insert the modified f in ylist. - ** The modified f does not already exists in ylist. - ** (Because of the uniqueness of the cofactors.) - */ - posn = ddHash(newf1, newf0, yshift); - newykeys++; - previousP = &(ylist[posn]); - tmp = *previousP; - while (newf1 < cuddT(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) { - previousP = &(tmp->next); - tmp = *previousP; - } - f->next = *previousP; - *previousP = f; - f = next; - } /* while f != NULL */ - - /* GC the y layer. */ - - /* For each node f in ylist. */ - for (i = 0; i < yslots; i++) { - previousP = &(ylist[i]); - f = *previousP; - while (f != sentinel) { - next = f->next; - if (f->ref == 0) { - tmp = cuddT(f); - cuddSatDec(tmp->ref); - tmp = Cudd_Regular(cuddE(f)); - cuddSatDec(tmp->ref); - cuddDeallocNode(table,f); - newykeys--; - } else { - *previousP = f; - previousP = &(f->next); - } - f = next; - } /* while f */ - *previousP = sentinel; - } /* for i */ - -#if DD_DEBUG -#if 0 - (void) fprintf(table->out,"Swapping %d and %d\n",x,y); -#endif - count = 0; - idcheck = 0; - for (i = 0; i < yslots; i++) { - f = ylist[i]; - while (f != sentinel) { - count++; - if (f->index != (DdHalfWord) yindex) - idcheck++; - f = f->next; - } - } - if (count != newykeys) { - (void) fprintf(table->out, - "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n", - oldykeys,newykeys,count); - } - if (idcheck != 0) - (void) fprintf(table->out, - "Error in id's of ylist\twrong id's = %d\n", - idcheck); - count = 0; - idcheck = 0; - for (i = 0; i < xslots; i++) { - f = xlist[i]; - while (f != sentinel) { - count++; - if (f->index != (DdHalfWord) xindex) - idcheck++; - f = f->next; - } - } - if (count != newxkeys) { - (void) fprintf(table->out, - "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n", - oldxkeys,newxkeys,count); - } - if (idcheck != 0) - (void) fprintf(table->out, - "Error in id's of xlist\twrong id's = %d\n", - idcheck); -#endif - - isolated += (table->vars[xindex]->ref == 1) + - (table->vars[yindex]->ref == 1); - table->isolated += isolated; - } - - /* Set the appropriate fields in table. */ - table->subtables[x].nodelist = ylist; - table->subtables[x].slots = yslots; - table->subtables[x].shift = yshift; - table->subtables[x].keys = newykeys; - table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; - i = table->subtables[x].bindVar; - table->subtables[x].bindVar = table->subtables[y].bindVar; - table->subtables[y].bindVar = i; - /* Adjust filds for lazy sifting. */ - varType = table->subtables[x].varType; - table->subtables[x].varType = table->subtables[y].varType; - table->subtables[y].varType = varType; - i = table->subtables[x].pairIndex; - table->subtables[x].pairIndex = table->subtables[y].pairIndex; - table->subtables[y].pairIndex = i; - i = table->subtables[x].varHandled; - table->subtables[x].varHandled = table->subtables[y].varHandled; - table->subtables[y].varHandled = i; - groupType = table->subtables[x].varToBeGrouped; - table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped; - table->subtables[y].varToBeGrouped = groupType; - - table->subtables[y].nodelist = xlist; - table->subtables[y].slots = xslots; - table->subtables[y].shift = xshift; - table->subtables[y].keys = newxkeys; - table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; - - table->perm[xindex] = y; table->perm[yindex] = x; - table->invperm[x] = yindex; table->invperm[y] = xindex; - - table->keys += newxkeys + newykeys - oldxkeys - oldykeys; - - return(table->keys - table->isolated); - -cuddSwapOutOfMem: - (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n"); - - return (0); - -} /* end of cuddSwapInPlace */ - - -/**Function******************************************************************** - - Synopsis [Reorders BDD variables according to the order of the ZDD - variables.] - - Description [Reorders BDD variables according to the order of the - ZDD variables. This function can be called at the end of ZDD - reordering to insure that the order of the BDD variables is - consistent with the order of the ZDD variables. The number of ZDD - variables must be a multiple of the number of BDD variables. Let - M be the ratio of the two numbers. cuddBddAlignToZdd - then considers the ZDD variables from M*i to - (M+1)*i-1 as corresponding to BDD variable - i. This function should be normally called from - Cudd_zddReduceHeap, which clears the cache. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [Changes the BDD variable order for all diagrams and performs - garbage collection of the BDD unique table.] - - SeeAlso [Cudd_ShuffleHeap Cudd_zddReduceHeap] - -******************************************************************************/ -int -cuddBddAlignToZdd( - DdManager * table /* DD manager */) -{ - int *invperm; /* permutation array */ - int M; /* ratio of ZDD variables to BDD variables */ - int i; /* loop index */ - int result; /* return value */ - - /* We assume that a ratio of 0 is OK. */ - if (table->size == 0) - return(1); - - M = table->sizeZ / table->size; - /* Check whether the number of ZDD variables is a multiple of the - ** number of BDD variables. - */ - if (M * table->size != table->sizeZ) - return(0); - /* Create and initialize the inverse permutation array. */ - invperm = ALLOC(int,table->size); - if (invperm == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < table->sizeZ; i += M) { - int indexZ = table->invpermZ[i]; - int index = indexZ / M; - invperm[i / M] = index; - } - /* Eliminate dead nodes. Do not scan the cache again, because we - ** assume that Cudd_zddReduceHeap has already cleared it. - */ - cuddGarbageCollect(table,0); - - /* Initialize number of isolated projection functions. */ - table->isolated = 0; - for (i = 0; i < table->size; i++) { - if (table->vars[i]->ref == 1) table->isolated++; - } - - /* Initialize the interaction matrix. */ - result = cuddInitInteract(table); - if (result == 0) return(0); - - result = ddShuffle(table, invperm); - FREE(invperm); - /* Free interaction matrix. */ - FREE(table->interact); - /* Fix the BDD variable group tree. */ - bddFixTree(table,table->tree); - return(result); - -} /* end of cuddBddAlignToZdd */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the - variables according to the number of keys in the subtables. - Returns the difference in number of keys between the two - variables being compared.] - - SideEffects [None] - -******************************************************************************/ -static int -ddUniqueCompare( - int * ptrX, - int * ptrY) -{ -#if 0 - if (entry[*ptrY] == entry[*ptrX]) { - return((*ptrX) - (*ptrY)); - } -#endif - return(entry[*ptrY] - entry[*ptrX]); - -} /* end of ddUniqueCompare */ - - -/**Function******************************************************************** - - Synopsis [Swaps any two variables.] - - Description [Swaps any two variables. Returns the set of moves.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddSwapAny( - DdManager * table, - int x, - int y) -{ - Move *move, *moves; - int xRef,yRef; - int xNext,yNext; - int size; - int limitSize; - int tmp; - - if (x >y) { - tmp = x; x = y; y = tmp; - } - - xRef = x; yRef = y; - - xNext = cuddNextHigh(table,x); - yNext = cuddNextLow(table,y); - moves = NULL; - limitSize = table->keys - table->isolated; - - for (;;) { - if ( xNext == yNext) { - size = cuddSwapInPlace(table,x,xNext); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = x; - move->y = xNext; - move->size = size; - move->next = moves; - moves = move; - - size = cuddSwapInPlace(table,yNext,y); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = yNext; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - size = cuddSwapInPlace(table,x,xNext); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = x; - move->y = xNext; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; x = y; y = tmp; - - } else if (x == yNext) { - - size = cuddSwapInPlace(table,x,xNext); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = x; - move->y = xNext; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; x = y; y = tmp; - - } else { - size = cuddSwapInPlace(table,x,xNext); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = x; - move->y = xNext; - move->size = size; - move->next = moves; - moves = move; - - size = cuddSwapInPlace(table,yNext,y); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = yNext; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - x = xNext; - y = yNext; - } - - xNext = cuddNextHigh(table,x); - yNext = cuddNextLow(table,y); - if (xNext > yRef) break; - - if ((double) size > table->maxGrowth * (double) limitSize) break; - if (size < limitSize) limitSize = size; - } - if (yNext>=xRef) { - size = cuddSwapInPlace(table,yNext,y); - if (size == 0) goto ddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSwapAnyOutOfMem; - move->x = yNext; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - } - - return(moves); - -ddSwapAnyOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(NULL); - -} /* end of ddSwapAny */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. Finds the best position and does the required changes. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSiftingAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - - Move *move; - Move *moveUp; /* list of up moves */ - Move *moveDown; /* list of down moves */ - int initialSize; - int result; - - initialSize = table->keys - table->isolated; - - moveDown = NULL; - moveUp = NULL; - - if (x == xLow) { - moveDown = ddSiftingDown(table,x,xHigh); - /* At this point x --> xHigh unless bounding occurred. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddSiftingBackward(table,initialSize,moveDown); - if (!result) goto ddSiftingAuxOutOfMem; - - } else if (x == xHigh) { - moveUp = ddSiftingUp(table,x,xLow); - /* At this point x --> xLow unless bounding occurred. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddSiftingBackward(table,initialSize,moveUp); - if (!result) goto ddSiftingAuxOutOfMem; - - } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ - moveDown = ddSiftingDown(table,x,xHigh); - /* At this point x --> xHigh unless bounding occurred. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - if (moveDown != NULL) { - x = moveDown->y; - } - moveUp = ddSiftingUp(table,x,xLow); - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - /* Move backward and stop at best position */ - result = ddSiftingBackward(table,initialSize,moveUp); - if (!result) goto ddSiftingAuxOutOfMem; - - } else { /* must go up first: shorter */ - moveUp = ddSiftingUp(table,x,xLow); - /* At this point x --> xLow unless bounding occurred. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - if (moveUp != NULL) { - x = moveUp->x; - } - moveDown = ddSiftingDown(table,x,xHigh); - if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem; - /* Move backward and stop at best position. */ - result = ddSiftingBackward(table,initialSize,moveDown); - if (!result) goto ddSiftingAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - - return(1); - -ddSiftingAuxOutOfMem: - if (moveDown != (Move *) CUDD_OUT_OF_MEM) { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - } - if (moveUp != (Move *) CUDD_OUT_OF_MEM) { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - } - - return(0); - -} /* end of ddSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable up.] - - Description [Sifts a variable up. Moves y up until either it reaches - the bound (xLow) or the size of the DD heap increases too much. - Returns the set of moves in case of success; NULL if memory is full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddSiftingUp( - DdManager * table, - int y, - int xLow) -{ - Move *moves; - Move *move; - int x; - int size; - int limitSize; - int xindex, yindex; - int isolated; - int L; /* lower bound on DD size */ -#ifdef DD_DEBUG - int checkL; - int z; - int zindex; -#endif - - moves = NULL; - yindex = table->invperm[y]; - - /* Initialize the lower bound. - ** The part of the DD below y will not change. - ** The part of the DD above y that does not interact with y will not - ** change. The rest may vanish in the best case, except for - ** the nodes at level xLow, which will not vanish, regardless. - */ - limitSize = L = table->keys - table->isolated; - for (x = xLow + 1; x < y; x++) { - xindex = table->invperm[x]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L -= table->subtables[x].keys - isolated; - } - } - isolated = table->vars[yindex]->ref == 1; - L -= table->subtables[y].keys - isolated; - - x = cuddNextLow(table,y); - while (x >= xLow && L <= limitSize) { - xindex = table->invperm[x]; -#ifdef DD_DEBUG - checkL = table->keys - table->isolated; - for (z = xLow + 1; z < y; z++) { - zindex = table->invperm[z]; - if (cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - checkL -= table->subtables[z].keys - isolated; - } - } - isolated = table->vars[yindex]->ref == 1; - checkL -= table->subtables[y].keys - isolated; - assert(L == checkL); -#endif - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddSiftingUpOutOfMem; - /* Update the lower bound. */ - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L += table->subtables[y].keys - isolated; - } - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > (double) limitSize * table->maxGrowth) break; - if (size < limitSize) limitSize = size; - y = x; - x = cuddNextLow(table,y); - } - return(moves); - -ddSiftingUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of ddSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable down.] - - Description [Sifts a variable down. Moves x down until either it - reaches the bound (xHigh) or the size of the DD heap increases too - much. Returns the set of moves in case of success; NULL if memory is - full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddSiftingDown( - DdManager * table, - int x, - int xHigh) -{ - Move *moves; - Move *move; - int y; - int size; - int R; /* upper bound on node decrease */ - int limitSize; - int xindex, yindex; - int isolated; -#ifdef DD_DEBUG - int checkR; - int z; - int zindex; -#endif - - moves = NULL; - /* Initialize R */ - xindex = table->invperm[x]; - limitSize = size = table->keys - table->isolated; - R = 0; - for (y = xHigh; y > x; y--) { - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R += table->subtables[y].keys - isolated; - } - } - - y = cuddNextHigh(table,x); - while (y <= xHigh && size - R < limitSize) { -#ifdef DD_DEBUG - checkR = 0; - for (z = xHigh; z > x; z--) { - zindex = table->invperm[z]; - if (cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - checkR += table->subtables[z].keys - isolated; - } - } - assert(R == checkR); -#endif - /* Update upper bound on node decrease. */ - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R -= table->subtables[y].keys - isolated; - } - size = cuddSwapInPlace(table,x,y); - if (size == 0) goto ddSiftingDownOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > (double) limitSize * table->maxGrowth) break; - if (size < limitSize) limitSize = size; - x = y; - y = cuddNextHigh(table,x); - } - return(moves); - -ddSiftingDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of ddSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the DD heap to the position - giving the minimum size.] - - Description [Given a set of moves, returns the DD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSiftingBackward( - DdManager * table, - int size, - Move * moves) -{ - Move *move; - int res; - - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) return(1); - res = cuddSwapInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - - return(1); - -} /* end of ddSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Prepares the DD heap for dynamic reordering.] - - Description [Prepares the DD heap for dynamic reordering. Does - garbage collection, to guarantee that there are no dead nodes; - clears the cache, which is invalidated by dynamic reordering; initializes - the number of isolated projection functions; and initializes the - interaction matrix. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddReorderPreprocess( - DdManager * table) -{ - int i; - int res; - - /* Clear the cache. */ - cuddCacheFlush(table); - cuddLocalCacheClearAll(table); - - /* Eliminate dead nodes. Do not scan the cache again. */ - cuddGarbageCollect(table,0); - - /* Initialize number of isolated projection functions. */ - table->isolated = 0; - for (i = 0; i < table->size; i++) { - if (table->vars[i]->ref == 1) table->isolated++; - } - - /* Initialize the interaction matrix. */ - res = cuddInitInteract(table); - if (res == 0) return(0); - - return(1); - -} /* end of ddReorderPreprocess */ - - -/**Function******************************************************************** - - Synopsis [Cleans up at the end of reordering.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -static int -ddReorderPostprocess( - DdManager * table) -{ - -#ifdef DD_VERBOSE - (void) fflush(table->out); -#endif - - /* Free interaction matrix. */ - FREE(table->interact); - - return(1); - -} /* end of ddReorderPostprocess */ - - -/**Function******************************************************************** - - Synopsis [Reorders variables according to a given permutation.] - - Description [Reorders variables according to a given permutation. - The i-th permutation array contains the index of the variable that - should be brought to the i-th level. ddShuffle assumes that no - dead nodes are present and that the interaction matrix is properly - initialized. The reordering is achieved by a series of upward sifts. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddShuffle( - DdManager * table, - int * permutation) -{ - int index; - int level; - int position; - int numvars; - int result; -#ifdef DD_STATS - long localTime; - int initialSize; - int finalSize; - int previousSize; -#endif - - ddTotalNumberSwapping = 0; -#ifdef DD_STATS - localTime = util_cpu_time(); - initialSize = table->keys - table->isolated; - (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", - initialSize); - ddTotalNISwaps = 0; -#endif - - numvars = table->size; - - for (level = 0; level < numvars; level++) { - index = permutation[level]; - position = table->perm[index]; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddSiftUp(table,position,level); - if (!result) return(0); -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - finalSize = table->keys - table->isolated; - (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); - (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", - ((double)(util_cpu_time() - localTime)/1000.0)); - (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", - ddTotalNumberSwapping); - (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps); -#endif - - return(1); - -} /* end of ddShuffle */ - - -/**Function******************************************************************** - - Synopsis [Moves one variable up.] - - Description [Takes a variable from position x and sifts it up to - position xLow; xLow should be less than or equal to x. - Returns 1 if successful; 0 otherwise] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -ddSiftUp( - DdManager * table, - int x, - int xLow) -{ - int y; - int size; - - y = cuddNextLow(table,x); - while (y >= xLow) { - size = cuddSwapInPlace(table,y,x); - if (size == 0) { - return(0); - } - x = y; - y = cuddNextLow(table,x); - } - return(1); - -} /* end of ddSiftUp */ - - -/**Function******************************************************************** - - Synopsis [Fixes the BDD variable group tree after a shuffle.] - - Description [Fixes the BDD variable group tree after a - shuffle. Assumes that the order of the variables in a terminal node - has not been changed.] - - SideEffects [Changes the BDD variable group tree.] - - SeeAlso [] - -******************************************************************************/ -static void -bddFixTree( - DdManager * table, - MtrNode * treenode) -{ - if (treenode == NULL) return; - treenode->low = ((int) treenode->index < table->size) ? - table->perm[treenode->index] : treenode->index; - if (treenode->child != NULL) { - bddFixTree(table, treenode->child); - } - if (treenode->younger != NULL) - bddFixTree(table, treenode->younger); - if (treenode->parent != NULL && treenode->low < treenode->parent->low) { - treenode->parent->low = treenode->low; - treenode->parent->index = treenode->index; - } - return; - -} /* end of bddFixTree */ - - -/**Function******************************************************************** - - Synopsis [Updates the BDD variable group tree before a shuffle.] - - Description [Updates the BDD variable group tree before a shuffle. - Returns 1 if successful; 0 otherwise.] - - SideEffects [Changes the BDD variable group tree.] - - SeeAlso [] - -******************************************************************************/ -static int -ddUpdateMtrTree( - DdManager * table, - MtrNode * treenode, - int * perm, - int * invperm) -{ - int i, size, index, level; - int minLevel, maxLevel, minIndex; - - if (treenode == NULL) return(1); - - /* i : level */ - for (i = treenode->low; i < treenode->low + treenode->size; i++) { - index = table->invperm[i]; - level = perm[index]; - if (level < minLevel) { - minLevel = level; - minIndex = index; - } - if (level > maxLevel) - maxLevel = level; - } - size = maxLevel - minLevel + 1; - if (size == treenode->size) { - treenode->low = minLevel; - treenode->index = minIndex; - } else - return(0); - - if (treenode->child != NULL) { - if (!ddUpdateMtrTree(table, treenode->child, perm, invperm)) - return(0); - } - if (treenode->younger != NULL) { - if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm)) - return(0); - } - return(1); -} - - -/**Function******************************************************************** - - Synopsis [Checks the BDD variable group tree before a shuffle.] - - Description [Checks the BDD variable group tree before a shuffle. - Returns 1 if successful; 0 otherwise.] - - SideEffects [Changes the BDD variable group tree.] - - SeeAlso [] - -******************************************************************************/ -static int -ddCheckPermuation( - DdManager * table, - MtrNode * treenode, - int * perm, - int * invperm) -{ - int i, size, index, level; - int minLevel, maxLevel; - - if (treenode == NULL) return(1); - - minLevel = table->size; - maxLevel = 0; - /* i : level */ - for (i = treenode->low; i < treenode->low + treenode->size; i++) { - index = table->invperm[i]; - level = perm[index]; - if (level < minLevel) - minLevel = level; - if (level > maxLevel) - maxLevel = level; - } - size = maxLevel - minLevel + 1; - if (size != treenode->size) - return(0); - - if (treenode->child != NULL) { - if (!ddCheckPermuation(table, treenode->child, perm, invperm)) - return(0); - } - if (treenode->younger != NULL) { - if (!ddCheckPermuation(table, treenode->younger, perm, invperm)) - return(0); - } - return(1); -} diff --git a/src/bdd/cudd/cuddSat.c b/src/bdd/cudd/cuddSat.c deleted file mode 100644 index 1755a1c1..00000000 --- a/src/bdd/cudd/cuddSat.c +++ /dev/null @@ -1,1305 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSat.c] - - PackageName [cudd] - - Synopsis [Functions for the solution of satisfiability related - problems.] - - Description [External procedures included in this file: -
              -
            • Cudd_Eval() -
            • Cudd_ShortestPath() -
            • Cudd_LargestCube() -
            • Cudd_ShortestLength() -
            • Cudd_Decreasing() -
            • Cudd_Increasing() -
            • Cudd_EquivDC() -
            • Cudd_bddLeqUnless() -
            • Cudd_EqualSupNorm() -
            • Cudd_bddMakePrime() -
            - Internal procedures included in this module: -
              -
            • cuddBddMakePrime() -
            - Static procedures included in this module: -
              -
            • freePathPair() -
            • getShortest() -
            • getPath() -
            • getLargest() -
            • getCube() -
            ] - - Author [Seh-Woong Jeong, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_BIGGY 1000000 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -typedef struct cuddPathPair { - int pos; - int neg; -} cuddPathPair; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static DdNode *one, *zero; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -#define WEIGHT(weight, col) ((weight) == NULL ? 1 : weight[col]) - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static enum st_retval freePathPair ARGS((char *key, char *value, char *arg)); -static cuddPathPair getShortest ARGS((DdNode *root, int *cost, int *support, st_table *visited)); -static DdNode * getPath ARGS((DdManager *manager, st_table *visited, DdNode *f, int *weight, int cost)); -static cuddPathPair getLargest ARGS((DdNode *root, st_table *visited)); -static DdNode * getCube ARGS((DdManager *manager, st_table *visited, DdNode *f, int cost)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Returns the value of a DD for a given variable assignment.] - - Description [Finds the value of a DD for a given variable - assignment. The variable assignment is passed in an array of int's, - that should specify a zero or a one for each variable in the support - of the function. Returns a pointer to a constant node. No new nodes - are produced.] - - SideEffects [None] - - SeeAlso [Cudd_bddLeq Cudd_addEvalConst] - -******************************************************************************/ -DdNode * -Cudd_Eval( - DdManager * dd, - DdNode * f, - int * inputs) -{ - int comple; - DdNode *ptr; - - comple = Cudd_IsComplement(f); - ptr = Cudd_Regular(f); - - while (!cuddIsConstant(ptr)) { - if (inputs[ptr->index] == 1) { - ptr = cuddT(ptr); - } else { - comple ^= Cudd_IsComplement(cuddE(ptr)); - ptr = Cudd_Regular(cuddE(ptr)); - } - } - return(Cudd_NotCond(ptr,comple)); - -} /* end of Cudd_Eval */ - - -/**Function******************************************************************** - - Synopsis [Finds a shortest path in a DD.] - - Description [Finds a shortest path in a DD. f is the DD we want to - get the shortest path for; weight\[i\] is the weight of the THEN arc - coming from the node whose index is i. If weight is NULL, then unit - weights are assumed for all THEN arcs. All ELSE arcs have 0 weight. - If non-NULL, both weight and support should point to arrays with at - least as many entries as there are variables in the manager. - Returns the shortest path as the BDD of a cube.] - - SideEffects [support contains on return the true support of f. - If support is NULL on entry, then Cudd_ShortestPath does not compute - the true support info. length contains the length of the path.] - - SeeAlso [Cudd_ShortestLength Cudd_LargestCube] - -******************************************************************************/ -DdNode * -Cudd_ShortestPath( - DdManager * manager, - DdNode * f, - int * weight, - int * support, - int * length) -{ - register DdNode *F; - st_table *visited; - DdNode *sol; - cuddPathPair *rootPair; - int complement, cost; - int i; - - one = DD_ONE(manager); - zero = DD_ZERO(manager); - - /* Initialize support. */ - if (support) { - for (i = 0; i < manager->size; i++) { - support[i] = 0; - } - } - - if (f == Cudd_Not(one) || f == zero) { - *length = DD_BIGGY; - return(Cudd_Not(one)); - } - /* From this point on, a path exists. */ - - /* Initialize visited table. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - - /* Now get the length of the shortest path(s) from f to 1. */ - (void) getShortest(f, weight, support, visited); - - complement = Cudd_IsComplement(f); - - F = Cudd_Regular(f); - - st_lookup(visited, (char *)F, (char **)&rootPair); - - if (complement) { - cost = rootPair->neg; - } else { - cost = rootPair->pos; - } - - /* Recover an actual shortest path. */ - do { - manager->reordered = 0; - sol = getPath(manager,visited,f,weight,cost); - } while (manager->reordered == 1); - - st_foreach(visited, freePathPair, NULL); - st_free_table(visited); - - *length = cost; - return(sol); - -} /* end of Cudd_ShortestPath */ - - -/**Function******************************************************************** - - Synopsis [Finds a largest cube in a DD.] - - Description [Finds a largest cube in a DD. f is the DD we want to - get the largest cube for. The problem is translated into the one of - finding a shortest path in f, when both THEN and ELSE arcs are assumed to - have unit length. This yields a largest cube in the disjoint cover - corresponding to the DD. Therefore, it is not necessarily the largest - implicant of f. Returns the largest cube as a BDD.] - - SideEffects [The number of literals of the cube is returned in length.] - - SeeAlso [Cudd_ShortestPath] - -******************************************************************************/ -DdNode * -Cudd_LargestCube( - DdManager * manager, - DdNode * f, - int * length) -{ - register DdNode *F; - st_table *visited; - DdNode *sol; - cuddPathPair *rootPair; - int complement, cost; - - one = DD_ONE(manager); - zero = DD_ZERO(manager); - - if (f == Cudd_Not(one) || f == zero) { - *length = DD_BIGGY; - return(Cudd_Not(one)); - } - /* From this point on, a path exists. */ - - /* Initialize visited table. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - - /* Now get the length of the shortest path(s) from f to 1. */ - (void) getLargest(f, visited); - - complement = Cudd_IsComplement(f); - - F = Cudd_Regular(f); - - st_lookup(visited, (char *)F, (char **)&rootPair); - - if (complement) { - cost = rootPair->neg; - } else { - cost = rootPair->pos; - } - - /* Recover an actual shortest path. */ - do { - manager->reordered = 0; - sol = getCube(manager,visited,f,cost); - } while (manager->reordered == 1); - - st_foreach(visited, freePathPair, NULL); - st_free_table(visited); - - *length = cost; - return(sol); - -} /* end of Cudd_LargestCube */ - - -/**Function******************************************************************** - - Synopsis [Find the length of the shortest path(s) in a DD.] - - Description [Find the length of the shortest path(s) in a DD. f is - the DD we want to get the shortest path for; weight\[i\] is the - weight of the THEN edge coming from the node whose index is i. All - ELSE edges have 0 weight. Returns the length of the shortest - path(s) if successful; CUDD_OUT_OF_MEM otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_ShortestPath] - -******************************************************************************/ -int -Cudd_ShortestLength( - DdManager * manager, - DdNode * f, - int * weight) -{ - register DdNode *F; - st_table *visited; - cuddPathPair *my_pair; - int complement, cost; - - one = DD_ONE(manager); - zero = DD_ZERO(manager); - - if (f == Cudd_Not(one) || f == zero) { - return(DD_BIGGY); - } - - /* From this point on, a path exists. */ - /* Initialize visited table and support. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - - /* Now get the length of the shortest path(s) from f to 1. */ - (void) getShortest(f, weight, NULL, visited); - - complement = Cudd_IsComplement(f); - - F = Cudd_Regular(f); - - st_lookup(visited, (char *)F, (char **)&my_pair); - - if (complement) { - cost = my_pair->neg; - } else { - cost = my_pair->pos; - } - - st_foreach(visited, freePathPair, NULL); - st_free_table(visited); - - return(cost); - -} /* end of Cudd_ShortestLength */ - - -/**Function******************************************************************** - - Synopsis [Determines whether a BDD is negative unate in a - variable.] - - Description [Determines whether the function represented by BDD f is - negative unate (monotonic decreasing) in variable i. Returns the - constant one is f is unate and the (logical) constant zero if it is not. - This function does not generate any new nodes.] - - SideEffects [None] - - SeeAlso [Cudd_Increasing] - -******************************************************************************/ -DdNode * -Cudd_Decreasing( - DdManager * dd, - DdNode * f, - int i) -{ - unsigned int topf, level; - DdNode *F, *fv, *fvn, *res; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - - statLine(dd); -#ifdef DD_DEBUG - assert(0 <= i && i < dd->size); -#endif - - F = Cudd_Regular(f); - topf = cuddI(dd,F->index); - - /* Check terminal case. If topf > i, f does not depend on var. - ** Therefore, f is unate in i. - */ - level = (unsigned) dd->perm[i]; - if (topf > level) { - return(DD_ONE(dd)); - } - - /* From now on, f is not constant. */ - - /* Check cache. */ - cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) Cudd_Decreasing; - res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]); - if (res != NULL) { - return(res); - } - - /* Compute cofactors. */ - fv = cuddT(F); fvn = cuddE(F); - if (F != f) { - fv = Cudd_Not(fv); - fvn = Cudd_Not(fvn); - } - - if (topf == (unsigned) level) { - /* Special case: if fv is regular, fv(1,...,1) = 1; - ** If in addition fvn is complemented, fvn(1,...,1) = 0. - ** But then f(1,1,...,1) > f(0,1,...,1). Hence f is not - ** monotonic decreasing in i. - */ - if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) { - return(Cudd_Not(DD_ONE(dd))); - } - res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd)); - } else { - res = Cudd_Decreasing(dd,fv,i); - if (res == DD_ONE(dd)) { - res = Cudd_Decreasing(dd,fvn,i); - } - } - - cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res); - return(res); - -} /* end of Cudd_Decreasing */ - - -/**Function******************************************************************** - - Synopsis [Determines whether a BDD is positive unate in a - variable.] - - Description [Determines whether the function represented by BDD f is - positive unate (monotonic decreasing) in variable i. It is based on - Cudd_Decreasing and the fact that f is monotonic increasing in i if - and only if its complement is monotonic decreasing in i.] - - SideEffects [None] - - SeeAlso [Cudd_Decreasing] - -******************************************************************************/ -DdNode * -Cudd_Increasing( - DdManager * dd, - DdNode * f, - int i) -{ - return(Cudd_Decreasing(dd,Cudd_Not(f),i)); - -} /* end of Cudd_Increasing */ - - -/**Function******************************************************************** - - Synopsis [Tells whether F and G are identical wherever D is 0.] - - Description [Tells whether F and G are identical wherever D is 0. F - and G are either two ADDs or two BDDs. D is either a 0-1 ADD or a - BDD. The function returns 1 if F and G are equivalent, and 0 - otherwise. No new nodes are created.] - - SideEffects [None] - - SeeAlso [Cudd_bddLeqUnless] - -******************************************************************************/ -int -Cudd_EquivDC( - DdManager * dd, - DdNode * F, - DdNode * G, - DdNode * D) -{ - DdNode *tmp, *One, *Gr, *Dr; - DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn; - int res; - unsigned int flevel, glevel, dlevel, top; - - One = DD_ONE(dd); - - statLine(dd); - /* Check terminal cases. */ - if (D == One || F == G) return(1); - if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0); - - /* From now on, D is non-constant. */ - - /* Normalize call to increase cache efficiency. */ - if (F > G) { - tmp = F; - F = G; - G = tmp; - } - if (Cudd_IsComplement(F)) { - F = Cudd_Not(F); - G = Cudd_Not(G); - } - - /* From now on, F is regular. */ - - /* Check cache. */ - tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D); - if (tmp != NULL) return(tmp == One); - - /* Find splitting variable. */ - flevel = cuddI(dd,F->index); - Gr = Cudd_Regular(G); - glevel = cuddI(dd,Gr->index); - top = ddMin(flevel,glevel); - Dr = Cudd_Regular(D); - dlevel = dd->perm[Dr->index]; - top = ddMin(top,dlevel); - - /* Compute cofactors. */ - if (top == flevel) { - Fv = cuddT(F); - Fvn = cuddE(F); - } else { - Fv = Fvn = F; - } - if (top == glevel) { - Gv = cuddT(Gr); - Gvn = cuddE(Gr); - if (G != Gr) { - Gv = Cudd_Not(Gv); - Gvn = Cudd_Not(Gvn); - } - } else { - Gv = Gvn = G; - } - if (top == dlevel) { - Dv = cuddT(Dr); - Dvn = cuddE(Dr); - if (D != Dr) { - Dv = Cudd_Not(Dv); - Dvn = Cudd_Not(Dvn); - } - } else { - Dv = Dvn = D; - } - - /* Solve recursively. */ - res = Cudd_EquivDC(dd,Fv,Gv,Dv); - if (res != 0) { - res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn); - } - cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One)); - - return(res); - -} /* end of Cudd_EquivDC */ - - -/**Function******************************************************************** - - Synopsis [Tells whether f is less than of equal to G unless D is 1.] - - Description [Tells whether f is less than of equal to G unless D is - 1. f, g, and D are BDDs. The function returns 1 if f is less than - of equal to G, and 0 otherwise. No new nodes are created.] - - SideEffects [None] - - SeeAlso [Cudd_EquivDC Cudd_bddLeq Cudd_bddIteConstant] - -******************************************************************************/ -int -Cudd_bddLeqUnless( - DdManager *dd, - DdNode *f, - DdNode *g, - DdNode *D) -{ - DdNode *tmp, *One, *F, *G; - DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De; - int res; - unsigned int flevel, glevel, dlevel, top; - - statLine(dd); - - One = DD_ONE(dd); - - /* Check terminal cases. */ - if (f == g || g == One || f == Cudd_Not(One) || D == One || - D == f || D == Cudd_Not(g)) return(1); - /* Check for two-operand cases. */ - if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f)) - return(Cudd_bddLeq(dd,f,g)); - if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D)); - if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D)); - - /* From now on, f, g, and D are non-constant, distinct, and - ** non-complementary. */ - - /* Normalize call to increase cache efficiency. We rely on the - ** fact that f <= g unless D is equivalent to not(g) <= not(f) - ** unless D and to f <= D unless g. We make sure that D is - ** regular, and that at most one of f and g is complemented. We also - ** ensure that when two operands can be swapped, the one with the - ** lowest address comes first. */ - - if (Cudd_IsComplement(D)) { - if (Cudd_IsComplement(g)) { - /* Special case: if f is regular and g is complemented, - ** f(1,...,1) = 1 > 0 = g(1,...,1). If D(1,...,1) = 0, return 0. - */ - if (!Cudd_IsComplement(f)) return(0); - /* !g <= D unless !f or !D <= g unless !f */ - tmp = D; - D = Cudd_Not(f); - if (g < tmp) { - f = Cudd_Not(g); - g = tmp; - } else { - f = Cudd_Not(tmp); - } - } else { - if (Cudd_IsComplement(f)) { - /* !D <= !f unless g or !D <= g unless !f */ - tmp = f; - f = Cudd_Not(D); - if (tmp < g) { - D = g; - g = Cudd_Not(tmp); - } else { - D = Cudd_Not(tmp); - } - } else { - /* f <= D unless g or !D <= !f unless g */ - tmp = D; - D = g; - if (tmp < f) { - g = Cudd_Not(f); - f = Cudd_Not(tmp); - } else { - g = tmp; - } - } - } - } else { - if (Cudd_IsComplement(g)) { - if (Cudd_IsComplement(f)) { - /* !g <= !f unless D or !g <= D unless !f */ - tmp = f; - f = Cudd_Not(g); - if (D < tmp) { - g = D; - D = Cudd_Not(tmp); - } else { - g = Cudd_Not(tmp); - } - } else { - /* f <= g unless D or !g <= !f unless D */ - if (g < f) { - tmp = g; - g = Cudd_Not(f); - f = Cudd_Not(tmp); - } - } - } else { - /* f <= g unless D or f <= D unless g */ - if (D < g) { - tmp = D; - D = g; - g = tmp; - } - } - } - - /* From now on, D is regular. */ - - /* Check cache. */ - tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D); - if (tmp != NULL) return(tmp == One); - - /* Find splitting variable. */ - F = Cudd_Regular(f); - flevel = dd->perm[F->index]; - G = Cudd_Regular(g); - glevel = dd->perm[G->index]; - top = ddMin(flevel,glevel); - dlevel = dd->perm[D->index]; - top = ddMin(top,dlevel); - - /* Compute cofactors. */ - if (top == flevel) { - Ft = cuddT(F); - Fe = cuddE(F); - if (F != f) { - Ft = Cudd_Not(Ft); - Fe = Cudd_Not(Fe); - } - } else { - Ft = Fe = f; - } - if (top == glevel) { - Gt = cuddT(G); - Ge = cuddE(G); - if (G != g) { - Gt = Cudd_Not(Gt); - Ge = Cudd_Not(Ge); - } - } else { - Gt = Ge = g; - } - if (top == dlevel) { - Dt = cuddT(D); - De = cuddE(D); - } else { - Dt = De = D; - } - - /* Solve recursively. */ - res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt); - if (res != 0) { - res = Cudd_bddLeqUnless(dd,Fe,Ge,De); - } - cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res)); - - return(res); - -} /* end of Cudd_bddLeqUnless */ - - -/**Function******************************************************************** - - Synopsis [Compares two ADDs for equality within tolerance.] - - Description [Compares two ADDs for equality within tolerance. Two - ADDs are reported to be equal if the maximum difference between them - (the sup norm of their difference) is less than or equal to the - tolerance parameter. Returns 1 if the two ADDs are equal (within - tolerance); 0 otherwise. If parameter pr is positive - the first failure is reported to the standard output.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_EqualSupNorm( - DdManager * dd /* manager */, - DdNode * f /* first ADD */, - DdNode * g /* second ADD */, - CUDD_VALUE_TYPE tolerance /* maximum allowed difference */, - int pr /* verbosity level */) -{ - DdNode *fv, *fvn, *gv, *gvn, *r; - unsigned int topf, topg; - - statLine(dd); - /* Check terminal cases. */ - if (f == g) return(1); - if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) { - if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) { - return(1); - } else { - if (pr>0) { - (void) fprintf(dd->out,"Offending nodes:\n"); -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out, - "f: address = %lx\t value = %40.30f\n", - (unsigned long) f, cuddV(f)); - (void) fprintf(dd->out, - "g: address = %lx\t value = %40.30f\n", - (unsigned long) g, cuddV(g)); -#else - (void) fprintf(dd->out, - "f: address = %x\t value = %40.30f\n", - (unsigned) f, cuddV(f)); - (void) fprintf(dd->out, - "g: address = %x\t value = %40.30f\n", - (unsigned) g, cuddV(g)); -#endif - } - return(0); - } - } - - /* We only insert the result in the cache if the comparison is - ** successful. Therefore, if we hit we return 1. */ - r = cuddCacheLookup2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_EqualSupNorm,f,g); - if (r != NULL) { - return(1); - } - - /* Compute the cofactors and solve the recursive subproblems. */ - topf = cuddI(dd,f->index); - topg = cuddI(dd,g->index); - - if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;} - if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;} - - if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0); - if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0); - - cuddCacheInsert2(dd,(DdNode * (*)(DdManager *, DdNode *, DdNode *))Cudd_EqualSupNorm,f,g,DD_ONE(dd)); - - return(1); - -} /* end of Cudd_EqualSupNorm */ - - -/**Function******************************************************************** - - Synopsis [Expands cube to a prime implicant of f.] - - Description [Expands cube to a prime implicant of f. Returns the prime - if successful; NULL otherwise. In particular, NULL is returned if cube - is not a real cube or is not an implicant of f.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_bddMakePrime( - DdManager *dd /* manager */, - DdNode *cube /* cube to be expanded */, - DdNode *f /* function of which the cube is to be made a prime */) -{ - DdNode *res; - - if (!Cudd_bddLeq(dd,cube,f)) return(NULL); - - do { - dd->reordered = 0; - res = cuddBddMakePrime(dd,cube,f); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddMakePrime */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddMakePrime.] - - Description [Performs the recursive step of Cudd_bddMakePrime. - Returns the prime if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddBddMakePrime( - DdManager *dd /* manager */, - DdNode *cube /* cube to be expanded */, - DdNode *f /* function of which the cube is to be made a prime */) -{ - DdNode *scan; - DdNode *t, *e; - DdNode *res = cube; - DdNode *zero = Cudd_Not(DD_ONE(dd)); - - Cudd_Ref(res); - scan = cube; - while (!Cudd_IsConstant(scan)) { - DdNode *reg = Cudd_Regular(scan); - DdNode *var = dd->vars[reg->index]; - DdNode *expanded = Cudd_bddExistAbstract(dd,res,var); - if (expanded == NULL) { - return(NULL); - } - Cudd_Ref(expanded); - if (Cudd_bddLeq(dd,expanded,f)) { - Cudd_RecursiveDeref(dd,res); - res = expanded; - } else { - Cudd_RecursiveDeref(dd,expanded); - } - cuddGetBranches(scan,&t,&e); - if (t == zero) { - scan = e; - } else if (e == zero) { - scan = t; - } else { - Cudd_RecursiveDeref(dd,res); - return(NULL); /* cube is not a cube */ - } - } - - if (scan == DD_ONE(dd)) { - Cudd_Deref(res); - return(res); - } else { - Cudd_RecursiveDeref(dd,res); - return(NULL); - } - -} /* end of cuddBddMakePrime */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Frees the entries of the visited symbol table.] - - Description [Frees the entries of the visited symbol table. Returns - ST_CONTINUE.] - - SideEffects [None] - -******************************************************************************/ -static enum st_retval -freePathPair( - char * key, - char * value, - char * arg) -{ - cuddPathPair *pair; - - pair = (cuddPathPair *) value; - FREE(pair); - return(ST_CONTINUE); - -} /* end of freePathPair */ - - -/**Function******************************************************************** - - Synopsis [Finds the length of the shortest path(s) in a DD.] - - Description [Finds the length of the shortest path(s) in a DD. - Uses a local symbol table to store the lengths for each - node. Only the lengths for the regular nodes are entered in the table, - because those for the complement nodes are simply obtained by swapping - the two lenghts. - Returns a pair of lengths: the length of the shortest path to 1; - and the length of the shortest path to 0. This is done so as to take - complement arcs into account.] - - SideEffects [Accumulates the support of the DD in support.] - - SeeAlso [] - -******************************************************************************/ -static cuddPathPair -getShortest( - DdNode * root, - int * cost, - int * support, - st_table * visited) -{ - cuddPathPair *my_pair, res_pair, pair_T, pair_E; - DdNode *my_root, *T, *E; - int weight; - - my_root = Cudd_Regular(root); - - if (st_lookup(visited, (char *)my_root, (char **)&my_pair)) { - if (Cudd_IsComplement(root)) { - res_pair.pos = my_pair->neg; - res_pair.neg = my_pair->pos; - } else { - res_pair.pos = my_pair->pos; - res_pair.neg = my_pair->neg; - } - return(res_pair); - } - - /* In the case of a BDD the following test is equivalent to - ** testing whether the BDD is the constant 1. This formulation, - ** however, works for ADDs as well, by assuming the usual - ** dichotomy of 0 and != 0. - */ - if (cuddIsConstant(my_root)) { - if (my_root != zero) { - res_pair.pos = 0; - res_pair.neg = DD_BIGGY; - } else { - res_pair.pos = DD_BIGGY; - res_pair.neg = 0; - } - } else { - T = cuddT(my_root); - E = cuddE(my_root); - - pair_T = getShortest(T, cost, support, visited); - pair_E = getShortest(E, cost, support, visited); - weight = WEIGHT(cost, my_root->index); - res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos); - res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg); - - /* Update support. */ - if (support != NULL) { - support[my_root->index] = 1; - } - } - - my_pair = ALLOC(cuddPathPair, 1); - if (my_pair == NULL) { - if (Cudd_IsComplement(root)) { - int tmp = res_pair.pos; - res_pair.pos = res_pair.neg; - res_pair.neg = tmp; - } - return(res_pair); - } - my_pair->pos = res_pair.pos; - my_pair->neg = res_pair.neg; - - st_insert(visited, (char *)my_root, (char *)my_pair); - if (Cudd_IsComplement(root)) { - res_pair.pos = my_pair->neg; - res_pair.neg = my_pair->pos; - } else { - res_pair.pos = my_pair->pos; - res_pair.neg = my_pair->neg; - } - return(res_pair); - -} /* end of getShortest */ - - -/**Function******************************************************************** - - Synopsis [Build a BDD for a shortest path of f.] - - Description [Build a BDD for a shortest path of f. - Given the minimum length from the root, and the minimum - lengths for each node (in visited), apply triangulation at each node. - Of the two children of each node on a shortest path, at least one is - on a shortest path. In case of ties the procedure chooses the THEN - children. - Returns a pointer to the cube BDD representing the path if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -getPath( - DdManager * manager, - st_table * visited, - DdNode * f, - int * weight, - int cost) -{ - DdNode *sol, *tmp; - DdNode *my_dd, *T, *E; - cuddPathPair *T_pair, *E_pair; - int Tcost, Ecost; - int complement; - - my_dd = Cudd_Regular(f); - complement = Cudd_IsComplement(f); - - sol = one; - cuddRef(sol); - - while (!cuddIsConstant(my_dd)) { - Tcost = cost - WEIGHT(weight, my_dd->index); - Ecost = cost; - - T = cuddT(my_dd); - E = cuddE(my_dd); - - if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);} - - st_lookup(visited, (char *)Cudd_Regular(T), (char **)&T_pair); - if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) || - (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) { - tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol); - if (tmp == NULL) { - Cudd_RecursiveDeref(manager,sol); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(manager,sol); - sol = tmp; - - complement = Cudd_IsComplement(T); - my_dd = Cudd_Regular(T); - cost = Tcost; - continue; - } - st_lookup(visited, (char *)Cudd_Regular(E), (char **)&E_pair); - if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) || - (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) { - tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol); - if (tmp == NULL) { - Cudd_RecursiveDeref(manager,sol); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(manager,sol); - sol = tmp; - complement = Cudd_IsComplement(E); - my_dd = Cudd_Regular(E); - cost = Ecost; - continue; - } - (void) fprintf(manager->err,"We shouldn't be here!!\n"); - manager->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - - cuddDeref(sol); - return(sol); - -} /* end of getPath */ - - -/**Function******************************************************************** - - Synopsis [Finds the size of the largest cube(s) in a DD.] - - Description [Finds the size of the largest cube(s) in a DD. - This problem is translated into finding the shortest paths from a node - when both THEN and ELSE arcs have unit lengths. - Uses a local symbol table to store the lengths for each - node. Only the lengths for the regular nodes are entered in the table, - because those for the complement nodes are simply obtained by swapping - the two lenghts. - Returns a pair of lengths: the length of the shortest path to 1; - and the length of the shortest path to 0. This is done so as to take - complement arcs into account.] - - SideEffects [none] - - SeeAlso [] - -******************************************************************************/ -static cuddPathPair -getLargest( - DdNode * root, - st_table * visited) -{ - cuddPathPair *my_pair, res_pair, pair_T, pair_E; - DdNode *my_root, *T, *E; - - my_root = Cudd_Regular(root); - - if (st_lookup(visited, (char *)my_root, (char **)&my_pair)) { - if (Cudd_IsComplement(root)) { - res_pair.pos = my_pair->neg; - res_pair.neg = my_pair->pos; - } else { - res_pair.pos = my_pair->pos; - res_pair.neg = my_pair->neg; - } - return(res_pair); - } - - /* In the case of a BDD the following test is equivalent to - ** testing whether the BDD is the constant 1. This formulation, - ** however, works for ADDs as well, by assuming the usual - ** dichotomy of 0 and != 0. - */ - if (cuddIsConstant(my_root)) { - if (my_root != zero) { - res_pair.pos = 0; - res_pair.neg = DD_BIGGY; - } else { - res_pair.pos = DD_BIGGY; - res_pair.neg = 0; - } - } else { - T = cuddT(my_root); - E = cuddE(my_root); - - pair_T = getLargest(T, visited); - pair_E = getLargest(E, visited); - res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1; - res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1; - } - - my_pair = ALLOC(cuddPathPair, 1); - if (my_pair == NULL) { /* simlpy do not cache this result */ - if (Cudd_IsComplement(root)) { - int tmp = res_pair.pos; - res_pair.pos = res_pair.neg; - res_pair.neg = tmp; - } - return(res_pair); - } - my_pair->pos = res_pair.pos; - my_pair->neg = res_pair.neg; - - st_insert(visited, (char *)my_root, (char *)my_pair); - if (Cudd_IsComplement(root)) { - res_pair.pos = my_pair->neg; - res_pair.neg = my_pair->pos; - } else { - res_pair.pos = my_pair->pos; - res_pair.neg = my_pair->neg; - } - return(res_pair); - -} /* end of getLargest */ - - -/**Function******************************************************************** - - Synopsis [Build a BDD for a largest cube of f.] - - Description [Build a BDD for a largest cube of f. - Given the minimum length from the root, and the minimum - lengths for each node (in visited), apply triangulation at each node. - Of the two children of each node on a shortest path, at least one is - on a shortest path. In case of ties the procedure chooses the THEN - children. - Returns a pointer to the cube BDD representing the path if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -getCube( - DdManager * manager, - st_table * visited, - DdNode * f, - int cost) -{ - DdNode *sol, *tmp; - DdNode *my_dd, *T, *E; - cuddPathPair *T_pair, *E_pair; - int Tcost, Ecost; - int complement; - - my_dd = Cudd_Regular(f); - complement = Cudd_IsComplement(f); - - sol = one; - cuddRef(sol); - - while (!cuddIsConstant(my_dd)) { - Tcost = cost - 1; - Ecost = cost - 1; - - T = cuddT(my_dd); - E = cuddE(my_dd); - - if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);} - - st_lookup(visited, (char *)Cudd_Regular(T), (char **)&T_pair); - if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) || - (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) { - tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol); - if (tmp == NULL) { - Cudd_RecursiveDeref(manager,sol); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(manager,sol); - sol = tmp; - - complement = Cudd_IsComplement(T); - my_dd = Cudd_Regular(T); - cost = Tcost; - continue; - } - st_lookup(visited, (char *)Cudd_Regular(E), (char **)&E_pair); - if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) || - (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) { - tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol); - if (tmp == NULL) { - Cudd_RecursiveDeref(manager,sol); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(manager,sol); - sol = tmp; - complement = Cudd_IsComplement(E); - my_dd = Cudd_Regular(E); - cost = Ecost; - continue; - } - (void) fprintf(manager->err,"We shouldn't be here!\n"); - manager->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - - cuddDeref(sol); - return(sol); - -} /* end of getCube */ diff --git a/src/bdd/cudd/cuddSign.c b/src/bdd/cudd/cuddSign.c deleted file mode 100644 index fcaa65c4..00000000 --- a/src/bdd/cudd/cuddSign.c +++ /dev/null @@ -1,292 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSign.c] - - PackageName [cudd] - - Synopsis [Computation of signatures] - - Description [External procedures included in this module: -
              -
            • Cudd_CofMinterm(); -
            - Static procedures included in this module: -
              -
            • ddCofMintermAux() -
            - ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSign.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static int size; - -#ifdef DD_STATS -static int num_calls; /* should equal 2n-1 (n is the # of nodes) */ -static int table_mem; -#endif - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static double * ddCofMintermAux ARGS((DdManager *dd, DdNode *node, st_table *table)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes the fraction of minterms in the on-set of all the - positive cofactors of a BDD or ADD.] - - Description [Computes the fraction of minterms in the on-set of all - the positive cofactors of DD. Returns the pointer to an array of - doubles if successful; NULL otherwise. The array hs as many - positions as there are BDD variables in the manager plus one. The - last position of the array contains the fraction of the minterms in - the ON-set of the function represented by the BDD or ADD. The other - positions of the array hold the variable signatures.] - - SideEffects [None] - -******************************************************************************/ -double * -Cudd_CofMinterm( - DdManager * dd, - DdNode * node) -{ - st_table *table; - double *values; - double *result = NULL; - int i, firstLevel; - -#ifdef DD_STATS - long startTime; - startTime = util_cpu_time(); - num_calls = 0; - table_mem = sizeof(st_table); -#endif - - table = st_init_table(st_ptrcmp, st_ptrhash); - if (table == NULL) { - (void) fprintf(dd->err, - "out-of-memory, couldn't measure DD cofactors.\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - size = dd->size; - values = ddCofMintermAux(dd, node, table); - if (values != NULL) { - result = ALLOC(double,size + 1); - if (result != NULL) { -#ifdef DD_STATS - table_mem += (size + 1) * sizeof(double); -#endif - if (Cudd_IsConstant(node)) - firstLevel = 1; - else - firstLevel = cuddI(dd,Cudd_Regular(node)->index); - for (i = 0; i < size; i++) { - if (i >= cuddI(dd,Cudd_Regular(node)->index)) { - result[dd->invperm[i]] = values[i - firstLevel]; - } else { - result[dd->invperm[i]] = values[size - firstLevel]; - } - } - result[size] = values[size - firstLevel]; - } else { - dd->errorCode = CUDD_MEMORY_OUT; - } - } - -#ifdef DD_STATS - table_mem += table->num_bins * sizeof(st_table_entry *); -#endif - if (Cudd_Regular(node)->ref == 1) FREE(values); - st_foreach(table, cuddStCountfree, NULL); - st_free_table(table); -#ifdef DD_STATS - (void) fprintf(dd->out,"Number of calls: %d\tTable memory: %d bytes\n", - num_calls, table_mem); - (void) fprintf(dd->out,"Time to compute measures: %s\n", - util_print_time(util_cpu_time() - startTime)); -#endif - if (result == NULL) { - (void) fprintf(dd->out, - "out-of-memory, couldn't measure DD cofactors.\n"); - dd->errorCode = CUDD_MEMORY_OUT; - } - return(result); - -} /* end of Cudd_CofMinterm */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Recursive Step for Cudd_CofMinterm function.] - - Description [Traverses the DD node and computes the fraction of - minterms in the on-set of all positive cofactors simultaneously. - It allocates an array with two more entries than there are - variables below the one labeling the node. One extra entry (the - first in the array) is for the variable labeling the node. The other - entry (the last one in the array) holds the fraction of minterms of - the function rooted at node. Each other entry holds the value for - one cofactor. The array is put in a symbol table, to avoid repeated - computation, and its address is returned by the procedure, for use - by the caller. Returns a pointer to the array of cofactor measures.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static double * -ddCofMintermAux( - DdManager * dd, - DdNode * node, - st_table * table) -{ - DdNode *N; /* regular version of node */ - DdNode *Nv, *Nnv; - double *values; - double *valuesT, *valuesE; - int i; - int localSize, localSizeT, localSizeE; - double vT, vE; - - statLine(dd); -#ifdef DD_STATS - num_calls++; -#endif - - if (st_lookup(table, (char *) node, (char **) &values)) { - return(values); - } - - N = Cudd_Regular(node); - if (cuddIsConstant(N)) { - localSize = 1; - } else { - localSize = size - cuddI(dd,N->index) + 1; - } - values = ALLOC(double, localSize); - if (values == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - if (cuddIsConstant(N)) { - if (node == DD_ZERO(dd) || node == Cudd_Not(DD_ONE(dd))) { - values[0] = 0.0; - } else { - values[0] = 1.0; - } - } else { - Nv = Cudd_NotCond(cuddT(N),N!=node); - Nnv = Cudd_NotCond(cuddE(N),N!=node); - - valuesT = ddCofMintermAux(dd, Nv, table); - if (valuesT == NULL) return(NULL); - valuesE = ddCofMintermAux(dd, Nnv, table); - if (valuesE == NULL) return(NULL); - - if (Cudd_IsConstant(Nv)) { - localSizeT = 1; - } else { - localSizeT = size - cuddI(dd,Cudd_Regular(Nv)->index) + 1; - } - if (Cudd_IsConstant(Nnv)) { - localSizeE = 1; - } else { - localSizeE = size - cuddI(dd,Cudd_Regular(Nnv)->index) + 1; - } - values[0] = valuesT[localSizeT - 1]; - for (i = 1; i < localSize; i++) { - if (i >= cuddI(dd,Cudd_Regular(Nv)->index) - cuddI(dd,N->index)) { - vT = valuesT[i - cuddI(dd,Cudd_Regular(Nv)->index) + - cuddI(dd,N->index)]; - } else { - vT = valuesT[localSizeT - 1]; - } - if (i >= cuddI(dd,Cudd_Regular(Nnv)->index) - cuddI(dd,N->index)) { - vE = valuesE[i - cuddI(dd,Cudd_Regular(Nnv)->index) + - cuddI(dd,N->index)]; - } else { - vE = valuesE[localSizeE - 1]; - } - values[i] = (vT + vE) / 2.0; - } - if (Cudd_Regular(Nv)->ref == 1) FREE(valuesT); - if (Cudd_Regular(Nnv)->ref == 1) FREE(valuesE); - } - - if (N->ref > 1) { - if (st_add_direct(table, (char *) node, (char *) values) == ST_OUT_OF_MEM) { - FREE(values); - return(NULL); - } -#ifdef DD_STATS - table_mem += localSize * sizeof(double) + sizeof(st_table_entry); -#endif - } - return(values); - -} /* end of ddCofMintermAux */ - diff --git a/src/bdd/cudd/cuddSolve.c b/src/bdd/cudd/cuddSolve.c deleted file mode 100644 index d9c4a2e7..00000000 --- a/src/bdd/cudd/cuddSolve.c +++ /dev/null @@ -1,339 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSolve.c] - - PackageName [cudd] - - Synopsis [Boolean equation solver and related functions.] - - Description [External functions included in this modoule: -
              -
            • Cudd_SolveEqn() -
            • Cudd_VerifySol() -
            - Internal functions included in this module: -
              -
            • cuddSolveEqnRecur() -
            • cuddVerifySol() -
            ] - - SeeAlso [] - - Author [Balakrishna Kumthekar] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Structure declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSolve.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the solution of F(x,y) = 0.] - - Description [Implements the solution for F(x,y) = 0. The return - value is the consistency condition. The y variables are the unknowns - and the remaining variables are the parameters. Returns the - consistency condition if successful; NULL otherwise. Cudd_SolveEqn - allocates an array and fills it with the indices of the - unknowns. This array is used by Cudd_VerifySol.] - - SideEffects [The solution is returned in G; the indices of the y - variables are returned in yIndex.] - - SeeAlso [Cudd_VerifySol] - -******************************************************************************/ -DdNode * -Cudd_SolveEqn( - DdManager * bdd, - DdNode * F /* the left-hand side of the equation */, - DdNode * Y /* the cube of the y variables */, - DdNode ** G /* the array of solutions (return parameter) */, - int ** yIndex /* index of y variables */, - int n /* numbers of unknowns */) -{ - DdNode *res; - int *temp; - - *yIndex = temp = ALLOC(int, n); - if (temp == NULL) { - bdd->errorCode = CUDD_MEMORY_OUT; - (void) fprintf(bdd->out, - "Cudd_SolveEqn: Out of memory for yIndex\n"); - return(NULL); - } - - do { - bdd->reordered = 0; - res = cuddSolveEqnRecur(bdd, F, Y, G, n, temp, 0); - } while (bdd->reordered == 1); - - return(res); - -} /* end of Cudd_SolveEqn */ - - -/**Function******************************************************************** - - Synopsis [Checks the solution of F(x,y) = 0.] - - Description [Checks the solution of F(x,y) = 0. This procedure - substitutes the solution components for the unknowns of F and returns - the resulting BDD for F.] - - SideEffects [Frees the memory pointed by yIndex.] - - SeeAlso [Cudd_SolveEqn] - -******************************************************************************/ -DdNode * -Cudd_VerifySol( - DdManager * bdd, - DdNode * F /* the left-hand side of the equation */, - DdNode ** G /* the array of solutions */, - int * yIndex /* index of y variables */, - int n /* numbers of unknowns */) -{ - DdNode *res; - - do { - bdd->reordered = 0; - res = cuddVerifySol(bdd, F, G, yIndex, n); - } while (bdd->reordered == 1); - - FREE(yIndex); - - return(res); - -} /* end of Cudd_VerifySol */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_SolveEqn.] - - Description [Implements the recursive step of Cudd_SolveEqn. - Returns NULL if the intermediate solution blows up - or reordering occurs. The parametric solutions are - stored in the array G.] - - SideEffects [none] - - SeeAlso [Cudd_SolveEqn, Cudd_VerifySol] - -******************************************************************************/ -DdNode * -cuddSolveEqnRecur( - DdManager * bdd, - DdNode * F /* the left-hand side of the equation */, - DdNode * Y /* the cube of remaining y variables */, - DdNode ** G /* the array of solutions */, - int n /* number of unknowns */, - int * yIndex /* array holding the y variable indices */, - int i /* level of recursion */) -{ - DdNode *Fn, *Fm1, *Fv, *Fvbar, *T, *w, *nextY, *one; - DdNodePtr *variables; - - int j; - - statLine(bdd); - variables = bdd->vars; - one = DD_ONE(bdd); - - /* Base condition. */ - if (Y == one) { - return F; - } - - /* Cofactor of Y. */ - yIndex[i] = Y->index; - nextY = Cudd_T(Y); - - /* Universal abstraction of F with respect to the top variable index. */ - Fm1 = cuddBddExistAbstractRecur(bdd, Cudd_Not(F), variables[yIndex[i]]); - if (Fm1) { - Fm1 = Cudd_Not(Fm1); - cuddRef(Fm1); - } else { - return(NULL); - } - - Fn = cuddSolveEqnRecur(bdd, Fm1, nextY, G, n, yIndex, i+1); - if (Fn) { - cuddRef(Fn); - } else { - Cudd_RecursiveDeref(bdd, Fm1); - return(NULL); - } - - Fv = cuddCofactorRecur(bdd, F, variables[yIndex[i]]); - if (Fv) { - cuddRef(Fv); - } else { - Cudd_RecursiveDeref(bdd, Fm1); - Cudd_RecursiveDeref(bdd, Fn); - return(NULL); - } - - Fvbar = cuddCofactorRecur(bdd, F, Cudd_Not(variables[yIndex[i]])); - if (Fvbar) { - cuddRef(Fvbar); - } else { - Cudd_RecursiveDeref(bdd, Fm1); - Cudd_RecursiveDeref(bdd, Fn); - Cudd_RecursiveDeref(bdd, Fv); - return(NULL); - } - - /* Build i-th component of the solution. */ - w = cuddBddIteRecur(bdd, variables[yIndex[i]], Cudd_Not(Fv), Fvbar); - if (w) { - cuddRef(w); - } else { - Cudd_RecursiveDeref(bdd, Fm1); - Cudd_RecursiveDeref(bdd, Fn); - Cudd_RecursiveDeref(bdd, Fv); - Cudd_RecursiveDeref(bdd, Fvbar); - return(NULL); - } - - T = cuddBddRestrictRecur(bdd, w, Cudd_Not(Fm1)); - if(T) { - cuddRef(T); - } else { - Cudd_RecursiveDeref(bdd, Fm1); - Cudd_RecursiveDeref(bdd, Fn); - Cudd_RecursiveDeref(bdd, Fv); - Cudd_RecursiveDeref(bdd, Fvbar); - Cudd_RecursiveDeref(bdd, w); - return(NULL); - } - - Cudd_RecursiveDeref(bdd,Fm1); - Cudd_RecursiveDeref(bdd,w); - Cudd_RecursiveDeref(bdd,Fv); - Cudd_RecursiveDeref(bdd,Fvbar); - - /* Substitute components of solution already found into solution. */ - for (j = n-1; j > i; j--) { - w = cuddBddComposeRecur(bdd,T, G[j], variables[yIndex[j]]); - if(w) { - cuddRef(w); - } else { - Cudd_RecursiveDeref(bdd, Fn); - Cudd_RecursiveDeref(bdd, T); - return(NULL); - } - Cudd_RecursiveDeref(bdd,T); - T = w; - } - G[i] = T; - - Cudd_Deref(Fn); - - return(Fn); - -} /* end of cuddSolveEqnRecur */ - - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_VerifySol. ] - - Description [] - - SideEffects [none] - - SeeAlso [Cudd_VerifySol] - -******************************************************************************/ -DdNode * -cuddVerifySol( - DdManager * bdd, - DdNode * F /* the left-hand side of the equation */, - DdNode ** G /* the array of solutions */, - int * yIndex /* array holding the y variable indices */, - int n /* number of unknowns */) -{ - DdNode *w, *R; - - int j; - - R = F; - cuddRef(R); - for(j = n - 1; j >= 0; j--) { - w = Cudd_bddCompose(bdd, R, G[j], yIndex[j]); - if (w) { - cuddRef(w); - } else { - return(NULL); - } - Cudd_RecursiveDeref(bdd,R); - R = w; - } - - cuddDeref(R); - - return(R); - -} /* end of cuddVerifySol */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddSplit.c b/src/bdd/cudd/cuddSplit.c deleted file mode 100644 index e21ea7cb..00000000 --- a/src/bdd/cudd/cuddSplit.c +++ /dev/null @@ -1,657 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSplit.c] - - PackageName [cudd] - - Synopsis [Returns a subset of minterms from a boolean function.] - - Description [External functions included in this modoule: -
              -
            • Cudd_SplitSet() -
            - Internal functions included in this module: -
              -
            • cuddSplitSetRecur() - - Static functions included in this module: -
                -
              • selectMintermsFromUniverse() -
              • mintermsFromUniverse() -
              • bddAnnotateMintermCount() -
              ] - - SeeAlso [] - - Author [Balakrishna Kumthekar] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Structure declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * selectMintermsFromUniverse ARGS((DdManager *manager, int *varSeen, double n)); -static DdNode * mintermsFromUniverse ARGS((DdManager *manager, DdNode **vars, int numVars, double n, int index)); -static double bddAnnotateMintermCount ARGS((DdManager *manager, DdNode *node, double max, st_table *table)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Returns m minterms from a BDD.] - - Description [Returns m minterms from a BDD whose - support has n variables at most. The procedure tries - to create as few extra nodes as possible. The function represented - by S depends on at most n of the variables - in xVars. Returns a BDD with m minterms - of the on-set of S if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_SplitSet( - DdManager * manager, - DdNode * S, - DdNode ** xVars, - int n, - double m) -{ - DdNode *result; - DdNode *zero, *one; - double max, num; - st_table *mtable; - int *varSeen; - int i,index, size; - - size = manager->size; - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Trivial cases. */ - if (m == 0.0) { - return(zero); - } - if (S == zero) { - return(NULL); - } - - max = pow(2.0,(double)n); - if (m > max) - return(NULL); - - do { - manager->reordered = 0; - /* varSeen is used to mark the variables that are encountered - ** while traversing the BDD S. - */ - varSeen = ALLOC(int, size); - if (varSeen == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < size; i++) { - varSeen[i] = -1; - } - for (i = 0; i < n; i++) { - index = (xVars[i])->index; - varSeen[manager->invperm[index]] = 0; - } - - if (S == one) { - if (m == max) - return(S); - result = selectMintermsFromUniverse(manager,varSeen,m); - if (result) - cuddRef(result); - FREE(varSeen); - } else { - mtable = st_init_table(st_ptrcmp,st_ptrhash); - if (mtable == NULL) { - (void) fprintf(manager->out, - "Cudd_SplitSet: out-of-memory.\n"); - FREE(varSeen); - manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - /* The nodes of BDD S are annotated by the number of minterms - ** in their onset. The node and the number of minterms in its - ** onset are stored in mtable. - */ - num = bddAnnotateMintermCount(manager,S,max,mtable); - if (m == num) { - st_foreach(mtable,cuddStCountfree,NIL(char)); - st_free_table(mtable); - FREE(varSeen); - return(S); - } - - result = cuddSplitSetRecur(manager,mtable,varSeen,S,m,max,0); - if (result) - cuddRef(result); - st_foreach(mtable,cuddStCountfree,NULL); - st_free_table(mtable); - FREE(varSeen); - } - } while (manager->reordered == 1); - - cuddDeref(result); - return(result); - -} /* end of Cudd_SplitSet */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_SplitSet.] - - Description [Implements the recursive step of Cudd_SplitSet. The - procedure recursively traverses the BDD and checks to see if any - node satisfies the minterm requirements as specified by 'n'. At any - node X, n is compared to the number of minterms in the onset of X's - children. If either of the child nodes have exactly n minterms, then - that node is returned; else, if n is greater than the onset of one - of the child nodes, that node is retained and the difference in the - number of minterms is extracted from the other child. In case n - minterms can be extracted from constant 1, the algorithm returns the - result with at most log(n) nodes.] - - SideEffects [The array 'varSeen' is updated at every recursive call - to set the variables traversed by the procedure.] - - SeeAlso [] - -******************************************************************************/ -DdNode* -cuddSplitSetRecur( - DdManager * manager, - st_table * mtable, - int * varSeen, - DdNode * p, - double n, - double max, - int index) -{ - DdNode *one, *zero, *N, *Nv; - DdNode *Nnv, *q, *r, *v; - DdNode *result; - double *dummy, numT, numE; - int variable, positive; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* If p is constant, extract n minterms from constant 1. The procedure by - ** construction guarantees that minterms will not be extracted from - ** constant 0. - */ - if (Cudd_IsConstant(p)) { - q = selectMintermsFromUniverse(manager,varSeen,n); - return(q); - } - - N = Cudd_Regular(p); - - /* Set variable as seen. */ - variable = N->index; - varSeen[manager->invperm[variable]] = -1; - - Nv = cuddT(N); - Nnv = cuddE(N); - if (Cudd_IsComplement(p)) { - Nv = Cudd_Not(Nv); - Nnv = Cudd_Not(Nnv); - } - - /* If both the children of 'p' are constants, extract n minterms from a - ** constant node. - */ - if (Cudd_IsConstant(Nv) && Cudd_IsConstant(Nnv)) { - q = selectMintermsFromUniverse(manager,varSeen,n); - if (q == NULL) { - return(NULL); - } - cuddRef(q); - r = cuddBddAndRecur(manager,p,q); - if (r == NULL) { - Cudd_RecursiveDeref(manager,q); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDeref(manager,q); - cuddDeref(r); - return(r); - } - - /* Lookup the # of minterms in the onset of the node from the table. */ - if (!Cudd_IsConstant(Nv)) { - st_lookup(mtable,(char *)Nv, (char **)&dummy); - numT = *dummy/(2*(1<size; - one = DD_ONE(manager); - zero = Cudd_Not(one); - - /* Count the number of variables not encountered so far in procedure - ** cuddSplitSetRecur. - */ - for (i = size-1; i >= 0; i--) { - if(varSeen[i] == 0) - numVars++; - } - vars = ALLOC(DdNode *, numVars); - if (!vars) { - manager->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - j = 0; - for (i = size-1; i >= 0; i--) { - if(varSeen[i] == 0) { - vars[j] = cuddUniqueInter(manager,manager->perm[i],one,zero); - cuddRef(vars[j]); - j++; - } - } - - /* Compute a function which has n minterms and depends on at most - ** numVars variables. - */ - result = mintermsFromUniverse(manager,vars,numVars,n, 0); - if (result) - cuddRef(result); - - for (i = 0; i < numVars; i++) - Cudd_RecursiveDeref(manager,vars[i]); - FREE(vars); - - return(result); - -} /* end of selectMintermsFromUniverse */ - - -/**Function******************************************************************** - - Synopsis [Recursive procedure to extract n mintems from constant 1.] - - Description [Recursive procedure to extract n mintems from constant 1.] - - SideEffects [None] - -******************************************************************************/ -static DdNode * -mintermsFromUniverse( - DdManager * manager, - DdNode ** vars, - int numVars, - double n, - int index) -{ - DdNode *one, *zero; - DdNode *q, *result; - double max, max2; - - statLine(manager); - one = DD_ONE(manager); - zero = Cudd_Not(one); - - max = pow(2.0, (double)numVars); - max2 = max / 2.0; - - if (n == max) - return(one); - if (n == 0.0) - return(zero); - /* if n == 2^(numVars-1), return a single variable */ - if (n == max2) - return vars[index]; - else if (n > max2) { - /* When n > 2^(numVars-1), a single variable vars[index] - ** contains 2^(numVars-1) minterms. The rest are extracted - ** from a constant with 1 less variable. - */ - q = mintermsFromUniverse(manager,vars,numVars-1,(n-max2),index+1); - if (q == NULL) - return(NULL); - cuddRef(q); - result = cuddBddIteRecur(manager,vars[index],one,q); - } else { - /* When n < 2^(numVars-1), a literal of variable vars[index] - ** is selected. The required n minterms are extracted from a - ** constant with 1 less variable. - */ - q = mintermsFromUniverse(manager,vars,numVars-1,n,index+1); - if (q == NULL) - return(NULL); - cuddRef(q); - result = cuddBddAndRecur(manager,vars[index],q); - } - - if (result == NULL) { - Cudd_RecursiveDeref(manager,q); - return(NULL); - } - cuddRef(result); - Cudd_RecursiveDeref(manager,q); - cuddDeref(result); - return(result); - -} /* end of mintermsFromUniverse */ - - -/**Function******************************************************************** - - Synopsis [Annotates every node in the BDD node with its minterm count.] - - Description [Annotates every node in the BDD node with its minterm count. - In this function, every node and the minterm count represented by it are - stored in a hash table.] - - SideEffects [Fills up 'table' with the pair .] - -******************************************************************************/ -static double -bddAnnotateMintermCount( - DdManager * manager, - DdNode * node, - double max, - st_table * table) -{ - - DdNode *N,*Nv,*Nnv; - register double min_v,min_nv; - register double min_N; - double *pmin; - double *dummy; - - statLine(manager); - N = Cudd_Regular(node); - if (cuddIsConstant(N)) { - if (node == DD_ONE(manager)) { - return(max); - } else { - return(0.0); - } - } - - if (st_lookup(table,(char *)node,(char **)&dummy)) { - return(*dummy); - } - - Nv = cuddT(N); - Nnv = cuddE(N); - if (N != node) { - Nv = Cudd_Not(Nv); - Nnv = Cudd_Not(Nnv); - } - - /* Recur on the two branches. */ - min_v = bddAnnotateMintermCount(manager,Nv,max,table) / 2.0; - if (min_v == (double)CUDD_OUT_OF_MEM) - return ((double)CUDD_OUT_OF_MEM); - min_nv = bddAnnotateMintermCount(manager,Nnv,max,table) / 2.0; - if (min_nv == (double)CUDD_OUT_OF_MEM) - return ((double)CUDD_OUT_OF_MEM); - min_N = min_v + min_nv; - - pmin = ALLOC(double,1); - if (pmin == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return((double)CUDD_OUT_OF_MEM); - } - *pmin = min_N; - - if (st_insert(table,(char *)node, (char *)pmin) == ST_OUT_OF_MEM) { - FREE(pmin); - return((double)CUDD_OUT_OF_MEM); - } - - return(min_N); - -} /* end of bddAnnotateMintermCount */ diff --git a/src/bdd/cudd/cuddSubsetHB.c b/src/bdd/cudd/cuddSubsetHB.c deleted file mode 100644 index 24d41ce5..00000000 --- a/src/bdd/cudd/cuddSubsetHB.c +++ /dev/null @@ -1,1311 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSubsetHB.c] - - PackageName [cudd] - - Synopsis [Procedure to subset the given BDD by choosing the heavier - branches] - - - Description [External procedures provided by this module: -
                -
              • Cudd_SubsetHeavyBranch() -
              • Cudd_SupersetHeavyBranch() -
              - Internal procedures included in this module: -
                -
              • cuddSubsetHeavyBranch() -
              - Static procedures included in this module: -
                -
              • ResizeCountMintermPages(); -
              • ResizeNodeDataPages() -
              • ResizeCountNodePages() -
              • SubsetCountMintermAux() -
              • SubsetCountMinterm() -
              • SubsetCountNodesAux() -
              • SubsetCountNodes() -
              • BuildSubsetBdd() -
              - ] - - SeeAlso [cuddSubsetSP.c] - - Author [Kavita Ravi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no - warranty about the suitability of this software for any - purpose. It is presented on an AS IS basis.] - -******************************************************************************/ - -#ifdef __STDC__ -#include -#else -#define DBL_MAX_EXP 1024 -#endif -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DEFAULT_PAGE_SIZE 2048 -#define DEFAULT_NODE_DATA_PAGE_SIZE 1024 -#define INITIAL_PAGES 128 - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/* data structure to store the information on each node. It keeps - * the number of minterms represented by the DAG rooted at this node - * in terms of the number of variables specified by the user, number - * of nodes in this DAG and the number of nodes of its child with - * lesser number of minterms that are not shared by the child with - * more minterms - */ -struct NodeData { - double *mintermPointer; - int *nodesPointer; - int *lightChildNodesPointer; -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -typedef struct NodeData NodeData_t; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static int memOut; -#ifdef DEBUG -static int num_calls; -#endif - -static DdNode *zero, *one; /* constant functions */ -static double **mintermPages; /* pointers to the pages */ -static int **nodePages; /* pointers to the pages */ -static int **lightNodePages; /* pointers to the pages */ -static double *currentMintermPage; /* pointer to the current - page */ -static double max; /* to store the 2^n value of the number - * of variables */ - -static int *currentNodePage; /* pointer to the current - page */ -static int *currentLightNodePage; /* pointer to the - * current page */ -static int pageIndex; /* index to next element */ -static int page; /* index to current page */ -static int pageSize = DEFAULT_PAGE_SIZE; /* page size */ -static int maxPages; /* number of page pointers */ - -static NodeData_t *currentNodeDataPage; /* pointer to the current - page */ -static int nodeDataPage; /* index to next element */ -static int nodeDataPageIndex; /* index to next element */ -static NodeData_t **nodeDataPages; /* index to current page */ -static int nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE; - /* page size */ -static int maxNodeDataPages; /* number of page pointers */ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void ResizeNodeDataPages ARGS(()); -static void ResizeCountMintermPages ARGS(()); -static void ResizeCountNodePages ARGS(()); -static double SubsetCountMintermAux ARGS((DdNode *node, double max, st_table *table)); -static st_table * SubsetCountMinterm ARGS((DdNode *node, int nvars)); -static int SubsetCountNodesAux ARGS((DdNode *node, st_table *table, double max)); -static int SubsetCountNodes ARGS((DdNode *node, st_table *table, int nvars)); -static void StoreNodes ARGS((st_table *storeTable, DdManager *dd, DdNode *node)); -static DdNode * BuildSubsetBdd ARGS((DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Extracts a dense subset from a BDD with the heavy branch - heuristic.] - - Description [Extracts a dense subset from a BDD. This procedure - builds a subset by throwing away one of the children of each node, - starting from the root, until the result is small enough. The child - that is eliminated from the result is the one that contributes the - fewer minterms. Returns a pointer to the BDD of the subset if - successful. NULL if the procedure runs out of memory. The parameter - numVars is the maximum number of variables to be used in minterm - calculation and node count calculation. The optimal number should - be as close as possible to the size of the support of f. However, - it is safe to pass the value returned by Cudd_ReadSize for numVars - when the number of variables is under 1023. If numVars is larger - than 1023, it will overflow. If a 0 parameter is passed then the - procedure will compute a value which will avoid overflow but will - cause underflow with 2046 variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_SubsetHeavyBranch( - DdManager * dd /* manager */, - DdNode * f /* function to be subset */, - int numVars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the subset */) -{ - DdNode *subset; - - memOut = 0; - do { - dd->reordered = 0; - subset = cuddSubsetHeavyBranch(dd, f, numVars, threshold); - } while ((dd->reordered == 1) && (!memOut)); - - return(subset); - -} /* end of Cudd_SubsetHeavyBranch */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense superset from a BDD with the heavy branch - heuristic.] - - Description [Extracts a dense superset from a BDD. The procedure is - identical to the subset procedure except for the fact that it - receives the complement of the given function. Extracting the subset - of the complement function is equivalent to extracting the superset - of the function. This procedure builds a superset by throwing away - one of the children of each node starting from the root of the - complement function, until the result is small enough. The child - that is eliminated from the result is the one that contributes the - fewer minterms. - Returns a pointer to the BDD of the superset if successful. NULL if - intermediate result causes the procedure to run out of memory. The - parameter numVars is the maximum number of variables to be used in - minterm calculation and node count calculation. The optimal number - should be as close as possible to the size of the support of f. - However, it is safe to pass the value returned by Cudd_ReadSize for - numVars when the number of variables is under 1023. If numVars is - larger than 1023, it will overflow. If a 0 parameter is passed then - the procedure will compute a value which will avoid overflow but - will cause underflow with 2046 variables or more.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_SupersetHeavyBranch( - DdManager * dd /* manager */, - DdNode * f /* function to be superset */, - int numVars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the superset */) -{ - DdNode *subset, *g; - - g = Cudd_Not(f); - memOut = 0; - do { - dd->reordered = 0; - subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold); - } while ((dd->reordered == 1) && (!memOut)); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_SupersetHeavyBranch */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [The main procedure that returns a subset by choosing the heavier - branch in the BDD.] - - Description [Here a subset BDD is built by throwing away one of the - children. Starting at root, annotate each node with the number of - minterms (in terms of the total number of variables specified - - numVars), number of nodes taken by the DAG rooted at this node and - number of additional nodes taken by the child that has the lesser - minterms. The child with the lower number of minterms is thrown away - and a dyanmic count of the nodes of the subset is kept. Once the - threshold is reached the subset is returned to the calling - procedure.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetHeavyBranch] - -******************************************************************************/ -DdNode * -cuddSubsetHeavyBranch( - DdManager * dd /* DD manager */, - DdNode * f /* current DD */, - int numVars /* maximum number of variables */, - int threshold /* threshold size for the subset */) -{ - - int i, *size; - st_table *visitedTable; - int numNodes; - NodeData_t *currNodeQual; - DdNode *subset; - double minN; - st_table *storeTable, *approxTable; - char *key, *value; - st_generator *stGen; - - if (f == NULL) { - fprintf(dd->err, "Cannot subset, nil object\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - - one = Cudd_ReadOne(dd); - zero = Cudd_Not(one); - - /* If user does not know numVars value, set it to the maximum - * exponent that the pow function can take. The -1 is due to the - * discrepancy in the value that pow takes and the value that - * log gives. - */ - if (numVars == 0) { - /* set default value */ - numVars = DBL_MAX_EXP - 1; - } - - if (Cudd_IsConstant(f)) { - return(f); - } - - max = pow(2.0, (double)numVars); - - /* Create visited table where structures for node data are allocated and - stored in a st_table */ - visitedTable = SubsetCountMinterm(f, numVars); - if ((visitedTable == NULL) || memOut) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - numNodes = SubsetCountNodes(f, visitedTable, numVars); - if (memOut) { - (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - - if (st_lookup(visitedTable, (char *)f, (char **)&currNodeQual)) { - minN = *(((NodeData_t *)currNodeQual)->mintermPointer); - } else { - fprintf(dd->err, - "Something is wrong, ought to be node quality table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - } - - size = ALLOC(int, 1); - if (size == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - *size = numNodes; - -#ifdef DEBUG - num_calls = 0; -#endif - /* table to store nodes being created. */ - storeTable = st_init_table(st_ptrcmp, st_ptrhash); - /* insert the constant */ - cuddRef(one); - if (st_insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) == - ST_OUT_OF_MEM) { - fprintf(dd->out, "Something wrong, st_table insert failed\n"); - } - /* table to store approximations of nodes */ - approxTable = st_init_table(st_ptrcmp, st_ptrhash); - subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold, - storeTable, approxTable); - if (subset != NULL) { - cuddRef(subset); - } - - stGen = st_init_gen(approxTable); - if (stGen == NULL) { - st_free_table(approxTable); - return(NULL); - } - while(st_gen(stGen, (char **)&key, (char **)&value)) { - Cudd_RecursiveDeref(dd, (DdNode *)value); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(approxTable); - - stGen = st_init_gen(storeTable); - if (stGen == NULL) { - st_free_table(storeTable); - return(NULL); - } - while(st_gen(stGen, (char **)&key, (char **)&value)) { - Cudd_RecursiveDeref(dd, (DdNode *)key); - } - st_free_gen(stGen); stGen = NULL; - st_free_table(storeTable); - - for (i = 0; i <= page; i++) { - FREE(mintermPages[i]); - } - FREE(mintermPages); - for (i = 0; i <= page; i++) { - FREE(nodePages[i]); - } - FREE(nodePages); - for (i = 0; i <= page; i++) { - FREE(lightNodePages[i]); - } - FREE(lightNodePages); - for (i = 0; i <= nodeDataPage; i++) { - FREE(nodeDataPages[i]); - } - FREE(nodeDataPages); - st_free_table(visitedTable); - FREE(size); -#if 0 - (void) Cudd_DebugCheck(dd); - (void) Cudd_CheckKeys(dd); -#endif - - if (subset != NULL) { -#ifdef DD_DEBUG - if (!Cudd_bddLeq(dd, subset, f)) { - fprintf(dd->err, "Wrong subset\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } -#endif - cuddDeref(subset); - return(subset); - } else { - return(NULL); - } -} /* end of cuddSubsetHeavyBranch */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Resize the number of pages allocated to store the node data.] - - Description [Resize the number of pages allocated to store the node data - The procedure moves the counter to the next page when the end of - the page is reached and allocates new pages when necessary.] - - SideEffects [Changes the size of pages, page, page index, maximum - number of pages freeing stuff in case of memory out. ] - - SeeAlso [] - -******************************************************************************/ -static void -ResizeNodeDataPages( - ) -{ - int i; - NodeData_t **newNodeDataPages; - - nodeDataPage++; - /* If the current page index is larger than the number of pages - * allocated, allocate a new page array. Page numbers are incremented by - * INITIAL_PAGES - */ - if (nodeDataPage == maxNodeDataPages) { - newNodeDataPages = ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES); - if (newNodeDataPages == NULL) { - for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - memOut = 1; - return; - } else { - for (i = 0; i < maxNodeDataPages; i++) { - newNodeDataPages[i] = nodeDataPages[i]; - } - /* Increase total page count */ - maxNodeDataPages += INITIAL_PAGES; - FREE(nodeDataPages); - nodeDataPages = newNodeDataPages; - } - } - /* Allocate a new page */ - currentNodeDataPage = nodeDataPages[nodeDataPage] = - ALLOC(NodeData_t ,nodeDataPageSize); - if (currentNodeDataPage == NULL) { - for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - memOut = 1; - return; - } - /* reset page index */ - nodeDataPageIndex = 0; - return; - -} /* end of ResizeNodeDataPages */ - - -/**Function******************************************************************** - - Synopsis [Resize the number of pages allocated to store the minterm - counts. ] - - Description [Resize the number of pages allocated to store the minterm - counts. The procedure moves the counter to the next page when the - end of the page is reached and allocates new pages when necessary.] - - SideEffects [Changes the size of minterm pages, page, page index, maximum - number of pages freeing stuff in case of memory out. ] - - SeeAlso [] - -******************************************************************************/ -static void -ResizeCountMintermPages( - ) -{ - int i; - double **newMintermPages; - - page++; - /* If the current page index is larger than the number of pages - * allocated, allocate a new page array. Page numbers are incremented by - * INITIAL_PAGES - */ - if (page == maxPages) { - newMintermPages = ALLOC(double *,maxPages + INITIAL_PAGES); - if (newMintermPages == NULL) { - for (i = 0; i < page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - memOut = 1; - return; - } else { - for (i = 0; i < maxPages; i++) { - newMintermPages[i] = mintermPages[i]; - } - /* Increase total page count */ - maxPages += INITIAL_PAGES; - FREE(mintermPages); - mintermPages = newMintermPages; - } - } - /* Allocate a new page */ - currentMintermPage = mintermPages[page] = ALLOC(double,pageSize); - if (currentMintermPage == NULL) { - for (i = 0; i < page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - memOut = 1; - return; - } - /* reset page index */ - pageIndex = 0; - return; - -} /* end of ResizeCountMintermPages */ - - -/**Function******************************************************************** - - Synopsis [Resize the number of pages allocated to store the node counts.] - - Description [Resize the number of pages allocated to store the node counts. - The procedure moves the counter to the next page when the end of - the page is reached and allocates new pages when necessary.] - - SideEffects [Changes the size of pages, page, page index, maximum - number of pages freeing stuff in case of memory out.] - - SeeAlso [] - -******************************************************************************/ -static void -ResizeCountNodePages( - ) -{ - int i; - int **newNodePages; - - page++; - - /* If the current page index is larger than the number of pages - * allocated, allocate a new page array. The number of pages is incremented - * by INITIAL_PAGES. - */ - if (page == maxPages) { - newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES); - if (newNodePages == NULL) { - for (i = 0; i < page; i++) FREE(nodePages[i]); - FREE(nodePages); - for (i = 0; i < page; i++) FREE(lightNodePages[i]); - FREE(lightNodePages); - memOut = 1; - return; - } else { - for (i = 0; i < maxPages; i++) { - newNodePages[i] = nodePages[i]; - } - FREE(nodePages); - nodePages = newNodePages; - } - - newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES); - if (newNodePages == NULL) { - for (i = 0; i < page; i++) FREE(nodePages[i]); - FREE(nodePages); - for (i = 0; i < page; i++) FREE(lightNodePages[i]); - FREE(lightNodePages); - memOut = 1; - return; - } else { - for (i = 0; i < maxPages; i++) { - newNodePages[i] = lightNodePages[i]; - } - FREE(lightNodePages); - lightNodePages = newNodePages; - } - /* Increase total page count */ - maxPages += INITIAL_PAGES; - } - /* Allocate a new page */ - currentNodePage = nodePages[page] = ALLOC(int,pageSize); - if (currentNodePage == NULL) { - for (i = 0; i < page; i++) FREE(nodePages[i]); - FREE(nodePages); - for (i = 0; i < page; i++) FREE(lightNodePages[i]); - FREE(lightNodePages); - memOut = 1; - return; - } - /* Allocate a new page */ - currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); - if (currentLightNodePage == NULL) { - for (i = 0; i <= page; i++) FREE(nodePages[i]); - FREE(nodePages); - for (i = 0; i < page; i++) FREE(lightNodePages[i]); - FREE(lightNodePages); - memOut = 1; - return; - } - /* reset page index */ - pageIndex = 0; - return; - -} /* end of ResizeCountNodePages */ - - -/**Function******************************************************************** - - Synopsis [Recursively counts minterms of each node in the DAG.] - - Description [Recursively counts minterms of each node in the DAG. - Similar to the cuddCountMintermAux which recursively counts the - number of minterms for the dag rooted at each node in terms of the - total number of variables (max). This procedure creates the node - data structure and stores the minterm count as part of the node - data structure. ] - - SideEffects [Creates structures of type node quality and fills the st_table] - - SeeAlso [SubsetCountMinterm] - -******************************************************************************/ -static double -SubsetCountMintermAux( - DdNode * node /* function to analyze */, - double max /* number of minterms of constant 1 */, - st_table * table /* visitedTable table */) -{ - - DdNode *N,*Nv,*Nnv; /* nodes to store cofactors */ - double min,*pmin; /* minterm count */ - double min1, min2; /* minterm count */ - NodeData_t *dummy; - NodeData_t *newEntry; - int i; - -#ifdef DEBUG - num_calls++; -#endif - - /* Constant case */ - if (Cudd_IsConstant(node)) { - if (node == zero) { - return(0.0); - } else { - return(max); - } - } else { - - /* check if entry for this node exists */ - if (st_lookup(table,(char *)node, (char **)&dummy)) { - min = *(dummy->mintermPointer); - return(min); - } - - /* Make the node regular to extract cofactors */ - N = Cudd_Regular(node); - - /* store the cofactors */ - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - min1 = SubsetCountMintermAux(Nv, max,table)/2.0; - if (memOut) return(0.0); - min2 = SubsetCountMintermAux(Nnv,max,table)/2.0; - if (memOut) return(0.0); - min = (min1+min2); - - /* if page index is at the bottom, then create a new page */ - if (pageIndex == pageSize) ResizeCountMintermPages(); - if (memOut) { - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0.0); - } - - /* point to the correct location in the page */ - pmin = currentMintermPage+pageIndex; - pageIndex++; - - /* store the minterm count of this node in the page */ - *pmin = min; - - /* Note I allocate the struct here. Freeing taken care of later */ - if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages(); - if (memOut) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - st_free_table(table); - return(0.0); - } - - newEntry = currentNodeDataPage + nodeDataPageIndex; - nodeDataPageIndex++; - - /* points to the correct location in the page */ - newEntry->mintermPointer = pmin; - /* initialize this field of the Node Quality structure */ - newEntry->nodesPointer = NULL; - - /* insert entry for the node in the table */ - if (st_insert(table,(char *)node, (char *)newEntry) == ST_OUT_OF_MEM) { - memOut = 1; - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0.0); - } - return(min); - } - -} /* end of SubsetCountMintermAux */ - - -/**Function******************************************************************** - - Synopsis [Counts minterms of each node in the DAG] - - Description [Counts minterms of each node in the DAG. Similar to the - Cudd_CountMinterm procedure except this returns the minterm count for - all the nodes in the bdd in an st_table.] - - SideEffects [none] - - SeeAlso [SubsetCountMintermAux] - -******************************************************************************/ -static st_table * -SubsetCountMinterm( - DdNode * node /* function to be analyzed */, - int nvars /* number of variables node depends on */) -{ - st_table *table; - double num; - int i; - - -#ifdef DEBUG - num_calls = 0; -#endif - - max = pow(2.0,(double) nvars); - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) goto OUT_OF_MEM; - maxPages = INITIAL_PAGES; - mintermPages = ALLOC(double *,maxPages); - if (mintermPages == NULL) { - st_free_table(table); - goto OUT_OF_MEM; - } - page = 0; - currentMintermPage = ALLOC(double,pageSize); - mintermPages[page] = currentMintermPage; - if (currentMintermPage == NULL) { - FREE(mintermPages); - st_free_table(table); - goto OUT_OF_MEM; - } - pageIndex = 0; - maxNodeDataPages = INITIAL_PAGES; - nodeDataPages = ALLOC(NodeData_t *, maxNodeDataPages); - if (nodeDataPages == NULL) { - for (i = 0; i <= page ; i++) FREE(mintermPages[i]); - FREE(mintermPages); - st_free_table(table); - goto OUT_OF_MEM; - } - nodeDataPage = 0; - currentNodeDataPage = ALLOC(NodeData_t ,nodeDataPageSize); - nodeDataPages[nodeDataPage] = currentNodeDataPage; - if (currentNodeDataPage == NULL) { - for (i = 0; i <= page ; i++) FREE(mintermPages[i]); - FREE(mintermPages); - FREE(nodeDataPages); - st_free_table(table); - goto OUT_OF_MEM; - } - nodeDataPageIndex = 0; - - num = SubsetCountMintermAux(node,max,table); - if (memOut) goto OUT_OF_MEM; - return(table); - -OUT_OF_MEM: - memOut = 1; - return(NULL); - -} /* end of SubsetCountMinterm */ - - -/**Function******************************************************************** - - Synopsis [Recursively counts the number of nodes under the dag. - Also counts the number of nodes under the lighter child of - this node.] - - Description [Recursively counts the number of nodes under the dag. - Also counts the number of nodes under the lighter child of - this node. . Note that the same dag may be the lighter child of two - different nodes and have different counts. As with the minterm counts, - the node counts are stored in pages to be space efficient and the - address for these node counts are stored in an st_table associated - to each node. ] - - SideEffects [Updates the node data table with node counts] - - SeeAlso [SubsetCountNodes] - -******************************************************************************/ -static int -SubsetCountNodesAux( - DdNode * node /* current node */, - st_table * table /* table to update node count, also serves as visited table. */, - double max /* maximum number of variables */) -{ - int tval, eval, i; - DdNode *N, *Nv, *Nnv; - double minNv, minNnv; - NodeData_t *dummyN, *dummyNv, *dummyNnv, *dummyNBar; - int *pmin, *pminBar, *val; - - if ((node == NULL) || Cudd_IsConstant(node)) - return(0); - - /* if this node has been processed do nothing */ - if (st_lookup(table, (char *)node, (char **)&dummyN) == 1) { - val = dummyN->nodesPointer; - if (val != NULL) - return(0); - } else { - return(0); - } - - N = Cudd_Regular(node); - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - /* find the minterm counts for the THEN and ELSE branches */ - if (Cudd_IsConstant(Nv)) { - if (Nv == zero) { - minNv = 0.0; - } else { - minNv = max; - } - } else { - if (st_lookup(table, (char *)Nv, (char **)&dummyNv) == 1) - minNv = *(dummyNv->mintermPointer); - else { - return(0); - } - } - if (Cudd_IsConstant(Nnv)) { - if (Nnv == zero) { - minNnv = 0.0; - } else { - minNnv = max; - } - } else { - if (st_lookup(table, (char *)Nnv, (char **)&dummyNnv) == 1) { - minNnv = *(dummyNnv->mintermPointer); - } - else { - return(0); - } - } - - - /* recur based on which has larger minterm, */ - if (minNv >= minNnv) { - tval = SubsetCountNodesAux(Nv, table, max); - if (memOut) return(0); - eval = SubsetCountNodesAux(Nnv, table, max); - if (memOut) return(0); - - /* store the node count of the lighter child. */ - if (pageIndex == pageSize) ResizeCountNodePages(); - if (memOut) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0); - } - pmin = currentLightNodePage + pageIndex; - *pmin = eval; /* Here the ELSE child is lighter */ - dummyN->lightChildNodesPointer = pmin; - - } else { - eval = SubsetCountNodesAux(Nnv, table, max); - if (memOut) return(0); - tval = SubsetCountNodesAux(Nv, table, max); - if (memOut) return(0); - - /* store the node count of the lighter child. */ - if (pageIndex == pageSize) ResizeCountNodePages(); - if (memOut) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0); - } - pmin = currentLightNodePage + pageIndex; - *pmin = tval; /* Here the THEN child is lighter */ - dummyN->lightChildNodesPointer = pmin; - - } - /* updating the page index for node count storage. */ - pmin = currentNodePage + pageIndex; - *pmin = tval + eval + 1; - dummyN->nodesPointer = pmin; - - /* pageIndex is parallel page index for count_nodes and count_lightNodes */ - pageIndex++; - - /* if this node has been reached first, it belongs to a heavier - branch. Its complement will be reached later on a lighter branch. - Hence the complement has zero node count. */ - - if (st_lookup(table, (char *)Cudd_Not(node), (char **)&dummyNBar) == 1) { - if (pageIndex == pageSize) ResizeCountNodePages(); - if (memOut) { - for (i = 0; i < page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0); - } - pminBar = currentLightNodePage + pageIndex; - *pminBar = 0; - dummyNBar->lightChildNodesPointer = pminBar; - /* The lighter child has less nodes than the parent. - * So if parent 0 then lighter child zero - */ - if (pageIndex == pageSize) ResizeCountNodePages(); - if (memOut) { - for (i = 0; i < page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - st_free_table(table); - return(0); - } - pminBar = currentNodePage + pageIndex; - *pminBar = 0; - dummyNBar->nodesPointer = pminBar ; /* maybe should point to zero */ - - pageIndex++; - } - return(*pmin); -} /*end of SubsetCountNodesAux */ - - -/**Function******************************************************************** - - Synopsis [Counts the nodes under the current node and its lighter child] - - Description [Counts the nodes under the current node and its lighter - child. Calls a recursive procedure to count the number of nodes of - a DAG rooted at a particular node and the number of nodes taken by its - lighter child.] - - SideEffects [None] - - SeeAlso [SubsetCountNodesAux] - -******************************************************************************/ -static int -SubsetCountNodes( - DdNode * node /* function to be analyzed */, - st_table * table /* node quality table */, - int nvars /* number of variables node depends on */) -{ - int num; - int i; - -#ifdef DEBUG - num_calls = 0; -#endif - - max = pow(2.0,(double) nvars); - maxPages = INITIAL_PAGES; - nodePages = ALLOC(int *,maxPages); - if (nodePages == NULL) { - goto OUT_OF_MEM; - } - - lightNodePages = ALLOC(int *,maxPages); - if (lightNodePages == NULL) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - FREE(nodePages); - goto OUT_OF_MEM; - } - - page = 0; - currentNodePage = nodePages[page] = ALLOC(int,pageSize); - if (currentNodePage == NULL) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - FREE(lightNodePages); - FREE(nodePages); - goto OUT_OF_MEM; - } - - currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); - if (currentLightNodePage == NULL) { - for (i = 0; i <= page; i++) FREE(mintermPages[i]); - FREE(mintermPages); - for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); - FREE(nodeDataPages); - FREE(currentNodePage); - FREE(lightNodePages); - FREE(nodePages); - goto OUT_OF_MEM; - } - - pageIndex = 0; - num = SubsetCountNodesAux(node,table,max); - if (memOut) goto OUT_OF_MEM; - return(num); - -OUT_OF_MEM: - memOut = 1; - return(0); - -} /* end of SubsetCountNodes */ - - -/**Function******************************************************************** - - Synopsis [Procedure to recursively store nodes that are retained in the subset.] - - Description [rocedure to recursively store nodes that are retained in the subset.] - - SideEffects [None] - - SeeAlso [StoreNodes] - -******************************************************************************/ -static void -StoreNodes( - st_table * storeTable, - DdManager * dd, - DdNode * node) -{ - char *dummy; - DdNode *N, *Nt, *Ne; - if (Cudd_IsConstant(dd)) { - return; - } - N = Cudd_Regular(node); - if (st_lookup(storeTable, (char *)N, (char **)&dummy)) { - return; - } - cuddRef(N); - if (st_insert(storeTable, (char *)N, NIL(char)) == ST_OUT_OF_MEM) { - fprintf(dd->err,"Something wrong, st_table insert failed\n"); - } - - Nt = Cudd_T(N); - Ne = Cudd_E(N); - - StoreNodes(storeTable, dd, Nt); - StoreNodes(storeTable, dd, Ne); - return; - -} - - -/**Function******************************************************************** - - Synopsis [Builds the subset BDD using the heavy branch method.] - - Description [The procedure carries out the building of the subset BDD - starting at the root. Using the three different counts labelling each node, - the procedure chooses the heavier branch starting from the root and keeps - track of the number of nodes it discards at each step, thus keeping count - of the size of the subset BDD dynamically. Once the threshold is satisfied, - the procedure then calls ITE to build the BDD.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -BuildSubsetBdd( - DdManager * dd /* DD manager */, - DdNode * node /* current node */, - int * size /* current size of the subset */, - st_table * visitedTable /* visited table storing all node data */, - int threshold, - st_table * storeTable, - st_table * approxTable) -{ - - DdNode *Nv, *Nnv, *N, *topv, *neW; - double minNv, minNnv; - NodeData_t *currNodeQual; - NodeData_t *currNodeQualT; - NodeData_t *currNodeQualE; - DdNode *ThenBranch, *ElseBranch; - unsigned int topid; - char *dummy; - -#ifdef DEBUG - num_calls++; -#endif - /*If the size of the subset is below the threshold, dont do - anything. */ - if ((*size) <= threshold) { - /* store nodes below this, so we can recombine if possible */ - StoreNodes(storeTable, dd, node); - return(node); - } - - if (Cudd_IsConstant(node)) - return(node); - - /* Look up minterm count for this node. */ - if (!st_lookup(visitedTable, (char *)node, (char **)&currNodeQual)) { - fprintf(dd->err, - "Something is wrong, ought to be in node quality table\n"); - } - - /* Get children. */ - N = Cudd_Regular(node); - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - /* complement if necessary */ - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - if (!Cudd_IsConstant(Nv)) { - /* find out minterms and nodes contributed by then child */ - if (!st_lookup(visitedTable, (char *)Nv, - (char **)&currNodeQualT)) { - fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - else { - minNv = *(((NodeData_t *)currNodeQualT)->mintermPointer); - } - } else { - if (Nv == zero) { - minNv = 0; - } else { - minNv = max; - } - } - if (!Cudd_IsConstant(Nnv)) { - /* find out minterms and nodes contributed by else child */ - if (!st_lookup(visitedTable, (char *)Nnv, (char **)&currNodeQualE)) { - fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } else { - minNnv = *(((NodeData_t *)currNodeQualE)->mintermPointer); - } - } else { - if (Nnv == zero) { - minNnv = 0; - } else { - minNnv = max; - } - } - - /* keep track of size of subset by subtracting the number of - * differential nodes contributed by lighter child - */ - *size = (*(size)) - (int)*(currNodeQual->lightChildNodesPointer); - if (minNv >= minNnv) { /*SubsetCountNodesAux procedure takes - the Then branch in case of a tie */ - - /* recur with the Then branch */ - ThenBranch = (DdNode *)BuildSubsetBdd(dd, Nv, size, - visitedTable, threshold, storeTable, approxTable); - if (ThenBranch == NULL) { - return(NULL); - } - cuddRef(ThenBranch); - /* The Else branch is either a node that already exists in the - * subset, or one whose approximation has been computed, or - * Zero. - */ - if (st_lookup(storeTable, (char *)Cudd_Regular(Nnv), (char **)&dummy)) { - ElseBranch = Nnv; - cuddRef(ElseBranch); - } else { - if (st_lookup(approxTable, (char *)Nnv, (char **)&dummy)) { - ElseBranch = (DdNode *)dummy; - cuddRef(ElseBranch); - } else { - ElseBranch = zero; - cuddRef(ElseBranch); - } - } - - } - else { - /* recur with the Else branch */ - ElseBranch = (DdNode *)BuildSubsetBdd(dd, Nnv, size, - visitedTable, threshold, storeTable, approxTable); - if (ElseBranch == NULL) { - return(NULL); - } - cuddRef(ElseBranch); - /* The Then branch is either a node that already exists in the - * subset, or one whose approximation has been computed, or - * Zero. - */ - if (st_lookup(storeTable, (char *)Cudd_Regular(Nv), (char **)&dummy)) { - ThenBranch = Nv; - cuddRef(ThenBranch); - } else { - if (st_lookup(approxTable, (char *)Nv, (char **)&dummy)) { - ThenBranch = (DdNode *)dummy; - cuddRef(ThenBranch); - } else { - ThenBranch = zero; - cuddRef(ThenBranch); - } - } - } - - /* construct the Bdd with the top variable and the two children */ - topid = Cudd_NodeReadIndex(N); - topv = Cudd_ReadVars(dd, topid); - cuddRef(topv); - neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); - if (neW != NULL) { - cuddRef(neW); - } - Cudd_RecursiveDeref(dd, topv); - Cudd_RecursiveDeref(dd, ThenBranch); - Cudd_RecursiveDeref(dd, ElseBranch); - - - if (neW == NULL) - return(NULL); - else { - /* store this node in the store table */ - if (!st_lookup(storeTable, (char *)Cudd_Regular(neW), (char **)&dummy)) { - cuddRef(neW); - st_insert(storeTable, (char *)Cudd_Regular(neW), (char *)NIL(char)); - - } - /* store the approximation for this node */ - if (N != Cudd_Regular(neW)) { - if (st_lookup(approxTable, (char *)node, (char **)&dummy)) { - fprintf(dd->err, "This node should not be in the approximated table\n"); - } else { - cuddRef(neW); - st_insert(approxTable, (char *)node, (char *)neW); - } - } - cuddDeref(neW); - return(neW); - } -} /* end of BuildSubsetBdd */ - diff --git a/src/bdd/cudd/cuddSubsetSP.c b/src/bdd/cudd/cuddSubsetSP.c deleted file mode 100644 index 55ee3470..00000000 --- a/src/bdd/cudd/cuddSubsetSP.c +++ /dev/null @@ -1,1624 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSubsetSP.c] - - PackageName [cudd] - - Synopsis [Procedure to subset the given BDD choosing the shortest paths - (largest cubes) in the BDD.] - - - Description [External procedures included in this module: -
                -
              • Cudd_SubsetShortPaths() -
              • Cudd_SupersetShortPaths() -
              - Internal procedures included in this module: -
                -
              • cuddSubsetShortPaths() -
              - Static procedures included in this module: -
                -
              • BuildSubsetBdd() -
              • CreatePathTable() -
              • AssessPathLength() -
              • CreateTopDist() -
              • CreateBotDist() -
              • ResizeNodeDistPages() -
              • ResizeQueuePages() -
              • stPathTableDdFree() -
              - ] - - SeeAlso [cuddSubsetHB.c] - - Author [Kavita Ravi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DEFAULT_PAGE_SIZE 2048 /* page size to store the BFS queue element type */ -#define DEFAULT_NODE_DIST_PAGE_SIZE 2048 /* page sizesto store NodeDist_t type */ -#define MAXSHORTINT ((DdHalfWord) ~0) /* constant defined to store - * maximum distance of a node - * from the root or the - * constant - */ -#define INITIAL_PAGES 128 /* number of initial pages for the - * queue/NodeDist_t type */ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/* structure created to store subset results for each node and distances with - * odd and even parity of the node from the root and sink. Main data structure - * in this procedure. - */ -struct NodeDist{ - DdHalfWord oddTopDist; - DdHalfWord evenTopDist; - DdHalfWord oddBotDist; - DdHalfWord evenBotDist; - DdNode *regResult; - DdNode *compResult; -}; - -/* assorted information needed by the BuildSubsetBdd procedure. */ -struct AssortedInfo { - unsigned int maxpath; - int findShortestPath; - int thresholdReached; - st_table *maxpathTable; - int threshold; -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -typedef struct NodeDist NodeDist_t; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -#ifdef DD_DEBUG -static int numCalls; -static int hits; -static int thishit; -#endif - - -static int memOut; /* flag to indicate out of memory */ -static DdNode *zero, *one; /* constant functions */ - -static NodeDist_t **nodeDistPages; /* pointers to the pages */ -static int nodeDistPageIndex; /* index to next element */ -static int nodeDistPage; /* index to current page */ -static int nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE; /* page size */ -static int maxNodeDistPages; /* number of page pointers */ -static NodeDist_t *currentNodeDistPage; /* current page */ - -static DdNode ***queuePages; /* pointers to the pages */ -static int queuePageIndex; /* index to next element */ -static int queuePage; /* index to current page */ -static int queuePageSize = DEFAULT_PAGE_SIZE; /* page size */ -static int maxQueuePages; /* number of page pointers */ -static DdNode **currentQueuePage; /* current page */ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void ResizeNodeDistPages ARGS(()); -static void ResizeQueuePages ARGS(()); -static void CreateTopDist ARGS((st_table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp)); -static int CreateBotDist ARGS((DdNode *node, st_table *pathTable, unsigned int *pathLengthArray, FILE *fp)); -static st_table * CreatePathTable ARGS((DdNode *node, unsigned int *pathLengthArray, FILE *fp)); -static unsigned int AssessPathLength ARGS((unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp)); -static DdNode * BuildSubsetBdd ARGS((DdManager *dd, st_table *pathTable, DdNode *node, struct AssortedInfo *info, st_table *subsetNodeTable)); -static enum st_retval stPathTableDdFree ARGS((char *key, char *value, char *arg)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of Exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense subset from a BDD with the shortest paths - heuristic.] - - Description [Extracts a dense subset from a BDD. This procedure - tries to preserve the shortest paths of the input BDD, because they - give many minterms and contribute few nodes. This procedure may - increase the number of nodes in trying to create the subset or - reduce the number of nodes due to recombination as compared to the - original BDD. Hence the threshold may not be strictly adhered to. In - practice, recombination overshadows the increase in the number of - nodes and results in small BDDs as compared to the threshold. The - hardlimit specifies whether threshold needs to be strictly adhered - to. If it is set to 1, the procedure ensures that result is never - larger than the specified limit but may be considerably less than - the threshold. Returns a pointer to the BDD for the subset if - successful; NULL otherwise. The value for numVars should be as - close as possible to the size of the support of f for better - efficiency. However, it is safe to pass the value returned by - Cudd_ReadSize for numVars. If 0 is passed, then the value returned - by Cudd_ReadSize is used.] - - SideEffects [None] - - SeeAlso [Cudd_SupersetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_SubsetShortPaths( - DdManager * dd /* manager */, - DdNode * f /* function to be subset */, - int numVars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the subset */, - int hardlimit /* flag: 1 if threshold is a hard limit */) -{ - DdNode *subset; - - memOut = 0; - do { - dd->reordered = 0; - subset = cuddSubsetShortPaths(dd, f, numVars, threshold, hardlimit); - } while((dd->reordered ==1) && (!memOut)); - - return(subset); - -} /* end of Cudd_SubsetShortPaths */ - - -/**Function******************************************************************** - - Synopsis [Extracts a dense superset from a BDD with the shortest paths - heuristic.] - - Description [Extracts a dense superset from a BDD. The procedure is - identical to the subset procedure except for the fact that it - receives the complement of the given function. Extracting the subset - of the complement function is equivalent to extracting the superset - of the function. This procedure tries to preserve the shortest - paths of the complement BDD, because they give many minterms and - contribute few nodes. This procedure may increase the number of - nodes in trying to create the superset or reduce the number of nodes - due to recombination as compared to the original BDD. Hence the - threshold may not be strictly adhered to. In practice, recombination - overshadows the increase in the number of nodes and results in small - BDDs as compared to the threshold. The hardlimit specifies whether - threshold needs to be strictly adhered to. If it is set to 1, the - procedure ensures that result is never larger than the specified - limit but may be considerably less than the threshold. Returns a - pointer to the BDD for the superset if successful; NULL - otherwise. The value for numVars should be as close as possible to - the size of the support of f for better efficiency. However, it is - safe to pass the value returned by Cudd_ReadSize for numVar. If 0 - is passed, then the value returned by Cudd_ReadSize is used.] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize] - -******************************************************************************/ -DdNode * -Cudd_SupersetShortPaths( - DdManager * dd /* manager */, - DdNode * f /* function to be superset */, - int numVars /* number of variables in the support of f */, - int threshold /* maximum number of nodes in the subset */, - int hardlimit /* flag: 1 if threshold is a hard limit */) -{ - DdNode *subset, *g; - - g = Cudd_Not(f); - memOut = 0; - do { - dd->reordered = 0; - subset = cuddSubsetShortPaths(dd, g, numVars, threshold, hardlimit); - } while((dd->reordered ==1) && (!memOut)); - - return(Cudd_NotCond(subset, (subset != NULL))); - -} /* end of Cudd_SupersetShortPaths */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [The outermost procedure to return a subset of the given BDD - with the shortest path lengths.] - - Description [The outermost procedure to return a subset of the given - BDD with the largest cubes. The path lengths are calculated, the maximum - allowable path length is determined and the number of nodes of this - path length that can be used to build a subset. If the threshold is - larger than the size of the original BDD, the original BDD is - returned. ] - - SideEffects [None] - - SeeAlso [Cudd_SubsetShortPaths] - -******************************************************************************/ -DdNode * -cuddSubsetShortPaths( - DdManager * dd /* DD manager */, - DdNode * f /* function to be subset */, - int numVars /* total number of variables in consideration */, - int threshold /* maximum number of nodes allowed in the subset */, - int hardlimit /* flag determining whether thershold should be respected strictly */) -{ - st_table *pathTable; - DdNode *N, *subset; - - unsigned int *pathLengthArray; - unsigned int maxpath, oddLen, evenLen, pathLength, *excess; - int i; - NodeDist_t *nodeStat; - struct AssortedInfo *info; - st_table *subsetNodeTable; - - one = DD_ONE(dd); - zero = Cudd_Not(one); - - if (numVars == 0) { - /* set default value */ - numVars = Cudd_ReadSize(dd); - } - - if (threshold > numVars) { - threshold = threshold - numVars; - } - if (f == NULL) { - fprintf(dd->err, "Cannot partition, nil object\n"); - dd->errorCode = CUDD_INVALID_ARG; - return(NULL); - } - if (Cudd_IsConstant(f)) - return (f); - - pathLengthArray = ALLOC(unsigned int, numVars+1); - for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0; - - -#ifdef DD_DEBUG - numCalls = 0; -#endif - - pathTable = CreatePathTable(f, pathLengthArray, dd->err); - - if ((pathTable == NULL) || (memOut)) { - if (pathTable != NULL) - st_free_table(pathTable); - FREE(pathLengthArray); - return (NIL(DdNode)); - } - - excess = ALLOC(unsigned int, 1); - *excess = 0; - maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess, - dd->err); - - if (maxpath != (unsigned) (numVars + 1)) { - - info = ALLOC(struct AssortedInfo, 1); - info->maxpath = maxpath; - info->findShortestPath = 0; - info->thresholdReached = *excess; - info->maxpathTable = st_init_table(st_ptrcmp, st_ptrhash); - info->threshold = threshold; - -#ifdef DD_DEBUG - (void) fprintf(dd->out, "Path length array\n"); - for (i = 0; i < (numVars+1); i++) { - if (pathLengthArray[i]) - (void) fprintf(dd->out, "%d ",i); - } - (void) fprintf(dd->out, "\n"); - for (i = 0; i < (numVars+1); i++) { - if (pathLengthArray[i]) - (void) fprintf(dd->out, "%d ",pathLengthArray[i]); - } - (void) fprintf(dd->out, "\n"); - (void) fprintf(dd->out, "Maxpath = %d, Thresholdreached = %d\n", - maxpath, info->thresholdReached); -#endif - - N = Cudd_Regular(f); - if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { - fprintf(dd->err, "Something wrong, root node must be in table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } else { - if ((nodeStat->oddTopDist != MAXSHORTINT) && - (nodeStat->oddBotDist != MAXSHORTINT)) - oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); - else - oddLen = MAXSHORTINT; - - if ((nodeStat->evenTopDist != MAXSHORTINT) && - (nodeStat->evenBotDist != MAXSHORTINT)) - evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); - else - evenLen = MAXSHORTINT; - - pathLength = (oddLen <= evenLen) ? oddLen : evenLen; - if (pathLength > maxpath) { - (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %d, %d\n", maxpath, pathLength); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - } - -#ifdef DD_DEBUG - numCalls = 0; - hits = 0; - thishit = 0; -#endif - /* initialize a table to store computed nodes */ - if (hardlimit) { - subsetNodeTable = st_init_table(st_ptrcmp, st_ptrhash); - } else { - subsetNodeTable = NIL(st_table); - } - subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable); - if (subset != NULL) { - cuddRef(subset); - } - /* record the number of times a computed result for a node is hit */ - -#ifdef DD_DEBUG - (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n", - hits, thishit, numCalls); -#endif - - if (subsetNodeTable != NIL(st_table)) { - st_free_table(subsetNodeTable); - } - st_free_table(info->maxpathTable); - st_foreach(pathTable, stPathTableDdFree, (char *)dd); - - FREE(info); - - } else {/* if threshold larger than size of dd */ - subset = f; - cuddRef(subset); - } - FREE(excess); - st_free_table(pathTable); - FREE(pathLengthArray); - for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - -#ifdef DD_DEBUG - /* check containment of subset in f */ - if (subset != NULL) { - DdNode *check; - check = Cudd_bddIteConstant(dd, subset, f, one); - if (check != one) { - (void) fprintf(dd->err, "Wrong partition\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - } -#endif - - if (subset != NULL) { - cuddDeref(subset); - return(subset); - } else { - return(NULL); - } - -} /* end of cuddSubsetShortPaths */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Resize the number of pages allocated to store the distances - related to each node.] - - Description [Resize the number of pages allocated to store the distances - related to each node. The procedure moves the counter to the - next page when the end of the page is reached and allocates new - pages when necessary. ] - - SideEffects [Changes the size of pages, page, page index, maximum - number of pages freeing stuff in case of memory out. ] - - SeeAlso [] - -******************************************************************************/ -static void -ResizeNodeDistPages( - ) -{ - int i; - NodeDist_t **newNodeDistPages; - - /* move to next page */ - nodeDistPage++; - - /* If the current page index is larger than the number of pages - * allocated, allocate a new page array. Page numbers are incremented by - * INITIAL_PAGES - */ - if (nodeDistPage == maxNodeDistPages) { - newNodeDistPages = ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES); - if (newNodeDistPages == NULL) { - for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - memOut = 1; - return; - } else { - for (i = 0; i < maxNodeDistPages; i++) { - newNodeDistPages[i] = nodeDistPages[i]; - } - /* Increase total page count */ - maxNodeDistPages += INITIAL_PAGES; - FREE(nodeDistPages); - nodeDistPages = newNodeDistPages; - } - } - /* Allocate a new page */ - currentNodeDistPage = nodeDistPages[nodeDistPage] = ALLOC(NodeDist_t, - nodeDistPageSize); - if (currentNodeDistPage == NULL) { - for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - memOut = 1; - return; - } - /* reset page index */ - nodeDistPageIndex = 0; - return; - -} /* end of ResizeNodeDistPages */ - - -/**Function******************************************************************** - - Synopsis [Resize the number of pages allocated to store nodes in the BFS - traversal of the Bdd .] - - Description [Resize the number of pages allocated to store nodes in the BFS - traversal of the Bdd. The procedure moves the counter to the - next page when the end of the page is reached and allocates new - pages when necessary.] - - SideEffects [Changes the size of pages, page, page index, maximum - number of pages freeing stuff in case of memory out. ] - - SeeAlso [] - -******************************************************************************/ -static void -ResizeQueuePages( - ) -{ - int i; - DdNode ***newQueuePages; - - queuePage++; - /* If the current page index is larger than the number of pages - * allocated, allocate a new page array. Page numbers are incremented by - * INITIAL_PAGES - */ - if (queuePage == maxQueuePages) { - newQueuePages = ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES); - if (newQueuePages == NULL) { - for (i = 0; i < queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - memOut = 1; - return; - } else { - for (i = 0; i < maxQueuePages; i++) { - newQueuePages[i] = queuePages[i]; - } - /* Increase total page count */ - maxQueuePages += INITIAL_PAGES; - FREE(queuePages); - queuePages = newQueuePages; - } - } - /* Allocate a new page */ - currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *,queuePageSize); - if (currentQueuePage == NULL) { - for (i = 0; i < queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - memOut = 1; - return; - } - /* reset page index */ - queuePageIndex = 0; - return; - -} /* end of ResizeQueuePages */ - - -/**Function******************************************************************** - - Synopsis [ Labels each node with its shortest distance from the root] - - Description [ Labels each node with its shortest distance from the root. - This is done in a BFS search of the BDD. The nodes are processed - in a queue implemented as pages(array) to reduce memory fragmentation. - An entry is created for each node visited. The distance from the root - to the node with the corresponding parity is updated. The procedure - is called recursively each recusion level handling nodes at a given - level from the root.] - - - SideEffects [Creates entries in the pathTable] - - SeeAlso [CreatePathTable CreateBotDist] - -******************************************************************************/ -static void -CreateTopDist( - st_table * pathTable /* hast table to store path lengths */, - int parentPage /* the pointer to the page on which the first parent in the queue is to be found. */, - int parentQueueIndex /* pointer to the first parent on the page */, - int topLen /* current distance from the root */, - DdNode ** childPage /* pointer to the page on which the first child is to be added. */, - int childQueueIndex /* pointer to the first child */, - int numParents /* number of parents to process in this recursive call */, - FILE *fp /* where to write messages */) -{ - NodeDist_t *nodeStat; - DdNode *N, *Nv, *Nnv, *node, *child, *regChild; - int i; - int processingDone, childrenCount; - -#ifdef DD_DEBUG - numCalls++; - - /* assume this procedure comes in with only the root node*/ - /* set queue index to the next available entry for addition */ - /* set queue page to page of addition */ - if ((queuePages[parentPage] == childPage) && (parentQueueIndex == - childQueueIndex)) { - fprintf(fp, "Should not happen that they are equal\n"); - } - assert(queuePageIndex == childQueueIndex); - assert(currentQueuePage == childPage); -#endif - /* number children added to queue is initialized , needed for - * numParents in the next call - */ - childrenCount = 0; - /* process all the nodes in this level */ - while (numParents) { - numParents--; - if (parentQueueIndex == queuePageSize) { - parentPage++; - parentQueueIndex = 0; - } - /* a parent to process */ - node = *(queuePages[parentPage] + parentQueueIndex); - parentQueueIndex++; - /* get its children */ - N = Cudd_Regular(node); - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - processingDone = 2; - while (processingDone) { - /* processing the THEN and the ELSE children, the THEN - * child first - */ - if (processingDone == 2) { - child = Nv; - } else { - child = Nnv; - } - - regChild = Cudd_Regular(child); - /* dont process if the child is a constant */ - if (!Cudd_IsConstant(child)) { - /* check is already visited, if not add a new entry in - * the path Table - */ - if (!st_lookup(pathTable, (char *)regChild, (char **)&nodeStat)) { - /* if not in table, has never been visited */ - /* create entry for table */ - if (nodeDistPageIndex == nodeDistPageSize) - ResizeNodeDistPages(); - if (memOut) { - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - st_free_table(pathTable); - return; - } - /* New entry for child in path Table is created here */ - nodeStat = currentNodeDistPage + nodeDistPageIndex; - nodeDistPageIndex++; - - /* Initialize fields of the node data */ - nodeStat->oddTopDist = MAXSHORTINT; - nodeStat->evenTopDist = MAXSHORTINT; - nodeStat->evenBotDist = MAXSHORTINT; - nodeStat->oddBotDist = MAXSHORTINT; - nodeStat->regResult = NULL; - nodeStat->compResult = NULL; - /* update the table entry element, the distance keeps - * track of the parity of the path from the root - */ - if (Cudd_IsComplement(child)) { - nodeStat->oddTopDist = (DdHalfWord) topLen + 1; - } else { - nodeStat->evenTopDist = (DdHalfWord) topLen + 1; - } - - /* insert entry element for child in the table */ - if (st_insert(pathTable, (char *)regChild, - (char *)nodeStat) == ST_OUT_OF_MEM) { - memOut = 1; - for (i = 0; i <= nodeDistPage; i++) - FREE(nodeDistPages[i]); - FREE(nodeDistPages); - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - st_free_table(pathTable); - return; - } - - /* Create list element for this child to process its children. - * If this node has been processed already, then it appears - * in the path table and hence is never added to the list - * again. - */ - - if (queuePageIndex == queuePageSize) ResizeQueuePages(); - if (memOut) { - for (i = 0; i <= nodeDistPage; i++) - FREE(nodeDistPages[i]); - FREE(nodeDistPages); - st_free_table(pathTable); - return; - } - *(currentQueuePage + queuePageIndex) = child; - queuePageIndex++; - - childrenCount++; - } else { - /* if not been met in a path with this parity before */ - /* put in list */ - if (((Cudd_IsComplement(child)) && (nodeStat->oddTopDist == - MAXSHORTINT)) || ((!Cudd_IsComplement(child)) && - (nodeStat->evenTopDist == MAXSHORTINT))) { - - if (queuePageIndex == queuePageSize) ResizeQueuePages(); - if (memOut) { - for (i = 0; i <= nodeDistPage; i++) - FREE(nodeDistPages[i]); - FREE(nodeDistPages); - st_free_table(pathTable); - return; - - } - *(currentQueuePage + queuePageIndex) = child; - queuePageIndex++; - - /* update the distance with the appropriate parity */ - if (Cudd_IsComplement(child)) { - nodeStat->oddTopDist = (DdHalfWord) topLen + 1; - } else { - nodeStat->evenTopDist = (DdHalfWord) topLen + 1; - } - childrenCount++; - } - - } /* end of else (not found in st_table) */ - } /*end of if Not constant child */ - processingDone--; - } /*end of while processing Nv, Nnv */ - } /*end of while numParents */ - -#ifdef DD_DEBUG - assert(queuePages[parentPage] == childPage); - assert(parentQueueIndex == childQueueIndex); -#endif - - if (childrenCount != 0) { - topLen++; - childPage = currentQueuePage; - childQueueIndex = queuePageIndex; - CreateTopDist(pathTable, parentPage, parentQueueIndex, topLen, - childPage, childQueueIndex, childrenCount, fp); - } - - return; - -} /* end of CreateTopDist */ - - -/**Function******************************************************************** - - Synopsis [ Labels each node with the shortest distance from the constant.] - - Description [Labels each node with the shortest distance from the constant. - This is done in a DFS search of the BDD. Each node has an odd - and even parity distance from the sink (since there exists paths to both - zero and one) which is less than MAXSHORTINT. At each node these distances - are updated using the minimum distance of its children from the constant. - SInce now both the length from the root and child is known, the minimum path - length(length of the shortest path between the root and the constant that - this node lies on) of this node can be calculated and used to update the - pathLengthArray] - - SideEffects [Updates Path Table and path length array] - - SeeAlso [CreatePathTable CreateTopDist AssessPathLength] - -******************************************************************************/ -static int -CreateBotDist( - DdNode * node /* current node */, - st_table * pathTable /* path table with path lengths */, - unsigned int * pathLengthArray /* array that stores number of nodes belonging to a particular path length. */, - FILE *fp /* where to write messages */) -{ - DdNode *N, *Nv, *Nnv; - DdNode *realChild; - DdNode *child, *regChild; - NodeDist_t *nodeStat, *nodeStatChild; - unsigned int oddLen, evenLen, pathLength; - DdHalfWord botDist; - int processingDone; - - if (Cudd_IsConstant(node)) - return(1); - N = Cudd_Regular(node); - /* each node has one table entry */ - /* update as you go down the min dist of each node from - the root in each (odd and even) parity */ - if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { - fprintf(fp, "Something wrong, the entry doesn't exist\n"); - return(0); - } - - /* compute length of odd parity distances */ - if ((nodeStat->oddTopDist != MAXSHORTINT) && - (nodeStat->oddBotDist != MAXSHORTINT)) - oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); - else - oddLen = MAXSHORTINT; - - /* compute length of even parity distances */ - if (!((nodeStat->evenTopDist == MAXSHORTINT) || - (nodeStat->evenBotDist == MAXSHORTINT))) - evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); - else - evenLen = MAXSHORTINT; - - /* assign pathlength to minimum of the two */ - pathLength = (oddLen <= evenLen) ? oddLen : evenLen; - - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - /* process each child */ - processingDone = 0; - while (processingDone != 2) { - if (!processingDone) { - child = Nv; - } else { - child = Nnv; - } - - realChild = Cudd_NotCond(child, Cudd_IsComplement(node)); - regChild = Cudd_Regular(child); - if (Cudd_IsConstant(realChild)) { - /* Found a minterm; count parity and shortest distance - ** from the constant. - */ - if (Cudd_IsComplement(child)) - nodeStat->oddBotDist = 1; - else - nodeStat->evenBotDist = 1; - } else { - /* If node not in table, recur. */ - if (!st_lookup(pathTable, (char *) regChild, - (char **)&nodeStatChild)) { - fprintf(fp, "Something wrong, node in table should have been created in top dist proc.\n"); - return(0); - } - - if (nodeStatChild->oddBotDist == MAXSHORTINT) { - if (nodeStatChild->evenBotDist == MAXSHORTINT) { - if (!CreateBotDist(realChild, pathTable, pathLengthArray, fp)) - return(0); - } else { - fprintf(fp, "Something wrong, both bot nodeStats should be there\n"); - return(0); - } - } - - /* Update shortest distance from the constant depending on - ** parity. */ - - if (Cudd_IsComplement(child)) { - /* If parity on the edge then add 1 to even distance - ** of child to get odd parity distance and add 1 to - ** odd distance of child to get even parity - ** distance. Change distance of current node only if - ** the calculated distance is less than existing - ** distance. */ - if (nodeStatChild->oddBotDist != MAXSHORTINT) - botDist = nodeStatChild->oddBotDist + 1; - else - botDist = MAXSHORTINT; - if (nodeStat->evenBotDist > botDist ) - nodeStat->evenBotDist = botDist; - - if (nodeStatChild->evenBotDist != MAXSHORTINT) - botDist = nodeStatChild->evenBotDist + 1; - else - botDist = MAXSHORTINT; - if (nodeStat->oddBotDist > botDist) - nodeStat->oddBotDist = botDist; - - } else { - /* If parity on the edge then add 1 to even distance - ** of child to get even parity distance and add 1 to - ** odd distance of child to get odd parity distance. - ** Change distance of current node only if the - ** calculated distance is lesser than existing - ** distance. */ - if (nodeStatChild->evenBotDist != MAXSHORTINT) - botDist = nodeStatChild->evenBotDist + 1; - else - botDist = MAXSHORTINT; - if (nodeStat->evenBotDist > botDist) - nodeStat->evenBotDist = botDist; - - if (nodeStatChild->oddBotDist != MAXSHORTINT) - botDist = nodeStatChild->oddBotDist + 1; - else - botDist = MAXSHORTINT; - if (nodeStat->oddBotDist > botDist) - nodeStat->oddBotDist = botDist; - } - } /* end of else (if not constant child ) */ - processingDone++; - } /* end of while processing Nv, Nnv */ - - /* Compute shortest path length on the fly. */ - if ((nodeStat->oddTopDist != MAXSHORTINT) && - (nodeStat->oddBotDist != MAXSHORTINT)) - oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); - else - oddLen = MAXSHORTINT; - - if ((nodeStat->evenTopDist != MAXSHORTINT) && - (nodeStat->evenBotDist != MAXSHORTINT)) - evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); - else - evenLen = MAXSHORTINT; - - /* Update path length array that has number of nodes of a particular - ** path length. */ - if (oddLen < pathLength ) { - if (pathLength != MAXSHORTINT) - pathLengthArray[pathLength]--; - if (oddLen != MAXSHORTINT) - pathLengthArray[oddLen]++; - pathLength = oddLen; - } - if (evenLen < pathLength ) { - if (pathLength != MAXSHORTINT) - pathLengthArray[pathLength]--; - if (evenLen != MAXSHORTINT) - pathLengthArray[evenLen]++; - } - - return(1); - -} /*end of CreateBotDist */ - - -/**Function******************************************************************** - - Synopsis [ The outer procedure to label each node with its shortest - distance from the root and constant] - - Description [ The outer procedure to label each node with its shortest - distance from the root and constant. Calls CreateTopDist and CreateBotDist. - The basis for computing the distance between root and constant is that - the distance may be the sum of even distances from the node to the root - and constant or the sum of odd distances from the node to the root and - constant. Both CreateTopDist and CreateBotDist create the odd and - even parity distances from the root and constant respectively.] - - SideEffects [None] - - SeeAlso [CreateTopDist CreateBotDist] - -******************************************************************************/ -static st_table * -CreatePathTable( - DdNode * node /* root of function */, - unsigned int * pathLengthArray /* array of path lengths to store nodes labeled with the various path lengths */, - FILE *fp /* where to write messages */) -{ - - st_table *pathTable; - NodeDist_t *nodeStat; - DdHalfWord topLen; - DdNode *N; - int i, numParents; - int insertValue; - DdNode **childPage; - int parentPage; - int childQueueIndex, parentQueueIndex; - - /* Creating path Table for storing data about nodes */ - pathTable = st_init_table(st_ptrcmp,st_ptrhash); - - /* initializing pages for info about each node */ - maxNodeDistPages = INITIAL_PAGES; - nodeDistPages = ALLOC(NodeDist_t *, maxNodeDistPages); - if (nodeDistPages == NULL) { - goto OUT_OF_MEM; - } - nodeDistPage = 0; - currentNodeDistPage = nodeDistPages[nodeDistPage] = - ALLOC(NodeDist_t, nodeDistPageSize); - if (currentNodeDistPage == NULL) { - for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - goto OUT_OF_MEM; - } - nodeDistPageIndex = 0; - - /* Initializing pages for the BFS search queue, implemented as an array. */ - maxQueuePages = INITIAL_PAGES; - queuePages = ALLOC(DdNode **, maxQueuePages); - if (queuePages == NULL) { - goto OUT_OF_MEM; - } - queuePage = 0; - currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *, queuePageSize); - if (currentQueuePage == NULL) { - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - goto OUT_OF_MEM; - } - queuePageIndex = 0; - - /* Enter the root node into the queue to start with. */ - parentPage = queuePage; - parentQueueIndex = queuePageIndex; - topLen = 0; - *(currentQueuePage + queuePageIndex) = node; - queuePageIndex++; - childPage = currentQueuePage; - childQueueIndex = queuePageIndex; - - N = Cudd_Regular(node); - - if (nodeDistPageIndex == nodeDistPageSize) ResizeNodeDistPages(); - if (memOut) { - for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - st_free_table(pathTable); - goto OUT_OF_MEM; - } - - nodeStat = currentNodeDistPage + nodeDistPageIndex; - nodeDistPageIndex++; - - nodeStat->oddTopDist = MAXSHORTINT; - nodeStat->evenTopDist = MAXSHORTINT; - nodeStat->evenBotDist = MAXSHORTINT; - nodeStat->oddBotDist = MAXSHORTINT; - nodeStat->regResult = NULL; - nodeStat->compResult = NULL; - - insertValue = st_insert(pathTable, (char *)N, (char *)nodeStat); - if (insertValue == ST_OUT_OF_MEM) { - memOut = 1; - for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); - FREE(nodeDistPages); - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - st_free_table(pathTable); - goto OUT_OF_MEM; - } else if (insertValue == 1) { - fprintf(fp, "Something wrong, the entry exists but didnt show up in st_lookup\n"); - return(NULL); - } - - if (Cudd_IsComplement(node)) { - nodeStat->oddTopDist = 0; - } else { - nodeStat->evenTopDist = 0; - } - numParents = 1; - /* call the function that counts the distance of each node from the - * root - */ -#ifdef DD_DEBUG - numCalls = 0; -#endif - CreateTopDist(pathTable, parentPage, parentQueueIndex, (int) topLen, - childPage, childQueueIndex, numParents, fp); - if (memOut) { - fprintf(fp, "Out of Memory and cant count path lengths\n"); - goto OUT_OF_MEM; - } - -#ifdef DD_DEBUG - numCalls = 0; -#endif - /* call the function that counts the distance of each node from the - * constant - */ - if (!CreateBotDist(node, pathTable, pathLengthArray, fp)) return(NULL); - - /* free BFS queue pages as no longer required */ - for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); - FREE(queuePages); - return(pathTable); - -OUT_OF_MEM: - (void) fprintf(fp, "Out of Memory, cannot allocate pages\n"); - memOut = 1; - return(NULL); - -} /*end of CreatePathTable */ - - -/**Function******************************************************************** - - Synopsis [Chooses the maximum allowable path length of nodes under the - threshold.] - - Description [Chooses the maximum allowable path length under each node. - The corner cases are when the threshold is larger than the number - of nodes in the BDD iself, in which case 'numVars + 1' is returned. - If all nodes of a particular path length are needed, then the - maxpath returned is the next one with excess nodes = 0;] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static unsigned int -AssessPathLength( - unsigned int * pathLengthArray /* array determining number of nodes belonging to the different path lengths */, - int threshold /* threshold to determine maximum allowable nodes in the subset */, - int numVars /* maximum number of variables */, - unsigned int * excess /* number of nodes labeled maxpath required in the subset */, - FILE *fp /* where to write messages */) -{ - unsigned int i, maxpath; - int temp; - - temp = threshold; - i = 0; - maxpath = 0; - /* quit loop if i reaches max number of variables or if temp reaches - * below zero - */ - while ((i < (unsigned) numVars+1) && (temp > 0)) { - if (pathLengthArray[i] > 0) { - maxpath = i; - temp = temp - pathLengthArray[i]; - } - i++; - } - /* if all nodes of max path are needed */ - if (temp >= 0) { - maxpath++; /* now maxpath becomes the next maxppath or max number - of variables */ - *excess = 0; - } else { /* normal case when subset required is less than size of - original BDD */ - *excess = temp + pathLengthArray[maxpath]; - } - - if (maxpath == 0) { - fprintf(fp, "Path Length array seems to be all zeroes, check\n"); - } - return(maxpath); - -} /* end of AssessPathLength */ - - -/**Function******************************************************************** - - Synopsis [Builds the BDD with nodes labeled with path length less than or equal to maxpath] - - Description [Builds the BDD with nodes labeled with path length - under maxpath and as many nodes labeled maxpath as determined by the - threshold. The procedure uses the path table to determine which nodes - in the original bdd need to be retained. This procedure picks a - shortest path (tie break decided by taking the child with the shortest - distance to the constant) and recurs down the path till it reaches the - constant. the procedure then starts building the subset upward from - the constant. All nodes labeled by path lengths less than the given - maxpath are used to build the subset. However, in the case of nodes - that have label equal to maxpath, as many are chosen as required by - the threshold. This number is stored in the info structure in the - field thresholdReached. This field is decremented whenever a node - labeled maxpath is encountered and the nodes labeled maxpath are - aggregated in a maxpath table. As soon as the thresholdReached count - goes to 0, the shortest path from this node to the constant is found. - The extraction of nodes with the above labeling is based on the fact - that each node, labeled with a path length, P, has at least one child - labeled P or less. So extracting all nodes labeled a given path length - P ensures complete paths between the root and the constant. Extraction - of a partial number of nodes with a given path length may result in - incomplete paths and hence the additional number of nodes are grabbed - to complete the path. Since the Bdd is built bottom-up, other nodes - labeled maxpath do lie on complete paths. The procedure may cause the - subset to have a larger or smaller number of nodes than the specified - threshold. The increase in the number of nodes is caused by the - building of a subset and the reduction by recombination. However in - most cases, the recombination overshadows the increase and the - procedure returns a result with lower number of nodes than specified. - The subsetNodeTable is NIL when there is no hard limit on the number - of nodes. Further efforts towards keeping the subset closer to the - threshold number were abandoned in favour of keeping the procedure - simple and fast.] - - SideEffects [SubsetNodeTable is changed if it is not NIL.] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -BuildSubsetBdd( - DdManager * dd /* DD manager */, - st_table * pathTable /* path table with path lengths and computed results */, - DdNode * node /* current node */, - struct AssortedInfo * info /* assorted information structure */, - st_table * subsetNodeTable /* table storing computed results */) -{ - DdNode *N, *Nv, *Nnv; - DdNode *ThenBranch, *ElseBranch, *childBranch; - DdNode *child, *regChild, *regNnv, *regNv; - NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv; - DdNode *neW, *topv, *regNew; - char *entry; - unsigned int topid; - unsigned int childPathLength, oddLen, evenLen, NnvPathLength, NvPathLength; - unsigned int NvBotDist, NnvBotDist; - int tiebreakChild; - int processingDone, thenDone, elseDone; - - -#ifdef DD_DEBUG - numCalls++; -#endif - if (Cudd_IsConstant(node)) - return(node); - - N = Cudd_Regular(node); - /* Find node in table. */ - if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { - (void) fprintf(dd->err, "Something wrong, node must be in table \n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - /* If the node in the table has been visited, then return the corresponding - ** Dd. Since a node can become a subset of itself, its - ** complement (that is te same node reached by a different parity) will - ** become a superset of the original node and result in some minterms - ** that were not in the original set. Hence two different results are - ** maintained, corresponding to the odd and even parities. - */ - - /* If this node is reached with an odd parity, get odd parity results. */ - if (Cudd_IsComplement(node)) { - if (nodeStat->compResult != NULL) { -#ifdef DD_DEBUG - hits++; -#endif - return(nodeStat->compResult); - } - } else { - /* if this node is reached with an even parity, get even parity - * results - */ - if (nodeStat->regResult != NULL) { -#ifdef DD_DEBUG - hits++; -#endif - return(nodeStat->regResult); - } - } - - - /* get children */ - Nv = Cudd_T(N); - Nnv = Cudd_E(N); - - Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); - Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); - - /* no child processed */ - processingDone = 0; - /* then child not processed */ - thenDone = 0; - ThenBranch = NULL; - /* else child not processed */ - elseDone = 0; - ElseBranch = NULL; - /* if then child constant, branch is the child */ - if (Cudd_IsConstant(Nv)) { - /*shortest path found */ - if ((Nv == DD_ONE(dd)) && (info->findShortestPath)) { - info->findShortestPath = 0; - } - - ThenBranch = Nv; - cuddRef(ThenBranch); - if (ThenBranch == NULL) { - return(NULL); - } - - thenDone++; - processingDone++; - NvBotDist = MAXSHORTINT; - } else { - /* Derive regular child for table lookup. */ - regNv = Cudd_Regular(Nv); - /* Get node data for shortest path length. */ - if (!st_lookup(pathTable, (char *)regNv, (char **)&nodeStatNv) ) { - (void) fprintf(dd->err, "Something wrong, node must be in table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - /* Derive shortest path length for child. */ - if ((nodeStatNv->oddTopDist != MAXSHORTINT) && - (nodeStatNv->oddBotDist != MAXSHORTINT)) { - oddLen = (nodeStatNv->oddTopDist + nodeStatNv->oddBotDist); - } else { - oddLen = MAXSHORTINT; - } - - if ((nodeStatNv->evenTopDist != MAXSHORTINT) && - (nodeStatNv->evenBotDist != MAXSHORTINT)) { - evenLen = (nodeStatNv->evenTopDist +nodeStatNv->evenBotDist); - } else { - evenLen = MAXSHORTINT; - } - - NvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; - NvBotDist = (oddLen <= evenLen) ? nodeStatNv->oddBotDist: - nodeStatNv->evenBotDist; - } - /* if else child constant, branch is the child */ - if (Cudd_IsConstant(Nnv)) { - /*shortest path found */ - if ((Nnv == DD_ONE(dd)) && (info->findShortestPath)) { - info->findShortestPath = 0; - } - - ElseBranch = Nnv; - cuddRef(ElseBranch); - if (ElseBranch == NULL) { - return(NULL); - } - - elseDone++; - processingDone++; - NnvBotDist = MAXSHORTINT; - } else { - /* Derive regular child for table lookup. */ - regNnv = Cudd_Regular(Nnv); - /* Get node data for shortest path length. */ - if (!st_lookup(pathTable, (char *)regNnv, (char **)&nodeStatNnv) ) { - (void) fprintf(dd->err, "Something wrong, node must be in table\n"); - dd->errorCode = CUDD_INTERNAL_ERROR; - return(NULL); - } - /* Derive shortest path length for child. */ - if ((nodeStatNnv->oddTopDist != MAXSHORTINT) && - (nodeStatNnv->oddBotDist != MAXSHORTINT)) { - oddLen = (nodeStatNnv->oddTopDist + nodeStatNnv->oddBotDist); - } else { - oddLen = MAXSHORTINT; - } - - if ((nodeStatNnv->evenTopDist != MAXSHORTINT) && - (nodeStatNnv->evenBotDist != MAXSHORTINT)) { - evenLen = (nodeStatNnv->evenTopDist +nodeStatNnv->evenBotDist); - } else { - evenLen = MAXSHORTINT; - } - - NnvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; - NnvBotDist = (oddLen <= evenLen) ? nodeStatNnv->oddBotDist : - nodeStatNnv->evenBotDist; - } - - tiebreakChild = (NvBotDist <= NnvBotDist) ? 1 : 0; - /* while both children not processed */ - while (processingDone != 2) { - if (!processingDone) { - /* if no child processed */ - /* pick the child with shortest path length and record which one - * picked - */ - if ((NvPathLength < NnvPathLength) || - ((NvPathLength == NnvPathLength) && (tiebreakChild == 1))) { - child = Nv; - regChild = regNv; - thenDone = 1; - childPathLength = NvPathLength; - } else { - child = Nnv; - regChild = regNnv; - elseDone = 1; - childPathLength = NnvPathLength; - } /* then path length less than else path length */ - } else { - /* if one child processed, process the other */ - if (thenDone) { - child = Nnv; - regChild = regNnv; - elseDone = 1; - childPathLength = NnvPathLength; - } else { - child = Nv; - regChild = regNv; - thenDone = 1; - childPathLength = NvPathLength; - } /* end of else pick the Then child if ELSE child processed */ - } /* end of else one child has been processed */ - - /* ignore (replace with constant 0) all nodes which lie on paths larger - * than the maximum length of the path required - */ - if (childPathLength > info->maxpath) { - /* record nodes visited */ - childBranch = zero; - } else { - if (childPathLength < info->maxpath) { - if (info->findShortestPath) { - info->findShortestPath = 0; - } - childBranch = BuildSubsetBdd(dd, pathTable, child, info, - subsetNodeTable); - - } else { /* Case: path length of node = maxpath */ - /* If the node labeled with maxpath is found in the - ** maxpathTable, use it to build the subset BDD. */ - if (st_lookup(info->maxpathTable, (char *)regChild, - (char **)&entry)) { - /* When a node that is already been chosen is hit, - ** the quest for a complete path is over. */ - if (info->findShortestPath) { - info->findShortestPath = 0; - } - childBranch = BuildSubsetBdd(dd, pathTable, child, info, - subsetNodeTable); - } else { - /* If node is not found in the maxpathTable and - ** the threshold has been reached, then if the - ** path needs to be completed, continue. Else - ** replace the node with a zero. */ - if (info->thresholdReached <= 0) { - if (info->findShortestPath) { - if (st_insert(info->maxpathTable, (char *)regChild, - (char *)NIL(char)) == ST_OUT_OF_MEM) { - memOut = 1; - (void) fprintf(dd->err, "OUT of memory\n"); - info->thresholdReached = 0; - childBranch = zero; - } else { - info->thresholdReached--; - childBranch = BuildSubsetBdd(dd, pathTable, - child, info,subsetNodeTable); - } - } else { /* not find shortest path, we dont need this - node */ - childBranch = zero; - } - } else { /* Threshold hasn't been reached, - ** need the node. */ - if (st_insert(info->maxpathTable, (char *)regChild, - (char *)NIL(char)) == ST_OUT_OF_MEM) { - memOut = 1; - (void) fprintf(dd->err, "OUT of memory\n"); - info->thresholdReached = 0; - childBranch = zero; - } else { - info->thresholdReached--; - if (info->thresholdReached <= 0) { - info->findShortestPath = 1; - } - childBranch = BuildSubsetBdd(dd, pathTable, - child, info, subsetNodeTable); - - } /* end of st_insert successful */ - } /* end of threshold hasnt been reached yet */ - } /* end of else node not found in maxpath table */ - } /* end of if (path length of node = maxpath) */ - } /* end if !(childPathLength > maxpath) */ - if (childBranch == NULL) { - /* deref other stuff incase reordering has taken place */ - if (ThenBranch != NULL) { - Cudd_RecursiveDeref(dd, ThenBranch); - ThenBranch = NULL; - } - if (ElseBranch != NULL) { - Cudd_RecursiveDeref(dd, ElseBranch); - ElseBranch = NULL; - } - return(NULL); - } - - cuddRef(childBranch); - - if (child == Nv) { - ThenBranch = childBranch; - } else { - ElseBranch = childBranch; - } - processingDone++; - - } /*end of while processing Nv, Nnv */ - - info->findShortestPath = 0; - topid = Cudd_NodeReadIndex(N); - topv = Cudd_ReadVars(dd, topid); - cuddRef(topv); - neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); - if (neW != NULL) { - cuddRef(neW); - } - Cudd_RecursiveDeref(dd, topv); - Cudd_RecursiveDeref(dd, ThenBranch); - Cudd_RecursiveDeref(dd, ElseBranch); - - - /* Hard Limit of threshold has been imposed */ - if (subsetNodeTable != NIL(st_table)) { - /* check if a new node is created */ - regNew = Cudd_Regular(neW); - /* subset node table keeps all new nodes that have been created to keep - * a running count of how many nodes have been built in the subset. - */ - if (!st_lookup(subsetNodeTable, (char *)regNew, (char **)&entry)) { - if (!Cudd_IsConstant(regNew)) { - if (st_insert(subsetNodeTable, (char *)regNew, - (char *)NULL) == ST_OUT_OF_MEM) { - (void) fprintf(dd->err, "Out of memory\n"); - return (NULL); - } - if (st_count(subsetNodeTable) > info->threshold) { - info->thresholdReached = 0; - } - } - } - } - - - if (neW == NULL) { - return(NULL); - } else { - /*store computed result in regular form*/ - if (Cudd_IsComplement(node)) { - nodeStat->compResult = neW; - cuddRef(nodeStat->compResult); - /* if the new node is the same as the corresponding node in the - * original bdd then its complement need not be computed as it - * cannot be larger than the node itself - */ - if (neW == node) { -#ifdef DD_DEBUG - thishit++; -#endif - /* if a result for the node has already been computed, then - * it can only be smaller than teh node itself. hence store - * the node result in order not to break recombination - */ - if (nodeStat->regResult != NULL) { - Cudd_RecursiveDeref(dd, nodeStat->regResult); - } - nodeStat->regResult = Cudd_Not(neW); - cuddRef(nodeStat->regResult); - } - - } else { - nodeStat->regResult = neW; - cuddRef(nodeStat->regResult); - if (neW == node) { -#ifdef DD_DEBUG - thishit++; -#endif - if (nodeStat->compResult != NULL) { - Cudd_RecursiveDeref(dd, nodeStat->compResult); - } - nodeStat->compResult = Cudd_Not(neW); - cuddRef(nodeStat->compResult); - } - } - - cuddDeref(neW); - return(neW); - } /* end of else i.e. Subset != NULL */ -} /* end of BuildSubsetBdd */ - - -/**Function******************************************************************** - - Synopsis [Procedure to free te result dds stored in the NodeDist pages.] - - Description [None] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static enum st_retval -stPathTableDdFree( - char * key, - char * value, - char * arg) -{ - NodeDist_t *nodeStat; - DdManager *dd; - - nodeStat = (NodeDist_t *)value; - dd = (DdManager *)arg; - if (nodeStat->regResult != NULL) { - Cudd_RecursiveDeref(dd, nodeStat->regResult); - } - if (nodeStat->compResult != NULL) { - Cudd_RecursiveDeref(dd, nodeStat->compResult); - } - return(ST_CONTINUE); - -} /* end of stPathTableFree */ diff --git a/src/bdd/cudd/cuddSymmetry.c b/src/bdd/cudd/cuddSymmetry.c deleted file mode 100644 index e5488b17..00000000 --- a/src/bdd/cudd/cuddSymmetry.c +++ /dev/null @@ -1,1668 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddSymmetry.c] - - PackageName [cudd] - - Synopsis [Functions for symmetry-based variable reordering.] - - Description [External procedures included in this file: -
                -
              • Cudd_SymmProfile() -
              - Internal procedures included in this module: -
                -
              • cuddSymmCheck() -
              • cuddSymmSifting() -
              • cuddSymmSiftingConv() -
              - Static procedures included in this module: -
                -
              • ddSymmUniqueCompare() -
              • ddSymmSiftingAux() -
              • ddSymmSiftingConvAux() -
              • ddSymmSiftingUp() -
              • ddSymmSiftingDown() -
              • ddSymmGroupMove() -
              • ddSymmGroupMoveBackward() -
              • ddSymmSiftingBackward() -
              • ddSymmSummary() -
              ] - - Author [Shipra Panda, Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define MV_OOM (Move *)1 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static int *entry; - -extern int ddTotalNumberSwapping; -#ifdef DD_STATS -extern int ddTotalNISwaps; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddSymmUniqueCompare ARGS((int *ptrX, int *ptrY)); -static int ddSymmSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static int ddSymmSiftingConvAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static Move * ddSymmSiftingUp ARGS((DdManager *table, int y, int xLow)); -static Move * ddSymmSiftingDown ARGS((DdManager *table, int x, int xHigh)); -static int ddSymmGroupMove ARGS((DdManager *table, int x, int y, Move **moves)); -static int ddSymmGroupMoveBackward ARGS((DdManager *table, int x, int y)); -static int ddSymmSiftingBackward ARGS((DdManager *table, Move *moves, int size)); -static void ddSymmSummary ARGS((DdManager *table, int lower, int upper, int *symvars, int *symgroups)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints statistics on symmetric variables.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -void -Cudd_SymmProfile( - DdManager * table, - int lower, - int upper) -{ - int i,x,gbot; - int TotalSymm = 0; - int TotalSymmGroups = 0; - - for (i = lower; i <= upper; i++) { - if (table->subtables[i].next != (unsigned) i) { - x = i; - (void) fprintf(table->out,"Group:"); - do { - (void) fprintf(table->out," %d",table->invperm[x]); - TotalSymm++; - gbot = x; - x = table->subtables[x].next; - } while (x != i); - TotalSymmGroups++; -#ifdef DD_DEBUG - assert(table->subtables[gbot].next == (unsigned) i); -#endif - i = gbot; - (void) fprintf(table->out,"\n"); - } - } - (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm); - (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups); - -} /* end of Cudd_SymmProfile */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Checks for symmetry of x and y.] - - Description [Checks for symmetry of x and y. Ignores projection - functions, unless they are isolated. Returns 1 in case of symmetry; 0 - otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddSymmCheck( - DdManager * table, - int x, - int y) -{ - DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10; - int comple; /* f0 is complemented */ - int xsymmy; /* x and y may be positively symmetric */ - int xsymmyp; /* x and y may be negatively symmetric */ - int arccount; /* number of arcs from layer x to layer y */ - int TotalRefCount; /* total reference count of layer y minus 1 */ - int yindex; - int i; - DdNodePtr *list; - int slots; - DdNode *sentinel = &(table->sentinel); -#ifdef DD_DEBUG - int xindex; -#endif - - /* Checks that x and y are not the projection functions. - ** For x it is sufficient to check whether there is only one - ** node; indeed, if there is one node, it is the projection function - ** and it cannot point to y. Hence, if y isn't just the projection - ** function, it has one arc coming from a layer different from x. - */ - if (table->subtables[x].keys == 1) { - return(0); - } - yindex = table->invperm[y]; - if (table->subtables[y].keys == 1) { - if (table->vars[yindex]->ref == 1) - return(0); - } - - xsymmy = xsymmyp = 1; - arccount = 0; - slots = table->subtables[x].slots; - list = table->subtables[x].nodelist; - for (i = 0; i < slots; i++) { - f = list[i]; - while (f != sentinel) { - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); - f0 = Cudd_Regular(cuddE(f)); - comple = Cudd_IsComplement(cuddE(f)); - if ((int) f1->index == yindex) { - arccount++; - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - if ((int) f0->index != yindex) { - /* If f is an isolated projection function it is - ** allowed to bypass layer y. - */ - if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) - return(0); /* f bypasses layer y */ - } - f11 = f10 = f1; - } - if ((int) f0->index == yindex) { - arccount++; - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = f00 = f0; - } - if (comple) { - f01 = Cudd_Not(f01); - f00 = Cudd_Not(f00); - } - - if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) { - xsymmy &= f01 == f10; - xsymmyp &= f11 == f00; - if ((xsymmy == 0) && (xsymmyp == 0)) - return(0); - } - - f = f->next; - } /* while */ - } /* for */ - - /* Calculate the total reference counts of y */ - TotalRefCount = -1; /* -1 for projection function */ - slots = table->subtables[y].slots; - list = table->subtables[y].nodelist; - for (i = 0; i < slots; i++) { - f = list[i]; - while (f != sentinel) { - TotalRefCount += f->ref; - f = f->next; - } - } - -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if (arccount == TotalRefCount) { - xindex = table->invperm[x]; - (void) fprintf(table->out, - "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", - xindex,yindex,x,y); - } -#endif - - return(arccount == TotalRefCount); - -} /* end of cuddSymmCheck */ - - -/**Function******************************************************************** - - Synopsis [Symmetric sifting algorithm.] - - Description [Symmetric sifting algorithm. - Assumes that no dead nodes are present. -
                -
              1. Order all the variables according to the number of entries in - each unique subtable. -
              2. Sift the variable up and down, remembering each time the total - size of the DD heap and grouping variables that are symmetric. -
              3. Select the best permutation. -
              4. Repeat 3 and 4 for all variables. -
              - Returns 1 plus the number of symmetric variables if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddSymmSiftingConv] - -******************************************************************************/ -int -cuddSymmSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; - int symvars; - int symgroups; -#ifdef DD_STATS - int previousSize; -#endif - - size = table->size; - - /* Find order in which to sift variables. */ - var = NULL; - entry = ALLOC(int,size); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddSymmSiftingOutOfMem; - } - var = ALLOC(int,size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddSymmSiftingOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->perm[i]; - entry[i] = table->subtables[x].keys; - var[i] = i; - } - - qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare); - - /* Initialize the symmetry of each subtable to itself. */ - for (i = lower; i <= upper; i++) { - table->subtables[i].next = i; - } - - for (i = 0; i < ddMin(table->siftMaxVar,size); i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->perm[var[i]]; -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - if (x < lower || x > upper) continue; - if (table->subtables[x].next == (unsigned) x) { - result = ddSymmSiftingAux(table,x,lower,upper); - if (!result) goto ddSymmSiftingOutOfMem; -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + - table->isolated) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } - - FREE(var); - FREE(entry); - - ddSymmSummary(table, lower, upper, &symvars, &symgroups); - -#ifdef DD_STATS - (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", - symvars); - (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", - symgroups); -#endif - - return(1+symvars); - -ddSymmSiftingOutOfMem: - - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddSymmSifting */ - - -/**Function******************************************************************** - - Synopsis [Symmetric sifting to convergence algorithm.] - - Description [Symmetric sifting to convergence algorithm. - Assumes that no dead nodes are present. -
                -
              1. Order all the variables according to the number of entries in - each unique subtable. -
              2. Sift the variable up and down, remembering each time the total - size of the DD heap and grouping variables that are symmetric. -
              3. Select the best permutation. -
              4. Repeat 3 and 4 for all variables. -
              5. Repeat 1-4 until no further improvement. -
              - Returns 1 plus the number of symmetric variables if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddSymmSifting] - -******************************************************************************/ -int -cuddSymmSiftingConv( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; - int symvars; - int symgroups; - int classes; - int initialSize; -#ifdef DD_STATS - int previousSize; -#endif - - initialSize = table->keys - table->isolated; - - size = table->size; - - /* Find order in which to sift variables. */ - var = NULL; - entry = ALLOC(int,size); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddSymmSiftingConvOutOfMem; - } - var = ALLOC(int,size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto ddSymmSiftingConvOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->perm[i]; - entry[i] = table->subtables[x].keys; - var[i] = i; - } - - qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare); - - /* Initialize the symmetry of each subtable to itself - ** for first pass of converging symmetric sifting. - */ - for (i = lower; i <= upper; i++) { - table->subtables[i].next = i; - } - - for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->perm[var[i]]; - if (x < lower || x > upper) continue; - /* Only sift if not in symmetry group already. */ - if (table->subtables[x].next == (unsigned) x) { -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddSymmSiftingAux(table,x,lower,upper); - if (!result) goto ddSymmSiftingConvOutOfMem; -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + - table->isolated) { - (void) fprintf(table->out,"+"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } - - /* Sifting now until convergence. */ - while ((unsigned) initialSize > table->keys - table->isolated) { - initialSize = table->keys - table->isolated; -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); -#endif - /* Here we consider only one representative for each symmetry class. */ - for (x = lower, classes = 0; x <= upper; x++, classes++) { - while ((unsigned) x < table->subtables[x].next) { - x = table->subtables[x].next; - } - /* Here x is the largest index in a group. - ** Groups consist of adjacent variables. - ** Hence, the next increment of x will move it to a new group. - */ - i = table->invperm[x]; - entry[i] = table->subtables[x].keys; - var[classes] = i; - } - - qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { - if (ddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->perm[var[i]]; - if ((unsigned) x >= table->subtables[x].next) { -#ifdef DD_STATS - previousSize = table->keys - table->isolated; -#endif - result = ddSymmSiftingConvAux(table,x,lower,upper); - if (!result ) goto ddSymmSiftingConvOutOfMem; -#ifdef DD_STATS - if (table->keys < (unsigned) previousSize + table->isolated) { - (void) fprintf(table->out,"-"); - } else if (table->keys > (unsigned) previousSize + - table->isolated) { - (void) fprintf(table->out,"+"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } /* for */ - } - - ddSymmSummary(table, lower, upper, &symvars, &symgroups); - -#ifdef DD_STATS - (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n", - symvars); - (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups", - symgroups); -#endif - - FREE(var); - FREE(entry); - - return(1+symvars); - -ddSymmSiftingConvOutOfMem: - - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddSymmSiftingConv */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the variables - according to the number of keys in the subtables. - Returns the difference in number of keys between the two - variables being compared.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmUniqueCompare( - int * ptrX, - int * ptrY) -{ -#if 0 - if (entry[*ptrY] == entry[*ptrX]) { - return((*ptrX) - (*ptrY)); - } -#endif - return(entry[*ptrY] - entry[*ptrX]); - -} /* end of ddSymmUniqueCompare */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. Finds the best position and does the required changes. - Assumes that x is not part of a symmetry group. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmSiftingAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - Move *move; - Move *moveUp; /* list of up moves */ - Move *moveDown; /* list of down moves */ - int initialSize; - int result; - int i; - int topbot; /* index to either top or bottom of symmetry group */ - int initGroupSize, finalGroupSize; - - -#ifdef DD_DEBUG - /* check for previously detected symmetry */ - assert(table->subtables[x].next == (unsigned) x); -#endif - - initialSize = table->keys - table->isolated; - - moveDown = NULL; - moveUp = NULL; - - if ((x - xLow) > (xHigh - x)) { - /* Will go down first, unless x == xHigh: - ** Look for consecutive symmetries above x. - */ - for (i = x; i > xLow; i--) { - if (!cuddSymmCheck(table,i-1,i)) - break; - topbot = table->subtables[i-1].next; /* find top of i-1's group */ - table->subtables[i-1].next = i; - table->subtables[x].next = topbot; /* x is bottom of group so its */ - /* next is top of i-1's group */ - i = topbot + 1; /* add 1 for i--; new i is top of symm group */ - } - } else { - /* Will go up first unless x == xlow: - ** Look for consecutive symmetries below x. - */ - for (i = x; i < xHigh; i++) { - if (!cuddSymmCheck(table,i,i+1)) - break; - /* find bottom of i+1's symm group */ - topbot = i + 1; - while ((unsigned) topbot < table->subtables[topbot].next) { - topbot = table->subtables[topbot].next; - } - table->subtables[topbot].next = table->subtables[i].next; - table->subtables[i].next = i + 1; - i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */ - } - } - - /* Now x may be in the middle of a symmetry group. - ** Find bottom of x's symm group. - */ - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - - if (x == xLow) { /* Sift down */ - -#ifdef DD_DEBUG - /* x must be a singleton */ - assert((unsigned) x == table->subtables[x].next); -#endif - if (x == xHigh) return(1); /* just one variable */ - - initGroupSize = 1; - - moveDown = ddSymmSiftingDown(table,x,xHigh); - /* after this point x --> xHigh, unless early term */ - if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - if (moveDown == NULL) return(1); - - x = moveDown->y; - /* Find bottom of x's group */ - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetry group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - finalGroupSize = i - x + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetry groups detected, return to best position */ - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } else { - initialSize = table->keys - table->isolated; - moveUp = ddSymmSiftingUp(table,x,xLow); - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } - if (!result) goto ddSymmSiftingAuxOutOfMem; - - } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ - /* Find top of x's symm group */ - i = x; /* bottom */ - x = table->subtables[x].next; /* top */ - - if (x == xLow) return(1); /* just one big group */ - - initGroupSize = i - x + 1; - - moveUp = ddSymmSiftingUp(table,x,xLow); - /* after this point x --> xLow, unless early term */ - if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - if (moveUp == NULL) return(1); - - x = moveUp->x; - /* Find top of x's group */ - i = table->subtables[x].next; -#ifdef DD_DEBUG - /* x should be the bottom of the symmetry group and i the top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - finalGroupSize = x - i + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetry groups detected, return to best position */ - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } else { - initialSize = table->keys - table->isolated; - moveDown = ddSymmSiftingDown(table,x,xHigh); - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } - if (!result) goto ddSymmSiftingAuxOutOfMem; - - } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ - - moveDown = ddSymmSiftingDown(table,x,xHigh); - /* at this point x == xHigh, unless early term */ - if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - - if (moveDown != NULL) { - x = moveDown->y; /* x is top here */ - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } - } else { - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } - x = table->subtables[i].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetry group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - initGroupSize = i - x + 1; - - moveUp = ddSymmSiftingUp(table,x,xLow); - if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - - if (moveUp != NULL) { - x = moveUp->x; - i = table->subtables[x].next; - } else { - i = x; - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x should be the bottom of the symmetry group and i the top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - finalGroupSize = x - i + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetry groups detected, return to best position */ - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } else { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - initialSize = table->keys - table->isolated; - moveDown = ddSymmSiftingDown(table,x,xHigh); - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } - if (!result) goto ddSymmSiftingAuxOutOfMem; - - } else { /* moving up first: shorter */ - /* Find top of x's symmetry group */ - x = table->subtables[x].next; - - moveUp = ddSymmSiftingUp(table,x,xLow); - /* at this point x == xHigh, unless early term */ - if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - - if (moveUp != NULL) { - x = moveUp->x; - i = table->subtables[x].next; - } else { - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - i = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x is bottom of the symmetry group and i is top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - initGroupSize = x - i + 1; - - moveDown = ddSymmSiftingDown(table,x,xHigh); - if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem; - - if (moveDown != NULL) { - x = moveDown->y; - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } - } else { - i = x; - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetry group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - finalGroupSize = i - x + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetries detected, go back to best position */ - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } else { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - initialSize = table->keys - table->isolated; - moveUp = ddSymmSiftingUp(table,x,xLow); - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } - if (!result) goto ddSymmSiftingAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - - return(1); - -ddSymmSiftingAuxOutOfMem: - if (moveDown != MV_OOM) { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - } - if (moveUp != MV_OOM) { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - } - - return(0); - -} /* end of ddSymmSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. Finds the best position and does the required changes. - Assumes that x is either an isolated variable, or it is the bottom of - a symmetry group. All symmetries may not have been found, because of - exceeded growth limit. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmSiftingConvAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - Move *move; - Move *moveUp; /* list of up moves */ - Move *moveDown; /* list of down moves */ - int initialSize; - int result; - int i; - int initGroupSize, finalGroupSize; - - - initialSize = table->keys - table->isolated; - - moveDown = NULL; - moveUp = NULL; - - if (x == xLow) { /* Sift down */ -#ifdef DD_DEBUG - /* x is bottom of symmetry group */ - assert((unsigned) x >= table->subtables[x].next); -#endif - i = table->subtables[x].next; - initGroupSize = x - i + 1; - - moveDown = ddSymmSiftingDown(table,x,xHigh); - /* at this point x == xHigh, unless early term */ - if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - if (moveDown == NULL) return(1); - - x = moveDown->y; - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetric group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - finalGroupSize = i - x + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetries detected, go back to best position */ - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } else { - initialSize = table->keys - table->isolated; - moveUp = ddSymmSiftingUp(table,x,xLow); - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } - if (!result) goto ddSymmSiftingConvAuxOutOfMem; - - } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */ - /* Find top of x's symm group */ - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - i = x; /* bottom */ - x = table->subtables[x].next; /* top */ - - if (x == xLow) return(1); - - initGroupSize = i - x + 1; - - moveUp = ddSymmSiftingUp(table,x,xLow); - /* at this point x == xLow, unless early term */ - if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - if (moveUp == NULL) return(1); - - x = moveUp->x; - i = table->subtables[x].next; -#ifdef DD_DEBUG - /* x should be the bottom of the symmetry group and i the top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - finalGroupSize = x - i + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetry groups detected, return to best position */ - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } else { - initialSize = table->keys - table->isolated; - moveDown = ddSymmSiftingDown(table,x,xHigh); - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } - if (!result) - goto ddSymmSiftingConvAuxOutOfMem; - - } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ - moveDown = ddSymmSiftingDown(table,x,xHigh); - /* at this point x == xHigh, unless early term */ - if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - - if (moveDown != NULL) { - x = moveDown->y; - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } - } else { - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - i = x; - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetry group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - initGroupSize = i - x + 1; - - moveUp = ddSymmSiftingUp(table,x,xLow); - if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - - if (moveUp != NULL) { - x = moveUp->x; - i = table->subtables[x].next; - } else { - i = x; - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x should be the bottom of the symmetry group and i the top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - finalGroupSize = x - i + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetry groups detected, return to best position */ - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } else { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - initialSize = table->keys - table->isolated; - moveDown = ddSymmSiftingDown(table,x,xHigh); - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } - if (!result) goto ddSymmSiftingConvAuxOutOfMem; - - } else { /* moving up first: shorter */ - /* Find top of x's symmetry group */ - x = table->subtables[x].next; - - moveUp = ddSymmSiftingUp(table,x,xLow); - /* at this point x == xHigh, unless early term */ - if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - - if (moveUp != NULL) { - x = moveUp->x; - i = table->subtables[x].next; - } else { - i = x; - while ((unsigned) x < table->subtables[x].next) - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x is bottom of the symmetry group and i is top */ - assert((unsigned) x >= table->subtables[x].next); - assert((unsigned) i == table->subtables[x].next); -#endif - initGroupSize = x - i + 1; - - moveDown = ddSymmSiftingDown(table,x,xHigh); - if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem; - - if (moveDown != NULL) { - x = moveDown->y; - i = x; - while ((unsigned) i < table->subtables[i].next) { - i = table->subtables[i].next; - } - } else { - i = x; - x = table->subtables[x].next; - } -#ifdef DD_DEBUG - /* x should be the top of the symmetry group and i the bottom */ - assert((unsigned) i >= table->subtables[i].next); - assert((unsigned) x == table->subtables[i].next); -#endif - finalGroupSize = i - x + 1; - - if (initGroupSize == finalGroupSize) { - /* No new symmetries detected, go back to best position */ - result = ddSymmSiftingBackward(table,moveDown,initialSize); - } else { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - initialSize = table->keys - table->isolated; - moveUp = ddSymmSiftingUp(table,x,xLow); - result = ddSymmSiftingBackward(table,moveUp,initialSize); - } - if (!result) goto ddSymmSiftingConvAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - - return(1); - -ddSymmSiftingConvAuxOutOfMem: - if (moveDown != MV_OOM) { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *) moveDown); - moveDown = move; - } - } - if (moveUp != MV_OOM) { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *) moveUp); - moveUp = move; - } - } - - return(0); - -} /* end of ddSymmSiftingConvAux */ - - -/**Function******************************************************************** - - Synopsis [Moves x up until either it reaches the bound (xLow) or - the size of the DD heap increases too much.] - - Description [Moves x up until either it reaches the bound (xLow) or - the size of the DD heap increases too much. Assumes that x is the top - of a symmetry group. Checks x for symmetry to the adjacent - variables. If symmetry is found, the symmetry group of x is merged - with the symmetry group of the other variable. Returns the set of - moves in case of success; MV_OOM if memory is full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddSymmSiftingUp( - DdManager * table, - int y, - int xLow) -{ - Move *moves; - Move *move; - int x; - int size; - int i; - int gxtop,gybot; - int limitSize; - int xindex, yindex; - int zindex; - int z; - int isolated; - int L; /* lower bound on DD size */ -#ifdef DD_DEBUG - int checkL; -#endif - - - moves = NULL; - yindex = table->invperm[y]; - - /* Initialize the lower bound. - ** The part of the DD below the bottom of y' group will not change. - ** The part of the DD above y that does not interact with y will not - ** change. The rest may vanish in the best case, except for - ** the nodes at level xLow, which will not vanish, regardless. - */ - limitSize = L = table->keys - table->isolated; - gybot = y; - while ((unsigned) gybot < table->subtables[gybot].next) - gybot = table->subtables[gybot].next; - for (z = xLow + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - L -= table->subtables[z].keys - isolated; - } - } - - x = cuddNextLow(table,y); - while (x >= xLow && L <= limitSize) { -#ifdef DD_DEBUG - gybot = y; - while ((unsigned) gybot < table->subtables[gybot].next) - gybot = table->subtables[gybot].next; - checkL = table->keys - table->isolated; - for (z = xLow + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - checkL -= table->subtables[z].keys - isolated; - } - } - assert(L == checkL); -#endif - gxtop = table->subtables[x].next; - if (cuddSymmCheck(table,x,y)) { - /* Symmetry found, attach symm groups */ - table->subtables[x].next = y; - i = table->subtables[y].next; - while (table->subtables[i].next != (unsigned) y) - i = table->subtables[i].next; - table->subtables[i].next = gxtop; - } else if (table->subtables[x].next == (unsigned) x && - table->subtables[y].next == (unsigned) y) { - /* x and y have self symmetry */ - xindex = table->invperm[x]; - size = cuddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtables[x].next == (unsigned) x); - assert(table->subtables[y].next == (unsigned) y); -#endif - if (size == 0) goto ddSymmSiftingUpOutOfMem; - /* Update the lower bound. */ - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[xindex]->ref == 1; - L += table->subtables[y].keys - isolated; - } - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSymmSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > (double) limitSize * table->maxGrowth) - return(moves); - if (size < limitSize) limitSize = size; - } else { /* Group move */ - size = ddSymmGroupMove(table,x,y,&moves); - if (size == 0) goto ddSymmSiftingUpOutOfMem; - /* Update the lower bound. */ - z = moves->y; - do { - zindex = table->invperm[z]; - if (cuddTestInteract(table,zindex,yindex)) { - isolated = table->vars[zindex]->ref == 1; - L += table->subtables[z].keys - isolated; - } - z = table->subtables[z].next; - } while (z != (int) moves->y); - if ((double) size > (double) limitSize * table->maxGrowth) - return(moves); - if (size < limitSize) limitSize = size; - } - y = gxtop; - x = cuddNextLow(table,y); - } - - return(moves); - -ddSymmSiftingUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(MV_OOM); - -} /* end of ddSymmSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Moves x down until either it reaches the bound (xHigh) or - the size of the DD heap increases too much.] - - Description [Moves x down until either it reaches the bound (xHigh) - or the size of the DD heap increases too much. Assumes that x is the - bottom of a symmetry group. Checks x for symmetry to the adjacent - variables. If symmetry is found, the symmetry group of x is merged - with the symmetry group of the other variable. Returns the set of - moves in case of success; MV_OOM if memory is full.] - - SideEffects [None] - -******************************************************************************/ -static Move * -ddSymmSiftingDown( - DdManager * table, - int x, - int xHigh) -{ - Move *moves; - Move *move; - int y; - int size; - int limitSize; - int gxtop,gybot; - int R; /* upper bound on node decrease */ - int xindex, yindex; - int isolated; - int z; - int zindex; -#ifdef DD_DEBUG - int checkR; -#endif - - moves = NULL; - /* Initialize R */ - xindex = table->invperm[x]; - gxtop = table->subtables[x].next; - limitSize = size = table->keys - table->isolated; - R = 0; - for (z = xHigh; z > gxtop; z--) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R += table->subtables[z].keys - isolated; - } - } - - y = cuddNextHigh(table,x); - while (y <= xHigh && size - R < limitSize) { -#ifdef DD_DEBUG - gxtop = table->subtables[x].next; - checkR = 0; - for (z = xHigh; z > gxtop; z--) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - checkR += table->subtables[z].keys - isolated; - } - } - assert(R == checkR); -#endif - gybot = table->subtables[y].next; - while (table->subtables[gybot].next != (unsigned) y) - gybot = table->subtables[gybot].next; - if (cuddSymmCheck(table,x,y)) { - /* Symmetry found, attach symm groups */ - gxtop = table->subtables[x].next; - table->subtables[x].next = y; - table->subtables[gybot].next = gxtop; - } else if (table->subtables[x].next == (unsigned) x && - table->subtables[y].next == (unsigned) y) { - /* x and y have self symmetry */ - /* Update upper bound on node decrease. */ - yindex = table->invperm[y]; - if (cuddTestInteract(table,xindex,yindex)) { - isolated = table->vars[yindex]->ref == 1; - R -= table->subtables[y].keys - isolated; - } - size = cuddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtables[x].next == (unsigned) x); - assert(table->subtables[y].next == (unsigned) y); -#endif - if (size == 0) goto ddSymmSiftingDownOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto ddSymmSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double) size > (double) limitSize * table->maxGrowth) - return(moves); - if (size < limitSize) limitSize = size; - } else { /* Group move */ - /* Update upper bound on node decrease: first phase. */ - gxtop = table->subtables[x].next; - z = gxtop + 1; - do { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R -= table->subtables[z].keys - isolated; - } - z++; - } while (z <= gybot); - size = ddSymmGroupMove(table,x,y,&moves); - if (size == 0) goto ddSymmSiftingDownOutOfMem; - if ((double) size > (double) limitSize * table->maxGrowth) - return(moves); - if (size < limitSize) limitSize = size; - /* Update upper bound on node decrease: second phase. */ - gxtop = table->subtables[gybot].next; - for (z = gxtop + 1; z <= gybot; z++) { - zindex = table->invperm[z]; - if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) { - isolated = table->vars[zindex]->ref == 1; - R += table->subtables[z].keys - isolated; - } - } - } - x = gybot; - y = cuddNextHigh(table,x); - } - - return(moves); - -ddSymmSiftingDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(MV_OOM); - -} /* end of ddSymmSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Swaps two groups.] - - Description [Swaps two groups. x is assumed to be the bottom variable - of the first group. y is assumed to be the top variable of the second - group. Updates the list of moves. Returns the number of keys in the - table if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmGroupMove( - DdManager * table, - int x, - int y, - Move ** moves) -{ - Move *move; - int size; - int i,j; - int xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - int swapx,swapy; - -#if DD_DEBUG - assert(x < y); /* we assume that x < y */ -#endif - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtables[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtables[ybot].next) - ybot = table->subtables[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - - /* Sift the variables of the second group up through the first group. */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddSwapInPlace(table,x,y); - if (size == 0) return(0); - swapx = x; swapy = y; - y = x; - x = y - 1; - } - y = ytop + i; - x = y - 1; - } - - /* fix symmetries */ - y = xtop; /* ytop is now where xtop used to be */ - for (i = 0; i < ysize-1 ; i++) { - table->subtables[y].next = y + 1; - y = y + 1; - } - table->subtables[y].next = xtop; /* y is bottom of its group, join */ - /* its symmetry to top of its group */ - x = y + 1; - newxtop = x; - for (i = 0; i < xsize - 1 ; i++) { - table->subtables[x].next = x + 1; - x = x + 1; - } - table->subtables[x].next = newxtop; /* x is bottom of its group, join */ - /* its symmetry to top of its group */ - /* Store group move */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) return(0); - move->x = swapx; - move->y = swapy; - move->size = size; - move->next = *moves; - *moves = move; - - return(size); - -} /* end of ddSymmGroupMove */ - - -/**Function******************************************************************** - - Synopsis [Undoes the swap of two groups.] - - Description [Undoes the swap of two groups. x is assumed to be the - bottom variable of the first group. y is assumed to be the top - variable of the second group. Returns the number of keys in the table - if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmGroupMoveBackward( - DdManager * table, - int x, - int y) -{ - int size; - int i,j; - int xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - -#if DD_DEBUG - assert(x < y); /* We assume that x < y */ -#endif - - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtables[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtables[ybot].next) - ybot = table->subtables[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - - /* Sift the variables of the second group up through the first group. */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddSwapInPlace(table,x,y); - if (size == 0) return(0); - y = x; - x = cuddNextLow(table,y); - } - y = ytop + i; - x = y - 1; - } - - /* Fix symmetries. */ - y = xtop; - for (i = 0; i < ysize-1 ; i++) { - table->subtables[y].next = y + 1; - y = y + 1; - } - table->subtables[y].next = xtop; /* y is bottom of its group, join */ - /* its symmetry to top of its group */ - x = y + 1; - newxtop = x; - for (i = 0; i < xsize-1 ; i++) { - table->subtables[x].next = x + 1; - x = x + 1; - } - table->subtables[x].next = newxtop; /* x is bottom of its group, join */ - /* its symmetry to top of its group */ - - return(size); - -} /* end of ddSymmGroupMoveBackward */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the DD heap to the position - giving the minimum size.] - - Description [Given a set of moves, returns the DD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddSymmSiftingBackward( - DdManager * table, - Move * moves, - int size) -{ - Move *move; - int res; - - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) return(1); - if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) { - res = cuddSwapInPlace(table,(int)move->x,(int)move->y); -#ifdef DD_DEBUG - assert(table->subtables[move->x].next == move->x); - assert(table->subtables[move->y].next == move->y); -#endif - } else { /* Group move necessary */ - res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y); - } - if (!res) return(0); - } - - return(1); - -} /* end of ddSymmSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Counts numbers of symmetric variables and symmetry - groups.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -static void -ddSymmSummary( - DdManager * table, - int lower, - int upper, - int * symvars, - int * symgroups) -{ - int i,x,gbot; - int TotalSymm = 0; - int TotalSymmGroups = 0; - - for (i = lower; i <= upper; i++) { - if (table->subtables[i].next != (unsigned) i) { - TotalSymmGroups++; - x = i; - do { - TotalSymm++; - gbot = x; - x = table->subtables[x].next; - } while (x != i); -#ifdef DD_DEBUG - assert(table->subtables[gbot].next == (unsigned) i); -#endif - i = gbot; - } - } - *symvars = TotalSymm; - *symgroups = TotalSymmGroups; - - return; - -} /* end of ddSymmSummary */ diff --git a/src/bdd/cudd/cuddTable.c b/src/bdd/cudd/cuddTable.c deleted file mode 100644 index 7f14aed1..00000000 --- a/src/bdd/cudd/cuddTable.c +++ /dev/null @@ -1,3141 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddTable.c] - - PackageName [cudd] - - Synopsis [Unique table management functions.] - - Description [External procedures included in this module: -
                -
              • Cudd_Prime() -
              - Internal procedures included in this module: -
                -
              • cuddAllocNode() -
              • cuddInitTable() -
              • cuddFreeTable() -
              • cuddGarbageCollect() -
              • cuddGarbageCollectZdd() -
              • cuddZddGetNode() -
              • cuddZddGetNodeIVO() -
              • cuddUniqueInter() -
              • cuddUniqueInterIVO() -
              • cuddUniqueInterZdd() -
              • cuddUniqueConst() -
              • cuddRehash() -
              • cuddShrinkSubtable() -
              • cuddInsertSubtables() -
              • cuddDestroySubtables() -
              • cuddResizeTableZdd() -
              • cuddSlowTableGrowth() -
              - Static procedures included in this module: -
                -
              • ddRehashZdd() -
              • ddResizeTable() -
              • cuddFindParent() -
              • cuddOrderedInsert() -
              • cuddOrderedThread() -
              • cuddRotateLeft() -
              • cuddRotateRight() -
              • cuddDoRebalance() -
              • cuddCheckCollisionOrdering() -
              ] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef DD_UNSORTED_FREE_LIST -/* Constants for red/black trees. */ -#define DD_STACK_SIZE 128 -#define DD_RED 0 -#define DD_BLACK 1 -#define DD_PAGE_SIZE 8192 -#define DD_PAGE_MASK ~(DD_PAGE_SIZE - 1) -#define DD_INSERT_COMPARE(x,y) \ - (((ptruint) (x) & DD_PAGE_MASK) - ((ptruint) (y) & DD_PAGE_MASK)) -#endif - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/* This is a hack for when CUDD_VALUE_TYPE is double */ -typedef union hack { - CUDD_VALUE_TYPE value; - unsigned int bits[2]; -} hack; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddTable.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -#ifndef DD_UNSORTED_FREE_LIST -/* Macros for red/black trees. */ -#define DD_COLOR(p) ((p)->index) -#define DD_IS_BLACK(p) ((p)->index == DD_BLACK) -#define DD_IS_RED(p) ((p)->index == DD_RED) -#define DD_LEFT(p) cuddT(p) -#define DD_RIGHT(p) cuddE(p) -#define DD_NEXT(p) ((p)->next) -#endif - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void ddRehashZdd ARGS((DdManager *unique, int i)); -static int ddResizeTable ARGS((DdManager *unique, int index)); -static int cuddFindParent ARGS((DdManager *table, DdNode *node)); -DD_INLINE static void ddFixLimits ARGS((DdManager *unique)); -static void cuddOrderedInsert ARGS((DdNodePtr *root, DdNodePtr node)); -static DdNode * cuddOrderedThread ARGS((DdNode *root, DdNode *list)); -static void cuddRotateLeft ARGS((DdNodePtr *nodeP)); -static void cuddRotateRight ARGS((DdNodePtr *nodeP)); -static void cuddDoRebalance ARGS((DdNodePtr **stack, int stackN)); -static void ddPatchTree ARGS((DdManager *dd, MtrNode *treenode)); -#ifdef DD_DEBUG -static int cuddCheckCollisionOrdering ARGS((DdManager *unique, int i, int j)); -#endif -static void ddReportRefMess ARGS((DdManager *unique, int i, char *caller)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Returns the next prime >= p.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -unsigned int -Cudd_Prime( - unsigned int p) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Fast storage allocation for DdNodes in the table.] - - Description [Fast storage allocation for DdNodes in the table. The - first 4 bytes of a chunk contain a pointer to the next block; the - rest contains DD_MEM_CHUNK spaces for DdNodes. Returns a pointer to - a new node if successful; NULL is memory is full.] - - SideEffects [None] - - SeeAlso [cuddDynamicAllocNode] - -******************************************************************************/ -DdNode * -cuddAllocNode( - DdManager * unique) -{ - int i; - DdNodePtr *mem; - DdNode *list, *node; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - if (unique->nextFree == NULL) { /* free list is empty */ - /* Check for exceeded limits. */ - if ((unique->keys - unique->dead) + (unique->keysZ - unique->deadZ) > - unique->maxLive) { - unique->errorCode = CUDD_TOO_MANY_NODES; - return(NULL); - } - if (unique->stash == NULL || unique->memused > unique->maxmemhard) { - (void) cuddGarbageCollect(unique,1); - mem = NULL; - } - if (unique->nextFree == NULL) { - if (unique->memused > unique->maxmemhard) { - unique->errorCode = CUDD_MAX_MEM_EXCEEDED; - return(NULL); - } - /* Try to allocate a new block. */ - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); - MMoutOfMemory = saveHandler; - if (mem == NULL) { - /* No more memory: Try collecting garbage. If this succeeds, - ** we end up with mem still NULL, but unique->nextFree != - ** NULL. */ - if (cuddGarbageCollect(unique,1) == 0) { - /* Last resort: Free the memory stashed away, if there - ** any. If this succeeeds, mem != NULL and - ** unique->nextFree still NULL. */ - if (unique->stash != NULL) { - FREE(unique->stash); - unique->stash = NULL; - /* Inhibit resizing of tables. */ - cuddSlowTableGrowth(unique); - /* Now try again. */ - mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1); - } - if (mem == NULL) { - /* Out of luck. Call the default handler to do - ** whatever it specifies for a failed malloc. - ** If this handler returns, then set error code, - ** print warning, and return. */ - (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1)); - unique->errorCode = CUDD_MEMORY_OUT; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "cuddAllocNode: out of memory"); - (void) fprintf(unique->err, "Memory in use = %ld\n", - unique->memused); -#endif - return(NULL); - } - } - } - if (mem != NULL) { /* successful allocation; slice memory */ - ptruint offset; - unique->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode); - mem[0] = (DdNodePtr) unique->memoryList; - unique->memoryList = mem; - - /* Here we rely on the fact that a DdNode is as large - ** as 4 pointers. */ - offset = (ptruint) mem & (sizeof(DdNode) - 1); - mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr); - assert(((ptruint) mem & (sizeof(DdNode) - 1)) == 0); - list = (DdNode *) mem; - - i = 1; - do { - list[i - 1].next = &list[i]; - } while (++i < DD_MEM_CHUNK); - - list[DD_MEM_CHUNK-1].next = NULL; - - unique->nextFree = &list[0]; - } - } - } - unique->allocated++; - node = unique->nextFree; - unique->nextFree = node->next; - return(node); - -} /* end of cuddAllocNode */ - - -/**Function******************************************************************** - - Synopsis [Creates and initializes the unique table.] - - Description [Creates and initializes the unique table. Returns a pointer - to the table if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Init cuddFreeTable] - -******************************************************************************/ -DdManager * -cuddInitTable( - unsigned int numVars /* Initial number of BDD variables (and subtables) */, - unsigned int numVarsZ /* Initial number of ZDD variables (and subtables) */, - unsigned int numSlots /* Initial size of the BDD subtables */, - unsigned int looseUpTo /* Limit for fast table growth */) -{ - DdManager *unique = ALLOC(DdManager,1); - int i, j; - DdNodePtr *nodelist; - DdNode *sentinel; - unsigned int slots; - int shift; - - if (unique == NULL) { - return(NULL); - } - sentinel = &(unique->sentinel); - sentinel->ref = 0; - sentinel->index = 0; - cuddT(sentinel) = NULL; - cuddE(sentinel) = NULL; - sentinel->next = NULL; - unique->epsilon = DD_EPSILON; - unique->maxGrowth = DD_MAX_REORDER_GROWTH; - unique->maxGrowthAlt = 2.0 * DD_MAX_REORDER_GROWTH; - unique->reordCycle = 0; /* do not use alternate threshold */ - unique->size = numVars; - unique->sizeZ = numVarsZ; - unique->maxSize = ddMax(DD_DEFAULT_RESIZE, numVars); - unique->maxSizeZ = ddMax(DD_DEFAULT_RESIZE, numVarsZ); - - /* Adjust the requested number of slots to a power of 2. */ - slots = 8; - while (slots < numSlots) { - slots <<= 1; - } - unique->initSlots = slots; - shift = sizeof(int) * 8 - cuddComputeFloorLog2(slots); - - unique->slots = (numVars + numVarsZ + 1) * slots; - unique->keys = 0; - unique->maxLive = ~0; /* very large number */ - unique->keysZ = 0; - unique->dead = 0; - unique->deadZ = 0; - unique->gcFrac = DD_GC_FRAC_HI; - unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); - unique->looseUpTo = looseUpTo; - unique->gcEnabled = 1; - unique->allocated = 0; - unique->reclaimed = 0; - unique->subtables = ALLOC(DdSubtable,unique->maxSize); - if (unique->subtables == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->subtableZ = ALLOC(DdSubtable,unique->maxSizeZ); - if (unique->subtableZ == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->perm = ALLOC(int,unique->maxSize); - if (unique->perm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->invperm = ALLOC(int,unique->maxSize); - if (unique->invperm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->permZ = ALLOC(int,unique->maxSizeZ); - if (unique->permZ == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->invpermZ = ALLOC(int,unique->maxSizeZ); - if (unique->invpermZ == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->map = NULL; - unique->stack = ALLOC(DdNodePtr,ddMax(unique->maxSize,unique->maxSizeZ)+1); - if (unique->stack == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->stack[0] = NULL; /* to suppress harmless UMR */ - -#ifndef DD_NO_DEATH_ROW - unique->deathRowDepth = 1 << cuddComputeFloorLog2(unique->looseUpTo >> 2); - unique->deathRow = ALLOC(DdNodePtr,unique->deathRowDepth); - if (unique->deathRow == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < unique->deathRowDepth; i++) { - unique->deathRow[i] = NULL; - } - unique->nextDead = 0; - unique->deadMask = unique->deathRowDepth - 1; -#endif - - for (i = 0; (unsigned) i < numVars; i++) { - unique->subtables[i].slots = slots; - unique->subtables[i].shift = shift; - unique->subtables[i].keys = 0; - unique->subtables[i].dead = 0; - unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - unique->subtables[i].bindVar = 0; - unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; - unique->subtables[i].pairIndex = 0; - unique->subtables[i].varHandled = 0; - unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; - - nodelist = unique->subtables[i].nodelist = ALLOC(DdNodePtr,slots); - if (nodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = sentinel; - } - unique->perm[i] = i; - unique->invperm[i] = i; - } - for (i = 0; (unsigned) i < numVarsZ; i++) { - unique->subtableZ[i].slots = slots; - unique->subtableZ[i].shift = shift; - unique->subtableZ[i].keys = 0; - unique->subtableZ[i].dead = 0; - unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - nodelist = unique->subtableZ[i].nodelist = ALLOC(DdNodePtr,slots); - if (nodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = NULL; - } - unique->permZ[i] = i; - unique->invpermZ[i] = i; - } - unique->constants.slots = slots; - unique->constants.shift = shift; - unique->constants.keys = 0; - unique->constants.dead = 0; - unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - nodelist = unique->constants.nodelist = ALLOC(DdNodePtr,slots); - if (nodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = NULL; - } - - unique->memoryList = NULL; - unique->nextFree = NULL; - - unique->memused = sizeof(DdManager) + (unique->maxSize + unique->maxSizeZ) - * (sizeof(DdSubtable) + 2 * sizeof(int)) + (numVars + 1) * - slots * sizeof(DdNodePtr) + - (ddMax(unique->maxSize,unique->maxSizeZ) + 1) * sizeof(DdNodePtr); -#ifndef DD_NO_DEATH_ROW - unique->memused += unique->deathRowDepth * sizeof(DdNodePtr); -#endif - - /* Initialize fields concerned with automatic dynamic reordering */ - unique->reorderings = 0; - unique->autoDyn = 0; /* initially disabled */ - unique->autoDynZ = 0; /* initially disabled */ - unique->realign = 0; /* initially disabled */ - unique->realignZ = 0; /* initially disabled */ - unique->reordered = 0; - unique->autoMethod = CUDD_REORDER_SIFT; - unique->autoMethodZ = CUDD_REORDER_SIFT; - unique->nextDyn = DD_FIRST_REORDER; - unique->countDead = ~0; - unique->siftMaxVar = DD_SIFT_MAX_VAR; - unique->siftMaxSwap = DD_SIFT_MAX_SWAPS; - unique->tree = NULL; - unique->treeZ = NULL; - unique->groupcheck = CUDD_GROUP_CHECK7; - unique->recomb = DD_DEFAULT_RECOMB; - unique->symmviolation = 0; - unique->arcviolation = 0; - unique->populationSize = 0; - unique->numberXovers = 0; - unique->linear = NULL; - unique->linearSize = 0; - - /* Initialize ZDD universe. */ - unique->univ = (DdNodePtr *)NULL; - - /* Initialize auxiliary fields. */ - unique->localCaches = NULL; - unique->preGCHook = NULL; - unique->postGCHook = NULL; - unique->preReorderingHook = NULL; - unique->postReorderingHook = NULL; - unique->out = stdout; - unique->err = stderr; - unique->errorCode = CUDD_NO_ERROR; - - /* Initialize statistical counters. */ - unique->maxmemhard = (long) ((~ (unsigned long) 0) >> 1); - unique->garbageCollections = 0; - unique->GCTime = 0; - unique->reordTime = 0; -#ifdef DD_STATS - unique->nodesDropped = 0; - unique->nodesFreed = 0; -#endif - unique->peakLiveNodes = 0; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLookUps = 0; - unique->uniqueLinks = 0; -#endif -#ifdef DD_COUNT - unique->recursiveCalls = 0; - unique->swapSteps = 0; -#ifdef DD_STATS - unique->nextSample = 250000; -#endif -#endif - - return(unique); - -} /* end of cuddInitTable */ - - -/**Function******************************************************************** - - Synopsis [Frees the resources associated to a unique table.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddInitTable] - -******************************************************************************/ -void -cuddFreeTable( - DdManager * unique) -{ - DdNodePtr *next; - DdNodePtr *memlist = unique->memoryList; - int i; - - if (unique->univ != NULL) cuddZddFreeUniv(unique); - while (memlist != NULL) { - next = (DdNodePtr *) memlist[0]; /* link to next block */ - FREE(memlist); - memlist = next; - } - unique->nextFree = NULL; - unique->memoryList = NULL; - - for (i = 0; i < unique->size; i++) { - FREE(unique->subtables[i].nodelist); - } - for (i = 0; i < unique->sizeZ; i++) { - FREE(unique->subtableZ[i].nodelist); - } - FREE(unique->constants.nodelist); - FREE(unique->subtables); - FREE(unique->subtableZ); - FREE(unique->acache); - FREE(unique->perm); - FREE(unique->permZ); - FREE(unique->invperm); - FREE(unique->invpermZ); - FREE(unique->vars); - if (unique->map != NULL) FREE(unique->map); - FREE(unique->stack); -#ifndef DD_NO_DEATH_ROW - FREE(unique->deathRow); -#endif - if (unique->tree != NULL) Mtr_FreeTree(unique->tree); - if (unique->treeZ != NULL) Mtr_FreeTree(unique->treeZ); - if (unique->linear != NULL) FREE(unique->linear); - while (unique->preGCHook != NULL) - Cudd_RemoveHook(unique,unique->preGCHook->f,CUDD_PRE_GC_HOOK); - while (unique->postGCHook != NULL) - Cudd_RemoveHook(unique,unique->postGCHook->f,CUDD_POST_GC_HOOK); - while (unique->preReorderingHook != NULL) - Cudd_RemoveHook(unique,unique->preReorderingHook->f, - CUDD_PRE_REORDERING_HOOK); - while (unique->postReorderingHook != NULL) - Cudd_RemoveHook(unique,unique->postReorderingHook->f, - CUDD_POST_REORDERING_HOOK); - FREE(unique); - -} /* end of cuddFreeTable */ - - -/**Function******************************************************************** - - Synopsis [Performs garbage collection on a unique table.] - - Description [Performs garbage collection on a unique table. - If clearCache is 0, the cache is not cleared. This should only be - specified if the cache has been cleared right before calling - cuddGarbageCollect. (As in the case of dynamic reordering.) - Returns the total number of deleted nodes.] - - SideEffects [None] - - SeeAlso [cuddGarbageCollectZdd] - -******************************************************************************/ -int -cuddGarbageCollect( - DdManager * unique, - int clearCache) -{ - DdHook *hook; - DdCache *cache = unique->cache; - DdNode *sentinel = &(unique->sentinel); - DdNodePtr *nodelist; - int i, j, deleted, totalDeleted; - DdCache *c; - DdNode *node,*next; - DdNodePtr *lastP; - int slots; - long localTime; -#ifndef DD_UNSORTED_FREE_LIST - DdNodePtr tree; -#endif - -#ifndef DD_NO_DEATH_ROW - cuddClearDeathRow(unique); -#endif - - hook = unique->preGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"BDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - - if (unique->dead == 0) { - hook = unique->postGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"BDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - return(0); - } - - /* If many nodes are being reclaimed, we want to resize the tables - ** more aggressively, to reduce the frequency of garbage collection. - */ - if (clearCache && unique->gcFrac == DD_GC_FRAC_LO && - unique->slots <= unique->looseUpTo && unique->stash != NULL) { - unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); -#ifdef DD_VERBOSE - (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_HI); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); -#endif - unique->gcFrac = DD_GC_FRAC_HI; - return(0); - } - - localTime = util_cpu_time(); - - unique->garbageCollections++; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "garbage collecting (%d dead out of %d, min %d)...", - unique->dead, unique->keys, unique->minDead); -#endif - - /* Remove references to garbage collected nodes from the cache. */ - if (clearCache) { - slots = unique->cacheSlots; - for (i = 0; i < slots; i++) { - c = &cache[i]; - if (c->data != NULL) { - if (cuddClean(c->f)->ref == 0 || - cuddClean(c->g)->ref == 0 || - (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) || - (c->data != DD_NON_CONSTANT && - Cudd_Regular(c->data)->ref == 0)) { - c->data = NULL; - unique->cachedeletions++; - } - } - } - cuddLocalCacheClearDead(unique); - } - - /* Now return dead nodes to free list. Count them for sanity check. */ - totalDeleted = 0; -#ifndef DD_UNSORTED_FREE_LIST - tree = NULL; -#endif - - for (i = 0; i < unique->size; i++) { - if (unique->subtables[i].dead == 0) continue; - nodelist = unique->subtables[i].nodelist; - - deleted = 0; - slots = unique->subtables[i].slots; - for (j = 0; j < slots; j++) { - lastP = &(nodelist[j]); - node = *lastP; - while (node != sentinel) { - next = node->next; - if (node->ref == 0) { - deleted++; -#ifndef DD_UNSORTED_FREE_LIST -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - cuddOrderedInsert(&tree,node); -#ifdef __osf__ -#pragma pointer_size restore -#endif -#else - cuddDeallocNode(unique,node); -#endif - } else { - *lastP = node; - lastP = &(node->next); - } - node = next; - } - *lastP = sentinel; - } - if ((unsigned) deleted != unique->subtables[i].dead) { - ddReportRefMess(unique, i, "cuddGarbageCollect"); - } - totalDeleted += deleted; - unique->subtables[i].keys -= deleted; - unique->subtables[i].dead = 0; - } - if (unique->constants.dead != 0) { - nodelist = unique->constants.nodelist; - deleted = 0; - slots = unique->constants.slots; - for (j = 0; j < slots; j++) { - lastP = &(nodelist[j]); - node = *lastP; - while (node != NULL) { - next = node->next; - if (node->ref == 0) { - deleted++; -#ifndef DD_UNSORTED_FREE_LIST -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - cuddOrderedInsert(&tree,node); -#ifdef __osf__ -#pragma pointer_size restore -#endif -#else - cuddDeallocNode(unique,node); -#endif - } else { - *lastP = node; - lastP = &(node->next); - } - node = next; - } - *lastP = NULL; - } - if ((unsigned) deleted != unique->constants.dead) { - ddReportRefMess(unique, CUDD_CONST_INDEX, "cuddGarbageCollect"); - } - totalDeleted += deleted; - unique->constants.keys -= deleted; - unique->constants.dead = 0; - } - if ((unsigned) totalDeleted != unique->dead) { - ddReportRefMess(unique, -1, "cuddGarbageCollect"); - } - unique->keys -= totalDeleted; - unique->dead = 0; -#ifdef DD_STATS - unique->nodesFreed += (double) totalDeleted; -#endif - -#ifndef DD_UNSORTED_FREE_LIST - unique->nextFree = cuddOrderedThread(tree,unique->nextFree); -#endif - - unique->GCTime += util_cpu_time() - localTime; - - hook = unique->postGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"BDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - -#ifdef DD_VERBOSE - (void) fprintf(unique->err," done\n"); -#endif - - return(totalDeleted); - -} /* end of cuddGarbageCollect */ - - -/**Function******************************************************************** - - Synopsis [Performs garbage collection on a ZDD unique table.] - - Description [Performs garbage collection on a ZDD unique table. - If clearCache is 0, the cache is not cleared. This should only be - specified if the cache has been cleared right before calling - cuddGarbageCollectZdd. (As in the case of dynamic reordering.) - Returns the total number of deleted nodes.] - - SideEffects [None] - - SeeAlso [cuddGarbageCollect] - -******************************************************************************/ -int -cuddGarbageCollectZdd( - DdManager * unique, - int clearCache) -{ - DdHook *hook; - DdCache *cache = unique->cache; - DdNodePtr *nodelist; - int i, j, deleted, totalDeleted; - DdCache *c; - DdNode *node,*next; - DdNodePtr *lastP; - int slots; - long localTime; -#ifndef DD_UNSORTED_FREE_LIST - DdNodePtr tree; -#endif - - hook = unique->preGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"ZDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - - if (unique->deadZ == 0) { - hook = unique->postGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"ZDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - return(0); - } - - /* If many nodes are being reclaimed, we want to resize the tables - ** more aggressively, to reduce the frequency of garbage collection. - */ - if (clearCache && unique->slots <= unique->looseUpTo) { - unique->minDead = (unsigned) (DD_GC_FRAC_HI * (double) unique->slots); -#ifdef DD_VERBOSE - if (unique->gcFrac == DD_GC_FRAC_LO) { - (void) fprintf(unique->err,"GC fraction = %.2f\t", - DD_GC_FRAC_HI); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); - } -#endif - unique->gcFrac = DD_GC_FRAC_HI; - } - - localTime = util_cpu_time(); - - unique->garbageCollections++; -#ifdef DD_VERBOSE - (void) fprintf(unique->err,"garbage collecting (%d dead out of %d)...", - unique->deadZ,unique->keysZ); -#endif - - /* Remove references to garbage collected nodes from the cache. */ - if (clearCache) { - slots = unique->cacheSlots; - for (i = 0; i < slots; i++) { - c = &cache[i]; - if (c->data != NULL) { - if (cuddClean(c->f)->ref == 0 || - cuddClean(c->g)->ref == 0 || - (((ptruint)c->f & 0x2) && Cudd_Regular(c->h)->ref == 0) || - (c->data != DD_NON_CONSTANT && - Cudd_Regular(c->data)->ref == 0)) { - c->data = NULL; - unique->cachedeletions++; - } - } - } - } - - /* Now return dead nodes to free list. Count them for sanity check. */ - totalDeleted = 0; -#ifndef DD_UNSORTED_FREE_LIST - tree = NULL; -#endif - - for (i = 0; i < unique->sizeZ; i++) { - if (unique->subtableZ[i].dead == 0) continue; - nodelist = unique->subtableZ[i].nodelist; - - deleted = 0; - slots = unique->subtableZ[i].slots; - for (j = 0; j < slots; j++) { - lastP = &(nodelist[j]); - node = *lastP; - while (node != NULL) { - next = node->next; - if (node->ref == 0) { - deleted++; -#ifndef DD_UNSORTED_FREE_LIST -#ifdef __osf__ -#pragma pointer_size save -#pragma pointer_size short -#endif - cuddOrderedInsert(&tree,node); -#ifdef __osf__ -#pragma pointer_size restore -#endif -#else - cuddDeallocNode(unique,node); -#endif - } else { - *lastP = node; - lastP = &(node->next); - } - node = next; - } - *lastP = NULL; - } - if ((unsigned) deleted != unique->subtableZ[i].dead) { - ddReportRefMess(unique, i, "cuddGarbageCollectZdd"); - } - totalDeleted += deleted; - unique->subtableZ[i].keys -= deleted; - unique->subtableZ[i].dead = 0; - } - - /* No need to examine the constant table for ZDDs. - ** If we did we should be careful not to count whatever dead - ** nodes we found there among the dead ZDD nodes. */ - if ((unsigned) totalDeleted != unique->deadZ) { - ddReportRefMess(unique, -1, "cuddGarbageCollectZdd"); - } - unique->keysZ -= totalDeleted; - unique->deadZ = 0; -#ifdef DD_STATS - unique->nodesFreed += (double) totalDeleted; -#endif - -#ifndef DD_UNSORTED_FREE_LIST - unique->nextFree = cuddOrderedThread(tree,unique->nextFree); -#endif - - unique->GCTime += util_cpu_time() - localTime; - - hook = unique->postGCHook; - while (hook != NULL) { - int res = (hook->f)(unique,"ZDD",NULL); - if (res == 0) return(0); - hook = hook->next; - } - -#ifdef DD_VERBOSE - (void) fprintf(unique->err," done\n"); -#endif - - return(totalDeleted); - -} /* end of cuddGarbageCollectZdd */ - - -/**Function******************************************************************** - - Synopsis [Wrapper for cuddUniqueInterZdd.] - - Description [Wrapper for cuddUniqueInterZdd, which applies the ZDD - reduction rule. Returns a pointer to the result node under normal - conditions; NULL if reordering occurred or memory was exhausted.] - - SideEffects [None] - - SeeAlso [cuddUniqueInterZdd] - -******************************************************************************/ -DdNode * -cuddZddGetNode( - DdManager * zdd, - int id, - DdNode * T, - DdNode * E) -{ - DdNode *node; - - if (T == DD_ZERO(zdd)) - return(E); - node = cuddUniqueInterZdd(zdd, id, T, E); - return(node); - -} /* end of cuddZddGetNode */ - - -/**Function******************************************************************** - - Synopsis [Wrapper for cuddUniqueInterZdd that is independent of variable - ordering.] - - Description [Wrapper for cuddUniqueInterZdd that is independent of - variable ordering (IVO). This function does not require parameter - index to precede the indices of the top nodes of g and h in the - variable order. Returns a pointer to the result node under normal - conditions; NULL if reordering occurred or memory was exhausted.] - - SideEffects [None] - - SeeAlso [cuddZddGetNode cuddZddIsop] - -******************************************************************************/ -DdNode * -cuddZddGetNodeIVO( - DdManager * dd, - int index, - DdNode * g, - DdNode * h) -{ - DdNode *f, *r, *t; - DdNode *zdd_one = DD_ONE(dd); - DdNode *zdd_zero = DD_ZERO(dd); - - f = cuddUniqueInterZdd(dd, index, zdd_one, zdd_zero); - if (f == NULL) { - return(NULL); - } - cuddRef(f); - t = cuddZddProduct(dd, f, g); - if (t == NULL) { - Cudd_RecursiveDerefZdd(dd, f); - return(NULL); - } - cuddRef(t); - Cudd_RecursiveDerefZdd(dd, f); - r = cuddZddUnion(dd, t, h); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, t); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDerefZdd(dd, t); - - cuddDeref(r); - return(r); - -} /* end of cuddZddGetNodeIVO */ - - -/**Function******************************************************************** - - Synopsis [Checks the unique table for the existence of an internal node.] - - Description [Checks the unique table for the existence of an internal - node. If it does not exist, it creates a new one. Does not - modify the reference count of whatever is returned. A newly created - internal node comes back with a reference count 0. For a newly - created node, increments the reference counts of what T and E point - to. Returns a pointer to the new node if successful; NULL if memory - is exhausted or if reordering took place.] - - SideEffects [None] - - SeeAlso [cuddUniqueInterZdd] - -******************************************************************************/ -DdNode * -cuddUniqueInter( - DdManager * unique, - int index, - DdNode * T, - DdNode * E) -{ - int pos; - unsigned int level; - int retval; - DdNodePtr *nodelist; - DdNode *looking; - DdNodePtr *previousP; - DdSubtable *subtable; - int gcNumber; - -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLookUps++; -#endif - - if (index >= unique->size) { - if (!ddResizeTable(unique,index)) return(NULL); - } - - level = unique->perm[index]; - subtable = &(unique->subtables[level]); - -#ifdef DD_DEBUG - assert(level < (unsigned) cuddI(unique,T->index)); - assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index)); -#endif - - pos = ddHash(T, E, subtable->shift); - nodelist = subtable->nodelist; - previousP = &(nodelist[pos]); - looking = *previousP; - - while (T < cuddT(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - while (T == cuddT(looking) && E < cuddE(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - if (T == cuddT(looking) && E == cuddE(looking)) { - if (looking->ref == 0) { - cuddReclaim(unique,looking); - } - return(looking); - } - - /* countDead is 0 if deads should be counted and ~0 if they should not. */ - if (unique->autoDyn && - unique->keys - (unique->dead & unique->countDead) >= unique->nextDyn) { -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(unique); - if (retval != 0) return(NULL); - retval = Cudd_CheckKeys(unique); - if (retval != 0) return(NULL); -#endif - retval = Cudd_ReduceHeap(unique,unique->autoMethod,10); /* 10 = whatever */ - if (retval == 0) unique->reordered = 2; -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(unique); - if (retval != 0) unique->reordered = 2; - retval = Cudd_CheckKeys(unique); - if (retval != 0) unique->reordered = 2; -#endif - return(NULL); - } - - if (subtable->keys > subtable->maxKeys) { - if (unique->gcEnabled && - ((unique->dead > unique->minDead) || - ((unique->dead > unique->minDead / 2) && - (subtable->dead > subtable->keys * 0.95)))) { /* too many dead */ - (void) cuddGarbageCollect(unique,1); - } else { - cuddRehash(unique,(int)level); - } - /* Update pointer to insertion point. In the case of rehashing, - ** the slot may have changed. In the case of garbage collection, - ** the predecessor may have been dead. */ - pos = ddHash(T, E, subtable->shift); - nodelist = subtable->nodelist; - previousP = &(nodelist[pos]); - looking = *previousP; - - while (T < cuddT(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - while (T == cuddT(looking) && E < cuddE(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - } - - gcNumber = unique->garbageCollections; - looking = cuddAllocNode(unique); - if (looking == NULL) { - return(NULL); - } - unique->keys++; - subtable->keys++; - - if (gcNumber != unique->garbageCollections) { - DdNode *looking2; - pos = ddHash(T, E, subtable->shift); - nodelist = subtable->nodelist; - previousP = &(nodelist[pos]); - looking2 = *previousP; - - while (T < cuddT(looking2)) { - previousP = &(looking2->next); - looking2 = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - while (T == cuddT(looking2) && E < cuddE(looking2)) { - previousP = &(looking2->next); - looking2 = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - } - looking->ref = 0; - looking->index = index; - cuddT(looking) = T; - cuddE(looking) = E; - looking->next = *previousP; - *previousP = looking; - cuddSatInc(T->ref); /* we know T is a regular pointer */ - cuddRef(E); - -#ifdef DD_DEBUG - cuddCheckCollisionOrdering(unique,level,pos); -#endif - - return(looking); - -} /* end of cuddUniqueInter */ - - -/**Function******************************************************************** - - Synopsis [Wrapper for cuddUniqueInter that is independent of variable - ordering.] - - Description [Wrapper for cuddUniqueInter that is independent of - variable ordering (IVO). This function does not require parameter - index to precede the indices of the top nodes of T and E in the - variable order. Returns a pointer to the result node under normal - conditions; NULL if reordering occurred or memory was exhausted.] - - SideEffects [None] - - SeeAlso [cuddUniqueInter Cudd_MakeBddFromZddCover] - -******************************************************************************/ -DdNode * -cuddUniqueInterIVO( - DdManager * unique, - int index, - DdNode * T, - DdNode * E) -{ - DdNode *result; - DdNode *v; - - v = cuddUniqueInter(unique, index, DD_ONE(unique), - Cudd_Not(DD_ONE(unique))); - if (v == NULL) - return(NULL); - cuddRef(v); - result = cuddBddIteRecur(unique, v, T, E); - Cudd_RecursiveDeref(unique, v); - return(result); -} - - -/**Function******************************************************************** - - Synopsis [Checks the unique table for the existence of an internal - ZDD node.] - - Description [Checks the unique table for the existence of an internal - ZDD node. If it does not exist, it creates a new one. Does not - modify the reference count of whatever is returned. A newly created - internal node comes back with a reference count 0. For a newly - created node, increments the reference counts of what T and E point - to. Returns a pointer to the new node if successful; NULL if memory - is exhausted or if reordering took place.] - - SideEffects [None] - - SeeAlso [cuddUniqueInter] - -******************************************************************************/ -DdNode * -cuddUniqueInterZdd( - DdManager * unique, - int index, - DdNode * T, - DdNode * E) -{ - int pos; - unsigned int level; - int retval; - DdNodePtr *nodelist; - DdNode *looking; - DdSubtable *subtable; - -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLookUps++; -#endif - - if (index >= unique->sizeZ) { - if (!cuddResizeTableZdd(unique,index)) return(NULL); - } - - level = unique->permZ[index]; - subtable = &(unique->subtableZ[level]); - -#ifdef DD_DEBUG - assert(level < (unsigned) cuddIZ(unique,T->index)); - assert(level < (unsigned) cuddIZ(unique,Cudd_Regular(E)->index)); -#endif - - if (subtable->keys > subtable->maxKeys) { - if (unique->gcEnabled && ((unique->deadZ > unique->minDead) || - (10 * subtable->dead > 9 * subtable->keys))) { /* too many dead */ - (void) cuddGarbageCollectZdd(unique,1); - } else { - ddRehashZdd(unique,(int)level); - } - } - - pos = ddHash(T, E, subtable->shift); - nodelist = subtable->nodelist; - looking = nodelist[pos]; - - while (looking != NULL) { - if (cuddT(looking) == T && cuddE(looking) == E) { - if (looking->ref == 0) { - cuddReclaimZdd(unique,looking); - } - return(looking); - } - looking = looking->next; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - - /* countDead is 0 if deads should be counted and ~0 if they should not. */ - if (unique->autoDynZ && - unique->keysZ - (unique->deadZ & unique->countDead) >= unique->nextDyn) { -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(unique); - if (retval != 0) return(NULL); - retval = Cudd_CheckKeys(unique); - if (retval != 0) return(NULL); -#endif - retval = Cudd_zddReduceHeap(unique,unique->autoMethodZ,10); /* 10 = whatever */ - if (retval == 0) unique->reordered = 2; -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(unique); - if (retval != 0) unique->reordered = 2; - retval = Cudd_CheckKeys(unique); - if (retval != 0) unique->reordered = 2; -#endif - return(NULL); - } - - unique->keysZ++; - subtable->keys++; - - looking = cuddAllocNode(unique); - if (looking == NULL) return(NULL); - looking->ref = 0; - looking->index = index; - cuddT(looking) = T; - cuddE(looking) = E; - looking->next = nodelist[pos]; - nodelist[pos] = looking; - cuddRef(T); - cuddRef(E); - - return(looking); - -} /* end of cuddUniqueInterZdd */ - - -/**Function******************************************************************** - - Synopsis [Checks the unique table for the existence of a constant node.] - - Description [Checks the unique table for the existence of a constant node. - If it does not exist, it creates a new one. Does not - modify the reference count of whatever is returned. A newly created - internal node comes back with a reference count 0. Returns a - pointer to the new node.] - - SideEffects [None] - -******************************************************************************/ -DdNode * -cuddUniqueConst( - DdManager * unique, - CUDD_VALUE_TYPE value) -{ - int pos; - DdNodePtr *nodelist; - DdNode *looking; - hack split; - -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLookUps++; -#endif - - if (unique->constants.keys > unique->constants.maxKeys) { - if (unique->gcEnabled && ((unique->dead > unique->minDead) || - (10 * unique->constants.dead > 9 * unique->constants.keys))) { /* too many dead */ - (void) cuddGarbageCollect(unique,1); - } else { - cuddRehash(unique,CUDD_CONST_INDEX); - } - } - - cuddAdjust(value); /* for the case of crippled infinities */ - - if (ddAbs(value) < unique->epsilon) { - value = 0.0; - } - split.value = value; - - pos = ddHash(split.bits[0], split.bits[1], unique->constants.shift); - nodelist = unique->constants.nodelist; - looking = nodelist[pos]; - - /* Here we compare values both for equality and for difference less - * than epsilon. The first comparison is required when values are - * infinite, since Infinity - Infinity is NaN and NaN < X is 0 for - * every X. - */ - while (looking != NULL) { - if (looking->type.value == value || - ddEqualVal(looking->type.value,value,unique->epsilon)) { - if (looking->ref == 0) { - cuddReclaim(unique,looking); - } - return(looking); - } - looking = looking->next; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - - unique->keys++; - unique->constants.keys++; - - looking = cuddAllocNode(unique); - if (looking == NULL) return(NULL); - looking->ref = 0; - looking->index = CUDD_CONST_INDEX; - looking->type.value = value; - looking->next = nodelist[pos]; - nodelist[pos] = looking; - - return(looking); - -} /* end of cuddUniqueConst */ - - -/**Function******************************************************************** - - Synopsis [Rehashes a unique subtable.] - - Description [Doubles the size of a unique subtable and rehashes its - contents.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddRehash( - DdManager * unique, - int i) -{ - unsigned int slots, oldslots; - int shift, oldshift; - int j, pos; - DdNodePtr *nodelist, *oldnodelist; - DdNode *node, *next; - DdNode *sentinel = &(unique->sentinel); - hack split; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - if (unique->gcFrac == DD_GC_FRAC_HI && unique->slots > unique->looseUpTo) { - unique->gcFrac = DD_GC_FRAC_LO; - unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); -#ifdef DD_VERBOSE - (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_LO); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); -#endif - } - - if (unique->gcFrac != DD_GC_FRAC_MIN && unique->memused > unique->maxmem) { - unique->gcFrac = DD_GC_FRAC_MIN; - unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); -#ifdef DD_VERBOSE - (void) fprintf(unique->err,"GC fraction = %.2f\t", DD_GC_FRAC_MIN); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); -#endif - cuddShrinkDeathRow(unique); - if (cuddGarbageCollect(unique,1) > 0) return; - } - - if (i != CUDD_CONST_INDEX) { - oldslots = unique->subtables[i].slots; - oldshift = unique->subtables[i].shift; - oldnodelist = unique->subtables[i].nodelist; - - /* Compute the new size of the subtable. */ - slots = oldslots << 1; - shift = oldshift - 1; - - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - nodelist = ALLOC(DdNodePtr, slots); - MMoutOfMemory = saveHandler; - if (nodelist == NULL) { - (void) fprintf(unique->err, - "Unable to resize subtable %d for lack of memory\n", - i); - /* Prevent frequent resizing attempts. */ - (void) cuddGarbageCollect(unique,1); - if (unique->stash != NULL) { - FREE(unique->stash); - unique->stash = NULL; - /* Inhibit resizing of tables. */ - cuddSlowTableGrowth(unique); - } - return; - } - unique->subtables[i].nodelist = nodelist; - unique->subtables[i].slots = slots; - unique->subtables[i].shift = shift; - unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - - /* Move the nodes from the old table to the new table. - ** This code depends on the type of hash function. - ** It assumes that the effect of doubling the size of the table - ** is to retain one more bit of the 32-bit hash value. - ** The additional bit is the LSB. */ - for (j = 0; (unsigned) j < oldslots; j++) { - DdNodePtr *evenP, *oddP; - node = oldnodelist[j]; - evenP = &(nodelist[j<<1]); - oddP = &(nodelist[(j<<1)+1]); - while (node != sentinel) { - next = node->next; - pos = ddHash(cuddT(node), cuddE(node), shift); - if (pos & 1) { - *oddP = node; - oddP = &(node->next); - } else { - *evenP = node; - evenP = &(node->next); - } - node = next; - } - *evenP = *oddP = sentinel; - } - FREE(oldnodelist); - -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "rehashing layer %d: keys %d dead %d new size %d\n", - i, unique->subtables[i].keys, - unique->subtables[i].dead, slots); -#endif - } else { - oldslots = unique->constants.slots; - oldshift = unique->constants.shift; - oldnodelist = unique->constants.nodelist; - - /* The constant subtable is never subjected to reordering. - ** Therefore, when it is resized, it is because it has just - ** reached the maximum load. We can safely just double the size, - ** with no need for the loop we use for the other tables. - */ - slots = oldslots << 1; - shift = oldshift - 1; - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - nodelist = ALLOC(DdNodePtr, slots); - MMoutOfMemory = saveHandler; - if (nodelist == NULL) { - int j; - (void) fprintf(unique->err, - "Unable to resize constant subtable for lack of memory\n"); - (void) cuddGarbageCollect(unique,1); - for (j = 0; j < unique->size; j++) { - unique->subtables[j].maxKeys <<= 1; - } - unique->constants.maxKeys <<= 1; - return; - } - unique->constants.slots = slots; - unique->constants.shift = shift; - unique->constants.maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - unique->constants.nodelist = nodelist; - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = NULL; - } - for (j = 0; (unsigned) j < oldslots; j++) { - node = oldnodelist[j]; - while (node != NULL) { - next = node->next; - split.value = cuddV(node); - pos = ddHash(split.bits[0], split.bits[1], shift); - node->next = nodelist[pos]; - nodelist[pos] = node; - node = next; - } - } - FREE(oldnodelist); - -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "rehashing constants: keys %d dead %d new size %d\n", - unique->constants.keys,unique->constants.dead,slots); -#endif - } - - /* Update global data */ - - unique->memused += (slots - oldslots) * sizeof(DdNodePtr); - unique->slots += (slots - oldslots); - ddFixLimits(unique); - -} /* end of cuddRehash */ - - -/**Function******************************************************************** - - Synopsis [Shrinks a subtable.] - - Description [Shrinks a subtable.] - - SideEffects [None] - - SeeAlso [cuddRehash] - -******************************************************************************/ -void -cuddShrinkSubtable( - DdManager *unique, - int i) -{ - int j; - int shift, posn; - DdNodePtr *nodelist, *oldnodelist; - DdNode *node, *next; - DdNode *sentinel = &(unique->sentinel); - unsigned int slots, oldslots; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - oldnodelist = unique->subtables[i].nodelist; - oldslots = unique->subtables[i].slots; - slots = oldslots >> 1; - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - nodelist = ALLOC(DdNodePtr, slots); - MMoutOfMemory = saveHandler; - if (nodelist == NULL) { - return; - } - unique->subtables[i].nodelist = nodelist; - unique->subtables[i].slots = slots; - unique->subtables[i].shift++; - unique->subtables[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "shrunk layer %d (%d keys) from %d to %d slots\n", - i, unique->subtables[i].keys, oldslots, slots); -#endif - - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = sentinel; - } - shift = unique->subtables[i].shift; - for (j = 0; (unsigned) j < oldslots; j++) { - node = oldnodelist[j]; - while (node != sentinel) { - DdNode *looking, *T, *E; - DdNodePtr *previousP; - next = node->next; - posn = ddHash(cuddT(node), cuddE(node), shift); - previousP = &(nodelist[posn]); - looking = *previousP; - T = cuddT(node); - E = cuddE(node); - while (T < cuddT(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - while (T == cuddT(looking) && E < cuddE(looking)) { - previousP = &(looking->next); - looking = *previousP; -#ifdef DD_UNIQUE_PROFILE - unique->uniqueLinks++; -#endif - } - node->next = *previousP; - *previousP = node; - node = next; - } - } - FREE(oldnodelist); - - unique->memused += ((long) slots - (long) oldslots) * sizeof(DdNode *); - unique->slots += slots - oldslots; - unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); - unique->cacheSlack = (int) - ddMin(unique->maxCacheHard,DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) - - 2 * (int) unique->cacheSlots; - -} /* end of cuddShrinkSubtable */ - - -/**Function******************************************************************** - - Synopsis [Inserts n new subtables in a unique table at level.] - - Description [Inserts n new subtables in a unique table at level. - The number n should be positive, and level should be an existing level. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddDestroySubtables] - -******************************************************************************/ -int -cuddInsertSubtables( - DdManager * unique, - int n, - int level) -{ - DdSubtable *newsubtables; - DdNodePtr *newnodelist; - DdNodePtr *newvars; - DdNode *sentinel = &(unique->sentinel); - int oldsize,newsize; - int i,j,index,reorderSave; - unsigned int numSlots = unique->initSlots; - int *newperm, *newinvperm, *newmap; - DdNode *one, *zero; - -#ifdef DD_DEBUG - assert(n > 0 && level < unique->size); -#endif - - oldsize = unique->size; - /* Easy case: there is still room in the current table. */ - if (oldsize + n <= unique->maxSize) { - /* Shift the tables at and below level. */ - for (i = oldsize - 1; i >= level; i--) { - unique->subtables[i+n].slots = unique->subtables[i].slots; - unique->subtables[i+n].shift = unique->subtables[i].shift; - unique->subtables[i+n].keys = unique->subtables[i].keys; - unique->subtables[i+n].maxKeys = unique->subtables[i].maxKeys; - unique->subtables[i+n].dead = unique->subtables[i].dead; - unique->subtables[i+n].nodelist = unique->subtables[i].nodelist; - unique->subtables[i+n].bindVar = unique->subtables[i].bindVar; - unique->subtables[i+n].varType = unique->subtables[i].varType; - unique->subtables[i+n].pairIndex = unique->subtables[i].pairIndex; - unique->subtables[i+n].varHandled = unique->subtables[i].varHandled; - unique->subtables[i+n].varToBeGrouped = - unique->subtables[i].varToBeGrouped; - - index = unique->invperm[i]; - unique->invperm[i+n] = index; - unique->perm[index] += n; - } - /* Create new subtables. */ - for (i = 0; i < n; i++) { - unique->subtables[level+i].slots = numSlots; - unique->subtables[level+i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - unique->subtables[level+i].keys = 0; - unique->subtables[level+i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - unique->subtables[level+i].dead = 0; - unique->subtables[level+i].bindVar = 0; - unique->subtables[level+i].varType = CUDD_VAR_PRIMARY_INPUT; - unique->subtables[level+i].pairIndex = 0; - unique->subtables[level+i].varHandled = 0; - unique->subtables[level+i].varToBeGrouped = CUDD_LAZY_NONE; - - unique->perm[oldsize+i] = level + i; - unique->invperm[level+i] = oldsize + i; - newnodelist = unique->subtables[level+i].nodelist = - ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = sentinel; - } - } - if (unique->map != NULL) { - for (i = 0; i < n; i++) { - unique->map[oldsize+i] = oldsize + i; - } - } - } else { - /* The current table is too small: we need to allocate a new, - ** larger one; move all old subtables, and initialize the new - ** subtables. - */ - newsize = oldsize + n + DD_DEFAULT_RESIZE; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "Increasing the table size from %d to %d\n", - unique->maxSize, newsize); -#endif - /* Allocate memory for new arrays (except nodelists). */ - newsubtables = ALLOC(DdSubtable,newsize); - if (newsubtables == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newvars = ALLOC(DdNodePtr,newsize); - if (newvars == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - FREE(newsubtables); - return(0); - } - newperm = ALLOC(int,newsize); - if (newperm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - FREE(newsubtables); - FREE(newvars); - return(0); - } - newinvperm = ALLOC(int,newsize); - if (newinvperm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - FREE(newsubtables); - FREE(newvars); - FREE(newperm); - return(0); - } - if (unique->map != NULL) { - newmap = ALLOC(int,newsize); - if (newmap == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - FREE(newsubtables); - FREE(newvars); - FREE(newperm); - FREE(newinvperm); - return(0); - } - unique->memused += (newsize - unique->maxSize) * sizeof(int); - } - unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * - sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); - /* Copy levels before insertion points from old tables. */ - for (i = 0; i < level; i++) { - newsubtables[i].slots = unique->subtables[i].slots; - newsubtables[i].shift = unique->subtables[i].shift; - newsubtables[i].keys = unique->subtables[i].keys; - newsubtables[i].maxKeys = unique->subtables[i].maxKeys; - newsubtables[i].dead = unique->subtables[i].dead; - newsubtables[i].nodelist = unique->subtables[i].nodelist; - newsubtables[i].bindVar = unique->subtables[i].bindVar; - newsubtables[i].varType = unique->subtables[i].varType; - newsubtables[i].pairIndex = unique->subtables[i].pairIndex; - newsubtables[i].varHandled = unique->subtables[i].varHandled; - newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; - - newvars[i] = unique->vars[i]; - newperm[i] = unique->perm[i]; - newinvperm[i] = unique->invperm[i]; - } - /* Finish initializing permutation for new table to old one. */ - for (i = level; i < oldsize; i++) { - newperm[i] = unique->perm[i]; - } - /* Initialize new levels. */ - for (i = level; i < level + n; i++) { - newsubtables[i].slots = numSlots; - newsubtables[i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - newsubtables[i].keys = 0; - newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - newsubtables[i].dead = 0; - newsubtables[i].bindVar = 0; - newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; - newsubtables[i].pairIndex = 0; - newsubtables[i].varHandled = 0; - newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; - - newperm[oldsize + i - level] = i; - newinvperm[i] = oldsize + i - level; - newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - /* We are going to leak some memory. We should clean up. */ - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = sentinel; - } - } - /* Copy the old tables for levels past the insertion point. */ - for (i = level; i < oldsize; i++) { - newsubtables[i+n].slots = unique->subtables[i].slots; - newsubtables[i+n].shift = unique->subtables[i].shift; - newsubtables[i+n].keys = unique->subtables[i].keys; - newsubtables[i+n].maxKeys = unique->subtables[i].maxKeys; - newsubtables[i+n].dead = unique->subtables[i].dead; - newsubtables[i+n].nodelist = unique->subtables[i].nodelist; - newsubtables[i+n].bindVar = unique->subtables[i].bindVar; - newsubtables[i+n].varType = unique->subtables[i].varType; - newsubtables[i+n].pairIndex = unique->subtables[i].pairIndex; - newsubtables[i+n].varHandled = unique->subtables[i].varHandled; - newsubtables[i+n].varToBeGrouped = - unique->subtables[i].varToBeGrouped; - - newvars[i] = unique->vars[i]; - index = unique->invperm[i]; - newinvperm[i+n] = index; - newperm[index] += n; - } - /* Update the map. */ - if (unique->map != NULL) { - for (i = 0; i < oldsize; i++) { - newmap[i] = unique->map[i]; - } - for (i = oldsize; i < oldsize + n; i++) { - newmap[i] = i; - } - FREE(unique->map); - unique->map = newmap; - } - /* Install the new tables and free the old ones. */ - FREE(unique->subtables); - unique->subtables = newsubtables; - unique->maxSize = newsize; - FREE(unique->vars); - unique->vars = newvars; - FREE(unique->perm); - unique->perm = newperm; - FREE(unique->invperm); - unique->invperm = newinvperm; - /* Update the stack for iterative procedures. */ - if (newsize > unique->maxSizeZ) { - FREE(unique->stack); - unique->stack = ALLOC(DdNodePtr,newsize + 1); - if (unique->stack == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->stack[0] = NULL; /* to suppress harmless UMR */ - unique->memused += - (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) - * sizeof(DdNode *); - } - } - /* Update manager parameters to account for the new subtables. */ - unique->slots += n * numSlots; - ddFixLimits(unique); - unique->size += n; - - /* Now that the table is in a coherent state, create the new - ** projection functions. We need to temporarily disable reordering, - ** because we cannot reorder without projection functions in place. - **/ - one = unique->one; - zero = Cudd_Not(one); - - reorderSave = unique->autoDyn; - unique->autoDyn = 0; - for (i = oldsize; i < oldsize + n; i++) { - unique->vars[i] = cuddUniqueInter(unique,i,one,zero); - if (unique->vars[i] == NULL) { - unique->autoDyn = reorderSave; - /* Shift everything back so table remains coherent. */ - for (j = oldsize; j < i; j++) { - Cudd_IterDerefBdd(unique,unique->vars[j]); - cuddDeallocNode(unique,unique->vars[j]); - unique->vars[j] = NULL; - } - for (j = level; j < oldsize; j++) { - unique->subtables[j].slots = unique->subtables[j+n].slots; - unique->subtables[j].slots = unique->subtables[j+n].slots; - unique->subtables[j].shift = unique->subtables[j+n].shift; - unique->subtables[j].keys = unique->subtables[j+n].keys; - unique->subtables[j].maxKeys = - unique->subtables[j+n].maxKeys; - unique->subtables[j].dead = unique->subtables[j+n].dead; - FREE(unique->subtables[j].nodelist); - unique->subtables[j].nodelist = - unique->subtables[j+n].nodelist; - unique->subtables[j+n].nodelist = NULL; - unique->subtables[j].bindVar = - unique->subtables[j+n].bindVar; - unique->subtables[j].varType = - unique->subtables[j+n].varType; - unique->subtables[j].pairIndex = - unique->subtables[j+n].pairIndex; - unique->subtables[j].varHandled = - unique->subtables[j+n].varHandled; - unique->subtables[j].varToBeGrouped = - unique->subtables[j+n].varToBeGrouped; - index = unique->invperm[j+n]; - unique->invperm[j] = index; - unique->perm[index] -= n; - } - unique->size = oldsize; - unique->slots -= n * numSlots; - ddFixLimits(unique); - (void) Cudd_DebugCheck(unique); - return(0); - } - cuddRef(unique->vars[i]); - } - if (unique->tree != NULL) { - unique->tree->size += n; - unique->tree->index = unique->invperm[0]; - ddPatchTree(unique,unique->tree); - } - unique->autoDyn = reorderSave; - - return(1); - -} /* end of cuddInsertSubtables */ - - -/**Function******************************************************************** - - Synopsis [Destroys the n most recently created subtables in a unique table.] - - Description [Destroys the n most recently created subtables in a unique - table. n should be positive. The subtables should not contain any live - nodes, except the (isolated) projection function. The projection - functions are freed. Returns 1 if successful; 0 otherwise.] - - SideEffects [The variable map used for fast variable substitution is - destroyed if it exists. In this case the cache is also cleared.] - - SeeAlso [cuddInsertSubtables Cudd_SetVarMap] - -******************************************************************************/ -int -cuddDestroySubtables( - DdManager * unique, - int n) -{ - DdSubtable *subtables; - DdNodePtr *nodelist; - DdNodePtr *vars; - int firstIndex, lastIndex; - int index, level, newlevel; - int lowestLevel; - int shift; - int found; - - /* Sanity check and set up. */ - if (n <= 0) return(0); - if (n > unique->size) n = unique->size; - - subtables = unique->subtables; - vars = unique->vars; - firstIndex = unique->size - n; - lastIndex = unique->size; - - /* Check for nodes labeled by the variables being destroyed - ** that may still be in use. It is allowed to destroy a variable - ** only if there are no such nodes. Also, find the lowest level - ** among the variables being destroyed. This will make further - ** processing more efficient. - */ - lowestLevel = unique->size; - for (index = firstIndex; index < lastIndex; index++) { - level = unique->perm[index]; - if (level < lowestLevel) lowestLevel = level; - nodelist = subtables[level].nodelist; - if (subtables[level].keys - subtables[level].dead != 1) return(0); - /* The projection function should be isolated. If the ref count - ** is 1, everything is OK. If the ref count is saturated, then - ** we need to make sure that there are no nodes pointing to it. - ** As for the external references, we assume the application is - ** responsible for them. - */ - if (vars[index]->ref != 1) { - if (vars[index]->ref != DD_MAXREF) return(0); - found = cuddFindParent(unique,vars[index]); - if (found) { - return(0); - } else { - vars[index]->ref = 1; - } - } - Cudd_RecursiveDeref(unique,vars[index]); - } - - /* Collect garbage, because we cannot afford having dead nodes pointing - ** to the dead nodes in the subtables being destroyed. - */ - (void) cuddGarbageCollect(unique,1); - - /* Here we know we can destroy our subtables. */ - for (index = firstIndex; index < lastIndex; index++) { - level = unique->perm[index]; - nodelist = subtables[level].nodelist; -#ifdef DD_DEBUG - assert(subtables[level].keys == 0); -#endif - FREE(nodelist); - unique->memused -= sizeof(DdNodePtr) * subtables[level].slots; - unique->slots -= subtables[level].slots; - unique->dead -= subtables[level].dead; - } - - /* Here all subtables to be destroyed have their keys field == 0 and - ** their hash tables have been freed. - ** We now scan the subtables from level lowestLevel + 1 to level size - 1, - ** shifting the subtables as required. We keep a running count of - ** how many subtables have been moved, so that we know by how many - ** positions each subtable should be shifted. - */ - shift = 1; - for (level = lowestLevel + 1; level < unique->size; level++) { - if (subtables[level].keys == 0) { - shift++; - continue; - } - newlevel = level - shift; - subtables[newlevel].slots = subtables[level].slots; - subtables[newlevel].shift = subtables[level].shift; - subtables[newlevel].keys = subtables[level].keys; - subtables[newlevel].maxKeys = subtables[level].maxKeys; - subtables[newlevel].dead = subtables[level].dead; - subtables[newlevel].nodelist = subtables[level].nodelist; - index = unique->invperm[level]; - unique->perm[index] = newlevel; - unique->invperm[newlevel] = index; - subtables[newlevel].bindVar = subtables[level].bindVar; - subtables[newlevel].varType = subtables[level].varType; - subtables[newlevel].pairIndex = subtables[level].pairIndex; - subtables[newlevel].varHandled = subtables[level].varHandled; - subtables[newlevel].varToBeGrouped = subtables[level].varToBeGrouped; - } - /* Destroy the map. If a surviving variable is - ** mapped to a dying variable, and the map were used again, - ** an out-of-bounds access to unique->vars would result. */ - if (unique->map != NULL) { - cuddCacheFlush(unique); - FREE(unique->map); - unique->map = NULL; - } - - unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); - unique->size -= n; - - return(1); - -} /* end of cuddDestroySubtables */ - - -/**Function******************************************************************** - - Synopsis [Increases the number of ZDD subtables in a unique table so - that it meets or exceeds index.] - - Description [Increases the number of ZDD subtables in a unique table so - that it meets or exceeds index. When new ZDD variables are created, it - is possible to preserve the functions unchanged, or it is possible to - preserve the covers unchanged, but not both. cuddResizeTableZdd preserves - the covers. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [ddResizeTable] - -******************************************************************************/ -int -cuddResizeTableZdd( - DdManager * unique, - int index) -{ - DdSubtable *newsubtables; - DdNodePtr *newnodelist; - int oldsize,newsize; - int i,j,reorderSave; - unsigned int numSlots = unique->initSlots; - int *newperm, *newinvperm; - DdNode *one, *zero; - - oldsize = unique->sizeZ; - /* Easy case: there is still room in the current table. */ - if (index < unique->maxSizeZ) { - for (i = oldsize; i <= index; i++) { - unique->subtableZ[i].slots = numSlots; - unique->subtableZ[i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - unique->subtableZ[i].keys = 0; - unique->subtableZ[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - unique->subtableZ[i].dead = 0; - unique->permZ[i] = i; - unique->invpermZ[i] = i; - newnodelist = unique->subtableZ[i].nodelist = - ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = NULL; - } - } - } else { - /* The current table is too small: we need to allocate a new, - ** larger one; move all old subtables, and initialize the new - ** subtables up to index included. - */ - newsize = index + DD_DEFAULT_RESIZE; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "Increasing the ZDD table size from %d to %d\n", - unique->maxSizeZ, newsize); -#endif - newsubtables = ALLOC(DdSubtable,newsize); - if (newsubtables == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newperm = ALLOC(int,newsize); - if (newperm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newinvperm = ALLOC(int,newsize); - if (newinvperm == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->memused += (newsize - unique->maxSizeZ) * ((numSlots+1) * - sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); - if (newsize > unique->maxSize) { - FREE(unique->stack); - unique->stack = ALLOC(DdNodePtr,newsize + 1); - if (unique->stack == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->stack[0] = NULL; /* to suppress harmless UMR */ - unique->memused += - (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) - * sizeof(DdNode *); - } - for (i = 0; i < oldsize; i++) { - newsubtables[i].slots = unique->subtableZ[i].slots; - newsubtables[i].shift = unique->subtableZ[i].shift; - newsubtables[i].keys = unique->subtableZ[i].keys; - newsubtables[i].maxKeys = unique->subtableZ[i].maxKeys; - newsubtables[i].dead = unique->subtableZ[i].dead; - newsubtables[i].nodelist = unique->subtableZ[i].nodelist; - newperm[i] = unique->permZ[i]; - newinvperm[i] = unique->invpermZ[i]; - } - for (i = oldsize; i <= index; i++) { - newsubtables[i].slots = numSlots; - newsubtables[i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - newsubtables[i].keys = 0; - newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - newsubtables[i].dead = 0; - newperm[i] = i; - newinvperm[i] = i; - newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = NULL; - } - } - FREE(unique->subtableZ); - unique->subtableZ = newsubtables; - unique->maxSizeZ = newsize; - FREE(unique->permZ); - unique->permZ = newperm; - FREE(unique->invpermZ); - unique->invpermZ = newinvperm; - } - unique->slots += (index + 1 - unique->sizeZ) * numSlots; - ddFixLimits(unique); - unique->sizeZ = index + 1; - - /* Now that the table is in a coherent state, update the ZDD - ** universe. We need to temporarily disable reordering, - ** because we cannot reorder without universe in place. - */ - one = unique->one; - zero = unique->zero; - - reorderSave = unique->autoDynZ; - unique->autoDynZ = 0; - cuddZddFreeUniv(unique); - if (!cuddZddInitUniv(unique)) { - unique->autoDynZ = reorderSave; - return(0); - } - unique->autoDynZ = reorderSave; - - return(1); - -} /* end of cuddResizeTableZdd */ - - -/**Function******************************************************************** - - Synopsis [Adjusts parameters of a table to slow down its growth.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -cuddSlowTableGrowth( - DdManager *unique) -{ - int i; - - unique->maxCacheHard = unique->cacheSlots - 1; - unique->cacheSlack = -(unique->cacheSlots + 1); - for (i = 0; i < unique->size; i++) { - unique->subtables[i].maxKeys <<= 2; - } - unique->gcFrac = DD_GC_FRAC_MIN; - unique->minDead = (unsigned) (DD_GC_FRAC_MIN * (double) unique->slots); - cuddShrinkDeathRow(unique); - (void) fprintf(unique->err,"Slowing down table growth: "); - (void) fprintf(unique->err,"GC fraction = %.2f\t", unique->gcFrac); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); - -} /* end of cuddSlowTableGrowth */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Rehashes a ZDD unique subtable.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddRehash] - -******************************************************************************/ -static void -ddRehashZdd( - DdManager * unique, - int i) -{ - unsigned int slots, oldslots; - int shift, oldshift; - int j, pos; - DdNodePtr *nodelist, *oldnodelist; - DdNode *node, *next; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - - if (unique->slots > unique->looseUpTo) { - unique->minDead = (unsigned) (DD_GC_FRAC_LO * (double) unique->slots); -#ifdef DD_VERBOSE - if (unique->gcFrac == DD_GC_FRAC_HI) { - (void) fprintf(unique->err,"GC fraction = %.2f\t", - DD_GC_FRAC_LO); - (void) fprintf(unique->err,"minDead = %d\n", unique->minDead); - } -#endif - unique->gcFrac = DD_GC_FRAC_LO; - } - - assert(i != CUDD_MAXINDEX); - oldslots = unique->subtableZ[i].slots; - oldshift = unique->subtableZ[i].shift; - oldnodelist = unique->subtableZ[i].nodelist; - - /* Compute the new size of the subtable. Normally, we just - ** double. However, after reordering, a table may be severely - ** overloaded. Therefore, we iterate. */ - slots = oldslots; - shift = oldshift; - do { - slots <<= 1; - shift--; - } while (slots * DD_MAX_SUBTABLE_DENSITY < unique->subtableZ[i].keys); - - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - nodelist = ALLOC(DdNodePtr, slots); - MMoutOfMemory = saveHandler; - if (nodelist == NULL) { - int j; - (void) fprintf(unique->err, - "Unable to resize ZDD subtable %d for lack of memory.\n", - i); - (void) cuddGarbageCollectZdd(unique,1); - for (j = 0; j < unique->sizeZ; j++) { - unique->subtableZ[j].maxKeys <<= 1; - } - return; - } - unique->subtableZ[i].nodelist = nodelist; - unique->subtableZ[i].slots = slots; - unique->subtableZ[i].shift = shift; - unique->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = NULL; - } - for (j = 0; (unsigned) j < oldslots; j++) { - node = oldnodelist[j]; - while (node != NULL) { - next = node->next; - pos = ddHash(cuddT(node), cuddE(node), shift); - node->next = nodelist[pos]; - nodelist[pos] = node; - node = next; - } - } - FREE(oldnodelist); - -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "rehashing layer %d: keys %d dead %d new size %d\n", - i, unique->subtableZ[i].keys, - unique->subtableZ[i].dead, slots); -#endif - - /* Update global data. */ - unique->memused += (slots - oldslots) * sizeof(DdNode *); - unique->slots += (slots - oldslots); - ddFixLimits(unique); - -} /* end of ddRehashZdd */ - - -/**Function******************************************************************** - - Synopsis [Increases the number of subtables in a unique table so - that it meets or exceeds index.] - - Description [Increases the number of subtables in a unique table so - that it meets or exceeds index. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddResizeTableZdd] - -******************************************************************************/ -static int -ddResizeTable( - DdManager * unique, - int index) -{ - DdSubtable *newsubtables; - DdNodePtr *newnodelist; - DdNodePtr *newvars; - DdNode *sentinel = &(unique->sentinel); - int oldsize,newsize; - int i,j,reorderSave; - int numSlots = unique->initSlots; - int *newperm, *newinvperm, *newmap; - DdNode *one, *zero; - - oldsize = unique->size; - /* Easy case: there is still room in the current table. */ - if (index < unique->maxSize) { - for (i = oldsize; i <= index; i++) { - unique->subtables[i].slots = numSlots; - unique->subtables[i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - unique->subtables[i].keys = 0; - unique->subtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - unique->subtables[i].dead = 0; - unique->subtables[i].bindVar = 0; - unique->subtables[i].varType = CUDD_VAR_PRIMARY_INPUT; - unique->subtables[i].pairIndex = 0; - unique->subtables[i].varHandled = 0; - unique->subtables[i].varToBeGrouped = CUDD_LAZY_NONE; - - unique->perm[i] = i; - unique->invperm[i] = i; - newnodelist = unique->subtables[i].nodelist = - ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - for (j = oldsize; j < i; j++) { - FREE(unique->subtables[j].nodelist); - } - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = sentinel; - } - } - if (unique->map != NULL) { - for (i = oldsize; i <= index; i++) { - unique->map[i] = i; - } - } - } else { - /* The current table is too small: we need to allocate a new, - ** larger one; move all old subtables, and initialize the new - ** subtables up to index included. - */ - newsize = index + DD_DEFAULT_RESIZE; -#ifdef DD_VERBOSE - (void) fprintf(unique->err, - "Increasing the table size from %d to %d\n", - unique->maxSize, newsize); -#endif - newsubtables = ALLOC(DdSubtable,newsize); - if (newsubtables == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newvars = ALLOC(DdNodePtr,newsize); - if (newvars == NULL) { - FREE(newsubtables); - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newperm = ALLOC(int,newsize); - if (newperm == NULL) { - FREE(newsubtables); - FREE(newvars); - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - newinvperm = ALLOC(int,newsize); - if (newinvperm == NULL) { - FREE(newsubtables); - FREE(newvars); - FREE(newperm); - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - if (unique->map != NULL) { - newmap = ALLOC(int,newsize); - if (newmap == NULL) { - FREE(newsubtables); - FREE(newvars); - FREE(newperm); - FREE(newinvperm); - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->memused += (newsize - unique->maxSize) * sizeof(int); - } - unique->memused += (newsize - unique->maxSize) * ((numSlots+1) * - sizeof(DdNode *) + 2 * sizeof(int) + sizeof(DdSubtable)); - if (newsize > unique->maxSizeZ) { - FREE(unique->stack); - unique->stack = ALLOC(DdNodePtr,newsize + 1); - if (unique->stack == NULL) { - FREE(newsubtables); - FREE(newvars); - FREE(newperm); - FREE(newinvperm); - if (unique->map != NULL) { - FREE(newmap); - } - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - unique->stack[0] = NULL; /* to suppress harmless UMR */ - unique->memused += - (newsize - ddMax(unique->maxSize,unique->maxSizeZ)) - * sizeof(DdNode *); - } - for (i = 0; i < oldsize; i++) { - newsubtables[i].slots = unique->subtables[i].slots; - newsubtables[i].shift = unique->subtables[i].shift; - newsubtables[i].keys = unique->subtables[i].keys; - newsubtables[i].maxKeys = unique->subtables[i].maxKeys; - newsubtables[i].dead = unique->subtables[i].dead; - newsubtables[i].nodelist = unique->subtables[i].nodelist; - newsubtables[i].bindVar = unique->subtables[i].bindVar; - newsubtables[i].varType = unique->subtables[i].varType; - newsubtables[i].pairIndex = unique->subtables[i].pairIndex; - newsubtables[i].varHandled = unique->subtables[i].varHandled; - newsubtables[i].varToBeGrouped = unique->subtables[i].varToBeGrouped; - - newvars[i] = unique->vars[i]; - newperm[i] = unique->perm[i]; - newinvperm[i] = unique->invperm[i]; - } - for (i = oldsize; i <= index; i++) { - newsubtables[i].slots = numSlots; - newsubtables[i].shift = sizeof(int) * 8 - - cuddComputeFloorLog2(numSlots); - newsubtables[i].keys = 0; - newsubtables[i].maxKeys = numSlots * DD_MAX_SUBTABLE_DENSITY; - newsubtables[i].dead = 0; - newsubtables[i].bindVar = 0; - newsubtables[i].varType = CUDD_VAR_PRIMARY_INPUT; - newsubtables[i].pairIndex = 0; - newsubtables[i].varHandled = 0; - newsubtables[i].varToBeGrouped = CUDD_LAZY_NONE; - - newperm[i] = i; - newinvperm[i] = i; - newnodelist = newsubtables[i].nodelist = ALLOC(DdNodePtr, numSlots); - if (newnodelist == NULL) { - unique->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (j = 0; j < numSlots; j++) { - newnodelist[j] = sentinel; - } - } - if (unique->map != NULL) { - for (i = 0; i < oldsize; i++) { - newmap[i] = unique->map[i]; - } - for (i = oldsize; i <= index; i++) { - newmap[i] = i; - } - FREE(unique->map); - unique->map = newmap; - } - FREE(unique->subtables); - unique->subtables = newsubtables; - unique->maxSize = newsize; - FREE(unique->vars); - unique->vars = newvars; - FREE(unique->perm); - unique->perm = newperm; - FREE(unique->invperm); - unique->invperm = newinvperm; - } - - /* Now that the table is in a coherent state, create the new - ** projection functions. We need to temporarily disable reordering, - ** because we cannot reorder without projection functions in place. - **/ - one = unique->one; - zero = Cudd_Not(one); - - unique->size = index + 1; - unique->slots += (index + 1 - oldsize) * numSlots; - ddFixLimits(unique); - - reorderSave = unique->autoDyn; - unique->autoDyn = 0; - for (i = oldsize; i <= index; i++) { - unique->vars[i] = cuddUniqueInter(unique,i,one,zero); - if (unique->vars[i] == NULL) { - unique->autoDyn = reorderSave; - for (j = oldsize; j < i; j++) { - Cudd_IterDerefBdd(unique,unique->vars[j]); - cuddDeallocNode(unique,unique->vars[j]); - unique->vars[j] = NULL; - } - for (j = oldsize; j <= index; j++) { - FREE(unique->subtables[j].nodelist); - unique->subtables[j].nodelist = NULL; - } - unique->size = oldsize; - unique->slots -= (index + 1 - oldsize) * numSlots; - ddFixLimits(unique); - return(0); - } - cuddRef(unique->vars[i]); - } - unique->autoDyn = reorderSave; - - return(1); - -} /* end of ddResizeTable */ - - -/**Function******************************************************************** - - Synopsis [Searches the subtables above node for a parent.] - - Description [Searches the subtables above node for a parent. Returns 1 - as soon as one parent is found. Returns 0 is the search is fruitless.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddFindParent( - DdManager * table, - DdNode * node) -{ - int i,j; - int slots; - DdNodePtr *nodelist; - DdNode *f; - - for (i = cuddI(table,node->index) - 1; i >= 0; i--) { - nodelist = table->subtables[i].nodelist; - slots = table->subtables[i].slots; - - for (j = 0; j < slots; j++) { - f = nodelist[j]; - while (cuddT(f) > node) { - f = f->next; - } - while (cuddT(f) == node && Cudd_Regular(cuddE(f)) > node) { - f = f->next; - } - if (cuddT(f) == node && Cudd_Regular(cuddE(f)) == node) { - return(1); - } - } - } - - return(0); - -} /* end of cuddFindParent */ - - -/**Function******************************************************************** - - Synopsis [Adjusts the values of table limits.] - - Description [Adjusts the values of table fields controlling the. - sizes of subtables and computed table. If the computed table is too small - according to the new values, it is resized.] - - SideEffects [Modifies manager fields. May resize computed table.] - - SeeAlso [] - -******************************************************************************/ -DD_INLINE -static void -ddFixLimits( - DdManager *unique) -{ - unique->minDead = (unsigned) (unique->gcFrac * (double) unique->slots); - unique->cacheSlack = (int) ddMin(unique->maxCacheHard, - DD_MAX_CACHE_TO_SLOTS_RATIO * unique->slots) - - 2 * (int) unique->cacheSlots; - if (unique->cacheSlots < unique->slots/2 && unique->cacheSlack >= 0) - cuddCacheResize(unique); - return; - -} /* end of ddFixLimits */ - - -#ifndef DD_UNSORTED_FREE_LIST -/**Function******************************************************************** - - Synopsis [Inserts a DdNode in a red/black search tree.] - - Description [Inserts a DdNode in a red/black search tree. Nodes from - the same "page" (defined by DD_PAGE_MASK) are linked in a LIFO list.] - - SideEffects [None] - - SeeAlso [cuddOrderedThread] - -******************************************************************************/ -static void -cuddOrderedInsert( - DdNodePtr * root, - DdNodePtr node) -{ - DdNode *scan; - DdNodePtr *scanP; - DdNodePtr *stack[DD_STACK_SIZE]; - int stackN = 0; - - scanP = root; - while ((scan = *scanP) != NULL) { - stack[stackN++] = scanP; - if (DD_INSERT_COMPARE(node, scan) == 0) { /* add to page list */ - DD_NEXT(node) = DD_NEXT(scan); - DD_NEXT(scan) = node; - return; - } - scanP = (node < scan) ? &DD_LEFT(scan) : &DD_RIGHT(scan); - } - DD_RIGHT(node) = DD_LEFT(node) = DD_NEXT(node) = NULL; - DD_COLOR(node) = DD_RED; - *scanP = node; - stack[stackN] = &node; - cuddDoRebalance(stack,stackN); - -} /* end of cuddOrderedInsert */ - - -/**Function******************************************************************** - - Synopsis [Threads all the nodes of a search tree into a linear list.] - - Description [Threads all the nodes of a search tree into a linear - list. For each node of the search tree, the "left" child, if non-null, has - a lower address than its parent, and the "right" child, if non-null, has a - higher address than its parent. - The list is sorted in order of increasing addresses. The search - tree is destroyed as a result of this operation. The last element of - the linear list is made to point to the address passed in list. Each - node if the search tree is a linearly-linked list of nodes from the - same memory page (as defined in DD_PAGE_MASK). When a node is added to - the linear list, all the elements of the linked list are added.] - - SideEffects [The search tree is destroyed as a result of this operation.] - - SeeAlso [cuddOrderedInsert] - -******************************************************************************/ -static DdNode * -cuddOrderedThread( - DdNode * root, - DdNode * list) -{ - DdNode *current, *next, *prev, *end; - - current = root; - /* The first word in the node is used to implement a stack that holds - ** the nodes from the root of the tree to the current node. Here we - ** put the root of the tree at the bottom of the stack. - */ - *((DdNodePtr *) current) = NULL; - - while (current != NULL) { - if (DD_RIGHT(current) != NULL) { - /* If possible, we follow the "right" link. Eventually we'll - ** find the node with the largest address in the current tree. - ** In this phase we use the first word of a node to implemen - ** a stack of the nodes on the path from the root to "current". - ** Also, we disconnect the "right" pointers to indicate that - ** we have already followed them. - */ - next = DD_RIGHT(current); - DD_RIGHT(current) = NULL; - *((DdNodePtr *)next) = current; - current = next; - } else { - /* We can't proceed along the "right" links any further. - ** Hence "current" is the largest element in the current tree. - ** We make this node the new head of "list". (Repeating this - ** operation until the tree is empty yields the desired linear - ** threading of all nodes.) - */ - prev = *((DdNodePtr *) current); /* save prev node on stack in prev */ - /* Traverse the linked list of current until the end. */ - for (end = current; DD_NEXT(end) != NULL; end = DD_NEXT(end)); - DD_NEXT(end) = list; /* attach "list" at end and make */ - list = current; /* "current" the new head of "list" */ - /* Now, if current has a "left" child, we push it on the stack. - ** Otherwise, we just continue with the parent of "current". - */ - if (DD_LEFT(current) != NULL) { - next = DD_LEFT(current); - *((DdNodePtr *) next) = prev; - current = next; - } else { - current = prev; - } - } - } - - return(list); - -} /* end of cuddOrderedThread */ - - -/**Function******************************************************************** - - Synopsis [Performs the left rotation for red/black trees.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddRotateRight] - -******************************************************************************/ -DD_INLINE -static void -cuddRotateLeft( - DdNodePtr * nodeP) -{ - DdNode *newRoot; - DdNode *oldRoot = *nodeP; - - *nodeP = newRoot = DD_RIGHT(oldRoot); - DD_RIGHT(oldRoot) = DD_LEFT(newRoot); - DD_LEFT(newRoot) = oldRoot; - -} /* end of cuddRotateLeft */ - - -/**Function******************************************************************** - - Synopsis [Performs the right rotation for red/black trees.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddRotateLeft] - -******************************************************************************/ -DD_INLINE -static void -cuddRotateRight( - DdNodePtr * nodeP) -{ - DdNode *newRoot; - DdNode *oldRoot = *nodeP; - - *nodeP = newRoot = DD_LEFT(oldRoot); - DD_LEFT(oldRoot) = DD_RIGHT(newRoot); - DD_RIGHT(newRoot) = oldRoot; - -} /* end of cuddRotateRight */ - - -/**Function******************************************************************** - - Synopsis [Rebalances a red/black tree.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -cuddDoRebalance( - DdNodePtr ** stack, - int stackN) -{ - DdNodePtr *xP, *parentP, *grandpaP; - DdNode *x, *y, *parent, *grandpa; - - xP = stack[stackN]; - x = *xP; - /* Work our way back up, re-balancing the tree. */ - while (--stackN >= 0) { - parentP = stack[stackN]; - parent = *parentP; - if (DD_IS_BLACK(parent)) break; - /* Since the root is black, here a non-null grandparent exists. */ - grandpaP = stack[stackN-1]; - grandpa = *grandpaP; - if (parent == DD_LEFT(grandpa)) { - y = DD_RIGHT(grandpa); - if (y != NULL && DD_IS_RED(y)) { - DD_COLOR(parent) = DD_BLACK; - DD_COLOR(y) = DD_BLACK; - DD_COLOR(grandpa) = DD_RED; - x = grandpa; - stackN--; - } else { - if (x == DD_RIGHT(parent)) { - cuddRotateLeft(parentP); - DD_COLOR(x) = DD_BLACK; - } else { - DD_COLOR(parent) = DD_BLACK; - } - DD_COLOR(grandpa) = DD_RED; - cuddRotateRight(grandpaP); - break; - } - } else { - y = DD_LEFT(grandpa); - if (y != NULL && DD_IS_RED(y)) { - DD_COLOR(parent) = DD_BLACK; - DD_COLOR(y) = DD_BLACK; - DD_COLOR(grandpa) = DD_RED; - x = grandpa; - stackN--; - } else { - if (x == DD_LEFT(parent)) { - cuddRotateRight(parentP); - DD_COLOR(x) = DD_BLACK; - } else { - DD_COLOR(parent) = DD_BLACK; - } - DD_COLOR(grandpa) = DD_RED; - cuddRotateLeft(grandpaP); - } - } - } - DD_COLOR(*(stack[0])) = DD_BLACK; - -} /* end of cuddDoRebalance */ -#endif - - -/**Function******************************************************************** - - Synopsis [Fixes a variable tree after the insertion of new subtables.] - - Description [Fixes a variable tree after the insertion of new subtables. - After such an insertion, the low fields of the tree below the insertion - point are inconsistent.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -ddPatchTree( - DdManager *dd, - MtrNode *treenode) -{ - MtrNode *auxnode = treenode; - - while (auxnode != NULL) { - auxnode->low = dd->perm[auxnode->index]; - if (auxnode->child != NULL) { - ddPatchTree(dd, auxnode->child); - } - auxnode = auxnode->younger; - } - - return; - -} /* end of ddPatchTree */ - - -#ifdef DD_DEBUG -/**Function******************************************************************** - - Synopsis [Checks whether a collision list is ordered.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddCheckCollisionOrdering( - DdManager *unique, - int i, - int j) -{ - int slots; - DdNode *node, *next; - DdNodePtr *nodelist; - DdNode *sentinel = &(unique->sentinel); - - nodelist = unique->subtables[i].nodelist; - slots = unique->subtables[i].slots; - node = nodelist[j]; - if (node == sentinel) return(1); - next = node->next; - while (next != sentinel) { - if (cuddT(node) < cuddT(next) || - (cuddT(node) == cuddT(next) && cuddE(node) < cuddE(next))) { - (void) fprintf(unique->err, - "Unordered list: index %u, position %d\n", i, j); - return(0); - } - node = next; - next = node->next; - } - return(1); - -} /* end of cuddCheckCollisionOrdering */ -#endif - - - - -/**Function******************************************************************** - - Synopsis [Reports problem in garbage collection.] - - Description [] - - SideEffects [None] - - SeeAlso [cuddGarbageCollect cuddGarbageCollectZdd] - -******************************************************************************/ -static void -ddReportRefMess( - DdManager *unique /* manager */, - int i /* table in which the problem occurred */, - char *caller /* procedure that detected the problem */) -{ - if (i == CUDD_CONST_INDEX) { - (void) fprintf(unique->err, - "%s: problem in constants\n", caller); - } else if (i != -1) { - (void) fprintf(unique->err, - "%s: problem in table %d\n", caller, i); - } - (void) fprintf(unique->err, " dead count != deleted\n"); - (void) fprintf(unique->err, " This problem is often due to a missing \ -call to Cudd_Ref\n or to an extra call to Cudd_RecursiveDeref.\n \ -See the CUDD Programmer's Guide for additional details."); - abort(); - -} /* end of ddReportRefMess */ diff --git a/src/bdd/cudd/cuddUtil.c b/src/bdd/cudd/cuddUtil.c deleted file mode 100644 index d5fa18e2..00000000 --- a/src/bdd/cudd/cuddUtil.c +++ /dev/null @@ -1,3633 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddUtil.c] - - PackageName [cudd] - - Synopsis [Utility functions.] - - Description [External procedures included in this module: -
                -
              • Cudd_PrintMinterm() -
              • Cudd_PrintDebug() -
              • Cudd_DagSize() -
              • Cudd_EstimateCofactor() -
              • Cudd_EstimateCofactorSimple() -
              • Cudd_SharingSize() -
              • Cudd_CountMinterm() -
              • Cudd_EpdCountMinterm() -
              • Cudd_CountPath() -
              • Cudd_CountPathsToNonZero() -
              • Cudd_Support() -
              • Cudd_SupportIndex() -
              • Cudd_SupportSize() -
              • Cudd_VectorSupport() -
              • Cudd_VectorSupportIndex() -
              • Cudd_VectorSupportSize() -
              • Cudd_ClassifySupport() -
              • Cudd_CountLeaves() -
              • Cudd_bddPickOneCube() -
              • Cudd_bddPickOneMinterm() -
              • Cudd_bddPickArbitraryMinterms() -
              • Cudd_SubsetWithMaskVars() -
              • Cudd_FirstCube() -
              • Cudd_NextCube() -
              • Cudd_bddComputeCube() -
              • Cudd_addComputeCube() -
              • Cudd_FirstNode() -
              • Cudd_NextNode() -
              • Cudd_GenFree() -
              • Cudd_IsGenEmpty() -
              • Cudd_IndicesToCube() -
              • Cudd_PrintVersion() -
              • Cudd_AverageDistance() -
              • Cudd_Random() -
              • Cudd_Srandom() -
              • Cudd_Density() -
              - Internal procedures included in this module: -
                -
              • cuddP() -
              • cuddStCountfree() -
              • cuddCollectNodes() -
              - Static procedures included in this module: -
                -
              • dp2() -
              • ddPrintMintermAux() -
              • ddDagInt() -
              • ddCountMintermAux() -
              • ddEpdCountMintermAux() -
              • ddCountPathAux() -
              • ddSupportStep() -
              • ddClearFlag() -
              • ddLeavesInt() -
              • ddPickArbitraryMinterms() -
              • ddPickRepresentativeCube() -
              • ddEpdFree() -
              ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/* Random generator constants. */ -#define MODULUS1 2147483563 -#define LEQA1 40014 -#define LEQQ1 53668 -#define LEQR1 12211 -#define MODULUS2 2147483399 -#define LEQA2 40692 -#define LEQQ2 52774 -#define LEQR2 3791 -#define STAB_SIZE 64 -#define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE) - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddUtil.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -static DdNode *background, *zero; - -static long cuddRand = 0; -static long cuddRand2; -static long shuffleSelect; -static long shuffleTable[STAB_SIZE]; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -#define bang(f) ((Cudd_IsComplement(f)) ? '!' : ' ') - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int dp2 ARGS((DdManager *dd, DdNode *f, st_table *t)); -static void ddPrintMintermAux ARGS((DdManager *dd, DdNode *node, int *list)); -static int ddDagInt ARGS((DdNode *n)); -static int cuddEstimateCofactor ARGS((DdManager *dd, st_table *table, DdNode * node, int i, int phase, DdNode ** ptr)); -static DdNode * cuddUniqueLookup ARGS((DdManager * unique, int index, DdNode * T, DdNode * E)); -static int cuddEstimateCofactorSimple ARGS((DdNode * node, int i)); -static double ddCountMintermAux ARGS((DdNode *node, double max, DdHashTable *table)); -static int ddEpdCountMintermAux ARGS((DdNode *node, EpDouble *max, EpDouble *epd, st_table *table)); -static double ddCountPathAux ARGS((DdNode *node, st_table *table)); -static double ddCountPathsToNonZero ARGS((DdNode * N, st_table * table)); -static void ddSupportStep ARGS((DdNode *f, int *support)); -static void ddClearFlag ARGS((DdNode *f)); -static int ddLeavesInt ARGS((DdNode *n)); -static int ddPickArbitraryMinterms ARGS((DdManager *dd, DdNode *node, int nvars, int nminterms, char **string)); -static int ddPickRepresentativeCube ARGS((DdManager *dd, DdNode *node, int nvars, double *weight, char *string)); -static enum st_retval ddEpdFree ARGS((char * key, char * value, char * arg)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints a disjoint sum of products.] - - Description [Prints a disjoint sum of product cover for the function - rooted at node. Each product corresponds to a path from node to a - leaf node different from the logical zero, and different from the - background value. Uses the package default output file. Returns 1 - if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintDebug Cudd_bddPrintCover] - -******************************************************************************/ -int -Cudd_PrintMinterm( - DdManager * manager, - DdNode * node) -{ - int i, *list; - - background = manager->background; - zero = Cudd_Not(manager->one); - list = ALLOC(int,manager->size); - if (list == NULL) { - manager->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < manager->size; i++) list[i] = 2; - ddPrintMintermAux(manager,node,list); - FREE(list); - return(1); - -} /* end of Cudd_PrintMinterm */ - - -/**Function******************************************************************** - - Synopsis [Prints a sum of prime implicants of a BDD.] - - Description [Prints a sum of product cover for an incompletely - specified function given by a lower bound and an upper bound. Each - product is a prime implicant obtained by expanding the product - corresponding to a path from node to the constant one. Uses the - package default output file. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintMinterm] - -******************************************************************************/ -int -Cudd_bddPrintCover( - DdManager *dd, - DdNode *l, - DdNode *u) -{ - int *array; - int q, result; - DdNode *lb; -#ifdef DD_DEBUG - DdNode *cover; -#endif - - array = ALLOC(int, Cudd_ReadSize(dd)); - if (array == NULL) return(0); - lb = l; - cuddRef(lb); -#ifdef DD_DEBUG - cover = Cudd_ReadLogicZero(dd); - cuddRef(cover); -#endif - while (lb != Cudd_ReadLogicZero(dd)) { - DdNode *implicant, *prime, *tmp; - int length; - implicant = Cudd_LargestCube(dd,lb,&length); - if (implicant == NULL) { - Cudd_RecursiveDeref(dd,lb); - FREE(array); - return(0); - } - cuddRef(implicant); - prime = Cudd_bddMakePrime(dd,implicant,u); - if (prime == NULL) { - Cudd_RecursiveDeref(dd,lb); - Cudd_RecursiveDeref(dd,implicant); - FREE(array); - return(0); - } - cuddRef(prime); - Cudd_RecursiveDeref(dd,implicant); - tmp = Cudd_bddAnd(dd,lb,Cudd_Not(prime)); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,lb); - Cudd_RecursiveDeref(dd,prime); - FREE(array); - return(0); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,lb); - lb = tmp; - result = Cudd_BddToCubeArray(dd,prime,array); - if (result == 0) { - Cudd_RecursiveDeref(dd,lb); - Cudd_RecursiveDeref(dd,prime); - FREE(array); - return(0); - } - for (q = 0; q < dd->size; q++) { - switch (array[q]) { - case 0: - (void) fprintf(dd->out, "0"); - break; - case 1: - (void) fprintf(dd->out, "1"); - break; - case 2: - (void) fprintf(dd->out, "-"); - break; - default: - (void) fprintf(dd->out, "?"); - } - } - (void) fprintf(dd->out, " 1\n"); -#ifdef DD_DEBUG - tmp = Cudd_bddOr(dd,prime,cover); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,cover); - Cudd_RecursiveDeref(dd,lb); - Cudd_RecursiveDeref(dd,prime); - FREE(array); - return(0); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,cover); - cover = tmp; -#endif - Cudd_RecursiveDeref(dd,prime); - } - (void) fprintf(dd->out, "\n"); - Cudd_RecursiveDeref(dd,lb); - FREE(array); -#ifdef DD_DEBUG - if (!Cudd_bddLeq(dd,cover,u) || !Cudd_bddLeq(dd,l,cover)) { - Cudd_RecursiveDeref(dd,cover); - return(0); - } - Cudd_RecursiveDeref(dd,cover); -#endif - return(1); - -} /* end of Cudd_bddPrintCover */ - - -/**Function******************************************************************** - - Synopsis [Prints to the standard output a DD and its statistics.] - - Description [Prints to the standard output a DD and its statistics. - The statistics include the number of nodes, the number of leaves, and - the number of minterms. (The number of minterms is the number of - assignments to the variables that cause the function to be different - from the logical zero (for BDDs) and from the background value (for - ADDs.) The statistics are printed if pr > 0. Specifically: -
                -
              • pr = 0 : prints nothing -
              • pr = 1 : prints counts of nodes and minterms -
              • pr = 2 : prints counts + disjoint sum of product -
              • pr = 3 : prints counts + list of nodes -
              • pr > 3 : prints counts + disjoint sum of product + list of nodes -
              - For the purpose of counting the number of minterms, the function is - supposed to depend on n variables. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_DagSize Cudd_CountLeaves Cudd_CountMinterm - Cudd_PrintMinterm] - -******************************************************************************/ -int -Cudd_PrintDebug( - DdManager * dd, - DdNode * f, - int n, - int pr) -{ - DdNode *azero, *bzero; - int nodes; - int leaves; - double minterms; - int retval = 1; - - if (f == NULL) { - (void) fprintf(dd->out,": is the NULL DD\n"); - (void) fflush(dd->out); - return(0); - } - azero = DD_ZERO(dd); - bzero = Cudd_Not(DD_ONE(dd)); - if ((f == azero || f == bzero) && pr > 0){ - (void) fprintf(dd->out,": is the zero DD\n"); - (void) fflush(dd->out); - return(1); - } - if (pr > 0) { - nodes = Cudd_DagSize(f); - if (nodes == CUDD_OUT_OF_MEM) retval = 0; - leaves = Cudd_CountLeaves(f); - if (leaves == CUDD_OUT_OF_MEM) retval = 0; - minterms = Cudd_CountMinterm(dd, f, n); - if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0; - (void) fprintf(dd->out,": %d nodes %d leaves %g minterms\n", - nodes, leaves, minterms); - if (pr > 2) { - if (!cuddP(dd, f)) retval = 0; - } - if (pr == 2 || pr > 3) { - if (!Cudd_PrintMinterm(dd,f)) retval = 0; - (void) fprintf(dd->out,"\n"); - } - (void) fflush(dd->out); - } - return(retval); - -} /* end of Cudd_PrintDebug */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of nodes in a DD.] - - Description [Counts the number of nodes in a DD. Returns the number - of nodes in the graph rooted at node.] - - SideEffects [None] - - SeeAlso [Cudd_SharingSize Cudd_PrintDebug] - -******************************************************************************/ -int -Cudd_DagSize( - DdNode * node) -{ - int i; - - i = ddDagInt(Cudd_Regular(node)); - ddClearFlag(Cudd_Regular(node)); - - return(i); - -} /* end of Cudd_DagSize */ - - -/**Function******************************************************************** - - Synopsis [Estimates the number of nodes in a cofactor of a DD.] - - Description [Estimates the number of nodes in a cofactor of a DD. - Returns an estimate of the number of nodes in a cofactor of - the graph rooted at node with respect to the variable whose index is i. - In case of failure, returns CUDD_OUT_OF_MEM. - This function uses a refinement of the algorithm of Cabodi et al. - (ICCAD96). The refinement allows the procedure to account for part - of the recombination that may occur in the part of the cofactor above - the cofactoring variable. This procedure does no create any new node. - It does keep a small table of results; therefore itmay run out of memory. - If this is a concern, one should use Cudd_EstimateCofactorSimple, which - is faster, does not allocate any memory, but is less accurate.] - - SideEffects [None] - - SeeAlso [Cudd_DagSize Cudd_EstimateCofactorSimple] - -******************************************************************************/ -int -Cudd_EstimateCofactor( - DdManager *dd /* manager */, - DdNode * f /* function */, - int i /* index of variable */, - int phase /* 1: positive; 0: negative */ - ) -{ - int val; - DdNode *ptr; - st_table *table; - - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) return(CUDD_OUT_OF_MEM); - val = cuddEstimateCofactor(dd,table,Cudd_Regular(f),i,phase,&ptr); - ddClearFlag(Cudd_Regular(f)); - st_free_table(table); - - return(val); - -} /* end of Cudd_EstimateCofactor */ - - -/**Function******************************************************************** - - Synopsis [Estimates the number of nodes in a cofactor of a DD.] - - Description [Estimates the number of nodes in a cofactor of a DD. - Returns an estimate of the number of nodes in the positive cofactor of - the graph rooted at node with respect to the variable whose index is i. - This procedure implements with minor changes the algorithm of Cabodi et al. - (ICCAD96). It does not allocate any memory, it does not change the - state of the manager, and it is fast. However, it has been observed to - overestimate the size of the cofactor by as much as a factor of 2.] - - SideEffects [None] - - SeeAlso [Cudd_DagSize] - -******************************************************************************/ -int -Cudd_EstimateCofactorSimple( - DdNode * node, - int i) -{ - int val; - - val = cuddEstimateCofactorSimple(Cudd_Regular(node),i); - ddClearFlag(Cudd_Regular(node)); - - return(val); - -} /* end of Cudd_EstimateCofactorSimple */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of nodes in an array of DDs.] - - Description [Counts the number of nodes in an array of DDs. Shared - nodes are counted only once. Returns the total number of nodes.] - - SideEffects [None] - - SeeAlso [Cudd_DagSize] - -******************************************************************************/ -int -Cudd_SharingSize( - DdNode ** nodeArray, - int n) -{ - int i,j; - - i = 0; - for (j = 0; j < n; j++) { - i += ddDagInt(Cudd_Regular(nodeArray[j])); - } - for (j = 0; j < n; j++) { - ddClearFlag(Cudd_Regular(nodeArray[j])); - } - return(i); - -} /* end of Cudd_SharingSize */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms of a DD.] - - Description [Counts the number of minterms of a DD. The function is - assumed to depend on nvars variables. The minterm count is - represented as a double, to allow for a larger number of variables. - Returns the number of minterms of the function rooted at node if - successful; (double) CUDD_OUT_OF_MEM otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintDebug Cudd_CountPath] - -******************************************************************************/ -double -Cudd_CountMinterm( - DdManager * manager, - DdNode * node, - int nvars) -{ - double max; - DdHashTable *table; - double res; - CUDD_VALUE_TYPE epsilon; - - background = manager->background; - zero = Cudd_Not(manager->one); - - max = pow(2.0,(double)nvars); - table = cuddHashTableInit(manager,1,2); - if (table == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - epsilon = Cudd_ReadEpsilon(manager); - Cudd_SetEpsilon(manager,(CUDD_VALUE_TYPE)0.0); - res = ddCountMintermAux(node,max,table); - cuddHashTableQuit(table); - Cudd_SetEpsilon(manager,epsilon); - - return(res); - -} /* end of Cudd_CountMinterm */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of paths of a DD.] - - Description [Counts the number of paths of a DD. Paths to all - terminal nodes are counted. The path count is represented as a - double, to allow for a larger number of variables. Returns the - number of paths of the function rooted at node if successful; - (double) CUDD_OUT_OF_MEM otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_CountMinterm] - -******************************************************************************/ -double -Cudd_CountPath( - DdNode * node) -{ - - st_table *table; - double i; - - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - i = ddCountPathAux(Cudd_Regular(node),table); - st_foreach(table, cuddStCountfree, NULL); - st_free_table(table); - return(i); - -} /* end of Cudd_CountPath */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms of a DD with extended precision.] - - Description [Counts the number of minterms of a DD with extended precision. - The function is assumed to depend on nvars variables. The minterm count is - represented as an EpDouble, to allow any number of variables. - Returns 0 if successful; CUDD_OUT_OF_MEM otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintDebug Cudd_CountPath] - -******************************************************************************/ -int -Cudd_EpdCountMinterm( - DdManager * manager, - DdNode * node, - int nvars, - EpDouble * epd) -{ - EpDouble max, tmp; - st_table *table; - int status; - - background = manager->background; - zero = Cudd_Not(manager->one); - - EpdPow2(nvars, &max); - table = st_init_table(EpdCmp, st_ptrhash); - if (table == NULL) { - EpdMakeZero(epd, 0); - return(CUDD_OUT_OF_MEM); - } - status = ddEpdCountMintermAux(Cudd_Regular(node),&max,epd,table); - st_foreach(table, ddEpdFree, NULL); - st_free_table(table); - if (status == CUDD_OUT_OF_MEM) { - EpdMakeZero(epd, 0); - return(CUDD_OUT_OF_MEM); - } - if (Cudd_IsComplement(node)) { - EpdSubtract3(&max, epd, &tmp); - EpdCopy(&tmp, epd); - } - return(0); - -} /* end of Cudd_EpdCountMinterm */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of paths to a non-zero terminal of a DD.] - - Description [Counts the number of paths to a non-zero terminal of a - DD. The path count is - represented as a double, to allow for a larger number of variables. - Returns the number of paths of the function rooted at node.] - - SideEffects [None] - - SeeAlso [Cudd_CountMinterm Cudd_CountPath] - -******************************************************************************/ -double -Cudd_CountPathsToNonZero( - DdNode * node) -{ - - st_table *table; - double i; - - table = st_init_table(st_ptrcmp,st_ptrhash); - if (table == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - i = ddCountPathsToNonZero(node,table); - st_foreach(table, cuddStCountfree, NULL); - st_free_table(table); - return(i); - -} /* end of Cudd_CountPathsToNonZero */ - - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a DD depends.] - - Description [Finds the variables on which a DD depends. - Returns a BDD consisting of the product of the variables if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_VectorSupport Cudd_ClassifySupport] - -******************************************************************************/ -DdNode * -Cudd_Support( - DdManager * dd /* manager */, - DdNode * f /* DD whose support is sought */) -{ - int *support; - DdNode *res, *tmp, *var; - int i,j; - int size; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax(dd->size, dd->sizeZ); - support = ALLOC(int,size); - if (support == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < size; i++) { - support[i] = 0; - } - - /* Compute support and clean up markers. */ - ddSupportStep(Cudd_Regular(f),support); - ddClearFlag(Cudd_Regular(f)); - - /* Transform support from array to cube. */ - do { - dd->reordered = 0; - res = DD_ONE(dd); - cuddRef(res); - for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */ - i = (j >= dd->size) ? j : dd->invperm[j]; - if (support[i] == 1) { - var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); - cuddRef(var); - tmp = cuddBddAndRecur(dd,res,var); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,res); - Cudd_RecursiveDeref(dd,var); - res = NULL; - break; - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,res); - Cudd_RecursiveDeref(dd,var); - res = tmp; - } - } - } while (dd->reordered == 1); - - FREE(support); - if (res != NULL) cuddDeref(res); - return(res); - -} /* end of Cudd_Support */ - - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a DD depends.] - - Description [Finds the variables on which a DD depends. - Returns an index array of the variables if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport] - -******************************************************************************/ -int * -Cudd_SupportIndex( - DdManager * dd /* manager */, - DdNode * f /* DD whose support is sought */) -{ - int *support; - int i; - int size; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax(dd->size, dd->sizeZ); - support = ALLOC(int,size); - if (support == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < size; i++) { - support[i] = 0; - } - - /* Compute support and clean up markers. */ - ddSupportStep(Cudd_Regular(f),support); - ddClearFlag(Cudd_Regular(f)); - - return(support); - -} /* end of Cudd_SupportIndex */ - - -/**Function******************************************************************** - - Synopsis [Counts the variables on which a DD depends.] - - Description [Counts the variables on which a DD depends. - Returns the number of the variables if successful; CUDD_OUT_OF_MEM - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Support] - -******************************************************************************/ -int -Cudd_SupportSize( - DdManager * dd /* manager */, - DdNode * f /* DD whose support size is sought */) -{ - int *support; - int i; - int size; - int count; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax(dd->size, dd->sizeZ); - support = ALLOC(int,size); - if (support == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(CUDD_OUT_OF_MEM); - } - for (i = 0; i < size; i++) { - support[i] = 0; - } - - /* Compute support and clean up markers. */ - ddSupportStep(Cudd_Regular(f),support); - ddClearFlag(Cudd_Regular(f)); - - /* Count support variables. */ - count = 0; - for (i = 0; i < size; i++) { - if (support[i] == 1) count++; - } - - FREE(support); - return(count); - -} /* end of Cudd_SupportSize */ - - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a set of DDs depends.] - - Description [Finds the variables on which a set of DDs depends. - The set must contain either BDDs and ADDs, or ZDDs. - Returns a BDD consisting of the product of the variables if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Support Cudd_ClassifySupport] - -******************************************************************************/ -DdNode * -Cudd_VectorSupport( - DdManager * dd /* manager */, - DdNode ** F /* array of DDs whose support is sought */, - int n /* size of the array */) -{ - int *support; - DdNode *res, *tmp, *var; - int i,j; - int size; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax(dd->size, dd->sizeZ); - support = ALLOC(int,size); - if (support == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < size; i++) { - support[i] = 0; - } - - /* Compute support and clean up markers. */ - for (i = 0; i < n; i++) { - ddSupportStep(Cudd_Regular(F[i]),support); - } - for (i = 0; i < n; i++) { - ddClearFlag(Cudd_Regular(F[i])); - } - - /* Transform support from array to cube. */ - res = DD_ONE(dd); - cuddRef(res); - for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */ - i = (j >= dd->size) ? j : dd->invperm[j]; - if (support[i] == 1) { - var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); - cuddRef(var); - tmp = Cudd_bddAnd(dd,res,var); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,res); - Cudd_RecursiveDeref(dd,var); - FREE(support); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,res); - Cudd_RecursiveDeref(dd,var); - res = tmp; - } - } - - FREE(support); - cuddDeref(res); - return(res); - -} /* end of Cudd_VectorSupport */ - - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a set of DDs depends.] - - Description [Finds the variables on which a set of DDs depends. - The set must contain either BDDs and ADDs, or ZDDs. - Returns an index array of the variables if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_SupportIndex Cudd_VectorSupport Cudd_ClassifySupport] - -******************************************************************************/ -int * -Cudd_VectorSupportIndex( - DdManager * dd /* manager */, - DdNode ** F /* array of DDs whose support is sought */, - int n /* size of the array */) -{ - int *support; - int i; - int size; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax(dd->size, dd->sizeZ); - support = ALLOC(int,size); - if (support == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < size; i++) { - support[i] = 0; - } - - /* Compute support and clean up markers. */ - for (i = 0; i < n; i++) { - ddSupportStep(Cudd_Regular(F[i]),support); - } - for (i = 0; i < n; i++) { - ddClearFlag(Cudd_Regular(F[i])); - } - - return(support); - -} /* end of Cudd_VectorSupportIndex */ - - -/**Function******************************************************************** - - Synopsis [Counts the variables on which a set of DDs depends.] - - Description [Counts the variables on which a set of DDs depends. - The set must contain either BDDs and ADDs, or ZDDs. - Returns the number of the variables if successful; CUDD_OUT_OF_MEM - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_VectorSupport Cudd_SupportSize] - -******************************************************************************/ -int -Cudd_VectorSupportSize( - DdManager * dd /* manager */, - DdNode ** F /* array of DDs whose support is sought */, - int n /* size of the array */) -{ - int *support; - int i; - int size; - int count; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax(dd->size, dd->sizeZ); - support = ALLOC(int,size); - if (support == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(CUDD_OUT_OF_MEM); - } - for (i = 0; i < size; i++) { - support[i] = 0; - } - - /* Compute support and clean up markers. */ - for (i = 0; i < n; i++) { - ddSupportStep(Cudd_Regular(F[i]),support); - } - for (i = 0; i < n; i++) { - ddClearFlag(Cudd_Regular(F[i])); - } - - /* Count vriables in support. */ - count = 0; - for (i = 0; i < size; i++) { - if (support[i] == 1) count++; - } - - FREE(support); - return(count); - -} /* end of Cudd_VectorSupportSize */ - - -/**Function******************************************************************** - - Synopsis [Classifies the variables in the support of two DDs.] - - Description [Classifies the variables in the support of two DDs - f and g, depending on whther they appear - in both DDs, only in f, or only in g. - Returns 1 if successful; 0 otherwise.] - - SideEffects [The cubes of the three classes of variables are - returned as side effects.] - - SeeAlso [Cudd_Support Cudd_VectorSupport] - -******************************************************************************/ -int -Cudd_ClassifySupport( - DdManager * dd /* manager */, - DdNode * f /* first DD */, - DdNode * g /* second DD */, - DdNode ** common /* cube of shared variables */, - DdNode ** onlyF /* cube of variables only in f */, - DdNode ** onlyG /* cube of variables only in g */) -{ - int *supportF, *supportG; - DdNode *tmp, *var; - int i,j; - int size; - - /* Allocate and initialize support arrays for ddSupportStep. */ - size = ddMax(dd->size, dd->sizeZ); - supportF = ALLOC(int,size); - if (supportF == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - supportG = ALLOC(int,size); - if (supportG == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(supportF); - return(0); - } - for (i = 0; i < size; i++) { - supportF[i] = 0; - supportG[i] = 0; - } - - /* Compute supports and clean up markers. */ - ddSupportStep(Cudd_Regular(f),supportF); - ddClearFlag(Cudd_Regular(f)); - ddSupportStep(Cudd_Regular(g),supportG); - ddClearFlag(Cudd_Regular(g)); - - /* Classify variables and create cubes. */ - *common = *onlyF = *onlyG = DD_ONE(dd); - cuddRef(*common); cuddRef(*onlyF); cuddRef(*onlyG); - for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */ - i = (j >= dd->size) ? j : dd->invperm[j]; - if (supportF[i] == 0 && supportG[i] == 0) continue; - var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one)); - cuddRef(var); - if (supportG[i] == 0) { - tmp = Cudd_bddAnd(dd,*onlyF,var); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,*common); - Cudd_RecursiveDeref(dd,*onlyF); - Cudd_RecursiveDeref(dd,*onlyG); - Cudd_RecursiveDeref(dd,var); - FREE(supportF); FREE(supportG); - return(0); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,*onlyF); - *onlyF = tmp; - } else if (supportF[i] == 0) { - tmp = Cudd_bddAnd(dd,*onlyG,var); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,*common); - Cudd_RecursiveDeref(dd,*onlyF); - Cudd_RecursiveDeref(dd,*onlyG); - Cudd_RecursiveDeref(dd,var); - FREE(supportF); FREE(supportG); - return(0); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,*onlyG); - *onlyG = tmp; - } else { - tmp = Cudd_bddAnd(dd,*common,var); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,*common); - Cudd_RecursiveDeref(dd,*onlyF); - Cudd_RecursiveDeref(dd,*onlyG); - Cudd_RecursiveDeref(dd,var); - FREE(supportF); FREE(supportG); - return(0); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,*common); - *common = tmp; - } - Cudd_RecursiveDeref(dd,var); - } - - FREE(supportF); FREE(supportG); - cuddDeref(*common); cuddDeref(*onlyF); cuddDeref(*onlyG); - return(1); - -} /* end of Cudd_ClassifySupport */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of leaves in a DD.] - - Description [Counts the number of leaves in a DD. Returns the number - of leaves in the DD rooted at node if successful; CUDD_OUT_OF_MEM - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintDebug] - -******************************************************************************/ -int -Cudd_CountLeaves( - DdNode * node) -{ - int i; - - i = ddLeavesInt(Cudd_Regular(node)); - ddClearFlag(Cudd_Regular(node)); - return(i); - -} /* end of Cudd_CountLeaves */ - - -/**Function******************************************************************** - - Synopsis [Picks one on-set cube randomly from the given DD.] - - Description [Picks one on-set cube randomly from the given DD. The - cube is written into an array of characters. The array must have at - least as many entries as there are variables. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddPickOneMinterm] - -******************************************************************************/ -int -Cudd_bddPickOneCube( - DdManager * ddm, - DdNode * node, - char * string) -{ - DdNode *N, *T, *E; - DdNode *one, *bzero; - char dir; - int i; - - if (string == NULL || node == NULL) return(0); - - /* The constant 0 function has no on-set cubes. */ - one = DD_ONE(ddm); - bzero = Cudd_Not(one); - if (node == bzero) return(0); - - for (i = 0; i < ddm->size; i++) string[i] = 2; - - for (;;) { - - if (node == one) break; - - N = Cudd_Regular(node); - - T = cuddT(N); E = cuddE(N); - if (Cudd_IsComplement(node)) { - T = Cudd_Not(T); E = Cudd_Not(E); - } - if (T == bzero) { - string[N->index] = 0; - node = E; - } else if (E == bzero) { - string[N->index] = 1; - node = T; - } else { - dir = (char) ((Cudd_Random() & 0x2000) >> 13); - string[N->index] = dir; - node = dir ? T : E; - } - } - return(1); - -} /* end of Cudd_bddPickOneCube */ - - -/**Function******************************************************************** - - Synopsis [Picks one on-set minterm randomly from the given DD.] - - Description [Picks one on-set minterm randomly from the given - DD. The minterm is in terms of vars. The array - vars should contain at least all variables in the - support of f; if this condition is not met the minterm - built by this procedure may not be contained in - f. Builds a BDD for the minterm and returns a pointer - to it if successful; NULL otherwise. There are three reasons why the - procedure may fail: -
                -
              • It may run out of memory; -
              • the function f may be the constant 0; -
              • the minterm may not be contained in f. -
              ] - - SideEffects [None] - - SeeAlso [Cudd_bddPickOneCube] - -******************************************************************************/ -DdNode * -Cudd_bddPickOneMinterm( - DdManager * dd /* manager */, - DdNode * f /* function from which to pick one minterm */, - DdNode ** vars /* array of variables */, - int n /* size of vars */) -{ - char *string; - int i, size; - int *indices; - int result; - DdNode *old, *neW; - - size = dd->size; - string = ALLOC(char, size); - if (string == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - indices = ALLOC(int,n); - if (indices == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(string); - return(NULL); - } - - for (i = 0; i < n; i++) { - indices[i] = vars[i]->index; - } - - result = Cudd_bddPickOneCube(dd,f,string); - if (result == 0) { - FREE(string); - FREE(indices); - return(NULL); - } - - /* Randomize choice for don't cares. */ - for (i = 0; i < n; i++) { - if (string[indices[i]] == 2) - string[indices[i]] = (char) ((Cudd_Random() & 0x20) >> 5); - } - - /* Build result BDD. */ - old = Cudd_ReadOne(dd); - cuddRef(old); - - for (i = n-1; i >= 0; i--) { - neW = Cudd_bddAnd(dd,old,Cudd_NotCond(vars[i],string[indices[i]]==0)); - if (neW == NULL) { - FREE(string); - FREE(indices); - Cudd_RecursiveDeref(dd,old); - return(NULL); - } - cuddRef(neW); - Cudd_RecursiveDeref(dd,old); - old = neW; - } - -#ifdef DD_DEBUG - /* Test. */ - if (Cudd_bddLeq(dd,old,f)) { - cuddDeref(old); - } else { - Cudd_RecursiveDeref(dd,old); - old = NULL; - } -#else - cuddDeref(old); -#endif - - FREE(string); - FREE(indices); - return(old); - -} /* end of Cudd_bddPickOneMinterm */ - - -/**Function******************************************************************** - - Synopsis [Picks k on-set minterms evenly distributed from given DD.] - - Description [Picks k on-set minterms evenly distributed from given DD. - The minterms are in terms of vars. The array - vars should contain at least all variables in the - support of f; if this condition is not met the minterms - built by this procedure may not be contained in - f. Builds an array of BDDs for the minterms and returns a - pointer to it if successful; NULL otherwise. There are three reasons - why the procedure may fail: -
                -
              • It may run out of memory; -
              • the function f may be the constant 0; -
              • the minterms may not be contained in f. -
              ] - - SideEffects [None] - - SeeAlso [Cudd_bddPickOneMinterm Cudd_bddPickOneCube] - -******************************************************************************/ -DdNode ** -Cudd_bddPickArbitraryMinterms( - DdManager * dd /* manager */, - DdNode * f /* function from which to pick k minterms */, - DdNode ** vars /* array of variables */, - int n /* size of vars */, - int k /* number of minterms to find */) -{ - char **string; - int i, j, l, size; - int *indices; - int result; - DdNode **old, *neW; - double minterms; - char *saveString; - int saveFlag, savePoint, isSame; - - minterms = Cudd_CountMinterm(dd,f,n); - if ((double)k > minterms) { - return(NULL); - } - - size = dd->size; - string = ALLOC(char *, k); - if (string == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < k; i++) { - string[i] = ALLOC(char, size + 1); - if (string[i] == NULL) { - for (j = 0; j < i; j++) - FREE(string[i]); - FREE(string); - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (j = 0; j < size; j++) string[i][j] = '2'; - string[i][size] = '\0'; - } - indices = ALLOC(int,n); - if (indices == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - for (i = 0; i < k; i++) - FREE(string[i]); - FREE(string); - return(NULL); - } - - for (i = 0; i < n; i++) { - indices[i] = vars[i]->index; - } - - result = ddPickArbitraryMinterms(dd,f,n,k,string); - if (result == 0) { - for (i = 0; i < k; i++) - FREE(string[i]); - FREE(string); - FREE(indices); - return(NULL); - } - - old = ALLOC(DdNode *, k); - if (old == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - for (i = 0; i < k; i++) - FREE(string[i]); - FREE(string); - FREE(indices); - return(NULL); - } - saveString = ALLOC(char, size + 1); - if (saveString == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - for (i = 0; i < k; i++) - FREE(string[i]); - FREE(string); - FREE(indices); - FREE(old); - return(NULL); - } - saveFlag = 0; - - /* Build result BDD array. */ - for (i = 0; i < k; i++) { - isSame = 0; - if (!saveFlag) { - for (j = i + 1; j < k; j++) { - if (strcmp(string[i], string[j]) == 0) { - savePoint = i; - strcpy(saveString, string[i]); - saveFlag = 1; - break; - } - } - } else { - if (strcmp(string[i], saveString) == 0) { - isSame = 1; - } else { - saveFlag = 0; - for (j = i + 1; j < k; j++) { - if (strcmp(string[i], string[j]) == 0) { - savePoint = i; - strcpy(saveString, string[i]); - saveFlag = 1; - break; - } - } - } - } - /* Randomize choice for don't cares. */ - for (j = 0; j < n; j++) { - if (string[i][indices[j]] == '2') - string[i][indices[j]] = (Cudd_Random() & 0x20) ? '1' : '0'; - } - - while (isSame) { - isSame = 0; - for (j = savePoint; j < i; j++) { - if (strcmp(string[i], string[j]) == 0) { - isSame = 1; - break; - } - } - if (isSame) { - strcpy(string[i], saveString); - /* Randomize choice for don't cares. */ - for (j = 0; j < n; j++) { - if (string[i][indices[j]] == '2') - string[i][indices[j]] = (Cudd_Random() & 0x20) ? - '1' : '0'; - } - } - } - - old[i] = Cudd_ReadOne(dd); - cuddRef(old[i]); - - for (j = 0; j < n; j++) { - if (string[i][indices[j]] == '0') { - neW = Cudd_bddAnd(dd,old[i],Cudd_Not(vars[j])); - } else { - neW = Cudd_bddAnd(dd,old[i],vars[j]); - } - if (neW == NULL) { - FREE(saveString); - for (l = 0; l < k; l++) - FREE(string[l]); - FREE(string); - FREE(indices); - for (l = 0; l <= i; l++) - Cudd_RecursiveDeref(dd,old[l]); - FREE(old); - return(NULL); - } - cuddRef(neW); - Cudd_RecursiveDeref(dd,old[i]); - old[i] = neW; - } - - /* Test. */ - if (!Cudd_bddLeq(dd,old[i],f)) { - FREE(saveString); - for (l = 0; l < k; l++) - FREE(string[l]); - FREE(string); - FREE(indices); - for (l = 0; l <= i; l++) - Cudd_RecursiveDeref(dd,old[l]); - FREE(old); - return(NULL); - } - } - - FREE(saveString); - for (i = 0; i < k; i++) { - cuddDeref(old[i]); - FREE(string[i]); - } - FREE(string); - FREE(indices); - return(old); - -} /* end of Cudd_bddPickArbitraryMinterms */ - - -/**Function******************************************************************** - - Synopsis [Extracts a subset from a BDD.] - - Description [Extracts a subset from a BDD in the following procedure. - 1. Compute the weight for each mask variable by counting the number of - minterms for both positive and negative cofactors of the BDD with - respect to each mask variable. (weight = #positive - #negative) - 2. Find a representative cube of the BDD by using the weight. From the - top variable of the BDD, for each variable, if the weight is greater - than 0.0, choose THEN branch, othereise ELSE branch, until meeting - the constant 1. - 3. Quantify out the variables not in maskVars from the representative - cube and if a variable in maskVars is don't care, replace the - variable with a constant(1 or 0) depending on the weight. - 4. Make a subset of the BDD by multiplying with the modified cube.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_SubsetWithMaskVars( - DdManager * dd /* manager */, - DdNode * f /* function from which to pick a cube */, - DdNode ** vars /* array of variables */, - int nvars /* size of vars */, - DdNode ** maskVars /* array of variables */, - int mvars /* size of maskVars */) -{ - double *weight; - char *string; - int i, size; - int *indices, *mask; - int result; - DdNode *zero, *cube, *newCube, *subset; - DdNode *cof; - - DdNode *support; - support = Cudd_Support(dd,f); - cuddRef(support); - Cudd_RecursiveDeref(dd,support); - - zero = Cudd_Not(dd->one); - size = dd->size; - - weight = ALLOC(double,size); - if (weight == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - for (i = 0; i < size; i++) { - weight[i] = 0.0; - } - for (i = 0; i < mvars; i++) { - cof = Cudd_Cofactor(dd, f, maskVars[i]); - cuddRef(cof); - weight[i] = Cudd_CountMinterm(dd, cof, nvars); - Cudd_RecursiveDeref(dd,cof); - - cof = Cudd_Cofactor(dd, f, Cudd_Not(maskVars[i])); - cuddRef(cof); - weight[i] -= Cudd_CountMinterm(dd, cof, nvars); - Cudd_RecursiveDeref(dd,cof); - } - - string = ALLOC(char, size + 1); - if (string == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - mask = ALLOC(int, size); - if (mask == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(string); - return(NULL); - } - for (i = 0; i < size; i++) { - string[i] = '2'; - mask[i] = 0; - } - string[size] = '\0'; - indices = ALLOC(int,nvars); - if (indices == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(string); - FREE(mask); - return(NULL); - } - for (i = 0; i < nvars; i++) { - indices[i] = vars[i]->index; - } - - result = ddPickRepresentativeCube(dd,f,nvars,weight,string); - if (result == 0) { - FREE(string); - FREE(mask); - FREE(indices); - return(NULL); - } - - cube = Cudd_ReadOne(dd); - cuddRef(cube); - zero = Cudd_Not(Cudd_ReadOne(dd)); - for (i = 0; i < nvars; i++) { - if (string[indices[i]] == '0') { - newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero); - } else if (string[indices[i]] == '1') { - newCube = Cudd_bddIte(dd,cube,vars[i],zero); - } else - continue; - if (newCube == NULL) { - FREE(string); - FREE(mask); - FREE(indices); - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(newCube); - Cudd_RecursiveDeref(dd,cube); - cube = newCube; - } - Cudd_RecursiveDeref(dd,cube); - - for (i = 0; i < mvars; i++) { - mask[maskVars[i]->index] = 1; - } - for (i = 0; i < nvars; i++) { - if (mask[indices[i]]) { - if (string[indices[i]] == '2') { - if (weight[indices[i]] >= 0.0) - string[indices[i]] = '1'; - else - string[indices[i]] = '0'; - } - } else { - string[indices[i]] = '2'; - } - } - - cube = Cudd_ReadOne(dd); - cuddRef(cube); - zero = Cudd_Not(Cudd_ReadOne(dd)); - - /* Build result BDD. */ - for (i = 0; i < nvars; i++) { - if (string[indices[i]] == '0') { - newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero); - } else if (string[indices[i]] == '1') { - newCube = Cudd_bddIte(dd,cube,vars[i],zero); - } else - continue; - if (newCube == NULL) { - FREE(string); - FREE(mask); - FREE(indices); - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(newCube); - Cudd_RecursiveDeref(dd,cube); - cube = newCube; - } - - subset = Cudd_bddAnd(dd,f,cube); - cuddRef(subset); - Cudd_RecursiveDeref(dd,cube); - - /* Test. */ - if (Cudd_bddLeq(dd,subset,f)) { - cuddDeref(subset); - } else { - Cudd_RecursiveDeref(dd,subset); - subset = NULL; - } - - FREE(string); - FREE(mask); - FREE(indices); - FREE(weight); - return(subset); - -} /* end of Cudd_SubsetWithMaskVars */ - - -/**Function******************************************************************** - - Synopsis [Finds the first cube of a decision diagram.] - - Description [Defines an iterator on the onset of a decision diagram - and finds its first cube. Returns a generator that contains the - information necessary to continue the enumeration if successful; NULL - otherwise.

              - A cube is represented as an array of literals, which are integers in - {0, 1, 2}; 0 represents a complemented literal, 1 represents an - uncomplemented literal, and 2 stands for don't care. The enumeration - produces a disjoint cover of the function associated with the diagram. - The size of the array equals the number of variables in the manager at - the time Cudd_FirstCube is called.

              - For each cube, a value is also returned. This value is always 1 for a - BDD, while it may be different from 1 for an ADD. - For BDDs, the offset is the set of cubes whose value is the logical zero. - For ADDs, the offset is the set of cubes whose value is the - background value. The cubes of the offset are not enumerated.] - - SideEffects [The first cube and its value are returned as side effects.] - - SeeAlso [Cudd_ForeachCube Cudd_NextCube Cudd_GenFree Cudd_IsGenEmpty - Cudd_FirstNode] - -******************************************************************************/ -DdGen * -Cudd_FirstCube( - DdManager * dd, - DdNode * f, - int ** cube, - CUDD_VALUE_TYPE * value) -{ - DdGen *gen; - DdNode *top, *treg, *next, *nreg, *prev, *preg; - int i; - int nvars; - - /* Sanity Check. */ - if (dd == NULL || f == NULL) return(NULL); - - /* Allocate generator an initialize it. */ - gen = ALLOC(DdGen,1); - if (gen == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - gen->manager = dd; - gen->type = CUDD_GEN_CUBES; - gen->status = CUDD_GEN_EMPTY; - gen->gen.cubes.cube = NULL; - gen->gen.cubes.value = DD_ZERO_VAL; - gen->stack.sp = 0; - gen->stack.stack = NULL; - gen->node = NULL; - - nvars = dd->size; - gen->gen.cubes.cube = ALLOC(int,nvars); - if (gen->gen.cubes.cube == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(gen); - return(NULL); - } - for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2; - - /* The maximum stack depth is one plus the number of variables. - ** because a path may have nodes at all levels, including the - ** constant level. - */ - gen->stack.stack = ALLOC(DdNode *, nvars+1); - if (gen->stack.stack == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - FREE(gen->gen.cubes.cube); - FREE(gen); - return(NULL); - } - for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL; - - /* Find the first cube of the onset. */ - gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++; - - while (1) { - top = gen->stack.stack[gen->stack.sp-1]; - treg = Cudd_Regular(top); - if (!cuddIsConstant(treg)) { - /* Take the else branch first. */ - gen->gen.cubes.cube[treg->index] = 0; - next = cuddE(treg); - if (top != treg) next = Cudd_Not(next); - gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; - } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) { - /* Backtrack */ - while (1) { - if (gen->stack.sp == 1) { - /* The current node has no predecessor. */ - gen->status = CUDD_GEN_EMPTY; - gen->stack.sp--; - goto done; - } - prev = gen->stack.stack[gen->stack.sp-2]; - preg = Cudd_Regular(prev); - nreg = cuddT(preg); - if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[preg->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[preg->index] = 2; - gen->stack.sp--; - top = gen->stack.stack[gen->stack.sp-1]; - treg = Cudd_Regular(top); - } - } else { - gen->status = CUDD_GEN_NONEMPTY; - gen->gen.cubes.value = cuddV(top); - goto done; - } - } - -done: - *cube = gen->gen.cubes.cube; - *value = gen->gen.cubes.value; - return(gen); - -} /* end of Cudd_FirstCube */ - - -/**Function******************************************************************** - - Synopsis [Generates the next cube of a decision diagram onset.] - - Description [Generates the next cube of a decision diagram onset, - using generator gen. Returns 0 if the enumeration is completed; 1 - otherwise.] - - SideEffects [The cube and its value are returned as side effects. The - generator is modified.] - - SeeAlso [Cudd_ForeachCube Cudd_FirstCube Cudd_GenFree Cudd_IsGenEmpty - Cudd_NextNode] - -******************************************************************************/ -int -Cudd_NextCube( - DdGen * gen, - int ** cube, - CUDD_VALUE_TYPE * value) -{ - DdNode *top, *treg, *next, *nreg, *prev, *preg; - DdManager *dd = gen->manager; - - /* Backtrack from previously reached terminal node. */ - while (1) { - if (gen->stack.sp == 1) { - /* The current node has no predecessor. */ - gen->status = CUDD_GEN_EMPTY; - gen->stack.sp--; - goto done; - } - top = gen->stack.stack[gen->stack.sp-1]; - treg = Cudd_Regular(top); - prev = gen->stack.stack[gen->stack.sp-2]; - preg = Cudd_Regular(prev); - nreg = cuddT(preg); - if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[preg->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[preg->index] = 2; - gen->stack.sp--; - } - - while (1) { - top = gen->stack.stack[gen->stack.sp-1]; - treg = Cudd_Regular(top); - if (!cuddIsConstant(treg)) { - /* Take the else branch first. */ - gen->gen.cubes.cube[treg->index] = 0; - next = cuddE(treg); - if (top != treg) next = Cudd_Not(next); - gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; - } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) { - /* Backtrack */ - while (1) { - if (gen->stack.sp == 1) { - /* The current node has no predecessor. */ - gen->status = CUDD_GEN_EMPTY; - gen->stack.sp--; - goto done; - } - prev = gen->stack.stack[gen->stack.sp-2]; - preg = Cudd_Regular(prev); - nreg = cuddT(preg); - if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;} - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[preg->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[preg->index] = 2; - gen->stack.sp--; - top = gen->stack.stack[gen->stack.sp-1]; - treg = Cudd_Regular(top); - } - } else { - gen->status = CUDD_GEN_NONEMPTY; - gen->gen.cubes.value = cuddV(top); - goto done; - } - } - -done: - if (gen->status == CUDD_GEN_EMPTY) return(0); - *cube = gen->gen.cubes.cube; - *value = gen->gen.cubes.value; - return(1); - -} /* end of Cudd_NextCube */ - - -/**Function******************************************************************** - - Synopsis [Computes the cube of an array of BDD variables.] - - Description [Computes the cube of an array of BDD variables. If - non-null, the phase argument indicates which literal of each - variable should appear in the cube. If phase\[i\] is nonzero, then the - positive literal is used. If phase is NULL, the cube is positive unate. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_addComputeCube Cudd_IndicesToCube Cudd_CubeArrayToBdd] - -******************************************************************************/ -DdNode * -Cudd_bddComputeCube( - DdManager * dd, - DdNode ** vars, - int * phase, - int n) -{ - DdNode *cube; - DdNode *fn; - int i; - - cube = DD_ONE(dd); - cuddRef(cube); - - for (i = n - 1; i >= 0; i--) { - if (phase == NULL || phase[i] != 0) { - fn = Cudd_bddAnd(dd,vars[i],cube); - } else { - fn = Cudd_bddAnd(dd,Cudd_Not(vars[i]),cube); - } - if (fn == NULL) { - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(fn); - Cudd_RecursiveDeref(dd,cube); - cube = fn; - } - cuddDeref(cube); - - return(cube); - -} /* end of Cudd_bddComputeCube */ - - -/**Function******************************************************************** - - Synopsis [Computes the cube of an array of ADD variables.] - - Description [Computes the cube of an array of ADD variables. If - non-null, the phase argument indicates which literal of each - variable should appear in the cube. If phase\[i\] is nonzero, then the - positive literal is used. If phase is NULL, the cube is positive unate. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [none] - - SeeAlso [Cudd_bddComputeCube] - -******************************************************************************/ -DdNode * -Cudd_addComputeCube( - DdManager * dd, - DdNode ** vars, - int * phase, - int n) -{ - DdNode *cube, *zero; - DdNode *fn; - int i; - - cube = DD_ONE(dd); - cuddRef(cube); - zero = DD_ZERO(dd); - - for (i = n - 1; i >= 0; i--) { - if (phase == NULL || phase[i] != 0) { - fn = Cudd_addIte(dd,vars[i],cube,zero); - } else { - fn = Cudd_addIte(dd,vars[i],zero,cube); - } - if (fn == NULL) { - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(fn); - Cudd_RecursiveDeref(dd,cube); - cube = fn; - } - cuddDeref(cube); - - return(cube); - -} /* end of Cudd_addComputeCube */ - - -/**Function******************************************************************** - - Synopsis [Builds the BDD of a cube from a positional array.] - - Description [Builds a cube from a positional array. The array must - have one integer entry for each BDD variable. If the i-th entry is - 1, the variable of index i appears in true form in the cube; If the - i-th entry is 0, the variable of index i appears complemented in the - cube; otherwise the variable does not appear in the cube. Returns a - pointer to the BDD for the cube if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddComputeCube Cudd_IndicesToCube Cudd_BddToCubeArray] - -******************************************************************************/ -DdNode * -Cudd_CubeArrayToBdd( - DdManager *dd, - int *array) -{ - DdNode *cube, *var, *tmp; - int i; - int size = Cudd_ReadSize(dd); - - cube = DD_ONE(dd); - cuddRef(cube); - for (i = size - 1; i >= 0; i--) { - if ((array[i] & ~1) == 0) { - var = Cudd_bddIthVar(dd,i); - tmp = Cudd_bddAnd(dd,cube,Cudd_NotCond(var,array[i]==0)); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,cube); - cube = tmp; - } - } - cuddDeref(cube); - return(cube); - -} /* end of Cudd_CubeArrayToBdd */ - - -/**Function******************************************************************** - - Synopsis [Builds a positional array from the BDD of a cube.] - - Description [Builds a positional array from the BDD of a cube. - Array must have one entry for each BDD variable. The positional - array has 1 in i-th position if the variable of index i appears in - true form in the cube; it has 0 in i-th position if the variable of - index i appears in complemented form in the cube; finally, it has 2 - in i-th position if the variable of index i does not appear in the - cube. Returns 1 if successful (the BDD is indeed a cube); 0 - otherwise.] - - SideEffects [The result is in the array passed by reference.] - - SeeAlso [Cudd_CubeArrayToBdd] - -******************************************************************************/ -int -Cudd_BddToCubeArray( - DdManager *dd, - DdNode *cube, - int *array) -{ - DdNode *scan, *t, *e; - int i; - int size = Cudd_ReadSize(dd); - DdNode *zero = Cudd_Not(DD_ONE(dd)); - - for (i = size-1; i >= 0; i--) { - array[i] = 2; - } - scan = cube; - while (!Cudd_IsConstant(scan)) { - int index = Cudd_Regular(scan)->index; - cuddGetBranches(scan,&t,&e); - if (t == zero) { - array[index] = 0; - scan = e; - } else if (e == zero) { - array[index] = 1; - scan = t; - } else { - return(0); /* cube is not a cube */ - } - } - if (scan == zero) { - return(0); - } else { - return(1); - } - -} /* end of Cudd_BddToCubeArray */ - - -/**Function******************************************************************** - - Synopsis [Finds the first node of a decision diagram.] - - Description [Defines an iterator on the nodes of a decision diagram - and finds its first node. Returns a generator that contains the - information necessary to continue the enumeration if successful; NULL - otherwise.] - - SideEffects [The first node is returned as a side effect.] - - SeeAlso [Cudd_ForeachNode Cudd_NextNode Cudd_GenFree Cudd_IsGenEmpty - Cudd_FirstCube] - -******************************************************************************/ -DdGen * -Cudd_FirstNode( - DdManager * dd, - DdNode * f, - DdNode ** node) -{ - DdGen *gen; - int retval; - - /* Sanity Check. */ - if (dd == NULL || f == NULL) return(NULL); - - /* Allocate generator an initialize it. */ - gen = ALLOC(DdGen,1); - if (gen == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - gen->manager = dd; - gen->type = CUDD_GEN_NODES; - gen->status = CUDD_GEN_EMPTY; - gen->gen.nodes.visited = NULL; - gen->gen.nodes.stGen = NULL; - gen->stack.sp = 0; - gen->stack.stack = NULL; - gen->node = NULL; - - gen->gen.nodes.visited = st_init_table(st_ptrcmp,st_ptrhash); - if (gen->gen.nodes.visited == NULL) { - FREE(gen); - return(NULL); - } - - /* Collect all the nodes in a st table for later perusal. */ - retval = cuddCollectNodes(Cudd_Regular(f),gen->gen.nodes.visited); - if (retval == 0) { - st_free_table(gen->gen.nodes.visited); - FREE(gen); - return(NULL); - } - - /* Initialize the st table generator. */ - gen->gen.nodes.stGen = st_init_gen(gen->gen.nodes.visited); - if (gen->gen.nodes.stGen == NULL) { - st_free_table(gen->gen.nodes.visited); - FREE(gen); - return(NULL); - } - - /* Find the first node. */ - retval = st_gen(gen->gen.nodes.stGen, (char **) &(gen->node), NULL); - if (retval != 0) { - gen->status = CUDD_GEN_NONEMPTY; - *node = gen->node; - } - - return(gen); - -} /* end of Cudd_FirstNode */ - - -/**Function******************************************************************** - - Synopsis [Finds the next node of a decision diagram.] - - Description [Finds the node of a decision diagram, using generator - gen. Returns 0 if the enumeration is completed; 1 otherwise.] - - SideEffects [The next node is returned as a side effect.] - - SeeAlso [Cudd_ForeachNode Cudd_FirstNode Cudd_GenFree Cudd_IsGenEmpty - Cudd_NextCube] - -******************************************************************************/ -int -Cudd_NextNode( - DdGen * gen, - DdNode ** node) -{ - int retval; - - /* Find the next node. */ - retval = st_gen(gen->gen.nodes.stGen, (char **) &(gen->node), NULL); - if (retval == 0) { - gen->status = CUDD_GEN_EMPTY; - } else { - *node = gen->node; - } - - return(retval); - -} /* end of Cudd_NextNode */ - - -/**Function******************************************************************** - - Synopsis [Frees a CUDD generator.] - - Description [Frees a CUDD generator. Always returns 0, so that it can - be used in mis-like foreach constructs.] - - SideEffects [None] - - SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube - Cudd_FirstNode Cudd_NextNode Cudd_IsGenEmpty] - -******************************************************************************/ -int -Cudd_GenFree( - DdGen * gen) -{ - - if (gen == NULL) return(0); - switch (gen->type) { - case CUDD_GEN_CUBES: - case CUDD_GEN_ZDD_PATHS: - FREE(gen->gen.cubes.cube); - FREE(gen->stack.stack); - break; - case CUDD_GEN_NODES: - st_free_gen(gen->gen.nodes.stGen); - st_free_table(gen->gen.nodes.visited); - break; - default: - return(0); - } - FREE(gen); - return(0); - -} /* end of Cudd_GenFree */ - - -/**Function******************************************************************** - - Synopsis [Queries the status of a generator.] - - Description [Queries the status of a generator. Returns 1 if the - generator is empty or NULL; 0 otherswise.] - - SideEffects [None] - - SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube - Cudd_FirstNode Cudd_NextNode Cudd_GenFree] - -******************************************************************************/ -int -Cudd_IsGenEmpty( - DdGen * gen) -{ - if (gen == NULL) return(1); - return(gen->status == CUDD_GEN_EMPTY); - -} /* end of Cudd_IsGenEmpty */ - - -/**Function******************************************************************** - - Synopsis [Builds a cube of BDD variables from an array of indices.] - - Description [Builds a cube of BDD variables from an array of indices. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_bddComputeCube Cudd_CubeArrayToBdd] - -******************************************************************************/ -DdNode * -Cudd_IndicesToCube( - DdManager * dd, - int * array, - int n) -{ - DdNode *cube, *tmp; - int i; - - cube = DD_ONE(dd); - cuddRef(cube); - for (i = n - 1; i >= 0; i--) { - tmp = Cudd_bddAnd(dd,Cudd_bddIthVar(dd,array[i]),cube); - if (tmp == NULL) { - Cudd_RecursiveDeref(dd,cube); - return(NULL); - } - cuddRef(tmp); - Cudd_RecursiveDeref(dd,cube); - cube = tmp; - } - - cuddDeref(cube); - return(cube); - -} /* end of Cudd_IndicesToCube */ - - -/**Function******************************************************************** - - Synopsis [Prints the package version number.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_PrintVersion( - FILE * fp) -{ - (void) fprintf(fp, "%s\n", CUDD_VERSION); - -} /* end of Cudd_PrintVersion */ - - -/**Function******************************************************************** - - Synopsis [Computes the average distance between adjacent nodes.] - - Description [Computes the average distance between adjacent nodes in - the manager. Adjacent nodes are node pairs such that the second node - is the then child, else child, or next node in the collision list.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -double -Cudd_AverageDistance( - DdManager * dd) -{ - double tetotal, nexttotal; - double tesubtotal, nextsubtotal; - double temeasured, nextmeasured; - int i, j; - int slots, nvars; - long diff; - DdNode *scan; - DdNodePtr *nodelist; - DdNode *sentinel = &(dd->sentinel); - - nvars = dd->size; - if (nvars == 0) return(0.0); - - /* Initialize totals. */ - tetotal = 0.0; - nexttotal = 0.0; - temeasured = 0.0; - nextmeasured = 0.0; - - /* Scan the variable subtables. */ - for (i = 0; i < nvars; i++) { - nodelist = dd->subtables[i].nodelist; - tesubtotal = 0.0; - nextsubtotal = 0.0; - slots = dd->subtables[i].slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != sentinel) { - diff = (long) scan - (long) cuddT(scan); - tesubtotal += (double) ddAbs(diff); - diff = (long) scan - (long) Cudd_Regular(cuddE(scan)); - tesubtotal += (double) ddAbs(diff); - temeasured += 2.0; - if (scan->next != NULL) { - diff = (long) scan - (long) scan->next; - nextsubtotal += (double) ddAbs(diff); - nextmeasured += 1.0; - } - scan = scan->next; - } - } - tetotal += tesubtotal; - nexttotal += nextsubtotal; - } - - /* Scan the constant table. */ - nodelist = dd->constants.nodelist; - nextsubtotal = 0.0; - slots = dd->constants.slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (scan->next != NULL) { - diff = (long) scan - (long) scan->next; - nextsubtotal += (double) ddAbs(diff); - nextmeasured += 1.0; - } - scan = scan->next; - } - } - nexttotal += nextsubtotal; - - return((tetotal + nexttotal) / (temeasured + nextmeasured)); - -} /* end of Cudd_AverageDistance */ - - -/**Function******************************************************************** - - Synopsis [Portable random number generator.] - - Description [Portable number generator based on ran2 from "Numerical - Recipes in C." It is a long period (> 2 * 10^18) random number generator - of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly - distributed between 0 and 2147483561 (inclusive of the endpoint values). - The random generator can be explicitly initialized by calling - Cudd_Srandom. If no explicit initialization is performed, then the - seed 1 is assumed.] - - SideEffects [None] - - SeeAlso [Cudd_Srandom] - -******************************************************************************/ -long -Cudd_Random( - ) -{ - int i; /* index in the shuffle table */ - long int w; /* work variable */ - - /* cuddRand == 0 if the geneartor has not been initialized yet. */ - if (cuddRand == 0) Cudd_Srandom(1); - - /* Compute cuddRand = (cuddRand * LEQA1) % MODULUS1 avoiding - ** overflows by Schrage's method. - */ - w = cuddRand / LEQQ1; - cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1; - cuddRand += (cuddRand < 0) * MODULUS1; - - /* Compute cuddRand2 = (cuddRand2 * LEQA2) % MODULUS2 avoiding - ** overflows by Schrage's method. - */ - w = cuddRand2 / LEQQ2; - cuddRand2 = LEQA2 * (cuddRand2 - w * LEQQ2) - w * LEQR2; - cuddRand2 += (cuddRand2 < 0) * MODULUS2; - - /* cuddRand is shuffled with the Bays-Durham algorithm. - ** shuffleSelect and cuddRand2 are combined to generate the output. - */ - - /* Pick one element from the shuffle table; "i" will be in the range - ** from 0 to STAB_SIZE-1. - */ - i = (int) (shuffleSelect / STAB_DIV); - /* Mix the element of the shuffle table with the current iterate of - ** the second sub-generator, and replace the chosen element of the - ** shuffle table with the current iterate of the first sub-generator. - */ - shuffleSelect = shuffleTable[i] - cuddRand2; - shuffleTable[i] = cuddRand; - shuffleSelect += (shuffleSelect < 1) * (MODULUS1 - 1); - /* Since shuffleSelect != 0, and we want to be able to return 0, - ** here we subtract 1 before returning. - */ - return(shuffleSelect - 1); - -} /* end of Cudd_Random */ - - -/**Function******************************************************************** - - Synopsis [Initializer for the portable random number generator.] - - Description [Initializer for the portable number generator based on - ran2 in "Numerical Recipes in C." The input is the seed for the - generator. If it is negative, its absolute value is taken as seed. - If it is 0, then 1 is taken as seed. The initialized sets up the two - recurrences used to generate a long-period stream, and sets up the - shuffle table.] - - SideEffects [None] - - SeeAlso [Cudd_Random] - -******************************************************************************/ -void -Cudd_Srandom( - long seed) -{ - int i; - - if (seed < 0) cuddRand = -seed; - else if (seed == 0) cuddRand = 1; - else cuddRand = seed; - cuddRand2 = cuddRand; - /* Load the shuffle table (after 11 warm-ups). */ - for (i = 0; i < STAB_SIZE + 11; i++) { - long int w; - w = cuddRand / LEQQ1; - cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1; - cuddRand += (cuddRand < 0) * MODULUS1; - shuffleTable[i % STAB_SIZE] = cuddRand; - } - shuffleSelect = shuffleTable[1 % STAB_SIZE]; - -} /* end of Cudd_Srandom */ - - -/**Function******************************************************************** - - Synopsis [Computes the density of a BDD or ADD.] - - Description [Computes the density of a BDD or ADD. The density is - the ratio of the number of minterms to the number of nodes. If 0 is - passed as number of variables, the number of variables existing in - the manager is used. Returns the density if successful; (double) - CUDD_OUT_OF_MEM otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_CountMinterm Cudd_DagSize] - -******************************************************************************/ -double -Cudd_Density( - DdManager * dd /* manager */, - DdNode * f /* function whose density is sought */, - int nvars /* size of the support of f */) -{ - double minterms; - int nodes; - double density; - - if (nvars == 0) nvars = dd->size; - minterms = Cudd_CountMinterm(dd,f,nvars); - if (minterms == (double) CUDD_OUT_OF_MEM) return(minterms); - nodes = Cudd_DagSize(f); - density = minterms / (double) nodes; - return(density); - -} /* end of Cudd_Density */ - - -/**Function******************************************************************** - - Synopsis [Warns that a memory allocation failed.] - - Description [Warns that a memory allocation failed. - This function can be used as replacement of MMout_of_memory to prevent - the safe_mem functions of the util package from exiting when malloc - returns NULL. One possible use is in case of discretionary allocations; - for instance, the allocation of memory to enlarge the computed table.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_OutOfMem( - long size /* size of the allocation that failed */) -{ - (void) fflush(stdout); - (void) fprintf(stderr, "\nunable to allocate %ld bytes\n", size); - return; - -} /* end of Cudd_OutOfMem */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints a DD to the standard output. One line per node is - printed.] - - Description [Prints a DD to the standard output. One line per node is - printed. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_PrintDebug] - -******************************************************************************/ -int -cuddP( - DdManager * dd, - DdNode * f) -{ - int retval; - st_table *table = st_init_table(st_ptrcmp,st_ptrhash); - - if (table == NULL) return(0); - - retval = dp2(dd,f,table); - st_free_table(table); - (void) fputc('\n',dd->out); - return(retval); - -} /* end of cuddP */ - - -/**Function******************************************************************** - - Synopsis [Frees the memory used to store the minterm counts recorded - in the visited table.] - - Description [Frees the memory used to store the minterm counts - recorded in the visited table. Returns ST_CONTINUE.] - - SideEffects [None] - -******************************************************************************/ -enum st_retval -cuddStCountfree( - char * key, - char * value, - char * arg) -{ - double *d; - - d = (double *)value; - FREE(d); - return(ST_CONTINUE); - -} /* end of cuddStCountfree */ - - -/**Function******************************************************************** - - Synopsis [Recursively collects all the nodes of a DD in a symbol - table.] - - Description [Traverses the BDD f and collects all its nodes in a - symbol table. f is assumed to be a regular pointer and - cuddCollectNodes guarantees this assumption in the recursive calls. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddCollectNodes( - DdNode * f, - st_table * visited) -{ - DdNode *T, *E; - int retval; - -#ifdef DD_DEBUG - assert(!Cudd_IsComplement(f)); -#endif - - /* If already visited, nothing to do. */ - if (st_is_member(visited, (char *) f) == 1) - return(1); - - /* Check for abnormal condition that should never happen. */ - if (f == NULL) - return(0); - - /* Mark node as visited. */ - if (st_add_direct(visited, (char *) f, NULL) == ST_OUT_OF_MEM) - return(0); - - /* Check terminal case. */ - if (cuddIsConstant(f)) - return(1); - - /* Recursive calls. */ - T = cuddT(f); - retval = cuddCollectNodes(T,visited); - if (retval != 1) return(retval); - E = Cudd_Regular(cuddE(f)); - retval = cuddCollectNodes(E,visited); - return(retval); - -} /* end of cuddCollectNodes */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of cuddP.] - - Description [Performs the recursive step of cuddP. Returns 1 in case - of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -dp2( - DdManager *dd, - DdNode * f, - st_table * t) -{ - DdNode *g, *n, *N; - int T,E; - - if (f == NULL) { - return(0); - } - g = Cudd_Regular(f); - if (cuddIsConstant(g)) { -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out,"ID = %c0x%lx\tvalue = %-9g\n", bang(f), - (unsigned long) g / (unsigned long) sizeof(DdNode),cuddV(g)); -#else - (void) fprintf(dd->out,"ID = %c0x%x\tvalue = %-9g\n", bang(f), - (unsigned) g / (unsigned) sizeof(DdNode),cuddV(g)); -#endif - return(1); - } - if (st_is_member(t,(char *) g) == 1) { - return(1); - } - if (st_add_direct(t,(char *) g,NULL) == ST_OUT_OF_MEM) - return(0); -#ifdef DD_STATS -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\tr = %d\t", bang(f), - (unsigned long) g / (unsigned long) sizeof(DdNode), g->index, g->ref); -#else - (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\tr = %d\t", bang(f), - (unsigned) g / (unsigned) sizeof(DdNode),g->index,g->ref); -#endif -#else -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\t", bang(f), - (unsigned long) g / (unsigned long) sizeof(DdNode),g->index); -#else - (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\t", bang(f), - (unsigned) g / (unsigned) sizeof(DdNode),g->index); -#endif -#endif - n = cuddT(g); - if (cuddIsConstant(n)) { - (void) fprintf(dd->out,"T = %-9g\t",cuddV(n)); - T = 1; - } else { -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out,"T = 0x%lx\t",(unsigned long) n / (unsigned long) sizeof(DdNode)); -#else - (void) fprintf(dd->out,"T = 0x%x\t",(unsigned) n / (unsigned) sizeof(DdNode)); -#endif - T = 0; - } - - n = cuddE(g); - N = Cudd_Regular(n); - if (cuddIsConstant(N)) { - (void) fprintf(dd->out,"E = %c%-9g\n",bang(n),cuddV(N)); - E = 1; - } else { -#if SIZEOF_VOID_P == 8 - (void) fprintf(dd->out,"E = %c0x%lx\n", bang(n), (unsigned long) N/(unsigned long) sizeof(DdNode)); -#else - (void) fprintf(dd->out,"E = %c0x%x\n", bang(n), (unsigned) N/(unsigned) sizeof(DdNode)); -#endif - E = 0; - } - if (E == 0) { - if (dp2(dd,N,t) == 0) - return(0); - } - if (T == 0) { - if (dp2(dd,cuddT(g),t) == 0) - return(0); - } - return(1); - -} /* end of dp2 */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_PrintMinterm.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -static void -ddPrintMintermAux( - DdManager * dd /* manager */, - DdNode * node /* current node */, - int * list /* current recursion path */) -{ - DdNode *N,*Nv,*Nnv; - int i,v,index; - - N = Cudd_Regular(node); - - if (cuddIsConstant(N)) { - /* Terminal case: Print one cube based on the current recursion - ** path, unless we have reached the background value (ADDs) or - ** the logical zero (BDDs). - */ - if (node != background && node != zero) { - for (i = 0; i < dd->size; i++) { - v = list[i]; - if (v == 0) (void) fprintf(dd->out,"0"); - else if (v == 1) (void) fprintf(dd->out,"1"); - else (void) fprintf(dd->out,"-"); - } - (void) fprintf(dd->out," % g\n", cuddV(node)); - } - } else { - Nv = cuddT(N); - Nnv = cuddE(N); - if (Cudd_IsComplement(node)) { - Nv = Cudd_Not(Nv); - Nnv = Cudd_Not(Nnv); - } - index = N->index; - list[index] = 0; - ddPrintMintermAux(dd,Nnv,list); - list[index] = 1; - ddPrintMintermAux(dd,Nv,list); - list[index] = 2; - } - return; - -} /* end of ddPrintMintermAux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_DagSize.] - - Description [Performs the recursive step of Cudd_DagSize. Returns the - number of nodes in the graph rooted at n.] - - SideEffects [None] - -******************************************************************************/ -static int -ddDagInt( - DdNode * n) -{ - int tval, eval; - - if (Cudd_IsComplement(n->next)) { - return(0); - } - n->next = Cudd_Not(n->next); - if (cuddIsConstant(n)) { - return(1); - } - tval = ddDagInt(cuddT(n)); - eval = ddDagInt(Cudd_Regular(cuddE(n))); - return(1 + tval + eval); - -} /* end of ddDagInt */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CofactorEstimate.] - - Description [Performs the recursive step of Cudd_CofactorEstimate. - Returns an estimate of the number of nodes in the DD of a - cofactor of node. Uses the least significant bit of the next field as - visited flag. node is supposed to be regular; the invariant is maintained - by this procedure.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddEstimateCofactor( - DdManager *dd, - st_table *table, - DdNode * node, - int i, - int phase, - DdNode ** ptr) -{ - int tval, eval, val; - DdNode *ptrT, *ptrE; - - if (Cudd_IsComplement(node->next)) { - if (!st_lookup(table,(char *)node,(char **)ptr)) { - st_add_direct(table,(char *)node,(char *)node); - *ptr = node; - } - return(0); - } - node->next = Cudd_Not(node->next); - if (cuddIsConstant(node)) { - *ptr = node; - if (st_add_direct(table,(char *)node,(char *)node) == ST_OUT_OF_MEM) - return(CUDD_OUT_OF_MEM); - return(1); - } - if ((int) node->index == i) { - if (phase == 1) { - *ptr = cuddT(node); - val = ddDagInt(cuddT(node)); - } else { - *ptr = cuddE(node); - val = ddDagInt(Cudd_Regular(cuddE(node))); - } - if (node->ref > 1) { - if (st_add_direct(table,(char *)node,(char *)*ptr) == - ST_OUT_OF_MEM) - return(CUDD_OUT_OF_MEM); - } - return(val); - } - if (dd->perm[node->index] > dd->perm[i]) { - *ptr = node; - tval = ddDagInt(cuddT(node)); - eval = ddDagInt(Cudd_Regular(cuddE(node))); - if (node->ref > 1) { - if (st_add_direct(table,(char *)node,(char *)node) == - ST_OUT_OF_MEM) - return(CUDD_OUT_OF_MEM); - } - val = 1 + tval + eval; - return(val); - } - tval = cuddEstimateCofactor(dd,table,cuddT(node),i,phase,&ptrT); - eval = cuddEstimateCofactor(dd,table,Cudd_Regular(cuddE(node)),i, - phase,&ptrE); - ptrE = Cudd_NotCond(ptrE,Cudd_IsComplement(cuddE(node))); - if (ptrT == ptrE) { /* recombination */ - *ptr = ptrT; - val = tval; - if (node->ref > 1) { - if (st_add_direct(table,(char *)node,(char *)*ptr) == - ST_OUT_OF_MEM) - return(CUDD_OUT_OF_MEM); - } - } else if ((ptrT != cuddT(node) || ptrE != cuddE(node)) && - (*ptr = cuddUniqueLookup(dd,node->index,ptrT,ptrE)) != NULL) { - if (Cudd_IsComplement((*ptr)->next)) { - val = 0; - } else { - val = 1 + tval + eval; - } - if (node->ref > 1) { - if (st_add_direct(table,(char *)node,(char *)*ptr) == - ST_OUT_OF_MEM) - return(CUDD_OUT_OF_MEM); - } - } else { - *ptr = node; - val = 1 + tval + eval; - } - return(val); - -} /* end of cuddEstimateCofactor */ - - -/**Function******************************************************************** - - Synopsis [Checks the unique table for the existence of an internal node.] - - Description [Checks the unique table for the existence of an internal - node. Returns a pointer to the node if it is in the table; NULL otherwise.] - - SideEffects [None] - - SeeAlso [cuddUniqueInter] - -******************************************************************************/ -static DdNode * -cuddUniqueLookup( - DdManager * unique, - int index, - DdNode * T, - DdNode * E) -{ - int posn; - unsigned int level; - DdNodePtr *nodelist; - DdNode *looking; - DdSubtable *subtable; - - if (index >= unique->size) { - return(NULL); - } - - level = unique->perm[index]; - subtable = &(unique->subtables[level]); - -#ifdef DD_DEBUG - assert(level < (unsigned) cuddI(unique,T->index)); - assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index)); -#endif - - posn = ddHash(T, E, subtable->shift); - nodelist = subtable->nodelist; - looking = nodelist[posn]; - - while (T < cuddT(looking)) { - looking = Cudd_Regular(looking->next); - } - while (T == cuddT(looking) && E < cuddE(looking)) { - looking = Cudd_Regular(looking->next); - } - if (cuddT(looking) == T && cuddE(looking) == E) { - return(looking); - } - - return(NULL); - -} /* end of cuddUniqueLookup */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CofactorEstimateSimple.] - - Description [Performs the recursive step of Cudd_CofactorEstimateSimple. - Returns an estimate of the number of nodes in the DD of the positive - cofactor of node. Uses the least significant bit of the next field as - visited flag. node is supposed to be regular; the invariant is maintained - by this procedure.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddEstimateCofactorSimple( - DdNode * node, - int i) -{ - int tval, eval; - - if (Cudd_IsComplement(node->next)) { - return(0); - } - node->next = Cudd_Not(node->next); - if (cuddIsConstant(node)) { - return(1); - } - tval = cuddEstimateCofactorSimple(cuddT(node),i); - if ((int) node->index == i) return(tval); - eval = cuddEstimateCofactorSimple(Cudd_Regular(cuddE(node)),i); - return(1 + tval + eval); - -} /* end of cuddEstimateCofactorSimple */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CountMinterm.] - - Description [Performs the recursive step of Cudd_CountMinterm. - It is based on the following identity. Let |f| be the - number of minterms of f. Then: -

              - |f| = (|f0|+|f1|)/2 - - where f0 and f1 are the two cofactors of f. Does not use the - identity |f'| = max - |f|, to minimize loss of accuracy due to - roundoff. Returns the number of minterms of the function rooted at - node.] - - SideEffects [None] - -******************************************************************************/ -static double -ddCountMintermAux( - DdNode * node, - double max, - DdHashTable * table) -{ - DdNode *N, *Nt, *Ne; - double min, minT, minE; - DdNode *res; - - N = Cudd_Regular(node); - - if (cuddIsConstant(N)) { - if (node == background || node == zero) { - return(0.0); - } else { - return(max); - } - } - if (N->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) { - min = cuddV(res); - if (res->ref == 0) { - table->manager->dead++; - table->manager->constants.dead++; - } - return(min); - } - - Nt = cuddT(N); Ne = cuddE(N); - if (Cudd_IsComplement(node)) { - Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne); - } - - minT = ddCountMintermAux(Nt,max,table); - if (minT == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - minT *= 0.5; - minE = ddCountMintermAux(Ne,max,table); - if (minE == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - minE *= 0.5; - min = minT + minE; - - if (N->ref != 1) { - ptrint fanout = (ptrint) N->ref; - cuddSatDec(fanout); - res = cuddUniqueConst(table->manager,min); - if (!cuddHashTableInsert1(table,node,res,fanout)) { - cuddRef(res); Cudd_RecursiveDeref(table->manager, res); - return((double)CUDD_OUT_OF_MEM); - } - } - - return(min); - -} /* end of ddCountMintermAux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CountPath.] - - Description [Performs the recursive step of Cudd_CountPath. - It is based on the following identity. Let |f| be the - number of paths of f. Then: - - |f| = |f0|+|f1| - - where f0 and f1 are the two cofactors of f. Uses the - identity |f'| = |f|, to improve the utilization of the (local) cache. - Returns the number of paths of the function rooted at node.] - - SideEffects [None] - -******************************************************************************/ -static double -ddCountPathAux( - DdNode * node, - st_table * table) -{ - - DdNode *Nv, *Nnv; - double paths, *ppaths, paths1, paths2; - double *dummy; - - - if (cuddIsConstant(node)) { - return(1.0); - } - if (st_lookup(table, (char *)node, (char **)&dummy)) { - paths = *dummy; - return(paths); - } - - Nv = cuddT(node); Nnv = cuddE(node); - - paths1 = ddCountPathAux(Nv,table); - if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - paths2 = ddCountPathAux(Cudd_Regular(Nnv),table); - if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - paths = paths1 + paths2; - - ppaths = ALLOC(double,1); - if (ppaths == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - - *ppaths = paths; - - if (st_add_direct(table,(char *)node, (char *)ppaths) == ST_OUT_OF_MEM) { - FREE(ppaths); - return((double)CUDD_OUT_OF_MEM); - } - return(paths); - -} /* end of ddCountPathAux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CountMinterm.] - - Description [Performs the recursive step of Cudd_CountMinterm. - It is based on the following identity. Let |f| be the - number of minterms of f. Then: - - |f| = (|f0|+|f1|)/2 - - where f0 and f1 are the two cofactors of f. Does not use the - identity |f'| = max - |f|, to minimize loss of accuracy due to - roundoff. Returns the number of minterms of the function rooted at - node.] - - SideEffects [None] - -******************************************************************************/ -static int -ddEpdCountMintermAux( - DdNode * node, - EpDouble * max, - EpDouble * epd, - st_table * table) -{ - DdNode *Nt, *Ne; - EpDouble *min, minT, minE; - EpDouble *res; - int status; - - if (cuddIsConstant(node)) { - if (node == background || node == zero) { - EpdMakeZero(epd, 0); - } else { - EpdCopy(max, epd); - } - return(0); - } - if (node->ref != 1 && st_lookup(table, (char *)node, (char **)&res)) { - EpdCopy(res, epd); - return(0); - } - - Nt = cuddT(node); Ne = cuddE(node); - if (Cudd_IsComplement(node)) { - Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne); - } - - status = ddEpdCountMintermAux(Nt,max,&minT,table); - if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); - EpdMultiply(&minT, (double)0.5); - status = ddEpdCountMintermAux(Ne,max,&minE,table); - if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM); - if (Cudd_IsComplement(Ne)) { - EpdSubtract3(max, &minE, epd); - EpdCopy(epd, &minE); - } - EpdMultiply(&minE, (double)0.5); - EpdAdd3(&minT, &minE, epd); - - if (node->ref > 1) { - min = EpdAlloc(); - if (!min) - return(CUDD_OUT_OF_MEM); - EpdCopy(epd, min); - if (st_insert(table, (char *)node, (char *)min) == ST_OUT_OF_MEM) { - EpdFree(min); - return(CUDD_OUT_OF_MEM); - } - } - - return(0); - -} /* end of ddEpdCountMintermAux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CountPathsToNonZero.] - - Description [Performs the recursive step of Cudd_CountPathsToNonZero. - It is based on the following identity. Let |f| be the - number of paths of f. Then: - - |f| = |f0|+|f1| - - where f0 and f1 are the two cofactors of f. Returns the number of - paths of the function rooted at node.] - - SideEffects [None] - -******************************************************************************/ -static double -ddCountPathsToNonZero( - DdNode * N, - st_table * table) -{ - - DdNode *node, *Nt, *Ne; - double paths, *ppaths, paths1, paths2; - double *dummy; - - node = Cudd_Regular(N); - if (cuddIsConstant(node)) { - return((double) !(Cudd_IsComplement(N) || cuddV(node)==DD_ZERO_VAL)); - } - if (st_lookup(table, (char *)N, (char **)&dummy)) { - paths = *dummy; - return(paths); - } - - Nt = cuddT(node); Ne = cuddE(node); - if (node != N) { - Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne); - } - - paths1 = ddCountPathsToNonZero(Nt,table); - if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - paths2 = ddCountPathsToNonZero(Ne,table); - if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM); - paths = paths1 + paths2; - - ppaths = ALLOC(double,1); - if (ppaths == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - - *ppaths = paths; - - if (st_add_direct(table,(char *)N, (char *)ppaths) == ST_OUT_OF_MEM) { - FREE(ppaths); - return((double)CUDD_OUT_OF_MEM); - } - return(paths); - -} /* end of ddCountPathsToNonZero */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_Support.] - - Description [Performs the recursive step of Cudd_Support. Performs a - DFS from f. The support is accumulated in supp as a side effect. Uses - the LSB of the then pointer as visited flag.] - - SideEffects [None] - - SeeAlso [ddClearFlag] - -******************************************************************************/ -static void -ddSupportStep( - DdNode * f, - int * support) -{ - if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) { - return; - } - - support[f->index] = 1; - ddSupportStep(cuddT(f),support); - ddSupportStep(Cudd_Regular(cuddE(f)),support); - /* Mark as visited. */ - f->next = Cudd_Not(f->next); - return; - -} /* end of ddSupportStep */ - - -/**Function******************************************************************** - - Synopsis [Performs a DFS from f, clearing the LSB of the next - pointers.] - - Description [] - - SideEffects [None] - - SeeAlso [ddSupportStep ddDagInt] - -******************************************************************************/ -static void -ddClearFlag( - DdNode * f) -{ - if (!Cudd_IsComplement(f->next)) { - return; - } - /* Clear visited flag. */ - f->next = Cudd_Regular(f->next); - if (cuddIsConstant(f)) { - return; - } - ddClearFlag(cuddT(f)); - ddClearFlag(Cudd_Regular(cuddE(f))); - return; - -} /* end of ddClearFlag */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_CountLeaves.] - - Description [Performs the recursive step of Cudd_CountLeaves. Returns - the number of leaves in the DD rooted at n.] - - SideEffects [None] - - SeeAlso [Cudd_CountLeaves] - -******************************************************************************/ -static int -ddLeavesInt( - DdNode * n) -{ - int tval, eval; - - if (Cudd_IsComplement(n->next)) { - return(0); - } - n->next = Cudd_Not(n->next); - if (cuddIsConstant(n)) { - return(1); - } - tval = ddLeavesInt(cuddT(n)); - eval = ddLeavesInt(Cudd_Regular(cuddE(n))); - return(tval + eval); - -} /* end of ddLeavesInt */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddPickArbitraryMinterms.] - - Description [Performs the recursive step of Cudd_bddPickArbitraryMinterms. - Returns 1 if successful; 0 otherwise.] - - SideEffects [none] - - SeeAlso [Cudd_bddPickArbitraryMinterms] - -******************************************************************************/ -static int -ddPickArbitraryMinterms( - DdManager *dd, - DdNode *node, - int nvars, - int nminterms, - char **string) -{ - DdNode *N, *T, *E; - DdNode *one, *bzero; - int i, t, result; - double min1, min2; - - if (string == NULL || node == NULL) return(0); - - /* The constant 0 function has no on-set cubes. */ - one = DD_ONE(dd); - bzero = Cudd_Not(one); - if (nminterms == 0 || node == bzero) return(1); - if (node == one) { - return(1); - } - - N = Cudd_Regular(node); - T = cuddT(N); E = cuddE(N); - if (Cudd_IsComplement(node)) { - T = Cudd_Not(T); E = Cudd_Not(E); - } - - min1 = Cudd_CountMinterm(dd, T, nvars) / 2.0; - if (min1 == (double)CUDD_OUT_OF_MEM) return(0); - min2 = Cudd_CountMinterm(dd, E, nvars) / 2.0; - if (min2 == (double)CUDD_OUT_OF_MEM) return(0); - - t = (int)((double)nminterms * min1 / (min1 + min2) + 0.5); - for (i = 0; i < t; i++) - string[i][N->index] = '1'; - for (i = t; i < nminterms; i++) - string[i][N->index] = '0'; - - result = ddPickArbitraryMinterms(dd,T,nvars,t,&string[0]); - if (result == 0) - return(0); - result = ddPickArbitraryMinterms(dd,E,nvars,nminterms-t,&string[t]); - return(result); - -} /* end of ddPickArbitraryMinterms */ - - -/**Function******************************************************************** - - Synopsis [Finds a representative cube of a BDD.] - - Description [Finds a representative cube of a BDD with the weight of - each variable. From the top variable, if the weight is greater than or - equal to 0.0, choose THEN branch unless the child is the constant 0. - Otherwise, choose ELSE branch unless the child is the constant 0.] - - SideEffects [Cudd_SubsetWithMaskVars Cudd_bddPickOneCube] - -******************************************************************************/ -static int -ddPickRepresentativeCube( - DdManager *dd, - DdNode *node, - int nvars, - double *weight, - char *string) -{ - DdNode *N, *T, *E; - DdNode *one, *bzero; - - if (string == NULL || node == NULL) return(0); - - /* The constant 0 function has no on-set cubes. */ - one = DD_ONE(dd); - bzero = Cudd_Not(one); - if (node == bzero) return(0); - - if (node == DD_ONE(dd)) return(1); - - for (;;) { - N = Cudd_Regular(node); - if (N == one) - break; - T = cuddT(N); - E = cuddE(N); - if (Cudd_IsComplement(node)) { - T = Cudd_Not(T); - E = Cudd_Not(E); - } - if (weight[N->index] >= 0.0) { - if (T == bzero) { - node = E; - string[N->index] = '0'; - } else { - node = T; - string[N->index] = '1'; - } - } else { - if (E == bzero) { - node = T; - string[N->index] = '1'; - } else { - node = E; - string[N->index] = '0'; - } - } - } - return(1); - -} /* end of ddPickRepresentativeCube */ - - -/**Function******************************************************************** - - Synopsis [Frees the memory used to store the minterm counts recorded - in the visited table.] - - Description [Frees the memory used to store the minterm counts - recorded in the visited table. Returns ST_CONTINUE.] - - SideEffects [None] - -******************************************************************************/ -static enum st_retval -ddEpdFree( - char * key, - char * value, - char * arg) -{ - EpDouble *epd; - - epd = (EpDouble *) value; - EpdFree(epd); - return(ST_CONTINUE); - -} /* end of ddEpdFree */ diff --git a/src/bdd/cudd/cuddWindow.c b/src/bdd/cudd/cuddWindow.c deleted file mode 100644 index 9ceb79b2..00000000 --- a/src/bdd/cudd/cuddWindow.c +++ /dev/null @@ -1,997 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddWindow.c] - - PackageName [cudd] - - Synopsis [Functions for window permutation] - - Description [Internal procedures included in this module: -
                -
              • cuddWindowReorder() -
              - Static procedures included in this module: -
                -
              • ddWindow2() -
              • ddWindowConv2() -
              • ddPermuteWindow3() -
              • ddWindow3() -
              • ddWindowConv3() -
              • ddPermuteWindow4() -
              • ddWindow4() -
              • ddWindowConv4() -
              ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddWindow.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -#ifdef DD_STATS -extern int ddTotalNumberSwapping; -extern int ddTotalNISwaps; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int ddWindow2 ARGS((DdManager *table, int low, int high)); -static int ddWindowConv2 ARGS((DdManager *table, int low, int high)); -static int ddPermuteWindow3 ARGS((DdManager *table, int x)); -static int ddWindow3 ARGS((DdManager *table, int low, int high)); -static int ddWindowConv3 ARGS((DdManager *table, int low, int high)); -static int ddPermuteWindow4 ARGS((DdManager *table, int w)); -static int ddWindow4 ARGS((DdManager *table, int low, int high)); -static int ddWindowConv4 ARGS((DdManager *table, int low, int high)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Reorders by applying the method of the sliding window.] - - Description [Reorders by applying the method of the sliding window. - Tries all possible permutations to the variables in a window that - slides from low to high. The size of the window is determined by - submethod. Assumes that no dead nodes are present. Returns 1 in - case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddWindowReorder( - DdManager * table /* DD table */, - int low /* lowest index to reorder */, - int high /* highest index to reorder */, - Cudd_ReorderingType submethod /* window reordering option */) -{ - - int res; -#ifdef DD_DEBUG - int supposedOpt; -#endif - - switch (submethod) { - case CUDD_REORDER_WINDOW2: - res = ddWindow2(table,low,high); - break; - case CUDD_REORDER_WINDOW3: - res = ddWindow3(table,low,high); - break; - case CUDD_REORDER_WINDOW4: - res = ddWindow4(table,low,high); - break; - case CUDD_REORDER_WINDOW2_CONV: - res = ddWindowConv2(table,low,high); - break; - case CUDD_REORDER_WINDOW3_CONV: - res = ddWindowConv3(table,low,high); -#ifdef DD_DEBUG - supposedOpt = table->keys - table->isolated; - res = ddWindow3(table,low,high); - if (table->keys - table->isolated != (unsigned) supposedOpt) { - (void) fprintf(table->err, "Convergence failed! (%d != %d)\n", - table->keys - table->isolated, supposedOpt); - } -#endif - break; - case CUDD_REORDER_WINDOW4_CONV: - res = ddWindowConv4(table,low,high); -#ifdef DD_DEBUG - supposedOpt = table->keys - table->isolated; - res = ddWindow4(table,low,high); - if (table->keys - table->isolated != (unsigned) supposedOpt) { - (void) fprintf(table->err,"Convergence failed! (%d != %d)\n", - table->keys - table->isolated, supposedOpt); - } -#endif - break; - default: return(0); - } - - return(res); - -} /* end of cuddWindowReorder */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Reorders by applying a sliding window of width 2.] - - Description [Reorders by applying a sliding window of width 2. - Tries both permutations of the variables in a window - that slides from low to high. Assumes that no dead nodes are - present. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindow2( - DdManager * table, - int low, - int high) -{ - - int x; - int res; - int size; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 1) return(0); - - res = table->keys - table->isolated; - for (x = low; x < high; x++) { - size = res; - res = cuddSwapInPlace(table,x,x+1); - if (res == 0) return(0); - if (res >= size) { /* no improvement: undo permutation */ - res = cuddSwapInPlace(table,x,x+1); - if (res == 0) return(0); - } -#ifdef DD_STATS - if (res < size) { - (void) fprintf(table->out,"-"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - return(1); - -} /* end of ddWindow2 */ - - -/**Function******************************************************************** - - Synopsis [Reorders by repeatedly applying a sliding window of width 2.] - - Description [Reorders by repeatedly applying a sliding window of width - 2. Tries both permutations of the variables in a window - that slides from low to high. Assumes that no dead nodes are - present. Uses an event-driven approach to determine convergence. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindowConv2( - DdManager * table, - int low, - int high) -{ - int x; - int res; - int nwin; - int newevent; - int *events; - int size; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 1) return(ddWindowConv2(table,low,high)); - - nwin = high-low; - events = ALLOC(int,nwin); - if (events == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (x=0; xkeys - table->isolated; - do { - newevent = 0; - for (x=0; x= size) { /* no improvement: undo permutation */ - res = cuddSwapInPlace(table,x+low,x+low+1); - if (res == 0) { - FREE(events); - return(0); - } - } - if (res < size) { - if (x < nwin-1) events[x+1] = 1; - if (x > 0) events[x-1] = 1; - newevent = 1; - } - events[x] = 0; -#ifdef DD_STATS - if (res < size) { - (void) fprintf(table->out,"-"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } -#ifdef DD_STATS - if (newevent) { - (void) fprintf(table->out,"|"); - fflush(table->out); - } -#endif - } while (newevent); - - FREE(events); - - return(1); - -} /* end of ddWindowConv3 */ - - -/**Function******************************************************************** - - Synopsis [Tries all the permutations of the three variables between - x and x+2 and retains the best.] - - Description [Tries all the permutations of the three variables between - x and x+2 and retains the best. Assumes that no dead nodes are - present. Returns the index of the best permutation (1-6) in case of - success; 0 otherwise.Assumes that no dead nodes are present. Returns - the index of the best permutation (1-6) in case of success; 0 - otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddPermuteWindow3( - DdManager * table, - int x) -{ - int y,z; - int size,sizeNew; - int best; - -#ifdef DD_DEBUG - assert(table->dead == 0); - assert(x+2 < table->size); -#endif - - size = table->keys - table->isolated; - y = x+1; z = y+1; - - /* The permutation pattern is: - ** (x,y)(y,z) - ** repeated three times to get all 3! = 6 permutations. - */ -#define ABC 1 - best = ABC; - -#define BAC 2 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = BAC; - size = sizeNew; - } -#define BCA 3 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = BCA; - size = sizeNew; - } -#define CBA 4 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = CBA; - size = sizeNew; - } -#define CAB 5 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = CAB; - size = sizeNew; - } -#define ACB 6 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = ACB; - size = sizeNew; - } - - /* Now take the shortest route to the best permuytation. - ** The initial permutation is ACB. - */ - switch(best) { - case BCA: if (!cuddSwapInPlace(table,y,z)) return(0); - case CBA: if (!cuddSwapInPlace(table,x,y)) return(0); - case ABC: if (!cuddSwapInPlace(table,y,z)) return(0); - case ACB: break; - case BAC: if (!cuddSwapInPlace(table,y,z)) return(0); - case CAB: if (!cuddSwapInPlace(table,x,y)) return(0); - break; - default: return(0); - } - -#ifdef DD_DEBUG - assert(table->keys - table->isolated == (unsigned) size); -#endif - - return(best); - -} /* end of ddPermuteWindow3 */ - - -/**Function******************************************************************** - - Synopsis [Reorders by applying a sliding window of width 3.] - - Description [Reorders by applying a sliding window of width 3. - Tries all possible permutations to the variables in a - window that slides from low to high. Assumes that no dead nodes are - present. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindow3( - DdManager * table, - int low, - int high) -{ - - int x; - int res; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 2) return(ddWindow2(table,low,high)); - - for (x = low; x+1 < high; x++) { - res = ddPermuteWindow3(table,x); - if (res == 0) return(0); -#ifdef DD_STATS - if (res == ABC) { - (void) fprintf(table->out,"="); - } else { - (void) fprintf(table->out,"-"); - } - fflush(table->out); -#endif - } - - return(1); - -} /* end of ddWindow3 */ - - -/**Function******************************************************************** - - Synopsis [Reorders by repeatedly applying a sliding window of width 3.] - - Description [Reorders by repeatedly applying a sliding window of width - 3. Tries all possible permutations to the variables in a - window that slides from low to high. Assumes that no dead nodes are - present. Uses an event-driven approach to determine convergence. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindowConv3( - DdManager * table, - int low, - int high) -{ - int x; - int res; - int nwin; - int newevent; - int *events; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 2) return(ddWindowConv2(table,low,high)); - - nwin = high-low-1; - events = ALLOC(int,nwin); - if (events == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (x=0; x 1) events[x-2] = 1; - newevent = 1; - break; - case BCA: - case CBA: - case CAB: - if (x < nwin-2) events[x+2] = 1; - if (x < nwin-1) events[x+1] = 1; - if (x > 0) events[x-1] = 1; - if (x > 1) events[x-2] = 1; - newevent = 1; - break; - case ACB: - if (x < nwin-2) events[x+2] = 1; - if (x > 0) events[x-1] = 1; - newevent = 1; - break; - default: - FREE(events); - return(0); - } - events[x] = 0; -#ifdef DD_STATS - if (res == ABC) { - (void) fprintf(table->out,"="); - } else { - (void) fprintf(table->out,"-"); - } - fflush(table->out); -#endif - } - } -#ifdef DD_STATS - if (newevent) { - (void) fprintf(table->out,"|"); - fflush(table->out); - } -#endif - } while (newevent); - - FREE(events); - - return(1); - -} /* end of ddWindowConv3 */ - - -/**Function******************************************************************** - - Synopsis [Tries all the permutations of the four variables between w - and w+3 and retains the best.] - - Description [Tries all the permutations of the four variables between - w and w+3 and retains the best. Assumes that no dead nodes are - present. Returns the index of the best permutation (1-24) in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddPermuteWindow4( - DdManager * table, - int w) -{ - int x,y,z; - int size,sizeNew; - int best; - -#ifdef DD_DEBUG - assert(table->dead == 0); - assert(w+3 < table->size); -#endif - - size = table->keys - table->isolated; - x = w+1; y = x+1; z = y+1; - - /* The permutation pattern is: - * (w,x)(y,z)(w,x)(x,y) - * (y,z)(w,x)(y,z)(x,y) - * repeated three times to get all 4! = 24 permutations. - * This gives a hamiltonian circuit of Cayley's graph. - * The codes to the permutation are assigned in topological order. - * The permutations at lower distance from the final permutation are - * assigned lower codes. This way we can choose, between - * permutations that give the same size, one that requires the minimum - * number of swaps from the final permutation of the hamiltonian circuit. - * There is an exception to this rule: ABCD is given Code 1, to - * avoid oscillation when convergence is sought. - */ -#define ABCD 1 - best = ABCD; - -#define BACD 7 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = BACD; - size = sizeNew; - } -#define BADC 13 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = BADC; - size = sizeNew; - } -#define ABDC 8 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && ABDC < best)) { - if (sizeNew == 0) return(0); - best = ABDC; - size = sizeNew; - } -#define ADBC 14 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = ADBC; - size = sizeNew; - } -#define ADCB 9 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && ADCB < best)) { - if (sizeNew == 0) return(0); - best = ADCB; - size = sizeNew; - } -#define DACB 15 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = DACB; - size = sizeNew; - } -#define DABC 20 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = DABC; - size = sizeNew; - } -#define DBAC 23 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = DBAC; - size = sizeNew; - } -#define BDAC 19 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && BDAC < best)) { - if (sizeNew == 0) return(0); - best = BDAC; - size = sizeNew; - } -#define BDCA 21 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && BDCA < best)) { - if (sizeNew == 0) return(0); - best = BDCA; - size = sizeNew; - } -#define DBCA 24 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size) { - if (sizeNew == 0) return(0); - best = DBCA; - size = sizeNew; - } -#define DCBA 22 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size || (sizeNew == size && DCBA < best)) { - if (sizeNew == 0) return(0); - best = DCBA; - size = sizeNew; - } -#define DCAB 18 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && DCAB < best)) { - if (sizeNew == 0) return(0); - best = DCAB; - size = sizeNew; - } -#define CDAB 12 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && CDAB < best)) { - if (sizeNew == 0) return(0); - best = CDAB; - size = sizeNew; - } -#define CDBA 17 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && CDBA < best)) { - if (sizeNew == 0) return(0); - best = CDBA; - size = sizeNew; - } -#define CBDA 11 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size || (sizeNew == size && CBDA < best)) { - if (sizeNew == 0) return(0); - best = CBDA; - size = sizeNew; - } -#define BCDA 16 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && BCDA < best)) { - if (sizeNew == 0) return(0); - best = BCDA; - size = sizeNew; - } -#define BCAD 10 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && BCAD < best)) { - if (sizeNew == 0) return(0); - best = BCAD; - size = sizeNew; - } -#define CBAD 5 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && CBAD < best)) { - if (sizeNew == 0) return(0); - best = CBAD; - size = sizeNew; - } -#define CABD 3 - sizeNew = cuddSwapInPlace(table,x,y); - if (sizeNew < size || (sizeNew == size && CABD < best)) { - if (sizeNew == 0) return(0); - best = CABD; - size = sizeNew; - } -#define CADB 6 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && CADB < best)) { - if (sizeNew == 0) return(0); - best = CADB; - size = sizeNew; - } -#define ACDB 4 - sizeNew = cuddSwapInPlace(table,w,x); - if (sizeNew < size || (sizeNew == size && ACDB < best)) { - if (sizeNew == 0) return(0); - best = ACDB; - size = sizeNew; - } -#define ACBD 2 - sizeNew = cuddSwapInPlace(table,y,z); - if (sizeNew < size || (sizeNew == size && ACBD < best)) { - if (sizeNew == 0) return(0); - best = ACBD; - size = sizeNew; - } - - /* Now take the shortest route to the best permutation. - ** The initial permutation is ACBD. - */ - switch(best) { - case DBCA: if (!cuddSwapInPlace(table,y,z)) return(0); - case BDCA: if (!cuddSwapInPlace(table,x,y)) return(0); - case CDBA: if (!cuddSwapInPlace(table,w,x)) return(0); - case ADBC: if (!cuddSwapInPlace(table,y,z)) return(0); - case ABDC: if (!cuddSwapInPlace(table,x,y)) return(0); - case ACDB: if (!cuddSwapInPlace(table,y,z)) return(0); - case ACBD: break; - case DCBA: if (!cuddSwapInPlace(table,y,z)) return(0); - case BCDA: if (!cuddSwapInPlace(table,x,y)) return(0); - case CBDA: if (!cuddSwapInPlace(table,w,x)) return(0); - if (!cuddSwapInPlace(table,x,y)) return(0); - if (!cuddSwapInPlace(table,y,z)) return(0); - break; - case DBAC: if (!cuddSwapInPlace(table,x,y)) return(0); - case DCAB: if (!cuddSwapInPlace(table,w,x)) return(0); - case DACB: if (!cuddSwapInPlace(table,y,z)) return(0); - case BACD: if (!cuddSwapInPlace(table,x,y)) return(0); - case CABD: if (!cuddSwapInPlace(table,w,x)) return(0); - break; - case DABC: if (!cuddSwapInPlace(table,y,z)) return(0); - case BADC: if (!cuddSwapInPlace(table,x,y)) return(0); - case CADB: if (!cuddSwapInPlace(table,w,x)) return(0); - if (!cuddSwapInPlace(table,y,z)) return(0); - break; - case BDAC: if (!cuddSwapInPlace(table,x,y)) return(0); - case CDAB: if (!cuddSwapInPlace(table,w,x)) return(0); - case ADCB: if (!cuddSwapInPlace(table,y,z)) return(0); - case ABCD: if (!cuddSwapInPlace(table,x,y)) return(0); - break; - case BCAD: if (!cuddSwapInPlace(table,x,y)) return(0); - case CBAD: if (!cuddSwapInPlace(table,w,x)) return(0); - if (!cuddSwapInPlace(table,x,y)) return(0); - break; - default: return(0); - } - -#ifdef DD_DEBUG - assert(table->keys - table->isolated == (unsigned) size); -#endif - - return(best); - -} /* end of ddPermuteWindow4 */ - - -/**Function******************************************************************** - - Synopsis [Reorders by applying a sliding window of width 4.] - - Description [Reorders by applying a sliding window of width 4. - Tries all possible permutations to the variables in a - window that slides from low to high. Assumes that no dead nodes are - present. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindow4( - DdManager * table, - int low, - int high) -{ - - int w; - int res; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 3) return(ddWindow3(table,low,high)); - - for (w = low; w+2 < high; w++) { - res = ddPermuteWindow4(table,w); - if (res == 0) return(0); -#ifdef DD_STATS - if (res == ABCD) { - (void) fprintf(table->out,"="); - } else { - (void) fprintf(table->out,"-"); - } - fflush(table->out); -#endif - } - - return(1); - -} /* end of ddWindow4 */ - - -/**Function******************************************************************** - - Synopsis [Reorders by repeatedly applying a sliding window of width 4.] - - Description [Reorders by repeatedly applying a sliding window of width - 4. Tries all possible permutations to the variables in a - window that slides from low to high. Assumes that no dead nodes are - present. Uses an event-driven approach to determine convergence. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -ddWindowConv4( - DdManager * table, - int low, - int high) -{ - int x; - int res; - int nwin; - int newevent; - int *events; - -#ifdef DD_DEBUG - assert(low >= 0 && high < table->size); -#endif - - if (high-low < 3) return(ddWindowConv3(table,low,high)); - - nwin = high-low-2; - events = ALLOC(int,nwin); - if (events == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (x=0; x 2) events[x-3] = 1; - newevent = 1; - break; - case BADC: - if (x < nwin-3) events[x+3] = 1; - if (x < nwin-1) events[x+1] = 1; - if (x > 0) events[x-1] = 1; - if (x > 2) events[x-3] = 1; - newevent = 1; - break; - case ABDC: - if (x < nwin-3) events[x+3] = 1; - if (x > 0) events[x-1] = 1; - newevent = 1; - break; - case ADBC: - case ADCB: - case ACDB: - if (x < nwin-3) events[x+3] = 1; - if (x < nwin-2) events[x+2] = 1; - if (x > 0) events[x-1] = 1; - if (x > 1) events[x-2] = 1; - newevent = 1; - break; - case DACB: - case DABC: - case DBAC: - case BDAC: - case BDCA: - case DBCA: - case DCBA: - case DCAB: - case CDAB: - case CDBA: - case CBDA: - case BCDA: - case CADB: - if (x < nwin-3) events[x+3] = 1; - if (x < nwin-2) events[x+2] = 1; - if (x < nwin-1) events[x+1] = 1; - if (x > 0) events[x-1] = 1; - if (x > 1) events[x-2] = 1; - if (x > 2) events[x-3] = 1; - newevent = 1; - break; - case BCAD: - case CBAD: - case CABD: - if (x < nwin-2) events[x+2] = 1; - if (x < nwin-1) events[x+1] = 1; - if (x > 1) events[x-2] = 1; - if (x > 2) events[x-3] = 1; - newevent = 1; - break; - case ACBD: - if (x < nwin-2) events[x+2] = 1; - if (x > 1) events[x-2] = 1; - newevent = 1; - break; - default: - FREE(events); - return(0); - } - events[x] = 0; -#ifdef DD_STATS - if (res == ABCD) { - (void) fprintf(table->out,"="); - } else { - (void) fprintf(table->out,"-"); - } - fflush(table->out); -#endif - } - } -#ifdef DD_STATS - if (newevent) { - (void) fprintf(table->out,"|"); - fflush(table->out); - } -#endif - } while (newevent); - - FREE(events); - - return(1); - -} /* end of ddWindowConv4 */ - diff --git a/src/bdd/cudd/cuddZddCount.c b/src/bdd/cudd/cuddZddCount.c deleted file mode 100644 index 6c6ec1df..00000000 --- a/src/bdd/cudd/cuddZddCount.c +++ /dev/null @@ -1,324 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddCount.c] - - PackageName [cudd] - - Synopsis [Procedures to count the number of minterms of a ZDD.] - - Description [External procedures included in this module: -
                -
              • Cudd_zddCount(); -
              • Cudd_zddCountDouble(); -
              - Internal procedures included in this module: -
                -
              - Static procedures included in this module: -
                -
              • cuddZddCountStep(); -
              • cuddZddCountDoubleStep(); -
              • st_zdd_count_dbl_free() -
              • st_zdd_countfree() -
              - ] - - SeeAlso [] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddCount.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int cuddZddCountStep ARGS((DdNode *P, st_table *table, DdNode *base, DdNode *empty)); -static double cuddZddCountDoubleStep ARGS((DdNode *P, st_table *table, DdNode *base, DdNode *empty)); -static enum st_retval st_zdd_countfree ARGS((char *key, char *value, char *arg)); -static enum st_retval st_zdd_count_dbl_free ARGS((char *key, char *value, char *arg)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms in a ZDD.] - - Description [Returns an integer representing the number of minterms - in a ZDD.] - - SideEffects [None] - - SeeAlso [Cudd_zddCountDouble] - -******************************************************************************/ -int -Cudd_zddCount( - DdManager * zdd, - DdNode * P) -{ - st_table *table; - int res; - DdNode *base, *empty; - - base = DD_ONE(zdd); - empty = DD_ZERO(zdd); - table = st_init_table(st_ptrcmp, st_ptrhash); - if (table == NULL) return(CUDD_OUT_OF_MEM); - res = cuddZddCountStep(P, table, base, empty); - if (res == CUDD_OUT_OF_MEM) { - zdd->errorCode = CUDD_MEMORY_OUT; - } - st_foreach(table, st_zdd_countfree, NIL(char)); - st_free_table(table); - - return(res); - -} /* end of Cudd_zddCount */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms of a ZDD.] - - Description [Counts the number of minterms of a ZDD. The result is - returned as a double. If the procedure runs out of memory, it - returns (double) CUDD_OUT_OF_MEM. This procedure is used in - Cudd_zddCountMinterm.] - - SideEffects [None] - - SeeAlso [Cudd_zddCountMinterm Cudd_zddCount] - -******************************************************************************/ -double -Cudd_zddCountDouble( - DdManager * zdd, - DdNode * P) -{ - st_table *table; - double res; - DdNode *base, *empty; - - base = DD_ONE(zdd); - empty = DD_ZERO(zdd); - table = st_init_table(st_ptrcmp, st_ptrhash); - if (table == NULL) return((double)CUDD_OUT_OF_MEM); - res = cuddZddCountDoubleStep(P, table, base, empty); - if (res == (double)CUDD_OUT_OF_MEM) { - zdd->errorCode = CUDD_MEMORY_OUT; - } - st_foreach(table, st_zdd_count_dbl_free, NIL(char)); - st_free_table(table); - - return(res); - -} /* end of Cudd_zddCountDouble */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddCount.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddCountStep( - DdNode * P, - st_table * table, - DdNode * base, - DdNode * empty) -{ - int res; - int *dummy; - - if (P == empty) - return(0); - if (P == base) - return(1); - - /* Check cache. */ - if (st_lookup(table, (char *)P, (char **)(&dummy))) { - res = *dummy; - return(res); - } - - res = cuddZddCountStep(cuddE(P), table, base, empty) + - cuddZddCountStep(cuddT(P), table, base, empty); - - dummy = ALLOC(int, 1); - if (dummy == NULL) { - return(CUDD_OUT_OF_MEM); - } - *dummy = res; - if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) { - FREE(dummy); - return(CUDD_OUT_OF_MEM); - } - - return(res); - -} /* end of cuddZddCountStep */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddCountDouble.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static double -cuddZddCountDoubleStep( - DdNode * P, - st_table * table, - DdNode * base, - DdNode * empty) -{ - double res; - double *dummy; - - if (P == empty) - return((double)0.0); - if (P == base) - return((double)1.0); - - /* Check cache */ - if (st_lookup(table, (char *)P, (char **)(&dummy))) { - res = *dummy; - return(res); - } - - res = cuddZddCountDoubleStep(cuddE(P), table, base, empty) + - cuddZddCountDoubleStep(cuddT(P), table, base, empty); - - dummy = ALLOC(double, 1); - if (dummy == NULL) { - return((double)CUDD_OUT_OF_MEM); - } - *dummy = res; - if (st_insert(table, (char *)P, (char *)dummy) == ST_OUT_OF_MEM) { - FREE(dummy); - return((double)CUDD_OUT_OF_MEM); - } - - return(res); - -} /* end of cuddZddCountDoubleStep */ - - -/**Function******************************************************************** - - Synopsis [Frees the memory associated with the computed table of - Cudd_zddCount.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static enum st_retval -st_zdd_countfree( - char * key, - char * value, - char * arg) -{ - int *d; - - d = (int *)value; - FREE(d); - return(ST_CONTINUE); - -} /* end of st_zdd_countfree */ - - -/**Function******************************************************************** - - Synopsis [Frees the memory associated with the computed table of - Cudd_zddCountDouble.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static enum st_retval -st_zdd_count_dbl_free( - char * key, - char * value, - char * arg) -{ - double *d; - - d = (double *)value; - FREE(d); - return(ST_CONTINUE); - -} /* end of st_zdd_count_dbl_free */ diff --git a/src/bdd/cudd/cuddZddFuncs.c b/src/bdd/cudd/cuddZddFuncs.c deleted file mode 100644 index 9dc27a95..00000000 --- a/src/bdd/cudd/cuddZddFuncs.c +++ /dev/null @@ -1,1603 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddFuncs.c] - - PackageName [cudd] - - Synopsis [Functions to manipulate covers represented as ZDDs.] - - Description [External procedures included in this module: -
                -
              • Cudd_zddProduct(); -
              • Cudd_zddUnateProduct(); -
              • Cudd_zddWeakDiv(); -
              • Cudd_zddWeakDivF(); -
              • Cudd_zddDivide(); -
              • Cudd_zddDivideF(); -
              • Cudd_zddComplement(); -
              - Internal procedures included in this module: -
                -
              • cuddZddProduct(); -
              • cuddZddUnateProduct(); -
              • cuddZddWeakDiv(); -
              • cuddZddWeakDivF(); -
              • cuddZddDivide(); -
              • cuddZddDivideF(); -
              • cuddZddGetCofactors3() -
              • cuddZddGetCofactors2() -
              • cuddZddComplement(); -
              • cuddZddGetPosVarIndex(); -
              • cuddZddGetNegVarIndex(); -
              • cuddZddGetPosVarLevel(); -
              • cuddZddGetNegVarLevel(); -
              - Static procedures included in this module: -
                -
              - ] - - SeeAlso [] - - Author [In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddFuncs.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the product of two covers represented by ZDDs.] - - Description [Computes the product of two covers represented by - ZDDs. The result is also a ZDD. Returns a pointer to the result if - successful; NULL otherwise. The covers on which Cudd_zddProduct - operates use two ZDD variables for each function variable (one ZDD - variable for each literal of the variable). Those two ZDD variables - should be adjacent in the order.] - - SideEffects [None] - - SeeAlso [Cudd_zddUnateProduct] - -******************************************************************************/ -DdNode * -Cudd_zddProduct( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddProduct(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddProduct */ - - -/**Function******************************************************************** - - Synopsis [Computes the product of two unate covers.] - - Description [Computes the product of two unate covers represented as - ZDDs. Unate covers use one ZDD variable for each BDD - variable. Returns a pointer to the result if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddProduct] - -******************************************************************************/ -DdNode * -Cudd_zddUnateProduct( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddUnateProduct(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddUnateProduct */ - - -/**Function******************************************************************** - - Synopsis [Applies weak division to two covers.] - - Description [Applies weak division to two ZDDs representing two - covers. Returns a pointer to the ZDD representing the result if - successful; NULL otherwise. The result of weak division depends on - the variable order. The covers on which Cudd_zddWeakDiv operates use - two ZDD variables for each function variable (one ZDD variable for - each literal of the variable). Those two ZDD variables should be - adjacent in the order.] - - SideEffects [None] - - SeeAlso [Cudd_zddDivide] - -******************************************************************************/ -DdNode * -Cudd_zddWeakDiv( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddWeakDiv(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddWeakDiv */ - - -/**Function******************************************************************** - - Synopsis [Computes the quotient of two unate covers.] - - Description [Computes the quotient of two unate covers represented - by ZDDs. Unate covers use one ZDD variable for each BDD - variable. Returns a pointer to the resulting ZDD if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddWeakDiv] - -******************************************************************************/ -DdNode * -Cudd_zddDivide( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddDivide(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddDivide */ - - -/**Function******************************************************************** - - Synopsis [Modified version of Cudd_zddWeakDiv.] - - Description [Modified version of Cudd_zddWeakDiv. This function may - disappear in future releases.] - - SideEffects [None] - - SeeAlso [Cudd_zddWeakDiv] - -******************************************************************************/ -DdNode * -Cudd_zddWeakDivF( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddWeakDivF(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddWeakDivF */ - - -/**Function******************************************************************** - - Synopsis [Modified version of Cudd_zddDivide.] - - Description [Modified version of Cudd_zddDivide. This function may - disappear in future releases.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddDivideF( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddDivideF(dd, f, g); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddDivideF */ - - -/**Function******************************************************************** - - Synopsis [Computes a complement cover for a ZDD node.] - - Description [Computes a complement cover for a ZDD node. For lack of a - better method, we first extract the function BDD from the ZDD cover, - then make the complement of the ZDD cover from the complement of the - BDD node by using ISOP. Returns a pointer to the resulting cover if - successful; NULL otherwise. The result depends on current variable - order.] - - SideEffects [The result depends on current variable order.] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddComplement( - DdManager *dd, - DdNode *node) -{ - DdNode *b, *isop, *zdd_I; - - /* Check cache */ - zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); - if (zdd_I) - return(zdd_I); - - b = Cudd_MakeBddFromZddCover(dd, node); - if (!b) - return(NULL); - Cudd_Ref(b); - isop = Cudd_zddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); - if (!isop) { - Cudd_RecursiveDeref(dd, b); - return(NULL); - } - Cudd_Ref(isop); - Cudd_Ref(zdd_I); - Cudd_RecursiveDeref(dd, b); - Cudd_RecursiveDeref(dd, isop); - - cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); - Cudd_Deref(zdd_I); - return(zdd_I); -} /* end of Cudd_zddComplement */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddProduct.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddProduct] - -******************************************************************************/ -DdNode * -cuddZddProduct( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v, top_f, top_g; - DdNode *tmp, *term1, *term2, *term3; - DdNode *f0, *f1, *fd, *g0, *g1, *gd; - DdNode *R0, *R1, *Rd, *N0, *N1; - DdNode *r; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - int flag; - int pv, nv; - - statLine(dd); - if (f == zero || g == zero) - return(zero); - if (f == one) - return(g); - if (g == one) - return(f); - - top_f = dd->permZ[f->index]; - top_g = dd->permZ[g->index]; - - if (top_f > top_g) - return(cuddZddProduct(dd, g, f)); - - /* Check cache */ - r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g); - if (r) - return(r); - - v = f->index; /* either yi or zi */ - flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - Cudd_Ref(fd); - flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - Cudd_Ref(gd); - pv = cuddZddGetPosVarIndex(dd, v); - nv = cuddZddGetNegVarIndex(dd, v); - - Rd = cuddZddProduct(dd, fd, gd); - if (Rd == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(Rd); - - term1 = cuddZddProduct(dd, f0, g0); - if (term1 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - return(NULL); - } - Cudd_Ref(term1); - term2 = cuddZddProduct(dd, f0, gd); - if (term2 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - Cudd_RecursiveDerefZdd(dd, term1); - return(NULL); - } - Cudd_Ref(term2); - term3 = cuddZddProduct(dd, fd, g0); - if (term3 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - return(NULL); - } - Cudd_Ref(term3); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g0); - tmp = cuddZddUnion(dd, term1, term2); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - Cudd_RecursiveDerefZdd(dd, term3); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - R0 = cuddZddUnion(dd, tmp, term3); - if (R0 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - Cudd_RecursiveDerefZdd(dd, term3); - Cudd_RecursiveDerefZdd(dd, tmp); - return(NULL); - } - Cudd_Ref(R0); - Cudd_RecursiveDerefZdd(dd, tmp); - Cudd_RecursiveDerefZdd(dd, term3); - N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */ - if (N0 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, Rd); - Cudd_RecursiveDerefZdd(dd, R0); - return(NULL); - } - Cudd_Ref(N0); - Cudd_RecursiveDerefZdd(dd, R0); - Cudd_RecursiveDerefZdd(dd, Rd); - - term1 = cuddZddProduct(dd, f1, g1); - if (term1 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, N0); - return(NULL); - } - Cudd_Ref(term1); - term2 = cuddZddProduct(dd, f1, gd); - if (term2 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, N0); - Cudd_RecursiveDerefZdd(dd, term1); - return(NULL); - } - Cudd_Ref(term2); - term3 = cuddZddProduct(dd, fd, g1); - if (term3 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, gd); - Cudd_RecursiveDerefZdd(dd, N0); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - return(NULL); - } - Cudd_Ref(term3); - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - tmp = cuddZddUnion(dd, term1, term2); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, N0); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - Cudd_RecursiveDerefZdd(dd, term3); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - R1 = cuddZddUnion(dd, tmp, term3); - if (R1 == NULL) { - Cudd_RecursiveDerefZdd(dd, N0); - Cudd_RecursiveDerefZdd(dd, term3); - Cudd_RecursiveDerefZdd(dd, tmp); - return(NULL); - } - Cudd_Ref(R1); - Cudd_RecursiveDerefZdd(dd, tmp); - Cudd_RecursiveDerefZdd(dd, term3); - N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */ - if (N1 == NULL) { - Cudd_RecursiveDerefZdd(dd, N0); - Cudd_RecursiveDerefZdd(dd, R1); - return(NULL); - } - Cudd_Ref(N1); - Cudd_RecursiveDerefZdd(dd, R1); - Cudd_RecursiveDerefZdd(dd, N0); - - cuddCacheInsert2(dd, cuddZddProduct, f, g, N1); - Cudd_Deref(N1); - return(N1); - -} /* end of cuddZddProduct */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddUnateProduct.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddUnateProduct] - -******************************************************************************/ -DdNode * -cuddZddUnateProduct( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v, top_f, top_g; - DdNode *term1, *term2, *term3, *term4; - DdNode *sum1, *sum2; - DdNode *f0, *f1, *g0, *g1; - DdNode *r; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - int flag; - - statLine(dd); - if (f == zero || g == zero) - return(zero); - if (f == one) - return(g); - if (g == one) - return(f); - - top_f = dd->permZ[f->index]; - top_g = dd->permZ[g->index]; - - if (top_f > top_g) - return(cuddZddUnateProduct(dd, g, f)); - - /* Check cache */ - r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g); - if (r) - return(r); - - v = f->index; /* either yi or zi */ - flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - - term1 = cuddZddUnateProduct(dd, f1, g1); - if (term1 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - return(NULL); - } - Cudd_Ref(term1); - term2 = cuddZddUnateProduct(dd, f1, g0); - if (term2 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, term1); - return(NULL); - } - Cudd_Ref(term2); - term3 = cuddZddUnateProduct(dd, f0, g1); - if (term3 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - return(NULL); - } - Cudd_Ref(term3); - term4 = cuddZddUnateProduct(dd, f0, g0); - if (term4 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - Cudd_RecursiveDerefZdd(dd, term3); - return(NULL); - } - Cudd_Ref(term4); - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - sum1 = cuddZddUnion(dd, term1, term2); - if (sum1 == NULL) { - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - Cudd_RecursiveDerefZdd(dd, term3); - Cudd_RecursiveDerefZdd(dd, term4); - return(NULL); - } - Cudd_Ref(sum1); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term2); - sum2 = cuddZddUnion(dd, sum1, term3); - if (sum2 == NULL) { - Cudd_RecursiveDerefZdd(dd, term3); - Cudd_RecursiveDerefZdd(dd, term4); - Cudd_RecursiveDerefZdd(dd, sum1); - return(NULL); - } - Cudd_Ref(sum2); - Cudd_RecursiveDerefZdd(dd, sum1); - Cudd_RecursiveDerefZdd(dd, term3); - r = cuddZddGetNode(dd, v, sum2, term4); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, term4); - Cudd_RecursiveDerefZdd(dd, sum2); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDerefZdd(dd, sum2); - Cudd_RecursiveDerefZdd(dd, term4); - - cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r); - Cudd_Deref(r); - return(r); - -} /* end of cuddZddUnateProduct */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddWeakDiv.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddWeakDiv] - -******************************************************************************/ -DdNode * -cuddZddWeakDiv( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - DdNode *f0, *f1, *fd, *g0, *g1, *gd; - DdNode *q, *tmp; - DdNode *r; - int flag; - - statLine(dd); - if (g == one) - return(f); - if (f == zero || f == one) - return(zero); - if (f == g) - return(one); - - /* Check cache. */ - r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g); - if (r) - return(r); - - v = g->index; - - flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - Cudd_Ref(fd); - flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - Cudd_Ref(gd); - - q = g; - - if (g0 != zero) { - q = cuddZddWeakDiv(dd, f0, g0); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(q); - } - else - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g0); - - if (q == zero) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); - Cudd_Deref(q); - return(zero); - } - - if (g1 != zero) { - Cudd_RecursiveDerefZdd(dd, q); - tmp = cuddZddWeakDiv(dd, f1, g1); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - if (q == g) - q = tmp; - else { - q = cuddZddIntersect(dd, q, tmp); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - } - else { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - } - - if (q == zero) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); - Cudd_Deref(q); - return(zero); - } - - if (gd != zero) { - Cudd_RecursiveDerefZdd(dd, q); - tmp = cuddZddWeakDiv(dd, fd, gd); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - if (q == g) - q = tmp; - else { - q = cuddZddIntersect(dd, q, tmp); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, tmp); - return(NULL); - } - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - } - else { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - } - - cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q); - Cudd_Deref(q); - return(q); - -} /* end of cuddZddWeakDiv */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddWeakDivF.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddWeakDivF] - -******************************************************************************/ -DdNode * -cuddZddWeakDivF( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v, top_f, top_g, vf, vg; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - DdNode *f0, *f1, *fd, *g0, *g1, *gd; - DdNode *q, *tmp; - DdNode *r; - DdNode *term1, *term0, *termd; - int flag; - int pv, nv; - - statLine(dd); - if (g == one) - return(f); - if (f == zero || f == one) - return(zero); - if (f == g) - return(one); - - /* Check cache. */ - r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g); - if (r) - return(r); - - top_f = dd->permZ[f->index]; - top_g = dd->permZ[g->index]; - vf = top_f >> 1; - vg = top_g >> 1; - v = ddMin(top_f, top_g); - - if (v == top_f && vf < vg) { - v = f->index; - flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - Cudd_Ref(fd); - - pv = cuddZddGetPosVarIndex(dd, v); - nv = cuddZddGetNegVarIndex(dd, v); - - term1 = cuddZddWeakDivF(dd, f1, g); - if (term1 == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - return(NULL); - } - Cudd_Ref(term1); - Cudd_RecursiveDerefZdd(dd, f1); - term0 = cuddZddWeakDivF(dd, f0, g); - if (term0 == NULL) { - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, term1); - return(NULL); - } - Cudd_Ref(term0); - Cudd_RecursiveDerefZdd(dd, f0); - termd = cuddZddWeakDivF(dd, fd, g); - if (termd == NULL) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term0); - return(NULL); - } - Cudd_Ref(termd); - Cudd_RecursiveDerefZdd(dd, fd); - - tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */ - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, term0); - Cudd_RecursiveDerefZdd(dd, termd); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, term0); - Cudd_RecursiveDerefZdd(dd, termd); - q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */ - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, tmp); - return(NULL); - } - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, term1); - Cudd_RecursiveDerefZdd(dd, tmp); - - cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); - Cudd_Deref(q); - return(q); - } - - if (v == top_f) - v = f->index; - else - v = g->index; - - flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - Cudd_Ref(fd); - flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - Cudd_Ref(gd); - - q = g; - - if (g0 != zero) { - q = cuddZddWeakDivF(dd, f0, g0); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(q); - } - else - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g0); - - if (q == zero) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); - Cudd_Deref(q); - return(zero); - } - - if (g1 != zero) { - Cudd_RecursiveDerefZdd(dd, q); - tmp = cuddZddWeakDivF(dd, f1, g1); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - if (q == g) - q = tmp; - else { - q = cuddZddIntersect(dd, q, tmp); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - } - else { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, g1); - } - - if (q == zero) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); - Cudd_Deref(q); - return(zero); - } - - if (gd != zero) { - Cudd_RecursiveDerefZdd(dd, q); - tmp = cuddZddWeakDivF(dd, fd, gd); - if (tmp == NULL) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - return(NULL); - } - Cudd_Ref(tmp); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - if (q == g) - q = tmp; - else { - q = cuddZddIntersect(dd, q, tmp); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, tmp); - return(NULL); - } - Cudd_Ref(q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - } - else { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDerefZdd(dd, gd); - } - - cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); - Cudd_Deref(q); - return(q); - -} /* end of cuddZddWeakDivF */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddDivide.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddDivide] - -******************************************************************************/ -DdNode * -cuddZddDivide( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - DdNode *f0, *f1, *g0, *g1; - DdNode *q, *r, *tmp; - int flag; - - statLine(dd); - if (g == one) - return(f); - if (f == zero || f == one) - return(zero); - if (f == g) - return(one); - - /* Check cache. */ - r = cuddCacheLookup2Zdd(dd, cuddZddDivide, f, g); - if (r) - return(r); - - v = g->index; - - flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */ - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - - r = cuddZddDivide(dd, f1, g1); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - return(NULL); - } - Cudd_Ref(r); - - if (r != zero && g0 != zero) { - tmp = r; - q = cuddZddDivide(dd, f0, g0); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - return(NULL); - } - Cudd_Ref(q); - r = cuddZddIntersect(dd, r, q); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, q); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDerefZdd(dd, q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - - cuddCacheInsert2(dd, cuddZddDivide, f, g, r); - Cudd_Deref(r); - return(r); - -} /* end of cuddZddDivide */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddDivideF.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddDivideF] - -******************************************************************************/ -DdNode * -cuddZddDivideF( - DdManager * dd, - DdNode * f, - DdNode * g) -{ - int v; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - DdNode *f0, *f1, *g0, *g1; - DdNode *q, *r, *tmp; - int flag; - - statLine(dd); - if (g == one) - return(f); - if (f == zero || f == one) - return(zero); - if (f == g) - return(one); - - /* Check cache. */ - r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g); - if (r) - return(r); - - v = g->index; - - flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); - if (flag == 1) - return(NULL); - Cudd_Ref(f1); - Cudd_Ref(f0); - flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); /* g1 != zero */ - if (flag == 1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - return(NULL); - } - Cudd_Ref(g1); - Cudd_Ref(g0); - - r = cuddZddDivideF(dd, f1, g1); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - return(NULL); - } - Cudd_Ref(r); - - if (r != zero && g0 != zero) { - tmp = r; - q = cuddZddDivideF(dd, f0, g0); - if (q == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - return(NULL); - } - Cudd_Ref(q); - r = cuddZddIntersect(dd, r, q); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - Cudd_RecursiveDerefZdd(dd, q); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDerefZdd(dd, q); - Cudd_RecursiveDerefZdd(dd, tmp); - } - - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, g1); - Cudd_RecursiveDerefZdd(dd, g0); - - cuddCacheInsert2(dd, cuddZddDivideF, f, g, r); - Cudd_Deref(r); - return(r); - -} /* end of cuddZddDivideF */ - - -/**Function******************************************************************** - - Synopsis [Computes the three-way decomposition of f w.r.t. v.] - - Description [Computes the three-way decomposition of function f (represented - by a ZDD) wit respect to variable v.] - - SideEffects [The results are returned in f1, f0, and fd.] - - SeeAlso [cuddZddGetCofactors2] - -******************************************************************************/ -int -cuddZddGetCofactors3( - DdManager * dd, - DdNode * f, - int v, - DdNode ** f1, - DdNode ** f0, - DdNode ** fd) -{ - DdNode *pc, *nc; - DdNode *zero = DD_ZERO(dd); - int top, hv, ht, pv, nv; - int level; - - top = dd->permZ[f->index]; - level = dd->permZ[v]; - hv = level >> 1; - ht = top >> 1; - - if (hv < ht) { - *f1 = zero; - *f0 = zero; - *fd = f; - } - else { - pv = cuddZddGetPosVarIndex(dd, v); - nv = cuddZddGetNegVarIndex(dd, v); - - /* not to create intermediate ZDD node */ - if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) { - pc = cuddZddSubset1(dd, f, pv); - if (pc == NULL) - return(1); - Cudd_Ref(pc); - nc = cuddZddSubset0(dd, f, pv); - if (nc == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - return(1); - } - Cudd_Ref(nc); - - *f1 = cuddZddSubset0(dd, pc, nv); - if (*f1 == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - return(1); - } - Cudd_Ref(*f1); - *f0 = cuddZddSubset1(dd, nc, nv); - if (*f0 == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - Cudd_RecursiveDerefZdd(dd, *f1); - return(1); - } - Cudd_Ref(*f0); - - *fd = cuddZddSubset0(dd, nc, nv); - if (*fd == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - Cudd_RecursiveDerefZdd(dd, *f1); - Cudd_RecursiveDerefZdd(dd, *f0); - return(1); - } - Cudd_Ref(*fd); - } else { - pc = cuddZddSubset1(dd, f, nv); - if (pc == NULL) - return(1); - Cudd_Ref(pc); - nc = cuddZddSubset0(dd, f, nv); - if (nc == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - return(1); - } - Cudd_Ref(nc); - - *f0 = cuddZddSubset0(dd, pc, pv); - if (*f0 == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - return(1); - } - Cudd_Ref(*f0); - *f1 = cuddZddSubset1(dd, nc, pv); - if (*f1 == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - Cudd_RecursiveDerefZdd(dd, *f1); - return(1); - } - Cudd_Ref(*f1); - - *fd = cuddZddSubset0(dd, nc, pv); - if (*fd == NULL) { - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - Cudd_RecursiveDerefZdd(dd, *f1); - Cudd_RecursiveDerefZdd(dd, *f0); - return(1); - } - Cudd_Ref(*fd); - } - - Cudd_RecursiveDerefZdd(dd, pc); - Cudd_RecursiveDerefZdd(dd, nc); - Cudd_Deref(*f1); - Cudd_Deref(*f0); - Cudd_Deref(*fd); - } - return(0); - -} /* end of cuddZddGetCofactors3 */ - - -/**Function******************************************************************** - - Synopsis [Computes the two-way decomposition of f w.r.t. v.] - - Description [] - - SideEffects [The results are returned in f1 and f0.] - - SeeAlso [cuddZddGetCofactors3] - -******************************************************************************/ -int -cuddZddGetCofactors2( - DdManager * dd, - DdNode * f, - int v, - DdNode ** f1, - DdNode ** f0) -{ - *f1 = cuddZddSubset1(dd, f, v); - if (*f1 == NULL) - return(1); - *f0 = cuddZddSubset0(dd, f, v); - if (*f0 == NULL) { - Cudd_RecursiveDerefZdd(dd, *f1); - return(1); - } - return(0); - -} /* end of cuddZddGetCofactors2 */ - - -/**Function******************************************************************** - - Synopsis [Computes a complement of a ZDD node.] - - Description [Computes the complement of a ZDD node. So far, since we - couldn't find a direct way to get the complement of a ZDD cover, we first - convert a ZDD cover to a BDD, then make the complement of the ZDD cover - from the complement of the BDD node by using ISOP.] - - SideEffects [The result depends on current variable order.] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddComplement( - DdManager * dd, - DdNode *node) -{ - DdNode *b, *isop, *zdd_I; - - /* Check cache */ - zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); - if (zdd_I) - return(zdd_I); - - b = cuddMakeBddFromZddCover(dd, node); - if (!b) - return(NULL); - cuddRef(b); - isop = cuddZddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); - if (!isop) { - Cudd_RecursiveDeref(dd, b); - return(NULL); - } - cuddRef(isop); - cuddRef(zdd_I); - Cudd_RecursiveDeref(dd, b); - Cudd_RecursiveDeref(dd, isop); - - cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); - cuddDeref(zdd_I); - return(zdd_I); -} /* end of cuddZddComplement */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of positive ZDD variable.] - - Description [Returns the index of positive ZDD variable.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddGetPosVarIndex( - DdManager * dd, - int index) -{ - int pv = (index >> 1) << 1; - return(pv); -} /* end of cuddZddGetPosVarIndex */ - - -/**Function******************************************************************** - - Synopsis [Returns the index of negative ZDD variable.] - - Description [Returns the index of negative ZDD variable.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddGetNegVarIndex( - DdManager * dd, - int index) -{ - int nv = index | 0x1; - return(nv); -} /* end of cuddZddGetPosVarIndex */ - - -/**Function******************************************************************** - - Synopsis [Returns the level of positive ZDD variable.] - - Description [Returns the level of positive ZDD variable.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddGetPosVarLevel( - DdManager * dd, - int index) -{ - int pv = cuddZddGetPosVarIndex(dd, index); - return(dd->permZ[pv]); -} /* end of cuddZddGetPosVarLevel */ - - -/**Function******************************************************************** - - Synopsis [Returns the level of negative ZDD variable.] - - Description [Returns the level of negative ZDD variable.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddGetNegVarLevel( - DdManager * dd, - int index) -{ - int nv = cuddZddGetNegVarIndex(dd, index); - return(dd->permZ[nv]); -} /* end of cuddZddGetNegVarLevel */ diff --git a/src/bdd/cudd/cuddZddGroup.c b/src/bdd/cudd/cuddZddGroup.c deleted file mode 100644 index 621fa43f..00000000 --- a/src/bdd/cudd/cuddZddGroup.c +++ /dev/null @@ -1,1317 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddGroup.c] - - PackageName [cudd] - - Synopsis [Functions for ZDD group sifting.] - - Description [External procedures included in this file: -
                -
              • Cudd_MakeZddTreeNode() -
              - Internal procedures included in this file: -
                -
              • cuddZddTreeSifting() -
              - Static procedures included in this module: -
                -
              • zddTreeSiftingAux() -
              • zddCountInternalMtrNodes() -
              • zddReorderChildren() -
              • zddFindNodeHiLo() -
              • zddUniqueCompareGroup() -
              • zddGroupSifting() -
              • zddGroupSiftingAux() -
              • zddGroupSiftingUp() -
              • zddGroupSiftingDown() -
              • zddGroupMove() -
              • zddGroupMoveBackward() -
              • zddGroupSiftingBackward() -
              • zddMergeGroups() -
              ] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -static int *entry; -extern int zddTotalNumberSwapping; -#ifdef DD_STATS -static int extsymmcalls; -static int extsymm; -static int secdiffcalls; -static int secdiff; -static int secdiffmisfire; -#endif -#ifdef DD_DEBUG -static int pr = 0; /* flag to enable printing while debugging */ - /* by depositing a 1 into it */ -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int zddTreeSiftingAux ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); -#ifdef DD_STATS -static int zddCountInternalMtrNodes ARGS((DdManager *table, MtrNode *treenode)); -#endif -static int zddReorderChildren ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method)); -static void zddFindNodeHiLo ARGS((DdManager *table, MtrNode *treenode, int *lower, int *upper)); -static int zddUniqueCompareGroup ARGS((int *ptrX, int *ptrY)); -static int zddGroupSifting ARGS((DdManager *table, int lower, int upper)); -static int zddGroupSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static int zddGroupSiftingUp ARGS((DdManager *table, int y, int xLow, Move **moves)); -static int zddGroupSiftingDown ARGS((DdManager *table, int x, int xHigh, Move **moves)); -static int zddGroupMove ARGS((DdManager *table, int x, int y, Move **moves)); -static int zddGroupMoveBackward ARGS((DdManager *table, int x, int y)); -static int zddGroupSiftingBackward ARGS((DdManager *table, Move *moves, int size)); -static void zddMergeGroups ARGS((DdManager *table, MtrNode *treenode, int low, int high)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Creates a new ZDD variable group.] - - Description [Creates a new ZDD variable group. The group starts at - variable and contains size variables. The parameter low is the index - of the first variable. If the variable already exists, its current - position in the order is known to the manager. If the variable does - not exist yet, the position is assumed to be the same as the index. - The group tree is created if it does not exist yet. - Returns a pointer to the group if successful; NULL otherwise.] - - SideEffects [The ZDD variable tree is changed.] - - SeeAlso [Cudd_MakeTreeNode] - -******************************************************************************/ -MtrNode * -Cudd_MakeZddTreeNode( - DdManager * dd /* manager */, - unsigned int low /* index of the first group variable */, - unsigned int size /* number of variables in the group */, - unsigned int type /* MTR_DEFAULT or MTR_FIXED */) -{ - MtrNode *group; - MtrNode *tree; - unsigned int level; - - /* If the variable does not exist yet, the position is assumed to be - ** the same as the index. Therefore, applications that rely on - ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new - ** variables have to create the variables before they group them. - */ - level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low; - - if (level + size - 1> (int) MTR_MAXHIGH) - return(NULL); - - /* If the tree does not exist yet, create it. */ - tree = dd->treeZ; - if (tree == NULL) { - dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ); - if (tree == NULL) - return(NULL); - tree->index = dd->invpermZ[0]; - } - - /* Extend the upper bound of the tree if necessary. This allows the - ** application to create groups even before the variables are created. - */ - tree->size = ddMax(tree->size, level + size); - - /* Create the group. */ - group = Mtr_MakeGroup(tree, level, size, type); - if (group == NULL) - return(NULL); - - /* Initialize the index field to the index of the variable currently - ** in position low. This field will be updated by the reordering - ** procedure to provide a handle to the group once it has been moved. - */ - group->index = (MtrHalfWord) low; - - return(group); - -} /* end of Cudd_MakeZddTreeNode */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Tree sifting algorithm for ZDDs.] - - Description [Tree sifting algorithm for ZDDs. Assumes that a tree - representing a group hierarchy is passed as a parameter. It then - reorders each group in postorder fashion by calling - zddTreeSiftingAux. Assumes that no dead nodes are present. Returns - 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -int -cuddZddTreeSifting( - DdManager * table /* DD table */, - Cudd_ReorderingType method /* reordering method for the groups of leaves */) -{ - int i; - int nvars; - int result; - int tempTree; - - /* If no tree is provided we create a temporary one in which all - ** variables are in a single group. After reordering this tree is - ** destroyed. - */ - tempTree = table->treeZ == NULL; - if (tempTree) { - table->treeZ = Mtr_InitGroupTree(0,table->sizeZ); - table->treeZ->index = table->invpermZ[0]; - } - nvars = table->sizeZ; - -#ifdef DD_DEBUG - if (pr > 0 && !tempTree) - (void) fprintf(table->out,"cuddZddTreeSifting:"); - Mtr_PrintGroups(table->treeZ,pr <= 0); -#endif -#if 0 - /* Debugging code. */ - if (table->tree && table->treeZ) { - (void) fprintf(table->out,"\n"); - Mtr_PrintGroups(table->tree, 0); - cuddPrintVarGroups(table,table->tree,0,0); - for (i = 0; i < table->size; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->invperm[i]); - } - (void) fprintf(table->out,"\n"); - for (i = 0; i < table->size; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->perm[i]); - } - (void) fprintf(table->out,"\n\n"); - Mtr_PrintGroups(table->treeZ,0); - cuddPrintVarGroups(table,table->treeZ,1,0); - for (i = 0; i < table->sizeZ; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->invpermZ[i]); - } - (void) fprintf(table->out,"\n"); - for (i = 0; i < table->sizeZ; i++) { - (void) fprintf(table->out,"%s%d", - (i == 0) ? "" : ",", table->permZ[i]); - } - (void) fprintf(table->out,"\n"); - } - /* End of debugging code. */ -#endif -#ifdef DD_STATS - extsymmcalls = 0; - extsymm = 0; - secdiffcalls = 0; - secdiff = 0; - secdiffmisfire = 0; - - (void) fprintf(table->out,"\n"); - if (!tempTree) - (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n", - zddCountInternalMtrNodes(table,table->treeZ)); -#endif - - /* Initialize the group of each subtable to itself. Initially - ** there are no groups. Groups are created according to the tree - ** structure in postorder fashion. - */ - for (i = 0; i < nvars; i++) - table->subtableZ[i].next = i; - - /* Reorder. */ - result = zddTreeSiftingAux(table, table->treeZ, method); - -#ifdef DD_STATS /* print stats */ - if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && - (table->groupcheck == CUDD_GROUP_CHECK7 || - table->groupcheck == CUDD_GROUP_CHECK5)) { - (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls); - (void) fprintf(table->out,"extsymm = %d",extsymm); - } - if (!tempTree && method == CUDD_REORDER_GROUP_SIFT && - table->groupcheck == CUDD_GROUP_CHECK7) { - (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls); - (void) fprintf(table->out,"secdiff = %d\n",secdiff); - (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire); - } -#endif - - if (tempTree) - Cudd_FreeZddTree(table); - return(result); - -} /* end of cuddZddTreeSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Visits the group tree and reorders each group.] - - Description [Recursively visits the group tree and reorders each - group in postorder fashion. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddTreeSiftingAux( - DdManager * table, - MtrNode * treenode, - Cudd_ReorderingType method) -{ - MtrNode *auxnode; - int res; - -#ifdef DD_DEBUG - Mtr_PrintGroups(treenode,1); -#endif - - auxnode = treenode; - while (auxnode != NULL) { - if (auxnode->child != NULL) { - if (!zddTreeSiftingAux(table, auxnode->child, method)) - return(0); - res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT); - if (res == 0) - return(0); - } else if (auxnode->size > 1) { - if (!zddReorderChildren(table, auxnode, method)) - return(0); - } - auxnode = auxnode->younger; - } - - return(1); - -} /* end of zddTreeSiftingAux */ - - -#ifdef DD_STATS -/**Function******************************************************************** - - Synopsis [Counts the number of internal nodes of the group tree.] - - Description [Counts the number of internal nodes of the group tree. - Returns the count.] - - SideEffects [None] - -******************************************************************************/ -static int -zddCountInternalMtrNodes( - DdManager * table, - MtrNode * treenode) -{ - MtrNode *auxnode; - int count,nodeCount; - - - nodeCount = 0; - auxnode = treenode; - while (auxnode != NULL) { - if (!(MTR_TEST(auxnode,MTR_TERMINAL))) { - nodeCount++; - count = zddCountInternalMtrNodes(table,auxnode->child); - nodeCount += count; - } - auxnode = auxnode->younger; - } - - return(nodeCount); - -} /* end of zddCountInternalMtrNodes */ -#endif - - -/**Function******************************************************************** - - Synopsis [Reorders the children of a group tree node according to - the options.] - - Description [Reorders the children of a group tree node according to - the options. After reordering puts all the variables in the group - and/or its descendents in a single group. This allows hierarchical - reordering. If the variables in the group do not exist yet, simply - does nothing. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddReorderChildren( - DdManager * table, - MtrNode * treenode, - Cudd_ReorderingType method) -{ - int lower; - int upper; - int result; - unsigned int initialSize; - - zddFindNodeHiLo(table,treenode,&lower,&upper); - /* If upper == -1 these variables do not exist yet. */ - if (upper == -1) - return(1); - - if (treenode->flags == MTR_FIXED) { - result = 1; - } else { -#ifdef DD_STATS - (void) fprintf(table->out," "); -#endif - switch (method) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - result = cuddZddSwapping(table,lower,upper,method); - break; - case CUDD_REORDER_SIFT: - result = cuddZddSifting(table,lower,upper); - break; - case CUDD_REORDER_SIFT_CONVERGE: - do { - initialSize = table->keysZ; - result = cuddZddSifting(table,lower,upper); - if (initialSize <= table->keysZ) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - case CUDD_REORDER_SYMM_SIFT: - result = cuddZddSymmSifting(table,lower,upper); - break; - case CUDD_REORDER_SYMM_SIFT_CONV: - result = cuddZddSymmSiftingConv(table,lower,upper); - break; - case CUDD_REORDER_GROUP_SIFT: - result = zddGroupSifting(table,lower,upper); - break; - case CUDD_REORDER_LINEAR: - result = cuddZddLinearSifting(table,lower,upper); - break; - case CUDD_REORDER_LINEAR_CONVERGE: - do { - initialSize = table->keysZ; - result = cuddZddLinearSifting(table,lower,upper); - if (initialSize <= table->keysZ) - break; -#ifdef DD_STATS - else - (void) fprintf(table->out,"\n"); -#endif - } while (result != 0); - break; - default: - return(0); - } - } - - /* Create a single group for all the variables that were sifted, - ** so that they will be treated as a single block by successive - ** invocations of zddGroupSifting. - */ - zddMergeGroups(table,treenode,lower,upper); - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:"); -#endif - - return(result); - -} /* end of zddReorderChildren */ - - -/**Function******************************************************************** - - Synopsis [Finds the lower and upper bounds of the group represented - by treenode.] - - Description [Finds the lower and upper bounds of the group represented - by treenode. The high and low fields of treenode are indices. From - those we need to derive the current positions, and find maximum and - minimum.] - - SideEffects [The bounds are returned as side effects.] - - SeeAlso [] - -******************************************************************************/ -static void -zddFindNodeHiLo( - DdManager * table, - MtrNode * treenode, - int * lower, - int * upper) -{ - int low; - int high; - - /* Check whether no variables in this group already exist. - ** If so, return immediately. The calling procedure will know from - ** the values of upper that no reordering is needed. - */ - if ((int) treenode->low >= table->sizeZ) { - *lower = table->sizeZ; - *upper = -1; - return; - } - - *lower = low = (unsigned int) table->permZ[treenode->index]; - high = (int) (low + treenode->size - 1); - - if (high >= table->sizeZ) { - /* This is the case of a partially existing group. The aim is to - ** reorder as many variables as safely possible. If the tree - ** node is terminal, we just reorder the subset of the group - ** that is currently in existence. If the group has - ** subgroups, then we only reorder those subgroups that are - ** fully instantiated. This way we avoid breaking up a group. - */ - MtrNode *auxnode = treenode->child; - if (auxnode == NULL) { - *upper = (unsigned int) table->sizeZ - 1; - } else { - /* Search the subgroup that strands the table->sizeZ line. - ** If the first group starts at 0 and goes past table->sizeZ - ** upper will get -1, thus correctly signaling that no reordering - ** should take place. - */ - while (auxnode != NULL) { - int thisLower = table->permZ[auxnode->low]; - int thisUpper = thisLower + auxnode->size - 1; - if (thisUpper >= table->sizeZ && thisLower < table->sizeZ) - *upper = (unsigned int) thisLower - 1; - auxnode = auxnode->younger; - } - } - } else { - /* Normal case: All the variables of the group exist. */ - *upper = (unsigned int) high; - } - -#ifdef DD_DEBUG - /* Make sure that all variables in group are contiguous. */ - assert(treenode->size >= *upper - *lower + 1); -#endif - - return; - -} /* end of zddFindNodeHiLo */ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the variables - according to the number of keys in the subtables. Returns the - difference in number of keys between the two variables being - compared.] - - SideEffects [None] - -******************************************************************************/ -static int -zddUniqueCompareGroup( - int * ptrX, - int * ptrY) -{ -#if 0 - if (entry[*ptrY] == entry[*ptrX]) { - return((*ptrX) - (*ptrY)); - } -#endif - return(entry[*ptrY] - entry[*ptrX]); - -} /* end of zddUniqueCompareGroup */ - - -/**Function******************************************************************** - - Synopsis [Sifts from treenode->low to treenode->high.] - - Description [Sifts from treenode->low to treenode->high. If - croupcheck == CUDD_GROUP_CHECK7, it checks for group creation at the - end of the initial sifting. If a group is created, it is then sifted - again. After sifting one variable, the group that contains it is - dissolved. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSifting( - DdManager * table, - int lower, - int upper) -{ - int *var; - int i,j,x,xInit; - int nvars; - int classes; - int result; - int *sifted; -#ifdef DD_STATS - unsigned previousSize; -#endif - int xindex; - - nvars = table->sizeZ; - - /* Order variables to sift. */ - entry = NULL; - sifted = NULL; - var = ALLOC(int,nvars); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto zddGroupSiftingOutOfMem; - } - entry = ALLOC(int,nvars); - if (entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto zddGroupSiftingOutOfMem; - } - sifted = ALLOC(int,nvars); - if (sifted == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto zddGroupSiftingOutOfMem; - } - - /* Here we consider only one representative for each group. */ - for (i = 0, classes = 0; i < nvars; i++) { - sifted[i] = 0; - x = table->permZ[i]; - if ((unsigned) x >= table->subtableZ[x].next) { - entry[i] = table->subtableZ[x].keys; - var[classes] = i; - classes++; - } - } - - qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))zddUniqueCompareGroup); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - xindex = var[i]; - if (sifted[xindex] == 1) /* variable already sifted as part of group */ - continue; - x = table->permZ[xindex]; /* find current level of this variable */ - if (x < lower || x > upper) - continue; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif -#ifdef DD_DEBUG - /* x is bottom of group */ - assert((unsigned) x >= table->subtableZ[x].next); -#endif - result = zddGroupSiftingAux(table,x,lower,upper); - if (!result) goto zddGroupSiftingOutOfMem; - -#ifdef DD_STATS - if (table->keysZ < previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > previousSize) { - (void) fprintf(table->out,"+"); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - - /* Mark variables in the group just sifted. */ - x = table->permZ[xindex]; - if ((unsigned) x != table->subtableZ[x].next) { - xInit = x; - do { - j = table->invpermZ[x]; - sifted[j] = 1; - x = table->subtableZ[x].next; - } while (x != xInit); - } - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:"); -#endif - } /* for */ - - FREE(sifted); - FREE(var); - FREE(entry); - - return(1); - -zddGroupSiftingOutOfMem: - if (entry != NULL) FREE(entry); - if (var != NULL) FREE(var); - if (sifted != NULL) FREE(sifted); - - return(0); - -} /* end of zddGroupSifting */ - - -/**Function******************************************************************** - - Synopsis [Sifts one variable up and down until it has taken all - positions. Checks for aggregation.] - - Description [Sifts one variable up and down until it has taken all - positions. Checks for aggregation. There may be at most two sweeps, - even if the group grows. Assumes that x is either an isolated - variable, or it is the bottom of a group. All groups may not have - been found. The variable being moved is returned to the best position - seen during sifting. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - Move *move; - Move *moves; /* list of moves */ - int initialSize; - int result; - - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh); - assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */ -#endif - - initialSize = table->keysZ; - moves = NULL; - - if (x == xLow) { /* Sift down */ -#ifdef DD_DEBUG - /* x must be a singleton */ - assert((unsigned) x == table->subtableZ[x].next); -#endif - if (x == xHigh) return(1); /* just one variable */ - - if (!zddGroupSiftingDown(table,x,xHigh,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - - } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */ -#ifdef DD_DEBUG - /* x is bottom of group */ - assert((unsigned) x >= table->subtableZ[x].next); -#endif - /* Find top of x's group */ - x = table->subtableZ[x].next; - - if (!zddGroupSiftingUp(table,x,xLow,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xLow, unless early term */ - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - - } else if (x - xLow > xHigh - x) { /* must go down first: shorter */ - if (!zddGroupSiftingDown(table,x,xHigh,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - /* Find top of group */ - if (moves) { - x = moves->y; - } - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; -#ifdef DD_DEBUG - /* x should be the top of a group */ - assert((unsigned) x <= table->subtableZ[x].next); -#endif - - if (!zddGroupSiftingUp(table,x,xLow,&moves)) - goto zddGroupSiftingAuxOutOfMem; - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - - } else { /* moving up first: shorter */ - /* Find top of x's group */ - x = table->subtableZ[x].next; - - if (!zddGroupSiftingUp(table,x,xLow,&moves)) - goto zddGroupSiftingAuxOutOfMem; - /* at this point x == xHigh, unless early term */ - - if (moves) { - x = moves->x; - } - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; -#ifdef DD_DEBUG - /* x is bottom of a group */ - assert((unsigned) x >= table->subtableZ[x].next); -#endif - - if (!zddGroupSiftingDown(table,x,xHigh,&moves)) - goto zddGroupSiftingAuxOutOfMem; - - /* move backward and stop at best position */ - result = zddGroupSiftingBackward(table,moves,initialSize); -#ifdef DD_DEBUG - assert(table->keysZ <= (unsigned) initialSize); -#endif - if (!result) goto zddGroupSiftingAuxOutOfMem; - } - - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(1); - -zddGroupSiftingAuxOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - - return(0); - -} /* end of zddGroupSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts up a variable until either it reaches position xLow - or the size of the DD heap increases too much.] - - Description [Sifts up a variable until either it reaches position - xLow or the size of the DD heap increases too much. Assumes that y is - the top of a group (or a singleton). Checks y for aggregation to the - adjacent variables. Records all the moves that are appended to the - list of moves received as input and returned as a side effect. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingUp( - DdManager * table, - int y, - int xLow, - Move ** moves) -{ - Move *move; - int x; - int size; - int gxtop; - int limitSize; - int xindex, yindex; - - yindex = table->invpermZ[y]; - - limitSize = table->keysZ; - - x = cuddZddNextLow(table,y); - while (x >= xLow) { - gxtop = table->subtableZ[x].next; - if (table->subtableZ[x].next == (unsigned) x && - table->subtableZ[y].next == (unsigned) y) { - /* x and y are self groups */ - xindex = table->invpermZ[x]; - size = cuddZddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtableZ[x].next == (unsigned) x); - assert(table->subtableZ[y].next == (unsigned) y); -#endif - if (size == 0) goto zddGroupSiftingUpOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) goto zddGroupSiftingUpOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_DEFAULT; - move->size = size; - move->next = *moves; - *moves = move; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n"); -#endif - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } else { /* group move */ - size = zddGroupMove(table,x,y,moves); - if (size == 0) goto zddGroupSiftingUpOutOfMem; - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } - y = gxtop; - x = cuddZddNextLow(table,y); - } - - return(1); - -zddGroupSiftingUpOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - return(0); - -} /* end of zddGroupSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts down a variable until it reaches position xHigh.] - - Description [Sifts down a variable until it reaches position xHigh. - Assumes that x is the bottom of a group (or a singleton). Records - all the moves. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingDown( - DdManager * table, - int x, - int xHigh, - Move ** moves) -{ - Move *move; - int y; - int size; - int limitSize; - int gxtop,gybot; - int xindex; - - - /* Initialize R */ - xindex = table->invpermZ[x]; - gxtop = table->subtableZ[x].next; - limitSize = size = table->keysZ; - y = cuddZddNextHigh(table,x); - while (y <= xHigh) { - /* Find bottom of y group. */ - gybot = table->subtableZ[y].next; - while (table->subtableZ[gybot].next != (unsigned) y) - gybot = table->subtableZ[gybot].next; - - if (table->subtableZ[x].next == (unsigned) x && - table->subtableZ[y].next == (unsigned) y) { - /* x and y are self groups */ - size = cuddZddSwapInPlace(table,x,y); -#ifdef DD_DEBUG - assert(table->subtableZ[x].next == (unsigned) x); - assert(table->subtableZ[y].next == (unsigned) y); -#endif - if (size == 0) goto zddGroupSiftingDownOutOfMem; - - /* Record move. */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto zddGroupSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->flags = MTR_DEFAULT; - move->size = size; - move->next = *moves; - *moves = move; - -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n"); -#endif - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - x = y; - y = cuddZddNextHigh(table,x); - } else { /* Group move */ - size = zddGroupMove(table,x,y,moves); - if (size == 0) goto zddGroupSiftingDownOutOfMem; - if ((double) size > (double) limitSize * table->maxGrowth) - return(1); - if (size < limitSize) limitSize = size; - } - x = gybot; - y = cuddZddNextHigh(table,x); - } - - return(1); - -zddGroupSiftingDownOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - - return(0); - -} /* end of zddGroupSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Swaps two groups and records the move.] - - Description [Swaps two groups and records the move. Returns the - number of keys in the DD table in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupMove( - DdManager * table, - int x, - int y, - Move ** moves) -{ - Move *move; - int size; - int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - int swapx,swapy; -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - int initialSize,bestSize; -#endif - -#if DD_DEBUG - /* We assume that x < y */ - assert(x < y); -#endif - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtableZ[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtableZ[ybot].next) - ybot = table->subtableZ[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - initialSize = bestSize = table->keysZ; -#endif - /* Sift the variables of the second group up through the first group */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddZddSwapInPlace(table,x,y); - if (size == 0) goto zddGroupMoveOutOfMem; -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if (size < bestSize) - bestSize = size; -#endif - swapx = x; swapy = y; - y = x; - x = cuddZddNextLow(table,y); - } - y = ytop + i; - x = cuddZddNextLow(table,y); - } -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if ((bestSize < initialSize) && (bestSize < size)) - (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size); -#endif - - /* fix groups */ - y = xtop; /* ytop is now where xtop used to be */ - for (i = 0; i < ysize - 1; i++) { - table->subtableZ[y].next = cuddZddNextHigh(table,y); - y = cuddZddNextHigh(table,y); - } - table->subtableZ[y].next = xtop; /* y is bottom of its group, join */ - /* it to top of its group */ - x = cuddZddNextHigh(table,y); - newxtop = x; - for (i = 0; i < xsize - 1; i++) { - table->subtableZ[x].next = cuddZddNextHigh(table,x); - x = cuddZddNextHigh(table,x); - } - table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */ - /* it to top of its group */ -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n"); -#endif - - /* Store group move */ - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) goto zddGroupMoveOutOfMem; - move->x = swapx; - move->y = swapy; - move->flags = MTR_DEFAULT; - move->size = table->keysZ; - move->next = *moves; - *moves = move; - - return(table->keysZ); - -zddGroupMoveOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *) *moves); - *moves = move; - } - return(0); - -} /* end of zddGroupMove */ - - -/**Function******************************************************************** - - Synopsis [Undoes the swap two groups.] - - Description [Undoes the swap two groups. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupMoveBackward( - DdManager * table, - int x, - int y) -{ - int size; - int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop; - - -#if DD_DEBUG - /* We assume that x < y */ - assert(x < y); -#endif - - /* Find top, bottom, and size for the two groups. */ - xbot = x; - xtop = table->subtableZ[x].next; - xsize = xbot - xtop + 1; - ybot = y; - while ((unsigned) ybot < table->subtableZ[ybot].next) - ybot = table->subtableZ[ybot].next; - ytop = y; - ysize = ybot - ytop + 1; - - /* Sift the variables of the second group up through the first group */ - for (i = 1; i <= ysize; i++) { - for (j = 1; j <= xsize; j++) { - size = cuddZddSwapInPlace(table,x,y); - if (size == 0) - return(0); - y = x; - x = cuddZddNextLow(table,y); - } - y = ytop + i; - x = cuddZddNextLow(table,y); - } - - /* fix groups */ - y = xtop; - for (i = 0; i < ysize - 1; i++) { - table->subtableZ[y].next = cuddZddNextHigh(table,y); - y = cuddZddNextHigh(table,y); - } - table->subtableZ[y].next = xtop; /* y is bottom of its group, join */ - /* to its top */ - x = cuddZddNextHigh(table,y); - newxtop = x; - for (i = 0; i < xsize - 1; i++) { - table->subtableZ[x].next = cuddZddNextHigh(table,x); - x = cuddZddNextHigh(table,x); - } - table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */ - /* to its top */ -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n"); -#endif - - return(1); - -} /* end of zddGroupMoveBackward */ - - -/**Function******************************************************************** - - Synopsis [Determines the best position for a variables and returns - it there.] - - Description [Determines the best position for a variables and returns - it there. Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddGroupSiftingBackward( - DdManager * table, - Move * moves, - int size) -{ - Move *move; - int res; - - - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) return(1); - if ((table->subtableZ[move->x].next == move->x) && - (table->subtableZ[move->y].next == move->y)) { - res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); -#ifdef DD_DEBUG - if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n"); - assert(table->subtableZ[move->x].next == move->x); - assert(table->subtableZ[move->y].next == move->y); -#endif - } else { /* Group move necessary */ - res = zddGroupMoveBackward(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - } - - return(1); - -} /* end of zddGroupSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Merges groups in the DD table.] - - Description [Creates a single group from low to high and adjusts the - idex field of the tree node.] - - SideEffects [None] - -******************************************************************************/ -static void -zddMergeGroups( - DdManager * table, - MtrNode * treenode, - int low, - int high) -{ - int i; - MtrNode *auxnode; - int saveindex; - int newindex; - - /* Merge all variables from low to high in one group, unless - ** this is the topmost group. In such a case we do not merge lest - ** we lose the symmetry information. */ - if (treenode != table->treeZ) { - for (i = low; i < high; i++) - table->subtableZ[i].next = i+1; - table->subtableZ[high].next = low; - } - - /* Adjust the index fields of the tree nodes. If a node is the - ** first child of its parent, then the parent may also need adjustment. */ - saveindex = treenode->index; - newindex = table->invpermZ[low]; - auxnode = treenode; - do { - auxnode->index = newindex; - if (auxnode->parent == NULL || - (int) auxnode->parent->index != saveindex) - break; - auxnode = auxnode->parent; - } while (1); - return; - -} /* end of zddMergeGroups */ - diff --git a/src/bdd/cudd/cuddZddIsop.c b/src/bdd/cudd/cuddZddIsop.c deleted file mode 100644 index f4b057ea..00000000 --- a/src/bdd/cudd/cuddZddIsop.c +++ /dev/null @@ -1,885 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddIsop.c] - - PackageName [cudd] - - Synopsis [Functions to find irredundant SOP covers as ZDDs from BDDs.] - - Description [External procedures included in this module: -
                -
              • Cudd_bddIsop() -
              • Cudd_zddIsop() -
              • Cudd_MakeBddFromZddCover() -
              - Internal procedures included in this module: -
                -
              • cuddBddIsop() -
              • cuddZddIsop() -
              • cuddMakeBddFromZddCover() -
              - Static procedures included in this module: -
                -
              - ] - - SeeAlso [] - - Author [In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddIsop.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes an ISOP in ZDD form from BDDs.] - - Description [Computes an irredundant sum of products (ISOP) in ZDD - form from BDDs. The two BDDs L and U represent the lower bound and - the upper bound, respectively, of the function. The ISOP uses two - ZDD variables for each BDD variable: One for the positive literal, - and one for the negative literal. These two variables should be - adjacent in the ZDD order. The two ZDD variables corresponding to - BDD variable i should have indices 2i and - 2i+1. The result of this procedure depends on the - variable order. If successful, Cudd_zddIsop returns the BDD for - the function chosen from the interval. The ZDD representing the - irredundant cover is returned as a side effect in zdd_I. In case of - failure, NULL is returned.] - - SideEffects [zdd_I holds the pointer to the ZDD for the ISOP on - successful return.] - - SeeAlso [Cudd_bddIsop Cudd_zddVarsFromBddVars] - -******************************************************************************/ -DdNode * -Cudd_zddIsop( - DdManager * dd, - DdNode * L, - DdNode * U, - DdNode ** zdd_I) -{ - DdNode *res; - int autoDynZ; - - autoDynZ = dd->autoDynZ; - dd->autoDynZ = 0; - - do { - dd->reordered = 0; - res = cuddZddIsop(dd, L, U, zdd_I); - } while (dd->reordered == 1); - dd->autoDynZ = autoDynZ; - return(res); - -} /* end of Cudd_zddIsop */ - - -/**Function******************************************************************** - - Synopsis [Computes a BDD in the interval between L and U with a - simple sum-of-produuct cover.] - - Description [Computes a BDD in the interval between L and U with a - simple sum-of-produuct cover. This procedure is similar to - Cudd_zddIsop, but it does not return the ZDD for the cover. Returns - a pointer to the BDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddIsop] - -******************************************************************************/ -DdNode * -Cudd_bddIsop( - DdManager * dd, - DdNode * L, - DdNode * U) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddBddIsop(dd, L, U); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_bddIsop */ - - -/**Function******************************************************************** - - Synopsis [Converts a ZDD cover to a BDD graph.] - - Description [Converts a ZDD cover to a BDD graph. If successful, it - returns a BDD node, otherwise it returns NULL.] - - SideEffects [] - - SeeAlso [cuddMakeBddFromZddCover] - -******************************************************************************/ -DdNode * -Cudd_MakeBddFromZddCover( - DdManager * dd, - DdNode * node) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddMakeBddFromZddCover(dd, node); - } while (dd->reordered == 1); - return(res); -} /* end of Cudd_MakeBddFromZddCover */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddIsop.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_zddIsop] - -******************************************************************************/ -DdNode * -cuddZddIsop( - DdManager * dd, - DdNode * L, - DdNode * U, - DdNode ** zdd_I) -{ - DdNode *one = DD_ONE(dd); - DdNode *zero = Cudd_Not(one); - DdNode *zdd_one = DD_ONE(dd); - DdNode *zdd_zero = DD_ZERO(dd); - int v, top_l, top_u; - DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; - DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; - DdNode *Isub0, *Isub1, *Id; - DdNode *zdd_Isub0, *zdd_Isub1, *zdd_Id; - DdNode *x; - DdNode *term0, *term1, *sum; - DdNode *Lv, *Uv, *Lnv, *Unv; - DdNode *r, *y, *z; - int index; - DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); - - statLine(dd); - if (L == zero) { - *zdd_I = zdd_zero; - return(zero); - } - if (U == one) { - *zdd_I = zdd_one; - return(one); - } - - if (U == zero || L == one) { - printf("*** ERROR : illegal condition for ISOP (U < L).\n"); - exit(1); - } - - /* Check the cache. We store two results for each recursive call. - ** One is the BDD, and the other is the ZDD. Both are needed. - ** Hence we need a double hit in the cache to terminate the - ** recursion. Clearly, collisions may evict only one of the two - ** results. */ - cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) cuddZddIsop; - r = cuddCacheLookup2(dd, cuddBddIsop, L, U); - if (r) { - *zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U); - if (*zdd_I) - return(r); - else { - /* The BDD result may have been dead. In that case - ** cuddCacheLookup2 would have called cuddReclaim, - ** whose effects we now have to undo. */ - cuddRef(r); - Cudd_RecursiveDeref(dd, r); - } - } - - top_l = dd->perm[Cudd_Regular(L)->index]; - top_u = dd->perm[Cudd_Regular(U)->index]; - v = ddMin(top_l, top_u); - - /* Compute cofactors. */ - if (top_l == v) { - index = Cudd_Regular(L)->index; - Lv = Cudd_T(L); - Lnv = Cudd_E(L); - if (Cudd_IsComplement(L)) { - Lv = Cudd_Not(Lv); - Lnv = Cudd_Not(Lnv); - } - } - else { - index = Cudd_Regular(U)->index; - Lv = Lnv = L; - } - - if (top_u == v) { - Uv = Cudd_T(U); - Unv = Cudd_E(U); - if (Cudd_IsComplement(U)) { - Uv = Cudd_Not(Uv); - Unv = Cudd_Not(Unv); - } - } - else { - Uv = Unv = U; - } - - Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); - if (Lsub0 == NULL) - return(NULL); - Cudd_Ref(Lsub0); - Usub0 = Unv; - Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); - if (Lsub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - return(NULL); - } - Cudd_Ref(Lsub1); - Usub1 = Uv; - - Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0); - if (Isub0 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - return(NULL); - } - /* - if ((!cuddIsConstant(Cudd_Regular(Isub0))) && - (Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 || - dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) { - printf("*** ERROR : illegal permutation in ZDD. ***\n"); - } - */ - Cudd_Ref(Isub0); - Cudd_Ref(zdd_Isub0); - Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1); - if (Isub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - return(NULL); - } - /* - if ((!cuddIsConstant(Cudd_Regular(Isub1))) && - (Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 || - dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) { - printf("*** ERROR : illegal permutation in ZDD. ***\n"); - } - */ - Cudd_Ref(Isub1); - Cudd_Ref(zdd_Isub1); - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - - Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); - if (Lsuper0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - return(NULL); - } - Cudd_Ref(Lsuper0); - Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); - if (Lsuper1 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - return(NULL); - } - Cudd_Ref(Lsuper1); - Usuper0 = Unv; - Usuper1 = Uv; - - /* Ld = Lsuper0 + Lsuper1 */ - Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); - if (Ld == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - return(NULL); - } - Ld = Cudd_Not(Ld); - Cudd_Ref(Ld); - /* Ud = Usuper0 * Usuper1 */ - Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); - if (Ud == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - Cudd_RecursiveDeref(dd, Ld); - return(NULL); - } - Cudd_Ref(Ud); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - - Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id); - if (Id == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - return(NULL); - } - /* - if ((!cuddIsConstant(Cudd_Regular(Id))) && - (Cudd_Regular(Id)->index != zdd_Id->index / 2 || - dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) { - printf("*** ERROR : illegal permutation in ZDD. ***\n"); - } - */ - Cudd_Ref(Id); - Cudd_Ref(zdd_Id); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - - x = cuddUniqueInter(dd, index, one, zero); - if (x == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - return(NULL); - } - Cudd_Ref(x); - /* term0 = x * Isub0 */ - term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); - if (term0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, x); - return(NULL); - } - Cudd_Ref(term0); - Cudd_RecursiveDeref(dd, Isub0); - /* term1 = x * Isub1 */ - term1 = cuddBddAndRecur(dd, x, Isub1); - if (term1 == NULL) { - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, term0); - return(NULL); - } - Cudd_Ref(term1); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, Isub1); - /* sum = term0 + term1 */ - sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); - if (sum == NULL) { - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - return(NULL); - } - sum = Cudd_Not(sum); - Cudd_Ref(sum); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - /* r = sum + Id */ - r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); - r = Cudd_NotCond(r, r != NULL); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, sum); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDeref(dd, sum); - Cudd_RecursiveDeref(dd, Id); - - if (zdd_Isub0 != zdd_zero) { - z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id); - if (z == NULL) { - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, r); - return(NULL); - } - } - else { - z = zdd_Id; - } - Cudd_Ref(z); - if (zdd_Isub1 != zdd_zero) { - y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z); - if (y == NULL) { - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDeref(dd, r); - Cudd_RecursiveDerefZdd(dd, z); - return(NULL); - } - } - else - y = z; - Cudd_Ref(y); - - Cudd_RecursiveDerefZdd(dd, zdd_Isub0); - Cudd_RecursiveDerefZdd(dd, zdd_Isub1); - Cudd_RecursiveDerefZdd(dd, zdd_Id); - Cudd_RecursiveDerefZdd(dd, z); - - cuddCacheInsert2(dd, cuddBddIsop, L, U, r); - cuddCacheInsert2(dd, cacheOp, L, U, y); - - Cudd_Deref(r); - Cudd_Deref(y); - *zdd_I = y; - /* - if (Cudd_Regular(r)->index != y->index / 2) { - printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n"); - } - */ - return(r); - -} /* end of cuddZddIsop */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_bddIsop.] - - Description [] - - SideEffects [None] - - SeeAlso [Cudd_bddIsop] - -******************************************************************************/ -DdNode * -cuddBddIsop( - DdManager * dd, - DdNode * L, - DdNode * U) -{ - DdNode *one = DD_ONE(dd); - DdNode *zero = Cudd_Not(one); - int v, top_l, top_u; - DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; - DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; - DdNode *Isub0, *Isub1, *Id; - DdNode *x; - DdNode *term0, *term1, *sum; - DdNode *Lv, *Uv, *Lnv, *Unv; - DdNode *r; - int index; - - statLine(dd); - if (L == zero) - return(zero); - if (U == one) - return(one); - - /* Check cache */ - r = cuddCacheLookup2(dd, cuddBddIsop, L, U); - if (r) - return(r); - - top_l = dd->perm[Cudd_Regular(L)->index]; - top_u = dd->perm[Cudd_Regular(U)->index]; - v = ddMin(top_l, top_u); - - /* Compute cofactors */ - if (top_l == v) { - index = Cudd_Regular(L)->index; - Lv = Cudd_T(L); - Lnv = Cudd_E(L); - if (Cudd_IsComplement(L)) { - Lv = Cudd_Not(Lv); - Lnv = Cudd_Not(Lnv); - } - } - else { - index = Cudd_Regular(U)->index; - Lv = Lnv = L; - } - - if (top_u == v) { - Uv = Cudd_T(U); - Unv = Cudd_E(U); - if (Cudd_IsComplement(U)) { - Uv = Cudd_Not(Uv); - Unv = Cudd_Not(Unv); - } - } - else { - Uv = Unv = U; - } - - Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); - if (Lsub0 == NULL) - return(NULL); - Cudd_Ref(Lsub0); - Usub0 = Unv; - Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); - if (Lsub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - return(NULL); - } - Cudd_Ref(Lsub1); - Usub1 = Uv; - - Isub0 = cuddBddIsop(dd, Lsub0, Usub0); - if (Isub0 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - return(NULL); - } - Cudd_Ref(Isub0); - Isub1 = cuddBddIsop(dd, Lsub1, Usub1); - if (Isub1 == NULL) { - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - Cudd_RecursiveDeref(dd, Isub0); - return(NULL); - } - Cudd_Ref(Isub1); - Cudd_RecursiveDeref(dd, Lsub0); - Cudd_RecursiveDeref(dd, Lsub1); - - Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); - if (Lsuper0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - return(NULL); - } - Cudd_Ref(Lsuper0); - Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); - if (Lsuper1 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - return(NULL); - } - Cudd_Ref(Lsuper1); - Usuper0 = Unv; - Usuper1 = Uv; - - /* Ld = Lsuper0 + Lsuper1 */ - Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); - Ld = Cudd_NotCond(Ld, Ld != NULL); - if (Ld == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - return(NULL); - } - Cudd_Ref(Ld); - Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); - if (Ud == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - Cudd_RecursiveDeref(dd, Ld); - return(NULL); - } - Cudd_Ref(Ud); - Cudd_RecursiveDeref(dd, Lsuper0); - Cudd_RecursiveDeref(dd, Lsuper1); - - Id = cuddBddIsop(dd, Ld, Ud); - if (Id == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - return(NULL); - } - Cudd_Ref(Id); - Cudd_RecursiveDeref(dd, Ld); - Cudd_RecursiveDeref(dd, Ud); - - x = cuddUniqueInter(dd, index, one, zero); - if (x == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - return(NULL); - } - Cudd_Ref(x); - term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); - if (term0 == NULL) { - Cudd_RecursiveDeref(dd, Isub0); - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, x); - return(NULL); - } - Cudd_Ref(term0); - Cudd_RecursiveDeref(dd, Isub0); - term1 = cuddBddAndRecur(dd, x, Isub1); - if (term1 == NULL) { - Cudd_RecursiveDeref(dd, Isub1); - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, term0); - return(NULL); - } - Cudd_Ref(term1); - Cudd_RecursiveDeref(dd, x); - Cudd_RecursiveDeref(dd, Isub1); - /* sum = term0 + term1 */ - sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); - sum = Cudd_NotCond(sum, sum != NULL); - if (sum == NULL) { - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - return(NULL); - } - Cudd_Ref(sum); - Cudd_RecursiveDeref(dd, term0); - Cudd_RecursiveDeref(dd, term1); - /* r = sum + Id */ - r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); - r = Cudd_NotCond(r, r != NULL); - if (r == NULL) { - Cudd_RecursiveDeref(dd, Id); - Cudd_RecursiveDeref(dd, sum); - return(NULL); - } - Cudd_Ref(r); - Cudd_RecursiveDeref(dd, sum); - Cudd_RecursiveDeref(dd, Id); - - cuddCacheInsert2(dd, cuddBddIsop, L, U, r); - - Cudd_Deref(r); - return(r); - -} /* end of cuddBddIsop */ - - -/**Function******************************************************************** - - Synopsis [Converts a ZDD cover to a BDD graph.] - - Description [Converts a ZDD cover to a BDD graph. If successful, it - returns a BDD node, otherwise it returns NULL. It is a recursive - algorithm as the following. First computes 3 cofactors of a ZDD cover; - f1, f0 and fd. Second, compute BDDs(b1, b0 and bd) of f1, f0 and fd. - Third, compute T=b1+bd and E=b0+bd. Fourth, compute ITE(v,T,E) where v - is the variable which has the index of the top node of the ZDD cover. - In this case, since the index of v can be larger than either one of T or - one of E, cuddUniqueInterIVO is called, here IVO stands for - independent variable ordering.] - - SideEffects [] - - SeeAlso [Cudd_MakeBddFromZddCover] - -******************************************************************************/ -DdNode * -cuddMakeBddFromZddCover( - DdManager * dd, - DdNode * node) -{ - DdNode *neW; - int v; - DdNode *f1, *f0, *fd; - DdNode *b1, *b0, *bd; - DdNode *T, *E; - - statLine(dd); - if (node == dd->one) - return(dd->one); - if (node == dd->zero) - return(Cudd_Not(dd->one)); - - /* Check cache */ - neW = cuddCacheLookup1(dd, cuddMakeBddFromZddCover, node); - if (neW) - return(neW); - - v = Cudd_Regular(node)->index; /* either yi or zi */ - cuddZddGetCofactors3(dd, node, v, &f1, &f0, &fd); - Cudd_Ref(f1); - Cudd_Ref(f0); - Cudd_Ref(fd); - - b1 = cuddMakeBddFromZddCover(dd, f1); - if (!b1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - return(NULL); - } - Cudd_Ref(b1); - b0 = cuddMakeBddFromZddCover(dd, f0); - if (!b1) { - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDeref(dd, b1); - return(NULL); - } - Cudd_Ref(b0); - Cudd_RecursiveDerefZdd(dd, f1); - Cudd_RecursiveDerefZdd(dd, f0); - if (fd != dd->zero) { - bd = cuddMakeBddFromZddCover(dd, fd); - if (!bd) { - Cudd_RecursiveDerefZdd(dd, fd); - Cudd_RecursiveDeref(dd, b1); - Cudd_RecursiveDeref(dd, b0); - return(NULL); - } - Cudd_Ref(bd); - Cudd_RecursiveDerefZdd(dd, fd); - - T = cuddBddAndRecur(dd, Cudd_Not(b1), Cudd_Not(bd)); - if (!T) { - Cudd_RecursiveDeref(dd, b1); - Cudd_RecursiveDeref(dd, b0); - Cudd_RecursiveDeref(dd, bd); - return(NULL); - } - T = Cudd_NotCond(T, T != NULL); - Cudd_Ref(T); - Cudd_RecursiveDeref(dd, b1); - E = cuddBddAndRecur(dd, Cudd_Not(b0), Cudd_Not(bd)); - if (!E) { - Cudd_RecursiveDeref(dd, b0); - Cudd_RecursiveDeref(dd, bd); - Cudd_RecursiveDeref(dd, T); - return(NULL); - } - E = Cudd_NotCond(E, E != NULL); - Cudd_Ref(E); - Cudd_RecursiveDeref(dd, b0); - Cudd_RecursiveDeref(dd, bd); - } - else { - Cudd_RecursiveDerefZdd(dd, fd); - T = b1; - E = b0; - } - - if (Cudd_IsComplement(T)) { - neW = cuddUniqueInterIVO(dd, v / 2, Cudd_Not(T), Cudd_Not(E)); - if (!neW) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - neW = Cudd_Not(neW); - } - else { - neW = cuddUniqueInterIVO(dd, v / 2, T, E); - if (!neW) { - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - return(NULL); - } - } - Cudd_Ref(neW); - Cudd_RecursiveDeref(dd, T); - Cudd_RecursiveDeref(dd, E); - - cuddCacheInsert1(dd, cuddMakeBddFromZddCover, node, neW); - Cudd_Deref(neW); - return(neW); - -} /* end of cuddMakeBddFromZddCover */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/cudd/cuddZddLin.c b/src/bdd/cudd/cuddZddLin.c deleted file mode 100644 index ef2cd298..00000000 --- a/src/bdd/cudd/cuddZddLin.c +++ /dev/null @@ -1,939 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddLin.c] - - PackageName [cudd] - - Synopsis [Procedures for dynamic variable ordering of ZDDs.] - - Description [Internal procedures included in this module: -
                -
              • cuddZddLinearSifting() -
              - Static procedures included in this module: -
                -
              • cuddZddLinearInPlace() -
              • cuddZddLinerAux() -
              • cuddZddLinearUp() -
              • cuddZddLinearDown() -
              • cuddZddLinearBackward() -
              • cuddZddUndoMoves() -
              - ] - - SeeAlso [cuddLinear.c cuddZddReord.c] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define CUDD_SWAP_MOVE 0 -#define CUDD_LINEAR_TRANSFORM_MOVE 1 -#define CUDD_INVERSE_TRANSFORM_MOVE 2 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddLin.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -extern int *zdd_entry; -extern int zddTotalNumberSwapping; -static int zddTotalNumberLinearTr; -static DdNode *empty; - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int cuddZddLinearAux ARGS((DdManager *table, int x, int xLow, int xHigh)); -static Move * cuddZddLinearUp ARGS((DdManager *table, int y, int xLow, Move *prevMoves)); -static Move * cuddZddLinearDown ARGS((DdManager *table, int x, int xHigh, Move *prevMoves)); -static int cuddZddLinearBackward ARGS((DdManager *table, int size, Move *moves)); -static Move* cuddZddUndoMoves ARGS((DdManager *table, Move *moves)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - - - -/**Function******************************************************************** - - Synopsis [Implementation of the linear sifting algorithm for ZDDs.] - - Description [Implementation of the linear sifting algorithm for ZDDs. - Assumes that no dead nodes are present. -
                -
              1. Order all the variables according to the number of entries - in each unique table. -
              2. Sift the variable up and down and applies the XOR transformation, - remembering each time the total size of the DD heap. -
              3. Select the best permutation. -
              4. Repeat 3 and 4 for all variables. -
              - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddLinearSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; -#ifdef DD_STATS - int previousSize; -#endif - - size = table->sizeZ; - empty = table->zero; - - /* Find order in which to sift variables. */ - var = NULL; - zdd_entry = ALLOC(int, size); - if (zdd_entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSiftingOutOfMem; - } - var = ALLOC(int, size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSiftingOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->permZ[i]; - zdd_entry[i] = table->subtableZ[x].keys; - var[i] = i; - } - - qsort((void *)var, size, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->permZ[var[i]]; - if (x < lower || x > upper) continue; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = cuddZddLinearAux(table, x, lower, upper); - if (!result) - goto cuddZddSiftingOutOfMem; -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); /* should never happen */ - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - FREE(var); - FREE(zdd_entry); - - return(1); - -cuddZddSiftingOutOfMem: - - if (zdd_entry != NULL) FREE(zdd_entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddZddLinearSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Linearly combines two adjacent variables.] - - Description [Linearly combines two adjacent variables. It assumes - that no dead nodes are present on entry to this procedure. The - procedure then guarantees that no dead nodes will be present when it - terminates. cuddZddLinearInPlace assumes that x < y. Returns the - number of keys in the table if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [cuddZddSwapInPlace cuddLinearInPlace] - -******************************************************************************/ -int -cuddZddLinearInPlace( - DdManager * table, - int x, - int y) -{ - DdNodePtr *xlist, *ylist; - int xindex, yindex; - int xslots, yslots; - int xshift, yshift; - int oldxkeys, oldykeys; - int newxkeys, newykeys; - int i; - int posn; - DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; - DdNode *newf1, *newf0, *g, *next, *previous; - DdNode *special; - -#ifdef DD_DEBUG - assert(x < y); - assert(cuddZddNextHigh(table,x) == y); - assert(table->subtableZ[x].keys != 0); - assert(table->subtableZ[y].keys != 0); - assert(table->subtableZ[x].dead == 0); - assert(table->subtableZ[y].dead == 0); -#endif - - zddTotalNumberLinearTr++; - - /* Get parameters of x subtable. */ - xindex = table->invpermZ[x]; - xlist = table->subtableZ[x].nodelist; - oldxkeys = table->subtableZ[x].keys; - xslots = table->subtableZ[x].slots; - xshift = table->subtableZ[x].shift; - newxkeys = 0; - - /* Get parameters of y subtable. */ - yindex = table->invpermZ[y]; - ylist = table->subtableZ[y].nodelist; - oldykeys = table->subtableZ[y].keys; - yslots = table->subtableZ[y].slots; - yshift = table->subtableZ[y].shift; - newykeys = oldykeys; - - /* The nodes in the x layer are put in two chains. The chain - ** pointed by g holds the normal nodes. When re-expressed they stay - ** in the x list. The chain pointed by special holds the elements - ** that will move to the y list. - */ - g = special = NULL; - for (i = 0; i < xslots; i++) { - f = xlist[i]; - if (f == NULL) continue; - xlist[i] = NULL; - while (f != NULL) { - next = f->next; - f1 = cuddT(f); - /* if (f1->index == yindex) */ cuddSatDec(f1->ref); - f0 = cuddE(f); - /* if (f0->index == yindex) */ cuddSatDec(f0->ref); - if ((int) f1->index == yindex && cuddE(f1) == empty && - (int) f0->index != yindex) { - f->next = special; - special = f; - } else { - f->next = g; - g = f; - } - f = next; - } /* while there are elements in the collision chain */ - } /* for each slot of the x subtable */ - - /* Mark y nodes with pointers from above x. We mark them by - ** changing their index to x. - */ - for (i = 0; i < yslots; i++) { - f = ylist[i]; - while (f != NULL) { - if (f->ref != 0) { - f->index = xindex; - } - f = f->next; - } /* while there are elements in the collision chain */ - } /* for each slot of the y subtable */ - - /* Move special nodes to the y list. */ - f = special; - while (f != NULL) { - next = f->next; - f1 = cuddT(f); - f11 = cuddT(f1); - cuddT(f) = f11; - cuddSatInc(f11->ref); - f0 = cuddE(f); - cuddSatInc(f0->ref); - f->index = yindex; - /* Insert at the beginning of the list so that it will be - ** found first if there is a duplicate. The duplicate will - ** eventually be moved or garbage collected. No node - ** re-expression will add a pointer to it. - */ - posn = ddHash(f11, f0, yshift); - f->next = ylist[posn]; - ylist[posn] = f; - newykeys++; - f = next; - } - - /* Take care of the remaining x nodes that must be re-expressed. - ** They form a linked list pointed by g. - */ - f = g; - while (f != NULL) { -#ifdef DD_COUNT - table->swapSteps++; -#endif - next = f->next; - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); - if ((int) f1->index == yindex || (int) f1->index == xindex) { - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - f11 = empty; f10 = f1; - } - f0 = cuddE(f); - if ((int) f0->index == yindex || (int) f0->index == xindex) { - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = empty; f00 = f0; - } - /* Create the new T child. */ - if (f01 == empty) { - newf1 = f10; - cuddSatInc(newf1->ref); - } else { - /* Check ylist for triple (yindex, f01, f10). */ - posn = ddHash(f01, f10, yshift); - /* For each element newf1 in collision list ylist[posn]. */ - newf1 = ylist[posn]; - /* Search the collision chain skipping the marked nodes. */ - while (newf1 != NULL) { - if (cuddT(newf1) == f01 && cuddE(newf1) == f10 && - (int) newf1->index == yindex) { - cuddSatInc(newf1->ref); - break; /* match */ - } - newf1 = newf1->next; - } /* while newf1 */ - if (newf1 == NULL) { /* no match */ - newf1 = cuddDynamicAllocNode(table); - if (newf1 == NULL) - goto zddSwapOutOfMem; - newf1->index = yindex; newf1->ref = 1; - cuddT(newf1) = f01; - cuddE(newf1) = f10; - /* Insert newf1 in the collision list ylist[pos]; - ** increase the ref counts of f01 and f10 - */ - newykeys++; - newf1->next = ylist[posn]; - ylist[posn] = newf1; - cuddSatInc(f01->ref); - cuddSatInc(f10->ref); - } - } - cuddT(f) = newf1; - - /* Do the same for f0. */ - /* Create the new E child. */ - if (f11 == empty) { - newf0 = f00; - cuddSatInc(newf0->ref); - } else { - /* Check ylist for triple (yindex, f11, f00). */ - posn = ddHash(f11, f00, yshift); - /* For each element newf0 in collision list ylist[posn]. */ - newf0 = ylist[posn]; - while (newf0 != NULL) { - if (cuddT(newf0) == f11 && cuddE(newf0) == f00 && - (int) newf0->index == yindex) { - cuddSatInc(newf0->ref); - break; /* match */ - } - newf0 = newf0->next; - } /* while newf0 */ - if (newf0 == NULL) { /* no match */ - newf0 = cuddDynamicAllocNode(table); - if (newf0 == NULL) - goto zddSwapOutOfMem; - newf0->index = yindex; newf0->ref = 1; - cuddT(newf0) = f11; cuddE(newf0) = f00; - /* Insert newf0 in the collision list ylist[posn]; - ** increase the ref counts of f11 and f00. - */ - newykeys++; - newf0->next = ylist[posn]; - ylist[posn] = newf0; - cuddSatInc(f11->ref); - cuddSatInc(f00->ref); - } - } - cuddE(f) = newf0; - - /* Re-insert the modified f in xlist. - ** The modified f does not already exists in xlist. - ** (Because of the uniqueness of the cofactors.) - */ - posn = ddHash(newf1, newf0, xshift); - newxkeys++; - f->next = xlist[posn]; - xlist[posn] = f; - f = next; - } /* while f != NULL */ - - /* GC the y layer and move the marked nodes to the x list. */ - - /* For each node f in ylist. */ - for (i = 0; i < yslots; i++) { - previous = NULL; - f = ylist[i]; - while (f != NULL) { - next = f->next; - if (f->ref == 0) { - cuddSatDec(cuddT(f)->ref); - cuddSatDec(cuddE(f)->ref); - cuddDeallocNode(table, f); - newykeys--; - if (previous == NULL) - ylist[i] = next; - else - previous->next = next; - } else if ((int) f->index == xindex) { /* move marked node */ - if (previous == NULL) - ylist[i] = next; - else - previous->next = next; - f1 = cuddT(f); - cuddSatDec(f1->ref); - /* Check ylist for triple (yindex, f1, empty). */ - posn = ddHash(f1, empty, yshift); - /* For each element newf1 in collision list ylist[posn]. */ - newf1 = ylist[posn]; - while (newf1 != NULL) { - if (cuddT(newf1) == f1 && cuddE(newf1) == empty && - (int) newf1->index == yindex) { - cuddSatInc(newf1->ref); - break; /* match */ - } - newf1 = newf1->next; - } /* while newf1 */ - if (newf1 == NULL) { /* no match */ - newf1 = cuddDynamicAllocNode(table); - if (newf1 == NULL) - goto zddSwapOutOfMem; - newf1->index = yindex; newf1->ref = 1; - cuddT(newf1) = f1; cuddE(newf1) = empty; - /* Insert newf1 in the collision list ylist[posn]; - ** increase the ref counts of f1 and empty. - */ - newykeys++; - newf1->next = ylist[posn]; - ylist[posn] = newf1; - if (posn == i && previous == NULL) - previous = newf1; - cuddSatInc(f1->ref); - cuddSatInc(empty->ref); - } - cuddT(f) = newf1; - f0 = cuddE(f); - /* Insert f in x list. */ - posn = ddHash(newf1, f0, xshift); - newxkeys++; - newykeys--; - f->next = xlist[posn]; - xlist[posn] = f; - } else { - previous = f; - } - f = next; - } /* while f */ - } /* for i */ - - /* Set the appropriate fields in table. */ - table->subtableZ[x].keys = newxkeys; - table->subtableZ[y].keys = newykeys; - - table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; - - /* Update univ section; univ[x] remains the same. */ - table->univ[y] = cuddT(table->univ[x]); - -#if 0 - (void) fprintf(table->out,"x = %d y = %d\n", x, y); - (void) Cudd_DebugCheck(table); - (void) Cudd_CheckKeys(table); -#endif - - return (table->keysZ); - -zddSwapOutOfMem: - (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); - - return (0); - -} /* end of cuddZddLinearInPlace */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. Finds the best position and does the required changes. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddLinearAux( - DdManager * table, - int x, - int xLow, - int xHigh) -{ - Move *move; - Move *moveUp; /* list of up move */ - Move *moveDown; /* list of down move */ - - int initial_size; - int result; - - initial_size = table->keysZ; - -#ifdef DD_DEBUG - assert(table->subtableZ[x].keys > 0); -#endif - - moveDown = NULL; - moveUp = NULL; - - if (x == xLow) { - moveDown = cuddZddLinearDown(table, x, xHigh, NULL); - /* At this point x --> xHigh. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - /* Move backward and stop at best position. */ - result = cuddZddLinearBackward(table, initial_size, moveDown); - if (!result) - goto cuddZddLinearAuxOutOfMem; - - } else if (x == xHigh) { - moveUp = cuddZddLinearUp(table, x, xLow, NULL); - /* At this point x --> xLow. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - /* Move backward and stop at best position. */ - result = cuddZddLinearBackward(table, initial_size, moveUp); - if (!result) - goto cuddZddLinearAuxOutOfMem; - - } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */ - moveDown = cuddZddLinearDown(table, x, xHigh, NULL); - /* At this point x --> xHigh. */ - if (moveDown == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - moveUp = cuddZddUndoMoves(table,moveDown); -#ifdef DD_DEBUG - assert(moveUp == NULL || moveUp->x == x); -#endif - moveUp = cuddZddLinearUp(table, x, xLow, moveUp); - if (moveUp == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - /* Move backward and stop at best position. */ - result = cuddZddLinearBackward(table, initial_size, moveUp); - if (!result) - goto cuddZddLinearAuxOutOfMem; - - } else { - moveUp = cuddZddLinearUp(table, x, xLow, NULL); - /* At this point x --> xHigh. */ - if (moveUp == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - /* Then move up. */ - moveDown = cuddZddUndoMoves(table,moveUp); -#ifdef DD_DEBUG - assert(moveDown == NULL || moveDown->y == x); -#endif - moveDown = cuddZddLinearDown(table, x, xHigh, moveDown); - if (moveDown == (Move *) CUDD_OUT_OF_MEM) - goto cuddZddLinearAuxOutOfMem; - /* Move backward and stop at best position. */ - result = cuddZddLinearBackward(table, initial_size, moveDown); - if (!result) - goto cuddZddLinearAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *)moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *)moveUp); - moveUp = move; - } - - return(1); - -cuddZddLinearAuxOutOfMem: - if (moveDown != (Move *) CUDD_OUT_OF_MEM) { - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *)moveDown); - moveDown = move; - } - } - if (moveUp != (Move *) CUDD_OUT_OF_MEM) { - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *)moveUp); - moveUp = move; - } - } - - return(0); - -} /* end of cuddZddLinearAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable up applying the XOR transformation.] - - Description [Sifts a variable up applying the XOR - transformation. Moves y up until either it reaches the bound (xLow) - or the size of the ZDD heap increases too much. Returns the set of - moves in case of success; NULL if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddLinearUp( - DdManager * table, - int y, - int xLow, - Move * prevMoves) -{ - Move *moves; - Move *move; - int x; - int size, newsize; - int limitSize; - - moves = prevMoves; - limitSize = table->keysZ; - - x = cuddZddNextLow(table, y); - while (x >= xLow) { - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - goto cuddZddLinearUpOutOfMem; - newsize = cuddZddLinearInPlace(table, x, y); - if (newsize == 0) - goto cuddZddLinearUpOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddLinearUpOutOfMem; - move->x = x; - move->y = y; - move->next = moves; - moves = move; - move->flags = CUDD_SWAP_MOVE; - if (newsize > size) { - /* Undo transformation. The transformation we apply is - ** its own inverse. Hence, we just apply the transformation - ** again. - */ - newsize = cuddZddLinearInPlace(table,x,y); - if (newsize == 0) goto cuddZddLinearUpOutOfMem; -#ifdef DD_DEBUG - if (newsize != size) { - (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize); - } -#endif - } else { - size = newsize; - move->flags = CUDD_LINEAR_TRANSFORM_MOVE; - } - move->size = size; - - if ((double)size > (double)limitSize * table->maxGrowth) - break; - if (size < limitSize) - limitSize = size; - - y = x; - x = cuddZddNextLow(table, y); - } - return(moves); - -cuddZddLinearUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of cuddZddLinearUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable down and applies the XOR transformation.] - - Description [Sifts a variable down. Moves x down until either it - reaches the bound (xHigh) or the size of the ZDD heap increases too - much. Returns the set of moves in case of success; NULL if memory is - full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddLinearDown( - DdManager * table, - int x, - int xHigh, - Move * prevMoves) -{ - Move *moves; - Move *move; - int y; - int size, newsize; - int limitSize; - - moves = prevMoves; - limitSize = table->keysZ; - - y = cuddZddNextHigh(table, x); - while (y <= xHigh) { - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - goto cuddZddLinearDownOutOfMem; - newsize = cuddZddLinearInPlace(table, x, y); - if (newsize == 0) - goto cuddZddLinearDownOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddLinearDownOutOfMem; - move->x = x; - move->y = y; - move->next = moves; - moves = move; - move->flags = CUDD_SWAP_MOVE; - if (newsize > size) { - /* Undo transformation. The transformation we apply is - ** its own inverse. Hence, we just apply the transformation - ** again. - */ - newsize = cuddZddLinearInPlace(table,x,y); - if (newsize == 0) goto cuddZddLinearDownOutOfMem; - if (newsize != size) { - (void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize); - } - } else { - size = newsize; - move->flags = CUDD_LINEAR_TRANSFORM_MOVE; - } - move->size = size; - - if ((double)size > (double)limitSize * table->maxGrowth) - break; - if (size < limitSize) - limitSize = size; - - x = y; - y = cuddZddNextHigh(table, x); - } - return(moves); - -cuddZddLinearDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of cuddZddLinearDown */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the ZDD heap to the position - giving the minimum size.] - - Description [Given a set of moves, returns the ZDD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddLinearBackward( - DdManager * table, - int size, - Move * moves) -{ - Move *move; - int res; - - /* Find the minimum size among moves. */ - for (move = moves; move != NULL; move = move->next) { - if (move->size < size) { - size = move->size; - } - } - - for (move = moves; move != NULL; move = move->next) { - if (move->size == size) return(1); - if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { - res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - res = cuddZddSwapInPlace(table, move->x, move->y); - if (!res) - return(0); - if (move->flags == CUDD_INVERSE_TRANSFORM_MOVE) { - res = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); - if (!res) return(0); - } - } - - return(1); - -} /* end of cuddZddLinearBackward */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the ZDD heap to the order - in effect before the moves.] - - Description [Given a set of moves, returns the ZDD heap to the - order in effect before the moves. Returns 1 in case of success; - 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static Move* -cuddZddUndoMoves( - DdManager * table, - Move * moves) -{ - Move *invmoves = NULL; - Move *move; - Move *invmove; - int size; - - for (move = moves; move != NULL; move = move->next) { - invmove = (Move *) cuddDynamicAllocNode(table); - if (invmove == NULL) goto cuddZddUndoMovesOutOfMem; - invmove->x = move->x; - invmove->y = move->y; - invmove->next = invmoves; - invmoves = invmove; - if (move->flags == CUDD_SWAP_MOVE) { - invmove->flags = CUDD_SWAP_MOVE; - size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto cuddZddUndoMovesOutOfMem; - } else if (move->flags == CUDD_LINEAR_TRANSFORM_MOVE) { - invmove->flags = CUDD_INVERSE_TRANSFORM_MOVE; - size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); - if (!size) goto cuddZddUndoMovesOutOfMem; - size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto cuddZddUndoMovesOutOfMem; - } else { /* must be CUDD_INVERSE_TRANSFORM_MOVE */ -#ifdef DD_DEBUG - (void) fprintf(table->err,"Unforseen event in ddUndoMoves!\n"); -#endif - invmove->flags = CUDD_LINEAR_TRANSFORM_MOVE; - size = cuddZddSwapInPlace(table,(int)move->x,(int)move->y); - if (!size) goto cuddZddUndoMovesOutOfMem; - size = cuddZddLinearInPlace(table,(int)move->x,(int)move->y); - if (!size) goto cuddZddUndoMovesOutOfMem; - } - invmove->size = size; - } - - return(invmoves); - -cuddZddUndoMovesOutOfMem: - while (invmoves != NULL) { - move = invmoves->next; - cuddDeallocNode(table, (DdNode *) invmoves); - invmoves = move; - } - return((Move *) CUDD_OUT_OF_MEM); - -} /* end of cuddZddUndoMoves */ - diff --git a/src/bdd/cudd/cuddZddMisc.c b/src/bdd/cudd/cuddZddMisc.c deleted file mode 100644 index 6a4ddd09..00000000 --- a/src/bdd/cudd/cuddZddMisc.c +++ /dev/null @@ -1,252 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddMisc.c] - - PackageName [cudd] - - Synopsis [.] - - Description [External procedures included in this module: -
                -
              • Cudd_zddDagSize() -
              • Cudd_zddCountMinterm() -
              • Cudd_zddPrintSubtable() -
              - Internal procedures included in this module: -
                -
              - Static procedures included in this module: -
                -
              • cuddZddDagInt() -
              - ] - - SeeAlso [] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddMisc.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int cuddZddDagInt ARGS((DdNode *n, st_table *tab)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Counts the number of nodes in a ZDD.] - - Description [Counts the number of nodes in a ZDD. This function - duplicates Cudd_DagSize and is only retained for compatibility.] - - SideEffects [None] - - SeeAlso [Cudd_DagSize] - -******************************************************************************/ -int -Cudd_zddDagSize( - DdNode * p_node) -{ - - int i; - st_table *table; - - table = st_init_table(st_ptrcmp, st_ptrhash); - i = cuddZddDagInt(p_node, table); - st_free_table(table); - return(i); - -} /* end of Cudd_zddDagSize */ - - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms of a ZDD.] - - Description [Counts the number of minterms of the ZDD rooted at - node. This procedure takes a parameter - path that specifies how many variables are in the - support of the function. If the procedure runs out of memory, it - returns (double) CUDD_OUT_OF_MEM.] - - SideEffects [None] - - SeeAlso [Cudd_zddCountDouble] - -******************************************************************************/ -double -Cudd_zddCountMinterm( - DdManager * zdd, - DdNode * node, - int path) -{ - double dc_var, minterms; - - dc_var = (double)((double)(zdd->sizeZ) - (double)path); - minterms = Cudd_zddCountDouble(zdd, node) / pow(2.0, dc_var); - return(minterms); - -} /* end of Cudd_zddCountMinterm */ - - -/**Function******************************************************************** - - Synopsis [Prints the ZDD table.] - - Description [Prints the ZDD table for debugging purposes.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_zddPrintSubtable( - DdManager * table) -{ - int i, j; - DdNode *z1, *z1_next, *base; - DdSubtable *ZSubTable; - - base = table->one; - for (i = table->sizeZ - 1; i >= 0; i--) { - ZSubTable = &(table->subtableZ[i]); - printf("subtable[%d]:\n", i); - for (j = ZSubTable->slots - 1; j >= 0; j--) { - z1 = ZSubTable->nodelist[j]; - while (z1 != NIL(DdNode)) { - (void) fprintf(table->out, -#if SIZEOF_VOID_P == 8 - "ID = 0x%lx\tindex = %d\tr = %d\t", - (unsigned long) z1 / (unsigned long) sizeof(DdNode), - z1->index, z1->ref); -#else - "ID = 0x%x\tindex = %d\tr = %d\t", - (unsigned) z1 / (unsigned) sizeof(DdNode), - z1->index, z1->ref); -#endif - z1_next = cuddT(z1); - if (Cudd_IsConstant(z1_next)) { - (void) fprintf(table->out, "T = %d\t\t", - (z1_next == base)); - } - else { -#if SIZEOF_VOID_P == 8 - (void) fprintf(table->out, "T = 0x%lx\t", - (unsigned long) z1_next / (unsigned long) sizeof(DdNode)); -#else - (void) fprintf(table->out, "T = 0x%x\t", - (unsigned) z1_next / (unsigned) sizeof(DdNode)); -#endif - } - z1_next = cuddE(z1); - if (Cudd_IsConstant(z1_next)) { - (void) fprintf(table->out, "E = %d\n", - (z1_next == base)); - } - else { -#if SIZEOF_VOID_P == 8 - (void) fprintf(table->out, "E = 0x%lx\n", - (unsigned long) z1_next / (unsigned long) sizeof(DdNode)); -#else - (void) fprintf(table->out, "E = 0x%x\n", - (unsigned) z1_next / (unsigned) sizeof(DdNode)); -#endif - } - - z1_next = z1->next; - z1 = z1_next; - } - } - } - putchar('\n'); - -} /* Cudd_zddPrintSubtable */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddDagSize.] - - Description [Performs the recursive step of Cudd_zddDagSize. Does - not check for out-of-memory conditions.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddDagInt( - DdNode * n, - st_table * tab) -{ - if (n == NIL(DdNode)) - return(0); - - if (st_is_member(tab, (char *)n) == 1) - return(0); - - if (Cudd_IsConstant(n)) - return(0); - - (void)st_insert(tab, (char *)n, NIL(char)); - return(1 + cuddZddDagInt(cuddT(n), tab) + - cuddZddDagInt(cuddE(n), tab)); - -} /* cuddZddDagInt */ - diff --git a/src/bdd/cudd/cuddZddPort.c b/src/bdd/cudd/cuddZddPort.c deleted file mode 100644 index 6d4a3236..00000000 --- a/src/bdd/cudd/cuddZddPort.c +++ /dev/null @@ -1,354 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddPort.c] - - PackageName [cudd] - - Synopsis [Functions that translate BDDs to ZDDs.] - - Description [External procedures included in this module: -
                -
              • Cudd_zddPortFromBdd() -
              • Cudd_zddPortToBdd() -
              - Internal procedures included in this module: -
                -
              - Static procedures included in this module: -
                -
              • zddPortFromBddStep() -
              • zddPortToBddStep() -
              - ] - - SeeAlso [] - - Author [Hyong-kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddPort.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * zddPortFromBddStep ARGS((DdManager *dd, DdNode *B, int expected)); -static DdNode * zddPortToBddStep ARGS((DdManager *dd, DdNode *f, int depth)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Converts a BDD into a ZDD.] - - Description [Converts a BDD into a ZDD. This function assumes that - there is a one-to-one correspondence between the BDD variables and the - ZDD variables, and that the variable order is the same for both types - of variables. These conditions are established if the ZDD variables - are created by one call to Cudd_zddVarsFromBddVars with multiplicity = - 1. Returns a pointer to the resulting ZDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddVarsFromBddVars] - -******************************************************************************/ -DdNode * -Cudd_zddPortFromBdd( - DdManager * dd, - DdNode * B) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = zddPortFromBddStep(dd,B,0); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_zddPortFromBdd */ - - -/**Function******************************************************************** - - Synopsis [Converts a ZDD into a BDD.] - - Description [Converts a ZDD into a BDD. Returns a pointer to the resulting - ZDD if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddPortFromBdd] - -******************************************************************************/ -DdNode * -Cudd_zddPortToBdd( - DdManager * dd, - DdNode * f) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = zddPortToBddStep(dd,f,0); - } while (dd->reordered == 1); - - return(res); - -} /* end of Cudd_zddPortToBdd */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddPortFromBdd.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -zddPortFromBddStep( - DdManager * dd, - DdNode * B, - int expected) -{ - DdNode *res, *prevZdd, *t, *e; - DdNode *Breg, *Bt, *Be; - int id, level; - - statLine(dd); - /* Terminal cases. */ - if (B == Cudd_Not(DD_ONE(dd))) - return(DD_ZERO(dd)); - if (B == DD_ONE(dd)) { - if (expected >= dd->sizeZ) { - return(DD_ONE(dd)); - } else { - return(dd->univ[expected]); - } - } - - Breg = Cudd_Regular(B); - - /* Computed table look-up. */ - res = cuddCacheLookup1Zdd(dd,Cudd_zddPortFromBdd,B); - if (res != NULL) { - level = cuddI(dd,Breg->index); - /* Adding DC vars. */ - if (expected < level) { - /* Add suppressed variables. */ - cuddRef(res); - for (level--; level >= expected; level--) { - prevZdd = res; - id = dd->invperm[level]; - res = cuddZddGetNode(dd, id, prevZdd, prevZdd); - if (res == NULL) { - Cudd_RecursiveDerefZdd(dd, prevZdd); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDerefZdd(dd, prevZdd); - } - cuddDeref(res); - } - return(res); - } /* end of cache look-up */ - - if (Cudd_IsComplement(B)) { - Bt = Cudd_Not(cuddT(Breg)); - Be = Cudd_Not(cuddE(Breg)); - } else { - Bt = cuddT(Breg); - Be = cuddE(Breg); - } - - id = Breg->index; - level = cuddI(dd,id); - t = zddPortFromBddStep(dd, Bt, level+1); - if (t == NULL) return(NULL); - cuddRef(t); - e = zddPortFromBddStep(dd, Be, level+1); - if (e == NULL) { - Cudd_RecursiveDerefZdd(dd, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(dd, id, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(dd, t); - Cudd_RecursiveDerefZdd(dd, e); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDerefZdd(dd, t); - Cudd_RecursiveDerefZdd(dd, e); - - cuddCacheInsert1(dd,Cudd_zddPortFromBdd,B,res); - - for (level--; level >= expected; level--) { - prevZdd = res; - id = dd->invperm[level]; - res = cuddZddGetNode(dd, id, prevZdd, prevZdd); - if (res == NULL) { - Cudd_RecursiveDerefZdd(dd, prevZdd); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDerefZdd(dd, prevZdd); - } - - cuddDeref(res); - return(res); - -} /* end of zddPortFromBddStep */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddPortToBdd.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -zddPortToBddStep( - DdManager * dd /* manager */, - DdNode * f /* ZDD to be converted */, - int depth /* recursion depth */) -{ - DdNode *one, *zero, *T, *E, *res, *var; - unsigned int index; - unsigned int level; - - statLine(dd); - one = DD_ONE(dd); - zero = DD_ZERO(dd); - if (f == zero) return(Cudd_Not(one)); - - if (depth == dd->sizeZ) return(one); - - index = dd->invpermZ[depth]; - level = cuddIZ(dd,f->index); - var = cuddUniqueInter(dd,index,one,Cudd_Not(one)); - if (var == NULL) return(NULL); - cuddRef(var); - - if (level > (unsigned) depth) { - E = zddPortToBddStep(dd,f,depth+1); - if (E == NULL) { - Cudd_RecursiveDeref(dd,var); - return(NULL); - } - cuddRef(E); - res = cuddBddIteRecur(dd,var,Cudd_Not(one),E); - if (res == NULL) { - Cudd_RecursiveDeref(dd,var); - Cudd_RecursiveDeref(dd,E); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd,var); - Cudd_RecursiveDeref(dd,E); - cuddDeref(res); - return(res); - } - - res = cuddCacheLookup1(dd,Cudd_zddPortToBdd,f); - if (res != NULL) { - Cudd_RecursiveDeref(dd,var); - return(res); - } - - T = zddPortToBddStep(dd,cuddT(f),depth+1); - if (T == NULL) { - Cudd_RecursiveDeref(dd,var); - return(NULL); - } - cuddRef(T); - E = zddPortToBddStep(dd,cuddE(f),depth+1); - if (E == NULL) { - Cudd_RecursiveDeref(dd,var); - Cudd_RecursiveDeref(dd,T); - return(NULL); - } - cuddRef(E); - - res = cuddBddIteRecur(dd,var,T,E); - if (res == NULL) { - Cudd_RecursiveDeref(dd,var); - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDeref(dd,var); - Cudd_RecursiveDeref(dd,T); - Cudd_RecursiveDeref(dd,E); - cuddDeref(res); - - cuddCacheInsert1(dd,Cudd_zddPortToBdd,f,res); - - return(res); - -} /* end of zddPortToBddStep */ - diff --git a/src/bdd/cudd/cuddZddReord.c b/src/bdd/cudd/cuddZddReord.c deleted file mode 100644 index e2da37f2..00000000 --- a/src/bdd/cudd/cuddZddReord.c +++ /dev/null @@ -1,1633 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddReord.c] - - PackageName [cudd] - - Synopsis [Procedures for dynamic variable ordering of ZDDs.] - - Description [External procedures included in this module: -
                -
              • Cudd_zddReduceHeap() -
              • Cudd_zddShuffleHeap() -
              - Internal procedures included in this module: -
                -
              • cuddZddAlignToBdd() -
              • cuddZddNextHigh() -
              • cuddZddNextLow() -
              • cuddZddUniqueCompare() -
              • cuddZddSwapInPlace() -
              • cuddZddSwapping() -
              • cuddZddSifting() -
              - Static procedures included in this module: -
                -
              • zddSwapAny() -
              • cuddZddSiftingAux() -
              • cuddZddSiftingUp() -
              • cuddZddSiftingDown() -
              • cuddZddSiftingBackward() -
              • zddReorderPreprocess() -
              • zddReorderPostprocess() -
              • zddShuffle() -
              • zddSiftUp() -
              - ] - - SeeAlso [] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_MAX_SUBTABLE_SPARSITY 8 -#define DD_SHRINK_FACTOR 2 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -int *zdd_entry; - -int zddTotalNumberSwapping; - -static DdNode *empty; - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static Move * zddSwapAny ARGS((DdManager *table, int x, int y)); -static int cuddZddSiftingAux ARGS((DdManager *table, int x, int x_low, int x_high)); -static Move * cuddZddSiftingUp ARGS((DdManager *table, int x, int x_low, int initial_size)); -static Move * cuddZddSiftingDown ARGS((DdManager *table, int x, int x_high, int initial_size)); -static int cuddZddSiftingBackward ARGS((DdManager *table, Move *moves, int size)); -static void zddReorderPreprocess ARGS((DdManager *table)); -static int zddReorderPostprocess ARGS((DdManager *table)); -static int zddShuffle ARGS((DdManager *table, int *permutation)); -static int zddSiftUp ARGS((DdManager *table, int x, int xLow)); -static void zddFixTree ARGS((DdManager *table, MtrNode *treenode)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Main dynamic reordering routine for ZDDs.] - - Description [Main dynamic reordering routine for ZDDs. - Calls one of the possible reordering procedures: -
                -
              • Swapping -
              • Sifting -
              • Symmetric Sifting -
              - - For sifting and symmetric sifting it is possible to request reordering - to convergence.

              - - The core of all methods is the reordering procedure - cuddZddSwapInPlace() which swaps two adjacent variables. - Returns 1 in case of success; 0 otherwise. In the case of symmetric - sifting (with and without convergence) returns 1 plus the number of - symmetric variables, in case of success.] - - SideEffects [Changes the variable order for all ZDDs and clears - the cache.] - -******************************************************************************/ -int -Cudd_zddReduceHeap( - DdManager * table /* DD manager */, - Cudd_ReorderingType heuristic /* method used for reordering */, - int minsize /* bound below which no reordering occurs */) -{ - DdHook *hook; - int result; - unsigned int nextDyn; -#ifdef DD_STATS - unsigned int initialSize; - unsigned int finalSize; -#endif - long localTime; - - /* Don't reorder if there are too many dead nodes. */ - if (table->keysZ - table->deadZ < (unsigned) minsize) - return(1); - - if (heuristic == CUDD_REORDER_SAME) { - heuristic = table->autoMethodZ; - } - if (heuristic == CUDD_REORDER_NONE) { - return(1); - } - - /* This call to Cudd_zddReduceHeap does initiate reordering. Therefore - ** we count it. - */ - table->reorderings++; - empty = table->zero; - - localTime = util_cpu_time(); - - /* Run the hook functions. */ - hook = table->preReorderingHook; - while (hook != NULL) { - int res = (hook->f)(table, "ZDD", (void *)heuristic); - if (res == 0) return(0); - hook = hook->next; - } - - /* Clear the cache and collect garbage. */ - zddReorderPreprocess(table); - zddTotalNumberSwapping = 0; - -#ifdef DD_STATS - initialSize = table->keysZ; - - switch(heuristic) { - case CUDD_REORDER_RANDOM: - case CUDD_REORDER_RANDOM_PIVOT: - (void) fprintf(table->out,"#:I_RANDOM "); - break; - case CUDD_REORDER_SIFT: - case CUDD_REORDER_SIFT_CONVERGE: - case CUDD_REORDER_SYMM_SIFT: - case CUDD_REORDER_SYMM_SIFT_CONV: - (void) fprintf(table->out,"#:I_SIFTING "); - break; - case CUDD_REORDER_LINEAR: - case CUDD_REORDER_LINEAR_CONVERGE: - (void) fprintf(table->out,"#:I_LINSIFT "); - break; - default: - (void) fprintf(table->err,"Unsupported ZDD reordering method\n"); - return(0); - } - (void) fprintf(table->out,"%8d: initial size",initialSize); -#endif - - result = cuddZddTreeSifting(table,heuristic); - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - finalSize = table->keysZ; - (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize); - (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n", - ((double)(util_cpu_time() - localTime)/1000.0)); - (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n", - zddTotalNumberSwapping); -#endif - - if (result == 0) - return(0); - - if (!zddReorderPostprocess(table)) - return(0); - - if (table->realignZ) { - if (!cuddBddAlignToZdd(table)) - return(0); - } - - nextDyn = table->keysZ * DD_DYN_RATIO; - if (table->reorderings < 20 || nextDyn > table->nextDyn) - table->nextDyn = nextDyn; - else - table->nextDyn += 20; - - table->reordered = 1; - - /* Run hook functions. */ - hook = table->postReorderingHook; - while (hook != NULL) { - int res = (hook->f)(table, "ZDD", (void *)localTime); - if (res == 0) return(0); - hook = hook->next; - } - /* Update cumulative reordering time. */ - table->reordTime += util_cpu_time() - localTime; - - return(result); - -} /* end of Cudd_zddReduceHeap */ - - -/**Function******************************************************************** - - Synopsis [Reorders ZDD variables according to given permutation.] - - Description [Reorders ZDD variables according to given permutation. - The i-th entry of the permutation array contains the index of the variable - that should be brought to the i-th level. The size of the array should be - equal or greater to the number of variables currently in use. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [Changes the ZDD variable order for all diagrams and clears - the cache.] - - SeeAlso [Cudd_zddReduceHeap] - -******************************************************************************/ -int -Cudd_zddShuffleHeap( - DdManager * table /* DD manager */, - int * permutation /* required variable permutation */) -{ - - int result; - - empty = table->zero; - zddReorderPreprocess(table); - - result = zddShuffle(table,permutation); - - if (!zddReorderPostprocess(table)) return(0); - - return(result); - -} /* end of Cudd_zddShuffleHeap */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Reorders ZDD variables according to the order of the BDD - variables.] - - Description [Reorders ZDD variables according to the order of the - BDD variables. This function can be called at the end of BDD - reordering to insure that the order of the ZDD variables is - consistent with the order of the BDD variables. The number of ZDD - variables must be a multiple of the number of BDD variables. Let - M be the ratio of the two numbers. cuddZddAlignToBdd - then considers the ZDD variables from M*i to - (M+1)*i-1 as corresponding to BDD variable - i. This function should be normally called from - Cudd_ReduceHeap, which clears the cache. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [Changes the ZDD variable order for all diagrams and performs - garbage collection of the ZDD unique table.] - - SeeAlso [Cudd_zddShuffleHeap Cudd_ReduceHeap] - -******************************************************************************/ -int -cuddZddAlignToBdd( - DdManager * table /* DD manager */) -{ - int *invpermZ; /* permutation array */ - int M; /* ratio of ZDD variables to BDD variables */ - int i,j; /* loop indices */ - int result; /* return value */ - - /* We assume that a ratio of 0 is OK. */ - if (table->sizeZ == 0) - return(1); - - empty = table->zero; - M = table->sizeZ / table->size; - /* Check whether the number of ZDD variables is a multiple of the - ** number of BDD variables. - */ - if (M * table->size != table->sizeZ) - return(0); - /* Create and initialize the inverse permutation array. */ - invpermZ = ALLOC(int,table->sizeZ); - if (invpermZ == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < table->size; i++) { - int index = table->invperm[i]; - int indexZ = index * M; - int levelZ = table->permZ[indexZ]; - levelZ = (levelZ / M) * M; - for (j = 0; j < M; j++) { - invpermZ[M * i + j] = table->invpermZ[levelZ + j]; - } - } - /* Eliminate dead nodes. Do not scan the cache again, because we - ** assume that Cudd_ReduceHeap has already cleared it. - */ - cuddGarbageCollectZdd(table,0); - - result = zddShuffle(table, invpermZ); - FREE(invpermZ); - /* Fix the ZDD variable group tree. */ - zddFixTree(table,table->treeZ); - return(result); - -} /* end of cuddZddAlignToBdd */ - - -/**Function******************************************************************** - - Synopsis [Finds the next subtable with a larger index.] - - Description [Finds the next subtable with a larger index. Returns the - index.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddNextHigh( - DdManager * table, - int x) -{ - return(x + 1); - -} /* end of cuddZddNextHigh */ - - -/**Function******************************************************************** - - Synopsis [Finds the next subtable with a smaller index.] - - Description [Finds the next subtable with a smaller index. Returns the - index.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddNextLow( - DdManager * table, - int x) -{ - return(x - 1); - -} /* end of cuddZddNextLow */ - - -/**Function******************************************************************** - - Synopsis [Comparison function used by qsort.] - - Description [Comparison function used by qsort to order the - variables according to the number of keys in the subtables. - Returns the difference in number of keys between the two - variables being compared.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddUniqueCompare( - int * ptr_x, - int * ptr_y) -{ - return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]); - -} /* end of cuddZddUniqueCompare */ - - -/**Function******************************************************************** - - Synopsis [Swaps two adjacent variables.] - - Description [Swaps two adjacent variables. It assumes that no dead - nodes are present on entry to this procedure. The procedure then - guarantees that no dead nodes will be present when it terminates. - cuddZddSwapInPlace assumes that x < y. Returns the number of keys in - the table if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddSwapInPlace( - DdManager * table, - int x, - int y) -{ - DdNodePtr *xlist, *ylist; - int xindex, yindex; - int xslots, yslots; - int xshift, yshift; - int oldxkeys, oldykeys; - int newxkeys, newykeys; - int i; - int posn; - DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00; - DdNode *newf1, *newf0, *next; - DdNodePtr g, *lastP, *previousP; - -#ifdef DD_DEBUG - assert(x < y); - assert(cuddZddNextHigh(table,x) == y); - assert(table->subtableZ[x].keys != 0); - assert(table->subtableZ[y].keys != 0); - assert(table->subtableZ[x].dead == 0); - assert(table->subtableZ[y].dead == 0); -#endif - - zddTotalNumberSwapping++; - - /* Get parameters of x subtable. */ - xindex = table->invpermZ[x]; - xlist = table->subtableZ[x].nodelist; - oldxkeys = table->subtableZ[x].keys; - xslots = table->subtableZ[x].slots; - xshift = table->subtableZ[x].shift; - newxkeys = 0; - - yindex = table->invpermZ[y]; - ylist = table->subtableZ[y].nodelist; - oldykeys = table->subtableZ[y].keys; - yslots = table->subtableZ[y].slots; - yshift = table->subtableZ[y].shift; - newykeys = oldykeys; - - /* The nodes in the x layer that don't depend on y directly - ** will stay there; the others are put in a chain. - ** The chain is handled as a FIFO; g points to the beginning and - ** last points to the end. - */ - - g = NULL; - lastP = &g; - for (i = 0; i < xslots; i++) { - previousP = &(xlist[i]); - f = *previousP; - while (f != NULL) { - next = f->next; - f1 = cuddT(f); f0 = cuddE(f); - if ((f1->index != (DdHalfWord) yindex) && - (f0->index != (DdHalfWord) yindex)) { /* stays */ - newxkeys++; - *previousP = f; - previousP = &(f->next); - } else { - f->index = yindex; - *lastP = f; - lastP = &(f->next); - } - f = next; - } /* while there are elements in the collision chain */ - *previousP = NULL; - } /* for each slot of the x subtable */ - *lastP = NULL; - - -#ifdef DD_COUNT - table->swapSteps += oldxkeys - newxkeys; -#endif - /* Take care of the x nodes that must be re-expressed. - ** They form a linked list pointed by g. Their index has been - ** changed to yindex already. - */ - f = g; - while (f != NULL) { - next = f->next; - /* Find f1, f0, f11, f10, f01, f00. */ - f1 = cuddT(f); - if ((int) f1->index == yindex) { - f11 = cuddT(f1); f10 = cuddE(f1); - } else { - f11 = empty; f10 = f1; - } - f0 = cuddE(f); - if ((int) f0->index == yindex) { - f01 = cuddT(f0); f00 = cuddE(f0); - } else { - f01 = empty; f00 = f0; - } - - /* Decrease ref count of f1. */ - cuddSatDec(f1->ref); - /* Create the new T child. */ - if (f11 == empty) { - if (f01 != empty) { - newf1 = f01; - cuddSatInc(newf1->ref); - } - /* else case was already handled when finding nodes - ** with both children below level y - */ - } else { - /* Check xlist for triple (xindex, f11, f01). */ - posn = ddHash(f11, f01, xshift); - /* For each element newf1 in collision list xlist[posn]. */ - newf1 = xlist[posn]; - while (newf1 != NULL) { - if (cuddT(newf1) == f11 && cuddE(newf1) == f01) { - cuddSatInc(newf1->ref); - break; /* match */ - } - newf1 = newf1->next; - } /* while newf1 */ - if (newf1 == NULL) { /* no match */ - newf1 = cuddDynamicAllocNode(table); - if (newf1 == NULL) - goto zddSwapOutOfMem; - newf1->index = xindex; newf1->ref = 1; - cuddT(newf1) = f11; - cuddE(newf1) = f01; - /* Insert newf1 in the collision list xlist[pos]; - ** increase the ref counts of f11 and f01 - */ - newxkeys++; - newf1->next = xlist[posn]; - xlist[posn] = newf1; - cuddSatInc(f11->ref); - cuddSatInc(f01->ref); - } - } - cuddT(f) = newf1; - - /* Do the same for f0. */ - /* Decrease ref count of f0. */ - cuddSatDec(f0->ref); - /* Create the new E child. */ - if (f10 == empty) { - newf0 = f00; - cuddSatInc(newf0->ref); - } else { - /* Check xlist for triple (xindex, f10, f00). */ - posn = ddHash(f10, f00, xshift); - /* For each element newf0 in collision list xlist[posn]. */ - newf0 = xlist[posn]; - while (newf0 != NULL) { - if (cuddT(newf0) == f10 && cuddE(newf0) == f00) { - cuddSatInc(newf0->ref); - break; /* match */ - } - newf0 = newf0->next; - } /* while newf0 */ - if (newf0 == NULL) { /* no match */ - newf0 = cuddDynamicAllocNode(table); - if (newf0 == NULL) - goto zddSwapOutOfMem; - newf0->index = xindex; newf0->ref = 1; - cuddT(newf0) = f10; cuddE(newf0) = f00; - /* Insert newf0 in the collision list xlist[posn]; - ** increase the ref counts of f10 and f00. - */ - newxkeys++; - newf0->next = xlist[posn]; - xlist[posn] = newf0; - cuddSatInc(f10->ref); - cuddSatInc(f00->ref); - } - } - cuddE(f) = newf0; - - /* Insert the modified f in ylist. - ** The modified f does not already exists in ylist. - ** (Because of the uniqueness of the cofactors.) - */ - posn = ddHash(newf1, newf0, yshift); - newykeys++; - f->next = ylist[posn]; - ylist[posn] = f; - f = next; - } /* while f != NULL */ - - /* GC the y layer. */ - - /* For each node f in ylist. */ - for (i = 0; i < yslots; i++) { - previousP = &(ylist[i]); - f = *previousP; - while (f != NULL) { - next = f->next; - if (f->ref == 0) { - cuddSatDec(cuddT(f)->ref); - cuddSatDec(cuddE(f)->ref); - cuddDeallocNode(table, f); - newykeys--; - } else { - *previousP = f; - previousP = &(f->next); - } - f = next; - } /* while f */ - *previousP = NULL; - } /* for i */ - - /* Set the appropriate fields in table. */ - table->subtableZ[x].nodelist = ylist; - table->subtableZ[x].slots = yslots; - table->subtableZ[x].shift = yshift; - table->subtableZ[x].keys = newykeys; - table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY; - - table->subtableZ[y].nodelist = xlist; - table->subtableZ[y].slots = xslots; - table->subtableZ[y].shift = xshift; - table->subtableZ[y].keys = newxkeys; - table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY; - - table->permZ[xindex] = y; table->permZ[yindex] = x; - table->invpermZ[x] = yindex; table->invpermZ[y] = xindex; - - table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys; - - /* Update univ section; univ[x] remains the same. */ - table->univ[y] = cuddT(table->univ[x]); - - return (table->keysZ); - -zddSwapOutOfMem: - (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n"); - - return (0); - -} /* end of cuddZddSwapInPlace */ - - -/**Function******************************************************************** - - Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.] - - Description [Implementation of Plessier's algorithm that reorders - variables by a sequence of (non-adjacent) swaps. -

                -
              1. Select two variables (RANDOM or HEURISTIC). -
              2. Permute these variables. -
              3. If the nodes have decreased accept the permutation. -
              4. Otherwise reconstruct the original heap. -
              5. Loop. -
              - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddSwapping( - DdManager * table, - int lower, - int upper, - Cudd_ReorderingType heuristic) -{ - int i, j; - int max, keys; - int nvars; - int x, y; - int iterate; - int previousSize; - Move *moves, *move; - int pivot; - int modulo; - int result; - -#ifdef DD_DEBUG - /* Sanity check */ - assert(lower >= 0 && upper < table->sizeZ && lower <= upper); -#endif - - nvars = upper - lower + 1; - iterate = nvars; - - for (i = 0; i < iterate; i++) { - if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { - /* Find pivot <= id with maximum keys. */ - for (max = -1, j = lower; j <= upper; j++) { - if ((keys = table->subtableZ[j].keys) > max) { - max = keys; - pivot = j; - } - } - - modulo = upper - pivot; - if (modulo == 0) { - y = pivot; /* y = nvars-1 */ - } else { - /* y = random # from {pivot+1 .. nvars-1} */ - y = pivot + 1 + (int) (Cudd_Random() % modulo); - } - - modulo = pivot - lower - 1; - if (modulo < 1) { /* if pivot = 1 or 0 */ - x = lower; - } else { - do { /* x = random # from {0 .. pivot-2} */ - x = (int) Cudd_Random() % modulo; - } while (x == y); - /* Is this condition really needed, since x and y - are in regions separated by pivot? */ - } - } else { - x = (int) (Cudd_Random() % nvars) + lower; - do { - y = (int) (Cudd_Random() % nvars) + lower; - } while (x == y); - } - - previousSize = table->keysZ; - moves = zddSwapAny(table, x, y); - if (moves == NULL) - goto cuddZddSwappingOutOfMem; - - result = cuddZddSiftingBackward(table, moves, previousSize); - if (!result) - goto cuddZddSwappingOutOfMem; - - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - return(1); - -cuddZddSwappingOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *) moves); - moves = move; - } - return(0); - -} /* end of cuddZddSwapping */ - - -/**Function******************************************************************** - - Synopsis [Implementation of Rudell's sifting algorithm.] - - Description [Implementation of Rudell's sifting algorithm. - Assumes that no dead nodes are present. -
                -
              1. Order all the variables according to the number of entries - in each unique table. -
              2. Sift the variable up and down, remembering each time the - total size of the DD heap. -
              3. Select the best permutation. -
              4. Repeat 3 and 4 for all variables. -
              - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int size; - int x; - int result; -#ifdef DD_STATS - int previousSize; -#endif - - size = table->sizeZ; - - /* Find order in which to sift variables. */ - var = NULL; - zdd_entry = ALLOC(int, size); - if (zdd_entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSiftingOutOfMem; - } - var = ALLOC(int, size); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSiftingOutOfMem; - } - - for (i = 0; i < size; i++) { - x = table->permZ[i]; - zdd_entry[i] = table->subtableZ[x].keys; - var[i] = i; - } - - qsort((void *)var, size, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); - - /* Now sift. */ - for (i = 0; i < ddMin(table->siftMaxVar, size); i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->permZ[var[i]]; - if (x < lower || x > upper) continue; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = cuddZddSiftingAux(table, x, lower, upper); - if (!result) - goto cuddZddSiftingOutOfMem; -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); /* should never happen */ - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]); - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - - FREE(var); - FREE(zdd_entry); - - return(1); - -cuddZddSiftingOutOfMem: - - if (zdd_entry != NULL) FREE(zdd_entry); - if (var != NULL) FREE(var); - - return(0); - -} /* end of cuddZddSifting */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Swaps any two variables.] - - Description [Swaps any two variables. Returns the set of moves.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -zddSwapAny( - DdManager * table, - int x, - int y) -{ - Move *move, *moves; - int tmp, size; - int x_ref, y_ref; - int x_next, y_next; - int limit_size; - - if (x > y) { /* make x precede y */ - tmp = x; x = y; y = tmp; - } - - x_ref = x; y_ref = y; - - x_next = cuddZddNextHigh(table, x); - y_next = cuddZddNextLow(table, y); - moves = NULL; - limit_size = table->keysZ; - - for (;;) { - if (x_next == y_next) { /* x < x_next = y_next < y */ - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *) cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - size = cuddZddSwapInPlace(table, y_next, y); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; x = y; y = tmp; - - } else if (x == y_next) { /* x = y_next < y = x_next */ - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - tmp = x; x = y; y = tmp; - } else { - size = cuddZddSwapInPlace(table, x, x_next); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = x; - move->y = x_next; - move->size = size; - move->next = moves; - moves = move; - - size = cuddZddSwapInPlace(table, y_next, y); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - x = x_next; y = y_next; - } - - x_next = cuddZddNextHigh(table, x); - y_next = cuddZddNextLow(table, y); - if (x_next > y_ref) - break; /* if x == y_ref */ - - if ((double) size > table->maxGrowth * (double) limit_size) - break; - if (size < limit_size) - limit_size = size; - } - if (y_next >= x_ref) { - size = cuddZddSwapInPlace(table, y_next, y); - if (size == 0) - goto zddSwapAnyOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zddSwapAnyOutOfMem; - move->x = y_next; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - } - - return(moves); - -zddSwapAnyOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(NULL); - -} /* end of zddSwapAny */ - - -/**Function******************************************************************** - - Synopsis [Given xLow <= x <= xHigh moves x up and down between the - boundaries.] - - Description [Given xLow <= x <= xHigh moves x up and down between the - boundaries. Finds the best position and does the required changes. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSiftingAux( - DdManager * table, - int x, - int x_low, - int x_high) -{ - Move *move; - Move *moveUp; /* list of up move */ - Move *moveDown; /* list of down move */ - - int initial_size; - int result; - - initial_size = table->keysZ; - -#ifdef DD_DEBUG - assert(table->subtableZ[x].keys > 0); -#endif - - moveDown = NULL; - moveUp = NULL; - - if (x == x_low) { - moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); - /* after that point x --> x_high */ - if (moveDown == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveDown, - initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - - } - else if (x == x_high) { - moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); - /* after that point x --> x_low */ - if (moveUp == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveUp, initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - } - else if ((x - x_low) > (x_high - x)) { - /* must go down first:shorter */ - moveDown = cuddZddSiftingDown(table, x, x_high, initial_size); - /* after that point x --> x_high */ - if (moveDown == NULL) - goto cuddZddSiftingAuxOutOfMem; - moveUp = cuddZddSiftingUp(table, moveDown->y, x_low, - initial_size); - if (moveUp == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveUp, initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - } - else { - moveUp = cuddZddSiftingUp(table, x, x_low, initial_size); - /* after that point x --> x_high */ - if (moveUp == NULL) - goto cuddZddSiftingAuxOutOfMem; - moveDown = cuddZddSiftingDown(table, moveUp->x, x_high, - initial_size); - /* then move up */ - if (moveDown == NULL) - goto cuddZddSiftingAuxOutOfMem; - result = cuddZddSiftingBackward(table, moveDown, - initial_size); - /* move backward and stop at best position */ - if (!result) - goto cuddZddSiftingAuxOutOfMem; - } - - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *)moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *)moveUp); - moveUp = move; - } - - return(1); - -cuddZddSiftingAuxOutOfMem: - while (moveDown != NULL) { - move = moveDown->next; - cuddDeallocNode(table, (DdNode *)moveDown); - moveDown = move; - } - while (moveUp != NULL) { - move = moveUp->next; - cuddDeallocNode(table, (DdNode *)moveUp); - moveUp = move; - } - - return(0); - -} /* end of cuddZddSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable up.] - - Description [Sifts a variable up. Moves y up until either it reaches - the bound (x_low) or the size of the ZDD heap increases too much. - Returns the set of moves in case of success; NULL if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddSiftingUp( - DdManager * table, - int x, - int x_low, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - - moves = NULL; - y = cuddZddNextLow(table, x); - while (y >= x_low) { - size = cuddZddSwapInPlace(table, y, x); - if (size == 0) - goto cuddZddSiftingUpOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddSiftingUpOutOfMem; - move->x = y; - move->y = x; - move->size = size; - move->next = moves; - moves = move; - - if ((double)size > (double)limit_size * table->maxGrowth) - break; - if (size < limit_size) - limit_size = size; - - x = y; - y = cuddZddNextLow(table, x); - } - return(moves); - -cuddZddSiftingUpOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(NULL); - -} /* end of cuddZddSiftingUp */ - - -/**Function******************************************************************** - - Synopsis [Sifts a variable down.] - - Description [Sifts a variable down. Moves x down until either it - reaches the bound (x_high) or the size of the ZDD heap increases too - much. Returns the set of moves in case of success; NULL if memory is - full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddSiftingDown( - DdManager * table, - int x, - int x_high, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - - moves = NULL; - y = cuddZddNextHigh(table, x); - while (y <= x_high) { - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - goto cuddZddSiftingDownOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddSiftingDownOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - - if ((double)size > (double)limit_size * table->maxGrowth) - break; - if (size < limit_size) - limit_size = size; - - x = y; - y = cuddZddNextHigh(table, x); - } - return(moves); - -cuddZddSiftingDownOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(NULL); - -} /* end of cuddZddSiftingDown */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the ZDD heap to the position - giving the minimum size.] - - Description [Given a set of moves, returns the ZDD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSiftingBackward( - DdManager * table, - Move * moves, - int size) -{ - int i; - int i_best; - Move *move; - int res; - - /* Find the minimum size among moves. */ - i_best = -1; - for (move = moves, i = 0; move != NULL; move = move->next, i++) { - if (move->size < size) { - i_best = i; - size = move->size; - } - } - - for (move = moves, i = 0; move != NULL; move = move->next, i++) { - if (i == i_best) - break; - res = cuddZddSwapInPlace(table, move->x, move->y); - if (!res) - return(0); - if (i_best == -1 && res == size) - break; - } - - return(1); - -} /* end of cuddZddSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Prepares the ZDD heap for dynamic reordering.] - - Description [Prepares the ZDD heap for dynamic reordering. Does - garbage collection, to guarantee that there are no dead nodes; - and clears the cache, which is invalidated by dynamic reordering.] - - SideEffects [None] - -******************************************************************************/ -static void -zddReorderPreprocess( - DdManager * table) -{ - - /* Clear the cache. */ - cuddCacheFlush(table); - - /* Eliminate dead nodes. Do not scan the cache again. */ - cuddGarbageCollectZdd(table,0); - - return; - -} /* end of ddReorderPreprocess */ - - -/**Function******************************************************************** - - Synopsis [Shrinks almost empty ZDD subtables at the end of reordering - to guarantee that they have a reasonable load factor.] - - Description [Shrinks almost empty subtables at the end of reordering to - guarantee that they have a reasonable load factor. However, if there many - nodes are being reclaimed, then no resizing occurs. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - -******************************************************************************/ -static int -zddReorderPostprocess( - DdManager * table) -{ - int i, j, posn; - DdNodePtr *nodelist, *oldnodelist; - DdNode *node, *next; - unsigned int slots, oldslots; - extern void (*MMoutOfMemory)(long); - void (*saveHandler)(long); - -#ifdef DD_VERBOSE - (void) fflush(table->out); -#endif - - /* If we have very many reclaimed nodes, we do not want to shrink - ** the subtables, because this will lead to more garbage - ** collections. More garbage collections mean shorter mean life for - ** nodes with zero reference count; hence lower probability of finding - ** a result in the cache. - */ - if (table->reclaimed > table->allocated * 0.5) return(1); - - /* Resize subtables. */ - for (i = 0; i < table->sizeZ; i++) { - int shift; - oldslots = table->subtableZ[i].slots; - if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY || - oldslots <= table->initSlots) continue; - oldnodelist = table->subtableZ[i].nodelist; - slots = oldslots >> 1; - saveHandler = MMoutOfMemory; - MMoutOfMemory = Cudd_OutOfMem; - nodelist = ALLOC(DdNodePtr, slots); - MMoutOfMemory = saveHandler; - if (nodelist == NULL) { - return(1); - } - table->subtableZ[i].nodelist = nodelist; - table->subtableZ[i].slots = slots; - table->subtableZ[i].shift++; - table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY; -#ifdef DD_VERBOSE - (void) fprintf(table->err, - "shrunk layer %d (%d keys) from %d to %d slots\n", - i, table->subtableZ[i].keys, oldslots, slots); -#endif - - for (j = 0; (unsigned) j < slots; j++) { - nodelist[j] = NULL; - } - shift = table->subtableZ[i].shift; - for (j = 0; (unsigned) j < oldslots; j++) { - node = oldnodelist[j]; - while (node != NULL) { - next = node->next; - posn = ddHash(cuddT(node), cuddE(node), shift); - node->next = nodelist[posn]; - nodelist[posn] = node; - node = next; - } - } - FREE(oldnodelist); - - table->memused += (slots - oldslots) * sizeof(DdNode *); - table->slots += slots - oldslots; - table->minDead = (unsigned) (table->gcFrac * (double) table->slots); - table->cacheSlack = (int) ddMin(table->maxCacheHard, - DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) - - 2 * (int) table->cacheSlots; - } - /* We don't look at the constant subtable, because it is not - ** affected by reordering. - */ - - return(1); - -} /* end of zddReorderPostprocess */ - - -/**Function******************************************************************** - - Synopsis [Reorders ZDD variables according to a given permutation.] - - Description [Reorders ZDD variables according to a given permutation. - The i-th permutation array contains the index of the variable that - should be brought to the i-th level. zddShuffle assumes that no - dead nodes are present. The reordering is achieved by a series of - upward sifts. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -zddShuffle( - DdManager * table, - int * permutation) -{ - int index; - int level; - int position; - int numvars; - int result; -#ifdef DD_STATS - long localTime; - int initialSize; - int finalSize; - int previousSize; -#endif - - zddTotalNumberSwapping = 0; -#ifdef DD_STATS - localTime = util_cpu_time(); - initialSize = table->keysZ; - (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n", - initialSize); -#endif - - numvars = table->sizeZ; - - for (level = 0; level < numvars; level++) { - index = permutation[level]; - position = table->permZ[index]; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = zddSiftUp(table,position,level); - if (!result) return(0); -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); /* should never happen */ - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); - finalSize = table->keysZ; - (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize); - (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n", - ((double)(util_cpu_time() - localTime)/1000.0)); - (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n", - zddTotalNumberSwapping); -#endif - - return(1); - -} /* end of zddShuffle */ - - -/**Function******************************************************************** - - Synopsis [Moves one ZDD variable up.] - - Description [Takes a ZDD variable from position x and sifts it up to - position xLow; xLow should be less than or equal to x. - Returns 1 if successful; 0 otherwise] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -zddSiftUp( - DdManager * table, - int x, - int xLow) -{ - int y; - int size; - - y = cuddZddNextLow(table,x); - while (y >= xLow) { - size = cuddZddSwapInPlace(table,y,x); - if (size == 0) { - return(0); - } - x = y; - y = cuddZddNextLow(table,x); - } - return(1); - -} /* end of zddSiftUp */ - - -/**Function******************************************************************** - - Synopsis [Fixes the ZDD variable group tree after a shuffle.] - - Description [Fixes the ZDD variable group tree after a - shuffle. Assumes that the order of the variables in a terminal node - has not been changed.] - - SideEffects [Changes the ZDD variable group tree.] - - SeeAlso [] - -******************************************************************************/ -static void -zddFixTree( - DdManager * table, - MtrNode * treenode) -{ - if (treenode == NULL) return; - treenode->low = ((int) treenode->index < table->sizeZ) ? - table->permZ[treenode->index] : treenode->index; - if (treenode->child != NULL) { - zddFixTree(table, treenode->child); - } - if (treenode->younger != NULL) - zddFixTree(table, treenode->younger); - if (treenode->parent != NULL && treenode->low < treenode->parent->low) { - treenode->parent->low = treenode->low; - treenode->parent->index = treenode->index; - } - return; - -} /* end of zddFixTree */ - diff --git a/src/bdd/cudd/cuddZddSetop.c b/src/bdd/cudd/cuddZddSetop.c deleted file mode 100644 index f1bd72f3..00000000 --- a/src/bdd/cudd/cuddZddSetop.c +++ /dev/null @@ -1,1137 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddSetop.c] - - PackageName [cudd] - - Synopsis [Set operations on ZDDs.] - - Description [External procedures included in this module: -
                -
              • Cudd_zddIte() -
              • Cudd_zddUnion() -
              • Cudd_zddIntersect() -
              • Cudd_zddDiff() -
              • Cudd_zddDiffConst() -
              • Cudd_zddSubset1() -
              • Cudd_zddSubset0() -
              • Cudd_zddChange() -
              - Internal procedures included in this module: -
                -
              • cuddZddIte() -
              • cuddZddUnion() -
              • cuddZddIntersect() -
              • cuddZddDiff() -
              • cuddZddChangeAux() -
              • cuddZddSubset1() -
              • cuddZddSubset0() -
              - Static procedures included in this module: -
                -
              • zdd_subset1_aux() -
              • zdd_subset0_aux() -
              • zddVarToConst() -
              - ] - - SeeAlso [] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddSetop.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * zdd_subset1_aux ARGS((DdManager *zdd, DdNode *P, DdNode *zvar)); -static DdNode * zdd_subset0_aux ARGS((DdManager *zdd, DdNode *P, DdNode *zvar)); -static void zddVarToConst ARGS((DdNode *f, DdNode **gp, DdNode **hp, DdNode *base, DdNode *empty)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the ITE of three ZDDs.] - - Description [Computes the ITE of three ZDDs. Returns a pointer to the - result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddIte( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddIte(dd, f, g, h); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddIte */ - - -/**Function******************************************************************** - - Synopsis [Computes the union of two ZDDs.] - - Description [Computes the union of two ZDDs. Returns a pointer to the - result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddUnion( - DdManager * dd, - DdNode * P, - DdNode * Q) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddUnion(dd, P, Q); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddUnion */ - - -/**Function******************************************************************** - - Synopsis [Computes the intersection of two ZDDs.] - - Description [Computes the intersection of two ZDDs. Returns a pointer to - the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddIntersect( - DdManager * dd, - DdNode * P, - DdNode * Q) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddIntersect(dd, P, Q); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddIntersect */ - - -/**Function******************************************************************** - - Synopsis [Computes the difference of two ZDDs.] - - Description [Computes the difference of two ZDDs. Returns a pointer to the - result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddDiffConst] - -******************************************************************************/ -DdNode * -Cudd_zddDiff( - DdManager * dd, - DdNode * P, - DdNode * Q) -{ - DdNode *res; - - do { - dd->reordered = 0; - res = cuddZddDiff(dd, P, Q); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddDiff */ - - -/**Function******************************************************************** - - Synopsis [Performs the inclusion test for ZDDs (P implies Q).] - - Description [Inclusion test for ZDDs (P implies Q). No new nodes are - generated by this procedure. Returns empty if true; - a valid pointer different from empty or DD_NON_CONSTANT otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddDiff] - -******************************************************************************/ -DdNode * -Cudd_zddDiffConst( - DdManager * zdd, - DdNode * P, - DdNode * Q) -{ - int p_top, q_top; - DdNode *empty = DD_ZERO(zdd), *t, *res; - DdManager *table = zdd; - - statLine(zdd); - if (P == empty) - return(empty); - if (Q == empty) - return(P); - if (P == Q) - return(empty); - - /* Check cache. The cache is shared by cuddZddDiff(). */ - res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q); - if (res != NULL) - return(res); - - if (cuddIsConstant(P)) - p_top = P->index; - else - p_top = zdd->permZ[P->index]; - if (cuddIsConstant(Q)) - q_top = Q->index; - else - q_top = zdd->permZ[Q->index]; - if (p_top < q_top) { - res = DD_NON_CONSTANT; - } else if (p_top > q_top) { - res = Cudd_zddDiffConst(zdd, P, cuddE(Q)); - } else { - t = Cudd_zddDiffConst(zdd, cuddT(P), cuddT(Q)); - if (t != empty) - res = DD_NON_CONSTANT; - else - res = Cudd_zddDiffConst(zdd, cuddE(P), cuddE(Q)); - } - - cuddCacheInsert2(table, cuddZddDiff, P, Q, res); - - return(res); - -} /* end of Cudd_zddDiffConst */ - - -/**Function******************************************************************** - - Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.] - - Description [Computes the positive cofactor of a ZDD w.r.t. a - variable. In terms of combinations, the result is the set of all - combinations in which the variable is asserted. Returns a pointer to - the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddSubset0] - -******************************************************************************/ -DdNode * -Cudd_zddSubset1( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *r; - - do { - dd->reordered = 0; - r = cuddZddSubset1(dd, P, var); - } while (dd->reordered == 1); - - return(r); - -} /* end of Cudd_zddSubset1 */ - - -/**Function******************************************************************** - - Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.] - - Description [Computes the negative cofactor of a ZDD w.r.t. a - variable. In terms of combinations, the result is the set of all - combinations in which the variable is negated. Returns a pointer to - the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddSubset1] - -******************************************************************************/ -DdNode * -Cudd_zddSubset0( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *r; - - do { - dd->reordered = 0; - r = cuddZddSubset0(dd, P, var); - } while (dd->reordered == 1); - - return(r); - -} /* end of Cudd_zddSubset0 */ - - -/**Function******************************************************************** - - Synopsis [Substitutes a variable with its complement in a ZDD.] - - Description [Substitutes a variable with its complement in a ZDD. - returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Cudd_zddChange( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *res; - - if ((unsigned int) var >= CUDD_MAXINDEX - 1) return(NULL); - - do { - dd->reordered = 0; - res = cuddZddChange(dd, P, var); - } while (dd->reordered == 1); - return(res); - -} /* end of Cudd_zddChange */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddIte.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddIte( - DdManager * dd, - DdNode * f, - DdNode * g, - DdNode * h) -{ - DdNode *tautology, *empty; - DdNode *r,*Gv,*Gvn,*Hv,*Hvn,*t,*e; - unsigned int topf,topg,toph,v,top; - int index; - - statLine(dd); - /* Trivial cases. */ - /* One variable cases. */ - if (f == (empty = DD_ZERO(dd))) { /* ITE(0,G,H) = H */ - return(h); - } - topf = cuddIZ(dd,f->index); - topg = cuddIZ(dd,g->index); - toph = cuddIZ(dd,h->index); - v = ddMin(topg,toph); - top = ddMin(topf,v); - - tautology = (top == CUDD_MAXINDEX) ? DD_ONE(dd) : dd->univ[top]; - if (f == tautology) { /* ITE(1,G,H) = G */ - return(g); - } - - /* From now on, f is known to not be a constant. */ - zddVarToConst(f,&g,&h,tautology,empty); - - /* Check remaining one variable cases. */ - if (g == h) { /* ITE(F,G,G) = G */ - return(g); - } - - if (g == tautology) { /* ITE(F,1,0) = F */ - if (h == empty) return(f); - } - - /* Check cache. */ - r = cuddCacheLookupZdd(dd,DD_ZDD_ITE_TAG,f,g,h); - if (r != NULL) { - return(r); - } - - /* Recompute these because they may have changed in zddVarToConst. */ - topg = cuddIZ(dd,g->index); - toph = cuddIZ(dd,h->index); - v = ddMin(topg,toph); - - if (topf < v) { - r = cuddZddIte(dd,cuddE(f),g,h); - if (r == NULL) return(NULL); - } else if (topf > v) { - if (topg > v) { - Gvn = g; - index = h->index; - } else { - Gvn = cuddE(g); - index = g->index; - } - if (toph > v) { - Hv = empty; Hvn = h; - } else { - Hv = cuddT(h); Hvn = cuddE(h); - } - e = cuddZddIte(dd,f,Gvn,Hvn); - if (e == NULL) return(NULL); - cuddRef(e); - r = cuddZddGetNode(dd,index,Hv,e); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd,e); - return(NULL); - } - cuddDeref(e); - } else { - index = f->index; - if (topg > v) { - Gv = empty; Gvn = g; - } else { - Gv = cuddT(g); Gvn = cuddE(g); - } - if (toph > v) { - Hv = empty; Hvn = h; - } else { - Hv = cuddT(h); Hvn = cuddE(h); - } - e = cuddZddIte(dd,cuddE(f),Gvn,Hvn); - if (e == NULL) return(NULL); - cuddRef(e); - t = cuddZddIte(dd,cuddT(f),Gv,Hv); - if (t == NULL) { - Cudd_RecursiveDerefZdd(dd,e); - return(NULL); - } - cuddRef(t); - r = cuddZddGetNode(dd,index,t,e); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd,e); - Cudd_RecursiveDerefZdd(dd,t); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert(dd,DD_ZDD_ITE_TAG,f,g,h,r); - - return(r); - -} /* end of cuddZddIte */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddUnion.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddUnion( - DdManager * zdd, - DdNode * P, - DdNode * Q) -{ - int p_top, q_top; - DdNode *empty = DD_ZERO(zdd), *t, *e, *res; - DdManager *table = zdd; - - statLine(zdd); - if (P == empty) - return(Q); - if (Q == empty) - return(P); - if (P == Q) - return(P); - - /* Check cache */ - res = cuddCacheLookup2Zdd(table, cuddZddUnion, P, Q); - if (res != NULL) - return(res); - - if (cuddIsConstant(P)) - p_top = P->index; - else - p_top = zdd->permZ[P->index]; - if (cuddIsConstant(Q)) - q_top = Q->index; - else - q_top = zdd->permZ[Q->index]; - if (p_top < q_top) { - e = cuddZddUnion(zdd, cuddE(P), Q); - if (e == NULL) return (NULL); - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, cuddT(P), e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(e); - } else if (p_top > q_top) { - e = cuddZddUnion(zdd, P, cuddE(Q)); - if (e == NULL) return(NULL); - cuddRef(e); - res = cuddZddGetNode(zdd, Q->index, cuddT(Q), e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(e); - } else { - t = cuddZddUnion(zdd, cuddT(P), cuddT(Q)); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddZddUnion(zdd, cuddE(P), cuddE(Q)); - if (e == NULL) { - Cudd_RecursiveDerefZdd(table, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, t); - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(table, cuddZddUnion, P, Q, res); - - return(res); - -} /* end of cuddZddUnion */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddIntersect.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddIntersect( - DdManager * zdd, - DdNode * P, - DdNode * Q) -{ - int p_top, q_top; - DdNode *empty = DD_ZERO(zdd), *t, *e, *res; - DdManager *table = zdd; - - statLine(zdd); - if (P == empty) - return(empty); - if (Q == empty) - return(empty); - if (P == Q) - return(P); - - /* Check cache. */ - res = cuddCacheLookup2Zdd(table, cuddZddIntersect, P, Q); - if (res != NULL) - return(res); - - if (cuddIsConstant(P)) - p_top = P->index; - else - p_top = zdd->permZ[P->index]; - if (cuddIsConstant(Q)) - q_top = Q->index; - else - q_top = zdd->permZ[Q->index]; - if (p_top < q_top) { - res = cuddZddIntersect(zdd, cuddE(P), Q); - if (res == NULL) return(NULL); - } else if (p_top > q_top) { - res = cuddZddIntersect(zdd, P, cuddE(Q)); - if (res == NULL) return(NULL); - } else { - t = cuddZddIntersect(zdd, cuddT(P), cuddT(Q)); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddZddIntersect(zdd, cuddE(P), cuddE(Q)); - if (e == NULL) { - Cudd_RecursiveDerefZdd(table, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, t); - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(table, cuddZddIntersect, P, Q, res); - - return(res); - -} /* end of cuddZddIntersect */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddDiff.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddDiff( - DdManager * zdd, - DdNode * P, - DdNode * Q) -{ - int p_top, q_top; - DdNode *empty = DD_ZERO(zdd), *t, *e, *res; - DdManager *table = zdd; - - statLine(zdd); - if (P == empty) - return(empty); - if (Q == empty) - return(P); - if (P == Q) - return(empty); - - /* Check cache. The cache is shared by Cudd_zddDiffConst(). */ - res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q); - if (res != NULL && res != DD_NON_CONSTANT) - return(res); - - if (cuddIsConstant(P)) - p_top = P->index; - else - p_top = zdd->permZ[P->index]; - if (cuddIsConstant(Q)) - q_top = Q->index; - else - q_top = zdd->permZ[Q->index]; - if (p_top < q_top) { - e = cuddZddDiff(zdd, cuddE(P), Q); - if (e == NULL) return(NULL); - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, cuddT(P), e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(e); - } else if (p_top > q_top) { - res = cuddZddDiff(zdd, P, cuddE(Q)); - if (res == NULL) return(NULL); - } else { - t = cuddZddDiff(zdd, cuddT(P), cuddT(Q)); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddZddDiff(zdd, cuddE(P), cuddE(Q)); - if (e == NULL) { - Cudd_RecursiveDerefZdd(table, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(table, t); - Cudd_RecursiveDerefZdd(table, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(table, cuddZddDiff, P, Q, res); - - return(res); - -} /* end of cuddZddDiff */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddChange.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -cuddZddChangeAux( - DdManager * zdd, - DdNode * P, - DdNode * zvar) -{ - int top_var, level; - DdNode *res, *t, *e; - DdNode *base = DD_ONE(zdd); - DdNode *empty = DD_ZERO(zdd); - - statLine(zdd); - if (P == empty) - return(empty); - if (P == base) - return(zvar); - - /* Check cache. */ - res = cuddCacheLookup2Zdd(zdd, cuddZddChangeAux, P, zvar); - if (res != NULL) - return(res); - - top_var = zdd->permZ[P->index]; - level = zdd->permZ[zvar->index]; - - if (top_var > level) { - res = cuddZddGetNode(zdd, zvar->index, P, DD_ZERO(zdd)); - if (res == NULL) return(NULL); - } else if (top_var == level) { - res = cuddZddGetNode(zdd, zvar->index, cuddE(P), cuddT(P)); - if (res == NULL) return(NULL); - } else { - t = cuddZddChangeAux(zdd, cuddT(P), zvar); - if (t == NULL) return(NULL); - cuddRef(t); - e = cuddZddChangeAux(zdd, cuddE(P), zvar); - if (e == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - Cudd_RecursiveDerefZdd(zdd, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(zdd, cuddZddChangeAux, P, zvar, res); - - return(res); - -} /* end of cuddZddChangeAux */ - - -/**Function******************************************************************** - - Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.] - - Description [Computes the positive cofactor of a ZDD w.r.t. a - variable. In terms of combinations, the result is the set of all - combinations in which the variable is asserted. Returns a pointer to - the result if successful; NULL otherwise. cuddZddSubset1 performs - the same function as Cudd_zddSubset1, but does not restart if - reordering has taken place. Therefore it can be called from within a - recursive procedure.] - - SideEffects [None] - - SeeAlso [cuddZddSubset0 Cudd_zddSubset1] - -******************************************************************************/ -DdNode * -cuddZddSubset1( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *zvar, *r; - DdNode *base, *empty; - - base = DD_ONE(dd); - empty = DD_ZERO(dd); - - zvar = cuddUniqueInterZdd(dd, var, base, empty); - if (zvar == NULL) { - return(NULL); - } else { - cuddRef(zvar); - r = zdd_subset1_aux(dd, P, zvar); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, zvar); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDerefZdd(dd, zvar); - } - - cuddDeref(r); - return(r); - -} /* end of cuddZddSubset1 */ - - -/**Function******************************************************************** - - Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.] - - Description [Computes the negative cofactor of a ZDD w.r.t. a - variable. In terms of combinations, the result is the set of all - combinations in which the variable is negated. Returns a pointer to - the result if successful; NULL otherwise. cuddZddSubset0 performs - the same function as Cudd_zddSubset0, but does not restart if - reordering has taken place. Therefore it can be called from within a - recursive procedure.] - - SideEffects [None] - - SeeAlso [cuddZddSubset1 Cudd_zddSubset0] - -******************************************************************************/ -DdNode * -cuddZddSubset0( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *zvar, *r; - DdNode *base, *empty; - - base = DD_ONE(dd); - empty = DD_ZERO(dd); - - zvar = cuddUniqueInterZdd(dd, var, base, empty); - if (zvar == NULL) { - return(NULL); - } else { - cuddRef(zvar); - r = zdd_subset0_aux(dd, P, zvar); - if (r == NULL) { - Cudd_RecursiveDerefZdd(dd, zvar); - return(NULL); - } - cuddRef(r); - Cudd_RecursiveDerefZdd(dd, zvar); - } - - cuddDeref(r); - return(r); - -} /* end of cuddZddSubset0 */ - - -/**Function******************************************************************** - - Synopsis [Substitutes a variable with its complement in a ZDD.] - - Description [Substitutes a variable with its complement in a ZDD. - returns a pointer to the result if successful; NULL - otherwise. cuddZddChange performs the same function as - Cudd_zddChange, but does not restart if reordering has taken - place. Therefore it can be called from within a recursive - procedure.] - - SideEffects [None] - - SeeAlso [Cudd_zddChange] - -******************************************************************************/ -DdNode * -cuddZddChange( - DdManager * dd, - DdNode * P, - int var) -{ - DdNode *zvar, *res; - - zvar = cuddUniqueInterZdd(dd, var, DD_ONE(dd), DD_ZERO(dd)); - if (zvar == NULL) return(NULL); - cuddRef(zvar); - - res = cuddZddChangeAux(dd, P, zvar); - if (res == NULL) { - Cudd_RecursiveDerefZdd(dd,zvar); - return(NULL); - } - cuddRef(res); - Cudd_RecursiveDerefZdd(dd,zvar); - cuddDeref(res); - return(res); - -} /* end of cuddZddChange */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddSubset1.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -zdd_subset1_aux( - DdManager * zdd, - DdNode * P, - DdNode * zvar) -{ - int top_var, level; - DdNode *res, *t, *e; - DdNode *base, *empty; - - statLine(zdd); - base = DD_ONE(zdd); - empty = DD_ZERO(zdd); - - /* Check cache. */ - res = cuddCacheLookup2Zdd(zdd, zdd_subset1_aux, P, zvar); - if (res != NULL) - return(res); - - if (cuddIsConstant(P)) { - res = empty; - cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res); - return(res); - } - - top_var = zdd->permZ[P->index]; - level = zdd->permZ[zvar->index]; - - if (top_var > level) { - res = empty; - } else if (top_var == level) { - res = cuddT(P); - } else { - t = zdd_subset1_aux(zdd, cuddT(P), zvar); - if (t == NULL) return(NULL); - cuddRef(t); - e = zdd_subset1_aux(zdd, cuddE(P), zvar); - if (e == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - Cudd_RecursiveDerefZdd(zdd, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res); - - return(res); - -} /* end of zdd_subset1_aux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddSubset0.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static DdNode * -zdd_subset0_aux( - DdManager * zdd, - DdNode * P, - DdNode * zvar) -{ - int top_var, level; - DdNode *res, *t, *e; - DdNode *base, *empty; - - statLine(zdd); - base = DD_ONE(zdd); - empty = DD_ZERO(zdd); - - /* Check cache. */ - res = cuddCacheLookup2Zdd(zdd, zdd_subset0_aux, P, zvar); - if (res != NULL) - return(res); - - if (cuddIsConstant(P)) { - res = P; - cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res); - return(res); - } - - top_var = zdd->permZ[P->index]; - level = zdd->permZ[zvar->index]; - - if (top_var > level) { - res = P; - } - else if (top_var == level) { - res = cuddE(P); - } - else { - t = zdd_subset0_aux(zdd, cuddT(P), zvar); - if (t == NULL) return(NULL); - cuddRef(t); - e = zdd_subset0_aux(zdd, cuddE(P), zvar); - if (e == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - return(NULL); - } - cuddRef(e); - res = cuddZddGetNode(zdd, P->index, t, e); - if (res == NULL) { - Cudd_RecursiveDerefZdd(zdd, t); - Cudd_RecursiveDerefZdd(zdd, e); - return(NULL); - } - cuddDeref(t); - cuddDeref(e); - } - - cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res); - - return(res); - -} /* end of zdd_subset0_aux */ - - -/**Function******************************************************************** - - Synopsis [Replaces variables with constants if possible (part of - canonical form).] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -zddVarToConst( - DdNode * f, - DdNode ** gp, - DdNode ** hp, - DdNode * base, - DdNode * empty) -{ - DdNode *g = *gp; - DdNode *h = *hp; - - if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */ - *gp = base; - } - - if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */ - *hp = empty; - } - -} /* end of zddVarToConst */ - diff --git a/src/bdd/cudd/cuddZddSymm.c b/src/bdd/cudd/cuddZddSymm.c deleted file mode 100644 index 54019892..00000000 --- a/src/bdd/cudd/cuddZddSymm.c +++ /dev/null @@ -1,1677 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddSymm.c] - - PackageName [cudd] - - Synopsis [Functions for symmetry-based ZDD variable reordering.] - - Description [External procedures included in this module: -
                -
              • Cudd_zddSymmProfile() -
              - Internal procedures included in this module: -
                -
              • cuddZddSymmCheck() -
              • cuddZddSymmSifting() -
              • cuddZddSymmSiftingConv() -
              - Static procedures included in this module: -
                -
              • cuddZddUniqueCompare() -
              • cuddZddSymmSiftingAux() -
              • cuddZddSymmSiftingConvAux() -
              • cuddZddSymmSifting_up() -
              • cuddZddSymmSifting_down() -
              • zdd_group_move() -
              • cuddZddSymmSiftingBackward() -
              • zdd_group_move_backward() -
              - ] - - SeeAlso [cuddSymmetry.c] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define ZDD_MV_OOM (Move *)1 - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -extern int *zdd_entry; - -extern int zddTotalNumberSwapping; - -static DdNode *empty; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int cuddZddSymmSiftingAux ARGS((DdManager *table, int x, int x_low, int x_high)); -static int cuddZddSymmSiftingConvAux ARGS((DdManager *table, int x, int x_low, int x_high)); -static Move * cuddZddSymmSifting_up ARGS((DdManager *table, int x, int x_low, int initial_size)); -static Move * cuddZddSymmSifting_down ARGS((DdManager *table, int x, int x_high, int initial_size)); -static int cuddZddSymmSiftingBackward ARGS((DdManager *table, Move *moves, int size)); -static int zdd_group_move ARGS((DdManager *table, int x, int y, Move **moves)); -static int zdd_group_move_backward ARGS((DdManager *table, int x, int y)); -static void cuddZddSymmSummary ARGS((DdManager *table, int lower, int upper, int *symvars, int *symgroups)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints statistics on symmetric ZDD variables.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -Cudd_zddSymmProfile( - DdManager * table, - int lower, - int upper) -{ - int i, x, gbot; - int TotalSymm = 0; - int TotalSymmGroups = 0; - int nvars; - - nvars = table->sizeZ; - - for (i = lower; i < upper; i++) { - if (table->subtableZ[i].next != (unsigned) i) { - x = i; - (void) fprintf(table->out,"Group:"); - do { - (void) fprintf(table->out," %d", table->invpermZ[x]); - TotalSymm++; - gbot = x; - x = table->subtableZ[x].next; - } while (x != i); - TotalSymmGroups++; -#ifdef DD_DEBUG - assert(table->subtableZ[gbot].next == (unsigned) i); -#endif - i = gbot; - (void) fprintf(table->out,"\n"); - } - } - (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm); - (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups); - -} /* end of Cudd_zddSymmProfile */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Checks for symmetry of x and y.] - - Description [Checks for symmetry of x and y. Ignores projection - functions, unless they are isolated. Returns 1 in case of - symmetry; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -cuddZddSymmCheck( - DdManager * table, - int x, - int y) -{ - int i; - DdNode *f, *f0, *f1, *f01, *f00, *f11, *f10; - int yindex; - int xsymmy = 1; - int xsymmyp = 1; - int arccount = 0; - int TotalRefCount = 0; - int symm_found; - - empty = table->zero; - - yindex = table->invpermZ[y]; - for (i = table->subtableZ[x].slots - 1; i >= 0; i--) { - f = table->subtableZ[x].nodelist[i]; - while (f != NULL) { - /* Find f1, f0, f11, f10, f01, f00 */ - f1 = cuddT(f); - f0 = cuddE(f); - if ((int) f1->index == yindex) { - f11 = cuddT(f1); - f10 = cuddE(f1); - if (f10 != empty) - arccount++; - } else { - if ((int) f0->index != yindex) { - return(0); /* f bypasses layer y */ - } - f11 = empty; - f10 = f1; - } - if ((int) f0->index == yindex) { - f01 = cuddT(f0); - f00 = cuddE(f0); - if (f00 != empty) - arccount++; - } else { - f01 = empty; - f00 = f0; - } - if (f01 != f10) - xsymmy = 0; - if (f11 != f00) - xsymmyp = 0; - if ((xsymmy == 0) && (xsymmyp == 0)) - return(0); - - f = f->next; - } /* for each element of the collision list */ - } /* for each slot of the subtable */ - - /* Calculate the total reference counts of y - ** whose else arc is not empty. - */ - for (i = table->subtableZ[y].slots - 1; i >= 0; i--) { - f = table->subtableZ[y].nodelist[i]; - while (f != NIL(DdNode)) { - if (cuddE(f) != empty) - TotalRefCount += f->ref; - f = f->next; - } - } - - symm_found = (arccount == TotalRefCount); -#if defined(DD_DEBUG) && defined(DD_VERBOSE) - if (symm_found) { - int xindex = table->invpermZ[x]; - (void) fprintf(table->out, - "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n", - xindex,yindex,x,y); - } -#endif - - return(symm_found); - -} /* end cuddZddSymmCheck */ - - -/**Function******************************************************************** - - Synopsis [Symmetric sifting algorithm for ZDDs.] - - Description [Symmetric sifting algorithm. - Assumes that no dead nodes are present. -
                -
              1. Order all the variables according to the number of entries in - each unique subtable. -
              2. Sift the variable up and down, remembering each time the total - size of the ZDD heap and grouping variables that are symmetric. -
              3. Select the best permutation. -
              4. Repeat 3 and 4 for all variables. -
              - Returns 1 plus the number of symmetric variables if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddZddSymmSiftingConv] - -******************************************************************************/ -int -cuddZddSymmSifting( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int nvars; - int x; - int result; - int symvars; - int symgroups; - int iteration; -#ifdef DD_STATS - int previousSize; -#endif - - nvars = table->sizeZ; - - /* Find order in which to sift variables. */ - var = NULL; - zdd_entry = ALLOC(int, nvars); - if (zdd_entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSymmSiftingOutOfMem; - } - var = ALLOC(int, nvars); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSymmSiftingOutOfMem; - } - - for (i = 0; i < nvars; i++) { - x = table->permZ[i]; - zdd_entry[i] = table->subtableZ[x].keys; - var[i] = i; - } - - qsort((void *)var, nvars, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); - - /* Initialize the symmetry of each subtable to itself. */ - for (i = lower; i <= upper; i++) - table->subtableZ[i].next = i; - - iteration = ddMin(table->siftMaxVar, nvars); - for (i = 0; i < iteration; i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->permZ[var[i]]; -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - if (x < lower || x > upper) continue; - if (table->subtableZ[x].next == (unsigned) x) { - result = cuddZddSymmSiftingAux(table, x, lower, upper); - if (!result) - goto cuddZddSymmSiftingOutOfMem; -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); -#ifdef DD_VERBOSE - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); -#endif - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } - - FREE(var); - FREE(zdd_entry); - - cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); - -#ifdef DD_STATS - (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars); - (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups); -#endif - - return(1+symvars); - -cuddZddSymmSiftingOutOfMem: - - if (zdd_entry != NULL) - FREE(zdd_entry); - if (var != NULL) - FREE(var); - - return(0); - -} /* end of cuddZddSymmSifting */ - - -/**Function******************************************************************** - - Synopsis [Symmetric sifting to convergence algorithm for ZDDs.] - - Description [Symmetric sifting to convergence algorithm for ZDDs. - Assumes that no dead nodes are present. -
                -
              1. Order all the variables according to the number of entries in - each unique subtable. -
              2. Sift the variable up and down, remembering each time the total - size of the ZDD heap and grouping variables that are symmetric. -
              3. Select the best permutation. -
              4. Repeat 3 and 4 for all variables. -
              5. Repeat 1-4 until no further improvement. -
              - Returns 1 plus the number of symmetric variables if successful; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [cuddZddSymmSifting] - -******************************************************************************/ -int -cuddZddSymmSiftingConv( - DdManager * table, - int lower, - int upper) -{ - int i; - int *var; - int nvars; - int initialSize; - int x; - int result; - int symvars; - int symgroups; - int classes; - int iteration; -#ifdef DD_STATS - int previousSize; -#endif - - initialSize = table->keysZ; - - nvars = table->sizeZ; - - /* Find order in which to sift variables. */ - var = NULL; - zdd_entry = ALLOC(int, nvars); - if (zdd_entry == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSymmSiftingConvOutOfMem; - } - var = ALLOC(int, nvars); - if (var == NULL) { - table->errorCode = CUDD_MEMORY_OUT; - goto cuddZddSymmSiftingConvOutOfMem; - } - - for (i = 0; i < nvars; i++) { - x = table->permZ[i]; - zdd_entry[i] = table->subtableZ[x].keys; - var[i] = i; - } - - qsort((void *)var, nvars, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare); - - /* Initialize the symmetry of each subtable to itself - ** for first pass of converging symmetric sifting. - */ - for (i = lower; i <= upper; i++) - table->subtableZ[i].next = i; - - iteration = ddMin(table->siftMaxVar, table->sizeZ); - for (i = 0; i < iteration; i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->permZ[var[i]]; - if (x < lower || x > upper) continue; - /* Only sift if not in symmetry group already. */ - if (table->subtableZ[x].next == (unsigned) x) { -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = cuddZddSymmSiftingAux(table, x, lower, upper); - if (!result) - goto cuddZddSymmSiftingConvOutOfMem; -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); -#ifdef DD_VERBOSE - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); -#endif - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } - - /* Sifting now until convergence. */ - while ((unsigned) initialSize > table->keysZ) { - initialSize = table->keysZ; -#ifdef DD_STATS - (void) fprintf(table->out,"\n"); -#endif - /* Here we consider only one representative for each symmetry class. */ - for (x = lower, classes = 0; x <= upper; x++, classes++) { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - /* Here x is the largest index in a group. - ** Groups consists of adjacent variables. - ** Hence, the next increment of x will move it to a new group. - */ - i = table->invpermZ[x]; - zdd_entry[i] = table->subtableZ[x].keys; - var[classes] = i; - } - - qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))cuddZddUniqueCompare); - - /* Now sift. */ - iteration = ddMin(table->siftMaxVar, nvars); - for (i = 0; i < iteration; i++) { - if (zddTotalNumberSwapping >= table->siftMaxSwap) - break; - x = table->permZ[var[i]]; - if ((unsigned) x >= table->subtableZ[x].next) { -#ifdef DD_STATS - previousSize = table->keysZ; -#endif - result = cuddZddSymmSiftingConvAux(table, x, lower, upper); - if (!result) - goto cuddZddSymmSiftingConvOutOfMem; -#ifdef DD_STATS - if (table->keysZ < (unsigned) previousSize) { - (void) fprintf(table->out,"-"); - } else if (table->keysZ > (unsigned) previousSize) { - (void) fprintf(table->out,"+"); -#ifdef DD_VERBOSE - (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]); -#endif - } else { - (void) fprintf(table->out,"="); - } - fflush(table->out); -#endif - } - } /* for */ - } - - cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups); - -#ifdef DD_STATS - (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n", - symvars); - (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n", - symgroups); -#endif - - FREE(var); - FREE(zdd_entry); - - return(1+symvars); - -cuddZddSymmSiftingConvOutOfMem: - - if (zdd_entry != NULL) - FREE(zdd_entry); - if (var != NULL) - FREE(var); - - return(0); - -} /* end of cuddZddSymmSiftingConv */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Given x_low <= x <= x_high moves x up and down between the - boundaries.] - - Description [Given x_low <= x <= x_high moves x up and down between the - boundaries. Finds the best position and does the required changes. - Assumes that x is not part of a symmetry group. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSymmSiftingAux( - DdManager * table, - int x, - int x_low, - int x_high) -{ - Move *move; - Move *move_up; /* list of up move */ - Move *move_down; /* list of down move */ - int initial_size; - int result; - int i; - int topbot; /* index to either top or bottom of symmetry group */ - int init_group_size, final_group_size; - - initial_size = table->keysZ; - - move_down = NULL; - move_up = NULL; - - /* Look for consecutive symmetries above x. */ - for (i = x; i > x_low; i--) { - if (!cuddZddSymmCheck(table, i - 1, i)) - break; - /* find top of i-1's symmetry */ - topbot = table->subtableZ[i - 1].next; - table->subtableZ[i - 1].next = i; - table->subtableZ[x].next = topbot; - /* x is bottom of group so its symmetry is top of i-1's - group */ - i = topbot + 1; /* add 1 for i--, new i is top of symm group */ - } - /* Look for consecutive symmetries below x. */ - for (i = x; i < x_high; i++) { - if (!cuddZddSymmCheck(table, i, i + 1)) - break; - /* find bottom of i+1's symm group */ - topbot = i + 1; - while ((unsigned) topbot < table->subtableZ[topbot].next) - topbot = table->subtableZ[topbot].next; - - table->subtableZ[topbot].next = table->subtableZ[i].next; - table->subtableZ[i].next = i + 1; - i = topbot - 1; /* add 1 for i++, - new i is bottom of symm group */ - } - - /* Now x maybe in the middle of a symmetry group. */ - if (x == x_low) { /* Sift down */ - /* Find bottom of x's symm group */ - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - - i = table->subtableZ[x].next; - init_group_size = x - i + 1; - - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - /* after that point x --> x_high, unless early term */ - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_down == NULL || - table->subtableZ[move_down->y].next != move_down->y) { - /* symmetry detected may have to make another complete - pass */ - if (move_down != NULL) - x = move_down->y; - else - x = table->subtableZ[x].next; - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - final_group_size = i - x + 1; - - if (init_group_size == final_group_size) { - /* No new symmetry groups detected, - return to best position */ - result = cuddZddSymmSiftingBackward(table, - move_down, initial_size); - } - else { - initial_size = table->keysZ; - move_up = cuddZddSymmSifting_up(table, x, x_low, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingAuxOutOfMem; - } - else if (x == x_high) { /* Sift up */ - /* Find top of x's symm group */ - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - init_group_size = i - x + 1; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - /* after that point x --> x_low, unless early term */ - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_up == NULL || - table->subtableZ[move_up->x].next != move_up->x) { - /* symmetry detected may have to make another complete - pass */ - if (move_up != NULL) - x = move_up->x; - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - final_group_size = x - i + 1; - - if (init_group_size == final_group_size) { - /* No new symmetry groups detected, - return to best position */ - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - else { - initial_size = table->keysZ; - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingAuxOutOfMem; - } - else if ((x - x_low) > (x_high - x)) { /* must go down first: - shorter */ - /* Find bottom of x's symm group */ - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - /* after that point x --> x_high, unless early term */ - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_down != NULL) { - x = move_down->y; - } - else { - x = table->subtableZ[x].next; - } - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - init_group_size = i - x + 1; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_up == NULL || - table->subtableZ[move_up->x].next != move_up->x) { - /* symmetry detected may have to make another complete - pass */ - if (move_up != NULL) { - x = move_up->x; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - final_group_size = x - i + 1; - - if (init_group_size == final_group_size) { - /* No new symmetry groups detected, - return to best position */ - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - else { - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - initial_size = table->keysZ; - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingAuxOutOfMem; - } - else { /* moving up first:shorter */ - /* Find top of x's symmetry group */ - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - /* after that point x --> x_high, unless early term */ - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_up != NULL) { - x = move_up->x; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - init_group_size = x - i + 1; - - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingAuxOutOfMem; - - if (move_down == NULL || - table->subtableZ[move_down->y].next != move_down->y) { - /* symmetry detected may have to make another complete - pass */ - if (move_down != NULL) { - x = move_down->y; - } - else { - x = table->subtableZ[x].next; - } - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - final_group_size = i - x + 1; - - if (init_group_size == final_group_size) { - /* No new symmetries detected, - go back to best position */ - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - else { - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - initial_size = table->keysZ; - move_up = cuddZddSymmSifting_up(table, x, x_low, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingAuxOutOfMem; - } - - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - - return(1); - -cuddZddSymmSiftingAuxOutOfMem: - if (move_down != ZDD_MV_OOM) { - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - } - if (move_up != ZDD_MV_OOM) { - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - } - - return(0); - -} /* end of cuddZddSymmSiftingAux */ - - -/**Function******************************************************************** - - Synopsis [Given x_low <= x <= x_high moves x up and down between the - boundaries.] - - Description [Given x_low <= x <= x_high moves x up and down between the - boundaries. Finds the best position and does the required changes. - Assumes that x is either an isolated variable, or it is the bottom of - a symmetry group. All symmetries may not have been found, because of - exceeded growth limit. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSymmSiftingConvAux( - DdManager * table, - int x, - int x_low, - int x_high) -{ - Move *move; - Move *move_up; /* list of up move */ - Move *move_down; /* list of down move */ - int initial_size; - int result; - int i; - int init_group_size, final_group_size; - - initial_size = table->keysZ; - - move_down = NULL; - move_up = NULL; - - if (x == x_low) { /* Sift down */ - i = table->subtableZ[x].next; - init_group_size = x - i + 1; - - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - /* after that point x --> x_high, unless early term */ - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_down == NULL || - table->subtableZ[move_down->y].next != move_down->y) { - /* symmetry detected may have to make another complete - pass */ - if (move_down != NULL) - x = move_down->y; - else { - while ((unsigned) x < table->subtableZ[x].next); - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - } - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - final_group_size = i - x + 1; - - if (init_group_size == final_group_size) { - /* No new symmetries detected, - go back to best position */ - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - else { - initial_size = table->keysZ; - move_up = cuddZddSymmSifting_up(table, x, x_low, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingConvAuxOutOfMem; - } - else if (x == x_high) { /* Sift up */ - /* Find top of x's symm group */ - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - init_group_size = i - x + 1; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - /* after that point x --> x_low, unless early term */ - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_up == NULL || - table->subtableZ[move_up->x].next != move_up->x) { - /* symmetry detected may have to make another complete - pass */ - if (move_up != NULL) - x = move_up->x; - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - final_group_size = x - i + 1; - - if (init_group_size == final_group_size) { - /* No new symmetry groups detected, - return to best position */ - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - else { - initial_size = table->keysZ; - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingConvAuxOutOfMem; - } - else if ((x - x_low) > (x_high - x)) { /* must go down first: - shorter */ - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - /* after that point x --> x_high */ - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_down != NULL) { - x = move_down->y; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - } - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - init_group_size = i - x + 1; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_up == NULL || - table->subtableZ[move_up->x].next != move_up->x) { - /* symmetry detected may have to make another complete - pass */ - if (move_up != NULL) { - x = move_up->x; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - final_group_size = x - i + 1; - - if (init_group_size == final_group_size) { - /* No new symmetry groups detected, - return to best position */ - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - else { - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - initial_size = table->keysZ; - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingConvAuxOutOfMem; - } - else { /* moving up first:shorter */ - /* Find top of x's symmetry group */ - x = table->subtableZ[x].next; - - move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size); - /* after that point x --> x_high, unless early term */ - if (move_up == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_up != NULL) { - x = move_up->x; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - } - i = table->subtableZ[x].next; - init_group_size = x - i + 1; - - move_down = cuddZddSymmSifting_down(table, x, x_high, - initial_size); - if (move_down == ZDD_MV_OOM) - goto cuddZddSymmSiftingConvAuxOutOfMem; - - if (move_down == NULL || - table->subtableZ[move_down->y].next != move_down->y) { - /* symmetry detected may have to make another complete - pass */ - if (move_down != NULL) { - x = move_down->y; - } - else { - while ((unsigned) x < table->subtableZ[x].next) - x = table->subtableZ[x].next; - x = table->subtableZ[x].next; - } - i = x; - while ((unsigned) i < table->subtableZ[i].next) { - i = table->subtableZ[i].next; - } - final_group_size = i - x + 1; - - if (init_group_size == final_group_size) { - /* No new symmetries detected, - go back to best position */ - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - } - else { - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - initial_size = table->keysZ; - move_up = cuddZddSymmSifting_up(table, x, x_low, - initial_size); - result = cuddZddSymmSiftingBackward(table, move_up, - initial_size); - } - } - else { - result = cuddZddSymmSiftingBackward(table, move_down, - initial_size); - /* move backward and stop at best position */ - } - if (!result) - goto cuddZddSymmSiftingConvAuxOutOfMem; - } - - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - - return(1); - -cuddZddSymmSiftingConvAuxOutOfMem: - if (move_down != ZDD_MV_OOM) { - while (move_down != NULL) { - move = move_down->next; - cuddDeallocNode(table, (DdNode *)move_down); - move_down = move; - } - } - if (move_up != ZDD_MV_OOM) { - while (move_up != NULL) { - move = move_up->next; - cuddDeallocNode(table, (DdNode *)move_up); - move_up = move; - } - } - - return(0); - -} /* end of cuddZddSymmSiftingConvAux */ - - -/**Function******************************************************************** - - Synopsis [Moves x up until either it reaches the bound (x_low) or - the size of the ZDD heap increases too much.] - - Description [Moves x up until either it reaches the bound (x_low) or - the size of the ZDD heap increases too much. Assumes that x is the top - of a symmetry group. Checks x for symmetry to the adjacent - variables. If symmetry is found, the symmetry group of x is merged - with the symmetry group of the other variable. Returns the set of - moves in case of success; ZDD_MV_OOM if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddSymmSifting_up( - DdManager * table, - int x, - int x_low, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - int i, gytop; - - moves = NULL; - y = cuddZddNextLow(table, x); - while (y >= x_low) { - gytop = table->subtableZ[y].next; - if (cuddZddSymmCheck(table, y, x)) { - /* Symmetry found, attach symm groups */ - table->subtableZ[y].next = x; - i = table->subtableZ[x].next; - while (table->subtableZ[i].next != (unsigned) x) - i = table->subtableZ[i].next; - table->subtableZ[i].next = gytop; - } - else if ((table->subtableZ[x].next == (unsigned) x) && - (table->subtableZ[y].next == (unsigned) y)) { - /* x and y have self symmetry */ - size = cuddZddSwapInPlace(table, y, x); - if (size == 0) - goto cuddZddSymmSifting_upOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddSymmSifting_upOutOfMem; - move->x = y; - move->y = x; - move->size = size; - move->next = moves; - moves = move; - if ((double)size > - (double)limit_size * table->maxGrowth) - return(moves); - if (size < limit_size) - limit_size = size; - } - else { /* Group move */ - size = zdd_group_move(table, y, x, &moves); - if ((double)size > - (double)limit_size * table->maxGrowth) - return(moves); - if (size < limit_size) - limit_size = size; - } - x = gytop; - y = cuddZddNextLow(table, x); - } - - return(moves); - -cuddZddSymmSifting_upOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(ZDD_MV_OOM); - -} /* end of cuddZddSymmSifting_up */ - - -/**Function******************************************************************** - - Synopsis [Moves x down until either it reaches the bound (x_high) or - the size of the ZDD heap increases too much.] - - Description [Moves x down until either it reaches the bound (x_high) - or the size of the ZDD heap increases too much. Assumes that x is the - bottom of a symmetry group. Checks x for symmetry to the adjacent - variables. If symmetry is found, the symmetry group of x is merged - with the symmetry group of the other variable. Returns the set of - moves in case of success; ZDD_MV_OOM if memory is full.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static Move * -cuddZddSymmSifting_down( - DdManager * table, - int x, - int x_high, - int initial_size) -{ - Move *moves; - Move *move; - int y; - int size; - int limit_size = initial_size; - int i, gxtop, gybot; - - moves = NULL; - y = cuddZddNextHigh(table, x); - while (y <= x_high) { - gybot = table->subtableZ[y].next; - while (table->subtableZ[gybot].next != (unsigned) y) - gybot = table->subtableZ[gybot].next; - if (cuddZddSymmCheck(table, x, y)) { - /* Symmetry found, attach symm groups */ - gxtop = table->subtableZ[x].next; - table->subtableZ[x].next = y; - i = table->subtableZ[y].next; - while (table->subtableZ[i].next != (unsigned) y) - i = table->subtableZ[i].next; - table->subtableZ[i].next = gxtop; - } - else if ((table->subtableZ[x].next == (unsigned) x) && - (table->subtableZ[y].next == (unsigned) y)) { - /* x and y have self symmetry */ - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - goto cuddZddSymmSifting_downOutOfMem; - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto cuddZddSymmSifting_downOutOfMem; - move->x = x; - move->y = y; - move->size = size; - move->next = moves; - moves = move; - if ((double)size > - (double)limit_size * table->maxGrowth) - return(moves); - if (size < limit_size) - limit_size = size; - x = y; - y = cuddZddNextHigh(table, x); - } - else { /* Group move */ - size = zdd_group_move(table, x, y, &moves); - if ((double)size > - (double)limit_size * table->maxGrowth) - return(moves); - if (size < limit_size) - limit_size = size; - } - x = gybot; - y = cuddZddNextHigh(table, x); - } - - return(moves); - -cuddZddSymmSifting_downOutOfMem: - while (moves != NULL) { - move = moves->next; - cuddDeallocNode(table, (DdNode *)moves); - moves = move; - } - return(ZDD_MV_OOM); - -} /* end of cuddZddSymmSifting_down */ - - -/**Function******************************************************************** - - Synopsis [Given a set of moves, returns the ZDD heap to the position - giving the minimum size.] - - Description [Given a set of moves, returns the ZDD heap to the - position giving the minimum size. In case of ties, returns to the - closest position giving the minimum size. Returns 1 in case of - success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -cuddZddSymmSiftingBackward( - DdManager * table, - Move * moves, - int size) -{ - int i; - int i_best; - Move *move; - int res; - - i_best = -1; - for (move = moves, i = 0; move != NULL; move = move->next, i++) { - if (move->size < size) { - i_best = i; - size = move->size; - } - } - - for (move = moves, i = 0; move != NULL; move = move->next, i++) { - if (i == i_best) break; - if ((table->subtableZ[move->x].next == move->x) && - (table->subtableZ[move->y].next == move->y)) { - res = cuddZddSwapInPlace(table, move->x, move->y); - if (!res) return(0); - } - else { /* Group move necessary */ - res = zdd_group_move_backward(table, move->x, move->y); - } - if (i_best == -1 && res == size) - break; - } - - return(1); - -} /* end of cuddZddSymmSiftingBackward */ - - -/**Function******************************************************************** - - Synopsis [Swaps two groups.] - - Description [Swaps two groups. x is assumed to be the bottom variable - of the first group. y is assumed to be the top variable of the second - group. Updates the list of moves. Returns the number of keys in the - table if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -zdd_group_move( - DdManager * table, - int x, - int y, - Move ** moves) -{ - Move *move; - int size; - int i, temp, gxtop, gxbot, gytop, gybot, yprev; - int swapx, swapy; - -#ifdef DD_DEBUG - assert(x < y); /* we assume that x < y */ -#endif - /* Find top and bottom for the two groups. */ - gxtop = table->subtableZ[x].next; - gytop = y; - gxbot = x; - gybot = table->subtableZ[y].next; - while (table->subtableZ[gybot].next != (unsigned) y) - gybot = table->subtableZ[gybot].next; - yprev = gybot; - - while (x <= y) { - while (y > gxtop) { - /* Set correct symmetries. */ - temp = table->subtableZ[x].next; - if (temp == x) - temp = y; - i = gxtop; - for (;;) { - if (table->subtableZ[i].next == (unsigned) x) { - table->subtableZ[i].next = y; - break; - } else { - i = table->subtableZ[i].next; - } - } - if (table->subtableZ[y].next != (unsigned) y) { - table->subtableZ[x].next = table->subtableZ[y].next; - } else { - table->subtableZ[x].next = x; - } - - if (yprev != y) { - table->subtableZ[yprev].next = x; - } else { - yprev = x; - } - table->subtableZ[y].next = temp; - - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - goto zdd_group_moveOutOfMem; - swapx = x; - swapy = y; - y = x; - x--; - } /* while y > gxtop */ - - /* Trying to find the next y. */ - if (table->subtableZ[y].next <= (unsigned) y) { - gybot = y; - } else { - y = table->subtableZ[y].next; - } - - yprev = gxtop; - gxtop++; - gxbot++; - x = gxbot; - } /* while x <= y, end of group movement */ - move = (Move *)cuddDynamicAllocNode(table); - if (move == NULL) - goto zdd_group_moveOutOfMem; - move->x = swapx; - move->y = swapy; - move->size = table->keysZ; - move->next = *moves; - *moves = move; - - return(table->keysZ); - -zdd_group_moveOutOfMem: - while (*moves != NULL) { - move = (*moves)->next; - cuddDeallocNode(table, (DdNode *)(*moves)); - *moves = move; - } - return(0); - -} /* end of zdd_group_move */ - - -/**Function******************************************************************** - - Synopsis [Undoes the swap of two groups.] - - Description [Undoes the swap of two groups. x is assumed to be the - bottom variable of the first group. y is assumed to be the top - variable of the second group. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -zdd_group_move_backward( - DdManager * table, - int x, - int y) -{ - int size; - int i, temp, gxtop, gxbot, gytop, gybot, yprev; - -#ifdef DD_DEBUG - assert(x < y); /* we assume that x < y */ -#endif - /* Find top and bottom of the two groups. */ - gxtop = table->subtableZ[x].next; - gytop = y; - gxbot = x; - gybot = table->subtableZ[y].next; - while (table->subtableZ[gybot].next != (unsigned) y) - gybot = table->subtableZ[gybot].next; - yprev = gybot; - - while (x <= y) { - while (y > gxtop) { - /* Set correct symmetries. */ - temp = table->subtableZ[x].next; - if (temp == x) - temp = y; - i = gxtop; - for (;;) { - if (table->subtableZ[i].next == (unsigned) x) { - table->subtableZ[i].next = y; - break; - } else { - i = table->subtableZ[i].next; - } - } - if (table->subtableZ[y].next != (unsigned) y) { - table->subtableZ[x].next = table->subtableZ[y].next; - } else { - table->subtableZ[x].next = x; - } - - if (yprev != y) { - table->subtableZ[yprev].next = x; - } else { - yprev = x; - } - table->subtableZ[y].next = temp; - - size = cuddZddSwapInPlace(table, x, y); - if (size == 0) - return(0); - y = x; - x--; - } /* while y > gxtop */ - - /* Trying to find the next y. */ - if (table->subtableZ[y].next <= (unsigned) y) { - gybot = y; - } else { - y = table->subtableZ[y].next; - } - - yprev = gxtop; - gxtop++; - gxbot++; - x = gxbot; - } /* while x <= y, end of group movement backward */ - - return(size); - -} /* end of zdd_group_move_backward */ - - -/**Function******************************************************************** - - Synopsis [Counts numbers of symmetric variables and symmetry - groups.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -static void -cuddZddSymmSummary( - DdManager * table, - int lower, - int upper, - int * symvars, - int * symgroups) -{ - int i,x,gbot; - int TotalSymm = 0; - int TotalSymmGroups = 0; - - for (i = lower; i <= upper; i++) { - if (table->subtableZ[i].next != (unsigned) i) { - TotalSymmGroups++; - x = i; - do { - TotalSymm++; - gbot = x; - x = table->subtableZ[x].next; - } while (x != i); -#ifdef DD_DEBUG - assert(table->subtableZ[gbot].next == (unsigned) i); -#endif - i = gbot; - } - } - *symvars = TotalSymm; - *symgroups = TotalSymmGroups; - - return; - -} /* end of cuddZddSymmSummary */ - diff --git a/src/bdd/cudd/cuddZddUtil.c b/src/bdd/cudd/cuddZddUtil.c deleted file mode 100644 index 616d16d4..00000000 --- a/src/bdd/cudd/cuddZddUtil.c +++ /dev/null @@ -1,1021 +0,0 @@ -/**CFile*********************************************************************** - - FileName [cuddZddUtil.c] - - PackageName [cudd] - - Synopsis [Utility functions for ZDDs.] - - Description [External procedures included in this module: -
                -
              • Cudd_zddPrintMinterm() -
              • Cudd_zddPrintCover() -
              • Cudd_zddPrintDebug() -
              • Cudd_zddDumpDot() -
              - Internal procedures included in this module: -
                -
              • cuddZddP() -
              - Static procedures included in this module: -
                -
              • zp2() -
              • zdd_print_minterm_aux() -
              - ] - - SeeAlso [] - - Author [Hyong-Kyoon Shin, In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: cuddZddUtil.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int zp2 ARGS((DdManager *zdd, DdNode *f, st_table *t)); -static void zdd_print_minterm_aux ARGS((DdManager *zdd, DdNode *node, int level, int *list)); -static void zddPrintCoverAux ARGS((DdManager *zdd, DdNode *node, int level, int *list)); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints a disjoint sum of product form for a ZDD.] - - Description [Prints a disjoint sum of product form for a ZDD. Returns 1 - if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddPrintDebug Cudd_zddPrintCover] - -******************************************************************************/ -int -Cudd_zddPrintMinterm( - DdManager * zdd, - DdNode * node) -{ - int i, size; - int *list; - - size = (int)zdd->sizeZ; - list = ALLOC(int, size); - if (list == NULL) { - zdd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */ - zdd_print_minterm_aux(zdd, node, 0, list); - FREE(list); - return(1); - -} /* end of Cudd_zddPrintMinterm */ - - -/**Function******************************************************************** - - Synopsis [Prints a sum of products from a ZDD representing a cover.] - - Description [Prints a sum of products from a ZDD representing a cover. - Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddPrintMinterm] - -******************************************************************************/ -int -Cudd_zddPrintCover( - DdManager * zdd, - DdNode * node) -{ - int i, size; - int *list; - - size = (int)zdd->sizeZ; - if (size % 2 != 0) return(0); /* number of variables should be even */ - list = ALLOC(int, size); - if (list == NULL) { - zdd->errorCode = CUDD_MEMORY_OUT; - return(0); - } - for (i = 0; i < size; i++) list[i] = 3; /* bogus value should disappear */ - zddPrintCoverAux(zdd, node, 0, list); - FREE(list); - return(1); - -} /* end of Cudd_zddPrintCover */ - - -/**Function******************************************************************** - - Synopsis [Prints to the standard output a ZDD and its statistics.] - - Description [Prints to the standard output a DD and its statistics. - The statistics include the number of nodes and the number of minterms. - (The number of minterms is also the number of combinations in the set.) - The statistics are printed if pr > 0. Specifically: -
                -
              • pr = 0 : prints nothing -
              • pr = 1 : prints counts of nodes and minterms -
              • pr = 2 : prints counts + disjoint sum of products -
              • pr = 3 : prints counts + list of nodes -
              • pr > 3 : prints counts + disjoint sum of products + list of nodes -
              - Returns 1 if successful; 0 otherwise. - ] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Cudd_zddPrintDebug( - DdManager * zdd, - DdNode * f, - int n, - int pr) -{ - DdNode *empty = DD_ZERO(zdd); - int nodes; - double minterms; - int retval = 1; - - if (f == empty && pr > 0) { - (void) fprintf(zdd->out,": is the empty ZDD\n"); - (void) fflush(zdd->out); - return(1); - } - - if (pr > 0) { - nodes = Cudd_zddDagSize(f); - if (nodes == CUDD_OUT_OF_MEM) retval = 0; - minterms = Cudd_zddCountMinterm(zdd, f, n); - if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0; - (void) fprintf(zdd->out,": %d nodes %g minterms\n", - nodes, minterms); - if (pr > 2) - if (!cuddZddP(zdd, f)) retval = 0; - if (pr == 2 || pr > 3) { - if (!Cudd_zddPrintMinterm(zdd, f)) retval = 0; - (void) fprintf(zdd->out,"\n"); - } - (void) fflush(zdd->out); - } - return(retval); - -} /* end of Cudd_zddPrintDebug */ - - - -/**Function******************************************************************** - - Synopsis [Finds the first path of a ZDD.] - - Description [Defines an iterator on the paths of a ZDD - and finds its first path. Returns a generator that contains the - information necessary to continue the enumeration if successful; NULL - otherwise.

              - A path is represented as an array of literals, which are integers in - {0, 1, 2}; 0 represents an else arc out of a node, 1 represents a then arc - out of a node, and 2 stands for the absence of a node. - The size of the array equals the number of variables in the manager at - the time Cudd_zddFirstCube is called.

              - The paths that end in the empty terminal are not enumerated.] - - SideEffects [The first path is returned as a side effect.] - - SeeAlso [Cudd_zddForeachPath Cudd_zddNextPath Cudd_GenFree - Cudd_IsGenEmpty] - -******************************************************************************/ -DdGen * -Cudd_zddFirstPath( - DdManager * zdd, - DdNode * f, - int ** path) -{ - DdGen *gen; - DdNode *top, *next, *prev; - int i; - int nvars; - - /* Sanity Check. */ - if (zdd == NULL || f == NULL) return(NULL); - - /* Allocate generator an initialize it. */ - gen = ALLOC(DdGen,1); - if (gen == NULL) { - zdd->errorCode = CUDD_MEMORY_OUT; - return(NULL); - } - - gen->manager = zdd; - gen->type = CUDD_GEN_ZDD_PATHS; - gen->status = CUDD_GEN_EMPTY; - gen->gen.cubes.cube = NULL; - gen->gen.cubes.value = DD_ZERO_VAL; - gen->stack.sp = 0; - gen->stack.stack = NULL; - gen->node = NULL; - - nvars = zdd->sizeZ; - gen->gen.cubes.cube = ALLOC(int,nvars); - if (gen->gen.cubes.cube == NULL) { - zdd->errorCode = CUDD_MEMORY_OUT; - FREE(gen); - return(NULL); - } - for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2; - - /* The maximum stack depth is one plus the number of variables. - ** because a path may have nodes at all levels, including the - ** constant level. - */ - gen->stack.stack = ALLOC(DdNode *, nvars+1); - if (gen->stack.stack == NULL) { - zdd->errorCode = CUDD_MEMORY_OUT; - FREE(gen->gen.cubes.cube); - FREE(gen); - return(NULL); - } - for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL; - - /* Find the first path of the ZDD. */ - gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++; - - while (1) { - top = gen->stack.stack[gen->stack.sp-1]; - if (!cuddIsConstant(top)) { - /* Take the else branch first. */ - gen->gen.cubes.cube[top->index] = 0; - next = cuddE(top); - gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; - } else if (top == DD_ZERO(zdd)) { - /* Backtrack. */ - while (1) { - if (gen->stack.sp == 1) { - /* The current node has no predecessor. */ - gen->status = CUDD_GEN_EMPTY; - gen->stack.sp--; - goto done; - } - prev = gen->stack.stack[gen->stack.sp-2]; - next = cuddT(prev); - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[prev->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[prev->index] = 2; - gen->stack.sp--; - top = gen->stack.stack[gen->stack.sp-1]; - } - } else { - gen->status = CUDD_GEN_NONEMPTY; - gen->gen.cubes.value = cuddV(top); - goto done; - } - } - -done: - *path = gen->gen.cubes.cube; - return(gen); - -} /* end of Cudd_zddFirstPath */ - - -/**Function******************************************************************** - - Synopsis [Generates the next path of a ZDD.] - - Description [Generates the next path of a ZDD onset, - using generator gen. Returns 0 if the enumeration is completed; 1 - otherwise.] - - SideEffects [The path is returned as a side effect. The - generator is modified.] - - SeeAlso [Cudd_zddForeachPath Cudd_zddFirstPath Cudd_GenFree - Cudd_IsGenEmpty] - -******************************************************************************/ -int -Cudd_zddNextPath( - DdGen * gen, - int ** path) -{ - DdNode *top, *next, *prev; - DdManager *zdd = gen->manager; - - /* Backtrack from previously reached terminal node. */ - while (1) { - if (gen->stack.sp == 1) { - /* The current node has no predecessor. */ - gen->status = CUDD_GEN_EMPTY; - gen->stack.sp--; - goto done; - } - top = gen->stack.stack[gen->stack.sp-1]; - prev = gen->stack.stack[gen->stack.sp-2]; - next = cuddT(prev); - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[prev->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[prev->index] = 2; - gen->stack.sp--; - } - - while (1) { - top = gen->stack.stack[gen->stack.sp-1]; - if (!cuddIsConstant(top)) { - /* Take the else branch first. */ - gen->gen.cubes.cube[top->index] = 0; - next = cuddE(top); - gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++; - } else if (top == DD_ZERO(zdd)) { - /* Backtrack. */ - while (1) { - if (gen->stack.sp == 1) { - /* The current node has no predecessor. */ - gen->status = CUDD_GEN_EMPTY; - gen->stack.sp--; - goto done; - } - prev = gen->stack.stack[gen->stack.sp-2]; - next = cuddT(prev); - if (next != top) { /* follow the then branch next */ - gen->gen.cubes.cube[prev->index] = 1; - gen->stack.stack[gen->stack.sp-1] = next; - break; - } - /* Pop the stack and try again. */ - gen->gen.cubes.cube[prev->index] = 2; - gen->stack.sp--; - top = gen->stack.stack[gen->stack.sp-1]; - } - } else { - gen->status = CUDD_GEN_NONEMPTY; - gen->gen.cubes.value = cuddV(top); - goto done; - } - } - -done: - if (gen->status == CUDD_GEN_EMPTY) return(0); - *path = gen->gen.cubes.cube; - return(1); - -} /* end of Cudd_zddNextPath */ - - -/**Function******************************************************************** - - Synopsis [Converts a path of a ZDD representing a cover to a string.] - - Description [Converts a path of a ZDD representing a cover to a - string. The string represents an implicant of the cover. The path - is typically produced by Cudd_zddForeachPath. Returns a pointer to - the string if successful; NULL otherwise. If the str input is NULL, - it allocates a new string. The string passed to this function must - have enough room for all variables and for the terminator.] - - SideEffects [None] - - SeeAlso [Cudd_zddForeachPath] - -******************************************************************************/ -char * -Cudd_zddCoverPathToString( - DdManager *zdd /* DD manager */, - int *path /* path of ZDD representing a cover */, - char *str /* pointer to string to use if != NULL */ - ) -{ - int nvars = zdd->sizeZ; - int i; - char *res; - - if (nvars & 1) return(NULL); - nvars >>= 1; - if (str == NULL) { - res = ALLOC(char, nvars+1); - if (res == NULL) return(NULL); - } else { - res = str; - } - for (i = 0; i < nvars; i++) { - int v = (path[2*i] << 2) | path[2*i+1]; - switch (v) { - case 0: - case 2: - case 8: - case 10: - res[i] = '-'; - break; - case 1: - case 9: - res[i] = '0'; - break; - case 4: - case 6: - res[i] = '1'; - break; - default: - res[i] = '?'; - } - } - res[nvars] = 0; - - return(res); - -} /* end of Cudd_zddCoverPathToString */ - - -/**Function******************************************************************** - - Synopsis [Writes a dot file representing the argument ZDDs.] - - Description [Writes a file representing the argument ZDDs in a format - suitable for the graph drawing program dot. - It returns 1 in case of success; 0 otherwise (e.g., out-of-memory, - file system full). - Cudd_zddDumpDot does not close the file: This is the caller - responsibility. Cudd_zddDumpDot uses a minimal unique subset of the - hexadecimal address of a node as name for it. - If the argument inames is non-null, it is assumed to hold the pointers - to the names of the inputs. Similarly for onames. - Cudd_zddDumpDot uses the following convention to draw arcs: -

                -
              • solid line: THEN arcs; -
              • dashed line: ELSE arcs. -
              - The dot options are chosen so that the drawing fits on a letter-size - sheet. - ] - - SideEffects [None] - - SeeAlso [Cudd_DumpDot Cudd_zddPrintDebug] - -******************************************************************************/ -int -Cudd_zddDumpDot( - DdManager * dd /* manager */, - int n /* number of output nodes to be dumped */, - DdNode ** f /* array of output nodes to be dumped */, - char ** inames /* array of input names (or NULL) */, - char ** onames /* array of output names (or NULL) */, - FILE * fp /* pointer to the dump file */) -{ - DdNode *support = NULL; - DdNode *scan; - int *sorted = NULL; - int nvars = dd->sizeZ; - st_table *visited = NULL; - st_generator *gen; - int retval; - int i, j; - int slots; - DdNodePtr *nodelist; - long refAddr, diff, mask; - - /* Build a bit array with the support of f. */ - sorted = ALLOC(int,nvars); - if (sorted == NULL) { - dd->errorCode = CUDD_MEMORY_OUT; - goto failure; - } - for (i = 0; i < nvars; i++) sorted[i] = 0; - - /* Take the union of the supports of each output function. */ - for (i = 0; i < n; i++) { - support = Cudd_Support(dd,f[i]); - if (support == NULL) goto failure; - cuddRef(support); - scan = support; - while (!cuddIsConstant(scan)) { - sorted[scan->index] = 1; - scan = cuddT(scan); - } - Cudd_RecursiveDeref(dd,support); - } - support = NULL; /* so that we do not try to free it in case of failure */ - - /* Initialize symbol table for visited nodes. */ - visited = st_init_table(st_ptrcmp, st_ptrhash); - if (visited == NULL) goto failure; - - /* Collect all the nodes of this DD in the symbol table. */ - for (i = 0; i < n; i++) { - retval = cuddCollectNodes(f[i],visited); - if (retval == 0) goto failure; - } - - /* Find how many most significant hex digits are identical - ** in the addresses of all the nodes. Build a mask based - ** on this knowledge, so that digits that carry no information - ** will not be printed. This is done in two steps. - ** 1. We scan the symbol table to find the bits that differ - ** in at least 2 addresses. - ** 2. We choose one of the possible masks. There are 8 possible - ** masks for 32-bit integer, and 16 possible masks for 64-bit - ** integers. - */ - - /* Find the bits that are different. */ - refAddr = (long) f[0]; - diff = 0; - gen = st_init_gen(visited); - while (st_gen(gen, (char **) &scan, NULL)) { - diff |= refAddr ^ (long) scan; - } - st_free_gen(gen); - - /* Choose the mask. */ - for (i = 0; (unsigned) i < 8 * sizeof(long); i += 4) { - mask = (1 << i) - 1; - if (diff <= mask) break; - } - - /* Write the header and the global attributes. */ - retval = fprintf(fp,"digraph \"ZDD\" {\n"); - if (retval == EOF) return(0); - retval = fprintf(fp, - "size = \"7.5,10\"\ncenter = true;\nedge [dir = none];\n"); - if (retval == EOF) return(0); - - /* Write the input name subgraph by scanning the support array. */ - retval = fprintf(fp,"{ node [shape = plaintext];\n"); - if (retval == EOF) goto failure; - retval = fprintf(fp," edge [style = invis];\n"); - if (retval == EOF) goto failure; - /* We use a name ("CONST NODES") with an embedded blank, because - ** it is unlikely to appear as an input name. - */ - retval = fprintf(fp," \"CONST NODES\" [style = invis];\n"); - if (retval == EOF) goto failure; - for (i = 0; i < nvars; i++) { - if (sorted[dd->invpermZ[i]]) { - if (inames == NULL) { - retval = fprintf(fp,"\" %d \" -> ", dd->invpermZ[i]); - } else { - retval = fprintf(fp,"\" %s \" -> ", inames[dd->invpermZ[i]]); - } - if (retval == EOF) goto failure; - } - } - retval = fprintf(fp,"\"CONST NODES\"; \n}\n"); - if (retval == EOF) goto failure; - - /* Write the output node subgraph. */ - retval = fprintf(fp,"{ rank = same; node [shape = box]; edge [style = invis];\n"); - if (retval == EOF) goto failure; - for (i = 0; i < n; i++) { - if (onames == NULL) { - retval = fprintf(fp,"\"F%d\"", i); - } else { - retval = fprintf(fp,"\" %s \"", onames[i]); - } - if (retval == EOF) goto failure; - if (i == n - 1) { - retval = fprintf(fp,"; }\n"); - } else { - retval = fprintf(fp," -> "); - } - if (retval == EOF) goto failure; - } - - /* Write rank info: All nodes with the same index have the same rank. */ - for (i = 0; i < nvars; i++) { - if (sorted[dd->invpermZ[i]]) { - retval = fprintf(fp,"{ rank = same; "); - if (retval == EOF) goto failure; - if (inames == NULL) { - retval = fprintf(fp,"\" %d \";\n", dd->invpermZ[i]); - } else { - retval = fprintf(fp,"\" %s \";\n", inames[dd->invpermZ[i]]); - } - if (retval == EOF) goto failure; - nodelist = dd->subtableZ[i].nodelist; - slots = dd->subtableZ[i].slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (st_is_member(visited,(char *) scan)) { - retval = fprintf(fp,"\"%lx\";\n", (mask & (long) scan) / sizeof(DdNode)); - if (retval == EOF) goto failure; - } - scan = scan->next; - } - } - retval = fprintf(fp,"}\n"); - if (retval == EOF) goto failure; - } - } - - /* All constants have the same rank. */ - retval = fprintf(fp, - "{ rank = same; \"CONST NODES\";\n{ node [shape = box]; "); - if (retval == EOF) goto failure; - nodelist = dd->constants.nodelist; - slots = dd->constants.slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (st_is_member(visited,(char *) scan)) { - retval = fprintf(fp,"\"%lx\";\n", (mask & (long) scan) / sizeof(DdNode)); - if (retval == EOF) goto failure; - } - scan = scan->next; - } - } - retval = fprintf(fp,"}\n}\n"); - if (retval == EOF) goto failure; - - /* Write edge info. */ - /* Edges from the output nodes. */ - for (i = 0; i < n; i++) { - if (onames == NULL) { - retval = fprintf(fp,"\"F%d\"", i); - } else { - retval = fprintf(fp,"\" %s \"", onames[i]); - } - if (retval == EOF) goto failure; - retval = fprintf(fp," -> \"%lx\" [style = solid];\n", - (mask & (long) f[i]) / sizeof(DdNode)); - if (retval == EOF) goto failure; - } - - /* Edges from internal nodes. */ - for (i = 0; i < nvars; i++) { - if (sorted[dd->invpermZ[i]]) { - nodelist = dd->subtableZ[i].nodelist; - slots = dd->subtableZ[i].slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (st_is_member(visited,(char *) scan)) { - retval = fprintf(fp, - "\"%lx\" -> \"%lx\";\n", - (mask & (long) scan) / sizeof(DdNode), - (mask & (long) cuddT(scan)) / sizeof(DdNode)); - if (retval == EOF) goto failure; - retval = fprintf(fp, - "\"%lx\" -> \"%lx\" [style = dashed];\n", - (mask & (long) scan) / sizeof(DdNode), - (mask & (long) cuddE(scan)) / sizeof(DdNode)); - if (retval == EOF) goto failure; - } - scan = scan->next; - } - } - } - } - - /* Write constant labels. */ - nodelist = dd->constants.nodelist; - slots = dd->constants.slots; - for (j = 0; j < slots; j++) { - scan = nodelist[j]; - while (scan != NULL) { - if (st_is_member(visited,(char *) scan)) { - retval = fprintf(fp,"\"%lx\" [label = \"%g\"];\n", - (mask & (long) scan) / sizeof(DdNode), cuddV(scan)); - if (retval == EOF) goto failure; - } - scan = scan->next; - } - } - - /* Write trailer and return. */ - retval = fprintf(fp,"}\n"); - if (retval == EOF) goto failure; - - st_free_table(visited); - FREE(sorted); - return(1); - -failure: - if (sorted != NULL) FREE(sorted); - if (support != NULL) Cudd_RecursiveDeref(dd,support); - if (visited != NULL) st_free_table(visited); - return(0); - -} /* end of Cudd_zddDumpBlif */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints a ZDD to the standard output. One line per node is - printed.] - - Description [Prints a ZDD to the standard output. One line per node is - printed. Returns 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_zddPrintDebug] - -******************************************************************************/ -int -cuddZddP( - DdManager * zdd, - DdNode * f) -{ - int retval; - st_table *table = st_init_table(st_ptrcmp, st_ptrhash); - - if (table == NULL) return(0); - - retval = zp2(zdd, f, table); - st_free_table(table); - (void) fputc('\n', zdd->out); - return(retval); - -} /* end of cuddZddP */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of cuddZddP.] - - Description [Performs the recursive step of cuddZddP. Returns 1 in - case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -zp2( - DdManager * zdd, - DdNode * f, - st_table * t) -{ - DdNode *n; - int T, E; - DdNode *base = DD_ONE(zdd); - - if (f == NULL) - return(0); - - if (Cudd_IsConstant(f)) { - (void)fprintf(zdd->out, "ID = %d\n", (f == base)); - return(1); - } - if (st_is_member(t, (char *)f) == 1) - return(1); - - if (st_insert(t, (char *) f, NULL) == ST_OUT_OF_MEM) - return(0); - -#if SIZEOF_VOID_P == 8 - (void) fprintf(zdd->out, "ID = 0x%lx\tindex = %d\tr = %d\t", - (unsigned long)f / (unsigned long) sizeof(DdNode), f->index, f->ref); -#else - (void) fprintf(zdd->out, "ID = 0x%x\tindex = %d\tr = %d\t", - (unsigned)f / (unsigned) sizeof(DdNode), f->index, f->ref); -#endif - - n = cuddT(f); - if (Cudd_IsConstant(n)) { - (void) fprintf(zdd->out, "T = %d\t\t", (n == base)); - T = 1; - } else { -#if SIZEOF_VOID_P == 8 - (void) fprintf(zdd->out, "T = 0x%lx\t", (unsigned long) n / - (unsigned long) sizeof(DdNode)); -#else - (void) fprintf(zdd->out, "T = 0x%x\t", (unsigned) n / (unsigned) sizeof(DdNode)); -#endif - T = 0; - } - - n = cuddE(f); - if (Cudd_IsConstant(n)) { - (void) fprintf(zdd->out, "E = %d\n", (n == base)); - E = 1; - } else { -#if SIZEOF_VOID_P == 8 - (void) fprintf(zdd->out, "E = 0x%lx\n", (unsigned long) n / - (unsigned long) sizeof(DdNode)); -#else - (void) fprintf(zdd->out, "E = 0x%x\n", (unsigned) n / (unsigned) sizeof(DdNode)); -#endif - E = 0; - } - - if (E == 0) - if (zp2(zdd, cuddE(f), t) == 0) return(0); - if (T == 0) - if (zp2(zdd, cuddT(f), t) == 0) return(0); - return(1); - -} /* end of zp2 */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddPrintMinterm.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -zdd_print_minterm_aux( - DdManager * zdd /* manager */, - DdNode * node /* current node */, - int level /* depth in the recursion */, - int * list /* current recursion path */) -{ - DdNode *Nv, *Nnv; - int i, v; - DdNode *base = DD_ONE(zdd); - - if (Cudd_IsConstant(node)) { - if (node == base) { - /* Check for missing variable. */ - if (level != zdd->sizeZ) { - list[zdd->invpermZ[level]] = 0; - zdd_print_minterm_aux(zdd, node, level + 1, list); - return; - } - /* Terminal case: Print one cube based on the current recursion - ** path. - */ - for (i = 0; i < zdd->sizeZ; i++) { - v = list[i]; - if (v == 0) - (void) fprintf(zdd->out,"0"); - else if (v == 1) - (void) fprintf(zdd->out,"1"); - else if (v == 3) - (void) fprintf(zdd->out,"@"); /* should never happen */ - else - (void) fprintf(zdd->out,"-"); - } - (void) fprintf(zdd->out," 1\n"); - } - } else { - /* Check for missing variable. */ - if (level != cuddIZ(zdd,node->index)) { - list[zdd->invpermZ[level]] = 0; - zdd_print_minterm_aux(zdd, node, level + 1, list); - return; - } - - Nnv = cuddE(node); - Nv = cuddT(node); - if (Nv == Nnv) { - list[node->index] = 2; - zdd_print_minterm_aux(zdd, Nnv, level + 1, list); - return; - } - - list[node->index] = 1; - zdd_print_minterm_aux(zdd, Nv, level + 1, list); - list[node->index] = 0; - zdd_print_minterm_aux(zdd, Nnv, level + 1, list); - } - return; - -} /* end of zdd_print_minterm_aux */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_zddPrintCover.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -zddPrintCoverAux( - DdManager * zdd /* manager */, - DdNode * node /* current node */, - int level /* depth in the recursion */, - int * list /* current recursion path */) -{ - DdNode *Nv, *Nnv; - int i, v; - DdNode *base = DD_ONE(zdd); - - if (Cudd_IsConstant(node)) { - if (node == base) { - /* Check for missing variable. */ - if (level != zdd->sizeZ) { - list[zdd->invpermZ[level]] = 0; - zddPrintCoverAux(zdd, node, level + 1, list); - return; - } - /* Terminal case: Print one cube based on the current recursion - ** path. - */ - for (i = 0; i < zdd->sizeZ; i += 2) { - v = list[i] * 4 + list[i+1]; - if (v == 0) - (void) putc('-',zdd->out); - else if (v == 4) - (void) putc('1',zdd->out); - else if (v == 1) - (void) putc('0',zdd->out); - else - (void) putc('@',zdd->out); /* should never happen */ - } - (void) fprintf(zdd->out," 1\n"); - } - } else { - /* Check for missing variable. */ - if (level != cuddIZ(zdd,node->index)) { - list[zdd->invpermZ[level]] = 0; - zddPrintCoverAux(zdd, node, level + 1, list); - return; - } - - Nnv = cuddE(node); - Nv = cuddT(node); - if (Nv == Nnv) { - list[node->index] = 2; - zddPrintCoverAux(zdd, Nnv, level + 1, list); - return; - } - - list[node->index] = 1; - zddPrintCoverAux(zdd, Nv, level + 1, list); - list[node->index] = 0; - zddPrintCoverAux(zdd, Nnv, level + 1, list); - } - return; - -} /* end of zddPrintCoverAux */ diff --git a/src/bdd/cudd/module.make b/src/bdd/cudd/module.make deleted file mode 100644 index c526a50e..00000000 --- a/src/bdd/cudd/module.make +++ /dev/null @@ -1,61 +0,0 @@ -SRC += src/bdd/cudd/cuddAPI.c \ - src/bdd/cudd/cuddAddAbs.c \ - src/bdd/cudd/cuddAddApply.c \ - src/bdd/cudd/cuddAddFind.c \ - src/bdd/cudd/cuddAddInv.c \ - src/bdd/cudd/cuddAddIte.c \ - src/bdd/cudd/cuddAddNeg.c \ - src/bdd/cudd/cuddAddWalsh.c \ - src/bdd/cudd/cuddAndAbs.c \ - src/bdd/cudd/cuddAnneal.c \ - src/bdd/cudd/cuddApa.c \ - src/bdd/cudd/cuddApprox.c \ - src/bdd/cudd/cuddBddAbs.c \ - src/bdd/cudd/cuddBddCorr.c \ - src/bdd/cudd/cuddBddIte.c \ - src/bdd/cudd/cuddBridge.c \ - src/bdd/cudd/cuddCache.c \ - src/bdd/cudd/cuddCheck.c \ - src/bdd/cudd/cuddClip.c \ - src/bdd/cudd/cuddCof.c \ - src/bdd/cudd/cuddCompose.c \ - src/bdd/cudd/cuddDecomp.c \ - src/bdd/cudd/cuddEssent.c \ - src/bdd/cudd/cuddExact.c \ - src/bdd/cudd/cuddExport.c \ - src/bdd/cudd/cuddGenCof.c \ - src/bdd/cudd/cuddGenetic.c \ - src/bdd/cudd/cuddGroup.c \ - src/bdd/cudd/cuddHarwell.c \ - src/bdd/cudd/cuddInit.c \ - src/bdd/cudd/cuddInteract.c \ - src/bdd/cudd/cuddLCache.c \ - src/bdd/cudd/cuddLevelQ.c \ - src/bdd/cudd/cuddLinear.c \ - src/bdd/cudd/cuddLiteral.c \ - src/bdd/cudd/cuddMatMult.c \ - src/bdd/cudd/cuddPriority.c \ - src/bdd/cudd/cuddRead.c \ - src/bdd/cudd/cuddRef.c \ - src/bdd/cudd/cuddReorder.c \ - src/bdd/cudd/cuddSat.c \ - src/bdd/cudd/cuddSign.c \ - src/bdd/cudd/cuddSolve.c \ - src/bdd/cudd/cuddSplit.c \ - src/bdd/cudd/cuddSubsetHB.c \ - src/bdd/cudd/cuddSubsetSP.c \ - src/bdd/cudd/cuddSymmetry.c \ - src/bdd/cudd/cuddTable.c \ - src/bdd/cudd/cuddUtil.c \ - src/bdd/cudd/cuddWindow.c \ - src/bdd/cudd/cuddZddCount.c \ - src/bdd/cudd/cuddZddFuncs.c \ - src/bdd/cudd/cuddZddGroup.c \ - src/bdd/cudd/cuddZddIsop.c \ - src/bdd/cudd/cuddZddLin.c \ - src/bdd/cudd/cuddZddMisc.c \ - src/bdd/cudd/cuddZddPort.c \ - src/bdd/cudd/cuddZddReord.c \ - src/bdd/cudd/cuddZddSetop.c \ - src/bdd/cudd/cuddZddSymm.c \ - src/bdd/cudd/cuddZddUtil.c diff --git a/src/bdd/cudd/r7x8.1.mat b/src/bdd/cudd/r7x8.1.mat deleted file mode 100644 index b0dd0a0a..00000000 --- a/src/bdd/cudd/r7x8.1.mat +++ /dev/null @@ -1,53 +0,0 @@ -7 9 -0 0 1 -0 1 1 -0 2 1 -0 3 4 -0 4 3 -0 5 3 -0 6 3 -0 8 3 -1 0 4 -1 1 3 -1 2 2 -1 3 4 -1 4 1 -1 5 2 -1 6 4 -1 8 3 -2 0 1 -2 1 1 -2 2 4 -2 4 2 -2 5 3 -2 6 3 -2 8 3 -3 0 2 -3 1 1 -3 3 4 -3 4 4 -3 5 1 -3 8 1 -4 0 2 -4 1 3 -4 2 2 -4 3 4 -4 4 1 -4 5 1 -4 6 2 -4 8 2 -5 0 3 -5 1 3 -5 2 4 -5 3 4 -5 4 1 -5 5 3 -5 6 3 -5 8 4 -6 1 1 -6 2 1 -6 3 4 -6 4 2 -6 5 4 -6 6 4 -6 8 2 diff --git a/src/bdd/cudd/testcudd.c b/src/bdd/cudd/testcudd.c deleted file mode 100644 index d8affadc..00000000 --- a/src/bdd/cudd/testcudd.c +++ /dev/null @@ -1,988 +0,0 @@ -/**CFile*********************************************************************** - - FileName [testcudd.c] - - PackageName [cudd] - - Synopsis [Sanity check tests for some CUDD functions.] - - Description [testcudd reads a matrix with real coefficients and - transforms it into an ADD. It then performs various operations on - the ADD and on the BDD corresponding to the ADD pattern. Finally, - testcudd tests functions relate to Walsh matrices and matrix - multiplication.] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "cuddInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define TESTCUDD_VERSION "TestCudd Version #1.0, Release date 3/17/01" - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] DD_UNUSED = "$Id: testcudd.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $"; -#endif - -static char *onames[] = { "C", "M" }; /* names of functions to be dumped */ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static void usage ARGS((char * prog)); -static FILE *open_file ARGS((char *filename, char *mode)); -static int testIterators ARGS((DdManager *dd, DdNode *M, DdNode *C, int pr)); -static int testXor ARGS((DdManager *dd, DdNode *f, int pr, int nvars)); -static int testHamming ARGS((DdManager *dd, DdNode *f, int pr, int nvars)); -static int testWalsh ARGS((DdManager *dd, int N, int cmu, int approach, int pr)); - -/**AutomaticEnd***************************************************************/ - - -/**Function******************************************************************** - - Synopsis [Main function for testcudd.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -main(int argc, char **argv) -{ - FILE *fp; /* pointer to input file */ - char *file = ""; /* input file name */ - FILE *dfp = NULL; /* pointer to dump file */ - char *dfile; /* file for DD dump */ - DdNode *dfunc[2]; /* addresses of the functions to be dumped */ - DdManager *dd; /* pointer to DD manager */ - DdNode *one, *zero; /* fast access to constant functions */ - DdNode *M; - DdNode **x; /* pointers to variables */ - DdNode **y; /* pointers to variables */ - DdNode **xn; /* complements of row variables */ - DdNode **yn_; /* complements of column variables */ - DdNode **xvars; - DdNode **yvars; - DdNode *C; /* result of converting from ADD to BDD */ - DdNode *ess; /* cube of essential variables */ - DdNode *shortP; /* BDD cube of shortest path */ - DdNode *largest; /* BDD of largest cube */ - DdNode *shortA; /* ADD cube of shortest path */ - DdNode *constN; /* value returned by evaluation of ADD */ - DdNode *ycube; /* cube of the negated y vars for c-proj */ - DdNode *CP; /* C-Projection of C */ - DdNode *CPr; /* C-Selection of C */ - int length; /* length of the shortest path */ - int nx; /* number of variables */ - int ny; - int maxnx; - int maxny; - int m; - int n; - int N; - int cmu; /* use CMU multiplication */ - int pr; /* verbose printout level */ - int harwell; - int multiple; /* read multiple matrices */ - int ok; - int c; /* variable to read in options */ - int approach; /* reordering approach */ - int autodyn; /* automatic reordering */ - int groupcheck; /* option for group sifting */ - int profile; /* print heap profile if != 0 */ - int keepperm; /* keep track of permutation */ - int clearcache; /* clear the cache after each matrix */ - int blifOrDot; /* dump format: 0 -> dot, 1 -> blif, ... */ - int retval; /* return value */ - int i; /* loop index */ - long startTime; /* initial time */ - long lapTime; - int size; - unsigned int cacheSize, maxMemory; - unsigned int nvars,nslots; - - startTime = util_cpu_time(); - - approach = CUDD_REORDER_NONE; - autodyn = 0; - pr = 0; - harwell = 0; - multiple = 0; - profile = 0; - keepperm = 0; - cmu = 0; - N = 4; - nvars = 4; - cacheSize = 127; - maxMemory = 0; - nslots = CUDD_UNIQUE_SLOTS; - clearcache = 0; - groupcheck = CUDD_GROUP_CHECK7; - dfile = NULL; - blifOrDot = 0; /* dot format */ - - /* Parse command line. */ - while ((c = util_getopt(argc, argv, "CDHMPS:a:bcd:g:hkmn:p:v:x:X:")) - != EOF) { - switch(c) { - case 'C': - cmu = 1; - break; - case 'D': - autodyn = 1; - break; - case 'H': - harwell = 1; - break; - case 'M': -#ifdef MNEMOSYNE - (void) mnem_setrecording(0); -#endif - break; - case 'P': - profile = 1; - break; - case 'S': - nslots = atoi(util_optarg); - break; - case 'X': - maxMemory = atoi(util_optarg); - break; - case 'a': - approach = atoi(util_optarg); - break; - case 'b': - blifOrDot = 1; /* blif format */ - break; - case 'c': - clearcache = 1; - break; - case 'd': - dfile = util_optarg; - break; - case 'g': - groupcheck = atoi(util_optarg); - break; - case 'k': - keepperm = 1; - break; - case 'm': - multiple = 1; - break; - case 'n': - N = atoi(util_optarg); - break; - case 'p': - pr = atoi(util_optarg); - break; - case 'v': - nvars = atoi(util_optarg); - break; - case 'x': - cacheSize = atoi(util_optarg); - break; - case 'h': - default: - usage(argv[0]); - break; - } - } - - if (argc - util_optind == 0) { - file = "-"; - } else if (argc - util_optind == 1) { - file = argv[util_optind]; - } else { - usage(argv[0]); - } - if ((approach<0) || (approach>17)) { - (void) fprintf(stderr,"Invalid approach: %d \n",approach); - usage(argv[0]); - } - - if (pr >= 0) { - (void) printf("# %s\n", TESTCUDD_VERSION); - /* Echo command line and arguments. */ - (void) printf("#"); - for (i = 0; i < argc; i++) { - (void) printf(" %s", argv[i]); - } - (void) printf("\n"); - (void) fflush(stdout); - } - - /* Initialize manager and provide easy reference to terminals. */ - dd = Cudd_Init(nvars,0,nslots,cacheSize,maxMemory); - one = DD_ONE(dd); - zero = DD_ZERO(dd); - dd->groupcheck = (Cudd_AggregationType) groupcheck; - if (autodyn) Cudd_AutodynEnable(dd,CUDD_REORDER_SAME); - - /* Open input file. */ - fp = open_file(file, "r"); - - /* Open dump file if requested */ - if (dfile != NULL) { - dfp = open_file(dfile, "w"); - } - - x = y = xn = yn_ = NULL; - do { - /* We want to start anew for every matrix. */ - maxnx = maxny = 0; - nx = maxnx; ny = maxny; - if (pr>0) lapTime = util_cpu_time(); - if (harwell) { - if (pr >= 0) (void) printf(":name: "); - ok = Cudd_addHarwell(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, - &m, &n, 0, 2, 1, 2, pr); - } else { - ok = Cudd_addRead(fp, dd, &M, &x, &y, &xn, &yn_, &nx, &ny, - &m, &n, 0, 2, 1, 2); - if (pr >= 0) - (void) printf(":name: %s: %d rows %d columns\n", file, m, n); - } - if (!ok) { - (void) fprintf(stderr, "Error reading matrix\n"); - exit(1); - } - - if (nx > maxnx) maxnx = nx; - if (ny > maxny) maxny = ny; - - /* Build cube of negated y's. */ - ycube = DD_ONE(dd); - Cudd_Ref(ycube); - for (i = maxny - 1; i >= 0; i--) { - DdNode *tmpp; - tmpp = Cudd_bddAnd(dd,Cudd_Not(dd->vars[y[i]->index]),ycube); - if (tmpp == NULL) exit(2); - Cudd_Ref(tmpp); - Cudd_RecursiveDeref(dd,ycube); - ycube = tmpp; - } - /* Initialize vectors of BDD variables used by priority func. */ - xvars = ALLOC(DdNode *, nx); - if (xvars == NULL) exit(2); - for (i = 0; i < nx; i++) { - xvars[i] = dd->vars[x[i]->index]; - } - yvars = ALLOC(DdNode *, ny); - if (yvars == NULL) exit(2); - for (i = 0; i < ny; i++) { - yvars[i] = dd->vars[y[i]->index]; - } - - /* Clean up */ - for (i=0; i < maxnx; i++) { - Cudd_RecursiveDeref(dd, x[i]); - Cudd_RecursiveDeref(dd, xn[i]); - } - FREE(x); - FREE(xn); - for (i=0; i < maxny; i++) { - Cudd_RecursiveDeref(dd, y[i]); - Cudd_RecursiveDeref(dd, yn_[i]); - } - FREE(y); - FREE(yn_); - - if (pr>0) {(void) printf(":1: M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} - - if (pr>0) (void) printf(":2: time to read the matrix = %s\n", - util_print_time(util_cpu_time() - lapTime)); - - C = Cudd_addBddPattern(dd, M); - if (C == 0) exit(2); - Cudd_Ref(C); - if (pr>0) {(void) printf(":3: C"); Cudd_PrintDebug(dd,C,nx+ny,pr);} - - /* Test iterators. */ - retval = testIterators(dd,M,C,pr); - if (retval == 0) exit(2); - - cuddCacheProfile(dd,stdout); - - /* Test XOR */ - retval = testXor(dd,C,pr,nx+ny); - if (retval == 0) exit(2); - - /* Test Hamming distance functions. */ - retval = testHamming(dd,C,pr,nx+ny); - if (retval == 0) exit(2); - - /* Test selection functions. */ - CP = Cudd_CProjection(dd,C,ycube); - if (CP == NULL) exit(2); - Cudd_Ref(CP); - if (pr>0) {(void) printf("ycube"); Cudd_PrintDebug(dd,ycube,nx+ny,pr);} - if (pr>0) {(void) printf("CP"); Cudd_PrintDebug(dd,CP,nx+ny,pr);} - - if (nx == ny) { - CPr = Cudd_PrioritySelect(dd,C,xvars,yvars,(DdNode **)NULL, - (DdNode *)NULL,ny,Cudd_Xgty); - if (CPr == NULL) exit(2); - Cudd_Ref(CPr); - if (pr>0) {(void) printf(":4: CPr"); Cudd_PrintDebug(dd,CPr,nx+ny,pr);} - if (CP != CPr) { - (void) printf("CP != CPr!\n"); - } - Cudd_RecursiveDeref(dd, CPr); - } - FREE(xvars); FREE(yvars); - - Cudd_RecursiveDeref(dd, CP); - Cudd_RecursiveDeref(dd, ycube); - - /* Test functions for essential variables. */ - ess = Cudd_FindEssential(dd,C); - if (ess == NULL) exit(2); - Cudd_Ref(ess); - if (pr>0) {(void) printf(":4: ess"); Cudd_PrintDebug(dd,ess,nx+ny,pr);} - Cudd_RecursiveDeref(dd, ess); - - /* Test functions for shortest paths. */ - shortP = Cudd_ShortestPath(dd, M, NULL, NULL, &length); - if (shortP == NULL) exit(2); - Cudd_Ref(shortP); - if (pr>0) { - (void) printf(":5: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); - } - /* Test functions for largest cubes. */ - largest = Cudd_LargestCube(dd, Cudd_Not(C), &length); - if (largest == NULL) exit(2); - Cudd_Ref(largest); - if (pr>0) { - (void) printf(":5b: largest"); - Cudd_PrintDebug(dd,largest,nx+ny,pr); - } - Cudd_RecursiveDeref(dd, largest); - - /* Test Cudd_addEvalConst and Cudd_addIteConstant. */ - shortA = Cudd_BddToAdd(dd,shortP); - if (shortA == NULL) exit(2); - Cudd_Ref(shortA); - Cudd_RecursiveDeref(dd, shortP); - constN = Cudd_addEvalConst(dd,shortA,M); - if (constN == DD_NON_CONSTANT) exit(2); - if (Cudd_addIteConstant(dd,shortA,M,constN) != constN) exit(2); - if (pr>0) {(void) printf("The value of M along the chosen shortest path is %g\n", cuddV(constN));} - Cudd_RecursiveDeref(dd, shortA); - - shortP = Cudd_ShortestPath(dd, C, NULL, NULL, &length); - if (shortP == NULL) exit(2); - Cudd_Ref(shortP); - if (pr>0) { - (void) printf(":6: shortP"); Cudd_PrintDebug(dd,shortP,nx+ny,pr); - } - - /* Test Cudd_bddIteConstant and Cudd_bddLeq. */ - if (!Cudd_bddLeq(dd,shortP,C)) exit(2); - if (Cudd_bddIteConstant(dd,Cudd_Not(shortP),one,C) != one) exit(2); - Cudd_RecursiveDeref(dd, shortP); - - if (profile) { - retval = cuddHeapProfile(dd); - } - - size = dd->size; - - if (pr>0) { - (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); - } - - /* Reorder if so requested. */ - if (approach != CUDD_REORDER_NONE) { -#ifndef DD_STATS - retval = Cudd_EnableReorderingReporting(dd); - if (retval == 0) { - (void) fprintf(stderr,"Error reported by Cudd_EnableReorderingReporting\n"); - exit(3); - } -#endif -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); - exit(3); - } - retval = Cudd_CheckKeys(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); - exit(3); - } -#endif - retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5); - if (retval == 0) { - (void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n"); - exit(3); - } -#ifndef DD_STATS - retval = Cudd_DisableReorderingReporting(dd); - if (retval == 0) { - (void) fprintf(stderr,"Error reported by Cudd_DisableReorderingReporting\n"); - exit(3); - } -#endif -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); - exit(3); - } - retval = Cudd_CheckKeys(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_CheckKeys\n"); - exit(3); - } -#endif - if (approach == CUDD_REORDER_SYMM_SIFT || - approach == CUDD_REORDER_SYMM_SIFT_CONV) { - Cudd_SymmProfile(dd,0,dd->size-1); - } - - if (pr>0) { - (void) printf("Average distance: %g\n", Cudd_AverageDistance(dd)); - } - - if (keepperm) { - /* Print variable permutation. */ - (void) printf("Variable Permutation:"); - for (i=0; iinvperm[i]); - } - (void) printf("\n"); - (void) printf("Inverse Permutation:"); - for (i=0; iperm[i]); - } - (void) printf("\n"); - } - - if (pr>0) {(void) printf("M"); Cudd_PrintDebug(dd,M,nx+ny,pr);} - - if (profile) { - retval = cuddHeapProfile(dd); - } - - } - - /* Dump DDs of C and M if so requested. */ - if (dfile != NULL) { - dfunc[0] = C; - dfunc[1] = M; - if (blifOrDot == 1) { - /* Only dump C because blif cannot handle ADDs */ - retval = Cudd_DumpBlif(dd,1,dfunc,NULL,onames,NULL,dfp); - } else { - retval = Cudd_DumpDot(dd,2,dfunc,NULL,onames,dfp); - } - if (retval != 1) { - (void) fprintf(stderr,"abnormal termination\n"); - exit(2); - } - } - - Cudd_RecursiveDeref(dd, C); - Cudd_RecursiveDeref(dd, M); - - if (clearcache) { - if (pr>0) {(void) printf("Clearing the cache... ");} - for (i = dd->cacheSlots - 1; i>=0; i--) { - dd->cache[i].data = NIL(DdNode); - } - if (pr>0) {(void) printf("done\n");} - } - if (pr>0) { - (void) printf("Number of variables = %6d\t",dd->size); - (void) printf("Number of slots = %6d\n",dd->slots); - (void) printf("Number of keys = %6d\t",dd->keys); - (void) printf("Number of min dead = %6d\n",dd->minDead); - } - - } while (multiple && !feof(fp)); - - fclose(fp); - if (dfile != NULL) { - fclose(dfp); - } - - /* Second phase: experiment with Walsh matrices. */ - if (!testWalsh(dd,N,cmu,approach,pr)) { - exit(2); - } - - /* Check variable destruction. */ - assert(cuddDestroySubtables(dd,3)); - assert(Cudd_DebugCheck(dd) == 0); - assert(Cudd_CheckKeys(dd) == 0); - - retval = Cudd_CheckZeroRef(dd); - ok = retval != 0; /* ok == 0 means O.K. */ - if (retval != 0) { - (void) fprintf(stderr, - "%d non-zero DD reference counts after dereferencing\n", retval); - } - - if (pr >= 0) { - (void) Cudd_PrintInfo(dd,stdout); - } - - Cudd_Quit(dd); - -#ifdef MNEMOSYNE - mnem_writestats(); -#endif - - if (pr>0) (void) printf("total time = %s\n", - util_print_time(util_cpu_time() - startTime)); - - if (pr >= 0) util_print_cpu_stats(stdout); - exit(ok); - /* NOTREACHED */ - -} /* end of main */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints usage info for testcudd.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static void -usage(char *prog) -{ - (void) fprintf(stderr, "usage: %s [options] [file]\n", prog); - (void) fprintf(stderr, " -C\t\tuse CMU multiplication algorithm\n"); - (void) fprintf(stderr, " -D\t\tenable automatic dynamic reordering\n"); - (void) fprintf(stderr, " -H\t\tread matrix in Harwell format\n"); - (void) fprintf(stderr, " -M\t\tturns off memory allocation recording\n"); - (void) fprintf(stderr, " -P\t\tprint BDD heap profile\n"); - (void) fprintf(stderr, " -S n\t\tnumber of slots for each subtable\n"); - (void) fprintf(stderr, " -X n\t\ttarget maximum memory in bytes\n"); - (void) fprintf(stderr, " -a n\t\tchoose reordering approach (0-13)\n"); - (void) fprintf(stderr, " \t\t\t0: same as autoMethod\n"); - (void) fprintf(stderr, " \t\t\t1: no reordering (default)\n"); - (void) fprintf(stderr, " \t\t\t2: random\n"); - (void) fprintf(stderr, " \t\t\t3: pivot\n"); - (void) fprintf(stderr, " \t\t\t4: sifting\n"); - (void) fprintf(stderr, " \t\t\t5: sifting to convergence\n"); - (void) fprintf(stderr, " \t\t\t6: symmetric sifting\n"); - (void) fprintf(stderr, " \t\t\t7: symmetric sifting to convergence\n"); - (void) fprintf(stderr, " \t\t\t8-10: window of size 2-4\n"); - (void) fprintf(stderr, " \t\t\t11-13: window of size 2-4 to conv.\n"); - (void) fprintf(stderr, " \t\t\t14: group sifting\n"); - (void) fprintf(stderr, " \t\t\t15: group sifting to convergence\n"); - (void) fprintf(stderr, " \t\t\t16: simulated annealing\n"); - (void) fprintf(stderr, " \t\t\t17: genetic algorithm\n"); - (void) fprintf(stderr, " -b\t\tuse blif as format for dumps\n"); - (void) fprintf(stderr, " -c\t\tclear the cache after each matrix\n"); - (void) fprintf(stderr, " -d file\tdump DDs to file\n"); - (void) fprintf(stderr, " -g\t\tselect aggregation criterion (0,5,7)\n"); - (void) fprintf(stderr, " -h\t\tprints this message\n"); - (void) fprintf(stderr, " -k\t\tprint the variable permutation\n"); - (void) fprintf(stderr, " -m\t\tread multiple matrices (only with -H)\n"); - (void) fprintf(stderr, " -n n\t\tnumber of variables\n"); - (void) fprintf(stderr, " -p n\t\tcontrol verbosity\n"); - (void) fprintf(stderr, " -v n\t\tinitial variables in the unique table\n"); - (void) fprintf(stderr, " -x n\t\tinitial size of the cache\n"); - exit(2); -} /* end of usage */ - - -/**Function******************************************************************** - - Synopsis [Opens a file.] - - Description [Opens a file, or fails with an error message and exits. - Allows '-' as a synonym for standard input.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static FILE * -open_file(char *filename, char *mode) -{ - FILE *fp; - - if (strcmp(filename, "-") == 0) { - return mode[0] == 'r' ? stdin : stdout; - } else if ((fp = fopen(filename, mode)) == NULL) { - perror(filename); - exit(1); - } - return fp; - -} /* end of open_file */ - - -/**Function******************************************************************** - - Synopsis [Tests Walsh matrix multiplication.] - - Description [Tests Walsh matrix multiplication. Return 1 if successful; - 0 otherwise.] - - SideEffects [May create new variables in the manager.] - - SeeAlso [] - -******************************************************************************/ -static int -testWalsh( - DdManager *dd /* manager */, - int N /* number of variables */, - int cmu /* use CMU approach to matrix multiplication */, - int approach /* reordering approach */, - int pr /* verbosity level */) -{ - DdNode *walsh1, *walsh2, *wtw; - DdNode **x, **v, **z; - int i, retval; - DdNode *one = DD_ONE(dd); - DdNode *zero = DD_ZERO(dd); - - if (N > 3) { - x = ALLOC(DdNode *,N); - v = ALLOC(DdNode *,N); - z = ALLOC(DdNode *,N); - - for (i = N-1; i >= 0; i--) { - Cudd_Ref(x[i]=cuddUniqueInter(dd,3*i,one,zero)); - Cudd_Ref(v[i]=cuddUniqueInter(dd,3*i+1,one,zero)); - Cudd_Ref(z[i]=cuddUniqueInter(dd,3*i+2,one,zero)); - } - Cudd_Ref(walsh1 = Cudd_addWalsh(dd,v,z,N)); - if (pr>0) {(void) printf("walsh1"); Cudd_PrintDebug(dd,walsh1,2*N,pr);} - Cudd_Ref(walsh2 = Cudd_addWalsh(dd,x,v,N)); - if (cmu) { - Cudd_Ref(wtw = Cudd_addTimesPlus(dd,walsh2,walsh1,v,N)); - } else { - Cudd_Ref(wtw = Cudd_addMatrixMultiply(dd,walsh2,walsh1,v,N)); - } - if (pr>0) {(void) printf("wtw"); Cudd_PrintDebug(dd,wtw,2*N,pr);} - - if (approach != CUDD_REORDER_NONE) { -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); - return(0); - } -#endif - retval = Cudd_ReduceHeap(dd,(Cudd_ReorderingType)approach,5); - if (retval == 0) { - (void) fprintf(stderr,"Error reported by Cudd_ReduceHeap\n"); - return(0); - } -#ifdef DD_DEBUG - retval = Cudd_DebugCheck(dd); - if (retval != 0) { - (void) fprintf(stderr,"Error reported by Cudd_DebugCheck\n"); - return(0); - } -#endif - if (approach == CUDD_REORDER_SYMM_SIFT || - approach == CUDD_REORDER_SYMM_SIFT_CONV) { - Cudd_SymmProfile(dd,0,dd->size-1); - } - } - /* Clean up. */ - Cudd_RecursiveDeref(dd, wtw); - Cudd_RecursiveDeref(dd, walsh1); - Cudd_RecursiveDeref(dd, walsh2); - for (i=0; i < N; i++) { - Cudd_RecursiveDeref(dd, x[i]); - Cudd_RecursiveDeref(dd, v[i]); - Cudd_RecursiveDeref(dd, z[i]); - } - FREE(x); - FREE(v); - FREE(z); - } - return(1); - -} /* end of testWalsh */ - -/**Function******************************************************************** - - Synopsis [Tests iterators.] - - Description [Tests iterators on cubes and nodes.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -testIterators( - DdManager *dd, - DdNode *M, - DdNode *C, - int pr) -{ - int *cube; - CUDD_VALUE_TYPE value; - DdGen *gen; - int q; - - /* Test iterator for cubes. */ - if (pr>1) { - (void) printf("Testing iterator on cubes:\n"); - Cudd_ForeachCube(dd,M,gen,cube,value) { - for (q = 0; q < dd->size; q++) { - switch (cube[q]) { - case 0: - (void) printf("0"); - break; - case 1: - (void) printf("1"); - break; - case 2: - (void) printf("-"); - break; - default: - (void) printf("?"); - } - } - (void) printf(" %g\n",value); - } - (void) printf("\n"); - } - - if (pr>1) { - (void) printf("Testing prime expansion of cubes:\n"); - if (!Cudd_bddPrintCover(dd,C,C)) return(0); - } - - /* Test iterator on nodes. */ - if (pr>2) { - DdGen *gen; - DdNode *node; - (void) printf("Testing iterator on nodes:\n"); - Cudd_ForeachNode(dd,M,gen,node) { - if (Cudd_IsConstant(node)) { -#if SIZEOF_VOID_P == 8 - (void) printf("ID = 0x%lx\tvalue = %-9g\n", - (unsigned long) node / - (unsigned long) sizeof(DdNode), - Cudd_V(node)); -#else - (void) printf("ID = 0x%x\tvalue = %-9g\n", - (unsigned int) node / - (unsigned int) sizeof(DdNode), - Cudd_V(node)); -#endif - } else { -#if SIZEOF_VOID_P == 8 - (void) printf("ID = 0x%lx\tindex = %d\tr = %d\n", - (unsigned long) node / - (unsigned long) sizeof(DdNode), - node->index, node->ref); -#else - (void) printf("ID = 0x%x\tindex = %d\tr = %d\n", - (unsigned int) node / - (unsigned int) sizeof(DdNode), - node->index, node->ref); -#endif - } - } - (void) printf("\n"); - } - return(1); - -} /* end of testIterators */ - - -/**Function******************************************************************** - - Synopsis [Tests the functions related to the exclusive OR.] - - Description [Tests the functions related to the exclusive OR. It - builds the boolean difference of the given function in three - different ways and checks that the results is the same. Returns 1 if - successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -testXor(DdManager *dd, DdNode *f, int pr, int nvars) -{ - DdNode *f1, *f0, *res1, *res2; - int x; - - /* Extract cofactors w.r.t. mid variable. */ - x = nvars / 2; - f1 = Cudd_Cofactor(dd,f,dd->vars[x]); - if (f1 == NULL) return(0); - Cudd_Ref(f1); - - f0 = Cudd_Cofactor(dd,f,Cudd_Not(dd->vars[x])); - if (f0 == NULL) { - Cudd_RecursiveDeref(dd,f1); - return(0); - } - Cudd_Ref(f0); - - /* Compute XOR of cofactors with ITE. */ - res1 = Cudd_bddIte(dd,f1,Cudd_Not(f0),f0); - if (res1 == NULL) return(0); - Cudd_Ref(res1); - - if (pr>0) {(void) printf("xor1"); Cudd_PrintDebug(dd,res1,nvars,pr);} - - /* Compute XOR of cofactors with XOR. */ - res2 = Cudd_bddXor(dd,f1,f0); - if (res2 == NULL) { - Cudd_RecursiveDeref(dd,res1); - return(0); - } - Cudd_Ref(res2); - - if (res1 != res2) { - if (pr>0) {(void) printf("xor2"); Cudd_PrintDebug(dd,res2,nvars,pr);} - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,res2); - return(0); - } - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,f1); - Cudd_RecursiveDeref(dd,f0); - - /* Compute boolean difference directly. */ - res1 = Cudd_bddBooleanDiff(dd,f,x); - if (res1 == NULL) { - Cudd_RecursiveDeref(dd,res2); - return(0); - } - Cudd_Ref(res1); - - if (res1 != res2) { - if (pr>0) {(void) printf("xor3"); Cudd_PrintDebug(dd,res1,nvars,pr);} - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,res2); - return(0); - } - Cudd_RecursiveDeref(dd,res1); - Cudd_RecursiveDeref(dd,res2); - return(1); - -} /* end of testXor */ - - -/**Function******************************************************************** - - Synopsis [Tests the Hamming distance functions.] - - Description [Tests the Hammming distance functions. Returns - 1 if successful; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -testHamming( - DdManager *dd, - DdNode *f, - int pr, - int nvars) -{ - DdNode **vars, *minBdd, *zero, *scan; - int i; - int d; - int *minterm; - int size = Cudd_ReadSize(dd); - - vars = ALLOC(DdNode *, size); - if (vars == NULL) return(0); - for (i = 0; i < size; i++) { - vars[i] = Cudd_bddIthVar(dd,i); - } - - minBdd = Cudd_bddPickOneMinterm(dd,Cudd_Not(f),vars,size); - Cudd_Ref(minBdd); - if (pr > 0) { - (void) printf("Chosen minterm for Hamming distance test: "); - Cudd_PrintDebug(dd,minBdd,size,pr); - } - - minterm = ALLOC(int,size); - if (minterm == NULL) { - FREE(vars); - Cudd_RecursiveDeref(dd,minBdd); - return(0); - } - scan = minBdd; - zero = Cudd_Not(DD_ONE(dd)); - while (!Cudd_IsConstant(scan)) { - DdNode *R = Cudd_Regular(scan); - DdNode *T = Cudd_T(R); - DdNode *E = Cudd_E(R); - if (R != scan) { - T = Cudd_Not(T); - E = Cudd_Not(E); - } - if (T == zero) { - minterm[R->index] = 0; - scan = E; - } else { - minterm[R->index] = 1; - scan = T; - } - } - Cudd_RecursiveDeref(dd,minBdd); - - d = Cudd_MinHammingDist(dd,f,minterm,size); - - (void) printf("Minimum Hamming distance = %d\n", d); - - FREE(vars); - FREE(minterm); - return(1); - -} /* end of testHamming */ diff --git a/src/bdd/dsd/dsd.h b/src/bdd/dsd/dsd.h deleted file mode 100644 index b73b81ab..00000000 --- a/src/bdd/dsd/dsd.h +++ /dev/null @@ -1,129 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsd.h] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [External declarations of the package. - This fast BDD-based recursive algorithm for simple - (single-output) DSD is based on the following papers: - (1) V. Bertacco and M. Damiani, "Disjunctive decomposition of - logic functions," Proc. ICCAD '97, pp. 78-82. - (2) Y. Matsunaga, "An exact and efficient algorithm for disjunctive - decomposition", Proc. SASIMI '98, pp. 44-50. - The scope of detected decompositions is the same as in the paper: - T. Sasao and M. Matsuura, "DECOMPOS: An integrated system for - functional decomposition," Proc. IWLS '98, pp. 471-477.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsd.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DSD_H__ -#define __DSD_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// TYPEDEF DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dsd_Manager_t_ Dsd_Manager_t; -typedef struct Dsd_Node_t_ Dsd_Node_t; -typedef enum Dsd_Type_t_ Dsd_Type_t; - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// types of DSD nodes -enum Dsd_Type_t_ { - DSD_NODE_NONE = 0, - DSD_NODE_CONST1 = 1, - DSD_NODE_BUF = 2, - DSD_NODE_OR = 3, - DSD_NODE_EXOR = 4, - DSD_NODE_PRIME = 5, -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// complementation and testing for pointers for decomposition entries -#define Dsd_IsComplement(p) (((int)((unsigned long) (p) & 01))) -#define Dsd_Regular(p) ((Dsd_Node_t *)((unsigned long)(p) & ~01)) -#define Dsd_Not(p) ((Dsd_Node_t *)((unsigned long)(p) ^ 01)) -#define Dsd_NotCond(p,c) ((Dsd_Node_t *)((unsigned long)(p) ^ (c))) - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// iterator through the transitions -#define Dsd_NodeForEachChild( Node, Index, Child ) \ - for ( Index = 0; \ - Index < Dsd_NodeReadDecsNum(Node) && \ - ((Child = Dsd_NodeReadDec(Node,Index))>=0); \ - Index++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== dsdApi.c =======================================================*/ -extern Dsd_Type_t Dsd_NodeReadType( Dsd_Node_t * p ); -extern DdNode * Dsd_NodeReadFunc( Dsd_Node_t * p ); -extern DdNode * Dsd_NodeReadSupp( Dsd_Node_t * p ); -extern Dsd_Node_t ** Dsd_NodeReadDecs( Dsd_Node_t * p ); -extern Dsd_Node_t * Dsd_NodeReadDec ( Dsd_Node_t * p, int i ); -extern int Dsd_NodeReadDecsNum( Dsd_Node_t * p ); -extern int Dsd_NodeReadMark( Dsd_Node_t * p ); -extern void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ); -extern DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan ); -extern Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i ); -extern Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ); -extern Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan ); -/*=== dsdMan.c =======================================================*/ -extern Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose ); -extern void Dsd_ManagerStop( Dsd_Manager_t * dMan ); -/*=== dsdProc.c =======================================================*/ -extern void Dsd_Decompose( Dsd_Manager_t * dMan, DdNode ** pbFuncs, int nFuncs ); -extern Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc ); -/*=== dsdTree.c =======================================================*/ -extern void Dsd_TreeNodeGetInfo( Dsd_Manager_t * dMan, int * DepthMax, int * GateSizeMax ); -extern void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax ); -extern int Dsd_TreeGetAigCost( Dsd_Node_t * pNode ); -extern int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * dMan ); -extern int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot ); -extern int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan ); -extern int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot ); -extern int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * dMan, int * pVars ); -extern Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * dMan, int * pnNodes ); -extern Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes ); -extern void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * dMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ); -extern void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ); -/*=== dsdLocal.c =======================================================*/ -extern DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdApi.c b/src/bdd/dsd/dsdApi.c deleted file mode 100644 index d1c90e23..00000000 --- a/src/bdd/dsd/dsdApi.c +++ /dev/null @@ -1,97 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdApi.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Implementation of API functions.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdApi.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [APIs of the DSD node.] - - Description [The node's type can be retrieved by calling - Dsd_NodeReadType(). The type is one of the following: constant 1 node, - the buffer (or the elementary variable), OR gate, EXOR gate, or - PRIME function (a non-DSD-decomposable function with more than two - inputs). The return value of Dsd_NodeReadFunc() is the global function - of the DSD node. The return value of Dsd_NodeReadSupp() is the support - of the global function of the DSD node. The array of DSD nodes - returned by Dsd_NodeReadDecs() is the array of decomposition nodes for - the formal inputs of the given node. The number of decomposition entries - returned by Dsd_NodeReadDecsNum() is the number of formal inputs. - The mark is explained below.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Type_t Dsd_NodeReadType( Dsd_Node_t * p ) { return p->Type; } -DdNode * Dsd_NodeReadFunc( Dsd_Node_t * p ) { return p->G; } -DdNode * Dsd_NodeReadSupp( Dsd_Node_t * p ) { return p->S; } -Dsd_Node_t ** Dsd_NodeReadDecs( Dsd_Node_t * p ) { return p->pDecs; } -Dsd_Node_t * Dsd_NodeReadDec ( Dsd_Node_t * p, int i ) { return p->pDecs[i]; } -int Dsd_NodeReadDecsNum( Dsd_Node_t * p ) { return p->nDecs; } -int Dsd_NodeReadMark( Dsd_Node_t * p ) { return p->Mark; } - -/**Function************************************************************* - - Synopsis [APIs of the DSD node.] - - Description [This API allows the user to set the integer mark in the - given DSD node. The mark is guaranteed to persist as long as the - calls to the decomposition are not performed. In any case, the mark - is useful to associate the node with some temporary information, such - as its number in the DFS ordered list of the DSD nodes or its number in - the BLIF file that it being written.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_NodeSetMark( Dsd_Node_t * p, int Mark ){ p->Mark = Mark; } - -/**Function************************************************************* - - Synopsis [APIs of the DSD manager.] - - Description [Allows the use to get hold of an individual leave of - the DSD tree (Dsd_ManagerReadInput) or an individual root of the - decomposition tree (Dsd_ManagerReadRoot). The root may have the - complemented attribute.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * Dsd_ManagerReadRoot( Dsd_Manager_t * pMan, int i ) { return pMan->pRoots[i]; } -Dsd_Node_t * Dsd_ManagerReadInput( Dsd_Manager_t * pMan, int i ) { return pMan->pInputs[i]; } -Dsd_Node_t * Dsd_ManagerReadConst1( Dsd_Manager_t * pMan ) { return pMan->pConst1; } -DdManager * Dsd_ManagerReadDd( Dsd_Manager_t * pMan ) { return pMan->dd; } - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdCheck.c b/src/bdd/dsd/dsdCheck.c deleted file mode 100644 index 58b824d2..00000000 --- a/src/bdd/dsd/dsdCheck.c +++ /dev/null @@ -1,314 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdCheck.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Procedures to check the identity of root functions.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdCheck.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dsd_Cache_t_ Dds_Cache_t; -typedef struct Dsd_Entry_t_ Dsd_Entry_t; - -struct Dsd_Cache_t_ -{ - Dsd_Entry_t * pTable; - int nTableSize; - int nSuccess; - int nFailure; -}; - -struct Dsd_Entry_t_ -{ - DdNode * bX[5]; -}; - -static Dds_Cache_t * pCache; - -static int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function******************************************************************** - - Synopsis [(Re)allocates the local cache.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Dsd_CheckCacheAllocate( int nEntries ) -{ - int nRequested; - - pCache = ALLOC( Dds_Cache_t, 1 ); - memset( pCache, 0, sizeof(Dds_Cache_t) ); - - // check what is the size of the current cache - nRequested = Cudd_Prime( nEntries ); - if ( pCache->nTableSize != nRequested ) - { // the current size is different - // deallocate the old, allocate the new - if ( pCache->nTableSize ) - Dsd_CheckCacheDeallocate(); - // allocate memory for the hash table - pCache->nTableSize = nRequested; - pCache->pTable = ALLOC( Dsd_Entry_t, nRequested ); - } - // otherwise, there is no need to allocate, just clean - Dsd_CheckCacheClear(); -// printf( "\nThe number of allocated cache entries = %d.\n\n", pCache->nTableSize ); -} - -/**Function******************************************************************** - - Synopsis [Deallocates the local cache.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Dsd_CheckCacheDeallocate() -{ - free( pCache->pTable ); - free( pCache ); -} - -/**Function******************************************************************** - - Synopsis [Clears the local cache.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Dsd_CheckCacheClear() -{ - int i; - for ( i = 0; i < pCache->nTableSize; i++ ) - pCache->pTable[0].bX[0] = NULL; -} - - -/**Function******************************************************************** - - Synopsis [Checks whether it is true that bF1(bC1=0) == bF2(bC2=0).] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ) -{ - int RetValue; -// pCache->nSuccess = 0; -// pCache->nFailure = 0; - RetValue = Dsd_CheckRootFunctionIdentity_rec(dd, bF1, bF2, bC1, bC2); -// printf( "Cache success = %d. Cache failure = %d.\n", pCache->nSuccess, pCache->nFailure ); - return RetValue; -} - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Dsd_CheckRootFunctionIdentity().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Dsd_CheckRootFunctionIdentity_rec( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ) -{ - unsigned HKey; - - // if either bC1 or bC2 is zero, the test is true -// if ( bC1 == b0 || bC2 == b0 ) return 1; - assert( bC1 != b0 ); - assert( bC2 != b0 ); - - // if both bC1 and bC2 are one - perform comparison - if ( bC1 == b1 && bC2 == b1 ) return (int)( bF1 == bF2 ); - - if ( bF1 == b0 ) - return Cudd_bddLeq( dd, bC2, Cudd_Not(bF2) ); - - if ( bF1 == b1 ) - return Cudd_bddLeq( dd, bC2, bF2 ); - - if ( bF2 == b0 ) - return Cudd_bddLeq( dd, bC1, Cudd_Not(bF1) ); - - if ( bF2 == b1 ) - return Cudd_bddLeq( dd, bC1, bF1 ); - - // otherwise, keep expanding - - // check cache -// HKey = _Hash( ((unsigned)bF1), ((unsigned)bF2), ((unsigned)bC1), ((unsigned)bC2) ); - HKey = hashKey4( bF1, bF2, bC1, bC2, pCache->nTableSize ); - if ( pCache->pTable[HKey].bX[0] == bF1 && - pCache->pTable[HKey].bX[1] == bF2 && - pCache->pTable[HKey].bX[2] == bC1 && - pCache->pTable[HKey].bX[3] == bC2 ) - { - pCache->nSuccess++; - return (int)pCache->pTable[HKey].bX[4]; // the last bit records the result (yes/no) - } - else - { - - // determine the top variables - int RetValue; - DdNode * bA[4] = { bF1, bF2, bC1, bC2 }; // arguments - DdNode * bAR[4] = { Cudd_Regular(bF1), Cudd_Regular(bF2), Cudd_Regular(bC1), Cudd_Regular(bC2) }; // regular arguments - int CurLevel[4] = { cuddI(dd,bAR[0]->index), cuddI(dd,bAR[1]->index), cuddI(dd,bAR[2]->index), cuddI(dd,bAR[3]->index) }; - int TopLevel = CUDD_CONST_INDEX; - int i; - DdNode * bE[4], * bT[4]; - DdNode * bF1next, * bF2next, * bC1next, * bC2next; - - pCache->nFailure++; - - // determine the top level - for ( i = 0; i < 4; i++ ) - if ( TopLevel > CurLevel[i] ) - TopLevel = CurLevel[i]; - - // compute the cofactors - for ( i = 0; i < 4; i++ ) - if ( TopLevel == CurLevel[i] ) - { - if ( bA[i] != bAR[i] ) // complemented - { - bE[i] = Cudd_Not(cuddE(bAR[i])); - bT[i] = Cudd_Not(cuddT(bAR[i])); - } - else - { - bE[i] = cuddE(bAR[i]); - bT[i] = cuddT(bAR[i]); - } - } - else - bE[i] = bT[i] = bA[i]; - - // solve subproblems - // three cases are possible - - // (1) the top var belongs to both C1 and C2 - // in this case, any cofactor of F1 and F2 will do, - // as long as the corresponding cofactor of C1 and C2 is not equal to 0 - if ( TopLevel == CurLevel[2] && TopLevel == CurLevel[3] ) - { - if ( bE[2] != b0 ) // C1 - { - bF1next = bE[0]; - bC1next = bE[2]; - } - else - { - bF1next = bT[0]; - bC1next = bT[2]; - } - if ( bE[3] != b0 ) // C2 - { - bF2next = bE[1]; - bC2next = bE[3]; - } - else - { - bF2next = bT[1]; - bC2next = bT[3]; - } - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bF2next, bC1next, bC2next ); - } - // (2) the top var belongs to either C1 or C2 - // in this case normal splitting of cofactors - else if ( TopLevel == CurLevel[2] && TopLevel != CurLevel[3] ) - { - if ( bE[2] != b0 ) // C1 - { - bF1next = bE[0]; - bC1next = bE[2]; - } - else - { - bF1next = bT[0]; - bC1next = bT[2]; - } - // split around this variable - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bE[1], bC1next, bE[3] ); - if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bF1next, bT[1], bC1next, bT[3] ); - } - else if ( TopLevel != CurLevel[2] && TopLevel == CurLevel[3] ) - { - if ( bE[3] != b0 ) // C2 - { - bF2next = bE[1]; - bC2next = bE[3]; - } - else - { - bF2next = bT[1]; - bC2next = bT[3]; - } - // split around this variable - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bF2next, bE[2], bC2next ); - if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bF2next, bT[2], bC2next ); - } - // (3) the top var does not belong to C1 and C2 - // in this case normal splitting of cofactors - else // if ( TopLevel != CurLevel[2] && TopLevel != CurLevel[3] ) - { - // split around this variable - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bE[0], bE[1], bE[2], bE[3] ); - if ( RetValue == 1 ) // test another branch; otherwise, there is no need to test - RetValue = Dsd_CheckRootFunctionIdentity_rec( dd, bT[0], bT[1], bT[2], bT[3] ); - } - - // set cache - for ( i = 0; i < 4; i++ ) - pCache->pTable[HKey].bX[i] = bA[i]; - pCache->pTable[HKey].bX[4] = (DdNode*)RetValue; - - return RetValue; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/dsd/dsdInt.h b/src/bdd/dsd/dsdInt.h deleted file mode 100644 index 62ce7e99..00000000 --- a/src/bdd/dsd/dsdInt.h +++ /dev/null @@ -1,91 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdInt.h] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Internal declarations of the package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdInt.h,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DSD_INT_H__ -#define __DSD_INT_H__ - -#include "extra.h" -#include "dsd.h" - -//////////////////////////////////////////////////////////////////////// -/// TYPEDEF DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef unsigned char byte; - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// DSD manager -struct Dsd_Manager_t_ -{ - DdManager * dd; // the BDD manager - st_table * Table; // the mapping of BDDs into their DEs - int nInputs; // the number of primary inputs - int nRoots; // the number of primary outputs - int nRootsAlloc;// the number of primary outputs - Dsd_Node_t ** pInputs; // the primary input nodes - Dsd_Node_t ** pRoots; // the primary output nodes - Dsd_Node_t * pConst1; // the constant node - int fVerbose; // the verbosity level -}; - -// DSD node -struct Dsd_Node_t_ -{ - Dsd_Type_t Type; // decomposition type - DdNode * G; // function of the node - DdNode * S; // support of this function - Dsd_Node_t ** pDecs; // pointer to structures for formal inputs - int Mark; // the mark used by CASE 4 of disjoint decomposition - short nDecs; // the number of formal inputs - short nVisits; // the counter of visits -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define MAXINPUTS 1000 - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== dsdCheck.c =======================================================*/ -extern void Dsd_CheckCacheAllocate( int nEntries ); -extern void Dsd_CheckCacheDeallocate(); -extern void Dsd_CheckCacheClear(); -extern int Dsd_CheckRootFunctionIdentity( DdManager * dd, DdNode * bF1, DdNode * bF2, DdNode * bC1, DdNode * bC2 ); -/*=== dsdTree.c =======================================================*/ -extern Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum ); -extern void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode ); -extern void Dsd_TreeUnmark( Dsd_Manager_t * dMan ); -extern DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/dsd/dsdLocal.c b/src/bdd/dsd/dsdLocal.c deleted file mode 100644 index 6dd6e7d1..00000000 --- a/src/bdd/dsd/dsdLocal.c +++ /dev/null @@ -1,337 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdLocal.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Deriving the local function of the DSD node.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdLocal.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STATIC VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -static DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bFunc, st_table * pCache, - int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ); -static DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the local function of the DSD node. ] - - Description [The local function is computed using the global function - of the node and the global functions of the formal inputs. The resulting - local function is mapped using the topmost N variables of the manager. - The number of variables N is equal to the number of formal inputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Dsd_TreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode ) -{ - int * pForm2Var; // the mapping of each formal input into its first var - int * pVar2Form; // the mapping of each var into its formal inputs - int i, iVar, iLev, * pPermute; - DdNode ** pbCube0, ** pbCube1; - DdNode * bFunc, * bRes, * bTemp; - st_table * pCache; - - pPermute = ALLOC( int, dd->size ); - pVar2Form = ALLOC( int, dd->size ); - pForm2Var = ALLOC( int, dd->size ); - - pbCube0 = ALLOC( DdNode *, dd->size ); - pbCube1 = ALLOC( DdNode *, dd->size ); - - // remap the global function in such a way that - // the support variables of each formal input are adjacent - iLev = 0; - for ( i = 0; i < pNode->nDecs; i++ ) - { - pForm2Var[i] = dd->invperm[i]; - for ( bTemp = pNode->pDecs[i]->S; bTemp != b1; bTemp = cuddT(bTemp) ) - { - iVar = dd->invperm[iLev]; - pPermute[bTemp->index] = iVar; - pVar2Form[iVar] = i; - iLev++; - } - - // collect the cubes representing each assignment - pbCube0[i] = Extra_bddGetOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); - Cudd_Ref( pbCube0[i] ); - pbCube1[i] = Extra_bddGetOneCube( dd, pNode->pDecs[i]->G ); - Cudd_Ref( pbCube1[i] ); - } - - // remap the function - bFunc = Cudd_bddPermute( dd, pNode->G, pPermute ); Cudd_Ref( bFunc ); - // remap the cube - for ( i = 0; i < pNode->nDecs; i++ ) - { - pbCube0[i] = Cudd_bddPermute( dd, bTemp = pbCube0[i], pPermute ); Cudd_Ref( pbCube0[i] ); - Cudd_RecursiveDeref( dd, bTemp ); - pbCube1[i] = Cudd_bddPermute( dd, bTemp = pbCube1[i], pPermute ); Cudd_Ref( pbCube1[i] ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - // remap the function - pCache = st_init_table(st_ptrcmp,st_ptrhash); - bRes = Extra_dsdRemap( dd, bFunc, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes ); - st_free_table( pCache ); - - Cudd_RecursiveDeref( dd, bFunc ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - Cudd_RecursiveDeref( dd, pbCube0[i] ); - Cudd_RecursiveDeref( dd, pbCube1[i] ); - } -/* -//////////// - // permute the function once again - // in such a way that i-th var stood for i-th formal input - for ( i = 0; i < dd->size; i++ ) - pPermute[i] = -1; - for ( i = 0; i < pNode->nDecs; i++ ) - pPermute[dd->invperm[i]] = i; - bRes = Cudd_bddPermute( dd, bTemp = bRes, pPermute ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); -//////////// -*/ - FREE(pPermute); - FREE(pVar2Form); - FREE(pForm2Var); - FREE(pbCube0); - FREE(pbCube1); - - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_dsdRemap( DdManager * dd, DdNode * bF, st_table * pCache, - int * pVar2Form, int * pForm2Var, DdNode * pbCube0[], DdNode * pbCube1[] ) -{ - DdNode * bFR, * bF0, * bF1; - DdNode * bRes0, * bRes1, * bRes; - int iForm; - - bFR = Cudd_Regular(bF); - if ( cuddIsConstant(bFR) ) - return bF; - - // check the hash-table - if ( bFR->ref != 1 ) - { - if ( st_lookup( pCache, (char *)bF, (char **)&bRes ) ) - return bRes; - } - - // get the formal input - iForm = pVar2Form[bFR->index]; - - // get the nodes pointed to by the cube - bF0 = Extra_bddNodePointedByCube( dd, bF, pbCube0[iForm] ); - bF1 = Extra_bddNodePointedByCube( dd, bF, pbCube1[iForm] ); - - // call recursively for these nodes - bRes0 = Extra_dsdRemap( dd, bF0, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes0 ); - bRes1 = Extra_dsdRemap( dd, bF1, pCache, pVar2Form, pForm2Var, pbCube0, pbCube1 ); Cudd_Ref( bRes1 ); - - // derive the result using ITE - bRes = Cudd_bddIte( dd, dd->vars[ pForm2Var[iForm] ], bRes1, bRes0 ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bRes1 ); - - // add to the hash table - if ( bFR->ref != 1 ) - st_insert( pCache, (char *)bF, (char *)bRes ); - Cudd_Deref( bRes ); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddNodePointedByCube( DdManager * dd, DdNode * bF, DdNode * bC ) -{ - DdNode * bFR, * bCR; - DdNode * bF0, * bF1; - DdNode * bC0, * bC1; - int LevelF, LevelC; - - assert( bC != b0 ); - if ( bC == b1 ) - return bF; - -// bRes = cuddCacheLookup2( dd, Extra_bddNodePointedByCube, bF, bC ); -// if ( bRes ) -// return bRes; - // there is no need for caching because this operation is very fast - // there will no gain reusing the results of this operations - // instead, it will flush CUDD cache of other useful entries - - - bFR = Cudd_Regular( bF ); - bCR = Cudd_Regular( bC ); - assert( !cuddIsConstant( bFR ) ); - - LevelF = dd->perm[bFR->index]; - LevelC = dd->perm[bCR->index]; - - if ( LevelF <= LevelC ) - { - if ( bFR != bF ) - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - } - else - { - bF0 = bF1 = bF; - } - - if ( LevelC <= LevelF ) - { - if ( bCR != bC ) - { - bC0 = Cudd_Not( cuddE(bCR) ); - bC1 = Cudd_Not( cuddT(bCR) ); - } - else - { - bC0 = cuddE(bCR); - bC1 = cuddT(bCR); - } - } - else - { - bC0 = bC1 = bC; - } - - assert( bC0 == b0 || bC1 == b0 ); - if ( bC0 == b0 ) - return Extra_bddNodePointedByCube( dd, bF1, bC1 ); - return Extra_bddNodePointedByCube( dd, bF0, bC0 ); -} - -#if 0 - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * dsdTreeGetPrimeFunction( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) -{ - DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; - int i; - int fAllBuffs = 1; - static int Permute[MAXINPUTS]; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->Type == DT_PRIME ); - - // transform the function of this block to depend on inputs - // corresponding to the formal inputs - - // first, substitute those inputs that have some blocks associated with them - // second, remap the inputs to the top of the manager (then, it is easy to output them) - - // start the function - bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); - // go over all primary inputs - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pNode->pDecs[i]->Type != DT_BUF ) // remap only if it is not the buffer - { - bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); - bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); - Cudd_RecursiveDeref( dd, bCube0 ); - - bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); - bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); - Cudd_RecursiveDeref( dd, bCube1 ); - - Cudd_RecursiveDeref( dd, bNewFunc ); - - // use the variable in the i-th level of the manager -// bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - // use the first variale in the support of the component - bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); - } - - if ( fRemap ) - { - // remap the function to the top of the manager - // remap the function to the first variables of the manager - for ( i = 0; i < pNode->nDecs; i++ ) - // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; - Permute[ pNode->pDecs[i]->S->index ] = i; - - bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - Cudd_Deref( bNewFunc ); - return bNewFunc; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdMan.c b/src/bdd/dsd/dsdMan.c deleted file mode 100644 index 6e43f0f4..00000000 --- a/src/bdd/dsd/dsdMan.c +++ /dev/null @@ -1,114 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdMan.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [APIs of the DSD manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdMan.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// API OF DSD MANAGER /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the DSD manager.] - - Description [Takes the started BDD manager and the maximum support size - of the function to be DSD-decomposed. The manager should have at least as - many variables as there are variables in the support. The functions should - be expressed using the first nSuppSizeMax variables in the manager (these - may be ordered not necessarily on top of the manager).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Manager_t * Dsd_ManagerStart( DdManager * dd, int nSuppMax, int fVerbose ) -{ - Dsd_Manager_t * dMan; - Dsd_Node_t * pNode; - int i; - - assert( nSuppMax <= dd->size ); - - dMan = ALLOC( Dsd_Manager_t, 1 ); - memset( dMan, 0, sizeof(Dsd_Manager_t) ); - dMan->dd = dd; - dMan->nInputs = nSuppMax; - dMan->fVerbose = fVerbose; - dMan->nRoots = 0; - dMan->nRootsAlloc = 50; - dMan->pRoots = (Dsd_Node_t **) malloc( dMan->nRootsAlloc * sizeof(Dsd_Node_t *) ); - dMan->pInputs = (Dsd_Node_t **) malloc( dMan->nInputs * sizeof(Dsd_Node_t *) ); - - // create the primary inputs and insert them into the table - dMan->Table = st_init_table(st_ptrcmp, st_ptrhash); - for ( i = 0; i < dMan->nInputs; i++ ) - { - pNode = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, 0 ); - pNode->G = dd->vars[i]; Cudd_Ref( pNode->G ); - pNode->S = dd->vars[i]; Cudd_Ref( pNode->S ); - st_insert( dMan->Table, (char*)dd->vars[i], (char*)pNode ); - dMan->pInputs[i] = pNode; - } - pNode = Dsd_TreeNodeCreate( DSD_NODE_CONST1, 0, 0 ); - pNode->G = b1; Cudd_Ref( pNode->G ); - pNode->S = b1; Cudd_Ref( pNode->S ); - st_insert( dMan->Table, (char*)b1, (char*)pNode ); - dMan->pConst1 = pNode; - - Dsd_CheckCacheAllocate( 5000 ); - return dMan; -} - -/**Function************************************************************* - - Synopsis [Stops the DSD manager.] - - Description [Stopping the DSD manager automatically derefereces and - deallocates all the DSD nodes that were created during the life time - of the DSD manager. As a result, the user does not need to deref or - deallocate any DSD nodes or trees that are derived and placed in - the manager while it exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_ManagerStop( Dsd_Manager_t * dMan ) -{ - st_generator * gen; - Dsd_Node_t * pNode; - DdNode * bFunc; - // delete the nodes - st_foreach_item( dMan->Table, gen, (char**)&bFunc, (char**)&pNode ) - Dsd_TreeNodeDelete( dMan->dd, Dsd_Regular(pNode) ); - st_free_table(dMan->Table); - free( dMan->pInputs ); - free( dMan->pRoots ); - free( dMan ); - Dsd_CheckCacheDeallocate(); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdProc.c b/src/bdd/dsd/dsdProc.c deleted file mode 100644 index 543ad387..00000000 --- a/src/bdd/dsd/dsdProc.c +++ /dev/null @@ -1,1617 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdProc.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [The core procedures of the package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdProc.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the most important procedures -void dsdKernelDecompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs ); -static Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * F ); - -// additional procedures -static Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity ); -static int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH ); -static void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor ); -static int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall ); - -// list copying -static void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize ); -static void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int Skipped ); - -// debugging procedures -static int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE ); - -//////////////////////////////////////////////////////////////////////// -/// STATIC VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -// the counter of marks -static int s_Mark; - -// debugging flag -static int s_Show = 0; -// temporary var used for debugging -static int Depth = 0; - -static int s_Loops1; -static int s_Loops2; -static int s_Loops3; -static int s_Pivot; -static int s_PivotNo; -static int s_Common; -static int s_CommonNo; - -static int s_Case4Calls; -static int s_Case4CallsSpecial; - -static int s_Case5; -static int s_Loops2Useless; - - -static int s_DecNodesTotal; -static int s_DecNodesUsed; - -// statistical variables -static int s_nDecBlocks; -static int s_nLiterals; -static int s_nExorGates; -static int s_nReusedBlocks; -static int s_nCascades; -static float s_nArea; -static float s_MaxDelay; -static long s_Time; -static int s_nInvertors; -static int s_nPrimeBlocks; - -static int HashSuccess = 0; -static int HashFailure = 0; - -static int s_CacheEntries; - - -//////////////////////////////////////////////////////////////////////// -/// DECOMPOSITION FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs DSD for the array of functions represented by BDDs.] - - Description [This function takes the DSD manager, which should be - previously allocated by the call to Dsd_ManagerStart(). The resulting - DSD tree is stored in the DSD manager (pDsdMan->pRoots, pDsdMan->nRoots). - Access to the tree is through the APIs of the manager. The resulting - tree is a shared DSD DAG for the functions given in the array. For one - function the resulting DAG is always a tree. The root node pointers can - be complemented, as discussed in the literature referred to in "dsd.h". - This procedure can be called repeatedly for different functions. There is - no need to remove the decomposition tree after it is returned, because - the next call to the DSD manager will "recycle" the tree. The user should - not modify or dereference any data associated with the nodes of the - DSD trees (the user can only change the contents of a temporary - mark associated with each node by the calling to Dsd_NodeSetMark()). - All the decomposition trees and intermediate nodes will be removed when - the DSD manager is deallocated at the end by calling Dsd_ManagerStop().] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_Decompose( Dsd_Manager_t * pDsdMan, DdNode ** pbFuncs, int nFuncs ) -{ - DdManager * dd = pDsdMan->dd; - int i; - long clk; - Dsd_Node_t * pTemp; - int SumMaxGateSize = 0; - int nDecOutputs = 0; - int nCBFOutputs = 0; -/* -s_Loops1 = 0; -s_Loops2 = 0; -s_Loops3 = 0; -s_Case4Calls = 0; -s_Case4CallsSpecial = 0; -s_Case5 = 0; -s_Loops2Useless = 0; -*/ - // resize the number of roots in the manager - if ( pDsdMan->nRootsAlloc < nFuncs ) - { - if ( pDsdMan->nRootsAlloc > 0 ) - free( pDsdMan->pRoots ); - pDsdMan->nRootsAlloc = nFuncs; - pDsdMan->pRoots = (Dsd_Node_t **) malloc( pDsdMan->nRootsAlloc * sizeof(Dsd_Node_t *) ); - } - - if ( pDsdMan->fVerbose ) - printf( "\nDecomposability statistics for individual outputs:\n" ); - - // set the counter of decomposition nodes - s_nDecBlocks = 0; - - // perform decomposition for all outputs - clk = clock(); - pDsdMan->nRoots = 0; - s_nCascades = 0; - for ( i = 0; i < nFuncs; i++ ) - { - int nLiteralsPrev; - int nDecBlocksPrev; - int nExorGatesPrev; - int nReusedBlocksPres; - int nCascades; - int MaxBlock; - int nPrimeBlocks; - long clk; - - clk = clock(); - nLiteralsPrev = s_nLiterals; - nDecBlocksPrev = s_nDecBlocks; - nExorGatesPrev = s_nExorGates; - nReusedBlocksPres = s_nReusedBlocks; - nPrimeBlocks = s_nPrimeBlocks; - - pDsdMan->pRoots[ pDsdMan->nRoots++ ] = dsdKernelDecompose_rec( pDsdMan, pbFuncs[i] ); - - Dsd_TreeNodeGetInfoOne( pDsdMan->pRoots[i], &nCascades, &MaxBlock ); - s_nCascades = ddMax( s_nCascades, nCascades ); - pTemp = Dsd_Regular(pDsdMan->pRoots[i]); - if ( pTemp->Type != DSD_NODE_PRIME || pTemp->nDecs != Extra_bddSuppSize(dd,pTemp->S) ) - nDecOutputs++; - if ( MaxBlock < 3 ) - nCBFOutputs++; - SumMaxGateSize += MaxBlock; - - if ( pDsdMan->fVerbose ) - { - printf("#%02d: ", i ); - printf("Ins=%2d. ", Cudd_SupportSize(dd,pbFuncs[i]) ); - printf("Gts=%3d. ", Dsd_TreeCountNonTerminalNodesOne( pDsdMan->pRoots[i] ) ); - printf("Pri=%3d. ", Dsd_TreeCountPrimeNodesOne( pDsdMan->pRoots[i] ) ); - printf("Max=%3d. ", MaxBlock ); - printf("Reuse=%2d. ", s_nReusedBlocks-nReusedBlocksPres ); - printf("Csc=%2d. ", nCascades ); - printf("T= %.2f s. ", (float)(clock()-clk)/(float)(CLOCKS_PER_SEC) ) ; - printf("Bdd=%2d. ", Cudd_DagSize(pbFuncs[i]) ); - printf("\n"); - fflush( stdout ); - } - } - assert( pDsdMan->nRoots == nFuncs ); - - if ( pDsdMan->fVerbose ) - { - printf( "\n" ); - printf( "The cumulative decomposability statistics:\n" ); - printf( " Total outputs = %5d\n", nFuncs ); - printf( " Decomposable outputs = %5d\n", nDecOutputs ); - printf( " Completely decomposable outputs = %5d\n", nCBFOutputs ); - printf( " The sum of max gate sizes = %5d\n", SumMaxGateSize ); - printf( " Shared BDD size = %5d\n", Cudd_SharingSize( pbFuncs, nFuncs ) ); - printf( " Decomposition entries = %5d\n", st_count( pDsdMan->Table ) ); - printf( " Pure decomposition time = %.2f sec\n", (float)(clock() - clk)/(float)(CLOCKS_PER_SEC) ); - } -/* - printf( "s_Loops1 = %d.\n", s_Loops1 ); - printf( "s_Loops2 = %d.\n", s_Loops2 ); - printf( "s_Loops3 = %d.\n", s_Loops3 ); - printf( "s_Case4Calls = %d.\n", s_Case4Calls ); - printf( "s_Case4CallsSpecial = %d.\n", s_Case4CallsSpecial ); - printf( "s_Case5 = %d.\n", s_Case5 ); - printf( "s_Loops2Useless = %d.\n", s_Loops2Useless ); -*/ -} - -/**Function************************************************************* - - Synopsis [Performs decomposition for one function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * Dsd_DecomposeOne( Dsd_Manager_t * pDsdMan, DdNode * bFunc ) -{ - return dsdKernelDecompose_rec( pDsdMan, bFunc ); -} - -/**Function************************************************************* - - Synopsis [The main function of this module. Recursive implementation of DSD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * dsdKernelDecompose_rec( Dsd_Manager_t * pDsdMan, DdNode * bFunc0 ) -{ - DdManager * dd = pDsdMan->dd; - DdNode * bLow; - DdNode * bLowR; - DdNode * bHigh; - - int VarInt; - DdNode * bVarCur; - Dsd_Node_t * pVarCurDE; - // works only if var indices start from 0!!! - DdNode * bSuppNew = NULL, * bTemp; - - int fContained; - int nSuppLH; - int nSuppL; - int nSuppH; - - - - // various decomposition nodes - Dsd_Node_t * pThis, * pL, * pH, * pLR, * pHR; - - Dsd_Node_t * pSmallR, * pLargeR; - Dsd_Node_t * pTableEntry; - - - // treat the complemented case - DdNode * bF = Cudd_Regular(bFunc0); - int fCompF = (int)(bF != bFunc0); - - // check cache - if ( st_lookup( pDsdMan->Table, (char*)bF, (char**)&pTableEntry ) ) - { // the entry is present - HashSuccess++; - return Dsd_NotCond( pTableEntry, fCompF ); - } - HashFailure++; - Depth++; - - // proceed to consider "four cases" - ////////////////////////////////////////////////////////////////////// - // TERMINAL CASES - CASES 1 and 2 - ////////////////////////////////////////////////////////////////////// - bLow = cuddE(bF); - bLowR = Cudd_Regular(bLow); - bHigh = cuddT(bF); - VarInt = bF->index; - bVarCur = dd->vars[VarInt]; - pVarCurDE = pDsdMan->pInputs[VarInt]; - // works only if var indices start from 0!!! - bSuppNew = NULL; - - if ( bLowR->index == CUDD_CONST_INDEX || bHigh->index == CUDD_CONST_INDEX ) - { // one of the cofactors in the constant - if ( bHigh == b1 ) // bHigh cannot be equal to b0, because then it will be complemented - if ( bLow == b0 ) // bLow cannot be equal to b1, because then the node will have bLow == bHigh - ///////////////////////////////////////////////////////////////// - // bLow == 0, bHigh == 1, F = x'&0 + x&1 = x - ///////////////////////////////////////////////////////////////// - { // create the elementary variable node - assert(0); // should be already in the hash table - pThis = Dsd_TreeNodeCreate( DSD_NODE_BUF, 1, s_nDecBlocks++ ); - pThis->pDecs[0] = NULL; - } - else // if ( bLow != constant ) - ///////////////////////////////////////////////////////////////// - // bLow != const, bHigh == 1, F = x'&bLow + x&1 = bLow + x --- DSD_NODE_OR(x,bLow) - ///////////////////////////////////////////////////////////////// - { - pL = dsdKernelDecompose_rec( pDsdMan, bLow ); - pLR = Dsd_Regular( pL ); - bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew); - if ( pLR->Type == DSD_NODE_OR && pL == pLR ) // OR and no complement - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pL->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pVarCurDE, pL->pDecs, pL->nDecs ); - } - else // all other cases - { // create a new 2-input OR-gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 ); - } - } - else // if ( bHigh != const ) // meaning that bLow should be a constant - { - pH = dsdKernelDecompose_rec( pDsdMan, bHigh ); - pHR = Dsd_Regular( pH ); - bSuppNew = Cudd_bddAnd( dd, bVarCur, pHR->S ); Cudd_Ref(bSuppNew); - if ( bLow == b0 ) - ///////////////////////////////////////////////////////////////// - // Low == 0, High != 1, F = x'&0+x&High = (x'+High')'--- NOR(x',High') - ///////////////////////////////////////////////////////////////// - if ( pHR->Type == DSD_NODE_OR && pH != pHR ) // DSD_NODE_OR and complement - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pHR->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pHR->pDecs, pHR->nDecs ); - pThis = Dsd_Not(pThis); - } - else // all other cases - { // create a new 2-input NOR gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - pH = Dsd_Not(pH); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 ); - pThis = Dsd_Not(pThis); - } - else // if ( bLow == b1 ) - ///////////////////////////////////////////////////////////////// - // Low == 1, High != 1, F = x'&1 + x&High = x' + High --- DSD_NODE_OR(x',High) - ///////////////////////////////////////////////////////////////// - if ( pHR->Type == DSD_NODE_OR && pH == pHR ) // OR and no complement - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, pH->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), pH->pDecs, pH->nDecs ); - } - else // all other cases - { // create a new 2-input OR-gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, Dsd_Not(pVarCurDE), &pH, 1 ); - } - } - goto EXIT; - } - // else if ( bLow != const && bHigh != const ) - - // the case of equal cofactors (up to complementation) - if ( bLowR == bHigh ) - ///////////////////////////////////////////////////////////////// - // Low == G, High == G', F = x'&G + x&G' = (x(+)G) --- EXOR(x,Low) - ///////////////////////////////////////////////////////////////// - { - pL = dsdKernelDecompose_rec( pDsdMan, bLow ); - pLR = Dsd_Regular( pL ); - bSuppNew = Cudd_bddAnd( dd, bVarCur, pLR->S ); Cudd_Ref(bSuppNew); - if ( pLR->Type == DSD_NODE_EXOR ) // complemented or not - does not matter! - { // add to the components - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, pLR->nDecs+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pVarCurDE, pLR->pDecs, pLR->nDecs ); - if ( pL != pLR ) - pThis = Dsd_Not( pThis ); - } - else // all other cases - { // create a new 2-input EXOR-gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ ); - if ( pL != pLR ) // complemented - { - dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pLR, 1 ); - pThis = Dsd_Not( pThis ); - } - else // non-complemented - dsdKernelCopyListPlusOne( pThis, pVarCurDE, &pL, 1 ); - } - goto EXIT; - } - - ////////////////////////////////////////////////////////////////////// - // solve subproblems - ////////////////////////////////////////////////////////////////////// - pL = dsdKernelDecompose_rec( pDsdMan, bLow ); - pH = dsdKernelDecompose_rec( pDsdMan, bHigh ); - pLR = Dsd_Regular( pL ); - pHR = Dsd_Regular( pH ); - - assert( pLR->Type == DSD_NODE_BUF || pLR->Type == DSD_NODE_OR || pLR->Type == DSD_NODE_EXOR || pLR->Type == DSD_NODE_PRIME ); - assert( pHR->Type == DSD_NODE_BUF || pHR->Type == DSD_NODE_OR || pHR->Type == DSD_NODE_EXOR || pHR->Type == DSD_NODE_PRIME ); - -/* -if ( Depth == 1 ) -{ -// PRK(bLow,pDecTreeTotal->nInputs); -// PRK(bHigh,pDecTreeTotal->nInputs); -if ( s_Show ) -{ - PRD( pL ); - PRD( pH ); -} -} -*/ - // compute the new support - bTemp = Cudd_bddAnd( dd, pLR->S, pHR->S ); Cudd_Ref( bTemp ); - nSuppL = Extra_bddSuppSize( dd, pLR->S ); - nSuppH = Extra_bddSuppSize( dd, pHR->S ); - nSuppLH = Extra_bddSuppSize( dd, bTemp ); - bSuppNew = Cudd_bddAnd( dd, bTemp, bVarCur ); Cudd_Ref( bSuppNew ); - Cudd_RecursiveDeref( dd, bTemp ); - - - // several possibilities are possible - // (1) support of one component contains another - // (2) none of the supports is contained in another - fContained = dsdKernelCheckContainment( pDsdMan, pLR, pHR, &pLargeR, &pSmallR ); - - ////////////////////////////////////////////////////////////////////// - // CASE 3.b One of the cofactors in a constant (OR and EXOR) - ////////////////////////////////////////////////////////////////////// - // the support of the larger component should contain the support of the smaller - // it is possible to have PRIME function in this role - // for example: F = ITE( a+b, c(+)d, e+f ), F0 = ITE( b, c(+)d, e+f ), F1 = c(+)d - if ( fContained ) - { - Dsd_Node_t * pSmall, * pLarge; - int c, iCompLarge; // the number of the component is Large is equal to the whole of Small - int fLowIsLarge; - - DdNode * bFTemp; // the changed input function - Dsd_Node_t * pDETemp, * pDENew; - - Dsd_Node_t * pComp = NULL; - int nComp; - - if ( pSmallR == pLR ) - { // Low is Small => High is Large - pSmall = pL; - pLarge = pH; - fLowIsLarge = 0; - } - else - { // vice versa - pSmall = pH; - pLarge = pL; - fLowIsLarge = 1; - } - - // treat the situation when the larger is PRIME - if ( pLargeR->Type == DSD_NODE_PRIME ) //&& pLargeR->nDecs != pSmallR->nDecs ) - { - // QUESTION: Is it possible for pLargeR->nDecs > 3 - // and pSmall contained as one of input in pLarge? - // Yes, for example F = a'c + a & MUX(b,c',d) = a'c + abc' + ab'd is non-decomposable - // Consider the function H(a->xy) = F( xy, b, c, d ) - // H0 = H(x=0) = F(0,b,c,d) = c - // H1 = F(x=1) = F(y,b,c,d) - non-decomposable - // - // QUESTION: Is it possible that pLarge is PRIME(3) and pSmall is OR(2), - // which is not contained in PRIME as one input? - // Yes, for example F = abcd + b'c'd' + a'c'd' = PRIME(ab, c, d) - // F(a=0) = c'd' = NOT(OR(a,d)) F(a=1) = bcd + b'c'd' = PRIME(b,c,d) - // To find decomposition, we have to prove that F(a=1)|b=0 = F(a=0) - - // Is it possible that (pLargeR->nDecs == pSmallR->nDecs) and yet this case holds? - // Yes, consider the function such that F(a=0) = PRIME(a,b+c,d,e) and F(a=1) = OR(b,c,d,e) - // They have the same number of inputs and it is possible that they will be the cofactors - // as discribed in the previous example. - - // find the component, which when substituted for 0 or 1, produces the desired result - int g, fFoundComp; // {0,1} depending on whether setting cofactor to 0 or 1 worked out - - DdNode * bLarge, * bSmall; - if ( fLowIsLarge ) - { - bLarge = bLow; - bSmall = bHigh; - } - else - { - bLarge = bHigh; - bSmall = bLow; - } - - for ( g = 0; g < pLargeR->nDecs; g++ ) -// if ( g != c ) - { - pDETemp = pLargeR->pDecs[g]; // cannot be complemented - if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, pDETemp->G, b1 ) ) - { - fFoundComp = 1; - break; - } - - s_Loops1++; - - if ( Dsd_CheckRootFunctionIdentity( dd, bLarge, bSmall, Cudd_Not(pDETemp->G), b1 ) ) - { - fFoundComp = 0; - break; - } - - s_Loops1++; - } - - if ( g != pLargeR->nDecs ) - { // decomposition is found - if ( fFoundComp ) - if ( fLowIsLarge ) - bFTemp = Cudd_bddOr( dd, bVarCur, pLargeR->pDecs[g]->G ); - else - bFTemp = Cudd_bddOr( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G ); - else - if ( fLowIsLarge ) - bFTemp = Cudd_bddAnd( dd, Cudd_Not(bVarCur), pLargeR->pDecs[g]->G ); - else - bFTemp = Cudd_bddAnd( dd, bVarCur, pLargeR->pDecs[g]->G ); - Cudd_Ref( bFTemp ); - - pDENew = dsdKernelDecompose_rec( pDsdMan, bFTemp ); - pDENew = Dsd_Regular( pDENew ); - Cudd_RecursiveDeref( dd, bFTemp ); - - // get the new gate - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLargeR->nDecs, s_nDecBlocks++ ); - dsdKernelCopyListPlusOneMinusOne( pThis, pDENew, pLargeR->pDecs, pLargeR->nDecs, g ); - goto EXIT; - } - } - - // try to find one component in the pLarger that is equal to the whole of pSmaller - for ( c = 0; c < pLargeR->nDecs; c++ ) - if ( pLargeR->pDecs[c] == pSmall || pLargeR->pDecs[c] == Dsd_Not(pSmall) ) - { - iCompLarge = c; - break; - } - - // assign the equal component - if ( c != pLargeR->nDecs ) // the decomposition is possible! - { - pComp = pLargeR->pDecs[iCompLarge]; - nComp = 1; - } - else // the decomposition is still possible - { // for example F = OR(ab,c,d), F(a=0) = OR(c,d), F(a=1) = OR(b,c,d) - // supp(F0) is contained in supp(F1), Polarity(F(a=0)) == Polarity(F(a=1)) - - // try to find a group of common components - if ( pLargeR->Type == pSmallR->Type && - (pLargeR->Type == DSD_NODE_EXOR || pSmallR->Type == DSD_NODE_OR&& ((pLarge==pLargeR) == (pSmall==pSmallR))) ) - { - Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; - int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLargeR, pSmallR, &pCommon, &pLastDiffL, &pLastDiffH ); - // if all the components of pSmall are contained in pLarge, - // then the decomposition exists - if ( nCommon == pSmallR->nDecs ) - { - pComp = pSmallR; - nComp = pSmallR->nDecs; - } - } - } - - if ( pComp ) // the decomposition is possible! - { -// Dsd_Node_t * pComp = pLargeR->pDecs[iCompLarge]; - Dsd_Node_t * pCompR = Dsd_Regular( pComp ); - int fComp1 = (int)( pLarge != pLargeR ); - int fComp2 = (int)( pComp != pCompR ); - int fComp3 = (int)( pSmall != pSmallR ); - - DdNode * bFuncComp; // the function of the given component - DdNode * bFuncNew; // the function of the input component - - if ( pLargeR->Type == DSD_NODE_OR ) // Figure 4 of Matsunaga's paper - { - // the decomposition exists only if the polarity assignment - // along the paths is the same - if ( (fComp1 ^ fComp2) == fComp3 ) - { // decomposition exists = consider 4 cases - // consideration of cases leads to the following conclusion - // fComp1 gives the polarity of the resulting DSD_NODE_OR gate - // fComp2 gives the polarity of the common component feeding into the DSD_NODE_OR gate - // - // | fComp1 pL/ |pS - // <> .........<=>....... <> | - // | / | - // [OR] [OR] | fComp3 - // / \ fComp2 / | \ | - // <> <> .......<=>... /..|..<> | - // / \ / | \| - // [OR] [C] S1 S2 C - // / \ - // <> \ - // / \ - // [OR] [x] - // / \ - // S1 S2 - // - - - // at this point we have the function F (bFTemp) and the common component C (bFuncComp) - // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0 - // we compute the following R = Exist( F - C, supp(C) ) - bFTemp = (fComp1)? Cudd_Not( bF ): bF; - bFuncComp = (fComp2)? Cudd_Not( pCompR->G ): pCompR->G; - bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bFuncComp), pCompR->S ); Cudd_Ref( bFuncNew ); - - // there is no need to copy the dec entry list first, because pComp is a component - // which will not be destroyed by the recursive call to decomposition - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - assert( Dsd_IsComplement(pDENew) ); // follows from the consideration of cases - Cudd_RecursiveDeref( dd, bFuncNew ); - - // get the new gate - if ( nComp == 1 ) - { - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, 2, s_nDecBlocks++ ); - pThis->pDecs[0] = pDENew; - pThis->pDecs[1] = pComp; // takes the complement - } - else - { // pComp is not complemented - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nComp+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp ); - } - - if ( fComp1 ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - } - else if ( pLargeR->Type == DSD_NODE_EXOR ) // Figure 5 of Matsunaga's paper (with correction) - { // decomposition always exists = consider 4 cases - - // consideration of cases leads to the following conclusion - // fComp3 gives the COMPLEMENT of the polarity of the resulting EXOR gate - // (if fComp3 is 0, the EXOR gate is complemented, and vice versa) - // - // | fComp1 pL/ |pS - // <> .........<=>....... /....| fComp3 - // | / | - // [XOR] [XOR] | - // / \ fComp2==0 / | \ | - // / \ / | \ | - // / \ / | \| - // [OR] [C] S1 S2 C - // / \ - // <> \ - // / \ - // [XOR] [x] - // / \ - // S1 S2 - // - - assert( fComp2 == 0 ); - // find the functionality of the lower gates - bFTemp = (fComp3)? bF: Cudd_Not( bF ); - bFuncNew = Cudd_bddXor( dd, bFTemp, pComp->G ); Cudd_Ref( bFuncNew ); - - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases - Cudd_RecursiveDeref( dd, bFuncNew ); - - // get the new gate - if ( nComp == 1 ) - { - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, 2, s_nDecBlocks++ ); - pThis->pDecs[0] = pDENew; - pThis->pDecs[1] = pComp; - } - else - { // pComp is not complemented - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nComp+1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, pDENew, pComp->pDecs, nComp ); - } - - if ( !fComp3 ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - } - } - - // this case was added to fix the trivial bug found November 4, 2002 in Japan - // by running the example provided by T. Sasao - if ( nSuppLH == nSuppL + nSuppH ) // the supports of the components are disjoint - { - // create a new component of the type ITE( a, pH, pL ) - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, 3, s_nDecBlocks++ ); - if ( dd->perm[pLR->S->index] < dd->perm[pHR->S->index] ) // pLR is higher in the varible order - { - pThis->pDecs[1] = pLR; - pThis->pDecs[2] = pHR; - } - else // pHR is higher in the varible order - { - pThis->pDecs[1] = pHR; - pThis->pDecs[2] = pLR; - } - // add the first component - pThis->pDecs[0] = pVarCurDE; - goto EXIT; - } - - - ////////////////////////////////////////////////////////////////////// - // CASE 3.a Neither of the cofactors is a constant (OR, EXOR, PRIME) - ////////////////////////////////////////////////////////////////////// - // the component types are identical - // and if they are OR, they are either both complemented or both not complemented - // and if they are PRIME, their dec numbers should be the same - if ( pLR->Type == pHR->Type && - pLR->Type != DSD_NODE_BUF && - (pLR->Type != DSD_NODE_OR || ( pL == pLR && pH == pHR || pL != pLR && pH != pHR ) ) && - (pLR->Type != DSD_NODE_PRIME || pLR->nDecs == pHR->nDecs) ) - { - // array to store common comps in pL and pH - Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; - int nCommon = dsdKernelFindCommonComponents( pDsdMan, pLR, pHR, &pCommon, &pLastDiffL, &pLastDiffH ); - if ( nCommon ) - { - if ( pLR->Type == DSD_NODE_OR ) // Figure 2 of Matsunaga's paper - { // at this point we have the function F and the group of common components C - // to get the remainder, R, in the relationship F = R + C, supp(R) & supp(C) = 0 - // we compute the following R = Exist( F - C, supp(C) ) - - // compute the sum total of the common components and the union of their supports - DdNode * bCommF, * bCommS, * bFTemp, * bFuncNew; - Dsd_Node_t * pDENew; - - dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, &bCommS, 0 ); - Cudd_Ref( bCommF ); - Cudd_Ref( bCommS ); - bFTemp = ( pL != pLR )? Cudd_Not(bF): bF; - - bFuncNew = Cudd_bddAndAbstract( dd, bFTemp, Cudd_Not(bCommF), bCommS ); Cudd_Ref( bFuncNew ); - Cudd_RecursiveDeref( dd, bCommF ); - Cudd_RecursiveDeref( dd, bCommS ); - - // get the new gate - - // copy the components first, then call the decomposition - // because decomposition will distroy the list used for copying - pThis = Dsd_TreeNodeCreate( DSD_NODE_OR, nCommon + 1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); - - // call the decomposition recursively - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); -// assert( !Dsd_IsComplement(pDENew) ); // follows from the consideration of cases - Cudd_RecursiveDeref( dd, bFuncNew ); - - // add the first component - pThis->pDecs[0] = pDENew; - - if ( pL != pLR ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - else - if ( pLR->Type == DSD_NODE_EXOR ) // Figure 3 of Matsunaga's paper - { - // compute the sum total of the common components and the union of their supports - DdNode * bCommF, * bFuncNew; - Dsd_Node_t * pDENew; - int fCompExor; - - dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, 1 ); - Cudd_Ref( bCommF ); - - bFuncNew = Cudd_bddXor( dd, bF, bCommF ); Cudd_Ref( bFuncNew ); - Cudd_RecursiveDeref( dd, bCommF ); - - // get the new gate - - // copy the components first, then call the decomposition - // because decomposition will distroy the list used for copying - pThis = Dsd_TreeNodeCreate( DSD_NODE_EXOR, nCommon + 1, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); - - // call the decomposition recursively - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - Cudd_RecursiveDeref( dd, bFuncNew ); - - // remember the fact that it was complemented - fCompExor = Dsd_IsComplement(pDENew); - pDENew = Dsd_Regular(pDENew); - - // add the first component - pThis->pDecs[0] = pDENew; - - - if ( fCompExor ) - pThis = Dsd_Not( pThis ); - goto EXIT; - } - else - if ( pLR->Type == DSD_NODE_PRIME && (nCommon == pLR->nDecs-1 || nCommon == pLR->nDecs) ) - { - // for example the function F(a,b,c,d) = ITE(b,c,a(+)d) produces - // two cofactors F(a=0) = PRIME(b,c,d) and F(a=1) = PRIME(b,c,d) - // with exactly the same list of common components - - Dsd_Node_t * pDENew; - DdNode * bFuncNew; - int fCompComp = 0; // this flag can be {0,1,2} - // if it is 0 there is no identity - // if it is 1/2, the cofactored functions are equal in the direct/complemented polarity - - if ( nCommon == pLR->nDecs ) - { // all the components are the same - // find the formal input, in which pLow and pHigh differ (if such input exists) - int m; - Dsd_Node_t * pTempL, * pTempH; - - s_Common++; - for ( m = 0; m < pLR->nDecs; m++ ) - { - pTempL = pLR->pDecs[m]; // cannot be complemented - pTempH = pHR->pDecs[m]; // cannot be complemented - - if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pTempL->G, Cudd_Not(pTempH->G) ) && - Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pTempL->G), pTempH->G ) ) - { - pLastDiffL = pTempL; - pLastDiffH = pTempH; - assert( pLastDiffL == pLastDiffH ); - fCompComp = 2; - break; - } - - s_Loops2++; - s_Loops2++; -/* - if ( s_Loops2 % 10000 == 0 ) - { - int i; - for ( i = 0; i < pLR->nDecs; i++ ) - printf( " %d(s=%d)", pLR->pDecs[i]->Type, - Extra_bddSuppSize(dd, pLR->pDecs[i]->S) ); - printf( "\n" ); - } -*/ - - } -// if ( pLR->nDecs == Extra_bddSuppSize(dd, pLR->S) ) -// s_Loops2Useless += pLR->nDecs * 2; - - if ( fCompComp ) - { // put the equal components into pCommon, so that they could be copied into the new dec entry - nCommon = 0; - for ( m = 0; m < pLR->nDecs; m++ ) - if ( pLR->pDecs[m] != pLastDiffL ) - pCommon[nCommon++] = pLR->pDecs[m]; - assert( nCommon = pLR->nDecs-1 ); - } - } - else - { // the differing components are known - check that they have compatible PRIME function - - s_CommonNo++; - - // find the numbers of different components - assert( pLastDiffL ); - assert( pLastDiffH ); - // also, they cannot be complemented, because the decomposition type is PRIME - - if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), Cudd_Not(pLastDiffH->G) ) && - Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, pLastDiffH->G ) ) - fCompComp = 1; - else if ( Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, pLastDiffL->G, Cudd_Not(pLastDiffH->G) ) && - Dsd_CheckRootFunctionIdentity( dd, bLow, bHigh, Cudd_Not(pLastDiffL->G), pLastDiffH->G ) ) - fCompComp = 2; - - s_Loops3 += 4; - } - - if ( fCompComp ) - { - if ( fCompComp == 1 ) // it is true that bLow(G=0) == bHigh(H=0) && bLow(G=1) == bHigh(H=1) - bFuncNew = Cudd_bddIte( dd, bVarCur, pLastDiffH->G, pLastDiffL->G ); - else // it is true that bLow(G=0) == bHigh(H=1) && bLow(G=1) == bHigh(H=0) - bFuncNew = Cudd_bddIte( dd, bVarCur, Cudd_Not(pLastDiffH->G), pLastDiffL->G ); - Cudd_Ref( bFuncNew ); - - // get the new gate - - // copy the components first, then call the decomposition - // because decomposition will distroy the list used for copying - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, pLR->nDecs, s_nDecBlocks++ ); - dsdKernelCopyListPlusOne( pThis, NULL, pCommon, nCommon ); - - // create a new component - pDENew = dsdKernelDecompose_rec( pDsdMan, bFuncNew ); - Cudd_RecursiveDeref( dd, bFuncNew ); - // the BDD of the argument function in PRIME decomposition, should be regular - pDENew = Dsd_Regular(pDENew); - - // add the first component - pThis->pDecs[0] = pDENew; - goto EXIT; - } - } // end of PRIME type - } // end of existing common components - } // end of CASE 3.a - -// if ( Depth != 1) -// { - -//CASE4: - ////////////////////////////////////////////////////////////////////// - // CASE 4 - ////////////////////////////////////////////////////////////////////// - { - // estimate the number of entries in the list - int nEntriesMax = pDsdMan->nInputs - dd->perm[VarInt]; - - // create the new decomposition entry - int nEntries = 0; - - DdNode * SuppL, * SuppH, * SuppL_init, * SuppH_init; - Dsd_Node_t *pHigher, *pLower, * pTemp, * pDENew; - - - int levTopSuppL; - int levTopSuppH; - int levTop; - - pThis = Dsd_TreeNodeCreate( DSD_NODE_PRIME, nEntriesMax, s_nDecBlocks++ ); - pThis->pDecs[ nEntries++ ] = pVarCurDE; - // other entries will be added to this list one-by-one during analysis - - // count how many times does it happen that the decomposition entries are - s_Case4Calls++; - - // consider the simplest case: when the supports are equal - // and at least one of the components - // is the PRIME without decompositions, or - // when both of them are without decomposition - if ( (((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) || (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) && pLR->S == pHR->S) || - ((pLR->Type == DSD_NODE_PRIME && nSuppL == pLR->nDecs) && (pHR->Type == DSD_NODE_PRIME && nSuppH == pHR->nDecs)) ) - { - - s_Case4CallsSpecial++; - // walk through both supports and create the decomposition list composed of simple entries - SuppL = pLR->S; - SuppH = pHR->S; - do - { - // determine levels - levTopSuppL = cuddI(dd,SuppL->index); - levTopSuppH = cuddI(dd,SuppH->index); - - // skip the topmost variable in both supports - if ( levTopSuppL <= levTopSuppH ) - { - levTop = levTopSuppL; - SuppL = cuddT(SuppL); - } - else - levTop = levTopSuppH; - - if ( levTopSuppH <= levTopSuppL ) - SuppH = cuddT(SuppH); - - // set the new decomposition entry - pThis->pDecs[ nEntries++ ] = pDsdMan->pInputs[ dd->invperm[levTop] ]; - } - while ( SuppL != b1 || SuppH != b1 ); - } - else - { - - // compare two different decomposition lists - SuppL_init = pLR->S; - SuppH_init = pHR->S; - // start references (because these supports will change) - SuppL = pLR->S; Cudd_Ref( SuppL ); - SuppH = pHR->S; Cudd_Ref( SuppH ); - while ( SuppL != b1 || SuppH != b1 ) - { - // determine the top level in cofactors and - // whether they have the same top level - int TopLevL = cuddI(dd,SuppL->index); - int TopLevH = cuddI(dd,SuppH->index); - int TopLevel = TopLevH; - int fEqualLevel = 0; - - DdNode * bVarTop; - DdNode * bSuppSubract; - - - if ( TopLevL < TopLevH ) - { - pHigher = pLR; - pLower = pHR; - TopLevel = TopLevL; - } - else if ( TopLevL > TopLevH ) - { - pHigher = pHR; - pLower = pLR; - } - else - fEqualLevel = 1; - assert( TopLevel != CUDD_CONST_INDEX ); - - - // find the currently top variable in the decomposition lists - bVarTop = dd->vars[dd->invperm[TopLevel]]; - - if ( !fEqualLevel ) - { - // find the lower support - DdNode * bSuppLower = (TopLevL < TopLevH)? SuppH_init: SuppL_init; - - // find the first component in pHigher - // whose support does not overlap with supp(Lower) - // and remember the previous component - int fPolarity; - Dsd_Node_t * pPrev = NULL; // the pointer to the component proceeding pCur - Dsd_Node_t * pCur = pHigher; // the first component not contained in supp(Lower) - while ( Extra_bddSuppOverlapping( dd, pCur->S, bSuppLower ) ) - { // get the next component - pPrev = pCur; - pCur = dsdKernelFindContainingComponent( pDsdMan, pCur, bVarTop, &fPolarity ); - }; - - // look for the possibility to subtract more than one component - if ( pPrev == NULL || pPrev->Type == DSD_NODE_PRIME ) - { // if there is no previous component, or if the previous component is PRIME - // there is no way to subtract more than one component - - // add the new decomposition entry (it is already regular) - pThis->pDecs[ nEntries++ ] = pCur; - // assign the support to be subtracted from both components - bSuppSubract = pCur->S; - } - else // all other types - { - // go through the decomposition list of pPrev and find components - // whose support does not overlap with supp(Lower) - - static Dsd_Node_t * pNonOverlap[MAXINPUTS]; - int i, nNonOverlap = 0; - for ( i = 0; i < pPrev->nDecs; i++ ) - { - pTemp = Dsd_Regular( pPrev->pDecs[i] ); - if ( !Extra_bddSuppOverlapping( dd, pTemp->S, bSuppLower ) ) - pNonOverlap[ nNonOverlap++ ] = pPrev->pDecs[i]; - } - assert( nNonOverlap > 0 ); - - if ( nNonOverlap == 1 ) - { // one one component was found, which is the original one - assert( Dsd_Regular(pNonOverlap[0]) == pCur); - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pCur; - // assign the support to be subtracted from both components - bSuppSubract = pCur->S; - } - else // more than one components was found - { - // find the OR (EXOR) of the non-overlapping components - DdNode * bCommF; - dsdKernelComputeSumOfComponents( pDsdMan, pNonOverlap, nNonOverlap, &bCommF, NULL, (int)(pPrev->Type==DSD_NODE_EXOR) ); - Cudd_Ref( bCommF ); - - // create a new gated - pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF ); - Cudd_RecursiveDeref(dd, bCommF); - // make it regular... it must be regular already - assert( !Dsd_IsComplement(pDENew) ); - - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pDENew; - // assign the support to be subtracted from both components - bSuppSubract = pDENew->S; - } - } - - // subtract its support from the support of upper component - if ( TopLevL < TopLevH ) - { - SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ); Cudd_Ref( SuppL ); - Cudd_RecursiveDeref(dd, bTemp); - } - else - { - SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ); Cudd_Ref( SuppH ); - Cudd_RecursiveDeref(dd, bTemp); - } - } // end of if ( !fEqualLevel ) - else // if ( fEqualLevel ) -- they have the same top level var - { - static Dsd_Node_t * pMarkedLeft[MAXINPUTS]; // the pointers to the marked blocks - static char pMarkedPols[MAXINPUTS]; // polarities of the marked blocks - int nMarkedLeft = 0; - - int fPolarity = 0; - Dsd_Node_t * pTempL = pLR; - - int fPolarityCurH = 0; - Dsd_Node_t * pPrevH = NULL, * pCurH = pHR; - - int fPolarityCurL = 0; - Dsd_Node_t * pPrevL = NULL, * pCurL = pLR; // = pMarkedLeft[0]; - int index = 1; - - // set the new mark - s_Mark++; - - // go over the dec list of pL, mark all components that contain the given variable - assert( Extra_bddSuppContainVar( dd, pLR->S, bVarTop ) ); - assert( Extra_bddSuppContainVar( dd, pHR->S, bVarTop ) ); - do { - pTempL->Mark = s_Mark; - pMarkedLeft[ nMarkedLeft ] = pTempL; - pMarkedPols[ nMarkedLeft ] = fPolarity; - nMarkedLeft++; - } while ( pTempL = dsdKernelFindContainingComponent( pDsdMan, pTempL, bVarTop, &fPolarity ) ); - - // go over the dec list of pH, and find the component that is marked and the previos one - // (such component always exists, because they have common variables) - while ( pCurH->Mark != s_Mark ) - { - pPrevH = pCurH; - pCurH = dsdKernelFindContainingComponent( pDsdMan, pCurH, bVarTop, &fPolarityCurH ); - assert( pCurH ); - } - - // go through the first list once again and find - // the component proceeding the one marked found in the second list - while ( pCurL != pCurH ) - { - pPrevL = pCurL; - pCurL = pMarkedLeft[index]; - fPolarityCurL = pMarkedPols[index]; - index++; - } - - // look for the possibility to subtract more than one component - if ( !pPrevL || !pPrevH || pPrevL->Type != pPrevH->Type || pPrevL->Type == DSD_NODE_PRIME || fPolarityCurL != fPolarityCurH ) - { // there is no way to extract more than one - pThis->pDecs[ nEntries++ ] = pCurH; - // assign the support to be subtracted from both components - bSuppSubract = pCurH->S; - } - else - { - // find the equal components in two decomposition lists - Dsd_Node_t ** pCommon, * pLastDiffL = NULL, * pLastDiffH = NULL; - int nCommon = dsdKernelFindCommonComponents( pDsdMan, pPrevL, pPrevH, &pCommon, &pLastDiffL, &pLastDiffH ); - - if ( nCommon == 0 || nCommon == 1 ) - { // one one component was found, which is the original one - // assert( Dsd_Regular(pCommon[0]) == pCurL); - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pCurL; - // assign the support to be subtracted from both components - bSuppSubract = pCurL->S; - } - else // more than one components was found - { - // find the OR (EXOR) of the non-overlapping components - DdNode * bCommF; - dsdKernelComputeSumOfComponents( pDsdMan, pCommon, nCommon, &bCommF, NULL, (int)(pPrevL->Type==DSD_NODE_EXOR) ); - Cudd_Ref( bCommF ); - - pDENew = dsdKernelDecompose_rec( pDsdMan, bCommF ); - assert( !Dsd_IsComplement(pDENew) ); // cannot be complemented because of construction - Cudd_RecursiveDeref( dd, bCommF ); - - // add the new decomposition entry - pThis->pDecs[ nEntries++ ] = pDENew; - - // assign the support to be subtracted from both components - bSuppSubract = pDENew->S; - } - } - - SuppL = Cudd_bddExistAbstract( dd, bTemp = SuppL, bSuppSubract ), Cudd_Ref( SuppL ); - Cudd_RecursiveDeref(dd, bTemp); - - SuppH = Cudd_bddExistAbstract( dd, bTemp = SuppH, bSuppSubract ), Cudd_Ref( SuppH ); - Cudd_RecursiveDeref(dd, bTemp); - - } // end of if ( fEqualLevel ) - - } // end of decomposition list comparison - Cudd_RecursiveDeref( dd, SuppL ); - Cudd_RecursiveDeref( dd, SuppH ); - - } - - // check that the estimation of the number of entries was okay - assert( nEntries <= nEntriesMax ); - -// if ( nEntries != Extra_bddSuppSize(dd, bSuppNew) ) -// s_Case5++; - - // update the number of entries in the new decomposition list - pThis->nDecs = nEntries; - } -//} -EXIT: - - { - // if the component created is complemented, it represents a function without complement - // therefore, as it is, without complement, it should recieve the complemented function - Dsd_Node_t * pThisR = Dsd_Regular( pThis ); - assert( pThisR->G == NULL ); - assert( pThisR->S == NULL ); - - if ( pThisR == pThis ) // set regular function - pThisR->G = bF; - else // set complemented function - pThisR->G = Cudd_Not(bF); - Cudd_Ref(bF); // reference the function in the component - - assert( bSuppNew ); - pThisR->S = bSuppNew; // takes the reference from the new support - if ( st_insert( pDsdMan->Table, (char*)bF, (char*)pThis ) ) - { - assert( 0 ); - } - s_CacheEntries++; - - -/* - if ( dsdKernelVerifyDecomposition(dd, pThis) == 0 ) - { - // write the function, for which verification does not work - cout << endl << "Internal verification failed!"" ); - - // create the variable mask - static int s_pVarMask[MAXINPUTS]; - int nInputCounter = 0; - - Cudd_SupportArray( dd, bF, s_pVarMask ); - int k; - for ( k = 0; k < dd->size; k++ ) - if ( s_pVarMask[k] ) - nInputCounter++; - - cout << endl << "The problem function is "" ); - - DdNode * zNewFunc = Cudd_zddIsopCover( dd, bF, bF ); Cudd_Ref( zNewFunc ); - cuddWriteFunctionSop( stdout, dd, zNewFunc, -1, dd->size, "1", s_pVarMask ); - Cudd_RecursiveDerefZdd( dd, zNewFunc ); - } -*/ - - } - - Depth--; - return Dsd_NotCond( pThis, fCompF ); -} - - -//////////////////////////////////////////////////////////////////////// -/// OTHER FUNCTIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Finds the corresponding decomposition entry.] - - Description [This function returns the non-complemented pointer to the - DecEntry of that component which contains the given variable in its - support, or NULL if no such component exists] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * dsdKernelFindContainingComponent( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pWhere, DdNode * Var, int * fPolarity ) - -{ - Dsd_Node_t * pTemp; - int i; - -// assert( !Dsd_IsComplement( pWhere ) ); -// assert( Extra_bddSuppContainVar( pDsdMan->dd, pWhere->S, Var ) ); - - if ( pWhere->nDecs == 1 ) - return NULL; - - for( i = 0; i < pWhere->nDecs; i++ ) - { - pTemp = Dsd_Regular( pWhere->pDecs[i] ); - if ( Extra_bddSuppContainVar( pDsdMan->dd, pTemp->S, Var ) ) - { - *fPolarity = (int)( pTemp != pWhere->pDecs[i] ); - return pTemp; - } - } - assert( 0 ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Find the common decomposition components.] - - Description [This function determines the common components. It counts - the number of common components in the decomposition lists of pL and pH - and returns their number and the lists of common components. It assumes - that pL and pH are regular pointers. It retuns also the pointers to the - last different components encountered in pL and pH.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int dsdKernelFindCommonComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t *** pCommon, Dsd_Node_t ** pLastDiffL, Dsd_Node_t ** pLastDiffH ) -{ - static Dsd_Node_t * Common[MAXINPUTS]; - int nCommon = 0; - - // pointers to the current decomposition entries - Dsd_Node_t * pLcur; - Dsd_Node_t * pHcur; - - // the pointers to their supports - DdNode * bSLcur; - DdNode * bSHcur; - - // the top variable in the supports - int TopVar; - - // the indices running through the components - int iCurL = 0; - int iCurH = 0; - while ( iCurL < pL->nDecs && iCurH < pH->nDecs ) - { // both did not run out - - pLcur = Dsd_Regular(pL->pDecs[iCurL]); - pHcur = Dsd_Regular(pH->pDecs[iCurH]); - - bSLcur = pLcur->S; - bSHcur = pHcur->S; - - // find out what component is higher in the BDD - if ( pDsdMan->dd->perm[bSLcur->index] < pDsdMan->dd->perm[bSHcur->index] ) - TopVar = bSLcur->index; - else - TopVar = bSHcur->index; - - if ( TopVar == bSLcur->index && TopVar == bSHcur->index ) - { - // the components may be equal - should match exactly! - if ( pL->pDecs[iCurL] == pH->pDecs[iCurH] ) - Common[nCommon++] = pL->pDecs[iCurL]; - else - { - *pLastDiffL = pL->pDecs[iCurL]; - *pLastDiffH = pH->pDecs[iCurH]; - } - - // skip both - iCurL++; - iCurH++; - } - else if ( TopVar == bSLcur->index ) - { // the components cannot be equal - // skip the top-most one - *pLastDiffL = pL->pDecs[iCurL++]; - } - else // if ( TopVar == bSHcur->index ) - { // the components cannot be equal - // skip the top-most one - *pLastDiffH = pH->pDecs[iCurH++]; - } - } - - // if one of the lists still has components, write the first one down - if ( iCurL < pL->nDecs ) - *pLastDiffL = pL->pDecs[iCurL]; - - if ( iCurH < pH->nDecs ) - *pLastDiffH = pH->pDecs[iCurH]; - - // return the pointer to the array - *pCommon = Common; - // return the number of common components - return nCommon; -} - -/**Function************************************************************* - - Synopsis [Computes the sum (OR or EXOR) of the functions of the components.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void dsdKernelComputeSumOfComponents( Dsd_Manager_t * pDsdMan, Dsd_Node_t ** pCommon, int nCommon, DdNode ** pCompF, DdNode ** pCompS, int fExor ) -{ - DdManager * dd = pDsdMan->dd; - DdNode * bF, * bS, * bFadd, * bTemp; - Dsd_Node_t * pDE, * pDER; - int i; - - // start the function - bF = b0; Cudd_Ref( bF ); - // start the support - if ( pCompS ) - bS = b1, Cudd_Ref( bS ); - - assert( nCommon > 0 ); - for ( i = 0; i < nCommon; i++ ) - { - pDE = pCommon[i]; - pDER = Dsd_Regular( pDE ); - bFadd = (pDE != pDER)? Cudd_Not(pDER->G): pDER->G; - // add to the function - if ( fExor ) - bF = Cudd_bddXor( dd, bTemp = bF, bFadd ); - else - bF = Cudd_bddOr( dd, bTemp = bF, bFadd ); - Cudd_Ref( bF ); - Cudd_RecursiveDeref( dd, bTemp ); - if ( pCompS ) - { - // add to the support - bS = Cudd_bddAnd( dd, bTemp = bS, pDER->S ); Cudd_Ref( bS ); - Cudd_RecursiveDeref( dd, bTemp ); - } - } - // return the function - Cudd_Deref( bF ); - *pCompF = bF; - - // return the support - if ( pCompS ) - Cudd_Deref( bS ), *pCompS = bS; -} - -/**Function************************************************************* - - Synopsis [Checks support containment of the decomposition components.] - - Description [This function returns 1 if support of one component is contained - in that of another. In this case, pLarge (pSmall) is assigned to point to the - larger (smaller) support. If the supports are identical return 0, and does not - assign the components.] -] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int dsdKernelCheckContainment( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pL, Dsd_Node_t * pH, Dsd_Node_t ** pLarge, Dsd_Node_t ** pSmall ) -{ - DdManager * dd = pDsdMan->dd; - DdNode * bSuppLarge, * bSuppSmall; - int RetValue; - - RetValue = Extra_bddSuppCheckContainment( dd, pL->S, pH->S, &bSuppLarge, &bSuppSmall ); - - if ( RetValue == 0 ) - return 0; - - if ( pH->S == bSuppLarge ) - { - *pLarge = pH; - *pSmall = pL; - } - else // if ( pL->S == bSuppLarge ) - { - *pLarge = pL; - *pSmall = pH; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Copies the list of components plus one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void dsdKernelCopyListPlusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize ) -{ - int i; - assert( nListSize+1 == p->nDecs ); - p->pDecs[0] = First; - for( i = 0; i < nListSize; i++ ) - p->pDecs[i+1] = ppList[i]; -} - -/**Function************************************************************* - - Synopsis [Copies the list of components plus one, and skips one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void dsdKernelCopyListPlusOneMinusOne( Dsd_Node_t * p, Dsd_Node_t * First, Dsd_Node_t ** ppList, int nListSize, int iSkipped ) -{ - int i, Counter; - assert( nListSize == p->nDecs ); - p->pDecs[0] = First; - for( i = 0, Counter = 1; i < nListSize; i++ ) - if ( i != iSkipped ) - p->pDecs[Counter++] = ppList[i]; -} - -/**Function************************************************************* - - Synopsis [Debugging procedure to compute the functionality of the decomposed structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int dsdKernelVerifyDecomposition( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pDE ) -{ - DdManager * dd = pDsdMan->dd; - Dsd_Node_t * pR = Dsd_Regular(pDE); - int fCompP = (int)( pDE != pR ); - int RetValue; - - DdNode * bRes; - if ( pR->Type == DSD_NODE_CONST1 ) - bRes = b1; - else if ( pR->Type == DSD_NODE_BUF ) - bRes = pR->G; - else if ( pR->Type == DSD_NODE_OR || pR->Type == DSD_NODE_EXOR ) - dsdKernelComputeSumOfComponents( pDsdMan, pR->pDecs, pR->nDecs, &bRes, NULL, (int)(pR->Type == DSD_NODE_EXOR) ); - else if ( pR->Type == DSD_NODE_PRIME ) - { - int i; - static DdNode * bGVars[MAXINPUTS]; - // transform the function of this block, so that it depended on inputs - // corresponding to the formal inputs - DdNode * bNewFunc = Dsd_TreeGetPrimeFunctionOld( dd, pR, 1 ); Cudd_Ref( bNewFunc ); - - // compose this function with the inputs - // create the elementary permutation - for ( i = 0; i < dd->size; i++ ) - bGVars[i] = dd->vars[i]; - - // assign functions to be composed - for ( i = 0; i < pR->nDecs; i++ ) - bGVars[dd->invperm[i]] = pR->pDecs[i]->G; - - // perform the composition - bRes = Cudd_bddVectorCompose( dd, bNewFunc, bGVars ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bNewFunc ); - - ///////////////////////////////////////////////////////// - RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) ); - ///////////////////////////////////////////////////////// - Cudd_Deref( bRes ); - } - else - { - assert(0); - } - - Cudd_Ref( bRes ); - RetValue = (int)( bRes == pR->G );//|| bRes == Cudd_Not(pR->G) ); - Cudd_RecursiveDeref( dd, bRes ); - return RetValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/dsdTree.c b/src/bdd/dsd/dsdTree.c deleted file mode 100644 index 2855d68d..00000000 --- a/src/bdd/dsd/dsdTree.c +++ /dev/null @@ -1,1068 +0,0 @@ -/**CFile**************************************************************** - - FileName [dsdTree.c] - - PackageName [DSD: Disjoint-support decomposition package.] - - Synopsis [Managing the decomposition tree.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 8.0. Started - September 22, 2003.] - - Revision [$Id: dsdTree.c,v 1.0 2002/22/09 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "dsdInt.h" - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode ); -static void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ); -static int Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode ); -static int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode ); -static int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars ); -static void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes ); -static void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fCcmp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames ); -static void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter ); - -//////////////////////////////////////////////////////////////////////// -/// STATIC VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -static int s_DepthMax; -static int s_GateSizeMax; - -static int s_CounterBlocks; -static int s_CounterPos; -static int s_CounterNeg; -static int s_CounterNo; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Create the DSD node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t * Dsd_TreeNodeCreate( int Type, int nDecs, int BlockNum ) -{ - // allocate memory for this node - Dsd_Node_t * p = (Dsd_Node_t *) malloc( sizeof(Dsd_Node_t) ); - memset( p, 0, sizeof(Dsd_Node_t) ); - p->Type = Type; // the type of this block - p->nDecs = nDecs; // the number of decompositions - if ( p->nDecs ) - { - p->pDecs = (Dsd_Node_t **) malloc( p->nDecs * sizeof(Dsd_Node_t *) ); - p->pDecs[0] = NULL; - } - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the DSD node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeNodeDelete( DdManager * dd, Dsd_Node_t * pNode ) -{ - if ( pNode->G ) Cudd_RecursiveDeref( dd, pNode->G ); - if ( pNode->S ) Cudd_RecursiveDeref( dd, pNode->S ); - FREE( pNode->pDecs ); - FREE( pNode ); -} - -/**Function************************************************************* - - Synopsis [Unmarks the decomposition tree.] - - Description [This function assumes that originally pNode->nVisits are - set to zero!] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeUnmark( Dsd_Manager_t * pDsdMan ) -{ - int i; - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Dsd_TreeUnmark_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); -} - - -/**Function************************************************************* - - Synopsis [Recursive unmarking.] - - Description [This function should be called with a non-complemented - pointer.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeUnmark_rec( Dsd_Node_t * pNode ) -{ - int i; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits > 0 ); - - if ( --pNode->nVisits ) // if this is not the last visit, return - return; - - // upon the last visit, go through the list of successors and call recursively - if ( pNode->Type != DSD_NODE_BUF && pNode->Type != DSD_NODE_CONST1 ) - for ( i = 0; i < pNode->nDecs; i++ ) - Dsd_TreeUnmark_rec( Dsd_Regular(pNode->pDecs[i]) ); -} - -/**Function************************************************************* - - Synopsis [Getting information about the node.] - - Description [This function computes the max depth and the max gate size - of the tree rooted at the node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeNodeGetInfo( Dsd_Manager_t * pDsdMan, int * DepthMax, int * GateSizeMax ) -{ - int i; - s_DepthMax = 0; - s_GateSizeMax = 0; - - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Dsd_TreeGetInfo_rec( Dsd_Regular( pDsdMan->pRoots[i] ), 0 ); - - if ( DepthMax ) - *DepthMax = s_DepthMax; - if ( GateSizeMax ) - *GateSizeMax = s_GateSizeMax; -} - -/**Function************************************************************* - - Synopsis [Getting information about the node.] - - Description [This function computes the max depth and the max gate size - of the tree rooted at the node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeNodeGetInfoOne( Dsd_Node_t * pNode, int * DepthMax, int * GateSizeMax ) -{ - s_DepthMax = 0; - s_GateSizeMax = 0; - - Dsd_TreeGetInfo_rec( Dsd_Regular(pNode), 0 ); - - if ( DepthMax ) - *DepthMax = s_DepthMax; - if ( GateSizeMax ) - *GateSizeMax = s_GateSizeMax; -} - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Dsd_TreeNodeGetInfo().] - - Description [pNode is the node, for the tree rooted in which we are - determining info. RankCur is the current rank to assign to the node. - fSetRank is the flag saying whether the rank will be written in the - node. s_DepthMax is the maximum depths of the tree. s_GateSizeMax is - the maximum gate size.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeGetInfo_rec( Dsd_Node_t * pNode, int RankCur ) -{ - int i; - int GateSize; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - // we don't want the two-input gates to count for non-decomposable blocks - if ( pNode->Type == DSD_NODE_OR || - pNode->Type == DSD_NODE_EXOR ) - GateSize = 2; - else - GateSize = pNode->nDecs; - - // update the max size of the node - if ( s_GateSizeMax < GateSize ) - s_GateSizeMax = GateSize; - - if ( pNode->nDecs < 2 ) - return; - - // update the max rank - if ( s_DepthMax < RankCur+1 ) - s_DepthMax = RankCur+1; - - // call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Dsd_TreeGetInfo_rec( Dsd_Regular(pNode->pDecs[i]), RankCur+1 ); -} - -/**Function************************************************************* - - Synopsis [Counts AIG nodes needed to implement this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeGetAigCost_rec( Dsd_Node_t * pNode ) -{ - int i, Counter = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nDecs < 2 ) - return 0; - - // we don't want the two-input gates to count for non-decomposable blocks - if ( pNode->Type == DSD_NODE_OR ) - Counter += pNode->nDecs - 1; - else if ( pNode->Type == DSD_NODE_EXOR ) - Counter += 3*(pNode->nDecs - 1); - else if ( pNode->Type == DSD_NODE_PRIME && pNode->nDecs == 3 ) - Counter += 3; - - // call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Counter += Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode->pDecs[i]) ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts AIG nodes needed to implement this node.] - - Description [Assumes that the only primes of the DSD tree are MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeGetAigCost( Dsd_Node_t * pNode ) -{ - return Dsd_TreeGetAigCost_rec( Dsd_Regular(pNode) ); -} - -/**Function************************************************************* - - Synopsis [Counts non-terminal nodes of the DSD tree.] - - Description [Nonterminal nodes include all the nodes with the - support more than 1. These are OR, EXOR, and PRIME nodes. They - do not include the elementary variable nodes and the constant 1 - node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountNonTerminalNodes( Dsd_Manager_t * pDsdMan ) -{ - int Counter, i; - Counter = 0; - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); - Dsd_TreeUnmark( pDsdMan ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountNonTerminalNodesOne( Dsd_Node_t * pRoot ) -{ - int Counter = 0; - - // go through the list of successors and call recursively - Counter = Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pRoot) ); - - Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) ); - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Counts non-terminal nodes for one root.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountNonTerminalNodes_rec( Dsd_Node_t * pNode ) -{ - int i; - int Counter = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nVisits++ ) // if this is not the first visit, return zero - return 0; - - if ( pNode->nDecs <= 1 ) - return 0; - - // upon the first visit, go through the list of successors and call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Counter += Dsd_TreeCountNonTerminalNodes_rec( Dsd_Regular(pNode->pDecs[i]) ); - - return Counter + 1; -} - - -/**Function************************************************************* - - Synopsis [Counts prime nodes of the DSD tree.] - - Description [Prime nodes are nodes with the support more than 2, - that is not an OR or EXOR gate.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountPrimeNodes( Dsd_Manager_t * pDsdMan ) -{ - int Counter, i; - Counter = 0; - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular( pDsdMan->pRoots[i] ) ); - Dsd_TreeUnmark( pDsdMan ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts prime nodes for one root.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountPrimeNodesOne( Dsd_Node_t * pRoot ) -{ - int Counter = 0; - - // go through the list of successors and call recursively - Counter = Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pRoot) ); - - Dsd_TreeUnmark_rec( Dsd_Regular(pRoot) ); - return Counter; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCountPrimeNodes_rec( Dsd_Node_t * pNode ) -{ - int i; - int Counter = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nVisits++ ) // if this is not the first visit, return zero - return 0; - - if ( pNode->nDecs <= 1 ) - return 0; - - // upon the first visit, go through the list of successors and call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Counter += Dsd_TreeCountPrimeNodes_rec( Dsd_Regular(pNode->pDecs[i]) ); - - if ( pNode->Type == DSD_NODE_PRIME ) - Counter++; - - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Collects the decomposable vars on the PI side.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCollectDecomposableVars( Dsd_Manager_t * pDsdMan, int * pVars ) -{ - int nVars; - - // set the vars collected to 0 - nVars = 0; - Dsd_TreeCollectDecomposableVars_rec( pDsdMan->dd, Dsd_Regular(pDsdMan->pRoots[0]), pVars, &nVars ); - // return the number of collected vars - return nVars; -} - -/**Function************************************************************* - - Synopsis [Implements the recursive part of Dsd_TreeCollectDecomposableVars().] - - Description [Adds decomposable variables as they are found to pVars and increments - nVars. Returns 1 if a non-dec node with more than 4 inputs was encountered - in the processed subtree. Returns 0, otherwise. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dsd_TreeCollectDecomposableVars_rec( DdManager * dd, Dsd_Node_t * pNode, int * pVars, int * nVars ) -{ - int fSkipThisNode, i; - Dsd_Node_t * pTemp; - int fVerbose = 0; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - - if ( pNode->nDecs <= 1 ) - return 0; - - // go through the list of successors and call recursively - fSkipThisNode = 0; - for ( i = 0; i < pNode->nDecs; i++ ) - if ( Dsd_TreeCollectDecomposableVars_rec(dd, Dsd_Regular(pNode->pDecs[i]), pVars, nVars) ) - fSkipThisNode = 1; - - if ( !fSkipThisNode && (pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR || pNode->nDecs <= 4) ) - { -if ( fVerbose ) -printf( "Node of type <%d> (OR=6,EXOR=8,RAND=1): ", pNode->Type ); - - for ( i = 0; i < pNode->nDecs; i++ ) - { - pTemp = Dsd_Regular(pNode->pDecs[i]); - if ( pTemp->Type == DSD_NODE_BUF ) - { - if ( pVars ) - pVars[ (*nVars)++ ] = pTemp->S->index; - else - (*nVars)++; - -if ( fVerbose ) -printf( "%d ", pTemp->S->index ); - } - } -if ( fVerbose ) -printf( "\n" ); - } - else - fSkipThisNode = 1; - - - return fSkipThisNode; -} - - -/**Function************************************************************* - - Synopsis [Creates the DFS ordered array of DSD nodes in the tree.] - - Description [The collected nodes do not include the terminal nodes - and the constant 1 node. The array of nodes is returned. The number - of entries in the array is returned in the variale pnNodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t ** Dsd_TreeCollectNodesDfs( Dsd_Manager_t * pDsdMan, int * pnNodes ) -{ - Dsd_Node_t ** ppNodes; - int nNodes, nNodesAlloc; - int i; - - nNodesAlloc = Dsd_TreeCountNonTerminalNodes(pDsdMan); - nNodes = 0; - ppNodes = ALLOC( Dsd_Node_t *, nNodesAlloc ); - for ( i = 0; i < pDsdMan->nRoots; i++ ) - Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pDsdMan->pRoots[i]), ppNodes, &nNodes ); - Dsd_TreeUnmark( pDsdMan ); - assert( nNodesAlloc == nNodes ); - *pnNodes = nNodes; - return ppNodes; -} - -/**Function************************************************************* - - Synopsis [Creates the DFS ordered array of DSD nodes in the tree.] - - Description [The collected nodes do not include the terminal nodes - and the constant 1 node. The array of nodes is returned. The number - of entries in the array is returned in the variale pnNodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dsd_Node_t ** Dsd_TreeCollectNodesDfsOne( Dsd_Manager_t * pDsdMan, Dsd_Node_t * pNode, int * pnNodes ) -{ - Dsd_Node_t ** ppNodes; - int nNodes, nNodesAlloc; - nNodesAlloc = Dsd_TreeCountNonTerminalNodesOne(pNode); - nNodes = 0; - ppNodes = ALLOC( Dsd_Node_t *, nNodesAlloc ); - Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode), ppNodes, &nNodes ); - Dsd_TreeUnmark_rec(Dsd_Regular(pNode)); - assert( nNodesAlloc == nNodes ); - *pnNodes = nNodes; - return ppNodes; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreeCollectNodesDfs_rec( Dsd_Node_t * pNode, Dsd_Node_t * ppNodes[], int * pnNodes ) -{ - int i; - assert( pNode ); - assert( !Dsd_IsComplement(pNode) ); - assert( pNode->nVisits >= 0 ); - - if ( pNode->nVisits++ ) // if this is not the first visit, return zero - return; - if ( pNode->nDecs <= 1 ) - return; - - // upon the first visit, go through the list of successors and call recursively - for ( i = 0; i < pNode->nDecs; i++ ) - Dsd_TreeCollectNodesDfs_rec( Dsd_Regular(pNode->pDecs[i]), ppNodes, pnNodes ); - - ppNodes[ (*pnNodes)++ ] = pNode; -} - -/**Function************************************************************* - - Synopsis [Prints the decompostion tree into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreePrint( FILE * pFile, Dsd_Manager_t * pDsdMan, char * pInputNames[], char * pOutputNames[], int fShortNames, int Output ) -{ - Dsd_Node_t * pNode; - int SigCounter; - int i; - SigCounter = 1; - - if ( Output == -1 ) - { - for ( i = 0; i < pDsdMan->nRoots; i++ ) - { - pNode = Dsd_Regular( pDsdMan->pRoots[i] ); - Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[i]), pInputNames, pOutputNames[i], 0, &SigCounter, fShortNames ); - } - } - else - { - assert( Output >= 0 && Output < pDsdMan->nRoots ); - pNode = Dsd_Regular( pDsdMan->pRoots[Output] ); - Dsd_TreePrint_rec( pFile, pNode, (pNode != pDsdMan->pRoots[Output]), pInputNames, pOutputNames[Output], 0, &SigCounter, fShortNames ); - } -} - -/**Function************************************************************* - - Synopsis [Prints the decompostion tree into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_TreePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pInputNames[], char * pOutputName, int nOffset, int * pSigCounter, int fShortNames ) -{ - char Buffer[100]; - Dsd_Node_t * pInput; - int * pInputNums; - int fCompNew, i; - - assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || - pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); - - Extra_PrintSymbols( pFile, ' ', nOffset, 0 ); - if ( !fComp ) - fprintf( pFile, "%s = ", pOutputName ); - else - fprintf( pFile, "NOT(%s) = ", pOutputName ); - pInputNums = ALLOC( int, pNode->nDecs ); - if ( pNode->Type == DSD_NODE_CONST1 ) - { - fprintf( pFile, " Constant 1.\n" ); - } - else if ( pNode->Type == DSD_NODE_BUF ) - { - if ( fShortNames ) - fprintf( pFile, "%d", 'a' + pNode->S->index ); - else - fprintf( pFile, "%s", pInputNames[pNode->S->index] ); - fprintf( pFile, "\n" ); - } - else if ( pNode->Type == DSD_NODE_PRIME ) - { - // print the line - fprintf( pFile, "PRIME(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - if ( fShortNames ) - fprintf( pFile, "%d", pInput->S->index ); - else - fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, "<%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, ")" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); - } - } - else if ( pNode->Type == DSD_NODE_OR ) - { - // print the line - fprintf( pFile, "OR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - if ( fShortNames ) - fprintf( pFile, "%c", 'a' + pInput->S->index ); - else - fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, "<%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, ")" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); - } - } - else if ( pNode->Type == DSD_NODE_EXOR ) - { - // print the line - fprintf( pFile, "EXOR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( fCompNew ) - fprintf( pFile, " NOT(" ); - else - fprintf( pFile, " " ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - if ( fShortNames ) - fprintf( pFile, "%c", 'a' + pInput->S->index ); - else - fprintf( pFile, "%s", pInputNames[pInput->S->index] ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, "<%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, ")" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_TreePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, pInputNames, Buffer, nOffset + 6, pSigCounter, fShortNames ); - } - } - free( pInputNums ); -} - -/**Function************************************************************* - - Synopsis [Prints the decompostion tree into file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_NodePrint( FILE * pFile, Dsd_Node_t * pNode ) -{ - Dsd_Node_t * pNodeR; - int SigCounter = 1; - pNodeR = Dsd_Regular(pNode); - Dsd_NodePrint_rec( pFile, pNodeR, pNodeR != pNode, "F", 0, &SigCounter ); -} - -/**Function************************************************************* - - Synopsis [Prints one node of the decomposition tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dsd_NodePrint_rec( FILE * pFile, Dsd_Node_t * pNode, int fComp, char * pOutputName, int nOffset, int * pSigCounter ) -{ - char Buffer[100]; - Dsd_Node_t * pInput; - int * pInputNums; - int fCompNew, i; - - assert( pNode->Type == DSD_NODE_BUF || pNode->Type == DSD_NODE_CONST1 || - pNode->Type == DSD_NODE_PRIME || pNode->Type == DSD_NODE_OR || pNode->Type == DSD_NODE_EXOR ); - - Extra_PrintSymbols( pFile, ' ', nOffset, 0 ); - if ( !fComp ) - fprintf( pFile, "%s = ", pOutputName ); - else - fprintf( pFile, "NOT(%s) = ", pOutputName ); - pInputNums = ALLOC( int, pNode->nDecs ); - if ( pNode->Type == DSD_NODE_CONST1 ) - { - fprintf( pFile, " Constant 1.\n" ); - } - else if ( pNode->Type == DSD_NODE_BUF ) - { - fprintf( pFile, " " ); - fprintf( pFile, "%c", 'a' + pNode->S->index ); - fprintf( pFile, "\n" ); - } - else if ( pNode->Type == DSD_NODE_PRIME ) - { - // print the line - fprintf( pFile, "PRIME(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - assert( fCompNew == 0 ); - if ( i ) - fprintf( pFile, "," ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - fprintf( pFile, " %c", 'a' + pInput->S->index ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, " <%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, "\'" ); - } - fprintf( pFile, " )\n" ); -/* - fprintf( pFile, " ) " ); - { - DdNode * bLocal; - bLocal = Dsd_TreeGetPrimeFunction( dd, pNodeDsd ); Cudd_Ref( bLocal ); - Extra_bddPrint( dd, bLocal ); - Cudd_RecursiveDeref( dd, bLocal ); - } -*/ - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); - } - } - else if ( pNode->Type == DSD_NODE_OR ) - { - // print the line - fprintf( pFile, "OR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - if ( i ) - fprintf( pFile, "," ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - fprintf( pFile, " %c", 'a' + pInput->S->index ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, " <%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, "\'" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); - } - } - else if ( pNode->Type == DSD_NODE_EXOR ) - { - // print the line - fprintf( pFile, "EXOR(" ); - for ( i = 0; i < pNode->nDecs; i++ ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - fCompNew = (int)( pInput != pNode->pDecs[i] ); - assert( fCompNew == 0 ); - if ( i ) - fprintf( pFile, "," ); - if ( pInput->Type == DSD_NODE_BUF ) - { - pInputNums[i] = 0; - fprintf( pFile, " %c", 'a' + pInput->S->index ); - } - else - { - pInputNums[i] = (*pSigCounter)++; - fprintf( pFile, " <%d>", pInputNums[i] ); - } - if ( fCompNew ) - fprintf( pFile, "\'" ); - } - fprintf( pFile, " )\n" ); - // call recursively for the following blocks - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pInputNums[i] ) - { - pInput = Dsd_Regular( pNode->pDecs[i] ); - sprintf( Buffer, "<%d>", pInputNums[i] ); - Dsd_NodePrint_rec( pFile, Dsd_Regular( pNode->pDecs[i] ), 0, Buffer, nOffset + 6, pSigCounter ); - } - } - free( pInputNums ); -} - - -/**Function************************************************************* - - Synopsis [Retuns the function of one node of the decomposition tree.] - - Description [This is the old procedure. It is now superceded by the - procedure Dsd_TreeGetPrimeFunction() found in "dsdLocal.c".] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Dsd_TreeGetPrimeFunctionOld( DdManager * dd, Dsd_Node_t * pNode, int fRemap ) -{ - DdNode * bCof0, * bCof1, * bCube0, * bCube1, * bNewFunc, * bTemp; - int i; - int fAllBuffs = 1; - static int Permute[MAXINPUTS]; - - assert( pNode ); - assert( !Dsd_IsComplement( pNode ) ); - assert( pNode->Type == DSD_NODE_PRIME ); - - // transform the function of this block to depend on inputs - // corresponding to the formal inputs - - // first, substitute those inputs that have some blocks associated with them - // second, remap the inputs to the top of the manager (then, it is easy to output them) - - // start the function - bNewFunc = pNode->G; Cudd_Ref( bNewFunc ); - // go over all primary inputs - for ( i = 0; i < pNode->nDecs; i++ ) - if ( pNode->pDecs[i]->Type != DSD_NODE_BUF ) // remap only if it is not the buffer - { - bCube0 = Extra_bddFindOneCube( dd, Cudd_Not(pNode->pDecs[i]->G) ); Cudd_Ref( bCube0 ); - bCof0 = Cudd_Cofactor( dd, bNewFunc, bCube0 ); Cudd_Ref( bCof0 ); - Cudd_RecursiveDeref( dd, bCube0 ); - - bCube1 = Extra_bddFindOneCube( dd, pNode->pDecs[i]->G ); Cudd_Ref( bCube1 ); - bCof1 = Cudd_Cofactor( dd, bNewFunc, bCube1 ); Cudd_Ref( bCof1 ); - Cudd_RecursiveDeref( dd, bCube1 ); - - Cudd_RecursiveDeref( dd, bNewFunc ); - - // use the variable in the i-th level of the manager -// bNewFunc = Cudd_bddIte( dd, dd->vars[dd->invperm[i]],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - // use the first variale in the support of the component - bNewFunc = Cudd_bddIte( dd, dd->vars[pNode->pDecs[i]->S->index],bCof1,bCof0 ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); - } - - if ( fRemap ) - { - // remap the function to the top of the manager - // remap the function to the first variables of the manager - for ( i = 0; i < pNode->nDecs; i++ ) - // Permute[ pNode->pDecs[i]->S->index ] = dd->invperm[i]; - Permute[ pNode->pDecs[i]->S->index ] = i; - - bNewFunc = Cudd_bddPermute( dd, bTemp = bNewFunc, Permute ); Cudd_Ref( bNewFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - - Cudd_Deref( bNewFunc ); - return bNewFunc; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/dsd/module.make b/src/bdd/dsd/module.make deleted file mode 100644 index f5e6673d..00000000 --- a/src/bdd/dsd/module.make +++ /dev/null @@ -1,6 +0,0 @@ -SRC += src/bdd/dsd/dsdApi.c \ - src/bdd/dsd/dsdCheck.c \ - src/bdd/dsd/dsdLocal.c \ - src/bdd/dsd/dsdMan.c \ - src/bdd/dsd/dsdProc.c \ - src/bdd/dsd/dsdTree.c diff --git a/src/bdd/epd/epd.c b/src/bdd/epd/epd.c deleted file mode 100644 index a80240bc..00000000 --- a/src/bdd/epd/epd.c +++ /dev/null @@ -1,1314 +0,0 @@ -/**CFile*********************************************************************** - - FileName [epd.c] - - PackageName [epd] - - Synopsis [Arithmetic functions with extended double precision.] - - Description [] - - SeeAlso [] - - Author [In-Ho Moon] - - Copyright [ This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: epd.c,v 1.1.1.1 2003/02/24 22:23:57 wjiang Exp $] - -******************************************************************************/ - -#include -#include -#include -#include -#include "util_hack.h" -#include "epd.h" - - -/**Function******************************************************************** - - Synopsis [Allocates an EpDouble struct.] - - Description [Allocates an EpDouble struct.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -EpDouble * -EpdAlloc() -{ - EpDouble *epd; - - epd = ALLOC(EpDouble, 1); - return(epd); -} - - -/**Function******************************************************************** - - Synopsis [Compares two EpDouble struct.] - - Description [Compares two EpDouble struct.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdCmp(const char *key1, const char *key2) -{ - EpDouble *epd1 = (EpDouble *) key1; - EpDouble *epd2 = (EpDouble *) key2; - if (epd1->type.value != epd2->type.value || - epd1->exponent != epd2->exponent) { - return(1); - } - return(0); -} - - -/**Function******************************************************************** - - Synopsis [Frees an EpDouble struct.] - - Description [Frees an EpDouble struct.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdFree(EpDouble *epd) -{ - FREE(epd); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdGetString(EpDouble *epd, char *str) -{ - double value; - int exponent; - char *pos; - - if (IsNanDouble(epd->type.value)) { - sprintf(str, "NaN"); - return; - } else if (IsInfDouble(epd->type.value)) { - if (epd->type.bits.sign == 1) - sprintf(str, "-Inf"); - else - sprintf(str, "Inf"); - return; - } - - assert(epd->type.bits.exponent == EPD_MAX_BIN || - epd->type.bits.exponent == 0); - - EpdGetValueAndDecimalExponent(epd, &value, &exponent); - sprintf(str, "%e", value); - pos = strstr(str, "e"); - if (exponent >= 0) { - if (exponent < 10) - sprintf(pos + 1, "+0%d", exponent); - else - sprintf(pos + 1, "+%d", exponent); - } else { - exponent *= -1; - if (exponent < 10) - sprintf(pos + 1, "-0%d", exponent); - else - sprintf(pos + 1, "-%d", exponent); - } -} - - -/**Function******************************************************************** - - Synopsis [Converts double to EpDouble struct.] - - Description [Converts double to EpDouble struct.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdConvert(double value, EpDouble *epd) -{ - epd->type.value = value; - epd->exponent = 0; - EpdNormalize(epd); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMultiply(EpDouble *epd1, double value) -{ - EpDouble epd2; - double tmp; - int exponent; - - if (EpdIsNan(epd1) || IsNanDouble(value)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || IsInfDouble(value)) { - int sign; - - EpdConvert(value, &epd2); - sign = epd1->type.bits.sign ^ epd2.type.bits.sign; - EpdMakeInf(epd1, sign); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - - EpdConvert(value, &epd2); - tmp = epd1->type.value * epd2.type.value; - exponent = epd1->exponent + epd2.exponent; - epd1->type.value = tmp; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMultiply2(EpDouble *epd1, EpDouble *epd2) -{ - double value; - int exponent; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd1, sign); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - value = epd1->type.value * epd2->type.value; - exponent = epd1->exponent + epd2->exponent; - epd1->type.value = value; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2) -{ - double value; - int exponent; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd1, sign); - return; - } - - value = epd1->type.value * epd2->type.value; - exponent = epd1->exponent + epd2->exponent; - epd1->type.value = value; - epd1->exponent = exponent; - EpdNormalizeDecimal(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) -{ - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd3, sign); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - epd3->type.value = epd1->type.value * epd2->type.value; - epd3->exponent = epd1->exponent + epd2->exponent; - EpdNormalize(epd3); -} - - -/**Function******************************************************************** - - Synopsis [Multiplies two arbitrary precision double values.] - - Description [Multiplies two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) -{ - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd3, sign); - return; - } - - epd3->type.value = epd1->type.value * epd2->type.value; - epd3->exponent = epd1->exponent + epd2->exponent; - EpdNormalizeDecimal(epd3); -} - - -/**Function******************************************************************** - - Synopsis [Divides two arbitrary precision double values.] - - Description [Divides two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdDivide(EpDouble *epd1, double value) -{ - EpDouble epd2; - double tmp; - int exponent; - - if (EpdIsNan(epd1) || IsNanDouble(value)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || IsInfDouble(value)) { - int sign; - - EpdConvert(value, &epd2); - if (EpdIsInf(epd1) && IsInfDouble(value)) { - EpdMakeNan(epd1); - } else if (EpdIsInf(epd1)) { - sign = epd1->type.bits.sign ^ epd2.type.bits.sign; - EpdMakeInf(epd1, sign); - } else { - sign = epd1->type.bits.sign ^ epd2.type.bits.sign; - EpdMakeZero(epd1, sign); - } - return; - } - - if (value == 0.0) { - EpdMakeNan(epd1); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - - EpdConvert(value, &epd2); - tmp = epd1->type.value / epd2.type.value; - exponent = epd1->exponent - epd2.exponent; - epd1->type.value = tmp; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Divides two arbitrary precision double values.] - - Description [Divides two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdDivide2(EpDouble *epd1, EpDouble *epd2) -{ - double value; - int exponent; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - EpdMakeNan(epd1); - } else if (EpdIsInf(epd1)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd1, sign); - } else { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeZero(epd1, sign); - } - return; - } - - if (epd2->type.value == 0.0) { - EpdMakeNan(epd1); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - value = epd1->type.value / epd2->type.value; - exponent = epd1->exponent - epd2->exponent; - epd1->type.value = value; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Divides two arbitrary precision double values.] - - Description [Divides two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) -{ - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd3); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - EpdMakeNan(epd3); - } else if (EpdIsInf(epd1)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeInf(epd3, sign); - } else { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - EpdMakeZero(epd3, sign); - } - return; - } - - if (epd2->type.value == 0.0) { - EpdMakeNan(epd3); - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - epd3->type.value = epd1->type.value / epd2->type.value; - epd3->exponent = epd1->exponent - epd2->exponent; - EpdNormalize(epd3); -} - - -/**Function******************************************************************** - - Synopsis [Adds two arbitrary precision double values.] - - Description [Adds two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdAdd(EpDouble *epd1, double value) -{ - EpDouble epd2; - double tmp; - int exponent, diff; - - if (EpdIsNan(epd1) || IsNanDouble(value)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || IsInfDouble(value)) { - int sign; - - EpdConvert(value, &epd2); - if (EpdIsInf(epd1) && IsInfDouble(value)) { - sign = epd1->type.bits.sign ^ epd2.type.bits.sign; - if (sign == 1) - EpdMakeNan(epd1); - } else if (EpdIsInf(&epd2)) { - EpdCopy(&epd2, epd1); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - - EpdConvert(value, &epd2); - if (epd1->exponent > epd2.exponent) { - diff = epd1->exponent - epd2.exponent; - if (diff <= EPD_MAX_BIN) - tmp = epd1->type.value + epd2.type.value / pow((double)2.0, (double)diff); - else - tmp = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2.exponent) { - diff = epd2.exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) - tmp = epd1->type.value / pow((double)2.0, (double)diff) + epd2.type.value; - else - tmp = epd2.type.value; - exponent = epd2.exponent; - } else { - tmp = epd1->type.value + epd2.type.value; - exponent = epd1->exponent; - } - epd1->type.value = tmp; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Adds two arbitrary precision double values.] - - Description [Adds two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdAdd2(EpDouble *epd1, EpDouble *epd2) -{ - double value; - int exponent, diff; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - if (sign == 1) - EpdMakeNan(epd1); - } else if (EpdIsInf(epd2)) { - EpdCopy(epd2, epd1); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - if (epd1->exponent > epd2->exponent) { - diff = epd1->exponent - epd2->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value + - epd2->type.value / pow((double)2.0, (double)diff); - } else - value = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2->exponent) { - diff = epd2->exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value / pow((double)2.0, (double)diff) + - epd2->type.value; - } else - value = epd2->type.value; - exponent = epd2->exponent; - } else { - value = epd1->type.value + epd2->type.value; - exponent = epd1->exponent; - } - epd1->type.value = value; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Adds two arbitrary precision double values.] - - Description [Adds two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) -{ - double value; - int exponent, diff; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd3); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - if (sign == 1) - EpdMakeNan(epd3); - else - EpdCopy(epd1, epd3); - } else if (EpdIsInf(epd1)) { - EpdCopy(epd1, epd3); - } else { - EpdCopy(epd2, epd3); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - if (epd1->exponent > epd2->exponent) { - diff = epd1->exponent - epd2->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value + - epd2->type.value / pow((double)2.0, (double)diff); - } else - value = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2->exponent) { - diff = epd2->exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value / pow((double)2.0, (double)diff) + - epd2->type.value; - } else - value = epd2->type.value; - exponent = epd2->exponent; - } else { - value = epd1->type.value + epd2->type.value; - exponent = epd1->exponent; - } - epd3->type.value = value; - epd3->exponent = exponent; - EpdNormalize(epd3); -} - - -/**Function******************************************************************** - - Synopsis [Subtracts two arbitrary precision double values.] - - Description [Subtracts two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdSubtract(EpDouble *epd1, double value) -{ - EpDouble epd2; - double tmp; - int exponent, diff; - - if (EpdIsNan(epd1) || IsNanDouble(value)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || IsInfDouble(value)) { - int sign; - - EpdConvert(value, &epd2); - if (EpdIsInf(epd1) && IsInfDouble(value)) { - sign = epd1->type.bits.sign ^ epd2.type.bits.sign; - if (sign == 0) - EpdMakeNan(epd1); - } else if (EpdIsInf(&epd2)) { - EpdCopy(&epd2, epd1); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - - EpdConvert(value, &epd2); - if (epd1->exponent > epd2.exponent) { - diff = epd1->exponent - epd2.exponent; - if (diff <= EPD_MAX_BIN) - tmp = epd1->type.value - epd2.type.value / pow((double)2.0, (double)diff); - else - tmp = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2.exponent) { - diff = epd2.exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) - tmp = epd1->type.value / pow((double)2.0, (double)diff) - epd2.type.value; - else - tmp = epd2.type.value * (double)(-1.0); - exponent = epd2.exponent; - } else { - tmp = epd1->type.value - epd2.type.value; - exponent = epd1->exponent; - } - epd1->type.value = tmp; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Subtracts two arbitrary precision double values.] - - Description [Subtracts two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdSubtract2(EpDouble *epd1, EpDouble *epd2) -{ - double value; - int exponent, diff; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd1); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - if (sign == 0) - EpdMakeNan(epd1); - } else if (EpdIsInf(epd2)) { - EpdCopy(epd2, epd1); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - if (epd1->exponent > epd2->exponent) { - diff = epd1->exponent - epd2->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value - - epd2->type.value / pow((double)2.0, (double)diff); - } else - value = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2->exponent) { - diff = epd2->exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value / pow((double)2.0, (double)diff) - - epd2->type.value; - } else - value = epd2->type.value * (double)(-1.0); - exponent = epd2->exponent; - } else { - value = epd1->type.value - epd2->type.value; - exponent = epd1->exponent; - } - epd1->type.value = value; - epd1->exponent = exponent; - EpdNormalize(epd1); -} - - -/**Function******************************************************************** - - Synopsis [Subtracts two arbitrary precision double values.] - - Description [Subtracts two arbitrary precision double values.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3) -{ - double value; - int exponent, diff; - - if (EpdIsNan(epd1) || EpdIsNan(epd2)) { - EpdMakeNan(epd3); - return; - } else if (EpdIsInf(epd1) || EpdIsInf(epd2)) { - int sign; - - if (EpdIsInf(epd1) && EpdIsInf(epd2)) { - sign = epd1->type.bits.sign ^ epd2->type.bits.sign; - if (sign == 0) - EpdCopy(epd1, epd3); - else - EpdMakeNan(epd3); - } else if (EpdIsInf(epd1)) { - EpdCopy(epd1, epd1); - } else { - sign = epd2->type.bits.sign ^ 0x1; - EpdMakeInf(epd3, sign); - } - return; - } - - assert(epd1->type.bits.exponent == EPD_MAX_BIN); - assert(epd2->type.bits.exponent == EPD_MAX_BIN); - - if (epd1->exponent > epd2->exponent) { - diff = epd1->exponent - epd2->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value - - epd2->type.value / pow((double)2.0, (double)diff); - } else - value = epd1->type.value; - exponent = epd1->exponent; - } else if (epd1->exponent < epd2->exponent) { - diff = epd2->exponent - epd1->exponent; - if (diff <= EPD_MAX_BIN) { - value = epd1->type.value / pow((double)2.0, (double)diff) - - epd2->type.value; - } else - value = epd2->type.value * (double)(-1.0); - exponent = epd2->exponent; - } else { - value = epd1->type.value - epd2->type.value; - exponent = epd1->exponent; - } - epd3->type.value = value; - epd3->exponent = exponent; - EpdNormalize(epd3); -} - - -/**Function******************************************************************** - - Synopsis [Computes arbitrary precision pow of base 2.] - - Description [Computes arbitrary precision pow of base 2.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdPow2(int n, EpDouble *epd) -{ - if (n <= EPD_MAX_BIN) { - EpdConvert(pow((double)2.0, (double)n), epd); - } else { - EpDouble epd1, epd2; - int n1, n2; - - n1 = n / 2; - n2 = n - n1; - EpdPow2(n1, &epd1); - EpdPow2(n2, &epd2); - EpdMultiply3(&epd1, &epd2, epd); - } -} - - -/**Function******************************************************************** - - Synopsis [Computes arbitrary precision pow of base 2.] - - Description [Computes arbitrary precision pow of base 2.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdPow2Decimal(int n, EpDouble *epd) -{ - if (n <= EPD_MAX_BIN) { - epd->type.value = pow((double)2.0, (double)n); - epd->exponent = 0; - EpdNormalizeDecimal(epd); - } else { - EpDouble epd1, epd2; - int n1, n2; - - n1 = n / 2; - n2 = n - n1; - EpdPow2Decimal(n1, &epd1); - EpdPow2Decimal(n2, &epd2); - EpdMultiply3Decimal(&epd1, &epd2, epd); - } -} - - -/**Function******************************************************************** - - Synopsis [Normalize an arbitrary precision double value.] - - Description [Normalize an arbitrary precision double value.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdNormalize(EpDouble *epd) -{ - int exponent; - - if (IsNanOrInfDouble(epd->type.value)) { - epd->exponent = 0; - return; - } - - exponent = EpdGetExponent(epd->type.value); - if (exponent == EPD_MAX_BIN) - return; - exponent -= EPD_MAX_BIN; - epd->type.bits.exponent = EPD_MAX_BIN; - epd->exponent += exponent; -} - - -/**Function******************************************************************** - - Synopsis [Normalize an arbitrary precision double value.] - - Description [Normalize an arbitrary precision double value.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdNormalizeDecimal(EpDouble *epd) -{ - int exponent; - - if (IsNanOrInfDouble(epd->type.value)) { - epd->exponent = 0; - return; - } - - exponent = EpdGetExponentDecimal(epd->type.value); - epd->type.value /= pow((double)10.0, (double)exponent); - epd->exponent += exponent; -} - - -/**Function******************************************************************** - - Synopsis [Returns value and decimal exponent of EpDouble.] - - Description [Returns value and decimal exponent of EpDouble.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent) -{ - EpDouble epd1, epd2; - - if (EpdIsNanOrInf(epd)) - return; - - if (EpdIsZero(epd)) { - *value = 0.0; - *exponent = 0; - return; - } - - epd1.type.value = epd->type.value; - epd1.exponent = 0; - EpdPow2Decimal(epd->exponent, &epd2); - EpdMultiply2Decimal(&epd1, &epd2); - - *value = epd1.type.value; - *exponent = epd1.exponent; -} - -/**Function******************************************************************** - - Synopsis [Returns the exponent value of a double.] - - Description [Returns the exponent value of a double.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdGetExponent(double value) -{ - int exponent; - EpDouble epd; - - epd.type.value = value; - exponent = epd.type.bits.exponent; - return(exponent); -} - - -/**Function******************************************************************** - - Synopsis [Returns the decimal exponent value of a double.] - - Description [Returns the decimal exponent value of a double.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdGetExponentDecimal(double value) -{ - char *pos, str[24]; - int exponent; - - sprintf(str, "%E", value); - pos = strstr(str, "E"); - sscanf(pos, "E%d", &exponent); - return(exponent); -} - - -/**Function******************************************************************** - - Synopsis [Makes EpDouble Inf.] - - Description [Makes EpDouble Inf.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMakeInf(EpDouble *epd, int sign) -{ - epd->type.bits.mantissa1 = 0; - epd->type.bits.mantissa0 = 0; - epd->type.bits.exponent = EPD_EXP_INF; - epd->type.bits.sign = sign; - epd->exponent = 0; -} - - -/**Function******************************************************************** - - Synopsis [Makes EpDouble Zero.] - - Description [Makes EpDouble Zero.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMakeZero(EpDouble *epd, int sign) -{ - epd->type.bits.mantissa1 = 0; - epd->type.bits.mantissa0 = 0; - epd->type.bits.exponent = 0; - epd->type.bits.sign = sign; - epd->exponent = 0; -} - - -/**Function******************************************************************** - - Synopsis [Makes EpDouble NaN.] - - Description [Makes EpDouble NaN.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdMakeNan(EpDouble *epd) -{ - epd->type.nan.mantissa1 = 0; - epd->type.nan.mantissa0 = 0; - epd->type.nan.quiet_bit = 1; - epd->type.nan.exponent = EPD_EXP_INF; - epd->type.nan.sign = 1; - epd->exponent = 0; -} - - -/**Function******************************************************************** - - Synopsis [Copies a EpDouble struct.] - - Description [Copies a EpDouble struct.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void -EpdCopy(EpDouble *from, EpDouble *to) -{ - to->type.value = from->type.value; - to->exponent = from->exponent; -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is Inf.] - - Description [Checks whether the value is Inf.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdIsInf(EpDouble *epd) -{ - return(IsInfDouble(epd->type.value)); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is Zero.] - - Description [Checks whether the value is Zero.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdIsZero(EpDouble *epd) -{ - if (epd->type.value == 0.0) - return(1); - else - return(0); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is NaN.] - - Description [Checks whether the value is NaN.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdIsNan(EpDouble *epd) -{ - return(IsNanDouble(epd->type.value)); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is NaN or Inf.] - - Description [Checks whether the value is NaN or Inf.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -EpdIsNanOrInf(EpDouble *epd) -{ - return(IsNanOrInfDouble(epd->type.value)); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is Inf.] - - Description [Checks whether the value is Inf.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -IsInfDouble(double value) -{ - IeeeDouble *ptr = (IeeeDouble *)(&value); - - if (ptr->exponent == EPD_EXP_INF && - ptr->mantissa0 == 0 && - ptr->mantissa1 == 0) { - if (ptr->sign == 0) - return(1); - else - return(-1); - } - return(0); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is NaN.] - - Description [Checks whether the value is NaN.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -IsNanDouble(double value) -{ - IeeeNan *ptr = (IeeeNan *)(&value); - - if (ptr->exponent == EPD_EXP_INF && - ptr->sign == 1 && - ptr->quiet_bit == 1 && - ptr->mantissa0 == 0 && - ptr->mantissa1 == 0) { - return(1); - } - return(0); -} - - -/**Function******************************************************************** - - Synopsis [Checks whether the value is NaN or Inf.] - - Description [Checks whether the value is NaN or Inf.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int -IsNanOrInfDouble(double value) -{ - IeeeNan *ptr = (IeeeNan *)(&value); - - if (ptr->exponent == EPD_EXP_INF && - ptr->mantissa0 == 0 && - ptr->mantissa1 == 0 && - (ptr->sign == 1 || ptr->quiet_bit == 0)) { - return(1); - } - return(0); -} diff --git a/src/bdd/epd/epd.h b/src/bdd/epd/epd.h deleted file mode 100644 index 66db80e3..00000000 --- a/src/bdd/epd/epd.h +++ /dev/null @@ -1,160 +0,0 @@ -/**CHeaderFile***************************************************************** - - FileName [epd.h] - - PackageName [epd] - - Synopsis [The University of Colorado extended double precision package.] - - Description [arithmetic functions with extended double precision.] - - SeeAlso [] - - Author [In-Ho Moon] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: epd.h,v 1.1.1.1 2003/02/24 22:23:57 wjiang Exp $] - -******************************************************************************/ - -#ifndef _EPD -#define _EPD - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#define EPD_MAX_BIN 1023 -#define EPD_MAX_DEC 308 -#define EPD_EXP_INF 0x7ff - -/*---------------------------------------------------------------------------*/ -/* Structure declarations */ -/*---------------------------------------------------------------------------*/ - -/**Struct********************************************************************** - - Synopsis [IEEE double struct.] - - Description [IEEE double struct.] - - SeeAlso [] - -******************************************************************************/ -#ifdef EPD_BIG_ENDIAN -struct IeeeDoubleStruct { /* BIG_ENDIAN */ - unsigned int sign: 1; - unsigned int exponent: 11; - unsigned int mantissa0: 20; - unsigned int mantissa1: 32; -}; -#else -struct IeeeDoubleStruct { /* LITTLE_ENDIAN */ - unsigned int mantissa1: 32; - unsigned int mantissa0: 20; - unsigned int exponent: 11; - unsigned int sign: 1; -}; -#endif - -/**Struct********************************************************************** - - Synopsis [IEEE double NaN struct.] - - Description [IEEE double NaN struct.] - - SeeAlso [] - -******************************************************************************/ -#ifdef EPD_BIG_ENDIAN -struct IeeeNanStruct { /* BIG_ENDIAN */ - unsigned int sign: 1; - unsigned int exponent: 11; - unsigned int quiet_bit: 1; - unsigned int mantissa0: 19; - unsigned int mantissa1: 32; -}; -#else -struct IeeeNanStruct { /* LITTLE_ENDIAN */ - unsigned int mantissa1: 32; - unsigned int mantissa0: 19; - unsigned int quiet_bit: 1; - unsigned int exponent: 11; - unsigned int sign: 1; -}; -#endif - -/**Struct********************************************************************** - - Synopsis [Extended precision double to keep very large value.] - - Description [Extended precision double to keep very large value.] - - SeeAlso [] - -******************************************************************************/ -struct EpDoubleStruct { - union { - double value; - struct IeeeDoubleStruct bits; - struct IeeeNanStruct nan; - } type; - int exponent; -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ -typedef struct EpDoubleStruct EpDouble; -typedef struct IeeeDoubleStruct IeeeDouble; -typedef struct IeeeNanStruct IeeeNan; - - -/*---------------------------------------------------------------------------*/ -/* Function prototypes */ -/*---------------------------------------------------------------------------*/ - -EpDouble *EpdAlloc(); -int EpdCmp(const char *key1, const char *key2); -void EpdFree(EpDouble *epd); -void EpdGetString(EpDouble *epd, char *str); -void EpdConvert(double value, EpDouble *epd); -void EpdMultiply(EpDouble *epd1, double value); -void EpdMultiply2(EpDouble *epd1, EpDouble *epd2); -void EpdMultiply2Decimal(EpDouble *epd1, EpDouble *epd2); -void EpdMultiply3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); -void EpdMultiply3Decimal(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); -void EpdDivide(EpDouble *epd1, double value); -void EpdDivide2(EpDouble *epd1, EpDouble *epd2); -void EpdDivide3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); -void EpdAdd(EpDouble *epd1, double value); -void EpdAdd2(EpDouble *epd1, EpDouble *epd2); -void EpdAdd3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); -void EpdSubtract(EpDouble *epd1, double value); -void EpdSubtract2(EpDouble *epd1, EpDouble *epd2); -void EpdSubtract3(EpDouble *epd1, EpDouble *epd2, EpDouble *epd3); -void EpdPow2(int n, EpDouble *epd); -void EpdPow2Decimal(int n, EpDouble *epd); -void EpdNormalize(EpDouble *epd); -void EpdNormalizeDecimal(EpDouble *epd); -void EpdGetValueAndDecimalExponent(EpDouble *epd, double *value, int *exponent); -int EpdGetExponent(double value); -int EpdGetExponentDecimal(double value); -void EpdMakeInf(EpDouble *epd, int sign); -void EpdMakeZero(EpDouble *epd, int sign); -void EpdMakeNan(EpDouble *epd); -void EpdCopy(EpDouble *from, EpDouble *to); -int EpdIsInf(EpDouble *epd); -int EpdIsZero(EpDouble *epd); -int EpdIsNan(EpDouble *epd); -int EpdIsNanOrInf(EpDouble *epd); -int IsInfDouble(double value); -int IsNanDouble(double value); -int IsNanOrInfDouble(double value); - -#endif /* _EPD */ diff --git a/src/bdd/epd/module.make b/src/bdd/epd/module.make deleted file mode 100644 index a8084db1..00000000 --- a/src/bdd/epd/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += src/bdd/epd/epd.c diff --git a/src/bdd/mtr/module.make b/src/bdd/mtr/module.make deleted file mode 100644 index d7fa63d9..00000000 --- a/src/bdd/mtr/module.make +++ /dev/null @@ -1,2 +0,0 @@ -SRC += src/bdd/mtr/mtrBasic.c \ - src/bdd/mtr/mtrGroup.c diff --git a/src/bdd/mtr/mtr.h b/src/bdd/mtr/mtr.h deleted file mode 100644 index 201329ae..00000000 --- a/src/bdd/mtr/mtr.h +++ /dev/null @@ -1,173 +0,0 @@ -/**CHeaderFile***************************************************************** - - FileName [mtr.h] - - PackageName [mtr] - - Synopsis [Multiway-branch tree manipulation] - - Description [This package provides two layers of functions. Functions - of the lower level manipulate multiway-branch trees, implemented - according to the classical scheme whereby each node points to its - first child and its previous and next siblings. These functions are - collected in mtrBasic.c.

              - Functions of the upper layer deal with group trees, that is the trees - used by group sifting to represent the grouping of variables. These - functions are collected in mtrGroup.c.] - - SeeAlso [The CUDD package documentation; specifically on group - sifting.] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: mtr.h,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $] - -******************************************************************************/ - -#ifndef __MTR -#define __MTR - -/*---------------------------------------------------------------------------*/ -/* Nested includes */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef SIZEOF_VOID_P -#define SIZEOF_VOID_P 4 -#endif -#ifndef SIZEOF_INT -#define SIZEOF_INT 4 -#endif - -#undef CONST -#if defined(__STDC__) || defined(__cplusplus) -#define CONST const -#else /* !(__STDC__ || __cplusplus) */ -#define CONST -#endif /* !(__STDC__ || __cplusplus) */ - -/* These are potential duplicates. */ -#ifndef EXTERN -# ifdef __cplusplus -# define EXTERN extern "C" -# else -# define EXTERN extern -# endif -#endif -#ifndef ARGS -# if defined(__STDC__) || defined(__cplusplus) -# define ARGS(protos) protos /* ANSI C */ -# else /* !(__STDC__ || __cplusplus) */ -# define ARGS(protos) () /* K&R C */ -# endif /* !(__STDC__ || __cplusplus) */ -#endif - -#if defined(__GNUC__) -#define MTR_INLINE __inline__ -# if (__GNUC__ >2 || __GNUC_MINOR__ >=7) -# define MTR_UNUSED __attribute__ ((unused)) -# else -# define MTR_UNUSED -# endif -#else -#define MTR_INLINE -#define MTR_UNUSED -#endif - -/* Flag definitions */ -#define MTR_DEFAULT 0x00000000 -#define MTR_TERMINAL 0x00000001 -#define MTR_SOFT 0x00000002 -#define MTR_FIXED 0x00000004 -#define MTR_NEWNODE 0x00000008 - -/* MTR_MAXHIGH is defined in such a way that on 32-bit and 64-bit -** machines one can cast a value to (int) without generating a negative -** number. -*/ -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -#define MTR_MAXHIGH (((MtrHalfWord) ~0) >> 1) -#else -#define MTR_MAXHIGH ((MtrHalfWord) ~0) -#endif - - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -#if SIZEOF_VOID_P == 8 && SIZEOF_INT == 4 -typedef unsigned int MtrHalfWord; -#else -typedef unsigned short MtrHalfWord; -#endif - -typedef struct MtrNode { - MtrHalfWord flags; - MtrHalfWord low; - MtrHalfWord size; - MtrHalfWord index; - struct MtrNode *parent; - struct MtrNode *child; - struct MtrNode *elder; - struct MtrNode *younger; -} MtrNode; - - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/* Flag manipulation macros */ -#define MTR_SET(node, flag) (node->flags |= (flag)) -#define MTR_RESET(node, flag) (node->flags &= ~ (flag)) -#define MTR_TEST(node, flag) (node->flags & (flag)) - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Function prototypes */ -/*---------------------------------------------------------------------------*/ - -EXTERN MtrNode * Mtr_AllocNode ARGS(()); -EXTERN void Mtr_DeallocNode ARGS((MtrNode *node)); -EXTERN MtrNode * Mtr_InitTree ARGS(()); -EXTERN void Mtr_FreeTree ARGS((MtrNode *node)); -EXTERN MtrNode * Mtr_CopyTree ARGS((MtrNode *node, int expansion)); -EXTERN void Mtr_MakeFirstChild ARGS((MtrNode *parent, MtrNode *child)); -EXTERN void Mtr_MakeLastChild ARGS((MtrNode *parent, MtrNode *child)); -EXTERN MtrNode * Mtr_CreateFirstChild ARGS((MtrNode *parent)); -EXTERN MtrNode * Mtr_CreateLastChild ARGS((MtrNode *parent)); -EXTERN void Mtr_MakeNextSibling ARGS((MtrNode *first, MtrNode *second)); -EXTERN void Mtr_PrintTree ARGS((MtrNode *node)); -EXTERN MtrNode * Mtr_InitGroupTree ARGS((int lower, int size)); -EXTERN MtrNode * Mtr_MakeGroup ARGS((MtrNode *root, unsigned int low, unsigned int high, unsigned int flags)); -EXTERN MtrNode * Mtr_DissolveGroup ARGS((MtrNode *group)); -EXTERN MtrNode * Mtr_FindGroup ARGS((MtrNode *root, unsigned int low, unsigned int high)); -EXTERN int Mtr_SwapGroups ARGS((MtrNode *first, MtrNode *second)); -EXTERN void Mtr_PrintGroups ARGS((MtrNode *root, int silent)); -EXTERN MtrNode * Mtr_ReadGroups ARGS((FILE *fp, int nleaves)); - -/**AutomaticEnd***************************************************************/ - -#endif /* __MTR */ diff --git a/src/bdd/mtr/mtrBasic.c b/src/bdd/mtr/mtrBasic.c deleted file mode 100644 index 94105282..00000000 --- a/src/bdd/mtr/mtrBasic.c +++ /dev/null @@ -1,426 +0,0 @@ -/**CFile*********************************************************************** - - FileName [mtrBasic.c] - - PackageName [mtr] - - Synopsis [Basic manipulation of multiway branching trees.] - - Description [External procedures included in this module: -

                -
              • Mtr_AllocNode() -
              • Mtr_DeallocNode() -
              • Mtr_InitTree() -
              • Mtr_FreeTree() -
              • Mtr_CopyTree() -
              • Mtr_MakeFirstChild() -
              • Mtr_MakeLastChild() -
              • Mtr_CreateFirstChild() -
              • Mtr_CreateLastChild() -
              • Mtr_MakeNextSibling() -
              • Mtr_PrintTree() -
              - ] - - SeeAlso [cudd package] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "mtrInt.h" - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] MTR_UNUSED = "$Id: mtrBasic.c,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Allocates new tree node.] - - Description [Allocates new tree node. Returns pointer to node.] - - SideEffects [None] - - SeeAlso [Mtr_DeallocNode] - -******************************************************************************/ -MtrNode * -Mtr_AllocNode( - ) -{ - MtrNode *node; - - node = ALLOC(MtrNode,1); - return node; - -} /* Mtr_AllocNode */ - - -/**Function******************************************************************** - - Synopsis [Deallocates tree node.] - - Description [] - - SideEffects [None] - - SeeAlso [Mtr_AllocNode] - -******************************************************************************/ -void -Mtr_DeallocNode( - MtrNode * node /* node to be deallocated */) -{ - FREE(node); - return; - -} /* end of Mtr_DeallocNode */ - - -/**Function******************************************************************** - - Synopsis [Initializes tree with one node.] - - Description [Initializes tree with one node. Returns pointer to node.] - - SideEffects [None] - - SeeAlso [Mtr_FreeTree Mtr_InitGroupTree] - -******************************************************************************/ -MtrNode * -Mtr_InitTree( - ) -{ - MtrNode *node; - - node = Mtr_AllocNode(); - if (node == NULL) return(NULL); - - node->parent = node->child = node->elder = node->younger = NULL; - node->flags = 0; - - return(node); - -} /* end of Mtr_InitTree */ - - -/**Function******************************************************************** - - Synopsis [Disposes of tree rooted at node.] - - Description [] - - SideEffects [None] - - SeeAlso [Mtr_InitTree] - -******************************************************************************/ -void -Mtr_FreeTree( - MtrNode * node) -{ - if (node == NULL) return; - if (! MTR_TEST(node,MTR_TERMINAL)) Mtr_FreeTree(node->child); - Mtr_FreeTree(node->younger); - Mtr_DeallocNode(node); - return; - -} /* end of Mtr_FreeTree */ - - -/**Function******************************************************************** - - Synopsis [Makes a copy of tree.] - - Description [Makes a copy of tree. If parameter expansion is greater - than 1, it will expand the tree by that factor. It is an error for - expansion to be less than 1. Returns a pointer to the copy if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Mtr_InitTree] - -******************************************************************************/ -MtrNode * -Mtr_CopyTree( - MtrNode * node, - int expansion) -{ - MtrNode *copy; - - if (node == NULL) return(NULL); - if (expansion < 1) return(NULL); - copy = Mtr_AllocNode(); - if (copy == NULL) return(NULL); - copy->parent = copy->elder = copy->child = copy->younger = NULL; - if (node->child != NULL) { - copy->child = Mtr_CopyTree(node->child, expansion); - if (copy->child == NULL) { - Mtr_DeallocNode(copy); - return(NULL); - } - } - if (node->younger != NULL) { - copy->younger = Mtr_CopyTree(node->younger, expansion); - if (copy->younger == NULL) { - Mtr_FreeTree(copy); - return(NULL); - } - } - copy->flags = node->flags; - copy->low = node->low * expansion; - copy->size = node->size * expansion; - copy->index = node->index * expansion; - if (copy->younger) copy->younger->elder = copy; - if (copy->child) { - MtrNode *auxnode = copy->child; - while (auxnode != NULL) { - auxnode->parent = copy; - auxnode = auxnode->younger; - } - } - return(copy); - -} /* end of Mtr_CopyTree */ - - -/**Function******************************************************************** - - Synopsis [Makes child the first child of parent.] - - Description [] - - SideEffects [None] - - SeeAlso [Mtr_MakeLastChild Mtr_CreateFirstChild] - -******************************************************************************/ -void -Mtr_MakeFirstChild( - MtrNode * parent, - MtrNode * child) -{ - child->parent = parent; - child->younger = parent->child; - child->elder = NULL; - if (parent->child != NULL) { -#ifdef MTR_DEBUG - assert(parent->child->elder == NULL); -#endif - parent->child->elder = child; - } - parent->child = child; - return; - -} /* end of Mtr_MakeFirstChild */ - - -/**Function******************************************************************** - - Synopsis [Makes child the last child of parent.] - - Description [] - - SideEffects [None] - - SeeAlso [Mtr_MakeFirstChild Mtr_CreateLastChild] - -******************************************************************************/ -void -Mtr_MakeLastChild( - MtrNode * parent, - MtrNode * child) -{ - MtrNode *node; - - child->younger = NULL; - - if (parent->child == NULL) { - parent->child = child; - child->elder = NULL; - } else { - for (node = parent->child; - node->younger != NULL; - node = node->younger); - node->younger = child; - child->elder = node; - } - child->parent = parent; - return; - -} /* end of Mtr_MakeLastChild */ - - -/**Function******************************************************************** - - Synopsis [Creates a new node and makes it the first child of parent.] - - Description [Creates a new node and makes it the first child of - parent. Returns pointer to new child.] - - SideEffects [None] - - SeeAlso [Mtr_MakeFirstChild Mtr_CreateLastChild] - -******************************************************************************/ -MtrNode * -Mtr_CreateFirstChild( - MtrNode * parent) -{ - MtrNode *child; - - child = Mtr_AllocNode(); - if (child == NULL) return(NULL); - - child->child = child->younger = child-> elder = NULL; - child->flags = 0; - Mtr_MakeFirstChild(parent,child); - return(child); - -} /* end of Mtr_CreateFirstChild */ - - -/**Function******************************************************************** - - Synopsis [Creates a new node and makes it the last child of parent.] - - Description [Creates a new node and makes it the last child of parent. - Returns pointer to new child.] - - SideEffects [None] - - SeeAlso [Mtr_MakeLastChild Mtr_CreateFirstChild] - -******************************************************************************/ -MtrNode * -Mtr_CreateLastChild( - MtrNode * parent) -{ - MtrNode *child; - - child = Mtr_AllocNode(); - if (child == NULL) return(NULL); - - child->child = child->younger = child->elder = NULL; - child->flags = 0; - Mtr_MakeLastChild(parent,child); - return(child); - -} /* end of Mtr_CreateLastChild */ - - -/**Function******************************************************************** - - Synopsis [Makes second the next sibling of first.] - - Description [Makes second the next sibling of first. Second becomes a - child of the parent of first.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void -Mtr_MakeNextSibling( - MtrNode * first, - MtrNode * second) -{ - second->younger = first->younger; - if (first->younger != NULL) { - first->younger->elder = second; - } - second->parent = first->parent; - first->younger = second; - second->elder = first; - return; - -} /* end of Mtr_MakeNextSibling */ - - -/**Function******************************************************************** - - Synopsis [Prints a tree, one node per line.] - - Description [] - - SideEffects [None] - - SeeAlso [Mtr_PrintGroups] - -******************************************************************************/ -void -Mtr_PrintTree( - MtrNode * node) -{ - if (node == NULL) return; - (void) fprintf(stdout, -#if SIZEOF_VOID_P == 8 - "N=0x%-8lx C=0x%-8lx Y=0x%-8lx E=0x%-8lx P=0x%-8lx F=%x L=%d S=%d\n", - (unsigned long) node, (unsigned long) node->child, - (unsigned long) node->younger, (unsigned long) node->elder, - (unsigned long) node->parent, node->flags, node->low, node->size); -#else - "N=0x%-8x C=0x%-8x Y=0x%-8x E=0x%-8x P=0x%-8x F=%x L=%d S=%d\n", - (unsigned) node, (unsigned) node->child, - (unsigned) node->younger, (unsigned) node->elder, - (unsigned) node->parent, node->flags, node->low, node->size); -#endif - if (!MTR_TEST(node,MTR_TERMINAL)) Mtr_PrintTree(node->child); - Mtr_PrintTree(node->younger); - return; - -} /* end of Mtr_PrintTree */ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/bdd/mtr/mtrGroup.c b/src/bdd/mtr/mtrGroup.c deleted file mode 100644 index 363b776b..00000000 --- a/src/bdd/mtr/mtrGroup.c +++ /dev/null @@ -1,690 +0,0 @@ -/**CFile*********************************************************************** - - FileName [mtrGroup.c] - - PackageName [mtr] - - Synopsis [Functions to support group specification for reordering.] - - Description [External procedures included in this module: -
                -
              • Mtr_InitGroupTree() -
              • Mtr_MakeGroup() -
              • Mtr_DissolveGroup() -
              • Mtr_FindGroup() -
              • Mtr_SwapGroups() -
              • Mtr_PrintGroups() -
              • Mtr_ReadGroups() -
              - Static procedures included in this module: -
                -
              • mtrShiftHL -
              - ] - - SeeAlso [cudd package] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - -******************************************************************************/ - -#include "util_hack.h" -#include "mtrInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -#ifndef lint -static char rcsid[] MTR_UNUSED = "$Id: mtrGroup.c,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $"; -#endif - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int mtrShiftHL ARGS((MtrNode *node, int shift)); - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Allocate new tree.] - - Description [Allocate new tree with one node, whose low and size - fields are specified by the lower and size parameters. - Returns pointer to tree root.] - - SideEffects [None] - - SeeAlso [Mtr_InitTree Mtr_FreeTree] - -******************************************************************************/ -MtrNode * -Mtr_InitGroupTree( - int lower, - int size) -{ - MtrNode *root; - - root = Mtr_InitTree(); - if (root == NULL) return(NULL); - root->flags = MTR_DEFAULT; - root->low = lower; - root->size = size; - return(root); - -} /* end of Mtr_InitGroupTree */ - - -/**Function******************************************************************** - - Synopsis [Makes a new group with size leaves starting at low.] - - Description [Makes a new group with size leaves starting at low. - If the new group intersects an existing group, it must - either contain it or be contained by it. This procedure relies on - the low and size fields of each node. It also assumes that the - children of each node are sorted in order of increasing low. In - case of a valid request, the flags of the new group are set to the - value passed in `flags.' This can also be used to change the flags - of an existing group. Returns the pointer to the root of the new - group upon successful termination; NULL otherwise. If the group - already exists, the pointer to its root is returned.] - - SideEffects [None] - - SeeAlso [Mtr_DissolveGroup Mtr_ReadGroups Mtr_FindGroup] - -******************************************************************************/ -MtrNode * -Mtr_MakeGroup( - MtrNode * root /* root of the group tree */, - unsigned int low /* lower bound of the group */, - unsigned int size /* upper bound of the group */, - unsigned int flags /* flags for the new group */) -{ - MtrNode *node, - *first, - *last, - *previous, - *newn; - - /* Sanity check. */ - if (size == 0) - return(NULL); - - /* Check whether current group includes new group. This check is - ** necessary at the top-level call. In the subsequent calls it is - ** redundant. */ - if (low < (unsigned int) root->low || - low + size > (unsigned int) (root->low + root->size)) - return(NULL); - - /* Trying to create an existing group has the effect of updating - ** the flags. */ - if (root->size == size && root->low == low) { - root->flags = flags; - return(root); - } - - /* At this point we know that the new group is properly contained - ** in the group of root. We have two possible cases here: - root - ** is a terminal node; - root has children. */ - - /* Root has no children: create a new group. */ - if (root->child == NULL) { - newn = Mtr_AllocNode(); - if (newn == NULL) return(NULL); /* out of memory */ - newn->low = low; - newn->size = size; - newn->flags = flags; - newn->parent = root; - newn->elder = newn->younger = newn->child = NULL; - root->child = newn; - return(newn); - } - - /* Root has children: Find all chidren of root that are included - ** in the new group. If the group of any child entirely contains - ** the new group, call Mtr_MakeGroup recursively. */ - previous = NULL; - first = root->child; /* guaranteed to be non-NULL */ - while (first != NULL && low >= (unsigned int) (first->low + first->size)) { - previous = first; - first = first->younger; - } - if (first == NULL) { - /* We have scanned the entire list and we need to append a new - ** child at the end of it. Previous points to the last child - ** of root. */ - newn = Mtr_AllocNode(); - if (newn == NULL) return(NULL); /* out of memory */ - newn->low = low; - newn->size = size; - newn->flags = flags; - newn->parent = root; - newn->elder = previous; - previous->younger = newn; - newn->younger = newn->child = NULL; - return(newn); - } - /* Here first is non-NULL and low < first->low + first->size. */ - if (low >= (unsigned int) first->low && - low + size <= (unsigned int) (first->low + first->size)) { - /* The new group is contained in the group of first. */ - newn = Mtr_MakeGroup(first, low, size, flags); - return(newn); - } else if (low + size <= first->low) { - /* The new group is entirely contained in the gap between - ** previous and first. */ - newn = Mtr_AllocNode(); - if (newn == NULL) return(NULL); /* out of memory */ - newn->low = low; - newn->size = size; - newn->flags = flags; - newn->child = NULL; - newn->parent = root; - newn->elder = previous; - newn->younger = first; - first->elder = newn; - if (previous != NULL) { - previous->younger = newn; - } else { - root->child = newn; - } - return(newn); - } else if (low < (unsigned int) first->low && - low + size < (unsigned int) (first->low + first->size)) { - /* Trying to cut an existing group: not allowed. */ - return(NULL); - } else if (low > first->low) { - /* The new group neither is contained in the group of first - ** (this was tested above) nor contains it. It is therefore - ** trying to cut an existing group: not allowed. */ - return(NULL); - } - - /* First holds the pointer to the first child contained in the new - ** group. Here low <= first->low and low + size >= first->low + - ** first->size. One of the two inequalities is strict. */ - last = first->younger; - while (last != NULL && - (unsigned int) (last->low + last->size) < low + size) { - last = last->younger; - } - if (last == NULL) { - /* All the chilren of root from first onward become children - ** of the new group. */ - newn = Mtr_AllocNode(); - if (newn == NULL) return(NULL); /* out of memory */ - newn->low = low; - newn->size = size; - newn->flags = flags; - newn->child = first; - newn->parent = root; - newn->elder = previous; - newn->younger = NULL; - first->elder = NULL; - if (previous != NULL) { - previous->younger = newn; - } else { - root->child = newn; - } - last = first; - while (last != NULL) { - last->parent = newn; - last = last->younger; - } - return(newn); - } - - /* Here last != NULL and low + size <= last->low + last->size. */ - if (low + size - 1 >= (unsigned int) last->low && - low + size < (unsigned int) (last->low + last->size)) { - /* Trying to cut an existing group: not allowed. */ - return(NULL); - } - - /* First and last point to the first and last of the children of - ** root that are included in the new group. Allocate a new node - ** and make all children of root between first and last chidren of - ** the new node. Previous points to the child of root immediately - ** preceeding first. If it is NULL, then first is the first child - ** of root. */ - newn = Mtr_AllocNode(); - if (newn == NULL) return(NULL); /* out of memory */ - newn->low = low; - newn->size = size; - newn->flags = flags; - newn->child = first; - newn->parent = root; - if (previous == NULL) { - root->child = newn; - } else { - previous->younger = newn; - } - newn->elder = previous; - newn->younger = last->younger; - if (last->younger != NULL) { - last->younger->elder = newn; - } - last->younger = NULL; - first->elder = NULL; - for (node = first; node != NULL; node = node->younger) { - node->parent = newn; - } - - return(newn); - -} /* end of Mtr_MakeGroup */ - - -/**Function******************************************************************** - - Synopsis [Merges the children of `group' with the children of its - parent.] - - Description [Merges the children of `group' with the children of its - parent. Disposes of the node pointed by group. If group is the - root of the group tree, this procedure leaves the tree unchanged. - Returns the pointer to the parent of `group' upon successful - termination; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Mtr_MakeGroup] - -******************************************************************************/ -MtrNode * -Mtr_DissolveGroup( - MtrNode * group /* group to be dissolved */) -{ - MtrNode *parent; - MtrNode *last; - - parent = group->parent; - - if (parent == NULL) return(NULL); - if (MTR_TEST(group,MTR_TERMINAL) || group->child == NULL) return(NULL); - - /* Make all children of group children of its parent, and make - ** last point to the last child of group. */ - for (last = group->child; last->younger != NULL; last = last->younger) { - last->parent = parent; - } - last->parent = parent; - - last->younger = group->younger; - if (group->younger != NULL) { - group->younger->elder = last; - } - - group->child->elder = group->elder; - if (group == parent->child) { - parent->child = group->child; - } else { - group->elder->younger = group->child; - } - - Mtr_DeallocNode(group); - return(parent); - -} /* end of Mtr_DissolveGroup */ - - -/**Function******************************************************************** - - Synopsis [Finds a group with size leaves starting at low, if it exists.] - - Description [Finds a group with size leaves starting at low, if it - exists. This procedure relies on the low and size fields of each - node. It also assumes that the children of each node are sorted in - order of increasing low. Returns the pointer to the root of the - group upon successful termination; NULL otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -MtrNode * -Mtr_FindGroup( - MtrNode * root /* root of the group tree */, - unsigned int low /* lower bound of the group */, - unsigned int size /* upper bound of the group */) -{ - MtrNode *node; - -#ifdef MTR_DEBUG - /* We cannot have a non-empty proper subgroup of a singleton set. */ - assert(!MTR_TEST(root,MTR_TERMINAL)); -#endif - - /* Sanity check. */ - if (size < 1) return(NULL); - - /* Check whether current group includes the group sought. This - ** check is necessary at the top-level call. In the subsequent - ** calls it is redundant. */ - if (low < (unsigned int) root->low || - low + size > (unsigned int) (root->low + root->size)) - return(NULL); - - if (root->size == size && root->low == low) - return(root); - - if (root->child == NULL) - return(NULL); - - /* Find all chidren of root that are included in the new group. If - ** the group of any child entirely contains the new group, call - ** Mtr_MakeGroup recursively. */ - node = root->child; - while (low >= (unsigned int) (node->low + node->size)) { - node = node->younger; - } - if (low + size <= (unsigned int) (node->low + node->size)) { - /* The group is contained in the group of node. */ - node = Mtr_FindGroup(node, low, size); - return(node); - } else { - return(NULL); - } - -} /* end of Mtr_FindGroup */ - - -/**Function******************************************************************** - - Synopsis [Swaps two children of a tree node.] - - Description [Swaps two children of a tree node. Adjusts the high and - low fields of the two nodes and their descendants. The two children - must be adjacent. However, first may be the younger sibling of second. - Returns 1 in case of success; 0 otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -int -Mtr_SwapGroups( - MtrNode * first /* first node to be swapped */, - MtrNode * second /* second node to be swapped */) -{ - MtrNode *node; - MtrNode *parent; - int sizeFirst; - int sizeSecond; - - if (second->younger == first) { /* make first first */ - node = first; - first = second; - second = node; - } else if (first->younger != second) { /* non-adjacent */ - return(0); - } - - sizeFirst = first->size; - sizeSecond = second->size; - - /* Swap the two nodes. */ - parent = first->parent; - if (parent == NULL || second->parent != parent) return(0); - if (parent->child == first) { - parent->child = second; - } else { /* first->elder != NULL */ - first->elder->younger = second; - } - if (second->younger != NULL) { - second->younger->elder = first; - } - first->younger = second->younger; - second->elder = first->elder; - first->elder = second; - second->younger = first; - - /* Adjust the high and low fields. */ - if (!mtrShiftHL(first,sizeSecond)) return(0); - if (!mtrShiftHL(second,-sizeFirst)) return(0); - - return(1); - -} /* end of Mtr_SwapGroups */ - - -/**Function******************************************************************** - - Synopsis [Prints the groups as a parenthesized list.] - - Description [Prints the groups as a parenthesized list. After each - group, the group's flag are printed, preceded by a `|'. For each - flag (except MTR_TERMINAL) a character is printed. -
                -
              • F: MTR_FIXED -
              • N: MTR_NEWNODE -
              • S: MTR_SOFT -
              - The second argument, silent, if different from 0, causes - Mtr_PrintGroups to only check the syntax of the group tree. - ] - - SideEffects [None] - - SeeAlso [Mtr_PrintTree] - -******************************************************************************/ -void -Mtr_PrintGroups( - MtrNode * root /* root of the group tree */, - int silent /* flag to check tree syntax only */) -{ - MtrNode *node; - - assert(root != NULL); - assert(root->younger == NULL || root->younger->elder == root); - assert(root->elder == NULL || root->elder->younger == root); - if (!silent) (void) printf("(%d",root->low); - if (MTR_TEST(root,MTR_TERMINAL) || root->child == NULL) { - if (!silent) (void) printf(","); - } else { - node = root->child; - while (node != NULL) { - assert(node->low >= root->low && (int) (node->low + node->size) <= (int) (root->low + root->size)); - assert(node->parent == root); - Mtr_PrintGroups(node,silent); - node = node->younger; - } - } - if (!silent) { - (void) printf("%d", root->low + root->size - 1); - if (root->flags != MTR_DEFAULT) { - (void) printf("|"); - if (MTR_TEST(root,MTR_FIXED)) (void) printf("F"); - if (MTR_TEST(root,MTR_NEWNODE)) (void) printf("N"); - if (MTR_TEST(root,MTR_SOFT)) (void) printf("S"); - } - (void) printf(")"); - if (root->parent == NULL) (void) printf("\n"); - } - assert((root->flags &~(MTR_TERMINAL | MTR_SOFT | MTR_FIXED | MTR_NEWNODE)) == 0); - return; - -} /* end of Mtr_PrintGroups */ - - -/**Function******************************************************************** - - Synopsis [Reads groups from a file and creates a group tree.] - - Description [Reads groups from a file and creates a group tree. - Each group is specified by three fields: - - low size flags. - - Low and size are (short) integers. Flags is a string composed of the - following characters (with associated translation): -
                -
              • D: MTR_DEFAULT -
              • F: MTR_FIXED -
              • N: MTR_NEWNODE -
              • S: MTR_SOFT -
              • T: MTR_TERMINAL -
              - Normally, the only flags that are needed are D and F. Groups and - fields are separated by white space (spaces, tabs, and newlines). - Returns a pointer to the group tree if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Mtr_InitGroupTree Mtr_MakeGroup] - -******************************************************************************/ -MtrNode * -Mtr_ReadGroups( - FILE * fp /* file pointer */, - int nleaves /* number of leaves of the new tree */) -{ - int low; - int size; - int err; - unsigned int flags; - MtrNode *root; - MtrNode *node; - char attrib[8*sizeof(unsigned int)+1]; - char *c; - - root = Mtr_InitGroupTree(0,nleaves); - if (root == NULL) return NULL; - - while (! feof(fp)) { - /* Read a triple and check for consistency. */ - err = fscanf(fp, "%d %d %s", &low, &size, attrib); - if (err == EOF) { - break; - } else if (err != 3) { - return(NULL); - } else if (low < 0 || low+size > nleaves || size < 1) { - return(NULL); - } else if (strlen(attrib) > 8 * sizeof(MtrHalfWord)) { - /* Not enough bits in the flags word to store these many - ** attributes. */ - return(NULL); - } - - /* Parse the flag string. Currently all flags are permitted, - ** to make debugging easier. Normally, specifying NEWNODE - ** wouldn't be allowed. */ - flags = MTR_DEFAULT; - for (c=attrib; *c != 0; c++) { - switch (*c) { - case 'D': - break; - case 'F': - flags |= MTR_FIXED; - break; - case 'N': - flags |= MTR_NEWNODE; - break; - case 'S': - flags |= MTR_SOFT; - break; - case 'T': - flags |= MTR_TERMINAL; - break; - default: - return NULL; - } - } - node = Mtr_MakeGroup(root, (MtrHalfWord) low, (MtrHalfWord) size, - flags); - if (node == NULL) return(NULL); - } - - return(root); - -} /* end of Mtr_ReadGroups */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Adjusts the low fields of a node and its descendants.] - - Description [Adjusts the low fields of a node and its - descendants. Adds shift to low of each node. Checks that no - out-of-bounds values result. Returns 1 in case of success; 0 - otherwise.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -static int -mtrShiftHL( - MtrNode * node /* group tree node */, - int shift /* amount by which low should be changed */) -{ - MtrNode *auxnode; - int low; - - low = (int) node->low; - - - low += shift; - - if (low < 0 || low + (int) (node->size - 1) > (int) MTR_MAXHIGH) return(0); - - node->low = (MtrHalfWord) low; - - if (!MTR_TEST(node,MTR_TERMINAL) && node->child != NULL) { - auxnode = node->child; - do { - if (!mtrShiftHL(auxnode,shift)) return(0); - auxnode = auxnode->younger; - } while (auxnode != NULL); - } - - return(1); - -} /* end of mtrShiftHL */ - diff --git a/src/bdd/mtr/mtrInt.h b/src/bdd/mtr/mtrInt.h deleted file mode 100644 index a8d5aa6c..00000000 --- a/src/bdd/mtr/mtrInt.h +++ /dev/null @@ -1,65 +0,0 @@ -/**CHeaderFile***************************************************************** - - FileName [mtrInt.h] - - PackageName [mtr] - - Synopsis [Internal data structures of the mtr package] - - Description [In this package all definitions are external.] - - SeeAlso [] - - Author [Fabio Somenzi] - - Copyright [This file was created at the University of Colorado at - Boulder. The University of Colorado at Boulder makes no warranty - about the suitability of this software for any purpose. It is - presented on an AS IS basis.] - - Revision [$Id: mtrInt.h,v 1.1.1.1 2003/02/24 22:24:02 wjiang Exp $] - -******************************************************************************/ - -#ifndef _MTRINT -#define _MTRINT - -#include "mtr.h" - -/*---------------------------------------------------------------------------*/ -/* Nested includes */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Function prototypes */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticEnd***************************************************************/ - -#endif /* _MTRINT */ diff --git a/src/bdd/parse/module.make b/src/bdd/parse/module.make deleted file mode 100644 index 4f590f01..00000000 --- a/src/bdd/parse/module.make +++ /dev/null @@ -1,3 +0,0 @@ -SRC += src/bdd/parse/parseCore.c \ - src/bdd/parse/parseEqn.c \ - src/bdd/parse/parseStack.c diff --git a/src/bdd/parse/parse.h b/src/bdd/parse/parse.h deleted file mode 100644 index 4923fbdd..00000000 --- a/src/bdd/parse/parse.h +++ /dev/null @@ -1,54 +0,0 @@ -/**CFile**************************************************************** - - FileName [parse.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Parsing symbolic Boolean formulas into BDDs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: parse.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __PARSE_H__ -#define __PARSE_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== parseCore.c =============================================================*/ -extern DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormula, int nVars, int nRanks, - char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/parse/parseCore.c b/src/bdd/parse/parseCore.c deleted file mode 100644 index 21a37070..00000000 --- a/src/bdd/parse/parseCore.c +++ /dev/null @@ -1,504 +0,0 @@ -/**CFile**************************************************************** - - FileNameIn [parseCore.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Boolean formula parser.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: parseCore.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -/* - Some aspects of Boolean Formula Parser: - - 1) The names in the boolean formulas can be any strings of symbols - that start with char or underscore and contain chars, digits - and underscores: For example: 1) a&b <+> c'&d => a + b; - 2) a1 b2 c3' dummy' + (a2+b2')c3 dummy - 2) Constant values 0 and 1 can be used just like normal variables - 3) Any boolean operator (listed below) and parantheses can be used - any number of times provided there are equal number of opening - and closing parantheses. - 4) By default, absence of an operator between vars and before and - after parantheses is taken for AND. - 5) Both complementation prefix and complementation suffix can be - used at the same time (but who needs this?) - 6) Spaces (tabs, end-of-lines) may be inserted anywhere, - except between characters of the operations: <=>, =>, <=, <+> - 7) The stack size is defined by macro STACKSIZE and is used by the - stack constructor. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#include "parseInt.h" - -// the list of operation symbols to be used in expressions -#define PARSE_SYM_OPEN '(' // opening paranthesis -#define PARSE_SYM_CLOSE ')' // closing paranthesis -#define PARSE_SYM_LOWER '[' // shifts one rank down -#define PARSE_SYM_RAISE ']' // shifts one rank up -#define PARSE_SYM_CONST0 '0' // constant 0 -#define PARSE_SYM_CONST1 '1' // constant 1 -#define PARSE_SYM_NEGBEF1 '!' // negation before the variable -#define PARSE_SYM_NEGBEF2 '~' // negation before the variable -#define PARSE_SYM_NEGAFT '\'' // negation after the variable -#define PARSE_SYM_AND1 '&' // logic AND -#define PARSE_SYM_AND2 '*' // logic AND -#define PARSE_SYM_XOR1 '<' // logic EXOR (the 1st symbol) -#define PARSE_SYM_XOR2 '+' // logic EXOR (the 2nd symbol) -#define PARSE_SYM_XOR3 '>' // logic EXOR (the 3rd symbol) -#define PARSE_SYM_OR '+' // logic OR -#define PARSE_SYM_EQU1 '<' // equvalence (the 1st symbol) -#define PARSE_SYM_EQU2 '=' // equvalence (the 2nd symbol) -#define PARSE_SYM_EQU3 '>' // equvalence (the 3rd symbol) -#define PARSE_SYM_FLR1 '=' // implication (the 1st symbol) -#define PARSE_SYM_FLR2 '>' // implication (the 2nd symbol) -#define PARSE_SYM_FLL1 '<' // backward imp (the 1st symbol) -#define PARSE_SYM_FLL2 '=' // backward imp (the 2nd symbol) -// PARSE_SYM_FLR1 and PARSE_SYM_FLR2 should be the same as PARSE_SYM_EQU2 and PARSE_SYM_EQU3! - -// the list of opcodes (also specifying operation precedence) -#define PARSE_OPER_NEG 10 // negation -#define PARSE_OPER_AND 9 // logic AND -#define PARSE_OPER_XOR 8 // logic EXOR (a'b | ab') -#define PARSE_OPER_OR 7 // logic OR -#define PARSE_OPER_EQU 6 // equvalence (a'b'| ab ) -#define PARSE_OPER_FLR 5 // implication ( a' | b ) -#define PARSE_OPER_FLL 4 // backward imp ( 'b | a ) -#define PARSE_OPER_MARK 1 // OpStack token standing for an opening paranthesis - -// these are values of the internal Flag -#define PARSE_FLAG_START 1 // after the opening parenthesis -#define PARSE_FLAG_VAR 2 // after operation is received -#define PARSE_FLAG_OPER 3 // after operation symbol is received -#define PARSE_FLAG_ERROR 4 // when error is detected - -#define STACKSIZE 1000 - -static DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the BDD corresponding to the formula in language L.] - - Description [Takes the stream to output messages, the formula, the number - variables and the rank in the formula. The array of variable names is also - given. The BDD manager and the elementary 0-rank variable are the last two - arguments. The manager should have at least as many variables as - nVars * (nRanks + 1). The 0-rank variables should have numbers larger - than the variables of other ranks.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Parse_FormulaParser( FILE * pOutput, char * pFormulaInit, int nVars, int nRanks, - char * ppVarNames[], DdManager * dd, DdNode * pbVars[] ) -{ - char * pFormula; - Parse_StackFn_t * pStackFn; - Parse_StackOp_t * pStackOp; - DdNode * bFunc, * bTemp; - char * pTemp; - int nParans, fFound, Flag; - int Oper, Oper1, Oper2; - int i, v, fLower; - - // make sure that the number of vars and ranks is correct - if ( nVars * (nRanks + 1) > dd->size ) - { - printf( "Parse_FormulaParser(): The BDD manager does not have enough variables.\n" ); - return NULL; - } - - // make sure that the number of opening and closing parantheses is the same - nParans = 0; - for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) - if ( *pTemp == '(' ) - nParans++; - else if ( *pTemp == ')' ) - nParans--; - if ( nParans != 0 ) - { - fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing parantheses ().\n" ); - return NULL; - } - - nParans = 0; - for ( pTemp = pFormulaInit; *pTemp; pTemp++ ) - if ( *pTemp == '[' ) - nParans++; - else if ( *pTemp == ']' ) - nParans--; - if ( nParans != 0 ) - { - fprintf( pOutput, "Parse_FormulaParser(): Different number of opening and closing brackets [].\n" ); - return NULL; - } - - // copy the formula - pFormula = ALLOC( char, strlen(pFormulaInit) + 3 ); - sprintf( pFormula, "(%s)", pFormulaInit ); - - // start the stacks - pStackFn = Parse_StackFnStart( STACKSIZE ); - pStackOp = Parse_StackOpStart( STACKSIZE ); - - Flag = PARSE_FLAG_START; - fLower = 0; - for ( pTemp = pFormula; *pTemp; pTemp++ ) - { - switch ( *pTemp ) - { - // skip all spaces, tabs, and end-of-lines - case ' ': - case '\t': - case '\r': - case '\n': - continue; - - // treat Constant 0 as a variable - case PARSE_SYM_CONST0: - Parse_StackFnPush( pStackFn, b0 ); Cudd_Ref( b0 ); - if ( Flag == PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 0.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_VAR; - break; - - // the same for Constant 1 - case PARSE_SYM_CONST1: - Parse_StackFnPush( pStackFn, b1 ); Cudd_Ref( b1 ); - if ( Flag == PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): No operation symbol before constant 1.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_VAR; - break; - - case PARSE_SYM_NEGBEF1: - case PARSE_SYM_NEGBEF2: - if ( Flag == PARSE_FLAG_VAR ) - {// if NEGBEF follows a variable, AND is assumed - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - Flag = PARSE_FLAG_OPER; - } - Parse_StackOpPush( pStackOp, PARSE_OPER_NEG ); - break; - - case PARSE_SYM_NEGAFT: - if ( Flag != PARSE_FLAG_VAR ) - {// if there is no variable before NEGAFT, it is an error - fprintf( pOutput, "Parse_FormulaParser(): No variable is specified before the negation suffix.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - else // if ( Flag == PARSE_FLAG_VAR ) - Parse_StackFnPush( pStackFn, Cudd_Not( Parse_StackFnPop(pStackFn) ) ); - break; - - case PARSE_SYM_AND1: - case PARSE_SYM_AND2: - case PARSE_SYM_OR: - if ( Flag != PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no variable before AND, EXOR, or OR.\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - if ( *pTemp == PARSE_SYM_AND1 || *pTemp == PARSE_SYM_AND2 ) - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - else //if ( Str[Pos] == PARSE_SYM_OR ) - Parse_StackOpPush( pStackOp, PARSE_OPER_OR ); - Flag = PARSE_FLAG_OPER; - break; - - case PARSE_SYM_EQU1: - if ( Flag != PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Equivalence or Implication\n" ); - Flag = PARSE_FLAG_ERROR; break; - } - if ( pTemp[1] == PARSE_SYM_EQU2 ) - { // check what is the next symbol in the string - pTemp++; - if ( pTemp[1] == PARSE_SYM_EQU3 ) - { - pTemp++; - Parse_StackOpPush( pStackOp, PARSE_OPER_EQU ); - } - else - { - Parse_StackOpPush( pStackOp, PARSE_OPER_FLL ); - } - } - else if ( pTemp[1] == PARSE_SYM_XOR2 ) - { - pTemp++; - if ( pTemp[1] == PARSE_SYM_XOR3 ) - { - pTemp++; - Parse_StackOpPush( pStackOp, PARSE_OPER_XOR ); - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c%c\"\n", PARSE_SYM_EQU1, PARSE_SYM_XOR2 ); - Flag = PARSE_FLAG_ERROR; - break; - } - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU1 ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_OPER; - break; - - case PARSE_SYM_EQU2: - if ( Flag != PARSE_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no variable before Reverse Implication\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - if ( pTemp[1] == PARSE_SYM_EQU3 ) - { - pTemp++; - Parse_StackOpPush( pStackOp, PARSE_OPER_FLR ); - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): Wrong symbol after \"%c\"\n", PARSE_SYM_EQU2 ); - Flag = PARSE_FLAG_ERROR; - break; - } - Flag = PARSE_FLAG_OPER; - break; - - case PARSE_SYM_LOWER: - case PARSE_SYM_OPEN: - if ( Flag == PARSE_FLAG_VAR ) - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - Parse_StackOpPush( pStackOp, PARSE_OPER_MARK ); - // after an opening bracket, it feels like starting over again - Flag = PARSE_FLAG_START; - break; - - case PARSE_SYM_RAISE: - fLower = 1; - case PARSE_SYM_CLOSE: - if ( !Parse_StackOpIsEmpty( pStackOp ) ) - { - while ( 1 ) - { - if ( Parse_StackOpIsEmpty( pStackOp ) ) - { - fprintf( pOutput, "Parse_FormulaParser(): There is no opening paranthesis\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper == PARSE_OPER_MARK ) - break; - - // perform the given operation - if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper ) == NULL ) - { - fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); - free( pFormula ); - return NULL; - } - } - - if ( fLower ) - { - bFunc = Parse_StackFnPop( pStackFn ); - bFunc = Extra_bddMove( dd, bTemp = bFunc, -nVars ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - Parse_StackFnPush( pStackFn, bFunc ); - } - } - else - { - fprintf( pOutput, "Parse_FormulaParser(): There is no opening paranthesis\n" ); - Flag = PARSE_FLAG_ERROR; - break; - } - if ( Flag != PARSE_FLAG_ERROR ) - Flag = PARSE_FLAG_VAR; - fLower = 0; - break; - - - default: - // scan the next name - fFound = 0; - for ( i = 0; pTemp[i] && pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n'; i++ ) - { - for ( v = 0; v < nVars; v++ ) - if ( strncmp( pTemp, ppVarNames[v], i+1 ) == 0 && strlen(ppVarNames[v]) == (unsigned)(i+1) ) - { - pTemp += i; - fFound = 1; - break; - } - if ( fFound ) - break; - } - if ( !fFound ) - { - fprintf( pOutput, "Parse_FormulaParser(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); - Flag = PARSE_FLAG_ERROR; - break; - } - - // assume operation AND, if vars follow one another - if ( Flag == PARSE_FLAG_VAR ) - Parse_StackOpPush( pStackOp, PARSE_OPER_AND ); - Parse_StackFnPush( pStackFn, pbVars[v] ); Cudd_Ref( pbVars[v] ); - Flag = PARSE_FLAG_VAR; - break; - } - - if ( Flag == PARSE_FLAG_ERROR ) - break; // error exit - else if ( Flag == PARSE_FLAG_START ) - continue; // go on parsing - else if ( Flag == PARSE_FLAG_VAR ) - while ( 1 ) - { // check if there are negations in the OpStack - if ( Parse_StackOpIsEmpty(pStackOp) ) - break; - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper != PARSE_OPER_NEG ) - { - Parse_StackOpPush( pStackOp, Oper ); - break; - } - else - { - Parse_StackFnPush( pStackFn, Cudd_Not(Parse_StackFnPop(pStackFn)) ); - } - } - else // if ( Flag == PARSE_FLAG_OPER ) - while ( 1 ) - { // execute all the operations in the OpStack - // with precedence higher or equal than the last one - Oper1 = Parse_StackOpPop( pStackOp ); // the last operation - if ( Parse_StackOpIsEmpty(pStackOp) ) - { // if it is the only operation, push it back - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one - if ( Oper2 >= Oper1 ) - { // if Oper2 precedence is higher or equal, execute it -// Parse_StackPush( pStackFn, Operation( FunStack.Pop(), FunStack.Pop(), Oper2 ) ); - if ( Parse_ParserPerformTopOp( dd, pStackFn, Oper2 ) == NULL ) - { - fprintf( pOutput, "Parse_FormulaParser(): Unknown operation\n" ); - free( pFormula ); - return NULL; - } - Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back - } - else - { // if Oper2 precedence is lower, push them back and done - Parse_StackOpPush( pStackOp, Oper2 ); - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - } - } - - if ( Flag != PARSE_FLAG_ERROR ) - { - if ( !Parse_StackFnIsEmpty(pStackFn) ) - { - bFunc = Parse_StackFnPop(pStackFn); - if ( Parse_StackFnIsEmpty(pStackFn) ) - if ( Parse_StackOpIsEmpty(pStackOp) ) - { - Parse_StackFnFree(pStackFn); - Parse_StackOpFree(pStackOp); - Cudd_Deref( bFunc ); - free( pFormula ); - return bFunc; - } - else - fprintf( pOutput, "Parse_FormulaParser(): Something is left in the operation stack\n" ); - else - fprintf( pOutput, "Parse_FormulaParser(): Something is left in the function stack\n" ); - } - else - fprintf( pOutput, "Parse_FormulaParser(): The input string is empty\n" ); - } - free( pFormula ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs the operation on the top entries in the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Parse_ParserPerformTopOp( DdManager * dd, Parse_StackFn_t * pStackFn, int Oper ) -{ - DdNode * bArg1, * bArg2, * bFunc; - // perform the given operation - bArg2 = Parse_StackFnPop( pStackFn ); - bArg1 = Parse_StackFnPop( pStackFn ); - if ( Oper == PARSE_OPER_AND ) - bFunc = Cudd_bddAnd( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_XOR ) - bFunc = Cudd_bddXor( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_OR ) - bFunc = Cudd_bddOr( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_EQU ) - bFunc = Cudd_bddXnor( dd, bArg1, bArg2 ); - else if ( Oper == PARSE_OPER_FLR ) - bFunc = Cudd_bddOr( dd, Cudd_Not(bArg1), bArg2 ); - else if ( Oper == PARSE_OPER_FLL ) - bFunc = Cudd_bddOr( dd, Cudd_Not(bArg2), bArg1 ); - else - return NULL; - Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bArg1 ); - Cudd_RecursiveDeref( dd, bArg2 ); - Parse_StackFnPush( pStackFn, bFunc ); - return bFunc; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/parse/parseEqn.c b/src/bdd/parse/parseEqn.c deleted file mode 100644 index 02d83966..00000000 --- a/src/bdd/parse/parseEqn.c +++ /dev/null @@ -1,349 +0,0 @@ -/**CFile**************************************************************** - - FileNameIn [parseEqn.c] - - PackageName [ABC: Logic synthesis and verification system.] - - Synopsis [Boolean formula parser.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - December 18, 2006.] - - Revision [$Id: parseEqn.c,v 1.0 2006/12/18 00:00:00 alanmi Exp $] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#include "parseInt.h" -#include "vec.h" -#include "hop.h" - -// the list of operation symbols to be used in expressions -#define PARSE_EQN_SYM_OPEN '(' // opening paranthesis -#define PARSE_EQN_SYM_CLOSE ')' // closing paranthesis -#define PARSE_EQN_SYM_CONST0 '0' // constant 0 -#define PARSE_EQN_SYM_CONST1 '1' // constant 1 -#define PARSE_EQN_SYM_NEG '!' // negation before the variable -#define PARSE_EQN_SYM_AND '*' // logic AND -#define PARSE_EQN_SYM_OR '+' // logic OR - -// the list of opcodes (also specifying operation precedence) -#define PARSE_EQN_OPER_NEG 10 // negation -#define PARSE_EQN_OPER_AND 9 // logic AND -#define PARSE_EQN_OPER_OR 7 // logic OR -#define PARSE_EQN_OPER_MARK 1 // OpStack token standing for an opening paranthesis - -// these are values of the internal Flag -#define PARSE_EQN_FLAG_START 1 // after the opening parenthesis -#define PARSE_EQN_FLAG_VAR 2 // after operation is received -#define PARSE_EQN_FLAG_OPER 3 // after operation symbol is received -#define PARSE_EQN_FLAG_ERROR 4 // when error is detected - -#define PARSE_EQN_STACKSIZE 1000 - -static Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives the AIG corresponding to the equation.] - - Description [Takes the stream to output messages, the formula, the vector - of variable names and the AIG manager.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Parse_FormulaParserEqn( FILE * pOutput, char * pFormInit, Vec_Ptr_t * vVarNames, Hop_Man_t * pMan ) -{ - char * pFormula; - Parse_StackFn_t * pStackFn; - Parse_StackOp_t * pStackOp; - Hop_Obj_t * gFunc; - char * pTemp, * pName; - int nParans, fFound, Flag; - int Oper, Oper1, Oper2; - int i, v; - - // make sure that the number of opening and closing parantheses is the same - nParans = 0; - for ( pTemp = pFormInit; *pTemp; pTemp++ ) - if ( *pTemp == '(' ) - nParans++; - else if ( *pTemp == ')' ) - nParans--; - if ( nParans != 0 ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): Different number of opening and closing parantheses ().\n" ); - return NULL; - } - - // copy the formula - pFormula = ALLOC( char, strlen(pFormInit) + 3 ); - sprintf( pFormula, "(%s)", pFormInit ); - - // start the stacks - pStackFn = Parse_StackFnStart( PARSE_EQN_STACKSIZE ); - pStackOp = Parse_StackOpStart( PARSE_EQN_STACKSIZE ); - - Flag = PARSE_EQN_FLAG_START; - for ( pTemp = pFormula; *pTemp; pTemp++ ) - { - switch ( *pTemp ) - { - // skip all spaces, tabs, and end-of-lines - case ' ': - case '\t': - case '\r': - case '\n': - continue; - case PARSE_EQN_SYM_CONST0: - Parse_StackFnPush( pStackFn, Hop_ManConst0(pMan) ); // Cudd_Ref( b0 ); - if ( Flag == PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 0.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Flag = PARSE_EQN_FLAG_VAR; - break; - case PARSE_EQN_SYM_CONST1: - Parse_StackFnPush( pStackFn, Hop_ManConst1(pMan) ); // Cudd_Ref( b1 ); - if ( Flag == PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): No operation symbol before constant 1.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Flag = PARSE_EQN_FLAG_VAR; - break; - case PARSE_EQN_SYM_NEG: - if ( Flag == PARSE_EQN_FLAG_VAR ) - {// if NEGBEF follows a variable, AND is assumed - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); - Flag = PARSE_EQN_FLAG_OPER; - } - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_NEG ); - break; - case PARSE_EQN_SYM_AND: - case PARSE_EQN_SYM_OR: - if ( Flag != PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): There is no variable before AND, EXOR, or OR.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - if ( *pTemp == PARSE_EQN_SYM_AND ) - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); - else //if ( *pTemp == PARSE_EQN_SYM_OR ) - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_OR ); - Flag = PARSE_EQN_FLAG_OPER; - break; - case PARSE_EQN_SYM_OPEN: - if ( Flag == PARSE_EQN_FLAG_VAR ) - { -// Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_AND ); - fprintf( pOutput, "Parse_FormulaParserEqn(): An opening paranthesis follows a var without operation sign.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Parse_StackOpPush( pStackOp, PARSE_EQN_OPER_MARK ); - // after an opening bracket, it feels like starting over again - Flag = PARSE_EQN_FLAG_START; - break; - case PARSE_EQN_SYM_CLOSE: - if ( !Parse_StackOpIsEmpty( pStackOp ) ) - { - while ( 1 ) - { - if ( Parse_StackOpIsEmpty( pStackOp ) ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening paranthesis\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper == PARSE_EQN_OPER_MARK ) - break; - - // perform the given operation - if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper ) == NULL ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); - free( pFormula ); - return NULL; - } - } - } - else - { - fprintf( pOutput, "Parse_FormulaParserEqn(): There is no opening paranthesis\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - if ( Flag != PARSE_EQN_FLAG_ERROR ) - Flag = PARSE_EQN_FLAG_VAR; - break; - - - default: - // scan the next name - for ( i = 0; pTemp[i] && - pTemp[i] != ' ' && pTemp[i] != '\t' && pTemp[i] != '\r' && pTemp[i] != '\n' && - pTemp[i] != PARSE_EQN_SYM_AND && pTemp[i] != PARSE_EQN_SYM_OR && pTemp[i] != PARSE_EQN_SYM_CLOSE; i++ ) - { - if ( pTemp[i] == PARSE_EQN_SYM_NEG || pTemp[i] == PARSE_EQN_SYM_OPEN ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): The negation sign or an opening paranthesis inside the variable name.\n" ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - } - // variable name is found - fFound = 0; - Vec_PtrForEachEntry( vVarNames, pName, v ) - if ( strncmp(pTemp, pName, i) == 0 && strlen(pName) == (unsigned)i ) - { - pTemp += i-1; - fFound = 1; - break; - } - if ( !fFound ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): The parser cannot find var \"%s\" in the input var list.\n", pTemp ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - if ( Flag == PARSE_EQN_FLAG_VAR ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): The variable name \"%s\" follows another var without operation sign.\n", pTemp ); - Flag = PARSE_EQN_FLAG_ERROR; - break; - } - Parse_StackFnPush( pStackFn, Hop_IthVar( pMan, v ) ); // Cudd_Ref( pbVars[v] ); - Flag = PARSE_EQN_FLAG_VAR; - break; - } - - if ( Flag == PARSE_EQN_FLAG_ERROR ) - break; // error exit - else if ( Flag == PARSE_EQN_FLAG_START ) - continue; // go on parsing - else if ( Flag == PARSE_EQN_FLAG_VAR ) - while ( 1 ) - { // check if there are negations in the OpStack - if ( Parse_StackOpIsEmpty(pStackOp) ) - break; - Oper = Parse_StackOpPop( pStackOp ); - if ( Oper != PARSE_EQN_OPER_NEG ) - { - Parse_StackOpPush( pStackOp, Oper ); - break; - } - else - { - Parse_StackFnPush( pStackFn, Hop_Not(Parse_StackFnPop(pStackFn)) ); - } - } - else // if ( Flag == PARSE_EQN_FLAG_OPER ) - while ( 1 ) - { // execute all the operations in the OpStack - // with precedence higher or equal than the last one - Oper1 = Parse_StackOpPop( pStackOp ); // the last operation - if ( Parse_StackOpIsEmpty(pStackOp) ) - { // if it is the only operation, push it back - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - Oper2 = Parse_StackOpPop( pStackOp ); // the operation before the last one - if ( Oper2 >= Oper1 ) - { // if Oper2 precedence is higher or equal, execute it - if ( Parse_ParserPerformTopOp( pMan, pStackFn, Oper2 ) == NULL ) - { - fprintf( pOutput, "Parse_FormulaParserEqn(): Unknown operation\n" ); - free( pFormula ); - return NULL; - } - Parse_StackOpPush( pStackOp, Oper1 ); // push the last operation back - } - else - { // if Oper2 precedence is lower, push them back and done - Parse_StackOpPush( pStackOp, Oper2 ); - Parse_StackOpPush( pStackOp, Oper1 ); - break; - } - } - } - - if ( Flag != PARSE_EQN_FLAG_ERROR ) - { - if ( !Parse_StackFnIsEmpty(pStackFn) ) - { - gFunc = Parse_StackFnPop(pStackFn); - if ( Parse_StackFnIsEmpty(pStackFn) ) - if ( Parse_StackOpIsEmpty(pStackOp) ) - { - Parse_StackFnFree(pStackFn); - Parse_StackOpFree(pStackOp); -// Cudd_Deref( gFunc ); - free( pFormula ); - return gFunc; - } - else - fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the operation stack\n" ); - else - fprintf( pOutput, "Parse_FormulaParserEqn(): Something is left in the function stack\n" ); - } - else - fprintf( pOutput, "Parse_FormulaParserEqn(): The input string is empty\n" ); - } - free( pFormula ); - return NULL; -} - -/**Function************************************************************* - - Synopsis [Performs the operation on the top entries in the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Parse_ParserPerformTopOp( Hop_Man_t * pMan, Parse_StackFn_t * pStackFn, int Oper ) -{ - Hop_Obj_t * gArg1, * gArg2, * gFunc; - // perform the given operation - gArg2 = Parse_StackFnPop( pStackFn ); - gArg1 = Parse_StackFnPop( pStackFn ); - if ( Oper == PARSE_EQN_OPER_AND ) - gFunc = Hop_And( pMan, gArg1, gArg2 ); - else if ( Oper == PARSE_EQN_OPER_OR ) - gFunc = Hop_Or( pMan, gArg1, gArg2 ); - else - return NULL; -// Cudd_Ref( gFunc ); -// Cudd_RecursiveDeref( dd, gArg1 ); -// Cudd_RecursiveDeref( dd, gArg2 ); - Parse_StackFnPush( pStackFn, gFunc ); - return gFunc; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/parse/parseInt.h b/src/bdd/parse/parseInt.h deleted file mode 100644 index 17f48375..00000000 --- a/src/bdd/parse/parseInt.h +++ /dev/null @@ -1,74 +0,0 @@ -/**CFile**************************************************************** - - FileName [parseInt.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Parsing symbolic Boolean formulas into BDDs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: parseInt.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __PARSE_INT_H__ -#define __PARSE_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - - -#include -#include "cuddInt.h" -#include "extra.h" -#include "parse.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef int bool; - -typedef struct ParseStackFnStruct Parse_StackFn_t; // the function stack -typedef struct ParseStackOpStruct Parse_StackOp_t; // the operation stack - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== parseStack.c =============================================================*/ -extern Parse_StackFn_t * Parse_StackFnStart ( int nDepth ); -extern bool Parse_StackFnIsEmpty( Parse_StackFn_t * p ); -extern void Parse_StackFnPush ( Parse_StackFn_t * p, void * bFunc ); -extern void * Parse_StackFnPop ( Parse_StackFn_t * p ); -extern void Parse_StackFnFree ( Parse_StackFn_t * p ); - -extern Parse_StackOp_t * Parse_StackOpStart ( int nDepth ); -extern bool Parse_StackOpIsEmpty( Parse_StackOp_t * p ); -extern void Parse_StackOpPush ( Parse_StackOp_t * p, int Oper ); -extern int Parse_StackOpPop ( Parse_StackOp_t * p ); -extern void Parse_StackOpFree ( Parse_StackOp_t * p ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/parse/parseStack.c b/src/bdd/parse/parseStack.c deleted file mode 100644 index cd7cd7e3..00000000 --- a/src/bdd/parse/parseStack.c +++ /dev/null @@ -1,243 +0,0 @@ -/**CFile**************************************************************** - - FileName [parseStack.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Stacks used by the formula parser.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 18, 2003.] - - Revision [$Id: parseStack.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "parseInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct ParseStackFnStruct -{ - void ** pData; // the array of elements - int Top; // the index - int Size; // the stack size -}; - -struct ParseStackOpStruct -{ - int * pData; // the array of elements - int Top; // the index - int Size; // the stack size -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Parse_StackFn_t * Parse_StackFnStart( int nDepth ) -{ - Parse_StackFn_t * p; - p = ALLOC( Parse_StackFn_t, 1 ); - memset( p, 0, sizeof(Parse_StackFn_t) ); - p->pData = ALLOC( void *, nDepth ); - p->Size = nDepth; - return p; -} - -/**Function************************************************************* - - Synopsis [Checks whether the stack is empty.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Parse_StackFnIsEmpty( Parse_StackFn_t * p ) -{ - return (bool)(p->Top == 0); -} - -/**Function************************************************************* - - Synopsis [Pushes an entry into the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackFnPush( Parse_StackFn_t * p, void * bFunc ) -{ - if ( p->Top >= p->Size ) - { - printf( "Parse_StackFnPush(): Stack size is too small!\n" ); - return; - } - p->pData[ p->Top++ ] = bFunc; -} - -/**Function************************************************************* - - Synopsis [Pops an entry out of the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Parse_StackFnPop( Parse_StackFn_t * p ) -{ - if ( p->Top == 0 ) - { - printf( "Parse_StackFnPush(): Trying to extract data from the empty stack!\n" ); - return NULL; - } - return p->pData[ --p->Top ]; -} - -/**Function************************************************************* - - Synopsis [Deletes the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackFnFree( Parse_StackFn_t * p ) -{ - FREE( p->pData ); - FREE( p ); -} - - - - -/**Function************************************************************* - - Synopsis [Starts the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Parse_StackOp_t * Parse_StackOpStart( int nDepth ) -{ - Parse_StackOp_t * p; - p = ALLOC( Parse_StackOp_t, 1 ); - memset( p, 0, sizeof(Parse_StackOp_t) ); - p->pData = ALLOC( int, nDepth ); - p->Size = nDepth; - return p; -} - -/**Function************************************************************* - - Synopsis [Checks whether the stack is empty.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Parse_StackOpIsEmpty( Parse_StackOp_t * p ) -{ - return (bool)(p->Top == 0); -} - -/**Function************************************************************* - - Synopsis [Pushes an entry into the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackOpPush( Parse_StackOp_t * p, int Oper ) -{ - if ( p->Top >= p->Size ) - { - printf( "Parse_StackOpPush(): Stack size is too small!\n" ); - return; - } - p->pData[ p->Top++ ] = Oper; -} - -/**Function************************************************************* - - Synopsis [Pops an entry out of the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Parse_StackOpPop( Parse_StackOp_t * p ) -{ - if ( p->Top == 0 ) - { - printf( "Parse_StackOpPush(): Trying to extract data from the empty stack!\n" ); - return -1; - } - return p->pData[ --p->Top ]; -} - -/**Function************************************************************* - - Synopsis [Deletes the stack.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Parse_StackOpFree( Parse_StackOp_t * p ) -{ - FREE( p->pData ); - FREE( p ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/bdd/reo/module.make b/src/bdd/reo/module.make deleted file mode 100644 index 7eb41e0e..00000000 --- a/src/bdd/reo/module.make +++ /dev/null @@ -1,7 +0,0 @@ -SRC += src/bdd/reo/reoApi.c \ - src/bdd/reo/reoCore.c \ - src/bdd/reo/reoProfile.c \ - src/bdd/reo/reoSift.c \ - src/bdd/reo/reoSwap.c \ - src/bdd/reo/reoTransfer.c \ - src/bdd/reo/reoUnits.c diff --git a/src/bdd/reo/reo.h b/src/bdd/reo/reo.h deleted file mode 100644 index 1a31242a..00000000 --- a/src/bdd/reo/reo.h +++ /dev/null @@ -1,232 +0,0 @@ -/**CFile**************************************************************** - - FileName [reo.h] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [External and internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reo.h,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __REO_H__ -#define __REO_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "extra.h" - -//#pragma warning( disable : 4514 ) - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// reordering parameters -#define REO_REORDER_LIMIT 1.15 // determines the quality/runtime trade-off -#define REO_QUAL_PAR 3 // the quality [1 = simple lower bound, 2 = strict, larger = heuristic] -// internal parameters -#define REO_CONST_LEVEL 30000 // the number of the constant level -#define REO_TOPREF_UNDEF 30000 // the undefined top reference -#define REO_CHUNK_SIZE 5000 // the number of units allocated at one time -#define REO_COST_EPSILON 0.0000001 // difference in cost large enough so that it counted as an error -#define REO_HIGH_VALUE 10000000 // a large value used to initialize some variables -// interface parameters -#define REO_ENABLE 1 // the value of the enable flag -#define REO_DISABLE 0 // the value of the disable flag - -// the types of minimization currently supported -typedef enum { - REO_MINIMIZE_NODES, - REO_MINIMIZE_WIDTH, // may not work for BDDs with complemented edges - REO_MINIMIZE_APL -} reo_min_type; - -//////////////////////////////////////////////////////////////////////// -/// DATA STRUCTURES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct _reo_unit reo_unit; // the unit representing one DD node during reordering -typedef struct _reo_plane reo_plane; // the set of nodes on one level -typedef struct _reo_hash reo_hash; // the entry in the hash table -typedef struct _reo_man reo_man; // the reordering manager -typedef struct _reo_test reo_test; // - -struct _reo_unit -{ - short lev; // the level of this node at the beginning - short TopRef; // the top level from which this node is refed (used to update BDD width) - short TopRefNew; // the new top level from which this node is refed (used to update BDD width) - short n; // the number of incoming edges (similar to ref count in the BDD) - int Sign; // the signature - - reo_unit * pE; // the pointer to the "else" branch - reo_unit * pT; // the pointer to the "then" branch - reo_unit * Next; // the link to the next one in the list - double Weight; // the probability of traversing this node -}; - -struct _reo_plane -{ - int fSifted; // to mark the sifted variables - int statsNodes; // the number of nodes in the current level - int statsWidth; // the width on the current level - double statsApl; // the sum of node probabilities on this level - double statsCost; // the current cost is stored here - double statsCostAbove; // the current cost is stored here - double statsCostBelow; // the current cost is stored here - - reo_unit * pHead; // the pointer to the beginning of the unit list -}; - -struct _reo_hash -{ - int Sign; // signature of the current cache operation - reo_unit * Arg1; // the first argument - reo_unit * Arg2; // the second argument - reo_unit * Arg3; // the third argument -}; - -struct _reo_man -{ - // these paramaters can be set by the API functions - int fMinWidth; // the flag to enable reordering for minimum width - int fMinApl; // the flag to enable reordering for minimum APL - int fVerbose; // the verbosity level - int fVerify; // the flag toggling verification - int fRemapUp; // the flag to enable remapping - int nIters; // the number of interations of sifting to perform - - // parameters given by the user when reordering is called - DdManager * dd; // the CUDD BDD manager - int * pOrder; // the resulting variable order will be returned here - - // derived parameters - int fThisIsAdd; // this flag is one if the function is the ADD - int * pSupp; // the support of the given function - int nSuppAlloc; // the max allowed number of support variables - int nSupp; // the number of support variables - int * pOrderInt; // the array storing the internal variable permutation - double * pVarCosts; // other arrays - int * pLevelOrder; // other arrays - reo_unit ** pWidthCofs; // temporary storage for cofactors used during reordering for width - - // parameters related to cost - int nNodesBeg; - int nNodesCur; - int nNodesEnd; - int nWidthCur; - int nWidthBeg; - int nWidthEnd; - double nAplCur; - double nAplBeg; - double nAplEnd; - - // mapping of the function into planes and back - int * pMapToPlanes; // the mapping of var indexes into plane levels - int * pMapToDdVarsOrig;// the mapping of plane levels into the original indexes - int * pMapToDdVarsFinal;// the mapping of plane levels into the final indexes - - // the planes table - reo_plane * pPlanes; - int nPlanes; - reo_unit ** pTops; - int nTops; - int nTopsAlloc; - - // the hash table - reo_hash * HTable; // the table itself - int nTableSize; // the size of the hash table - int Signature; // the signature counter - - // the referenced node list - int nNodesMaxAlloc; // this parameters determins how much memory is allocated - DdNode ** pRefNodes; - int nRefNodes; - int nRefNodesAlloc; - - // unit memory management - reo_unit * pUnitFreeList; - reo_unit ** pMemChunks; - int nMemChunks; - int nMemChunksAlloc; - int nUnitsUsed; - - // statistic variables - int HashSuccess; - int HashFailure; - int nSwaps; // the number of swaps - int nNISwaps; // the number of swaps without interaction -}; - -// used to manipulate units -#define Unit_Regular(u) ((reo_unit *)((unsigned long)(u) & ~01)) -#define Unit_Not(u) ((reo_unit *)((unsigned long)(u) ^ 01)) -#define Unit_NotCond(u,c) ((reo_unit *)((unsigned long)(u) ^ (c))) -#define Unit_IsConstant(u) ((int)((u)->lev == REO_CONST_LEVEL)) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// ======================= reoApi.c ======================================== -extern reo_man * Extra_ReorderInit( int nDdVarsMax, int nNodesMax ); -extern void Extra_ReorderQuit( reo_man * p ); -extern void Extra_ReorderSetMinimizationType( reo_man * p, reo_min_type fMinType ); -extern void Extra_ReorderSetRemapping( reo_man * p, int fRemapUp ); -extern void Extra_ReorderSetIterations( reo_man * p, int nIters ); -extern void Extra_ReorderSetVerbosity( reo_man * p, int fVerbose ); -extern void Extra_ReorderSetVerification( reo_man * p, int fVerify ); -extern DdNode * Extra_Reorder( reo_man * p, DdManager * dd, DdNode * Func, int * pOrder ); -extern void Extra_ReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ); -// ======================= reoCore.c ======================================= -extern void reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ); -extern void reoResizeStructures( reo_man * p, int nDdVarsMax, int nNodesMax, int nFuncs ); -// ======================= reoProfile.c ====================================== -extern void reoProfileNodesStart( reo_man * p ); -extern void reoProfileAplStart( reo_man * p ); -extern void reoProfileWidthStart( reo_man * p ); -extern void reoProfileWidthStart2( reo_man * p ); -extern void reoProfileAplPrint( reo_man * p ); -extern void reoProfileNodesPrint( reo_man * p ); -extern void reoProfileWidthPrint( reo_man * p ); -extern void reoProfileWidthVerifyLevel( reo_plane * pPlane, int Level ); -// ======================= reoSift.c ======================================= -extern void reoReorderSift( reo_man * p ); -// ======================= reoSwap.c ======================================= -extern double reoReorderSwapAdjacentVars( reo_man * p, int Level, int fMovingUp ); -// ======================= reoTransfer.c =================================== -extern reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ); -extern DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ); -// ======================= reoUnits.c ====================================== -extern reo_unit * reoUnitsGetNextUnit(reo_man * p ); -extern void reoUnitsRecycleUnit( reo_man * p, reo_unit * pUnit ); -extern void reoUnitsRecycleUnitList( reo_man * p, reo_plane * pPlane ); -extern void reoUnitsAddUnitToPlane( reo_plane * pPlane, reo_unit * pUnit ); -extern void reoUnitsStopDispenser( reo_man * p ); -// ======================= reoTest.c ======================================= -extern void Extra_ReorderTest( DdManager * dd, DdNode * Func ); -extern DdNode * Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermuteReo[] ); -extern int Extra_bddReorderTest( DdManager * dd, DdNode * bF ); -extern int Extra_addReorderTest( DdManager * dd, DdNode * aF ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/bdd/reo/reoApi.c b/src/bdd/reo/reoApi.c deleted file mode 100644 index e833dabd..00000000 --- a/src/bdd/reo/reoApi.c +++ /dev/null @@ -1,289 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoApi.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Implementation of API functions.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoApi.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Initializes the reordering engine.] - - Description [The first argument is the max number of variables in the - CUDD DD manager which will be used with the reordering engine - (this number of should be the maximum of BDD and ZDD parts). - The second argument is the maximum number of BDD nodes in the BDDs - to be reordered. These limits are soft. Setting lower limits will later - cause the reordering manager to resize internal data structures. - However, setting the exact values will make reordering more efficient - because resizing will be not necessary.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -reo_man * Extra_ReorderInit( int nDdVarsMax, int nNodesMax ) -{ - reo_man * p; - // allocate and clean the data structure - p = ALLOC( reo_man, 1 ); - memset( p, 0, sizeof(reo_man) ); - // resize the manager to meet user's needs - reoResizeStructures( p, nDdVarsMax, nNodesMax, 100 ); - // set the defaults - p->fMinApl = 0; - p->fMinWidth = 0; - p->fRemapUp = 0; - p->fVerbose = 0; - p->fVerify = 0; - p->nIters = 1; - return p; -} - -/**Function************************************************************* - - Synopsis [Disposes of the reordering engine.] - - Description [Removes all memory associated with the reordering engine.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderQuit( reo_man * p ) -{ - free( p->pTops ); - free( p->pSupp ); - free( p->pOrderInt ); - free( p->pWidthCofs ); - free( p->pMapToPlanes ); - free( p->pMapToDdVarsOrig ); - free( p->pMapToDdVarsFinal ); - free( p->pPlanes ); - free( p->pVarCosts ); - free( p->pLevelOrder ); - free( p->HTable ); - free( p->pRefNodes ); - reoUnitsStopDispenser( p ); - free( p->pMemChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Sets the type of DD minimizationl that will be performed.] - - Description [Currently, three different types of minimization are supported. - It is possible to minimize the number of BDD nodes. This is a classical type - of minimization, which is attempting to reduce the total number of nodes in - the (shared) BDD of the given Boolean functions. It is also possible to - minimize the BDD width, defined as the sum total of the number of cofactors - on each level in the (shared) BDD (note that the number of cofactors on the - given level may be larger than the number of nodes appearing on the given level). - It is also possible to minimize the average path length in the (shared) BDD - defined as the sum of products, for all BDD paths from the top node to any - terminal node, of the number of minterms on the path by the number of nodes - on the path. The default reordering type is minimization for the number of - BDD nodes. Calling this function with REO_MINIMIZE_WIDTH or REO_MINIMIZE_APL - as the second argument, changes the default minimization option for all the - reorder calls performed afterwards.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderSetMinimizationType( reo_man * p, reo_min_type fMinType ) -{ - if ( fMinType == REO_MINIMIZE_NODES ) - { - p->fMinWidth = 0; - p->fMinApl = 0; - } - else if ( fMinType == REO_MINIMIZE_WIDTH ) - { - p->fMinWidth = 1; - p->fMinApl = 0; - } - else if ( fMinType == REO_MINIMIZE_APL ) - { - p->fMinWidth = 0; - p->fMinApl = 1; - } - else - { - assert( 0 ); - } -} - -/**Function************************************************************* - - Synopsis [Sets the type of remapping performed by the engine.] - - Description [The remapping refers to the way the resulting BDD - is expressed using the elementary variables of the CUDD BDD manager. - Currently, two types possibilities are supported: remapping and no - remapping. Remapping means that the function(s) after reordering - depend on the topmost variables in the manager. No remapping means - that the function(s) after reordering depend on the same variables - as before. Consider the following example. Suppose the initial four - variable function depends on variables 2,4,5, and 9 on the CUDD BDD - manager, which may be found anywhere in the current variable order. - If remapping is set, the function after ordering depends on the - topmost variables in the manager, which may or may not be the same - as the variables 2,4,5, and 9. If no remapping is set, then the - reordered function depend on the same variables 2,4,5, and 9, but - the meaning of each variale has changed according to the new ordering. - The resulting ordering is returned in the array "pOrder" filled out - by the reordering engine in the call to Extra_Reorder(). The default - is no remapping.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderSetRemapping( reo_man * p, int fRemapUp ) -{ - p->fRemapUp = fRemapUp; -} - -/**Function************************************************************* - - Synopsis [Sets the number of iterations of sifting performed.] - - Description [The default is one iteration. But a higher minimization - quality is desired, it is possible to set the number of iterations - to any number larger than 1. Convergence is often reached after - several iterations, so typically it make no sense to set the number - of iterations higher than 3.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderSetIterations( reo_man * p, int nIters ) -{ - p->nIters = nIters; -} - -/**Function************************************************************* - - Synopsis [Sets the verification mode.] - - Description [Setting the level to 1 results in verifying the results - of variable reordering. Verification is performed by remapping the - resulting functions into the original variable order and comparing - them with the original functions given by the user. Enabling verification - typically leads to 20-30% increase in the total runtime of REO.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderSetVerification( reo_man * p, int fVerify ) -{ - p->fVerify = fVerify; -} - -/**Function************************************************************* - - Synopsis [Sets the verbosity level.] - - Description [Setting the level to 1 results in printing statistics - before and after the reordering.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderSetVerbosity( reo_man * p, int fVerbose ) -{ - p->fVerbose = fVerbose; -} - -/**Function************************************************************* - - Synopsis [Performs reordering of the function.] - - Description [Returns the DD minimized by variable reordering in the REO - engine. Takes the CUDD decision diagram manager (dd) and the function (Func) - represented as a BDD or ADD (MTBDD). If the variable array (pOrder) is not NULL, - returns the resulting variable permutation. The permutation is such that if the resulting - function is permuted by Cudd_(add,bdd)Permute() using pOrder as the permutation - array, the initial function (Func) results. - Several flag set by other interface functions specify reordering options: - - Remappig can be set by Extra_ReorderSetRemapping(). Then the resulting DD after - reordering is remapped into the topmost levels of the DD manager. Otherwise, - the resulting DD after reordering is mapped using the same variables, on which it - originally depended, only (possibly) permuted as a result of reordering. - - Minimization type can be set by Extra_ReorderSetMinimizationType(). Note - that when the BDD is minimized for the total width of the total APL, the number - BDD nodes can increase. The total width is defines as sum total of widths on each - level. The width on one level is defined as the number of distinct BDD nodes - pointed by the nodes situated above the given level. - - The number of iterations of sifting can be set by Extra_ReorderSetIterations(). - The decision diagram returned by this procedure is not referenced.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_Reorder( reo_man * p, DdManager * dd, DdNode * Func, int * pOrder ) -{ - DdNode * FuncRes; - Extra_ReorderArray( p, dd, &Func, &FuncRes, 1, pOrder ); - Cudd_Deref( FuncRes ); - return FuncRes; -} - -/**Function************************************************************* - - Synopsis [Performs reordering of the array of functions.] - - Description [The options are similar to the procedure Extra_Reorder(), except that - the user should also provide storage for the resulting DDs, which are returned - referenced.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ) -{ - reoReorderArray( p, dd, Funcs, FuncsRes, nFuncs, pOrder ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoCore.c b/src/bdd/reo/reoCore.c deleted file mode 100644 index 3782631c..00000000 --- a/src/bdd/reo/reoCore.c +++ /dev/null @@ -1,438 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoCore.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Implementation of the core reordering procedure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoCore.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define CALLOC(type, num) ((type *) calloc((long)(num), (long)sizeof(type))) - -static int reoRecursiveDeref( reo_unit * pUnit ); -static int reoCheckZeroRefs( reo_plane * pPlane ); -static int reoCheckLevels( reo_man * p ); - -double s_AplBefore; -double s_AplAfter; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ) -{ - int Counter, i; - - // set the initial parameters - p->dd = dd; - p->pOrder = pOrder; - p->nTops = nFuncs; - // get the initial number of nodes - p->nNodesBeg = Cudd_SharingSize( Funcs, nFuncs ); - // resize the internal data structures of the manager if necessary - reoResizeStructures( p, ddMax(dd->size,dd->sizeZ), p->nNodesBeg, nFuncs ); - // compute the support - p->pSupp = Extra_VectorSupportArray( dd, Funcs, nFuncs, p->pSupp ); - // get the number of support variables - p->nSupp = 0; - for ( i = 0; i < dd->size; i++ ) - p->nSupp += p->pSupp[i]; - - // if it is the constant function, no need to reorder - if ( p->nSupp == 0 ) - { - for ( i = 0; i < nFuncs; i++ ) - { - FuncsRes[i] = Funcs[i]; Cudd_Ref( FuncsRes[i] ); - } - return; - } - - // create the internal variable maps - // go through variable levels in the manager - Counter = 0; - for ( i = 0; i < dd->size; i++ ) - if ( p->pSupp[ dd->invperm[i] ] ) - { - p->pMapToPlanes[ dd->invperm[i] ] = Counter; - p->pMapToDdVarsOrig[Counter] = dd->invperm[i]; - if ( !p->fRemapUp ) - p->pMapToDdVarsFinal[Counter] = dd->invperm[i]; - else - p->pMapToDdVarsFinal[Counter] = dd->invperm[Counter]; - p->pOrderInt[Counter] = Counter; - Counter++; - } - - // set the initial parameters - p->nUnitsUsed = 0; - p->nNodesCur = 0; - p->fThisIsAdd = 0; - p->Signature++; - // transfer the function from the CUDD package into REO"s internal data structure - for ( i = 0; i < nFuncs; i++ ) - p->pTops[i] = reoTransferNodesToUnits_rec( p, Funcs[i] ); - assert( p->nNodesBeg == p->nNodesCur ); - - if ( !p->fThisIsAdd && p->fMinWidth ) - { - printf( "An important message from the REO reordering engine:\n" ); - printf( "The BDD given to the engine for reordering contains complemented edges.\n" ); - printf( "Currently, such BDDs cannot be reordered for the minimum width.\n" ); - printf( "Therefore, minimization for the number of BDD nodes is performed.\n" ); - fflush( stdout ); - p->fMinApl = 0; - p->fMinWidth = 0; - } - - if ( p->fMinWidth ) - reoProfileWidthStart(p); - else if ( p->fMinApl ) - reoProfileAplStart(p); - else - reoProfileNodesStart(p); - - if ( p->fVerbose ) - { - printf( "INITIAL: " ); - if ( p->fMinWidth ) - reoProfileWidthPrint(p); - else if ( p->fMinApl ) - reoProfileAplPrint(p); - else - reoProfileNodesPrint(p); - } - - /////////////////////////////////////////////////////////////////// - // performs the reordering - p->nSwaps = 0; - p->nNISwaps = 0; - for ( i = 0; i < p->nIters; i++ ) - { - reoReorderSift( p ); - // print statistics after each iteration - if ( p->fVerbose ) - { - printf( "ITER #%d: ", i+1 ); - if ( p->fMinWidth ) - reoProfileWidthPrint(p); - else if ( p->fMinApl ) - reoProfileAplPrint(p); - else - reoProfileNodesPrint(p); - } - // if the cost function did not change, stop iterating - if ( p->fMinWidth ) - { - p->nWidthEnd = p->nWidthCur; - assert( p->nWidthEnd <= p->nWidthBeg ); - if ( p->nWidthEnd == p->nWidthBeg ) - break; - } - else if ( p->fMinApl ) - { - p->nAplEnd = p->nAplCur; - assert( p->nAplEnd <= p->nAplBeg ); - if ( p->nAplEnd == p->nAplBeg ) - break; - } - else - { - p->nNodesEnd = p->nNodesCur; - assert( p->nNodesEnd <= p->nNodesBeg ); - if ( p->nNodesEnd == p->nNodesBeg ) - break; - } - } - assert( reoCheckLevels( p ) ); - /////////////////////////////////////////////////////////////////// - -s_AplBefore = p->nAplBeg; -s_AplAfter = p->nAplEnd; - - // set the initial parameters - p->nRefNodes = 0; - p->nNodesCur = 0; - p->Signature++; - // transfer the BDDs from REO's internal data structure to CUDD - for ( i = 0; i < nFuncs; i++ ) - { - FuncsRes[i] = reoTransferUnitsToNodes_rec( p, p->pTops[i] ); Cudd_Ref( FuncsRes[i] ); - } - // undo the DDs referenced for storing in the cache - for ( i = 0; i < p->nRefNodes; i++ ) - Cudd_RecursiveDeref( dd, p->pRefNodes[i] ); - // verify zero refs of the terminal nodes - for ( i = 0; i < nFuncs; i++ ) - { - assert( reoRecursiveDeref( p->pTops[i] ) ); - } - assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) ); - - // prepare the variable map to return to the user - if ( p->pOrder ) - { - // i is the current level in the planes data structure - // p->pOrderInt[i] is the original level in the planes data structure - // p->pMapToDdVarsOrig[i] is the variable, into which we remap when we construct the BDD from planes - // p->pMapToDdVarsOrig[ p->pOrderInt[i] ] is the original BDD variable corresponding to this level - // Therefore, p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ] - // creates the permutation, which remaps the resulting BDD variable into the original BDD variable - for ( i = 0; i < p->nSupp; i++ ) - p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; - } - - if ( p->fVerify ) - { - int fVerification; - DdNode * FuncRemapped; - int * pOrder; - - if ( p->pOrder == NULL ) - { - pOrder = ALLOC( int, p->nSupp ); - for ( i = 0; i < p->nSupp; i++ ) - pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; - } - else - pOrder = p->pOrder; - - fVerification = 1; - for ( i = 0; i < nFuncs; i++ ) - { - // verify the result - if ( p->fThisIsAdd ) - FuncRemapped = Cudd_addPermute( dd, FuncsRes[i], pOrder ); - else - FuncRemapped = Cudd_bddPermute( dd, FuncsRes[i], pOrder ); - Cudd_Ref( FuncRemapped ); - - if ( FuncRemapped != Funcs[i] ) - { - fVerification = 0; - printf( "REO: Internal verification has failed!\n" ); - fflush( stdout ); - } - Cudd_RecursiveDeref( dd, FuncRemapped ); - } - if ( fVerification ) - printf( "REO: Internal verification is okay!\n" ); - - if ( p->pOrder == NULL ) - free( pOrder ); - } - - // recycle the data structure - for ( i = 0; i <= p->nSupp; i++ ) - reoUnitsRecycleUnitList( p, p->pPlanes + i ); -} - -/**Function************************************************************* - - Synopsis [Resizes the internal manager data structures.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoResizeStructures( reo_man * p, int nDdVarsMax, int nNodesMax, int nFuncs ) -{ - // resize data structures depending on the number of variables in the DD manager - if ( p->nSuppAlloc == 0 ) - { - p->pSupp = ALLOC( int, nDdVarsMax + 1 ); - p->pOrderInt = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToPlanes = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToDdVarsOrig = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToDdVarsFinal = ALLOC( int, nDdVarsMax + 1 ); - p->pPlanes = CALLOC( reo_plane, nDdVarsMax + 1 ); - p->pVarCosts = ALLOC( double, nDdVarsMax + 1 ); - p->pLevelOrder = ALLOC( int, nDdVarsMax + 1 ); - p->nSuppAlloc = nDdVarsMax + 1; - } - else if ( p->nSuppAlloc < nDdVarsMax ) - { - free( p->pSupp ); - free( p->pOrderInt ); - free( p->pMapToPlanes ); - free( p->pMapToDdVarsOrig ); - free( p->pMapToDdVarsFinal ); - free( p->pPlanes ); - free( p->pVarCosts ); - free( p->pLevelOrder ); - - p->pSupp = ALLOC( int, nDdVarsMax + 1 ); - p->pOrderInt = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToPlanes = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToDdVarsOrig = ALLOC( int, nDdVarsMax + 1 ); - p->pMapToDdVarsFinal = ALLOC( int, nDdVarsMax + 1 ); - p->pPlanes = CALLOC( reo_plane, nDdVarsMax + 1 ); - p->pVarCosts = ALLOC( double, nDdVarsMax + 1 ); - p->pLevelOrder = ALLOC( int, nDdVarsMax + 1 ); - p->nSuppAlloc = nDdVarsMax + 1; - } - - // resize the data structures depending on the number of nodes - if ( p->nRefNodesAlloc == 0 ) - { - p->nNodesMaxAlloc = nNodesMax; - p->nTableSize = 3*nNodesMax + 1; - p->nRefNodesAlloc = 3*nNodesMax + 1; - p->nMemChunksAlloc = (10*nNodesMax + 1)/REO_CHUNK_SIZE + 1; - - p->HTable = CALLOC( reo_hash, p->nTableSize ); - p->pRefNodes = ALLOC( DdNode *, p->nRefNodesAlloc ); - p->pWidthCofs = ALLOC( reo_unit *, p->nRefNodesAlloc ); - p->pMemChunks = ALLOC( reo_unit *, p->nMemChunksAlloc ); - } - else if ( p->nNodesMaxAlloc < nNodesMax ) - { - void * pTemp; - int nMemChunksAllocPrev = p->nMemChunksAlloc; - - p->nNodesMaxAlloc = nNodesMax; - p->nTableSize = 3*nNodesMax + 1; - p->nRefNodesAlloc = 3*nNodesMax + 1; - p->nMemChunksAlloc = (10*nNodesMax + 1)/REO_CHUNK_SIZE + 1; - - free( p->HTable ); - free( p->pRefNodes ); - free( p->pWidthCofs ); - p->HTable = CALLOC( reo_hash, p->nTableSize ); - p->pRefNodes = ALLOC( DdNode *, p->nRefNodesAlloc ); - p->pWidthCofs = ALLOC( reo_unit *, p->nRefNodesAlloc ); - // p->pMemChunks should be reallocated because it contains pointers currently in use - pTemp = ALLOC( reo_unit *, p->nMemChunksAlloc ); - memmove( pTemp, p->pMemChunks, sizeof(reo_unit *) * nMemChunksAllocPrev ); - free( p->pMemChunks ); - p->pMemChunks = pTemp; - } - - // resize the data structures depending on the number of functions - if ( p->nTopsAlloc == 0 ) - { - p->pTops = ALLOC( reo_unit *, nFuncs ); - p->nTopsAlloc = nFuncs; - } - else if ( p->nTopsAlloc < nFuncs ) - { - free( p->pTops ); - p->pTops = ALLOC( reo_unit *, nFuncs ); - p->nTopsAlloc = nFuncs; - } -} - - -/**Function************************************************************* - - Synopsis [Dereferences units the data structure after reordering.] - - Description [This function is only useful for debugging.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int reoRecursiveDeref( reo_unit * pUnit ) -{ - reo_unit * pUnitR; - pUnitR = Unit_Regular(pUnit); - pUnitR->n--; - if ( Unit_IsConstant(pUnitR) ) - return 1; - if ( pUnitR->n == 0 ) - { - reoRecursiveDeref( pUnitR->pE ); - reoRecursiveDeref( pUnitR->pT ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks the zero references for the given plane.] - - Description [This function is only useful for debugging.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int reoCheckZeroRefs( reo_plane * pPlane ) -{ - reo_unit * pUnit; - for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) - { - if ( pUnit->n != 0 ) - { - assert( 0 ); - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Checks the zero references for the given plane.] - - Description [This function is only useful for debugging.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int reoCheckLevels( reo_man * p ) -{ - reo_unit * pUnit; - int i; - - for ( i = 0; i < p->nSupp; i++ ) - { - // there are some nodes left on each level - assert( p->pPlanes[i].statsNodes ); - for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) - { - // the level is properly set - assert( pUnit->lev == i ); - } - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoProfile.c b/src/bdd/reo/reoProfile.c deleted file mode 100644 index 84a0bc19..00000000 --- a/src/bdd/reo/reoProfile.c +++ /dev/null @@ -1,365 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoProfile.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Procudures that compute variables profiles (nodes, width, APL).] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoProfile.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function******************************************************************** - - Synopsis [Start the profile for the BDD nodes.] - - Description [TopRef is the first level, on this the given node counts towards - the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileNodesStart( reo_man * p ) -{ - int Total, i; - Total = 0; - for ( i = 0; i <= p->nSupp; i++ ) - { - p->pPlanes[i].statsCost = p->pPlanes[i].statsNodes; - Total += p->pPlanes[i].statsNodes; - } - assert( Total == p->nNodesCur ); - p->nNodesBeg = p->nNodesCur; -} - -/**Function************************************************************* - - Synopsis [Start the profile for the APL.] - - Description [Computes the total path length. The path length is normalized - by dividing it by 2^|supp(f)|. To get the "real" APL, multiply by 2^|supp(f)|. - This procedure assumes that Weight field of all nodes has been set to 0.0 - before the call, except for the weight of the topmost node, which is set to 1.0 - (1.0 is the probability of traversing the topmost node). This procedure - assigns the edge weights. Because of the equal probability of selecting 0 and 1 - assignment at a node, the edge weights are the same for the node. - Instead of storing them, we store the weight of the node, which is the probability - of traversing the node (pUnit->Weight) during the top down evalation of the BDD. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoProfileAplStart( reo_man * p ) -{ - reo_unit * pER, * pTR; - reo_unit * pUnit; - double Res, Half; - int i; - - // clean the weights of all nodes - for ( i = 0; i < p->nSupp; i++ ) - for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) - pUnit->Weight = 0.0; - // to assign the node weights (the probability of visiting each node) - // we visit the node after visiting its predecessors - - // set the probability of visits to the top nodes - for ( i = 0; i < p->nTops; i++ ) - Unit_Regular(p->pTops[i])->Weight += 1.0; - - // to compute the path length (the sum of products of edge weight by edge length) - // we visit the nodes in any order (the above order will do) - Res = 0.0; - for ( i = 0; i < p->nSupp; i++ ) - { - p->pPlanes[i].statsCost = 0.0; - for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) - { - pER = Unit_Regular(pUnit->pE); - pTR = Unit_Regular(pUnit->pT); - Half = 0.5 * pUnit->Weight; - pER->Weight += Half; - pTR->Weight += Half; - // add to the path length - p->pPlanes[i].statsCost += pUnit->Weight; - } - Res += p->pPlanes[i].statsCost; - } - p->pPlanes[p->nSupp].statsCost = 0.0; - p->nAplBeg = p->nAplCur = Res; -} - -/**Function******************************************************************** - - Synopsis [Start the profile for the BDD width. Complexity of the algorithm is O(N + n).] - - Description [TopRef is the first level, on which the given node counts towards - the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileWidthStart( reo_man * p ) -{ - reo_unit * pUnit; - int * pWidthStart; - int * pWidthStop; - int v; - - // allocate and clean the storage for starting and stopping levels - pWidthStart = ALLOC( int, p->nSupp + 1 ); - pWidthStop = ALLOC( int, p->nSupp + 1 ); - memset( pWidthStart, 0, sizeof(int) * (p->nSupp + 1) ); - memset( pWidthStop, 0, sizeof(int) * (p->nSupp + 1) ); - - // go through the non-constant nodes and set the topmost level of their cofactors - for ( v = 0; v <= p->nSupp; v++ ) - for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) - { - pUnit->TopRef = REO_TOPREF_UNDEF; - pUnit->Sign = 0; - } - - // add the topmost level of the width profile - for ( v = 0; v < p->nTops; v++ ) - { - pUnit = Unit_Regular(p->pTops[v]); - if ( pUnit->TopRef == REO_TOPREF_UNDEF ) - { - // set the starting level - pUnit->TopRef = 0; - pWidthStart[pUnit->TopRef]++; - // set the stopping level - if ( pUnit->lev != REO_CONST_LEVEL ) - pWidthStop[pUnit->lev+1]++; - } - } - - for ( v = 0; v < p->nSupp; v++ ) - for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) - { - if ( pUnit->pE->TopRef == REO_TOPREF_UNDEF ) - { - // set the starting level - pUnit->pE->TopRef = pUnit->lev + 1; - pWidthStart[pUnit->pE->TopRef]++; - // set the stopping level - if ( pUnit->pE->lev != REO_CONST_LEVEL ) - pWidthStop[pUnit->pE->lev+1]++; - } - if ( pUnit->pT->TopRef == REO_TOPREF_UNDEF ) - { - // set the starting level - pUnit->pT->TopRef = pUnit->lev + 1; - pWidthStart[pUnit->pT->TopRef]++; - // set the stopping level - if ( pUnit->pT->lev != REO_CONST_LEVEL ) - pWidthStop[pUnit->pT->lev+1]++; - } - } - - // verify the top reference - for ( v = 0; v < p->nSupp; v++ ) - reoProfileWidthVerifyLevel( p->pPlanes + v, v ); - - // derive the profile - p->nWidthCur = 0; - for ( v = 0; v <= p->nSupp; v++ ) - { - if ( v == 0 ) - p->pPlanes[v].statsWidth = pWidthStart[v] - pWidthStop[v]; - else - p->pPlanes[v].statsWidth = p->pPlanes[v-1].statsWidth + pWidthStart[v] - pWidthStop[v]; - p->pPlanes[v].statsCost = p->pPlanes[v].statsWidth; - p->nWidthCur += p->pPlanes[v].statsWidth; -// printf( "Level %2d: Width = %5d. Correct = %d.\n", v, Temp, p->pPlanes[v].statsWidth ); - } - p->nWidthBeg = p->nWidthCur; - free( pWidthStart ); - free( pWidthStop ); -} - -/**Function******************************************************************** - - Synopsis [Start the profile for the BDD width. Complexity of the algorithm is O(N * n).] - - Description [TopRef is the first level, on which the given node counts towards - the width of the BDDs. (In other words, it is the level of the referencing node plus 1.)] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileWidthStart2( reo_man * p ) -{ - reo_unit * pUnit; - int i, v; - - // clean the profile - for ( i = 0; i <= p->nSupp; i++ ) - p->pPlanes[i].statsWidth = 0; - - // clean the node structures - for ( v = 0; v <= p->nSupp; v++ ) - for ( pUnit = p->pPlanes[v].pHead; pUnit; pUnit = pUnit->Next ) - { - pUnit->TopRef = REO_TOPREF_UNDEF; - pUnit->Sign = 0; - } - - // set the topref to the topmost nodes - for ( i = 0; i < p->nTops; i++ ) - Unit_Regular(p->pTops[i])->TopRef = 0; - - // go through the non-constant nodes and set the topmost level of their cofactors - for ( i = 0; i < p->nSupp; i++ ) - for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) - { - if ( pUnit->pE->TopRef > i+1 ) - pUnit->pE->TopRef = i+1; - if ( pUnit->pT->TopRef > i+1 ) - pUnit->pT->TopRef = i+1; - } - - // verify the top reference - for ( i = 0; i < p->nSupp; i++ ) - reoProfileWidthVerifyLevel( p->pPlanes + i, i ); - - // compute the profile for the internal nodes - for ( i = 0; i < p->nSupp; i++ ) - for ( pUnit = p->pPlanes[i].pHead; pUnit; pUnit = pUnit->Next ) - for ( v = pUnit->TopRef; v <= pUnit->lev; v++ ) - p->pPlanes[v].statsWidth++; - - // compute the profile for the constant nodes - for ( pUnit = p->pPlanes[p->nSupp].pHead; pUnit; pUnit = pUnit->Next ) - for ( v = pUnit->TopRef; v <= p->nSupp; v++ ) - p->pPlanes[v].statsWidth++; - - // get the width cost - p->nWidthCur = 0; - for ( i = 0; i <= p->nSupp; i++ ) - { - p->pPlanes[i].statsCost = p->pPlanes[i].statsWidth; - p->nWidthCur += p->pPlanes[i].statsWidth; - } - p->nWidthBeg = p->nWidthCur; -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileNodesPrint( reo_man * p ) -{ - printf( "NODES: Total = %6d. Average = %6.2f.\n", p->nNodesCur, p->nNodesCur / (float)p->nSupp ); -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileAplPrint( reo_man * p ) -{ - printf( "APL: Total = %8.2f. Average =%6.2f.\n", p->nAplCur, p->nAplCur / (float)p->nSupp ); -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileWidthPrint( reo_man * p ) -{ - int WidthMax; - int TotalWidth; - int i; - - WidthMax = 0; - TotalWidth = 0; - for ( i = 0; i <= p->nSupp; i++ ) - { -// printf( "Level = %2d. Width = %3d.\n", i, p->pProfile[i] ); - if ( WidthMax < p->pPlanes[i].statsWidth ) - WidthMax = p->pPlanes[i].statsWidth; - TotalWidth += p->pPlanes[i].statsWidth; - } - assert( p->nWidthCur == TotalWidth ); - printf( "WIDTH: " ); - printf( "Maximum = %5d. ", WidthMax ); - printf( "Total = %7d. ", p->nWidthCur ); - printf( "Average = %6.2f.\n", TotalWidth / (float)p->nSupp ); -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void reoProfileWidthVerifyLevel( reo_plane * pPlane, int Level ) -{ - reo_unit * pUnit; - for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) - { - assert( pUnit->TopRef <= Level ); - assert( pUnit->pE->TopRef <= Level + 1 ); - assert( pUnit->pT->TopRef <= Level + 1 ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoSift.c b/src/bdd/reo/reoSift.c deleted file mode 100644 index 93d82f08..00000000 --- a/src/bdd/reo/reoSift.c +++ /dev/null @@ -1,341 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoSift.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Implementation of the sifting algorihtm.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoSift.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Implements the variable sifting algorithm.] - - Description [Performs a sequence of adjacent variable swaps known as "sifting". - Uses the cost functions determined by the flag.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoReorderSift( reo_man * p ) -{ - double CostCurrent; // the cost of the current permutation - double CostLimit; // the maximum increase in cost that can be tolerated - double CostBest; // the best cost - int BestQ; // the best position - int VarCurrent; // the current variable to move - int q; // denotes the current position of the variable - int c; // performs the loops over variables until all of them are sifted - int v; // used for other purposes - - assert( p->nSupp > 0 ); - - // set the current cost depending on the minimization criteria - if ( p->fMinWidth ) - CostCurrent = p->nWidthCur; - else if ( p->fMinApl ) - CostCurrent = p->nAplCur; - else - CostCurrent = p->nNodesCur; - - // find the upper bound on tbe cost growth - CostLimit = 1 + (int)(REO_REORDER_LIMIT * CostCurrent); - - // perform sifting for each of p->nSupp variables - for ( c = 0; c < p->nSupp; c++ ) - { - // select the current variable to be the one with the largest number of nodes that is not sifted yet - VarCurrent = -1; - CostBest = -1.0; - for ( v = 0; v < p->nSupp; v++ ) - { - p->pVarCosts[v] = REO_HIGH_VALUE; - if ( !p->pPlanes[v].fSifted ) - { -// VarCurrent = v; -// if ( CostBest < p->pPlanes[v].statsCost ) - if ( CostBest < p->pPlanes[v].statsNodes ) - { -// CostBest = p->pPlanes[v].statsCost; - CostBest = p->pPlanes[v].statsNodes; - VarCurrent = v; - } - - } - } - assert( VarCurrent != -1 ); - // mark this variable as sifted - p->pPlanes[VarCurrent].fSifted = 1; - - // set the current value - p->pVarCosts[VarCurrent] = CostCurrent; - - // set the best cost - CostBest = CostCurrent; - BestQ = VarCurrent; - - // determine which way to move the variable first (up or down) - // the rationale is that if we move the shorter way first - // it is more likely that the best position will be found on the longer way - // and the reverse movement (to take the best position) will be faster - if ( VarCurrent < p->nSupp/2 ) // move up first, then down - { - // set the total cost on all levels above the current level - p->pPlanes[0].statsCostAbove = 0; - for ( v = 1; v <= VarCurrent; v++ ) - p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost; - // set the total cost on all levels below the current level - p->pPlanes[p->nSupp].statsCostBelow = 0; - for ( v = p->nSupp - 1; v >= VarCurrent; v-- ) - p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost; - - assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + - p->pPlanes[VarCurrent].statsCost + - p->pPlanes[VarCurrent].statsCostBelow ); - - // move up - for ( q = VarCurrent-1; q >= 0; q-- ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 ); - // now q points to the position of this var in the order - p->pVarCosts[q] = CostCurrent; - // update the lower bound (assuming that for level q+1 it is set correctly) - p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost; - // check the upper bound - if ( CostCurrent >= CostLimit ) - break; - // check the lower bound - if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest ) - break; - // update the best cost - if ( CostBest > CostCurrent ) - { - CostBest = CostCurrent; - BestQ = q; - // adjust node limit - CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); - } - - // when we are reordering for width or APL, it may happen that - // the number of nodes has grown above certain limit, - // in which case we have to resize the data structures - if ( p->fMinWidth || p->fMinApl ) - { - if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) - { -// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); - reoResizeStructures( p, 0, p->nNodesCur, 0 ); - } - } - } - // fix the plane index - if ( q == -1 ) - q++; - // now p points to the position of this var in the order - - // move down - for ( ; q < p->nSupp-1; ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); - q++; // change q to point to the position of this var in the order - // sanity check: the number of nodes on the back pass should be the same - if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON ) - printf("reoReorderSift(): Error! On the backward move, the costs are different.\n"); - p->pVarCosts[q] = CostCurrent; - // update the lower bound (assuming that for level q-1 it is set correctly) - p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost; - // check the bounds only if the variable already reached its previous position - if ( q >= BestQ ) - { - // check the upper bound - if ( CostCurrent >= CostLimit ) - break; - // check the lower bound - if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest ) - break; - } - // update the best cost - if ( CostBest >= CostCurrent ) - { - CostBest = CostCurrent; - BestQ = q; - // adjust node limit - CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); - } - - // when we are reordering for width or APL, it may happen that - // the number of nodes has grown above certain limit, - // in which case we have to resize the data structures - if ( p->fMinWidth || p->fMinApl ) - { - if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) - { -// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); - reoResizeStructures( p, 0, p->nNodesCur, 0 ); - } - } - } - // move the variable up from the given position (q) to the best position (BestQ) - assert( q >= BestQ ); - for ( ; q > BestQ; q-- ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q-1, 1 ); - // sanity check: the number of nodes on the back pass should be the same - if ( fabs( p->pVarCosts[q-1] - CostCurrent ) > REO_COST_EPSILON ) - { - printf("reoReorderSift(): Error! On the return move, the costs are different.\n" ); - fflush(stdout); - } - } - } - else // move down first, then up - { - // set the current number of nodes on all levels above the given level - p->pPlanes[0].statsCostAbove = 0; - for ( v = 1; v <= VarCurrent; v++ ) - p->pPlanes[v].statsCostAbove = p->pPlanes[v-1].statsCostAbove + p->pPlanes[v-1].statsCost; - // set the current number of nodes on all levels below the given level - p->pPlanes[p->nSupp].statsCostBelow = 0; - for ( v = p->nSupp - 1; v >= VarCurrent; v-- ) - p->pPlanes[v].statsCostBelow = p->pPlanes[v+1].statsCostBelow + p->pPlanes[v+1].statsCost; - - assert( CostCurrent == p->pPlanes[VarCurrent].statsCostAbove + - p->pPlanes[VarCurrent].statsCost + - p->pPlanes[VarCurrent].statsCostBelow ); - - // move down - for ( q = VarCurrent; q < p->nSupp-1; ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); - q++; // change q to point to the position of this var in the order - p->pVarCosts[q] = CostCurrent; - // update the lower bound (assuming that for level q-1 it is set correctly) - p->pPlanes[q].statsCostAbove = p->pPlanes[q-1].statsCostAbove + p->pPlanes[q-1].statsCost; - // check the upper bound - if ( CostCurrent >= CostLimit ) - break; - // check the lower bound - if ( p->pPlanes[q].statsCostAbove + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostBelow/REO_QUAL_PAR >= CostBest ) - break; - // update the best cost - if ( CostBest > CostCurrent ) - { - CostBest = CostCurrent; - BestQ = q; - // adjust node limit - CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); - } - - // when we are reordering for width or APL, it may happen that - // the number of nodes has grown above certain limit, - // in which case we have to resize the data structures - if ( p->fMinWidth || p->fMinApl ) - { - if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) - { -// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); - reoResizeStructures( p, 0, p->nNodesCur, 0 ); - } - } - } - - // move up - for ( --q; q >= 0; q-- ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q, 1 ); - // now q points to the position of this var in the order - // sanity check: the number of nodes on the back pass should be the same - if ( p->pVarCosts[q] != REO_HIGH_VALUE && fabs( p->pVarCosts[q] - CostCurrent ) > REO_COST_EPSILON ) - printf("reoReorderSift(): Error! On the backward move, the costs are different.\n"); - p->pVarCosts[q] = CostCurrent; - // update the lower bound (assuming that for level q+1 it is set correctly) - p->pPlanes[q].statsCostBelow = p->pPlanes[q+1].statsCostBelow + p->pPlanes[q+1].statsCost; - // check the bounds only if the variable already reached its previous position - if ( q <= BestQ ) - { - // check the upper bound - if ( CostCurrent >= CostLimit ) - break; - // check the lower bound - if ( p->pPlanes[q].statsCostBelow + (REO_QUAL_PAR-1)*p->pPlanes[q].statsCostAbove/REO_QUAL_PAR >= CostBest ) - break; - } - // update the best cost - if ( CostBest >= CostCurrent ) - { - CostBest = CostCurrent; - BestQ = q; - // adjust node limit - CostLimit = ddMin( CostLimit, 1 + (int)(REO_REORDER_LIMIT * CostCurrent) ); - } - - // when we are reordering for width or APL, it may happen that - // the number of nodes has grown above certain limit, - // in which case we have to resize the data structures - if ( p->fMinWidth || p->fMinApl ) - { - if ( p->nNodesCur >= 2 * p->nNodesMaxAlloc ) - { -// printf( "Resizing data structures. Old size = %6d. New size = %6d.\n", p->nNodesMaxAlloc, p->nNodesCur ); - reoResizeStructures( p, 0, p->nNodesCur, 0 ); - } - } - } - // fix the plane index - if ( q == -1 ) - q++; - // now q points to the position of this var in the order - // move the variable down from the given position (q) to the best position (BestQ) - assert( q <= BestQ ); - for ( ; q < BestQ; q++ ) - { - CostCurrent -= reoReorderSwapAdjacentVars( p, q, 0 ); - // sanity check: the number of nodes on the back pass should be the same - if ( fabs( p->pVarCosts[q+1] - CostCurrent ) > REO_COST_EPSILON ) - { - printf("reoReorderSift(): Error! On the return move, the costs are different.\n" ); - fflush(stdout); - } - } - } - assert( fabs( CostBest - CostCurrent ) < REO_COST_EPSILON ); - - // update the cost - if ( p->fMinWidth ) - p->nWidthCur = (int)CostBest; - else if ( p->fMinApl ) - p->nAplCur = CostCurrent; - else - p->nNodesCur = (int)CostBest; - } - - // remove the sifted attributes if any - for ( v = 0; v < p->nSupp; v++ ) - p->pPlanes[v].fSifted = 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoSwap.c b/src/bdd/reo/reoSwap.c deleted file mode 100644 index 4afa650c..00000000 --- a/src/bdd/reo/reoSwap.c +++ /dev/null @@ -1,898 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoSwap.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Implementation of the two-variable swap.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoSwap.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define AddToLinkedList( ppList, pLink ) (((pLink)->Next = *(ppList)), (*(ppList) = (pLink))) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [Takes the level (lev0) of the plane, which should be swapped - with the next plane. Returns the gain using the current cost function.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -double reoReorderSwapAdjacentVars( reo_man * p, int lev0, int fMovingUp ) -{ - // the levels in the decision diagram - int lev1 = lev0 + 1, lev2 = lev0 + 2; - // the new nodes on lev0 - reo_unit * pLoop, * pUnit; - // the new nodes on lev1 - reo_unit * pNewPlane20, * pNewPlane21, * pNewPlane20R; - reo_unit * pUnitE, * pUnitER, * pUnitT; - // the nodes below lev1 - reo_unit * pNew1E, * pNew1T, * pNew2E, * pNew2T; - reo_unit * pNew1ER, * pNew2ER; - // the old linked lists - reo_unit * pListOld0 = p->pPlanes[lev0].pHead; - reo_unit * pListOld1 = p->pPlanes[lev1].pHead; - // working planes and one more temporary plane - reo_unit * pListNew0 = NULL, ** ppListNew0 = &pListNew0; - reo_unit * pListNew1 = NULL, ** ppListNew1 = &pListNew1; - reo_unit * pListTemp = NULL, ** ppListTemp = &pListTemp; - // various integer variables - int fComp, fCompT, fFound, nWidthCofs, HKey, fInteract, temp, c; - // statistical variables - int nNodesUpMovedDown = 0; - int nNodesDownMovedUp = 0; - int nNodesUnrefRemoved = 0; - int nNodesUnrefAdded = 0; - int nWidthReduction = 0; - double AplWeightTotalLev0; - double AplWeightTotalLev1; - double AplWeightHalf; - double AplWeightPrev; - double AplWeightAfter; - double nCostGain; - - // set the old lists - assert( lev0 >= 0 && lev1 < p->nSupp ); - pListOld0 = p->pPlanes[lev0].pHead; - pListOld1 = p->pPlanes[lev1].pHead; - - // make sure the planes have nodes - assert( p->pPlanes[lev0].statsNodes && p->pPlanes[lev1].statsNodes ); - assert( pListOld0 && pListOld1 ); - - if ( p->fMinWidth ) - { - // verify that the width parameters are set correctly - reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 ); - reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 ); - // start the storage for cofactors - nWidthCofs = 0; - } - else if ( p->fMinApl ) - { - AplWeightPrev = p->nAplCur; - AplWeightAfter = p->nAplCur; - AplWeightTotalLev0 = 0.0; - AplWeightTotalLev1 = 0.0; - } - - // check if the planes interact - fInteract = 0; // assume that they do not interact - for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) - { - if ( pUnit->pT->lev == lev1 || Unit_Regular(pUnit->pE)->lev == lev1 ) - { - fInteract = 1; - break; - } - // change the level now, this is done for efficiency reasons - pUnit->lev = lev1; - } - - // set the new signature for hashing - p->nSwaps++; - if ( !fInteract ) -// if ( 0 ) - { - // perform the swap without interaction - p->nNISwaps++; - - // change the levels - if ( p->fMinWidth ) - { - // go through the current lower level, which will become upper - for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next ) - { - pUnit->lev = lev0; - - pUnitER = Unit_Regular(pUnit->pE); - if ( pUnitER->TopRef > lev0 ) - { - if ( pUnitER->Sign != p->nSwaps ) - { - if ( pUnitER->TopRef == lev2 ) - { - pUnitER->TopRef = lev1; - nWidthReduction--; - } - else - { - assert( pUnitER->TopRef == lev1 ); - } - pUnitER->Sign = p->nSwaps; - } - } - - pUnitT = pUnit->pT; - if ( pUnitT->TopRef > lev0 ) - { - if ( pUnitT->Sign != p->nSwaps ) - { - if ( pUnitT->TopRef == lev2 ) - { - pUnitT->TopRef = lev1; - nWidthReduction--; - } - else - { - assert( pUnitT->TopRef == lev1 ); - } - pUnitT->Sign = p->nSwaps; - } - } - - } - - // go through the current upper level, which will become lower - for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) - { - pUnit->lev = lev1; - - pUnitER = Unit_Regular(pUnit->pE); - if ( pUnitER->TopRef > lev0 ) - { - if ( pUnitER->Sign != p->nSwaps ) - { - assert( pUnitER->TopRef == lev1 ); - pUnitER->TopRef = lev2; - pUnitER->Sign = p->nSwaps; - nWidthReduction++; - } - } - - pUnitT = pUnit->pT; - if ( pUnitT->TopRef > lev0 ) - { - if ( pUnitT->Sign != p->nSwaps ) - { - assert( pUnitT->TopRef == lev1 ); - pUnitT->TopRef = lev2; - pUnitT->Sign = p->nSwaps; - nWidthReduction++; - } - } - } - } - else - { -// for ( pUnit = pListOld0; pUnit; pUnit = pUnit->Next ) -// pUnit->lev = lev1; - for ( pUnit = pListOld1; pUnit; pUnit = pUnit->Next ) - pUnit->lev = lev0; - } - - // set the new linked lists, which will be attached to the planes - pListNew0 = pListOld1; - pListNew1 = pListOld0; - - if ( p->fMinApl ) - { - AplWeightTotalLev0 = p->pPlanes[lev1].statsCost; - AplWeightTotalLev1 = p->pPlanes[lev0].statsCost; - } - - // set the changes in terms of nodes - nNodesUpMovedDown = p->pPlanes[lev0].statsNodes; - nNodesDownMovedUp = p->pPlanes[lev1].statsNodes; - goto finish; - } - p->Signature++; - - - // two-variable swap is done in three easy steps - // previously I thought that steps (1) and (2) can be merged into one step - // now it is clear that this cannot be done without changing a lot of other stuff... - - // (1) walk through the upper level, find units without cofactors in the lower level - // and move them to the new lower level (while adding to the cache) - // (2) walk through the uppoer level, and tranform all the remaning nodes - // while employing cache for the new lower level - // (3) walk through the old lower level, find those nodes whose ref counters are not zero, - // and move them to the new uppoer level, free other nodes - - // (1) walk through the upper level, find units without cofactors in the lower level - // and move them to the new lower level (while adding to the cache) - for ( pLoop = pListOld0; pLoop; ) - { - pUnit = pLoop; - pLoop = pLoop->Next; - - pUnitE = pUnit->pE; - pUnitER = Unit_Regular(pUnitE); - pUnitT = pUnit->pT; - - if ( pUnitER->lev != lev1 && pUnitT->lev != lev1 ) - { - // before after - // - // - // 0 / \ 1 - // / \ - // / \ - // / \ - // / \ 0 / \ 1 - // / \ / \ - // / \ / \ - // F0 F1 F0 F1 - - // move to plane-2-new - // nothing changes in the process (cofactors, ref counter, APL weight) - pUnit->lev = lev1; - AddToLinkedList( ppListNew1, pUnit ); - if ( p->fMinApl ) - AplWeightTotalLev1 += pUnit->Weight; - - // add to cache - find the cell with different signature (not the current one!) - for ( HKey = hashKey3(p->Signature, pUnitE, pUnitT, p->nTableSize); - p->HTable[HKey].Sign == p->Signature; - HKey = (HKey+1) % p->nTableSize ); - assert( p->HTable[HKey].Sign != p->Signature ); - p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = pUnitE; - p->HTable[HKey].Arg2 = pUnitT; - p->HTable[HKey].Arg3 = pUnit; - - nNodesUpMovedDown++; - - if ( p->fMinWidth ) - { - // update the cofactors's top ref - if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - assert( pUnitER->TopRef == lev1 ); - pUnitER->TopRefNew = lev2; - if ( pUnitER->Sign != p->nSwaps ) - { - pUnitER->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pUnitER; - } - } - if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - assert( pUnitT->TopRef == lev1 ); - pUnitT->TopRefNew = lev2; - if ( pUnitT->Sign != p->nSwaps ) - { - pUnitT->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pUnitT; - } - } - } - } - else - { - // add to the temporary plane - AddToLinkedList( ppListTemp, pUnit ); - } - } - - - // (2) walk through the uppoer level, and tranform all the remaning nodes - // while employing cache for the new lower level - for ( pLoop = pListTemp; pLoop; ) - { - pUnit = pLoop; - pLoop = pLoop->Next; - - pUnitE = pUnit->pE; - pUnitER = Unit_Regular(pUnitE); - pUnitT = pUnit->pT; - fComp = (int)(pUnitER != pUnitE); - - // count the amount of weight to reduce the APL of the children of this node - if ( p->fMinApl ) - AplWeightHalf = 0.5 * pUnit->Weight; - - // determine what situation is this - if ( pUnitER->lev == lev1 && pUnitT->lev == lev1 ) - { - if ( fComp == 0 ) - { - // before after - // - // - // 0 / \ 1 0 / \ 1 - // / \ / \ - // / \ / \ - // - // 0 / \ 1 0 / \ 1 0 / \ 1 0 / \ 1 - // / \ / \ / \ / \ - // / \ / \ / \ / \ - // F0 F1 F2 F3 F0 F2 F1 F3 - // pNew1E pNew1T pNew2E pNew2T - // - pNew1E = pUnitE->pE; // F0 - pNew1T = pUnitT->pE; // F2 - - pNew2E = pUnitE->pT; // F1 - pNew2T = pUnitT->pT; // F3 - } - else - { - // before after - // - // - // 0 . \ 1 0 / \ 1 - // . \ / \ - // . \ / \ - // - // 0 / \ 1 0 / \ 1 0 . \ 1 0 . \ 1 - // / \ / \ . \ . \ - // / \ / \ . \ . \ - // F0 F1 F2 F3 F0 F2 F1 F3 - // pNew1E pNew1T pNew2E pNew2T - // - pNew1E = Unit_Not(pUnitER->pE); // F0 - pNew1T = pUnitT->pE; // F2 - - pNew2E = Unit_Not(pUnitER->pT); // F1 - pNew2T = pUnitT->pT; // F3 - } - // subtract ref counters - on the level P2 - pUnitER->n--; - pUnitT->n--; - - // mark the change in the APL weights - if ( p->fMinApl ) - { - pUnitER->Weight -= AplWeightHalf; - pUnitT->Weight -= AplWeightHalf; - AplWeightAfter -= pUnit->Weight; - } - } - else if ( pUnitER->lev == lev1 ) - { - if ( fComp == 0 ) - { - // before after - // - // - // 0 / \ 1 0 / \ 1 - // / \ / \ - // / \ / \ - // \ - // 0 / \ 1 \ 0 / \ 1 0 / \ 1 - // / \ \ / \ / \ - // / \ \ / \ / \ - // F0 F1 F3 F0 F3 F1 F3 - // pNew1E pNew1T pNew2E pNew2T - // - pNew1E = pUnitER->pE; // F0 - pNew1T = pUnitT; // F3 - - pNew2E = pUnitER->pT; // F1 - pNew2T = pUnitT; // F3 - } - else - { - // before after - // - // - // 0 . \ 1 0 / \ 1 - // . \ / \ - // . \ / \ - // \ - // 0 / \ 1 \ 0 . \ 1 0 . \ 1 - // / \ \ . \ . \ - // / \ \ . \ . \ - // F0 F1 F3 F0 F3 F1 F3 - // pNew1E pNew1T pNew2E pNew2T - // - pNew1E = Unit_Not(pUnitER->pE); // F0 - pNew1T = pUnitT; // F3 - - pNew2E = Unit_Not(pUnitER->pT); // F1 - pNew2T = pUnitT; // F3 - } - // subtract ref counter - on the level P2 - pUnitER->n--; - // subtract ref counter - on other levels - pUnitT->n--; /// - - // mark the change in the APL weights - if ( p->fMinApl ) - { - pUnitER->Weight -= AplWeightHalf; - AplWeightAfter -= AplWeightHalf; - } - } - else if ( pUnitT->lev == lev1 ) - { - // before after - // - // - // 0 / \ 1 0 / \ 1 - // / \ / \ - // / \ / \ - // / - // / 0 / \ 1 0 / \ 1 0 / \ 1 - // / / \ / \ / \ - // / / \ / \ / \ - // F0 F2 F3 F0 F2 F0 F3 - // pNew1E pNew1T pNew2E pNew2T - // - pNew1E = pUnitE; // F0 - pNew1T = pUnitT->pE; // F2 - - pNew2E = pUnitE; // F0 - pNew2T = pUnitT->pT; // F3 - - // subtract incoming edge counter - on the level P2 - pUnitT->n--; - // subtract ref counter - on other levels - pUnitER->n--; /// - - // mark the change in the APL weights - if ( p->fMinApl ) - { - pUnitT->Weight -= AplWeightHalf; - AplWeightAfter -= AplWeightHalf; - } - } - else - { - assert( 0 ); // should never happen - } - - - // consider all the cases except the last one - if ( pNew1E == pNew1T ) - { - pNewPlane20 = pNew1T; - - if ( p->fMinWidth ) - { - // update the cofactors's top ref - if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - pNew1T->TopRefNew = lev1; - if ( pNew1T->Sign != p->nSwaps ) - { - pNew1T->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew1T; - } - } - } - } - else - { - // pNew1T can be complemented - fCompT = Cudd_IsComplement(pNew1T); - if ( fCompT ) - { - pNew1E = Unit_Not(pNew1E); - pNew1T = Unit_Not(pNew1T); - } - - // check the hash-table - fFound = 0; - for ( HKey = hashKey3(p->Signature, pNew1E, pNew1T, p->nTableSize); - p->HTable[HKey].Sign == p->Signature; - HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == pNew1E && p->HTable[HKey].Arg2 == pNew1T ) - { // the entry is present - // assign this entry - pNewPlane20 = p->HTable[HKey].Arg3; - assert( pNewPlane20->lev == lev1 ); - fFound = 1; - p->HashSuccess++; - break; - } - - if ( !fFound ) - { // create the new entry - pNewPlane20 = reoUnitsGetNextUnit( p ); // increments the unit counter - pNewPlane20->pE = pNew1E; - pNewPlane20->pT = pNew1T; - pNewPlane20->n = 0; // ref will be added later - pNewPlane20->lev = lev1; - if ( p->fMinWidth ) - { - pNewPlane20->TopRef = lev1; - pNewPlane20->Sign = 0; - } - // set the weight of this node - if ( p->fMinApl ) - pNewPlane20->Weight = 0.0; - - // increment ref counters of children - pNew1ER = Unit_Regular(pNew1E); - pNew1ER->n++; // - pNew1T->n++; // - - // insert into the data structure - AddToLinkedList( ppListNew1, pNewPlane20 ); - - // add this entry to cache - assert( p->HTable[HKey].Sign != p->Signature ); - p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = pNew1E; - p->HTable[HKey].Arg2 = pNew1T; - p->HTable[HKey].Arg3 = pNewPlane20; - - nNodesUnrefAdded++; - - if ( p->fMinWidth ) - { - // update the cofactors's top ref - if ( pNew1ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - if ( pNew1ER->Sign != p->nSwaps ) - { - pNew1ER->TopRefNew = lev2; - if ( pNew1ER->Sign != p->nSwaps ) - { - pNew1ER->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew1ER; - } - } - // otherwise the level is already set correctly - else - { - assert( pNew1ER->TopRefNew == lev1 || pNew1ER->TopRefNew == lev2 ); - } - } - // update the cofactors's top ref - if ( pNew1T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - if ( pNew1T->Sign != p->nSwaps ) - { - pNew1T->TopRefNew = lev2; - if ( pNew1T->Sign != p->nSwaps ) - { - pNew1T->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew1T; - } - } - // otherwise the level is already set correctly - else - { - assert( pNew1T->TopRefNew == lev1 || pNew1T->TopRefNew == lev2 ); - } - } - } - } - - if ( p->fMinApl ) - { - // increment the weight of this node - pNewPlane20->Weight += AplWeightHalf; - // mark the change in the APL weight - AplWeightAfter += AplWeightHalf; - // update the total weight of this level - AplWeightTotalLev1 += AplWeightHalf; - } - - if ( fCompT ) - pNewPlane20 = Unit_Not(pNewPlane20); - } - - if ( pNew2E == pNew2T ) - { - pNewPlane21 = pNew2T; - - if ( p->fMinWidth ) - { - // update the cofactors's top ref - if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - pNew2T->TopRefNew = lev1; - if ( pNew2T->Sign != p->nSwaps ) - { - pNew2T->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew2T; - } - } - } - } - else - { - assert( !Cudd_IsComplement(pNew2T) ); - - // check the hash-table - fFound = 0; - for ( HKey = hashKey3(p->Signature, pNew2E, pNew2T, p->nTableSize); - p->HTable[HKey].Sign == p->Signature; - HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == pNew2E && p->HTable[HKey].Arg2 == pNew2T ) - { // the entry is present - // assign this entry - pNewPlane21 = p->HTable[HKey].Arg3; - assert( pNewPlane21->lev == lev1 ); - fFound = 1; - p->HashSuccess++; - break; - } - - if ( !fFound ) - { // create the new entry - pNewPlane21 = reoUnitsGetNextUnit( p ); // increments the unit counter - pNewPlane21->pE = pNew2E; - pNewPlane21->pT = pNew2T; - pNewPlane21->n = 0; // ref will be added later - pNewPlane21->lev = lev1; - if ( p->fMinWidth ) - { - pNewPlane21->TopRef = lev1; - pNewPlane21->Sign = 0; - } - // set the weight of this node - if ( p->fMinApl ) - pNewPlane21->Weight = 0.0; - - // increment ref counters of children - pNew2ER = Unit_Regular(pNew2E); - pNew2ER->n++; // - pNew2T->n++; // - - // insert into the data structure -// reoUnitsAddUnitToPlane( &P2new, pNewPlane21 ); - AddToLinkedList( ppListNew1, pNewPlane21 ); - - // add this entry to cache - assert( p->HTable[HKey].Sign != p->Signature ); - p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = pNew2E; - p->HTable[HKey].Arg2 = pNew2T; - p->HTable[HKey].Arg3 = pNewPlane21; - - nNodesUnrefAdded++; - - - if ( p->fMinWidth ) - { - // update the cofactors's top ref - if ( pNew2ER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - if ( pNew2ER->Sign != p->nSwaps ) - { - pNew2ER->TopRefNew = lev2; - if ( pNew2ER->Sign != p->nSwaps ) - { - pNew2ER->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew2ER; - } - } - // otherwise the level is already set correctly - else - { - assert( pNew2ER->TopRefNew == lev1 || pNew2ER->TopRefNew == lev2 ); - } - } - // update the cofactors's top ref - if ( pNew2T->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - if ( pNew2T->Sign != p->nSwaps ) - { - pNew2T->TopRefNew = lev2; - if ( pNew2T->Sign != p->nSwaps ) - { - pNew2T->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pNew2T; - } - } - // otherwise the level is already set correctly - else - { - assert( pNew2T->TopRefNew == lev1 || pNew2T->TopRefNew == lev2 ); - } - } - } - } - - if ( p->fMinApl ) - { - // increment the weight of this node - pNewPlane21->Weight += AplWeightHalf; - // mark the change in the APL weight - AplWeightAfter += AplWeightHalf; - // update the total weight of this level - AplWeightTotalLev1 += AplWeightHalf; - } - } - // in all cases, the node will be added to the plane-1 - // this should be the same node (pUnit) as was originally there - // because it is referenced by the above nodes - - assert( !Cudd_IsComplement(pNewPlane21) ); - // should be the case; otherwise reordering is not a local operation - - pUnit->pE = pNewPlane20; - pUnit->pT = pNewPlane21; - assert( pUnit->lev == lev0 ); - // reference counter remains the same; the APL weight remains the same - - // increment ref counters of children - pNewPlane20R = Unit_Regular(pNewPlane20); - pNewPlane20R->n++; /// - pNewPlane21->n++; /// - - // insert into the data structure - AddToLinkedList( ppListNew0, pUnit ); - if ( p->fMinApl ) - AplWeightTotalLev0 += pUnit->Weight; - } - - // (3) walk through the old lower level, find those nodes whose ref counters are not zero, - // and move them to the new uppoer level, free other nodes - for ( pLoop = pListOld1; pLoop; ) - { - pUnit = pLoop; - pLoop = pLoop->Next; - if ( pUnit->n ) - { - assert( !p->fMinApl || pUnit->Weight > 0.0 ); - // the node should be added to the new level - // no need to check the hash table - pUnit->lev = lev0; - AddToLinkedList( ppListNew0, pUnit ); - if ( p->fMinApl ) - AplWeightTotalLev0 += pUnit->Weight; - - nNodesDownMovedUp++; - - if ( p->fMinWidth ) - { - pUnitER = Unit_Regular(pUnit->pE); - pUnitT = pUnit->pT; - - // update the cofactors's top ref - if ( pUnitER->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - pUnitER->TopRefNew = lev1; - if ( pUnitER->Sign != p->nSwaps ) - { - pUnitER->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pUnitER; - } - } - if ( pUnitT->TopRef > lev0 ) // the cofactor's top ref level is one of the current two levels - { - pUnitT->TopRefNew = lev1; - if ( pUnitT->Sign != p->nSwaps ) - { - pUnitT->Sign = p->nSwaps; // set the current signature - p->pWidthCofs[ nWidthCofs++ ] = pUnitT; - } - } - } - } - else - { - assert( !p->fMinApl || pUnit->Weight == 0.0 ); - // decrement reference counters of children - pUnitER = Unit_Regular(pUnit->pE); - pUnitT = pUnit->pT; - pUnitER->n--; /// - pUnitT->n--; /// - // the node should be thrown away - reoUnitsRecycleUnit( p, pUnit ); - nNodesUnrefRemoved++; - } - } - -finish: - - // attach the new levels to the planes - p->pPlanes[lev0].pHead = pListNew0; - p->pPlanes[lev1].pHead = pListNew1; - - // swap the sift status - temp = p->pPlanes[lev0].fSifted; - p->pPlanes[lev0].fSifted = p->pPlanes[lev1].fSifted; - p->pPlanes[lev1].fSifted = temp; - - // swap variables in the variable map - if ( p->pOrderInt ) - { - temp = p->pOrderInt[lev0]; - p->pOrderInt[lev0] = p->pOrderInt[lev1]; - p->pOrderInt[lev1] = temp; - } - - // adjust the node profile - p->pPlanes[lev0].statsNodes -= (nNodesUpMovedDown - nNodesDownMovedUp); - p->pPlanes[lev1].statsNodes -= (nNodesDownMovedUp - nNodesUpMovedDown) + nNodesUnrefRemoved - nNodesUnrefAdded; - p->nNodesCur -= nNodesUnrefRemoved - nNodesUnrefAdded; - - // adjust the node profile on this level - if ( p->fMinWidth ) - { - for ( c = 0; c < nWidthCofs; c++ ) - { - if ( p->pWidthCofs[c]->TopRefNew < p->pWidthCofs[c]->TopRef ) - { - p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew; - nWidthReduction--; - } - else if ( p->pWidthCofs[c]->TopRefNew > p->pWidthCofs[c]->TopRef ) - { - p->pWidthCofs[c]->TopRef = p->pWidthCofs[c]->TopRefNew; - nWidthReduction++; - } - } - // verify that the profile is okay - reoProfileWidthVerifyLevel( p->pPlanes + lev0, lev0 ); - reoProfileWidthVerifyLevel( p->pPlanes + lev1, lev1 ); - - // compute the total gain in terms of width - nCostGain = (nNodesDownMovedUp - nNodesUpMovedDown + nNodesUnrefRemoved - nNodesUnrefAdded) + nWidthReduction; - // adjust the width on this level - p->pPlanes[lev1].statsWidth -= (int)nCostGain; - // set the cost - p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsWidth; - } - else if ( p->fMinApl ) - { - // compute the total gain in terms of APL - nCostGain = AplWeightPrev - AplWeightAfter; - // make sure that the ALP is updated correctly -// assert( p->pPlanes[lev0].statsCost + p->pPlanes[lev1].statsCost - nCostGain == -// AplWeightTotalLev0 + AplWeightTotalLev1 ); - // adjust the profile - p->pPlanes[lev0].statsApl = AplWeightTotalLev0; - p->pPlanes[lev1].statsApl = AplWeightTotalLev1; - // set the cost - p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsApl; - p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsApl; - } - else - { - // compute the total gain in terms of the number of nodes - nCostGain = nNodesUnrefRemoved - nNodesUnrefAdded; - // adjust the profile (adjusted above) - // set the cost - p->pPlanes[lev0].statsCost = p->pPlanes[lev0].statsNodes; - p->pPlanes[lev1].statsCost = p->pPlanes[lev1].statsNodes; - } - - return nCostGain; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoTest.c b/src/bdd/reo/reoTest.c deleted file mode 100644 index 82f3d5f5..00000000 --- a/src/bdd/reo/reoTest.c +++ /dev/null @@ -1,251 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoTest.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Various testing procedures (may be outdated).] - - Author [Alan Mishchenko ] - - Affiliation [ECE Department. Portland State University, Portland, Oregon.] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoTest.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reorders the DD using REO and CUDD.] - - Description [This function can be used to test the performance of the reordering package.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderTest( DdManager * dd, DdNode * Func ) -{ - reo_man * pReo; - DdNode * Temp, * Temp1; - int pOrder[1000]; - - pReo = Extra_ReorderInit( 100, 100 ); - -//Extra_DumpDot( dd, &Func, 1, "beforReo.dot", 0 ); - Temp = Extra_Reorder( pReo, dd, Func, pOrder ); Cudd_Ref( Temp ); -//Extra_DumpDot( dd, &Temp, 1, "afterReo.dot", 0 ); - - Temp1 = Extra_ReorderCudd(dd, Func, NULL ); Cudd_Ref( Temp1 ); -printf( "Initial = %d. Final = %d. Cudd = %d.\n", Cudd_DagSize(Func), Cudd_DagSize(Temp), Cudd_DagSize(Temp1) ); - Cudd_RecursiveDeref( dd, Temp1 ); - Cudd_RecursiveDeref( dd, Temp ); - - Extra_ReorderQuit( pReo ); -} - - -/**Function************************************************************* - - Synopsis [Reorders the DD using REO and CUDD.] - - Description [This function can be used to test the performance of the reordering package.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ReorderTestArray( DdManager * dd, DdNode * Funcs[], int nFuncs ) -{ - reo_man * pReo; - DdNode * FuncsRes[1000]; - int pOrder[1000]; - int i; - - pReo = Extra_ReorderInit( 100, 100 ); - Extra_ReorderArray( pReo, dd, Funcs, FuncsRes, nFuncs, pOrder ); - Extra_ReorderQuit( pReo ); - -printf( "Initial = %d. Final = %d.\n", Cudd_SharingSize(Funcs,nFuncs), Cudd_SharingSize(FuncsRes,nFuncs) ); - - for ( i = 0; i < nFuncs; i++ ) - Cudd_RecursiveDeref( dd, FuncsRes[i] ); - -} - -/**Function************************************************************* - - Synopsis [Reorders the DD using CUDD package.] - - Description [Transfers the DD into a temporary manager in such a way - that the level correspondence is preserved. Reorders the manager - and transfers the DD back into the original manager using the topmost - levels of the manager, in such a way that the ordering of levels is - preserved. The resulting permutation is returned in the array - given by the user.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_ReorderCudd( DdManager * dd, DdNode * aFunc, int pPermuteReo[] ) -{ - static DdManager * ddReorder = NULL; - static int * Permute = NULL; - static int * PermuteReo1 = NULL; - static int * PermuteReo2 = NULL; - DdNode * aFuncReorder, * aFuncNew; - int lev, var; - - // start the reordering manager - if ( ddReorder == NULL ) - { - Permute = ALLOC( int, dd->size ); - PermuteReo1 = ALLOC( int, dd->size ); - PermuteReo2 = ALLOC( int, dd->size ); - ddReorder = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_AutodynDisable(ddReorder); - } - - // determine the permutation of variable to make sure that var order in bFunc - // will not change when this function is transfered into the new manager - for ( lev = 0; lev < dd->size; lev++ ) - { - Permute[ dd->invperm[lev] ] = ddReorder->invperm[lev]; - PermuteReo1[ ddReorder->invperm[lev] ] = dd->invperm[lev]; - } - // transfer this function into the new manager in such a way that ordering of vars does not change - aFuncReorder = Extra_TransferPermute( dd, ddReorder, aFunc, Permute ); Cudd_Ref( aFuncReorder ); -// assert( Cudd_DagSize(aFunc) == Cudd_DagSize(aFuncReorder) ); - - // perform the reordering -printf( "Nodes before = %d.\n", Cudd_DagSize(aFuncReorder) ); - Cudd_ReduceHeap( ddReorder, CUDD_REORDER_SYMM_SIFT, 1 ); -printf( "Nodes before = %d.\n", Cudd_DagSize(aFuncReorder) ); - - // determine the reverse variable permutation - for ( lev = 0; lev < dd->size; lev++ ) - { - Permute[ ddReorder->invperm[lev] ] = dd->invperm[lev]; - PermuteReo2[ dd->invperm[lev] ] = ddReorder->invperm[lev]; - } - - // transfer this function into the new manager in such a way that ordering of vars does not change - aFuncNew = Extra_TransferPermute( ddReorder, dd, aFuncReorder, Permute ); Cudd_Ref( aFuncNew ); -// assert( Cudd_DagSize(aFuncNew) == Cudd_DagSize(aFuncReorder) ); - Cudd_RecursiveDeref( ddReorder, aFuncReorder ); - - // derive the resulting variable ordering - if ( pPermuteReo ) - for ( var = 0; var < dd->size; var++ ) - pPermuteReo[var] = PermuteReo1[ PermuteReo2[var] ]; - - Cudd_Deref( aFuncNew ); - return aFuncNew; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [Transfers the BDD into another manager minimizes it and - returns the min number of nodes; disposes of the BDD in the new manager. - Useful for debugging or comparing the performance of other reordering - procedures.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_bddReorderTest( DdManager * dd, DdNode * bF ) -{ - static DdManager * s_ddmin; - DdNode * bFmin; - int nNodes; -// int clk1; - - if ( s_ddmin == NULL ) - s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); - -// Cudd_ShuffleHeap( s_ddmin, dd->invperm ); - -// clk1 = clock(); - bFmin = Cudd_bddTransfer( dd, s_ddmin, bF ); Cudd_Ref( bFmin ); - Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SIFT,1); -// Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); - nNodes = Cudd_DagSize( bFmin ); - Cudd_RecursiveDeref( s_ddmin, bFmin ); - -// printf( "Classical variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - return nNodes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Transfers the ADD into another manager minimizes it and - returns the min number of nodes; disposes of the BDD in the new manager. - Useful for debugging or comparing the performance of other reordering - procedures.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_addReorderTest( DdManager * dd, DdNode * aF ) -{ - static DdManager * s_ddmin; - DdNode * bF; - DdNode * bFmin; - DdNode * aFmin; - int nNodesBeg; - int nNodesEnd; - int clk1; - - if ( s_ddmin == NULL ) - s_ddmin = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0); - -// Cudd_ShuffleHeap( s_ddmin, dd->invperm ); - - clk1 = clock(); - bF = Cudd_addBddPattern( dd, aF ); Cudd_Ref( bF ); - bFmin = Cudd_bddTransfer( dd, s_ddmin, bF ); Cudd_Ref( bFmin ); - Cudd_RecursiveDeref( dd, bF ); - aFmin = Cudd_BddToAdd( s_ddmin, bFmin ); Cudd_Ref( aFmin ); - Cudd_RecursiveDeref( s_ddmin, bFmin ); - - nNodesBeg = Cudd_DagSize( aFmin ); - Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SIFT,1); -// Cudd_ReduceHeap(s_ddmin,CUDD_REORDER_SYMM_SIFT,1); - nNodesEnd = Cudd_DagSize( aFmin ); - Cudd_RecursiveDeref( s_ddmin, aFmin ); - - printf( "Classical reordering of ADDs: Before = %d. After = %d.\n", nNodesBeg, nNodesEnd ); - printf( "Classical variable reordering time = %.2f sec\n", (float)(clock() - clk1)/(float)(CLOCKS_PER_SEC) ); - return nNodesEnd; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoTransfer.c b/src/bdd/reo/reoTransfer.c deleted file mode 100644 index 65d31d01..00000000 --- a/src/bdd/reo/reoTransfer.c +++ /dev/null @@ -1,199 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoTransfer.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Transfering a DD from the CUDD manager into REO"s internal data structures and back.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoTransfer.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transfers the DD into the internal reordering data structure.] - - Description [It is important that the hash table is lossless.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -reo_unit * reoTransferNodesToUnits_rec( reo_man * p, DdNode * F ) -{ - DdManager * dd = p->dd; - reo_unit * pUnit; - int HKey, fComp; - - fComp = Cudd_IsComplement(F); - F = Cudd_Regular(F); - - // check the hash-table - if ( F->ref != 1 ) - { - // search cache - use linear probing - for ( HKey = hashKey2(p->Signature,F,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == (reo_unit *)F ) - { - pUnit = p->HTable[HKey].Arg2; - assert( pUnit ); - // increment the edge counter - pUnit->n++; - return Unit_NotCond( pUnit, fComp ); - } - } - // the entry in not found in the cache - - // create a new entry - pUnit = reoUnitsGetNextUnit( p ); - pUnit->n = 1; - if ( cuddIsConstant(F) ) - { - pUnit->lev = REO_CONST_LEVEL; - pUnit->pE = (reo_unit*)((int)(cuddV(F))); - pUnit->pT = NULL; - // check if the diagram that is being reordering has complement edges - if ( F != dd->one ) - p->fThisIsAdd = 1; - // insert the unit into the corresponding plane - reoUnitsAddUnitToPlane( &(p->pPlanes[p->nSupp]), pUnit ); // increments the unit counter - } - else - { - pUnit->lev = p->pMapToPlanes[F->index]; - pUnit->pE = reoTransferNodesToUnits_rec( p, cuddE(F) ); - pUnit->pT = reoTransferNodesToUnits_rec( p, cuddT(F) ); - // insert the unit into the corresponding plane - reoUnitsAddUnitToPlane( &(p->pPlanes[pUnit->lev]), pUnit ); // increments the unit counter - } - - // add to the hash table - if ( F->ref != 1 ) - { - // the next free entry is already found - it is pointed to by HKey - // while we traversed the diagram, the hash entry to which HKey points, - // might have been used. Make sure that its signature is different. - for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); - p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = (reo_unit *)F; - p->HTable[HKey].Arg2 = pUnit; - } - - // increment the counter of nodes - p->nNodesCur++; - return Unit_NotCond( pUnit, fComp ); -} - -/**Function************************************************************* - - Synopsis [Creates the DD from the internal reordering data structure.] - - Description [It is important that the hash table is lossless.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit ) -{ - DdManager * dd = p->dd; - DdNode * bRes, * E, * T; - int HKey, fComp; - - fComp = Cudd_IsComplement(pUnit); - pUnit = Unit_Regular(pUnit); - - // check the hash-table - if ( pUnit->n != 1 ) - { - for ( HKey = hashKey2(p->Signature,pUnit,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ) - if ( p->HTable[HKey].Arg1 == pUnit ) - { - bRes = (DdNode*) p->HTable[HKey].Arg2; - assert( bRes ); - return Cudd_NotCond( bRes, fComp ); - } - } - - // treat the case of constants - if ( Unit_IsConstant(pUnit) ) - { - bRes = cuddUniqueConst( dd, ((double)((int)(pUnit->pE))) ); - cuddRef( bRes ); - } - else - { - // split and recur on children of this node - E = reoTransferUnitsToNodes_rec( p, pUnit->pE ); - if ( E == NULL ) - return NULL; - cuddRef(E); - - T = reoTransferUnitsToNodes_rec( p, pUnit->pT ); - if ( T == NULL ) - { - Cudd_RecursiveDeref(dd, E); - return NULL; - } - cuddRef(T); - - // consider the case when Res0 and Res1 are the same node - assert( E != T ); - assert( !Cudd_IsComplement(T) ); - - bRes = cuddUniqueInter( dd, p->pMapToDdVarsFinal[pUnit->lev], T, E ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,E); - Cudd_RecursiveDeref(dd,T); - return NULL; - } - cuddRef( bRes ); - cuddDeref( E ); - cuddDeref( T ); - } - - // do not keep the result if the ref count is only 1, since it will not be visited again - if ( pUnit->n != 1 ) - { - // while we traversed the diagram, the hash entry to which HKey points, - // might have been used. Make sure that its signature is different. - for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize ); - p->HTable[HKey].Sign = p->Signature; - p->HTable[HKey].Arg1 = pUnit; - p->HTable[HKey].Arg2 = (reo_unit *)bRes; - - // add the DD to the referenced DD list in order to be able to store it in cache - p->pRefNodes[p->nRefNodes++] = bRes; Cudd_Ref( bRes ); - // no need to do this, because the garbage collection will not take bRes away - // it is held by the diagram in the making - } - // increment the counter of nodes - p->nNodesCur++; - cuddDeref( bRes ); - return Cudd_NotCond( bRes, fComp ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/bdd/reo/reoUnits.c b/src/bdd/reo/reoUnits.c deleted file mode 100644 index aa86516e..00000000 --- a/src/bdd/reo/reoUnits.c +++ /dev/null @@ -1,184 +0,0 @@ -/**CFile**************************************************************** - - FileName [reoUnits.c] - - PackageName [REO: A specialized DD reordering engine.] - - Synopsis [Procedures which support internal data structures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - October 15, 2002.] - - Revision [$Id: reoUnits.c,v 1.0 2002/15/10 03:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "reo.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void reoUnitsAddToFreeUnitList( reo_man * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Extract the next unit from the free unit list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -reo_unit * reoUnitsGetNextUnit(reo_man * p ) -{ - reo_unit * pUnit; - // check there are stil units to extract - if ( p->pUnitFreeList == NULL ) - reoUnitsAddToFreeUnitList( p ); - // extract the next unit from the linked list - pUnit = p->pUnitFreeList; - p->pUnitFreeList = pUnit->Next; - p->nUnitsUsed++; - return pUnit; -} - -/**Function************************************************************* - - Synopsis [Returns the unit to the free unit list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoUnitsRecycleUnit( reo_man * p, reo_unit * pUnit ) -{ - pUnit->Next = p->pUnitFreeList; - p->pUnitFreeList = pUnit; - p->nUnitsUsed--; -} - -/**Function************************************************************* - - Synopsis [Returns the list of units to the free unit list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoUnitsRecycleUnitList( reo_man * p, reo_plane * pPlane ) -{ - reo_unit * pUnit; - reo_unit * pTail; - - if ( pPlane->pHead == NULL ) - return; - - // find the tail - for ( pUnit = pPlane->pHead; pUnit; pUnit = pUnit->Next ) - pTail = pUnit; - pTail->Next = p->pUnitFreeList; - p->pUnitFreeList = pPlane->pHead; - memset( pPlane, 0, sizeof(reo_plane) ); -} - -/**Function************************************************************* - - Synopsis [Stops the unit dispenser.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoUnitsStopDispenser( reo_man * p ) -{ - int i; - for ( i = 0; i < p->nMemChunks; i++ ) - free( p->pMemChunks[i] ); -// printf("\nThe number of chunks used is %d, each of them %d units\n", p->nMemChunks, REO_CHUNK_SIZE ); - p->nMemChunks = 0; -} - -/**Function************************************************************* - - Synopsis [Adds one unit to the list of units which constitutes the plane.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoUnitsAddUnitToPlane( reo_plane * pPlane, reo_unit * pUnit ) -{ - if ( pPlane->pHead == NULL ) - { - pPlane->pHead = pUnit; - pUnit->Next = NULL; - } - else - { - pUnit->Next = pPlane->pHead; - pPlane->pHead = pUnit; - } - pPlane->statsNodes++; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void reoUnitsAddToFreeUnitList( reo_man * p ) -{ - int c; - // check that we still have chunks left - if ( p->nMemChunks == p->nMemChunksAlloc ) - { - printf( "reoUnitsAddToFreeUnitList(): Memory manager ran out of memory!\n" ); - fflush( stdout ); - return; - } - // allocate the next chunk - assert( p->pUnitFreeList == NULL ); - p->pUnitFreeList = ALLOC( reo_unit, REO_CHUNK_SIZE ); - // split chunks into list-connected units - for ( c = 0; c < REO_CHUNK_SIZE-1; c++ ) - (p->pUnitFreeList + c)->Next = p->pUnitFreeList + c + 1; - // set the last pointer to NULL - (p->pUnitFreeList + REO_CHUNK_SIZE-1)->Next = NULL; - // add the chunk to the array of chunks - p->pMemChunks[p->nMemChunks++] = p->pUnitFreeList; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/generic.c b/src/generic.c deleted file mode 100644 index f94c50e6..00000000 --- a/src/generic.c +++ /dev/null @@ -1,47 +0,0 @@ -/**CFile**************************************************************** - - FileName [.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: .c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "__Int.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/generic.h b/src/generic.h deleted file mode 100644 index e17d2edf..00000000 --- a/src/generic.h +++ /dev/null @@ -1,59 +0,0 @@ -/**CFile**************************************************************** - - FileName [.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: .h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __zzz_H__ -#define __zzz_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== zzz.c ==========================================================*/ - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/fpga/fpga.c b/src/map/fpga/fpga.c deleted file mode 100644 index 40423f4f..00000000 --- a/src/map/fpga/fpga.c +++ /dev/null @@ -1,283 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpga.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Command file for the FPGA package.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpga.c,v 1.4 2004/10/28 17:36:07 alanmi Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" -#include "main.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); -static int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); - -// the library file format should be as follows: -/* -# The area/delay of k-variable LUTs: -# k area delay -1 1 1 -2 2 2 -3 4 3 -4 8 4 -5 16 5 -6 32 6 -*/ - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Package initialization procedure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_Init( Abc_Frame_t * pAbc ) -{ - // set the default library - //Fpga_LutLib_t s_LutLib = { "lutlib", 6, 0, {0,1,2,4,8,16,32}, {{0},{1},{2},{3},{4},{5},{6}} }; -// Fpga_LutLib_t s_LutLib = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} }; - Fpga_LutLib_t s_LutLib = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} }; - //Fpga_LutLib_t s_LutLib = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} }; - - Abc_FrameSetLibLut( Fpga_LutLibDup(&s_LutLib) ); - - Cmd_CommandAdd( pAbc, "FPGA mapping", "read_lut", Fpga_CommandReadLibrary, 0 ); - Cmd_CommandAdd( pAbc, "FPGA mapping", "print_lut", Fpga_CommandPrintLibrary, 0 ); -} - -/**Function************************************************************* - - Synopsis [Package ending procedure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_End() -{ - Fpga_LutLibFree( Abc_FrameReadLibLut() ); -} - - -/**Function************************************************************* - - Synopsis [Command procedure to read LUT libraries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - FILE * pFile; - FILE * pOut, * pErr; - Fpga_LutLib_t * pLib; - Abc_Ntk_t * pNet; - char * FileName; - int fVerbose; - int c; - - pNet = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set the defaults - fVerbose = 1; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) - { - switch (c) - { - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - - if ( argc != globalUtilOptind + 1 ) - { - goto usage; - } - - // get the input file name - FileName = argv[globalUtilOptind]; - if ( (pFile = fopen( FileName, "r" )) == NULL ) - { - fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); - if ( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) ) - fprintf( pErr, "Did you mean \"%s\"?", FileName ); - fprintf( pErr, "\n" ); - return 1; - } - fclose( pFile ); - - // set the new network - pLib = Fpga_LutLibCreate( FileName, fVerbose ); - if ( pLib == NULL ) - { - fprintf( pErr, "Reading LUT library has failed.\n" ); - goto usage; - } - // replace the current library - Fpga_LutLibFree( Abc_FrameReadLibLut() ); - Abc_FrameSetLibLut( pLib ); - return 0; - -usage: - fprintf( pErr, "\nusage: read_lut [-vh]\n"); - fprintf( pErr, "\t read the LUT library from the file\n" ); - fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); - fprintf( pErr, "\t-h : print the command usage\n"); - fprintf( pErr, "\t \n"); - fprintf( pErr, "\t File format for a LUT library:\n"); - fprintf( pErr, "\t (the default library is shown)\n"); - fprintf( pErr, "\t \n"); - fprintf( pErr, "\t # The area/delay of k-variable LUTs:\n"); - fprintf( pErr, "\t # k area delay\n"); - fprintf( pErr, "\t 1 1 1\n"); - fprintf( pErr, "\t 2 2 2\n"); - fprintf( pErr, "\t 3 4 3\n"); - fprintf( pErr, "\t 4 8 4\n"); - fprintf( pErr, "\t 5 16 5\n"); - fprintf( pErr, "\t 6 32 6\n"); - return 1; /* error exit */ -} - -/**Function************************************************************* - - Synopsis [Command procedure to read LUT libraries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNet; - int fVerbose; - int c; - - pNet = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set the defaults - fVerbose = 1; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) - { - switch (c) - { - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - - if ( argc != globalUtilOptind ) - { - goto usage; - } - - // set the new network - Fpga_LutLibPrint( Abc_FrameReadLibLut() ); - return 0; - -usage: - fprintf( pErr, "\nusage: read_print [-vh]\n"); - fprintf( pErr, "\t print the current LUT library\n" ); - fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; /* error exit */ -} - -/**Function************************************************************* - - Synopsis [Sets simple LUT library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_SetSimpleLutLib( int nLutSize ) -{ - Fpga_LutLib_t s_LutLib10= { "lutlib",10, 0, {0,1,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1},{1}} }; - Fpga_LutLib_t s_LutLib9 = { "lutlib", 9, 0, {0,1,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1},{1}} }; - Fpga_LutLib_t s_LutLib8 = { "lutlib", 8, 0, {0,1,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1},{1}} }; - Fpga_LutLib_t s_LutLib7 = { "lutlib", 7, 0, {0,1,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1},{1}} }; - Fpga_LutLib_t s_LutLib6 = { "lutlib", 6, 0, {0,1,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1},{1}} }; - Fpga_LutLib_t s_LutLib5 = { "lutlib", 5, 0, {0,1,1,1,1,1}, {{0},{1},{1},{1},{1},{1}} }; - Fpga_LutLib_t s_LutLib4 = { "lutlib", 4, 0, {0,1,1,1,1}, {{0},{1},{1},{1},{1}} }; - Fpga_LutLib_t s_LutLib3 = { "lutlib", 3, 0, {0,1,1,1}, {{0},{1},{1},{1}} }; - Fpga_LutLib_t * pLutLib; - assert( nLutSize >= 3 && nLutSize <= 10 ); - switch ( nLutSize ) - { - case 3: pLutLib = &s_LutLib3; break; - case 4: pLutLib = &s_LutLib4; break; - case 5: pLutLib = &s_LutLib5; break; - case 6: pLutLib = &s_LutLib6; break; - case 7: pLutLib = &s_LutLib7; break; - case 8: pLutLib = &s_LutLib8; break; - case 9: pLutLib = &s_LutLib9; break; - case 10: pLutLib = &s_LutLib10; break; - default: pLutLib = NULL; break; - } - if ( pLutLib == NULL ) - return; - Fpga_LutLibFree( Abc_FrameReadLibLut() ); - Abc_FrameSetLibLut( Fpga_LutLibDup(pLutLib) ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/fpga/fpga.h b/src/map/fpga/fpga.h deleted file mode 100644 index 188420b1..00000000 --- a/src/map/fpga/fpga.h +++ /dev/null @@ -1,172 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpga.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Technology mapping for variable-size-LUT FPGAs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpga.h,v 1.7 2004/09/30 21:18:09 satrajit Exp $] - -***********************************************************************/ - -#ifndef __FPGA_H__ -#define __FPGA_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// the maximum size of LUTs used for mapping -#define FPGA_MAX_LUTSIZE 32 - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Fpga_ManStruct_t_ Fpga_Man_t; -typedef struct Fpga_NodeStruct_t_ Fpga_Node_t; -typedef struct Fpga_NodeVecStruct_t_ Fpga_NodeVec_t; -typedef struct Fpga_CutStruct_t_ Fpga_Cut_t; -typedef struct Fpga_LutLibStruct_t_ Fpga_LutLib_t; - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Fpga_IsComplement(p) (((int)((unsigned long) (p) & 01))) -#define Fpga_Regular(p) ((Fpga_Node_t *)((unsigned long)(p) & ~01)) -#define Fpga_Not(p) ((Fpga_Node_t *)((unsigned long)(p) ^ 01)) -#define Fpga_NotCond(p,c) ((Fpga_Node_t *)((unsigned long)(p) ^ (c))) - -#define Fpga_Ref(p) -#define Fpga_Deref(p) -#define Fpga_RecursiveDeref(p,c) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== fpgaCreate.c =============================================================*/ -extern Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose ); -extern Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); -extern void Fpga_ManFree( Fpga_Man_t * pMan ); -extern void Fpga_ManPrintTimeStats( Fpga_Man_t * p ); - -extern int Fpga_ManReadInputNum( Fpga_Man_t * p ); -extern int Fpga_ManReadOutputNum( Fpga_Man_t * p ); -extern Fpga_Node_t ** Fpga_ManReadInputs ( Fpga_Man_t * p ); -extern Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p ); -extern Fpga_Node_t * Fpga_ManReadConst1 ( Fpga_Man_t * p ); -extern float * Fpga_ManReadInputArrivals( Fpga_Man_t * p ); -extern int Fpga_ManReadVerbose( Fpga_Man_t * p ); -extern float * Fpga_ManReadLutAreas( Fpga_Man_t * p ); -extern void Fpga_ManSetTimeToMap( Fpga_Man_t * p, int Time ); -extern void Fpga_ManSetTimeToNet( Fpga_Man_t * p, int Time ); -extern void Fpga_ManSetTimeTotal( Fpga_Man_t * p, int Time ); -extern void Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames ); -extern void Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals ); -extern void Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery ); -extern void Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit ); -extern void Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit ); -extern void Fpga_ManSetTimeLimit( Fpga_Man_t * p, float TimeLimit ); -extern void Fpga_ManSetObeyFanoutLimits( Fpga_Man_t * p, int fObeyFanoutLimits ); -extern void Fpga_ManSetNumIterations( Fpga_Man_t * p, int nNumIterations ); -extern int Fpga_ManReadFanoutViolations( Fpga_Man_t * p ); -extern void Fpga_ManSetFanoutViolations( Fpga_Man_t * p, int nVio ); -extern void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ); -extern void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices ); -extern void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose ); -extern void Fpga_ManSetSwitching( Fpga_Man_t * p, int fSwitching ); -extern void Fpga_ManSetLatchPaths( Fpga_Man_t * p, int fLatchPaths ); -extern void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches ); -extern void Fpga_ManSetDelayTarget( Fpga_Man_t * p, float DelayTarget ); -extern void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName ); - -extern int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib ); - -extern char * Fpga_NodeReadData0( Fpga_Node_t * p ); -extern Fpga_Node_t * Fpga_NodeReadData1( Fpga_Node_t * p ); -extern int Fpga_NodeReadRefs( Fpga_Node_t * p ); -extern int Fpga_NodeReadNum( Fpga_Node_t * p ); -extern int Fpga_NodeReadLevel( Fpga_Node_t * p ); -extern Fpga_Cut_t * Fpga_NodeReadCuts( Fpga_Node_t * p ); -extern Fpga_Cut_t * Fpga_NodeReadCutBest( Fpga_Node_t * p ); -extern Fpga_Node_t * Fpga_NodeReadOne( Fpga_Node_t * p ); -extern Fpga_Node_t * Fpga_NodeReadTwo( Fpga_Node_t * p ); -extern void Fpga_NodeSetLevel( Fpga_Node_t * p, Fpga_Node_t * pNode ); -extern void Fpga_NodeSetData0( Fpga_Node_t * p, char * pData ); -extern void Fpga_NodeSetData1( Fpga_Node_t * p, Fpga_Node_t * pNode ); -extern void Fpga_NodeSetArrival( Fpga_Node_t * p, float Time ); -extern void Fpga_NodeSetNextE( Fpga_Node_t * p, Fpga_Node_t * pNextE ); -extern void Fpga_NodeSetRepr( Fpga_Node_t * p, Fpga_Node_t * pRepr ); -extern void Fpga_NodeSetSwitching( Fpga_Node_t * p, float Switching ); - -extern int Fpga_NodeIsConst( Fpga_Node_t * p ); -extern int Fpga_NodeIsVar( Fpga_Node_t * p ); -extern int Fpga_NodeIsAnd( Fpga_Node_t * p ); -extern int Fpga_NodeComparePhase( Fpga_Node_t * p1, Fpga_Node_t * p2 ); - -extern int Fpga_CutReadLeavesNum( Fpga_Cut_t * p ); -extern Fpga_Node_t ** Fpga_CutReadLeaves( Fpga_Cut_t * p ); - -extern Fpga_Node_t * Fpga_NodeAnd( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); -extern Fpga_Node_t * Fpga_NodeOr( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); -extern Fpga_Node_t * Fpga_NodeExor( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); -extern Fpga_Node_t * Fpga_NodeMux( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Node_t * pNodeT, Fpga_Node_t * pNodeE ); -extern void Fpga_NodeSetChoice( Fpga_Man_t * pMan, Fpga_Node_t * pNodeOld, Fpga_Node_t * pNodeNew ); - -extern void Fpga_ManStats( Fpga_Man_t * p ); - -/*=== fpgaCore.c =============================================================*/ -extern int Fpga_Mapping( Fpga_Man_t * p ); -/*=== fpgaCut.c ===============================================================*/ -extern void Fpga_MappingCreatePiCuts( Fpga_Man_t * p ); -extern void Fpga_CutsCleanSign( Fpga_Man_t * pMan ); -/*=== fpgaCutUtils.c =============================================================*/ -extern void Fpga_CutCreateFromNode( Fpga_Man_t * p, int iRoot, int * pLeaves, int nLeaves ); -extern void Fpga_MappingSetUsedCuts( Fpga_Man_t * p ); -/*=== fpgaLib.c =============================================================*/ -extern Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p ); -extern int Fpga_LutLibReadVarMax( Fpga_LutLib_t * p ); -extern float * Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p ); -extern float * Fpga_LutLibReadLutDelays( Fpga_LutLib_t * p ); -extern float Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size ); -extern float Fpga_LutLibReadLutDelay( Fpga_LutLib_t * p, int Size ); -/*=== fpgaTruth.c =============================================================*/ -extern void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut ); -extern int Fpga_CutVolume( Fpga_Cut_t * pCut ); -/*=== fpgaUtil.c =============================================================*/ -extern int Fpga_ManCheckConsistency( Fpga_Man_t * p ); -extern void Fpga_ManCleanData0( Fpga_Man_t * pMan ); -extern Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode ); -/*=== fpga.c =============================================================*/ -extern void Fpga_SetSimpleLutLib( int nLutSize ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/map/fpga/fpgaCore.c b/src/map/fpga/fpgaCore.c deleted file mode 100644 index 634a8eb1..00000000 --- a/src/map/fpga/fpgaCore.c +++ /dev/null @@ -1,188 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaCore.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Technology mapping for variable-size-LUT FPGAs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaCore.c,v 1.7 2004/10/01 23:41:04 satrajit Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Fpga_MappingPostProcess( Fpga_Man_t * p ); - -extern int s_MappingTime; -extern int s_MappingMem; - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs technology mapping for the given object graph.] - - Description [The object graph is stored in the mapping manager. - First, all the AND-nodes, which fanout into the POs, are collected - in the DFS fashion. Next, three steps are performed: the k-feasible - cuts are computed for each node, the truth tables are computed for - each cut, and the delay-optimal matches are assigned for each node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_Mapping( Fpga_Man_t * p ) -{ - int clk, clkTotal = clock(); - - // collect the nodes reachable from POs in the DFS order (including the choices) - p->vAnds = Fpga_MappingDfs( p, 1 ); - Fpga_ManReportChoices( p ); // recomputes levels - Fpga_MappingSetChoiceLevels( p ); - - // compute the cuts of nodes in the DFS order - clk = clock(); - Fpga_MappingCuts( p ); - p->timeCuts = clock() - clk; - - // match the truth tables to the supergates - clk = clock(); - if ( !Fpga_MappingMatches( p, 1 ) ) - return 0; - p->timeMatch = clock() - clk; - - // perform area recovery - clk = clock(); - if ( !Fpga_MappingPostProcess( p ) ) - return 0; - p->timeRecover = clock() - clk; -//PRT( "Total mapping time", clock() - clkTotal ); - - s_MappingTime = clock() - clkTotal; - s_MappingMem = Fpga_CutCountAll(p) * (sizeof(Fpga_Cut_t) - sizeof(int) * (FPGA_MAX_LEAVES - p->nVarsMax)); - - // print the AI-graph used for mapping - //Fpga_ManShow( p, "test" ); -// if ( p->fVerbose ) -// Fpga_MappingPrintOutputArrivals( p ); - if ( p->fVerbose ) - { - PRT( "Total time", clock() - clkTotal ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Postprocesses the mapped network for area recovery.] - - Description [This procedure assumes that the mapping is assigned. - It iterates the loop, in which the required times are computed and - the mapping is updated. It is conceptually similar to the paper: - V. Manohararajah, S. D. Brown, Z. G. Vranesic, Heuristics for area - minimization in LUT-based FPGA technology mapping. Proc. IWLS '04.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_MappingPostProcess( Fpga_Man_t * p ) -{ - int fShowSwitching = 0; - int fRecoverAreaFlow = 1; - int fRecoverArea = 1; - float aAreaTotalCur, aAreaTotalCur2; - int Iter, clk; - -//if ( p->fVerbose ) -// printf( "Best clock period = %5.2f\n", Fpga_TimeComputeArrivalMax(p) ); - - // compute area, set references, and collect nodes used in the mapping - Iter = 1; - aAreaTotalCur = Fpga_MappingSetRefsAndArea( p ); -if ( p->fVerbose ) -{ -printf( "Iteration %dD : Area = %8.1f ", Iter++, aAreaTotalCur ); -if ( fShowSwitching ) -printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) ); -else -printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) ); - -PRT( "Time", p->timeMatch ); -} - - if ( !p->fAreaRecovery ) - return 1; - - if ( fRecoverAreaFlow ) - { -clk = clock(); - // compute the required times and the fanouts - Fpga_TimeComputeRequiredGlobal( p, 1 ); - // remap topologically - Fpga_MappingMatches( p, 0 ); - // get the resulting area -// aAreaTotalCur = Fpga_MappingSetRefsAndArea( p ); - aAreaTotalCur = Fpga_MappingAreaTrav( p ); - // note that here we do not update the reference counter - // for some reason, this works better on benchmarks -if ( p->fVerbose ) -{ -printf( "Iteration %dF : Area = %8.1f ", Iter++, aAreaTotalCur ); -if ( fShowSwitching ) -printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) ); -else -printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) ); -PRT( "Time", clock() - clk ); -} - } - - // update reference counters - aAreaTotalCur2 = Fpga_MappingSetRefsAndArea( p ); - assert( aAreaTotalCur == aAreaTotalCur2 ); - - if ( fRecoverArea ) - { -clk = clock(); - // compute the required times and the fanouts - Fpga_TimeComputeRequiredGlobal( p, 0 ); - // remap topologically - if ( p->fSwitching ) - Fpga_MappingMatchesSwitch( p ); - else - Fpga_MappingMatchesArea( p ); - // get the resulting area - aAreaTotalCur = Fpga_MappingSetRefsAndArea( p ); -if ( p->fVerbose ) -{ -printf( "Iteration %d%s : Area = %8.1f ", Iter++, (p->fSwitching?"S":"A"), aAreaTotalCur ); -if ( fShowSwitching ) -printf( "Switch = %8.1f ", Fpga_MappingGetSwitching(p,p->vMapping) ); -else -printf( "Delay = %5.2f ", Fpga_TimeComputeArrivalMax(p) ); -PRT( "Time", clock() - clk ); -} - } - - p->fAreaGlo = aAreaTotalCur; - return 1; -} - - diff --git a/src/map/fpga/fpgaCreate.c b/src/map/fpga/fpgaCreate.c deleted file mode 100644 index fa0f80d1..00000000 --- a/src/map/fpga/fpgaCreate.c +++ /dev/null @@ -1,580 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaCreate.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Technology mapping for variable-size-LUT FPGAs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaCreate.c,v 1.8 2004/09/30 21:18:09 satrajit Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" -#include "main.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Fpga_TableCreate( Fpga_Man_t * p ); -static void Fpga_TableResize( Fpga_Man_t * p ); -static Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ); - -// hash key for the structural hash table -static inline unsigned Fpga_HashKey2( Fpga_Node_t * p0, Fpga_Node_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads parameters of the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_ManReadInputNum( Fpga_Man_t * p ) { return p->nInputs; } -int Fpga_ManReadOutputNum( Fpga_Man_t * p ) { return p->nOutputs; } -Fpga_Node_t ** Fpga_ManReadInputs ( Fpga_Man_t * p ) { return p->pInputs; } -Fpga_Node_t ** Fpga_ManReadOutputs( Fpga_Man_t * p ) { return p->pOutputs; } -Fpga_Node_t * Fpga_ManReadConst1 ( Fpga_Man_t * p ) { return p->pConst1; } -float * Fpga_ManReadInputArrivals( Fpga_Man_t * p ) { return p->pInputArrivals;} -int Fpga_ManReadVerbose( Fpga_Man_t * p ) { return p->fVerbose; } -float * Fpga_ManReadLutAreas( Fpga_Man_t * p ) { return p->pLutLib->pLutAreas; } -void Fpga_ManSetTimeToMap( Fpga_Man_t * p, int Time ) { p->timeToMap = Time; } -void Fpga_ManSetTimeToNet( Fpga_Man_t * p, int Time ) { p->timeToNet = Time; } -void Fpga_ManSetTimeTotal( Fpga_Man_t * p, int Time ) { p->timeTotal = Time; } -void Fpga_ManSetOutputNames( Fpga_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; } -void Fpga_ManSetInputArrivals( Fpga_Man_t * p, float * pArrivals ) { p->pInputArrivals = pArrivals; } -void Fpga_ManSetAreaRecovery( Fpga_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;} -void Fpga_ManSetDelayLimit( Fpga_Man_t * p, float DelayLimit ) { p->DelayLimit = DelayLimit; } -void Fpga_ManSetAreaLimit( Fpga_Man_t * p, float AreaLimit ) { p->AreaLimit = AreaLimit; } -void Fpga_ManSetTimeLimit( Fpga_Man_t * p, float TimeLimit ) { p->TimeLimit = TimeLimit; } -void Fpga_ManSetChoiceNodeNum( Fpga_Man_t * p, int nChoiceNodes ) { p->nChoiceNodes = nChoiceNodes; } -void Fpga_ManSetChoiceNum( Fpga_Man_t * p, int nChoices ) { p->nChoices = nChoices; } -void Fpga_ManSetVerbose( Fpga_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; } -void Fpga_ManSetSwitching( Fpga_Man_t * p, int fSwitching ) { p->fSwitching = fSwitching; } -void Fpga_ManSetLatchPaths( Fpga_Man_t * p, int fLatchPaths ) { p->fLatchPaths = fLatchPaths; } -void Fpga_ManSetLatchNum( Fpga_Man_t * p, int nLatches ) { p->nLatches = nLatches; } -void Fpga_ManSetDelayTarget( Fpga_Man_t * p, float DelayTarget ) { p->DelayTarget = DelayTarget; } -void Fpga_ManSetName( Fpga_Man_t * p, char * pFileName ) { p->pFileName = pFileName; } - -/**Function************************************************************* - - Synopsis [Reads the parameters of the LUT library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_LibReadLutMax( Fpga_LutLib_t * pLib ) { return pLib->LutMax; } - -/**Function************************************************************* - - Synopsis [Reads parameters of the mapping node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Fpga_NodeReadData0( Fpga_Node_t * p ) { return p->pData0; } -Fpga_Node_t * Fpga_NodeReadData1( Fpga_Node_t * p ) { return p->pLevel; } -int Fpga_NodeReadRefs( Fpga_Node_t * p ) { return p->nRefs; } -int Fpga_NodeReadNum( Fpga_Node_t * p ) { return p->Num; } -int Fpga_NodeReadLevel( Fpga_Node_t * p ) { return Fpga_Regular(p)->Level; } -Fpga_Cut_t * Fpga_NodeReadCuts( Fpga_Node_t * p ) { return p->pCuts; } -Fpga_Cut_t * Fpga_NodeReadCutBest( Fpga_Node_t * p ) { return p->pCutBest; } -Fpga_Node_t * Fpga_NodeReadOne( Fpga_Node_t * p ) { return p->p1; } -Fpga_Node_t * Fpga_NodeReadTwo( Fpga_Node_t * p ) { return p->p2; } -void Fpga_NodeSetData0( Fpga_Node_t * p, char * pData ) { p->pData0 = pData; } -void Fpga_NodeSetData1( Fpga_Node_t * p, Fpga_Node_t * pNode ) { p->pLevel = pNode; } -void Fpga_NodeSetNextE( Fpga_Node_t * p, Fpga_Node_t * pNextE ) { p->pNextE = pNextE; } -void Fpga_NodeSetRepr( Fpga_Node_t * p, Fpga_Node_t * pRepr ) { p->pRepr = pRepr; } -void Fpga_NodeSetSwitching( Fpga_Node_t * p, float Switching ) { p->Switching = Switching; } - -/**Function************************************************************* - - Synopsis [Checks the type of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_NodeIsConst( Fpga_Node_t * p ) { return (Fpga_Regular(p))->Num == -1; } -int Fpga_NodeIsVar( Fpga_Node_t * p ) { return (Fpga_Regular(p))->p1 == NULL && (Fpga_Regular(p))->Num >= 0; } -int Fpga_NodeIsAnd( Fpga_Node_t * p ) { return (Fpga_Regular(p))->p1 != NULL; } -int Fpga_NodeComparePhase( Fpga_Node_t * p1, Fpga_Node_t * p2 ) { assert( !Fpga_IsComplement(p1) ); assert( !Fpga_IsComplement(p2) ); return p1->fInv ^ p2->fInv; } - -/**Function************************************************************* - - Synopsis [Reads parameters from the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CutReadLeavesNum( Fpga_Cut_t * p ) { return p->nLeaves; } -Fpga_Node_t ** Fpga_CutReadLeaves( Fpga_Cut_t * p ) { return p->ppLeaves; } - - -/**Function************************************************************* - - Synopsis [Create the mapping manager.] - - Description [The number of inputs and outputs is assumed to be - known is advance. It is much simpler to have them fixed upfront. - When it comes to representing the object graph in the form of - AIG, the resulting manager is similar to the regular AIG manager, - except that it does not use reference counting (and therefore - does not have garbage collections). It does have table resizing. - The data structure is more flexible to represent additional - information needed for mapping.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Man_t * Fpga_ManCreate( int nInputs, int nOutputs, int fVerbose ) -{ - Fpga_Man_t * p; - int i; - - // start the manager - p = ALLOC( Fpga_Man_t, 1 ); - memset( p, 0, sizeof(Fpga_Man_t) ); - p->pLutLib = Abc_FrameReadLibLut(); - p->nVarsMax = p->pLutLib->LutMax; - p->fVerbose = fVerbose; - p->fAreaRecovery = 1; - p->fEpsilon = (float)0.001; - - Fpga_TableCreate( p ); -//if ( p->fVerbose ) -// printf( "Node = %d (%d) bytes. Cut = %d bytes.\n", sizeof(Fpga_Node_t), FPGA_NUM_BYTES(sizeof(Fpga_Node_t)), sizeof(Fpga_Cut_t) ); - p->mmNodes = Extra_MmFixedStart( FPGA_NUM_BYTES(sizeof(Fpga_Node_t)) ); - p->mmCuts = Extra_MmFixedStart( sizeof(Fpga_Cut_t) ); - - assert( p->nVarsMax > 0 ); -// Fpga_MappingSetupTruthTables( p->uTruths ); - - // make sure the constant node will get index -1 - p->nNodes = -1; - // create the constant node - p->pConst1 = Fpga_NodeCreate( p, NULL, NULL ); - p->vNodesAll = Fpga_NodeVecAlloc( 1000 ); - p->vMapping = Fpga_NodeVecAlloc( 1000 ); - - // create the PI nodes - p->nInputs = nInputs; - p->pInputs = ALLOC( Fpga_Node_t *, nInputs ); - for ( i = 0; i < nInputs; i++ ) - p->pInputs[i] = Fpga_NodeCreate( p, NULL, NULL ); - - // create the place for the output nodes - p->nOutputs = nOutputs; - p->pOutputs = ALLOC( Fpga_Node_t *, nOutputs ); - memset( p->pOutputs, 0, sizeof(Fpga_Node_t *) * nOutputs ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_ManFree( Fpga_Man_t * p ) -{ -// Fpga_ManStats( p ); -// int i; -// for ( i = 0; i < p->vNodesAll->nSize; i++ ) -// Fpga_NodeVecFree( p->vNodesAll->pArray[i]->vFanouts ); -// Fpga_NodeVecFree( p->pConst1->vFanouts ); - if ( p->vMapping ) - Fpga_NodeVecFree( p->vMapping ); - if ( p->vAnds ) - Fpga_NodeVecFree( p->vAnds ); - if ( p->vNodesAll ) - Fpga_NodeVecFree( p->vNodesAll ); - Extra_MmFixedStop( p->mmNodes ); - Extra_MmFixedStop( p->mmCuts ); - FREE( p->ppOutputNames ); - FREE( p->pInputArrivals ); - FREE( p->pInputs ); - FREE( p->pOutputs ); - FREE( p->pBins ); - FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [Prints runtime statistics of the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_ManPrintTimeStats( Fpga_Man_t * p ) -{ - extern char * pNetName; - extern int TotalLuts; -// FILE * pTable; - - -/* - pTable = fopen( "stats.txt", "a+" ); - fprintf( pTable, "%s ", pNetName ); - fprintf( pTable, "%.0f ", p->fRequiredGlo ); -// fprintf( pTable, "%.0f ", p->fAreaGlo );//+ (float)nOutputInvs ); - fprintf( pTable, "%.0f ", (float)TotalLuts ); - fprintf( pTable, "%4.2f\n", (float)(p->timeTotal-p->timeToMap)/(float)(CLOCKS_PER_SEC) ); - fclose( pTable ); -*/ - -// printf( "N-canonical = %d. Matchings = %d. ", p->nCanons, p->nMatches ); -// printf( "Choice nodes = %d. Choices = %d.\n", p->nChoiceNodes, p->nChoices ); - PRT( "ToMap", p->timeToMap ); - PRT( "Cuts ", p->timeCuts ); - PRT( "Match", p->timeMatch ); - PRT( "Area ", p->timeRecover ); - PRT( "ToNet", p->timeToNet ); - PRT( "TOTAL", p->timeTotal ); - if ( p->time1 ) { PRT( "time1", p->time1 ); } - if ( p->time2 ) { PRT( "time2", p->time2 ); } -} - -/**Function************************************************************* - - Synopsis [Creates a new node.] - - Description [This procedure should be called to create the constant - node and the PI nodes first.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Node_t * Fpga_NodeCreate( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) -{ - Fpga_Node_t * pNode; - // create the node - pNode = (Fpga_Node_t *)Extra_MmFixedEntryFetch( p->mmNodes ); - memset( pNode, 0, sizeof(Fpga_Node_t) ); - // set very large required time - pNode->tRequired = FPGA_FLOAT_LARGE; - pNode->aEstFanouts = -1; - pNode->p1 = p1; - pNode->p2 = p2; - // set the number of this node - pNode->Num = p->nNodes++; - // place to store the fanouts -// pNode->vFanouts = Fpga_NodeVecAlloc( 5 ); - // store this node in the internal array - if ( pNode->Num >= 0 ) - Fpga_NodeVecPush( p->vNodesAll, pNode ); - else - pNode->fInv = 1; - // set the level of this node - if ( p1 ) - { -#ifdef FPGA_ALLOCATE_FANOUT - // create the fanout info - Fpga_NodeAddFaninFanout( Fpga_Regular(p1), pNode ); - Fpga_NodeAddFaninFanout( Fpga_Regular(p2), pNode ); -#endif - // compute the level - pNode->Level = 1 + FPGA_MAX(Fpga_Regular(p1)->Level, Fpga_Regular(p2)->Level); - pNode->fInv = Fpga_NodeIsSimComplement(p1) & Fpga_NodeIsSimComplement(p2); - } - // reference the inputs - if ( p1 ) Fpga_NodeRef(p1); - if ( p2 ) Fpga_NodeRef(p2); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Create the unique table of AND gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_TableCreate( Fpga_Man_t * pMan ) -{ - assert( pMan->pBins == NULL ); - pMan->nBins = Cudd_Prime(50000); - pMan->pBins = ALLOC( Fpga_Node_t *, pMan->nBins ); - memset( pMan->pBins, 0, sizeof(Fpga_Node_t *) * pMan->nBins ); - pMan->nNodes = 0; -} - -/**Function************************************************************* - - Synopsis [Looks up the AND2 node in the unique table.] - - Description [This procedure implements one-level hashing. All the nodes - are hashed by their children. If the node with the same children was already - created, it is returned by the call to this procedure. If it does not exist, - this procedure creates a new node with these children. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Node_t * Fpga_TableLookup( Fpga_Man_t * pMan, Fpga_Node_t * p1, Fpga_Node_t * p2 ) -{ - Fpga_Node_t * pEnt; - unsigned Key; - - if ( p1 == p2 ) - return p1; - if ( p1 == Fpga_Not(p2) ) - return Fpga_Not(pMan->pConst1); - if ( Fpga_NodeIsConst(p1) ) - { - if ( p1 == pMan->pConst1 ) - return p2; - return Fpga_Not(pMan->pConst1); - } - if ( Fpga_NodeIsConst(p2) ) - { - if ( p2 == pMan->pConst1 ) - return p1; - return Fpga_Not(pMan->pConst1); - } - - if ( Fpga_Regular(p1)->Num > Fpga_Regular(p2)->Num ) - pEnt = p1, p1 = p2, p2 = pEnt; - - Key = Fpga_HashKey2( p1, p2, pMan->nBins ); - for ( pEnt = pMan->pBins[Key]; pEnt; pEnt = pEnt->pNext ) - if ( pEnt->p1 == p1 && pEnt->p2 == p2 ) - return pEnt; - // resize the table - if ( pMan->nNodes >= 2 * pMan->nBins ) - { - Fpga_TableResize( pMan ); - Key = Fpga_HashKey2( p1, p2, pMan->nBins ); - } - // create the new node - pEnt = Fpga_NodeCreate( pMan, p1, p2 ); - // add the node to the corresponding linked list in the table - pEnt->pNext = pMan->pBins[Key]; - pMan->pBins[Key] = pEnt; - return pEnt; -} - - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_TableResize( Fpga_Man_t * pMan ) -{ - Fpga_Node_t ** pBinsNew; - Fpga_Node_t * pEnt, * pEnt2; - int nBinsNew, Counter, i, clk; - unsigned Key; - -clk = clock(); - // get the new table size - nBinsNew = Cudd_Prime(2 * pMan->nBins); - // allocate a new array - pBinsNew = ALLOC( Fpga_Node_t *, nBinsNew ); - memset( pBinsNew, 0, sizeof(Fpga_Node_t *) * nBinsNew ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < pMan->nBins; i++ ) - for ( pEnt = pMan->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; - pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL ) - { - Key = Fpga_HashKey2( pEnt->p1, pEnt->p2, nBinsNew ); - pEnt->pNext = pBinsNew[Key]; - pBinsNew[Key] = pEnt; - Counter++; - } - assert( Counter == pMan->nNodes - pMan->nInputs ); - if ( pMan->fVerbose ) - { -// printf( "Increasing the unique table size from %6d to %6d. ", pMan->nBins, nBinsNew ); -// PRT( "Time", clock() - clk ); - } - // replace the table and the parameters - free( pMan->pBins ); - pMan->pBins = pBinsNew; - pMan->nBins = nBinsNew; -} - - - -/**Function************************************************************* - - Synopsis [Elementary AND operation on the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Node_t * Fpga_NodeAnd( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) -{ - Fpga_Node_t * pNode; - pNode = Fpga_TableLookup( p, p1, p2 ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Elementary OR operation on the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Node_t * Fpga_NodeOr( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) -{ - Fpga_Node_t * pNode; - pNode = Fpga_Not( Fpga_TableLookup( p, Fpga_Not(p1), Fpga_Not(p2) ) ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Elementary EXOR operation on the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Node_t * Fpga_NodeExor( Fpga_Man_t * p, Fpga_Node_t * p1, Fpga_Node_t * p2 ) -{ - return Fpga_NodeMux( p, p1, Fpga_Not(p2), p2 ); -} - -/**Function************************************************************* - - Synopsis [Elementary MUX operation on the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Node_t * Fpga_NodeMux( Fpga_Man_t * p, Fpga_Node_t * pC, Fpga_Node_t * pT, Fpga_Node_t * pE ) -{ - Fpga_Node_t * pAnd1, * pAnd2, * pRes; - pAnd1 = Fpga_TableLookup( p, pC, pT ); - pAnd2 = Fpga_TableLookup( p, Fpga_Not(pC), pE ); - pRes = Fpga_NodeOr( p, pAnd1, pAnd2 ); - return pRes; -} - - -/**Function************************************************************* - - Synopsis [Sets the node to be equivalent to the given one.] - - Description [This procedure is a work-around for the equivalence check. - Does not verify the equivalence. Use at the user's risk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeSetChoice( Fpga_Man_t * pMan, Fpga_Node_t * pNodeOld, Fpga_Node_t * pNodeNew ) -{ - pNodeNew->pNextE = pNodeOld->pNextE; - pNodeOld->pNextE = pNodeNew; - pNodeNew->pRepr = pNodeOld; -} - - - -/**Function************************************************************* - - Synopsis [Prints some interesting stats.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_ManStats( Fpga_Man_t * p ) -{ - FILE * pTable; - pTable = fopen( "stats.txt", "a+" ); - fprintf( pTable, "%s ", p->pFileName ); - fprintf( pTable, "%4d ", p->nInputs - p->nLatches ); - fprintf( pTable, "%4d ", p->nOutputs - p->nLatches ); - fprintf( pTable, "%4d ", p->nLatches ); - fprintf( pTable, "%7d ", p->vAnds->nSize ); - fprintf( pTable, "%7d ", Fpga_CutCountAll(p) ); - fprintf( pTable, "%2d\n", (int)p->fRequiredGlo ); - fclose( pTable ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/fpga/fpgaCut.c b/src/map/fpga/fpgaCut.c deleted file mode 100644 index a5505e72..00000000 --- a/src/map/fpga/fpgaCut.c +++ /dev/null @@ -1,1159 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaCut.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaCut.c,v 1.3 2004/07/06 04:55:57 alanmi Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Fpga_CutTableStrutct_t Fpga_CutTable_t; -struct Fpga_CutTableStrutct_t -{ - Fpga_Cut_t ** pBins; // the table used for linear probing - int nBins; // the size of the table - int * pCuts; // the array of cuts currently stored - int nCuts; // the number of cuts currently stored - Fpga_Cut_t ** pArray; // the temporary array of cuts - Fpga_Cut_t ** pCuts1; // the temporary array of cuts - Fpga_Cut_t ** pCuts2; // the temporary array of cuts -}; - -// the largest number of cuts considered -//#define FPGA_CUTS_MAX_COMPUTE 500 -#define FPGA_CUTS_MAX_COMPUTE 2000 -// the largest number of cuts used -//#define FPGA_CUTS_MAX_USE 200 -#define FPGA_CUTS_MAX_USE 1000 - -// primes used to compute the hash key -static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 }; - -static int bit_count[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; - -#define FPGA_COUNT_ONES(u) (bit_count[(u)&255]+bit_count[((u)>>8)&255]+bit_count[((u)>>16)&255]+bit_count[(u)>>24]) - -static Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode ); -static void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode ); -static Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ); -static int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax ); -static Fpga_Cut_t * Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 ); -static int Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes ); -extern Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p ); -extern int Fpga_CutCountAll( Fpga_Man_t * pMan ); - -static void Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ); -static void Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ); -static void Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot ); - -static Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan ); -static void Fpga_CutTableStop( Fpga_CutTable_t * p ); -static unsigned Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes ); -static int Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ); -static Fpga_Cut_t * Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ); -static void Fpga_CutTableRestart( Fpga_CutTable_t * p ); - -static int Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 ); -static Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList ); -static int Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList ); -static Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts ); - - -// iterator through all the cuts of the list -#define Fpga_ListForEachCut( pList, pCut ) \ - for ( pCut = pList; \ - pCut; \ - pCut = pCut->pNext ) -#define Fpga_ListForEachCutSafe( pList, pCut, pCut2 ) \ - for ( pCut = pList, \ - pCut2 = pCut? pCut->pNext: NULL; \ - pCut; \ - pCut = pCut2, \ - pCut2 = pCut? pCut->pNext: NULL ) - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the cuts for each node in the object graph.] - - Description [The cuts are computed in one sweep over the mapping graph. - First, the elementary cuts, which include the node itself, are assigned - to the PI nodes. The internal nodes are considered in the DFS order. - Each node is two-input AND-gate. So to compute the cuts at a node, we - need to merge the sets of cuts of its two predecessors. The merged set - contains only unique cuts with the number of inputs equal to k or less. - Finally, the elementary cut, composed of the node itself, is added to - the set of cuts for the node. - - This procedure is pretty fast for 5-feasible cuts, but it dramatically - slows down on some "dense" networks when computing 6-feasible cuts. - The problem is that there are too many cuts in this case. We should - think how to heuristically trim the number of cuts in such cases, - to have reasonable runtime.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_MappingCuts( Fpga_Man_t * p ) -{ - ProgressBar * pProgress; - Fpga_CutTable_t * pTable; - Fpga_Node_t * pNode; - int nCuts, nNodes, i; - int clk = clock(); - - // set the elementary cuts for the PI variables - assert( p->nVarsMax > 1 && p->nVarsMax < 11 ); - Fpga_MappingCreatePiCuts( p ); - - // compute the cuts for the internal nodes - nNodes = p->vAnds->nSize; - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - pTable = Fpga_CutTableStart( p ); - for ( i = 0; i < nNodes; i++ ) - { - Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." ); - pNode = p->vAnds->pArray[i]; - if ( !Fpga_NodeIsAnd( pNode ) ) - continue; - Fpga_CutCompute( p, pTable, pNode ); - } - Extra_ProgressBarStop( pProgress ); - Fpga_CutTableStop( pTable ); - - // report the stats - if ( p->fVerbose ) - { - nCuts = Fpga_CutCountAll(p); - printf( "Nodes = %6d. Total %d-cuts = %d. Cuts per node = %.1f. ", - p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes ); - PRT( "Time", clock() - clk ); - } - - // print the cuts for the first primary output -// Fpga_CutListPrint( p, Fpga_Regular(p->pOutputs[0]) ); -} - -/**Function************************************************************* - - Synopsis [Performs technology mapping for variable-size-LUTs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_MappingCreatePiCuts( Fpga_Man_t * p ) -{ - Fpga_Cut_t * pCut; - int i; - - // set the elementary cuts for the PI variables - for ( i = 0; i < p->nInputs; i++ ) - { - pCut = Fpga_CutAlloc( p ); - pCut->nLeaves = 1; - pCut->ppLeaves[0] = p->pInputs[i]; - pCut->uSign = (1 << (i%31)); - p->pInputs[i]->pCuts = pCut; - p->pInputs[i]->pCutBest = pCut; - // set the input arrival times -// p->pInputs[i]->pCut[1]->tArrival = p->pInputArrivals[i]; - } -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode ) -{ - Fpga_Node_t * pTemp; - Fpga_Cut_t * pList, * pList1, * pList2; - Fpga_Cut_t * pCut; - int fTree = 0; - int fPivot1 = fTree && (Fpga_NodeReadRef(pNode->p1)>2); - int fPivot2 = fTree && (Fpga_NodeReadRef(pNode->p2)>2); - - // if the cuts are computed return them - if ( pNode->pCuts ) - return pNode->pCuts; - - // compute the cuts for the children - pList1 = Fpga_Regular(pNode->p1)->pCuts; - pList2 = Fpga_Regular(pNode->p2)->pCuts; - // merge the lists - pList = Fpga_CutMergeLists( p, pTable, pList1, pList2, - Fpga_IsComplement(pNode->p1), Fpga_IsComplement(pNode->p2), - fPivot1, fPivot2 ); - // if there are functionally equivalent nodes, union them with this list - assert( pList ); - // only add to the list of cuts if the node is a representative one - if ( pNode->pRepr == NULL ) - { - for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) - { - assert( pTemp->pCuts ); - pList = Fpga_CutUnionLists( pList, pTemp->pCuts ); - assert( pTemp->pCuts ); - pList = Fpga_CutSortCuts( p, pTable, pList ); - } - } - // add the new cut - pCut = Fpga_CutAlloc( p ); - pCut->nLeaves = 1; - pCut->ppLeaves[0] = pNode; - pCut->uSign = (1 << (pNode->Num%31)); - pCut->fLevel = (float)pCut->ppLeaves[0]->Level; - // append (it is important that the elementary cut is appended first) - pCut->pNext = pList; - // set at the node - pNode->pCuts = pCut; - // remove the dominated cuts -// Fpga_CutFilter( p, pNode ); - // set the phase correctly - if ( pNode->pRepr && Fpga_NodeComparePhase(pNode, pNode->pRepr) ) - { - Fpga_ListForEachCut( pNode->pCuts, pCut ) - pCut->Phase = 1; - } - - -/* - { - Fpga_Cut_t * pPrev; - int i, Counter = 0; - for ( pCut = pNode->pCuts->pNext, pPrev = pNode->pCuts; pCut; pCut = pCut->pNext ) - { - for ( i = 0; i < pCut->nLeaves; i++ ) - if ( pCut->ppLeaves[i]->Level >= pNode->Level ) - break; - if ( i != pCut->nLeaves ) - pPrev->pNext = pCut->pNext; - else - pPrev = pCut; - } - } - { - int i, Counter = 0;; - for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) - for ( i = 0; i < pCut->nLeaves; i++ ) - Counter += (pCut->ppLeaves[i]->Level >= pNode->Level); - if ( Counter ) - printf( " %d", Counter ); - } -*/ - - return pCut; -} - -/**Function************************************************************* - - Synopsis [Filter the cuts using dominance.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode ) -{ - Fpga_Cut_t * pTemp, * pPrev, * pCut, * pCut2; - int i, k, Counter; - - Counter = 0; - pPrev = pNode->pCuts; - Fpga_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 ) - { - // go through all the previous cuts up to pCut - for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext ) - { - // check if every node in pTemp is contained in pCut - for ( i = 0; i < pTemp->nLeaves; i++ ) - { - for ( k = 0; k < pCut->nLeaves; k++ ) - if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] ) - break; - if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut - break; - } - if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut - { - Counter++; - break; - } - } - if ( pTemp != pCut ) // pTemp contain pCut - { - pPrev->pNext = pCut->pNext; // skip pCut - // recycle pCut - Fpga_CutFree( p, pCut ); - } - else - pPrev = pCut; - } -// printf( "Dominated = %3d. \n", Counter ); -} - - -/**Function************************************************************* - - Synopsis [Merges two lists of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable, - Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ) -{ - Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES]; - Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL }; - Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; - int nNodes, Counter, i; - Fpga_Cut_t ** ppArray1, ** ppArray2, ** ppArray3; - int nCuts1, nCuts2, nCuts3, k, fComp3; - - ppArray1 = pTable->pCuts1; - ppArray2 = pTable->pCuts2; - nCuts1 = Fpga_CutList2Array( ppArray1, pList1 ); - nCuts2 = Fpga_CutList2Array( ppArray2, pList2 ); - if ( fPivot1 ) - nCuts1 = 1; - if ( fPivot2 ) - nCuts2 = 1; - // swap the lists based on their length - if ( nCuts1 > nCuts2 ) - { - ppArray3 = ppArray1; - ppArray1 = ppArray2; - ppArray2 = ppArray3; - - nCuts3 = nCuts1; - nCuts1 = nCuts2; - nCuts2 = nCuts3; - - fComp3 = fComp1; - fComp1 = fComp2; - fComp2 = fComp3; - } - // pList1 is shorter or equal length compared to pList2 - - // prepare the manager for the cut computation - Fpga_CutTableRestart( pTable ); - // go through the cut pairs - Counter = 0; -// for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext ) -// for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext ) - for ( i = 0; i < nCuts1; i++ ) - { - for ( k = 0; k <= i; k++ ) - { - pTemp1 = ppArray1[i]; - pTemp2 = ppArray2[k]; - - if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) - { - if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) - continue; - if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) - continue; - } - - // check if k-feasible cut exists - nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); - if ( nNodes == 0 ) - continue; - // consider the cut for possible addition to the set of new cuts - pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); - if ( pCut == NULL ) - continue; - // add data to the cut - pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); - pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); - // create the signature - pCut->uSign = pTemp1->uSign | pTemp2->uSign; - // add it to the corresponding list - pCut->pNext = pLists[pCut->nLeaves]; - pLists[pCut->nLeaves] = pCut; - // count this cut and quit if limit is reached - Counter++; - if ( Counter == FPGA_CUTS_MAX_COMPUTE ) - goto QUITS; - } - for ( k = 0; k < i; k++ ) - { - pTemp1 = ppArray1[k]; - pTemp2 = ppArray2[i]; - - if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) - { - if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) - continue; - if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) - continue; - } - - - // check if k-feasible cut exists - nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); - if ( nNodes == 0 ) - continue; - // consider the cut for possible addition to the set of new cuts - pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); - if ( pCut == NULL ) - continue; - // add data to the cut - pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); - pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); - // create the signature - pCut->uSign = pTemp1->uSign | pTemp2->uSign; - // add it to the corresponding list - pCut->pNext = pLists[pCut->nLeaves]; - pLists[pCut->nLeaves] = pCut; - // count this cut and quit if limit is reached - Counter++; - if ( Counter == FPGA_CUTS_MAX_COMPUTE ) - goto QUITS; - } - } - // consider the rest of them - for ( i = nCuts1; i < nCuts2; i++ ) - for ( k = 0; k < nCuts1; k++ ) - { - pTemp1 = ppArray1[k]; - pTemp2 = ppArray2[i]; - - if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) - { - if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) - continue; - if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) - continue; - if ( pTemp1->ppLeaves[2] != pTemp2->ppLeaves[2] ) - continue; - } - - - // check if k-feasible cut exists - nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); - if ( nNodes == 0 ) - continue; - // consider the cut for possible addition to the set of new cuts - pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); - if ( pCut == NULL ) - continue; - // add data to the cut - pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); - pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); - // create the signature - pCut->uSign = pTemp1->uSign | pTemp2->uSign; - // add it to the corresponding list - pCut->pNext = pLists[pCut->nLeaves]; - pLists[pCut->nLeaves] = pCut; - // count this cut and quit if limit is reached - Counter++; - if ( Counter == FPGA_CUTS_MAX_COMPUTE ) - goto QUITS; - } -QUITS : - // combine all the lists into one - pListNew = NULL; - ppListNew = &pListNew; - for ( i = 1; i <= p->nVarsMax; i++ ) - { - if ( pLists[i] == NULL ) - continue; - // find the last entry - for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; - pPrev = pCut, pCut = pCut->pNext ); - // connect these lists - *ppListNew = pLists[i]; - ppListNew = &pPrev->pNext; - } - *ppListNew = NULL; - // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE - pListNew = Fpga_CutSortCuts( p, pTable, pListNew ); - return pListNew; -} - - -/**Function************************************************************* - - Synopsis [Merges two lists of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_CutMergeLists2( Fpga_Man_t * p, Fpga_CutTable_t * pTable, - Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ) -{ - Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES]; - Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL }; - Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; - int nNodes, Counter, i; - - // prepare the manager for the cut computation - Fpga_CutTableRestart( pTable ); - // go through the cut pairs - Counter = 0; - for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext ) - for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext ) - { - // check if k-feasible cut exists - nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); - if ( nNodes == 0 ) - continue; - // consider the cut for possible addition to the set of new cuts - pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); - if ( pCut == NULL ) - continue; - // add data to the cut - pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); - pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); - // add it to the corresponding list - pCut->pNext = pLists[pCut->nLeaves]; - pLists[pCut->nLeaves] = pCut; - // count this cut and quit if limit is reached - Counter++; - if ( Counter == FPGA_CUTS_MAX_COMPUTE ) - goto QUITS; - } -QUITS : - // combine all the lists into one - pListNew = NULL; - ppListNew = &pListNew; - for ( i = 1; i <= p->nVarsMax; i++ ) - { - if ( pLists[i] == NULL ) - continue; - // find the last entry - for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; - pPrev = pCut, pCut = pCut->pNext ); - // connect these lists - *ppListNew = pLists[i]; - ppListNew = &pPrev->pNext; - } - *ppListNew = NULL; - // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE - pListNew = Fpga_CutSortCuts( p, pTable, pListNew ); - return pListNew; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [Returns the number of nodes in the resulting cut, or 0 if the - cut is infeasible. Returns the resulting nodes in the array ppNodes[].] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax ) -{ - Fpga_Node_t * pNodeTemp; - int nTotal, i, k, min, Counter; - unsigned uSign; - - // use quick prefiltering - uSign = pCut1->uSign | pCut2->uSign; - Counter = FPGA_COUNT_ONES(uSign); - if ( Counter > nNodesMax ) - return 0; -/* - // check the special case when at least of the cuts is the largest - if ( pCut1->nLeaves == nNodesMax ) - { - if ( pCut2->nLeaves == nNodesMax ) - { - // return 0 if the cuts are different - for ( i = 0; i < nNodesMax; i++ ) - if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] ) - return 0; - // return nNodesMax if they are the same - for ( i = 0; i < nNodesMax; i++ ) - ppNodes[i] = pCut1->ppLeaves[i]; - return nNodesMax; - } - else if ( pCut2->nLeaves == nNodesMax - 1 ) - { - // return 0 if the cuts are different - fMismatch = 0; - for ( i = 0; i < nNodesMax; i++ ) - if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] ) - { - if ( fMismatch == 1 ) - return 0; - fMismatch = 1; - } - // return nNodesMax if they are the same - for ( i = 0; i < nNodesMax; i++ ) - ppNodes[i] = pCut1->ppLeaves[i]; - return nNodesMax; - } - } - else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax ) - { - // return 0 if the cuts are different - fMismatch = 0; - for ( i = 0; i < nNodesMax; i++ ) - if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] ) - { - if ( fMismatch == 1 ) - return 0; - fMismatch = 1; - } - // return nNodesMax if they are the same - for ( i = 0; i < nNodesMax; i++ ) - ppNodes[i] = pCut2->ppLeaves[i]; - return nNodesMax; - } -*/ - // count the number of unique entries in pCut2 - nTotal = pCut1->nLeaves; - for ( i = 0; i < pCut2->nLeaves; i++ ) - { - // try to find this entry among the leaves of pCut1 - for ( k = 0; k < pCut1->nLeaves; k++ ) - if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] ) - break; - if ( k < pCut1->nLeaves ) // found - continue; - // we found a new entry to add - if ( nTotal == nNodesMax ) - return 0; - ppNodes[nTotal++] = pCut2->ppLeaves[i]; - } - // we know that the feasible cut exists - - // add the starting entries - for ( k = 0; k < pCut1->nLeaves; k++ ) - ppNodes[k] = pCut1->ppLeaves[k]; - - // selection-sort the entries - for ( i = 0; i < nTotal - 1; i++ ) - { - min = i; - for ( k = i+1; k < nTotal; k++ ) -// if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!) - if ( ppNodes[k]->Num < ppNodes[min]->Num ) - min = k; - pNodeTemp = ppNodes[i]; - ppNodes[i] = ppNodes[min]; - ppNodes[min] = pNodeTemp; - } - - return nTotal; -} - -/**Function************************************************************* - - Synopsis [Computes the union of the two lists of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 ) -{ - Fpga_Cut_t * pTemp, * pRoot; - // find the last cut in the first list - pRoot = pList1; - Fpga_ListForEachCut( pList1, pTemp ) - pRoot = pTemp; - // attach the non-trival part of the second cut to the end of the first - assert( pRoot->pNext == NULL ); - pRoot->pNext = pList2->pNext; - pList2->pNext = NULL; - return pList1; -} - - -/**Function************************************************************* - - Synopsis [Checks whether the given cut belongs to the list.] - - Description [This procedure takes most of the runtime in the cut - computation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes ) -{ - Fpga_Cut_t * pTemp; - int i; - for ( pTemp = pList; pTemp; pTemp = pTemp->pNext ) - { - for ( i = 0; i < nNodes; i++ ) - if ( pTemp->ppLeaves[i] != ppNodes[i] ) - break; - if ( i == nNodes ) - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Counts all the cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CutCountAll( Fpga_Man_t * pMan ) -{ - Fpga_Node_t * pNode; - Fpga_Cut_t * pCut; - int i, nCuts; - // go through all the nodes in the unique table of the manager - nCuts = 0; - for ( i = 0; i < pMan->nBins; i++ ) - for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) - for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) - if ( pCut->nLeaves > 1 ) // skip the elementary cuts - { -// Fpga_CutVolume( pCut ); - nCuts++; - } - return nCuts; -} - - -/**Function************************************************************* - - Synopsis [Clean the signatures.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutsCleanSign( Fpga_Man_t * pMan ) -{ - Fpga_Node_t * pNode; - Fpga_Cut_t * pCut; - int i; - for ( i = 0; i < pMan->nBins; i++ ) - for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) - for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) - pCut->uSign = 0; -} - - - -/**Function************************************************************* - - Synopsis [Prints the cuts in the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ) -{ - Fpga_Cut_t * pTemp; - int Counter; - for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) - { - printf( "%2d : ", Counter + 1 ); - Fpga_CutPrint_( pMan, pTemp, pRoot ); - } -} - -/**Function************************************************************* - - Synopsis [Prints the cuts in the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ) -{ - Fpga_Cut_t * pTemp; - int Counter; - for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) - { - printf( "%2d : ", Counter + 1 ); - Fpga_CutPrint_( pMan, pTemp, pRoot ); - } -} - -/**Function************************************************************* - - Synopsis [Prints the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot ) -{ - int i; - printf( "(%3d) {", pRoot->Num ); - for ( i = 0; i < pMan->nVarsMax; i++ ) - if ( pCut->ppLeaves[i] ) - printf( " %3d", pCut->ppLeaves[i]->Num ); - printf( " }\n" ); -} - - - - - - - - -/**Function************************************************************* - - Synopsis [Starts the hash table to canonicize cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan ) -{ - Fpga_CutTable_t * p; - // allocate the table - p = ALLOC( Fpga_CutTable_t, 1 ); - memset( p, 0, sizeof(Fpga_CutTable_t) ); - p->nBins = Cudd_Prime( 10 * FPGA_CUTS_MAX_COMPUTE ); - p->pBins = ALLOC( Fpga_Cut_t *, p->nBins ); - memset( p->pBins, 0, sizeof(Fpga_Cut_t *) * p->nBins ); - p->pCuts = ALLOC( int, 2 * FPGA_CUTS_MAX_COMPUTE ); - p->pArray = ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); - p->pCuts1 = ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); - p->pCuts2 = ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutTableStop( Fpga_CutTable_t * p ) -{ - free( p->pCuts1 ); - free( p->pCuts2 ); - free( p->pArray ); - free( p->pBins ); - free( p->pCuts ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Computes the hash value of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes ) -{ - unsigned uRes; - int i; - uRes = 0; - for ( i = 0; i < nNodes; i++ ) - uRes += s_HashPrimes[i] * ppNodes[i]->Num; - return uRes; -} - -/**Function************************************************************* - - Synopsis [Looks up the table for the available cut.] - - Description [Returns -1 if the same cut is found. Returns the index - of the cell where the cut should be added, if it does not exist.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ) -{ - Fpga_Cut_t * pCut; - unsigned Key; - int b, i; - - Key = Fpga_CutTableHash(ppNodes, nNodes) % p->nBins; - for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins ) - { - pCut = p->pBins[b]; - if ( pCut->nLeaves != nNodes ) - continue; - for ( i = 0; i < nNodes; i++ ) - if ( pCut->ppLeaves[i] != ppNodes[i] ) - break; - if ( i == nNodes ) - return -1; - } - return b; -} - - -/**Function************************************************************* - - Synopsis [Starts the hash table to canonicize cuts.] - - Description [Considers addition of the cut to the hash table.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ) -{ - Fpga_Cut_t * pCut; - int Place, i; - // check the cut - Place = Fpga_CutTableLookup( p, ppNodes, nNodes ); - if ( Place == -1 ) - return NULL; - assert( nNodes > 0 ); - // create the new cut - pCut = Fpga_CutAlloc( pMan ); - pCut->nLeaves = nNodes; - pCut->fLevel = 0.0; - for ( i = 0; i < nNodes; i++ ) - { - pCut->ppLeaves[i] = ppNodes[i]; - pCut->fLevel += ppNodes[i]->Level; - } - pCut->fLevel /= nNodes; - // add the cut to the table - assert( p->pBins[Place] == NULL ); - p->pBins[Place] = pCut; - // add the cut to the new list - p->pCuts[ p->nCuts++ ] = Place; - return pCut; -} - -/**Function************************************************************* - - Synopsis [Prepares the table to be used with other cuts.] - - Description [Restarts the table by cleaning the info about cuts stored - when the previous node was considered.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutTableRestart( Fpga_CutTable_t * p ) -{ - int i; - for ( i = 0; i < p->nCuts; i++ ) - { - assert( p->pBins[ p->pCuts[i] ] ); - p->pBins[ p->pCuts[i] ] = NULL; - } - p->nCuts = 0; -} - - - -/**Function************************************************************* - - Synopsis [Compares the cuts by the number of leaves and then by delay.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 ) -{ - if ( (*pC1)->nLeaves < (*pC2)->nLeaves ) - return -1; - if ( (*pC1)->nLeaves > (*pC2)->nLeaves ) - return 1; -/* - if ( (*pC1)->fLevel > (*pC2)->fLevel ) - return -1; - if ( (*pC1)->fLevel < (*pC2)->fLevel ) - return 1; -*/ - return 0; -} - -/**Function************************************************************* - - Synopsis [Sorts the cuts by average arrival time.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList ) -{ - Fpga_Cut_t * pListNew; - int nCuts, i; - // move the cuts from the list into the array - nCuts = Fpga_CutList2Array( p->pCuts1, pList ); - assert( nCuts <= FPGA_CUTS_MAX_COMPUTE ); - // sort the cuts - qsort( (void *)p->pCuts1, nCuts, sizeof(void *), - (int (*)(const void *, const void *)) Fpga_CutSortCutsCompare ); - // move them back into the list - if ( nCuts > FPGA_CUTS_MAX_USE - 1 ) - { -// printf( "*" ); - // free the remaining cuts - for ( i = FPGA_CUTS_MAX_USE - 1; i < nCuts; i++ ) - Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] ); - // update the number of cuts - nCuts = FPGA_CUTS_MAX_USE - 1; - } - pListNew = Fpga_CutArray2List( p->pCuts1, nCuts ); - return pListNew; -} - -/**Function************************************************************* - - Synopsis [Moves the nodes from the list into the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList ) -{ - int i; - for ( i = 0; pList; pList = pList->pNext, i++ ) - pArray[i] = pList; - return i; -} - -/**Function************************************************************* - - Synopsis [Moves the nodes from the array into the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts ) -{ - Fpga_Cut_t * pListNew, ** ppListNew; - int i; - pListNew = NULL; - ppListNew = &pListNew; - for ( i = 0; i < nCuts; i++ ) - { - // connect these lists - *ppListNew = pArray[i]; - ppListNew = &pArray[i]->pNext; -//printf( " %d(%.2f)", pArray[i]->nLeaves, pArray[i]->fLevel ); - } -//printf( "\n" ); - - *ppListNew = NULL; - return pListNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/fpga/fpgaCutUtils.c b/src/map/fpga/fpgaCutUtils.c deleted file mode 100644 index e60a1dee..00000000 --- a/src/map/fpga/fpgaCutUtils.c +++ /dev/null @@ -1,470 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaCutUtils.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaCutUtils.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p ) -{ - Fpga_Cut_t * pCut; - pCut = (Fpga_Cut_t *)Extra_MmFixedEntryFetch( p->mmCuts ); - memset( pCut, 0, sizeof(Fpga_Cut_t) ); - return pCut; -} - -/**Function************************************************************* - - Synopsis [Duplicates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_CutDup( Fpga_Man_t * p, Fpga_Cut_t * pCutOld ) -{ - Fpga_Cut_t * pCutNew; - int i; - pCutNew = Fpga_CutAlloc( p ); - pCutNew->pRoot = pCutOld->pRoot; - pCutNew->nLeaves = pCutOld->nLeaves; - for ( i = 0; i < pCutOld->nLeaves; i++ ) - pCutNew->ppLeaves[i] = pCutOld->ppLeaves[i]; - return pCutNew; -} - -/**Function************************************************************* - - Synopsis [Deallocates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutFree( Fpga_Man_t * p, Fpga_Cut_t * pCut ) -{ - if ( pCut ) - Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pCut ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutPrint( Fpga_Man_t * p, Fpga_Node_t * pRoot, Fpga_Cut_t * pCut ) -{ - int i; - printf( "CUT: Delay = %4.2f. Area = %4.2f. Nodes = %d -> {", - pCut->tArrival, pCut->aFlow, pRoot->Num ); - for ( i = 0; i < pCut->nLeaves; i++ ) - printf( " %d", pCut->ppLeaves[i]->Num ); - printf( " } \n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_CutCreateSimple( Fpga_Man_t * p, Fpga_Node_t * pNode ) -{ - Fpga_Cut_t * pCut; - pCut = Fpga_CutAlloc( p ); - pCut->pRoot = pNode; - pCut->nLeaves = 1; - pCut->ppLeaves[0] = pNode; - pCut->uSign = FPGA_SEQ_SIGN(pCut->ppLeaves[0]); - return pCut; -} - - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Fpga_CutGetRootArea( Fpga_Man_t * p, Fpga_Cut_t * pCut ) -{ - return p->pLutLib->pLutAreas[pCut->nLeaves]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_CutListAppend( Fpga_Cut_t * pSetAll, Fpga_Cut_t * pSets ) -{ - Fpga_Cut_t * pPrev, * pTemp; - if ( pSetAll == NULL ) - return pSets; - if ( pSets == NULL ) - return pSetAll; - // find the last one - for ( pTemp = pSets; pTemp; pTemp = pTemp->pNext ) - pPrev = pTemp; - // append all the end of the current set - assert( pPrev->pNext == NULL ); - pPrev->pNext = pSetAll; - return pSets; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutListRecycle( Fpga_Man_t * p, Fpga_Cut_t * pSetList, Fpga_Cut_t * pSave ) -{ - Fpga_Cut_t * pNext, * pTemp; - for ( pTemp = pSetList, pNext = pTemp? pTemp->pNext : NULL; - pTemp; - pTemp = pNext, pNext = pNext? pNext->pNext : NULL ) - if ( pTemp != pSave ) - Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pTemp ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CutListCount( Fpga_Cut_t * pSets ) -{ - Fpga_Cut_t * pTemp; - int i; - for ( i = 0, pTemp = pSets; pTemp; pTemp = pTemp->pNext, i++ ); - return i; -} - -#if 0 - -/**function************************************************************* - - synopsis [Removes the fanouts of the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -void Fpga_CutRemoveFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ) -{ - Fpga_NodeVec_t * vFanouts; - int i, k; - for ( i = 0; i < pCut->nLeaves; i++ ) - { - vFanouts = pCut->ppLeaves[i]->vFanouts; - for ( k = 0; k < vFanouts->nSize; k++ ) - if ( vFanouts->pArray[k] == pNode ) - break; - assert( k != vFanouts->nSize ); - for ( k++; k < vFanouts->nSize; k++ ) - vFanouts->pArray[k-1] = vFanouts->pArray[k]; - vFanouts->nSize--; - } -} - -/**function************************************************************* - - synopsis [Removes the fanouts of the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -void Fpga_CutInsertFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ) -{ - int i; - for ( i = 0; i < pCut->nLeaves; i++ ) - Fpga_NodeVecPush( pCut->ppLeaves[i]->vFanouts, pNode ); -} -#endif - -/**Function************************************************************* - - Synopsis [Computes the arrival time and the area flow of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) -{ - Fpga_Cut_t * pFaninCut; - int i; - pCut->tArrival = -FPGA_FLOAT_LARGE; - pCut->aFlow = pMan->pLutLib->pLutAreas[pCut->nLeaves]; - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pFaninCut = pCut->ppLeaves[i]->pCutBest; - if ( pCut->tArrival < pFaninCut->tArrival ) - pCut->tArrival = pFaninCut->tArrival; - // if the fanout count is not set, assume it to be 1 - if ( pCut->ppLeaves[i]->nRefs == 0 ) - pCut->aFlow += pFaninCut->aFlow; - else -// pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->nRefs; - pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->aEstFanouts; - } - // use the first pin to compute the delay of the LUT - // (this mapper does not support the variable pin delay model) - pCut->tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves][0]; -} - - -/**function************************************************************* - - synopsis [Computes the area flow of the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Fpga_CutGetAreaFlow( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) -{ - Fpga_Cut_t * pCutFanin; - int i; - pCut->aFlow = pMan->pLutLib->pLutAreas[pCut->nLeaves]; - for ( i = 0; i < pCut->nLeaves; i++ ) - { - // get the cut implementing this phase of the fanin - pCutFanin = pCut->ppLeaves[i]->pCutBest; - assert( pCutFanin ); - pCut->aFlow += pCutFanin->aFlow / pCut->ppLeaves[i]->nRefs; - } - return pCut->aFlow; -} - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) -{ - float aResult, aResult2; - if ( pCut->nLeaves == 1 ) - return 0; - aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 ); - aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 ); - assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) ); - return aResult; -} - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) -{ - float aResult, aResult2; - if ( pCut->nLeaves == 1 ) - return 0; - aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 ); - aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 ); - assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) ); - return aResult; -} - -/**function************************************************************* - - synopsis [References the cut.] - - description [This procedure is similar to the procedure NodeReclaim.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Fpga_CutRef( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) -{ - Fpga_Node_t * pNodeChild; - float aArea; - int i; - - // deref the fanouts -// if ( fFanouts ) -// Fpga_CutInsertFanouts( pMan, pNode, pCut ); - - // start the area of this cut - aArea = pMan->pLutLib->pLutAreas[pCut->nLeaves]; - // go through the children - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pNodeChild = pCut->ppLeaves[i]; - assert( pNodeChild->nRefs >= 0 ); - if ( pNodeChild->nRefs++ > 0 ) - continue; - if ( !Fpga_NodeIsAnd(pNodeChild) ) - continue; - aArea += Fpga_CutRef( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); - } - return aArea; -} - -/**function************************************************************* - - synopsis [Dereferences the cut.] - - description [This procedure is similar to the procedure NodeRecusiveDeref.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Fpga_CutDeref( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) -{ - Fpga_Node_t * pNodeChild; - float aArea; - int i; - - // deref the fanouts -// if ( fFanouts ) -// Fpga_CutRemoveFanouts( pMan, pNode, pCut ); - - // start the area of this cut - aArea = pMan->pLutLib->pLutAreas[pCut->nLeaves]; - // go through the children - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pNodeChild = pCut->ppLeaves[i]; - assert( pNodeChild->nRefs > 0 ); - if ( --pNodeChild->nRefs > 0 ) - continue; - if ( !Fpga_NodeIsAnd(pNodeChild) ) - continue; - aArea += Fpga_CutDeref( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); - } - return aArea; -} - - -/**Function************************************************************* - - Synopsis [Sets the used cuts to be the currently selected ones.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_MappingSetUsedCuts( Fpga_Man_t * pMan ) -{ - int i; - for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) - if ( pMan->vNodesAll->pArray[i]->pCutOld ) - { - pMan->vNodesAll->pArray[i]->pCutBest = pMan->vNodesAll->pArray[i]->pCutOld; - pMan->vNodesAll->pArray[i]->pCutOld = NULL; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/fpga/fpgaFanout.c b/src/map/fpga/fpgaFanout.c deleted file mode 100644 index c28a8799..00000000 --- a/src/map/fpga/fpgaFanout.c +++ /dev/null @@ -1,141 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaFanout.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaFanout.c,v 1.1 2005/01/23 06:59:41 alanmi Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" - -#ifdef MAP_ALLOCATE_FANOUT - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Add the fanout to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeAddFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanout ) -{ - Fpga_Node_t * pPivot; - - // pFanins is a fanin of pFanout - assert( !Fpga_IsComplement(pFanin) ); - assert( !Fpga_IsComplement(pFanout) ); - assert( Fpga_Regular(pFanout->p1) == pFanin || Fpga_Regular(pFanout->p2) == pFanin ); - - pPivot = pFanin->pFanPivot; - if ( pPivot == NULL ) - { - pFanin->pFanPivot = pFanout; - return; - } - - if ( Fpga_Regular(pPivot->p1) == pFanin ) - { - if ( Fpga_Regular(pFanout->p1) == pFanin ) - { - pFanout->pFanFanin1 = pPivot->pFanFanin1; - pPivot->pFanFanin1 = pFanout; - } - else // if ( Fpga_Regular(pFanout->p2) == pFanin ) - { - pFanout->pFanFanin2 = pPivot->pFanFanin1; - pPivot->pFanFanin1 = pFanout; - } - } - else // if ( Fpga_Regular(pPivot->p2) == pFanin ) - { - assert( Fpga_Regular(pPivot->p2) == pFanin ); - if ( Fpga_Regular(pFanout->p1) == pFanin ) - { - pFanout->pFanFanin1 = pPivot->pFanFanin2; - pPivot->pFanFanin2 = pFanout; - } - else // if ( Fpga_Regular(pFanout->p2) == pFanin ) - { - pFanout->pFanFanin2 = pPivot->pFanFanin2; - pPivot->pFanFanin2 = pFanout; - } - } -} - -/**Function************************************************************* - - Synopsis [Add the fanout to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeRemoveFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanoutToRemove ) -{ - Fpga_Node_t * pFanout, * pFanout2, ** ppFanList; - // start the linked list of fanouts - ppFanList = &pFanin->pFanPivot; - // go through the fanouts - Fpga_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 ) - { - // skip the fanout-to-remove - if ( pFanout == pFanoutToRemove ) - continue; - // add useful fanouts to the list - *ppFanList = pFanout; - ppFanList = Fpga_NodeReadNextFanoutPlace( pFanin, pFanout ); - } - *ppFanList = NULL; -} - -/**Function************************************************************* - - Synopsis [Returns the number of fanouts of a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_NodeGetFanoutNum( Fpga_Node_t * pNode ) -{ - Fpga_Node_t * pFanout; - int Counter = 0; - Fpga_NodeForEachFanout( pNode, pFanout ) - Counter++; - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#endif - diff --git a/src/map/fpga/fpgaGENERIC.c b/src/map/fpga/fpgaGENERIC.c deleted file mode 100644 index 4483c215..00000000 --- a/src/map/fpga/fpgaGENERIC.c +++ /dev/null @@ -1,46 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpga__.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: fpga__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/fpga/fpgaInt.h b/src/map/fpga/fpgaInt.h deleted file mode 100644 index b93eacab..00000000 --- a/src/map/fpga/fpgaInt.h +++ /dev/null @@ -1,388 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaInt.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Technology mapping for variable-size-LUT FPGAs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaInt.h,v 1.8 2004/09/30 21:18:10 satrajit Exp $] - -***********************************************************************/ - -#ifndef __FPGA_INT_H__ -#define __FPGA_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//#include "leaks.h" -#include -#include -#include -#include "extra.h" -#include "fpga.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// uncomment to have fanouts represented in the mapping graph -//#define FPGA_ALLOCATE_FANOUT 1 - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#ifdef _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#endif - -// the maximum number of cut leaves (currently does not work for 7) -#define FPGA_MAX_LEAVES 6 - -// the bit masks -#define FPGA_MASK(n) ((~((unsigned)0)) >> (32-(n))) -#define FPGA_FULL (~((unsigned)0)) -#define FPGA_NO_VAR (-9999.0) -#define FPGA_NUM_BYTES(n) (((n)/16 + (((n)%16) > 0))*16) - -// maximum/minimum operators -#define FPGA_MIN(a,b) (((a) < (b))? (a) : (b)) -#define FPGA_MAX(a,b) (((a) > (b))? (a) : (b)) - -// the small and large numbers (min/max float are 1.17e-38/3.40e+38) -#define FPGA_FLOAT_LARGE ((float)1.0e+20) -#define FPGA_FLOAT_SMALL ((float)1.0e-20) -#define FPGA_INT_LARGE (10000000) - -// the macro to compute the signature -#define FPGA_SEQ_SIGN(p) (1 << (((unsigned)p)%31)); - -// internal macros to work with cuts -#define Fpga_CutIsComplement(p) (((int)((unsigned long) (p) & 01))) -#define Fpga_CutRegular(p) ((Fpga_Cut_t *)((unsigned long)(p) & ~01)) -#define Fpga_CutNot(p) ((Fpga_Cut_t *)((unsigned long)(p) ^ 01)) -#define Fpga_CutNotCond(p,c) ((Fpga_Cut_t *)((unsigned long)(p) ^ (c))) - -// the cut nodes -#define Fpga_SeqIsComplement( p ) (((int)((unsigned long) (p) & 01))) -#define Fpga_SeqRegular( p ) ((Fpga_Node_t *)((unsigned long)(p) & ~015)) -#define Fpga_SeqIndex( p ) ((((unsigned long)(p)) >> 1) & 07) -#define Fpga_SeqIndexCreate( p, Ind ) (((unsigned long)(p)) | (1 << (((unsigned)(Ind)) & 07))) - -// internal macros for referencing of nodes -#define Fpga_NodeReadRef(p) ((Fpga_Regular(p))->nRefs) -#define Fpga_NodeRef(p) ((Fpga_Regular(p))->nRefs++) - -// returns the complemented attribute of the node -#define Fpga_NodeIsSimComplement(p) (Fpga_IsComplement(p)? !(Fpga_Regular(p)->fInv) : (p)->fInv) - -// generating random unsigned (#define RAND_MAX 0x7fff) -#define FPGA_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) - -// outputs the runtime in seconds -#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// the mapping manager -struct Fpga_ManStruct_t_ -{ - // the mapping graph - Fpga_Node_t ** pBins; // the table of nodes hashed by their children - int nBins; // the size of the table - Fpga_Node_t ** pInputs; // the array of inputs - int nInputs; // the number of inputs - Fpga_Node_t ** pOutputs; // the array of outputs - int nOutputs; // the number of outputs - int nNodes; // the total number of nodes - int nLatches; // the number of latches in the circuit - Fpga_Node_t * pConst1; // the constant 1 node - Fpga_NodeVec_t * vNodesAll; // the nodes by number - Fpga_NodeVec_t * vAnds; // the nodes reachable from COs - Fpga_NodeVec_t * vMapping; // the nodes used in the current mapping - - // info about the original circuit - char * pFileName; // the file name - char ** ppOutputNames; // the primary output names - float * pInputArrivals;// the PI arrival times - - // mapping parameters - int nVarsMax; // the max number of variables - int fAreaRecovery; // the flag to use area flow as the first parameter - int fVerbose; // the verbosiness flag - int fSwitching; // minimize the switching activity (instead of area) - int fLatchPaths; // optimize latch paths for delay, other paths for area - int nTravIds; // the counter of traversal IDs - float DelayTarget; // the target required times - - // support of choice nodes - int nChoiceNodes; // the number of choice nodes - int nChoices; // the number of all choices - - int nCanons; - int nMatches; - - // the supergate library - Fpga_LutLib_t * pLutLib; // the current LUT library - - // the memory managers - Extra_MmFixed_t * mmNodes; // the memory manager for nodes - Extra_MmFixed_t * mmCuts; // the memory manager for cuts - - // resynthesis parameters - int fResynthesis; // the resynthesis flag - float fRequiredGlo; // the global required times - float fRequiredShift;// the shift of the required times - float fRequiredStart;// the starting global required times - float fRequiredGain; // the reduction in delay - float fAreaGlo; // the total area - float fAreaGain; // the reduction in area - float fEpsilon; // the epsilon used to compare floats - float fDelayWindow; // the delay window for delay-oriented resynthesis - float DelayLimit; // for resynthesis - float AreaLimit; // for resynthesis - float TimeLimit; // for resynthesis - - // runtime statistics - int timeToMap; // time to transfer to the mapping structure - int timeCuts; // time to compute k-feasible cuts - int timeTruth; // time to compute the truth table for each cut - int timeMatch; // time to perform matching for each node - int timeRecover; // time to perform area recovery - int timeToNet; // time to transfer back to the network - int timeTotal; // the total mapping time - int time1; // time to transfer to the mapping structure - int time2; // time to transfer to the mapping structure -}; - -// the LUT library -struct Fpga_LutLibStruct_t_ -{ - char * pName; // the name of the LUT library - int LutMax; // the maximum LUT size - int fVarPinDelays; // set to 1 if variable pin delays are specified - float pLutAreas[FPGA_MAX_LUTSIZE+1]; // the areas of LUTs - float pLutDelays[FPGA_MAX_LUTSIZE+1][FPGA_MAX_LUTSIZE+1];// the delays of LUTs -}; - -// the mapping node -struct Fpga_NodeStruct_t_ -{ - // general information about the node - Fpga_Node_t * pNext; // the next node in the hash table - Fpga_Node_t * pLevel; // the next node in the linked list by level - int Num; // the unique number of this node - int NumA; // the unique number of this node - short Num2; // the temporary number of this node - short nRefs; // the number of references (fanouts) of the given node - unsigned fMark0 : 1; // the mark used for traversals - unsigned fMark1 : 1; // the mark used for traversals - unsigned fInv : 1; // the complemented attribute for the equivalent nodes - unsigned Value : 2; // the value of the nodes - unsigned fUsed : 1; // the flag indicating that the node is used in the mapping - unsigned fTemp : 1; // unused - unsigned Level :11; // the level of the given node - unsigned uData :14; // used to mark the fanins, for which resynthesis was tried - int TravId; - - // the successors of this node - Fpga_Node_t * p1; // the first child - Fpga_Node_t * p2; // the second child - Fpga_Node_t * pNextE; // the next functionally equivalent node - Fpga_Node_t * pRepr; // the representative of the functionally equivalent class - -#ifdef FPGA_ALLOCATE_FANOUT - // representation of node's fanouts - Fpga_Node_t * pFanPivot; // the first fanout of this node - Fpga_Node_t * pFanFanin1; // the next fanout of p1 - Fpga_Node_t * pFanFanin2; // the next fanout of p2 -// Fpga_NodeVec_t * vFanouts; // the array of fanouts of the gate -#endif - - // the delay information - float tRequired; // the best area flow - float aEstFanouts; // the fanout estimation - float Switching; // the probability of switching - int LValue; // the l-value of the node - short nLatches1; // the number of latches on the first edge - short nLatches2; // the number of latches on the second edge - - // cut information - Fpga_Cut_t * pCutBest; // the best mapping - Fpga_Cut_t * pCutOld; // the old mapping - Fpga_Cut_t * pCuts; // mapping choices for the node (elementary comes first) - Fpga_Cut_t * pCutsN; // mapping choices for the node (elementary comes first) - - // misc information - char * pData0; // temporary storage for the corresponding network node -}; - -// the cuts used for matching -struct Fpga_CutStruct_t_ -{ - Fpga_Cut_t * pOne; // the father of this cut - Fpga_Cut_t * pTwo; // the mother of this cut - Fpga_Node_t * pRoot; // the root of the cut - Fpga_Node_t * ppLeaves[FPGA_MAX_LEAVES+1]; // the leaves of this cut - float fLevel; // the average level of the fanins - unsigned uSign; // signature for quick comparison - char fMark; // the mark to denote visited cut - char Phase; // the mark to denote complemented cut - char nLeaves; // the number of leaves of this cut - char nVolume; // the volume of this cut - float tArrival; // the arrival time - float aFlow; // the area flow of the cut - Fpga_Cut_t * pNext; // the pointer to the next cut in the list -}; - -// the vector of nodes -struct Fpga_NodeVecStruct_t_ -{ - Fpga_Node_t ** pArray; // the array of nodes - int nSize; // the number of entries in the array - int nCap; // the number of allocated entries -}; - -// getting hold of the next fanout of the node -#define Fpga_NodeReadNextFanout( pNode, pFanout ) \ - ( ( pFanout == NULL )? NULL : \ - ((Fpga_Regular((pFanout)->p1) == (pNode))? \ - (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) ) - -// getting hold of the place where the next fanout will be attached -#define Fpga_NodeReadNextFanoutPlace( pNode, pFanout ) \ - ( (Fpga_Regular((pFanout)->p1) == (pNode))? \ - &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 ) - -// iterator through the fanouts of the node -#define Fpga_NodeForEachFanout( pNode, pFanout ) \ - for ( pFanout = (pNode)->pFanPivot; pFanout; \ - pFanout = Fpga_NodeReadNextFanout(pNode, pFanout) ) - -// safe iterator through the fanouts of the node -#define Fpga_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \ - for ( pFanout = (pNode)->pFanPivot, \ - pFanout2 = Fpga_NodeReadNextFanout(pNode, pFanout); \ - pFanout; \ - pFanout = pFanout2, \ - pFanout2 = Fpga_NodeReadNextFanout(pNode, pFanout) ) - -static inline Fpga_FloatMoreThan( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 > Arg2 + p->fEpsilon; } -static inline Fpga_FloatLessThan( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 < Arg2 - p->fEpsilon; } -static inline Fpga_FloatEqual( Fpga_Man_t * p, float Arg1, float Arg2 ) { return Arg1 > Arg2 - p->fEpsilon && Arg1 < Arg2 + p->fEpsilon; } - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== fpgaCut.c ===============================================================*/ -extern void Fpga_MappingCuts( Fpga_Man_t * p ); -extern void Fpga_MappingCreatePiCuts( Fpga_Man_t * p ); -extern int Fpga_CutCountAll( Fpga_Man_t * pMan ); -/*=== fpgaCutUtils.c ===============================================================*/ -extern Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p ); -extern Fpga_Cut_t * Fpga_CutDup( Fpga_Man_t * p, Fpga_Cut_t * pCutOld ); -extern void Fpga_CutFree( Fpga_Man_t * p, Fpga_Cut_t * pCut ); -extern void Fpga_CutPrint( Fpga_Man_t * p, Fpga_Node_t * pRoot, Fpga_Cut_t * pCut ); -extern Fpga_Cut_t * Fpga_CutCreateSimple( Fpga_Man_t * p, Fpga_Node_t * pNode ); -extern float Fpga_CutGetRootArea( Fpga_Man_t * p, Fpga_Cut_t * pCut ); -extern Fpga_Cut_t * Fpga_CutListAppend( Fpga_Cut_t * pSetAll, Fpga_Cut_t * pSets ); -extern void Fpga_CutListRecycle( Fpga_Man_t * p, Fpga_Cut_t * pSetList, Fpga_Cut_t * pSave ); -extern int Fpga_CutListCount( Fpga_Cut_t * pSets ); -extern void Fpga_CutRemoveFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ); -extern void Fpga_CutInsertFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ); -extern float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); -extern float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); -extern float Fpga_CutRef( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); -extern float Fpga_CutDeref( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); -extern float Fpga_CutGetAreaFlow( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); -extern void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); -/*=== fraigFanout.c =============================================================*/ -extern void Fpga_NodeAddFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanout ); -extern void Fpga_NodeRemoveFaninFanout( Fpga_Node_t * pFanin, Fpga_Node_t * pFanoutToRemove ); -extern int Fpga_NodeGetFanoutNum( Fpga_Node_t * pNode ); -/*=== fpgaLib.c ============================================================*/ -extern Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose ); -extern void Fpga_LutLibFree( Fpga_LutLib_t * p ); -extern void Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib ); -extern int Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib ); -/*=== fpgaMatch.c ===============================================================*/ -extern int Fpga_MappingMatches( Fpga_Man_t * p, int fDelayOriented ); -extern int Fpga_MappingMatchesArea( Fpga_Man_t * p ); -extern int Fpga_MappingMatchesSwitch( Fpga_Man_t * p ); -/*=== fpgaShow.c =============================================================*/ -extern void Fpga_MappingShow( Fpga_Man_t * pMan, char * pFileName ); -extern void Fpga_MappingShowNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppRoots, int nRoots, char * pFileName ); -/*=== fpgaSwitch.c =============================================================*/ -extern float Fpga_CutGetSwitchDerefed( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ); -extern float Fpga_CutRefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); -extern float Fpga_CutDerefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ); -extern float Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeVec_t * vMapping ); -/*=== fpgaTime.c ===============================================================*/ -extern float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); -extern float Fpga_TimeCutComputeArrival_rec( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ); -extern float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p ); -extern void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p, int fFirstTime ); -extern void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired ); -extern void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ); -extern void Fpga_TimePropagateArrival( Fpga_Man_t * p ); -/*=== fpgaVec.c =============================================================*/ -extern Fpga_NodeVec_t * Fpga_NodeVecAlloc( int nCap ); -extern void Fpga_NodeVecFree( Fpga_NodeVec_t * p ); -extern Fpga_Node_t ** Fpga_NodeVecReadArray( Fpga_NodeVec_t * p ); -extern int Fpga_NodeVecReadSize( Fpga_NodeVec_t * p ); -extern void Fpga_NodeVecGrow( Fpga_NodeVec_t * p, int nCapMin ); -extern void Fpga_NodeVecShrink( Fpga_NodeVec_t * p, int nSizeNew ); -extern void Fpga_NodeVecClear( Fpga_NodeVec_t * p ); -extern void Fpga_NodeVecPush( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ); -extern int Fpga_NodeVecPushUnique( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ); -extern Fpga_Node_t * Fpga_NodeVecPop( Fpga_NodeVec_t * p ); -extern void Fpga_NodeVecWriteEntry( Fpga_NodeVec_t * p, int i, Fpga_Node_t * Entry ); -extern Fpga_Node_t * Fpga_NodeVecReadEntry( Fpga_NodeVec_t * p, int i ); -extern void Fpga_NodeVecSortByLevel( Fpga_NodeVec_t * p ); -extern void Fpga_SortNodesByArrivalTimes( Fpga_NodeVec_t * p ); -extern void Fpga_NodeVecUnion( Fpga_NodeVec_t * p, Fpga_NodeVec_t * p1, Fpga_NodeVec_t * p2 ); -extern void Fpga_NodeVecPushOrder( Fpga_NodeVec_t * vNodes, Fpga_Node_t * pNode, int fIncreasing ); -extern void Fpga_NodeVecReverse( Fpga_NodeVec_t * vNodes ); - -/*=== fpgaUtils.c ===============================================================*/ -extern Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv ); -extern Fpga_NodeVec_t * Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv ); -extern int Fpga_CountLevels( Fpga_Man_t * pMan ); -extern float Fpga_MappingGetAreaFlow( Fpga_Man_t * p ); -extern float Fpga_MappingArea( Fpga_Man_t * pMan ); -extern float Fpga_MappingAreaTrav( Fpga_Man_t * pMan ); -extern float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan ); -extern void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p ); -extern void Fpga_MappingSetupTruthTables( unsigned uTruths[][2] ); -extern void Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax ); -extern void Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes, int fIncreasing ); -extern Fpga_NodeVec_t * Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels ); -extern Fpga_NodeVec_t * Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes ); -extern int Fpga_MappingMaxLevel( Fpga_Man_t * pMan ); -extern void Fpga_ManReportChoices( Fpga_Man_t * pMan ); -extern void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan ); - -/*=== CUDD package.c ===============================================================*/ -extern unsigned int Cudd_Prime( unsigned int p ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/map/fpga/fpgaLib.c b/src/map/fpga/fpgaLib.c deleted file mode 100644 index e74def32..00000000 --- a/src/map/fpga/fpgaLib.c +++ /dev/null @@ -1,249 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaLib.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Technology mapping for variable-size-LUT FPGAs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaLib.c,v 1.4 2005/01/23 06:59:41 alanmi Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [APIs to access LUT library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_LutLibReadVarMax( Fpga_LutLib_t * p ) { return p->LutMax; } -float * Fpga_LutLibReadLutAreas( Fpga_LutLib_t * p ) { return p->pLutAreas; } -float Fpga_LutLibReadLutArea( Fpga_LutLib_t * p, int Size ) { assert( Size <= p->LutMax ); return p->pLutAreas[Size]; } - -/**Function************************************************************* - - Synopsis [Reads the description of LUTs from the LUT library file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_LutLib_t * Fpga_LutLibCreate( char * FileName, int fVerbose ) -{ - char pBuffer[1000], * pToken; - Fpga_LutLib_t * p; - FILE * pFile; - int i, k; - - pFile = fopen( FileName, "r" ); - if ( pFile == NULL ) - { - printf( "Cannot open LUT library file \"%s\".\n", FileName ); - return NULL; - } - - p = ALLOC( Fpga_LutLib_t, 1 ); - memset( p, 0, sizeof(Fpga_LutLib_t) ); - p->pName = Extra_UtilStrsav( FileName ); - - i = 1; - while ( fgets( pBuffer, 1000, pFile ) != NULL ) - { - pToken = strtok( pBuffer, " \t\n" ); - if ( pToken == NULL ) - continue; - if ( pToken[0] == '#' ) - continue; - if ( i != atoi(pToken) ) - { - printf( "Error in the LUT library file \"%s\".\n", FileName ); - free( p ); - return NULL; - } - - // read area - pToken = strtok( NULL, " \t\n" ); - p->pLutAreas[i] = (float)atof(pToken); - - // read delays - k = 0; - while ( pToken = strtok( NULL, " \t\n" ) ) - p->pLutDelays[i][k++] = (float)atof(pToken); - - // check for out-of-bound - if ( k > i ) - { - printf( "LUT %d has too many pins (%d). Max allowed is %d.\n", i, k, i ); - return NULL; - } - - // check if var delays are specifies - if ( k > 1 ) - p->fVarPinDelays = 1; - - if ( i == FPGA_MAX_LUTSIZE ) - { - printf( "Skipping LUTs of size more than %d.\n", i ); - return NULL; - } - i++; - } - p->LutMax = i-1; - if ( p->LutMax > FPGA_MAX_LEAVES ) - { - p->LutMax = FPGA_MAX_LEAVES; - printf( "Warning: LUTs with more than %d input will not be used.\n", FPGA_MAX_LEAVES ); - } - - // check the library - if ( p->fVarPinDelays ) - { - for ( i = 1; i <= p->LutMax; i++ ) - for ( k = 0; k < i; k++ ) - { - if ( p->pLutDelays[i][k] <= 0.0 ) - printf( "Warning: Pin %d of LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", - k, i, p->pLutDelays[i][k] ); - if ( k && p->pLutDelays[i][k-1] > p->pLutDelays[i][k] ) - printf( "Warning: Pin %d of LUT %d has delay %f. Pin %d of LUT %d has delay %f. Pin delays should be in non-decreasing order. Technology mapping may not work correctly.\n", - k-1, i, p->pLutDelays[i][k-1], - k, i, p->pLutDelays[i][k] ); - } - } - else - { - for ( i = 1; i <= p->LutMax; i++ ) - { - if ( p->pLutDelays[i][0] <= 0.0 ) - printf( "Warning: LUT %d has delay %f. Pin delays should be non-negative numbers. Technology mapping may not work correctly.\n", - k, i, p->pLutDelays[i][0] ); - } - } - - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the LUT library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_LutLib_t * Fpga_LutLibDup( Fpga_LutLib_t * p ) -{ - Fpga_LutLib_t * pNew; - pNew = ALLOC( Fpga_LutLib_t, 1 ); - *pNew = *p; - pNew->pName = Extra_UtilStrsav( pNew->pName ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Frees the LUT library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_LutLibFree( Fpga_LutLib_t * pLutLib ) -{ - if ( pLutLib == NULL ) - return; - FREE( pLutLib->pName ); - FREE( pLutLib ); -} - - -/**Function************************************************************* - - Synopsis [Prints the LUT library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_LutLibPrint( Fpga_LutLib_t * pLutLib ) -{ - int i, k; - printf( "# The area/delay of k-variable LUTs:\n" ); - printf( "# k area delay\n" ); - if ( pLutLib->fVarPinDelays ) - { - for ( i = 1; i <= pLutLib->LutMax; i++ ) - { - printf( "%d %7.2f ", i, pLutLib->pLutAreas[i] ); - for ( k = 0; k < i; k++ ) - printf( " %7.2f", pLutLib->pLutDelays[i][k] ); - printf( "\n" ); - } - } - else - for ( i = 1; i <= pLutLib->LutMax; i++ ) - printf( "%d %7.2f %7.2f\n", i, pLutLib->pLutAreas[i], pLutLib->pLutDelays[i][0] ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the delays are discrete.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_LutLibDelaysAreDiscrete( Fpga_LutLib_t * pLutLib ) -{ - float Delay; - int i; - for ( i = 1; i <= pLutLib->LutMax; i++ ) - { - Delay = pLutLib->pLutDelays[i][0]; - if ( ((float)((int)Delay)) != Delay ) - return 0; - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/fpga/fpgaMatch.c b/src/map/fpga/fpgaMatch.c deleted file mode 100644 index 73fa1258..00000000 --- a/src/map/fpga/fpgaMatch.c +++ /dev/null @@ -1,794 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaMatch.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Technology mapping for variable-size-LUT FPGAs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaMatch.c,v 1.7 2004/09/30 21:18:10 satrajit Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Fpga_MatchNode( Fpga_Man_t * p, Fpga_Node_t * pNode, int fDelayOriented ); -static int Fpga_MatchNodeArea( Fpga_Man_t * p, Fpga_Node_t * pNode ); -static int Fpga_MatchNodeSwitch( Fpga_Man_t * p, Fpga_Node_t * pNode ); - -static Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * pFanout, Fpga_Node_t * pNodeNo ); -static int Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Finds the best delay assignment of LUTs.] - - Description [This procedure iterates through all the nodes - of the object graph reachable from the POs and assigns the best - match to each of them. If the flag fDelayOriented is set to 1, it - tries to minimize the arrival time and uses the area flow as a - tie-breaker. If the flag is set to 0, it considers all the cuts, - whose arrival times matches the required time at the node, and - minimizes the area flow using the arrival time as a tie-breaker. - - Before this procedure is called, the required times should be set - and the fanout counts should be computed. In the first iteration, - the required times are set to very large number (by NodeCreate) - and the fanout counts are set to the number of fanouts in the AIG. - In the following iterations, the required times are set by the - backward traversal, while the fanouts are estimated approximately. - - If the arrival times of the PI nodes are given, they should be - assigned to the PIs after the cuts are computed and before this - procedure is called for the first time.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_MappingMatches( Fpga_Man_t * p, int fDelayOriented ) -{ - ProgressBar * pProgress; - Fpga_Node_t * pNode; - int i, nNodes; - - // assign the arrival times of the PIs - for ( i = 0; i < p->nInputs; i++ ) - p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i]; - - // match LUTs with nodes in the topological order - nNodes = p->vAnds->nSize; - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - for ( i = 0; i < nNodes; i++ ) - { - pNode = p->vAnds->pArray[i]; - if ( !Fpga_NodeIsAnd( pNode ) ) - continue; - // skip a secondary node - if ( pNode->pRepr ) - continue; - // match the node - Fpga_MatchNode( p, pNode, fDelayOriented ); - Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); - } - Extra_ProgressBarStop( pProgress ); -/* - if ( !fDelayOriented ) - { - float Area = 0.0; - for ( i = 0; i < p->nOutputs; i++ ) - { - printf( "%5.2f ", Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow ); - Area += Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow; - } - printf( "\nTotal = %5.2f\n", Area ); - } -*/ - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes the best matching for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_MatchNode( Fpga_Man_t * p, Fpga_Node_t * pNode, int fDelayOriented ) -{ - Fpga_Cut_t * pCut, * pCutBestOld; - int clk; - // make sure that at least one cut other than the trivial is present - if ( pNode->pCuts->pNext == NULL ) - { - printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); - return 0; - } - - // estimate the fanouts of the node - if ( pNode->aEstFanouts < 0 ) - pNode->aEstFanouts = (float)pNode->nRefs; - else - pNode->aEstFanouts = (float)((2.0 * pNode->aEstFanouts + pNode->nRefs) / 3.0); -// pNode->aEstFanouts = (float)pNode->nRefs; - - pCutBestOld = pNode->pCutBest; - pNode->pCutBest = NULL; - for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) - { - // compute the arrival time of the cut and its area flow -clk = clock(); - Fpga_CutGetParameters( p, pCut ); -//p->time2 += clock() - clk; - // drop the cut if it does not meet the required times - if ( Fpga_FloatMoreThan(p, pCut->tArrival, pNode->tRequired) ) - continue; - // if no cut is assigned, use the current one - if ( pNode->pCutBest == NULL ) - { - pNode->pCutBest = pCut; - continue; - } - // choose the best cut using one of the two criteria: - // (1) delay oriented mapping (first traversal), delay first, area-flow as a tie-breaker - // (2) area recovery (subsequent traversals), area-flow first, delay as a tie-breaker - if ( (fDelayOriented && - (Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival) || - Fpga_FloatEqual(p, pNode->pCutBest->tArrival, pCut->tArrival) && Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) )) || - (!fDelayOriented && - (Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || - Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival))) ) - { - pNode->pCutBest = pCut; - } - } - - // make sure the match is found - if ( pNode->pCutBest == NULL ) - { - if ( pCutBestOld == NULL ) - { -// printf( "\nError: Could not match a node in the object graph.\n" ); - return 0; - } - pNode->pCutBest = pCutBestOld; - } - return 1; -} - - - - - -/**Function************************************************************* - - Synopsis [Finds the best area assignment of LUTs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_MappingMatchesArea( Fpga_Man_t * p ) -{ - ProgressBar * pProgress; - Fpga_Node_t * pNode; - int i, nNodes; - - // assign the arrival times of the PIs - for ( i = 0; i < p->nInputs; i++ ) - p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i]; - - // match LUTs with nodes in the topological order - nNodes = p->vAnds->nSize; - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - for ( i = 0; i < nNodes; i++ ) - { - pNode = p->vAnds->pArray[i]; - if ( !Fpga_NodeIsAnd( pNode ) ) - continue; - // skip a secondary node - if ( pNode->pRepr ) - continue; - // match the node - Fpga_MatchNodeArea( p, pNode ); - Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); - } - Extra_ProgressBarStop( pProgress ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Finds the best area assignment of LUTs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_MappingMatchesAreaArray( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ) -{ - Fpga_Node_t * pNode; - int i; - - // match LUTs with nodes in the topological order - for ( i = 0; i < vNodes->nSize; i++ ) - { - pNode = vNodes->pArray[i]; - if ( !Fpga_NodeIsAnd( pNode ) ) - continue; - // skip a secondary node - if ( pNode->pRepr ) - continue; - // match the node - if ( !Fpga_MatchNodeArea( p, pNode ) ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes the best matching for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_MatchNodeArea( Fpga_Man_t * p, Fpga_Node_t * pNode ) -{ - Fpga_Cut_t * pCut, * pCutBestOld; - float aAreaCutBest; - int clk; - // make sure that at least one cut other than the trivial is present - if ( pNode->pCuts->pNext == NULL ) - { - printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); - return 0; - } - - // remember the old cut - pCutBestOld = pNode->pCutBest; - // deref the old cut - if ( pNode->nRefs ) - aAreaCutBest = Fpga_CutDeref( p, pNode, pNode->pCutBest, 0 ); - - // search for a better cut - pNode->pCutBest = NULL; - for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) - { - // compute the arrival time of the cut and its area flow -clk = clock(); - pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut ); -//p->time2 += clock() - clk; - // drop the cut if it does not meet the required times - if ( Fpga_FloatMoreThan( p, pCut->tArrival, pNode->tRequired ) ) - continue; - // get the area of this cut - pCut->aFlow = Fpga_CutGetAreaDerefed( p, pCut ); - // if no cut is assigned, use the current one - if ( pNode->pCutBest == NULL ) - { - pNode->pCutBest = pCut; - continue; - } - // choose the best cut as follows: exact area first, delay as a tie-breaker - if ( Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || - Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival) ) - { - pNode->pCutBest = pCut; - } - } - - // make sure the match is found - if ( pNode->pCutBest == NULL ) - { - pNode->pCutBest = pCutBestOld; - // insert the new cut - if ( pNode->nRefs ) - pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 ); -// printf( "\nError: Could not match a node in the object graph.\n" ); - return 0; - } - - // insert the new cut - // make sure the area selected is not worse then the original area - if ( pNode->nRefs ) - { - pNode->pCutBest->aFlow = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 ); -// assert( pNode->pCutBest->aFlow <= aAreaCutBest ); -// assert( pNode->tRequired < FPGA_FLOAT_LARGE ); - } - return 1; -} - - - - -/**Function************************************************************* - - Synopsis [Finds the best area assignment of LUTs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_MappingMatchesSwitch( Fpga_Man_t * p ) -{ - ProgressBar * pProgress; - Fpga_Node_t * pNode; - int i, nNodes; - - // assign the arrival times of the PIs - for ( i = 0; i < p->nInputs; i++ ) - p->pInputs[i]->pCutBest->tArrival = p->pInputArrivals[i]; - - // match LUTs with nodes in the topological order - nNodes = p->vAnds->nSize; - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - for ( i = 0; i < nNodes; i++ ) - { - pNode = p->vAnds->pArray[i]; - if ( !Fpga_NodeIsAnd( pNode ) ) - continue; - // skip a secondary node - if ( pNode->pRepr ) - continue; - // match the node - Fpga_MatchNodeSwitch( p, pNode ); - Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); - } - Extra_ProgressBarStop( pProgress ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes the best matching for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_MatchNodeSwitch( Fpga_Man_t * p, Fpga_Node_t * pNode ) -{ - Fpga_Cut_t * pCut, * pCutBestOld; - float aAreaCutBest; - int clk; - // make sure that at least one cut other than the trivial is present - if ( pNode->pCuts->pNext == NULL ) - { - printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); - return 0; - } - - // remember the old cut - pCutBestOld = pNode->pCutBest; - // deref the old cut - if ( pNode->nRefs ) - aAreaCutBest = Fpga_CutDerefSwitch( p, pNode, pNode->pCutBest, 0 ); - - // search for a better cut - pNode->pCutBest = NULL; - for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) - { - // compute the arrival time of the cut and its area flow -clk = clock(); - pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut ); -//p->time2 += clock() - clk; - // drop the cut if it does not meet the required times - if ( Fpga_FloatMoreThan( p, pCut->tArrival, pNode->tRequired ) ) - continue; - // get the area of this cut - pCut->aFlow = Fpga_CutGetSwitchDerefed( p, pNode, pCut ); - // if no cut is assigned, use the current one - if ( pNode->pCutBest == NULL ) - { - pNode->pCutBest = pCut; - continue; - } - // choose the best cut as follows: exact area first, delay as a tie-breaker - if ( Fpga_FloatMoreThan(p, pNode->pCutBest->aFlow, pCut->aFlow) || - Fpga_FloatEqual(p, pNode->pCutBest->aFlow, pCut->aFlow) && Fpga_FloatMoreThan(p, pNode->pCutBest->tArrival, pCut->tArrival) ) - { - pNode->pCutBest = pCut; - } - } - - // make sure the match is found - if ( pNode->pCutBest == NULL ) - { - pNode->pCutBest = pCutBestOld; - // insert the new cut - if ( pNode->nRefs ) - pNode->pCutBest->aFlow = Fpga_CutRefSwitch( p, pNode, pNode->pCutBest, 0 ); -// printf( "\nError: Could not match a node in the object graph.\n" ); - return 0; - } - - // insert the new cut - // make sure the area selected is not worse then the original area - if ( pNode->nRefs ) - { - pNode->pCutBest->aFlow = Fpga_CutRefSwitch( p, pNode, pNode->pCutBest, 0 ); - assert( pNode->pCutBest->aFlow <= aAreaCutBest + 0.001 ); -// assert( pNode->tRequired < FPGA_FLOAT_LARGE ); - } - return 1; -} - - -#if 0 -/**function************************************************************* - - synopsis [References the cut.] - - description [This procedure is similar to the procedure NodeReclaim.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -void Fpga_Experiment( Fpga_Man_t * p ) -{ - int Counter[10] = {0}; - Fpga_Node_t * pNode; - int i; - - for ( i = 0; i < p->nOutputs; i++ ) - { - pNode = Fpga_Regular(p->pOutputs[i]); - pNode->vFanouts = NULL; - } - - for ( i = 0; i < p->vAnds->nSize; i++ ) - { - pNode = p->vAnds->pArray[i]; - if ( !Fpga_NodeIsAnd( pNode ) ) - continue; - if ( pNode->vFanouts == NULL ) - continue; - if ( pNode->vFanouts->nSize >= 10 ) - continue; - Counter[pNode->vFanouts->nSize]++; - } - - printf( "Fanout stats: " ); - for ( i = 0; i < 10; i++ ) - printf( " %d=%d", i, Counter[i] ); - printf( "\n" ); - printf( "Area before = %4.2f.\n", Fpga_MappingArea(p) ); - - for ( i = 0; i < p->vAnds->nSize; i++ ) - { - Fpga_NodeVec_t * vNodesTfo; - float AreaBefore; - - pNode = p->vAnds->pArray[i]; - if ( !Fpga_NodeIsAnd( pNode ) ) - continue; - if ( pNode->vFanouts == NULL ) - continue; - if ( pNode->vFanouts->nSize != 1 && pNode->vFanouts->nSize != 2 && pNode->vFanouts->nSize != 3 ) - continue; - -// assert( pNode->nRefs > 0 ); - if ( pNode->nRefs == 0 ) - continue; - - AreaBefore = pNode->pCutBest->aFlow; - pNode->pCutBest->aFlow = FPGA_FLOAT_LARGE; - - Fpga_TimeComputeRequiredGlobal( p, 0 ); - - vNodesTfo = Fpga_CollectNodeTfo( p, pNode ); - if ( Fpga_MappingMatchesAreaArray( p, vNodesTfo ) == 0 ) - printf( "attempt failed\n" ); - else - printf( "attempt succeeded\n" ); - Fpga_NodeVecFree( vNodesTfo ); - - pNode->pCutBest->aFlow = AreaBefore; -// break; - } - printf( "Area after = %4.2f.\n", Fpga_MappingArea(p) ); -// printf( "AREA GAIN = %4.2f (%.2f %%)\n", GainTotal, 100.0 * GainTotal / Fpga_MappingArea(p) ); -} - - - -/**function************************************************************* - - synopsis [References the cut.] - - description [This procedure is similar to the procedure NodeReclaim.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -void Fpga_Experiment2( Fpga_Man_t * p ) -{ - int Counter[10] = {0}; - Fpga_Cut_t * ppCutsNew[10]; - Fpga_Cut_t * ppCutsOld[10]; - Fpga_Node_t * pFanout, * pNode; - float Gain, Loss, GainTotal, Area1, Area2; - int i, k; - - for ( i = 0; i < p->nOutputs; i++ ) - { - pNode = Fpga_Regular(p->pOutputs[i]); - pNode->vFanouts = NULL; - } - - for ( i = 0; i < p->vAnds->nSize; i++ ) - { - pNode = p->vAnds->pArray[i]; - if ( !Fpga_NodeIsAnd( pNode ) ) - continue; - if ( pNode->vFanouts == NULL ) - continue; - if ( pNode->vFanouts->nSize >= 10 ) - continue; - Counter[pNode->vFanouts->nSize]++; - } - - printf( "Fanout stats: " ); - for ( i = 0; i < 10; i++ ) - printf( " %d=%d", i, Counter[i] ); - printf( "\n" ); - printf( "Area before = %4.2f.\n", Fpga_MappingArea(p) ); - - GainTotal = 0; - for ( i = 0; i < p->vAnds->nSize; i++ ) - { - pNode = p->vAnds->pArray[i]; - if ( !Fpga_NodeIsAnd( pNode ) ) - continue; - if ( pNode->vFanouts == NULL ) - continue; - if ( pNode->vFanouts->nSize != 2 )//&& pNode->vFanouts->nSize != 2 && pNode->vFanouts->nSize != 3 ) - continue; - - assert( pNode->nRefs > 0 ); - - // for all fanouts, find the best cut without this node - for ( k = 0; k < pNode->vFanouts->nSize; k++ ) - { - pFanout = pNode->vFanouts->pArray[k]; - ppCutsOld[k] = pFanout->pCutBest; - ppCutsNew[k] = Fpga_MappingAreaWithoutNode( p, pFanout, pNode ); - if ( ppCutsNew[k] == NULL ) - break; - } - if ( k != pNode->vFanouts->nSize ) - { - printf( "Node %4d: Skipped.\n", pNode->Num ); - continue; - } - - - // compute the area after replacing all the cuts - Gain = 0; - for ( k = 0; k < pNode->vFanouts->nSize; k++ ) - { - pFanout = pNode->vFanouts->pArray[k]; - // deref old cut - Area1 = Fpga_MatchAreaDeref( p, ppCutsOld[k] ); - // assign new cut - pFanout->pCutBest = ppCutsNew[k]; - // ref new cut - Area2 = Fpga_MatchAreaRef( p, ppCutsNew[k] ); - // compute the gain - Gain += Area1 - Area2; - } - - printf( "%d ", pNode->nRefs ); - - // undo the whole thing - Loss = 0; - for ( k = 0; k < pNode->vFanouts->nSize; k++ ) - { - pFanout = pNode->vFanouts->pArray[k]; - // deref old cut - Area1 = Fpga_MatchAreaDeref( p, ppCutsNew[k] ); - // assign new cut - pFanout->pCutBest = ppCutsOld[k]; - // ref new cut - Area2 = Fpga_MatchAreaRef( p, ppCutsOld[k] ); - // compute the gain - Loss += Area2 - Area1; - } - assert( Gain == Loss ); - - - printf( "Node %4d: Fanouts = %d. Cut area = %4.2f. Gain = %4.2f.\n", - pNode->Num, pNode->nRefs, pNode->pCutBest->aFlow, Gain ); - - if ( Gain > 0 ) - GainTotal += Gain; - } - printf( "Area after = %4.2f.\n", Fpga_MappingArea(p) ); - printf( "AREA GAIN = %4.2f (%.2f %%)\n", GainTotal, 100.0 * GainTotal / Fpga_MappingArea(p) ); -} - - -/**function************************************************************* - - synopsis [Computes the loss of area when node is not allowed.] - - description [Returning FPGA_FLOAT_LARGE means it does not exist.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -Fpga_Cut_t * Fpga_MappingAreaWithoutNode( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Node_t * pNodeNo ) -{ - Fpga_Cut_t * pCut, * pCutBestOld, * pCutRes; - float aAreaCutBest; - int i, clk; - // make sure that at least one cut other than the trivial is present - if ( pNode->pCuts->pNext == NULL ) - { - printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); - return 0; - } - - assert( pNode->nRefs > 0 ); - - // remember the old cut - pCutBestOld = pNode->pCutBest; - // deref the old cut - aAreaCutBest = Fpga_MatchAreaDeref( p, pNode->pCutBest ); - - // search for a better cut - pNode->pCutBest = NULL; - for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) - { - // compute the arrival time of the cut and its area flow -clk = clock(); - Fpga_MatchCutGetArrTime( p, pCut ); -//p->time2 += clock() - clk; - // drop the cut if it does not meet the required times - if ( pCut->tArrival > pNode->tRequired ) - continue; - - // skip the cut if it contains the no-node - for ( i = 0; i < pCut->nLeaves; i++ ) - if ( pCut->ppLeaves[i] == pNodeNo ) - break; - if ( i != pCut->nLeaves ) - continue; - - // get the area of this cut - pCut->aFlow = Fpga_MatchAreaCount( p, pCut ); - // if no cut is assigned, use the current one - if ( pNode->pCutBest == NULL ) - { - pNode->pCutBest = pCut; - continue; - } - // choose the best cut as follows: exact area first, delay as a tie-breaker - if ( pNode->pCutBest->aFlow > pCut->aFlow || - pNode->pCutBest->aFlow == pCut->aFlow && pNode->pCutBest->tArrival > pCut->tArrival ) - { - pNode->pCutBest = pCut; - } - } - - // make sure the match is found - if ( pNode->pCutBest == NULL ) - { - pNode->pCutBest = pCutBestOld; - // insert the new cut - pNode->pCutBest->aFlow = Fpga_MatchAreaRef( p, pNode->pCutBest ); - return NULL; - } - - pCutRes = pNode->pCutBest; - pNode->pCutBest = pCutBestOld; - - // insert the new cut - pNode->pCutBest->aFlow = Fpga_MatchAreaRef( p, pNode->pCutBest ); - - // make sure the area selected is not worse then the original area - assert( pNode->pCutBest->aFlow == aAreaCutBest ); - assert( pNode->tRequired < FPGA_FLOAT_LARGE ); - return pCutRes; -} - -#endif - - -/**function************************************************************* - - synopsis [Performs area minimization using a heuristic algorithm.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Fpga_FindBestNode( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes, Fpga_Node_t ** ppNode, Fpga_Cut_t ** ppCutBest ) -{ - Fpga_Node_t * pNode; - Fpga_Cut_t * pCut; - float Gain, CutArea1, CutArea2, CutArea3; - int i; - - Gain = 0; - for ( i = 0; i < vNodes->nSize; i++ ) - { - pNode = vNodes->pArray[i]; - // deref the current cut - CutArea1 = Fpga_CutDeref( p, pNode, pNode->pCutBest, 0 ); - - // ref all the cuts - for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) - { - if ( pCut == pNode->pCutBest ) - continue; - if ( pCut->tArrival > pNode->tRequired ) - continue; - - CutArea2 = Fpga_CutGetAreaDerefed( p, pCut ); - if ( Gain < CutArea1 - CutArea2 ) - { - *ppNode = pNode; - *ppCutBest = pCut; - Gain = CutArea1 - CutArea2; - } - } - // ref the old cut - CutArea3 = Fpga_CutRef( p, pNode, pNode->pCutBest, 0 ); - assert( CutArea1 == CutArea3 ); - } - if ( Gain == 0 ) - printf( "Returning no gain.\n" ); - - return Gain; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/map/fpga/fpgaSwitch.c b/src/map/fpga/fpgaSwitch.c deleted file mode 100644 index c93e0de4..00000000 --- a/src/map/fpga/fpgaSwitch.c +++ /dev/null @@ -1,151 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaSwitch.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: fpgaSwitch.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Fpga_CutGetSwitchDerefed( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ) -{ - float aResult, aResult2; - aResult2 = Fpga_CutRefSwitch( pMan, pNode, pCut, 0 ); - aResult = Fpga_CutDerefSwitch( pMan, pNode, pCut, 0 ); -// assert( aResult == aResult2 ); - return aResult; -} - -/**function************************************************************* - - synopsis [References the cut.] - - description [This procedure is similar to the procedure NodeReclaim.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Fpga_CutRefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) -{ - Fpga_Node_t * pNodeChild; - float aArea; - int i; - // start the area of this cut - aArea = pNode->Switching; - if ( pCut->nLeaves == 1 ) - return aArea; - // go through the children - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pNodeChild = pCut->ppLeaves[i]; - assert( pNodeChild->nRefs >= 0 ); - if ( pNodeChild->nRefs++ > 0 ) - continue; - aArea += Fpga_CutRefSwitch( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); - } - return aArea; -} - -/**function************************************************************* - - synopsis [Dereferences the cut.] - - description [This procedure is similar to the procedure NodeRecusiveDeref.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Fpga_CutDerefSwitch( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) -{ - Fpga_Node_t * pNodeChild; - float aArea; - int i; - // start the area of this cut - aArea = pNode->Switching; - if ( pCut->nLeaves == 1 ) - return aArea; - // go through the children - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pNodeChild = pCut->ppLeaves[i]; - assert( pNodeChild->nRefs > 0 ); - if ( --pNodeChild->nRefs > 0 ) - continue; - aArea += Fpga_CutDerefSwitch( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); - } - return aArea; -} - -/**Function************************************************************* - - Synopsis [Computes the array of mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Fpga_MappingGetSwitching( Fpga_Man_t * pMan, Fpga_NodeVec_t * vMapping ) -{ - Fpga_Node_t * pNode; - float Switch; - int i; - Switch = 0.0; - for ( i = 0; i < vMapping->nSize; i++ ) - { - pNode = vMapping->pArray[i]; - // at least one phase has the best cut assigned - assert( !Fpga_NodeIsAnd(pNode) || pNode->pCutBest != NULL ); - // at least one phase is used in the mapping - assert( pNode->nRefs > 0 ); - // compute the array due to the supergate - Switch += pNode->Switching; - } - // add buffer for each CO driven by a CI - for ( i = 0; i < pMan->nOutputs; i++ ) - if ( Fpga_NodeIsVar(pMan->pOutputs[i]) && !Fpga_IsComplement(pMan->pOutputs[i]) ) - Switch += pMan->pOutputs[i]->Switching; - return Switch; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/fpga/fpgaTime.c b/src/map/fpga/fpgaTime.c deleted file mode 100644 index 879cad4d..00000000 --- a/src/map/fpga/fpgaTime.c +++ /dev/null @@ -1,262 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaTime.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Technology mapping for variable-size-LUT FPGAs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaTime.c,v 1.1 2005/01/23 06:59:42 alanmi Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the arrival times of the cut.] - - Description [Computes the maximum arrival time of the cut leaves and - adds the delay of the LUT.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Fpga_TimeCutComputeArrival( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) -{ - int i; - float tArrival; - tArrival = -FPGA_FLOAT_LARGE; - for ( i = 0; i < pCut->nLeaves; i++ ) - if ( tArrival < pCut->ppLeaves[i]->pCutBest->tArrival ) - tArrival = pCut->ppLeaves[i]->pCutBest->tArrival; - tArrival += pMan->pLutLib->pLutDelays[pCut->nLeaves][0]; - return tArrival; -} - -/**Function************************************************************* - - Synopsis [Computes the arrival times of the cut recursively.] - - Description [When computing the arrival time for the previously unused - cuts, their arrival time may be incorrect because their fanins have - incorrect arrival time. This procedure is called to fix this problem.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Fpga_TimeCutComputeArrival_rec( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) -{ - int i; - for ( i = 0; i < pCut->nLeaves; i++ ) - if ( pCut->ppLeaves[i]->nRefs == 0 ) - Fpga_TimeCutComputeArrival_rec( pMan, pCut->ppLeaves[i]->pCutBest ); - return Fpga_TimeCutComputeArrival( pMan, pCut ); -} - -/**Function************************************************************* - - Synopsis [Computes the maximum arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Fpga_TimeComputeArrivalMax( Fpga_Man_t * p ) -{ - float fRequired; - int i; - if ( p->fLatchPaths && p->nLatches == 0 ) - { - printf( "Delay optimization of latch path is not performed because there is no latches.\n" ); - p->fLatchPaths = 0; - } - // get the critical PO arrival time - fRequired = -FPGA_FLOAT_LARGE; - if ( p->fLatchPaths ) - { - for ( i = p->nOutputs - p->nLatches; i < p->nOutputs; i++ ) - { - if ( Fpga_NodeIsConst(p->pOutputs[i]) ) - continue; - fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); -// printf( " %5.1f", Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); - } -// printf( "Required latches = %5.1f\n", fRequired ); - } - else - { - for ( i = 0; i < p->nOutputs; i++ ) - { - if ( Fpga_NodeIsConst(p->pOutputs[i]) ) - continue; - fRequired = FPGA_MAX( fRequired, Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); -// printf( " %5.1f", Fpga_Regular(p->pOutputs[i])->pCutBest->tArrival ); - } -// printf( "Required outputs = %5.1f\n", fRequired ); - } - return fRequired; -} - -/**Function************************************************************* - - Synopsis [Computes the required times of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_TimeComputeRequiredGlobal( Fpga_Man_t * p, int fFirstTime ) -{ - p->fRequiredGlo = Fpga_TimeComputeArrivalMax( p ); - // update the required times according to the target - if ( p->DelayTarget != -1 ) - { - if ( p->fRequiredGlo > p->DelayTarget + p->fEpsilon ) - { - if ( fFirstTime ) - printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->DelayTarget ); - } - else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon ) - { - if ( fFirstTime ) - printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget ); - p->fRequiredGlo = p->DelayTarget; - } - } - Fpga_TimeComputeRequired( p, p->fRequiredGlo ); -} - -/**Function************************************************************* - - Synopsis [Computes the required times of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_TimeComputeRequired( Fpga_Man_t * p, float fRequired ) -{ - int i; - // clean the required times and the fanout counts for all nodes - for ( i = 0; i < p->vAnds->nSize; i++ ) - p->vAnds->pArray[i]->tRequired = FPGA_FLOAT_LARGE; - // set the required times for the POs - if ( p->fLatchPaths ) - for ( i = p->nOutputs - p->nLatches; i < p->nOutputs; i++ ) - Fpga_Regular(p->pOutputs[i])->tRequired = fRequired; - else - for ( i = 0; i < p->nOutputs; i++ ) - Fpga_Regular(p->pOutputs[i])->tRequired = fRequired; - // collect nodes reachable from POs in the DFS order through the best cuts - Fpga_TimePropagateRequired( p, p->vMapping ); -/* - { - int Counter = 0; - for ( i = 0; i < p->vAnds->nSize; i++ ) - if ( p->vAnds->pArray[i]->tRequired > FPGA_FLOAT_LARGE - 100 ) - Counter++; - printf( "The number of nodes with large required times = %d.\n", Counter ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Computes the required times of the given nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_TimePropagateRequired( Fpga_Man_t * p, Fpga_NodeVec_t * vNodes ) -{ - Fpga_Node_t * pNode, * pChild; - float fRequired; - int i, k; - - // sorts the nodes in the decreasing order of levels -// Fpga_MappingSortByLevel( p, vNodes, 0 ); - // the nodes area already sorted in Fpga_MappingSetRefsAndArea() - - // go through the nodes in the reverse topological order - for ( k = 0; k < vNodes->nSize; k++ ) - { - pNode = vNodes->pArray[k]; - if ( !Fpga_NodeIsAnd(pNode) ) - continue; - // get the required time for children - fRequired = pNode->tRequired - p->pLutLib->pLutDelays[pNode->pCutBest->nLeaves][0]; - // update the required time of the children - for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) - { - pChild = pNode->pCutBest->ppLeaves[i]; - pChild->tRequired = FPGA_MIN( pChild->tRequired, fRequired ); - } - } -} - - - -/**Function************************************************************* - - Synopsis [Computes the required times of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_TimePropagateArrival( Fpga_Man_t * p ) -{ - Fpga_Node_t * pNode; - Fpga_Cut_t * pCut; - int i; - - // clean the required times and the fanout counts for all nodes - for ( i = 0; i < p->vAnds->nSize; i++ ) - { - pNode = p->vAnds->pArray[i]; - for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) - pCut->tArrival = Fpga_TimeCutComputeArrival( p, pCut ); - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/fpga/fpgaTruth.c b/src/map/fpga/fpgaTruth.c deleted file mode 100644 index e3eb487f..00000000 --- a/src/map/fpga/fpgaTruth.c +++ /dev/null @@ -1,166 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaTruth.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Technology mapping for variable-size-LUT FPGAs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaTruth.c,v 1.4 2005/01/23 06:59:42 alanmi Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" -#include "cudd.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Recursively derives the truth table for the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Fpga_TruthsCutBdd_rec( DdManager * dd, Fpga_Cut_t * pCut, Fpga_NodeVec_t * vVisited ) -{ - DdNode * bFunc, * bFunc0, * bFunc1; - assert( !Fpga_IsComplement(pCut) ); - // if the cut is visited, return the result - if ( pCut->uSign ) - return (DdNode *)pCut->uSign; - // compute the functions of the children - bFunc0 = Fpga_TruthsCutBdd_rec( dd, Fpga_CutRegular(pCut->pOne), vVisited ); Cudd_Ref( bFunc0 ); - bFunc0 = Cudd_NotCond( bFunc0, Fpga_CutIsComplement(pCut->pOne) ); - bFunc1 = Fpga_TruthsCutBdd_rec( dd, Fpga_CutRegular(pCut->pTwo), vVisited ); Cudd_Ref( bFunc1 ); - bFunc1 = Cudd_NotCond( bFunc1, Fpga_CutIsComplement(pCut->pTwo) ); - // get the function of the cut - bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc ); - bFunc = Cudd_NotCond( bFunc, pCut->Phase ); - Cudd_RecursiveDeref( dd, bFunc0 ); - Cudd_RecursiveDeref( dd, bFunc1 ); - assert( pCut->uSign == 0 ); - pCut->uSign = (unsigned)bFunc; - // add this cut to the visited list - Fpga_NodeVecPush( vVisited, (Fpga_Node_t *)pCut ); - return bFunc; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table for one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Fpga_TruthsCutBdd( void * dd, Fpga_Cut_t * pCut ) -{ - Fpga_NodeVec_t * vVisited; - DdNode * bFunc; - int i; - assert( pCut->nLeaves > 1 ); - // set the leaf variables - for ( i = 0; i < pCut->nLeaves; i++ ) - pCut->ppLeaves[i]->pCuts->uSign = (unsigned)Cudd_bddIthVar( dd, i ); - // recursively compute the function - vVisited = Fpga_NodeVecAlloc( 10 ); - bFunc = Fpga_TruthsCutBdd_rec( dd, pCut, vVisited ); Cudd_Ref( bFunc ); - // clean the intermediate BDDs - for ( i = 0; i < pCut->nLeaves; i++ ) - pCut->ppLeaves[i]->pCuts->uSign = 0; - for ( i = 0; i < vVisited->nSize; i++ ) - { - pCut = (Fpga_Cut_t *)vVisited->pArray[i]; - Cudd_RecursiveDeref( dd, (DdNode*)pCut->uSign ); - pCut->uSign = 0; - } -// printf( "%d ", vVisited->nSize ); - Fpga_NodeVecFree( vVisited ); - Cudd_Deref( bFunc ); - return bFunc; -} - - -/**Function************************************************************* - - Synopsis [Recursively derives the truth table for the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_CutVolume_rec( Fpga_Cut_t * pCut, Fpga_NodeVec_t * vVisited ) -{ - assert( !Fpga_IsComplement(pCut) ); - if ( pCut->fMark ) - return; - pCut->fMark = 1; - Fpga_CutVolume_rec( Fpga_CutRegular(pCut->pOne), vVisited ); - Fpga_CutVolume_rec( Fpga_CutRegular(pCut->pTwo), vVisited ); - Fpga_NodeVecPush( vVisited, (Fpga_Node_t *)pCut ); -} - -/**Function************************************************************* - - Synopsis [Derives the truth table for one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CutVolume( Fpga_Cut_t * pCut ) -{ - Fpga_NodeVec_t * vVisited; - int Volume, i; - assert( pCut->nLeaves > 1 ); - // set the leaf variables - for ( i = 0; i < pCut->nLeaves; i++ ) - pCut->ppLeaves[i]->pCuts->fMark = 1; - // recursively compute the function - vVisited = Fpga_NodeVecAlloc( 10 ); - Fpga_CutVolume_rec( pCut, vVisited ); - // clean the marks - for ( i = 0; i < pCut->nLeaves; i++ ) - pCut->ppLeaves[i]->pCuts->fMark = 0; - for ( i = 0; i < vVisited->nSize; i++ ) - { - pCut = (Fpga_Cut_t *)vVisited->pArray[i]; - pCut->fMark = 0; - } - Volume = vVisited->nSize; - printf( "%d ", Volume ); - Fpga_NodeVecFree( vVisited ); - return Volume; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/fpga/fpgaUtils.c b/src/map/fpga/fpgaUtils.c deleted file mode 100644 index b951fd8f..00000000 --- a/src/map/fpga/fpgaUtils.c +++ /dev/null @@ -1,986 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaUtils.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Technology mapping for variable-size-LUT FPGAs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaUtils.c,v 1.3 2004/07/06 04:55:58 alanmi Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define FPGA_CO_LIST_SIZE 5 - -static void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv ); -static void Fpga_MappingDfsCuts_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes ); -static int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 ); -static void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax ); -static void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes ); -static int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo ); -static Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan ); -static Fpga_Man_t * s_pMan = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv ) -{ - Fpga_NodeVec_t * vNodes;//, * vNodesCo; - Fpga_Node_t * pNode; - int i; - // collect the CO nodes by level -// vNodesCo = Fpga_MappingOrderCosByLevel( pMan ); - // start the array - vNodes = Fpga_NodeVecAlloc( 100 ); - // collect the PIs - for ( i = 0; i < pMan->nInputs; i++ ) - { - pNode = pMan->pInputs[i]; - Fpga_NodeVecPush( vNodes, pNode ); - pNode->fMark0 = 1; - } - // perform the traversal - for ( i = 0; i < pMan->nOutputs; i++ ) - Fpga_MappingDfs_rec( Fpga_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv ); -// for ( i = vNodesCo->nSize - 1; i >= 0 ; i-- ) -// for ( pNode = vNodesCo->pArray[i]; pNode; pNode = (Fpga_Node_t *)pNode->pData0 ) -// Fpga_MappingDfs_rec( pNode, vNodes, fCollectEquiv ); - // clean the node marks - for ( i = 0; i < vNodes->nSize; i++ ) - vNodes->pArray[i]->fMark0 = 0; -// for ( i = 0; i < pMan->nOutputs; i++ ) -// Fpga_MappingUnmark_rec( Fpga_Regular(pMan->pOutputs[i]) ); -// Fpga_NodeVecFree( vNodesCo ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv ) -{ - assert( !Fpga_IsComplement(pNode) ); - if ( pNode->fMark0 ) - return; - // visit the transitive fanin - if ( Fpga_NodeIsAnd(pNode) ) - { - Fpga_MappingDfs_rec( Fpga_Regular(pNode->p1), vNodes, fCollectEquiv ); - Fpga_MappingDfs_rec( Fpga_Regular(pNode->p2), vNodes, fCollectEquiv ); - } - // visit the equivalent nodes - if ( fCollectEquiv && pNode->pNextE ) - Fpga_MappingDfs_rec( pNode->pNextE, vNodes, fCollectEquiv ); - // make sure the node is not visited through the equivalent nodes - assert( pNode->fMark0 == 0 ); - // mark the node as visited - pNode->fMark0 = 1; - // add the node to the list - Fpga_NodeVecPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_NodeVec_t * Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv ) -{ - Fpga_NodeVec_t * vNodes; - int i; - // perform the traversal - vNodes = Fpga_NodeVecAlloc( 200 ); - for ( i = 0; i < nNodes; i++ ) - Fpga_MappingDfs_rec( ppNodes[i], vNodes, fEquiv ); - for ( i = 0; i < vNodes->nSize; i++ ) - vNodes->pArray[i]->fMark0 = 0; - return vNodes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Fpga_MappingGetAreaFlow( Fpga_Man_t * p ) -{ - float aFlowFlowTotal = 0; - int i; - for ( i = 0; i < p->nOutputs; i++ ) - { - if ( Fpga_NodeIsConst(p->pOutputs[i]) ) - continue; - aFlowFlowTotal += Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow; - } - return aFlowFlowTotal; -} - -/**Function************************************************************* - - Synopsis [Computes the area of the current mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Fpga_MappingArea( Fpga_Man_t * pMan ) -{ - Fpga_Node_t * pNode; - float aTotal; - int i; - // perform the traversal - aTotal = 0; - for ( i = 0; i < pMan->vMapping->nSize; i++ ) - { - pNode = pMan->vMapping->pArray[i]; - aTotal += pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves]; - } - return aTotal; -} - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Fpga_MappingArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes ) -{ - float aArea; - int i; - assert( !Fpga_IsComplement(pNode) ); - if ( !Fpga_NodeIsAnd(pNode) ) - return 0; - if ( pNode->fMark0 ) - return 0; - assert( pNode->pCutBest != NULL ); - // visit the transitive fanin of the selected cut - aArea = 0; - for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) - aArea += Fpga_MappingArea_rec( pMan, pNode->pCutBest->ppLeaves[i], vNodes ); - // make sure the node is not visited through the fanin nodes - assert( pNode->fMark0 == 0 ); - // mark the node as visited - pNode->fMark0 = 1; - // add the node to the list - aArea += pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves]; - // add the node to the list - Fpga_NodeVecPush( vNodes, pNode ); - return aArea; -} - -/**Function************************************************************* - - Synopsis [Computes the area of the current mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Fpga_MappingAreaTrav( Fpga_Man_t * pMan ) -{ - Fpga_NodeVec_t * vNodes; - float aTotal; - int i; - // perform the traversal - aTotal = 0; - vNodes = Fpga_NodeVecAlloc( 100 ); - for ( i = 0; i < pMan->nOutputs; i++ ) - aTotal += Fpga_MappingArea_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), vNodes ); - for ( i = 0; i < vNodes->nSize; i++ ) - vNodes->pArray[i]->fMark0 = 0; - Fpga_NodeVecFree( vNodes ); - return aTotal; -} - - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Fpga_MappingSetRefsAndArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Node_t ** ppStore ) -{ - float aArea; - int i; - assert( !Fpga_IsComplement(pNode) ); - if ( pNode->nRefs++ ) - return 0; - if ( !Fpga_NodeIsAnd(pNode) ) - return 0; - assert( pNode->pCutBest != NULL ); - // store the node in the structure by level - pNode->pData0 = (char *)ppStore[pNode->Level]; - ppStore[pNode->Level] = pNode; - // visit the transitive fanin of the selected cut - aArea = pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves]; - for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) - aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode->pCutBest->ppLeaves[i], ppStore ); - return aArea; -} - -/**Function************************************************************* - - Synopsis [Sets the correct reference counts for the mapping.] - - Description [Collects the nodes in reverse topological order - and places in them in array pMan->vMapping.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan ) -{ - Fpga_Node_t * pNode, ** ppStore; - float aArea; - int i, LevelMax; - - // clean all references - for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) - pMan->vNodesAll->pArray[i]->nRefs = 0; - - // allocate place to store the nodes - LevelMax = Fpga_MappingMaxLevel( pMan ); - ppStore = ALLOC( Fpga_Node_t *, LevelMax + 1 ); - memset( ppStore, 0, sizeof(Fpga_Node_t *) * (LevelMax + 1) ); - - // collect nodes reachable from POs in the DFS order through the best cuts - aArea = 0; - for ( i = 0; i < pMan->nOutputs; i++ ) - { - pNode = Fpga_Regular(pMan->pOutputs[i]); - if ( pNode == pMan->pConst1 ) - continue; - aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode, ppStore ); - pNode->nRefs++; - } - - // reconnect the nodes in reverse topological order - pMan->vMapping->nSize = 0; - for ( i = LevelMax; i >= 0; i-- ) - for ( pNode = ppStore[i]; pNode; pNode = (Fpga_Node_t *)pNode->pData0 ) - Fpga_NodeVecPush( pMan->vMapping, pNode ); - free( ppStore ); - return aArea; -} - - -/**Function************************************************************* - - Synopsis [Compares the outputs by their arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 ) -{ - Fpga_Node_t * pNode1 = Fpga_Regular(*ppNode1); - Fpga_Node_t * pNode2 = Fpga_Regular(*ppNode2); - float Arrival1 = pNode1->pCutBest? pNode1->pCutBest->tArrival : 0; - float Arrival2 = pNode2->pCutBest? pNode2->pCutBest->tArrival : 0; - if ( Arrival1 < Arrival2 ) - return -1; - if ( Arrival1 > Arrival2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Finds given number of latest arriving COs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax ) -{ - int nNodes, i, k, v; - assert( p->nOutputs >= nNodesMax ); - pNodes[0] = 0; - nNodes = 1; - for ( i = 1; i < p->nOutputs; i++ ) - { - for ( k = nNodes - 1; k >= 0; k-- ) - if ( Fpga_MappingCompareOutputDelay( &p->pOutputs[pNodes[k]], &p->pOutputs[i] ) >= 0 ) - break; - if ( k == nNodesMax - 1 ) - continue; - if ( nNodes < nNodesMax ) - nNodes++; - for ( v = nNodes - 1; v > k+1; v-- ) - pNodes[v] = pNodes[v-1]; - pNodes[k+1] = i; - } -} - -/**Function************************************************************* - - Synopsis [Prints a bunch of latest arriving outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p ) -{ - Fpga_Node_t * pNode; - int pSorted[FPGA_CO_LIST_SIZE]; - int fCompl, Limit, MaxNameSize, i; - - // determine the number of nodes to print - Limit = (p->nOutputs > FPGA_CO_LIST_SIZE)? FPGA_CO_LIST_SIZE : p->nOutputs; - - // determine the order - Fpga_MappingFindLatest( p, pSorted, Limit ); - - // determine max size of the node's name - MaxNameSize = 0; - for ( i = 0; i < Limit; i++ ) - if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) ) - MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]); - - // print the latest outputs - for ( i = 0; i < Limit; i++ ) - { - // get the i-th latest output - pNode = Fpga_Regular(p->pOutputs[pSorted[i]]); - fCompl = Fpga_IsComplement(p->pOutputs[pSorted[i]]); - // print out the best arrival time - printf( "Output %-*s : ", MaxNameSize + 3, p->ppOutputNames[pSorted[i]] ); - printf( "Delay = %8.2f ", (double)pNode->pCutBest->tArrival ); - if ( fCompl ) - printf( "NEG" ); - else - printf( "POS" ); - printf( "\n" ); - } -} - - -/**Function************************************************************* - - Synopsis [Sets up the truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_MappingSetupTruthTables( unsigned uTruths[][2] ) -{ - int m, v; - // set up the truth tables - for ( m = 0; m < 32; m++ ) - for ( v = 0; v < 5; v++ ) - if ( m & (1 << v) ) - uTruths[v][0] |= (1 << m); - // make adjustments for the case of 6 variables - for ( v = 0; v < 5; v++ ) - uTruths[v][1] = uTruths[v][0]; - uTruths[5][0] = 0; - uTruths[5][1] = FPGA_FULL; -} - -/**Function************************************************************* - - Synopsis [Sets up the mask.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax ) -{ - if ( nVarsMax == 6 ) - uMask[0] = uMask[1] = FPGA_FULL; - else - { - uMask[0] = FPGA_MASK(1 << nVarsMax); - uMask[1] = 0; - } -} - -/**Function************************************************************* - - Synopsis [Verify one useful property.] - - Description [This procedure verifies one useful property. After - the FRAIG construction with choice nodes is over, each primary node - should have fanins that are primary nodes. The primary nodes is the - one that does not have pNode->pRepr set to point to another node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_ManCheckConsistency( Fpga_Man_t * p ) -{ - Fpga_Node_t * pNode; - Fpga_NodeVec_t * pVec; - int i; - pVec = Fpga_MappingDfs( p, 0 ); - for ( i = 0; i < pVec->nSize; i++ ) - { - pNode = pVec->pArray[i]; - if ( Fpga_NodeIsVar(pNode) ) - { - if ( pNode->pRepr ) - printf( "Primary input %d is a secondary node.\n", pNode->Num ); - } - else if ( Fpga_NodeIsConst(pNode) ) - { - if ( pNode->pRepr ) - printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); - } - else - { - if ( pNode->pRepr ) - printf( "Internal node %d is a secondary node.\n", pNode->Num ); - if ( Fpga_Regular(pNode->p1)->pRepr ) - printf( "Internal node %d has first fanin that is a secondary node.\n", pNode->Num ); - if ( Fpga_Regular(pNode->p2)->pRepr ) - printf( "Internal node %d has second fanin that is a secondary node.\n", pNode->Num ); - } - } - Fpga_NodeVecFree( pVec ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Compares the supergates by their level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CompareNodesByLevelDecreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 ) -{ - if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level ) - return -1; - if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Compares the supergates by their level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CompareNodesByLevelIncreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 ) -{ - if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level ) - return -1; - if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Orders the nodes in the decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes, int fIncreasing ) -{ - if ( fIncreasing ) - qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *), - (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelIncreasing ); - else - qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *), - (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelDecreasing ); -// assert( Fpga_CompareNodesByLevel( vNodes->pArray, vNodes->pArray + vNodes->nSize - 1 ) <= 0 ); -} - -/**Function************************************************************* - - Synopsis [Computes the limited DFS ordering for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_NodeVec_t * Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels ) -{ - Fpga_NodeVec_t * vNodes; - int i; - // perform the traversal - vNodes = Fpga_NodeVecAlloc( 100 ); - Fpga_DfsLim_rec( pNode, nLevels, vNodes ); - for ( i = 0; i < vNodes->nSize; i++ ) - vNodes->pArray[i]->fMark0 = 0; - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes ) -{ - assert( !Fpga_IsComplement(pNode) ); - if ( pNode->fMark0 ) - return; - pNode->fMark0 = 1; - // visit the transitive fanin - Level--; - if ( Level > 0 && Fpga_NodeIsAnd(pNode) ) - { - Fpga_DfsLim_rec( Fpga_Regular(pNode->p1), Level, vNodes ); - Fpga_DfsLim_rec( Fpga_Regular(pNode->p2), Level, vNodes ); - } - // add the node to the list - Fpga_NodeVecPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Computes the limited DFS ordering for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_ManCleanData0( Fpga_Man_t * pMan ) -{ - int i; - for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) - pMan->vNodesAll->pArray[i]->pData0 = 0; -} - -/**Function************************************************************* - - Synopsis [Collects the TFO of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode ) -{ - Fpga_NodeVec_t * vVisited, * vTfo; - int i; - // perform the traversal - vVisited = Fpga_NodeVecAlloc( 100 ); - vTfo = Fpga_NodeVecAlloc( 100 ); - for ( i = 0; i < pMan->nOutputs; i++ ) - Fpga_CollectNodeTfo_rec( Fpga_Regular(pMan->pOutputs[i]), pNode, vVisited, vTfo ); - for ( i = 0; i < vVisited->nSize; i++ ) - vVisited->pArray[i]->fMark0 = vVisited->pArray[i]->fMark1 = 0; - Fpga_NodeVecFree( vVisited ); - return vTfo; -} - -/**Function************************************************************* - - Synopsis [Collects the TFO of the node.] - - Description [Returns 1 if the node should be collected.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo ) -{ - int Ret1, Ret2; - assert( !Fpga_IsComplement(pNode) ); - // skip visited nodes - if ( pNode->fMark0 ) - return pNode->fMark1; - pNode->fMark0 = 1; - Fpga_NodeVecPush( vVisited, pNode ); - - // return the pivot node - if ( pNode == pPivot ) - { - pNode->fMark1 = 1; - return 1; - } - if ( pNode->Level < pPivot->Level ) - { - pNode->fMark1 = 0; - return 0; - } - // visit the transitive fanin - assert( Fpga_NodeIsAnd(pNode) ); - Ret1 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p1), pPivot, vVisited, vTfo ); - Ret2 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p2), pPivot, vVisited, vTfo ); - if ( Ret1 || Ret2 ) - { - pNode->fMark1 = 1; - Fpga_NodeVecPush( vTfo, pNode ); - } - else - pNode->fMark1 = 0; - return pNode->fMark1; -} - -/**Function************************************************************* - - Synopsis [Levelizes the nodes accessible from the POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_NodeVec_t * Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes ) -{ - Fpga_NodeVec_t * vLevels; - Fpga_Node_t ** ppNodes; - Fpga_Node_t * pNode; - int nNodes, nLevelsMax, i; - - // reassign the levels (this may be necessary for networks which choices) - ppNodes = vNodes->pArray; - nNodes = vNodes->nSize; - for ( i = 0; i < nNodes; i++ ) - { - pNode = ppNodes[i]; - if ( !Fpga_NodeIsAnd(pNode) ) - { - pNode->Level = 0; - continue; - } - pNode->Level = 1 + FPGA_MAX( Fpga_Regular(pNode->p1)->Level, Fpga_Regular(pNode->p2)->Level ); - } - - // get the max levels - nLevelsMax = 0; - for ( i = 0; i < pMan->nOutputs; i++ ) - nLevelsMax = FPGA_MAX( nLevelsMax, (int)Fpga_Regular(pMan->pOutputs[i])->Level ); - nLevelsMax++; - - // allocate storage for levels - vLevels = Fpga_NodeVecAlloc( nLevelsMax ); - for ( i = 0; i < nLevelsMax; i++ ) - Fpga_NodeVecPush( vLevels, NULL ); - - // go through the nodes and add them to the levels - for ( i = 0; i < nNodes; i++ ) - { - pNode = ppNodes[i]; - pNode->pLevel = NULL; - if ( !Fpga_NodeIsAnd(pNode) ) - continue; - // attach the node to this level - pNode->pLevel = Fpga_NodeVecReadEntry( vLevels, pNode->Level ); - Fpga_NodeVecWriteEntry( vLevels, pNode->Level, pNode ); - } - return vLevels; -} - -/**Function************************************************************* - - Synopsis [Sets up the mask.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_MappingMaxLevel( Fpga_Man_t * pMan ) -{ - int nLevelMax, i; - nLevelMax = 0; - for ( i = 0; i < pMan->nOutputs; i++ ) - nLevelMax = nLevelMax > (int)Fpga_Regular(pMan->pOutputs[i])->Level? - nLevelMax : (int)Fpga_Regular(pMan->pOutputs[i])->Level; - return nLevelMax; -} - - -/**Function************************************************************* - - Synopsis [Analyses choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_MappingUpdateLevel_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int fMaximum ) -{ - Fpga_Node_t * pTemp; - int Level1, Level2, LevelE; - assert( !Fpga_IsComplement(pNode) ); - if ( !Fpga_NodeIsAnd(pNode) ) - return pNode->Level; - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return pNode->Level; - pNode->TravId = pMan->nTravIds; - // compute levels of the children nodes - Level1 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p1), fMaximum ); - Level2 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p2), fMaximum ); - pNode->Level = 1 + FPGA_MAX( Level1, Level2 ); - if ( pNode->pNextE ) - { - LevelE = Fpga_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); - if ( fMaximum ) - { - if ( pNode->Level < (unsigned)LevelE ) - pNode->Level = LevelE; - } - else - { - if ( pNode->Level > (unsigned)LevelE ) - pNode->Level = LevelE; - } - // set the level of all equivalent nodes to be the same minimum - if ( pNode->pRepr == NULL ) // the primary node - for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) - pTemp->Level = pNode->Level; - } - return pNode->Level; -} - -/**Function************************************************************* - - Synopsis [Resets the levels of the nodes in the choice graph.] - - Description [Makes the level of the choice nodes to be equal to the - maximum of the level of the nodes in the equivalence class. This way - sorting by level leads to the reverse topological order, which is - needed for the required time computation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan ) -{ - int i; - pMan->nTravIds++; - for ( i = 0; i < pMan->nOutputs; i++ ) - Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 1 ); -} - -/**Function************************************************************* - - Synopsis [Reports statistics on choice nodes.] - - Description [The number of choice nodes is the number of primary nodes, - which has pNextE set to a pointer. The number of choices is the number - of entries in the equivalent-node lists of the primary nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_ManReportChoices( Fpga_Man_t * pMan ) -{ - Fpga_Node_t * pNode, * pTemp; - int nChoiceNodes, nChoices; - int i, LevelMax1, LevelMax2; - - // report the number of levels - LevelMax1 = Fpga_MappingMaxLevel( pMan ); - pMan->nTravIds++; - for ( i = 0; i < pMan->nOutputs; i++ ) - Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 0 ); - LevelMax2 = Fpga_MappingMaxLevel( pMan ); - - // report statistics about choices - nChoiceNodes = nChoices = 0; - for ( i = 0; i < pMan->vAnds->nSize; i++ ) - { - pNode = pMan->vAnds->pArray[i]; - if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) - { // this is a choice node = the primary node that has equivalent nodes - nChoiceNodes++; - for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) - nChoices++; - } - } - if ( pMan->fVerbose ) - { - printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); - printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); - } -/* - { - FILE * pTable; - pTable = fopen( "stats_choice.txt", "a+" ); - fprintf( pTable, "%s ", pMan->pFileName ); - fprintf( pTable, "%4d ", LevelMax1 ); - fprintf( pTable, "%4d ", pMan->vAnds->nSize - pMan->nInputs ); - fprintf( pTable, "%4d ", LevelMax2 ); - fprintf( pTable, "%7d ", nChoiceNodes ); - fprintf( pTable, "%7d ", nChoices + nChoiceNodes ); - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Returns the array of CO nodes sorted by level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan ) -{ - Fpga_Node_t * pNode; - Fpga_NodeVec_t * vNodes; - int i, nLevels; - // get the largest level of a CO - nLevels = Fpga_MappingMaxLevel( pMan ); - // allocate the array of nodes - vNodes = Fpga_NodeVecAlloc( nLevels + 1 ); - for ( i = 0; i <= nLevels; i++ ) - Fpga_NodeVecPush( vNodes, NULL ); - // clean the marks - for ( i = 0; i < pMan->nOutputs; i++ ) - Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0; - // put the nodes into the structure - for ( i = 0; i < pMan->nOutputs; i++ ) - { - pNode = Fpga_Regular(pMan->pOutputs[i]); - if ( pNode->fMark0 ) - continue; - pNode->fMark0 = 1; - pNode->pData0 = (char *)Fpga_NodeVecReadEntry( vNodes, pNode->Level ); - Fpga_NodeVecWriteEntry( vNodes, pNode->Level, pNode ); - } - for ( i = 0; i < pMan->nOutputs; i++ ) - Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0; - return vNodes; - -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/fpga/fpgaVec.c b/src/map/fpga/fpgaVec.c deleted file mode 100644 index 70a4a7ac..00000000 --- a/src/map/fpga/fpgaVec.c +++ /dev/null @@ -1,408 +0,0 @@ -/**CFile**************************************************************** - - FileName [fpgaVec.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Technology mapping for variable-size-LUT FPGAs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - August 18, 2004.] - - Revision [$Id: fpgaVec.c,v 1.3 2005/01/23 06:59:42 alanmi Exp $] - -***********************************************************************/ - -#include "fpgaInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_NodeVec_t * Fpga_NodeVecAlloc( int nCap ) -{ - Fpga_NodeVec_t * p; - p = ALLOC( Fpga_NodeVec_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( Fpga_Node_t *, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeVecFree( Fpga_NodeVec_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Node_t ** Fpga_NodeVecReadArray( Fpga_NodeVec_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_NodeVecReadSize( Fpga_NodeVec_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeVecGrow( Fpga_NodeVec_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( Fpga_Node_t *, p->pArray, nCapMin ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeVecShrink( Fpga_NodeVec_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeVecClear( Fpga_NodeVec_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeVecPush( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Fpga_NodeVecGrow( p, 16 ); - else - Fpga_NodeVecGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [Add the element while ensuring uniqueness.] - - Description [Returns 1 if the element was found, and 0 if it was new. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_NodeVecPushUnique( Fpga_NodeVec_t * p, Fpga_Node_t * Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Fpga_NodeVecPush( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Node_t * Fpga_NodeVecPop( Fpga_NodeVec_t * p ) -{ - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeVecWriteEntry( Fpga_NodeVec_t * p, int i, Fpga_Node_t * Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fpga_Node_t * Fpga_NodeVecReadEntry( Fpga_NodeVec_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_NodeVecCompareLevels( Fpga_Node_t ** pp1, Fpga_Node_t ** pp2 ) -{ - int Level1 = Fpga_Regular(*pp1)->Level; - int Level2 = Fpga_Regular(*pp2)->Level; - if ( Level1 < Level2 ) - return -1; - if ( Level1 > Level2 ) - return 1; - if ( Fpga_Regular(*pp1)->Num < Fpga_Regular(*pp2)->Num ) - return -1; - if ( Fpga_Regular(*pp1)->Num > Fpga_Regular(*pp2)->Num ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeVecSortByLevel( Fpga_NodeVec_t * p ) -{ - qsort( (void *)p->pArray, p->nSize, sizeof(Fpga_Node_t *), - (int (*)(const void *, const void *)) Fpga_NodeVecCompareLevels ); -} - -/**Function************************************************************* - - Synopsis [Compares the arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fpga_NodeVecCompareArrivals( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 ) -{ - if ( (*ppS1)->pCutBest->tArrival < (*ppS2)->pCutBest->tArrival ) - return -1; - if ( (*ppS1)->pCutBest->tArrival > (*ppS2)->pCutBest->tArrival ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Orders the nodes in the increasing order of the arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_SortNodesByArrivalTimes( Fpga_NodeVec_t * p ) -{ - qsort( (void *)p->pArray, p->nSize, sizeof(Fpga_Node_t *), - (int (*)(const void *, const void *)) Fpga_NodeVecCompareArrivals ); -// assert( Fpga_CompareNodesByLevel( p->pArray, p->pArray + p->nSize - 1 ) <= 0 ); -} - - -/**Function************************************************************* - - Synopsis [Computes the union of nodes in two arrays.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeVecUnion( Fpga_NodeVec_t * p, Fpga_NodeVec_t * p1, Fpga_NodeVec_t * p2 ) -{ - int i; - Fpga_NodeVecClear( p ); - for ( i = 0; i < p1->nSize; i++ ) - Fpga_NodeVecPush( p, p1->pArray[i] ); - for ( i = 0; i < p2->nSize; i++ ) - Fpga_NodeVecPush( p, p2->pArray[i] ); -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeVecPushOrder( Fpga_NodeVec_t * vNodes, Fpga_Node_t * pNode, int fIncreasing ) -{ - Fpga_Node_t * pNode1, * pNode2; - int i; - Fpga_NodeVecPush( vNodes, pNode ); - // find the place of the node - for ( i = vNodes->nSize-1; i > 0; i-- ) - { - pNode1 = vNodes->pArray[i ]; - pNode2 = vNodes->pArray[i-1]; - if ( fIncreasing && pNode1->pCutBest->tArrival >= pNode2->pCutBest->tArrival || - !fIncreasing && pNode1->pCutBest->tArrival <= pNode2->pCutBest->tArrival ) - break; - vNodes->pArray[i ] = pNode2; - vNodes->pArray[i-1] = pNode1; - } -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fpga_NodeVecReverse( Fpga_NodeVec_t * vNodes ) -{ - Fpga_Node_t * pNode1, * pNode2; - int i; - for ( i = 0; i < vNodes->nSize/2; i++ ) - { - pNode1 = vNodes->pArray[i]; - pNode2 = vNodes->pArray[vNodes->nSize-1-i]; - vNodes->pArray[i] = pNode2; - vNodes->pArray[vNodes->nSize-1-i] = pNode1; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/fpga/module.make b/src/map/fpga/module.make deleted file mode 100644 index cc3a6573..00000000 --- a/src/map/fpga/module.make +++ /dev/null @@ -1,13 +0,0 @@ -SRC += src/map/fpga/fpga.c \ - src/map/fpga/fpgaCore.c \ - src/map/fpga/fpgaCreate.c \ - src/map/fpga/fpgaCut.c \ - src/map/fpga/fpgaCutUtils.c \ - src/map/fpga/fpgaFanout.c \ - src/map/fpga/fpgaLib.c \ - src/map/fpga/fpgaMatch.c \ - src/map/fpga/fpgaSwitch.c \ - src/map/fpga/fpgaTime.c \ - src/map/fpga/fpgaTruth.c \ - src/map/fpga/fpgaUtils.c \ - src/map/fpga/fpgaVec.c diff --git a/src/map/if/if.h b/src/map/if/if.h deleted file mode 100644 index 706f8552..00000000 --- a/src/map/if/if.h +++ /dev/null @@ -1,386 +0,0 @@ -/**CFile**************************************************************** - - FileName [if.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapping based on priority cuts.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: if.h,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __IF_H__ -#define __IF_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include "vec.h" -#include "mem.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// the maximum size of LUTs used for mapping (should be the same as FPGA_MAX_LUTSIZE defined in "fpga.h"!!!) -#define IF_MAX_LUTSIZE 32 -// the largest possible number of LUT inputs when funtionality of the LUTs are computed -#define IF_MAX_FUNC_LUTSIZE 15 -// a very large number -#define IF_INFINITY 100000000 -// the largest possible user cut cost -#define IF_COST_MAX ((1<<14)-1) - -// object types -typedef enum { - IF_NONE, // 0: non-existent object - IF_CONST1, // 1: constant 1 - IF_CI, // 2: combinational input - IF_CO, // 3: combinational output - IF_AND, // 4: AND node - IF_VOID // 5: unused object -} If_Type_t; - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct If_Man_t_ If_Man_t; -typedef struct If_Par_t_ If_Par_t; -typedef struct If_Lib_t_ If_Lib_t; -typedef struct If_Obj_t_ If_Obj_t; -typedef struct If_Cut_t_ If_Cut_t; -typedef struct If_Set_t_ If_Set_t; - -// parameters -struct If_Par_t_ -{ - // user-controlable paramters - int nLutSize; // the LUT size - int nCutsMax; // the max number of cuts - int nFlowIters; // the number of iterations of area recovery - int nAreaIters; // the number of iterations of area recovery - float DelayTarget; // delay target - int fPreprocess; // preprossing - int fArea; // area-oriented mapping - int fFancy; // a fancy feature - int fExpRed; // expand/reduce of the best cuts - int fLatchPaths; // reset timing on latch paths - int fSeqMap; // sequential mapping - int fVerbose; // the verbosity flag - // internal parameters - int fAreaOnly; // area only mode - int fTruth; // truth table computation enabled - int fUsePerm; // use permutation (delay info) - int fUseBdds; // use local BDDs as a cost function - int fUseSops; // use local SOPs as a cost function - int fUseCnfs; // use local CNFs as a cost function - int fUseMv; // use local MV-SOPs as a cost function - int nLatches; // the number of latches in seq mapping - int fLiftLeaves; // shift the leaves for seq mapping - If_Lib_t * pLutLib; // the LUT library - float * pTimesArr; // arrival times - float * pTimesReq; // required times - int (* pFuncCost) (If_Cut_t *); // procedure to compute the user's cost of a cut - int (* pFuncUser) (If_Man_t *, If_Obj_t *, If_Cut_t *); // procedure called for each cut when cut computation is finished - void * pReoMan; // reordering manager -}; - -// the LUT library -struct If_Lib_t_ -{ - char * pName; // the name of the LUT library - int LutMax; // the maximum LUT size - int fVarPinDelays; // set to 1 if variable pin delays are specified - float pLutAreas[IF_MAX_LUTSIZE+1]; // the areas of LUTs - float pLutDelays[IF_MAX_LUTSIZE+1][IF_MAX_LUTSIZE+1];// the delays of LUTs -}; - -// manager -struct If_Man_t_ -{ - // mapping parameters - If_Par_t * pPars; - // mapping nodes - If_Obj_t * pConst1; // the constant 1 node - Vec_Ptr_t * vCis; // the primary inputs - Vec_Ptr_t * vCos; // the primary outputs - Vec_Ptr_t * vObjs; // all objects - Vec_Ptr_t * vMapped; // objects used in the mapping - Vec_Ptr_t * vTemp; // temporary array - int nObjs[IF_VOID];// the number of objects by type - // various data - int nLevelMax; // the max number of AIG levels - float fEpsilon; // epsilon used for comparison - float RequiredGlo; // global required times - float RequiredGlo2; // global required times - float AreaGlo; // global area - int nNets; // the sum total of fanins of all LUTs in the mapping - int nCutsUsed; // the number of cuts currently used - int nCutsMerged; // the total number of cuts merged - unsigned * puTemp[4]; // used for the truth table computation - int SortMode; // one of the three sorting modes - int fNextRound; // set to 1 after the first round - int nChoices; // the number of choice nodes - // sequential mapping - Vec_Ptr_t * vLatchOrder; // topological ordering of latches - Vec_Int_t * vLags; // sequentail lags of all nodes - int nAttempts; // the number of attempts in binary search - int nMaxIters; // the maximum number of iterations - int Period; // the current value of the clock period (for seq mapping) - // memory management - int nTruthWords; // the size of the truth table if allocated - int nPermWords; // the size of the permutation array (in words) - int nObjBytes; // the size of the object - int nCutBytes; // the size of the cut - int nSetBytes; // the size of the cut set - Mem_Fixed_t * pMemObj; // memory manager for objects (entrysize = nEntrySize) - Mem_Fixed_t * pMemSet; // memory manager for sets of cuts (entrysize = nCutSize*(nCutsMax+1)) - If_Set_t * pMemCi; // memory for CI cutsets - If_Set_t * pMemAnd; // memory for AND cutsets - If_Set_t * pFreeList; // the list of free cutsets -}; - -// priority cut -struct If_Cut_t_ -{ - float Delay; // delay of the cut - float Area; // area (or area-flow) of the cut - float AveRefs; // the average number of leaf references - unsigned uSign; // cut signature - unsigned Cost : 14; // the user's cost of the cut - unsigned fCompl : 1; // the complemented attribute - unsigned fUser : 1; // using the user's area and delay - unsigned nLimit : 8; // the maximum number of leaves - unsigned nLeaves : 8; // the number of leaves - int * pLeaves; // array of fanins - char * pPerm; // permutation - unsigned * pTruth; // the truth table -}; - -// set of priority cut -struct If_Set_t_ -{ - short nCutsMax; // the max number of cuts - short nCuts; // the current number of cuts - If_Set_t * pNext; // next cutset in the free list - If_Cut_t ** ppCuts; // the array of pointers to the cuts -}; - -// node extension -struct If_Obj_t_ -{ - unsigned Type : 4; // object - unsigned fCompl0 : 1; // complemented attribute - unsigned fCompl1 : 1; // complemented attribute - unsigned fPhase : 1; // phase of the node - unsigned fRepr : 1; // representative of the equivalence class - unsigned fMark : 1; // multipurpose mark - unsigned fVisit : 1; // multipurpose mark - unsigned Level : 22; // logic level of the node - int Id; // integer ID - int nRefs; // the number of references - int nVisits; // the number of visits to this node - int nVisitsCopy; // the number of visits to this node - If_Obj_t * pFanin0; // the first fanin - If_Obj_t * pFanin1; // the second fanin - If_Obj_t * pEquiv; // the choice node - float EstRefs; // estimated reference counter - float Required; // required time of the onde - float LValue; // sequential arrival time of the node - void * pCopy; // used for object duplication - If_Set_t * pCutSet; // the pointer to the cutset - If_Cut_t CutBest; // the best cut selected -}; - -static inline If_Obj_t * If_Regular( If_Obj_t * p ) { return (If_Obj_t *)((unsigned long)(p) & ~01); } -static inline If_Obj_t * If_Not( If_Obj_t * p ) { return (If_Obj_t *)((unsigned long)(p) ^ 01); } -static inline If_Obj_t * If_NotCond( If_Obj_t * p, int c ) { return (If_Obj_t *)((unsigned long)(p) ^ (c)); } -static inline int If_IsComplement( If_Obj_t * p ) { return (int )(((unsigned long)p) & 01); } - -static inline int If_ManCiNum( If_Man_t * p ) { return p->nObjs[IF_CI]; } -static inline int If_ManCoNum( If_Man_t * p ) { return p->nObjs[IF_CO]; } -static inline int If_ManAndNum( If_Man_t * p ) { return p->nObjs[IF_AND]; } -static inline int If_ManObjNum( If_Man_t * p ) { return Vec_PtrSize(p->vObjs); } - -static inline If_Obj_t * If_ManConst1( If_Man_t * p ) { return p->pConst1; } -static inline If_Obj_t * If_ManCi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCis, i ); } -static inline If_Obj_t * If_ManCo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCos, i ); } -static inline If_Obj_t * If_ManLi( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCos, If_ManCoNum(p) - p->pPars->nLatches + i ); } -static inline If_Obj_t * If_ManLo( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vCis, If_ManCiNum(p) - p->pPars->nLatches + i ); } -static inline If_Obj_t * If_ManObj( If_Man_t * p, int i ) { return (If_Obj_t *)Vec_PtrEntry( p->vObjs, i ); } - -static inline int If_ObjIsConst1( If_Obj_t * pObj ) { return pObj->Type == IF_CONST1; } -static inline int If_ObjIsCi( If_Obj_t * pObj ) { return pObj->Type == IF_CI; } -static inline int If_ObjIsCo( If_Obj_t * pObj ) { return pObj->Type == IF_CO; } -static inline int If_ObjIsPi( If_Obj_t * pObj ) { return If_ObjIsCi(pObj) && pObj->pFanin0 == NULL; } -static inline int If_ObjIsLatch( If_Obj_t * pObj ) { return If_ObjIsCi(pObj) && pObj->pFanin0 != NULL; } -static inline int If_ObjIsAnd( If_Obj_t * pObj ) { return pObj->Type == IF_AND; } - -static inline If_Obj_t * If_ObjFanin0( If_Obj_t * pObj ) { return pObj->pFanin0; } -static inline If_Obj_t * If_ObjFanin1( If_Obj_t * pObj ) { return pObj->pFanin1; } -static inline int If_ObjFaninC0( If_Obj_t * pObj ) { return pObj->fCompl0; } -static inline int If_ObjFaninC1( If_Obj_t * pObj ) { return pObj->fCompl1; } -static inline void * If_ObjCopy( If_Obj_t * pObj ) { return pObj->pCopy; } -static inline void If_ObjSetCopy( If_Obj_t * pObj, void * pCopy ) { pObj->pCopy = pCopy; } -static inline void If_ObjSetChoice( If_Obj_t * pObj, If_Obj_t * pEqu ) { pObj->pEquiv = pEqu; } - -static inline If_Cut_t * If_ObjCutBest( If_Obj_t * pObj ) { return &pObj->CutBest; } -static inline unsigned If_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId % 31)); } - -static inline float If_ObjArrTime( If_Obj_t * pObj ) { return If_ObjCutBest(pObj)->Delay; } -static inline void If_ObjSetArrTime( If_Obj_t * pObj, float ArrTime ) { If_ObjCutBest(pObj)->Delay = ArrTime; } - -static inline float If_ObjLValue( If_Obj_t * pObj ) { return pObj->LValue; } -static inline void If_ObjSetLValue( If_Obj_t * pObj, float LValue ) { pObj->LValue = LValue; } - -static inline void * If_CutData( If_Cut_t * pCut ) { return *(void **)pCut; } -static inline void If_CutSetData( If_Cut_t * pCut, void * pData ) { *(void **)pCut = pData; } - -static inline int If_CutLeaveNum( If_Cut_t * pCut ) { return pCut->nLeaves; } -static inline unsigned * If_CutTruth( If_Cut_t * pCut ) { return pCut->pTruth; } -static inline int If_CutTruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 1 : (1 << (nVarsMax - 5)); } -static inline int If_CutPermWords( int nVarsMax ) { return nVarsMax / sizeof(int) + ((nVarsMax % sizeof(int)) > 0); } - -static inline float If_CutLutArea( If_Man_t * p, If_Cut_t * pCut ) { return pCut->fUser? (float)pCut->Cost : (p->pPars->pLutLib? p->pPars->pLutLib->pLutAreas[pCut->nLeaves] : (float)1.0); } - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define IF_MIN(a,b) (((a) < (b))? (a) : (b)) -#define IF_MAX(a,b) (((a) > (b))? (a) : (b)) - -// the small and large numbers (min/max float are 1.17e-38/3.40e+38) -#define IF_FLOAT_LARGE ((float)1.0e+20) -#define IF_FLOAT_SMALL ((float)1.0e-20) -#define IF_INT_LARGE (10000000) - -// iterator over the primary inputs -#define If_ManForEachCi( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vCis, pObj, i ) -// iterator over the primary outputs -#define If_ManForEachCo( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vCos, pObj, i ) -// iterator over the primary inputs -#define If_ManForEachPi( p, pObj, i ) \ - Vec_PtrForEachEntryStop( p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatches ) -// iterator over the primary outputs -#define If_ManForEachPo( p, pObj, i ) \ - Vec_PtrForEachEntryStop( p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatches ) -// iterator over the latches -#define If_ManForEachLatchInput( p, pObj, i ) \ - Vec_PtrForEachEntryStart( p->vCos, pObj, i, If_ManCoNum(p) - p->pPars->nLatches ) -#define If_ManForEachLatchOutput( p, pObj, i ) \ - Vec_PtrForEachEntryStart( p->vCis, pObj, i, If_ManCiNum(p) - p->pPars->nLatches ) -// iterator over all objects, including those currently not used -#define If_ManForEachObj( p, pObj, i ) \ - Vec_PtrForEachEntry( p->vObjs, pObj, i ) -// iterator over logic nodes -#define If_ManForEachNode( p, pObj, i ) \ - If_ManForEachObj( p, pObj, i ) if ( pObj->Type != IF_AND ) {} else -// iterator over cuts of the node -#define If_ObjForEachCut( pObj, pCut, i ) \ - for ( i = 0; (i < (pObj)->pCutSet->nCuts) && ((pCut) = (pObj)->pCutSet->ppCuts[i]); i++ ) -// iterator over the leaves of the cut -#define If_CutForEachLeaf( p, pCut, pLeaf, i ) \ - for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i++ ) -#define If_CutForEachLeafReverse( p, pCut, pLeaf, i ) \ - for ( i = (int)(pCut)->nLeaves - 1; (i >= 0) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i])); i-- ) -//#define If_CutForEachLeaf( p, pCut, pLeaf, i ) \ -// for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, p->pPars->fLiftLeaves? (pCut)->pLeaves[i] >> 8 : (pCut)->pLeaves[i])); i++ ) -// iterator over the leaves of the sequential cut -#define If_CutForEachLeafSeq( p, pCut, pLeaf, Shift, i ) \ - for ( i = 0; (i < (int)(pCut)->nLeaves) && ((pLeaf) = If_ManObj(p, (pCut)->pLeaves[i] >> 8)) && (((Shift) = ((pCut)->pLeaves[i] & 255)) >= 0); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== ifCore.c ===========================================================*/ -extern int If_ManPerformMapping( If_Man_t * p ); -extern int If_ManPerformMappingComb( If_Man_t * p ); -/*=== ifCut.c ============================================================*/ -extern float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut, int nLevels ); -extern float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut, int nLevels ); -extern float If_CutDeref( If_Man_t * p, If_Cut_t * pCut, int nLevels ); -extern float If_CutRef( If_Man_t * p, If_Cut_t * pCut, int nLevels ); -extern void If_CutPrint( If_Man_t * p, If_Cut_t * pCut ); -extern void If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutFlow( If_Man_t * p, If_Cut_t * pCut ); -extern float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut ); -extern int If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut ); -extern void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ); -extern int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut ); -extern void If_CutLift( If_Cut_t * pCut ); -extern void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc ); -extern void If_ManSortCuts( If_Man_t * p, int Mode ); -/*=== ifMan.c =============================================================*/ -extern If_Man_t * If_ManStart( If_Par_t * pPars ); -extern void If_ManRestart( If_Man_t * p ); -extern void If_ManStop( If_Man_t * p ); -extern If_Obj_t * If_ManCreateCi( If_Man_t * p ); -extern If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver ); -extern If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ); -extern If_Obj_t * If_ManCreateXor( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ); -extern If_Obj_t * If_ManCreateMux( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1, If_Obj_t * pCtrl ); -extern void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pRepr ); -extern void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId ); -extern void If_ManSetupCiCutSets( If_Man_t * p ); -extern If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj ); -extern void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj ); -extern void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj ); -extern void If_ManSetupSetAll( If_Man_t * p, int nCrossCut ); -/*=== ifMap.c =============================================================*/ -extern void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess ); -extern void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess ); -extern int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, char * pLabel ); -/*=== ifReduce.c ==========================================================*/ -extern void If_ManImproveMapping( If_Man_t * p ); -/*=== ifSeq.c =============================================================*/ -extern int If_ManPerformMappingSeq( If_Man_t * p ); -/*=== ifTime.c ============================================================*/ -extern float If_CutDelay( If_Man_t * p, If_Cut_t * pCut ); -extern void If_CutPropagateRequired( If_Man_t * p, If_Cut_t * pCut, float Required ); -/*=== ifTruth.c ===========================================================*/ -extern void If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ); -/*=== ifUtil.c ============================================================*/ -extern void If_ManCleanNodeCopy( If_Man_t * p ); -extern void If_ManCleanCutData( If_Man_t * p ); -extern void If_ManCleanMarkV( If_Man_t * p ); -extern float If_ManDelayMax( If_Man_t * p, int fSeq ); -extern void If_ManComputeRequired( If_Man_t * p ); -extern float If_ManScanMapping( If_Man_t * p ); -extern float If_ManScanMappingSeq( If_Man_t * p ); -extern void If_ManResetOriginalRefs( If_Man_t * p ); -extern int If_ManCrossCut( If_Man_t * p ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/if/ifCore.c b/src/map/if/ifCore.c deleted file mode 100644 index 59ad5a1c..00000000 --- a/src/map/if/ifCore.c +++ /dev/null @@ -1,146 +0,0 @@ -/**CFile**************************************************************** - - FileName [ifCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapping based on priority cuts.] - - Synopsis [The central part of the mapper.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: ifCore.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "if.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern int s_MappingTime; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManPerformMapping( If_Man_t * p ) -{ - p->pPars->fAreaOnly = p->pPars->fArea; // temporary - - // create the CI cutsets - If_ManSetupCiCutSets( p ); - // allocate memory for other cutsets - If_ManSetupSetAll( p, If_ManCrossCut(p) ); - - // try sequential mapping - if ( p->pPars->fSeqMap ) - { - int RetValue; -// printf( "Currently sequential mapping is not performed.\n" ); - RetValue = If_ManPerformMappingSeq( p ); - return RetValue; -// return 1; - } - - return If_ManPerformMappingComb( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManPerformMappingComb( If_Man_t * p ) -{ - If_Obj_t * pObj; - int clkTotal = clock(); - int i; - - // set arrival times and fanout estimates - If_ManForEachCi( p, pObj, i ) - { - If_ObjSetArrTime( pObj, p->pPars->pTimesArr[i] ); - pObj->EstRefs = (float)1.0; - } - - // delay oriented mapping - if ( p->pPars->fPreprocess && !p->pPars->fArea ) - { - // map for delay - If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Delay" ); - // map for delay second option - p->pPars->fFancy = 1; - If_ManResetOriginalRefs( p ); - If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Delay-2" ); - p->pPars->fFancy = 0; - // map for area - p->pPars->fArea = 1; - If_ManResetOriginalRefs( p ); - If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 1, "Area" ); - p->pPars->fArea = 0; - } - else - If_ManPerformMappingRound( p, p->pPars->nCutsMax, 0, 0, "Delay" ); - - // try to improve area by expanding and reducing the cuts - if ( p->pPars->fExpRed && !p->pPars->fTruth ) - If_ManImproveMapping( p ); - - // area flow oriented mapping - for ( i = 0; i < p->pPars->nFlowIters; i++ ) - { - If_ManPerformMappingRound( p, p->pPars->nCutsMax, 1, 0, "Flow" ); - if ( p->pPars->fExpRed && !p->pPars->fTruth ) - If_ManImproveMapping( p ); - } - - // area oriented mapping - for ( i = 0; i < p->pPars->nAreaIters; i++ ) - { - If_ManPerformMappingRound( p, p->pPars->nCutsMax, 2, 0, "Area" ); - if ( p->pPars->fExpRed && !p->pPars->fTruth ) - If_ManImproveMapping( p ); - } - - if ( p->pPars->fVerbose ) - { -// printf( "Total memory = %7.2f Mb. Peak cut memory = %7.2f Mb. ", -// 1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20), -// 1.0 * p->nSetBytes * Mem_FixedReadMaxEntriesUsed(p->pMemSet) / (1<<20) ); - PRT( "Total time", clock() - clkTotal ); - } -// printf( "Cross cut memory = %d.\n", Mem_FixedReadMaxEntriesUsed(p->pMemSet) ); - s_MappingTime = clock() - clkTotal; - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/ifCut.c b/src/map/if/ifCut.c deleted file mode 100644 index 1a7ecc2c..00000000 --- a/src/map/if/ifCut.c +++ /dev/null @@ -1,777 +0,0 @@ -/**CFile**************************************************************** - - FileName [ifCut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapping based on priority cuts.] - - Synopsis [Cut computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: ifCut.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "if.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Returns 1 if pDom is contained in pCut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int If_CutCheckDominance( If_Cut_t * pDom, If_Cut_t * pCut ) -{ - int i, k; - for ( i = 0; i < (int)pDom->nLeaves; i++ ) - { - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) - break; - if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut - return 0; - } - // every node in pDom is contained in pCut - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pDom is equal to pCut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int If_CutCheckEquality( If_Cut_t * pDom, If_Cut_t * pCut ) -{ - int i; - if ( (int)pDom->nLeaves != (int)pCut->nLeaves ) - return 0; - for ( i = 0; i < (int)pDom->nLeaves; i++ ) - if ( pDom->pLeaves[i] != pCut->pLeaves[i] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the cut is contained.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_CutFilter( If_Set_t * pCutSet, If_Cut_t * pCut ) -{ - If_Cut_t * pTemp; - int i, k; - assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut ); - for ( i = 0; i < pCutSet->nCuts; i++ ) - { - pTemp = pCutSet->ppCuts[i]; - if ( pTemp->nLeaves > pCut->nLeaves ) - { - // do not fiter the first cut - if ( i == 0 ) - continue; - // skip the non-contained cuts - if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) - continue; - // check containment seriously - if ( If_CutCheckDominance( pCut, pTemp ) ) - { -// p->ppCuts[i] = p->ppCuts[p->nCuts-1]; -// p->ppCuts[p->nCuts-1] = pTemp; -// p->nCuts--; -// i--; - // remove contained cut - for ( k = i; k < pCutSet->nCuts; k++ ) - pCutSet->ppCuts[k] = pCutSet->ppCuts[k+1]; - pCutSet->ppCuts[pCutSet->nCuts] = pTemp; - pCutSet->nCuts--; - i--; - } - } - else - { - // skip the non-contained cuts - if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) - continue; - // check containment seriously - if ( If_CutCheckDominance( pTemp, pCut ) ) - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int If_CutMergeOrdered( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC ) -{ - int i, k, c; - assert( pC0->nLeaves >= pC1->nLeaves ); - // the case of the largest cut sizes - if ( pC0->nLeaves == pC->nLimit && pC1->nLeaves == pC->nLimit ) - { - for ( i = 0; i < (int)pC0->nLeaves; i++ ) - if ( pC0->pLeaves[i] != pC1->pLeaves[i] ) - return 0; - for ( i = 0; i < (int)pC0->nLeaves; i++ ) - pC->pLeaves[i] = pC0->pLeaves[i]; - pC->nLeaves = pC0->nLeaves; - return 1; - } - // the case when one of the cuts is the largest - if ( pC0->nLeaves == pC->nLimit ) - { - for ( i = 0; i < (int)pC1->nLeaves; i++ ) - { - for ( k = (int)pC0->nLeaves - 1; k >= 0; k-- ) - if ( pC0->pLeaves[k] == pC1->pLeaves[i] ) - break; - if ( k == -1 ) // did not find - return 0; - } - for ( i = 0; i < (int)pC0->nLeaves; i++ ) - pC->pLeaves[i] = pC0->pLeaves[i]; - pC->nLeaves = pC0->nLeaves; - return 1; - } - - // compare two cuts with different numbers - i = k = 0; - for ( c = 0; c < (int)pC->nLimit; c++ ) - { - if ( k == (int)pC1->nLeaves ) - { - if ( i == (int)pC0->nLeaves ) - { - pC->nLeaves = c; - return 1; - } - pC->pLeaves[c] = pC0->pLeaves[i++]; - continue; - } - if ( i == (int)pC0->nLeaves ) - { - if ( k == (int)pC1->nLeaves ) - { - pC->nLeaves = c; - return 1; - } - pC->pLeaves[c] = pC1->pLeaves[k++]; - continue; - } - if ( pC0->pLeaves[i] < pC1->pLeaves[k] ) - { - pC->pLeaves[c] = pC0->pLeaves[i++]; - continue; - } - if ( pC0->pLeaves[i] > pC1->pLeaves[k] ) - { - pC->pLeaves[c] = pC1->pLeaves[k++]; - continue; - } - pC->pLeaves[c] = pC0->pLeaves[i++]; - k++; - } - if ( i < (int)pC0->nLeaves || k < (int)pC1->nLeaves ) - return 0; - pC->nLeaves = c; - return 1; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [Special case when the cut is known to exist.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int If_CutMergeOrdered2( If_Cut_t * pC0, If_Cut_t * pC1, If_Cut_t * pC ) -{ - int i, k, c; - assert( pC0->nLeaves >= pC1->nLeaves ); - // copy the first cut - for ( i = 0; i < (int)pC0->nLeaves; i++ ) - pC->pLeaves[i] = pC0->pLeaves[i]; - pC->nLeaves = pC0->nLeaves; - // the case when one of the cuts is the largest - if ( pC0->nLeaves == pC->nLimit ) - return 1; - // add nodes of the second cut - k = 0; - for ( i = 0; i < (int)pC1->nLeaves; i++ ) - { - // find k-th node before which i-th node should be added - for ( ; k < (int)pC->nLeaves; k++ ) - if ( pC->pLeaves[k] >= pC1->pLeaves[i] ) - break; - // check the case when this should be the last node - if ( k == (int)pC->nLeaves ) - { - pC->pLeaves[k++] = pC1->pLeaves[i]; - pC->nLeaves++; - continue; - } - // check the case when equal node is found - if ( pC1->pLeaves[i] == pC->pLeaves[k] ) - continue; - // add the node - for ( c = (int)pC->nLeaves; c > k; c-- ) - pC->pLeaves[c] = pC->pLeaves[c-1]; - pC->pLeaves[k++] = pC1->pLeaves[i]; - pC->nLeaves++; - } -/* - assert( pC->nLeaves <= pC->nLimit ); - for ( i = 1; i < (int)pC->nLeaves; i++ ) - assert( pC->pLeaves[i-1] < pC->pLeaves[i] ); -*/ - return 1; -} - -/**Function************************************************************* - - Synopsis [Prepares the object for FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_CutMerge( If_Cut_t * pCut0, If_Cut_t * pCut1, If_Cut_t * pCut ) -{ - assert( pCut->nLimit > 0 ); - // merge the nodes - if ( pCut0->nLeaves < pCut1->nLeaves ) - { - if ( !If_CutMergeOrdered( pCut1, pCut0, pCut ) ) - return 0; - } - else - { - if ( !If_CutMergeOrdered( pCut0, pCut1, pCut ) ) - return 0; - } - pCut->uSign = pCut0->uSign | pCut1->uSign; - return 1; -} - -/**Function************************************************************* - - Synopsis [Prepares the object for FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_CutCompareDelay( If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) -{ - If_Cut_t * pC0 = *ppC0; - If_Cut_t * pC1 = *ppC1; - if ( pC0->Delay < pC1->Delay - 0.0001 ) - return -1; - if ( pC0->Delay > pC1->Delay + 0.0001 ) - return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; - if ( pC0->Area < pC1->Area - 0.0001 ) - return -1; - if ( pC0->Area > pC1->Area + 0.0001 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Prepares the object for FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_CutCompareDelayOld( If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) -{ - If_Cut_t * pC0 = *ppC0; - If_Cut_t * pC1 = *ppC1; - if ( pC0->Delay < pC1->Delay - 0.0001 ) - return -1; - if ( pC0->Delay > pC1->Delay + 0.0001 ) - return 1; - if ( pC0->Area < pC1->Area - 0.0001 ) - return -1; - if ( pC0->Area > pC1->Area + 0.0001 ) - return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Prepares the object for FPGA mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_CutCompareArea( If_Cut_t ** ppC0, If_Cut_t ** ppC1 ) -{ - If_Cut_t * pC0 = *ppC0; - If_Cut_t * pC1 = *ppC1; - if ( pC0->Area < pC1->Area - 0.0001 ) - return -1; - if ( pC0->Area > pC1->Area + 0.0001 ) - return 1; - if ( pC0->AveRefs > pC1->AveRefs ) - return -1; - if ( pC0->AveRefs < pC1->AveRefs ) - return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; - if ( pC0->Delay < pC1->Delay - 0.0001 ) - return -1; - if ( pC0->Delay > pC1->Delay + 0.0001 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Sorts the cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManSortCuts( If_Man_t * p, int Mode ) -{ -/* - // sort the cuts - if ( Mode || p->pPars->fArea ) // area - qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareArea ); - else if ( p->pPars->fFancy ) - qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelayOld ); - else - qsort( p->ppCuts, p->nCuts, sizeof(If_Cut_t *), (int (*)(const void *, const void *))If_CutCompareDelay ); -*/ -} - -/**Function************************************************************* - - Synopsis [Comparison function for two cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int If_ManSortCompare( If_Man_t * p, If_Cut_t * pC0, If_Cut_t * pC1 ) -{ - if ( p->SortMode == 1 ) // area - { - if ( pC0->Area < pC1->Area - 0.0001 ) - return -1; - if ( pC0->Area > pC1->Area + 0.0001 ) - return 1; - if ( pC0->AveRefs > pC1->AveRefs ) - return -1; - if ( pC0->AveRefs < pC1->AveRefs ) - return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; - if ( pC0->Delay < pC1->Delay - 0.0001 ) - return -1; - if ( pC0->Delay > pC1->Delay + 0.0001 ) - return 1; - return 0; - } - if ( p->SortMode == 0 ) // delay - { - if ( pC0->Delay < pC1->Delay - 0.0001 ) - return -1; - if ( pC0->Delay > pC1->Delay + 0.0001 ) - return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; - if ( pC0->Area < pC1->Area - 0.0001 ) - return -1; - if ( pC0->Area > pC1->Area + 0.0001 ) - return 1; - return 0; - } - assert( p->SortMode == 2 ); // delay old - if ( pC0->Delay < pC1->Delay - 0.0001 ) - return -1; - if ( pC0->Delay > pC1->Delay + 0.0001 ) - return 1; - if ( pC0->Area < pC1->Area - 0.0001 ) - return -1; - if ( pC0->Area > pC1->Area + 0.0001 ) - return 1; - if ( pC0->nLeaves < pC1->nLeaves ) - return -1; - if ( pC0->nLeaves > pC1->nLeaves ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Performs incremental sorting of cuts.] - - Description [Currently only the trivial sorting is implemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_CutSort( If_Man_t * p, If_Set_t * pCutSet, If_Cut_t * pCut ) -{ -// int Counter = 0; - int i; - - // the new cut is the last one - assert( pCutSet->ppCuts[pCutSet->nCuts] == pCut ); - assert( pCutSet->nCuts <= pCutSet->nCutsMax ); - - // cut structure is empty - if ( pCutSet->nCuts == 0 ) - { - pCutSet->nCuts++; - return; - } - - // the cut will be added - find its place - for ( i = pCutSet->nCuts-1; i >= 0; i-- ) - { -// Counter++; - if ( If_ManSortCompare( p, pCutSet->ppCuts[i], pCut ) <= 0 ) - break; - pCutSet->ppCuts[i+1] = pCutSet->ppCuts[i]; - pCutSet->ppCuts[i] = pCut; - } -// printf( "%d ", Counter ); - - // update the number of cuts - if ( pCutSet->nCuts < pCutSet->nCutsMax ) - pCutSet->nCuts++; -} - -/**Function************************************************************* - - Synopsis [Computes area flow.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutFlow( If_Man_t * p, If_Cut_t * pCut ) -{ - If_Obj_t * pLeaf; - float Flow; - int i; - assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); - Flow = If_CutLutArea(p, pCut); - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - if ( pLeaf->nRefs == 0 ) - Flow += If_ObjCutBest(pLeaf)->Area; - else if ( p->pPars->fSeqMap ) // seq - Flow += If_ObjCutBest(pLeaf)->Area / pLeaf->nRefs; - else - { - assert( pLeaf->EstRefs > p->fEpsilon ); - Flow += If_ObjCutBest(pLeaf)->Area / pLeaf->EstRefs; - } - } - return Flow; -} - -/**Function************************************************************* - - Synopsis [Average number of references of the leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutAverageRefs( If_Man_t * p, If_Cut_t * pCut ) -{ - If_Obj_t * pLeaf; - int nRefsTotal, i; - assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); - nRefsTotal = 0; - If_CutForEachLeaf( p, pCut, pLeaf, i ) - nRefsTotal += pLeaf->nRefs; - return ((float)nRefsTotal)/pCut->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Computes area of the first level.] - - Description [The cut need to be derefed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutDeref( If_Man_t * p, If_Cut_t * pCut, int nLevels ) -{ - If_Obj_t * pLeaf; - float Area; - int i; - Area = If_CutLutArea(p, pCut); - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - assert( pLeaf->nRefs > 0 ); - if ( --pLeaf->nRefs > 0 || !If_ObjIsAnd(pLeaf) || nLevels == 1 ) - continue; - Area += If_CutDeref( p, If_ObjCutBest(pLeaf), nLevels - 1 ); - } - return Area; -} - -/**Function************************************************************* - - Synopsis [Computes area of the first level.] - - Description [The cut need to be derefed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutRef( If_Man_t * p, If_Cut_t * pCut, int nLevels ) -{ - If_Obj_t * pLeaf; - float Area; - int i; - Area = If_CutLutArea(p, pCut); - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - assert( pLeaf->nRefs >= 0 ); - if ( pLeaf->nRefs++ > 0 || !If_ObjIsAnd(pLeaf) || nLevels == 1 ) - continue; - Area += If_CutRef( p, If_ObjCutBest(pLeaf), nLevels - 1 ); - } - return Area; -} - -/**Function************************************************************* - - Synopsis [Prints one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_CutPrint( If_Man_t * p, If_Cut_t * pCut ) -{ - unsigned i; - printf( "{" ); - for ( i = 0; i < pCut->nLeaves; i++ ) - printf( " %d", pCut->pLeaves[i] ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_CutPrintTiming( If_Man_t * p, If_Cut_t * pCut ) -{ - If_Obj_t * pLeaf; - unsigned i; - printf( "{" ); - If_CutForEachLeaf( p, pCut, pLeaf, i ) - printf( " %d(%.2f/%.2f)", pLeaf->Id, If_ObjCutBest(pLeaf)->Delay, pLeaf->Required ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [Computes area of the first level.] - - Description [The cut need to be derefed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutAreaDerefed( If_Man_t * p, If_Cut_t * pCut, int nLevels ) -{ - float aResult, aResult2; - assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); - aResult2 = If_CutRef( p, pCut, nLevels ); - aResult = If_CutDeref( p, pCut, nLevels ); - assert( aResult > aResult2 - p->fEpsilon ); - assert( aResult < aResult2 + p->fEpsilon ); - return aResult; -} - -/**Function************************************************************* - - Synopsis [Computes area of the first level.] - - Description [The cut need to be derefed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutAreaRefed( If_Man_t * p, If_Cut_t * pCut, int nLevels ) -{ - float aResult, aResult2; - assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); - aResult2 = If_CutDeref( p, pCut, nLevels ); - aResult = If_CutRef( p, pCut, nLevels ); - assert( aResult > aResult2 - p->fEpsilon ); - assert( aResult < aResult2 + p->fEpsilon ); - return aResult; -} - -/**Function************************************************************* - - Synopsis [Moves the cut over the latch.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_CutLift( If_Cut_t * pCut ) -{ - unsigned i; - for ( i = 0; i < pCut->nLeaves; i++ ) - { - assert( (pCut->pLeaves[i] & 255) < 255 ); - pCut->pLeaves[i]++; - } -} - -/**Function************************************************************* - - Synopsis [Computes area of the first level.] - - Description [The cut need to be derefed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_CutCopy( If_Man_t * p, If_Cut_t * pCutDest, If_Cut_t * pCutSrc ) -{ - int * pLeaves; - char * pPerm; - unsigned * pTruth; - // save old arrays - pLeaves = pCutDest->pLeaves; - pPerm = pCutDest->pPerm; - pTruth = pCutDest->pTruth; - // copy the cut info - memcpy( pCutDest, pCutSrc, p->nCutBytes ); - // restore the arrays - pCutDest->pLeaves = pLeaves; - pCutDest->pPerm = pPerm; - pCutDest->pTruth = pTruth; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/ifMan.c b/src/map/if/ifMan.c deleted file mode 100644 index b713d80d..00000000 --- a/src/map/if/ifMan.c +++ /dev/null @@ -1,570 +0,0 @@ -/**CFile**************************************************************** - - FileName [ifMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapping based on priority cuts.] - - Synopsis [Mapping manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: ifMan.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "if.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static If_Obj_t * If_ManSetupObj( If_Man_t * p ); - -static void If_ManCutSetRecycle( If_Man_t * p, If_Set_t * pSet ) { pSet->pNext = p->pFreeList; p->pFreeList = pSet; } -static If_Set_t * If_ManCutSetFetch( If_Man_t * p ) { If_Set_t * pTemp = p->pFreeList; p->pFreeList = p->pFreeList->pNext; return pTemp; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the AIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Man_t * If_ManStart( If_Par_t * pPars ) -{ - If_Man_t * p; - // start the manager - p = ALLOC( If_Man_t, 1 ); - memset( p, 0, sizeof(If_Man_t) ); - p->pPars = pPars; - p->fEpsilon = (float)0.001; - // allocate arrays for nodes - p->vCis = Vec_PtrAlloc( 100 ); - p->vCos = Vec_PtrAlloc( 100 ); - p->vObjs = Vec_PtrAlloc( 100 ); - p->vMapped = Vec_PtrAlloc( 100 ); - p->vTemp = Vec_PtrAlloc( 100 ); - // prepare the memory manager - p->nTruthWords = p->pPars->fTruth? If_CutTruthWords( p->pPars->nLutSize ) : 0; - p->nPermWords = p->pPars->fUsePerm? If_CutPermWords( p->pPars->nLutSize ) : 0; - p->nObjBytes = sizeof(If_Obj_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords); - p->nCutBytes = sizeof(If_Cut_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords); - p->nSetBytes = sizeof(If_Set_t) + (sizeof(If_Cut_t *) + p->nCutBytes) * (p->pPars->nCutsMax + 1); - p->pMemObj = Mem_FixedStart( p->nObjBytes ); -// p->pMemSet = Mem_FixedStart( p->nSetBytes ); - // report expected memory usage - if ( p->pPars->fVerbose ) - printf( "Memory (bytes): Truth = %4d. Cut = %4d. Obj = %4d. Set = %4d.\n", - 4 * p->nTruthWords, p->nCutBytes, p->nObjBytes, p->nSetBytes ); - // room for temporary truth tables - p->puTemp[0] = p->pPars->fTruth? ALLOC( unsigned, 4 * p->nTruthWords ) : NULL; - p->puTemp[1] = p->puTemp[0] + p->nTruthWords; - p->puTemp[2] = p->puTemp[1] + p->nTruthWords; - p->puTemp[3] = p->puTemp[2] + p->nTruthWords; - // create the constant node - p->pConst1 = If_ManSetupObj( p ); - p->pConst1->Type = IF_CONST1; - p->pConst1->fPhase = 1; - p->nObjs[IF_CONST1]++; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManRestart( If_Man_t * p ) -{ - FREE( p->pMemCi ); - Vec_PtrClear( p->vCis ); - Vec_PtrClear( p->vCos ); - Vec_PtrClear( p->vObjs ); - Vec_PtrClear( p->vMapped ); - Vec_PtrClear( p->vTemp ); - Mem_FixedRestart( p->pMemObj ); - // create the constant node - p->pConst1 = If_ManSetupObj( p ); - p->pConst1->Type = IF_CONST1; - p->pConst1->fPhase = 1; - // reset the counter of other nodes - p->nObjs[IF_CI] = p->nObjs[IF_CO] = p->nObjs[IF_AND] = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManStop( If_Man_t * p ) -{ - Vec_PtrFree( p->vCis ); - Vec_PtrFree( p->vCos ); - Vec_PtrFree( p->vObjs ); - Vec_PtrFree( p->vMapped ); - Vec_PtrFree( p->vTemp ); - if ( p->vLatchOrder ) Vec_PtrFree( p->vLatchOrder ); - if ( p->vLags ) Vec_IntFree( p->vLags ); - Mem_FixedStop( p->pMemObj, 0 ); - FREE( p->pMemCi ); - FREE( p->pMemAnd ); - FREE( p->puTemp[0] ); - // free pars memory - if ( p->pPars->pTimesArr ) - FREE( p->pPars->pTimesArr ); - if ( p->pPars->pTimesReq ) - FREE( p->pPars->pTimesReq ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Creates primary input.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * If_ManCreateCi( If_Man_t * p ) -{ - If_Obj_t * pObj; - pObj = If_ManSetupObj( p ); - pObj->Type = IF_CI; - Vec_PtrPush( p->vCis, pObj ); - p->nObjs[IF_CI]++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Creates primary output with the given driver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver ) -{ - If_Obj_t * pObj; - pObj = If_ManSetupObj( p ); - Vec_PtrPush( p->vCos, pObj ); - pObj->Type = IF_CO; - pObj->fCompl0 = If_IsComplement(pDriver); pDriver = If_Regular(pDriver); - pObj->pFanin0 = pDriver; pDriver->nRefs++; - p->nObjs[IF_CO]++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ) -{ - If_Obj_t * pObj; - // perform constant propagation - if ( pFan0 == pFan1 ) - return pFan0; - if ( pFan0 == If_Not(pFan1) ) - return If_Not(p->pConst1); - if ( If_Regular(pFan0) == p->pConst1 ) - return pFan0 == p->pConst1 ? pFan1 : If_Not(p->pConst1); - if ( If_Regular(pFan1) == p->pConst1 ) - return pFan1 == p->pConst1 ? pFan0 : If_Not(p->pConst1); - // get memory for the new object - pObj = If_ManSetupObj( p ); - pObj->Type = IF_AND; - pObj->fCompl0 = If_IsComplement(pFan0); pFan0 = If_Regular(pFan0); - pObj->fCompl1 = If_IsComplement(pFan1); pFan1 = If_Regular(pFan1); - pObj->pFanin0 = pFan0; pFan0->nRefs++; pFan0->nVisits++; pFan0->nVisitsCopy++; - pObj->pFanin1 = pFan1; pFan1->nRefs++; pFan1->nVisits++; pFan1->nVisitsCopy++; - pObj->fPhase = (pObj->fCompl0 ^ pFan0->fPhase) & (pObj->fCompl1 ^ pFan1->fPhase); - pObj->Level = 1 + IF_MAX( pFan0->Level, pFan1->Level ); - if ( p->nLevelMax < (int)pObj->Level ) - p->nLevelMax = (int)pObj->Level; - p->nObjs[IF_AND]++; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * If_ManCreateXor( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ) -{ - If_Obj_t * pRes1, * pRes2; - pRes1 = If_ManCreateAnd( p, If_Not(pFan0), pFan1 ); - pRes2 = If_ManCreateAnd( p, pFan0, If_Not(pFan1) ); - return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) ); -} - -/**Function************************************************************* - - Synopsis [Create the new node assuming it does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * If_ManCreateMux( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1, If_Obj_t * pCtrl ) -{ - If_Obj_t * pRes1, * pRes2; - pRes1 = If_ManCreateAnd( p, pFan0, If_Not(pCtrl) ); - pRes2 = If_ManCreateAnd( p, pFan1, pCtrl ); - return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) ); -} - -/**Function************************************************************* - - Synopsis [Creates the choice node.] - - Description [Should be called after the equivalence class nodes are linked.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj ) -{ - If_Obj_t * pTemp; - // mark the node as a representative if its class - assert( pObj->fRepr == 0 ); - pObj->fRepr = 1; - // update the level of this node (needed for correct required time computation) - for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) - { - pObj->Level = IF_MAX( pObj->Level, pTemp->Level ); - pTemp->nVisits++; pTemp->nVisitsCopy++; - } - // mark the largest level - if ( p->nLevelMax < (int)pObj->Level ) - p->nLevelMax = (int)pObj->Level; -} - -/**Function************************************************************* - - Synopsis [Prepares memory for one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManSetupCut( If_Man_t * p, If_Cut_t * pCut ) -{ - memset( pCut, 0, sizeof(If_Cut_t) ); - pCut->nLimit = p->pPars->nLutSize; - pCut->pLeaves = (int *)(pCut + 1); - if ( p->pPars->fUsePerm ) - pCut->pPerm = (char *)(pCut->pLeaves + p->pPars->nLutSize); - if ( p->pPars->fTruth ) - pCut->pTruth = pCut->pLeaves + p->pPars->nLutSize + p->nPermWords; -} - -/**Function************************************************************* - - Synopsis [Prepares memory for one cutset.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManSetupSet( If_Man_t * p, If_Set_t * pSet ) -{ - char * pArray; - int i; - pSet->nCuts = 0; - pSet->nCutsMax = p->pPars->nCutsMax; - pSet->ppCuts = (If_Cut_t **)(pSet + 1); - pArray = (char *)pSet->ppCuts + sizeof(If_Cut_t *) * (pSet->nCutsMax+1); - for ( i = 0; i <= pSet->nCutsMax; i++ ) - { - pSet->ppCuts[i] = (If_Cut_t *)(pArray + i * p->nCutBytes); - If_ManSetupCut( p, pSet->ppCuts[i] ); - } -// pArray += (pSet->nCutsMax + 1) * p->nCutBytes; -// assert( ((char *)pArray) - ((char *)pSet) == p->nSetBytes ); -} - -/**Function************************************************************* - - Synopsis [Prepares memory for one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId ) -{ - pCut->fCompl = 0; - pCut->nLimit = p->pPars->nLutSize; - pCut->nLeaves = 1; - pCut->pLeaves[0] = p->pPars->fLiftLeaves? (ObjId << 8) : ObjId; - pCut->uSign = If_ObjCutSign( pCut->pLeaves[0] ); - // set up elementary truth table of the unit cut - if ( p->pPars->fTruth ) - { - int i, nTruthWords; - nTruthWords = pCut->nLimit <= 5 ? 1 : (1 << (pCut->nLimit - 5)); - for ( i = 0; i < nTruthWords; i++ ) - If_CutTruth(pCut)[i] = 0xAAAAAAAA; - } -} - -/**Function************************************************************* - - Synopsis [Prepares memory for the node with cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * If_ManSetupObj( If_Man_t * p ) -{ - If_Obj_t * pObj; - // get memory for the object - pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMemObj ); - memset( pObj, 0, sizeof(If_Obj_t) ); - If_ManSetupCut( p, &pObj->CutBest ); - // assign ID and save - pObj->Id = Vec_PtrSize(p->vObjs); - Vec_PtrPush( p->vObjs, pObj ); - // set the required times - pObj->Required = IF_FLOAT_LARGE; - return pObj; -} - -/**Function************************************************************* - - Synopsis [Prepares memory for one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManSetupCiCutSets( If_Man_t * p ) -{ - If_Obj_t * pObj; - int i; - assert( p->pMemCi == NULL ); - // create elementary cuts for the CIs - If_ManForEachCi( p, pObj, i ) - If_ManSetupCutTriv( p, &pObj->CutBest, pObj->Id ); - // create elementary cutsets for the CIs - p->pMemCi = (If_Set_t *)malloc( If_ManCiNum(p) * (sizeof(If_Set_t) + sizeof(void *)) ); - If_ManForEachCi( p, pObj, i ) - { - pObj->pCutSet = (If_Set_t *)((char *)p->pMemCi + i * (sizeof(If_Set_t) + sizeof(void *))); - pObj->pCutSet->nCuts = 1; - pObj->pCutSet->nCutsMax = p->pPars->nCutsMax; - pObj->pCutSet->ppCuts = (If_Cut_t **)(pObj->pCutSet + 1); - pObj->pCutSet->ppCuts[0] = &pObj->CutBest; - } -} - -/**Function************************************************************* - - Synopsis [Prepares cutset of the node.] - - Description [Elementary cutset will be added last.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj ) -{ - assert( If_ObjIsAnd(pObj) ); - assert( pObj->pCutSet == NULL ); -// pObj->pCutSet = (If_Set_t *)Mem_FixedEntryFetch( p->pMemSet ); -// If_ManSetupSet( p, pObj->pCutSet ); - - pObj->pCutSet = If_ManCutSetFetch( p ); - pObj->pCutSet->nCuts = 0; - pObj->pCutSet->nCutsMax = p->pPars->nCutsMax; - - return pObj->pCutSet; -} - -/**Function************************************************************* - - Synopsis [Dereferences cutset of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj ) -{ - If_Obj_t * pFanin; - assert( If_ObjIsAnd(pObj) ); - // consider the node - assert( pObj->nVisits >= 0 ); - if ( pObj->nVisits == 0 ) - { -// Mem_FixedEntryRecycle( p->pMemSet, (char *)pObj->pCutSet ); - If_ManCutSetRecycle( p, pObj->pCutSet ); - pObj->pCutSet = NULL; - } - // consider the first fanin - pFanin = If_ObjFanin0(pObj); - assert( pFanin->nVisits > 0 ); - if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) - { -// Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet ); - If_ManCutSetRecycle( p, pFanin->pCutSet ); - pFanin->pCutSet = NULL; - } - // consider the second fanin - pFanin = If_ObjFanin1(pObj); - assert( pFanin->nVisits > 0 ); - if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) - { -// Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet ); - If_ManCutSetRecycle( p, pFanin->pCutSet ); - pFanin->pCutSet = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Dereferences cutset of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj ) -{ - If_Obj_t * pTemp; - assert( If_ObjIsAnd(pObj) ); - assert( pObj->fRepr ); - assert( pObj->nVisits > 0 ); - // consider the nodes in the choice class - for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) - { - assert( pTemp == pObj || pTemp->nVisits == 1 ); - if ( --pTemp->nVisits == 0 ) - { -// Mem_FixedEntryRecycle( p->pMemSet, (char *)pTemp->pCutSet ); - If_ManCutSetRecycle( p, pTemp->pCutSet ); - pTemp->pCutSet = NULL; - } - } -} - -/**Function************************************************************* - - Synopsis [Dereferences cutset of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManSetupSetAll( If_Man_t * p, int nCrossCut ) -{ - If_Set_t * pCutSet; - int i, nCutSets; - nCutSets = 128 + nCrossCut; - p->pFreeList = p->pMemAnd = pCutSet = (If_Set_t *)malloc( nCutSets * p->nSetBytes ); - for ( i = 0; i < nCutSets; i++ ) - { - If_ManSetupSet( p, pCutSet ); - if ( i == nCutSets - 1 ) - pCutSet->pNext = NULL; - else - pCutSet->pNext = (If_Set_t *)( (char *)pCutSet + p->nSetBytes ); - pCutSet = pCutSet->pNext; - } - assert( pCutSet == NULL ); - - if ( p->pPars->fVerbose ) - { - printf( "Node = %7d. Ch = %5d. Total mem = %7.2f Mb. Peak cut mem = %7.2f Mb.\n", - If_ManAndNum(p), p->nChoices, - 1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20), - 1.0 * p->nSetBytes * nCrossCut / (1<<20) ); - } -// printf( "Cross cut = %d.\n", nCrossCut ); - -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/ifMap.c b/src/map/if/ifMap.c deleted file mode 100644 index e3f0dfda..00000000 --- a/src/map/if/ifMap.c +++ /dev/null @@ -1,300 +0,0 @@ -/**CFile**************************************************************** - - FileName [ifMap.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapping based on priority cuts.] - - Synopsis [Mapping procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: ifMap.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "if.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Counts the number of 1s in the signature.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int If_WordCountOnes( unsigned uWord ) -{ - uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); - uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); - uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); - uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); - return (uWord & 0x0000FFFF) + (uWord>>16); -} - -/**Function************************************************************* - - Synopsis [Finds the best cut for the given node.] - - Description [Mapping modes: delay (0), area flow (1), area (2).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ObjPerformMappingAnd( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess ) -{ - If_Set_t * pCutSet; - If_Cut_t * pCut0, * pCut1, * pCut; - int i, k; - - assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin0) || pObj->pFanin0->pCutSet->nCuts > 1 ); - assert( p->pPars->fSeqMap || !If_ObjIsAnd(pObj->pFanin1) || pObj->pFanin1->pCutSet->nCuts > 1 ); - - // prepare - if ( !p->pPars->fSeqMap ) - { - if ( Mode == 0 ) - pObj->EstRefs = (float)pObj->nRefs; - else if ( Mode == 1 ) - pObj->EstRefs = (float)((2.0 * pObj->EstRefs + pObj->nRefs) / 3.0); - } - if ( Mode && pObj->nRefs > 0 ) - If_CutDeref( p, If_ObjCutBest(pObj), IF_INFINITY ); - - // prepare the cutset - pCutSet = If_ManSetupNodeCutSet( p, pObj ); - - // get the current assigned best cut - pCut = If_ObjCutBest(pObj); - if ( pCut->nLeaves > 0 ) - { - // recompute the parameters of the best cut - pCut->Delay = If_CutDelay( p, pCut ); - assert( pCut->Delay <= pObj->Required + p->fEpsilon ); - pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut ); - // save the best cut from the previous iteration - if ( !fPreprocess ) - If_CutCopy( p, pCutSet->ppCuts[pCutSet->nCuts++], pCut ); - } - - // generate cuts - If_ObjForEachCut( pObj->pFanin0, pCut0, i ) - If_ObjForEachCut( pObj->pFanin1, pCut1, k ) - { - // get the next free cut - assert( pCutSet->nCuts <= pCutSet->nCutsMax ); - pCut = pCutSet->ppCuts[pCutSet->nCuts]; - // make sure K-feasible cut exists - if ( If_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->pPars->nLutSize ) - continue; - // merge the nodes - if ( !If_CutMerge( pCut0, pCut1, pCut ) ) - continue; - assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); - p->nCutsMerged++; - // check if this cut is contained in any of the available cuts -// if ( p->pPars->pFuncCost == NULL && If_CutFilter( p, pCut ) ) // do not filter functionality cuts - if ( If_CutFilter( pCutSet, pCut ) ) - continue; - // compute the truth table - pCut->fCompl = 0; - if ( p->pPars->fTruth ) - If_CutComputeTruth( p, pCut, pCut0, pCut1, pObj->fCompl0, pObj->fCompl1 ); - // compute the application-specific cost and depth - pCut->fUser = (p->pPars->pFuncCost != NULL); - pCut->Cost = p->pPars->pFuncCost? p->pPars->pFuncCost(pCut) : 0; - if ( pCut->Cost == IF_COST_MAX ) - continue; - // check if the cut satisfies the required times - pCut->Delay = If_CutDelay( p, pCut ); -// printf( "%.2f ", pCut->Delay ); - if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon ) - continue; - // compute area of the cut (this area may depend on the application specific cost) - pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut ); - pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut ); - // insert the cut into storage - If_CutSort( p, pCutSet, pCut ); - } - assert( pCutSet->nCuts > 0 ); - - // add the trivial cut to the set - If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id ); - assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 ); - - // update the best cut - if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon ) - If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] ); - assert( p->pPars->fSeqMap || If_ObjCutBest(pObj)->nLeaves > 1 ); - - // ref the selected cut - if ( Mode && pObj->nRefs > 0 ) - If_CutRef( p, If_ObjCutBest(pObj), IF_INFINITY ); - - // call the user specified function for each cut - if ( p->pPars->pFuncUser ) - If_ObjForEachCut( pObj, pCut, i ) - p->pPars->pFuncUser( p, pObj, pCut ); - - // free the cuts - If_ManDerefNodeCutSet( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Finds the best cut for the choice node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ObjPerformMappingChoice( If_Man_t * p, If_Obj_t * pObj, int Mode, int fPreprocess ) -{ - If_Set_t * pCutSet; - If_Obj_t * pTemp; - If_Cut_t * pCutTemp, * pCut; - int i; - assert( pObj->pEquiv != NULL ); - - // prepare - if ( Mode && pObj->nRefs > 0 ) - If_CutDeref( p, If_ObjCutBest(pObj), IF_INFINITY ); - - // remove elementary cuts - for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) - pTemp->pCutSet->nCuts--; - - // update the cutset of the node - pCutSet = pObj->pCutSet; - - // generate cuts - for ( pTemp = pObj->pEquiv; pTemp; pTemp = pTemp->pEquiv ) - { - assert( pTemp->nRefs == 0 ); - assert( p->pPars->fSeqMap || pTemp->pCutSet->nCuts > 0 ); - // go through the cuts of this node - If_ObjForEachCut( pTemp, pCutTemp, i ) - { - assert( p->pPars->fSeqMap || pCutTemp->nLeaves > 1 ); - // get the next free cut - assert( pCutSet->nCuts <= pCutSet->nCutsMax ); - pCut = pCutSet->ppCuts[pCutSet->nCuts]; - // copy the cut into storage - If_CutCopy( p, pCut, pCutTemp ); - // check if this cut is contained in any of the available cuts - if ( If_CutFilter( pCutSet, pCut ) ) - continue; - // check if the cut satisfies the required times - assert( pCut->Delay == If_CutDelay( p, pCut ) ); - if ( Mode && pCut->Delay > pObj->Required + p->fEpsilon ) - continue; - // set the phase attribute - assert( pCut->fCompl == 0 ); - pCut->fCompl ^= (pObj->fPhase ^ pTemp->fPhase); // why ^= ? - // compute area of the cut (this area may depend on the application specific cost) - pCut->Area = (Mode == 2)? If_CutAreaDerefed( p, pCut, IF_INFINITY ) : If_CutFlow( p, pCut ); - pCut->AveRefs = (Mode == 0)? (float)0.0 : If_CutAverageRefs( p, pCut ); - // insert the cut into storage - If_CutSort( p, pCutSet, pCut ); - } - } - assert( pCutSet->nCuts > 0 ); - - // add the trivial cut to the set - If_ManSetupCutTriv( p, pCutSet->ppCuts[pCutSet->nCuts++], pObj->Id ); - assert( pCutSet->nCuts <= pCutSet->nCutsMax+1 ); - - // update the best cut - if ( !fPreprocess || pCutSet->ppCuts[0]->Delay <= pObj->Required + p->fEpsilon ) - If_CutCopy( p, If_ObjCutBest(pObj), pCutSet->ppCuts[0] ); - assert( p->pPars->fSeqMap || If_ObjCutBest(pObj)->nLeaves > 1 ); - - // ref the selected cut - if ( Mode && pObj->nRefs > 0 ) - If_CutRef( p, If_ObjCutBest(pObj), IF_INFINITY ); - - // free the cuts - If_ManDerefChoiceCutSet( p, pObj ); -} - -/**Function************************************************************* - - Synopsis [Performs one mapping pass over all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManPerformMappingRound( If_Man_t * p, int nCutsUsed, int Mode, int fPreprocess, char * pLabel ) -{ -// ProgressBar * pProgress; - If_Obj_t * pObj; - int i, clk = clock(); - assert( Mode >= 0 && Mode <= 2 ); - // set the sorting function - if ( Mode || p->pPars->fArea ) // area - p->SortMode = 1; - else if ( p->pPars->fFancy ) - p->SortMode = 2; - else - p->SortMode = 0; - // set the cut number - p->nCutsUsed = nCutsUsed; - p->nCutsMerged = 0; - // map the internal nodes -// pProgress = Extra_ProgressBarStart( stdout, If_ManObjNum(p) ); - If_ManForEachNode( p, pObj, i ) - { -// Extra_ProgressBarUpdate( pProgress, i, pLabel ); - If_ObjPerformMappingAnd( p, pObj, Mode, fPreprocess ); - if ( pObj->fRepr ) - If_ObjPerformMappingChoice( p, pObj, Mode, fPreprocess ); - } -// Extra_ProgressBarStop( pProgress ); - // make sure the visit counters are all zero - If_ManForEachNode( p, pObj, i ) - assert( pObj->nVisits == 0 ); - // compute required times and stats - If_ManComputeRequired( p ); - if ( p->pPars->fVerbose ) - { - char Symb = fPreprocess? 'P' : ((Mode == 0)? 'D' : ((Mode == 1)? 'F' : 'A')); - printf( "%c: Del = %7.2f. Ar = %9.1f. Net = %8d. Cut = %8d. ", - Symb, p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged ); - PRT( "T", clock() - clk ); -// printf( "Max number of cuts = %d. Average number of cuts = %5.2f.\n", -// p->nCutsMax, 1.0 * p->nCutsMerged / If_ManAndNum(p) ); - } - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/ifReduce.c b/src/map/if/ifReduce.c deleted file mode 100644 index 9728b3db..00000000 --- a/src/map/if/ifReduce.c +++ /dev/null @@ -1,574 +0,0 @@ -/**CFile**************************************************************** - - FileName [ifExpand.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapping based on priority cuts.] - - Synopsis [Incremental improvement of current mapping.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: ifExpand.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "if.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void If_ManImproveReduce( If_Man_t * p, int nLimit ); -static void If_ManImproveExpand( If_Man_t * p, int nLimit ); -static void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ); -static void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ); -static void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront ); -static void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Improves current mapping using expand/Expand of one cut.] - - Description [Assumes current mapping assigned and required times computed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManImproveMapping( If_Man_t * p ) -{ - int clk; - - clk = clock(); - If_ManImproveExpand( p, p->pPars->nLutSize ); - If_ManComputeRequired( p ); - if ( p->pPars->fVerbose ) - { - printf( "E: Del = %7.2f. Ar = %9.1f. Net = %8d. Cut = %8d. ", - p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged ); - PRT( "T", clock() - clk ); - } - -/* - clk = clock(); - If_ManImproveReduce( p, p->pPars->nLutSize ); - If_ManComputeRequired( p, 0 ); - if ( p->pPars->fVerbose ) - { - printf( "R: Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ", - p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) ); - PRT( "T", clock() - clk ); - } -*/ -/* - clk = clock(); - If_ManImproveExpand( p, p->pPars->nLutSize ); - If_ManComputeRequired( p, 0 ); - if ( p->pPars->fVerbose ) - { - printf( "E: Del = %6.2f. Area = %8.2f. Nets = %6d. Cuts = %8d. Lim = %2d. Ave = %5.2f. ", - p->RequiredGlo, p->AreaGlo, p->nNets, p->nCutsMerged, p->nCutsUsed, 1.0 * p->nCutsMerged / If_ManAndNum(p) ); - PRT( "T", clock() - clk ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManImproveExpand( If_Man_t * p, int nLimit ) -{ - Vec_Ptr_t * vFront, * vFrontOld, * vVisited; - If_Obj_t * pObj; - int i; - vFront = Vec_PtrAlloc( nLimit ); - vFrontOld = Vec_PtrAlloc( nLimit ); - vVisited = Vec_PtrAlloc( 100 ); - // iterate through all nodes in the topological order - If_ManForEachNode( p, pObj, i ) - If_ManImproveNodeExpand( p, pObj, nLimit, vFront, vFrontOld, vVisited ); - Vec_PtrFree( vFront ); - Vec_PtrFree( vFrontOld ); - Vec_PtrFree( vVisited ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of nodes with no external fanout.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManImproveCutCost( If_Man_t * p, Vec_Ptr_t * vFront ) -{ - If_Obj_t * pFanin; - int i, Counter = 0; - Vec_PtrForEachEntry( vFront, pFanin, i ) - if ( pFanin->nRefs == 0 ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManImproveNodeExpand( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ) -{ - If_Obj_t * pFanin; - If_Cut_t * pCut; - int CostBef, CostAft, i; - float DelayOld, AreaBef, AreaAft; - pCut = If_ObjCutBest(pObj); - assert( pCut->Delay <= pObj->Required + p->fEpsilon ); - if ( pObj->nRefs == 0 ) - return; - // get the delay - DelayOld = pCut->Delay; - // get the area - AreaBef = If_CutAreaRefed( p, pCut, IF_INFINITY ); -// if ( AreaBef == 1 ) -// return; - // the cut is non-trivial - If_ManImproveNodePrepare( p, pObj, nLimit, vFront, vFrontOld, vVisited ); - // iteratively modify the cut - If_CutDeref( p, pCut, IF_INFINITY ); - CostBef = If_ManImproveCutCost( p, vFront ); - If_ManImproveNodeFaninCompact( p, pObj, nLimit, vFront, vVisited ); - CostAft = If_ManImproveCutCost( p, vFront ); - If_CutRef( p, pCut, IF_INFINITY ); - assert( CostBef >= CostAft ); - // clean up - Vec_PtrForEachEntry( vVisited, pFanin, i ) - pFanin->fMark = 0; - // update the node - If_ManImproveNodeUpdate( p, pObj, vFront ); - pCut->Delay = If_CutDelay( p, pCut ); - // get the new area - AreaAft = If_CutAreaRefed( p, pCut, IF_INFINITY ); - if ( AreaAft > AreaBef || pCut->Delay > pObj->Required + p->fEpsilon ) - { - If_ManImproveNodeUpdate( p, pObj, vFrontOld ); - AreaAft = If_CutAreaRefed( p, pCut, IF_INFINITY ); - assert( AreaAft == AreaBef ); - pCut->Delay = DelayOld; - } -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManImproveMark_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vVisited ) -{ - if ( pObj->fMark ) - return; - assert( If_ObjIsAnd(pObj) ); - If_ManImproveMark_rec( p, If_ObjFanin0(pObj), vVisited ); - If_ManImproveMark_rec( p, If_ObjFanin1(pObj), vVisited ); - Vec_PtrPush( vVisited, pObj ); - pObj->fMark = 1; -} - -/**Function************************************************************* - - Synopsis [Prepares node mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManImproveNodePrepare( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld, Vec_Ptr_t * vVisited ) -{ - If_Cut_t * pCut; - If_Obj_t * pLeaf; - int i; - Vec_PtrClear( vFront ); - Vec_PtrClear( vFrontOld ); - Vec_PtrClear( vVisited ); - // expand the cut downwards from the given place - pCut = If_ObjCutBest(pObj); - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - Vec_PtrPush( vFront, pLeaf ); - Vec_PtrPush( vFrontOld, pLeaf ); - Vec_PtrPush( vVisited, pLeaf ); - pLeaf->fMark = 1; - } - // mark the nodes in the cone - If_ManImproveMark_rec( p, pObj, vVisited ); -} - -/**Function************************************************************* - - Synopsis [Updates the frontier.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManImproveNodeUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront ) -{ - If_Cut_t * pCut; - If_Obj_t * pFanin; - int i; - pCut = If_ObjCutBest(pObj); - // deref node's cut - If_CutDeref( p, pCut, IF_INFINITY ); - // update the node's cut - pCut->nLeaves = Vec_PtrSize(vFront); - Vec_PtrForEachEntry( vFront, pFanin, i ) - pCut->pLeaves[i] = pFanin->Id; - // ref the new cut - If_CutRef( p, pCut, IF_INFINITY ); -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if the number of fanins will grow.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManImproveNodeWillGrow( If_Man_t * p, If_Obj_t * pObj ) -{ - If_Obj_t * pFanin0, * pFanin1; - assert( If_ObjIsAnd(pObj) ); - pFanin0 = If_ObjFanin0(pObj); - pFanin1 = If_ObjFanin1(pObj); - return !pFanin0->fMark && !pFanin1->fMark; -} - -/**Function************************************************************* - - Synopsis [Returns the increase in the number of fanins with no external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManImproveNodeFaninCost( If_Man_t * p, If_Obj_t * pObj ) -{ - int Counter = 0; - assert( If_ObjIsAnd(pObj) ); - // check if the node has external refs - if ( pObj->nRefs == 0 ) - Counter--; - // increment the number of fanins without external refs - if ( !If_ObjFanin0(pObj)->fMark && If_ObjFanin0(pObj)->nRefs == 0 ) - Counter++; - // increment the number of fanins without external refs - if ( !If_ObjFanin1(pObj)->fMark && If_ObjFanin1(pObj)->nRefs == 0 ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Updates the frontier.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManImproveNodeFaninUpdate( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) -{ - If_Obj_t * pFanin; - assert( If_ObjIsAnd(pObj) ); - Vec_PtrRemove( vFront, pObj ); - pFanin = If_ObjFanin0(pObj); - if ( !pFanin->fMark ) - { - Vec_PtrPush( vFront, pFanin ); - Vec_PtrPush( vVisited, pFanin ); - pFanin->fMark = 1; - } - pFanin = If_ObjFanin1(pObj); - if ( !pFanin->fMark ) - { - Vec_PtrPush( vFront, pFanin ); - Vec_PtrPush( vVisited, pFanin ); - pFanin->fMark = 1; - } -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManImproveNodeFaninCompact0( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) -{ - If_Obj_t * pFanin; - int i; - Vec_PtrForEachEntry( vFront, pFanin, i ) - { - if ( If_ObjIsCi(pFanin) ) - continue; - if ( If_ManImproveNodeWillGrow(p, pFanin) ) - continue; - if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 ) - { - If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManImproveNodeFaninCompact1( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) -{ - If_Obj_t * pFanin; - int i; - Vec_PtrForEachEntry( vFront, pFanin, i ) - { - if ( If_ObjIsCi(pFanin) ) - continue; - if ( If_ManImproveNodeFaninCost(p, pFanin) < 0 ) - { - If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManImproveNodeFaninCompact2( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) -{ - If_Obj_t * pFanin; - int i; - Vec_PtrForEachEntry( vFront, pFanin, i ) - { - if ( If_ObjIsCi(pFanin) ) - continue; - if ( If_ManImproveNodeFaninCost(p, pFanin) <= 0 ) - { - If_ManImproveNodeFaninUpdate( p, pFanin, vFront, vVisited ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManImproveNodeFaninCompact_int( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) -{ - if ( If_ManImproveNodeFaninCompact0(p, pObj, nLimit, vFront, vVisited) ) - return 1; - if ( Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact1(p, pObj, nLimit, vFront, vVisited) ) - return 1; - if ( Vec_PtrSize(vFront) < nLimit && If_ManImproveNodeFaninCompact2(p, pObj, nLimit, vFront, vVisited) ) - return 1; - assert( Vec_PtrSize(vFront) <= nLimit ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Compacts the number of external refs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManImproveNodeFaninCompact( If_Man_t * p, If_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited ) -{ - while ( If_ManImproveNodeFaninCompact_int( p, pObj, nLimit, vFront, vVisited ) ); -} - - - - - -/**Function************************************************************* - - Synopsis [Performs fast mapping for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManImproveNodeReduce( If_Man_t * p, If_Obj_t * pObj, int nLimit ) -{ -/* - If_Cut_t * pCut, * pCut0, * pCut1, * pCutR; - If_Obj_t * pFanin0, * pFanin1; - float AreaBef, AreaAft; - int RetValue; - - assert( nLimit <= 32 ); - assert( If_ObjIsAnd(pObj) ); - // get the fanins - pFanin0 = If_ObjFanin0(pObj); - pFanin1 = If_ObjFanin1(pObj); - // get the cuts - pCut = If_ObjCutBest(pObj); - pCut0 = If_ObjIsCi(pFanin0) ? If_ObjCutTriv(pFanin0) : If_ObjCutBest(pFanin0); - pCut1 = If_ObjIsCi(pFanin1) ? If_ObjCutTriv(pFanin1) : If_ObjCutBest(pFanin1); - assert( pCut->Delay <= pObj->Required + p->fEpsilon ); - - // deref the cut if the node is refed - if ( pObj->nRefs > 0 ) - If_CutDeref( p, pCut, IF_INFINITY ); - // get the area - AreaBef = If_CutAreaDerefed( p, pCut, IF_INFINITY ); - // get the fanin support - if ( pFanin0->nRefs > 2 && pCut0->Delay < pObj->Required + p->fEpsilon ) -// if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results - { - pCut0 = If_ObjCutTriv(pFanin0); - } - // get the fanin support - if ( pFanin1->nRefs > 2 && pCut1->Delay < pObj->Required + p->fEpsilon ) -// if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR ) - { - pCut1 = If_ObjCutTriv(pFanin1); - } - - // merge the cuts - pCutR = p->ppCuts[0]; - RetValue = If_CutMerge( pCut0, pCut1, pCutR ); - // try very simple cut - if ( !RetValue ) - { - RetValue = If_CutMerge( If_ObjCutTriv(pFanin0), If_ObjCutTriv(pFanin1), pCutR ); - assert( RetValue == 1 ); - } - if ( RetValue ) - { - pCutR->Delay = If_CutDelay( p, pCutR ); - AreaAft = If_CutAreaDerefed( p, pCutR, IF_INFINITY ); - // update the best cut - if ( AreaAft < AreaBef - p->fEpsilon && pCutR->Delay < pObj->Required + p->fEpsilon ) - If_CutCopy( p, pCut, pCutR ); - } - // recompute the delay of the best cut - pCut->Delay = If_CutDelay( p, pCut ); - // ref the cut if the node is refed - if ( pObj->nRefs > 0 ) - If_CutRef( p, pCut, IF_INFINITY ); -*/ -} - -/**Function************************************************************* - - Synopsis [Performs area recovery for each node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManImproveReduce( If_Man_t * p, int nLimit ) -{ - If_Obj_t * pObj; - int i; - If_ManForEachNode( p, pObj, i ) - If_ManImproveNodeReduce( p, pObj, nLimit ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/ifSeq.c b/src/map/if/ifSeq.c deleted file mode 100644 index 8d1de8c1..00000000 --- a/src/map/if/ifSeq.c +++ /dev/null @@ -1,405 +0,0 @@ -/**CFile**************************************************************** - - FileName [ifSeq.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapping based on priority cuts.] - - Synopsis [Sequential mapping.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: ifSeq.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "if.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern int s_MappingTime; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Prepares for sequential mapping by linking the latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManPrepareMappingSeq( If_Man_t * p ) -{ - If_Obj_t * pObjLi, * pObjLo; - int i; - - // link the latch outputs (CIs) directly to the drivers of latch inputs (COs) - for ( i = 0; i < p->pPars->nLatches; i++ ) - { - pObjLi = If_ManLi( p, i ); - pObjLo = If_ManLo( p, i ); - pObjLo->pFanin0 = If_ObjFanin0( pObjLi ); - pObjLo->fCompl0 = If_ObjFaninC0( pObjLi ); - } -} - -/**Function************************************************************* - - Synopsis [Collects latches in the topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManCollectLatches_rec( If_Obj_t * pObj, Vec_Ptr_t * vLatches ) -{ - if ( !If_ObjIsLatch(pObj) ) - return; - if ( pObj->fMark ) - return; - pObj->fMark = 1; - If_ManCollectLatches_rec( pObj->pFanin0, vLatches ); - Vec_PtrPush( vLatches, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects latches in the topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * If_ManCollectLatches( If_Man_t * p ) -{ - Vec_Ptr_t * vLatches; - If_Obj_t * pObj; - int i; - // collect latches - vLatches = Vec_PtrAlloc( p->pPars->nLatches ); - If_ManForEachLatchOutput( p, pObj, i ) - If_ManCollectLatches_rec( pObj, vLatches ); - // clean marks - Vec_PtrForEachEntry( vLatches, pObj, i ) - pObj->fMark = 0; - assert( Vec_PtrSize(vLatches) == p->pPars->nLatches ); - return vLatches; -} - -/**Function************************************************************* - - Synopsis [Performs one pass of l-value computation over all nodes.] - - Description [Experimentally it was found that checking POs changes - is not enough to detect the convergence of l-values in the network.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManPerformMappingRoundSeq( If_Man_t * p, int nIter ) -{ - If_Obj_t * pObj; - int i, clk = clock(); - int fVeryVerbose = 0; - int fChange = 0; - - // map the internal nodes - p->nCutsMerged = 0; - If_ManForEachNode( p, pObj, i ) - { - If_ObjPerformMappingAnd( p, pObj, 0, 0 ); - if ( pObj->fRepr ) - If_ObjPerformMappingChoice( p, pObj, 0, 0 ); - } - - // postprocess the mapping -//printf( "Itereation %d: \n", nIter ); - If_ManForEachNode( p, pObj, i ) - { - // update the LValues stored separately - if ( If_ObjLValue(pObj) < If_ObjCutBest(pObj)->Delay - p->fEpsilon ) - { - If_ObjSetLValue( pObj, If_ObjCutBest(pObj)->Delay ); - fChange = 1; - } -//printf( "%d ", (int)If_ObjLValue(pObj) ); - // reset the visit counters - assert( pObj->nVisits == 0 ); - pObj->nVisits = pObj->nVisitsCopy; - } -//printf( "\n" ); - - // propagate LValues over the registers - Vec_PtrForEachEntry( p->vLatchOrder, pObj, i ) - { - If_ObjSetLValue( pObj, If_ObjLValue(If_ObjFanin0(pObj)) - p->Period ); - If_ObjSetArrTime( pObj, If_ObjLValue(pObj) ); - } - - // compute area and delay - if ( fVeryVerbose ) - { - p->RequiredGlo = If_ManDelayMax( p, 1 ); - p->AreaGlo = If_ManScanMapping(p); - printf( "S%d: Fi = %6.2f. Del = %6.2f. Area = %8.2f. Cuts = %8d. ", - nIter, (float)p->Period, p->RequiredGlo, p->AreaGlo, p->nCutsMerged ); - PRT( "T", clock() - clk ); - } - return fChange; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if retiming with this clock period is feasible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManBinarySearchPeriod( If_Man_t * p ) -{ - If_Obj_t * pObj; - int i, c, fConverged; - int fResetRefs = 0; - - p->nAttempts++; - - // reset initial LValues (PIs to 0; others to -inf) - If_ManForEachObj( p, pObj, i ) - { - if ( If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) ) - { - If_ObjSetLValue( pObj, (float)0.0 ); - If_ObjSetArrTime( pObj, (float)0.0 ); - } - else - { - If_ObjSetLValue( pObj, (float)-IF_INFINITY ); - If_ObjSetArrTime( pObj, (float)-IF_INFINITY ); - } - // undo any previous mapping, except for CIs - if ( If_ObjIsAnd(pObj) ) - If_ObjCutBest(pObj)->nLeaves = 0; - } - - // update all values iteratively - fConverged = 0; - for ( c = 1; c <= p->nMaxIters; c++ ) - { - if ( !If_ManPerformMappingRoundSeq( p, c ) ) - { - p->RequiredGlo = If_ManDelayMax( p, 1 ); - fConverged = 1; - break; - } - p->RequiredGlo = If_ManDelayMax( p, 1 ); -//printf( "Global = %d \n", (int)p->RequiredGlo ); - if ( p->RequiredGlo > p->Period + p->fEpsilon ) - break; - } - - // report the results - if ( p->pPars->fVerbose ) - { - p->AreaGlo = If_ManScanMapping(p); - printf( "Attempt = %2d. Iters = %3d. Area = %10.2f. Fi = %6.2f. ", p->nAttempts, c, p->AreaGlo, (float)p->Period ); - if ( fConverged ) - printf( " Feasible" ); - else if ( c > p->nMaxIters ) - printf( "Infeasible (timeout)" ); - else - printf( "Infeasible" ); - printf( "\n" ); - } - return fConverged; -} - - -/**Function************************************************************* - - Synopsis [Performs binary search for the optimal clock period.] - - Description [Assumes that FiMin is infeasible while FiMax is feasible.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManBinarySearch_rec( If_Man_t * p, int FiMin, int FiMax ) -{ - assert( FiMin < FiMax ); - if ( FiMin + 1 == FiMax ) - return FiMax; - // compute the median - p->Period = FiMin + (FiMax - FiMin)/2; - if ( If_ManBinarySearchPeriod( p ) ) - return If_ManBinarySearch_rec( p, FiMin, p->Period ); // Median is feasible - else - return If_ManBinarySearch_rec( p, p->Period, FiMax ); // Median is infeasible -} - -/**Function************************************************************* - - Synopsis [Performs sequential mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManPerformMappingSeqPost( If_Man_t * p ) -{ - If_Obj_t * pObjLi, * pObjLo, * pObj; - int i; - - // link the latch outputs (CIs) directly to the drivers of latch inputs (COs) - for ( i = 0; i < p->pPars->nLatches; i++ ) - { - pObjLi = If_ManLi( p, i ); - pObjLo = If_ManLo( p, i ); -// printf( "%3d : %2d -> %2d \n", i, -// (int)If_ObjLValue(If_ObjFanin0(pObjLo)), (int)If_ObjLValue(pObjLo) ); - } - - // set arrival times - assert( p->pPars->pTimesArr != NULL ); - If_ManForEachLatchOutput( p, pObjLo, i ) - p->pPars->pTimesArr[i] = If_ObjLValue(pObjLo); - - // set the required times - assert( p->pPars->pTimesReq == NULL ); - p->pPars->pTimesReq = ALLOC( float, If_ManCoNum(p) ); - If_ManForEachPo( p, pObj, i ) - { - p->pPars->pTimesReq[i] = p->RequiredGlo2; -// printf( "Out %3d : %2d \n", i, (int)p->pPars->pTimesReq[i] ); - } - If_ManForEachLatchInput( p, pObjLi, i ) - { - p->pPars->pTimesReq[i] = If_ObjLValue(If_ObjFanin0(pObjLi)); -// printf( "Out %3d : %2d \n", i, (int)p->pPars->pTimesReq[i] ); - } - - // undo previous mapping - If_ManForEachObj( p, pObj, i ) - if ( If_ObjIsAnd(pObj) ) - If_ObjCutBest(pObj)->nLeaves = 0; - - // map again combinationally - p->pPars->fSeqMap = 0; - If_ManPerformMappingComb( p ); - p->pPars->fSeqMap = 1; -} - -/**Function************************************************************* - - Synopsis [Performs sequential mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManPerformMappingSeq( If_Man_t * p ) -{ - int clkTotal = clock(); - int PeriodBest; - - p->SortMode = 0; - - // perform combinational mapping to get the upper bound on the clock period - If_ManPerformMappingRound( p, 1, 0, 0, NULL ); - p->RequiredGlo = If_ManDelayMax( p, 0 ); - p->RequiredGlo2 = p->RequiredGlo; - - // set direct linking of latches with their inputs - If_ManPrepareMappingSeq( p ); - - // collect latches - p->vLatchOrder = If_ManCollectLatches( p ); - - // set parameters - p->nCutsUsed = p->pPars->nCutsMax; - p->nAttempts = 0; - p->nMaxIters = 50; - p->Period = (int)p->RequiredGlo; - - // make sure the clock period works - if ( !If_ManBinarySearchPeriod( p ) ) - { - printf( "If_ManPerformMappingSeq(): The upper bound on the clock period cannot be computed.\n" ); - return 0; - } - - // perform binary search - PeriodBest = If_ManBinarySearch_rec( p, 0, p->Period ); - - // recompute the best l-values - if ( p->Period != PeriodBest ) - { - p->Period = PeriodBest; - if ( !If_ManBinarySearchPeriod( p ) ) - { - printf( "If_ManPerformMappingSeq(): The final clock period cannot be confirmed.\n" ); - return 0; - } - } - if ( p->pPars->fVerbose ) - { -/* - { - FILE * pTable; - pTable = fopen( "iscas/stats_new.txt", "a+" ); -// fprintf( pTable, "%s ", pNtk->pName ); - fprintf( pTable, "%d ", p->Period ); - // fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) ); -// fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) ); -// fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ - printf( "The best clock period is %3d. ", p->Period ); - PRT( "Sequential time", clock() - clkTotal ); - } - p->RequiredGlo = (float)PeriodBest; - - // postprocess it using combinational mapping - If_ManPerformMappingSeqPost( p ); - s_MappingTime = clock() - clkTotal; - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/ifTime.c b/src/map/if/ifTime.c deleted file mode 100644 index 60417c67..00000000 --- a/src/map/if/ifTime.c +++ /dev/null @@ -1,221 +0,0 @@ -/**CFile**************************************************************** - - FileName [ifTime.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapping based on priority cuts.] - - Synopsis [Computation of delay paramters depending on the library.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: ifTime.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "if.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void If_CutSortInputPins( If_Man_t * p, If_Cut_t * pCut, int * pPinPerm, float * pPinDelays ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes delay.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_CutDelay( If_Man_t * p, If_Cut_t * pCut ) -{ - static int pPinPerm[IF_MAX_LUTSIZE]; - static float pPinDelays[IF_MAX_LUTSIZE]; - If_Obj_t * pLeaf; - float Delay, DelayCur; - float * pLutDelays; - int i, Shift; - assert( p->pPars->fSeqMap || pCut->nLeaves > 1 ); - Delay = -IF_FLOAT_LARGE; - if ( p->pPars->pLutLib ) - { - assert( !p->pPars->fLiftLeaves ); - pLutDelays = p->pPars->pLutLib->pLutDelays[pCut->nLeaves]; - if ( p->pPars->pLutLib->fVarPinDelays ) - { - // compute the delay using sorted pins - If_CutSortInputPins( p, pCut, pPinPerm, pPinDelays ); - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - { - DelayCur = pPinDelays[pPinPerm[i]] + pLutDelays[i]; - Delay = IF_MAX( Delay, DelayCur ); - } - } - else - { - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - DelayCur = If_ObjCutBest(pLeaf)->Delay + pLutDelays[0]; - Delay = IF_MAX( Delay, DelayCur ); - } - } - } - else - { - if ( pCut->fUser ) - { - assert( !p->pPars->fLiftLeaves ); - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - DelayCur = If_ObjCutBest(pLeaf)->Delay + (float)pCut->pPerm[i]; - Delay = IF_MAX( Delay, DelayCur ); - } - } - else - { - if ( p->pPars->fLiftLeaves ) - { - If_CutForEachLeafSeq( p, pCut, pLeaf, Shift, i ) - { - DelayCur = If_ObjCutBest(pLeaf)->Delay - Shift * p->Period; - Delay = IF_MAX( Delay, DelayCur ); - } - } - else - { - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - DelayCur = If_ObjCutBest(pLeaf)->Delay; - Delay = IF_MAX( Delay, DelayCur ); - } - } - Delay += 1.0; - } - } - return Delay; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_CutPropagateRequired( If_Man_t * p, If_Cut_t * pCut, float ObjRequired ) -{ - static int pPinPerm[IF_MAX_LUTSIZE]; - static float pPinDelays[IF_MAX_LUTSIZE]; - If_Obj_t * pLeaf; - float * pLutDelays; - float Required; - int i; - assert( !p->pPars->fLiftLeaves ); - // compute the pins - if ( p->pPars->pLutLib ) - { - pLutDelays = p->pPars->pLutLib->pLutDelays[pCut->nLeaves]; - if ( p->pPars->pLutLib->fVarPinDelays ) - { - // compute the delay using sorted pins - If_CutSortInputPins( p, pCut, pPinPerm, pPinDelays ); - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - { - Required = ObjRequired - pLutDelays[i]; - pLeaf = If_ManObj( p, pCut->pLeaves[pPinPerm[i]] ); - pLeaf->Required = IF_MIN( pLeaf->Required, Required ); - } - } - else - { - Required = ObjRequired - pLutDelays[0]; - If_CutForEachLeaf( p, pCut, pLeaf, i ) - pLeaf->Required = IF_MIN( pLeaf->Required, Required ); - } - } - else - { - if ( pCut->fUser ) - { - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - Required = ObjRequired - (float)pCut->pPerm[i]; - pLeaf->Required = IF_MIN( pLeaf->Required, Required ); - } - } - else - { - Required = ObjRequired - (float)1.0; - If_CutForEachLeaf( p, pCut, pLeaf, i ) - pLeaf->Required = IF_MIN( pLeaf->Required, Required ); - } - } -} - -/**Function************************************************************* - - Synopsis [Sorts the pins in the decreasing order of delays.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_CutSortInputPins( If_Man_t * p, If_Cut_t * pCut, int * pPinPerm, float * pPinDelays ) -{ - If_Obj_t * pLeaf; - int i, j, best_i, temp; - // start the trivial permutation and collect pin delays - If_CutForEachLeaf( p, pCut, pLeaf, i ) - { - pPinPerm[i] = i; - pPinDelays[i] = If_ObjCutBest(pLeaf)->Delay; - } - // selection sort the pins in the decreasible order of delays - // this order will match the increasing order of LUT input pins - for ( i = 0; i < (int)pCut->nLeaves-1; i++ ) - { - best_i = i; - for ( j = i+1; j < (int)pCut->nLeaves; j++ ) - if ( pPinDelays[pPinPerm[j]] > pPinDelays[pPinPerm[best_i]] ) - best_i = j; - if ( best_i == i ) - continue; - temp = pPinPerm[i]; - pPinPerm[i] = pPinPerm[best_i]; - pPinPerm[best_i] = temp; - } - // verify - assert( pPinPerm[0] < (int)pCut->nLeaves ); - for ( i = 1; i < (int)pCut->nLeaves; i++ ) - { - assert( pPinPerm[i] < (int)pCut->nLeaves ); - assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/ifTruth.c b/src/map/if/ifTruth.c deleted file mode 100644 index 5587e3ff..00000000 --- a/src/map/if/ifTruth.c +++ /dev/null @@ -1,230 +0,0 @@ -/**CFile**************************************************************** - - FileName [ifTruth.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapping based on priority cuts.] - - Synopsis [Computation of truth tables of the cuts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: ifTruth.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "if.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Several simple procedures working with truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int If_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } -static inline void If_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) -{ - int w; - for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~pIn[w]; -} -static inline void If_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) -{ - int w; - for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn[w]; -} -static inline void If_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~(pIn0[w] & pIn1[w]); -} -static inline void If_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = If_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] & pIn1[w]; -} - -/**Function************************************************************* - - Synopsis [Swaps two adjacent variables in the truth table.] - - Description [Swaps var number Start and var number Start+1 (0-based numbers). - The input truth table is pIn. The output truth table is pOut.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) -{ - static unsigned PMasks[4][3] = { - { 0x99999999, 0x22222222, 0x44444444 }, - { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 }, - { 0xF00FF00F, 0x00F000F0, 0x0F000F00 }, - { 0xFF0000FF, 0x0000FF00, 0x00FF0000 } - }; - int nWords = If_TruthWordNum( nVars ); - int i, k, Step, Shift; - - assert( iVar < nVars - 1 ); - if ( iVar < 4 ) - { - Shift = (1 << iVar); - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift); - } - else if ( iVar > 4 ) - { - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 4*Step ) - { - for ( i = 0; i < Step; i++ ) - pOut[i] = pIn[i]; - for ( i = 0; i < Step; i++ ) - pOut[Step+i] = pIn[2*Step+i]; - for ( i = 0; i < Step; i++ ) - pOut[2*Step+i] = pIn[Step+i]; - for ( i = 0; i < Step; i++ ) - pOut[3*Step+i] = pIn[3*Step+i]; - pIn += 4*Step; - pOut += 4*Step; - } - } - else // if ( iVar == 4 ) - { - for ( i = 0; i < nWords; i += 2 ) - { - pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); - pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); - } - } -} - -/**Function************************************************************* - - Synopsis [Expands the truth table according to the phase.] - - Description [The input and output truth tables are in pIn/pOut. The current number - of variables is nVars. The total number of variables in nVarsAll. The last argument - (Phase) contains shows where the variables should go.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ) -{ - unsigned * pTemp; - int i, k, Var = nVars - 1, Counter = 0; - for ( i = nVarsAll - 1; i >= 0; i-- ) - if ( Phase & (1 << i) ) - { - for ( k = Var; k < i; k++ ) - { - If_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - Counter++; - } - Var--; - } - assert( Var == -1 ); - // swap if it was moved an even number of times - if ( !(Counter & 1) ) - If_TruthCopy( pOut, pIn, nVarsAll ); -} - -/**Function************************************************************* - - Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned If_CutTruthPhase( If_Cut_t * pCut, If_Cut_t * pCut1 ) -{ - unsigned uPhase = 0; - int i, k; - for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) - { - if ( k == (int)pCut1->nLeaves ) - break; - if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) - continue; - assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); - uPhase |= (1 << i); - k++; - } - return uPhase; -} - -/**Function************************************************************* - - Synopsis [Performs truth table computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_CutComputeTruth( If_Man_t * p, If_Cut_t * pCut, If_Cut_t * pCut0, If_Cut_t * pCut1, int fCompl0, int fCompl1 ) -{ - extern void Kit_FactorTest( unsigned * pTruth, int nVars ); - - // permute the first table - if ( fCompl0 ^ pCut0->fCompl ) - If_TruthNot( p->puTemp[0], If_CutTruth(pCut0), pCut->nLimit ); - else - If_TruthCopy( p->puTemp[0], If_CutTruth(pCut0), pCut->nLimit ); - If_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nLimit, If_CutTruthPhase(pCut, pCut0) ); - // permute the second table - if ( fCompl1 ^ pCut1->fCompl ) - If_TruthNot( p->puTemp[1], If_CutTruth(pCut1), pCut->nLimit ); - else - If_TruthCopy( p->puTemp[1], If_CutTruth(pCut1), pCut->nLimit ); - If_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nLimit, If_CutTruthPhase(pCut, pCut1) ); - // produce the resulting table - assert( pCut->fCompl == 0 ); - if ( pCut->fCompl ) - If_TruthNand( If_CutTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nLimit ); - else - If_TruthAnd( If_CutTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nLimit ); - - // perform -// Kit_FactorTest( If_CutTruth(pCut), pCut->nLimit ); -// printf( "%d ", If_CutLeaveNum(pCut) - Kit_TruthSupportSize(If_CutTruth(pCut), If_CutLeaveNum(pCut)) ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/ifUtil.c b/src/map/if/ifUtil.c deleted file mode 100644 index f3fa049e..00000000 --- a/src/map/if/ifUtil.c +++ /dev/null @@ -1,454 +0,0 @@ -/**CFile**************************************************************** - - FileName [ifUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapping based on priority cuts.] - - Synopsis [Various utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: ifUtil.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "if.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Sets all the node copy to NULL.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManCleanNodeCopy( If_Man_t * p ) -{ - If_Obj_t * pObj; - int i; - If_ManForEachObj( p, pObj, i ) - If_ObjSetCopy( pObj, NULL ); -} - -/**Function************************************************************* - - Synopsis [Sets all the cut data to NULL.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManCleanCutData( If_Man_t * p ) -{ - If_Obj_t * pObj; - int i; - If_ManForEachObj( p, pObj, i ) - If_CutSetData( If_ObjCutBest(pObj), NULL ); -} - -/**Function************************************************************* - - Synopsis [Sets all visited marks to 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManCleanMarkV( If_Man_t * p ) -{ - If_Obj_t * pObj; - int i; - If_ManForEachObj( p, pObj, i ) - pObj->fVisit = 0; -} - -/**Function************************************************************* - - Synopsis [Returns the max delay of the POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_ManDelayMax( If_Man_t * p, int fSeq ) -{ - If_Obj_t * pObj; - float DelayBest; - int i; - if ( p->pPars->fLatchPaths && p->pPars->nLatches == 0 ) - { - printf( "Delay optimization of latch path is not performed because there is no latches.\n" ); - p->pPars->fLatchPaths = 0; - } - DelayBest = -IF_FLOAT_LARGE; - if ( fSeq ) - { - assert( p->pPars->nLatches > 0 ); - If_ManForEachPo( p, pObj, i ) - if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) ) - DelayBest = If_ObjArrTime(If_ObjFanin0(pObj)); - } - else if ( p->pPars->fLatchPaths ) - { - If_ManForEachLatchInput( p, pObj, i ) - if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) ) - DelayBest = If_ObjArrTime(If_ObjFanin0(pObj)); - } - else - { - If_ManForEachCo( p, pObj, i ) - if ( DelayBest < If_ObjArrTime(If_ObjFanin0(pObj)) ) - DelayBest = If_ObjArrTime(If_ObjFanin0(pObj)); - } - return DelayBest; -} - -/**Function************************************************************* - - Synopsis [Computes the required times of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManComputeRequired( If_Man_t * p ) -{ - If_Obj_t * pObj; - int i, Counter; - - // compute area, clean required times, collect nodes used in the mapping - p->nNets = 0; - p->AreaGlo = If_ManScanMapping( p ); - - // consider the case when the required times are given - if ( p->pPars->pTimesReq ) - { - assert( !p->pPars->fAreaOnly ); - // make sure that the required time hold - Counter = 0; - If_ManForEachCo( p, pObj, i ) - { - if ( If_ObjArrTime(If_ObjFanin0(pObj)) > p->pPars->pTimesReq[i] + p->fEpsilon ) - { - Counter++; -// printf( "Required times are violated for output %d (arr = %d; req = %d).\n", -// i, (int)If_ObjArrTime(If_ObjFanin0(pObj)), (int)p->pPars->pTimesReq[i] ); - } - If_ObjFanin0(pObj)->Required = p->pPars->pTimesReq[i]; - } - if ( Counter ) - printf( "Required times are violated for %d outputs.\n", Counter ); - } - else - { - // get the global required times - p->RequiredGlo = If_ManDelayMax( p, 0 ); - // update the required times according to the target - if ( p->pPars->DelayTarget != -1 ) - { - if ( p->RequiredGlo > p->pPars->DelayTarget + p->fEpsilon ) - { - if ( p->fNextRound == 0 ) - { - p->fNextRound = 1; - printf( "Cannot meet the target required times (%4.2f). Mapping continues anyway.\n", p->pPars->DelayTarget ); - } - } - else if ( p->RequiredGlo < p->pPars->DelayTarget - p->fEpsilon ) - { - if ( p->fNextRound == 0 ) - { - p->fNextRound = 1; - printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->RequiredGlo, p->pPars->DelayTarget ); - } - p->RequiredGlo = p->pPars->DelayTarget; - } - } - // do not propagate required times if area minimization is requested - if ( p->pPars->fAreaOnly ) - return; - // set the required times for the POs - if ( p->pPars->fLatchPaths ) - { - If_ManForEachLatchInput( p, pObj, i ) - If_ObjFanin0(pObj)->Required = p->RequiredGlo; - } - else - { - If_ManForEachCo( p, pObj, i ) - If_ObjFanin0(pObj)->Required = p->RequiredGlo; - } - } - // go through the nodes in the reverse topological order - Vec_PtrForEachEntry( p->vMapped, pObj, i ) - If_CutPropagateRequired( p, If_ObjCutBest(pObj), pObj->Required ); -} - -/**Function************************************************************* - - Synopsis [Computes area, references, and nodes used in the mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_ManScanMapping_rec( If_Man_t * p, If_Obj_t * pObj, If_Obj_t ** ppStore ) -{ - If_Obj_t * pLeaf; - If_Cut_t * pCutBest; - float aArea; - int i; - if ( pObj->nRefs++ || If_ObjIsCi(pObj) || If_ObjIsConst1(pObj) ) - return 0.0; - // store the node in the structure by level - assert( If_ObjIsAnd(pObj) ); - pObj->pCopy = (char *)ppStore[pObj->Level]; - ppStore[pObj->Level] = pObj; - // visit the transitive fanin of the selected cut - pCutBest = If_ObjCutBest(pObj); - p->nNets += pCutBest->nLeaves; - aArea = If_CutLutArea( p, pCutBest ); - If_CutForEachLeaf( p, pCutBest, pLeaf, i ) - aArea += If_ManScanMapping_rec( p, pLeaf, ppStore ); - return aArea; -} - -/**Function************************************************************* - - Synopsis [Computes area, references, and nodes used in the mapping.] - - Description [Collects the nodes in reverse topological order in array - p->vMapping.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_ManScanMapping( If_Man_t * p ) -{ - If_Obj_t * pObj, ** ppStore; - float aArea; - int i; - assert( !p->pPars->fLiftLeaves ); - // clean all references - If_ManForEachObj( p, pObj, i ) - { - pObj->Required = IF_FLOAT_LARGE; - pObj->nVisits = pObj->nVisitsCopy; - pObj->nRefs = 0; - } - // allocate place to store the nodes - ppStore = ALLOC( If_Obj_t *, p->nLevelMax + 1 ); - memset( ppStore, 0, sizeof(If_Obj_t *) * (p->nLevelMax + 1) ); - // collect nodes reachable from POs in the DFS order through the best cuts - aArea = 0; - If_ManForEachCo( p, pObj, i ) - aArea += If_ManScanMapping_rec( p, If_ObjFanin0(pObj), ppStore ); - // reconnect the nodes in reverse topological order - Vec_PtrClear( p->vMapped ); - for ( i = p->nLevelMax; i >= 0; i-- ) - for ( pObj = ppStore[i]; pObj; pObj = pObj->pCopy ) - Vec_PtrPush( p->vMapped, pObj ); - free( ppStore ); - return aArea; -} - -/**Function************************************************************* - - Synopsis [Computes area, references, and nodes used in the mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_ManScanMappingSeq_rec( If_Man_t * p, If_Obj_t * pObj, Vec_Ptr_t * vMapped ) -{ - If_Obj_t * pLeaf; - If_Cut_t * pCutBest; - float aArea; - int i, Shift; - // treat latches transparently - if ( If_ObjIsLatch(pObj) ) - return If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), vMapped ); - // consider trivial cases - if ( pObj->nRefs++ || If_ObjIsPi(pObj) || If_ObjIsConst1(pObj) ) - return 0.0; - // store the node in the structure by level - assert( If_ObjIsAnd(pObj) ); - // visit the transitive fanin of the selected cut - pCutBest = If_ObjCutBest(pObj); - aArea = If_ObjIsAnd(pObj)? If_CutLutArea(p, pCutBest) : (float)0.0; - If_CutForEachLeafSeq( p, pCutBest, pLeaf, Shift, i ) - aArea += If_ManScanMappingSeq_rec( p, pLeaf, vMapped ); - // add the node - Vec_PtrPush( vMapped, pObj ); - return aArea; -} - -/**Function************************************************************* - - Synopsis [Computes area, references, and nodes used in the mapping.] - - Description [Collects the nodes in reverse topological order in array - p->vMapping.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float If_ManScanMappingSeq( If_Man_t * p ) -{ - If_Obj_t * pObj; - float aArea; - int i; - assert( p->pPars->fLiftLeaves ); - // clean all references - If_ManForEachObj( p, pObj, i ) - pObj->nRefs = 0; - // collect nodes reachable from POs in the DFS order through the best cuts - aArea = 0; - Vec_PtrClear( p->vMapped ); - If_ManForEachPo( p, pObj, i ) - aArea += If_ManScanMappingSeq_rec( p, If_ObjFanin0(pObj), p->vMapped ); - return aArea; -} - -/**Function************************************************************* - - Synopsis [Computes area, references, and nodes used in the mapping.] - - Description [Collects the nodes in reverse topological order in array - p->vMapping.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void If_ManResetOriginalRefs( If_Man_t * p ) -{ - If_Obj_t * pObj; - int i; - If_ManForEachObj( p, pObj, i ) - pObj->nRefs = 0; - If_ManForEachObj( p, pObj, i ) - { - if ( If_ObjIsAnd(pObj) ) - { - pObj->pFanin0->nRefs++; - pObj->pFanin1->nRefs++; - } - else if ( If_ObjIsCo(pObj) ) - pObj->pFanin0->nRefs++; - } -} - -/**Function************************************************************* - - Synopsis [Computes cross-cut of the circuit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManCrossCut( If_Man_t * p ) -{ - If_Obj_t * pObj, * pFanin; - int i, nCutSize = 0, nCutSizeMax = 0; - If_ManForEachObj( p, pObj, i ) - { - if ( !If_ObjIsAnd(pObj) ) - continue; - // consider the node - if ( nCutSizeMax < ++nCutSize ) - nCutSizeMax = nCutSize; - if ( pObj->nVisits == 0 ) - nCutSize--; - // consider the fanins - pFanin = If_ObjFanin0(pObj); - if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) - nCutSize--; - pFanin = If_ObjFanin1(pObj); - if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) - nCutSize--; - // consider the choice class - if ( pObj->fRepr ) - for ( pFanin = pObj; pFanin; pFanin = pFanin->pEquiv ) - if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) - nCutSize--; - } - If_ManForEachObj( p, pObj, i ) - { - assert( If_ObjIsCi(pObj) || pObj->fVisit == 0 ); - pObj->nVisits = pObj->nVisitsCopy; - } - assert( nCutSize == 0 ); -// printf( "Max cross cut size = %6d.\n", nCutSizeMax ); - return nCutSizeMax; -} - -/**Function************************************************************* - - Synopsis [Computes cross-cut of the circuit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int If_ManCountTrueArea( If_Man_t * p ) -{ - If_Obj_t * pObj; - int i, Area = 0; - Vec_PtrForEachEntry( p->vMapped, pObj, i ) - Area += 1 + (If_ObjCutBest(pObj)->nLeaves > (unsigned)p->pPars->nLutSize / 2); - return Area; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/if_.c b/src/map/if/if_.c deleted file mode 100644 index d2960077..00000000 --- a/src/map/if/if_.c +++ /dev/null @@ -1,47 +0,0 @@ -/**CFile**************************************************************** - - FileName [if_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [FPGA mapping based on priority cuts.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - November 21, 2006.] - - Revision [$Id: if_.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "if.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/if/module.make b/src/map/if/module.make deleted file mode 100644 index f3d189be..00000000 --- a/src/map/if/module.make +++ /dev/null @@ -1,9 +0,0 @@ -SRC += src/map/if/ifCore.c \ - src/map/if/ifCut.c \ - src/map/if/ifMan.c \ - src/map/if/ifMap.c \ - src/map/if/ifReduce.c \ - src/map/if/ifSeq.c \ - src/map/if/ifTime.c \ - src/map/if/ifTruth.c \ - src/map/if/ifUtil.c diff --git a/src/map/mapper/mapper.c b/src/map/mapper/mapper.c deleted file mode 100644 index b18b68c0..00000000 --- a/src/map/mapper/mapper.c +++ /dev/null @@ -1,176 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapper.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Command file for the mapper package.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapper.c,v 1.7 2005/01/23 06:59:42 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "mainInt.h" -#include "mio.h" -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Map_CommandReadLibrary ( Abc_Frame_t * pAbc, int argc, char **argv ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_Init( Abc_Frame_t * pAbc ) -{ - Cmd_CommandAdd( pAbc, "SC mapping", "read_super", Map_CommandReadLibrary, 0 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_End() -{ -// Map_SuperLibFree( s_pSuperLib ); - Map_SuperLibFree( Abc_FrameReadLibSuper() ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - FILE * pFile; - FILE * pOut, * pErr; - Map_SuperLib_t * pLib; - Abc_Ntk_t * pNet; - char * FileName, * ExcludeFile; - int fVerbose; - int fAlgorithm; - int c; - - pNet = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set the defaults - fVerbose = 1; - fAlgorithm = 1; - ExcludeFile = 0; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "eovh")) != EOF ) - { - switch (c) - { - case 'e': - ExcludeFile = argv[globalUtilOptind]; - if ( ExcludeFile == 0 ) - goto usage; - globalUtilOptind++; - break; - case 'o': - fAlgorithm ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - - if ( argc != globalUtilOptind + 1 ) - { - goto usage; - } - - // get the input file name - FileName = argv[globalUtilOptind]; - if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) -// if ( (pFile = fopen( FileName, "r" )) == NULL ) - { - fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); - if ( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) ) - fprintf( pErr, "Did you mean \"%s\"?", FileName ); - fprintf( pErr, "\n" ); - return 1; - } - fclose( pFile ); - - // set the new network - pLib = Map_SuperLibCreate( FileName, ExcludeFile, fAlgorithm, fVerbose ); - if ( pLib == NULL ) - { - fprintf( pErr, "Reading supergate library has failed.\n" ); - goto usage; - } - // replace the current library -// Map_SuperLibFree( s_pSuperLib ); -// s_pSuperLib = pLib; - Map_SuperLibFree( Abc_FrameReadLibSuper() ); - Abc_FrameSetLibSuper( pLib ); - // replace the current genlib library -// if ( s_pLib ) Mio_LibraryDelete( s_pLib ); -// s_pLib = s_pSuperLib->pGenlib; - Mio_LibraryDelete( Abc_FrameReadLibGen() ); - Abc_FrameSetLibGen( pLib->pGenlib ); - return 0; - -usage: - fprintf( pErr, "\nusage: read_super [-ovh]\n"); - fprintf( pErr, "\t read the supergate library from the file\n" ); - fprintf( pErr, "\t-e file : file contains list of genlib gates to exclude\n" ); - fprintf( pErr, "\t-o : toggles the use of old file format [default = %s]\n", (fAlgorithm? "new" : "old") ); - fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; /* error exit */ -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapper.h b/src/map/mapper/mapper.h deleted file mode 100644 index 8eade761..00000000 --- a/src/map/mapper/mapper.h +++ /dev/null @@ -1,195 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapper.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapper.h,v 1.11 2005/02/28 05:34:26 alanmi Exp $] - -***********************************************************************/ - -#ifndef __MAPPER_H__ -#define __MAPPER_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Map_ManStruct_t_ Map_Man_t; -typedef struct Map_NodeStruct_t_ Map_Node_t; -typedef struct Map_NodeVecStruct_t_ Map_NodeVec_t; -typedef struct Map_CutStruct_t_ Map_Cut_t; -typedef struct Map_MatchStruct_t_ Map_Match_t; -typedef struct Map_SuperStruct_t_ Map_Super_t; -typedef struct Map_SuperLibStruct_t_ Map_SuperLib_t; -typedef struct Map_HashTableStruct_t_ Map_HashTable_t; -typedef struct Map_HashEntryStruct_t_ Map_HashEntry_t; -typedef struct Map_TimeStruct_t_ Map_Time_t; - -// the pair of rise/fall time parameters -struct Map_TimeStruct_t_ -{ - float Rise; - float Fall; - float Worst; -}; - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Map_IsComplement(p) (((int)((unsigned long) (p) & 01))) -#define Map_Regular(p) ((Map_Node_t *)((unsigned long)(p) & ~01)) -#define Map_Not(p) ((Map_Node_t *)((unsigned long)(p) ^ 01)) -#define Map_NotCond(p,c) ((Map_Node_t *)((unsigned long)(p) ^ (c))) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== mapperCreate.c =============================================================*/ -extern Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose ); -extern Map_Node_t * Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); -extern void Map_ManFree( Map_Man_t * pMan ); -extern void Map_ManPrintTimeStats( Map_Man_t * p ); -extern void Map_ManPrintStatsToFile( char * pName, float Area, float Delay, int Time ); -extern int Map_ManReadInputNum( Map_Man_t * p ); -extern int Map_ManReadOutputNum( Map_Man_t * p ); -extern Map_Node_t ** Map_ManReadInputs ( Map_Man_t * p ); -extern Map_Node_t ** Map_ManReadOutputs( Map_Man_t * p ); -extern Map_Node_t * Map_ManReadConst1 ( Map_Man_t * p ); -extern Map_Time_t * Map_ManReadInputArrivals( Map_Man_t * p ); -extern Mio_Library_t * Map_ManReadGenLib ( Map_Man_t * p ); -extern bool Map_ManReadVerbose( Map_Man_t * p ); -extern float Map_ManReadAreaFinal( Map_Man_t * p ); -extern float Map_ManReadRequiredGlo( Map_Man_t * p ); -extern void Map_ManSetTimeToMap( Map_Man_t * p, int Time ); -extern void Map_ManSetTimeToNet( Map_Man_t * p, int Time ); -extern void Map_ManSetTimeSweep( Map_Man_t * p, int Time ); -extern void Map_ManSetTimeTotal( Map_Man_t * p, int Time ); -extern void Map_ManSetOutputNames( Map_Man_t * p, char ** ppNames ); -extern void Map_ManSetAreaRecovery( Map_Man_t * p, int fAreaRecovery ); -extern void Map_ManSetDelayTarget( Map_Man_t * p, float DelayTarget ); -extern void Map_ManSetInputArrivals( Map_Man_t * p, Map_Time_t * pArrivals ); -extern void Map_ManSetObeyFanoutLimits( Map_Man_t * p, bool fObeyFanoutLimits ); -extern void Map_ManSetNumIterations( Map_Man_t * p, int nNumIterations ); -extern int Map_ManReadPass( Map_Man_t * p ); -extern void Map_ManSetPass( Map_Man_t * p, int nPass ); -extern int Map_ManReadFanoutViolations( Map_Man_t * p ); -extern void Map_ManSetFanoutViolations( Map_Man_t * p, int nVio ); -extern void Map_ManSetChoiceNodeNum( Map_Man_t * p, int nChoiceNodes ); -extern void Map_ManSetChoiceNum( Map_Man_t * p, int nChoices ); -extern void Map_ManSetVerbose( Map_Man_t * p, int fVerbose ); -extern void Map_ManSetSwitching( Map_Man_t * p, int fSwitching ); - -extern Map_Man_t * Map_NodeReadMan( Map_Node_t * p ); -extern char * Map_NodeReadData( Map_Node_t * p, int fPhase ); -extern int Map_NodeReadNum( Map_Node_t * p ); -extern int Map_NodeReadLevel( Map_Node_t * p ); -extern Map_Cut_t * Map_NodeReadCuts( Map_Node_t * p ); -extern Map_Cut_t * Map_NodeReadCutBest( Map_Node_t * p, int fPhase ); -extern Map_Node_t * Map_NodeReadOne( Map_Node_t * p ); -extern Map_Node_t * Map_NodeReadTwo( Map_Node_t * p ); -extern void Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData ); -extern void Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE ); -extern void Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr ); -extern void Map_NodeSetSwitching( Map_Node_t * p, float Switching ); - -extern int Map_NodeIsConst( Map_Node_t * p ); -extern int Map_NodeIsVar( Map_Node_t * p ); -extern int Map_NodeIsAnd( Map_Node_t * p ); -extern int Map_NodeComparePhase( Map_Node_t * p1, Map_Node_t * p2 ); - -extern Map_Super_t * Map_CutReadSuperBest( Map_Cut_t * p, int fPhase ); -extern Map_Super_t * Map_CutReadSuper0( Map_Cut_t * p ); -extern Map_Super_t * Map_CutReadSuper1( Map_Cut_t * p ); -extern int Map_CutReadLeavesNum( Map_Cut_t * p ); -extern Map_Node_t ** Map_CutReadLeaves( Map_Cut_t * p ); -extern unsigned Map_CutReadPhaseBest( Map_Cut_t * p, int fPhase ); -extern unsigned Map_CutReadPhase0( Map_Cut_t * p ); -extern unsigned Map_CutReadPhase1( Map_Cut_t * p ); -extern Map_Cut_t * Map_CutReadNext( Map_Cut_t * p ); - -extern char * Map_SuperReadFormula( Map_Super_t * p ); -extern Mio_Gate_t * Map_SuperReadRoot( Map_Super_t * p ); -extern int Map_SuperReadNum( Map_Super_t * p ); -extern Map_Super_t ** Map_SuperReadFanins( Map_Super_t * p ); -extern int Map_SuperReadFaninNum( Map_Super_t * p ); -extern Map_Super_t * Map_SuperReadNext( Map_Super_t * p ); -extern int Map_SuperReadNumPhases( Map_Super_t * p ); -extern unsigned char * Map_SuperReadPhases( Map_Super_t * p ); -extern int Map_SuperReadFanoutLimit( Map_Super_t * p ); - -extern Mio_Library_t * Map_SuperLibReadGenLib( Map_SuperLib_t * p ); -extern float Map_SuperLibReadAreaInv( Map_SuperLib_t * p ); -extern Map_Time_t Map_SuperLibReadDelayInv( Map_SuperLib_t * p ); -extern int Map_SuperLibReadVarsMax( Map_SuperLib_t * p ); - -extern Map_Node_t * Map_NodeAnd( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); -extern Map_Node_t * Map_NodeOr( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); -extern Map_Node_t * Map_NodeExor( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); -extern Map_Node_t * Map_NodeMux( Map_Man_t * p, Map_Node_t * pNode, Map_Node_t * pNodeT, Map_Node_t * pNodeE ); -extern void Map_NodeSetChoice( Map_Man_t * pMan, Map_Node_t * pNodeOld, Map_Node_t * pNodeNew ); - -/*=== resmCanon.c =============================================================*/ -extern int Map_CanonComputeSlow( unsigned uTruths[][2], int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ); -extern int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ); -/*=== mapperCut.c =============================================================*/ -extern Map_Cut_t * Map_CutAlloc( Map_Man_t * p ); -/*=== mapperCutUtils.c =============================================================*/ -extern void Map_CutCreateFromNode( Map_Man_t * p, Map_Super_t * pSuper, int iRoot, unsigned uPhaseRoot, - int * pLeaves, int nLeaves, unsigned uPhaseLeaves ); -/*=== mapperCore.c =============================================================*/ -extern int Map_Mapping( Map_Man_t * p ); -/*=== mapperLib.c =============================================================*/ -extern int Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib ); -/*=== mapperMntk.c =============================================================*/ -//extern Mntk_Man_t * Map_ConvertMappingToMntk( Map_Man_t * pMan ); -/*=== mapperSuper.c =============================================================*/ -extern char * Map_LibraryReadFormulaStep( char * pFormula, char * pStrings[], int * pnStrings ); -/*=== mapperSweep.c =============================================================*/ -extern void Map_NetworkSweep( Abc_Ntk_t * pNet ); -/*=== mapperTable.c =============================================================*/ -extern Map_Super_t * Map_SuperTableLookupC( Map_SuperLib_t * pLib, unsigned uTruth[] ); -/*=== mapperTime.c =============================================================*/ -/*=== mapperUtil.c =============================================================*/ -extern int Map_ManCheckConsistency( Map_Man_t * p ); -extern st_table * Map_CreateTableGate2Super( Map_Man_t * p ); -extern void Map_ManCleanData( Map_Man_t * p ); -extern void Map_MappingSetupTruthTables( unsigned uTruths[][2] ); -extern void Map_MappingSetupTruthTablesLarge( unsigned uTruths[][32] ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/map/mapper/mapperCanon.c b/src/map/mapper/mapperCanon.c deleted file mode 100644 index 203c9142..00000000 --- a/src/map/mapper/mapperCanon.c +++ /dev/null @@ -1,271 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperCanon.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperCanon.c,v 1.2 2005/01/23 06:59:42 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase ); -static void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the N-canonical form of the Boolean function.] - - Description [The N-canonical form is defined as the truth table with - the minimum integer value. This function exhaustively enumerates - through the complete set of 2^N phase assignments.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_CanonComputeSlow( unsigned uTruths[][2], int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ) -{ - unsigned uTruthPerm[2]; - int nMints, nPhases, m; - - nPhases = 0; - nMints = (1 << nVarsReal); - if ( nVarsMax < 6 ) - { - uTruthRes[0] = MAP_MASK(32); - for ( m = 0; m < nMints; m++ ) - { - uTruthPerm[0] = Map_CanonComputePhase( uTruths, nVarsMax, uTruth[0], m ); - if ( uTruthRes[0] > uTruthPerm[0] ) - { - uTruthRes[0] = uTruthPerm[0]; - nPhases = 0; - puPhases[nPhases++] = (unsigned char)m; - } - else if ( uTruthRes[0] == uTruthPerm[0] ) - { - if ( nPhases < 4 ) // the max number of phases in Map_Super_t - puPhases[nPhases++] = (unsigned char)m; - } - } - uTruthRes[1] = uTruthRes[0]; - } - else - { - uTruthRes[0] = MAP_MASK(32); - uTruthRes[1] = MAP_MASK(32); - for ( m = 0; m < nMints; m++ ) - { - Map_CanonComputePhase6( uTruths, nVarsMax, uTruth, m, uTruthPerm ); - if ( uTruthRes[1] > uTruthPerm[1] || uTruthRes[1] == uTruthPerm[1] && uTruthRes[0] > uTruthPerm[0] ) - { - uTruthRes[0] = uTruthPerm[0]; - uTruthRes[1] = uTruthPerm[1]; - nPhases = 0; - puPhases[nPhases++] = (unsigned char)m; - } - else if ( uTruthRes[1] == uTruthPerm[1] && uTruthRes[0] == uTruthPerm[0] ) - { - if ( nPhases < 4 ) // the max number of phases in Map_Super_t - puPhases[nPhases++] = (unsigned char)m; - } - } - } - assert( nPhases > 0 ); -// printf( "%d ", nPhases ); - return nPhases; -} - -/**Function************************************************************* - - Synopsis [Performs phase transformation for one function of less than 6 variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Map_CanonComputePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase ) -{ - int v, Shift; - for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) - if ( uPhase & Shift ) - uTruth = (((uTruth & ~uTruths[v][0]) << Shift) | ((uTruth & uTruths[v][0]) >> Shift)); - return uTruth; -} - -/**Function************************************************************* - - Synopsis [Performs phase transformation for one function of 6 variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CanonComputePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] ) -{ - unsigned uTemp; - int v, Shift; - - // initialize the result - uTruthRes[0] = uTruth[0]; - uTruthRes[1] = uTruth[1]; - if ( uPhase == 0 ) - return; - // compute the phase - for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) - if ( uPhase & Shift ) - { - if ( Shift < 32 ) - { - uTruthRes[0] = (((uTruthRes[0] & ~uTruths[v][0]) << Shift) | ((uTruthRes[0] & uTruths[v][0]) >> Shift)); - uTruthRes[1] = (((uTruthRes[1] & ~uTruths[v][1]) << Shift) | ((uTruthRes[1] & uTruths[v][1]) >> Shift)); - } - else - { - uTemp = uTruthRes[0]; - uTruthRes[0] = uTruthRes[1]; - uTruthRes[1] = uTemp; - } - } -} - -/**Function************************************************************* - - Synopsis [Computes the N-canonical form of the Boolean function.] - - Description [The N-canonical form is defined as the truth table with - the minimum integer value. This function exhaustively enumerates - through the complete set of 2^N phase assignments.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_CanonComputeFast( Map_Man_t * p, int nVarsMax, int nVarsReal, unsigned uTruth[], unsigned char * puPhases, unsigned uTruthRes[] ) -{ - unsigned uTruth0, uTruth1; - unsigned uCanon0, uCanon1, uCanonBest, uPhaseBest; - int i, Limit; - - if ( nVarsMax == 6 ) - return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes ); - - if ( nVarsReal < 5 ) - { -// return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes ); - - uTruth0 = uTruth[0] & 0xFFFF; - assert( p->pCounters[uTruth0] > 0 ); - uTruthRes[0] = (p->uCanons[uTruth0] << 16) | p->uCanons[uTruth0]; - uTruthRes[1] = uTruthRes[0]; - puPhases[0] = p->uPhases[uTruth0][0]; - return 1; - } - - assert( nVarsMax == 5 ); - assert( nVarsReal == 5 ); - uTruth0 = uTruth[0] & 0xFFFF; - uTruth1 = (uTruth[0] >> 16); - if ( uTruth1 == 0 ) - { - uTruthRes[0] = p->uCanons[uTruth0]; - uTruthRes[1] = uTruthRes[0]; - Limit = (p->pCounters[uTruth0] > 4)? 4 : p->pCounters[uTruth0]; - for ( i = 0; i < Limit; i++ ) - puPhases[i] = p->uPhases[uTruth0][i]; - return Limit; - } - else if ( uTruth0 == 0 ) - { - uTruthRes[0] = p->uCanons[uTruth1]; - uTruthRes[1] = uTruthRes[0]; - Limit = (p->pCounters[uTruth1] > 4)? 4 : p->pCounters[uTruth1]; - for ( i = 0; i < Limit; i++ ) - { - puPhases[i] = p->uPhases[uTruth1][i]; - puPhases[i] |= (1 << 4); - } - return Limit; - } - uCanon0 = p->uCanons[uTruth0]; - uCanon1 = p->uCanons[uTruth1]; - if ( uCanon0 >= uCanon1 ) // using nCanon1 as the main one - { - assert( p->pCounters[uTruth1] > 0 ); - uCanonBest = 0xFFFFFFFF; - for ( i = 0; i < p->pCounters[uTruth1]; i++ ) - { - uCanon0 = Extra_TruthPolarize( uTruth0, p->uPhases[uTruth1][i], 4 ); - if ( uCanonBest > uCanon0 ) - { - uCanonBest = uCanon0; - uPhaseBest = p->uPhases[uTruth1][i]; - assert( uPhaseBest < 16 ); - } - } - uTruthRes[0] = (uCanon1 << 16) | uCanonBest; - uTruthRes[1] = uTruthRes[0]; - puPhases[0] = uPhaseBest; - return 1; - } - else if ( uCanon0 < uCanon1 ) - { - assert( p->pCounters[uTruth0] > 0 ); - uCanonBest = 0xFFFFFFFF; - for ( i = 0; i < p->pCounters[uTruth0]; i++ ) - { - uCanon1 = Extra_TruthPolarize( uTruth1, p->uPhases[uTruth0][i], 4 ); - if ( uCanonBest > uCanon1 ) - { - uCanonBest = uCanon1; - uPhaseBest = p->uPhases[uTruth0][i]; - assert( uPhaseBest < 16 ); - } - } - uTruthRes[0] = (uCanon0 << 16) | uCanonBest; - uTruthRes[1] = uTruthRes[0]; - puPhases[0] = uPhaseBest | (1 << 4); - return 1; - } - else - { - assert( 0 ); - return Map_CanonComputeSlow( p->uTruths, nVarsMax, nVarsReal, uTruth, puPhases, uTruthRes ); - } -} - - - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperCore.c b/src/map/mapper/mapperCore.c deleted file mode 100644 index 5d4854e6..00000000 --- a/src/map/mapper/mapperCore.c +++ /dev/null @@ -1,228 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperCore.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperCore.c,v 1.7 2004/10/01 23:41:04 satrajit Exp $] - -***********************************************************************/ - -#include "mapperInt.h" -//#include "resm.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs technology mapping for the given object graph.] - - Description [The object graph is stored in the mapping manager. - First, the AND nodes that fanout into POs are collected in the DFS order. - Two preprocessing steps are performed: the k-feasible cuts are computed - for each node and the truth tables are computed for each cut. Next, the - delay-optimal matches are assigned for each node, followed by several - iterations of area recoveryd: using area flow (global optimization) - and using exact area at a node (local optimization).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_Mapping( Map_Man_t * p ) -{ - int fShowSwitching = 1; - int fUseAreaFlow = 1; - int fUseExactArea = !p->fSwitching; - int fUseExactAreaWithPhase = !p->fSwitching; - int clk; - - ////////////////////////////////////////////////////////////////////// - // perform pre-mapping computations - // collect the nodes reachable from POs in the DFS order (including the choices) - p->vAnds = Map_MappingDfs( p, 1 ); - if ( p->fVerbose ) - Map_MappingReportChoices( p ); - Map_MappingSetChoiceLevels( p ); // should always be called before mapping! -// return 1; - - // compute the cuts of nodes in the DFS order - clk = clock(); - Map_MappingCuts( p ); - p->timeCuts = clock() - clk; - // derive the truth tables - clk = clock(); - Map_MappingTruths( p ); - p->timeTruth = clock() - clk; - ////////////////////////////////////////////////////////////////////// -//PRT( "Truths", clock() - clk ); - - ////////////////////////////////////////////////////////////////////// - // compute the minimum-delay mapping - clk = clock(); - p->fMappingMode = 0; - if ( !Map_MappingMatches( p ) ) - return 0; - p->timeMatch = clock() - clk; - // compute the references and collect the nodes used in the mapping - Map_MappingSetRefs( p ); - p->AreaBase = Map_MappingGetArea( p, p->vMapping ); -if ( p->fVerbose ) -{ -printf( "Delay : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", - fShowSwitching? "Switch" : "Delay", - fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, - Map_MappingGetAreaFlow(p), p->AreaBase, 0.0 ); -PRT( "Time", p->timeMatch ); -} - ////////////////////////////////////////////////////////////////////// - - if ( !p->fAreaRecovery ) - { - if ( p->fVerbose ) - Map_MappingPrintOutputArrivals( p ); - return 1; - } - - ////////////////////////////////////////////////////////////////////// - // perform area recovery using area flow - clk = clock(); - if ( fUseAreaFlow ) - { - // compute the required times - Map_TimeComputeRequiredGlobal( p ); - // recover area flow - p->fMappingMode = 1; - Map_MappingMatches( p ); - // compute the references and collect the nodes used in the mapping - Map_MappingSetRefs( p ); - p->AreaFinal = Map_MappingGetArea( p, p->vMapping ); -if ( p->fVerbose ) -{ -printf( "AreaFlow : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", - fShowSwitching? "Switch" : "Delay", - fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, - Map_MappingGetAreaFlow(p), p->AreaFinal, - 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); -PRT( "Time", clock() - clk ); -} - } - p->timeArea += clock() - clk; - ////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////// - // perform area recovery using exact area - clk = clock(); - if ( fUseExactArea ) - { - // compute the required times - Map_TimeComputeRequiredGlobal( p ); - // recover area - p->fMappingMode = 2; - Map_MappingMatches( p ); - // compute the references and collect the nodes used in the mapping - Map_MappingSetRefs( p ); - p->AreaFinal = Map_MappingGetArea( p, p->vMapping ); -if ( p->fVerbose ) -{ -printf( "Area : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", - fShowSwitching? "Switch" : "Delay", - fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, - 0.0, p->AreaFinal, - 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); -PRT( "Time", clock() - clk ); -} - } - p->timeArea += clock() - clk; - ////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////// - // perform area recovery using exact area - clk = clock(); - if ( fUseExactAreaWithPhase ) - { - // compute the required times - Map_TimeComputeRequiredGlobal( p ); - // recover area - p->fMappingMode = 3; - Map_MappingMatches( p ); - // compute the references and collect the nodes used in the mapping - Map_MappingSetRefs( p ); - p->AreaFinal = Map_MappingGetArea( p, p->vMapping ); -if ( p->fVerbose ) -{ -printf( "Area : %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", - fShowSwitching? "Switch" : "Delay", - fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, - 0.0, p->AreaFinal, - 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); -PRT( "Time", clock() - clk ); -} - } - p->timeArea += clock() - clk; - ////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////// - // perform area recovery using exact area - clk = clock(); - if ( p->fSwitching ) - { - // compute the required times - Map_TimeComputeRequiredGlobal( p ); - // recover switching activity - p->fMappingMode = 4; - Map_MappingMatches( p ); - // compute the references and collect the nodes used in the mapping - Map_MappingSetRefs( p ); - p->AreaFinal = Map_MappingGetArea( p, p->vMapping ); -if ( p->fVerbose ) -{ -printf( "Switching: %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", - fShowSwitching? "Switch" : "Delay", - fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, - 0.0, p->AreaFinal, - 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); -PRT( "Time", clock() - clk ); -} - - // compute the required times - Map_TimeComputeRequiredGlobal( p ); - // recover switching activity - p->fMappingMode = 4; - Map_MappingMatches( p ); - // compute the references and collect the nodes used in the mapping - Map_MappingSetRefs( p ); - p->AreaFinal = Map_MappingGetArea( p, p->vMapping ); -if ( p->fVerbose ) -{ -printf( "Switching: %s = %8.2f Flow = %11.1f Area = %11.1f %4.1f %% ", - fShowSwitching? "Switch" : "Delay", - fShowSwitching? Map_MappingGetSwitching(p,p->vMapping) : p->fRequiredGlo, - 0.0, p->AreaFinal, - 100.0*(p->AreaBase-p->AreaFinal)/p->AreaBase ); -PRT( "Time", clock() - clk ); -} - } - p->timeArea += clock() - clk; - ////////////////////////////////////////////////////////////////////// - - // print the arrival times of the latest outputs - if ( p->fVerbose ) - Map_MappingPrintOutputArrivals( p ); - return 1; -} diff --git a/src/map/mapper/mapperCreate.c b/src/map/mapper/mapperCreate.c deleted file mode 100644 index 157d467b..00000000 --- a/src/map/mapper/mapperCreate.c +++ /dev/null @@ -1,600 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperCreate.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperCreate.c,v 1.15 2005/02/28 05:34:26 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Map_TableCreate( Map_Man_t * p ); -static void Map_TableResize( Map_Man_t * p ); -static Map_Node_t * Map_TableLookup( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ); - -// hash key for the structural hash table -static inline unsigned Map_HashKey2( Map_Node_t * p0, Map_Node_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads parameters from the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_ManReadInputNum( Map_Man_t * p ) { return p->nInputs; } -int Map_ManReadOutputNum( Map_Man_t * p ) { return p->nOutputs; } -Map_Node_t ** Map_ManReadInputs ( Map_Man_t * p ) { return p->pInputs; } -Map_Node_t ** Map_ManReadOutputs( Map_Man_t * p ) { return p->pOutputs; } -Map_Node_t * Map_ManReadConst1 ( Map_Man_t * p ) { return p->pConst1; } -Map_Time_t * Map_ManReadInputArrivals( Map_Man_t * p ) { return p->pInputArrivals;} -Mio_Library_t * Map_ManReadGenLib ( Map_Man_t * p ) { return p->pSuperLib->pGenlib; } -bool Map_ManReadVerbose( Map_Man_t * p ) { return p->fVerbose; } -float Map_ManReadAreaFinal( Map_Man_t * p ) { return p->AreaFinal; } -float Map_ManReadRequiredGlo( Map_Man_t * p ) { return p->fRequiredGlo; } -void Map_ManSetTimeToMap( Map_Man_t * p, int Time ) { p->timeToMap = Time; } -void Map_ManSetTimeToNet( Map_Man_t * p, int Time ) { p->timeToNet = Time; } -void Map_ManSetTimeSweep( Map_Man_t * p, int Time ) { p->timeSweep = Time; } -void Map_ManSetTimeTotal( Map_Man_t * p, int Time ) { p->timeTotal = Time; } -void Map_ManSetOutputNames( Map_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; } -void Map_ManSetAreaRecovery( Map_Man_t * p, int fAreaRecovery ) { p->fAreaRecovery = fAreaRecovery;} -void Map_ManSetDelayTarget( Map_Man_t * p, float DelayTarget ) { p->DelayTarget = DelayTarget;} -void Map_ManSetInputArrivals( Map_Man_t * p, Map_Time_t * pArrivals ) { p->pInputArrivals = pArrivals;} -void Map_ManSetObeyFanoutLimits( Map_Man_t * p, bool fObeyFanoutLimits ) { p->fObeyFanoutLimits = fObeyFanoutLimits; } -void Map_ManSetNumIterations( Map_Man_t * p, int nIterations ) { p->nIterations = nIterations; } -int Map_ManReadFanoutViolations( Map_Man_t * p ) { return p->nFanoutViolations; } -void Map_ManSetFanoutViolations( Map_Man_t * p, int nVio ) { p->nFanoutViolations = nVio; } -void Map_ManSetChoiceNodeNum( Map_Man_t * p, int nChoiceNodes ) { p->nChoiceNodes = nChoiceNodes; } -void Map_ManSetChoiceNum( Map_Man_t * p, int nChoices ) { p->nChoices = nChoices; } -void Map_ManSetVerbose( Map_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; } -void Map_ManSetSwitching( Map_Man_t * p, int fSwitching ) { p->fSwitching = fSwitching; } - -/**Function************************************************************* - - Synopsis [Reads parameters from the mapping node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Man_t * Map_NodeReadMan( Map_Node_t * p ) { return p->p; } -char * Map_NodeReadData( Map_Node_t * p, int fPhase ) { return fPhase? p->pData1 : p->pData0; } -int Map_NodeReadNum( Map_Node_t * p ) { return p->Num; } -int Map_NodeReadLevel( Map_Node_t * p ) { return Map_Regular(p)->Level; } -Map_Cut_t * Map_NodeReadCuts( Map_Node_t * p ) { return p->pCuts; } -Map_Cut_t * Map_NodeReadCutBest( Map_Node_t * p, int fPhase ) { return p->pCutBest[fPhase]; } -Map_Node_t * Map_NodeReadOne( Map_Node_t * p ) { return p->p1; } -Map_Node_t * Map_NodeReadTwo( Map_Node_t * p ) { return p->p2; } -void Map_NodeSetData( Map_Node_t * p, int fPhase, char * pData ) { if (fPhase) p->pData1 = pData; else p->pData0 = pData; } -void Map_NodeSetNextE( Map_Node_t * p, Map_Node_t * pNextE ) { p->pNextE = pNextE; } -void Map_NodeSetRepr( Map_Node_t * p, Map_Node_t * pRepr ) { p->pRepr = pRepr; } -void Map_NodeSetSwitching( Map_Node_t * p, float Switching ) { p->Switching = Switching; } - -/**Function************************************************************* - - Synopsis [Checks the type of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_NodeIsConst( Map_Node_t * p ) { return (Map_Regular(p))->Num == -1; } -int Map_NodeIsVar( Map_Node_t * p ) { return (Map_Regular(p))->p1 == NULL && (Map_Regular(p))->Num >= 0; } -int Map_NodeIsAnd( Map_Node_t * p ) { return (Map_Regular(p))->p1 != NULL; } -int Map_NodeComparePhase( Map_Node_t * p1, Map_Node_t * p2 ) { assert( !Map_IsComplement(p1) ); assert( !Map_IsComplement(p2) ); return p1->fInv ^ p2->fInv; } - -/**Function************************************************************* - - Synopsis [Reads parameters from the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Super_t * Map_CutReadSuperBest( Map_Cut_t * p, int fPhase ) { return p->M[fPhase].pSuperBest;} -Map_Super_t * Map_CutReadSuper0( Map_Cut_t * p ) { return p->M[0].pSuperBest;} -Map_Super_t * Map_CutReadSuper1( Map_Cut_t * p ) { return p->M[1].pSuperBest;} -int Map_CutReadLeavesNum( Map_Cut_t * p ) { return p->nLeaves; } -Map_Node_t ** Map_CutReadLeaves( Map_Cut_t * p ) { return p->ppLeaves; } -unsigned Map_CutReadPhaseBest( Map_Cut_t * p, int fPhase ) { return p->M[fPhase].uPhaseBest;} -unsigned Map_CutReadPhase0( Map_Cut_t * p ) { return p->M[0].uPhaseBest;} -unsigned Map_CutReadPhase1( Map_Cut_t * p ) { return p->M[1].uPhaseBest;} -Map_Cut_t * Map_CutReadNext( Map_Cut_t * p ) { return p->pNext; } - -/**Function************************************************************* - - Synopsis [Reads parameters from the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Map_SuperReadFormula( Map_Super_t * p ) { return p->pFormula; } -Mio_Gate_t * Map_SuperReadRoot( Map_Super_t * p ) { return p->pRoot; } -int Map_SuperReadNum( Map_Super_t * p ) { return p->Num; } -Map_Super_t ** Map_SuperReadFanins( Map_Super_t * p ) { return p->pFanins; } -int Map_SuperReadFaninNum( Map_Super_t * p ) { return p->nFanins; } -Map_Super_t * Map_SuperReadNext( Map_Super_t * p ) { return p->pNext; } -int Map_SuperReadNumPhases( Map_Super_t * p ) { return p->nPhases; } -unsigned char * Map_SuperReadPhases( Map_Super_t * p ) { return p->uPhases; } -int Map_SuperReadFanoutLimit( Map_Super_t * p ) { return p->nFanLimit;} - -Mio_Library_t * Map_SuperLibReadGenLib( Map_SuperLib_t * p ) { return p->pGenlib; } -float Map_SuperLibReadAreaInv( Map_SuperLib_t * p ) { return p->AreaInv; } -Map_Time_t Map_SuperLibReadDelayInv( Map_SuperLib_t * p ) { return p->tDelayInv;} -int Map_SuperLibReadVarsMax( Map_SuperLib_t * p ) { return p->nVarsMax; } - - -/**Function************************************************************* - - Synopsis [Create the mapping manager.] - - Description [The number of inputs and outputs is assumed to be - known is advance. It is much simpler to have them fixed upfront. - When it comes to representing the object graph in the form of - AIG, the resulting manager is similar to the regular AIG manager, - except that it does not use reference counting (and therefore - does not have garbage collections). It does have table resizing. - The data structure is more flexible to represent additional - information needed for mapping.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Man_t * Map_ManCreate( int nInputs, int nOutputs, int fVerbose ) -{ - Map_Man_t * p; - int i; - - // derive the supergate library - if ( Abc_FrameReadLibSuper() == NULL ) - { - printf( "The supergate library is not specified. Use \"read_library\" or \"read_super\".\n" ); - return NULL; - } - - // start the manager - p = ALLOC( Map_Man_t, 1 ); - memset( p, 0, sizeof(Map_Man_t) ); - p->pSuperLib = Abc_FrameReadLibSuper(); - p->nVarsMax = p->pSuperLib->nVarsMax; - p->fVerbose = fVerbose; - p->fEpsilon = (float)0.001; - assert( p->nVarsMax > 0 ); - - if ( p->nVarsMax == 5 ) - Extra_Truth4VarN( &p->uCanons, &p->uPhases, &p->pCounters, 8 ); - - // start various data structures - Map_TableCreate( p ); - Map_MappingSetupTruthTables( p->uTruths ); - Map_MappingSetupTruthTablesLarge( p->uTruthsLarge ); -// printf( "Node = %d bytes. Cut = %d bytes. Super = %d bytes.\n", sizeof(Map_Node_t), sizeof(Map_Cut_t), sizeof(Map_Super_t) ); - p->mmNodes = Extra_MmFixedStart( sizeof(Map_Node_t) ); - p->mmCuts = Extra_MmFixedStart( sizeof(Map_Cut_t) ); - - // make sure the constant node will get index -1 - p->nNodes = -1; - // create the constant node - p->pConst1 = Map_NodeCreate( p, NULL, NULL ); - p->vNodesAll = Map_NodeVecAlloc( 100 ); - p->vNodesTemp = Map_NodeVecAlloc( 100 ); - p->vMapping = Map_NodeVecAlloc( 100 ); - p->vVisited = Map_NodeVecAlloc( 100 ); - - // create the PI nodes - p->nInputs = nInputs; - p->pInputs = ALLOC( Map_Node_t *, nInputs ); - for ( i = 0; i < nInputs; i++ ) - p->pInputs[i] = Map_NodeCreate( p, NULL, NULL ); - - // create the place for the output nodes - p->nOutputs = nOutputs; - p->pOutputs = ALLOC( Map_Node_t *, nOutputs ); - memset( p->pOutputs, 0, sizeof(Map_Node_t *) * nOutputs ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_ManFree( Map_Man_t * p ) -{ -// int i; -// for ( i = 0; i < p->vNodesAll->nSize; i++ ) -// Map_NodeVecFree( p->vNodesAll->pArray[i]->vFanouts ); -// Map_NodeVecFree( p->pConst1->vFanouts ); - if ( p->vAnds ) - Map_NodeVecFree( p->vAnds ); - if ( p->vNodesAll ) - Map_NodeVecFree( p->vNodesAll ); - if ( p->vNodesTemp ) - Map_NodeVecFree( p->vNodesTemp ); - if ( p->vMapping ) - Map_NodeVecFree( p->vMapping ); - if ( p->vVisited ) - Map_NodeVecFree( p->vVisited ); - if ( p->uCanons ) free( p->uCanons ); - if ( p->uPhases ) free( p->uPhases ); - if ( p->pCounters ) free( p->pCounters ); - Extra_MmFixedStop( p->mmNodes ); - Extra_MmFixedStop( p->mmCuts ); - FREE( p->pInputArrivals ); - FREE( p->pInputs ); - FREE( p->pOutputs ); - FREE( p->pBins ); - FREE( p->ppOutputNames ); - FREE( p ); -} - - -/**Function************************************************************* - - Synopsis [Deallocates the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_ManPrintTimeStats( Map_Man_t * p ) -{ - printf( "N-canonical = %d. Matchings = %d. Phases = %d. ", p->nCanons, p->nMatches, p->nPhases ); - printf( "Choice nodes = %d. Choices = %d.\n", p->nChoiceNodes, p->nChoices ); - PRT( "ToMap", p->timeToMap ); - PRT( "Cuts ", p->timeCuts ); - PRT( "Truth", p->timeTruth ); - PRT( "Match", p->timeMatch ); - PRT( "Area ", p->timeArea ); - PRT( "Sweep", p->timeSweep ); - PRT( "ToNet", p->timeToNet ); - PRT( "TOTAL", p->timeTotal ); - if ( p->time1 ) { PRT( "time1", p->time1 ); } - if ( p->time2 ) { PRT( "time2", p->time2 ); } - if ( p->time3 ) { PRT( "time3", p->time3 ); } -} - -/**Function************************************************************* - - Synopsis [Prints the mapping stats.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_ManPrintStatsToFile( char * pName, float Area, float Delay, int Time ) -{ - FILE * pTable; - pTable = fopen( "map_stats.txt", "a+" ); - fprintf( pTable, "%s ", pName ); - fprintf( pTable, "%4.2f ", Area ); - fprintf( pTable, "%4.2f ", Delay ); - fprintf( pTable, "%4.2f\n", (float)(Time)/(float)(CLOCKS_PER_SEC) ); - fclose( pTable ); -} - -/**Function************************************************************* - - Synopsis [Creates a new node.] - - Description [This procedure should be called to create the constant - node and the PI nodes first.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Node_t * Map_NodeCreate( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ) -{ - Map_Node_t * pNode; - // create the node - pNode = (Map_Node_t *)Extra_MmFixedEntryFetch( p->mmNodes ); - memset( pNode, 0, sizeof(Map_Node_t) ); - pNode->tRequired[0].Rise = pNode->tRequired[0].Fall = pNode->tRequired[0].Worst = MAP_FLOAT_LARGE; - pNode->tRequired[1].Rise = pNode->tRequired[1].Fall = pNode->tRequired[1].Worst = MAP_FLOAT_LARGE; - pNode->p1 = p1; - pNode->p2 = p2; - pNode->p = p; - // set the number of this node - pNode->Num = p->nNodes++; - // place to store the fanouts -// pNode->vFanouts = Map_NodeVecAlloc( 5 ); - // store this node in the internal array - if ( pNode->Num >= 0 ) - Map_NodeVecPush( p->vNodesAll, pNode ); - else - pNode->fInv = 1; - // set the level of this node - if ( p1 ) - { -#ifdef MAP_ALLOCATE_FANOUT - // create the fanout info - Map_NodeAddFaninFanout( Map_Regular(p1), pNode ); - Map_NodeAddFaninFanout( Map_Regular(p2), pNode ); -#endif - pNode->Level = 1 + MAP_MAX(Map_Regular(pNode->p1)->Level, Map_Regular(pNode->p2)->Level); - pNode->fInv = Map_NodeIsSimComplement(p1) & Map_NodeIsSimComplement(p2); - } - // reference the inputs (will be used to compute the number of fanouts) - if ( p1 ) Map_NodeRef(p1); - if ( p2 ) Map_NodeRef(p2); - - pNode->nRefEst[0] = pNode->nRefEst[1] = -1; - return pNode; -} - -/**Function************************************************************* - - Synopsis [Create the unique table of AND gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_TableCreate( Map_Man_t * pMan ) -{ - assert( pMan->pBins == NULL ); - pMan->nBins = Cudd_Prime(5000); - pMan->pBins = ALLOC( Map_Node_t *, pMan->nBins ); - memset( pMan->pBins, 0, sizeof(Map_Node_t *) * pMan->nBins ); - pMan->nNodes = 0; -} - -/**Function************************************************************* - - Synopsis [Looks up the AND2 node in the unique table.] - - Description [This procedure implements one-level hashing. All the nodes - are hashed by their children. If the node with the same children was already - created, it is returned by the call to this procedure. If it does not exist, - this procedure creates a new node with these children. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Node_t * Map_TableLookup( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 ) -{ - Map_Node_t * pEnt; - unsigned Key; - - if ( p1 == p2 ) - return p1; - if ( p1 == Map_Not(p2) ) - return Map_Not(pMan->pConst1); - if ( Map_NodeIsConst(p1) ) - { - if ( p1 == pMan->pConst1 ) - return p2; - return Map_Not(pMan->pConst1); - } - if ( Map_NodeIsConst(p2) ) - { - if ( p2 == pMan->pConst1 ) - return p1; - return Map_Not(pMan->pConst1); - } - - if ( Map_Regular(p1)->Num > Map_Regular(p2)->Num ) - pEnt = p1, p1 = p2, p2 = pEnt; - - Key = Map_HashKey2( p1, p2, pMan->nBins ); - for ( pEnt = pMan->pBins[Key]; pEnt; pEnt = pEnt->pNext ) - if ( pEnt->p1 == p1 && pEnt->p2 == p2 ) - return pEnt; - // resize the table - if ( pMan->nNodes >= 2 * pMan->nBins ) - { - Map_TableResize( pMan ); - Key = Map_HashKey2( p1, p2, pMan->nBins ); - } - // create the new node - pEnt = Map_NodeCreate( pMan, p1, p2 ); - // add the node to the corresponding linked list in the table - pEnt->pNext = pMan->pBins[Key]; - pMan->pBins[Key] = pEnt; - return pEnt; -} - - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_TableResize( Map_Man_t * pMan ) -{ - Map_Node_t ** pBinsNew; - Map_Node_t * pEnt, * pEnt2; - int nBinsNew, Counter, i, clk; - unsigned Key; - -clk = clock(); - // get the new table size - nBinsNew = Cudd_Prime(2 * pMan->nBins); - // allocate a new array - pBinsNew = ALLOC( Map_Node_t *, nBinsNew ); - memset( pBinsNew, 0, sizeof(Map_Node_t *) * nBinsNew ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < pMan->nBins; i++ ) - for ( pEnt = pMan->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; - pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL ) - { - Key = Map_HashKey2( pEnt->p1, pEnt->p2, nBinsNew ); - pEnt->pNext = pBinsNew[Key]; - pBinsNew[Key] = pEnt; - Counter++; - } - assert( Counter == pMan->nNodes - pMan->nInputs ); - if ( pMan->fVerbose ) - { -// printf( "Increasing the unique table size from %6d to %6d. ", pMan->nBins, nBinsNew ); -// PRT( "Time", clock() - clk ); - } - // replace the table and the parameters - free( pMan->pBins ); - pMan->pBins = pBinsNew; - pMan->nBins = nBinsNew; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Node_t * Map_NodeAnd( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ) -{ - Map_Node_t * pNode; - pNode = Map_TableLookup( p, p1, p2 ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Node_t * Map_NodeOr( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ) -{ - Map_Node_t * pNode; - pNode = Map_Not( Map_TableLookup( p, Map_Not(p1), Map_Not(p2) ) ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Node_t * Map_NodeExor( Map_Man_t * p, Map_Node_t * p1, Map_Node_t * p2 ) -{ - return Map_NodeMux( p, p1, Map_Not(p2), p2 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Node_t * Map_NodeMux( Map_Man_t * p, Map_Node_t * pC, Map_Node_t * pT, Map_Node_t * pE ) -{ - Map_Node_t * pAnd1, * pAnd2, * pRes; - pAnd1 = Map_TableLookup( p, pC, pT ); - pAnd2 = Map_TableLookup( p, Map_Not(pC), pE ); - pRes = Map_NodeOr( p, pAnd1, pAnd2 ); - return pRes; -} - - -/**Function************************************************************* - - Synopsis [Sets the node to be equivalent to the given one.] - - Description [This procedure is a work-around for the equivalence check. - Does not verify the equivalence. Use at the user's risk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeSetChoice( Map_Man_t * pMan, Map_Node_t * pNodeOld, Map_Node_t * pNodeNew ) -{ - pNodeNew->pNextE = pNodeOld->pNextE; - pNodeOld->pNextE = pNodeNew; - pNodeNew->pRepr = pNodeOld; -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/mapper/mapperCut.c b/src/map/mapper/mapperCut.c deleted file mode 100644 index b05e9d0c..00000000 --- a/src/map/mapper/mapperCut.c +++ /dev/null @@ -1,1168 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperCut.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperCut.c,v 1.12 2005/02/28 05:34:27 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the largest number of cuts considered -#define MAP_CUTS_MAX_COMPUTE 1000 -// the largest number of cuts used -#define MAP_CUTS_MAX_USE 250 - -// temporary hash table to store the cuts -typedef struct Map_CutTableStrutct_t Map_CutTable_t; -struct Map_CutTableStrutct_t -{ - Map_Cut_t ** pBins; // the table used for linear probing - int nBins; // the size of the table - int * pCuts; // the array of cuts currently stored - int nCuts; // the number of cuts currently stored - Map_Cut_t ** pArray; // the temporary array of cuts - Map_Cut_t ** pCuts1; // the temporary array of cuts - Map_Cut_t ** pCuts2; // the temporary array of cuts -}; - -// primes used to compute the hash key -static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 }; - -static Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode ); -static void Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode ); -static Map_Cut_t * Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable, Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 ); -static int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax ); -static Map_Cut_t * Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 ); -static int Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes ); - -static void Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot ); -static void Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot ); -static void Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot ); - -static Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan ); -static void Map_CutTableStop( Map_CutTable_t * p ); -static unsigned Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes ); -static int Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ); -static Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ); -static void Map_CutTableRestart( Map_CutTable_t * p ); - -static Map_Cut_t * Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList ); -static int Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList ); -static Map_Cut_t * Map_CutArray2List( Map_Cut_t ** pArray, int nCuts ); - -static unsigned Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Map_Cut_t * pTemp0, Map_Cut_t * pTemp1, int fComp0, int fComp1 ); - -// iterator through all the cuts of the list -#define Map_ListForEachCut( pList, pCut ) \ - for ( pCut = pList; \ - pCut; \ - pCut = pCut->pNext ) -#define Map_ListForEachCutSafe( pList, pCut, pCut2 ) \ - for ( pCut = pList, \ - pCut2 = pCut? pCut->pNext: NULL; \ - pCut; \ - pCut = pCut2, \ - pCut2 = pCut? pCut->pNext: NULL ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the cuts for each node in the object graph.] - - Description [The cuts are computed in one sweep over the mapping graph. - First, the elementary cuts, which include the node itself, are assigned - to the PI nodes. The internal nodes are considered in the DFS order. - Each node is two-input AND-gate. So to compute the cuts at a node, we - need to merge the sets of cuts of its two predecessors. The merged set - contains only unique cuts with the number of inputs equal to k or less. - Finally, the elementary cut, composed of the node itself, is added to - the set of cuts for the node. - - This procedure is pretty fast for 5-feasible cuts, but it dramatically - slows down on some "dense" networks when computing 6-feasible cuts. - The problem is that there are too many cuts in this case. We should - think how to heuristically trim the number of cuts in such cases, - to have reasonable runtime.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingCuts( Map_Man_t * p ) -{ - ProgressBar * pProgress; - Map_CutTable_t * pTable; - Map_Node_t * pNode; - Map_Cut_t * pCut; - int nCuts, nNodes, i; - int clk = clock(); - // set the elementary cuts for the PI variables - assert( p->nVarsMax > 1 && p->nVarsMax < 7 ); - for ( i = 0; i < p->nInputs; i++ ) - { - pCut = Map_CutAlloc( p ); - pCut->nLeaves = 1; - pCut->ppLeaves[0] = p->pInputs[i]; - p->pInputs[i]->pCuts = pCut; - p->pInputs[i]->pCutBest[0] = NULL; // negative polarity is not mapped - p->pInputs[i]->pCutBest[1] = pCut; // positive polarity is a trivial cut - pCut->uTruth = 0xAAAAAAAA; // the first variable "10101010" - pCut->M[0].AreaFlow = 0.0; - pCut->M[1].AreaFlow = 0.0; - } - - // compute the cuts for the internal nodes - nNodes = p->vAnds->nSize; - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - pTable = Map_CutTableStart( p ); - for ( i = 0; i < nNodes; i++ ) - { - pNode = p->vAnds->pArray[i]; - if ( !Map_NodeIsAnd( pNode ) ) - continue; - Map_CutCompute( p, pTable, pNode ); - Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." ); - } - Extra_ProgressBarStop( pProgress ); - Map_CutTableStop( pTable ); - - // report the stats - if ( p->fVerbose ) - { - nCuts = Map_MappingCountAllCuts(p); - printf( "Nodes = %6d. Total %d-feasible cuts = %10d. Per node = %.1f. ", - p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes ); - PRT( "Time", clock() - clk ); - } - - // print the cuts for the first primary output -// Map_CutListPrint( p, Map_Regular(p->pOutputs[0]) ); -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Cut_t * Map_CutCompute( Map_Man_t * p, Map_CutTable_t * pTable, Map_Node_t * pNode ) -{ - Map_Node_t * pTemp; - Map_Cut_t * pList, * pList1, * pList2; - Map_Cut_t * pCut; - - // if the cuts are computed return them - if ( pNode->pCuts ) - return pNode->pCuts; - - // compute the cuts for the children - pList1 = Map_Regular(pNode->p1)->pCuts; - pList2 = Map_Regular(pNode->p2)->pCuts; - // merge the lists - pList = Map_CutMergeLists( p, pTable, pList1, pList2, - Map_IsComplement(pNode->p1), Map_IsComplement(pNode->p2) ); - // if there are functionally equivalent nodes, union them with this list - assert( pList ); - // only add to the list of cuts if the node is a representative one - if ( pNode->pRepr == NULL ) - { - for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) - { - assert( pTemp->pCuts ); - pList = Map_CutUnionLists( pList, pTemp->pCuts ); - assert( pTemp->pCuts ); - pList = Map_CutSortCuts( p, pTable, pList ); - } - } - // add the new cut - pCut = Map_CutAlloc( p ); - pCut->nLeaves = 1; - pCut->ppLeaves[0] = pNode; - pCut->uTruth = 0xAAAAAAAA; - // append (it is important that the elementary cut is appended first) - pCut->pNext = pList; - // set at the node - pNode->pCuts = pCut; - // remove the dominated cuts - Map_CutFilter( p, pNode ); - // set the phase correctly - if ( pNode->pRepr && Map_NodeComparePhase(pNode, pNode->pRepr) ) - { - Map_ListForEachCut( pNode->pCuts, pCut ) - pCut->Phase = 1; - } -/* - { - int i, Counter = 0;; - for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) - for ( i = 0; i < pCut->nLeaves; i++ ) - Counter += (pCut->ppLeaves[i]->Level >= pNode->Level); -// if ( Counter ) -// printf( " %d", Counter ); - } -*/ - return pCut; -} - -/**Function************************************************************* - - Synopsis [Filter the cuts using dominance.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CutFilter( Map_Man_t * p, Map_Node_t * pNode ) -{ - Map_Cut_t * pTemp, * pPrev, * pCut, * pCut2; - int i, k, Counter; - - Counter = 0; - pPrev = pNode->pCuts; - Map_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 ) - { - // go through all the previous cuts up to pCut - for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext ) - { - // check if every node in pTemp is contained in pCut - for ( i = 0; i < pTemp->nLeaves; i++ ) - { - for ( k = 0; k < pCut->nLeaves; k++ ) - if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] ) - break; - if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut - break; - } - if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut - { - Counter++; - break; - } - } - if ( pTemp != pCut ) // pTemp contain pCut - { - pPrev->pNext = pCut->pNext; // skip pCut - // recycle pCut - Map_CutFree( p, pCut ); - } - else - pPrev = pCut; - } -// printf( "Dominated = %3d. \n", Counter ); -} - -/**Function************************************************************* - - Synopsis [Merges two lists of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Cut_t * Map_CutMergeLists( Map_Man_t * p, Map_CutTable_t * pTable, - Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 ) -{ - Map_Node_t * ppNodes[6]; - Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL }; - Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; - int nNodes, Counter, i; - Map_Cut_t ** ppArray1, ** ppArray2, ** ppArray3; - int nCuts1, nCuts2, nCuts3, k, fComp3; - - ppArray1 = pTable->pCuts1; - ppArray2 = pTable->pCuts2; - nCuts1 = Map_CutList2Array( ppArray1, pList1 ); - nCuts2 = Map_CutList2Array( ppArray2, pList2 ); - // swap the lists based on their length - if ( nCuts1 > nCuts2 ) - { - ppArray3 = ppArray1; - ppArray1 = ppArray2; - ppArray2 = ppArray3; - - nCuts3 = nCuts1; - nCuts1 = nCuts2; - nCuts2 = nCuts3; - - fComp3 = fComp1; - fComp1 = fComp2; - fComp2 = fComp3; - } - // pList1 is shorter or equal length compared to pList2 - - // prepare the manager for the cut computation - Map_CutTableRestart( pTable ); - // go through the cut pairs - Counter = 0; -// for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext ) -// for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext ) - for ( i = 0; i < nCuts1; i++ ) - { - for ( k = 0; k <= i; k++ ) - { - pTemp1 = ppArray1[i]; - pTemp2 = ppArray2[k]; - - if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) - { - if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) - continue; - if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) - continue; - } - - // check if k-feasible cut exists - nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); - if ( nNodes == 0 ) - continue; - // consider the cut for possible addition to the set of new cuts - pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); - if ( pCut == NULL ) - continue; - // add data to the cut - pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); - pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); -// if ( p->nVarsMax == 5 ) -// pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 ); - // add it to the corresponding list - pCut->pNext = pLists[pCut->nLeaves]; - pLists[pCut->nLeaves] = pCut; - // count this cut and quit if limit is reached - Counter++; - if ( Counter == MAP_CUTS_MAX_COMPUTE ) - goto QUITS; - } - for ( k = 0; k < i; k++ ) - { - pTemp1 = ppArray1[k]; - pTemp2 = ppArray2[i]; - - if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) - { - if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) - continue; - if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) - continue; - } - - // check if k-feasible cut exists - nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); - if ( nNodes == 0 ) - continue; - // consider the cut for possible addition to the set of new cuts - pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); - if ( pCut == NULL ) - continue; - // add data to the cut - pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); - pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); -// if ( p->nVarsMax == 5 ) -// pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 ); - // add it to the corresponding list - pCut->pNext = pLists[pCut->nLeaves]; - pLists[pCut->nLeaves] = pCut; - // count this cut and quit if limit is reached - Counter++; - if ( Counter == MAP_CUTS_MAX_COMPUTE ) - goto QUITS; - } - } - // consider the rest of them - for ( i = nCuts1; i < nCuts2; i++ ) - for ( k = 0; k < nCuts1; k++ ) - { - pTemp1 = ppArray1[k]; - pTemp2 = ppArray2[i]; - - if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) - { - if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) - continue; - if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) - continue; - } - - // check if k-feasible cut exists - nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); - if ( nNodes == 0 ) - continue; - // consider the cut for possible addition to the set of new cuts - pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); - if ( pCut == NULL ) - continue; - // add data to the cut - pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); - pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); -// if ( p->nVarsMax == 5 ) -// pCut->uTruth = Map_CutComputeTruth( p, pCut, pTemp1, pTemp2, fComp1, fComp2 ); - // add it to the corresponding list - pCut->pNext = pLists[pCut->nLeaves]; - pLists[pCut->nLeaves] = pCut; - // count this cut and quit if limit is reached - Counter++; - if ( Counter == MAP_CUTS_MAX_COMPUTE ) - goto QUITS; - } -QUITS : - // combine all the lists into one - pListNew = NULL; - ppListNew = &pListNew; - for ( i = 1; i <= p->nVarsMax; i++ ) - { - if ( pLists[i] == NULL ) - continue; - // find the last entry - for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; - pPrev = pCut, pCut = pCut->pNext ); - // connect these lists - *ppListNew = pLists[i]; - ppListNew = &pPrev->pNext; - } - *ppListNew = NULL; - // soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE - pListNew = Map_CutSortCuts( p, pTable, pListNew ); - return pListNew; -} - - -/**Function************************************************************* - - Synopsis [Merges two lists of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Cut_t * Map_CutMergeLists2( Map_Man_t * p, Map_CutTable_t * pTable, - Map_Cut_t * pList1, Map_Cut_t * pList2, int fComp1, int fComp2 ) -{ - Map_Node_t * ppNodes[6]; - Map_Cut_t * pListNew, ** ppListNew, * pLists[7] = { NULL }; - Map_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; - int nNodes, Counter, i; - - // prepare the manager for the cut computation - Map_CutTableRestart( pTable ); - // go through the cut pairs - Counter = 0; - for ( pTemp1 = pList1; pTemp1; pTemp1 = pTemp1->pNext ) - for ( pTemp2 = pList2; pTemp2; pTemp2 = pTemp2->pNext ) - { - // check if k-feasible cut exists - nNodes = Map_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); - if ( nNodes == 0 ) - continue; - // consider the cut for possible addition to the set of new cuts - pCut = Map_CutTableConsider( p, pTable, ppNodes, nNodes ); - if ( pCut == NULL ) - continue; - // add data to the cut - pCut->pOne = Map_CutNotCond( pTemp1, fComp1 ); - pCut->pTwo = Map_CutNotCond( pTemp2, fComp2 ); - // add it to the corresponding list - pCut->pNext = pLists[pCut->nLeaves]; - pLists[pCut->nLeaves] = pCut; - // count this cut and quit if limit is reached - Counter++; - if ( Counter == MAP_CUTS_MAX_COMPUTE ) - goto QUITS; - } -QUITS : - // combine all the lists into one - pListNew = NULL; - ppListNew = &pListNew; - for ( i = 1; i <= p->nVarsMax; i++ ) - { - if ( pLists[i] == NULL ) - continue; - // find the last entry - for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; - pPrev = pCut, pCut = pCut->pNext ); - // connect these lists - *ppListNew = pLists[i]; - ppListNew = &pPrev->pNext; - } - *ppListNew = NULL; - // soft the cuts by arrival times and use only the first MAP_CUTS_MAX_USE - pListNew = Map_CutSortCuts( p, pTable, pListNew ); - return pListNew; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [Returns the number of nodes in the resulting cut, or 0 if the - cut is infeasible. Returns the resulting nodes in the array ppNodes[].] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_CutMergeTwo( Map_Cut_t * pCut1, Map_Cut_t * pCut2, Map_Node_t * ppNodes[], int nNodesMax ) -{ - Map_Node_t * pNodeTemp; - int nTotal, i, k, min, fMismatch; - - // check the special case when at least of the cuts is the largest - if ( pCut1->nLeaves == nNodesMax ) - { - if ( pCut2->nLeaves == nNodesMax ) - { - // return 0 if the cuts are different - for ( i = 0; i < nNodesMax; i++ ) - if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] ) - return 0; - // return nNodesMax if they are the same - for ( i = 0; i < nNodesMax; i++ ) - ppNodes[i] = pCut1->ppLeaves[i]; - return nNodesMax; - } - else if ( pCut2->nLeaves == nNodesMax - 1 ) - { - // return 0 if the cuts are different - fMismatch = 0; - for ( i = 0; i < nNodesMax; i++ ) - if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] ) - { - if ( fMismatch == 1 ) - return 0; - fMismatch = 1; - } - // return nNodesMax if they are the same - for ( i = 0; i < nNodesMax; i++ ) - ppNodes[i] = pCut1->ppLeaves[i]; - return nNodesMax; - } - } - else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax ) - { - // return 0 if the cuts are different - fMismatch = 0; - for ( i = 0; i < nNodesMax; i++ ) - if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] ) - { - if ( fMismatch == 1 ) - return 0; - fMismatch = 1; - } - // return nNodesMax if they are the same - for ( i = 0; i < nNodesMax; i++ ) - ppNodes[i] = pCut2->ppLeaves[i]; - return nNodesMax; - } - - // count the number of unique entries in pCut2 - nTotal = pCut1->nLeaves; - for ( i = 0; i < pCut2->nLeaves; i++ ) - { - // try to find this entry among the leaves of pCut1 - for ( k = 0; k < pCut1->nLeaves; k++ ) - if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] ) - break; - if ( k < pCut1->nLeaves ) // found - continue; - // we found a new entry to add - if ( nTotal == nNodesMax ) - return 0; - ppNodes[nTotal++] = pCut2->ppLeaves[i]; - } - // we know that the feasible cut exists - - // add the starting entries - for ( k = 0; k < pCut1->nLeaves; k++ ) - ppNodes[k] = pCut1->ppLeaves[k]; - - // selection-sort the entries - for ( i = 0; i < nTotal - 1; i++ ) - { - min = i; - for ( k = i+1; k < nTotal; k++ ) -// if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!) - if ( ppNodes[k]->Num < ppNodes[min]->Num ) - min = k; - pNodeTemp = ppNodes[i]; - ppNodes[i] = ppNodes[min]; - ppNodes[min] = pNodeTemp; - } - - return nTotal; -} - -/**Function************************************************************* - - Synopsis [Computes the union of the two lists of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Cut_t * Map_CutUnionLists( Map_Cut_t * pList1, Map_Cut_t * pList2 ) -{ - Map_Cut_t * pTemp, * pRoot; - // find the last cut in the first list - pRoot = pList1; - Map_ListForEachCut( pList1, pTemp ) - pRoot = pTemp; - // attach the non-trival part of the second cut to the end of the first - assert( pRoot->pNext == NULL ); - pRoot->pNext = pList2->pNext; - pList2->pNext = NULL; - return pList1; -} - - -/**Function************************************************************* - - Synopsis [Checks whether the given cut belongs to the list.] - - Description [This procedure takes most of the runtime in the cut - computation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_CutBelongsToList( Map_Cut_t * pList, Map_Node_t * ppNodes[], int nNodes ) -{ - Map_Cut_t * pTemp; - int i; - for ( pTemp = pList; pTemp; pTemp = pTemp->pNext ) - { - for ( i = 0; i < nNodes; i++ ) - if ( pTemp->ppLeaves[i] != ppNodes[i] ) - break; - if ( i == nNodes ) - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Counts all the cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MappingCountAllCuts( Map_Man_t * pMan ) -{ - Map_Node_t * pNode; - Map_Cut_t * pCut; - int i, nCuts; -// int nCuts55 = 0, nCuts5x = 0, nCuts4x = 0, nCuts3x = 0; -// int pCounts[7] = {0}; - nCuts = 0; - for ( i = 0; i < pMan->nBins; i++ ) - for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) - for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) - if ( pCut->nLeaves > 1 ) // skip the elementary cuts - { - nCuts++; -/* - if ( Map_CutRegular(pCut->pOne)->nLeaves == 5 && Map_CutRegular(pCut->pTwo)->nLeaves == 5 ) - nCuts55++; - if ( Map_CutRegular(pCut->pOne)->nLeaves == 5 || Map_CutRegular(pCut->pTwo)->nLeaves == 5 ) - nCuts5x++; - else if ( Map_CutRegular(pCut->pOne)->nLeaves == 4 || Map_CutRegular(pCut->pTwo)->nLeaves == 4 ) - nCuts4x++; - else if ( Map_CutRegular(pCut->pOne)->nLeaves == 3 || Map_CutRegular(pCut->pTwo)->nLeaves == 3 ) - nCuts3x++; -*/ -// pCounts[ Map_CutRegular(pCut->pOne)->nLeaves ]++; -// pCounts[ Map_CutRegular(pCut->pTwo)->nLeaves ]++; - } -// printf( "Total cuts = %6d. 55 = %6d. 5x = %6d. 4x = %6d. 3x = %6d.\n", nCuts, nCuts55, nCuts5x, nCuts4x, nCuts3x ); - -// printf( "Total cuts = %6d. 6= %6d. 5= %6d. 4= %6d. 3= %6d. 2= %6d. 1= %6d.\n", -// nCuts, pCounts[6], pCounts[5], pCounts[4], pCounts[3], pCounts[2], pCounts[1] ); - return nCuts; -} - - -/**Function************************************************************* - - Synopsis [Prints the cuts in the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CutListPrint( Map_Man_t * pMan, Map_Node_t * pRoot ) -{ - Map_Cut_t * pTemp; - int Counter; - for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) - { - printf( "%2d : ", Counter + 1 ); - Map_CutPrint_( pMan, pTemp, pRoot ); - } -} - -/**Function************************************************************* - - Synopsis [Prints the cuts in the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CutListPrint2( Map_Man_t * pMan, Map_Node_t * pRoot ) -{ - Map_Cut_t * pTemp; - int Counter; - for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) - { - printf( "%2d : ", Counter + 1 ); - Map_CutPrint_( pMan, pTemp, pRoot ); - } -} - -/**Function************************************************************* - - Synopsis [Prints the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CutPrint_( Map_Man_t * pMan, Map_Cut_t * pCut, Map_Node_t * pRoot ) -{ - int i; - printf( "(%3d) {", pRoot->Num ); - for ( i = 0; i < pMan->nVarsMax; i++ ) - if ( pCut->ppLeaves[i] ) - printf( " %3d", pCut->ppLeaves[i]->Num ); - printf( " }\n" ); -} - - - - - - - - -/**Function************************************************************* - - Synopsis [Starts the hash table to canonicize cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_CutTable_t * Map_CutTableStart( Map_Man_t * pMan ) -{ - Map_CutTable_t * p; - // allocate the table - p = ALLOC( Map_CutTable_t, 1 ); - memset( p, 0, sizeof(Map_CutTable_t) ); - p->nBins = Cudd_Prime( 10 * MAP_CUTS_MAX_COMPUTE ); - p->pBins = ALLOC( Map_Cut_t *, p->nBins ); - memset( p->pBins, 0, sizeof(Map_Cut_t *) * p->nBins ); - p->pCuts = ALLOC( int, 2 * MAP_CUTS_MAX_COMPUTE ); - p->pArray = ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE ); - p->pCuts1 = ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE ); - p->pCuts2 = ALLOC( Map_Cut_t *, 2 * MAP_CUTS_MAX_COMPUTE ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CutTableStop( Map_CutTable_t * p ) -{ - free( p->pCuts1 ); - free( p->pCuts2 ); - free( p->pArray ); - free( p->pBins ); - free( p->pCuts ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Computes the hash value of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Map_CutTableHash( Map_Node_t * ppNodes[], int nNodes ) -{ - unsigned uRes; - int i; - uRes = 0; - for ( i = 0; i < nNodes; i++ ) - uRes += s_HashPrimes[i] * ppNodes[i]->Num; - return uRes; -} - -/**Function************************************************************* - - Synopsis [Looks up the table for the available cut.] - - Description [Returns -1 if the same cut is found. Returns the index - of the cell where the cut should be added, if it does not exist.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_CutTableLookup( Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ) -{ - Map_Cut_t * pCut; - unsigned Key; - int b, i; - - Key = Map_CutTableHash(ppNodes, nNodes) % p->nBins; - for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins ) - { - pCut = p->pBins[b]; - if ( pCut->nLeaves != nNodes ) - continue; - for ( i = 0; i < nNodes; i++ ) - if ( pCut->ppLeaves[i] != ppNodes[i] ) - break; - if ( i == nNodes ) - return -1; - } - return b; -} - - -/**Function************************************************************* - - Synopsis [Starts the hash table to canonicize cuts.] - - Description [Considers addition of the cut to the hash table.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node_t * ppNodes[], int nNodes ) -{ - Map_Cut_t * pCut; - int Place, i; -// int clk; - // check the cut - Place = Map_CutTableLookup( p, ppNodes, nNodes ); - if ( Place == -1 ) - return NULL; - assert( nNodes > 0 ); - // create the new cut -//clk = clock(); - pCut = Map_CutAlloc( pMan ); -//pMan->time1 += clock() - clk; - pCut->nLeaves = nNodes; - for ( i = 0; i < nNodes; i++ ) - pCut->ppLeaves[i] = ppNodes[i]; - // add the cut to the table - assert( p->pBins[Place] == NULL ); - p->pBins[Place] = pCut; - // add the cut to the new list - p->pCuts[ p->nCuts++ ] = Place; - return pCut; -} - -/**Function************************************************************* - - Synopsis [Prepares the table to be used with other cuts.] - - Description [Restarts the table by cleaning the info about cuts stored - when the previous node was considered.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CutTableRestart( Map_CutTable_t * p ) -{ - int i; - for ( i = 0; i < p->nCuts; i++ ) - { - assert( p->pBins[ p->pCuts[i] ] ); - p->pBins[ p->pCuts[i] ] = NULL; - } - p->nCuts = 0; -} - - - -/**Function************************************************************* - - Synopsis [Compares the cuts by the number of leaves and then by delay.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_CutSortCutsCompare( Map_Cut_t ** pC1, Map_Cut_t ** pC2 ) -{ - if ( (*pC1)->nLeaves < (*pC2)->nLeaves ) - return -1; - if ( (*pC1)->nLeaves > (*pC2)->nLeaves ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Sorts the cuts by average arrival time.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Cut_t * Map_CutSortCuts( Map_Man_t * pMan, Map_CutTable_t * p, Map_Cut_t * pList ) -{ - Map_Cut_t * pListNew; - int nCuts, i; -// int clk; - // move the cuts from the list into the array - nCuts = Map_CutList2Array( p->pCuts1, pList ); - assert( nCuts <= MAP_CUTS_MAX_COMPUTE ); - // sort the cuts -//clk = clock(); - qsort( (void *)p->pCuts1, nCuts, sizeof(Map_Cut_t *), - (int (*)(const void *, const void *)) Map_CutSortCutsCompare ); -//pMan->time2 += clock() - clk; - // move them back into the list - if ( nCuts > MAP_CUTS_MAX_USE - 1 ) - { - // free the remaining cuts - for ( i = MAP_CUTS_MAX_USE - 1; i < nCuts; i++ ) - Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] ); - // update the number of cuts - nCuts = MAP_CUTS_MAX_USE - 1; - } - pListNew = Map_CutArray2List( p->pCuts1, nCuts ); - return pListNew; -} - -/**Function************************************************************* - - Synopsis [Moves the nodes from the list into the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_CutList2Array( Map_Cut_t ** pArray, Map_Cut_t * pList ) -{ - int i; - for ( i = 0; pList; pList = pList->pNext, i++ ) - pArray[i] = pList; - return i; -} - -/**Function************************************************************* - - Synopsis [Moves the nodes from the array into the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Cut_t * Map_CutArray2List( Map_Cut_t ** pArray, int nCuts ) -{ - Map_Cut_t * pListNew, ** ppListNew; - int i; - pListNew = NULL; - ppListNew = &pListNew; - for ( i = 0; i < nCuts; i++ ) - { - // connect these lists - *ppListNew = pArray[i]; - ppListNew = &pArray[i]->pNext; - } -//printf( "\n" ); - - *ppListNew = NULL; - return pListNew; -} - - -/**Function************************************************************* - - Synopsis [Computes the truth table of the 5-input cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Map_CutComputeTruth( Map_Man_t * p, Map_Cut_t * pCut, Map_Cut_t * pTemp0, Map_Cut_t * pTemp1, int fComp0, int fComp1 ) -{ - static unsigned ** pPerms53 = NULL; - static unsigned ** pPerms54 = NULL; - - unsigned uPhase, uTruth, uTruth0, uTruth1; - int i, k; - - if ( pPerms53 == NULL ) - { - pPerms53 = (unsigned **)Extra_TruthPerm53(); - pPerms54 = (unsigned **)Extra_TruthPerm54(); - } - - // find the mapping from the old nodes to the new - if ( pTemp0->nLeaves == pCut->nLeaves ) - uTruth0 = pTemp0->uTruth; - else - { - assert( pTemp0->nLeaves < pCut->nLeaves ); - uPhase = 0; - for ( i = 0; i < (int)pTemp0->nLeaves; i++ ) - { - for ( k = 0; k < pCut->nLeaves; k++ ) - if ( pTemp0->ppLeaves[i] == pCut->ppLeaves[k] ) - break; - uPhase |= (1 << k); - } - assert( uPhase < 32 ); - if ( pTemp0->nLeaves == 4 ) - { - if ( uPhase == 31-16 ) // 01111 - uTruth0 = pTemp0->uTruth; - else if ( uPhase == 31-8 ) // 10111 - uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][0]; - else if ( uPhase == 31-4 ) // 11011 - uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][1]; - else if ( uPhase == 31-2 ) // 11101 - uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][2]; - else if ( uPhase == 31-1 ) // 11110 - uTruth0 = pPerms54[pTemp0->uTruth & 0xFFFF][3]; - else - assert( 0 ); - } - else - uTruth0 = pPerms53[pTemp0->uTruth & 0xFF][uPhase]; - } - uTruth0 = fComp0? ~uTruth0: uTruth0; - - // find the mapping from the old nodes to the new - if ( pTemp1->nLeaves == pCut->nLeaves ) - uTruth1 = pTemp1->uTruth; - else - { - assert( pTemp1->nLeaves < pCut->nLeaves ); - uPhase = 0; - for ( i = 0; i < (int)pTemp1->nLeaves; i++ ) - { - for ( k = 0; k < pCut->nLeaves; k++ ) - if ( pTemp1->ppLeaves[i] == pCut->ppLeaves[k] ) - break; - uPhase |= (1 << k); - } - assert( uPhase < 32 ); - if ( pTemp1->nLeaves == 4 ) - { - if ( uPhase == 31-16 ) // 01111 - uTruth1 = pTemp1->uTruth; - else if ( uPhase == 31-8 ) // 10111 - uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][0]; - else if ( uPhase == 31-4 ) // 11011 - uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][1]; - else if ( uPhase == 31-2 ) // 11101 - uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][2]; - else if ( uPhase == 31-1 ) // 11110 - uTruth1 = pPerms54[pTemp1->uTruth & 0xFFFF][3]; - else - assert( 0 ); - } - else - uTruth1 = pPerms53[pTemp1->uTruth & 0xFF][uPhase]; - } - uTruth1 = fComp1? ~uTruth1: uTruth1; - uTruth = uTruth0 & uTruth1; - return uTruth; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/mapper/mapperCutUtils.c b/src/map/mapper/mapperCutUtils.c deleted file mode 100644 index 4450cb04..00000000 --- a/src/map/mapper/mapperCutUtils.c +++ /dev/null @@ -1,273 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperCutUtils.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperCutUtils.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Cut_t * Map_CutAlloc( Map_Man_t * p ) -{ - Map_Cut_t * pCut; - Map_Match_t * pMatch; - pCut = (Map_Cut_t *)Extra_MmFixedEntryFetch( p->mmCuts ); - memset( pCut, 0, sizeof(Map_Cut_t) ); - - pMatch = pCut->M; - pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned - pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned - pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned - pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned - - pMatch = pCut->M + 1; - pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned - pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned - pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned - pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned - return pCut; -} - -/**Function************************************************************* - - Synopsis [Deallocates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CutFree( Map_Man_t * p, Map_Cut_t * pCut ) -{ - if ( pCut ) - Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pCut ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CutPrint( Map_Man_t * p, Map_Node_t * pRoot, Map_Cut_t * pCut, int fPhase ) -{ - int i; - printf( "CUT: Delay = (%4.2f, %4.2f). Area = %4.2f. Nodes = %d -> {", - pCut->M[fPhase].tArrive.Rise, pCut->M[fPhase].tArrive.Fall, pCut->M[fPhase].AreaFlow, pRoot->Num ); - for ( i = 0; i < pCut->nLeaves; i++ ) - printf( " %d", pCut->ppLeaves[i]->Num ); - printf( " } \n" ); -} - - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_CutGetRootArea( Map_Cut_t * pCut, int fPhase ) -{ - assert( pCut->M[fPhase].pSuperBest ); - return pCut->M[fPhase].pSuperBest->Area; -} - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -int Map_CutGetLeafPhase( Map_Cut_t * pCut, int fPhase, int iLeaf ) -{ - assert( pCut->M[fPhase].pSuperBest ); - return (( pCut->M[fPhase].uPhaseBest & (1<pCutBest[fPhase]->M[fPhase].pSuperBest ); - return (( pNode->pCutBest[fPhase]->M[fPhase].uPhaseBest & (1<pNext ) - pPrev = pTemp; - // append all the end of the current set - assert( pPrev->pNext == NULL ); - pPrev->pNext = pSetAll; - return pSets; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CutListRecycle( Map_Man_t * p, Map_Cut_t * pSetList, Map_Cut_t * pSave ) -{ - Map_Cut_t * pNext, * pTemp; - for ( pTemp = pSetList, pNext = pTemp? pTemp->pNext : NULL; - pTemp; - pTemp = pNext, pNext = pNext? pNext->pNext : NULL ) - if ( pTemp != pSave ) - Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pTemp ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_CutListCount( Map_Cut_t * pSets ) -{ - Map_Cut_t * pTemp; - int i; - for ( i = 0, pTemp = pSets; pTemp; pTemp = pTemp->pNext, i++ ); - return i; -} - -#if 0 - -/**function************************************************************* - - synopsis [Removes the fanouts of the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -void Map_CutRemoveFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) -{ - Map_NodeVec_t * vFanouts; - int i, k; - for ( i = 0; i < pCut->nLeaves; i++ ) - { - vFanouts = pCut->ppLeaves[i]->vFanouts; - for ( k = 0; k < vFanouts->nSize; k++ ) - if ( vFanouts->pArray[k] == pNode ) - break; - assert( k != vFanouts->nSize ); - for ( k++; k < vFanouts->nSize; k++ ) - vFanouts->pArray[k-1] = vFanouts->pArray[k]; - vFanouts->nSize--; - } -} - -/**function************************************************************* - - synopsis [Removes the fanouts of the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -void Map_CutInsertFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) -{ - int i; - for ( i = 0; i < pCut->nLeaves; i++ ) - Map_NodeVecPush( pCut->ppLeaves[i]->vFanouts, pNode ); -} - -#endif - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperFanout.c b/src/map/mapper/mapperFanout.c deleted file mode 100644 index 63cdbd2a..00000000 --- a/src/map/mapper/mapperFanout.c +++ /dev/null @@ -1,141 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperFanout.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperFanout.c,v 1.5 2005/01/23 06:59:43 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -#ifdef MAP_ALLOCATE_FANOUT - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Add the fanout to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeAddFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanout ) -{ - Map_Node_t * pPivot; - - // pFanins is a fanin of pFanout - assert( !Map_IsComplement(pFanin) ); - assert( !Map_IsComplement(pFanout) ); - assert( Map_Regular(pFanout->p1) == pFanin || Map_Regular(pFanout->p2) == pFanin ); - - pPivot = pFanin->pFanPivot; - if ( pPivot == NULL ) - { - pFanin->pFanPivot = pFanout; - return; - } - - if ( Map_Regular(pPivot->p1) == pFanin ) - { - if ( Map_Regular(pFanout->p1) == pFanin ) - { - pFanout->pFanFanin1 = pPivot->pFanFanin1; - pPivot->pFanFanin1 = pFanout; - } - else // if ( Map_Regular(pFanout->p2) == pFanin ) - { - pFanout->pFanFanin2 = pPivot->pFanFanin1; - pPivot->pFanFanin1 = pFanout; - } - } - else // if ( Map_Regular(pPivot->p2) == pFanin ) - { - assert( Map_Regular(pPivot->p2) == pFanin ); - if ( Map_Regular(pFanout->p1) == pFanin ) - { - pFanout->pFanFanin1 = pPivot->pFanFanin2; - pPivot->pFanFanin2 = pFanout; - } - else // if ( Map_Regular(pFanout->p2) == pFanin ) - { - pFanout->pFanFanin2 = pPivot->pFanFanin2; - pPivot->pFanFanin2 = pFanout; - } - } -} - -/**Function************************************************************* - - Synopsis [Add the fanout to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeRemoveFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanoutToRemove ) -{ - Map_Node_t * pFanout, * pFanout2, ** ppFanList; - // start the linked list of fanouts - ppFanList = &pFanin->pFanPivot; - // go through the fanouts - Map_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 ) - { - // skip the fanout-to-remove - if ( pFanout == pFanoutToRemove ) - continue; - // add useful fanouts to the list - *ppFanList = pFanout; - ppFanList = Map_NodeReadNextFanoutPlace( pFanin, pFanout ); - } - *ppFanList = NULL; -} - -/**Function************************************************************* - - Synopsis [Returns the number of fanouts of a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_NodeGetFanoutNum( Map_Node_t * pNode ) -{ - Map_Node_t * pFanout; - int Counter = 0; - Map_NodeForEachFanout( pNode, pFanout ) - Counter++; - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#endif - diff --git a/src/map/mapper/mapperGENERIC.c b/src/map/mapper/mapperGENERIC.c deleted file mode 100644 index 823eb4f2..00000000 --- a/src/map/mapper/mapperGENERIC.c +++ /dev/null @@ -1,46 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapper__.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: mapper__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperInt.h b/src/map/mapper/mapperInt.h deleted file mode 100644 index 37cca3d3..00000000 --- a/src/map/mapper/mapperInt.h +++ /dev/null @@ -1,477 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperInt.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperInt.h,v 1.8 2004/09/30 21:18:10 satrajit Exp $] - -***********************************************************************/ - -#ifndef __MAPPER_INT_H__ -#define __MAPPER_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//#include "leaks.h" -#include -#include -#include -#include -#include "cuddInt.h" -#include "main.h" -#include "mio.h" -#include "mapper.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// uncomment to have fanouts represented in the mapping graph -//#define MAP_ALLOCATE_FANOUT 1 - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// the bit masks -#define MAP_MASK(n) ((~((unsigned)0)) >> (32-(n))) -#define MAP_FULL (~((unsigned)0)) -#define MAP_NO_VAR (-9999.0) - -// maximum/minimum operators -#define MAP_MIN(a,b) (((a) < (b))? (a) : (b)) -#define MAP_MAX(a,b) (((a) > (b))? (a) : (b)) - -// the small and large numbers (min/max float are 1.17e-38/3.40e+38) -#define MAP_FLOAT_LARGE ((float)(FLT_MAX/10)) -#define MAP_FLOAT_SMALL ((float)1.0e-03) - -// generating random unsigned (#define RAND_MAX 0x7fff) -#define MAP_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) - -// internal macros to work with cuts -#define Map_CutIsComplement(p) (((int)((unsigned long) (p) & 01))) -#define Map_CutRegular(p) ((Map_Cut_t *)((unsigned long)(p) & ~01)) -#define Map_CutNot(p) ((Map_Cut_t *)((unsigned long)(p) ^ 01)) -#define Map_CutNotCond(p,c) ((Map_Cut_t *)((unsigned long)(p) ^ (c))) - -// internal macros for referencing of nodes -#define Map_NodeReadRef(p) ((Map_Regular(p))->nRefs) -#define Map_NodeRef(p) ((Map_Regular(p))->nRefs++) - -// macros to get hold of the bits in the support info -#define Map_InfoSetVar(p,i) (p[(i)>>5] |= (1<<((i) & 31))) -#define Map_InfoRemVar(p,i) (p[(i)>>5] &= ~(1<<((i) & 31))) -#define Map_InfoFlipVar(p,i) (p[(i)>>5] ^= (1<<((i) & 31))) -#define Map_InfoReadVar(p,i) ((p[(i)>>5] & (1<<((i) & 31))) > 0) - -// returns the complemented attribute of the node -#define Map_NodeIsSimComplement(p) (Map_IsComplement(p)? !(Map_Regular(p)->fInv) : (p)->fInv) - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// the mapping manager -struct Map_ManStruct_t_ -{ - // the mapping graph - Map_Node_t ** pBins; // the table of nodes hashed by their children - int nBins; // the size of the table - Map_Node_t ** pInputs; // the array of inputs - int nInputs; // the number of inputs - Map_Node_t ** pOutputs; // the array of outputs - int nOutputs; // the number of outputs - int nNodes; // the total number of nodes - Map_Node_t * pConst1; // the constant 1 node - Map_NodeVec_t * vAnds; // the array of nodes in the DFS order - Map_NodeVec_t * vNodesAll; // the array of all nodes - Map_NodeVec_t * vNodesTemp; // the array of all nodes - Map_NodeVec_t * vMapping; // the array of internal nodes used in the mapping - - // info about the original circuit - char ** ppOutputNames; // the primary output names - Map_Time_t * pInputArrivals;// the PI arrival times - - // mapping parameters - int nVarsMax; // the max number of variables - int fAreaRecovery; // the flag to enable area recovery - int fVerbose; // the verbosiness flag - int fMappingMode; // set to 1 when doing area - float fRequiredGlo; // the global required times - float fEpsilon; // the epsilon used to compare floats - float AreaBase; // the area after delay-oriented mapping - float AreaFinal; // the area after delay-oriented mapping - int nIterations; // How many matching passes to do - bool fObeyFanoutLimits;// Should mapper try to obey fanout limits or not - float DelayTarget; // the required times set by the user - int nTravIds; // the traversal counter - bool fSwitching; // Should mapper try to obey fanout limits or not - - // the supergate library - Map_SuperLib_t * pSuperLib; // the current supergate library - unsigned uTruths[6][2]; // the elementary truth tables - unsigned uTruthsLarge[10][32]; // the elementary truth tables - int nCounts[32]; // the counter of minterms - int nCountsBest[32];// the counter of minterms - Map_NodeVec_t * vVisited; // the visited cuts during cut computation - - // the memory managers - Extra_MmFixed_t * mmNodes; // the memory manager for nodes - Extra_MmFixed_t * mmCuts; // the memory manager for cuts - - // precomputed N-canonical forms - unsigned short * uCanons; // N-canonical forms - char ** uPhases; // N-canonical phases - char * pCounters; // counters of phases - - // various statistical variables - int nChoiceNodes; // the number of choice nodes - int nChoices; // the number of all choices - int nCanons; // the number of times N-canonical form was computed - int nMatches; // the number of times supergate matching was performed - int nPhases; // the number of phases considered during matching - int nFanoutViolations; // the number of nodes in mapped circuit violating fanout - - // runtime statistics - int timeToMap; // time to transfer to the mapping structure - int timeCuts; // time to compute k-feasible cuts - int timeTruth; // time to compute the truth table for each cut - int timeMatch; // time to perform matching for each node - int timeArea; // time to recover area after delay oriented mapping - int timeSweep; // time to perform technology dependent sweep - int timeToNet; // time to transfer back to the network - int timeTotal; // the total mapping time - int time1; // time to transfer to the mapping structure - int time2; // time to transfer to the mapping structure - int time3; // time to transfer to the mapping structure -}; - -// the supergate library -struct Map_SuperLibStruct_t_ -{ - // general info - char * pName; // the name of the supergate library - Mio_Library_t * pGenlib; // the generic library - - // other info - int nVarsMax; // the max number of variables - int nSupersAll; // the total number of supergates - int nSupersReal; // the total number of supergates - int nLines; // the total number of lines in the supergate file - bool fVerbose; // the verbosity flag - - // hash tables - Map_Super_t ** ppSupers; // the array of supergates - Map_HashTable_t * tTableC; // the table mapping N-canonical forms into supergates - Map_HashTable_t * tTable; // the table mapping truth tables into supergates - - // data structures for N-canonical form computation - unsigned uTruths[6][2]; // the elementary truth tables - unsigned uMask[2]; // the mask for the truth table - - // the invertor - Mio_Gate_t * pGateInv; // the pointer to the intertor gate - Map_Time_t tDelayInv; // the delay of the inverter - float AreaInv; // the area of the inverter - float AreaBuf; // the area of the buffer - Map_Super_t * pSuperInv; // the supergate representing the inverter - - // the memory manager for the internal table - Extra_MmFixed_t * mmSupers; // the mamory manager for supergates - Extra_MmFixed_t * mmEntries; // the memory manager for the entries - Extra_MmFlex_t * mmForms; // the memory manager for formulas -}; - -// the mapping node -struct Map_NodeStruct_t_ -{ - // general information about the node - Map_Man_t * p; // the mapping manager - Map_Node_t * pNext; // the next node in the hash table - int Num; // the unique number of this node - int TravId; // the traversal ID (use to avoid cleaning marks) - int nRefs; // the number of references (fanouts) of the given node - unsigned fMark0 : 1; // the mark used for traversals - unsigned fMark1 : 1; // the mark used for traversals - unsigned fUsed : 1; // the mark to mark the node or its fanins - unsigned fInv : 1; // the complemented attribute for the equivalent nodes - unsigned fInvert: 1; // the flag to denote the use of interter - unsigned Level :16; // the level of the given node - unsigned NumTemp:10; // the level of the given node - int nRefAct[3]; // estimated fanout for current covering phase, neg and pos and sum - float nRefEst[3]; // actual fanout for previous covering phase, neg and pos and sum - float Switching; // the probability of switching - - // connectivity - Map_Node_t * p1; // the first child - Map_Node_t * p2; // the second child - Map_Node_t * pNextE; // the next functionally equivalent node - Map_Node_t * pRepr; // the representative of the functionally equivalent class - -#ifdef MAP_ALLOCATE_FANOUT - // representation of node's fanouts - Map_Node_t * pFanPivot; // the first fanout of this node - Map_Node_t * pFanFanin1; // the next fanout of p1 - Map_Node_t * pFanFanin2; // the next fanout of p2 -// Map_NodeVec_t * vFanouts; // the array of fanouts of the gate -#endif - - // the delay information - Map_Time_t tArrival[2]; // the best arrival time of the neg (0) and pos (1) phases - Map_Time_t tRequired[2]; // the required time of the neg (0) and pos (1) phases - - // misc information - Map_Cut_t * pCutBest[2]; // the best mapping for neg and pos phase - Map_Cut_t * pCuts; // mapping choices for the node (elementary comes first) - char * pData0; // temporary storage for the corresponding network node - char * pData1; // temporary storage for the corresponding network node -}; - -// the match of the cut -struct Map_MatchStruct_t_ -{ - // information used for matching - Map_Super_t * pSupers; - unsigned uPhase; - // information about the best selected match - unsigned uPhaseBest; // the best phase (the EXOR of match's phase and gate's phase) - Map_Super_t * pSuperBest; // the best supergate matched - // the parameters of the match - Map_Time_t tArrive; // the arrival time of this match - float AreaFlow; // the area flow or area of this match -}; - -// the cuts used for matching -struct Map_CutStruct_t_ -{ - Map_Cut_t * pNext; // the pointer to the next cut in the list - Map_Cut_t * pOne; // the father of this cut - Map_Cut_t * pTwo; // the mother of this cut - Map_Node_t * ppLeaves[6]; // the leaves of this cut - unsigned uTruth; // truth table for five-input cuts - char nLeaves; // the number of leaves - char nVolume; // the volume of this cut - char fMark; // the mark to denote visited cut - char Phase; // the mark to denote complemented cut - Map_Match_t M[2]; // the matches for positive/negative phase -}; - -// the supergate internally represented -struct Map_SuperStruct_t_ -{ - int Num; // the ID of the supergate - unsigned fSuper : 1; // the flag to distinquish a real super from a fake one - unsigned fExclude: 1; // the flag if set causes gate to be excluded from being used for mapping - unsigned nFanins : 3; // the number of inputs - unsigned nGates : 3; // the number of gates inside this supergate - unsigned nFanLimit: 4; // the max number of fanout count - unsigned nSupers : 16; // the number of supergates in the list - unsigned nPhases : 4; // the number of phases for matching with canonical form - unsigned char uPhases[4]; // the maximum of 4 phases for matching with canonical form - int nUsed; // the number of times the supergate is used - Map_Super_t * pFanins[6]; // the fanins of the gate - Mio_Gate_t * pRoot; // the root gate - unsigned uTruth[2]; // the truth table - Map_Time_t tDelaysR[6]; // the pin-to-pin delay constraints for the rise of the output - Map_Time_t tDelaysF[6]; // the pin-to-pin delay constraints for the rise of the output - Map_Time_t tDelayMax; // the maximum delay - float Area; // the area - char * pFormula; // the symbolic formula - Map_Super_t * pNext; // the pointer to the next super in the list -}; - -// the vector of nodes -struct Map_NodeVecStruct_t_ -{ - Map_Node_t ** pArray; // the array of nodes - int nSize; // the number of entries in the array - int nCap; // the number of allocated entries -}; - -// the hash table -struct Map_HashTableStruct_t_ -{ - Map_HashEntry_t ** pBins; // the table bins - int nBins; // the size of the table - int nEntries; // the total number of entries in the table - Extra_MmFixed_t * mmMan; // the memory manager for entries -}; - -// the entry in the hash table -struct Map_HashEntryStruct_t_ -{ - unsigned uTruth[2]; // the truth table for 6-var function - unsigned uPhase; // the phase to tranform it into the canonical form - Map_Super_t * pGates; // the linked list of matching supergates - Map_HashEntry_t * pNext; // the next entry in the hash table -}; - -// getting hold of the next fanout of the node -#define Map_NodeReadNextFanout( pNode, pFanout ) \ - ( ( pFanout == NULL )? NULL : \ - ((Map_Regular((pFanout)->p1) == (pNode))? \ - (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) ) - -// getting hold of the place where the next fanout will be attached -#define Map_NodeReadNextFanoutPlace( pNode, pFanout ) \ - ( (Map_Regular((pFanout)->p1) == (pNode))? \ - &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 ) - -// iterator through the fanouts of the node -#define Map_NodeForEachFanout( pNode, pFanout ) \ - for ( pFanout = (pNode)->pFanPivot; pFanout; \ - pFanout = Map_NodeReadNextFanout(pNode, pFanout) ) - -// safe iterator through the fanouts of the node -#define Map_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \ - for ( pFanout = (pNode)->pFanPivot, \ - pFanout2 = Map_NodeReadNextFanout(pNode, pFanout); \ - pFanout; \ - pFanout = pFanout2, \ - pFanout2 = Map_NodeReadNextFanout(pNode, pFanout) ) - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== mapperCanon.c =============================================================*/ -/*=== mapperCut.c ===============================================================*/ -extern void Map_MappingCuts( Map_Man_t * p ); -extern int Map_MappingCountAllCuts( Map_Man_t * p ); -/*=== mapperCutDcs.c ===============================================================*/ -extern void Map_ComputeDcs( Map_Man_t * p ); -extern unsigned Map_ComputeIsop_rec( Map_Man_t * p, unsigned uF, unsigned uFD, int iVar, int nVars, int fDir ); -/*=== mapperCutUtils.c ===============================================================*/ -extern Map_Cut_t * Map_CutAlloc( Map_Man_t * p ); -extern void Map_CutFree( Map_Man_t * p, Map_Cut_t * pCut ); -extern void Map_CutPrint( Map_Man_t * p, Map_Node_t * pRoot, Map_Cut_t * pCut, int fPhase ); -extern float Map_CutGetRootArea( Map_Cut_t * pCut, int fPhase ); -extern int Map_CutGetLeafPhase( Map_Cut_t * pCut, int fPhase, int iLeaf ); -extern int Map_NodeGetLeafPhase( Map_Node_t * pNode, int fPhase, int iLeaf ); -extern Map_Cut_t * Map_CutListAppend( Map_Cut_t * pSetAll, Map_Cut_t * pSets ); -extern void Map_CutListRecycle( Map_Man_t * p, Map_Cut_t * pSetList, Map_Cut_t * pSave ); -extern int Map_CutListCount( Map_Cut_t * pSets ); -extern void Map_CutRemoveFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); -extern void Map_CutInsertFanouts( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); -/*=== mapperFanout.c =============================================================*/ -extern void Map_NodeAddFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanout ); -extern void Map_NodeRemoveFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanoutToRemove ); -extern int Map_NodeGetFanoutNum( Map_Node_t * pNode ); -/*=== mapperLib.c ============================================================*/ -extern Map_SuperLib_t * Map_SuperLibCreate( char * pFileName, char * pExcludeFile, bool fAlgorithm, bool fVerbose ); -extern void Map_SuperLibFree( Map_SuperLib_t * p ); -/*=== mapperMatch.c ===============================================================*/ -extern int Map_MappingMatches( Map_Man_t * p ); -extern float Map_MappingCombinePhases( Map_Man_t * p ); -extern void Map_MatchClean( Map_Match_t * pMatch ); -extern int Map_MatchCompare( Map_Man_t * pMan, Map_Match_t * pM1, Map_Match_t * pM2, int fDoingArea ); -/*=== mapperPower.c =============================================================*/ -extern float Map_SwitchCutGetDerefed( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); -extern float Map_SwitchCutRef( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); -extern float Map_SwitchCutDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); -extern float Map_MappingGetSwitching( Map_Man_t * pMan, Map_NodeVec_t * vMapping ); -/*=== mapperRefs.c =============================================================*/ -extern int Map_NodeReadRefPhaseAct( Map_Node_t * pNode, int fPhase ); -extern float Map_NodeReadRefPhaseEst( Map_Node_t * pNode, int fPhase ); -extern void Map_MappingEstimateRefsInit( Map_Man_t * p ); -extern void Map_MappingEstimateRefs( Map_Man_t * p ); -extern float Map_CutGetAreaFlow( Map_Cut_t * pCut, int fPhase ); -extern float Map_CutGetAreaRefed( Map_Cut_t * pCut, int fPhase ); -extern float Map_CutGetAreaDerefed( Map_Cut_t * pCut, int fPhase ); -extern float Map_CutRef( Map_Cut_t * pCut, int fPhase ); -extern float Map_CutDeref( Map_Cut_t * pCut, int fPhase ); -extern void Map_MappingSetRefs( Map_Man_t * pMan ); -extern float Map_MappingGetArea( Map_Man_t * pMan, Map_NodeVec_t * vMapping ); -/*=== mapperShow.c =============================================================*/ -extern void Map_MappingShow( Map_Man_t * pMan, char * pFileName ); -/*=== mapperTree.c ===============================================================*/ -extern int Map_LibraryReadTree( Map_SuperLib_t * pLib, char * pFileName, char * pExcludeFile ); -extern void Map_LibraryPrintTree( Map_SuperLib_t * pLib ); -/*=== mapperSuper.c ===============================================================*/ -extern int Map_LibraryRead( Map_SuperLib_t * p, char * pFileName ); -extern void Map_LibraryPrintSupergate( Map_Super_t * pGate ); -/*=== mapperTable.c ============================================================*/ -extern Map_HashTable_t * Map_SuperTableCreate( Map_SuperLib_t * pLib ); -extern void Map_SuperTableFree( Map_HashTable_t * p ); -extern int Map_SuperTableInsertC( Map_HashTable_t * pLib, unsigned uTruthC[], Map_Super_t * pGate ); -extern int Map_SuperTableInsert( Map_HashTable_t * pLib, unsigned uTruth[], Map_Super_t * pGate, unsigned uPhase ); -extern Map_Super_t * Map_SuperTableLookup( Map_HashTable_t * p, unsigned uTruth[], unsigned * puPhase ); -extern void Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax ); -extern void Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax ); -/*=== mapperTime.c =============================================================*/ -extern float Map_TimeCutComputeArrival( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float tWorstCaseLimit ); -extern void Map_TimeCutComputeArrival_rec( Map_Cut_t * pCut, int fPhase ); -extern float Map_TimeComputeArrivalMax( Map_Man_t * p ); -extern void Map_TimeComputeRequiredGlobal( Map_Man_t * p ); -extern void Map_TimeComputeRequired( Map_Man_t * p, float fRequired ); -extern float Map_TimeNodeFanoutDelay( Map_Node_t * pNode, int fPhase ); -extern float Map_TimeCutFanoutDelay( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ); -extern float Map_TimeMatchWithInverter( Map_Man_t * p, Map_Match_t * pMatch ); -/*=== mapperTruth.c ===============================================================*/ -extern void Map_MappingTruths( Map_Man_t * pMan ); -extern int Map_TruthsCutDontCare( Map_Man_t * pMan, Map_Cut_t * pCut, unsigned * uTruthDc ); -extern int Map_TruthCountOnes( unsigned * uTruth, int nLeaves ); -extern int Map_TruthDetectTwoFirst( unsigned * uTruth, int nLeaves ); -/*=== mapperUtils.c ===============================================================*/ -extern Map_NodeVec_t * Map_MappingDfs( Map_Man_t * pMan, int fCollectEquiv ); -extern Map_NodeVec_t * Map_MappingDfsNodes( Map_Man_t * pMan, Map_Node_t ** ppNodes, int nNodes, int fEquiv ); - -extern void Map_MappingDfsMarked1_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fFirst ); -extern void Map_MappingDfsMarked2_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, Map_NodeVec_t * vBoundary, int fFirst ); - -extern int Map_MappingCountLevels( Map_Man_t * pMan ); -extern void Map_MappingUnmark( Map_Man_t * pMan ); -extern void Map_MappingMark_rec( Map_Node_t * pNode ); -extern void Map_MappingUnmark_rec( Map_Node_t * pNode ); -extern void Map_MappingPrintOutputArrivals( Map_Man_t * p ); -extern void Map_MappingSetupMask( unsigned uMask[], int nVarsMax ); -extern int Map_MappingNodeIsViolator( Map_Node_t * pNode, Map_Cut_t * pCut, int fPosPol ); -extern float Map_MappingGetAreaFlow( Map_Man_t * p ); -extern void Map_MappingSortByLevel( Map_Man_t * pMan, Map_NodeVec_t * vNodes ); -extern int Map_MappingCountDoubles( Map_Man_t * pMan, Map_NodeVec_t * vNodes ); -extern void Map_MappingExpandTruth( unsigned uTruth[2], int nVars ); -extern float Map_MappingPrintSwitching( Map_Man_t * pMan ); -extern void Map_MappingSetPlacementInfo( Map_Man_t * p ); -extern float Map_MappingPrintWirelength( Map_Man_t * p ); -extern void Map_MappingWireReport( Map_Man_t * p ); -extern float Map_MappingComputeDelayWithFanouts( Map_Man_t * p ); -extern int Map_MappingGetMaxLevel( Map_Man_t * pMan ); -extern void Map_MappingSetChoiceLevels( Map_Man_t * pMan ); -extern void Map_MappingReportChoices( Map_Man_t * pMan ); -/*=== mapperVec.c =============================================================*/ -extern Map_NodeVec_t * Map_NodeVecAlloc( int nCap ); -extern void Map_NodeVecFree( Map_NodeVec_t * p ); -extern Map_Node_t ** Map_NodeVecReadArray( Map_NodeVec_t * p ); -extern int Map_NodeVecReadSize( Map_NodeVec_t * p ); -extern void Map_NodeVecGrow( Map_NodeVec_t * p, int nCapMin ); -extern void Map_NodeVecShrink( Map_NodeVec_t * p, int nSizeNew ); -extern void Map_NodeVecClear( Map_NodeVec_t * p ); -extern void Map_NodeVecPush( Map_NodeVec_t * p, Map_Node_t * Entry ); -extern int Map_NodeVecPushUnique( Map_NodeVec_t * p, Map_Node_t * Entry ); -extern Map_Node_t * Map_NodeVecPop( Map_NodeVec_t * p ); -extern void Map_NodeVecRemove( Map_NodeVec_t * p, Map_Node_t * Entry ); -extern void Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_Node_t * Entry ); -extern Map_Node_t * Map_NodeVecReadEntry( Map_NodeVec_t * p, int i ); -extern void Map_NodeVecSortByLevel( Map_NodeVec_t * p ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/map/mapper/mapperLib.c b/src/map/mapper/mapperLib.c deleted file mode 100644 index d916487e..00000000 --- a/src/map/mapper/mapperLib.c +++ /dev/null @@ -1,231 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperLib.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperLib.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads in the supergate library and prepares it for use.] - - Description [The supergates library comes in a .super file. This file - contains descriptions of supergates along with some relevant information. - This procedure reads the supergate file, canonicizes the supergates, - and constructs an additional lookup table, which can be used to map - truth tables of the cuts into the pair (phase, supergate). The phase - indicates how the current truth table should be phase assigned to - match the canonical form of the supergate. The resulting phase is the - bitwise EXOR of the phase needed to canonicize the supergate and the - phase needed to transform the truth table into its canonical form.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_SuperLib_t * Map_SuperLibCreate( char * pFileName, char * pExcludeFile, bool fAlgorithm, bool fVerbose ) -{ - Map_SuperLib_t * p; - int clk; - - // start the supergate library - p = ALLOC( Map_SuperLib_t, 1 ); - memset( p, 0, sizeof(Map_SuperLib_t) ); - p->pName = pFileName; - p->fVerbose = fVerbose; - p->mmSupers = Extra_MmFixedStart( sizeof(Map_Super_t) ); - p->mmEntries = Extra_MmFixedStart( sizeof(Map_HashEntry_t) ); - p->mmForms = Extra_MmFlexStart(); - Map_MappingSetupTruthTables( p->uTruths ); - - // start the hash table - p->tTableC = Map_SuperTableCreate( p ); - p->tTable = Map_SuperTableCreate( p ); - - // read the supergate library from file -clk = clock(); - if ( fAlgorithm ) - { - if ( !Map_LibraryReadTree( p, pFileName, pExcludeFile ) ) - { - Map_SuperLibFree( p ); - return NULL; - } - } - else - { - if ( pExcludeFile != 0 ) - { - printf ("Error: Exclude file support not present for old format. Stop.\n"); - return NULL; - } - if ( !Map_LibraryRead( p, pFileName ) ) - { - Map_SuperLibFree( p ); - return NULL; - } - } - assert( p->nVarsMax > 0 ); - - // report the stats -if ( fVerbose ) { - printf( "Loaded %d unique %d-input supergates from \"%s\". ", - p->nSupersReal, p->nVarsMax, pFileName ); - PRT( "Time", clock() - clk ); -} - - // assign the interver parameters - p->pGateInv = Mio_LibraryReadInv( p->pGenlib ); - p->tDelayInv.Rise = Mio_LibraryReadDelayInvRise( p->pGenlib ); - p->tDelayInv.Fall = Mio_LibraryReadDelayInvFall( p->pGenlib ); - p->tDelayInv.Worst = MAP_MAX( p->tDelayInv.Rise, p->tDelayInv.Fall ); - p->AreaInv = Mio_LibraryReadAreaInv( p->pGenlib ); - p->AreaBuf = Mio_LibraryReadAreaBuf( p->pGenlib ); - - // assign the interver supergate - p->pSuperInv = (Map_Super_t *)Extra_MmFixedEntryFetch( p->mmSupers ); - memset( p->pSuperInv, 0, sizeof(Map_Super_t) ); - p->pSuperInv->Num = -1; - p->pSuperInv->nGates = 1; - p->pSuperInv->nFanins = 1; - p->pSuperInv->nFanLimit = 10; - p->pSuperInv->pFanins[0] = p->ppSupers[0]; - p->pSuperInv->pRoot = p->pGateInv; - p->pSuperInv->Area = p->AreaInv; - p->pSuperInv->tDelayMax = p->tDelayInv; - p->pSuperInv->tDelaysR[0].Rise = MAP_NO_VAR; - p->pSuperInv->tDelaysR[0].Fall = p->tDelayInv.Rise; - p->pSuperInv->tDelaysF[0].Rise = p->tDelayInv.Fall; - p->pSuperInv->tDelaysF[0].Fall = MAP_NO_VAR; - return p; -} - - -/**Function************************************************************* - - Synopsis [Deallocates the supergate library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_SuperLibFree( Map_SuperLib_t * p ) -{ - if ( p == NULL ) return; - if ( p->pGenlib ) - { - assert( p->pGenlib == Abc_FrameReadLibGen() ); - Mio_LibraryDelete( p->pGenlib ); - Abc_FrameSetLibGen( NULL ); - } - if ( p->tTableC ) - Map_SuperTableFree( p->tTableC ); - if ( p->tTable ) - Map_SuperTableFree( p->tTable ); - Extra_MmFixedStop( p->mmSupers ); - Extra_MmFixedStop( p->mmEntries ); - Extra_MmFlexStop( p->mmForms ); - FREE( p->ppSupers ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Derives the library from the genlib library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_SuperLibDeriveFromGenlib( Mio_Library_t * pLib ) -{ - Abc_Frame_t * pAbc = Abc_FrameGetGlobalFrame(); - char * pNameGeneric; - char FileNameGenlib[100]; - char FileNameSuper[100]; - char CommandSuper[500]; - char CommandRead[500]; - FILE * pFile; - - if ( pLib == NULL ) - return 0; - - // write the current library into the file - sprintf( FileNameGenlib, "%s_temp", Mio_LibraryReadName(pLib) ); - pFile = fopen( FileNameGenlib, "w" ); - Mio_WriteLibrary( pFile, pLib, 0 ); - fclose( pFile ); - - // get the file name with the library - pNameGeneric = Extra_FileNameGeneric( Mio_LibraryReadName(pLib) ); - sprintf( FileNameSuper, "%s.super", pNameGeneric ); - free( pNameGeneric ); - - sprintf( CommandSuper, "super -l 1 -i 5 -d 10000000 -a 10000000 -t 100 %s", FileNameGenlib ); - if ( Cmd_CommandExecute( pAbc, CommandSuper ) ) - { - fprintf( stdout, "Cannot execute command \"%s\".\n", CommandSuper ); - return 0; - } -//#ifdef WIN32 -// _unlink( FileNameGenlib ); -//#else -// unlink( FileNameGenlib ); -//#endif - - sprintf( CommandRead, "read_super %s", FileNameSuper ); - if ( Cmd_CommandExecute( pAbc, CommandRead ) ) - { -#ifdef WIN32 - _unlink( FileNameSuper ); -#else - unlink( FileNameSuper ); -#endif - fprintf( stdout, "Cannot execute command \"%s\".\n", CommandRead ); - return 0; - } - -/* // don't remove the intermediate file -#ifdef WIN32 - _unlink( FileNameSuper ); -#else - unlink( FileNameSuper ); -#endif -*/ - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperMatch.c b/src/map/mapper/mapperMatch.c deleted file mode 100644 index bfa72601..00000000 --- a/src/map/mapper/mapperMatch.c +++ /dev/null @@ -1,596 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperMatch.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperMatch.c,v 1.7 2004/09/30 21:18:10 satrajit Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -/* - A potential improvement: - When an internal node is not used in the mapping, its required times - are set to be +infinity. So when we recover area, we try to find the - best match for area and completely disregard the delay for the nodes - that are not currently used in the mapping because any match whose - arrival times are less than the required times (+infinity) can be used. - It may be possible to develop a better approach to recover area for - the nodes that are not currently used in the mapping... -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Map_MatchNodePhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase ); -static int Map_MatchNodeCut( Map_Man_t * p, Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float fWorstLimit ); - -static void Map_MappingSetPiArrivalTimes( Map_Man_t * p ); -static void Map_NodeTryDroppingOnePhase( Map_Man_t * p, Map_Node_t * pNode ); -static void Map_NodeTransferArrivalTimes( Map_Man_t * p, Map_Node_t * pNode ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the best matches of the nodes.] - - Description [Uses parameter p->fMappingMode to decide how to assign - the matches for both polarities of the node. While the matches are - being assigned, one of them may turn out to be better than the other - (in terms of delay, for example). In this case, the worse match can - be permanently dropped, and the corresponding pointer set to NULL.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MappingMatches( Map_Man_t * p ) -{ - ProgressBar * pProgress; - Map_Node_t * pNode; - int i; - - assert( p->fMappingMode >= 0 && p->fMappingMode <= 4 ); - - // use the externally given PI arrival times - if ( p->fMappingMode == 0 ) - Map_MappingSetPiArrivalTimes( p ); - - // estimate the fanouts - if ( p->fMappingMode == 0 ) - Map_MappingEstimateRefsInit( p ); - else if ( p->fMappingMode == 1 ) - Map_MappingEstimateRefs( p ); - - // the PI cuts are matched in the cut computation package - // in the loop below we match the internal nodes - pProgress = Extra_ProgressBarStart( stdout, p->vAnds->nSize ); - for ( i = 0; i < p->vAnds->nSize; i++ ) - { - // skip primary inputs and secondary nodes if mapping with choices - pNode = p->vAnds->pArray[i]; - if ( !Map_NodeIsAnd( pNode ) || pNode->pRepr ) - continue; - - // make sure that at least one non-trival cut is present - if ( pNode->pCuts->pNext == NULL ) - { - printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); - return 0; - } - - // match negative phase - if ( !Map_MatchNodePhase( p, pNode, 0 ) ) - return 0; - // match positive phase - if ( !Map_MatchNodePhase( p, pNode, 1 ) ) - return 0; - - // make sure that at least one phase is mapped - if ( pNode->pCutBest[0] == NULL && pNode->pCutBest[1] == NULL ) - { - printf( "\nError: Could not match both phases of AIG node %d.\n", pNode->Num ); - printf( "Please make sure that the supergate library has equivalents of AND2 or NAND2.\n" ); - printf( "If such supergates exist in the library, report a bug.\n" ); - return 0; - } - - // if both phases are assigned, check if one of them can be dropped - Map_NodeTryDroppingOnePhase( p, pNode ); - // set the arrival times of the node using the best cuts - Map_NodeTransferArrivalTimes( p, pNode ); - - // update the progress bar - Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); - } - Extra_ProgressBarStop( pProgress ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Find the matching of one polarity of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MatchNodePhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase ) -{ - Map_Match_t MatchBest, * pMatch; - Map_Cut_t * pCut, * pCutBest; - float Area1, Area2, fWorstLimit; - - // skip the cuts that have been unassigned during area recovery - pCutBest = pNode->pCutBest[fPhase]; - if ( p->fMappingMode != 0 && pCutBest == NULL ) - return 1; - - // recompute the arrival times of the current best match - // because the arrival times of the fanins may have changed - // as a result of remapping fanins in the topological order - if ( p->fMappingMode != 0 ) - { - Map_TimeCutComputeArrival( pNode, pCutBest, fPhase, MAP_FLOAT_LARGE ); - // make sure that the required times are met - assert( pCutBest->M[fPhase].tArrive.Rise < pNode->tRequired[fPhase].Rise + p->fEpsilon ); - assert( pCutBest->M[fPhase].tArrive.Fall < pNode->tRequired[fPhase].Fall + p->fEpsilon ); - } - - // recompute the exact area of the current best match - // because the exact area of the fanins may have changed - // as a result of remapping fanins in the topological order - if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) - { - pMatch = pCutBest->M + fPhase; - if ( pNode->nRefAct[fPhase] > 0 || - (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0) ) - pMatch->AreaFlow = Area1 = Map_CutDeref( pCutBest, fPhase ); - else - pMatch->AreaFlow = Area1 = Map_CutGetAreaDerefed( pCutBest, fPhase ); - } - else if ( p->fMappingMode == 4 ) - { - pMatch = pCutBest->M + fPhase; - if ( pNode->nRefAct[fPhase] > 0 || - (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0) ) - pMatch->AreaFlow = Area1 = Map_SwitchCutDeref( pNode, pCutBest, fPhase ); - else - pMatch->AreaFlow = Area1 = Map_SwitchCutGetDerefed( pNode, pCutBest, fPhase ); - } - - // save the old mapping - if ( pCutBest ) - MatchBest = pCutBest->M[fPhase]; - else - Map_MatchClean( &MatchBest ); - - // select the new best cut - fWorstLimit = pNode->tRequired[fPhase].Worst; - for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) - { - pMatch = pCut->M + fPhase; - if ( pMatch->pSupers == NULL ) - continue; - - // find the matches for the cut - Map_MatchNodeCut( p, pNode, pCut, fPhase, fWorstLimit ); - if ( pMatch->pSuperBest == NULL || pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon ) - continue; - - // if the cut can be matched compare the matchings - if ( Map_MatchCompare( p, &MatchBest, pMatch, p->fMappingMode ) ) - { - pCutBest = pCut; - MatchBest = *pMatch; - // if we are mapping for delay, the worst-case limit should be tightened - if ( p->fMappingMode == 0 ) - fWorstLimit = MatchBest.tArrive.Worst; - } - } - - if ( pCutBest == NULL ) - return 1; - - // set the new mapping - pNode->pCutBest[fPhase] = pCutBest; - pCutBest->M[fPhase] = MatchBest; - - // reference the new cut if it used - if ( p->fMappingMode >= 2 && - (pNode->nRefAct[fPhase] > 0 || - (pNode->pCutBest[!fPhase] == NULL && pNode->nRefAct[!fPhase] > 0)) ) - { - if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) - Area2 = Map_CutRef( pNode->pCutBest[fPhase], fPhase ); - else if ( p->fMappingMode == 4 ) - Area2 = Map_SwitchCutRef( pNode, pNode->pCutBest[fPhase], fPhase ); - else - assert( 0 ); - assert( Area2 < Area1 + p->fEpsilon ); - } - - // make sure that the requited times are met - assert( MatchBest.tArrive.Rise < pNode->tRequired[fPhase].Rise + p->fEpsilon ); - assert( MatchBest.tArrive.Fall < pNode->tRequired[fPhase].Fall + p->fEpsilon ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Find the best matching of the cut.] - - Description [The parameters: the node (pNode), the cut (pCut), the phase to be matched - (fPhase), and the upper bound on the arrival times of the cut (fWorstLimit). This - procedure goes through the matching supergates up to the phase assignment, and selects the - best supergate, which will be used to map the cut. As a result of calling this procedure - the matching information is written into pMatch.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MatchNodeCut( Map_Man_t * p, Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float fWorstLimit ) -{ - Map_Match_t MatchBest, * pMatch = pCut->M + fPhase; - Map_Super_t * pSuper; - int i, Counter; - - // save the current match of the cut - MatchBest = *pMatch; - // go through the supergates - for ( pSuper = pMatch->pSupers, Counter = 0; pSuper; pSuper = pSuper->pNext, Counter++ ) - { - p->nMatches++; - // this is an attempt to reduce the runtime of matching and area - // at the cost of rare and very minor increase in delay - // (the supergates are sorted by increasing area) - if ( Counter == 30 ) - break; - - // go through different phases of the given match and supergate - pMatch->pSuperBest = pSuper; - for ( i = 0; i < (int)pSuper->nPhases; i++ ) - { - p->nPhases++; - // find the overall phase of this match - pMatch->uPhaseBest = pMatch->uPhase ^ pSuper->uPhases[i]; - if ( p->fMappingMode == 0 ) - { - // get the arrival time - Map_TimeCutComputeArrival( pNode, pCut, fPhase, fWorstLimit ); - // skip the cut if the arrival times exceed the required times - if ( pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon ) - continue; - // get the area (area flow) - pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase ); - } - else - { - // get the area (area flow) - if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) - pMatch->AreaFlow = Map_CutGetAreaDerefed( pCut, fPhase ); - else if ( p->fMappingMode == 4 ) - pMatch->AreaFlow = Map_SwitchCutGetDerefed( pNode, pCut, fPhase ); - else - pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase ); - // skip if the cut is too large - if ( pMatch->AreaFlow > MatchBest.AreaFlow + p->fEpsilon ) - continue; - // get the arrival time - Map_TimeCutComputeArrival( pNode, pCut, fPhase, fWorstLimit ); - // skip the cut if the arrival times exceed the required times - if ( pMatch->tArrive.Worst > fWorstLimit + p->fEpsilon ) - continue; - } - - // if the cut is non-trivial, compare it - if ( Map_MatchCompare( p, &MatchBest, pMatch, p->fMappingMode ) ) - { - MatchBest = *pMatch; - // if we are mapping for delay, the worst-case limit should be reduced - if ( p->fMappingMode == 0 ) - fWorstLimit = MatchBest.tArrive.Worst; - } - } - } - // set the best match - *pMatch = MatchBest; - - // recompute the arrival time and area (area flow) of this cut - if ( pMatch->pSuperBest ) - { - Map_TimeCutComputeArrival( pNode, pCut, fPhase, MAP_FLOAT_LARGE ); - if ( p->fMappingMode == 2 || p->fMappingMode == 3 ) - pMatch->AreaFlow = Map_CutGetAreaDerefed( pCut, fPhase ); - else if ( p->fMappingMode == 4 ) - pMatch->AreaFlow = Map_SwitchCutGetDerefed( pNode, pCut, fPhase ); - else - pMatch->AreaFlow = Map_CutGetAreaFlow( pCut, fPhase ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Cleans the match.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MatchClean( Map_Match_t * pMatch ) -{ - memset( pMatch, 0, sizeof(Map_Match_t) ); - pMatch->AreaFlow = MAP_FLOAT_LARGE; // unassigned - pMatch->tArrive.Rise = MAP_FLOAT_LARGE; // unassigned - pMatch->tArrive.Fall = MAP_FLOAT_LARGE; // unassigned - pMatch->tArrive.Worst = MAP_FLOAT_LARGE; // unassigned -} - -/**Function************************************************************* - - Synopsis [Compares two matches.] - - Description [Returns 1 if the second match is better. Otherwise returns 0.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MatchCompare( Map_Man_t * pMan, Map_Match_t * pM1, Map_Match_t * pM2, int fDoingArea ) -{ - if ( !fDoingArea ) - { - // compare the arrival times - if ( pM1->tArrive.Worst < pM2->tArrive.Worst - pMan->fEpsilon ) - return 0; - if ( pM1->tArrive.Worst > pM2->tArrive.Worst + pMan->fEpsilon ) - return 1; - // compare the areas or area flows - if ( pM1->AreaFlow < pM2->AreaFlow - pMan->fEpsilon ) - return 0; - if ( pM1->AreaFlow > pM2->AreaFlow + pMan->fEpsilon ) - return 1; - // compare the fanout limits - if ( pM1->pSuperBest->nFanLimit > pM2->pSuperBest->nFanLimit ) - return 0; - if ( pM1->pSuperBest->nFanLimit < pM2->pSuperBest->nFanLimit ) - return 1; - // compare the number of leaves - if ( pM1->pSuperBest->nFanins < pM2->pSuperBest->nFanins ) - return 0; - if ( pM1->pSuperBest->nFanins > pM2->pSuperBest->nFanins ) - return 1; - // otherwise prefer the old cut - return 0; - } - else - { - // compare the areas or area flows - if ( pM1->AreaFlow < pM2->AreaFlow - pMan->fEpsilon ) - return 0; - if ( pM1->AreaFlow > pM2->AreaFlow + pMan->fEpsilon ) - return 1; - // compare the arrival times - if ( pM1->tArrive.Worst < pM2->tArrive.Worst - pMan->fEpsilon ) - return 0; - if ( pM1->tArrive.Worst > pM2->tArrive.Worst + pMan->fEpsilon ) - return 1; - // compare the fanout limits - if ( pM1->pSuperBest->nFanLimit > pM2->pSuperBest->nFanLimit ) - return 0; - if ( pM1->pSuperBest->nFanLimit < pM2->pSuperBest->nFanLimit ) - return 1; - // compare the number of leaves - if ( pM1->pSuperBest->nFanins < pM2->pSuperBest->nFanins ) - return 0; - if ( pM1->pSuperBest->nFanins > pM2->pSuperBest->nFanins ) - return 1; - // otherwise prefer the old cut - return 0; - } -} - -/**Function************************************************************* - - Synopsis [Sets the PI arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingSetPiArrivalTimes( Map_Man_t * p ) -{ - Map_Node_t * pNode; - int i; - for ( i = 0; i < p->nInputs; i++ ) - { - pNode = p->pInputs[i]; - // set the arrival time of the positive phase - pNode->tArrival[1] = p->pInputArrivals[i]; - // set the arrival time of the negative phase - pNode->tArrival[0].Rise = pNode->tArrival[1].Fall + p->pSuperLib->tDelayInv.Rise; - pNode->tArrival[0].Fall = pNode->tArrival[1].Rise + p->pSuperLib->tDelayInv.Fall; - pNode->tArrival[0].Worst = MAP_MAX(pNode->tArrival[0].Rise, pNode->tArrival[0].Fall); - } -} - - -/**Function************************************************************* - - Synopsis [Attempts dropping one phase of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeTryDroppingOnePhase( Map_Man_t * p, Map_Node_t * pNode ) -{ - Map_Match_t * pMatchBest0, * pMatchBest1; - float tWorst0Using1, tWorst1Using0; - int fUsePhase1, fUsePhase0; - - // nothing to do if one of the phases is already dropped - if ( pNode->pCutBest[0] == NULL || pNode->pCutBest[1] == NULL ) - return; - - // do not drop while recovering area flow - if ( p->fMappingMode == 1 )//|| p->fMappingMode == 2 ) - return; - - // get the pointers to the matches of the best cuts - pMatchBest0 = pNode->pCutBest[0]->M + 0; - pMatchBest1 = pNode->pCutBest[1]->M + 1; - - // get the worst arrival times of each phase - // implemented using the other phase with inverter added - tWorst0Using1 = Map_TimeMatchWithInverter( p, pMatchBest1 ); - tWorst1Using0 = Map_TimeMatchWithInverter( p, pMatchBest0 ); - - // consider the case of mapping for delay - if ( p->fMappingMode == 0 ) - { - // if the arrival time of a phase is larger than the arrival time - // of the opposite phase plus the inverter, drop this phase - if ( pMatchBest0->tArrive.Worst > tWorst0Using1 + p->fEpsilon ) - pNode->pCutBest[0] = NULL; - else if ( pMatchBest1->tArrive.Worst > tWorst1Using0 + p->fEpsilon ) - pNode->pCutBest[1] = NULL; - return; - } - - // do not perform replacement if one of the phases is unused - if ( pNode->nRefAct[0] == 0 || pNode->nRefAct[1] == 0 ) - return; - - // check if replacement of each phase is possible using required times - fUsePhase0 = fUsePhase1 = 0; - if ( p->fMappingMode == 2 ) - { - fUsePhase0 = (pNode->tRequired[1].Worst > tWorst1Using0 + 3*p->pSuperLib->tDelayInv.Worst + p->fEpsilon); - fUsePhase1 = (pNode->tRequired[0].Worst > tWorst0Using1 + 3*p->pSuperLib->tDelayInv.Worst + p->fEpsilon); - } - else if ( p->fMappingMode == 3 || p->fMappingMode == 4 ) - { - fUsePhase0 = (pNode->tRequired[1].Worst > tWorst1Using0 + p->fEpsilon); - fUsePhase1 = (pNode->tRequired[0].Worst > tWorst0Using1 + p->fEpsilon); - } - if ( !fUsePhase0 && !fUsePhase1 ) - return; - - // if replacement is possible both ways, use the one that works better - if ( fUsePhase0 && fUsePhase1 ) - { - if ( pMatchBest0->AreaFlow < pMatchBest1->AreaFlow ) - fUsePhase1 = 0; - else - fUsePhase0 = 0; - } - // only one phase should be used - assert( fUsePhase0 ^ fUsePhase1 ); - - // set the corresponding cut to NULL - if ( fUsePhase0 ) - { - // deref phase 1 cut if necessary - if ( p->fMappingMode >= 2 && pNode->nRefAct[1] > 0 ) - Map_CutDeref( pNode->pCutBest[1], 1 ); - // get rid of the cut - pNode->pCutBest[1] = NULL; - // ref phase 0 cut if necessary - if ( p->fMappingMode >= 2 && pNode->nRefAct[0] == 0 ) - Map_CutRef( pNode->pCutBest[0], 0 ); - } - else - { - // deref phase 0 cut if necessary - if ( p->fMappingMode >= 2 && pNode->nRefAct[0] > 0 ) - Map_CutDeref( pNode->pCutBest[0], 0 ); - // get rid of the cut - pNode->pCutBest[0] = NULL; - // ref phase 1 cut if necessary - if ( p->fMappingMode >= 2 && pNode->nRefAct[1] == 0 ) - Map_CutRef( pNode->pCutBest[1], 1 ); - } -} - - -/**Function************************************************************* - - Synopsis [Transfers the arrival times from the best cuts to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeTransferArrivalTimes( Map_Man_t * p, Map_Node_t * pNode ) -{ - // if both phases are available, set their arrival times - if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) - { - pNode->tArrival[0] = pNode->pCutBest[0]->M[0].tArrive; - pNode->tArrival[1] = pNode->pCutBest[1]->M[1].tArrive; - } - // if only one phase is available, compute the arrival time of other phase - else if ( pNode->pCutBest[0] ) - { - pNode->tArrival[0] = pNode->pCutBest[0]->M[0].tArrive; - pNode->tArrival[1].Rise = pNode->tArrival[0].Fall + p->pSuperLib->tDelayInv.Rise; - pNode->tArrival[1].Fall = pNode->tArrival[0].Rise + p->pSuperLib->tDelayInv.Fall; - pNode->tArrival[1].Worst = MAP_MAX(pNode->tArrival[1].Rise, pNode->tArrival[1].Fall); - } - else if ( pNode->pCutBest[1] ) - { - pNode->tArrival[1] = pNode->pCutBest[1]->M[1].tArrive; - pNode->tArrival[0].Rise = pNode->tArrival[1].Fall + p->pSuperLib->tDelayInv.Rise; - pNode->tArrival[0].Fall = pNode->tArrival[1].Rise + p->pSuperLib->tDelayInv.Fall; - pNode->tArrival[0].Worst = MAP_MAX(pNode->tArrival[0].Rise, pNode->tArrival[0].Fall); - } - else - { - assert( 0 ); - } - - assert( pNode->tArrival[0].Rise < pNode->tRequired[0].Rise + p->fEpsilon ); - assert( pNode->tArrival[0].Fall < pNode->tRequired[0].Fall + p->fEpsilon ); - - assert( pNode->tArrival[1].Rise < pNode->tRequired[1].Rise + p->fEpsilon ); - assert( pNode->tArrival[1].Fall < pNode->tRequired[1].Fall + p->fEpsilon ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/map/mapper/mapperRefs.c b/src/map/mapper/mapperRefs.c deleted file mode 100644 index a50b134a..00000000 --- a/src/map/mapper/mapperRefs.c +++ /dev/null @@ -1,557 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperRefs.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperRefs.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Map_NodeIncRefPhaseAct( Map_Node_t * pNode, int fPhase ); -static int Map_NodeDecRefPhaseAct( Map_Node_t * pNode, int fPhase ); -static float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference ); -static void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_Node_t ** ppStore ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the actual reference counter of a phase.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_NodeReadRefPhaseAct( Map_Node_t * pNode, int fPhase ) -{ - assert( !Map_IsComplement(pNode) ); - if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned - return pNode->nRefAct[fPhase]; - assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned - return pNode->nRefAct[2]; -} - -/**Function************************************************************* - - Synopsis [Reads the estimated reference counter of a phase.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Map_NodeReadRefPhaseEst( Map_Node_t * pNode, int fPhase ) -{ - assert( !Map_IsComplement(pNode) ); - if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned - return pNode->nRefEst[fPhase]; - assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned -// return pNode->nRefEst[0] + pNode->nRefEst[1]; - return pNode->nRefEst[2]; -} - - -/**Function************************************************************* - - Synopsis [Increments the actual reference counter of a phase.] - - Description [Returns the old reference counter.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_NodeIncRefPhaseAct( Map_Node_t * pNode, int fPhase ) -{ - assert( !Map_IsComplement(pNode) ); - if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned - return pNode->nRefAct[fPhase]++; - assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned - return pNode->nRefAct[2]++; -} - -/**Function************************************************************* - - Synopsis [Decrements the actual reference counter of a phase.] - - Description [Returns the new reference counter.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_NodeDecRefPhaseAct( Map_Node_t * pNode, int fPhase ) -{ - assert( !Map_IsComplement(pNode) ); - if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned - return --pNode->nRefAct[fPhase]; - assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned - return --pNode->nRefAct[2]; -} - - -/**Function************************************************************* - - Synopsis [Sets the estimated reference counter for the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingEstimateRefsInit( Map_Man_t * p ) -{ - Map_Node_t * pNode; - int i; - for ( i = 0; i < p->vAnds->nSize; i++ ) - { - pNode = p->vAnds->pArray[i]; -// pNode->nRefEst[0] = pNode->nRefEst[1] = ((float)pNode->nRefs)*(float)2.0; - pNode->nRefEst[0] = pNode->nRefEst[1] = pNode->nRefEst[2] = ((float)pNode->nRefs); - } -} - -/**Function************************************************************* - - Synopsis [Sets the estimated reference counter.] - - Description [When this procedure is called for the first time, - the reference counter is estimated from the AIG. Otherwise, it is - a linear combination of reference counters in the last two iterations.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingEstimateRefs( Map_Man_t * p ) -{ - Map_Node_t * pNode; - int i; - for ( i = 0; i < p->vAnds->nSize; i++ ) - { - pNode = p->vAnds->pArray[i]; -// pNode->nRefEst[0] = (float)((2.0 * pNode->nRefEst[0] + 1.0 * pNode->nRefAct[0]) / 3.0); -// pNode->nRefEst[1] = (float)((2.0 * pNode->nRefEst[1] + 1.0 * pNode->nRefAct[1]) / 3.0); -// pNode->nRefEst[2] = (float)((2.0 * pNode->nRefEst[2] + 1.0 * pNode->nRefAct[2]) / 3.0); - pNode->nRefEst[0] = (float)((3.0 * pNode->nRefEst[0] + 1.0 * pNode->nRefAct[0]) / 4.0); - pNode->nRefEst[1] = (float)((3.0 * pNode->nRefEst[1] + 1.0 * pNode->nRefAct[1]) / 4.0); - pNode->nRefEst[2] = (float)((3.0 * pNode->nRefEst[2] + 1.0 * pNode->nRefAct[2]) / 4.0); - } -} - - - - - -/**function************************************************************* - - synopsis [Computes the area flow of the cut.] - - description [Computes the area flow of the cut if it is implemented using - the best supergate with the best phase.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_CutGetAreaFlow( Map_Cut_t * pCut, int fPhase ) -{ - Map_Match_t * pM = pCut->M + fPhase; - Map_Super_t * pSuper = pM->pSuperBest; - unsigned uPhaseTot = pM->uPhaseBest; - Map_Cut_t * pCutFanin; - float aFlowRes, aFlowFanin, nRefs; - int i, fPinPhasePos; - - // start the resulting area flow - aFlowRes = pSuper->Area; - // iterate through the leaves - for ( i = 0; i < pCut->nLeaves; i++ ) - { - // get the phase of this fanin - fPinPhasePos = ((uPhaseTot & (1 << i)) == 0); - // get the cut implementing this phase of the fanin - pCutFanin = pCut->ppLeaves[i]->pCutBest[fPinPhasePos]; - // if the cut is not available, we have to use the opposite phase - if ( pCutFanin == NULL ) - { - fPinPhasePos = !fPinPhasePos; - pCutFanin = pCut->ppLeaves[i]->pCutBest[fPinPhasePos]; - } - aFlowFanin = pCutFanin->M[fPinPhasePos].AreaFlow; // ignores the area of the interter - // get the fanout count of the cut in the given phase - nRefs = Map_NodeReadRefPhaseEst( pCut->ppLeaves[i], fPinPhasePos ); - // if the node does no fanout, assume fanout count equal to 1 - if ( nRefs == (float)0.0 ) - nRefs = (float)1.0; - // add the area flow due to the fanin - aFlowRes += aFlowFanin / nRefs; - } - pM->AreaFlow = aFlowRes; - return aFlowRes; -} - - - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [Assumes that the cut is referenced.] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_CutGetAreaRefed( Map_Cut_t * pCut, int fPhase ) -{ - float aResult, aResult2; - aResult2 = Map_CutRefDeref( pCut, fPhase, 0 ); // dereference - aResult = Map_CutRefDeref( pCut, fPhase, 1 ); // reference -// assert( aResult == aResult2 ); - return aResult; -} - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_CutGetAreaDerefed( Map_Cut_t * pCut, int fPhase ) -{ - float aResult, aResult2; - aResult2 = Map_CutRefDeref( pCut, fPhase, 1 ); // reference - aResult = Map_CutRefDeref( pCut, fPhase, 0 ); // dereference -// assert( aResult == aResult2 ); - return aResult; -} - -/**function************************************************************* - - synopsis [References the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_CutRef( Map_Cut_t * pCut, int fPhase ) -{ - return Map_CutRefDeref( pCut, fPhase, 1 ); // reference -} - -/**function************************************************************* - - synopsis [Dereferences the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_CutDeref( Map_Cut_t * pCut, int fPhase ) -{ - return Map_CutRefDeref( pCut, fPhase, 0 ); // dereference -} - -/**function************************************************************* - - synopsis [References or dereferences the cut.] - - description [This reference part is similar to Cudd_NodeReclaim(). - The dereference part is similar to Cudd_RecursiveDeref().] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_CutRefDeref( Map_Cut_t * pCut, int fPhase, int fReference ) -{ - Map_Node_t * pNodeChild; - Map_Cut_t * pCutChild; - float aArea; - int i, fPhaseChild; -// int nRefs; - - // consider the elementary variable - if ( pCut->nLeaves == 1 ) - return 0; - // start the area of this cut - aArea = Map_CutGetRootArea( pCut, fPhase ); - // go through the children - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pNodeChild = pCut->ppLeaves[i]; - fPhaseChild = Map_CutGetLeafPhase( pCut, fPhase, i ); - // get the reference counter of the child -/* - // this code does not take inverters into account - // the quality of area recovery seems to always be a little worse - if ( fReference ) - nRefs = Map_NodeIncRefPhaseAct( pNodeChild, fPhaseChild ); - else - nRefs = Map_NodeDecRefPhaseAct( pNodeChild, fPhaseChild ); - assert( nRefs >= 0 ); - // skip if the child was already reference before - if ( nRefs > 0 ) - continue; -*/ - - if ( fReference ) - { - if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present - { - // if this phase of the node is referenced, there is no recursive call - pNodeChild->nRefAct[2]++; - if ( pNodeChild->nRefAct[fPhaseChild]++ > 0 ) - continue; - } - else // only one phase is present - { - // inverter should be added if the phase - // (a) has no reference and (b) is implemented using other phase - if ( pNodeChild->nRefAct[fPhaseChild]++ == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) - aArea += pNodeChild->p->pSuperLib->AreaInv; - // if the node is referenced, there is no recursive call - if ( pNodeChild->nRefAct[2]++ > 0 ) - continue; - } - } - else - { - if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present - { - // if this phase of the node is referenced, there is no recursive call - --pNodeChild->nRefAct[2]; - if ( --pNodeChild->nRefAct[fPhaseChild] > 0 ) - continue; - } - else // only one phase is present - { - // inverter should be added if the phase - // (a) has no reference and (b) is implemented using other phase - if ( --pNodeChild->nRefAct[fPhaseChild] == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) - aArea += pNodeChild->p->pSuperLib->AreaInv; - // if the node is referenced, there is no recursive call - if ( --pNodeChild->nRefAct[2] > 0 ) - continue; - } - assert( pNodeChild->nRefAct[fPhaseChild] >= 0 ); - } - - // get the child cut - pCutChild = pNodeChild->pCutBest[fPhaseChild]; - // if the child does not have this phase mapped, take the opposite phase - if ( pCutChild == NULL ) - { - fPhaseChild = !fPhaseChild; - pCutChild = pNodeChild->pCutBest[fPhaseChild]; - } - // reference and compute area recursively - aArea += Map_CutRefDeref( pCutChild, fPhaseChild, fReference ); - } - return aArea; -} - - - - -/**Function************************************************************* - - Synopsis [Computes actual reference counters.] - - Description [Collects the nodes used in the mapping in array pMan->vMapping. - Nodes are collected in reverse topological order to facilitate the - computation of required times.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingSetRefs( Map_Man_t * pMan ) -{ - Map_Node_t * pNode, ** ppStore; - int i, fPhase, LevelMax; - - // clean all references - for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) - { - pNode = pMan->vNodesAll->pArray[i]; - pNode->nRefAct[0] = 0; - pNode->nRefAct[1] = 0; - pNode->nRefAct[2] = 0; - } - - // find the largest level of a node - LevelMax = 0; - for ( i = 0; i < pMan->nOutputs; i++ ) - if ( LevelMax < (int)Map_Regular(pMan->pOutputs[i])->Level ) - LevelMax = Map_Regular(pMan->pOutputs[i])->Level; - - // allocate place to store the nodes - ppStore = ALLOC( Map_Node_t *, LevelMax + 1 ); - memset( ppStore, 0, sizeof(Map_Node_t *) * (LevelMax + 1) ); - - // visit nodes reachable from POs in the DFS order through the best cuts - for ( i = 0; i < pMan->nOutputs; i++ ) - { - pNode = pMan->pOutputs[i]; - fPhase = !Map_IsComplement(pNode); - if ( !Map_NodeIsConst(pNode) ) - Map_MappingSetRefs_rec( pMan, pNode, ppStore ); - } - - // reconnect the nodes in reverse topological order - pMan->vMapping->nSize = 0; - for ( i = LevelMax; i >= 0; i-- ) - for ( pNode = ppStore[i]; pNode; pNode = (Map_Node_t *)pNode->pData0 ) - Map_NodeVecPush( pMan->vMapping, pNode ); - free( ppStore ); -} - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_Node_t ** ppStore ) -{ - Map_Cut_t * pCut; - Map_Node_t * pNodeR; - unsigned uPhase; - int i, fPhase, fInvPin; - - // get the regular node and its phase - pNodeR = Map_Regular(pNode); - fPhase = !Map_IsComplement(pNode); - - // add the node to the list of all visited nodes - if ( pNodeR->nRefAct[2]++ == 0 ) -// Map_NodeVecPush( pMan->vMapping, pNodeR ); - pNodeR->pData0 = (char *)ppStore[pNodeR->Level], ppStore[pNodeR->Level] = pNodeR; - - // quit if the node was already visited in this phase - if ( pNodeR->nRefAct[fPhase]++ ) - return; - - // quit if this is a PI node - if ( Map_NodeIsVar(pNodeR) ) - return; - - // get the cut implementing this or opposite polarity - pCut = pNodeR->pCutBest[fPhase]; - if ( pCut == NULL ) - { - fPhase = !fPhase; - pCut = pNodeR->pCutBest[fPhase]; - } - - // visit the transitive fanin - uPhase = pCut->M[fPhase].uPhaseBest; - for ( i = 0; i < pCut->nLeaves; i++ ) - { - fInvPin = ((uPhase & (1 << i)) > 0); - Map_MappingSetRefs_rec( pMan, Map_NotCond(pCut->ppLeaves[i], fInvPin), ppStore ); - } -} - - -/**Function************************************************************* - - Synopsis [Computes the array of mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Map_MappingGetArea( Map_Man_t * pMan, Map_NodeVec_t * vMapping ) -{ - Map_Node_t * pNode; - float Area; - int i; - Area = 0.0; - for ( i = 0; i < vMapping->nSize; i++ ) - { - pNode = vMapping->pArray[i]; - // at least one phase has the best cut assigned - assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); - // at least one phase is used in the mapping - assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); - // compute the array due to the supergate - if ( Map_NodeIsAnd(pNode) ) - { - // count area of the negative phase - if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) - Area += pNode->pCutBest[0]->M[0].pSuperBest->Area; - // count area of the positive phase - if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) - Area += pNode->pCutBest[1]->M[1].pSuperBest->Area; - } - // count area of the interver if we need to implement one phase with another phase - if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) || - (pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) ) - Area += pMan->pSuperLib->AreaInv; - } - // add buffers for each CO driven by a CI - for ( i = 0; i < pMan->nOutputs; i++ ) - if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) ) - Area += pMan->pSuperLib->AreaBuf; - return Area; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperSuper.c b/src/map/mapper/mapperSuper.c deleted file mode 100644 index ce6a780f..00000000 --- a/src/map/mapper/mapperSuper.c +++ /dev/null @@ -1,449 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperSuper.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperSuper.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Map_LibraryReadFile( Map_SuperLib_t * pLib, FILE * pFile ); -static Map_Super_t * Map_LibraryReadGate( Map_SuperLib_t * pLib, char * pBuffer, int nVars ); -static int Map_LibraryTruthVerify( Map_SuperLib_t * pLib, Map_Super_t * pGate ); -static void Map_LibraryComputeTruth( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthRes[] ); -static void Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthsIn[][2], unsigned uTruthRes[] ); -static void Map_LibraryPrintClasses( Map_SuperLib_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the supergate library from file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_LibraryRead( Map_SuperLib_t * pLib, char * pFileName ) -{ - FILE * pFile; - int Status; - // read the beginning of the file - assert( pLib->pGenlib == NULL ); - pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - printf( "Cannot open input file \"%s\".\n", pFileName ); - return 0; - } - Status = Map_LibraryReadFile( pLib, pFile ); - fclose( pFile ); -// Map_LibraryPrintClasses( pLib ); - return Status; -} - - -/**Function************************************************************* - - Synopsis [Reads the library file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_LibraryReadFile( Map_SuperLib_t * pLib, FILE * pFile ) -{ - ProgressBar * pProgress; - char pBuffer[2000]; - FILE * pFileGen; - Map_Super_t * pGate; - char * pTemp, * pLibName; - int nCounter, nGatesTotal; - unsigned uCanon[2]; - - // skip empty and comment lines - while ( fgets( pBuffer, 5000, pFile ) != NULL ) - { - // skip leading spaces - for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); - // skip comment lines and empty lines - if ( *pTemp != 0 && *pTemp != '#' ) - break; - } - - // get the genlib file name - pLibName = strtok( pTemp, " \t\r\n" ); - if ( strcmp( pLibName, "GATE" ) == 0 ) - { - printf( "The input file \"%s\" looks like a GENLIB file and not a supergate library file.\n", pLib->pName ); - return 0; - } - pFileGen = fopen( pLibName, "r" ); - if ( pFileGen == NULL ) - { - printf( "Cannot open the GENLIB file \"%s\".\n", pLibName ); - return 0; - } - fclose( pFileGen ); - - // read the genlib library - pLib->pGenlib = Mio_LibraryRead( Abc_FrameGetGlobalFrame(), pLibName, 0, 0 ); - if ( pLib->pGenlib == NULL ) - { - printf( "Cannot read GENLIB file \"%s\".\n", pLibName ); - return 0; - } - - // read the number of variables - fscanf( pFile, "%d\n", &pLib->nVarsMax ); - if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 ) - { - printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax ); - return 0; - } - - // read the number of gates - fscanf( pFile, "%d\n", &nGatesTotal ); - if ( nGatesTotal < 1 || nGatesTotal > 10000000 ) - { - printf( "Suspicious number of gates (%d).\n", nGatesTotal ); - return 0; - } - - // read the lines - nCounter = 0; - pProgress = Extra_ProgressBarStart( stdout, nGatesTotal ); - while ( fgets( pBuffer, 5000, pFile ) != NULL ) - { - for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); - if ( pTemp[0] == '\0' ) - continue; - // get the gate - pGate = Map_LibraryReadGate( pLib, pTemp, pLib->nVarsMax ); - assert( pGate->Num == nCounter + 1 ); - // count the number of parantheses in the formula - this is the number of gates - for ( pTemp = pGate->pFormula; *pTemp; pTemp++ ) - pGate->nGates += (*pTemp == '('); - // verify the truth table - assert( Map_LibraryTruthVerify(pLib, pGate) ); - - // find the N-canonical form of this supergate - pGate->nPhases = Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, pLib->nVarsMax, pGate->uTruth, pGate->uPhases, uCanon ); - // add the supergate into the table by its N-canonical table - Map_SuperTableInsertC( pLib->tTableC, uCanon, pGate ); - // update the progress bar - Extra_ProgressBarUpdate( pProgress, ++nCounter, NULL ); - } - Extra_ProgressBarStop( pProgress ); - pLib->nSupersAll = nCounter; - if ( nCounter != nGatesTotal ) - printf( "The number of gates read (%d) is different what the file says (%d).\n", nGatesTotal, nCounter ); - return 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Super_t * Map_LibraryReadGate( Map_SuperLib_t * pLib, char * pBuffer, int nVars ) -{ - Map_Super_t * pGate; - char * pTemp; - int i; - - // start and clean the gate - pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); - memset( pGate, 0, sizeof(Map_Super_t) ); - - // read the number - pTemp = strtok( pBuffer, " " ); - pGate->Num = atoi(pTemp); - - // read the signature - pTemp = strtok( NULL, " " ); - if ( pLib->nVarsMax < 6 ) - { - pGate->uTruth[0] = Extra_ReadBinary(pTemp); - pGate->uTruth[1] = 0; - } - else - { - pGate->uTruth[0] = Extra_ReadBinary(pTemp+32); - pTemp[32] = 0; - pGate->uTruth[1] = Extra_ReadBinary(pTemp); - } - - // read the max delay - pTemp = strtok( NULL, " " ); - pGate->tDelayMax.Rise = (float)atof(pTemp); - pGate->tDelayMax.Fall = pGate->tDelayMax.Rise; - - // read the pin-to-pin delay - for ( i = 0; i < nVars; i++ ) - { - pTemp = strtok( NULL, " " ); - pGate->tDelaysR[i].Rise = (float)atof(pTemp); - pGate->tDelaysF[i].Fall = pGate->tDelaysR[i].Rise; - } - - // read the area - pTemp = strtok( NULL, " " ); - pGate->Area = (float)atof(pTemp); - - // the rest is the gate name - pTemp = strtok( NULL, " \r\n" ); - if ( strlen(pTemp) == 0 ) - printf( "A gate name is empty.\n" ); - - // save the gate name - pGate->pFormula = Extra_MmFlexEntryFetch( pLib->mmForms, strlen(pTemp) + 1 ); - strcpy( pGate->pFormula, pTemp ); - - // the rest is the gate name - pTemp = strtok( NULL, " \n\0" ); - if ( pTemp != NULL ) - printf( "The following trailing symbols found \"%s\".\n", pTemp ); - return pGate; -} - -/**Function************************************************************* - - Synopsis [Performs one step of parsing the formula into parts.] - - Description [This function will eventually be replaced when the - tree-supergate library representation will become standard.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Map_LibraryReadFormulaStep( char * pFormula, char * pStrings[], int * pnStrings ) -{ - char * pName, * pPar1, * pPar2, * pCur; - int nStrings, CountPars; - - // skip leading spaces - for ( pName = pFormula; *pName && *pName == ' '; pName++ ); - assert( *pName ); - // find the first opening paranthesis - for ( pPar1 = pName; *pPar1 && *pPar1 != '('; pPar1++ ); - if ( *pPar1 == 0 ) - { - *pnStrings = 0; - return pName; - } - // overwrite it with space - assert( *pPar1 == '(' ); - *pPar1 = 0; - // find the corresponding closing paranthesis - for ( CountPars = 1, pPar2 = pPar1 + 1; *pPar2 && CountPars; pPar2++ ) - if ( *pPar2 == '(' ) - CountPars++; - else if ( *pPar2 == ')' ) - CountPars--; - pPar2--; - assert( CountPars == 0 ); - // overwrite it with space - assert( *pPar2 == ')' ); - *pPar2 = 0; - // save the intervals between the commas - nStrings = 0; - pCur = pPar1 + 1; - while ( 1 ) - { - // save the current string - pStrings[ nStrings++ ] = pCur; - // find the beginning of the next string - for ( CountPars = 0; *pCur && (CountPars || *pCur != ','); pCur++ ) - if ( *pCur == '(' ) - CountPars++; - else if ( *pCur == ')' ) - CountPars--; - if ( *pCur == 0 ) - break; - assert( *pCur == ',' ); - *pCur = 0; - pCur++; - } - // save the results and return - *pnStrings = nStrings; - return pName; -} - - -/**Function************************************************************* - - Synopsis [Verifies the truth table of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_LibraryTruthVerify( Map_SuperLib_t * pLib, Map_Super_t * pGate ) -{ - unsigned uTruthRes[2]; - Map_LibraryComputeTruth( pLib, pGate->pFormula, uTruthRes ); - if ( uTruthRes[0] != pGate->uTruth[0] || uTruthRes[1] != pGate->uTruth[1] ) - return 0; - return 1; -} - - -/**Function************************************************************* - - Synopsis [Derives the functionality of the supergate.] - - Description [This procedure is useful for verification the supergate - library. The truth table derived by this procedure should be the same - as the one contained in the original supergate file.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_LibraryComputeTruth( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthRes[] ) -{ - char Buffer[1000]; - strcpy( Buffer, pFormula ); - Map_LibraryComputeTruth_rec( pLib, Buffer, pLib->uTruths, uTruthRes ); -} - -/**Function************************************************************* - - Synopsis [Derives the functionality of the supergate.] - - Description [This procedure is useful for verification the supergate - library. The truth table derived by this procedure should be the same - as the one contained in the original supergate file.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_LibraryComputeTruth_rec( Map_SuperLib_t * pLib, char * pFormula, unsigned uTruthsIn[][2], unsigned uTruthRes[] ) -{ - Mio_Gate_t * pMioGate; - char * pGateName, * pStrings[6]; - unsigned uTruthsFanins[6][2]; - int nStrings, i; - - // perform one step parsing of the formula - // detect the root gate name, the next-step strings, and their number - pGateName = Map_LibraryReadFormulaStep( pFormula, pStrings, &nStrings ); - if ( nStrings == 0 ) // elementary variable - { - assert( pGateName[0] - 'a' < pLib->nVarsMax ); - uTruthRes[0] = uTruthsIn[pGateName[0] - 'a'][0]; - uTruthRes[1] = uTruthsIn[pGateName[0] - 'a'][1]; - return; - } - // derive the functionality of the fanins - for ( i = 0; i < nStrings; i++ ) - Map_LibraryComputeTruth_rec( pLib, pStrings[i], uTruthsIn, uTruthsFanins[i] ); - // get the root supergate - pMioGate = Mio_LibraryReadGateByName( pLib->pGenlib, pGateName ); - if ( pMioGate == NULL ) - printf( "A supergate contains gate \"%s\" that is not in \"%s\".\n", pGateName, Mio_LibraryReadName(pLib->pGenlib) ); - // derive the functionality of the output of the supergate - Mio_DeriveTruthTable( pMioGate, uTruthsFanins, nStrings, pLib->nVarsMax, uTruthRes ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_LibraryPrintSupergate( Map_Super_t * pGate ) -{ - printf( "%5d : ", pGate->nUsed ); - printf( "%5d ", pGate->Num ); - printf( "A = %5.2f ", pGate->Area ); - printf( "D = %5.2f ", pGate->tDelayMax ); - printf( "%s", pGate->pFormula ); - printf( "\n" ); -} - - -/**Function************************************************************* - - Synopsis [Prints N-classes of supergates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_LibraryPrintClasses( Map_SuperLib_t * p ) -{ -/* - st_generator * gen; - Map_Super_t * pSuper, * pSuper2; - unsigned Key, uTruth; - int Counter = 0; - // copy all the supergates into one array - st_foreach_item( p->tSuplib, gen, (char **)&Key, (char **)&pSuper ) - { - for ( pSuper2 = pSuper; pSuper2; pSuper2 = pSuper2->pNext ) - { - uTruth = pSuper2->Phase; - Extra_PrintBinary( stdout, &uTruth, 5 ); - printf( " %5d ", pSuper2->Num ); - printf( "%s", pSuper2->pFormula ); - printf( "\n" ); - } - printf( "\n" ); - if ( ++ Counter == 100 ) - break; - } -*/ -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperSwitch.c b/src/map/mapper/mapperSwitch.c deleted file mode 100644 index 9dd6e42b..00000000 --- a/src/map/mapper/mapperSwitch.c +++ /dev/null @@ -1,223 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperSwitch.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: mapperSwitch.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_SwitchCutGetDerefed( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) -{ - float aResult, aResult2; -// assert( pNode->Switching > 0 ); - aResult2 = Map_SwitchCutRefDeref( pNode, pCut, fPhase, 1 ); // reference - aResult = Map_SwitchCutRefDeref( pNode, pCut, fPhase, 0 ); // dereference -// assert( aResult == aResult2 ); - return aResult; -} - -/**function************************************************************* - - synopsis [References the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_SwitchCutRef( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) -{ - return Map_SwitchCutRefDeref( pNode, pCut, fPhase, 1 ); // reference -} - -/**function************************************************************* - - synopsis [References the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_SwitchCutDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase ) -{ - return Map_SwitchCutRefDeref( pNode, pCut, fPhase, 0 ); // dereference -} - -/**function************************************************************* - - synopsis [References or dereferences the cut.] - - description [This reference part is similar to Cudd_NodeReclaim(). - The dereference part is similar to Cudd_RecursiveDeref().] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_SwitchCutRefDeref( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, int fReference ) -{ - Map_Node_t * pNodeChild; - Map_Cut_t * pCutChild; - float aSwitchActivity; - int i, fPhaseChild; - - // start switching activity for the node - aSwitchActivity = pNode->Switching; - // consider the elementary variable - if ( pCut->nLeaves == 1 ) - return aSwitchActivity; - - // go through the children - assert( pCut->M[fPhase].pSuperBest ); - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pNodeChild = pCut->ppLeaves[i]; - fPhaseChild = Map_CutGetLeafPhase( pCut, fPhase, i ); - // get the reference counter of the child - - if ( fReference ) - { - if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present - { - // if this phase of the node is referenced, there is no recursive call - pNodeChild->nRefAct[2]++; - if ( pNodeChild->nRefAct[fPhaseChild]++ > 0 ) - continue; - } - else // only one phase is present - { - // inverter should be added if the phase - // (a) has no reference and (b) is implemented using other phase - if ( pNodeChild->nRefAct[fPhaseChild]++ == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) - aSwitchActivity += pNodeChild->Switching; // inverter switches the same as the node - // if the node is referenced, there is no recursive call - if ( pNodeChild->nRefAct[2]++ > 0 ) - continue; - } - } - else - { - if ( pNodeChild->pCutBest[0] && pNodeChild->pCutBest[1] ) // both phases are present - { - // if this phase of the node is referenced, there is no recursive call - --pNodeChild->nRefAct[2]; - if ( --pNodeChild->nRefAct[fPhaseChild] > 0 ) - continue; - } - else // only one phase is present - { - // inverter should be added if the phase - // (a) has no reference and (b) is implemented using other phase - if ( --pNodeChild->nRefAct[fPhaseChild] == 0 && pNodeChild->pCutBest[fPhaseChild] == NULL ) - aSwitchActivity += pNodeChild->Switching; // inverter switches the same as the node - // if the node is referenced, there is no recursive call - if ( --pNodeChild->nRefAct[2] > 0 ) - continue; - } - assert( pNodeChild->nRefAct[fPhaseChild] >= 0 ); - } - - // get the child cut - pCutChild = pNodeChild->pCutBest[fPhaseChild]; - // if the child does not have this phase mapped, take the opposite phase - if ( pCutChild == NULL ) - { - fPhaseChild = !fPhaseChild; - pCutChild = pNodeChild->pCutBest[fPhaseChild]; - } - // reference and compute area recursively - aSwitchActivity += Map_SwitchCutRefDeref( pNodeChild, pCutChild, fPhaseChild, fReference ); - } - return aSwitchActivity; -} - -/**Function************************************************************* - - Synopsis [Computes the array of mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Map_MappingGetSwitching( Map_Man_t * pMan, Map_NodeVec_t * vMapping ) -{ - Map_Node_t * pNode; - float Switch; - int i; - Switch = 0.0; - for ( i = 0; i < vMapping->nSize; i++ ) - { - pNode = vMapping->pArray[i]; - // at least one phase has the best cut assigned - assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); - // at least one phase is used in the mapping - assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); - // compute the array due to the supergate - if ( Map_NodeIsAnd(pNode) ) - { - // count switching of the negative phase - if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) - Switch += pNode->Switching; - // count switching of the positive phase - if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) - Switch += pNode->Switching; - } - // count switching of the interver if we need to implement one phase with another phase - if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) || - (pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) ) - Switch += pNode->Switching; // inverter switches the same as the node - } - // add buffers for each CO driven by a CI - for ( i = 0; i < pMan->nOutputs; i++ ) - if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) ) - Switch += pMan->pOutputs[i]->Switching; - return Switch; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperTable.c b/src/map/mapper/mapperTable.c deleted file mode 100644 index d0cb7a01..00000000 --- a/src/map/mapper/mapperTable.c +++ /dev/null @@ -1,402 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperTable.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperTable.c,v 1.6 2005/01/23 06:59:44 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the table function for the tables -#define MAP_TABLE_HASH(u1,u2,nSize) (((u1) + 2003 * (u2)) % nSize) - -static void Map_SuperTableResize( Map_HashTable_t * pLib ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the hash table for supergates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_HashTable_t * Map_SuperTableCreate( Map_SuperLib_t * pLib ) -{ - Map_HashTable_t * p; - // allocate the table - p = ALLOC( Map_HashTable_t, 1 ); - memset( p, 0, sizeof(Map_HashTable_t) ); - p->mmMan = pLib->mmEntries; - // allocate and clean the bins - p->nBins = Cudd_Prime(20000); - p->pBins = ALLOC( Map_HashEntry_t *, p->nBins ); - memset( p->pBins, 0, sizeof(Map_HashEntry_t *) * p->nBins ); - return p; -} - - -/**Function************************************************************* - - Synopsis [Deallocates the supergate hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_SuperTableFree( Map_HashTable_t * p ) -{ - FREE( p->pBins ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Inserts a new entry into the hash table.] - - Description [This function inserts the new gate (pGate), which will be - accessible through its canonical form (uTruthC).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_SuperTableInsertC( Map_HashTable_t * p, unsigned uTruthC[], Map_Super_t * pGate ) -{ - Map_HashEntry_t * pEnt; - unsigned Key; - // resize the table - if ( p->nEntries >= 2 * p->nBins ) - Map_SuperTableResize( p ); - // check if another supergate with the same canonical form exists - Key = MAP_TABLE_HASH( uTruthC[0], uTruthC[1], p->nBins ); - for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext ) - if ( pEnt->uTruth[0] == uTruthC[0] && pEnt->uTruth[1] == uTruthC[1] ) - break; - // create a new entry if it does not exist - if ( pEnt == NULL ) - { - // add the new entry to the table - pEnt = (Map_HashEntry_t *)Extra_MmFixedEntryFetch( p->mmMan ); - memset( pEnt, 0, sizeof(Map_HashEntry_t) ); - pEnt->uTruth[0] = uTruthC[0]; - pEnt->uTruth[1] = uTruthC[1]; - // add the hash table entry to the corresponding linked list in the table - pEnt->pNext = p->pBins[Key]; - p->pBins[Key] = pEnt; - p->nEntries++; - } - // add the supergate to the entry - pGate->pNext = pEnt->pGates; - pEnt->pGates = pGate; - return 0; -} - - - -/**Function************************************************************* - - Synopsis [Inserts a new entry into the library.] - - Description [This function inserts the new gate (pGate), which will be - accessible through its unfolded function (uTruth).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_SuperTableInsert( Map_HashTable_t * p, unsigned uTruth[], Map_Super_t * pGate, unsigned uPhase ) -{ - Map_HashEntry_t * pEnt; - unsigned Key; - // resize the table - if ( p->nEntries >= 2 * p->nBins ) - Map_SuperTableResize( p ); - // check if this entry already exists - Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->nBins ); - for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext ) - if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] ) - return 1; - // add the new hash table entry to the table - pEnt = (Map_HashEntry_t *)Extra_MmFixedEntryFetch( p->mmMan ); - memset( pEnt, 0, sizeof(Map_HashEntry_t) ); - pEnt->uTruth[0] = uTruth[0]; - pEnt->uTruth[1] = uTruth[1]; - pEnt->pGates = pGate; - pEnt->uPhase = uPhase; - // add the hash table to the corresponding linked list in the table - pEnt->pNext = p->pBins[Key]; - p->pBins[Key] = pEnt; - p->nEntries++; -/* -printf( "Adding gate: %10u ", Key ); -Map_LibraryPrintSupergate( pGate ); -Extra_PrintBinary( stdout, uTruth, 32 ); -printf( "\n" ); -*/ - return 0; -} - -/**Function************************************************************* - - Synopsis [Looks up an entry in the library.] - - Description [This function looks up the function, given by its truth table, - and return two things: (1) the linked list of supergates, which can implement - the functions of this N-class; (2) the phase, which should be applied to the - given function, in order to derive the canonical form of this N-class.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Super_t * Map_SuperTableLookupC( Map_SuperLib_t * p, unsigned uTruth[] ) -{ - Map_HashEntry_t * pEnt; - unsigned Key; - Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->tTableC->nBins ); - for ( pEnt = p->tTableC->pBins[Key]; pEnt; pEnt = pEnt->pNext ) - if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] ) - return pEnt->pGates; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Looks up an entry in the library.] - - Description [This function looks up the function, given by its truth table, - and return two things: (1) the linked list of supergates, which can implement - the functions of this N-class; (2) the phase, which should be applied to the - given function, in order to derive the canonical form of this N-class.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Super_t * Map_SuperTableLookup( Map_HashTable_t * p, unsigned uTruth[], unsigned * puPhase ) -{ - Map_HashEntry_t * pEnt; - unsigned Key; - Key = MAP_TABLE_HASH( uTruth[0], uTruth[1], p->nBins ); - for ( pEnt = p->pBins[Key]; pEnt; pEnt = pEnt->pNext ) - if ( pEnt->uTruth[0] == uTruth[0] && pEnt->uTruth[1] == uTruth[1] ) - { - *puPhase = pEnt->uPhase; - return pEnt->pGates; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_SuperTableResize( Map_HashTable_t * p ) -{ - Map_HashEntry_t ** pBinsNew; - Map_HashEntry_t * pEnt, * pEnt2; - int nBinsNew, Counter, i, clk = clock(); - unsigned Key; - // get the new table size - nBinsNew = Cudd_Prime(2 * p->nBins); - // allocate a new array - pBinsNew = ALLOC( Map_HashEntry_t *, nBinsNew ); - memset( pBinsNew, 0, sizeof(Map_HashEntry_t *) * nBinsNew ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < p->nBins; i++ ) - for ( pEnt = p->pBins[i], pEnt2 = pEnt? pEnt->pNext: NULL; pEnt; - pEnt = pEnt2, pEnt2 = pEnt? pEnt->pNext: NULL ) - { - Key = MAP_TABLE_HASH( pEnt->uTruth[0], pEnt->uTruth[1], nBinsNew ); - pEnt->pNext = pBinsNew[Key]; - pBinsNew[Key] = pEnt; - Counter++; - } - assert( Counter == p->nEntries ); - // replace the table and the parameters - free( p->pBins ); - p->pBins = pBinsNew; - p->nBins = nBinsNew; -} - -/**Function************************************************************* - - Synopsis [Compares the supergates by the number of times they are used.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_SuperTableCompareSupergates( Map_Super_t ** ppS1, Map_Super_t ** ppS2 ) -{ - if ( (*ppS1)->nUsed > (*ppS2)->nUsed ) - return -1; - if ( (*ppS1)->nUsed < (*ppS2)->nUsed ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Compares the supergates by the number of times they are used.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_SuperTableCompareGatesInList( Map_Super_t ** ppS1, Map_Super_t ** ppS2 ) -{ -// if ( (*ppS1)->tDelayMax.Rise > (*ppS2)->tDelayMax.Rise ) - if ( (*ppS1)->Area > (*ppS2)->Area ) - return -1; -// if ( (*ppS1)->tDelayMax.Rise < (*ppS2)->tDelayMax.Rise ) - if ( (*ppS1)->Area < (*ppS2)->Area ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Sorts supergates by usefulness and prints out most useful.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_SuperTableSortSupergates( Map_HashTable_t * p, int nSupersMax ) -{ - Map_HashEntry_t * pEnt; - Map_Super_t ** ppSupers; - Map_Super_t * pSuper; - int nSupers, i; - - // copy all the supergates into one array - ppSupers = ALLOC( Map_Super_t *, nSupersMax ); - nSupers = 0; - for ( i = 0; i < p->nBins; i++ ) - for ( pEnt = p->pBins[i]; pEnt; pEnt = pEnt->pNext ) - for ( pSuper = pEnt->pGates; pSuper; pSuper = pSuper->pNext ) - ppSupers[nSupers++] = pSuper; - - // sort by usage - qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *), - (int (*)(const void *, const void *)) Map_SuperTableCompareSupergates ); - assert( Map_SuperTableCompareSupergates( ppSupers, ppSupers + nSupers - 1 ) <= 0 ); - - // print out the "top ten" -// for ( i = 0; i < nSupers; i++ ) - for ( i = 0; i < 10; i++ ) - { - if ( ppSupers[i]->nUsed == 0 ) - break; - printf( "%5d : ", ppSupers[i]->nUsed ); - printf( "%5d ", ppSupers[i]->Num ); - printf( "A = %5.2f ", ppSupers[i]->Area ); - printf( "D = %5.2f ", ppSupers[i]->tDelayMax.Rise ); - printf( "%s", ppSupers[i]->pFormula ); - printf( "\n" ); - } - free( ppSupers ); -} - -/**Function************************************************************* - - Synopsis [Sorts supergates by max delay for each truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_SuperTableSortSupergatesByDelay( Map_HashTable_t * p, int nSupersMax ) -{ - Map_HashEntry_t * pEnt; - Map_Super_t ** ppSupers; - Map_Super_t * pSuper; - int nSupers, i, k; - - ppSupers = ALLOC( Map_Super_t *, nSupersMax ); - for ( i = 0; i < p->nBins; i++ ) - for ( pEnt = p->pBins[i]; pEnt; pEnt = pEnt->pNext ) - { - // collect the gates in this entry - nSupers = 0; - for ( pSuper = pEnt->pGates; pSuper; pSuper = pSuper->pNext ) - { - // skip supergates, whose root is the AND gate -// if ( strcmp( Mio_GateReadName(pSuper->pRoot), "and" ) == 0 ) -// continue; - ppSupers[nSupers++] = pSuper; - } - pEnt->pGates = NULL; - if ( nSupers == 0 ) - continue; - // sort the gates by delay - qsort( (void *)ppSupers, nSupers, sizeof(Map_Super_t *), - (int (*)(const void *, const void *)) Map_SuperTableCompareGatesInList ); - assert( Map_SuperTableCompareGatesInList( ppSupers, ppSupers + nSupers - 1 ) <= 0 ); - // link them in the reverse order - for ( k = 0; k < nSupers; k++ ) - { - ppSupers[k]->pNext = pEnt->pGates; - pEnt->pGates = ppSupers[k]; - } - // save the number of supergates in the list - pEnt->pGates->nSupers = nSupers; - } - FREE( ppSupers ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperTime.c b/src/map/mapper/mapperTime.c deleted file mode 100644 index cc4173cf..00000000 --- a/src/map/mapper/mapperTime.c +++ /dev/null @@ -1,510 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperTime.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperTime.c,v 1.3 2005/03/02 02:35:54 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Map_TimePropagateRequired( Map_Man_t * p, Map_NodeVec_t * vNodes ); -static void Map_TimePropagateRequiredPhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase ); -static float Map_MatchComputeReqTimes( Map_Cut_t * pCut, int fPhase, Map_Time_t * ptArrRes ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**function************************************************************* - - synopsis [Computes the exact area associated with the cut.] - - description [] - - sideeffects [] - - seealso [] - -***********************************************************************/ -float Map_TimeMatchWithInverter( Map_Man_t * p, Map_Match_t * pMatch ) -{ - Map_Time_t tArrInv; - tArrInv.Fall = pMatch->tArrive.Rise + p->pSuperLib->tDelayInv.Fall; - tArrInv.Rise = pMatch->tArrive.Fall + p->pSuperLib->tDelayInv.Rise; - tArrInv.Worst = MAP_MAX( tArrInv.Rise, tArrInv.Fall ); - return tArrInv.Worst; -} - -/**Function************************************************************* - - Synopsis [Computes the arrival times of the cut recursively.] - - Description [When computing the arrival time for the previously unused - cuts, their arrival time may be incorrect because their fanins have - incorrect arrival time. This procedure is called to fix this problem.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_TimeCutComputeArrival_rec( Map_Cut_t * pCut, int fPhase ) -{ - int i, fPhaseLeaf; - for ( i = 0; i < pCut->nLeaves; i++ ) - { - fPhaseLeaf = Map_CutGetLeafPhase( pCut, fPhase, i ); - if ( pCut->ppLeaves[i]->nRefAct[fPhaseLeaf] > 0 ) - continue; - Map_TimeCutComputeArrival_rec( pCut->ppLeaves[i]->pCutBest[fPhaseLeaf], fPhaseLeaf ); - } - Map_TimeCutComputeArrival( NULL, pCut, fPhase, MAP_FLOAT_LARGE ); -} - -/**Function************************************************************* - - Synopsis [Computes the arrival times of the cut.] - - Description [Computes the arrival times of the cut if it is implemented using - the given supergate with the given phase. Uses the constraint-type specification - of rise/fall arrival times.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Map_TimeCutComputeArrival( Map_Node_t * pNode, Map_Cut_t * pCut, int fPhase, float tWorstLimit ) -{ - Map_Match_t * pM = pCut->M + fPhase; - Map_Super_t * pSuper = pM->pSuperBest; - unsigned uPhaseTot = pM->uPhaseBest; - Map_Time_t * ptArrRes = &pM->tArrive; - Map_Time_t * ptArrIn; - bool fPinPhase; - float tDelay; - int i; - - ptArrRes->Rise = ptArrRes->Fall = 0.0; - ptArrRes->Worst = MAP_FLOAT_LARGE; - for ( i = pCut->nLeaves - 1; i >= 0; i-- ) - { - // get the phase of the given pin - fPinPhase = ((uPhaseTot & (1 << i)) == 0); - ptArrIn = pCut->ppLeaves[i]->tArrival + fPinPhase; - - // get the rise of the output due to rise of the inputs - if ( pSuper->tDelaysR[i].Rise > 0 ) - { - tDelay = ptArrIn->Rise + pSuper->tDelaysR[i].Rise; - if ( tDelay > tWorstLimit ) - return MAP_FLOAT_LARGE; - if ( ptArrRes->Rise < tDelay ) - ptArrRes->Rise = tDelay; - } - - // get the rise of the output due to fall of the inputs - if ( pSuper->tDelaysR[i].Fall > 0 ) - { - tDelay = ptArrIn->Fall + pSuper->tDelaysR[i].Fall; - if ( tDelay > tWorstLimit ) - return MAP_FLOAT_LARGE; - if ( ptArrRes->Rise < tDelay ) - ptArrRes->Rise = tDelay; - } - - // get the fall of the output due to rise of the inputs - if ( pSuper->tDelaysF[i].Rise > 0 ) - { - tDelay = ptArrIn->Rise + pSuper->tDelaysF[i].Rise; - if ( tDelay > tWorstLimit ) - return MAP_FLOAT_LARGE; - if ( ptArrRes->Fall < tDelay ) - ptArrRes->Fall = tDelay; - } - - // get the fall of the output due to fall of the inputs - if ( pSuper->tDelaysF[i].Fall > 0 ) - { - tDelay = ptArrIn->Fall + pSuper->tDelaysF[i].Fall; - if ( tDelay > tWorstLimit ) - return MAP_FLOAT_LARGE; - if ( ptArrRes->Fall < tDelay ) - ptArrRes->Fall = tDelay; - } - } - // return the worst-case of rise/fall arrival times - ptArrRes->Worst = MAP_MAX(ptArrRes->Rise, ptArrRes->Fall); - return ptArrRes->Worst; -} - - -/**Function************************************************************* - - Synopsis [Computes the maximum arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Map_TimeComputeArrivalMax( Map_Man_t * p ) -{ - float tReqMax, tReq; - int i, fPhase; - // get the critical PO arrival time - tReqMax = -MAP_FLOAT_LARGE; - for ( i = 0; i < p->nOutputs; i++ ) - { - if ( Map_NodeIsConst(p->pOutputs[i]) ) - continue; - fPhase = !Map_IsComplement(p->pOutputs[i]); - tReq = Map_Regular(p->pOutputs[i])->tArrival[fPhase].Worst; - tReqMax = MAP_MAX( tReqMax, tReq ); - } - return tReqMax; -} - -/**Function************************************************************* - - Synopsis [Computes the required times of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_TimeComputeRequiredGlobal( Map_Man_t * p ) -{ - p->fRequiredGlo = Map_TimeComputeArrivalMax( p ); - // update the required times according to the target - if ( p->DelayTarget != -1 ) - { - if ( p->fRequiredGlo > p->DelayTarget + p->fEpsilon ) - { - if ( p->fMappingMode == 1 ) - printf( "Cannot meet the target required times (%4.2f). Continue anyway.\n", p->DelayTarget ); - } - else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon ) - { - if ( p->fMappingMode == 1 ) - printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget ); - p->fRequiredGlo = p->DelayTarget; - } - } - Map_TimeComputeRequired( p, p->fRequiredGlo ); -} - -/**Function************************************************************* - - Synopsis [Computes the required times of all nodes.] - - Description [This procedure assumes that the nodes used in the mapping - are collected in p->vMapping.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_TimeComputeRequired( Map_Man_t * p, float fRequired ) -{ - Map_Time_t * ptTime; - int fPhase, i; - - // clean the required times - for ( i = 0; i < p->vAnds->nSize; i++ ) - { - p->vAnds->pArray[i]->tRequired[0].Rise = MAP_FLOAT_LARGE; - p->vAnds->pArray[i]->tRequired[0].Fall = MAP_FLOAT_LARGE; - p->vAnds->pArray[i]->tRequired[0].Worst = MAP_FLOAT_LARGE; - p->vAnds->pArray[i]->tRequired[1].Rise = MAP_FLOAT_LARGE; - p->vAnds->pArray[i]->tRequired[1].Fall = MAP_FLOAT_LARGE; - p->vAnds->pArray[i]->tRequired[1].Worst = MAP_FLOAT_LARGE; - } - - // set the required times for the POs - for ( i = 0; i < p->nOutputs; i++ ) - { - fPhase = !Map_IsComplement(p->pOutputs[i]); - ptTime = Map_Regular(p->pOutputs[i])->tRequired + fPhase; - ptTime->Rise = ptTime->Fall = ptTime->Worst = fRequired; - } - - // sorts the nodes in the decreasing order of levels - // this puts the nodes in reverse topological order -// Map_MappingSortByLevel( p, p->vMapping ); - // the array is already sorted by construction in Map_MappingSetRefs() - - Map_TimePropagateRequired( p, p->vMapping ); -} - -/**Function************************************************************* - - Synopsis [Computes the required times of the given nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_TimePropagateRequired( Map_Man_t * p, Map_NodeVec_t * vNodes ) -{ - Map_Node_t * pNode; - Map_Time_t tReqOutTest, * ptReqOutTest = &tReqOutTest; - Map_Time_t * ptReqIn, * ptReqOut; - int fPhase, k; - - // go through the nodes in the reverse topological order - for ( k = 0; k < vNodes->nSize; k++ ) - { - pNode = vNodes->pArray[k]; - - // this computation works for regular nodes only - assert( !Map_IsComplement(pNode) ); - // at least one phase should be mapped - assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); - // the node should be used in the currently assigned mapping - assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); - - // if one of the cuts is not given, project the required times from the other cut - if ( pNode->pCutBest[0] == NULL || pNode->pCutBest[1] == NULL ) - { -// assert( 0 ); - // get the missing phase - fPhase = (pNode->pCutBest[1] == NULL); - // check if the missing phase is needed in the mapping - if ( pNode->nRefAct[fPhase] > 0 ) - { - // get the pointers to the required times of the missing phase - ptReqOut = pNode->tRequired + fPhase; -// assert( ptReqOut->Fall < MAP_FLOAT_LARGE ); - // get the pointers to the required times of the present phase - ptReqIn = pNode->tRequired + !fPhase; - // propagate the required times from the missing phase to the present phase - // tArrInv.Fall = pMatch->tArrive.Rise + p->pSuperLib->tDelayInv.Fall; - // tArrInv.Rise = pMatch->tArrive.Fall + p->pSuperLib->tDelayInv.Rise; - ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, ptReqOut->Rise - p->pSuperLib->tDelayInv.Rise ); - ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, ptReqOut->Fall - p->pSuperLib->tDelayInv.Fall ); - } - } - - // finalize the worst case computation - pNode->tRequired[0].Worst = MAP_MIN( pNode->tRequired[0].Fall, pNode->tRequired[0].Rise ); - pNode->tRequired[1].Worst = MAP_MIN( pNode->tRequired[1].Fall, pNode->tRequired[1].Rise ); - - // skip the PIs - if ( !Map_NodeIsAnd(pNode) ) - continue; - - // propagate required times of different phases of the node - // the ordering of phases does not matter since they are mapped independently - if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE ) - Map_TimePropagateRequiredPhase( p, pNode, 0 ); - if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE ) - Map_TimePropagateRequiredPhase( p, pNode, 1 ); - } - - // in the end, we verify the required times - // for this, we compute the arrival times of the outputs of each phase - // of the supergates using the fanins' required times as the fanins' arrival times - // the resulting arrival time of the supergate should be less than the actual required time - for ( k = 0; k < vNodes->nSize; k++ ) - { - pNode = vNodes->pArray[k]; - if ( !Map_NodeIsAnd(pNode) ) - continue; - // verify that the required times are propagated correctly -// if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) - if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE ) - { - Map_MatchComputeReqTimes( pNode->pCutBest[0], 0, ptReqOutTest ); - assert( ptReqOutTest->Rise < pNode->tRequired[0].Rise + p->fEpsilon ); - assert( ptReqOutTest->Fall < pNode->tRequired[0].Fall + p->fEpsilon ); - } -// if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) - if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE ) - { - Map_MatchComputeReqTimes( pNode->pCutBest[1], 1, ptReqOutTest ); - assert( ptReqOutTest->Rise < pNode->tRequired[1].Rise + p->fEpsilon ); - assert( ptReqOutTest->Fall < pNode->tRequired[1].Fall + p->fEpsilon ); - } - } - -} - -/**Function************************************************************* - - Synopsis [Computes the required times of the given nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_TimePropagateRequiredPhase( Map_Man_t * p, Map_Node_t * pNode, int fPhase ) -{ - Map_Time_t * ptReqIn, * ptReqOut; - Map_Cut_t * pCut; - Map_Super_t * pSuper; - float tNewReqTime; - unsigned uPhase; - int fPinPhase, i; - - // get the cut to be propagated - pCut = pNode->pCutBest[fPhase]; - assert( pCut != NULL ); - // get the supergate and its polarity - pSuper = pCut->M[fPhase].pSuperBest; - uPhase = pCut->M[fPhase].uPhaseBest; - // get the required time of the output of the supergate - ptReqOut = pNode->tRequired + fPhase; - // set the required time of the children - for ( i = 0; i < pCut->nLeaves; i++ ) - { - // get the phase of the given pin of the supergate - fPinPhase = ((uPhase & (1 << i)) == 0); - ptReqIn = pCut->ppLeaves[i]->tRequired + fPinPhase; - assert( pCut->ppLeaves[i]->nRefAct[2] > 0 ); - - // get the rise of the output due to rise of the inputs -// if ( ptArrOut->Rise < ptArrIn->Rise + pSuper->tDelaysR[i].Rise ) -// ptArrOut->Rise = ptArrIn->Rise + pSuper->tDelaysR[i].Rise; - if ( pSuper->tDelaysR[i].Rise > 0 ) - { - tNewReqTime = ptReqOut->Rise - pSuper->tDelaysR[i].Rise; - ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, tNewReqTime ); - } - - // get the rise of the output due to fall of the inputs -// if ( ptArrOut->Rise < ptArrIn->Fall + pSuper->tDelaysR[i].Fall ) -// ptArrOut->Rise = ptArrIn->Fall + pSuper->tDelaysR[i].Fall; - if ( pSuper->tDelaysR[i].Fall > 0 ) - { - tNewReqTime = ptReqOut->Rise - pSuper->tDelaysR[i].Fall; - ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, tNewReqTime ); - } - - // get the fall of the output due to rise of the inputs -// if ( ptArrOut->Fall < ptArrIn->Rise + pSuper->tDelaysF[i].Rise ) -// ptArrOut->Fall = ptArrIn->Rise + pSuper->tDelaysF[i].Rise; - if ( pSuper->tDelaysF[i].Rise > 0 ) - { - tNewReqTime = ptReqOut->Fall - pSuper->tDelaysF[i].Rise; - ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, tNewReqTime ); - } - - // get the fall of the output due to fall of the inputs -// if ( ptArrOut->Fall < ptArrIn->Fall + pSuper->tDelaysF[i].Fall ) -// ptArrOut->Fall = ptArrIn->Fall + pSuper->tDelaysF[i].Fall; - if ( pSuper->tDelaysF[i].Fall > 0 ) - { - tNewReqTime = ptReqOut->Fall - pSuper->tDelaysF[i].Fall; - ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, tNewReqTime ); - } - } - - // compare the required times with the arrival times - assert( pNode->tArrival[fPhase].Rise < ptReqOut->Rise + p->fEpsilon ); - assert( pNode->tArrival[fPhase].Fall < ptReqOut->Fall + p->fEpsilon ); -} - -/**Function************************************************************* - - Synopsis [Computes the arrival times of the cut.] - - Description [Computes the arrival times of the cut if it is implemented using - the given supergate with the given phase. Uses the constraint-type specification - of rise/fall arrival times.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Map_MatchComputeReqTimes( Map_Cut_t * pCut, int fPhase, Map_Time_t * ptArrRes ) -{ - Map_Time_t * ptArrIn; - Map_Super_t * pSuper; - unsigned uPhaseTot; - int fPinPhase, i; - float tDelay; - - // get the supergate and the phase - pSuper = pCut->M[fPhase].pSuperBest; - uPhaseTot = pCut->M[fPhase].uPhaseBest; - - // propagate the arrival times - ptArrRes->Rise = ptArrRes->Fall = -MAP_FLOAT_LARGE; - for ( i = 0; i < pCut->nLeaves; i++ ) - { - // get the phase of the given pin - fPinPhase = ((uPhaseTot & (1 << i)) == 0); - ptArrIn = pCut->ppLeaves[i]->tRequired + fPinPhase; -// assert( ptArrIn->Worst < MAP_FLOAT_LARGE ); - - // get the rise of the output due to rise of the inputs - if ( pSuper->tDelaysR[i].Rise > 0 ) - { - tDelay = ptArrIn->Rise + pSuper->tDelaysR[i].Rise; - if ( ptArrRes->Rise < tDelay ) - ptArrRes->Rise = tDelay; - } - - // get the rise of the output due to fall of the inputs - if ( pSuper->tDelaysR[i].Fall > 0 ) - { - tDelay = ptArrIn->Fall + pSuper->tDelaysR[i].Fall; - if ( ptArrRes->Rise < tDelay ) - ptArrRes->Rise = tDelay; - } - - // get the fall of the output due to rise of the inputs - if ( pSuper->tDelaysF[i].Rise > 0 ) - { - tDelay = ptArrIn->Rise + pSuper->tDelaysF[i].Rise; - if ( ptArrRes->Fall < tDelay ) - ptArrRes->Fall = tDelay; - } - - // get the fall of the output due to fall of the inputs - if ( pSuper->tDelaysF[i].Fall > 0 ) - { - tDelay = ptArrIn->Fall + pSuper->tDelaysF[i].Fall; - if ( ptArrRes->Fall < tDelay ) - ptArrRes->Fall = tDelay; - } - } - // return the worst-case of rise/fall arrival times - return MAP_MAX(ptArrRes->Rise, ptArrRes->Fall); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperTree.c b/src/map/mapper/mapperTree.c deleted file mode 100644 index ef66082d..00000000 --- a/src/map/mapper/mapperTree.c +++ /dev/null @@ -1,818 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperTree.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperTree.c,v 1.9 2005/01/23 06:59:45 alanmi Exp $] - -***********************************************************************/ - -#ifdef __linux__ -#include -#endif - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Map_LibraryReadFileTree( Map_SuperLib_t * pLib, FILE * pFile, char *pFileName ); -static Map_Super_t * Map_LibraryReadGateTree( Map_SuperLib_t * pLib, char * pBuffer, int Number, int nVars ); -static int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st_table * tExcludeGate ); -static void Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin ); -static int Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate ); -static unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate ); - -// fanout limits -extern const int s_MapFanoutLimits[10] = { 1/*0*/, 10/*1*/, 5/*2*/, 2/*3*/, 1/*4*/, 1/*5*/, 1/*6*/ }; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Reads the supergate library from file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_LibraryReadTree( Map_SuperLib_t * pLib, char * pFileName, char * pExcludeFile ) -{ - FILE * pFile; - int Status, num; - Abc_Frame_t * pAbc; - st_table * tExcludeGate = 0; - - // read the beginning of the file - assert( pLib->pGenlib == NULL ); - pFile = Io_FileOpen( pFileName, "open_path", "r", 1 ); -// pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - printf( "Cannot open input file \"%s\".\n", pFileName ); - return 0; - } - - if ( pExcludeFile ) - { - pAbc = Abc_FrameGetGlobalFrame(); - - tExcludeGate = st_init_table(strcmp, st_strhash); - if ( (num = Mio_LibraryReadExclude( pAbc, pExcludeFile, tExcludeGate )) == -1 ) - { - st_free_table( tExcludeGate ); - tExcludeGate = 0; - return 0; - } - - fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num ); - } - - Status = Map_LibraryReadFileTree( pLib, pFile, pFileName ); - fclose( pFile ); - if ( Status == 0 ) - return 0; - // prepare the info about the library - return Map_LibraryDeriveGateInfo( pLib, tExcludeGate ); -} - - -/**Function************************************************************* - - Synopsis [Reads the library file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_LibraryReadFileTree( Map_SuperLib_t * pLib, FILE * pFile, char *pFileName ) -{ - ProgressBar * pProgress; - char pBuffer[5000], pLibFile[5000]; - FILE * pFileGen; - Map_Super_t * pGate; - char * pTemp = 0, * pLibName; - int nCounter, k, i; - - // skip empty and comment lines - while ( fgets( pBuffer, 5000, pFile ) != NULL ) - { - // skip leading spaces - for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); - // skip comment lines and empty lines - if ( *pTemp != 0 && *pTemp != '#' ) - break; - } - - // get the genlib file name (base) - pLibName = strtok( pTemp, " \t\r\n" ); - - if ( strcmp( pLibName, "GATE" ) == 0 ) - { - printf( "The input file \"%s\" looks like a GENLIB file and not a supergate library file.\n", pLib->pName ); - return 0; - } - - - // now figure out the directory if any in the pFileName -#ifdef __linux__ - snprintf( pLibFile, 5000, "%s/%s", dirname(strdup(pFileName)), pLibName ); -#else - { - char * pStr; - strcpy( pLibFile, pFileName ); - pStr = pLibFile + strlen(pBuffer) - 1; - while ( pStr > pLibFile && *pStr != '\\' && *pStr != '/' ) - pStr--; - if ( pStr == pLibFile ) - strcpy( pLibFile, pLibName ); - else - sprintf( pStr, "/%s", pLibName ); - } -#endif - - pFileGen = Io_FileOpen( pLibFile, "open_path", "r", 1 ); -// pFileGen = fopen( pLibFile, "r" ); - if ( pFileGen == NULL ) - { - printf( "Cannot open the GENLIB file \"%s\".\n", pLibFile ); - return 0; - } - fclose( pFileGen ); - - // read the genlib library - pLib->pGenlib = Mio_LibraryRead( Abc_FrameGetGlobalFrame(), pLibFile, 0, 0 ); - if ( pLib->pGenlib == NULL ) - { - printf( "Cannot read GENLIB file \"%s\".\n", pLibFile ); - return 0; - } - - // read the number of variables - fscanf( pFile, "%d\n", &pLib->nVarsMax ); - if ( pLib->nVarsMax < 2 || pLib->nVarsMax > 10 ) - { - printf( "Suspicious number of variables (%d).\n", pLib->nVarsMax ); - return 0; - } - - // read the number of gates - fscanf( pFile, "%d\n", &pLib->nSupersReal ); - if ( pLib->nSupersReal < 1 || pLib->nSupersReal > 10000000 ) - { - printf( "Suspicious number of gates (%d).\n", pLib->nSupersReal ); - return 0; - } - - // read the number of lines - fscanf( pFile, "%d\n", &pLib->nLines ); - if ( pLib->nLines < 1 || pLib->nLines > 10000000 ) - { - printf( "Suspicious number of lines (%d).\n", pLib->nLines ); - return 0; - } - - // allocate room for supergate pointers - pLib->ppSupers = ALLOC( Map_Super_t *, pLib->nLines + 10000 ); - - // create the elementary supergates - for ( i = 0; i < pLib->nVarsMax; i++ ) - { - // get a new gate - pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); - memset( pGate, 0, sizeof(Map_Super_t) ); - // assign the elementary variable, the truth table, and the delays - pGate->Num = i; - // set the truth table - pGate->uTruth[0] = pLib->uTruths[i][0]; - pGate->uTruth[1] = pLib->uTruths[i][1]; - // set the arrival times of all input to non-existent delay - for ( k = 0; k < pLib->nVarsMax; k++ ) - { - pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR; - pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR; - } - // set an existent arrival time for rise and fall - pGate->tDelaysR[i].Rise = 0.0; - pGate->tDelaysF[i].Fall = 0.0; - // set the gate - pLib->ppSupers[i] = pGate; - } - - // read the lines - nCounter = pLib->nVarsMax; - pProgress = Extra_ProgressBarStart( stdout, pLib->nLines ); - while ( fgets( pBuffer, 5000, pFile ) != NULL ) - { - for ( pTemp = pBuffer; *pTemp == ' ' || *pTemp == '\r' || *pTemp == '\n'; pTemp++ ); - if ( pTemp[0] == '\0' ) - continue; -// if ( pTemp[0] == 'a' || pTemp[2] == 'a' ) -// { -// pLib->nLines--; -// continue; -// } - - // get the gate - pGate = Map_LibraryReadGateTree( pLib, pTemp, nCounter, pLib->nVarsMax ); - if ( pGate == NULL ) - { - Extra_ProgressBarStop( pProgress ); - return 0; - } - pLib->ppSupers[nCounter++] = pGate; - // later we will derive: truth table, delays, area, number of component gates, etc - - // update the progress bar - Extra_ProgressBarUpdate( pProgress, nCounter, NULL ); - } - Extra_ProgressBarStop( pProgress ); - if ( nCounter != pLib->nLines ) - printf( "The number of lines read (%d) is different what the file says (%d).\n", nCounter, pLib->nLines ); - pLib->nSupersAll = nCounter; - // count the number of real supergates - nCounter = 0; - for ( k = 0; k < pLib->nLines; k++ ) - nCounter += pLib->ppSupers[k]->fSuper; - if ( nCounter != pLib->nSupersReal ) - printf( "The number of gates read (%d) is different what the file says (%d).\n", nCounter, pLib->nSupersReal ); - pLib->nSupersReal = nCounter; - return 1; -} - -/**Function************************************************************* - - Synopsis [Reads one gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Super_t * Map_LibraryReadGateTree( Map_SuperLib_t * pLib, char * pBuffer, int Number, int nVarsMax ) -{ - Map_Super_t * pGate; - char * pTemp; - int i, Num; - - // start and clean the gate - pGate = (Map_Super_t *)Extra_MmFixedEntryFetch( pLib->mmSupers ); - memset( pGate, 0, sizeof(Map_Super_t) ); - - // set the gate number - pGate->Num = Number; - - // read the mark - pTemp = strtok( pBuffer, " " ); - if ( pTemp[0] == '*' ) - { - pGate->fSuper = 1; - pTemp = strtok( NULL, " " ); - } - - // read the root gate - pGate->pRoot = Mio_LibraryReadGateByName( pLib->pGenlib, pTemp ); - if ( pGate->pRoot == NULL ) - { - printf( "Cannot read the root gate names %s.\n", pTemp ); - return NULL; - } - // set the max number of fanouts - pGate->nFanLimit = s_MapFanoutLimits[ Mio_GateReadInputs(pGate->pRoot) ]; - - // read the pin-to-pin delay - for ( i = 0; ( pTemp = strtok( NULL, " \n\0" ) ); i++ ) - { - if ( pTemp[0] == '#' ) - break; - if ( i == nVarsMax ) - { - printf( "There are too many entries on the line.\n" ); - return NULL; - } - Num = atoi(pTemp); - if ( Num < 0 ) - { - printf( "The number of a child supergate is negative.\n" ); - return NULL; - } - if ( Num > pLib->nLines ) - { - printf( "The number of a child supergate (%d) exceeded the number of lines (%d).\n", - Num, pLib->nLines ); - return NULL; - } - pGate->pFanins[i] = pLib->ppSupers[Num]; - } - pGate->nFanins = i; - if ( pGate->nFanins != (unsigned)Mio_GateReadInputs(pGate->pRoot) ) - { - printf( "The number of fanins of a root gate is wrong.\n" ); - return NULL; - } - - // save the gate name, just in case - if ( pTemp && pTemp[0] == '#' ) - { - if ( pTemp[1] == 0 ) - pTemp = strtok( NULL, " \n\0" ); - else // skip spaces - for ( pTemp++; *pTemp == ' '; pTemp++ ); - // save the formula - pGate->pFormula = Extra_MmFlexEntryFetch( pLib->mmForms, strlen(pTemp)+1 ); - strcpy( pGate->pFormula, pTemp ); - } - // check the rest of the string - pTemp = strtok( NULL, " \n\0" ); - if ( pTemp != NULL ) - printf( "The following trailing symbols found \"%s\".\n", pTemp ); - return pGate; -} - - -/**Function************************************************************* - - Synopsis [Derives information about the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st_table * tExcludeGate ) -{ - Map_Super_t * pGate, * pFanin; - Mio_Pin_t * pPin; - unsigned uCanon[2]; - unsigned uTruths[6][2]; - int i, k, nRealVars; - - // set all the derivable info related to the supergates - for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ ) - { - pGate = pLib->ppSupers[i]; - - if ( tExcludeGate ) - { - if ( st_is_member( tExcludeGate, Mio_GateReadName( pGate->pRoot ) ) ) - pGate->fExclude = 1; - for ( k = 0; k < (int)pGate->nFanins; k++ ) - { - pFanin = pGate->pFanins[k]; - if ( pFanin->fExclude ) - { - pGate->fExclude = 1; - continue; - } - } - } - - // collect the truth tables of the fanins - for ( k = 0; k < (int)pGate->nFanins; k++ ) - { - pFanin = pGate->pFanins[k]; - uTruths[k][0] = pFanin->uTruth[0]; - uTruths[k][1] = pFanin->uTruth[1]; - } - // derive the new truth table - Mio_DeriveTruthTable( pGate->pRoot, uTruths, pGate->nFanins, 6, pGate->uTruth ); - - // set the initial delays of the supergate - for ( k = 0; k < pLib->nVarsMax; k++ ) - { - pGate->tDelaysR[k].Rise = pGate->tDelaysR[k].Fall = MAP_NO_VAR; - pGate->tDelaysF[k].Rise = pGate->tDelaysF[k].Fall = MAP_NO_VAR; - } - // get the linked list of pins for the given root gate - pPin = Mio_GateReadPins( pGate->pRoot ); - // update the initial delay of the supergate using info from the corresponding pin - for ( k = 0; k < (int)pGate->nFanins; k++, pPin = Mio_PinReadNext(pPin) ) - { - // if there is no corresponding pin, this is a bug, return fail - if ( pPin == NULL ) - { - printf( "There are less pins than gate inputs.\n" ); - return 0; - } - // update the delay information of k-th fanins info from the corresponding pin - Map_LibraryAddFaninDelays( pLib, pGate, pGate->pFanins[k], pPin ); - } - // if there are some pins left, this is a bug, return fail - if ( pPin != NULL ) - { - printf( "There are more pins than gate inputs.\n" ); - return 0; - } - // find the max delay - pGate->tDelayMax.Rise = pGate->tDelayMax.Fall = MAP_NO_VAR; - for ( k = 0; k < pLib->nVarsMax; k++ ) - { - // the rise of the output depends on the rise and fall of the output - if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Rise ) - pGate->tDelayMax.Rise = pGate->tDelaysR[k].Rise; - if ( pGate->tDelayMax.Rise < pGate->tDelaysR[k].Fall ) - pGate->tDelayMax.Rise = pGate->tDelaysR[k].Fall; - // the fall of the output depends on the rise and fall of the output - if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Rise ) - pGate->tDelayMax.Fall = pGate->tDelaysF[k].Rise; - if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Fall ) - pGate->tDelayMax.Fall = pGate->tDelaysF[k].Fall; - - pGate->tDelaysF[k].Worst = MAP_MAX( pGate->tDelaysF[k].Fall, pGate->tDelaysF[k].Rise ); - pGate->tDelaysR[k].Worst = MAP_MAX( pGate->tDelaysR[k].Fall, pGate->tDelaysR[k].Rise ); - } - - // count gates and area of the supergate - pGate->nGates = 1; - pGate->Area = (float)Mio_GateReadArea(pGate->pRoot); - for ( k = 0; k < (int)pGate->nFanins; k++ ) - { - pGate->nGates += pGate->pFanins[k]->nGates; - pGate->Area += pGate->pFanins[k]->Area; - } - // do not add the gate to the table, if this gate is an internal gate - // of some supegate and does not correspond to a supergate output - if ( ( !pGate->fSuper ) || pGate->fExclude ) - continue; - - // find the maximum index of a variable in the support of the supergates - // this is important for two reasons: - // (1) to limit the number of permutations considered for canonicization - // (2) to get rid of equivalence phases to speed-up matching - nRealVars = Map_LibraryGetMaxSuperPi_rec( pGate ) + 1; - assert( nRealVars > 0 && nRealVars <= pLib->nVarsMax ); - // if there are some problems with this code, try this instead -// nRealVars = pLib->nVarsMax; - - // find the N-canonical form of this supergate - pGate->nPhases = Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, nRealVars, pGate->uTruth, pGate->uPhases, uCanon ); - // add the supergate into the table by its N-canonical table - Map_SuperTableInsertC( pLib->tTableC, uCanon, pGate ); -/* - { - int uCanon1, uCanon2; - uCanon1 = uCanon[0]; - pGate->uTruth[0] = ~pGate->uTruth[0]; - pGate->uTruth[1] = ~pGate->uTruth[1]; - Map_CanonComputeSlow( pLib->uTruths, pLib->nVarsMax, nRealVars, pGate->uTruth, pGate->uPhases, uCanon ); - uCanon2 = uCanon[0]; -Rwt_Man5ExploreCount( uCanon1 < uCanon2 ? uCanon1 : uCanon2 ); - } -*/ - } - // sort the gates in each line - Map_SuperTableSortSupergatesByDelay( pLib->tTableC, pLib->nSupersAll ); - - // let the glory be manifest -// Map_LibraryPrintTree( pLib ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Finds the largest PI number in the support of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_LibraryGetMaxSuperPi_rec( Map_Super_t * pGate ) -{ - int i, VarCur, VarMax = 0; - if ( pGate->pRoot == NULL ) - return pGate->Num; - for ( i = 0; i < (int)pGate->nFanins; i++ ) - { - VarCur = Map_LibraryGetMaxSuperPi_rec( pGate->pFanins[i] ); - if ( VarMax < VarCur ) - VarMax = VarCur; - } - return VarMax; -} - -/**Function************************************************************* - - Synopsis [Finds the largest PI number in the support of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Map_LibraryGetGateSupp_rec( Map_Super_t * pGate ) -{ - unsigned uSupport; - int i; - if ( pGate->pRoot == NULL ) - return (unsigned)(1 << (pGate->Num)); - uSupport = 0; - for ( i = 0; i < (int)pGate->nFanins; i++ ) - uSupport |= Map_LibraryGetGateSupp_rec( pGate->pFanins[i] ); - return uSupport; -} - -/**Function************************************************************* - - Synopsis [Derives the pin-to-pin delay constraints for the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_LibraryAddFaninDelays( Map_SuperLib_t * pLib, Map_Super_t * pGate, Map_Super_t * pFanin, Mio_Pin_t * pPin ) -{ - Mio_PinPhase_t PinPhase; - float tDelayBlockRise, tDelayBlockFall, tDelayPin; - bool fMaxDelay = 0; - int i; - - // use this node to enable max-delay model - if ( fMaxDelay ) - { - float tDelayBlockMax; - // get the maximum delay - tDelayBlockMax = (float)Mio_PinReadDelayBlockMax(pPin); - // go through the supergate inputs - for ( i = 0; i < pLib->nVarsMax; i++ ) - { - if ( pFanin->tDelaysR[i].Rise < 0 ) - continue; - tDelayPin = pFanin->tDelaysR[i].Rise + tDelayBlockMax; - if ( pGate->tDelaysR[i].Rise < tDelayPin ) - pGate->tDelaysR[i].Rise = tDelayPin; - } - // go through the supergate inputs - for ( i = 0; i < pLib->nVarsMax; i++ ) - { - if ( pFanin->tDelaysF[i].Fall < 0 ) - continue; - tDelayPin = pFanin->tDelaysF[i].Fall + tDelayBlockMax; - if ( pGate->tDelaysF[i].Fall < tDelayPin ) - pGate->tDelaysF[i].Fall = tDelayPin; - } - return; - } - - // get the interesting parameters of this pin - PinPhase = Mio_PinReadPhase(pPin); - tDelayBlockRise = (float)Mio_PinReadDelayBlockRise( pPin ); - tDelayBlockFall = (float)Mio_PinReadDelayBlockFall( pPin ); - - // update the rise and fall of the output depending on the phase of the pin - if ( PinPhase != MIO_PHASE_INV ) // NONINV phase is present - { - // the rise of the gate is determined by the rise of the fanin - // the fall of the gate is determined by the fall of the fanin - for ( i = 0; i < pLib->nVarsMax; i++ ) - { - //////////////////////////////////////////////////////// - // consider the rise of the gate - //////////////////////////////////////////////////////// - // check two types of constraints on the rise of the fanin: - // (1) the constraints related to the rise of the PIs - // (2) the constraints related to the fall of the PIs - if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1) - { // fanin's rise depends on the rise of i-th PI - // update the rise of the gate's output - if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockRise ) - pGate->tDelaysR[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockRise; - } - if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2) - { // fanin's rise depends on the fall of i-th PI - // update the rise of the gate's output - if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockRise ) - pGate->tDelaysR[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockRise; - } - //////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////// - // consider the fall of the gate (similar) - //////////////////////////////////////////////////////// - // check two types of constraints on the fall of the fanin: - // (1) the constraints related to the rise of the PIs - // (2) the constraints related to the fall of the PIs - if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1) - { - if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockFall ) - pGate->tDelaysF[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockFall; - } - if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2) - { - if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockFall ) - pGate->tDelaysF[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockFall; - } - //////////////////////////////////////////////////////// - } - } - if ( PinPhase != MIO_PHASE_NONINV ) // INV phase is present - { - // the rise of the gate is determined by the fall of the fanin - // the fall of the gate is determined by the rise of the fanin - for ( i = 0; i < pLib->nVarsMax; i++ ) - { - //////////////////////////////////////////////////////// - // consider the rise of the gate's output - //////////////////////////////////////////////////////// - // check two types of constraints on the fall of the fanin: - // (1) the constraints related to the rise of the PIs - // (2) the constraints related to the fall of the PIs - if ( pFanin->tDelaysF[i].Rise >= 0 ) // case (1) - { // fanin's rise depends on the rise of i-th PI - // update the rise of the gate - if ( pGate->tDelaysR[i].Rise < pFanin->tDelaysF[i].Rise + tDelayBlockRise ) - pGate->tDelaysR[i].Rise = pFanin->tDelaysF[i].Rise + tDelayBlockRise; - } - if ( pFanin->tDelaysF[i].Fall >= 0 ) // case (2) - { // fanin's rise depends on the fall of i-th PI - // update the rise of the gate - if ( pGate->tDelaysR[i].Fall < pFanin->tDelaysF[i].Fall + tDelayBlockRise ) - pGate->tDelaysR[i].Fall = pFanin->tDelaysF[i].Fall + tDelayBlockRise; - } - //////////////////////////////////////////////////////// - - //////////////////////////////////////////////////////// - // consider the fall of the gate (similar) - //////////////////////////////////////////////////////// - // check two types of constraints on the rise of the fanin: - // (1) the constraints related to the rise of the PIs - // (2) the constraints related to the fall of the PIs - if ( pFanin->tDelaysR[i].Rise >= 0 ) // case (1) - { - if ( pGate->tDelaysF[i].Rise < pFanin->tDelaysR[i].Rise + tDelayBlockFall ) - pGate->tDelaysF[i].Rise = pFanin->tDelaysR[i].Rise + tDelayBlockFall; - } - if ( pFanin->tDelaysR[i].Fall >= 0 ) // case (2) - { - if ( pGate->tDelaysF[i].Fall < pFanin->tDelaysR[i].Fall + tDelayBlockFall ) - pGate->tDelaysF[i].Fall = pFanin->tDelaysR[i].Fall + tDelayBlockFall; - } - //////////////////////////////////////////////////////// - } - } -} - - -/**Function************************************************************* - - Synopsis [Performs phase transformation for one function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Map_CalculatePhase( unsigned uTruths[][2], int nVars, unsigned uTruth, unsigned uPhase ) -{ - int v, Shift; - for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) - if ( uPhase & Shift ) - uTruth = (((uTruth & ~uTruths[v][0]) << Shift) | ((uTruth & uTruths[v][0]) >> Shift)); - return uTruth; -} - -/**Function************************************************************* - - Synopsis [Performs phase transformation for one function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CalculatePhase6( unsigned uTruths[][2], int nVars, unsigned uTruth[], unsigned uPhase, unsigned uTruthRes[] ) -{ - unsigned uTemp; - int v, Shift; - - // initialize the result - uTruthRes[0] = uTruth[0]; - uTruthRes[1] = uTruth[1]; - if ( uPhase == 0 ) - return; - // compute the phase - for ( v = 0, Shift = 1; v < nVars; v++, Shift <<= 1 ) - if ( uPhase & Shift ) - { - if ( Shift < 32 ) - { - uTruthRes[0] = (((uTruthRes[0] & ~uTruths[v][0]) << Shift) | ((uTruthRes[0] & uTruths[v][0]) >> Shift)); - uTruthRes[1] = (((uTruthRes[1] & ~uTruths[v][1]) << Shift) | ((uTruthRes[1] & uTruths[v][1]) >> Shift)); - } - else - { - uTemp = uTruthRes[0]; - uTruthRes[0] = uTruthRes[1]; - uTruthRes[1] = uTemp; - } - } -} - -/**Function************************************************************* - - Synopsis [Prints the supergate library after deriving parameters.] - - Description [This procedure is very useful to see the library after - it has been read into the mapper by "read_super" and all the information - about the supergates derived.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_LibraryPrintTree( Map_SuperLib_t * pLib ) -{ - Map_Super_t * pGate; - int i, k; - - // print all the info related to the supergates -// for ( i = pLib->nVarsMax; i < (int)pLib->nLines; i++ ) - for ( i = pLib->nVarsMax; i < 20; i++ ) - { - pGate = pLib->ppSupers[i]; - - // write the gate's fanin info and formula - printf( "%6d ", pGate->Num ); - printf( "%c ", pGate->fSuper? '*' : ' ' ); - printf( "%6s", Mio_GateReadName(pGate->pRoot) ); - for ( k = 0; k < (int)pGate->nFanins; k++ ) - printf( " %6d", pGate->pFanins[k]->Num ); - printf( " %s", pGate->pFormula ); - printf( "\n" ); - - // write the gate's derived info - Extra_PrintBinary( stdout, pGate->uTruth, 64 ); - printf( " %3d", pGate->nGates ); - printf( " %6.2f", pGate->Area ); - printf( " (%4.2f, %4.2f)", pGate->tDelayMax.Rise, pGate->tDelayMax.Fall ); - printf( "\n" ); - for ( k = 0; k < pLib->nVarsMax; k++ ) - { - // print the constraint on the rise of the gate in the form (D1, D2), - // where D1 is the constraint related to the rise of the k-th PI - // where D2 is the constraint related to the fall of the k-th PI - if ( pGate->tDelaysR[k].Rise < 0 && pGate->tDelaysR[k].Fall < 0 ) - printf( " (----, ----)" ); - else if ( pGate->tDelaysR[k].Fall < 0 ) - printf( " (%4.2f, ----)", pGate->tDelaysR[k].Rise ); - else if ( pGate->tDelaysR[k].Rise < 0 ) - printf( " (----, %4.2f)", pGate->tDelaysR[k].Fall ); - else - printf( " (%4.2f, %4.2f)", pGate->tDelaysR[k].Rise, pGate->tDelaysR[k].Fall ); - - // print the constraint on the fall of the gate in the form (D1, D2), - // where D1 is the constraint related to the rise of the k-th PI - // where D2 is the constraint related to the fall of the k-th PI - if ( pGate->tDelaysF[k].Rise < 0 && pGate->tDelaysF[k].Fall < 0 ) - printf( " (----, ----)" ); - else if ( pGate->tDelaysF[k].Fall < 0 ) - printf( " (%4.2f, ----)", pGate->tDelaysF[k].Rise ); - else if ( pGate->tDelaysF[k].Rise < 0 ) - printf( " (----, %4.2f)", pGate->tDelaysF[k].Fall ); - else - printf( " (%4.2f, %4.2f)", pGate->tDelaysF[k].Rise, pGate->tDelaysF[k].Fall ); - printf( "\n" ); - } - printf( "\n" ); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperTruth.c b/src/map/mapper/mapperTruth.c deleted file mode 100644 index 388b6dd3..00000000 --- a/src/map/mapper/mapperTruth.c +++ /dev/null @@ -1,310 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperTruth.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperTruth.c,v 1.8 2005/01/23 06:59:45 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Map_TruthsCut( Map_Man_t * pMan, Map_Cut_t * pCut ); -extern void Map_TruthsCutOne( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] ); -static void Map_CutsCollect_rec( Map_Cut_t * pCut, Map_NodeVec_t * vVisited ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Derives truth tables for each cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingTruths( Map_Man_t * pMan ) -{ - ProgressBar * pProgress; - Map_Node_t * pNode; - Map_Cut_t * pCut; - int nNodes, i; - // compute the cuts for the POs - nNodes = pMan->vAnds->nSize; - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - for ( i = 0; i < nNodes; i++ ) - { - pNode = pMan->vAnds->pArray[i]; - if ( !Map_NodeIsAnd( pNode ) ) - continue; - assert( pNode->pCuts ); - assert( pNode->pCuts->nLeaves == 1 ); - - // match the simple cut - pNode->pCuts->M[0].uPhase = 0; - pNode->pCuts->M[0].pSupers = pMan->pSuperLib->pSuperInv; - pNode->pCuts->M[0].uPhaseBest = 0; - pNode->pCuts->M[0].pSuperBest = pMan->pSuperLib->pSuperInv; - - pNode->pCuts->M[1].uPhase = 0; - pNode->pCuts->M[1].pSupers = pMan->pSuperLib->pSuperInv; - pNode->pCuts->M[1].uPhaseBest = 1; - pNode->pCuts->M[1].pSuperBest = pMan->pSuperLib->pSuperInv; - - // match the rest of the cuts - for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) - Map_TruthsCut( pMan, pCut ); - Extra_ProgressBarUpdate( pProgress, i, "Tables ..." ); - } - Extra_ProgressBarStop( pProgress ); -} - -/**Function************************************************************* - - Synopsis [Derives the truth table for one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut ) -{ -// unsigned uCanon1, uCanon2; - unsigned uTruth[2], uCanon[2]; - unsigned char uPhases[16]; - unsigned * uCanon2; - char * pPhases2; - int fUseFast = 1; - int fUseSlow = 0; - int fUseRec = 0; // this does not work for Solaris - - extern int Map_CanonCompute( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes ); - - // generally speaking, 1-input cut can be matched into a wire! - if ( pCut->nLeaves == 1 ) - return; -/* - if ( p->nVarsMax == 5 ) - { - uTruth[0] = pCut->uTruth; - uTruth[1] = pCut->uTruth; - } - else -*/ - Map_TruthsCutOne( p, pCut, uTruth ); - - - // compute the canonical form for the positive phase - if ( fUseFast ) - Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); - else if ( fUseSlow ) - Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); - else if ( fUseRec ) - { -// Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); - Extra_TruthCanonFastN( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); -/* - if ( uCanon[0] != uCanon2[0] || uPhases[0] != pPhases2[0] ) - { - int k = 0; - Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); - } -*/ - uCanon[0] = uCanon2[0]; - uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; - uPhases[0] = pPhases2[0]; - } - else - Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); - pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon ); - pCut->M[1].uPhase = uPhases[0]; - p->nCanons++; - -//uCanon1 = uCanon[0] & 0xFFFF; - - // compute the canonical form for the negative phase - uTruth[0] = ~uTruth[0]; - uTruth[1] = ~uTruth[1]; - if ( fUseFast ) - Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); - else if ( fUseSlow ) - Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); - else if ( fUseRec ) - { -// Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); - Extra_TruthCanonFastN( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); -/* - if ( uCanon[0] != uCanon2[0] || uPhases[0] != pPhases2[0] ) - { - int k = 0; - Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); - } -*/ - uCanon[0] = uCanon2[0]; - uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; - uPhases[0] = pPhases2[0]; - } - else - Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); - pCut->M[0].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon ); - pCut->M[0].uPhase = uPhases[0]; - p->nCanons++; - -//uCanon2 = uCanon[0] & 0xFFFF; -//assert( p->nVarsMax == 4 ); -//Rwt_Man4ExploreCount( uCanon1 < uCanon2 ? uCanon1 : uCanon2 ); - - // restore the truth table - uTruth[0] = ~uTruth[0]; - uTruth[1] = ~uTruth[1]; -} - -/**Function************************************************************* - - Synopsis [Computes the truth table of one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_TruthsCutOne( Map_Man_t * p, Map_Cut_t * pCut, unsigned uTruth[] ) -{ - unsigned uTruth1[2], uTruth2[2]; - Map_Cut_t * pTemp; - int i; - // mark the cut leaves - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pTemp = pCut->ppLeaves[i]->pCuts; - pTemp->fMark = 1; - pTemp->M[0].uPhaseBest = p->uTruths[i][0]; - pTemp->M[1].uPhaseBest = p->uTruths[i][1]; - } - assert( pCut->fMark == 0 ); - - // collect the cuts in the cut cone - p->vVisited->nSize = 0; - Map_CutsCollect_rec( pCut, p->vVisited ); - assert( p->vVisited->nSize > 0 ); - pCut->nVolume = p->vVisited->nSize; - - // compute the tables and unmark - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pTemp = pCut->ppLeaves[i]->pCuts; - pTemp->fMark = 0; - } - for ( i = 0; i < p->vVisited->nSize; i++ ) - { - // get the cut - pTemp = (Map_Cut_t *)p->vVisited->pArray[i]; - pTemp->fMark = 0; - // get truth table of the first branch - if ( Map_CutIsComplement(pTemp->pOne) ) - { - uTruth1[0] = ~Map_CutRegular(pTemp->pOne)->M[0].uPhaseBest; - uTruth1[1] = ~Map_CutRegular(pTemp->pOne)->M[1].uPhaseBest; - } - else - { - uTruth1[0] = Map_CutRegular(pTemp->pOne)->M[0].uPhaseBest; - uTruth1[1] = Map_CutRegular(pTemp->pOne)->M[1].uPhaseBest; - } - // get truth table of the second branch - if ( Map_CutIsComplement(pTemp->pTwo) ) - { - uTruth2[0] = ~Map_CutRegular(pTemp->pTwo)->M[0].uPhaseBest; - uTruth2[1] = ~Map_CutRegular(pTemp->pTwo)->M[1].uPhaseBest; - } - else - { - uTruth2[0] = Map_CutRegular(pTemp->pTwo)->M[0].uPhaseBest; - uTruth2[1] = Map_CutRegular(pTemp->pTwo)->M[1].uPhaseBest; - } - // get the truth table of the output - if ( !pTemp->Phase ) - { - pTemp->M[0].uPhaseBest = uTruth1[0] & uTruth2[0]; - pTemp->M[1].uPhaseBest = uTruth1[1] & uTruth2[1]; - } - else - { - pTemp->M[0].uPhaseBest = ~(uTruth1[0] & uTruth2[0]); - pTemp->M[1].uPhaseBest = ~(uTruth1[1] & uTruth2[1]); - } - } - uTruth[0] = pTemp->M[0].uPhaseBest; - uTruth[1] = pTemp->M[1].uPhaseBest; -} - -/**Function************************************************************* - - Synopsis [Recursively collect the cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_CutsCollect_rec( Map_Cut_t * pCut, Map_NodeVec_t * vVisited ) -{ - if ( pCut->fMark ) - return; - Map_CutsCollect_rec( Map_CutRegular(pCut->pOne), vVisited ); - Map_CutsCollect_rec( Map_CutRegular(pCut->pTwo), vVisited ); - assert( pCut->fMark == 0 ); - pCut->fMark = 1; - Map_NodeVecPush( vVisited, (Map_Node_t *)pCut ); -} - -/* - { - unsigned * uCanon2; - char * pPhases2; - - Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); - Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); - if ( uCanon2[0] != uCanon[0] ) - { - int v = 0; - Map_CanonCompute( p->nVarsMax, pCut->nLeaves, uTruth, &uCanon2, &pPhases2 ); - Map_CanonComputeFast( p, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon ); - } -// else -// { -// printf( "Correct.\n" ); -// } - } -*/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperUtils.c b/src/map/mapper/mapperUtils.c deleted file mode 100644 index 11a3a683..00000000 --- a/src/map/mapper/mapperUtils.c +++ /dev/null @@ -1,1154 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperUtils.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperUtils.c,v 1.8 2004/11/03 22:41:45 satrajit Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define MAP_CO_LIST_SIZE 5 - -static void Map_MappingDfs_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fCollectEquiv ); -static int Map_MappingCountLevels_rec( Map_Node_t * pNode ); -static float Map_MappingSetRefsAndArea_rec( Map_Man_t * pMan, Map_Node_t * pNode ); -static float Map_MappingSetRefsAndSwitch_rec( Map_Man_t * pMan, Map_Node_t * pNode ); -static float Map_MappingSetRefsAndWire_rec( Map_Man_t * pMan, Map_Node_t * pNode ); -static void Map_MappingDfsCuts_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes ); -static float Map_MappingArea_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_NodeVec_t * vNodes ); -static int Map_MappingCompareOutputDelay( Map_Node_t ** ppNode1, Map_Node_t ** ppNode2 ); -static void Map_MappingFindLatest( Map_Man_t * p, int * pNodes, int nNodesMax ); -static unsigned Map_MappingExpandTruth_rec( unsigned uTruth, int nVars ); -static void Map_MappingGetChoiceLevels( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2, int * pMin, int * pMax ); -static float Map_MappingGetChoiceVolumes( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 ); -static int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices ); -static Map_Man_t * s_pMan = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_NodeVec_t * Map_MappingDfs( Map_Man_t * pMan, int fCollectEquiv ) -{ - Map_NodeVec_t * vNodes; - int i; - // perform the traversal - vNodes = Map_NodeVecAlloc( 100 ); - for ( i = 0; i < pMan->nOutputs; i++ ) - Map_MappingDfs_rec( Map_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv ); - for ( i = 0; i < vNodes->nSize; i++ ) - vNodes->pArray[i]->fMark0 = 0; -// for ( i = 0; i < pMan->nOutputs; i++ ) -// Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_NodeVec_t * Map_MappingDfsNodes( Map_Man_t * pMan, Map_Node_t ** ppCuts, int nNodes, int fEquiv ) -{ - Map_NodeVec_t * vNodes; - int i; - // perform the traversal - vNodes = Map_NodeVecAlloc( 200 ); - for ( i = 0; i < nNodes; i++ ) - Map_MappingDfs_rec( ppCuts[i], vNodes, fEquiv ); - for ( i = 0; i < vNodes->nSize; i++ ) - vNodes->pArray[i]->fMark0 = 0; - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingDfs_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fCollectEquiv ) -{ - assert( !Map_IsComplement(pNode) ); - if ( pNode->fMark0 ) - return; - // visit the transitive fanin - if ( Map_NodeIsAnd(pNode) ) - { - Map_MappingDfs_rec( Map_Regular(pNode->p1), vNodes, fCollectEquiv ); - Map_MappingDfs_rec( Map_Regular(pNode->p2), vNodes, fCollectEquiv ); - } - // visit the equivalent nodes - if ( fCollectEquiv && pNode->pNextE ) - Map_MappingDfs_rec( pNode->pNextE, vNodes, fCollectEquiv ); - // make sure the node is not visited through the equivalent nodes - assert( pNode->fMark0 == 0 ); - // mark the node as visited - pNode->fMark0 = 1; - // add the node to the list - Map_NodeVecPush( vNodes, pNode ); -} - - - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingDfsMarked1_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fFirst ) -{ - assert( !Map_IsComplement(pNode) ); - if ( pNode->fMark0 ) - return; - // visit the transitive fanin - if ( Map_NodeIsAnd(pNode) ) - { - Map_MappingDfsMarked1_rec( Map_Regular(pNode->p1), vNodes, 0 ); - Map_MappingDfsMarked1_rec( Map_Regular(pNode->p2), vNodes, 0 ); - } - // visit the equivalent nodes - if ( !fFirst && pNode->pNextE ) - Map_MappingDfsMarked1_rec( pNode->pNextE, vNodes, 0 ); - // make sure the node is not visited through the equivalent nodes - assert( pNode->fMark0 == 0 ); - // mark the node as visited - pNode->fMark0 = 1; - // add the node to the list - Map_NodeVecPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingDfsMarked2_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, Map_NodeVec_t * vBoundary, int fFirst ) -{ - assert( !Map_IsComplement(pNode) ); - if ( pNode->fMark1 ) - return; - if ( pNode->fMark0 || Map_NodeIsVar(pNode) ) - { - pNode->fMark1 = 1; - Map_NodeVecPush(vBoundary, pNode); - return; - } - // visit the transitive fanin - if ( Map_NodeIsAnd(pNode) ) - { - Map_MappingDfsMarked2_rec( Map_Regular(pNode->p1), vNodes, vBoundary, 0 ); - Map_MappingDfsMarked2_rec( Map_Regular(pNode->p2), vNodes, vBoundary, 0 ); - } - // visit the equivalent nodes - if ( !fFirst && pNode->pNextE ) - Map_MappingDfsMarked2_rec( pNode->pNextE, vNodes, vBoundary, 0 ); - // make sure the node is not visited through the equivalent nodes - assert( pNode->fMark1 == 0 ); - // mark the node as visited - pNode->fMark1 = 1; - // add the node to the list - Map_NodeVecPush( vNodes, pNode ); -} - - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingDfsMarked3_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes ) -{ - assert( !Map_IsComplement(pNode) ); - if ( pNode->fMark0 ) - return; - // visit the transitive fanin - if ( Map_NodeIsAnd(pNode) ) - { - Map_MappingDfsMarked3_rec( Map_Regular(pNode->p1), vNodes ); - Map_MappingDfsMarked3_rec( Map_Regular(pNode->p2), vNodes ); - } - // make sure the node is not visited through the equivalent nodes - assert( pNode->fMark0 == 0 ); - // mark the node as visited - pNode->fMark0 = 1; - // add the node to the list - Map_NodeVecPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingDfsMarked4_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes ) -{ - assert( !Map_IsComplement(pNode) ); - if ( pNode->fMark1 ) - return; - // visit the transitive fanin - if ( Map_NodeIsAnd(pNode) ) - { - Map_MappingDfsMarked4_rec( Map_Regular(pNode->p1), vNodes ); - Map_MappingDfsMarked4_rec( Map_Regular(pNode->p2), vNodes ); - } - // make sure the node is not visited through the equivalent nodes - assert( pNode->fMark1 == 0 ); - // mark the node as visited - pNode->fMark1 = 1; - // add the node to the list - Map_NodeVecPush( vNodes, pNode ); -} - - - -/**Function************************************************************* - - Synopsis [Computes the number of logic levels not counting PIs/POs.] - - Description [] - - SideEffects [Note that this procedure will reassign the levels assigned - originally by NodeCreate() because it counts the number of levels with - choices differently!] - - SeeAlso [] - -***********************************************************************/ -int Map_MappingCountLevels( Map_Man_t * pMan ) -{ - int i, LevelsMax, LevelsCur; - // perform the traversal - LevelsMax = -1; - for ( i = 0; i < pMan->nOutputs; i++ ) - { - LevelsCur = Map_MappingCountLevels_rec( Map_Regular(pMan->pOutputs[i]) ); - if ( LevelsMax < LevelsCur ) - LevelsMax = LevelsCur; - } - for ( i = 0; i < pMan->nOutputs; i++ ) - Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) ); - return LevelsMax; -} - -/**Function************************************************************* - - Synopsis [Recursively computes the number of logic levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MappingCountLevels_rec( Map_Node_t * pNode ) -{ - int Level1, Level2; - assert( !Map_IsComplement(pNode) ); - if ( !Map_NodeIsAnd(pNode) ) - { - pNode->Level = 0; - return 0; - } - if ( pNode->fMark0 ) - return pNode->Level; - pNode->fMark0 = 1; - // visit the transitive fanin - Level1 = Map_MappingCountLevels_rec( Map_Regular(pNode->p1) ); - Level2 = Map_MappingCountLevels_rec( Map_Regular(pNode->p2) ); - // set the number of levels - pNode->Level = 1 + ((Level1>Level2)? Level1: Level2); - return pNode->Level; -} - -/**Function************************************************************* - - Synopsis [Unmarks the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingUnmark( Map_Man_t * pMan ) -{ - int i; - for ( i = 0; i < pMan->nOutputs; i++ ) - Map_MappingUnmark_rec( Map_Regular(pMan->pOutputs[i]) ); -} - -/**Function************************************************************* - - Synopsis [Recursively unmarks the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingUnmark_rec( Map_Node_t * pNode ) -{ - assert( !Map_IsComplement(pNode) ); - if ( pNode->fMark0 == 0 ) - return; - pNode->fMark0 = 0; - if ( !Map_NodeIsAnd(pNode) ) - return; - Map_MappingUnmark_rec( Map_Regular(pNode->p1) ); - Map_MappingUnmark_rec( Map_Regular(pNode->p2) ); - // visit the equivalent nodes - if ( pNode->pNextE ) - Map_MappingUnmark_rec( pNode->pNextE ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingMark_rec( Map_Node_t * pNode ) -{ - assert( !Map_IsComplement(pNode) ); - if ( pNode->fMark0 == 1 ) - return; - pNode->fMark0 = 1; - if ( !Map_NodeIsAnd(pNode) ) - return; - // visit the transitive fanin of the selected cut - Map_MappingMark_rec( Map_Regular(pNode->p1) ); - Map_MappingMark_rec( Map_Regular(pNode->p2) ); -} - -/**Function************************************************************* - - Synopsis [Compares the outputs by their arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MappingCompareOutputDelay( Map_Node_t ** ppNode1, Map_Node_t ** ppNode2 ) -{ - Map_Node_t * pNode1 = Map_Regular(*ppNode1); - Map_Node_t * pNode2 = Map_Regular(*ppNode2); - int fPhase1 = !Map_IsComplement(*ppNode1); - int fPhase2 = !Map_IsComplement(*ppNode2); - float Arrival1 = pNode1->tArrival[fPhase1].Worst; - float Arrival2 = pNode2->tArrival[fPhase2].Worst; - if ( Arrival1 < Arrival2 ) - return -1; - if ( Arrival1 > Arrival2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Finds given number of latest arriving COs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingFindLatest( Map_Man_t * p, int * pNodes, int nNodesMax ) -{ - int nNodes, i, k, v; - assert( p->nOutputs >= nNodesMax ); - pNodes[0] = 0; - nNodes = 1; - for ( i = 1; i < p->nOutputs; i++ ) - { - for ( k = nNodes - 1; k >= 0; k-- ) - if ( Map_MappingCompareOutputDelay( &p->pOutputs[pNodes[k]], &p->pOutputs[i] ) >= 0 ) - break; - if ( k == nNodesMax - 1 ) - continue; - if ( nNodes < nNodesMax ) - nNodes++; - for ( v = nNodes - 1; v > k+1; v-- ) - pNodes[v] = pNodes[v-1]; - pNodes[k+1] = i; - } -} - -/**Function************************************************************* - - Synopsis [Prints a bunch of latest arriving outputs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingPrintOutputArrivals( Map_Man_t * p ) -{ - int pSorted[MAP_CO_LIST_SIZE]; - Map_Time_t * pTimes; - Map_Node_t * pNode; - int fPhase, Limit, i; - int MaxNameSize; - - // determine the number of nodes to print - Limit = (p->nOutputs > MAP_CO_LIST_SIZE)? MAP_CO_LIST_SIZE : p->nOutputs; - - // determine the order - Map_MappingFindLatest( p, pSorted, Limit ); - - // determine max size of the node's name - MaxNameSize = 0; - for ( i = 0; i < Limit; i++ ) - if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) ) - MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]); - - // print the latest outputs - for ( i = 0; i < Limit; i++ ) - { - // get the i-th latest output - pNode = Map_Regular(p->pOutputs[pSorted[i]]); - fPhase =!Map_IsComplement(p->pOutputs[pSorted[i]]); - pTimes = pNode->tArrival + fPhase; - // print out the best arrival time - printf( "Output %-*s : ", MaxNameSize + 3, p->ppOutputNames[pSorted[i]] ); - printf( "Delay = (%5.2f, %5.2f) ", (double)pTimes->Rise, (double)pTimes->Fall ); - printf( "%s", fPhase? "POS" : "NEG" ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Sets up the truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingSetupTruthTables( unsigned uTruths[][2] ) -{ - int m, v; - // set up the truth tables - for ( m = 0; m < 32; m++ ) - for ( v = 0; v < 5; v++ ) - if ( m & (1 << v) ) - uTruths[v][0] |= (1 << m); - // make adjustments for the case of 6 variables - for ( v = 0; v < 5; v++ ) - uTruths[v][1] = uTruths[v][0]; - uTruths[5][0] = 0; - uTruths[5][1] = MAP_FULL; -} - -/**Function************************************************************* - - Synopsis [Sets up the truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingSetupTruthTablesLarge( unsigned uTruths[][32] ) -{ - int m, v; - // clean everything - for ( m = 0; m < 32; m++ ) - for ( v = 0; v < 10; v++ ) - uTruths[v][m] = 0; - // set up the truth tables - for ( m = 0; m < 32; m++ ) - for ( v = 0; v < 5; v++ ) - if ( m & (1 << v) ) - { - uTruths[v][0] |= (1 << m); - uTruths[v+5][m] = MAP_FULL; - } - // extend this info for the rest of the first 5 variables - for ( m = 0; m < 32; m++ ) - for ( v = 0; v < 5; v++ ) - uTruths[v][m] = uTruths[v][0]; -/* - // verify - for ( m = 0; m < 1024; m++, printf("\n") ) - for ( v = 0; v < 10; v++ ) - if ( Map_InfoReadVar( uTruths[v], m ) ) - printf( "1" ); - else - printf( "0" ); -*/ -} - -/**Function************************************************************* - - Synopsis [Sets up the mask.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingSetupMask( unsigned uMask[], int nVarsMax ) -{ - if ( nVarsMax == 6 ) - uMask[0] = uMask[1] = MAP_FULL; - else - { - uMask[0] = MAP_MASK(1 << nVarsMax); - uMask[1] = 0; - } -} - -/**Function************************************************************* - - Synopsis [Verify one useful property.] - - Description [This procedure verifies one useful property. After - the FRAIG construction with choice nodes is over, each primary node - should have fanins that are primary nodes. The primary nodes is the - one that does not have pNode->pRepr set to point to another node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_ManCheckConsistency( Map_Man_t * p ) -{ - Map_Node_t * pNode; - Map_NodeVec_t * pVec; - int i; - pVec = Map_MappingDfs( p, 0 ); - for ( i = 0; i < pVec->nSize; i++ ) - { - pNode = pVec->pArray[i]; - if ( Map_NodeIsVar(pNode) ) - { - if ( pNode->pRepr ) - printf( "Primary input %d is a secondary node.\n", pNode->Num ); - } - else if ( Map_NodeIsConst(pNode) ) - { - if ( pNode->pRepr ) - printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); - } - else - { - if ( pNode->pRepr ) - printf( "Internal node %d is a secondary node.\n", pNode->Num ); - if ( Map_Regular(pNode->p1)->pRepr ) - printf( "Internal node %d has first fanin that is a secondary node.\n", pNode->Num ); - if ( Map_Regular(pNode->p2)->pRepr ) - printf( "Internal node %d has second fanin that is a secondary node.\n", pNode->Num ); - } - } - Map_NodeVecFree( pVec ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if current mapping of the node violates fanout limits.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MappingNodeIsViolator( Map_Node_t * pNode, Map_Cut_t * pCut, int fPosPol ) -{ - return pNode->nRefAct[fPosPol] > (int)pCut->M[fPosPol].pSuperBest->nFanLimit; -} - -/**Function************************************************************* - - Synopsis [Computes the total are flow of the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Map_MappingGetAreaFlow( Map_Man_t * p ) -{ - Map_Node_t * pNode; - Map_Cut_t * pCut; - float aFlowFlowTotal = 0; - int fPosPol, i; - for ( i = 0; i < p->nOutputs; i++ ) - { - pNode = Map_Regular(p->pOutputs[i]); - if ( !Map_NodeIsAnd(pNode) ) - continue; - fPosPol = !Map_IsComplement(p->pOutputs[i]); - pCut = pNode->pCutBest[fPosPol]; - if ( pCut == NULL ) - { - fPosPol = !fPosPol; - pCut = pNode->pCutBest[fPosPol]; - } - aFlowFlowTotal += pNode->pCutBest[fPosPol]->M[fPosPol].AreaFlow; - } - return aFlowFlowTotal; -} - - -/**Function************************************************************* - - Synopsis [Compares the supergates by their level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_CompareNodesByLevel( Map_Node_t ** ppS1, Map_Node_t ** ppS2 ) -{ - Map_Node_t * pN1 = Map_Regular(*ppS1); - Map_Node_t * pN2 = Map_Regular(*ppS2); - if ( pN1->Level > pN2->Level ) - return -1; - if ( pN1->Level < pN2->Level ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Orders the nodes in the decreasing order of levels.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingSortByLevel( Map_Man_t * pMan, Map_NodeVec_t * vNodes ) -{ - qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Map_Node_t *), - (int (*)(const void *, const void *)) Map_CompareNodesByLevel ); -// assert( Map_CompareNodesByLevel( vNodes->pArray, vNodes->pArray + vNodes->nSize - 1 ) <= 0 ); -} - - -/**Function************************************************************* - - Synopsis [Compares the supergates by their pointer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_CompareNodesByPointer( Map_Node_t ** ppS1, Map_Node_t ** ppS2 ) -{ - if ( *ppS1 < *ppS2 ) - return -1; - if ( *ppS1 > *ppS2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Counts how many AIG nodes are mapped in both polarities.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MappingCountDoubles( Map_Man_t * pMan, Map_NodeVec_t * vNodes ) -{ - Map_Node_t * pNode; - int Counter, i; - // count the number of equal adjacent nodes - Counter = 0; - for ( i = 0; i < vNodes->nSize; i++ ) - { - pNode = vNodes->pArray[i]; - if ( !Map_NodeIsAnd(pNode) ) - continue; - if ( (pNode->nRefAct[0] && pNode->pCutBest[0]) && - (pNode->nRefAct[1] && pNode->pCutBest[1]) ) - Counter++; - } - return Counter; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -st_table * Map_CreateTableGate2Super( Map_Man_t * pMan ) -{ - Map_Super_t * pSuper; - st_table * tTable; - int i, nInputs, v; - tTable = st_init_table(strcmp, st_strhash); - for ( i = 0; i < pMan->pSuperLib->nSupersAll; i++ ) - { - pSuper = pMan->pSuperLib->ppSupers[i]; - if ( pSuper->nGates == 1 ) - { - // skip different versions of the same root gate - nInputs = Mio_GateReadInputs(pSuper->pRoot); - for ( v = 0; v < nInputs; v++ ) - if ( pSuper->pFanins[v]->Num != nInputs - 1 - v ) - break; - if ( v != nInputs ) - continue; -// printf( "%s\n", Mio_GateReadName(pSuper->pRoot) ); - if ( st_insert( tTable, (char *)pSuper->pRoot, (char *)pSuper ) ) - { - assert( 0 ); - } - } - } - return tTable; -} - -/**Function************************************************************* - - Synopsis [Get the FRAIG node with phase.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_ManCleanData( Map_Man_t * p ) -{ - int i; - for ( i = 0; i < p->vNodesAll->nSize; i++ ) - p->vNodesAll->pArray[i]->pData0 = p->vNodesAll->pArray[i]->pData1 = 0; -} - -/**Function************************************************************* - - Synopsis [Expand the truth table] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingExpandTruth( unsigned uTruth[2], int nVars ) -{ - assert( nVars < 7 ); - if ( nVars == 6 ) - return; - if ( nVars < 5 ) - { - uTruth[0] &= MAP_MASK( (1<vAnds->nSize; i++ ) - { - // skip primary inputs - pNode = p->vAnds->pArray[i]; - if ( !Map_NodeIsAnd( pNode ) ) - continue; - // skip a secondary node - if ( pNode->pRepr ) - continue; - // count the switching nodes - if ( pNode->nRefAct[0] > 0 ) - Map_TimeCutComputeArrival( pNode, pNode->pCutBest[0], 0, MAP_FLOAT_LARGE ); - if ( pNode->nRefAct[1] > 0 ) - Map_TimeCutComputeArrival( pNode, pNode->pCutBest[1], 1, MAP_FLOAT_LARGE ); - } - Result = Map_TimeComputeArrivalMax(p); - printf( "Max arrival times with fanouts = %10.2f.\n", Result ); - return Result; -} - - -/**Function************************************************************* - - Synopsis [Sets up the mask.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MappingGetMaxLevel( Map_Man_t * pMan ) -{ - int nLevelMax, i; - nLevelMax = 0; - for ( i = 0; i < pMan->nOutputs; i++ ) - nLevelMax = ((unsigned)nLevelMax) > Map_Regular(pMan->pOutputs[i])->Level? - nLevelMax : Map_Regular(pMan->pOutputs[i])->Level; - return nLevelMax; -} - -/**Function************************************************************* - - Synopsis [Analyses choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MappingUpdateLevel_rec( Map_Man_t * pMan, Map_Node_t * pNode, int fMaximum ) -{ - Map_Node_t * pTemp; - int Level1, Level2, LevelE; - assert( !Map_IsComplement(pNode) ); - if ( !Map_NodeIsAnd(pNode) ) - return pNode->Level; - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return pNode->Level; - pNode->TravId = pMan->nTravIds; - // compute levels of the children nodes - Level1 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p1), fMaximum ); - Level2 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p2), fMaximum ); - pNode->Level = 1 + MAP_MAX( Level1, Level2 ); - if ( pNode->pNextE ) - { - LevelE = Map_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); - if ( fMaximum ) - { - if ( pNode->Level < (unsigned)LevelE ) - pNode->Level = LevelE; - } - else - { - if ( pNode->Level > (unsigned)LevelE ) - pNode->Level = LevelE; - } - // set the level of all equivalent nodes to be the same minimum - if ( pNode->pRepr == NULL ) // the primary node - for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) - pTemp->Level = pNode->Level; - } - return pNode->Level; -} - -/**Function************************************************************* - - Synopsis [Resets the levels of the nodes in the choice graph.] - - Description [Makes the level of the choice nodes to be equal to the - maximum of the level of the nodes in the equivalence class. This way - sorting by level leads to the reverse topological order, which is - needed for the required time computation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingSetChoiceLevels( Map_Man_t * pMan ) -{ - int i; - pMan->nTravIds++; - for ( i = 0; i < pMan->nOutputs; i++ ) - Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 1 ); -} - -/**Function************************************************************* - - Synopsis [Reports statistics on choice nodes.] - - Description [The number of choice nodes is the number of primary nodes, - which has pNextE set to a pointer. The number of choices is the number - of entries in the equivalent-node lists of the primary nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingReportChoices( Map_Man_t * pMan ) -{ - Map_Node_t * pNode, * pTemp; - int nChoiceNodes, nChoices; - int i, LevelMax1, LevelMax2; - - // report the number of levels - LevelMax1 = Map_MappingGetMaxLevel( pMan ); - pMan->nTravIds++; - for ( i = 0; i < pMan->nOutputs; i++ ) - Map_MappingUpdateLevel_rec( pMan, Map_Regular(pMan->pOutputs[i]), 0 ); - LevelMax2 = Map_MappingGetMaxLevel( pMan ); - - // report statistics about choices - nChoiceNodes = nChoices = 0; - for ( i = 0; i < pMan->vAnds->nSize; i++ ) - { - pNode = pMan->vAnds->pArray[i]; - if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) - { // this is a choice node = the primary node that has equivalent nodes - nChoiceNodes++; - for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) - nChoices++; - } - } - printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); - printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); -} - -/**Function************************************************************* - - Synopsis [Computes the maximum and minimum levels of the choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_MappingGetChoiceLevels( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2, int * pMin, int * pMax ) -{ - Map_NodeVec_t * vNodes; - Map_NodeVec_t * vBoundary; - Map_Node_t * pNode; - int i, Min, Max; - - vNodes = Map_NodeVecAlloc( 100 ); - vBoundary = Map_NodeVecAlloc( 100 ); - Map_MappingDfsMarked1_rec( p1, vNodes, 1 ); - Map_MappingDfsMarked2_rec( p2, vNodes, vBoundary, 1 ); - // clean the marks - Min = 100000; - Max = -100000; - for ( i = 0; i < vBoundary->nSize; i++ ) - { - pNode = vBoundary->pArray[i]; - if ( Min > (int)pNode->Level ) - Min = pNode->Level; - if ( Max < (int)pNode->Level ) - Max = pNode->Level; - } - Map_NodeVecFree( vBoundary ); - for ( i = 0; i < vNodes->nSize; i++ ) - { - pNode = vNodes->pArray[i]; - pNode->fMark0 = pNode->fMark1 = 0; - } - Map_NodeVecFree( vNodes ); - *pMin = Min; - *pMax = Max; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Map_MappingGetChoiceVolumes( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 ) -{ - Map_NodeVec_t * vNodes; - Map_Node_t * pNode; - int i, nVolumeTotal, nVolumeUnique; - - vNodes = Map_NodeVecAlloc( 100 ); - Map_MappingDfsMarked3_rec( p1, vNodes ); - Map_MappingDfsMarked4_rec( p2, vNodes ); - // clean the marks - nVolumeTotal = nVolumeUnique = 0; - for ( i = 0; i < vNodes->nSize; i++ ) - { - pNode = vNodes->pArray[i]; - if ( !Map_NodeIsAnd(pNode) ) - continue; - nVolumeTotal++; - if ( pNode->fMark0 ^ pNode->fMark1 ) - nVolumeUnique++; - pNode->fMark0 = pNode->fMark1 = 0; - } - Map_NodeVecFree( vNodes ); -// return ((float)nVolumeUnique)/nVolumeTotal; - return (float)nVolumeUnique; -} - - -/**Function************************************************************* - - Synopsis [Computes the maximum and minimum levels of the choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_MappingCountUsedNodes( Map_Man_t * pMan, int fChoices ) -{ - Map_NodeVec_t * vNodes; - int Result; - vNodes = Map_MappingDfs( pMan, fChoices ); - Result = vNodes->nSize; - Map_NodeVecFree( vNodes ); - return Result; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mapper/mapperVec.c b/src/map/mapper/mapperVec.c deleted file mode 100644 index f75138fb..00000000 --- a/src/map/mapper/mapperVec.c +++ /dev/null @@ -1,318 +0,0 @@ -/**CFile**************************************************************** - - FileName [mapperVec.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Generic technology mapping engine.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - June 1, 2004.] - - Revision [$Id: mapperVec.c,v 1.3 2005/01/23 06:59:45 alanmi Exp $] - -***********************************************************************/ - -#include "mapperInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_NodeVec_t * Map_NodeVecAlloc( int nCap ) -{ - Map_NodeVec_t * p; - p = ALLOC( Map_NodeVec_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( Map_Node_t *, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeVecFree( Map_NodeVec_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Node_t ** Map_NodeVecReadArray( Map_NodeVec_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_NodeVecReadSize( Map_NodeVec_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeVecGrow( Map_NodeVec_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( Map_Node_t *, p->pArray, nCapMin ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeVecShrink( Map_NodeVec_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeVecClear( Map_NodeVec_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeVecPush( Map_NodeVec_t * p, Map_Node_t * Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Map_NodeVecGrow( p, 16 ); - else - Map_NodeVecGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [Add the element while ensuring uniqueness.] - - Description [Returns 1 if the element was found, and 0 if it was new. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_NodeVecPushUnique( Map_NodeVec_t * p, Map_Node_t * Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Map_NodeVecPush( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Node_t * Map_NodeVecPop( Map_NodeVec_t * p ) -{ - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeVecRemove( Map_NodeVec_t * p, Map_Node_t * Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - break; - assert( i < p->nSize ); - for ( i++; i < p->nSize; i++ ) - p->pArray[i-1] = p->pArray[i]; - p->nSize--; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeVecWriteEntry( Map_NodeVec_t * p, int i, Map_Node_t * Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Map_Node_t * Map_NodeVecReadEntry( Map_NodeVec_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Map_NodeVecSortByLevel( Map_NodeVec_t * p ) -{ - qsort( (void *)p->pArray, p->nSize, sizeof(Map_Node_t *), - (int (*)(const void *, const void *)) Map_NodeVecCompareLevels ); -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Map_NodeVecCompareLevels( Map_Node_t ** pp1, Map_Node_t ** pp2 ) -{ - int Level1 = Map_Regular(*pp1)->Level; - int Level2 = Map_Regular(*pp2)->Level; - if ( Level1 < Level2 ) - return -1; - if ( Level1 > Level2 ) - return 1; - if ( Map_Regular(*pp1)->Num < Map_Regular(*pp2)->Num ) - return -1; - if ( Map_Regular(*pp1)->Num > Map_Regular(*pp2)->Num ) - return 1; - return 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/mapper/module.make b/src/map/mapper/module.make deleted file mode 100644 index bd6447d8..00000000 --- a/src/map/mapper/module.make +++ /dev/null @@ -1,18 +0,0 @@ -SRC += src/map/mapper/mapper.c \ - src/map/mapper/mapperCanon.c \ - src/map/mapper/mapperCore.c \ - src/map/mapper/mapperCreate.c \ - src/map/mapper/mapperCut.c \ - src/map/mapper/mapperCutUtils.c \ - src/map/mapper/mapperFanout.c \ - src/map/mapper/mapperLib.c \ - src/map/mapper/mapperMatch.c \ - src/map/mapper/mapperRefs.c \ - src/map/mapper/mapperSuper.c \ - src/map/mapper/mapperSwitch.c \ - src/map/mapper/mapperTable.c \ - src/map/mapper/mapperTime.c \ - src/map/mapper/mapperTree.c \ - src/map/mapper/mapperTruth.c \ - src/map/mapper/mapperUtils.c \ - src/map/mapper/mapperVec.c diff --git a/src/map/mio/mio.c b/src/map/mio/mio.c deleted file mode 100644 index 10a5af9d..00000000 --- a/src/map/mio/mio.c +++ /dev/null @@ -1,269 +0,0 @@ -/**CFile**************************************************************** - - FileName [mio.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [File reading/writing for technology mapping.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 18, 2003.] - - Revision [$Id: mio.c,v 1.4 2004/08/05 18:34:51 satrajit Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "mvc.h" -#include "mainInt.h" -#include "mioInt.h" -#include "mapper.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); -static int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ); - -// internal version of GENLIB library -static char * pMcncGenlib[25] = { - "GATE inv1 1 O=!a; PIN * INV 1 999 0.9 0.0 0.9 0.0\n", - "GATE inv2 2 O=!a; PIN * INV 2 999 1.0 0.0 1.0 0.0\n", - "GATE inv3 3 O=!a; PIN * INV 3 999 1.1 0.0 1.1 0.0\n", - "GATE inv4 4 O=!a; PIN * INV 4 999 1.2 0.0 1.2 0.0\n", - "GATE nand2 2 O=!(a*b); PIN * INV 1 999 1.0 0.0 1.0 0.0\n", - "GATE nand3 3 O=!(a*b*c); PIN * INV 1 999 1.1 0.0 1.1 0.0\n", - "GATE nand4 4 O=!(a*b*c*d); PIN * INV 1 999 1.4 0.0 1.4 0.0\n", - "GATE nor2 2 O=!(a+b); PIN * INV 1 999 1.4 0.0 1.4 0.0\n", - "GATE nor3 3 O=!(a+b+c); PIN * INV 1 999 2.4 0.0 2.4 0.0\n", - "GATE nor4 4 O=!(a+b+c+d); PIN * INV 1 999 3.8 0.0 3.8 0.0\n", - "GATE xora 5 O=a*!b+!a*b; PIN * UNKNOWN 2 999 1.9 0.0 1.9 0.0\n", - "GATE xorb 5 O=!(a*b+!a*!b); PIN * UNKNOWN 2 999 1.9 0.0 1.9 0.0\n", - "GATE xnora 5 O=a*b+!a*!b; PIN * UNKNOWN 2 999 2.1 0.0 2.1 0.0\n", - "GATE xnorb 5 O=!(!a*b+a*!b); PIN * UNKNOWN 2 999 2.1 0.0 2.1 0.0\n", - "GATE aoi21 3 O=!(a*b+c); PIN * INV 1 999 1.6 0.0 1.6 0.0\n", - "GATE aoi22 4 O=!(a*b+c*d); PIN * INV 1 999 2.0 0.0 2.0 0.0\n", - "GATE oai21 3 O=!((a+b)*c); PIN * INV 1 999 1.6 0.0 1.6 0.0\n", - "GATE oai22 4 O=!((a+b)*(c+d)); PIN * INV 1 999 2.0 0.0 2.0 0.0\n", - "GATE buf 1 O=a; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n", - "GATE zero 0 O=CONST0;\n", - "GATE one 0 O=CONST1;\n" -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_Init( Abc_Frame_t * pAbc ) -{ - char * pFileTemp = "mcnc_temp.genlib"; - Mio_Library_t * pLibGen; - FILE * pFile; - int i; - - // write genlib into file - pFile = fopen( pFileTemp, "w" ); - for ( i = 0; pMcncGenlib[i]; i++ ) - fputs( pMcncGenlib[i], pFile ); - fclose( pFile ); - // read genlib from file - pLibGen = Mio_LibraryRead( pAbc, pFileTemp, NULL, 0 ); - Abc_FrameSetLibGen( pLibGen ); -#ifdef WIN32 - _unlink( pFileTemp ); -#else - unlink( pFileTemp ); -#endif - - Cmd_CommandAdd( pAbc, "SC mapping", "read_library", Mio_CommandReadLibrary, 0 ); - Cmd_CommandAdd( pAbc, "SC mapping", "print_library", Mio_CommandPrintLibrary, 0 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_End() -{ -// Mio_LibraryDelete( s_pLib ); - Mio_LibraryDelete( Abc_FrameReadLibGen() ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mio_CommandReadLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - FILE * pFile; - FILE * pOut, * pErr; - Mio_Library_t * pLib; - Abc_Ntk_t * pNet; - char * FileName; - int fVerbose; - int c; - - pNet = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set the defaults - fVerbose = 1; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) - { - switch (c) - { - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - - if ( argc != globalUtilOptind + 1 ) - { - goto usage; - } - - // get the input file name - FileName = argv[globalUtilOptind]; - if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) - { - fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); - if ( (FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL )) ) - fprintf( pErr, "Did you mean \"%s\"?", FileName ); - fprintf( pErr, "\n" ); - return 1; - } - fclose( pFile ); - - // set the new network - pLib = Mio_LibraryRead( pAbc, FileName, 0, fVerbose ); - if ( pLib == NULL ) - { - fprintf( pErr, "Reading GENLIB library has failed.\n" ); - return 1; - } - // free the current superlib because it depends on the old Mio library - if ( Abc_FrameReadLibSuper() ) - { - extern void Map_SuperLibFree( Map_SuperLib_t * p ); -// Map_SuperLibFree( s_pSuperLib ); -// s_pSuperLib = NULL; - Map_SuperLibFree( Abc_FrameReadLibSuper() ); - Abc_FrameSetLibSuper( NULL ); - } - - // replace the current library -// Mio_LibraryDelete( s_pLib ); -// s_pLib = pLib; - Mio_LibraryDelete( Abc_FrameReadLibGen() ); - Abc_FrameSetLibGen( pLib ); - return 0; - -usage: - fprintf( pErr, "usage: read_library [-vh]\n"); - fprintf( pErr, "\t read the library from a genlib file\n" ); - fprintf( pErr, "\t-h : enable verbose output\n"); - return 1; /* error exit */ -} - - -/**Function************************************************************* - - Synopsis [Command procedure to read LUT libraries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mio_CommandPrintLibrary( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - FILE * pOut, * pErr; - Abc_Ntk_t * pNet; - int fVerbose; - int c; - - pNet = Abc_FrameReadNtk(pAbc); - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set the defaults - fVerbose = 1; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "vh")) != EOF ) - { - switch (c) - { - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - - if ( argc != globalUtilOptind ) - { - goto usage; - } - - // set the new network - Mio_WriteLibrary( stdout, Abc_FrameReadLibGen(), 0 ); - return 0; - -usage: - fprintf( pErr, "\nusage: print_library [-vh]\n"); - fprintf( pErr, "\t print the current genlib library\n" ); - fprintf( pErr, "\t-v : toggles enabling of verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); - fprintf( pErr, "\t-h : print the command usage\n"); - return 1; /* error exit */ -} -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mio/mio.h b/src/map/mio/mio.h deleted file mode 100644 index dbe2420b..00000000 --- a/src/map/mio/mio.h +++ /dev/null @@ -1,150 +0,0 @@ -/**CFile**************************************************************** - - FileName [mio.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [File reading/writing for technology mapping.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: mio.h,v 1.6 2004/08/09 22:16:31 satrajit Exp $] - -***********************************************************************/ - -#ifndef __MIO_H__ -#define __MIO_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef enum { MIO_PHASE_UNKNOWN, MIO_PHASE_INV, MIO_PHASE_NONINV } Mio_PinPhase_t; - -typedef struct Mio_LibraryStruct_t_ Mio_Library_t; -typedef struct Mio_GateStruct_t_ Mio_Gate_t; -typedef struct Mio_PinStruct_t_ Mio_Pin_t; - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Mio_LibraryForEachGate( Lib, Gate ) \ - for ( Gate = Mio_LibraryReadGates(Lib); \ - Gate; \ - Gate = Mio_GateReadNext(Gate) ) -#define Mio_LibraryForEachGateSafe( Lib, Gate, Gate2 ) \ - for ( Gate = Mio_LibraryReadGates(Lib), \ - Gate2 = (Gate? Mio_GateReadNext(Gate): NULL); \ - Gate; \ - Gate = Gate2, \ - Gate2 = (Gate? Mio_GateReadNext(Gate): NULL) ) - -#define Mio_GateForEachPin( Gate, Pin ) \ - for ( Pin = Mio_GateReadPins(Gate); \ - Pin; \ - Pin = Mio_PinReadNext(Pin) ) -#define Mio_GateForEachPinSafe( Gate, Pin, Pin2 ) \ - for ( Pin = Mio_GateReadPins(Gate), \ - Pin2 = (Pin? Mio_PinReadNext(Pin): NULL); \ - Pin; \ - Pin = Pin2, \ - Pin2 = (Pin? Mio_PinReadNext(Pin): NULL) ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== mioApi.c =============================================================*/ -extern char * Mio_LibraryReadName ( Mio_Library_t * pLib ); -extern int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ); -extern Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ); -extern DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib ); -extern Mio_Gate_t * Mio_LibraryReadGateByName ( Mio_Library_t * pLib, char * pName ); -extern char * Mio_LibraryReadSopByName ( Mio_Library_t * pLib, char * pName ); -extern Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib ); -extern Mio_Gate_t * Mio_LibraryReadConst1 ( Mio_Library_t * pLib ); -extern Mio_Gate_t * Mio_LibraryReadNand2 ( Mio_Library_t * pLib ); -extern Mio_Gate_t * Mio_LibraryReadAnd2 ( Mio_Library_t * pLib ); -extern Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib ); -extern Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib ); -extern float Mio_LibraryReadDelayInvRise( Mio_Library_t * pLib ); -extern float Mio_LibraryReadDelayInvFall( Mio_Library_t * pLib ); -extern float Mio_LibraryReadDelayInvMax( Mio_Library_t * pLib ); -extern float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib ); -extern float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib ); -extern float Mio_LibraryReadDelayNand2Max( Mio_Library_t * pLib ); -extern float Mio_LibraryReadDelayAnd2Max( Mio_Library_t * pLib ); -extern float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib ); -extern float Mio_LibraryReadAreaBuf ( Mio_Library_t * pLib ); -extern float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib ); -extern int Mio_LibraryReadGateNameMax( Mio_Library_t * pLib ); -extern char * Mio_GateReadName ( Mio_Gate_t * pGate ); -extern char * Mio_GateReadOutName ( Mio_Gate_t * pGate ); -extern double Mio_GateReadArea ( Mio_Gate_t * pGate ); -extern char * Mio_GateReadForm ( Mio_Gate_t * pGate ); -extern Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate ); -extern Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate ); -extern Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate ); -extern int Mio_GateReadInputs ( Mio_Gate_t * pGate ); -extern double Mio_GateReadDelayMax ( Mio_Gate_t * pGate ); -extern char * Mio_GateReadSop ( Mio_Gate_t * pGate ); -extern DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate ); -extern char * Mio_PinReadName ( Mio_Pin_t * pPin ); -extern Mio_PinPhase_t Mio_PinReadPhase ( Mio_Pin_t * pPin ); -extern double Mio_PinReadInputLoad ( Mio_Pin_t * pPin ); -extern double Mio_PinReadMaxLoad ( Mio_Pin_t * pPin ); -extern double Mio_PinReadDelayBlockRise ( Mio_Pin_t * pPin ); -extern double Mio_PinReadDelayFanoutRise( Mio_Pin_t * pPin ); -extern double Mio_PinReadDelayBlockFall ( Mio_Pin_t * pPin ); -extern double Mio_PinReadDelayFanoutFall( Mio_Pin_t * pPin ); -extern double Mio_PinReadDelayBlockMax ( Mio_Pin_t * pPin ); -extern Mio_Pin_t * Mio_PinReadNext ( Mio_Pin_t * pPin ); -/*=== mioRead.c =============================================================*/ -extern Mio_Library_t * Mio_LibraryRead( void * pAbc, char * FileName, char * ExcludeFile, int fVerbose ); -extern int Mio_LibraryReadExclude( void * pAbc, char * ExcludeFile, st_table * tExcludeGate ); -/*=== mioFunc.c =============================================================*/ -extern int Mio_LibraryParseFormulas( Mio_Library_t * pLib ); -/*=== mioUtils.c =============================================================*/ -extern void Mio_LibraryDelete( Mio_Library_t * pLib ); -extern void Mio_GateDelete( Mio_Gate_t * pGate ); -extern void Mio_PinDelete( Mio_Pin_t * pPin ); -extern Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin ); -extern void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops ); -extern Mio_Gate_t ** Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, bool fSkipInv, int * pnGates ); -extern void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] ); -extern void Mio_DeriveGateDelays( Mio_Gate_t * pGate, - float ** ptPinDelays, int nPins, int nInputs, float tDelayZero, - float * ptDelaysRes, float * ptPinDelayMax ); -extern Mio_Gate_t * Mio_GateCreatePseudo( int nInputs ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/mio/mioApi.c b/src/map/mio/mioApi.c deleted file mode 100644 index 73473f8b..00000000 --- a/src/map/mio/mioApi.c +++ /dev/null @@ -1,172 +0,0 @@ -/**CFile**************************************************************** - - FileName [mioApi.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [File reading/writing for technology mapping.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: mioApi.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $] - -***********************************************************************/ - -#include "mioInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Mio_LibraryReadName ( Mio_Library_t * pLib ) { return pLib->pName; } -int Mio_LibraryReadGateNum ( Mio_Library_t * pLib ) { return pLib->nGates; } -Mio_Gate_t * Mio_LibraryReadGates ( Mio_Library_t * pLib ) { return pLib->pGates; } -DdManager * Mio_LibraryReadDd ( Mio_Library_t * pLib ) { return pLib->dd; } -Mio_Gate_t * Mio_LibraryReadBuf ( Mio_Library_t * pLib ) { return pLib->pGateBuf; } -Mio_Gate_t * Mio_LibraryReadInv ( Mio_Library_t * pLib ) { return pLib->pGateInv; } -Mio_Gate_t * Mio_LibraryReadConst0 ( Mio_Library_t * pLib ) { return pLib->pGate0; } -Mio_Gate_t * Mio_LibraryReadConst1 ( Mio_Library_t * pLib ) { return pLib->pGate1; } -Mio_Gate_t * Mio_LibraryReadNand2 ( Mio_Library_t * pLib ) { return pLib->pGateNand2; } -Mio_Gate_t * Mio_LibraryReadAnd2 ( Mio_Library_t * pLib ) { return pLib->pGateAnd2; } -float Mio_LibraryReadDelayInvRise ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockRise : 0.0); } -float Mio_LibraryReadDelayInvFall ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockFall : 0.0); } -float Mio_LibraryReadDelayInvMax ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->pPins->dDelayBlockMax : 0.0); } -float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockRise : 0.0); } -float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockFall : 0.0); } -float Mio_LibraryReadDelayNand2Max ( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockMax : 0.0); } -float Mio_LibraryReadDelayAnd2Max ( Mio_Library_t * pLib ) { return (float)(pLib->pGateAnd2? pLib->pGateAnd2->pPins->dDelayBlockMax : 0.0); } -float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->dArea : 0.0); } -float Mio_LibraryReadAreaBuf ( Mio_Library_t * pLib ) { return (float)(pLib->pGateBuf? pLib->pGateBuf->dArea : 0.0); } -float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->dArea : 0.0); } - -/**Function************************************************************* - - Synopsis [Returns the longest gate name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mio_LibraryReadGateNameMax( Mio_Library_t * pLib ) -{ - Mio_Gate_t * pGate; - int LenMax = 0, LenCur; - Mio_LibraryForEachGate( pLib, pGate ) - { - LenCur = strlen( Mio_GateReadName(pGate) ); - if ( LenMax < LenCur ) - LenMax = LenCur; - } - return LenMax; -} - -/**Function************************************************************* - - Synopsis [Read Mvc of the gate by name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mio_Gate_t * Mio_LibraryReadGateByName( Mio_Library_t * pLib, char * pName ) -{ - Mio_Gate_t * pGate; - if ( st_lookup( pLib->tName2Gate, pName, (char **)&pGate ) ) - return pGate; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Read Mvc of the gate by name.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Mio_LibraryReadSopByName( Mio_Library_t * pLib, char * pName ) -{ - Mio_Gate_t * pGate; - if ( st_lookup( pLib->tName2Gate, pName, (char **)&pGate ) ) - return pGate->pSop; - return NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Mio_GateReadName ( Mio_Gate_t * pGate ) { return pGate->pName; } -char * Mio_GateReadOutName ( Mio_Gate_t * pGate ) { return pGate->pOutName; } -double Mio_GateReadArea ( Mio_Gate_t * pGate ) { return pGate->dArea; } -char * Mio_GateReadForm ( Mio_Gate_t * pGate ) { return pGate->pForm; } -Mio_Pin_t * Mio_GateReadPins ( Mio_Gate_t * pGate ) { return pGate->pPins; } -Mio_Library_t * Mio_GateReadLib ( Mio_Gate_t * pGate ) { return pGate->pLib; } -Mio_Gate_t * Mio_GateReadNext ( Mio_Gate_t * pGate ) { return pGate->pNext; } -int Mio_GateReadInputs ( Mio_Gate_t * pGate ) { return pGate->nInputs; } -double Mio_GateReadDelayMax( Mio_Gate_t * pGate ) { return pGate->dDelayMax; } -char * Mio_GateReadSop ( Mio_Gate_t * pGate ) { return pGate->pSop; } -DdNode * Mio_GateReadFunc ( Mio_Gate_t * pGate ) { return pGate->bFunc; } - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Mio_PinReadName ( Mio_Pin_t * pPin ) { return pPin->pName; } -Mio_PinPhase_t Mio_PinReadPhase ( Mio_Pin_t * pPin ) { return pPin->Phase; } -double Mio_PinReadInputLoad ( Mio_Pin_t * pPin ) { return pPin->dLoadInput; } -double Mio_PinReadMaxLoad ( Mio_Pin_t * pPin ) { return pPin->dLoadMax; } -double Mio_PinReadDelayBlockRise ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockRise; } -double Mio_PinReadDelayFanoutRise( Mio_Pin_t * pPin ) { return pPin->dDelayFanoutRise;} -double Mio_PinReadDelayBlockFall ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockFall; } -double Mio_PinReadDelayFanoutFall( Mio_Pin_t * pPin ) { return pPin->dDelayFanoutFall;} -double Mio_PinReadDelayBlockMax ( Mio_Pin_t * pPin ) { return pPin->dDelayBlockMax; } -Mio_Pin_t * Mio_PinReadNext ( Mio_Pin_t * pPin ) { return pPin->pNext; } - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mio/mioFunc.c b/src/map/mio/mioFunc.c deleted file mode 100644 index 21a078f9..00000000 --- a/src/map/mio/mioFunc.c +++ /dev/null @@ -1,268 +0,0 @@ -/**CFile**************************************************************** - - FileName [mioFunc.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [File reading/writing for technology mapping.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: mioFunc.c,v 1.4 2004/06/28 14:20:25 alanmi Exp $] - -***********************************************************************/ - -#include "mioInt.h" -#include "parse.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// these symbols (and no other) can appear in the formulas -#define MIO_SYMB_AND '*' -#define MIO_SYMB_OR '+' -#define MIO_SYMB_NOT '!' -#define MIO_SYMB_AFTNOT '\'' -#define MIO_SYMB_OPEN '(' -#define MIO_SYMB_CLOSE ')' - -static int Mio_GateParseFormula( Mio_Gate_t * pGate ); -static int Mio_GateCollectNames( char * pFormula, char * pPinNames[] ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Deriving the functionality of the gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mio_LibraryParseFormulas( Mio_Library_t * pLib ) -{ - Mio_Gate_t * pGate; - - // count the gates - pLib->nGates = 0; - Mio_LibraryForEachGate( pLib, pGate ) - pLib->nGates++; - - // start a temporary BDD manager - pLib->dd = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - // introduce ZDD variables - Cudd_zddVarsFromBddVars( pLib->dd, 2 ); - - // for each gate, derive its function - Mio_LibraryForEachGate( pLib, pGate ) - if ( Mio_GateParseFormula( pGate ) ) - return 1; - return 0; -} - - -/**Function************************************************************* - - Synopsis [Deriving the functionality of the gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mio_GateParseFormula( Mio_Gate_t * pGate ) -{ - DdManager * dd = pGate->pLib->dd; - char * pPinNames[100]; - char * pPinNamesCopy[100]; - Mio_Pin_t * pPin, ** ppPin; - int nPins, iPin, i; - - // set the maximum delay of the gate; count pins - pGate->dDelayMax = 0.0; - nPins = 0; - Mio_GateForEachPin( pGate, pPin ) - { - // set the maximum delay of the gate - if ( pGate->dDelayMax < pPin->dDelayBlockMax ) - pGate->dDelayMax = pPin->dDelayBlockMax; - // count the pin - nPins++; - } - - // check for the gate with const function - if ( nPins == 0 ) - { - if ( strcmp( pGate->pForm, MIO_STRING_CONST0 ) == 0 ) - { - pGate->bFunc = b0; - pGate->pSop = Abc_SopRegister( pGate->pLib->pMmFlex, " 0\n" ); - pGate->pLib->pGate0 = pGate; - } - else if ( strcmp( pGate->pForm, MIO_STRING_CONST1 ) == 0 ) - { - pGate->bFunc = b1; - pGate->pSop = Abc_SopRegister( pGate->pLib->pMmFlex, " 1\n" ); - pGate->pLib->pGate1 = pGate; - } - else - { - printf( "Cannot parse formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName ); - return 1; - } - Cudd_Ref( pGate->bFunc ); - return 0; - } - - // collect the names as they appear in the formula - nPins = Mio_GateCollectNames( pGate->pForm, pPinNames ); - if ( nPins == 0 ) - { - printf( "Cannot read formula \"%s\" of gate \"%s\".\n", pGate->pForm, pGate->pName ); - return 1; - } - - // set the number of inputs - pGate->nInputs = nPins; - - // consider the case when all the pins have identical pin info - if ( strcmp( pGate->pPins->pName, "*" ) == 0 ) - { - // get the topmost (generic) pin - pPin = pGate->pPins; - FREE( pPin->pName ); - - // create individual pins from the generic pin - ppPin = &pPin->pNext; - for ( i = 1; i < nPins; i++ ) - { - // get the new pin - *ppPin = Mio_PinDup( pPin ); - // set its name - (*ppPin)->pName = pPinNames[i]; - // prepare the next place in the list - ppPin = &((*ppPin)->pNext); - } - *ppPin = NULL; - - // set the name of the topmost pin - pPin->pName = pPinNames[0]; - } - else - { - // reorder the variable names to appear the save way as the pins - iPin = 0; - Mio_GateForEachPin( pGate, pPin ) - { - // find the pin with the name pPin->pName - for ( i = 0; i < nPins; i++ ) - { - if ( pPinNames[i] && strcmp( pPinNames[i], pPin->pName ) == 0 ) - { - // free pPinNames[i] because it is already available as pPin->pName - // setting pPinNames[i] to NULL is useful to make sure that - // this name is not assigned to two pins in the list - FREE( pPinNames[i] ); - pPinNamesCopy[iPin++] = pPin->pName; - break; - } - if ( i == nPins ) - { - printf( "Cannot find pin name \"%s\" in the formula \"%s\" of gate \"%s\".\n", - pPin->pName, pGate->pForm, pGate->pName ); - return 1; - } - } - } - - // check for the remaining names - for ( i = 0; i < nPins; i++ ) - if ( pPinNames[i] ) - { - printf( "Name \"%s\" appears in the formula \"%s\" of gate \"%s\" but there is no such pin.\n", - pPinNames[i], pGate->pForm, pGate->pName ); - return 1; - } - - // copy the names back - memcpy( pPinNames, pPinNamesCopy, nPins * sizeof(char *) ); - } - - // expand the manager if necessary - if ( dd->size < nPins ) - { - Cudd_Quit( dd ); - dd = Cudd_Init( nPins + 10, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); - Cudd_zddVarsFromBddVars( dd, 2 ); - } - - // derive the formula as the BDD - pGate->bFunc = Parse_FormulaParser( stdout, pGate->pForm, nPins, 0, pPinNames, dd, dd->vars ); - Cudd_Ref( pGate->bFunc ); - - // derive the cover (SOP) - pGate->pSop = Abc_ConvertBddToSop( pGate->pLib->pMmFlex, dd, pGate->bFunc, pGate->bFunc, nPins, 0, pGate->pLib->vCube, -1 ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Collect the pin names in the formula.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mio_GateCollectNames( char * pFormula, char * pPinNames[] ) -{ - char Buffer[1000]; - char * pTemp; - int nPins, i; - - // save the formula as it was - strcpy( Buffer, pFormula ); - - // remove the non-name symbols - for ( pTemp = Buffer; *pTemp; pTemp++ ) - if ( *pTemp == MIO_SYMB_AND || *pTemp == MIO_SYMB_OR || *pTemp == MIO_SYMB_NOT - || *pTemp == MIO_SYMB_OPEN || *pTemp == MIO_SYMB_CLOSE || *pTemp == MIO_SYMB_AFTNOT ) - *pTemp = ' '; - - // save the names - nPins = 0; - pTemp = strtok( Buffer, " " ); - while ( pTemp ) - { - for ( i = 0; i < nPins; i++ ) - if ( strcmp( pTemp, pPinNames[i] ) == 0 ) - break; - if ( i == nPins ) - { // cannot find this name; save it - pPinNames[nPins++] = Extra_UtilStrsav(pTemp); - } - // get the next name - pTemp = strtok( NULL, " " ); - } - return nPins; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mio/mioGENERIC.c b/src/map/mio/mioGENERIC.c deleted file mode 100644 index 972c4ffc..00000000 --- a/src/map/mio/mioGENERIC.c +++ /dev/null @@ -1,46 +0,0 @@ -/**CFile**************************************************************** - - FileName [mio___.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [File reading/writing for technology mapping.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: mio___.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "mioInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mio/mioInt.h b/src/map/mio/mioInt.h deleted file mode 100644 index 3f90b625..00000000 --- a/src/map/mio/mioInt.h +++ /dev/null @@ -1,125 +0,0 @@ -/**CFile**************************************************************** - - FileName [mioInt.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [File reading/writing for technology mapping.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: mioInt.h,v 1.4 2004/06/28 14:20:25 alanmi Exp $] - -***********************************************************************/ - -#ifndef __MIO_INT_H__ -#define __MIO_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "abc.h" -#include "mvc.h" -#include "main.h" -#include "mio.h" -#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -#define MIO_STRING_GATE "GATE" -#define MIO_STRING_PIN "PIN" -#define MIO_STRING_NONINV "NONINV" -#define MIO_STRING_INV "INV" -#define MIO_STRING_UNKNOWN "UNKNOWN" - -#define MIO_STRING_CONST0 "CONST0" -#define MIO_STRING_CONST1 "CONST1" - -// the bit masks -#define MIO_MASK(n) ((~((unsigned)0)) >> (32-(n))) -#define MIO_FULL (~((unsigned)0)) - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Mio_LibraryStruct_t_ -{ - char * pName; // the name of the library - int nGates; // the number of the gates - Mio_Gate_t * pGates; // the linked list of all gates in no particular order - Mio_Gate_t * pGate0; // the constant zero gate - Mio_Gate_t * pGate1; // the constant one gate - Mio_Gate_t * pGateBuf; // the buffer - Mio_Gate_t * pGateInv; // the inverter - Mio_Gate_t * pGateNand2; // the NAND2 gate - Mio_Gate_t * pGateAnd2; // the AND2 gate - st_table * tName2Gate; // the mapping of gate names into their pointer - DdManager * dd; // the nanager storing functions of gates - Extra_MmFlex_t * pMmFlex; // the memory manaqer for SOPs - Vec_Str_t * vCube; // temporary cube -}; - -struct Mio_GateStruct_t_ -{ - // information derived from the genlib file - char * pName; // the name of the gate - double dArea; // the area of the gate - char * pForm; // the formula describing functionality of the gate - Mio_Pin_t * pPins; // the linked list of all pins (one pin if info is the same) - char * pOutName; // the name of the output pin - // the library to which this gate belongs - Mio_Library_t * pLib; - // the next gate in the list - Mio_Gate_t * pNext; - - // the derived information - int nInputs; // the number of inputs - double dDelayMax; // the maximum delay - DdNode * bFunc; // the functionality - char * pSop; -}; - -struct Mio_PinStruct_t_ -{ - char * pName; - Mio_PinPhase_t Phase; - double dLoadInput; - double dLoadMax; - double dDelayBlockRise; - double dDelayFanoutRise; - double dDelayBlockFall; - double dDelayFanoutFall; - double dDelayBlockMax; - Mio_Pin_t * pNext; -}; - - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== mio.c =============================================================*/ -/*=== mioRead.c =============================================================*/ -/*=== mioUtils.c =============================================================*/ - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/map/mio/mioRead.c b/src/map/mio/mioRead.c deleted file mode 100644 index 13c2cdcd..00000000 --- a/src/map/mio/mioRead.c +++ /dev/null @@ -1,582 +0,0 @@ -/**CFile**************************************************************** - - FileName [mioRead.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [File reading/writing for technology mapping.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: mioRead.c,v 1.9 2004/10/19 06:40:16 satrajit Exp $] - -***********************************************************************/ - -#include "mioInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -static Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose ); -static int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose ); -static Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat ); -static Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, bool fExtendedFormat ); -static char * chomp( char *s ); -static void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib ); -static void Io_ReadFileRemoveComments( char * pBuffer, int * pnDots, int * pnLines ); - -#ifdef WIN32 -extern int isspace( int c ); // to silence the warning in VS -#endif - -/**Function************************************************************* - - Synopsis [Read the genlib type of library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mio_Library_t * Mio_LibraryRead( void * pAbc, char * FileName, char * ExcludeFile, int fVerbose ) -{ - Mio_Library_t * pLib; - int num; - - st_table * tExcludeGate = 0; - - if ( ExcludeFile ) - { - tExcludeGate = st_init_table(strcmp, st_strhash); - if ( (num = Mio_LibraryReadExclude( pAbc, ExcludeFile, tExcludeGate )) == -1 ) - { - st_free_table( tExcludeGate ); - tExcludeGate = 0; - return 0; - } - - fprintf ( Abc_FrameReadOut( pAbc ), "Read %d gates from exclude file\n", num ); - } - - pLib = Mio_LibraryReadOne( pAbc, FileName, 0, tExcludeGate, fVerbose ); // try normal format first .. - if ( pLib == NULL ) - { - pLib = Mio_LibraryReadOne( pAbc, FileName, 1, tExcludeGate, fVerbose ); // .. otherwise try extended format - if ( pLib != NULL ) - printf ( "Warning: Read extended GENLIB format but ignoring extensions\n" ); - } - - return pLib; -} - -/**Function************************************************************* - - Synopsis [Read the genlib type of library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mio_Library_t * Mio_LibraryReadOne( Abc_Frame_t * pAbc, char * FileName, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose ) -{ - Mio_Library_t * pLib; - char * pBuffer = 0; - - // allocate the genlib structure - pLib = ALLOC( Mio_Library_t, 1 ); - memset( pLib, 0, sizeof(Mio_Library_t) ); - pLib->pName = Extra_UtilStrsav( FileName ); - pLib->tName2Gate = st_init_table(strcmp, st_strhash); - pLib->pMmFlex = Extra_MmFlexStart(); - pLib->vCube = Vec_StrAlloc( 100 ); - - // read the file and clean comments - // pBuffer = Io_ReadFileFileContents( FileName, NULL ); - // we don't use above function but actually do the same thing explicitly - // to handle open_path expansion correctly - - { - FILE * pFile; - int nFileSize; - - // open the BLIF file for binary reading - pFile = Io_FileOpen( FileName, "open_path", "rb", 1 ); -// pFile = fopen( FileName, "rb" ); - // if we got this far, file should be okay otherwise would - // have been detected by caller - assert ( pFile != NULL ); - // get the file size, in bytes - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - // move the file current reading position to the beginning - rewind( pFile ); - // load the contents of the file into memory - pBuffer = ALLOC( char, nFileSize + 10 ); - fread( pBuffer, nFileSize, 1, pFile ); - // terminate the string with '\0' - pBuffer[ nFileSize ] = '\0'; - strcat( pBuffer, "\n.end\n" ); - // close file - fclose( pFile ); - } - - Io_ReadFileRemoveComments( pBuffer, NULL, NULL ); - - // parse the contents of the file - if ( Mio_LibraryReadInternal( pLib, pBuffer, fExtendedFormat, tExcludeGate, fVerbose ) ) - { - Mio_LibraryDelete( pLib ); - free( pBuffer ); - return NULL; - } - free( pBuffer ); - - // derive the functinality of gates - if ( Mio_LibraryParseFormulas( pLib ) ) - { - printf( "Mio_LibraryRead: Had problems parsing formulas.\n" ); - Mio_LibraryDelete( pLib ); - return NULL; - } - - // detect INV and NAND2 - Mio_LibraryDetectSpecialGates( pLib ); -//Mio_WriteLibrary( stdout, pLib ); - return pLib; -} - -/**Function************************************************************* - - Synopsis [Read the genlib type of library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mio_LibraryReadInternal( Mio_Library_t * pLib, char * pBuffer, bool fExtendedFormat, st_table * tExcludeGate, int fVerbose ) -{ - Mio_Gate_t * pGate, ** ppGate; - char * pToken; - int nGates = 0; - int nDel = 0; - - // start the linked list of gates - pLib->pGates = NULL; - ppGate = &pLib->pGates; - - // read gates one by one - pToken = strtok( pBuffer, " \t\r\n" ); - while ( pToken && strcmp( pToken, MIO_STRING_GATE ) == 0 ) - { - // derive the next gate - pGate = Mio_LibraryReadGate( &pToken, fExtendedFormat ); - if ( pGate == NULL ) - return 1; - - // set the library - pGate->pLib = pLib; - - // printf ("Processing: '%s'\n", pGate->pName); - - if ( tExcludeGate && st_is_member( tExcludeGate, pGate->pName ) ) - { - //printf ("Excluding: '%s'\n", pGate->pName); - Mio_GateDelete( pGate ); - nDel++; - } - else - { - // add this gate to the list - *ppGate = pGate; - ppGate = &pGate->pNext; - nGates++; - - // remember this gate by name - if ( !st_is_member( pLib->tName2Gate, pGate->pName ) ) - st_insert( pLib->tName2Gate, pGate->pName, (char *)pGate ); - else - printf( "The gate with name \"%s\" appears more than once.\n", pGate->pName ); - } - } - if ( fVerbose ) - printf( "The number of gates read = %d.\n", nGates ); - - // check what is the last word read - if ( pToken && strcmp( pToken, ".end" ) != 0 ) - return 1; - - if ( nDel != 0 ) - printf( "Actually excluded %d cells\n", nDel ); - - return 0; -} - -/**Function************************************************************* - - Synopsis [Read the genlib type of gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mio_Gate_t * Mio_LibraryReadGate( char ** ppToken, bool fExtendedFormat ) -{ - Mio_Gate_t * pGate; - Mio_Pin_t * pPin, ** ppPin; - char * pToken = *ppToken; - - // allocate the gate structure - pGate = ALLOC( Mio_Gate_t, 1 ); - memset( pGate, 0, sizeof(Mio_Gate_t) ); - - // read the name - pToken = strtok( NULL, " \t\r\n" ); - pGate->pName = Extra_UtilStrsav( pToken ); - - // read the area - pToken = strtok( NULL, " \t\r\n" ); - pGate->dArea = atof( pToken ); - - // read the formula - - // first the output name - pToken = strtok( NULL, "=" ); - pGate->pOutName = chomp( pToken ); - - // then rest of the expression - pToken = strtok( NULL, ";" ); - pGate->pForm = Extra_UtilStrsav( pToken ); - - // read the pin info - // start the linked list of pins - pGate->pPins = NULL; - ppPin = &pGate->pPins; - - // read gates one by one - pToken = strtok( NULL, " \t\r\n" ); - while ( pToken && strcmp( pToken, MIO_STRING_PIN ) == 0 ) - { - // derive the next gate - pPin = Mio_LibraryReadPin( &pToken, fExtendedFormat ); - if ( pPin == NULL ) - { - Mio_GateDelete( pGate ); - *ppToken = pToken; - return NULL; - } - // add this pin to the list - *ppPin = pPin; - ppPin = &pPin->pNext; - // get the next token - pToken = strtok( NULL, " \t\r\n" ); - } - - *ppToken = pToken; - return pGate; -} - - - -/**Function************************************************************* - - Synopsis [Read the genlib type of pin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mio_Pin_t * Mio_LibraryReadPin( char ** ppToken, bool fExtendedFormat ) -{ - Mio_Pin_t * pPin; - char * pToken = *ppToken; - - // allocate the gate structure - pPin = ALLOC( Mio_Pin_t, 1 ); - memset( pPin, 0, sizeof(Mio_Pin_t) ); - - // read the name - pToken = strtok( NULL, " \t\r\n" ); - pPin->pName = Extra_UtilStrsav( pToken ); - - // read the pin phase - pToken = strtok( NULL, " \t\r\n" ); - if ( strcmp( pToken, MIO_STRING_UNKNOWN ) == 0 ) - pPin->Phase = MIO_PHASE_UNKNOWN; - else if ( strcmp( pToken, MIO_STRING_INV ) == 0 ) - pPin->Phase = MIO_PHASE_INV; - else if ( strcmp( pToken, MIO_STRING_NONINV ) == 0 ) - pPin->Phase = MIO_PHASE_NONINV; - else - { - printf( "Cannot read pin phase specification\n" ); - Mio_PinDelete( pPin ); - *ppToken = pToken; - return NULL; - } - - pToken = strtok( NULL, " \t\r\n" ); - pPin->dLoadInput = atof( pToken ); - - pToken = strtok( NULL, " \t\r\n" ); - pPin->dLoadMax = atof( pToken ); - - pToken = strtok( NULL, " \t\r\n" ); - pPin->dDelayBlockRise = atof( pToken ); - - pToken = strtok( NULL, " \t\r\n" ); - pPin->dDelayFanoutRise = atof( pToken ); - - pToken = strtok( NULL, " \t\r\n" ); - pPin->dDelayBlockFall = atof( pToken ); - - pToken = strtok( NULL, " \t\r\n" ); - pPin->dDelayFanoutFall = atof( pToken ); - - if ( fExtendedFormat ) - { - /* In extended format, the field after dDelayFanoutRise - * is to be ignored - **/ - - pPin->dDelayBlockFall = pPin->dDelayFanoutFall; - - pToken = strtok( NULL, " \t" ); - pPin->dDelayFanoutFall = atof( pToken ); - - /* last field is ignored */ - pToken = strtok( NULL, " \t\r\n" ); - } - - if ( pPin->dDelayBlockRise > pPin->dDelayBlockFall ) - pPin->dDelayBlockMax = pPin->dDelayBlockRise; - else - pPin->dDelayBlockMax = pPin->dDelayBlockFall; - - *ppToken = pToken; - return pPin; -} - - -/**Function************************************************************* - - Synopsis [Duplicates string and returns it with leading and - trailing spaces removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char *chomp( char *s ) -{ - char *b = ALLOC(char, strlen(s)+1), *c = b; - while (*s && isspace(*s)) - ++s; - while (*s && !isspace(*s)) - *c++ = *s++; - *c = 0; - return b; -} - -/**Function************************************************************* - - Synopsis [Duplicates string and returns it with leading and - trailing spaces removed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_LibraryDetectSpecialGates( Mio_Library_t * pLib ) -{ - Mio_Gate_t * pGate; - DdNode * bFuncBuf, * bFuncInv, * bFuncNand2, * bFuncAnd2; - - bFuncBuf = pLib->dd->vars[0]; Cudd_Ref( bFuncBuf ); - bFuncInv = Cudd_Not( pLib->dd->vars[0] ); Cudd_Ref( bFuncInv ); - bFuncNand2 = Cudd_bddNand( pLib->dd, pLib->dd->vars[0], pLib->dd->vars[1] ); Cudd_Ref( bFuncNand2 ); - bFuncAnd2 = Cudd_bddAnd( pLib->dd, pLib->dd->vars[0], pLib->dd->vars[1] ); Cudd_Ref( bFuncAnd2 ); - - // get buffer - Mio_LibraryForEachGate( pLib, pGate ) - if ( pLib->pGateBuf == NULL && pGate->bFunc == bFuncBuf ) - { - pLib->pGateBuf = pGate; - break; - } - if ( pLib->pGateBuf == NULL ) - { - printf( "Warnings: GENLIB library reader cannot detect the buffer gate.\n" ); - printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" ); - } - - // get inverter - Mio_LibraryForEachGate( pLib, pGate ) - if ( pLib->pGateInv == NULL && pGate->bFunc == bFuncInv ) - { - pLib->pGateInv = pGate; - break; - } - if ( pLib->pGateInv == NULL ) - { - printf( "Warnings: GENLIB library reader cannot detect the invertor gate.\n" ); - printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" ); - } - - // get the NAND2 and AND2 gates - Mio_LibraryForEachGate( pLib, pGate ) - if ( pLib->pGateNand2 == NULL && pGate->bFunc == bFuncNand2 ) - { - pLib->pGateNand2 = pGate; - break; - } - Mio_LibraryForEachGate( pLib, pGate ) - if ( pLib->pGateAnd2 == NULL && pGate->bFunc == bFuncAnd2 ) - { - pLib->pGateAnd2 = pGate; - break; - } - if ( pLib->pGateAnd2 == NULL && pLib->pGateNand2 == NULL ) - { - printf( "Warnings: GENLIB library reader cannot detect the AND2 or NAND2 gate.\n" ); - printf( "Some parts of the supergate-based technology mapper may not work correctly.\n" ); - } - - Cudd_RecursiveDeref( pLib->dd, bFuncInv ); - Cudd_RecursiveDeref( pLib->dd, bFuncNand2 ); - Cudd_RecursiveDeref( pLib->dd, bFuncAnd2 ); -} - -/**Function************************************************************* - - Synopsis [populate hash table of gates to be exlcuded from genlib] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mio_LibraryReadExclude( void * pAbc, char * ExcludeFile, st_table * tExcludeGate ) -{ - int nDel = 0; - FILE *pEx; - char buffer[128]; - - assert ( tExcludeGate ); - - if ( ExcludeFile ) - { - pEx = fopen( ExcludeFile, "r" ); - - if ( pEx == NULL ) - { - fprintf ( Abc_FrameReadErr( pAbc ), "Error: Could not open exclude file %s. Stop.\n", ExcludeFile ); - return -1; - } - - while (1 == fscanf( pEx, "%127s", buffer )) - { - //printf ("Read: '%s'\n", buffer ); - st_insert( tExcludeGate, Extra_UtilStrsav( buffer ), (char *)0 ); - nDel++; - } - - fclose( pEx ); - } - - return nDel; -} - -/**Function************************************************************* - - Synopsis [Eliminates comments from the input file.] - - Description [As a byproduct, this procedure also counts the number - lines and dot-statements in the input file. This also joins non-comment - lines that are joined with a backspace '\'] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Io_ReadFileRemoveComments( char * pBuffer, int * pnDots, int * pnLines ) -{ - char * pCur; - int nDots, nLines; - // scan through the buffer and eliminate comments - // (in the BLIF file, comments are lines starting with "#") - nDots = nLines = 0; - for ( pCur = pBuffer; *pCur; pCur++ ) - { - // if this is the beginning of comment - // clean it with spaces until the new line statement - if ( *pCur == '#' ) - while ( *pCur != '\n' ) - *pCur++ = ' '; - - // count the number of new lines and dots - if ( *pCur == '\n' ) { - if (*(pCur-1)=='\r') { - // DOS(R) file support - if (*(pCur-2)!='\\') nLines++; - else { - // rewind to backslash and overwrite with a space - *(pCur-2) = ' '; - *(pCur-1) = ' '; - *pCur = ' '; - } - } else { - // UNIX(TM) file support - if (*(pCur-1)!='\\') nLines++; - else { - // rewind to backslash and overwrite with a space - *(pCur-1) = ' '; - *pCur = ' '; - } - } - } - else if ( *pCur == '.' ) - nDots++; - } - if ( pnDots ) - *pnDots = nDots; - if ( pnLines ) - *pnLines = nLines; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mio/mioUtils.c b/src/map/mio/mioUtils.c deleted file mode 100644 index bd3d01f7..00000000 --- a/src/map/mio/mioUtils.c +++ /dev/null @@ -1,531 +0,0 @@ -/**CFile**************************************************************** - - FileName [mioUtils.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [File reading/writing for technology mapping.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: mioUtils.c,v 1.6 2004/09/03 18:02:20 satrajit Exp $] - -***********************************************************************/ - -#include "mioInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Mio_WriteGate( FILE * pFile, Mio_Gate_t * pGate, int fPrintSops ); -static void Mio_WritePin( FILE * pFile, Mio_Pin_t * pPin ); -static int Mio_DelayCompare( Mio_Gate_t ** ppG1, Mio_Gate_t ** ppG2 ); -static void Mio_DeriveTruthTable_rec( DdNode * bFunc, unsigned uTruthsIn[][2], unsigned uTruthRes[] ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_LibraryDelete( Mio_Library_t * pLib ) -{ - Mio_Gate_t * pGate, * pGate2; - if ( pLib == NULL ) - return; - // free the bindings of nodes to gates from this library for all networks - Abc_FrameUnmapAllNetworks( Abc_FrameGetGlobalFrame() ); - // free the library - FREE( pLib->pName ); - Mio_LibraryForEachGateSafe( pLib, pGate, pGate2 ) - Mio_GateDelete( pGate ); - Extra_MmFlexStop( pLib->pMmFlex ); - Vec_StrFree( pLib->vCube ); - if ( pLib->tName2Gate ) - st_free_table( pLib->tName2Gate ); - if ( pLib->dd ) - Cudd_Quit( pLib->dd ); - free( pLib ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_GateDelete( Mio_Gate_t * pGate ) -{ - Mio_Pin_t * pPin, * pPin2; - FREE( pGate->pOutName ); - FREE( pGate->pName ); - FREE( pGate->pForm ); - if ( pGate->bFunc ) - Cudd_RecursiveDeref( pGate->pLib->dd, pGate->bFunc ); - Mio_GateForEachPinSafe( pGate, pPin, pPin2 ) - Mio_PinDelete( pPin ); - free( pGate ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_PinDelete( Mio_Pin_t * pPin ) -{ - FREE( pPin->pName ); - free( pPin ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mio_Pin_t * Mio_PinDup( Mio_Pin_t * pPin ) -{ - Mio_Pin_t * pPinNew; - - pPinNew = ALLOC( Mio_Pin_t, 1 ); - *pPinNew = *pPin; - pPinNew->pName = (pPinNew->pName ? Extra_UtilStrsav(pPinNew->pName) : NULL); - pPinNew->pNext = NULL; - - return pPinNew; -} - - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_WriteLibrary( FILE * pFile, Mio_Library_t * pLib, int fPrintSops ) -{ - Mio_Gate_t * pGate; - - fprintf( pFile, "# The genlib library \"%s\".\n", pLib->pName ); - Mio_LibraryForEachGate( pLib, pGate ) - Mio_WriteGate( pFile, pGate, fPrintSops ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_WriteGate( FILE * pFile, Mio_Gate_t * pGate, int fPrintSops ) -{ - Mio_Pin_t * pPin; - - fprintf( pFile, "GATE " ); - fprintf( pFile, "%12s ", pGate->pName ); - fprintf( pFile, "%10.2f ", pGate->dArea ); - fprintf( pFile, "%s=%s;\n", pGate->pOutName, pGate->pForm ); - // print the pins - if ( fPrintSops ) - fprintf( pFile, "%s", pGate->pSop? pGate->pSop : "unspecified\n" ); -// Extra_bddPrint( pGate->pLib->dd, pGate->bFunc ); -// fprintf( pFile, "\n" ); - Mio_GateForEachPin( pGate, pPin ) - Mio_WritePin( pFile, pPin ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_WritePin( FILE * pFile, Mio_Pin_t * pPin ) -{ - char * pPhaseNames[10] = { "UNKNOWN", "INV", "NONINV" }; - fprintf( pFile, " PIN " ); - fprintf( pFile, "%9s ", pPin->pName ); - fprintf( pFile, "%10s ", pPhaseNames[pPin->Phase] ); - fprintf( pFile, "%6d ", (int)pPin->dLoadInput ); - fprintf( pFile, "%6d ", (int)pPin->dLoadMax ); - fprintf( pFile, "%6.2f ", pPin->dDelayBlockRise ); - fprintf( pFile, "%6.2f ", pPin->dDelayFanoutRise ); - fprintf( pFile, "%6.2f ", pPin->dDelayBlockFall ); - fprintf( pFile, "%6.2f", pPin->dDelayFanoutFall ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Collects the set of root gates.] - - Description [Only collects the gates with unique functionality, - which have fewer inputs and shorter delay than the given limits.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mio_Gate_t ** Mio_CollectRoots( Mio_Library_t * pLib, int nInputs, float tDelay, bool fSkipInv, int * pnGates ) -{ - Mio_Gate_t * pGate; - Mio_Gate_t ** ppGates; - /* st_table * tFuncs; */ - /* st_generator * gen; */ - DdNode * bFunc; - DdManager * dd; - int nGates, iGate; - - dd = Mio_LibraryReadDd( pLib ); - nGates = Mio_LibraryReadGateNum( pLib ); - - /* - - // for each functionality select one gate; skip constants and buffers - tFuncs = st_init_table( st_ptrcmp, st_ptrhash ); - Mio_LibraryForEachGate( pLib, pGate ) - { - bFunc = Mio_GateReadFunc(pGate); - if ( pGate->nInputs > nInputs ) - continue; - if ( pGate->dDelayMax > (double)tDelay ) - continue; - if ( bFunc == b0 || bFunc == b1 ) - continue; - if ( bFunc == dd->vars[0] ) - continue; - if ( bFunc == Cudd_Not(dd->vars[0]) && fSkipInv ) - continue; - if ( st_is_member( tFuncs, (char *)bFunc ) ) - continue; - st_insert( tFuncs, (char *)bFunc, (char *)pGate ); - } - - // collect the gates into the array - ppGates = ALLOC( Mio_Gate_t *, nGates ); - iGate = 0; - st_foreach_item( tFuncs, gen, (char **)&bFunc, (char **)&pGate ) - ppGates[ iGate++ ] = pGate; - assert( iGate <= nGates ); - st_free_table( tFuncs ); - - */ - - ppGates = ALLOC( Mio_Gate_t *, nGates ); - iGate = 0; - Mio_LibraryForEachGate( pLib, pGate ) - { - bFunc = Mio_GateReadFunc(pGate); - if ( pGate->nInputs > nInputs ) - continue; - if ( pGate->dDelayMax > (double)tDelay ) - continue; - if ( bFunc == b0 || bFunc == b1 ) - continue; - if ( bFunc == dd->vars[0] ) - continue; - if ( bFunc == Cudd_Not(dd->vars[0]) && fSkipInv ) - continue; - - assert( iGate < nGates ); - ppGates[ iGate++ ] = pGate; - } - - if ( iGate > 0 ) - { - // sort the gates by delay - qsort( (void *)ppGates, iGate, sizeof(Mio_Gate_t *), - (int (*)(const void *, const void *)) Mio_DelayCompare ); - assert( Mio_DelayCompare( ppGates, ppGates + iGate - 1 ) <= 0 ); - } - - if ( pnGates ) - *pnGates = iGate; - return ppGates; -} - -/**Function************************************************************* - - Synopsis [Compares the max delay of two gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mio_DelayCompare( Mio_Gate_t ** ppG1, Mio_Gate_t ** ppG2 ) -{ - if ( (*ppG1)->dDelayMax < (*ppG2)->dDelayMax ) - return -1; - if ( (*ppG1)->dDelayMax > (*ppG2)->dDelayMax ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Derives the truth table of the gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_DeriveTruthTable( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nSigns, int nInputs, unsigned uTruthRes[] ) -{ - Mio_DeriveTruthTable_rec( pGate->bFunc, uTruthsIn, uTruthRes ); -} - -/**Function************************************************************* - - Synopsis [Recursively derives the truth table of the gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_DeriveTruthTable_rec( DdNode * bFunc, unsigned uTruthsIn[][2], unsigned uTruthRes[] ) -{ - unsigned uTruthsCof0[2]; - unsigned uTruthsCof1[2]; - - // complement the resulting truth table, if the function is complemented - if ( Cudd_IsComplement(bFunc) ) - { - Mio_DeriveTruthTable_rec( Cudd_Not(bFunc), uTruthsIn, uTruthRes ); - uTruthRes[0] = ~uTruthRes[0]; - uTruthRes[1] = ~uTruthRes[1]; - return; - } - - // if the function is constant 1, return the constant 1 truth table - if ( bFunc->index == CUDD_CONST_INDEX ) - { - uTruthRes[0] = MIO_FULL; - uTruthRes[1] = MIO_FULL; - return; - } - - // solve the problem for both cofactors - Mio_DeriveTruthTable_rec( cuddE(bFunc), uTruthsIn, uTruthsCof0 ); - Mio_DeriveTruthTable_rec( cuddT(bFunc), uTruthsIn, uTruthsCof1 ); - - // derive the resulting truth table using the input truth tables - uTruthRes[0] = (uTruthsCof0[0] & ~uTruthsIn[bFunc->index][0]) | - (uTruthsCof1[0] & uTruthsIn[bFunc->index][0]); - uTruthRes[1] = (uTruthsCof0[1] & ~uTruthsIn[bFunc->index][1]) | - (uTruthsCof1[1] & uTruthsIn[bFunc->index][1]); -} - -/**Function************************************************************* - - Synopsis [Derives the truth table of the root of the gate.] - - Description [Given the truth tables of the leaves of the gate, - this procedure derives the truth table of the root.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_DeriveTruthTable2( Mio_Gate_t * pGate, unsigned uTruthsIn[][2], int nTruths, int nInputs, unsigned uTruthRes[] ) -{ - unsigned uSignCube[2]; - int i, nFanins; - char * pCube; - - // make sure that the number of input truth tables in equal to the number of gate inputs - assert( pGate->nInputs == nTruths ); - assert( nInputs < 7 ); - - nFanins = Abc_SopGetVarNum( pGate->pSop ); - assert( nFanins == nInputs ); - - // clean the resulting truth table - uTruthRes[0] = 0; - uTruthRes[1] = 0; - if ( nInputs < 6 ) - { -// for ( c = 0; *(pCube = pGate->pSop + c * (nFanins + 3)); c++ ) - Abc_SopForEachCube( pGate->pSop, nFanins, pCube ) - { - // add the clause - uSignCube[0] = MIO_FULL; - for ( i = 0; i < nFanins; i++ ) - { - if ( pCube[i] == '0' ) - uSignCube[0] &= ~uTruthsIn[i][0]; - else if ( pCube[i] == '1' ) - uSignCube[0] &= uTruthsIn[i][0]; - } - } - if ( nInputs < 5 ) - uTruthRes[0] &= MIO_MASK(1<pSop + c * (nFanins + 3)); c++ ) - Abc_SopForEachCube( pGate->pSop, nFanins, pCube ) - { - uSignCube[0] = MIO_FULL; - uSignCube[1] = MIO_FULL; - for ( i = 0; i < nFanins; i++ ) - { - if ( pCube[i] == '0' ) - { - uSignCube[0] &= ~uTruthsIn[i][0]; - uSignCube[1] &= ~uTruthsIn[i][1]; - } - else if ( pCube[i] == '1' ) - { - uSignCube[0] &= uTruthsIn[i][0]; - uSignCube[1] &= uTruthsIn[i][1]; - } - } - uTruthRes[0] |= uSignCube[0]; - uTruthRes[1] |= uSignCube[1]; - } - } -} - -/**Function************************************************************* - - Synopsis [Derives the area and delay of the root of the gate.] - - Description [Array of the resulting delays should be initialized - to the (negative) SUPER_NO_VAR value.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mio_DeriveGateDelays( Mio_Gate_t * pGate, - float ** ptPinDelays, int nPins, int nInputs, float tDelayZero, - float * ptDelaysRes, float * ptPinDelayMax ) -{ - Mio_Pin_t * pPin; - float Delay, DelayMax; - int i, k; - assert( pGate->nInputs == nPins ); - // set all the delays to the unused delay - for ( i = 0; i < nInputs; i++ ) - ptDelaysRes[i] = tDelayZero; - // compute the delays for each input and the max delay at the same time - DelayMax = 0; - for ( i = 0; i < nInputs; i++ ) - { - for ( k = 0, pPin = pGate->pPins; pPin; pPin = pPin->pNext, k++ ) - { - if ( ptPinDelays[k][i] < 0 ) - continue; - Delay = ptPinDelays[k][i] + (float)pPin->dDelayBlockMax; - if ( ptDelaysRes[i] < Delay ) - ptDelaysRes[i] = Delay; - } - if ( k != nPins ) - { - printf ("DEBUG: problem gate is %s\n", Mio_GateReadName( pGate )); - } - assert( k == nPins ); - if ( DelayMax < ptDelaysRes[i] ) - DelayMax = ptDelaysRes[i]; - } - *ptPinDelayMax = DelayMax; -} - - -/**Function************************************************************* - - Synopsis [Creates a pseudo-gate.] - - Description [The pseudo-gate is a N-input gate with all info set to 0.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mio_Gate_t * Mio_GateCreatePseudo( int nInputs ) -{ - Mio_Gate_t * pGate; - Mio_Pin_t * pPin; - int i; - // allocate the gate structure - pGate = ALLOC( Mio_Gate_t, 1 ); - memset( pGate, 0, sizeof(Mio_Gate_t) ); - pGate->nInputs = nInputs; - // create pins - for ( i = 0; i < nInputs; i++ ) - { - pPin = ALLOC( Mio_Pin_t, 1 ); - memset( pPin, 0, sizeof(Mio_Pin_t) ); - pPin->pNext = pGate->pPins; - pGate->pPins = pPin; - } - return pGate; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/mio/module.make b/src/map/mio/module.make deleted file mode 100644 index 26a4561c..00000000 --- a/src/map/mio/module.make +++ /dev/null @@ -1,5 +0,0 @@ -SRC += src/map/mio/mio.c \ - src/map/mio/mioApi.c \ - src/map/mio/mioFunc.c \ - src/map/mio/mioRead.c \ - src/map/mio/mioUtils.c diff --git a/src/map/pcm/module.make b/src/map/pcm/module.make deleted file mode 100644 index e69de29b..00000000 diff --git a/src/map/super/module.make b/src/map/super/module.make deleted file mode 100644 index 19ce8228..00000000 --- a/src/map/super/module.make +++ /dev/null @@ -1,4 +0,0 @@ -SRC += src/map/super/super.c \ - src/map/super/superAnd.c \ - src/map/super/superGate.c \ - src/map/super/superWrite.c diff --git a/src/map/super/super.c b/src/map/super/super.c deleted file mode 100644 index 97420c5c..00000000 --- a/src/map/super/super.c +++ /dev/null @@ -1,319 +0,0 @@ -/**CFile**************************************************************** - - FileName [super.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Pre-computation of supergates.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 18, 2003.] - - Revision [$Id: super.c,v 1.6 2004/10/30 20:51:11 satrajit Exp $] - -***********************************************************************/ - -#include "superInt.h" -#include "mainInt.h" -#include "mio.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Super_CommandSupergates ( Abc_Frame_t * pAbc, int argc, char **argv ); -static int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_Init( Abc_Frame_t * pAbc ) -{ - Cmd_CommandAdd( pAbc, "SC mapping", "super", Super_CommandSupergates, 0 ); - Cmd_CommandAdd( pAbc, "SC mapping", "super2", Super_CommandSupergatesAnd, 0 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_End() -{ -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Super_CommandSupergatesAnd( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - FILE * pOut, * pErr; - int nVarsMax, nLevels; - int fVerbose; - int c; - - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set the defaults - nVarsMax = 4; - nLevels = 3; - fVerbose = 0; - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "ilvh")) != EOF ) - { - switch (c) - { - case 'i': - nVarsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nVarsMax < 0 ) - goto usage; - break; - case 'l': - nLevels = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLevels < 0 ) - goto usage; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - Super2_Precompute( nVarsMax, nLevels, fVerbose ); - - return 0; - -usage: - fprintf( pErr, "usage: super2 [-i num] [-l num] [-vh]\n"); - fprintf( pErr, "\t precomputes the supergates composed of AND2s and INVs\n" ); - fprintf( pErr, "\t-i num : the max number of inputs to the supergate [default = %d]\n", nVarsMax ); - fprintf( pErr, "\t-l num : the max number of logic levels of gates [default = %d]\n", nLevels ); - fprintf( pErr, "\t-v : enable verbose output\n"); - fprintf( pErr, "\t-h : print the help message\n"); - return 1; /* error exit */ -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Super_CommandSupergates( Abc_Frame_t * pAbc, int argc, char **argv ) -{ - FILE * pFile; - FILE * pOut, * pErr; - Mio_Library_t * pLib; - char * FileName, * ExcludeFile; - float DelayLimit; - float AreaLimit; - bool fSkipInvs; - bool fWriteOldFormat; - int nVarsMax, nLevels, TimeLimit; - int fVerbose; - int c; - - pOut = Abc_FrameReadOut(pAbc); - pErr = Abc_FrameReadErr(pAbc); - - // set the defaults - nVarsMax = 5; - nLevels = 3; - DelayLimit = 3.5; - AreaLimit = 9; - TimeLimit = 10; - fSkipInvs = 1; - fVerbose = 0; - fWriteOldFormat = 0; - ExcludeFile = 0; - - Extra_UtilGetoptReset(); - while ( (c = Extra_UtilGetopt(argc, argv, "eiltdasovh")) != EOF ) - { - switch (c) - { - case 'e': - ExcludeFile = argv[globalUtilOptind]; - if ( ExcludeFile == 0 ) - goto usage; - globalUtilOptind++; - break; - case 'i': - nVarsMax = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nVarsMax < 0 ) - goto usage; - break; - case 'l': - nLevels = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( nLevels < 0 ) - goto usage; - break; - case 't': - TimeLimit = atoi(argv[globalUtilOptind]); - globalUtilOptind++; - if ( TimeLimit < 0 ) - goto usage; - break; - case 'd': - DelayLimit = (float)atof(argv[globalUtilOptind]); - globalUtilOptind++; - if ( DelayLimit <= 0.0 ) - goto usage; - break; - case 'a': - AreaLimit = (float)atof(argv[globalUtilOptind]); - globalUtilOptind++; - if ( AreaLimit <= 0.0 ) - goto usage; - break; - case 's': - fSkipInvs ^= 1; - break; - case 'o': - fWriteOldFormat ^= 1; - break; - case 'v': - fVerbose ^= 1; - break; - case 'h': - goto usage; - break; - default: - goto usage; - } - } - - - if ( argc != globalUtilOptind + 1 ) - { - fprintf( pErr, "The GENLIB library file should be given on the command line.\n" ); - goto usage; - } - - if ( nVarsMax < 2 || nVarsMax > 6 ) - { - fprintf( pErr, "The max number of variables (%d) should be more than 1 and less than 7.\n", nVarsMax ); - goto usage; - } - - // get the input file name - FileName = argv[globalUtilOptind]; - if ( (pFile = Io_FileOpen( FileName, "open_path", "r", 0 )) == NULL ) -// if ( (pFile = fopen( FileName, "r" )) == NULL ) - { - fprintf( pErr, "Cannot open input file \"%s\". ", FileName ); - if (( FileName = Extra_FileGetSimilarName( FileName, ".genlib", ".lib", ".gen", ".g", NULL ) )) - fprintf( pErr, "Did you mean \"%s\"?", FileName ); - fprintf( pErr, "\n" ); - return 1; - } - fclose( pFile ); - - // set the new network - pLib = Mio_LibraryRead( pAbc, FileName, ExcludeFile, fVerbose ); - if ( pLib == NULL ) - { - fprintf( pErr, "Reading library has failed.\n" ); - goto usage; - } - - // compute the gates - Super_Precompute( pLib, nVarsMax, nLevels, DelayLimit, AreaLimit, TimeLimit, fSkipInvs, fWriteOldFormat, fVerbose ); - - // delete the library - Mio_LibraryDelete( pLib ); - return 0; - -usage: - fprintf( pErr, "usage: super [-i num] [-l num] [-d float] [-a float] [-t num] [-sovh] \n"); - fprintf( pErr, "\t precomputes the supergates for the given GENLIB library\n" ); - fprintf( pErr, "\t-i num : the max number of supergate inputs [default = %d]\n", nVarsMax ); - fprintf( pErr, "\t-l num : the max number of levels of gates [default = %d]\n", nLevels ); - fprintf( pErr, "\t-d float : the max delay of the supergates [default = %.2f]\n", DelayLimit ); - fprintf( pErr, "\t-a float : the max area of the supergates [default = %.2f]\n", AreaLimit ); - fprintf( pErr, "\t-t num : the approximate runtime limit in seconds [default = %d]\n", TimeLimit ); - fprintf( pErr, "\t-s : toggle the use of inverters at the inputs [default = %s]\n", (fSkipInvs? "no": "yes") ); - fprintf( pErr, "\t-o : toggle dumping the supergate library in old format [default = %s]\n", (fWriteOldFormat? "yes": "no") ); - fprintf( pErr, "\t-e file : file contains list of genlib gates to exclude\n" ); - fprintf( pErr, "\t-v : enable verbose output [default = %s]\n", (fVerbose? "yes" : "no") ); - fprintf( pErr, "\t-h : print the help message\n"); - fprintf( pErr, "\n"); - fprintf( pErr, "\tHere is a piece of advice on precomputing supergate libraries:\n"); - fprintf( pErr, "\t\n"); - fprintf( pErr, "\tStart with the number of inputs equal to 5 (-i 5), the number of \n"); - fprintf( pErr, "\tlevels equal to 3 (-l 3), the delay equal to 2-3 delays of inverter, \n"); - fprintf( pErr, "\tthe area equal to 3-4 areas of two input NAND, and runtime limit equal \n"); - fprintf( pErr, "\tto 10 seconds (-t 10). Run precomputation and learn from the result.\n"); - fprintf( pErr, "\tDetermine what parameter is most constraining and try to increase \n"); - fprintf( pErr, "\tthe value of that parameter. The goal is to have a well-balanced\n"); - fprintf( pErr, "\tset of constraints and the resulting supergate library containing\n"); - fprintf( pErr, "\tapproximately 100K-200K supergates. Typically, it is better to increase\n"); - fprintf( pErr, "\tdelay limit rather than area limit, because having large-area supergates\n"); - fprintf( pErr, "\tmay result in a considerable increase in area.\n"); - fprintf( pErr, "\t\n"); - fprintf( pErr, "\tNote that a good supergate library for experiments typically can be \n"); - fprintf( pErr, "\tprecomputed in 30 sec. Increasing the runtime limit makes sense when\n"); - fprintf( pErr, "\tother parameters are well-balanced and it is needed to enumerate more\n"); - fprintf( pErr, "\tchoices to have a good result. In the end, to compute the final library\n"); - fprintf( pErr, "\tthe runtime can be set to 300 sec to ensure the ultimate quality.\n"); - fprintf( pErr, "\tIn some cases, the runtime has to be reduced if the supergate library\n"); - fprintf( pErr, "\tcontains too many supergates (> 500K).\n"); - fprintf( pErr, "\t\n"); - fprintf( pErr, "\tWhen precomputing libraries of 6 inputs (-i 6), start with even more \n"); - fprintf( pErr, "\trestricted parameters and gradually increase them until the goal is met.\n"); - fprintf( pErr, "\t\n"); - return 1; /* error exit */ -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/super/super.h b/src/map/super/super.h deleted file mode 100644 index a7169924..00000000 --- a/src/map/super/super.h +++ /dev/null @@ -1,60 +0,0 @@ -/**CFile**************************************************************** - - FileName [super.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Pre-computation of supergates (delay-limited gate combinations).] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: super.h,v 1.3 2004/06/28 14:20:25 alanmi Exp $] - -***********************************************************************/ - -#ifndef __SUPER_H__ -#define __SUPER_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== superCore.c =============================================================*/ - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/map/super/superAnd.c b/src/map/super/superAnd.c deleted file mode 100644 index 52473fba..00000000 --- a/src/map/super/superAnd.c +++ /dev/null @@ -1,696 +0,0 @@ -/**CFile**************************************************************** - - FileName [superAnd.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Pre-computation of supergates.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: superAnd.c,v 1.3 2004/06/28 14:20:25 alanmi Exp $] - -***********************************************************************/ - -#include "superInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the bit masks -#define SUPER_MASK(n) ((~((unsigned)0)) >> (32-n)) -#define SUPER_FULL (~((unsigned)0)) - -// data structure for AND2 subgraph precomputation -typedef struct Super2_ManStruct_t_ Super2_Man_t; // manager -typedef struct Super2_LibStruct_t_ Super2_Lib_t; // library -typedef struct Super2_GateStruct_t_ Super2_Gate_t; // supergate - -struct Super2_ManStruct_t_ -{ - Extra_MmFixed_t * pMem; // memory manager for all supergates - stmm_table * tTable; // mapping of truth tables into gates - int nTried; // the total number of tried -}; - -struct Super2_LibStruct_t_ -{ - int i; // used to iterate through the table - int k; // used to iterate through the table - int nInputs; // the number of inputs - int nMints; // the number of minterms - int nLevels; // the number of logic levels - int nGates; // the number of gates in the library - int nGatesAlloc; // the number of allocated places - Super2_Gate_t ** pGates; // the gates themselves - unsigned uMaskBit; // the mask used to determine the compl bit -}; - -struct Super2_GateStruct_t_ -{ - unsigned uTruth; // the truth table of this supergate - Super2_Gate_t * pOne; // the left wing - Super2_Gate_t * pTwo; // the right wing - Super2_Gate_t * pNext; // the next gate in the table -}; - - -// manipulation of complemented attributes -#define Super2_IsComplement(p) (((int)((unsigned long) (p) & 01))) -#define Super2_Regular(p) ((Super2_Gate_t *)((unsigned long)(p) & ~01)) -#define Super2_Not(p) ((Super2_Gate_t *)((unsigned long)(p) ^ 01)) -#define Super2_NotCond(p,c) ((Super2_Gate_t *)((unsigned long)(p) ^ (c))) - -// iterating through the gates in the library -#define Super2_LibForEachGate( Lib, Gate ) \ - for ( Lib->i = 0; \ - Lib->i < Lib->nGates && (Gate = Lib->pGates[Lib->i]); \ - Lib->i++ ) -#define Super2_LibForEachGate2( Lib, Gate2 ) \ - for ( Lib->k = 0; \ - Lib->k < Lib->i && (Gate2 = Lib->pGates[Lib->k]); \ - Lib->k++ ) - -// static functions -static Super2_Man_t * Super2_ManStart(); -static void Super2_ManStop( Super2_Man_t * pMan ); -static Super2_Lib_t * Super2_LibStart(); -static Super2_Lib_t * Super2_LibDup( Super2_Lib_t * pLib ); -static void Super2_LibStop( Super2_Lib_t * pLib ); -static void Super2_LibAddGate( Super2_Lib_t * pLib, Super2_Gate_t * pGate ); -static Super2_Lib_t * Super2_LibFirst( Super2_Man_t * pMan, int nInputs ); -static Super2_Lib_t * Super2_LibCompute( Super2_Man_t * pMan, Super2_Lib_t * pLib ); - -static void Super2_LibWrite( Super2_Lib_t * pLib ); -static void Super2_LibWriteGate( FILE * pFile, Super2_Lib_t * pLib, Super2_Gate_t * pGate ); -static char * Super2_LibWriteGate_rec( Super2_Gate_t * pGate, int fInv, int Level ); -static int Super2_LibWriteCompare( char * pStr1, char * pStr2 ); -static int Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Precomputes the library of AND2 gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super2_Precompute( int nInputs, int nLevels, int fVerbose ) -{ - Super2_Man_t * pMan; - Super2_Lib_t * pLibCur, * pLibNext; - int Level; - int clk; - - assert( nInputs < 6 ); - - // start the manager - pMan = Super2_ManStart(); - - // get the starting supergates - pLibCur = Super2_LibFirst( pMan, nInputs ); - - // perform the computation of supergates -printf( "Computing supergates for %d inputs and %d levels:\n", nInputs, nLevels ); - for ( Level = 1; Level <= nLevels; Level++ ) - { -clk = clock(); - pLibNext = Super2_LibCompute( pMan, pLibCur ); - pLibNext->nLevels = Level; - Super2_LibStop( pLibCur ); - pLibCur = pLibNext; -printf( "Level %d: Tried = %7d. Computed = %7d. ", Level, pMan->nTried, pLibCur->nGates ); -PRT( "Runtime", clock() - clk ); -fflush( stdout ); - } - -printf( "Writing the output file...\n" ); -fflush( stdout ); - // write them into a file - Super2_LibWrite( pLibCur ); - Super2_LibStop( pLibCur ); - - // stop the manager - Super2_ManStop( pMan ); -} - - - - -/**Function************************************************************* - - Synopsis [Starts the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Super2_Man_t * Super2_ManStart() -{ - Super2_Man_t * pMan; - pMan = ALLOC( Super2_Man_t, 1 ); - memset( pMan, 0, sizeof(Super2_Man_t) ); - pMan->pMem = Extra_MmFixedStart( sizeof(Super2_Gate_t) ); - pMan->tTable = stmm_init_table( st_ptrcmp, st_ptrhash ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Stops the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super2_ManStop( Super2_Man_t * pMan ) -{ - Extra_MmFixedStop( pMan->pMem ); - stmm_free_table( pMan->tTable ); - free( pMan ); -} - -/**Function************************************************************* - - Synopsis [Starts the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Super2_Lib_t * Super2_LibStart() -{ - Super2_Lib_t * pLib; - pLib = ALLOC( Super2_Lib_t, 1 ); - memset( pLib, 0, sizeof(Super2_Lib_t) ); - return pLib; -} - -/**Function************************************************************* - - Synopsis [Duplicates the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Super2_Lib_t * Super2_LibDup( Super2_Lib_t * pLib ) -{ - Super2_Lib_t * pLibNew; - pLibNew = Super2_LibStart(); - pLibNew->nInputs = pLib->nInputs; - pLibNew->nMints = pLib->nMints; - pLibNew->nLevels = pLib->nLevels; - pLibNew->nGates = pLib->nGates; - pLibNew->uMaskBit = pLib->uMaskBit; - pLibNew->nGatesAlloc = 1000 + pLib->nGatesAlloc; - pLibNew->pGates = ALLOC( Super2_Gate_t *, pLibNew->nGatesAlloc ); - memcpy( pLibNew->pGates, pLib->pGates, pLibNew->nGates * sizeof(Super2_Gate_t *) ); - return pLibNew; -} - -/**Function************************************************************* - - Synopsis [Add gate to the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super2_LibAddGate( Super2_Lib_t * pLib, Super2_Gate_t * pGate ) -{ - if ( pLib->nGates == pLib->nGatesAlloc ) - { - pLib->pGates = REALLOC( Super2_Gate_t *, pLib->pGates, 3 * pLib->nGatesAlloc ); - pLib->nGatesAlloc *= 3; - } - pLib->pGates[ pLib->nGates++ ] = pGate; -} - -/**Function************************************************************* - - Synopsis [Stops the library.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super2_LibStop( Super2_Lib_t * pLib ) -{ - free( pLib->pGates ); - free( pLib ); -} - -/**Function************************************************************* - - Synopsis [Derives the starting supergates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Super2_Lib_t * Super2_LibFirst( Super2_Man_t * pMan, int nInputs ) -{ - Super2_Lib_t * pLib; - int v, m; - - // start the library - pLib = Super2_LibStart(); - - // create the starting supergates - pLib->nInputs = nInputs; - pLib->nMints = (1 << nInputs); - pLib->nLevels = 0; - pLib->nGates = nInputs + 1; - pLib->nGatesAlloc = nInputs + 1; - pLib->uMaskBit = (1 << (pLib->nMints-1)); - pLib->pGates = ALLOC( Super2_Gate_t *, nInputs + 1 ); - // add the constant 0 - pLib->pGates[0] = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); - memset( pLib->pGates[0], 0, sizeof(Super2_Gate_t) ); - // add the elementary gates - for ( v = 0; v < nInputs; v++ ) - { - pLib->pGates[v+1] = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); - memset( pLib->pGates[v+1], 0, sizeof(Super2_Gate_t) ); - pLib->pGates[v+1]->pTwo = (Super2_Gate_t *)v; - } - - // set up their truth tables - for ( m = 0; m < pLib->nMints; m++ ) - for ( v = 0; v < nInputs; v++ ) - if ( m & (1 << v) ) - pLib->pGates[v+1]->uTruth |= (1 << m); - return pLib; -} - -/**Function************************************************************* - - Synopsis [Precomputes one level of supergates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Super2_Lib_t * Super2_LibCompute( Super2_Man_t * pMan, Super2_Lib_t * pLib ) -{ - Super2_Lib_t * pLibNew; - Super2_Gate_t * pGate1, * pGate2, * pGateNew; - Super2_Gate_t ** ppGate; - unsigned Mask = SUPER_MASK(pLib->nMints); - unsigned uTruth, uTruthR, uTruth1, uTruth2, uTruth1c, uTruth2c; - - // start the new library - pLibNew = Super2_LibDup( pLib ); - - // reset the hash table - stmm_free_table( pMan->tTable ); - pMan->tTable = stmm_init_table( st_ptrcmp, st_ptrhash ); - // set the starting things into the hash table - Super2_LibForEachGate( pLibNew, pGate1 ) - { - uTruthR = ((pGate1->uTruth & pLibNew->uMaskBit)? Mask & ~pGate1->uTruth : pGate1->uTruth); - - if ( stmm_lookup( pMan->tTable, (char *)uTruthR, (char **)&pGate2 ) ) - { - printf( "New gate:\n" ); - Super2_LibWriteGate( stdout, pLibNew, pGate1 ); - printf( "Gate in the table:\n" ); - Super2_LibWriteGate( stdout, pLibNew, pGate2 ); - assert( 0 ); - } - stmm_insert( pMan->tTable, (char *)uTruthR, (char *)pGate1 ); - } - - - // set the number of gates tried - pMan->nTried = pLibNew->nGates; - - // go through the gate pairs - Super2_LibForEachGate( pLib, pGate1 ) - { - if ( pLib->i && pLib->i % 300 == 0 ) - { - printf( "Tried %5d first gates...\n", pLib->i ); - fflush( stdout ); - } - - Super2_LibForEachGate2( pLib, pGate2 ) - { - uTruth1 = pGate1->uTruth; - uTruth2 = pGate2->uTruth; - uTruth1c = Mask & ~uTruth1; - uTruth2c = Mask & ~uTruth2; - - // none complemented - uTruth = uTruth1 & uTruth2; - uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); - - if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) ) - { - pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); - pGateNew->pOne = pGate1; - pGateNew->pTwo = pGate2; - pGateNew->uTruth = uTruth; - *ppGate = pGateNew; - Super2_LibAddGate( pLibNew, pGateNew ); - } - - // one complemented - uTruth = uTruth1c & uTruth2; - uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); - - if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) ) - { - pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); - pGateNew->pOne = Super2_Not(pGate1); - pGateNew->pTwo = pGate2; - pGateNew->uTruth = uTruth; - *ppGate = pGateNew; - Super2_LibAddGate( pLibNew, pGateNew ); - } - - // another complemented - uTruth = uTruth1 & uTruth2c; - uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); - - if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) ) - { - pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); - pGateNew->pOne = pGate1; - pGateNew->pTwo = Super2_Not(pGate2); - pGateNew->uTruth = uTruth; - *ppGate = pGateNew; - Super2_LibAddGate( pLibNew, pGateNew ); - } - - // both complemented - uTruth = uTruth1c & uTruth2c; - uTruthR = ((uTruth & pLibNew->uMaskBit)? Mask & ~uTruth : uTruth); - - if ( !stmm_find_or_add( pMan->tTable, (char *)uTruthR, (char ***)&ppGate ) ) - { - pGateNew = (Super2_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); - pGateNew->pOne = Super2_Not(pGate1); - pGateNew->pTwo = Super2_Not(pGate2); - pGateNew->uTruth = uTruth; - *ppGate = pGateNew; - Super2_LibAddGate( pLibNew, pGateNew ); - } - - pMan->nTried += 4; - } - } - return pLibNew; -} - - -static unsigned s_uMaskBit; -static unsigned s_uMaskAll; - -/**Function************************************************************* - - Synopsis [Writes the library into the file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super2_LibWrite( Super2_Lib_t * pLib ) -{ - Super2_Gate_t * pGate; - FILE * pFile; - char FileName[100]; - int clk; - - if ( pLib->nLevels > 5 ) - { - printf( "Cannot write file for %d levels.\n", pLib->nLevels ); - return; - } - -clk = clock(); - // sort the supergates by truth table - s_uMaskBit = pLib->uMaskBit; - s_uMaskAll = SUPER_MASK(pLib->nMints); - qsort( (void *)pLib->pGates, pLib->nGates, sizeof(Super2_Gate_t *), - (int (*)(const void *, const void *)) Super2_LibCompareGates ); - assert( Super2_LibCompareGates( pLib->pGates, pLib->pGates + pLib->nGates - 1 ) < 0 ); -PRT( "Sorting", clock() - clk ); - - - // start the file - sprintf( FileName, "superI%dL%d", pLib->nInputs, pLib->nLevels ); - pFile = fopen( FileName, "w" ); - fprintf( pFile, "# AND2/INV supergates derived on %s.\n", Extra_TimeStamp() ); - fprintf( pFile, "# Command line: \"super2 -i %d -l %d\".\n", pLib->nInputs, pLib->nLevels ); - fprintf( pFile, "# The number of inputs = %6d.\n", pLib->nInputs ); - fprintf( pFile, "# The number of levels = %6d.\n", pLib->nLevels ); - fprintf( pFile, "# The number of supergates = %6d.\n", pLib->nGates ); - fprintf( pFile, "# The total functions = %6d.\n", (1<<(pLib->nMints-1)) ); - fprintf( pFile, "\n" ); - fprintf( pFile, "%6d\n", pLib->nGates ); - - // print the gates - Super2_LibForEachGate( pLib, pGate ) - Super2_LibWriteGate( pFile, pLib, pGate ); - fclose( pFile ); - - printf( "The supergates are written into file \"%s\" ", FileName ); - printf( "(%0.2f Mb).\n", ((double)Extra_FileSize(FileName))/(1<<20) ); -} - -/**Function************************************************************* - - Synopsis [Writes the gate into the file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Super2_LibCompareGates( Super2_Gate_t ** ppG1, Super2_Gate_t ** ppG2 ) -{ - Super2_Gate_t * pG1 = *ppG1; - Super2_Gate_t * pG2 = *ppG2; - unsigned uTruth1, uTruth2; - - uTruth1 = (pG1->uTruth & s_uMaskBit)? s_uMaskAll & ~pG1->uTruth : pG1->uTruth; - uTruth2 = (pG2->uTruth & s_uMaskBit)? s_uMaskAll & ~pG2->uTruth : pG2->uTruth; - - if ( uTruth1 < uTruth2 ) - return -1; - return 1; -} - -/**Function************************************************************* - - Synopsis [Writes the gate into the file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super2_LibWriteGate( FILE * pFile, Super2_Lib_t * pLib, Super2_Gate_t * pGate ) -{ -// unsigned uTruthR; - unsigned uTruth; - int fInv; - - // check whether the gate need complementation - fInv = (int)(pGate->uTruth & pLib->uMaskBit); - uTruth = (fInv? ~pGate->uTruth : pGate->uTruth); -/* - // reverse the truth table - uTruthR = 0; - for ( m = 0; m < pLib->nMints; m++ ) - if ( uTruth & (1 << m) ) - uTruthR |= (1 << (pLib->nMints-1-m)); -*/ - // write the truth table - Extra_PrintBinary( pFile, &uTruth, pLib->nMints ); - fprintf( pFile, " " ); - // write the symbolic expression - fprintf( pFile, "%s", Super2_LibWriteGate_rec( pGate, fInv, pLib->nLevels ) ); - fprintf( pFile, "\n" ); -} - - -/**Function************************************************************* - - Synopsis [Recursively writes the gate into the file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Super2_LibWriteGate_rec( Super2_Gate_t * pGate, int fInv, int Level ) -{ - static char Buff01[ 3], Buff02[ 3]; // Max0 = 1 - static char Buff11[ 6], Buff12[ 6]; // Max1 = 2*Max0 + 2 = 4 - static char Buff21[ 12], Buff22[ 12]; // Max2 = 2*Max1 + 2 = 10 - static char Buff31[ 25], Buff32[ 25]; // Max3 = 2*Max2 + 2 = 22 - static char Buff41[ 50], Buff42[ 50]; // Max4 = 2*Max3 + 2 = 46 - static char Buff51[100], Buff52[100]; // Max5 = 2*Max4 + 2 = 94 - static char * pBuffs1[6] = { Buff01, Buff11, Buff21, Buff31, Buff41, Buff51 }; - static char * pBuffs2[6] = { Buff02, Buff12, Buff22, Buff32, Buff42, Buff52 }; - char * pBranch; - char * pBuffer1 = pBuffs1[Level]; - char * pBuffer2 = pBuffs2[Level]; - Super2_Gate_t * pGateNext1, * pGateNext2; - int fInvNext1, fInvNext2; - int RetValue; - - // consider the last level - assert( Level >= 0 ); - if ( pGate->pOne == NULL ) - { - if ( pGate->uTruth == 0 ) - { - pBuffer1[0] = (fInv? '1': '0'); - pBuffer1[1] = '$'; - pBuffer1[2] = 0; - } - else - { - pBuffer1[0] = (fInv? 'A' + ((int)pGate->pTwo): 'a' + ((int)pGate->pTwo)); - pBuffer1[1] = 0; - } - return pBuffer1; - } - assert( Level > 0 ); - - - // get the left branch - pGateNext1 = Super2_Regular(pGate->pOne); - fInvNext1 = Super2_IsComplement(pGate->pOne); - pBranch = Super2_LibWriteGate_rec(pGateNext1, fInvNext1, Level - 1); - // copy into Buffer1 - strcpy( pBuffer1, pBranch ); - - // get the right branch - pGateNext2 = Super2_Regular(pGate->pTwo); - fInvNext2 = Super2_IsComplement(pGate->pTwo); - pBranch = Super2_LibWriteGate_rec(pGateNext2, fInvNext2, Level - 1); - - // consider the case when comparison is not necessary - if ( fInvNext1 ^ fInvNext2 ) - { - if ( fInvNext1 > fInvNext2 ) - sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBuffer1, pBranch, (fInv? '>': ')') ); - else - sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBranch, pBuffer1, (fInv? '>': ')') ); - } - else - { - // compare the two branches - RetValue = Super2_LibWriteCompare( pBuffer1, pBranch ); - if ( RetValue == 1 ) - sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBuffer1, pBranch, (fInv? '>': ')') ); - else // if ( RetValue == -1 ) - { - sprintf( pBuffer2, "%c%s%s%c", (fInv? '<': '('), pBranch, pBuffer1, (fInv? '>': ')') ); - if ( RetValue == 0 ) - printf( "Strange!\n" ); - } - } - return pBuffer2; -} - -/**Function************************************************************* - - Synopsis [Compares the two branches of the tree.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Super2_LibWriteCompare( char * pStr1, char * pStr2 ) -{ - while ( 1 ) - { - // skip extra symbols - while ( *pStr1 && *pStr1 < 'A' ) - pStr1++; - while ( *pStr2 && *pStr2 < 'A' ) - pStr2++; - - // check if any one is finished - if ( *pStr1 == 0 || *pStr2 == 0 ) - { - if ( *pStr2 ) - return 1; - return -1; - } - - // compare - if ( *pStr1 == *pStr2 ) - { - pStr1++; - pStr2++; - } - else - { - if ( *pStr1 < *pStr2 ) - return 1; - return -1; - } - } - return 0; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/super/superGENERIC.c b/src/map/super/superGENERIC.c deleted file mode 100644 index 1f2b7651..00000000 --- a/src/map/super/superGENERIC.c +++ /dev/null @@ -1,46 +0,0 @@ -/**CFile**************************************************************** - - FileName [super__.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Pre-computation of supergates.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: super__.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "superInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/map/super/superGate.c b/src/map/super/superGate.c deleted file mode 100644 index 91a1e513..00000000 --- a/src/map/super/superGate.c +++ /dev/null @@ -1,1324 +0,0 @@ -/**CFile**************************************************************** - - FileName [superGate.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Pre-computation of supergates.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: superGate.c,v 1.7 2004/08/03 00:11:40 satrajit Exp $] - -***********************************************************************/ - -#include "superInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the bit masks -#define SUPER_MASK(n) ((~((unsigned)0)) >> (32-(n))) -#define SUPER_FULL (~((unsigned)0)) -#define SUPER_NO_VAR (-9999.0) -#define SUPER_EPSILON (0.001) - -// data structure for supergate precomputation -typedef struct Super_ManStruct_t_ Super_Man_t; // manager -typedef struct Super_GateStruct_t_ Super_Gate_t; // supergate - -struct Super_ManStruct_t_ -{ - // parameters - char * pName; // the original genlib file name - int nVarsMax; // the number of inputs - int nMints; // the number of minterms - int nLevels; // the number of logic levels - float tDelayMax; // the max delay of the supergates in the library - float tAreaMax; // the max area of the supergates in the library - int fSkipInv; // the flag says about skipping inverters - int fWriteOldFormat; // in addition, writes the file in the old format - int fVerbose; - - // supergates - Super_Gate_t * pInputs[10]; // the input supergates - int nGates; // the number of gates in the library - Super_Gate_t ** pGates; // the gates themselves - stmm_table * tTable; // mapping of truth tables into gates - - // memory managers - Extra_MmFixed_t * pMem; // memory manager for the supergates - Extra_MmFlex_t * pMemFlex; // memory manager for the fanin arrays - - // statistics - int nTried; // the total number of tried - int nAdded; // the number of entries added - int nRemoved; // the number of entries removed - int nUnique; // the number of unique gates - int nLookups; // the number of hash table lookups - int nAliases; // the number of hash table lookups thrown away due to aliasing - - // runtime - int Time; // the runtime of the generation procedure - int TimeLimit; // the runtime limit (in seconds) - int TimeSec; // the time passed (in seconds) - int TimeStop; // the time to stop computation (in miliseconds) - int TimePrint; // the time to print message -}; - -struct Super_GateStruct_t_ -{ - Mio_Gate_t * pRoot; // the root gate for this supergate - unsigned fVar : 1; // the flag signaling the elementary variable - unsigned fSuper : 1; // the flag signaling the elementary variable - unsigned nFanins : 6; // the number of fanin gates - unsigned Number : 24; // the number assigned in the process - unsigned uTruth[2]; // the truth table of this supergate - Super_Gate_t * pFanins[6]; // the fanins of the gate - float Area; // the area of this gate - float ptDelays[6]; // the pin-to-pin delays for all inputs - float tDelayMax; // the maximum delay - Super_Gate_t * pNext; // the next gate in the table -}; - - -// iterating through the gates in the library -#define Super_ManForEachGate( GateArray, Limit, Index, Gate ) \ - for ( Index = 0; \ - Index < Limit && (Gate = GateArray[Index]); \ - Index++ ) - -// static functions -static Super_Man_t * Super_ManStart(); -static void Super_ManStop( Super_Man_t * pMan ); - -static void Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate ); -static void Super_First( Super_Man_t * pMan, int nVarsMax ); -static Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, bool fSkipInv ); -static Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers, unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins ); -static bool Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins ); -static int Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); -static int Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); -static void Super_TranferGatesToArray( Super_Man_t * pMan ); -static int Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan ); - -static void Super_Write( Super_Man_t * pMan ); -static int Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ); -static void Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile ); - -static void Super_WriteLibrary( Super_Man_t * pMan ); -static void Super_WriteLibraryGate( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pGate, int Num ); -static char * Super_WriteLibraryGateName( Super_Gate_t * pGate ); -static void Super_WriteLibraryGateName_rec( Super_Gate_t * pGate, char * pBuffer ); - -static void Super_WriteLibraryTree( Super_Man_t * pMan ); -static void Super_WriteLibraryTree_rec( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Precomputes the library of supergates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_Precompute( Mio_Library_t * pLibGen, int nVarsMax, int nLevels, float tDelayMax, float tAreaMax, int TimeLimit, bool fSkipInv, bool fWriteOldFormat, int fVerbose ) -{ - Super_Man_t * pMan; - Mio_Gate_t ** ppGates; - int nGates, Level, clk, clockStart; - - assert( nVarsMax < 7 ); - - // get the root gates - ppGates = Mio_CollectRoots( pLibGen, nVarsMax, tDelayMax, 0, &nGates ); - - // start the manager - pMan = Super_ManStart(); - pMan->pName = Mio_LibraryReadName(pLibGen); - pMan->fSkipInv = fSkipInv; - pMan->tDelayMax = tDelayMax; - pMan->tAreaMax = tAreaMax; - pMan->TimeLimit = TimeLimit; // in seconds - pMan->TimeStop = TimeLimit * CLOCKS_PER_SEC + clock(); // in CPU ticks - pMan->fWriteOldFormat = fWriteOldFormat; - pMan->fVerbose = fVerbose; - - if ( nGates == 0 ) - { - fprintf( stderr, "Error: No genlib gates satisfy the limits criteria. Stop.\n"); - fprintf( stderr, "Limits: max delay = %.2f, max area = %.2f, time limit = %d sec.\n", - pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit ); - - // stop the manager - Super_ManStop( pMan ); - free( ppGates ); - - return; - } - - // get the starting supergates - Super_First( pMan, nVarsMax ); - - // perform the computation of supergates - clockStart = clock(); -if ( fVerbose ) -{ - printf( "Computing supergates with %d inputs and %d levels.\n", - pMan->nVarsMax, nLevels ); - printf( "Limits: max delay = %.2f, max area = %.2f, time limit = %d sec.\n", - pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit ); -} - - for ( Level = 1; Level <= nLevels; Level++ ) - { - if ( clock() > pMan->TimeStop ) - break; -clk = clock(); - Super_Compute( pMan, ppGates, nGates, fSkipInv ); - pMan->nLevels = Level; -if ( fVerbose ) -{ - printf( "Lev %d: Try =%12d. Add =%6d. Rem =%5d. Save =%6d. Lookups =%12d. Aliases =%12d. ", - Level, pMan->nTried, pMan->nAdded, pMan->nRemoved, pMan->nAdded - pMan->nRemoved, pMan->nLookups, pMan->nAliases ); -PRT( "Time", clock() - clk ); -fflush( stdout ); -} - } - pMan->Time = clock() - clockStart; - -if ( fVerbose ) -{ -printf( "Writing the output file...\n" ); -fflush( stdout ); -} - // write them into a file - Super_Write( pMan ); - - // stop the manager - Super_ManStop( pMan ); - free( ppGates ); -} - - -/**Function************************************************************* - - Synopsis [Derives the starting supergates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_First( Super_Man_t * pMan, int nVarsMax ) -{ - Super_Gate_t * pSuper; - int nMintLimit, nVarLimit; - int v, m; - // set the parameters - pMan->nVarsMax = nVarsMax; - pMan->nMints = (1 << nVarsMax); - pMan->nLevels = 0; - // allocate room for the gates - pMan->nGates = nVarsMax; - pMan->pGates = ALLOC( Super_Gate_t *, nVarsMax + 2 ); - // create the gates corresponding to the elementary variables - for ( v = 0; v < nVarsMax; v++ ) - { - // get a new gate - pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); - memset( pSuper, 0, sizeof(Super_Gate_t) ); - // assign the elementary variable, the truth table, and the delays - pSuper->fVar = 1; - pSuper->Number = v; - for ( m = 0; m < nVarsMax; m++ ) - pSuper->ptDelays[m] = SUPER_NO_VAR; - pSuper->ptDelays[v] = 0.0; - // set the gate - pMan->pGates[v] = pSuper; - Super_AddGateToTable( pMan, pSuper ); - pMan->pInputs[v] = pSuper; - } - // set up their truth tables - nVarLimit = (nVarsMax >= 5)? 5 : nVarsMax; - nMintLimit = (1 << nVarLimit); - for ( m = 0; m < nMintLimit; m++ ) - for ( v = 0; v < nVarLimit; v++ ) - if ( m & (1 << v) ) - pMan->pGates[v]->uTruth[0] |= (1 << m); - // make adjustments for the case of 6 variables - if ( nVarsMax == 6 ) - { - for ( v = 0; v < 5; v++ ) - pMan->pGates[v]->uTruth[1] = pMan->pGates[v]->uTruth[0]; - pMan->pGates[5]->uTruth[0] = 0; - pMan->pGates[5]->uTruth[1] = ~((unsigned)0); - } - else - { - for ( v = 0; v < nVarsMax; v++ ) - pMan->pGates[v]->uTruth[1] = 0; - } -} - -/**Function************************************************************* - - Synopsis [Precomputes one level of supergates.] - - Description [This procedure computes the set of supergates that can be - derived from the given set of root gates (from GENLIB library) by composing - the root gates with the currently available supergates. This procedure is - smart in the sense that it tries to avoid useless emuration by imposing - tight bounds by area and delay. Only the supergates and are guaranteed to - have smaller area and delay are enumereated. See comments below for details.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Super_Man_t * Super_Compute( Super_Man_t * pMan, Mio_Gate_t ** ppGates, int nGates, bool fSkipInv ) -{ - Super_Gate_t * pSupers[6], * pGate0, * pGate1, * pGate2, * pGate3, * pGate4, * pGate5, * pGateNew; - float tPinDelaysRes[6], * ptPinDelays[6], tPinDelayMax, tDelayMio; - float Area, Area0, Area1, Area2, Area3, Area4, AreaMio; - unsigned uTruth[2], uTruths[6][2]; - int i0, i1, i2, i3, i4, i5; - Super_Gate_t ** ppGatesLimit; - int nFanins, nGatesLimit, k, s, t; - ProgressBar * pProgress; - int fTimeOut; - int fPrune = 1; // Shall we prune? - int iPruneLimit = 3; // Each of the gates plugged into the root gate will have - // less than these many fanins - int iPruneLimitRoot = 4; // The root gate may have only less than these many fanins - - // put the gates from the unique table into the array - // the gates from the array will be used to compose other gates - // the gates in tbe table are used to check uniqueness of collected gates - Super_TranferGatesToArray( pMan ); - - // sort the gates in the increasing order of maximum delay - if ( pMan->nGates > 10000 ) - { - printf( "Sorting array of %d supergates...\r", pMan->nGates ); - fflush( stdout ); - } - qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *), - (int (*)(const void *, const void *)) Super_DelayCompare ); - assert( Super_DelayCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 ); - if ( pMan->nGates > 10000 ) - { - printf( " \r" ); - } - - pProgress = Extra_ProgressBarStart( stdout, pMan->TimeLimit ); - pMan->TimePrint = clock() + CLOCKS_PER_SEC; - ppGatesLimit = ALLOC( Super_Gate_t *, pMan->nGates ); - // go through the root gates - // the root gates are sorted in the increasing gelay - fTimeOut = 0; - for ( k = 0; k < nGates; k++ ) - { - if ( fTimeOut ) break; - - if ( fPrune ) - { - if ( pMan->nLevels >= 1 ) // First level gates have been computed - { - if ( Mio_GateReadInputs(ppGates[k]) >= iPruneLimitRoot ) - continue; - } - } - - // select the subset of gates to be considered with this root gate - // all the gates past this point will lead to delay larger than the limit - tDelayMio = (float)Mio_GateReadDelayMax(ppGates[k]); - for ( s = 0, t = 0; s < pMan->nGates; s++ ) - { - if ( fPrune && ( pMan->nLevels >= 1 ) && ( ((int)pMan->pGates[s]->nFanins) >= iPruneLimit )) - continue; - - ppGatesLimit[t] = pMan->pGates[s]; - if ( ppGatesLimit[t++]->tDelayMax + tDelayMio > pMan->tDelayMax ) - break; - } - nGatesLimit = t; - - if ( pMan->fVerbose ) - { - printf ("Trying %d choices for %d inputs\n", t, Mio_GateReadInputs(ppGates[k]) ); - } - - // resort part of this range by area - // now we can prune the search by going up in the list until we reach the limit on area - // all the gates beyond this point can be skipped because their area can be only larger - if ( nGatesLimit > 10000 ) - printf( "Sorting array of %d supergates...\r", nGatesLimit ); - qsort( (void *)ppGatesLimit, nGatesLimit, sizeof(Super_Gate_t *), - (int (*)(const void *, const void *)) Super_AreaCompare ); - assert( Super_AreaCompare( ppGatesLimit, ppGatesLimit + nGatesLimit - 1 ) <= 0 ); - if ( nGatesLimit > 10000 ) - printf( " \r" ); - - // consider the combinations of gates with the root gate on top - AreaMio = (float)Mio_GateReadArea(ppGates[k]); - nFanins = Mio_GateReadInputs(ppGates[k]); - switch ( nFanins ) - { - case 0: // should not happen - assert( 0 ); - break; - case 1: // interter root - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) - { - if ( fTimeOut ) break; - fTimeOut = Super_CheckTimeout( pProgress, pMan ); - // skip the inverter as the root gate before the elementary variable - // as a result, the supergates will not have inverters on the input side - // but inverters still may occur at the output of or inside complex supergates - if ( fSkipInv && pGate0->tDelayMax == 0 ) - continue; - // compute area - Area = AreaMio + pGate0->Area; - if ( Area > pMan->tAreaMax ) - break; - - pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; - Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); - Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); - if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) - continue; - // create a new gate - pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); - Super_AddGateToTable( pMan, pGateNew ); - } - break; - case 2: // two-input root gate - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) - { - Area0 = AreaMio + pGate0->Area; - if ( Area0 > pMan->tAreaMax ) - break; - pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) - if ( i1 != i0 ) - { - if ( fTimeOut ) goto done; - fTimeOut = Super_CheckTimeout( pProgress, pMan ); - // compute area - Area = Area0 + pGate1->Area; - if ( Area > pMan->tAreaMax ) - break; - - pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; - Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); - Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); - if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) - continue; - // create a new gate - pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); - Super_AddGateToTable( pMan, pGateNew ); - } - } - break; - case 3: // three-input root gate - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) - { - Area0 = AreaMio + pGate0->Area; - if ( Area0 > pMan->tAreaMax ) - break; - pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) - if ( i1 != i0 ) - { - Area1 = Area0 + pGate1->Area; - if ( Area1 > pMan->tAreaMax ) - break; - pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) - if ( i2 != i0 && i2 != i1 ) - { - if ( fTimeOut ) goto done; - fTimeOut = Super_CheckTimeout( pProgress, pMan ); - // compute area - Area = Area1 + pGate2->Area; - if ( Area > pMan->tAreaMax ) - break; - pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; - - Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); - Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); - if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) - continue; - // create a new gate - pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); - Super_AddGateToTable( pMan, pGateNew ); - } - } - } - break; - case 4: // four-input root gate - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) - { - Area0 = AreaMio + pGate0->Area; - if ( Area0 > pMan->tAreaMax ) - break; - pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) - if ( i1 != i0 ) - { - Area1 = Area0 + pGate1->Area; - if ( Area1 > pMan->tAreaMax ) - break; - pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) - if ( i2 != i0 && i2 != i1 ) - { - Area2 = Area1 + pGate2->Area; - if ( Area2 > pMan->tAreaMax ) - break; - pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) - if ( i3 != i0 && i3 != i1 && i3 != i2 ) - { - if ( fTimeOut ) goto done; - fTimeOut = Super_CheckTimeout( pProgress, pMan ); - // compute area - Area = Area2 + pGate3->Area; - if ( Area > pMan->tAreaMax ) - break; - pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; - - Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); - Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); - if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) - continue; - // create a new gate - pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); - Super_AddGateToTable( pMan, pGateNew ); - } - } - } - } - break; - case 5: // five-input root gate - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) - { - Area0 = AreaMio + pGate0->Area; - if ( Area0 > pMan->tAreaMax ) - break; - pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) - if ( i1 != i0 ) - { - Area1 = Area0 + pGate1->Area; - if ( Area1 > pMan->tAreaMax ) - break; - pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) - if ( i2 != i0 && i2 != i1 ) - { - Area2 = Area1 + pGate2->Area; - if ( Area2 > pMan->tAreaMax ) - break; - pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) - if ( i3 != i0 && i3 != i1 && i3 != i2 ) - { - Area3 = Area2 + pGate3->Area; - if ( Area3 > pMan->tAreaMax ) - break; - pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 ) - if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 ) - { - if ( fTimeOut ) goto done; - fTimeOut = Super_CheckTimeout( pProgress, pMan ); - // compute area - Area = Area3 + pGate4->Area; - if ( Area > pMan->tAreaMax ) - break; - pSupers[4] = pGate4; uTruths[4][0] = pGate4->uTruth[0]; uTruths[4][1] = pGate4->uTruth[1]; ptPinDelays[4] = pGate4->ptDelays; - - Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); - Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); - if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) - continue; - // create a new gate - pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); - Super_AddGateToTable( pMan, pGateNew ); - } - } - } - } - } - break; - case 6: // six-input root gate - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i0, pGate0 ) - { - Area0 = AreaMio + pGate0->Area; - if ( Area0 > pMan->tAreaMax ) - break; - pSupers[0] = pGate0; uTruths[0][0] = pGate0->uTruth[0]; uTruths[0][1] = pGate0->uTruth[1]; ptPinDelays[0] = pGate0->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i1, pGate1 ) - if ( i1 != i0 ) - { - Area1 = Area0 + pGate1->Area; - if ( Area1 > pMan->tAreaMax ) - break; - pSupers[1] = pGate1; uTruths[1][0] = pGate1->uTruth[0]; uTruths[1][1] = pGate1->uTruth[1]; ptPinDelays[1] = pGate1->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i2, pGate2 ) - if ( i2 != i0 && i2 != i1 ) - { - Area2 = Area1 + pGate2->Area; - if ( Area2 > pMan->tAreaMax ) - break; - pSupers[2] = pGate2; uTruths[2][0] = pGate2->uTruth[0]; uTruths[2][1] = pGate2->uTruth[1]; ptPinDelays[2] = pGate2->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i3, pGate3 ) - if ( i3 != i0 && i3 != i1 && i3 != i2 ) - { - Area3 = Area2 + pGate3->Area; - if ( Area3 > pMan->tAreaMax ) - break; - pSupers[3] = pGate3; uTruths[3][0] = pGate3->uTruth[0]; uTruths[3][1] = pGate3->uTruth[1]; ptPinDelays[3] = pGate3->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i4, pGate4 ) - if ( i4 != i0 && i4 != i1 && i4 != i2 && i4 != i3 ) - { - if ( fTimeOut ) break; - fTimeOut = Super_CheckTimeout( pProgress, pMan ); - // compute area - Area4 = Area3 + pGate4->Area; - if ( Area > pMan->tAreaMax ) - break; - pSupers[4] = pGate4; uTruths[4][0] = pGate4->uTruth[0]; uTruths[4][1] = pGate4->uTruth[1]; ptPinDelays[4] = pGate4->ptDelays; - - Super_ManForEachGate( ppGatesLimit, nGatesLimit, i5, pGate5 ) - if ( i5 != i0 && i5 != i1 && i5 != i2 && i5 != i3 && i5 != i4 ) - { - if ( fTimeOut ) goto done; - fTimeOut = Super_CheckTimeout( pProgress, pMan ); - // compute area - Area = Area4 + pGate5->Area; - if ( Area > pMan->tAreaMax ) - break; - pSupers[5] = pGate5; uTruths[5][0] = pGate5->uTruth[0]; uTruths[5][1] = pGate5->uTruth[1]; ptPinDelays[5] = pGate5->ptDelays; - - Mio_DeriveGateDelays( ppGates[k], ptPinDelays, nFanins, pMan->nVarsMax, SUPER_NO_VAR, tPinDelaysRes, &tPinDelayMax ); - Mio_DeriveTruthTable( ppGates[k], uTruths, nFanins, pMan->nVarsMax, uTruth ); - if ( !Super_CompareGates( pMan, uTruth, Area, tPinDelaysRes, pMan->nVarsMax ) ) - continue; - // create a new gate - pGateNew = Super_CreateGateNew( pMan, ppGates[k], pSupers, nFanins, uTruth, Area, tPinDelaysRes, tPinDelayMax, pMan->nVarsMax ); - Super_AddGateToTable( pMan, pGateNew ); - } - } - } - } - } - } - break; - default : - assert( 0 ); - break; - } - } -done: - Extra_ProgressBarStop( pProgress ); - free( ppGatesLimit ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Transfers gates from table into the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Super_CheckTimeout( ProgressBar * pPro, Super_Man_t * pMan ) -{ - int TimeNow = clock(); - if ( TimeNow > pMan->TimePrint ) - { - Extra_ProgressBarUpdate( pPro, ++pMan->TimeSec, NULL ); - pMan->TimePrint = clock() + CLOCKS_PER_SEC; - } - if ( TimeNow > pMan->TimeStop ) - { - printf ("Timeout!\n"); - return 1; - } - pMan->nTried++; - return 0; -} - - -/**Function************************************************************* - - Synopsis [Transfers gates from table into the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_TranferGatesToArray( Super_Man_t * pMan ) -{ - stmm_generator * gen; - Super_Gate_t * pGate, * pList; - unsigned Key; - - // put the gates fron the table into the array - free( pMan->pGates ); - pMan->pGates = ALLOC( Super_Gate_t *, pMan->nAdded ); - pMan->nGates = 0; - stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pList ) - { - for ( pGate = pList; pGate; pGate = pGate->pNext ) - pMan->pGates[ pMan->nGates++ ] = pGate; - } -// assert( pMan->nGates == pMan->nAdded - pMan->nRemoved ); -} - -/**Function************************************************************* - - Synopsis [Adds one supergate into the unique table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_AddGateToTable( Super_Man_t * pMan, Super_Gate_t * pGate ) -{ - Super_Gate_t ** ppList; - unsigned Key; -// Key = pGate->uTruth[0] + 2003 * pGate->uTruth[1]; - Key = pGate->uTruth[0] ^ pGate->uTruth[1]; - if ( !stmm_find_or_add( pMan->tTable, (char *)Key, (char ***)&ppList ) ) - *ppList = NULL; - pGate->pNext = *ppList; - *ppList = pGate; - pMan->nAdded++; -} - -/**Function************************************************************* - - Synopsis [Check the manager's unique table for comparable gates.] - - Description [Returns 0 if the gate is dominated by others. Returns 1 - if the gate is new or is better than the available ones. In this case, - cleans the table by removing the gates that are worse than the given one.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Super_CompareGates( Super_Man_t * pMan, unsigned uTruth[], float Area, float tPinDelaysRes[], int nPins ) -{ - Super_Gate_t ** ppList, * pPrev, * pGate, * pGate2; - int i, fNewIsBetter, fGateIsBetter; - unsigned Key; - - // skip constant functions - if ( pMan->nVarsMax < 6 ) - { - if ( uTruth[0] == 0 || ~uTruth[0] == 0 ) - return 0; - } - else - { - if ( ( uTruth[0] == 0 && uTruth[1] == 0 ) || ( ~uTruth[0] == 0 && ~uTruth[1] == 0 ) ) - return 0; - } - - // get hold of the place where the entry is stored -// Key = uTruth[0] + 2003 * uTruth[1]; - Key = uTruth[0] ^ uTruth[1]; - if ( !stmm_find( pMan->tTable, (char *)Key, (char ***)&ppList ) ) - return 1; - // the entry with this truth table is found - pPrev = NULL; - for ( pGate = *ppList, pGate2 = pGate? pGate->pNext: NULL; pGate; - pGate = pGate2, pGate2 = pGate? pGate->pNext: NULL ) - { - pMan->nLookups++; - if ( pGate->uTruth[0] != uTruth[0] || pGate->uTruth[1] != uTruth[1] ) - { - pMan->nAliases++; - continue; - } - fGateIsBetter = 0; - fNewIsBetter = 0; - if ( pGate->Area + SUPER_EPSILON < Area ) - fGateIsBetter = 1; - else if ( pGate->Area > Area + SUPER_EPSILON ) - fNewIsBetter = 1; - for ( i = 0; i < nPins; i++ ) - { - if ( pGate->ptDelays[i] == SUPER_NO_VAR || tPinDelaysRes[i] == SUPER_NO_VAR ) - continue; - if ( pGate->ptDelays[i] + SUPER_EPSILON < tPinDelaysRes[i] ) - fGateIsBetter = 1; - else if ( pGate->ptDelays[i] > tPinDelaysRes[i] + SUPER_EPSILON ) - fNewIsBetter = 1; - if ( fGateIsBetter && fNewIsBetter ) - break; - } - // consider 4 cases - if ( fGateIsBetter && fNewIsBetter ) // Pareto points; save both - pPrev = pGate; - else if ( fNewIsBetter ) // gate is worse; remove the gate - { - if ( pPrev == NULL ) - *ppList = pGate->pNext; - else - pPrev->pNext = pGate->pNext; - Extra_MmFixedEntryRecycle( pMan->pMem, (char *)pGate ); - pMan->nRemoved++; - } - else if ( fGateIsBetter ) // new is worse, already dominated no need to see others - return 0; - else // if ( !fGateIsBetter && !fNewIsBetter ) // they are identical, no need to see others - return 0; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Create a new supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Super_Gate_t * Super_CreateGateNew( Super_Man_t * pMan, Mio_Gate_t * pRoot, Super_Gate_t ** pSupers, int nSupers, - unsigned uTruth[], float Area, float tPinDelaysRes[], float tDelayMax, int nPins ) -{ - Super_Gate_t * pSuper; - pSuper = (Super_Gate_t *)Extra_MmFixedEntryFetch( pMan->pMem ); - memset( pSuper, 0, sizeof(Super_Gate_t) ); - pSuper->pRoot = pRoot; - pSuper->uTruth[0] = uTruth[0]; - pSuper->uTruth[1] = uTruth[1]; - memcpy( pSuper->ptDelays, tPinDelaysRes, sizeof(float) * nPins ); - pSuper->Area = Area; - pSuper->nFanins = nSupers; - memcpy( pSuper->pFanins, pSupers, sizeof(Super_Gate_t *) * nSupers ); - pSuper->pNext = NULL; - pSuper->tDelayMax = tDelayMax; - return pSuper; -} - -/**Function************************************************************* - - Synopsis [Starts the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Super_Man_t * Super_ManStart() -{ - Super_Man_t * pMan; - pMan = ALLOC( Super_Man_t, 1 ); - memset( pMan, 0, sizeof(Super_Man_t) ); - pMan->pMem = Extra_MmFixedStart( sizeof(Super_Gate_t) ); - pMan->tTable = stmm_init_table( st_ptrcmp, st_ptrhash ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Stops the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_ManStop( Super_Man_t * pMan ) -{ - Extra_MmFixedStop( pMan->pMem ); - if ( pMan->tTable ) stmm_free_table( pMan->tTable ); - FREE( pMan->pGates ); - free( pMan ); -} - - - - - -/**Function************************************************************* - - Synopsis [Writes the supergate library into the file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_Write( Super_Man_t * pMan ) -{ - Super_Gate_t * pGateRoot, * pGate; - stmm_generator * gen; - int fZeroFound, clk, v; - unsigned Key; - - if ( pMan->nGates < 1 ) - { - printf( "The generated library is empty. No output file written.\n" ); - return; - } - - // Filters the supergates by removing those that have fewer inputs than - // the given limit, provided that the inputs are not consequtive. - // For example, NAND2(a,c) is removed, but NAND2(a,b) is left, - // because a and b are consequtive. - FREE( pMan->pGates ); - pMan->pGates = ALLOC( Super_Gate_t *, pMan->nAdded ); - pMan->nGates = 0; - stmm_foreach_item( pMan->tTable, gen, (char **)&Key, (char **)&pGateRoot ) - { - for ( pGate = pGateRoot; pGate; pGate = pGate->pNext ) - { - // skip the elementary variables - if ( pGate->pRoot == NULL ) - continue; - // skip the non-consequtive gates - fZeroFound = 0; - for ( v = 0; v < pMan->nVarsMax; v++ ) - if ( pGate->ptDelays[v] < SUPER_NO_VAR + SUPER_EPSILON ) - fZeroFound = 1; - else if ( fZeroFound ) - break; - if ( v < pMan->nVarsMax ) - continue; - // save the unique gate - pMan->pGates[ pMan->nGates++ ] = pGate; - } - } - -clk = clock(); - // sort the supergates by truth table - qsort( (void *)pMan->pGates, pMan->nGates, sizeof(Super_Gate_t *), - (int (*)(const void *, const void *)) Super_WriteCompare ); - assert( Super_WriteCompare( pMan->pGates, pMan->pGates + pMan->nGates - 1 ) <= 0 ); -if ( pMan->fVerbose ) -{ -PRT( "Sorting", clock() - clk ); -} - - - // write library in the old format -clk = clock(); - if ( pMan->fWriteOldFormat ) - Super_WriteLibrary( pMan ); -if ( pMan->fVerbose ) -{ -PRT( "Writing old format", clock() - clk ); -} - - // write the tree-like structure of supergates -clk = clock(); - Super_WriteLibraryTree( pMan ); -if ( pMan->fVerbose ) -{ -PRT( "Writing new format", clock() - clk ); -} -} - - -/**Function************************************************************* - - Synopsis [Writes the file header.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_WriteFileHeader( Super_Man_t * pMan, FILE * pFile ) -{ - fprintf( pFile, "#\n" ); - fprintf( pFile, "# Supergate library derived for \"%s\" on %s.\n", pMan->pName, Extra_TimeStamp() ); - fprintf( pFile, "#\n" ); - fprintf( pFile, "# Command line: \"super -i %d -l %d -d %.2f -a %.2f -t %d %s %s\".\n", - pMan->nVarsMax, pMan->nLevels, pMan->tDelayMax, pMan->tAreaMax, pMan->TimeLimit, (pMan->fSkipInv? "" : "-s"), pMan->pName ); - fprintf( pFile, "#\n" ); - fprintf( pFile, "# The number of inputs = %10d.\n", pMan->nVarsMax ); - fprintf( pFile, "# The number of levels = %10d.\n", pMan->nLevels ); - fprintf( pFile, "# The maximum delay = %10.2f.\n", pMan->tDelayMax ); - fprintf( pFile, "# The maximum area = %10.2f.\n", pMan->tAreaMax ); - fprintf( pFile, "# The maximum runtime (sec) = %10d.\n", pMan->TimeLimit ); - fprintf( pFile, "#\n" ); - fprintf( pFile, "# The number of attempts = %10d.\n", pMan->nTried ); - fprintf( pFile, "# The number of supergates = %10d.\n", pMan->nGates ); - fprintf( pFile, "# The number of functions = %10d.\n", pMan->nUnique ); - fprintf( pFile, "# The total functions = %.0f (2^%d).\n", pow(2,pMan->nMints), pMan->nMints ); - fprintf( pFile, "#\n" ); - fprintf( pFile, "# Generation time (sec) = %10.2f.\n", (float)(pMan->Time)/(float)(CLOCKS_PER_SEC) ); - fprintf( pFile, "#\n" ); - fprintf( pFile, "%s\n", pMan->pName ); - fprintf( pFile, "%d\n", pMan->nVarsMax ); - fprintf( pFile, "%d\n", pMan->nGates ); -} - -/**Function************************************************************* - - Synopsis [Compares the truth tables of two gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Super_WriteCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) -{ - unsigned * pTruth1 = (*ppG1)->uTruth; - unsigned * pTruth2 = (*ppG2)->uTruth; - if ( pTruth1[1] < pTruth2[1] ) - return -1; - if ( pTruth1[1] > pTruth2[1] ) - return 1; - if ( pTruth1[0] < pTruth2[0] ) - return -1; - if ( pTruth1[0] > pTruth2[0] ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Compares the max delay of two gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Super_DelayCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) -{ - if ( (*ppG1)->tDelayMax < (*ppG2)->tDelayMax ) - return -1; - if ( (*ppG1)->tDelayMax > (*ppG2)->tDelayMax ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Compares the area of two gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Super_AreaCompare( Super_Gate_t ** ppG1, Super_Gate_t ** ppG2 ) -{ - if ( (*ppG1)->Area < (*ppG2)->Area ) - return -1; - if ( (*ppG1)->Area > (*ppG2)->Area ) - return 1; - return 0; -} - - - - - - -/**Function************************************************************* - - Synopsis [Writes the gates into the file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_WriteLibrary( Super_Man_t * pMan ) -{ - Super_Gate_t * pGate, * pGateNext; - FILE * pFile; - char FileName[100]; - char * pNameGeneric; - int i, Counter; - - // get the file name - pNameGeneric = Extra_FileNameGeneric( pMan->pName ); - sprintf( FileName, "%s.super_old", pNameGeneric ); - free( pNameGeneric ); - - // count the number of unique functions - pMan->nUnique = 1; - Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate ) - { - if ( i == pMan->nGates - 1 ) - break; - // print the newline if this gate is different from the following one - pGateNext = pMan->pGates[i+1]; - if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] ) - pMan->nUnique++; - } - - // start the file - pFile = fopen( FileName, "w" ); - Super_WriteFileHeader( pMan, pFile ); - - // print the gates - Counter = 0; - Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pGate ) - { - Super_WriteLibraryGate( pFile, pMan, pGate, ++Counter ); - if ( i == pMan->nGates - 1 ) - break; - // print the newline if this gate is different from the following one - pGateNext = pMan->pGates[i+1]; - if ( pGateNext->uTruth[0] != pGate->uTruth[0] || pGateNext->uTruth[1] != pGate->uTruth[1] ) - fprintf( pFile, "\n" ); - } - assert( Counter == pMan->nGates ); - fclose( pFile ); - -if ( pMan->fVerbose ) -{ - printf( "The supergates are written using old format \"%s\" ", FileName ); - printf( "(%0.3f Mb).\n", ((double)Extra_FileSize(FileName))/(1<<20) ); -} -} - -/**Function************************************************************* - - Synopsis [Writes the supergate into the file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_WriteLibraryGate( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pGate, int Num ) -{ - int i; - fprintf( pFile, "%04d ", Num ); // the number - Extra_PrintBinary( pFile, pGate->uTruth, pMan->nMints ); // the truth table - fprintf( pFile, " %5.2f", pGate->tDelayMax ); // the max delay - fprintf( pFile, " " ); - for ( i = 0; i < pMan->nVarsMax; i++ ) // the pin-to-pin delays - fprintf( pFile, " %5.2f", pGate->ptDelays[i]==SUPER_NO_VAR? 0.0 : pGate->ptDelays[i] ); - fprintf( pFile, " %5.2f", pGate->Area ); // the area - fprintf( pFile, " " ); - fprintf( pFile, "%s", Super_WriteLibraryGateName(pGate) ); // the symbolic expression - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Recursively generates symbolic name of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Super_WriteLibraryGateName( Super_Gate_t * pGate ) -{ - static char Buffer[2000]; - Buffer[0] = 0; - Super_WriteLibraryGateName_rec( pGate, Buffer ); - return Buffer; -} - -/**Function************************************************************* - - Synopsis [Recursively generates symbolic name of the supergate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_WriteLibraryGateName_rec( Super_Gate_t * pGate, char * pBuffer ) -{ - char Buffer[10]; - int i; - - if ( pGate->pRoot == NULL ) - { - sprintf( Buffer, "%c", 'a' + pGate->Number ); - strcat( pBuffer, Buffer ); - return; - } - strcat( pBuffer, Mio_GateReadName(pGate->pRoot) ); - strcat( pBuffer, "(" ); - for ( i = 0; i < (int)pGate->nFanins; i++ ) - { - if ( i ) - strcat( pBuffer, "," ); - Super_WriteLibraryGateName_rec( pGate->pFanins[i], pBuffer ); - } - strcat( pBuffer, ")" ); -} - - - - - -/**Function************************************************************* - - Synopsis [Recursively writes the gates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_WriteLibraryTree( Super_Man_t * pMan ) -{ - Super_Gate_t * pSuper; - FILE * pFile; - char FileName[100]; - char * pNameGeneric; - int i, Counter; - int posStart; - - // get the file name - pNameGeneric = Extra_FileNameGeneric( pMan->pName ); - sprintf( FileName, "%s.super", pNameGeneric ); - free( pNameGeneric ); - - // write the elementary variables - pFile = fopen( FileName, "w" ); - Super_WriteFileHeader( pMan, pFile ); - // write the place holder for the number of lines - posStart = ftell( pFile ); - fprintf( pFile, " \n" ); - // mark the real supergates - Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) - pSuper->fSuper = 1; - // write the supergates - Counter = pMan->nVarsMax; - Super_ManForEachGate( pMan->pGates, pMan->nGates, i, pSuper ) - Super_WriteLibraryTree_rec( pFile, pMan, pSuper, &Counter ); - fclose( pFile ); - // write the number of lines - pFile = fopen( FileName, "rb+" ); - fseek( pFile, posStart, SEEK_SET ); - fprintf( pFile, "%d", Counter ); - fclose( pFile ); - -if ( pMan->fVerbose ) -{ - printf( "The supergates are written using new format \"%s\" ", FileName ); - printf( "(%0.3f Mb).\n", ((double)Extra_FileSize(FileName))/(1<<20) ); -} -} - -/**Function************************************************************* - - Synopsis [Recursively writes the gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Super_WriteLibraryTree_rec( FILE * pFile, Super_Man_t * pMan, Super_Gate_t * pSuper, int * pCounter ) -{ - int nFanins, i; - // skip an elementary variable and a gate that was already written - if ( pSuper->fVar || pSuper->Number > 0 ) - return; - // write the fanins - nFanins = Mio_GateReadInputs(pSuper->pRoot); - for ( i = 0; i < nFanins; i++ ) - Super_WriteLibraryTree_rec( pFile, pMan, pSuper->pFanins[i], pCounter ); - // finally write the gate - pSuper->Number = (*pCounter)++; - fprintf( pFile, "%s", pSuper->fSuper? "* " : "" ); - fprintf( pFile, "%s", Mio_GateReadName(pSuper->pRoot) ); - for ( i = 0; i < nFanins; i++ ) - fprintf( pFile, " %d", pSuper->pFanins[i]->Number ); - // write the formula - // this step is optional, the resulting library will work in any case - // however, it may be helpful to for debugging to compare the same library - // written in the old format and written in the new format with formulas -// fprintf( pFile, " # %s", Super_WriteLibraryGateName( pSuper ) ); - fprintf( pFile, "\n" ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/map/super/superInt.h b/src/map/super/superInt.h deleted file mode 100644 index ec6d0a38..00000000 --- a/src/map/super/superInt.h +++ /dev/null @@ -1,62 +0,0 @@ -/**CFile**************************************************************** - - FileName [superInt.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Pre-computation of supergates.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: superInt.h,v 1.4 2004/07/06 04:55:59 alanmi Exp $] - -***********************************************************************/ - -#ifndef __super_INT_H__ -#define __super_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "abc.h" -#include "mainInt.h" -#include "mvc.h" -#include "mio.h" -#include "stmm.h" -#include "super.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== superAnd.c =============================================================*/ -extern void Super2_Precompute( int nInputs, int nLevels, int fVerbose ); -/*=== superGate.c =============================================================*/ -extern void Super_Precompute( Mio_Library_t * pLibGen, int nInputs, int nLevels, float tDelayMax, float tAreaMax, int TimeLimit, bool fSkipInv, bool fWriteOldFormat, int fVerbose ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/map/super/superWrite.c b/src/map/super/superWrite.c deleted file mode 100644 index 395ef145..00000000 --- a/src/map/super/superWrite.c +++ /dev/null @@ -1,76 +0,0 @@ -/**CFile**************************************************************** - - FileName [superWrite.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Pre-computation of supergates.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 8, 2003.] - - Revision [$Id: superWrite.c,v 1.1 2004/04/03 01:36:45 alanmi Exp $] - -***********************************************************************/ - -#include "superInt.h" - -/* - One record in the supergate library file consists of: - - - - is a zero-based integer - is a string of 2^n bits representing the value of the function for each minterm - is the maximum delay of the gate - is the array of n double values - is a floating point value - is the string representing the gate in the following format: - GATENAME1( GATENAME2( a, c ), GATENAME3( a, d ), ... ) - The gate names (GATENAME1, etc) are the names as they appear in the .genlib library. - The primary inputs of the gates are denoted by lowercase chars 'a', 'b', etc. - The parantheses are mandatory for each gate, except for the wire. - The wire name can be omitted, so that "a" can be used instead of "**wire**( a )". - The spaces are optional in any position of this string. - - - The supergates are generated exhaustively from all gate combinations that - have the max delay lower than the delay given by the user, or until the specified time - limit is reached. - - The supergates are stored in supergate classes by their functionality. - Among the gates with the equivalent functionaly only those are dropped, which are - dominated by at least one other gate in the class in terms of both delay and area. - For the definition of gate dominance see pliGenCheckDominance(). -*/ - - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/espresso/cofactor.c b/src/misc/espresso/cofactor.c deleted file mode 100644 index b851a639..00000000 --- a/src/misc/espresso/cofactor.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - -/* - The cofactor of a cover against a cube "c" is a cover formed by the - cofactor of each cube in the cover against c. The cofactor of two - cubes is null if they are distance 1 or more apart. If they are - distance zero apart, the cofactor is the restriction of the cube - to the minterms of c. - - The cube list contains the following information: - - T[0] = pointer to a cube identifying the variables that have - been cofactored against - T[1] = pointer to just beyond the sentinel (i.e., T[n] in this case) - T[2] - . - . = pointers to cubes - . - T[n-2] - T[n-1] = NULL pointer (sentinel) - - - Cofactoring involves repeated application of "cdist0" to check if a - cube of the cover intersects the cofactored cube. This can be - slow, especially for the recursive descent of the espresso - routines. Therefore, a special cofactor routine "scofactor" is - provided which assumes the cofactor is only in a single variable. -*/ - - -/* cofactor -- compute the cofactor of a cover with respect to a cube */ -pcube *cofactor(T, c) -IN pcube *T; -IN register pcube c; -{ - pcube temp = cube.temp[0], *Tc_save, *Tc, *T1; - register pcube p; - int listlen; - - listlen = CUBELISTSIZE(T) + 5; - - /* Allocate a new list of cube pointers (max size is previous size) */ - Tc_save = Tc = ALLOC(pcube, listlen); - - /* pass on which variables have been cofactored against */ - *Tc++ = set_or(new_cube(), T[0], set_diff(temp, cube.fullset, c)); - Tc++; - - /* Loop for each cube in the list, determine suitability, and save */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (p != c) { - -#ifdef NO_INLINE - if (! cdist0(p, c)) goto false; -#else - {register int w,last;register unsigned int x;if((last=cube.inword)!=-1) - {x=p[last]&c[last];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w>1)&DISJOINT)goto false;}}}{register int w,var,last; - register pcube mask;for(var=cube.num_binary_vars;var= 0; i--) - count[i] = 0; - } - - /* Count the number of zeros in each column */ - { register int i, *cnt; - register unsigned int val; - register pcube p, cof = T[0], full = cube.fullset; - for(T1 = T+2; (p = *T1++) != NULL; ) - for(i = LOOP(p); i > 0; i--) - if (val = full[i] & ~ (p[i] | cof[i])) { - cnt = count + ((i-1) << LOGBPI); -#if BPI == 32 - if (val & 0xFF000000) { - if (val & 0x80000000) cnt[31]++; - if (val & 0x40000000) cnt[30]++; - if (val & 0x20000000) cnt[29]++; - if (val & 0x10000000) cnt[28]++; - if (val & 0x08000000) cnt[27]++; - if (val & 0x04000000) cnt[26]++; - if (val & 0x02000000) cnt[25]++; - if (val & 0x01000000) cnt[24]++; - } - if (val & 0x00FF0000) { - if (val & 0x00800000) cnt[23]++; - if (val & 0x00400000) cnt[22]++; - if (val & 0x00200000) cnt[21]++; - if (val & 0x00100000) cnt[20]++; - if (val & 0x00080000) cnt[19]++; - if (val & 0x00040000) cnt[18]++; - if (val & 0x00020000) cnt[17]++; - if (val & 0x00010000) cnt[16]++; - } -#endif - if (val & 0xFF00) { - if (val & 0x8000) cnt[15]++; - if (val & 0x4000) cnt[14]++; - if (val & 0x2000) cnt[13]++; - if (val & 0x1000) cnt[12]++; - if (val & 0x0800) cnt[11]++; - if (val & 0x0400) cnt[10]++; - if (val & 0x0200) cnt[ 9]++; - if (val & 0x0100) cnt[ 8]++; - } - if (val & 0x00FF) { - if (val & 0x0080) cnt[ 7]++; - if (val & 0x0040) cnt[ 6]++; - if (val & 0x0020) cnt[ 5]++; - if (val & 0x0010) cnt[ 4]++; - if (val & 0x0008) cnt[ 3]++; - if (val & 0x0004) cnt[ 2]++; - if (val & 0x0002) cnt[ 1]++; - if (val & 0x0001) cnt[ 0]++; - } - } - } - - /* - * Perform counts for each variable: - * cdata.var_zeros[var] = number of zeros in the variable - * cdata.parts_active[var] = number of active parts for each variable - * cdata.vars_active = number of variables which are active - * cdata.vars_unate = number of variables which are active and unate - * - * best -- the variable which is best for splitting based on: - * mostactive -- most # active parts in any variable - * mostzero -- most # zeros in any variable - * mostbalanced -- minimum over the maximum # zeros / part / variable - */ - - { register int var, i, lastbit, active, maxactive; - int best = -1, mostactive = 0, mostzero = 0, mostbalanced = 32000; - cdata.vars_unate = cdata.vars_active = 0; - - for(var = 0; var < cube.num_vars; var++) { - if (var < cube.num_binary_vars) { /* special hack for binary vars */ - i = count[var*2]; - lastbit = count[var*2 + 1]; - active = (i > 0) + (lastbit > 0); - cdata.var_zeros[var] = i + lastbit; - maxactive = MAX(i, lastbit); - } else { - maxactive = active = cdata.var_zeros[var] = 0; - lastbit = cube.last_part[var]; - for(i = cube.first_part[var]; i <= lastbit; i++) { - cdata.var_zeros[var] += count[i]; - active += (count[i] > 0); - if (active > maxactive) maxactive = active; - } - } - - /* first priority is to maximize the number of active parts */ - /* for binary case, this will usually select the output first */ - if (active > mostactive) - best = var, mostactive = active, mostzero = cdata.var_zeros[best], - mostbalanced = maxactive; - else if (active == mostactive) - /* secondary condition is to maximize the number zeros */ - /* for binary variables, this is the same as minimum # of 2's */ - if (cdata.var_zeros[var] > mostzero) - best = var, mostzero = cdata.var_zeros[best], - mostbalanced = maxactive; - else if (cdata.var_zeros[var] == mostzero) - /* third condition is to pick a balanced variable */ - /* for binary vars, this means roughly equal # 0's and 1's */ - if (maxactive < mostbalanced) - best = var, mostbalanced = maxactive; - - cdata.parts_active[var] = active; - cdata.is_unate[var] = (active == 1); - cdata.vars_active += (active > 0); - cdata.vars_unate += (active == 1); - } - cdata.best = best; - } -} - -int binate_split_select(T, cleft, cright, debug_flag) -IN pcube *T; -IN register pcube cleft, cright; -IN int debug_flag; -{ - int best = cdata.best; - register int i, lastbit = cube.last_part[best], halfbit = 0; - register pcube cof=T[0]; - - /* Create the cubes to cofactor against */ - (void) set_diff(cleft, cube.fullset, cube.var_mask[best]); - (void) set_diff(cright, cube.fullset, cube.var_mask[best]); - for(i = cube.first_part[best]; i <= lastbit; i++) - if (! is_in_set(cof,i)) - halfbit++; - for(i = cube.first_part[best], halfbit = halfbit/2; halfbit > 0; i++) - if (! is_in_set(cof,i)) - halfbit--, set_insert(cleft, i); - for(; i <= lastbit; i++) - if (! is_in_set(cof,i)) - set_insert(cright, i); - - if (debug & debug_flag) { - (void) printf("BINATE_SPLIT_SELECT: split against %d\n", best); - if (verbose_debug) - (void) printf("cl=%s\ncr=%s\n", pc1(cleft), pc2(cright)); - } - return best; -} - - -pcube *cube1list(A) -pcover A; -{ - register pcube last, p, *plist, *list; - - list = plist = ALLOC(pcube, A->count + 3); - *plist++ = new_cube(); - plist++; - foreach_set(A, last, p) { - *plist++ = p; - } - *plist++ = NULL; /* sentinel */ - list[1] = (pcube) plist; - return list; -} - - -pcube *cube2list(A, B) -pcover A, B; -{ - register pcube last, p, *plist, *list; - - list = plist = ALLOC(pcube, A->count + B->count + 3); - *plist++ = new_cube(); - plist++; - foreach_set(A, last, p) { - *plist++ = p; - } - foreach_set(B, last, p) { - *plist++ = p; - } - *plist++ = NULL; - list[1] = (pcube) plist; - return list; -} - - -pcube *cube3list(A, B, C) -pcover A, B, C; -{ - register pcube last, p, *plist, *list; - - plist = ALLOC(pcube, A->count + B->count + C->count + 3); - list = plist; - *plist++ = new_cube(); - plist++; - foreach_set(A, last, p) { - *plist++ = p; - } - foreach_set(B, last, p) { - *plist++ = p; - } - foreach_set(C, last, p) { - *plist++ = p; - } - *plist++ = NULL; - list[1] = (pcube) plist; - return list; -} - - -pcover cubeunlist(A1) -pcube *A1; -{ - register int i; - register pcube p, pdest, cof = A1[0]; - register pcover A; - - A = new_cover(CUBELISTSIZE(A1)); - for(i = 2; (p = A1[i]) != NULL; i++) { - pdest = GETSET(A, i-2); - INLINEset_or(pdest, p, cof); - } - A->count = CUBELISTSIZE(A1); - return A; -} - -simplify_cubelist(T) -pcube *T; -{ - register pcube *Tdest; - register int i, ncubes; - - (void) set_copy(cube.temp[0], T[0]); /* retrieve cofactor */ - - ncubes = CUBELISTSIZE(T); - qsort((char *) (T+2), ncubes, sizeof(pset), (int (*)()) d1_order); - - Tdest = T+2; - /* *Tdest++ = T[2]; */ - for(i = 3; i < ncubes; i++) { - if (d1_order(&T[i-1], &T[i]) != 0) { - *Tdest++ = T[i]; - } - } - - *Tdest++ = NULL; /* sentinel */ - Tdest[1] = (pcube) Tdest; /* save pointer to last */ -} diff --git a/src/misc/espresso/cols.c b/src/misc/espresso/cols.c deleted file mode 100644 index ec3797e6..00000000 --- a/src/misc/espresso/cols.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -//#include "port.h" -#include "sparse_int.h" - - -/* - * allocate a new col vector - */ -sm_col * -sm_col_alloc() -{ - register sm_col *pcol; - -#ifdef FAST_AND_LOOSE - if (sm_col_freelist == NIL(sm_col)) { - pcol = ALLOC(sm_col, 1); - } else { - pcol = sm_col_freelist; - sm_col_freelist = pcol->next_col; - } -#else - pcol = ALLOC(sm_col, 1); -#endif - - pcol->col_num = 0; - pcol->length = 0; - pcol->first_row = pcol->last_row = NIL(sm_element); - pcol->next_col = pcol->prev_col = NIL(sm_col); - pcol->flag = 0; - pcol->user_word = NIL(char); /* for our user ... */ - return pcol; -} - - -/* - * free a col vector -- for FAST_AND_LOOSE, this is real cheap for cols; - * however, freeing a rowumn must still walk down the rowumn discarding - * the elements one-by-one; that is the only use for the extra '-DCOLS' - * compile flag ... - */ -void -sm_col_free(pcol) -register sm_col *pcol; -{ -#if defined(FAST_AND_LOOSE) && ! defined(COLS) - if (pcol->first_row != NIL(sm_element)) { - /* Add the linked list of col items to the free list */ - pcol->last_row->next_row = sm_element_freelist; - sm_element_freelist = pcol->first_row; - } - - /* Add the col to the free list of cols */ - pcol->next_col = sm_col_freelist; - sm_col_freelist = pcol; -#else - register sm_element *p, *pnext; - - for(p = pcol->first_row; p != 0; p = pnext) { - pnext = p->next_row; - sm_element_free(p); - } - FREE(pcol); -#endif -} - - -/* - * duplicate an existing col - */ -sm_col * -sm_col_dup(pcol) -register sm_col *pcol; -{ - register sm_col *pnew; - register sm_element *p; - - pnew = sm_col_alloc(); - for(p = pcol->first_row; p != 0; p = p->next_row) { - (void) sm_col_insert(pnew, p->row_num); - } - return pnew; -} - - -/* - * insert an element into a col vector - */ -sm_element * -sm_col_insert(pcol, row) -register sm_col *pcol; -register int row; -{ - register sm_element *test, *element; - - /* get a new item, save its address */ - sm_element_alloc(element); - test = element; - sorted_insert(sm_element, pcol->first_row, pcol->last_row, pcol->length, - next_row, prev_row, row_num, row, test); - - /* if item was not used, free it */ - if (element != test) { - sm_element_free(element); - } - - /* either way, return the current new value */ - return test; -} - - -/* - * remove an element from a col vector - */ -void -sm_col_remove(pcol, row) -register sm_col *pcol; -register int row; -{ - register sm_element *p; - - for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row) - ; - if (p != 0 && p->row_num == row) { - dll_unlink(p, pcol->first_row, pcol->last_row, - next_row, prev_row, pcol->length); - sm_element_free(p); - } -} - - -/* - * find an element (if it is in the col vector) - */ -sm_element * -sm_col_find(pcol, row) -sm_col *pcol; -int row; -{ - register sm_element *p; - - for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row) - ; - if (p != 0 && p->row_num == row) { - return p; - } else { - return NIL(sm_element); - } -} - -/* - * return 1 if col p2 contains col p1; 0 otherwise - */ -int -sm_col_contains(p1, p2) -sm_col *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_row; - q2 = p2->first_row; - while (q1 != 0) { - if (q2 == 0 || q1->row_num < q2->row_num) { - return 0; - } else if (q1->row_num == q2->row_num) { - q1 = q1->next_row; - q2 = q2->next_row; - } else { - q2 = q2->next_row; - } - } - return 1; -} - - -/* - * return 1 if col p1 and col p2 share an element in common - */ -int -sm_col_intersects(p1, p2) -sm_col *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_row; - q2 = p2->first_row; - if (q1 == 0 || q2 == 0) return 0; - for(;;) { - if (q1->row_num < q2->row_num) { - if ((q1 = q1->next_row) == 0) { - return 0; - } - } else if (q1->row_num > q2->row_num) { - if ((q2 = q2->next_row) == 0) { - return 0; - } - } else { - return 1; - } - } -} - - -/* - * compare two cols, lexical ordering - */ -int -sm_col_compare(p1, p2) -sm_col *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_row; - q2 = p2->first_row; - while(q1 != 0 && q2 != 0) { - if (q1->row_num != q2->row_num) { - return q1->row_num - q2->row_num; - } - q1 = q1->next_row; - q2 = q2->next_row; - } - - if (q1 != 0) { - return 1; - } else if (q2 != 0) { - return -1; - } else { - return 0; - } -} - - -/* - * return the intersection - */ -sm_col * -sm_col_and(p1, p2) -sm_col *p1, *p2; -{ - register sm_element *q1, *q2; - register sm_col *result; - - result = sm_col_alloc(); - q1 = p1->first_row; - q2 = p2->first_row; - if (q1 == 0 || q2 == 0) return result; - for(;;) { - if (q1->row_num < q2->row_num) { - if ((q1 = q1->next_row) == 0) { - return result; - } - } else if (q1->row_num > q2->row_num) { - if ((q2 = q2->next_row) == 0) { - return result; - } - } else { - (void) sm_col_insert(result, q1->row_num); - if ((q1 = q1->next_row) == 0) { - return result; - } - if ((q2 = q2->next_row) == 0) { - return result; - } - } - } -} - -int -sm_col_hash(pcol, modulus) -sm_col *pcol; -int modulus; -{ - register int sum; - register sm_element *p; - - sum = 0; - for(p = pcol->first_row; p != 0; p = p->next_row) { - sum = (sum*17 + p->row_num) % modulus; - } - return sum; -} - -/* - * remove an element from a col vector (given a pointer to the element) - */ -void -sm_col_remove_element(pcol, p) -register sm_col *pcol; -register sm_element *p; -{ - dll_unlink(p, pcol->first_row, pcol->last_row, - next_row, prev_row, pcol->length); - sm_element_free(p); -} - - -void -sm_col_print(fp, pcol) -FILE *fp; -sm_col *pcol; -{ - sm_element *p; - - for(p = pcol->first_row; p != 0; p = p->next_row) { - (void) fprintf(fp, " %d", p->row_num); - } -} diff --git a/src/misc/espresso/compl.c b/src/misc/espresso/compl.c deleted file mode 100644 index 8f1c6606..00000000 --- a/src/misc/espresso/compl.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - * module: compl.c - * purpose: compute the complement of a multiple-valued function - * - * The "unate recursive paradigm" is used. After a set of special - * cases are examined, the function is split on the "most active - * variable". These two halves are complemented recursively, and then - * the results are merged. - * - * Changes (from Version 2.1 to Version 2.2) - * 1. Minor bug in compl_lifting -- cubes in the left half were - * not marked as active, so that when merging a leaf from the left - * hand side, the active flags were essentially random. This led - * to minor impredictability problem, but never affected the - * accuracy of the results. - */ - -#include "espresso.h" - -#define USE_COMPL_LIFT 0 -#define USE_COMPL_LIFT_ONSET 1 -#define USE_COMPL_LIFT_ONSET_COMPLEX 2 -#define NO_LIFTING 3 - -static bool compl_special_cases(); -static pcover compl_merge(); -static void compl_d1merge(); -static pcover compl_cube(); -static void compl_lift(); -static void compl_lift_onset(); -static void compl_lift_onset_complex(); -static bool simp_comp_special_cases(); -static bool simplify_special_cases(); - - -/* complement -- compute the complement of T */ -pcover complement(T) -pcube *T; /* T will be disposed of */ -{ - register pcube cl, cr; - register int best; - pcover Tbar, Tl, Tr; - int lifting; - static int compl_level = 0; - - if (debug & COMPL) - debug_print(T, "COMPLEMENT", compl_level++); - - if (compl_special_cases(T, &Tbar) == MAYBE) { - - /* Allocate space for the partition cubes */ - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, COMPL); - - /* Complement the left and right halves */ - Tl = complement(scofactor(T, cl, best)); - Tr = complement(scofactor(T, cr, best)); - - if (Tr->count*Tl->count > (Tr->count+Tl->count)*CUBELISTSIZE(T)) { - lifting = USE_COMPL_LIFT_ONSET; - } else { - lifting = USE_COMPL_LIFT; - } - Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting); - - free_cube(cl); - free_cube(cr); - free_cubelist(T); - } - - if (debug & COMPL) - debug1_print(Tbar, "exit COMPLEMENT", --compl_level); - return Tbar; -} - -static bool compl_special_cases(T, Tbar) -pcube *T; /* will be disposed if answer is determined */ -pcover *Tbar; /* returned only if answer determined */ -{ - register pcube *T1, p, ceil, cof=T[0]; - pcover A, ceil_compl; - - /* Check for no cubes in the cover */ - if (T[2] == NULL) { - *Tbar = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - } - - /* Check for only a single cube in the cover */ - if (T[3] == NULL) { - *Tbar = compl_cube(set_or(cof, cof, T[2])); - free_cubelist(T); - return TRUE; - } - - /* Check for a row of all 1's (implies complement is null) */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, cof)) { - *Tbar = new_cover(0); - free_cubelist(T); - return TRUE; - } - } - - /* Check for a column of all 0's which can be factored out */ - ceil = set_save(cof); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - ceil_compl = compl_cube(ceil); - (void) set_or(cof, cof, set_diff(ceil, cube.fullset, ceil)); - set_free(ceil); - *Tbar = sf_append(complement(T), ceil_compl); - return TRUE; - } - set_free(ceil); - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If single active variable not factored out above, then tautology ! */ - if (cdata.vars_active == 1) { - *Tbar = new_cover(0); - free_cubelist(T); - return TRUE; - - /* Check for unate cover */ - } else if (cdata.vars_unate == cdata.vars_active) { - A = map_cover_to_unate(T); - free_cubelist(T); - A = unate_compl(A); - *Tbar = map_unate_to_cover(A); - sf_free(A); - return TRUE; - - /* Not much we can do about it */ - } else { - return MAYBE; - } -} - -/* - * compl_merge -- merge the two cofactors around the splitting - * variable - * - * The merge operation involves intersecting each cube of the left - * cofactor with cl, and intersecting each cube of the right cofactor - * with cr. The union of these two covers is the merged result. - * - * In order to reduce the number of cubes, a distance-1 merge is - * performed (note that two cubes can only combine distance-1 in the - * splitting variable). Also, a simple expand is performed in the - * splitting variable (simple implies the covering check for the - * expansion is not full containment, but single-cube containment). - */ - -static pcover compl_merge(T1, L, R, cl, cr, var, lifting) -pcube *T1; /* Original ON-set */ -pcover L, R; /* Complement from each recursion branch */ -register pcube cl, cr; /* cubes used for cofactoring */ -int var; /* splitting variable */ -int lifting; /* whether to perform lifting or not */ -{ - register pcube p, last, pt; - pcover T, Tbar; - pcube *L1, *R1; - - if (debug & COMPL) { - (void) printf("compl_merge: left %d, right %d\n", L->count, R->count); - (void) printf("%s (cl)\n%s (cr)\nLeft is\n", pc1(cl), pc2(cr)); - cprint(L); - (void) printf("Right is\n"); - cprint(R); - } - - /* Intersect each cube with the cofactored cube */ - foreach_set(L, last, p) { - INLINEset_and(p, p, cl); - SET(p, ACTIVE); - } - foreach_set(R, last, p) { - INLINEset_and(p, p, cr); - SET(p, ACTIVE); - } - - /* Sort the arrays for a distance-1 merge */ - (void) set_copy(cube.temp[0], cube.var_mask[var]); - qsort((char *) (L1 = sf_list(L)), L->count, sizeof(pset), (int (*)()) d1_order); - qsort((char *) (R1 = sf_list(R)), R->count, sizeof(pset), (int (*)()) d1_order); - - /* Perform distance-1 merge */ - compl_d1merge(L1, R1); - - /* Perform lifting */ - switch(lifting) { - case USE_COMPL_LIFT_ONSET: - T = cubeunlist(T1); - compl_lift_onset(L1, T, cr, var); - compl_lift_onset(R1, T, cl, var); - free_cover(T); - break; - case USE_COMPL_LIFT_ONSET_COMPLEX: - T = cubeunlist(T1); - compl_lift_onset_complex(L1, T, var); - compl_lift_onset_complex(R1, T, var); - free_cover(T); - break; - case USE_COMPL_LIFT: - compl_lift(L1, R1, cr, var); - compl_lift(R1, L1, cl, var); - break; - case NO_LIFTING: - break; - default: - ; - } - FREE(L1); - FREE(R1); - - /* Re-create the merged cover */ - Tbar = new_cover(L->count + R->count); - pt = Tbar->data; - foreach_set(L, last, p) { - INLINEset_copy(pt, p); - Tbar->count++; - pt += Tbar->wsize; - } - foreach_active_set(R, last, p) { - INLINEset_copy(pt, p); - Tbar->count++; - pt += Tbar->wsize; - } - - if (debug & COMPL) { - (void) printf("Result %d\n", Tbar->count); - if (verbose_debug) - cprint(Tbar); - } - - free_cover(L); - free_cover(R); - return Tbar; -} - -/* - * compl_lift_simple -- expand in the splitting variable using single - * cube containment against the other recursion branch to check - * validity of the expansion, and expanding all (or none) of the - * splitting variable. - */ -static void compl_lift(A1, B1, bcube, var) -pcube *A1, *B1, bcube; -int var; -{ - register pcube a, b, *B2, lift=cube.temp[4], liftor=cube.temp[5]; - pcube mask = cube.var_mask[var]; - - (void) set_and(liftor, bcube, mask); - - /* for each cube in the first array ... */ - for(; (a = *A1++) != NULL; ) { - if (TESTP(a, ACTIVE)) { - - /* create a lift of this cube in the merging coord */ - (void) set_merge(lift, bcube, a, mask); - - /* for each cube in the second array */ - for(B2 = B1; (b = *B2++) != NULL; ) { - INLINEsetp_implies(lift, b, /* when_false => */ continue); - /* when_true => fall through to next statement */ - - /* cube of A1 was contained by some cube of B1, so raise */ - INLINEset_or(a, a, liftor); - break; - } - } - } -} - - - -/* - * compl_lift_onset -- expand in the splitting variable using a - * distance-1 check against the original on-set; expand all (or - * none) of the splitting variable. Each cube of A1 is expanded - * against the original on-set T. - */ -static void compl_lift_onset(A1, T, bcube, var) -pcube *A1; -pcover T; -pcube bcube; -int var; -{ - register pcube a, last, p, lift=cube.temp[4], mask=cube.var_mask[var]; - - /* for each active cube from one branch of the complement */ - for(; (a = *A1++) != NULL; ) { - if (TESTP(a, ACTIVE)) { - - /* create a lift of this cube in the merging coord */ - INLINEset_and(lift, bcube, mask); /* isolate parts to raise */ - INLINEset_or(lift, a, lift); /* raise these parts in a */ - - /* for each cube in the ON-set, check for intersection */ - foreach_set(T, last, p) { - if (cdist0(p, lift)) { - goto nolift; - } - } - INLINEset_copy(a, lift); /* save the raising */ - SET(a, ACTIVE); -nolift : ; - } - } -} - -/* - * compl_lift_complex -- expand in the splitting variable, but expand all - * parts which can possibly expand. - * T is the original ON-set - * A1 is either the left or right cofactor - */ -static void compl_lift_onset_complex(A1, T, var) -pcube *A1; /* array of pointers to new result */ -pcover T; /* original ON-set */ -int var; /* which variable we split on */ -{ - register int dist; - register pcube last, p, a, xlower; - - /* for each cube in the complement */ - xlower = new_cube(); - for(; (a = *A1++) != NULL; ) { - - if (TESTP(a, ACTIVE)) { - - /* Find which parts of the splitting variable are forced low */ - INLINEset_clear(xlower, cube.size); - foreach_set(T, last, p) { - if ((dist = cdist01(p, a)) < 2) { - if (dist == 0) { - fatal("compl: ON-set and OFF-set are not orthogonal"); - } else { - (void) force_lower(xlower, p, a); - } - } - } - - (void) set_diff(xlower, cube.var_mask[var], xlower); - (void) set_or(a, a, xlower); - free_cube(xlower); - } - } -} - - - -/* - * compl_d1merge -- distance-1 merge in the splitting variable - */ -static void compl_d1merge(L1, R1) -register pcube *L1, *R1; -{ - register pcube pl, pr; - - /* Find equal cubes between the two cofactors */ - for(pl = *L1, pr = *R1; (pl != NULL) && (pr != NULL); ) - switch (d1_order(L1, R1)) { - case 1: - pr = *(++R1); break; /* advance right pointer */ - case -1: - pl = *(++L1); break; /* advance left pointer */ - case 0: - RESET(pr, ACTIVE); - INLINEset_or(pl, pl, pr); - pr = *(++R1); - default: - ; - } -} - - - -/* compl_cube -- return the complement of a single cube (De Morgan's law) */ -static pcover compl_cube(p) -register pcube p; -{ - register pcube diff=cube.temp[7], pdest, mask, full=cube.fullset; - int var; - pcover R; - - /* Allocate worst-case size cover (to avoid checking overflow) */ - R = new_cover(cube.num_vars); - - /* Compute bit-wise complement of the cube */ - INLINEset_diff(diff, full, p); - - for(var = 0; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; - /* If the bit-wise complement is not empty in var ... */ - if (! setp_disjoint(diff, mask)) { - pdest = GETSET(R, R->count++); - INLINEset_merge(pdest, diff, full, mask); - } - } - return R; -} - -/* simp_comp -- quick simplification of T */ -void simp_comp(T, Tnew, Tbar) -pcube *T; /* T will be disposed of */ -pcover *Tnew; -pcover *Tbar; -{ - register pcube cl, cr; - register int best; - pcover Tl, Tr, Tlbar, Trbar; - int lifting; - static int simplify_level = 0; - - if (debug & COMPL) - debug_print(T, "SIMPCOMP", simplify_level++); - - if (simp_comp_special_cases(T, Tnew, Tbar) == MAYBE) { - - /* Allocate space for the partition cubes */ - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, COMPL); - - /* Complement the left and right halves */ - simp_comp(scofactor(T, cl, best), &Tl, &Tlbar); - simp_comp(scofactor(T, cr, best), &Tr, &Trbar); - - lifting = USE_COMPL_LIFT; - *Tnew = compl_merge(T, Tl, Tr, cl, cr, best, lifting); - - lifting = USE_COMPL_LIFT; - *Tbar = compl_merge(T, Tlbar, Trbar, cl, cr, best, lifting); - - /* All of this work for nothing ? Let's hope not ... */ - if ((*Tnew)->count > CUBELISTSIZE(T)) { - sf_free(*Tnew); - *Tnew = cubeunlist(T); - } - - free_cube(cl); - free_cube(cr); - free_cubelist(T); - } - - if (debug & COMPL) { - debug1_print(*Tnew, "exit SIMPCOMP (new)", simplify_level); - debug1_print(*Tbar, "exit SIMPCOMP (compl)", simplify_level); - simplify_level--; - } -} - -static bool simp_comp_special_cases(T, Tnew, Tbar) -pcube *T; /* will be disposed if answer is determined */ -pcover *Tnew; /* returned only if answer determined */ -pcover *Tbar; /* returned only if answer determined */ -{ - register pcube *T1, p, ceil, cof=T[0]; - pcube last; - pcover A; - - /* Check for no cubes in the cover (function is empty) */ - if (T[2] == NULL) { - *Tnew = new_cover(1); - *Tbar = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - } - - /* Check for only a single cube in the cover */ - if (T[3] == NULL) { - (void) set_or(cof, cof, T[2]); - *Tnew = sf_addset(new_cover(1), cof); - *Tbar = compl_cube(cof); - free_cubelist(T); - return TRUE; - } - - /* Check for a row of all 1's (function is a tautology) */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, cof)) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - *Tbar = new_cover(1); - free_cubelist(T); - return TRUE; - } - } - - /* Check for a column of all 0's which can be factored out */ - ceil = set_save(cof); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - p = new_cube(); - (void) set_diff(p, cube.fullset, ceil); - (void) set_or(cof, cof, p); - set_free(p); - simp_comp(T, Tnew, Tbar); - - /* Adjust the ON-set */ - A = *Tnew; - foreach_set(A, last, p) { - INLINEset_and(p, p, ceil); - } - - /* Compute the new complement */ - *Tbar = sf_append(*Tbar, compl_cube(ceil)); - set_free(ceil); - return TRUE; - } - set_free(ceil); - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If single active variable not factored out above, then tautology ! */ - if (cdata.vars_active == 1) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - *Tbar = new_cover(1); - free_cubelist(T); - return TRUE; - - /* Check for unate cover */ - } else if (cdata.vars_unate == cdata.vars_active) { - /* Make the cover minimum by single-cube containment */ - A = cubeunlist(T); - *Tnew = sf_contain(A); - - /* Now form a minimum representation of the complement */ - A = map_cover_to_unate(T); - A = unate_compl(A); - *Tbar = map_unate_to_cover(A); - sf_free(A); - free_cubelist(T); - return TRUE; - - /* Not much we can do about it */ - } else { - return MAYBE; - } -} - -/* simplify -- quick simplification of T */ -pcover simplify(T) -pcube *T; /* T will be disposed of */ -{ - register pcube cl, cr; - register int best; - pcover Tbar, Tl, Tr; - int lifting; - static int simplify_level = 0; - - if (debug & COMPL) { - debug_print(T, "SIMPLIFY", simplify_level++); - } - - if (simplify_special_cases(T, &Tbar) == MAYBE) { - - /* Allocate space for the partition cubes */ - cl = new_cube(); - cr = new_cube(); - - best = binate_split_select(T, cl, cr, COMPL); - - /* Complement the left and right halves */ - Tl = simplify(scofactor(T, cl, best)); - Tr = simplify(scofactor(T, cr, best)); - - lifting = USE_COMPL_LIFT; - Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting); - - /* All of this work for nothing ? Let's hope not ... */ - if (Tbar->count > CUBELISTSIZE(T)) { - sf_free(Tbar); - Tbar = cubeunlist(T); - } - - free_cube(cl); - free_cube(cr); - free_cubelist(T); - } - - if (debug & COMPL) { - debug1_print(Tbar, "exit SIMPLIFY", --simplify_level); - } - return Tbar; -} - -static bool simplify_special_cases(T, Tnew) -pcube *T; /* will be disposed if answer is determined */ -pcover *Tnew; /* returned only if answer determined */ -{ - register pcube *T1, p, ceil, cof=T[0]; - pcube last; - pcover A; - - /* Check for no cubes in the cover */ - if (T[2] == NULL) { - *Tnew = new_cover(0); - free_cubelist(T); - return TRUE; - } - - /* Check for only a single cube in the cover */ - if (T[3] == NULL) { - *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2])); - free_cubelist(T); - return TRUE; - } - - /* Check for a row of all 1's (implies function is a tautology) */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, cof)) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - } - } - - /* Check for a column of all 0's which can be factored out */ - ceil = set_save(cof); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - p = new_cube(); - (void) set_diff(p, cube.fullset, ceil); - (void) set_or(cof, cof, p); - free_cube(p); - - A = simplify(T); - foreach_set(A, last, p) { - INLINEset_and(p, p, ceil); - } - *Tnew = A; - set_free(ceil); - return TRUE; - } - set_free(ceil); - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If single active variable not factored out above, then tautology ! */ - if (cdata.vars_active == 1) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - - /* Check for unate cover */ - } else if (cdata.vars_unate == cdata.vars_active) { - A = cubeunlist(T); - *Tnew = sf_contain(A); - free_cubelist(T); - return TRUE; - - /* Not much we can do about it */ - } else { - return MAYBE; - } -} diff --git a/src/misc/espresso/contain.c b/src/misc/espresso/contain.c deleted file mode 100644 index 180dceb6..00000000 --- a/src/misc/espresso/contain.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - contain.c -- set containment routines - - These are complex routines for performing containment over a - family of sets, but they have the advantage of being much faster - than a straightforward n*n routine. - - First the cubes are sorted by size, and as a secondary key they are - sorted so that if two cubes are equal they end up adjacent. We can - than quickly remove equal cubes from further consideration by - comparing each cube to its neighbor. Finally, because the cubes - are sorted by size, we need only check cubes which are larger (or - smaller) than a given cube for containment. -*/ - -#include "espresso.h" - - -/* - sf_contain -- perform containment on a set family (delete sets which - are contained by some larger set in the family). No assumptions are - made about A, and the result will be returned in decreasing order of - set size. -*/ -pset_family sf_contain(A) -INOUT pset_family A; /* disposes of A */ -{ - int cnt; - pset *A1; - pset_family R; - - A1 = sf_sort(A, descend); /* sort into descending order */ - cnt = rm_equal(A1, descend); /* remove duplicates */ - cnt = rm_contain(A1); /* remove contained sets */ - R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ - sf_free(A); - return R; -} - - -/* - sf_rev_contain -- perform containment on a set family (delete sets which - contain some smaller set in the family). No assumptions are made about - A, and the result will be returned in increasing order of set size -*/ -pset_family sf_rev_contain(A) -INOUT pset_family A; /* disposes of A */ -{ - int cnt; - pset *A1; - pset_family R; - - A1 = sf_sort(A, ascend); /* sort into ascending order */ - cnt = rm_equal(A1, ascend); /* remove duplicates */ - cnt = rm_rev_contain(A1); /* remove containing sets */ - R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ - sf_free(A); - return R; -} - - -/* - sf_ind_contain -- perform containment on a set family (delete sets which - are contained by some larger set in the family). No assumptions are - made about A, and the result will be returned in decreasing order of - set size. Also maintains a set of row_indices to track which rows - disappear and how the rows end up permuted. -*/ -pset_family sf_ind_contain(A, row_indices) -INOUT pset_family A; /* disposes of A */ -INOUT int *row_indices; /* updated with the new values */ -{ - int cnt; - pset *A1; - pset_family R; - - A1 = sf_sort(A, descend); /* sort into descending order */ - cnt = rm_equal(A1, descend); /* remove duplicates */ - cnt = rm_contain(A1); /* remove contained sets */ - R = sf_ind_unlist(A1, cnt, A->sf_size, row_indices, A->data); - sf_free(A); - return R; -} - - -/* sf_dupl -- delete duplicate sets in a set family */ -pset_family sf_dupl(A) -INOUT pset_family A; /* disposes of A */ -{ - register int cnt; - register pset *A1; - pset_family R; - - A1 = sf_sort(A, descend); /* sort the set family */ - cnt = rm_equal(A1, descend); /* remove duplicates */ - R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */ - sf_free(A); - return R; -} - - -/* - sf_union -- form the contained union of two set families (delete - sets which are contained by some larger set in the family). A and - B are assumed already sorted in decreasing order of set size (and - the SIZE field is assumed to contain the set size), and the result - will be returned sorted likewise. -*/ -pset_family sf_union(A, B) -INOUT pset_family A, B; /* disposes of A and B */ -{ - int cnt; - pset_family R; - pset *A1 = sf_list(A), *B1 = sf_list(B), *E1; - - E1 = ALLOC(pset, MAX(A->count, B->count) + 1); - cnt = rm2_equal(A1, B1, E1, descend); - cnt += rm2_contain(A1, B1) + rm2_contain(B1, A1); - R = sf_merge(A1, B1, E1, cnt, A->sf_size); - sf_free(A); sf_free(B); - return R; -} - - -/* - dist_merge -- consider all sets to be "or"-ed with "mask" and then - delete duplicates from the set family. -*/ -pset_family dist_merge(A, mask) -INOUT pset_family A; /* disposes of A */ -IN pset mask; /* defines variables to mask out */ -{ - pset *A1; - int cnt; - pset_family R; - - (void) set_copy(cube.temp[0], mask); - A1 = sf_sort(A, d1_order); - cnt = d1_rm_equal(A1, d1_order); - R = sf_unlist(A1, cnt, A->sf_size); - sf_free(A); - return R; -} - - -/* - d1merge -- perform an efficient distance-1 merge of cubes of A -*/ -pset_family d1merge(A, var) -INOUT pset_family A; /* disposes of A */ -IN int var; -{ - return dist_merge(A, cube.var_mask[var]); -} - - - -/* d1_rm_equal -- distance-1 merge (merge cubes which are equal under a mask) */ -int d1_rm_equal(A1, compare) -register pset *A1; /* array of set pointers */ -int (*compare)(); /* comparison function */ -{ - register int i, j, dest; - - dest = 0; - if (A1[0] != (pcube) NULL) { - for(i = 0, j = 1; A1[j] != (pcube) NULL; j++) - if ( (*compare)(&A1[i], &A1[j]) == 0) { - /* if sets are equal (under the mask) merge them */ - (void) set_or(A1[i], A1[i], A1[j]); - } else { - /* sets are unequal, so save the set i */ - A1[dest++] = A1[i]; - i = j; - } - A1[dest++] = A1[i]; - } - A1[dest] = (pcube) NULL; - return dest; -} - - -/* rm_equal -- scan a sorted array of set pointers for duplicate sets */ -int rm_equal(A1, compare) -INOUT pset *A1; /* updated in place */ -IN int (*compare)(); -{ - register pset *p, *pdest = A1; - - if (*A1 != NULL) { /* If more than one set */ - for(p = A1+1; *p != NULL; p++) - if ((*compare)(p, p-1) != 0) - *pdest++ = *(p-1); - *pdest++ = *(p-1); - *pdest = NULL; - } - return pdest - A1; -} - - -/* rm_contain -- perform containment over a sorted array of set pointers */ -int rm_contain(A1) -INOUT pset *A1; /* updated in place */ -{ - register pset *pa, *pb, *pcheck, a, b; - pset *pdest = A1; - int last_size = -1; - - /* Loop for all cubes of A1 */ - for(pa = A1; (a = *pa++) != NULL; ) { - /* Update the check pointer if the size has changed */ - if (SIZE(a) != last_size) - last_size = SIZE(a), pcheck = pdest; - for(pb = A1; pb != pcheck; ) { - b = *pb++; - INLINEsetp_implies(a, b, /* when_false => */ continue); - goto lnext1; - } - /* set a was not contained by some larger set, so save it */ - *pdest++ = a; - lnext1: ; - } - - *pdest = NULL; - return pdest - A1; -} - - -/* rm_rev_contain -- perform rcontainment over a sorted array of set pointers */ -int rm_rev_contain(A1) -INOUT pset *A1; /* updated in place */ -{ - register pset *pa, *pb, *pcheck, a, b; - pset *pdest = A1; - int last_size = -1; - - /* Loop for all cubes of A1 */ - for(pa = A1; (a = *pa++) != NULL; ) { - /* Update the check pointer if the size has changed */ - if (SIZE(a) != last_size) - last_size = SIZE(a), pcheck = pdest; - for(pb = A1; pb != pcheck; ) { - b = *pb++; - INLINEsetp_implies(b, a, /* when_false => */ continue); - goto lnext1; - } - /* the set a did not contain some smaller set, so save it */ - *pdest++ = a; - lnext1: ; - } - - *pdest = NULL; - return pdest - A1; -} - - -/* rm2_equal -- check two sorted arrays of set pointers for equal cubes */ -int rm2_equal(A1, B1, E1, compare) -INOUT register pset *A1, *B1; /* updated in place */ -OUT pset *E1; -IN int (*compare)(); -{ - register pset *pda = A1, *pdb = B1, *pde = E1; - - /* Walk through the arrays advancing pointer to larger cube */ - for(; *A1 != NULL && *B1 != NULL; ) - switch((*compare)(A1, B1)) { - case -1: /* "a" comes before "b" */ - *pda++ = *A1++; break; - case 0: /* equal cubes */ - *pde++ = *A1++; B1++; break; - case 1: /* "a" is to follow "b" */ - *pdb++ = *B1++; break; - } - - /* Finish moving down the pointers of A and B */ - while (*A1 != NULL) - *pda++ = *A1++; - while (*B1 != NULL) - *pdb++ = *B1++; - *pda = *pdb = *pde = NULL; - - return pde - E1; -} - - -/* rm2_contain -- perform containment between two arrays of set pointers */ -int rm2_contain(A1, B1) -INOUT pset *A1; /* updated in place */ -IN pset *B1; /* unchanged */ -{ - register pset *pa, *pb, a, b, *pdest = A1; - - /* for each set in the first array ... */ - for(pa = A1; (a = *pa++) != NULL; ) { - /* for each set in the second array which is larger ... */ - for(pb = B1; (b = *pb++) != NULL && SIZE(b) > SIZE(a); ) { - INLINEsetp_implies(a, b, /* when_false => */ continue); - /* set was contained in some set of B, so don't save pointer */ - goto lnext1; - } - /* set wasn't contained in any set of B, so save the pointer */ - *pdest++ = a; - lnext1: ; - } - - *pdest = NULL; /* sentinel */ - return pdest - A1; /* # elements in A1 */ -} - - - -/* sf_sort -- sort the sets of A */ -pset *sf_sort(A, compare) -IN pset_family A; -IN int (*compare)(); -{ - register pset p, last, *pdest, *A1; - - /* Create a single array pointing to each cube of A */ - pdest = A1 = ALLOC(pset, A->count + 1); - foreach_set(A, last, p) { - PUTSIZE(p, set_ord(p)); /* compute the set size */ - *pdest++ = p; /* save the pointer */ - } - *pdest = NULL; /* Sentinel -- never seen by sort */ - - /* Sort cubes by size */ - qsort((char *) A1, A->count, sizeof(pset), compare); - return A1; -} - - -/* sf_list -- make a list of pointers to the sets in a set family */ -pset *sf_list(A) -IN register pset_family A; -{ - register pset p, last, *pdest, *A1; - - /* Create a single array pointing to each cube of A */ - pdest = A1 = ALLOC(pset, A->count + 1); - foreach_set(A, last, p) - *pdest++ = p; /* save the pointer */ - *pdest = NULL; /* Sentinel */ - return A1; -} - - -/* sf_unlist -- make a set family out of a list of pointers to sets */ -pset_family sf_unlist(A1, totcnt, size) -IN pset *A1; -IN int totcnt, size; -{ - register pset pr, p, *pa; - pset_family R = sf_new(totcnt, size); - - R->count = totcnt; - for(pr = R->data, pa = A1; (p = *pa++) != NULL; pr += R->wsize) - INLINEset_copy(pr, p); - FREE(A1); - return R; -} - - -/* sf_ind_unlist -- make a set family out of a list of pointers to sets */ -pset_family sf_ind_unlist(A1, totcnt, size, row_indices, pfirst) -IN pset *A1; -IN int totcnt, size; -INOUT int *row_indices; -IN register pset pfirst; -{ - register pset pr, p, *pa; - register int i, *new_row_indices; - pset_family R = sf_new(totcnt, size); - - R->count = totcnt; - new_row_indices = ALLOC(int, totcnt); - for(pr = R->data, pa = A1, i=0; (p = *pa++) != NULL; pr += R->wsize, i++) { - INLINEset_copy(pr, p); - new_row_indices[i] = row_indices[(p - pfirst)/R->wsize]; - } - for(i = 0; i < totcnt; i++) - row_indices[i] = new_row_indices[i]; - FREE(new_row_indices); - FREE(A1); - return R; -} - - -/* sf_merge -- merge three sorted lists of set pointers */ -pset_family sf_merge(A1, B1, E1, totcnt, size) -INOUT pset *A1, *B1, *E1; /* will be disposed of */ -IN int totcnt, size; -{ - register pset pr, ps, *pmin, *pmid, *pmax; - pset_family R; - pset *temp[3], *swap; - int i, j, n; - - /* Allocate the result set_family */ - R = sf_new(totcnt, size); - R->count = totcnt; - pr = R->data; - - /* Quick bubble sort to order the top member of the three arrays */ - n = 3; temp[0] = A1; temp[1] = B1; temp[2] = E1; - for(i = 0; i < n-1; i++) - for(j = i+1; j < n; j++) - if (desc1(*temp[i], *temp[j]) > 0) { - swap = temp[j]; - temp[j] = temp[i]; - temp[i] = swap; - } - pmin = temp[0]; pmid = temp[1]; pmax = temp[2]; - - /* Save the minimum element, then update pmin, pmid, pmax */ - while (*pmin != (pset) NULL) { - ps = *pmin++; - INLINEset_copy(pr, ps); - pr += R->wsize; - if (desc1(*pmin, *pmax) > 0) { - swap = pmax; pmax = pmin; pmin = pmid; pmid = swap; - } else if (desc1(*pmin, *pmid) > 0) { - swap = pmin; pmin = pmid; pmid = swap; - } - } - - FREE(A1); - FREE(B1); - FREE(E1); - return R; -} diff --git a/src/misc/espresso/cubehack.c b/src/misc/espresso/cubehack.c deleted file mode 100644 index 8e1724fc..00000000 --- a/src/misc/espresso/cubehack.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Revision Control Information - * - * $Source: /vol/opua/opua2/sis/sis-1.1/common/src/sis/node/RCS/cubehack.c,v $ - * $Author: sis $ - * $Revision: 1.2 $ - * $Date: 1992/05/06 18:57:41 $ - * - */ -/* -#include "sis.h" -#include "node_int.h" - -#ifdef lint -struct cube_struct cube; -bool summary; -bool trace; -bool remove_essential; -bool force_irredundant; -bool unwrap_onset; -bool single_expand; -bool pos; -bool recompute_onset; -bool use_super_gasp; -bool use_random_order; -#endif -*/ -#include "espresso.h" - - -void -cautious_define_cube_size(n) -int n; -{ - if (cube.fullset != 0 && cube.num_binary_vars == n) - return; - if (cube.fullset != 0) { - setdown_cube(); - FREE(cube.part_size); - } - cube.num_binary_vars = cube.num_vars = n; - cube.part_size = ALLOC(int, n); - cube_setup(); -} - - -void -define_cube_size(n) -int n; -{ - register int q, i; - static int called_before = 0; - - /* check if the cube is already just the right size */ - if (cube.fullset != 0 && cube.num_binary_vars == n && cube.num_vars == n) - return; - - /* We can't handle more than 100 inputs */ - if (n > 100) { - cautious_define_cube_size(n); - called_before = 0; - return; - } - - if (cube.fullset == 0 || ! called_before) { - cautious_define_cube_size(100); - called_before = 1; - } - - cube.num_vars = n; - cube.num_binary_vars = n; - cube.num_mv_vars = 0; - cube.output = -1; - cube.size = n * 2; - - /* first_part, last_part, first_word, last_word, part_size OKAY */ - /* cube.sparse is OKAY */ - - /* need to completely re-make cube.fullset and cube.binary_mask */ - (void) set_fill(cube.fullset, n*2); - (void) set_fill(cube.binary_mask, n*2); - - /* need to resize each set in cube.var_mask and cube.temp */ - q = cube.fullset[0]; - for(i = 0; i < cube.num_vars; i++) - cube.var_mask[i][0] = q; - for(i = 0; i < CUBE_TEMP; i++) - cube.temp[i][0] = q; - - /* need to resize cube.emptyset and cube.mv_mask */ - cube.emptyset[0] = q; - cube.mv_mask[0] = q; - - /* need to reset the inword and inmask */ - if (cube.num_binary_vars != 0) { - cube.inword = cube.last_word[cube.num_binary_vars - 1]; - cube.inmask = cube.binary_mask[cube.inword] & DISJOINT; - } else { - cube.inword = -1; - cube.inmask = 0; - } - - /* cdata (entire structure) is OKAY */ -} - - -void -undefine_cube_size() -{ - if (cube.num_binary_vars > 100) { - if (cube.fullset != 0) { - setdown_cube(); - FREE(cube.part_size); - } - } else { - cube.num_vars = cube.num_binary_vars = 100; - if (cube.fullset != 0) { - setdown_cube(); - FREE(cube.part_size); - } - } -} - - -void -set_espresso_flags() -{ - summary = FALSE; - trace = FALSE; - remove_essential = TRUE; - force_irredundant = TRUE; - unwrap_onset = TRUE; - single_expand = FALSE; - pos = FALSE; - recompute_onset = FALSE; - use_super_gasp = FALSE; - use_random_order = FALSE; -} diff --git a/src/misc/espresso/cubestr.c b/src/misc/espresso/cubestr.c deleted file mode 100644 index 77389e73..00000000 --- a/src/misc/espresso/cubestr.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - Module: cubestr.c -- routines for managing the global cube structure -*/ - -#include "espresso.h" - -/* - cube_setup -- assume that the fields "num_vars", "num_binary_vars", and - part_size[num_binary_vars .. num_vars-1] are setup, and initialize the - rest of cube and cdata. - - If a part_size is < 0, then the field size is abs(part_size) and the - field read from the input is symbolic. -*/ -void cube_setup() -{ - register int i, var; - register pcube p; - - if (cube.num_binary_vars < 0 || cube.num_vars < cube.num_binary_vars) - fatal("cube size is silly, error in .i/.o or .mv"); - - cube.num_mv_vars = cube.num_vars - cube.num_binary_vars; - cube.output = cube.num_mv_vars > 0 ? cube.num_vars - 1 : -1; - - cube.size = 0; - cube.first_part = ALLOC(int, cube.num_vars); - cube.last_part = ALLOC(int, cube.num_vars); - cube.first_word = ALLOC(int, cube.num_vars); - cube.last_word = ALLOC(int, cube.num_vars); - for(var = 0; var < cube.num_vars; var++) { - if (var < cube.num_binary_vars) - cube.part_size[var] = 2; - cube.first_part[var] = cube.size; - cube.first_word[var] = WHICH_WORD(cube.size); - cube.size += ABS(cube.part_size[var]); - cube.last_part[var] = cube.size - 1; - cube.last_word[var] = WHICH_WORD(cube.size - 1); - } - - cube.var_mask = ALLOC(pset, cube.num_vars); - cube.sparse = ALLOC(int, cube.num_vars); - cube.binary_mask = new_cube(); - cube.mv_mask = new_cube(); - for(var = 0; var < cube.num_vars; var++) { - p = cube.var_mask[var] = new_cube(); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) - set_insert(p, i); - if (var < cube.num_binary_vars) { - INLINEset_or(cube.binary_mask, cube.binary_mask, p); - cube.sparse[var] = 0; - } else { - INLINEset_or(cube.mv_mask, cube.mv_mask, p); - cube.sparse[var] = 1; - } - } - if (cube.num_binary_vars == 0) - cube.inword = -1; - else { - cube.inword = cube.last_word[cube.num_binary_vars - 1]; - cube.inmask = cube.binary_mask[cube.inword] & DISJOINT; - } - - cube.temp = ALLOC(pset, CUBE_TEMP); - for(i = 0; i < CUBE_TEMP; i++) - cube.temp[i] = new_cube(); - cube.fullset = set_fill(new_cube(), cube.size); - cube.emptyset = new_cube(); - - cdata.part_zeros = ALLOC(int, cube.size); - cdata.var_zeros = ALLOC(int, cube.num_vars); - cdata.parts_active = ALLOC(int, cube.num_vars); - cdata.is_unate = ALLOC(int, cube.num_vars); -} - -/* - setdown_cube -- free memory allocated for the cube/cdata structs - (free's all but the part_size array) - - (I wanted to call this cube_setdown, but that violates the 8-character - external routine limit on the IBM !) -*/ -void setdown_cube() -{ - register int i, var; - - FREE(cube.first_part); - FREE(cube.last_part); - FREE(cube.first_word); - FREE(cube.last_word); - FREE(cube.sparse); - - free_cube(cube.binary_mask); - free_cube(cube.mv_mask); - free_cube(cube.fullset); - free_cube(cube.emptyset); - for(var = 0; var < cube.num_vars; var++) - free_cube(cube.var_mask[var]); - FREE(cube.var_mask); - - for(i = 0; i < CUBE_TEMP; i++) - free_cube(cube.temp[i]); - FREE(cube.temp); - - FREE(cdata.part_zeros); - FREE(cdata.var_zeros); - FREE(cdata.parts_active); - FREE(cdata.is_unate); - - cube.first_part = cube.last_part = (int *) NULL; - cube.first_word = cube.last_word = (int *) NULL; - cube.sparse = (int *) NULL; - cube.binary_mask = cube.mv_mask = (pcube) NULL; - cube.fullset = cube.emptyset = (pcube) NULL; - cube.var_mask = cube.temp = (pcube *) NULL; - - cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL; - cdata.is_unate = (bool *) NULL; -} - - -void save_cube_struct() -{ - temp_cube_save = cube; /* structure copy ! */ - temp_cdata_save = cdata; /* "" */ - - cube.first_part = cube.last_part = (int *) NULL; - cube.first_word = cube.last_word = (int *) NULL; - cube.part_size = (int *) NULL; - cube.binary_mask = cube.mv_mask = (pcube) NULL; - cube.fullset = cube.emptyset = (pcube) NULL; - cube.var_mask = cube.temp = (pcube *) NULL; - - cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL; - cdata.is_unate = (bool *) NULL; -} - - -void restore_cube_struct() -{ - cube = temp_cube_save; /* structure copy ! */ - cdata = temp_cdata_save; /* "" */ -} diff --git a/src/misc/espresso/cvrin.c b/src/misc/espresso/cvrin.c deleted file mode 100644 index 7790b38b..00000000 --- a/src/misc/espresso/cvrin.c +++ /dev/null @@ -1,810 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - module: cvrin.c - purpose: cube and cover input routines -*/ - -#include "espresso.h" - -static bool line_length_error; -static int lineno; - -void skip_line(fpin, fpout, echo) -register FILE *fpin, *fpout; -register bool echo; -{ - register int ch; - while ((ch=getc(fpin)) != EOF && ch != '\n') - if (echo) - putc(ch, fpout); - if (echo) - putc('\n', fpout); - lineno++; -} - -char *get_word(fp, word) -register FILE *fp; -register char *word; -{ - register int ch, i = 0; - while ((ch = getc(fp)) != EOF && isspace(ch)) - ; - word[i++] = ch; - while ((ch = getc(fp)) != EOF && ! isspace(ch)) - word[i++] = ch; - word[i++] = '\0'; - return word; -} - -/* - * Yes, I know this routine is a mess - */ -void read_cube(fp, PLA) -register FILE *fp; -pPLA PLA; -{ - register int var, i; - pcube cf = cube.temp[0], cr = cube.temp[1], cd = cube.temp[2]; - bool savef = FALSE, saved = FALSE, saver = FALSE; - char token[256]; /* for kiss read hack */ - int varx, first, last, offset; /* for kiss read hack */ - - set_clear(cf, cube.size); - - /* Loop and read binary variables */ - for(var = 0; var < cube.num_binary_vars; var++) - switch(getc(fp)) { - case EOF: - goto bad_char; - case '\n': - if (! line_length_error) - (void) fprintf(stderr, "product term(s) %s\n", - "span more than one line (warning only)"); - line_length_error = TRUE; - lineno++; - var--; - break; - case ' ': case '|': case '\t': - var--; - break; - case '2': case '-': - set_insert(cf, var*2+1); - case '0': - set_insert(cf, var*2); - break; - case '1': - set_insert(cf, var*2+1); - break; - case '?': - break; - default: - goto bad_char; - } - - - /* Loop for the all but one of the multiple-valued variables */ - for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) - - /* Read a symbolic multiple-valued variable */ - if (cube.part_size[var] < 0) { - (void) fscanf(fp, "%s", token); - if (equal(token, "-") || equal(token, "ANY")) { - if (kiss && var == cube.num_vars - 2) { - /* leave it empty */ - } else { - /* make it full */ - set_or(cf, cf, cube.var_mask[var]); - } - } else if (equal(token, "~")) { - ; - /* leave it empty ... (?) */ - } else { - if (kiss && var == cube.num_vars - 2) - varx = var - 1, offset = ABS(cube.part_size[var-1]); - else - varx = var, offset = 0; - /* Find the symbolic label in the label table */ - first = cube.first_part[varx]; - last = cube.last_part[varx]; - for(i = first; i <= last; i++) - if (PLA->label[i] == (char *) NULL) { - PLA->label[i] = util_strsav(token); /* add new label */ - set_insert(cf, i+offset); - break; - } else if (equal(PLA->label[i], token)) { - set_insert(cf, i+offset); /* use column i */ - break; - } - if (i > last) { - (void) fprintf(stderr, -"declared size of variable %d (counting from variable 0) is too small\n", var); - exit(-1); - } - } - - } else for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) - switch (getc(fp)) { - case EOF: - goto bad_char; - case '\n': - if (! line_length_error) - (void) fprintf(stderr, "product term(s) %s\n", - "span more than one line (warning only)"); - line_length_error = TRUE; - lineno++; - i--; - break; - case ' ': case '|': case '\t': - i--; - break; - case '1': - set_insert(cf, i); - case '0': - break; - default: - goto bad_char; - } - - /* Loop for last multiple-valued variable */ - if (kiss) { - saver = savef = TRUE; - (void) set_xor(cr, cf, cube.var_mask[cube.num_vars - 2]); - } else - set_copy(cr, cf); - set_copy(cd, cf); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) - switch (getc(fp)) { - case EOF: - goto bad_char; - case '\n': - if (! line_length_error) - (void) fprintf(stderr, "product term(s) %s\n", - "span more than one line (warning only)"); - line_length_error = TRUE; - lineno++; - i--; - break; - case ' ': case '|': case '\t': - i--; - break; - case '4': case '1': - if (PLA->pla_type & F_type) - set_insert(cf, i), savef = TRUE; - break; - case '3': case '0': - if (PLA->pla_type & R_type) - set_insert(cr, i), saver = TRUE; - break; - case '2': case '-': - if (PLA->pla_type & D_type) - set_insert(cd, i), saved = TRUE; - case '~': - break; - default: - goto bad_char; - } - if (savef) PLA->F = sf_addset(PLA->F, cf); - if (saved) PLA->D = sf_addset(PLA->D, cd); - if (saver) PLA->R = sf_addset(PLA->R, cr); - return; - -bad_char: - (void) fprintf(stderr, "(warning): input line #%d ignored\n", lineno); - skip_line(fp, stdout, TRUE); - return; -} -void parse_pla(fp, PLA) -IN FILE *fp; -INOUT pPLA PLA; -{ - int i, var, ch, np, last; - char word[256]; - - lineno = 1; - line_length_error = FALSE; - -loop: - switch(ch = getc(fp)) { - case EOF: - return; - - case '\n': - lineno++; - - case ' ': case '\t': case '\f': case '\r': - break; - - case '#': - (void) ungetc(ch, fp); - skip_line(fp, stdout, echo_comments); - break; - - case '.': - /* .i gives the cube input size (binary-functions only) */ - if (equal(get_word(fp, word), "i")) { - if (cube.fullset != NULL) { - (void) fprintf(stderr, "extra .i ignored\n"); - skip_line(fp, stdout, /* echo */ FALSE); - } else { - if (fscanf(fp, "%d", &cube.num_binary_vars) != 1) - fatal("error reading .i"); - cube.num_vars = cube.num_binary_vars + 1; - cube.part_size = ALLOC(int, cube.num_vars); - } - - /* .o gives the cube output size (binary-functions only) */ - } else if (equal(word, "o")) { - if (cube.fullset != NULL) { - (void) fprintf(stderr, "extra .o ignored\n"); - skip_line(fp, stdout, /* echo */ FALSE); - } else { - if (cube.part_size == NULL) - fatal(".o cannot appear before .i"); - if (fscanf(fp, "%d", &(cube.part_size[cube.num_vars-1]))!=1) - fatal("error reading .o"); - cube_setup(); - PLA_labels(PLA); - } - - /* .mv gives the cube size for a multiple-valued function */ - } else if (equal(word, "mv")) { - if (cube.fullset != NULL) { - (void) fprintf(stderr, "extra .mv ignored\n"); - skip_line(fp, stdout, /* echo */ FALSE); - } else { - if (cube.part_size != NULL) - fatal("cannot mix .i and .mv"); - if (fscanf(fp,"%d %d", - &cube.num_vars,&cube.num_binary_vars) != 2) - fatal("error reading .mv"); - if (cube.num_binary_vars < 0) -fatal("num_binary_vars (second field of .mv) cannot be negative"); - if (cube.num_vars < cube.num_binary_vars) - fatal( -"num_vars (1st field of .mv) must exceed num_binary_vars (2nd field of .mv)"); - cube.part_size = ALLOC(int, cube.num_vars); - for(var=cube.num_binary_vars; var < cube.num_vars; var++) - if (fscanf(fp, "%d", &(cube.part_size[var])) != 1) - fatal("error reading .mv"); - cube_setup(); - PLA_labels(PLA); - } - - /* .p gives the number of product terms -- we ignore it */ - } else if (equal(word, "p")) - (void) fscanf(fp, "%d", &np); - /* .e and .end specify the end of the file */ - else if (equal(word, "e") || equal(word,"end")) { - if (cube.fullset == NULL) { - /* fatal("unknown PLA size, need .i/.o or .mv");*/ - } else if (PLA->F == NULL) { - PLA->F = new_cover(10); - PLA->D = new_cover(10); - PLA->R = new_cover(10); - } - return; - } - /* .kiss turns on the kiss-hack option */ - else if (equal(word, "kiss")) - kiss = TRUE; - - /* .type specifies a logical type for the PLA */ - else if (equal(word, "type")) { - (void) get_word(fp, word); - for(i = 0; pla_types[i].key != 0; i++) - if (equal(pla_types[i].key + 1, word)) { - PLA->pla_type = pla_types[i].value; - break; - } - if (pla_types[i].key == 0) - fatal("unknown type in .type command"); - - /* parse the labels */ - } else if (equal(word, "ilb")) { - if (cube.fullset == NULL) - fatal("PLA size must be declared before .ilb or .ob"); - if (PLA->label == NULL) - PLA_labels(PLA); - for(var = 0; var < cube.num_binary_vars; var++) { - (void) get_word(fp, word); - i = cube.first_part[var]; - PLA->label[i+1] = util_strsav(word); - PLA->label[i] = ALLOC(char, strlen(word) + 6); - (void) sprintf(PLA->label[i], "%s.bar", word); - } - } else if (equal(word, "ob")) { - if (cube.fullset == NULL) - fatal("PLA size must be declared before .ilb or .ob"); - if (PLA->label == NULL) - PLA_labels(PLA); - var = cube.num_vars - 1; - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - (void) get_word(fp, word); - PLA->label[i] = util_strsav(word); - } - /* .label assigns labels to multiple-valued variables */ - } else if (equal(word, "label")) { - if (cube.fullset == NULL) - fatal("PLA size must be declared before .label"); - if (PLA->label == NULL) - PLA_labels(PLA); - if (fscanf(fp, "var=%d", &var) != 1) - fatal("Error reading labels"); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - (void) get_word(fp, word); - PLA->label[i] = util_strsav(word); - } - - } else if (equal(word, "symbolic")) { - symbolic_t *newlist, *p1; - if (read_symbolic(fp, PLA, word, &newlist)) { - if (PLA->symbolic == NIL(symbolic_t)) { - PLA->symbolic = newlist; - } else { - for(p1=PLA->symbolic;p1->next!=NIL(symbolic_t); - p1=p1->next){ - } - p1->next = newlist; - } - } else { - fatal("error reading .symbolic"); - } - - } else if (equal(word, "symbolic-output")) { - symbolic_t *newlist, *p1; - if (read_symbolic(fp, PLA, word, &newlist)) { - if (PLA->symbolic_output == NIL(symbolic_t)) { - PLA->symbolic_output = newlist; - } else { - for(p1=PLA->symbolic_output;p1->next!=NIL(symbolic_t); - p1=p1->next){ - } - p1->next = newlist; - } - } else { - fatal("error reading .symbolic-output"); - } - - /* .phase allows a choice of output phases */ - } else if (equal(word, "phase")) { - if (cube.fullset == NULL) - fatal("PLA size must be declared before .phase"); - if (PLA->phase != NULL) { - (void) fprintf(stderr, "extra .phase ignored\n"); - skip_line(fp, stdout, /* echo */ FALSE); - } else { - do ch = getc(fp); while (ch == ' ' || ch == '\t'); - (void) ungetc(ch, fp); - PLA->phase = set_save(cube.fullset); - last = cube.last_part[cube.num_vars - 1]; - for(i=cube.first_part[cube.num_vars - 1]; i <= last; i++) - if ((ch = getc(fp)) == '0') - set_remove(PLA->phase, i); - else if (ch != '1') - fatal("only 0 or 1 allowed in phase description"); - } - - /* .pair allows for bit-pairing input variables */ - } else if (equal(word, "pair")) { - int j; - if (PLA->pair != NULL) { - (void) fprintf(stderr, "extra .pair ignored\n"); - } else { - ppair pair; - PLA->pair = pair = ALLOC(pair_t, 1); - if (fscanf(fp, "%d", &(pair->cnt)) != 1) - fatal("syntax error in .pair"); - pair->var1 = ALLOC(int, pair->cnt); - pair->var2 = ALLOC(int, pair->cnt); - for(i = 0; i < pair->cnt; i++) { - (void) get_word(fp, word); - if (word[0] == '(') (void) strcpy(word, word+1); - if (label_index(PLA, word, &var, &j)) { - pair->var1[i] = var+1; - } else { - fatal("syntax error in .pair"); - } - - (void) get_word(fp, word); - if (word[strlen(word)-1] == ')') { - word[strlen(word)-1]='\0'; - } - if (label_index(PLA, word, &var, &j)) { - pair->var2[i] = var+1; - } else { - fatal("syntax error in .pair"); - } - } - } - - } else { - if (echo_unknown_commands) - printf("%c%s ", ch, word); - skip_line(fp, stdout, echo_unknown_commands); - } - break; - default: - (void) ungetc(ch, fp); - if (cube.fullset == NULL) { -/* fatal("unknown PLA size, need .i/.o or .mv");*/ - if (echo_comments) - putchar('#'); - skip_line(fp, stdout, echo_comments); - break; - } - if (PLA->F == NULL) { - PLA->F = new_cover(10); - PLA->D = new_cover(10); - PLA->R = new_cover(10); - } - read_cube(fp, PLA); - } - goto loop; -} -/* - read_pla -- read a PLA from a file - - Input stops when ".e" is encountered in the input file, or upon reaching - end of file. - - Returns the PLA in the variable PLA after massaging the "symbolic" - representation into a positional cube notation of the ON-set, OFF-set, - and the DC-set. - - needs_dcset and needs_offset control the computation of the OFF-set - and DC-set (i.e., if either needs to be computed, then it will be - computed via complement only if the corresponding option is TRUE.) - pla_type specifies the interpretation to be used when reading the - PLA. - - The phase of the output functions is adjusted according to the - global option "pos" or according to an imbedded .phase option in - the input file. Note that either phase option implies that the - OFF-set be computed regardless of whether the caller needs it - explicitly or not. - - Bit pairing of the binary variables is performed according to an - imbedded .pair option in the input file. - - The global cube structure also reflects the sizes of the PLA which - was just read. If these fields have already been set, then any - subsequent PLA must conform to these sizes. - - The global flags trace and summary control the output produced - during the read. - - Returns a status code as a result: - EOF (-1) : End of file reached before any data was read - > 0 : Operation successful -*/ - -int read_pla(fp, needs_dcset, needs_offset, pla_type, PLA_return) -IN FILE *fp; -IN bool needs_dcset, needs_offset; -IN int pla_type; -OUT pPLA *PLA_return; -{ - pPLA PLA; - int i, second, third; - long time; - cost_t cost; - - /* Allocate and initialize the PLA structure */ - PLA = *PLA_return = new_PLA(); - PLA->pla_type = pla_type; - - /* Read the pla */ - time = ptime(); - parse_pla(fp, PLA); - - /* Check for nothing on the file -- implies reached EOF */ - if (PLA->F == NULL) { - return EOF; - } - - /* This hack merges the next-state field with the outputs */ - for(i = 0; i < cube.num_vars; i++) { - cube.part_size[i] = ABS(cube.part_size[i]); - } - if (kiss) { - third = cube.num_vars - 3; - second = cube.num_vars - 2; - if (cube.part_size[third] != cube.part_size[second]) { - (void) fprintf(stderr," with .kiss option, third to last and second\n"); - (void) fprintf(stderr, "to last variables must be the same size.\n"); - return EOF; - } - for(i = 0; i < cube.part_size[second]; i++) { - PLA->label[i + cube.first_part[second]] = - util_strsav(PLA->label[i + cube.first_part[third]]); - } - cube.part_size[second] += cube.part_size[cube.num_vars-1]; - cube.num_vars--; - setdown_cube(); - cube_setup(); - } - - if (trace) { - totals(time, READ_TIME, PLA->F, &cost); - } - - /* Decide how to break PLA into ON-set, OFF-set and DC-set */ - time = ptime(); - if (pos || PLA->phase != NULL || PLA->symbolic_output != NIL(symbolic_t)) { - needs_offset = TRUE; - } - if (needs_offset && (PLA->pla_type==F_type || PLA->pla_type==FD_type)) { - free_cover(PLA->R); - PLA->R = complement(cube2list(PLA->F, PLA->D)); - } else if (needs_dcset && PLA->pla_type == FR_type) { - pcover X; - free_cover(PLA->D); - /* hack, why not? */ - X = d1merge(sf_join(PLA->F, PLA->R), cube.num_vars - 1); - PLA->D = complement(cube1list(X)); - free_cover(X); - } else if (PLA->pla_type == R_type || PLA->pla_type == DR_type) { - free_cover(PLA->F); - PLA->F = complement(cube2list(PLA->D, PLA->R)); - } - - if (trace) { - totals(time, COMPL_TIME, PLA->R, &cost); - } - - /* Check for phase rearrangement of the functions */ - if (pos) { - pcover onset = PLA->F; - PLA->F = PLA->R; - PLA->R = onset; - PLA->phase = new_cube(); - set_diff(PLA->phase, cube.fullset, cube.var_mask[cube.num_vars-1]); - } else if (PLA->phase != NULL) { - (void) set_phase(PLA); - } - - /* Setup minimization for two-bit decoders */ - if (PLA->pair != (ppair) NULL) { - set_pair(PLA); - } - - if (PLA->symbolic != NIL(symbolic_t)) { - EXEC(map_symbolic(PLA), "MAP-INPUT ", PLA->F); - } - if (PLA->symbolic_output != NIL(symbolic_t)) { - EXEC(map_output_symbolic(PLA), "MAP-OUTPUT ", PLA->F); - if (needs_offset) { - free_cover(PLA->R); -EXECUTE(PLA->R=complement(cube2list(PLA->F,PLA->D)), COMPL_TIME, PLA->R, cost); - } - } - - return 1; -} - -void PLA_summary(PLA) -pPLA PLA; -{ - int var, i; - symbolic_list_t *p2; - symbolic_t *p1; - - printf("# PLA is %s", PLA->filename); - if (cube.num_binary_vars == cube.num_vars - 1) - printf(" with %d inputs and %d outputs\n", - cube.num_binary_vars, cube.part_size[cube.num_vars - 1]); - else { - printf(" with %d variables (%d binary, mv sizes", - cube.num_vars, cube.num_binary_vars); - for(var = cube.num_binary_vars; var < cube.num_vars; var++) - printf(" %d", cube.part_size[var]); - printf(")\n"); - } - printf("# ON-set cost is %s\n", print_cost(PLA->F)); - printf("# OFF-set cost is %s\n", print_cost(PLA->R)); - printf("# DC-set cost is %s\n", print_cost(PLA->D)); - if (PLA->phase != NULL) - printf("# phase is %s\n", pc1(PLA->phase)); - if (PLA->pair != NULL) { - printf("# two-bit decoders:"); - for(i = 0; i < PLA->pair->cnt; i++) - printf(" (%d %d)", PLA->pair->var1[i], PLA->pair->var2[i]); - printf("\n"); - } - if (PLA->symbolic != NIL(symbolic_t)) { - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { - printf("# symbolic: "); - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - printf(" %d", p2->variable); - } - printf("\n"); - } - } - if (PLA->symbolic_output != NIL(symbolic_t)) { - for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1->next) { - printf("# output symbolic: "); - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - printf(" %d", p2->pos); - } - printf("\n"); - } - } - (void) fflush(stdout); -} - - -pPLA new_PLA() -{ - pPLA PLA; - - PLA = ALLOC(PLA_t, 1); - PLA->F = PLA->D = PLA->R = (pcover) NULL; - PLA->phase = (pcube) NULL; - PLA->pair = (ppair) NULL; - PLA->label = (char **) NULL; - PLA->filename = (char *) NULL; - PLA->pla_type = 0; - PLA->symbolic = NIL(symbolic_t); - PLA->symbolic_output = NIL(symbolic_t); - return PLA; -} - - -PLA_labels(PLA) -pPLA PLA; -{ - int i; - - PLA->label = ALLOC(char *, cube.size); - for(i = 0; i < cube.size; i++) - PLA->label[i] = (char *) NULL; -} - - -void free_PLA(PLA) -pPLA PLA; -{ - symbolic_list_t *p2, *p2next; - symbolic_t *p1, *p1next; - int i; - - if (PLA->F != (pcover) NULL) - free_cover(PLA->F); - if (PLA->R != (pcover) NULL) - free_cover(PLA->R); - if (PLA->D != (pcover) NULL) - free_cover(PLA->D); - if (PLA->phase != (pcube) NULL) - free_cube(PLA->phase); - if (PLA->pair != (ppair) NULL) { - FREE(PLA->pair->var1); - FREE(PLA->pair->var2); - FREE(PLA->pair); - } - if (PLA->label != NULL) { - for(i = 0; i < cube.size; i++) - if (PLA->label[i] != NULL) - FREE(PLA->label[i]); - FREE(PLA->label); - } - if (PLA->filename != NULL) { - FREE(PLA->filename); - } - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1next) { - for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) { - p2next = p2->next; - FREE(p2); - } - p1next = p1->next; - FREE(p1); - } - PLA->symbolic = NIL(symbolic_t); - for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1next) { - for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) { - p2next = p2->next; - FREE(p2); - } - p1next = p1->next; - FREE(p1); - } - PLA->symbolic_output = NIL(symbolic_t); - FREE(PLA); -} - - -int read_symbolic(fp, PLA, word, retval) -FILE *fp; -pPLA PLA; -char *word; /* scratch string for words */ -symbolic_t **retval; -{ - symbolic_list_t *listp, *prev_listp; - symbolic_label_t *labelp, *prev_labelp; - symbolic_t *newlist; - int i, var; - - newlist = ALLOC(symbolic_t, 1); - newlist->next = NIL(symbolic_t); - newlist->symbolic_list = NIL(symbolic_list_t); - newlist->symbolic_list_length = 0; - newlist->symbolic_label = NIL(symbolic_label_t); - newlist->symbolic_label_length = 0; - prev_listp = NIL(symbolic_list_t); - prev_labelp = NIL(symbolic_label_t); - - for(;;) { - (void) get_word(fp, word); - if (equal(word, ";")) - break; - if (label_index(PLA, word, &var, &i)) { - listp = ALLOC(symbolic_list_t, 1); - listp->variable = var; - listp->pos = i; - listp->next = NIL(symbolic_list_t); - if (prev_listp == NIL(symbolic_list_t)) { - newlist->symbolic_list = listp; - } else { - prev_listp->next = listp; - } - prev_listp = listp; - newlist->symbolic_list_length++; - } else { - return FALSE; - } - } - - for(;;) { - (void) get_word(fp, word); - if (equal(word, ";")) - break; - labelp = ALLOC(symbolic_label_t, 1); - labelp->label = util_strsav(word); - labelp->next = NIL(symbolic_label_t); - if (prev_labelp == NIL(symbolic_label_t)) { - newlist->symbolic_label = labelp; - } else { - prev_labelp->next = labelp; - } - prev_labelp = labelp; - newlist->symbolic_label_length++; - } - - *retval = newlist; - return TRUE; -} - - -int label_index(PLA, word, varp, ip) -pPLA PLA; -char *word; -int *varp; -int *ip; -{ - int var, i; - - if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) { - if (sscanf(word, "%d", varp) == 1) { - *ip = *varp; - return TRUE; - } - } else { - for(var = 0; var < cube.num_vars; var++) { - for(i = 0; i < cube.part_size[var]; i++) { - if (equal(PLA->label[cube.first_part[var]+i], word)) { - *varp = var; - *ip = i; - return TRUE; - } - } - } - } - return FALSE; -} diff --git a/src/misc/espresso/cvrm.c b/src/misc/espresso/cvrm.c deleted file mode 100644 index 7d42d6e3..00000000 --- a/src/misc/espresso/cvrm.c +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - module: cvrm.c - Purpose: miscellaneous cover manipulation - a) verify two covers are equal, check consistency of a cover - b) unravel a multiple-valued cover into minterms - c) sort covers -*/ - -#include "espresso.h" - - -static void cb_unravel(c, start, end, startbase, B1) -IN register pcube c; -IN int start, end; -IN pcube startbase; -INOUT pcover B1; -{ - pcube base = cube.temp[0], p, last; - int expansion, place, skip, var, size, offset; - register int i, j, k, n; - - /* Determine how many cubes it will blow up into, and create a mask - for those parts that have only a single coordinate - */ - expansion = 1; - (void) set_copy(base, startbase); - for(var = start; var <= end; var++) { - if ((size = set_dist(c, cube.var_mask[var])) < 2) { - (void) set_or(base, base, cube.var_mask[var]); - } else { - expansion *= size; - } - } - (void) set_and(base, c, base); - - /* Add the unravelled sets starting at the last element of B1 */ - offset = B1->count; - B1->count += expansion; - foreach_remaining_set(B1, last, GETSET(B1, offset-1), p) { - INLINEset_copy(p, base); - } - - place = expansion; - for(var = start; var <= end; var++) { - if ((size = set_dist(c, cube.var_mask[var])) > 1) { - skip = place; - place = place / size; - n = 0; - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - if (is_in_set(c, i)) { - for(j = n; j < expansion; j += skip) { - for(k = 0; k < place; k++) { - p = GETSET(B1, j+k+offset); - (void) set_insert(p, i); - } - } - n += place; - } - } - } - } -} - - -pcover unravel_range(B, start, end) -IN pcover B; -IN int start, end; -{ - pcover B1; - int var, total_size, expansion, size; - register pcube p, last, startbase = cube.temp[1]; - - /* Create the starting base for those variables not being unravelled */ - (void) set_copy(startbase, cube.emptyset); - for(var = 0; var < start; var++) - (void) set_or(startbase, startbase, cube.var_mask[var]); - for(var = end+1; var < cube.num_vars; var++) - (void) set_or(startbase, startbase, cube.var_mask[var]); - - /* Determine how many cubes it will blow up into */ - total_size = 0; - foreach_set(B, last, p) { - expansion = 1; - for(var = start; var <= end; var++) - if ((size = set_dist(p, cube.var_mask[var])) >= 2) - if ((expansion *= size) > 1000000) - fatal("unreasonable expansion in unravel"); - total_size += expansion; - } - - /* We can now allocate a cover of exactly the correct size */ - B1 = new_cover(total_size); - foreach_set(B, last, p) { - cb_unravel(p, start, end, startbase, B1); - } - free_cover(B); - return B1; -} - - -pcover unravel(B, start) -IN pcover B; -IN int start; -{ - return unravel_range(B, start, cube.num_vars-1); -} - -/* lex_sort -- sort cubes in a standard lexical fashion */ -pcover lex_sort(T) -pcover T; -{ - pcover T1 = sf_unlist(sf_sort(T, lex_order), T->count, T->sf_size); - free_cover(T); - return T1; -} - - -/* size_sort -- sort cubes by their size */ -pcover size_sort(T) -pcover T; -{ - pcover T1 = sf_unlist(sf_sort(T, descend), T->count, T->sf_size); - free_cover(T); - return T1; -} - - -/* mini_sort -- sort cubes according to the heuristics of mini */ -pcover mini_sort(F, compare) -pcover F; -int (*compare)(); -{ - register int *count, cnt, n = cube.size, i; - register pcube p, last; - pcover F_sorted; - pcube *F1; - - /* Perform a column sum over the set family */ - count = sf_count(F); - - /* weight is "inner product of the cube and the column sums" */ - foreach_set(F, last, p) { - cnt = 0; - for(i = 0; i < n; i++) - if (is_in_set(p, i)) - cnt += count[i]; - PUTSIZE(p, cnt); - } - FREE(count); - - /* use qsort to sort the array */ - qsort((char *) (F1 = sf_list(F)), F->count, sizeof(pcube), compare); - F_sorted = sf_unlist(F1, F->count, F->sf_size); - free_cover(F); - - return F_sorted; -} - - -/* sort_reduce -- Espresso strategy for ordering the cubes before reduction */ -pcover sort_reduce(T) -IN pcover T; -{ - register pcube p, last, largest = NULL; - register int bestsize = -1, size, n = cube.num_vars; - pcover T_sorted; - pcube *T1; - - if (T->count == 0) - return T; - - /* find largest cube */ - foreach_set(T, last, p) - if ((size = set_ord(p)) > bestsize) - largest = p, bestsize = size; - - foreach_set(T, last, p) - PUTSIZE(p, ((n - cdist(largest,p)) << 7) + MIN(set_ord(p),127)); - - qsort((char *) (T1 = sf_list(T)), T->count, sizeof(pcube), (int (*)()) descend); - T_sorted = sf_unlist(T1, T->count, T->sf_size); - free_cover(T); - - return T_sorted; -} - -pcover random_order(F) -register pcover F; -{ - pset temp; - register int i, k; -#ifdef RANDOM - long random(); -#endif - - temp = set_new(F->sf_size); - for(i = F->count - 1; i > 0; i--) { - /* Choose a random number between 0 and i */ -#ifdef RANDOM - k = random() % i; -#else - /* this is not meant to be really used; just provides an easy - "out" if random() and srandom() aren't around - */ - k = (i*23 + 997) % i; -#endif - /* swap sets i and k */ - (void) set_copy(temp, GETSET(F, k)); - (void) set_copy(GETSET(F, k), GETSET(F, i)); - (void) set_copy(GETSET(F, i), temp); - } - set_free(temp); - return F; -} - -/* - * cubelist_partition -- take a cubelist T and see if it has any components; - * if so, return cubelist's of the two partitions A and B; the return value - * is the size of the partition; if not, A and B - * are undefined and the return value is 0 - */ -int cubelist_partition(T, A, B, comp_debug) -pcube *T; /* a list of cubes */ -pcube **A, **B; /* cubelist of partition and remainder */ -unsigned int comp_debug; -{ - register pcube *T1, p, seed, cof; - pcube *A1, *B1; - bool change; - int count, numcube; - - numcube = CUBELISTSIZE(T); - - /* Mark all cubes -- covered cubes belong to the partition */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - RESET(p, COVERED); - } - - /* - * Extract a partition from the cubelist T; start with the first cube as a - * seed, and then pull in all cubes which share a variable with the seed; - * iterate until no new cubes are brought into the partition. - */ - seed = set_save(T[2]); - cof = T[0]; - SET(T[2], COVERED); - count = 1; - - do { - change = FALSE; - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (! TESTP(p, COVERED) && ccommon(p, seed, cof)) { - INLINEset_and(seed, seed, p); - SET(p, COVERED); - change = TRUE; - count++; - } - - } - } while (change); - - set_free(seed); - - if (comp_debug) { - (void) printf("COMPONENT_REDUCTION: split into %d %d\n", - count, numcube - count); - } - - if (count != numcube) { - /* Allocate and setup the cubelist's for the two partitions */ - *A = A1 = ALLOC(pcube, numcube+3); - *B = B1 = ALLOC(pcube, numcube+3); - (*A)[0] = set_save(T[0]); - (*B)[0] = set_save(T[0]); - A1 = *A + 2; - B1 = *B + 2; - - /* Loop over the cubes in T and distribute to A and B */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (TESTP(p, COVERED)) { - *A1++ = p; - } else { - *B1++ = p; - } - } - - /* Stuff needed at the end of the cubelist's */ - *A1++ = NULL; - (*A)[1] = (pcube) A1; - *B1++ = NULL; - (*B)[1] = (pcube) B1; - } - - return numcube - count; -} - -/* - * quick cofactor against a single output function - */ -pcover cof_output(T, i) -pcover T; -register int i; -{ - pcover T1; - register pcube p, last, pdest, mask; - - mask = cube.var_mask[cube.output]; - T1 = new_cover(T->count); - foreach_set(T, last, p) { - if (is_in_set(p, i)) { - pdest = GETSET(T1, T1->count++); - INLINEset_or(pdest, p, mask); - RESET(pdest, PRIME); - } - } - return T1; -} - - -/* - * quick intersection against a single output function - */ -pcover uncof_output(T, i) -pcover T; -int i; -{ - register pcube p, last, mask; - - if (T == NULL) { - return T; - } - - mask = cube.var_mask[cube.output]; - foreach_set(T, last, p) { - INLINEset_diff(p, p, mask); - set_insert(p, i); - } - return T; -} - - -/* - * A generic routine to perform an operation for each output function - * - * func() is called with a PLA for each output function (with the output - * part effectively removed). - * func1() is called after reforming the equivalent output function - * - * Each function returns TRUE if process is to continue - */ -foreach_output_function(PLA, func, func1) -pPLA PLA; -int (*func)(); -int (*func1)(); -{ - pPLA PLA1; - int i; - - /* Loop for each output function */ - for(i = 0; i < cube.part_size[cube.output]; i++) { - - /* cofactor on the output part */ - PLA1 = new_PLA(); - PLA1->F = cof_output(PLA->F, i + cube.first_part[cube.output]); - PLA1->R = cof_output(PLA->R, i + cube.first_part[cube.output]); - PLA1->D = cof_output(PLA->D, i + cube.first_part[cube.output]); - - /* Call a routine to do something with the cover */ - if ((*func)(PLA1, i) == 0) { - free_PLA(PLA1); - return; - } - - /* intersect with the particular output part again */ - PLA1->F = uncof_output(PLA1->F, i + cube.first_part[cube.output]); - PLA1->R = uncof_output(PLA1->R, i + cube.first_part[cube.output]); - PLA1->D = uncof_output(PLA1->D, i + cube.first_part[cube.output]); - - /* Call a routine to do something with the final result */ - if ((*func1)(PLA1, i) == 0) { - free_PLA(PLA1); - return; - } - - /* Cleanup for next go-around */ - free_PLA(PLA1); - - - } -} - -static pcover Fmin; -static pcube phase; - -/* - * minimize each output function individually - */ -void so_espresso(PLA, strategy) -pPLA PLA; -int strategy; -{ - Fmin = new_cover(PLA->F->count); - if (strategy == 0) { - foreach_output_function(PLA, so_do_espresso, so_save); - } else { - foreach_output_function(PLA, so_do_exact, so_save); - } - sf_free(PLA->F); - PLA->F = Fmin; -} - - -/* - * minimize each output function, choose function or complement based on the - * one with the fewer number of terms - */ -void so_both_espresso(PLA, strategy) -pPLA PLA; -int strategy; -{ - phase = set_save(cube.fullset); - Fmin = new_cover(PLA->F->count); - if (strategy == 0) { - foreach_output_function(PLA, so_both_do_espresso, so_both_save); - } else { - foreach_output_function(PLA, so_both_do_exact, so_both_save); - } - sf_free(PLA->F); - PLA->F = Fmin; - PLA->phase = phase; -} - - -int so_do_espresso(PLA, i) -pPLA PLA; -int i; -{ - char word[32]; - - /* minimize the single-output function (on-set) */ - skip_make_sparse = 1; - (void) sprintf(word, "ESPRESSO-POS(%d)", i); - EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F); - return 1; -} - - -int so_do_exact(PLA, i) -pPLA PLA; -int i; -{ - char word[32]; - - /* minimize the single-output function (on-set) */ - skip_make_sparse = 1; - (void) sprintf(word, "EXACT-POS(%d)", i); - EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F); - return 1; -} - - -/*ARGSUSED*/ -int so_save(PLA, i) -pPLA PLA; -int i; -{ - Fmin = sf_append(Fmin, PLA->F); /* disposes of PLA->F */ - PLA->F = NULL; - return 1; -} - - -int so_both_do_espresso(PLA, i) -pPLA PLA; -int i; -{ - char word[32]; - - /* minimize the single-output function (on-set) */ - (void) sprintf(word, "ESPRESSO-POS(%d)", i); - skip_make_sparse = 1; - EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F); - - /* minimize the single-output function (off-set) */ - (void) sprintf(word, "ESPRESSO-NEG(%d)", i); - skip_make_sparse = 1; - EXEC_S(PLA->R = espresso(PLA->R, PLA->D, PLA->F), word, PLA->R); - - return 1; -} - - -int so_both_do_exact(PLA, i) -pPLA PLA; -int i; -{ - char word[32]; - - /* minimize the single-output function (on-set) */ - (void) sprintf(word, "EXACT-POS(%d)", i); - skip_make_sparse = 1; - EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F); - - /* minimize the single-output function (off-set) */ - (void) sprintf(word, "EXACT-NEG(%d)", i); - skip_make_sparse = 1; - EXEC_S(PLA->R = minimize_exact(PLA->R, PLA->D, PLA->F, 1), word, PLA->R); - - return 1; -} - - -int so_both_save(PLA, i) -pPLA PLA; -int i; -{ - if (PLA->F->count > PLA->R->count) { - sf_free(PLA->F); - PLA->F = PLA->R; - PLA->R = NULL; - i += cube.first_part[cube.output]; - set_remove(phase, i); - } else { - sf_free(PLA->R); - PLA->R = NULL; - } - Fmin = sf_append(Fmin, PLA->F); - PLA->F = NULL; - return 1; -} diff --git a/src/misc/espresso/cvrmisc.c b/src/misc/espresso/cvrmisc.c deleted file mode 100644 index 0f3de195..00000000 --- a/src/misc/espresso/cvrmisc.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - - -/* cost -- compute the cost of a cover */ -void cover_cost(F, cost) -IN pcover F; -INOUT pcost cost; -{ - register pcube p, last; - pcube *T; - int var; - - /* use the routine used by cofactor to decide splitting variables */ - massive_count(T = cube1list(F)); - free_cubelist(T); - - cost->cubes = F->count; - cost->total = cost->in = cost->out = cost->mv = cost->primes = 0; - - /* Count transistors (zeros) for each binary variable (inputs) */ - for(var = 0; var < cube.num_binary_vars; var++) - cost->in += cdata.var_zeros[var]; - - /* Count transistors for each mv variable based on sparse/dense */ - for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) - if (cube.sparse[var]) - cost->mv += F->count * cube.part_size[var] - cdata.var_zeros[var]; - else - cost->mv += cdata.var_zeros[var]; - - /* Count the transistors (ones) for the output variable */ - if (cube.num_binary_vars != cube.num_vars) { - var = cube.num_vars - 1; - cost->out = F->count * cube.part_size[var] - cdata.var_zeros[var]; - } - - /* Count the number of nonprime cubes */ - foreach_set(F, last, p) - cost->primes += TESTP(p, PRIME) != 0; - - /* Count the total number of literals */ - cost->total = cost->in + cost->out + cost->mv; -} - - -/* fmt_cost -- return a string which reports the "cost" of a cover */ -char *fmt_cost(cost) -IN pcost cost; -{ - static char s[200]; - - if (cube.num_binary_vars == cube.num_vars - 1) - (void) sprintf(s, "c=%d(%d) in=%d out=%d tot=%d", - cost->cubes, cost->cubes - cost->primes, cost->in, - cost->out, cost->total); - else - (void) sprintf(s, "c=%d(%d) in=%d mv=%d out=%d", - cost->cubes, cost->cubes - cost->primes, cost->in, - cost->mv, cost->out); - return s; -} - - -char *print_cost(F) -IN pcover F; -{ - cost_t cost; - cover_cost(F, &cost); - return fmt_cost(&cost); -} - - -/* copy_cost -- copy a cost function from s to d */ -void copy_cost(s, d) -pcost s, d; -{ - d->cubes = s->cubes; - d->in = s->in; - d->out = s->out; - d->mv = s->mv; - d->total = s->total; - d->primes = s->primes; -} - - -/* size_stamp -- print single line giving the size of a cover */ -void size_stamp(T, name) -IN pcover T; -IN char *name; -{ - (void) printf("# %s\tCost is %s\n", name, print_cost(T)); - (void) fflush(stdout); -} - - -/* print_trace -- print a line reporting size and time after a function */ -void print_trace(T, name, time) -pcover T; -char *name; -long time; -{ - (void) printf("# %s\tTime was %s, cost is %s\n", - name, print_time(time), print_cost(T)); - (void) fflush(stdout); -} - - -/* totals -- add time spent in the function into the totals */ -void totals(time, i, T, cost) -long time; -int i; -pcover T; -pcost cost; -{ - time = ptime() - time; - total_time[i] += time; - total_calls[i]++; - cover_cost(T, cost); - if (trace) { - (void) printf("# %s\tTime was %s, cost is %s\n", - total_name[i], print_time(time), fmt_cost(cost)); - (void) fflush(stdout); - } -} - - -/* fatal -- report fatal error message and take a dive */ -void fatal(s) -char *s; -{ - (void) fprintf(stderr, "espresso: %s\n", s); - exit(1); -} diff --git a/src/misc/espresso/cvrout.c b/src/misc/espresso/cvrout.c deleted file mode 100644 index 4bd1c53b..00000000 --- a/src/misc/espresso/cvrout.c +++ /dev/null @@ -1,609 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - module: cvrout.c - purpose: cube and cover output routines -*/ - -#include "espresso.h" - -void fprint_pla(fp, PLA, output_type) -INOUT FILE *fp; -IN pPLA PLA; -IN int output_type; -{ - int num; - register pcube last, p; - - if ((output_type & CONSTRAINTS_type) != 0) { - output_symbolic_constraints(fp, PLA, 0); - output_type &= ~ CONSTRAINTS_type; - if (output_type == 0) { - return; - } - } - - if ((output_type & SYMBOLIC_CONSTRAINTS_type) != 0) { - output_symbolic_constraints(fp, PLA, 1); - output_type &= ~ SYMBOLIC_CONSTRAINTS_type; - if (output_type == 0) { - return; - } - } - - if (output_type == PLEASURE_type) { - pls_output(PLA); - } else if (output_type == EQNTOTT_type) { - eqn_output(PLA); - } else if (output_type == KISS_type) { - kiss_output(fp, PLA); - } else { - fpr_header(fp, PLA, output_type); - - num = 0; - if (output_type & F_type) num += (PLA->F)->count; - if (output_type & D_type) num += (PLA->D)->count; - if (output_type & R_type) num += (PLA->R)->count; - (void) fprintf(fp, ".p %d\n", num); - - /* quick patch 01/17/85 to support TPLA ! */ - if (output_type == F_type) { - foreach_set(PLA->F, last, p) { - print_cube(fp, p, "01"); - } - (void) fprintf(fp, ".e\n"); - } else { - if (output_type & F_type) { - foreach_set(PLA->F, last, p) { - print_cube(fp, p, "~1"); - } - } - if (output_type & D_type) { - foreach_set(PLA->D, last, p) { - print_cube(fp, p, "~2"); - } - } - if (output_type & R_type) { - foreach_set(PLA->R, last, p) { - print_cube(fp, p, "~0"); - } - } - (void) fprintf(fp, ".end\n"); - } - } -} - -void fpr_header(fp, PLA, output_type) -FILE *fp; -pPLA PLA; -int output_type; -{ - register int i, var; - int first, last; - - /* .type keyword gives logical type */ - if (output_type != F_type) { - (void) fprintf(fp, ".type "); - if (output_type & F_type) putc('f', fp); - if (output_type & D_type) putc('d', fp); - if (output_type & R_type) putc('r', fp); - putc('\n', fp); - } - - /* Check for binary or multiple-valued labels */ - if (cube.num_mv_vars <= 1) { - (void) fprintf(fp, ".i %d\n", cube.num_binary_vars); - if (cube.output != -1) - (void) fprintf(fp, ".o %d\n", cube.part_size[cube.output]); - } else { - (void) fprintf(fp, ".mv %d %d", cube.num_vars, cube.num_binary_vars); - for(var = cube.num_binary_vars; var < cube.num_vars; var++) - (void) fprintf(fp, " %d", cube.part_size[var]); - (void) fprintf(fp, "\n"); - } - - /* binary valued labels */ - if (PLA->label != NIL(char *) && PLA->label[1] != NIL(char) - && cube.num_binary_vars > 0) { - (void) fprintf(fp, ".ilb"); - for(var = 0; var < cube.num_binary_vars; var++) - /* see (NIL) OUTLABELS comment below */ - if(INLABEL(var) == NIL(char)){ - (void) fprintf(fp, " (null)"); - } - else{ - (void) fprintf(fp, " %s", INLABEL(var)); - } - putc('\n', fp); - } - - /* output-part (last multiple-valued variable) labels */ - if (PLA->label != NIL(char *) && - PLA->label[cube.first_part[cube.output]] != NIL(char) - && cube.output != -1) { - (void) fprintf(fp, ".ob"); - for(i = 0; i < cube.part_size[cube.output]; i++) - /* (NIL) OUTLABELS caused espresso to segfault under solaris */ - if(OUTLABEL(i) == NIL(char)){ - (void) fprintf(fp, " (null)"); - } - else{ - (void) fprintf(fp, " %s", OUTLABEL(i)); - } - putc('\n', fp); - } - - /* multiple-valued labels */ - for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) { - first = cube.first_part[var]; - last = cube.last_part[var]; - if (PLA->label != NULL && PLA->label[first] != NULL) { - (void) fprintf(fp, ".label var=%d", var); - for(i = first; i <= last; i++) { - (void) fprintf(fp, " %s", PLA->label[i]); - } - putc('\n', fp); - } - } - - if (PLA->phase != (pcube) NULL) { - first = cube.first_part[cube.output]; - last = cube.last_part[cube.output]; - (void) fprintf(fp, "#.phase "); - for(i = first; i <= last; i++) - putc(is_in_set(PLA->phase,i) ? '1' : '0', fp); - (void) fprintf(fp, "\n"); - } -} - -void pls_output(PLA) -IN pPLA PLA; -{ - register pcube last, p; - - (void) printf(".option unmerged\n"); - makeup_labels(PLA); - pls_label(PLA, stdout); - pls_group(PLA, stdout); - (void) printf(".p %d\n", PLA->F->count); - foreach_set(PLA->F, last, p) { - print_expanded_cube(stdout, p, PLA->phase); - } - (void) printf(".end\n"); -} - - -void pls_group(PLA, fp) -pPLA PLA; -FILE *fp; -{ - int var, i, col, len; - - (void) fprintf(fp, "\n.group"); - col = 6; - for(var = 0; var < cube.num_vars-1; var++) { - (void) fprintf(fp, " ("), col += 2; - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - len = strlen(PLA->label[i]); - if (col + len > 75) - (void) fprintf(fp, " \\\n"), col = 0; - else if (i != 0) - putc(' ', fp), col += 1; - (void) fprintf(fp, "%s", PLA->label[i]), col += len; - } - (void) fprintf(fp, ")"), col += 1; - } - (void) fprintf(fp, "\n"); -} - - -void pls_label(PLA, fp) -pPLA PLA; -FILE *fp; -{ - int var, i, col, len; - - (void) fprintf(fp, ".label"); - col = 6; - for(var = 0; var < cube.num_vars; var++) - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - len = strlen(PLA->label[i]); - if (col + len > 75) - (void) fprintf(fp, " \\\n"), col = 0; - else - putc(' ', fp), col += 1; - (void) fprintf(fp, "%s", PLA->label[i]), col += len; - } -} - - - -/* - eqntott output mode -- output algebraic equations -*/ -void eqn_output(PLA) -pPLA PLA; -{ - register pcube p, last; - register int i, var, col, len; - int x; - bool firstand, firstor; - - if (cube.output == -1) - fatal("Cannot have no-output function for EQNTOTT output mode"); - if (cube.num_mv_vars != 1) - fatal("Must have binary-valued function for EQNTOTT output mode"); - makeup_labels(PLA); - - /* Write a single equation for each output */ - for(i = 0; i < cube.part_size[cube.output]; i++) { - (void) printf("%s = ", OUTLABEL(i)); - col = strlen(OUTLABEL(i)) + 3; - firstor = TRUE; - - /* Write product terms for each cube in this output */ - foreach_set(PLA->F, last, p) - if (is_in_set(p, i + cube.first_part[cube.output])) { - if (firstor) - (void) printf("("), col += 1; - else - (void) printf(" | ("), col += 4; - firstor = FALSE; - firstand = TRUE; - - /* print out a product term */ - for(var = 0; var < cube.num_binary_vars; var++) - if ((x=GETINPUT(p, var)) != DASH) { - len = strlen(INLABEL(var)); - if (col+len > 72) - (void) printf("\n "), col = 4; - if (! firstand) - (void) printf("&"), col += 1; - firstand = FALSE; - if (x == ZERO) - (void) printf("!"), col += 1; - (void) printf("%s", INLABEL(var)), col += len; - } - (void) printf(")"), col += 1; - } - (void) printf(";\n\n"); - } -} - - -char *fmt_cube(c, out_map, s) -register pcube c; -register char *out_map, *s; -{ - register int i, var, last, len = 0; - - for(var = 0; var < cube.num_binary_vars; var++) { - s[len++] = "?01-" [GETINPUT(c, var)]; - } - for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { - s[len++] = ' '; - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - s[len++] = "01" [is_in_set(c, i) != 0]; - } - } - if (cube.output != -1) { - last = cube.last_part[cube.output]; - s[len++] = ' '; - for(i = cube.first_part[cube.output]; i <= last; i++) { - s[len++] = out_map [is_in_set(c, i) != 0]; - } - } - s[len] = '\0'; - return s; -} - - -void print_cube(fp, c, out_map) -register FILE *fp; -register pcube c; -register char *out_map; -{ - register int i, var, ch; - int last; - - for(var = 0; var < cube.num_binary_vars; var++) { - ch = "?01-" [GETINPUT(c, var)]; - putc(ch, fp); - } - for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { - putc(' ', fp); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - ch = "01" [is_in_set(c, i) != 0]; - putc(ch, fp); - } - } - if (cube.output != -1) { - last = cube.last_part[cube.output]; - putc(' ', fp); - for(i = cube.first_part[cube.output]; i <= last; i++) { - ch = out_map [is_in_set(c, i) != 0]; - putc(ch, fp); - } - } - putc('\n', fp); -} - - -void print_expanded_cube(fp, c, phase) -register FILE *fp; -register pcube c; -pcube phase; -{ - register int i, var, ch; - char *out_map; - - for(var = 0; var < cube.num_binary_vars; var++) { - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - ch = "~1" [is_in_set(c, i) != 0]; - putc(ch, fp); - } - } - for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - ch = "1~" [is_in_set(c, i) != 0]; - putc(ch, fp); - } - } - if (cube.output != -1) { - var = cube.num_vars - 1; - putc(' ', fp); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - if (phase == (pcube) NULL || is_in_set(phase, i)) { - out_map = "~1"; - } else { - out_map = "~0"; - } - ch = out_map[is_in_set(c, i) != 0]; - putc(ch, fp); - } - } - putc('\n', fp); -} - - -char *pc1(c) pcube c; -{static char s1[256];return fmt_cube(c, "01", s1);} -char *pc2(c) pcube c; -{static char s2[256];return fmt_cube(c, "01", s2);} - - -void debug_print(T, name, level) -pcube *T; -char *name; -int level; -{ - register pcube *T1, p, temp; - register int cnt; - - cnt = CUBELISTSIZE(T); - temp = new_cube(); - if (verbose_debug && level == 0) - (void) printf("\n"); - (void) printf("%s[%d]: ord(T)=%d\n", name, level, cnt); - if (verbose_debug) { - (void) printf("cofactor=%s\n", pc1(T[0])); - for(T1 = T+2, cnt = 1; (p = *T1++) != (pcube) NULL; cnt++) - (void) printf("%4d. %s\n", cnt, pc1(set_or(temp, p, T[0]))); - } - free_cube(temp); -} - - -void debug1_print(T, name, num) -pcover T; -char *name; -int num; -{ - register int cnt = 1; - register pcube p, last; - - if (verbose_debug && num == 0) - (void) printf("\n"); - (void) printf("%s[%d]: ord(T)=%d\n", name, num, T->count); - if (verbose_debug) - foreach_set(T, last, p) - (void) printf("%4d. %s\n", cnt++, pc1(p)); -} - - -void cprint(T) -pcover T; -{ - register pcube p, last; - - foreach_set(T, last, p) - (void) printf("%s\n", pc1(p)); -} - - -int makeup_labels(PLA) -pPLA PLA; -{ - int var, i, ind; - - if (PLA->label == (char **) NULL) - PLA_labels(PLA); - - for(var = 0; var < cube.num_vars; var++) - for(i = 0; i < cube.part_size[var]; i++) { - ind = cube.first_part[var] + i; - if (PLA->label[ind] == (char *) NULL) { - PLA->label[ind] = ALLOC(char, 15); - if (var < cube.num_binary_vars) - if ((i % 2) == 0) - (void) sprintf(PLA->label[ind], "v%d.bar", var); - else - (void) sprintf(PLA->label[ind], "v%d", var); - else - (void) sprintf(PLA->label[ind], "v%d.%d", var, i); - } - } -} - - -kiss_output(fp, PLA) -FILE *fp; -pPLA PLA; -{ - register pset last, p; - - foreach_set(PLA->F, last, p) { - kiss_print_cube(fp, PLA, p, "~1"); - } - foreach_set(PLA->D, last, p) { - kiss_print_cube(fp, PLA, p, "~2"); - } -} - - -kiss_print_cube(fp, PLA, p, out_string) -FILE *fp; -pPLA PLA; -pcube p; -char *out_string; -{ - register int i, var; - int part, x; - - for(var = 0; var < cube.num_binary_vars; var++) { - x = "?01-" [GETINPUT(p, var)]; - putc(x, fp); - } - - for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) { - putc(' ', fp); - if (setp_implies(cube.var_mask[var], p)) { - putc('-', fp); - } else { - part = -1; - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - if (is_in_set(p, i)) { - if (part != -1) { - fatal("more than 1 part in a symbolic variable\n"); - } - part = i; - } - } - if (part == -1) { - putc('~', fp); /* no parts, hope its an output ... */ - } else { - (void) fputs(PLA->label[part], fp); - } - } - } - - if ((var = cube.output) != -1) { - putc(' ', fp); - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - x = out_string [is_in_set(p, i) != 0]; - putc(x, fp); - } - } - - putc('\n', fp); -} - -output_symbolic_constraints(fp, PLA, output_symbolic) -FILE *fp; -pPLA PLA; -int output_symbolic; -{ - pset_family A; - register int i, j; - int size, var, npermute, *permute, *weight, noweight; - - if ((cube.num_vars - cube.num_binary_vars) <= 1) { - return; - } - makeup_labels(PLA); - - for(var=cube.num_binary_vars; var < cube.num_vars-1; var++) { - - /* pull out the columns for variable "var" */ - npermute = cube.part_size[var]; - permute = ALLOC(int, npermute); - for(i=0; i < npermute; i++) { - permute[i] = cube.first_part[var] + i; - } - A = sf_permute(sf_save(PLA->F), permute, npermute); - FREE(permute); - - - /* Delete the singletons and the full sets */ - noweight = 0; - for(i = 0; i < A->count; i++) { - size = set_ord(GETSET(A,i)); - if (size == 1 || size == A->sf_size) { - sf_delset(A, i--); - noweight++; - } - } - - - /* Count how many times each is duplicated */ - weight = ALLOC(int, A->count); - for(i = 0; i < A->count; i++) { - RESET(GETSET(A, i), COVERED); - } - for(i = 0; i < A->count; i++) { - weight[i] = 0; - if (! TESTP(GETSET(A,i), COVERED)) { - weight[i] = 1; - for(j = i+1; j < A->count; j++) { - if (setp_equal(GETSET(A,i), GETSET(A,j))) { - weight[i]++; - SET(GETSET(A,j), COVERED); - } - } - } - } - - - /* Print out the contraints */ - if (! output_symbolic) { - (void) fprintf(fp, - "# Symbolic constraints for variable %d (Numeric form)\n", var); - (void) fprintf(fp, "# unconstrained weight = %d\n", noweight); - (void) fprintf(fp, "num_codes=%d\n", cube.part_size[var]); - for(i = 0; i < A->count; i++) { - if (weight[i] > 0) { - (void) fprintf(fp, "weight=%d: ", weight[i]); - for(j = 0; j < A->sf_size; j++) { - if (is_in_set(GETSET(A,i), j)) { - (void) fprintf(fp, " %d", j); - } - } - (void) fprintf(fp, "\n"); - } - } - } else { - (void) fprintf(fp, - "# Symbolic constraints for variable %d (Symbolic form)\n", var); - for(i = 0; i < A->count; i++) { - if (weight[i] > 0) { - (void) fprintf(fp, "# w=%d: (", weight[i]); - for(j = 0; j < A->sf_size; j++) { - if (is_in_set(GETSET(A,i), j)) { - (void) fprintf(fp, " %s", - PLA->label[cube.first_part[var]+j]); - } - } - (void) fprintf(fp, " )\n"); - } - } - FREE(weight); - } - } -} diff --git a/src/misc/espresso/dominate.c b/src/misc/espresso/dominate.c deleted file mode 100644 index a930d453..00000000 --- a/src/misc/espresso/dominate.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "mincov_int.h" - - -int -sm_row_dominance(A) -sm_matrix *A; -{ - register sm_row *prow, *prow1; - register sm_col *pcol, *least_col; - register sm_element *p, *pnext; - int rowcnt; - - rowcnt = A->nrows; - - /* Check each row against all other rows */ - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - - /* Among all columns with a 1 in this row, choose smallest */ - least_col = sm_get_col(A, prow->first_col->col_num); - for(p = prow->first_col->next_col; p != 0; p = p->next_col) { - pcol = sm_get_col(A, p->col_num); - if (pcol->length < least_col->length) { - least_col = pcol; - } - } - - /* Only check for containment against rows in this column */ - for(p = least_col->first_row; p != 0; p = pnext) { - pnext = p->next_row; - - prow1 = sm_get_row(A, p->row_num); - if ((prow1->length > prow->length) || - (prow1->length == prow->length && - prow1->row_num > prow->row_num)) { - if (sm_row_contains(prow, prow1)) { - sm_delrow(A, prow1->row_num); - } - } - } - } - - return rowcnt - A->nrows; -} - -int -sm_col_dominance(A, weight) -sm_matrix *A; -int *weight; -{ - register sm_row *prow; - register sm_col *pcol, *pcol1; - register sm_element *p; - sm_row *least_row; - sm_col *next_col; - int colcnt; - - colcnt = A->ncols; - - /* Check each column against all other columns */ - for(pcol = A->first_col; pcol != 0; pcol = next_col) { - next_col = pcol->next_col; - - /* Check all rows to find the one with fewest elements */ - least_row = sm_get_row(A, pcol->first_row->row_num); - for(p = pcol->first_row->next_row; p != 0; p = p->next_row) { - prow = sm_get_row(A, p->row_num); - if (prow->length < least_row->length) { - least_row = prow; - } - } - - /* Only check for containment against columns in this row */ - for(p = least_row->first_col; p != 0; p = p->next_col) { - pcol1 = sm_get_col(A, p->col_num); - if (weight != 0 && weight[pcol1->col_num] > weight[pcol->col_num]) - continue; - if ((pcol1->length > pcol->length) || - (pcol1->length == pcol->length && - pcol1->col_num > pcol->col_num)) { - if (sm_col_contains(pcol, pcol1)) { - sm_delcol(A, pcol->col_num); - break; - } - } - } - } - - return colcnt - A->ncols; -} diff --git a/src/misc/espresso/equiv.c b/src/misc/espresso/equiv.c deleted file mode 100644 index ba898a70..00000000 --- a/src/misc/espresso/equiv.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - - -find_equiv_outputs(PLA) -pPLA PLA; -{ - int i, j, ipart, jpart, some_equiv; - pcover *R, *F; - - some_equiv = FALSE; - - makeup_labels(PLA); - - F = ALLOC(pcover, cube.part_size[cube.output]); - R = ALLOC(pcover, cube.part_size[cube.output]); - - for(i = 0; i < cube.part_size[cube.output]; i++) { - ipart = cube.first_part[cube.output] + i; - R[i] = cof_output(PLA->R, ipart); - F[i] = complement(cube1list(R[i])); - } - - for(i = 0; i < cube.part_size[cube.output]-1; i++) { - for(j = i+1; j < cube.part_size[cube.output]; j++) { - ipart = cube.first_part[cube.output] + i; - jpart = cube.first_part[cube.output] + j; - - if (check_equiv(F[i], F[j])) { - (void) printf("# Outputs %d and %d (%s and %s) are equivalent\n", - i, j, PLA->label[ipart], PLA->label[jpart]); - some_equiv = TRUE; - } else if (check_equiv(F[i], R[j])) { - (void) printf("# Outputs %d and NOT %d (%s and %s) are equivalent\n", - i, j, PLA->label[ipart], PLA->label[jpart]); - some_equiv = TRUE; - } else if (check_equiv(R[i], F[j])) { - (void) printf("# Outputs NOT %d and %d (%s and %s) are equivalent\n", - i, j, PLA->label[ipart], PLA->label[jpart]); - some_equiv = TRUE; - } else if (check_equiv(R[i], R[j])) { - (void) printf("# Outputs NOT %d and NOT %d (%s and %s) are equivalent\n", - i, j, PLA->label[ipart], PLA->label[jpart]); - some_equiv = TRUE; - } - } - } - - if (! some_equiv) { - (void) printf("# No outputs are equivalent\n"); - } - - for(i = 0; i < cube.part_size[cube.output]; i++) { - free_cover(F[i]); - free_cover(R[i]); - } - FREE(F); - FREE(R); -} - - - -int check_equiv(f1, f2) -pcover f1, f2; -{ - register pcube *f1list, *f2list; - register pcube p, last; - - f1list = cube1list(f1); - foreach_set(f2, last, p) { - if (! cube_is_covered(f1list, p)) { - return FALSE; - } - } - free_cubelist(f1list); - - f2list = cube1list(f2); - foreach_set(f1, last, p) { - if (! cube_is_covered(f2list, p)) { - return FALSE; - } - } - free_cubelist(f2list); - - return TRUE; -} diff --git a/src/misc/espresso/espresso.c b/src/misc/espresso/espresso.c deleted file mode 100644 index 8f05d43f..00000000 --- a/src/misc/espresso/espresso.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - * Module: espresso.c - * Purpose: The main espresso algorithm - * - * Returns a minimized version of the ON-set of a function - * - * The following global variables affect the operation of Espresso: - * - * MISCELLANEOUS: - * trace - * print trace information as the minimization progresses - * - * remove_essential - * remove essential primes - * - * single_expand - * if true, stop after first expand/irredundant - * - * LAST_GASP or SUPER_GASP strategy: - * use_super_gasp - * uses the super_gasp strategy rather than last_gasp - * - * SETUP strategy: - * recompute_onset - * recompute onset using the complement before starting - * - * unwrap_onset - * unwrap the function output part before first expand - * - * MAKE_SPARSE strategy: - * force_irredundant - * iterates make_sparse to force a minimal solution (used - * indirectly by make_sparse) - * - * skip_make_sparse - * skip the make_sparse step (used by opo only) - */ - -#include "espresso.h" - -pcover espresso(F, D1, R) -pcover F, D1, R; -{ - pcover E, D, Fsave; - pset last, p; - cost_t cost, best_cost; - -begin: - Fsave = sf_save(F); /* save original function */ - D = sf_save(D1); /* make a scratch copy of D */ - - /* Setup has always been a problem */ - if (recompute_onset) { - EXEC(E = simplify(cube1list(F)), "SIMPLIFY ", E); - free_cover(F); - F = E; - } - cover_cost(F, &cost); - if (unwrap_onset && (cube.part_size[cube.num_vars - 1] > 1) - && (cost.out != cost.cubes*cube.part_size[cube.num_vars-1]) - && (cost.out < 5000)) - EXEC(F = sf_contain(unravel(F, cube.num_vars - 1)), "SETUP ", F); - - /* Initial expand and irredundant */ - foreach_set(F, last, p) { - RESET(p, PRIME); - } - EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost); - EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost); - - if (! single_expand) { - if (remove_essential) { - EXECUTE(E = essential(&F, &D), ESSEN_TIME, E, cost); - } else { - E = new_cover(0); - } - - cover_cost(F, &cost); - do { - - /* Repeat inner loop until solution becomes "stable" */ - do { - copy_cost(&cost, &best_cost); - EXECUTE(F = reduce(F, D), REDUCE_TIME, F, cost); - EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost); - EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost); - } while (cost.cubes < best_cost.cubes); - - /* Perturb solution to see if we can continue to iterate */ - copy_cost(&cost, &best_cost); - if (use_super_gasp) { - F = super_gasp(F, D, R, &cost); - if (cost.cubes >= best_cost.cubes) - break; - } else { - F = last_gasp(F, D, R, &cost); - } - - } while (cost.cubes < best_cost.cubes || - (cost.cubes == best_cost.cubes && cost.total < best_cost.total)); - - /* Append the essential cubes to F */ - F = sf_append(F, E); /* disposes of E */ - if (trace) size_stamp(F, "ADJUST "); - } - - /* Free the D which we used */ - free_cover(D); - - /* Attempt to make the PLA matrix sparse */ - if (! skip_make_sparse) { - F = make_sparse(F, D1, R); - } - - /* - * Check to make sure function is actually smaller !! - * This can only happen because of the initial unravel. If we fail, - * then run the whole thing again without the unravel. - */ - if (Fsave->count < F->count) { - free_cover(F); - F = Fsave; - unwrap_onset = FALSE; - goto begin; - } else { - free_cover(Fsave); - } - - return F; -} diff --git a/src/misc/espresso/espresso.h b/src/misc/espresso/espresso.h deleted file mode 100644 index 1c7a8646..00000000 --- a/src/misc/espresso/espresso.h +++ /dev/null @@ -1,782 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - * espresso.h -- header file for Espresso-mv - */ - -//#include "port.h" -//#include "utility.h" -#include "sparse.h" -#include "mincov.h" - -#include "util_hack.h" // added - -#define ptime() util_cpu_time() -#define print_time(t) util_print_time(t) - -#ifdef IBM_WATC -#define void int -#include "short.h" -#endif - -#ifdef IBMPC /* set default options for IBM/PC */ -#define NO_INLINE -#define BPI 16 -#endif - -/*-----THIS USED TO BE set.h----- */ - -/* - * set.h -- definitions for packed arrays of bits - * - * This header file describes the data structures which comprise a - * facility for efficiently implementing packed arrays of bits - * (otherwise known as sets, cf. Pascal). - * - * A set is a vector of bits and is implemented here as an array of - * unsigned integers. The low order bits of set[0] give the index of - * the last word of set data. The higher order bits of set[0] are - * used to store data associated with the set. The set data is - * contained in elements set[1] ... set[LOOP(set)] as a packed bit - * array. - * - * A family of sets is a two-dimensional matrix of bits and is - * implemented with the data type "set_family". - * - * BPI == 32 and BPI == 16 have been tested and work. - */ - - -/* Define host machine characteristics of "unsigned int" */ -#ifndef BPI -#define BPI 32 /* # bits per integer */ -#endif - -#if BPI == 32 -#define LOGBPI 5 /* log(BPI)/log(2) */ -#else -#define LOGBPI 4 /* log(BPI)/log(2) */ -#endif - -/* Define the set type */ -typedef unsigned int *pset; - -/* Define the set family type -- an array of sets */ -typedef struct set_family { - int wsize; /* Size of each set in 'ints' */ - int sf_size; /* User declared set size */ - int capacity; /* Number of sets allocated */ - int count; /* The number of sets in the family */ - int active_count; /* Number of "active" sets */ - pset data; /* Pointer to the set data */ - struct set_family *next; /* For garbage collection */ -} set_family_t, *pset_family; - -/* Macros to set and test single elements */ -#define WHICH_WORD(element) (((element) >> LOGBPI) + 1) -#define WHICH_BIT(element) ((element) & (BPI-1)) - -/* # of ints needed to allocate a set with "size" elements */ -#if BPI == 32 -#define SET_SIZE(size) ((size) <= BPI ? 2 : (WHICH_WORD((size)-1) + 1)) -#else -#define SET_SIZE(size) ((size) <= BPI ? 3 : (WHICH_WORD((size)-1) + 2)) -#endif - -/* - * Three fields are maintained in the first word of the set - * LOOP is the index of the last word used for set data - * LOOPCOPY is the index of the last word in the set - * SIZE is available for general use (e.g., recording # elements in set) - * NELEM retrieves the number of elements in the set - */ -#define LOOP(set) (set[0] & 0x03ff) -#define PUTLOOP(set, i) (set[0] &= ~0x03ff, set[0] |= (i)) -#if BPI == 32 -#define LOOPCOPY(set) LOOP(set) -#define SIZE(set) (set[0] >> 16) -#define PUTSIZE(set, size) (set[0] &= 0xffff, set[0] |= ((size) << 16)) -#else -#define LOOPCOPY(set) (LOOP(set) + 1) -#define SIZE(set) (set[LOOP(set)+1]) -#define PUTSIZE(set, size) ((set[LOOP(set)+1]) = (size)) -#endif - -#define NELEM(set) (BPI * LOOP(set)) -#define LOOPINIT(size) ((size <= BPI) ? 1 : WHICH_WORD((size)-1)) - -/* - * FLAGS store general information about the set - */ -#define SET(set, flag) (set[0] |= (flag)) -#define RESET(set, flag) (set[0] &= ~ (flag)) -#define TESTP(set, flag) (set[0] & (flag)) - -/* Flag definitions are ... */ -#define PRIME 0x8000 /* cube is prime */ -#define NONESSEN 0x4000 /* cube cannot be essential prime */ -#define ACTIVE 0x2000 /* cube is still active */ -#define REDUND 0x1000 /* cube is redundant(at this point) */ -#define COVERED 0x0800 /* cube has been covered */ -#define RELESSEN 0x0400 /* cube is relatively essential */ - -/* Most efficient way to look at all members of a set family */ -#define foreach_set(R, last, p)\ - for(p=R->data,last=p+R->count*R->wsize;pwsize) -#define foreach_remaining_set(R, last, pfirst, p)\ - for(p=pfirst+R->wsize,last=R->data+R->count*R->wsize;pwsize) -#define foreach_active_set(R, last, p)\ - foreach_set(R,last,p) if (TESTP(p, ACTIVE)) - -/* Another way that also keeps the index of the current set member in i */ -#define foreachi_set(R, i, p)\ - for(p=R->data,i=0;icount;p+=R->wsize,i++) -#define foreachi_active_set(R, i, p)\ - foreachi_set(R,i,p) if (TESTP(p, ACTIVE)) - -/* Looping over all elements in a set: - * foreach_set_element(pset p, int i, unsigned val, int base) { - * . - * . - * . - * } - */ -#define foreach_set_element(p, i, val, base) \ - for(i = LOOP(p); i > 0; ) \ - for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) \ - if (val & 1) - -/* Return a pointer to a given member of a set family */ -#define GETSET(family, index) ((family)->data + (family)->wsize * (index)) - -/* Allocate and deallocate sets */ -#define set_new(size) set_clear(ALLOC(unsigned int, SET_SIZE(size)), size) -#define set_full(size) set_fill(ALLOC(unsigned int, SET_SIZE(size)), size) -#define set_save(r) set_copy(ALLOC(unsigned int, SET_SIZE(NELEM(r))), r) -#define set_free(r) FREE(r) - -/* Check for set membership, remove set element and insert set element */ -#define is_in_set(set, e) (set[WHICH_WORD(e)] & (1 << WHICH_BIT(e))) -#define set_remove(set, e) (set[WHICH_WORD(e)] &= ~ (1 << WHICH_BIT(e))) -#define set_insert(set, e) (set[WHICH_WORD(e)] |= 1 << WHICH_BIT(e)) - -/* Inline code substitution for those places that REALLY need it on a VAX */ -#ifdef NO_INLINE -#define INLINEset_copy(r, a) (void) set_copy(r,a) -#define INLINEset_clear(r, size) (void) set_clear(r, size) -#define INLINEset_fill(r, size) (void) set_fill(r, size) -#define INLINEset_and(r, a, b) (void) set_and(r, a, b) -#define INLINEset_or(r, a, b) (void) set_or(r, a, b) -#define INLINEset_diff(r, a, b) (void) set_diff(r, a, b) -#define INLINEset_ndiff(r, a, b, f) (void) set_ndiff(r, a, b, f) -#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b) -#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f) -#define INLINEset_merge(r, a, b, mask) (void) set_merge(r, a, b, mask) -#define INLINEsetp_implies(a, b, when_false) \ - if (! setp_implies(a,b)) when_false -#define INLINEsetp_disjoint(a, b, when_false) \ - if (! setp_disjoint(a,b)) when_false -#define INLINEsetp_equal(a, b, when_false) \ - if (! setp_equal(a,b)) when_false - -#else - -#define INLINEset_copy(r, a)\ - {register int i_=LOOPCOPY(a); do r[i_]=a[i_]; while (--i_>=0);} -#define INLINEset_clear(r, size)\ - {register int i_=LOOPINIT(size); *r=i_; do r[i_] = 0; while (--i_ > 0);} -#define INLINEset_fill(r, size)\ - {register int i_=LOOPINIT(size); *r=i_; \ - r[i_]=((unsigned int)(~0))>>(i_*BPI-size); while(--i_>0) r[i_]=~0;} -#define INLINEset_and(r, a, b)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = a[i_] & b[i_]; while (--i_>0);} -#define INLINEset_or(r, a, b)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = a[i_] | b[i_]; while (--i_>0);} -#define INLINEset_diff(r, a, b)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = a[i_] & ~ b[i_]; while (--i_>0);} -#define INLINEset_ndiff(r, a, b, fullset)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = fullset[i_] & (a[i_] | ~ b[i_]); while (--i_>0);} -#ifdef IBM_WATC -#define INLINEset_xor(r, a, b) (void) set_xor(r, a, b) -#define INLINEset_xnor(r, a, b, f) (void) set_xnor(r, a, b, f) -#else -#define INLINEset_xor(r, a, b)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = a[i_] ^ b[i_]; while (--i_>0);} -#define INLINEset_xnor(r, a, b, fullset)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = fullset[i_] & ~ (a[i_] ^ b[i_]); while (--i_>0);} -#endif -#define INLINEset_merge(r, a, b, mask)\ - {register int i_=LOOP(a); PUTLOOP(r,i_);\ - do r[i_] = (a[i_]&mask[i_]) | (b[i_]&~mask[i_]); while (--i_>0);} -#define INLINEsetp_implies(a, b, when_false)\ - {register int i_=LOOP(a); do if (a[i_]&~b[i_]) break; while (--i_>0);\ - if (i_ != 0) when_false;} -#define INLINEsetp_disjoint(a, b, when_false)\ - {register int i_=LOOP(a); do if (a[i_]&b[i_]) break; while (--i_>0);\ - if (i_ != 0) when_false;} -#define INLINEsetp_equal(a, b, when_false)\ - {register int i_=LOOP(a); do if (a[i_]!=b[i_]) break; while (--i_>0);\ - if (i_ != 0) when_false;} - -#endif - -#if BPI == 32 -#define count_ones(v)\ - (bit_count[v & 255] + bit_count[(v >> 8) & 255]\ - + bit_count[(v >> 16) & 255] + bit_count[(v >> 24) & 255]) -#else -#define count_ones(v) (bit_count[v & 255] + bit_count[(v >> 8) & 255]) -#endif - -/* Table for efficient bit counting */ -extern int bit_count[256]; -/*----- END OF set.h ----- */ - - -/* Define a boolean type */ -#define bool int -#define FALSE 0 -#define TRUE 1 -#define MAYBE 2 -#define print_bool(x) ((x) == 0 ? "FALSE" : ((x) == 1 ? "TRUE" : "MAYBE")) - -/* Map many cube/cover types/routines into equivalent set types/routines */ -#define pcube pset -#define new_cube() set_new(cube.size) -#define free_cube(r) set_free(r) -#define pcover pset_family -#define new_cover(i) sf_new(i, cube.size) -#define free_cover(r) sf_free(r) -#define free_cubelist(T) FREE(T[0]); FREE(T); - - -/* cost_t describes the cost of a cover */ -typedef struct cost_struct { - int cubes; /* number of cubes in the cover */ - int in; /* transistor count, binary-valued variables */ - int out; /* transistor count, output part */ - int mv; /* transistor count, multiple-valued vars */ - int total; /* total number of transistors */ - int primes; /* number of prime cubes */ -} cost_t, *pcost; - - -/* pair_t describes bit-paired variables */ -typedef struct pair_struct { - int cnt; - int *var1; - int *var2; -} pair_t, *ppair; - - -/* symbolic_list_t describes a single ".symbolic" line */ -typedef struct symbolic_list_struct { - int variable; - int pos; - struct symbolic_list_struct *next; -} symbolic_list_t; - - -/* symbolic_list_t describes a single ".symbolic" line */ -typedef struct symbolic_label_struct { - char *label; - struct symbolic_label_struct *next; -} symbolic_label_t; - - -/* symbolic_t describes a linked list of ".symbolic" lines */ -typedef struct symbolic_struct { - symbolic_list_t *symbolic_list; /* linked list of items */ - int symbolic_list_length; /* length of symbolic_list list */ - symbolic_label_t *symbolic_label; /* linked list of new names */ - int symbolic_label_length; /* length of symbolic_label list */ - struct symbolic_struct *next; -} symbolic_t; - - -/* PLA_t stores the logical representation of a PLA */ -typedef struct { - pcover F, D, R; /* on-set, off-set and dc-set */ - char *filename; /* filename */ - int pla_type; /* logical PLA format */ - pcube phase; /* phase to split into on-set and off-set */ - ppair pair; /* how to pair variables */ - char **label; /* labels for the columns */ - symbolic_t *symbolic; /* allow binary->symbolic mapping */ - symbolic_t *symbolic_output;/* allow symbolic output mapping */ -} PLA_t, *pPLA; - -#define equal(a,b) (strcmp(a,b) == 0) - -/* This is a hack which I wish I hadn't done, but too painful to change */ -#define CUBELISTSIZE(T) (((pcube *) T[1] - T) - 3) - -/* For documentation purposes */ -#define IN -#define OUT -#define INOUT - -/* The pla_type field describes the input and output format of the PLA */ -#define F_type 1 -#define D_type 2 -#define R_type 4 -#define PLEASURE_type 8 /* output format */ -#define EQNTOTT_type 16 /* output format algebraic eqns */ -#define KISS_type 128 /* output format kiss */ -#define CONSTRAINTS_type 256 /* output the constraints (numeric) */ -#define SYMBOLIC_CONSTRAINTS_type 512 /* output the constraints (symbolic) */ -#define FD_type (F_type | D_type) -#define FR_type (F_type | R_type) -#define DR_type (D_type | R_type) -#define FDR_type (F_type | D_type | R_type) - -/* Definitions for the debug variable */ -#define COMPL 0x0001 -#define ESSEN 0x0002 -#define EXPAND 0x0004 -#define EXPAND1 0x0008 -#define GASP 0x0010 -#define IRRED 0x0020 -#define REDUCE 0x0040 -#define REDUCE1 0x0080 -#define SPARSE 0x0100 -#define TAUT 0x0200 -#define EXACT 0x0400 -#define MINCOV 0x0800 -#define MINCOV1 0x1000 -#define SHARP 0x2000 -#define IRRED1 0x4000 - -#define VERSION\ - "UC Berkeley, Espresso Version #2.3, Release date 01/31/88" - -/* Define constants used for recording program statistics */ -#define TIME_COUNT 16 -#define READ_TIME 0 -#define COMPL_TIME 1 -#define ONSET_TIME 2 -#define ESSEN_TIME 3 -#define EXPAND_TIME 4 -#define IRRED_TIME 5 -#define REDUCE_TIME 6 -#define GEXPAND_TIME 7 -#define GIRRED_TIME 8 -#define GREDUCE_TIME 9 -#define PRIMES_TIME 10 -#define MINCOV_TIME 11 -#define MV_REDUCE_TIME 12 -#define RAISE_IN_TIME 13 -#define VERIFY_TIME 14 -#define WRITE_TIME 15 - - -/* For those who like to think about PLAs, macros to get at inputs/outputs */ -#define NUMINPUTS cube.num_binary_vars -#define NUMOUTPUTS cube.part_size[cube.num_vars - 1] - -#define POSITIVE_PHASE(pos)\ - (is_in_set(PLA->phase, cube.first_part[cube.output]+pos) != 0) - -#define INLABEL(var) PLA->label[cube.first_part[var] + 1] -#define OUTLABEL(pos) PLA->label[cube.first_part[cube.output] + pos] - -#define GETINPUT(c, pos)\ - ((c[WHICH_WORD(2*pos)] >> WHICH_BIT(2*pos)) & 3) -#define GETOUTPUT(c, pos)\ - (is_in_set(c, cube.first_part[cube.output] + pos) != 0) - -#define PUTINPUT(c, pos, value)\ - c[WHICH_WORD(2*pos)] = (c[WHICH_WORD(2*pos)] & ~(3 << WHICH_BIT(2*pos)))\ - | (value << WHICH_BIT(2*pos)) -#define PUTOUTPUT(c, pos, value)\ - c[WHICH_WORD(pos)] = (c[WHICH_WORD(pos)] & ~(1 << WHICH_BIT(pos)))\ - | (value << WHICH_BIT(pos)) - -#define TWO 3 -#define DASH 3 -#define ONE 2 -#define ZERO 1 - - -#define EXEC(fct, name, S)\ - {long t=ptime();fct;if(trace)print_trace(S,name,ptime()-t);} -#define EXEC_S(fct, name, S)\ - {long t=ptime();fct;if(summary)print_trace(S,name,ptime()-t);} -#define EXECUTE(fct,i,S,cost)\ - {long t=ptime();fct;totals(t,i,S,&(cost));} - -/* - * Global Variable Declarations - */ - -extern unsigned int debug; /* debug parameter */ -extern bool verbose_debug; /* -v: whether to print a lot */ -extern char *total_name[TIME_COUNT]; /* basic function names */ -extern long total_time[TIME_COUNT]; /* time spent in basic fcts */ -extern int total_calls[TIME_COUNT]; /* # calls to each fct */ - -extern bool echo_comments; /* turned off by -eat option */ -extern bool echo_unknown_commands; /* always true ?? */ -extern bool force_irredundant; /* -nirr command line option */ -extern bool skip_make_sparse; -extern bool kiss; /* -kiss command line option */ -extern bool pos; /* -pos command line option */ -extern bool print_solution; /* -x command line option */ -extern bool recompute_onset; /* -onset command line option */ -extern bool remove_essential; /* -ness command line option */ -extern bool single_expand; /* -fast command line option */ -extern bool summary; /* -s command line option */ -extern bool trace; /* -t command line option */ -extern bool unwrap_onset; /* -nunwrap command line option */ -extern bool use_random_order; /* -random command line option */ -extern bool use_super_gasp; /* -strong command line option */ -extern char *filename; /* filename PLA was read from */ -extern bool debug_exact_minimization; /* dumps info for -do exact */ - - -/* - * pla_types are the input and output types for reading/writing a PLA - */ -struct pla_types_struct { - char *key; - int value; -}; - - -/* - * The cube structure is a global structure which contains information - * on how a set maps into a cube -- i.e., number of parts per variable, - * number of variables, etc. Also, many fields are pre-computed to - * speed up various primitive operations. - */ -#define CUBE_TEMP 10 - -struct cube_struct { - int size; /* set size of a cube */ - int num_vars; /* number of variables in a cube */ - int num_binary_vars; /* number of binary variables */ - int *first_part; /* first element of each variable */ - int *last_part; /* first element of each variable */ - int *part_size; /* number of elements in each variable */ - int *first_word; /* first word for each variable */ - int *last_word; /* last word for each variable */ - pset binary_mask; /* Mask to extract binary variables */ - pset mv_mask; /* mask to get mv parts */ - pset *var_mask; /* mask to extract a variable */ - pset *temp; /* an array of temporary sets */ - pset fullset; /* a full cube */ - pset emptyset; /* an empty cube */ - unsigned int inmask; /* mask to get odd word of binary part */ - int inword; /* which word number for above */ - int *sparse; /* should this variable be sparse? */ - int num_mv_vars; /* number of multiple-valued variables */ - int output; /* which variable is "output" (-1 if none) */ -}; - -struct cdata_struct { - int *part_zeros; /* count of zeros for each element */ - int *var_zeros; /* count of zeros for each variable */ - int *parts_active; /* number of "active" parts for each var */ - bool *is_unate; /* indicates given var is unate */ - int vars_active; /* number of "active" variables */ - int vars_unate; /* number of unate variables */ - int best; /* best "binate" variable */ -}; - - -extern struct pla_types_struct pla_types[]; -extern struct cube_struct cube, temp_cube_save; -extern struct cdata_struct cdata, temp_cdata_save; - -#ifdef lint -#define DISJOINT 0x5555 -#else -#if BPI == 32 -#define DISJOINT 0x55555555 -#else -#define DISJOINT 0x5555 -#endif -#endif - -/* function declarations */ - -/* cofactor.c */ extern int binate_split_select(); -/* cofactor.c */ extern pcover cubeunlist(); -/* cofactor.c */ extern pcube *cofactor(); -/* cofactor.c */ extern pcube *cube1list(); -/* cofactor.c */ extern pcube *cube2list(); -/* cofactor.c */ extern pcube *cube3list(); -/* cofactor.c */ extern pcube *scofactor(); -/* cofactor.c */ extern void massive_count(); -/* compl.c */ extern pcover complement(); -/* compl.c */ extern pcover simplify(); -/* compl.c */ extern void simp_comp(); -/* contain.c */ extern int d1_rm_equal(); -/* contain.c */ extern int rm2_contain(); -/* contain.c */ extern int rm2_equal(); -/* contain.c */ extern int rm_contain(); -/* contain.c */ extern int rm_equal(); -/* contain.c */ extern int rm_rev_contain(); -/* contain.c */ extern pset *sf_list(); -/* contain.c */ extern pset *sf_sort(); -/* contain.c */ extern pset_family d1merge(); -/* contain.c */ extern pset_family dist_merge(); -/* contain.c */ extern pset_family sf_contain(); -/* contain.c */ extern pset_family sf_dupl(); -/* contain.c */ extern pset_family sf_ind_contain(); -/* contain.c */ extern pset_family sf_ind_unlist(); -/* contain.c */ extern pset_family sf_merge(); -/* contain.c */ extern pset_family sf_rev_contain(); -/* contain.c */ extern pset_family sf_union(); -/* contain.c */ extern pset_family sf_unlist(); -/* cubestr.c */ extern void cube_setup(); -/* cubestr.c */ extern void restore_cube_struct(); -/* cubestr.c */ extern void save_cube_struct(); -/* cubestr.c */ extern void setdown_cube(); -/* cvrin.c */ extern PLA_labels(); -/* cvrin.c */ extern char *get_word(); -/* cvrin.c */ extern int label_index(); -/* cvrin.c */ extern int read_pla(); -/* cvrin.c */ extern int read_symbolic(); -/* cvrin.c */ extern pPLA new_PLA(); -/* cvrin.c */ extern void PLA_summary(); -/* cvrin.c */ extern void free_PLA(); -/* cvrin.c */ extern void parse_pla(); -/* cvrin.c */ extern void read_cube(); -/* cvrin.c */ extern void skip_line(); -/* cvrm.c */ extern foreach_output_function(); -/* cvrm.c */ extern int cubelist_partition(); -/* cvrm.c */ extern int so_both_do_espresso(); -/* cvrm.c */ extern int so_both_do_exact(); -/* cvrm.c */ extern int so_both_save(); -/* cvrm.c */ extern int so_do_espresso(); -/* cvrm.c */ extern int so_do_exact(); -/* cvrm.c */ extern int so_save(); -/* cvrm.c */ extern pcover cof_output(); -/* cvrm.c */ extern pcover lex_sort(); -/* cvrm.c */ extern pcover mini_sort(); -/* cvrm.c */ extern pcover random_order(); -/* cvrm.c */ extern pcover size_sort(); -/* cvrm.c */ extern pcover sort_reduce(); -/* cvrm.c */ extern pcover uncof_output(); -/* cvrm.c */ extern pcover unravel(); -/* cvrm.c */ extern pcover unravel_range(); -/* cvrm.c */ extern void so_both_espresso(); -/* cvrm.c */ extern void so_espresso(); -/* cvrmisc.c */ extern char *fmt_cost(); -/* cvrmisc.c */ extern char *print_cost(); -/* cvrmisc.c */ extern char *strsav(); -/* cvrmisc.c */ extern void copy_cost(); -/* cvrmisc.c */ extern void cover_cost(); -/* cvrmisc.c */ extern void fatal(); -/* cvrmisc.c */ extern void print_trace(); -/* cvrmisc.c */ extern void size_stamp(); -/* cvrmisc.c */ extern void totals(); -/* cvrout.c */ extern char *fmt_cube(); -/* cvrout.c */ extern char *fmt_expanded_cube(); -/* cvrout.c */ extern char *pc1(); -/* cvrout.c */ extern char *pc2(); -/* cvrout.c */ extern char *pc3(); -/* cvrout.c */ extern int makeup_labels(); -/* cvrout.c */ extern kiss_output(); -/* cvrout.c */ extern kiss_print_cube(); -/* cvrout.c */ extern output_symbolic_constraints(); -/* cvrout.c */ extern void cprint(); -/* cvrout.c */ extern void debug1_print(); -/* cvrout.c */ extern void debug_print(); -/* cvrout.c */ extern void eqn_output(); -/* cvrout.c */ extern void fpr_header(); -/* cvrout.c */ extern void fprint_pla(); -/* cvrout.c */ extern void pls_group(); -/* cvrout.c */ extern void pls_label(); -/* cvrout.c */ extern void pls_output(); -/* cvrout.c */ extern void print_cube(); -/* cvrout.c */ extern void print_expanded_cube(); -/* cvrout.c */ extern void sf_debug_print(); -/* equiv.c */ extern find_equiv_outputs(); -/* equiv.c */ extern int check_equiv(); -/* espresso.c */ extern pcover espresso(); -/* essen.c */ extern bool essen_cube(); -/* essen.c */ extern pcover cb_consensus(); -/* essen.c */ extern pcover cb_consensus_dist0(); -/* essen.c */ extern pcover essential(); -/* exact.c */ extern pcover minimize_exact(); -/* exact.c */ extern pcover minimize_exact_literals(); -/* expand.c */ extern bool feasibly_covered(); -/* expand.c */ extern int most_frequent(); -/* expand.c */ extern pcover all_primes(); -/* expand.c */ extern pcover expand(); -/* expand.c */ extern pcover find_all_primes(); -/* expand.c */ extern void elim_lowering(); -/* expand.c */ extern void essen_parts(); -/* expand.c */ extern void essen_raising(); -/* expand.c */ extern void expand1(); -/* expand.c */ extern void mincov(); -/* expand.c */ extern void select_feasible(); -/* expand.c */ extern void setup_BB_CC(); -/* gasp.c */ extern pcover expand_gasp(); -/* gasp.c */ extern pcover irred_gasp(); -/* gasp.c */ extern pcover last_gasp(); -/* gasp.c */ extern pcover super_gasp(); -/* gasp.c */ extern void expand1_gasp(); -/* getopt.c */ extern int util_getopt(); -/* hack.c */ extern find_dc_inputs(); -/* hack.c */ extern find_inputs(); -/* hack.c */ extern form_bitvector(); -/* hack.c */ extern map_dcset(); -/* hack.c */ extern map_output_symbolic(); -/* hack.c */ extern map_symbolic(); -/* hack.c */ extern pcover map_symbolic_cover(); -/* hack.c */ extern symbolic_hack_labels(); -/* irred.c */ extern bool cube_is_covered(); -/* irred.c */ extern bool taut_special_cases(); -/* irred.c */ extern bool tautology(); -/* irred.c */ extern pcover irredundant(); -/* irred.c */ extern void mark_irredundant(); -/* irred.c */ extern void irred_split_cover(); -/* irred.c */ extern sm_matrix *irred_derive_table(); -/* map.c */ extern pset minterms(); -/* map.c */ extern void explode(); -/* map.c */ extern void map(); -/* opo.c */ extern output_phase_setup(); -/* opo.c */ extern pPLA set_phase(); -/* opo.c */ extern pcover opo(); -/* opo.c */ extern pcube find_phase(); -/* opo.c */ extern pset_family find_covers(); -/* opo.c */ extern pset_family form_cover_table(); -/* opo.c */ extern pset_family opo_leaf(); -/* opo.c */ extern pset_family opo_recur(); -/* opo.c */ extern void opoall(); -/* opo.c */ extern void phase_assignment(); -/* opo.c */ extern void repeated_phase_assignment(); -/* pair.c */ extern generate_all_pairs(); -/* pair.c */ extern int **find_pairing_cost(); -/* pair.c */ extern int find_best_cost(); -/* pair.c */ extern int greedy_best_cost(); -/* pair.c */ extern int minimize_pair(); -/* pair.c */ extern int pair_free(); -/* pair.c */ extern pair_all(); -/* pair.c */ extern pcover delvar(); -/* pair.c */ extern pcover pairvar(); -/* pair.c */ extern ppair pair_best_cost(); -/* pair.c */ extern ppair pair_new(); -/* pair.c */ extern ppair pair_save(); -/* pair.c */ extern print_pair(); -/* pair.c */ extern void find_optimal_pairing(); -/* pair.c */ extern void set_pair(); -/* pair.c */ extern void set_pair1(); -/* primes.c */ extern pcover primes_consensus(); -/* reduce.c */ extern bool sccc_special_cases(); -/* reduce.c */ extern pcover reduce(); -/* reduce.c */ extern pcube reduce_cube(); -/* reduce.c */ extern pcube sccc(); -/* reduce.c */ extern pcube sccc_cube(); -/* reduce.c */ extern pcube sccc_merge(); -/* set.c */ extern bool set_andp(); -/* set.c */ extern bool set_orp(); -/* set.c */ extern bool setp_disjoint(); -/* set.c */ extern bool setp_empty(); -/* set.c */ extern bool setp_equal(); -/* set.c */ extern bool setp_full(); -/* set.c */ extern bool setp_implies(); -/* set.c */ extern char *pbv1(); -/* set.c */ extern char *ps1(); -/* set.c */ extern int *sf_count(); -/* set.c */ extern int *sf_count_restricted(); -/* set.c */ extern int bit_index(); -/* set.c */ extern int set_dist(); -/* set.c */ extern int set_ord(); -/* set.c */ extern void set_adjcnt(); -/* set.c */ extern pset set_and(); -/* set.c */ extern pset set_clear(); -/* set.c */ extern pset set_copy(); -/* set.c */ extern pset set_diff(); -/* set.c */ extern pset set_fill(); -/* set.c */ extern pset set_merge(); -/* set.c */ extern pset set_or(); -/* set.c */ extern pset set_xor(); -/* set.c */ extern pset sf_and(); -/* set.c */ extern pset sf_or(); -/* set.c */ extern pset_family sf_active(); -/* set.c */ extern pset_family sf_addcol(); -/* set.c */ extern pset_family sf_addset(); -/* set.c */ extern pset_family sf_append(); -/* set.c */ extern pset_family sf_bm_read(); -/* set.c */ extern pset_family sf_compress(); -/* set.c */ extern pset_family sf_copy(); -/* set.c */ extern pset_family sf_copy_col(); -/* set.c */ extern pset_family sf_delc(); -/* set.c */ extern pset_family sf_delcol(); -/* set.c */ extern pset_family sf_inactive(); -/* set.c */ extern pset_family sf_join(); -/* set.c */ extern pset_family sf_new(); -/* set.c */ extern pset_family sf_permute(); -/* set.c */ extern pset_family sf_read(); -/* set.c */ extern pset_family sf_save(); -/* set.c */ extern pset_family sf_transpose(); -/* set.c */ extern void set_write(); -/* set.c */ extern void sf_bm_print(); -/* set.c */ extern void sf_cleanup(); -/* set.c */ extern void sf_delset(); -/* set.c */ extern void sf_free(); -/* set.c */ extern void sf_print(); -/* set.c */ extern void sf_write(); -/* setc.c */ extern bool ccommon(); -/* setc.c */ extern bool cdist0(); -/* setc.c */ extern bool full_row(); -/* setc.c */ extern int ascend(); -/* setc.c */ extern int cactive(); -/* setc.c */ extern int cdist(); -/* setc.c */ extern int cdist01(); -/* setc.c */ extern int cvolume(); -/* setc.c */ extern int d1_order(); -/* setc.c */ extern int d1_order_size(); -/* setc.c */ extern int desc1(); -/* setc.c */ extern int descend(); -/* setc.c */ extern int lex_order(); -/* setc.c */ extern int lex_order1(); -/* setc.c */ extern pset force_lower(); -/* setc.c */ extern void consensus(); -/* sharp.c */ extern pcover cb1_dsharp(); -/* sharp.c */ extern pcover cb_dsharp(); -/* sharp.c */ extern pcover cb_recur_dsharp(); -/* sharp.c */ extern pcover cb_recur_sharp(); -/* sharp.c */ extern pcover cb_sharp(); -/* sharp.c */ extern pcover cv_dsharp(); -/* sharp.c */ extern pcover cv_intersect(); -/* sharp.c */ extern pcover cv_sharp(); -/* sharp.c */ extern pcover dsharp(); -/* sharp.c */ extern pcover make_disjoint(); -/* sharp.c */ extern pcover sharp(); -/* sminterf.c */pset do_sm_minimum_cover(); -/* sparse.c */ extern pcover make_sparse(); -/* sparse.c */ extern pcover mv_reduce(); -#if !defined(__osf__) && !defined(__STDC__) && !defined(__hpux) -/* ucbqsort.c */ extern qsort(); -#endif -/* ucbqsort.c */ extern qst(); -/* unate.c */ extern pcover find_all_minimal_covers_petrick(); -/* unate.c */ extern pcover map_cover_to_unate(); -/* unate.c */ extern pcover map_unate_to_cover(); -/* unate.c */ extern pset_family exact_minimum_cover(); -/* unate.c */ extern pset_family gen_primes(); -/* unate.c */ extern pset_family unate_compl(); -/* unate.c */ extern pset_family unate_complement(); -/* unate.c */ extern pset_family unate_intersect(); -/* verify.c */ extern PLA_permute(); -/* verify.c */ extern bool PLA_verify(); -/* verify.c */ extern bool check_consistency(); -/* verify.c */ extern bool verify(); diff --git a/src/misc/espresso/essen.c b/src/misc/espresso/essen.c deleted file mode 100644 index 6a46295d..00000000 --- a/src/misc/espresso/essen.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - module: essen.c - purpose: Find essential primes in a multiple-valued function -*/ - -#include "espresso.h" - -/* - essential -- return a cover consisting of the cubes of F which are - essential prime implicants (with respect to F u D); Further, remove - these cubes from the ON-set F, and add them to the OFF-set D. - - Sometimes EXPAND can determine that a cube is not an essential prime. - If so, it will set the "NONESSEN" flag in the cube. - - We count on IRREDUNDANT to have set the flag RELESSEN to indicate - that a prime was relatively essential (i.e., covers some minterm - not contained in any other prime in the current cover), or to have - reset the flag to indicate that a prime was relatively redundant - (i.e., all minterms covered by other primes in the current cover). - Of course, after executing irredundant, all of the primes in the - cover are relatively essential, but we can mark the primes which - were redundant at the start of irredundant and avoid an extra check - on these primes for essentiality. -*/ - -pcover essential(Fp, Dp) -IN pcover *Fp, *Dp; -{ - register pcube last, p; - pcover E, F = *Fp, D = *Dp; - - /* set all cubes in F active */ - (void) sf_active(F); - - /* Might as well start out with some cubes in E */ - E = new_cover(10); - - foreach_set(F, last, p) { - /* don't test a prime which EXPAND says is nonessential */ - if (! TESTP(p, NONESSEN)) { - /* only test a prime which was relatively essential */ - if (TESTP(p, RELESSEN)) { - /* Check essentiality */ - if (essen_cube(F, D, p)) { - if (debug & ESSEN) - printf("ESSENTIAL: %s\n", pc1(p)); - E = sf_addset(E, p); - RESET(p, ACTIVE); - F->active_count--; - } - } - } - } - - *Fp = sf_inactive(F); /* delete the inactive cubes from F */ - *Dp = sf_join(D, E); /* add the essentials to D */ - sf_free(D); - return E; -} - -/* - essen_cube -- check if a single cube is essential or not - - The prime c is essential iff - - consensus((F u D) # c, c) u D - - does not contain c. -*/ -bool essen_cube(F, D, c) -IN pcover F, D; -IN pcube c; -{ - pcover H, FD; - pcube *H1; - bool essen; - - /* Append F and D together, and take the sharp-consensus with c */ - FD = sf_join(F, D); - H = cb_consensus(FD, c); - free_cover(FD); - - /* Add the don't care set, and see if this covers c */ - H1 = cube2list(H, D); - essen = ! cube_is_covered(H1, c); - free_cubelist(H1); - - free_cover(H); - return essen; -} - - -/* - * cb_consensus -- compute consensus(T # c, c) - */ -pcover cb_consensus(T, c) -register pcover T; -register pcube c; -{ - register pcube temp, last, p; - register pcover R; - - R = new_cover(T->count*2); - temp = new_cube(); - foreach_set(T, last, p) { - if (p != c) { - switch (cdist01(p, c)) { - case 0: - /* distance-0 needs special care */ - R = cb_consensus_dist0(R, p, c); - break; - - case 1: - /* distance-1 is easy because no sharping required */ - consensus(temp, p, c); - R = sf_addset(R, temp); - break; - } - } - } - set_free(temp); - return R; -} - - -/* - * form the sharp-consensus for p and c when they intersect - * What we are forming is consensus(p # c, c). - */ -pcover cb_consensus_dist0(R, p, c) -pcover R; -register pcube p, c; -{ - int var; - bool got_one; - register pcube temp, mask; - register pcube p_diff_c=cube.temp[0], p_and_c=cube.temp[1]; - - /* If c contains p, then this gives us no information for essential test */ - if (setp_implies(p, c)) { - return R; - } - - /* For the multiple-valued variables */ - temp = new_cube(); - got_one = FALSE; - INLINEset_diff(p_diff_c, p, c); - INLINEset_and(p_and_c, p, c); - - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - /* Check if c(var) is contained in p(var) -- if so, no news */ - mask = cube.var_mask[var]; - if (! setp_disjoint(p_diff_c, mask)) { - INLINEset_merge(temp, c, p_and_c, mask); - R = sf_addset(R, temp); - got_one = TRUE; - } - } - - /* if no cube so far, add one for the intersection */ - if (! got_one && cube.num_binary_vars > 0) { - /* Add a single cube for the intersection of p and c */ - INLINEset_and(temp, p, c); - R = sf_addset(R, temp); - } - - set_free(temp); - return R; -} diff --git a/src/misc/espresso/exact.c b/src/misc/espresso/exact.c deleted file mode 100644 index b1943636..00000000 --- a/src/misc/espresso/exact.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - - -static void dump_irredundant(); -static pcover do_minimize(); - - -/* - * minimize_exact -- main entry point for exact minimization - * - * Global flags which affect this routine are: - * - * debug - * skip_make_sparse - */ - -pcover -minimize_exact(F, D, R, exact_cover) -pcover F, D, R; -int exact_cover; -{ - return do_minimize(F, D, R, exact_cover, /*weighted*/ 0); -} - - -pcover -minimize_exact_literals(F, D, R, exact_cover) -pcover F, D, R; -int exact_cover; -{ - return do_minimize(F, D, R, exact_cover, /*weighted*/ 1); -} - - - -static pcover -do_minimize(F, D, R, exact_cover, weighted) -pcover F, D, R; -int exact_cover; -int weighted; -{ - pcover newF, E, Rt, Rp; - pset p, last; - int heur, level, *weights, i; - sm_matrix *table; - sm_row *cover; - sm_element *pe; - int debug_save = debug; - - if (debug & EXACT) { - debug |= (IRRED | MINCOV); - } -#if defined(sun) || defined(bsd4_2) /* hack ... */ - if (debug & MINCOV) { - setlinebuf(stdout); - } -#endif - level = (debug & MINCOV) ? 4 : 0; - heur = ! exact_cover; - - /* Generate all prime implicants */ - EXEC(F = primes_consensus(cube2list(F, D)), "PRIMES ", F); - - /* Setup the prime implicant table */ - EXEC(irred_split_cover(F, D, &E, &Rt, &Rp), "ESSENTIALS ", E); - EXEC(table = irred_derive_table(D, E, Rp), "PI-TABLE ", Rp); - - /* Solve either a weighted or nonweighted covering problem */ - if (weighted) { - /* correct only for all 2-valued variables */ - weights = ALLOC(int, F->count); - foreach_set(Rp, last, p) { - weights[SIZE(p)] = cube.size - set_ord(p); - /* We have added the 0's in the output part instead of the 1's. - This loop corrects the literal count. */ - for (i = cube.first_part[cube.output]; - i <= cube.last_part[cube.output]; i++) { - is_in_set(p, i) ? weights[SIZE(p)]++ : weights[SIZE(p)]--; - } - } - } else { - weights = NIL(int); - } - EXEC(cover=sm_minimum_cover(table,weights,heur,level), "MINCOV ", F); - if (weights != 0) { - FREE(weights); - } - - if (debug & EXACT) { - dump_irredundant(E, Rt, Rp, table); - } - - /* Form the result cover */ - newF = new_cover(100); - foreach_set(E, last, p) { - newF = sf_addset(newF, p); - } - sm_foreach_row_element(cover, pe) { - newF = sf_addset(newF, GETSET(F, pe->col_num)); - } - - free_cover(E); - free_cover(Rt); - free_cover(Rp); - sm_free(table); - sm_row_free(cover); - free_cover(F); - - /* Attempt to make the results more sparse */ - debug &= ~ (IRRED | SHARP | MINCOV); - if (! skip_make_sparse && R != 0) { - newF = make_sparse(newF, D, R); - } - - debug = debug_save; - return newF; -} - -static void -dump_irredundant(E, Rt, Rp, table) -pcover E, Rt, Rp; -sm_matrix *table; -{ - FILE *fp_pi_table, *fp_primes; - pPLA PLA; - pset last, p; - char *file; - - if (filename == 0 || strcmp(filename, "(stdin)") == 0) { - fp_pi_table = fp_primes = stdout; - } else { - file = ALLOC(char, strlen(filename)+20); - (void) sprintf(file, "%s.primes", filename); - if ((fp_primes = fopen(file, "w")) == NULL) { - (void) fprintf(stderr, "espresso: Unable to open %s\n", file); - fp_primes = stdout; - } - (void) sprintf(file, "%s.pi", filename); - if ((fp_pi_table = fopen(file, "w")) == NULL) { - (void) fprintf(stderr, "espresso: Unable to open %s\n", file); - fp_pi_table = stdout; - } - FREE(file); - } - - PLA = new_PLA(); - PLA_labels(PLA); - - fpr_header(fp_primes, PLA, F_type); - free_PLA(PLA); - - (void) fprintf(fp_primes, "# Essential primes are\n"); - foreach_set(E, last, p) { - (void) fprintf(fp_primes, "%s\n", pc1(p)); - } - (void) fprintf(fp_primes, "# Totally redundant primes are\n"); - foreach_set(Rt, last, p) { - (void) fprintf(fp_primes, "%s\n", pc1(p)); - } - (void) fprintf(fp_primes, "# Partially redundant primes are\n"); - foreach_set(Rp, last, p) { - (void) fprintf(fp_primes, "%s\n", pc1(p)); - } - if (fp_primes != stdout) { - (void) fclose(fp_primes); - } - - sm_write(fp_pi_table, table); - if (fp_pi_table != stdout) { - (void) fclose(fp_pi_table); - } -} diff --git a/src/misc/espresso/expand.c b/src/misc/espresso/expand.c deleted file mode 100644 index 2765d71c..00000000 --- a/src/misc/espresso/expand.c +++ /dev/null @@ -1,693 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - module: expand.c - purpose: Perform the Espresso-II Expansion Step - - The idea is to take each nonprime cube of the on-set and expand it - into a prime implicant such that we can cover as many other cubes - of the on-set. If no cube of the on-set can be covered, then we - expand each cube into a large prime implicant by transforming the - problem into a minimum covering problem which is solved by the - heuristics of minimum_cover. - - These routines revolve around having a representation of the - OFF-set. (In contrast to the Espresso-II manuscript, we do NOT - require an "unwrapped" version of the OFF-set). - - Some conventions on variable names: - - SUPER_CUBE is the supercube of all cubes which can be covered - by an expansion of the cube being expanded - - OVEREXPANDED_CUBE is the cube which would result from expanding - all parts which can expand individually of the cube being expanded - - RAISE is the current expansion of the current cube - - FREESET is the set of parts which haven't been raised or lowered yet. - - INIT_LOWER is a set of parts to be removed from the free parts before - starting the expansion -*/ - -#include "espresso.h" - -/* - expand -- expand each nonprime cube of F into a prime implicant - - If nonsparse is true, only the non-sparse variables will be expanded; - this is done by forcing all of the sparse variables out of the free set. -*/ - -pcover expand(F, R, nonsparse) -INOUT pcover F; -IN pcover R; -IN bool nonsparse; /* expand non-sparse variables only */ -{ - register pcube last, p; - pcube RAISE, FREESET, INIT_LOWER, SUPER_CUBE, OVEREXPANDED_CUBE; - int var, num_covered; - bool change; - - /* Order the cubes according to "chewing-away from the edges" of mini */ - if (use_random_order) - F = random_order(F); - else - F = mini_sort(F, ascend); - - /* Allocate memory for variables needed by expand1() */ - RAISE = new_cube(); - FREESET = new_cube(); - INIT_LOWER = new_cube(); - SUPER_CUBE = new_cube(); - OVEREXPANDED_CUBE = new_cube(); - - /* Setup the initial lowering set (differs only for nonsparse) */ - if (nonsparse) - for(var = 0; var < cube.num_vars; var++) - if (cube.sparse[var]) - (void) set_or(INIT_LOWER, INIT_LOWER, cube.var_mask[var]); - - /* Mark all cubes as not covered, and maybe essential */ - foreach_set(F, last, p) { - RESET(p, COVERED); - RESET(p, NONESSEN); - } - - /* Try to expand each nonprime and noncovered cube */ - foreach_set(F, last, p) { - /* do not expand if PRIME or if covered by previous expansion */ - if (! TESTP(p, PRIME) && ! TESTP(p, COVERED)) { - - /* expand the cube p, result is RAISE */ - expand1(R, F, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE, - INIT_LOWER, &num_covered, p); - if (debug & EXPAND) - printf("EXPAND: %s (covered %d)\n", pc1(p), num_covered); - (void) set_copy(p, RAISE); - SET(p, PRIME); - RESET(p, COVERED); /* not really necessary */ - - /* See if we generated an inessential prime */ - if (num_covered == 0 && ! setp_equal(p, OVEREXPANDED_CUBE)) { - SET(p, NONESSEN); - } - } - } - - /* Delete any cubes of F which became covered during the expansion */ - F->active_count = 0; - change = FALSE; - foreach_set(F, last, p) { - if (TESTP(p, COVERED)) { - RESET(p, ACTIVE); - change = TRUE; - } else { - SET(p, ACTIVE); - F->active_count++; - } - } - if (change) - F = sf_inactive(F); - - free_cube(RAISE); - free_cube(FREESET); - free_cube(INIT_LOWER); - free_cube(SUPER_CUBE); - free_cube(OVEREXPANDED_CUBE); - return F; -} - -/* - expand1 -- Expand a single cube against the OFF-set -*/ -void expand1(BB, CC, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE, - INIT_LOWER, num_covered, c) -pcover BB; /* Blocking matrix (OFF-set) */ -pcover CC; /* Covering matrix (ON-set) */ -pcube RAISE; /* The current parts which have been raised */ -pcube FREESET; /* The current parts which are free */ -pcube OVEREXPANDED_CUBE; /* Overexpanded cube of c */ -pcube SUPER_CUBE; /* Supercube of all cubes of CC we cover */ -pcube INIT_LOWER; /* Parts to initially remove from FREESET */ -int *num_covered; /* Number of cubes of CC which are covered */ -pcube c; /* The cube to be expanded */ -{ - int bestindex; - - if (debug & EXPAND1) - printf("\nEXPAND1: \t%s\n", pc1(c)); - - /* initialize BB and CC */ - SET(c, PRIME); /* don't try to cover ourself */ - setup_BB_CC(BB, CC); - - /* initialize count of # cubes covered, and the supercube of them */ - *num_covered = 0; - (void) set_copy(SUPER_CUBE, c); - - /* Initialize the lowering, raising and unassigned sets */ - (void) set_copy(RAISE, c); - (void) set_diff(FREESET, cube.fullset, RAISE); - - /* If some parts are forced into lowering set, remove them */ - if (! setp_empty(INIT_LOWER)) { - (void) set_diff(FREESET, FREESET, INIT_LOWER); - elim_lowering(BB, CC, RAISE, FREESET); - } - - /* Determine what can be raised, and return the over-expanded cube */ - essen_parts(BB, CC, RAISE, FREESET); - (void) set_or(OVEREXPANDED_CUBE, RAISE, FREESET); - - /* While there are still cubes which can be covered, cover them ! */ - if (CC->active_count > 0) { - select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered); - } - - /* While there are still cubes covered by the overexpanded cube ... */ - while (CC->active_count > 0) { - bestindex = most_frequent(CC, FREESET); - set_insert(RAISE, bestindex); - set_remove(FREESET, bestindex); - essen_parts(BB, CC, RAISE, FREESET); - } - - /* Finally, when all else fails, choose the largest possible prime */ - /* We will loop only if we decide unravelling OFF-set is too expensive */ - while (BB->active_count > 0) { - mincov(BB, RAISE, FREESET); - } - - /* Raise any remaining free coordinates */ - (void) set_or(RAISE, RAISE, FREESET); -} - -/* - essen_parts -- determine which parts are forced into the lowering - set to insure that the cube be orthognal to the OFF-set. - - If any cube of the OFF-set is distance 1 from the raising cube, - then we must lower all parts of the conflicting variable. (If the - cube is distance 0, we detect this error here.) - - If there are essentially lowered parts, we can remove from consideration - any cubes of the OFF-set which are more than distance 1 from the - overexpanded cube of RAISE. -*/ - -void essen_parts(BB, CC, RAISE, FREESET) -pcover BB, CC; -pcube RAISE, FREESET; -{ - register pcube p, r = RAISE; - pcube lastp, xlower = cube.temp[0]; - int dist; - - (void) set_copy(xlower, cube.emptyset); - - foreach_active_set(BB, lastp, p) { -#ifdef NO_INLINE - if ((dist = cdist01(p, r)) > 1) goto exit_if; -#else - {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1) -{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto -exit_if;for(w=1;w>1)&DISJOINT)if(dist==1||( -dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube -mask;for(var=cube.num_binary_vars;var1)goto exit_if;nextvar:;}} -#endif - if (dist == 0) { - fatal("ON-set and OFF-set are not orthogonal"); - } else { - (void) force_lower(xlower, p, r); - BB->active_count--; - RESET(p, ACTIVE); - } -exit_if: ; - } - - if (! setp_empty(xlower)) { - (void) set_diff(FREESET, FREESET, xlower);/* remove from free set */ - elim_lowering(BB, CC, RAISE, FREESET); - } - - if (debug & EXPAND1) - printf("ESSEN_PARTS:\tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); -} - -/* - essen_raising -- determine which parts may always be added to - the raising set without restricting further expansions - - General rule: if some part is not blocked by any cube of BB, then - this part can always be raised. -*/ - -void essen_raising(BB, RAISE, FREESET) -register pcover BB; -pcube RAISE, FREESET; -{ - register pcube last, p, xraise = cube.temp[0]; - - /* Form union of all cubes of BB, and then take complement wrt FREESET */ - (void) set_copy(xraise, cube.emptyset); - foreach_active_set(BB, last, p) - INLINEset_or(xraise, xraise, p); - (void) set_diff(xraise, FREESET, xraise); - - (void) set_or(RAISE, RAISE, xraise); /* add to raising set */ - (void) set_diff(FREESET, FREESET, xraise); /* remove from free set */ - - if (debug & EXPAND1) - printf("ESSEN_RAISING:\tRAISE=%s FREESET=%s\n", - pc1(RAISE), pc2(FREESET)); -} - -/* - elim_lowering -- after removing parts from FREESET, we can reduce the - size of both BB and CC. - - We mark as inactive any cube of BB which does not intersect the - overexpanded cube (i.e., RAISE + FREESET). Likewise, we remove - from CC any cube which is not covered by the overexpanded cube. -*/ - -void elim_lowering(BB, CC, RAISE, FREESET) -pcover BB, CC; -pcube RAISE, FREESET; -{ - register pcube p, r = set_or(cube.temp[0], RAISE, FREESET); - pcube last; - - /* - * Remove sets of BB which are orthogonal to future expansions - */ - foreach_active_set(BB, last, p) { -#ifdef NO_INLINE - if (! cdist0(p, r)) -#else - {register int w,lastw;register unsigned int x;if((lastw=cube.inword)!=-1){x=p[ -lastw]&r[lastw];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w>1)&DISJOINT)goto false;}}}{register int w,var,lastw;register -pcube mask;for(var=cube.num_binary_vars;varactive_count--, RESET(p, ACTIVE); - } - - - /* - * Remove sets of CC which cannot be covered by future expansions - */ - if (CC != (pcover) NULL) { - foreach_active_set(CC, last, p) { -#ifdef NO_INLINE - if (! setp_implies(p, r)) -#else - INLINEsetp_implies(p, r, /* when false => */ goto false1); - /* when true => go to end of loop */ continue; - false1: -#endif - CC->active_count--, RESET(p, ACTIVE); - } - } -} - -/* - most_frequent -- When all else fails, select a reasonable part to raise - The active cubes of CC are the cubes which are covered by the - overexpanded cube of the original cube (however, we know that none - of them can actually be covered by a feasible expansion of the - original cube). We resort to the MINI strategy of selecting to - raise the part which will cover the same part in the most cubes of CC. -*/ -int most_frequent(CC, FREESET) -pcover CC; -pcube FREESET; -{ - register int i, best_part, best_count, *count; - register pset p, last; - - /* Count occurences of each variable */ - count = ALLOC(int, cube.size); - for(i = 0; i < cube.size; i++) - count[i] = 0; - if (CC != (pcover) NULL) - foreach_active_set(CC, last, p) - set_adjcnt(p, count, 1); - - /* Now find which free part occurs most often */ - best_count = best_part = -1; - for(i = 0; i < cube.size; i++) - if (is_in_set(FREESET,i) && count[i] > best_count) { - best_part = i; - best_count = count[i]; - } - FREE(count); - - if (debug & EXPAND1) - printf("MOST_FREQUENT:\tbest=%d FREESET=%s\n", best_part, pc2(FREESET)); - return best_part; -} - -/* - setup_BB_CC -- set up the blocking and covering set families; - - Note that the blocking family is merely the set of cubes of R, and - that CC is the set of cubes of F which might possibly be covered - (i.e., nonprime cubes, and cubes not already covered) -*/ - -void setup_BB_CC(BB, CC) -register pcover BB, CC; -{ - register pcube p, last; - - /* Create the block and cover set families */ - BB->active_count = BB->count; - foreach_set(BB, last, p) - SET(p, ACTIVE); - - if (CC != (pcover) NULL) { - CC->active_count = CC->count; - foreach_set(CC, last, p) - if (TESTP(p, COVERED) || TESTP(p, PRIME)) - CC->active_count--, RESET(p, ACTIVE); - else - SET(p, ACTIVE); - } -} - -/* - select_feasible -- Determine if there are cubes which can be covered, - and if so, raise those parts necessary to cover as many as possible. - - We really don't check to maximize the number that can be covered; - instead, we check, for each fcc, how many other fcc remain fcc - after expanding to cover the fcc. (Essentially one-level lookahead). -*/ - -void select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered) -pcover BB, CC; -pcube RAISE, FREESET, SUPER_CUBE; -int *num_covered; -{ - register pcube p, last, bestfeas, *feas; - register int i, j; - pcube *feas_new_lower; - int bestcount, bestsize, count, size, numfeas, lastfeas; - pcover new_lower; - - /* Start out with all cubes covered by the over-expanded cube as - * the "possibly" feasibly-covered cubes (pfcc) - */ - feas = ALLOC(pcube, CC->active_count); - numfeas = 0; - foreach_active_set(CC, last, p) - feas[numfeas++] = p; - - /* Setup extra cubes to record parts forced low after a covering */ - feas_new_lower = ALLOC(pcube, CC->active_count); - new_lower = new_cover(numfeas); - for(i = 0; i < numfeas; i++) - feas_new_lower[i] = GETSET(new_lower, i); - - -loop: - /* Find the essentially raised parts -- this might cover some cubes - for us, without having to find out if they are fcc or not - */ - essen_raising(BB, RAISE, FREESET); - - /* Now check all "possibly" feasibly covered cubes to check feasibility */ - lastfeas = numfeas; - numfeas = 0; - for(i = 0; i < lastfeas; i++) { - p = feas[i]; - - /* Check active because essen_parts might have removed it */ - if (TESTP(p, ACTIVE)) { - - /* See if the cube is already covered by RAISE -- - * this can happen because of essen_raising() or because of - * the previous "loop" - */ - if (setp_implies(p, RAISE)) { - (*num_covered) += 1; - (void) set_or(SUPER_CUBE, SUPER_CUBE, p); - CC->active_count--; - RESET(p, ACTIVE); - SET(p, COVERED); - /* otherwise, test if it is feasibly covered */ - } else if (feasibly_covered(BB,p,RAISE,feas_new_lower[numfeas])) { - feas[numfeas] = p; /* save the fcc */ - numfeas++; - } - } - } - if (debug & EXPAND1) - printf("SELECT_FEASIBLE: started with %d pfcc, ended with %d fcc\n", - lastfeas, numfeas); - - /* Exit here if there are no feasibly covered cubes */ - if (numfeas == 0) { - FREE(feas); - FREE(feas_new_lower); - free_cover(new_lower); - return; - } - - /* Now find which is the best feasibly covered cube */ - bestcount = 0; - bestsize = 9999; - for(i = 0; i < numfeas; i++) { - size = set_dist(feas[i], FREESET); /* # of newly raised parts */ - count = 0; /* # of other cubes which remain fcc after raising */ - -#define NEW -#ifdef NEW - for(j = 0; j < numfeas; j++) - if (setp_disjoint(feas_new_lower[i], feas[j])) - count++; -#else - for(j = 0; j < numfeas; j++) - if (setp_implies(feas[j], feas[i])) - count++; -#endif - if (count > bestcount) { - bestcount = count; - bestfeas = feas[i]; - bestsize = size; - } else if (count == bestcount && size < bestsize) { - bestfeas = feas[i]; - bestsize = size; - } - } - - /* Add the necessary parts to the raising set */ - (void) set_or(RAISE, RAISE, bestfeas); - (void) set_diff(FREESET, FREESET, RAISE); - if (debug & EXPAND1) - printf("FEASIBLE: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); - essen_parts(BB, CC, RAISE, FREESET); - goto loop; -/* NOTREACHED */ -} - -/* - feasibly_covered -- determine if the cube c is feasibly covered - (i.e., if it is possible to raise all of the necessary variables - while still insuring orthogonality with R). Also, if c is feasibly - covered, then compute the new set of parts which are forced into - the lowering set. -*/ - -bool feasibly_covered(BB, c, RAISE, new_lower) -pcover BB; -pcube c, RAISE, new_lower; -{ - register pcube p, r = set_or(cube.temp[0], RAISE, c); - int dist; - pcube lastp; - - set_copy(new_lower, cube.emptyset); - foreach_active_set(BB, lastp, p) { -#ifdef NO_INLINE - if ((dist = cdist01(p, r)) > 1) goto exit_if; -#else - {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1) -{x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto -exit_if;for(w=1;w>1)&DISJOINT)if(dist==1||( -dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube -mask;for(var=cube.num_binary_vars;var1)goto exit_if;nextvar:;}} -#endif - if (dist == 0) - return FALSE; - else - (void) force_lower(new_lower, p, r); - exit_if: ; - } - return TRUE; -} - -/* - mincov -- transform the problem of expanding a cube to a maximally- - large prime implicant into the problem of selecting a minimum - cardinality cover over a family of sets. - - When we get to this point, we must unravel the remaining off-set. - This may be painful. -*/ - -void mincov(BB, RAISE, FREESET) -pcover BB; -pcube RAISE, FREESET; -{ - int expansion, nset, var, dist; - pset_family B; - register pcube xraise=cube.temp[0], xlower, p, last, plower; - -#ifdef RANDOM_MINCOV -#if defined(_POSIX_SOURCE) || defined(__SVR4) - dist = rand() % set_ord(FREESET); -#else - dist = random() % set_ord(FREESET); -#endif - for(var = 0; var < cube.size && dist >= 0; var++) { - if (is_in_set(FREESET, var)) { - dist--; - } - } - - set_insert(RAISE, var); - set_remove(FREESET, var); - (void) essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET); -#else - - /* Create B which are those cubes which we must avoid intersecting */ - B = new_cover(BB->active_count); - foreach_active_set(BB, last, p) { - plower = set_copy(GETSET(B, B->count++), cube.emptyset); - (void) force_lower(plower, p, RAISE); - } - - /* Determine how many sets it will blow up into after the unravel */ - nset = 0; - foreach_set(B, last, p) { - expansion = 1; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - if ((dist=set_dist(p, cube.var_mask[var])) > 1) { - expansion *= dist; - if (expansion > 500) goto heuristic_mincov; - } - } - nset += expansion; - if (nset > 500) goto heuristic_mincov; - } - - B = unravel(B, cube.num_binary_vars); - xlower = do_sm_minimum_cover(B); - - /* Add any remaining free parts to the raising set */ - (void) set_or(RAISE, RAISE, set_diff(xraise, FREESET, xlower)); - (void) set_copy(FREESET, cube.emptyset); /* free set is empty */ - BB->active_count = 0; /* BB satisfied */ - if (debug & EXPAND1) { - printf("MINCOV: \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET)); - } - sf_free(B); - set_free(xlower); - return; - -heuristic_mincov: - sf_free(B); - /* most_frequent will pick first free part */ - set_insert(RAISE, most_frequent(/*CC*/ (pcover) NULL, FREESET)); - (void) set_diff(FREESET, FREESET, RAISE); - essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET); - return; -#endif -} - -/* - find_all_primes -- find all of the primes which cover the - currently reduced BB -*/ -pcover find_all_primes(BB, RAISE, FREESET) -pcover BB; -register pcube RAISE, FREESET; -{ - register pset last, p, plower; - pset_family B, B1; - - if (BB->active_count == 0) { - B1 = new_cover(1); - p = GETSET(B1, B1->count++); - (void) set_copy(p, RAISE); - SET(p, PRIME); - } else { - B = new_cover(BB->active_count); - foreach_active_set(BB, last, p) { - plower = set_copy(GETSET(B, B->count++), cube.emptyset); - (void) force_lower(plower, p, RAISE); - } - B = sf_rev_contain(unravel(B, cube.num_binary_vars)); - B1 = exact_minimum_cover(B); - foreach_set(B1, last, p) { - INLINEset_diff(p, FREESET, p); - INLINEset_or(p, p, RAISE); - SET(p, PRIME); - } - free_cover(B); - } - return B1; -} - -/* - all_primes -- foreach cube in F, generate all of the primes - which cover the cube. -*/ - -pcover all_primes(F, R) -pcover F, R; -{ - register pcube last, p, RAISE, FREESET; - pcover Fall_primes, B1; - - FREESET = new_cube(); - RAISE = new_cube(); - Fall_primes = new_cover(F->count); - - foreach_set(F, last, p) { - if (TESTP(p, PRIME)) { - Fall_primes = sf_addset(Fall_primes, p); - } else { - /* Setup for call to essential parts */ - (void) set_copy(RAISE, p); - (void) set_diff(FREESET, cube.fullset, RAISE); - setup_BB_CC(R, /* CC */ (pcover) NULL); - essen_parts(R, /* CC */ (pcover) NULL, RAISE, FREESET); - - /* Find all of the primes, and add them to the prime set */ - B1 = find_all_primes(R, RAISE, FREESET); - Fall_primes = sf_append(Fall_primes, B1); - } - } - - set_free(RAISE); - set_free(FREESET); - return Fall_primes; -} diff --git a/src/misc/espresso/gasp.c b/src/misc/espresso/gasp.c deleted file mode 100644 index aa3254d3..00000000 --- a/src/misc/espresso/gasp.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - module: gasp.c - - The "last_gasp" heuristic computes the reduction of each cube in - the cover (without replacement) and then performs an expansion of - these cubes. The cubes which expand to cover some other cube are - added to the original cover and irredundant finds a minimal subset. - - If one of the reduced cubes expands to cover some other reduced - cube, then the new prime thus generated is a candidate for reducing - the size of the cover. - - super_gasp is a variation on this strategy which extracts a minimal - subset from the set of all prime implicants which cover all - maximally reduced cubes. -*/ - -#include "espresso.h" - - -/* - * reduce_gasp -- compute the maximal reduction of each cube of F - * - * If a cube does not reduce, it remains prime; otherwise, it is marked - * as nonprime. If the cube is redundant (should NEVER happen here) we - * just crap out ... - * - * A cover with all of the cubes of F is returned. Those that did - * reduce are marked "NONPRIME"; those that reduced are marked "PRIME". - * The cubes are in the same order as in F. - */ -static pcover reduce_gasp(F, D) -pcover F, D; -{ - pcube p, last, cunder, *FD; - pcover G; - - G = new_cover(F->count); - FD = cube2list(F, D); - - /* Reduce cubes of F without replacement */ - foreach_set(F, last, p) { - cunder = reduce_cube(FD, p); - if (setp_empty(cunder)) { - fatal("empty reduction in reduce_gasp, shouldn't happen"); - } else if (setp_equal(cunder, p)) { - SET(cunder, PRIME); /* just to make sure */ - G = sf_addset(G, p); /* it did not reduce ... */ - } else { - RESET(cunder, PRIME); /* it reduced ... */ - G = sf_addset(G, cunder); - } - if (debug & GASP) { - printf("REDUCE_GASP: %s reduced to %s\n", pc1(p), pc2(cunder)); - } - free_cube(cunder); - } - - free_cubelist(FD); - return G; -} - -/* - * expand_gasp -- expand each nonprime cube of F into a prime implicant - * - * The gasp strategy differs in that only those cubes which expand to - * cover some other cube are saved; also, all cubes are expanded - * regardless of whether they become covered or not. - */ - -pcover expand_gasp(F, D, R, Foriginal) -INOUT pcover F; -IN pcover D; -IN pcover R; -IN pcover Foriginal; -{ - int c1index; - pcover G; - - /* Try to expand each nonprime and noncovered cube */ - G = new_cover(10); - for(c1index = 0; c1index < F->count; c1index++) { - expand1_gasp(F, D, R, Foriginal, c1index, &G); - } - G = sf_dupl(G); - G = expand(G, R, /*nonsparse*/ FALSE); /* Make them prime ! */ - return G; -} - - - -/* - * expand1 -- Expand a single cube against the OFF-set, using the gasp strategy - */ -void expand1_gasp(F, D, R, Foriginal, c1index, G) -pcover F; /* reduced cubes of ON-set */ -pcover D; /* DC-set */ -pcover R; /* OFF-set */ -pcover Foriginal; /* ON-set before reduction (same order as F) */ -int c1index; /* which index of F (or Freduced) to be checked */ -pcover *G; -{ - register int c2index; - register pcube p, last, c2under; - pcube RAISE, FREESET, temp, *FD, c2essential; - pcover F1; - - if (debug & EXPAND1) { - printf("\nEXPAND1_GASP: \t%s\n", pc1(GETSET(F, c1index))); - } - - RAISE = new_cube(); - FREESET = new_cube(); - temp = new_cube(); - - /* Initialize the OFF-set */ - R->active_count = R->count; - foreach_set(R, last, p) { - SET(p, ACTIVE); - } - /* Initialize the reduced ON-set, all nonprime cubes become active */ - F->active_count = F->count; - foreachi_set(F, c2index, c2under) { - if (c1index == c2index || TESTP(c2under, PRIME)) { - F->active_count--; - RESET(c2under, ACTIVE); - } else { - SET(c2under, ACTIVE); - } - } - - /* Initialize the raising and unassigned sets */ - (void) set_copy(RAISE, GETSET(F, c1index)); - (void) set_diff(FREESET, cube.fullset, RAISE); - - /* Determine parts which must be lowered */ - essen_parts(R, F, RAISE, FREESET); - - /* Determine parts which can always be raised */ - essen_raising(R, RAISE, FREESET); - - /* See which, if any, of the reduced cubes we can cover */ - foreachi_set(F, c2index, c2under) { - if (TESTP(c2under, ACTIVE)) { - /* See if this cube can be covered by an expansion */ - if (setp_implies(c2under, RAISE) || - feasibly_covered(R, c2under, RAISE, temp)) { - - /* See if c1under can expanded to cover c2 reduced against - * (F - c1) u c1under; if so, c2 can definitely be removed ! - */ - - /* Copy F and replace c1 with c1under */ - F1 = sf_save(Foriginal); - (void) set_copy(GETSET(F1, c1index), GETSET(F, c1index)); - - /* Reduce c2 against ((F - c1) u c1under) */ - FD = cube2list(F1, D); - c2essential = reduce_cube(FD, GETSET(F1, c2index)); - free_cubelist(FD); - sf_free(F1); - - /* See if c2essential is covered by an expansion of c1under */ - if (feasibly_covered(R, c2essential, RAISE, temp)) { - (void) set_or(temp, RAISE, c2essential); - RESET(temp, PRIME); /* cube not prime */ - *G = sf_addset(*G, temp); - } - set_free(c2essential); - } - } - } - - free_cube(RAISE); - free_cube(FREESET); - free_cube(temp); -} - -/* irred_gasp -- Add new primes to F and find an irredundant subset */ -pcover irred_gasp(F, D, G) -pcover F, D, G; /* G is disposed of */ -{ - if (G->count != 0) - F = irredundant(sf_append(F, G), D); - else - free_cover(G); - return F; -} - - -/* last_gasp */ -pcover last_gasp(F, D, R, cost) -pcover F, D, R; -cost_t *cost; -{ - pcover G, G1; - - EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost); - EXECUTE(G1 = expand_gasp(G, D, R, F), GEXPAND_TIME, G1, *cost); - free_cover(G); - EXECUTE(F = irred_gasp(F, D, G1), GIRRED_TIME, F, *cost); - return F; -} - - -/* super_gasp */ -pcover super_gasp(F, D, R, cost) -pcover F, D, R; -cost_t *cost; -{ - pcover G, G1; - - EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost); - EXECUTE(G1 = all_primes(G, R), GEXPAND_TIME, G1, *cost); - free_cover(G); - EXEC(G = sf_dupl(sf_append(F, G1)), "NEWPRIMES", G); - EXECUTE(F = irredundant(G, D), IRRED_TIME, F, *cost); - return F; -} diff --git a/src/misc/espresso/gimpel.c b/src/misc/espresso/gimpel.c deleted file mode 100644 index 648bb64a..00000000 --- a/src/misc/espresso/gimpel.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "mincov_int.h" - - -/* - * check for: - * - * c1 c2 rest - * -- -- --- - * 1 1 0 0 0 0 <-- primary row - * 1 0 S1 <-- secondary row - * 0 1 T1 - * 0 1 T2 - * 0 1 Tn - * 0 0 R - */ - -int -gimpel_reduce(A, select, weight, lb, bound, depth, stats, best) -sm_matrix *A; -solution_t *select; -int *weight; -int lb; -int bound; -int depth; -stats_t *stats; -solution_t **best; -{ - register sm_row *prow, *save_sec; - register sm_col *c1, *c2; - register sm_element *p, *p1; - int c1_col_num, c2_col_num, primary_row_num, secondary_row_num; - int reduce_it; - - reduce_it = 0; - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - if (prow->length == 2) { - c1 = sm_get_col(A, prow->first_col->col_num); - c2 = sm_get_col(A, prow->last_col->col_num); - if (c1->length == 2) { - reduce_it = 1; - } else if (c2->length == 2) { - c1 = sm_get_col(A, prow->last_col->col_num); - c2 = sm_get_col(A, prow->first_col->col_num); - reduce_it = 1; - } - if (reduce_it) { - primary_row_num = prow->row_num; - secondary_row_num = c1->first_row->row_num; - if (secondary_row_num == primary_row_num) { - secondary_row_num = c1->last_row->row_num; - } - break; - } - } - } - - if (reduce_it) { - c1_col_num = c1->col_num; - c2_col_num = c2->col_num; - save_sec = sm_row_dup(sm_get_row(A, secondary_row_num)); - sm_row_remove(save_sec, c1_col_num); - - for(p = c2->first_row; p != 0; p = p->next_row) { - if (p->row_num != primary_row_num) { - /* merge rows S1 and T */ - for(p1 = save_sec->first_col; p1 != 0; p1 = p1->next_col) { - (void) sm_insert(A, p->row_num, p1->col_num); - } - } - } - - sm_delcol(A, c1_col_num); - sm_delcol(A, c2_col_num); - sm_delrow(A, primary_row_num); - sm_delrow(A, secondary_row_num); - - stats->gimpel_count++; - stats->gimpel++; - *best = sm_mincov(A, select, weight, lb-1, bound-1, depth, stats); - stats->gimpel--; - - if (*best != NIL(solution_t)) { - /* is secondary row covered ? */ - if (sm_row_intersects(save_sec, (*best)->row)) { - /* yes, actually select c2 */ - solution_add(*best, weight, c2_col_num); - } else { - solution_add(*best, weight, c1_col_num); - } - } - - sm_row_free(save_sec); - return 1; - } else { - return 0; - } -} diff --git a/src/misc/espresso/globals.c b/src/misc/espresso/globals.c deleted file mode 100644 index d04771e9..00000000 --- a/src/misc/espresso/globals.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - -/* - * Global Variable Declarations - */ - -unsigned int debug; /* debug parameter */ -bool verbose_debug; /* -v: whether to print a lot */ -char *total_name[TIME_COUNT]; /* basic function names */ -long total_time[TIME_COUNT]; /* time spent in basic fcts */ -int total_calls[TIME_COUNT]; /* # calls to each fct */ - -bool echo_comments; /* turned off by -eat option */ -bool echo_unknown_commands; /* always true ?? */ -bool force_irredundant; /* -nirr command line option */ -bool skip_make_sparse; -bool kiss; /* -kiss command line option */ -bool pos; /* -pos command line option */ -bool print_solution; /* -x command line option */ -bool recompute_onset; /* -onset command line option */ -bool remove_essential; /* -ness command line option */ -bool single_expand; /* -fast command line option */ -bool summary; /* -s command line option */ -bool trace; /* -t command line option */ -bool unwrap_onset; /* -nunwrap command line option */ -bool use_random_order; /* -random command line option */ -bool use_super_gasp; /* -strong command line option */ -char *filename; /* filename PLA was read from */ - -struct pla_types_struct pla_types[] = { - "-f", F_type, - "-r", R_type, - "-d", D_type, - "-fd", FD_type, - "-fr", FR_type, - "-dr", DR_type, - "-fdr", FDR_type, - "-fc", F_type | CONSTRAINTS_type, - "-rc", R_type | CONSTRAINTS_type, - "-dc", D_type | CONSTRAINTS_type, - "-fdc", FD_type | CONSTRAINTS_type, - "-frc", FR_type | CONSTRAINTS_type, - "-drc", DR_type | CONSTRAINTS_type, - "-fdrc", FDR_type | CONSTRAINTS_type, - "-pleasure", PLEASURE_type, - "-eqn", EQNTOTT_type, - "-eqntott", EQNTOTT_type, - "-kiss", KISS_type, - "-cons", CONSTRAINTS_type, - "-scons", SYMBOLIC_CONSTRAINTS_type, - 0, 0 -}; - - -struct cube_struct cube, temp_cube_save; -struct cdata_struct cdata, temp_cdata_save; - -int bit_count[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; diff --git a/src/misc/espresso/hack.c b/src/misc/espresso/hack.c deleted file mode 100644 index 927f5341..00000000 --- a/src/misc/espresso/hack.c +++ /dev/null @@ -1,641 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - -map_dcset(PLA) -pPLA PLA; -{ - int var, i; - pcover Tplus, Tminus, Tplusbar, Tminusbar; - pcover newf, term1, term2, dcset, dcsetbar; - pcube cplus, cminus, last, p; - - if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) - return; - - /* try to find a binary variable named "DONT_CARE" */ - var = -1; - for(i = 0; i < cube.num_binary_vars * 2; i++) { - if (strncmp(PLA->label[i], "DONT_CARE", 9) == 0 || - strncmp(PLA->label[i], "DONTCARE", 8) == 0 || - strncmp(PLA->label[i], "dont_care", 9) == 0 || - strncmp(PLA->label[i], "dontcare", 8) == 0) { - var = i/2; - break; - } - } - if (var == -1) { - return; - } - - /* form the cofactor cubes for the don't-care variable */ - cplus = set_save(cube.fullset); - cminus = set_save(cube.fullset); - set_remove(cplus, var*2); - set_remove(cminus, var*2 + 1); - - /* form the don't-care set */ - EXEC(simp_comp(cofactor(cube1list(PLA->F), cplus), &Tplus, &Tplusbar), - "simpcomp+", Tplus); - EXEC(simp_comp(cofactor(cube1list(PLA->F), cminus), &Tminus, &Tminusbar), - "simpcomp-", Tminus); - EXEC(term1 = cv_intersect(Tplus, Tminusbar), "term1 ", term1); - EXEC(term2 = cv_intersect(Tminus, Tplusbar), "term2 ", term2); - EXEC(dcset = sf_union(term1, term2), "union ", dcset); - EXEC(simp_comp(cube1list(dcset), &PLA->D, &dcsetbar), "simplify", PLA->D); - EXEC(newf = cv_intersect(PLA->F, dcsetbar), "separate ", PLA->F); - free_cover(PLA->F); - PLA->F = newf; - free_cover(Tplus); - free_cover(Tminus); - free_cover(Tplusbar); - free_cover(Tminusbar); - free_cover(dcsetbar); - - /* remove any cubes dependent on the DONT_CARE variable */ - (void) sf_active(PLA->F); - foreach_set(PLA->F, last, p) { - if (! is_in_set(p, var*2) || ! is_in_set(p, var*2+1)) { - RESET(p, ACTIVE); - } - } - PLA->F = sf_inactive(PLA->F); - - /* resize the cube and delete the don't-care variable */ - setdown_cube(); - for(i = 2*var+2; i < cube.size; i++) { - PLA->label[i-2] = PLA->label[i]; - } - for(i = var+1; i < cube.num_vars; i++) { - cube.part_size[i-1] = cube.part_size[i]; - } - cube.num_binary_vars--; - cube.num_vars--; - cube_setup(); - PLA->F = sf_delc(PLA->F, 2*var, 2*var+1); - PLA->D = sf_delc(PLA->D, 2*var, 2*var+1); -} - -map_output_symbolic(PLA) -pPLA PLA; -{ - pset_family newF, newD; - pset compress; - symbolic_t *p1; - symbolic_list_t *p2; - int i, bit, tot_size, base, old_size; - - /* Remove the DC-set from the ON-set (is this necessary ??) */ - if (PLA->D->count > 0) { - sf_free(PLA->F); - PLA->F = complement(cube2list(PLA->D, PLA->R)); - } - - /* tot_size = width added for all symbolic variables */ - tot_size = 0; - for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - if (p2->pos<0 || p2->pos>=cube.part_size[cube.output]) { - fatal("symbolic-output index out of range"); -/* } else if (p2->variable != cube.output) { - fatal("symbolic-output label must be an output");*/ - } - } - tot_size += 1 << p1->symbolic_list_length; - } - - /* adjust the indices to skip over new outputs */ - for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - p2->pos += tot_size; - } - } - - /* resize the cube structure -- add enough for the one-hot outputs */ - old_size = cube.size; - cube.part_size[cube.output] += tot_size; - setdown_cube(); - cube_setup(); - - /* insert space in the output part for the one-hot output */ - base = cube.first_part[cube.output]; - PLA->F = sf_addcol(PLA->F, base, tot_size); - PLA->D = sf_addcol(PLA->D, base, tot_size); - PLA->R = sf_addcol(PLA->R, base, tot_size); - - /* do the real work */ - for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { - newF = new_cover(100); - newD = new_cover(100); - find_inputs(NIL(set_family_t), PLA, p1->symbolic_list, base, 0, - &newF, &newD); -/* - * Not sure what this means - find_dc_inputs(PLA, p1->symbolic_list, - base, 1 << p1->symbolic_list_length, &newF, &newD); - */ - free_cover(PLA->F); - PLA->F = newF; -/* - * retain OLD DC-set -- but we've lost the don't-care arc information - * (it defaults to branch to the zero state) - free_cover(PLA->D); - PLA->D = newD; - */ - free_cover(newD); - base += 1 << p1->symbolic_list_length; - } - - /* delete the old outputs, and resize the cube */ - compress = set_full(newF->sf_size); - for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) { - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - bit = cube.first_part[cube.output] + p2->pos; - set_remove(compress, bit); - } - } - cube.part_size[cube.output] -= newF->sf_size - set_ord(compress); - setdown_cube(); - cube_setup(); - PLA->F = sf_compress(PLA->F, compress); - PLA->D = sf_compress(PLA->D, compress); - if (cube.size != PLA->F->sf_size) fatal("error"); - - /* Quick minimization */ - PLA->F = sf_contain(PLA->F); - PLA->D = sf_contain(PLA->D); - for(i = 0; i < cube.num_vars; i++) { - PLA->F = d1merge(PLA->F, i); - PLA->D = d1merge(PLA->D, i); - } - PLA->F = sf_contain(PLA->F); - PLA->D = sf_contain(PLA->D); - - free_cover(PLA->R); - PLA->R = new_cover(0); - - symbolic_hack_labels(PLA, PLA->symbolic_output, - compress, cube.size, old_size, tot_size); - set_free(compress); -} - - -find_inputs(A, PLA, list, base, value, newF, newD) -pcover A; -pPLA PLA; -symbolic_list_t *list; -int base, value; -pcover *newF, *newD; -{ - pcover S, S1; - register pset last, p; - - /* - * A represents th 'input' values for which the outputs assume - * the integer value 'value - */ - if (list == NIL(symbolic_list_t)) { - /* - * Simulate these inputs against the on-set; then, insert into the - * new on-set a 1 in the proper position - */ - S = cv_intersect(A, PLA->F); - foreach_set(S, last, p) { - set_insert(p, base + value); - } - *newF = sf_append(*newF, S); - - /* - * 'simulate' these inputs against the don't-care set - S = cv_intersect(A, PLA->D); - *newD = sf_append(*newD, S); - */ - - } else { - /* intersect and recur with the OFF-set */ - S = cof_output(PLA->R, cube.first_part[cube.output] + list->pos); - if (A != NIL(set_family_t)) { - S1 = cv_intersect(A, S); - free_cover(S); - S = S1; - } - find_inputs(S, PLA, list->next, base, value*2, newF, newD); - free_cover(S); - - /* intersect and recur with the ON-set */ - S = cof_output(PLA->F, cube.first_part[cube.output] + list->pos); - if (A != NIL(set_family_t)) { - S1 = cv_intersect(A, S); - free_cover(S); - S = S1; - } - find_inputs(S, PLA, list->next, base, value*2 + 1, newF, newD); - free_cover(S); - } -} - - -#if 0 -find_dc_inputs(PLA, list, base, maxval, newF, newD) -pPLA PLA; -symbolic_list_t *list; -int base, maxval; -pcover *newF, *newD; -{ - pcover A, S, S1; - symbolic_list_t *p2; - register pset p, last; - register int i; - - /* painfully find the points for which the symbolic output is dc */ - A = NIL(set_family_t); - for(p2=list; p2!=NIL(symbolic_list_t); p2=p2->next) { - S = cof_output(PLA->D, cube.first_part[cube.output] + p2->pos); - if (A == NIL(set_family_t)) { - A = S; - } else { - S1 = cv_intersect(A, S); - free_cover(S); - free_cover(A); - A = S1; - } - } - - S = cv_intersect(A, PLA->F); - *newF = sf_append(*newF, S); - - S = cv_intersect(A, PLA->D); - foreach_set(S, last, p) { - for(i = base; i < base + maxval; i++) { - set_insert(p, i); - } - } - *newD = sf_append(*newD, S); - free_cover(A); -} -#endif - -map_symbolic(PLA) -pPLA PLA; -{ - symbolic_t *p1; - symbolic_list_t *p2; - int var, base, num_vars, num_binary_vars, *new_part_size; - int new_size, size_added, num_deleted_vars, num_added_vars, newvar; - pset compress; - - /* Verify legal values are in the symbolic lists */ - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - if (p2->variable < 0 || p2->variable >= cube.num_binary_vars) { - fatal(".symbolic requires binary variables"); - } - } - } - - /* - * size_added = width added for all symbolic variables - * num_deleted_vars = # binary variables to be deleted - * num_added_vars = # new mv variables - * compress = a cube which will be used to compress the set families - */ - size_added = 0; - num_added_vars = 0; - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { - size_added += 1 << p1->symbolic_list_length; - num_added_vars++; - } - compress = set_full(PLA->F->sf_size + size_added); - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { - for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) { - set_remove(compress, p2->variable*2); - set_remove(compress, p2->variable*2+1); - } - } - num_deleted_vars = ((PLA->F->sf_size + size_added) - set_ord(compress))/2; - - /* compute the new cube constants */ - num_vars = cube.num_vars - num_deleted_vars + num_added_vars; - num_binary_vars = cube.num_binary_vars - num_deleted_vars; - new_size = cube.size - num_deleted_vars*2 + size_added; - new_part_size = ALLOC(int, num_vars); - new_part_size[num_vars-1] = cube.part_size[cube.num_vars-1]; - for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) { - new_part_size[var-num_deleted_vars] = cube.part_size[var]; - } - - /* re-size the covers, opening room for the new mv variables */ - base = cube.first_part[cube.output]; - PLA->F = sf_addcol(PLA->F, base, size_added); - PLA->D = sf_addcol(PLA->D, base, size_added); - PLA->R = sf_addcol(PLA->R, base, size_added); - - /* compute the values for the new mv variables */ - newvar = (cube.num_vars - 1) - num_deleted_vars; - for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) { - PLA->F = map_symbolic_cover(PLA->F, p1->symbolic_list, base); - PLA->D = map_symbolic_cover(PLA->D, p1->symbolic_list, base); - PLA->R = map_symbolic_cover(PLA->R, p1->symbolic_list, base); - base += 1 << p1->symbolic_list_length; - new_part_size[newvar++] = 1 << p1->symbolic_list_length; - } - - /* delete the binary variables which disappear */ - PLA->F = sf_compress(PLA->F, compress); - PLA->D = sf_compress(PLA->D, compress); - PLA->R = sf_compress(PLA->R, compress); - - symbolic_hack_labels(PLA, PLA->symbolic, compress, - new_size, cube.size, size_added); - setdown_cube(); - FREE(cube.part_size); - cube.num_vars = num_vars; - cube.num_binary_vars = num_binary_vars; - cube.part_size = new_part_size; - cube_setup(); - set_free(compress); -} - - -pcover map_symbolic_cover(T, list, base) -pcover T; -symbolic_list_t *list; -int base; -{ - pset last, p; - foreach_set(T, last, p) { - form_bitvector(p, base, 0, list); - } - return T; -} - - -form_bitvector(p, base, value, list) -pset p; /* old cube, looking at binary variables */ -int base; /* where in mv cube the new variable starts */ -int value; /* current value for this recursion */ -symbolic_list_t *list; /* current place in the symbolic list */ -{ - if (list == NIL(symbolic_list_t)) { - set_insert(p, base + value); - } else { - switch(GETINPUT(p, list->variable)) { - case ZERO: - form_bitvector(p, base, value*2, list->next); - break; - case ONE: - form_bitvector(p, base, value*2+1, list->next); - break; - case TWO: - form_bitvector(p, base, value*2, list->next); - form_bitvector(p, base, value*2+1, list->next); - break; - default: - fatal("bad cube in form_bitvector"); - } - } -} - - -symbolic_hack_labels(PLA, list, compress, new_size, old_size, size_added) -pPLA PLA; -symbolic_t *list; -pset compress; -int new_size, old_size, size_added; -{ - int i, base; - char **oldlabel; - symbolic_t *p1; - symbolic_label_t *p3; - - /* hack with the labels */ - if ((oldlabel = PLA->label) == NIL(char *)) - return; - PLA->label = ALLOC(char *, new_size); - for(i = 0; i < new_size; i++) { - PLA->label[i] = NIL(char); - } - - /* copy the binary variable labels and unchanged mv variable labels */ - base = 0; - for(i = 0; i < cube.first_part[cube.output]; i++) { - if (is_in_set(compress, i)) { - PLA->label[base++] = oldlabel[i]; - } else { - if (oldlabel[i] != NIL(char)) { - FREE(oldlabel[i]); - } - } - } - - /* add the user-defined labels for the symbolic outputs */ - for(p1 = list; p1 != NIL(symbolic_t); p1 = p1->next) { - p3 = p1->symbolic_label; - for(i = 0; i < (1 << p1->symbolic_list_length); i++) { - if (p3 == NIL(symbolic_label_t)) { - PLA->label[base+i] = ALLOC(char, 10); - (void) sprintf(PLA->label[base+i], "X%d", i); - } else { - PLA->label[base+i] = p3->label; - p3 = p3->next; - } - } - base += 1 << p1->symbolic_list_length; - } - - /* copy the labels for the binary outputs which remain */ - for(i = cube.first_part[cube.output]; i < old_size; i++) { - if (is_in_set(compress, i + size_added)) { - PLA->label[base++] = oldlabel[i]; - } else { - if (oldlabel[i] != NIL(char)) { - FREE(oldlabel[i]); - } - } - } - FREE(oldlabel); -} - -static pcover fsm_simplify(F) -pcover F; -{ - pcover D, R; - D = new_cover(0); - R = complement(cube1list(F)); - F = espresso(F, D, R); - free_cover(D); - free_cover(R); - return F; -} - - -disassemble_fsm(PLA, verbose_mode) -pPLA PLA; -int verbose_mode; -{ - int nin, nstates, nout; - int before, after, present_state, next_state, i, j; - pcube next_state_mask, present_state_mask, state_mask, p, p1, last; - pcover go_nowhere, F, tF; - - /* We make the DISGUSTING assumption that the first 'n' outputs have - * been created by .symbolic-output, and represent a one-hot encoding - * of the next state. 'n' is the size of the second-to-last multiple- - * valued variable (i.e., before the outputs - */ - - if (cube.num_vars - cube.num_binary_vars != 2) { - (void) fprintf(stderr, - "use .symbolic and .symbolic-output to specify\n"); - (void) fprintf(stderr, - "the present state and next state field information\n"); - fatal("disassemble_pla: need two multiple-valued variables\n"); - } - - nin = cube.num_binary_vars; - nstates = cube.part_size[cube.num_binary_vars]; - nout = cube.part_size[cube.num_vars - 1]; - if (nout < nstates) { - (void) fprintf(stderr, - "use .symbolic and .symbolic-output to specify\n"); - (void) fprintf(stderr, - "the present state and next state field information\n"); - fatal("disassemble_pla: # outputs < # states\n"); - } - - - present_state = cube.first_part[cube.num_binary_vars]; - present_state_mask = new_cube(); - for(i = 0; i < nstates; i++) { - set_insert(present_state_mask, i + present_state); - } - - next_state = cube.first_part[cube.num_binary_vars+1]; - next_state_mask = new_cube(); - for(i = 0; i < nstates; i++) { - set_insert(next_state_mask, i + next_state); - } - - state_mask = set_or(new_cube(), next_state_mask, present_state_mask); - - F = new_cover(10); - - - /* - * check for arcs which go from ANY state to state #i - */ - for(i = 0; i < nstates; i++) { - tF = new_cover(10); - foreach_set(PLA->F, last, p) { - if (setp_implies(present_state_mask, p)) { /* from any state ! */ - if (is_in_set(p, next_state + i)) { - tF = sf_addset(tF, p); - } - } - } - before = tF->count; - if (before > 0) { - tF = fsm_simplify(tF); - /* don't allow the next state to disappear ... */ - foreach_set(tF, last, p) { - set_insert(p, next_state + i); - } - after = tF->count; - F = sf_append(F, tF); - if (verbose_mode) { - printf("# state EVERY to %d, before=%d after=%d\n", - i, before, after); - } - } - } - - - /* - * some 'arcs' may NOT have a next state -- handle these - * we must unravel the present state part - */ - go_nowhere = new_cover(10); - foreach_set(PLA->F, last, p) { - if (setp_disjoint(p, next_state_mask)) { /* no next state !! */ - go_nowhere = sf_addset(go_nowhere, p); - } - } - before = go_nowhere->count; - go_nowhere = unravel_range(go_nowhere, - cube.num_binary_vars, cube.num_binary_vars); - after = go_nowhere->count; - F = sf_append(F, go_nowhere); - if (verbose_mode) { - printf("# state ANY to NOWHERE, before=%d after=%d\n", before, after); - } - - - /* - * minimize cover for all arcs from state #i to state #j - */ - for(i = 0; i < nstates; i++) { - for(j = 0; j < nstates; j++) { - tF = new_cover(10); - foreach_set(PLA->F, last, p) { - /* not EVERY state */ - if (! setp_implies(present_state_mask, p)) { - if (is_in_set(p, present_state + i)) { - if (is_in_set(p, next_state + j)) { - p1 = set_save(p); - set_diff(p1, p1, state_mask); - set_insert(p1, present_state + i); - set_insert(p1, next_state + j); - tF = sf_addset(tF, p1); - set_free(p1); - } - } - } - } - before = tF->count; - if (before > 0) { - tF = fsm_simplify(tF); - /* don't allow the next state to disappear ... */ - foreach_set(tF, last, p) { - set_insert(p, next_state + j); - } - after = tF->count; - F = sf_append(F, tF); - if (verbose_mode) { - printf("# state %d to %d, before=%d after=%d\n", - i, j, before, after); - } - } - } - } - - - free_cube(state_mask); - free_cube(present_state_mask); - free_cube(next_state_mask); - - free_cover(PLA->F); - PLA->F = F; - free_cover(PLA->D); - PLA->D = new_cover(0); - - setdown_cube(); - FREE(cube.part_size); - cube.num_binary_vars = nin; - cube.num_vars = nin + 3; - cube.part_size = ALLOC(int, cube.num_vars); - cube.part_size[cube.num_binary_vars] = nstates; - cube.part_size[cube.num_binary_vars+1] = nstates; - cube.part_size[cube.num_binary_vars+2] = nout - nstates; - cube_setup(); - - foreach_set(PLA->F, last, p) { - kiss_print_cube(stdout, PLA, p, "~1"); - } -} diff --git a/src/misc/espresso/indep.c b/src/misc/espresso/indep.c deleted file mode 100644 index 10b363a0..00000000 --- a/src/misc/espresso/indep.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "mincov_int.h" - -static sm_matrix *build_intersection_matrix(); - - -#if 0 -/* - * verify that all rows in 'indep' are actually independent ! - */ -static int -verify_indep_set(A, indep) -sm_matrix *A; -sm_row *indep; -{ - register sm_row *prow, *prow1; - register sm_element *p, *p1; - - for(p = indep->first_col; p != 0; p = p->next_col) { - prow = sm_get_row(A, p->col_num); - for(p1 = p->next_col; p1 != 0; p1 = p1->next_col) { - prow1 = sm_get_row(A, p1->col_num); - if (sm_row_intersects(prow, prow1)) { - return 0; - } - } - } - return 1; -} -#endif - -solution_t * -sm_maximal_independent_set(A, weight) -sm_matrix *A; -int *weight; -{ - register sm_row *best_row, *prow; - register sm_element *p; - int least_weight; - sm_row *save; - sm_matrix *B; - solution_t *indep; - - indep = solution_alloc(); - B = build_intersection_matrix(A); - - while (B->nrows > 0) { - /* Find the row which is disjoint from a maximum number of rows */ - best_row = B->first_row; - for(prow = B->first_row->next_row; prow != 0; prow = prow->next_row) { - if (prow->length < best_row->length) { - best_row = prow; - } - } - - /* Find which element in this row has least weight */ - if (weight == NIL(int)) { - least_weight = 1; - } else { - prow = sm_get_row(A, best_row->row_num); - least_weight = weight[prow->first_col->col_num]; - for(p = prow->first_col->next_col; p != 0; p = p->next_col) { - if (weight[p->col_num] < least_weight) { - least_weight = weight[p->col_num]; - } - } - } - indep->cost += least_weight; - (void) sm_row_insert(indep->row, best_row->row_num); - - /* Discard the rows which intersect this row */ - save = sm_row_dup(best_row); - for(p = save->first_col; p != 0; p = p->next_col) { - sm_delrow(B, p->col_num); - sm_delcol(B, p->col_num); - } - sm_row_free(save); - } - - sm_free(B); - -/* - if (! verify_indep_set(A, indep->row)) { - fail("sm_maximal_independent_set: row set is not independent"); - } -*/ - return indep; -} - -static sm_matrix * -build_intersection_matrix(A) -sm_matrix *A; -{ - register sm_row *prow, *prow1; - register sm_element *p, *p1; - register sm_col *pcol; - sm_matrix *B; - - /* Build row-intersection matrix */ - B = sm_alloc(); - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - - /* Clear flags on all rows we can reach from row 'prow' */ - for(p = prow->first_col; p != 0; p = p->next_col) { - pcol = sm_get_col(A, p->col_num); - for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) { - prow1 = sm_get_row(A, p1->row_num); - prow1->flag = 0; - } - } - - /* Now record which rows can be reached */ - for(p = prow->first_col; p != 0; p = p->next_col) { - pcol = sm_get_col(A, p->col_num); - for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) { - prow1 = sm_get_row(A, p1->row_num); - if (! prow1->flag) { - prow1->flag = 1; - (void) sm_insert(B, prow->row_num, prow1->row_num); - } - } - } - } - - return B; -} diff --git a/src/misc/espresso/irred.c b/src/misc/espresso/irred.c deleted file mode 100644 index 384e698f..00000000 --- a/src/misc/espresso/irred.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - -static void fcube_is_covered(); -static void ftautology(); -static bool ftaut_special_cases(); - - -static int Rp_current; - -/* - * irredundant -- Return a minimal subset of F - */ - -pcover -irredundant(F, D) -pcover F, D; -{ - mark_irredundant(F, D); - return sf_inactive(F); -} - - -/* - * mark_irredundant -- find redundant cubes, and mark them "INACTIVE" - */ - -void -mark_irredundant(F, D) -pcover F, D; -{ - pcover E, Rt, Rp; - pset p, p1, last; - sm_matrix *table; - sm_row *cover; - sm_element *pe; - - /* extract a minimum cover */ - irred_split_cover(F, D, &E, &Rt, &Rp); - table = irred_derive_table(D, E, Rp); - cover = sm_minimum_cover(table, NIL(int), /* heuristic */ 1, /* debug */ 0); - - /* mark the cubes for the result */ - foreach_set(F, last, p) { - RESET(p, ACTIVE); - RESET(p, RELESSEN); - } - foreach_set(E, last, p) { - p1 = GETSET(F, SIZE(p)); - assert(setp_equal(p1, p)); - SET(p1, ACTIVE); - SET(p1, RELESSEN); /* for essen(), mark as rel. ess. */ - } - sm_foreach_row_element(cover, pe) { - p1 = GETSET(F, pe->col_num); - SET(p1, ACTIVE); - } - - if (debug & IRRED) { - printf("# IRRED: F=%d E=%d R=%d Rt=%d Rp=%d Rc=%d Final=%d Bound=%d\n", - F->count, E->count, Rt->count+Rp->count, Rt->count, Rp->count, - cover->length, E->count + cover->length, 0); - } - - free_cover(E); - free_cover(Rt); - free_cover(Rp); - sm_free(table); - sm_row_free(cover); -} - -/* - * irred_split_cover -- find E, Rt, and Rp from the cover F, D - * - * E -- relatively essential cubes - * Rt -- totally redundant cubes - * Rp -- partially redundant cubes - */ - -void -irred_split_cover(F, D, E, Rt, Rp) -pcover F, D; -pcover *E, *Rt, *Rp; -{ - register pcube p, last; - register int index; - pcover R; - pcube *FD, *ED; - - /* number the cubes of F -- these numbers track into E, Rp, Rt, etc. */ - index = 0; - foreach_set(F, last, p) { - PUTSIZE(p, index); - index++; - } - - *E = new_cover(10); - *Rt = new_cover(10); - *Rp = new_cover(10); - R = new_cover(10); - - /* Split F into E and R */ - FD = cube2list(F, D); - foreach_set(F, last, p) { - if (cube_is_covered(FD, p)) { - R = sf_addset(R, p); - } else { - *E = sf_addset(*E, p); - } - if (debug & IRRED1) { - (void) printf("IRRED1: zr=%d ze=%d to-go=%d time=%s\n", - R->count, (*E)->count, F->count - (R->count + (*E)->count), - print_time(ptime())); - } - } - free_cubelist(FD); - - /* Split R into Rt and Rp */ - ED = cube2list(*E, D); - foreach_set(R, last, p) { - if (cube_is_covered(ED, p)) { - *Rt = sf_addset(*Rt, p); - } else { - *Rp = sf_addset(*Rp, p); - } - if (debug & IRRED1) { - (void) printf("IRRED1: zr=%d zrt=%d to-go=%d time=%s\n", - (*Rp)->count, (*Rt)->count, - R->count - ((*Rp)->count +(*Rt)->count), print_time(ptime())); - } - } - free_cubelist(ED); - - free_cover(R); -} - -/* - * irred_derive_table -- given the covers D, E and the set of - * partially redundant primes Rp, build a covering table showing - * possible selections of primes to cover Rp. - */ - -sm_matrix * -irred_derive_table(D, E, Rp) -pcover D, E, Rp; -{ - register pcube last, p, *list; - sm_matrix *table; - int size_last_dominance, i; - - /* Mark each cube in DE as not part of the redundant set */ - foreach_set(D, last, p) { - RESET(p, REDUND); - } - foreach_set(E, last, p) { - RESET(p, REDUND); - } - - /* Mark each cube in Rp as partially redundant */ - foreach_set(Rp, last, p) { - SET(p, REDUND); /* belongs to redundant set */ - } - - /* For each cube in Rp, find ways to cover its minterms */ - list = cube3list(D, E, Rp); - table = sm_alloc(); - size_last_dominance = 0; - i = 0; - foreach_set(Rp, last, p) { - Rp_current = SIZE(p); - fcube_is_covered(list, p, table); - RESET(p, REDUND); /* can now consider this cube redundant */ - if (debug & IRRED1) { - (void) printf("IRRED1: %d of %d to-go=%d, table=%dx%d time=%s\n", - i, Rp->count, Rp->count - i, - table->nrows, table->ncols, print_time(ptime())); - } - /* try to keep memory limits down by reducing table as we go along */ - if (table->nrows - size_last_dominance > 1000) { - (void) sm_row_dominance(table); - size_last_dominance = table->nrows; - if (debug & IRRED1) { - (void) printf("IRRED1: delete redundant rows, now %dx%d\n", - table->nrows, table->ncols); - } - } - i++; - } - free_cubelist(list); - - return table; -} - -/* cube_is_covered -- determine if a cubelist "covers" a single cube */ -bool -cube_is_covered(T, c) -pcube *T, c; -{ - return tautology(cofactor(T,c)); -} - - - -/* tautology -- answer the tautology question for T */ -bool -tautology(T) -pcube *T; /* T will be disposed of */ -{ - register pcube cl, cr; - register int best, result; - static int taut_level = 0; - - if (debug & TAUT) { - debug_print(T, "TAUTOLOGY", taut_level++); - } - - if ((result = taut_special_cases(T)) == MAYBE) { - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, TAUT); - result = tautology(scofactor(T, cl, best)) && - tautology(scofactor(T, cr, best)); - free_cubelist(T); - free_cube(cl); - free_cube(cr); - } - - if (debug & TAUT) { - printf("exit TAUTOLOGY[%d]: %s\n", --taut_level, print_bool(result)); - } - return result; -} - -/* - * taut_special_cases -- check special cases for tautology - */ - -bool -taut_special_cases(T) -pcube *T; /* will be disposed if answer is determined */ -{ - register pcube *T1, *Tsave, p, ceil=cube.temp[0], temp=cube.temp[1]; - pcube *A, *B; - int var; - - /* Check for a row of all 1's which implies tautology */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, T[0])) { - free_cubelist(T); - return TRUE; - } - } - - /* Check for a column of all 0's which implies no tautology */ -start: - INLINEset_copy(ceil, T[0]); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - free_cubelist(T); - return FALSE; - } - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If function is unate (and no row of all 1's), then no tautology */ - if (cdata.vars_unate == cdata.vars_active) { - free_cubelist(T); - return FALSE; - - /* If active in a single variable (and no column of 0's) then tautology */ - } else if (cdata.vars_active == 1) { - free_cubelist(T); - return TRUE; - - /* Check for unate variables, and reduce cover if there are any */ - } else if (cdata.vars_unate != 0) { - /* Form a cube "ceil" with full variables in the unate variables */ - (void) set_copy(ceil, cube.emptyset); - for(var = 0; var < cube.num_vars; var++) { - if (cdata.is_unate[var]) { - INLINEset_or(ceil, ceil, cube.var_mask[var]); - } - } - - /* Save only those cubes that are "full" in all unate variables */ - for(Tsave = T1 = T+2; (p = *T1++) != 0; ) { - if (setp_implies(ceil, set_or(temp, p, T[0]))) { - *Tsave++ = p; - } - } - *Tsave++ = NULL; - T[1] = (pcube) Tsave; - - if (debug & TAUT) { - printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n", - cdata.vars_unate, CUBELISTSIZE(T)); - } - goto start; - - /* Check for component reduction */ - } else if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T) / 2) { - if (cubelist_partition(T, &A, &B, debug & TAUT) == 0) { - return MAYBE; - } else { - free_cubelist(T); - if (tautology(A)) { - free_cubelist(B); - return TRUE; - } else { - return tautology(B); - } - } - } - - /* We tried as hard as we could, but must recurse from here on */ - return MAYBE; -} - -/* fcube_is_covered -- determine exactly how a cubelist "covers" a cube */ -static void -fcube_is_covered(T, c, table) -pcube *T, c; -sm_matrix *table; -{ - ftautology(cofactor(T,c), table); -} - - -/* ftautology -- find ways to make a tautology */ -static void -ftautology(T, table) -pcube *T; /* T will be disposed of */ -sm_matrix *table; -{ - register pcube cl, cr; - register int best; - static int ftaut_level = 0; - - if (debug & TAUT) { - debug_print(T, "FIND_TAUTOLOGY", ftaut_level++); - } - - if (ftaut_special_cases(T, table) == MAYBE) { - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, TAUT); - - ftautology(scofactor(T, cl, best), table); - ftautology(scofactor(T, cr, best), table); - - free_cubelist(T); - free_cube(cl); - free_cube(cr); - } - - if (debug & TAUT) { - (void) printf("exit FIND_TAUTOLOGY[%d]: table is %d by %d\n", - --ftaut_level, table->nrows, table->ncols); - } -} - -static bool -ftaut_special_cases(T, table) -pcube *T; /* will be disposed if answer is determined */ -sm_matrix *table; -{ - register pcube *T1, *Tsave, p, temp = cube.temp[0], ceil = cube.temp[1]; - int var, rownum; - - /* Check for a row of all 1's in the essential cubes */ - for(T1 = T+2; (p = *T1++) != 0; ) { - if (! TESTP(p, REDUND)) { - if (full_row(p, T[0])) { - /* subspace is covered by essentials -- no new rows for table */ - free_cubelist(T); - return TRUE; - } - } - } - - /* Collect column counts, determine unate variables, etc. */ -start: - massive_count(T); - - /* If function is unate, find the rows of all 1's */ - if (cdata.vars_unate == cdata.vars_active) { - /* find which nonessentials cover this subspace */ - rownum = table->last_row ? table->last_row->row_num+1 : 0; - (void) sm_insert(table, rownum, Rp_current); - for(T1 = T+2; (p = *T1++) != 0; ) { - if (TESTP(p, REDUND)) { - /* See if a redundant cube covers this leaf */ - if (full_row(p, T[0])) { - (void) sm_insert(table, rownum, (int) SIZE(p)); - } - } - } - free_cubelist(T); - return TRUE; - - /* Perform unate reduction if there are any unate variables */ - } else if (cdata.vars_unate != 0) { - /* Form a cube "ceil" with full variables in the unate variables */ - (void) set_copy(ceil, cube.emptyset); - for(var = 0; var < cube.num_vars; var++) { - if (cdata.is_unate[var]) { - INLINEset_or(ceil, ceil, cube.var_mask[var]); - } - } - - /* Save only those cubes that are "full" in all unate variables */ - for(Tsave = T1 = T+2; (p = *T1++) != 0; ) { - if (setp_implies(ceil, set_or(temp, p, T[0]))) { - *Tsave++ = p; - } - } - *Tsave++ = 0; - T[1] = (pcube) Tsave; - - if (debug & TAUT) { - printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n", - cdata.vars_unate, CUBELISTSIZE(T)); - } - goto start; - } - - /* Not much we can do about it */ - return MAYBE; -} diff --git a/src/misc/espresso/main.c b/src/misc/espresso/main.c deleted file mode 100644 index 0a511c0e..00000000 --- a/src/misc/espresso/main.c +++ /dev/null @@ -1,746 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - * Main driver for espresso - * - * Old style -do xxx, -out xxx, etc. are still supported. - */ - -#include "espresso.h" -#include "main.h" /* table definitions for options */ - -static FILE *last_fp; -static int input_type = FD_type; - - -main(argc, argv) -int argc; -char *argv[]; -{ - int i, j, first, last, strategy, out_type, option; - pPLA PLA, PLA1; - pcover F, Fold, Dold; - pset last1, p; - cost_t cost; - bool error, exact_cover; - long start; - extern char *util_optarg; - extern int util_optind; - - start = ptime(); - - error = FALSE; - init_runtime(); -#ifdef RANDOM - srandom(314973); -#endif - - option = 0; /* default -D: ESPRESSO */ - out_type = F_type; /* default -o: default is ON-set only */ - debug = 0; /* default -d: no debugging info */ - verbose_debug = FALSE; /* default -v: not verbose */ - print_solution = TRUE; /* default -x: print the solution (!) */ - summary = FALSE; /* default -s: no summary */ - trace = FALSE; /* default -t: no trace information */ - strategy = 0; /* default -S: strategy number */ - first = -1; /* default -R: select range */ - last = -1; - remove_essential = TRUE; /* default -e: */ - force_irredundant = TRUE; - unwrap_onset = TRUE; - single_expand = FALSE; - pos = FALSE; - recompute_onset = FALSE; - use_super_gasp = FALSE; - use_random_order = FALSE; - kiss = FALSE; - echo_comments = TRUE; - echo_unknown_commands = TRUE; - exact_cover = FALSE; /* for -qm option, the default */ - - backward_compatibility_hack(&argc, argv, &option, &out_type); - - - /* parse command line options*/ - while ((i = util_getopt(argc, argv, "D:S:de:o:r:stv:x")) != EOF) { - switch(i) { - case 'D': /* -Dcommand invokes a subcommand */ - for(j = 0; option_table[j].name != 0; j++) { - if (strcmp(util_optarg, option_table[j].name) == 0) { - option = j; - break; - } - } - if (option_table[j].name == 0) { - (void) fprintf(stderr, "%s: bad subcommand \"%s\"\n", - argv[0], util_optarg); - exit(1); - } - break; - - case 'o': /* -ooutput selects and output option */ - for(j = 0; pla_types[j].key != 0; j++) { - if (strcmp(util_optarg, pla_types[j].key+1) == 0) { - out_type = pla_types[j].value; - break; - } - } - if (pla_types[j].key == 0) { - (void) fprintf(stderr, "%s: bad output type \"%s\"\n", - argv[0], util_optarg); - exit(1); - } - break; - - case 'e': /* -eespresso selects an option for espresso */ - for(j = 0; esp_opt_table[j].name != 0; j++) { - if (strcmp(util_optarg, esp_opt_table[j].name) == 0) { - *(esp_opt_table[j].variable) = esp_opt_table[j].value; - break; - } - } - if (esp_opt_table[j].name == 0) { - (void) fprintf(stderr, "%s: bad espresso option \"%s\"\n", - argv[0], util_optarg); - exit(1); - } - break; - - case 'd': /* -d turns on (softly) all debug switches */ - debug = debug_table[0].value; - trace = TRUE; - summary = TRUE; - break; - - case 'v': /* -vdebug invokes a debug option */ - verbose_debug = TRUE; - for(j = 0; debug_table[j].name != 0; j++) { - if (strcmp(util_optarg, debug_table[j].name) == 0) { - debug |= debug_table[j].value; - break; - } - } - if (debug_table[j].name == 0) { - (void) fprintf(stderr, "%s: bad debug type \"%s\"\n", - argv[0], util_optarg); - exit(1); - } - break; - - case 't': - trace = TRUE; - break; - - case 's': - summary = TRUE; - break; - - case 'x': /* -x suppress printing of results */ - print_solution = FALSE; - break; - - case 'S': /* -S sets a strategy for several cmds */ - strategy = atoi(util_optarg); - break; - - case 'r': /* -r selects range (outputs or vars) */ - if (sscanf(util_optarg, "%d-%d", &first, &last) < 2) { - (void) fprintf(stderr, "%s: bad output range \"%s\"\n", - argv[0], util_optarg); - exit(1); - } - break; - - default: - usage(); - exit(1); - } - } - - /* provide version information and summaries */ - if (summary || trace) { - /* echo command line and arguments */ - printf("#"); - for(i = 0; i < argc; i++) { - printf(" %s", argv[i]); - } - printf("\n"); - printf("# %s\n", VERSION); - } - - /* the remaining arguments are argv[util_optind ... argc-1] */ - PLA = PLA1 = NIL(PLA_t); - switch(option_table[option].num_plas) { - case 2: - if (util_optind+2 < argc) fatal("trailing arguments on command line"); - getPLA(util_optind++, argc, argv, option, &PLA, out_type); - getPLA(util_optind++, argc, argv, option, &PLA1, out_type); - break; - case 1: - if (util_optind+1 < argc) fatal("trailing arguments on command line"); - getPLA(util_optind++, argc, argv, option, &PLA, out_type); - break; - } - if (util_optind < argc) fatal("trailing arguments on command line"); - - if (summary || trace) { - if (PLA != NIL(PLA_t)) PLA_summary(PLA); - if (PLA1 != NIL(PLA_t)) PLA_summary(PLA1); - } - -/* - * Now a case-statement to decide what to do - */ - - switch(option_table[option].key) { - - -/******************** Espresso operations ********************/ - - case KEY_ESPRESSO: - Fold = sf_save(PLA->F); - PLA->F = espresso(PLA->F, PLA->D, PLA->R); - EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost); - if (error) { - print_solution = FALSE; - PLA->F = Fold; - (void) check_consistency(PLA); - } else { - free_cover(Fold); - } - break; - - case KEY_MANY_ESPRESSO: { - int pla_type; - do { - EXEC(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F); - if (print_solution) { - fprint_pla(stdout, PLA, out_type); - (void) fflush(stdout); - } - pla_type = PLA->pla_type; - free_PLA(PLA); - setdown_cube(); - FREE(cube.part_size); - } while (read_pla(last_fp, TRUE, TRUE, pla_type, &PLA) != EOF); - exit(0); - } - - case KEY_simplify: - EXEC(PLA->F = simplify(cube1list(PLA->F)), "SIMPLIFY ", PLA->F); - break; - - case KEY_so: /* minimize all functions as single-output */ - if (strategy < 0 || strategy > 1) { - strategy = 0; - } - so_espresso(PLA, strategy); - break; - - case KEY_so_both: /* minimize all functions as single-output */ - if (strategy < 0 || strategy > 1) { - strategy = 0; - } - so_both_espresso(PLA, strategy); - break; - - case KEY_expand: /* execute expand */ - EXECUTE(PLA->F=expand(PLA->F,PLA->R,FALSE),EXPAND_TIME, PLA->F, cost); - break; - - case KEY_irred: /* extract minimal irredundant subset */ - EXECUTE(PLA->F = irredundant(PLA->F, PLA->D), IRRED_TIME, PLA->F, cost); - break; - - case KEY_reduce: /* perform reduction */ - EXECUTE(PLA->F = reduce(PLA->F, PLA->D), REDUCE_TIME, PLA->F, cost); - break; - - case KEY_essen: /* check for essential primes */ - foreach_set(PLA->F, last1, p) { - SET(p, RELESSEN); - RESET(p, NONESSEN); - } - EXECUTE(F = essential(&(PLA->F), &(PLA->D)), ESSEN_TIME, PLA->F, cost); - free_cover(F); - break; - - case KEY_super_gasp: - PLA->F = super_gasp(PLA->F, PLA->D, PLA->R, &cost); - break; - - case KEY_gasp: - PLA->F = last_gasp(PLA->F, PLA->D, PLA->R, &cost); - break; - - case KEY_make_sparse: /* make_sparse step of Espresso */ - PLA->F = make_sparse(PLA->F, PLA->D, PLA->R); - break; - - case KEY_exact: - exact_cover = TRUE; - - case KEY_qm: - Fold = sf_save(PLA->F); - PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, exact_cover); - EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost); - if (error) { - print_solution = FALSE; - PLA->F = Fold; - (void) check_consistency(PLA); - } - free_cover(Fold); - break; - - case KEY_primes: /* generate all prime implicants */ - EXEC(PLA->F = primes_consensus(cube2list(PLA->F, PLA->D)), - "PRIMES ", PLA->F); - break; - - case KEY_map: /* print out a Karnaugh map of function */ - map(PLA->F); - print_solution = FALSE; - break; - - - -/******************** Output phase and bit pairing ********************/ - - case KEY_opo: /* sasao output phase assignment */ - phase_assignment(PLA, strategy); - break; - - case KEY_opoall: /* try all phase assignments (!) */ - if (first < 0 || first >= cube.part_size[cube.output]) { - first = 0; - } - if (last < 0 || last >= cube.part_size[cube.output]) { - last = cube.part_size[cube.output] - 1; - } - opoall(PLA, first, last, strategy); - break; - - case KEY_pair: /* find an optimal pairing */ - find_optimal_pairing(PLA, strategy); - break; - - case KEY_pairall: /* try all pairings !! */ - pair_all(PLA, strategy); - break; - - - -/******************** Simple cover operations ********************/ - - case KEY_echo: /* echo the PLA */ - break; - - case KEY_taut: /* tautology check */ - printf("ON-set is%sa tautology\n", - tautology(cube1list(PLA->F)) ? " " : " not "); - print_solution = FALSE; - break; - - case KEY_contain: /* single cube containment */ - PLA->F = sf_contain(PLA->F); - break; - - case KEY_intersect: /* cover intersection */ - PLA->F = cv_intersect(PLA->F, PLA1->F); - break; - - case KEY_union: /* cover union */ - PLA->F = sf_union(PLA->F, PLA1->F); - break; - - case KEY_disjoint: /* make cover disjoint */ - PLA->F = make_disjoint(PLA->F); - break; - - case KEY_dsharp: /* cover disjoint-sharp */ - PLA->F = cv_dsharp(PLA->F, PLA1->F); - break; - - case KEY_sharp: /* cover sharp */ - PLA->F = cv_sharp(PLA->F, PLA1->F); - break; - - case KEY_lexsort: /* lexical sort order */ - PLA->F = lex_sort(PLA->F); - break; - - case KEY_stats: /* print info on size */ - if (! summary) PLA_summary(PLA); - print_solution = FALSE; - break; - - case KEY_minterms: /* explode into minterms */ - if (first < 0 || first >= cube.num_vars) { - first = 0; - } - if (last < 0 || last >= cube.num_vars) { - last = cube.num_vars - 1; - } - PLA->F = sf_dupl(unravel_range(PLA->F, first, last)); - break; - - case KEY_d1merge: /* distance-1 merge */ - if (first < 0 || first >= cube.num_vars) { - first = 0; - } - if (last < 0 || last >= cube.num_vars) { - last = cube.num_vars - 1; - } - for(i = first; i <= last; i++) { - PLA->F = d1merge(PLA->F, i); - } - break; - - case KEY_d1merge_in: /* distance-1 merge inputs only */ - for(i = 0; i < cube.num_binary_vars; i++) { - PLA->F = d1merge(PLA->F, i); - } - break; - - case KEY_PLA_verify: /* check two PLAs for equivalence */ - EXECUTE(error = PLA_verify(PLA, PLA1), VERIFY_TIME, PLA->F, cost); - if (error) { - printf("PLA comparison failed; the PLA's are not equivalent\n"); - exit(1); - } else { - printf("PLA's compared equal\n"); - exit(0); - } - break; /* silly */ - - case KEY_verify: /* check two covers for equivalence */ - Fold = PLA->F; Dold = PLA->D; F = PLA1->F; - EXECUTE(error=verify(F, Fold, Dold), VERIFY_TIME, PLA->F, cost); - if (error) { - printf("PLA comparison failed; the PLA's are not equivalent\n"); - exit(1); - } else { - printf("PLA's compared equal\n"); - exit(0); - } - break; /* silly */ - - case KEY_check: /* check consistency */ - (void) check_consistency(PLA); - print_solution = FALSE; - break; - - case KEY_mapdc: /* compute don't care set */ - map_dcset(PLA); - out_type = FD_type; - break; - - case KEY_equiv: - find_equiv_outputs(PLA); - print_solution = FALSE; - break; - - case KEY_separate: /* remove PLA->D from PLA->F */ - PLA->F = complement(cube2list(PLA->D, PLA->R)); - break; - - case KEY_xor: { - pcover T1 = cv_intersect(PLA->F, PLA1->R); - pcover T2 = cv_intersect(PLA1->F, PLA->R); - free_cover(PLA->F); - PLA->F = sf_contain(sf_join(T1, T2)); - free_cover(T1); - free_cover(T2); - break; - } - - case KEY_fsm: { - disassemble_fsm(PLA, summary); - print_solution = FALSE; - break; - } - - case KEY_test: { - pcover T, E; - T = sf_join(PLA->D, PLA->R); - E = new_cover(10); - sf_free(PLA->F); - EXECUTE(PLA->F = complement(cube1list(T)), COMPL_TIME, PLA->F, cost); - EXECUTE(PLA->F = expand(PLA->F, T, FALSE), EXPAND_TIME, PLA->F, cost); - EXECUTE(PLA->F = irredundant(PLA->F, E), IRRED_TIME, PLA->F, cost); - sf_free(T); - T = sf_join(PLA->F, PLA->R); - EXECUTE(PLA->D = expand(PLA->D, T, FALSE), EXPAND_TIME, PLA->D, cost); - EXECUTE(PLA->D = irredundant(PLA->D, E), IRRED_TIME, PLA->D, cost); - sf_free(T); - sf_free(E); - break; - } - - - } - - /* Print a runtime summary if trace mode enabled */ - if (trace) { - runtime(); - } - - /* Print total runtime */ - if (summary || trace) { - print_trace(PLA->F, option_table[option].name, ptime()-start); - } - - /* Output the solution */ - if (print_solution) { - EXECUTE(fprint_pla(stdout, PLA, out_type), WRITE_TIME, PLA->F, cost); - } - - /* Crash and burn if there was a verify error */ - if (error) { - fatal("cover verification failed"); - } - - /* cleanup all used memory */ - free_PLA(PLA); - FREE(cube.part_size); - setdown_cube(); /* free the cube/cdata structure data */ - sf_cleanup(); /* free unused set structures */ - sm_cleanup(); /* sparse matrix cleanup */ - - exit(0); -} - - -getPLA(opt, argc, argv, option, PLA, out_type) -int opt; -int argc; -char *argv[]; -int option; -pPLA *PLA; -int out_type; -{ - FILE *fp; - int needs_dcset, needs_offset; - char *fname; - - if (opt >= argc) { - fp = stdin; - fname = "(stdin)"; - } else { - fname = argv[opt]; - if (strcmp(fname, "-") == 0) { - fp = stdin; - } else if ((fp = fopen(argv[opt], "r")) == NULL) { - (void) fprintf(stderr, "%s: Unable to open %s\n", argv[0], fname); - exit(1); - } - } - if (option_table[option].key == KEY_echo) { - needs_dcset = (out_type & D_type) != 0; - needs_offset = (out_type & R_type) != 0; - } else { - needs_dcset = option_table[option].needs_dcset; - needs_offset = option_table[option].needs_offset; - } - - if (read_pla(fp, needs_dcset, needs_offset, input_type, PLA) == EOF) { - (void) fprintf(stderr, "%s: Unable to find PLA on file %s\n", argv[0], fname); - exit(1); - } - (*PLA)->filename = util_strsav(fname); - filename = (*PLA)->filename; -/* (void) fclose(fp);*/ -/* hackto support -Dmany */ - last_fp = fp; -} - - -runtime() -{ - int i; - long total = 1, temp; - - for(i = 0; i < TIME_COUNT; i++) { - total += total_time[i]; - } - for(i = 0; i < TIME_COUNT; i++) { - if (total_calls[i] != 0) { - temp = 100 * total_time[i]; - printf("# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n", - total_name[i], total_calls[i], print_time(total_time[i]), - temp/total, (10 * (temp%total)) / total); - } - } -} - - -init_runtime() -{ - total_name[READ_TIME] = "READ "; - total_name[WRITE_TIME] = "WRITE "; - total_name[COMPL_TIME] = "COMPL "; - total_name[REDUCE_TIME] = "REDUCE "; - total_name[EXPAND_TIME] = "EXPAND "; - total_name[ESSEN_TIME] = "ESSEN "; - total_name[IRRED_TIME] = "IRRED "; - total_name[GREDUCE_TIME] = "REDUCE_GASP"; - total_name[GEXPAND_TIME] = "EXPAND_GASP"; - total_name[GIRRED_TIME] = "IRRED_GASP "; - total_name[MV_REDUCE_TIME] ="MV_REDUCE "; - total_name[RAISE_IN_TIME] = "RAISE_IN "; - total_name[VERIFY_TIME] = "VERIFY "; - total_name[PRIMES_TIME] = "PRIMES "; - total_name[MINCOV_TIME] = "MINCOV "; -} - - -subcommands() -{ - int i, col; - printf(" "); - col = 16; - for(i = 0; option_table[i].name != 0; i++) { - if ((col + strlen(option_table[i].name) + 1) > 76) { - printf(",\n "); - col = 16; - } else if (i != 0) { - printf(", "); - } - printf("%s", option_table[i].name); - col += strlen(option_table[i].name) + 2; - } - printf("\n"); -} - - -usage() -{ - printf("%s\n\n", VERSION); - printf("SYNOPSIS: espresso [options] [file]\n\n"); - printf(" -d Enable debugging\n"); - printf(" -e[opt] Select espresso option:\n"); - printf(" fast, ness, nirr, nunwrap, onset, pos, strong,\n"); - printf(" eat, eatdots, kiss, random\n"); - printf(" -o[type] Select output format:\n"); - printf(" f, fd, fr, fdr, pleasure, eqntott, kiss, cons\n"); - printf(" -rn-m Select range for subcommands:\n"); - printf(" d1merge: first and last variables (0 ... m-1)\n"); - printf(" minterms: first and last variables (0 ... m-1)\n"); - printf(" opoall: first and last outputs (0 ... m-1)\n"); - printf(" -s Provide short execution summary\n"); - printf(" -t Provide longer execution trace\n"); - printf(" -x Suppress printing of solution\n"); - printf(" -v[type] Verbose debugging detail (-v '' for all)\n"); - printf(" -D[cmd] Execute subcommand 'cmd':\n"); - subcommands(); - printf(" -Sn Select strategy for subcommands:\n"); - printf(" opo: bit2=exact bit1=repeated bit0=skip sparse\n"); - printf(" opoall: 0=minimize, 1=exact\n"); - printf(" pair: 0=algebraic, 1=strongd, 2=espresso, 3=exact\n"); - printf(" pairall: 0=minimize, 1=exact, 2=opo\n"); - printf(" so_espresso: 0=minimize, 1=exact\n"); - printf(" so_both: 0=minimize, 1=exact\n"); -} - -/* - * Hack for backward compatibility (ACK! ) - */ - -backward_compatibility_hack(argc, argv, option, out_type) -int *argc; -char **argv; -int *option; -int *out_type; -{ - int i, j; - - /* Scan the argument list for something to do (default is ESPRESSO) */ - *option = 0; - for(i = 1; i < (*argc)-1; i++) { - if (strcmp(argv[i], "-do") == 0) { - for(j = 0; option_table[j].name != 0; j++) - if (strcmp(argv[i+1], option_table[j].name) == 0) { - *option = j; - delete_arg(argc, argv, i+1); - delete_arg(argc, argv, i); - break; - } - if (option_table[j].name == 0) { - (void) fprintf(stderr, - "espresso: bad keyword \"%s\" following -do\n",argv[i+1]); - exit(1); - } - break; - } - } - - for(i = 1; i < (*argc)-1; i++) { - if (strcmp(argv[i], "-out") == 0) { - for(j = 0; pla_types[j].key != 0; j++) - if (strcmp(pla_types[j].key+1, argv[i+1]) == 0) { - *out_type = pla_types[j].value; - delete_arg(argc, argv, i+1); - delete_arg(argc, argv, i); - break; - } - if (pla_types[j].key == 0) { - (void) fprintf(stderr, - "espresso: bad keyword \"%s\" following -out\n",argv[i+1]); - exit(1); - } - break; - } - } - - for(i = 1; i < (*argc); i++) { - if (argv[i][0] == '-') { - for(j = 0; esp_opt_table[j].name != 0; j++) { - if (strcmp(argv[i]+1, esp_opt_table[j].name) == 0) { - delete_arg(argc, argv, i); - *(esp_opt_table[j].variable) = esp_opt_table[j].value; - break; - } - } - } - } - - if (check_arg(argc, argv, "-fdr")) input_type = FDR_type; - if (check_arg(argc, argv, "-fr")) input_type = FR_type; - if (check_arg(argc, argv, "-f")) input_type = F_type; -} - - -/* delete_arg -- delete an argument from the argument list */ -delete_arg(argc, argv, num) -int *argc, num; -register char *argv[]; -{ - register int i; - (*argc)--; - for(i = num; i < *argc; i++) { - argv[i] = argv[i+1]; - } -} - - -/* check_arg -- scan argv for an argument, and return TRUE if found */ -bool check_arg(argc, argv, s) -int *argc; -register char *argv[], *s; -{ - register int i; - for(i = 1; i < *argc; i++) { - if (strcmp(argv[i], s) == 0) { - delete_arg(argc, argv, i); - return TRUE; - } - } - return FALSE; -} diff --git a/src/misc/espresso/main.h b/src/misc/espresso/main.h deleted file mode 100644 index 00657f39..00000000 --- a/src/misc/espresso/main.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -enum keys { - KEY_ESPRESSO, KEY_PLA_verify, KEY_check, KEY_contain, KEY_d1merge, - KEY_disjoint, KEY_dsharp, KEY_echo, KEY_essen, KEY_exact, KEY_expand, - KEY_gasp, KEY_intersect, KEY_irred, KEY_lexsort, KEY_make_sparse, - KEY_map, KEY_mapdc, KEY_minterms, KEY_opo, KEY_opoall, - KEY_pair, KEY_pairall, KEY_primes, KEY_qm, KEY_reduce, KEY_sharp, - KEY_simplify, KEY_so, KEY_so_both, KEY_stats, KEY_super_gasp, KEY_taut, - KEY_test, KEY_equiv, KEY_union, KEY_verify, KEY_MANY_ESPRESSO, - KEY_separate, KEY_xor, KEY_d1merge_in, KEY_fsm, - KEY_unknown -}; - -/* Lookup table for program options */ -struct { - char *name; - enum keys key; - int num_plas; - bool needs_offset; - bool needs_dcset; -} option_table [] = { - /* ways to minimize functions */ - "ESPRESSO", KEY_ESPRESSO, 1, TRUE, TRUE, /* must be first */ - "many", KEY_MANY_ESPRESSO, 1, TRUE, TRUE, - "exact", KEY_exact, 1, TRUE, TRUE, - "qm", KEY_qm, 1, TRUE, TRUE, - "single_output", KEY_so, 1, TRUE, TRUE, - "so", KEY_so, 1, TRUE, TRUE, - "so_both", KEY_so_both, 1, TRUE, TRUE, - "simplify", KEY_simplify, 1, FALSE, FALSE, - "echo", KEY_echo, 1, FALSE, FALSE, - - /* output phase assignment and assignment of inputs to two-bit decoders */ - "opo", KEY_opo, 1, TRUE, TRUE, - "opoall", KEY_opoall, 1, TRUE, TRUE, - "pair", KEY_pair, 1, TRUE, TRUE, - "pairall", KEY_pairall, 1, TRUE, TRUE, - - /* Ways to check covers */ - "check", KEY_check, 1, TRUE, TRUE, - "stats", KEY_stats, 1, FALSE, FALSE, - "verify", KEY_verify, 2, FALSE, TRUE, - "PLAverify", KEY_PLA_verify, 2, FALSE, TRUE, - - /* hacks */ - "equiv", KEY_equiv, 1, TRUE, TRUE, - "map", KEY_map, 1, FALSE, FALSE, - "mapdc", KEY_mapdc, 1, FALSE, FALSE, - "fsm", KEY_fsm, 1, FALSE, TRUE, - - /* the basic boolean operations on covers */ - "contain", KEY_contain, 1, FALSE, FALSE, - "d1merge", KEY_d1merge, 1, FALSE, FALSE, - "d1merge_in", KEY_d1merge_in, 1, FALSE, FALSE, - "disjoint", KEY_disjoint, 1, TRUE, FALSE, - "dsharp", KEY_dsharp, 2, FALSE, FALSE, - "intersect", KEY_intersect, 2, FALSE, FALSE, - "minterms", KEY_minterms, 1, FALSE, FALSE, - "primes", KEY_primes, 1, FALSE, TRUE, - "separate", KEY_separate, 1, TRUE, TRUE, - "sharp", KEY_sharp, 2, FALSE, FALSE, - "union", KEY_union, 2, FALSE, FALSE, - "xor", KEY_xor, 2, TRUE, TRUE, - - /* debugging only -- call each step of the espresso algorithm */ - "essen", KEY_essen, 1, FALSE, TRUE, - "expand", KEY_expand, 1, TRUE, FALSE, - "gasp", KEY_gasp, 1, TRUE, TRUE, - "irred", KEY_irred, 1, FALSE, TRUE, - "make_sparse", KEY_make_sparse, 1, TRUE, TRUE, - "reduce", KEY_reduce, 1, FALSE, TRUE, - "taut", KEY_taut, 1, FALSE, FALSE, - "super_gasp", KEY_super_gasp, 1, TRUE, TRUE, - "lexsort", KEY_lexsort, 1, FALSE, FALSE, - "test", KEY_test, 1, TRUE, TRUE, - 0, KEY_unknown, 0, FALSE, FALSE /* must be last */ -}; - - -struct { - char *name; - int value; -} debug_table[] = { - "", EXPAND + ESSEN + IRRED + REDUCE + SPARSE + GASP + SHARP + MINCOV, - "compl", COMPL, "essen", ESSEN, - "expand", EXPAND, "expand1", EXPAND1|EXPAND, - "irred", IRRED, "irred1", IRRED1|IRRED, - "reduce", REDUCE, "reduce1", REDUCE1|REDUCE, - "mincov", MINCOV, "mincov1", MINCOV1|MINCOV, - "sparse", SPARSE, "sharp", SHARP, - "taut", TAUT, "gasp", GASP, - "exact", EXACT, - 0, -}; - - -struct { - char *name; - int *variable; - int value; -} esp_opt_table[] = { - "eat", &echo_comments, FALSE, - "eatdots", &echo_unknown_commands, FALSE, - "fast", &single_expand, TRUE, - "kiss", &kiss, TRUE, - "ness", &remove_essential, FALSE, - "nirr", &force_irredundant, FALSE, - "nunwrap", &unwrap_onset, FALSE, - "onset", &recompute_onset, TRUE, - "pos", &pos, TRUE, - "random", &use_random_order, TRUE, - "strong", &use_super_gasp, TRUE, - 0, -}; diff --git a/src/misc/espresso/map.c b/src/misc/espresso/map.c deleted file mode 100644 index 5ccf264c..00000000 --- a/src/misc/espresso/map.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - -static pcube Gcube; -static pset Gminterm; - -pset minterms(T) -pcover T; -{ - int size, var; - register pcube last; - - size = 1; - for(var = 0; var < cube.num_vars; var++) - size *= cube.part_size[var]; - Gminterm = set_new(size); - - foreach_set(T, last, Gcube) - explode(cube.num_vars-1, 0); - - return Gminterm; -} - - -void explode(var, z) -int var, z; -{ - int i, last = cube.last_part[var]; - for(i=cube.first_part[var], z *= cube.part_size[var]; i<=last; i++, z++) - if (is_in_set(Gcube, i)) - if (var == 0) - set_insert(Gminterm, z); - else - explode(var-1, z); -} - - -static int mapindex[16][16] = { - 0, 1, 3, 2, 16, 17, 19, 18, 80, 81, 83, 82, 64, 65, 67, 66, - 4, 5, 7, 6, 20, 21, 23, 22, 84, 85, 87, 86, 68, 69, 71, 70, - 12, 13, 15, 14, 28, 29, 31, 30, 92, 93, 95, 94, 76, 77, 79, 78, - 8, 9, 11, 10, 24, 25, 27, 26, 88, 89, 91, 90, 72, 73, 75, 74, - - 32, 33, 35, 34, 48, 49, 51, 50, 112,113,115,114, 96, 97, 99, 98, - 36, 37, 39, 38, 52, 53, 55, 54, 116,117,119,118, 100,101,103,102, - 44, 45, 47, 46, 60, 61, 63, 62, 124,125,127,126, 108,109,111,110, - 40, 41, 43, 42, 56, 57, 59, 58, 120,121,123,122, 104,105,107,106, - - - 160,161,163,162, 176,177,179,178, 240,241,243,242, 224,225,227,226, - 164,165,167,166, 180,181,183,182, 244,245,247,246, 228,229,231,230, - 172,173,175,174, 188,189,191,190, 252,253,255,254, 236,237,239,238, - 168,169,171,170, 184,185,187,186, 248,249,251,250, 232,233,235,234, - - 128,129,131,130, 144,145,147,146, 208,209,211,210, 192,193,195,194, - 132,133,135,134, 148,149,151,150, 212,213,215,214, 196,197,199,198, - 140,141,143,142, 156,157,159,158, 220,221,223,222, 204,205,207,206, - 136,137,139,138, 152,153,155,154, 216,217,219,218, 200,201,203,202 -}; - -#define POWER2(n) (1 << n) -void map(T) -pcover T; -{ - int j, k, l, other_input_offset, output_offset, outnum, ind; - int largest_input_ind, numout; - char c; - pset m; - bool some_output; - - m = minterms(T); - largest_input_ind = POWER2(cube.num_binary_vars); - numout = cube.part_size[cube.num_vars-1]; - - for(outnum = 0; outnum < numout; outnum++) { - output_offset = outnum * largest_input_ind; - printf("\n\nOutput space # %d\n", outnum); - for(l = 0; l <= MAX(cube.num_binary_vars - 8, 0); l++) { - other_input_offset = l * 256; - for(k = 0; k < 16; k++) { - some_output = FALSE; - for(j = 0; j < 16; j++) { - ind = mapindex[k][j] + other_input_offset; - if (ind < largest_input_ind) { - c = is_in_set(m, ind+output_offset) ? '1' : '.'; - putchar(c); - some_output = TRUE; - } - if ((j+1)%4 == 0) - putchar(' '); - if ((j+1)%8 == 0) - printf(" "); - } - if (some_output) - putchar('\n'); - if ((k+1)%4 == 0) { - if (k != 15 && mapindex[k+1][0] >= largest_input_ind) - break; - putchar('\n'); - } - if ((k+1)%8 == 0) - putchar('\n'); - } - } - } - set_free(m); -} diff --git a/src/misc/espresso/matrix.c b/src/misc/espresso/matrix.c deleted file mode 100644 index 747fe54f..00000000 --- a/src/misc/espresso/matrix.c +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -//#include "port.h" -#include "sparse_int.h" - -/* - * free-lists are only used if 'FAST_AND_LOOSE' is set; this is because - * we lose the debugging capability of libmm_t which trashes objects when - * they are free'd. However, FAST_AND_LOOSE is much faster if matrices - * are created and freed frequently. - */ - -#ifdef FAST_AND_LOOSE -sm_element *sm_element_freelist; -sm_row *sm_row_freelist; -sm_col *sm_col_freelist; -#endif - - -sm_matrix * -sm_alloc() -{ - register sm_matrix *A; - - A = ALLOC(sm_matrix, 1); - A->rows = NIL(sm_row *); - A->cols = NIL(sm_col *); - A->nrows = A->ncols = 0; - A->rows_size = A->cols_size = 0; - A->first_row = A->last_row = NIL(sm_row); - A->first_col = A->last_col = NIL(sm_col); - A->user_word = NIL(char); /* for our user ... */ - return A; -} - - -sm_matrix * -sm_alloc_size(row, col) -int row, col; -{ - register sm_matrix *A; - - A = sm_alloc(); - sm_resize(A, row, col); - return A; -} - - -void -sm_free(A) -sm_matrix *A; -{ -#ifdef FAST_AND_LOOSE - register sm_row *prow; - - if (A->first_row != 0) { - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - /* add the elements to the free list of elements */ - prow->last_col->next_col = sm_element_freelist; - sm_element_freelist = prow->first_col; - } - - /* Add the linked list of rows to the row-free-list */ - A->last_row->next_row = sm_row_freelist; - sm_row_freelist = A->first_row; - - /* Add the linked list of cols to the col-free-list */ - A->last_col->next_col = sm_col_freelist; - sm_col_freelist = A->first_col; - } -#else - register sm_row *prow, *pnext_row; - register sm_col *pcol, *pnext_col; - - for(prow = A->first_row; prow != 0; prow = pnext_row) { - pnext_row = prow->next_row; - sm_row_free(prow); - } - for(pcol = A->first_col; pcol != 0; pcol = pnext_col) { - pnext_col = pcol->next_col; - pcol->first_row = pcol->last_row = NIL(sm_element); - sm_col_free(pcol); - } -#endif - - /* Free the arrays to map row/col numbers into pointers */ - FREE(A->rows); - FREE(A->cols); - FREE(A); -} - - -sm_matrix * -sm_dup(A) -sm_matrix *A; -{ - register sm_row *prow; - register sm_element *p; - register sm_matrix *B; - - B = sm_alloc(); - if (A->last_row != 0) { - sm_resize(B, A->last_row->row_num, A->last_col->col_num); - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) sm_insert(B, p->row_num, p->col_num); - } - } - } - return B; -} - - -void -sm_resize(A, row, col) -register sm_matrix *A; -int row, col; -{ - register int i, new_size; - - if (row >= A->rows_size) { - new_size = MAX(A->rows_size*2, row+1); - A->rows = REALLOC(sm_row *, A->rows, new_size); - for(i = A->rows_size; i < new_size; i++) { - A->rows[i] = NIL(sm_row); - } - A->rows_size = new_size; - } - - if (col >= A->cols_size) { - new_size = MAX(A->cols_size*2, col+1); - A->cols = REALLOC(sm_col *, A->cols, new_size); - for(i = A->cols_size; i < new_size; i++) { - A->cols[i] = NIL(sm_col); - } - A->cols_size = new_size; - } -} - - -/* - * insert -- insert a value into the matrix - */ -sm_element * -sm_insert(A, row, col) -register sm_matrix *A; -register int row, col; -{ - register sm_row *prow; - register sm_col *pcol; - register sm_element *element; - sm_element *save_element; - - if (row >= A->rows_size || col >= A->cols_size) { - sm_resize(A, row, col); - } - - prow = A->rows[row]; - if (prow == NIL(sm_row)) { - prow = A->rows[row] = sm_row_alloc(); - prow->row_num = row; - sorted_insert(sm_row, A->first_row, A->last_row, A->nrows, - next_row, prev_row, row_num, row, prow); - } - - pcol = A->cols[col]; - if (pcol == NIL(sm_col)) { - pcol = A->cols[col] = sm_col_alloc(); - pcol->col_num = col; - sorted_insert(sm_col, A->first_col, A->last_col, A->ncols, - next_col, prev_col, col_num, col, pcol); - } - - /* get a new item, save its address */ - sm_element_alloc(element); - save_element = element; - - /* insert it into the row list */ - sorted_insert(sm_element, prow->first_col, prow->last_col, - prow->length, next_col, prev_col, col_num, col, element); - - /* if it was used, also insert it into the column list */ - if (element == save_element) { - sorted_insert(sm_element, pcol->first_row, pcol->last_row, - pcol->length, next_row, prev_row, row_num, row, element); - } else { - /* otherwise, it was already in matrix -- free element we allocated */ - sm_element_free(save_element); - } - return element; -} - - -sm_element * -sm_find(A, rownum, colnum) -sm_matrix *A; -int rownum, colnum; -{ - sm_row *prow; - sm_col *pcol; - - prow = sm_get_row(A, rownum); - if (prow == NIL(sm_row)) { - return NIL(sm_element); - } else { - pcol = sm_get_col(A, colnum); - if (pcol == NIL(sm_col)) { - return NIL(sm_element); - } - if (prow->length < pcol->length) { - return sm_row_find(prow, colnum); - } else { - return sm_col_find(pcol, rownum); - } - } -} - - -void -sm_remove(A, rownum, colnum) -sm_matrix *A; -int rownum, colnum; -{ - sm_remove_element(A, sm_find(A, rownum, colnum)); -} - - - -void -sm_remove_element(A, p) -register sm_matrix *A; -register sm_element *p; -{ - register sm_row *prow; - register sm_col *pcol; - - if (p == 0) return; - - /* Unlink the element from its row */ - prow = sm_get_row(A, p->row_num); - dll_unlink(p, prow->first_col, prow->last_col, - next_col, prev_col, prow->length); - - /* if no more elements in the row, discard the row header */ - if (prow->first_col == NIL(sm_element)) { - sm_delrow(A, p->row_num); - } - - /* Unlink the element from its column */ - pcol = sm_get_col(A, p->col_num); - dll_unlink(p, pcol->first_row, pcol->last_row, - next_row, prev_row, pcol->length); - - /* if no more elements in the column, discard the column header */ - if (pcol->first_row == NIL(sm_element)) { - sm_delcol(A, p->col_num); - } - - sm_element_free(p); -} - -void -sm_delrow(A, i) -sm_matrix *A; -int i; -{ - register sm_element *p, *pnext; - sm_col *pcol; - sm_row *prow; - - prow = sm_get_row(A, i); - if (prow != NIL(sm_row)) { - /* walk across the row */ - for(p = prow->first_col; p != 0; p = pnext) { - pnext = p->next_col; - - /* unlink the item from the column (and delete it) */ - pcol = sm_get_col(A, p->col_num); - sm_col_remove_element(pcol, p); - - /* discard the column if it is now empty */ - if (pcol->first_row == NIL(sm_element)) { - sm_delcol(A, pcol->col_num); - } - } - - /* discard the row -- we already threw away the elements */ - A->rows[i] = NIL(sm_row); - dll_unlink(prow, A->first_row, A->last_row, - next_row, prev_row, A->nrows); - prow->first_col = prow->last_col = NIL(sm_element); - sm_row_free(prow); - } -} - -void -sm_delcol(A, i) -sm_matrix *A; -int i; -{ - register sm_element *p, *pnext; - sm_row *prow; - sm_col *pcol; - - pcol = sm_get_col(A, i); - if (pcol != NIL(sm_col)) { - /* walk down the column */ - for(p = pcol->first_row; p != 0; p = pnext) { - pnext = p->next_row; - - /* unlink the element from the row (and delete it) */ - prow = sm_get_row(A, p->row_num); - sm_row_remove_element(prow, p); - - /* discard the row if it is now empty */ - if (prow->first_col == NIL(sm_element)) { - sm_delrow(A, prow->row_num); - } - } - - /* discard the column -- we already threw away the elements */ - A->cols[i] = NIL(sm_col); - dll_unlink(pcol, A->first_col, A->last_col, - next_col, prev_col, A->ncols); - pcol->first_row = pcol->last_row = NIL(sm_element); - sm_col_free(pcol); - } -} - -void -sm_copy_row(dest, dest_row, prow) -register sm_matrix *dest; -int dest_row; -sm_row *prow; -{ - register sm_element *p; - - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) sm_insert(dest, dest_row, p->col_num); - } -} - - -void -sm_copy_col(dest, dest_col, pcol) -register sm_matrix *dest; -int dest_col; -sm_col *pcol; -{ - register sm_element *p; - - for(p = pcol->first_row; p != 0; p = p->next_row) { - (void) sm_insert(dest, dest_col, p->row_num); - } -} - - -sm_row * -sm_longest_row(A) -sm_matrix *A; -{ - register sm_row *large_row, *prow; - register int max_length; - - max_length = 0; - large_row = NIL(sm_row); - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - if (prow->length > max_length) { - max_length = prow->length; - large_row = prow; - } - } - return large_row; -} - - -sm_col * -sm_longest_col(A) -sm_matrix *A; -{ - register sm_col *large_col, *pcol; - register int max_length; - - max_length = 0; - large_col = NIL(sm_col); - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - if (pcol->length > max_length) { - max_length = pcol->length; - large_col = pcol; - } - } - return large_col; -} - -int -sm_num_elements(A) -sm_matrix *A; -{ - register sm_row *prow; - register int num; - - num = 0; - sm_foreach_row(A, prow) { - num += prow->length; - } - return num; -} - -int -sm_read(fp, A) -FILE *fp; -sm_matrix **A; -{ - int i, j, err; - - *A = sm_alloc(); - while (! feof(fp)) { - err = fscanf(fp, "%d %d", &i, &j); - if (err == EOF) { - return 1; - } else if (err != 2) { - return 0; - } - (void) sm_insert(*A, i, j); - } - return 1; -} - - -int -sm_read_compressed(fp, A) -FILE *fp; -sm_matrix **A; -{ - int i, j, k, nrows, ncols; - unsigned long x; - - *A = sm_alloc(); - if (fscanf(fp, "%d %d", &nrows, &ncols) != 2) { - return 0; - } - sm_resize(*A, nrows, ncols); - - for(i = 0; i < nrows; i++) { - if (fscanf(fp, "%lx", &x) != 1) { - return 0; - } - for(j = 0; j < ncols; j += 32) { - if (fscanf(fp, "%lx", &x) != 1) { - return 0; - } - for(k = j; x != 0; x >>= 1, k++) { - if (x & 1) { - (void) sm_insert(*A, i, k); - } - } - } - } - return 1; -} - - -void -sm_write(fp, A) -FILE *fp; -sm_matrix *A; -{ - register sm_row *prow; - register sm_element *p; - - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) fprintf(fp, "%d %d\n", p->row_num, p->col_num); - } - } -} - -void -sm_print(fp, A) -FILE *fp; -sm_matrix *A; -{ - register sm_row *prow; - register sm_col *pcol; - int c; - - if (A->last_col->col_num >= 100) { - (void) fprintf(fp, " "); - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - (void) fprintf(fp, "%d", (pcol->col_num / 100)%10); - } - putc('\n', fp); - } - - if (A->last_col->col_num >= 10) { - (void) fprintf(fp, " "); - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - (void) fprintf(fp, "%d", (pcol->col_num / 10)%10); - } - putc('\n', fp); - } - - (void) fprintf(fp, " "); - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - (void) fprintf(fp, "%d", pcol->col_num % 10); - } - putc('\n', fp); - - (void) fprintf(fp, " "); - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - (void) fprintf(fp, "-"); - } - putc('\n', fp); - - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - (void) fprintf(fp, "%3d:", prow->row_num); - - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - c = sm_row_find(prow, pcol->col_num) ? '1' : '.'; - putc(c, fp); - } - putc('\n', fp); - } -} - - -void -sm_dump(A, s, max) -sm_matrix *A; -char *s; -int max; -{ - FILE *fp = stdout; - - (void) fprintf(fp, "%s %d rows by %d cols\n", s, A->nrows, A->ncols); - if (A->nrows < max) { - sm_print(fp, A); - } -} - -void -sm_cleanup() -{ -#ifdef FAST_AND_LOOSE - register sm_element *p, *pnext; - register sm_row *prow, *pnextrow; - register sm_col *pcol, *pnextcol; - - for(p = sm_element_freelist; p != 0; p = pnext) { - pnext = p->next_col; - FREE(p); - } - sm_element_freelist = 0; - - for(prow = sm_row_freelist; prow != 0; prow = pnextrow) { - pnextrow = prow->next_row; - FREE(prow); - } - sm_row_freelist = 0; - - for(pcol = sm_col_freelist; pcol != 0; pcol = pnextcol) { - pnextcol = pcol->next_col; - FREE(pcol); - } - sm_col_freelist = 0; -#endif -} diff --git a/src/misc/espresso/mincov.c b/src/misc/espresso/mincov.c deleted file mode 100644 index ee18a3f1..00000000 --- a/src/misc/espresso/mincov.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "mincov_int.h" - -/* - * mincov.c - */ - -#define USE_GIMPEL -#define USE_INDEP_SET - -static int select_column(); -static void select_essential(); -static int verify_cover(); - -#define fail(why) {\ - (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\ - __FILE__, __LINE__, why);\ - (void) fflush(stdout);\ - abort();\ -} - -sm_row * -sm_minimum_cover(A, weight, heuristic, debug_level) -sm_matrix *A; -int *weight; -int heuristic; /* set to 1 for a heuristic covering */ -int debug_level; /* how deep in the recursion to provide info */ -{ - stats_t stats; - solution_t *best, *select; - sm_row *prow, *sol; - sm_col *pcol; - sm_matrix *dup_A; - int nelem, bound; - double sparsity; - - /* Avoid sillyness */ - if (A->nrows <= 0) { - return sm_row_alloc(); /* easy to cover */ - } - - /* Initialize debugging structure */ - stats.start_time = util_cpu_time(); - stats.debug = debug_level > 0; - stats.max_print_depth = debug_level; - stats.max_depth = -1; - stats.nodes = 0; - stats.component = stats.comp_count = 0; - stats.gimpel = stats.gimpel_count = 0; - stats.no_branching = heuristic != 0; - stats.lower_bound = -1; - - /* Check the matrix sparsity */ - nelem = 0; - sm_foreach_row(A, prow) { - nelem += prow->length; - } - sparsity = (double) nelem / (double) (A->nrows * A->ncols); - - /* Determine an upper bound on the solution */ - bound = 1; - sm_foreach_col(A, pcol) { - bound += WEIGHT(weight, pcol->col_num); - } - - /* Perform the covering */ - select = solution_alloc(); - dup_A = sm_dup(A); - best = sm_mincov(dup_A, select, weight, 0, bound, 0, &stats); - sm_free(dup_A); - solution_free(select); - - if (stats.debug) { - if (stats.no_branching) { - (void) printf("**** heuristic covering ...\n"); - (void) printf("lower bound = %d\n", stats.lower_bound); - } - (void) printf("matrix = %d by %d with %d elements (%4.3f%%)\n", - A->nrows, A->ncols, nelem, sparsity * 100.0); - (void) printf("cover size = %d elements\n", best->row->length); - (void) printf("cover cost = %d\n", best->cost); - (void) printf("time = %s\n", - util_print_time(util_cpu_time() - stats.start_time)); - (void) printf("components = %d\n", stats.comp_count); - (void) printf("gimpel = %d\n", stats.gimpel_count); - (void) printf("nodes = %d\n", stats.nodes); - (void) printf("max_depth = %d\n", stats.max_depth); - } - - sol = sm_row_dup(best->row); - if (! verify_cover(A, sol)) { - fail("mincov: internal error -- cover verification failed\n"); - } - solution_free(best); - return sol; -} - -/* - * Find the best cover for 'A' (given that 'select' already selected); - * - * - abort search if a solution cannot be found which beats 'bound' - * - * - if any solution meets 'lower_bound', then it is the optimum solution - * and can be returned without further work. - */ - -solution_t * -sm_mincov(A, select, weight, lb, bound, depth, stats) -sm_matrix *A; -solution_t *select; -int *weight; -int lb; -int bound; -int depth; -stats_t *stats; -{ - sm_matrix *A1, *A2, *L, *R; - sm_element *p; - solution_t *select1, *select2, *best, *best1, *best2, *indep; - int pick, lb_new, debug; - - /* Start out with some debugging information */ - stats->nodes++; - if (depth > stats->max_depth) stats->max_depth = depth; - debug = stats->debug && (depth <= stats->max_print_depth); - - /* Apply row dominance, column dominance, and select essentials */ - select_essential(A, select, weight, bound); - if (select->cost >= bound) { - return NIL(solution_t); - } - - /* See if gimpel's reduction technique applies ... */ -#ifdef USE_GIMPEL - if ( weight == NIL(int)) { /* hack until we fix it */ - if (gimpel_reduce(A, select, weight, lb, bound, depth, stats, &best)) { - return best; - } - } -#endif - -#ifdef USE_INDEP_SET - /* Determine bound from here to final solution using independent-set */ - indep = sm_maximal_independent_set(A, weight); - - /* make sure the lower bound is monotonically increasing */ - lb_new = MAX(select->cost + indep->cost, lb); - pick = select_column(A, weight, indep); - solution_free(indep); -#else - lb_new = select->cost + (A->nrows > 0); - pick = select_column(A, weight, NIL(solution_t)); -#endif - - if (depth == 0) { - stats->lower_bound = lb_new + stats->gimpel; - } - - if (debug) { - (void) printf("ABSMIN[%2d]%s", depth, stats->component ? "*" : " "); - (void) printf(" %3dx%3d sel=%3d bnd=%3d lb=%3d %12s ", - A->nrows, A->ncols, select->cost + stats->gimpel, - bound + stats->gimpel, lb_new + stats->gimpel, - util_print_time(util_cpu_time()-stats->start_time)); - } - - /* Check for bounding based on no better solution possible */ - if (lb_new >= bound) { - if (debug) (void) printf("bounded\n"); - best = NIL(solution_t); - - - /* Check for new best solution */ - } else if (A->nrows == 0) { - best = solution_dup(select); - if (debug) (void) printf("BEST\n"); - if (stats->debug && stats->component == 0) { - (void) printf("new 'best' solution %d at level %d (time is %s)\n", - best->cost + stats->gimpel, depth, - util_print_time(util_cpu_time() - stats->start_time)); - } - - - /* Check for a partition of the problem */ - } else if (sm_block_partition(A, &L, &R)) { - /* Make L the smaller problem */ - if (L->ncols > R->ncols) { - A1 = L; - L = R; - R = A1; - } - if (debug) (void) printf("comp %d %d\n", L->nrows, R->nrows); - stats->comp_count++; - - /* Solve problem for L */ - select1 = solution_alloc(); - stats->component++; - best1 = sm_mincov(L, select1, weight, 0, - bound-select->cost, depth+1, stats); - stats->component--; - solution_free(select1); - sm_free(L); - - /* Add best solution to the selected set */ - if (best1 == NIL(solution_t)) { - best = NIL(solution_t); - } else { - for(p = best1->row->first_col; p != 0; p = p->next_col) { - solution_add(select, weight, p->col_num); - } - solution_free(best1); - - /* recur for the remaining block */ - best = sm_mincov(R, select, weight, lb_new, bound, depth+1, stats); - } - sm_free(R); - - /* We've tried as hard as possible, but now we must split and recur */ - } else { - if (debug) (void) printf("pick=%d\n", pick); - - /* Assume we choose this column to be in the covering set */ - A1 = sm_dup(A); - select1 = solution_dup(select); - solution_accept(select1, A1, weight, pick); - best1 = sm_mincov(A1, select1, weight, lb_new, bound, depth+1, stats); - solution_free(select1); - sm_free(A1); - - /* Update the upper bound if we found a better solution */ - if (best1 != NIL(solution_t) && bound > best1->cost) { - bound = best1->cost; - } - - /* See if this is a heuristic covering (no branching) */ - if (stats->no_branching) { - return best1; - } - - /* Check for reaching lower bound -- if so, don't actually branch */ - if (best1 != NIL(solution_t) && best1->cost == lb_new) { - return best1; - } - - /* Now assume we cannot have that column */ - A2 = sm_dup(A); - select2 = solution_dup(select); - solution_reject(select2, A2, weight, pick); - best2 = sm_mincov(A2, select2, weight, lb_new, bound, depth+1, stats); - solution_free(select2); - sm_free(A2); - - best = solution_choose_best(best1, best2); - } - - return best; -} - -static int -select_column(A, weight, indep) -sm_matrix *A; -int *weight; -solution_t *indep; -{ - register sm_col *pcol; - register sm_row *prow, *indep_cols; - register sm_element *p, *p1; - double w, best; - int best_col; - - indep_cols = sm_row_alloc(); - if (indep != NIL(solution_t)) { - /* Find which columns are in the independent sets */ - for(p = indep->row->first_col; p != 0; p = p->next_col) { - prow = sm_get_row(A, p->col_num); - for(p1 = prow->first_col; p1 != 0; p1 = p1->next_col) { - (void) sm_row_insert(indep_cols, p1->col_num); - } - } - } else { - /* select out of all columns */ - sm_foreach_col(A, pcol) { - (void) sm_row_insert(indep_cols, pcol->col_num); - } - } - - /* Find the best column */ - best_col = -1; - best = -1; - - /* Consider only columns which are in some independent row */ - sm_foreach_row_element(indep_cols, p1) { - pcol = sm_get_col(A, p1->col_num); - - /* Compute the total 'value' of all things covered by the column */ - w = 0.0; - for(p = pcol->first_row; p != 0; p = p->next_row) { - prow = sm_get_row(A, p->row_num); - w += 1.0 / ((double) prow->length - 1.0); - } - - /* divide this by the relative cost of choosing this column */ - w = w / (double) WEIGHT(weight, pcol->col_num); - - /* maximize this ratio */ - if (w > best) { - best_col = pcol->col_num; - best = w; - } - } - - sm_row_free(indep_cols); - return best_col; -} - -static void -select_essential(A, select, weight, bound) -sm_matrix *A; -solution_t *select; -int *weight; -int bound; /* must beat this solution */ -{ - register sm_element *p; - register sm_row *prow, *essen; - int delcols, delrows, essen_count; - - do { - /* Check for dominated columns */ - delcols = sm_col_dominance(A, weight); - - /* Find the rows with only 1 element (the essentials) */ - essen = sm_row_alloc(); - sm_foreach_row(A, prow) { - if (prow->length == 1) { - (void) sm_row_insert(essen, prow->first_col->col_num); - } - } - - /* Select all of the elements */ - sm_foreach_row_element(essen, p) { - solution_accept(select, A, weight, p->col_num); - /* Make sure solution still looks good */ - if (select->cost >= bound) { - sm_row_free(essen); - return; - } - } - essen_count = essen->length; - sm_row_free(essen); - - /* Check for dominated rows */ - delrows = sm_row_dominance(A); - - } while (delcols > 0 || delrows > 0 || essen_count > 0); -} - -static int -verify_cover(A, cover) -sm_matrix *A; -sm_row *cover; -{ - sm_row *prow; - - sm_foreach_row(A, prow) { - if (! sm_row_intersects(prow, cover)) { - return 0; - } - } - return 1; -} diff --git a/src/misc/espresso/mincov.h b/src/misc/espresso/mincov.h deleted file mode 100644 index 95310774..00000000 --- a/src/misc/espresso/mincov.h +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* exported */ -extern sm_row *sm_minimum_cover(); diff --git a/src/misc/espresso/mincov_int.h b/src/misc/espresso/mincov_int.h deleted file mode 100644 index e81850f2..00000000 --- a/src/misc/espresso/mincov_int.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -//#include "port.h" -//#include "utility.h" -#include "sparse.h" -#include "mincov.h" - -#include "util_hack.h" // added - - -typedef struct stats_struct stats_t; -struct stats_struct { - int debug; /* 1 if debugging is enabled */ - int max_print_depth; /* dump stats for levels up to this level */ - int max_depth; /* deepest the recursion has gone */ - int nodes; /* total nodes visited */ - int component; /* currently solving a component */ - int comp_count; /* number of components detected */ - int gimpel_count; /* number of times Gimpel reduction applied */ - int gimpel; /* currently inside Gimpel reduction */ - long start_time; /* cpu time when the covering started */ - int no_branching; - int lower_bound; -}; - - - -typedef struct solution_struct solution_t; -struct solution_struct { - sm_row *row; - int cost; -}; - - -extern solution_t *solution_alloc(); -extern void solution_free(); -extern solution_t *solution_dup(); -extern void solution_accept(); -extern void solution_reject(); -extern void solution_add(); -extern solution_t *solution_choose_best(); - -extern solution_t *sm_maximal_independent_set(); -extern solution_t *sm_mincov(); -extern int gimpel_reduce(); - - -#define WEIGHT(weight, col) (weight == NIL(int) ? 1 : weight[col]) diff --git a/src/misc/espresso/module.make b/src/misc/espresso/module.make deleted file mode 100644 index 53ce982a..00000000 --- a/src/misc/espresso/module.make +++ /dev/null @@ -1,39 +0,0 @@ -SRC += src/misc/espresso/cofactor.c \ - src/misc/espresso/cols.c \ - src/misc/espresso/compl.c \ - src/misc/espresso/contain.c \ - src/misc/espresso/cubehack.c \ - src/misc/espresso/cubestr.c \ - src/misc/espresso/cvrin.c \ - src/misc/espresso/cvrm.c \ - src/misc/espresso/cvrmisc.c \ - src/misc/espresso/cvrout.c \ - src/misc/espresso/dominate.c \ - src/misc/espresso/equiv.c \ - src/misc/espresso/espresso.c \ - src/misc/espresso/essen.c \ - src/misc/espresso/exact.c \ - src/misc/espresso/expand.c \ - src/misc/espresso/gasp.c \ - src/misc/espresso/gimpel.c \ - src/misc/espresso/globals.c \ - src/misc/espresso/hack.c \ - src/misc/espresso/indep.c \ - src/misc/espresso/irred.c \ - src/misc/espresso/map.c \ - src/misc/espresso/matrix.c \ - src/misc/espresso/mincov.c \ - src/misc/espresso/opo.c \ - src/misc/espresso/pair.c \ - src/misc/espresso/part.c \ - src/misc/espresso/primes.c \ - src/misc/espresso/reduce.c \ - src/misc/espresso/rows.c \ - src/misc/espresso/set.c \ - src/misc/espresso/setc.c \ - src/misc/espresso/sharp.c \ - src/misc/espresso/sminterf.c \ - src/misc/espresso/solution.c \ - src/misc/espresso/sparse.c \ - src/misc/espresso/unate.c \ - src/misc/espresso/verify.c diff --git a/src/misc/espresso/opo.c b/src/misc/espresso/opo.c deleted file mode 100644 index 8daa0771..00000000 --- a/src/misc/espresso/opo.c +++ /dev/null @@ -1,624 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - -/* - * Phase assignment technique (T. Sasao): - * - * 1. create a function with 2*m outputs which implements the - * original function and its complement for each output - * - * 2. minimize this function - * - * 3. choose the minimum number of prime implicants from the - * result of step 2 which are needed to realize either a function - * or its complement for each output - * - * Step 3 is performed in a rather crude way -- by simply multiplying - * out a large expression of the form: - * - * I = (ab + cdef)(acd + bgh) ... - * - * which is a product of m expressions where each expression has two - * product terms -- one representing which primes are needed for the - * function, and one representing which primes are needed for the - * complement. The largest product term resulting shows which primes - * to keep to implement one function or the other for each output. - * For problems with many outputs, this may grind to a - * halt. - * - * Untried: form complement of I and use unate_complement ... - * - * I have unsuccessfully tried several modifications to the basic - * algorithm. The first is quite simple: use Sasao's technique, but - * only commit to a single output at a time (rather than all - * outputs). The goal would be that the later minimizations can "take - * into account" the partial assignment at each step. This is - * expensive (m+1 minimizations rather than 2), and the results are - * discouraging. - * - * The second modification is rather complicated. The result from the - * minimization in step 2 is guaranteed to be minimal. Hence, for - * each output, the set of primes with a 1 in that output are both - * necessary and sufficient to implement the function. Espresso - * achieves the minimality using the routine MAKE_SPARSE. The - * modification is to prevent MAKE_SPARSE from running. Hence, there - * are potentially many subsets of the set of primes with a 1 in a - * column which can be used to implement that output. We use - * IRREDUNDANT to enumerate all possible subsets and then proceed as - * before. - */ - -static int opo_no_make_sparse; -static int opo_repeated; -static int opo_exact; -static void minimize(); - -void phase_assignment(PLA, opo_strategy) -pPLA PLA; -int opo_strategy; -{ - opo_no_make_sparse = opo_strategy % 2; - skip_make_sparse = opo_no_make_sparse; - opo_repeated = (opo_strategy / 2) % 2; - opo_exact = (opo_strategy / 4) % 2; - - /* Determine a phase assignment */ - if (PLA->phase != NULL) { - FREE(PLA->phase); - } - - if (opo_repeated) { - PLA->phase = set_save(cube.fullset); - repeated_phase_assignment(PLA); - } else { - PLA->phase = find_phase(PLA, 0, (pcube) NULL); - } - - /* Now minimize with this assignment */ - skip_make_sparse = FALSE; - (void) set_phase(PLA); - minimize(PLA); -} - -/* - * repeated_phase_assignment -- an alternate strategy which commits - * to a single phase assignment a step at a time. Performs m + 1 - * minimizations ! - */ -void repeated_phase_assignment(PLA) -pPLA PLA; -{ - int i; - pcube phase; - - for(i = 0; i < cube.part_size[cube.output]; i++) { - - /* Find best assignment for all undecided outputs */ - phase = find_phase(PLA, i, PLA->phase); - - /* Commit for only a single output ... */ - if (! is_in_set(phase, cube.first_part[cube.output] + i)) { - set_remove(PLA->phase, cube.first_part[cube.output] + i); - } - - if (trace || summary) { - printf("\nOPO loop for output #%d\n", i); - printf("PLA->phase is %s\n", pc1(PLA->phase)); - printf("phase is %s\n", pc1(phase)); - } - set_free(phase); - } -} - - -/* - * find_phase -- find a phase assignment for the PLA for all outputs starting - * with output number first_output. - */ -pcube find_phase(PLA, first_output, phase1) -pPLA PLA; -int first_output; -pcube phase1; -{ - pcube phase; - pPLA PLA1; - - phase = set_save(cube.fullset); - - /* setup the double-phase characteristic function, resize the cube */ - PLA1 = new_PLA(); - PLA1->F = sf_save(PLA->F); - PLA1->R = sf_save(PLA->R); - PLA1->D = sf_save(PLA->D); - if (phase1 != NULL) { - PLA1->phase = set_save(phase1); - (void) set_phase(PLA1); - } - EXEC_S(output_phase_setup(PLA1, first_output), "OPO-SETUP ", PLA1->F); - - /* minimize the double-phase function */ - minimize(PLA1); - - /* set the proper phases according to what gives a minimum solution */ - EXEC_S(PLA1->F = opo(phase, PLA1->F, PLA1->D, PLA1->R, first_output), - "OPO ", PLA1->F); - free_PLA(PLA1); - - /* set the cube structure to reflect the old size */ - setdown_cube(); - cube.part_size[cube.output] -= - (cube.part_size[cube.output] - first_output) / 2; - cube_setup(); - - return phase; -} - -/* - * opo -- multiply the expression out to determine a minimum subset of - * primes. - */ - -/*ARGSUSED*/ -pcover opo(phase, T, D, R, first_output) -pcube phase; -pcover T, D, R; -int first_output; -{ - int offset, output, i, last_output, ind; - pset pdest, select, p, p1, last, last1, not_covered, tmp; - pset_family temp, T1, T2; - - /* must select all primes for outputs [0 .. first_output-1] */ - select = set_full(T->count); - for(output = 0; output < first_output; output++) { - ind = cube.first_part[cube.output] + output; - foreachi_set(T, i, p) { - if (is_in_set(p, ind)) { - set_remove(select, i); - } - } - } - - /* Recursively perform the intersections */ - offset = (cube.part_size[cube.output] - first_output) / 2; - last_output = first_output + offset - 1; - temp = opo_recur(T, D, select, offset, first_output, last_output); - - /* largest set is on top -- select primes which are inferred from it */ - pdest = temp->data; - T1 = new_cover(T->count); - foreachi_set(T, i, p) { - if (! is_in_set(pdest, i)) { - T1 = sf_addset(T1, p); - } - } - - set_free(select); - sf_free(temp); - - /* finding phases is difficult -- see which functions are not covered */ - T2 = complement(cube1list(T1)); - not_covered = new_cube(); - tmp = new_cube(); - foreach_set(T, last, p) { - foreach_set(T2, last1, p1) { - if (cdist0(p, p1)) { - (void) set_or(not_covered, not_covered, set_and(tmp, p, p1)); - } - } - } - free_cover(T); - free_cover(T2); - set_free(tmp); - - /* Now reflect the phase choice in a single cube */ - for(output = first_output; output <= last_output; output++) { - ind = cube.first_part[cube.output] + output; - if (is_in_set(not_covered, ind)) { - if (is_in_set(not_covered, ind + offset)) { - fatal("error in output phase assignment"); - } else { - set_remove(phase, ind); - } - } - } - set_free(not_covered); - return T1; -} - -pset_family opo_recur(T, D, select, offset, first, last) -pcover T, D; -pcube select; -int offset, first, last; -{ - static int level = 0; - int middle; - pset_family sl, sr, temp; - - level++; - if (first == last) { -#if 0 - if (opo_no_make_sparse) { - temp = form_cover_table(T, D, select, first, first + offset); - } else { - temp = opo_leaf(T, select, first, first + offset); - } -#else - temp = opo_leaf(T, select, first, first + offset); -#endif - } else { - middle = (first + last) / 2; - sl = opo_recur(T, D, select, offset, first, middle); - sr = opo_recur(T, D, select, offset, middle+1, last); - temp = unate_intersect(sl, sr, level == 1); - if (trace) { - printf("# OPO[%d]: %4d = %4d x %4d, time = %s\n", level - 1, - temp->count, sl->count, sr->count, print_time(ptime())); - (void) fflush(stdout); - } - free_cover(sl); - free_cover(sr); - } - level--; - return temp; -} - - -pset_family opo_leaf(T, select, out1, out2) -register pcover T; -pset select; -int out1, out2; -{ - register pset_family temp; - register pset p, pdest; - register int i; - - out1 += cube.first_part[cube.output]; - out2 += cube.first_part[cube.output]; - - /* Allocate space for the result */ - temp = sf_new(2, T->count); - - /* Find which primes are needed for the ON-set of this fct */ - pdest = GETSET(temp, temp->count++); - (void) set_copy(pdest, select); - foreachi_set(T, i, p) { - if (is_in_set(p, out1)) { - set_remove(pdest, i); - } - } - - /* Find which primes are needed for the OFF-set of this fct */ - pdest = GETSET(temp, temp->count++); - (void) set_copy(pdest, select); - foreachi_set(T, i, p) { - if (is_in_set(p, out2)) { - set_remove(pdest, i); - } - } - - return temp; -} - -#if 0 -pset_family form_cover_table(F, D, select, f, fbar) -pcover F, D; -pset select; -int f, fbar; /* indices of f and fbar in the output part */ -{ - register int i; - register pcube p; - pset_family f_table, fbar_table; - - /* setup required for fcube_is_covered */ - Rp_size = F->count; - Rp_start = set_new(Rp_size); - foreachi_set(F, i, p) { - PUTSIZE(p, i); - } - foreachi_set(D, i, p) { - RESET(p, REDUND); - } - - f_table = find_covers(F, D, select, f); - fbar_table = find_covers(F, D, select, fbar); - f_table = sf_append(f_table, fbar_table); - - set_free(Rp_start); - return f_table; -} - - -pset_family find_covers(F, D, select, n) -pcover F, D; -register pset select; -int n; -{ - register pset p, last, new; - pcover F1; - pcube *Flist; - pset_family f_table, table; - int i; - - n += cube.first_part[cube.output]; - - /* save cubes in this output, and remove the output variable */ - F1 = new_cover(F->count); - foreach_set(F, last, p) - if (is_in_set(p, n)) { - new = GETSET(F1, F1->count++); - set_or(new, p, cube.var_mask[cube.output]); - PUTSIZE(new, SIZE(p)); - SET(new, REDUND); - } - - /* Find ways (sop form) to fail to cover output indexed by n */ - Flist = cube2list(F1, D); - table = sf_new(10, Rp_size); - foreach_set(F1, last, p) { - set_fill(Rp_start, Rp_size); - set_remove(Rp_start, SIZE(p)); - table = sf_append(table, fcube_is_covered(Flist, p)); - RESET(p, REDUND); - } - set_fill(Rp_start, Rp_size); - foreach_set(table, last, p) { - set_diff(p, Rp_start, p); - } - - /* complement this to get possible ways to cover the function */ - for(i = 0; i < Rp_size; i++) { - if (! is_in_set(select, i)) { - p = set_new(Rp_size); - set_insert(p, i); - table = sf_addset(table, p); - set_free(p); - } - } - f_table = unate_compl(table); - - /* what a pain, but we need bitwise complement of this */ - set_fill(Rp_start, Rp_size); - foreach_set(f_table, last, p) { - set_diff(p, Rp_start, p); - } - - free_cubelist(Flist); - sf_free(F1); - return f_table; -} -#endif - -/* - * Take a PLA (ON-set, OFF-set and DC-set) and create the - * "double-phase characteristic function" which is merely a new - * function which has twice as many outputs and realizes both the - * function and the complement. - * - * The cube structure is assumed to represent the PLA upon entering. - * It will be modified to represent the double-phase function upon - * exit. - * - * Only the outputs numbered starting with "first_output" are - * duplicated in the output part - */ - -output_phase_setup(PLA, first_output) -INOUT pPLA PLA; -int first_output; -{ - pcover F, R, D; - pcube mask, mask1, last; - int first_part, offset; - bool save; - register pcube p, pr, pf; - register int i, last_part; - - if (cube.output == -1) - fatal("output_phase_setup: must have an output"); - - F = PLA->F; - D = PLA->D; - R = PLA->R; - first_part = cube.first_part[cube.output] + first_output; - last_part = cube.last_part[cube.output]; - offset = cube.part_size[cube.output] - first_output; - - /* Change the output size, setup the cube structure */ - setdown_cube(); - cube.part_size[cube.output] += offset; - cube_setup(); - - /* Create a mask to select that part of the cube which isn't changing */ - mask = set_save(cube.fullset); - for(i = first_part; i < cube.size; i++) - set_remove(mask, i); - mask1 = set_save(mask); - for(i = cube.first_part[cube.output]; i < first_part; i++) { - set_remove(mask1, i); - } - - PLA->F = new_cover(F->count + R->count); - PLA->R = new_cover(F->count + R->count); - PLA->D = new_cover(D->count); - - foreach_set(F, last, p) { - pf = GETSET(PLA->F, (PLA->F)->count++); - pr = GETSET(PLA->R, (PLA->R)->count++); - INLINEset_and(pf, mask, p); - INLINEset_and(pr, mask1, p); - for(i = first_part; i <= last_part; i++) - if (is_in_set(p, i)) - set_insert(pf, i); - save = FALSE; - for(i = first_part; i <= last_part; i++) - if (is_in_set(p, i)) - save = TRUE, set_insert(pr, i+offset); - if (! save) PLA->R->count--; - } - - foreach_set(R, last, p) { - pf = GETSET(PLA->F, (PLA->F)->count++); - pr = GETSET(PLA->R, (PLA->R)->count++); - INLINEset_and(pf, mask1, p); - INLINEset_and(pr, mask, p); - save = FALSE; - for(i = first_part; i <= last_part; i++) - if (is_in_set(p, i)) - save = TRUE, set_insert(pf, i+offset); - if (! save) PLA->F->count--; - for(i = first_part; i <= last_part; i++) - if (is_in_set(p, i)) - set_insert(pr, i); - } - - foreach_set(D, last, p) { - pf = GETSET(PLA->D, (PLA->D)->count++); - INLINEset_and(pf, mask, p); - for(i = first_part; i <= last_part; i++) - if (is_in_set(p, i)) { - set_insert(pf, i); - set_insert(pf, i+offset); - } - } - - free_cover(F); - free_cover(D); - free_cover(R); - set_free(mask); - set_free(mask1); -} - -/* - * set_phase -- given a "cube" which describes which phases of the output - * are to be implemented, compute the appropriate on-set and off-set - */ -pPLA set_phase(PLA) -INOUT pPLA PLA; -{ - pcover F1, R1; - register pcube last, p, outmask; - register pcube temp=cube.temp[0], phase=PLA->phase, phase1=cube.temp[1]; - - outmask = cube.var_mask[cube.num_vars - 1]; - set_diff(phase1, outmask, phase); - set_or(phase1, set_diff(temp, cube.fullset, outmask), phase1); - F1 = new_cover((PLA->F)->count + (PLA->R)->count); - R1 = new_cover((PLA->F)->count + (PLA->R)->count); - - foreach_set(PLA->F, last, p) { - if (! setp_disjoint(set_and(temp, p, phase), outmask)) - set_copy(GETSET(F1, F1->count++), temp); - if (! setp_disjoint(set_and(temp, p, phase1), outmask)) - set_copy(GETSET(R1, R1->count++), temp); - } - foreach_set(PLA->R, last, p) { - if (! setp_disjoint(set_and(temp, p, phase), outmask)) - set_copy(GETSET(R1, R1->count++), temp); - if (! setp_disjoint(set_and(temp, p, phase1), outmask)) - set_copy(GETSET(F1, F1->count++), temp); - } - free_cover(PLA->F); - free_cover(PLA->R); - PLA->F = F1; - PLA->R = R1; - return PLA; -} - -#define POW2(x) (1 << (x)) - -void opoall(PLA, first_output, last_output, opo_strategy) -pPLA PLA; -int first_output, last_output; -int opo_strategy; -{ - pcover F, D, R, best_F, best_D, best_R; - int i, j, ind, num; - pcube bestphase; - - opo_exact = opo_strategy; - - if (PLA->phase != NULL) { - set_free(PLA->phase); - } - - bestphase = set_save(cube.fullset); - best_F = sf_save(PLA->F); - best_D = sf_save(PLA->D); - best_R = sf_save(PLA->R); - - for(i = 0; i < POW2(last_output - first_output + 1); i++) { - - /* save the initial PLA covers */ - F = sf_save(PLA->F); - D = sf_save(PLA->D); - R = sf_save(PLA->R); - - /* compute the phase cube for this iteration */ - PLA->phase = set_save(cube.fullset); - num = i; - for(j = last_output; j >= first_output; j--) { - if (num % 2 == 0) { - ind = cube.first_part[cube.output] + j; - set_remove(PLA->phase, ind); - } - num /= 2; - } - - /* set the phase and minimize */ - (void) set_phase(PLA); - printf("# phase is %s\n", pc1(PLA->phase)); - summary = TRUE; - minimize(PLA); - - /* see if this is the best so far */ - if (PLA->F->count < best_F->count) { - /* save new best solution */ - set_copy(bestphase, PLA->phase); - sf_free(best_F); - sf_free(best_D); - sf_free(best_R); - best_F = PLA->F; - best_D = PLA->D; - best_R = PLA->R; - } else { - /* throw away the solution */ - free_cover(PLA->F); - free_cover(PLA->D); - free_cover(PLA->R); - } - set_free(PLA->phase); - - /* restore the initial PLA covers */ - PLA->F = F; - PLA->D = D; - PLA->R = R; - } - - /* one more minimization to restore the best answer */ - PLA->phase = bestphase; - sf_free(PLA->F); - sf_free(PLA->D); - sf_free(PLA->R); - PLA->F = best_F; - PLA->D = best_D; - PLA->R = best_R; -} - -static void minimize(PLA) -pPLA PLA; -{ - if (opo_exact) { - EXEC_S(PLA->F = minimize_exact(PLA->F,PLA->D,PLA->R,1), "EXACT", PLA->F); - } else { - EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), "ESPRESSO ",PLA->F); - } -} diff --git a/src/misc/espresso/pair.c b/src/misc/espresso/pair.c deleted file mode 100644 index a8077176..00000000 --- a/src/misc/espresso/pair.c +++ /dev/null @@ -1,675 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - -void set_pair(PLA) -pPLA PLA; -{ - set_pair1(PLA, TRUE); -} - -void set_pair1(PLA, adjust_labels) -pPLA PLA; -bool adjust_labels; -{ - int i, var, *paired, newvar; - int old_num_vars, old_num_binary_vars, old_size, old_mv_start; - int *new_part_size, new_num_vars, new_num_binary_vars, new_mv_start; - ppair pair = PLA->pair; - char scratch[1000], **oldlabel, *var1, *var1bar, *var2, *var2bar; - - if (adjust_labels) - makeup_labels(PLA); - - /* Check the pair structure for valid entries and see which binary - variables are left unpaired - */ - paired = ALLOC(bool, cube.num_binary_vars); - for(var = 0; var < cube.num_binary_vars; var++) - paired[var] = FALSE; - for(i = 0; i < pair->cnt; i++) - if ((pair->var1[i] > 0 && pair->var1[i] <= cube.num_binary_vars) && - (pair->var2[i] > 0 && pair->var2[i] <= cube.num_binary_vars)) { - paired[pair->var1[i]-1] = TRUE; - paired[pair->var2[i]-1] = TRUE; - } else - fatal("can only pair binary-valued variables"); - - PLA->F = delvar(pairvar(PLA->F, pair), paired); - PLA->R = delvar(pairvar(PLA->R, pair), paired); - PLA->D = delvar(pairvar(PLA->D, pair), paired); - - /* Now painfully adjust the cube size */ - old_size = cube.size; - old_num_vars = cube.num_vars; - old_num_binary_vars = cube.num_binary_vars; - old_mv_start = cube.first_part[cube.num_binary_vars]; - /* Create the new cube.part_size vector and setup the cube structure */ - new_num_binary_vars = 0; - for(var = 0; var < old_num_binary_vars; var++) - new_num_binary_vars += (paired[var] == FALSE); - new_num_vars = new_num_binary_vars + pair->cnt; - new_num_vars += old_num_vars - old_num_binary_vars; - new_part_size = ALLOC(int, new_num_vars); - for(var = 0; var < pair->cnt; var++) - new_part_size[new_num_binary_vars + var] = 4; - for(var = 0; var < old_num_vars - old_num_binary_vars; var++) - new_part_size[new_num_binary_vars + pair->cnt + var] = - cube.part_size[old_num_binary_vars + var]; - setdown_cube(); - FREE(cube.part_size); - cube.num_vars = new_num_vars; - cube.num_binary_vars = new_num_binary_vars; - cube.part_size = new_part_size; - cube_setup(); - - /* hack with the labels to get them correct */ - if (adjust_labels) { - oldlabel = PLA->label; - PLA->label = ALLOC(char *, cube.size); - for(var = 0; var < pair->cnt; var++) { - newvar = cube.num_binary_vars*2 + var*4; - var1 = oldlabel[ (pair->var1[var]-1) * 2 + 1]; - var2 = oldlabel[ (pair->var2[var]-1) * 2 + 1]; - var1bar = oldlabel[ (pair->var1[var]-1) * 2]; - var2bar = oldlabel[ (pair->var2[var]-1) * 2]; - (void) sprintf(scratch, "%s+%s", var1bar, var2bar); - PLA->label[newvar] = util_strsav(scratch); - (void) sprintf(scratch, "%s+%s", var1bar, var2); - PLA->label[newvar+1] = util_strsav(scratch); - (void) sprintf(scratch, "%s+%s", var1, var2bar); - PLA->label[newvar+2] = util_strsav(scratch); - (void) sprintf(scratch, "%s+%s", var1, var2); - PLA->label[newvar+3] = util_strsav(scratch); - } - /* Copy the old labels for the unpaired binary vars */ - i = 0; - for(var = 0; var < old_num_binary_vars; var++) { - if (paired[var] == FALSE) { - PLA->label[2*i] = oldlabel[2*var]; - PLA->label[2*i+1] = oldlabel[2*var+1]; - oldlabel[2*var] = oldlabel[2*var+1] = (char *) NULL; - i++; - } - } - /* Copy the old labels for the remaining unpaired vars */ - new_mv_start = cube.num_binary_vars*2 + pair->cnt*4; - for(i = old_mv_start; i < old_size; i++) { - PLA->label[new_mv_start + i - old_mv_start] = oldlabel[i]; - oldlabel[i] = (char *) NULL; - } - /* free remaining entries in oldlabel */ - for(i = 0; i < old_size; i++) - if (oldlabel[i] != (char *) NULL) - FREE(oldlabel[i]); - FREE(oldlabel); - } - - /* the paired variables should not be sparse (cf. mv_reduce/raise_in)*/ - for(var = 0; var < pair->cnt; var++) - cube.sparse[cube.num_binary_vars + var] = 0; - FREE(paired); -} - -pcover pairvar(A, pair) -pcover A; -ppair pair; -{ - register pcube last, p; - register int val, p1, p2, b1, b0; - int insert_col, pairnum; - - insert_col = cube.first_part[cube.num_vars - 1]; - - /* stretch the cover matrix to make room for the paired variables */ - A = sf_delcol(A, insert_col, -4*pair->cnt); - - /* compute the paired values */ - foreach_set(A, last, p) { - for(pairnum = 0; pairnum < pair->cnt; pairnum++) { - p1 = cube.first_part[pair->var1[pairnum] - 1]; - p2 = cube.first_part[pair->var2[pairnum] - 1]; - b1 = is_in_set(p, p2+1); - b0 = is_in_set(p, p2); - val = insert_col + pairnum * 4; - if (/* a0 */ is_in_set(p, p1)) { - if (b0) - set_insert(p, val + 3); - if (b1) - set_insert(p, val + 2); - } - if (/* a1 */ is_in_set(p, p1+1)) { - if (b0) - set_insert(p, val + 1); - if (b1) - set_insert(p, val); - } - } - } - return A; -} - - -/* delvar -- delete variables from A, minimize the number of column shifts */ -pcover delvar(A, paired) -pcover A; -bool paired[]; -{ - bool run; - int first_run, run_length, var, offset = 0; - - run = FALSE; run_length = 0; - for(var = 0; var < cube.num_binary_vars; var++) - if (paired[var]) - if (run) - run_length += cube.part_size[var]; - else { - run = TRUE; - first_run = cube.first_part[var]; - run_length = cube.part_size[var]; - } - else - if (run) { - A = sf_delcol(A, first_run-offset, run_length); - run = FALSE; - offset += run_length; - } - if (run) - A = sf_delcol(A, first_run-offset, run_length); - return A; -} - -/* - find_optimal_pairing -- find which binary variables should be paired - to maximally reduce the number of terms - - This is essentially the technique outlined by T. Sasao in the - Trans. on Comp., Oct 1984. We estimate the cost of pairing each - pair individually using 1 of 4 strategies: (1) algebraic division - of F by the pair (exactly T. Sasao technique); (2) strong division - of F by the paired variables (using REDUCE/EXPAND/ IRREDUNDANT from - espresso); (3) full minimization using espresso; (4) exact - minimization. These are in order of both increasing accuracy and - increasing difficulty (!) - - Once the n squared pairs have been evaluated, T. Sasao proposes a - graph covering of nodes by disjoint edges. For now, I solve this - problem exhaustively (complexity = (n-1)*(n-3)*...*3*1 for n - variables when n is even). Note that solving this problem exactly - is the same as evaluating the cost function for all possible - pairings. - - n pairs - - 1, 2 1 - 3, 4 3 - 5, 6 15 - 7, 8 105 - 9,10 945 - 11,12 10,395 - 13,14 135,135 - 15,16 2,027,025 - 17,18 34,459,425 - 19,20 654,729,075 -*/ -void find_optimal_pairing(PLA, strategy) -pPLA PLA; -int strategy; -{ - int i, j, **cost_array; - - cost_array = find_pairing_cost(PLA, strategy); - - if (summary) { - printf(" "); - for(i = 0; i < cube.num_binary_vars; i++) - printf("%3d ", i+1); - printf("\n"); - for(i = 0; i < cube.num_binary_vars; i++) { - printf("%3d ", i+1); - for(j = 0; j < cube.num_binary_vars; j++) - printf("%3d ", cost_array[i][j]); - printf("\n"); - } - } - - if (cube.num_binary_vars <= 14) { - PLA->pair = pair_best_cost(cost_array); - } else { - (void) greedy_best_cost(cost_array, &(PLA->pair)); - } - printf("# "); - print_pair(PLA->pair); - - for(i = 0; i < cube.num_binary_vars; i++) - FREE(cost_array[i]); - FREE(cost_array); - - set_pair(PLA); - EXEC_S(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO ",PLA->F); -} - -int **find_pairing_cost(PLA, strategy) -pPLA PLA; -int strategy; -{ - int var1, var2, **cost_array; - int i, j, xnum_binary_vars, xnum_vars, *xpart_size, cost; - pcover T, Fsave, Dsave, Rsave; - pset mask; -/* char *s;*/ - - /* data is returned in the cost array */ - cost_array = ALLOC(int *, cube.num_binary_vars); - for(i = 0; i < cube.num_binary_vars; i++) - cost_array[i] = ALLOC(int, cube.num_binary_vars); - for(i = 0; i < cube.num_binary_vars; i++) - for(j = 0; j < cube.num_binary_vars; j++) - cost_array[i][j] = 0; - - /* Setup the pair structure for pairing variables together */ - PLA->pair = pair_new(1); - PLA->pair->cnt = 1; - - for(var1 = 0; var1 < cube.num_binary_vars-1; var1++) { - for(var2 = var1+1; var2 < cube.num_binary_vars; var2++) { - /* if anything but simple strategy, perform setup */ - if (strategy > 0) { - /* save the original covers */ - Fsave = sf_save(PLA->F); - Dsave = sf_save(PLA->D); - Rsave = sf_save(PLA->R); - - /* save the original cube structure */ - xnum_binary_vars = cube.num_binary_vars; - xnum_vars = cube.num_vars; - xpart_size = ALLOC(int, cube.num_vars); - for(i = 0; i < cube.num_vars; i++) - xpart_size[i] = cube.part_size[i]; - - /* pair two variables together */ - PLA->pair->var1[0] = var1 + 1; - PLA->pair->var2[0] = var2 + 1; - set_pair1(PLA, /* adjust_labels */ FALSE); - } - - - /* decide how to best estimate worth of this pairing */ - switch(strategy) { - case 3: - /*s = "exact minimization";*/ - PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1); - cost = Fsave->count - PLA->F->count; - break; - case 2: - /*s = "full minimization";*/ - PLA->F = espresso(PLA->F, PLA->D, PLA->R); - cost = Fsave->count - PLA->F->count; - break; - case 1: - /*s = "strong division";*/ - PLA->F = reduce(PLA->F, PLA->D); - PLA->F = expand(PLA->F, PLA->R, FALSE); - PLA->F = irredundant(PLA->F, PLA->D); - cost = Fsave->count - PLA->F->count; - break; - case 0: - /*s = "weak division";*/ - mask = new_cube(); - set_or(mask, cube.var_mask[var1], cube.var_mask[var2]); - T = dist_merge(sf_save(PLA->F), mask); - cost = PLA->F->count - T->count; - sf_free(T); - set_free(mask); - } - - cost_array[var1][var2] = cost; - - if (strategy > 0) { - /* restore the original cube structure -- free the new ones */ - setdown_cube(); - FREE(cube.part_size); - cube.num_binary_vars = xnum_binary_vars; - cube.num_vars = xnum_vars; - cube.part_size = xpart_size; - cube_setup(); - - /* restore the original cover(s) -- free the new ones */ - sf_free(PLA->F); - sf_free(PLA->D); - sf_free(PLA->R); - PLA->F = Fsave; - PLA->D = Dsave; - PLA->R = Rsave; - } - } - } - - pair_free(PLA->pair); - PLA->pair = NULL; - return cost_array; -} - -static int best_cost; -static int **cost_array; -static ppair best_pair; -static pset best_phase; -static pPLA global_PLA; -static pcover best_F, best_D, best_R; -static int pair_minim_strategy; - - -print_pair(pair) -ppair pair; -{ - int i; - - printf("pair is"); - for(i = 0; i < pair->cnt; i++) - printf (" (%d %d)", pair->var1[i], pair->var2[i]); - printf("\n"); -} - - -int greedy_best_cost(cost_array_local, pair_p) -int **cost_array_local; -ppair *pair_p; -{ - int i, j, besti, bestj, maxcost, total_cost; - pset cand; - ppair pair; - - pair = pair_new(cube.num_binary_vars); - cand = set_full(cube.num_binary_vars); - total_cost = 0; - - while (set_ord(cand) >= 2) { - maxcost = -1; - for(i = 0; i < cube.num_binary_vars; i++) { - if (is_in_set(cand, i)) { - for(j = i+1; j < cube.num_binary_vars; j++) { - if (is_in_set(cand, j)) { - if (cost_array_local[i][j] > maxcost) { - maxcost = cost_array_local[i][j]; - besti = i; - bestj = j; - } - } - } - } - } - pair->var1[pair->cnt] = besti+1; - pair->var2[pair->cnt] = bestj+1; - pair->cnt++; - set_remove(cand, besti); - set_remove(cand, bestj); - total_cost += maxcost; - } - set_free(cand); - *pair_p = pair; - return total_cost; -} - - -ppair pair_best_cost(cost_array_local) -int **cost_array_local; -{ - ppair pair; - pset candidate; - - best_cost = -1; - best_pair = NULL; - cost_array = cost_array_local; - - pair = pair_new(cube.num_binary_vars); - candidate = set_full(cube.num_binary_vars); - generate_all_pairs(pair, cube.num_binary_vars, candidate, find_best_cost); - pair_free(pair); - set_free(candidate); - return best_pair; -} - - -int find_best_cost(pair) -register ppair pair; -{ - register int i, cost; - - cost = 0; - for(i = 0; i < pair->cnt; i++) - cost += cost_array[pair->var1[i]-1][pair->var2[i]-1]; - if (cost > best_cost) { - best_cost = cost; - best_pair = pair_save(pair, pair->cnt); - } - if ((debug & MINCOV) && trace) { - printf("cost is %d ", cost); - print_pair(pair); - } -} - -/* - pair_all: brute-force approach to try all possible pairings - - pair_strategy is: - 2) for espresso - 3) for minimize_exact - 4) for phase assignment -*/ - -pair_all(PLA, pair_strategy) -pPLA PLA; -int pair_strategy; -{ - ppair pair; - pset candidate; - - global_PLA = PLA; - pair_minim_strategy = pair_strategy; - best_cost = PLA->F->count + 1; - best_pair = NULL; - best_phase = NULL; - best_F = best_D = best_R = NULL; - pair = pair_new(cube.num_binary_vars); - candidate = set_fill(set_new(cube.num_binary_vars), cube.num_binary_vars); - - generate_all_pairs(pair, cube.num_binary_vars, candidate, minimize_pair); - - pair_free(pair); - set_free(candidate); - - PLA->pair = best_pair; - PLA->phase = best_phase; -/* not really necessary - if (phase != NULL) - (void) set_phase(PLA->phase); -*/ - set_pair(PLA); - printf("# "); - print_pair(PLA->pair); - - sf_free(PLA->F); - sf_free(PLA->D); - sf_free(PLA->R); - PLA->F = best_F; - PLA->D = best_D; - PLA->R = best_R; -} - - -/* - * minimize_pair -- called as each pair is generated - */ -int minimize_pair(pair) -ppair pair; -{ - pcover Fsave, Dsave, Rsave; - int i, xnum_binary_vars, xnum_vars, *xpart_size; - - /* save the original covers */ - Fsave = sf_save(global_PLA->F); - Dsave = sf_save(global_PLA->D); - Rsave = sf_save(global_PLA->R); - - /* save the original cube structure */ - xnum_binary_vars = cube.num_binary_vars; - xnum_vars = cube.num_vars; - xpart_size = ALLOC(int, cube.num_vars); - for(i = 0; i < cube.num_vars; i++) - xpart_size[i] = cube.part_size[i]; - - /* setup the paired variables */ - global_PLA->pair = pair; - set_pair1(global_PLA, /* adjust_labels */ FALSE); - - /* call the minimizer */ - if (summary) - print_pair(pair); - switch(pair_minim_strategy) { - case 2: - EXEC_S(phase_assignment(global_PLA,0), "OPO ", global_PLA->F); - if (summary) - printf("# phase is %s\n", pc1(global_PLA->phase)); - break; - case 1: - EXEC_S(global_PLA->F = minimize_exact(global_PLA->F, global_PLA->D, - global_PLA->R, 1), "EXACT ", global_PLA->F); - break; - case 0: - EXEC_S(global_PLA->F = espresso(global_PLA->F, global_PLA->D, - global_PLA->R), "ESPRESSO ", global_PLA->F); - break; - default: - break; - } - - /* see if we have a new best solution */ - if (global_PLA->F->count < best_cost) { - best_cost = global_PLA->F->count; - best_pair = pair_save(pair, pair->cnt); - best_phase = global_PLA->phase!=NULL?set_save(global_PLA->phase):NULL; - if (best_F != NULL) sf_free(best_F); - if (best_D != NULL) sf_free(best_D); - if (best_R != NULL) sf_free(best_R); - best_F = sf_save(global_PLA->F); - best_D = sf_save(global_PLA->D); - best_R = sf_save(global_PLA->R); - } - - /* restore the original cube structure -- free the new ones */ - setdown_cube(); - FREE(cube.part_size); - cube.num_binary_vars = xnum_binary_vars; - cube.num_vars = xnum_vars; - cube.part_size = xpart_size; - cube_setup(); - - /* restore the original cover(s) -- free the new ones */ - sf_free(global_PLA->F); - sf_free(global_PLA->D); - sf_free(global_PLA->R); - global_PLA->F = Fsave; - global_PLA->D = Dsave; - global_PLA->R = Rsave; - global_PLA->pair = NULL; - global_PLA->phase = NULL; -} - -generate_all_pairs(pair, n, candidate, action) -ppair pair; -int n; -pset candidate; -int (*action)(); -{ - int i, j; - pset recur_candidate; - ppair recur_pair; - - if (set_ord(candidate) < 2) { - (*action)(pair); - return; - } - - recur_pair = pair_save(pair, n); - recur_candidate = set_save(candidate); - - /* Find first variable still in the candidate set */ - for(i = 0; i < n; i++) - if (is_in_set(candidate, i)) - break; - - /* Try all pairs of i with other variables */ - for(j = i+1; j < n; j++) - if (is_in_set(candidate, j)) { - /* pair (i j) -- remove from candidate set for future pairings */ - set_remove(recur_candidate, i); - set_remove(recur_candidate, j); - - /* add to the pair array */ - recur_pair->var1[recur_pair->cnt] = i+1; - recur_pair->var2[recur_pair->cnt] = j+1; - recur_pair->cnt++; - - /* recur looking for the end ... */ - generate_all_pairs(recur_pair, n, recur_candidate, action); - - /* now break this pair, and restore candidate set */ - recur_pair->cnt--; - set_insert(recur_candidate, i); - set_insert(recur_candidate, j); - } - - /* if odd, generate all pairs which do NOT include i */ - if ((set_ord(candidate) % 2) == 1) { - set_remove(recur_candidate, i); - generate_all_pairs(recur_pair, n, recur_candidate, action); - } - - pair_free(recur_pair); - set_free(recur_candidate); -} - -ppair pair_new(n) -register int n; -{ - register ppair pair1; - - pair1 = ALLOC(pair_t, 1); - pair1->cnt = 0; - pair1->var1 = ALLOC(int, n); - pair1->var2 = ALLOC(int, n); - return pair1; -} - - -ppair pair_save(pair, n) -register ppair pair; -register int n; -{ - register int k; - register ppair pair1; - - pair1 = pair_new(n); - pair1->cnt = pair->cnt; - for(k = 0; k < pair->cnt; k++) { - pair1->var1[k] = pair->var1[k]; - pair1->var2[k] = pair->var2[k]; - } - return pair1; -} - - -int pair_free(pair) -register ppair pair; -{ - FREE(pair->var1); - FREE(pair->var2); - FREE(pair); -} diff --git a/src/misc/espresso/part.c b/src/misc/espresso/part.c deleted file mode 100644 index 42843aeb..00000000 --- a/src/misc/espresso/part.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "mincov_int.h" - -static int visit_col(); - -static void -copy_row(A, prow) -register sm_matrix *A; -register sm_row *prow; -{ - register sm_element *p; - - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) sm_insert(A, p->row_num, p->col_num); - } -} - - -static int -visit_row(A, prow, rows_visited, cols_visited) -sm_matrix *A; -sm_row *prow; -int *rows_visited; -int *cols_visited; -{ - sm_element *p; - sm_col *pcol; - - if (! prow->flag) { - prow->flag = 1; - (*rows_visited)++; - if (*rows_visited == A->nrows) { - return 1; - } - for(p = prow->first_col; p != 0; p = p->next_col) { - pcol = sm_get_col(A, p->col_num); - if (! pcol->flag) { - if (visit_col(A, pcol, rows_visited, cols_visited)) { - return 1; - } - } - } - } - return 0; -} - - -static int -visit_col(A, pcol, rows_visited, cols_visited) -sm_matrix *A; -sm_col *pcol; -int *rows_visited; -int *cols_visited; -{ - sm_element *p; - sm_row *prow; - - if (! pcol->flag) { - pcol->flag = 1; - (*cols_visited)++; - if (*cols_visited == A->ncols) { - return 1; - } - for(p = pcol->first_row; p != 0; p = p->next_row) { - prow = sm_get_row(A, p->row_num); - if (! prow->flag) { - if (visit_row(A, prow, rows_visited, cols_visited)) { - return 1; - } - } - } - } - return 0; -} - -int -sm_block_partition(A, L, R) -sm_matrix *A; -sm_matrix **L, **R; -{ - int cols_visited, rows_visited; - register sm_row *prow; - register sm_col *pcol; - - /* Avoid the trivial case */ - if (A->nrows == 0) { - return 0; - } - - /* Reset the visited flags for each row and column */ - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - prow->flag = 0; - } - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) { - pcol->flag = 0; - } - - cols_visited = rows_visited = 0; - if (visit_row(A, A->first_row, &rows_visited, &cols_visited)) { - /* we found all of the rows */ - return 0; - } else { - *L = sm_alloc(); - *R = sm_alloc(); - for(prow = A->first_row; prow != 0; prow = prow->next_row) { - if (prow->flag) { - copy_row(*L, prow); - } else { - copy_row(*R, prow); - } - } - return 1; - } -} diff --git a/src/misc/espresso/primes.c b/src/misc/espresso/primes.c deleted file mode 100644 index 3e40da27..00000000 --- a/src/misc/espresso/primes.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - -static bool primes_consensus_special_cases(); -static pcover primes_consensus_merge(); -static pcover and_with_cofactor(); - - -/* primes_consensus -- generate primes using consensus */ -pcover primes_consensus(T) -pcube *T; /* T will be disposed of */ -{ - register pcube cl, cr; - register int best; - pcover Tnew, Tl, Tr; - - if (primes_consensus_special_cases(T, &Tnew) == MAYBE) { - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, COMPL); - - Tl = primes_consensus(scofactor(T, cl, best)); - Tr = primes_consensus(scofactor(T, cr, best)); - Tnew = primes_consensus_merge(Tl, Tr, cl, cr); - - free_cube(cl); - free_cube(cr); - free_cubelist(T); - } - - return Tnew; -} - -static bool -primes_consensus_special_cases(T, Tnew) -pcube *T; /* will be disposed if answer is determined */ -pcover *Tnew; /* returned only if answer determined */ -{ - register pcube *T1, p, ceil, cof=T[0]; - pcube last; - pcover A; - - /* Check for no cubes in the cover */ - if (T[2] == NULL) { - *Tnew = new_cover(0); - free_cubelist(T); - return TRUE; - } - - /* Check for only a single cube in the cover */ - if (T[3] == NULL) { - *Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2])); - free_cubelist(T); - return TRUE; - } - - /* Check for a row of all 1's (implies function is a tautology) */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, cof)) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - } - } - - /* Check for a column of all 0's which can be factored out */ - ceil = set_save(cof); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - p = new_cube(); - (void) set_diff(p, cube.fullset, ceil); - (void) set_or(cof, cof, p); - free_cube(p); - - A = primes_consensus(T); - foreach_set(A, last, p) { - INLINEset_and(p, p, ceil); - } - *Tnew = A; - set_free(ceil); - return TRUE; - } - set_free(ceil); - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If single active variable not factored out above, then tautology ! */ - if (cdata.vars_active == 1) { - *Tnew = sf_addset(new_cover(1), cube.fullset); - free_cubelist(T); - return TRUE; - - /* Check for unate cover */ - } else if (cdata.vars_unate == cdata.vars_active) { - A = cubeunlist(T); - *Tnew = sf_contain(A); - free_cubelist(T); - return TRUE; - - /* Not much we can do about it */ - } else { - return MAYBE; - } -} - -static pcover -primes_consensus_merge(Tl, Tr, cl, cr) -pcover Tl, Tr; -pcube cl, cr; -{ - register pcube pl, pr, lastl, lastr, pt; - pcover T, Tsave; - - Tl = and_with_cofactor(Tl, cl); - Tr = and_with_cofactor(Tr, cr); - - T = sf_new(500, Tl->sf_size); - pt = T->data; - Tsave = sf_contain(sf_join(Tl, Tr)); - - foreach_set(Tl, lastl, pl) { - foreach_set(Tr, lastr, pr) { - if (cdist01(pl, pr) == 1) { - consensus(pt, pl, pr); - if (++T->count >= T->capacity) { - Tsave = sf_union(Tsave, sf_contain(T)); - T = sf_new(500, Tl->sf_size); - pt = T->data; - } else { - pt += T->wsize; - } - } - } - } - free_cover(Tl); - free_cover(Tr); - - Tsave = sf_union(Tsave, sf_contain(T)); - return Tsave; -} - - -static pcover -and_with_cofactor(A, cof) -pset_family A; -register pset cof; -{ - register pset last, p; - - foreach_set(A, last, p) { - INLINEset_and(p, p, cof); - if (cdist(p, cube.fullset) > 0) { - RESET(p, ACTIVE); - } else { - SET(p, ACTIVE); - } - } - return sf_inactive(A); -} diff --git a/src/misc/espresso/reduce.c b/src/misc/espresso/reduce.c deleted file mode 100644 index 00e4507f..00000000 --- a/src/misc/espresso/reduce.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - module: reduce.c - purpose: Perform the Espresso-II reduction step - - Reduction is a technique used to explore larger regions of the - optimization space. We replace each cube of F with a smaller - cube while still maintaining a cover of the same logic function. -*/ - -#include "espresso.h" - -static bool toggle = TRUE; - - -/* - reduce -- replace each cube in F with its reduction - - The reduction of a cube is the smallest cube contained in the cube - which can replace the cube in the original cover without changing - the cover. This is equivalent to the super cube of all of the - essential points in the cube. This can be computed directly. - - The problem is that the order in which the cubes are reduced can - greatly affect the final result. We alternate between two ordering - strategies: - - (1) Order the cubes in ascending order of distance from the - largest cube breaking ties by ordering cubes of equal distance - in descending order of size (sort_reduce) - - (2) Order the cubes in descending order of the inner-product of - the cube and the column sums (mini_sort) - - The real workhorse of this section is the routine SCCC which is - used to find the Smallest Cube Containing the Complement of a cover. - Reduction as proposed by Espresso-II takes a cube and computes its - maximal reduction as the intersection between the cube and the - smallest cube containing the complement of (F u D - {c}) cofactored - against c. - - As usual, the unate-recursive paradigm is used to compute SCCC. - The SCCC of a unate cover is trivial to compute, and thus we perform - Shannon Cofactor expansion attempting to drive the cover to be unate - as fast as possible. -*/ - -pcover reduce(F, D) -INOUT pcover F; -IN pcover D; -{ - register pcube last, p, cunder, *FD; - - /* Order the cubes */ - if (use_random_order) - F = random_order(F); - else { - F = toggle ? sort_reduce(F) : mini_sort(F, descend); - toggle = ! toggle; - } - - /* Try to reduce each cube */ - FD = cube2list(F, D); - foreach_set(F, last, p) { - cunder = reduce_cube(FD, p); /* reduce the cube */ - if (setp_equal(cunder, p)) { /* see if it actually did */ - SET(p, ACTIVE); /* cube remains active */ - SET(p, PRIME); /* cube remains prime ? */ - } else { - if (debug & REDUCE) { - printf("REDUCE: %s to %s %s\n", - pc1(p), pc2(cunder), print_time(ptime())); - } - set_copy(p, cunder); /* save reduced version */ - RESET(p, PRIME); /* cube is no longer prime */ - if (setp_empty(cunder)) - RESET(p, ACTIVE); /* if null, kill the cube */ - else - SET(p, ACTIVE); /* cube is active */ - } - free_cube(cunder); - } - free_cubelist(FD); - - /* Delete any cubes of F which reduced to the empty cube */ - return sf_inactive(F); -} - -/* reduce_cube -- find the maximal reduction of a cube */ -pcube reduce_cube(FD, p) -IN pcube *FD, p; -{ - pcube cunder; - - cunder = sccc(cofactor(FD, p)); - return set_and(cunder, cunder, p); -} - - -/* sccc -- find Smallest Cube Containing the Complement of a cover */ -pcube sccc(T) -INOUT pcube *T; /* T will be disposed of */ -{ - pcube r; - register pcube cl, cr; - register int best; - static int sccc_level = 0; - - if (debug & REDUCE1) { - debug_print(T, "SCCC", sccc_level++); - } - - if (sccc_special_cases(T, &r) == MAYBE) { - cl = new_cube(); - cr = new_cube(); - best = binate_split_select(T, cl, cr, REDUCE1); - r = sccc_merge(sccc(scofactor(T, cl, best)), - sccc(scofactor(T, cr, best)), cl, cr); - free_cubelist(T); - } - - if (debug & REDUCE1) - printf("SCCC[%d]: result is %s\n", --sccc_level, pc1(r)); - return r; -} - - -pcube sccc_merge(left, right, cl, cr) -INOUT register pcube left, right; /* will be disposed of ... */ -INOUT register pcube cl, cr; /* will be disposed of ... */ -{ - INLINEset_and(left, left, cl); - INLINEset_and(right, right, cr); - INLINEset_or(left, left, right); - free_cube(right); - free_cube(cl); - free_cube(cr); - return left; -} - - -/* - sccc_cube -- find the smallest cube containing the complement of a cube - - By DeMorgan's law and the fact that the smallest cube containing a - cover is the "or" of the positional cubes, it is simple to see that - the SCCC is the universe if the cube has more than two active - variables. If there is only a single active variable, then the - SCCC is merely the bitwise complement of the cube in that - variable. A last special case is no active variables, in which - case the SCCC is empty. - - This is "anded" with the incoming cube result. -*/ -pcube sccc_cube(result, p) -register pcube result, p; -{ - register pcube temp=cube.temp[0], mask; - int var; - - if ((var = cactive(p)) >= 0) { - mask = cube.var_mask[var]; - INLINEset_xor(temp, p, mask); - INLINEset_and(result, result, temp); - } - return result; -} - -/* - * sccc_special_cases -- check the special cases for sccc - */ - -bool sccc_special_cases(T, result) -INOUT pcube *T; /* will be disposed if answer is determined */ -OUT pcube *result; /* returned only if answer determined */ -{ - register pcube *T1, p, temp = cube.temp[1], ceil, cof = T[0]; - pcube *A, *B; - - /* empty cover => complement is universe => SCCC is universe */ - if (T[2] == NULL) { - *result = set_save(cube.fullset); - free_cubelist(T); - return TRUE; - } - - /* row of 1's => complement is empty => SCCC is empty */ - for(T1 = T+2; (p = *T1++) != NULL; ) { - if (full_row(p, cof)) { - *result = new_cube(); - free_cubelist(T); - return TRUE; - } - } - - /* Collect column counts, determine unate variables, etc. */ - massive_count(T); - - /* If cover is unate (or single cube), apply simple rules to find SCCCU */ - if (cdata.vars_unate == cdata.vars_active || T[3] == NULL) { - *result = set_save(cube.fullset); - for(T1 = T+2; (p = *T1++) != NULL; ) { - (void) sccc_cube(*result, set_or(temp, p, cof)); - } - free_cubelist(T); - return TRUE; - } - - /* Check for column of 0's (which can be easily factored( */ - ceil = set_save(cof); - for(T1 = T+2; (p = *T1++) != NULL; ) { - INLINEset_or(ceil, ceil, p); - } - if (! setp_equal(ceil, cube.fullset)) { - *result = sccc_cube(set_save(cube.fullset), ceil); - if (setp_equal(*result, cube.fullset)) { - free_cube(ceil); - } else { - *result = sccc_merge(sccc(cofactor(T,ceil)), - set_save(cube.fullset), ceil, *result); - } - free_cubelist(T); - return TRUE; - } - free_cube(ceil); - - /* Single active column at this point => tautology => SCCC is empty */ - if (cdata.vars_active == 1) { - *result = new_cube(); - free_cubelist(T); - return TRUE; - } - - /* Check for components */ - if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T)/2) { - if (cubelist_partition(T, &A, &B, debug & REDUCE1) == 0) { - return MAYBE; - } else { - free_cubelist(T); - *result = sccc(A); - ceil = sccc(B); - (void) set_and(*result, *result, ceil); - set_free(ceil); - return TRUE; - } - } - - /* Not much we can do about it */ - return MAYBE; -} diff --git a/src/misc/espresso/rows.c b/src/misc/espresso/rows.c deleted file mode 100644 index bf0c0baa..00000000 --- a/src/misc/espresso/rows.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -//#include "port.h" -#include "sparse_int.h" - - -/* - * allocate a new row vector - */ -sm_row * -sm_row_alloc() -{ - register sm_row *prow; - -#ifdef FAST_AND_LOOSE - if (sm_row_freelist == NIL(sm_row)) { - prow = ALLOC(sm_row, 1); - } else { - prow = sm_row_freelist; - sm_row_freelist = prow->next_row; - } -#else - prow = ALLOC(sm_row, 1); -#endif - - prow->row_num = 0; - prow->length = 0; - prow->first_col = prow->last_col = NIL(sm_element); - prow->next_row = prow->prev_row = NIL(sm_row); - prow->flag = 0; - prow->user_word = NIL(char); /* for our user ... */ - return prow; -} - - -/* - * free a row vector -- for FAST_AND_LOOSE, this is real cheap for rows; - * however, freeing a column must still walk down the column discarding - * the elements one-by-one; that is the only use for the extra '-DCOLS' - * compile flag ... - */ -void -sm_row_free(prow) -register sm_row *prow; -{ -#if defined(FAST_AND_LOOSE) && ! defined(COLS) - if (prow->first_col != NIL(sm_element)) { - /* Add the linked list of row items to the free list */ - prow->last_col->next_col = sm_element_freelist; - sm_element_freelist = prow->first_col; - } - - /* Add the row to the free list of rows */ - prow->next_row = sm_row_freelist; - sm_row_freelist = prow; -#else - register sm_element *p, *pnext; - - for(p = prow->first_col; p != 0; p = pnext) { - pnext = p->next_col; - sm_element_free(p); - } - FREE(prow); -#endif -} - - -/* - * duplicate an existing row - */ -sm_row * -sm_row_dup(prow) -register sm_row *prow; -{ - register sm_row *pnew; - register sm_element *p; - - pnew = sm_row_alloc(); - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) sm_row_insert(pnew, p->col_num); - } - return pnew; -} - - -/* - * insert an element into a row vector - */ -sm_element * -sm_row_insert(prow, col) -register sm_row *prow; -register int col; -{ - register sm_element *test, *element; - - /* get a new item, save its address */ - sm_element_alloc(element); - test = element; - sorted_insert(sm_element, prow->first_col, prow->last_col, prow->length, - next_col, prev_col, col_num, col, test); - - /* if item was not used, free it */ - if (element != test) { - sm_element_free(element); - } - - /* either way, return the current new value */ - return test; -} - - -/* - * remove an element from a row vector - */ -void -sm_row_remove(prow, col) -register sm_row *prow; -register int col; -{ - register sm_element *p; - - for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col) - ; - if (p != 0 && p->col_num == col) { - dll_unlink(p, prow->first_col, prow->last_col, - next_col, prev_col, prow->length); - sm_element_free(p); - } -} - - -/* - * find an element (if it is in the row vector) - */ -sm_element * -sm_row_find(prow, col) -sm_row *prow; -int col; -{ - register sm_element *p; - - for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col) - ; - if (p != 0 && p->col_num == col) { - return p; - } else { - return NIL(sm_element); - } -} - -/* - * return 1 if row p2 contains row p1; 0 otherwise - */ -int -sm_row_contains(p1, p2) -sm_row *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_col; - q2 = p2->first_col; - while (q1 != 0) { - if (q2 == 0 || q1->col_num < q2->col_num) { - return 0; - } else if (q1->col_num == q2->col_num) { - q1 = q1->next_col; - q2 = q2->next_col; - } else { - q2 = q2->next_col; - } - } - return 1; -} - - -/* - * return 1 if row p1 and row p2 share an element in common - */ -int -sm_row_intersects(p1, p2) -sm_row *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_col; - q2 = p2->first_col; - if (q1 == 0 || q2 == 0) return 0; - for(;;) { - if (q1->col_num < q2->col_num) { - if ((q1 = q1->next_col) == 0) { - return 0; - } - } else if (q1->col_num > q2->col_num) { - if ((q2 = q2->next_col) == 0) { - return 0; - } - } else { - return 1; - } - } -} - - -/* - * compare two rows, lexical ordering - */ -int -sm_row_compare(p1, p2) -sm_row *p1, *p2; -{ - register sm_element *q1, *q2; - - q1 = p1->first_col; - q2 = p2->first_col; - while(q1 != 0 && q2 != 0) { - if (q1->col_num != q2->col_num) { - return q1->col_num - q2->col_num; - } - q1 = q1->next_col; - q2 = q2->next_col; - } - - if (q1 != 0) { - return 1; - } else if (q2 != 0) { - return -1; - } else { - return 0; - } -} - - -/* - * return the intersection - */ -sm_row * -sm_row_and(p1, p2) -sm_row *p1, *p2; -{ - register sm_element *q1, *q2; - register sm_row *result; - - result = sm_row_alloc(); - q1 = p1->first_col; - q2 = p2->first_col; - if (q1 == 0 || q2 == 0) return result; - for(;;) { - if (q1->col_num < q2->col_num) { - if ((q1 = q1->next_col) == 0) { - return result; - } - } else if (q1->col_num > q2->col_num) { - if ((q2 = q2->next_col) == 0) { - return result; - } - } else { - (void) sm_row_insert(result, q1->col_num); - if ((q1 = q1->next_col) == 0) { - return result; - } - if ((q2 = q2->next_col) == 0) { - return result; - } - } - } -} - -int -sm_row_hash(prow, modulus) -sm_row *prow; -int modulus; -{ - register int sum; - register sm_element *p; - - sum = 0; - for(p = prow->first_col; p != 0; p = p->next_col) { - sum = (sum*17 + p->col_num) % modulus; - } - return sum; -} - -/* - * remove an element from a row vector (given a pointer to the element) - */ -void -sm_row_remove_element(prow, p) -register sm_row *prow; -register sm_element *p; -{ - dll_unlink(p, prow->first_col, prow->last_col, - next_col, prev_col, prow->length); - sm_element_free(p); -} - - -void -sm_row_print(fp, prow) -FILE *fp; -sm_row *prow; -{ - sm_element *p; - - for(p = prow->first_col; p != 0; p = p->next_col) { - (void) fprintf(fp, " %d", p->col_num); - } -} diff --git a/src/misc/espresso/set.c b/src/misc/espresso/set.c deleted file mode 100644 index fce88288..00000000 --- a/src/misc/espresso/set.c +++ /dev/null @@ -1,820 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - * set.c -- routines for maniuplating sets and set families - */ - -/* LINTLIBRARY */ - -#include "espresso.h" -static pset_family set_family_garbage = NULL; - -static int intcpy(d, s, n) -register unsigned int *d, *s; -register long n; -{ - register int i; - for(i = 0; i < n; i++) { - *d++ = *s++; - } -} - - -/* bit_index -- find first bit (from LSB) in a word (MSB=bit n, LSB=bit 0) */ -int bit_index(a) -register unsigned int a; -{ - register int i; - if (a == 0) - return -1; - for(i = 0; (a & 1) == 0; a >>= 1, i++) - ; - return i; -} - - -/* set_ord -- count number of elements in a set */ -int set_ord(a) -register pset a; -{ - register int i, sum = 0; - register unsigned int val; - for(i = LOOP(a); i > 0; i--) - if ((val = a[i]) != 0) - sum += count_ones(val); - return sum; -} - -/* set_dist -- distance between two sets (# elements in common) */ -int set_dist(a, b) -register pset a, b; -{ - register int i, sum = 0; - register unsigned int val; - for(i = LOOP(a); i > 0; i--) - if ((val = a[i] & b[i]) != 0) - sum += count_ones(val); - return sum; -} - -/* set_clear -- make "r" the empty set of "size" elements */ -pset set_clear(r, size) -register pset r; -int size; -{ - register int i = LOOPINIT(size); - *r = i; do r[i] = 0; while (--i > 0); - return r; -} - -/* set_fill -- make "r" the universal set of "size" elements */ -pset set_fill(r, size) -register pset r; -register int size; -{ - register int i = LOOPINIT(size); - *r = i; - r[i] = ~ (unsigned) 0; - r[i] >>= i * BPI - size; - while (--i > 0) - r[i] = ~ (unsigned) 0; - return r; -} - -/* set_copy -- copy set a into set r */ -pset set_copy(r, a) -register pset r, a; -{ - register int i = LOOPCOPY(a); - do r[i] = a[i]; while (--i >= 0); - return r; -} - -/* set_and -- compute intersection of sets "a" and "b" */ -pset set_and(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); - PUTLOOP(r,i); do r[i] = a[i] & b[i]; while (--i > 0); - return r; -} - -/* set_or -- compute union of sets "a" and "b" */ -pset set_or(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); - PUTLOOP(r,i); do r[i] = a[i] | b[i]; while (--i > 0); - return r; -} - -/* set_diff -- compute difference of sets "a" and "b" */ -pset set_diff(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); - PUTLOOP(r,i); do r[i] = a[i] & ~b[i]; while (--i > 0); - return r; -} - -/* set_xor -- compute exclusive-or of sets "a" and "b" */ -pset set_xor(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); -#ifdef IBM_WATC - PUTLOOP(r,i); do r[i] = (a[i]&~b[i]) | (~a[i]&b[i]); while (--i > 0); -#else - PUTLOOP(r,i); do r[i] = a[i] ^ b[i]; while (--i > 0); -#endif - return r; -} - -/* set_merge -- compute "a" & "mask" | "b" & ~ "mask" */ -pset set_merge(r, a, b, mask) -register pset r, a, b, mask; -{ - register int i = LOOP(a); - PUTLOOP(r,i); do r[i] = (a[i]&mask[i]) | (b[i]&~mask[i]); while (--i > 0); - return r; -} - -/* set_andp -- compute intersection of sets "a" and "b" , TRUE if nonempty */ -bool set_andp(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); - register unsigned int x = 0; - PUTLOOP(r,i); do {r[i] = a[i] & b[i]; x |= r[i];} while (--i > 0); - return x != 0; -} - -/* set_orp -- compute union of sets "a" and "b" , TRUE if nonempty */ -bool set_orp(r, a, b) -register pset r, a, b; -{ - register int i = LOOP(a); - register unsigned int x = 0; - PUTLOOP(r,i); do {r[i] = a[i] | b[i]; x |= r[i];} while (--i > 0); - return x != 0; -} - -/* setp_empty -- check if the set "a" is empty */ -bool setp_empty(a) -register pset a; -{ - register int i = LOOP(a); - do if (a[i]) return FALSE; while (--i > 0); - return TRUE; -} - -/* setp_full -- check if the set "a" is the full set of "size" elements */ -bool setp_full(a, size) -register pset a; -register int size; -{ - register int i = LOOP(a); - register unsigned int test; - test = ~ (unsigned) 0; - test >>= i * BPI - size; - if (a[i] != test) - return FALSE; - while (--i > 0) - if (a[i] != (~(unsigned) 0)) - return FALSE; - return TRUE; -} - -/* setp_equal -- check if the set "a" equals set "b" */ -bool setp_equal(a, b) -register pset a, b; -{ - register int i = LOOP(a); - do if (a[i] != b[i]) return FALSE; while (--i > 0); - return TRUE; -} - -/* setp_disjoint -- check if intersection of "a" and "b" is empty */ -bool setp_disjoint(a, b) -register pset a, b; -{ - register int i = LOOP(a); - do if (a[i] & b[i]) return FALSE; while (--i > 0); - return TRUE; -} - -/* setp_implies -- check if "a" implies "b" ("b" contains "a") */ -bool setp_implies(a, b) -register pset a, b; -{ - register int i = LOOP(a); - do if (a[i] & ~b[i]) return FALSE; while (--i > 0); - return TRUE; -} - -/* sf_or -- form the "or" of all sets in a set family */ -pset sf_or(A) -pset_family A; -{ - register pset or, last, p; - - or = set_new(A->sf_size); - foreach_set(A, last, p) - INLINEset_or(or, or, p); - return or; -} - -/* sf_and -- form the "and" of all sets in a set family */ -pset sf_and(A) -pset_family A; -{ - register pset and, last, p; - - and = set_fill(set_new(A->sf_size), A->sf_size); - foreach_set(A, last, p) - INLINEset_and(and, and, p); - return and; -} - -/* sf_active -- make all members of the set family active */ -pset_family sf_active(A) -pset_family A; -{ - register pset p, last; - foreach_set(A, last, p) { - SET(p, ACTIVE); - } - A->active_count = A->count; - return A; -} - - -/* sf_inactive -- remove all inactive cubes in a set family */ -pset_family sf_inactive(A) -pset_family A; -{ - register pset p, last, pdest; - - pdest = A->data; - foreach_set(A, last, p) { - if (TESTP(p, ACTIVE)) { - if (pdest != p) { - INLINEset_copy(pdest, p); - } - pdest += A->wsize; - } else { - A->count--; - } - } - return A; -} - - -/* sf_copy -- copy a set family */ -pset_family sf_copy(R, A) -pset_family R, A; -{ - R->sf_size = A->sf_size; - R->wsize = A->wsize; -/*R->capacity = A->count;*/ -/*R->data = REALLOC(unsigned int, R->data, (long) R->capacity * R->wsize);*/ - R->count = A->count; - R->active_count = A->active_count; - intcpy(R->data, A->data, (long) A->wsize * A->count); - return R; -} - - -/* sf_join -- join A and B into a single set_family */ -pset_family sf_join(A, B) -pset_family A, B; -{ - pset_family R; - long asize = A->count * A->wsize; - long bsize = B->count * B->wsize; - - if (A->sf_size != B->sf_size) fatal("sf_join: sf_size mismatch"); - R = sf_new(A->count + B->count, A->sf_size); - R->count = A->count + B->count; - R->active_count = A->active_count + B->active_count; - intcpy(R->data, A->data, asize); - intcpy(R->data + asize, B->data, bsize); - return R; -} - - -/* sf_append -- append the sets of B to the end of A, and dispose of B */ -pset_family sf_append(A, B) -pset_family A, B; -{ - long asize = A->count * A->wsize; - long bsize = B->count * B->wsize; - - if (A->sf_size != B->sf_size) fatal("sf_append: sf_size mismatch"); - A->capacity = A->count + B->count; - A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize); - intcpy(A->data + asize, B->data, bsize); - A->count += B->count; - A->active_count += B->active_count; - sf_free(B); - return A; -} - - -/* sf_new -- allocate "num" sets of "size" elements each */ -pset_family sf_new(num, size) -int num, size; -{ - pset_family A; - if (set_family_garbage == NULL) { - A = ALLOC(set_family_t, 1); - } else { - A = set_family_garbage; - set_family_garbage = A->next; - } - A->sf_size = size; - A->wsize = SET_SIZE(size); - A->capacity = num; - A->data = ALLOC(unsigned int, (long) A->capacity * A->wsize); - A->count = 0; - A->active_count = 0; - return A; -} - - -/* sf_save -- create a duplicate copy of a set family */ -pset_family sf_save(A) -register pset_family A; -{ - return sf_copy(sf_new(A->count, A->sf_size), A); -} - - -/* sf_free -- free the storage allocated for a set family */ -void sf_free(A) -pset_family A; -{ - FREE(A->data); - A->next = set_family_garbage; - set_family_garbage = A; -} - - -/* sf_cleanup -- free all of the set families from the garbage list */ -void sf_cleanup() -{ - register pset_family p, pnext; - for(p = set_family_garbage; p != (pset_family) NULL; p = pnext) { - pnext = p->next; - FREE(p); - } - set_family_garbage = (pset_family) NULL; -} - - -/* sf_addset -- add a set to the end of a set family */ -pset_family sf_addset(A, s) -pset_family A; -pset s; -{ - register pset p; - - if (A->count >= A->capacity) { - A->capacity = A->capacity + A->capacity/2 + 1; - A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize); - } - p = GETSET(A, A->count++); - INLINEset_copy(p, s); - return A; -} - -/* sf_delset -- delete a set from a set family */ -void sf_delset(A, i) -pset_family A; -int i; -{ (void) set_copy(GETSET(A,i), GETSET(A, --A->count));} - -/* sf_print -- print a set_family as a set (list the element numbers) */ -void sf_print(A) -pset_family A; -{ - char *ps1(); - register pset p; - register int i; - foreachi_set(A, i, p) - printf("A[%d] = %s\n", i, ps1(p)); -} - -/* sf_bm_print -- print a set_family as a bit-matrix */ -void sf_bm_print(A) -pset_family A; -{ - char *pbv1(); - register pset p; - register int i; - foreachi_set(A, i, p) - printf("[%4d] %s\n", i, pbv1(p, A->sf_size)); -} - - -/* sf_write -- output a set family in an unintelligable manner */ -void sf_write(fp, A) -FILE *fp; -pset_family A; -{ - register pset p, last; - (void) fprintf(fp, "%d %d\n", A->count, A->sf_size); - foreach_set(A, last, p) - set_write(fp, p); - (void) fflush(fp); -} - - -/* sf_read -- read a set family written by sf_write */ -pset_family sf_read(fp) -FILE *fp; -{ - int i, j; - register pset p, last; - pset_family A; - - (void) fscanf(fp, "%d %d\n", &i, &j); - A = sf_new(i, j); - A->count = i; - foreach_set(A, last, p) { - (void) fscanf(fp, "%x", p); - for(j = 1; j <= LOOP(p); j++) - (void) fscanf(fp, "%x", p+j); - } - return A; -} - - -/* set_write -- output a set in an unintelligable manner */ -void set_write(fp, a) -register FILE *fp; -register pset a; -{ - register int n = LOOP(a), j; - - for(j = 0; j <= n; j++) { - (void) fprintf(fp, "%x ", a[j]); - if ((j+1) % 8 == 0 && j != n) - (void) fprintf(fp, "\n\t"); - } - (void) fprintf(fp, "\n"); -} - - -/* sf_bm_read -- read a set family written by sf_bm_print (almost) */ -pset_family sf_bm_read(fp) -FILE *fp; -{ - int i, j, rows, cols; - register pset pdest; - pset_family A; - - (void) fscanf(fp, "%d %d\n", &rows, &cols); - A = sf_new(rows, cols); - for(i = 0; i < rows; i++) { - pdest = GETSET(A, A->count++); - (void) set_clear(pdest, A->sf_size); - for(j = 0; j < cols; j++) { - switch(getc(fp)) { - case '0': - break; - case '1': - set_insert(pdest, j); - break; - default: - fatal("Error reading set family"); - } - } - if (getc(fp) != '\n') { - fatal("Error reading set family (at end of line)"); - } - } - return A; -} - - - -/* ps1 -- convert a set into a printable string */ -#define largest_string 120 -static char s1[largest_string]; -char *ps1(a) -register pset a; -{ - register int i, num, l, len = 0, n = NELEM(a); - char temp[20]; - bool first = TRUE; - - s1[len++] = '['; - for(i = 0; i < n; i++) - if (is_in_set(a,i)) { - if (! first) - s1[len++] = ','; - first = FALSE; num = i; - /* Generate digits (reverse order) */ - l = 0; do temp[l++] = num % 10 + '0'; while ((num /= 10) > 0); - /* Copy them back in correct order */ - do s1[len++] = temp[--l]; while (l > 0); - if (len > largest_string-15) { - s1[len++] = '.'; s1[len++] = '.'; s1[len++] = '.'; - break; - } - } - - s1[len++] = ']'; - s1[len++] = '\0'; - return s1; -} - -/* pbv1 -- print bit-vector */ -char *pbv1(s, n) -pset s; -int n; -{ - register int i; - for(i = 0; i < n; i++) - s1[i] = is_in_set(s,i) ? '1' : '0'; - s1[n] = '\0'; - return s1; -} - - -/* set_adjcnt -- adjust the counts for a set by "weight" */ -void -set_adjcnt(a, count, weight) -register pset a; -register int *count, weight; -{ - register int i, base; - register unsigned int val; - - for(i = LOOP(a); i > 0; ) { - for(val = a[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) { - if (val & 1) { - count[base] += weight; - } - } - } -} - - - -/* sf_count -- perform a column sum over a set family */ -int *sf_count(A) -pset_family A; -{ - register pset p, last; - register int i, base, *count; - register unsigned int val; - - count = ALLOC(int, A->sf_size); - for(i = A->sf_size - 1; i >= 0; i--) { - count[i] = 0; - } - - foreach_set(A, last, p) { - for(i = LOOP(p); i > 0; ) { - for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) { - if (val & 1) { - count[base]++; - } - } - } - } - return count; -} - - -/* sf_count_restricted -- perform a column sum over a set family, restricting - * to only the columns which are in r; also, the columns are weighted by the - * number of elements which are in each row - */ -int *sf_count_restricted(A, r) -pset_family A; -register pset r; -{ - register pset p; - register int i, base, *count; - register unsigned int val; - int weight; - pset last; - - count = ALLOC(int, A->sf_size); - for(i = A->sf_size - 1; i >= 0; i--) { - count[i] = 0; - } - - /* Loop for each set */ - foreach_set(A, last, p) { - weight = 1024 / (set_ord(p) - 1); - for(i = LOOP(p); i > 0; ) { - for(val=p[i]&r[i], base= --i<>= 1) { - if (val & 1) { - count[base] += weight; - } - } - } - } - return count; -} - - -/* - * sf_delc -- delete columns first ... last of A - */ -pset_family sf_delc(A, first, last) -pset_family A; -int first, last; -{ - return sf_delcol(A, first, last-first + 1); -} - - -/* - * sf_addcol -- add columns to a set family; includes a quick check to see - * if there is already enough room (and hence, can avoid copying) - */ -pset_family sf_addcol(A, firstcol, n) -pset_family A; -int firstcol, n; -{ - int maxsize; - - /* Check if adding columns at the end ... */ - if (firstcol == A->sf_size) { - /* If so, check if there is already enough room */ - maxsize = BPI * LOOPINIT(A->sf_size); - if ((A->sf_size + n) <= maxsize) { - A->sf_size += n; - return A; - } - } - return sf_delcol(A, firstcol, -n); -} - -/* - * sf_delcol -- add/delete columns to/from a set family - * - * if n > 0 then n columns starting from firstcol are deleted if n < 0 - * then n blank columns are inserted starting at firstcol - * (i.e., the first new column number is firstcol) - * - * This is done by copying columns in the array which is a relatively - * slow operation. - */ -pset_family sf_delcol(A, firstcol, n) -pset_family A; -register int firstcol, n; -{ - register pset p, last, pdest; - register int i; - pset_family B; - - B = sf_new(A->count, A->sf_size - n); - foreach_set(A, last, p) { - pdest = GETSET(B, B->count++); - INLINEset_clear(pdest, B->sf_size); - for(i = 0; i < firstcol; i++) - if (is_in_set(p, i)) - set_insert(pdest, i); - for(i = n > 0 ? firstcol + n : firstcol; i < A->sf_size; i++) - if (is_in_set(p, i)) - set_insert(pdest, i - n); - } - sf_free(A); - return B; -} - - -/* - * sf_copy_col -- copy column "srccol" from "src" to column "dstcol" of "dst" - */ -pset_family sf_copy_col(dst, dstcol, src, srccol) -pset_family dst, src; -int dstcol, srccol; -{ - register pset last, p, pdest; - register int word_test, word_set; - unsigned int bit_set, bit_test; - - /* CHEAT! form these constants outside the loop */ - word_test = WHICH_WORD(srccol); - bit_test = 1 << WHICH_BIT(srccol); - word_set = WHICH_WORD(dstcol); - bit_set = 1 << WHICH_BIT(dstcol); - - pdest = dst->data; - foreach_set(src, last, p) { - if ((p[word_test] & bit_test) != 0) - pdest[word_set] |= bit_set; -/* - * equivalent code for this is ... - * if (is_in_set(p, srccol)) set_insert(pdest, destcol); - */ - pdest += dst->wsize; - } - return dst; -} - - - -/* - * sf_compress -- delete columns from a matrix - */ -pset_family sf_compress(A, c) -pset_family A; /* will be freed */ -register pset c; -{ - register pset p; - register int i, bcol; - pset_family B; - - /* create a clean set family for the result */ - B = sf_new(A->count, set_ord(c)); - for(i = 0; i < A->count; i++) { - p = GETSET(B, B->count++); - INLINEset_clear(p, B->sf_size); - } - - /* copy each column of A which has a 1 in c */ - bcol = 0; - for(i = 0; i < A->sf_size; i++) { - if (is_in_set(c, i)) { - (void) sf_copy_col(B, bcol++, A, i); - } - } - sf_free(A); - return B; -} - - - -/* - * sf_transpose -- transpose a bit matrix - * - * There are trickier ways of doing this, but this works. - */ -pset_family sf_transpose(A) -pset_family A; -{ - pset_family B; - register pset p; - register int i, j; - - B = sf_new(A->sf_size, A->count); - B->count = A->sf_size; - foreachi_set(B, i, p) { - INLINEset_clear(p, B->sf_size); - } - foreachi_set(A, i, p) { - for(j = 0; j < A->sf_size; j++) { - if (is_in_set(p, j)) { - set_insert(GETSET(B, j), i); - } - } - } - sf_free(A); - return B; -} - - -/* - * sf_permute -- permute the columns of a set_family - * - * permute is an array of integers containing column numbers of A which - * are to be retained. - */ -pset_family sf_permute(A, permute, npermute) -pset_family A; -register int *permute, npermute; -{ - pset_family B; - register pset p, last, pdest; - register int j; - - B = sf_new(A->count, npermute); - B->count = A->count; - foreach_set(B, last, p) - INLINEset_clear(p, npermute); - - pdest = B->data; - foreach_set(A, last, p) { - for(j = 0; j < npermute; j++) - if (is_in_set(p, permute[j])) - set_insert(pdest, j); - pdest += B->wsize; - } - sf_free(A); - return B; -} diff --git a/src/misc/espresso/setc.c b/src/misc/espresso/setc.c deleted file mode 100644 index a6112ebc..00000000 --- a/src/misc/espresso/setc.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - setc.c -- massive bit-hacking for performing special "cube"-type - operations on a set - - The basic trick used for binary valued variables is the following: - - If a[w] and b[w] contain a full word of binary variables, then: - - 1) to get the full word of their intersection, we use - - x = a[w] & b[w]; - - - 2) to see if the intersection is null in any variables, we examine - - x = ~(x | x >> 1) & DISJOINT; - - this will have a single 1 in each binary variable for which - the intersection is null. In particular, if this is zero, - then there are no disjoint variables; or, if this is nonzero, - then there is at least one disjoint variable. A "count_ones" - over x will tell in how many variables they have an null - intersection. - - - 3) to get a mask which selects the disjoint variables, we use - - (x | x << 1) - - this provides a selector which can be used to see where - they have an null intersection - - - cdist return distance between two cubes - cdist0 return true if two cubes are distance 0 apart - cdist01 return distance, or 2 if distance exceeds 1 - consensus compute consensus of two cubes distance 1 apart - force_lower expand hack (for now), related to consensus -*/ - -#include "espresso.h" - -/* see if the cube has a full row of 1's (with respect to cof) */ -bool full_row(p, cof) -IN register pcube p, cof; -{ - register int i = LOOP(p); - do if ((p[i] | cof[i]) != cube.fullset[i]) return FALSE; while (--i > 0); - return TRUE; -} - -/* - cdist0 -- return TRUE if a and b are distance 0 apart -*/ - -bool cdist0(a, b) -register pcube a, b; -{ - { /* Check binary variables */ - register int w, last; register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last] & b[last]; - if (~(x | x >> 1) & cube.inmask) - return FALSE; /* disjoint in some variable */ - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w] & b[w]; - if (~(x | x >> 1) & DISJOINT) - return FALSE; /* disjoint in some variable */ - } - } - } - - { /* Check the multiple-valued variables */ - register int w, var, last; register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; last = cube.last_word[var]; - for(w = cube.first_word[var]; w <= last; w++) - if (a[w] & b[w] & mask[w]) - goto nextvar; - return FALSE; /* disjoint in this variable */ - nextvar: ; - } - } - return TRUE; -} - -/* - cdist01 -- return the "distance" between two cubes (defined as the - number of null variables in their intersection). If the distance - exceeds 1, the value 2 is returned. -*/ - -int cdist01(a, b) -register pset a, b; -{ - int dist = 0; - - { /* Check binary variables */ - register int w, last; register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last] & b[last]; - if (x = ~ (x | x >> 1) & cube.inmask) - if ((dist = count_ones(x)) > 1) - return 2; - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w] & b[w]; - if (x = ~ (x | x >> 1) & DISJOINT) - if (dist == 1 || (dist += count_ones(x)) > 1) - return 2; - } - } - } - - { /* Check the multiple-valued variables */ - register int w, var, last; register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; last = cube.last_word[var]; - for(w = cube.first_word[var]; w <= last; w++) - if (a[w] & b[w] & mask[w]) - goto nextvar; - if (++dist > 1) - return 2; - nextvar: ; - } - } - return dist; -} - -/* - cdist -- return the "distance" between two cubes (defined as the - number of null variables in their intersection). -*/ - -int cdist(a, b) -register pset a, b; -{ - int dist = 0; - - { /* Check binary variables */ - register int w, last; register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last] & b[last]; - if (x = ~ (x | x >> 1) & cube.inmask) - dist = count_ones(x); - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w] & b[w]; - if (x = ~ (x | x >> 1) & DISJOINT) - dist += count_ones(x); - } - } - } - - { /* Check the multiple-valued variables */ - register int w, var, last; register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; last = cube.last_word[var]; - for(w = cube.first_word[var]; w <= last; w++) - if (a[w] & b[w] & mask[w]) - goto nextvar; - dist++; - nextvar: ; - } - } - return dist; -} - -/* - force_lower -- Determine which variables of a do not intersect b. -*/ - -pset force_lower(xlower, a, b) -INOUT pset xlower; -IN register pset a, b; -{ - - { /* Check binary variables (if any) */ - register int w, last; register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last] & b[last]; - if (x = ~(x | x >> 1) & cube.inmask) - xlower[last] |= (x | (x << 1)) & a[last]; - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w] & b[w]; - if (x = ~(x | x >> 1) & DISJOINT) - xlower[w] |= (x | (x << 1)) & a[w]; - } - } - } - - { /* Check the multiple-valued variables */ - register int w, var, last; register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; last = cube.last_word[var]; - for(w = cube.first_word[var]; w <= last; w++) - if (a[w] & b[w] & mask[w]) - goto nextvar; - for(w = cube.first_word[var]; w <= last; w++) - xlower[w] |= a[w] & mask[w]; - nextvar: ; - } - } - return xlower; -} - -/* - consensus -- multiple-valued consensus - - Although this looks very messy, the idea is to compute for r the - "and" of the cubes a and b for each variable, unless the "and" is - null in a variable, in which case the "or" of a and b is computed - for this variable. - - Because we don't check how many variables are null in the - intersection of a and b, the returned value for r really only - represents the consensus when a and b are distance 1 apart. -*/ - -void consensus(r, a, b) -INOUT pcube r; -IN register pcube a, b; -{ - INLINEset_clear(r, cube.size); - - { /* Check binary variables (if any) */ - register int w, last; register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - r[last] = x = a[last] & b[last]; - if (x = ~(x | x >> 1) & cube.inmask) - r[last] |= (x | (x << 1)) & (a[last] | b[last]); - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - r[w] = x = a[w] & b[w]; - if (x = ~(x | x >> 1) & DISJOINT) - r[w] |= (x | (x << 1)) & (a[w] | b[w]); - } - } - } - - - { /* Check the multiple-valued variables */ - bool empty; int var; unsigned int x; - register int w, last; register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; - last = cube.last_word[var]; - empty = TRUE; - for(w = cube.first_word[var]; w <= last; w++) - if (x = a[w] & b[w] & mask[w]) - empty = FALSE, r[w] |= x; - if (empty) - for(w = cube.first_word[var]; w <= last; w++) - r[w] |= mask[w] & (a[w] | b[w]); - } - } -} - -/* - cactive -- return the index of the single active variable in - the cube, or return -1 if there are none or more than 2. -*/ - -int cactive(a) -register pcube a; -{ - int active = -1, dist = 0, bit_index(); - - { /* Check binary variables */ - register int w, last; - register unsigned int x; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last]; - if (x = ~ (x & x >> 1) & cube.inmask) { - if ((dist = count_ones(x)) > 1) - return -1; /* more than 2 active variables */ - active = (last-1)*(BPI/2) + bit_index(x) / 2; - } - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w]; - if (x = ~ (x & x >> 1) & DISJOINT) { - if ((dist += count_ones(x)) > 1) - return -1; /* more than 2 active variables */ - active = (w-1)*(BPI/2) + bit_index(x) / 2; - } - } - } - } - - { /* Check the multiple-valued variables */ - register int w, var, last; - register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; - last = cube.last_word[var]; - for(w = cube.first_word[var]; w <= last; w++) - if (mask[w] & ~ a[w]) { - if (++dist > 1) - return -1; - active = var; - break; - } - } - } - return active; -} - -/* - ccommon -- return TRUE if a and b are share "active" variables - active variables include variables that are empty; -*/ - -bool ccommon(a, b, cof) -register pcube a, b, cof; -{ - { /* Check binary variables */ - int last; - register int w; - register unsigned int x, y; - if ((last = cube.inword) != -1) { - - /* Check the partial word of binary variables */ - x = a[last] | cof[last]; - y = b[last] | cof[last]; - if (~(x & x>>1) & ~(y & y>>1) & cube.inmask) - return TRUE; - - /* Check the full words of binary variables */ - for(w = 1; w < last; w++) { - x = a[w] | cof[w]; - y = b[w] | cof[w]; - if (~(x & x>>1) & ~(y & y>>1) & DISJOINT) - return TRUE; - } - } - } - - { /* Check the multiple-valued variables */ - int var; - register int w, last; - register pcube mask; - for(var = cube.num_binary_vars; var < cube.num_vars; var++) { - mask = cube.var_mask[var]; last = cube.last_word[var]; - /* Check for some part missing from a */ - for(w = cube.first_word[var]; w <= last; w++) - if (mask[w] & ~a[w] & ~cof[w]) { - - /* If so, check for some part missing from b */ - for(w = cube.first_word[var]; w <= last; w++) - if (mask[w] & ~b[w] & ~cof[w]) - return TRUE; /* both active */ - break; - } - } - } - return FALSE; -} - -/* - These routines compare two sets (cubes) for the qsort() routine and - return: - - -1 if set a is to precede set b - 0 if set a and set b are equal - 1 if set a is to follow set b - - Usually the SIZE field of the set is assumed to contain the size - of the set (which will save recomputing the set size during the - sort). For distance-1 merging, the global variable cube.temp[0] is - a mask which mask's-out the merging variable. -*/ - -/* descend -- comparison for descending sort on set size */ -int descend(a, b) -pset *a, *b; -{ - register pset a1 = *a, b1 = *b; - if (SIZE(a1) > SIZE(b1)) return -1; - else if (SIZE(a1) < SIZE(b1)) return 1; - else { - register int i = LOOP(a1); - do - if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1; - while (--i > 0); - } - return 0; -} - -/* ascend -- comparison for ascending sort on set size */ -int ascend(a, b) -pset *a, *b; -{ - register pset a1 = *a, b1 = *b; - if (SIZE(a1) > SIZE(b1)) return 1; - else if (SIZE(a1) < SIZE(b1)) return -1; - else { - register int i = LOOP(a1); - do - if (a1[i] > b1[i]) return 1; else if (a1[i] < b1[i]) return -1; - while (--i > 0); - } - return 0; -} - - -/* lex_order -- comparison for "lexical" ordering of cubes */ -int lex_order(a, b) -pset *a, *b; -{ - register pset a1 = *a, b1 = *b; - register int i = LOOP(a1); - do - if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1; - while (--i > 0); - return 0; -} - - -/* d1_order -- comparison for distance-1 merge routine */ -int d1_order(a, b) -pset *a, *b; -{ - register pset a1 = *a, b1 = *b, c1 = cube.temp[0]; - register int i = LOOP(a1); - register unsigned int x1, x2; - do - if ((x1 = a1[i] | c1[i]) > (x2 = b1[i] | c1[i])) return -1; - else if (x1 < x2) return 1; - while (--i > 0); - return 0; -} - - -/* desc1 -- comparison (without indirection) for descending sort */ -/* also has effect of handling NULL pointers,and a NULL pointer has smallest -order */ -int desc1(a, b) -register pset a, b; -{ - if (a == (pset) NULL) - return (b == (pset) NULL) ? 0 : 1; - else if (b == (pset) NULL) - return -1; - if (SIZE(a) > SIZE(b)) return -1; - else if (SIZE(a) < SIZE(b)) return 1; - else { - register int i = LOOP(a); - do - if (a[i] > b[i]) return -1; else if (a[i] < b[i]) return 1; - while (--i > 0); - } - return 0; -} diff --git a/src/misc/espresso/sharp.c b/src/misc/espresso/sharp.c deleted file mode 100644 index 53435078..00000000 --- a/src/misc/espresso/sharp.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - sharp.c -- perform sharp, disjoint sharp, and intersection -*/ - -#include "espresso.h" - -long start_time; - - -/* cv_sharp -- form the sharp product between two covers */ -pcover cv_sharp(A, B) -pcover A, B; -{ - pcube last, p; - pcover T; - - T = new_cover(0); - foreach_set(A, last, p) - T = sf_union(T, cb_sharp(p, B)); - return T; -} - - -/* cb_sharp -- form the sharp product between a cube and a cover */ -pcover cb_sharp(c, T) -pcube c; -pcover T; -{ - if (T->count == 0) { - T = sf_addset(new_cover(1), c); - } else { - start_time = ptime(); - T = cb_recur_sharp(c, T, 0, T->count-1, 0); - } - return T; -} - - -/* recursive formulation to provide balanced merging */ -pcover cb_recur_sharp(c, T, first, last, level) -pcube c; -pcover T; -int first, last, level; -{ - pcover temp, left, right; - int middle; - - if (first == last) { - temp = sharp(c, GETSET(T, first)); - } else { - middle = (first + last) / 2; - left = cb_recur_sharp(c, T, first, middle, level+1); - right = cb_recur_sharp(c, T, middle+1, last, level+1); - temp = cv_intersect(left, right); - if ((debug & SHARP) && level < 4) { - printf("# SHARP[%d]: %4d = %4d x %4d, time = %s\n", - level, temp->count, left->count, right->count, - print_time(ptime() - start_time)); - (void) fflush(stdout); - } - free_cover(left); - free_cover(right); - } - return temp; -} - - -/* sharp -- form the sharp product between two cubes */ -pcover sharp(a, b) -pcube a, b; -{ - register int var; - register pcube d=cube.temp[0], temp=cube.temp[1], temp1=cube.temp[2]; - pcover r = new_cover(cube.num_vars); - - if (cdist0(a, b)) { - set_diff(d, a, b); - for(var = 0; var < cube.num_vars; var++) { - if (! setp_empty(set_and(temp, d, cube.var_mask[var]))) { - set_diff(temp1, a, cube.var_mask[var]); - set_or(GETSET(r, r->count++), temp, temp1); - } - } - } else { - r = sf_addset(r, a); - } - return r; -} - -pcover make_disjoint(A) -pcover A; -{ - pcover R, new; - register pset last, p; - - R = new_cover(0); - foreach_set(A, last, p) { - new = cb_dsharp(p, R); - R = sf_append(R, new); - } - return R; -} - - -/* cv_dsharp -- disjoint-sharp product between two covers */ -pcover cv_dsharp(A, B) -pcover A, B; -{ - register pcube last, p; - pcover T; - - T = new_cover(0); - foreach_set(A, last, p) { - T = sf_union(T, cb_dsharp(p, B)); - } - return T; -} - - -/* cb1_dsharp -- disjoint-sharp product between a cover and a cube */ -pcover cb1_dsharp(T, c) -pcover T; -pcube c; -{ - pcube last, p; - pcover R; - - R = new_cover(T->count); - foreach_set(T, last, p) { - R = sf_union(R, dsharp(p, c)); - } - return R; -} - - -/* cb_dsharp -- disjoint-sharp product between a cube and a cover */ -pcover cb_dsharp(c, T) -pcube c; -pcover T; -{ - pcube last, p; - pcover Y, Y1; - - if (T->count == 0) { - Y = sf_addset(new_cover(1), c); - } else { - Y = new_cover(T->count); - set_copy(GETSET(Y,Y->count++), c); - foreach_set(T, last, p) { - Y1 = cb1_dsharp(Y, p); - free_cover(Y); - Y = Y1; - } - } - return Y; -} - - -/* dsharp -- form the disjoint-sharp product between two cubes */ -pcover dsharp(a, b) -pcube a, b; -{ - register pcube mask, diff, and, temp, temp1 = cube.temp[0]; - int var; - pcover r; - - r = new_cover(cube.num_vars); - - if (cdist0(a, b)) { - diff = set_diff(new_cube(), a, b); - and = set_and(new_cube(), a, b); - mask = new_cube(); - for(var = 0; var < cube.num_vars; var++) { - /* check if position var of "a and not b" is not empty */ - if (! setp_disjoint(diff, cube.var_mask[var])) { - - /* coordinate var equals the difference between a and b */ - temp = GETSET(r, r->count++); - (void) set_and(temp, diff, cube.var_mask[var]); - - /* coordinates 0 ... var-1 equal the intersection */ - INLINEset_and(temp1, and, mask); - INLINEset_or(temp, temp, temp1); - - /* coordinates var+1 .. cube.num_vars equal a */ - set_or(mask, mask, cube.var_mask[var]); - INLINEset_diff(temp1, a, mask); - INLINEset_or(temp, temp, temp1); - } - } - free_cube(diff); - free_cube(and); - free_cube(mask); - } else { - r = sf_addset(r, a); - } - return r; -} - -/* cv_intersect -- form the intersection of two covers */ - -#define MAGIC 500 /* save 500 cubes before containment */ - -pcover cv_intersect(A, B) -pcover A, B; -{ - register pcube pi, pj, lasti, lastj, pt; - pcover T, Tsave = NULL; - - /* How large should each temporary result cover be ? */ - T = new_cover(MAGIC); - pt = T->data; - - /* Form pairwise intersection of each cube of A with each cube of B */ - foreach_set(A, lasti, pi) { - foreach_set(B, lastj, pj) { - if (cdist0(pi, pj)) { - (void) set_and(pt, pi, pj); - if (++T->count >= T->capacity) { - if (Tsave == NULL) - Tsave = sf_contain(T); - else - Tsave = sf_union(Tsave, sf_contain(T)); - T = new_cover(MAGIC); - pt = T->data; - } else - pt += T->wsize; - } - } - } - - - if (Tsave == NULL) - Tsave = sf_contain(T); - else - Tsave = sf_union(Tsave, sf_contain(T)); - return Tsave; -} diff --git a/src/misc/espresso/sminterf.c b/src/misc/espresso/sminterf.c deleted file mode 100644 index 50a6db4e..00000000 --- a/src/misc/espresso/sminterf.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "espresso.h" - - -pset -do_sm_minimum_cover(A) -pset_family A; -{ - sm_matrix *M; - sm_row *sparse_cover; - sm_element *pe; - pset cover; - register int i, base, rownum; - register unsigned val; - register pset last, p; - - M = sm_alloc(); - rownum = 0; - foreach_set(A, last, p) { - foreach_set_element(p, i, val, base) { - (void) sm_insert(M, rownum, base); - } - rownum++; - } - - sparse_cover = sm_minimum_cover(M, NIL(int), 1, 0); - sm_free(M); - - cover = set_new(A->sf_size); - sm_foreach_row_element(sparse_cover, pe) { - set_insert(cover, pe->col_num); - } - sm_row_free(sparse_cover); - - return cover; -} diff --git a/src/misc/espresso/solution.c b/src/misc/espresso/solution.c deleted file mode 100644 index 26119185..00000000 --- a/src/misc/espresso/solution.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#include "mincov_int.h" - - -solution_t * -solution_alloc() -{ - solution_t *sol; - - sol = ALLOC(solution_t, 1); - sol->cost = 0; - sol->row = sm_row_alloc(); - return sol; -} - - -void -solution_free(sol) -solution_t *sol; -{ - sm_row_free(sol->row); - FREE(sol); -} - - -solution_t * -solution_dup(sol) -solution_t *sol; -{ - solution_t *new_sol; - - new_sol = ALLOC(solution_t, 1); - new_sol->cost = sol->cost; - new_sol->row = sm_row_dup(sol->row); - return new_sol; -} - - -void -solution_add(sol, weight, col) -solution_t *sol; -int *weight; -int col; -{ - (void) sm_row_insert(sol->row, col); - sol->cost += WEIGHT(weight, col); -} - - -void -solution_accept(sol, A, weight, col) -solution_t *sol; -sm_matrix *A; -int *weight; -int col; -{ - register sm_element *p, *pnext; - sm_col *pcol; - - solution_add(sol, weight, col); - - /* delete rows covered by this column */ - pcol = sm_get_col(A, col); - for(p = pcol->first_row; p != 0; p = pnext) { - pnext = p->next_row; /* grab it before it disappears */ - sm_delrow(A, p->row_num); - } -} - - -/* ARGSUSED */ -void -solution_reject(sol, A, weight, col) -solution_t *sol; -sm_matrix *A; -int *weight; -int col; -{ - sm_delcol(A, col); -} - - -solution_t * -solution_choose_best(best1, best2) -solution_t *best1, *best2; -{ - if (best1 != NIL(solution_t)) { - if (best2 != NIL(solution_t)) { - if (best1->cost <= best2->cost) { - solution_free(best2); - return best1; - } else { - solution_free(best1); - return best2; - } - } else { - return best1; - } - } else { - if (best2 != NIL(solution_t)) { - return best2; - } else { - return NIL(solution_t); - } - } -} diff --git a/src/misc/espresso/sparse.c b/src/misc/espresso/sparse.c deleted file mode 100644 index 137ce7c1..00000000 --- a/src/misc/espresso/sparse.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - module: sparse.c - - make_sparse is a last-step cleanup to reduce the total number - of literals in the cover. - - This is done by reducing the "sparse" variables (using a modified - version of irredundant rather than reduce), followed by expanding - the "dense" variables (using modified version of expand). -*/ - -#include "espresso.h" - -pcover make_sparse(F, D, R) -pcover F, D, R; -{ - cost_t cost, best_cost; - - cover_cost(F, &best_cost); - - do { - EXECUTE(F = mv_reduce(F, D), MV_REDUCE_TIME, F, cost); - if (cost.total == best_cost.total) - break; - copy_cost(&cost, &best_cost); - - EXECUTE(F = expand(F, R, TRUE), RAISE_IN_TIME, F, cost); - if (cost.total == best_cost.total) - break; - copy_cost(&cost, &best_cost); - } while (force_irredundant); - - return F; -} - -/* - mv_reduce -- perform an "optimal" reduction of the variables which - we desire to be sparse - - This could be done using "reduce" and then saving just the desired - part of the reduction. Instead, this version uses IRRED to find - which cubes of an output are redundant. Note that this gets around - the cube-ordering problem. - - In normal use, it is expected that the cover is irredundant and - hence no cubes will be reduced to the empty cube (however, this is - checked for and such cubes will be deleted) -*/ - -pcover -mv_reduce(F, D) -pcover F, D; -{ - register int i, var; - register pcube p, p1, last; - int index; - pcover F1, D1; - pcube *F_cube_table; - - /* loop for each multiple-valued variable */ - for(var = 0; var < cube.num_vars; var++) { - - if (cube.sparse[var]) { - - /* loop for each part of the variable */ - for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) { - - /* remember mapping of F1 cubes back to F cubes */ - F_cube_table = ALLOC(pcube, F->count); - - /* 'cofactor' against part #i of variable #var */ - F1 = new_cover(F->count); - foreach_set(F, last, p) { - if (is_in_set(p, i)) { - F_cube_table[F1->count] = p; - p1 = GETSET(F1, F1->count++); - (void) set_diff(p1, p, cube.var_mask[var]); - set_insert(p1, i); - } - } - - /* 'cofactor' against part #i of variable #var */ - /* not really necessary -- just more efficient ? */ - D1 = new_cover(D->count); - foreach_set(D, last, p) { - if (is_in_set(p, i)) { - p1 = GETSET(D1, D1->count++); - (void) set_diff(p1, p, cube.var_mask[var]); - set_insert(p1, i); - } - } - - mark_irredundant(F1, D1); - - /* now remove part i from cubes which are redundant */ - index = 0; - foreach_set(F1, last, p1) { - if (! TESTP(p1, ACTIVE)) { - p = F_cube_table[index]; - - /* don't reduce a variable which is full - * (unless it is the output variable) - */ - if (var == cube.num_vars-1 || - ! setp_implies(cube.var_mask[var], p)) { - set_remove(p, i); - } - RESET(p, PRIME); - } - index++; - } - - free_cover(F1); - free_cover(D1); - FREE(F_cube_table); - } - } - } - - /* Check if any cubes disappeared */ - (void) sf_active(F); - for(var = 0; var < cube.num_vars; var++) { - if (cube.sparse[var]) { - foreach_active_set(F, last, p) { - if (setp_disjoint(p, cube.var_mask[var])) { - RESET(p, ACTIVE); - F->active_count--; - } - } - } - } - - if (F->count != F->active_count) { - F = sf_inactive(F); - } - return F; -} diff --git a/src/misc/espresso/sparse.h b/src/misc/espresso/sparse.h deleted file mode 100644 index 212a32ed..00000000 --- a/src/misc/espresso/sparse.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -#ifndef SPARSE_H -#define SPARSE_H - -/* - * sparse.h -- sparse matrix package header file - */ - -typedef struct sm_element_struct sm_element; -typedef struct sm_row_struct sm_row; -typedef struct sm_col_struct sm_col; -typedef struct sm_matrix_struct sm_matrix; - - -/* - * sparse matrix element - */ -struct sm_element_struct { - int row_num; /* row number of this element */ - int col_num; /* column number of this element */ - sm_element *next_row; /* next row in this column */ - sm_element *prev_row; /* previous row in this column */ - sm_element *next_col; /* next column in this row */ - sm_element *prev_col; /* previous column in this row */ - char *user_word; /* user-defined word */ -}; - - -/* - * row header - */ -struct sm_row_struct { - int row_num; /* the row number */ - int length; /* number of elements in this row */ - int flag; /* user-defined word */ - sm_element *first_col; /* first element in this row */ - sm_element *last_col; /* last element in this row */ - sm_row *next_row; /* next row (in sm_matrix linked list) */ - sm_row *prev_row; /* previous row (in sm_matrix linked list) */ - char *user_word; /* user-defined word */ -}; - - -/* - * column header - */ -struct sm_col_struct { - int col_num; /* the column number */ - int length; /* number of elements in this column */ - int flag; /* user-defined word */ - sm_element *first_row; /* first element in this column */ - sm_element *last_row; /* last element in this column */ - sm_col *next_col; /* next column (in sm_matrix linked list) */ - sm_col *prev_col; /* prev column (in sm_matrix linked list) */ - char *user_word; /* user-defined word */ -}; - - -/* - * A sparse matrix - */ -struct sm_matrix_struct { - sm_row **rows; /* pointer to row headers (by row #) */ - int rows_size; /* alloc'ed size of above array */ - sm_col **cols; /* pointer to column headers (by col #) */ - int cols_size; /* alloc'ed size of above array */ - sm_row *first_row; /* first row (linked list of all rows) */ - sm_row *last_row; /* last row (linked list of all rows) */ - int nrows; /* number of rows */ - sm_col *first_col; /* first column (linked list of columns) */ - sm_col *last_col; /* last column (linked list of columns) */ - int ncols; /* number of columns */ - char *user_word; /* user-defined word */ -}; - - -#define sm_get_col(A, colnum) \ - (((colnum) >= 0 && (colnum) < (A)->cols_size) ? \ - (A)->cols[colnum] : (sm_col *) 0) - -#define sm_get_row(A, rownum) \ - (((rownum) >= 0 && (rownum) < (A)->rows_size) ? \ - (A)->rows[rownum] : (sm_row *) 0) - -#define sm_foreach_row(A, prow) \ - for(prow = A->first_row; prow != 0; prow = prow->next_row) - -#define sm_foreach_col(A, pcol) \ - for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) - -#define sm_foreach_row_element(prow, p) \ - for(p = prow->first_col; p != 0; p = p->next_col) - -#define sm_foreach_col_element(pcol, p) \ - for(p = pcol->first_row; p != 0; p = p->next_row) - -#define sm_put(x, val) \ - (x->user_word = (char *) val) - -#define sm_get(type, x) \ - ((type) (x->user_word)) - -extern sm_matrix *sm_alloc(), *sm_alloc_size(), *sm_dup(); -extern void sm_free(), sm_delrow(), sm_delcol(), sm_resize(); -extern void sm_write(), sm_print(), sm_dump(), sm_cleanup(); -extern void sm_copy_row(), sm_copy_col(); -extern void sm_remove(), sm_remove_element(); -extern sm_element *sm_insert(), *sm_find(); -extern sm_row *sm_longest_row(); -extern sm_col *sm_longest_col(); -extern int sm_read(), sm_read_compressed(); - -extern sm_row *sm_row_alloc(), *sm_row_dup(), *sm_row_and(); -extern void sm_row_free(), sm_row_remove(), sm_row_print(); -extern sm_element *sm_row_insert(), *sm_row_find(); -extern int sm_row_contains(), sm_row_intersects(); -extern int sm_row_compare(), sm_row_hash(); - -extern sm_col *sm_col_alloc(), *sm_col_dup(), *sm_col_and(); -extern void sm_col_free(), sm_col_remove(), sm_col_print(); -extern sm_element *sm_col_insert(), *sm_col_find(); -extern int sm_col_contains(), sm_col_intersects(); -extern int sm_col_compare(), sm_col_hash(); - -extern int sm_row_dominance(), sm_col_dominance(), sm_block_partition(); - -#endif diff --git a/src/misc/espresso/sparse_int.h b/src/misc/espresso/sparse_int.h deleted file mode 100644 index 49b2509a..00000000 --- a/src/misc/espresso/sparse_int.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -//#include "port.h" -//#include "utility.h" -#include "sparse.h" - -#include "util_hack.h" // added - - - -/* - * sorted, double-linked list insertion - * - * type: object type - * - * first, last: fields (in header) to head and tail of the list - * count: field (in header) of length of the list - * - * next, prev: fields (in object) to link next and previous objects - * value: field (in object) which controls the order - * - * newval: value field for new object - * e: an object to use if insertion needed (set to actual value used) - */ - -#define sorted_insert(type, first, last, count, next, prev, value, newval, e) \ - if (last == 0) { \ - e->value = newval; \ - first = e; \ - last = e; \ - e->next = 0; \ - e->prev = 0; \ - count++; \ - } else if (last->value < newval) { \ - e->value = newval; \ - last->next = e; \ - e->prev = last; \ - last = e; \ - e->next = 0; \ - count++; \ - } else if (first->value > newval) { \ - e->value = newval; \ - first->prev = e; \ - e->next = first; \ - first = e; \ - e->prev = 0; \ - count++; \ - } else { \ - type *p; \ - for(p = first; p->value < newval; p = p->next) \ - ; \ - if (p->value > newval) { \ - e->value = newval; \ - p = p->prev; \ - p->next->prev = e; \ - e->next = p->next; \ - p->next = e; \ - e->prev = p; \ - count++; \ - } else { \ - e = p; \ - } \ - } - - -/* - * double linked-list deletion - */ -#define dll_unlink(p, first, last, next, prev, count) { \ - if (p->prev == 0) { \ - first = p->next; \ - } else { \ - p->prev->next = p->next; \ - } \ - if (p->next == 0) { \ - last = p->prev; \ - } else { \ - p->next->prev = p->prev; \ - } \ - count--; \ -} - - -#ifdef FAST_AND_LOOSE -extern sm_element *sm_element_freelist; -extern sm_row *sm_row_freelist; -extern sm_col *sm_col_freelist; - -#define sm_element_alloc(newobj) \ - if (sm_element_freelist == NIL(sm_element)) { \ - newobj = ALLOC(sm_element, 1); \ - } else { \ - newobj = sm_element_freelist; \ - sm_element_freelist = sm_element_freelist->next_col; \ - } \ - newobj->user_word = NIL(char); \ - -#define sm_element_free(e) \ - (e->next_col = sm_element_freelist, sm_element_freelist = e) - -#else - -#define sm_element_alloc(newobj) \ - newobj = ALLOC(sm_element, 1); \ - newobj->user_word = NIL(char); -#define sm_element_free(e) \ - FREE(e) -#endif - - -extern void sm_row_remove_element(); -extern void sm_col_remove_element(); - -/* LINTLIBRARY */ diff --git a/src/misc/espresso/unate.c b/src/misc/espresso/unate.c deleted file mode 100644 index bd71207f..00000000 --- a/src/misc/espresso/unate.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - * unate.c -- routines for dealing with unate functions - */ - -#include "espresso.h" - -static pset_family abs_covered(); -static pset_family abs_covered_many(); -static int abs_select_restricted(); - -pcover map_cover_to_unate(T) -pcube *T; -{ - register unsigned int word_test, word_set, bit_test, bit_set; - register pcube p, pA; - pset_family A; - pcube *T1; - int ncol, i; - - A = sf_new(CUBELISTSIZE(T), cdata.vars_unate); - A->count = CUBELISTSIZE(T); - foreachi_set(A, i, p) { - (void) set_clear(p, A->sf_size); - } - ncol = 0; - - for(i = 0; i < cube.size; i++) { - if (cdata.part_zeros[i] > 0) { - assert(ncol <= cdata.vars_unate); - - /* Copy a column from T to A */ - word_test = WHICH_WORD(i); - bit_test = 1 << WHICH_BIT(i); - word_set = WHICH_WORD(ncol); - bit_set = 1 << WHICH_BIT(ncol); - - pA = A->data; - for(T1 = T+2; (p = *T1++) != 0; ) { - if ((p[word_test] & bit_test) == 0) { - pA[word_set] |= bit_set; - } - pA += A->wsize; - } - - ncol++; - } - } - - return A; -} - -pcover map_unate_to_cover(A) -pset_family A; -{ - register int i, ncol, lp; - register pcube p, pB; - int var, nunate, *unate; - pcube last; - pset_family B; - - B = sf_new(A->count, cube.size); - B->count = A->count; - - /* Find the unate variables */ - unate = ALLOC(int, cube.num_vars); - nunate = 0; - for(var = 0; var < cube.num_vars; var++) { - if (cdata.is_unate[var]) { - unate[nunate++] = var; - } - } - - /* Loop for each set of A */ - pB = B->data; - foreach_set(A, last, p) { - - /* Initialize this set of B */ - INLINEset_fill(pB, cube.size); - - /* Now loop for the unate variables; if the part is in A, - * then this variable of B should be a single 1 in the unate - * part. - */ - for(ncol = 0; ncol < nunate; ncol++) { - if (is_in_set(p, ncol)) { - lp = cube.last_part[unate[ncol]]; - for(i = cube.first_part[unate[ncol]]; i <= lp; i++) { - if (cdata.part_zeros[i] == 0) { - set_remove(pB, i); - } - } - } - } - pB += B->wsize; - } - - FREE(unate); - return B; -} - -/* - * unate_compl - */ - -pset_family unate_compl(A) -pset_family A; -{ - register pset p, last; - - /* Make sure A is single-cube containment minimal */ -/* A = sf_rev_contain(A);*/ - - foreach_set(A, last, p) { - PUTSIZE(p, set_ord(p)); - } - - /* Recursively find the complement */ - A = unate_complement(A); - - /* Now, we can guarantee a minimal result by containing the result */ - A = sf_rev_contain(A); - return A; -} - - -/* - * Assume SIZE(p) records the size of each set - */ -pset_family unate_complement(A) -pset_family A; /* disposes of A */ -{ - pset_family Abar; - register pset p, p1, restrict; - register int i; - int max_i, min_set_ord, j; - - /* Check for no sets in the matrix -- complement is the universe */ - if (A->count == 0) { - sf_free(A); - Abar = sf_new(1, A->sf_size); - (void) set_clear(GETSET(Abar, Abar->count++), A->sf_size); - - /* Check for a single set in the maxtrix -- compute de Morgan complement */ - } else if (A->count == 1) { - p = A->data; - Abar = sf_new(A->sf_size, A->sf_size); - for(i = 0; i < A->sf_size; i++) { - if (is_in_set(p, i)) { - p1 = set_clear(GETSET(Abar, Abar->count++), A->sf_size); - set_insert(p1, i); - } - } - sf_free(A); - - } else { - - /* Select splitting variable as the variable which belongs to a set - * of the smallest size, and which has greatest column count - */ - restrict = set_new(A->sf_size); - min_set_ord = A->sf_size + 1; - foreachi_set(A, i, p) { - if (SIZE(p) < min_set_ord) { - set_copy(restrict, p); - min_set_ord = SIZE(p); - } else if (SIZE(p) == min_set_ord) { - set_or(restrict, restrict, p); - } - } - - /* Check for no data (shouldn't happen ?) */ - if (min_set_ord == 0) { - A->count = 0; - Abar = A; - - /* Check for "essential" columns */ - } else if (min_set_ord == 1) { - Abar = unate_complement(abs_covered_many(A, restrict)); - sf_free(A); - foreachi_set(Abar, i, p) { - set_or(p, p, restrict); - } - - /* else, recur as usual */ - } else { - max_i = abs_select_restricted(A, restrict); - - /* Select those rows of A which are not covered by max_i, - * recursively find all minimal covers of these rows, and - * then add back in max_i - */ - Abar = unate_complement(abs_covered(A, max_i)); - foreachi_set(Abar, i, p) { - set_insert(p, max_i); - } - - /* Now recur on A with all zero's on column max_i */ - foreachi_set(A, i, p) { - if (is_in_set(p, max_i)) { - set_remove(p, max_i); - j = SIZE(p) - 1; - PUTSIZE(p, j); - } - } - - Abar = sf_append(Abar, unate_complement(A)); - } - set_free(restrict); - } - - return Abar; -} - -pset_family exact_minimum_cover(T) -IN pset_family T; -{ - register pset p, last, p1; - register int i, n; - int lev, lvl; - pset nlast; - pset_family temp; - long start = ptime(); - struct { - pset_family sf; - int level; - } stack[32]; /* 32 suffices for 2 ** 32 cubes ! */ - - if (T->count <= 0) - return sf_new(1, T->sf_size); - for(n = T->count, lev = 0; n != 0; n >>= 1, lev++) ; - - /* A simple heuristic ordering */ - T = lex_sort(sf_save(T)); - - /* Push a full set on the stack to get things started */ - n = 1; - stack[0].sf = sf_new(1, T->sf_size); - stack[0].level = lev; - set_fill(GETSET(stack[0].sf, stack[0].sf->count++), T->sf_size); - - nlast = GETSET(T, T->count - 1); - foreach_set(T, last, p) { - - /* "unstack" the set into a family */ - temp = sf_new(set_ord(p), T->sf_size); - for(i = 0; i < T->sf_size; i++) - if (is_in_set(p, i)) { - p1 = set_fill(GETSET(temp, temp->count++), T->sf_size); - set_remove(p1, i); - } - stack[n].sf = temp; - stack[n++].level = lev; - - /* Pop the stack and perform (leveled) intersections */ - while (n > 1 && (stack[n-1].level==stack[n-2].level || p == nlast)) { - temp = unate_intersect(stack[n-1].sf, stack[n-2].sf, FALSE); - lvl = MIN(stack[n-1].level, stack[n-2].level) - 1; - if (debug & MINCOV && lvl < 10) { - printf("# EXACT_MINCOV[%d]: %4d = %4d x %4d, time = %s\n", - lvl, temp->count, stack[n-1].sf->count, - stack[n-2].sf->count, print_time(ptime() - start)); - (void) fflush(stdout); - } - sf_free(stack[n-2].sf); - sf_free(stack[n-1].sf); - stack[n-2].sf = temp; - stack[n-2].level = lvl; - n--; - } - } - - temp = stack[0].sf; - p1 = set_fill(set_new(T->sf_size), T->sf_size); - foreach_set(temp, last, p) - INLINEset_diff(p, p1, p); - set_free(p1); - if (debug & MINCOV1) { - printf("MINCOV: family of all minimal coverings is\n"); - sf_print(temp); - } - sf_free(T); /* this is the copy of T we made ... */ - return temp; -} - -/* - * unate_intersect -- intersect two unate covers - * - * If largest_only is TRUE, then only the largest cube(s) are returned - */ - -#define MAGIC 500 /* save 500 cubes before containment */ - -pset_family unate_intersect(A, B, largest_only) -pset_family A, B; -bool largest_only; -{ - register pset pi, pj, lasti, lastj, pt; - pset_family T, Tsave; - bool save; - int maxord, ord; - - /* How large should each temporary result cover be ? */ - T = sf_new(MAGIC, A->sf_size); - Tsave = NULL; - maxord = 0; - pt = T->data; - - /* Form pairwise intersection of each set of A with each cube of B */ - foreach_set(A, lasti, pi) { - - foreach_set(B, lastj, pj) { - - save = set_andp(pt, pi, pj); - - /* Check if we want the largest only */ - if (save && largest_only) { - if ((ord = set_ord(pt)) > maxord) { - /* discard Tsave and T */ - if (Tsave != NULL) { - sf_free(Tsave); - Tsave = NULL; - } - pt = T->data; - T->count = 0; - /* Re-create pt (which was just thrown away) */ - (void) set_and(pt, pi, pj); - maxord = ord; - } else if (ord < maxord) { - save = FALSE; - } - } - - if (save) { - if (++T->count >= T->capacity) { - T = sf_contain(T); - Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T); - T = sf_new(MAGIC, A->sf_size); - pt = T->data; - } else { - pt += T->wsize; - } - } - } - } - - - /* Contain the final result and merge it into Tsave */ - T = sf_contain(T); - Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T); - - return Tsave; -} - -/* - * abs_covered -- after selecting a new column for the selected set, - * create a new matrix which is only those rows which are still uncovered - */ -static pset_family -abs_covered(A, pick) -pset_family A; -register int pick; -{ - register pset last, p, pdest; - register pset_family Aprime; - - Aprime = sf_new(A->count, A->sf_size); - pdest = Aprime->data; - foreach_set(A, last, p) - if (! is_in_set(p, pick)) { - INLINEset_copy(pdest, p); - Aprime->count++; - pdest += Aprime->wsize; - } - return Aprime; -} - - -/* - * abs_covered_many -- after selecting many columns for ther selected set, - * create a new matrix which is only those rows which are still uncovered - */ -static pset_family -abs_covered_many(A, pick_set) -pset_family A; -register pset pick_set; -{ - register pset last, p, pdest; - register pset_family Aprime; - - Aprime = sf_new(A->count, A->sf_size); - pdest = Aprime->data; - foreach_set(A, last, p) - if (setp_disjoint(p, pick_set)) { - INLINEset_copy(pdest, p); - Aprime->count++; - pdest += Aprime->wsize; - } - return Aprime; -} - - -/* - * abs_select_restricted -- select the column of maximum column count which - * also belongs to the set "restrict"; weight each column of a set as - * 1 / (set_ord(p) - 1). - */ -static int -abs_select_restricted(A, restrict) -pset_family A; -pset restrict; -{ - register int i, best_var, best_count, *count; - - /* Sum the elements in these columns */ - count = sf_count_restricted(A, restrict); - - /* Find which variable has maximum weight */ - best_var = -1; - best_count = 0; - for(i = 0; i < A->sf_size; i++) { - if (count[i] > best_count) { - best_var = i; - best_count = count[i]; - } - } - FREE(count); - - if (best_var == -1) - fatal("abs_select_restricted: should not have best_var == -1"); - - return best_var; -} diff --git a/src/misc/espresso/util_old.h b/src/misc/espresso/util_old.h deleted file mode 100644 index 5451cbe9..00000000 --- a/src/misc/espresso/util_old.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Revision Control Information - * - * $Source: /vol/opua/opua2/sis/sis-1.2/common/src/sis/util/RCS/util.h,v $ - * $Author: sis $ - * $Revision: 1.9 $ - * $Date: 1993/06/07 21:04:07 $ - * - */ -#ifndef UTIL_H -#define UTIL_H - -#if defined(_IBMR2) -#ifndef _POSIX_SOURCE -#define _POSIX_SOURCE /* Argh! IBM strikes again */ -#endif -#ifndef _ALL_SOURCE -#define _ALL_SOURCE /* Argh! IBM strikes again */ -#endif -#ifndef _ANSI_C_SOURCE -#define _ANSI_C_SOURCE /* Argh! IBM strikes again */ -#endif -#endif - -#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__) -#include -#endif - -#if defined(_IBMR2) && !defined(__STDC__) -#define _BSD -#endif - -#include "ansi.h" /* since some files don't include sis.h */ - -/* This was taken out and defined at compile time in the SIS Makefile - that uses the OctTools. When the OctTools are used, USE_MM is defined, - because the OctTools contain libmm.a. Otherwise, USE_MM is not defined, - since the mm package is not distributed with SIS, only with Oct. */ - -/* #define USE_MM */ /* choose libmm.a as the memory allocator */ - -#define NIL(type) ((type *) 0) - -#ifdef USE_MM -/* - * assumes the memory manager is libmm.a - * - allows malloc(0) or realloc(obj, 0) - * - catches out of memory (and calls MMout_of_memory()) - * - catch free(0) and realloc(0, size) in the macros - */ -#define ALLOC(type, num) \ - ((type *) malloc(sizeof(type) * (num))) -#define REALLOC(type, obj, num) \ - (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num))) -#define FREE(obj) \ - ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#else -/* - * enforce strict semantics on the memory allocator - * - when in doubt, delete the '#define USE_MM' above - */ -#define ALLOC(type, num) \ - ((type *) MMalloc((long) sizeof(type) * (long) (num))) -#define REALLOC(type, obj, num) \ - ((type *) MMrealloc((char *) (obj), (long) sizeof(type) * (long) (num))) -#define FREE(obj) \ - ((obj) ? (free((void *) (obj)), (obj) = 0) : 0) -#endif - - -/* Ultrix (and SABER) have 'fixed' certain functions which used to be int */ -#if defined(ultrix) || defined(SABER) || defined(aiws) || defined(__hpux) || defined(__STDC__) || defined(apollo) -#define VOID_HACK void -#else -#define VOID_HACK int -#endif - - -/* No machines seem to have much of a problem with these */ -#include -#include - - -/* Some machines fail to define some functions in stdio.h */ -#if !defined(__STDC__) && !defined(sprite) && !defined(_IBMR2) && !defined(__osf__) -extern FILE *popen(), *tmpfile(); -extern int pclose(); -#ifndef clearerr /* is a macro on many machines, but not all */ -extern VOID_HACK clearerr(); -#endif -#ifndef rewind -extern VOID_HACK rewind(); -#endif -#endif - -#ifndef PORT_H -#include -#include -#if defined(ultrix) -#if defined(_SIZE_T_) -#define ultrix4 -#else -#if defined(SIGLOST) -#define ultrix3 -#else -#define ultrix2 -#endif -#endif -#endif -#endif - -/* most machines don't give us a header file for these */ -#if defined(__STDC__) || defined(sprite) || defined(_IBMR2) || defined(__osf__) || defined(sunos4) || defined(__hpux) -#include -#if defined(__hpux) -#include /* For perror() defininition */ -#endif /* __hpux */ -#else -extern VOID_HACK abort(), free(), exit(), perror(); -extern char *getenv(); -#ifdef ultrix4 -extern void *malloc(), *realloc(), *calloc(); -#else -extern char *malloc(), *realloc(), *calloc(); -#endif -#if defined(aiws) -extern int sprintf(); -#else -#ifndef _IBMR2 -extern char *sprintf(); -#endif -#endif -extern int system(); -extern double atof(); -#endif - -#ifndef PORT_H -#if defined(ultrix3) || defined(sunos4) || defined(_IBMR2) || defined(__STDC__) -#define SIGNAL_FN void -#else -/* sequent, ultrix2, 4.3BSD (vax, hp), sunos3 */ -#define SIGNAL_FN int -#endif -#endif - -/* some call it strings.h, some call it string.h; others, also have memory.h */ -#if defined(__STDC__) || defined(sprite) -#include -#else -#if defined(ultrix4) || defined(__hpux) -#include -#else -#if defined(_IBMR2) || defined(__osf__) -#include -#include -#else -/* ANSI C string.h -- 1/11/88 Draft Standard */ -/* ugly, awful hack */ -#ifndef PORT_H -extern char *strcpy(), *strncpy(), *strcat(), *strncat(), *strerror(); -extern char *strpbrk(), *strtok(), *strchr(), *strrchr(), *strstr(); -extern int strcoll(), strxfrm(), strncmp(), strlen(), strspn(), strcspn(); -extern char *memmove(), *memccpy(), *memchr(), *memcpy(), *memset(); -extern int memcmp(), strcmp(); -#endif -#endif -#endif -#endif - -/* a few extras */ -#if defined(__hpux) -#define random() lrand48() -#define srandom(a) srand48(a) -#define bzero(a,b) memset(a, 0, b) -#else -#if !defined(__osf__) && !defined(linux) -/* these are defined as macros in stdlib.h */ -extern VOID_HACK srandom(); -extern long random(); -#endif -#endif - -/* code from sis-1.3 commented out below -#if defined(__STDC__) || defined(sprite) -#include -#else -#ifndef NDEBUG -#define assert(ex) {\ - if (! (ex)) {\ - (void) fprintf(stderr,\ - "Assertion failed: file %s, line %d\n\"%s\"\n",\ - __FILE__, __LINE__, "ex");\ - (void) fflush(stdout);\ - abort();\ - }\ -} -#else -#define assert(ex) {ex;} -#endif -#endif -*/ - - /* Sunil 5/3/97: - sis-1.4: dont let the assert call go to the OS, since - much of the code in SIS has actual computation done in - the assert function. %$#$@@#! The OS version of assert - will do nothing if NDEBUG is set. We cant let that happen... - */ -# ifdef NDEBUG -# define assert(ex) {ex;} -# else -# define assert(ex) {\ - if (! (ex)) {\ - (void) fprintf(stderr,\ - "Assertion failed: file %s, line %d\n\"%s\"\n",\ - __FILE__, __LINE__, "ex");\ - (void) fflush(stdout);\ - abort();\ - }\ -} -# endif - - -#define fail(why) {\ - (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\ - __FILE__, __LINE__, why);\ - (void) fflush(stdout);\ - abort();\ -} - - -#ifdef lint -#undef putc /* correct lint '_flsbuf' bug */ -#undef ALLOC /* allow for lint -h flag */ -#undef REALLOC -#define ALLOC(type, num) (((type *) 0) + (num)) -#define REALLOC(type, obj, num) ((obj) + (num)) -#endif - -/* -#if !defined(__osf__) -#define MAXPATHLEN 1024 -#endif -*/ - -/* These arguably do NOT belong in util.h */ -#ifndef ABS -#define ABS(a) ((a) < 0 ? -(a) : (a)) -#endif -#ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - - -#ifndef USE_MM -EXTERN void MMout_of_memory ARGS((long)); -EXTERN char *MMalloc ARGS((long)); -EXTERN char *MMrealloc ARGS((char *, long)); -EXTERN void MMfree ARGS((char *)); -#endif - -EXTERN void util_print_cpu_stats ARGS((FILE *)); -EXTERN long util_cpu_time ARGS((void)); -EXTERN void util_getopt_reset ARGS((void)); -EXTERN int util_getopt ARGS((int, char **, char *)); -EXTERN char *util_path_search ARGS((char *)); -EXTERN char *util_file_search ARGS((char *, char *, char *)); -EXTERN int util_pipefork ARGS((char **, FILE **, FILE **, int *)); -EXTERN char *util_print_time ARGS((long)); -EXTERN int util_save_image ARGS((char *, char *)); -EXTERN char *util_strsav ARGS((char *)); -EXTERN int util_do_nothing ARGS((void)); -EXTERN char *util_tilde_expand ARGS((char *)); -EXTERN char *util_tempnam ARGS((char *, char *)); -EXTERN FILE *util_tmpfile ARGS((void)); -EXTERN long getSoftDataLimit(); - -#define ptime() util_cpu_time() -#define print_time(t) util_print_time(t) - -/* util_getopt() global variables (ack !) */ -extern int util_optind; -extern char *util_optarg; - -#include -#ifndef HUGE_VAL -#ifndef HUGE -#define HUGE 8.9884656743115790e+307 -#endif -#define HUGE_VAL HUGE -#endif -#ifndef MAXINT -#define MAXINT (1 << 30) -#endif - -#include -#endif diff --git a/src/misc/espresso/verify.c b/src/misc/espresso/verify.c deleted file mode 100644 index 64342787..00000000 --- a/src/misc/espresso/verify.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Revision Control Information - * - * $Source$ - * $Author$ - * $Revision$ - * $Date$ - * - */ -/* - */ - -#include "espresso.h" - -/* - * verify -- check that all minterms of F are contained in (Fold u Dold) - * and that all minterms of Fold are contained in (F u Dold). - */ -bool verify(F, Fold, Dold) -pcover F, Fold, Dold; -{ - pcube p, last, *FD; - bool verify_error = FALSE; - - /* Make sure the function didn't grow too large */ - FD = cube2list(Fold, Dold); - foreach_set(F, last, p) - if (! cube_is_covered(FD, p)) { - printf("some minterm in F is not covered by Fold u Dold\n"); - verify_error = TRUE; - if (verbose_debug) printf("%s\n", pc1(p)); else break; - } - free_cubelist(FD); - - /* Make sure minimized function covers the original function */ - FD = cube2list(F, Dold); - foreach_set(Fold, last, p) - if (! cube_is_covered(FD, p)) { - printf("some minterm in Fold is not covered by F u Dold\n"); - verify_error = TRUE; - if (verbose_debug) printf("%s\n", pc1(p)); else break; - } - free_cubelist(FD); - - return verify_error; -} - - - -/* - * PLA_verify -- verify that two PLA's are identical - * - * If names are given, row and column permutations are done to make - * the comparison meaningful. - * - */ -bool PLA_verify(PLA1, PLA2) -pPLA PLA1, PLA2; -{ - /* Check if both have names given; if so, attempt to permute to - * match the names - */ - if (PLA1->label != NULL && PLA1->label[0] != NULL && - PLA2->label != NULL && PLA2->label[0] != NULL) { - PLA_permute(PLA1, PLA2); - } else { - (void) fprintf(stderr, "Warning: cannot permute columns without names\n"); - return TRUE; - } - - if (PLA1->F->sf_size != PLA2->F->sf_size) { - (void) fprintf(stderr, "PLA_verify: PLA's are not the same size\n"); - return TRUE; - } - - return verify(PLA2->F, PLA1->F, PLA1->D); -} - - - -/* - * Permute the columns of PLA1 so that they match the order of PLA2 - * Discard any columns of PLA1 which are not in PLA2 - * Association is strictly by the names of the columns of the cover. - */ -PLA_permute(PLA1, PLA2) -pPLA PLA1, PLA2; -{ - register int i, j, *permute, npermute; - register char *labi; - char **label; - - /* determine which columns of PLA1 to save, and place these in the list - * "permute"; the order in this list is the final output order - */ - npermute = 0; - permute = ALLOC(int, PLA2->F->sf_size); - for(i = 0; i < PLA2->F->sf_size; i++) { - labi = PLA2->label[i]; - for(j = 0; j < PLA1->F->sf_size; j++) { - if (strcmp(labi, PLA1->label[j]) == 0) { - permute[npermute++] = j; - break; - } - } - } - - /* permute columns */ - if (PLA1->F != NULL) { - PLA1->F = sf_permute(PLA1->F, permute, npermute); - } - if (PLA1->R != NULL) { - PLA1->R = sf_permute(PLA1->R, permute, npermute); - } - if (PLA1->D != NULL) { - PLA1->D = sf_permute(PLA1->D, permute, npermute); - } - - /* permute the labels */ - label = ALLOC(char *, cube.size); - for(i = 0; i < npermute; i++) { - label[i] = PLA1->label[permute[i]]; - } - for(i = npermute; i < cube.size; i++) { - label[i] = NULL; - } - FREE(PLA1->label); - PLA1->label = label; - - FREE(permute); -} - - - -/* - * check_consistency -- test that the ON-set, OFF-set and DC-set form - * a partition of the boolean space. - */ -bool check_consistency(PLA) -pPLA PLA; -{ - bool verify_error = FALSE; - pcover T; - - T = cv_intersect(PLA->F, PLA->D); - if (T->count == 0) - printf("ON-SET and DC-SET are disjoint\n"); - else { - printf("Some minterm(s) belong to both the ON-SET and DC-SET !\n"); - if (verbose_debug) - cprint(T); - verify_error = TRUE; - } - (void) fflush(stdout); - free_cover(T); - - T = cv_intersect(PLA->F, PLA->R); - if (T->count == 0) - printf("ON-SET and OFF-SET are disjoint\n"); - else { - printf("Some minterm(s) belong to both the ON-SET and OFF-SET !\n"); - if (verbose_debug) - cprint(T); - verify_error = TRUE; - } - (void) fflush(stdout); - free_cover(T); - - T = cv_intersect(PLA->D, PLA->R); - if (T->count == 0) - printf("DC-SET and OFF-SET are disjoint\n"); - else { - printf("Some minterm(s) belong to both the OFF-SET and DC-SET !\n"); - if (verbose_debug) - cprint(T); - verify_error = TRUE; - } - (void) fflush(stdout); - free_cover(T); - - if (tautology(cube3list(PLA->F, PLA->D, PLA->R))) - printf("Union of ON-SET, OFF-SET and DC-SET is the universe\n"); - else { - T = complement(cube3list(PLA->F, PLA->D, PLA->R)); - printf("There are minterms left unspecified !\n"); - if (verbose_debug) - cprint(T); - verify_error = TRUE; - free_cover(T); - } - (void) fflush(stdout); - return verify_error; -} diff --git a/src/misc/extra/extra.h b/src/misc/extra/extra.h deleted file mode 100644 index 314257a2..00000000 --- a/src/misc/extra/extra.h +++ /dev/null @@ -1,626 +0,0 @@ -/**CFile**************************************************************** - - FileName [extra.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [Various reusable software utilities.] - - Description [This library contains a number of operators and - traversal routines developed to extend the functionality of - CUDD v.2.3.x, by Fabio Somenzi (http://vlsi.colorado.edu/~fabio/) - To compile your code with the library, #include "extra.h" - in your source files and link your project to CUDD and this - library. Use the library at your own risk and with caution. - Note that debugging of some operators still continues.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extra.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __EXTRA_H__ -#define __EXTRA_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#endif - -/*---------------------------------------------------------------------------*/ -/* Nested includes */ -/*---------------------------------------------------------------------------*/ - -// this include should be the first one in the list -// it is used to catch memory leaks on Windows -#include "leaks.h" - -#include -#include -#include -#include -#include -#include "st.h" -#include "cuddInt.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; -#ifdef WIN32 -typedef unsigned __int64 uint64; -#else -typedef unsigned long long uint64; -#endif - -/* constants of the manager */ -#define b0 Cudd_Not((dd)->one) -#define b1 (dd)->one -#define z0 (dd)->zero -#define z1 (dd)->one -#define a0 (dd)->zero -#define a1 (dd)->one - -// hash key macros -#define hashKey1(a,TSIZE) \ -((unsigned)(a) % TSIZE) - -#define hashKey2(a,b,TSIZE) \ -(((unsigned)(a) + (unsigned)(b) * DD_P1) % TSIZE) - -#define hashKey3(a,b,c,TSIZE) \ -(((((unsigned)(a) + (unsigned)(b)) * DD_P1 + (unsigned)(c)) * DD_P2 ) % TSIZE) - -#define hashKey4(a,b,c,d,TSIZE) \ -((((((unsigned)(a) + (unsigned)(b)) * DD_P1 + (unsigned)(c)) * DD_P2 + \ - (unsigned)(d)) * DD_P3) % TSIZE) - -#define hashKey5(a,b,c,d,e,TSIZE) \ -(((((((unsigned)(a) + (unsigned)(b)) * DD_P1 + (unsigned)(c)) * DD_P2 + \ - (unsigned)(d)) * DD_P3 + (unsigned)(e)) * DD_P1) % TSIZE) - -#ifndef PRT -#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) -#define PRTn(a,t) printf("%s = ", (a)); printf("%6.2f sec ", (float)(t)/(float)(CLOCKS_PER_SEC)) -#endif - -#ifndef PRTP -#define PRTP(a,t,T) printf("%s = ", (a)); printf("%6.2f sec (%6.2f %%)\n", (float)(t)/(float)(CLOCKS_PER_SEC), (T)? 100.0*(t)/(T) : 0.0) -#endif - -/*===========================================================================*/ -/* Various Utilities */ -/*===========================================================================*/ - -/*=== extraBddAuto.c ========================================================*/ - -extern DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ); -extern DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ); -extern DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ); -extern DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ); -extern DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ); -extern DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ); -extern DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ); - -extern DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace ); -extern DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bSpace ); - -extern DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace ); -extern DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ); -extern DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ); -extern DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ); -extern DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ); - -extern DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ); -extern DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ); -extern DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ); -extern DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ); - -extern DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars ); -extern DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations ); - -/*=== extraBddCas.c =============================================================*/ - -/* performs the binary encoding of the set of function using the given vars */ -extern DdNode * Extra_bddEncodingBinary( DdManager * dd, DdNode ** pbFuncs, int nFuncs, DdNode ** pbVars, int nVars ); -/* solves the column encoding problem using a sophisticated method */ -extern DdNode * Extra_bddEncodingNonStrict( DdManager * dd, DdNode ** pbColumns, int nColumns, DdNode * bVarsCol, DdNode ** pCVars, int nMulti, int * pSimple ); -/* collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root */ -extern st_table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel ); -/* collects the nodes under the cut starting from the given set of ADD nodes */ -extern int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel ); -/* find the profile of a DD (the number of edges crossing each level) */ -extern int Extra_ProfileWidth( DdManager * dd, DdNode * F, int * Profile, int CutLevel ); - -/*=== extraBddMisc.c ========================================================*/ - -extern DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ); -extern DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ); -extern DdNode * Extra_bddRemapUp( DdManager * dd, DdNode * bF ); -extern DdNode * Extra_bddMove( DdManager * dd, DdNode * bF, int fShiftUp ); -extern DdNode * extraBddMove( DdManager * dd, DdNode * bF, DdNode * bFlag ); -extern void Extra_StopManager( DdManager * dd ); -extern void Extra_bddPrint( DdManager * dd, DdNode * F ); -extern void extraDecomposeCover( DdManager* dd, DdNode* zC, DdNode** zC0, DdNode** zC1, DdNode** zC2 ); -extern int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ); -extern int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ); -extern int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ); -extern int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ); -extern int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ); -extern int * Extra_SupportArray( DdManager * dd, DdNode * F, int * support ); -extern int * Extra_VectorSupportArray( DdManager * dd, DdNode ** F, int n, int * support ); -extern DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ); -extern DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ); -extern DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ); -extern DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ); -extern DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ); -extern int Extra_bddIsVar( DdNode * bFunc ); -extern DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ); -extern DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ); -extern DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ); -extern DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ); -extern void Extra_bddPermuteArray( DdManager * dd, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ); - -/*=== extraBddKmap.c ================================================================*/ - -/* displays the Karnaugh Map of a function */ -extern void Extra_PrintKMap( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nVars, DdNode ** XVars, int fSuppType, char ** pVarNames ); -/* displays the Karnaugh Map of a relation */ -extern void Extra_PrintKMapRelation( FILE * pFile, DdManager * dd, DdNode * OnSet, DdNode * OffSet, int nXVars, int nYVars, DdNode ** XVars, DdNode ** YVars ); - -/*=== extraBddSymm.c =================================================================*/ - -typedef struct Extra_SymmInfo_t_ Extra_SymmInfo_t; -struct Extra_SymmInfo_t_ { - int nVars; // the number of variables in the support - int nVarsMax; // the number of variables in the DD manager - int nSymms; // the number of pair-wise symmetries - int nNodes; // the number of nodes in a ZDD (if applicable) - int * pVars; // the list of all variables present in the support - char ** pSymms; // the symmetry information -}; - -/* computes the classical symmetry information for the function - recursive */ -extern Extra_SymmInfo_t * Extra_SymmPairsCompute( DdManager * dd, DdNode * bFunc ); -/* computes the classical symmetry information for the function - using naive approach */ -extern Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ); -extern int Extra_bddCheckVarsSymmetricNaive( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); - -/* allocates the data structure */ -extern Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ); -/* deallocates the data structure */ -extern void Extra_SymmPairsDissolve( Extra_SymmInfo_t * ); -/* print the contents the data structure */ -extern void Extra_SymmPairsPrint( Extra_SymmInfo_t * ); -/* converts the ZDD into the Extra_SymmInfo_t structure */ -extern Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bVars ); - -/* computes the classical symmetry information as a ZDD */ -extern DdNode * Extra_zddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); -extern DdNode * extraZddSymmPairsCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); -/* returns a singleton-set ZDD containing all variables that are symmetric with the given one */ -extern DdNode * Extra_zddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); -extern DdNode * extraZddGetSymmetricVars( DdManager * dd, DdNode * bF, DdNode * bG, DdNode * bVars ); -/* converts a set of variables into a set of singleton subsets */ -extern DdNode * Extra_zddGetSingletons( DdManager * dd, DdNode * bVars ); -extern DdNode * extraZddGetSingletons( DdManager * dd, DdNode * bVars ); -/* filters the set of variables using the support of the function */ -extern DdNode * Extra_bddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); -extern DdNode * extraBddReduceVarSet( DdManager * dd, DdNode * bVars, DdNode * bF ); - -/* checks the possibility that the two vars are symmetric */ -extern int Extra_bddCheckVarsSymmetric( DdManager * dd, DdNode * bF, int iVar1, int iVar2 ); -extern DdNode * extraBddCheckVarsSymmetric( DdManager * dd, DdNode * bF, DdNode * bVars ); - -/* build the set of all tuples of K variables out of N from the BDD cube */ -extern DdNode * Extra_zddTuplesFromBdd( DdManager * dd, int K, DdNode * bVarsN ); -extern DdNode * extraZddTuplesFromBdd( DdManager * dd, DdNode * bVarsK, DdNode * bVarsN ); -/* selects one subset from a ZDD representing the set of subsets */ -extern DdNode * Extra_zddSelectOneSubset( DdManager * dd, DdNode * zS ); -extern DdNode * extraZddSelectOneSubset( DdManager * dd, DdNode * zS ); - -/*=== extraBddUnate.c =================================================================*/ - -typedef struct Extra_UnateVar_t_ Extra_UnateVar_t; -struct Extra_UnateVar_t_ { - unsigned iVar : 30; // index of the variable - unsigned Pos : 1; // 1 if positive unate - unsigned Neg : 1; // 1 if negative unate -}; - -typedef struct Extra_UnateInfo_t_ Extra_UnateInfo_t; -struct Extra_UnateInfo_t_ { - int nVars; // the number of variables in the support - int nVarsMax; // the number of variables in the DD manager - int nUnate; // the number of unate variables - Extra_UnateVar_t * pVars; // the array of variables present in the support -}; - -/* allocates the data structure */ -extern Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars ); -/* deallocates the data structure */ -extern void Extra_UnateInfoDissolve( Extra_UnateInfo_t * ); -/* print the contents the data structure */ -extern void Extra_UnateInfoPrint( Extra_UnateInfo_t * ); -/* converts the ZDD into the Extra_SymmInfo_t structure */ -extern Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zUnate, DdNode * bVars ); -/* naive check of unateness of one variable */ -extern int Extra_bddCheckUnateNaive( DdManager * dd, DdNode * bF, int iVar ); - -/* computes the unateness information for the function */ -extern Extra_UnateInfo_t * Extra_UnateComputeFast( DdManager * dd, DdNode * bFunc ); -extern Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc ); - -/* computes the classical symmetry information as a ZDD */ -extern DdNode * Extra_zddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); -extern DdNode * extraZddUnateInfoCompute( DdManager * dd, DdNode * bF, DdNode * bVars ); - -/* converts a set of variables into a set of singleton subsets */ -extern DdNode * Extra_zddGetSingletonsBoth( DdManager * dd, DdNode * bVars ); -extern DdNode * extraZddGetSingletonsBoth( DdManager * dd, DdNode * bVars ); - -/*=== extraUtilBitMatrix.c ================================================================*/ - -typedef struct Extra_BitMat_t_ Extra_BitMat_t; -extern Extra_BitMat_t * Extra_BitMatrixStart( int nSize ); -extern void Extra_BitMatrixClean( Extra_BitMat_t * p ); -extern void Extra_BitMatrixStop( Extra_BitMat_t * p ); -extern void Extra_BitMatrixPrint( Extra_BitMat_t * p ); -extern int Extra_BitMatrixReadSize( Extra_BitMat_t * p ); -extern void Extra_BitMatrixInsert1( Extra_BitMat_t * p, int i, int k ); -extern int Extra_BitMatrixLookup1( Extra_BitMat_t * p, int i, int k ); -extern void Extra_BitMatrixDelete1( Extra_BitMat_t * p, int i, int k ); -extern void Extra_BitMatrixInsert2( Extra_BitMat_t * p, int i, int k ); -extern int Extra_BitMatrixLookup2( Extra_BitMat_t * p, int i, int k ); -extern void Extra_BitMatrixDelete2( Extra_BitMat_t * p, int i, int k ); -extern void Extra_BitMatrixOr( Extra_BitMat_t * p, int i, unsigned * pInfo ); -extern void Extra_BitMatrixOrTwo( Extra_BitMat_t * p, int i, int j ); -extern int Extra_BitMatrixCountOnesUpper( Extra_BitMat_t * p ); -extern int Extra_BitMatrixIsDisjoint( Extra_BitMat_t * p1, Extra_BitMat_t * p2 ); -extern int Extra_BitMatrixIsClique( Extra_BitMat_t * p ); - -/*=== extraUtilFile.c ========================================================*/ - -extern char * Extra_FileGetSimilarName( char * pFileNameWrong, char * pS1, char * pS2, char * pS3, char * pS4, char * pS5 ); -extern char * Extra_FileNameExtension( char * FileName ); -extern char * Extra_FileNameAppend( char * pBase, char * pSuffix ); -extern char * Extra_FileNameGeneric( char * FileName ); -extern int Extra_FileSize( char * pFileName ); -extern char * Extra_FileRead( FILE * pFile ); -extern char * Extra_TimeStamp(); -extern char * Extra_StringAppend( char * pStrGiven, char * pStrAdd ); -extern unsigned Extra_ReadBinary( char * Buffer ); -extern void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ); -extern int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars ); -extern void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ); -extern void Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars ); -extern void Extra_PrintHex( FILE * pFile, unsigned uTruth, int nVars ); -extern void Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine ); - -/*=== extraUtilReader.c ========================================================*/ - -typedef struct Extra_FileReader_t_ Extra_FileReader_t; -extern Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName, - char * pCharsComment, char * pCharsStop, char * pCharsClean ); -extern void Extra_FileReaderFree( Extra_FileReader_t * p ); -extern char * Extra_FileReaderGetFileName( Extra_FileReader_t * p ); -extern int Extra_FileReaderGetFileSize( Extra_FileReader_t * p ); -extern int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p ); -extern void * Extra_FileReaderGetTokens( Extra_FileReader_t * p ); -extern int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken ); - -/*=== extraUtilMemory.c ========================================================*/ - -typedef struct Extra_MmFixed_t_ Extra_MmFixed_t; -typedef struct Extra_MmFlex_t_ Extra_MmFlex_t; -typedef struct Extra_MmStep_t_ Extra_MmStep_t; - -// fixed-size-block memory manager -extern Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize ); -extern void Extra_MmFixedStop( Extra_MmFixed_t * p ); -extern char * Extra_MmFixedEntryFetch( Extra_MmFixed_t * p ); -extern void Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry ); -extern void Extra_MmFixedRestart( Extra_MmFixed_t * p ); -extern int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p ); -extern int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p ); -// flexible-size-block memory manager -extern Extra_MmFlex_t * Extra_MmFlexStart(); -extern void Extra_MmFlexStop( Extra_MmFlex_t * p ); -extern void Extra_MmFlexPrint( Extra_MmFlex_t * p ); -extern char * Extra_MmFlexEntryFetch( Extra_MmFlex_t * p, int nBytes ); -extern int Extra_MmFlexReadMemUsage( Extra_MmFlex_t * p ); -// hierarchical memory manager -extern Extra_MmStep_t * Extra_MmStepStart( int nSteps ); -extern void Extra_MmStepStop( Extra_MmStep_t * p ); -extern char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes ); -extern void Extra_MmStepEntryRecycle( Extra_MmStep_t * p, char * pEntry, int nBytes ); -extern int Extra_MmStepReadMemUsage( Extra_MmStep_t * p ); - -/*=== extraUtilMisc.c ========================================================*/ - -/* finds the smallest integer larger or equal than the logarithm */ -extern int Extra_Base2Log( unsigned Num ); -extern int Extra_Base2LogDouble( double Num ); -extern int Extra_Base10Log( unsigned Num ); -/* returns the power of two as a double */ -extern double Extra_Power2( int Num ); -extern int Extra_Power3( int Num ); -/* the number of combinations of k elements out of n */ -extern int Extra_NumCombinations( int k, int n ); -extern int * Extra_DeriveRadixCode( int Number, int Radix, int nDigits ); -/* counts the number of 1s in the bitstring */ -extern int Extra_CountOnes( unsigned char * pBytes, int nBytes ); -/* the factorial of number */ -extern int Extra_Factorial( int n ); -/* the permutation of the given number of elements */ -extern char ** Extra_Permutations( int n ); -/* permutation and complementation of a truth table */ -unsigned Extra_TruthPermute( unsigned Truth, char * pPerms, int nVars, int fReverse ); -unsigned Extra_TruthPolarize( unsigned uTruth, int Polarity, int nVars ); -/* canonical forms of a truth table */ -extern unsigned Extra_TruthCanonN( unsigned uTruth, int nVars ); -extern unsigned Extra_TruthCanonNN( unsigned uTruth, int nVars ); -extern unsigned Extra_TruthCanonP( unsigned uTruth, int nVars ); -extern unsigned Extra_TruthCanonNP( unsigned uTruth, int nVars ); -extern unsigned Extra_TruthCanonNPN( unsigned uTruth, int nVars ); -/* canonical forms of 4-variable functions */ -extern void Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ); -extern void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int nPhasesMax ); -/* permutation mapping */ -extern unsigned short Extra_TruthPerm4One( unsigned uTruth, int Phase ); -extern unsigned Extra_TruthPerm5One( unsigned uTruth, int Phase ); -extern void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes ); -extern void Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR ); -/* precomputing tables for permutation mapping */ -extern void ** Extra_ArrayAlloc( int nCols, int nRows, int Size ); -extern unsigned short ** Extra_TruthPerm43(); -extern unsigned ** Extra_TruthPerm53(); -extern unsigned ** Extra_TruthPerm54(); -/* bubble sort for small number of entries */ -extern void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing ); -/* for independence from CUDD */ -extern unsigned int Cudd_PrimeCopy( unsigned int p ); - -/*=== extraUtilCanon.c ========================================================*/ - -/* fast computation of N-canoninical form up to 6 inputs */ -extern int Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes ); - -/*=== extraUtilProgress.c ================================================================*/ - -typedef struct ProgressBarStruct ProgressBar; - -extern ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal ); -extern void Extra_ProgressBarStop( ProgressBar * p ); -extern void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString ); - -static inline void Extra_ProgressBarUpdate( ProgressBar * p, int nItemsCur, char * pString ) -{ if ( p && nItemsCur < *((int*)p) ) return; Extra_ProgressBarUpdate_int(p, nItemsCur, pString); } - -/*=== extraUtilTruth.c ================================================================*/ - -static inline int Extra_Float2Int( float Val ) { return *((int *)&Val); } -static inline float Extra_Int2Float( int Num ) { return *((float *)&Num); } -static inline int Extra_BitWordNum( int nBits ) { return nBits/(8*sizeof(unsigned)) + ((nBits%(8*sizeof(unsigned))) > 0); } -static inline int Extra_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } - -static inline void Extra_TruthSetBit( unsigned * p, int Bit ) { p[Bit>>5] |= (1<<(Bit & 31)); } -static inline void Extra_TruthXorBit( unsigned * p, int Bit ) { p[Bit>>5] ^= (1<<(Bit & 31)); } -static inline int Extra_TruthHasBit( unsigned * p, int Bit ) { return (p[Bit>>5] & (1<<(Bit & 31))) > 0; } - -static inline int Extra_WordCountOnes( unsigned uWord ) -{ - uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); - uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); - uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); - uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); - return (uWord & 0x0000FFFF) + (uWord>>16); -} -static inline int Extra_TruthCountOnes( unsigned * pIn, int nVars ) -{ - int w, Counter = 0; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - Counter += Extra_WordCountOnes(pIn[w]); - return Counter; -} -static inline int Extra_TruthIsEqual( unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn0[w] != pIn1[w] ) - return 0; - return 1; -} -static inline int Extra_TruthIsConst0( unsigned * pIn, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn[w] ) - return 0; - return 1; -} -static inline int Extra_TruthIsConst1( unsigned * pIn, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn[w] != ~(unsigned)0 ) - return 0; - return 1; -} -static inline int Extra_TruthIsImply( unsigned * pIn1, unsigned * pIn2, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - if ( pIn1[w] & ~pIn2[w] ) - return 0; - return 1; -} -static inline void Extra_TruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn[w]; -} -static inline void Extra_TruthClear( unsigned * pOut, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = 0; -} -static inline void Extra_TruthFill( unsigned * pOut, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~(unsigned)0; -} -static inline void Extra_TruthNot( unsigned * pOut, unsigned * pIn, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~pIn[w]; -} -static inline void Extra_TruthAnd( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] & pIn1[w]; -} -static inline void Extra_TruthOr( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] | pIn1[w]; -} -static inline void Extra_TruthSharp( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] & ~pIn1[w]; -} -static inline void Extra_TruthNand( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars ) -{ - int w; - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~(pIn0[w] & pIn1[w]); -} -static inline void Extra_TruthAndPhase( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nVars, int fCompl0, int fCompl1 ) -{ - int w; - if ( fCompl0 && fCompl1 ) - { - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~(pIn0[w] | pIn1[w]); - } - else if ( fCompl0 && !fCompl1 ) - { - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = ~pIn0[w] & pIn1[w]; - } - else if ( !fCompl0 && fCompl1 ) - { - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] & ~pIn1[w]; - } - else // if ( !fCompl0 && !fCompl1 ) - { - for ( w = Extra_TruthWordNum(nVars)-1; w >= 0; w-- ) - pOut[w] = pIn0[w] & pIn1[w]; - } -} - -extern unsigned ** Extra_TruthElementary( int nVars ); -extern void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int Start ); -extern void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ); -extern void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ); -extern int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ); -extern int Extra_TruthSupportSize( unsigned * pTruth, int nVars ); -extern int Extra_TruthSupport( unsigned * pTruth, int nVars ); -extern void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ); -extern void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ); -extern void Extra_TruthExist( unsigned * pTruth, int nVars, int iVar ); -extern void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar ); -extern void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ); -extern void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ); -extern int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ); -extern void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ); -extern unsigned Extra_TruthHash( unsigned * pIn, int nWords ); -extern unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ); - -/*=== extraUtilUtil.c ================================================================*/ - -#ifndef ABS -#define ABS(a) ((a) < 0 ? -(a) : (a)) -#endif - -#ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef ALLOC -#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#endif - -#ifndef FREE -#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#endif - -#ifndef REALLOC -#define REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) -#endif - - -extern long Extra_CpuTime(); -extern int Extra_GetSoftDataLimit(); -extern void Extra_UtilGetoptReset(); -extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring ); -extern char * Extra_UtilPrintTime( long t ); -extern char * Extra_UtilStrsav( char *s ); -extern char * Extra_UtilTildeExpand( char *fname ); -extern char * Extra_UtilFileSearch( char *file, char *path, char *mode ); -extern void (*Extra_UtilMMoutOfMemory)(); - -extern char * globalUtilOptarg; -extern int globalUtilOptind; - -/**AutomaticEnd***************************************************************/ - -#ifdef __cplusplus -} -#endif - -#endif /* __EXTRA_H__ */ diff --git a/src/misc/extra/extraBddAuto.c b/src/misc/extra/extraBddAuto.c deleted file mode 100644 index 21a969ba..00000000 --- a/src/misc/extra/extraBddAuto.c +++ /dev/null @@ -1,1558 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddAuto.c] - - PackageName [extra] - - Synopsis [Computation of autosymmetries.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - September 1, 2003.] - - Revision [$Id: extraBddAuto.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] - -***********************************************************************/ - -#include "extra.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - - -/* - LinearSpace(f) = Space(f,f) - - Space(f,g) - { - if ( f = const ) - { - if ( f = g ) return 1; - else return 0; - } - if ( g = const ) return 0; - return x' * Space(fx',gx') * Space(fx,gx) + x * Space(fx',gx) * Space(fx,gx'); - } - - Equations(s) = Pos(s) + Neg(s); - - Pos(s) - { - if ( s = 0 ) return 1; - if ( s = 1 ) return 0; - if ( sx'= 0 ) return Pos(sx) + x; - if ( sx = 0 ) return Pos(sx'); - return 1 * [Pos(sx') & Pos(sx)] + x * [Pos(sx') & Neg(sx)]; - } - - Neg(s) - { - if ( s = 0 ) return 1; - if ( s = 1 ) return 0; - if ( sx'= 0 ) return Neg(sx); - if ( sx = 0 ) return Neg(sx') + x; - return 1 * [Neg(sx') & Neg(sx)] + x * [Neg(sx') & Pos(sx)]; - } - - - SpaceP(A) - { - if ( A = 0 ) return 1; - if ( A = 1 ) return 1; - return x' * SpaceP(Ax') * SpaceP(Ax) + x * SpaceP(Ax') * SpaceN(Ax); - } - - SpaceN(A) - { - if ( A = 0 ) return 1; - if ( A = 1 ) return 0; - return x' * SpaceN(Ax') * SpaceN(Ax) + x * SpaceN(Ax') * SpaceP(Ax); - } - - - LinInd(A) - { - if ( A = const ) return 1; - if ( !LinInd(Ax') ) return 0; - if ( !LinInd(Ax) ) return 0; - if ( LinSumOdd(Ax') & LinSumEven(Ax) != 0 ) return 0; - if ( LinSumEven(Ax') & LinSumEven(Ax) != 0 ) return 0; - return 1; - } - - LinSumOdd(A) - { - if ( A = 0 ) return 0; // Odd0 ---e-- Odd1 - if ( A = 1 ) return 1; // \ o - Odd0 = LinSumOdd(Ax'); // x is absent // \ - Even0 = LinSumEven(Ax'); // x is absent // / o - Odd1 = LinSumOdd(Ax); // x is present // Even0 ---e-- Even1 - Even1 = LinSumEven(Ax); // x is absent - return 1 * [Odd0 + ExorP(Odd0, Even1)] + x * [Odd1 + ExorP(Odd1, Even0)]; - } - - LinSumEven(A) - { - if ( A = 0 ) return 0; - if ( A = 1 ) return 0; - Odd0 = LinSumOdd(Ax'); // x is absent - Even0 = LinSumEven(Ax'); // x is absent - Odd1 = LinSumOdd(Ax); // x is present - Even1 = LinSumEven(Ax); // x is absent - return 1 * [Even0 + Even1 + ExorP(Even0, Even1)] + x * [ExorP(Odd0, Odd1)]; - } - -*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromFunctionFast( DdManager * dd, DdNode * bFunc ) -{ - int * pSupport; - int * pPermute; - int * pPermuteBack; - DdNode ** pCompose; - DdNode * bCube, * bTemp; - DdNode * bSpace, * bFunc1, * bFunc2, * bSpaceShift; - int nSupp, Counter; - int i, lev; - - // get the support - pSupport = ALLOC( int, ddMax(dd->size,dd->sizeZ) ); - Extra_SupportArray( dd, bFunc, pSupport ); - nSupp = 0; - for ( i = 0; i < dd->size; i++ ) - if ( pSupport[i] ) - nSupp++; - - // make sure the manager has enough variables - if ( 2*nSupp > dd->size ) - { - printf( "Cannot derive linear space, because DD manager does not have enough variables.\n" ); - fflush( stdout ); - free( pSupport ); - return NULL; - } - - // create the permutation arrays - pPermute = ALLOC( int, dd->size ); - pPermuteBack = ALLOC( int, dd->size ); - pCompose = ALLOC( DdNode *, dd->size ); - for ( i = 0; i < dd->size; i++ ) - { - pPermute[i] = i; - pPermuteBack[i] = i; - pCompose[i] = dd->vars[i]; Cudd_Ref( pCompose[i] ); - } - - // remap the function in such a way that the variables are interleaved - Counter = 0; - bCube = b1; Cudd_Ref( bCube ); - for ( lev = 0; lev < dd->size; lev++ ) - if ( pSupport[ dd->invperm[lev] ] ) - { // var "dd->invperm[lev]" on level "lev" should go to level 2*Counter; - pPermute[ dd->invperm[lev] ] = dd->invperm[2*Counter]; - // var from level 2*Counter+1 should go back to the place of this var - pPermuteBack[ dd->invperm[2*Counter+1] ] = dd->invperm[lev]; - // the permutation should be defined in such a way that variable - // on level 2*Counter is replaced by an EXOR of itself and var on the next level - Cudd_Deref( pCompose[ dd->invperm[2*Counter] ] ); - pCompose[ dd->invperm[2*Counter] ] = - Cudd_bddXor( dd, dd->vars[ dd->invperm[2*Counter] ], dd->vars[ dd->invperm[2*Counter+1] ] ); - Cudd_Ref( pCompose[ dd->invperm[2*Counter] ] ); - // add this variable to the cube - bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[ dd->invperm[2*Counter] ] ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - // increment the counter - Counter ++; - } - - // permute the functions - bFunc1 = Cudd_bddPermute( dd, bFunc, pPermute ); Cudd_Ref( bFunc1 ); - // compose to gate the function depending on both vars - bFunc2 = Cudd_bddVectorCompose( dd, bFunc1, pCompose ); Cudd_Ref( bFunc2 ); - // gate the vector space - // L(a) = ForAll x [ F(x) = F(x+a) ] = Not( Exist x [ F(x) (+) F(x+a) ] ) - bSpaceShift = Cudd_bddXorExistAbstract( dd, bFunc1, bFunc2, bCube ); Cudd_Ref( bSpaceShift ); - bSpaceShift = Cudd_Not( bSpaceShift ); - // permute the space back into the original mapping - bSpace = Cudd_bddPermute( dd, bSpaceShift, pPermuteBack ); Cudd_Ref( bSpace ); - Cudd_RecursiveDeref( dd, bFunc1 ); - Cudd_RecursiveDeref( dd, bFunc2 ); - Cudd_RecursiveDeref( dd, bSpaceShift ); - Cudd_RecursiveDeref( dd, bCube ); - - for ( i = 0; i < dd->size; i++ ) - Cudd_RecursiveDeref( dd, pCompose[i] ); - free( pPermute ); - free( pPermuteBack ); - free( pCompose ); - free( pSupport ); - - Cudd_Deref( bSpace ); - return bSpace; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceFromFunction( dd, bF, bG ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromFunctionPos( DdManager * dd, DdNode * bFunc ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceFromFunctionPos( dd, bFunc ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromFunctionNeg( DdManager * dd, DdNode * bFunc ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceFromFunctionNeg( dd, bFunc ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceCanonVars( DdManager * dd, DdNode * bSpace ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceCanonVars( dd, bSpace ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceReduce( DdManager * dd, DdNode * bFunc, DdNode * bCanonVars ) -{ - DdNode * bNegCube; - DdNode * bResult; - bNegCube = Extra_bddSupportNegativeCube( dd, bCanonVars ); Cudd_Ref( bNegCube ); - bResult = Cudd_Cofactor( dd, bFunc, bNegCube ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bNegCube ); - Cudd_Deref( bResult ); - return bResult; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceEquations( DdManager * dd, DdNode * bSpace ) -{ - DdNode * zRes; - DdNode * zEquPos; - DdNode * zEquNeg; - zEquPos = Extra_bddSpaceEquationsPos( dd, bSpace ); Cudd_Ref( zEquPos ); - zEquNeg = Extra_bddSpaceEquationsNeg( dd, bSpace ); Cudd_Ref( zEquNeg ); - zRes = Cudd_zddUnion( dd, zEquPos, zEquNeg ); Cudd_Ref( zRes ); - Cudd_RecursiveDerefZdd( dd, zEquPos ); - Cudd_RecursiveDerefZdd( dd, zEquNeg ); - Cudd_Deref( zRes ); - return zRes; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceEquationsPos( DdManager * dd, DdNode * bSpace ) -{ - DdNode * zRes; - do { - dd->reordered = 0; - zRes = extraBddSpaceEquationsPos( dd, bSpace ); - } while (dd->reordered == 1); - return zRes; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceEquationsNeg( DdManager * dd, DdNode * bSpace ) -{ - DdNode * zRes; - do { - dd->reordered = 0; - zRes = extraBddSpaceEquationsNeg( dd, bSpace ); - } while (dd->reordered == 1); - return zRes; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceFromMatrixPos( dd, zA ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Extra_bddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ) -{ - DdNode * bRes; - do { - dd->reordered = 0; - bRes = extraBddSpaceFromMatrixNeg( dd, zA ); - } while (dd->reordered == 1); - return bRes; -} - -/**Function************************************************************* - - Synopsis [Counts the number of literals in one combination.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_zddLitCountComb( DdManager * dd, DdNode * zComb ) -{ - int Counter; - if ( zComb == z0 ) - return 0; - Counter = 0; - for ( ; zComb != z1; zComb = cuddT(zComb) ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Returns the array of ZDDs with the number equal to the number of - vars in the DD manager. If the given var is non-canonical, this array contains - the referenced ZDD representing literals in the corresponding EXOR equation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode ** Extra_bddSpaceExorGates( DdManager * dd, DdNode * bFuncRed, DdNode * zEquations ) -{ - DdNode ** pzRes; - int * pVarsNonCan; - DdNode * zEquRem; - int iVarNonCan; - DdNode * zExor, * zTemp; - - // get the set of non-canonical variables - pVarsNonCan = ALLOC( int, ddMax(dd->size,dd->sizeZ) ); - Extra_SupportArray( dd, bFuncRed, pVarsNonCan ); - - // allocate storage for the EXOR sets - pzRes = ALLOC( DdNode *, dd->size ); - memset( pzRes, 0, sizeof(DdNode *) * dd->size ); - - // go through all the equations - zEquRem = zEquations; Cudd_Ref( zEquRem ); - while ( zEquRem != z0 ) - { - // extract one product - zExor = Extra_zddSelectOneSubset( dd, zEquRem ); Cudd_Ref( zExor ); - // remove it from the set - zEquRem = Cudd_zddDiff( dd, zTemp = zEquRem, zExor ); Cudd_Ref( zEquRem ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - - // locate the non-canonical variable - iVarNonCan = -1; - for ( zTemp = zExor; zTemp != z1; zTemp = cuddT(zTemp) ) - { - if ( pVarsNonCan[zTemp->index/2] == 1 ) - { - assert( iVarNonCan == -1 ); - iVarNonCan = zTemp->index/2; - } - } - assert( iVarNonCan != -1 ); - - if ( Extra_zddLitCountComb( dd, zExor ) > 1 ) - pzRes[ iVarNonCan ] = zExor; // takes ref - else - Cudd_RecursiveDerefZdd( dd, zExor ); - } - Cudd_RecursiveDerefZdd( dd, zEquRem ); - - free( pVarsNonCan ); - return pzRes; -} - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs the recursive steps of Extra_bddSpaceFromFunction.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ) -{ - DdNode * bRes; - DdNode * bFR, * bGR; - - bFR = Cudd_Regular( bF ); - bGR = Cudd_Regular( bG ); - if ( cuddIsConstant(bFR) ) - { - if ( bF == bG ) - return b1; - else - return b0; - } - if ( cuddIsConstant(bGR) ) - return b0; - // both bFunc and bCore are not constants - - // the operation is commutative - normalize the problem - if ( (unsigned)bF > (unsigned)bG ) - return extraBddSpaceFromFunction(dd, bG, bF); - - - if ( bRes = cuddCacheLookup2(dd, extraBddSpaceFromFunction, bF, bG) ) - return bRes; - else - { - DdNode * bF0, * bF1; - DdNode * bG0, * bG1; - DdNode * bTemp1, * bTemp2; - DdNode * bRes0, * bRes1; - int LevelF, LevelG; - int index; - - LevelF = dd->perm[bFR->index]; - LevelG = dd->perm[bGR->index]; - if ( LevelF <= LevelG ) - { - index = dd->invperm[LevelF]; - if ( bFR != bF ) - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - } - else - { - index = dd->invperm[LevelG]; - bF0 = bF1 = bF; - } - - if ( LevelG <= LevelF ) - { - if ( bGR != bG ) - { - bG0 = Cudd_Not( cuddE(bGR) ); - bG1 = Cudd_Not( cuddT(bGR) ); - } - else - { - bG0 = cuddE(bGR); - bG1 = cuddT(bGR); - } - } - else - bG0 = bG1 = bG; - - bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG0 ); - if ( bTemp1 == NULL ) - return NULL; - cuddRef( bTemp1 ); - - bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG1 ); - if ( bTemp2 == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp1 ); - return NULL; - } - cuddRef( bTemp2 ); - - - bRes0 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); - if ( bRes0 == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp1 ); - Cudd_RecursiveDeref( dd, bTemp2 ); - return NULL; - } - cuddRef( bRes0 ); - Cudd_RecursiveDeref( dd, bTemp1 ); - Cudd_RecursiveDeref( dd, bTemp2 ); - - - bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG1 ); - if ( bTemp1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bTemp1 ); - - bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG0 ); - if ( bTemp2 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bTemp1 ); - return NULL; - } - cuddRef( bTemp2 ); - - bRes1 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bTemp1 ); - Cudd_RecursiveDeref( dd, bTemp2 ); - return NULL; - } - cuddRef( bRes1 ); - Cudd_RecursiveDeref( dd, bTemp1 ); - Cudd_RecursiveDeref( dd, bTemp2 ); - - - - // consider the case when Res0 and Res1 are the same node - if ( bRes0 == bRes1 ) - bRes = bRes1; - // consider the case when Res1 is complemented - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter(dd, index, Cudd_Not(bRes1), Cudd_Not(bRes0)); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, index, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - - // insert the result into cache - cuddCacheInsert2(dd, extraBddSpaceFromFunction, bF, bG, bRes); - return bRes; - } -} /* end of extraBddSpaceFromFunction */ - - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceFromFunctionPos( DdManager * dd, DdNode * bF ) -{ - DdNode * bRes, * bFR; - statLine( dd ); - - bFR = Cudd_Regular(bF); - if ( cuddIsConstant(bFR) ) - return b1; - - if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionPos, bF) ) - return bRes; - else - { - DdNode * bF0, * bF1; - DdNode * bPos0, * bPos1; - DdNode * bNeg0, * bNeg1; - DdNode * bRes0, * bRes1; - - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - - bPos0 = extraBddSpaceFromFunctionPos( dd, bF0 ); - if ( bPos0 == NULL ) - return NULL; - cuddRef( bPos0 ); - - bPos1 = extraBddSpaceFromFunctionPos( dd, bF1 ); - if ( bPos1 == NULL ) - { - Cudd_RecursiveDeref( dd, bPos0 ); - return NULL; - } - cuddRef( bPos1 ); - - bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 ); - if ( bRes0 == NULL ) - { - Cudd_RecursiveDeref( dd, bPos0 ); - Cudd_RecursiveDeref( dd, bPos1 ); - return NULL; - } - cuddRef( bRes0 ); - Cudd_RecursiveDeref( dd, bPos0 ); - Cudd_RecursiveDeref( dd, bPos1 ); - - - bNeg0 = extraBddSpaceFromFunctionNeg( dd, bF0 ); - if ( bNeg0 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bNeg0 ); - - bNeg1 = extraBddSpaceFromFunctionNeg( dd, bF1 ); - if ( bNeg1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - return NULL; - } - cuddRef( bNeg1 ); - - bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - Cudd_RecursiveDeref( dd, bNeg1 ); - return NULL; - } - cuddRef( bRes1 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - Cudd_RecursiveDeref( dd, bNeg1 ); - - - // consider the case when Res0 and Res1 are the same node - if ( bRes0 == bRes1 ) - bRes = bRes1; - // consider the case when Res1 is complemented - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - - cuddCacheInsert1( dd, extraBddSpaceFromFunctionPos, bF, bRes ); - return bRes; - } -} - - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceFromFunctionNeg( DdManager * dd, DdNode * bF ) -{ - DdNode * bRes, * bFR; - statLine( dd ); - - bFR = Cudd_Regular(bF); - if ( cuddIsConstant(bFR) ) - return b0; - - if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromFunctionNeg, bF) ) - return bRes; - else - { - DdNode * bF0, * bF1; - DdNode * bPos0, * bPos1; - DdNode * bNeg0, * bNeg1; - DdNode * bRes0, * bRes1; - - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - - bPos0 = extraBddSpaceFromFunctionNeg( dd, bF0 ); - if ( bPos0 == NULL ) - return NULL; - cuddRef( bPos0 ); - - bPos1 = extraBddSpaceFromFunctionNeg( dd, bF1 ); - if ( bPos1 == NULL ) - { - Cudd_RecursiveDeref( dd, bPos0 ); - return NULL; - } - cuddRef( bPos1 ); - - bRes0 = cuddBddAndRecur( dd, bPos0, bPos1 ); - if ( bRes0 == NULL ) - { - Cudd_RecursiveDeref( dd, bPos0 ); - Cudd_RecursiveDeref( dd, bPos1 ); - return NULL; - } - cuddRef( bRes0 ); - Cudd_RecursiveDeref( dd, bPos0 ); - Cudd_RecursiveDeref( dd, bPos1 ); - - - bNeg0 = extraBddSpaceFromFunctionPos( dd, bF0 ); - if ( bNeg0 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bNeg0 ); - - bNeg1 = extraBddSpaceFromFunctionPos( dd, bF1 ); - if ( bNeg1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - return NULL; - } - cuddRef( bNeg1 ); - - bRes1 = cuddBddAndRecur( dd, bNeg0, bNeg1 ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - Cudd_RecursiveDeref( dd, bNeg1 ); - return NULL; - } - cuddRef( bRes1 ); - Cudd_RecursiveDeref( dd, bNeg0 ); - Cudd_RecursiveDeref( dd, bNeg1 ); - - - // consider the case when Res0 and Res1 are the same node - if ( bRes0 == bRes1 ) - bRes = bRes1; - // consider the case when Res1 is complemented - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter( dd, bFR->index, Cudd_Not(bRes1), Cudd_Not(bRes0) ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, bFR->index, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - - cuddCacheInsert1( dd, extraBddSpaceFromFunctionNeg, bF, bRes ); - return bRes; - } -} - - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceCanonVars().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceCanonVars( DdManager * dd, DdNode * bF ) -{ - DdNode * bRes, * bFR; - statLine( dd ); - - bFR = Cudd_Regular(bF); - if ( cuddIsConstant(bFR) ) - return bF; - - if ( bRes = cuddCacheLookup1(dd, extraBddSpaceCanonVars, bF) ) - return bRes; - else - { - DdNode * bF0, * bF1; - DdNode * bRes, * bRes0; - - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - if ( bF0 == b0 ) - { - bRes = extraBddSpaceCanonVars( dd, bF1 ); - if ( bRes == NULL ) - return NULL; - } - else if ( bF1 == b0 ) - { - bRes = extraBddSpaceCanonVars( dd, bF0 ); - if ( bRes == NULL ) - return NULL; - } - else - { - bRes0 = extraBddSpaceCanonVars( dd, bF0 ); - if ( bRes0 == NULL ) - return NULL; - cuddRef( bRes0 ); - - bRes = cuddUniqueInter( dd, bFR->index, bRes0, b0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( dd,bRes0 ); - return NULL; - } - cuddDeref( bRes0 ); - } - - cuddCacheInsert1( dd, extraBddSpaceCanonVars, bF, bRes ); - return bRes; - } -} - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceEquationsPos().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceEquationsPos( DdManager * dd, DdNode * bF ) -{ - DdNode * zRes; - statLine( dd ); - - if ( bF == b0 ) - return z1; - if ( bF == b1 ) - return z0; - - if ( zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsPos, bF) ) - return zRes; - else - { - DdNode * bFR, * bF0, * bF1; - DdNode * zPos0, * zPos1, * zNeg1; - DdNode * zRes, * zRes0, * zRes1; - - bFR = Cudd_Regular(bF); - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - if ( bF0 == b0 ) - { - zRes1 = extraBddSpaceEquationsPos( dd, bF1 ); - if ( zRes1 == NULL ) - return NULL; - cuddRef( zRes1 ); - - // add the current element to the set - zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes1 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes1); - return NULL; - } - cuddDeref( zRes1 ); - } - else if ( bF1 == b0 ) - { - zRes = extraBddSpaceEquationsPos( dd, bF0 ); - if ( zRes == NULL ) - return NULL; - } - else - { - zPos0 = extraBddSpaceEquationsPos( dd, bF0 ); - if ( zPos0 == NULL ) - return NULL; - cuddRef( zPos0 ); - - zPos1 = extraBddSpaceEquationsPos( dd, bF1 ); - if ( zPos1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zPos0); - return NULL; - } - cuddRef( zPos1 ); - - zNeg1 = extraBddSpaceEquationsNeg( dd, bF1 ); - if ( zNeg1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zNeg1 ); - - - zRes0 = cuddZddIntersect( dd, zPos0, zPos1 ); - if ( zRes0 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zRes0 ); - - zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes0); - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zRes1 ); - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - // only zRes0 and zRes1 are refed at this point - - zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes0); - Cudd_RecursiveDerefZdd(dd, zRes1); - return NULL; - } - cuddDeref( zRes0 ); - cuddDeref( zRes1 ); - } - - cuddCacheInsert1( dd, extraBddSpaceEquationsPos, bF, zRes ); - return zRes; - } -} - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceEquationsNev().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceEquationsNeg( DdManager * dd, DdNode * bF ) -{ - DdNode * zRes; - statLine( dd ); - - if ( bF == b0 ) - return z1; - if ( bF == b1 ) - return z0; - - if ( zRes = cuddCacheLookup1Zdd(dd, extraBddSpaceEquationsNeg, bF) ) - return zRes; - else - { - DdNode * bFR, * bF0, * bF1; - DdNode * zPos0, * zPos1, * zNeg1; - DdNode * zRes, * zRes0, * zRes1; - - bFR = Cudd_Regular(bF); - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - if ( bF0 == b0 ) - { - zRes = extraBddSpaceEquationsNeg( dd, bF1 ); - if ( zRes == NULL ) - return NULL; - } - else if ( bF1 == b0 ) - { - zRes0 = extraBddSpaceEquationsNeg( dd, bF0 ); - if ( zRes0 == NULL ) - return NULL; - cuddRef( zRes0 ); - - // add the current element to the set - zRes = cuddZddGetNode( dd, 2*bFR->index, z1, zRes0 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes0); - return NULL; - } - cuddDeref( zRes0 ); - } - else - { - zPos0 = extraBddSpaceEquationsNeg( dd, bF0 ); - if ( zPos0 == NULL ) - return NULL; - cuddRef( zPos0 ); - - zPos1 = extraBddSpaceEquationsNeg( dd, bF1 ); - if ( zPos1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zPos0); - return NULL; - } - cuddRef( zPos1 ); - - zNeg1 = extraBddSpaceEquationsPos( dd, bF1 ); - if ( zNeg1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zNeg1 ); - - - zRes0 = cuddZddIntersect( dd, zPos0, zPos1 ); - if ( zRes0 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zRes0 ); - - zRes1 = cuddZddIntersect( dd, zPos0, zNeg1 ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes0); - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - return NULL; - } - cuddRef( zRes1 ); - Cudd_RecursiveDerefZdd(dd, zNeg1); - Cudd_RecursiveDerefZdd(dd, zPos0); - Cudd_RecursiveDerefZdd(dd, zPos1); - // only zRes0 and zRes1 are refed at this point - - zRes = cuddZddGetNode( dd, 2*bFR->index, zRes1, zRes0 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zRes0); - Cudd_RecursiveDerefZdd(dd, zRes1); - return NULL; - } - cuddDeref( zRes0 ); - cuddDeref( zRes1 ); - } - - cuddCacheInsert1( dd, extraBddSpaceEquationsNeg, bF, zRes ); - return zRes; - } -} - - - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceFromMatrixPos( DdManager * dd, DdNode * zA ) -{ - DdNode * bRes; - statLine( dd ); - - if ( zA == z0 ) - return b1; - if ( zA == z1 ) - return b1; - - if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixPos, zA) ) - return bRes; - else - { - DdNode * bP0, * bP1; - DdNode * bN0, * bN1; - DdNode * bRes0, * bRes1; - - bP0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) ); - if ( bP0 == NULL ) - return NULL; - cuddRef( bP0 ); - - bP1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) ); - if ( bP1 == NULL ) - { - Cudd_RecursiveDeref( dd, bP0 ); - return NULL; - } - cuddRef( bP1 ); - - bRes0 = cuddBddAndRecur( dd, bP0, bP1 ); - if ( bRes0 == NULL ) - { - Cudd_RecursiveDeref( dd, bP0 ); - Cudd_RecursiveDeref( dd, bP1 ); - return NULL; - } - cuddRef( bRes0 ); - Cudd_RecursiveDeref( dd, bP0 ); - Cudd_RecursiveDeref( dd, bP1 ); - - - bN0 = extraBddSpaceFromMatrixPos( dd, cuddE(zA) ); - if ( bN0 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bN0 ); - - bN1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) ); - if ( bN1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bN0 ); - return NULL; - } - cuddRef( bN1 ); - - bRes1 = cuddBddAndRecur( dd, bN0, bN1 ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bN0 ); - Cudd_RecursiveDeref( dd, bN1 ); - return NULL; - } - cuddRef( bRes1 ); - Cudd_RecursiveDeref( dd, bN0 ); - Cudd_RecursiveDeref( dd, bN1 ); - - - // consider the case when Res0 and Res1 are the same node - if ( bRes0 == bRes1 ) - bRes = bRes1; - // consider the case when Res1 is complemented - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - - cuddCacheInsert1( dd, extraBddSpaceFromMatrixPos, zA, bRes ); - return bRes; - } -} - - -/**Function************************************************************* - - Synopsis [Performs the recursive step of Extra_bddSpaceFromFunctionPos().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * extraBddSpaceFromMatrixNeg( DdManager * dd, DdNode * zA ) -{ - DdNode * bRes; - statLine( dd ); - - if ( zA == z0 ) - return b1; - if ( zA == z1 ) - return b0; - - if ( bRes = cuddCacheLookup1(dd, extraBddSpaceFromMatrixNeg, zA) ) - return bRes; - else - { - DdNode * bP0, * bP1; - DdNode * bN0, * bN1; - DdNode * bRes0, * bRes1; - - bP0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) ); - if ( bP0 == NULL ) - return NULL; - cuddRef( bP0 ); - - bP1 = extraBddSpaceFromMatrixNeg( dd, cuddT(zA) ); - if ( bP1 == NULL ) - { - Cudd_RecursiveDeref( dd, bP0 ); - return NULL; - } - cuddRef( bP1 ); - - bRes0 = cuddBddAndRecur( dd, bP0, bP1 ); - if ( bRes0 == NULL ) - { - Cudd_RecursiveDeref( dd, bP0 ); - Cudd_RecursiveDeref( dd, bP1 ); - return NULL; - } - cuddRef( bRes0 ); - Cudd_RecursiveDeref( dd, bP0 ); - Cudd_RecursiveDeref( dd, bP1 ); - - - bN0 = extraBddSpaceFromMatrixNeg( dd, cuddE(zA) ); - if ( bN0 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bN0 ); - - bN1 = extraBddSpaceFromMatrixPos( dd, cuddT(zA) ); - if ( bN1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bN0 ); - return NULL; - } - cuddRef( bN1 ); - - bRes1 = cuddBddAndRecur( dd, bN0, bN1 ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bN0 ); - Cudd_RecursiveDeref( dd, bN1 ); - return NULL; - } - cuddRef( bRes1 ); - Cudd_RecursiveDeref( dd, bN0 ); - Cudd_RecursiveDeref( dd, bN1 ); - - - // consider the case when Res0 and Res1 are the same node - if ( bRes0 == bRes1 ) - bRes = bRes1; - // consider the case when Res1 is complemented - else if ( Cudd_IsComplement(bRes1) ) - { - bRes = cuddUniqueInter( dd, zA->index/2, Cudd_Not(bRes1), Cudd_Not(bRes0) ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - bRes = Cudd_Not(bRes); - } - else - { - bRes = cuddUniqueInter( dd, zA->index/2, bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref(dd,bRes0); - Cudd_RecursiveDeref(dd,bRes1); - return NULL; - } - } - cuddDeref( bRes0 ); - cuddDeref( bRes1 ); - - cuddCacheInsert1( dd, extraBddSpaceFromMatrixNeg, zA, bRes ); - return bRes; - } -} - - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/misc/extra/extraBddCas.c b/src/misc/extra/extraBddCas.c deleted file mode 100644 index 29382bfb..00000000 --- a/src/misc/extra/extraBddCas.c +++ /dev/null @@ -1,1230 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddCas.c] - - PackageName [extra] - - Synopsis [Procedures related to LUT cascade synthesis.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - September 1, 2003.] - - Revision [$Id: extraBddCas.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] - -***********************************************************************/ - -#include "extra.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -// the table to store cofactor operations -#define _TABLESIZE_COF 51113 -typedef struct -{ - unsigned Sign; - DdNode * Arg1; -} _HashEntry_cof; -_HashEntry_cof HHTable1[_TABLESIZE_COF]; - -// the table to store the result of computation of the number of minterms -#define _TABLESIZE_MINT 15113 -typedef struct -{ - DdNode * Arg1; - unsigned Arg2; - unsigned Res; -} _HashEntry_mint; -_HashEntry_mint HHTable2[_TABLESIZE_MINT]; - -typedef struct -{ - int nEdges; // the number of in-coming edges of the node - DdNode * bSum; // the sum of paths of the incoming edges -} traventry; - -// the signature used for hashing -static unsigned s_Signature = 1; - -static int s_CutLevel = 0; - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -// because the proposed solution to the optimal encoding problem has exponential complexity -// we limit the depth of the branch and bound procedure to 5 levels -static int s_MaxDepth = 5; - -static int s_nVarsBest; // the number of vars in the best ordering -static int s_VarOrderBest[32]; // storing the best ordering of vars in the "simple encoding" -static int s_VarOrderCur[32]; // storing the current ordering of vars - -// the place to store the supports of the encoded function -static DdNode * s_Field[8][256]; // the size should be K, 2^K, where K is no less than MaxDepth -static DdNode * s_Encoded; // this is the original function -static DdNode * s_VarAll; // the set of all column variables -static int s_MultiStart; // the total number of encoding variables used -// the array field now stores the supports - -static DdNode ** s_pbTemp; // the temporary storage for the columns - -static int s_BackTracks; -static int s_BackTrackLimit = 100; - -static DdNode * s_Terminal; // the terminal value for counting minterms - - -static int s_EncodingVarsLevel; - - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars ); -static void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level ); -// functions called from EvaluateEncodings_rec() -static DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ); -static DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ); -unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll ); -static unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max ); - -static void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st_table * Visited ); -static void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st_table * Visited, st_table * CutNodes ); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs the binary encoding of the set of function using the given vars.] - - Description [Performs a straight binary encoding of the set of functions using - the variable cubes formed from the given set of variables. ] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * -Extra_bddEncodingBinary( - DdManager * dd, - DdNode ** pbFuncs, // pbFuncs is the array of columns to be encoded - int nFuncs, // nFuncs is the number of columns in the array - DdNode ** pbVars, // pbVars is the array of variables to use for the codes - int nVars ) // nVars is the column multiplicity, [log2(nFuncs)] -{ - int i; - DdNode * bResult; - DdNode * bCube, * bTemp, * bProd; - - assert( nVars >= Extra_Base2Log(nFuncs) ); - - bResult = b0; Cudd_Ref( bResult ); - for ( i = 0; i < nFuncs; i++ ) - { - bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube ); - bProd = Cudd_bddAnd( dd, bCube, pbFuncs[i] ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bCube ); - - bResult = Cudd_bddOr( dd, bProd, bTemp = bResult ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bProd ); - } - - Cudd_Deref( bResult ); - return bResult; -} /* end of Extra_bddEncodingBinary */ - - -/**Function******************************************************************** - - Synopsis [Solves the column encoding problem using a sophisticated method.] - - Description [The encoding is based on the idea of deriving functions which - depend on only one variable, which corresponds to the case of non-disjoint - decompostion. It is assumed that the variables pCVars are ordered below the variables - representing the solumns, and the first variable pCVars[0] is the topmost one.] - - SideEffects [] - - SeeAlso [Extra_bddEncodingBinary] - -******************************************************************************/ - -DdNode * -Extra_bddEncodingNonStrict( - DdManager * dd, - DdNode ** pbColumns, // pbColumns is the array of columns to be encoded; - int nColumns, // nColumns is the number of columns in the array - DdNode * bVarsCol, // bVarsCol is the cube of variables on which the columns depend - DdNode ** pCVars, // pCVars is the array of variables to use for the codes - int nMulti, // nMulti is the column multiplicity, [log2(nColumns)] - int * pSimple ) // pSimple gets the number of code variables taken from the input varibles without change -{ - DdNode * bEncoded, * bResult; - int nVarsCol = Cudd_SupportSize(dd,bVarsCol); - long clk; - - // cannot work with more that 32-bit codes - assert( nMulti < 32 ); - - // perform the preliminary encoding using the straight binary code - bEncoded = Extra_bddEncodingBinary( dd, pbColumns, nColumns, pCVars, nMulti ); Cudd_Ref( bEncoded ); - //printf( "Node count = %d", Cudd_DagSize(bEncoded) ); - - // set the backgroup value for counting minterms - s_Terminal = b0; - // set the level of the encoding variables - s_EncodingVarsLevel = dd->invperm[pCVars[0]->index]; - - // the current number of backtracks - s_BackTracks = 0; - // the variables that are cofactored on the topmost level where everything starts (no vars) - s_Field[0][0] = b1; - // the size of the best set of "simple" encoding variables found so far - s_nVarsBest = 0; - - // set the relation to be accessible to traversal procedures - s_Encoded = bEncoded; - // the set of all vars to be accessible to traversal procedures - s_VarAll = bVarsCol; - // the column multiplicity - s_MultiStart = nMulti; - - - clk = clock(); - // find the simplest encoding - if ( nColumns > 2 ) - EvaluateEncodings_rec( dd, bVarsCol, nVarsCol, nMulti, 1 ); -// printf( "The number of backtracks = %d\n", s_BackTracks ); -// s_EncSearchTime += clock() - clk; - - // allocate the temporary storage for the columns - s_pbTemp = (DdNode **) malloc( nColumns * sizeof(DdNode *) ); - -// clk = clock(); - bResult = CreateTheCodes_rec( dd, bEncoded, 0, pCVars ); Cudd_Ref( bResult ); -// s_EncComputeTime += clock() - clk; - - // delocate the preliminarily encoded set - Cudd_RecursiveDeref( dd, bEncoded ); -// Cudd_RecursiveDeref( dd, aEncoded ); - - free( s_pbTemp ); - - *pSimple = s_nVarsBest; - Cudd_Deref( bResult ); - return bResult; -} - -/**Function******************************************************************** - - Synopsis [Collects the nodes under the cut and, for each node, computes the sum of paths leading to it from the root.] - - Description [The table returned contains the set of BDD nodes pointed to under the cut - and, for each node, the BDD of the sum of paths leading to this node from the root - The sums of paths in the table are referenced. CutLevel is the first DD level - considered to be under the cut.] - - SideEffects [] - - SeeAlso [Extra_bddNodePaths] - -******************************************************************************/ -st_table * Extra_bddNodePathsUnderCut( DdManager * dd, DdNode * bFunc, int CutLevel ) -{ - st_table * Visited; // temporary table to remember the visited nodes - st_table * CutNodes; // the result goes here - st_table * Result; // the result goes here - DdNode * aFunc; - - s_CutLevel = CutLevel; - - Result = st_init_table(st_ptrcmp,st_ptrhash); - // the terminal cases - if ( Cudd_IsConstant( bFunc ) ) - { - if ( bFunc == b1 ) - { - st_insert( Result, (char*)b1, (char*)b1 ); - Cudd_Ref( b1 ); - Cudd_Ref( b1 ); - } - else - { - st_insert( Result, (char*)b0, (char*)b0 ); - Cudd_Ref( b0 ); - Cudd_Ref( b0 ); - } - return Result; - } - - // create the ADD to simplify processing (no complemented edges) - aFunc = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( aFunc ); - - // Step 1: Start the tables and collect information about the nodes above the cut - // this information tells how many edges point to each node - Visited = st_init_table(st_ptrcmp,st_ptrhash); - CutNodes = st_init_table(st_ptrcmp,st_ptrhash); - - CountNodeVisits_rec( dd, aFunc, Visited ); - - // Step 2: Traverse the BDD using the visited table and compute the sum of paths - CollectNodesAndComputePaths_rec( dd, aFunc, b1, Visited, CutNodes ); - - // at this point the table of cut nodes is ready and the table of visited is useless - { - st_generator * gen; - DdNode * aNode; - traventry * p; - st_foreach_item( Visited, gen, (char**)&aNode, (char**)&p ) - { - Cudd_RecursiveDeref( dd, p->bSum ); - free( p ); - } - st_free_table( Visited ); - } - - // go through the table CutNodes and create the BDD and the path to be returned - { - st_generator * gen; - DdNode * aNode, * bNode, * bSum; - st_foreach_item( CutNodes, gen, (char**)&aNode, (char**)&bSum) - { - // aNode is not referenced, because aFunc is holding it - bNode = Cudd_addBddPattern( dd, aNode ); Cudd_Ref( bNode ); - st_insert( Result, (char*)bNode, (char*)bSum ); - // the new table takes both refs - } - st_free_table( CutNodes ); - } - - // dereference the ADD - Cudd_RecursiveDeref( dd, aFunc ); - - // return the table - return Result; - -} /* end of Extra_bddNodePathsUnderCut */ - -/**Function******************************************************************** - - Synopsis [Collects the nodes under the cut in the ADD starting from the given set of ADD nodes.] - - Description [Takes the array, paNodes, of ADD nodes to start the traversal, - the array, pbCubes, of BDD cubes to start the traversal with in each node, - and the number, nNodes, of ADD nodes and BDD cubes in paNodes and pbCubes. - Returns the number of columns found. Fills in paNodesRes (pbCubesRes) - with the set of ADD columns (BDD paths). These arrays should be allocated - by the user.] - - SideEffects [] - - SeeAlso [Extra_bddNodePaths] - -******************************************************************************/ -int Extra_bddNodePathsUnderCutArray( DdManager * dd, DdNode ** paNodes, DdNode ** pbCubes, int nNodes, DdNode ** paNodesRes, DdNode ** pbCubesRes, int CutLevel ) -{ - st_table * Visited; // temporary table to remember the visited nodes - st_table * CutNodes; // the nodes under the cut go here - int i, Counter; - - s_CutLevel = CutLevel; - - // there should be some nodes - assert( nNodes > 0 ); - if ( nNodes == 1 && Cudd_IsConstant( paNodes[0] ) ) - { - if ( paNodes[0] == a1 ) - { - paNodesRes[0] = a1; Cudd_Ref( a1 ); - pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] ); - } - else - { - paNodesRes[0] = a0; Cudd_Ref( a0 ); - pbCubesRes[0] = pbCubes[0]; Cudd_Ref( pbCubes[0] ); - } - return 1; - } - - // Step 1: Start the table and collect information about the nodes above the cut - // this information tells how many edges point to each node - CutNodes = st_init_table(st_ptrcmp,st_ptrhash); - Visited = st_init_table(st_ptrcmp,st_ptrhash); - - for ( i = 0; i < nNodes; i++ ) - CountNodeVisits_rec( dd, paNodes[i], Visited ); - - // Step 2: Traverse the BDD using the visited table and compute the sum of paths - for ( i = 0; i < nNodes; i++ ) - CollectNodesAndComputePaths_rec( dd, paNodes[i], pbCubes[i], Visited, CutNodes ); - - // at this point, the table of cut nodes is ready and the table of visited is useless - { - st_generator * gen; - DdNode * aNode; - traventry * p; - st_foreach_item( Visited, gen, (char**)&aNode, (char**)&p ) - { - Cudd_RecursiveDeref( dd, p->bSum ); - free( p ); - } - st_free_table( Visited ); - } - - // go through the table CutNodes and create the BDD and the path to be returned - { - st_generator * gen; - DdNode * aNode, * bSum; - Counter = 0; - st_foreach_item( CutNodes, gen, (char**)&aNode, (char**)&bSum) - { - paNodesRes[Counter] = aNode; Cudd_Ref( aNode ); - pbCubesRes[Counter] = bSum; - Counter++; - } - st_free_table( CutNodes ); - } - - // return the number of cofactors found - return Counter; - -} /* end of Extra_bddNodePathsUnderCutArray */ - -/**Function************************************************************* - - Synopsis [Collects all the BDD nodes into the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void extraCollectNodes( DdNode * Func, st_table * tNodes ) -{ - DdNode * FuncR; - FuncR = Cudd_Regular(Func); - if ( st_find_or_add( tNodes, (char*)FuncR, NULL ) ) - return; - if ( cuddIsConstant(FuncR) ) - return; - extraCollectNodes( cuddE(FuncR), tNodes ); - extraCollectNodes( cuddT(FuncR), tNodes ); -} - -/**Function************************************************************* - - Synopsis [Collects all the nodes of one DD into the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -st_table * Extra_CollectNodes( DdNode * Func ) -{ - st_table * tNodes; - tNodes = st_init_table( st_ptrcmp, st_ptrhash ); - extraCollectNodes( Func, tNodes ); - return tNodes; -} - -/**Function************************************************************* - - Synopsis [Updates the topmost level from which the given node is referenced.] - - Description [Takes the table which maps each BDD nodes (including the constants) - into the topmost level on which this node counts as a cofactor. Takes the topmost - level, on which this node counts as a cofactor (see Extra_ProfileWidthFast(). - Takes the node, for which the table entry should be updated.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void extraProfileUpdateTopLevel( st_table * tNodeTopRef, int TopLevelNew, DdNode * node ) -{ - int * pTopLevel; - - if ( st_find_or_add( tNodeTopRef, (char*)node, (char***)&pTopLevel ) ) - { // the node is already referenced - // the current top level should be updated if it is larger than the new level - if ( *pTopLevel > TopLevelNew ) - *pTopLevel = TopLevelNew; - } - else - { // the node is not referenced - // its level should be set to the current new level - *pTopLevel = TopLevelNew; - } -} -/**Function************************************************************* - - Synopsis [Fast computation of the BDD profile.] - - Description [The array to store the profile is given by the user and should - contain at least as many entries as there is the maximum of the BDD/ZDD - size of the manager PLUS ONE. - When we say that the widths of the DD on level L is W, we mean the following. - Let us create the cut between the level L-1 and the level L and count the number - of different DD nodes pointed to across the cut. This number is the width W. - From this it follows the on level 0, the width is equal to the number of external - pointers to the considered DDs. If there is only one DD, then the profile on - level 0 is always 1. If this DD is rooted in the topmost variable, then the width - on level 1 is always 2, etc. The width at the level equal to dd->size is the - number of terminal nodes in the DD. (Because we consider the first level #0 - and the last level #dd->size, the profile array should contain dd->size+1 entries.) - ] - - SideEffects [This procedure will not work for BDDs w/ complement edges, only for ADDs and ZDDs] - - SeeAlso [] - -***********************************************************************/ -int Extra_ProfileWidth( DdManager * dd, DdNode * Func, int * pProfile, int CutLevel ) -{ - st_generator * gen; - st_table * tNodeTopRef; // this table stores the top level from which this node is pointed to - st_table * tNodes; - DdNode * node; - DdNode * nodeR; - int LevelStart, Limit; - int i, size; - int WidthMax; - - // start the mapping table - tNodeTopRef = st_init_table(st_ptrcmp,st_ptrhash); - // add the topmost node to the profile - extraProfileUpdateTopLevel( tNodeTopRef, 0, Func ); - - // collect all nodes - tNodes = Extra_CollectNodes( Func ); - // go though all the nodes and set the top level the cofactors are pointed from -// Cudd_ForeachNode( dd, Func, genDD, node ) - st_foreach_item( tNodes, gen, (char**)&node, NULL ) - { -// assert( Cudd_Regular(node) ); // this procedure works only with ADD/ZDD (not BDD w/ compl.edges) - nodeR = Cudd_Regular(node); - if ( cuddIsConstant(nodeR) ) - continue; - // this node is not a constant - consider its cofactors - extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddE(nodeR) ); - extraProfileUpdateTopLevel( tNodeTopRef, dd->perm[node->index]+1, cuddT(nodeR) ); - } - st_free_table( tNodes ); - - // clean the profile - size = ddMax(dd->size, dd->sizeZ) + 1; - for ( i = 0; i < size; i++ ) - pProfile[i] = 0; - - // create the profile - st_foreach_item( tNodeTopRef, gen, (char**)&node, (char**)&LevelStart ) - { - nodeR = Cudd_Regular(node); - Limit = (cuddIsConstant(nodeR))? dd->size: dd->perm[nodeR->index]; - for ( i = LevelStart; i <= Limit; i++ ) - pProfile[i]++; - } - - if ( CutLevel != -1 && CutLevel != 0 ) - size = CutLevel; - - // get the max width - WidthMax = 0; - for ( i = 0; i < size; i++ ) - if ( WidthMax < pProfile[i] ) - WidthMax = pProfile[i]; - - // deref the table - st_free_table( tNodeTopRef ); - - return WidthMax; -} /* end of Extra_ProfileWidth */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes the non-strict codes when evaluation is finished.] - - Description [The information about the best code is stored in s_VarOrderBest, - which has s_nVarsBest entries.] - - SideEffects [None] - -******************************************************************************/ -DdNode * CreateTheCodes_rec( DdManager * dd, DdNode * bEncoded, int Level, DdNode ** pCVars ) -// bEncoded is the preliminarily encoded set of columns -// Level is the current level in the recursion -// pCVars are the variables to be used for encoding -{ - DdNode * bRes; - if ( Level == s_nVarsBest ) - { // the terminal case, when we need to remap the encoded function - // from the preliminary encoded variables to the new ones - st_table * CutNodes; - int nCols; -// double nMints; -/* -#ifdef _DEBUG - - { - DdNode * bTemp; - // make sure that the given number of variables is enough - bTemp = Cudd_bddExistAbstract( dd, bEncoded, s_VarAll ); Cudd_Ref( bTemp ); -// nMints = Cudd_CountMinterm( dd, bTemp, s_MultiStart ); - nMints = Extra_CountMintermsSimple( bTemp, (1< Extra_Power2( s_MultiStart-Level ) ) - { // the number of minterms is too large to encode the columns - // using the given minimum number of encoding variables - assert( 0 ); - } - Cudd_RecursiveDeref( dd, bTemp ); - } -#endif -*/ - // get the columns to be re-encoded - CutNodes = Extra_bddNodePathsUnderCut( dd, bEncoded, s_EncodingVarsLevel ); - // LUT size is the cut level because because the temporary encoding variables - // are above the functional variables - this is not true!!! - // the temporary variables are below! - - // put the entries from the table into the temporary array - { - st_generator * gen; - DdNode * bColumn, * bCode; - nCols = 0; - st_foreach_item( CutNodes, gen, (char**)&bCode, (char**)&bColumn ) - { - if ( bCode == b0 ) - { // the unused part of the columns - Cudd_RecursiveDeref( dd, bColumn ); - Cudd_RecursiveDeref( dd, bCode ); - continue; - } - else - { - s_pbTemp[ nCols ] = bColumn; // takes ref - Cudd_RecursiveDeref( dd, bCode ); - nCols++; - } - } - st_free_table( CutNodes ); -// assert( nCols == (int)nMints ); - } - - // encode the columns - if ( s_MultiStart-Level == 0 ) // we reached the bottom level of recursion - { - assert( nCols == 1 ); -// assert( (int)nMints == 1 ); - bRes = s_pbTemp[0]; Cudd_Ref( bRes ); - } - else - { - bRes = Extra_bddEncodingBinary( dd, s_pbTemp, nCols, pCVars+Level, s_MultiStart-Level ); Cudd_Ref( bRes ); - } - - // deref the columns - { - int i; - for ( i = 0; i < nCols; i++ ) - Cudd_RecursiveDeref( dd, s_pbTemp[i] ); - } - } - else - { - // cofactor the problem as specified in the best solution - DdNode * bCof0, * bCof1; - DdNode * bRes0, * bRes1; - DdNode * bProd0, * bProd1; - DdNode * bTemp; - DdNode * bVarNext = dd->vars[ s_VarOrderBest[Level] ]; - - bCof0 = Cudd_Cofactor( dd, bEncoded, Cudd_Not( bVarNext ) ); Cudd_Ref( bCof0 ); - bCof1 = Cudd_Cofactor( dd, bEncoded, bVarNext ); Cudd_Ref( bCof1 ); - - // call recursively - bRes0 = CreateTheCodes_rec( dd, bCof0, Level+1, pCVars ); Cudd_Ref( bRes0 ); - bRes1 = CreateTheCodes_rec( dd, bCof1, Level+1, pCVars ); Cudd_Ref( bRes1 ); - - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); - - // compose the result using the identity (bVarNext <=> pCVars[Level]) - this is wrong! - // compose the result as follows: x'y'F0 + xyF1 - bProd0 = Cudd_bddAnd( dd, Cudd_Not(bVarNext), Cudd_Not(pCVars[Level]) ); Cudd_Ref( bProd0 ); - bProd1 = Cudd_bddAnd( dd, bVarNext , pCVars[Level] ); Cudd_Ref( bProd1 ); - - bProd0 = Cudd_bddAnd( dd, bTemp = bProd0, bRes0 ); Cudd_Ref( bProd0 ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bRes0 ); - - bProd1 = Cudd_bddAnd( dd, bTemp = bProd1, bRes1 ); Cudd_Ref( bProd1 ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bRes1 ); - - bRes = Cudd_bddOr( dd, bProd0, bProd1 ); Cudd_Ref( bRes ); - - Cudd_RecursiveDeref( dd, bProd0 ); - Cudd_RecursiveDeref( dd, bProd1 ); - } - Cudd_Deref( bRes ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Computes the current set of variables and counts the number of minterms.] - - Description [Old implementation.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void EvaluateEncodings_rec( DdManager * dd, DdNode * bVarsCol, int nVarsCol, int nMulti, int Level ) -// bVarsCol is the set of remaining variables -// nVarsCol is the number of remaining variables -// nMulti is the number of encoding variables to be used -// Level is the level of recursion, from which this function is called -// if we successfully finish this procedure, Level also stands for how many encoding variabled we saved -{ - int i, k; - int nEntries = (1<<(Level-1)); // the number of entries in the field of the previous level - DdNode * bVars0, * bVars1; // the cofactors - unsigned nMint0, nMint1; // the number of minterms - DdNode * bTempV; - DdNode * bVarTop; - int fBreak; - - - // there is no need to search above this level - if ( Level > s_MaxDepth ) - return; - - // if there are no variables left, quit the research - if ( bVarsCol == b1 ) - return; - - if ( s_BackTracks > s_BackTrackLimit ) - return; - - s_BackTracks++; - - // otherwise, go through the remaining variables - for ( bTempV = bVarsCol; bTempV != b1; bTempV = cuddT(bTempV) ) - { - // the currently tested variable - bVarTop = dd->vars[bTempV->index]; - - // put it into the array - s_VarOrderCur[Level-1] = bTempV->index; - - // go through the entries and fill them out by cofactoring - fBreak = 0; - for ( i = 0; i < nEntries; i++ ) - { - bVars0 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], Cudd_Not(bVarTop), &nMint0 ); - Cudd_Ref( bVars0 ); - - if ( nMint0 > Extra_Power2( nMulti-1 ) ) - { - // there is no way to encode - dereference and return - Cudd_RecursiveDeref( dd, bVars0 ); - fBreak = 1; - break; - } - - bVars1 = ComputeVarSetAndCountMinterms( dd, s_Field[Level-1][i], bVarTop, &nMint1 ); - Cudd_Ref( bVars1 ); - - if ( nMint1 > Extra_Power2( nMulti-1 ) ) - { - // there is no way to encode - dereference and return - Cudd_RecursiveDeref( dd, bVars0 ); - Cudd_RecursiveDeref( dd, bVars1 ); - fBreak = 1; - break; - } - - // otherwise, add these two cofactors - s_Field[Level][2*i + 0] = bVars0; // takes ref - s_Field[Level][2*i + 1] = bVars1; // takes ref - } - - if ( !fBreak ) - { - DdNode * bVarsRem; - // if we ended up here, it means that the cofactors w.r.t. variable bVarTop satisfy the condition - // save this situation - if ( s_nVarsBest < Level ) - { - s_nVarsBest = Level; - // copy the variable assignment - for ( k = 0; k < Level; k++ ) - s_VarOrderBest[k] = s_VarOrderCur[k]; - } - - // call recursively - // get the new variable set - if ( nMulti-1 > 0 ) - { - bVarsRem = Cudd_bddExistAbstract( dd, bVarsCol, bVarTop ); Cudd_Ref( bVarsRem ); - EvaluateEncodings_rec( dd, bVarsRem, nVarsCol-1, nMulti-1, Level+1 ); - Cudd_RecursiveDeref( dd, bVarsRem ); - } - } - - // deref the contents of the array - for ( k = 0; k < i; k++ ) - { - Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 0] ); - Cudd_RecursiveDeref( dd, s_Field[Level][2*k + 1] ); - } - - // if the solution is found, there is no need to continue - if ( s_nVarsBest == s_MaxDepth ) - return; - - // if the solution is found, there is no need to continue - if ( s_nVarsBest == s_MultiStart ) - return; - } - // at this point, we have tried all possible directions in the space of variables -} - -/**Function******************************************************************** - - Synopsis [Computes the current set of variables and counts the number of minterms.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * ComputeVarSetAndCountMinterms( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ) -// takes bVars - the variables cofactored so far (some of them may be in negative polarity) -// bVarTop - the topmost variable w.r.t. which to cofactor (may be in negative polarity) -// returns the cost and the new set of variables (bVars & bVarTop) -{ - DdNode * bVarsRes; - - // get the resulting set of variables - bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes ); - - // increment signature before calling Cudd_CountCofactorMinterms() - s_Signature++; - *Cost = Extra_CountCofactorMinterms( dd, s_Encoded, bVarsRes, s_VarAll ); - - Cudd_Deref( bVarsRes ); -// s_CountCalls++; - return bVarsRes; -} - -/**Function******************************************************************** - - Synopsis [Computes the current set of variables and counts the number of minterms.] - - Description [The old implementation, which is approximately 4 times slower.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * ComputeVarSetAndCountMinterms2( DdManager * dd, DdNode * bVars, DdNode * bVarTop, unsigned * Cost ) -{ - DdNode * bVarsRes; - DdNode * bCof, * bFun; - - bVarsRes = Cudd_bddAnd( dd, bVars, bVarTop ); Cudd_Ref( bVarsRes ); - - bCof = Cudd_Cofactor( dd, s_Encoded, bVarsRes ); Cudd_Ref( bCof ); - bFun = Cudd_bddExistAbstract( dd, bCof, s_VarAll ); Cudd_Ref( bFun ); - *Cost = (unsigned)Cudd_CountMinterm( dd, bFun, s_MultiStart ); - Cudd_RecursiveDeref( dd, bFun ); - Cudd_RecursiveDeref( dd, bCof ); - - Cudd_Deref( bVarsRes ); -// s_CountCalls++; - return bVarsRes; -} - - -/**Function******************************************************************** - - Synopsis [Counts the number of encoding minterms pointed to by the cofactor of the function.] - - Description [] - - SideEffects [None] - -******************************************************************************/ -unsigned Extra_CountCofactorMinterms( DdManager * dd, DdNode * bFunc, DdNode * bVarsCof, DdNode * bVarsAll ) -// this function computes how many minterms depending on the encoding variables -// are there in the cofactor of bFunc w.r.t. variables bVarsCof -// bFunc is assumed to depend on variables s_VarsAll -// the variables s_VarsAll should be ordered above the encoding variables -{ - unsigned HKey; - DdNode * bFuncR; - - // if the function is zero, there are no minterms -// if ( bFunc == b0 ) -// return 0; - -// if ( st_lookup(Visited, (char*)bFunc, NULL) ) -// return 0; - -// HKey = hashKey2c( s_Signature, bFuncR ); -// if ( HHTable1[HKey].Sign == s_Signature && HHTable1[HKey].Arg1 == bFuncR ) // this node is visited -// return 0; - - - // check the hash-table - bFuncR = Cudd_Regular(bFunc); -// HKey = hashKey2( s_Signature, bFuncR, _TABLESIZE_COF ); - HKey = hashKey2( s_Signature, bFunc, _TABLESIZE_COF ); - for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF ) -// if ( HHTable1[HKey].Arg1 == bFuncR ) // this node is visited - if ( HHTable1[HKey].Arg1 == bFunc ) // this node is visited - return 0; - - - // if the function is already the code - if ( dd->perm[bFuncR->index] >= s_EncodingVarsLevel ) - { -// st_insert(Visited, (char*)bFunc, NULL); - -// HHTable1[HKey].Sign = s_Signature; -// HHTable1[HKey].Arg1 = bFuncR; - - assert( HHTable1[HKey].Sign != s_Signature ); - HHTable1[HKey].Sign = s_Signature; -// HHTable1[HKey].Arg1 = bFuncR; - HHTable1[HKey].Arg1 = bFunc; - - return Extra_CountMintermsSimple( bFunc, (1<perm[bFuncR->index]; - int LevelC = cuddI(dd,bVarsCofR->index); - int LevelA = dd->perm[bVarsAll->index]; - - int LevelTop = LevelF; - - if ( LevelTop > LevelC ) - LevelTop = LevelC; - - if ( LevelTop > LevelA ) - LevelTop = LevelA; - - // the top var in the function or in cofactoring vars always belongs to the set of all vars - assert( !( LevelTop == LevelF || LevelTop == LevelC ) || LevelTop == LevelA ); - - // cofactor the function - if ( LevelTop == LevelF ) - { - if ( bFuncR != bFunc ) // bFunc is complemented - { - bFunc0 = Cudd_Not( cuddE(bFuncR) ); - bFunc1 = Cudd_Not( cuddT(bFuncR) ); - } - else - { - bFunc0 = cuddE(bFuncR); - bFunc1 = cuddT(bFuncR); - } - } - else // bVars is higher in the variable order - bFunc0 = bFunc1 = bFunc; - - // cofactor the cube - if ( LevelTop == LevelC ) - { - if ( bVarsCofR != bVarsCof ) // bFunc is complemented - { - bVarsCof0 = Cudd_Not( cuddE(bVarsCofR) ); - bVarsCof1 = Cudd_Not( cuddT(bVarsCofR) ); - } - else - { - bVarsCof0 = cuddE(bVarsCofR); - bVarsCof1 = cuddT(bVarsCofR); - } - } - else // bVars is higher in the variable order - bVarsCof0 = bVarsCof1 = bVarsCof; - - // there are two cases: - // (1) the top variable belongs to the cofactoring variables - // (2) the top variable does not belong to the cofactoring variables - - // (1) the top variable belongs to the cofactoring variables - Res = 0; - if ( LevelTop == LevelC ) - { - if ( bVarsCof1 == b0 ) // this is a negative cofactor - { - if ( bFunc0 != b0 ) - Res = Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) ); - } - else // this is a positive cofactor - { - if ( bFunc1 != b0 ) - Res = Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) ); - } - } - else - { - if ( bFunc0 != b0 ) - Res += Extra_CountCofactorMinterms( dd, bFunc0, bVarsCof0, cuddT(bVarsAll) ); - - if ( bFunc1 != b0 ) - Res += Extra_CountCofactorMinterms( dd, bFunc1, bVarsCof1, cuddT(bVarsAll) ); - } - -// st_insert(Visited, (char*)bFunc, NULL); - -// HHTable1[HKey].Sign = s_Signature; -// HHTable1[HKey].Arg1 = bFuncR; - - // skip through the entries with the same signatures - // (these might have been created at the time of recursive calls) - for ( ; HHTable1[HKey].Sign == s_Signature; HKey = (HKey+1) % _TABLESIZE_COF ); - assert( HHTable1[HKey].Sign != s_Signature ); - HHTable1[HKey].Sign = s_Signature; -// HHTable1[HKey].Arg1 = bFuncR; - HHTable1[HKey].Arg1 = bFunc; - - return Res; - } -} - -/**Function******************************************************************** - - Synopsis [Counts the number of minterms.] - - Description [This function counts minterms for functions up to 32 variables - using a local cache. The terminal value (s_Termina) should be adjusted for - BDDs and ADDs.] - - SideEffects [None] - -******************************************************************************/ -unsigned Extra_CountMintermsSimple( DdNode * bFunc, unsigned max ) -{ - unsigned HKey; - - // normalize - if ( Cudd_IsComplement(bFunc) ) - return max - Extra_CountMintermsSimple( Cudd_Not(bFunc), max ); - - // now it is known that the function is not complemented - if ( cuddIsConstant(bFunc) ) - return ((bFunc==s_Terminal)? 0: max); - - // check cache - HKey = hashKey2( bFunc, max, _TABLESIZE_MINT ); - if ( HHTable2[HKey].Arg1 == bFunc && HHTable2[HKey].Arg2 == max ) - return HHTable2[HKey].Res; - else - { - // min = min0/2 + min1/2; - unsigned min = (Extra_CountMintermsSimple( cuddE(bFunc), max ) >> 1) + - (Extra_CountMintermsSimple( cuddT(bFunc), max ) >> 1); - - HHTable2[HKey].Arg1 = bFunc; - HHTable2[HKey].Arg2 = max; - HHTable2[HKey].Res = min; - - return min; - } -} /* end of Extra_CountMintermsSimple */ - - -/**Function******************************************************************** - - Synopsis [Visits the nodes.] - - Description [Visits the nodes above the cut and the nodes pointed to below the cut; - collects the visited nodes, counts how many times each node is visited, and sets - the path-sum to be the constant zero BDD.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void CountNodeVisits_rec( DdManager * dd, DdNode * aFunc, st_table * Visited ) - -{ - traventry * p; - char **slot; - if ( st_find_or_add(Visited, (char*)aFunc, &slot) ) - { // the entry already exists - p = (traventry*) *slot; - // increment the counter of incoming edges - p->nEdges++; - return; - } - // this node has not been visited - assert( !Cudd_IsComplement(aFunc) ); - - // create the new traversal entry - p = (traventry *) malloc( sizeof(traventry) ); - // set the initial sum of edges to zero BDD - p->bSum = b0; Cudd_Ref( b0 ); - // set the starting number of incoming edges - p->nEdges = 1; - // set this entry into the slot - *slot = (char*)p; - - // recur if the node is above the cut - if ( cuddI(dd,aFunc->index) < s_CutLevel ) - { - CountNodeVisits_rec( dd, cuddE(aFunc), Visited ); - CountNodeVisits_rec( dd, cuddT(aFunc), Visited ); - } -} /* end of CountNodeVisits_rec */ - - -/**Function******************************************************************** - - Synopsis [Revisits the nodes and computes the paths.] - - Description [This function visits the nodes above the cut having the goal of - summing all the incomming BDD edges; when this function comes across the node - below the cut, it saves this node in the CutNode table.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void CollectNodesAndComputePaths_rec( DdManager * dd, DdNode * aFunc, DdNode * bCube, st_table * Visited, st_table * CutNodes ) -{ - // find the node in the visited table - DdNode * bTemp; - traventry * p; - char **slot; - if ( st_find_or_add(Visited, (char*)aFunc, &slot) ) - { // the node is found - // get the pointer to the traversal entry - p = (traventry*) *slot; - - // make sure that the counter of incoming edges is positive - assert( p->nEdges > 0 ); - - // add the cube to the currently accumulated cubes - p->bSum = Cudd_bddOr( dd, bTemp = p->bSum, bCube ); Cudd_Ref( p->bSum ); - Cudd_RecursiveDeref( dd, bTemp ); - - // decrement the number of visits - p->nEdges--; - - // if more visits to this node are expected, return - if ( p->nEdges ) - return; - else // if ( p->nEdges == 0 ) - { // this is the last visit - propagate the cube - - // check where this node is - if ( cuddI(dd,aFunc->index) < s_CutLevel ) - { // the node is above the cut - DdNode * bCube0, * bCube1; - - // get the top-most variable - DdNode * bVarTop = dd->vars[aFunc->index]; - - // compute the propagated cubes - bCube0 = Cudd_bddAnd( dd, p->bSum, Cudd_Not( bVarTop ) ); Cudd_Ref( bCube0 ); - bCube1 = Cudd_bddAnd( dd, p->bSum, bVarTop ); Cudd_Ref( bCube1 ); - - // call recursively - CollectNodesAndComputePaths_rec( dd, cuddE(aFunc), bCube0, Visited, CutNodes ); - CollectNodesAndComputePaths_rec( dd, cuddT(aFunc), bCube1, Visited, CutNodes ); - - // dereference the cubes - Cudd_RecursiveDeref( dd, bCube0 ); - Cudd_RecursiveDeref( dd, bCube1 ); - return; - } - else - { // the node is below the cut - // add this node to the cut node table, if it is not yet there - -// DdNode * bNode; -// bNode = Cudd_addBddPattern( dd, aFunc ); Cudd_Ref( bNode ); - if ( st_find_or_add(CutNodes, (char*)aFunc, &slot) ) - { // the node exists - should never happen - assert( 0 ); - } - *slot = (char*) p->bSum; Cudd_Ref( p->bSum ); - // the table takes the reference of bNode - return; - } - } - } - - // the node does not exist in the visited table - should never happen - assert(0); - -} /* end of CollectNodesAndComputePaths_rec */ - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/misc/extra/extraBddKmap.c b/src/misc/extra/extraBddKmap.c deleted file mode 100644 index bb43db68..00000000 --- a/src/misc/extra/extraBddKmap.c +++ /dev/null @@ -1,783 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddKmap.c] - - PackageName [extra] - - Synopsis [Visualizing the K-map.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - September 1, 2003.] - - Revision [$Id: extraBddKmap.c,v 1.0 2003/05/21 18:03:50 alanmi Exp $] - -***********************************************************************/ - -/// K-map visualization using pseudo graphics /// -/// Version 1.0. Started - August 20, 2000 /// -/// Version 2.0. Added to EXTRA - July 17, 2001 /// - -#include "extra.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -// the maximum number of variables in the Karnaugh Map -#define MAXVARS 20 - -/* -// single line -#define SINGLE_VERTICAL (char)179 -#define SINGLE_HORIZONTAL (char)196 -#define SINGLE_TOP_LEFT (char)218 -#define SINGLE_TOP_RIGHT (char)191 -#define SINGLE_BOT_LEFT (char)192 -#define SINGLE_BOT_RIGHT (char)217 - -// double line -#define DOUBLE_VERTICAL (char)186 -#define DOUBLE_HORIZONTAL (char)205 -#define DOUBLE_TOP_LEFT (char)201 -#define DOUBLE_TOP_RIGHT (char)187 -#define DOUBLE_BOT_LEFT (char)200 -#define DOUBLE_BOT_RIGHT (char)188 - -// line intersections -#define SINGLES_CROSS (char)197 -#define DOUBLES_CROSS (char)206 -#define S_HOR_CROSS_D_VER (char)215 -#define S_VER_CROSS_D_HOR (char)216 - -// single line joining -#define S_JOINS_S_VER_LEFT (char)180 -#define S_JOINS_S_VER_RIGHT (char)195 -#define S_JOINS_S_HOR_TOP (char)193 -#define S_JOINS_S_HOR_BOT (char)194 - -// double line joining -#define D_JOINS_D_VER_LEFT (char)185 -#define D_JOINS_D_VER_RIGHT (char)204 -#define D_JOINS_D_HOR_TOP (char)202 -#define D_JOINS_D_HOR_BOT (char)203 - -// single line joining double line -#define S_JOINS_D_VER_LEFT (char)182 -#define S_JOINS_D_VER_RIGHT (char)199 -#define S_JOINS_D_HOR_TOP (char)207 -#define S_JOINS_D_HOR_BOT (char)209 -*/ - -// single line -#define SINGLE_VERTICAL (char)'|' -#define SINGLE_HORIZONTAL (char)'-' -#define SINGLE_TOP_LEFT (char)'+' -#define SINGLE_TOP_RIGHT (char)'+' -#define SINGLE_BOT_LEFT (char)'+' -#define SINGLE_BOT_RIGHT (char)'+' - -// double line -#define DOUBLE_VERTICAL (char)'|' -#define DOUBLE_HORIZONTAL (char)'-' -#define DOUBLE_TOP_LEFT (char)'+' -#define DOUBLE_TOP_RIGHT (char)'+' -#define DOUBLE_BOT_LEFT (char)'+' -#define DOUBLE_BOT_RIGHT (char)'+' - -// line intersections -#define SINGLES_CROSS (char)'+' -#define DOUBLES_CROSS (char)'+' -#define S_HOR_CROSS_D_VER (char)'+' -#define S_VER_CROSS_D_HOR (char)'+' - -// single line joining -#define S_JOINS_S_VER_LEFT (char)'+' -#define S_JOINS_S_VER_RIGHT (char)'+' -#define S_JOINS_S_HOR_TOP (char)'+' -#define S_JOINS_S_HOR_BOT (char)'+' - -// double line joining -#define D_JOINS_D_VER_LEFT (char)'+' -#define D_JOINS_D_VER_RIGHT (char)'+' -#define D_JOINS_D_HOR_TOP (char)'+' -#define D_JOINS_D_HOR_BOT (char)'+' - -// single line joining double line -#define S_JOINS_D_VER_LEFT (char)'+' -#define S_JOINS_D_VER_RIGHT (char)'+' -#define S_JOINS_D_HOR_TOP (char)'+' -#define S_JOINS_D_HOR_BOT (char)'+' - - -// other symbols -#define UNDERSCORE (char)95 -//#define SYMBOL_ZERO (char)248 // degree sign -//#define SYMBOL_ZERO (char)'o' -#define SYMBOL_ZERO (char)' ' -#define SYMBOL_ONE (char)'1' -#define SYMBOL_DC (char)'-' -#define SYMBOL_OVERLAP (char)'?' - -// full cells and half cells -#define CELL_FREE (char)32 -#define CELL_FULL (char)219 -#define HALF_UPPER (char)223 -#define HALF_LOWER (char)220 -#define HALF_LEFT (char)221 -#define HALF_RIGHT (char)222 - - -/*---------------------------------------------------------------------------*/ -/* Structure declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -// the array of BDD variables used internally -static DdNode * s_XVars[MAXVARS]; - -// flag which determines where the horizontal variable names are printed -static int fHorizontalVarNamesPrintedAbove = 1; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -// Oleg's way of generating the gray code -static int GrayCode( int BinCode ); -static int BinCode ( int GrayCode ); - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Prints the K-map of the function.] - - Description [If the pointer to the array of variables XVars is NULL, - fSuppType determines how the support will be determined. - fSuppType == 0 -- takes the first nVars of the manager - fSuppType == 1 -- takes the topmost nVars of the manager - fSuppType == 2 -- determines support from the on-set and the offset - ] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Extra_PrintKMap( - FILE * Output, /* the output stream */ - DdManager * dd, - DdNode * OnSet, - DdNode * OffSet, - int nVars, - DdNode ** XVars, - int fSuppType, /* the flag which determines how support is computed */ - char ** pVarNames ) -{ - int d, p, n, s, v, h, w; - int nVarsVer; - int nVarsHor; - int nCellsVer; - int nCellsHor; - int nSkipSpaces; - - // make sure that on-set and off-set do not overlap - if ( !Cudd_bddLeq( dd, OnSet, Cudd_Not(OffSet) ) ) - { - fprintf( Output, "PrintKMap(): The on-set and the off-set overlap\n" ); - return; - } -/* - if ( OnSet == b1 ) - { - fprintf( Output, "PrintKMap(): Constant 1\n" ); - return; - } - if ( OffSet == b1 ) - { - fprintf( Output, "PrintKMap(): Constant 0\n" ); - return; - } -*/ - if ( nVars < 0 || nVars > MAXVARS ) - { - fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS ); - return; - } - - // determine the support if it is not given - if ( XVars == NULL ) - { - if ( fSuppType == 0 ) - { // assume that the support includes the first nVars of the manager - assert( nVars ); - for ( v = 0; v < nVars; v++ ) - s_XVars[v] = Cudd_bddIthVar( dd, v ); - } - else if ( fSuppType == 1 ) - { // assume that the support includes the topmost nVars of the manager - assert( nVars ); - for ( v = 0; v < nVars; v++ ) - s_XVars[v] = Cudd_bddIthVar( dd, dd->invperm[v] ); - } - else // determine the support - { - DdNode * SuppOn, * SuppOff, * Supp; - int cVars = 0; - DdNode * TempSupp; - - // determine support - SuppOn = Cudd_Support( dd, OnSet ); Cudd_Ref( SuppOn ); - SuppOff = Cudd_Support( dd, OffSet ); Cudd_Ref( SuppOff ); - Supp = Cudd_bddAnd( dd, SuppOn, SuppOff ); Cudd_Ref( Supp ); - Cudd_RecursiveDeref( dd, SuppOn ); - Cudd_RecursiveDeref( dd, SuppOff ); - - nVars = Cudd_SupportSize( dd, Supp ); - if ( nVars > MAXVARS ) - { - fprintf( Output, "PrintKMap(): The number of variables is more than %d\n", MAXVARS ); - Cudd_RecursiveDeref( dd, Supp ); - return; - } - - // assign variables - for ( TempSupp = Supp; TempSupp != dd->one; TempSupp = Cudd_T(TempSupp), cVars++ ) - s_XVars[cVars] = Cudd_bddIthVar( dd, TempSupp->index ); - - Cudd_RecursiveDeref( dd, TempSupp ); - } - } - else - { - // copy variables - assert( XVars ); - for ( v = 0; v < nVars; v++ ) - s_XVars[v] = XVars[v]; - } - - //////////////////////////////////////////////////////////////////// - // determine the Karnaugh map parameters - nVarsVer = nVars/2; - nVarsHor = nVars - nVarsVer; - nCellsVer = (1< MAXVARS ) - { - fprintf( Output, "PrintKMap(): The number of variables is less than zero or more than %d\n", MAXVARS ); - return; - } - - - //////////////////////////////////////////////////////////////////// - // determine the Karnaugh map parameters - nVarsVer = nXVars; - nVarsHor = nYVars; - nCellsVer = (1<> 1 ); -} - -/**Function******************************************************************** - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int BinCode ( int GrayCode ) -{ - int bc = GrayCode; - while( GrayCode >>= 1 ) bc ^= GrayCode; - return bc; -} - - diff --git a/src/misc/extra/extraBddMisc.c b/src/misc/extra/extraBddMisc.c deleted file mode 100644 index a3320ad3..00000000 --- a/src/misc/extra/extraBddMisc.c +++ /dev/null @@ -1,1614 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddMisc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [DD-based utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraBddMisc.c,v 1.4 2005/10/04 00:19:54 alanmi Exp $] - -***********************************************************************/ - -#include "extra.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -// file "extraDdTransfer.c" -static DdNode * extraTransferPermuteRecur( DdManager * ddS, DdManager * ddD, DdNode * f, st_table * table, int * Permute ); -static DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ); -static DdNode * cuddBddPermuteRecur ARGS( ( DdManager * manager, DdHashTable * table, DdNode * node, int *permut ) ); - -// file "cuddUtils.c" -static void ddSupportStep(DdNode *f, int *support); -static void ddClearFlag(DdNode *f); - -static DdNode* extraZddPrimes( DdManager *dd, DdNode* F ); - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Convert a {A,B}DD from a manager to another with variable remapping.] - - Description [Convert a {A,B}DD from a manager to another one. The orders of the - variables in the two managers may be different. Returns a - pointer to the {A,B}DD in the destination manager if successful; NULL - otherwise. The i-th entry in the array Permute tells what is the index - of the i-th variable from the old manager in the new manager.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_TransferPermute( DdManager * ddSource, DdManager * ddDestination, DdNode * f, int * Permute ) -{ - DdNode * bRes; - do - { - ddDestination->reordered = 0; - bRes = extraTransferPermute( ddSource, ddDestination, f, Permute ); - } - while ( ddDestination->reordered == 1 ); - return ( bRes ); - -} /* end of Extra_TransferPermute */ - -/**Function******************************************************************** - - Synopsis [Transfers the BDD from one manager into another level by level.] - - Description [Transfers the BDD from one manager into another while - preserving the correspondence between variables level by level.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_TransferLevelByLevel( DdManager * ddSource, DdManager * ddDestination, DdNode * f ) -{ - DdNode * bRes; - int * pPermute; - int nMin, nMax, i; - - nMin = ddMin(ddSource->size, ddDestination->size); - nMax = ddMax(ddSource->size, ddDestination->size); - pPermute = ALLOC( int, nMax ); - // set up the variable permutation - for ( i = 0; i < nMin; i++ ) - pPermute[ ddSource->invperm[i] ] = ddDestination->invperm[i]; - if ( ddSource->size > ddDestination->size ) - { - for ( ; i < nMax; i++ ) - pPermute[ ddSource->invperm[i] ] = -1; - } - bRes = Extra_TransferPermute( ddSource, ddDestination, f, pPermute ); - FREE( pPermute ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Remaps the function to depend on the topmost variables on the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddRemapUp( - DdManager * dd, - DdNode * bF ) -{ - int * pPermute; - DdNode * bSupp, * bTemp, * bRes; - int Counter; - - pPermute = ALLOC( int, dd->size ); - - // get support - bSupp = Cudd_Support( dd, bF ); Cudd_Ref( bSupp ); - - // create the variable map - // to remap the DD into the upper part of the manager - Counter = 0; - for ( bTemp = bSupp; bTemp != dd->one; bTemp = cuddT(bTemp) ) - pPermute[bTemp->index] = dd->invperm[Counter++]; - - // transfer the BDD and remap it - bRes = Cudd_bddPermute( dd, bF, pPermute ); Cudd_Ref( bRes ); - - // remove support - Cudd_RecursiveDeref( dd, bSupp ); - - // return - Cudd_Deref( bRes ); - free( pPermute ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Moves the BDD by the given number of variables up or down.] - - Description [] - - SideEffects [] - - SeeAlso [Extra_bddShift] - -******************************************************************************/ -DdNode * Extra_bddMove( - DdManager * dd, /* the DD manager */ - DdNode * bF, - int nVars) -{ - DdNode * res; - DdNode * bVars; - if ( nVars == 0 ) - return bF; - if ( Cudd_IsConstant(bF) ) - return bF; - assert( nVars <= dd->size ); - if ( nVars > 0 ) - bVars = dd->vars[nVars]; - else - bVars = Cudd_Not(dd->vars[-nVars]); - - do { - dd->reordered = 0; - res = extraBddMove( dd, bF, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_bddMove */ - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_StopManager( DdManager * dd ) -{ - int RetValue; - // check for remaining references in the package - RetValue = Cudd_CheckZeroRef( dd ); - if ( RetValue > 0 ) - printf( "\nThe number of referenced nodes = %d\n\n", RetValue ); -// Cudd_PrintInfo( dd, stdout ); - Cudd_Quit( dd ); -} - -/**Function******************************************************************** - - Synopsis [Outputs the BDD in a readable format.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -void Extra_bddPrint( DdManager * dd, DdNode * F ) -{ - DdGen * Gen; - int * Cube; - CUDD_VALUE_TYPE Value; - int nVars = dd->size; - int fFirstCube = 1; - int i; - - if ( F == NULL ) - { - printf("NULL"); - return; - } - if ( F == b0 ) - { - printf("Constant 0"); - return; - } - if ( F == b1 ) - { - printf("Constant 1"); - return; - } - - Cudd_ForeachCube( dd, F, Gen, Cube, Value ) - { - if ( fFirstCube ) - fFirstCube = 0; - else -// Output << " + "; - printf( " + " ); - - for ( i = 0; i < nVars; i++ ) - if ( Cube[i] == 0 ) - printf( "[%d]'", i ); -// printf( "%c'", (char)('a'+i) ); - else if ( Cube[i] == 1 ) - printf( "[%d]", i ); -// printf( "%c", (char)('a'+i) ); - } - -// printf("\n"); -} -/**Function******************************************************************** - - Synopsis [Returns the size of the support.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppSize( DdManager * dd, DdNode * bSupp ) -{ - int Counter = 0; - while ( bSupp != b1 ) - { - assert( !Cudd_IsComplement(bSupp) ); - assert( cuddE(bSupp) == b0 ); - - bSupp = cuddT(bSupp); - Counter++; - } - return Counter; -} - -/**Function******************************************************************** - - Synopsis [Returns 1 if the support contains the given BDD variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppContainVar( DdManager * dd, DdNode * bS, DdNode * bVar ) -{ - for( ; bS != b1; bS = cuddT(bS) ) - if ( bS->index == bVar->index ) - return 1; - return 0; -} - -/**Function******************************************************************** - - Synopsis [Returns 1 if two supports represented as BDD cubes are overlapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppOverlapping( DdManager * dd, DdNode * S1, DdNode * S2 ) -{ - while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) - { - // if the top vars are the same, they intersect - if ( S1->index == S2->index ) - return 1; - // if the top vars are different, skip the one, which is higher - if ( dd->perm[S1->index] < dd->perm[S2->index] ) - S1 = cuddT(S1); - else - S2 = cuddT(S2); - } - return 0; -} - -/**Function******************************************************************** - - Synopsis [Returns the number of different vars in two supports.] - - Description [Counts the number of variables that appear in one support and - does not appear in other support. If the number exceeds DiffMax, returns DiffMax.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppDifferentVars( DdManager * dd, DdNode * S1, DdNode * S2, int DiffMax ) -{ - int Result = 0; - while ( S1->index != CUDD_CONST_INDEX && S2->index != CUDD_CONST_INDEX ) - { - // if the top vars are the same, this var is the same - if ( S1->index == S2->index ) - { - S1 = cuddT(S1); - S2 = cuddT(S2); - continue; - } - // the top var is different - Result++; - - if ( Result >= DiffMax ) - return DiffMax; - - // if the top vars are different, skip the one, which is higher - if ( dd->perm[S1->index] < dd->perm[S2->index] ) - S1 = cuddT(S1); - else - S2 = cuddT(S2); - } - - // consider the remaining variables - if ( S1->index != CUDD_CONST_INDEX ) - Result += Extra_bddSuppSize(dd,S1); - else if ( S2->index != CUDD_CONST_INDEX ) - Result += Extra_bddSuppSize(dd,S2); - - if ( Result >= DiffMax ) - return DiffMax; - return Result; -} - - -/**Function******************************************************************** - - Synopsis [Checks the support containment.] - - Description [This function returns 1 if one support is contained in another. - In this case, bLarge (bSmall) is assigned to point to the larger (smaller) support. - If the supports are identical, return 0 and does not assign the supports!] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddSuppCheckContainment( DdManager * dd, DdNode * bL, DdNode * bH, DdNode ** bLarge, DdNode ** bSmall ) -{ - DdNode * bSL = bL; - DdNode * bSH = bH; - int fLcontainsH = 1; - int fHcontainsL = 1; - int TopVar; - - if ( bSL == bSH ) - return 0; - - while ( bSL != b1 || bSH != b1 ) - { - if ( bSL == b1 ) - { // Low component has no vars; High components has some vars - fLcontainsH = 0; - if ( fHcontainsL == 0 ) - return 0; - else - break; - } - - if ( bSH == b1 ) - { // similarly - fHcontainsL = 0; - if ( fLcontainsH == 0 ) - return 0; - else - break; - } - - // determine the topmost var of the supports by comparing their levels - if ( dd->perm[bSL->index] < dd->perm[bSH->index] ) - TopVar = bSL->index; - else - TopVar = bSH->index; - - if ( TopVar == bSL->index && TopVar == bSH->index ) - { // they are on the same level - // it does not tell us anything about their containment - // skip this var - bSL = cuddT(bSL); - bSH = cuddT(bSH); - } - else if ( TopVar == bSL->index ) // and TopVar != bSH->index - { // Low components is higher and contains more vars - // it is not possible that High component contains Low - fHcontainsL = 0; - // skip this var - bSL = cuddT(bSL); - } - else // if ( TopVar == bSH->index ) // and TopVar != bSL->index - { // similarly - fLcontainsH = 0; - // skip this var - bSH = cuddT(bSH); - } - - // check the stopping condition - if ( !fHcontainsL && !fLcontainsH ) - return 0; - } - // only one of them can be true at the same time - assert( !fHcontainsL || !fLcontainsH ); - if ( fHcontainsL ) - { - *bLarge = bH; - *bSmall = bL; - } - else // fLcontainsH - { - *bLarge = bL; - *bSmall = bH; - } - return 1; -} - - -/**Function******************************************************************** - - Synopsis [Finds variables on which the DD depends and returns them as am array.] - - Description [Finds the variables on which the DD depends. Returns an array - with entries set to 1 for those variables that belong to the support; - NULL otherwise. The array is allocated by the user and should have at least - as many entries as the maximum number of variables in BDD and ZDD parts of - the manager.] - - SideEffects [None] - - SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport] - -******************************************************************************/ -int * -Extra_SupportArray( - DdManager * dd, /* manager */ - DdNode * f, /* DD whose support is sought */ - int * support ) /* array allocated by the user */ -{ - int i, size; - - /* Initialize support array for ddSupportStep. */ - size = ddMax(dd->size, dd->sizeZ); - for (i = 0; i < size; i++) - support[i] = 0; - - /* Compute support and clean up markers. */ - ddSupportStep(Cudd_Regular(f),support); - ddClearFlag(Cudd_Regular(f)); - - return(support); - -} /* end of Extra_SupportArray */ - -/**Function******************************************************************** - - Synopsis [Finds the variables on which a set of DDs depends.] - - Description [Finds the variables on which a set of DDs depends. - The set must contain either BDDs and ADDs, or ZDDs. - Returns a BDD consisting of the product of the variables if - successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_Support Cudd_ClassifySupport] - -******************************************************************************/ -int * -Extra_VectorSupportArray( - DdManager * dd, /* manager */ - DdNode ** F, /* array of DDs whose support is sought */ - int n, /* size of the array */ - int * support ) /* array allocated by the user */ -{ - int i, size; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax( dd->size, dd->sizeZ ); - for ( i = 0; i < size; i++ ) - support[i] = 0; - - /* Compute support and clean up markers. */ - for ( i = 0; i < n; i++ ) - ddSupportStep( Cudd_Regular(F[i]), support ); - for ( i = 0; i < n; i++ ) - ddClearFlag( Cudd_Regular(F[i]) ); - - return support; -} - -/**Function******************************************************************** - - Synopsis [Find any cube belonging to the on-set of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddFindOneCube( DdManager * dd, DdNode * bF ) -{ - char * s_Temp; - DdNode * bCube, * bTemp; - int v; - - // get the vector of variables in the cube - s_Temp = ALLOC( char, dd->size ); - Cudd_bddPickOneCube( dd, bF, s_Temp ); - - // start the cube - bCube = b1; Cudd_Ref( bCube ); - for ( v = 0; v < dd->size; v++ ) - if ( s_Temp[v] == 0 ) - { -// Cube &= !s_XVars[v]; - bCube = Cudd_bddAnd( dd, bTemp = bCube, Cudd_Not(dd->vars[v]) ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - else if ( s_Temp[v] == 1 ) - { -// Cube &= s_XVars[v]; - bCube = Cudd_bddAnd( dd, bTemp = bCube, dd->vars[v] ); Cudd_Ref( bCube ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref(bCube); - free( s_Temp ); - return bCube; -} - -/**Function******************************************************************** - - Synopsis [Returns one cube contained in the given BDD.] - - Description [This function returns the cube with the smallest - bits-to-integer value.] - - SideEffects [] - -******************************************************************************/ -DdNode * Extra_bddGetOneCube( DdManager * dd, DdNode * bFunc ) -{ - DdNode * bFuncR, * bFunc0, * bFunc1; - DdNode * bRes0, * bRes1, * bRes; - - bFuncR = Cudd_Regular(bFunc); - if ( cuddIsConstant(bFuncR) ) - return bFunc; - - // cofactor - if ( Cudd_IsComplement(bFunc) ) - { - bFunc0 = Cudd_Not( cuddE(bFuncR) ); - bFunc1 = Cudd_Not( cuddT(bFuncR) ); - } - else - { - bFunc0 = cuddE(bFuncR); - bFunc1 = cuddT(bFuncR); - } - - // try to find the cube with the negative literal - bRes0 = Extra_bddGetOneCube( dd, bFunc0 ); Cudd_Ref( bRes0 ); - - if ( bRes0 != b0 ) - { - bRes = Cudd_bddAnd( dd, bRes0, Cudd_Not(dd->vars[bFuncR->index]) ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bRes0 ); - } - else - { - Cudd_RecursiveDeref( dd, bRes0 ); - // try to find the cube with the positive literal - bRes1 = Extra_bddGetOneCube( dd, bFunc1 ); Cudd_Ref( bRes1 ); - assert( bRes1 != b0 ); - bRes = Cudd_bddAnd( dd, bRes1, dd->vars[bFuncR->index] ); Cudd_Ref( bRes ); - Cudd_RecursiveDeref( dd, bRes1 ); - } - - Cudd_Deref( bRes ); - return bRes; -} - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddComputeRangeCube( DdManager * dd, int iStart, int iStop ) -{ - DdNode * bTemp, * bProd; - int i; - assert( iStart <= iStop ); - assert( iStart >= 0 && iStart <= dd->size ); - assert( iStop >= 0 && iStop <= dd->size ); - bProd = b1; Cudd_Ref( bProd ); - for ( i = iStart; i < iStop; i++ ) - { - bProd = Cudd_bddAnd( dd, bTemp = bProd, dd->vars[i] ); Cudd_Ref( bProd ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bProd ); - return bProd; -} - -/**Function******************************************************************** - - Synopsis [Computes the cube of BDD variables corresponding to bits it the bit-code] - - Description [Returns a bdd composed of elementary bdds found in array BddVars[] such - that the bdd vars encode the number Value of bit length CodeWidth (if fMsbFirst is 1, - the most significant bit is encoded with the first bdd variable). If the variables - BddVars are not specified, takes the first CodeWidth variables of the manager] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddBitsToCube( DdManager * dd, int Code, int CodeWidth, DdNode ** pbVars, int fMsbFirst ) -{ - int z; - DdNode * bTemp, * bVar, * bVarBdd, * bResult; - - bResult = b1; Cudd_Ref( bResult ); - for ( z = 0; z < CodeWidth; z++ ) - { - bVarBdd = (pbVars)? pbVars[z]: dd->vars[z]; - if ( fMsbFirst ) - bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (CodeWidth-1-z)))==0 ); - else - bVar = Cudd_NotCond( bVarBdd, (Code & (1 << (z)))==0 ); - bResult = Cudd_bddAnd( dd, bTemp = bResult, bVar ); Cudd_Ref( bResult ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bResult ); - - return bResult; -} /* end of Extra_bddBitsToCube */ - -/**Function******************************************************************** - - Synopsis [Finds the support as a negative polarity cube.] - - Description [Finds the variables on which a DD depends. Returns a BDD - consisting of the product of the variables in the negative polarity - if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [Cudd_VectorSupport Cudd_Support] - -******************************************************************************/ -DdNode * Extra_bddSupportNegativeCube( DdManager * dd, DdNode * f ) -{ - int *support; - DdNode *res, *tmp, *var; - int i, j; - int size; - - /* Allocate and initialize support array for ddSupportStep. */ - size = ddMax( dd->size, dd->sizeZ ); - support = ALLOC( int, size ); - if ( support == NULL ) - { - dd->errorCode = CUDD_MEMORY_OUT; - return ( NULL ); - } - for ( i = 0; i < size; i++ ) - { - support[i] = 0; - } - - /* Compute support and clean up markers. */ - ddSupportStep( Cudd_Regular( f ), support ); - ddClearFlag( Cudd_Regular( f ) ); - - /* Transform support from array to cube. */ - do - { - dd->reordered = 0; - res = DD_ONE( dd ); - cuddRef( res ); - for ( j = size - 1; j >= 0; j-- ) - { /* for each level bottom-up */ - i = ( j >= dd->size ) ? j : dd->invperm[j]; - if ( support[i] == 1 ) - { - var = cuddUniqueInter( dd, i, dd->one, Cudd_Not( dd->one ) ); - ////////////////////////////////////////////////////////////////// - var = Cudd_Not(var); - ////////////////////////////////////////////////////////////////// - cuddRef( var ); - tmp = cuddBddAndRecur( dd, res, var ); - if ( tmp == NULL ) - { - Cudd_RecursiveDeref( dd, res ); - Cudd_RecursiveDeref( dd, var ); - res = NULL; - break; - } - cuddRef( tmp ); - Cudd_RecursiveDeref( dd, res ); - Cudd_RecursiveDeref( dd, var ); - res = tmp; - } - } - } - while ( dd->reordered == 1 ); - - FREE( support ); - if ( res != NULL ) - cuddDeref( res ); - return ( res ); - -} /* end of Extra_SupportNeg */ - -/**Function******************************************************************** - - Synopsis [Returns 1 if the BDD is the BDD of elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddIsVar( DdNode * bFunc ) -{ - bFunc = Cudd_Regular( bFunc ); - if ( cuddIsConstant(bFunc) ) - return 0; - return cuddIsConstant( cuddT(bFunc) ) && cuddIsConstant( Cudd_Regular(cuddE(bFunc)) ); -} - -/**Function******************************************************************** - - Synopsis [Creates AND composed of the first nVars of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddCreateAnd( DdManager * dd, int nVars ) -{ - DdNode * bFunc, * bTemp; - int i; - bFunc = Cudd_ReadOne(dd); Cudd_Ref( bFunc ); - for ( i = 0; i < nVars; i++ ) - { - bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function******************************************************************** - - Synopsis [Creates OR composed of the first nVars of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddCreateOr( DdManager * dd, int nVars ) -{ - DdNode * bFunc, * bTemp; - int i; - bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); - for ( i = 0; i < nVars; i++ ) - { - bFunc = Cudd_bddOr( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function******************************************************************** - - Synopsis [Creates EXOR composed of the first nVars of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddCreateExor( DdManager * dd, int nVars ) -{ - DdNode * bFunc, * bTemp; - int i; - bFunc = Cudd_ReadLogicZero(dd); Cudd_Ref( bFunc ); - for ( i = 0; i < nVars; i++ ) - { - bFunc = Cudd_bddXor( dd, bTemp = bFunc, Cudd_bddIthVar(dd,i) ); Cudd_Ref( bFunc ); - Cudd_RecursiveDeref( dd, bTemp ); - } - Cudd_Deref( bFunc ); - return bFunc; -} - -/**Function******************************************************************** - - Synopsis [Computes the set of primes as a ZDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddPrimes( DdManager * dd, DdNode * F ) -{ - DdNode *res; - do { - dd->reordered = 0; - res = extraZddPrimes(dd, F); - if ( dd->reordered == 1 ) - printf("\nReordering in Extra_zddPrimes()\n"); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddPrimes */ - -/**Function******************************************************************** - - Synopsis [Permutes the variables of the array of BDDs.] - - Description [Given a permutation in array permut, creates a new BDD - with permuted variables. There should be an entry in array permut - for each variable in the manager. The i-th entry of permut holds the - index of the variable that is to substitute the i-th variable. - The DDs in the resulting array are already referenced.] - - SideEffects [None] - - SeeAlso [Cudd_addPermute Cudd_bddSwapVariables] - -******************************************************************************/ -void Extra_bddPermuteArray( DdManager * manager, DdNode ** bNodesIn, DdNode ** bNodesOut, int nNodes, int *permut ) -{ - DdHashTable *table; - int i, k; - do - { - manager->reordered = 0; - table = cuddHashTableInit( manager, 1, 2 ); - - /* permute the output functions one-by-one */ - for ( i = 0; i < nNodes; i++ ) - { - bNodesOut[i] = cuddBddPermuteRecur( manager, table, bNodesIn[i], permut ); - if ( bNodesOut[i] == NULL ) - { - /* deref the array of the already computed outputs */ - for ( k = 0; k < i; k++ ) - Cudd_RecursiveDeref( manager, bNodesOut[k] ); - break; - } - cuddRef( bNodesOut[i] ); - } - /* Dispose of local cache. */ - cuddHashTableQuit( table ); - } - while ( manager->reordered == 1 ); -} /* end of Extra_bddPermuteArray */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_bddMove().] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraBddMove( - DdManager * dd, /* the DD manager */ - DdNode * bF, - DdNode * bDist) -{ - DdNode * bRes; - - if ( Cudd_IsConstant(bF) ) - return bF; - - if ( bRes = cuddCacheLookup2(dd, extraBddMove, bF, bDist) ) - return bRes; - else - { - DdNode * bRes0, * bRes1; - DdNode * bF0, * bF1; - DdNode * bFR = Cudd_Regular(bF); - int VarNew; - - if ( Cudd_IsComplement(bDist) ) - VarNew = bFR->index - Cudd_Not(bDist)->index; - else - VarNew = bFR->index + bDist->index; - assert( VarNew < dd->size ); - - // cofactor the functions - if ( bFR != bF ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - bRes0 = extraBddMove( dd, bF0, bDist ); - if ( bRes0 == NULL ) - return NULL; - cuddRef( bRes0 ); - - bRes1 = extraBddMove( dd, bF1, bDist ); - if ( bRes1 == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - return NULL; - } - cuddRef( bRes1 ); - - /* only bRes0 and bRes1 are referenced at this point */ - bRes = cuddBddIteRecur( dd, dd->vars[VarNew], bRes1, bRes0 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bRes1 ); - return NULL; - } - cuddRef( bRes ); - Cudd_RecursiveDeref( dd, bRes0 ); - Cudd_RecursiveDeref( dd, bRes1 ); - - /* insert the result into cache */ - cuddCacheInsert2( dd, extraBddMove, bF, bDist, bRes ); - cuddDeref( bRes ); - return bRes; - } -} /* end of extraBddMove */ - - -/**Function******************************************************************** - - Synopsis [Finds three cofactors of the cover w.r.t. to the topmost variable.] - - Description [Finds three cofactors of the cover w.r.t. to the topmost variable. - Does not check the cover for being a constant. Assumes that ZDD variables encoding - positive and negative polarities are adjacent in the variable order. Is different - from cuddZddGetCofactors3() in that it does not compute the cofactors w.r.t. the - given variable but takes the cofactors with respent to the topmost variable. - This function is more efficient when used in recursive procedures because it does - not require referencing of the resulting cofactors (compare cuddZddProduct() - and extraZddPrimeProduct()).] - - SideEffects [None] - - SeeAlso [cuddZddGetCofactors3] - -******************************************************************************/ -void -extraDecomposeCover( - DdManager* dd, /* the manager */ - DdNode* zC, /* the cover */ - DdNode** zC0, /* the pointer to the negative var cofactor */ - DdNode** zC1, /* the pointer to the positive var cofactor */ - DdNode** zC2 ) /* the pointer to the cofactor without var */ -{ - if ( (zC->index & 1) == 0 ) - { /* the top variable is present in positive polarity and maybe in negative */ - - DdNode *Temp = cuddE( zC ); - *zC1 = cuddT( zC ); - if ( cuddIZ(dd,Temp->index) == cuddIZ(dd,zC->index) + 1 ) - { /* Temp is not a terminal node - * top var is present in negative polarity */ - *zC2 = cuddE( Temp ); - *zC0 = cuddT( Temp ); - } - else - { /* top var is not present in negative polarity */ - *zC2 = Temp; - *zC0 = dd->zero; - } - } - else - { /* the top variable is present only in negative */ - *zC1 = dd->zero; - *zC2 = cuddE( zC ); - *zC0 = cuddT( zC ); - } -} /* extraDecomposeCover */ - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Convert a BDD from a manager to another one.] - - Description [Convert a BDD from a manager to another one. Returns a - pointer to the BDD in the destination manager if successful; NULL - otherwise.] - - SideEffects [None] - - SeeAlso [Extra_TransferPermute] - -******************************************************************************/ -DdNode * extraTransferPermute( DdManager * ddS, DdManager * ddD, DdNode * f, int * Permute ) -{ - DdNode *res; - st_table *table = NULL; - st_generator *gen = NULL; - DdNode *key, *value; - - table = st_init_table( st_ptrcmp, st_ptrhash ); - if ( table == NULL ) - goto failure; - res = extraTransferPermuteRecur( ddS, ddD, f, table, Permute ); - if ( res != NULL ) - cuddRef( res ); - - /* Dereference all elements in the table and dispose of the table. - ** This must be done also if res is NULL to avoid leaks in case of - ** reordering. */ - gen = st_init_gen( table ); - if ( gen == NULL ) - goto failure; - while ( st_gen( gen, ( char ** ) &key, ( char ** ) &value ) ) - { - Cudd_RecursiveDeref( ddD, value ); - } - st_free_gen( gen ); - gen = NULL; - st_free_table( table ); - table = NULL; - - if ( res != NULL ) - cuddDeref( res ); - return ( res ); - - failure: - if ( table != NULL ) - st_free_table( table ); - if ( gen != NULL ) - st_free_gen( gen ); - return ( NULL ); - -} /* end of extraTransferPermute */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Extra_TransferPermute.] - - Description [Performs the recursive step of Extra_TransferPermute. - Returns a pointer to the result if successful; NULL otherwise.] - - SideEffects [None] - - SeeAlso [extraTransferPermute] - -******************************************************************************/ -static DdNode * -extraTransferPermuteRecur( - DdManager * ddS, - DdManager * ddD, - DdNode * f, - st_table * table, - int * Permute ) -{ - DdNode *ft, *fe, *t, *e, *var, *res; - DdNode *one, *zero; - int index; - int comple = 0; - - statLine( ddD ); - one = DD_ONE( ddD ); - comple = Cudd_IsComplement( f ); - - /* Trivial cases. */ - if ( Cudd_IsConstant( f ) ) - return ( Cudd_NotCond( one, comple ) ); - - - /* Make canonical to increase the utilization of the cache. */ - f = Cudd_NotCond( f, comple ); - /* Now f is a regular pointer to a non-constant node. */ - - /* Check the cache. */ - if ( st_lookup( table, ( char * ) f, ( char ** ) &res ) ) - return ( Cudd_NotCond( res, comple ) ); - - /* Recursive step. */ - if ( Permute ) - index = Permute[f->index]; - else - index = f->index; - - ft = cuddT( f ); - fe = cuddE( f ); - - t = extraTransferPermuteRecur( ddS, ddD, ft, table, Permute ); - if ( t == NULL ) - { - return ( NULL ); - } - cuddRef( t ); - - e = extraTransferPermuteRecur( ddS, ddD, fe, table, Permute ); - if ( e == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - return ( NULL ); - } - cuddRef( e ); - - zero = Cudd_Not(ddD->one); - var = cuddUniqueInter( ddD, index, one, zero ); - if ( var == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - res = cuddBddIteRecur( ddD, var, t, e ); - - if ( res == NULL ) - { - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - return ( NULL ); - } - cuddRef( res ); - Cudd_RecursiveDeref( ddD, t ); - Cudd_RecursiveDeref( ddD, e ); - - if ( st_add_direct( table, ( char * ) f, ( char * ) res ) == - ST_OUT_OF_MEM ) - { - Cudd_RecursiveDeref( ddD, res ); - return ( NULL ); - } - return ( Cudd_NotCond( res, comple ) ); - -} /* end of extraTransferPermuteRecur */ - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Cudd_Support.] - - Description [Performs the recursive step of Cudd_Support. Performs a - DFS from f. The support is accumulated in supp as a side effect. Uses - the LSB of the then pointer as visited flag.] - - SideEffects [None] - - SeeAlso [ddClearFlag] - -******************************************************************************/ -static void -ddSupportStep( - DdNode * f, - int * support) -{ - if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) { - return; - } - - support[f->index] = 1; - ddSupportStep(cuddT(f),support); - ddSupportStep(Cudd_Regular(cuddE(f)),support); - /* Mark as visited. */ - f->next = Cudd_Not(f->next); - return; - -} /* end of ddSupportStep */ - - -/**Function******************************************************************** - - Synopsis [Performs a DFS from f, clearing the LSB of the next - pointers.] - - Description [] - - SideEffects [None] - - SeeAlso [ddSupportStep ddDagInt] - -******************************************************************************/ -static void -ddClearFlag( - DdNode * f) -{ - if (!Cudd_IsComplement(f->next)) { - return; - } - /* Clear visited flag. */ - f->next = Cudd_Regular(f->next); - if (cuddIsConstant(f)) { - return; - } - ddClearFlag(cuddT(f)); - ddClearFlag(Cudd_Regular(cuddE(f))); - return; - -} /* end of ddClearFlag */ - - -/**Function******************************************************************** - - Synopsis [Composed three subcovers into one ZDD.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * -extraComposeCover( - DdManager* dd, /* the manager */ - DdNode* zC0, /* the pointer to the negative var cofactor */ - DdNode* zC1, /* the pointer to the positive var cofactor */ - DdNode* zC2, /* the pointer to the cofactor without var */ - int TopVar) /* the index of the positive ZDD var */ -{ - DdNode * zRes, * zTemp; - /* compose with-neg-var and without-var using the neg ZDD var */ - zTemp = cuddZddGetNode( dd, 2*TopVar + 1, zC0, zC2 ); - if ( zTemp == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zC0); - Cudd_RecursiveDerefZdd(dd, zC1); - Cudd_RecursiveDerefZdd(dd, zC2); - return NULL; - } - cuddRef( zTemp ); - cuddDeref( zC0 ); - cuddDeref( zC2 ); - - /* compose with-pos-var and previous result using the pos ZDD var */ - zRes = cuddZddGetNode( dd, 2*TopVar, zC1, zTemp ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd(dd, zC1); - Cudd_RecursiveDerefZdd(dd, zTemp); - return NULL; - } - cuddDeref( zC1 ); - cuddDeref( zTemp ); - return zRes; -} /* extraComposeCover */ - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of prime computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode* extraZddPrimes( DdManager *dd, DdNode* F ) -{ - DdNode *zRes; - - if ( F == Cudd_Not( dd->one ) ) - return dd->zero; - if ( F == dd->one ) - return dd->one; - - /* check cache */ - zRes = cuddCacheLookup1Zdd(dd, extraZddPrimes, F); - if (zRes) - return(zRes); - { - /* temporary variables */ - DdNode *bF01, *zP0, *zP1; - /* three components of the prime set */ - DdNode *zResE, *zResP, *zResN; - int fIsComp = Cudd_IsComplement( F ); - - /* find cofactors of F */ - DdNode * bF0 = Cudd_NotCond( Cudd_E( F ), fIsComp ); - DdNode * bF1 = Cudd_NotCond( Cudd_T( F ), fIsComp ); - - /* find the intersection of cofactors */ - bF01 = cuddBddAndRecur( dd, bF0, bF1 ); - if ( bF01 == NULL ) return NULL; - cuddRef( bF01 ); - - /* solve the problems for cofactors */ - zP0 = extraZddPrimes( dd, bF0 ); - if ( zP0 == NULL ) - { - Cudd_RecursiveDeref( dd, bF01 ); - return NULL; - } - cuddRef( zP0 ); - - zP1 = extraZddPrimes( dd, bF1 ); - if ( zP1 == NULL ) - { - Cudd_RecursiveDeref( dd, bF01 ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - return NULL; - } - cuddRef( zP1 ); - - /* check for local unateness */ - if ( bF01 == bF0 ) /* unate increasing */ - { - /* intersection is useless */ - cuddDeref( bF01 ); - /* the primes of intersection are the primes of F0 */ - zResE = zP0; - /* there are no primes with negative var */ - zResN = dd->zero; - cuddRef( zResN ); - /* primes with positive var are primes of F1 that are not primes of F01 */ - zResP = cuddZddDiff( dd, zP1, zP0 ); - if ( zResP == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zResN ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResP ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - } - else if ( bF01 == bF1 ) /* unate decreasing */ - { - /* intersection is useless */ - cuddDeref( bF01 ); - /* the primes of intersection are the primes of F1 */ - zResE = zP1; - /* there are no primes with positive var */ - zResP = dd->zero; - cuddRef( zResP ); - /* primes with negative var are primes of F0 that are not primes of F01 */ - zResN = cuddZddDiff( dd, zP0, zP1 ); - if ( zResN == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zResP ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - return NULL; - } - cuddRef( zResN ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - } - else /* not unate */ - { - /* primes without the top var are primes of F10 */ - zResE = extraZddPrimes( dd, bF01 ); - if ( zResE == NULL ) - { - Cudd_RecursiveDerefZdd( dd, bF01 ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResE ); - Cudd_RecursiveDeref( dd, bF01 ); - - /* primes with the negative top var are those of P0 that are not in F10 */ - zResN = cuddZddDiff( dd, zP0, zResE ); - if ( zResN == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResN ); - Cudd_RecursiveDerefZdd( dd, zP0 ); - - /* primes with the positive top var are those of P1 that are not in F10 */ - zResP = cuddZddDiff( dd, zP1, zResE ); - if ( zResP == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zResE ); - Cudd_RecursiveDerefZdd( dd, zResN ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - return NULL; - } - cuddRef( zResP ); - Cudd_RecursiveDerefZdd( dd, zP1 ); - } - - zRes = extraComposeCover( dd, zResN, zResP, zResE, Cudd_Regular(F)->index ); - if ( zRes == NULL ) return NULL; - - /* insert the result into cache */ - cuddCacheInsert1(dd, extraZddPrimes, F, zRes); - return zRes; - } -} /* end of extraZddPrimes */ - -/**Function******************************************************************** - - Synopsis [Implements the recursive step of Cudd_bddPermute.] - - Description [ Recursively puts the BDD in the order given in the array permut. - Checks for trivial cases to terminate recursion, then splits on the - children of this node. Once the solutions for the children are - obtained, it puts into the current position the node from the rest of - the BDD that should be here. Then returns this BDD. - The key here is that the node being visited is NOT put in its proper - place by this instance, but rather is switched when its proper position - is reached in the recursion tree.

              - The DdNode * that is returned is the same BDD as passed in as node, - but in the new order.] - - SideEffects [None] - - SeeAlso [Cudd_bddPermute cuddAddPermuteRecur] - -******************************************************************************/ -static DdNode * -cuddBddPermuteRecur( DdManager * manager /* DD manager */ , - DdHashTable * table /* computed table */ , - DdNode * node /* BDD to be reordered */ , - int *permut /* permutation array */ ) -{ - DdNode *N, *T, *E; - DdNode *res; - int index; - - statLine( manager ); - N = Cudd_Regular( node ); - - /* Check for terminal case of constant node. */ - if ( cuddIsConstant( N ) ) - { - return ( node ); - } - - /* If problem already solved, look up answer and return. */ - if ( N->ref != 1 && ( res = cuddHashTableLookup1( table, N ) ) != NULL ) - { -#ifdef DD_DEBUG - bddPermuteRecurHits++; -#endif - return ( Cudd_NotCond( res, N != node ) ); - } - - /* Split and recur on children of this node. */ - T = cuddBddPermuteRecur( manager, table, cuddT( N ), permut ); - if ( T == NULL ) - return ( NULL ); - cuddRef( T ); - E = cuddBddPermuteRecur( manager, table, cuddE( N ), permut ); - if ( E == NULL ) - { - Cudd_IterDerefBdd( manager, T ); - return ( NULL ); - } - cuddRef( E ); - - /* Move variable that should be in this position to this position - ** by retrieving the single var BDD for that variable, and calling - ** cuddBddIteRecur with the T and E we just created. - */ - index = permut[N->index]; - res = cuddBddIteRecur( manager, manager->vars[index], T, E ); - if ( res == NULL ) - { - Cudd_IterDerefBdd( manager, T ); - Cudd_IterDerefBdd( manager, E ); - return ( NULL ); - } - cuddRef( res ); - Cudd_IterDerefBdd( manager, T ); - Cudd_IterDerefBdd( manager, E ); - - /* Do not keep the result if the reference count is only 1, since - ** it will not be visited again. - */ - if ( N->ref != 1 ) - { - ptrint fanout = ( ptrint ) N->ref; - cuddSatDec( fanout ); - if ( !cuddHashTableInsert1( table, N, res, fanout ) ) - { - Cudd_IterDerefBdd( manager, res ); - return ( NULL ); - } - } - cuddDeref( res ); - return ( Cudd_NotCond( res, N != node ) ); - -} /* end of cuddBddPermuteRecur */ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/extra/extraBddSymm.c b/src/misc/extra/extraBddSymm.c deleted file mode 100644 index 358402b0..00000000 --- a/src/misc/extra/extraBddSymm.c +++ /dev/null @@ -1,1469 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddSymm.c] - - PackageName [extra] - - Synopsis [Efficient methods to compute the information about - symmetric variables using the algorithm presented in the paper: - A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. - Transactions on CAD, Nov. 2003.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - September 1, 2003.] - - Revision [$Id: extraBddSymm.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "extra.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -#define DD_GET_SYMM_VARS_TAG 0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes the classical symmetry information for the function.] - - Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.] - - SideEffects [If the ZDD variables are not derived from BDD variables with - multiplicity 2, this function may derive them in a wrong way.] - - SeeAlso [] - -******************************************************************************/ -Extra_SymmInfo_t * Extra_SymmPairsCompute( - DdManager * dd, /* the manager */ - DdNode * bFunc) /* the function whose symmetries are computed */ -{ - DdNode * bSupp; - DdNode * zRes; - Extra_SymmInfo_t * p; - - bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); - zRes = Extra_zddSymmPairsCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); - - p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp ); - - Cudd_RecursiveDeref( dd, bSupp ); - Cudd_RecursiveDerefZdd( dd, zRes ); - - return p; - -} /* end of Extra_SymmPairsCompute */ - - -/**Function******************************************************************** - - Synopsis [Computes the classical symmetry information as a ZDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddSymmPairsCompute( - DdManager * dd, /* the DD manager */ - DdNode * bF, - DdNode * bVars) -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraZddSymmPairsCompute( dd, bF, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddSymmPairsCompute */ - -/**Function******************************************************************** - - Synopsis [Returns a singleton-set ZDD containing all variables that are symmetric with the given one.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddGetSymmetricVars( - DdManager * dd, /* the DD manager */ - DdNode * bF, /* the first function - originally, the positive cofactor */ - DdNode * bG, /* the second fucntion - originally, the negative cofactor */ - DdNode * bVars) /* the set of variables, on which F and G depend */ -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraZddGetSymmetricVars( dd, bF, bG, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddGetSymmetricVars */ - - -/**Function******************************************************************** - - Synopsis [Converts a set of variables into a set of singleton subsets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddGetSingletons( - DdManager * dd, /* the DD manager */ - DdNode * bVars) /* the set of variables */ -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraZddGetSingletons( dd, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddGetSingletons */ - -/**Function******************************************************************** - - Synopsis [Filters the set of variables using the support of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_bddReduceVarSet( - DdManager * dd, /* the DD manager */ - DdNode * bVars, /* the set of variables to be reduced */ - DdNode * bF) /* the function whose support is used for reduction */ -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraBddReduceVarSet( dd, bVars, bF ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_bddReduceVarSet */ - - -/**Function******************************************************************** - - Synopsis [Allocates symmetry information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_SymmInfo_t * Extra_SymmPairsAllocate( int nVars ) -{ - int i; - Extra_SymmInfo_t * p; - - // allocate and clean the storage for symmetry info - p = ALLOC( Extra_SymmInfo_t, 1 ); - memset( p, 0, sizeof(Extra_SymmInfo_t) ); - p->nVars = nVars; - p->pVars = ALLOC( int, nVars ); - p->pSymms = ALLOC( char *, nVars ); - p->pSymms[0] = ALLOC( char , nVars * nVars ); - memset( p->pSymms[0], 0, nVars * nVars * sizeof(char) ); - - for ( i = 1; i < nVars; i++ ) - p->pSymms[i] = p->pSymms[i-1] + nVars; - - return p; -} /* end of Extra_SymmPairsAllocate */ - -/**Function******************************************************************** - - Synopsis [Deallocates symmetry information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Extra_SymmPairsDissolve( Extra_SymmInfo_t * p ) -{ - free( p->pVars ); - free( p->pSymms[0] ); - free( p->pSymms ); - free( p ); -} /* end of Extra_SymmPairsDissolve */ - -/**Function******************************************************************** - - Synopsis [Allocates symmetry information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Extra_SymmPairsPrint( Extra_SymmInfo_t * p ) -{ - int i, k; - printf( "\n" ); - for ( i = 0; i < p->nVars; i++ ) - { - for ( k = 0; k <= i; k++ ) - printf( " " ); - for ( k = i+1; k < p->nVars; k++ ) - if ( p->pSymms[i][k] ) - printf( "1" ); - else - printf( "." ); - printf( "\n" ); - } -} /* end of Extra_SymmPairsPrint */ - - -/**Function******************************************************************** - - Synopsis [Creates the symmetry information structure from ZDD.] - - Description [ZDD representation of symmetries is the set of cubes, each - of which has two variables in the positive polarity. These variables correspond - to the symmetric variable pair.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp ) -{ - int i; - int nSuppSize; - Extra_SymmInfo_t * p; - int * pMapVars2Nums; - DdNode * bTemp; - DdNode * zSet, * zCube, * zTemp; - int iVar1, iVar2; - - nSuppSize = Extra_bddSuppSize( dd, bSupp ); - - // allocate and clean the storage for symmetry info - p = Extra_SymmPairsAllocate( nSuppSize ); - - // allocate the storage for the temporary map - pMapVars2Nums = ALLOC( int, dd->size ); - memset( pMapVars2Nums, 0, dd->size * sizeof(int) ); - - // assign the variables - p->nVarsMax = dd->size; -// p->nNodes = Cudd_DagSize( zPairs ); - p->nNodes = 0; - for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) - { - p->pVars[i] = bTemp->index; - pMapVars2Nums[bTemp->index] = i; - } - - // write the symmetry info into the structure - zSet = zPairs; Cudd_Ref( zSet ); - while ( zSet != z0 ) - { - // get the next cube - zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube ); - - // add these two variables to the data structure - assert( cuddT( cuddT(zCube) ) == z1 ); - iVar1 = zCube->index/2; - iVar2 = cuddT(zCube)->index/2; - if ( pMapVars2Nums[iVar1] < pMapVars2Nums[iVar2] ) - p->pSymms[ pMapVars2Nums[iVar1] ][ pMapVars2Nums[iVar2] ] = 1; - else - p->pSymms[ pMapVars2Nums[iVar2] ][ pMapVars2Nums[iVar1] ] = 1; - // count the symmetric pairs - p->nSymms ++; - - // update the cuver and deref the cube - zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zCube ); - - } // for each cube - Cudd_RecursiveDerefZdd( dd, zSet ); - - FREE( pMapVars2Nums ); - return p; - -} /* end of Extra_SymmPairsCreateFromZdd */ - - -/**Function******************************************************************** - - Synopsis [Checks the possibility of two variables being symmetric.] - - Description [Returns 0 if vars are not symmetric. Return 1 if vars can be symmetric.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddCheckVarsSymmetric( - DdManager * dd, /* the DD manager */ - DdNode * bF, - int iVar1, - int iVar2) -{ - DdNode * bVars; - int Res; - -// return 1; - - assert( iVar1 != iVar2 ); - assert( iVar1 < dd->size ); - assert( iVar2 < dd->size ); - - bVars = Cudd_bddAnd( dd, dd->vars[iVar1], dd->vars[iVar2] ); Cudd_Ref( bVars ); - - Res = (int)( extraBddCheckVarsSymmetric( dd, bF, bVars ) == b1 ); - - Cudd_RecursiveDeref( dd, bVars ); - - return Res; -} /* end of Extra_bddCheckVarsSymmetric */ - - -/**Function******************************************************************** - - Synopsis [Computes the classical symmetry information for the function.] - - Description [Uses the naive way of comparing cofactors.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc ) -{ - DdNode * bSupp, * bTemp; - int nSuppSize; - Extra_SymmInfo_t * p; - int i, k; - - // compute the support - bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); - nSuppSize = Extra_bddSuppSize( dd, bSupp ); -//printf( "Support = %d. ", nSuppSize ); -//Extra_bddPrint( dd, bSupp ); -//printf( "%d ", nSuppSize ); - - // allocate the storage for symmetry info - p = Extra_SymmPairsAllocate( nSuppSize ); - - // assign the variables - p->nVarsMax = dd->size; - for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) - p->pVars[i] = bTemp->index; - - // go through the candidate pairs and check using Idea1 - for ( i = 0; i < nSuppSize; i++ ) - for ( k = i+1; k < nSuppSize; k++ ) - { - p->pSymms[k][i] = p->pSymms[i][k] = Extra_bddCheckVarsSymmetricNaive( dd, bFunc, p->pVars[i], p->pVars[k] ); - if ( p->pSymms[i][k] ) - p->nSymms++; - } - - Cudd_RecursiveDeref( dd, bSupp ); - return p; - -} /* end of Extra_SymmPairsComputeNaive */ - -/**Function******************************************************************** - - Synopsis [Checks if the two variables are symmetric.] - - Description [Returns 0 if vars are not symmetric. Return 1 if vars are symmetric.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddCheckVarsSymmetricNaive( - DdManager * dd, /* the DD manager */ - DdNode * bF, - int iVar1, - int iVar2) -{ - DdNode * bCube1, * bCube2; - DdNode * bCof01, * bCof10; - int Res; - - assert( iVar1 != iVar2 ); - assert( iVar1 < dd->size ); - assert( iVar2 < dd->size ); - - bCube1 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar1] ), dd->vars[iVar2] ); Cudd_Ref( bCube1 ); - bCube2 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar2] ), dd->vars[iVar1] ); Cudd_Ref( bCube2 ); - - bCof01 = Cudd_Cofactor( dd, bF, bCube1 ); Cudd_Ref( bCof01 ); - bCof10 = Cudd_Cofactor( dd, bF, bCube2 ); Cudd_Ref( bCof10 ); - - Res = (int)( bCof10 == bCof01 ); - - Cudd_RecursiveDeref( dd, bCof01 ); - Cudd_RecursiveDeref( dd, bCof10 ); - Cudd_RecursiveDeref( dd, bCube1 ); - Cudd_RecursiveDeref( dd, bCube2 ); - - return Res; -} /* end of Extra_bddCheckVarsSymmetricNaive */ - - -/**Function******************************************************************** - - Synopsis [Builds ZDD representing the set of fixed-size variable tuples.] - - Description [Creates ZDD of all combinations of variables in Support that - is represented by a BDD.] - - SideEffects [New ZDD variables are created if indices of the variables - present in the combination are larger than the currently - allocated number of ZDD variables.] - - SeeAlso [] - -******************************************************************************/ -DdNode* Extra_zddTuplesFromBdd( - DdManager * dd, /* the DD manager */ - int K, /* the number of variables in tuples */ - DdNode * bVarsN) /* the set of all variables represented as a BDD */ -{ - DdNode *zRes; - int autoDynZ; - - autoDynZ = dd->autoDynZ; - dd->autoDynZ = 0; - - do { - /* transform the numeric arguments (K) into a DdNode* argument; - * this allows us to use the standard internal CUDD cache */ - DdNode *bVarSet = bVarsN, *bVarsK = bVarsN; - int nVars = 0, i; - - /* determine the number of variables in VarSet */ - while ( bVarSet != b1 ) - { - nVars++; - /* make sure that the VarSet is a cube */ - if ( cuddE( bVarSet ) != b0 ) - return NULL; - bVarSet = cuddT( bVarSet ); - } - /* make sure that the number of variables in VarSet is less or equal - that the number of variables that should be present in the tuples - */ - if ( K > nVars ) - return NULL; - - /* the second argument in the recursive call stannds for ; - /* reate the first argument, which stands for - * as when we are talking about the tuple of out of */ - for ( i = 0; i < nVars-K; i++ ) - bVarsK = cuddT( bVarsK ); - - dd->reordered = 0; - zRes = extraZddTuplesFromBdd(dd, bVarsK, bVarsN ); - - } while (dd->reordered == 1); - dd->autoDynZ = autoDynZ; - return zRes; - -} /* end of Extra_zddTuplesFromBdd */ - -/**Function******************************************************************** - - Synopsis [Selects one subset from the set of subsets represented by a ZDD.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode* Extra_zddSelectOneSubset( - DdManager * dd, /* the DD manager */ - DdNode * zS) /* the ZDD */ -{ - DdNode *res; - do { - dd->reordered = 0; - res = extraZddSelectOneSubset(dd, zS); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddSelectOneSubset */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_SymmPairsCompute.] - - Description [Returns the set of symmetric variable pairs represented as a set - of two-literal ZDD cubes. Both variables always appear in the positive polarity - in the cubes. This function works without building new BDD nodes. Some relatively - small number of ZDD nodes may be built to ensure proper bookkeeping of the - symmetry information.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * -extraZddSymmPairsCompute( - DdManager * dd, /* the manager */ - DdNode * bFunc, /* the function whose symmetries are computed */ - DdNode * bVars ) /* the set of variables on which this function depends */ -{ - DdNode * zRes; - DdNode * bFR = Cudd_Regular(bFunc); - - if ( cuddIsConstant(bFR) ) - { - int nVars, i; - - // determine how many vars are in the bVars - nVars = Extra_bddSuppSize( dd, bVars ); - if ( nVars < 2 ) - return z0; - else - { - DdNode * bVarsK; - - // create the BDD bVarsK corresponding to K = 2; - bVarsK = bVars; - for ( i = 0; i < nVars-2; i++ ) - bVarsK = cuddT( bVarsK ); - return extraZddTuplesFromBdd( dd, bVarsK, bVars ); - } - } - assert( bVars != b1 ); - - if ( zRes = cuddCacheLookup2Zdd(dd, extraZddSymmPairsCompute, bFunc, bVars) ) - return zRes; - else - { - DdNode * zRes0, * zRes1; - DdNode * zTemp, * zPlus, * zSymmVars; - DdNode * bF0, * bF1; - DdNode * bVarsNew; - int nVarsExtra; - int LevelF; - - // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV - // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F - // count how many extra vars are there in bVars - nVarsExtra = 0; - LevelF = dd->perm[bFR->index]; - for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) - nVarsExtra++; - // the indexes (level) of variables should be synchronized now - assert( bFR->index == bVarsNew->index ); - - // cofactor the function - if ( bFR != bFunc ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - // solve subproblems - zRes0 = extraZddSymmPairsCompute( dd, bF0, cuddT(bVarsNew) ); - if ( zRes0 == NULL ) - return NULL; - cuddRef( zRes0 ); - - // if there is no symmetries in the negative cofactor - // there is no need to test the positive cofactor - if ( zRes0 == z0 ) - zRes = zRes0; // zRes takes reference - else - { - zRes1 = extraZddSymmPairsCompute( dd, bF1, cuddT(bVarsNew) ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - return NULL; - } - cuddRef( zRes1 ); - - // only those variables are pair-wise symmetric - // that are pair-wise symmetric in both cofactors - // therefore, intersect the solutions - zRes = cuddZddIntersect( dd, zRes0, zRes1 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - } - - // consider the current top-most variable and find all the vars - // that are pairwise symmetric with it - // these variables are returned as a set of ZDD singletons - zSymmVars = extraZddGetSymmetricVars( dd, bF1, bF0, cuddT(bVarsNew) ); - if ( zSymmVars == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zSymmVars ); - - // attach the topmost variable to the set, to get the variable pairs - // use the positive polarity ZDD variable for the purpose - - // there is no need to do so, if zSymmVars is empty - if ( zSymmVars == z0 ) - Cudd_RecursiveDerefZdd( dd, zSymmVars ); - else - { - zPlus = cuddZddGetNode( dd, 2*bFR->index, zSymmVars, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - Cudd_RecursiveDerefZdd( dd, zSymmVars ); - return NULL; - } - cuddRef( zPlus ); - cuddDeref( zSymmVars ); - - // add these variable pairs to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - - // only zRes is referenced at this point - - // if we skipped some variables, these variables cannot be symmetric with - // any variables that are currently in the support of bF, but they can be - // symmetric with the variables that are in bVars but not in the support of bF - if ( nVarsExtra ) - { - // it is possible to improve this step: - // (1) there is no need to enter here, if nVarsExtra < 2 - - // create the set of topmost nVarsExtra in bVars - DdNode * bVarsExtra; - int nVars; - - // remove from bVars all the variable that are in the support of bFunc - bVarsExtra = extraBddReduceVarSet( dd, bVars, bFunc ); - if ( bVarsExtra == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( bVarsExtra ); - - // determine how many vars are in the bVarsExtra - nVars = Extra_bddSuppSize( dd, bVarsExtra ); - if ( nVars < 2 ) - { - Cudd_RecursiveDeref( dd, bVarsExtra ); - } - else - { - int i; - DdNode * bVarsK; - - // create the BDD bVarsK corresponding to K = 2; - bVarsK = bVarsExtra; - for ( i = 0; i < nVars-2; i++ ) - bVarsK = cuddT( bVarsK ); - - // create the 2 variable tuples - zPlus = extraZddTuplesFromBdd( dd, bVarsK, bVarsExtra ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDeref( dd, bVarsExtra ); - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - Cudd_RecursiveDeref( dd, bVarsExtra ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - } - cuddDeref( zRes ); - - - /* insert the result into cache */ - cuddCacheInsert2(dd, extraZddSymmPairsCompute, bFunc, bVars, zRes); - return zRes; - } -} /* end of extraZddSymmPairsCompute */ - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_zddGetSymmetricVars.] - - Description [Returns the set of ZDD singletons, containing those positive - ZDD variables that correspond to BDD variables x, for which it is true - that bF(x=0) == bG(x=1).] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraZddGetSymmetricVars( - DdManager * dd, /* the DD manager */ - DdNode * bF, /* the first function - originally, the positive cofactor */ - DdNode * bG, /* the second function - originally, the negative cofactor */ - DdNode * bVars) /* the set of variables, on which F and G depend */ -{ - DdNode * zRes; - DdNode * bFR = Cudd_Regular(bF); - DdNode * bGR = Cudd_Regular(bG); - - if ( cuddIsConstant(bFR) && cuddIsConstant(bGR) ) - { - if ( bF == bG ) - return extraZddGetSingletons( dd, bVars ); - else - return z0; - } - assert( bVars != b1 ); - - if ( zRes = cuddCacheLookupZdd(dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars) ) - return zRes; - else - { - DdNode * zRes0, * zRes1; - DdNode * zPlus, * zTemp; - DdNode * bF0, * bF1; - DdNode * bG0, * bG1; - DdNode * bVarsNew; - - int LevelF = cuddI(dd,bFR->index); - int LevelG = cuddI(dd,bGR->index); - int LevelFG; - - if ( LevelF < LevelG ) - LevelFG = LevelF; - else - LevelFG = LevelG; - - // at least one of the arguments is not a constant - assert( LevelFG < dd->size ); - - // every variable in bF and bG should be also in bVars, therefore LevelFG cannot be above LevelV - // if LevelFG is below LevelV, scroll through the vars in bVars to the same level as LevelFG - for ( bVarsNew = bVars; LevelFG > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ); - assert( LevelFG == dd->perm[bVarsNew->index] ); - - // cofactor the functions - if ( LevelF == LevelFG ) - { - if ( bFR != bF ) // bF is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - } - else - bF0 = bF1 = bF; - - if ( LevelG == LevelFG ) - { - if ( bGR != bG ) // bG is complemented - { - bG0 = Cudd_Not( cuddE(bGR) ); - bG1 = Cudd_Not( cuddT(bGR) ); - } - else - { - bG0 = cuddE(bGR); - bG1 = cuddT(bGR); - } - } - else - bG0 = bG1 = bG; - - // solve subproblems - zRes0 = extraZddGetSymmetricVars( dd, bF0, bG0, cuddT(bVarsNew) ); - if ( zRes0 == NULL ) - return NULL; - cuddRef( zRes0 ); - - // if there is not symmetries in the negative cofactor - // there is no need to test the positive cofactor - if ( zRes0 == z0 ) - zRes = zRes0; // zRes takes reference - else - { - zRes1 = extraZddGetSymmetricVars( dd, bF1, bG1, cuddT(bVarsNew) ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - return NULL; - } - cuddRef( zRes1 ); - - // only those variables should belong to the resulting set - // for which the property is true for both cofactors - zRes = cuddZddIntersect( dd, zRes0, zRes1 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - } - - // add one more singleton if the property is true for this variable - if ( bF0 == bG1 ) - { - zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these variable pairs to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - - if ( bF == bG && bVars != bVarsNew ) - { - // if the functions are equal, so are their cofactors - // add those variables from V that are above F and G - - DdNode * bVarsExtra; - - assert( LevelFG > dd->perm[bVars->index] ); - - // create the BDD of the extra variables - bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsNew ); - if ( bVarsExtra == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( bVarsExtra ); - - zPlus = extraZddGetSingletons( dd, bVarsExtra ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDeref( dd, bVarsExtra ); - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - Cudd_RecursiveDeref( dd, bVarsExtra ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - cuddDeref( zRes ); - - cuddCacheInsert( dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars, zRes ); - return zRes; - } -} /* end of extraZddGetSymmetricVars */ - - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_zddGetSingletons.] - - Description [Returns the set of ZDD singletons, containing those positive - polarity ZDD variables that correspond to the BDD variables in bVars.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraZddGetSingletons( - DdManager * dd, /* the DD manager */ - DdNode * bVars) /* the set of variables */ -{ - DdNode * zRes; - - if ( bVars == b1 ) -// if ( bVars == b0 ) // bug fixed by Jin Zhang, Jan 23, 2004 - return z1; - - if ( zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars) ) - return zRes; - else - { - DdNode * zTemp, * zPlus; - - // solve subproblem - zRes = extraZddGetSingletons( dd, cuddT(bVars) ); - if ( zRes == NULL ) - return NULL; - cuddRef( zRes ); - - zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - cuddDeref( zRes ); - - cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes ); - return zRes; - } -} /* end of extraZddGetSingletons */ - - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_bddReduceVarSet.] - - Description [Returns the set of all variables in the given set that are not in the - support of the given function.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraBddReduceVarSet( - DdManager * dd, /* the DD manager */ - DdNode * bVars, /* the set of variables to be reduced */ - DdNode * bF) /* the function whose support is used for reduction */ -{ - DdNode * bRes; - DdNode * bFR = Cudd_Regular(bF); - - if ( cuddIsConstant(bFR) || bVars == b1 ) - return bVars; - - if ( bRes = cuddCacheLookup2(dd, extraBddReduceVarSet, bVars, bF) ) - return bRes; - else - { - DdNode * bF0, * bF1; - DdNode * bVarsThis, * bVarsLower, * bTemp; - int LevelF; - - // if LevelF is below LevelV, scroll through the vars in bVars - LevelF = dd->perm[bFR->index]; - for ( bVarsThis = bVars; LevelF > cuddI(dd,bVarsThis->index); bVarsThis = cuddT(bVarsThis) ); - // scroll also through the current var, because it should be not be added - if ( LevelF == cuddI(dd,bVarsThis->index) ) - bVarsLower = cuddT(bVarsThis); - else - bVarsLower = bVarsThis; - - // cofactor the function - if ( bFR != bF ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - // solve subproblems - bRes = extraBddReduceVarSet( dd, bVarsLower, bF0 ); - if ( bRes == NULL ) - return NULL; - cuddRef( bRes ); - - bRes = extraBddReduceVarSet( dd, bTemp = bRes, bF1 ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - return NULL; - } - cuddRef( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - - // the current var should not be added - // add the skipped vars - if ( bVarsThis != bVars ) - { - DdNode * bVarsExtra; - - // extract the skipped variables - bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsThis ); - if ( bVarsExtra == NULL ) - { - Cudd_RecursiveDeref( dd, bRes ); - return NULL; - } - cuddRef( bVarsExtra ); - - // add these variables - bRes = cuddBddAndRecur( dd, bTemp = bRes, bVarsExtra ); - if ( bRes == NULL ) - { - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bVarsExtra ); - return NULL; - } - cuddRef( bRes ); - Cudd_RecursiveDeref( dd, bTemp ); - Cudd_RecursiveDeref( dd, bVarsExtra ); - } - cuddDeref( bRes ); - - cuddCacheInsert2( dd, extraBddReduceVarSet, bVars, bF, bRes ); - return bRes; - } -} /* end of extraBddReduceVarSet */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Extra_bddCheckVarsSymmetric().] - - Description [Returns b0 if the variables are not symmetric. Returns b1 if the - variables can be symmetric. The variables are represented in the form of a - two-variable cube. In case the cube contains one variable (below Var1 level), - the cube's pointer is complemented if the variable Var1 occurred on the - current path; otherwise, the cube's pointer is regular. Uses additional - complemented bit (Hash_Not) to mark the result if in the BDD rooted that this - node there is a branch passing though the node labeled with Var2.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraBddCheckVarsSymmetric( - DdManager * dd, /* the DD manager */ - DdNode * bF, - DdNode * bVars) -{ - DdNode * bRes; - - if ( bF == b0 ) - return b1; - - assert( bVars != b1 ); - - if ( bRes = cuddCacheLookup2(dd, extraBddCheckVarsSymmetric, bF, bVars) ) - return bRes; - else - { - DdNode * bRes0, * bRes1; - DdNode * bF0, * bF1; - DdNode * bFR = Cudd_Regular(bF); - int LevelF = cuddI(dd,bFR->index); - - DdNode * bVarsR = Cudd_Regular(bVars); - int fVar1Pres; - int iLev1; - int iLev2; - - if ( bVarsR != bVars ) // cube's pointer is complemented - { - assert( cuddT(bVarsR) == b1 ); - fVar1Pres = 1; // the first var is present on the path - iLev1 = -1; // we are already below the first var level - iLev2 = dd->perm[bVarsR->index]; // the level of the second var - } - else // cube's pointer is NOT complemented - { - fVar1Pres = 0; // the first var is absent on the path - if ( cuddT(bVars) == b1 ) - { - iLev1 = -1; // we are already below the first var level - iLev2 = dd->perm[bVars->index]; // the level of the second var - } - else - { - assert( cuddT(cuddT(bVars)) == b1 ); - iLev1 = dd->perm[bVars->index]; // the level of the first var - iLev2 = dd->perm[cuddT(bVars)->index]; // the level of the second var - } - } - - // cofactor the function - // the cofactors are needed only if we are above the second level - if ( LevelF < iLev2 ) - { - if ( bFR != bF ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - } - else - bF0 = bF1 = NULL; - - // consider five cases: - // (1) F is above iLev1 - // (2) F is on the level iLev1 - // (3) F is between iLev1 and iLev2 - // (4) F is on the level iLev2 - // (5) F is below iLev2 - - // (1) F is above iLev1 - if ( LevelF < iLev1 ) - { - // the returned result cannot have the hash attribute - // because we still did not reach the level of Var1; - // the attribute never travels above the level of Var1 - bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); -// assert( !Hash_IsComplement( bRes0 ) ); - assert( bRes0 != z0 ); - if ( bRes0 == b0 ) - bRes = b0; - else - bRes = extraBddCheckVarsSymmetric( dd, bF1, bVars ); -// assert( !Hash_IsComplement( bRes ) ); - assert( bRes != z0 ); - } - // (2) F is on the level iLev1 - else if ( LevelF == iLev1 ) - { - bRes0 = extraBddCheckVarsSymmetric( dd, bF0, Cudd_Not( cuddT(bVars) ) ); - if ( bRes0 == b0 ) - bRes = b0; - else - { - bRes1 = extraBddCheckVarsSymmetric( dd, bF1, Cudd_Not( cuddT(bVars) ) ); - if ( bRes1 == b0 ) - bRes = b0; - else - { -// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) - if ( bRes0 == z0 || bRes1 == z0 ) - bRes = b1; - else - bRes = b0; - } - } - } - // (3) F is between iLev1 and iLev2 - else if ( LevelF < iLev2 ) - { - bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); - if ( bRes0 == b0 ) - bRes = b0; - else - { - bRes1 = extraBddCheckVarsSymmetric( dd, bF1, bVars ); - if ( bRes1 == b0 ) - bRes = b0; - else - { -// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) -// bRes = Hash_Not( b1 ); - if ( bRes0 == z0 || bRes1 == z0 ) - bRes = z0; - else - bRes = b1; - } - } - } - // (4) F is on the level iLev2 - else if ( LevelF == iLev2 ) - { - // this is the only place where the hash attribute (Hash_Not) can be added - // to the result; it can be added only if the path came through the node - // lebeled with Var1; therefore, the hash attribute cannot be returned - // to the caller function - if ( fVar1Pres ) -// bRes = Hash_Not( b1 ); - bRes = z0; - else - bRes = b0; - } - // (5) F is below iLev2 - else // if ( LevelF > iLev2 ) - { - // it is possible that the path goes through the node labeled by Var1 - // and still everything is okay; we do not label with Hash_Not here - // because the path does not go through node labeled by Var2 - bRes = b1; - } - - cuddCacheInsert2(dd, extraBddCheckVarsSymmetric, bF, bVars, bRes); - return bRes; - } -} /* end of extraBddCheckVarsSymmetric */ - -/**Function******************************************************************** - - Synopsis [Performs the reordering-sensitive step of Extra_zddTupleFromBdd().] - - Description [Generates in a bottom-up fashion ZDD for all combinations - composed of k variables out of variables belonging to Support.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode* extraZddTuplesFromBdd( - DdManager * dd, /* the DD manager */ - DdNode * bVarsK, /* the number of variables in tuples */ - DdNode * bVarsN) /* the set of all variables */ -{ - DdNode *zRes, *zRes0, *zRes1; - statLine(dd); - - /* terminal cases */ -/* if ( k < 0 || k > n ) - * return dd->zero; - * if ( n == 0 ) - * return dd->one; - */ - if ( cuddI( dd, bVarsK->index ) < cuddI( dd, bVarsN->index ) ) - return z0; - if ( bVarsN == b1 ) - return z1; - - /* check cache */ - zRes = cuddCacheLookup2Zdd(dd, extraZddTuplesFromBdd, bVarsK, bVarsN); - if (zRes) - return(zRes); - - /* ZDD in which this variable is 0 */ -/* zRes0 = extraZddTuplesFromBdd( dd, k, n-1 ); */ - zRes0 = extraZddTuplesFromBdd( dd, bVarsK, cuddT(bVarsN) ); - if ( zRes0 == NULL ) - return NULL; - cuddRef( zRes0 ); - - /* ZDD in which this variable is 1 */ -/* zRes1 = extraZddTuplesFromBdd( dd, k-1, n-1 ); */ - if ( bVarsK == b1 ) - { - zRes1 = z0; - cuddRef( zRes1 ); - } - else - { - zRes1 = extraZddTuplesFromBdd( dd, cuddT(bVarsK), cuddT(bVarsN) ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - return NULL; - } - cuddRef( zRes1 ); - } - - /* compose Res0 and Res1 with the given ZDD variable */ - zRes = cuddZddGetNode( dd, 2*bVarsN->index, zRes1, zRes0 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - return NULL; - } - cuddDeref( zRes0 ); - cuddDeref( zRes1 ); - - /* insert the result into cache */ - cuddCacheInsert2(dd, extraZddTuplesFromBdd, bVarsK, bVarsN, zRes); - return zRes; - -} /* end of extraZddTuplesFromBdd */ - - -/**Function******************************************************************** - - Synopsis [Performs the recursive step of Extra_zddSelectOneSubset.] - - Description [] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraZddSelectOneSubset( - DdManager * dd, - DdNode * zS ) -// selects one subset from the ZDD zS -// returns z0 if and only if zS is an empty set of cubes -{ - DdNode * zRes; - - if ( zS == z0 ) return z0; - if ( zS == z1 ) return z1; - - // check cache - if ( zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS ) ) - return zRes; - else - { - DdNode * zS0, * zS1, * zTemp; - - zS0 = cuddE(zS); - zS1 = cuddT(zS); - - if ( zS0 != z0 ) - { - zRes = extraZddSelectOneSubset( dd, zS0 ); - if ( zRes == NULL ) - return NULL; - } - else // if ( zS0 == z0 ) - { - assert( zS1 != z0 ); - zRes = extraZddSelectOneSubset( dd, zS1 ); - if ( zRes == NULL ) - return NULL; - cuddRef( zRes ); - - zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - return NULL; - } - cuddDeref( zTemp ); - } - - // insert the result into cache - cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes ); - return zRes; - } -} /* end of extraZddSelectOneSubset */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ diff --git a/src/misc/extra/extraBddUnate.c b/src/misc/extra/extraBddUnate.c deleted file mode 100644 index b0297c77..00000000 --- a/src/misc/extra/extraBddUnate.c +++ /dev/null @@ -1,641 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraBddUnate.c] - - PackageName [extra] - - Synopsis [Efficient methods to compute the information about - unate variables using an algorithm that is conceptually similar to - the algorithm for two-variable symmetry computation presented in: - A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. - Transactions on CAD, Nov. 2003.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - September 1, 2003.] - - Revision [$Id: extraBddUnate.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "extra.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Computes the classical symmetry information for the function.] - - Description [Returns the symmetry information in the form of Extra_UnateInfo_t structure.] - - SideEffects [If the ZDD variables are not derived from BDD variables with - multiplicity 2, this function may derive them in a wrong way.] - - SeeAlso [] - -******************************************************************************/ -Extra_UnateInfo_t * Extra_UnateComputeFast( - DdManager * dd, /* the manager */ - DdNode * bFunc) /* the function whose symmetries are computed */ -{ - DdNode * bSupp; - DdNode * zRes; - Extra_UnateInfo_t * p; - - bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); - zRes = Extra_zddUnateInfoCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes ); - - p = Extra_UnateInfoCreateFromZdd( dd, zRes, bSupp ); - - Cudd_RecursiveDeref( dd, bSupp ); - Cudd_RecursiveDerefZdd( dd, zRes ); - - return p; - -} /* end of Extra_UnateInfoCompute */ - - -/**Function******************************************************************** - - Synopsis [Computes the classical symmetry information as a ZDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddUnateInfoCompute( - DdManager * dd, /* the DD manager */ - DdNode * bF, - DdNode * bVars) -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraZddUnateInfoCompute( dd, bF, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddUnateInfoCompute */ - - -/**Function******************************************************************** - - Synopsis [Converts a set of variables into a set of singleton subsets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * Extra_zddGetSingletonsBoth( - DdManager * dd, /* the DD manager */ - DdNode * bVars) /* the set of variables */ -{ - DdNode * res; - do { - dd->reordered = 0; - res = extraZddGetSingletonsBoth( dd, bVars ); - } while (dd->reordered == 1); - return(res); - -} /* end of Extra_zddGetSingletonsBoth */ - -/**Function******************************************************************** - - Synopsis [Allocates unateness information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_UnateInfo_t * Extra_UnateInfoAllocate( int nVars ) -{ - Extra_UnateInfo_t * p; - // allocate and clean the storage for unateness info - p = ALLOC( Extra_UnateInfo_t, 1 ); - memset( p, 0, sizeof(Extra_UnateInfo_t) ); - p->nVars = nVars; - p->pVars = ALLOC( Extra_UnateVar_t, nVars ); - memset( p->pVars, 0, nVars * sizeof(Extra_UnateVar_t) ); - return p; -} /* end of Extra_UnateInfoAllocate */ - -/**Function******************************************************************** - - Synopsis [Deallocates symmetry information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Extra_UnateInfoDissolve( Extra_UnateInfo_t * p ) -{ - free( p->pVars ); - free( p ); -} /* end of Extra_UnateInfoDissolve */ - -/**Function******************************************************************** - - Synopsis [Allocates symmetry information structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -void Extra_UnateInfoPrint( Extra_UnateInfo_t * p ) -{ - char * pBuffer; - int i; - pBuffer = ALLOC( char, p->nVarsMax+1 ); - memset( pBuffer, ' ', p->nVarsMax ); - pBuffer[p->nVarsMax] = 0; - for ( i = 0; i < p->nVars; i++ ) - if ( p->pVars[i].Neg ) - pBuffer[ p->pVars[i].iVar ] = 'n'; - else if ( p->pVars[i].Pos ) - pBuffer[ p->pVars[i].iVar ] = 'p'; - else - pBuffer[ p->pVars[i].iVar ] = '.'; - printf( "%s\n", pBuffer ); - free( pBuffer ); -} /* end of Extra_UnateInfoPrint */ - - -/**Function******************************************************************** - - Synopsis [Creates the symmetry information structure from ZDD.] - - Description [ZDD representation of symmetries is the set of cubes, each - of which has two variables in the positive polarity. These variables correspond - to the symmetric variable pair.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_UnateInfo_t * Extra_UnateInfoCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp ) -{ - Extra_UnateInfo_t * p; - DdNode * bTemp, * zSet, * zCube, * zTemp; - int * pMapVars2Nums; - int i, nSuppSize; - - nSuppSize = Extra_bddSuppSize( dd, bSupp ); - - // allocate and clean the storage for symmetry info - p = Extra_UnateInfoAllocate( nSuppSize ); - - // allocate the storage for the temporary map - pMapVars2Nums = ALLOC( int, dd->size ); - memset( pMapVars2Nums, 0, dd->size * sizeof(int) ); - - // assign the variables - p->nVarsMax = dd->size; - for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) - { - p->pVars[i].iVar = bTemp->index; - pMapVars2Nums[bTemp->index] = i; - } - - // write the symmetry info into the structure - zSet = zPairs; Cudd_Ref( zSet ); -// Cudd_zddPrintCover( dd, zPairs ); printf( "\n" ); - while ( zSet != z0 ) - { - // get the next cube - zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube ); - - // add this var to the data structure - assert( cuddT(zCube) == z1 && cuddE(zCube) == z0 ); - if ( zCube->index & 1 ) // neg - p->pVars[ pMapVars2Nums[zCube->index/2] ].Neg = 1; - else - p->pVars[ pMapVars2Nums[zCube->index/2] ].Pos = 1; - // count the unate vars - p->nUnate++; - - // update the cuver and deref the cube - zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zCube ); - - } // for each cube - Cudd_RecursiveDerefZdd( dd, zSet ); - FREE( pMapVars2Nums ); - return p; - -} /* end of Extra_UnateInfoCreateFromZdd */ - - - -/**Function******************************************************************** - - Synopsis [Computes the classical unateness information for the function.] - - Description [Uses the naive way of comparing cofactors.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -Extra_UnateInfo_t * Extra_UnateComputeSlow( DdManager * dd, DdNode * bFunc ) -{ - int nSuppSize; - DdNode * bSupp, * bTemp; - Extra_UnateInfo_t * p; - int i, Res; - - // compute the support - bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp ); - nSuppSize = Extra_bddSuppSize( dd, bSupp ); -//printf( "Support = %d. ", nSuppSize ); -//Extra_bddPrint( dd, bSupp ); -//printf( "%d ", nSuppSize ); - - // allocate the storage for symmetry info - p = Extra_UnateInfoAllocate( nSuppSize ); - - // assign the variables - p->nVarsMax = dd->size; - for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ ) - { - Res = Extra_bddCheckUnateNaive( dd, bFunc, bTemp->index ); - p->pVars[i].iVar = bTemp->index; - if ( Res == -1 ) - p->pVars[i].Neg = 1; - else if ( Res == 1 ) - p->pVars[i].Pos = 1; - p->nUnate += (Res != 0); - } - Cudd_RecursiveDeref( dd, bSupp ); - return p; - -} /* end of Extra_UnateComputeSlow */ - -/**Function******************************************************************** - - Synopsis [Checks if the two variables are symmetric.] - - Description [Returns 0 if vars are not unate. Return -1/+1 if the var is neg/pos unate.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_bddCheckUnateNaive( - DdManager * dd, /* the DD manager */ - DdNode * bF, - int iVar) -{ - DdNode * bCof0, * bCof1; - int Res; - - assert( iVar < dd->size ); - - bCof0 = Cudd_Cofactor( dd, bF, Cudd_Not(Cudd_bddIthVar(dd,iVar)) ); Cudd_Ref( bCof0 ); - bCof1 = Cudd_Cofactor( dd, bF, Cudd_bddIthVar(dd,iVar) ); Cudd_Ref( bCof1 ); - - if ( Cudd_bddLeq( dd, bCof0, bCof1 ) ) - Res = 1; - else if ( Cudd_bddLeq( dd, bCof1, bCof0 ) ) - Res =-1; - else - Res = 0; - - Cudd_RecursiveDeref( dd, bCof0 ); - Cudd_RecursiveDeref( dd, bCof1 ); - return Res; -} /* end of Extra_bddCheckUnateNaive */ - - - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_UnateInfoCompute.] - - Description [Returns the set of symmetric variable pairs represented as a set - of two-literal ZDD cubes. Both variables always appear in the positive polarity - in the cubes. This function works without building new BDD nodes. Some relatively - small number of ZDD nodes may be built to ensure proper bookkeeping of the - symmetry information.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * -extraZddUnateInfoCompute( - DdManager * dd, /* the manager */ - DdNode * bFunc, /* the function whose symmetries are computed */ - DdNode * bVars ) /* the set of variables on which this function depends */ -{ - DdNode * zRes; - DdNode * bFR = Cudd_Regular(bFunc); - - if ( cuddIsConstant(bFR) ) - { - if ( cuddIsConstant(bVars) ) - return z0; - return extraZddGetSingletonsBoth( dd, bVars ); - } - assert( bVars != b1 ); - - if ( zRes = cuddCacheLookup2Zdd(dd, extraZddUnateInfoCompute, bFunc, bVars) ) - return zRes; - else - { - DdNode * zRes0, * zRes1; - DdNode * zTemp, * zPlus; - DdNode * bF0, * bF1; - DdNode * bVarsNew; - int nVarsExtra; - int LevelF; - int AddVar; - - // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV - // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F - // count how many extra vars are there in bVars - nVarsExtra = 0; - LevelF = dd->perm[bFR->index]; - for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) - nVarsExtra++; - // the indexes (level) of variables should be synchronized now - assert( bFR->index == bVarsNew->index ); - - // cofactor the function - if ( bFR != bFunc ) // bFunc is complemented - { - bF0 = Cudd_Not( cuddE(bFR) ); - bF1 = Cudd_Not( cuddT(bFR) ); - } - else - { - bF0 = cuddE(bFR); - bF1 = cuddT(bFR); - } - - // solve subproblems - zRes0 = extraZddUnateInfoCompute( dd, bF0, cuddT(bVarsNew) ); - if ( zRes0 == NULL ) - return NULL; - cuddRef( zRes0 ); - - // if there is no symmetries in the negative cofactor - // there is no need to test the positive cofactor - if ( zRes0 == z0 ) - zRes = zRes0; // zRes takes reference - else - { - zRes1 = extraZddUnateInfoCompute( dd, bF1, cuddT(bVarsNew) ); - if ( zRes1 == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - return NULL; - } - cuddRef( zRes1 ); - - // only those variables are pair-wise symmetric - // that are pair-wise symmetric in both cofactors - // therefore, intersect the solutions - zRes = cuddZddIntersect( dd, zRes0, zRes1 ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zRes0 ); - Cudd_RecursiveDerefZdd( dd, zRes1 ); - } - - // consider the current top-most variable - AddVar = -1; - if ( Cudd_bddLeq( dd, bF0, bF1 ) ) // pos - AddVar = 0; - else if ( Cudd_bddLeq( dd, bF1, bF0 ) ) // neg - AddVar = 1; - if ( AddVar >= 0 ) - { - // create the singleton - zPlus = cuddZddGetNode( dd, 2*bFR->index + AddVar, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - // only zRes is referenced at this point - - // if we skipped some variables, these variables cannot be symmetric with - // any variables that are currently in the support of bF, but they can be - // symmetric with the variables that are in bVars but not in the support of bF - for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) ) - { - // create the negative singleton - zPlus = cuddZddGetNode( dd, 2*bVarsNew->index+1, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - - - // create the positive singleton - zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - } - cuddDeref( zRes ); - - /* insert the result into cache */ - cuddCacheInsert2(dd, extraZddUnateInfoCompute, bFunc, bVars, zRes); - return zRes; - } -} /* end of extraZddUnateInfoCompute */ - - -/**Function******************************************************************** - - Synopsis [Performs a recursive step of Extra_zddGetSingletons.] - - Description [Returns the set of ZDD singletons, containing those pos/neg - polarity ZDD variables that correspond to the BDD variables in bVars.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -DdNode * extraZddGetSingletonsBoth( - DdManager * dd, /* the DD manager */ - DdNode * bVars) /* the set of variables */ -{ - DdNode * zRes; - - if ( bVars == b1 ) - return z1; - - if ( zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletonsBoth, bVars) ) - return zRes; - else - { - DdNode * zTemp, * zPlus; - - // solve subproblem - zRes = extraZddGetSingletonsBoth( dd, cuddT(bVars) ); - if ( zRes == NULL ) - return NULL; - cuddRef( zRes ); - - - // create the negative singleton - zPlus = cuddZddGetNode( dd, 2*bVars->index+1, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - - - // create the positive singleton - zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 ); - if ( zPlus == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zRes ); - return NULL; - } - cuddRef( zPlus ); - - // add these to the result - zRes = cuddZddUnion( dd, zTemp = zRes, zPlus ); - if ( zRes == NULL ) - { - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - return NULL; - } - cuddRef( zRes ); - Cudd_RecursiveDerefZdd( dd, zTemp ); - Cudd_RecursiveDerefZdd( dd, zPlus ); - - cuddDeref( zRes ); - cuddCacheInsert1( dd, extraZddGetSingletonsBoth, bVars, zRes ); - return zRes; - } -} /* end of extraZddGetSingletonsBoth */ - - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ diff --git a/src/misc/extra/extraUtilBitMatrix.c b/src/misc/extra/extraUtilBitMatrix.c deleted file mode 100644 index b860a538..00000000 --- a/src/misc/extra/extraUtilBitMatrix.c +++ /dev/null @@ -1,415 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraUtilBitMatrix.c] - - PackageName [extra] - - Synopsis [Various reusable software utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - September 1, 2003.] - - Revision [$Id: extraUtilBitMatrix.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "extra.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -struct Extra_BitMat_t_ -{ - unsigned ** ppData; // bit data - int nSize; // the number of bits in one dimension - int nWords; // the number of words in one dimension - int nBitShift; // the number of bits to shift to get words - unsigned uMask; // the mask to get the number of bits in the word - int nLookups; // the number of lookups - int nInserts; // the number of inserts - int nDeletes; // the number of deletions -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [Starts the bit matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_BitMat_t * Extra_BitMatrixStart( int nSize ) -{ - Extra_BitMat_t * p; - int i; - p = ALLOC( Extra_BitMat_t, 1 ); - memset( p, 0, sizeof(Extra_BitMat_t) ); - p->nSize = nSize; - p->nBitShift = (sizeof(unsigned) == 4) ? 5: 6; - p->uMask = (sizeof(unsigned) == 4) ? 31: 63; - p->nWords = nSize / (8 * sizeof(unsigned)) + ((nSize % (8 * sizeof(unsigned))) > 0); - p->ppData = ALLOC( unsigned *, nSize ); - p->ppData[0] = ALLOC( unsigned, nSize * p->nWords ); - memset( p->ppData[0], 0, sizeof(unsigned) * nSize * p->nWords ); - for ( i = 1; i < nSize; i++ ) - p->ppData[i] = p->ppData[i-1] + p->nWords; - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the bit matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_BitMatrixClean( Extra_BitMat_t * p ) -{ - memset( p->ppData[0], 0, sizeof(unsigned) * p->nSize * p->nWords ); -} - -/**Function************************************************************* - - Synopsis [Stops the bit matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_BitMatrixStop( Extra_BitMat_t * p ) -{ - FREE( p->ppData[0] ); - FREE( p->ppData ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Prints the bit-matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_BitMatrixPrint( Extra_BitMat_t * pMat ) -{ - int i, k, nVars; - printf( "\n" ); - nVars = Extra_BitMatrixReadSize( pMat ); - for ( i = 0; i < nVars; i++ ) - { - for ( k = 0; k <= i; k++ ) - printf( " " ); - for ( k = i+1; k < nVars; k++ ) - if ( Extra_BitMatrixLookup1( pMat, i, k ) ) - printf( "1" ); - else - printf( "." ); - printf( "\n" ); - } -} - - -/**Function************************************************************* - - Synopsis [Reads the matrix size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_BitMatrixReadSize( Extra_BitMat_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [Inserts the element into the upper part.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_BitMatrixInsert1( Extra_BitMat_t * p, int i, int k ) -{ - p->nInserts++; - if ( i < k ) - p->ppData[i][k>>p->nBitShift] |= (1<<(k & p->uMask)); - else - p->ppData[k][i>>p->nBitShift] |= (1<<(i & p->uMask)); -} - -/**Function************************************************************* - - Synopsis [Inserts the element into the upper part.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_BitMatrixLookup1( Extra_BitMat_t * p, int i, int k ) -{ - p->nLookups++; - if ( i < k ) - return ((p->ppData[i][k>>p->nBitShift] & (1<<(k & p->uMask))) > 0); - else - return ((p->ppData[k][i>>p->nBitShift] & (1<<(i & p->uMask))) > 0); -} - -/**Function************************************************************* - - Synopsis [Inserts the element into the upper part.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_BitMatrixDelete1( Extra_BitMat_t * p, int i, int k ) -{ - p->nDeletes++; - if ( i < k ) - p->ppData[i][k>>p->nBitShift] &= ~(1<<(k & p->uMask)); - else - p->ppData[k][i>>p->nBitShift] &= ~(1<<(i & p->uMask)); -} - - - -/**Function************************************************************* - - Synopsis [Inserts the element into the upper part.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_BitMatrixInsert2( Extra_BitMat_t * p, int i, int k ) -{ - p->nInserts++; - if ( i > k ) - p->ppData[i][k>>p->nBitShift] |= (1<<(k & p->uMask)); - else - p->ppData[k][i>>p->nBitShift] |= (1<<(i & p->uMask)); -} - -/**Function************************************************************* - - Synopsis [Inserts the element into the upper part.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_BitMatrixLookup2( Extra_BitMat_t * p, int i, int k ) -{ - p->nLookups++; - if ( i > k ) - return ((p->ppData[i][k>>p->nBitShift] & (1<<(k & p->uMask))) > 0); - else - return ((p->ppData[k][i>>p->nBitShift] & (1<<(i & p->uMask))) > 0); -} - -/**Function************************************************************* - - Synopsis [Inserts the element into the upper part.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_BitMatrixDelete2( Extra_BitMat_t * p, int i, int k ) -{ - p->nDeletes++; - if ( i > k ) - p->ppData[i][k>>p->nBitShift] &= ~(1<<(k & p->uMask)); - else - p->ppData[k][i>>p->nBitShift] &= ~(1<<(i & p->uMask)); -} - - -/**Function************************************************************* - - Synopsis [Inserts the element into the upper part.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_BitMatrixOr( Extra_BitMat_t * p, int i, unsigned * pInfo ) -{ - int w; - for ( w = 0; w < p->nWords; w++ ) - p->ppData[i][w] |= pInfo[w]; -} - -/**Function************************************************************* - - Synopsis [Inserts the element into the upper part.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_BitMatrixOrTwo( Extra_BitMat_t * p, int i, int j ) -{ - int w; - for ( w = 0; w < p->nWords; w++ ) - p->ppData[i][w] = p->ppData[j][w] = (p->ppData[i][w] | p->ppData[j][w]); -} - -/**Function************************************************************* - - Synopsis [Counts the number of 1's in the upper rectangle.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_BitMatrixCountOnesUpper( Extra_BitMat_t * p ) -{ - int i, k, nTotal = 0; - for ( i = 0; i < p->nSize; i++ ) - for ( k = i + 1; k < p->nSize; k++ ) - nTotal += ( (p->ppData[i][k>>5] & (1 << (k&31))) > 0 ); - return nTotal; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the matrices have no entries in common.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_BitMatrixIsDisjoint( Extra_BitMat_t * p1, Extra_BitMat_t * p2 ) -{ - int i, w; - assert( p1->nSize == p2->nSize ); - for ( i = 0; i < p1->nSize; i++ ) - for ( w = 0; w < p1->nWords; w++ ) - if ( p1->ppData[i][w] & p2->ppData[i][w] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the matrix is a set of cliques.] - - Description [For example pairwise symmetry info should satisfy this property.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_BitMatrixIsClique( Extra_BitMat_t * pMat ) -{ - int v, u, i; - for ( v = 0; v < pMat->nSize; v++ ) - for ( u = v+1; u < pMat->nSize; u++ ) - { - if ( !Extra_BitMatrixLookup1( pMat, v, u ) ) - continue; - // v and u are symmetric - for ( i = 0; i < pMat->nSize; i++ ) - { - if ( i == v || i == u ) - continue; - // i is neither v nor u - // the symmetry status of i is the same w.r.t. to v and u - if ( Extra_BitMatrixLookup1( pMat, i, v ) != Extra_BitMatrixLookup1( pMat, i, u ) ) - return 0; - } - } - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/extra/extraUtilCanon.c b/src/misc/extra/extraUtilCanon.c deleted file mode 100644 index fcc7d84d..00000000 --- a/src/misc/extra/extraUtilCanon.c +++ /dev/null @@ -1,701 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraUtilMisc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [Computing canonical forms of Boolean functions using truth tables.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "extra.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -static unsigned s_Truths3[256]; -static char s_Phases3[256][9]; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -static int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, char ** ppfRes, int Flag ); - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function******************************************************************** - - Synopsis [Computes the N-canonical form of the Boolean function up to 6 inputs.] - - Description [The N-canonical form is defined as the truth table with - the minimum integer value. This function exhaustively enumerates - through the complete set of 2^N phase assignments. - Returns pointers to the static storage to the truth table and phases. - This data should be used before the function is called again.] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_TruthCanonFastN( int nVarsMax, int nVarsReal, unsigned * pt, unsigned ** pptRes, char ** ppfRes ) -{ - static unsigned uTruthStore6[2]; - int RetValue; - assert( nVarsMax <= 6 ); - assert( nVarsReal <= nVarsMax ); - RetValue = Extra_TruthCanonN_rec( nVarsReal <= 3? 3: nVarsReal, (unsigned char *)pt, pptRes, ppfRes, 0 ); - if ( nVarsMax == 6 && nVarsReal < nVarsMax ) - { - uTruthStore6[0] = **pptRes; - uTruthStore6[1] = **pptRes; - *pptRes = uTruthStore6; - } - return RetValue; -} - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [Recursive implementation of the above.] - - Description [] - - SideEffects [This procedure has a bug, which shows on Solaris. - Most likely has something to do with the casts, i.g *((unsigned *)pt0)] - - SeeAlso [] - -***********************************************************************/ -int Extra_TruthCanonN_rec( int nVars, unsigned char * pt, unsigned ** pptRes, char ** ppfRes, int Flag ) -{ - static unsigned uTruthStore[7][2][2]; - static char uPhaseStore[7][2][64]; - - unsigned char * pt0, * pt1; - unsigned * ptRes0, * ptRes1, * ptRes; - unsigned uInit0, uInit1, uTruth0, uTruth1, uTemp; - char * pfRes0, * pfRes1, * pfRes; - int nf0, nf1, nfRes, i, nVarsN; - - // table lookup for three vars - if ( nVars == 3 ) - { - *pptRes = &s_Truths3[*pt]; - *ppfRes = s_Phases3[*pt]+1; - return s_Phases3[*pt][0]; - } - - // number of vars for the next call - nVarsN = nVars-1; - // truth table for the next call - pt0 = pt; - pt1 = pt + (1 << nVarsN) / 8; - // 5-var truth tables for this call -// uInit0 = *((unsigned *)pt0); -// uInit1 = *((unsigned *)pt1); - if ( nVarsN == 3 ) - { - uInit0 = (pt0[0] << 24) | (pt0[0] << 16) | (pt0[0] << 8) | pt0[0]; - uInit1 = (pt1[0] << 24) | (pt1[0] << 16) | (pt1[0] << 8) | pt1[0]; - } - else if ( nVarsN == 4 ) - { - uInit0 = (pt0[1] << 24) | (pt0[0] << 16) | (pt0[1] << 8) | pt0[0]; - uInit1 = (pt1[1] << 24) | (pt1[0] << 16) | (pt1[1] << 8) | pt1[0]; - } - else - { - uInit0 = (pt0[3] << 24) | (pt0[2] << 16) | (pt0[1] << 8) | pt0[0]; - uInit1 = (pt1[3] << 24) | (pt1[2] << 16) | (pt1[1] << 8) | pt1[0]; - } - - // storage for truth tables and phases - ptRes = uTruthStore[nVars][Flag]; - pfRes = uPhaseStore[nVars][Flag]; - - // solve trivial cases - if ( uInit1 == 0 ) - { - nf0 = Extra_TruthCanonN_rec( nVarsN, pt0, &ptRes0, &pfRes0, 0 ); - uTruth1 = uInit1; - uTruth0 = *ptRes0; - nfRes = 0; - for ( i = 0; i < nf0; i++ ) - pfRes[nfRes++] = pfRes0[i]; - goto finish; - } - if ( uInit0 == 0 ) - { - nf1 = Extra_TruthCanonN_rec( nVarsN, pt1, &ptRes1, &pfRes1, 1 ); - uTruth1 = uInit0; - uTruth0 = *ptRes1; - nfRes = 0; - for ( i = 0; i < nf1; i++ ) - pfRes[nfRes++] = pfRes1[i] | (1< uTemp ) - { - nfRes = 0; - uTruth0 = uTemp; - pfRes[nfRes++] = pfRes1[i]; - } - else if ( uTruth0 == uTemp ) - pfRes[nfRes++] = pfRes1[i]; - } - uTruth1 = *ptRes1; - } - else if ( *ptRes1 > *ptRes0 ) - { - uTruth0 = 0xFFFFFFFF; - nfRes = 0; - for ( i = 0; i < nf0; i++ ) - { - uTemp = Extra_TruthPolarize( uInit1, pfRes0[i], nVarsN ); - if ( uTruth0 > uTemp ) - { - nfRes = 0; - uTruth0 = uTemp; - pfRes[nfRes++] = pfRes0[i] | (1<= FileName; pDot-- ) - if ( *pDot == '.' ) - return pDot + 1; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Returns the composite name of the file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_FileNameAppend( char * pBase, char * pSuffix ) -{ - static char Buffer[500]; - sprintf( Buffer, "%s%s", pBase, pSuffix ); - return Buffer; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_FileNameGeneric( char * FileName ) -{ - char * pDot; - char * pUnd; - char * pRes; - - // find the generic name of the file - pRes = Extra_UtilStrsav( FileName ); - // find the pointer to the "." symbol in the file name -// pUnd = strstr( FileName, "_" ); - pUnd = NULL; - pDot = strstr( FileName, "." ); - if ( pUnd ) - pRes[pUnd - FileName] = 0; - else if ( pDot ) - pRes[pDot - FileName] = 0; - return pRes; -} - -/**Function************************************************************* - - Synopsis [Returns the file size.] - - Description [The file should be closed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_FileSize( char * pFileName ) -{ - FILE * pFile; - int nFileSize; - pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - printf( "Extra_FileSize(): The file is unavailable (absent or open).\n" ); - return 0; - } - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - fclose( pFile ); - return nFileSize; -} - - -/**Function************************************************************* - - Synopsis [Read the file into the internal buffer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_FileRead( FILE * pFile ) -{ - int nFileSize; - char * pBuffer; - // get the file size, in bytes - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - // move the file current reading position to the beginning - rewind( pFile ); - // load the contents of the file into memory - pBuffer = ALLOC( char, nFileSize + 3 ); - fread( pBuffer, nFileSize, 1, pFile ); - // terminate the string with '\0' - pBuffer[ nFileSize + 0] = '\n'; - pBuffer[ nFileSize + 1] = '\0'; - return pBuffer; -} - -/**Function************************************************************* - - Synopsis [Returns the time stamp.] - - Description [The file should be closed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_TimeStamp() -{ - static char Buffer[100]; - char * TimeStamp; - time_t ltime; - // get the current time - time( <ime ); - TimeStamp = asctime( localtime( <ime ) ); - TimeStamp[ strlen(TimeStamp) - 1 ] = 0; - strcpy( Buffer, TimeStamp ); - return Buffer; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Extra_ReadBinary( char * Buffer ) -{ - unsigned Result; - int i; - - Result = 0; - for ( i = 0; Buffer[i]; i++ ) - if ( Buffer[i] == '0' || Buffer[i] == '1' ) - Result = Result * 2 + Buffer[i] - '0'; - else - { - assert( 0 ); - } - return Result; -} - -/**Function************************************************************* - - Synopsis [Prints the bit string.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_PrintBinary( FILE * pFile, unsigned Sign[], int nBits ) -{ - int Remainder, nWords; - int w, i; - - Remainder = (nBits%(sizeof(unsigned)*8)); - nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); - - for ( w = nWords-1; w >= 0; w-- ) - for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) - fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1< 0) ); - -// fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Reads the hex unsigned into the bit-string.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_ReadHexadecimal( unsigned Sign[], char * pString, int nVars ) -{ - int nWords, nDigits, Digit, k, c; - nWords = Extra_TruthWordNum( nVars ); - for ( k = 0; k < nWords; k++ ) - Sign[k] = 0; - // read the number from the string - nDigits = (1 << nVars) / 4; - if ( nDigits == 0 ) - nDigits = 1; - for ( k = 0; k < nDigits; k++ ) - { - c = nDigits-1-k; - if ( pString[c] >= '0' && pString[c] <= '9' ) - Digit = pString[c] - '0'; - else if ( pString[c] >= 'A' && pString[c] <= 'F' ) - Digit = pString[c] - 'A' + 10; - else if ( pString[c] >= 'a' && pString[c] <= 'f' ) - Digit = pString[c] - 'a' + 10; - else { assert( 0 ); return 0; } - Sign[k/8] |= ( (Digit & 15) << ((k%8) * 4) ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Prints the hex unsigned into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ) -{ - int nDigits, Digit, k; - // write the number into the file - nDigits = (1 << nVars) / 4; - for ( k = nDigits - 1; k >= 0; k-- ) - { - Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15); - if ( Digit < 10 ) - fprintf( pFile, "%d", Digit ); - else - fprintf( pFile, "%c", 'a' + Digit-10 ); - } -// fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints the hex unsigned into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_PrintHexadecimalString( char * pString, unsigned Sign[], int nVars ) -{ - int nDigits, Digit, k; - // write the number into the file - nDigits = (1 << nVars) / 4; - for ( k = nDigits - 1; k >= 0; k-- ) - { - Digit = ((Sign[k/8] >> ((k%8) * 4)) & 15); - if ( Digit < 10 ) - *pString++ = '0' + Digit; - else - *pString++ = 'a' + Digit-10; - } -// fprintf( pFile, "\n" ); - *pString = 0; -} - -/**Function************************************************************* - - Synopsis [Prints the hex unsigned into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_PrintHex( FILE * pFile, unsigned uTruth, int nVars ) -{ - int nMints, nDigits, Digit, k; - - // write the number into the file - fprintf( pFile, "0x" ); - nMints = (1 << nVars); - nDigits = nMints / 4; - for ( k = nDigits - 1; k >= 0; k-- ) - { - Digit = ((uTruth >> (k * 4)) & 15); - if ( Digit < 10 ) - fprintf( pFile, "%d", Digit ); - else - fprintf( pFile, "%c", 'a' + Digit-10 ); - } -// fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Returns the composite name of the file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_PrintSymbols( FILE * pFile, char Char, int nTimes, int fPrintNewLine ) -{ - int i; - for ( i = 0; i < nTimes; i++ ) - printf( "%c", Char ); - if ( fPrintNewLine ) - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Appends the string.] - - Description [Assumes that the given string (pStrGiven) has been allocated - before using malloc(). The additional string has not been allocated. - Allocs more root, appends the additional part, frees the old given string.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_StringAppend( char * pStrGiven, char * pStrAdd ) -{ - char * pTemp; - if ( pStrGiven ) - { - pTemp = ALLOC( char, strlen(pStrGiven) + strlen(pStrAdd) + 2 ); - sprintf( pTemp, "%s%s", pStrGiven, pStrAdd ); - free( pStrGiven ); - } - else - pTemp = Extra_UtilStrsav( pStrAdd ); - return pTemp; -} - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/extra/extraUtilMemory.c b/src/misc/extra/extraUtilMemory.c deleted file mode 100644 index 6eccf015..00000000 --- a/src/misc/extra/extraUtilMemory.c +++ /dev/null @@ -1,625 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraUtilMemory.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [Memory managers.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraUtilMemory.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "extra.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -struct Extra_MmFixed_t_ -{ - // information about individual entries - int nEntrySize; // the size of one entry - int nEntriesAlloc; // the total number of entries allocated - int nEntriesUsed; // the number of entries in use - int nEntriesMax; // the max number of entries in use - char * pEntriesFree; // the linked list of free entries - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -struct Extra_MmFlex_t_ -{ - // information about individual entries - int nEntriesUsed; // the number of entries allocated - char * pCurrent; // the current pointer to free memory - char * pEnd; // the first entry outside the free memory - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - - -struct Extra_MmStep_t_ -{ - int nMems; // the number of fixed memory managers employed - Extra_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc - int nMapSize; // the size of the memory array - Extra_MmFixed_t ** pMap; // maps the number of bytes into its memory manager - int nLargeChunksAlloc; // the maximum number of large memory chunks - int nLargeChunks; // the current number of large memory chunks - void ** pLargeChunks; // the allocated large memory chunks -}; - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [Allocates memory pieces of fixed size.] - - Description [The size of the chunk is computed as the minimum of - 1024 entries and 64K. Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_MmFixed_t * Extra_MmFixedStart( int nEntrySize ) -{ - Extra_MmFixed_t * p; - - p = ALLOC( Extra_MmFixed_t, 1 ); - memset( p, 0, sizeof(Extra_MmFixed_t) ); - - p->nEntrySize = nEntrySize; - p->nEntriesAlloc = 0; - p->nEntriesUsed = 0; - p->pEntriesFree = NULL; - - if ( nEntrySize * (1 << 10) < (1<<16) ) - p->nChunkSize = (1 << 10); - else - p->nChunkSize = (1<<16) / nEntrySize; - if ( p->nChunkSize < 8 ) - p->nChunkSize = 8; - - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_MmFixedPrint( Extra_MmFixed_t * p ) -{ - printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", - p->nEntrySize, p->nChunkSize, p->nChunks ); - printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", - p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_MmFixedStop( Extra_MmFixed_t * p ) -{ - int i; - if ( p == NULL ) - return; - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_MmFixedEntryFetch( Extra_MmFixed_t * p ) -{ - char * pTemp; - int i; - - // check if there are still free entries - if ( p->nEntriesUsed == p->nEntriesAlloc ) - { // need to allocate more entries - assert( p->pEntriesFree == NULL ); - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); - p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; - // transform these entries into a linked list - pTemp = p->pEntriesFree; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pEntriesFree; - // add to the number of entries allocated - p->nEntriesAlloc += p->nChunkSize; - } - // incrememt the counter of used entries - p->nEntriesUsed++; - if ( p->nEntriesMax < p->nEntriesUsed ) - p->nEntriesMax = p->nEntriesUsed; - // return the first entry in the free entry list - pTemp = p->pEntriesFree; - p->pEntriesFree = *((char **)pTemp); - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_MmFixedEntryRecycle( Extra_MmFixed_t * p, char * pEntry ) -{ - // decrement the counter of used entries - p->nEntriesUsed--; - // add the entry to the linked list of free entries - *((char **)pEntry) = p->pEntriesFree; - p->pEntriesFree = pEntry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Relocates all the memory except the first chunk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_MmFixedRestart( Extra_MmFixed_t * p ) -{ - int i; - char * pTemp; - - // deallocate all chunks except the first one - for ( i = 1; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - p->nChunks = 1; - // transform these entries into a linked list - pTemp = p->pChunks[0]; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // set the free entry list - p->pEntriesFree = p->pChunks[0]; - // set the correct statistics - p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; - p->nMemoryUsed = 0; - p->nEntriesAlloc = p->nChunkSize; - p->nEntriesUsed = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_MmFixedReadMemUsage( Extra_MmFixed_t * p ) -{ - return p->nMemoryAlloc; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_MmFixedReadMaxEntriesUsed( Extra_MmFixed_t * p ) -{ - return p->nEntriesMax; -} - - -/**Function************************************************************* - - Synopsis [Allocates entries of flexible size.] - - Description [Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_MmFlex_t * Extra_MmFlexStart() -{ - Extra_MmFlex_t * p; -//printf( "allocing flex\n" ); - p = ALLOC( Extra_MmFlex_t, 1 ); - memset( p, 0, sizeof(Extra_MmFlex_t) ); - - p->nEntriesUsed = 0; - p->pCurrent = NULL; - p->pEnd = NULL; - - p->nChunkSize = (1 << 10); - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_MmFlexPrint( Extra_MmFlex_t * p ) -{ - printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", - p->nChunkSize, p->nChunks ); - printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", - p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_MmFlexStop( Extra_MmFlex_t * p ) -{ - int i; - if ( p == NULL ) - return; -//printf( "deleting flex\n" ); - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_MmFlexEntryFetch( Extra_MmFlex_t * p, int nBytes ) -{ - char * pTemp; - // check if there are still free entries - if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) - { // need to allocate more entries - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - if ( nBytes > p->nChunkSize ) - { - // resize the chunk size if more memory is requested than it can give - // (ideally, this should never happen) - p->nChunkSize = 2 * nBytes; - } - p->pCurrent = ALLOC( char, p->nChunkSize ); - p->pEnd = p->pCurrent + p->nChunkSize; - p->nMemoryAlloc += p->nChunkSize; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pCurrent; - } - assert( p->pCurrent + nBytes <= p->pEnd ); - // increment the counter of used entries - p->nEntriesUsed++; - // keep track of the memory used - p->nMemoryUsed += nBytes; - // return the next entry - pTemp = p->pCurrent; - p->pCurrent += nBytes; - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_MmFlexReadMemUsage( Extra_MmFlex_t * p ) -{ - return p->nMemoryAlloc; -} - - - - - -/**Function************************************************************* - - Synopsis [Starts the hierarchical memory manager.] - - Description [This manager can allocate entries of any size. - Iternally they are mapped into the entries with the number of bytes - equal to the power of 2. The smallest entry size is 8 bytes. The - next one is 16 bytes etc. So, if the user requests 6 bytes, he gets - 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. - The input parameters "nSteps" says how many fixed memory managers - are employed internally. Calling this procedure with nSteps equal - to 10 results in 10 hierarchically arranged internal memory managers, - which can allocate up to 4096 (1Kb) entries. Requests for larger - entries are handed over to malloc() and then free()ed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_MmStep_t * Extra_MmStepStart( int nSteps ) -{ - Extra_MmStep_t * p; - int i, k; - p = ALLOC( Extra_MmStep_t, 1 ); - memset( p, 0, sizeof(Extra_MmStep_t) ); - p->nMems = nSteps; - // start the fixed memory managers - p->pMems = ALLOC( Extra_MmFixed_t *, p->nMems ); - for ( i = 0; i < p->nMems; i++ ) - p->pMems[i] = Extra_MmFixedStart( (8<nMapSize = (4<nMems); - p->pMap = ALLOC( Extra_MmFixed_t *, p->nMapSize+1 ); - p->pMap[0] = NULL; - for ( k = 1; k <= 4; k++ ) - p->pMap[k] = p->pMems[0]; - for ( i = 0; i < p->nMems; i++ ) - for ( k = (4<pMap[k] = p->pMems[i]; -//for ( i = 1; i < 100; i ++ ) -//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_MmStepStop( Extra_MmStep_t * p ) -{ - int i; - for ( i = 0; i < p->nMems; i++ ) - Extra_MmFixedStop( p->pMems[i] ); -// if ( p->pLargeChunks ) -// { -// for ( i = 0; i < p->nLargeChunks; i++ ) -// free( p->pLargeChunks[i] ); -// free( p->pLargeChunks ); -// } - free( p->pMems ); - free( p->pMap ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Creates the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_MmStepEntryFetch( Extra_MmStep_t * p, int nBytes ) -{ - if ( nBytes == 0 ) - return NULL; - if ( nBytes > p->nMapSize ) - { -// printf( "Allocating %d bytes.\n", nBytes ); -/* - if ( p->nLargeChunks == p->nLargeChunksAlloc ) - { - if ( p->nLargeChunksAlloc == 0 ) - p->nLargeChunksAlloc = 5; - p->nLargeChunksAlloc *= 2; - p->pLargeChunks = REALLOC( char *, p->pLargeChunks, p->nLargeChunksAlloc ); - } - p->pLargeChunks[ p->nLargeChunks++ ] = ALLOC( char, nBytes ); - return p->pLargeChunks[ p->nLargeChunks - 1 ]; -*/ - return ALLOC( char, nBytes ); - } - return Extra_MmFixedEntryFetch( p->pMap[nBytes] ); -} - - -/**Function************************************************************* - - Synopsis [Recycles the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_MmStepEntryRecycle( Extra_MmStep_t * p, char * pEntry, int nBytes ) -{ - if ( nBytes == 0 ) - return; - if ( nBytes > p->nMapSize ) - { - free( pEntry ); - return; - } - Extra_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_MmStepReadMemUsage( Extra_MmStep_t * p ) -{ - int i, nMemTotal = 0; - for ( i = 0; i < p->nMems; i++ ) - nMemTotal += p->pMems[i]->nMemoryAlloc; - return nMemTotal; -} - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static functions */ -/*---------------------------------------------------------------------------*/ - diff --git a/src/misc/extra/extraUtilMisc.c b/src/misc/extra/extraUtilMisc.c deleted file mode 100644 index dff774bc..00000000 --- a/src/misc/extra/extraUtilMisc.c +++ /dev/null @@ -1,2235 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraUtilMisc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [Misc procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "extra.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - -static void Extra_Permutations_rec( char ** pRes, int nFact, int n, char Array[] ); - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function******************************************************************** - - Synopsis [Finds the smallest integer larger of equal than the logarithm.] - - Description [Returns [Log2(Num)].] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_Base2Log( unsigned Num ) -{ - int Res; - assert( Num >= 0 ); - if ( Num == 0 ) return 0; - if ( Num == 1 ) return 1; - for ( Res = 0, Num--; Num; Num >>= 1, Res++ ); - return Res; -} /* end of Extra_Base2Log */ - -/**Function******************************************************************** - - Synopsis [Finds the smallest integer larger of equal than the logarithm.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_Base2LogDouble( double Num ) -{ - double Res; - int ResInt; - - Res = log(Num)/log(2.0); - ResInt = (int)Res; - if ( ResInt == Res ) - return ResInt; - else - return ResInt+1; -} - -/**Function******************************************************************** - - Synopsis [Finds the smallest integer larger of equal than the logarithm.] - - Description [Returns [Log10(Num)].] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -int Extra_Base10Log( unsigned Num ) -{ - int Res; - assert( Num >= 0 ); - if ( Num == 0 ) return 0; - if ( Num == 1 ) return 1; - for ( Res = 0, Num--; Num; Num /= 10, Res++ ); - return Res; -} /* end of Extra_Base2Log */ - -/**Function******************************************************************** - - Synopsis [Returns the power of two as a double.] - - Description [] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -double Extra_Power2( int Degree ) -{ - double Res; - assert( Degree >= 0 ); - if ( Degree < 32 ) - return (double)(01<>= Shift; - uTruth = uCof0 | uCof1; - } - return uTruth; -} - -/**Function************************************************************* - - Synopsis [Computes N-canonical form using brute-force methods.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Extra_TruthCanonN( unsigned uTruth, int nVars ) -{ - unsigned uTruthMin, uPhase; - int nMints, i; - nMints = (1 << nVars); - uTruthMin = 0xFFFFFFFF; - for ( i = 0; i < nMints; i++ ) - { - uPhase = Extra_TruthPolarize( uTruth, i, nVars ); - if ( uTruthMin > uPhase ) - uTruthMin = uPhase; - } - return uTruthMin; -} - -/**Function************************************************************* - - Synopsis [Computes NN-canonical form using brute-force methods.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Extra_TruthCanonNN( unsigned uTruth, int nVars ) -{ - unsigned uTruthMin, uTruthC, uPhase; - int nMints, i; - nMints = (1 << nVars); - uTruthC = (unsigned)( (~uTruth) & ((~((unsigned)0)) >> (32-nMints)) ); - uTruthMin = 0xFFFFFFFF; - for ( i = 0; i < nMints; i++ ) - { - uPhase = Extra_TruthPolarize( uTruth, i, nVars ); - if ( uTruthMin > uPhase ) - uTruthMin = uPhase; - uPhase = Extra_TruthPolarize( uTruthC, i, nVars ); - if ( uTruthMin > uPhase ) - uTruthMin = uPhase; - } - return uTruthMin; -} - -/**Function************************************************************* - - Synopsis [Computes P-canonical form using brute-force methods.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Extra_TruthCanonP( unsigned uTruth, int nVars ) -{ - static int nVarsOld, nPerms; - static char ** pPerms = NULL; - - unsigned uTruthMin, uPerm; - int k; - - if ( pPerms == NULL ) - { - nPerms = Extra_Factorial( nVars ); - pPerms = Extra_Permutations( nVars ); - nVarsOld = nVars; - } - else if ( nVarsOld != nVars ) - { - free( pPerms ); - nPerms = Extra_Factorial( nVars ); - pPerms = Extra_Permutations( nVars ); - nVarsOld = nVars; - } - - uTruthMin = 0xFFFFFFFF; - for ( k = 0; k < nPerms; k++ ) - { - uPerm = Extra_TruthPermute( uTruth, pPerms[k], nVars, 0 ); - if ( uTruthMin > uPerm ) - uTruthMin = uPerm; - } - return uTruthMin; -} - -/**Function************************************************************* - - Synopsis [Computes NP-canonical form using brute-force methods.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Extra_TruthCanonNP( unsigned uTruth, int nVars ) -{ - static int nVarsOld, nPerms; - static char ** pPerms = NULL; - - unsigned uTruthMin, uPhase, uPerm; - int nMints, k, i; - - if ( pPerms == NULL ) - { - nPerms = Extra_Factorial( nVars ); - pPerms = Extra_Permutations( nVars ); - nVarsOld = nVars; - } - else if ( nVarsOld != nVars ) - { - free( pPerms ); - nPerms = Extra_Factorial( nVars ); - pPerms = Extra_Permutations( nVars ); - nVarsOld = nVars; - } - - nMints = (1 << nVars); - uTruthMin = 0xFFFFFFFF; - for ( i = 0; i < nMints; i++ ) - { - uPhase = Extra_TruthPolarize( uTruth, i, nVars ); - for ( k = 0; k < nPerms; k++ ) - { - uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 ); - if ( uTruthMin > uPerm ) - uTruthMin = uPerm; - } - } - return uTruthMin; -} - -/**Function************************************************************* - - Synopsis [Computes NPN-canonical form using brute-force methods.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Extra_TruthCanonNPN( unsigned uTruth, int nVars ) -{ - static int nVarsOld, nPerms; - static char ** pPerms = NULL; - - unsigned uTruthMin, uTruthC, uPhase, uPerm; - int nMints, k, i; - - if ( pPerms == NULL ) - { - nPerms = Extra_Factorial( nVars ); - pPerms = Extra_Permutations( nVars ); - nVarsOld = nVars; - } - else if ( nVarsOld != nVars ) - { - free( pPerms ); - nPerms = Extra_Factorial( nVars ); - pPerms = Extra_Permutations( nVars ); - nVarsOld = nVars; - } - - nMints = (1 << nVars); - uTruthC = (unsigned)( (~uTruth) & ((~((unsigned)0)) >> (32-nMints)) ); - uTruthMin = 0xFFFFFFFF; - for ( i = 0; i < nMints; i++ ) - { - uPhase = Extra_TruthPolarize( uTruth, i, nVars ); - for ( k = 0; k < nPerms; k++ ) - { - uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 ); - if ( uTruthMin > uPerm ) - uTruthMin = uPerm; - } - uPhase = Extra_TruthPolarize( uTruthC, i, nVars ); - for ( k = 0; k < nPerms; k++ ) - { - uPerm = Extra_TruthPermute( uPhase, pPerms[k], nVars, 0 ); - if ( uTruthMin > uPerm ) - uTruthMin = uPerm; - } - } - return uTruthMin; -} - -/**Function************************************************************* - - Synopsis [Computes NPN canonical forms for 4-variable functions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_Truth4VarNPN( unsigned short ** puCanons, char ** puPhases, char ** puPerms, unsigned char ** puMap ) -{ - unsigned short * uCanons; - unsigned char * uMap; - unsigned uTruth, uPhase, uPerm; - char ** pPerms4, * uPhases, * uPerms; - int nFuncs, nClasses; - int i, k; - - nFuncs = (1 << 16); - uCanons = ALLOC( unsigned short, nFuncs ); - uPhases = ALLOC( char, nFuncs ); - uPerms = ALLOC( char, nFuncs ); - uMap = ALLOC( unsigned char, nFuncs ); - memset( uCanons, 0, sizeof(unsigned short) * nFuncs ); - memset( uPhases, 0, sizeof(char) * nFuncs ); - memset( uPerms, 0, sizeof(char) * nFuncs ); - memset( uMap, 0, sizeof(unsigned char) * nFuncs ); - pPerms4 = Extra_Permutations( 4 ); - - nClasses = 1; - nFuncs = (1 << 15); - for ( uTruth = 1; uTruth < (unsigned)nFuncs; uTruth++ ) - { - // skip already assigned - if ( uCanons[uTruth] ) - { - assert( uTruth > uCanons[uTruth] ); - uMap[~uTruth & 0xFFFF] = uMap[uTruth] = uMap[uCanons[uTruth]]; - continue; - } - uMap[uTruth] = nClasses++; - for ( i = 0; i < 16; i++ ) - { - uPhase = Extra_TruthPolarize( uTruth, i, 4 ); - for ( k = 0; k < 24; k++ ) - { - uPerm = Extra_TruthPermute( uPhase, pPerms4[k], 4, 0 ); - if ( uCanons[uPerm] == 0 ) - { - uCanons[uPerm] = uTruth; - uPhases[uPerm] = i; - uPerms[uPerm] = k; - - uPerm = ~uPerm & 0xFFFF; - uCanons[uPerm] = uTruth; - uPhases[uPerm] = i | 16; - uPerms[uPerm] = k; - } - else - assert( uCanons[uPerm] == uTruth ); - } - uPhase = Extra_TruthPolarize( ~uTruth & 0xFFFF, i, 4 ); - for ( k = 0; k < 24; k++ ) - { - uPerm = Extra_TruthPermute( uPhase, pPerms4[k], 4, 0 ); - if ( uCanons[uPerm] == 0 ) - { - uCanons[uPerm] = uTruth; - uPhases[uPerm] = i; - uPerms[uPerm] = k; - - uPerm = ~uPerm & 0xFFFF; - uCanons[uPerm] = uTruth; - uPhases[uPerm] = i | 16; - uPerms[uPerm] = k; - } - else - assert( uCanons[uPerm] == uTruth ); - } - } - } - uPhases[(1<<16)-1] = 16; - assert( nClasses == 222 ); - free( pPerms4 ); - if ( puCanons ) - *puCanons = uCanons; - else - free( uCanons ); - if ( puPhases ) - *puPhases = uPhases; - else - free( uPhases ); - if ( puPerms ) - *puPerms = uPerms; - else - free( uPerms ); - if ( puMap ) - *puMap = uMap; - else - free( uMap ); -} - -/**Function************************************************************* - - Synopsis [Computes NPN canonical forms for 4-variable functions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_Truth3VarN( unsigned ** puCanons, char *** puPhases, char ** ppCounters ) -{ - int nPhasesMax = 8; - unsigned * uCanons; - unsigned uTruth, uPhase, uTruth32; - char ** uPhases, * pCounters; - int nFuncs, nClasses, i; - - nFuncs = (1 << 8); - uCanons = ALLOC( unsigned, nFuncs ); - memset( uCanons, 0, sizeof(unsigned) * nFuncs ); - pCounters = ALLOC( char, nFuncs ); - memset( pCounters, 0, sizeof(char) * nFuncs ); - uPhases = (char **)Extra_ArrayAlloc( nFuncs, nPhasesMax, sizeof(char) ); - nClasses = 0; - for ( uTruth = 0; uTruth < (unsigned)nFuncs; uTruth++ ) - { - // skip already assigned - uTruth32 = ((uTruth << 24) | (uTruth << 16) | (uTruth << 8) | uTruth); - if ( uCanons[uTruth] ) - { - assert( uTruth32 > uCanons[uTruth] ); - continue; - } - nClasses++; - for ( i = 0; i < 8; i++ ) - { - uPhase = Extra_TruthPolarize( uTruth, i, 3 ); - if ( uCanons[uPhase] == 0 && (uTruth || i==0) ) - { - uCanons[uPhase] = uTruth32; - uPhases[uPhase][0] = i; - pCounters[uPhase] = 1; - } - else - { - assert( uCanons[uPhase] == uTruth32 ); - if ( pCounters[uPhase] < nPhasesMax ) - uPhases[uPhase][ pCounters[uPhase]++ ] = i; - } - } - } - if ( puCanons ) - *puCanons = uCanons; - else - free( uCanons ); - if ( puPhases ) - *puPhases = uPhases; - else - free( uPhases ); - if ( ppCounters ) - *ppCounters = pCounters; - else - free( pCounters ); -// printf( "The number of 3N-classes = %d.\n", nClasses ); -} - -/**Function************************************************************* - - Synopsis [Computes NPN canonical forms for 4-variable functions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_Truth4VarN( unsigned short ** puCanons, char *** puPhases, char ** ppCounters, int nPhasesMax ) -{ - unsigned short * uCanons; - unsigned uTruth, uPhase; - char ** uPhases, * pCounters; - int nFuncs, nClasses, i; - - nFuncs = (1 << 16); - uCanons = ALLOC( unsigned short, nFuncs ); - memset( uCanons, 0, sizeof(unsigned short) * nFuncs ); - pCounters = ALLOC( char, nFuncs ); - memset( pCounters, 0, sizeof(char) * nFuncs ); - uPhases = (char **)Extra_ArrayAlloc( nFuncs, nPhasesMax, sizeof(char) ); - nClasses = 0; - for ( uTruth = 0; uTruth < (unsigned)nFuncs; uTruth++ ) - { - // skip already assigned - if ( uCanons[uTruth] ) - { - assert( uTruth > uCanons[uTruth] ); - continue; - } - nClasses++; - for ( i = 0; i < 16; i++ ) - { - uPhase = Extra_TruthPolarize( uTruth, i, 4 ); - if ( uCanons[uPhase] == 0 && (uTruth || i==0) ) - { - uCanons[uPhase] = uTruth; - uPhases[uPhase][0] = i; - pCounters[uPhase] = 1; - } - else - { - assert( uCanons[uPhase] == uTruth ); - if ( pCounters[uPhase] < nPhasesMax ) - uPhases[uPhase][ pCounters[uPhase]++ ] = i; - } - } - } - if ( puCanons ) - *puCanons = uCanons; - else - free( uCanons ); - if ( puPhases ) - *puPhases = uPhases; - else - free( uPhases ); - if ( ppCounters ) - *ppCounters = pCounters; - else - free( pCounters ); -// printf( "The number of 4N-classes = %d.\n", nClasses ); -} - -/**Function************************************************************* - - Synopsis [Allocated one-memory-chunk array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ** Extra_ArrayAlloc( int nCols, int nRows, int Size ) -{ - char ** pRes; - char * pBuffer; - int i; - assert( nCols > 0 && nRows > 0 && Size > 0 ); - pBuffer = ALLOC( char, nCols * (sizeof(void *) + nRows * Size) ); - pRes = (char **)pBuffer; - pRes[0] = pBuffer + nCols * sizeof(void *); - for ( i = 1; i < nCols; i++ ) - pRes[i] = pRes[0] + i * nRows * Size; - return pRes; -} - -/**Function************************************************************* - - Synopsis [Computes a phase of the 3-var function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned short Extra_TruthPerm4One( unsigned uTruth, int Phase ) -{ - // cases - static unsigned short Cases[16] = { - 0, // 0000 - skip - 0, // 0001 - skip - 0xCCCC, // 0010 - single var - 0, // 0011 - skip - 0xF0F0, // 0100 - single var - 1, // 0101 - 1, // 0110 - 0, // 0111 - skip - 0xFF00, // 1000 - single var - 1, // 1001 - 1, // 1010 - 1, // 1011 - 1, // 1100 - 1, // 1101 - 1, // 1110 - 0 // 1111 - skip - }; - // permutations - static int Perms[16][4] = { - { 0, 0, 0, 0 }, // 0000 - skip - { 0, 0, 0, 0 }, // 0001 - skip - { 0, 0, 0, 0 }, // 0010 - single var - { 0, 0, 0, 0 }, // 0011 - skip - { 0, 0, 0, 0 }, // 0100 - single var - { 0, 2, 1, 3 }, // 0101 - { 2, 0, 1, 3 }, // 0110 - { 0, 0, 0, 0 }, // 0111 - skip - { 0, 0, 0, 0 }, // 1000 - single var - { 0, 2, 3, 1 }, // 1001 - { 2, 0, 3, 1 }, // 1010 - { 0, 1, 3, 2 }, // 1011 - { 2, 3, 0, 1 }, // 1100 - { 0, 3, 1, 2 }, // 1101 - { 3, 0, 1, 2 }, // 1110 - { 0, 0, 0, 0 } // 1111 - skip - }; - int i, k, iRes; - unsigned uTruthRes; - assert( Phase >= 0 && Phase < 16 ); - if ( Cases[Phase] == 0 ) - return uTruth; - if ( Cases[Phase] > 1 ) - return Cases[Phase]; - uTruthRes = 0; - for ( i = 0; i < 16; i++ ) - if ( uTruth & (1 << i) ) - { - for ( iRes = 0, k = 0; k < 4; k++ ) - if ( i & (1 << Perms[Phase][k]) ) - iRes |= (1 << k); - uTruthRes |= (1 << iRes); - } - return uTruthRes; -} - -/**Function************************************************************* - - Synopsis [Computes a phase of the 3-var function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Extra_TruthPerm5One( unsigned uTruth, int Phase ) -{ - // cases - static unsigned Cases[32] = { - 0, // 00000 - skip - 0, // 00001 - skip - 0xCCCCCCCC, // 00010 - single var - 0, // 00011 - skip - 0xF0F0F0F0, // 00100 - single var - 1, // 00101 - 1, // 00110 - 0, // 00111 - skip - 0xFF00FF00, // 01000 - single var - 1, // 01001 - 1, // 01010 - 1, // 01011 - 1, // 01100 - 1, // 01101 - 1, // 01110 - 0, // 01111 - skip - 0xFFFF0000, // 10000 - skip - 1, // 10001 - 1, // 10010 - 1, // 10011 - 1, // 10100 - 1, // 10101 - 1, // 10110 - 1, // 10111 - four var - 1, // 11000 - 1, // 11001 - 1, // 11010 - 1, // 11011 - four var - 1, // 11100 - 1, // 11101 - four var - 1, // 11110 - four var - 0 // 11111 - skip - }; - // permutations - static int Perms[32][5] = { - { 0, 0, 0, 0, 0 }, // 00000 - skip - { 0, 0, 0, 0, 0 }, // 00001 - skip - { 0, 0, 0, 0, 0 }, // 00010 - single var - { 0, 0, 0, 0, 0 }, // 00011 - skip - { 0, 0, 0, 0, 0 }, // 00100 - single var - { 0, 2, 1, 3, 4 }, // 00101 - { 2, 0, 1, 3, 4 }, // 00110 - { 0, 0, 0, 0, 0 }, // 00111 - skip - { 0, 0, 0, 0, 0 }, // 01000 - single var - { 0, 2, 3, 1, 4 }, // 01001 - { 2, 0, 3, 1, 4 }, // 01010 - { 0, 1, 3, 2, 4 }, // 01011 - { 2, 3, 0, 1, 4 }, // 01100 - { 0, 3, 1, 2, 4 }, // 01101 - { 3, 0, 1, 2, 4 }, // 01110 - { 0, 0, 0, 0, 0 }, // 01111 - skip - { 0, 0, 0, 0, 0 }, // 10000 - single var - { 0, 4, 2, 3, 1 }, // 10001 - { 4, 0, 2, 3, 1 }, // 10010 - { 0, 1, 3, 4, 2 }, // 10011 - { 2, 3, 0, 4, 1 }, // 10100 - { 0, 3, 1, 4, 2 }, // 10101 - { 3, 0, 1, 4, 2 }, // 10110 - { 0, 1, 2, 4, 3 }, // 10111 - four var - { 2, 3, 4, 0, 1 }, // 11000 - { 0, 3, 4, 1, 2 }, // 11001 - { 3, 0, 4, 1, 2 }, // 11010 - { 0, 1, 4, 2, 3 }, // 11011 - four var - { 3, 4, 0, 1, 2 }, // 11100 - { 0, 4, 1, 2, 3 }, // 11101 - four var - { 4, 0, 1, 2, 3 }, // 11110 - four var - { 0, 0, 0, 0, 0 } // 11111 - skip - }; - int i, k, iRes; - unsigned uTruthRes; - assert( Phase >= 0 && Phase < 32 ); - if ( Cases[Phase] == 0 ) - return uTruth; - if ( Cases[Phase] > 1 ) - return Cases[Phase]; - uTruthRes = 0; - for ( i = 0; i < 32; i++ ) - if ( uTruth & (1 << i) ) - { - for ( iRes = 0, k = 0; k < 5; k++ ) - if ( i & (1 << Perms[Phase][k]) ) - iRes |= (1 << k); - uTruthRes |= (1 << iRes); - } - return uTruthRes; -} - -/**Function************************************************************* - - Synopsis [Computes a phase of the 3-var function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthPerm6One( unsigned * uTruth, int Phase, unsigned * uTruthRes ) -{ - // cases - static unsigned Cases[64] = { - 0, // 000000 - skip - 0, // 000001 - skip - 0xCCCCCCCC, // 000010 - single var - 0, // 000011 - skip - 0xF0F0F0F0, // 000100 - single var - 1, // 000101 - 1, // 000110 - 0, // 000111 - skip - 0xFF00FF00, // 001000 - single var - 1, // 001001 - 1, // 001010 - 1, // 001011 - 1, // 001100 - 1, // 001101 - 1, // 001110 - 0, // 001111 - skip - 0xFFFF0000, // 010000 - skip - 1, // 010001 - 1, // 010010 - 1, // 010011 - 1, // 010100 - 1, // 010101 - 1, // 010110 - 1, // 010111 - four var - 1, // 011000 - 1, // 011001 - 1, // 011010 - 1, // 011011 - four var - 1, // 011100 - 1, // 011101 - four var - 1, // 011110 - four var - 0, // 011111 - skip - 0xFFFFFFFF, // 100000 - single var - 1, // 100001 - 1, // 100010 - 1, // 100011 - 1, // 100100 - 1, // 100101 - 1, // 100110 - 1, // 100111 - 1, // 101000 - 1, // 101001 - 1, // 101010 - 1, // 101011 - 1, // 101100 - 1, // 101101 - 1, // 101110 - 1, // 101111 - 1, // 110000 - 1, // 110001 - 1, // 110010 - 1, // 110011 - 1, // 110100 - 1, // 110101 - 1, // 110110 - 1, // 110111 - 1, // 111000 - 1, // 111001 - 1, // 111010 - 1, // 111011 - 1, // 111100 - 1, // 111101 - 1, // 111110 - 0 // 111111 - skip - }; - // permutations - static int Perms[64][6] = { - { 0, 0, 0, 0, 0, 0 }, // 000000 - skip - { 0, 0, 0, 0, 0, 0 }, // 000001 - skip - { 0, 0, 0, 0, 0, 0 }, // 000010 - single var - { 0, 0, 0, 0, 0, 0 }, // 000011 - skip - { 0, 0, 0, 0, 0, 0 }, // 000100 - single var - { 0, 2, 1, 3, 4, 5 }, // 000101 - { 2, 0, 1, 3, 4, 5 }, // 000110 - { 0, 0, 0, 0, 0, 0 }, // 000111 - skip - { 0, 0, 0, 0, 0, 0 }, // 001000 - single var - { 0, 2, 3, 1, 4, 5 }, // 001001 - { 2, 0, 3, 1, 4, 5 }, // 001010 - { 0, 1, 3, 2, 4, 5 }, // 001011 - { 2, 3, 0, 1, 4, 5 }, // 001100 - { 0, 3, 1, 2, 4, 5 }, // 001101 - { 3, 0, 1, 2, 4, 5 }, // 001110 - { 0, 0, 0, 0, 0, 0 }, // 001111 - skip - { 0, 0, 0, 0, 0, 0 }, // 010000 - skip - { 0, 4, 2, 3, 1, 5 }, // 010001 - { 4, 0, 2, 3, 1, 5 }, // 010010 - { 0, 1, 3, 4, 2, 5 }, // 010011 - { 2, 3, 0, 4, 1, 5 }, // 010100 - { 0, 3, 1, 4, 2, 5 }, // 010101 - { 3, 0, 1, 4, 2, 5 }, // 010110 - { 0, 1, 2, 4, 3, 5 }, // 010111 - four var - { 2, 3, 4, 0, 1, 5 }, // 011000 - { 0, 3, 4, 1, 2, 5 }, // 011001 - { 3, 0, 4, 1, 2, 5 }, // 011010 - { 0, 1, 4, 2, 3, 5 }, // 011011 - four var - { 3, 4, 0, 1, 2, 5 }, // 011100 - { 0, 4, 1, 2, 3, 5 }, // 011101 - four var - { 4, 0, 1, 2, 3, 5 }, // 011110 - four var - { 0, 0, 0, 0, 0, 0 }, // 011111 - skip - { 0, 0, 0, 0, 0, 0 }, // 100000 - single var - { 0, 2, 3, 4, 5, 1 }, // 100001 - { 2, 0, 3, 4, 5, 1 }, // 100010 - { 0, 1, 3, 4, 5, 2 }, // 100011 - { 2, 3, 0, 4, 5, 1 }, // 100100 - { 0, 3, 1, 4, 5, 2 }, // 100101 - { 3, 0, 1, 4, 5, 2 }, // 100110 - { 0, 1, 2, 4, 5, 3 }, // 100111 - { 2, 3, 4, 0, 5, 1 }, // 101000 - { 0, 3, 4, 1, 5, 2 }, // 101001 - { 3, 0, 4, 1, 5, 2 }, // 101010 - { 0, 1, 4, 2, 5, 3 }, // 101011 - { 3, 4, 0, 1, 5, 2 }, // 101100 - { 0, 4, 1, 2, 5, 3 }, // 101101 - { 4, 0, 1, 2, 5, 3 }, // 101110 - { 0, 1, 2, 3, 5, 4 }, // 101111 - { 2, 3, 4, 5, 0, 1 }, // 110000 - { 0, 3, 4, 5, 1, 2 }, // 110001 - { 3, 0, 4, 5, 1, 2 }, // 110010 - { 0, 1, 4, 5, 2, 3 }, // 110011 - { 3, 4, 0, 5, 1, 2 }, // 110100 - { 0, 4, 1, 5, 2, 3 }, // 110101 - { 4, 0, 1, 5, 2, 3 }, // 110110 - { 0, 1, 2, 5, 3, 4 }, // 110111 - { 3, 4, 5, 0, 1, 2 }, // 111000 - { 0, 4, 5, 1, 2, 3 }, // 111001 - { 4, 0, 5, 1, 2, 3 }, // 111010 - { 0, 1, 5, 2, 3, 4 }, // 111011 - { 4, 5, 0, 1, 2, 3 }, // 111100 - { 0, 5, 1, 2, 3, 4 }, // 111101 - { 5, 0, 1, 2, 3, 4 }, // 111110 - { 0, 0, 0, 0, 0, 0 } // 111111 - skip - }; - int i, k, iRes; - assert( Phase >= 0 && Phase < 64 ); - if ( Cases[Phase] == 0 ) - { - uTruthRes[0] = uTruth[0]; - uTruthRes[1] = uTruth[1]; - return; - } - if ( Cases[Phase] > 1 ) - { - if ( Phase == 32 ) - { - uTruthRes[0] = 0x00000000; - uTruthRes[1] = 0xFFFFFFFF; - } - else - { - uTruthRes[0] = Cases[Phase]; - uTruthRes[1] = Cases[Phase]; - } - return; - } - uTruthRes[0] = 0; - uTruthRes[1] = 0; - for ( i = 0; i < 64; i++ ) - { - if ( i < 32 ) - { - if ( uTruth[0] & (1 << i) ) - { - for ( iRes = 0, k = 0; k < 6; k++ ) - if ( i & (1 << Perms[Phase][k]) ) - iRes |= (1 << k); - if ( iRes < 32 ) - uTruthRes[0] |= (1 << iRes); - else - uTruthRes[1] |= (1 << (iRes-32)); - } - } - else - { - if ( uTruth[1] & (1 << (i-32)) ) - { - for ( iRes = 0, k = 0; k < 6; k++ ) - if ( i & (1 << Perms[Phase][k]) ) - iRes |= (1 << k); - if ( iRes < 32 ) - uTruthRes[0] |= (1 << iRes); - else - uTruthRes[1] |= (1 << (iRes-32)); - } - } - } -} - -/**Function************************************************************* - - Synopsis [Computes a phase of the 8-var function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthExpand( int nVars, int nWords, unsigned * puTruth, unsigned uPhase, unsigned * puTruthR ) -{ - // elementary truth tables - static unsigned uTruths[8][8] = { - { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, - { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, - { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, - { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, - { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, - { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, - { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, - { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } - }; - static char Cases[256] = { - 0, // 00000000 - 0, // 00000001 - 1, // 00000010 - 0, // 00000011 - 2, // 00000100 - -1, // 00000101 - -1, // 00000110 - 0, // 00000111 - 3, // 00001000 - -1, // 00001001 - -1, // 00001010 - -1, // 00001011 - -1, // 00001100 - -1, // 00001101 - -1, // 00001110 - 0, // 00001111 - 4, // 00010000 - -1, // 00010001 - -1, // 00010010 - -1, // 00010011 - -1, // 00010100 - -1, // 00010101 - -1, // 00010110 - -1, // 00010111 - -1, // 00011000 - -1, // 00011001 - -1, // 00011010 - -1, // 00011011 - -1, // 00011100 - -1, // 00011101 - -1, // 00011110 - 0, // 00011111 - 5, // 00100000 - -1, // 00100001 - -1, // 00100010 - -1, // 00100011 - -1, // 00100100 - -1, // 00100101 - -1, // 00100110 - -1, // 00100111 - -1, // 00101000 - -1, // 00101001 - -1, // 00101010 - -1, // 00101011 - -1, // 00101100 - -1, // 00101101 - -1, // 00101110 - -1, // 00101111 - -1, // 00110000 - -1, // 00110001 - -1, // 00110010 - -1, // 00110011 - -1, // 00110100 - -1, // 00110101 - -1, // 00110110 - -1, // 00110111 - -1, // 00111000 - -1, // 00111001 - -1, // 00111010 - -1, // 00111011 - -1, // 00111100 - -1, // 00111101 - -1, // 00111110 - 0, // 00111111 - 6, // 01000000 - -1, // 01000001 - -1, // 01000010 - -1, // 01000011 - -1, // 01000100 - -1, // 01000101 - -1, // 01000110 - -1, // 01000111 - -1, // 01001000 - -1, // 01001001 - -1, // 01001010 - -1, // 01001011 - -1, // 01001100 - -1, // 01001101 - -1, // 01001110 - -1, // 01001111 - -1, // 01010000 - -1, // 01010001 - -1, // 01010010 - -1, // 01010011 - -1, // 01010100 - -1, // 01010101 - -1, // 01010110 - -1, // 01010111 - -1, // 01011000 - -1, // 01011001 - -1, // 01011010 - -1, // 01011011 - -1, // 01011100 - -1, // 01011101 - -1, // 01011110 - -1, // 01011111 - -1, // 01100000 - -1, // 01100001 - -1, // 01100010 - -1, // 01100011 - -1, // 01100100 - -1, // 01100101 - -1, // 01100110 - -1, // 01100111 - -1, // 01101000 - -1, // 01101001 - -1, // 01101010 - -1, // 01101011 - -1, // 01101100 - -1, // 01101101 - -1, // 01101110 - -1, // 01101111 - -1, // 01110000 - -1, // 01110001 - -1, // 01110010 - -1, // 01110011 - -1, // 01110100 - -1, // 01110101 - -1, // 01110110 - -1, // 01110111 - -1, // 01111000 - -1, // 01111001 - -1, // 01111010 - -1, // 01111011 - -1, // 01111100 - -1, // 01111101 - -1, // 01111110 - 0, // 01111111 - 7, // 10000000 - -1, // 10000001 - -1, // 10000010 - -1, // 10000011 - -1, // 10000100 - -1, // 10000101 - -1, // 10000110 - -1, // 10000111 - -1, // 10001000 - -1, // 10001001 - -1, // 10001010 - -1, // 10001011 - -1, // 10001100 - -1, // 10001101 - -1, // 10001110 - -1, // 10001111 - -1, // 10010000 - -1, // 10010001 - -1, // 10010010 - -1, // 10010011 - -1, // 10010100 - -1, // 10010101 - -1, // 10010110 - -1, // 10010111 - -1, // 10011000 - -1, // 10011001 - -1, // 10011010 - -1, // 10011011 - -1, // 10011100 - -1, // 10011101 - -1, // 10011110 - -1, // 10011111 - -1, // 10100000 - -1, // 10100001 - -1, // 10100010 - -1, // 10100011 - -1, // 10100100 - -1, // 10100101 - -1, // 10100110 - -1, // 10100111 - -1, // 10101000 - -1, // 10101001 - -1, // 10101010 - -1, // 10101011 - -1, // 10101100 - -1, // 10101101 - -1, // 10101110 - -1, // 10101111 - -1, // 10110000 - -1, // 10110001 - -1, // 10110010 - -1, // 10110011 - -1, // 10110100 - -1, // 10110101 - -1, // 10110110 - -1, // 10110111 - -1, // 10111000 - -1, // 10111001 - -1, // 10111010 - -1, // 10111011 - -1, // 10111100 - -1, // 10111101 - -1, // 10111110 - -1, // 10111111 - -1, // 11000000 - -1, // 11000001 - -1, // 11000010 - -1, // 11000011 - -1, // 11000100 - -1, // 11000101 - -1, // 11000110 - -1, // 11000111 - -1, // 11001000 - -1, // 11001001 - -1, // 11001010 - -1, // 11001011 - -1, // 11001100 - -1, // 11001101 - -1, // 11001110 - -1, // 11001111 - -1, // 11010000 - -1, // 11010001 - -1, // 11010010 - -1, // 11010011 - -1, // 11010100 - -1, // 11010101 - -1, // 11010110 - -1, // 11010111 - -1, // 11011000 - -1, // 11011001 - -1, // 11011010 - -1, // 11011011 - -1, // 11011100 - -1, // 11011101 - -1, // 11011110 - -1, // 11011111 - -1, // 11100000 - -1, // 11100001 - -1, // 11100010 - -1, // 11100011 - -1, // 11100100 - -1, // 11100101 - -1, // 11100110 - -1, // 11100111 - -1, // 11101000 - -1, // 11101001 - -1, // 11101010 - -1, // 11101011 - -1, // 11101100 - -1, // 11101101 - -1, // 11101110 - -1, // 11101111 - -1, // 11110000 - -1, // 11110001 - -1, // 11110010 - -1, // 11110011 - -1, // 11110100 - -1, // 11110101 - -1, // 11110110 - -1, // 11110111 - -1, // 11111000 - -1, // 11111001 - -1, // 11111010 - -1, // 11111011 - -1, // 11111100 - -1, // 11111101 - -1, // 11111110 - 0 // 11111111 - }; - static char Perms[256][8] = { - { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000000 - { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000001 - { 1, 0, 2, 3, 4, 5, 6, 7 }, // 00000010 - { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000011 - { 1, 2, 0, 3, 4, 5, 6, 7 }, // 00000100 - { 0, 2, 1, 3, 4, 5, 6, 7 }, // 00000101 - { 2, 0, 1, 3, 4, 5, 6, 7 }, // 00000110 - { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00000111 - { 1, 2, 3, 0, 4, 5, 6, 7 }, // 00001000 - { 0, 2, 3, 1, 4, 5, 6, 7 }, // 00001001 - { 2, 0, 3, 1, 4, 5, 6, 7 }, // 00001010 - { 0, 1, 3, 2, 4, 5, 6, 7 }, // 00001011 - { 2, 3, 0, 1, 4, 5, 6, 7 }, // 00001100 - { 0, 3, 1, 2, 4, 5, 6, 7 }, // 00001101 - { 3, 0, 1, 2, 4, 5, 6, 7 }, // 00001110 - { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00001111 - { 1, 2, 3, 4, 0, 5, 6, 7 }, // 00010000 - { 0, 2, 3, 4, 1, 5, 6, 7 }, // 00010001 - { 2, 0, 3, 4, 1, 5, 6, 7 }, // 00010010 - { 0, 1, 3, 4, 2, 5, 6, 7 }, // 00010011 - { 2, 3, 0, 4, 1, 5, 6, 7 }, // 00010100 - { 0, 3, 1, 4, 2, 5, 6, 7 }, // 00010101 - { 3, 0, 1, 4, 2, 5, 6, 7 }, // 00010110 - { 0, 1, 2, 4, 3, 5, 6, 7 }, // 00010111 - { 2, 3, 4, 0, 1, 5, 6, 7 }, // 00011000 - { 0, 3, 4, 1, 2, 5, 6, 7 }, // 00011001 - { 3, 0, 4, 1, 2, 5, 6, 7 }, // 00011010 - { 0, 1, 4, 2, 3, 5, 6, 7 }, // 00011011 - { 3, 4, 0, 1, 2, 5, 6, 7 }, // 00011100 - { 0, 4, 1, 2, 3, 5, 6, 7 }, // 00011101 - { 4, 0, 1, 2, 3, 5, 6, 7 }, // 00011110 - { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00011111 - { 1, 2, 3, 4, 5, 0, 6, 7 }, // 00100000 - { 0, 2, 3, 4, 5, 1, 6, 7 }, // 00100001 - { 2, 0, 3, 4, 5, 1, 6, 7 }, // 00100010 - { 0, 1, 3, 4, 5, 2, 6, 7 }, // 00100011 - { 2, 3, 0, 4, 5, 1, 6, 7 }, // 00100100 - { 0, 3, 1, 4, 5, 2, 6, 7 }, // 00100101 - { 3, 0, 1, 4, 5, 2, 6, 7 }, // 00100110 - { 0, 1, 2, 4, 5, 3, 6, 7 }, // 00100111 - { 2, 3, 4, 0, 5, 1, 6, 7 }, // 00101000 - { 0, 3, 4, 1, 5, 2, 6, 7 }, // 00101001 - { 3, 0, 4, 1, 5, 2, 6, 7 }, // 00101010 - { 0, 1, 4, 2, 5, 3, 6, 7 }, // 00101011 - { 3, 4, 0, 1, 5, 2, 6, 7 }, // 00101100 - { 0, 4, 1, 2, 5, 3, 6, 7 }, // 00101101 - { 4, 0, 1, 2, 5, 3, 6, 7 }, // 00101110 - { 0, 1, 2, 3, 5, 4, 6, 7 }, // 00101111 - { 2, 3, 4, 5, 0, 1, 6, 7 }, // 00110000 - { 0, 3, 4, 5, 1, 2, 6, 7 }, // 00110001 - { 3, 0, 4, 5, 1, 2, 6, 7 }, // 00110010 - { 0, 1, 4, 5, 2, 3, 6, 7 }, // 00110011 - { 3, 4, 0, 5, 1, 2, 6, 7 }, // 00110100 - { 0, 4, 1, 5, 2, 3, 6, 7 }, // 00110101 - { 4, 0, 1, 5, 2, 3, 6, 7 }, // 00110110 - { 0, 1, 2, 5, 3, 4, 6, 7 }, // 00110111 - { 3, 4, 5, 0, 1, 2, 6, 7 }, // 00111000 - { 0, 4, 5, 1, 2, 3, 6, 7 }, // 00111001 - { 4, 0, 5, 1, 2, 3, 6, 7 }, // 00111010 - { 0, 1, 5, 2, 3, 4, 6, 7 }, // 00111011 - { 4, 5, 0, 1, 2, 3, 6, 7 }, // 00111100 - { 0, 5, 1, 2, 3, 4, 6, 7 }, // 00111101 - { 5, 0, 1, 2, 3, 4, 6, 7 }, // 00111110 - { 0, 1, 2, 3, 4, 5, 6, 7 }, // 00111111 - { 1, 2, 3, 4, 5, 6, 0, 7 }, // 01000000 - { 0, 2, 3, 4, 5, 6, 1, 7 }, // 01000001 - { 2, 0, 3, 4, 5, 6, 1, 7 }, // 01000010 - { 0, 1, 3, 4, 5, 6, 2, 7 }, // 01000011 - { 2, 3, 0, 4, 5, 6, 1, 7 }, // 01000100 - { 0, 3, 1, 4, 5, 6, 2, 7 }, // 01000101 - { 3, 0, 1, 4, 5, 6, 2, 7 }, // 01000110 - { 0, 1, 2, 4, 5, 6, 3, 7 }, // 01000111 - { 2, 3, 4, 0, 5, 6, 1, 7 }, // 01001000 - { 0, 3, 4, 1, 5, 6, 2, 7 }, // 01001001 - { 3, 0, 4, 1, 5, 6, 2, 7 }, // 01001010 - { 0, 1, 4, 2, 5, 6, 3, 7 }, // 01001011 - { 3, 4, 0, 1, 5, 6, 2, 7 }, // 01001100 - { 0, 4, 1, 2, 5, 6, 3, 7 }, // 01001101 - { 4, 0, 1, 2, 5, 6, 3, 7 }, // 01001110 - { 0, 1, 2, 3, 5, 6, 4, 7 }, // 01001111 - { 2, 3, 4, 5, 0, 6, 1, 7 }, // 01010000 - { 0, 3, 4, 5, 1, 6, 2, 7 }, // 01010001 - { 3, 0, 4, 5, 1, 6, 2, 7 }, // 01010010 - { 0, 1, 4, 5, 2, 6, 3, 7 }, // 01010011 - { 3, 4, 0, 5, 1, 6, 2, 7 }, // 01010100 - { 0, 4, 1, 5, 2, 6, 3, 7 }, // 01010101 - { 4, 0, 1, 5, 2, 6, 3, 7 }, // 01010110 - { 0, 1, 2, 5, 3, 6, 4, 7 }, // 01010111 - { 3, 4, 5, 0, 1, 6, 2, 7 }, // 01011000 - { 0, 4, 5, 1, 2, 6, 3, 7 }, // 01011001 - { 4, 0, 5, 1, 2, 6, 3, 7 }, // 01011010 - { 0, 1, 5, 2, 3, 6, 4, 7 }, // 01011011 - { 4, 5, 0, 1, 2, 6, 3, 7 }, // 01011100 - { 0, 5, 1, 2, 3, 6, 4, 7 }, // 01011101 - { 5, 0, 1, 2, 3, 6, 4, 7 }, // 01011110 - { 0, 1, 2, 3, 4, 6, 5, 7 }, // 01011111 - { 2, 3, 4, 5, 6, 0, 1, 7 }, // 01100000 - { 0, 3, 4, 5, 6, 1, 2, 7 }, // 01100001 - { 3, 0, 4, 5, 6, 1, 2, 7 }, // 01100010 - { 0, 1, 4, 5, 6, 2, 3, 7 }, // 01100011 - { 3, 4, 0, 5, 6, 1, 2, 7 }, // 01100100 - { 0, 4, 1, 5, 6, 2, 3, 7 }, // 01100101 - { 4, 0, 1, 5, 6, 2, 3, 7 }, // 01100110 - { 0, 1, 2, 5, 6, 3, 4, 7 }, // 01100111 - { 3, 4, 5, 0, 6, 1, 2, 7 }, // 01101000 - { 0, 4, 5, 1, 6, 2, 3, 7 }, // 01101001 - { 4, 0, 5, 1, 6, 2, 3, 7 }, // 01101010 - { 0, 1, 5, 2, 6, 3, 4, 7 }, // 01101011 - { 4, 5, 0, 1, 6, 2, 3, 7 }, // 01101100 - { 0, 5, 1, 2, 6, 3, 4, 7 }, // 01101101 - { 5, 0, 1, 2, 6, 3, 4, 7 }, // 01101110 - { 0, 1, 2, 3, 6, 4, 5, 7 }, // 01101111 - { 3, 4, 5, 6, 0, 1, 2, 7 }, // 01110000 - { 0, 4, 5, 6, 1, 2, 3, 7 }, // 01110001 - { 4, 0, 5, 6, 1, 2, 3, 7 }, // 01110010 - { 0, 1, 5, 6, 2, 3, 4, 7 }, // 01110011 - { 4, 5, 0, 6, 1, 2, 3, 7 }, // 01110100 - { 0, 5, 1, 6, 2, 3, 4, 7 }, // 01110101 - { 5, 0, 1, 6, 2, 3, 4, 7 }, // 01110110 - { 0, 1, 2, 6, 3, 4, 5, 7 }, // 01110111 - { 4, 5, 6, 0, 1, 2, 3, 7 }, // 01111000 - { 0, 5, 6, 1, 2, 3, 4, 7 }, // 01111001 - { 5, 0, 6, 1, 2, 3, 4, 7 }, // 01111010 - { 0, 1, 6, 2, 3, 4, 5, 7 }, // 01111011 - { 5, 6, 0, 1, 2, 3, 4, 7 }, // 01111100 - { 0, 6, 1, 2, 3, 4, 5, 7 }, // 01111101 - { 6, 0, 1, 2, 3, 4, 5, 7 }, // 01111110 - { 0, 1, 2, 3, 4, 5, 6, 7 }, // 01111111 - { 1, 2, 3, 4, 5, 6, 7, 0 }, // 10000000 - { 0, 2, 3, 4, 5, 6, 7, 1 }, // 10000001 - { 2, 0, 3, 4, 5, 6, 7, 1 }, // 10000010 - { 0, 1, 3, 4, 5, 6, 7, 2 }, // 10000011 - { 2, 3, 0, 4, 5, 6, 7, 1 }, // 10000100 - { 0, 3, 1, 4, 5, 6, 7, 2 }, // 10000101 - { 3, 0, 1, 4, 5, 6, 7, 2 }, // 10000110 - { 0, 1, 2, 4, 5, 6, 7, 3 }, // 10000111 - { 2, 3, 4, 0, 5, 6, 7, 1 }, // 10001000 - { 0, 3, 4, 1, 5, 6, 7, 2 }, // 10001001 - { 3, 0, 4, 1, 5, 6, 7, 2 }, // 10001010 - { 0, 1, 4, 2, 5, 6, 7, 3 }, // 10001011 - { 3, 4, 0, 1, 5, 6, 7, 2 }, // 10001100 - { 0, 4, 1, 2, 5, 6, 7, 3 }, // 10001101 - { 4, 0, 1, 2, 5, 6, 7, 3 }, // 10001110 - { 0, 1, 2, 3, 5, 6, 7, 4 }, // 10001111 - { 2, 3, 4, 5, 0, 6, 7, 1 }, // 10010000 - { 0, 3, 4, 5, 1, 6, 7, 2 }, // 10010001 - { 3, 0, 4, 5, 1, 6, 7, 2 }, // 10010010 - { 0, 1, 4, 5, 2, 6, 7, 3 }, // 10010011 - { 3, 4, 0, 5, 1, 6, 7, 2 }, // 10010100 - { 0, 4, 1, 5, 2, 6, 7, 3 }, // 10010101 - { 4, 0, 1, 5, 2, 6, 7, 3 }, // 10010110 - { 0, 1, 2, 5, 3, 6, 7, 4 }, // 10010111 - { 3, 4, 5, 0, 1, 6, 7, 2 }, // 10011000 - { 0, 4, 5, 1, 2, 6, 7, 3 }, // 10011001 - { 4, 0, 5, 1, 2, 6, 7, 3 }, // 10011010 - { 0, 1, 5, 2, 3, 6, 7, 4 }, // 10011011 - { 4, 5, 0, 1, 2, 6, 7, 3 }, // 10011100 - { 0, 5, 1, 2, 3, 6, 7, 4 }, // 10011101 - { 5, 0, 1, 2, 3, 6, 7, 4 }, // 10011110 - { 0, 1, 2, 3, 4, 6, 7, 5 }, // 10011111 - { 2, 3, 4, 5, 6, 0, 7, 1 }, // 10100000 - { 0, 3, 4, 5, 6, 1, 7, 2 }, // 10100001 - { 3, 0, 4, 5, 6, 1, 7, 2 }, // 10100010 - { 0, 1, 4, 5, 6, 2, 7, 3 }, // 10100011 - { 3, 4, 0, 5, 6, 1, 7, 2 }, // 10100100 - { 0, 4, 1, 5, 6, 2, 7, 3 }, // 10100101 - { 4, 0, 1, 5, 6, 2, 7, 3 }, // 10100110 - { 0, 1, 2, 5, 6, 3, 7, 4 }, // 10100111 - { 3, 4, 5, 0, 6, 1, 7, 2 }, // 10101000 - { 0, 4, 5, 1, 6, 2, 7, 3 }, // 10101001 - { 4, 0, 5, 1, 6, 2, 7, 3 }, // 10101010 - { 0, 1, 5, 2, 6, 3, 7, 4 }, // 10101011 - { 4, 5, 0, 1, 6, 2, 7, 3 }, // 10101100 - { 0, 5, 1, 2, 6, 3, 7, 4 }, // 10101101 - { 5, 0, 1, 2, 6, 3, 7, 4 }, // 10101110 - { 0, 1, 2, 3, 6, 4, 7, 5 }, // 10101111 - { 3, 4, 5, 6, 0, 1, 7, 2 }, // 10110000 - { 0, 4, 5, 6, 1, 2, 7, 3 }, // 10110001 - { 4, 0, 5, 6, 1, 2, 7, 3 }, // 10110010 - { 0, 1, 5, 6, 2, 3, 7, 4 }, // 10110011 - { 4, 5, 0, 6, 1, 2, 7, 3 }, // 10110100 - { 0, 5, 1, 6, 2, 3, 7, 4 }, // 10110101 - { 5, 0, 1, 6, 2, 3, 7, 4 }, // 10110110 - { 0, 1, 2, 6, 3, 4, 7, 5 }, // 10110111 - { 4, 5, 6, 0, 1, 2, 7, 3 }, // 10111000 - { 0, 5, 6, 1, 2, 3, 7, 4 }, // 10111001 - { 5, 0, 6, 1, 2, 3, 7, 4 }, // 10111010 - { 0, 1, 6, 2, 3, 4, 7, 5 }, // 10111011 - { 5, 6, 0, 1, 2, 3, 7, 4 }, // 10111100 - { 0, 6, 1, 2, 3, 4, 7, 5 }, // 10111101 - { 6, 0, 1, 2, 3, 4, 7, 5 }, // 10111110 - { 0, 1, 2, 3, 4, 5, 7, 6 }, // 10111111 - { 2, 3, 4, 5, 6, 7, 0, 1 }, // 11000000 - { 0, 3, 4, 5, 6, 7, 1, 2 }, // 11000001 - { 3, 0, 4, 5, 6, 7, 1, 2 }, // 11000010 - { 0, 1, 4, 5, 6, 7, 2, 3 }, // 11000011 - { 3, 4, 0, 5, 6, 7, 1, 2 }, // 11000100 - { 0, 4, 1, 5, 6, 7, 2, 3 }, // 11000101 - { 4, 0, 1, 5, 6, 7, 2, 3 }, // 11000110 - { 0, 1, 2, 5, 6, 7, 3, 4 }, // 11000111 - { 3, 4, 5, 0, 6, 7, 1, 2 }, // 11001000 - { 0, 4, 5, 1, 6, 7, 2, 3 }, // 11001001 - { 4, 0, 5, 1, 6, 7, 2, 3 }, // 11001010 - { 0, 1, 5, 2, 6, 7, 3, 4 }, // 11001011 - { 4, 5, 0, 1, 6, 7, 2, 3 }, // 11001100 - { 0, 5, 1, 2, 6, 7, 3, 4 }, // 11001101 - { 5, 0, 1, 2, 6, 7, 3, 4 }, // 11001110 - { 0, 1, 2, 3, 6, 7, 4, 5 }, // 11001111 - { 3, 4, 5, 6, 0, 7, 1, 2 }, // 11010000 - { 0, 4, 5, 6, 1, 7, 2, 3 }, // 11010001 - { 4, 0, 5, 6, 1, 7, 2, 3 }, // 11010010 - { 0, 1, 5, 6, 2, 7, 3, 4 }, // 11010011 - { 4, 5, 0, 6, 1, 7, 2, 3 }, // 11010100 - { 0, 5, 1, 6, 2, 7, 3, 4 }, // 11010101 - { 5, 0, 1, 6, 2, 7, 3, 4 }, // 11010110 - { 0, 1, 2, 6, 3, 7, 4, 5 }, // 11010111 - { 4, 5, 6, 0, 1, 7, 2, 3 }, // 11011000 - { 0, 5, 6, 1, 2, 7, 3, 4 }, // 11011001 - { 5, 0, 6, 1, 2, 7, 3, 4 }, // 11011010 - { 0, 1, 6, 2, 3, 7, 4, 5 }, // 11011011 - { 5, 6, 0, 1, 2, 7, 3, 4 }, // 11011100 - { 0, 6, 1, 2, 3, 7, 4, 5 }, // 11011101 - { 6, 0, 1, 2, 3, 7, 4, 5 }, // 11011110 - { 0, 1, 2, 3, 4, 7, 5, 6 }, // 11011111 - { 3, 4, 5, 6, 7, 0, 1, 2 }, // 11100000 - { 0, 4, 5, 6, 7, 1, 2, 3 }, // 11100001 - { 4, 0, 5, 6, 7, 1, 2, 3 }, // 11100010 - { 0, 1, 5, 6, 7, 2, 3, 4 }, // 11100011 - { 4, 5, 0, 6, 7, 1, 2, 3 }, // 11100100 - { 0, 5, 1, 6, 7, 2, 3, 4 }, // 11100101 - { 5, 0, 1, 6, 7, 2, 3, 4 }, // 11100110 - { 0, 1, 2, 6, 7, 3, 4, 5 }, // 11100111 - { 4, 5, 6, 0, 7, 1, 2, 3 }, // 11101000 - { 0, 5, 6, 1, 7, 2, 3, 4 }, // 11101001 - { 5, 0, 6, 1, 7, 2, 3, 4 }, // 11101010 - { 0, 1, 6, 2, 7, 3, 4, 5 }, // 11101011 - { 5, 6, 0, 1, 7, 2, 3, 4 }, // 11101100 - { 0, 6, 1, 2, 7, 3, 4, 5 }, // 11101101 - { 6, 0, 1, 2, 7, 3, 4, 5 }, // 11101110 - { 0, 1, 2, 3, 7, 4, 5, 6 }, // 11101111 - { 4, 5, 6, 7, 0, 1, 2, 3 }, // 11110000 - { 0, 5, 6, 7, 1, 2, 3, 4 }, // 11110001 - { 5, 0, 6, 7, 1, 2, 3, 4 }, // 11110010 - { 0, 1, 6, 7, 2, 3, 4, 5 }, // 11110011 - { 5, 6, 0, 7, 1, 2, 3, 4 }, // 11110100 - { 0, 6, 1, 7, 2, 3, 4, 5 }, // 11110101 - { 6, 0, 1, 7, 2, 3, 4, 5 }, // 11110110 - { 0, 1, 2, 7, 3, 4, 5, 6 }, // 11110111 - { 5, 6, 7, 0, 1, 2, 3, 4 }, // 11111000 - { 0, 6, 7, 1, 2, 3, 4, 5 }, // 11111001 - { 6, 0, 7, 1, 2, 3, 4, 5 }, // 11111010 - { 0, 1, 7, 2, 3, 4, 5, 6 }, // 11111011 - { 6, 7, 0, 1, 2, 3, 4, 5 }, // 11111100 - { 0, 7, 1, 2, 3, 4, 5, 6 }, // 11111101 - { 7, 0, 1, 2, 3, 4, 5, 6 }, // 11111110 - { 0, 1, 2, 3, 4, 5, 6, 7 } // 11111111 - }; - - assert( uPhase > 0 && uPhase < (unsigned)(1 << nVars) ); - - // the same function - if ( Cases[uPhase] == 0 ) - { - int i; - for ( i = 0; i < nWords; i++ ) - puTruthR[i] = puTruth[i]; - return; - } - - // an elementary variable - if ( Cases[uPhase] > 0 ) - { - int i; - for ( i = 0; i < nWords; i++ ) - puTruthR[i] = uTruths[Cases[uPhase]][i]; - return; - } - - // truth table takes one word - if ( nWords == 1 ) - { - int i, k, nMints, iRes; - char * pPerm = Perms[uPhase]; - puTruthR[0] = 0; - nMints = (1 << nVars); - for ( i = 0; i < nMints; i++ ) - if ( puTruth[0] & (1 << i) ) - { - for ( iRes = 0, k = 0; k < nVars; k++ ) - if ( i & (1 << pPerm[k]) ) - iRes |= (1 << k); - puTruthR[0] |= (1 << iRes); - } - return; - } - else if ( nWords == 2 ) - { - int i, k, iRes; - char * pPerm = Perms[uPhase]; - puTruthR[0] = puTruthR[1] = 0; - for ( i = 0; i < 32; i++ ) - { - if ( puTruth[0] & (1 << i) ) - { - for ( iRes = 0, k = 0; k < 6; k++ ) - if ( i & (1 << pPerm[k]) ) - iRes |= (1 << k); - if ( iRes < 32 ) - puTruthR[0] |= (1 << iRes); - else - puTruthR[1] |= (1 << (iRes-32)); - } - } - for ( ; i < 64; i++ ) - { - if ( puTruth[1] & (1 << (i-32)) ) - { - for ( iRes = 0, k = 0; k < 6; k++ ) - if ( i & (1 << pPerm[k]) ) - iRes |= (1 << k); - if ( iRes < 32 ) - puTruthR[0] |= (1 << iRes); - else - puTruthR[1] |= (1 << (iRes-32)); - } - } - } - // truth table takes more than one word - else - { - int i, k, nMints, iRes; - char * pPerm = Perms[uPhase]; - for ( i = 0; i < nWords; i++ ) - puTruthR[i] = 0; - nMints = (1 << nVars); - for ( i = 0; i < nMints; i++ ) - if ( puTruth[i>>5] & (1 << (i&31)) ) - { - for ( iRes = 0, k = 0; k < 5; k++ ) - if ( i & (1 << pPerm[k]) ) - iRes |= (1 << k); - puTruthR[iRes>>5] |= (1 << (iRes&31)); - } - } -} - -/**Function************************************************************* - - Synopsis [Allocated lookup table for truth table permutation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned short ** Extra_TruthPerm43() -{ - unsigned short ** pTable; - unsigned uTruth; - int i, k; - pTable = (unsigned short **)Extra_ArrayAlloc( 256, 16, 2 ); - for ( i = 0; i < 256; i++ ) - { - uTruth = (i << 8) | i; - for ( k = 0; k < 16; k++ ) - pTable[i][k] = Extra_TruthPerm4One( uTruth, k ); - } - return pTable; -} - -/**Function************************************************************* - - Synopsis [Allocated lookup table for truth table permutation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned ** Extra_TruthPerm53() -{ - unsigned ** pTable; - unsigned uTruth; - int i, k; - pTable = (unsigned **)Extra_ArrayAlloc( 256, 32, 4 ); - for ( i = 0; i < 256; i++ ) - { - uTruth = (i << 24) | (i << 16) | (i << 8) | i; - for ( k = 0; k < 32; k++ ) - pTable[i][k] = Extra_TruthPerm5One( uTruth, k ); - } - return pTable; -} - -/**Function************************************************************* - - Synopsis [Allocated lookup table for truth table permutation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned ** Extra_TruthPerm54() -{ - unsigned ** pTable; - unsigned uTruth; - int i; - pTable = (unsigned **)Extra_ArrayAlloc( 256*256, 4, 4 ); - for ( i = 0; i < 256*256; i++ ) - { - uTruth = (i << 16) | i; - pTable[i][0] = Extra_TruthPerm5One( uTruth, 31-8 ); - pTable[i][1] = Extra_TruthPerm5One( uTruth, 31-4 ); - pTable[i][2] = Extra_TruthPerm5One( uTruth, 31-2 ); - pTable[i][3] = Extra_TruthPerm5One( uTruth, 31-1 ); - } - return pTable; -} - -/**Function************************************************************* - - Synopsis [Allocated lookup table for truth table permutation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned ** Extra_TruthPerm63() -{ - unsigned ** pTable; - unsigned uTruth[2]; - int i, k; - pTable = (unsigned **)Extra_ArrayAlloc( 256, 64, 8 ); - for ( i = 0; i < 256; i++ ) - { - uTruth[0] = (i << 24) | (i << 16) | (i << 8) | i; - uTruth[1] = uTruth[0]; - for ( k = 0; k < 64; k++ ) - Extra_TruthPerm6One( uTruth, k, &pTable[i][k] ); - } - return pTable; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the elementary truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned ** Extra_Truths8() -{ - static unsigned uTruths[8][8] = { - { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, - { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, - { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, - { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, - { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, - { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, - { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, - { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } - }; - static unsigned * puResult[8] = { - uTruths[0], uTruths[1], uTruths[2], uTruths[3], uTruths[4], uTruths[5], uTruths[6], uTruths[7] - }; - return (unsigned **)puResult; -} - -/**Function************************************************************* - - Synopsis [Bubble-sorts components by scores in increasing order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_BubbleSort( int Order[], int Costs[], int nSize, int fIncreasing ) -{ - int i, Temp, fChanges; - assert( nSize < 1000 ); - for ( i = 0; i < nSize; i++ ) - Order[i] = i; - if ( fIncreasing ) - { - do { - fChanges = 0; - for ( i = 0; i < nSize - 1; i++ ) - { - if ( Costs[Order[i]] <= Costs[Order[i+1]] ) - continue; - Temp = Order[i]; - Order[i] = Order[i+1]; - Order[i+1] = Temp; - fChanges = 1; - } - } while ( fChanges ); - } - else - { - do { - fChanges = 0; - for ( i = 0; i < nSize - 1; i++ ) - { - if ( Costs[Order[i]] >= Costs[Order[i+1]] ) - continue; - Temp = Order[i]; - Order[i] = Order[i+1]; - Order[i+1] = Temp; - fChanges = 1; - } - } while ( fChanges ); - } -} - -/**Function************************************************************* - - Synopsis [Returns the smallest prime larger than the number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned int Cudd_PrimeCopy( unsigned int p) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - -/*---------------------------------------------------------------------------*/ -/* Definition of internal functions */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Definition of static Functions */ -/*---------------------------------------------------------------------------*/ - - -/**Function************************************************************* - - Synopsis [Computes the permutation table for 8 variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthExpandGeneratePermTable() -{ - int i, k, nOnes, Last1, First0; - int iOne, iZero; - - printf( "\nstatic char Cases[256] = {\n" ); - for ( i = 0; i < 256; i++ ) - { - nOnes = 0; - Last1 = First0 = -1; - for ( k = 0; k < 8; k++ ) - { - if ( i & (1 << k) ) - { - nOnes++; - Last1 = k; - } - else if ( First0 == -1 ) - First0 = k; - } - if ( Last1 + 1 == First0 || i == 255 ) - printf( " %d%s", 0, (i==255? " ":",") ); - else if ( nOnes == 1 ) - printf( " %d,", Last1 ); - else - printf( " -%d,", 1 ); - printf( " // " ); - Extra_PrintBinary( stdout, (unsigned*)&i, 8 ); - printf( "\n" ); - } - printf( "};\n" ); - - printf( "\nstatic char Perms[256][8] = {\n" ); - for ( i = 0; i < 256; i++ ) - { - printf( " {" ); - nOnes = 0; - for ( k = 0; k < 8; k++ ) - if ( i & (1 << k) ) - nOnes++; - iOne = 0; - iZero = nOnes; - for ( k = 0; k < 8; k++ ) - if ( i & (1 << k) ) - printf( "%s %d", (k==0? "":","), iOne++ ); - else - printf( "%s %d", (k==0? "":","), iZero++ ); - assert( iOne + iZero == 8 ); - printf( " }%s // ", (i==255? " ":",") ); - Extra_PrintBinary( stdout, (unsigned*)&i, 8 ); - printf( "\n" ); - } - printf( "};\n" ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/extra/extraUtilProgress.c b/src/misc/extra/extraUtilProgress.c deleted file mode 100644 index 6b6d5132..00000000 --- a/src/misc/extra/extraUtilProgress.c +++ /dev/null @@ -1,176 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraUtilProgress.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [Progress bar.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraUtilProgress.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct ProgressBarStruct -{ - int nItemsNext; // the number of items for the next update of the progress bar - int nItemsTotal; // the total number of items - int posTotal; // the total number of positions - int posCur; // the current position - FILE * pFile; // the output stream -}; - -static void Extra_ProgressBarShow( ProgressBar * p, char * pString ); -static void Extra_ProgressBarClean( ProgressBar * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the progress bar.] - - Description [The first parameter is the output stream (pFile), where - the progress is printed. The current printing position should be the - first one on the given line. The second parameters is the total - number of items that correspond to 100% position of the progress bar.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -ProgressBar * Extra_ProgressBarStart( FILE * pFile, int nItemsTotal ) -{ - ProgressBar * p; - extern int Abc_FrameShowProgress( void * p ); - extern void * Abc_FrameGetGlobalFrame(); - - if ( !Abc_FrameShowProgress(Abc_FrameGetGlobalFrame()) ) return NULL; - p = ALLOC( ProgressBar, 1 ); - memset( p, 0, sizeof(ProgressBar) ); - p->pFile = pFile; - p->nItemsTotal = nItemsTotal; - p->posTotal = 78; - p->posCur = 1; - p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); - Extra_ProgressBarShow( p, NULL ); - return p; -} - -/**Function************************************************************* - - Synopsis [Updates the progress bar.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ProgressBarUpdate_int( ProgressBar * p, int nItemsCur, char * pString ) -{ - if ( p == NULL ) return; - if ( nItemsCur < p->nItemsNext ) - return; - if ( nItemsCur >= p->nItemsTotal ) - { - p->posCur = 78; - p->nItemsNext = 0x7FFFFFFF; - } - else - { - p->posCur += 7; - p->nItemsNext = (int)((7.0+p->posCur)*p->nItemsTotal/p->posTotal); - } - Extra_ProgressBarShow( p, pString ); -} - - -/**Function************************************************************* - - Synopsis [Stops the progress bar.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ProgressBarStop( ProgressBar * p ) -{ - if ( p == NULL ) return; - Extra_ProgressBarClean( p ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Prints the progress bar of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ProgressBarShow( ProgressBar * p, char * pString ) -{ - int i; - if ( p == NULL ) return; - if ( pString ) - fprintf( p->pFile, "%s ", pString ); - for ( i = (pString? strlen(pString) + 1 : 0); i < p->posCur; i++ ) - fprintf( p->pFile, "-" ); - if ( i == p->posCur ) - fprintf( p->pFile, ">" ); - for ( i++ ; i <= p->posTotal; i++ ) - fprintf( p->pFile, " " ); - fprintf( p->pFile, "\r" ); - fflush( stdout ); -} - -/**Function************************************************************* - - Synopsis [Cleans the progress bar before quitting.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_ProgressBarClean( ProgressBar * p ) -{ - int i; - if ( p == NULL ) return; - for ( i = 0; i <= p->posTotal; i++ ) - fprintf( p->pFile, " " ); - fprintf( p->pFile, "\r" ); - fflush( stdout ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/extra/extraUtilReader.c b/src/misc/extra/extraUtilReader.c deleted file mode 100644 index c165b989..00000000 --- a/src/misc/extra/extraUtilReader.c +++ /dev/null @@ -1,383 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraUtilReader.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [File reading utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraUtilReader.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include "extra.h" -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define EXTRA_BUFFER_SIZE 4*1048576 // 1M - size of the data chunk stored in memory -#define EXTRA_OFFSET_SIZE 4096 // 4K - load new data when less than this is left - -#define EXTRA_MINIMUM(a,b) (((a) < (b))? (a) : (b)) - -struct Extra_FileReader_t_ -{ - // the input file - char * pFileName; // the input file name - FILE * pFile; // the input file pointer - int nFileSize; // the total number of bytes in the file - int nFileRead; // the number of bytes currently read from file - // info about processing different types of input chars - char pCharMap[256]; // the character map - // temporary storage for data - char * pBuffer; // the buffer - int nBufferSize; // the size of the buffer - char * pBufferCur; // the current reading position - char * pBufferEnd; // the first position not used by currently loaded data - char * pBufferStop; // the position where loading new data will be done - // tokens given to the user - Vec_Ptr_t * vTokens; // the vector of tokens returned to the user - Vec_Int_t * vLines; // the vector of line numbers for each token - int nLineCounter; // the counter of lines processed - // status of the parser - int fStop; // this flag goes high when the end of file is reached -}; - -// character types -typedef enum { - EXTRA_CHAR_COMMENT, // a character that begins the comment - EXTRA_CHAR_NORMAL, // a regular character - EXTRA_CHAR_STOP, // a character that delimits a series of tokens - EXTRA_CHAR_CLEAN // a character that should be cleaned -} Extra_CharType_t; - -// the static functions -static void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ); -static void Extra_FileReaderReload( Extra_FileReader_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the file reader.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName, - char * pCharsComment, char * pCharsStop, char * pCharsClean ) -{ - Extra_FileReader_t * p; - FILE * pFile; - char * pChar; - int nCharsToRead; - // check if the file can be opened - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Extra_FileReaderAlloc(): Cannot open input file \"%s\".\n", pFileName ); - return NULL; - } - // start the file reader - p = ALLOC( Extra_FileReader_t, 1 ); - memset( p, 0, sizeof(Extra_FileReader_t) ); - p->pFileName = pFileName; - p->pFile = pFile; - // set the character map - memset( p->pCharMap, EXTRA_CHAR_NORMAL, 256 ); - for ( pChar = pCharsComment; *pChar; pChar++ ) - p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_COMMENT; - for ( pChar = pCharsStop; *pChar; pChar++ ) - p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_STOP; - for ( pChar = pCharsClean; *pChar; pChar++ ) - p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_CLEAN; - // get the file size, in bytes - fseek( pFile, 0, SEEK_END ); - p->nFileSize = ftell( pFile ); - rewind( pFile ); - // allocate the buffer - p->pBuffer = ALLOC( char, EXTRA_BUFFER_SIZE+1 ); - p->nBufferSize = EXTRA_BUFFER_SIZE; - p->pBufferCur = p->pBuffer; - // determine how many chars to read - nCharsToRead = EXTRA_MINIMUM(p->nFileSize, EXTRA_BUFFER_SIZE); - // load the first part into the buffer - fread( p->pBuffer, nCharsToRead, 1, p->pFile ); - p->nFileRead = nCharsToRead; - // set the ponters to the end and the stopping point - p->pBufferEnd = p->pBuffer + nCharsToRead; - p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE; - // start the arrays - p->vTokens = Vec_PtrAlloc( 100 ); - p->vLines = Vec_IntAlloc( 100 ); - p->nLineCounter = 1; // 1-based line counting - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the file reader.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_FileReaderFree( Extra_FileReader_t * p ) -{ - if ( p->pFile ) - fclose( p->pFile ); - FREE( p->pBuffer ); - Vec_PtrFree( p->vTokens ); - Vec_IntFree( p->vLines ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Returns the file size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_FileReaderGetFileName( Extra_FileReader_t * p ) -{ - return p->pFileName; -} - -/**Function************************************************************* - - Synopsis [Returns the file size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_FileReaderGetFileSize( Extra_FileReader_t * p ) -{ - return p->nFileSize; -} - -/**Function************************************************************* - - Synopsis [Returns the current reading position.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p ) -{ - return p->nFileRead - (p->pBufferEnd - p->pBufferCur); -} - -/**Function************************************************************* - - Synopsis [Returns the line number for the given token.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken ) -{ - assert( iToken >= 0 && iToken < p->vTokens->nSize ); - return p->vLines->pArray[iToken]; -} - - -/**Function************************************************************* - - Synopsis [Returns the next set of tokens.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Extra_FileReaderGetTokens( Extra_FileReader_t * p ) -{ - Vec_Ptr_t * vTokens; - while ( vTokens = Extra_FileReaderGetTokens_int( p ) ) - if ( vTokens->nSize > 0 ) - break; - return vTokens; -} - -/**Function************************************************************* - - Synopsis [Returns the next set of tokens.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ) -{ - char * pChar; - int fTokenStarted, MapValue; - if ( p->fStop ) - return NULL; - // reset the token info - p->vTokens->nSize = 0; - p->vLines->nSize = 0; - fTokenStarted = 0; - // check if the new data should to be loaded - if ( p->pBufferCur > p->pBufferStop ) - Extra_FileReaderReload( p ); - -// printf( "%d\n", p->pBufferEnd - p->pBufferCur ); - - // process the string starting from the current position - for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) - { - // count the lines - if ( *pChar == '\n' ) - p->nLineCounter++; - // switch depending on the character - MapValue = p->pCharMap[*pChar]; - -// printf( "Char value = %d. Map value = %d.\n", *pChar, MapValue ); - - - switch ( MapValue ) - { - case EXTRA_CHAR_COMMENT: - if ( *pChar != '/' || *(pChar+1) == '/' ) - { // dealing with the need to have // as a comment - // if the token was being written, stop it - if ( fTokenStarted ) - fTokenStarted = 0; - // eraze the comment till the end of line - while ( *pChar != '\n' ) - { - *pChar++ = 0; - if ( pChar == p->pBufferEnd ) - { // this failure is due to the fact the comment continued - // through EXTRA_OFFSET_SIZE chars till the end of the buffer - printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName ); - return NULL; - } - } - pChar--; - break; - } - // otherwise it is a normal character - case EXTRA_CHAR_NORMAL: - if ( !fTokenStarted ) - { - Vec_PtrPush( p->vTokens, pChar ); - Vec_IntPush( p->vLines, p->nLineCounter ); - fTokenStarted = 1; - } - break; - case EXTRA_CHAR_STOP: - if ( fTokenStarted ) - fTokenStarted = 0; - *pChar = 0; - // prepare before leaving - p->pBufferCur = pChar + 1; - return p->vTokens; - case EXTRA_CHAR_CLEAN: - if ( fTokenStarted ) - fTokenStarted = 0; - *pChar = 0; - break; - default: - assert( 0 ); - } - } - // the file is finished or the last part continued - // through EXTRA_OFFSET_SIZE chars till the end of the buffer - if ( p->pBufferStop == p->pBufferEnd ) // end of file - { - *pChar = 0; - p->fStop = 1; - return p->vTokens; - } - printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName ); -/* - { - int i; - for ( i = 0; i < p->vTokens->nSize; i++ ) - printf( "%s ", p->vTokens->pArray[i] ); - printf( "\n" ); - } -*/ - return NULL; -} - -/**Function************************************************************* - - Synopsis [Loads new data into the file reader.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_FileReaderReload( Extra_FileReader_t * p ) -{ - int nCharsUsed, nCharsToRead; - assert( !p->fStop ); - assert( p->pBufferCur > p->pBufferStop ); - assert( p->pBufferCur < p->pBufferEnd ); - // figure out how many chars are still not processed - nCharsUsed = p->pBufferEnd - p->pBufferCur; - // move the remaining data to the beginning of the buffer - memmove( p->pBuffer, p->pBufferCur, nCharsUsed ); - p->pBufferCur = p->pBuffer; - // determine how many chars we will read - nCharsToRead = EXTRA_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead ); - // read the chars - fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile ); - p->nFileRead += nCharsToRead; - // set the ponters to the end and the stopping point - p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead; - p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/extra/extraUtilTruth.c b/src/misc/extra/extraUtilTruth.c deleted file mode 100644 index 3b0b16eb..00000000 --- a/src/misc/extra/extraUtilTruth.c +++ /dev/null @@ -1,1148 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraUtilMisc.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [Various procedures for truth table manipulation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraUtilMisc.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "extra.h" - -/*---------------------------------------------------------------------------*/ -/* Constant declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Stucture declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Type declarations */ -/*---------------------------------------------------------------------------*/ - -/*---------------------------------------------------------------------------*/ -/* Variable declarations */ -/*---------------------------------------------------------------------------*/ - -static unsigned s_VarMasks[5][2] = { - { 0x33333333, 0xAAAAAAAA }, - { 0x55555555, 0xCCCCCCCC }, - { 0x0F0F0F0F, 0xF0F0F0F0 }, - { 0x00FF00FF, 0xFF00FF00 }, - { 0x0000FFFF, 0xFFFF0000 } -}; - -/*---------------------------------------------------------------------------*/ -/* Macro declarations */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticStart*************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Static function prototypes */ -/*---------------------------------------------------------------------------*/ - -/**AutomaticEnd***************************************************************/ - -/*---------------------------------------------------------------------------*/ -/* Definition of exported functions */ -/*---------------------------------------------------------------------------*/ - -/**Function************************************************************* - - Synopsis [Derive elementary truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned ** Extra_TruthElementary( int nVars ) -{ - unsigned ** pRes; - int i, k, nWords; - nWords = Extra_TruthWordNum(nVars); - pRes = (unsigned **)Extra_ArrayAlloc( nVars, nWords, 4 ); - for ( i = 0; i < nVars; i++ ) - { - if ( i < 5 ) - { - for ( k = 0; k < nWords; k++ ) - pRes[i][k] = s_VarMasks[i][1]; - } - else - { - for ( k = 0; k < nWords; k++ ) - if ( k & (1 << (i-5)) ) - pRes[i][k] = ~(unsigned)0; - else - pRes[i][k] = 0; - } - } - return pRes; -} - -/**Function************************************************************* - - Synopsis [Swaps two adjacent variables in the truth table.] - - Description [Swaps var number Start and var number Start+1 (0-based numbers). - The input truth table is pIn. The output truth table is pOut.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthSwapAdjacentVars( unsigned * pOut, unsigned * pIn, int nVars, int iVar ) -{ - static unsigned PMasks[4][3] = { - { 0x99999999, 0x22222222, 0x44444444 }, - { 0xC3C3C3C3, 0x0C0C0C0C, 0x30303030 }, - { 0xF00FF00F, 0x00F000F0, 0x0F000F00 }, - { 0xFF0000FF, 0x0000FF00, 0x00FF0000 } - }; - int nWords = Extra_TruthWordNum( nVars ); - int i, k, Step, Shift; - - assert( iVar < nVars - 1 ); - if ( iVar < 4 ) - { - Shift = (1 << iVar); - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & PMasks[iVar][0]) | ((pIn[i] & PMasks[iVar][1]) << Shift) | ((pIn[i] & PMasks[iVar][2]) >> Shift); - } - else if ( iVar > 4 ) - { - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 4*Step ) - { - for ( i = 0; i < Step; i++ ) - pOut[i] = pIn[i]; - for ( i = 0; i < Step; i++ ) - pOut[Step+i] = pIn[2*Step+i]; - for ( i = 0; i < Step; i++ ) - pOut[2*Step+i] = pIn[Step+i]; - for ( i = 0; i < Step; i++ ) - pOut[3*Step+i] = pIn[3*Step+i]; - pIn += 4*Step; - pOut += 4*Step; - } - } - else // if ( iVar == 4 ) - { - for ( i = 0; i < nWords; i += 2 ) - { - pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); - pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); - } - } -} - -/**Function************************************************************* - - Synopsis [Swaps two adjacent variables in the truth table.] - - Description [Swaps var number Start and var number Start+1 (0-based numbers). - The input truth table is pIn. The output truth table is pOut.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthSwapAdjacentVars2( unsigned * pIn, unsigned * pOut, int nVars, int Start ) -{ - int nWords = (nVars <= 5)? 1 : (1 << (nVars-5)); - int i, k, Step; - - assert( Start < nVars - 1 ); - switch ( Start ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0x99999999) | ((pIn[i] & 0x22222222) << 1) | ((pIn[i] & 0x44444444) >> 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0xC3C3C3C3) | ((pIn[i] & 0x0C0C0C0C) << 2) | ((pIn[i] & 0x30303030) >> 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0xF00FF00F) | ((pIn[i] & 0x00F000F0) << 4) | ((pIn[i] & 0x0F000F00) >> 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pIn[i] & 0xFF0000FF) | ((pIn[i] & 0x0000FF00) << 8) | ((pIn[i] & 0x00FF0000) >> 8); - return; - case 4: - for ( i = 0; i < nWords; i += 2 ) - { - pOut[i] = (pIn[i] & 0x0000FFFF) | ((pIn[i+1] & 0x0000FFFF) << 16); - pOut[i+1] = (pIn[i+1] & 0xFFFF0000) | ((pIn[i] & 0xFFFF0000) >> 16); - } - return; - default: - Step = (1 << (Start - 5)); - for ( k = 0; k < nWords; k += 4*Step ) - { - for ( i = 0; i < Step; i++ ) - pOut[i] = pIn[i]; - for ( i = 0; i < Step; i++ ) - pOut[Step+i] = pIn[2*Step+i]; - for ( i = 0; i < Step; i++ ) - pOut[2*Step+i] = pIn[Step+i]; - for ( i = 0; i < Step; i++ ) - pOut[3*Step+i] = pIn[3*Step+i]; - pIn += 4*Step; - pOut += 4*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Expands the truth table according to the phase.] - - Description [The input and output truth tables are in pIn/pOut. The current number - of variables is nVars. The total number of variables in nVarsAll. The last argument - (Phase) contains shows where the variables should go.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthStretch( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ) -{ - unsigned * pTemp; - int i, k, Var = nVars - 1, Counter = 0; - for ( i = nVarsAll - 1; i >= 0; i-- ) - if ( Phase & (1 << i) ) - { - for ( k = Var; k < i; k++ ) - { - Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - Counter++; - } - Var--; - } - assert( Var == -1 ); - // swap if it was moved an even number of times - if ( !(Counter & 1) ) - Extra_TruthCopy( pOut, pIn, nVarsAll ); -} - -/**Function************************************************************* - - Synopsis [Shrinks the truth table according to the phase.] - - Description [The input and output truth tables are in pIn/pOut. The current number - of variables is nVars. The total number of variables in nVarsAll. The last argument - (Phase) contains shows what variables should remain.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthShrink( unsigned * pOut, unsigned * pIn, int nVars, int nVarsAll, unsigned Phase ) -{ - unsigned * pTemp; - int i, k, Var = 0, Counter = 0; - for ( i = 0; i < nVarsAll; i++ ) - if ( Phase & (1 << i) ) - { - for ( k = i-1; k >= Var; k-- ) - { - Extra_TruthSwapAdjacentVars( pOut, pIn, nVarsAll, k ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - Counter++; - } - Var++; - } - assert( Var == nVars ); - // swap if it was moved an even number of times - if ( !(Counter & 1) ) - Extra_TruthCopy( pOut, pIn, nVarsAll ); -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if TT depends on the given variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_TruthVarInSupport( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Extra_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - if ( (pTruth[i] & 0x55555555) != ((pTruth[i] & 0xAAAAAAAA) >> 1) ) - return 1; - return 0; - case 1: - for ( i = 0; i < nWords; i++ ) - if ( (pTruth[i] & 0x33333333) != ((pTruth[i] & 0xCCCCCCCC) >> 2) ) - return 1; - return 0; - case 2: - for ( i = 0; i < nWords; i++ ) - if ( (pTruth[i] & 0x0F0F0F0F) != ((pTruth[i] & 0xF0F0F0F0) >> 4) ) - return 1; - return 0; - case 3: - for ( i = 0; i < nWords; i++ ) - if ( (pTruth[i] & 0x00FF00FF) != ((pTruth[i] & 0xFF00FF00) >> 8) ) - return 1; - return 0; - case 4: - for ( i = 0; i < nWords; i++ ) - if ( (pTruth[i] & 0x0000FFFF) != ((pTruth[i] & 0xFFFF0000) >> 16) ) - return 1; - return 0; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - if ( pTruth[i] != pTruth[Step+i] ) - return 1; - pTruth += 2*Step; - } - return 0; - } -} - -/**Function************************************************************* - - Synopsis [Returns the number of support vars.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_TruthSupportSize( unsigned * pTruth, int nVars ) -{ - int i, Counter = 0; - for ( i = 0; i < nVars; i++ ) - Counter += Extra_TruthVarInSupport( pTruth, nVars, i ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns support of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_TruthSupport( unsigned * pTruth, int nVars ) -{ - int i, Support = 0; - for ( i = 0; i < nVars; i++ ) - if ( Extra_TruthVarInSupport( pTruth, nVars, i ) ) - Support |= (1 << i); - return Support; -} - - - -/**Function************************************************************* - - Synopsis [Computes positive cofactor of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthCofactor1( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Extra_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0xAAAAAAAA) | ((pTruth[i] & 0xAAAAAAAA) >> 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0xCCCCCCCC) | ((pTruth[i] & 0xCCCCCCCC) >> 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0xF0F0F0F0) | ((pTruth[i] & 0xF0F0F0F0) >> 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0xFF00FF00) | ((pTruth[i] & 0xFF00FF00) >> 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0xFFFF0000) | ((pTruth[i] & 0xFFFF0000) >> 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - pTruth[i] = pTruth[Step+i]; - pTruth += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Computes negative cofactor of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthCofactor0( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Extra_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0x55555555) | ((pTruth[i] & 0x55555555) << 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0x33333333) | ((pTruth[i] & 0x33333333) << 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0x0F0F0F0F) | ((pTruth[i] & 0x0F0F0F0F) << 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0x00FF00FF) | ((pTruth[i] & 0x00FF00FF) << 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = (pTruth[i] & 0x0000FFFF) | ((pTruth[i] & 0x0000FFFF) << 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - pTruth[Step+i] = pTruth[i]; - pTruth += 2*Step; - } - return; - } -} - - -/**Function************************************************************* - - Synopsis [Existentially quantifies the variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthExist( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Extra_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pTruth[i] |= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pTruth[i] |= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pTruth[i] |= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pTruth[i] |= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pTruth[i] |= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - pTruth[i] |= pTruth[Step+i]; - pTruth[Step+i] = pTruth[i]; - } - pTruth += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Existentially quantifies the variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthForall( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Extra_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pTruth[i] &= ((pTruth[i] & 0xAAAAAAAA) >> 1) | ((pTruth[i] & 0x55555555) << 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pTruth[i] &= ((pTruth[i] & 0xCCCCCCCC) >> 2) | ((pTruth[i] & 0x33333333) << 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pTruth[i] &= ((pTruth[i] & 0xF0F0F0F0) >> 4) | ((pTruth[i] & 0x0F0F0F0F) << 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pTruth[i] &= ((pTruth[i] & 0xFF00FF00) >> 8) | ((pTruth[i] & 0x00FF00FF) << 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pTruth[i] &= ((pTruth[i] & 0xFFFF0000) >> 16) | ((pTruth[i] & 0x0000FFFF) << 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - pTruth[i] &= pTruth[Step+i]; - pTruth[Step+i] = pTruth[i]; - } - pTruth += 2*Step; - } - return; - } -} - - -/**Function************************************************************* - - Synopsis [Computes negative cofactor of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthMux( unsigned * pOut, unsigned * pCof0, unsigned * pCof1, int nVars, int iVar ) -{ - int nWords = Extra_TruthWordNum( nVars ); - int i, k, Step; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pCof0[i] & 0x55555555) | (pCof1[i] & 0xAAAAAAAA); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pCof0[i] & 0x33333333) | (pCof1[i] & 0xCCCCCCCC); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pCof0[i] & 0x0F0F0F0F) | (pCof1[i] & 0xF0F0F0F0); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pCof0[i] & 0x00FF00FF) | (pCof1[i] & 0xFF00FF00); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (pCof0[i] & 0x0000FFFF) | (pCof1[i] & 0xFFFF0000); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - pOut[i] = pCof0[i]; - pOut[Step+i] = pCof1[Step+i]; - } - pOut += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Checks symmetry of two variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_TruthVarsSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) -{ - static unsigned uTemp0[16], uTemp1[16]; - assert( nVars <= 9 ); - // compute Cof01 - Extra_TruthCopy( uTemp0, pTruth, nVars ); - Extra_TruthCofactor0( uTemp0, nVars, iVar0 ); - Extra_TruthCofactor1( uTemp0, nVars, iVar1 ); - // compute Cof10 - Extra_TruthCopy( uTemp1, pTruth, nVars ); - Extra_TruthCofactor1( uTemp1, nVars, iVar0 ); - Extra_TruthCofactor0( uTemp1, nVars, iVar1 ); - // compare - return Extra_TruthIsEqual( uTemp0, uTemp1, nVars ); -} - -/**Function************************************************************* - - Synopsis [Checks antisymmetry of two variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_TruthVarsAntiSymm( unsigned * pTruth, int nVars, int iVar0, int iVar1 ) -{ - static unsigned uTemp0[16], uTemp1[16]; - assert( nVars <= 9 ); - // compute Cof00 - Extra_TruthCopy( uTemp0, pTruth, nVars ); - Extra_TruthCofactor0( uTemp0, nVars, iVar0 ); - Extra_TruthCofactor0( uTemp0, nVars, iVar1 ); - // compute Cof11 - Extra_TruthCopy( uTemp1, pTruth, nVars ); - Extra_TruthCofactor1( uTemp1, nVars, iVar0 ); - Extra_TruthCofactor1( uTemp1, nVars, iVar1 ); - // compare - return Extra_TruthIsEqual( uTemp0, uTemp1, nVars ); -} - -/**Function************************************************************* - - Synopsis [Changes phase of the function w.r.t. one variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthChangePhase( unsigned * pTruth, int nVars, int iVar ) -{ - int nWords = Extra_TruthWordNum( nVars ); - int i, k, Step; - unsigned Temp; - - assert( iVar < nVars ); - switch ( iVar ) - { - case 0: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ((pTruth[i] & 0x55555555) << 1) | ((pTruth[i] & 0xAAAAAAAA) >> 1); - return; - case 1: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ((pTruth[i] & 0x33333333) << 2) | ((pTruth[i] & 0xCCCCCCCC) >> 2); - return; - case 2: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ((pTruth[i] & 0x0F0F0F0F) << 4) | ((pTruth[i] & 0xF0F0F0F0) >> 4); - return; - case 3: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ((pTruth[i] & 0x00FF00FF) << 8) | ((pTruth[i] & 0xFF00FF00) >> 8); - return; - case 4: - for ( i = 0; i < nWords; i++ ) - pTruth[i] = ((pTruth[i] & 0x0000FFFF) << 16) | ((pTruth[i] & 0xFFFF0000) >> 16); - return; - default: - Step = (1 << (iVar - 5)); - for ( k = 0; k < nWords; k += 2*Step ) - { - for ( i = 0; i < Step; i++ ) - { - Temp = pTruth[i]; - pTruth[i] = pTruth[Step+i]; - pTruth[Step+i] = Temp; - } - pTruth += 2*Step; - } - return; - } -} - -/**Function************************************************************* - - Synopsis [Computes minimum overlap in supports of cofactors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_TruthMinCofSuppOverlap( unsigned * pTruth, int nVars, int * pVarMin ) -{ - static unsigned uCofactor[16]; - int i, ValueCur, ValueMin, VarMin; - unsigned uSupp0, uSupp1; - int nVars0, nVars1; - assert( nVars <= 9 ); - ValueMin = 32; - VarMin = -1; - for ( i = 0; i < nVars; i++ ) - { - // get negative cofactor - Extra_TruthCopy( uCofactor, pTruth, nVars ); - Extra_TruthCofactor0( uCofactor, nVars, i ); - uSupp0 = Extra_TruthSupport( uCofactor, nVars ); - nVars0 = Extra_WordCountOnes( uSupp0 ); -//Extra_PrintBinary( stdout, &uSupp0, 8 ); printf( "\n" ); - // get positive cofactor - Extra_TruthCopy( uCofactor, pTruth, nVars ); - Extra_TruthCofactor1( uCofactor, nVars, i ); - uSupp1 = Extra_TruthSupport( uCofactor, nVars ); - nVars1 = Extra_WordCountOnes( uSupp1 ); -//Extra_PrintBinary( stdout, &uSupp1, 8 ); printf( "\n" ); - // get the number of common vars - ValueCur = Extra_WordCountOnes( uSupp0 & uSupp1 ); - if ( ValueMin > ValueCur && nVars0 <= 5 && nVars1 <= 5 ) - { - ValueMin = ValueCur; - VarMin = i; - } - if ( ValueMin == 0 ) - break; - } - if ( pVarMin ) - *pVarMin = VarMin; - return ValueMin; -} - - -/**Function************************************************************* - - Synopsis [Counts the number of 1's in each cofactor.] - - Description [The resulting numbers are stored in the array of shorts, - whose length is 2*nVars. The number of 1's is counted in a different - space than the original function. For example, if the function depends - on k variables, the cofactors are assumed to depend on k-1 variables.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_TruthCountOnesInCofs( unsigned * pTruth, int nVars, short * pStore ) -{ - int nWords = Extra_TruthWordNum( nVars ); - int i, k, Counter; - memset( pStore, 0, sizeof(short) * 2 * nVars ); - if ( nVars <= 5 ) - { - if ( nVars > 0 ) - { - pStore[2*0+0] = Extra_WordCountOnes( pTruth[0] & 0x55555555 ); - pStore[2*0+1] = Extra_WordCountOnes( pTruth[0] & 0xAAAAAAAA ); - } - if ( nVars > 1 ) - { - pStore[2*1+0] = Extra_WordCountOnes( pTruth[0] & 0x33333333 ); - pStore[2*1+1] = Extra_WordCountOnes( pTruth[0] & 0xCCCCCCCC ); - } - if ( nVars > 2 ) - { - pStore[2*2+0] = Extra_WordCountOnes( pTruth[0] & 0x0F0F0F0F ); - pStore[2*2+1] = Extra_WordCountOnes( pTruth[0] & 0xF0F0F0F0 ); - } - if ( nVars > 3 ) - { - pStore[2*3+0] = Extra_WordCountOnes( pTruth[0] & 0x00FF00FF ); - pStore[2*3+1] = Extra_WordCountOnes( pTruth[0] & 0xFF00FF00 ); - } - if ( nVars > 4 ) - { - pStore[2*4+0] = Extra_WordCountOnes( pTruth[0] & 0x0000FFFF ); - pStore[2*4+1] = Extra_WordCountOnes( pTruth[0] & 0xFFFF0000 ); - } - return; - } - // nVars >= 6 - // count 1's for all other variables - for ( k = 0; k < nWords; k++ ) - { - Counter = Extra_WordCountOnes( pTruth[k] ); - for ( i = 5; i < nVars; i++ ) - if ( k & (1 << (i-5)) ) - pStore[2*i+1] += Counter; - else - pStore[2*i+0] += Counter; - } - // count 1's for the first five variables - for ( k = 0; k < nWords/2; k++ ) - { - pStore[2*0+0] += Extra_WordCountOnes( (pTruth[0] & 0x55555555) | ((pTruth[1] & 0x55555555) << 1) ); - pStore[2*0+1] += Extra_WordCountOnes( (pTruth[0] & 0xAAAAAAAA) | ((pTruth[1] & 0xAAAAAAAA) >> 1) ); - pStore[2*1+0] += Extra_WordCountOnes( (pTruth[0] & 0x33333333) | ((pTruth[1] & 0x33333333) << 2) ); - pStore[2*1+1] += Extra_WordCountOnes( (pTruth[0] & 0xCCCCCCCC) | ((pTruth[1] & 0xCCCCCCCC) >> 2) ); - pStore[2*2+0] += Extra_WordCountOnes( (pTruth[0] & 0x0F0F0F0F) | ((pTruth[1] & 0x0F0F0F0F) << 4) ); - pStore[2*2+1] += Extra_WordCountOnes( (pTruth[0] & 0xF0F0F0F0) | ((pTruth[1] & 0xF0F0F0F0) >> 4) ); - pStore[2*3+0] += Extra_WordCountOnes( (pTruth[0] & 0x00FF00FF) | ((pTruth[1] & 0x00FF00FF) << 8) ); - pStore[2*3+1] += Extra_WordCountOnes( (pTruth[0] & 0xFF00FF00) | ((pTruth[1] & 0xFF00FF00) >> 8) ); - pStore[2*4+0] += Extra_WordCountOnes( (pTruth[0] & 0x0000FFFF) | ((pTruth[1] & 0x0000FFFF) << 16) ); - pStore[2*4+1] += Extra_WordCountOnes( (pTruth[0] & 0xFFFF0000) | ((pTruth[1] & 0xFFFF0000) >> 16) ); - pTruth += 2; - } -} - - -/**Function************************************************************* - - Synopsis [Canonicize the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Extra_TruthHash( unsigned * pIn, int nWords ) -{ - // The 1,024 smallest prime numbers used to compute the hash value - // http://www.math.utah.edu/~alfeld/math/primelist.html - static int HashPrimes[1024] = { 2, 3, 5, - 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, - 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, - 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, - 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, - 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, - 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, - 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, - 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, - 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, - 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, - 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, - 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, - 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, - 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, - 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, - 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, - 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, - 1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, - 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, - 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, - 2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, - 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, - 2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, - 2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, - 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, - 2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, - 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, - 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, - 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, - 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, - 3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, - 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, - 3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, - 3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, - 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, - 3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, - 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, - 4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, - 4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, - 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, - 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, - 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, - 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, - 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, - 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, - 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, - 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, - 5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, - 5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, - 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, - 5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, - 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, - 6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, - 6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, - 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, - 6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, - 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, - 6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, - 6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, - 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, - 6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, - 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, - 7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, - 7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, - 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, - 7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, - 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, - 7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, - 8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, - 8147, 8161 }; - int i; - unsigned uHashKey; - assert( nWords <= 1024 ); - uHashKey = 0; - for ( i = 0; i < nWords; i++ ) - uHashKey ^= HashPrimes[i] * pIn[i]; - return uHashKey; -} - - -/**Function************************************************************* - - Synopsis [Canonicize the truth table.] - - Description [Returns the phase. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Extra_TruthSemiCanonicize( unsigned * pInOut, unsigned * pAux, int nVars, char * pCanonPerm, short * pStore ) -{ - unsigned * pIn = pInOut, * pOut = pAux, * pTemp; - int nWords = Extra_TruthWordNum( nVars ); - int i, Temp, fChange, Counter, nOnes;//, k, j, w, Limit; - unsigned uCanonPhase; - - // canonicize output - uCanonPhase = 0; - nOnes = Extra_TruthCountOnes(pIn, nVars); - if ( (nOnes > nWords * 16) || ((nOnes == nWords * 16) && (pIn[0] & 1)) ) - { - uCanonPhase |= (1 << nVars); - Extra_TruthNot( pIn, pIn, nVars ); - } - - // collect the minterm counts - Extra_TruthCountOnesInCofs( pIn, nVars, pStore ); - - // canonicize phase - for ( i = 0; i < nVars; i++ ) - { - if ( pStore[2*i+0] <= pStore[2*i+1] ) - continue; - uCanonPhase |= (1 << i); - Temp = pStore[2*i+0]; - pStore[2*i+0] = pStore[2*i+1]; - pStore[2*i+1] = Temp; - Extra_TruthChangePhase( pIn, nVars, i ); - } - -// Extra_PrintHexadecimal( stdout, pIn, nVars ); -// printf( "\n" ); - - // permute - Counter = 0; - do { - fChange = 0; - for ( i = 0; i < nVars-1; i++ ) - { - if ( pStore[2*i] <= pStore[2*(i+1)] ) - continue; - Counter++; - fChange = 1; - - Temp = pCanonPerm[i]; - pCanonPerm[i] = pCanonPerm[i+1]; - pCanonPerm[i+1] = Temp; - - Temp = pStore[2*i]; - pStore[2*i] = pStore[2*(i+1)]; - pStore[2*(i+1)] = Temp; - - Temp = pStore[2*i+1]; - pStore[2*i+1] = pStore[2*(i+1)+1]; - pStore[2*(i+1)+1] = Temp; - - Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - } - } while ( fChange ); - -/* - Extra_PrintBinary( stdout, &uCanonPhase, nVars+1 ); printf( " : " ); - for ( i = 0; i < nVars; i++ ) - printf( "%d=%d/%d ", pCanonPerm[i], pStore[2*i], pStore[2*i+1] ); - printf( " C = %d\n", Counter ); - Extra_PrintHexadecimal( stdout, pIn, nVars ); - printf( "\n" ); -*/ - -/* - // process symmetric variable groups - uSymms = 0; - for ( i = 0; i < nVars-1; i++ ) - { - if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric - continue; - if ( pStore[2*i] != pStore[2*i+1] ) - continue; - if ( Extra_TruthVarsSymm( pIn, nVars, i, i+1 ) ) - continue; - if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, i+1 ) ) - Extra_TruthChangePhase( pIn, nVars, i+1 ); - } -*/ - -/* - // process symmetric variable groups - uSymms = 0; - for ( i = 0; i < nVars-1; i++ ) - { - if ( pStore[2*i] != pStore[2*(i+1)] ) // i and i+1 cannot be symmetric - continue; - // i and i+1 can be symmetric - // find the end of this group - for ( k = i+1; k < nVars; k++ ) - if ( pStore[2*i] != pStore[2*k] ) - break; - Limit = k; - assert( i < Limit-1 ); - // go through the variables in this group - for ( j = i + 1; j < Limit; j++ ) - { - // check symmetry - if ( Extra_TruthVarsSymm( pIn, nVars, i, j ) ) - { - uSymms |= (1 << j); - continue; - } - // they are phase-unknown - if ( pStore[2*i] == pStore[2*i+1] ) - { - if ( Extra_TruthVarsAntiSymm( pIn, nVars, i, j ) ) - { - Extra_TruthChangePhase( pIn, nVars, j ); - uCanonPhase ^= (1 << j); - uSymms |= (1 << j); - continue; - } - } - - // they are not symmetric - move j as far as it goes in the group - for ( k = j; k < Limit-1; k++ ) - { - Counter++; - - Temp = pCanonPerm[k]; - pCanonPerm[k] = pCanonPerm[k+1]; - pCanonPerm[k+1] = Temp; - - assert( pStore[2*k] == pStore[2*(k+1)] ); - Extra_TruthSwapAdjacentVars( pOut, pIn, nVars, k ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - } - Limit--; - j--; - } - i = Limit - 1; - } -*/ - - // swap if it was moved an even number of times - if ( Counter & 1 ) - Extra_TruthCopy( pOut, pIn, nVars ); - return uCanonPhase; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/extra/extraUtilUtil.c b/src/misc/extra/extraUtilUtil.c deleted file mode 100644 index ee0c400a..00000000 --- a/src/misc/extra/extraUtilUtil.c +++ /dev/null @@ -1,330 +0,0 @@ -/**CFile**************************************************************** - - FileName [extraUtilUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [extra] - - Synopsis [Old SIS utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: extraUtilUtil.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define EXTRA_RLIMIT_DATA_DEFAULT 67108864 // assume 64MB by default - -/* File : getopt.c - * Author : Henry Spencer, University of Toronto - * Updated: 28 April 1984 - * - * Changes: (R Rudell) - * changed index() to strchr(); - * added getopt_reset() to reset the getopt argument parsing - * - * Purpose: get option letter from argv. - */ - -char * globalUtilOptarg; // Global argument pointer (util_optarg) -int globalUtilOptind = 0; // Global argv index (util_optind) - -static char *pScanStr; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [util_cpu_time()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -long Extra_CpuTime() -{ - return clock(); -} - -/**Function************************************************************* - - Synopsis [getSoftDataLimit()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_GetSoftDataLimit() -{ - return EXTRA_RLIMIT_DATA_DEFAULT; -} - -/**Function************************************************************* - - Synopsis [util_getopt_reset()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_UtilGetoptReset() -{ - globalUtilOptarg = 0; - globalUtilOptind = 0; - pScanStr = 0; -} - -/**Function************************************************************* - - Synopsis [util_getopt()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_UtilGetopt( int argc, char *argv[], char *optstring ) -{ - register int c; - register char *place; - - globalUtilOptarg = NULL; - - if (pScanStr == NULL || *pScanStr == '\0') { - if (globalUtilOptind == 0) globalUtilOptind++; - if (globalUtilOptind >= argc) return EOF; - place = argv[globalUtilOptind]; - if (place[0] != '-' || place[1] == '\0') return EOF; - globalUtilOptind++; - if (place[1] == '-' && place[2] == '\0') return EOF; - pScanStr = place+1; - } - - c = *pScanStr++; - place = strchr(optstring, c); - if (place == NULL || c == ':') { - (void) fprintf(stderr, "%s: unknown option %c\n", argv[0], c); - return '?'; - } - if (*++place == ':') { - if (*pScanStr != '\0') { - globalUtilOptarg = pScanStr; - pScanStr = NULL; - } else { - if (globalUtilOptind >= argc) { - (void) fprintf(stderr, "%s: %c requires an argument\n", - argv[0], c); - return '?'; - } - globalUtilOptarg = argv[globalUtilOptind]; - globalUtilOptind++; - } - } - return c; -} - -/**Function************************************************************* - - Synopsis [util_print_time()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_UtilPrintTime( long t ) -{ - static char s[40]; - - (void) sprintf(s, "%ld.%02ld sec", t/1000, (t%1000)/10); - return s; -} - - -/**Function************************************************************* - - Synopsis [Extra_UtilStrsav()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_UtilStrsav( char *s ) -{ - if(s == NULL) { /* added 7/95, for robustness */ - return s; - } - else { - return strcpy(ALLOC(char, strlen(s)+1), s); - } -} - -/**Function************************************************************* - - Synopsis [util_tilde_expand()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_UtilTildeExpand( char *fname ) -{ - return Extra_UtilStrsav( fname ); -} - -/**Function************************************************************* - - Synopsis [check_file()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Extra_UtilCheckFile(char *filename, char *mode) -{ - FILE *fp; - int got_file; - - if (strcmp(mode, "x") == 0) { - mode = "r"; - } - fp = fopen(filename, mode); - got_file = (fp != 0); - if (fp != 0) { - (void) fclose(fp); - } - return got_file; -} - -/**Function************************************************************* - - Synopsis [util_file_search()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Extra_UtilFileSearch(char *file, char *path, char *mode) -//char *file; // file we're looking for -//char *path; // search path, colon separated -//char *mode; // "r", "w", or "x" -{ - int quit; - char *buffer, *filename, *save_path, *cp; - - if (path == 0 || strcmp(path, "") == 0) { - path = "."; /* just look in the current directory */ - } - - save_path = path = Extra_UtilStrsav(path); - quit = 0; - do { - cp = strchr(path, ':'); - if (cp != 0) { - *cp = '\0'; - } else { - quit = 1; - } - - /* cons up the filename out of the path and file name */ - if (strcmp(path, ".") == 0) { - buffer = Extra_UtilStrsav(file); - } else { - buffer = ALLOC(char, strlen(path) + strlen(file) + 4); - (void) sprintf(buffer, "%s/%s", path, file); - } - filename = Extra_UtilTildeExpand(buffer); - FREE(buffer); - - /* see if we can access it */ - if (Extra_UtilCheckFile(filename, mode)) { - FREE(save_path); - return filename; - } - FREE(filename); - path = ++cp; - } while (! quit); - - FREE(save_path); - return 0; -} - -/**Function************************************************************* - - Synopsis [MMout_of_memory()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -/* MMout_of_memory -- out of memory for lazy people, flush and exit */ -void Extra_UtilMMout_Of_Memory( long size ) -{ - (void) fflush(stdout); - (void) fprintf(stderr, "\nout of memory allocating %u bytes\n", - (unsigned) size); - assert( 0 ); - exit(1); -} - -/**Function************************************************************* - - Synopsis [MMoutOfMemory()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void (*Extra_UtilMMoutOfMemory)() = Extra_UtilMMout_Of_Memory; - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/extra/module.make b/src/misc/extra/module.make deleted file mode 100644 index ec8bca4d..00000000 --- a/src/misc/extra/module.make +++ /dev/null @@ -1,15 +0,0 @@ -SRC += src/misc/extra/extraBddAuto.c \ - src/misc/extra/extraBddCas.c \ - src/misc/extra/extraBddKmap.c \ - src/misc/extra/extraBddMisc.c \ - src/misc/extra/extraBddSymm.c \ - src/misc/extra/extraBddUnate.c \ - src/misc/extra/extraUtilBitMatrix.c \ - src/misc/extra/extraUtilCanon.c \ - src/misc/extra/extraUtilFile.c \ - src/misc/extra/extraUtilMemory.c \ - src/misc/extra/extraUtilMisc.c \ - src/misc/extra/extraUtilProgress.c \ - src/misc/extra/extraUtilReader.c \ - src/misc/extra/extraUtilTruth.c \ - src/misc/extra/extraUtilUtil.c diff --git a/src/misc/hash/hash.h b/src/misc/hash/hash.h deleted file mode 100644 index 90e72868..00000000 --- a/src/misc/hash/hash.h +++ /dev/null @@ -1,65 +0,0 @@ -/**CFile**************************************************************** - - FileName [hash.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Hash map.] - - Synopsis [External declarations.] - - Author [Aaron P. Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 16, 2005.] - - Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] - -***********************************************************************/ - -#ifndef __HASH_H__ -#define __HASH_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#ifdef _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#endif - -#include "hashInt.h" -#include "hashFlt.h" -#include "hashPtr.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#ifndef ABS -#define ABS(a) ((a) < 0 ? -(a) : (a)) -#endif - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -int Hash_DefaultHashFunc(int key, int nBins) { - return ABS( ( (key+11)*(key)*7+3 ) % nBins ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#endif - diff --git a/src/misc/hash/hashFlt.h b/src/misc/hash/hashFlt.h deleted file mode 100644 index da20ee28..00000000 --- a/src/misc/hash/hashFlt.h +++ /dev/null @@ -1,330 +0,0 @@ -/**CFile**************************************************************** - - FileName [hashFlt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Hash maps.] - - Synopsis [Hash maps.] - - Author [Aaron P. Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 16, 2006.] - - Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] - -***********************************************************************/ - -#ifndef __HASH_FLT_H__ -#define __HASH_FLT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "extra.h" - -extern int Hash_DefaultHashFunc(int key, int nBins); - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Hash_Flt_t_ Hash_Flt_t; -typedef struct Hash_Flt_Entry_t_ Hash_Flt_Entry_t; - -struct Hash_Flt_Entry_t_ -{ - int key; - float data; - struct Hash_Flt_Entry_t_ * pNext; -}; - -struct Hash_Flt_t_ -{ - int nSize; - int nBins; - int (* fHash)(int key, int nBins); - Hash_Flt_Entry_t ** pArray; -}; - - - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Hash_FltForEachEntry( pHash, pEntry, bin) \ - for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \ - if (pEntry) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a hash map with the given number of bins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Hash_Flt_t * Hash_FltAlloc( int nBins ) -{ - Hash_Flt_t * p; - int i; - assert(nBins > 0); - p = ALLOC( Hash_Flt_t, 1); - p->nBins = nBins; - p->fHash = Hash_DefaultHashFunc; - p->nSize = 0; - p->pArray = ALLOC( Hash_Flt_Entry_t *, nBins ); - for(i=0; ipArray[i] = NULL; - - return p; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if a key already exists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Hash_FltExists( Hash_Flt_t *p, int key ) -{ - int bin; - Hash_Flt_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) { - return 1; - } - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - return 0; -} - -/**Function************************************************************* - - Synopsis [Finds or creates an entry with a key and writes value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Hash_FltWriteEntry( Hash_Flt_t *p, int key, float data ) -{ - int bin; - Hash_Flt_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) { - pEntry->data = data; - return; - } - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - // this key does not currently exist - // create a new entry and add to bin - p->nSize++; - (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 ); - pEntry->pNext = NULL; - pEntry->key = key; - pEntry->data = data; - - return; -} - - -/**Function************************************************************* - - Synopsis [Finds or creates an entry with a key.] - - Description [fCreate specifies whether new entries should be created.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Hash_FltEntry( Hash_Flt_t *p, int key, int fCreate ) -{ - int bin; - Hash_Flt_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) - return pEntry->data; - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - // this key does not currently exist - if (fCreate) { - // create a new entry and add to bin - p->nSize++; - (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 ); - pEntry->pNext = NULL; - pEntry->key = key; - pEntry->data = 0.0; - return pEntry->data; - } - - return 0.0; -} - - -/**Function************************************************************* - - Synopsis [Finds or creates an entry with a key and returns the pointer to it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float* Hash_FltEntryPtr( Hash_Flt_t *p, int key ) -{ - int bin; - Hash_Flt_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) - return &(pEntry->data); - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - // this key does not currently exist - // create a new entry and add to bin - p->nSize++; - (*pLast) = pEntry = ALLOC( Hash_Flt_Entry_t, 1 ); - pEntry->pNext = NULL; - pEntry->key = key; - pEntry->data = 0.0; - - return &(pEntry->data); -} - -/**Function************************************************************* - - Synopsis [Deletes an entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Hash_FltRemove( Hash_Flt_t *p, int key ) -{ - int bin; - Hash_Flt_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) { - p->nSize--; - *pLast = pEntry->pNext; - FREE( pEntry ); - return; - } - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - // could not find key - return; -} - -/**Function************************************************************* - - Synopsis [Frees the hash.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Hash_FltFree( Hash_Flt_t *p ) { - int bin; - Hash_Flt_Entry_t *pEntry; - - // free bins - for(bin = 0; bin < p->nBins; bin++) { - pEntry = p->pArray[bin]; - while(pEntry) { - pEntry = pEntry->pNext; - FREE( pEntry ); - } - } - - // free hash - FREE( p->pArray ); - FREE( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#endif diff --git a/src/misc/hash/hashInt.h b/src/misc/hash/hashInt.h deleted file mode 100644 index 3b91f5df..00000000 --- a/src/misc/hash/hashInt.h +++ /dev/null @@ -1,293 +0,0 @@ -/**CFile**************************************************************** - - FileName [hashInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Hash maps.] - - Synopsis [Hash maps.] - - Author [Aaron P. Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 16, 2006.] - - Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] - -***********************************************************************/ - -#ifndef __HASH_INT_H__ -#define __HASH_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "extra.h" - -extern int Hash_DefaultHashFunc(int key, int nBins); - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Hash_Int_t_ Hash_Int_t; -typedef struct Hash_Int_Entry_t_ Hash_Int_Entry_t; - -struct Hash_Int_Entry_t_ -{ - int key; - int data; - struct Hash_Int_Entry_t_ * pNext; -}; - -struct Hash_Int_t_ -{ - int nSize; - int nBins; - int (* fHash)(int key, int nBins); - Hash_Int_Entry_t ** pArray; -}; - - - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Hash_IntForEachEntry( pHash, pEntry, bin) \ - for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \ - if (pEntry) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a hash map with the given number of bins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Hash_Int_t * Hash_IntAlloc( int nBins ) -{ - Hash_Int_t * p; - int i; - assert(nBins > 0); - p = ALLOC( Hash_Int_t, 1); - p->nBins = nBins; - p->fHash = Hash_DefaultHashFunc; - p->nSize = 0; - p->pArray = ALLOC( Hash_Int_Entry_t *, nBins ); - for(i=0; ipArray[i] = NULL; - - return p; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if a key already exists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Hash_IntExists( Hash_Int_t *p, int key) -{ - int bin; - Hash_Int_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) { - return 1; - } - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - return 0; -} - -/**Function************************************************************* - - Synopsis [Finds or creates an entry with a key and writes value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Hash_IntWriteEntry( Hash_Int_t *p, int key, int data ) -{ - int bin; - Hash_Int_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) { - pEntry->data = data; - return; - } - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - // this key does not currently exist - // create a new entry and add to bin - p->nSize++; - (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 ); - pEntry->pNext = NULL; - pEntry->key = key; - pEntry->data = data; - - return; -} - - -/**Function************************************************************* - - Synopsis [Finds or creates an entry with a key.] - - Description [fCreate specifies whether new entries will be created.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Hash_IntEntry( Hash_Int_t *p, int key, int fCreate ) -{ - int bin; - Hash_Int_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) - return pEntry->data; - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - // this key does not currently exist - if (fCreate) { - // create a new entry and add to bin - p->nSize++; - (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 ); - pEntry->pNext = NULL; - pEntry->key = key; - pEntry->data = 0; - return pEntry->data; - } - - return 0; -} - - -/**Function************************************************************* - - Synopsis [Finds or creates an entry with a key and returns the pointer to it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int* Hash_IntEntryPtr( Hash_Int_t *p, int key ) -{ - int bin; - Hash_Int_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) - return &(pEntry->data); - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - // this key does not currently exist - // create a new entry and add to bin - p->nSize++; - (*pLast) = pEntry = ALLOC( Hash_Int_Entry_t, 1 ); - pEntry->pNext = NULL; - pEntry->key = key; - pEntry->data = 0; - - return &(pEntry->data); -} - -/**Function************************************************************* - - Synopsis [Frees the hash.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Hash_IntFree( Hash_Int_t *p ) { - int bin; - Hash_Int_Entry_t *pEntry; - - // free bins - for(bin = 0; bin < p->nBins; bin++) { - pEntry = p->pArray[bin]; - while(pEntry) { - pEntry = pEntry->pNext; - FREE( pEntry ); - } - } - - // free hash - FREE( p->pArray ); - FREE( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#endif diff --git a/src/misc/hash/hashPtr.h b/src/misc/hash/hashPtr.h deleted file mode 100644 index 15398a8a..00000000 --- a/src/misc/hash/hashPtr.h +++ /dev/null @@ -1,331 +0,0 @@ -/**CFile**************************************************************** - - FileName [hashFlt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Hash maps.] - - Synopsis [Hash maps.] - - Author [Aaron P. Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - May 16, 2006.] - - Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 ahurst Exp $] - -***********************************************************************/ - -#ifndef __HASH_PTR_H__ -#define __HASH_PTR_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "extra.h" - -extern int Hash_DefaultHashFunc(int key, int nBins); - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Hash_Ptr_t_ Hash_Ptr_t; -typedef struct Hash_Ptr_Entry_t_ Hash_Ptr_Entry_t; - -struct Hash_Ptr_Entry_t_ -{ - int key; - void * data; - struct Hash_Ptr_Entry_t_ * pNext; -}; - -struct Hash_Ptr_t_ -{ - int nSize; - int nBins; - int (* fHash)(int key, int nBins); - Hash_Ptr_Entry_t ** pArray; -}; - - - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Hash_PtrForEachEntry( pHash, pEntry, bin ) \ - for(bin=-1, pEntry=NULL; bin < pHash->nBins; (!pEntry)?(pEntry=pHash->pArray[++bin]):(pEntry=pEntry->pNext)) \ - if (pEntry) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a hash map with the given number of bins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Hash_Ptr_t * Hash_PtrAlloc( int nBins ) -{ - Hash_Ptr_t * p; - int i; - assert(nBins > 0); - p = ALLOC( Hash_Ptr_t, 1); - p->nBins = nBins; - p->fHash = Hash_DefaultHashFunc; - p->nSize = 0; - p->pArray = ALLOC( Hash_Ptr_Entry_t *, nBins ); - for(i=0; ipArray[i] = NULL; - - return p; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if a key already exists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Hash_PtrExists( Hash_Ptr_t *p, int key ) -{ - int bin; - Hash_Ptr_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) { - return 1; - } - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - return 0; -} - -/**Function************************************************************* - - Synopsis [Finds or creates an entry with a key and writes value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Hash_PtrWriteEntry( Hash_Ptr_t *p, int key, void * data ) -{ - int bin; - Hash_Ptr_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) { - pEntry->data = data; - return; - } - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - // this key does not currently exist - // create a new entry and add to bin - p->nSize++; - (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 ); - pEntry->pNext = NULL; - pEntry->key = key; - pEntry->data = data; - - return; -} - - -/**Function************************************************************* - - Synopsis [Finds or creates an entry with a key.] - - Description [fCreate specifies whether a new entry should be created.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Hash_PtrEntry( Hash_Ptr_t *p, int key, int fCreate ) -{ - int bin; - Hash_Ptr_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) - return pEntry->data; - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - // this key does not currently exist - if (fCreate) { - // create a new entry and add to bin - p->nSize++; - (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 ); - pEntry->pNext = NULL; - pEntry->key = key; - pEntry->data = NULL; - return pEntry->data; - } - - return NULL; -} - - -/**Function************************************************************* - - Synopsis [Finds or creates an entry with a key and returns the pointer to it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void** Hash_PtrEntryPtr( Hash_Ptr_t *p, int key ) -{ - int bin; - Hash_Ptr_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) - return &(pEntry->data); - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - // this key does not currently exist - // create a new entry and add to bin - p->nSize++; - (*pLast) = pEntry = ALLOC( Hash_Ptr_Entry_t, 1 ); - pEntry->pNext = NULL; - pEntry->key = key; - pEntry->data = NULL; - - return &(pEntry->data); -} - -/**Function************************************************************* - - Synopsis [Deletes an entry.] - - Description [Returns data, if there was any.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void* Hash_PtrRemove( Hash_Ptr_t *p, int key ) -{ - int bin; - void * data; - Hash_Ptr_Entry_t *pEntry, **pLast; - - // find the bin where this key would live - bin = (*(p->fHash))(key, p->nBins); - - // search for key - pLast = &(p->pArray[bin]); - pEntry = p->pArray[bin]; - while(pEntry) { - if (pEntry->key == key) { - p->nSize--; - data = pEntry->data; - *pLast = pEntry->pNext; - return data; - } - pLast = &(pEntry->pNext); - pEntry = pEntry->pNext; - } - - // could not find key - return NULL; -} - -/**Function************************************************************* - - Synopsis [Frees the hash.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Hash_PtrFree( Hash_Ptr_t *p ) { - int bin; - Hash_Ptr_Entry_t *pEntry; - - // free bins - for(bin = 0; bin < p->nBins; bin++) { - pEntry = p->pArray[bin]; - while(pEntry) { - pEntry = pEntry->pNext; - FREE( pEntry ); - } - } - - // free hash - FREE( p->pArray ); - FREE( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#endif diff --git a/src/misc/hash/module.make b/src/misc/hash/module.make deleted file mode 100644 index d6d908e7..00000000 --- a/src/misc/hash/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += diff --git a/src/misc/mvc/module.make b/src/misc/mvc/module.make deleted file mode 100644 index 23735ca2..00000000 --- a/src/misc/mvc/module.make +++ /dev/null @@ -1,16 +0,0 @@ -SRC += src/misc/mvc/mvc.c \ - src/misc/mvc/mvcApi.c \ - src/misc/mvc/mvcCompare.c \ - src/misc/mvc/mvcContain.c \ - src/misc/mvc/mvcCover.c \ - src/misc/mvc/mvcCube.c \ - src/misc/mvc/mvcDivide.c \ - src/misc/mvc/mvcDivisor.c \ - src/misc/mvc/mvcList.c \ - src/misc/mvc/mvcLits.c \ - src/misc/mvc/mvcMan.c \ - src/misc/mvc/mvcOpAlg.c \ - src/misc/mvc/mvcOpBool.c \ - src/misc/mvc/mvcPrint.c \ - src/misc/mvc/mvcSort.c \ - src/misc/mvc/mvcUtils.c diff --git a/src/misc/mvc/mvc.c b/src/misc/mvc/mvc.c deleted file mode 100644 index 001b1c63..00000000 --- a/src/misc/mvc/mvc.c +++ /dev/null @@ -1,46 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvc.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvc.c,v 1.3 2003/03/19 19:50:26 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvc.h b/src/misc/mvc/mvc.h deleted file mode 100644 index 70834e0a..00000000 --- a/src/misc/mvc/mvc.h +++ /dev/null @@ -1,732 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvc.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Data structure for MV cube/cover manipulation.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvc.h,v 1.10 2003/05/02 23:23:59 wjiang Exp $] - -***********************************************************************/ - -#ifndef __MVC_H__ -#define __MVC_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "extra.h" -#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// this is the only part of Mvc package, which should be modified -// when compiling the package for other platforms - -// these parameters can be computed but setting them manually makes it faster -#define BITS_PER_WORD 32 // sizeof(Mvc_CubeWord_t) * 8 -#define BITS_PER_WORD_MINUS 31 // the same minus 1 -#define BITS_PER_WORD_LOG 5 // log2(sizeof(Mvc_CubeWord_t) * 8) -#define BITS_DISJOINT ((Mvc_CubeWord_t)0x55555555) // the mask of the type "01010101" -#define BITS_FULL ((Mvc_CubeWord_t)0xffffffff) // the mask of the type "11111111" - -// uncomment this macro to switch to standard memory management -//#define USE_SYSTEM_MEMORY_MANAGEMENT - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// cube/list/cover/data -typedef unsigned int Mvc_CubeWord_t; -typedef struct MvcCubeStruct Mvc_Cube_t; -typedef struct MvcListStruct Mvc_List_t; -typedef struct MvcCoverStruct Mvc_Cover_t; -typedef struct MvcDataStruct Mvc_Data_t; -typedef struct MvcManagerStruct Mvc_Manager_t; - -// the cube data structure -struct MvcCubeStruct -{ - Mvc_Cube_t * pNext; // the next cube in the linked list - unsigned iLast : 8; // the index of the last word - unsigned nUnused : 6; // the number of unused bits in the last word - unsigned fPrime : 1; // marks the prime cube - unsigned fEssen : 1; // marks the essential cube - unsigned nOnes : 16; // the number of 1's in the bit data - Mvc_CubeWord_t pData[1]; // the first Mvc_CubeWord_t filled with bit data -}; - -// the single-linked list of cubes in the cover -struct MvcListStruct -{ - Mvc_Cube_t * pHead; // the first cube in the list - Mvc_Cube_t * pTail; // the last cube in the list - int nItems; // the number of cubes in the list -}; - -// the cover data structure -struct MvcCoverStruct -{ - char nWords; // the number of machine words - char nUnused; // the number of unused bits in the last word - short nBits; // the number of used data bits in the cube - Mvc_List_t lCubes; // the single-linked list of cubes - Mvc_Cube_t ** pCubes; // the array of cubes (for sorting) - int nCubesAlloc; // the size of allocated storage - int * pLits; // the counter of lit occurrances in cubes - Mvc_Cube_t * pMask; // the multipurpose mask - Mvc_Manager_t * pMem; // the memory manager -}; - -// data structure to store information about MV variables -struct MvcDataStruct -{ - Mvc_Manager_t * pMan; // the memory manager -// Vm_VarMap_t * pVm; // the MV variable data - int nBinVars; // the number of binary variables - Mvc_Cube_t * pMaskBin; // the mask to select the binary bits only - Mvc_Cube_t ** ppMasks; // the mask to select each MV variable - Mvc_Cube_t * ppTemp[3]; // the temporary cubes -}; - -// the manager of covers and cubes (as of today, only managing memory) -struct MvcManagerStruct -{ - Extra_MmFixed_t * pManC; // the manager for covers - Extra_MmFixed_t * pMan1; // the manager for 1-word cubes - Extra_MmFixed_t * pMan2; // the manager for 2-word cubes - Extra_MmFixed_t * pMan4; // the manager for 3-word cubes -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// reading data from the header of the cube -#define Mvc_CubeReadNext(Cube) ((Cube)->pNext) -#define Mvc_CubeReadNextP(Cube) (&(Cube)->pNext) -#define Mvc_CubeReadLast(Cube) ((Cube)->iLast) -#define Mvc_CubeReadSize(Cube) ((Cube)->nOnes) -// setting data to the header of the cube -#define Mvc_CubeSetNext(Cube,Next) ((Cube)->pNext = (Next)) -#define Mvc_CubeSetLast(Cube,Last) ((Cube)->iLast = (Last)) -#define Mvc_CubeSetSize(Cube,Size) ((Cube)->nOnes = (Size)) -// checking the number of words - -#define Mvc_Cube1Words(Cube) ((Cube)->iLast == 0) -#define Mvc_Cube2Words(Cube) ((Cube)->iLast == 1) -#define Mvc_CubeNWords(Cube) ((Cube)->iLast > 1) -// getting one data bit -#define Mvc_CubeWhichWord(Bit) ((Bit) >> BITS_PER_WORD_LOG) -#define Mvc_CubeWhichBit(Bit) ((Bit) & BITS_PER_WORD_MINUS) -// accessing individual bits -#define Mvc_CubeBitValue(Cube, Bit) (((Cube)->pData[Mvc_CubeWhichWord(Bit)] & (((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit)))) > 0) -#define Mvc_CubeBitInsert(Cube, Bit) ((Cube)->pData[Mvc_CubeWhichWord(Bit)] |= (((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit)))) -#define Mvc_CubeBitRemove(Cube, Bit) ((Cube)->pData[Mvc_CubeWhichWord(Bit)] &= ~(((Mvc_CubeWord_t)1)<<(Mvc_CubeWhichBit(Bit)))) -// accessing values of the binary variables -#define Mvc_CubeVarValue(Cube, Var) (((Cube)->pData[Mvc_CubeWhichWord(2*(Var))] >> (Mvc_CubeWhichBit(2*(Var)))) & ((Mvc_CubeWord_t)3)) - -// various macros - -// cleaning the data bits of the cube -#define Mvc_Cube1BitClean( Cube )\ - ((Cube)->pData[0] = 0) -#define Mvc_Cube2BitClean( Cube )\ - (((Cube)->pData[0] = 0),\ - ((Cube)->pData[1] = 0)) -#define Mvc_CubeNBitClean( Cube )\ -{\ - int _i_;\ - for( _i_ = (Cube)->iLast; _i_ >= 0; _i_--)\ - (Cube)->pData[_i_] = 0;\ -} - -// cleaning the unused part of the lat word -#define Mvc_CubeBitCleanUnused( Cube )\ - ((Cube)->pData[(Cube)->iLast] &= (BITS_FULL >> (Cube)->nUnused)) - -// filling the used data bits with 1's -#define Mvc_Cube1BitFill( Cube )\ - (Cube)->pData[0] = (BITS_FULL >> (Cube)->nUnused); -#define Mvc_Cube2BitFill( Cube )\ - (((Cube)->pData[0] = BITS_FULL),\ - ((Cube)->pData[1] = (BITS_FULL >> (Cube)->nUnused))) -#define Mvc_CubeNBitFill( Cube )\ -{\ - int _i_;\ - (Cube)->pData[(Cube)->iLast] = (BITS_FULL >> (Cube)->nUnused);\ - for( _i_ = (Cube)->iLast - 1; _i_ >= 0; _i_-- )\ - (Cube)->pData[_i_] = BITS_FULL;\ -} - -// complementing the data bits -#define Mvc_Cube1BitNot( Cube )\ - ((Cube)->pData[0] ^= (BITS_FULL >> (Cube)->nUnused)) -#define Mvc_Cube2BitNot( Cube )\ - (((Cube)->pData[0] ^= BITS_FULL),\ - ((Cube)->pData[1] ^= (BITS_FULL >> (Cube)->nUnused))) -#define Mvc_CubeNBitNot( Cube )\ -{\ - int _i_;\ - (Cube)->pData[(Cube)->iLast] ^= (BITS_FULL >> (Cube)->nUnused);\ - for( _i_ = (Cube)->iLast - 1; _i_ >= 0; _i_-- )\ - (Cube)->pData[_i_] ^= BITS_FULL;\ -} - -#define Mvc_Cube1BitCopy( Cube1, Cube2 )\ - (((Cube1)->pData[0]) = ((Cube2)->pData[0])) -#define Mvc_Cube2BitCopy( Cube1, Cube2 )\ - ((((Cube1)->pData[0]) = ((Cube2)->pData[0])),\ - (((Cube1)->pData[1])= ((Cube2)->pData[1]))) -#define Mvc_CubeNBitCopy( Cube1, Cube2 )\ -{\ - int _i_;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - ((Cube1)->pData[_i_]) = ((Cube2)->pData[_i_]);\ -} - -#define Mvc_Cube1BitOr( CubeR, Cube1, Cube2 )\ - (((CubeR)->pData[0]) = ((Cube1)->pData[0] | (Cube2)->pData[0])) -#define Mvc_Cube2BitOr( CubeR, Cube1, Cube2 )\ - ((((CubeR)->pData[0]) = ((Cube1)->pData[0] | (Cube2)->pData[0])),\ - (((CubeR)->pData[1]) = ((Cube1)->pData[1] | (Cube2)->pData[1]))) -#define Mvc_CubeNBitOr( CubeR, Cube1, Cube2 )\ -{\ - int _i_;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] | (Cube2)->pData[_i_]));\ -} - -#define Mvc_Cube1BitExor( CubeR, Cube1, Cube2 )\ - (((CubeR)->pData[0]) = ((Cube1)->pData[0] ^ (Cube2)->pData[0])) -#define Mvc_Cube2BitExor( CubeR, Cube1, Cube2 )\ - ((((CubeR)->pData[0]) = ((Cube1)->pData[0] ^ (Cube2)->pData[0])),\ - (((CubeR)->pData[1]) = ((Cube1)->pData[1] ^ (Cube2)->pData[1]))) -#define Mvc_CubeNBitExor( CubeR, Cube1, Cube2 )\ -{\ - int _i_;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] ^ (Cube2)->pData[_i_]));\ -} - -#define Mvc_Cube1BitAnd( CubeR, Cube1, Cube2 )\ - (((CubeR)->pData[0]) = ((Cube1)->pData[0] & (Cube2)->pData[0])) -#define Mvc_Cube2BitAnd( CubeR, Cube1, Cube2 )\ - ((((CubeR)->pData[0]) = ((Cube1)->pData[0] & (Cube2)->pData[0])),\ - (((CubeR)->pData[1]) = ((Cube1)->pData[1] & (Cube2)->pData[1]))) -#define Mvc_CubeNBitAnd( CubeR, Cube1, Cube2 )\ -{\ - int _i_;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] & (Cube2)->pData[_i_]));\ -} - -#define Mvc_Cube1BitSharp( CubeR, Cube1, Cube2 )\ - (((CubeR)->pData[0]) = ((Cube1)->pData[0] & ~((Cube2)->pData[0]))) -#define Mvc_Cube2BitSharp( CubeR, Cube1, Cube2 )\ - ((((CubeR)->pData[0]) = ((Cube1)->pData[0] & ~((Cube2)->pData[0]))),\ - (((CubeR)->pData[1]) = ((Cube1)->pData[1] & ~((Cube2)->pData[1])))) -#define Mvc_CubeNBitSharp( CubeR, Cube1, Cube2 )\ -{\ - int _i_;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - (((CubeR)->pData[_i_]) = ((Cube1)->pData[_i_] & ~(Cube2)->pData[_i_]));\ -} - -#define Mvc_Cube1BitEmpty( Res, Cube )\ - (Res = ((Cube)->pData[0] == 0)) -#define Mvc_Cube2BitEmpty( Res, Cube )\ - (Res = ((Cube)->pData[0] == 0 && (Cube)->pData[1] == 0)) -#define Mvc_CubeNBitEmpty( Res, Cube )\ -{\ - int _i_; Res = 1;\ - for (_i_ = (Cube)->iLast; _i_ >= 0; _i_--)\ - if ( (Cube)->pData[_i_] )\ - { Res = 0; break; }\ -} - -#define Mvc_Cube1BitEqual( Res, Cube1, Cube2 )\ - (Res = (((Cube1)->pData[0]) == ((Cube2)->pData[0]))) -#define Mvc_Cube2BitEqual( Res, Cube1, Cube2 )\ - (Res = ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) &&\ - (((Cube1)->pData[1]) == ((Cube2)->pData[1])))) -#define Mvc_CubeNBitEqual( Res, Cube1, Cube2 )\ -{\ - int _i_; Res = 1;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - if (((Cube1)->pData[_i_]) != ((Cube2)->pData[_i_]))\ - { Res = 0; break; }\ -} - -#define Mvc_Cube1BitLess( Res, Cube1, Cube2 )\ - (Res = (((Cube1)->pData[0]) < ((Cube2)->pData[0]))) -#define Mvc_Cube2BitLess( Res, Cube1, Cube2 )\ - (Res = ((((Cube1)->pData[0]) < ((Cube2)->pData[0])) ||\ - ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) && (((Cube1)->pData[1]) < ((Cube2)->pData[1]))))) -#define Mvc_CubeNBitLess( Res, Cube1, Cube2 )\ -{\ - int _i_; Res = 1;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - if (((Cube1)->pData[_i_]) >= ((Cube2)->pData[_i_]))\ - { Res = 0; break; }\ -} - -#define Mvc_Cube1BitMore( Res, Cube1, Cube2 )\ - (Res = (((Cube1)->pData[0]) > ((Cube2)->pData[0]))) -#define Mvc_Cube2BitMore( Res, Cube1, Cube2 )\ - (Res = ((((Cube1)->pData[0]) > ((Cube2)->pData[0])) ||\ - ((((Cube1)->pData[0]) == ((Cube2)->pData[0])) && (((Cube1)->pData[1]) > ((Cube2)->pData[1]))))) -#define Mvc_CubeNBitMore( Res, Cube1, Cube2 )\ -{\ - int _i_; Res = 1;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - if (((Cube1)->pData[_i_]) <= ((Cube2)->pData[_i_]))\ - { Res = 0; break; }\ -} - -#define Mvc_Cube1BitNotImpl( Res, Cube1, Cube2 )\ - (Res = (((Cube1)->pData[0]) & ~((Cube2)->pData[0]))) -#define Mvc_Cube2BitNotImpl( Res, Cube1, Cube2 )\ - (Res = ((((Cube1)->pData[0]) & ~((Cube2)->pData[0])) ||\ - (((Cube1)->pData[1]) & ~((Cube2)->pData[1])))) -#define Mvc_CubeNBitNotImpl( Res, Cube1, Cube2 )\ -{\ - int _i_; Res = 0;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - if (((Cube1)->pData[_i_]) & ~((Cube2)->pData[_i_]))\ - { Res = 1; break; }\ -} - -#define Mvc_Cube1BitDisjoint( Res, Cube1, Cube2 )\ - (Res = ((((Cube1)->pData[0]) & ((Cube2)->pData[0])) == 0 )) -#define Mvc_Cube2BitDisjoint( Res, Cube1, Cube2 )\ - (Res = (((((Cube1)->pData[0]) & ((Cube2)->pData[0])) == 0 ) &&\ - ((((Cube1)->pData[1]) & ((Cube2)->pData[1])) == 0 ))) -#define Mvc_CubeNBitDisjoint( Res, Cube1, Cube2 )\ -{\ - int _i_; Res = 1;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - if (((Cube1)->pData[_i_]) & ((Cube2)->pData[_i_]))\ - { Res = 0; break; }\ -} - -#define Mvc_Cube1BitEqualUnderMask( Res, Cube1, Cube2, Mask )\ - (Res = ((((Cube1)->pData[0]) & ((Mask)->pData[0])) == (((Cube2)->pData[0]) & ((Mask)->pData[0])))) -#define Mvc_Cube2BitEqualUnderMask( Res, Cube1, Cube2, Mask )\ - (Res = (((((Cube1)->pData[0]) & ((Mask)->pData[0])) == (((Cube2)->pData[0]) & ((Mask)->pData[0]))) &&\ - ((((Cube1)->pData[1]) & ((Mask)->pData[1])) == (((Cube2)->pData[1]) & ((Mask)->pData[1]))))) -#define Mvc_CubeNBitEqualUnderMask( Res, Cube1, Cube2, Mask )\ -{\ - int _i_; Res = 1;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - if ((((Cube1)->pData[_i_]) & ((Mask)->pData[_i_])) != (((Cube2)->pData[_i_]) & ((Mask)->pData[_i_])))\ - { Res = 0; break; }\ -} - -#define Mvc_Cube1BitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ - (Res = ((((Cube1)->pData[0]) | ((Mask)->pData[0])) == (((Cube2)->pData[0]) | ((Mask)->pData[0])))) -#define Mvc_Cube2BitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ - (Res = (((((Cube1)->pData[0]) | ((Mask)->pData[0])) == (((Cube2)->pData[0]) | ((Mask)->pData[0]))) &&\ - ((((Cube1)->pData[1]) | ((Mask)->pData[1])) == (((Cube2)->pData[1]) | ((Mask)->pData[1]))))) -#define Mvc_CubeNBitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ -{\ - int _i_; Res = 1;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - if ((((Cube1)->pData[_i_]) | ((Mask)->pData[_i_])) != (((Cube2)->pData[_i_]) | ((Mask)->pData[_i_])))\ - { Res = 0; break; }\ -} - -#define Mvc_Cube1BitIntersectUnderMask( Res, Cube1, Cube2, Mask)\ - (Res = ((((Cube1)->pData[0]) & ((Cube2)->pData[0]) & ((Mask)->pData[0])) > 0)) -#define Mvc_Cube2BitIntersectUnderMask( Res, Cube1, Cube2, Mask)\ - (Res = (((((Cube1)->pData[0]) & ((Cube2)->pData[0]) & ((Mask)->pData[0])) > 0) ||\ - ((((Cube1)->pData[1]) & ((Cube2)->pData[1]) & ((Mask)->pData[1])) > 0))) -#define Mvc_CubeNBitIntersectUnderMask( Res, Cube1, Cube2, Mask)\ -{\ - int _i_; Res = 0;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - if (((Cube1)->pData[_i_]) & ((Cube2)->pData[_i_]) & ((Mask)->pData[_i_]))\ - { Res = 1; break; }\ -} - -#define Mvc_Cube1BitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ - (Res = (((Mask)->pData[0]) & ((Cube1)->pData[0]) & ~((Cube2)->pData[0]))) -#define Mvc_Cube2BitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ - (Res = ((((Mask)->pData[0]) & ((Cube1)->pData[0]) & ~((Cube2)->pData[0])) ||\ - (((Mask)->pData[1]) & ((Cube1)->pData[1]) & ~((Cube2)->pData[1])))) -#define Mvc_CubeNBitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ -{\ - int _i_; Res = 0;\ - for (_i_ = (Cube1)->iLast; _i_ >= 0; _i_--)\ - if (((Mask)->pData[_i_]) & ((Cube1)->pData[_i_]) & ~((Cube2)->pData[_i_]))\ - { Res = 1; break; }\ -} - -// the following macros make no assumption about the cube's bitset size -#define Mvc_CubeBitClean( Cube )\ - if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitClean( Cube ); }\ - else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitClean( Cube ); }\ - else { Mvc_CubeNBitClean( Cube ); } -#define Mvc_CubeBitFill( Cube )\ - if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitFill( Cube ); }\ - else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitFill( Cube ); }\ - else { Mvc_CubeNBitFill( Cube ); } -#define Mvc_CubeBitNot( Cube )\ - if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitNot( Cube ); }\ - else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitNot( Cube ); }\ - else { Mvc_CubeNBitNot( Cube ); } -#define Mvc_CubeBitCopy( Cube1, Cube2 )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitCopy( Cube1, Cube2 ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitCopy( Cube1, Cube2 ); }\ - else { Mvc_CubeNBitCopy( Cube1, Cube2 ); } -#define Mvc_CubeBitOr( CubeR, Cube1, Cube2 )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitOr( CubeR, Cube1, Cube2 ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitOr( CubeR, Cube1, Cube2 ); }\ - else { Mvc_CubeNBitOr( CubeR, Cube1, Cube2 ); } -#define Mvc_CubeBitExor( CubeR, Cube1, Cube2 )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitExor( CubeR, Cube1, Cube2 ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitExor( CubeR, Cube1, Cube2 ); }\ - else { Mvc_CubeNBitExor( CubeR, Cube1, Cube2 ); } -#define Mvc_CubeBitAnd( CubeR, Cube1, Cube2 )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitAnd( CubeR, Cube1, Cube2 ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitAnd( CubeR, Cube1, Cube2 ); }\ - else { Mvc_CubeNBitAnd( CubeR, Cube1, Cube2 ); } -#define Mvc_CubeBitSharp( CubeR, Cube1, Cube2 )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitSharp( CubeR, Cube1, Cube2 ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitSharp( CubeR, Cube1, Cube2 ); }\ - else { Mvc_CubeNBitSharp( CubeR, Cube1, Cube2 ); } -#define Mvc_CubeBitEmpty( Res, Cube )\ - if ( Mvc_Cube1Words(Cube) ) { Mvc_Cube1BitEmpty( Res, Cube ); }\ - else if ( Mvc_Cube2Words(Cube) ) { Mvc_Cube2BitEmpty( Res, Cube ); }\ - else { Mvc_CubeNBitEmpty( Res, Cube ); } -#define Mvc_CubeBitEqual( Res, Cube1, Cube2 )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqual( Res, Cube1, Cube2 ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqual( Res, Cube1, Cube2 ); }\ - else { Mvc_CubeNBitEqual( Res, Cube1, Cube2 ); } -#define Mvc_CubeBitLess( Res, Cube1, Cube2 )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitLess( Res, Cube1, Cube2 ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitLess( Res, Cube1, Cube2 ); }\ - else { Mvc_CubeNBitLess( Res, Cube1, Cube2 ); } -#define Mvc_CubeBitMore( Res, Cube1, Cube2 )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitMore( Res, Cube1, Cube2 ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitMore( Res, Cube1, Cube2 ); }\ - else { Mvc_CubeNBitMore( Res, Cube1, Cube2 ); } -#define Mvc_CubeBitNotImpl( Res, Cube1, Cube2 )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitNotImpl( Res, Cube1, Cube2 ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitNotImpl( Res, Cube1, Cube2 ); }\ - else { Mvc_CubeNBitNotImpl( Res, Cube1, Cube2 ); } -#define Mvc_CubeBitDisjoint( Res, Cube1, Cube2 )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitDisjoint( Res, Cube1, Cube2 ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitDisjoint( Res, Cube1, Cube2 ); }\ - else { Mvc_CubeNBitDisjoint( Res, Cube1, Cube2 ); } -#define Mvc_CubeBitEqualUnderMask( Res, Cube1, Cube2, Mask )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqualUnderMask( Res, Cube1, Cube2, Mask ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqualUnderMask( Res, Cube1, Cube2, Mask ); }\ - else { Mvc_CubeNBitEqualUnderMask( Res, Cube1, Cube2, Mask ); } -#define Mvc_CubeBitEqualOutsideMask( Res, Cube1, Cube2, Mask )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitEqualOutsideMask( Res, Cube1, Cube2, Mask ); }\ - else { Mvc_CubeNBitEqualOutsideMask( Res, Cube1, Cube2, Mask ); } -#define Mvc_CubeBitIntersectUnderMask( Res, Cube1, Cube2, Mask )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitIntersectUnderMask( Res, Cube1, Cube2, Mask ); }\ - else { Mvc_CubeNBitIntersectUnderMask( Res, Cube1, Cube2, Mask ); } -#define Mvc_CubeBitNotImplUnderMask( Res, Cube1, Cube2, Mask )\ - if ( Mvc_Cube1Words(Cube1) ) { Mvc_Cube1BitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }\ - else if ( Mvc_Cube2Words(Cube1) ){ Mvc_Cube2BitNotImplUnderMask( Res, Cube1, Cube2, Mask ); }\ - else { Mvc_CubeNBitNotImplUnderMask( Res, Cube1, Cube2, Mask ); } - - -// managing linked lists -#define Mvc_ListAddCubeHead( pList, pCube )\ - {\ - if ( pList->pHead == NULL )\ - {\ - Mvc_CubeSetNext( pCube, NULL );\ - pList->pHead = pCube;\ - pList->pTail = pCube;\ - }\ - else\ - {\ - Mvc_CubeSetNext( pCube, pList->pHead );\ - pList->pHead = pCube;\ - }\ - pList->nItems++;\ - } -#define Mvc_ListAddCubeTail( pList, pCube )\ - {\ - if ( pList->pHead == NULL )\ - pList->pHead = pCube;\ - else\ - Mvc_CubeSetNext( pList->pTail, pCube );\ - pList->pTail = pCube;\ - Mvc_CubeSetNext( pCube, NULL );\ - pList->nItems++;\ - } -#define Mvc_ListDeleteCube( pList, pPrev, pCube )\ -{\ - if ( pPrev == NULL )\ - pList->pHead = pCube->pNext;\ - else\ - pPrev->pNext = pCube->pNext;\ - if ( pList->pTail == pCube )\ - {\ - assert( pCube->pNext == NULL );\ - pList->pTail = pPrev;\ - }\ - pList->nItems--;\ -} - -// managing linked lists inside the cover -#define Mvc_CoverAddCubeHead( pCover, pCube )\ -{\ - Mvc_List_t * pList = &pCover->lCubes;\ - Mvc_ListAddCubeHead( pList, pCube );\ -} -#define Mvc_CoverAddCubeTail( pCover, pCube )\ -{\ - Mvc_List_t * pList = &pCover->lCubes;\ - Mvc_ListAddCubeTail( pList, pCube );\ -} -#define Mvc_CoverDeleteCube( pCover, pPrev, pCube )\ -{\ - Mvc_List_t * pList = &pCover->lCubes;\ - Mvc_ListDeleteCube( pList, pPrev, pCube );\ -} - - - - - - -// iterator through the cubes in the cube list -#define Mvc_ListForEachCube( List, Cube )\ - for ( Cube = List->pHead;\ - Cube;\ - Cube = Cube->pNext ) -#define Mvc_ListForEachCubeSafe( List, Cube, Cube2 )\ - for ( Cube = List->pHead, Cube2 = (Cube? Cube->pNext: NULL);\ - Cube;\ - Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) - -// iterator through cubes in the cover -#define Mvc_CoverForEachCube( Cover, Cube )\ - for ( Cube = (Cover)->lCubes.pHead;\ - Cube;\ - Cube = Cube->pNext ) -#define Mvc_CoverForEachCubeWithIndex( Cover, Cube, Index )\ - for ( Index = 0, Cube = (Cover)->lCubes.pHead;\ - Cube;\ - Index++, Cube = Cube->pNext ) -#define Mvc_CoverForEachCubeSafe( Cover, Cube, Cube2 )\ - for ( Cube = (Cover)->lCubes.pHead, Cube2 = (Cube? Cube->pNext: NULL);\ - Cube;\ - Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) - -// iterator which starts from the given cube -#define Mvc_CoverForEachCubeStart( Start, Cube )\ - for ( Cube = Start;\ - Cube;\ - Cube = Cube->pNext ) -#define Mvc_CoverForEachCubeStartSafe( Start, Cube, Cube2 )\ - for ( Cube = Start, Cube2 = (Cube? Cube->pNext: NULL);\ - Cube;\ - Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) - - -// iterator through literals of the cube -#define Mvc_CubeForEachBit( Cover, Cube, iBit, Value )\ - for ( iBit = 0;\ - iBit < Cover->nBits && ((Value = Mvc_CubeBitValue(Cube,iBit))>=0);\ - iBit++ ) -// iterator through values of binary variables -#define Mvc_CubeForEachVarValue( Cover, Cube, iVar, Value )\ - for ( iVar = 0;\ - iVar < Cover->nBits/2 && (Value = Mvc_CubeVarValue(Cube,iVar));\ - iVar++ ) - - -// macros which work with memory -// MEM_ALLOC: allocate the given number (Size) of items of type (Type) -// MEM_FREE: deallocate the pointer (Pointer) to the given number (Size) of items of type (Type) -#define MEM_ALLOC( Manager, Type, Size ) ((Type *)malloc( (Size) * sizeof(Type) )) -#define MEM_FREE( Manager, Type, Size, Pointer ) if ( Pointer ) { free(Pointer); Pointer = NULL; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== mvcApi.c ====================================================*/ -extern int Mvc_CoverReadWordNum( Mvc_Cover_t * pCover ); -extern int Mvc_CoverReadBitNum( Mvc_Cover_t * pCover ); -extern int Mvc_CoverReadCubeNum( Mvc_Cover_t * pCover ); -extern Mvc_Cube_t * Mvc_CoverReadCubeHead( Mvc_Cover_t * pCover ); -extern Mvc_Cube_t * Mvc_CoverReadCubeTail( Mvc_Cover_t * pCover ); -extern Mvc_List_t * Mvc_CoverReadCubeList( Mvc_Cover_t * pCover ); -extern int Mvc_ListReadCubeNum( Mvc_List_t * pList ); -extern Mvc_Cube_t * Mvc_ListReadCubeHead( Mvc_List_t * pList ); -extern Mvc_Cube_t * Mvc_ListReadCubeTail( Mvc_List_t * pList ); -extern void Mvc_CoverSetCubeNum( Mvc_Cover_t * pCover,int nItems ); -extern void Mvc_CoverSetCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -extern void Mvc_CoverSetCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -extern void Mvc_CoverSetCubeList( Mvc_Cover_t * pCover, Mvc_List_t * pList ); -extern int Mvc_CoverIsEmpty( Mvc_Cover_t * pCover ); -extern int Mvc_CoverIsTautology( Mvc_Cover_t * pCover ); -extern int Mvc_CoverIsBinaryBuffer( Mvc_Cover_t * pCover ); -extern void Mvc_CoverMakeEmpty( Mvc_Cover_t * pCover ); -extern void Mvc_CoverMakeTautology( Mvc_Cover_t * pCover ); -extern Mvc_Cover_t * Mvc_CoverCreateEmpty( Mvc_Cover_t * pCover ); -extern Mvc_Cover_t * Mvc_CoverCreateTautology( Mvc_Cover_t * pCover ); -/*=== mvcCover.c ====================================================*/ -extern Mvc_Cover_t * Mvc_CoverAlloc( Mvc_Manager_t * pMem, int nBits ); -extern Mvc_Cover_t * Mvc_CoverCreateConst( Mvc_Manager_t * pMem, int nBits, int Phase ); -extern Mvc_Cover_t * Mvc_CoverClone( Mvc_Cover_t * pCover ); -extern Mvc_Cover_t * Mvc_CoverDup( Mvc_Cover_t * pCover ); -extern void Mvc_CoverFree( Mvc_Cover_t * pCover ); -extern void Mvc_CoverAllocateMask( Mvc_Cover_t * pCover ); -extern void Mvc_CoverAllocateArrayLits( Mvc_Cover_t * pCover ); -extern void Mvc_CoverAllocateArrayCubes( Mvc_Cover_t * pCover ); -extern void Mvc_CoverDeallocateMask( Mvc_Cover_t * pCover ); -extern void Mvc_CoverDeallocateArrayLits( Mvc_Cover_t * pCover ); -/*=== mvcCube.c ====================================================*/ -extern Mvc_Cube_t * Mvc_CubeAlloc( Mvc_Cover_t * pCover ); -extern Mvc_Cube_t * Mvc_CubeDup( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -extern void Mvc_CubeFree( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -extern void Mvc_CubeBitRemoveDcs( Mvc_Cube_t * pCube ); -/*=== mvcCompare.c ====================================================*/ -extern int Mvc_CubeCompareInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); -extern int Mvc_CubeCompareSizeAndInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); -extern int Mvc_CubeCompareIntUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); -extern int Mvc_CubeCompareIntOutsideMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); -extern int Mvc_CubeCompareIntOutsideAndUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ); -/*=== mvcDd.c ====================================================*/ -/* -extern DdNode * Mvc_CoverConvertToBdd( DdManager * dd, Mvc_Cover_t * pCover ); -extern DdNode * Mvc_CoverConvertToZdd( DdManager * dd, Mvc_Cover_t * pCover ); -extern DdNode * Mvc_CoverConvertToZdd2( DdManager * dd, Mvc_Cover_t * pCover ); -extern DdNode * Mvc_CubeConvertToBdd( DdManager * dd, Mvc_Cube_t * pCube ); -extern DdNode * Mvc_CubeConvertToZdd( DdManager * dd, Mvc_Cube_t * pCube ); -extern DdNode * Mvc_CubeConvertToZdd2( DdManager * dd, Mvc_Cube_t * pCube ); -*/ -/*=== mvcDivisor.c ====================================================*/ -extern Mvc_Cover_t * Mvc_CoverDivisor( Mvc_Cover_t * pCover ); -/*=== mvcDivide.c ====================================================*/ -extern void Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); -extern void Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); -extern void Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); -extern void Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ); -extern void Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit ); -/*=== mvcList.c ====================================================*/ -// these functions are available as macros -extern void Mvc_ListAddCubeHead_( Mvc_List_t * pList, Mvc_Cube_t * pCube ); -extern void Mvc_ListAddCubeTail_( Mvc_List_t * pList, Mvc_Cube_t * pCube ); -extern void Mvc_ListDeleteCube_( Mvc_List_t * pList, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ); -extern void Mvc_CoverAddCubeHead_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -extern void Mvc_CoverAddCubeTail_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -extern void Mvc_CoverDeleteCube_( Mvc_Cover_t * pCover, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ); -extern void Mvc_CoverAddDupCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -extern void Mvc_CoverAddDupCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -// other functions -extern void Mvc_CoverAddLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -extern void Mvc_CoverDeleteLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -extern void Mvc_CoverList2Array( Mvc_Cover_t * pCover ); -extern void Mvc_CoverArray2List( Mvc_Cover_t * pCover ); -extern Mvc_Cube_t * Mvc_ListGetTailFromHead( Mvc_Cube_t * pHead ); -/*=== mvcPrint.c ====================================================*/ -extern void Mvc_CoverPrint( Mvc_Cover_t * pCover ); -extern void Mvc_CubePrint( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -extern void Mvc_CoverPrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover ); -extern void Mvc_CubePrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); -/*=== mvcSort.c ====================================================*/ -extern void Mvc_CoverSort( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ); -/*=== mvcUtils.c ====================================================*/ -extern void Mvc_CoverSupport( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp ); -extern int Mvc_CoverSupportSizeBinary( Mvc_Cover_t * pCover ); -extern int Mvc_CoverSupportVarBelongs( Mvc_Cover_t * pCover, int iVar ); -extern void Mvc_CoverCommonCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pComCube ); -extern int Mvc_CoverIsCubeFree( Mvc_Cover_t * pCover ); -extern void Mvc_CoverMakeCubeFree( Mvc_Cover_t * pCover ); -extern Mvc_Cover_t * Mvc_CoverCommonCubeCover( Mvc_Cover_t * pCover ); -extern int Mvc_CoverCheckSuppContainment( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); -extern int Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover ); -extern int Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube ); -extern int Mvc_CoverCountCubePairDiffs( Mvc_Cover_t * pCover, unsigned char pDiffs[] ); -extern Mvc_Cover_t * Mvc_CoverRemap( Mvc_Cover_t * pCover, int * pVarsRem, int nVarsRem ); -extern void Mvc_CoverInverse( Mvc_Cover_t * pCover ); -extern Mvc_Cover_t * Mvc_CoverRemoveDontCareLits( Mvc_Cover_t * pCover ); -extern Mvc_Cover_t * Mvc_CoverCofactor( Mvc_Cover_t * pCover, int iValue, int iValueOther ); -extern Mvc_Cover_t * Mvc_CoverFlipVar( Mvc_Cover_t * pCover, int iValue0, int iValue1 ); -extern Mvc_Cover_t * Mvc_CoverUnivQuantify( Mvc_Cover_t * p, int iValueA0, int iValueA1, int iValueB0, int iValueB1 ); -extern Mvc_Cover_t ** Mvc_CoverCofactors( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar ); -extern int Mvr_CoverCountLitsWithValue( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar, int iValue ); -//extern Mvc_Cover_t * Mvc_CoverCreateExpanded( Mvc_Cover_t * pCover, Vm_VarMap_t * pVmNew ); -extern Mvc_Cover_t * Mvc_CoverTranspose( Mvc_Cover_t * pCover ); -extern int Mvc_UtilsCheckUnusedZeros( Mvc_Cover_t * pCover ); -/*=== mvcLits.c ====================================================*/ -extern int Mvc_CoverAnyLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ); -extern int Mvc_CoverBestLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ); -extern int Mvc_CoverWorstLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ); -extern Mvc_Cover_t * Mvc_CoverBestLiteralCover( Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ); -extern int Mvc_CoverFirstCubeFirstLit( Mvc_Cover_t * pCover ); -extern int Mvc_CoverCountLiterals( Mvc_Cover_t * pCover ); -extern int Mvc_CoverIsOneLiteral( Mvc_Cover_t * pCover ); -/*=== mvcOpAlg.c ====================================================*/ -extern Mvc_Cover_t * Mvc_CoverAlgebraicMultiply( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); -extern Mvc_Cover_t * Mvc_CoverAlgebraicSubtract( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); -extern int Mvc_CoverAlgebraicEqual( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); -/*=== mvcOpBool.c ====================================================*/ -extern Mvc_Cover_t * Mvc_CoverBooleanOr( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); -extern Mvc_Cover_t * Mvc_CoverBooleanAnd( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); -extern int Mvc_CoverBooleanEqual( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ); - -/*=== mvcContain.c ====================================================*/ -extern int Mvc_CoverContain( Mvc_Cover_t * pCover ); -/*=== mvcTau.c ====================================================*/ -extern int Mvc_CoverTautology( Mvc_Data_t * p, Mvc_Cover_t * pCover ); -/*=== mvcCompl.c ====================================================*/ -extern Mvc_Cover_t * Mvc_CoverComplement( Mvc_Data_t * p, Mvc_Cover_t * pCover ); -/*=== mvcSharp.c ====================================================*/ -extern Mvc_Cover_t * Mvc_CoverSharp( Mvc_Data_t * p, Mvc_Cover_t * pA, Mvc_Cover_t * pB ); -extern int Mvc_CoverDist0Cubes( Mvc_Data_t * pData, Mvc_Cube_t * pA, Mvc_Cube_t * pB ); -extern void Mvc_CoverIntersectCubes( Mvc_Data_t * pData, Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); -extern int Mvc_CoverIsIntersecting( Mvc_Data_t * pData, Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); -extern void Mvc_CoverAppendCubes( Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); -extern void Mvc_CoverCopyAndAppendCubes( Mvc_Cover_t * pC1, Mvc_Cover_t * pC2 ); -extern void Mvc_CoverRemoveCubes( Mvc_Cover_t * pC ); - -/*=== mvcReshape.c ====================================================*/ -extern void Mvc_CoverMinimizeByReshape( Mvc_Data_t * pData, Mvc_Cover_t * pCover ); - -/*=== mvcMerge.c ====================================================*/ -extern void Mvc_CoverDist1Merge( Mvc_Data_t * p, Mvc_Cover_t * pCover ); - -/*=== mvcData.c ====================================================*/ -//extern Mvc_Data_t * Mvc_CoverDataAlloc( Vm_VarMap_t * pVm, Mvc_Cover_t * pCover ); -//extern void Mvc_CoverDataFree( Mvc_Data_t * p, Mvc_Cover_t * pCover ); - -/*=== mvcMan.c ====================================================*/ -extern void Mvc_ManagerFree( Mvc_Manager_t * p ); -extern Mvc_Manager_t * Mvc_ManagerStart(); -extern Mvc_Manager_t * Mvc_ManagerAllocCover(); -extern Mvc_Manager_t * Mvc_ManagerAllocCube( int nWords ); -extern Mvc_Manager_t * Mvc_ManagerFreeCover( Mvc_Cover_t * pCover ); -extern Mvc_Manager_t * Mvc_ManagerFreeCube( Mvc_Cover_t * pCube, int nWords ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/misc/mvc/mvcApi.c b/src/misc/mvc/mvcApi.c deleted file mode 100644 index eb942f93..00000000 --- a/src/misc/mvc/mvcApi.c +++ /dev/null @@ -1,233 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcApi.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcApi.c,v 1.4 2003/04/03 06:31:48 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverReadWordNum( Mvc_Cover_t * pCover ) { return pCover->nWords; } -int Mvc_CoverReadBitNum( Mvc_Cover_t * pCover ) { return pCover->nBits; } -int Mvc_CoverReadCubeNum( Mvc_Cover_t * pCover ) { return pCover->lCubes.nItems; } -Mvc_Cube_t * Mvc_CoverReadCubeHead( Mvc_Cover_t * pCover ) { return pCover->lCubes.pHead; } -Mvc_Cube_t * Mvc_CoverReadCubeTail( Mvc_Cover_t * pCover ) { return pCover->lCubes.pTail; } -Mvc_List_t * Mvc_CoverReadCubeList( Mvc_Cover_t * pCover ) { return &pCover->lCubes; } - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_ListReadCubeNum( Mvc_List_t * pList ) { return pList->nItems; } -Mvc_Cube_t * Mvc_ListReadCubeHead( Mvc_List_t * pList ) { return pList->pHead; } -Mvc_Cube_t * Mvc_ListReadCubeTail( Mvc_List_t * pList ) { return pList->pTail; } - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverSetCubeNum( Mvc_Cover_t * pCover,int nItems ) { pCover->lCubes.nItems = nItems; } -void Mvc_CoverSetCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { pCover->lCubes.pHead = pCube; } -void Mvc_CoverSetCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) { pCover->lCubes.pTail = pCube; } -void Mvc_CoverSetCubeList( Mvc_Cover_t * pCover, Mvc_List_t * pList ) { pCover->lCubes = *pList; } - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverIsEmpty( Mvc_Cover_t * pCover ) -{ - return Mvc_CoverReadCubeNum(pCover) == 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverIsTautology( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - int iBit, Value; - - if ( Mvc_CoverReadCubeNum(pCover) != 1 ) - return 0; - - pCube = Mvc_CoverReadCubeHead( pCover ); - Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) - if ( Value == 0 ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the cover is a binary buffer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverIsBinaryBuffer( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - if ( pCover->nBits != 2 ) - return 0; - if ( Mvc_CoverReadCubeNum(pCover) != 1 ) - return 0; - pCube = pCover->lCubes.pHead; - if ( Mvc_CubeBitValue(pCube, 0) == 0 && Mvc_CubeBitValue(pCube, 1) == 1 ) - return 1; - return 0; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverMakeEmpty( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube, * pCube2; - Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 ) - Mvc_CubeFree( pCover, pCube ); - pCover->lCubes.nItems = 0; - pCover->lCubes.pHead = NULL; - pCover->lCubes.pTail = NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverMakeTautology( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCubeNew; - Mvc_CoverMakeEmpty( pCover ); - pCubeNew = Mvc_CubeAlloc( pCover ); - Mvc_CubeBitFill( pCubeNew ); - Mvc_CoverAddCubeTail( pCover, pCubeNew ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverCreateEmpty( Mvc_Cover_t * pCover ) -{ - Mvc_Cover_t * pCoverNew; - pCoverNew = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); - return pCoverNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverCreateTautology( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCubeNew; - Mvc_Cover_t * pCoverNew; - pCoverNew = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); - pCubeNew = Mvc_CubeAlloc( pCoverNew ); - Mvc_CubeBitFill( pCubeNew ); - Mvc_CoverAddCubeTail( pCoverNew, pCubeNew ); - return pCoverNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcCompare.c b/src/misc/mvc/mvcCompare.c deleted file mode 100644 index 9cff99cd..00000000 --- a/src/misc/mvc/mvcCompare.c +++ /dev/null @@ -1,369 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcCompare.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Various cube comparison functions.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcCompare.c,v 1.5 2003/04/03 23:25:41 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Compares two cubes according to their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CubeCompareInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) -{ - if ( Mvc_Cube1Words(pC1) ) - { - if ( pC1->pData[0] < pC2->pData[0] ) - return -1; - if ( pC1->pData[0] > pC2->pData[0] ) - return 1; - return 0; - } - else if ( Mvc_Cube2Words(pC1) ) - { - if ( pC1->pData[1] < pC2->pData[1] ) - return -1; - if ( pC1->pData[1] > pC2->pData[1] ) - return 1; - if ( pC1->pData[0] < pC2->pData[0] ) - return -1; - if ( pC1->pData[0] > pC2->pData[0] ) - return 1; - return 0; - } - else - { - int i = Mvc_CubeReadLast(pC1); - for(; i >= 0; i--) - { - if ( pC1->pData[i] < pC2->pData[i] ) - return -1; - if ( pC1->pData[i] > pC2->pData[i] ) - return 1; - } - return 0; - } -} - - -/**Function************************************************************* - - Synopsis [Compares the cubes (1) by size, (2) by integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CubeCompareSizeAndInt( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) -{ - // compare the cubes by size - if ( Mvc_CubeReadSize( pC1 ) < Mvc_CubeReadSize( pC2 ) ) - return 1; - if ( Mvc_CubeReadSize( pC1 ) > Mvc_CubeReadSize( pC2 ) ) - return -1; - // the cubes have the same size - - // compare the cubes as integers - if ( Mvc_Cube1Words( pC1 ) ) - { - if ( pC1->pData[0] < pC2->pData[0] ) - return -1; - if ( pC1->pData[0] > pC2->pData[0] ) - return 1; - return 0; - } - else if ( Mvc_Cube2Words( pC1 ) ) - { - if ( pC1->pData[1] < pC2->pData[1] ) - return -1; - if ( pC1->pData[1] > pC2->pData[1] ) - return 1; - if ( pC1->pData[0] < pC2->pData[0] ) - return -1; - if ( pC1->pData[0] > pC2->pData[0] ) - return 1; - return 0; - } - else - { - int i = Mvc_CubeReadLast( pC1 ); - for(; i >= 0; i--) - { - if ( pC1->pData[i] < pC2->pData[i] ) - return -1; - if ( pC1->pData[i] > pC2->pData[i] ) - return 1; - } - return 0; - } -} - -/**Function************************************************************* - - Synopsis [Compares two cubes under the mask.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CubeCompareIntUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) -{ - unsigned uBits1, uBits2; - - // compare the cubes under the mask - if ( Mvc_Cube1Words(pC1) ) - { - uBits1 = pC1->pData[0] & pMask->pData[0]; - uBits2 = pC2->pData[0] & pMask->pData[0]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - // cubes are equal - return 0; - } - else if ( Mvc_Cube2Words(pC1) ) - { - uBits1 = pC1->pData[1] & pMask->pData[1]; - uBits2 = pC2->pData[1] & pMask->pData[1]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - uBits1 = pC1->pData[0] & pMask->pData[0]; - uBits2 = pC2->pData[0] & pMask->pData[0]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - return 0; - } - else - { - int i = Mvc_CubeReadLast(pC1); - for(; i >= 0; i--) - { - uBits1 = pC1->pData[i] & pMask->pData[i]; - uBits2 = pC2->pData[i] & pMask->pData[i]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - } - return 0; - } -} - -/**Function************************************************************* - - Synopsis [Compares two cubes under the mask.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CubeCompareIntOutsideMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) -{ - unsigned uBits1, uBits2; - - // compare the cubes under the mask - if ( Mvc_Cube1Words(pC1) ) - { - uBits1 = pC1->pData[0] | pMask->pData[0]; - uBits2 = pC2->pData[0] | pMask->pData[0]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - // cubes are equal - return 0; - } - else if ( Mvc_Cube2Words(pC1) ) - { - uBits1 = pC1->pData[1] | pMask->pData[1]; - uBits2 = pC2->pData[1] | pMask->pData[1]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - uBits1 = pC1->pData[0] | pMask->pData[0]; - uBits2 = pC2->pData[0] | pMask->pData[0]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - return 0; - } - else - { - int i = Mvc_CubeReadLast(pC1); - for(; i >= 0; i--) - { - uBits1 = pC1->pData[i] | pMask->pData[i]; - uBits2 = pC2->pData[i] | pMask->pData[i]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - } - return 0; - } -} - - -/**Function************************************************************* - - Synopsis [Compares the cubes (1) outside the mask, (2) under the mask.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CubeCompareIntOutsideAndUnderMask( Mvc_Cube_t * pC1, Mvc_Cube_t * pC2, Mvc_Cube_t * pMask ) -{ - unsigned uBits1, uBits2; - - if ( Mvc_Cube1Words(pC1) ) - { - // compare the cubes outside the mask - uBits1 = pC1->pData[0] & ~(pMask->pData[0]); - uBits2 = pC2->pData[0] & ~(pMask->pData[0]); - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - - // compare the cubes under the mask - uBits1 = pC1->pData[0] & pMask->pData[0]; - uBits2 = pC2->pData[0] & pMask->pData[0]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - // cubes are equal - // should never happen - assert( 0 ); - return 0; - } - else if ( Mvc_Cube2Words(pC1) ) - { - // compare the cubes outside the mask - uBits1 = pC1->pData[1] & ~(pMask->pData[1]); - uBits2 = pC2->pData[1] & ~(pMask->pData[1]); - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - - uBits1 = pC1->pData[0] & ~(pMask->pData[0]); - uBits2 = pC2->pData[0] & ~(pMask->pData[0]); - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - - // compare the cubes under the mask - uBits1 = pC1->pData[1] & pMask->pData[1]; - uBits2 = pC2->pData[1] & pMask->pData[1]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - - uBits1 = pC1->pData[0] & pMask->pData[0]; - uBits2 = pC2->pData[0] & pMask->pData[0]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - - // cubes are equal - // should never happen - assert( 0 ); - return 0; - } - else - { - int i; - - // compare the cubes outside the mask - for( i = Mvc_CubeReadLast(pC1); i >= 0; i-- ) - { - uBits1 = pC1->pData[i] & ~(pMask->pData[i]); - uBits2 = pC2->pData[i] & ~(pMask->pData[i]); - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - } - // compare the cubes under the mask - for( i = Mvc_CubeReadLast(pC1); i >= 0; i-- ) - { - uBits1 = pC1->pData[i] & pMask->pData[i]; - uBits2 = pC2->pData[i] & pMask->pData[i]; - if ( uBits1 < uBits2 ) - return -1; - if ( uBits1 > uBits2 ) - return 1; - } -/* - { - Mvc_Cover_t * pCover; - pCover = Mvc_CoverAlloc( NULL, 96 ); - Mvc_CubePrint( pCover, pC1 ); - Mvc_CubePrint( pCover, pC2 ); - Mvc_CubePrint( pCover, pMask ); - } -*/ - // cubes are equal - // should never happen - assert( 0 ); - return 0; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcContain.c b/src/misc/mvc/mvcContain.c deleted file mode 100644 index a9eae06e..00000000 --- a/src/misc/mvc/mvcContain.c +++ /dev/null @@ -1,173 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcContain.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Making the cover single-cube containment free.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcContain.c,v 1.4 2003/04/03 23:25:42 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover ); -static void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -/**Function************************************************************* - - Synopsis [Removes the contained cubes.] - - Description [Returns 1 if the cover has been changed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverContain( Mvc_Cover_t * pCover ) -{ - int nCubes; - nCubes = Mvc_CoverReadCubeNum( pCover ); - if ( nCubes < 2 ) - return 0; - Mvc_CoverSetCubeSizes(pCover); - Mvc_CoverSort( pCover, NULL, Mvc_CubeCompareSizeAndInt ); - Mvc_CoverRemoveDuplicates( pCover ); - if ( nCubes > 1 ) - Mvc_CoverRemoveContained( pCover ); - return (nCubes != Mvc_CoverReadCubeNum(pCover)); -} - -/**Function************************************************************* - - Synopsis [Removes adjacent duplicated cubes from the cube list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverRemoveDuplicates( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pPrev, * pCube, * pCube2; - int fEqual; - - // set the first cube of the cover - pPrev = Mvc_CoverReadCubeHead(pCover); - // go through all the cubes after this one - Mvc_CoverForEachCubeStartSafe( Mvc_CubeReadNext(pPrev), pCube, pCube2 ) - { - // compare the current cube with the prev cube - Mvc_CubeBitEqual( fEqual, pPrev, pCube ); - if ( fEqual ) - { // they are equal - remove the current cube - Mvc_CoverDeleteCube( pCover, pPrev, pCube ); - Mvc_CubeFree( pCover, pCube ); - // don't change the previous cube cube - } - else - { // they are not equal - update the previous cube - pPrev = pCube; - } - } -} - -/**Function************************************************************* - - Synopsis [Removes contained cubes from the sorted cube list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverRemoveContained( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCubeBeg, * pCubeEnd, * pCubeLarge; - Mvc_Cube_t * pCube, * pCube2, * pPrev; - unsigned sizeCur; - int Result; - - // since the cubes are sorted by size, it is sufficient - // to compare each cube with other cubes that have larger sizes - // if the given cube implies a larger cube, the larger cube is removed - pCubeBeg = Mvc_CoverReadCubeHead(pCover); - do - { - // get the current cube size - sizeCur = Mvc_CubeReadSize(pCubeBeg); - - // initialize the end of the given size group - pCubeEnd = pCubeBeg; - // find the beginning of the next size group - Mvc_CoverForEachCubeStart( Mvc_CubeReadNext(pCubeBeg), pCube ) - { - if ( sizeCur == Mvc_CubeReadSize(pCube) ) - pCubeEnd = pCube; - else // pCube is the first cube in the new size group - break; - } - // if we could not find the next size group - // the containment check is finished - if ( pCube == NULL ) - break; - // otherwise, pCubeBeg/pCubeEnd are the first/last cubes of the group - - // go through all the cubes between pCubeBeg and pCubeEnd, inclusive, - // and for each of them, try removing cubes after pCubeEnd - Mvc_CoverForEachCubeStart( pCubeBeg, pCubeLarge ) - { - pPrev = pCubeEnd; - Mvc_CoverForEachCubeStartSafe( Mvc_CubeReadNext(pCubeEnd), pCube, pCube2 ) - { - // check containment - Mvc_CubeBitNotImpl( Result, pCube, pCubeLarge ); - if ( !Result ) - { // pCubeLarge implies pCube - remove pCube - Mvc_CoverDeleteCube( pCover, pPrev, pCube ); - Mvc_CubeFree( pCover, pCube ); - // don't update the previous cube - } - else - { // update the previous cube - pPrev = pCube; - } - } - // quit, if the main cube was the last one of this size - if ( pCubeLarge == pCubeEnd ) - break; - } - - // set the beginning of the next group - pCubeBeg = Mvc_CubeReadNext(pCubeEnd); - } - while ( pCubeBeg ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcCover.c b/src/misc/mvc/mvcCover.c deleted file mode 100644 index d8584446..00000000 --- a/src/misc/mvc/mvcCover.c +++ /dev/null @@ -1,251 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcCover.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Basic procedures to manipulate unate cube covers.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcCover.c,v 1.5 2003/04/09 18:02:05 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverAlloc( Mvc_Manager_t * pMem, int nBits ) -{ - Mvc_Cover_t * p; - int nBitsInUnsigned; - - nBitsInUnsigned = 8 * sizeof(Mvc_CubeWord_t); -#ifdef USE_SYSTEM_MEMORY_MANAGEMENT - p = (Mvc_Cover_t *)malloc( sizeof(Mvc_Cover_t) ); -#else - p = (Mvc_Cover_t *)Extra_MmFixedEntryFetch( pMem->pManC ); -#endif - p->pMem = pMem; - p->nBits = nBits; - p->nWords = nBits / nBitsInUnsigned + (int)(nBits % nBitsInUnsigned > 0); - p->nUnused = p->nWords * nBitsInUnsigned - p->nBits; - p->lCubes.nItems = 0; - p->lCubes.pHead = NULL; - p->lCubes.pTail = NULL; - p->nCubesAlloc = 0; - p->pCubes = NULL; - p->pMask = NULL; - p->pLits = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverClone( Mvc_Cover_t * p ) -{ - Mvc_Cover_t * pCover; -#ifdef USE_SYSTEM_MEMORY_MANAGEMENT - pCover = (Mvc_Cover_t *)malloc( sizeof(Mvc_Cover_t) ); -#else - pCover = (Mvc_Cover_t *)Extra_MmFixedEntryFetch( p->pMem->pManC ); -#endif - pCover->pMem = p->pMem; - pCover->nBits = p->nBits; - pCover->nWords = p->nWords; - pCover->nUnused = p->nUnused; - pCover->lCubes.nItems = 0; - pCover->lCubes.pHead = NULL; - pCover->lCubes.pTail = NULL; - pCover->nCubesAlloc = 0; - pCover->pCubes = NULL; - pCover->pMask = NULL; - pCover->pLits = NULL; - return pCover; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverDup( Mvc_Cover_t * p ) -{ - Mvc_Cover_t * pCover; - Mvc_Cube_t * pCube, * pCubeCopy; - // clone the cover - pCover = Mvc_CoverClone( p ); - // copy the cube list - Mvc_CoverForEachCube( p, pCube ) - { - pCubeCopy = Mvc_CubeDup( p, pCube ); - Mvc_CoverAddCubeTail( pCover, pCubeCopy ); - } - return pCover; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverFree( Mvc_Cover_t * p ) -{ - Mvc_Cube_t * pCube, * pCube2; - // recycle cube list - Mvc_CoverForEachCubeSafe( p, pCube, pCube2 ) - Mvc_CubeFree( p, pCube ); - // recycle other pointers - Mvc_CubeFree( p, p->pMask ); - MEM_FREE( p->pMem, Mvc_Cube_t *, p->nCubesAlloc, p->pCubes ); - MEM_FREE( p->pMem, int, p->nBits, p->pLits ); - -#ifdef USE_SYSTEM_MEMORY_MANAGEMENT - free( p ); -#else - Extra_MmFixedEntryRecycle( p->pMem->pManC, (char *)p ); -#endif -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverAllocateMask( Mvc_Cover_t * pCover ) -{ - if ( pCover->pMask == NULL ) - pCover->pMask = Mvc_CubeAlloc( pCover ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverAllocateArrayLits( Mvc_Cover_t * pCover ) -{ - if ( pCover->pLits == NULL ) - pCover->pLits = MEM_ALLOC( pCover->pMem, int, pCover->nBits ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverAllocateArrayCubes( Mvc_Cover_t * pCover ) -{ - if ( pCover->nCubesAlloc < pCover->lCubes.nItems ) - { - if ( pCover->nCubesAlloc > 0 ) - MEM_FREE( pCover->pMem, Mvc_Cube_t *, pCover->nCubesAlloc, pCover->pCubes ); - pCover->nCubesAlloc = pCover->lCubes.nItems; - pCover->pCubes = MEM_ALLOC( pCover->pMem, Mvc_Cube_t *, pCover->nCubesAlloc ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverDeallocateMask( Mvc_Cover_t * pCover ) -{ - Mvc_CubeFree( pCover, pCover->pMask ); - pCover->pMask = NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverDeallocateArrayLits( Mvc_Cover_t * pCover ) -{ - if ( pCover->pLits ) - { - MEM_FREE( pCover->pMem, int, pCover->nBits, pCover->pLits ); - pCover->pLits = NULL; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcCube.c b/src/misc/mvc/mvcCube.c deleted file mode 100644 index e157879f..00000000 --- a/src/misc/mvc/mvcCube.c +++ /dev/null @@ -1,175 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcCube.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Manipulating unate cubes.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcCube.c,v 1.4 2003/04/03 06:31:49 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cube_t * Mvc_CubeAlloc( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - - assert( pCover->nWords >= 0 ); - // allocate the cube -#ifdef USE_SYSTEM_MEMORY_MANAGEMENT - if ( pCover->nWords == 0 ) - pCube = (Mvc_Cube_t *)malloc( sizeof(Mvc_Cube_t) ); - else - pCube = (Mvc_Cube_t *)malloc( sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) * (pCover->nWords - 1) ); -#else - switch( pCover->nWords ) - { - case 0: - case 1: - pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan1 ); - break; - case 2: - pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan2 ); - break; - case 3: - case 4: - pCube = (Mvc_Cube_t *)Extra_MmFixedEntryFetch( pCover->pMem->pMan4 ); - break; - default: - pCube = (Mvc_Cube_t *)malloc( sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) * (pCover->nWords - 1) ); - break; - } -#endif - // set the parameters charactering this cube - if ( pCover->nWords == 0 ) - pCube->iLast = pCover->nWords; - else - pCube->iLast = pCover->nWords - 1; - pCube->nUnused = pCover->nUnused; - return pCube; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cube_t * Mvc_CubeDup( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) -{ - Mvc_Cube_t * pCubeCopy; - pCubeCopy = Mvc_CubeAlloc( pCover ); - Mvc_CubeBitCopy( pCubeCopy, pCube ); - return pCubeCopy; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CubeFree( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) -{ - if ( pCube == NULL ) - return; - - // verify the parameters charactering this cube - assert( pCube->iLast == 0 || ((int)pCube->iLast) == pCover->nWords - 1 ); - assert( ((int)pCube->nUnused) == pCover->nUnused ); - - // deallocate the cube -#ifdef USE_SYSTEM_MEMORY_MANAGEMENT - free( pCube ); -#else - switch( pCover->nWords ) - { - case 0: - case 1: - Extra_MmFixedEntryRecycle( pCover->pMem->pMan1, (char *)pCube ); - break; - case 2: - Extra_MmFixedEntryRecycle( pCover->pMem->pMan2, (char *)pCube ); - break; - case 3: - case 4: - Extra_MmFixedEntryRecycle( pCover->pMem->pMan4, (char *)pCube ); - break; - default: - free( pCube ); - break; - } -#endif -} - - -/**Function************************************************************* - - Synopsis [Removes the don't-care variable from the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CubeBitRemoveDcs( Mvc_Cube_t * pCube ) -{ - unsigned Mask; - int i; - for ( i = Mvc_CubeReadLast(pCube); i >= 0; i-- ) - { - // detect those variables that are different (not DCs) - Mask = (pCube->pData[i] ^ (pCube->pData[i] >> 1)) & BITS_DISJOINT; - // create the mask of all that are different - Mask |= (Mask << 1); - // remove other bits from the set - pCube->pData[i] &= Mask; - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcDivide.c b/src/misc/mvc/mvcDivide.c deleted file mode 100644 index 03643dcf..00000000 --- a/src/misc/mvc/mvcDivide.c +++ /dev/null @@ -1,436 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcDivide.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Procedures for algebraic division.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcDivide.c,v 1.5 2003/04/26 20:41:36 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem ); - -int s_fVerbose = 0; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverDivide( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) -{ - // check the number of cubes - if ( Mvc_CoverReadCubeNum( pCover ) < Mvc_CoverReadCubeNum( pDiv ) ) - { - *ppQuo = NULL; - *ppRem = NULL; - return; - } - - // make sure that support of pCover contains that of pDiv - if ( !Mvc_CoverCheckSuppContainment( pCover, pDiv ) ) - { - *ppQuo = NULL; - *ppRem = NULL; - return; - } - - // perform the general division - Mvc_CoverDivideInternal( pCover, pDiv, ppQuo, ppRem ); -} - - -/**Function************************************************************* - - Synopsis [Merge the cubes inside the groups.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverDivideInternal( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) -{ - Mvc_Cover_t * pQuo, * pRem; - Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy; - Mvc_Cube_t * pCube1, * pCube2; - int * pGroups, nGroups; // the cube groups - int nCubesC, nCubesD, nMerges, iCubeC, iCubeD, iMerge; - int fSkipG, GroupSize, g, c, RetValue; - int nCubes; - - // get cover sizes - nCubesD = Mvc_CoverReadCubeNum( pDiv ); - nCubesC = Mvc_CoverReadCubeNum( pCover ); - - // check trivial cases - if ( nCubesD == 1 ) - { - if ( Mvc_CoverIsOneLiteral( pDiv ) ) - Mvc_CoverDivideByLiteral( pCover, pDiv, ppQuo, ppRem ); - else - Mvc_CoverDivideByCube( pCover, pDiv, ppQuo, ppRem ); - return; - } - - // create the divisor and the remainder - pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); - pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); - - // get the support of the divisor - Mvc_CoverAllocateMask( pDiv ); - Mvc_CoverSupport( pDiv, pDiv->pMask ); - - // sort the cubes of the divisor - Mvc_CoverSort( pDiv, NULL, Mvc_CubeCompareInt ); - // sort the cubes of the cover - Mvc_CoverSort( pCover, pDiv->pMask, Mvc_CubeCompareIntOutsideAndUnderMask ); - - // allocate storage for cube groups - pGroups = MEM_ALLOC( pCover->pMem, int, nCubesC + 1 ); - - // mask contains variables in the support of Div - // split the cubes into groups using the mask - Mvc_CoverList2Array( pCover ); - Mvc_CoverList2Array( pDiv ); - pGroups[0] = 0; - nGroups = 1; - for ( c = 1; c < nCubesC; c++ ) - { - // get the cubes - pCube1 = pCover->pCubes[c-1]; - pCube2 = pCover->pCubes[c ]; - // compare the cubes - Mvc_CubeBitEqualOutsideMask( RetValue, pCube1, pCube2, pDiv->pMask ); - if ( !RetValue ) - pGroups[nGroups++] = c; - } - // finish off the last group - pGroups[nGroups] = nCubesC; - - // consider each group separately and decide - // whether it can produce a quotient cube - nCubes = 0; - for ( g = 0; g < nGroups; g++ ) - { - // if the group has less than nCubesD cubes, - // there is no way it can produce the quotient cube - // copy the cubes to the remainder - GroupSize = pGroups[g+1] - pGroups[g]; - if ( GroupSize < nCubesD ) - { - for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) - { - pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] ); - Mvc_CoverAddCubeTail( pRem, pCubeCopy ); - nCubes++; - } - continue; - } - - // mark the cubes as those that should be added to the remainder - for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) - Mvc_CubeSetSize( pCover->pCubes[c], 1 ); - - // go through the cubes in the group and at the same time - // go through the cubes in the divisor - iCubeD = 0; - iCubeC = 0; - pCubeD = pDiv->pCubes[iCubeD++]; - pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; - fSkipG = 0; - nMerges = 0; - - while ( 1 ) - { - // compare the topmost cubes in F and in D - RetValue = Mvc_CubeCompareIntUnderMask( pCubeC, pCubeD, pDiv->pMask ); - // cube are ordered in increasing order of their int value - if ( RetValue == -1 ) // pCubeC is above pCubeD - { // cube in C should be added to the remainder - // check that there is enough cubes in the group - if ( GroupSize - iCubeC < nCubesD - nMerges ) - { - fSkipG = 1; - break; - } - // get the next cube in the cover - pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; - continue; - } - if ( RetValue == 1 ) // pCubeD is above pCubeC - { // given cube in D does not have a corresponding cube in the cover - fSkipG = 1; - break; - } - // mark the cube as the one that should NOT be added to the remainder - Mvc_CubeSetSize( pCubeC, 0 ); - // remember this merged cube - iMerge = iCubeC-1; - nMerges++; - - // stop if we considered the last cube of the group - if ( iCubeD == nCubesD ) - break; - - // advance the cube of the divisor - assert( iCubeD < nCubesD ); - pCubeD = pDiv->pCubes[iCubeD++]; - - // advance the cube of the group - assert( pGroups[g]+iCubeC < nCubesC ); - pCubeC = pCover->pCubes[pGroups[g]+iCubeC++]; - } - - if ( fSkipG ) - { - // the group has failed, add all the cubes to the remainder - for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) - { - pCubeCopy = Mvc_CubeDup( pRem, pCover->pCubes[c] ); - Mvc_CoverAddCubeTail( pRem, pCubeCopy ); - nCubes++; - } - continue; - } - - // the group has worked, add left-over cubes to the remainder - for ( c = pGroups[g]; c < pGroups[g+1]; c++ ) - { - pCubeC = pCover->pCubes[c]; - if ( Mvc_CubeReadSize(pCubeC) ) - { - pCubeCopy = Mvc_CubeDup( pRem, pCubeC ); - Mvc_CoverAddCubeTail( pRem, pCubeCopy ); - nCubes++; - } - } - - // create the quotient cube - pCube1 = Mvc_CubeAlloc( pQuo ); - Mvc_CubeBitSharp( pCube1, pCover->pCubes[pGroups[g]+iMerge], pDiv->pMask ); - // add the cube to the quotient - Mvc_CoverAddCubeTail( pQuo, pCube1 ); - nCubes += nCubesD; - } - assert( nCubes == nCubesC ); - - // deallocate the memory - MEM_FREE( pCover->pMem, int, nCubesC + 1, pGroups ); - - // return the results - *ppRem = pRem; - *ppQuo = pQuo; -// Mvc_CoverVerifyDivision( pCover, pDiv, pQuo, pRem ); -} - - -/**Function************************************************************* - - Synopsis [Divides the cover by a cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverDivideByCube( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) -{ - Mvc_Cover_t * pQuo, * pRem; - Mvc_Cube_t * pCubeC, * pCubeD, * pCubeCopy; - int CompResult; - - // get the only cube of D - assert( Mvc_CoverReadCubeNum(pDiv) == 1 ); - - // start the quotient and the remainder - pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); - pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); - - // get the first and only cube of the divisor - pCubeD = Mvc_CoverReadCubeHead( pDiv ); - - // iterate through the cubes in the cover - Mvc_CoverForEachCube( pCover, pCubeC ) - { - // check the containment of literals from pCubeD in pCube - Mvc_Cube2BitNotImpl( CompResult, pCubeD, pCubeC ); - if ( !CompResult ) - { // this cube belongs to the quotient - // alloc the cube - pCubeCopy = Mvc_CubeAlloc( pQuo ); - // clean the support of D - Mvc_CubeBitSharp( pCubeCopy, pCubeC, pCubeD ); - // add the cube to the quotient - Mvc_CoverAddCubeTail( pQuo, pCubeCopy ); - } - else - { - // copy the cube - pCubeCopy = Mvc_CubeDup( pRem, pCubeC ); - // add the cube to the remainder - Mvc_CoverAddCubeTail( pRem, pCubeCopy ); - } - } - // return the results - *ppRem = pRem; - *ppQuo = pQuo; -} - -/**Function************************************************************* - - Synopsis [Divides the cover by a literal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverDivideByLiteral( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t ** ppQuo, Mvc_Cover_t ** ppRem ) -{ - Mvc_Cover_t * pQuo, * pRem; - Mvc_Cube_t * pCubeC, * pCubeCopy; - int iLit; - - // get the only cube of D - assert( Mvc_CoverReadCubeNum(pDiv) == 1 ); - - // start the quotient and the remainder - pQuo = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); - pRem = Mvc_CoverAlloc( pCover->pMem, pCover->nBits ); - - // get the first and only literal in the divisor cube - iLit = Mvc_CoverFirstCubeFirstLit( pDiv ); - - // iterate through the cubes in the cover - Mvc_CoverForEachCube( pCover, pCubeC ) - { - // copy the cube - pCubeCopy = Mvc_CubeDup( pCover, pCubeC ); - // add the cube to the quotient or to the remainder depending on the literal - if ( Mvc_CubeBitValue( pCubeCopy, iLit ) ) - { // remove the literal - Mvc_CubeBitRemove( pCubeCopy, iLit ); - // add the cube ot the quotient - Mvc_CoverAddCubeTail( pQuo, pCubeCopy ); - } - else - { // add the cube ot the remainder - Mvc_CoverAddCubeTail( pRem, pCubeCopy ); - } - } - // return the results - *ppRem = pRem; - *ppQuo = pQuo; -} - - -/**Function************************************************************* - - Synopsis [Derives the quotient of division by literal.] - - Description [Reduces the cover to be the equal to the result of - division of the given cover by the literal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverDivideByLiteralQuo( Mvc_Cover_t * pCover, int iLit ) -{ - Mvc_Cube_t * pCube, * pCube2, * pPrev; - // delete those cubes that do not have this literal - // remove this literal from other cubes - pPrev = NULL; - Mvc_CoverForEachCubeSafe( pCover, pCube, pCube2 ) - { - if ( Mvc_CubeBitValue( pCube, iLit ) == 0 ) - { // delete the cube from the cover - Mvc_CoverDeleteCube( pCover, pPrev, pCube ); - Mvc_CubeFree( pCover, pCube ); - // don't update the previous cube - } - else - { // delete this literal from the cube - Mvc_CubeBitRemove( pCube, iLit ); - // update the previous cube - pPrev = pCube; - } - } -} - - -/**Function************************************************************* - - Synopsis [Verifies that the result of algebraic division is correct.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverVerifyDivision( Mvc_Cover_t * pCover, Mvc_Cover_t * pDiv, Mvc_Cover_t * pQuo, Mvc_Cover_t * pRem ) -{ - Mvc_Cover_t * pProd; - Mvc_Cover_t * pDiff; - - pProd = Mvc_CoverAlgebraicMultiply( pDiv, pQuo ); - pDiff = Mvc_CoverAlgebraicSubtract( pCover, pProd ); - - if ( Mvc_CoverAlgebraicEqual( pDiff, pRem ) ) - printf( "Verification OKAY!\n" ); - else - { - printf( "Verification FAILED!\n" ); - printf( "pCover:\n" ); - Mvc_CoverPrint( pCover ); - printf( "pDiv:\n" ); - Mvc_CoverPrint( pDiv ); - printf( "pRem:\n" ); - Mvc_CoverPrint( pRem ); - printf( "pQuo:\n" ); - Mvc_CoverPrint( pQuo ); - } - - Mvc_CoverFree( pProd ); - Mvc_CoverFree( pDiff ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcDivisor.c b/src/misc/mvc/mvcDivisor.c deleted file mode 100644 index ecdea75b..00000000 --- a/src/misc/mvc/mvcDivisor.c +++ /dev/null @@ -1,90 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcDivisor.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Procedures for compute the quick divisor.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcDivisor.c,v 1.1 2003/04/03 15:34:08 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the quick divisor of the cover.] - - Description [Returns NULL, if there is not divisor other than - trivial.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverDivisor( Mvc_Cover_t * pCover ) -{ - Mvc_Cover_t * pKernel; - if ( Mvc_CoverReadCubeNum(pCover) <= 1 ) - return NULL; - // allocate the literal array and count literals - if ( Mvc_CoverAnyLiteral( pCover, NULL ) == -1 ) - return NULL; - // duplicate the cover - pKernel = Mvc_CoverDup(pCover); - // perform the kerneling - Mvc_CoverDivisorZeroKernel( pKernel ); - assert( Mvc_CoverReadCubeNum(pKernel) ); - return pKernel; -} - -/**Function************************************************************* - - Synopsis [Computes a level-zero kernel.] - - Description [Modifies the cover to contain one level-zero kernel.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverDivisorZeroKernel( Mvc_Cover_t * pCover ) -{ - int iLit; - // find any literal that occurs at least two times -// iLit = Mvc_CoverAnyLiteral( pCover, NULL ); - iLit = Mvc_CoverWorstLiteral( pCover, NULL ); -// iLit = Mvc_CoverBestLiteral( pCover, NULL ); - if ( iLit == -1 ) - return; - // derive the cube-free quotient - Mvc_CoverDivideByLiteralQuo( pCover, iLit ); // the same cover - Mvc_CoverMakeCubeFree( pCover ); // the same cover - // call recursively - Mvc_CoverDivisorZeroKernel( pCover ); // the same cover -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcList.c b/src/misc/mvc/mvcList.c deleted file mode 100644 index 8a82f911..00000000 --- a/src/misc/mvc/mvcList.c +++ /dev/null @@ -1,362 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcList.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Manipulating list of cubes in the cover.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcList.c,v 1.4 2003/04/03 06:31:50 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_ListAddCubeHead_( Mvc_List_t * pList, Mvc_Cube_t * pCube ) -{ - if ( pList->pHead == NULL ) - { - Mvc_CubeSetNext( pCube, NULL ); - pList->pHead = pCube; - pList->pTail = pCube; - } - else - { - Mvc_CubeSetNext( pCube, pList->pHead ); - pList->pHead = pCube; - } - pList->nItems++; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_ListAddCubeTail_( Mvc_List_t * pList, Mvc_Cube_t * pCube ) -{ - if ( pList->pHead == NULL ) - pList->pHead = pCube; - else - Mvc_CubeSetNext( pList->pTail, pCube ); - pList->pTail = pCube; - Mvc_CubeSetNext( pCube, NULL ); - pList->nItems++; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_ListDeleteCube_( Mvc_List_t * pList, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ) -{ - if ( pPrev == NULL ) // deleting the head cube - pList->pHead = Mvc_CubeReadNext(pCube); - else - pPrev->pNext = pCube->pNext; - if ( pList->pTail == pCube ) // deleting the tail cube - { - assert( Mvc_CubeReadNext(pCube) == NULL ); - pList->pTail = pPrev; - } - pList->nItems--; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverAddCubeHead_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) -{ - Mvc_List_t * pList = &pCover->lCubes; - if ( pList->pHead == NULL ) - { - Mvc_CubeSetNext( pCube, NULL ); - pList->pHead = pCube; - pList->pTail = pCube; - } - else - { - Mvc_CubeSetNext( pCube, pList->pHead ); - pList->pHead = pCube; - } - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverAddCubeTail_( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) -{ - Mvc_List_t * pList = &pCover->lCubes; - - if ( pList->pHead == NULL ) - pList->pHead = pCube; - else - Mvc_CubeSetNext( pList->pTail, pCube ); - pList->pTail = pCube; - Mvc_CubeSetNext( pCube, NULL ); - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverDeleteCube_( Mvc_Cover_t * pCover, Mvc_Cube_t * pPrev, Mvc_Cube_t * pCube ) -{ - Mvc_List_t * pList = &pCover->lCubes; - - if ( pPrev == NULL ) // deleting the head cube - pList->pHead = Mvc_CubeReadNext(pCube); - else - pPrev->pNext = pCube->pNext; - if ( pList->pTail == pCube ) // deleting the tail cube - { - assert( Mvc_CubeReadNext(pCube) == NULL ); - pList->pTail = pPrev; - } - pList->nItems--; -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverAddDupCubeHead( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) -{ - Mvc_Cube_t * pCubeNew; - pCubeNew = Mvc_CubeAlloc( pCover ); - Mvc_CubeBitCopy( pCubeNew, pCube ); - Mvc_CoverAddCubeHead( pCover, pCubeNew ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverAddDupCubeTail( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) -{ - Mvc_Cube_t * pCubeNew; - // copy the cube as part of this cover - pCubeNew = Mvc_CubeAlloc( pCover ); - Mvc_CubeBitCopy( pCubeNew, pCube ); - // clean the last bits of the new cube -// pCubeNew->pData[pCubeNew->iLast] &= (BITS_FULL >> pCubeNew->nUnused); - // add the cube at the end - Mvc_CoverAddCubeTail( pCover, pCubeNew ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverAddLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) -{ -// int iBit, Value; -// assert( pCover->pLits ); -// Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) -// if ( Value ) -// pCover->pLits[iBit] += Value; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverDeleteLiteralsOfCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) -{ -// int iBit, Value; -// assert( pCover->pLits ); -// Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) -// if ( Value ) -// pCover->pLits[iBit] -= Value; -} - - -/**Function************************************************************* - - Synopsis [Transfers the cubes from the list into the array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverList2Array( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - int Counter; - // resize storage if necessary - Mvc_CoverAllocateArrayCubes( pCover ); - // iterate through the cubes - Counter = 0; - Mvc_CoverForEachCube( pCover, pCube ) - pCover->pCubes[ Counter++ ] = pCube; - assert( Counter == Mvc_CoverReadCubeNum(pCover) ); -} - -/**Function************************************************************* - - Synopsis [Transfers the cubes from the array into list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverArray2List( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - int nCubes, i; - - assert( pCover->pCubes ); - - nCubes = Mvc_CoverReadCubeNum(pCover); - if ( nCubes == 0 ) - return; - if ( nCubes == 1 ) - { - pCube = pCover->pCubes[0]; - pCube->pNext = NULL; - pCover->lCubes.pHead = pCover->lCubes.pTail = pCube; - return; - } - // set up the first cube - pCube = pCover->pCubes[0]; - pCover->lCubes.pHead = pCube; - // set up the last cube - pCube = pCover->pCubes[nCubes-1]; - pCube->pNext = NULL; - pCover->lCubes.pTail = pCube; - - // link all cubes starting from the first one - for ( i = 0; i < nCubes - 1; i++ ) - pCover->pCubes[i]->pNext = pCover->pCubes[i+1]; -} - -/**Function************************************************************* - - Synopsis [Returns the tail of the linked list given by the head.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cube_t * Mvc_ListGetTailFromHead( Mvc_Cube_t * pHead ) -{ - Mvc_Cube_t * pCube, * pTail; - for ( pTail = pCube = pHead; - pCube; - pTail = pCube, pCube = Mvc_CubeReadNext(pCube) ); - return pTail; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcLits.c b/src/misc/mvc/mvcLits.c deleted file mode 100644 index 910158e9..00000000 --- a/src/misc/mvc/mvcLits.c +++ /dev/null @@ -1,345 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcLits.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Literal counting/updating procedures.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcLits.c,v 1.4 2003/04/03 06:31:50 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Find the any literal that occurs more than once.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverAnyLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ) -{ - Mvc_Cube_t * pCube; - int nWord, nBit, i; - int nLitsCur; - int fUseFirst = 0; - - // go through each literal - if ( fUseFirst ) - { - for ( i = 0; i < pCover->nBits; i++ ) - if ( !pMask || Mvc_CubeBitValue(pMask,i) ) - { - // get the word and bit of this literal - nWord = Mvc_CubeWhichWord(i); - nBit = Mvc_CubeWhichBit(i); - // go through all the cubes - nLitsCur = 0; - Mvc_CoverForEachCube( pCover, pCube ) - if ( pCube->pData[nWord] & (1< 1 ) - return i; - } - } - } - else - { - for ( i = pCover->nBits - 1; i >=0; i-- ) - if ( !pMask || Mvc_CubeBitValue(pMask,i) ) - { - // get the word and bit of this literal - nWord = Mvc_CubeWhichWord(i); - nBit = Mvc_CubeWhichBit(i); - // go through all the cubes - nLitsCur = 0; - Mvc_CoverForEachCube( pCover, pCube ) - if ( pCube->pData[nWord] & (1< 1 ) - return i; - } - } - } - return -1; -} - -/**Function************************************************************* - - Synopsis [Find the most often occurring literal.] - - Description [Find the most often occurring literal among those - that occur more than once.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverBestLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ) -{ - Mvc_Cube_t * pCube; - int nWord, nBit; - int i, iMax, nLitsMax, nLitsCur; - int fUseFirst = 1; - - // go through each literal - iMax = -1; - nLitsMax = -1; - for ( i = 0; i < pCover->nBits; i++ ) - if ( !pMask || Mvc_CubeBitValue(pMask,i) ) - { - // get the word and bit of this literal - nWord = Mvc_CubeWhichWord(i); - nBit = Mvc_CubeWhichBit(i); - // go through all the cubes - nLitsCur = 0; - Mvc_CoverForEachCube( pCover, pCube ) - if ( pCube->pData[nWord] & (1< 1 ) - return iMax; - return -1; -} - -/**Function************************************************************* - - Synopsis [Find the most often occurring literal.] - - Description [Find the most often occurring literal among those - that occur more than once.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverWorstLiteral( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask ) -{ - Mvc_Cube_t * pCube; - int nWord, nBit; - int i, iMin, nLitsMin, nLitsCur; - int fUseFirst = 1; - - // go through each literal - iMin = -1; - nLitsMin = 1000000; - for ( i = 0; i < pCover->nBits; i++ ) - if ( !pMask || Mvc_CubeBitValue(pMask,i) ) - { - // get the word and bit of this literal - nWord = Mvc_CubeWhichWord(i); - nBit = Mvc_CubeWhichBit(i); - // go through all the cubes - nLitsCur = 0; - Mvc_CoverForEachCube( pCover, pCube ) - if ( pCube->pData[nWord] & (1< nLitsCur ) - { - nLitsMin = nLitsCur; - iMin = i; - } - } - else - { - if ( nLitsMin >= nLitsCur ) - { - nLitsMin = nLitsCur; - iMin = i; - } - } - } - - if ( nLitsMin < 1000000 ) - return iMin; - return -1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverBestLiteralCover( Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ) -{ - Mvc_Cover_t * pCoverNew; - Mvc_Cube_t * pCubeNew; - Mvc_Cube_t * pCubeS; - int iLitBest; - - // create the new cover - pCoverNew = Mvc_CoverClone( pCover ); - // get the new cube - pCubeNew = Mvc_CubeAlloc( pCoverNew ); - // clean the cube - Mvc_CubeBitClean( pCubeNew ); - - // get the first cube of pSimple - assert( Mvc_CoverReadCubeNum(pSimple) == 1 ); - pCubeS = Mvc_CoverReadCubeHead( pSimple ); - // find the best literal among those of pCubeS - iLitBest = Mvc_CoverBestLiteral( pCover, pCubeS ); - - // insert this literal into the cube - Mvc_CubeBitInsert( pCubeNew, iLitBest ); - // add the cube to the cover - Mvc_CoverAddCubeTail( pCoverNew, pCubeNew ); - return pCoverNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverFirstCubeFirstLit( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - int iBit, Value; - - // get the first cube - pCube = Mvc_CoverReadCubeHead( pCover ); - // get the first literal - Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) - if ( Value ) - return iBit; - return -1; -} - -/**Function************************************************************* - - Synopsis [Returns the number of literals in the cover.] - - Description [Allocates storage for literal counters and fills it up - using the current information.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverCountLiterals( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - int nWord, nBit; - int i, CounterTot, CounterCur; - - // allocate/clean the storage for literals -// Mvc_CoverAllocateArrayLits( pCover ); -// memset( pCover->pLits, 0, pCover->nBits * sizeof(int) ); - // go through each literal - CounterTot = 0; - for ( i = 0; i < pCover->nBits; i++ ) - { - // get the word and bit of this literal - nWord = Mvc_CubeWhichWord(i); - nBit = Mvc_CubeWhichBit(i); - // go through all the cubes - CounterCur = 0; - Mvc_CoverForEachCube( pCover, pCube ) - if ( pCube->pData[nWord] & (1< -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Manager_t * Mvc_ManagerStart() -{ - Mvc_Manager_t * p; - p = ALLOC( Mvc_Manager_t, 1 ); - memset( p, 0, sizeof(Mvc_Manager_t) ); - p->pMan1 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) ); - p->pMan2 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) + sizeof(Mvc_CubeWord_t) ); - p->pMan4 = Extra_MmFixedStart( sizeof(Mvc_Cube_t) + 3 * sizeof(Mvc_CubeWord_t) ); - p->pManC = Extra_MmFixedStart( sizeof(Mvc_Cover_t) ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_ManagerFree( Mvc_Manager_t * p ) -{ - Extra_MmFixedStop( p->pMan1 ); - Extra_MmFixedStop( p->pMan2 ); - Extra_MmFixedStop( p->pMan4 ); - Extra_MmFixedStop( p->pManC ); - free( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcOpAlg.c b/src/misc/mvc/mvcOpAlg.c deleted file mode 100644 index 65c02fa5..00000000 --- a/src/misc/mvc/mvcOpAlg.c +++ /dev/null @@ -1,163 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcOperAlg.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Miscellaneous operations on covers.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcOpAlg.c,v 1.4 2003/04/26 20:41:36 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Multiplies two disjoint-support covers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverAlgebraicMultiply( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) -{ - Mvc_Cover_t * pCover; - Mvc_Cube_t * pCube1, * pCube2, * pCube; - int CompResult; - - // covers should be the same base - assert( pCover1->nBits == pCover2->nBits ); - // make sure that supports do not overlap - Mvc_CoverAllocateMask( pCover1 ); - Mvc_CoverAllocateMask( pCover2 ); - Mvc_CoverSupport( pCover1, pCover1->pMask ); - Mvc_CoverSupport( pCover2, pCover2->pMask ); - // check if the cubes are bit-wise disjoint - Mvc_CubeBitDisjoint( CompResult, pCover1->pMask, pCover2->pMask ); - if ( !CompResult ) - printf( "Mvc_CoverMultiply(): Cover supports are not disjoint!\n" ); - - // iterate through the cubes - pCover = Mvc_CoverClone( pCover1 ); - Mvc_CoverForEachCube( pCover1, pCube1 ) - Mvc_CoverForEachCube( pCover2, pCube2 ) - { - // create the product cube - pCube = Mvc_CubeAlloc( pCover ); - // set the product cube equal to the product of the two cubes - Mvc_CubeBitOr( pCube, pCube1, pCube2 ); - // add the cube to the cover - Mvc_CoverAddCubeTail( pCover, pCube ); - } - return pCover; -} - - -/**Function************************************************************* - - Synopsis [Subtracts the second cover from the first.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverAlgebraicSubtract( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) -{ - Mvc_Cover_t * pCover; - Mvc_Cube_t * pCube1, * pCube2, * pCube; - int fFound; - int CompResult; - - // covers should be the same base - assert( pCover1->nBits == pCover2->nBits ); - - // iterate through the cubes - pCover = Mvc_CoverClone( pCover1 ); - Mvc_CoverForEachCube( pCover1, pCube1 ) - { - fFound = 0; - Mvc_CoverForEachCube( pCover2, pCube2 ) - { - Mvc_CubeBitEqual( CompResult, pCube1, pCube2 ); - if ( CompResult ) - { - fFound = 1; - break; - } - } - if ( !fFound ) - { - // create the copy of the cube - pCube = Mvc_CubeDup( pCover, pCube1 ); - // add the cube copy to the cover - Mvc_CoverAddCubeTail( pCover, pCube ); - } - } - return pCover; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverAlgebraicEqual( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) -{ - Mvc_Cube_t * pCube1, * pCube2; - int fFound; - int CompResult; - - // covers should be the same base - assert( pCover1->nBits == pCover2->nBits ); - // iterate through the cubes - Mvc_CoverForEachCube( pCover1, pCube1 ) - { - fFound = 0; - Mvc_CoverForEachCube( pCover2, pCube2 ) - { - Mvc_CubeBitEqual( CompResult, pCube1, pCube2 ); - if ( CompResult ) - { - fFound = 1; - break; - } - } - if ( !fFound ) - return 0; - } - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcOpBool.c b/src/misc/mvc/mvcOpBool.c deleted file mode 100644 index 0b34f1de..00000000 --- a/src/misc/mvc/mvcOpBool.c +++ /dev/null @@ -1,151 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcProc.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Various boolean procedures working with covers.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcOpBool.c,v 1.4 2003/04/16 01:55:37 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverBooleanOr( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) -{ - Mvc_Cover_t * pCover; - Mvc_Cube_t * pCube, * pCubeCopy; - // make sure the covers are compatible - assert( pCover1->nBits == pCover2->nBits ); - // clone the cover - pCover = Mvc_CoverClone( pCover1 ); - // create the cubes by making pair-wise products - // of cubes in pCover1 and pCover2 - Mvc_CoverForEachCube( pCover1, pCube ) - { - pCubeCopy = Mvc_CubeDup( pCover, pCube ); - Mvc_CoverAddCubeTail( pCover, pCubeCopy ); - } - Mvc_CoverForEachCube( pCover2, pCube ) - { - pCubeCopy = Mvc_CubeDup( pCover, pCube ); - Mvc_CoverAddCubeTail( pCover, pCubeCopy ); - } - return pCover; -} - -#if 0 - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverBooleanAnd( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) -{ - Mvc_Cover_t * pCover; - Mvc_Cube_t * pCube1, * pCube2, * pCubeCopy; - // make sure the covers are compatible - assert( pCover1->nBits == pCover2->nBits ); - // clone the cover - pCover = Mvc_CoverClone( pCover1 ); - // create the cubes by making pair-wise products - // of cubes in pCover1 and pCover2 - Mvc_CoverForEachCube( pCover1, pCube1 ) - { - Mvc_CoverForEachCube( pCover2, pCube2 ) - { - if ( Mvc_CoverDist0Cubes( p, pCube1, pCube2 ) ) - { - pCubeCopy = Mvc_CubeAlloc( pCover ); - Mvc_CubeBitAnd( pCubeCopy, pCube1, pCube2 ); - Mvc_CoverAddCubeTail( pCover, pCubeCopy ); - } - } - // if the number of cubes in the new cover is too large - // try compressing them - if ( Mvc_CoverReadCubeNum( pCover ) > 500 ) - Mvc_CoverContain( pCover ); - } - return pCover; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the two covers are equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverBooleanEqual( Mvc_Data_t * p, Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) -{ - Mvc_Cover_t * pSharp; - - pSharp = Mvc_CoverSharp( p, pCover1, pCover2 ); - if ( Mvc_CoverReadCubeNum( pSharp ) ) - { -Mvc_CoverContain( pSharp ); -printf( "Sharp \n" ); -Mvc_CoverPrint( pSharp ); - Mvc_CoverFree( pSharp ); - return 0; - } - Mvc_CoverFree( pSharp ); - - pSharp = Mvc_CoverSharp( p, pCover2, pCover1 ); - if ( Mvc_CoverReadCubeNum( pSharp ) ) - { -Mvc_CoverContain( pSharp ); -printf( "Sharp \n" ); -Mvc_CoverPrint( pSharp ); - Mvc_CoverFree( pSharp ); - return 0; - } - Mvc_CoverFree( pSharp ); - - return 1; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcPrint.c b/src/misc/mvc/mvcPrint.c deleted file mode 100644 index 52ac76b3..00000000 --- a/src/misc/mvc/mvcPrint.c +++ /dev/null @@ -1,220 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcPrint.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Printing cubes and covers.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcPrint.c,v 1.6 2003/04/09 18:02:06 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" -//#include "vm.h" -//#include "vmInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverPrint( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - int i; - // print general statistics - printf( "The cover contains %d cubes (%d bits and %d words)\n", - pCover->lCubes.nItems, pCover->nBits, pCover->nWords ); - // iterate through the cubes - Mvc_CoverForEachCube( pCover, pCube ) - Mvc_CubePrint( pCover, pCube ); - - if ( pCover->pLits ) - { - for ( i = 0; i < pCover->nBits; i++ ) - printf( " %d", pCover->pLits[i] ); - printf( "\n" ); - } - printf( "End of cover printout\n" ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CubePrint( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) -{ - int iBit, Value; - // iterate through the literals -// printf( "Size = %2d ", Mvc_CubeReadSize(pCube) ); - Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) - printf( "%c", '0' + Value ); - printf( "\n" ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverPrintBinary( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - int i; - // print general statistics - printf( "The cover contains %d cubes (%d bits and %d words)\n", - pCover->lCubes.nItems, pCover->nBits, pCover->nWords ); - // iterate through the cubes - Mvc_CoverForEachCube( pCover, pCube ) - Mvc_CubePrintBinary( pCover, pCube ); - - if ( pCover->pLits ) - { - for ( i = 0; i < pCover->nBits; i++ ) - printf( " %d", pCover->pLits[i] ); - printf( "\n" ); - } - printf( "End of cover printout\n" ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CubePrintBinary( Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) -{ - int iVar, Value; - // iterate through the literals -// printf( "Size = %2d ", Mvc_CubeReadSize(pCube) ); - Mvc_CubeForEachVarValue( pCover, pCube, iVar, Value ) - { - assert( Value != 0 ); - if ( Value == 3 ) - printf( "-" ); - else if ( Value == 1 ) - printf( "0" ); - else - printf( "1" ); - } - printf( "\n" ); -} - -#if 0 - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverPrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - int i; - // print general statistics - printf( "The cover contains %d cubes (%d bits and %d words)\n", - pCover->lCubes.nItems, pCover->nBits, pCover->nWords ); - // iterate through the cubes - Mvc_CoverForEachCube( pCover, pCube ) - Mvc_CubePrintMv( pData, pCover, pCube ); - - if ( pCover->pLits ) - { - for ( i = 0; i < pCover->nBits; i++ ) - printf( " %d", pCover->pLits[i] ); - printf( "\n" ); - } - printf( "End of cover printout\n" ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CubePrintMv( Mvc_Data_t * pData, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube ) -{ - int iLit, iVar; - // iterate through the literals - printf( "Size = %2d ", Mvc_CubeReadSize(pCube) ); - iVar = 0; - for ( iLit = 0; iLit < pData->pVm->nValuesIn; iLit++ ) - { - if ( iLit == pData->pVm->pValuesFirst[iVar+1] ) - { - printf( " " ); - iVar++; - } - if ( Mvc_CubeBitValue( pCube, iLit ) ) - printf( "%c", '0' + iLit - pData->pVm->pValuesFirst[iVar] ); - else - printf( "-" ); - } - printf( "\n" ); -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcSort.c b/src/misc/mvc/mvcSort.c deleted file mode 100644 index 3c975cb3..00000000 --- a/src/misc/mvc/mvcSort.c +++ /dev/null @@ -1,141 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcSort.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Sorting cubes in the cover with the mask.] - - Author [MVSIS Group] - - Affiliation [uC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcSort.c,v 1.5 2003/04/27 01:03:45 wjiang Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - - -Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ); -Mvc_Cube_t * Mvc_CoverSortMerge( Mvc_Cube_t * pList1, Mvc_Cube_t * pList2, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ); - -//////////////////////////////////////////////////////////////////////// -/// FuNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Sorts cubes using the given cost function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverSort( Mvc_Cover_t * pCover, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ) -{ - Mvc_Cube_t * pHead; - int nCubes; - // one cube does not need sorting - nCubes = Mvc_CoverReadCubeNum(pCover); - if ( nCubes <= 1 ) - return; - // sort the cubes - pHead = Mvc_CoverSort_rec( Mvc_CoverReadCubeHead(pCover), nCubes, pMask, pCompareFunc ); - // insert the sorted list into the cover - Mvc_CoverSetCubeHead( pCover, pHead ); - Mvc_CoverSetCubeTail( pCover, Mvc_ListGetTailFromHead(pHead) ); - // make sure that the list is sorted in the increasing order - assert( pCompareFunc( Mvc_CoverReadCubeHead(pCover), Mvc_CoverReadCubeTail(pCover), pMask ) <= 0 ); -} - -/**Function************************************************************* - - Synopsis [Recursive part of Mvc_CoverSort()] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cube_t * Mvc_CoverSort_rec( Mvc_Cube_t * pList, int nItems, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ) -{ - Mvc_Cube_t * pList1, * pList2; - int nItems1, nItems2, i; - - // trivial case - if ( nItems == 1 ) - { - Mvc_CubeSetNext( pList, NULL ); - return pList; - } - - // select the new sizes - nItems1 = nItems/2; - nItems2 = nItems - nItems1; - - // set the new beginnings - pList1 = pList2 = pList; - for ( i = 0; i < nItems1; i++ ) - pList2 = Mvc_CubeReadNext( pList2 ); - - // solve recursively - pList1 = Mvc_CoverSort_rec( pList1, nItems1, pMask, pCompareFunc ); - pList2 = Mvc_CoverSort_rec( pList2, nItems2, pMask, pCompareFunc ); - - // merge - return Mvc_CoverSortMerge( pList1, pList2, pMask, pCompareFunc ); -} - - -/**Function************************************************************* - - Synopsis [Merges two NULL-terminated linked lists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cube_t * Mvc_CoverSortMerge( Mvc_Cube_t * pList1, Mvc_Cube_t * pList2, Mvc_Cube_t * pMask, int (* pCompareFunc)(Mvc_Cube_t *, Mvc_Cube_t *, Mvc_Cube_t *) ) -{ - Mvc_Cube_t * pList = NULL, ** ppTail = &pList; - Mvc_Cube_t * pCube; - while ( pList1 && pList2 ) - { - if ( pCompareFunc( pList1, pList2, pMask ) < 0 ) - { - pCube = pList1; - pList1 = Mvc_CubeReadNext(pList1); - } - else - { - pCube = pList2; - pList2 = Mvc_CubeReadNext(pList2); - } - *ppTail = pCube; - ppTail = Mvc_CubeReadNextP(pCube); - } - *ppTail = pList1? pList1: pList2; - return pList; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/mvc/mvcUtils.c b/src/misc/mvc/mvcUtils.c deleted file mode 100644 index 4b13b23d..00000000 --- a/src/misc/mvc/mvcUtils.c +++ /dev/null @@ -1,868 +0,0 @@ -/**CFile**************************************************************** - - FileName [mvcUtils.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Various cover handling utilities.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: mvcUtils.c,v 1.7 2003/04/26 20:41:36 alanmi Exp $] - -***********************************************************************/ - -#include "mvc.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int bit_count[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; - - -static void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNew, int iColOld, int iColNew ); - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverSupport( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp ) -{ - Mvc_Cube_t * pCube; - // clean the support - Mvc_CubeBitClean( pSupp ); - // collect the support - Mvc_CoverForEachCube( pCover, pCube ) - Mvc_CubeBitOr( pSupp, pSupp, pCube ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverSupportAnd( Mvc_Cover_t * pCover, Mvc_Cube_t * pSupp ) -{ - Mvc_Cube_t * pCube; - // clean the support - Mvc_CubeBitFill( pSupp ); - // collect the support - Mvc_CoverForEachCube( pCover, pCube ) - Mvc_CubeBitAnd( pSupp, pSupp, pCube ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverSupportSizeBinary( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pSupp; - int Counter, i, v0, v1; - // compute the support - pSupp = Mvc_CubeAlloc( pCover ); - Mvc_CoverSupportAnd( pCover, pSupp ); - Counter = pCover->nBits/2; - for ( i = 0; i < pCover->nBits/2; i++ ) - { - v0 = Mvc_CubeBitValue( pSupp, 2*i ); - v1 = Mvc_CubeBitValue( pSupp, 2*i+1 ); - if ( v0 && v1 ) - Counter--; - } - Mvc_CubeFree( pCover, pSupp ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverSupportVarBelongs( Mvc_Cover_t * pCover, int iVar ) -{ - Mvc_Cube_t * pSupp; - int RetValue, v0, v1; - // compute the support - pSupp = Mvc_CubeAlloc( pCover ); - Mvc_CoverSupportAnd( pCover, pSupp ); - v0 = Mvc_CubeBitValue( pSupp, 2*iVar ); - v1 = Mvc_CubeBitValue( pSupp, 2*iVar+1 ); - RetValue = (int)( !v0 || !v1 ); - Mvc_CubeFree( pCover, pSupp ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverCommonCube( Mvc_Cover_t * pCover, Mvc_Cube_t * pComCube ) -{ - Mvc_Cube_t * pCube; - // clean the support - Mvc_CubeBitFill( pComCube ); - // collect the support - Mvc_CoverForEachCube( pCover, pCube ) - Mvc_CubeBitAnd( pComCube, pComCube, pCube ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverIsCubeFree( Mvc_Cover_t * pCover ) -{ - int Result; - // get the common cube - Mvc_CoverAllocateMask( pCover ); - Mvc_CoverCommonCube( pCover, pCover->pMask ); - // check whether the common cube is empty - Mvc_CubeBitEmpty( Result, pCover->pMask ); - return Result; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverMakeCubeFree( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - // get the common cube - Mvc_CoverAllocateMask( pCover ); - Mvc_CoverCommonCube( pCover, pCover->pMask ); - // remove this cube from the cubes in the cover - Mvc_CoverForEachCube( pCover, pCube ) - Mvc_CubeBitSharp( pCube, pCube, pCover->pMask ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverCommonCubeCover( Mvc_Cover_t * pCover ) -{ - Mvc_Cover_t * pRes; - Mvc_Cube_t * pCube; - // create the new cover - pRes = Mvc_CoverClone( pCover ); - // get the new cube - pCube = Mvc_CubeAlloc( pRes ); - // get the common cube - Mvc_CoverCommonCube( pCover, pCube ); - // add the cube to the cover - Mvc_CoverAddCubeTail( pRes, pCube ); - return pRes; -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if the support of cover2 is contained in the support of cover1.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverCheckSuppContainment( Mvc_Cover_t * pCover1, Mvc_Cover_t * pCover2 ) -{ - int Result; - assert( pCover1->nBits == pCover2->nBits ); - // set the supports - Mvc_CoverAllocateMask( pCover1 ); - Mvc_CoverSupport( pCover1, pCover1->pMask ); - Mvc_CoverAllocateMask( pCover2 ); - Mvc_CoverSupport( pCover2, pCover2->pMask ); - // check the containment - Mvc_CubeBitNotImpl( Result, pCover2->pMask, pCover1->pMask ); - return !Result; -} - -/**Function************************************************************* - - Synopsis [Counts the cube sizes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverSetCubeSizes( Mvc_Cover_t * pCover ) -{ - Mvc_Cube_t * pCube; - unsigned char * pByte, * pByteStart, * pByteStop; - int nBytes, nOnes; - - // get the number of unsigned chars in the cube's bit strings - nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0); - // iterate through the cubes - Mvc_CoverForEachCube( pCover, pCube ) - { - // clean the counter of ones - nOnes = 0; - // set the starting and stopping positions - pByteStart = (unsigned char *)pCube->pData; - pByteStop = pByteStart + nBytes; - // iterate through the positions - for ( pByte = pByteStart; pByte < pByteStop; pByte++ ) - nOnes += bit_count[*pByte]; - // set the nOnes - Mvc_CubeSetSize( pCube, nOnes ); - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Counts the cube sizes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverGetCubeSize( Mvc_Cube_t * pCube ) -{ - unsigned char * pByte, * pByteStart, * pByteStop; - int nOnes, nBytes, nBits; - // get the number of unsigned chars in the cube's bit strings - nBits = (pCube->iLast + 1) * sizeof(Mvc_CubeWord_t) * 8 - pCube->nUnused; - nBytes = nBits / (8 * sizeof(unsigned char)) + (int)(nBits % (8 * sizeof(unsigned char)) > 0); - // clean the counter of ones - nOnes = 0; - // set the starting and stopping positions - pByteStart = (unsigned char *)pCube->pData; - pByteStop = pByteStart + nBytes; - // iterate through the positions - for ( pByte = pByteStart; pByte < pByteStop; pByte++ ) - nOnes += bit_count[*pByte]; - return nOnes; -} - -/**Function************************************************************* - - Synopsis [Counts the differences in each cube pair in the cover.] - - Description [Takes the cover (pCover) and the array where the - diff counters go (pDiffs). The array pDiffs should have as many - entries as there are different pairs of cubes in the cover: n(n-1)/2. - Fills out the array pDiffs with the following info: For each cube - pair, included in the array is the number of literals in both cubes - after they are made cube free.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvc_CoverCountCubePairDiffs( Mvc_Cover_t * pCover, unsigned char pDiffs[] ) -{ - Mvc_Cube_t * pCube1; - Mvc_Cube_t * pCube2; - Mvc_Cube_t * pMask; - unsigned char * pByte, * pByteStart, * pByteStop; - int nBytes, nOnes; - int nCubePairs; - - // allocate a temporary mask - pMask = Mvc_CubeAlloc( pCover ); - // get the number of unsigned chars in the cube's bit strings - nBytes = pCover->nBits / (8 * sizeof(unsigned char)) + (int)(pCover->nBits % (8 * sizeof(unsigned char)) > 0); - // iterate through the cubes - nCubePairs = 0; - Mvc_CoverForEachCube( pCover, pCube1 ) - { - Mvc_CoverForEachCubeStart( Mvc_CubeReadNext(pCube1), pCube2 ) - { - // find the bit-wise exor of cubes - Mvc_CubeBitExor( pMask, pCube1, pCube2 ); - // set the starting and stopping positions - pByteStart = (unsigned char *)pMask->pData; - pByteStop = pByteStart + nBytes; - // clean the counter of ones - nOnes = 0; - // iterate through the positions - for ( pByte = pByteStart; pByte < pByteStop; pByte++ ) - nOnes += bit_count[*pByte]; - // set the nOnes - pDiffs[nCubePairs++] = nOnes; - } - } - // deallocate the mask - Mvc_CubeFree( pCover, pMask ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Creates a new cover containing some literals of the old cover.] - - Description [Creates the new cover containing the given number (nVarsRem) - literals of the old cover. All the bits of the new cover are initialized - to "1". The selected bits from the old cover are copied on top. The numbers - of the selected bits to copy are given in the array pVarsRem. The i-set - entry in this array is the index of the bit in the old cover which goes - to the i-th place in the new cover. If the i-th entry in pVarsRem is -1, - it means that the i-th bit does not change (remains composed of all 1's). - This is a useful feature to speed up remapping covers, which are known - to depend only on a subset of input variables.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverRemap( Mvc_Cover_t * p, int * pVarsRem, int nVarsRem ) -{ - Mvc_Cover_t * pCover; - Mvc_Cube_t * pCube, * pCubeCopy; - int i; - // clone the cover - pCover = Mvc_CoverAlloc( p->pMem, nVarsRem ); - // copy the cube list - Mvc_CoverForEachCube( p, pCube ) - { - pCubeCopy = Mvc_CubeAlloc( pCover ); - //Mvc_CubeBitClean( pCubeCopy ); //changed by wjiang - Mvc_CubeBitFill( pCubeCopy ); //changed by wjiang - Mvc_CoverAddCubeTail( pCover, pCubeCopy ); - } - // copy the corresponding columns - for ( i = 0; i < nVarsRem; i++ ) - { - if (pVarsRem[i] < 0) - continue; //added by wjiang - assert( pVarsRem[i] >= 0 && pVarsRem[i] < p->nBits ); - Mvc_CoverCopyColumn( p, pCover, pVarsRem[i], i ); - } - return pCover; -} - -/**Function************************************************************* - - Synopsis [Copies a column from the old cover to the new cover.] - - Description [Copies the column (iColOld) of the old cover (pCoverOld) - into the column (iColNew) of the new cover (pCoverNew). Assumes that - the number of cubes is the same in both covers. Makes no assuptions - about the current contents of the column in the new cover.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Mvc_CoverCopyColumn( Mvc_Cover_t * pCoverOld, Mvc_Cover_t * pCoverNew, - int iColOld, int iColNew ) -{ - Mvc_Cube_t * pCubeOld, * pCubeNew; - int iWordOld, iWordNew, iBitOld, iBitNew; - - assert( Mvc_CoverReadCubeNum(pCoverOld) == Mvc_CoverReadCubeNum(pCoverNew) ); - - // get the place of the old and new columns - iWordOld = Mvc_CubeWhichWord(iColOld); - iBitOld = Mvc_CubeWhichBit(iColOld); - iWordNew = Mvc_CubeWhichWord(iColNew); - iBitNew = Mvc_CubeWhichBit(iColNew); - - // go through the cubes of both covers - pCubeNew = Mvc_CoverReadCubeHead(pCoverNew); - Mvc_CoverForEachCube( pCoverOld, pCubeOld ) - { - if ( pCubeOld->pData[iWordOld] & (1<pData[iWordNew] |= (1<pData[iWordNew] &= ~(1<pVm, iVar); - nValues = Vm_VarMapReadValues(pData->pVm, iVar); - ppCofs = ALLOC( Mvc_Cover_t *, nValues + 1 ); - for ( i = 0; i <= nValues; i++ ) - ppCofs[i] = Mvc_CoverClone( pCover ); - - // go through the cubes - Mvc_CoverForEachCube( pCover, pCube ) - { - // if the literal if a full literal, add it to last "cofactor" - Mvc_CubeBitEqualUnderMask( Res, pCube, pData->ppMasks[iVar], pData->ppMasks[iVar] ); - if ( Res ) - { - pCubeNew = Mvc_CubeDup(pCover, pCube); - Mvc_CoverAddCubeTail( ppCofs[nValues], pCubeNew ); - continue; - } - - // otherwise, add it to separate values - for ( i = 0; i < nValues; i++ ) - if ( Mvc_CubeBitValue( pCube, iValueFirst + i ) ) - { - pCubeNew = Mvc_CubeDup(pCover, pCube); - Mvc_CubeBitOr( pCubeNew, pCubeNew, pData->ppMasks[iVar] ); - Mvc_CoverAddCubeTail( ppCofs[i], pCubeNew ); - } - } - return ppCofs; -} - -/**Function************************************************************* - - Synopsis [Count the cubes with non-trivial literals with the given value.] - - Description [The data and the cover are given (pData, pCover). Also given - are the variable number and the number of a value of this variable. - This procedure returns the number of cubes having a non-trivial literal - of this variable that have the given value present.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Mvr_CoverCountLitsWithValue( Mvc_Data_t * pData, Mvc_Cover_t * pCover, int iVar, int iValue ) -{ - Mvc_Cube_t * pCube; - int iValueFirst, Res, Counter; - - Counter = 0; - iValueFirst = Vm_VarMapReadValuesFirst( pData->pVm, iVar ); - Mvc_CoverForEachCube( pCover, pCube ) - { - // check if the given literal is the full literal - Mvc_CubeBitEqualUnderMask( Res, pCube, pData->ppMasks[iVar], pData->ppMasks[iVar] ); - if ( Res ) - continue; - // this literal is not a full literal; check if it has this value - Counter += Mvc_CubeBitValue( pCube, iValueFirst + iValue ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Creates the expanded cover.] - - Description [The original cover is expanded by adding some variables. - These variables are the additional variables in pVmNew, compared to - pCvr->pVm. The resulting cover is the same as the original one, except - that it contains the additional variables present as full literals - in every cube.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverCreateExpanded( Mvc_Cover_t * pCover, Vm_VarMap_t * pVmNew ) -{ - Mvc_Cover_t * pCoverNew; - Mvc_Cube_t * pCube, * pCubeNew; - int i, iLast, iLastNew; - - // create the new cover - pCoverNew = Mvc_CoverAlloc( pCover->pMem, Vm_VarMapReadValuesInNum(pVmNew) ); - - // get the cube composed of extra bits - Mvc_CoverAllocateMask( pCoverNew ); - Mvc_CubeBitClean( pCoverNew->pMask ); - for ( i = pCover->nBits; i < pCoverNew->nBits; i++ ) - Mvc_CubeBitInsert( pCoverNew->pMask, i ); - - // get the indexes of the last words in both covers - iLast = pCover->nWords? pCover->nWords - 1: 0; - iLastNew = pCoverNew->nWords? pCoverNew->nWords - 1: 0; - - // create the cubes of the new cover - Mvc_CoverForEachCube( pCover, pCube ) - { - pCubeNew = Mvc_CubeAlloc( pCoverNew ); - Mvc_CubeBitClean( pCubeNew ); - // copy the bits (cannot immediately use Mvc_CubeBitCopy, - // because covers have different numbers of bits) - Mvc_CubeSetLast( pCubeNew, iLast ); - Mvc_CubeBitCopy( pCubeNew, pCube ); - Mvc_CubeSetLast( pCubeNew, iLastNew ); - // add the extra bits - Mvc_CubeBitOr( pCubeNew, pCubeNew, pCoverNew->pMask ); - // add the cube to the new cover - Mvc_CoverAddCubeTail( pCoverNew, pCubeNew ); - } - return pCoverNew; -} - -#endif - -/**Function************************************************************* - - Synopsis [Transposes the cube cover.] - - Description [Returns the cube cover that looks like a transposed - matrix, compared to the matrix derived from the original cover.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Mvc_CoverTranspose( Mvc_Cover_t * pCover ) -{ - Mvc_Cover_t * pRes; - Mvc_Cube_t * pCubeRes, * pCube; - int nWord, nBit, i, iCube; - - pRes = Mvc_CoverAlloc( pCover->pMem, Mvc_CoverReadCubeNum(pCover) ); - for ( i = 0; i < pCover->nBits; i++ ) - { - // get the word and bit of this literal - nWord = Mvc_CubeWhichWord(i); - nBit = Mvc_CubeWhichBit(i); - // get the transposed cube - pCubeRes = Mvc_CubeAlloc( pRes ); - Mvc_CubeBitClean( pCubeRes ); - iCube = 0; - Mvc_CoverForEachCube( pCover, pCube ) - { - if ( pCube->pData[nWord] & (1<nUnused == 0 ) - continue; - - Unsigned = ( pCube->pData[pCube->iLast] & - (BITS_FULL << (32-pCube->nUnused)) ); - if( Unsigned ) - { - printf( "Cube %2d out of %2d contains dirty bits.\n", nCubes, - Mvc_CoverReadCubeNum(pCover) ); - } - nCubes++; - } - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/nm/module.make b/src/misc/nm/module.make deleted file mode 100644 index 2a3820c7..00000000 --- a/src/misc/nm/module.make +++ /dev/null @@ -1,2 +0,0 @@ -SRC += src/misc/nm/nmApi.c \ - src/misc/nm/nmTable.c diff --git a/src/misc/nm/nm.h b/src/misc/nm/nm.h deleted file mode 100644 index c6344bbf..00000000 --- a/src/misc/nm/nm.h +++ /dev/null @@ -1,92 +0,0 @@ -/**CFilextern e**************************************************************** - - FileName [nm.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Name manager.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nm.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __NM_H__ -#define __NM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - This manager is designed to store ID-to-name and name-to-ID mapping - for Boolean networks and And-Inverter Graphs. - - In a netlist, net names are unique. In this case, there is a one-to-one - mapping between IDs and names. - - In a logic network, which do not have nets, several objects may have - the same name. For example, a latch output and a primary output. - Another example, a primary input and an input to a black box. - In this case, for each ID on an object there is only one name, - but for each name may be several IDs of objects having this name. - - The name manager maps ID-to-name uniquely but it allows one name to - be mapped into several IDs. When a query to find an ID of the object - by its name is submitted, it is possible to specify the object type, - which will help select one of several IDs. If the type is -1, and - there is more than one object with the given name, any object with - the given name is returned. -*/ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Nm_Man_t_ Nm_Man_t; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== nmApi.c ==========================================================*/ -extern Nm_Man_t * Nm_ManCreate( int nSize ); -extern void Nm_ManFree( Nm_Man_t * p ); -extern int Nm_ManNumEntries( Nm_Man_t * p ); -extern char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix ); -extern void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId ); -extern char * Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId ); -extern char * Nm_ManFindNameById( Nm_Man_t * p, int ObjId ); -extern int Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type ); -extern int Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 ); -extern Vec_Int_t * Nm_ManReturnNameIds( Nm_Man_t * p ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/misc/nm/nmApi.c b/src/misc/nm/nmApi.c deleted file mode 100644 index 9165922f..00000000 --- a/src/misc/nm/nmApi.c +++ /dev/null @@ -1,272 +0,0 @@ -/**CFile**************************************************************** - - FileName [nmApi.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Name manager.] - - Synopsis [APIs of the name manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nmApi.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nmInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the name manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nm_Man_t * Nm_ManCreate( int nSize ) -{ - Nm_Man_t * p; - // allocate the table - p = ALLOC( Nm_Man_t, 1 ); - memset( p, 0, sizeof(Nm_Man_t) ); - // set the parameters - p->nSizeFactor = 2; // determined the limit on the grow of data before the table resizes - p->nGrowthFactor = 3; // determined how much the table grows after resizing - // allocate and clean the bins - p->nBins = Cudd_PrimeNm(nSize); - p->pBinsI2N = ALLOC( Nm_Entry_t *, p->nBins ); - p->pBinsN2I = ALLOC( Nm_Entry_t *, p->nBins ); - memset( p->pBinsI2N, 0, sizeof(Nm_Entry_t *) * p->nBins ); - memset( p->pBinsN2I, 0, sizeof(Nm_Entry_t *) * p->nBins ); - // start the memory manager - p->pMem = Extra_MmFlexStart(); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the name manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nm_ManFree( Nm_Man_t * p ) -{ - Extra_MmFlexStop( p->pMem ); - FREE( p->pBinsI2N ); - FREE( p->pBinsN2I ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of objects with names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nm_ManNumEntries( Nm_Man_t * p ) -{ - return p->nEntries; -} - -/**Function************************************************************* - - Synopsis [Creates a new entry in the name manager.] - - Description [Returns 1 if the entry with the given object ID - already exists in the name manager.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Nm_ManStoreIdName( Nm_Man_t * p, int ObjId, int Type, char * pName, char * pSuffix ) -{ - Nm_Entry_t * pEntry; - int RetValue, nEntrySize; - // check if the object with this ID is already stored - if ( pEntry = Nm_ManTableLookupId(p, ObjId) ) - { - printf( "Nm_ManStoreIdName(): Entry with the same ID already exists.\n" ); - return NULL; - } - // create a new entry - nEntrySize = sizeof(Nm_Entry_t) + strlen(pName) + (pSuffix?strlen(pSuffix):0) + 1; - nEntrySize = (nEntrySize / 4 + ((nEntrySize % 4) > 0)) * 4; - pEntry = (Nm_Entry_t *)Extra_MmFlexEntryFetch( p->pMem, nEntrySize ); - pEntry->pNextI2N = pEntry->pNextN2I = pEntry->pNameSake = NULL; - pEntry->ObjId = ObjId; - pEntry->Type = Type; - sprintf( pEntry->Name, "%s%s", pName, pSuffix? pSuffix : "" ); - // add the entry to the hash table - RetValue = Nm_ManTableAdd( p, pEntry ); - assert( RetValue == 1 ); - return pEntry->Name; -} - -/**Function************************************************************* - - Synopsis [Creates a new entry in the name manager.] - - Description [Returns 1 if the entry with the given object ID - already exists in the name manager.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nm_ManDeleteIdName( Nm_Man_t * p, int ObjId ) -{ - Nm_Entry_t * pEntry; - pEntry = Nm_ManTableLookupId(p, ObjId); - if ( pEntry == NULL ) - { - printf( "Nm_ManDeleteIdName(): This entry is not in the table.\n" ); - return; - } - // remove entry from the table - Nm_ManTableDelete( p, ObjId ); -} - - -/**Function************************************************************* - - Synopsis [Finds a unique name for the node.] - - Description [If the name exists, tries appending numbers to it until - it becomes unique. The name is not added to the table.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Nm_ManCreateUniqueName( Nm_Man_t * p, int ObjId ) -{ - static char NameStr[1000]; - Nm_Entry_t * pEntry; - int i; - if ( pEntry = Nm_ManTableLookupId(p, ObjId) ) - return pEntry->Name; - sprintf( NameStr, "n%d", ObjId ); - for ( i = 1; Nm_ManTableLookupName(p, NameStr, -1); i++ ) - sprintf( NameStr, "n%d_%d", ObjId, i ); - return NameStr; -} - -/**Function************************************************************* - - Synopsis [Returns name of the object if the ID is known.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Nm_ManFindNameById( Nm_Man_t * p, int ObjId ) -{ - Nm_Entry_t * pEntry; - if ( pEntry = Nm_ManTableLookupId(p, ObjId) ) - return pEntry->Name; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Returns ID of the object if its name is known.] - - Description [This procedure may return two IDs because POs and latches - may have the same name (the only allowed case of name duplication).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nm_ManFindIdByName( Nm_Man_t * p, char * pName, int Type ) -{ - Nm_Entry_t * pEntry; - if ( pEntry = Nm_ManTableLookupName(p, pName, Type) ) - return pEntry->ObjId; - return -1; -} - -/**Function************************************************************* - - Synopsis [Returns ID of the object if its name is known.] - - Description [This procedure may return two IDs because POs and latches - may have the same name (the only allowed case of name duplication).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nm_ManFindIdByNameTwoTypes( Nm_Man_t * p, char * pName, int Type1, int Type2 ) -{ - int iNodeId; - iNodeId = Nm_ManFindIdByName( p, pName, Type1 ); - if ( iNodeId == -1 ) - iNodeId = Nm_ManFindIdByName( p, pName, Type2 ); - if ( iNodeId == -1 ) - return -1; - return iNodeId; -} - -/**Function************************************************************* - - Synopsis [Return the IDs of objects with names.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Nm_ManReturnNameIds( Nm_Man_t * p ) -{ - Vec_Int_t * vNameIds; - int i; - vNameIds = Vec_IntAlloc( p->nEntries ); - for ( i = 0; i < p->nBins; i++ ) - if ( p->pBinsI2N[i] ) - Vec_IntPush( vNameIds, p->pBinsI2N[i]->ObjId ); - return vNameIds; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/nm/nmInt.h b/src/misc/nm/nmInt.h deleted file mode 100644 index 028316e1..00000000 --- a/src/misc/nm/nmInt.h +++ /dev/null @@ -1,91 +0,0 @@ -/**CFile**************************************************************** - - FileName [nmInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Name manager.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nmInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __NM_INT_H__ -#define __NM_INT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "extra.h" -#include "vec.h" -#include "nm.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Nm_Entry_t_ Nm_Entry_t; -struct Nm_Entry_t_ -{ - unsigned Type : 4; // object type - unsigned ObjId : 28; // object ID - Nm_Entry_t * pNextI2N; // the next entry in the ID hash table - Nm_Entry_t * pNextN2I; // the next entry in the name hash table - Nm_Entry_t * pNameSake; // the next entry with the same name - char Name[0]; // name of the object -}; - -struct Nm_Man_t_ -{ - Nm_Entry_t ** pBinsI2N; // mapping IDs into names - Nm_Entry_t ** pBinsN2I; // mapping names into IDs - int nBins; // the number of bins in tables - int nEntries; // the number of entries - int nSizeFactor; // determined how much larger the table should be - int nGrowthFactor; // determined how much the table grows after resizing - Extra_MmFlex_t * pMem; // memory manager for entries (and names) -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== nmTable.c ==========================================================*/ -extern int Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry ); -extern int Nm_ManTableDelete( Nm_Man_t * p, int ObjId ); -extern Nm_Entry_t * Nm_ManTableLookupId( Nm_Man_t * p, int ObjId ); -extern Nm_Entry_t * Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type ); -extern unsigned int Cudd_PrimeNm( unsigned int p ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/nm/nmTable.c b/src/misc/nm/nmTable.c deleted file mode 100644 index f97a2f0b..00000000 --- a/src/misc/nm/nmTable.c +++ /dev/null @@ -1,340 +0,0 @@ -/**CFile**************************************************************** - - FileName [nmTable.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Name manager.] - - Synopsis [Hash table for the name manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: nmTable.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "nmInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// hashing for integers -static unsigned Nm_HashNumber( int Num, int TableSize ) -{ - unsigned Key = 0; - Key ^= ( Num & 0xFF) * 7937; - Key ^= ((Num >> 8) & 0xFF) * 2971; - Key ^= ((Num >> 16) & 0xFF) * 911; - Key ^= ((Num >> 24) & 0xFF) * 353; - return Key % TableSize; -} - -// hashing for strings -static unsigned Nm_HashString( char * pName, int TableSize ) -{ - static int s_Primes[10] = { - 1291, 1699, 2357, 4177, 5147, - 5647, 6343, 7103, 7873, 8147 - }; - unsigned i, Key = 0; - for ( i = 0; pName[i] != '\0'; i++ ) - Key ^= s_Primes[i%10]*pName[i]*pName[i]; - return Key % TableSize; -} - -static void Nm_ManResize( Nm_Man_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Adds an entry to two hash tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nm_ManTableAdd( Nm_Man_t * p, Nm_Entry_t * pEntry ) -{ - Nm_Entry_t ** ppSpot, * pOther; - // resize the tables if needed - if ( p->nEntries > p->nBins * p->nSizeFactor ) - Nm_ManResize( p ); - // add the entry to the table Id->Name - assert( Nm_ManTableLookupId(p, pEntry->ObjId) == NULL ); - ppSpot = p->pBinsI2N + Nm_HashNumber(pEntry->ObjId, p->nBins); - pEntry->pNextI2N = *ppSpot; - *ppSpot = pEntry; - // check if an entry with the same name already exists - if ( pOther = Nm_ManTableLookupName(p, pEntry->Name, -1) ) - { - // entry with the same name already exists - add it to the ring - pEntry->pNameSake = pOther->pNameSake? pOther->pNameSake : pOther; - pOther->pNameSake = pEntry; - } - else - { - // entry with the same name does not exist - add it to the table - ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins); - pEntry->pNextN2I = *ppSpot; - *ppSpot = pEntry; - } - // report successfully added entry - p->nEntries++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Deletes the entry from two hash tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Nm_ManTableDelete( Nm_Man_t * p, int ObjId ) -{ - Nm_Entry_t ** ppSpot, * pEntry, * pPrev; - int fRemoved; - p->nEntries--; - // remove the entry from the table Id->Name - assert( Nm_ManTableLookupId(p, ObjId) != NULL ); - ppSpot = p->pBinsI2N + Nm_HashNumber(ObjId, p->nBins); - while ( (*ppSpot)->ObjId != (unsigned)ObjId ) - ppSpot = &(*ppSpot)->pNextI2N; - pEntry = *ppSpot; - *ppSpot = (*ppSpot)->pNextI2N; - // remove the entry from the table Name->Id - ppSpot = p->pBinsN2I + Nm_HashString(pEntry->Name, p->nBins); - while ( *ppSpot && *ppSpot != pEntry ) - ppSpot = &(*ppSpot)->pNextN2I; - // remember if we found this one in the list - fRemoved = (*ppSpot != NULL); - if ( *ppSpot ) - { - assert( *ppSpot == pEntry ); - *ppSpot = (*ppSpot)->pNextN2I; - } - // quit if this entry has no namesakes - if ( pEntry->pNameSake == NULL ) - { - assert( fRemoved ); - return 1; - } - // remove entry from the ring of namesakes - assert( pEntry->pNameSake != pEntry ); - for ( pPrev = pEntry; pPrev->pNameSake != pEntry; pPrev = pPrev->pNameSake ); - assert( !strcmp(pPrev->Name, pEntry->Name) ); - assert( pPrev->pNameSake == pEntry ); - if ( pEntry->pNameSake == pPrev ) // two entries in the ring - pPrev->pNameSake = NULL; - else - pPrev->pNameSake = pEntry->pNameSake; - // reinsert the ring back if we removed its connection with the list in the table - if ( fRemoved ) - { - assert( pPrev->pNextN2I == NULL ); - pPrev->pNextN2I = *ppSpot; - *ppSpot = pPrev; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Looks up the entry by ID.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nm_Entry_t * Nm_ManTableLookupId( Nm_Man_t * p, int ObjId ) -{ - Nm_Entry_t * pEntry; - for ( pEntry = p->pBinsI2N[ Nm_HashNumber(ObjId, p->nBins) ]; pEntry; pEntry = pEntry->pNextI2N ) - if ( pEntry->ObjId == (unsigned)ObjId ) - return pEntry; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Looks up the entry by name and type.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Nm_Entry_t * Nm_ManTableLookupName( Nm_Man_t * p, char * pName, int Type ) -{ - Nm_Entry_t * pEntry, * pTemp; - int Counter = 0; - for ( pEntry = p->pBinsN2I[ Nm_HashString(pName, p->nBins) ]; pEntry; pEntry = pEntry->pNextN2I ) - { - // check the entry itself - if ( !strcmp(pEntry->Name, pName) && (Type == -1 || pEntry->Type == (unsigned)Type) ) - return pEntry; - // if there is no namesakes, continue - if ( pEntry->pNameSake == NULL ) - continue; - // check the list of namesakes - for ( pTemp = pEntry->pNameSake; pTemp != pEntry; pTemp = pTemp->pNameSake ) - if ( !strcmp(pTemp->Name, pName) && (Type == -1 || pTemp->Type == (unsigned)Type) ) - return pTemp; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Profiles hash tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nm_ManProfile( Nm_Man_t * p ) -{ - Nm_Entry_t * pEntry; - int Counter, e; - printf( "I2N table: " ); - for ( e = 0; e < p->nBins; e++ ) - { - Counter = 0; - for ( pEntry = p->pBinsI2N[e]; pEntry; pEntry = pEntry->pNextI2N ) - Counter++; - printf( "%d ", Counter ); - } - printf( "\n" ); - printf( "N2I table: " ); - for ( e = 0; e < p->nBins; e++ ) - { - Counter = 0; - for ( pEntry = p->pBinsN2I[e]; pEntry; pEntry = pEntry->pNextN2I ) - Counter++; - printf( "%d ", Counter ); - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Nm_ManResize( Nm_Man_t * p ) -{ - Nm_Entry_t ** pBinsNewI2N, ** pBinsNewN2I, * pEntry, * pEntry2, ** ppSpot; - int nBinsNew, Counter, e, clk; - -clk = clock(); - // get the new table size - nBinsNew = Cudd_PrimeCopy( p->nGrowthFactor * p->nBins ); - // allocate a new array - pBinsNewI2N = ALLOC( Nm_Entry_t *, nBinsNew ); - pBinsNewN2I = ALLOC( Nm_Entry_t *, nBinsNew ); - memset( pBinsNewI2N, 0, sizeof(Nm_Entry_t *) * nBinsNew ); - memset( pBinsNewN2I, 0, sizeof(Nm_Entry_t *) * nBinsNew ); - // rehash entries in Id->Name table - Counter = 0; - for ( e = 0; e < p->nBins; e++ ) - for ( pEntry = p->pBinsI2N[e], pEntry2 = pEntry? pEntry->pNextI2N : NULL; - pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextI2N : NULL ) - { - ppSpot = pBinsNewI2N + Nm_HashNumber(pEntry->ObjId, nBinsNew); - pEntry->pNextI2N = *ppSpot; - *ppSpot = pEntry; - Counter++; - } - // rehash entries in Name->Id table - for ( e = 0; e < p->nBins; e++ ) - for ( pEntry = p->pBinsN2I[e], pEntry2 = pEntry? pEntry->pNextN2I : NULL; - pEntry; pEntry = pEntry2, pEntry2 = pEntry? pEntry->pNextN2I : NULL ) - { - ppSpot = pBinsNewN2I + Nm_HashString(pEntry->Name, nBinsNew); - pEntry->pNextN2I = *ppSpot; - *ppSpot = pEntry; - } - assert( Counter == p->nEntries ); -// printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew ); -// PRT( "Time", clock() - clk ); - // replace the table and the parameters - free( p->pBinsI2N ); - free( p->pBinsN2I ); - p->pBinsI2N = pBinsNewI2N; - p->pBinsN2I = pBinsNewN2I; - p->nBins = nBinsNew; -// Nm_ManProfile( p ); -} - - -/**Function************************************************************* - - Synopsis [Returns the smallest prime larger than the number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned int Cudd_PrimeNm( unsigned int p) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/misc/st/module.make b/src/misc/st/module.make deleted file mode 100644 index 33e442c0..00000000 --- a/src/misc/st/module.make +++ /dev/null @@ -1,2 +0,0 @@ -SRC += src/misc/st/st.c \ - src/misc/st/stmm.c diff --git a/src/misc/st/st.c b/src/misc/st/st.c deleted file mode 100644 index 872fe51b..00000000 --- a/src/misc/st/st.c +++ /dev/null @@ -1,625 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/st/st.c,v - * serdar - * 1.1 - * 1993/07/29 01:00:13 - * - */ -#include -#include -#include "st.h" - -#ifndef ABS -# define ABS(a) ((a) < 0 ? -(a) : (a)) -#endif - -#ifndef ALLOC -#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#endif - -#ifndef FREE -#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#endif - -#ifndef REALLOC -#define REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) -#endif - -#define ST_NUMCMP(x,y) ((x) != (y)) -#define ST_NUMHASH(x,size) (ABS((long)x)%(size)) -//#define ST_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size) // 64-bit bug fix 9/17/2007 -#define ST_PTRHASH(x,size) ((int)(((unsigned long)(x)>>2)%size)) -#define EQUAL(func, x, y) \ - ((((func) == st_numcmp) || ((func) == st_ptrcmp)) ?\ - (ST_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0)) - - -#define do_hash(key, table)\ - ((table->hash == st_ptrhash) ? ST_PTRHASH((key),(table)->num_bins) :\ - (table->hash == st_numhash) ? ST_NUMHASH((key), (table)->num_bins) :\ - (*table->hash)((key), (table)->num_bins)) - -static int rehash(); -int st_numhash(), st_ptrhash(), st_numcmp(), st_ptrcmp(); - -st_table * -st_init_table_with_params(compare, hash, size, density, grow_factor, - reorder_flag) -int (*compare)(); -int (*hash)(); -int size; -int density; -double grow_factor; -int reorder_flag; -{ - int i; - st_table *new; - - new = ALLOC(st_table, 1); - if (new == NULL) { - return NULL; - } - new->compare = compare; - new->hash = hash; - new->num_entries = 0; - new->max_density = density; - new->grow_factor = grow_factor; - new->reorder_flag = reorder_flag; - if (size <= 0) { - size = 1; - } - new->num_bins = size; - new->bins = ALLOC(st_table_entry *, size); - if (new->bins == NULL) { - FREE(new); - return NULL; - } - for(i = 0; i < size; i++) { - new->bins[i] = 0; - } - return new; -} - -st_table * -st_init_table(compare, hash) -int (*compare)(); -int (*hash)(); -{ - return st_init_table_with_params(compare, hash, ST_DEFAULT_INIT_TABLE_SIZE, - ST_DEFAULT_MAX_DENSITY, - ST_DEFAULT_GROW_FACTOR, - ST_DEFAULT_REORDER_FLAG); -} - -void -st_free_table(table) -st_table *table; -{ - register st_table_entry *ptr, *next; - int i; - - for(i = 0; i < table->num_bins ; i++) { - ptr = table->bins[i]; - while (ptr != NULL) { - next = ptr->next; - FREE(ptr); - ptr = next; - } - } - FREE(table->bins); - FREE(table); -} - -#define PTR_NOT_EQUAL(table, ptr, user_key)\ -(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) - -#define FIND_ENTRY(table, hash_val, key, ptr, last) \ - (last) = &(table)->bins[hash_val];\ - (ptr) = *(last);\ - while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ - (last) = &(ptr)->next; (ptr) = *(last);\ - }\ - if ((ptr) != NULL && (table)->reorder_flag) {\ - *(last) = (ptr)->next;\ - (ptr)->next = (table)->bins[hash_val];\ - (table)->bins[hash_val] = (ptr);\ - } - -int -st_lookup(table, key, value) -st_table *table; -register char *key; -char **value; -{ - int hash_val; - register st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr, last); - - if (ptr == NULL) { - return 0; - } else { - if (value != NULL) { - *value = ptr->record; - } - return 1; - } -} - -int -st_lookup_int(table, key, value) -st_table *table; -register char *key; -int *value; -{ - int hash_val; - register st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr, last); - - if (ptr == NULL) { - return 0; - } else { - if (value != 0) { - *value = (long) ptr->record; - } - return 1; - } -} - -/* This macro does not check if memory allocation fails. Use at you own risk */ -#define ADD_DIRECT(table, key, value, hash_val, new)\ -{\ - if (table->num_entries/table->num_bins >= table->max_density) {\ - rehash(table);\ - hash_val = do_hash(key,table);\ - }\ - \ - new = ALLOC(st_table_entry, 1);\ - \ - new->key = key;\ - new->record = value;\ - new->next = table->bins[hash_val];\ - table->bins[hash_val] = new;\ - table->num_entries++;\ -} - -int -st_insert(table, key, value) -register st_table *table; -register char *key; -char *value; -{ - int hash_val; - st_table_entry *new; - register st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr, last); - - if (ptr == NULL) { - if (table->num_entries/table->num_bins >= table->max_density) { - if (rehash(table) == ST_OUT_OF_MEM) { - return ST_OUT_OF_MEM; - } - hash_val = do_hash(key, table); - } - new = ALLOC(st_table_entry, 1); - if (new == NULL) { - return ST_OUT_OF_MEM; - } - new->key = key; - new->record = value; - new->next = table->bins[hash_val]; - table->bins[hash_val] = new; - table->num_entries++; - return 0; - } else { - ptr->record = value; - return 1; - } -} - -int -st_add_direct(table, key, value) -st_table *table; -char *key; -char *value; -{ - int hash_val; - st_table_entry *new; - - hash_val = do_hash(key, table); - if (table->num_entries / table->num_bins >= table->max_density) { - if (rehash(table) == ST_OUT_OF_MEM) { - return ST_OUT_OF_MEM; - } - } - hash_val = do_hash(key, table); - new = ALLOC(st_table_entry, 1); - if (new == NULL) { - return ST_OUT_OF_MEM; - } - new->key = key; - new->record = value; - new->next = table->bins[hash_val]; - table->bins[hash_val] = new; - table->num_entries++; - return 1; -} - -int -st_find_or_add(table, key, slot) -st_table *table; -char *key; -char ***slot; -{ - int hash_val; - st_table_entry *new, *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr, last); - - if (ptr == NULL) { - if (table->num_entries / table->num_bins >= table->max_density) { - if (rehash(table) == ST_OUT_OF_MEM) { - return ST_OUT_OF_MEM; - } - hash_val = do_hash(key, table); - } - new = ALLOC(st_table_entry, 1); - if (new == NULL) { - return ST_OUT_OF_MEM; - } - new->key = key; - new->record = (char *) 0; - new->next = table->bins[hash_val]; - table->bins[hash_val] = new; - table->num_entries++; - if (slot != NULL) *slot = &new->record; - return 0; - } else { - if (slot != NULL) *slot = &ptr->record; - return 1; - } -} - -int -st_find(table, key, slot) -st_table *table; -char *key; -char ***slot; -{ - int hash_val; - st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr, last); - - if (ptr == NULL) { - return 0; - } else { - if (slot != NULL) { - *slot = &ptr->record; - } - return 1; - } -} - -static int -rehash(table) -register st_table *table; -{ - register st_table_entry *ptr, *next, **old_bins; - int i, old_num_bins, hash_val, old_num_entries; - - /* save old values */ - old_bins = table->bins; - old_num_bins = table->num_bins; - old_num_entries = table->num_entries; - - /* rehash */ - table->num_bins = (int)(table->grow_factor * old_num_bins); - if (table->num_bins % 2 == 0) { - table->num_bins += 1; - } - table->num_entries = 0; - table->bins = ALLOC(st_table_entry *, table->num_bins); - if (table->bins == NULL) { - table->bins = old_bins; - table->num_bins = old_num_bins; - table->num_entries = old_num_entries; - return ST_OUT_OF_MEM; - } - /* initialize */ - for (i = 0; i < table->num_bins; i++) { - table->bins[i] = 0; - } - - /* copy data over */ - for (i = 0; i < old_num_bins; i++) { - ptr = old_bins[i]; - while (ptr != NULL) { - next = ptr->next; - hash_val = do_hash(ptr->key, table); - ptr->next = table->bins[hash_val]; - table->bins[hash_val] = ptr; - table->num_entries++; - ptr = next; - } - } - FREE(old_bins); - - return 1; -} - -st_table * -st_copy(old_table) -st_table *old_table; -{ - st_table *new_table; - st_table_entry *ptr, *newptr, *next, *new; - int i, j, num_bins = old_table->num_bins; - - new_table = ALLOC(st_table, 1); - if (new_table == NULL) { - return NULL; - } - - *new_table = *old_table; - new_table->bins = ALLOC(st_table_entry *, num_bins); - if (new_table->bins == NULL) { - FREE(new_table); - return NULL; - } - for(i = 0; i < num_bins ; i++) { - new_table->bins[i] = NULL; - ptr = old_table->bins[i]; - while (ptr != NULL) { - new = ALLOC(st_table_entry, 1); - if (new == NULL) { - for (j = 0; j <= i; j++) { - newptr = new_table->bins[j]; - while (newptr != NULL) { - next = newptr->next; - FREE(newptr); - newptr = next; - } - } - FREE(new_table->bins); - FREE(new_table); - return NULL; - } - *new = *ptr; - new->next = new_table->bins[i]; - new_table->bins[i] = new; - ptr = ptr->next; - } - } - return new_table; -} - -int -st_delete(table, keyp, value) -register st_table *table; -register char **keyp; -char **value; -{ - int hash_val; - char *key = *keyp; - register st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr ,last); - - if (ptr == NULL) { - return 0; - } - - *last = ptr->next; - if (value != NULL) *value = ptr->record; - *keyp = ptr->key; - FREE(ptr); - table->num_entries--; - return 1; -} - -int -st_delete_int(table, keyp, value) -register st_table *table; -register long *keyp; -char **value; -{ - int hash_val; - char *key = (char *) *keyp; - register st_table_entry *ptr, **last; - - hash_val = do_hash(key, table); - - FIND_ENTRY(table, hash_val, key, ptr ,last); - - if (ptr == NULL) { - return 0; - } - - *last = ptr->next; - if (value != NULL) *value = ptr->record; - *keyp = (long) ptr->key; - FREE(ptr); - table->num_entries--; - return 1; -} - -int -st_foreach(table, func, arg) -st_table *table; -enum st_retval (*func)(); -char *arg; -{ - st_table_entry *ptr, **last; - enum st_retval retval; - int i; - - for(i = 0; i < table->num_bins; i++) { - last = &table->bins[i]; ptr = *last; - while (ptr != NULL) { - retval = (*func)(ptr->key, ptr->record, arg); - switch (retval) { - case ST_CONTINUE: - last = &ptr->next; ptr = *last; - break; - case ST_STOP: - return 0; - case ST_DELETE: - *last = ptr->next; - table->num_entries--; /* cstevens@ic */ - FREE(ptr); - ptr = *last; - } - } - } - return 1; -} - -int -st_strhash(string, modulus) -register char *string; -int modulus; -{ - register int val = 0; - register int c; - - while ((c = *string++) != '\0') { - val = val*997 + c; - } - - return ((val < 0) ? -val : val)%modulus; -} - -int -st_numhash(x, size) -char *x; -int size; -{ - return ST_NUMHASH(x, size); -} - -int -st_ptrhash(x, size) -char *x; -int size; -{ - return ST_PTRHASH(x, size); -} - -int -st_numcmp(x, y) -char *x; -char *y; -{ - return ST_NUMCMP(x, y); -} - -int -st_ptrcmp(x, y) -char *x; -char *y; -{ - return ST_NUMCMP(x, y); -} - -st_generator * -st_init_gen(table) -st_table *table; -{ - st_generator *gen; - - gen = ALLOC(st_generator, 1); - if (gen == NULL) { - return NULL; - } - gen->table = table; - gen->entry = NULL; - gen->index = 0; - return gen; -} - - -int -st_gen(gen, key_p, value_p) -st_generator *gen; -char **key_p; -char **value_p; -{ - register int i; - - if (gen->entry == NULL) { - /* try to find next entry */ - for(i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NULL) { - gen->index = i+1; - gen->entry = gen->table->bins[i]; - break; - } - } - if (gen->entry == NULL) { - return 0; /* that's all folks ! */ - } - } - *key_p = gen->entry->key; - if (value_p != 0) { - *value_p = gen->entry->record; - } - gen->entry = gen->entry->next; - return 1; -} - - -int -st_gen_int(gen, key_p, value_p) -st_generator *gen; -char **key_p; -long *value_p; -{ - register int i; - - if (gen->entry == NULL) { - /* try to find next entry */ - for(i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NULL) { - gen->index = i+1; - gen->entry = gen->table->bins[i]; - break; - } - } - if (gen->entry == NULL) { - return 0; /* that's all folks ! */ - } - } - *key_p = gen->entry->key; - if (value_p != 0) { - *value_p = (long) gen->entry->record; - } - gen->entry = gen->entry->next; - return 1; -} - - -void -st_free_gen(gen) -st_generator *gen; -{ - FREE(gen); -} diff --git a/src/misc/st/st.h b/src/misc/st/st.h deleted file mode 100644 index b15f3c83..00000000 --- a/src/misc/st/st.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/st/st.h,v - * serdar - * 1.1 - * 1993/07/29 01:00:21 - * - */ -/* LINTLIBRARY */ - -/* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */ - -#ifndef ST_INCLUDED -#define ST_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct st_table_entry st_table_entry; -struct st_table_entry { - char *key; - char *record; - st_table_entry *next; -}; - -typedef struct st_table st_table; -struct st_table { - int (*compare)(); - int (*hash)(); - int num_bins; - int num_entries; - int max_density; - int reorder_flag; - double grow_factor; - st_table_entry **bins; -}; - -typedef struct st_generator st_generator; -struct st_generator { - st_table *table; - st_table_entry *entry; - int index; -}; - -#define st_is_member(table,key) st_lookup(table,key,(char **) 0) -#define st_count(table) ((table)->num_entries) - -enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE}; - -typedef enum st_retval (*ST_PFSR)(); -typedef int (*ST_PFI)(); - -extern st_table *st_init_table_with_params (ST_PFI, ST_PFI, int, int, double, int); -extern st_table *st_init_table (ST_PFI, ST_PFI); -extern void st_free_table (st_table *); -extern int st_lookup (st_table *, char *, char **); -extern int st_lookup_int (st_table *, char *, int *); -extern int st_insert (st_table *, char *, char *); -extern int st_add_direct (st_table *, char *, char *); -extern int st_find_or_add (st_table *, char *, char ***); -extern int st_find (st_table *, char *, char ***); -extern st_table *st_copy (st_table *); -extern int st_delete (st_table *, char **, char **); -extern int st_delete_int (st_table *, long *, char **); -extern int st_foreach (st_table *, ST_PFSR, char *); -extern int st_strhash (char *, int); -extern int st_numhash (char *, int); -extern int st_ptrhash (char *, int); -extern int st_numcmp (char *, char *); -extern int st_ptrcmp (char *, char *); -extern st_generator *st_init_gen (st_table *); -extern int st_gen (st_generator *, char **, char **); -extern int st_gen_int (st_generator *, char **, long *); -extern void st_free_gen (st_generator *); - - -#define ST_DEFAULT_MAX_DENSITY 5 -#define ST_DEFAULT_INIT_TABLE_SIZE 11 -#define ST_DEFAULT_GROW_FACTOR 2.0 -#define ST_DEFAULT_REORDER_FLAG 0 - -#define st_foreach_item(table, gen, key, value) \ - for(gen=st_init_gen(table); st_gen(gen,key,value) || (st_free_gen(gen),0);) - -#define st_foreach_item_int(table, gen, key, value) \ - for(gen=st_init_gen(table); st_gen_int(gen,key,value) || (st_free_gen(gen),0);) - -#define ST_OUT_OF_MEM -10000 - -#ifdef __cplusplus -} -#endif - -#endif /* ST_INCLUDED */ diff --git a/src/misc/st/stmm.c b/src/misc/st/stmm.c deleted file mode 100644 index 8dfacfe4..00000000 --- a/src/misc/st/stmm.c +++ /dev/null @@ -1,688 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/st/st.c,v - * serdar - * 1.1 - * 1993/07/29 01:00:13 - * - */ -#include -#include "extra.h" -#include "stmm.h" - -#ifndef ABS -# define ABS(a) ((a) < 0 ? -(a) : (a)) -#endif - -#define STMM_NUMCMP(x,y) ((x) != (y)) -#define STMM_NUMHASH(x,size) (ABS((long)x)%(size)) -//#define STMM_PTRHASH(x,size) ((int)((unsigned long)(x)>>2)%size) // 64-bit bug fix 9/17/2007 -#define STMM_PTRHASH(x,size) ((int)(((unsigned long)(x)>>2)%size)) -#define EQUAL(func, x, y) \ - ((((func) == stmm_numcmp) || ((func) == stmm_ptrcmp)) ?\ - (STMM_NUMCMP((x),(y)) == 0) : ((*func)((x), (y)) == 0)) - - -#define do_hash(key, table)\ - ((table->hash == stmm_ptrhash) ? STMM_PTRHASH((key),(table)->num_bins) :\ - (table->hash == stmm_numhash) ? STMM_NUMHASH((key), (table)->num_bins) :\ - (*table->hash)((key), (table)->num_bins)) - -static int rehash (); -int stmm_numhash (), stmm_ptrhash (), stmm_numcmp (), stmm_ptrcmp (); - -stmm_table * -stmm_init_table_with_params (compare, hash, size, density, grow_factor, - reorder_flag) - int (*compare) (); - int (*hash) (); - int size; - int density; - double grow_factor; - int reorder_flag; -{ - int i; - stmm_table *new; - - new = ALLOC (stmm_table, 1); - if (new == NULL) { - return NULL; - } - new->compare = compare; - new->hash = hash; - new->num_entries = 0; - new->max_density = density; - new->grow_factor = grow_factor; - new->reorder_flag = reorder_flag; - if (size <= 0) { - size = 1; - } - new->num_bins = size; - new->bins = ALLOC (stmm_table_entry *, size); - if (new->bins == NULL) { - FREE (new); - return NULL; - } - for (i = 0; i < size; i++) { - new->bins[i] = 0; - } - - // added by alanmi - new->pMemMan = Extra_MmFixedStart(sizeof (stmm_table_entry)); - return new; -} - -stmm_table * -stmm_init_table (compare, hash) - int (*compare) (); - int (*hash) (); -{ - return stmm_init_table_with_params (compare, hash, - STMM_DEFAULT_INIT_TABLE_SIZE, - STMM_DEFAULT_MAX_DENSITY, - STMM_DEFAULT_GROW_FACTOR, - STMM_DEFAULT_REORDER_FLAG); -} - -void -stmm_free_table (table) - stmm_table *table; -{ -/* - register stmm_table_entry *ptr, *next; - int i; - for ( i = 0; i < table->num_bins; i++ ) - { - ptr = table->bins[i]; - while ( ptr != NULL ) - { - next = ptr->next; - FREE( ptr ); - ptr = next; - } - } -*/ - // no need to deallocate entries because they are in the memory manager now - // added by alanmi - if ( table->pMemMan ) - Extra_MmFixedStop (table->pMemMan); - FREE (table->bins); - FREE (table); -} - -// this function recycles all the bins -void -stmm_clean (table) - stmm_table *table; -{ - int i; - // clean the bins - for (i = 0; i < table->num_bins; i++) - table->bins[i] = NULL; - // reset the parameters - table->num_entries = 0; - // restart the memory manager - Extra_MmFixedRestart (table->pMemMan); -} - - -#define PTR_NOT_EQUAL(table, ptr, user_key)\ -(ptr != NULL && !EQUAL(table->compare, user_key, (ptr)->key)) - -#define FIND_ENTRY(table, hash_val, key, ptr, last) \ - (last) = &(table)->bins[hash_val];\ - (ptr) = *(last);\ - while (PTR_NOT_EQUAL((table), (ptr), (key))) {\ - (last) = &(ptr)->next; (ptr) = *(last);\ - }\ - if ((ptr) != NULL && (table)->reorder_flag) {\ - *(last) = (ptr)->next;\ - (ptr)->next = (table)->bins[hash_val];\ - (table)->bins[hash_val] = (ptr);\ - } - -int -stmm_lookup (table, key, value) - stmm_table *table; - register char *key; - char **value; -{ - int hash_val; - register stmm_table_entry *ptr, **last; - - hash_val = do_hash (key, table); - - FIND_ENTRY (table, hash_val, key, ptr, last); - - if (ptr == NULL) { - return 0; - } - else { - if (value != NULL) - { - *value = ptr->record; - } - return 1; - } -} - -int -stmm_lookup_int (table, key, value) - stmm_table *table; - register char *key; - int *value; -{ - int hash_val; - register stmm_table_entry *ptr, **last; - - hash_val = do_hash (key, table); - - FIND_ENTRY (table, hash_val, key, ptr, last); - - if (ptr == NULL) { - return 0; - } - else { - if (value != 0) - { - *value = (long) ptr->record; - } - return 1; - } -} - -// This macro contained a line -// new = ALLOC(stmm_table_entry, 1); -// which was modified by alanmi - - -/* This macro does not check if memory allocation fails. Use at you own risk */ -#define ADD_DIRECT(table, key, value, hash_val, new)\ -{\ - if (table->num_entries/table->num_bins >= table->max_density) {\ - rehash(table);\ - hash_val = do_hash(key,table);\ - }\ - \ - new = (stmm_table_entry *)Extra_MmFixedEntryFetch( table->pMemMan );\ - \ - new->key = key;\ - new->record = value;\ - new->next = table->bins[hash_val];\ - table->bins[hash_val] = new;\ - table->num_entries++;\ -} - -int -stmm_insert (table, key, value) - register stmm_table *table; - register char *key; - char *value; -{ - int hash_val; - stmm_table_entry *new; - register stmm_table_entry *ptr, **last; - - hash_val = do_hash (key, table); - - FIND_ENTRY (table, hash_val, key, ptr, last); - - if (ptr == NULL) { - if (table->num_entries / table->num_bins >= table->max_density) { - if (rehash (table) == STMM_OUT_OF_MEM) { - return STMM_OUT_OF_MEM; - } - hash_val = do_hash (key, table); - } - -// new = ALLOC( stmm_table_entry, 1 ); - new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); - if (new == NULL) { - return STMM_OUT_OF_MEM; - } - - new->key = key; - new->record = value; - new->next = table->bins[hash_val]; - table->bins[hash_val] = new; - table->num_entries++; - return 0; - } - else { - ptr->record = value; - return 1; - } -} - -int -stmm_add_direct (table, key, value) - stmm_table *table; - char *key; - char *value; -{ - int hash_val; - stmm_table_entry *new; - - hash_val = do_hash (key, table); - if (table->num_entries / table->num_bins >= table->max_density) { - if (rehash (table) == STMM_OUT_OF_MEM) { - return STMM_OUT_OF_MEM; - } - } - hash_val = do_hash (key, table); - -// new = ALLOC( stmm_table_entry, 1 ); - new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); - if (new == NULL) { - return STMM_OUT_OF_MEM; - } - - new->key = key; - new->record = value; - new->next = table->bins[hash_val]; - table->bins[hash_val] = new; - table->num_entries++; - return 1; -} - -int -stmm_find_or_add (table, key, slot) - stmm_table *table; - char *key; - char ***slot; -{ - int hash_val; - stmm_table_entry *new, *ptr, **last; - - hash_val = do_hash (key, table); - - FIND_ENTRY (table, hash_val, key, ptr, last); - - if (ptr == NULL) { - if (table->num_entries / table->num_bins >= table->max_density) { - if (rehash (table) == STMM_OUT_OF_MEM) { - return STMM_OUT_OF_MEM; - } - hash_val = do_hash (key, table); - } - - // new = ALLOC( stmm_table_entry, 1 ); - new = (stmm_table_entry *) Extra_MmFixedEntryFetch (table->pMemMan); - if (new == NULL) { - return STMM_OUT_OF_MEM; - } - - new->key = key; - new->record = (char *) 0; - new->next = table->bins[hash_val]; - table->bins[hash_val] = new; - table->num_entries++; - if (slot != NULL) - *slot = &new->record; - return 0; - } - else { - if (slot != NULL) - *slot = &ptr->record; - return 1; - } -} - -int -stmm_find (table, key, slot) - stmm_table *table; - char *key; - char ***slot; -{ - int hash_val; - stmm_table_entry *ptr, **last; - - hash_val = do_hash (key, table); - - FIND_ENTRY (table, hash_val, key, ptr, last); - - if (ptr == NULL) { - return 0; - } - else { - if (slot != NULL) - { - *slot = &ptr->record; - } - return 1; - } -} - -static int -rehash (table) - register stmm_table *table; -{ - register stmm_table_entry *ptr, *next, **old_bins; - int i, old_num_bins, hash_val, old_num_entries; - - /* save old values */ - old_bins = table->bins; - old_num_bins = table->num_bins; - old_num_entries = table->num_entries; - - /* rehash */ - table->num_bins = (int) (table->grow_factor * old_num_bins); - if (table->num_bins % 2 == 0) { - table->num_bins += 1; - } - table->num_entries = 0; - table->bins = ALLOC (stmm_table_entry *, table->num_bins); - if (table->bins == NULL) { - table->bins = old_bins; - table->num_bins = old_num_bins; - table->num_entries = old_num_entries; - return STMM_OUT_OF_MEM; - } - /* initialize */ - for (i = 0; i < table->num_bins; i++) { - table->bins[i] = 0; - } - - /* copy data over */ - for (i = 0; i < old_num_bins; i++) { - ptr = old_bins[i]; - while (ptr != NULL) { - next = ptr->next; - hash_val = do_hash (ptr->key, table); - ptr->next = table->bins[hash_val]; - table->bins[hash_val] = ptr; - table->num_entries++; - ptr = next; - } - } - FREE (old_bins); - - return 1; -} - -stmm_table * -stmm_copy (old_table) - stmm_table *old_table; -{ - stmm_table *new_table; - stmm_table_entry *ptr, /* *newptr, *next, */ *new; - int i, /*j, */ num_bins = old_table->num_bins; - - new_table = ALLOC (stmm_table, 1); - if (new_table == NULL) { - return NULL; - } - - *new_table = *old_table; - new_table->bins = ALLOC (stmm_table_entry *, num_bins); - if (new_table->bins == NULL) { - FREE (new_table); - return NULL; - } - - // allocate the memory manager for the new table - new_table->pMemMan = - Extra_MmFixedStart (sizeof (stmm_table_entry)); - - for (i = 0; i < num_bins; i++) { - new_table->bins[i] = NULL; - ptr = old_table->bins[i]; - while (ptr != NULL) { -// new = ALLOC( stmm_table_entry, 1 ); - new = - (stmm_table_entry *) Extra_MmFixedEntryFetch (new_table-> - pMemMan); - - if (new == NULL) { -/* - for ( j = 0; j <= i; j++ ) - { - newptr = new_table->bins[j]; - while ( newptr != NULL ) - { - next = newptr->next; - FREE( newptr ); - newptr = next; - } - } -*/ - Extra_MmFixedStop (new_table->pMemMan); - - FREE (new_table->bins); - FREE (new_table); - return NULL; - } - *new = *ptr; - new->next = new_table->bins[i]; - new_table->bins[i] = new; - ptr = ptr->next; - } - } - return new_table; -} - -int -stmm_delete (table, keyp, value) - register stmm_table *table; - register char **keyp; - char **value; -{ - int hash_val; - char *key = *keyp; - register stmm_table_entry *ptr, **last; - - hash_val = do_hash (key, table); - - FIND_ENTRY (table, hash_val, key, ptr, last); - - if (ptr == NULL) { - return 0; - } - - *last = ptr->next; - if (value != NULL) - *value = ptr->record; - *keyp = ptr->key; -// FREE( ptr ); - Extra_MmFixedEntryRecycle (table->pMemMan, (char *) ptr); - - table->num_entries--; - return 1; -} - -int -stmm_delete_int (table, keyp, value) - register stmm_table *table; - register long *keyp; - char **value; -{ - int hash_val; - char *key = (char *) *keyp; - register stmm_table_entry *ptr, **last; - - hash_val = do_hash (key, table); - - FIND_ENTRY (table, hash_val, key, ptr, last); - - if (ptr == NULL) { - return 0; - } - - *last = ptr->next; - if (value != NULL) - *value = ptr->record; - *keyp = (long) ptr->key; -// FREE( ptr ); - Extra_MmFixedEntryRecycle (table->pMemMan, (char *) ptr); - - table->num_entries--; - return 1; -} - -int -stmm_foreach (table, func, arg) - stmm_table *table; - enum stmm_retval (*func) (); - char *arg; -{ - stmm_table_entry *ptr, **last; - enum stmm_retval retval; - int i; - - for (i = 0; i < table->num_bins; i++) { - last = &table->bins[i]; - ptr = *last; - while (ptr != NULL) { - retval = (*func) (ptr->key, ptr->record, arg); - switch (retval) { - case STMM_CONTINUE: - last = &ptr->next; - ptr = *last; - break; - case STMM_STOP: - return 0; - case STMM_DELETE: - *last = ptr->next; - table->num_entries--; /* cstevens@ic */ -// FREE( ptr ); - Extra_MmFixedEntryRecycle (table->pMemMan, (char *) ptr); - - ptr = *last; - } - } - } - return 1; -} - -int -stmm_strhash (string, modulus) - register char *string; - int modulus; -{ - register int val = 0; - register int c; - - while ((c = *string++) != '\0') { - val = val * 997 + c; - } - - return ((val < 0) ? -val : val) % modulus; -} - -int -stmm_numhash (x, size) - char *x; - int size; -{ - return STMM_NUMHASH (x, size); -} - -int -stmm_ptrhash (x, size) - char *x; - int size; -{ - return STMM_PTRHASH (x, size); -} - -int -stmm_numcmp (x, y) - char *x; - char *y; -{ - return STMM_NUMCMP (x, y); -} - -int -stmm_ptrcmp (x, y) - char *x; - char *y; -{ - return STMM_NUMCMP (x, y); -} - -stmm_generator * -stmm_init_gen (table) - stmm_table *table; -{ - stmm_generator *gen; - - gen = ALLOC (stmm_generator, 1); - if (gen == NULL) { - return NULL; - } - gen->table = table; - gen->entry = NULL; - gen->index = 0; - return gen; -} - - -int -stmm_gen (gen, key_p, value_p) - stmm_generator *gen; - char **key_p; - char **value_p; -{ - register int i; - - if (gen->entry == NULL) { - /* try to find next entry */ - for (i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NULL) { - gen->index = i + 1; - gen->entry = gen->table->bins[i]; - break; - } - } - if (gen->entry == NULL) { - return 0; /* that's all folks ! */ - } - } - *key_p = gen->entry->key; - if (value_p != 0) { - *value_p = gen->entry->record; - } - gen->entry = gen->entry->next; - return 1; -} - - -int -stmm_gen_int (gen, key_p, value_p) - stmm_generator *gen; - char **key_p; - long *value_p; -{ - register int i; - - if (gen->entry == NULL) { - /* try to find next entry */ - for (i = gen->index; i < gen->table->num_bins; i++) { - if (gen->table->bins[i] != NULL) { - gen->index = i + 1; - gen->entry = gen->table->bins[i]; - break; - } - } - if (gen->entry == NULL) { - return 0; /* that's all folks ! */ - } - } - *key_p = gen->entry->key; - if (value_p != 0) - { - *value_p = (long) gen->entry->record; - } - gen->entry = gen->entry->next; - return 1; -} - - -void -stmm_free_gen (gen) - stmm_generator *gen; -{ - FREE (gen); -} diff --git a/src/misc/st/stmm.h b/src/misc/st/stmm.h deleted file mode 100644 index 4330416e..00000000 --- a/src/misc/st/stmm.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Revision Control Information - * - * /projects/hsis/CVS/utilities/st/st.h,v - * serdar - * 1.1 - * 1993/07/29 01:00:21 - * - */ -/* LINTLIBRARY */ - -/* /projects/hsis/CVS/utilities/st/st.h,v 1.1 1993/07/29 01:00:21 serdar Exp */ - -#ifndef STMM_INCLUDED -#define STMM_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -#include "extra.h" - -typedef struct stmm_table_entry stmm_table_entry; -typedef struct stmm_table stmm_table; -typedef struct stmm_generator stmm_generator; - -struct stmm_table_entry -{ - char *key; - char *record; - stmm_table_entry *next; -}; - -struct stmm_table -{ - int (*compare) (); - int (*hash) (); - int num_bins; - int num_entries; - int max_density; - int reorder_flag; - double grow_factor; - stmm_table_entry **bins; - // memory manager to improve runtime and prevent memory fragmentation - // added by alanmi - January 16, 2003 - Extra_MmFixed_t *pMemMan; -}; - -struct stmm_generator -{ - stmm_table *table; - stmm_table_entry *entry; - int index; -}; - -#define stmm_is_member(table,key) stmm_lookup(table,key,(char **) 0) -#define stmm_count(table) ((table)->num_entries) - -enum stmm_retval -{ STMM_CONTINUE, STMM_STOP, STMM_DELETE }; - -typedef enum stmm_retval (*STMM_PFSR) (); -typedef int (*STMM_PFI) (); - -EXTERN stmm_table *stmm_init_table_with_params -ARGS ((STMM_PFI, STMM_PFI, int, int, double, int)); -EXTERN stmm_table *stmm_init_table ARGS ((STMM_PFI, STMM_PFI)); -EXTERN void stmm_free_table ARGS ((stmm_table *)); -EXTERN int stmm_lookup ARGS ((stmm_table *, char *, char **)); -EXTERN int stmm_lookup_int ARGS ((stmm_table *, char *, int *)); -EXTERN int stmm_insert ARGS ((stmm_table *, char *, char *)); -EXTERN int stmm_add_direct ARGS ((stmm_table *, char *, char *)); -EXTERN int stmm_find_or_add ARGS ((stmm_table *, char *, char ***)); -EXTERN int stmm_find ARGS ((stmm_table *, char *, char ***)); -EXTERN stmm_table *stmm_copy ARGS ((stmm_table *)); -EXTERN int stmm_delete ARGS ((stmm_table *, char **, char **)); -EXTERN int stmm_delete_int ARGS ((stmm_table *, long *, char **)); -EXTERN int stmm_foreach ARGS ((stmm_table *, STMM_PFSR, char *)); -EXTERN int stmm_strhash ARGS ((char *, int)); -EXTERN int stmm_numhash ARGS ((char *, int)); -EXTERN int stmm_ptrhash ARGS ((char *, int)); -EXTERN int stmm_numcmp ARGS ((char *, char *)); -EXTERN int stmm_ptrcmp ARGS ((char *, char *)); -EXTERN stmm_generator *stmm_init_gen ARGS ((stmm_table *)); -EXTERN int stmm_gen ARGS ((stmm_generator *, char **, char **)); -EXTERN int stmm_gen_int ARGS ((stmm_generator *, char **, long *)); -EXTERN void stmm_free_gen ARGS ((stmm_generator *)); -// additional functions -EXTERN void stmm_clean ARGS ((stmm_table *)); - - - -#define STMM_DEFAULT_MAX_DENSITY 5 -#define STMM_DEFAULT_INIT_TABLE_SIZE 11 -#define STMM_DEFAULT_GROW_FACTOR 2.0 -#define STMM_DEFAULT_REORDER_FLAG 0 - -// added by Zhihong: no need for memory allocation -#define stmm_foreach_item2(tb, /* stmm_generator */gen, key, value) \ - for(gen.table=(tb), gen.entry=NULL, gen.index=0; \ - stmm_gen(&(gen),key,value);) - -#define stmm_foreach_item(table, gen, key, value) \ - for(gen=stmm_init_gen(table); stmm_gen(gen,key,value) || (stmm_free_gen(gen),0);) - -#define stmm_foreach_item_int(table, gen, key, value) \ - for(gen=stmm_init_gen(table); stmm_gen_int(gen,key,value) || (stmm_free_gen(gen),0);) - -#define STMM_OUT_OF_MEM -10000 - -/* - -// consider adding these other other similar definitions -#define st_table stmm_table -#define st_insert stmm_insert -#define st_delete stmm_delete -#define st_lookup stmm_lookup -#define st_init_table stmm_init_table -#define st_free_table stmm_free_table - -*/ - -#ifdef __cplusplus -} -#endif - -#endif /* STMM_INCLUDED */ diff --git a/src/misc/util/leaks.h b/src/misc/util/leaks.h deleted file mode 100644 index 1a32062a..00000000 --- a/src/misc/util/leaks.h +++ /dev/null @@ -1,30 +0,0 @@ -////////////////////////////////////////////////////////////////////////// -// This file is used to detect memory leaks using Visual Studio 6.0 -// The idea comes from this page: http://www.michaelmoser.org/memory.htm -// In addition to this file, it required the presence of "stdlib_hack.h" -////////////////////////////////////////////////////////////////////////// - -#ifndef __LEAKS_H__ -#define __LEAKS_H__ - -#ifdef _DEBUG -#define _CRTDBG_MAP_ALLOC // include Microsoft memory leak detection procedures -//#define _INC_MALLOC // exclude standard memory alloc procedures - -#define malloc(s) _malloc_dbg(s, _NORMAL_BLOCK, __FILE__, __LINE__) -#define calloc(c, s) _calloc_dbg(c, s, _NORMAL_BLOCK, __FILE__, __LINE__) -#define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) -//#define _expand(p, s) _expand_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) -//#define free(p) _free_dbg(p, _NORMAL_BLOCK) -//#define _msize(p) _msize_dbg(p, _NORMAL_BLOCK) - -//#include -#include -#include -#endif - -#endif - -////////////////////////////////////// - - diff --git a/src/misc/util/module.make b/src/misc/util/module.make deleted file mode 100644 index d6d908e7..00000000 --- a/src/misc/util/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += diff --git a/src/misc/util/stdlib_hack.h b/src/misc/util/stdlib_hack.h deleted file mode 100644 index 2ddf73d1..00000000 --- a/src/misc/util/stdlib_hack.h +++ /dev/null @@ -1,4 +0,0 @@ - -#include - - diff --git a/src/misc/util/util_hack.h b/src/misc/util/util_hack.h deleted file mode 100644 index 71c77321..00000000 --- a/src/misc/util/util_hack.h +++ /dev/null @@ -1,95 +0,0 @@ -/**CFile**************************************************************** - - FileName [util_hack.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [This file is used to simulate the presence of "util.h".] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: util_hack.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __UTIL_HACK_H__ -#define __UTIL_HACK_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include -#include -#include - -#define EXTERN extern -#define NIL(type) ((type *) 0) -#define random rand -#define srandom srand - -#define util_cpu_time Extra_CpuTime -#define getSoftDataLimit Extra_GetSoftDataLimit -#define util_getopt_reset Extra_UtilGetoptReset -#define util_getopt Extra_UtilGetopt -#define util_print_time Extra_UtilPrintTime -#define util_strsav Extra_UtilStrsav -#define util_tilde_expand Extra_UtilTildeExpand -#define util_file_search Extra_UtilFileSearch -#define MMoutOfMemory Extra_UtilMMoutOfMemory - -#define util_optarg globalUtilOptarg -#define util_optind globalUtilOptind - -#ifndef ARGS -# ifdef __STDC__ -# define ARGS(args) args -# else -# define ARGS(args) () -# endif -#endif - -#ifndef ABS -# define ABS(a) ((a) < 0 ? -(a) : (a)) -#endif - -#ifndef MAX -# define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#define REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) - -extern long Extra_CpuTime(); -extern int Extra_GetSoftDataLimit(); -extern void Extra_UtilGetoptReset(); -extern int Extra_UtilGetopt( int argc, char *argv[], char *optstring ); -extern char * Extra_UtilPrintTime( long t ); -extern char * Extra_UtilStrsav( char *s ); -extern char * Extra_UtilTildeExpand( char *fname ); -extern char * Extra_UtilFileSearch( char *file, char *path, char *mode ); - -extern char * globalUtilOptarg; -extern int globalUtilOptind; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/misc/vec/module.make b/src/misc/vec/module.make deleted file mode 100644 index d6d908e7..00000000 --- a/src/misc/vec/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += diff --git a/src/misc/vec/vec.h b/src/misc/vec/vec.h deleted file mode 100644 index 6a97fcaa..00000000 --- a/src/misc/vec/vec.h +++ /dev/null @@ -1,110 +0,0 @@ -/**CFile**************************************************************** - - FileName [vec.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_H__ -#define __VEC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#pragma warning(disable : 4152) // warning C4152: nonstandard extension, function/data pointer conversion in expression -#pragma warning(disable : 4244) // warning C4244: '+=' : conversion from 'int ' to 'unsigned short ', possible loss of data -#pragma warning(disable : 4514) // warning C4514: 'Vec_StrPop' : unreferenced inline function has been removed -#pragma warning(disable : 4710) // warning C4710: function 'Vec_PtrGrow' not inlined -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -// this include should be the first one in the list -// it is used to catch memory leaks on Windows -#include "leaks.h" - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#ifndef ABS -#define ABS(a) ((a) < 0 ? -(a) : (a)) -#endif - -#ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#ifndef ALLOC -#define ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) -#endif - -#ifndef FREE -#define FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#endif - -#ifndef REALLOC -#define REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) -#endif - -#ifndef PRT -#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) -#endif - -#ifndef PRTP -#define PRTP(a,t,T) printf("%s = ", (a)); printf("%6.2f sec (%6.2f %%)\n", (float)(t)/(float)(CLOCKS_PER_SEC), (T)? 100.0*(t)/(T) : 0.0) -#endif - -#include "vecInt.h" -#include "vecFlt.h" -#include "vecStr.h" -#include "vecPtr.h" -#include "vecVec.h" -#include "vecAtt.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/misc/vec/vecAtt.h b/src/misc/vec/vecAtt.h deleted file mode 100644 index da7a8445..00000000 --- a/src/misc/vec/vecAtt.h +++ /dev/null @@ -1,391 +0,0 @@ -/**CFile**************************************************************** - - FileName [vecAtt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [Array of user-specified attiributes.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vecAtt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __Vec_Att_H__ -#define __Vec_Att_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// various attributes -typedef enum { - VEC_ATTR_NONE = 0, // 0 - VEC_ATTR_COPY, // 1 - VEC_ATTR_LOCAL_AIG, // 2 - VEC_ATTR_LOCAL_SOP, // 3 - VEC_ATTR_LOCAL_BDD, // 4 - VEC_ATTR_GLOBAL_AIG, // 5 - VEC_ATTR_GLOBAL_SOP, // 6 - VEC_ATTR_GLOBAL_BDD, // 7 - VEC_ATTR_LEVEL, // 8 - VEC_ATTR_LEVEL_REV, // 9 - VEC_ATTR_RETIME_LAG, // 10 - VEC_ATTR_FRAIG, // 11 - VEC_ATTR_MVVAR, // 12 - VEC_ATTR_DATA1, // 13 - VEC_ATTR_DATA2, // 14 - VEC_ATTR_TOTAL_NUM // 15 -} Vec_AttrType_t; - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Vec_Att_t_ Vec_Att_t; -struct Vec_Att_t_ -{ - // storage for attributes - int nCap; // the size of array allocated - int * pArrayInt; // the integer attribute array - void ** pArrayPtr; // the pointer attribute array - // attribute specific info - void * pMan; // the manager for this attribute - void (*pFuncFreeMan) (void *); // the procedure to free the manager - void*(*pFuncStartObj)(void *); // the procedure to start one attribute - void (*pFuncFreeObj) (void *, void *); // the procedure to free one attribute -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Att_t * Vec_AttAlloc( - int fInteger, int nSize, void * pMan, - void (*pFuncFreeMan) (void *), - void*(*pFuncStartObj)(void *), - void (*pFuncFreeObj) (void *, void *) ) -{ - Vec_Att_t * p; - p = ALLOC( Vec_Att_t, 1 ); - memset( p, 0, sizeof(Vec_Att_t) ); - p->pMan = pMan; - p->pFuncFreeMan = pFuncFreeMan; - p->pFuncStartObj = pFuncStartObj; - p->pFuncFreeObj = pFuncFreeObj; - p->nCap = nSize? nSize : 16; - if ( fInteger ) - { - p->pArrayInt = ALLOC( int, p->nCap ); - memset( p->pArrayInt, 0xff, sizeof(int) * p->nCap ); - } - else - { - p->pArrayPtr = ALLOC( void *, p->nCap ); - memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap ); - } - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_AttFree( Vec_Att_t * p, int fFreeMan ) -{ - void * pMan; - if ( p == NULL ) - return NULL; - // free the attributes of objects - if ( p->pFuncFreeObj ) - { - int i; - if ( p->pArrayInt ) - { - for ( i = 0; i < p->nCap; i++ ) - if ( p->pArrayInt[i] ) - p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] ); - } - else - { - for ( i = 0; i < p->nCap; i++ ) - if ( p->pArrayPtr[i] ) - p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] ); - } - } - // free the memory manager - pMan = fFreeMan? NULL : p->pMan; - if ( p->pMan && fFreeMan ) - p->pFuncFreeMan( p->pMan ); - FREE( p->pArrayInt ); - FREE( p->pArrayPtr ); - FREE( p ); - return pMan; -} - -/**Function************************************************************* - - Synopsis [Clears the vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_AttClear( Vec_Att_t * p ) -{ - // free the attributes of objects - if ( p->pFuncFreeObj ) - { - int i; - if ( p->pArrayInt ) - { - if ( p->pFuncFreeObj ) - for ( i = 0; i < p->nCap; i++ ) - if ( p->pArrayInt[i] ) - p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] ); - } - else - { - if ( p->pFuncFreeObj ) - for ( i = 0; i < p->nCap; i++ ) - if ( p->pArrayPtr[i] ) - p->pFuncFreeObj( p->pMan, p->pArrayPtr[i] ); - } - } - if ( p->pArrayInt ) - memset( p->pArrayInt, 0xff, sizeof(int) * p->nCap ); - else - memset( p->pArrayPtr, 0, sizeof(void *) * p->nCap ); - -} - -/**Function************************************************************* - - Synopsis [Deletes one entry from the attribute manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_AttFreeEntry( Vec_Att_t * p, int i ) -{ - if ( i >= p->nCap ) - return; - if ( p->pMan ) - { - if ( p->pArrayInt[i] && p->pFuncFreeObj ) - p->pFuncFreeObj( p->pMan, (void *)p->pArrayInt[i] ); - if ( p->pArrayPtr[i] && p->pFuncFreeObj ) - p->pFuncFreeObj( p->pMan, (void *)p->pArrayPtr[i] ); - } - if ( p->pArrayInt ) - p->pArrayInt[i] = ~(unsigned)0; - else - p->pArrayPtr[i] = NULL; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_AttGrow( Vec_Att_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - if ( p->pArrayInt ) - { - p->pArrayInt = REALLOC( int, p->pArrayInt, nCapMin ); - memset( p->pArrayInt + p->nCap, 0xff, sizeof(int) * (nCapMin - p->nCap) ); - } - else - { - p->pArrayPtr = REALLOC( void *, p->pArrayPtr, nCapMin ); - memset( p->pArrayPtr + p->nCap, 0, sizeof(void *) * (nCapMin - p->nCap) ); - } - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [Writes the entry into its place.] - - Description [Only works if the manager is not defined.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_AttWriteEntry( Vec_Att_t * p, int i, void * pEntry ) -{ - assert( p->pArrayPtr ); - assert( p->pFuncStartObj == NULL ); - if ( i >= p->nCap ) - Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 ); - p->pArrayPtr[i] = pEntry; -} - -/**Function************************************************************* - - Synopsis [Writes the entry into its place.] - - Description [Only works if the manager is not defined.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_AttWriteEntryInt( Vec_Att_t * p, int i, int Entry ) -{ - assert( p->pArrayInt ); - assert( p->pFuncStartObj == NULL ); - if ( i >= p->nCap ) - Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 ); - p->pArrayInt[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [Returns the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_AttEntry( Vec_Att_t * p, int i ) -{ - assert( p->pArrayPtr ); - if ( i >= p->nCap ) - Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 ); - if ( p->pArrayPtr[i] == NULL && p->pFuncStartObj ) - p->pArrayPtr[i] = p->pFuncStartObj( p->pMan ); - return p->pArrayPtr[i]; -} - -/**Function************************************************************* - - Synopsis [Returns the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_AttEntryInt( Vec_Att_t * p, int i ) -{ - assert( p->pArrayInt ); - assert( p->pMan == NULL ); - if ( i >= p->nCap ) - Vec_AttGrow( p, (2 * p->nCap > i)? 2 * p->nCap : i + 10 ); - return p->pArrayInt[i]; -} - -/**Function************************************************************* - - Synopsis [Returns the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_AttMan( Vec_Att_t * p ) -{ - return p->pMan; -} - -/**Function************************************************************* - - Synopsis [Returns the array of attributes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void ** Vec_AttArray( Vec_Att_t * p ) -{ - return p->pArrayPtr; -} - -/**Function************************************************************* - - Synopsis [Returns the array of attributes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int * Vec_AttArrayInt( Vec_Att_t * p ) -{ - return p->pArrayInt; -} - -#endif - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/misc/vec/vecFlt.h b/src/misc/vec/vecFlt.h deleted file mode 100644 index 6b36ce84..00000000 --- a/src/misc/vec/vecFlt.h +++ /dev/null @@ -1,630 +0,0 @@ -/**CFile**************************************************************** - - FileName [vecFlt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [Resizable arrays of floats.] - - Author [Aaron P. Hurst] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_FLT_H__ -#define __VEC_FLT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Vec_Flt_t_ Vec_Flt_t; -struct Vec_Flt_t_ -{ - int nCap; - int nSize; - float * pArray; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Vec_FltForEachEntry( vVec, Entry, i ) \ - for ( i = 0; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) -#define Vec_FltForEachEntryStart( vVec, Entry, i, Start ) \ - for ( i = Start; (i < Vec_FltSize(vVec)) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) -#define Vec_FltForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \ - for ( i = Start; (i < Stop) && (((Entry) = Vec_FltEntry(vVec, i)), 1); i++ ) -#define Vec_FltForEachEntryReverse( vVec, pEntry, i ) \ - for ( i = Vec_FltSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_FltEntry(vVec, i)), 1); i-- ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltAlloc( int nCap ) -{ - Vec_Flt_t * p; - p = ALLOC( Vec_Flt_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( float, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given size and cleans it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltStart( int nSize ) -{ - Vec_Flt_t * p; - p = Vec_FltAlloc( nSize ); - p->nSize = nSize; - memset( p->pArray, 0, sizeof(float) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from a float array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltAllocArray( float * pArray, int nSize ) -{ - Vec_Flt_t * p; - p = ALLOC( Vec_Flt_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = pArray; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from a float array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltAllocArrayCopy( float * pArray, int nSize ) -{ - Vec_Flt_t * p; - p = ALLOC( Vec_Flt_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = ALLOC( float, nSize ); - memcpy( p->pArray, pArray, sizeof(float) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the float array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltDup( Vec_Flt_t * pVec ) -{ - Vec_Flt_t * p; - p = ALLOC( Vec_Flt_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = p->nCap? ALLOC( float, p->nCap ) : NULL; - memcpy( p->pArray, pVec->pArray, sizeof(float) * pVec->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Transfers the array into another vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Flt_t * Vec_FltDupArray( Vec_Flt_t * pVec ) -{ - Vec_Flt_t * p; - p = ALLOC( Vec_Flt_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = pVec->pArray; - pVec->nSize = 0; - pVec->nCap = 0; - pVec->pArray = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltFree( Vec_Flt_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float * Vec_FltReleaseArray( Vec_Flt_t * p ) -{ - float * pArray = p->pArray; - p->nCap = 0; - p->nSize = 0; - p->pArray = NULL; - return pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float * Vec_FltArray( Vec_Flt_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltSize( Vec_Flt_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Vec_FltEntry( Vec_Flt_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltWriteEntry( Vec_Flt_t * p, int i, float Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltAddToEntry( Vec_Flt_t * p, int i, float Addition ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] += Addition; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Vec_FltEntryLast( Vec_Flt_t * p ) -{ - return p->pArray[p->nSize-1]; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltGrow( Vec_Flt_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( float, p->pArray, nCapMin ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltFill( Vec_Flt_t * p, int nSize, float Entry ) -{ - int i; - Vec_FltGrow( p, nSize ); - for ( i = 0; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltFillExtra( Vec_Flt_t * p, int nSize, float Entry ) -{ - int i; - if ( p->nSize >= nSize ) - return; - Vec_FltGrow( p, nSize ); - for ( i = p->nSize; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltShrink( Vec_Flt_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltClear( Vec_Flt_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltPush( Vec_Flt_t * p, float Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_FltGrow( p, 16 ); - else - Vec_FltGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltPushOrder( Vec_Flt_t * p, float Entry ) -{ - int i; - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_FltGrow( p, 16 ); - else - Vec_FltGrow( p, 2 * p->nCap ); - } - p->nSize++; - for ( i = p->nSize-2; i >= 0; i-- ) - if ( p->pArray[i] > Entry ) - p->pArray[i+1] = p->pArray[i]; - else - break; - p->pArray[i+1] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltPushUnique( Vec_Flt_t * p, float Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Vec_FltPush( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns the last entry and removes it from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline float Vec_FltPop( Vec_Flt_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [Find entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltFind( Vec_Flt_t * p, float Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltRemove( Vec_Flt_t * p, float Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - break; - if ( i == p->nSize ) - return 0; - assert( i < p->nSize ); - for ( i++; i < p->nSize; i++ ) - p->pArray[i-1] = p->pArray[i]; - p->nSize--; - return 1; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two floats.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltSortCompare1( float * pp1, float * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two floats.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_FltSortCompare2( float * pp1, float * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 > *pp2 ) - return -1; - if ( *pp1 < *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_FltSort( Vec_Flt_t * p, int fReverse ) -{ - if ( fReverse ) - qsort( (void *)p->pArray, p->nSize, sizeof(float), - (int (*)(const void *, const void *)) Vec_FltSortCompare2 ); - else - qsort( (void *)p->pArray, p->nSize, sizeof(float), - (int (*)(const void *, const void *)) Vec_FltSortCompare1 ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#endif - diff --git a/src/misc/vec/vecInt.h b/src/misc/vec/vecInt.h deleted file mode 100644 index 3afa39af..00000000 --- a/src/misc/vec/vecInt.h +++ /dev/null @@ -1,834 +0,0 @@ -/**CFile**************************************************************** - - FileName [vecInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [Resizable arrays of integers.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vecInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_INT_H__ -#define __VEC_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Vec_Int_t_ Vec_Int_t; -struct Vec_Int_t_ -{ - int nCap; - int nSize; - int * pArray; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Vec_IntForEachEntry( vVec, Entry, i ) \ - for ( i = 0; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) -#define Vec_IntForEachEntryStart( vVec, Entry, i, Start ) \ - for ( i = Start; (i < Vec_IntSize(vVec)) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) -#define Vec_IntForEachEntryStartStop( vVec, Entry, i, Start, Stop ) \ - for ( i = Start; (i < Stop) && (((Entry) = Vec_IntEntry(vVec, i)), 1); i++ ) -#define Vec_IntForEachEntryReverse( vVec, pEntry, i ) \ - for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_IntEntry(vVec, i)), 1); i-- ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntAlloc( int nCap ) -{ - Vec_Int_t * p; - p = ALLOC( Vec_Int_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given size and cleans it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntStart( int nSize ) -{ - Vec_Int_t * p; - p = Vec_IntAlloc( nSize ); - p->nSize = nSize; - memset( p->pArray, 0, sizeof(int) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given size and cleans it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntStartNatural( int nSize ) -{ - Vec_Int_t * p; - int i; - p = Vec_IntAlloc( nSize ); - p->nSize = nSize; - for ( i = 0; i < nSize; i++ ) - p->pArray[i] = i; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntAllocArray( int * pArray, int nSize ) -{ - Vec_Int_t * p; - p = ALLOC( Vec_Int_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = pArray; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntAllocArrayCopy( int * pArray, int nSize ) -{ - Vec_Int_t * p; - p = ALLOC( Vec_Int_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = ALLOC( int, nSize ); - memcpy( p->pArray, pArray, sizeof(int) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the integer array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntDup( Vec_Int_t * pVec ) -{ - Vec_Int_t * p; - p = ALLOC( Vec_Int_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nSize; - p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL; - memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Transfers the array into another vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntDupArray( Vec_Int_t * pVec ) -{ - Vec_Int_t * p; - p = ALLOC( Vec_Int_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = pVec->pArray; - pVec->nSize = 0; - pVec->nCap = 0; - pVec->pArray = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntFree( Vec_Int_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int * Vec_IntReleaseArray( Vec_Int_t * p ) -{ - int * pArray = p->pArray; - p->nCap = 0; - p->nSize = 0; - p->pArray = NULL; - return pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int * Vec_IntArray( Vec_Int_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntSize( Vec_Int_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntEntry( Vec_Int_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntWriteEntry( Vec_Int_t * p, int i, int Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntAddToEntry( Vec_Int_t * p, int i, int Addition ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] += Addition; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntEntryLast( Vec_Int_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[p->nSize-1]; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntGrow( Vec_Int_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( int, p->pArray, nCapMin ); - assert( p->pArray ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntFill( Vec_Int_t * p, int nSize, int Entry ) -{ - int i; - Vec_IntGrow( p, nSize ); - for ( i = 0; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntFillExtra( Vec_Int_t * p, int nSize, int Entry ) -{ - int i; - if ( p->nSize >= nSize ) - return; - Vec_IntGrow( p, nSize ); - for ( i = p->nSize; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntShrink( Vec_Int_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntClear( Vec_Int_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntPush( Vec_Int_t * p, int Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_IntGrow( p, 16 ); - else - Vec_IntGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntPushFirst( Vec_Int_t * p, int Entry ) -{ - int i; - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_IntGrow( p, 16 ); - else - Vec_IntGrow( p, 2 * p->nCap ); - } - p->nSize++; - for ( i = p->nSize - 1; i >= 1; i-- ) - p->pArray[i] = p->pArray[i-1]; - p->pArray[0] = Entry; -} - -/**Function************************************************************* - - Synopsis [Inserts the entry while preserving the increasing order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry ) -{ - int i; - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_IntGrow( p, 16 ); - else - Vec_IntGrow( p, 2 * p->nCap ); - } - p->nSize++; - for ( i = p->nSize-2; i >= 0; i-- ) - if ( p->pArray[i] > Entry ) - p->pArray[i+1] = p->pArray[i]; - else - break; - p->pArray[i+1] = Entry; -} - -/**Function************************************************************* - - Synopsis [Inserts the entry while preserving the increasing order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntPushUniqueOrder( Vec_Int_t * p, int Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Vec_IntPushOrder( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntPushUnique( Vec_Int_t * p, int Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Vec_IntPush( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the next nWords entries in the vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned * Vec_IntFetch( Vec_Int_t * p, int nWords ) -{ - if ( nWords == 0 ) - return NULL; - assert( nWords > 0 ); - p->nSize += nWords; - if ( p->nSize > p->nCap ) - { -// Vec_IntGrow( p, 2 * p->nSize ); - return NULL; - } - return ((unsigned *)p->pArray) + p->nSize - nWords; -} - -/**Function************************************************************* - - Synopsis [Returns the last entry and removes it from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntPop( Vec_Int_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [Find entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntFind( Vec_Int_t * p, int Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntRemove( Vec_Int_t * p, int Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - break; - if ( i == p->nSize ) - return 0; - assert( i < p->nSize ); - for ( i++; i < p->nSize; i++ ) - p->pArray[i-1] = p->pArray[i]; - p->nSize--; - return 1; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two integers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntSortCompare1( int * pp1, int * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two integers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntSortCompare2( int * pp1, int * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 > *pp2 ) - return -1; - if ( *pp1 < *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntSort( Vec_Int_t * p, int fReverse ) -{ - if ( fReverse ) - qsort( (void *)p->pArray, p->nSize, sizeof(int), - (int (*)(const void *, const void *)) Vec_IntSortCompare2 ); - else - qsort( (void *)p->pArray, p->nSize, sizeof(int), - (int (*)(const void *, const void *)) Vec_IntSortCompare1 ); -} - - -/**Function************************************************************* - - Synopsis [Comparison procedure for two integers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntSortCompareUnsigned( unsigned * pp1, unsigned * pp2 ) -{ - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_IntSortUnsigned( Vec_Int_t * p ) -{ - qsort( (void *)p->pArray, p->nSize, sizeof(int), - (int (*)(const void *, const void *)) Vec_IntSortCompareUnsigned ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of common entries.] - - Description [Assumes that the vectors are sorted in the increasing order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_IntTwoCountCommon( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) -{ - int * pBeg1 = vArr1->pArray; - int * pBeg2 = vArr2->pArray; - int * pEnd1 = vArr1->pArray + vArr1->nSize; - int * pEnd2 = vArr2->pArray + vArr2->nSize; - int Counter = 0; - while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) - { - if ( *pBeg1 == *pBeg2 ) - *pBeg1++, pBeg2++, Counter++; - else if ( *pBeg1 < *pBeg2 ) - *pBeg1++; - else - *pBeg2++; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Returns the result of merging the two vectors.] - - Description [Assumes that the vectors are sorted in the increasing order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Int_t * Vec_IntTwoMerge( Vec_Int_t * vArr1, Vec_Int_t * vArr2 ) -{ - Vec_Int_t * vArr = Vec_IntAlloc( vArr1->nSize + vArr2->nSize ); - int * pBeg = vArr->pArray; - int * pBeg1 = vArr1->pArray; - int * pBeg2 = vArr2->pArray; - int * pEnd1 = vArr1->pArray + vArr1->nSize; - int * pEnd2 = vArr2->pArray + vArr2->nSize; - while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) - { - if ( *pBeg1 == *pBeg2 ) - *pBeg++ = *pBeg1++, pBeg2++; - else if ( *pBeg1 < *pBeg2 ) - *pBeg++ = *pBeg1++; - else - *pBeg++ = *pBeg2++; - } - while ( pBeg1 < pEnd1 ) - *pBeg++ = *pBeg1++; - while ( pBeg2 < pEnd2 ) - *pBeg++ = *pBeg2++; - vArr->nSize = pBeg - vArr->pArray; - assert( vArr->nSize <= vArr->nCap ); - assert( vArr->nSize >= vArr1->nSize ); - assert( vArr->nSize >= vArr2->nSize ); - return vArr; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/misc/vec/vecPtr.h b/src/misc/vec/vecPtr.h deleted file mode 100644 index 1862bc7c..00000000 --- a/src/misc/vec/vecPtr.h +++ /dev/null @@ -1,762 +0,0 @@ -/**CFile**************************************************************** - - FileName [vecPtr.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [Resizable arrays of generic pointers.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vecPtr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_PTR_H__ -#define __VEC_PTR_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Vec_Ptr_t_ Vec_Ptr_t; -struct Vec_Ptr_t_ -{ - int nCap; - int nSize; - void ** pArray; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// iterators through entries -#define Vec_PtrForEachEntry( vVec, pEntry, i ) \ - for ( i = 0; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) -#define Vec_PtrForEachEntryStart( vVec, pEntry, i, Start ) \ - for ( i = Start; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) -#define Vec_PtrForEachEntryStop( vVec, pEntry, i, Stop ) \ - for ( i = 0; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) -#define Vec_PtrForEachEntryStartStop( vVec, pEntry, i, Start, Stop ) \ - for ( i = Start; (i < Stop) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ ) -#define Vec_PtrForEachEntryReverse( vVec, pEntry, i ) \ - for ( i = Vec_PtrSize(vVec) - 1; (i >= 0) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i-- ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrAlloc( int nCap ) -{ - Vec_Ptr_t * p; - p = ALLOC( Vec_Ptr_t, 1 ); - if ( nCap > 0 && nCap < 8 ) - nCap = 8; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given size and cleans it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrStart( int nSize ) -{ - Vec_Ptr_t * p; - p = Vec_PtrAlloc( nSize ); - p->nSize = nSize; - memset( p->pArray, 0, sizeof(void *) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrAllocArray( void ** pArray, int nSize ) -{ - Vec_Ptr_t * p; - p = ALLOC( Vec_Ptr_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = pArray; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrAllocArrayCopy( void ** pArray, int nSize ) -{ - Vec_Ptr_t * p; - p = ALLOC( Vec_Ptr_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = ALLOC( void *, nSize ); - memcpy( p->pArray, pArray, sizeof(void *) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates the array of simulation info.] - - Description [Allocates the array containing given number of entries, - each of which contains given number of unsigned words of simulation data. - The resulting array can be freed using regular procedure Vec_PtrFree(). - It is the responsibility of the user to ensure this array is never grown.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrAllocSimInfo( int nEntries, int nWords ) -{ - void ** pMemory; - unsigned * pInfo; - int i; - pMemory = (void **)ALLOC( char, (sizeof(void *) + sizeof(unsigned) * nWords) * nEntries ); - pInfo = (unsigned *)(pMemory + nEntries); - for ( i = 0; i < nEntries; i++ ) - pMemory[i] = pInfo + i * nWords; - return Vec_PtrAllocArray( pMemory, nEntries ); -} - -/**Function************************************************************* - - Synopsis [Allocates the array of truth tables for the given number of vars.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrAllocTruthTables( int nVars ) -{ - Vec_Ptr_t * p; - unsigned Masks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - unsigned * pTruth; - int i, k, nWords; - nWords = (nVars <= 5 ? 1 : (1 << (nVars - 5))); - p = Vec_PtrAllocSimInfo( nVars, nWords ); - for ( i = 0; i < nVars; i++ ) - { - pTruth = (unsigned *)p->pArray[i]; - if ( i < 5 ) - { - for ( k = 0; k < nWords; k++ ) - pTruth[k] = Masks[i]; - } - else - { - for ( k = 0; k < nWords; k++ ) - if ( k & (1 << (i-5)) ) - pTruth[k] = ~(unsigned)0; - else - pTruth[k] = 0; - } - } - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the integer array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrDup( Vec_Ptr_t * pVec ) -{ - Vec_Ptr_t * p; - p = ALLOC( Vec_Ptr_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL; - memcpy( p->pArray, pVec->pArray, sizeof(void *) * pVec->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Transfers the array into another vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Ptr_t * Vec_PtrDupArray( Vec_Ptr_t * pVec ) -{ - Vec_Ptr_t * p; - p = ALLOC( Vec_Ptr_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = pVec->pArray; - pVec->nSize = 0; - pVec->nCap = 0; - pVec->pArray = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrFree( Vec_Ptr_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void ** Vec_PtrReleaseArray( Vec_Ptr_t * p ) -{ - void ** pArray = p->pArray; - p->nCap = 0; - p->nSize = 0; - p->pArray = NULL; - return pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void ** Vec_PtrArray( Vec_Ptr_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_PtrSize( Vec_Ptr_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_PtrEntry( Vec_Ptr_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [Resizes the array of simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrDoubleSimInfo( Vec_Ptr_t * vInfo ) -{ - Vec_Ptr_t * vInfoNew; - int nWords; - assert( Vec_PtrSize(vInfo) > 2 ); - // get the new array - nWords = (unsigned *)Vec_PtrEntry(vInfo,1) - (unsigned *)Vec_PtrEntry(vInfo,0); - vInfoNew = Vec_PtrAllocSimInfo( 2*Vec_PtrSize(vInfo), nWords ); - // copy the simulation info - memcpy( Vec_PtrEntry(vInfoNew,0), Vec_PtrEntry(vInfo,0), Vec_PtrSize(vInfo) * nWords * 4 ); - // replace the array - free( vInfo->pArray ); - vInfo->pArray = vInfoNew->pArray; - vInfo->nSize *= 2; - vInfo->nCap *= 2; - // free the old array - vInfoNew->pArray = NULL; - free( vInfoNew ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void ** Vec_PtrEntryP( Vec_Ptr_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray + i; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrWriteEntry( Vec_Ptr_t * p, int i, void * Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_PtrEntryLast( Vec_Ptr_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[p->nSize-1]; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrGrow( Vec_Ptr_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( void *, p->pArray, nCapMin ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrFill( Vec_Ptr_t * p, int nSize, void * Entry ) -{ - int i; - Vec_PtrGrow( p, nSize ); - for ( i = 0; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrFillExtra( Vec_Ptr_t * p, int nSize, void * Entry ) -{ - int i; - if ( p->nSize >= nSize ) - return; - assert( p->nSize < nSize ); - if ( 2 * p->nSize > nSize ) - Vec_PtrGrow( p, 2 * nSize ); - else - Vec_PtrGrow( p, nSize ); - for ( i = p->nSize; i < nSize; i++ ) - p->pArray[i] = Entry; - p->nSize = nSize; -} - -/**Function************************************************************* - - Synopsis [Returns the entry even if the place not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_PtrGetEntry( Vec_Ptr_t * p, int i ) -{ - Vec_PtrFillExtra( p, i + 1, NULL ); - return Vec_PtrEntry( p, i ); -} - -/**Function************************************************************* - - Synopsis [Inserts the entry even if the place does not exist.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrSetEntry( Vec_Ptr_t * p, int i, void * Entry ) -{ - Vec_PtrFillExtra( p, i + 1, NULL ); - Vec_PtrWriteEntry( p, i, Entry ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrShrink( Vec_Ptr_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrClear( Vec_Ptr_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [Copies the interger array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrCopy( Vec_Ptr_t * pDest, Vec_Ptr_t * pSour ) -{ - pDest->nSize = 0; - Vec_PtrGrow( pDest, pSour->nSize ); - memcpy( pDest->pArray, pSour->pArray, sizeof(void *) * pSour->nSize ); - pDest->nSize = pSour->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrPush( Vec_Ptr_t * p, void * Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_PtrGrow( p, 16 ); - else - Vec_PtrGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_PtrPushUnique( Vec_Ptr_t * p, void * Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Vec_PtrPush( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns the last entry and removes it from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_PtrPop( Vec_Ptr_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [Find entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_PtrFind( Vec_Ptr_t * p, void * Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return i; - return -1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrRemove( Vec_Ptr_t * p, void * Entry ) -{ - int i; - // delete assuming that it is closer to the end - for ( i = p->nSize - 1; i >= 0; i-- ) - if ( p->pArray[i] == Entry ) - break; - assert( i >= 0 ); -/* - // delete assuming that it is closer to the beginning - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - break; - assert( i < p->nSize ); -*/ - for ( i++; i < p->nSize; i++ ) - p->pArray[i-1] = p->pArray[i]; - p->nSize--; -} - -/**Function************************************************************* - - Synopsis [Moves the first nItems to the end.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrReorder( Vec_Ptr_t * p, int nItems ) -{ - assert( nItems < p->nSize ); - Vec_PtrGrow( p, nItems + p->nSize ); - memmove( (char **)p->pArray + p->nSize, p->pArray, nItems * sizeof(void*) ); - memmove( p->pArray, (char **)p->pArray + nItems, p->nSize * sizeof(void*) ); -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrSort( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) -{ - if ( p->nSize < 2 ) - return; - qsort( (void *)p->pArray, p->nSize, sizeof(void *), - (int (*)(const void *, const void *)) Vec_PtrSortCompare ); -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_PtrUniqify( Vec_Ptr_t * p, int (*Vec_PtrSortCompare)() ) -{ - int i, k; - if ( p->nSize < 2 ) - return; - qsort( (void *)p->pArray, p->nSize, sizeof(void *), - (int (*)(const void *, const void *)) Vec_PtrSortCompare ); - for ( i = k = 1; i < p->nSize; i++ ) - if ( p->pArray[i] != p->pArray[i-1] ) - p->pArray[k++] = p->pArray[i]; - p->nSize = k; -} - -#endif - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/misc/vec/vecStr.h b/src/misc/vec/vecStr.h deleted file mode 100644 index 47367bc6..00000000 --- a/src/misc/vec/vecStr.h +++ /dev/null @@ -1,583 +0,0 @@ -/**CFile**************************************************************** - - FileName [vecStr.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [Resizable arrays of characters.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vecStr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_STR_H__ -#define __VEC_STR_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Vec_Str_t_ Vec_Str_t; -struct Vec_Str_t_ -{ - int nCap; - int nSize; - char * pArray; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define Vec_StrForEachEntry( vVec, Entry, i ) \ - for ( i = 0; (i < Vec_StrSize(vVec)) && (((Entry) = Vec_StrEntry(vVec, i)), 1); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrAlloc( int nCap ) -{ - Vec_Str_t * p; - p = ALLOC( Vec_Str_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given size and cleans it.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrStart( int nSize ) -{ - Vec_Str_t * p; - p = Vec_StrAlloc( nSize ); - p->nSize = nSize; - memset( p->pArray, 0, sizeof(char) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrAllocArray( char * pArray, int nSize ) -{ - Vec_Str_t * p; - p = ALLOC( Vec_Str_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = pArray; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrAllocArrayCopy( char * pArray, int nSize ) -{ - Vec_Str_t * p; - p = ALLOC( Vec_Str_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = ALLOC( char, nSize ); - memcpy( p->pArray, pArray, sizeof(char) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the integer array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrDup( Vec_Str_t * pVec ) -{ - Vec_Str_t * p; - p = ALLOC( Vec_Str_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = p->nCap? ALLOC( char, p->nCap ) : NULL; - memcpy( p->pArray, pVec->pArray, sizeof(char) * pVec->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Transfers the array into another vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Str_t * Vec_StrDupArray( Vec_Str_t * pVec ) -{ - Vec_Str_t * p; - p = ALLOC( Vec_Str_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = pVec->pArray; - pVec->nSize = 0; - pVec->nCap = 0; - pVec->pArray = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrFree( Vec_Str_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline char * Vec_StrReleaseArray( Vec_Str_t * p ) -{ - char * pArray = p->pArray; - p->nCap = 0; - p->nSize = 0; - p->pArray = NULL; - return pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline char * Vec_StrArray( Vec_Str_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_StrSize( Vec_Str_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline char Vec_StrEntry( Vec_Str_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrWriteEntry( Vec_Str_t * p, int i, char Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline char Vec_StrEntryLast( Vec_Str_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[p->nSize-1]; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrGrow( Vec_Str_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( char, p->pArray, 2 * nCapMin ); - p->nCap = 2 * nCapMin; -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrFill( Vec_Str_t * p, int nSize, char Entry ) -{ - int i; - Vec_StrGrow( p, nSize ); - p->nSize = nSize; - for ( i = 0; i < p->nSize; i++ ) - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrShrink( Vec_Str_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrClear( Vec_Str_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrPush( Vec_Str_t * p, char Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Vec_StrGrow( p, 16 ); - else - Vec_StrGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function******************************************************************** - - Synopsis [Finds the smallest integer larger of equal than the logarithm.] - - Description [Returns [Log10(Num)].] - - SideEffects [] - - SeeAlso [] - -******************************************************************************/ -static inline int Vec_StrBase10Log( unsigned Num ) -{ - int Res; - assert( Num >= 0 ); - if ( Num == 0 ) return 0; - if ( Num == 1 ) return 1; - for ( Res = 0, Num--; Num; Num /= 10, Res++ ); - return Res; -} /* end of Extra_Base2Log */ - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrPrintNum( Vec_Str_t * p, int Num ) -{ - int i, nDigits; - if ( Num < 0 ) - { - Vec_StrPush( p, '-' ); - Num = -Num; - } - if ( Num < 10 ) - { - Vec_StrPush( p, (char)('0' + Num) ); - return; - } - nDigits = Vec_StrBase10Log( Num ); - Vec_StrGrow( p, p->nSize + nDigits ); - for ( i = nDigits - 1; i >= 0; i-- ) - { - Vec_StrWriteEntry( p, p->nSize + i, (char)('0' + Num % 10) ); - Num /= 10; - } - assert( Num == 0 ); - p->nSize += nDigits; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrPrintStr( Vec_Str_t * p, char * pStr ) -{ - int i, Length = strlen(pStr); - for ( i = 0; i < Length; i++ ) - Vec_StrPush( p, pStr[i] ); -} - -/**Function************************************************************* - - Synopsis [Appends the string to the char vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrAppend( Vec_Str_t * p, char * pString ) -{ - int i, nLength = strlen(pString); - Vec_StrGrow( p, p->nSize + nLength ); - for ( i = 0; i < nLength; i++ ) - p->pArray[p->nSize + i] = pString[i]; - p->nSize += nLength; -} - -/**Function************************************************************* - - Synopsis [Returns the last entry and removes it from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline char Vec_StrPop( Vec_Str_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_StrSortCompare1( char * pp1, char * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_StrSortCompare2( char * pp1, char * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 > *pp2 ) - return -1; - if ( *pp1 < *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_StrSort( Vec_Str_t * p, int fReverse ) -{ - if ( fReverse ) - qsort( (void *)p->pArray, p->nSize, sizeof(char), - (int (*)(const void *, const void *)) Vec_StrSortCompare2 ); - else - qsort( (void *)p->pArray, p->nSize, sizeof(char), - (int (*)(const void *, const void *)) Vec_StrSortCompare1 ); -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/misc/vec/vecVec.h b/src/misc/vec/vecVec.h deleted file mode 100644 index 55ffdf4f..00000000 --- a/src/misc/vec/vecVec.h +++ /dev/null @@ -1,356 +0,0 @@ -/**CFile**************************************************************** - - FileName [vecVec.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resizable arrays.] - - Synopsis [Resizable vector of resizable vectors.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: vecVec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __VEC_VEC_H__ -#define __VEC_VEC_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Vec_Vec_t_ Vec_Vec_t; -struct Vec_Vec_t_ -{ - int nCap; - int nSize; - void ** pArray; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// iterators through levels -#define Vec_VecForEachLevel( vGlob, vVec, i ) \ - for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ ) -#define Vec_VecForEachLevelStart( vGlob, vVec, i, LevelStart ) \ - for ( i = LevelStart; (i < Vec_VecSize(vGlob)) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ ) -#define Vec_VecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ - for ( i = LevelStart; (i <= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i++ ) -#define Vec_VecForEachLevelReverse( vGlob, vVec, i ) \ - for ( i = Vec_VecSize(vGlob) - 1; (i >= 0) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- ) -#define Vec_VecForEachLevelReverseStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \ - for ( i = LevelStart; (i >= LevelStop) && (((vVec) = (Vec_Ptr_t*)Vec_VecEntry(vGlob, i)), 1); i-- ) - -// iteratores through entries -#define Vec_VecForEachEntry( vGlob, pEntry, i, k ) \ - for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \ - Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k ) -#define Vec_VecForEachEntryLevel( vGlob, pEntry, i, Level ) \ - Vec_PtrForEachEntry( Vec_VecEntry(vGlob, Level), pEntry, i ) -#define Vec_VecForEachEntryStart( vGlob, pEntry, i, k, LevelStart ) \ - for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ ) \ - Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k ) -#define Vec_VecForEachEntryStartStop( vGlob, pEntry, i, k, LevelStart, LevelStop ) \ - for ( i = LevelStart; i <= LevelStop; i++ ) \ - Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k ) -#define Vec_VecForEachEntryReverse( vGlob, pEntry, i, k ) \ - for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \ - Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k ) -#define Vec_VecForEachEntryReverseReverse( vGlob, pEntry, i, k ) \ - for ( i = Vec_VecSize(vGlob) - 1; i >= 0; i-- ) \ - Vec_PtrForEachEntryReverse( Vec_VecEntry(vGlob, i), pEntry, k ) -#define Vec_VecForEachEntryReverseStart( vGlob, pEntry, i, k, LevelStart ) \ - for ( i = LevelStart; i >= 0; i-- ) \ - Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Vec_t * Vec_VecAlloc( int nCap ) -{ - Vec_Vec_t * p; - p = ALLOC( Vec_Vec_t, 1 ); - if ( nCap > 0 && nCap < 8 ) - nCap = 8; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Vec_Vec_t * Vec_VecStart( int nSize ) -{ - Vec_Vec_t * p; - int i; - p = Vec_VecAlloc( nSize ); - for ( i = 0; i < nSize; i++ ) - p->pArray[i] = Vec_PtrAlloc( 0 ); - p->nSize = nSize; - return p; -} - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_VecExpand( Vec_Vec_t * p, int Level ) -{ - int i; - if ( p->nSize >= Level + 1 ) - return; - Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 ); - for ( i = p->nSize; i <= Level; i++ ) - p->pArray[i] = Vec_PtrAlloc( 0 ); - p->nSize = Level + 1; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_VecSize( Vec_Vec_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void * Vec_VecEntry( Vec_Vec_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [Frees the vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_VecFree( Vec_Vec_t * p ) -{ - Vec_Ptr_t * vVec; - int i; - Vec_VecForEachLevel( p, vVec, i ) - Vec_PtrFree( vVec ); - Vec_PtrFree( (Vec_Ptr_t *)p ); -} - -/**Function************************************************************* - - Synopsis [Frees the vector of vectors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_VecSizeSize( Vec_Vec_t * p ) -{ - Vec_Ptr_t * vVec; - int i, Counter = 0; - Vec_VecForEachLevel( p, vVec, i ) - Counter += vVec->nSize; - return Counter; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_VecClear( Vec_Vec_t * p ) -{ - Vec_Ptr_t * vVec; - int i; - Vec_VecForEachLevel( p, vVec, i ) - Vec_PtrClear( vVec ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry ) -{ - if ( p->nSize < Level + 1 ) - { - int i; - Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 ); - for ( i = p->nSize; i < Level + 1; i++ ) - p->pArray[i] = Vec_PtrAlloc( 0 ); - p->nSize = Level + 1; - } - Vec_PtrPush( (Vec_Ptr_t*)p->pArray[Level], Entry ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_VecPushUnique( Vec_Vec_t * p, int Level, void * Entry ) -{ - if ( p->nSize < Level + 1 ) - Vec_VecPush( p, Level, Entry ); - else - Vec_PtrPushUnique( (Vec_Ptr_t*)p->pArray[Level], Entry ); -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two arrays.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_VecSortCompare1( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 ) -{ - if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) ) - return -1; - if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two integers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Vec_VecSortCompare2( Vec_Ptr_t ** pp1, Vec_Ptr_t ** pp2 ) -{ - if ( Vec_PtrSize(*pp1) > Vec_PtrSize(*pp2) ) - return -1; - if ( Vec_PtrSize(*pp1) < Vec_PtrSize(*pp2) ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Vec_VecSort( Vec_Vec_t * p, int fReverse ) -{ - if ( fReverse ) - qsort( (void *)p->pArray, p->nSize, sizeof(void *), - (int (*)(const void *, const void *)) Vec_VecSortCompare2 ); - else - qsort( (void *)p->pArray, p->nSize, sizeof(void *), - (int (*)(const void *, const void *)) Vec_VecSortCompare1 ); -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/cut/abcCut.c b/src/opt/cut/abcCut.c deleted file mode 100644 index 9bbd5790..00000000 --- a/src/opt/cut/abcCut.c +++ /dev/null @@ -1,492 +0,0 @@ -/**CFile**************************************************************** - - FileName [abcCut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Interface to cut computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: abcCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "cut.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ); -static void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ); - - -extern int nTotal, nGood, nEqual; - -// temporary -//Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) { return NULL; } -Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ) -{ - Vec_Int_t * vAttrs = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); - int i; - Abc_Obj_t * pObj; - -// Abc_NtkForEachCi( pNtk, pObj, i ) -// Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); - - Abc_NtkForEachObj( pNtk, pObj, i ) - { -// if ( Abc_ObjIsNode(pObj) && (rand() % 4 == 0) ) - if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj) && (rand() % 3 == 0) ) - Vec_IntWriteEntry( vAttrs, pObj->Id, 1 ); - } - return vAttrs; -} - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) -{ - ProgressBar * pProgress; - Cut_Man_t * p; - Abc_Obj_t * pObj, * pNode; - Vec_Ptr_t * vNodes; - Vec_Int_t * vChoices; - int i; - int clk = clock(); - - extern void Abc_NtkBalanceAttach( Abc_Ntk_t * pNtk ); - extern void Abc_NtkBalanceDetach( Abc_Ntk_t * pNtk ); - - nTotal = nGood = nEqual = 0; - - assert( Abc_NtkIsStrash(pNtk) ); - // start the manager - pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); - p = Cut_ManStart( pParams ); - // compute node attributes if local or global cuts are requested - if ( pParams->fGlobal || pParams->fLocal ) - { - extern Vec_Int_t * Abc_NtkGetNodeAttributes( Abc_Ntk_t * pNtk ); - Cut_ManSetNodeAttrs( p, Abc_NtkGetNodeAttributes(pNtk) ); - } - // prepare for cut dropping - if ( pParams->fDrop ) - Cut_ManSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); - // set cuts for PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) > 0 ) - Cut_NodeSetTriv( p, pObj->Id ); - // compute cuts for internal nodes - vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs - vChoices = Vec_IntAlloc( 100 ); - pProgress = Extra_ProgressBarStart( stdout, Vec_PtrSize(vNodes) ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - // when we reached a CO, it is time to deallocate the cuts - if ( Abc_ObjIsCo(pObj) ) - { - if ( pParams->fDrop ) - Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); - continue; - } - // skip constant node, it has no cuts -// if ( Abc_NodeIsConst(pObj) ) -// continue; - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // compute the cuts to the internal node - Abc_NodeGetCuts( p, pObj, pParams->fDag, pParams->fTree ); - // consider dropping the fanins cuts - if ( pParams->fDrop ) - { - Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); - Cut_NodeTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); - } - // add cuts due to choices - if ( Abc_AigNodeIsChoice(pObj) ) - { - Vec_IntClear( vChoices ); - for ( pNode = pObj; pNode; pNode = pNode->pData ) - Vec_IntPush( vChoices, pNode->Id ); - Cut_NodeUnionCuts( p, vChoices ); - } - } - Extra_ProgressBarStop( pProgress ); - Vec_PtrFree( vNodes ); - Vec_IntFree( vChoices ); -PRT( "Total", clock() - clk ); -//Abc_NtkPrintCuts( p, pNtk, 0 ); -// Cut_ManPrintStatsToFile( p, pNtk->pSpec, clock() - clk ); - - // temporary printout of stats - if ( nTotal ) - printf( "Total cuts = %d. Good cuts = %d. Ratio = %5.2f\n", nTotal, nGood, ((double)nGood)/nTotal ); - return p; -} - -/**Function************************************************************* - - Synopsis [Cut computation using the oracle.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p ) -{ - Abc_Obj_t * pObj; - Vec_Ptr_t * vNodes; - int i, clk = clock(); - int fDrop = Cut_OracleReadDrop(p); - - assert( Abc_NtkIsStrash(pNtk) ); - - // prepare cut droppping - if ( fDrop ) - Cut_OracleSetFanoutCounts( p, Abc_NtkFanoutCounts(pNtk) ); - - // set cuts for PIs - Abc_NtkForEachCi( pNtk, pObj, i ) - if ( Abc_ObjFanoutNum(pObj) > 0 ) - Cut_OracleNodeSetTriv( p, pObj->Id ); - - // compute cuts for internal nodes - vNodes = Abc_AigDfs( pNtk, 0, 1 ); // collects POs - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - // when we reached a CO, it is time to deallocate the cuts - if ( Abc_ObjIsCo(pObj) ) - { - if ( fDrop ) - Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); - continue; - } - // skip constant node, it has no cuts -// if ( Abc_NodeIsConst(pObj) ) -// continue; - // compute the cuts to the internal node - Cut_OracleComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), - Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); - // consider dropping the fanins cuts - if ( fDrop ) - { - Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId0(pObj) ); - Cut_OracleTryDroppingCuts( p, Abc_ObjFaninId1(pObj) ); - } - } - Vec_PtrFree( vNodes ); -//PRT( "Total", clock() - clk ); -//Abc_NtkPrintCuts_( p, pNtk, 0 ); -} - - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ) -{ -/* - Cut_Man_t * p; - Abc_Obj_t * pObj, * pNode; - int i, nIters, fStatus; - Vec_Int_t * vChoices; - int clk = clock(); - - assert( Abc_NtkIsSeq(pNtk) ); - assert( pParams->fSeq ); -// assert( Abc_NtkIsDfsOrdered(pNtk) ); - - // start the manager - pParams->nIdsMax = Abc_NtkObjNumMax( pNtk ); - pParams->nCutSet = Abc_NtkCutSetNodeNum( pNtk ); - p = Cut_ManStart( pParams ); - - // set cuts for the constant node and the PIs - pObj = Abc_AigConst1(pNtk); - if ( Abc_ObjFanoutNum(pObj) > 0 ) - Cut_NodeSetTriv( p, pObj->Id ); - Abc_NtkForEachPi( pNtk, pObj, i ) - { -//printf( "Setting trivial cut %d.\n", pObj->Id ); - Cut_NodeSetTriv( p, pObj->Id ); - } - // label the cutset nodes and set their number in the array - // assign the elementary cuts to the cutset nodes - Abc_SeqForEachCutsetNode( pNtk, pObj, i ) - { - assert( pObj->fMarkC == 0 ); - pObj->fMarkC = 1; - pObj->pCopy = (Abc_Obj_t *)i; - Cut_NodeSetTriv( p, pObj->Id ); -//printf( "Setting trivial cut %d.\n", pObj->Id ); - } - - // process the nodes - vChoices = Vec_IntAlloc( 100 ); - for ( nIters = 0; nIters < 10; nIters++ ) - { -//printf( "ITERATION %d:\n", nIters ); - // compute the cuts for the internal nodes - Abc_AigForEachAnd( pNtk, pObj, i ) - { - Abc_NodeGetCutsSeq( p, pObj, nIters==0 ); - // add cuts due to choices - if ( Abc_AigNodeIsChoice(pObj) ) - { - Vec_IntClear( vChoices ); - for ( pNode = pObj; pNode; pNode = pNode->pData ) - Vec_IntPush( vChoices, pNode->Id ); - Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 ); - } - } - // merge the new cuts with the old cuts - Abc_NtkForEachPi( pNtk, pObj, i ) - Cut_NodeNewMergeWithOld( p, pObj->Id ); - Abc_AigForEachAnd( pNtk, pObj, i ) - Cut_NodeNewMergeWithOld( p, pObj->Id ); - // for the cutset, transfer temp cuts to new cuts - fStatus = 0; - Abc_SeqForEachCutsetNode( pNtk, pObj, i ) - fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i ); - if ( fStatus == 0 ) - break; - } - Vec_IntFree( vChoices ); - - // if the status is not finished, transfer new to old for the cutset - Abc_SeqForEachCutsetNode( pNtk, pObj, i ) - Cut_NodeNewMergeWithOld( p, pObj->Id ); - - // transfer the old cuts to the new positions - Abc_NtkForEachObj( pNtk, pObj, i ) - Cut_NodeOldTransferToNew( p, pObj->Id ); - - // unlabel the cutset nodes - Abc_SeqForEachCutsetNode( pNtk, pObj, i ) - pObj->fMarkC = 0; -if ( pParams->fVerbose ) -{ -PRT( "Total", clock() - clk ); -printf( "Converged after %d iterations.\n", nIters ); -} -//Abc_NtkPrintCuts( p, pNtk, 1 ); - return p; -*/ -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) -{ - void * pList; - if ( pList = Abc_NodeReadCuts( p, pObj ) ) - return pList; - Abc_NodeGetCutsRecursive( p, Abc_ObjFanin0(pObj), fDag, fTree ); - Abc_NodeGetCutsRecursive( p, Abc_ObjFanin1(pObj), fDag, fTree ); - return Abc_NodeGetCuts( p, pObj, fDag, fTree ); -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ) -{ - Abc_Obj_t * pFanin; - int fDagNode, fTriv, TreeCode = 0; -// assert( Abc_NtkIsStrash(pObj->pNtk) ); - assert( Abc_ObjFaninNum(pObj) == 2 ); - - - // check if the node is a DAG node - fDagNode = (Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsMuxControlType(pObj)); - // increment the counter of DAG nodes - if ( fDagNode ) Cut_ManIncrementDagNodes( p ); - // add the trivial cut if the node is a DAG node, or if we compute all cuts - fTriv = fDagNode || !fDag; - // check if fanins are DAG nodes - if ( fTree ) - { - pFanin = Abc_ObjFanin0(pObj); - TreeCode |= (Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)); - pFanin = Abc_ObjFanin1(pObj); - TreeCode |= ((Abc_ObjFanoutNum(pFanin) > 1 && !Abc_NodeIsMuxControlType(pFanin)) << 1); - } - - - // changes due to the global/local cut computation - { - Cut_Params_t * pParams = Cut_ManReadParams(p); - if ( pParams->fLocal ) - { - Vec_Int_t * vNodeAttrs = Cut_ManReadNodeAttrs(p); - fDagNode = Vec_IntEntry( vNodeAttrs, pObj->Id ); - if ( fDagNode ) Cut_ManIncrementDagNodes( p ); -// fTriv = fDagNode || !pParams->fGlobal; - fTriv = !Vec_IntEntry( vNodeAttrs, pObj->Id ); - TreeCode = 0; - pFanin = Abc_ObjFanin0(pObj); - TreeCode |= Vec_IntEntry( vNodeAttrs, pFanin->Id ); - pFanin = Abc_ObjFanin1(pObj); - TreeCode |= (Vec_IntEntry( vNodeAttrs, pFanin->Id ) << 1); - } - } - return Cut_NodeComputeCuts( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), - Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), fTriv, TreeCode ); -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fTriv ) -{ - int CutSetNum; - assert( Abc_NtkIsSeq(pObj->pNtk) ); - assert( Abc_ObjFaninNum(pObj) == 2 ); - fTriv = pObj->fMarkC ? 0 : fTriv; - CutSetNum = pObj->fMarkC ? (int)pObj->pCopy : -1; - Cut_NodeComputeCutsSeq( p, pObj->Id, Abc_ObjFaninId0(pObj), Abc_ObjFaninId1(pObj), - Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj), Seq_ObjFaninL0(pObj), Seq_ObjFaninL1(pObj), fTriv, CutSetNum ); -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ) -{ - return Cut_NodeReadCutsNew( p, pObj->Id ); -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ) -{ - Cut_NodeFreeCuts( p, pObj->Id ); -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintCuts( void * p, Abc_Ntk_t * pNtk, int fSeq ) -{ - Cut_Man_t * pMan = p; - Cut_Cut_t * pList; - Abc_Obj_t * pObj; - int i; - printf( "Cuts of the network:\n" ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - pList = Abc_NodeReadCuts( p, pObj ); - printf( "Node %s:\n", Abc_ObjName(pObj) ); - Cut_CutPrintList( pList, fSeq ); - } -} - -/**Function************************************************************* - - Synopsis [Computes the cuts for the network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkPrintCuts_( void * p, Abc_Ntk_t * pNtk, int fSeq ) -{ - Cut_Man_t * pMan = p; - Cut_Cut_t * pList; - Abc_Obj_t * pObj; - pObj = Abc_NtkObj( pNtk, 2 * Abc_NtkObjNum(pNtk) / 3 ); - pList = Abc_NodeReadCuts( p, pObj ); - printf( "Node %s:\n", Abc_ObjName(pObj) ); - Cut_CutPrintList( pList, fSeq ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/cut/cut.h b/src/opt/cut/cut.h deleted file mode 100644 index dee05dfc..00000000 --- a/src/opt/cut/cut.h +++ /dev/null @@ -1,165 +0,0 @@ -/**CFile**************************************************************** - - FileName [cut.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [K-feasible cut computation package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: .h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CUT_H__ -#define __CUT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -#define CUT_SIZE_MIN 3 // the min K of the K-feasible cut computation -#define CUT_SIZE_MAX 12 // the max K of the K-feasible cut computation - -#define CUT_SHIFT 8 // the number of bits for storing latch number in the cut leaves -#define CUT_MASK 0xFF // the mask to get the stored latch number - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Cut_ManStruct_t_ Cut_Man_t; -typedef struct Cut_OracleStruct_t_ Cut_Oracle_t; -typedef struct Cut_CutStruct_t_ Cut_Cut_t; -typedef struct Cut_ParamsStruct_t_ Cut_Params_t; - -struct Cut_ParamsStruct_t_ -{ - int nVarsMax; // the max cut size ("k" of the k-feasible cuts) - int nKeepMax; // the max number of cuts kept at a node - int nIdsMax; // the max number of IDs of cut objects - int nBitShift; // the number of bits used for the latch counter of an edge - int nCutSet; // the number of nodes in the cut set - int fTruth; // compute truth tables - int fFilter; // filter dominated cuts - int fSeq; // compute sequential cuts - int fDrop; // drop cuts on the fly - int fDag; // compute only DAG cuts - int fTree; // compute only tree cuts - int fGlobal; // compute only global cuts - int fLocal; // compute only local cuts - int fRecord; // record the cut computation flow - int fFancy; // perform fancy computations - int fMap; // computes delay of FPGA mapping with cuts - int fVerbose; // the verbosiness flag -}; - -struct Cut_CutStruct_t_ -{ - unsigned Num0 : 11; // temporary number - unsigned Num1 : 11; // temporary number - unsigned fSimul : 1; // the value of cut's output at 000.. pattern - unsigned fCompl : 1; // the cut is complemented - unsigned nVarsMax : 4; // the max number of vars [4-6] - unsigned nLeaves : 4; // the number of leaves [4-6] - unsigned uSign; // the signature - unsigned uCanon0; // the canonical form - unsigned uCanon1; // the canonical form - Cut_Cut_t * pNext; // the next cut in the list - int pLeaves[0]; // the array of leaves -}; - -static inline int Cut_CutReadLeaveNum( Cut_Cut_t * p ) { return p->nLeaves; } -static inline int * Cut_CutReadLeaves( Cut_Cut_t * p ) { return p->pLeaves; } -static inline unsigned * Cut_CutReadTruth( Cut_Cut_t * p ) { return (unsigned *)(p->pLeaves + p->nVarsMax); } -static inline void Cut_CutWriteTruth( Cut_Cut_t * p, unsigned * puTruth ) { - int i; - for ( i = (p->nVarsMax <= 5) ? 0 : ((1 << (p->nVarsMax - 5)) - 1); i >= 0; i-- ) - p->pLeaves[p->nVarsMax + i] = (int)puTruth[i]; -} - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== cutApi.c ==========================================================*/ -extern Cut_Cut_t * Cut_NodeReadCutsNew( Cut_Man_t * p, int Node ); -extern Cut_Cut_t * Cut_NodeReadCutsOld( Cut_Man_t * p, int Node ); -extern Cut_Cut_t * Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node ); -extern void Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList ); -extern void Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList ); -extern void Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList ); -extern void Cut_NodeSetTriv( Cut_Man_t * p, int Node ); -extern void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node ); -extern void Cut_NodeFreeCuts( Cut_Man_t * p, int Node ); -/*=== cutCut.c ==========================================================*/ -extern void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq ); -extern void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq ); -extern int Cut_CutCountList( Cut_Cut_t * pList ); -/*=== cutMan.c ==========================================================*/ -extern Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams ); -extern void Cut_ManStop( Cut_Man_t * p ); -extern void Cut_ManPrintStats( Cut_Man_t * p ); -extern void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, int TimeTotal ); -extern void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts ); -extern void Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vFanCounts ); -extern int Cut_ManReadVarsMax( Cut_Man_t * p ); -extern Cut_Params_t * Cut_ManReadParams( Cut_Man_t * p ); -extern Vec_Int_t * Cut_ManReadNodeAttrs( Cut_Man_t * p ); -extern void Cut_ManIncrementDagNodes( Cut_Man_t * p ); -/*=== cutNode.c ==========================================================*/ -extern Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode ); -extern Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ); -extern Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst ); -extern int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node ); -/*=== cutSeq.c ==========================================================*/ -extern void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum ); -extern void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node ); -extern int Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum ); -extern void Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node ); -/*=== cutOracle.c ==========================================================*/ -extern Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan ); -extern void Cut_OracleStop( Cut_Oracle_t * p ); -extern void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts ); -extern int Cut_OracleReadDrop( Cut_Oracle_t * p ); -extern void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node ); -extern Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 ); -extern void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node ); -/*=== cutTruth.c ==========================================================*/ -extern void Cut_TruthNCanonicize( Cut_Cut_t * pCut ); -/*=== cutPre22.c ==========================================================*/ -extern void Cut_CellPrecompute(); -extern void Cut_CellLoad(); -extern int Cut_CellIsRunning(); -extern void Cut_CellDumpToFile(); -extern int Cut_CellTruthLookup( unsigned * pTruth, int nVars ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/cut/cutApi.c b/src/opt/cut/cutApi.c deleted file mode 100644 index 980c6b12..00000000 --- a/src/opt/cut/cutApi.c +++ /dev/null @@ -1,197 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutNode.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [K-feasible cut computation package.] - - Synopsis [Procedures to compute cuts for a node.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cutInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns the pointer to the linked list of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_NodeReadCutsNew( Cut_Man_t * p, int Node ) -{ - if ( Node >= p->vCutsNew->nSize ) - return NULL; - return Vec_PtrEntry( p->vCutsNew, Node ); -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the linked list of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_NodeReadCutsOld( Cut_Man_t * p, int Node ) -{ - assert( Node < p->vCutsOld->nSize ); - return Vec_PtrEntry( p->vCutsOld, Node ); -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the linked list of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_NodeReadCutsTemp( Cut_Man_t * p, int Node ) -{ - assert( Node < p->vCutsTemp->nSize ); - return Vec_PtrEntry( p->vCutsTemp, Node ); -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the linked list of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_NodeWriteCutsNew( Cut_Man_t * p, int Node, Cut_Cut_t * pList ) -{ - Vec_PtrWriteEntry( p->vCutsNew, Node, pList ); -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the linked list of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_NodeWriteCutsOld( Cut_Man_t * p, int Node, Cut_Cut_t * pList ) -{ - Vec_PtrWriteEntry( p->vCutsOld, Node, pList ); -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the linked list of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_NodeWriteCutsTemp( Cut_Man_t * p, int Node, Cut_Cut_t * pList ) -{ - Vec_PtrWriteEntry( p->vCutsTemp, Node, pList ); -} - -/**Function************************************************************* - - Synopsis [Sets the trivial cut for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_NodeSetTriv( Cut_Man_t * p, int Node ) -{ - assert( Cut_NodeReadCutsNew(p, Node) == NULL ); - Cut_NodeWriteCutsNew( p, Node, Cut_CutCreateTriv(p, Node) ); -} - -/**Function************************************************************* - - Synopsis [Consider dropping cuts if they are useless by now.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_NodeTryDroppingCuts( Cut_Man_t * p, int Node ) -{ - int nFanouts; - assert( p->vFanCounts ); - nFanouts = Vec_IntEntry( p->vFanCounts, Node ); - assert( nFanouts > 0 ); - if ( --nFanouts == 0 ) - Cut_NodeFreeCuts( p, Node ); - Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts ); -} - -/**Function************************************************************* - - Synopsis [Deallocates the cuts at the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_NodeFreeCuts( Cut_Man_t * p, int Node ) -{ - Cut_Cut_t * pList, * pCut, * pCut2; - pList = Cut_NodeReadCutsNew( p, Node ); - if ( pList == NULL ) - return; - Cut_ListForEachCutSafe( pList, pCut, pCut2 ) - Cut_CutRecycle( p, pCut ); - Cut_NodeWriteCutsNew( p, Node, NULL ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/cut/cutCut.c b/src/opt/cut/cutCut.c deleted file mode 100644 index 94147278..00000000 --- a/src/opt/cut/cutCut.c +++ /dev/null @@ -1,359 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutNode.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [K-feasible cut computation package.] - - Synopsis [Procedures to compute cuts for a node.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cutInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p ) -{ - Cut_Cut_t * pCut; - // cut allocation - pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts ); - memset( pCut, 0, sizeof(Cut_Cut_t) ); - pCut->nVarsMax = p->pParams->nVarsMax; - pCut->fSimul = p->fSimul; - // statistics - p->nCutsAlloc++; - p->nCutsCur++; - if ( p->nCutsPeak < p->nCutsAlloc - p->nCutsDealloc ) - p->nCutsPeak = p->nCutsAlloc - p->nCutsDealloc; - return pCut; -} - -/**Function************************************************************* - - Synopsis [Recybles the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut ) -{ - p->nCutsDealloc++; - p->nCutsCur--; - if ( pCut->nLeaves == 1 ) - p->nCutsTriv--; - Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut ); -} - -/**Function************************************************************* - - Synopsis [Compares two cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 ) -{ - int i; - if ( pCut1->nLeaves < pCut2->nLeaves ) - return -1; - if ( pCut1->nLeaves > pCut2->nLeaves ) - return 1; - for ( i = 0; i < (int)pCut1->nLeaves; i++ ) - { - if ( pCut1->pLeaves[i] < pCut2->pLeaves[i] ) - return -1; - if ( pCut1->pLeaves[i] > pCut2->pLeaves[i] ) - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Duplicates the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList ) -{ - Cut_Cut_t * pHead = NULL, ** ppTail = &pHead; - Cut_Cut_t * pTemp, * pCopy; - if ( pList == NULL ) - return NULL; - Cut_ListForEachCut( pList, pTemp ) - { - pCopy = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts ); - memcpy( pCopy, pTemp, p->EntrySize ); - *ppTail = pCopy; - ppTail = &pCopy->pNext; - } - *ppTail = NULL; - return pHead; -} - -/**Function************************************************************* - - Synopsis [Recycles the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList ) -{ - Cut_Cut_t * pCut, * pCut2; - Cut_ListForEachCutSafe( pList, pCut, pCut2 ) - Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of cuts in the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_CutCountList( Cut_Cut_t * pList ) -{ - int Counter = 0; - Cut_ListForEachCut( pList, pList ) - Counter++; - return Counter; -} - -/**Function************************************************************* - - Synopsis [Merges two NULL-terminated linked lists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 ) -{ - Cut_Cut_t * pList = NULL, ** ppTail = &pList; - Cut_Cut_t * pCut; - while ( pList1 && pList2 ) - { - if ( Cut_CutCompare(pList1, pList2) < 0 ) - { - pCut = pList1; - pList1 = pList1->pNext; - } - else - { - pCut = pList2; - pList2 = pList2->pNext; - } - *ppTail = pCut; - ppTail = &pCut->pNext; - } - *ppTail = pList1? pList1: pList2; - return pList; -} - -/**Function************************************************************* - - Synopsis [Sets the number of the cuts in the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CutNumberList( Cut_Cut_t * pList ) -{ - Cut_Cut_t * pCut; - int i = 0; - Cut_ListForEachCut( pList, pCut ) - pCut->Num0 = i++; -} - -/**Function************************************************************* - - Synopsis [Creates the trivial cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node ) -{ - Cut_Cut_t * pCut; - if ( p->pParams->fSeq ) - Node <<= CUT_SHIFT; - pCut = Cut_CutAlloc( p ); - pCut->nLeaves = 1; - pCut->pLeaves[0] = Node; - pCut->uSign = Cut_NodeSign( Node ); - if ( p->pParams->fTruth ) - { -/* - if ( pCut->nVarsMax == 4 ) - Cut_CutWriteTruth( pCut, p->uTruthVars[0] ); - else - Extra_BitCopy( pCut->nLeaves, p->uTruths[0], (uint8*)Cut_CutReadTruth(pCut) ); -*/ - unsigned * pTruth = Cut_CutReadTruth(pCut); - int i; - for ( i = 0; i < p->nTruthWords; i++ ) - pTruth[i] = 0xAAAAAAAA; - } - p->nCutsTriv++; - return pCut; -} - - -/**Function************************************************************* - - Synopsis [Print the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CutPrint( Cut_Cut_t * pCut, int fSeq ) -{ - int i; - assert( pCut->nLeaves > 0 ); - printf( "%d : {", pCut->nLeaves ); - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - { - if ( fSeq ) - { - printf( " %d", pCut->pLeaves[i] >> CUT_SHIFT ); - if ( pCut->pLeaves[i] & CUT_MASK ) - printf( "(%d)", pCut->pLeaves[i] & CUT_MASK ); - } - else - printf( " %d", pCut->pLeaves[i] ); - } - printf( " }" ); -// printf( "\nSign = " ); -// Extra_PrintBinary( stdout, &pCut->uSign, 32 ); -} - -/**Function************************************************************* - - Synopsis [Print the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CutPrintList( Cut_Cut_t * pList, int fSeq ) -{ - Cut_Cut_t * pCut; - for ( pCut = pList; pCut; pCut = pCut->pNext ) - Cut_CutPrint( pCut, fSeq ), printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Consider dropping cuts if they are useless by now.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) -{ - printf( "\n" ); - printf( "%d : %5d %5d %5d %5d %5d\n", - pCut0->nLeaves, - pCut0->nLeaves > 0 ? pCut0->pLeaves[0] : -1, - pCut0->nLeaves > 1 ? pCut0->pLeaves[1] : -1, - pCut0->nLeaves > 2 ? pCut0->pLeaves[2] : -1, - pCut0->nLeaves > 3 ? pCut0->pLeaves[3] : -1, - pCut0->nLeaves > 4 ? pCut0->pLeaves[4] : -1 - ); - printf( "%d : %5d %5d %5d %5d %5d\n", - pCut1->nLeaves, - pCut1->nLeaves > 0 ? pCut1->pLeaves[0] : -1, - pCut1->nLeaves > 1 ? pCut1->pLeaves[1] : -1, - pCut1->nLeaves > 2 ? pCut1->pLeaves[2] : -1, - pCut1->nLeaves > 3 ? pCut1->pLeaves[3] : -1, - pCut1->nLeaves > 4 ? pCut1->pLeaves[4] : -1 - ); - if ( pCut == NULL ) - printf( "Cannot merge\n" ); - else - printf( "%d : %5d %5d %5d %5d %5d\n", - pCut->nLeaves, - pCut->nLeaves > 0 ? pCut->pLeaves[0] : -1, - pCut->nLeaves > 1 ? pCut->pLeaves[1] : -1, - pCut->nLeaves > 2 ? pCut->pLeaves[2] : -1, - pCut->nLeaves > 3 ? pCut->pLeaves[3] : -1, - pCut->nLeaves > 4 ? pCut->pLeaves[4] : -1 - ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/cut/cutExpand.c b/src/opt/cut/cutExpand.c deleted file mode 100644 index d389ef7a..00000000 --- a/src/opt/cut/cutExpand.c +++ /dev/null @@ -1,184 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutExpand.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [K-feasible cut computation package.] - - Synopsis [Computes the truth table of the cut after expansion.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutExpand.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cutInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define CUT_CELL_MVAR 9 - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 ) -{ - unsigned uPhase = 0; - int i, k; - for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) - { - if ( k == (int)pCut1->nLeaves ) - break; - if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) - continue; - assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); - uPhase |= (1 << i); - k++; - } - return uPhase; -} - -/**Function************************************************************* - - Synopsis [Computes the truth table of the composition of cuts.] - - Description [Inputs are: - - a factor cut (truth table is stored inside) - - a node in the factor cut - - a tree cut to be substituted (truth table is stored inside) - - the resulting cut (truth table will be filled in). - Note that all cuts, including the resulting one, should be already - computed and the nodes should be stored in the ascending order.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_TruthCompose( Cut_Cut_t * pCutF, int Node, Cut_Cut_t * pCutT, Cut_Cut_t * pCutRes ) -{ - static unsigned uCof0[1<<(CUT_CELL_MVAR-5)]; - static unsigned uCof1[1<<(CUT_CELL_MVAR-5)]; - static unsigned uTemp[1<<(CUT_CELL_MVAR-5)]; - unsigned * pIn, * pOut, * pTemp; - unsigned uPhase; - int NodeIndex, i, k; - - // sanity checks - assert( pCutF->nVarsMax == pCutT->nVarsMax ); - assert( pCutF->nVarsMax == pCutRes->nVarsMax ); - assert( pCutF->nVarsMax <= CUT_CELL_MVAR ); - // the factor cut (pCutF) should have its nodes sorted in the ascending order - assert( pCutF->nLeaves <= pCutF->nVarsMax ); - for ( i = 0; i < (int)pCutF->nLeaves - 1; i++ ) - assert( pCutF->pLeaves[i] < pCutF->pLeaves[i+1] ); - // the tree cut (pCutT) should have its nodes sorted in the ascending order - assert( pCutT->nLeaves <= pCutT->nVarsMax ); - for ( i = 0; i < (int)pCutT->nLeaves - 1; i++ ) - assert( pCutT->pLeaves[i] < pCutT->pLeaves[i+1] ); - // the resulting cut (pCutRes) should have its nodes sorted in the ascending order - assert( pCutRes->nLeaves <= pCutRes->nVarsMax ); - for ( i = 0; i < (int)pCutRes->nLeaves - 1; i++ ) - assert( pCutRes->pLeaves[i] < pCutRes->pLeaves[i+1] ); - // make sure that every node in pCutF (except Node) appears in pCutRes - for ( i = 0; i < (int)pCutF->nLeaves; i++ ) - { - if ( pCutF->pLeaves[i] == Node ) - continue; - for ( k = 0; k < (int)pCutRes->nLeaves; k++ ) - if ( pCutF->pLeaves[i] == pCutRes->pLeaves[k] ) - break; - assert( k < (int)pCutRes->nLeaves ); // node i from pCutF is not found in pCutRes!!! - } - // make sure that every node in pCutT appears in pCutRes - for ( i = 0; i < (int)pCutT->nLeaves; i++ ) - { - for ( k = 0; k < (int)pCutRes->nLeaves; k++ ) - if ( pCutT->pLeaves[i] == pCutRes->pLeaves[k] ) - break; - assert( k < (int)pCutRes->nLeaves ); // node i from pCutT is not found in pCutRes!!! - } - - - // find the index of the given node in the factor cut - NodeIndex = -1; - for ( NodeIndex = 0; NodeIndex < (int)pCutF->nLeaves; NodeIndex++ ) - if ( pCutF->pLeaves[NodeIndex] == Node ) - break; - assert( NodeIndex >= 0 ); // Node should be in pCutF - - // copy the truth table - Extra_TruthCopy( uTemp, Cut_CutReadTruth(pCutF), pCutF->nLeaves ); - - // bubble-move the NodeIndex variable to be the last one (the most significant one) - pIn = uTemp; pOut = uCof0; // uCof0 is used for temporary storage here - for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ ) - { - Extra_TruthSwapAdjacentVars( pOut, pIn, pCutF->nLeaves, i ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - } - if ( (pCutF->nLeaves - 1 - NodeIndex) & 1 ) - Extra_TruthCopy( pOut, pIn, pCutF->nLeaves ); - // the result of stretching is in uTemp - - // cofactor the factor cut with respect to the node - Extra_TruthCopy( uCof0, uTemp, pCutF->nLeaves ); - Extra_TruthCofactor0( uCof0, pCutF->nLeaves, pCutF->nLeaves-1 ); - Extra_TruthCopy( uCof1, uTemp, pCutF->nLeaves ); - Extra_TruthCofactor1( uCof1, pCutF->nLeaves, pCutF->nLeaves-1 ); - - // temporarily shrink the factor cut's variables by removing Node - for ( i = NodeIndex; i < (int)pCutF->nLeaves - 1; i++ ) - pCutF->pLeaves[i] = pCutF->pLeaves[i+1]; - pCutF->nLeaves--; - - // spread out the cofactors' truth tables to the same var order as the resulting cut - uPhase = Cut_TruthPhase(pCutRes, pCutF); - assert( Extra_WordCountOnes(uPhase) == (int)pCutF->nLeaves ); - Extra_TruthStretch( uTemp, uCof0, pCutF->nLeaves, pCutF->nVarsMax, uPhase ); - Extra_TruthCopy( uCof0, uTemp, pCutF->nVarsMax ); - Extra_TruthStretch( uTemp, uCof1, pCutF->nLeaves, pCutF->nVarsMax, uPhase ); - Extra_TruthCopy( uCof1, uTemp, pCutF->nVarsMax ); - - // spread out the tree cut's truth table to the same var order as the resulting cut - uPhase = Cut_TruthPhase(pCutRes, pCutT); - assert( Extra_WordCountOnes(uPhase) == (int)pCutT->nLeaves ); - Extra_TruthStretch( uTemp, Cut_CutReadTruth(pCutT), pCutT->nLeaves, pCutT->nVarsMax, uPhase ); - - // create the resulting truth table - pTemp = Cut_CutReadTruth(pCutRes); - for ( i = Extra_TruthWordNum(pCutRes->nLeaves)-1; i >= 0; i-- ) - pTemp[i] = (uCof0[i] & ~uTemp[i]) | (uCof1[i] & uTemp[i]); - - // undo the removal of the node from the cut - for ( i = (int)pCutF->nLeaves - 1; i >= NodeIndex; --i ) - pCutF->pLeaves[i+1] = pCutF->pLeaves[i]; - pCutF->pLeaves[NodeIndex] = Node; - pCutF->nLeaves++; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/cut/cutInt.h b/src/opt/cut/cutInt.h deleted file mode 100644 index 17f268c7..00000000 --- a/src/opt/cut/cutInt.h +++ /dev/null @@ -1,157 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [K-feasible cut computation package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CUT_INT_H__ -#define __CUT_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include -#include "extra.h" -#include "vec.h" -#include "cut.h" -#include "cutList.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Cut_HashTableStruct_t_ Cut_HashTable_t; - -struct Cut_ManStruct_t_ -{ - // user preferences - Cut_Params_t * pParams; // computation parameters - Vec_Int_t * vFanCounts; // the array of fanout counters - Vec_Int_t * vNodeAttrs; // node attributes (1 = global; 0 = local) - // storage for cuts - Vec_Ptr_t * vCutsNew; // new cuts by node ID - Vec_Ptr_t * vCutsOld; // old cuts by node ID - Vec_Ptr_t * vCutsTemp; // temp cuts for cutset nodes by cutset node number - // memory management - Extra_MmFixed_t * pMmCuts; - int EntrySize; - int nTruthWords; - // temporary variables - Cut_Cut_t * pReady; - Vec_Ptr_t * vTemp; - int fCompl0; - int fCompl1; - int fSimul; - int nNodeCuts; - Cut_Cut_t * pStore0[2]; - Cut_Cut_t * pStore1[2]; - Cut_Cut_t * pCompareOld; - Cut_Cut_t * pCompareNew; - unsigned * puTemp[4]; - // record of the cut computation - Vec_Int_t * vNodeCuts; // the number of cuts for each node - Vec_Int_t * vNodeStarts; // the number of the starting cut of each node - Vec_Int_t * vCutPairs; // the pairs of parent cuts for each cut - // minimum delay mapping with the given cuts - Vec_Ptr_t * vCutsMax; - Vec_Int_t * vDelays; - Vec_Int_t * vDelays2; - int nDelayMin; - // statistics - int nCutsCur; - int nCutsAlloc; - int nCutsDealloc; - int nCutsPeak; - int nCutsTriv; - int nCutsFilter; - int nCutsLimit; - int nNodes; - int nNodesDag; - int nNodesNoCuts; - // runtime - int timeMerge; - int timeUnion; - int timeTruth; - int timeFilter; - int timeHash; - int timeMap; -}; - -// iterator through all the cuts of the list -#define Cut_ListForEachCut( pList, pCut ) \ - for ( pCut = pList; \ - pCut; \ - pCut = pCut->pNext ) -#define Cut_ListForEachCutStop( pList, pCut, pStop ) \ - for ( pCut = pList; \ - pCut != pStop; \ - pCut = pCut->pNext ) -#define Cut_ListForEachCutSafe( pList, pCut, pCut2 ) \ - for ( pCut = pList, \ - pCut2 = pCut? pCut->pNext: NULL; \ - pCut; \ - pCut = pCut2, \ - pCut2 = pCut? pCut->pNext: NULL ) - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// computes signature of the node -static inline unsigned Cut_NodeSign( int Node ) { return (1 << (Node % 31)); } -static inline int Cut_TruthWords( int nVarsMax ) { return nVarsMax <= 5 ? 1 : (1 << (nVarsMax - 5)); } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== cutCut.c ==========================================================*/ -extern Cut_Cut_t * Cut_CutAlloc( Cut_Man_t * p ); -extern void Cut_CutRecycle( Cut_Man_t * p, Cut_Cut_t * pCut ); -extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 ); -extern Cut_Cut_t * Cut_CutDupList( Cut_Man_t * p, Cut_Cut_t * pList ); -extern void Cut_CutRecycleList( Cut_Man_t * p, Cut_Cut_t * pList ); -extern Cut_Cut_t * Cut_CutMergeLists( Cut_Cut_t * pList1, Cut_Cut_t * pList2 ); -extern void Cut_CutNumberList( Cut_Cut_t * pList ); -extern Cut_Cut_t * Cut_CutCreateTriv( Cut_Man_t * p, int Node ); -extern void Cut_CutPrintMerge( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); -/*=== cutMerge.c ==========================================================*/ -extern Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); -/*=== cutNode.c ==========================================================*/ -extern void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode ); -extern int Cut_CutListVerify( Cut_Cut_t * pList ); -/*=== cutTable.c ==========================================================*/ -extern Cut_HashTable_t * Cut_TableStart( int Size ); -extern void Cut_TableStop( Cut_HashTable_t * pTable ); -extern int Cut_TableLookup( Cut_HashTable_t * pTable, Cut_Cut_t * pCut, int fStore ); -extern void Cut_TableClear( Cut_HashTable_t * pTable ); -extern int Cut_TableReadTime( Cut_HashTable_t * pTable ); -/*=== cutTruth.c ==========================================================*/ -extern void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ); -extern void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/cut/cutList.h b/src/opt/cut/cutList.h deleted file mode 100644 index a03ec9d5..00000000 --- a/src/opt/cut/cutList.h +++ /dev/null @@ -1,207 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutList.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Implementation of layered listed list of cuts.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutList.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __CUT_LIST_H__ -#define __CUT_LIST_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Cut_ListStruct_t_ Cut_List_t; -struct Cut_ListStruct_t_ -{ - Cut_Cut_t * pHead[CUT_SIZE_MAX+1]; - Cut_Cut_t ** ppTail[CUT_SIZE_MAX+1]; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start the cut list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Cut_ListStart( Cut_List_t * p ) -{ - int i; - for ( i = 1; i <= CUT_SIZE_MAX; i++ ) - { - p->pHead[i] = 0; - p->ppTail[i] = &p->pHead[i]; - } -} - -/**Function************************************************************* - - Synopsis [Adds one cut to the cut list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Cut_ListAdd( Cut_List_t * p, Cut_Cut_t * pCut ) -{ - assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX ); - *p->ppTail[pCut->nLeaves] = pCut; - p->ppTail[pCut->nLeaves] = &pCut->pNext; -} - -/**Function************************************************************* - - Synopsis [Adds one cut to the cut list while preserving order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Cut_ListAdd2( Cut_List_t * p, Cut_Cut_t * pCut ) -{ - extern int Cut_CutCompare( Cut_Cut_t * pCut1, Cut_Cut_t * pCut2 ); - Cut_Cut_t * pTemp, ** ppSpot; - assert( pCut->nLeaves > 0 && pCut->nLeaves <= CUT_SIZE_MAX ); - if ( p->pHead[pCut->nLeaves] != NULL ) - { - ppSpot = &p->pHead[pCut->nLeaves]; - for ( pTemp = p->pHead[pCut->nLeaves]; pTemp; pTemp = pTemp->pNext ) - { - if ( Cut_CutCompare(pCut, pTemp) < 0 ) - { - *ppSpot = pCut; - pCut->pNext = pTemp; - return; - } - else - ppSpot = &pTemp->pNext; - } - } - *p->ppTail[pCut->nLeaves] = pCut; - p->ppTail[pCut->nLeaves] = &pCut->pNext; -} - -/**Function************************************************************* - - Synopsis [Derive the super list from the linked list of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Cut_ListDerive( Cut_List_t * p, Cut_Cut_t * pList ) -{ - Cut_Cut_t * pPrev; - int nLeaves; - Cut_ListStart( p ); - while ( pList != NULL ) - { - nLeaves = pList->nLeaves; - p->pHead[nLeaves] = pList; - for ( pPrev = pList, pList = pList->pNext; pList; pPrev = pList, pList = pList->pNext ) - if ( nLeaves < (int)pList->nLeaves ) - break; - p->ppTail[nLeaves] = &pPrev->pNext; - pPrev->pNext = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Adds the second list to the first list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Cut_ListAddList( Cut_List_t * pOld, Cut_List_t * pNew ) -{ - int i; - for ( i = 1; i <= CUT_SIZE_MAX; i++ ) - { - if ( pNew->pHead[i] == NULL ) - continue; - *pOld->ppTail[i] = pNew->pHead[i]; - pOld->ppTail[i] = pNew->ppTail[i]; - } -} - -/**Function************************************************************* - - Synopsis [Returns the cut list linked into one sequence of cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Cut_Cut_t * Cut_ListFinish( Cut_List_t * p ) -{ - Cut_Cut_t * pHead = NULL, ** ppTail = &pHead; - int i; - for ( i = 1; i <= CUT_SIZE_MAX; i++ ) - { - if ( p->pHead[i] == NULL ) - continue; - *ppTail = p->pHead[i]; - ppTail = p->ppTail[i]; - } - *ppTail = NULL; - return pHead; -} - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/cut/cutMan.c b/src/opt/cut/cutMan.c deleted file mode 100644 index 8593ef93..00000000 --- a/src/opt/cut/cutMan.c +++ /dev/null @@ -1,326 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [K-feasible cut computation package.] - - Synopsis [Cut manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cutInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern void Npn_StartTruth8( uint8 uTruths[][32] ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the cut manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Man_t * Cut_ManStart( Cut_Params_t * pParams ) -{ - Cut_Man_t * p; - int clk = clock(); -// extern int nTruthDsd; -// nTruthDsd = 0; - assert( pParams->nVarsMax >= 3 && pParams->nVarsMax <= CUT_SIZE_MAX ); - p = ALLOC( Cut_Man_t, 1 ); - memset( p, 0, sizeof(Cut_Man_t) ); - // set and correct parameters - p->pParams = pParams; - // prepare storage for cuts - p->vCutsNew = Vec_PtrAlloc( pParams->nIdsMax ); - Vec_PtrFill( p->vCutsNew, pParams->nIdsMax, NULL ); - // prepare storage for sequential cuts - if ( pParams->fSeq ) - { - p->pParams->fFilter = 1; - p->vCutsOld = Vec_PtrAlloc( pParams->nIdsMax ); - Vec_PtrFill( p->vCutsOld, pParams->nIdsMax, NULL ); - p->vCutsTemp = Vec_PtrAlloc( pParams->nCutSet ); - Vec_PtrFill( p->vCutsTemp, pParams->nCutSet, NULL ); - if ( pParams->fTruth && pParams->nVarsMax > 5 ) - { - pParams->fTruth = 0; - printf( "Skipping computation of truth tables for sequential cuts with more than 5 inputs.\n" ); - } - } - // entry size - p->EntrySize = sizeof(Cut_Cut_t) + pParams->nVarsMax * sizeof(int); - if ( pParams->fTruth ) - { - if ( pParams->nVarsMax > 14 ) - { - pParams->fTruth = 0; - printf( "Skipping computation of truth table for more than %d inputs.\n", 14 ); - } - else - { - p->nTruthWords = Cut_TruthWords( pParams->nVarsMax ); - p->EntrySize += p->nTruthWords * sizeof(unsigned); - } - p->puTemp[0] = ALLOC( unsigned, 4 * p->nTruthWords ); - p->puTemp[1] = p->puTemp[0] + p->nTruthWords; - p->puTemp[2] = p->puTemp[1] + p->nTruthWords; - p->puTemp[3] = p->puTemp[2] + p->nTruthWords; - } - // enable cut computation recording - if ( pParams->fRecord ) - { - p->vNodeCuts = Vec_IntStart( pParams->nIdsMax ); - p->vNodeStarts = Vec_IntStart( pParams->nIdsMax ); - p->vCutPairs = Vec_IntAlloc( 0 ); - } - // allocate storage for delays - if ( pParams->fMap && !p->pParams->fSeq ) - { - p->vDelays = Vec_IntStart( pParams->nIdsMax ); - p->vDelays2 = Vec_IntStart( pParams->nIdsMax ); - p->vCutsMax = Vec_PtrStart( pParams->nIdsMax ); - } - // memory for cuts - p->pMmCuts = Extra_MmFixedStart( p->EntrySize ); - p->vTemp = Vec_PtrAlloc( 100 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the cut manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_ManStop( Cut_Man_t * p ) -{ - Cut_Cut_t * pCut; - int i; -// extern int nTruthDsd; -// printf( "Decomposable cuts = %d.\n", nTruthDsd ); - - Vec_PtrForEachEntry( p->vCutsNew, pCut, i ) - if ( pCut != NULL ) - { - int k = 0; - } - if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew ); - if ( p->vCutsOld ) Vec_PtrFree( p->vCutsOld ); - if ( p->vCutsTemp ) Vec_PtrFree( p->vCutsTemp ); - if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts ); - if ( p->vTemp ) Vec_PtrFree( p->vTemp ); - - if ( p->vCutsMax ) Vec_PtrFree( p->vCutsMax ); - if ( p->vDelays ) Vec_IntFree( p->vDelays ); - if ( p->vDelays2 ) Vec_IntFree( p->vDelays2 ); - if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts ); - if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts ); - if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs ); - if ( p->puTemp[0] ) free( p->puTemp[0] ); - - Extra_MmFixedStop( p->pMmCuts ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_ManPrintStats( Cut_Man_t * p ) -{ - if ( p->pReady ) - { - Cut_CutRecycle( p, p->pReady ); - p->pReady = NULL; - } - printf( "Cut computation statistics:\n" ); - printf( "Current cuts = %8d. (Trivial = %d.)\n", p->nCutsCur-p->nCutsTriv, p->nCutsTriv ); - printf( "Peak cuts = %8d.\n", p->nCutsPeak ); - printf( "Total allocated = %8d.\n", p->nCutsAlloc ); - printf( "Total deallocated = %8d.\n", p->nCutsDealloc ); - printf( "Cuts filtered = %8d.\n", p->nCutsFilter ); - printf( "Nodes saturated = %8d. (Max cuts = %d.)\n", p->nCutsLimit, p->pParams->nKeepMax ); - printf( "Cuts per node = %8.1f\n", ((float)(p->nCutsCur-p->nCutsTriv))/p->nNodes ); - printf( "The cut size = %8d bytes.\n", p->EntrySize ); - printf( "Peak memory = %8.2f Mb.\n", (float)p->nCutsPeak * p->EntrySize / (1<<20) ); - printf( "Total nodes = %8d.\n", p->nNodes ); - if ( p->pParams->fDag || p->pParams->fTree ) - { - printf( "DAG nodes = %8d.\n", p->nNodesDag ); - printf( "Tree nodes = %8d.\n", p->nNodes - p->nNodesDag ); - } - printf( "Nodes w/o cuts = %8d.\n", p->nNodesNoCuts ); - if ( p->pParams->fMap && !p->pParams->fSeq ) - printf( "Mapping delay = %8d.\n", p->nDelayMin ); - - PRT( "Merge ", p->timeMerge ); - PRT( "Union ", p->timeUnion ); - PRT( "Filter", p->timeFilter ); - PRT( "Truth ", p->timeTruth ); - PRT( "Map ", p->timeMap ); -// printf( "Nodes = %d. Multi = %d. Cuts = %d. Multi = %d.\n", -// p->nNodes, p->nNodesMulti, p->nCutsCur-p->nCutsTriv, p->nCutsMulti ); -// printf( "Count0 = %d. Count1 = %d. Count2 = %d.\n\n", p->Count0, p->Count1, p->Count2 ); -} - - -/**Function************************************************************* - - Synopsis [Prints some interesting stats.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_ManPrintStatsToFile( Cut_Man_t * p, char * pFileName, int TimeTotal ) -{ - FILE * pTable; - pTable = fopen( "cut_stats.txt", "a+" ); - fprintf( pTable, "%-20s ", pFileName ); - fprintf( pTable, "%8d ", p->nNodes ); - fprintf( pTable, "%6.1f ", ((float)(p->nCutsCur))/p->nNodes ); - fprintf( pTable, "%6.2f ", ((float)(100.0 * p->nCutsLimit))/p->nNodes ); - fprintf( pTable, "%6.2f ", (float)p->nCutsPeak * p->EntrySize / (1<<20) ); - fprintf( pTable, "%6.2f ", (float)(TimeTotal)/(float)(CLOCKS_PER_SEC) ); - fprintf( pTable, "\n" ); - fclose( pTable ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_ManSetFanoutCounts( Cut_Man_t * p, Vec_Int_t * vFanCounts ) -{ - p->vFanCounts = vFanCounts; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_ManSetNodeAttrs( Cut_Man_t * p, Vec_Int_t * vNodeAttrs ) -{ - p->vNodeAttrs = vNodeAttrs; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_ManReadVarsMax( Cut_Man_t * p ) -{ - return p->pParams->nVarsMax; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Params_t * Cut_ManReadParams( Cut_Man_t * p ) -{ - return p->pParams; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Cut_ManReadNodeAttrs( Cut_Man_t * p ) -{ - return p->vNodeAttrs; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_ManIncrementDagNodes( Cut_Man_t * p ) -{ - p->nNodesDag++; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/cut/cutMerge.c b/src/opt/cut/cutMerge.c deleted file mode 100644 index d8a9989c..00000000 --- a/src/opt/cut/cutMerge.c +++ /dev/null @@ -1,657 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutMerge.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [K-feasible cut computation package.] - - Synopsis [Procedure to merge two cuts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutMerge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cutInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [This procedure works.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutMergeTwo2( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) -{ - static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}}; - Cut_Cut_t * pRes; - int * pRow; - int nLeaves0, nLeaves1, Limit; - int i, k, Count, nNodes; - - assert( pCut0->nLeaves >= pCut1->nLeaves ); - - // the case of the largest cut sizes - Limit = p->pParams->nVarsMax; - nLeaves0 = pCut0->nLeaves; - nLeaves1 = pCut1->nLeaves; - if ( nLeaves0 == Limit && nLeaves1 == Limit ) - { - for ( i = 0; i < nLeaves0; i++ ) - if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] ) - return NULL; - pRes = Cut_CutAlloc( p ); - for ( i = 0; i < nLeaves0; i++ ) - pRes->pLeaves[i] = pCut0->pLeaves[i]; - pRes->nLeaves = nLeaves0; - return pRes; - } - // the case when one of the cuts is the largest - if ( nLeaves0 == Limit ) - { - for ( i = 0; i < nLeaves1; i++ ) - { - for ( k = nLeaves0 - 1; k >= 0; k-- ) - if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) - break; - if ( k == -1 ) // did not find - return NULL; - } - pRes = Cut_CutAlloc( p ); - for ( i = 0; i < nLeaves0; i++ ) - pRes->pLeaves[i] = pCut0->pLeaves[i]; - pRes->nLeaves = nLeaves0; - return pRes; - } - // other cases - nNodes = nLeaves0; - for ( i = 0; i < nLeaves1; i++ ) - { - for ( k = nLeaves0 - 1; k >= 0; k-- ) - { - if ( pCut0->pLeaves[k] > pCut1->pLeaves[i] ) - continue; - if ( pCut0->pLeaves[k] < pCut1->pLeaves[i] ) - { - pRow = M[k+1]; - if ( pRow[0] == 0 ) - pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; - else if ( pRow[1] == 0 ) - pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; - else if ( pRow[2] == 0 ) - pRow[2] = pCut1->pLeaves[i]; - else - assert( 0 ); - if ( ++nNodes > Limit ) - { - for ( i = 0; i <= nLeaves0; i++ ) - M[i][0] = 0; - return NULL; - } - } - break; - } - if ( k == -1 ) - { - pRow = M[0]; - if ( pRow[0] == 0 ) - pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; - else if ( pRow[1] == 0 ) - pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; - else if ( pRow[2] == 0 ) - pRow[2] = pCut1->pLeaves[i]; - else - assert( 0 ); - if ( ++nNodes > Limit ) - { - for ( i = 0; i <= nLeaves0; i++ ) - M[i][0] = 0; - return NULL; - } - continue; - } - } - - pRes = Cut_CutAlloc( p ); - for ( Count = 0, i = 0; i <= nLeaves0; i++ ) - { - if ( i > 0 ) - pRes->pLeaves[Count++] = pCut0->pLeaves[i-1]; - pRow = M[i]; - if ( pRow[0] ) - { - pRes->pLeaves[Count++] = pRow[0]; - if ( pRow[1] ) - { - pRes->pLeaves[Count++] = pRow[1]; - if ( pRow[2] ) - pRes->pLeaves[Count++] = pRow[2]; - } - pRow[0] = 0; - } - } - assert( Count == nNodes ); - pRes->nLeaves = nNodes; - return pRes; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutMergeTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) -{ - Cut_Cut_t * pRes; - int * pLeaves; - int Limit, nLeaves0, nLeaves1; - int i, k, c; - - assert( pCut0->nLeaves >= pCut1->nLeaves ); - - // consider two cuts - nLeaves0 = pCut0->nLeaves; - nLeaves1 = pCut1->nLeaves; - - // the case of the largest cut sizes - Limit = p->pParams->nVarsMax; - if ( nLeaves0 == Limit && nLeaves1 == Limit ) - { - for ( i = 0; i < nLeaves0; i++ ) - if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] ) - return NULL; - pRes = Cut_CutAlloc( p ); - for ( i = 0; i < nLeaves0; i++ ) - pRes->pLeaves[i] = pCut0->pLeaves[i]; - pRes->nLeaves = pCut0->nLeaves; - return pRes; - } - // the case when one of the cuts is the largest - if ( nLeaves0 == Limit ) - { - for ( i = 0; i < nLeaves1; i++ ) - { - for ( k = nLeaves0 - 1; k >= 0; k-- ) - if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) - break; - if ( k == -1 ) // did not find - return NULL; - } - pRes = Cut_CutAlloc( p ); - for ( i = 0; i < nLeaves0; i++ ) - pRes->pLeaves[i] = pCut0->pLeaves[i]; - pRes->nLeaves = pCut0->nLeaves; - return pRes; - } - - // prepare the cut - if ( p->pReady == NULL ) - p->pReady = Cut_CutAlloc( p ); - pLeaves = p->pReady->pLeaves; - - // compare two cuts with different numbers - i = k = 0; - for ( c = 0; c < Limit; c++ ) - { - if ( k == nLeaves1 ) - { - if ( i == nLeaves0 ) - { - p->pReady->nLeaves = c; - pRes = p->pReady; p->pReady = NULL; - return pRes; - } - pLeaves[c] = pCut0->pLeaves[i++]; - continue; - } - if ( i == nLeaves0 ) - { - if ( k == nLeaves1 ) - { - p->pReady->nLeaves = c; - pRes = p->pReady; p->pReady = NULL; - return pRes; - } - pLeaves[c] = pCut1->pLeaves[k++]; - continue; - } - if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] ) - { - pLeaves[c] = pCut0->pLeaves[i++]; - continue; - } - if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] ) - { - pLeaves[c] = pCut1->pLeaves[k++]; - continue; - } - pLeaves[c] = pCut0->pLeaves[i++]; - k++; - } - if ( i < nLeaves0 || k < nLeaves1 ) - return NULL; - p->pReady->nLeaves = c; - pRes = p->pReady; p->pReady = NULL; - return pRes; -} - - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutMergeTwo3( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) -{ - Cut_Cut_t * pRes; - int * pLeaves; - int Limit, nLeaves0, nLeaves1; - int i, k, c; - - assert( pCut0->nLeaves >= pCut1->nLeaves ); - - // prepare the cut - if ( p->pReady == NULL ) - p->pReady = Cut_CutAlloc( p ); - pLeaves = p->pReady->pLeaves; - - // consider two cuts - Limit = p->pParams->nVarsMax; - nLeaves0 = pCut0->nLeaves; - nLeaves1 = pCut1->nLeaves; - if ( nLeaves0 == Limit ) - { // the case when one of the cuts is the largest - if ( nLeaves1 == Limit ) - { // the case when both cuts are the largest - for ( i = 0; i < nLeaves0; i++ ) - { - pLeaves[i] = pCut0->pLeaves[i]; - if ( pLeaves[i] != pCut1->pLeaves[i] ) - return NULL; - } - } - else - { - for ( i = k = 0; i < nLeaves0; i++ ) - { - pLeaves[i] = pCut0->pLeaves[i]; - if ( k == (int)nLeaves1 ) - continue; - if ( pLeaves[i] < pCut1->pLeaves[k] ) - continue; - if ( pLeaves[i] == pCut1->pLeaves[k++] ) - continue; - return NULL; - } - if ( k < nLeaves1 ) - return NULL; - } - p->pReady->nLeaves = nLeaves0; - pRes = p->pReady; p->pReady = NULL; - return pRes; - } - - // compare two cuts with different numbers - i = k = 0; - for ( c = 0; c < Limit; c++ ) - { - if ( k == nLeaves1 ) - { - if ( i == nLeaves0 ) - { - p->pReady->nLeaves = c; - pRes = p->pReady; p->pReady = NULL; - return pRes; - } - pLeaves[c] = pCut0->pLeaves[i++]; - continue; - } - if ( i == nLeaves0 ) - { - if ( k == nLeaves1 ) - { - p->pReady->nLeaves = c; - pRes = p->pReady; p->pReady = NULL; - return pRes; - } - pLeaves[c] = pCut1->pLeaves[k++]; - continue; - } - if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] ) - { - pLeaves[c] = pCut0->pLeaves[i++]; - continue; - } - if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] ) - { - pLeaves[c] = pCut1->pLeaves[k++]; - continue; - } - pLeaves[c] = pCut0->pLeaves[i++]; - k++; - } - if ( i < nLeaves0 || k < nLeaves1 ) - return NULL; - p->pReady->nLeaves = c; - pRes = p->pReady; p->pReady = NULL; - return pRes; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutMergeTwo4( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) -{ - Cut_Cut_t * pRes; - int * pLeaves; - int i, k, min, NodeTemp, Limit, nTotal; - - assert( pCut0->nLeaves >= pCut1->nLeaves ); - - // prepare the cut - if ( p->pReady == NULL ) - p->pReady = Cut_CutAlloc( p ); - pLeaves = p->pReady->pLeaves; - - // consider two cuts - Limit = p->pParams->nVarsMax; - if ( pCut0->nLeaves == (unsigned)Limit ) - { // the case when one of the cuts is the largest - if ( pCut1->nLeaves == (unsigned)Limit ) - { // the case when both cuts are the largest - for ( i = 0; i < (int)pCut0->nLeaves; i++ ) - { - pLeaves[i] = pCut0->pLeaves[i]; - if ( pLeaves[i] != pCut1->pLeaves[i] ) - return NULL; - } - } - else - { - for ( i = k = 0; i < (int)pCut0->nLeaves; i++ ) - { - pLeaves[i] = pCut0->pLeaves[i]; - if ( k == (int)pCut1->nLeaves ) - continue; - if ( pLeaves[i] < pCut1->pLeaves[k] ) - continue; - if ( pLeaves[i] == pCut1->pLeaves[k++] ) - continue; - return NULL; - } - if ( k < (int)pCut1->nLeaves ) - return NULL; - } - p->pReady->nLeaves = pCut0->nLeaves; - pRes = p->pReady; p->pReady = NULL; - return pRes; - } - - // count the number of unique entries in pCut1 - nTotal = pCut0->nLeaves; - for ( i = 0; i < (int)pCut1->nLeaves; i++ ) - { - // try to find this entry among the leaves of pCut0 - for ( k = 0; k < (int)pCut0->nLeaves; k++ ) - if ( pCut1->pLeaves[i] == pCut0->pLeaves[k] ) - break; - if ( k < (int)pCut0->nLeaves ) // found - continue; - // we found a new entry to add - if ( nTotal == Limit ) - return NULL; - pLeaves[nTotal++] = pCut1->pLeaves[i]; - } - // we know that the feasible cut exists - - // add the starting entries - for ( k = 0; k < (int)pCut0->nLeaves; k++ ) - pLeaves[k] = pCut0->pLeaves[k]; - - // selection-sort the entries - for ( i = 0; i < nTotal - 1; i++ ) - { - min = i; - for ( k = i+1; k < nTotal; k++ ) - if ( pLeaves[k] < pLeaves[min] ) - min = k; - NodeTemp = pLeaves[i]; - pLeaves[i] = pLeaves[min]; - pLeaves[min] = NodeTemp; - } - p->pReady->nLeaves = nTotal; - pRes = p->pReady; p->pReady = NULL; - return pRes; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [This procedure works.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutMergeTwo5( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) -{ - static int M[7][3] = {{0},{0},{0},{0},{0},{0},{0}}; - Cut_Cut_t * pRes; - int * pRow; - unsigned uSign0, uSign1; - int i, k, nNodes, Count; - unsigned Limit = p->pParams->nVarsMax; - - assert( pCut0->nLeaves >= pCut1->nLeaves ); - - // the case of the largest cut sizes - if ( pCut0->nLeaves == Limit && pCut1->nLeaves == Limit ) - { - for ( i = 0; i < (int)pCut0->nLeaves; i++ ) - if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] ) - return NULL; - pRes = Cut_CutAlloc( p ); - for ( i = 0; i < (int)pCut0->nLeaves; i++ ) - pRes->pLeaves[i] = pCut0->pLeaves[i]; - pRes->nLeaves = pCut0->nLeaves; - return pRes; - } - // the case when one of the cuts is the largest - if ( pCut0->nLeaves == Limit ) - { - if ( !p->pParams->fTruth ) - { - for ( i = 0; i < (int)pCut1->nLeaves; i++ ) - { - for ( k = pCut0->nLeaves - 1; k >= 0; k-- ) - if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) - break; - if ( k == -1 ) // did not find - return NULL; - } - pRes = Cut_CutAlloc( p ); - } - else - { - uSign1 = 0; - for ( i = 0; i < (int)pCut1->nLeaves; i++ ) - { - for ( k = pCut0->nLeaves - 1; k >= 0; k-- ) - if ( pCut0->pLeaves[k] == pCut1->pLeaves[i] ) - { - uSign1 |= (1 << i); - break; - } - if ( k == -1 ) // did not find - return NULL; - } - pRes = Cut_CutAlloc( p ); - pRes->Num1 = uSign1; - } - for ( i = 0; i < (int)pCut0->nLeaves; i++ ) - pRes->pLeaves[i] = pCut0->pLeaves[i]; - pRes->nLeaves = pCut0->nLeaves; - return pRes; - } - // other cases - nNodes = pCut0->nLeaves; - for ( i = 0; i < (int)pCut1->nLeaves; i++ ) - { - for ( k = pCut0->nLeaves - 1; k >= 0; k-- ) - { - if ( pCut0->pLeaves[k] > pCut1->pLeaves[i] ) - continue; - if ( pCut0->pLeaves[k] < pCut1->pLeaves[i] ) - { - pRow = M[k+1]; - if ( pRow[0] == 0 ) - pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; - else if ( pRow[1] == 0 ) - pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; - else if ( pRow[2] == 0 ) - pRow[2] = pCut1->pLeaves[i]; - else - assert( 0 ); - if ( ++nNodes > (int)Limit ) - { - for ( i = 0; i <= (int)pCut0->nLeaves; i++ ) - M[i][0] = 0; - return NULL; - } - } - break; - } - if ( k == -1 ) - { - pRow = M[0]; - if ( pRow[0] == 0 ) - pRow[0] = pCut1->pLeaves[i], pRow[1] = 0; - else if ( pRow[1] == 0 ) - pRow[1] = pCut1->pLeaves[i], pRow[2] = 0; - else if ( pRow[2] == 0 ) - pRow[2] = pCut1->pLeaves[i]; - else - assert( 0 ); - if ( ++nNodes > (int)Limit ) - { - for ( i = 0; i <= (int)pCut0->nLeaves; i++ ) - M[i][0] = 0; - return NULL; - } - continue; - } - } - - pRes = Cut_CutAlloc( p ); - if ( !p->pParams->fTruth ) - { - for ( Count = 0, i = 0; i <= (int)pCut0->nLeaves; i++ ) - { - if ( i > 0 ) - pRes->pLeaves[Count++] = pCut0->pLeaves[i-1]; - pRow = M[i]; - if ( pRow[0] ) - { - pRes->pLeaves[Count++] = pRow[0]; - if ( pRow[1] ) - { - pRes->pLeaves[Count++] = pRow[1]; - if ( pRow[2] ) - pRes->pLeaves[Count++] = pRow[2]; - } - pRow[0] = 0; - } - } - assert( Count == nNodes ); - pRes->nLeaves = nNodes; -/* - // make sure that the cut is correct - { - for ( i = 1; i < (int)pRes->nLeaves; i++ ) - if ( pRes->pLeaves[i-1] >= pRes->pLeaves[i] ) - { - int v = 0; - } - } -*/ - return pRes; - } - - uSign0 = uSign1 = 0; - for ( Count = 0, i = 0; i <= (int)pCut0->nLeaves; i++ ) - { - if ( i > 0 ) - { - uSign0 |= (1 << Count); - pRes->pLeaves[Count++] = pCut1->pLeaves[i-1]; - } - pRow = M[i]; - if ( pRow[0] ) - { - uSign1 |= (1 << Count); - pRes->pLeaves[Count++] = pRow[0]; - if ( pRow[1] ) - { - uSign1 |= (1 << Count); - pRes->pLeaves[Count++] = pRow[1]; - if ( pRow[2] ) - { - uSign1 |= (1 << Count); - pRes->pLeaves[Count++] = pRow[2]; - } - } - pRow[0] = 0; - } - } - assert( Count == nNodes ); - pRes->nLeaves = nNodes; - pRes->Num1 = uSign1; - pRes->Num0 = uSign0; - return pRes; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/cut/cutNode.c b/src/opt/cut/cutNode.c deleted file mode 100644 index 1f93b14b..00000000 --- a/src/opt/cut/cutNode.c +++ /dev/null @@ -1,992 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutNode.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [K-feasible cut computation package.] - - Synopsis [Procedures to compute cuts for a node.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutNode.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cutInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ); -static int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Returns 1 if pDom is contained in pCut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Cut_CutCheckDominance( Cut_Cut_t * pDom, Cut_Cut_t * pCut ) -{ - int i, k; - for ( i = 0; i < (int)pDom->nLeaves; i++ ) - { - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) - break; - if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut - return 0; - } - // every node in pDom is contained in pCut - return 1; -} - -/**Function************************************************************* - - Synopsis [Filters cuts using dominance.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Cut_CutFilter( Cut_Man_t * p, Cut_Cut_t * pList ) -{ - Cut_Cut_t * pListR, ** ppListR = &pListR; - Cut_Cut_t * pCut, * pCut2, * pDom, * pPrev; - // save the first cut - *ppListR = pList, ppListR = &pList->pNext; - // try to filter out other cuts - pPrev = pList; - Cut_ListForEachCutSafe( pList->pNext, pCut, pCut2 ) - { - assert( pCut->nLeaves > 1 ); - // go through all the previous cuts up to pCut - Cut_ListForEachCutStop( pList->pNext, pDom, pCut ) - { - if ( pDom->nLeaves > pCut->nLeaves ) - continue; - if ( (pDom->uSign & pCut->uSign) != pDom->uSign ) - continue; - if ( Cut_CutCheckDominance( pDom, pCut ) ) - break; - } - if ( pDom != pCut ) // pDom is contained in pCut - recycle pCut - { - // make sure cuts are connected after removing - pPrev->pNext = pCut->pNext; - // recycle the cut - Cut_CutRecycle( p, pCut ); - } - else // pDom is NOT contained in pCut - save pCut - { - *ppListR = pCut, ppListR = &pCut->pNext; - pPrev = pCut; - } - } - *ppListR = NULL; -} - -/**Function************************************************************* - - Synopsis [Checks equality of one cut.] - - Description [Returns 1 if the cut is removed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Cut_CutFilterOneEqual( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut ) -{ - Cut_Cut_t * pTemp; - Cut_ListForEachCut( pSuperList->pHead[pCut->nLeaves], pTemp ) - { - // skip the non-contained cuts - if ( pCut->uSign != pTemp->uSign ) - continue; - // check containment seriously - if ( Cut_CutCheckDominance( pTemp, pCut ) ) - { - p->nCutsFilter++; - Cut_CutRecycle( p, pCut ); - return 1; - } - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Checks containment for one cut.] - - Description [Returns 1 if the cut is removed.] - - SideEffects [May remove other cuts in the set.] - - SeeAlso [] - -***********************************************************************/ -static inline int Cut_CutFilterOne( Cut_Man_t * p, Cut_List_t * pSuperList, Cut_Cut_t * pCut ) -{ - Cut_Cut_t * pTemp, * pTemp2, ** ppTail; - int a; - - // check if this cut is filtered out by smaller cuts - for ( a = 2; a <= (int)pCut->nLeaves; a++ ) - { - Cut_ListForEachCut( pSuperList->pHead[a], pTemp ) - { - // skip the non-contained cuts - if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) - continue; - // check containment seriously - if ( Cut_CutCheckDominance( pTemp, pCut ) ) - { - p->nCutsFilter++; - Cut_CutRecycle( p, pCut ); - return 1; - } - } - } - - // filter out other cuts using this one - for ( a = pCut->nLeaves + 1; a <= (int)pCut->nVarsMax; a++ ) - { - ppTail = pSuperList->pHead + a; - Cut_ListForEachCutSafe( pSuperList->pHead[a], pTemp, pTemp2 ) - { - // skip the non-contained cuts - if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) - { - ppTail = &pTemp->pNext; - continue; - } - // check containment seriously - if ( Cut_CutCheckDominance( pCut, pTemp ) ) - { - p->nCutsFilter++; - p->nNodeCuts--; - // move the head - if ( pSuperList->pHead[a] == pTemp ) - pSuperList->pHead[a] = pTemp->pNext; - // move the tail - if ( pSuperList->ppTail[a] == &pTemp->pNext ) - pSuperList->ppTail[a] = ppTail; - // skip the given cut in the list - *ppTail = pTemp->pNext; - // recycle pTemp - Cut_CutRecycle( p, pTemp ); - } - else - ppTail = &pTemp->pNext; - } - assert( ppTail == pSuperList->ppTail[a] ); - assert( *ppTail == NULL ); - } - - return 0; -} - -/**Function************************************************************* - - Synopsis [Checks if the cut is local and can be removed.] - - Description [Returns 1 if the cut is removed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Cut_CutFilterGlobal( Cut_Man_t * p, Cut_Cut_t * pCut ) -{ - int a; - if ( pCut->nLeaves == 1 ) - return 0; - for ( a = 0; a < (int)pCut->nLeaves; a++ ) - if ( Vec_IntEntry( p->vNodeAttrs, pCut->pLeaves[a] ) ) // global - return 0; - // there is no global nodes, the cut should be removed - p->nCutsFilter++; - Cut_CutRecycle( p, pCut ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Checks containment for one cut.] - - Description [Returns 1 if the cut is removed.] - - SideEffects [May remove other cuts in the set.] - - SeeAlso [] - -***********************************************************************/ -static inline int Cut_CutFilterOld( Cut_Man_t * p, Cut_Cut_t * pList, Cut_Cut_t * pCut ) -{ - Cut_Cut_t * pPrev, * pTemp, * pTemp2, ** ppTail; - - // check if this cut is filtered out by smaller cuts - pPrev = NULL; - Cut_ListForEachCut( pList, pTemp ) - { - if ( pTemp->nLeaves > pCut->nLeaves ) - break; - pPrev = pTemp; - // skip the non-contained cuts - if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) - continue; - // check containment seriously - if ( Cut_CutCheckDominance( pTemp, pCut ) ) - { - p->nCutsFilter++; - Cut_CutRecycle( p, pCut ); - return 1; - } - } - assert( pPrev->pNext == pTemp ); - - // filter out other cuts using this one - ppTail = &pPrev->pNext; - Cut_ListForEachCutSafe( pTemp, pTemp, pTemp2 ) - { - // skip the non-contained cuts - if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) - { - ppTail = &pTemp->pNext; - continue; - } - // check containment seriously - if ( Cut_CutCheckDominance( pCut, pTemp ) ) - { - p->nCutsFilter++; - p->nNodeCuts--; - // skip the given cut in the list - *ppTail = pTemp->pNext; - // recycle pTemp - Cut_CutRecycle( p, pTemp ); - } - else - ppTail = &pTemp->pNext; - } - assert( *ppTail == NULL ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Processes two cuts.] - - Description [Returns 1 if the limit has been reached.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Cut_CutProcessTwo( Cut_Man_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, Cut_List_t * pSuperList ) -{ - Cut_Cut_t * pCut; - // merge the cuts - if ( pCut0->nLeaves >= pCut1->nLeaves ) - pCut = Cut_CutMergeTwo( p, pCut0, pCut1 ); - else - pCut = Cut_CutMergeTwo( p, pCut1, pCut0 ); - if ( pCut == NULL ) - return 0; - assert( p->pParams->fSeq || pCut->nLeaves > 1 ); - // set the signature - pCut->uSign = pCut0->uSign | pCut1->uSign; - if ( p->pParams->fRecord ) - pCut->Num0 = pCut0->Num0, pCut->Num1 = pCut1->Num0; - // check containment - if ( p->pParams->fFilter ) - { - if ( Cut_CutFilterOne(p, pSuperList, pCut) ) -// if ( Cut_CutFilterOneEqual(p, pSuperList, pCut) ) - return 0; - if ( p->pParams->fSeq ) - { - if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) - return 0; - if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) - return 0; - } - } - - if ( p->pParams->fGlobal ) - { - assert( p->vNodeAttrs != NULL ); - if ( Cut_CutFilterGlobal( p, pCut ) ) - return 0; - } - - // compute the truth table - if ( p->pParams->fTruth ) - Cut_TruthCompute( p, pCut, pCut0, pCut1, p->fCompl0, p->fCompl1 ); - // add to the list - Cut_ListAdd( pSuperList, pCut ); - // return status (0 if okay; 1 if exceeded the limit) - return ++p->nNodeCuts == p->pParams->nKeepMax; -} - -/**Function************************************************************* - - Synopsis [Computes the cuts by merging cuts at two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv, int TreeCode ) -{ - Cut_List_t Super, * pSuper = &Super; - Cut_Cut_t * pList, * pCut; - int clk; - // start the number of cuts at the node - p->nNodes++; - p->nNodeCuts = 0; - // prepare information for recording - if ( p->pParams->fRecord ) - { - Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node0) ); - Cut_CutNumberList( Cut_NodeReadCutsNew(p, Node1) ); - } - // compute the cuts -clk = clock(); - Cut_ListStart( pSuper ); - Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, Cut_NodeReadCutsNew(p, Node0), Cut_NodeReadCutsNew(p, Node1), fTriv, TreeCode ); - pList = Cut_ListFinish( pSuper ); -p->timeMerge += clock() - clk; - // verify the result of cut computation -// Cut_CutListVerify( pList ); - // performing the recording - if ( p->pParams->fRecord ) - { - Vec_IntWriteEntry( p->vNodeStarts, Node, Vec_IntSize(p->vCutPairs) ); - Cut_ListForEachCut( pList, pCut ) - Vec_IntPush( p->vCutPairs, ((pCut->Num1 << 16) | pCut->Num0) ); - Vec_IntWriteEntry( p->vNodeCuts, Node, Vec_IntSize(p->vCutPairs) - Vec_IntEntry(p->vNodeStarts, Node) ); - } - // check if the node is over the list - if ( p->nNodeCuts == p->pParams->nKeepMax ) - p->nCutsLimit++; - // set the list at the node - Vec_PtrFillExtra( p->vCutsNew, Node + 1, NULL ); - assert( Cut_NodeReadCutsNew(p, Node) == NULL ); - ///// -// pList->pNext = NULL; - ///// - Cut_NodeWriteCutsNew( p, Node, pList ); - // filter the cuts -//clk = clock(); -// if ( p->pParams->fFilter ) -// Cut_CutFilter( p, pList0 ); -//p->timeFilter += clock() - clk; - // perform mapping of this node with these cuts -clk = clock(); - if ( p->pParams->fMap && !p->pParams->fSeq ) - { -// int Delay1, Delay2; -// Delay1 = Cut_NodeMapping( p, pList, Node, Node0, Node1 ); -// Delay2 = Cut_NodeMapping2( p, pList, Node, Node0, Node1 ); -// assert( Delay1 >= Delay2 ); - Cut_NodeMapping( p, pList, Node, Node0, Node1 ); - } -p->timeMap += clock() - clk; - return pList; -} - -/**Function************************************************************* - - Synopsis [Returns optimum delay mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_NodeMapping2( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ) -{ - Cut_Cut_t * pCut; - int DelayMin, DelayCur, i; - if ( pCuts == NULL ) - p->nDelayMin = -1; - if ( p->nDelayMin == -1 ) - return -1; - DelayMin = 1000000; - Cut_ListForEachCut( pCuts, pCut ) - { - if ( pCut->nLeaves == 1 ) - continue; - DelayCur = 0; - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - if ( DelayCur < Vec_IntEntry(p->vDelays, pCut->pLeaves[i]) ) - DelayCur = Vec_IntEntry(p->vDelays, pCut->pLeaves[i]); - if ( DelayMin > DelayCur ) - DelayMin = DelayCur; - } - if ( DelayMin == 1000000 ) - { - p->nDelayMin = -1; - return -1; - } - DelayMin++; - Vec_IntWriteEntry( p->vDelays, Node, DelayMin ); - if ( p->nDelayMin < DelayMin ) - p->nDelayMin = DelayMin; - return DelayMin; -} - -/**Function************************************************************* - - Synopsis [Returns optimum delay mapping using the largest cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_NodeMapping( Cut_Man_t * p, Cut_Cut_t * pCuts, int Node, int Node0, int Node1 ) -{ - Cut_Cut_t * pCut0, * pCut1, * pCut; - int Delay0, Delay1, Delay; - // get the fanin cuts - Delay0 = Vec_IntEntry( p->vDelays2, Node0 ); - Delay1 = Vec_IntEntry( p->vDelays2, Node1 ); - pCut0 = (Delay0 == 0) ? Vec_PtrEntry( p->vCutsNew, Node0 ) : Vec_PtrEntry( p->vCutsMax, Node0 ); - pCut1 = (Delay1 == 0) ? Vec_PtrEntry( p->vCutsNew, Node1 ) : Vec_PtrEntry( p->vCutsMax, Node1 ); - if ( Delay0 == Delay1 ) - Delay = (Delay0 == 0) ? Delay0 + 1: Delay0; - else if ( Delay0 > Delay1 ) - { - Delay = Delay0; - pCut1 = Vec_PtrEntry( p->vCutsNew, Node1 ); - assert( pCut1->nLeaves == 1 ); - } - else // if ( Delay0 < Delay1 ) - { - Delay = Delay1; - pCut0 = Vec_PtrEntry( p->vCutsNew, Node0 ); - assert( pCut0->nLeaves == 1 ); - } - // merge the cuts - if ( pCut0->nLeaves < pCut1->nLeaves ) - pCut = Cut_CutMergeTwo( p, pCut1, pCut0 ); - else - pCut = Cut_CutMergeTwo( p, pCut0, pCut1 ); - if ( pCut == NULL ) - { - Delay++; - pCut = Cut_CutAlloc( p ); - pCut->nLeaves = 2; - pCut->pLeaves[0] = Node0 < Node1 ? Node0 : Node1; - pCut->pLeaves[1] = Node0 < Node1 ? Node1 : Node0; - } - assert( Delay > 0 ); - Vec_IntWriteEntry( p->vDelays2, Node, Delay ); - Vec_PtrWriteEntry( p->vCutsMax, Node, pCut ); - if ( p->nDelayMin < Delay ) - p->nDelayMin = Delay; - return Delay; -} - -/**Function************************************************************* - - Synopsis [Computes area after mapping.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_ManMappingArea_rec( Cut_Man_t * p, int Node ) -{ - Cut_Cut_t * pCut; - int i, Counter; - if ( p->vCutsMax == NULL ) - return 0; - pCut = Vec_PtrEntry( p->vCutsMax, Node ); - if ( pCut == NULL || pCut->nLeaves == 1 ) - return 0; - Counter = 0; - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - Counter += Cut_ManMappingArea_rec( p, pCut->pLeaves[i] ); - Vec_PtrWriteEntry( p->vCutsMax, Node, NULL ); - return 1 + Counter; -} - - -/**Function************************************************************* - - Synopsis [Computes the cuts by merging cuts at two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fCompl0, int fCompl1, Cut_Cut_t * pList0, Cut_Cut_t * pList1, int fTriv, int TreeCode ) -{ - Cut_Cut_t * pStop0, * pStop1, * pTemp0, * pTemp1, * pStore0, * pStore1; - int i, nCutsOld, Limit; - // start with the elementary cut - if ( fTriv ) - { -// printf( "Creating trivial cut %d.\n", Node ); - pTemp0 = Cut_CutCreateTriv( p, Node ); - Cut_ListAdd( pSuper, pTemp0 ); - p->nNodeCuts++; - } - // get the cut lists of children - if ( pList0 == NULL || pList1 == NULL || (p->pParams->fLocal && TreeCode) ) - return; - - // remember the old number of cuts - nCutsOld = p->nCutsCur; - Limit = p->pParams->nVarsMax; - // get the simultation bit of the node - p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul); - // set temporary variables - p->fCompl0 = fCompl0; - p->fCompl1 = fCompl1; - // if tree cuts are computed, make sure only the unit cuts propagate over the DAG nodes - if ( TreeCode & 1 ) - { - assert( pList0->nLeaves == 1 ); - pStore0 = pList0->pNext; - pList0->pNext = NULL; - } - if ( TreeCode & 2 ) - { - assert( pList1->nLeaves == 1 ); - pStore1 = pList1->pNext; - pList1->pNext = NULL; - } - // find the point in the list where the max-var cuts begin - Cut_ListForEachCut( pList0, pStop0 ) - if ( pStop0->nLeaves == (unsigned)Limit ) - break; - Cut_ListForEachCut( pList1, pStop1 ) - if ( pStop1->nLeaves == (unsigned)Limit ) - break; - - // small by small - Cut_ListForEachCutStop( pList0, pTemp0, pStop0 ) - Cut_ListForEachCutStop( pList1, pTemp1, pStop1 ) - { - if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) - goto Quits; - } - // small by large - Cut_ListForEachCutStop( pList0, pTemp0, pStop0 ) - Cut_ListForEachCut( pStop1, pTemp1 ) - { - if ( (pTemp0->uSign & pTemp1->uSign) != pTemp0->uSign ) - continue; - if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) - goto Quits; - } - // small by large - Cut_ListForEachCutStop( pList1, pTemp1, pStop1 ) - Cut_ListForEachCut( pStop0, pTemp0 ) - { - if ( (pTemp0->uSign & pTemp1->uSign) != pTemp1->uSign ) - continue; - if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) - goto Quits; - } - // large by large - Cut_ListForEachCut( pStop0, pTemp0 ) - Cut_ListForEachCut( pStop1, pTemp1 ) - { - assert( pTemp0->nLeaves == (unsigned)Limit && pTemp1->nLeaves == (unsigned)Limit ); - if ( pTemp0->uSign != pTemp1->uSign ) - continue; - for ( i = 0; i < Limit; i++ ) - if ( pTemp0->pLeaves[i] != pTemp1->pLeaves[i] ) - break; - if ( i < Limit ) - continue; - if ( Cut_CutProcessTwo( p, pTemp0, pTemp1, pSuper ) ) - goto Quits; - } - if ( p->nNodeCuts == 0 ) - p->nNodesNoCuts++; -Quits: - if ( TreeCode & 1 ) - pList0->pNext = pStore0; - if ( TreeCode & 2 ) - pList1->pNext = pStore1; -} - -/**Function************************************************************* - - Synopsis [Computes the cuts by unioning cuts at a choice node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes ) -{ - Cut_List_t Super, * pSuper = &Super; - Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop; - int i, k, Node, Root, Limit = p->pParams->nVarsMax; - int clk = clock(); - - // start the new list - Cut_ListStart( pSuper ); - - // remember the root node to save the resulting cuts - Root = Vec_IntEntry( vNodes, 0 ); - p->nNodeCuts = 1; - - // collect small cuts first - Vec_PtrClear( p->vTemp ); - Vec_IntForEachEntry( vNodes, Node, i ) - { - // get the cuts of this node - pList = Cut_NodeReadCutsNew( p, Node ); - Cut_NodeWriteCutsNew( p, Node, NULL ); - assert( pList ); - // remember the starting point - pListStart = pList->pNext; - pList->pNext = NULL; - // save or recycle the elementary cut - if ( i == 0 ) - Cut_ListAdd( pSuper, pList ), pTop = pList; - else - Cut_CutRecycle( p, pList ); - // save all the cuts that are smaller than the limit - Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) - { - if ( pCut->nLeaves == (unsigned)Limit ) - { - Vec_PtrPush( p->vTemp, pCut ); - break; - } - // check containment - if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) - continue; - // set the complemented bit by comparing the first cut with the current cut - pCut->fCompl = pTop->fSimul ^ pCut->fSimul; - pListStart = pCut->pNext; - pCut->pNext = NULL; - // add to the list - Cut_ListAdd( pSuper, pCut ); - if ( ++p->nNodeCuts == p->pParams->nKeepMax ) - { - // recycle the rest of the cuts of this node - Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) - Cut_CutRecycle( p, pCut ); - // recycle all cuts of other nodes - Vec_IntForEachEntryStart( vNodes, Node, k, i+1 ) - Cut_NodeFreeCuts( p, Node ); - // recycle the saved cuts of other nodes - Vec_PtrForEachEntry( p->vTemp, pList, k ) - Cut_ListForEachCutSafe( pList, pCut, pCut2 ) - Cut_CutRecycle( p, pCut ); - goto finish; - } - } - } - // collect larger cuts next - Vec_PtrForEachEntry( p->vTemp, pList, i ) - { - Cut_ListForEachCutSafe( pList, pCut, pCut2 ) - { - // check containment - if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) - continue; - // set the complemented bit - pCut->fCompl = pTop->fSimul ^ pCut->fSimul; - pListStart = pCut->pNext; - pCut->pNext = NULL; - // add to the list - Cut_ListAdd( pSuper, pCut ); - if ( ++p->nNodeCuts == p->pParams->nKeepMax ) - { - // recycle the rest of the cuts - Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) - Cut_CutRecycle( p, pCut ); - // recycle the saved cuts of other nodes - Vec_PtrForEachEntryStart( p->vTemp, pList, k, i+1 ) - Cut_ListForEachCutSafe( pList, pCut, pCut2 ) - Cut_CutRecycle( p, pCut ); - goto finish; - } - } - } -finish : - // set the cuts at the node - assert( Cut_NodeReadCutsNew(p, Root) == NULL ); - pList = Cut_ListFinish( pSuper ); - Cut_NodeWriteCutsNew( p, Root, pList ); -p->timeUnion += clock() - clk; - // filter the cuts -//clk = clock(); -// if ( p->pParams->fFilter ) -// Cut_CutFilter( p, pList ); -//p->timeFilter += clock() - clk; - p->nNodes -= vNodes->nSize - 1; - return pList; -} - -/**Function************************************************************* - - Synopsis [Computes the cuts by unioning cuts at a choice node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst ) -{ - Cut_List_t Super, * pSuper = &Super; - Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop; - int i, k, Node, Root, Limit = p->pParams->nVarsMax; - int clk = clock(); - - // start the new list - Cut_ListStart( pSuper ); - - // remember the root node to save the resulting cuts - Root = Vec_IntEntry( vNodes, 0 ); - p->nNodeCuts = 1; - - // store the original lists for comparison - p->pCompareOld = Cut_NodeReadCutsOld( p, Root ); - p->pCompareNew = (CutSetNum >= 0)? Cut_NodeReadCutsNew( p, Root ) : NULL; - - // get the topmost cut - pTop = NULL; - if ( (pTop = Cut_NodeReadCutsOld( p, Root )) == NULL ) - pTop = Cut_NodeReadCutsNew( p, Root ); - assert( pTop != NULL ); - - // collect small cuts first - Vec_PtrClear( p->vTemp ); - Vec_IntForEachEntry( vNodes, Node, i ) - { - // get the cuts of this node - if ( i == 0 && CutSetNum >= 0 ) - { - pList = Cut_NodeReadCutsTemp( p, CutSetNum ); - Cut_NodeWriteCutsTemp( p, CutSetNum, NULL ); - } - else - { - pList = Cut_NodeReadCutsNew( p, Node ); - Cut_NodeWriteCutsNew( p, Node, NULL ); - } - if ( pList == NULL ) - continue; - - // process the cuts - if ( fFirst ) - { - // remember the starting point - pListStart = pList->pNext; - pList->pNext = NULL; - // save or recycle the elementary cut - if ( i == 0 ) - Cut_ListAdd( pSuper, pList ); - else - Cut_CutRecycle( p, pList ); - } - else - pListStart = pList; - - // save all the cuts that are smaller than the limit - Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) - { - if ( pCut->nLeaves == (unsigned)Limit ) - { - Vec_PtrPush( p->vTemp, pCut ); - break; - } - // check containment -// if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) -// continue; - if ( p->pParams->fFilter ) - { - if ( Cut_CutFilterOne(p, pSuper, pCut) ) - continue; - if ( p->pParams->fSeq ) - { - if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) - continue; - if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) - continue; - } - } - - // set the complemented bit by comparing the first cut with the current cut - pCut->fCompl = pTop->fSimul ^ pCut->fSimul; - pListStart = pCut->pNext; - pCut->pNext = NULL; - // add to the list - Cut_ListAdd( pSuper, pCut ); - if ( ++p->nNodeCuts == p->pParams->nKeepMax ) - { - // recycle the rest of the cuts of this node - Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) - Cut_CutRecycle( p, pCut ); - // recycle all cuts of other nodes - Vec_IntForEachEntryStart( vNodes, Node, k, i+1 ) - Cut_NodeFreeCuts( p, Node ); - // recycle the saved cuts of other nodes - Vec_PtrForEachEntry( p->vTemp, pList, k ) - Cut_ListForEachCutSafe( pList, pCut, pCut2 ) - Cut_CutRecycle( p, pCut ); - goto finish; - } - } - } - // collect larger cuts next - Vec_PtrForEachEntry( p->vTemp, pList, i ) - { - Cut_ListForEachCutSafe( pList, pCut, pCut2 ) - { - // check containment -// if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) ) -// continue; - if ( p->pParams->fFilter ) - { - if ( Cut_CutFilterOne(p, pSuper, pCut) ) - continue; - if ( p->pParams->fSeq ) - { - if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) ) - continue; - if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) ) - continue; - } - } - - // set the complemented bit - pCut->fCompl = pTop->fSimul ^ pCut->fSimul; - pListStart = pCut->pNext; - pCut->pNext = NULL; - // add to the list - Cut_ListAdd( pSuper, pCut ); - if ( ++p->nNodeCuts == p->pParams->nKeepMax ) - { - // recycle the rest of the cuts - Cut_ListForEachCutSafe( pListStart, pCut, pCut2 ) - Cut_CutRecycle( p, pCut ); - // recycle the saved cuts of other nodes - Vec_PtrForEachEntryStart( p->vTemp, pList, k, i+1 ) - Cut_ListForEachCutSafe( pList, pCut, pCut2 ) - Cut_CutRecycle( p, pCut ); - goto finish; - } - } - } -finish : - // set the cuts at the node - pList = Cut_ListFinish( pSuper ); - - // set the lists at the node -// assert( Cut_NodeReadCutsNew(p, Root) == NULL ); -// Cut_NodeWriteCutsNew( p, Root, pList ); - if ( CutSetNum >= 0 ) - { - assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL ); - Cut_NodeWriteCutsTemp( p, CutSetNum, pList ); - } - else - { - assert( Cut_NodeReadCutsNew(p, Root) == NULL ); - Cut_NodeWriteCutsNew( p, Root, pList ); - } - -p->timeUnion += clock() - clk; - // filter the cuts -//clk = clock(); -// if ( p->pParams->fFilter ) -// Cut_CutFilter( p, pList ); -//p->timeFilter += clock() - clk; -// if ( fFirst ) -// p->nNodes -= vNodes->nSize - 1; - return pList; -} - - -/**Function************************************************************* - - Synopsis [Verifies that the list contains only non-dominated cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_CutListVerify( Cut_Cut_t * pList ) -{ - Cut_Cut_t * pCut, * pDom; - Cut_ListForEachCut( pList, pCut ) - { - Cut_ListForEachCutStop( pList, pDom, pCut ) - { - if ( Cut_CutCheckDominance( pDom, pCut ) ) - { - int x = 0; - printf( "******************* These are contained cuts:\n" ); - Cut_CutPrint( pDom, 1 ); - Cut_CutPrint( pDom, 1 ); - - return 0; - } - } - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/cut/cutOracle.c b/src/opt/cut/cutOracle.c deleted file mode 100644 index 3eb4462b..00000000 --- a/src/opt/cut/cutOracle.c +++ /dev/null @@ -1,428 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutOracle.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [K-feasible cut computation package.] - - Synopsis [Procedures to compute cuts for a node using the oracle.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutOracle.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cutInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Cut_OracleStruct_t_ -{ - // cut comptupatation parameters - Cut_Params_t * pParams; - Vec_Int_t * vFanCounts; - int fSimul; - // storage for cuts - Vec_Ptr_t * vCutsNew; - Vec_Ptr_t * vCuts0; - Vec_Ptr_t * vCuts1; - // oracle info - Vec_Int_t * vNodeCuts; - Vec_Int_t * vNodeStarts; - Vec_Int_t * vCutPairs; - // memory management - Extra_MmFixed_t * pMmCuts; - int EntrySize; - int nTruthWords; - // stats - int timeTotal; - int nCuts; - int nCutsTriv; -}; - -static Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p ); -static Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node ); -static Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the cut oracle.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Oracle_t * Cut_OracleStart( Cut_Man_t * pMan ) -{ - Cut_Oracle_t * p; - int clk = clock(); - - assert( pMan->pParams->nVarsMax >= 3 && pMan->pParams->nVarsMax <= CUT_SIZE_MAX ); - assert( pMan->pParams->fRecord ); - - p = ALLOC( Cut_Oracle_t, 1 ); - memset( p, 0, sizeof(Cut_Oracle_t) ); - - // set and correct parameters - p->pParams = pMan->pParams; - - // transfer the recording info - p->vNodeCuts = pMan->vNodeCuts; pMan->vNodeCuts = NULL; - p->vNodeStarts = pMan->vNodeStarts; pMan->vNodeStarts = NULL; - p->vCutPairs = pMan->vCutPairs; pMan->vCutPairs = NULL; - - // prepare storage for cuts - p->vCutsNew = Vec_PtrAlloc( p->pParams->nIdsMax ); - Vec_PtrFill( p->vCutsNew, p->pParams->nIdsMax, NULL ); - p->vCuts0 = Vec_PtrAlloc( 100 ); - p->vCuts1 = Vec_PtrAlloc( 100 ); - - // entry size - p->EntrySize = sizeof(Cut_Cut_t) + p->pParams->nVarsMax * sizeof(int); - if ( p->pParams->fTruth ) - { - if ( p->pParams->nVarsMax > 8 ) - { - p->pParams->fTruth = 0; - printf( "Skipping computation of truth table for more than 8 inputs.\n" ); - } - else - { - p->nTruthWords = Cut_TruthWords( p->pParams->nVarsMax ); - p->EntrySize += p->nTruthWords * sizeof(unsigned); - } - } - // memory for cuts - p->pMmCuts = Extra_MmFixedStart( p->EntrySize ); - return p; -} -/**Function************************************************************* - - Synopsis [Stop the cut oracle.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_OracleStop( Cut_Oracle_t * p ) -{ - Cut_Cut_t * pCut; - int i; - -// if ( p->pParams->fVerbose ) - { - printf( "Cut computation statistics with oracle:\n" ); - printf( "Current cuts = %8d. (Trivial = %d.)\n", p->nCuts-p->nCutsTriv, p->nCutsTriv ); - PRT( "Total time ", p->timeTotal ); - } - - Vec_PtrForEachEntry( p->vCutsNew, pCut, i ) - if ( pCut != NULL ) - { - int k = 0; - } - if ( p->vCuts0 ) Vec_PtrFree( p->vCuts0 ); - if ( p->vCuts1 ) Vec_PtrFree( p->vCuts1 ); - if ( p->vCutsNew ) Vec_PtrFree( p->vCutsNew ); - if ( p->vFanCounts ) Vec_IntFree( p->vFanCounts ); - - if ( p->vNodeCuts ) Vec_IntFree( p->vNodeCuts ); - if ( p->vNodeStarts ) Vec_IntFree( p->vNodeStarts ); - if ( p->vCutPairs ) Vec_IntFree( p->vCutPairs ); - - Extra_MmFixedStop( p->pMmCuts ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_OracleSetFanoutCounts( Cut_Oracle_t * p, Vec_Int_t * vFanCounts ) -{ - p->vFanCounts = vFanCounts; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_OracleReadDrop( Cut_Oracle_t * p ) -{ - return p->pParams->fDrop; -} - -/**Function************************************************************* - - Synopsis [Sets the trivial cut for the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node ) -{ - assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL ); - Vec_PtrWriteEntry( p->vCutsNew, Node, Cut_CutTriv(p, Node) ); -} - - - -/**Function************************************************************* - - Synopsis [Allocates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutStart( Cut_Oracle_t * p ) -{ - Cut_Cut_t * pCut; - // cut allocation - pCut = (Cut_Cut_t *)Extra_MmFixedEntryFetch( p->pMmCuts ); - memset( pCut, 0, sizeof(Cut_Cut_t) ); - pCut->nVarsMax = p->pParams->nVarsMax; - pCut->fSimul = p->fSimul; - p->nCuts++; - return pCut; -} - -/**Function************************************************************* - - Synopsis [Creates the trivial cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutTriv( Cut_Oracle_t * p, int Node ) -{ - Cut_Cut_t * pCut; - pCut = Cut_CutStart( p ); - pCut->nLeaves = 1; - pCut->pLeaves[0] = Node; - if ( p->pParams->fTruth ) - { - unsigned * pTruth = Cut_CutReadTruth(pCut); - int i; - for ( i = 0; i < p->nTruthWords; i++ ) - pTruth[i] = 0xAAAAAAAA; - } - p->nCutsTriv++; - return pCut; -} - -/**Function************************************************************* - - Synopsis [Merges two cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_CutMerge( Cut_Oracle_t * p, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1 ) -{ - Cut_Cut_t * pCut; - int Limit, i, k, c; - // create the leaves of the new cut - pCut = Cut_CutStart( p ); - Limit = p->pParams->nVarsMax; - for ( i = k = c = 0; c < Limit; c++ ) - { - if ( k == (int)pCut1->nLeaves ) - { - if ( i == (int)pCut0->nLeaves ) - { - pCut->nLeaves = c; - return pCut; - } - pCut->pLeaves[c] = pCut0->pLeaves[i++]; - continue; - } - if ( i == (int)pCut0->nLeaves ) - { - if ( k == (int)pCut1->nLeaves ) - { - pCut->nLeaves = c; - return pCut; - } - pCut->pLeaves[c] = pCut1->pLeaves[k++]; - continue; - } - if ( pCut0->pLeaves[i] < pCut1->pLeaves[k] ) - { - pCut->pLeaves[c] = pCut0->pLeaves[i++]; - continue; - } - if ( pCut0->pLeaves[i] > pCut1->pLeaves[k] ) - { - pCut->pLeaves[c] = pCut1->pLeaves[k++]; - continue; - } - pCut->pLeaves[c] = pCut0->pLeaves[i++]; - k++; - } - assert( i == (int)pCut0->nLeaves && k == (int)pCut1->nLeaves ); - pCut->nLeaves = c; - return pCut; -} - -/**Function************************************************************* - - Synopsis [Reconstruct the cuts of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 ) -{ - Cut_Cut_t * pList = NULL, ** ppTail = &pList; - Cut_Cut_t * pCut, * pCut0, * pCut1, * pList0, * pList1; - int iCutStart, nCuts, i, Entry; - int clk = clock(); - - // get the cuts of the children - pList0 = Vec_PtrEntry( p->vCutsNew, Node0 ); - pList1 = Vec_PtrEntry( p->vCutsNew, Node1 ); - assert( pList0 && pList1 ); - - // get the complemented attribute of the cut - p->fSimul = (fCompl0 ^ pList0->fSimul) & (fCompl1 ^ pList1->fSimul); - - // collect the cuts - Vec_PtrClear( p->vCuts0 ); - Cut_ListForEachCut( pList0, pCut ) - Vec_PtrPush( p->vCuts0, pCut ); - Vec_PtrClear( p->vCuts1 ); - Cut_ListForEachCut( pList1, pCut ) - Vec_PtrPush( p->vCuts1, pCut ); - - // get the first and last cuts of this node - nCuts = Vec_IntEntry(p->vNodeCuts, Node); - iCutStart = Vec_IntEntry(p->vNodeStarts, Node); - - // create trivial cut - assert( Vec_IntEntry(p->vCutPairs, iCutStart) == 0 ); - pCut = Cut_CutTriv( p, Node ); - *ppTail = pCut; - ppTail = &pCut->pNext; - // create other cuts - for ( i = 1; i < nCuts; i++ ) - { - Entry = Vec_IntEntry( p->vCutPairs, iCutStart + i ); - pCut0 = Vec_PtrEntry( p->vCuts0, Entry & 0xFFFF ); - pCut1 = Vec_PtrEntry( p->vCuts1, Entry >> 16 ); - pCut = Cut_CutMerge( p, pCut0, pCut1 ); - *ppTail = pCut; - ppTail = &pCut->pNext; - // compute the truth table - if ( p->pParams->fTruth ) - Cut_TruthComputeOld( pCut, pCut0, pCut1, fCompl0, fCompl1 ); - } - *ppTail = NULL; - - // write the new cut - assert( Vec_PtrEntry( p->vCutsNew, Node ) == NULL ); - Vec_PtrWriteEntry( p->vCutsNew, Node, pList ); -p->timeTotal += clock() - clk; - return pList; -} - -/**Function************************************************************* - - Synopsis [Deallocates the cuts at the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_OracleFreeCuts( Cut_Oracle_t * p, int Node ) -{ - Cut_Cut_t * pList, * pCut, * pCut2; - pList = Vec_PtrEntry( p->vCutsNew, Node ); - if ( pList == NULL ) - return; - Cut_ListForEachCutSafe( pList, pCut, pCut2 ) - Extra_MmFixedEntryRecycle( p->pMmCuts, (char *)pCut ); - Vec_PtrWriteEntry( p->vCutsNew, Node, pList ); -} - -/**Function************************************************************* - - Synopsis [Consider dropping cuts if they are useless by now.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node ) -{ - int nFanouts; - assert( p->vFanCounts ); - nFanouts = Vec_IntEntry( p->vFanCounts, Node ); - assert( nFanouts > 0 ); - if ( --nFanouts == 0 ) - Cut_OracleFreeCuts( p, Node ); - Vec_IntWriteEntry( p->vFanCounts, Node, nFanouts ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/cut/cutPre22.c b/src/opt/cut/cutPre22.c deleted file mode 100644 index 5cb87a9c..00000000 --- a/src/opt/cut/cutPre22.c +++ /dev/null @@ -1,988 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutPre22.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Precomputes truth tables for the 2x2 macro cell.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutPre22.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cutInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define CUT_CELL_MVAR 9 - -typedef struct Cut_Cell_t_ Cut_Cell_t; -typedef struct Cut_CMan_t_ Cut_CMan_t; - -struct Cut_Cell_t_ -{ - Cut_Cell_t * pNext; // pointer to the next cell in the table - Cut_Cell_t * pNextVar; // pointer to the next cell of this support size - Cut_Cell_t * pParent; // pointer to the cell used to derive this one - int nUsed; // the number of times the cell is used - char Box[4]; // functions in the boxes - unsigned nVars : 4; // the number of variables - unsigned CrossBar0 : 4; // the variable set equal - unsigned CrossBar1 : 4; // the variable set equal - unsigned CrossBarPhase : 2; // the phase of the cross bar (0, 1, or 2) - unsigned CanonPhase : 18; // the canonical phase - char CanonPerm[CUT_CELL_MVAR+3]; // semicanonical permutation - short Store[2*CUT_CELL_MVAR]; // minterm counts in the cofactors - unsigned uTruth[1<<(CUT_CELL_MVAR-5)]; // the current truth table -}; - -struct Cut_CMan_t_ -{ - // storage for canonical cells - Extra_MmFixed_t * pMem; - st_table * tTable; - Cut_Cell_t * pSameVar[CUT_CELL_MVAR+1]; - // elementary truth tables - unsigned uInputs[CUT_CELL_MVAR][1<<(CUT_CELL_MVAR-5)]; - // temporary truth tables - unsigned uTemp1[22][1<<(CUT_CELL_MVAR-5)]; - unsigned uTemp2[22][1<<(CUT_CELL_MVAR-5)]; - unsigned uTemp3[22][1<<(CUT_CELL_MVAR-5)]; - unsigned uFinal[1<<(CUT_CELL_MVAR-5)]; - unsigned puAux[1<<(CUT_CELL_MVAR-5)]; - // statistical variables - int nTotal; - int nGood; - int nVarCounts[CUT_CELL_MVAR+1]; - int nSymGroups[CUT_CELL_MVAR+1]; - int nSymGroupsE[CUT_CELL_MVAR+1]; - int timeCanon; - int timeSupp; - int timeTable; - int nCellFound; - int nCellNotFound; -}; - -// NP-classes of functions of 3 variables (22) -static char * s_NP3[22] = { - " 0\n", // 00 const 0 // 0 vars - " 1\n", // 01 const 1 // 0 vars - "1 1\n", // 02 a // 1 vars - "11 1\n", // 03 ab // 2 vars - "11 0\n", // 04 (ab)' // 2 vars - "10 1\n01 1\n", // 05 a<+>b // 2 vars - "111 1\n", // 06 0s abc // 3 vars - "111 0\n", // 07 (abc)' // - "11- 1\n1-1 1\n", // 08 1p a(b+c) // - "11- 0\n1-1 0\n", // 09 (a(b+c))' // - "111 1\n100 1\n010 1\n001 1\n", // 10 2s a<+>b<+>c // - "10- 0\n1-0 0\n011 0\n", // 11 3p a<+>bc // - "101 1\n110 1\n", // 12 4p a(b<+>c) // - "101 0\n110 0\n", // 13 (a(b<+>c))' // - "11- 1\n1-1 1\n-11 1\n", // 14 5s ab+bc+ac // - "111 1\n000 1\n", // 15 6s abc+a'b'c' // - "111 0\n000 0\n", // 16 (abc+a'b'c')' // - "11- 1\n-11 1\n0-1 1\n", // 17 7 ab+bc+a'c // - "011 1\n101 1\n110 1\n", // 18 8s a'bc+ab'c+abc' // - "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' // - "100 1\n-11 1\n", // 20 9p ab'c'+bc // - "100 0\n-11 0\n" // 21 (ab'c'+bc)' // -}; - -// NP-classes of functions of 3 variables (22) -static char * s_NP3Names[22] = { - " const 0 ", - " const 1 ", - " a ", - " ab ", - " (ab)' ", - " a<+>b ", - "0s abc ", - " (abc)' ", - "1p a(b+c) ", - " (a(b+c))' ", - "2s a<+>b<+>c ", - "3p a<+>bc ", - "4p a(b<+>c) ", - " (a(b<+>c))' ", - "5s ab+bc+ac ", - "6s abc+a'b'c' ", - " (abc+a'b'c')' ", - "7 ab+bc+a'c ", - "8s a'bc+ab'c+abc' ", - " (a'bc+ab'c+abc')' ", - "9p ab'c'+bc ", - " (ab'c'+bc)' " -}; - -// the number of variables in each function -static int s_NP3VarNums[22] = { 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; - -// NPN classes of functions of exactly 3 inputs (10) -static int s_NPNe3[10] = { 6, 8, 10, 11, 12, 14, 15, 17, 18, 20 }; - -// NPN classes of functions of exactly 3 inputs that are symmetric (5) -static int s_NPNe3s[10] = { 6, 10, 14, 15, 18 }; - -// NPN classes of functions of exactly 3 inputs (4) -static int s_NPNe3p[10] = { 8, 11, 12, 20 }; - -static Cut_CMan_t * Cut_CManStart(); -static void Cut_CManStop( Cut_CMan_t * p ); -static void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type ); -static void Cut_CellCanonicize( Cut_CMan_t * p, Cut_Cell_t * pCell ); -static int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell ); -static void Cut_CellSuppMin( Cut_Cell_t * pCell ); -static void Cut_CellCrossBar( Cut_Cell_t * pCell ); - - -static Cut_CMan_t * s_pCMan = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start the precomputation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CellLoad() -{ - FILE * pFile; - char * pFileName = "cells22_daomap_iwls.txt"; - char pString[1000]; - Cut_CMan_t * p; - Cut_Cell_t * pCell; - int Length; //, i; - pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - printf( "Cannot open file \"%s\".\n", pFileName ); - return; - } - // start the manager - p = Cut_CManStart(); - // load truth tables - while ( fgets(pString, 1000, pFile) ) - { - Length = strlen(pString); - pString[Length--] = 0; - if ( Length == 0 ) - continue; - // derive the cell - pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); - memset( pCell, 0, sizeof(Cut_Cell_t) ); - pCell->nVars = Extra_Base2Log(Length*4); - pCell->nUsed = 1; -// Extra_TruthCopy( pCell->uTruth, pTruth, nVars ); - Extra_ReadHexadecimal( pCell->uTruth, pString, pCell->nVars ); - Cut_CellSuppMin( pCell ); -/* - // set the elementary permutation - for ( i = 0; i < (int)pCell->nVars; i++ ) - pCell->CanonPerm[i] = i; - // canonicize - pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); -*/ - // add to the table - p->nTotal++; - -// Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); printf( "\n" ); -// if ( p->nTotal == 500 ) -// break; - - if ( !Cut_CellTableLookup( p, pCell ) ) // new cell - p->nGood++; - } - printf( "Read %d cells from file \"%s\". Added %d cells to the table.\n", p->nTotal, pFileName, p->nGood ); - fclose( pFile ); -// return p; -} - -/**Function************************************************************* - - Synopsis [Precomputes truth tables for the 2x2 macro cell.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CellPrecompute() -{ - Cut_CMan_t * p; - Cut_Cell_t * pCell, * pTemp; - int i1, i2, i3, i, j, k, c, clk = clock(), clk2 = clock(); - - p = Cut_CManStart(); - - // precompute truth tables - for ( i = 0; i < 22; i++ ) - Cut_CellTruthElem( p->uInputs[0], p->uInputs[1], p->uInputs[2], p->uTemp1[i], 9, i ); - for ( i = 0; i < 22; i++ ) - Cut_CellTruthElem( p->uInputs[3], p->uInputs[4], p->uInputs[5], p->uTemp2[i], 9, i ); - for ( i = 0; i < 22; i++ ) - Cut_CellTruthElem( p->uInputs[6], p->uInputs[7], p->uInputs[8], p->uTemp3[i], 9, i ); -/* - if ( k == 8 && ((i1 == 6 && i2 == 14 && i3 == 20) || (i1 == 20 && i2 == 6 && i3 == 14)) ) - { - Extra_PrintBinary( stdout, &pCell->CanonPhase, pCell->nVars+1 ); printf( " : " ); - for ( i = 0; i < pCell->nVars; i++ ) - printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); - Extra_PrintHexadecimal( stdout, pCell->uTruth, pCell->nVars ); - printf( "\n" ); - } -*/ -/* - // go through symmetric roots - for ( k = 0; k < 5; k++ ) - for ( i1 = 0; i1 < 22; i1++ ) - for ( i2 = i1; i2 < 22; i2++ ) - for ( i3 = i2; i3 < 22; i3++ ) - { - // derive the cell - pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); - memset( pCell, 0, sizeof(Cut_Cell_t) ); - pCell->nVars = 9; - pCell->Box[0] = s_NPNe3s[k]; - pCell->Box[1] = i1; - pCell->Box[2] = i2; - pCell->Box[3] = i3; - // fill in the truth table - Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3s[k] ); - // canonicize - Cut_CellCanonicize( pCell ); - - // add to the table - p->nTotal++; - if ( Cut_CellTableLookup( p, pCell ) ) // already exists - Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); - else - p->nGood++; - } - - // go through partially symmetric roots - for ( k = 0; k < 4; k++ ) - for ( i1 = 0; i1 < 22; i1++ ) - for ( i2 = 0; i2 < 22; i2++ ) - for ( i3 = i2; i3 < 22; i3++ ) - { - // derive the cell - pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); - memset( pCell, 0, sizeof(Cut_Cell_t) ); - pCell->nVars = 9; - pCell->Box[0] = s_NPNe3p[k]; - pCell->Box[1] = i1; - pCell->Box[2] = i2; - pCell->Box[3] = i3; - // fill in the truth table - Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3p[k] ); - // canonicize - Cut_CellCanonicize( pCell ); - - // add to the table - p->nTotal++; - if ( Cut_CellTableLookup( p, pCell ) ) // already exists - Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); - else - p->nGood++; - } - - // go through non-symmetric functions - for ( i1 = 0; i1 < 22; i1++ ) - for ( i2 = 0; i2 < 22; i2++ ) - for ( i3 = 0; i3 < 22; i3++ ) - { - // derive the cell - pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); - memset( pCell, 0, sizeof(Cut_Cell_t) ); - pCell->nVars = 9; - pCell->Box[0] = 17; - pCell->Box[1] = i1; - pCell->Box[2] = i2; - pCell->Box[3] = i3; - // fill in the truth table - Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, 17 ); - // canonicize - Cut_CellCanonicize( pCell ); - - // add to the table - p->nTotal++; - if ( Cut_CellTableLookup( p, pCell ) ) // already exists - Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); - else - p->nGood++; - } -*/ - - // go through non-symmetric functions - for ( k = 0; k < 10; k++ ) - for ( i1 = 0; i1 < 22; i1++ ) - for ( i2 = 0; i2 < 22; i2++ ) - for ( i3 = 0; i3 < 22; i3++ ) - { - // derive the cell - pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); - memset( pCell, 0, sizeof(Cut_Cell_t) ); - pCell->nVars = 9; - pCell->Box[0] = s_NPNe3[k]; - pCell->Box[1] = i1; - pCell->Box[2] = i2; - pCell->Box[3] = i3; - // set the elementary permutation - for ( i = 0; i < (int)pCell->nVars; i++ ) - pCell->CanonPerm[i] = i; - // fill in the truth table - Cut_CellTruthElem( p->uTemp1[i1], p->uTemp2[i2], p->uTemp3[i3], pCell->uTruth, 9, s_NPNe3[k] ); - // minimize the support - Cut_CellSuppMin( pCell ); - - // canonicize - pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); - - // add to the table - p->nTotal++; - if ( Cut_CellTableLookup( p, pCell ) ) // already exists - Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); - else - { - p->nGood++; - p->nVarCounts[pCell->nVars]++; - - if ( pCell->nVars ) - for ( i = 0; i < (int)pCell->nVars-1; i++ ) - { - if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric - continue; - // i and i+1 can be symmetric - // find the end of this group - for ( j = i+1; j < (int)pCell->nVars; j++ ) - if ( pCell->Store[2*i] != pCell->Store[2*j] ) - break; - - if ( pCell->Store[2*i] == pCell->Store[2*i+1] ) - p->nSymGroupsE[j-i]++; - else - p->nSymGroups[j-i]++; - i = j - 1; - } -/* - if ( pCell->nVars == 3 ) - { - Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" ); - for ( i = 0; i < (int)pCell->nVars; i++ ) - printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); - printf( "\n" ); - } -*/ - } - } - - printf( "BASIC: Total = %d. Good = %d. Entry = %d. ", p->nTotal, p->nGood, sizeof(Cut_Cell_t) ); - PRT( "Time", clock() - clk ); - printf( "Cells: " ); - for ( i = 0; i <= 9; i++ ) - printf( "%d=%d ", i, p->nVarCounts[i] ); - printf( "\nDiffs: " ); - for ( i = 0; i <= 9; i++ ) - printf( "%d=%d ", i, p->nSymGroups[i] ); - printf( "\nEquals: " ); - for ( i = 0; i <= 9; i++ ) - printf( "%d=%d ", i, p->nSymGroupsE[i] ); - printf( "\n" ); - - // continue adding new cells using support - for ( k = CUT_CELL_MVAR; k > 3; k-- ) - { - for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) - for ( i1 = 0; i1 < k; i1++ ) - for ( i2 = i1+1; i2 < k; i2++ ) - for ( c = 0; c < 3; c++ ) - { - // derive the cell - pCell = (Cut_Cell_t *)Extra_MmFixedEntryFetch( p->pMem ); - memset( pCell, 0, sizeof(Cut_Cell_t) ); - pCell->nVars = pTemp->nVars; - pCell->pParent = pTemp; - // set the elementary permutation - for ( i = 0; i < (int)pCell->nVars; i++ ) - pCell->CanonPerm[i] = i; - // fill in the truth table - Extra_TruthCopy( pCell->uTruth, pTemp->uTruth, pTemp->nVars ); - // create the cross-bar - pCell->CrossBar0 = i1; - pCell->CrossBar1 = i2; - pCell->CrossBarPhase = c; - Cut_CellCrossBar( pCell ); - // minimize the support -//clk2 = clock(); - Cut_CellSuppMin( pCell ); -//p->timeSupp += clock() - clk2; - // canonicize -//clk2 = clock(); - pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); -//p->timeCanon += clock() - clk2; - - // add to the table -//clk2 = clock(); - p->nTotal++; - if ( Cut_CellTableLookup( p, pCell ) ) // already exists - Extra_MmFixedEntryRecycle( p->pMem, (char *)pCell ); - else - { - p->nGood++; - p->nVarCounts[pCell->nVars]++; - - for ( i = 0; i < (int)pCell->nVars-1; i++ ) - { - if ( pCell->Store[2*i] != pCell->Store[2*(i+1)] ) // i and i+1 cannot be symmetric - continue; - // i and i+1 can be symmetric - // find the end of this group - for ( j = i+1; j < (int)pCell->nVars; j++ ) - if ( pCell->Store[2*i] != pCell->Store[2*j] ) - break; - - if ( pCell->Store[2*i] == pCell->Store[2*i+1] ) - p->nSymGroupsE[j-i]++; - else - p->nSymGroups[j-i]++; - i = j - 1; - } -/* - if ( pCell->nVars == 3 ) - { - Extra_PrintBinary( stdout, pCell->uTruth, 32 ); printf( "\n" ); - for ( i = 0; i < (int)pCell->nVars; i++ ) - printf( "%d=%d/%d ", pCell->CanonPerm[i], pCell->Store[2*i], pCell->Store[2*i+1] ); - printf( "\n" ); - } -*/ - } -//p->timeTable += clock() - clk2; - } - - printf( "VAR %d: Total = %d. Good = %d. Entry = %d. ", k, p->nTotal, p->nGood, sizeof(Cut_Cell_t) ); - PRT( "Time", clock() - clk ); - printf( "Cells: " ); - for ( i = 0; i <= 9; i++ ) - printf( "%d=%d ", i, p->nVarCounts[i] ); - printf( "\nDiffs: " ); - for ( i = 0; i <= 9; i++ ) - printf( "%d=%d ", i, p->nSymGroups[i] ); - printf( "\nEquals: " ); - for ( i = 0; i <= 9; i++ ) - printf( "%d=%d ", i, p->nSymGroupsE[i] ); - printf( "\n" ); - } -// printf( "\n" ); - PRT( "Supp ", p->timeSupp ); - PRT( "Canon", p->timeCanon ); - PRT( "Table", p->timeTable ); -// Cut_CManStop( p ); -} - -/**Function************************************************************* - - Synopsis [Check the table.] - - Description [Returns 1 if such a truth table already exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_CellTableLookup( Cut_CMan_t * p, Cut_Cell_t * pCell ) -{ - Cut_Cell_t ** pSlot, * pTemp; - unsigned Hash; - Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum( pCell->nVars ) ); - if ( !st_find_or_add( p->tTable, (char *)Hash, (char ***)&pSlot ) ) - *pSlot = NULL; - for ( pTemp = *pSlot; pTemp; pTemp = pTemp->pNext ) - { - if ( pTemp->nVars != pCell->nVars ) - continue; - if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) ) - return 1; - } - // the entry is new - pCell->pNext = *pSlot; - *pSlot = pCell; - // add it to the variable support list - pCell->pNextVar = p->pSameVar[pCell->nVars]; - p->pSameVar[pCell->nVars] = pCell; - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CellSuppMin( Cut_Cell_t * pCell ) -{ - static unsigned uTemp[1<<(CUT_CELL_MVAR-5)]; - unsigned * pIn, * pOut, * pTemp; - int i, k, Counter, Temp; - - // go backward through the support variables and remove redundant - for ( k = pCell->nVars - 1; k >= 0; k-- ) - if ( !Extra_TruthVarInSupport(pCell->uTruth, pCell->nVars, k) ) - { - // shift all the variables above this one - Counter = 0; - pIn = pCell->uTruth; pOut = uTemp; - for ( i = k; i < (int)pCell->nVars - 1; i++ ) - { - Extra_TruthSwapAdjacentVars( pOut, pIn, pCell->nVars, i ); - pTemp = pIn; pIn = pOut; pOut = pTemp; - // swap the support vars - Temp = pCell->CanonPerm[i]; - pCell->CanonPerm[i] = pCell->CanonPerm[i+1]; - pCell->CanonPerm[i+1] = Temp; - Counter++; - } - // return the function back into its place - if ( Counter & 1 ) - Extra_TruthCopy( pOut, pIn, pCell->nVars ); - // remove one variable - pCell->nVars--; -// Extra_PrintBinary( stdout, pCell->uTruth, (1<nVars) ); printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CellCrossBar( Cut_Cell_t * pCell ) -{ - static unsigned uTemp0[1<<(CUT_CELL_MVAR-5)]; - static unsigned uTemp1[1<<(CUT_CELL_MVAR-5)]; - Extra_TruthCopy( uTemp0, pCell->uTruth, pCell->nVars ); - Extra_TruthCopy( uTemp1, pCell->uTruth, pCell->nVars ); - if ( pCell->CanonPhase == 0 ) - { - Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 ); - Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 ); - Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 ); - Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 ); - } - else if ( pCell->CanonPhase == 1 ) - { - Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar0 ); - Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar1 ); - Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar0 ); - Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar1 ); - } - else if ( pCell->CanonPhase == 2 ) - { - Extra_TruthCofactor0( uTemp0, pCell->nVars, pCell->CrossBar0 ); - Extra_TruthCofactor1( uTemp0, pCell->nVars, pCell->CrossBar1 ); - Extra_TruthCofactor1( uTemp1, pCell->nVars, pCell->CrossBar0 ); - Extra_TruthCofactor0( uTemp1, pCell->nVars, pCell->CrossBar1 ); - } - else assert( 0 ); - Extra_TruthMux( pCell->uTruth, uTemp0, uTemp1, pCell->nVars, pCell->CrossBar0 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CellTruthElem( unsigned * InA, unsigned * InB, unsigned * InC, unsigned * pOut, int nVars, int Type ) -{ - int nWords = Extra_TruthWordNum( nVars ); - int i; - - assert( Type < 22 ); - switch ( Type ) - { - // " 0\n", // 00 const 0 - case 0: - for ( i = 0; i < nWords; i++ ) - pOut[i] = 0; - return; - // " 1\n", // 01 const 1 - case 1: - for ( i = 0; i < nWords; i++ ) - pOut[i] = 0xFFFFFFFF; - return; - // "1 1\n", // 02 a - case 2: - for ( i = 0; i < nWords; i++ ) - pOut[i] = InA[i]; - return; - // "11 1\n", // 03 ab - case 3: - for ( i = 0; i < nWords; i++ ) - pOut[i] = InA[i] & InB[i]; - return; - // "11 0\n", // 04 (ab)' - case 4: - for ( i = 0; i < nWords; i++ ) - pOut[i] = ~(InA[i] & InB[i]); - return; - // "10 1\n01 1\n", // 05 a<+>b - case 5: - for ( i = 0; i < nWords; i++ ) - pOut[i] = InA[i] ^ InB[i]; - return; - // "111 1\n", // 06 + abc - case 6: - for ( i = 0; i < nWords; i++ ) - pOut[i] = InA[i] & InB[i] & InC[i]; - return; - // "111 0\n", // 07 (abc)' - case 7: - for ( i = 0; i < nWords; i++ ) - pOut[i] = ~(InA[i] & InB[i] & InC[i]); - return; - // "11- 1\n1-1 1\n", // 08 + a(b+c) - case 8: - for ( i = 0; i < nWords; i++ ) - pOut[i] = InA[i] & (InB[i] | InC[i]); - return; - // "11- 0\n1-1 0\n", // 09 (a(b+c))' - case 9: - for ( i = 0; i < nWords; i++ ) - pOut[i] = ~(InA[i] & (InB[i] | InC[i])); - return; - // "111 1\n100 1\n010 1\n001 1\n", // 10 + a<+>b<+>c - case 10: - for ( i = 0; i < nWords; i++ ) - pOut[i] = InA[i] ^ InB[i] ^ InC[i]; - return; - // "10- 0\n1-0 0\n011 0\n", // 11 + a<+>bc - case 11: - for ( i = 0; i < nWords; i++ ) - pOut[i] = InA[i] ^ (InB[i] & InC[i]); - return; - // "101 1\n110 1\n", // 12 + a(b<+>c) - case 12: - for ( i = 0; i < nWords; i++ ) - pOut[i] = InA[i] & (InB[i] ^ InC[i]); - return; - // "101 0\n110 0\n", // 13 (a(b<+>c))' - case 13: - for ( i = 0; i < nWords; i++ ) - pOut[i] = ~(InA[i] & (InB[i] ^ InC[i])); - return; - // "11- 1\n1-1 1\n-11 1\n", // 14 + ab+bc+ac - case 14: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (InA[i] & InC[i]); - return; - // "111 1\n000 1\n", // 15 + abc+a'b'c' - case 15: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i]); - return; - // "111 0\n000 0\n", // 16 (abc+a'b'c')' - case 16: - for ( i = 0; i < nWords; i++ ) - pOut[i] = ~((InA[i] & InB[i] & InC[i]) | (~InA[i] & ~InB[i] & ~InC[i])); - return; - // "11- 1\n-11 1\n0-1 1\n", // 17 + ab+bc+a'c - case 17: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (InA[i] & InB[i]) | (InB[i] & InC[i]) | (~InA[i] & InC[i]); - return; - // "011 1\n101 1\n110 1\n", // 18 + a'bc+ab'c+abc' - case 18: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i]); - return; - // "011 0\n101 0\n110 0\n", // 19 (a'bc+ab'c+abc')' - case 19: - for ( i = 0; i < nWords; i++ ) - pOut[i] = ~((~InA[i] & InB[i] & InC[i]) | (InA[i] & ~InB[i] & InC[i]) | (InA[i] & InB[i] & ~InC[i])); - return; - // "100 1\n-11 1\n", // 20 + ab'c'+bc - case 20: - for ( i = 0; i < nWords; i++ ) - pOut[i] = (InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i]); - return; - // "100 0\n-11 0\n" // 21 (ab'c'+bc)' - case 21: - for ( i = 0; i < nWords; i++ ) - pOut[i] = ~((InA[i] & ~InB[i] & ~InC[i]) | (InB[i] & InC[i])); - return; - } -} - - -/**Function************************************************************* - - Synopsis [Start the precomputation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Cut_CMan_t * Cut_CManStart() -{ - Cut_CMan_t * p; - int i, k; - // start the manager - assert( sizeof(unsigned) == 4 ); - p = ALLOC( Cut_CMan_t, 1 ); - memset( p, 0, sizeof(Cut_CMan_t) ); - // start the table and the memory manager - p->tTable = st_init_table(st_ptrcmp,st_ptrhash); - p->pMem = Extra_MmFixedStart( sizeof(Cut_Cell_t) ); - // set elementary truth tables - for ( k = 0; k < CUT_CELL_MVAR; k++ ) - for ( i = 0; i < (1<uInputs[k][i>>5] |= (1 << (i&31)); - s_pCMan = p; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CManStop( Cut_CMan_t * p ) -{ - st_free_table( p->tTable ); - Extra_MmFixedStop( p->pMem ); - free( p ); -} -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_CellIsRunning() -{ - return s_pCMan != NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_CellDumpToFile() -{ - FILE * pFile; - Cut_CMan_t * p = s_pCMan; - Cut_Cell_t * pTemp; - char * pFileName = "celllib22.txt"; - int NumUsed[10][5] = {{0}}; - int BoxUsed[22][5] = {{0}}; - int i, k, Counter; - int clk = clock(); - - if ( p == NULL ) - { - printf( "Cut_CellDumpToFile: Cell manager is not defined.\n" ); - return; - } - - // count the number of cells used - for ( k = CUT_CELL_MVAR; k >= 0; k-- ) - { - for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) - { - if ( pTemp->nUsed == 0 ) - NumUsed[k][0]++; - else if ( pTemp->nUsed < 10 ) - NumUsed[k][1]++; - else if ( pTemp->nUsed < 100 ) - NumUsed[k][2]++; - else if ( pTemp->nUsed < 1000 ) - NumUsed[k][3]++; - else - NumUsed[k][4]++; - - for ( i = 0; i < 4; i++ ) - if ( pTemp->nUsed == 0 ) - BoxUsed[ pTemp->Box[i] ][0]++; - else if ( pTemp->nUsed < 10 ) - BoxUsed[ pTemp->Box[i] ][1]++; - else if ( pTemp->nUsed < 100 ) - BoxUsed[ pTemp->Box[i] ][2]++; - else if ( pTemp->nUsed < 1000 ) - BoxUsed[ pTemp->Box[i] ][3]++; - else - BoxUsed[ pTemp->Box[i] ][4]++; - } - } - - printf( "Functions found = %10d. Functions not found = %10d.\n", p->nCellFound, p->nCellNotFound ); - for ( k = 0; k <= CUT_CELL_MVAR; k++ ) - { - printf( "%3d : ", k ); - for ( i = 0; i < 5; i++ ) - printf( "%8d ", NumUsed[k][i] ); - printf( "\n" ); - } - printf( "Box usage:\n" ); - for ( k = 0; k < 22; k++ ) - { - printf( "%3d : ", k ); - for ( i = 0; i < 5; i++ ) - printf( "%8d ", BoxUsed[k][i] ); - printf( " %s", s_NP3Names[k] ); - printf( "\n" ); - } - - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - printf( "Cut_CellDumpToFile: Cannout open output file.\n" ); - return; - } - - Counter = 0; - for ( k = 0; k <= CUT_CELL_MVAR; k++ ) - { - for ( pTemp = p->pSameVar[k]; pTemp; pTemp = pTemp->pNextVar ) - if ( pTemp->nUsed > 0 ) - { - Extra_PrintHexadecimal( pFile, pTemp->uTruth, (k <= 5? 5 : k) ); - fprintf( pFile, "\n" ); - Counter++; - } - fprintf( pFile, "\n" ); - } - fclose( pFile ); - - printf( "Library composed of %d functions is written into file \"%s\". ", Counter, pFileName ); - - PRT( "Time", clock() - clk ); -} - - -/**Function************************************************************* - - Synopsis [Looks up if the given function exists in the hash table.] - - Description [If the function exists, returns 1, meaning that it can be - implemented using two levels of 3-input LUTs. If the function does not - exist, return 0.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_CellTruthLookup( unsigned * pTruth, int nVars ) -{ - Cut_CMan_t * p = s_pCMan; - Cut_Cell_t * pTemp; - Cut_Cell_t Cell, * pCell = &Cell; - unsigned Hash; - int i; - - // cell manager is not defined - if ( p == NULL ) - { - printf( "Cut_CellTruthLookup: Cell manager is not defined.\n" ); - return 0; - } - - // canonicize - memset( pCell, 0, sizeof(Cut_Cell_t) ); - pCell->nVars = nVars; - Extra_TruthCopy( pCell->uTruth, pTruth, nVars ); - Cut_CellSuppMin( pCell ); - // set the elementary permutation - for ( i = 0; i < (int)pCell->nVars; i++ ) - pCell->CanonPerm[i] = i; - // canonicize - pCell->CanonPhase = Extra_TruthSemiCanonicize( pCell->uTruth, p->puAux, pCell->nVars, pCell->CanonPerm, pCell->Store ); - - - // check if the cell exists - Hash = Extra_TruthHash( pCell->uTruth, Extra_TruthWordNum(pCell->nVars) ); - if ( st_lookup( p->tTable, (char *)Hash, (char **)&pTemp ) ) - { - for ( ; pTemp; pTemp = pTemp->pNext ) - { - if ( pTemp->nVars != pCell->nVars ) - continue; - if ( Extra_TruthIsEqual(pTemp->uTruth, pCell->uTruth, pCell->nVars) ) - { - pTemp->nUsed++; - p->nCellFound++; - return 1; - } - } - } - p->nCellNotFound++; - return 0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/cut/cutSeq.c b/src/opt/cut/cutSeq.c deleted file mode 100644 index d36f94f7..00000000 --- a/src/opt/cut/cutSeq.c +++ /dev/null @@ -1,227 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutSeq.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [K-feasible cut computation package.] - - Synopsis [Sequential cut computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cutInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Shifts all cut leaves of the node by the given number of latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Cut_NodeShiftCutLeaves( Cut_Cut_t * pList, int nLat ) -{ - Cut_Cut_t * pTemp; - int i; - // shift the cuts by as many latches - Cut_ListForEachCut( pList, pTemp ) - { - pTemp->uSign = 0; - for ( i = 0; i < (int)pTemp->nLeaves; i++ ) - { - pTemp->pLeaves[i] += nLat; - pTemp->uSign |= Cut_NodeSign( pTemp->pLeaves[i] ); - } - } -} - -/**Function************************************************************* - - Synopsis [Computes sequential cuts for the node from its fanins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum ) -{ - Cut_List_t Super, * pSuper = &Super; - Cut_Cut_t * pListNew; - int clk; - - // get the number of cuts at the node - p->nNodeCuts = Cut_CutCountList( Cut_NodeReadCutsOld(p, Node) ); - if ( p->nNodeCuts >= p->pParams->nKeepMax ) - return; - - // count only the first visit - if ( p->nNodeCuts == 0 ) - p->nNodes++; - - // store the fanin lists - p->pStore0[0] = Cut_NodeReadCutsOld( p, Node0 ); - p->pStore0[1] = Cut_NodeReadCutsNew( p, Node0 ); - p->pStore1[0] = Cut_NodeReadCutsOld( p, Node1 ); - p->pStore1[1] = Cut_NodeReadCutsNew( p, Node1 ); - - // duplicate the cut lists if fanin nodes are non-standard - if ( Node == Node0 || Node == Node1 || Node0 == Node1 ) - { - p->pStore0[0] = Cut_CutDupList( p, p->pStore0[0] ); - p->pStore0[1] = Cut_CutDupList( p, p->pStore0[1] ); - p->pStore1[0] = Cut_CutDupList( p, p->pStore1[0] ); - p->pStore1[1] = Cut_CutDupList( p, p->pStore1[1] ); - } - - // shift the cuts by as many latches and recompute signatures - if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], nLat0 ); - if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], nLat0 ); - if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], nLat1 ); - if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], nLat1 ); - - // store the original lists for comparison - p->pCompareOld = Cut_NodeReadCutsOld( p, Node ); - p->pCompareNew = Cut_NodeReadCutsNew( p, Node ); - - // merge the old and the new -clk = clock(); - Cut_ListStart( pSuper ); - Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[0], p->pStore1[1], 0, 0 ); - Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[0], 0, 0 ); - Cut_NodeDoComputeCuts( p, pSuper, Node, fCompl0, fCompl1, p->pStore0[1], p->pStore1[1], fTriv, 0 ); - pListNew = Cut_ListFinish( pSuper ); -p->timeMerge += clock() - clk; - - // shift the cuts by as many latches and recompute signatures - if ( Node == Node0 || Node == Node1 || Node0 == Node1 ) - { - Cut_CutRecycleList( p, p->pStore0[0] ); - Cut_CutRecycleList( p, p->pStore0[1] ); - Cut_CutRecycleList( p, p->pStore1[0] ); - Cut_CutRecycleList( p, p->pStore1[1] ); - } - else - { - if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[0], -nLat0 ); - if ( nLat0 ) Cut_NodeShiftCutLeaves( p->pStore0[1], -nLat0 ); - if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[0], -nLat1 ); - if ( nLat1 ) Cut_NodeShiftCutLeaves( p->pStore1[1], -nLat1 ); - } - - // set the lists at the node - if ( CutSetNum >= 0 ) - { - assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL ); - Cut_NodeWriteCutsTemp( p, CutSetNum, pListNew ); - } - else - { - assert( Cut_NodeReadCutsNew(p, Node) == NULL ); - Cut_NodeWriteCutsNew( p, Node, pListNew ); - } - - // mark the node if we exceeded the number of cuts - if ( p->nNodeCuts >= p->pParams->nKeepMax ) - p->nCutsLimit++; -} - -/**Function************************************************************* - - Synopsis [Merges the new cuts with the old cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node ) -{ - Cut_Cut_t * pListOld, * pListNew, * pList; - // get the new cuts - pListNew = Cut_NodeReadCutsNew( p, Node ); - if ( pListNew == NULL ) - return; - Cut_NodeWriteCutsNew( p, Node, NULL ); - // get the old cuts - pListOld = Cut_NodeReadCutsOld( p, Node ); - if ( pListOld == NULL ) - { - Cut_NodeWriteCutsOld( p, Node, pListNew ); - return; - } - // merge the lists - pList = Cut_CutMergeLists( pListOld, pListNew ); - Cut_NodeWriteCutsOld( p, Node, pList ); -} - - -/**Function************************************************************* - - Synopsis [Transfers the temporary cuts to be the new cuts.] - - Description [Returns 1 if something was transferred.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Cut_NodeTempTransferToNew( Cut_Man_t * p, int Node, int CutSetNum ) -{ - Cut_Cut_t * pList; - pList = Cut_NodeReadCutsTemp( p, CutSetNum ); - Cut_NodeWriteCutsTemp( p, CutSetNum, NULL ); - Cut_NodeWriteCutsNew( p, Node, pList ); - return pList != NULL; -} - -/**Function************************************************************* - - Synopsis [Transfers the old cuts to be the new cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_NodeOldTransferToNew( Cut_Man_t * p, int Node ) -{ - Cut_Cut_t * pList; - pList = Cut_NodeReadCutsOld( p, Node ); - Cut_NodeWriteCutsOld( p, Node, NULL ); - Cut_NodeWriteCutsNew( p, Node, pList ); -// Cut_CutListVerify( pList ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/cut/cutTruth.c b/src/opt/cut/cutTruth.c deleted file mode 100644 index c3514ad7..00000000 --- a/src/opt/cut/cutTruth.c +++ /dev/null @@ -1,226 +0,0 @@ -/**CFile**************************************************************** - - FileName [cutTruth.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [K-feasible cut computation package.] - - Synopsis [Incremental truth table computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: cutTruth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "cutInt.h" - -/* - Truth tables computed in this package are represented as bit-strings - stored in the cut data structure. Cuts of any number of inputs have - the truth table with 2^k bits, where k is the max number of cut inputs. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern int nTotal = 0; -extern int nGood = 0; -extern int nEqual = 0; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Cut_TruthPhase( Cut_Cut_t * pCut, Cut_Cut_t * pCut1 ) -{ - unsigned uPhase = 0; - int i, k; - for ( i = k = 0; i < (int)pCut->nLeaves; i++ ) - { - if ( k == (int)pCut1->nLeaves ) - break; - if ( pCut->pLeaves[i] < pCut1->pLeaves[k] ) - continue; - assert( pCut->pLeaves[i] == pCut1->pLeaves[k] ); - uPhase |= (1 << i); - k++; - } - return uPhase; -} - -/**Function************************************************************* - - Synopsis [Performs truth table computation.] - - Description [This procedure cannot be used while recording oracle - because it will overwrite Num0 and Num1.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_TruthNCanonicize( Cut_Cut_t * pCut ) -{ - unsigned uTruth; - unsigned * uCanon2; - char * pPhases2; - assert( pCut->nVarsMax < 6 ); - - // get the direct truth table - uTruth = *Cut_CutReadTruth(pCut); - - // compute the direct truth table - Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); -// uCanon[0] = uCanon2[0]; -// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; -// uPhases[0] = pPhases2[0]; - pCut->uCanon0 = uCanon2[0]; - pCut->Num0 = pPhases2[0]; - - // get the complemented truth table - uTruth = ~*Cut_CutReadTruth(pCut); - - // compute the direct truth table - Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 ); -// uCanon[0] = uCanon2[0]; -// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0]; -// uPhases[0] = pPhases2[0]; - pCut->uCanon1 = uCanon2[0]; - pCut->Num1 = pPhases2[0]; -} - -/**Function************************************************************* - - Synopsis [Performs truth table computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_TruthComputeOld( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) -{ - static unsigned uTruth0[8], uTruth1[8]; - int nTruthWords = Cut_TruthWords( pCut->nVarsMax ); - unsigned * pTruthRes; - int i, uPhase; - - // permute the first table - uPhase = Cut_TruthPhase( pCut, pCut0 ); - Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut0), uPhase, uTruth0 ); - if ( fCompl0 ) - { - for ( i = 0; i < nTruthWords; i++ ) - uTruth0[i] = ~uTruth0[i]; - } - - // permute the second table - uPhase = Cut_TruthPhase( pCut, pCut1 ); - Extra_TruthExpand( pCut->nVarsMax, nTruthWords, Cut_CutReadTruth(pCut1), uPhase, uTruth1 ); - if ( fCompl1 ) - { - for ( i = 0; i < nTruthWords; i++ ) - uTruth1[i] = ~uTruth1[i]; - } - - // write the resulting table - pTruthRes = Cut_CutReadTruth(pCut); - - if ( pCut->fCompl ) - { - for ( i = 0; i < nTruthWords; i++ ) - pTruthRes[i] = ~(uTruth0[i] & uTruth1[i]); - } - else - { - for ( i = 0; i < nTruthWords; i++ ) - pTruthRes[i] = uTruth0[i] & uTruth1[i]; - } -} - -/**Function************************************************************* - - Synopsis [Performs truth table computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Cut_TruthCompute( Cut_Man_t * p, Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, int fCompl0, int fCompl1 ) -{ - // permute the first table - if ( fCompl0 ) - Extra_TruthNot( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax ); - else - Extra_TruthCopy( p->puTemp[0], Cut_CutReadTruth(pCut0), pCut->nVarsMax ); - Extra_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut0) ); - // permute the second table - if ( fCompl1 ) - Extra_TruthNot( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax ); - else - Extra_TruthCopy( p->puTemp[1], Cut_CutReadTruth(pCut1), pCut->nVarsMax ); - Extra_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nLeaves, pCut->nVarsMax, Cut_TruthPhase(pCut, pCut1) ); - // produce the resulting table - if ( pCut->fCompl ) - Extra_TruthNand( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax ); - else - Extra_TruthAnd( Cut_CutReadTruth(pCut), p->puTemp[2], p->puTemp[3], pCut->nVarsMax ); - -// Ivy_TruthTestOne( *Cut_CutReadTruth(pCut) ); - - // quit if no fancy computation is needed - if ( !p->pParams->fFancy ) - return; - - if ( pCut->nLeaves != 7 ) - return; - - // count the total number of truth tables computed - nTotal++; - - // MAPPING INTO ALTERA 6-2 LOGIC BLOCKS - // call this procedure to find the minimum number of common variables in the cofactors - // if this number is less or equal than 3, the cut can be implemented using the 6-2 logic block - if ( Extra_TruthMinCofSuppOverlap( Cut_CutReadTruth(pCut), pCut->nVarsMax, NULL ) <= 4 ) - nGood++; - - // MAPPING INTO ACTEL 2x2 CELLS - // call this procedure to see if a semi-canonical form can be found in the lookup table - // (if it exists, then a two-level 3-input LUT implementation of the cut exists) - // Before this procedure is called, cell manager should be defined by calling - // Cut_CellLoad (make sure file "cells22_daomap_iwls.txt" is available in the working dir) -// if ( Cut_CellIsRunning() && pCut->nVarsMax <= 9 ) -// nGood += Cut_CellTruthLookup( Cut_CutReadTruth(pCut), pCut->nVarsMax ); -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/cut/module.make b/src/opt/cut/module.make deleted file mode 100644 index 132e730b..00000000 --- a/src/opt/cut/module.make +++ /dev/null @@ -1,9 +0,0 @@ -SRC += src/opt/cut/cutApi.c \ - src/opt/cut/cutCut.c \ - src/opt/cut/cutMan.c \ - src/opt/cut/cutMerge.c \ - src/opt/cut/cutNode.c \ - src/opt/cut/cutOracle.c \ - src/opt/cut/cutPre22.c \ - src/opt/cut/cutSeq.c \ - src/opt/cut/cutTruth.c diff --git a/src/opt/dec/dec.h b/src/opt/dec/dec.h deleted file mode 100644 index 41d22649..00000000 --- a/src/opt/dec/dec.h +++ /dev/null @@ -1,719 +0,0 @@ -/**CFile**************************************************************** - - FileName [dec.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [A simple decomposition tree/node data structure and its APIs.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: dec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __DEC_H__ -#define __DEC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Dec_Edge_t_ Dec_Edge_t; -struct Dec_Edge_t_ -{ - unsigned fCompl : 1; // the complemented bit - unsigned Node : 30; // the decomposition node pointed by the edge -}; - -typedef struct Dec_Node_t_ Dec_Node_t; -struct Dec_Node_t_ -{ - Dec_Edge_t eEdge0; // the left child of the node - Dec_Edge_t eEdge1; // the right child of the node - // other info - void * pFunc; // the function of the node (BDD or AIG) - unsigned Level : 14; // the level of this node in the global AIG - // printing info - unsigned fNodeOr : 1; // marks the original OR node - unsigned fCompl0 : 1; // marks the original complemented edge - unsigned fCompl1 : 1; // marks the original complemented edge - // latch info - unsigned nLat0 : 5; // the number of latches on the first edge - unsigned nLat1 : 5; // the number of latches on the second edge - unsigned nLat2 : 5; // the number of latches on the output edge -}; - -typedef struct Dec_Graph_t_ Dec_Graph_t; -struct Dec_Graph_t_ -{ - int fConst; // marks the constant 1 graph - int nLeaves; // the number of leaves - int nSize; // the number of nodes (including the leaves) - int nCap; // the number of allocated nodes - Dec_Node_t * pNodes; // the array of leaves and internal nodes - Dec_Edge_t eRoot; // the pointer to the topmost node -}; - -typedef struct Dec_Man_t_ Dec_Man_t; -struct Dec_Man_t_ -{ - void * pMvcMem; // memory manager for MVC cover (used for factoring) - Vec_Int_t * vCubes; // storage for cubes - Vec_Int_t * vLits; // storage for literals - // precomputation information about 4-variable functions - unsigned short * puCanons; // canonical forms - char * pPhases; // canonical phases - char * pPerms; // canonical permutations - unsigned char * pMap; // mapping of functions into class numbers -}; - - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -// interator throught the leaves -#define Dec_GraphForEachLeaf( pGraph, pLeaf, i ) \ - for ( i = 0; (i < (pGraph)->nLeaves) && (((pLeaf) = Dec_GraphNode(pGraph, i)), 1); i++ ) -// interator throught the internal nodes -#define Dec_GraphForEachNode( pGraph, pAnd, i ) \ - for ( i = (pGraph)->nLeaves; (i < (pGraph)->nSize) && (((pAnd) = Dec_GraphNode(pGraph, i)), 1); i++ ) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== decAbc.c ========================================================*/ -extern Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ); -extern Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ); -extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); -extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain ); -/*=== decFactor.c ========================================================*/ -extern Dec_Graph_t * Dec_Factor( char * pSop ); -/*=== decMan.c ========================================================*/ -extern Dec_Man_t * Dec_ManStart(); -extern void Dec_ManStop( Dec_Man_t * p ); -/*=== decPrint.c ========================================================*/ -extern void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut ); -/*=== decUtil.c ========================================================*/ -extern DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ); -extern unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates an edge pointing to the node in the given polarity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_EdgeCreate( int Node, int fCompl ) -{ - Dec_Edge_t eEdge = { fCompl, Node }; - return eEdge; -} - -/**Function************************************************************* - - Synopsis [Converts the edge into unsigned integer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dec_EdgeToInt( Dec_Edge_t eEdge ) -{ - return (eEdge.Node << 1) | eEdge.fCompl; -} - -/**Function************************************************************* - - Synopsis [Converts unsigned integer into the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_IntToEdge( unsigned Edge ) -{ - return Dec_EdgeCreate( Edge >> 1, Edge & 1 ); -} - -/**Function************************************************************* - - Synopsis [Converts the edge into unsigned integer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline unsigned Dec_EdgeToInt_( Dec_Edge_t eEdge ) -{ - return *(unsigned *)&eEdge; -} - -/**Function************************************************************* - - Synopsis [Converts unsigned integer into the edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_IntToEdge_( unsigned Edge ) -{ - return *(Dec_Edge_t *)&Edge; -} - -/**Function************************************************************* - - Synopsis [Creates a graph with the given number of leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreate( int nLeaves ) -{ - Dec_Graph_t * pGraph; - pGraph = ALLOC( Dec_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Dec_Graph_t) ); - pGraph->nLeaves = nLeaves; - pGraph->nSize = nLeaves; - pGraph->nCap = 2 * nLeaves + 50; - pGraph->pNodes = ALLOC( Dec_Node_t, pGraph->nCap ); - memset( pGraph->pNodes, 0, sizeof(Dec_Node_t) * pGraph->nSize ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates constant 0 graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreateConst0() -{ - Dec_Graph_t * pGraph; - pGraph = ALLOC( Dec_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Dec_Graph_t) ); - pGraph->fConst = 1; - pGraph->eRoot.fCompl = 1; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates constant 1 graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreateConst1() -{ - Dec_Graph_t * pGraph; - pGraph = ALLOC( Dec_Graph_t, 1 ); - memset( pGraph, 0, sizeof(Dec_Graph_t) ); - pGraph->fConst = 1; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates the literal graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Graph_t * Dec_GraphCreateLeaf( int iLeaf, int nLeaves, int fCompl ) -{ - Dec_Graph_t * pGraph; - assert( 0 <= iLeaf && iLeaf < nLeaves ); - pGraph = Dec_GraphCreate( nLeaves ); - pGraph->eRoot.Node = iLeaf; - pGraph->eRoot.fCompl = fCompl; - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Creates a graph with the given number of leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Dec_GraphFree( Dec_Graph_t * pGraph ) -{ - FREE( pGraph->pNodes ); - free( pGraph ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is a constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline bool Dec_GraphIsConst( Dec_Graph_t * pGraph ) -{ - return pGraph->fConst; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is constant 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline bool Dec_GraphIsConst0( Dec_Graph_t * pGraph ) -{ - return pGraph->fConst && pGraph->eRoot.fCompl; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is constant 1.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline bool Dec_GraphIsConst1( Dec_Graph_t * pGraph ) -{ - return pGraph->fConst && !pGraph->eRoot.fCompl; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the graph is complemented.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline bool Dec_GraphIsComplement( Dec_Graph_t * pGraph ) -{ - return pGraph->eRoot.fCompl; -} - -/**Function************************************************************* - - Synopsis [Checks if the graph is complemented.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Dec_GraphComplement( Dec_Graph_t * pGraph ) -{ - pGraph->eRoot.fCompl ^= 1; -} - - -/**Function************************************************************* - - Synopsis [Returns the number of leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphLeaveNum( Dec_Graph_t * pGraph ) -{ - return pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Returns the number of internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphNodeNum( Dec_Graph_t * pGraph ) -{ - return pGraph->nSize - pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphNode( Dec_Graph_t * pGraph, int i ) -{ - return pGraph->pNodes + i; -} - -/**Function************************************************************* - - Synopsis [Returns the pointer to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphNodeLast( Dec_Graph_t * pGraph ) -{ - return pGraph->pNodes + pGraph->nSize - 1; -} - -/**Function************************************************************* - - Synopsis [Returns the number of the given node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphNodeInt( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) -{ - return pNode - pGraph->pNodes; -} - -/**Function************************************************************* - - Synopsis [Check if the graph represents elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline bool Dec_GraphIsVar( Dec_Graph_t * pGraph ) -{ - return pGraph->eRoot.Node < (unsigned)pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Check if the graph represents elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline bool Dec_GraphNodeIsVar( Dec_Graph_t * pGraph, Dec_Node_t * pNode ) -{ - return Dec_GraphNodeInt(pGraph,pNode) < pGraph->nLeaves; -} - -/**Function************************************************************* - - Synopsis [Returns the elementary variable elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphVar( Dec_Graph_t * pGraph ) -{ - assert( Dec_GraphIsVar( pGraph ) ); - return Dec_GraphNode( pGraph, pGraph->eRoot.Node ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of the elementary variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Dec_GraphVarInt( Dec_Graph_t * pGraph ) -{ - assert( Dec_GraphIsVar( pGraph ) ); - return Dec_GraphNodeInt( pGraph, Dec_GraphVar(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Sets the root of the graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Dec_GraphSetRoot( Dec_Graph_t * pGraph, Dec_Edge_t eRoot ) -{ - pGraph->eRoot = eRoot; -} - -/**Function************************************************************* - - Synopsis [Appends a new node to the graph.] - - Description [This procedure is meant for internal use.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Node_t * Dec_GraphAppendNode( Dec_Graph_t * pGraph ) -{ - Dec_Node_t * pNode; - if ( pGraph->nSize == pGraph->nCap ) - { - pGraph->pNodes = REALLOC( Dec_Node_t, pGraph->pNodes, 2 * pGraph->nCap ); - pGraph->nCap = 2 * pGraph->nCap; - } - pNode = pGraph->pNodes + pGraph->nSize++; - memset( pNode, 0, sizeof(Dec_Node_t) ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates an AND node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeAnd( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) -{ - Dec_Node_t * pNode; - // get the new node - pNode = Dec_GraphAppendNode( pGraph ); - // set the inputs and other info - pNode->eEdge0 = eEdge0; - pNode->eEdge1 = eEdge1; - pNode->fCompl0 = eEdge0.fCompl; - pNode->fCompl1 = eEdge1.fCompl; - return Dec_EdgeCreate( pGraph->nSize - 1, 0 ); -} - -/**Function************************************************************* - - Synopsis [Creates an OR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeOr( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1 ) -{ - Dec_Node_t * pNode; - // get the new node - pNode = Dec_GraphAppendNode( pGraph ); - // set the inputs and other info - pNode->eEdge0 = eEdge0; - pNode->eEdge1 = eEdge1; - pNode->fCompl0 = eEdge0.fCompl; - pNode->fCompl1 = eEdge1.fCompl; - // make adjustments for the OR gate - pNode->fNodeOr = 1; - pNode->eEdge0.fCompl = !pNode->eEdge0.fCompl; - pNode->eEdge1.fCompl = !pNode->eEdge1.fCompl; - return Dec_EdgeCreate( pGraph->nSize - 1, 1 ); -} - -/**Function************************************************************* - - Synopsis [Creates an XOR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeXor( Dec_Graph_t * pGraph, Dec_Edge_t eEdge0, Dec_Edge_t eEdge1, int Type ) -{ - Dec_Edge_t eNode0, eNode1, eNode; - if ( Type == 0 ) - { - // derive the first AND - eEdge0.fCompl ^= 1; - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - eEdge0.fCompl ^= 1; - // derive the second AND - eEdge1.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - } - else - { - // derive the first AND - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the second AND - eEdge0.fCompl ^= 1; - eEdge1.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdge0, eEdge1 ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - eNode.fCompl ^= 1; - } - return eNode; -} - -/**Function************************************************************* - - Synopsis [Creates an XOR node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Dec_Edge_t Dec_GraphAddNodeMux( Dec_Graph_t * pGraph, Dec_Edge_t eEdgeC, Dec_Edge_t eEdgeT, Dec_Edge_t eEdgeE, int Type ) -{ - Dec_Edge_t eNode0, eNode1, eNode; - if ( Type == 0 ) - { - // derive the first AND - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); - // derive the second AND - eEdgeC.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - } - else - { - // complement the arguments - eEdgeT.fCompl ^= 1; - eEdgeE.fCompl ^= 1; - // derive the first AND - eNode0 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeT ); - // derive the second AND - eEdgeC.fCompl ^= 1; - eNode1 = Dec_GraphAddNodeAnd( pGraph, eEdgeC, eEdgeE ); - // derive the final OR - eNode = Dec_GraphAddNodeOr( pGraph, eNode0, eNode1 ); - eNode.fCompl ^= 1; - } - return eNode; -} - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/dec/decAbc.c b/src/opt/dec/decAbc.c deleted file mode 100644 index bd960c14..00000000 --- a/src/opt/dec/decAbc.c +++ /dev/null @@ -1,305 +0,0 @@ -/**CFile**************************************************************** - - FileName [decAbc.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Interface between the decomposition package and ABC network.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: decAbc.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "dec.h" -#include "ivy.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ) -{ - Abc_Obj_t * pAnd0, * pAnd1; - Dec_Node_t * pNode; - int i; - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) ); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - return Abc_ObjNotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); - // build the AIG nodes corresponding to the AND gates of the graph - Dec_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Abc_AigAnd( pNtk->pManFunc, pAnd0, pAnd1 ); - } - // complement the result if necessary - return Abc_ObjNotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph ) -{ - Abc_Obj_t * pAnd, * pAnd0, * pAnd1; - Dec_Node_t * pNode; - int i; - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Abc_ObjNotCond( Abc_AigConst1(pNtk), Dec_GraphIsComplement(pGraph) ); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - return Abc_ObjNotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); - // build the AIG nodes corresponding to the AND gates of the graph - Dec_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); -// pNode->pFunc = Abc_AigAnd( pNtk->pManFunc, pAnd0, pAnd1 ); - pAnd = Abc_NtkCreateNode( pNtk ); - Abc_ObjAddFanin( pAnd, pAnd0 ); - Abc_ObjAddFanin( pAnd, pAnd1 ); - pNode->pFunc = pAnd; - } - // complement the result if necessary - return Abc_ObjNotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of new nodes added when using this graph.] - - Description [AIG nodes for the fanins should be assigned to pNode->pFunc - of the leaves of the graph before calling this procedure. - Returns -1 if the number of nodes and levels exceeded the given limit or - the number of levels exceeded the maximum allowed level.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ) -{ - Abc_Aig_t * pMan = pRoot->pNtk->pManFunc; - Dec_Node_t * pNode, * pNode0, * pNode1; - Abc_Obj_t * pAnd, * pAnd0, * pAnd1; - int i, Counter, LevelNew, LevelOld; - // check for constant function or a literal - if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) - return 0; - // set the levels of the leaves - Dec_GraphForEachLeaf( pGraph, pNode, i ) - pNode->Level = Abc_ObjRegular(pNode->pFunc)->Level; - // compute the AIG size after adding the internal nodes - Counter = 0; - Dec_GraphForEachNode( pGraph, pNode, i ) - { - // get the children of this node - pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); - pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); - // get the AIG nodes corresponding to the children - pAnd0 = pNode0->pFunc; - pAnd1 = pNode1->pFunc; - if ( pAnd0 && pAnd1 ) - { - // if they are both present, find the resulting node - pAnd0 = Abc_ObjNotCond( pAnd0, pNode->eEdge0.fCompl ); - pAnd1 = Abc_ObjNotCond( pAnd1, pNode->eEdge1.fCompl ); - pAnd = Abc_AigAndLookup( pMan, pAnd0, pAnd1 ); - // return -1 if the node is the same as the original root - if ( Abc_ObjRegular(pAnd) == pRoot ) - return -1; - } - else - pAnd = NULL; - // count the number of added nodes - if ( pAnd == NULL || Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pAnd)) ) - { - if ( ++Counter > NodeMax ) - return -1; - } - // count the number of new levels - LevelNew = 1 + ABC_MAX( pNode0->Level, pNode1->Level ); - if ( pAnd ) - { - if ( Abc_ObjRegular(pAnd) == Abc_AigConst1(pRoot->pNtk) ) - LevelNew = 0; - else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd0) ) - LevelNew = (int)Abc_ObjRegular(pAnd0)->Level; - else if ( Abc_ObjRegular(pAnd) == Abc_ObjRegular(pAnd1) ) - LevelNew = (int)Abc_ObjRegular(pAnd1)->Level; - LevelOld = (int)Abc_ObjRegular(pAnd)->Level; -// assert( LevelNew == LevelOld ); - } - if ( LevelNew > LevelMax ) - return -1; - pNode->pFunc = pAnd; - pNode->Level = LevelNew; - } - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Replaces MFFC of the node by the new factored form.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain ) -{ - Abc_Obj_t * pRootNew; - Abc_Ntk_t * pNtk = pRoot->pNtk; - int nNodesNew, nNodesOld; - nNodesOld = Abc_NtkNodeNum(pNtk); - // create the new structure of nodes - pRootNew = Dec_GraphToNetwork( pNtk, pGraph ); - // remove the old nodes - Abc_AigReplace( pNtk->pManFunc, pRoot, pRootNew, fUpdateLevel ); - // compare the gains - nNodesNew = Abc_NtkNodeNum(pNtk); - assert( nGain <= nNodesOld - nNodesNew ); -} - - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Dec_GraphToNetworkAig( Hop_Man_t * pMan, Dec_Graph_t * pGraph ) -{ - Dec_Node_t * pNode; - Hop_Obj_t * pAnd0, * pAnd1; - int i; - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Hop_NotCond( Hop_ManConst1(pMan), Dec_GraphIsComplement(pGraph) ); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - return Hop_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); - // build the AIG nodes corresponding to the AND gates of the graph - Dec_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Hop_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Hop_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Hop_And( pMan, pAnd0, pAnd1 ); - } - // complement the result if necessary - return Hop_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop ) -{ - Hop_Obj_t * pFunc; - Dec_Graph_t * pFForm; - Dec_Node_t * pNode; - int i; - // perform factoring - pFForm = Dec_Factor( pSop ); - // collect the fanins - Dec_GraphForEachLeaf( pFForm, pNode, i ) - pNode->pFunc = Hop_IthVar( pMan, i ); - // perform strashing - pFunc = Dec_GraphToNetworkAig( pMan, pFForm ); - Dec_GraphFree( pFForm ); - return pFunc; -} - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Ivy_Obj_t * Dec_GraphToNetworkIvy( Ivy_Man_t * pMan, Dec_Graph_t * pGraph ) -{ - Dec_Node_t * pNode; - Ivy_Obj_t * pAnd0, * pAnd1; - int i; - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Ivy_NotCond( Ivy_ManConst1(pMan), Dec_GraphIsComplement(pGraph) ); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - return Ivy_NotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); - // build the AIG nodes corresponding to the AND gates of the graph - Dec_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - pAnd1 = Ivy_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Ivy_And( pMan, pAnd0, pAnd1 ); - } - // complement the result if necessary - return Ivy_NotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/dec/decFactor.c b/src/opt/dec/decFactor.c deleted file mode 100644 index dca422ea..00000000 --- a/src/opt/dec/decFactor.c +++ /dev/null @@ -1,392 +0,0 @@ -/**CFile**************************************************************** - - FileName [ftFactor.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Procedures for algebraic factoring.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: ftFactor.c,v 1.3 2003/09/01 04:56:43 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "main.h" -#include "mvc.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ); -static Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ); -static Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ); -static Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits ); -static Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr ); -static int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ); -static Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Factors the cover.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Dec_Factor( char * pSop ) -{ - Mvc_Cover_t * pCover; - Dec_Graph_t * pFForm; - Dec_Edge_t eRoot; - - // derive the cover from the SOP representation - pCover = Dec_ConvertSopToMvc( pSop ); - - // make sure the cover is CCS free (should be done before CST) - Mvc_CoverContain( pCover ); - // check for trivial functions - if ( Mvc_CoverIsEmpty(pCover) ) - { - Mvc_CoverFree( pCover ); - return Dec_GraphCreateConst0(); - } - if ( Mvc_CoverIsTautology(pCover) ) - { - Mvc_CoverFree( pCover ); - return Dec_GraphCreateConst1(); - } - - // perform CST - Mvc_CoverInverse( pCover ); // CST - // start the factored form - pFForm = Dec_GraphCreate( Abc_SopGetVarNum(pSop) ); - // factor the cover - eRoot = Dec_Factor_rec( pFForm, pCover ); - // finalize the factored form - Dec_GraphSetRoot( pFForm, eRoot ); - // complement the factored form if SOP is complemented - if ( Abc_SopIsComplement(pSop) ) - Dec_GraphComplement( pFForm ); - // verify the factored form -// if ( !Dec_FactorVerify( pSop, pFForm ) ) -// printf( "Verification has failed.\n" ); -// Mvc_CoverInverse( pCover ); // undo CST - Mvc_CoverFree( pCover ); - return pFForm; -} - -/**Function************************************************************* - - Synopsis [Internal recursive factoring procedure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Dec_Factor_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) -{ - Mvc_Cover_t * pDiv, * pQuo, * pRem, * pCom; - Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem; - Dec_Edge_t eNodeAnd, eNode; - - // make sure the cover contains some cubes - assert( Mvc_CoverReadCubeNum(pCover) ); - - // get the divisor - pDiv = Mvc_CoverDivisor( pCover ); - if ( pDiv == NULL ) - return Dec_FactorTrivial( pFForm, pCover ); - - // divide the cover by the divisor - Mvc_CoverDivideInternal( pCover, pDiv, &pQuo, &pRem ); - assert( Mvc_CoverReadCubeNum(pQuo) ); - - Mvc_CoverFree( pDiv ); - Mvc_CoverFree( pRem ); - - // check the trivial case - if ( Mvc_CoverReadCubeNum(pQuo) == 1 ) - { - eNode = Dec_FactorLF_rec( pFForm, pCover, pQuo ); - Mvc_CoverFree( pQuo ); - return eNode; - } - - // make the quotient cube free - Mvc_CoverMakeCubeFree( pQuo ); - - // divide the cover by the quotient - Mvc_CoverDivideInternal( pCover, pQuo, &pDiv, &pRem ); - - // check the trivial case - if ( Mvc_CoverIsCubeFree( pDiv ) ) - { - eNodeDiv = Dec_Factor_rec( pFForm, pDiv ); - eNodeQuo = Dec_Factor_rec( pFForm, pQuo ); - Mvc_CoverFree( pDiv ); - Mvc_CoverFree( pQuo ); - eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); - if ( Mvc_CoverReadCubeNum(pRem) == 0 ) - { - Mvc_CoverFree( pRem ); - return eNodeAnd; - } - else - { - eNodeRem = Dec_Factor_rec( pFForm, pRem ); - Mvc_CoverFree( pRem ); - return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); - } - } - - // get the common cube - pCom = Mvc_CoverCommonCubeCover( pDiv ); - Mvc_CoverFree( pDiv ); - Mvc_CoverFree( pQuo ); - Mvc_CoverFree( pRem ); - - // solve the simple problem - eNode = Dec_FactorLF_rec( pFForm, pCover, pCom ); - Mvc_CoverFree( pCom ); - return eNode; -} - - -/**Function************************************************************* - - Synopsis [Internal recursive factoring procedure for the leaf case.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Dec_FactorLF_rec( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cover_t * pSimple ) -{ - Dec_Man_t * pManDec = Abc_FrameReadManDec(); - Vec_Int_t * vEdgeLits = pManDec->vLits; - Mvc_Cover_t * pDiv, * pQuo, * pRem; - Dec_Edge_t eNodeDiv, eNodeQuo, eNodeRem; - Dec_Edge_t eNodeAnd; - - // get the most often occurring literal - pDiv = Mvc_CoverBestLiteralCover( pCover, pSimple ); - // divide the cover by the literal - Mvc_CoverDivideByLiteral( pCover, pDiv, &pQuo, &pRem ); - // get the node pointer for the literal - eNodeDiv = Dec_FactorTrivialCube( pFForm, pDiv, Mvc_CoverReadCubeHead(pDiv), vEdgeLits ); - Mvc_CoverFree( pDiv ); - // factor the quotient and remainder - eNodeQuo = Dec_Factor_rec( pFForm, pQuo ); - Mvc_CoverFree( pQuo ); - eNodeAnd = Dec_GraphAddNodeAnd( pFForm, eNodeDiv, eNodeQuo ); - if ( Mvc_CoverReadCubeNum(pRem) == 0 ) - { - Mvc_CoverFree( pRem ); - return eNodeAnd; - } - else - { - eNodeRem = Dec_Factor_rec( pFForm, pRem ); - Mvc_CoverFree( pRem ); - return Dec_GraphAddNodeOr( pFForm, eNodeAnd, eNodeRem ); - } -} - - - -/**Function************************************************************* - - Synopsis [Factoring the cover, which has no algebraic divisors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Dec_FactorTrivial( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover ) -{ - Dec_Man_t * pManDec = Abc_FrameReadManDec(); - Vec_Int_t * vEdgeCubes = pManDec->vCubes; - Vec_Int_t * vEdgeLits = pManDec->vLits; - Mvc_Manager_t * pMem = pManDec->pMvcMem; - Dec_Edge_t eNode; - Mvc_Cube_t * pCube; - // create the factored form for each cube - Vec_IntClear( vEdgeCubes ); - Mvc_CoverForEachCube( pCover, pCube ) - { - eNode = Dec_FactorTrivialCube( pFForm, pCover, pCube, vEdgeLits ); - Vec_IntPush( vEdgeCubes, Dec_EdgeToInt_(eNode) ); - } - // balance the factored forms - return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeCubes->pArray, vEdgeCubes->nSize, 1 ); -} - -/**Function************************************************************* - - Synopsis [Factoring the cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Dec_FactorTrivialCube( Dec_Graph_t * pFForm, Mvc_Cover_t * pCover, Mvc_Cube_t * pCube, Vec_Int_t * vEdgeLits ) -{ - Dec_Edge_t eNode; - int iBit, Value; - // create the factored form for each literal - Vec_IntClear( vEdgeLits ); - Mvc_CubeForEachBit( pCover, pCube, iBit, Value ) - if ( Value ) - { - eNode = Dec_EdgeCreate( iBit/2, iBit%2 ); // CST - Vec_IntPush( vEdgeLits, Dec_EdgeToInt_(eNode) ); - } - // balance the factored forms - return Dec_FactorTrivialTree_rec( pFForm, (Dec_Edge_t *)vEdgeLits->pArray, vEdgeLits->nSize, 0 ); -} - -/**Function************************************************************* - - Synopsis [Create the well-balanced tree of nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Dec_FactorTrivialTree_rec( Dec_Graph_t * pFForm, Dec_Edge_t * peNodes, int nNodes, int fNodeOr ) -{ - Dec_Edge_t eNode1, eNode2; - int nNodes1, nNodes2; - - if ( nNodes == 1 ) - return peNodes[0]; - - // split the nodes into two parts - nNodes1 = nNodes/2; - nNodes2 = nNodes - nNodes1; -// nNodes2 = nNodes/2; -// nNodes1 = nNodes - nNodes2; - - // recursively construct the tree for the parts - eNode1 = Dec_FactorTrivialTree_rec( pFForm, peNodes, nNodes1, fNodeOr ); - eNode2 = Dec_FactorTrivialTree_rec( pFForm, peNodes + nNodes1, nNodes2, fNodeOr ); - - if ( fNodeOr ) - return Dec_GraphAddNodeOr( pFForm, eNode1, eNode2 ); - else - return Dec_GraphAddNodeAnd( pFForm, eNode1, eNode2 ); -} - - - -/**Function************************************************************* - - Synopsis [Converts SOP into MVC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Mvc_Cover_t * Dec_ConvertSopToMvc( char * pSop ) -{ - Dec_Man_t * pManDec = Abc_FrameReadManDec(); - Mvc_Manager_t * pMem = pManDec->pMvcMem; - Mvc_Cover_t * pMvc; - Mvc_Cube_t * pMvcCube; - char * pCube; - int nVars, Value, v; - - // start the cover - nVars = Abc_SopGetVarNum(pSop); - pMvc = Mvc_CoverAlloc( pMem, nVars * 2 ); - // check the logic function of the node - Abc_SopForEachCube( pSop, nVars, pCube ) - { - // create and add the cube - pMvcCube = Mvc_CubeAlloc( pMvc ); - Mvc_CoverAddCubeTail( pMvc, pMvcCube ); - // fill in the literals - Mvc_CubeBitFill( pMvcCube ); - Abc_CubeForEachVar( pCube, Value, v ) - { - if ( Value == '0' ) - Mvc_CubeBitRemove( pMvcCube, v * 2 + 1 ); - else if ( Value == '1' ) - Mvc_CubeBitRemove( pMvcCube, v * 2 ); - } - } - return pMvc; -} - -/**Function************************************************************* - - Synopsis [Verifies that the factoring is correct.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dec_FactorVerify( char * pSop, Dec_Graph_t * pFForm ) -{ - DdManager * dd = Abc_FrameReadManDd(); - DdNode * bFunc1, * bFunc2; - int RetValue; - bFunc1 = Abc_ConvertSopToBdd( dd, pSop ); Cudd_Ref( bFunc1 ); - bFunc2 = Dec_GraphDeriveBdd( dd, pFForm ); Cudd_Ref( bFunc2 ); -//Extra_bddPrint( dd, bFunc1 ); printf("\n"); -//Extra_bddPrint( dd, bFunc2 ); printf("\n"); - RetValue = (bFunc1 == bFunc2); - if ( bFunc1 != bFunc2 ) - { - int s; - Extra_bddPrint( dd, bFunc1 ); printf("\n"); - Extra_bddPrint( dd, bFunc2 ); printf("\n"); - s = 0; - } - Cudd_RecursiveDeref( dd, bFunc1 ); - Cudd_RecursiveDeref( dd, bFunc2 ); - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/dec/decMan.c b/src/opt/dec/decMan.c deleted file mode 100644 index 65857461..00000000 --- a/src/opt/dec/decMan.c +++ /dev/null @@ -1,83 +0,0 @@ -/**CFile**************************************************************** - - FileName [decMan.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Decomposition manager.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: decMan.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "mvc.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start the MVC manager used in the factoring package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Man_t * Dec_ManStart() -{ - Dec_Man_t * p; - int clk = clock(); - p = ALLOC( Dec_Man_t, 1 ); - p->pMvcMem = Mvc_ManagerStart(); - p->vCubes = Vec_IntAlloc( 8 ); - p->vLits = Vec_IntAlloc( 8 ); - // canonical forms, phases, perms - Extra_Truth4VarNPN( &p->puCanons, &p->pPhases, &p->pPerms, &p->pMap ); -//PRT( "NPN classes precomputation time", clock() - clk ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the MVC maanager used in the factoring package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_ManStop( Dec_Man_t * p ) -{ - Mvc_ManagerFree( p->pMvcMem ); - Vec_IntFree( p->vCubes ); - Vec_IntFree( p->vLits ); - free( p->puCanons ); - free( p->pPhases ); - free( p->pPerms ); - free( p->pMap ); - free( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/dec/decPrint.c b/src/opt/dec/decPrint.c deleted file mode 100644 index 2d8f09b3..00000000 --- a/src/opt/dec/decPrint.c +++ /dev/null @@ -1,284 +0,0 @@ -/**CFile**************************************************************** - - FileName [decPrint.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Procedures to print the decomposition graphs (factored forms).] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: decPrint.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ); -static int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] ); -static void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax ); -static int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut, int fCompl ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Prints the decomposition graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_GraphPrint( FILE * pFile, Dec_Graph_t * pGraph, char * pNamesIn[], char * pNameOut ) -{ - Vec_Ptr_t * vNamesIn = NULL; - int LitSizeMax, LitSizeCur, Pos, i; - - // create the names if not given by the user - if ( pNamesIn == NULL ) - { - vNamesIn = Abc_NodeGetFakeNames( Dec_GraphLeaveNum(pGraph) ); - pNamesIn = (char **)vNamesIn->pArray; - } - if ( pNameOut == NULL ) - pNameOut = "F"; - - // get the size of the longest literal - LitSizeMax = 0; - for ( i = 0; i < Dec_GraphLeaveNum(pGraph); i++ ) - { - LitSizeCur = strlen(pNamesIn[i]); - if ( LitSizeMax < LitSizeCur ) - LitSizeMax = LitSizeCur; - } - if ( LitSizeMax > 50 ) - LitSizeMax = 20; - - // write the decomposition graph (factored form) - if ( Dec_GraphIsConst(pGraph) ) // constant - { - Pos = Dec_GraphPrintOutputName( pFile, pNameOut, 0 ); - fprintf( pFile, "Constant %d", !Dec_GraphIsComplement(pGraph) ); - } - else if ( Dec_GraphIsVar(pGraph) ) // literal - { - Pos = Dec_GraphPrintOutputName( pFile, pNameOut, 0 ); - Dec_GraphPrintGetLeafName( pFile, Dec_GraphVarInt(pGraph), Dec_GraphIsComplement(pGraph), pNamesIn ); - } - else - { - Pos = Dec_GraphPrintOutputName( pFile, pNameOut, Dec_GraphIsComplement(pGraph) ); - Dec_GraphPrint_rec( pFile, pGraph, Dec_GraphNodeLast(pGraph), 0, pNamesIn, &Pos, LitSizeMax ); - } - fprintf( pFile, "\n" ); - - if ( vNamesIn ) - Abc_NodeFreeNames( vNamesIn ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_GraphPrint2_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ) -{ - Dec_Node_t * pNode0, * pNode1; - pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node); - pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node); - if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF ) - { - (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn ); - return; - } - if ( !pNode->fNodeOr ) // FT_NODE_AND ) - { - if ( !pNode0->fNodeOr ) // != FT_NODE_OR ) - Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); - else - { - fprintf( pFile, "(" ); - (*pPos)++; - Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, ")" ); - (*pPos)++; - } - fprintf( pFile, " " ); - (*pPos)++; - - Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax ); - - if ( !pNode1->fNodeOr ) // != FT_NODE_OR ) - Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); - else - { - fprintf( pFile, "(" ); - (*pPos)++; - Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, ")" ); - (*pPos)++; - } - return; - } - if ( pNode->fNodeOr ) // FT_NODE_OR ) - { - Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, " + " ); - (*pPos) += 3; - - Dec_GraphPrintUpdatePos( pFile, pPos, LitSizeMax ); - - Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); - return; - } - assert( 0 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_GraphPrint_rec( FILE * pFile, Dec_Graph_t * pGraph, Dec_Node_t * pNode, int fCompl, char * pNamesIn[], int * pPos, int LitSizeMax ) -{ - Dec_Node_t * pNode0, * pNode1; - Dec_Node_t * pNode00, * pNode01, * pNode10, * pNode11; - pNode0 = Dec_GraphNode(pGraph, pNode->eEdge0.Node); - pNode1 = Dec_GraphNode(pGraph, pNode->eEdge1.Node); - if ( Dec_GraphNodeIsVar(pGraph, pNode) ) // FT_NODE_LEAF ) - { - (*pPos) += Dec_GraphPrintGetLeafName( pFile, Dec_GraphNodeInt(pGraph,pNode), fCompl, pNamesIn ); - return; - } - if ( !Dec_GraphNodeIsVar(pGraph, pNode0) && !Dec_GraphNodeIsVar(pGraph, pNode1) ) - { - pNode00 = Dec_GraphNode(pGraph, pNode0->eEdge0.Node); - pNode01 = Dec_GraphNode(pGraph, pNode0->eEdge1.Node); - pNode10 = Dec_GraphNode(pGraph, pNode1->eEdge0.Node); - pNode11 = Dec_GraphNode(pGraph, pNode1->eEdge1.Node); - if ( (pNode00 == pNode10 || pNode00 == pNode11) && (pNode01 == pNode10 || pNode01 == pNode11) ) - { - fprintf( pFile, "(" ); - (*pPos)++; - Dec_GraphPrint_rec( pFile, pGraph, pNode00, pNode00->fCompl0, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, " # " ); - (*pPos) += 3; - Dec_GraphPrint_rec( pFile, pGraph, pNode01, pNode01->fCompl1, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, ")" ); - (*pPos)++; - return; - } - } - if ( fCompl ) - { - fprintf( pFile, "(" ); - (*pPos)++; - Dec_GraphPrint_rec( pFile, pGraph, pNode0, !pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, " + " ); - (*pPos) += 3; - Dec_GraphPrint_rec( pFile, pGraph, pNode1, !pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, ")" ); - (*pPos)++; - } - else - { - fprintf( pFile, "(" ); - (*pPos)++; - Dec_GraphPrint_rec( pFile, pGraph, pNode0, pNode->fCompl0, pNamesIn, pPos, LitSizeMax ); - Dec_GraphPrint_rec( pFile, pGraph, pNode1, pNode->fCompl1, pNamesIn, pPos, LitSizeMax ); - fprintf( pFile, ")" ); - (*pPos)++; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dec_GraphPrintGetLeafName( FILE * pFile, int iLeaf, int fCompl, char * pNamesIn[] ) -{ - static char Buffer[100]; - sprintf( Buffer, "%s%s", pNamesIn[iLeaf], fCompl? "\'" : "" ); - fprintf( pFile, "%s", Buffer ); - return strlen( Buffer ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Dec_GraphPrintUpdatePos( FILE * pFile, int * pPos, int LitSizeMax ) -{ - int i; - if ( *pPos + LitSizeMax < 77 ) - return; - fprintf( pFile, "\n" ); - for ( i = 0; i < 10; i++ ) - fprintf( pFile, " " ); - *pPos = 10; -} - -/**Function************************************************************* - - Synopsis [Starts the printout for a decomposition graph.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Dec_GraphPrintOutputName( FILE * pFile, char * pNameOut, int fCompl ) -{ - if ( pNameOut == NULL ) - return 0; - fprintf( pFile, "%6s%s = ", pNameOut, fCompl? "\'" : " " ); - return 10; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/dec/decUtil.c b/src/opt/dec/decUtil.c deleted file mode 100644 index 463bc7e2..00000000 --- a/src/opt/dec/decUtil.c +++ /dev/null @@ -1,134 +0,0 @@ -/**CFile**************************************************************** - - FileName [decUtil.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Decomposition unitilies.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: decUtil.c,v 1.1 2003/05/22 19:20:05 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Converts graph to BDD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -DdNode * Dec_GraphDeriveBdd( DdManager * dd, Dec_Graph_t * pGraph ) -{ - DdNode * bFunc, * bFunc0, * bFunc1; - Dec_Node_t * pNode; - int i; - - // sanity checks - assert( Dec_GraphLeaveNum(pGraph) >= 0 ); - assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); - - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Cudd_NotCond( b1, Dec_GraphIsComplement(pGraph) ); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - return Cudd_NotCond( Cudd_bddIthVar(dd, Dec_GraphVarInt(pGraph)), Dec_GraphIsComplement(pGraph) ); - - // assign the elementary variables - Dec_GraphForEachLeaf( pGraph, pNode, i ) - pNode->pFunc = Cudd_bddIthVar( dd, i ); - - // compute the function for each internal node - Dec_GraphForEachNode( pGraph, pNode, i ) - { - bFunc0 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); - bFunc1 = Cudd_NotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); - pNode->pFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( pNode->pFunc ); - } - - // deref the intermediate results - bFunc = pNode->pFunc; Cudd_Ref( bFunc ); - Dec_GraphForEachNode( pGraph, pNode, i ) - Cudd_RecursiveDeref( dd, pNode->pFunc ); - Cudd_Deref( bFunc ); - - // complement the result if necessary - return Cudd_NotCond( bFunc, Dec_GraphIsComplement(pGraph) ); -} - -/**Function************************************************************* - - Synopsis [Derives the truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Dec_GraphDeriveTruth( Dec_Graph_t * pGraph ) -{ - unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - unsigned uTruth, uTruth0, uTruth1; - Dec_Node_t * pNode; - int i; - - // sanity checks - assert( Dec_GraphLeaveNum(pGraph) >= 0 ); - assert( Dec_GraphLeaveNum(pGraph) <= pGraph->nSize ); - assert( Dec_GraphLeaveNum(pGraph) <= 5 ); - - // check for constant function - if ( Dec_GraphIsConst(pGraph) ) - return Dec_GraphIsComplement(pGraph)? 0 : ~((unsigned)0); - // check for a literal - if ( Dec_GraphIsVar(pGraph) ) - return Dec_GraphIsComplement(pGraph)? ~uTruths[Dec_GraphVarInt(pGraph)] : uTruths[Dec_GraphVarInt(pGraph)]; - - // assign the elementary variables - Dec_GraphForEachLeaf( pGraph, pNode, i ) - pNode->pFunc = (void *)uTruths[i]; - - // compute the function for each internal node - Dec_GraphForEachNode( pGraph, pNode, i ) - { - uTruth0 = (unsigned)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; - uTruth1 = (unsigned)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; - uTruth0 = pNode->eEdge0.fCompl? ~uTruth0 : uTruth0; - uTruth1 = pNode->eEdge1.fCompl? ~uTruth1 : uTruth1; - uTruth = uTruth0 & uTruth1; - pNode->pFunc = (void *)uTruth; - } - - // complement the result if necessary - return Dec_GraphIsComplement(pGraph)? ~uTruth : uTruth; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/dec/module.make b/src/opt/dec/module.make deleted file mode 100644 index 1e0722d5..00000000 --- a/src/opt/dec/module.make +++ /dev/null @@ -1,5 +0,0 @@ -SRC += src/opt/dec/decAbc.c \ - src/opt/dec/decFactor.c \ - src/opt/dec/decMan.c \ - src/opt/dec/decPrint.c \ - src/opt/dec/decUtil.c diff --git a/src/opt/fxu/fxu.c b/src/opt/fxu/fxu.c deleted file mode 100644 index d11fd793..00000000 --- a/src/opt/fxu/fxu.c +++ /dev/null @@ -1,254 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxu.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [The entrance into the fast extract module.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxu.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fxuInt.h" -#include "fxu.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*===== fxuCreate.c ====================================================*/ -extern Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ); -extern void Fxu_CreateCovers( Fxu_Matrix * p, Fxu_Data_t * pData ); - -static int s_MemoryTotal; -static int s_MemoryPeak; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs fast_extract on a set of covers.] - - Description [All the covers are given in the array p->vSops. - The resulting covers are returned in the array p->vSopsNew. - The entries in these arrays correspond to objects in the network. - The entries corresponding to the PI and objects with trivial covers are NULL. - The number of extracted covers (not exceeding p->nNodesExt) is returned. - Two other things are important for the correct operation of this procedure: - (1) The input covers do not have duplicated fanins and are SCC-free. - (2) The fanins array contains the numbers of the fanin objects.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_FastExtract( Fxu_Data_t * pData ) -{ - Fxu_Matrix * p; - Fxu_Single * pSingle; - Fxu_Double * pDouble; - int Weight1, Weight2, Weight3; - int Counter = 0; - - s_MemoryTotal = 0; - s_MemoryPeak = 0; - - // create the matrix - p = Fxu_CreateMatrix( pData ); - if ( p == NULL ) - return -1; -// if ( pData->fVerbose ) -// printf( "Memory usage after construction: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak ); -//Fxu_MatrixPrint( NULL, p ); - - if ( pData->fOnlyS ) - { - pData->nNodesNew = 0; - do - { - Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ); - if ( pData->fVerbose ) - printf( "Div %5d : Best single = %5d.\r", Counter++, Weight1 ); - if ( Weight1 > 0 || Weight1 == 0 && pData->fUse0 ) - Fxu_UpdateSingle( p ); - else - break; - } - while ( ++pData->nNodesNew < pData->nNodesExt ); - } - else if ( pData->fOnlyD ) - { - pData->nNodesNew = 0; - do - { - Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); - if ( pData->fVerbose ) - printf( "Div %5d : Best double = %5d.\r", Counter++, Weight2 ); - if ( Weight2 > 0 || Weight2 == 0 && pData->fUse0 ) - Fxu_UpdateDouble( p ); - else - break; - } - while ( ++pData->nNodesNew < pData->nNodesExt ); - } - else if ( !pData->fUseCompl ) - { - pData->nNodesNew = 0; - do - { - Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ); - Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); - - if ( pData->fVerbose ) - printf( "Div %5d : Best double = %5d. Best single = %5d.\r", Counter++, Weight2, Weight1 ); -//Fxu_Select( p, &pSingle, &pDouble ); - - if ( Weight1 >= Weight2 ) - { - if ( Weight1 > 0 || Weight1 == 0 && pData->fUse0 ) - Fxu_UpdateSingle( p ); - else - break; - } - else - { - if ( Weight2 > 0 || Weight2 == 0 && pData->fUse0 ) - Fxu_UpdateDouble( p ); - else - break; - } - } - while ( ++pData->nNodesNew < pData->nNodesExt ); - } - else - { // use the complement - pData->nNodesNew = 0; - do - { - Weight1 = Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ); - Weight2 = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); - - // select the best single and double - Weight3 = Fxu_Select( p, &pSingle, &pDouble ); - if ( pData->fVerbose ) - printf( "Div %5d : Best double = %5d. Best single = %5d. Best complement = %5d.\r", - Counter++, Weight2, Weight1, Weight3 ); - - if ( Weight3 > 0 || Weight3 == 0 && pData->fUse0 ) - Fxu_Update( p, pSingle, pDouble ); - else - break; - } - while ( ++pData->nNodesNew < pData->nNodesExt ); - } - - if ( pData->fVerbose ) - printf( "Total single = %3d. Total double = %3d. Total compl = %3d. \n", - p->nDivs1, p->nDivs2, p->nDivs3 ); - - // create the new covers - if ( pData->nNodesNew ) - Fxu_CreateCovers( p, pData ); - Fxu_MatrixDelete( p ); -// printf( "Memory usage after deallocation: Total = %d. Peak = %d.\n", s_MemoryTotal, s_MemoryPeak ); - if ( pData->nNodesNew == pData->nNodesExt ) - printf( "Warning: The limit on the number of extracted divisors has been reached.\n" ); - return pData->nNodesNew; -} - - -/**Function************************************************************* - - Synopsis [Unmarks the cubes in the ring.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixRingCubesUnmark( Fxu_Matrix * p ) -{ - Fxu_Cube * pCube, * pCube2; - // unmark the cubes - Fxu_MatrixForEachCubeInRingSafe( p, pCube, pCube2 ) - pCube->pOrder = NULL; - Fxu_MatrixRingCubesReset( p ); -} - - -/**Function************************************************************* - - Synopsis [Unmarks the vars in the ring.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p ) -{ - Fxu_Var * pVar, * pVar2; - // unmark the vars - Fxu_MatrixForEachVarInRingSafe( p, pVar, pVar2 ) - pVar->pOrder = NULL; - Fxu_MatrixRingVarsReset( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Fxu_MemFetch( Fxu_Matrix * p, int nBytes ) -{ - s_MemoryTotal += nBytes; - if ( s_MemoryPeak < s_MemoryTotal ) - s_MemoryPeak = s_MemoryTotal; -// return malloc( nBytes ); - return Extra_MmFixedEntryFetch( p->pMemMan ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MemRecycle( Fxu_Matrix * p, char * pItem, int nBytes ) -{ - s_MemoryTotal -= nBytes; -// free( pItem ); - Extra_MmFixedEntryRecycle( p->pMemMan, pItem ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/fxu/fxu.h b/src/opt/fxu/fxu.h deleted file mode 100644 index e6d0b69e..00000000 --- a/src/opt/fxu/fxu.h +++ /dev/null @@ -1,93 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxu.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [External declarations of fast extract for unate covers.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxu.h,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __FXU_H__ -#define __FXU_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#ifndef __cplusplus -#ifndef bool -#define bool int -#endif -#endif - -typedef struct FxuDataStruct Fxu_Data_t; - -// structure for the FX input/output data -struct FxuDataStruct -{ - // user specified parameters - bool fOnlyS; // set to 1 to have only single-cube divs - bool fOnlyD; // set to 1 to have only double-cube divs - bool fUse0; // set to 1 to have 0-weight also extracted - bool fUseCompl; // set to 1 to have complement taken into account - bool fVerbose; // set to 1 to have verbose output - int nNodesExt; // the number of divisors to extract - int nSingleMax; // the max number of single-cube divisors to consider - int nPairsMax; // the max number of double-cube divisors to consider - // the input information - Vec_Ptr_t * vSops; // the SOPs for each node in the network - Vec_Ptr_t * vFanins; // the fanins of each node in the network - // output information - Vec_Ptr_t * vSopsNew; // the SOPs for each node in the network after extraction - Vec_Ptr_t * vFaninsNew; // the fanins of each node in the network after extraction - // the SOP manager - Extra_MmFlex_t * pManSop; - // statistics - int nNodesOld; // the old number of nodes - int nNodesNew; // the number of divisors actually extracted -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*===== fxu.c ==========================================================*/ -extern int Fxu_FastExtract( Fxu_Data_t * pData ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/fxu/fxuCreate.c b/src/opt/fxu/fxuCreate.c deleted file mode 100644 index e3300df9..00000000 --- a/src/opt/fxu/fxuCreate.c +++ /dev/null @@ -1,431 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuCreate.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Create matrix from covers and covers from matrix.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuCreate.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "fxuInt.h" -#include "fxu.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder ); -static int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY ); -static void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext ); -static Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode ); -static int * s_pLits; - -extern int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the sparse matrix from the array of SOPs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData ) -{ - Fxu_Matrix * p; - Fxu_Var * pVar; - Fxu_Cube * pCubeFirst, * pCubeNew; - Fxu_Cube * pCube1, * pCube2; - Vec_Int_t * vFanins; - char * pSopCover; - char * pSopCube; - int * pOrder, nBitsMax; - int i, v, c; - int nCubesTotal; - int nPairsTotal; - int nPairsStore; - int nCubes; - int iCube, iPair; - int nFanins; - - // collect all sorts of statistics - nCubesTotal = 0; - nPairsTotal = 0; - nPairsStore = 0; - nBitsMax = -1; - for ( i = 0; i < pData->nNodesOld; i++ ) - if ( pSopCover = pData->vSops->pArray[i] ) - { - nCubes = Abc_SopGetCubeNum( pSopCover ); - nFanins = Abc_SopGetVarNum( pSopCover ); - assert( nFanins > 1 && nCubes > 0 ); - - nCubesTotal += nCubes; - nPairsTotal += nCubes * (nCubes - 1) / 2; - nPairsStore += nCubes * nCubes; - if ( nBitsMax < nFanins ) - nBitsMax = nFanins; - } - if ( nBitsMax <= 0 ) - { - printf( "The current network does not have SOPs to perform extraction.\n" ); - return NULL; - } -/* - if ( nPairsStore > 10000000 ) - { - printf( "The problem is too large to be solved by \"fxu\" (%d cubes and %d cube pairs)\n", nCubesTotal, nPairsStore ); - return NULL; - } -*/ - // start the matrix - p = Fxu_MatrixAllocate(); - // create the column labels - p->ppVars = ALLOC( Fxu_Var *, 2 * (pData->nNodesOld + pData->nNodesExt) ); - for ( i = 0; i < 2 * pData->nNodesOld; i++ ) - p->ppVars[i] = Fxu_MatrixAddVar( p ); - - // allocate storage for all cube pairs at once - p->pppPairs = ALLOC( Fxu_Pair **, nCubesTotal + 100 ); - p->ppPairs = ALLOC( Fxu_Pair *, nPairsStore + 100 ); - memset( p->ppPairs, 0, sizeof(Fxu_Pair *) * nPairsStore ); - iCube = 0; - iPair = 0; - for ( i = 0; i < pData->nNodesOld; i++ ) - if ( pSopCover = pData->vSops->pArray[i] ) - { - // get the number of cubes - nCubes = Abc_SopGetCubeNum( pSopCover ); - // get the new var in the matrix - pVar = p->ppVars[2*i+1]; - // assign the pair storage - pVar->nCubes = nCubes; - if ( nCubes > 0 ) - { - pVar->ppPairs = p->pppPairs + iCube; - pVar->ppPairs[0] = p->ppPairs + iPair; - for ( v = 1; v < nCubes; v++ ) - pVar->ppPairs[v] = pVar->ppPairs[v-1] + nCubes; - } - // update - iCube += nCubes; - iPair += nCubes * nCubes; - } - assert( iCube == nCubesTotal ); - assert( iPair == nPairsStore ); - - - // allocate room for the reordered literals - pOrder = ALLOC( int, nBitsMax ); - // create the rows - for ( i = 0; i < pData->nNodesOld; i++ ) - if ( pSopCover = pData->vSops->pArray[i] ) - { - // get the new var in the matrix - pVar = p->ppVars[2*i+1]; - // here we sort the literals of the cover - // in the increasing order of the numbers of the corresponding nodes - // because literals should be added to the matrix in this order - vFanins = pData->vFanins->pArray[i]; - s_pLits = vFanins->pArray; - // start the variable order - nFanins = Abc_SopGetVarNum( pSopCover ); - for ( v = 0; v < nFanins; v++ ) - pOrder[v] = v; - // reorder the fanins - qsort( (void *)pOrder, nFanins, sizeof(int),(int (*)(const void *, const void *))Fxu_CreateMatrixLitCompare); - assert( s_pLits[ pOrder[0] ] < s_pLits[ pOrder[nFanins-1] ] ); - // create the corresponding cubes in the matrix - pCubeFirst = NULL; - c = 0; - Abc_SopForEachCube( pSopCover, nFanins, pSopCube ) - { - // create the cube - pCubeNew = Fxu_MatrixAddCube( p, pVar, c++ ); - Fxu_CreateMatrixAddCube( p, pCubeNew, pSopCube, vFanins, pOrder ); - if ( pCubeFirst == NULL ) - pCubeFirst = pCubeNew; - pCubeNew->pFirst = pCubeFirst; - } - // set the first cube of this var - pVar->pFirst = pCubeFirst; - // create the divisors without preprocessing - if ( nPairsTotal <= pData->nPairsMax ) - { - for ( pCube1 = pCubeFirst; pCube1; pCube1 = pCube1->pNext ) - for ( pCube2 = pCube1? pCube1->pNext: NULL; pCube2; pCube2 = pCube2->pNext ) - Fxu_MatrixAddDivisor( p, pCube1, pCube2 ); - } - } - FREE( pOrder ); - - // consider the case when cube pairs should be preprocessed - // before adding them to the set of divisors -// if ( pData->fVerbose ) -// printf( "The total number of cube pairs is %d.\n", nPairsTotal ); - if ( nPairsTotal > 10000000 ) - { - printf( "The total number of cube pairs of the network is more than 10,000,000.\n" ); - printf( "Command \"fx\" takes a long time to run in such cases. It is suggested\n" ); - printf( "that the user changes the network by reducing the size of logic node and\n" ); - printf( "consequently the number of cube pairs to be processed by this command.\n" ); - printf( "One way to achieve this is to run the commands \"st; multi -m -F \"\n" ); - printf( "as a proprocessing step, while selecting as approapriate.\n" ); - return NULL; - } - if ( nPairsTotal > pData->nPairsMax ) - if ( !Fxu_PreprocessCubePairs( p, pData->vSops, nPairsTotal, pData->nPairsMax ) ) - return NULL; -// if ( pData->fVerbose ) -// printf( "Only %d best cube pairs will be used by the fast extract command.\n", pData->nPairsMax ); - - // add the var pairs to the heap - Fxu_MatrixComputeSingles( p, pData->fUse0, pData->nSingleMax ); - - // print stats - if ( pData->fVerbose ) - { - double Density; - Density = ((double)p->nEntries) / p->lVars.nItems / p->lCubes.nItems; - fprintf( stdout, "Matrix: [vars x cubes] = [%d x %d] ", - p->lVars.nItems, p->lCubes.nItems ); - fprintf( stdout, "Lits = %d Density = %.5f%%\n", - p->nEntries, Density ); - fprintf( stdout, "1-cube divs = %6d. (Total = %6d) ", p->lSingles.nItems, p->nSingleTotal ); - fprintf( stdout, "2-cube divs = %6d. (Total = %6d)", p->nDivsTotal, nPairsTotal ); - fprintf( stdout, "\n" ); - } -// Fxu_MatrixPrint( stdout, p ); - return p; -} - -/**Function************************************************************* - - Synopsis [Adds one cube with literals to the matrix.] - - Description [Create the cube and literals in the matrix corresponding - to the given cube in the SOP cover. Co-singleton transform is performed here.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder ) -{ - Fxu_Var * pVar; - int Value, i; - // add literals to the matrix - Abc_CubeForEachVar( pSopCube, Value, i ) - { - Value = pSopCube[pOrder[i]]; - if ( Value == '0' ) - { - pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] + 1 ]; // CST - Fxu_MatrixAddLiteral( p, pCube, pVar ); - } - else if ( Value == '1' ) - { - pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] ]; // CST - Fxu_MatrixAddLiteral( p, pCube, pVar ); - } - } -} - - -/**Function************************************************************* - - Synopsis [Creates the new array of Sop covers from the sparse matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_CreateCovers( Fxu_Matrix * p, Fxu_Data_t * pData ) -{ - Fxu_Cube * pCube, * pCubeFirst, * pCubeNext; - char * pSopCover; - int iNode, n; - - // get the first cube of the first internal node - pCubeFirst = Fxu_CreateCoversFirstCube( p, pData, 0 ); - - // go through the internal nodes - for ( n = 0; n < pData->nNodesOld; n++ ) - if ( pSopCover = pData->vSops->pArray[n] ) - { - // get the number of this node - iNode = n; - // get the next first cube - pCubeNext = Fxu_CreateCoversFirstCube( p, pData, iNode + 1 ); - // check if there any new variables in these cubes - for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) - if ( pCube->lLits.pTail && pCube->lLits.pTail->iVar >= 2 * pData->nNodesOld ) - break; - if ( pCube != pCubeNext ) - Fxu_CreateCoversNode( p, pData, iNode, pCubeFirst, pCubeNext ); - // update the first cube - pCubeFirst = pCubeNext; - } - - // add the covers for the extracted nodes - for ( n = 0; n < pData->nNodesNew; n++ ) - { - // get the number of this node - iNode = pData->nNodesOld + n; - // get the next first cube - pCubeNext = Fxu_CreateCoversFirstCube( p, pData, iNode + 1 ); - // the node should be added - Fxu_CreateCoversNode( p, pData, iNode, pCubeFirst, pCubeNext ); - // update the first cube - pCubeFirst = pCubeNext; - } -} - -/**Function************************************************************* - - Synopsis [Create Sop covers for one node that has changed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext ) -{ - Vec_Int_t * vInputsNew; - char * pSopCover, * pSopCube; - Fxu_Var * pVar; - Fxu_Cube * pCube; - Fxu_Lit * pLit; - int iNum, nCubes, v; - - // collect positive polarity variable in the cubes between pCubeFirst and pCubeNext - Fxu_MatrixRingVarsStart( p ); - for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) - for ( pLit = pCube->lLits.pHead; pLit; pLit = pLit->pHNext ) - { - pVar = p->ppVars[ 2 * (pLit->pVar->iVar/2) + 1 ]; - if ( pVar->pOrder == NULL ) - Fxu_MatrixRingVarsAdd( p, pVar ); - } - Fxu_MatrixRingVarsStop( p ); - - // collect the variable numbers - vInputsNew = Vec_IntAlloc( 4 ); - Fxu_MatrixForEachVarInRing( p, pVar ) - Vec_IntPush( vInputsNew, pVar->iVar / 2 ); - Fxu_MatrixRingVarsUnmark( p ); - - // sort the vars by their number - Vec_IntSort( vInputsNew, 0 ); - - // mark the vars with their numbers in the sorted array - for ( v = 0; v < vInputsNew->nSize; v++ ) - { - p->ppVars[ 2 * vInputsNew->pArray[v] + 0 ]->lLits.nItems = v; // hack - reuse lLits.nItems - p->ppVars[ 2 * vInputsNew->pArray[v] + 1 ]->lLits.nItems = v; // hack - reuse lLits.nItems - } - - // count the number of cubes - nCubes = 0; - for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) - if ( pCube->lLits.nItems ) - nCubes++; - - // allocate room for the new cover - pSopCover = Abc_SopStart( pData->pManSop, nCubes, vInputsNew->nSize ); - // set the correct polarity of the cover - if ( iNode < pData->nNodesOld && Abc_SopGetPhase( pData->vSops->pArray[iNode] ) == 0 ) - Abc_SopComplement( pSopCover ); - - // add the cubes - nCubes = 0; - for ( pCube = pCubeFirst; pCube != pCubeNext; pCube = pCube->pNext ) - { - if ( pCube->lLits.nItems == 0 ) - continue; - // get hold of the SOP cube - pSopCube = pSopCover + nCubes * (vInputsNew->nSize + 3); - // insert literals - for ( pLit = pCube->lLits.pHead; pLit; pLit = pLit->pHNext ) - { - iNum = pLit->pVar->lLits.nItems; // hack - reuse lLits.nItems - assert( iNum < vInputsNew->nSize ); - if ( pLit->pVar->iVar / 2 < pData->nNodesOld ) - pSopCube[iNum] = (pLit->pVar->iVar & 1)? '0' : '1'; // reverse CST - else - pSopCube[iNum] = (pLit->pVar->iVar & 1)? '1' : '0'; // no CST - } - // count the cube - nCubes++; - } - assert( nCubes == Abc_SopGetCubeNum(pSopCover) ); - - // set the new cover and the array of fanins - pData->vSopsNew->pArray[iNode] = pSopCover; - pData->vFaninsNew->pArray[iNode] = vInputsNew; -} - - -/**Function************************************************************* - - Synopsis [Adds the var to storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iVar ) -{ - int v; - for ( v = iVar; v < pData->nNodesOld + pData->nNodesNew; v++ ) - if ( p->ppVars[ 2*v + 1 ]->pFirst ) - return p->ppVars[ 2*v + 1 ]->pFirst; - return NULL; -} - -/**Function************************************************************* - - Synopsis [Compares the vars by their number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY ) -{ - return s_pLits[*ptrX] - s_pLits[*ptrY]; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/opt/fxu/fxuHeapD.c b/src/opt/fxu/fxuHeapD.c deleted file mode 100644 index c81ad818..00000000 --- a/src/opt/fxu/fxuHeapD.c +++ /dev/null @@ -1,445 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuHeapD.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [The priority queue for double cube divisors.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuHeapD.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fxuInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define FXU_HEAP_DOUBLE_WEIGHT(pDiv) ((pDiv)->Weight) -#define FXU_HEAP_DOUBLE_CURRENT(p, pDiv) ((p)->pTree[(pDiv)->HNum]) -#define FXU_HEAP_DOUBLE_PARENT_EXISTS(p, pDiv) ((pDiv)->HNum > 1) -#define FXU_HEAP_DOUBLE_CHILD1_EXISTS(p, pDiv) (((pDiv)->HNum << 1) <= p->nItems) -#define FXU_HEAP_DOUBLE_CHILD2_EXISTS(p, pDiv) ((((pDiv)->HNum << 1)+1) <= p->nItems) -#define FXU_HEAP_DOUBLE_PARENT(p, pDiv) ((p)->pTree[(pDiv)->HNum >> 1]) -#define FXU_HEAP_DOUBLE_CHILD1(p, pDiv) ((p)->pTree[(pDiv)->HNum << 1]) -#define FXU_HEAP_DOUBLE_CHILD2(p, pDiv) ((p)->pTree[((pDiv)->HNum << 1)+1]) -#define FXU_HEAP_DOUBLE_ASSERT(p, pDiv) assert( (pDiv)->HNum >= 1 && (pDiv)->HNum <= p->nItemsAlloc ) - -static void Fxu_HeapDoubleResize( Fxu_HeapDouble * p ); -static void Fxu_HeapDoubleSwap( Fxu_Double ** pDiv1, Fxu_Double ** pDiv2 ); -static void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv ); -static void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_HeapDouble * Fxu_HeapDoubleStart() -{ - Fxu_HeapDouble * p; - p = ALLOC( Fxu_HeapDouble, 1 ); - memset( p, 0, sizeof(Fxu_HeapDouble) ); - p->nItems = 0; - p->nItemsAlloc = 10000; - p->pTree = ALLOC( Fxu_Double *, p->nItemsAlloc + 1 ); - p->pTree[0] = NULL; - return p; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapDoubleResize( Fxu_HeapDouble * p ) -{ - p->nItemsAlloc *= 2; - p->pTree = REALLOC( Fxu_Double *, p->pTree, p->nItemsAlloc + 1 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapDoubleStop( Fxu_HeapDouble * p ) -{ - free( p->pTree ); - free( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapDoublePrint( FILE * pFile, Fxu_HeapDouble * p ) -{ - Fxu_Double * pDiv; - int Counter = 1; - int Degree = 1; - - Fxu_HeapDoubleCheck( p ); - fprintf( pFile, "The contents of the heap:\n" ); - fprintf( pFile, "Level %d: ", Degree ); - Fxu_HeapDoubleForEachItem( p, pDiv ) - { - assert( Counter == p->pTree[Counter]->HNum ); - fprintf( pFile, "%2d=%3d ", Counter, FXU_HEAP_DOUBLE_WEIGHT(p->pTree[Counter]) ); - if ( ++Counter == (1 << Degree) ) - { - fprintf( pFile, "\n" ); - Degree++; - fprintf( pFile, "Level %d: ", Degree ); - } - } - fprintf( pFile, "\n" ); - fprintf( pFile, "End of the heap printout.\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapDoubleCheck( Fxu_HeapDouble * p ) -{ - Fxu_Double * pDiv; - Fxu_HeapDoubleForEachItem( p, pDiv ) - { - assert( pDiv->HNum == p->i ); - Fxu_HeapDoubleCheckOne( p, pDiv ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapDoubleCheckOne( Fxu_HeapDouble * p, Fxu_Double * pDiv ) -{ - int Weight1, Weight2; - if ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,pDiv) ) - { - Weight1 = FXU_HEAP_DOUBLE_WEIGHT(pDiv); - Weight2 = FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD1(p,pDiv) ); - assert( Weight1 >= Weight2 ); - } - if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,pDiv) ) - { - Weight1 = FXU_HEAP_DOUBLE_WEIGHT(pDiv); - Weight2 = FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD2(p,pDiv) ); - assert( Weight1 >= Weight2 ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapDoubleInsert( Fxu_HeapDouble * p, Fxu_Double * pDiv ) -{ - if ( p->nItems == p->nItemsAlloc ) - Fxu_HeapDoubleResize( p ); - // put the last entry to the last place and move up - p->pTree[++p->nItems] = pDiv; - pDiv->HNum = p->nItems; - // move the last entry up if necessary - Fxu_HeapDoubleMoveUp( p, pDiv ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapDoubleUpdate( Fxu_HeapDouble * p, Fxu_Double * pDiv ) -{ -//printf( "Updating divisor %d.\n", pDiv->Num ); - - FXU_HEAP_DOUBLE_ASSERT(p,pDiv); - if ( FXU_HEAP_DOUBLE_PARENT_EXISTS(p,pDiv) && - FXU_HEAP_DOUBLE_WEIGHT(pDiv) > FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_PARENT(p,pDiv) ) ) - Fxu_HeapDoubleMoveUp( p, pDiv ); - else if ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,pDiv) && - FXU_HEAP_DOUBLE_WEIGHT(pDiv) < FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD1(p,pDiv) ) ) - Fxu_HeapDoubleMoveDn( p, pDiv ); - else if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,pDiv) && - FXU_HEAP_DOUBLE_WEIGHT(pDiv) < FXU_HEAP_DOUBLE_WEIGHT( FXU_HEAP_DOUBLE_CHILD2(p,pDiv) ) ) - Fxu_HeapDoubleMoveDn( p, pDiv ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapDoubleDelete( Fxu_HeapDouble * p, Fxu_Double * pDiv ) -{ - FXU_HEAP_DOUBLE_ASSERT(p,pDiv); - // put the last entry to the deleted place - // decrement the number of entries - p->pTree[pDiv->HNum] = p->pTree[p->nItems--]; - p->pTree[pDiv->HNum]->HNum = pDiv->HNum; - // move the top entry down if necessary - Fxu_HeapDoubleUpdate( p, p->pTree[pDiv->HNum] ); - pDiv->HNum = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Double * Fxu_HeapDoubleReadMax( Fxu_HeapDouble * p ) -{ - if ( p->nItems == 0 ) - return NULL; - return p->pTree[1]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Double * Fxu_HeapDoubleGetMax( Fxu_HeapDouble * p ) -{ - Fxu_Double * pDiv; - if ( p->nItems == 0 ) - return NULL; - // prepare the return value - pDiv = p->pTree[1]; - pDiv->HNum = 0; - // put the last entry on top - // decrement the number of entries - p->pTree[1] = p->pTree[p->nItems--]; - p->pTree[1]->HNum = 1; - // move the top entry down if necessary - Fxu_HeapDoubleMoveDn( p, p->pTree[1] ); - return pDiv; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_HeapDoubleReadMaxWeight( Fxu_HeapDouble * p ) -{ - if ( p->nItems == 0 ) - return -1; - else - return FXU_HEAP_DOUBLE_WEIGHT(p->pTree[1]); -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapDoubleSwap( Fxu_Double ** pDiv1, Fxu_Double ** pDiv2 ) -{ - Fxu_Double * pDiv; - int Temp; - pDiv = *pDiv1; - *pDiv1 = *pDiv2; - *pDiv2 = pDiv; - Temp = (*pDiv1)->HNum; - (*pDiv1)->HNum = (*pDiv2)->HNum; - (*pDiv2)->HNum = Temp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapDoubleMoveUp( Fxu_HeapDouble * p, Fxu_Double * pDiv ) -{ - Fxu_Double ** ppDiv, ** ppPar; - ppDiv = &FXU_HEAP_DOUBLE_CURRENT(p, pDiv); - while ( FXU_HEAP_DOUBLE_PARENT_EXISTS(p,*ppDiv) ) - { - ppPar = &FXU_HEAP_DOUBLE_PARENT(p,*ppDiv); - if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) > FXU_HEAP_DOUBLE_WEIGHT(*ppPar) ) - { - Fxu_HeapDoubleSwap( ppDiv, ppPar ); - ppDiv = ppPar; - } - else - break; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapDoubleMoveDn( Fxu_HeapDouble * p, Fxu_Double * pDiv ) -{ - Fxu_Double ** ppChild1, ** ppChild2, ** ppDiv; - ppDiv = &FXU_HEAP_DOUBLE_CURRENT(p, pDiv); - while ( FXU_HEAP_DOUBLE_CHILD1_EXISTS(p,*ppDiv) ) - { // if Child1 does not exist, Child2 also does not exists - - // get the children - ppChild1 = &FXU_HEAP_DOUBLE_CHILD1(p,*ppDiv); - if ( FXU_HEAP_DOUBLE_CHILD2_EXISTS(p,*ppDiv) ) - { - ppChild2 = &FXU_HEAP_DOUBLE_CHILD2(p,*ppDiv); - - // consider two cases - if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) && - FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild2) ) - { // Div is larger than both, skip - break; - } - else - { // Div is smaller than one of them, then swap it with larger - if ( FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild2) ) - { - Fxu_HeapDoubleSwap( ppDiv, ppChild1 ); - // update the pointer - ppDiv = ppChild1; - } - else - { - Fxu_HeapDoubleSwap( ppDiv, ppChild2 ); - // update the pointer - ppDiv = ppChild2; - } - } - } - else // Child2 does not exist - { - // consider two cases - if ( FXU_HEAP_DOUBLE_WEIGHT(*ppDiv) >= FXU_HEAP_DOUBLE_WEIGHT(*ppChild1) ) - { // Div is larger than Child1, skip - break; - } - else - { // Div is smaller than Child1, then swap them - Fxu_HeapDoubleSwap( ppDiv, ppChild1 ); - // update the pointer - ppDiv = ppChild1; - } - } - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/fxu/fxuHeapS.c b/src/opt/fxu/fxuHeapS.c deleted file mode 100644 index eaca8363..00000000 --- a/src/opt/fxu/fxuHeapS.c +++ /dev/null @@ -1,444 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuHeapS.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [The priority queue for variables.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuHeapS.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fxuInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define FXU_HEAP_SINGLE_WEIGHT(pSingle) ((pSingle)->Weight) -#define FXU_HEAP_SINGLE_CURRENT(p, pSingle) ((p)->pTree[(pSingle)->HNum]) -#define FXU_HEAP_SINGLE_PARENT_EXISTS(p, pSingle) ((pSingle)->HNum > 1) -#define FXU_HEAP_SINGLE_CHILD1_EXISTS(p, pSingle) (((pSingle)->HNum << 1) <= p->nItems) -#define FXU_HEAP_SINGLE_CHILD2_EXISTS(p, pSingle) ((((pSingle)->HNum << 1)+1) <= p->nItems) -#define FXU_HEAP_SINGLE_PARENT(p, pSingle) ((p)->pTree[(pSingle)->HNum >> 1]) -#define FXU_HEAP_SINGLE_CHILD1(p, pSingle) ((p)->pTree[(pSingle)->HNum << 1]) -#define FXU_HEAP_SINGLE_CHILD2(p, pSingle) ((p)->pTree[((pSingle)->HNum << 1)+1]) -#define FXU_HEAP_SINGLE_ASSERT(p, pSingle) assert( (pSingle)->HNum >= 1 && (pSingle)->HNum <= p->nItemsAlloc ) - -static void Fxu_HeapSingleResize( Fxu_HeapSingle * p ); -static void Fxu_HeapSingleSwap( Fxu_Single ** pSingle1, Fxu_Single ** pSingle2 ); -static void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle ); -static void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_HeapSingle * Fxu_HeapSingleStart() -{ - Fxu_HeapSingle * p; - p = ALLOC( Fxu_HeapSingle, 1 ); - memset( p, 0, sizeof(Fxu_HeapSingle) ); - p->nItems = 0; - p->nItemsAlloc = 2000; - p->pTree = ALLOC( Fxu_Single *, p->nItemsAlloc + 10 ); - p->pTree[0] = NULL; - return p; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapSingleResize( Fxu_HeapSingle * p ) -{ - p->nItemsAlloc *= 2; - p->pTree = REALLOC( Fxu_Single *, p->pTree, p->nItemsAlloc + 10 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapSingleStop( Fxu_HeapSingle * p ) -{ - int i; - i = 0; - free( p->pTree ); - i = 1; - free( p ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapSinglePrint( FILE * pFile, Fxu_HeapSingle * p ) -{ - Fxu_Single * pSingle; - int Counter = 1; - int Degree = 1; - - Fxu_HeapSingleCheck( p ); - fprintf( pFile, "The contents of the heap:\n" ); - fprintf( pFile, "Level %d: ", Degree ); - Fxu_HeapSingleForEachItem( p, pSingle ) - { - assert( Counter == p->pTree[Counter]->HNum ); - fprintf( pFile, "%2d=%3d ", Counter, FXU_HEAP_SINGLE_WEIGHT(p->pTree[Counter]) ); - if ( ++Counter == (1 << Degree) ) - { - fprintf( pFile, "\n" ); - Degree++; - fprintf( pFile, "Level %d: ", Degree ); - } - } - fprintf( pFile, "\n" ); - fprintf( pFile, "End of the heap printout.\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapSingleCheck( Fxu_HeapSingle * p ) -{ - Fxu_Single * pSingle; - Fxu_HeapSingleForEachItem( p, pSingle ) - { - assert( pSingle->HNum == p->i ); - Fxu_HeapSingleCheckOne( p, pSingle ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapSingleCheckOne( Fxu_HeapSingle * p, Fxu_Single * pSingle ) -{ - int Weight1, Weight2; - if ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,pSingle) ) - { - Weight1 = FXU_HEAP_SINGLE_WEIGHT(pSingle); - Weight2 = FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD1(p,pSingle) ); - assert( Weight1 >= Weight2 ); - } - if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,pSingle) ) - { - Weight1 = FXU_HEAP_SINGLE_WEIGHT(pSingle); - Weight2 = FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD2(p,pSingle) ); - assert( Weight1 >= Weight2 ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapSingleInsert( Fxu_HeapSingle * p, Fxu_Single * pSingle ) -{ - if ( p->nItems == p->nItemsAlloc ) - Fxu_HeapSingleResize( p ); - // put the last entry to the last place and move up - p->pTree[++p->nItems] = pSingle; - pSingle->HNum = p->nItems; - // move the last entry up if necessary - Fxu_HeapSingleMoveUp( p, pSingle ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapSingleUpdate( Fxu_HeapSingle * p, Fxu_Single * pSingle ) -{ - FXU_HEAP_SINGLE_ASSERT(p,pSingle); - if ( FXU_HEAP_SINGLE_PARENT_EXISTS(p,pSingle) && - FXU_HEAP_SINGLE_WEIGHT(pSingle) > FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_PARENT(p,pSingle) ) ) - Fxu_HeapSingleMoveUp( p, pSingle ); - else if ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,pSingle) && - FXU_HEAP_SINGLE_WEIGHT(pSingle) < FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD1(p,pSingle) ) ) - Fxu_HeapSingleMoveDn( p, pSingle ); - else if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,pSingle) && - FXU_HEAP_SINGLE_WEIGHT(pSingle) < FXU_HEAP_SINGLE_WEIGHT( FXU_HEAP_SINGLE_CHILD2(p,pSingle) ) ) - Fxu_HeapSingleMoveDn( p, pSingle ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapSingleDelete( Fxu_HeapSingle * p, Fxu_Single * pSingle ) -{ - int Place = pSingle->HNum; - FXU_HEAP_SINGLE_ASSERT(p,pSingle); - // put the last entry to the deleted place - // decrement the number of entries - p->pTree[Place] = p->pTree[p->nItems--]; - p->pTree[Place]->HNum = Place; - // move the top entry down if necessary - Fxu_HeapSingleUpdate( p, p->pTree[Place] ); - pSingle->HNum = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p ) -{ - if ( p->nItems == 0 ) - return NULL; - return p->pTree[1]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p ) -{ - Fxu_Single * pSingle; - if ( p->nItems == 0 ) - return NULL; - // prepare the return value - pSingle = p->pTree[1]; - pSingle->HNum = 0; - // put the last entry on top - // decrement the number of entries - p->pTree[1] = p->pTree[p->nItems--]; - p->pTree[1]->HNum = 1; - // move the top entry down if necessary - Fxu_HeapSingleMoveDn( p, p->pTree[1] ); - return pSingle; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p ) -{ - if ( p->nItems == 0 ) - return -1; - return FXU_HEAP_SINGLE_WEIGHT(p->pTree[1]); -} - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapSingleSwap( Fxu_Single ** pSingle1, Fxu_Single ** pSingle2 ) -{ - Fxu_Single * pSingle; - int Temp; - pSingle = *pSingle1; - *pSingle1 = *pSingle2; - *pSingle2 = pSingle; - Temp = (*pSingle1)->HNum; - (*pSingle1)->HNum = (*pSingle2)->HNum; - (*pSingle2)->HNum = Temp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapSingleMoveUp( Fxu_HeapSingle * p, Fxu_Single * pSingle ) -{ - Fxu_Single ** ppSingle, ** ppPar; - ppSingle = &FXU_HEAP_SINGLE_CURRENT(p, pSingle); - while ( FXU_HEAP_SINGLE_PARENT_EXISTS(p,*ppSingle) ) - { - ppPar = &FXU_HEAP_SINGLE_PARENT(p,*ppSingle); - if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) > FXU_HEAP_SINGLE_WEIGHT(*ppPar) ) - { - Fxu_HeapSingleSwap( ppSingle, ppPar ); - ppSingle = ppPar; - } - else - break; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_HeapSingleMoveDn( Fxu_HeapSingle * p, Fxu_Single * pSingle ) -{ - Fxu_Single ** ppChild1, ** ppChild2, ** ppSingle; - ppSingle = &FXU_HEAP_SINGLE_CURRENT(p, pSingle); - while ( FXU_HEAP_SINGLE_CHILD1_EXISTS(p,*ppSingle) ) - { // if Child1 does not exist, Child2 also does not exists - - // get the children - ppChild1 = &FXU_HEAP_SINGLE_CHILD1(p,*ppSingle); - if ( FXU_HEAP_SINGLE_CHILD2_EXISTS(p,*ppSingle) ) - { - ppChild2 = &FXU_HEAP_SINGLE_CHILD2(p,*ppSingle); - - // consider two cases - if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild1) && - FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild2) ) - { // Var is larger than both, skip - break; - } - else - { // Var is smaller than one of them, then swap it with larger - if ( FXU_HEAP_SINGLE_WEIGHT(*ppChild1) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild2) ) - { - Fxu_HeapSingleSwap( ppSingle, ppChild1 ); - // update the pointer - ppSingle = ppChild1; - } - else - { - Fxu_HeapSingleSwap( ppSingle, ppChild2 ); - // update the pointer - ppSingle = ppChild2; - } - } - } - else // Child2 does not exist - { - // consider two cases - if ( FXU_HEAP_SINGLE_WEIGHT(*ppSingle) >= FXU_HEAP_SINGLE_WEIGHT(*ppChild1) ) - { // Var is larger than Child1, skip - break; - } - else - { // Var is smaller than Child1, then swap them - Fxu_HeapSingleSwap( ppSingle, ppChild1 ); - // update the pointer - ppSingle = ppChild1; - } - } - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/opt/fxu/fxuInt.h b/src/opt/fxu/fxuInt.h deleted file mode 100644 index ea85cb79..00000000 --- a/src/opt/fxu/fxuInt.h +++ /dev/null @@ -1,539 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuInt.h] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Internal declarations of fast extract for unate covers.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuInt.h,v 1.3 2003/04/10 05:42:44 donald Exp $] - -***********************************************************************/ - -#ifndef __FXU_INT_H__ -#define __FXU_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "extra.h" -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -// uncomment this macro to switch to standard memory management -//#define USE_SYSTEM_MEMORY_MANAGEMENT - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/* - Here is an informal description of the FX data structure. - (1) The sparse matrix is filled with literals, associated with - cubes (row) and variables (columns). The matrix contains - all the cubes of all the nodes in the network. - (2) A cube is associated with - (a) its literals in the matrix, - (b) the output variable of the node, to which this cube belongs, - (3) A variable is associated with - (a) its literals in the matrix and - (b) the list of cube pairs in the cover, for which it is the output - (4) A cube pair is associated with two cubes and contains the counters - of literals in the base and in the cubes without the base - (5) A double-cube divisor is associated with list of all cube pairs - that produce it and its current weight (which is updated automatically - each time a new pair is added or an old pair is removed). - (6) A single-cube divisor is associated the pair of variables. -*/ - -// sparse matrix -typedef struct FxuMatrix Fxu_Matrix; // the sparse matrix - -// sparse matrix contents: cubes (rows), vars (columns), literals (entries) -typedef struct FxuCube Fxu_Cube; // one cube in the sparse matrix -typedef struct FxuVar Fxu_Var; // one literal in the sparse matrix -typedef struct FxuLit Fxu_Lit; // one entry in the sparse matrix - -// double cube divisors -typedef struct FxuPair Fxu_Pair; // the pair of cubes -typedef struct FxuDouble Fxu_Double; // the double-cube divisor -typedef struct FxuSingle Fxu_Single; // the two-literal single-cube divisor - -// various lists -typedef struct FxuListCube Fxu_ListCube; // the list of cubes -typedef struct FxuListVar Fxu_ListVar; // the list of literals -typedef struct FxuListLit Fxu_ListLit; // the list of entries -typedef struct FxuListPair Fxu_ListPair; // the list of pairs -typedef struct FxuListDouble Fxu_ListDouble; // the list of divisors -typedef struct FxuListSingle Fxu_ListSingle; // the list of single-cube divisors - -// various heaps -typedef struct FxuHeapDouble Fxu_HeapDouble; // the heap of divisors -typedef struct FxuHeapSingle Fxu_HeapSingle; // the heap of variables - - -// various lists - -// the list of cubes in the sparse matrix -struct FxuListCube -{ - Fxu_Cube * pHead; - Fxu_Cube * pTail; - int nItems; -}; - -// the list of literals in the sparse matrix -struct FxuListVar -{ - Fxu_Var * pHead; - Fxu_Var * pTail; - int nItems; -}; - -// the list of entries in the sparse matrix -struct FxuListLit -{ - Fxu_Lit * pHead; - Fxu_Lit * pTail; - int nItems; -}; - -// the list of cube pair in the sparse matrix -struct FxuListPair -{ - Fxu_Pair * pHead; - Fxu_Pair * pTail; - int nItems; -}; - -// the list of divisors in the sparse matrix -struct FxuListDouble -{ - Fxu_Double * pHead; - Fxu_Double * pTail; - int nItems; -}; - -// the list of divisors in the sparse matrix -struct FxuListSingle -{ - Fxu_Single * pHead; - Fxu_Single * pTail; - int nItems; -}; - - -// various heaps - -// the heap of double cube divisors by weight -struct FxuHeapDouble -{ - Fxu_Double ** pTree; - int nItems; - int nItemsAlloc; - int i; -}; - -// the heap of variable by their occurrence in the cubes -struct FxuHeapSingle -{ - Fxu_Single ** pTree; - int nItems; - int nItemsAlloc; - int i; -}; - - - -// sparse matrix -struct FxuMatrix // ~ 30 words -{ - // the cubes - Fxu_ListCube lCubes; // the double linked list of cubes - // the values (binary literals) - Fxu_ListVar lVars; // the double linked list of variables - Fxu_Var ** ppVars; // the array of variables - // the double cube divisors - Fxu_ListDouble * pTable; // the hash table of divisors - int nTableSize; // the hash table size - int nDivs; // the number of divisors in the table - int nDivsTotal; // the number of divisors in the table - Fxu_HeapDouble * pHeapDouble; // the heap of divisors by weight - // the single cube divisors - Fxu_ListSingle lSingles; // the linked list of single cube divisors - Fxu_HeapSingle * pHeapSingle; // the heap of variables by the number of literals in the matrix - int nWeightLimit;// the limit on weight of single cube divisors collected - int nSingleTotal;// the total number of single cube divisors - // storage for cube pairs - Fxu_Pair *** pppPairs; - Fxu_Pair ** ppPairs; - // temporary storage for cubes - Fxu_Cube * pOrderCubes; - Fxu_Cube ** ppTailCubes; - // temporary storage for variables - Fxu_Var * pOrderVars; - Fxu_Var ** ppTailVars; - // temporary storage for pairs - Vec_Ptr_t * vPairs; - // statistics - int nEntries; // the total number of entries in the sparse matrix - int nDivs1; // the single cube divisors taken - int nDivs2; // the double cube divisors taken - int nDivs3; // the double cube divisors with complement - // memory manager - Extra_MmFixed_t * pMemMan; // the memory manager for all small sized entries -}; - -// the cube in the sparse matrix -struct FxuCube // 9 words -{ - int iCube; // the number of this cube in the cover - Fxu_Cube * pFirst; // the pointer to the first cube of this cover - Fxu_Var * pVar; // the variable representing the output of the cover - Fxu_ListLit lLits; // the row in the table - Fxu_Cube * pPrev; // the previous cube - Fxu_Cube * pNext; // the next cube - Fxu_Cube * pOrder; // the specialized linked list of cubes -}; - -// the variable in the sparse matrix -struct FxuVar // 10 words -{ - int iVar; // the number of this variable - int nCubes; // the number of cubes assoc with this var - Fxu_Cube * pFirst; // the first cube assoc with this var - Fxu_Pair *** ppPairs; // the pairs of cubes assoc with this var - Fxu_ListLit lLits; // the column in the table - Fxu_Var * pPrev; // the previous variable - Fxu_Var * pNext; // the next variable - Fxu_Var * pOrder; // the specialized linked list of variables -}; - -// the literal entry in the sparse matrix -struct FxuLit // 8 words -{ - int iVar; // the number of this variable - int iCube; // the number of this cube - Fxu_Cube * pCube; // the cube of this literal - Fxu_Var * pVar; // the variable of this literal - Fxu_Lit * pHPrev; // prev lit in the cube - Fxu_Lit * pHNext; // next lit in the cube - Fxu_Lit * pVPrev; // prev lit of the var - Fxu_Lit * pVNext; // next lit of the var -}; - -// the cube pair -struct FxuPair // 10 words -{ - int nLits1; // the number of literals in the two cubes - int nLits2; // the number of literals in the two cubes - int nBase; // the number of literals in the base - Fxu_Double * pDiv; // the divisor of this pair - Fxu_Cube * pCube1; // the first cube of the pair - Fxu_Cube * pCube2; // the second cube of the pair - int iCube1; // the first cube of the pair - int iCube2; // the second cube of the pair - Fxu_Pair * pDPrev; // the previous pair in the divisor - Fxu_Pair * pDNext; // the next pair in the divisor -}; - -// the double cube divisor -struct FxuDouble // 10 words -{ - int Num; // the unique number of this divisor - int HNum; // the heap number of this divisor - int Weight; // the weight of this divisor - unsigned Key; // the hash key of this divisor - Fxu_ListPair lPairs; // the pairs of cubes, which produce this divisor - Fxu_Double * pPrev; // the previous divisor in the table - Fxu_Double * pNext; // the next divisor in the table - Fxu_Double * pOrder; // the specialized linked list of divisors -}; - -// the single cube divisor -struct FxuSingle // 7 words -{ - int Num; // the unique number of this divisor - int HNum; // the heap number of this divisor - int Weight; // the weight of this divisor - Fxu_Var * pVar1; // the first variable of the single-cube divisor - Fxu_Var * pVar2; // the second variable of the single-cube divisor - Fxu_Single * pPrev; // the previous divisor in the list - Fxu_Single * pNext; // the next divisor in the list -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// minimum/maximum -#define Fxu_Min( a, b ) ( ((a)<(b))? (a):(b) ) -#define Fxu_Max( a, b ) ( ((a)>(b))? (a):(b) ) - -// selection of the minimum/maximum cube in the pair -#define Fxu_PairMinCube( pPair ) (((pPair)->iCube1 < (pPair)->iCube2)? (pPair)->pCube1: (pPair)->pCube2) -#define Fxu_PairMaxCube( pPair ) (((pPair)->iCube1 > (pPair)->iCube2)? (pPair)->pCube1: (pPair)->pCube2) -#define Fxu_PairMinCubeInt( pPair ) (((pPair)->iCube1 < (pPair)->iCube2)? (pPair)->iCube1: (pPair)->iCube2) -#define Fxu_PairMaxCubeInt( pPair ) (((pPair)->iCube1 > (pPair)->iCube2)? (pPair)->iCube1: (pPair)->iCube2) - -// iterators - -#define Fxu_MatrixForEachCube( Matrix, Cube )\ - for ( Cube = (Matrix)->lCubes.pHead;\ - Cube;\ - Cube = Cube->pNext ) -#define Fxu_MatrixForEachCubeSafe( Matrix, Cube, Cube2 )\ - for ( Cube = (Matrix)->lCubes.pHead, Cube2 = (Cube? Cube->pNext: NULL);\ - Cube;\ - Cube = Cube2, Cube2 = (Cube? Cube->pNext: NULL) ) - -#define Fxu_MatrixForEachVariable( Matrix, Var )\ - for ( Var = (Matrix)->lVars.pHead;\ - Var;\ - Var = Var->pNext ) -#define Fxu_MatrixForEachVariableSafe( Matrix, Var, Var2 )\ - for ( Var = (Matrix)->lVars.pHead, Var2 = (Var? Var->pNext: NULL);\ - Var;\ - Var = Var2, Var2 = (Var? Var->pNext: NULL) ) - -#define Fxu_MatrixForEachSingle( Matrix, Single )\ - for ( Single = (Matrix)->lSingles.pHead;\ - Single;\ - Single = Single->pNext ) -#define Fxu_MatrixForEachSingleSafe( Matrix, Single, Single2 )\ - for ( Single = (Matrix)->lSingles.pHead, Single2 = (Single? Single->pNext: NULL);\ - Single;\ - Single = Single2, Single2 = (Single? Single->pNext: NULL) ) - -#define Fxu_TableForEachDouble( Matrix, Key, Div )\ - for ( Div = (Matrix)->pTable[Key].pHead;\ - Div;\ - Div = Div->pNext ) -#define Fxu_TableForEachDoubleSafe( Matrix, Key, Div, Div2 )\ - for ( Div = (Matrix)->pTable[Key].pHead, Div2 = (Div? Div->pNext: NULL);\ - Div;\ - Div = Div2, Div2 = (Div? Div->pNext: NULL) ) - -#define Fxu_MatrixForEachDouble( Matrix, Div, Index )\ - for ( Index = 0; Index < (Matrix)->nTableSize; Index++ )\ - Fxu_TableForEachDouble( Matrix, Index, Div ) -#define Fxu_MatrixForEachDoubleSafe( Matrix, Div, Div2, Index )\ - for ( Index = 0; Index < (Matrix)->nTableSize; Index++ )\ - Fxu_TableForEachDoubleSafe( Matrix, Index, Div, Div2 ) - - -#define Fxu_CubeForEachLiteral( Cube, Lit )\ - for ( Lit = (Cube)->lLits.pHead;\ - Lit;\ - Lit = Lit->pHNext ) -#define Fxu_CubeForEachLiteralSafe( Cube, Lit, Lit2 )\ - for ( Lit = (Cube)->lLits.pHead, Lit2 = (Lit? Lit->pHNext: NULL);\ - Lit;\ - Lit = Lit2, Lit2 = (Lit? Lit->pHNext: NULL) ) - -#define Fxu_VarForEachLiteral( Var, Lit )\ - for ( Lit = (Var)->lLits.pHead;\ - Lit;\ - Lit = Lit->pVNext ) - -#define Fxu_CubeForEachDivisor( Cube, Div )\ - for ( Div = (Cube)->lDivs.pHead;\ - Div;\ - Div = Div->pCNext ) - -#define Fxu_DoubleForEachPair( Div, Pair )\ - for ( Pair = (Div)->lPairs.pHead;\ - Pair;\ - Pair = Pair->pDNext ) -#define Fxu_DoubleForEachPairSafe( Div, Pair, Pair2 )\ - for ( Pair = (Div)->lPairs.pHead, Pair2 = (Pair? Pair->pDNext: NULL);\ - Pair;\ - Pair = Pair2, Pair2 = (Pair? Pair->pDNext: NULL) ) - - -// iterator through the cube pairs belonging to the given cube -#define Fxu_CubeForEachPair( pCube, pPair, i )\ - for ( i = 0;\ - i < pCube->pVar->nCubes &&\ - (((unsigned)(pPair = pCube->pVar->ppPairs[pCube->iCube][i])) >= 0);\ - i++ )\ - if ( pPair ) - -// iterator through all the items in the heap -#define Fxu_HeapDoubleForEachItem( Heap, Div )\ - for ( Heap->i = 1;\ - Heap->i <= Heap->nItems && (Div = Heap->pTree[Heap->i]);\ - Heap->i++ ) -#define Fxu_HeapSingleForEachItem( Heap, Single )\ - for ( Heap->i = 1;\ - Heap->i <= Heap->nItems && (Single = Heap->pTree[Heap->i]);\ - Heap->i++ ) - -// starting the rings -#define Fxu_MatrixRingCubesStart( Matrix ) (((Matrix)->ppTailCubes = &((Matrix)->pOrderCubes)), ((Matrix)->pOrderCubes = NULL)) -#define Fxu_MatrixRingVarsStart( Matrix ) (((Matrix)->ppTailVars = &((Matrix)->pOrderVars)), ((Matrix)->pOrderVars = NULL)) -// stopping the rings -#define Fxu_MatrixRingCubesStop( Matrix ) -#define Fxu_MatrixRingVarsStop( Matrix ) -// resetting the rings -#define Fxu_MatrixRingCubesReset( Matrix ) (((Matrix)->pOrderCubes = NULL), ((Matrix)->ppTailCubes = NULL)) -#define Fxu_MatrixRingVarsReset( Matrix ) (((Matrix)->pOrderVars = NULL), ((Matrix)->ppTailVars = NULL)) -// adding to the rings -#define Fxu_MatrixRingCubesAdd( Matrix, Cube) ((*((Matrix)->ppTailCubes) = Cube), ((Matrix)->ppTailCubes = &(Cube)->pOrder), ((Cube)->pOrder = (Fxu_Cube *)1)) -#define Fxu_MatrixRingVarsAdd( Matrix, Var ) ((*((Matrix)->ppTailVars ) = Var ), ((Matrix)->ppTailVars = &(Var)->pOrder ), ((Var)->pOrder = (Fxu_Var *)1)) -// iterating through the rings -#define Fxu_MatrixForEachCubeInRing( Matrix, Cube )\ - if ( (Matrix)->pOrderCubes )\ - for ( Cube = (Matrix)->pOrderCubes;\ - Cube != (Fxu_Cube *)1;\ - Cube = Cube->pOrder ) -#define Fxu_MatrixForEachCubeInRingSafe( Matrix, Cube, Cube2 )\ - if ( (Matrix)->pOrderCubes )\ - for ( Cube = (Matrix)->pOrderCubes, Cube2 = ((Cube != (Fxu_Cube *)1)? Cube->pOrder: (Fxu_Cube *)1);\ - Cube != (Fxu_Cube *)1;\ - Cube = Cube2, Cube2 = ((Cube != (Fxu_Cube *)1)? Cube->pOrder: (Fxu_Cube *)1) ) -#define Fxu_MatrixForEachVarInRing( Matrix, Var )\ - if ( (Matrix)->pOrderVars )\ - for ( Var = (Matrix)->pOrderVars;\ - Var != (Fxu_Var *)1;\ - Var = Var->pOrder ) -#define Fxu_MatrixForEachVarInRingSafe( Matrix, Var, Var2 )\ - if ( (Matrix)->pOrderVars )\ - for ( Var = (Matrix)->pOrderVars, Var2 = ((Var != (Fxu_Var *)1)? Var->pOrder: (Fxu_Var *)1);\ - Var != (Fxu_Var *)1;\ - Var = Var2, Var2 = ((Var != (Fxu_Var *)1)? Var->pOrder: (Fxu_Var *)1) ) -// the procedures are related to the above macros -extern void Fxu_MatrixRingCubesUnmark( Fxu_Matrix * p ); -extern void Fxu_MatrixRingVarsUnmark( Fxu_Matrix * p ); - - -// macros working with memory -// MEM_ALLOC: allocate the given number (Size) of items of type (Type) -// MEM_FREE: deallocate the pointer (Pointer) to the given number (Size) of items of type (Type) -#ifdef USE_SYSTEM_MEMORY_MANAGEMENT -#define MEM_ALLOC_FXU( Manager, Type, Size ) ((Type *)malloc( (Size) * sizeof(Type) )) -#define MEM_FREE_FXU( Manager, Type, Size, Pointer ) if ( Pointer ) { free(Pointer); Pointer = NULL; } -#else -#define MEM_ALLOC_FXU( Manager, Type, Size )\ - ((Type *)Fxu_MemFetch( Manager, (Size) * sizeof(Type) )) -#define MEM_FREE_FXU( Manager, Type, Size, Pointer )\ - if ( Pointer ) { Fxu_MemRecycle( Manager, (char *)(Pointer), (Size) * sizeof(Type) ); Pointer = NULL; } -#endif - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*===== fxu.c ====================================================*/ -extern char * Fxu_MemFetch( Fxu_Matrix * p, int nBytes ); -extern void Fxu_MemRecycle( Fxu_Matrix * p, char * pItem, int nBytes ); -/*===== fxuCreate.c ====================================================*/ -/*===== fxuReduce.c ====================================================*/ -/*===== fxuPrint.c ====================================================*/ -extern void Fxu_MatrixPrint( FILE * pFile, Fxu_Matrix * p ); -extern void Fxu_MatrixPrintDivisorProfile( FILE * pFile, Fxu_Matrix * p ); -/*===== fxuSelect.c ====================================================*/ -extern int Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble ); -extern int Fxu_SelectSCD( Fxu_Matrix * p, int Weight, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 ); -/*===== fxuUpdate.c ====================================================*/ -extern void Fxu_Update( Fxu_Matrix * p, Fxu_Single * pSingle, Fxu_Double * pDouble ); -extern void Fxu_UpdateDouble( Fxu_Matrix * p ); -extern void Fxu_UpdateSingle( Fxu_Matrix * p ); -/*===== fxuPair.c ====================================================*/ -extern void Fxu_PairCanonicize( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 ); -extern unsigned Fxu_PairHashKeyArray( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ); -extern unsigned Fxu_PairHashKey( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, int * pnBase, int * pnLits1, int * pnLits2 ); -extern unsigned Fxu_PairHashKeyMv( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, int * pnBase, int * pnLits1, int * pnLits2 ); -extern int Fxu_PairCompare( Fxu_Pair * pPair1, Fxu_Pair * pPair2 ); -extern void Fxu_PairAllocStorage( Fxu_Var * pVar, int nCubes ); -extern void Fxu_PairFreeStorage( Fxu_Var * pVar ); -extern void Fxu_PairClearStorage( Fxu_Cube * pCube ); -extern Fxu_Pair * Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ); -extern void Fxu_PairAdd( Fxu_Pair * pPair ); -/*===== fxuSingle.c ====================================================*/ -extern void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax ); -extern void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar ); -extern int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 ); -/*===== fxuMatrix.c ====================================================*/ -// matrix -extern Fxu_Matrix * Fxu_MatrixAllocate(); -extern void Fxu_MatrixDelete( Fxu_Matrix * p ); -// double-cube divisor -extern void Fxu_MatrixAddDivisor( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ); -extern void Fxu_MatrixDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ); -// single-cube divisor -extern void Fxu_MatrixAddSingle( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, int Weight ); -// variable -extern Fxu_Var * Fxu_MatrixAddVar( Fxu_Matrix * p ); -// cube -extern Fxu_Cube * Fxu_MatrixAddCube( Fxu_Matrix * p, Fxu_Var * pVar, int iCube ); -// literal -extern void Fxu_MatrixAddLiteral( Fxu_Matrix * p, Fxu_Cube * pCube, Fxu_Var * pVar ); -extern void Fxu_MatrixDelLiteral( Fxu_Matrix * p, Fxu_Lit * pLit ); -/*===== fxuList.c ====================================================*/ -// matrix -> variable -extern void Fxu_ListMatrixAddVariable( Fxu_Matrix * p, Fxu_Var * pVar ); -extern void Fxu_ListMatrixDelVariable( Fxu_Matrix * p, Fxu_Var * pVar ); -// matrix -> cube -extern void Fxu_ListMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube ); -extern void Fxu_ListMatrixDelCube( Fxu_Matrix * p, Fxu_Cube * pCube ); -// matrix -> single -extern void Fxu_ListMatrixAddSingle( Fxu_Matrix * p, Fxu_Single * pSingle ); -extern void Fxu_ListMatrixDelSingle( Fxu_Matrix * p, Fxu_Single * pSingle ); -// table -> divisor -extern void Fxu_ListTableAddDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ); -extern void Fxu_ListTableDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ); -// cube -> literal -extern void Fxu_ListCubeAddLiteral( Fxu_Cube * pCube, Fxu_Lit * pLit ); -extern void Fxu_ListCubeDelLiteral( Fxu_Cube * pCube, Fxu_Lit * pLit ); -// var -> literal -extern void Fxu_ListVarAddLiteral( Fxu_Var * pVar, Fxu_Lit * pLit ); -extern void Fxu_ListVarDelLiteral( Fxu_Var * pVar, Fxu_Lit * pLit ); -// divisor -> pair -extern void Fxu_ListDoubleAddPairLast( Fxu_Double * pDiv, Fxu_Pair * pLink ); -extern void Fxu_ListDoubleAddPairFirst( Fxu_Double * pDiv, Fxu_Pair * pLink ); -extern void Fxu_ListDoubleAddPairMiddle( Fxu_Double * pDiv, Fxu_Pair * pSpot, Fxu_Pair * pLink ); -extern void Fxu_ListDoubleDelPair( Fxu_Double * pDiv, Fxu_Pair * pPair ); -/*===== fxuHeapDouble.c ====================================================*/ -extern Fxu_HeapDouble * Fxu_HeapDoubleStart(); -extern void Fxu_HeapDoubleStop( Fxu_HeapDouble * p ); -extern void Fxu_HeapDoublePrint( FILE * pFile, Fxu_HeapDouble * p ); -extern void Fxu_HeapDoubleCheck( Fxu_HeapDouble * p ); -extern void Fxu_HeapDoubleCheckOne( Fxu_HeapDouble * p, Fxu_Double * pDiv ); - -extern void Fxu_HeapDoubleInsert( Fxu_HeapDouble * p, Fxu_Double * pDiv ); -extern void Fxu_HeapDoubleUpdate( Fxu_HeapDouble * p, Fxu_Double * pDiv ); -extern void Fxu_HeapDoubleDelete( Fxu_HeapDouble * p, Fxu_Double * pDiv ); -extern int Fxu_HeapDoubleReadMaxWeight( Fxu_HeapDouble * p ); -extern Fxu_Double * Fxu_HeapDoubleReadMax( Fxu_HeapDouble * p ); -extern Fxu_Double * Fxu_HeapDoubleGetMax( Fxu_HeapDouble * p ); -/*===== fxuHeapSingle.c ====================================================*/ -extern Fxu_HeapSingle * Fxu_HeapSingleStart(); -extern void Fxu_HeapSingleStop( Fxu_HeapSingle * p ); -extern void Fxu_HeapSinglePrint( FILE * pFile, Fxu_HeapSingle * p ); -extern void Fxu_HeapSingleCheck( Fxu_HeapSingle * p ); -extern void Fxu_HeapSingleCheckOne( Fxu_HeapSingle * p, Fxu_Single * pSingle ); - -extern void Fxu_HeapSingleInsert( Fxu_HeapSingle * p, Fxu_Single * pSingle ); -extern void Fxu_HeapSingleUpdate( Fxu_HeapSingle * p, Fxu_Single * pSingle ); -extern void Fxu_HeapSingleDelete( Fxu_HeapSingle * p, Fxu_Single * pSingle ); -extern int Fxu_HeapSingleReadMaxWeight( Fxu_HeapSingle * p ); -extern Fxu_Single * Fxu_HeapSingleReadMax( Fxu_HeapSingle * p ); -extern Fxu_Single * Fxu_HeapSingleGetMax( Fxu_HeapSingle * p ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/fxu/fxuList.c b/src/opt/fxu/fxuList.c deleted file mode 100644 index 52995804..00000000 --- a/src/opt/fxu/fxuList.c +++ /dev/null @@ -1,522 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuList.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Operations on lists.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuList.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fxuInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// matrix -> var - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListMatrixAddVariable( Fxu_Matrix * p, Fxu_Var * pLink ) -{ - Fxu_ListVar * pList = &p->lVars; - if ( pList->pHead == NULL ) - { - pList->pHead = pLink; - pList->pTail = pLink; - pLink->pPrev = NULL; - pLink->pNext = NULL; - } - else - { - pLink->pNext = NULL; - pList->pTail->pNext = pLink; - pLink->pPrev = pList->pTail; - pList->pTail = pLink; - } - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListMatrixDelVariable( Fxu_Matrix * p, Fxu_Var * pLink ) -{ - Fxu_ListVar * pList = &p->lVars; - if ( pList->pHead == pLink ) - pList->pHead = pLink->pNext; - if ( pList->pTail == pLink ) - pList->pTail = pLink->pPrev; - if ( pLink->pPrev ) - pLink->pPrev->pNext = pLink->pNext; - if ( pLink->pNext ) - pLink->pNext->pPrev = pLink->pPrev; - pList->nItems--; -} - - -// matrix -> cube - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pLink ) -{ - Fxu_ListCube * pList = &p->lCubes; - if ( pList->pHead == NULL ) - { - pList->pHead = pLink; - pList->pTail = pLink; - pLink->pPrev = NULL; - pLink->pNext = NULL; - } - else - { - pLink->pNext = NULL; - pList->pTail->pNext = pLink; - pLink->pPrev = pList->pTail; - pList->pTail = pLink; - } - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListMatrixDelCube( Fxu_Matrix * p, Fxu_Cube * pLink ) -{ - Fxu_ListCube * pList = &p->lCubes; - if ( pList->pHead == pLink ) - pList->pHead = pLink->pNext; - if ( pList->pTail == pLink ) - pList->pTail = pLink->pPrev; - if ( pLink->pPrev ) - pLink->pPrev->pNext = pLink->pNext; - if ( pLink->pNext ) - pLink->pNext->pPrev = pLink->pPrev; - pList->nItems--; -} - - -// matrix -> single - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListMatrixAddSingle( Fxu_Matrix * p, Fxu_Single * pLink ) -{ - Fxu_ListSingle * pList = &p->lSingles; - if ( pList->pHead == NULL ) - { - pList->pHead = pLink; - pList->pTail = pLink; - pLink->pPrev = NULL; - pLink->pNext = NULL; - } - else - { - pLink->pNext = NULL; - pList->pTail->pNext = pLink; - pLink->pPrev = pList->pTail; - pList->pTail = pLink; - } - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListMatrixDelSingle( Fxu_Matrix * p, Fxu_Single * pLink ) -{ - Fxu_ListSingle * pList = &p->lSingles; - if ( pList->pHead == pLink ) - pList->pHead = pLink->pNext; - if ( pList->pTail == pLink ) - pList->pTail = pLink->pPrev; - if ( pLink->pPrev ) - pLink->pPrev->pNext = pLink->pNext; - if ( pLink->pNext ) - pLink->pNext->pPrev = pLink->pPrev; - pList->nItems--; -} - - -// table -> divisor - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListTableAddDivisor( Fxu_Matrix * p, Fxu_Double * pLink ) -{ - Fxu_ListDouble * pList = &(p->pTable[pLink->Key]); - if ( pList->pHead == NULL ) - { - pList->pHead = pLink; - pList->pTail = pLink; - pLink->pPrev = NULL; - pLink->pNext = NULL; - } - else - { - pLink->pNext = NULL; - pList->pTail->pNext = pLink; - pLink->pPrev = pList->pTail; - pList->pTail = pLink; - } - pList->nItems++; - p->nDivs++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListTableDelDivisor( Fxu_Matrix * p, Fxu_Double * pLink ) -{ - Fxu_ListDouble * pList = &(p->pTable[pLink->Key]); - if ( pList->pHead == pLink ) - pList->pHead = pLink->pNext; - if ( pList->pTail == pLink ) - pList->pTail = pLink->pPrev; - if ( pLink->pPrev ) - pLink->pPrev->pNext = pLink->pNext; - if ( pLink->pNext ) - pLink->pNext->pPrev = pLink->pPrev; - pList->nItems--; - p->nDivs--; -} - - -// cube -> literal - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListCubeAddLiteral( Fxu_Cube * pCube, Fxu_Lit * pLink ) -{ - Fxu_ListLit * pList = &(pCube->lLits); - if ( pList->pHead == NULL ) - { - pList->pHead = pLink; - pList->pTail = pLink; - pLink->pHPrev = NULL; - pLink->pHNext = NULL; - } - else - { - pLink->pHNext = NULL; - pList->pTail->pHNext = pLink; - pLink->pHPrev = pList->pTail; - pList->pTail = pLink; - } - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListCubeDelLiteral( Fxu_Cube * pCube, Fxu_Lit * pLink ) -{ - Fxu_ListLit * pList = &(pCube->lLits); - if ( pList->pHead == pLink ) - pList->pHead = pLink->pHNext; - if ( pList->pTail == pLink ) - pList->pTail = pLink->pHPrev; - if ( pLink->pHPrev ) - pLink->pHPrev->pHNext = pLink->pHNext; - if ( pLink->pHNext ) - pLink->pHNext->pHPrev = pLink->pHPrev; - pList->nItems--; -} - - -// var -> literal - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListVarAddLiteral( Fxu_Var * pVar, Fxu_Lit * pLink ) -{ - Fxu_ListLit * pList = &(pVar->lLits); - if ( pList->pHead == NULL ) - { - pList->pHead = pLink; - pList->pTail = pLink; - pLink->pVPrev = NULL; - pLink->pVNext = NULL; - } - else - { - pLink->pVNext = NULL; - pList->pTail->pVNext = pLink; - pLink->pVPrev = pList->pTail; - pList->pTail = pLink; - } - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListVarDelLiteral( Fxu_Var * pVar, Fxu_Lit * pLink ) -{ - Fxu_ListLit * pList = &(pVar->lLits); - if ( pList->pHead == pLink ) - pList->pHead = pLink->pVNext; - if ( pList->pTail == pLink ) - pList->pTail = pLink->pVPrev; - if ( pLink->pVPrev ) - pLink->pVPrev->pVNext = pLink->pVNext; - if ( pLink->pVNext ) - pLink->pVNext->pVPrev = pLink->pVPrev; - pList->nItems--; -} - - - -// divisor -> pair - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListDoubleAddPairLast( Fxu_Double * pDiv, Fxu_Pair * pLink ) -{ - Fxu_ListPair * pList = &pDiv->lPairs; - if ( pList->pHead == NULL ) - { - pList->pHead = pLink; - pList->pTail = pLink; - pLink->pDPrev = NULL; - pLink->pDNext = NULL; - } - else - { - pLink->pDNext = NULL; - pList->pTail->pDNext = pLink; - pLink->pDPrev = pList->pTail; - pList->pTail = pLink; - } - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListDoubleAddPairFirst( Fxu_Double * pDiv, Fxu_Pair * pLink ) -{ - Fxu_ListPair * pList = &pDiv->lPairs; - if ( pList->pHead == NULL ) - { - pList->pHead = pLink; - pList->pTail = pLink; - pLink->pDPrev = NULL; - pLink->pDNext = NULL; - } - else - { - pLink->pDPrev = NULL; - pList->pHead->pDPrev = pLink; - pLink->pDNext = pList->pHead; - pList->pHead = pLink; - } - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [Adds the entry in the middle of the list after the spot.] - - Description [Assumes that spot points to the link, after which the given - link should be added. Spot cannot be NULL or the tail of the list. - Therefore, the head and the tail of the list are not changed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListDoubleAddPairMiddle( Fxu_Double * pDiv, Fxu_Pair * pSpot, Fxu_Pair * pLink ) -{ - Fxu_ListPair * pList = &pDiv->lPairs; - assert( pSpot ); - assert( pSpot != pList->pTail ); - pLink->pDPrev = pSpot; - pLink->pDNext = pSpot->pDNext; - pLink->pDPrev->pDNext = pLink; - pLink->pDNext->pDPrev = pLink; - pList->nItems++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListDoubleDelPair( Fxu_Double * pDiv, Fxu_Pair * pLink ) -{ - Fxu_ListPair * pList = &pDiv->lPairs; - if ( pList->pHead == pLink ) - pList->pHead = pLink->pDNext; - if ( pList->pTail == pLink ) - pList->pTail = pLink->pDPrev; - if ( pLink->pDPrev ) - pLink->pDPrev->pDNext = pLink->pDNext; - if ( pLink->pDNext ) - pLink->pDNext->pDPrev = pLink->pDPrev; - pList->nItems--; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_ListDoubleAddPairPlace( Fxu_Double * pDiv, Fxu_Pair * pPair, Fxu_Pair * pPairSpot ) -{ - printf( "Fxu_ListDoubleAddPairPlace() is called!\n" ); -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/fxu/fxuMatrix.c b/src/opt/fxu/fxuMatrix.c deleted file mode 100644 index 93ec7b90..00000000 --- a/src/opt/fxu/fxuMatrix.c +++ /dev/null @@ -1,374 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuMatrix.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Procedures to manipulate the sparse matrix.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuMatrix.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fxuInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern unsigned int Cudd_Prime( unsigned int p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Matrix * Fxu_MatrixAllocate() -{ - Fxu_Matrix * p; - p = ALLOC( Fxu_Matrix, 1 ); - memset( p, 0, sizeof(Fxu_Matrix) ); - p->nTableSize = Cudd_Prime(10000); - p->pTable = ALLOC( Fxu_ListDouble, p->nTableSize ); - memset( p->pTable, 0, sizeof(Fxu_ListDouble) * p->nTableSize ); -#ifndef USE_SYSTEM_MEMORY_MANAGEMENT - { - // get the largest size in bytes for the following structures: - // Fxu_Cube, Fxu_Var, Fxu_Lit, Fxu_Pair, Fxu_Double, Fxu_Single - // (currently, Fxu_Var, Fxu_Pair, Fxu_Double take 10 machine words) - int nSizeMax, nSizeCur; - nSizeMax = -1; - nSizeCur = sizeof(Fxu_Cube); - if ( nSizeMax < nSizeCur ) - nSizeMax = nSizeCur; - nSizeCur = sizeof(Fxu_Var); - if ( nSizeMax < nSizeCur ) - nSizeMax = nSizeCur; - nSizeCur = sizeof(Fxu_Lit); - if ( nSizeMax < nSizeCur ) - nSizeMax = nSizeCur; - nSizeCur = sizeof(Fxu_Pair); - if ( nSizeMax < nSizeCur ) - nSizeMax = nSizeCur; - nSizeCur = sizeof(Fxu_Double); - if ( nSizeMax < nSizeCur ) - nSizeMax = nSizeCur; - nSizeCur = sizeof(Fxu_Single); - if ( nSizeMax < nSizeCur ) - nSizeMax = nSizeCur; - p->pMemMan = Extra_MmFixedStart( nSizeMax ); - } -#endif - p->pHeapDouble = Fxu_HeapDoubleStart(); - p->pHeapSingle = Fxu_HeapSingleStart(); - p->vPairs = Vec_PtrAlloc( 100 ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixDelete( Fxu_Matrix * p ) -{ - Fxu_HeapDoubleCheck( p->pHeapDouble ); - Fxu_HeapDoubleStop( p->pHeapDouble ); - Fxu_HeapSingleStop( p->pHeapSingle ); - - // delete other things -#ifdef USE_SYSTEM_MEMORY_MANAGEMENT - // this code is not needed when the custom memory manager is used - { - Fxu_Cube * pCube, * pCube2; - Fxu_Var * pVar, * pVar2; - Fxu_Lit * pLit, * pLit2; - Fxu_Double * pDiv, * pDiv2; - Fxu_Single * pSingle, * pSingle2; - Fxu_Pair * pPair, * pPair2; - int i; - // delete the divisors - Fxu_MatrixForEachDoubleSafe( p, pDiv, pDiv2, i ) - { - Fxu_DoubleForEachPairSafe( pDiv, pPair, pPair2 ) - MEM_FREE_FXU( p, Fxu_Pair, 1, pPair ); - MEM_FREE_FXU( p, Fxu_Double, 1, pDiv ); - } - Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 ) - MEM_FREE_FXU( p, Fxu_Single, 1, pSingle ); - // delete the entries - Fxu_MatrixForEachCube( p, pCube ) - Fxu_CubeForEachLiteralSafe( pCube, pLit, pLit2 ) - MEM_FREE_FXU( p, Fxu_Lit, 1, pLit ); - // delete the cubes - Fxu_MatrixForEachCubeSafe( p, pCube, pCube2 ) - MEM_FREE_FXU( p, Fxu_Cube, 1, pCube ); - // delete the vars - Fxu_MatrixForEachVariableSafe( p, pVar, pVar2 ) - MEM_FREE_FXU( p, Fxu_Var, 1, pVar ); - } -#else - Extra_MmFixedStop( p->pMemMan ); -#endif - - Vec_PtrFree( p->vPairs ); - FREE( p->pppPairs ); - FREE( p->ppPairs ); -// FREE( p->pPairsTemp ); - FREE( p->pTable ); - FREE( p->ppVars ); - FREE( p ); -} - - - -/**Function************************************************************* - - Synopsis [Adds a variable to the matrix.] - - Description [This procedure always adds variables at the end of the matrix. - It assigns the var's node and number. It adds the var to the linked list of - all variables and to the table of all nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Var * Fxu_MatrixAddVar( Fxu_Matrix * p ) -{ - Fxu_Var * pVar; - pVar = MEM_ALLOC_FXU( p, Fxu_Var, 1 ); - memset( pVar, 0, sizeof(Fxu_Var) ); - pVar->iVar = p->lVars.nItems; - p->ppVars[pVar->iVar] = pVar; - Fxu_ListMatrixAddVariable( p, pVar ); - return pVar; -} - -/**Function************************************************************* - - Synopsis [Adds a literal to the matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Cube * Fxu_MatrixAddCube( Fxu_Matrix * p, Fxu_Var * pVar, int iCube ) -{ - Fxu_Cube * pCube; - pCube = MEM_ALLOC_FXU( p, Fxu_Cube, 1 ); - memset( pCube, 0, sizeof(Fxu_Cube) ); - pCube->pVar = pVar; - pCube->iCube = iCube; - Fxu_ListMatrixAddCube( p, pCube ); - return pCube; -} - -/**Function************************************************************* - - Synopsis [Adds a literal to the matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixAddLiteral( Fxu_Matrix * p, Fxu_Cube * pCube, Fxu_Var * pVar ) -{ - Fxu_Lit * pLit; - pLit = MEM_ALLOC_FXU( p, Fxu_Lit, 1 ); - memset( pLit, 0, sizeof(Fxu_Lit) ); - // insert the literal into two linked lists - Fxu_ListCubeAddLiteral( pCube, pLit ); - Fxu_ListVarAddLiteral( pVar, pLit ); - // set the back pointers - pLit->pCube = pCube; - pLit->pVar = pVar; - pLit->iCube = pCube->iCube; - pLit->iVar = pVar->iVar; - // increment the literal counter - p->nEntries++; -} - -/**Function************************************************************* - - Synopsis [Deletes the divisor from the matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixDelDivisor( Fxu_Matrix * p, Fxu_Double * pDiv ) -{ - // delete divisor from the table - Fxu_ListTableDelDivisor( p, pDiv ); - // recycle the divisor - MEM_FREE_FXU( p, Fxu_Double, 1, pDiv ); -} - -/**Function************************************************************* - - Synopsis [Deletes the literal fromthe matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixDelLiteral( Fxu_Matrix * p, Fxu_Lit * pLit ) -{ - // delete the literal - Fxu_ListCubeDelLiteral( pLit->pCube, pLit ); - Fxu_ListVarDelLiteral( pLit->pVar, pLit ); - MEM_FREE_FXU( p, Fxu_Lit, 1, pLit ); - // increment the literal counter - p->nEntries--; -} - - -/**Function************************************************************* - - Synopsis [Creates and adds a single cube divisor.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixAddSingle( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, int Weight ) -{ - Fxu_Single * pSingle; - assert( pVar1->iVar < pVar2->iVar ); - pSingle = MEM_ALLOC_FXU( p, Fxu_Single, 1 ); - memset( pSingle, 0, sizeof(Fxu_Single) ); - pSingle->Num = p->lSingles.nItems; - pSingle->Weight = Weight; - pSingle->HNum = 0; - pSingle->pVar1 = pVar1; - pSingle->pVar2 = pVar2; - Fxu_ListMatrixAddSingle( p, pSingle ); - // add to the heap - Fxu_HeapSingleInsert( p->pHeapSingle, pSingle ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixAddDivisor( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ) -{ - Fxu_Pair * pPair; - Fxu_Double * pDiv; - int nBase, nLits1, nLits2; - int fFound; - unsigned Key; - - // canonicize the pair - Fxu_PairCanonicize( &pCube1, &pCube2 ); - // compute the hash key - Key = Fxu_PairHashKey( p, pCube1, pCube2, &nBase, &nLits1, &nLits2 ); - - // create the cube pair - pPair = Fxu_PairAlloc( p, pCube1, pCube2 ); - pPair->nBase = nBase; - pPair->nLits1 = nLits1; - pPair->nLits2 = nLits2; - - // check if the divisor for this pair already exists - fFound = 0; - Key %= p->nTableSize; - Fxu_TableForEachDouble( p, Key, pDiv ) - { - if ( Fxu_PairCompare( pPair, pDiv->lPairs.pTail ) ) // they are equal - { - fFound = 1; - break; - } - } - - if ( !fFound ) - { // create the new divisor - pDiv = MEM_ALLOC_FXU( p, Fxu_Double, 1 ); - memset( pDiv, 0, sizeof(Fxu_Double) ); - pDiv->Key = Key; - // set the number of this divisor - pDiv->Num = p->nDivsTotal++; // p->nDivs; - // insert the divisor in the table - Fxu_ListTableAddDivisor( p, pDiv ); - // set the initial cost of the divisor - pDiv->Weight -= pPair->nLits1 + pPair->nLits2; - } - - // link the pair to the cubes - Fxu_PairAdd( pPair ); - // connect the pair and the divisor - pPair->pDiv = pDiv; - Fxu_ListDoubleAddPairLast( pDiv, pPair ); - // update the max number of pairs in a divisor -// if ( p->nPairsMax < pDiv->lPairs.nItems ) -// p->nPairsMax = pDiv->lPairs.nItems; - // update the divisor's weight - pDiv->Weight += pPair->nLits1 + pPair->nLits2 - 1 + pPair->nBase; - if ( fFound ) // update the divisor in the heap - Fxu_HeapDoubleUpdate( p->pHeapDouble, pDiv ); - else // add the new divisor to the heap - Fxu_HeapDoubleInsert( p->pHeapDouble, pDiv ); -} - -/* - { - int piVarsC1[100], piVarsC2[100], nVarsC1, nVarsC2; - Fxu_Double * pDivCur; - Fxu_MatrixGetDoubleVars( p, pDiv, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 ); - pDivCur = Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 ); - assert( pDivCur == pDiv ); - } -*/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/fxu/fxuPair.c b/src/opt/fxu/fxuPair.c deleted file mode 100644 index 3c031ce8..00000000 --- a/src/opt/fxu/fxuPair.c +++ /dev/null @@ -1,555 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuPair.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Operations on cube pairs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuPair.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fxuInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define MAX_PRIMES 304 - -static s_Primes[MAX_PRIMES] = -{ - 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, - 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, - 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, - 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, - 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, - 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, - 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, - 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, - 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, - 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, - 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, - 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, - 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, - 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, - 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, - 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, - 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, - 1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, - 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, - 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, - 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, - 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, - 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, - 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, - 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, - 1993, 1997, 1999, 2003 -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Find the canonical permutation of two cubes in the pair.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_PairCanonicize( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 ) -{ - Fxu_Lit * pLit1, * pLit2; - Fxu_Cube * pCubeTemp; - - // walk through the cubes to determine - // the one that has higher first variable - pLit1 = (*ppCube1)->lLits.pHead; - pLit2 = (*ppCube2)->lLits.pHead; - while ( 1 ) - { - if ( pLit1->iVar == pLit2->iVar ) - { - pLit1 = pLit1->pHNext; - pLit2 = pLit2->pHNext; - continue; - } - assert( pLit1 && pLit2 ); // this is true if the covers are SCC-free - if ( pLit1->iVar > pLit2->iVar ) - { // swap the cubes - pCubeTemp = *ppCube1; - *ppCube1 = *ppCube2; - *ppCube2 = pCubeTemp; - } - break; - } -} - -/**Function************************************************************* - - Synopsis [Find the canonical permutation of two cubes in the pair.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_PairCanonicize2( Fxu_Cube ** ppCube1, Fxu_Cube ** ppCube2 ) -{ - Fxu_Cube * pCubeTemp; - // canonicize the pair by ordering the cubes - if ( (*ppCube1)->iCube > (*ppCube2)->iCube ) - { // swap the cubes - pCubeTemp = *ppCube1; - *ppCube1 = *ppCube2; - *ppCube2 = pCubeTemp; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Fxu_PairHashKeyArray( Fxu_Matrix * p, int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ) -{ - int Offset1 = 100, Offset2 = 200, i; - unsigned Key; - // compute the hash key - Key = 0; - for ( i = 0; i < nVarsC1; i++ ) - Key ^= s_Primes[Offset1+i] * piVarsC1[i]; - for ( i = 0; i < nVarsC2; i++ ) - Key ^= s_Primes[Offset2+i] * piVarsC2[i]; - return Key; -} - -/**Function************************************************************* - - Synopsis [Computes the hash key of the divisor represented by the pair of cubes.] - - Description [Goes through the variables in both cubes. Skips the identical - ones (this corresponds to making the cubes cube-free). Computes the hash - value of the cubes. Assigns the number of literals in the base and in the - cubes without base.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Fxu_PairHashKey( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, - int * pnBase, int * pnLits1, int * pnLits2 ) -{ - int Offset1 = 100, Offset2 = 200; - int nBase, nLits1, nLits2; - Fxu_Lit * pLit1, * pLit2; - unsigned Key; - - // compute the hash key - Key = 0; - nLits1 = 0; - nLits2 = 0; - nBase = 0; - pLit1 = pCube1->lLits.pHead; - pLit2 = pCube2->lLits.pHead; - while ( 1 ) - { - if ( pLit1 && pLit2 ) - { - if ( pLit1->iVar == pLit2->iVar ) - { // ensure cube-free - pLit1 = pLit1->pHNext; - pLit2 = pLit2->pHNext; - // add this literal to the base - nBase++; - } - else if ( pLit1->iVar < pLit2->iVar ) - { - Key ^= s_Primes[Offset1+nLits1] * pLit1->iVar; - pLit1 = pLit1->pHNext; - nLits1++; - } - else - { - Key ^= s_Primes[Offset2+nLits2] * pLit2->iVar; - pLit2 = pLit2->pHNext; - nLits2++; - } - } - else if ( pLit1 && !pLit2 ) - { - Key ^= s_Primes[Offset1+nLits1] * pLit1->iVar; - pLit1 = pLit1->pHNext; - nLits1++; - } - else if ( !pLit1 && pLit2 ) - { - Key ^= s_Primes[Offset2+nLits2] * pLit2->iVar; - pLit2 = pLit2->pHNext; - nLits2++; - } - else - break; - } - *pnBase = nBase; - *pnLits1 = nLits1; - *pnLits2 = nLits2; - return Key; -} - -/**Function************************************************************* - - Synopsis [Compares the two pairs.] - - Description [Returns 1 if the divisors represented by these pairs - are equal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_PairCompare( Fxu_Pair * pPair1, Fxu_Pair * pPair2 ) -{ - Fxu_Lit * pD1C1, * pD1C2; - Fxu_Lit * pD2C1, * pD2C2; - int TopVar1, TopVar2; - int Code; - - if ( pPair1->nLits1 != pPair2->nLits1 ) - return 0; - if ( pPair1->nLits2 != pPair2->nLits2 ) - return 0; - - pD1C1 = pPair1->pCube1->lLits.pHead; - pD1C2 = pPair1->pCube2->lLits.pHead; - - pD2C1 = pPair2->pCube1->lLits.pHead; - pD2C2 = pPair2->pCube2->lLits.pHead; - - Code = pD1C1? 8: 0; - Code |= pD1C2? 4: 0; - Code |= pD2C1? 2: 0; - Code |= pD2C2? 1: 0; - assert( Code == 15 ); - - while ( 1 ) - { - switch ( Code ) - { - case 0: // -- -- NULL NULL NULL NULL - return 1; - case 1: // -- -1 NULL NULL NULL pD2C2 - return 0; - case 2: // -- 1- NULL NULL pD2C1 NULL - return 0; - case 3: // -- 11 NULL NULL pD2C1 pD2C2 - if ( pD2C1->iVar != pD2C2->iVar ) - return 0; - pD2C1 = pD2C1->pHNext; - pD2C2 = pD2C2->pHNext; - break; - case 4: // -1 -- NULL pD1C2 NULL NULL - return 0; - case 5: // -1 -1 NULL pD1C2 NULL pD2C2 - if ( pD1C2->iVar != pD2C2->iVar ) - return 0; - pD1C2 = pD1C2->pHNext; - pD2C2 = pD2C2->pHNext; - break; - case 6: // -1 1- NULL pD1C2 pD2C1 NULL - return 0; - case 7: // -1 11 NULL pD1C2 pD2C1 pD2C2 - TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar ); - if ( TopVar2 == pD1C2->iVar ) - { - if ( pD2C1->iVar <= pD2C2->iVar ) - return 0; - pD1C2 = pD1C2->pHNext; - pD2C2 = pD2C2->pHNext; - } - else if ( TopVar2 < pD1C2->iVar ) - { - if ( pD2C1->iVar != pD2C2->iVar ) - return 0; - pD2C1 = pD2C1->pHNext; - pD2C2 = pD2C2->pHNext; - } - else - return 0; - break; - case 8: // 1- -- pD1C1 NULL NULL NULL - return 0; - case 9: // 1- -1 pD1C1 NULL NULL pD2C2 - return 0; - case 10: // 1- 1- pD1C1 NULL pD2C1 NULL - if ( pD1C1->iVar != pD2C1->iVar ) - return 0; - pD1C1 = pD1C1->pHNext; - pD2C1 = pD2C1->pHNext; - break; - case 11: // 1- 11 pD1C1 NULL pD2C1 pD2C2 - TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar ); - if ( TopVar2 == pD1C1->iVar ) - { - if ( pD2C1->iVar >= pD2C2->iVar ) - return 0; - pD1C1 = pD1C1->pHNext; - pD2C1 = pD2C1->pHNext; - } - else if ( TopVar2 < pD1C1->iVar ) - { - if ( pD2C1->iVar != pD2C2->iVar ) - return 0; - pD2C1 = pD2C1->pHNext; - pD2C2 = pD2C2->pHNext; - } - else - return 0; - break; - case 12: // 11 -- pD1C1 pD1C2 NULL NULL - if ( pD1C1->iVar != pD1C2->iVar ) - return 0; - pD1C1 = pD1C1->pHNext; - pD1C2 = pD1C2->pHNext; - break; - case 13: // 11 -1 pD1C1 pD1C2 NULL pD2C2 - TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar ); - if ( TopVar1 == pD2C2->iVar ) - { - if ( pD1C1->iVar <= pD1C2->iVar ) - return 0; - pD1C2 = pD1C2->pHNext; - pD2C2 = pD2C2->pHNext; - } - else if ( TopVar1 < pD2C2->iVar ) - { - if ( pD1C1->iVar != pD1C2->iVar ) - return 0; - pD1C1 = pD1C1->pHNext; - pD1C2 = pD1C2->pHNext; - } - else - return 0; - break; - case 14: // 11 1- pD1C1 pD1C2 pD2C1 NULL - TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar ); - if ( TopVar1 == pD2C1->iVar ) - { - if ( pD1C1->iVar >= pD1C2->iVar ) - return 0; - pD1C1 = pD1C1->pHNext; - pD2C1 = pD2C1->pHNext; - } - else if ( TopVar1 < pD2C1->iVar ) - { - if ( pD1C1->iVar != pD1C2->iVar ) - return 0; - pD1C1 = pD1C1->pHNext; - pD1C2 = pD1C2->pHNext; - } - else - return 0; - break; - case 15: // 11 11 pD1C1 pD1C2 pD2C1 pD2C2 - TopVar1 = Fxu_Min( pD1C1->iVar, pD1C2->iVar ); - TopVar2 = Fxu_Min( pD2C1->iVar, pD2C2->iVar ); - if ( TopVar1 == TopVar2 ) - { - if ( pD1C1->iVar == pD1C2->iVar ) - { - if ( pD2C1->iVar != pD2C2->iVar ) - return 0; - pD1C1 = pD1C1->pHNext; - pD1C2 = pD1C2->pHNext; - pD2C1 = pD2C1->pHNext; - pD2C2 = pD2C2->pHNext; - } - else - { - if ( pD2C1->iVar == pD2C2->iVar ) - return 0; - if ( pD1C1->iVar < pD1C2->iVar ) - { - if ( pD2C1->iVar > pD2C2->iVar ) - return 0; - pD1C1 = pD1C1->pHNext; - pD2C1 = pD2C1->pHNext; - } - else - { - if ( pD2C1->iVar < pD2C2->iVar ) - return 0; - pD1C2 = pD1C2->pHNext; - pD2C2 = pD2C2->pHNext; - } - } - } - else if ( TopVar1 < TopVar2 ) - { - if ( pD1C1->iVar != pD1C2->iVar ) - return 0; - pD1C1 = pD1C1->pHNext; - pD1C2 = pD1C2->pHNext; - } - else - { - if ( pD2C1->iVar != pD2C2->iVar ) - return 0; - pD2C1 = pD2C1->pHNext; - pD2C2 = pD2C2->pHNext; - } - break; - default: - assert( 0 ); - break; - } - - Code = pD1C1? 8: 0; - Code |= pD1C2? 4: 0; - Code |= pD2C1? 2: 0; - Code |= pD2C2? 1: 0; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Allocates the storage for cubes pairs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_PairAllocStorage( Fxu_Var * pVar, int nCubes ) -{ - int k; -// assert( pVar->nCubes == 0 ); - pVar->nCubes = nCubes; - // allocate memory for all the pairs - pVar->ppPairs = ALLOC( Fxu_Pair **, nCubes ); - pVar->ppPairs[0] = ALLOC( Fxu_Pair *, nCubes * nCubes ); - memset( pVar->ppPairs[0], 0, sizeof(Fxu_Pair *) * nCubes * nCubes ); - for ( k = 1; k < nCubes; k++ ) - pVar->ppPairs[k] = pVar->ppPairs[k-1] + nCubes; -} - -/**Function************************************************************* - - Synopsis [Clears all pairs associated with this cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_PairClearStorage( Fxu_Cube * pCube ) -{ - Fxu_Var * pVar; - int i; - pVar = pCube->pVar; - for ( i = 0; i < pVar->nCubes; i++ ) - { - pVar->ppPairs[pCube->iCube][i] = NULL; - pVar->ppPairs[i][pCube->iCube] = NULL; - } -} - -/**Function************************************************************* - - Synopsis [Clears all pairs associated with this cube.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_PairFreeStorage( Fxu_Var * pVar ) -{ - if ( pVar->ppPairs ) - { - FREE( pVar->ppPairs[0] ); - FREE( pVar->ppPairs ); - } -} - -/**Function************************************************************* - - Synopsis [Adds the pair to storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Pair * Fxu_PairAlloc( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2 ) -{ - Fxu_Pair * pPair; - assert( pCube1->pVar == pCube2->pVar ); - pPair = MEM_ALLOC_FXU( p, Fxu_Pair, 1 ); - memset( pPair, 0, sizeof(Fxu_Pair) ); - pPair->pCube1 = pCube1; - pPair->pCube2 = pCube2; - pPair->iCube1 = pCube1->iCube; - pPair->iCube2 = pCube2->iCube; - return pPair; -} - -/**Function************************************************************* - - Synopsis [Adds the pair to storage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_PairAdd( Fxu_Pair * pPair ) -{ - Fxu_Var * pVar; - - pVar = pPair->pCube1->pVar; - assert( pVar == pPair->pCube2->pVar ); - - pVar->ppPairs[pPair->iCube1][pPair->iCube2] = pPair; - pVar->ppPairs[pPair->iCube2][pPair->iCube1] = pPair; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/fxu/fxuPrint.c b/src/opt/fxu/fxuPrint.c deleted file mode 100644 index 232b109a..00000000 --- a/src/opt/fxu/fxuPrint.c +++ /dev/null @@ -1,195 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuPrint.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Various printing procedures.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuPrint.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fxuInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixPrint( FILE * pFile, Fxu_Matrix * p ) -{ - Fxu_Var * pVar; - Fxu_Cube * pCube; - Fxu_Double * pDiv; - Fxu_Single * pSingle; - Fxu_Lit * pLit; - Fxu_Pair * pPair; - int i, LastNum; - int fStdout; - - fStdout = 1; - if ( pFile == NULL ) - { - pFile = fopen( "matrix.txt", "w" ); - fStdout = 0; - } - - fprintf( pFile, "Matrix has %d vars, %d cubes, %d literals, %d divisors.\n", - p->lVars.nItems, p->lCubes.nItems, p->nEntries, p->nDivs ); - fprintf( pFile, "Divisors selected so far: single = %d, double = %d.\n", - p->nDivs1, p->nDivs2 ); - fprintf( pFile, "\n" ); - - // print the numbers on top of the matrix - for ( i = 0; i < 12; i++ ) - fprintf( pFile, " " ); - Fxu_MatrixForEachVariable( p, pVar ) - fprintf( pFile, "%d", pVar->iVar % 10 ); - fprintf( pFile, "\n" ); - - // print the rows - Fxu_MatrixForEachCube( p, pCube ) - { - fprintf( pFile, "%4d", pCube->iCube ); - fprintf( pFile, " " ); - fprintf( pFile, "%4d", pCube->pVar->iVar ); - fprintf( pFile, " " ); - - // print the literals - LastNum = -1; - Fxu_CubeForEachLiteral( pCube, pLit ) - { - for ( i = LastNum + 1; i < pLit->pVar->iVar; i++ ) - fprintf( pFile, "." ); - fprintf( pFile, "1" ); - LastNum = i; - } - for ( i = LastNum + 1; i < p->lVars.nItems; i++ ) - fprintf( pFile, "." ); - fprintf( pFile, "\n" ); - } - fprintf( pFile, "\n" ); - - // print the double-cube divisors - fprintf( pFile, "The double divisors are:\n" ); - Fxu_MatrixForEachDouble( p, pDiv, i ) - { - fprintf( pFile, "Divisor #%3d (lit=%d,%d) (w=%2d): ", - pDiv->Num, pDiv->lPairs.pHead->nLits1, - pDiv->lPairs.pHead->nLits2, pDiv->Weight ); - Fxu_DoubleForEachPair( pDiv, pPair ) - fprintf( pFile, " <%d, %d> (b=%d)", - pPair->pCube1->iCube, pPair->pCube2->iCube, pPair->nBase ); - fprintf( pFile, "\n" ); - } - fprintf( pFile, "\n" ); - - // print the divisors associated with each cube - fprintf( pFile, "The cubes are:\n" ); - Fxu_MatrixForEachCube( p, pCube ) - { - fprintf( pFile, "Cube #%3d: ", pCube->iCube ); - if ( pCube->pVar->ppPairs ) - Fxu_CubeForEachPair( pCube, pPair, i ) - fprintf( pFile, " <%d %d> (d=%d) (b=%d)", - pPair->iCube1, pPair->iCube2, pPair->pDiv->Num, pPair->nBase ); - fprintf( pFile, "\n" ); - } - fprintf( pFile, "\n" ); - - // print the single-cube divisors - fprintf( pFile, "The single divisors are:\n" ); - Fxu_MatrixForEachSingle( p, pSingle ) - { - fprintf( pFile, "Single-cube divisor #%5d: Var1 = %4d. Var2 = %4d. Weight = %2d\n", - pSingle->Num, pSingle->pVar1->iVar, pSingle->pVar2->iVar, pSingle->Weight ); - } - fprintf( pFile, "\n" ); - -/* - { - int Index; - fprintf( pFile, "Distribution of divisors in the hash table:\n" ); - for ( Index = 0; Index < p->nTableSize; Index++ ) - fprintf( pFile, " %d", p->pTable[Index].nItems ); - fprintf( pFile, "\n" ); - } -*/ - if ( !fStdout ) - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixPrintDivisorProfile( FILE * pFile, Fxu_Matrix * p ) -{ - Fxu_Double * pDiv; - int WeightMax; - int * pProfile; - int Counter1; // the number of -1 weight - int CounterL; // the number of less than -1 weight - int i; - - WeightMax = Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ); - pProfile = ALLOC( int, (WeightMax + 1) ); - memset( pProfile, 0, sizeof(int) * (WeightMax + 1) ); - - Counter1 = 0; - CounterL = 0; - Fxu_MatrixForEachDouble( p, pDiv, i ) - { - assert( pDiv->Weight <= WeightMax ); - if ( pDiv->Weight == -1 ) - Counter1++; - else if ( pDiv->Weight < 0 ) - CounterL++; - else - pProfile[ pDiv->Weight ]++; - } - - fprintf( pFile, "The double divisors profile:\n" ); - fprintf( pFile, "Weight < -1 divisors = %6d\n", CounterL ); - fprintf( pFile, "Weight -1 divisors = %6d\n", Counter1 ); - for ( i = 0; i <= WeightMax; i++ ) - if ( pProfile[i] ) - fprintf( pFile, "Weight %3d divisors = %6d\n", i, pProfile[i] ); - fprintf( pFile, "End of divisor profile printout\n" ); - FREE( pProfile ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/fxu/fxuReduce.c b/src/opt/fxu/fxuReduce.c deleted file mode 100644 index 0ab8a157..00000000 --- a/src/opt/fxu/fxuReduce.c +++ /dev/null @@ -1,204 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuReduce.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Procedures to reduce the number of considered cube pairs.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuReduce.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "fxuInt.h" -#include "fxu.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Precomputes the pairs to use for creating two-cube divisors.] - - Description [This procedure takes the matrix with variables and cubes - allocated (p), the original covers of the nodes (i-sets) and their number - (ppCovers,nCovers). The maximum number of pairs to compute and the total - number of pairs in existence. This procedure adds to the storage of - divisors exactly the given number of pairs (nPairsMax) while taking - first those pairs that have the smallest number of literals in their - cube-free form.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax ) -{ - unsigned char * pnLitsDiff; // storage for the counters of diff literals - int * pnPairCounters; // the counters of pairs for each number of diff literals - Fxu_Cube * pCubeFirst, * pCubeLast; - Fxu_Cube * pCube1, * pCube2; - Fxu_Var * pVar; - int nCubes, nBitsMax, nSum; - int CutOffNum, CutOffQuant; - int iPair, iQuant, k, c; - int clk = clock(); - char * pSopCover; - int nFanins; - - assert( nPairsMax < nPairsTotal ); - - // allocate storage for counter of diffs - pnLitsDiff = ALLOC( unsigned char, nPairsTotal ); - // go through the covers and precompute the distances between the pairs - iPair = 0; - nBitsMax = -1; - for ( c = 0; c < vCovers->nSize; c++ ) - if ( pSopCover = vCovers->pArray[c] ) - { - nFanins = Abc_SopGetVarNum(pSopCover); - // precompute the differences - Fxu_CountPairDiffs( pSopCover, pnLitsDiff + iPair ); - // update the counter - nCubes = Abc_SopGetCubeNum( pSopCover ); - iPair += nCubes * (nCubes - 1) / 2; - if ( nBitsMax < nFanins ) - nBitsMax = nFanins; - } - assert( iPair == nPairsTotal ); - - // allocate storage for counters of cube pairs by difference - pnPairCounters = ALLOC( int, 2 * nBitsMax ); - memset( pnPairCounters, 0, sizeof(int) * 2 * nBitsMax ); - // count the number of different pairs - for ( k = 0; k < nPairsTotal; k++ ) - pnPairCounters[ pnLitsDiff[k] ]++; - // determine what pairs to take starting from the lower - // so that there would be exactly pPairsMax pairs - if ( pnPairCounters[0] != 0 ) - { - printf( "The SOPs of the nodes are not cube-free. Run \"bdd; sop\" before \"fx\".\n" ); - return 0; - } - if ( pnPairCounters[1] != 0 ) - { - printf( "The SOPs of the nodes are not SCC-free. Run \"bdd; sop\" before \"fx\".\n" ); - return 0; - } - assert( pnPairCounters[0] == 0 ); // otherwise, covers are not dup-free - assert( pnPairCounters[1] == 0 ); // otherwise, covers are not SCC-free - nSum = 0; - for ( k = 0; k < 2 * nBitsMax; k++ ) - { - nSum += pnPairCounters[k]; - if ( nSum >= nPairsMax ) - { - CutOffNum = k; - CutOffQuant = pnPairCounters[k] - (nSum - nPairsMax); - break; - } - } - FREE( pnPairCounters ); - - // set to 0 all the pairs above the cut-off number and quantity - iQuant = 0; - iPair = 0; - for ( k = 0; k < nPairsTotal; k++ ) - if ( pnLitsDiff[k] > CutOffNum ) - pnLitsDiff[k] = 0; - else if ( pnLitsDiff[k] == CutOffNum ) - { - if ( iQuant++ >= CutOffQuant ) - pnLitsDiff[k] = 0; - else - iPair++; - } - else - iPair++; - assert( iPair == nPairsMax ); - - // collect the corresponding pairs and add the divisors - iPair = 0; - for ( c = 0; c < vCovers->nSize; c++ ) - if ( pSopCover = vCovers->pArray[c] ) - { - // get the var - pVar = p->ppVars[2*c+1]; - // get the first cube - pCubeFirst = pVar->pFirst; - // get the last cube - pCubeLast = pCubeFirst; - for ( k = 0; k < pVar->nCubes; k++ ) - pCubeLast = pCubeLast->pNext; - assert( pCubeLast == NULL || pCubeLast->pVar != pVar ); - - // go through the cube pairs - for ( pCube1 = pCubeFirst; pCube1 != pCubeLast; pCube1 = pCube1->pNext ) - for ( pCube2 = pCube1->pNext; pCube2 != pCubeLast; pCube2 = pCube2->pNext ) - if ( pnLitsDiff[iPair++] ) - { // create the divisors for this pair - Fxu_MatrixAddDivisor( p, pCube1, pCube2 ); - } - } - assert( iPair == nPairsTotal ); - FREE( pnLitsDiff ); -//PRT( "Preprocess", clock() - clk ); - return 1; -} - - -/**Function************************************************************* - - Synopsis [Counts the differences in each cube pair in the cover.] - - Description [Takes the cover (pCover) and the array where the - diff counters go (pDiffs). The array pDiffs should have as many - entries as there are different pairs of cubes in the cover: n(n-1)/2. - Fills out the array pDiffs with the following info: For each cube - pair, included in the array is the number of literals in both cubes - after they are made cube free.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_CountPairDiffs( char * pCover, unsigned char pDiffs[] ) -{ - char * pCube1, * pCube2; - int nOnes, nCubePairs, nFanins, v; - nCubePairs = 0; - nFanins = Abc_SopGetVarNum(pCover); - Abc_SopForEachCube( pCover, nFanins, pCube1 ) - Abc_SopForEachCube( pCube1, nFanins, pCube2 ) - { - if ( pCube1 == pCube2 ) - continue; - nOnes = 0; - for ( v = 0; v < nFanins; v++ ) - nOnes += (pCube1[v] != pCube2[v]); - pDiffs[nCubePairs++] = nOnes; - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/fxu/fxuSelect.c b/src/opt/fxu/fxuSelect.c deleted file mode 100644 index b9265487..00000000 --- a/src/opt/fxu/fxuSelect.c +++ /dev/null @@ -1,603 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuSelect.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Procedures to select the best divisor/complement pair.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuSelect.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fxuInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define MAX_SIZE_LOOKAHEAD 20 - -static int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar ); - -static Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle ); -static Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble ); -static Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble ); - -Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p, - int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ); -void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble, - int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 ); - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Selects the best pair (Single,Double) and returns their weight.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_Select( Fxu_Matrix * p, Fxu_Single ** ppSingle, Fxu_Double ** ppDouble ) -{ - // the top entries - Fxu_Single * pSingles[MAX_SIZE_LOOKAHEAD]; - Fxu_Double * pDoubles[MAX_SIZE_LOOKAHEAD]; - // the complements - Fxu_Double * pSCompl[MAX_SIZE_LOOKAHEAD]; - Fxu_Single * pDComplS[MAX_SIZE_LOOKAHEAD]; - Fxu_Double * pDComplD[MAX_SIZE_LOOKAHEAD]; - Fxu_Pair * pPair; - int nSingles; - int nDoubles; - int i; - int WeightBest; - int WeightCur; - int iNum, fBestS; - - // collect the top entries from the queues - for ( nSingles = 0; nSingles < MAX_SIZE_LOOKAHEAD; nSingles++ ) - { - pSingles[nSingles] = Fxu_HeapSingleGetMax( p->pHeapSingle ); - if ( pSingles[nSingles] == NULL ) - break; - } - // put them back into the queue - for ( i = 0; i < nSingles; i++ ) - if ( pSingles[i] ) - Fxu_HeapSingleInsert( p->pHeapSingle, pSingles[i] ); - - // the same for doubles - // collect the top entries from the queues - for ( nDoubles = 0; nDoubles < MAX_SIZE_LOOKAHEAD; nDoubles++ ) - { - pDoubles[nDoubles] = Fxu_HeapDoubleGetMax( p->pHeapDouble ); - if ( pDoubles[nDoubles] == NULL ) - break; - } - // put them back into the queue - for ( i = 0; i < nDoubles; i++ ) - if ( pDoubles[i] ) - Fxu_HeapDoubleInsert( p->pHeapDouble, pDoubles[i] ); - - // for each single, find the complement double (if any) - for ( i = 0; i < nSingles; i++ ) - if ( pSingles[i] ) - pSCompl[i] = Fxu_MatrixFindComplementSingle( p, pSingles[i] ); - - // for each double, find the complement single or double (if any) - for ( i = 0; i < nDoubles; i++ ) - if ( pDoubles[i] ) - { - pPair = pDoubles[i]->lPairs.pHead; - if ( pPair->nLits1 == 1 && pPair->nLits2 == 1 ) - { - pDComplS[i] = Fxu_MatrixFindComplementDouble2( p, pDoubles[i] ); - pDComplD[i] = NULL; - } -// else if ( pPair->nLits1 == 2 && pPair->nLits2 == 2 ) -// { -// pDComplS[i] = NULL; -// pDComplD[i] = Fxu_MatrixFindComplementDouble4( p, pDoubles[i] ); -// } - else - { - pDComplS[i] = NULL; - pDComplD[i] = NULL; - } - } - - // select the best pair - WeightBest = -1; - for ( i = 0; i < nSingles; i++ ) - { - WeightCur = pSingles[i]->Weight; - if ( pSCompl[i] ) - { - // add the weight of the double - WeightCur += pSCompl[i]->Weight; - // there is no need to implement this double, so... - pPair = pSCompl[i]->lPairs.pHead; - WeightCur += pPair->nLits1 + pPair->nLits2; - } - if ( WeightBest < WeightCur ) - { - WeightBest = WeightCur; - *ppSingle = pSingles[i]; - *ppDouble = pSCompl[i]; - fBestS = 1; - iNum = i; - } - } - for ( i = 0; i < nDoubles; i++ ) - { - WeightCur = pDoubles[i]->Weight; - if ( pDComplS[i] ) - { - // add the weight of the single - WeightCur += pDComplS[i]->Weight; - // there is no need to implement this double, so... - pPair = pDoubles[i]->lPairs.pHead; - WeightCur += pPair->nLits1 + pPair->nLits2; - } - if ( WeightBest < WeightCur ) - { - WeightBest = WeightCur; - *ppSingle = pDComplS[i]; - *ppDouble = pDoubles[i]; - fBestS = 0; - iNum = i; - } - } -/* - // print the statistics - printf( "\n" ); - for ( i = 0; i < nSingles; i++ ) - { - printf( "Single #%d: Weight = %3d. ", i, pSingles[i]->Weight ); - printf( "Compl: " ); - if ( pSCompl[i] == NULL ) - printf( "None." ); - else - printf( "D Weight = %3d Sum = %3d", - pSCompl[i]->Weight, pSCompl[i]->Weight + pSingles[i]->Weight ); - printf( "\n" ); - } - printf( "\n" ); - for ( i = 0; i < nDoubles; i++ ) - { - printf( "Double #%d: Weight = %3d. ", i, pDoubles[i]->Weight ); - printf( "Compl: " ); - if ( pDComplS[i] == NULL && pDComplD[i] == NULL ) - printf( "None." ); - else if ( pDComplS[i] ) - printf( "S Weight = %3d Sum = %3d", - pDComplS[i]->Weight, pDComplS[i]->Weight + pDoubles[i]->Weight ); - else if ( pDComplD[i] ) - printf( "D Weight = %3d Sum = %3d", - pDComplD[i]->Weight, pDComplD[i]->Weight + pDoubles[i]->Weight ); - printf( "\n" ); - } - if ( WeightBest == -1 ) - printf( "Selected NONE\n" ); - else - { - printf( "Selected = %s. ", fBestS? "S": "D" ); - printf( "Number = %d. ", iNum ); - printf( "Weight = %d.\n", WeightBest ); - } - printf( "\n" ); -*/ - return WeightBest; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Double * Fxu_MatrixFindComplementSingle( Fxu_Matrix * p, Fxu_Single * pSingle ) -{ -// int * pValue2Node = p->pValue2Node; - int iVar1, iVar2; - int iVar1C, iVar2C; - // get the variables of this single div - iVar1 = pSingle->pVar1->iVar; - iVar2 = pSingle->pVar2->iVar; - iVar1C = Fxu_MatrixFindComplement( p, iVar1 ); - iVar2C = Fxu_MatrixFindComplement( p, iVar2 ); - if ( iVar1C == -1 || iVar2C == -1 ) - return NULL; - assert( iVar1C < iVar2C ); - return Fxu_MatrixFindDouble( p, &iVar1C, &iVar2C, 1, 1 ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Single * Fxu_MatrixFindComplementDouble2( Fxu_Matrix * p, Fxu_Double * pDouble ) -{ -// int * pValue2Node = p->pValue2Node; - int piVarsC1[10], piVarsC2[10]; - int nVarsC1, nVarsC2; - int iVar1, iVar2, iVarTemp; - int iVar1C, iVar2C; - Fxu_Single * pSingle; - - // get the variables of this double div - Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 ); - assert( nVarsC1 == 1 ); - assert( nVarsC2 == 1 ); - iVar1 = piVarsC1[0]; - iVar2 = piVarsC2[0]; - assert( iVar1 < iVar2 ); - - iVar1C = Fxu_MatrixFindComplement( p, iVar1 ); - iVar2C = Fxu_MatrixFindComplement( p, iVar2 ); - if ( iVar1C == -1 || iVar2C == -1 ) - return NULL; - - // go through the queque and find this one -// assert( iVar1C < iVar2C ); - if ( iVar1C > iVar2C ) - { - iVarTemp = iVar1C; - iVar1C = iVar2C; - iVar2C = iVarTemp; - } - - Fxu_MatrixForEachSingle( p, pSingle ) - if ( pSingle->pVar1->iVar == iVar1C && pSingle->pVar2->iVar == iVar2C ) - return pSingle; - return NULL; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Double * Fxu_MatrixFindComplementDouble4( Fxu_Matrix * p, Fxu_Double * pDouble ) -{ -// int * pValue2Node = p->pValue2Node; - int piVarsC1[10], piVarsC2[10]; - int nVarsC1, nVarsC2; - int iVar11, iVar12, iVar21, iVar22; - int iVar11C, iVar12C, iVar21C, iVar22C; - int RetValue; - - // get the variables of this double div - Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1, piVarsC2, &nVarsC1, &nVarsC2 ); - assert( nVarsC1 == 2 && nVarsC2 == 2 ); - - iVar11 = piVarsC1[0]; - iVar12 = piVarsC1[1]; - iVar21 = piVarsC2[0]; - iVar22 = piVarsC2[1]; - assert( iVar11 < iVar21 ); - - iVar11C = Fxu_MatrixFindComplement( p, iVar11 ); - iVar12C = Fxu_MatrixFindComplement( p, iVar12 ); - iVar21C = Fxu_MatrixFindComplement( p, iVar21 ); - iVar22C = Fxu_MatrixFindComplement( p, iVar22 ); - if ( iVar11C == -1 || iVar12C == -1 || iVar21C == -1 || iVar22C == -1 ) - return NULL; - if ( iVar11C != iVar21 || iVar12C != iVar22 || - iVar21C != iVar11 || iVar22C != iVar12 ) - return NULL; - - // a'b' + ab => a'b + ab' - // a'b + ab' => a'b' + ab - // swap the second pair in each cube - RetValue = piVarsC1[1]; - piVarsC1[1] = piVarsC2[1]; - piVarsC2[1] = RetValue; - - return Fxu_MatrixFindDouble( p, piVarsC1, piVarsC2, 2, 2 ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_MatrixFindComplement( Fxu_Matrix * p, int iVar ) -{ - return iVar ^ 1; -/* -// int * pValue2Node = p->pValue2Node; - int iVarC; - int iNode; - int Beg, End; - - // get the nodes - iNode = pValue2Node[iVar]; - // get the first node with the same var - for ( Beg = iVar; Beg >= 0; Beg-- ) - if ( pValue2Node[Beg] != iNode ) - { - Beg++; - break; - } - // get the last node with the same var - for ( End = iVar; ; End++ ) - if ( pValue2Node[End] != iNode ) - { - End--; - break; - } - - // if one of the vars is not binary, quit - if ( End - Beg > 1 ) - return -1; - - // get the complements - if ( iVar == Beg ) - iVarC = End; - else if ( iVar == End ) - iVarC = Beg; - else - { - assert( 0 ); - } - return iVarC; -*/ -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixGetDoubleVars( Fxu_Matrix * p, Fxu_Double * pDouble, - int piVarsC1[], int piVarsC2[], int * pnVarsC1, int * pnVarsC2 ) -{ - Fxu_Pair * pPair; - Fxu_Lit * pLit1, * pLit2; - int nLits1, nLits2; - - // get the first pair - pPair = pDouble->lPairs.pHead; - // init the parameters - nLits1 = 0; - nLits2 = 0; - pLit1 = pPair->pCube1->lLits.pHead; - pLit2 = pPair->pCube2->lLits.pHead; - while ( 1 ) - { - if ( pLit1 && pLit2 ) - { - if ( pLit1->iVar == pLit2->iVar ) - { // ensure cube-free - pLit1 = pLit1->pHNext; - pLit2 = pLit2->pHNext; - } - else if ( pLit1->iVar < pLit2->iVar ) - { - piVarsC1[nLits1++] = pLit1->iVar; - pLit1 = pLit1->pHNext; - } - else - { - piVarsC2[nLits2++] = pLit2->iVar; - pLit2 = pLit2->pHNext; - } - } - else if ( pLit1 && !pLit2 ) - { - piVarsC1[nLits1++] = pLit1->iVar; - pLit1 = pLit1->pHNext; - } - else if ( !pLit1 && pLit2 ) - { - piVarsC2[nLits2++] = pLit2->iVar; - pLit2 = pLit2->pHNext; - } - else - break; - } - *pnVarsC1 = nLits1; - *pnVarsC2 = nLits2; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fxu_Double * Fxu_MatrixFindDouble( Fxu_Matrix * p, - int piVarsC1[], int piVarsC2[], int nVarsC1, int nVarsC2 ) -{ - int piVarsC1_[100], piVarsC2_[100]; - int nVarsC1_, nVarsC2_, i; - Fxu_Double * pDouble; - Fxu_Pair * pPair; - unsigned Key; - - assert( nVarsC1 > 0 ); - assert( nVarsC2 > 0 ); - assert( piVarsC1[0] < piVarsC2[0] ); - - // get the hash key - Key = Fxu_PairHashKeyArray( p, piVarsC1, piVarsC2, nVarsC1, nVarsC2 ); - - // check if the divisor for this pair already exists - Key %= p->nTableSize; - Fxu_TableForEachDouble( p, Key, pDouble ) - { - pPair = pDouble->lPairs.pHead; - if ( pPair->nLits1 != nVarsC1 ) - continue; - if ( pPair->nLits2 != nVarsC2 ) - continue; - // get the cubes of this divisor - Fxu_MatrixGetDoubleVars( p, pDouble, piVarsC1_, piVarsC2_, &nVarsC1_, &nVarsC2_ ); - // compare lits of the first cube - for ( i = 0; i < nVarsC1; i++ ) - if ( piVarsC1[i] != piVarsC1_[i] ) - break; - if ( i != nVarsC1 ) - continue; - // compare lits of the second cube - for ( i = 0; i < nVarsC2; i++ ) - if ( piVarsC2[i] != piVarsC2_[i] ) - break; - if ( i != nVarsC2 ) - continue; - return pDouble; - } - return NULL; -} - - - - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_SelectSCD( Fxu_Matrix * p, int WeightLimit, Fxu_Var ** ppVar1, Fxu_Var ** ppVar2 ) -{ -// int * pValue2Node = p->pValue2Node; - Fxu_Var * pVar1; - Fxu_Var * pVar2, * pVarTemp; - Fxu_Lit * pLitV, * pLitH; - int Coin; - int CounterAll; - int CounterTest; - int WeightCur; - int WeightBest; - - CounterAll = 0; - CounterTest = 0; - - WeightBest = -10; - - // iterate through the columns in the matrix - Fxu_MatrixForEachVariable( p, pVar1 ) - { - // start collecting the affected vars - Fxu_MatrixRingVarsStart( p ); - - // go through all the literals of this variable - for ( pLitV = pVar1->lLits.pHead; pLitV; pLitV = pLitV->pVNext ) - { - // for this literal, go through all the horizontal literals - for ( pLitH = pLitV->pHNext; pLitH; pLitH = pLitH->pHNext ) - { - // get another variable - pVar2 = pLitH->pVar; - CounterAll++; - // skip the var if it is already used - if ( pVar2->pOrder ) - continue; - // skip the var if it belongs to the same node -// if ( pValue2Node[pVar1->iVar] == pValue2Node[pVar2->iVar] ) -// continue; - // collect the var - Fxu_MatrixRingVarsAdd( p, pVar2 ); - } - } - // stop collecting the selected vars - Fxu_MatrixRingVarsStop( p ); - - // iterate through the selected vars - Fxu_MatrixForEachVarInRing( p, pVar2 ) - { - CounterTest++; - - // count the coincidence - Coin = Fxu_SingleCountCoincidence( p, pVar1, pVar2 ); - assert( Coin > 0 ); - - // get the new weight - WeightCur = Coin - 2; - - // compare the weights - if ( WeightBest < WeightCur ) - { - WeightBest = WeightCur; - *ppVar1 = pVar1; - *ppVar2 = pVar2; - } - } - // unmark the vars - Fxu_MatrixForEachVarInRingSafe( p, pVar2, pVarTemp ) - pVar2->pOrder = NULL; - Fxu_MatrixRingVarsReset( p ); - } - -// if ( WeightBest == WeightLimit ) -// return -1; - return WeightBest; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/fxu/fxuSingle.c b/src/opt/fxu/fxuSingle.c deleted file mode 100644 index 73d9a76c..00000000 --- a/src/opt/fxu/fxuSingle.c +++ /dev/null @@ -1,284 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuSingle.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Procedures to compute the set of single-cube divisors.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuSingle.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fxuInt.h" -#include "vec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes and adds all single-cube divisors to storage.] - - Description [This procedure should be called once when the matrix is - already contructed before the process of logic extraction begins..] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixComputeSingles( Fxu_Matrix * p, int fUse0, int nSingleMax ) -{ - Fxu_Var * pVar; - Vec_Ptr_t * vSingles; - int i, k; - // set the weight limit - p->nWeightLimit = 1 - fUse0; - // iterate through columns in the matrix and collect single-cube divisors - vSingles = Vec_PtrAlloc( 10000 ); - Fxu_MatrixForEachVariable( p, pVar ) - Fxu_MatrixComputeSinglesOneCollect( p, pVar, vSingles ); - p->nSingleTotal = Vec_PtrSize(vSingles) / 3; - // check if divisors should be filtered - if ( Vec_PtrSize(vSingles) > nSingleMax ) - { - int * pWeigtCounts, nDivCount, Weight, i, c;; - assert( Vec_PtrSize(vSingles) % 3 == 0 ); - // count how many divisors have the given weight - pWeigtCounts = ALLOC( int, 1000 ); - memset( pWeigtCounts, 0, sizeof(int) * 1000 ); - for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 ) - { - Weight = (int)Vec_PtrEntry(vSingles, i); - if ( Weight >= 999 ) - pWeigtCounts[999]++; - else - pWeigtCounts[Weight]++; - } - // select the bound on the weight (above this bound, singles will be included) - nDivCount = 0; - for ( c = 999; c >= 0; c-- ) - { - nDivCount += pWeigtCounts[c]; - if ( nDivCount >= nSingleMax ) - break; - } - free( pWeigtCounts ); - // collect singles with the given costs - k = 0; - for ( i = 2; i < Vec_PtrSize(vSingles); i += 3 ) - { - Weight = (int)Vec_PtrEntry(vSingles, i); - if ( Weight < c ) - continue; - Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-2) ); - Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i-1) ); - Vec_PtrWriteEntry( vSingles, k++, Vec_PtrEntry(vSingles, i) ); - if ( k/3 == nSingleMax ) - break; - } - Vec_PtrShrink( vSingles, k ); - // adjust the weight limit - p->nWeightLimit = c; - } - // collect the selected divisors - assert( Vec_PtrSize(vSingles) % 3 == 0 ); - for ( i = 0; i < Vec_PtrSize(vSingles); i += 3 ) - { - Fxu_MatrixAddSingle( p, - Vec_PtrEntry(vSingles,i), - Vec_PtrEntry(vSingles,i+1), - (int)Vec_PtrEntry(vSingles,i+2) ); - } - Vec_PtrFree( vSingles ); -} - -/**Function************************************************************* - - Synopsis [Adds the single-cube divisors associated with a new column.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixComputeSinglesOneCollect( Fxu_Matrix * p, Fxu_Var * pVar, Vec_Ptr_t * vSingles ) -{ - Fxu_Lit * pLitV, * pLitH; - Fxu_Var * pVar2; - int Coin; - int WeightCur; - - // start collecting the affected vars - Fxu_MatrixRingVarsStart( p ); - // go through all the literals of this variable - for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext ) - // for this literal, go through all the horizontal literals - for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev ) - { - // get another variable - pVar2 = pLitH->pVar; - // skip the var if it is already used - if ( pVar2->pOrder ) - continue; - // skip the var if it belongs to the same node -// if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] ) -// continue; - // collect the var - Fxu_MatrixRingVarsAdd( p, pVar2 ); - } - // stop collecting the selected vars - Fxu_MatrixRingVarsStop( p ); - - // iterate through the selected vars - Fxu_MatrixForEachVarInRing( p, pVar2 ) - { - // count the coincidence - Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar ); - assert( Coin > 0 ); - // get the new weight - WeightCur = Coin - 2; - // peformance fix (August 24, 2007) - if ( WeightCur >= p->nWeightLimit ) - { - Vec_PtrPush( vSingles, pVar2 ); - Vec_PtrPush( vSingles, pVar ); - Vec_PtrPush( vSingles, (void *)WeightCur ); - } - } - - // unmark the vars - Fxu_MatrixRingVarsUnmark( p ); -} - -/**Function************************************************************* - - Synopsis [Adds the single-cube divisors associated with a new column.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_MatrixComputeSinglesOne( Fxu_Matrix * p, Fxu_Var * pVar ) -{ - Fxu_Lit * pLitV, * pLitH; - Fxu_Var * pVar2; - int Coin; - int WeightCur; - - // start collecting the affected vars - Fxu_MatrixRingVarsStart( p ); - // go through all the literals of this variable - for ( pLitV = pVar->lLits.pHead; pLitV; pLitV = pLitV->pVNext ) - // for this literal, go through all the horizontal literals - for ( pLitH = pLitV->pHPrev; pLitH; pLitH = pLitH->pHPrev ) - { - // get another variable - pVar2 = pLitH->pVar; - // skip the var if it is already used - if ( pVar2->pOrder ) - continue; - // skip the var if it belongs to the same node -// if ( pValue2Node[pVar->iVar] == pValue2Node[pVar2->iVar] ) -// continue; - // collect the var - Fxu_MatrixRingVarsAdd( p, pVar2 ); - } - // stop collecting the selected vars - Fxu_MatrixRingVarsStop( p ); - - // iterate through the selected vars - Fxu_MatrixForEachVarInRing( p, pVar2 ) - { - // count the coincidence - Coin = Fxu_SingleCountCoincidence( p, pVar2, pVar ); - assert( Coin > 0 ); - // get the new weight - WeightCur = Coin - 2; - // peformance fix (August 24, 2007) -// if ( WeightCur >= 0 ) -// Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur ); - if ( WeightCur >= p->nWeightLimit ) - Fxu_MatrixAddSingle( p, pVar2, pVar, WeightCur ); - } - // unmark the vars - Fxu_MatrixRingVarsUnmark( p ); -} - -/**Function************************************************************* - - Synopsis [Computes the coincidence count of two columns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_SingleCountCoincidence( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2 ) -{ - Fxu_Lit * pLit1, * pLit2; - int Result; - - // compute the coincidence count - Result = 0; - pLit1 = pVar1->lLits.pHead; - pLit2 = pVar2->lLits.pHead; - while ( 1 ) - { - if ( pLit1 && pLit2 ) - { - if ( pLit1->pCube->pVar->iVar == pLit2->pCube->pVar->iVar ) - { // the variables are the same - if ( pLit1->iCube == pLit2->iCube ) - { // the literals are the same - pLit1 = pLit1->pVNext; - pLit2 = pLit2->pVNext; - // add this literal to the coincidence - Result++; - } - else if ( pLit1->iCube < pLit2->iCube ) - pLit1 = pLit1->pVNext; - else - pLit2 = pLit2->pVNext; - } - else if ( pLit1->pCube->pVar->iVar < pLit2->pCube->pVar->iVar ) - pLit1 = pLit1->pVNext; - else - pLit2 = pLit2->pVNext; - } - else if ( pLit1 && !pLit2 ) - pLit1 = pLit1->pVNext; - else if ( !pLit1 && pLit2 ) - pLit2 = pLit2->pVNext; - else - break; - } - return Result; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/fxu/fxuUpdate.c b/src/opt/fxu/fxuUpdate.c deleted file mode 100644 index 274f79f6..00000000 --- a/src/opt/fxu/fxuUpdate.c +++ /dev/null @@ -1,806 +0,0 @@ -/**CFile**************************************************************** - - FileName [fxuUpdate.c] - - PackageName [MVSIS 2.0: Multi-valued logic synthesis system.] - - Synopsis [Updating the sparse matrix when divisors are accepted.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fxuUpdate.c,v 1.0 2003/02/01 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "fxuInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Fxu_UpdateDoublePairs( Fxu_Matrix * p, Fxu_Double * pDouble, Fxu_Var * pVar ); -static void Fxu_UpdateMatrixDoubleCreateCubes( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, Fxu_Double * pDiv ); -static void Fxu_UpdateMatrixDoubleClean( Fxu_Matrix * p, Fxu_Cube * pCubeUse, Fxu_Cube * pCubeRem ); -static void Fxu_UpdateMatrixSingleClean( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, Fxu_Var * pVarNew ); - -static void Fxu_UpdateCreateNewVars( Fxu_Matrix * p, Fxu_Var ** ppVarC, Fxu_Var ** ppVarD, int nCubes ); -static int Fxu_UpdatePairCompare( Fxu_Pair ** ppP1, Fxu_Pair ** ppP2 ); -static void Fxu_UpdatePairsSort( Fxu_Matrix * p, Fxu_Double * pDouble ); - -static void Fxu_UpdateCleanOldDoubles( Fxu_Matrix * p, Fxu_Double * pDiv, Fxu_Cube * pCube ); -static void Fxu_UpdateAddNewDoubles( Fxu_Matrix * p, Fxu_Cube * pCube ); -static void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p ); -static void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Updates the matrix after selecting two divisors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_Update( Fxu_Matrix * p, Fxu_Single * pSingle, Fxu_Double * pDouble ) -{ - Fxu_Cube * pCube, * pCubeNew; - Fxu_Var * pVarC, * pVarD; - Fxu_Var * pVar1, * pVar2; - - // consider trivial cases - if ( pSingle == NULL ) - { - assert( pDouble->Weight == Fxu_HeapDoubleReadMaxWeight( p->pHeapDouble ) ); - Fxu_UpdateDouble( p ); - return; - } - if ( pDouble == NULL ) - { - assert( pSingle->Weight == Fxu_HeapSingleReadMaxWeight( p->pHeapSingle ) ); - Fxu_UpdateSingle( p ); - return; - } - - // get the variables of the single - pVar1 = pSingle->pVar1; - pVar2 = pSingle->pVar2; - - // remove the best double from the heap - Fxu_HeapDoubleDelete( p->pHeapDouble, pDouble ); - // remove the best divisor from the table - Fxu_ListTableDelDivisor( p, pDouble ); - - // create two new columns (vars) - Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 1 ); - // create one new row (cube) - pCubeNew = Fxu_MatrixAddCube( p, pVarD, 0 ); - pCubeNew->pFirst = pCubeNew; - // set the first cube of the positive var - pVarD->pFirst = pCubeNew; - - // start collecting the affected vars and cubes - Fxu_MatrixRingCubesStart( p ); - Fxu_MatrixRingVarsStart( p ); - // add the vars - Fxu_MatrixRingVarsAdd( p, pVar1 ); - Fxu_MatrixRingVarsAdd( p, pVar2 ); - // remove the literals and collect the affected cubes - // remove the divisors associated with this cube - // add to the affected cube the literal corresponding to the new column - Fxu_UpdateMatrixSingleClean( p, pVar1, pVar2, pVarD ); - // replace each two cubes of the pair by one new cube - // the new cube contains the base and the new literal - Fxu_UpdateDoublePairs( p, pDouble, pVarC ); - // stop collecting the affected vars and cubes - Fxu_MatrixRingCubesStop( p ); - Fxu_MatrixRingVarsStop( p ); - - // add the literals to the new cube - assert( pVar1->iVar < pVar2->iVar ); - assert( Fxu_SingleCountCoincidence( p, pVar1, pVar2 ) == 0 ); - Fxu_MatrixAddLiteral( p, pCubeNew, pVar1 ); - Fxu_MatrixAddLiteral( p, pCubeNew, pVar2 ); - - // create new doubles; we cannot add them in the same loop - // because we first have to create *all* new cubes for each node - Fxu_MatrixForEachCubeInRing( p, pCube ) - Fxu_UpdateAddNewDoubles( p, pCube ); - // update the singles after removing some literals - Fxu_UpdateCleanOldSingles( p ); - - // undo the temporary rings with cubes and vars - Fxu_MatrixRingCubesUnmark( p ); - Fxu_MatrixRingVarsUnmark( p ); - // we should undo the rings before creating new singles - - // create new singles - Fxu_UpdateAddNewSingles( p, pVarC ); - Fxu_UpdateAddNewSingles( p, pVarD ); - - // recycle the divisor - MEM_FREE_FXU( p, Fxu_Double, 1, pDouble ); - p->nDivs3++; -} - -/**Function************************************************************* - - Synopsis [Updates after accepting single cube divisor.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdateSingle( Fxu_Matrix * p ) -{ - Fxu_Single * pSingle; - Fxu_Cube * pCube, * pCubeNew; - Fxu_Var * pVarC, * pVarD; - Fxu_Var * pVar1, * pVar2; - - // read the best divisor from the heap - pSingle = Fxu_HeapSingleReadMax( p->pHeapSingle ); - // get the variables of this single-cube divisor - pVar1 = pSingle->pVar1; - pVar2 = pSingle->pVar2; - - // create two new columns (vars) - Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 1 ); - // create one new row (cube) - pCubeNew = Fxu_MatrixAddCube( p, pVarD, 0 ); - pCubeNew->pFirst = pCubeNew; - // set the first cube - pVarD->pFirst = pCubeNew; - - // start collecting the affected vars and cubes - Fxu_MatrixRingCubesStart( p ); - Fxu_MatrixRingVarsStart( p ); - // add the vars - Fxu_MatrixRingVarsAdd( p, pVar1 ); - Fxu_MatrixRingVarsAdd( p, pVar2 ); - // remove the literals and collect the affected cubes - // remove the divisors associated with this cube - // add to the affected cube the literal corresponding to the new column - Fxu_UpdateMatrixSingleClean( p, pVar1, pVar2, pVarD ); - // stop collecting the affected vars and cubes - Fxu_MatrixRingCubesStop( p ); - Fxu_MatrixRingVarsStop( p ); - - // add the literals to the new cube - assert( pVar1->iVar < pVar2->iVar ); - assert( Fxu_SingleCountCoincidence( p, pVar1, pVar2 ) == 0 ); - Fxu_MatrixAddLiteral( p, pCubeNew, pVar1 ); - Fxu_MatrixAddLiteral( p, pCubeNew, pVar2 ); - - // create new doubles; we cannot add them in the same loop - // because we first have to create *all* new cubes for each node - Fxu_MatrixForEachCubeInRing( p, pCube ) - Fxu_UpdateAddNewDoubles( p, pCube ); - // update the singles after removing some literals - Fxu_UpdateCleanOldSingles( p ); - // we should undo the rings before creating new singles - - // unmark the cubes - Fxu_MatrixRingCubesUnmark( p ); - Fxu_MatrixRingVarsUnmark( p ); - - // create new singles - Fxu_UpdateAddNewSingles( p, pVarC ); - Fxu_UpdateAddNewSingles( p, pVarD ); - p->nDivs1++; -} - -/**Function************************************************************* - - Synopsis [Updates the matrix after accepting a double cube divisor.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdateDouble( Fxu_Matrix * p ) -{ - Fxu_Double * pDiv; - Fxu_Cube * pCube, * pCubeNew1, * pCubeNew2; - Fxu_Var * pVarC, * pVarD; - - // remove the best divisor from the heap - pDiv = Fxu_HeapDoubleGetMax( p->pHeapDouble ); - // remove the best divisor from the table - Fxu_ListTableDelDivisor( p, pDiv ); - - // create two new columns (vars) - Fxu_UpdateCreateNewVars( p, &pVarC, &pVarD, 2 ); - // create two new rows (cubes) - pCubeNew1 = Fxu_MatrixAddCube( p, pVarD, 0 ); - pCubeNew1->pFirst = pCubeNew1; - pCubeNew2 = Fxu_MatrixAddCube( p, pVarD, 1 ); - pCubeNew2->pFirst = pCubeNew1; - // set the first cube - pVarD->pFirst = pCubeNew1; - - // add the literals to the new cubes - Fxu_UpdateMatrixDoubleCreateCubes( p, pCubeNew1, pCubeNew2, pDiv ); - - // start collecting the affected cubes and vars - Fxu_MatrixRingCubesStart( p ); - Fxu_MatrixRingVarsStart( p ); - // replace each two cubes of the pair by one new cube - // the new cube contains the base and the new literal - Fxu_UpdateDoublePairs( p, pDiv, pVarD ); - // stop collecting the affected cubes and vars - Fxu_MatrixRingCubesStop( p ); - Fxu_MatrixRingVarsStop( p ); - - // create new doubles; we cannot add them in the same loop - // because we first have to create *all* new cubes for each node - Fxu_MatrixForEachCubeInRing( p, pCube ) - Fxu_UpdateAddNewDoubles( p, pCube ); - // update the singles after removing some literals - Fxu_UpdateCleanOldSingles( p ); - - // undo the temporary rings with cubes and vars - Fxu_MatrixRingCubesUnmark( p ); - Fxu_MatrixRingVarsUnmark( p ); - // we should undo the rings before creating new singles - - // create new singles - Fxu_UpdateAddNewSingles( p, pVarC ); - Fxu_UpdateAddNewSingles( p, pVarD ); - - // recycle the divisor - MEM_FREE_FXU( p, Fxu_Double, 1, pDiv ); - p->nDivs2++; -} - -/**Function************************************************************* - - Synopsis [Update the pairs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdateDoublePairs( Fxu_Matrix * p, Fxu_Double * pDouble, Fxu_Var * pVar ) -{ - Fxu_Pair * pPair; - Fxu_Cube * pCubeUse, * pCubeRem; - int i; - - // collect and sort the pairs - Fxu_UpdatePairsSort( p, pDouble ); -// for ( i = 0; i < p->nPairsTemp; i++ ) - for ( i = 0; i < p->vPairs->nSize; i++ ) - { - // get the pair -// pPair = p->pPairsTemp[i]; - pPair = p->vPairs->pArray[i]; - // out of the two cubes, select the one which comes earlier - pCubeUse = Fxu_PairMinCube( pPair ); - pCubeRem = Fxu_PairMaxCube( pPair ); - // collect the affected cube - assert( pCubeUse->pOrder == NULL ); - Fxu_MatrixRingCubesAdd( p, pCubeUse ); - - // remove some literals from pCubeUse and all literals from pCubeRem - Fxu_UpdateMatrixDoubleClean( p, pCubeUse, pCubeRem ); - // add a literal that depends on the new variable - Fxu_MatrixAddLiteral( p, pCubeUse, pVar ); - // check the literal count - assert( pCubeUse->lLits.nItems == pPair->nBase + 1 ); - assert( pCubeRem->lLits.nItems == 0 ); - - // update the divisors by removing useless pairs - Fxu_UpdateCleanOldDoubles( p, pDouble, pCubeUse ); - Fxu_UpdateCleanOldDoubles( p, pDouble, pCubeRem ); - // remove the pair - MEM_FREE_FXU( p, Fxu_Pair, 1, pPair ); - } - p->vPairs->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [Add two cubes corresponding to the given double-cube divisor.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdateMatrixDoubleCreateCubes( Fxu_Matrix * p, Fxu_Cube * pCube1, Fxu_Cube * pCube2, Fxu_Double * pDiv ) -{ - Fxu_Lit * pLit1, * pLit2; - Fxu_Pair * pPair; - int nBase, nLits1, nLits2; - - // fill in the SOP and copy the fanins - nBase = nLits1 = nLits2 = 0; - pPair = pDiv->lPairs.pHead; - pLit1 = pPair->pCube1->lLits.pHead; - pLit2 = pPair->pCube2->lLits.pHead; - while ( 1 ) - { - if ( pLit1 && pLit2 ) - { - if ( pLit1->iVar == pLit2->iVar ) - { // skip the cube free part - pLit1 = pLit1->pHNext; - pLit2 = pLit2->pHNext; - nBase++; - } - else if ( pLit1->iVar < pLit2->iVar ) - { // add literal to the first cube - Fxu_MatrixAddLiteral( p, pCube1, pLit1->pVar ); - // move to the next literal in this cube - pLit1 = pLit1->pHNext; - nLits1++; - } - else - { // add literal to the second cube - Fxu_MatrixAddLiteral( p, pCube2, pLit2->pVar ); - // move to the next literal in this cube - pLit2 = pLit2->pHNext; - nLits2++; - } - } - else if ( pLit1 && !pLit2 ) - { // add literal to the first cube - Fxu_MatrixAddLiteral( p, pCube1, pLit1->pVar ); - // move to the next literal in this cube - pLit1 = pLit1->pHNext; - nLits1++; - } - else if ( !pLit1 && pLit2 ) - { // add literal to the second cube - Fxu_MatrixAddLiteral( p, pCube2, pLit2->pVar ); - // move to the next literal in this cube - pLit2 = pLit2->pHNext; - nLits2++; - } - else - break; - } - assert( pPair->nLits1 == nLits1 ); - assert( pPair->nLits2 == nLits2 ); - assert( pPair->nBase == nBase ); -} - - -/**Function************************************************************* - - Synopsis [Create the node equal to double-cube divisor.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdateMatrixDoubleClean( Fxu_Matrix * p, Fxu_Cube * pCubeUse, Fxu_Cube * pCubeRem ) -{ - Fxu_Lit * pLit1, * bLit1Next; - Fxu_Lit * pLit2, * bLit2Next; - - // initialize the starting literals - pLit1 = pCubeUse->lLits.pHead; - pLit2 = pCubeRem->lLits.pHead; - bLit1Next = pLit1? pLit1->pHNext: NULL; - bLit2Next = pLit2? pLit2->pHNext: NULL; - // go through the pair and remove the literals in the base - // from the first cube and all literals from the second cube - while ( 1 ) - { - if ( pLit1 && pLit2 ) - { - if ( pLit1->iVar == pLit2->iVar ) - { // this literal is present in both cubes - it belongs to the base - // mark the affected var - if ( pLit1->pVar->pOrder == NULL ) - Fxu_MatrixRingVarsAdd( p, pLit1->pVar ); - // leave the base in pCubeUse; delete it from pCubeRem - Fxu_MatrixDelLiteral( p, pLit2 ); - // step to the next literals - pLit1 = bLit1Next; - pLit2 = bLit2Next; - bLit1Next = pLit1? pLit1->pHNext: NULL; - bLit2Next = pLit2? pLit2->pHNext: NULL; - } - else if ( pLit1->iVar < pLit2->iVar ) - { // this literal is present in pCubeUse - remove it - // mark the affected var - if ( pLit1->pVar->pOrder == NULL ) - Fxu_MatrixRingVarsAdd( p, pLit1->pVar ); - // delete this literal - Fxu_MatrixDelLiteral( p, pLit1 ); - // step to the next literals - pLit1 = bLit1Next; - bLit1Next = pLit1? pLit1->pHNext: NULL; - } - else - { // this literal is present in pCubeRem - remove it - // mark the affected var - if ( pLit2->pVar->pOrder == NULL ) - Fxu_MatrixRingVarsAdd( p, pLit2->pVar ); - // delete this literal - Fxu_MatrixDelLiteral( p, pLit2 ); - // step to the next literals - pLit2 = bLit2Next; - bLit2Next = pLit2? pLit2->pHNext: NULL; - } - } - else if ( pLit1 && !pLit2 ) - { // this literal is present in pCubeUse - leave it - // mark the affected var - if ( pLit1->pVar->pOrder == NULL ) - Fxu_MatrixRingVarsAdd( p, pLit1->pVar ); - // delete this literal - Fxu_MatrixDelLiteral( p, pLit1 ); - // step to the next literals - pLit1 = bLit1Next; - bLit1Next = pLit1? pLit1->pHNext: NULL; - } - else if ( !pLit1 && pLit2 ) - { // this literal is present in pCubeRem - remove it - // mark the affected var - if ( pLit2->pVar->pOrder == NULL ) - Fxu_MatrixRingVarsAdd( p, pLit2->pVar ); - // delete this literal - Fxu_MatrixDelLiteral( p, pLit2 ); - // step to the next literals - pLit2 = bLit2Next; - bLit2Next = pLit2? pLit2->pHNext: NULL; - } - else - break; - } -} - -/**Function************************************************************* - - Synopsis [Updates the matrix after selecting a single cube divisor.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdateMatrixSingleClean( Fxu_Matrix * p, Fxu_Var * pVar1, Fxu_Var * pVar2, Fxu_Var * pVarNew ) -{ - Fxu_Lit * pLit1, * bLit1Next; - Fxu_Lit * pLit2, * bLit2Next; - - // initialize the starting literals - pLit1 = pVar1->lLits.pHead; - pLit2 = pVar2->lLits.pHead; - bLit1Next = pLit1? pLit1->pVNext: NULL; - bLit2Next = pLit2? pLit2->pVNext: NULL; - while ( 1 ) - { - if ( pLit1 && pLit2 ) - { - if ( pLit1->pCube->pVar->iVar == pLit2->pCube->pVar->iVar ) - { // these literals coincide - if ( pLit1->iCube == pLit2->iCube ) - { // these literals coincide - - // collect the affected cube - assert( pLit1->pCube->pOrder == NULL ); - Fxu_MatrixRingCubesAdd( p, pLit1->pCube ); - - // add the literal to this cube corresponding to the new column - Fxu_MatrixAddLiteral( p, pLit1->pCube, pVarNew ); - // clean the old cubes - Fxu_UpdateCleanOldDoubles( p, NULL, pLit1->pCube ); - - // remove the literals - Fxu_MatrixDelLiteral( p, pLit1 ); - Fxu_MatrixDelLiteral( p, pLit2 ); - - // go to the next literals - pLit1 = bLit1Next; - pLit2 = bLit2Next; - bLit1Next = pLit1? pLit1->pVNext: NULL; - bLit2Next = pLit2? pLit2->pVNext: NULL; - } - else if ( pLit1->iCube < pLit2->iCube ) - { - pLit1 = bLit1Next; - bLit1Next = pLit1? pLit1->pVNext: NULL; - } - else - { - pLit2 = bLit2Next; - bLit2Next = pLit2? pLit2->pVNext: NULL; - } - } - else if ( pLit1->pCube->pVar->iVar < pLit2->pCube->pVar->iVar ) - { - pLit1 = bLit1Next; - bLit1Next = pLit1? pLit1->pVNext: NULL; - } - else - { - pLit2 = bLit2Next; - bLit2Next = pLit2? pLit2->pVNext: NULL; - } - } - else if ( pLit1 && !pLit2 ) - { - pLit1 = bLit1Next; - bLit1Next = pLit1? pLit1->pVNext: NULL; - } - else if ( !pLit1 && pLit2 ) - { - pLit2 = bLit2Next; - bLit2Next = pLit2? pLit2->pVNext: NULL; - } - else - break; - } -} - -/**Function************************************************************* - - Synopsis [Sort the pairs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdatePairsSort( Fxu_Matrix * p, Fxu_Double * pDouble ) -{ - Fxu_Pair * pPair; - // order the pairs by the first cube to ensure that new literals are added - // to the matrix from top to bottom - collect pairs into the array - p->vPairs->nSize = 0; - Fxu_DoubleForEachPair( pDouble, pPair ) - Vec_PtrPush( p->vPairs, pPair ); - if ( p->vPairs->nSize < 2 ) - return; - // sort - qsort( (void *)p->vPairs->pArray, p->vPairs->nSize, sizeof(Fxu_Pair *), - (int (*)(const void *, const void *)) Fxu_UpdatePairCompare ); - assert( Fxu_UpdatePairCompare( (Fxu_Pair**)p->vPairs->pArray, (Fxu_Pair**)p->vPairs->pArray + p->vPairs->nSize - 1 ) < 0 ); -} - -/**Function************************************************************* - - Synopsis [Compares the vars by their number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fxu_UpdatePairCompare( Fxu_Pair ** ppP1, Fxu_Pair ** ppP2 ) -{ - Fxu_Cube * pC1 = (*ppP1)->pCube1; - Fxu_Cube * pC2 = (*ppP2)->pCube1; - int iP1CubeMin, iP2CubeMin; - if ( pC1->pVar->iVar < pC2->pVar->iVar ) - return -1; - if ( pC1->pVar->iVar > pC2->pVar->iVar ) - return 1; - iP1CubeMin = Fxu_PairMinCubeInt( *ppP1 ); - iP2CubeMin = Fxu_PairMinCubeInt( *ppP2 ); - if ( iP1CubeMin < iP2CubeMin ) - return -1; - if ( iP1CubeMin > iP2CubeMin ) - return 1; - assert( 0 ); - return 0; -} - - -/**Function************************************************************* - - Synopsis [Create new variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdateCreateNewVars( Fxu_Matrix * p, Fxu_Var ** ppVarC, Fxu_Var ** ppVarD, int nCubes ) -{ - Fxu_Var * pVarC, * pVarD; - - // add a new column for the complement - pVarC = Fxu_MatrixAddVar( p ); - pVarC->nCubes = 0; - // add a new column for the divisor - pVarD = Fxu_MatrixAddVar( p ); - pVarD->nCubes = nCubes; - - // mark this entry in the Value2Node array -// assert( p->pValue2Node[pVarC->iVar] > 0 ); -// p->pValue2Node[pVarD->iVar ] = p->pValue2Node[pVarC->iVar]; -// p->pValue2Node[pVarD->iVar+1] = p->pValue2Node[pVarC->iVar]+1; - - *ppVarC = pVarC; - *ppVarD = pVarD; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdateCleanOldDoubles( Fxu_Matrix * p, Fxu_Double * pDiv, Fxu_Cube * pCube ) -{ - Fxu_Double * pDivCur; - Fxu_Pair * pPair; - int i; - - // if the cube is a recently introduced one - // it does not have pairs allocated - // in this case, there is nothing to update - if ( pCube->pVar->ppPairs == NULL ) - return; - - // go through all the pairs of this cube - Fxu_CubeForEachPair( pCube, pPair, i ) - { - // get the divisor of this pair - pDivCur = pPair->pDiv; - // skip the current divisor - if ( pDivCur == pDiv ) - continue; - // remove this pair - Fxu_ListDoubleDelPair( pDivCur, pPair ); - // the divisor may have become useless by now - if ( pDivCur->lPairs.nItems == 0 ) - { - assert( pDivCur->Weight == pPair->nBase - 1 ); - Fxu_HeapDoubleDelete( p->pHeapDouble, pDivCur ); - Fxu_MatrixDelDivisor( p, pDivCur ); - } - else - { - // update the divisor's weight - pDivCur->Weight -= pPair->nLits1 + pPair->nLits2 - 1 + pPair->nBase; - Fxu_HeapDoubleUpdate( p->pHeapDouble, pDivCur ); - } - MEM_FREE_FXU( p, Fxu_Pair, 1, pPair ); - } - // finally erase all the pair info associated with this cube - Fxu_PairClearStorage( pCube ); -} - -/**Function************************************************************* - - Synopsis [Adds the new divisors that depend on the cube.] - - Description [Go through all the non-empty cubes of this cover - (except the given cube) and, for each of them, add the new divisor - with the given cube.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdateAddNewDoubles( Fxu_Matrix * p, Fxu_Cube * pCube ) -{ - Fxu_Cube * pTemp; - assert( pCube->pOrder ); - - // if the cube is a recently introduced one - // it does not have pairs allocated - // in this case, there is nothing to update - if ( pCube->pVar->ppPairs == NULL ) - return; - - for ( pTemp = pCube->pFirst; pTemp->pVar == pCube->pVar; pTemp = pTemp->pNext ) - { - // do not add pairs with the empty cubes - if ( pTemp->lLits.nItems == 0 ) - continue; - // to prevent adding duplicated pairs of the new cubes - // do not add the pair, if the current cube is marked - if ( pTemp->pOrder && pTemp >= pCube ) - continue; - Fxu_MatrixAddDivisor( p, pTemp, pCube ); - } -} - -/**Function************************************************************* - - Synopsis [Removes old single cube divisors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdateCleanOldSingles( Fxu_Matrix * p ) -{ - Fxu_Single * pSingle, * pSingle2; - int WeightNew; - int Counter = 0; - - Fxu_MatrixForEachSingleSafe( p, pSingle, pSingle2 ) - { - // if at least one of the variables is marked, recalculate - if ( pSingle->pVar1->pOrder || pSingle->pVar2->pOrder ) - { - Counter++; - // get the new weight - WeightNew = -2 + Fxu_SingleCountCoincidence( p, pSingle->pVar1, pSingle->pVar2 ); - if ( WeightNew >= 0 ) - { - pSingle->Weight = WeightNew; - Fxu_HeapSingleUpdate( p->pHeapSingle, pSingle ); - } - else - { - Fxu_HeapSingleDelete( p->pHeapSingle, pSingle ); - Fxu_ListMatrixDelSingle( p, pSingle ); - MEM_FREE_FXU( p, Fxu_Single, 1, pSingle ); - } - } - } -// printf( "Called procedure %d times.\n", Counter ); -} - -/**Function************************************************************* - - Synopsis [Updates the single cube divisors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fxu_UpdateAddNewSingles( Fxu_Matrix * p, Fxu_Var * pVar ) -{ - Fxu_MatrixComputeSinglesOne( p, pVar ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/fxu/module.make b/src/opt/fxu/module.make deleted file mode 100644 index dd8acd40..00000000 --- a/src/opt/fxu/module.make +++ /dev/null @@ -1,12 +0,0 @@ -SRC += src/opt/fxu/fxu.c \ - src/opt/fxu/fxuCreate.c \ - src/opt/fxu/fxuHeapD.c \ - src/opt/fxu/fxuHeapS.c \ - src/opt/fxu/fxuList.c \ - src/opt/fxu/fxuMatrix.c \ - src/opt/fxu/fxuPair.c \ - src/opt/fxu/fxuPrint.c \ - src/opt/fxu/fxuReduce.c \ - src/opt/fxu/fxuSelect.c \ - src/opt/fxu/fxuSingle.c \ - src/opt/fxu/fxuUpdate.c diff --git a/src/opt/lpk/lpk.h b/src/opt/lpk/lpk.h deleted file mode 100644 index 2a642db2..00000000 --- a/src/opt/lpk/lpk.h +++ /dev/null @@ -1,84 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpk.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpk.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __LPK_H__ -#define __LPK_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Lpk_Par_t_ Lpk_Par_t; -struct Lpk_Par_t_ -{ - // user-controlled parameters - int nLutsMax; // (N) the maximum number of LUTs in the structure - int nLutsOver; // (Q) the maximum number of LUTs not in the MFFC - int nVarsShared; // (S) the maximum number of shared variables (crossbars) - int nGrowthLevel; // (L) the maximum increase in the node level after resynthesis - int fSatur; // iterate till saturation - int fZeroCost; // accept zero-cost replacements - int fFirst; // use root node and first cut only - int fOldAlgo; // use old algorithm - int fVerbose; // the verbosiness flag - int fVeryVerbose; // additional verbose info printout - // internal parameters - int nLutSize; // (K) the LUT size (determined by the input network) - int nVarsMax; // (V) the largest number of variables: V = N * (K-1) + 1 -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== lpkCore.c ========================================================*/ -extern int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars ); - - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/lpk/lpkAbcDec.c b/src/opt/lpk/lpkAbcDec.c deleted file mode 100644 index aa2d4bc0..00000000 --- a/src/opt/lpk/lpkAbcDec.c +++ /dev/null @@ -1,290 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpkAbcDec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [The new core procedure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpkAbcDec.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "lpkInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Implements the function.] - - Description [Returns the node implementing this function.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Lpk_ImplementFun( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * p ) -{ - extern Hop_Obj_t * Kit_TruthToHop( Hop_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory ); - unsigned * pTruth; - Abc_Obj_t * pObjNew; - int i; - if ( p->fMark ) - pMan->nMuxes++; - else - pMan->nDsds++; - // create the new node - pObjNew = Abc_NtkCreateNode( pNtk ); - for ( i = 0; i < (int)p->nVars; i++ ) - Abc_ObjAddFanin( pObjNew, Abc_ObjRegular(Vec_PtrEntry(vLeaves, p->pFanins[i])) ); - Abc_ObjSetLevel( pObjNew, Abc_ObjLevelNew(pObjNew) ); - // assign the node's function - pTruth = Lpk_FunTruth(p, 0); - if ( p->nVars == 0 ) - { - pObjNew->pData = Hop_NotCond( Hop_ManConst1(pNtk->pManFunc), !(pTruth[0] & 1) ); - return pObjNew; - } - if ( p->nVars == 1 ) - { - pObjNew->pData = Hop_NotCond( Hop_ManPi(pNtk->pManFunc, 0), (pTruth[0] & 1) ); - return pObjNew; - } - // create the logic function - pObjNew->pData = Kit_TruthToHop( pNtk->pManFunc, pTruth, p->nVars, NULL ); - return pObjNew; -} - -/**Function************************************************************* - - Synopsis [Implements the function.] - - Description [Returns the node implementing this function.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Lpk_Implement_rec( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, Lpk_Fun_t * pFun ) -{ - Abc_Obj_t * pFanin, * pRes; - int i; - // prepare the leaves of the function - for ( i = 0; i < (int)pFun->nVars; i++ ) - { - pFanin = Vec_PtrEntry( vLeaves, pFun->pFanins[i] ); - if ( !Abc_ObjIsComplement(pFanin) ) - Lpk_Implement_rec( pMan, pNtk, vLeaves, (Lpk_Fun_t *)pFanin ); - pFanin = Vec_PtrEntry( vLeaves, pFun->pFanins[i] ); - assert( Abc_ObjIsComplement(pFanin) ); - } - // construct the function - pRes = Lpk_ImplementFun( pMan, pNtk, vLeaves, pFun ); - // replace the function - Vec_PtrWriteEntry( vLeaves, pFun->Id, Abc_ObjNot(pRes) ); - Lpk_FunFree( pFun ); - return pRes; -} - -/**Function************************************************************* - - Synopsis [Implements the function.] - - Description [Returns the node implementing this function.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Lpk_Implement( Lpk_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, int nLeavesOld ) -{ - Abc_Obj_t * pFanin, * pRes; - int i; - assert( nLeavesOld < Vec_PtrSize(vLeaves) ); - // mark implemented nodes - Vec_PtrForEachEntryStop( vLeaves, pFanin, i, nLeavesOld ) - Vec_PtrWriteEntry( vLeaves, i, Abc_ObjNot(pFanin) ); - // recursively construct starting from the first entry - pRes = Lpk_Implement_rec( pMan, pNtk, vLeaves, Vec_PtrEntry( vLeaves, nLeavesOld ) ); - Vec_PtrShrink( vLeaves, nLeavesOld ); - return pRes; -} - -/**Function************************************************************* - - Synopsis [Decomposes the function using recursive MUX decomposition.] - - Description [Returns the ID of the top-most decomposition node - implementing this function, or 0 if there is no decomposition satisfying - the constraints on area and delay.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_Decompose_rec( Lpk_Man_t * pMan, Lpk_Fun_t * p ) -{ - static Lpk_Res_t Res0, * pRes0 = &Res0; - Lpk_Res_t * pResMux, * pResDsd; - Lpk_Fun_t * p2; - int clk; - - // is only called for non-trivial blocks - assert( p->nLutK >= 3 && p->nLutK <= 6 ); - assert( p->nVars > p->nLutK ); - // skip if area bound is exceeded - if ( Lpk_LutNumLuts(p->nVars, p->nLutK) > (int)p->nAreaLim ) - return 0; - // skip if delay bound is exceeded - if ( Lpk_SuppDelay(p->uSupp, p->pDelays) > (int)p->nDelayLim ) - return 0; - - // compute supports if needed - if ( !p->fSupports ) - Lpk_FunComputeCofSupps( p ); - - // check DSD decomposition -clk = clock(); - pResDsd = Lpk_DsdAnalize( pMan, p, pMan->pPars->nVarsShared ); -pMan->timeEvalDsdAn += clock() - clk; - if ( pResDsd && (pResDsd->nBSVars == (int)p->nLutK || pResDsd->nBSVars == (int)p->nLutK - 1) && - pResDsd->AreaEst <= (int)p->nAreaLim && pResDsd->DelayEst <= (int)p->nDelayLim ) - { -clk = clock(); - p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars ); -pMan->timeEvalDsdSp += clock() - clk; - assert( p2->nVars <= (int)p->nLutK ); - if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) - return 0; - return 1; - } - - // check MUX decomposition -clk = clock(); - pResMux = Lpk_MuxAnalize( pMan, p ); -pMan->timeEvalMuxAn += clock() - clk; -// pResMux = NULL; - assert( !pResMux || (pResMux->DelayEst <= (int)p->nDelayLim && pResMux->AreaEst <= (int)p->nAreaLim) ); - // accept MUX decomposition if it is "good" - if ( pResMux && pResMux->nSuppSizeS <= (int)p->nLutK && pResMux->nSuppSizeL <= (int)p->nLutK ) - pResDsd = NULL; - else if ( pResMux && pResDsd ) - { - // compare two decompositions - if ( pResMux->AreaEst < pResDsd->AreaEst || - (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL < pResDsd->nSuppSizeL) || - (pResMux->AreaEst == pResDsd->AreaEst && pResMux->nSuppSizeL == pResDsd->nSuppSizeL && pResMux->DelayEst < pResDsd->DelayEst) ) - pResDsd = NULL; - else - pResMux = NULL; - } - assert( pResMux == NULL || pResDsd == NULL ); - if ( pResMux ) - { -clk = clock(); - p2 = Lpk_MuxSplit( pMan, p, pResMux->Variable, pResMux->Polarity ); -pMan->timeEvalMuxSp += clock() - clk; - if ( p2->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p2 ) ) - return 0; - if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) - return 0; - return 1; - } - if ( pResDsd ) - { -clk = clock(); - p2 = Lpk_DsdSplit( pMan, p, pResDsd->pCofVars, pResDsd->nCofVars, pResDsd->BSVars ); -pMan->timeEvalDsdSp += clock() - clk; - assert( p2->nVars <= (int)p->nLutK ); - if ( p->nVars > p->nLutK && !Lpk_Decompose_rec( pMan, p ) ) - return 0; - return 1; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Removes decomposed nodes from the array of fanins.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_DecomposeClean( Vec_Ptr_t * vLeaves, int nLeavesOld ) -{ - Lpk_Fun_t * pFunc; - int i; - Vec_PtrForEachEntryStart( vLeaves, pFunc, i, nLeavesOld ) - Lpk_FunFree( pFunc ); - Vec_PtrShrink( vLeaves, nLeavesOld ); -} - -/**Function************************************************************* - - Synopsis [Decomposes the function using recursive MUX decomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Lpk_Decompose( Lpk_Man_t * p, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, unsigned * puSupps, int nLutK, int AreaLim, int DelayLim ) -{ - Lpk_Fun_t * pFun; - Abc_Obj_t * pObjNew = NULL; - int nLeaves = Vec_PtrSize( vLeaves ); - pFun = Lpk_FunCreate( pNtk, vLeaves, pTruth, nLutK, AreaLim, DelayLim ); - if ( puSupps[0] || puSupps[1] ) - { -/* - int i; - Lpk_FunComputeCofSupps( pFun ); - for ( i = 0; i < nLeaves; i++ ) - { - assert( pFun->puSupps[2*i+0] == puSupps[2*i+0] ); - assert( pFun->puSupps[2*i+1] == puSupps[2*i+1] ); - } -*/ - memcpy( pFun->puSupps, puSupps, sizeof(unsigned) * 2 * nLeaves ); - pFun->fSupports = 1; - } - Lpk_FunSuppMinimize( pFun ); - if ( pFun->nVars <= pFun->nLutK ) - pObjNew = Lpk_ImplementFun( p, pNtk, vLeaves, pFun ); - else if ( Lpk_Decompose_rec(p, pFun) ) - pObjNew = Lpk_Implement( p, pNtk, vLeaves, nLeaves ); - Lpk_DecomposeClean( vLeaves, nLeaves ); - return pObjNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/lpkAbcDsd.c b/src/opt/lpk/lpkAbcDsd.c deleted file mode 100644 index f4095914..00000000 --- a/src/opt/lpk/lpkAbcDsd.c +++ /dev/null @@ -1,603 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpkAbcDsd.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [LUT-decomposition based on recursive DSD.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpkAbcDsd.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "lpkInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Cofactors TTs w.r.t. all vars and finds the best var.] - - Description [The best variable is the variable with the minimum - sum total of the support sizes of all truth tables. This procedure - computes and returns cofactors w.r.t. the best variable.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_FunComputeMinSuppSizeVar( Lpk_Fun_t * p, unsigned ** ppTruths, int nTruths, unsigned ** ppCofs, unsigned uNonDecSupp ) -{ - int i, Var, VarBest, nSuppSize0, nSuppSize1, nSuppTotalMin, nSuppTotalCur, nSuppMaxMin, nSuppMaxCur; - assert( nTruths > 0 ); - VarBest = -1; - Lpk_SuppForEachVar( p->uSupp, Var ) - { - if ( (uNonDecSupp & (1 << Var)) == 0 ) - continue; - nSuppMaxCur = 0; - nSuppTotalCur = 0; - for ( i = 0; i < nTruths; i++ ) - { - if ( nTruths == 1 ) - { - nSuppSize0 = Kit_WordCountOnes( p->puSupps[2*Var+0] ); - nSuppSize1 = Kit_WordCountOnes( p->puSupps[2*Var+1] ); - } - else - { - Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, Var ); - Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, Var ); - nSuppSize0 = Kit_TruthSupportSize( ppCofs[2*i+0], p->nVars ); - nSuppSize1 = Kit_TruthSupportSize( ppCofs[2*i+1], p->nVars ); - } - nSuppMaxCur = ABC_MAX( nSuppMaxCur, nSuppSize0 ); - nSuppMaxCur = ABC_MAX( nSuppMaxCur, nSuppSize1 ); - nSuppTotalCur += nSuppSize0 + nSuppSize1; - } - if ( VarBest == -1 || nSuppMaxMin > nSuppMaxCur || - (nSuppMaxMin == nSuppMaxCur && nSuppTotalMin > nSuppTotalCur) ) - { - VarBest = Var; - nSuppMaxMin = nSuppMaxCur; - nSuppTotalMin = nSuppTotalCur; - } - } - // recompute cofactors for the best var - for ( i = 0; i < nTruths; i++ ) - { - Kit_TruthCofactor0New( ppCofs[2*i+0], ppTruths[i], p->nVars, VarBest ); - Kit_TruthCofactor1New( ppCofs[2*i+1], ppTruths[i], p->nVars, VarBest ); - } - return VarBest; -} - -/**Function************************************************************* - - Synopsis [Recursively computes decomposable subsets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Lpk_ComputeBoundSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets, int nSizeMax ) -{ - unsigned i, iLitFanin, uSupport, uSuppCur; - Kit_DsdObj_t * pObj; - // consider the case of simple gate - pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); - if ( pObj == NULL ) - return (1 << Kit_DsdLit2Var(iLit)); - if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) - { - unsigned uSupps[16], Limit, s; - uSupport = 0; - Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) - { - uSupps[i] = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax ); - uSupport |= uSupps[i]; - } - // create all subsets, except empty and full - Limit = (1 << pObj->nFans) - 1; - for ( s = 1; s < Limit; s++ ) - { - uSuppCur = 0; - for ( i = 0; i < pObj->nFans; i++ ) - if ( s & (1 << i) ) - uSuppCur |= uSupps[i]; - if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax ) - Vec_IntPush( vSets, uSuppCur ); - } - return uSupport; - } - assert( pObj->Type == KIT_DSD_PRIME ); - // get the cumulative support of all fanins - uSupport = 0; - Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) - { - uSuppCur = Lpk_ComputeBoundSets_rec( p, iLitFanin, vSets, nSizeMax ); - uSupport |= uSuppCur; - if ( Kit_WordCountOnes(uSuppCur) <= nSizeMax ) - Vec_IntPush( vSets, uSuppCur ); - } - return uSupport; -} - -/**Function************************************************************* - - Synopsis [Computes the set of subsets of decomposable variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Lpk_ComputeBoundSets( Kit_DsdNtk_t * p, int nSizeMax ) -{ - Vec_Int_t * vSets; - unsigned uSupport, Entry; - int Number, i; - assert( p->nVars <= 16 ); - vSets = Vec_IntAlloc( 100 ); - Vec_IntPush( vSets, 0 ); - if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) - return vSets; - if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) - { - uSupport = ( 1 << Kit_DsdLit2Var(Kit_DsdNtkRoot(p)->pFans[0]) ); - if ( Kit_WordCountOnes(uSupport) <= nSizeMax ) - Vec_IntPush( vSets, uSupport ); - return vSets; - } - uSupport = Lpk_ComputeBoundSets_rec( p, p->Root, vSets, nSizeMax ); - assert( (uSupport & 0xFFFF0000) == 0 ); - // add the total support of the network - if ( Kit_WordCountOnes(uSupport) <= nSizeMax ) - Vec_IntPush( vSets, uSupport ); - // set the remaining variables - Vec_IntForEachEntry( vSets, Number, i ) - { - Entry = Number; - Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) ); - } - return vSets; -} - -/**Function************************************************************* - - Synopsis [Prints the sets of subsets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Lpk_PrintSetOne( int uSupport ) -{ - unsigned k; - for ( k = 0; k < 16; k++ ) - if ( uSupport & (1<> 16)) ) - continue; - if ( Kit_WordCountOnes(Entry & 0xffff) <= nSizeMax ) - Vec_IntPush( vSets, Entry ); - } - return vSets; -} - -/**Function************************************************************* - - Synopsis [Performs DSD-based decomposition of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_FunCompareBoundSets( Lpk_Fun_t * p, Vec_Int_t * vBSets, int nCofDepth, unsigned uNonDecSupp, unsigned uLateArrSupp, Lpk_Res_t * pRes ) -{ - int fVerbose = 0; - unsigned uBoundSet; - int i, nVarsBS, nVarsRem, Delay, Area; - - // compare the resulting boundsets - memset( pRes, 0, sizeof(Lpk_Res_t) ); - Vec_IntForEachEntry( vBSets, uBoundSet, i ) - { - if ( (uBoundSet & 0xFFFF) == 0 ) // skip empty boundset - continue; - if ( (uBoundSet & uNonDecSupp) == 0 ) // skip those boundsets that are not in the domain of interest - continue; - if ( (uBoundSet & uLateArrSupp) ) // skip those boundsets that are late arriving - continue; -if ( fVerbose ) -Lpk_PrintSetOne( uBoundSet ); - assert( (uBoundSet & (uBoundSet >> 16)) == 0 ); - nVarsBS = Kit_WordCountOnes( uBoundSet & 0xFFFF ); - if ( nVarsBS == 1 ) - continue; - assert( nVarsBS <= (int)p->nLutK - nCofDepth ); - nVarsRem = p->nVars - nVarsBS + 1; - Area = 1 + Lpk_LutNumLuts( nVarsRem, p->nLutK ); - Delay = 1 + Lpk_SuppDelay( uBoundSet & 0xFFFF, p->pDelays ); -if ( fVerbose ) -printf( "area = %d limit = %d delay = %d limit = %d\n", Area, (int)p->nAreaLim, Delay, (int)p->nDelayLim ); - if ( Area > (int)p->nAreaLim || Delay > (int)p->nDelayLim ) - continue; - if ( pRes->BSVars == 0 || pRes->nSuppSizeL > nVarsRem || (pRes->nSuppSizeL == nVarsRem && pRes->DelayEst > Delay) ) - { - pRes->nBSVars = nVarsBS; - pRes->BSVars = (uBoundSet & 0xFFFF); - pRes->nSuppSizeS = nVarsBS + nCofDepth; - pRes->nSuppSizeL = nVarsRem; - pRes->DelayEst = Delay; - pRes->AreaEst = Area; - } - } -if ( fVerbose ) -{ -if ( pRes->BSVars ) -{ -printf( "Found bound set " ); -Lpk_PrintSetOne( pRes->BSVars ); -printf( "\n" ); -} -else -printf( "Did not find boundsets.\n" ); -printf( "\n" ); -} - if ( pRes->BSVars ) - { - assert( pRes->DelayEst <= (int)p->nDelayLim ); - assert( pRes->AreaEst <= (int)p->nAreaLim ); - } -} - - -/**Function************************************************************* - - Synopsis [Finds late arriving inputs, which cannot be in the bound set.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Lpk_DsdLateArriving( Lpk_Fun_t * p ) -{ - unsigned i, uLateArrSupp = 0; - Lpk_SuppForEachVar( p->uSupp, i ) - if ( p->pDelays[i] > (int)p->nDelayLim - 2 ) - uLateArrSupp |= (1 << i); - return uLateArrSupp; -} - -/**Function************************************************************* - - Synopsis [Performs DSD-based decomposition of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_DsdAnalizeOne( Lpk_Fun_t * p, unsigned * ppTruths[5][16], Kit_DsdNtk_t * pNtks[], char pCofVars[], int nCofDepth, Lpk_Res_t * pRes ) -{ - int fVerbose = 0; - Vec_Int_t * pvBSets[4][8]; - unsigned uNonDecSupp, uLateArrSupp; - int i, k, nNonDecSize, nNonDecSizeMax; - assert( nCofDepth >= 1 && nCofDepth <= 3 ); - assert( nCofDepth < (int)p->nLutK - 1 ); - assert( p->fSupports ); - - // find the support of the largest non-DSD block - nNonDecSizeMax = 0; - uNonDecSupp = p->uSupp; - for ( i = 0; i < (1<<(nCofDepth-1)); i++ ) - { - nNonDecSize = Kit_DsdNonDsdSizeMax( pNtks[i] ); - if ( nNonDecSizeMax < nNonDecSize ) - { - nNonDecSizeMax = nNonDecSize; - uNonDecSupp = Kit_DsdNonDsdSupports( pNtks[i] ); - } - else if ( nNonDecSizeMax == nNonDecSize ) - uNonDecSupp |= Kit_DsdNonDsdSupports( pNtks[i] ); - } - - // remove those variables that cannot be used because of delay constraints - // if variables arrival time is more than p->DelayLim - 2, it cannot be used - uLateArrSupp = Lpk_DsdLateArriving( p ); - if ( (uNonDecSupp & ~uLateArrSupp) == 0 ) - { - memset( pRes, 0, sizeof(Lpk_Res_t) ); - return 0; - } - - // find the next cofactoring variable - pCofVars[nCofDepth-1] = Lpk_FunComputeMinSuppSizeVar( p, ppTruths[nCofDepth-1], 1<<(nCofDepth-1), ppTruths[nCofDepth], uNonDecSupp & ~uLateArrSupp ); - - // derive decomposed networks - for ( i = 0; i < (1<nVars ); -if ( fVerbose ) -Kit_DsdPrint( stdout, pNtks[i] ); - pvBSets[nCofDepth][i] = Lpk_ComputeBoundSets( pNtks[i], p->nLutK - nCofDepth ); // try restricting to those in uNonDecSupp!!! - } - - // derive the set of feasible boundsets - for ( i = nCofDepth - 1; i >= 0; i-- ) - for ( k = 0; k < (1<nLutK - nCofDepth ); - // compare bound-sets - Lpk_FunCompareBoundSets( p, pvBSets[0][0], nCofDepth, uNonDecSupp, uLateArrSupp, pRes ); - // free the bound sets - for ( i = nCofDepth; i >= 0; i-- ) - for ( k = 0; k < (1<BSVars ) - { - pRes->nCofVars = nCofDepth; - for ( i = 0; i < nCofDepth; i++ ) - pRes->pCofVars[i] = pCofVars[i]; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs DSD-based decomposition of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Lpk_Res_t * Lpk_DsdAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p, int nShared ) -{ - static Lpk_Res_t Res0, * pRes0 = &Res0; - static Lpk_Res_t Res1, * pRes1 = &Res1; - static Lpk_Res_t Res2, * pRes2 = &Res2; - static Lpk_Res_t Res3, * pRes3 = &Res3; - int fUseBackLooking = 1; - Lpk_Res_t * pRes = NULL; - Vec_Int_t * vBSets; - Kit_DsdNtk_t * pNtks[8] = {NULL}; - char pCofVars[5]; - int i; - - assert( p->nLutK >= 3 ); - assert( nShared >= 0 && nShared <= 3 ); - assert( p->uSupp == Kit_BitMask(p->nVars) ); - - // try decomposition without cofactoring - pNtks[0] = Kit_DsdDecomposeExpand( Lpk_FunTruth( p, 0 ), p->nVars ); - if ( pMan->pPars->fVerbose ) - pMan->nBlocks[ Kit_DsdNonDsdSizeMax(pNtks[0]) ]++; - vBSets = Lpk_ComputeBoundSets( pNtks[0], p->nLutK ); - Lpk_FunCompareBoundSets( p, vBSets, 0, 0xFFFF, Lpk_DsdLateArriving(p), pRes0 ); - Vec_IntFree( vBSets ); - - // check the result - if ( pRes0->nBSVars == (int)p->nLutK ) - { pRes = pRes0; goto finish; } - if ( pRes0->nBSVars == (int)p->nLutK - 1 ) - { pRes = pRes0; goto finish; } - if ( nShared == 0 ) - goto finish; - - // prepare storage - Kit_TruthCopy( pMan->ppTruths[0][0], Lpk_FunTruth( p, 0 ), p->nVars ); - - // cofactor 1 time - if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 1, pRes1 ) ) - goto finish; - assert( pRes1->nBSVars <= (int)p->nLutK - 1 ); - if ( pRes1->nBSVars == (int)p->nLutK - 1 ) - { pRes = pRes1; goto finish; } - if ( pRes0->nBSVars == (int)p->nLutK - 2 ) - { pRes = pRes0; goto finish; } - if ( pRes1->nBSVars == (int)p->nLutK - 2 ) - { pRes = pRes1; goto finish; } - if ( nShared == 1 ) - goto finish; - - // cofactor 2 times - if ( p->nLutK >= 4 ) - { - if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 2, pRes2 ) ) - goto finish; - assert( pRes2->nBSVars <= (int)p->nLutK - 2 ); - if ( pRes2->nBSVars == (int)p->nLutK - 2 ) - { pRes = pRes2; goto finish; } - if ( fUseBackLooking ) - { - if ( pRes0->nBSVars == (int)p->nLutK - 3 ) - { pRes = pRes0; goto finish; } - if ( pRes1->nBSVars == (int)p->nLutK - 3 ) - { pRes = pRes1; goto finish; } - } - if ( pRes2->nBSVars == (int)p->nLutK - 3 ) - { pRes = pRes2; goto finish; } - if ( nShared == 2 ) - goto finish; - assert( nShared == 3 ); - } - - // cofactor 3 times - if ( p->nLutK >= 5 ) - { - if ( !Lpk_DsdAnalizeOne( p, pMan->ppTruths, pNtks, pCofVars, 3, pRes3 ) ) - goto finish; - assert( pRes3->nBSVars <= (int)p->nLutK - 3 ); - if ( pRes3->nBSVars == (int)p->nLutK - 3 ) - { pRes = pRes3; goto finish; } - if ( fUseBackLooking ) - { - if ( pRes0->nBSVars == (int)p->nLutK - 4 ) - { pRes = pRes0; goto finish; } - if ( pRes1->nBSVars == (int)p->nLutK - 4 ) - { pRes = pRes1; goto finish; } - if ( pRes2->nBSVars == (int)p->nLutK - 4 ) - { pRes = pRes2; goto finish; } - } - if ( pRes3->nBSVars == (int)p->nLutK - 4 ) - { pRes = pRes3; goto finish; } - } - -finish: - // free the networks - for ( i = 0; i < (1<ppTruths[0][0], Lpk_FunTruth(p, 0), p->nVars ); - // get the vacuous variable - iVacVar = Kit_WordFindFirstBit( uBoundSet ); - // compute the cofactors - for ( i = 0; i < nCofVars; i++ ) - for ( k = 0; k < (1<ppTruths[i+1][2*k+0], pMan->ppTruths[i][k], p->nVars, pCofVars[i] ); - Kit_TruthCofactor1New( pMan->ppTruths[i+1][2*k+1], pMan->ppTruths[i][k], p->nVars, pCofVars[i] ); - } - // decompose each cofactor w.r.t. the bound set - nCofs = (1<ppTruths[nCofVars][k], p->nVars ); - Kit_DsdTruthPartialTwo( pMan->pDsdMan, pNtkDec, uBoundSet, iVacVar, pMan->ppTruths[nCofVars+1][k], pMan->ppTruths[nCofVars+1][nCofs+k] ); - Kit_DsdNtkFree( pNtkDec ); - } - // compute the composition/decomposition functions (they will be in pMan->ppTruths[1][0]/pMan->ppTruths[1][1]) - for ( i = nCofVars; i >= 1; i-- ) - for ( k = 0; k < (1<ppTruths[i][k], pMan->ppTruths[i+1][2*k+0], pMan->ppTruths[i+1][2*k+1], p->nVars, pCofVars[i-1] ); - - // derive the new component (decomposition function) - pNew = Lpk_FunDup( p, pMan->ppTruths[1][1] ); - // update the old component (composition function) - Kit_TruthCopy( Lpk_FunTruth(p, 0), pMan->ppTruths[1][0], p->nVars ); - p->uSupp = Kit_TruthSupport( Lpk_FunTruth(p, 0), p->nVars ); - p->pFanins[iVacVar] = pNew->Id; - p->pDelays[iVacVar] = Lpk_SuppDelay( pNew->uSupp, pNew->pDelays ); - // support minimize both - p->fSupports = 0; - Lpk_FunSuppMinimize( p ); - Lpk_FunSuppMinimize( pNew ); - // update delay and area requirements - pNew->nDelayLim = p->pDelays[iVacVar]; - pNew->nAreaLim = 1; - p->nAreaLim = p->nAreaLim - 1; - return pNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/lpkAbcMux.c b/src/opt/lpk/lpkAbcMux.c deleted file mode 100644 index d6f579ee..00000000 --- a/src/opt/lpk/lpkAbcMux.c +++ /dev/null @@ -1,235 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpkAbcMux.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [LUT-decomposition based on recursive MUX decomposition.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpkAbcMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "lpkInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks the possibility of MUX decomposition.] - - Description [Returns the best variable to use for MUX decomposition.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Lpk_Res_t * Lpk_MuxAnalize( Lpk_Man_t * pMan, Lpk_Fun_t * p ) -{ - static Lpk_Res_t Res, * pRes = &Res; - int nSuppSize0, nSuppSize1, nSuppSizeS, nSuppSizeL; - int Var, Area, Polarity, Delay, Delay0, Delay1, DelayA, DelayB; - memset( pRes, 0, sizeof(Lpk_Res_t) ); - assert( p->uSupp == Kit_BitMask(p->nVars) ); - assert( p->fSupports ); - // derive the delay and area after MUX-decomp with each var - and find the best var - pRes->Variable = -1; - Lpk_SuppForEachVar( p->uSupp, Var ) - { - nSuppSize0 = Kit_WordCountOnes(p->puSupps[2*Var+0]); - nSuppSize1 = Kit_WordCountOnes(p->puSupps[2*Var+1]); - assert( nSuppSize0 < (int)p->nVars ); - assert( nSuppSize1 < (int)p->nVars ); - if ( nSuppSize0 < 1 || nSuppSize1 < 1 ) - continue; -//printf( "%d %d ", nSuppSize0, nSuppSize1 ); - if ( nSuppSize0 <= (int)p->nLutK - 2 && nSuppSize1 <= (int)p->nLutK - 2 ) - { - // include cof var into 0-block - DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); - DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); - Delay0 = ABC_MAX( DelayA, DelayB + 1 ); - // include cof var into 1-block - DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); - DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); - Delay1 = ABC_MAX( DelayA, DelayB + 1 ); - // get the best delay - Delay = ABC_MIN( Delay0, Delay1 ); - Area = 2; - Polarity = (int)(Delay == Delay1); - } - else if ( nSuppSize0 <= (int)p->nLutK - 2 ) - { - DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); - DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); - Delay = ABC_MAX( DelayA, DelayB + 1 ); - Area = 1 + Lpk_LutNumLuts( nSuppSize1, p->nLutK ); - Polarity = 0; - } - else if ( nSuppSize1 <= (int)p->nLutK - 2 ) - { - DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); - DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); - Delay = ABC_MAX( DelayA, DelayB + 1 ); - Area = 1 + Lpk_LutNumLuts( nSuppSize0, p->nLutK ); - Polarity = 1; - } - else if ( nSuppSize0 <= (int)p->nLutK ) - { - DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); - DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); - Delay = ABC_MAX( DelayA, DelayB + 1 ); - Area = 1 + Lpk_LutNumLuts( nSuppSize1+2, p->nLutK ); - Polarity = 1; - } - else if ( nSuppSize1 <= (int)p->nLutK ) - { - DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); - DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); - Delay = ABC_MAX( DelayA, DelayB + 1 ); - Area = 1 + Lpk_LutNumLuts( nSuppSize0+2, p->nLutK ); - Polarity = 0; - } - else - { - // include cof var into 0-block - DelayA = Lpk_SuppDelay( p->puSupps[2*Var+0] | (1<pDelays ); - DelayB = Lpk_SuppDelay( p->puSupps[2*Var+1] , p->pDelays ); - Delay0 = ABC_MAX( DelayA, DelayB + 1 ); - // include cof var into 1-block - DelayA = Lpk_SuppDelay( p->puSupps[2*Var+1] | (1<pDelays ); - DelayB = Lpk_SuppDelay( p->puSupps[2*Var+0] , p->pDelays ); - Delay1 = ABC_MAX( DelayA, DelayB + 1 ); - // get the best delay - Delay = ABC_MIN( Delay0, Delay1 ); - if ( Delay == Delay0 ) - Area = Lpk_LutNumLuts( nSuppSize0+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize1, p->nLutK ); - else - Area = Lpk_LutNumLuts( nSuppSize1+2, p->nLutK ) + Lpk_LutNumLuts( nSuppSize0, p->nLutK ); - Polarity = (int)(Delay == Delay1); - } - // find the best variable - if ( Delay > (int)p->nDelayLim ) - continue; - if ( Area > (int)p->nAreaLim ) - continue; - nSuppSizeS = ABC_MIN( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity ); - nSuppSizeL = ABC_MAX( nSuppSize0 + 2 *!Polarity, nSuppSize1 + 2 * Polarity ); - if ( nSuppSizeL > (int)p->nVars ) - continue; - if ( pRes->Variable == -1 || pRes->AreaEst > Area || - (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL > nSuppSizeS + nSuppSizeL) || - (pRes->AreaEst == Area && pRes->nSuppSizeS + pRes->nSuppSizeL == nSuppSizeS + nSuppSizeL && pRes->DelayEst > Delay) ) - { - pRes->Variable = Var; - pRes->Polarity = Polarity; - pRes->AreaEst = Area; - pRes->DelayEst = Delay; - pRes->nSuppSizeS = nSuppSizeS; - pRes->nSuppSizeL = nSuppSizeL; - } - } - return pRes->Variable == -1 ? NULL : pRes; -} - -/**Function************************************************************* - - Synopsis [Transforms the function decomposed by the MUX decomposition.] - - Description [Returns the best variable to use for MUX decomposition.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Lpk_Fun_t * Lpk_MuxSplit( Lpk_Man_t * pMan, Lpk_Fun_t * p, int Var, int Pol ) -{ - Lpk_Fun_t * pNew; - unsigned * pTruth = Lpk_FunTruth( p, 0 ); - unsigned * pTruth0 = Lpk_FunTruth( p, 1 ); - unsigned * pTruth1 = Lpk_FunTruth( p, 2 ); -// unsigned uSupp; - int iVarVac; - assert( Var >= 0 && Var < (int)p->nVars ); - assert( p->nAreaLim >= 2 ); - assert( p->uSupp == Kit_BitMask(p->nVars) ); - Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var ); - Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var ); -/* -uSupp = Kit_TruthSupport( pTruth, p->nVars ); -Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" ); -uSupp = Kit_TruthSupport( pTruth0, p->nVars ); -Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n" ); -uSupp = Kit_TruthSupport( pTruth1, p->nVars ); -Extra_PrintBinary( stdout, &uSupp, 16 ); printf( "\n\n" ); -*/ - // derive the new component - pNew = Lpk_FunDup( p, Pol ? pTruth0 : pTruth1 ); - // update the support of the old component - p->uSupp = Kit_TruthSupport( Pol ? pTruth1 : pTruth0, p->nVars ); - p->uSupp |= (1 << Var); - // update the truth table of the old component - iVarVac = Kit_WordFindFirstBit( ~p->uSupp ); - assert( iVarVac < (int)p->nVars ); - p->uSupp |= (1 << iVarVac); - Kit_TruthIthVar( pTruth, p->nVars, iVarVac ); - if ( Pol ) - Kit_TruthMuxVar( pTruth, pTruth, pTruth1, p->nVars, Var ); - else - Kit_TruthMuxVar( pTruth, pTruth0, pTruth, p->nVars, Var ); - assert( p->uSupp == Kit_TruthSupport(pTruth, p->nVars) ); - // set the decomposed variable - p->pFanins[iVarVac] = pNew->Id; - p->pDelays[iVarVac] = p->nDelayLim - 1; - // support minimize both - p->fSupports = 0; - Lpk_FunSuppMinimize( p ); - Lpk_FunSuppMinimize( pNew ); - // update delay and area requirements - pNew->nDelayLim = p->nDelayLim - 1; - if ( pNew->nVars <= pNew->nLutK ) - { - pNew->nAreaLim = 1; - p->nAreaLim = p->nAreaLim - 1; - } - else if ( p->nVars <= p->nLutK ) - { - pNew->nAreaLim = p->nAreaLim - 1; - p->nAreaLim = 1; - } - else if ( p->nVars < pNew->nVars ) - { - pNew->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2; - p->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2; - } - else // if ( pNew->nVars < p->nVars ) - { - pNew->nAreaLim = p->nAreaLim / 2 - p->nAreaLim % 2; - p->nAreaLim = p->nAreaLim / 2 + p->nAreaLim % 2; - } - pNew->fMark = 1; - return pNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/lpkAbcUtil.c b/src/opt/lpk/lpkAbcUtil.c deleted file mode 100644 index 3f917ce2..00000000 --- a/src/opt/lpk/lpkAbcUtil.c +++ /dev/null @@ -1,244 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpkAbcUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [Procedures working on decomposed functions.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpkAbcUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "lpkInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Lpk_Fun_t * Lpk_FunAlloc( int nVars ) -{ - Lpk_Fun_t * p; - p = (Lpk_Fun_t *)malloc( sizeof(Lpk_Fun_t) + sizeof(unsigned) * Kit_TruthWordNum(nVars) * 3 ); - memset( p, 0, sizeof(Lpk_Fun_t) ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deletes the function] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_FunFree( Lpk_Fun_t * p ) -{ - free( p ); -} - -/**Function************************************************************* - - Synopsis [Creates the starting function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Lpk_Fun_t * Lpk_FunCreate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vLeaves, unsigned * pTruth, int nLutK, int AreaLim, int DelayLim ) -{ - Lpk_Fun_t * p; - Abc_Obj_t * pNode; - int i; - p = Lpk_FunAlloc( Vec_PtrSize(vLeaves) ); - p->Id = Vec_PtrSize(vLeaves); - p->vNodes = vLeaves; - p->nVars = Vec_PtrSize(vLeaves); - p->nLutK = nLutK; - p->nAreaLim = AreaLim; - p->nDelayLim = DelayLim; - p->uSupp = Kit_TruthSupport( pTruth, p->nVars ); - Kit_TruthCopy( Lpk_FunTruth(p,0), pTruth, p->nVars ); - Vec_PtrForEachEntry( vLeaves, pNode, i ) - { - p->pFanins[i] = i; - p->pDelays[i] = pNode->Level; - } - Vec_PtrPush( p->vNodes, p ); - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the new function with the given truth table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Lpk_Fun_t * Lpk_FunDup( Lpk_Fun_t * p, unsigned * pTruth ) -{ - Lpk_Fun_t * pNew; - pNew = Lpk_FunAlloc( p->nVars ); - pNew->Id = Vec_PtrSize(p->vNodes); - pNew->vNodes = p->vNodes; - pNew->nVars = p->nVars; - pNew->nLutK = p->nLutK; - pNew->nAreaLim = p->nAreaLim; - pNew->nDelayLim = p->nDelayLim; - pNew->uSupp = Kit_TruthSupport( pTruth, p->nVars ); - Kit_TruthCopy( Lpk_FunTruth(pNew,0), pTruth, p->nVars ); - memcpy( pNew->pFanins, p->pFanins, 16 ); - memcpy( pNew->pDelays, p->pDelays, 16 ); - Vec_PtrPush( p->vNodes, pNew ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Minimizes support of the function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_FunSuppMinimize( Lpk_Fun_t * p ) -{ - int i, k, nVarsNew; - // compress the truth table - if ( p->uSupp == Kit_BitMask(p->nVars) ) - return 0; - // invalidate support info - p->fSupports = 0; -//Extra_PrintBinary( stdout, &p->uSupp, p->nVars ); printf( "\n" ); - // minimize support - nVarsNew = Kit_WordCountOnes(p->uSupp); - Kit_TruthShrink( Lpk_FunTruth(p, 1), Lpk_FunTruth(p, 0), nVarsNew, p->nVars, p->uSupp, 1 ); - k = 0; - Lpk_SuppForEachVar( p->uSupp, i ) - { - p->pFanins[k] = p->pFanins[i]; - p->pDelays[k] = p->pDelays[i]; -/* - if ( p->fSupports ) - { - p->puSupps[2*k+0] = p->puSupps[2*i+0]; - p->puSupps[2*k+1] = p->puSupps[2*i+1]; - } -*/ - k++; - } - assert( k == nVarsNew ); - p->nVars = k; - p->uSupp = Kit_BitMask(p->nVars); - return 1; -} - -/**Function************************************************************* - - Synopsis [Computes cofactors w.r.t. each variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_FunComputeCofSupps( Lpk_Fun_t * p ) -{ - unsigned * pTruth = Lpk_FunTruth( p, 0 ); - unsigned * pTruth0 = Lpk_FunTruth( p, 1 ); - unsigned * pTruth1 = Lpk_FunTruth( p, 2 ); - int Var; - assert( p->fSupports == 0 ); -// Lpk_SuppForEachVar( p->uSupp, Var ) - for ( Var = 0; Var < (int)p->nVars; Var++ ) - { - Kit_TruthCofactor0New( pTruth0, pTruth, p->nVars, Var ); - Kit_TruthCofactor1New( pTruth1, pTruth, p->nVars, Var ); - p->puSupps[2*Var+0] = Kit_TruthSupport( pTruth0, p->nVars ); - p->puSupps[2*Var+1] = Kit_TruthSupport( pTruth1, p->nVars ); - } - p->fSupports = 1; -} - -/**Function************************************************************* - - Synopsis [Get the delay of the bound set.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_SuppDelay( unsigned uSupp, char * pDelays ) -{ - int Delay, Var; - Delay = 0; - Lpk_SuppForEachVar( uSupp, Var ) - Delay = ABC_MAX( Delay, pDelays[Var] ); - return Delay + 1; -} - -/**Function************************************************************* - - Synopsis [Converts support into variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_SuppToVars( unsigned uBoundSet, char * pVars ) -{ - int i, nVars = 0; - Lpk_SuppForEachVar( uBoundSet, i ) - pVars[nVars++] = i; - return nVars; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/lpkCore.c b/src/opt/lpk/lpkCore.c deleted file mode 100644 index 8b8028e3..00000000 --- a/src/opt/lpk/lpkCore.c +++ /dev/null @@ -1,659 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpkCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpkCore.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "lpkInt.h" -#include "cloud.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Prepares the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_IfManStart( Lpk_Man_t * p ) -{ - If_Par_t * pPars; - assert( p->pIfMan == NULL ); - // set defaults - pPars = ALLOC( If_Par_t, 1 ); - memset( pPars, 0, sizeof(If_Par_t) ); - // user-controlable paramters - pPars->nLutSize = p->pPars->nLutSize; - pPars->nCutsMax = 16; - pPars->nFlowIters = 0; // 1 - pPars->nAreaIters = 0; // 1 - pPars->DelayTarget = -1; - pPars->fPreprocess = 0; - pPars->fArea = 1; - pPars->fFancy = 0; - pPars->fExpRed = 0; // - pPars->fLatchPaths = 0; - pPars->fSeqMap = 0; - pPars->fVerbose = 0; - // internal parameters - pPars->fTruth = 1; - pPars->fUsePerm = 0; - pPars->nLatches = 0; - pPars->pLutLib = NULL; // Abc_FrameReadLibLut(); - pPars->pTimesArr = NULL; - pPars->pTimesArr = NULL; - pPars->fUseBdds = 0; - pPars->fUseSops = 0; - pPars->fUseCnfs = 0; - pPars->fUseMv = 0; - // start the mapping manager and set its parameters - p->pIfMan = If_ManStart( pPars ); - If_ManSetupSetAll( p->pIfMan, 1000 ); - p->pIfMan->pPars->pTimesArr = ALLOC( float, 32 ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if at least one entry has changed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_NodeHasChanged( Lpk_Man_t * p, int iNode ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pTemp; - int i; - vNodes = Vec_VecEntry( p->vVisited, iNode ); - if ( Vec_PtrSize(vNodes) == 0 ) - return 1; - Vec_PtrForEachEntry( vNodes, pTemp, i ) - { - // check if the node has changed - pTemp = Abc_NtkObj( p->pNtk, (int)pTemp ); - if ( pTemp == NULL ) - return 1; - // check if the number of fanouts has changed -// if ( Abc_ObjFanoutNum(pTemp) != (int)Vec_PtrEntry(vNodes, i+1) ) -// return 1; - i++; - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Prepares the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_ExploreCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, Kit_DsdNtk_t * pNtk ) -{ - extern Abc_Obj_t * Abc_NodeFromIf_rec( Abc_Ntk_t * pNtkNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vCover ); - Kit_DsdObj_t * pRoot; - If_Obj_t * pDriver, * ppLeaves[16]; - Abc_Obj_t * pLeaf, * pObjNew; - int nGain, i, clk; - int nNodesBef; -// int nOldShared; - - // check special cases - pRoot = Kit_DsdNtkRoot( pNtk ); - if ( pRoot->Type == KIT_DSD_CONST1 ) - { - if ( Kit_DsdLitIsCompl(pNtk->Root) ) - pObjNew = Abc_NtkCreateNodeConst0( p->pNtk ); - else - pObjNew = Abc_NtkCreateNodeConst1( p->pNtk ); - Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); - p->nGainTotal += pCut->nNodes - pCut->nNodesDup; - return 1; - } - if ( pRoot->Type == KIT_DSD_VAR ) - { - pObjNew = Abc_NtkObj( p->pNtk, pCut->pLeaves[ Kit_DsdLit2Var(pRoot->pFans[0]) ] ); - if ( Kit_DsdLitIsCompl(pNtk->Root) ^ Kit_DsdLitIsCompl(pRoot->pFans[0]) ) - pObjNew = Abc_NtkCreateNodeInv( p->pNtk, pObjNew ); - Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); - p->nGainTotal += pCut->nNodes - pCut->nNodesDup; - return 1; - } - assert( pRoot->Type == KIT_DSD_AND || pRoot->Type == KIT_DSD_XOR || pRoot->Type == KIT_DSD_PRIME ); - - // start the mapping manager - if ( p->pIfMan == NULL ) - Lpk_IfManStart( p ); - - // prepare the mapping manager - If_ManRestart( p->pIfMan ); - // create the PI variables - for ( i = 0; i < p->pPars->nVarsMax; i++ ) - ppLeaves[i] = If_ManCreateCi( p->pIfMan ); - // set the arrival times - Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i ) - p->pIfMan->pPars->pTimesArr[i] = (float)pLeaf->Level; - // prepare the PI cuts - If_ManSetupCiCutSets( p->pIfMan ); - // create the internal nodes - p->fCalledOnce = 0; - p->nCalledSRed = 0; - pDriver = Lpk_MapTree_rec( p, pNtk, ppLeaves, pNtk->Root, NULL ); - if ( pDriver == NULL ) - return 0; - // create the PO node - If_ManCreateCo( p->pIfMan, If_Regular(pDriver) ); - - // perform mapping - p->pIfMan->pPars->fAreaOnly = 1; -clk = clock(); - If_ManPerformMappingComb( p->pIfMan ); -p->timeMap += clock() - clk; - - // compute the gain in area - nGain = pCut->nNodes - pCut->nNodesDup - (int)p->pIfMan->AreaGlo; - if ( p->pPars->fVeryVerbose ) - printf( " Mffc = %2d. Mapped = %2d. Gain = %3d. Depth increase = %d. SReds = %d.\n", - pCut->nNodes - pCut->nNodesDup, (int)p->pIfMan->AreaGlo, nGain, (int)p->pIfMan->RequiredGlo - (int)p->pObj->Level, p->nCalledSRed ); - - // quit if there is no gain - if ( !(nGain > 0 || (p->pPars->fZeroCost && nGain == 0)) ) - return 0; - - // quit if depth increases too much - if ( (int)p->pIfMan->RequiredGlo > Abc_ObjRequiredLevel(p->pObj) ) - return 0; - - // perform replacement - p->nGainTotal += nGain; - p->nChanges++; - if ( p->nCalledSRed ) - p->nBenefited++; - - nNodesBef = Abc_NtkNodeNum(p->pNtk); - // prepare the mapping manager - If_ManCleanNodeCopy( p->pIfMan ); - If_ManCleanCutData( p->pIfMan ); - // set the PIs of the cut - Lpk_CutForEachLeaf( p->pNtk, pCut, pLeaf, i ) - If_ObjSetCopy( If_ManCi(p->pIfMan, i), pLeaf ); - // get the area of mapping - pObjNew = Abc_NodeFromIf_rec( p->pNtk, p->pIfMan, If_Regular(pDriver), p->vCover ); - pObjNew->pData = Hop_NotCond( pObjNew->pData, If_IsComplement(pDriver) ); - // perform replacement - Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); -//printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs resynthesis for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_ResynthesizeNode( Lpk_Man_t * p ) -{ - static int Count = 0; - Kit_DsdNtk_t * pDsdNtk; - Lpk_Cut_t * pCut; - unsigned * pTruth; - int i, k, nSuppSize, nCutNodes, RetValue, clk; - - // compute the cuts -clk = clock(); - if ( !Lpk_NodeCuts( p ) ) - { -p->timeCuts += clock() - clk; - return 0; - } -p->timeCuts += clock() - clk; - -//return 0; - - if ( p->pPars->fVeryVerbose ) - printf( "Node %5d : Mffc size = %5d. Cuts = %5d.\n", p->pObj->Id, p->nMffc, p->nEvals ); - // try the good cuts - p->nCutsTotal += p->nCuts; - p->nCutsUseful += p->nEvals; - for ( i = 0; i < p->nEvals; i++ ) - { - // get the cut - pCut = p->pCuts + p->pEvals[i]; - if ( p->pPars->fFirst && i == 1 ) - break; - - // skip bad cuts -// printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) ); - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++; - nCutNodes = Abc_NodeMffcLabel(p->pObj); -// printf( "Mffc with cut = %d. ", nCutNodes ); - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--; -// printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup ); -// printf( "\n" ); - if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup ) - continue; - - // compute the truth table -clk = clock(); - pTruth = Lpk_CutTruth( p, pCut, 0 ); - nSuppSize = Extra_TruthSupportSize(pTruth, pCut->nLeaves); -p->timeTruth += clock() - clk; - - pDsdNtk = Kit_DsdDecompose( pTruth, pCut->nLeaves ); -// Kit_DsdVerify( pDsdNtk, pTruth, pCut->nLeaves ); - // skip 16-input non-DSD because ISOP will not work - if ( Kit_DsdNtkRoot(pDsdNtk)->nFans == 16 ) - { - Kit_DsdNtkFree( pDsdNtk ); - continue; - } - - // if DSD has nodes that require splitting to fit them into LUTs - // we can skip those cuts that cannot lead to improvement - // (a full DSD network requires V = Nmin * (K-1) + 1 for improvement) - if ( Kit_DsdNonDsdSizeMax(pDsdNtk) > p->pPars->nLutSize && - nSuppSize >= ((int)pCut->nNodes - (int)pCut->nNodesDup - 1) * (p->pPars->nLutSize - 1) + 1 ) - { - Kit_DsdNtkFree( pDsdNtk ); - continue; - } - - if ( p->pPars->fVeryVerbose ) - { -// char * pFileName; - printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ", - i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight ); - Kit_DsdPrint( stdout, pDsdNtk ); - Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); -// pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ ); -// printf( "Saved truth table in file \"%s\".\n", pFileName ); - } - - // update the network -clk = clock(); - RetValue = Lpk_ExploreCut( p, pCut, pDsdNtk ); -p->timeEval += clock() - clk; - Kit_DsdNtkFree( pDsdNtk ); - if ( RetValue ) - break; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Computes supports of the cofactors of the function.] - - Description [This procedure should be called after Lpk_CutTruth(p,pCut,0)] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_ComputeSupports( Lpk_Man_t * p, Lpk_Cut_t * pCut, unsigned * pTruth ) -{ - unsigned * pTruthInv; - int RetValue1, RetValue2; - pTruthInv = Lpk_CutTruth( p, pCut, 1 ); - RetValue1 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruth, pCut->nLeaves, p->vBddDir ); - RetValue2 = Kit_CreateCloudFromTruth( p->pDsdMan->dd, pTruthInv, pCut->nLeaves, p->vBddInv ); - if ( RetValue1 && RetValue2 ) - Kit_TruthCofSupports( p->vBddDir, p->vBddInv, pCut->nLeaves, p->vMemory, p->puSupps ); - else - p->puSupps[0] = p->puSupps[1] = 0; -} - - -/**Function************************************************************* - - Synopsis [Performs resynthesis for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_ResynthesizeNodeNew( Lpk_Man_t * p ) -{ - static int Count = 0; - Abc_Obj_t * pObjNew, * pLeaf; - Lpk_Cut_t * pCut; - unsigned * pTruth; - int nNodesBef, nNodesAft, nCutNodes; - int i, k, clk; - int Required = Abc_ObjRequiredLevel(p->pObj); -// CloudNode * pFun2;//, * pFun1; - - // compute the cuts -clk = clock(); - if ( !Lpk_NodeCuts( p ) ) - { -p->timeCuts += clock() - clk; - return 0; - } -p->timeCuts += clock() - clk; - - if ( p->pPars->fVeryVerbose ) - printf( "Node %5d : Mffc size = %5d. Cuts = %5d. Level = %2d. Req = %2d.\n", - p->pObj->Id, p->nMffc, p->nEvals, p->pObj->Level, Required ); - // try the good cuts - p->nCutsTotal += p->nCuts; - p->nCutsUseful += p->nEvals; - for ( i = 0; i < p->nEvals; i++ ) - { - // get the cut - pCut = p->pCuts + p->pEvals[i]; - if ( p->pPars->fFirst && i == 1 ) - break; -// if ( pCut->Weight < 1.05 ) -// continue; - - // skip bad cuts -// printf( "Mffc size = %d. ", Abc_NodeMffcLabel(p->pObj) ); - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize++; - nCutNodes = Abc_NodeMffcLabel(p->pObj); -// printf( "Mffc with cut = %d. ", nCutNodes ); - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - Abc_NtkObj(p->pNtk, pCut->pLeaves[k])->vFanouts.nSize--; -// printf( "Mffc cut = %d. ", (int)pCut->nNodes - (int)pCut->nNodesDup ); -// printf( "\n" ); - if ( nCutNodes != (int)pCut->nNodes - (int)pCut->nNodesDup ) - continue; - - // collect nodes into the array - Vec_PtrClear( p->vLeaves ); - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - Vec_PtrPush( p->vLeaves, Abc_NtkObj(p->pNtk, pCut->pLeaves[k]) ); - - // compute the truth table -clk = clock(); - pTruth = Lpk_CutTruth( p, pCut, 0 ); -p->timeTruth += clock() - clk; -clk = clock(); - Lpk_ComputeSupports( p, pCut, pTruth ); -p->timeSupps += clock() - clk; -//clk = clock(); -// pFun1 = Lpk_CutTruthBdd( p, pCut ); -//p->timeTruth2 += clock() - clk; -/* -clk = clock(); - Cloud_Restart( p->pDsdMan->dd ); - pFun2 = Kit_TruthToCloud( p->pDsdMan->dd, pTruth, pCut->nLeaves ); - RetValue = Kit_CreateCloud( p->pDsdMan->dd, pFun2, p->vBddNodes ); -p->timeTruth3 += clock() - clk; -*/ -// if ( pFun1 != pFun2 ) -// printf( "Truth tables do not agree!\n" ); -// else -// printf( "Fine!\n" ); - - if ( p->pPars->fVeryVerbose ) - { -// char * pFileName; - int nSuppSize = Extra_TruthSupportSize( pTruth, pCut->nLeaves ); - printf( " C%02d: L= %2d/%2d V= %2d/%d N= %d W= %4.2f ", - i, pCut->nLeaves, nSuppSize, pCut->nNodes, pCut->nNodesDup, pCut->nLuts, pCut->Weight ); - Vec_PtrForEachEntry( p->vLeaves, pLeaf, k ) - printf( "%c=%d ", 'a'+k, Abc_ObjLevel(pLeaf) ); - printf( "\n" ); - Kit_DsdPrintFromTruth( pTruth, pCut->nLeaves ); -// pFileName = Kit_TruthDumpToFile( pTruth, pCut->nLeaves, Count++ ); -// printf( "Saved truth table in file \"%s\".\n", pFileName ); - } - if ( p->pObj->Id == 33 && i == 0 ) - { - int x = 0; - } - - // update the network - nNodesBef = Abc_NtkNodeNum(p->pNtk); -clk = clock(); - pObjNew = Lpk_Decompose( p, p->pNtk, p->vLeaves, pTruth, p->puSupps, p->pPars->nLutSize, - (int)pCut->nNodes - (int)pCut->nNodesDup - 1 + (int)(p->pPars->fZeroCost > 0), Required ); -p->timeEval += clock() - clk; - nNodesAft = Abc_NtkNodeNum(p->pNtk); - - // perform replacement - if ( pObjNew ) - { - int nGain = (int)pCut->nNodes - (int)pCut->nNodesDup - (nNodesAft - nNodesBef); - assert( nGain >= 1 - p->pPars->fZeroCost ); - assert( Abc_ObjLevel(pObjNew) <= Required ); -/* - if ( nGain <= 0 ) - { - int x = 0; - } - if ( Abc_ObjLevel(pObjNew) > Required ) - { - int x = 0; - } -*/ - p->nGainTotal += nGain; - p->nChanges++; - if ( p->pPars->fVeryVerbose ) - printf( "Performed resynthesis: Gain = %2d. Level = %2d. Req = %2d.\n", nGain, Abc_ObjLevel(pObjNew), Required ); - Abc_NtkUpdate( p->pObj, pObjNew, p->vLevels ); -//printf( "%3d : %d-%d=%d(%d) \n", p->nChanges, nNodesBef, Abc_NtkNodeNum(p->pNtk), nNodesBef-Abc_NtkNodeNum(p->pNtk), nGain ); - break; - } - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs resynthesis for one network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_Resynthesize( Abc_Ntk_t * pNtk, Lpk_Par_t * pPars ) -{ - ProgressBar * pProgress; - Lpk_Man_t * p; - Abc_Obj_t * pObj; - double Delta; - int i, Iter, nNodes, nNodesPrev, clk = clock(); - assert( Abc_NtkIsLogic(pNtk) ); - - // sweep dangling nodes as a preprocessing step - Abc_NtkSweep( pNtk, 0 ); - - // get the number of inputs - pPars->nLutSize = Abc_NtkGetFaninMax( pNtk ); - // adjust the number of crossbars based on LUT size - if ( pPars->nVarsShared > pPars->nLutSize - 2 ) - pPars->nVarsShared = pPars->nLutSize - 2; - // get the max number of LUTs tried - pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1; // V = N * (K-1) + 1 - while ( pPars->nVarsMax > 16 ) - { - pPars->nLutsMax--; - pPars->nVarsMax = pPars->nLutsMax * (pPars->nLutSize - 1) + 1; - - } - if ( pPars->fVerbose ) - { - printf( "Resynthesis for %d %d-LUTs with %d non-MFFC LUTs, %d crossbars, and %d-input cuts.\n", - pPars->nLutsMax, pPars->nLutSize, pPars->nLutsOver, pPars->nVarsShared, pPars->nVarsMax ); - } - - - // convert into the AIG - if ( !Abc_NtkToAig(pNtk) ) - { - fprintf( stdout, "Converting to BDD has failed.\n" ); - return 0; - } - assert( Abc_NtkHasAig(pNtk) ); - - // set the number of levels - Abc_NtkLevel( pNtk ); - Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); - - // start the manager - p = Lpk_ManStart( pPars ); - p->pNtk = pNtk; - p->nNodesTotal = Abc_NtkNodeNum(pNtk); - p->vLevels = Vec_VecStart( pNtk->LevelMax ); - if ( p->pPars->fSatur ) - p->vVisited = Vec_VecStart( 0 ); - if ( pPars->fVerbose ) - { - p->nTotalNets = Abc_NtkGetTotalFanins(pNtk); - p->nTotalNodes = Abc_NtkNodeNum(pNtk); - } - - // iterate over the network - nNodesPrev = p->nNodesTotal; - for ( Iter = 1; ; Iter++ ) - { - // expand storage for changed nodes - if ( p->pPars->fSatur ) - Vec_VecExpand( p->vVisited, Abc_NtkObjNumMax(pNtk) + 1 ); - - // consider all nodes - nNodes = Abc_NtkObjNumMax(pNtk); - if ( !pPars->fVeryVerbose ) - pProgress = Extra_ProgressBarStart( stdout, nNodes ); - Abc_NtkForEachNode( pNtk, pObj, i ) - { - // skip all except the final node - if ( pPars->fFirst ) - { - if ( !Abc_ObjIsCo(Abc_ObjFanout0(pObj)) ) - continue; - } - if ( i >= nNodes ) - break; - if ( !pPars->fVeryVerbose ) - Extra_ProgressBarUpdate( pProgress, i, NULL ); - // skip the nodes that did not change - if ( p->pPars->fSatur && !Lpk_NodeHasChanged(p, pObj->Id) ) - continue; - // resynthesize - p->pObj = pObj; - if ( p->pPars->fOldAlgo ) - Lpk_ResynthesizeNode( p ); - else - Lpk_ResynthesizeNodeNew( p ); - } - if ( !pPars->fVeryVerbose ) - Extra_ProgressBarStop( pProgress ); - - // check the increase - Delta = 100.00 * (nNodesPrev - Abc_NtkNodeNum(pNtk)) / p->nNodesTotal; - if ( Delta < 0.05 ) - break; - nNodesPrev = Abc_NtkNodeNum(pNtk); - if ( !p->pPars->fSatur ) - break; - - if ( pPars->fFirst ) - break; - } - Abc_NtkStopReverseLevels( pNtk ); - - if ( pPars->fVerbose ) - { -// Cloud_PrintInfo( p->pDsdMan->dd ); - p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk); - p->nTotalNodes2 = Abc_NtkNodeNum(pNtk); - printf( "Node gain = %5d. (%.2f %%) ", - p->nTotalNodes-p->nTotalNodes2, 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes ); - printf( "Edge gain = %5d. (%.2f %%) ", - p->nTotalNets-p->nTotalNets2, 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets ); - printf( "Muxes = %4d. Dsds = %4d.", p->nMuxes, p->nDsds ); - printf( "\n" ); - printf( "Nodes = %5d (%3d) Cuts = %5d (%4d) Changes = %5d Iter = %2d Benefit = %d.\n", - p->nNodesTotal, p->nNodesOver, p->nCutsTotal, p->nCutsUseful, p->nChanges, Iter, p->nBenefited ); - - printf( "Non-DSD:" ); - for ( i = 3; i <= pPars->nVarsMax; i++ ) - if ( p->nBlocks[i] ) - printf( " %d=%d", i, p->nBlocks[i] ); - printf( "\n" ); - - p->timeTotal = clock() - clk; - p->timeEval = p->timeEval - p->timeMap; - p->timeOther = p->timeTotal - p->timeCuts - p->timeTruth - p->timeEval - p->timeMap; - PRTP( "Cuts ", p->timeCuts, p->timeTotal ); - PRTP( "Truth ", p->timeTruth, p->timeTotal ); - PRTP( "CSupps", p->timeSupps, p->timeTotal ); - PRTP( "Eval ", p->timeEval, p->timeTotal ); - PRTP( " MuxAn", p->timeEvalMuxAn, p->timeEval ); - PRTP( " MuxSp", p->timeEvalMuxSp, p->timeEval ); - PRTP( " DsdAn", p->timeEvalDsdAn, p->timeEval ); - PRTP( " DsdSp", p->timeEvalDsdSp, p->timeEval ); - PRTP( " Other", p->timeEval-p->timeEvalMuxAn-p->timeEvalMuxSp-p->timeEvalDsdAn-p->timeEvalDsdSp, p->timeEval ); - PRTP( "Map ", p->timeMap, p->timeTotal ); - PRTP( "Other ", p->timeOther, p->timeTotal ); - PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); - } - - Lpk_ManStop( p ); - // check the resulting network - if ( !Abc_NtkCheck( pNtk ) ) - { - printf( "Lpk_Resynthesize: The network check has failed.\n" ); - return 0; - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/lpkCut.c b/src/opt/lpk/lpkCut.c deleted file mode 100644 index b2a743bd..00000000 --- a/src/opt/lpk/lpkCut.c +++ /dev/null @@ -1,683 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpkCut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpkCut.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "lpkInt.h" -#include "cloud.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the truth table of one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -CloudNode * Lpk_CutTruthBdd_rec( CloudManager * dd, Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars ) -{ - CloudNode * pTruth, * pTruth0, * pTruth1; - assert( !Hop_IsComplement(pObj) ); - if ( pObj->pData ) - { - assert( ((unsigned)pObj->pData) & 0xffff0000 ); - return pObj->pData; - } - // get the plan for a new truth table - if ( Hop_ObjIsConst1(pObj) ) - pTruth = dd->one; - else - { - assert( Hop_ObjIsAnd(pObj) ); - // compute the truth tables of the fanins - pTruth0 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin0(pObj), nVars ); - pTruth1 = Lpk_CutTruthBdd_rec( dd, pMan, Hop_ObjFanin1(pObj), nVars ); - pTruth0 = Cloud_NotCond( pTruth0, Hop_ObjFaninC0(pObj) ); - pTruth1 = Cloud_NotCond( pTruth1, Hop_ObjFaninC1(pObj) ); - // creat the truth table of the node - pTruth = Cloud_bddAnd( dd, pTruth0, pTruth1 ); - } - pObj->pData = pTruth; - return pTruth; -} - -/**Function************************************************************* - - Synopsis [Verifies that the factoring is correct.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -CloudNode * Lpk_CutTruthBdd( Lpk_Man_t * p, Lpk_Cut_t * pCut ) -{ - CloudManager * dd = p->pDsdMan->dd; - Hop_Man_t * pManHop = p->pNtk->pManFunc; - Hop_Obj_t * pObjHop; - Abc_Obj_t * pObj, * pFanin; - CloudNode * pTruth; - int i, k, iCount = 0; - -// return NULL; -// Lpk_NodePrintCut( p, pCut ); - // initialize the leaves - Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) - pObj->pCopy = (Abc_Obj_t *)dd->vars[pCut->nLeaves-1-i]; - - // construct truth table in the topological order - Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i ) - { - // get the local AIG - pObjHop = Hop_Regular(pObj->pData); - // clean the data field of the nodes in the AIG subgraph - Hop_ObjCleanData_rec( pObjHop ); - // set the initial truth tables at the fanins - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - assert( ((unsigned)pFanin->pCopy) & 0xffff0000 ); - Hop_ManPi( pManHop, k )->pData = pFanin->pCopy; - } - // compute the truth table of internal nodes - pTruth = Lpk_CutTruthBdd_rec( dd, pManHop, pObjHop, pCut->nLeaves ); - if ( Hop_IsComplement(pObj->pData) ) - pTruth = Cloud_Not(pTruth); - // set the truth table at the node - pObj->pCopy = (Abc_Obj_t *)pTruth; - - } - -// Cloud_bddPrint( dd, pTruth ); -// printf( "Bdd size = %d. Total nodes = %d.\n", Cloud_DagSize( dd, pTruth ), dd->nNodesCur-dd->nVars-1 ); - return pTruth; -} - - -/**Function************************************************************* - - Synopsis [Computes the truth table of one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Lpk_CutTruth_rec( Hop_Man_t * pMan, Hop_Obj_t * pObj, int nVars, Vec_Ptr_t * vTtNodes, int * piCount ) -{ - unsigned * pTruth, * pTruth0, * pTruth1; - assert( !Hop_IsComplement(pObj) ); - if ( pObj->pData ) - { - assert( ((unsigned)pObj->pData) & 0xffff0000 ); - return pObj->pData; - } - // get the plan for a new truth table - pTruth = Vec_PtrEntry( vTtNodes, (*piCount)++ ); - if ( Hop_ObjIsConst1(pObj) ) - Kit_TruthFill( pTruth, nVars ); - else - { - assert( Hop_ObjIsAnd(pObj) ); - // compute the truth tables of the fanins - pTruth0 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin0(pObj), nVars, vTtNodes, piCount ); - pTruth1 = Lpk_CutTruth_rec( pMan, Hop_ObjFanin1(pObj), nVars, vTtNodes, piCount ); - // creat the truth table of the node - Kit_TruthAndPhase( pTruth, pTruth0, pTruth1, nVars, Hop_ObjFaninC0(pObj), Hop_ObjFaninC1(pObj) ); - } - pObj->pData = pTruth; - return pTruth; -} - -/**Function************************************************************* - - Synopsis [Computes the truth able of one cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Lpk_CutTruth( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fInv ) -{ - Hop_Man_t * pManHop = p->pNtk->pManFunc; - Hop_Obj_t * pObjHop; - Abc_Obj_t * pObj, * pFanin; - unsigned * pTruth; - int i, k, iCount = 0; -// Lpk_NodePrintCut( p, pCut ); - assert( pCut->nNodes > 0 ); - - // initialize the leaves - Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) - pObj->pCopy = Vec_PtrEntry( p->vTtElems, fInv? pCut->nLeaves-1-i : i ); - - // construct truth table in the topological order - Lpk_CutForEachNodeReverse( p->pNtk, pCut, pObj, i ) - { - // get the local AIG - pObjHop = Hop_Regular(pObj->pData); - // clean the data field of the nodes in the AIG subgraph - Hop_ObjCleanData_rec( pObjHop ); - // set the initial truth tables at the fanins - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - assert( ((unsigned)pFanin->pCopy) & 0xffff0000 ); - Hop_ManPi( pManHop, k )->pData = pFanin->pCopy; - } - // compute the truth table of internal nodes - pTruth = Lpk_CutTruth_rec( pManHop, pObjHop, pCut->nLeaves, p->vTtNodes, &iCount ); - if ( Hop_IsComplement(pObj->pData) ) - Kit_TruthNot( pTruth, pTruth, pCut->nLeaves ); - // set the truth table at the node - pObj->pCopy = (Abc_Obj_t *)pTruth; - } - - // make sure direct truth table is stored elsewhere (assuming the first call for direct truth!!!) - if ( fInv == 0 ) - { - pTruth = Vec_PtrEntry( p->vTtNodes, iCount++ ); - Kit_TruthCopy( pTruth, (unsigned *)pObj->pCopy, pCut->nLeaves ); - } - assert( iCount <= Vec_PtrSize(p->vTtNodes) ); - return pTruth; -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if at least one entry has changed.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_NodeRecordImpact( Lpk_Man_t * p ) -{ - Lpk_Cut_t * pCut; - Vec_Ptr_t * vNodes = Vec_VecEntry( p->vVisited, p->pObj->Id ); - Abc_Obj_t * pNode; - int i, k; - // collect the nodes that impact the given node - Vec_PtrClear( vNodes ); - for ( i = 0; i < p->nCuts; i++ ) - { - pCut = p->pCuts + i; - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - { - pNode = Abc_NtkObj( p->pNtk, pCut->pLeaves[k] ); - if ( pNode->fMarkC ) - continue; - pNode->fMarkC = 1; - Vec_PtrPush( vNodes, (void *)pNode->Id ); - Vec_PtrPush( vNodes, (void *)Abc_ObjFanoutNum(pNode) ); - } - } - // clear the marks - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - pNode = Abc_NtkObj( p->pNtk, (int)pNode ); - pNode->fMarkC = 0; - i++; - } -//printf( "%d ", Vec_PtrSize(vNodes) ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the cut has structural DSD.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_NodeCutsCheckDsd( Lpk_Man_t * p, Lpk_Cut_t * pCut ) -{ - Abc_Obj_t * pObj, * pFanin; - int i, k, nCands, fLeavesOnly, RetValue; - assert( pCut->nLeaves > 0 ); - // clear ref counters - memset( p->pRefs, 0, sizeof(int) * pCut->nLeaves ); - // mark cut leaves - Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) - { - assert( pObj->fMarkA == 0 ); - pObj->fMarkA = 1; - pObj->pCopy = (void *)i; - } - // ref leaves pointed from the internal nodes - nCands = 0; - Lpk_CutForEachNode( p->pNtk, pCut, pObj, i ) - { - fLeavesOnly = 1; - Abc_ObjForEachFanin( pObj, pFanin, k ) - if ( pFanin->fMarkA ) - p->pRefs[(int)pFanin->pCopy]++; - else - fLeavesOnly = 0; - if ( fLeavesOnly ) - p->pCands[nCands++] = pObj->Id; - } - // look at the nodes that only point to the leaves - RetValue = 0; - for ( i = 0; i < nCands; i++ ) - { - pObj = Abc_NtkObj( p->pNtk, p->pCands[i] ); - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - assert( pFanin->fMarkA == 1 ); - if ( p->pRefs[(int)pFanin->pCopy] > 1 ) - break; - } - if ( k == Abc_ObjFaninNum(pObj) ) - { - RetValue = 1; - break; - } - } - // unmark cut leaves - Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) - pObj->fMarkA = 0; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pDom is contained in pCut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Lpk_NodeCutsOneDominance( Lpk_Cut_t * pDom, Lpk_Cut_t * pCut ) -{ - int i, k; - for ( i = 0; i < (int)pDom->nLeaves; i++ ) - { - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - if ( pDom->pLeaves[i] == pCut->pLeaves[k] ) - break; - if ( k == (int)pCut->nLeaves ) // node i in pDom is not contained in pCut - return 0; - } - // every node in pDom is contained in pCut - return 1; -} - -/**Function************************************************************* - - Synopsis [Check if the cut exists.] - - Description [Returns 1 if the cut exists.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_NodeCutsOneFilter( Lpk_Cut_t * pCuts, int nCuts, Lpk_Cut_t * pCutNew ) -{ - Lpk_Cut_t * pCut; - int i, k; - assert( pCutNew->uSign[0] || pCutNew->uSign[1] ); - // try to find the cut - for ( i = 0; i < nCuts; i++ ) - { - pCut = pCuts + i; - if ( pCut->nLeaves == 0 ) - continue; - if ( pCut->nLeaves == pCutNew->nLeaves ) - { - if ( pCut->uSign[0] == pCutNew->uSign[0] && pCut->uSign[1] == pCutNew->uSign[1] ) - { - for ( k = 0; k < (int)pCutNew->nLeaves; k++ ) - if ( pCut->pLeaves[k] != pCutNew->pLeaves[k] ) - break; - if ( k == (int)pCutNew->nLeaves ) - return 1; - } - continue; - } - if ( pCut->nLeaves < pCutNew->nLeaves ) - { - // skip the non-contained cuts - if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCut->uSign[0] ) - continue; - if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCut->uSign[1] ) - continue; - // check containment seriously - if ( Lpk_NodeCutsOneDominance( pCut, pCutNew ) ) - return 1; - continue; - } - // check potential containment of other cut - - // skip the non-contained cuts - if ( (pCut->uSign[0] & pCutNew->uSign[0]) != pCutNew->uSign[0] ) - continue; - if ( (pCut->uSign[1] & pCutNew->uSign[1]) != pCutNew->uSign[1] ) - continue; - // check containment seriously - if ( Lpk_NodeCutsOneDominance( pCutNew, pCut ) ) - pCut->nLeaves = 0; // removed - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Prints the given cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_NodePrintCut( Lpk_Man_t * p, Lpk_Cut_t * pCut, int fLeavesOnly ) -{ - Abc_Obj_t * pObj; - int i; - if ( !fLeavesOnly ) - printf( "LEAVES:\n" ); - Lpk_CutForEachLeaf( p->pNtk, pCut, pObj, i ) - printf( "%d,", pObj->Id ); - if ( !fLeavesOnly ) - { - printf( "\nNODES:\n" ); - Lpk_CutForEachNode( p->pNtk, pCut, pObj, i ) - { - printf( "%d,", pObj->Id ); - assert( Abc_ObjIsNode(pObj) ); - } - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Set the cut signature.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_NodeCutSignature( Lpk_Cut_t * pCut ) -{ - unsigned i; - pCut->uSign[0] = pCut->uSign[1] = 0; - for ( i = 0; i < pCut->nLeaves; i++ ) - { - pCut->uSign[(pCut->pLeaves[i] & 32) > 0] |= (1 << (pCut->pLeaves[i] & 31)); - if ( i != pCut->nLeaves - 1 ) - assert( pCut->pLeaves[i] < pCut->pLeaves[i+1] ); - } -} - - -/**Function************************************************************* - - Synopsis [Computes the set of all cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_NodeCutsOne( Lpk_Man_t * p, Lpk_Cut_t * pCut, int Node ) -{ - Lpk_Cut_t * pCutNew; - Abc_Obj_t * pObj, * pFanin; - int i, k, j, nLeavesNew; -/* - printf( "Exploring cut " ); - Lpk_NodePrintCut( p, pCut, 1 ); - printf( "with node %d\n", Node ); -*/ - // check if the cut can stand adding one more internal node - if ( pCut->nNodes == LPK_SIZE_MAX ) - return; - - // if the node is a PI, quit - pObj = Abc_NtkObj( p->pNtk, Node ); - if ( Abc_ObjIsCi(pObj) ) - return; - assert( Abc_ObjIsNode(pObj) ); - assert( Abc_ObjFaninNum(pObj) <= p->pPars->nLutSize ); - - // if the node is not in the MFFC, check the limit - if ( !Abc_NodeIsTravIdCurrent(pObj) ) - { - if ( (int)pCut->nNodesDup == p->pPars->nLutsOver ) - return; - assert( (int)pCut->nNodesDup < p->pPars->nLutsOver ); - } - - // check the possibility of adding this node using the signature - nLeavesNew = pCut->nLeaves - 1; - Abc_ObjForEachFanin( pObj, pFanin, i ) - { - if ( (pCut->uSign[(pFanin->Id & 32) > 0] & (1 << (pFanin->Id & 31))) ) - continue; - if ( ++nLeavesNew > p->pPars->nVarsMax ) - return; - } - - // initialize the set of leaves to the nodes in the cut - assert( p->nCuts < LPK_CUTS_MAX ); - pCutNew = p->pCuts + p->nCuts; - pCutNew->nLeaves = 0; - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - if ( pCut->pLeaves[i] != Node ) - pCutNew->pLeaves[pCutNew->nLeaves++] = pCut->pLeaves[i]; - - // add new nodes - Abc_ObjForEachFanin( pObj, pFanin, i ) - { - // find the place where this node belongs - for ( k = 0; k < (int)pCutNew->nLeaves; k++ ) - if ( pCutNew->pLeaves[k] >= pFanin->Id ) - break; - if ( k < (int)pCutNew->nLeaves && pCutNew->pLeaves[k] == pFanin->Id ) - continue; - // check if there is room - if ( (int)pCutNew->nLeaves == p->pPars->nVarsMax ) - return; - // move all the nodes - for ( j = pCutNew->nLeaves; j > k; j-- ) - pCutNew->pLeaves[j] = pCutNew->pLeaves[j-1]; - pCutNew->pLeaves[k] = pFanin->Id; - pCutNew->nLeaves++; - assert( pCutNew->nLeaves <= LPK_SIZE_MAX ); - - } - // skip the contained cuts - Lpk_NodeCutSignature( pCutNew ); - if ( Lpk_NodeCutsOneFilter( p->pCuts, p->nCuts, pCutNew ) ) - return; - - // update the set of internal nodes - assert( pCut->nNodes < LPK_SIZE_MAX ); - memcpy( pCutNew->pNodes, pCut->pNodes, pCut->nNodes * sizeof(int) ); - pCutNew->nNodes = pCut->nNodes; - pCutNew->nNodesDup = pCut->nNodesDup; - - // check if the node is already there - // if so, move the node to be the last - for ( i = 0; i < (int)pCutNew->nNodes; i++ ) - if ( pCutNew->pNodes[i] == Node ) - { - for ( k = i; k < (int)pCutNew->nNodes - 1; k++ ) - pCutNew->pNodes[k] = pCutNew->pNodes[k+1]; - pCutNew->pNodes[k] = Node; - break; - } - if ( i == (int)pCutNew->nNodes ) // new node - { - pCutNew->pNodes[ pCutNew->nNodes++ ] = Node; - pCutNew->nNodesDup += !Abc_NodeIsTravIdCurrent(pObj); - } - // the number of nodes does not exceed MFFC plus duplications - assert( pCutNew->nNodes <= p->nMffc + pCutNew->nNodesDup ); - // add the cut to storage - assert( p->nCuts < LPK_CUTS_MAX ); - p->nCuts++; -} - -/**Function************************************************************* - - Synopsis [Computes the set of all cuts.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_NodeCuts( Lpk_Man_t * p ) -{ - Lpk_Cut_t * pCut, * pCut2; - int i, k, Temp, nMffc, fChanges; - - // mark the MFFC of the node with the current trav ID - nMffc = p->nMffc = Abc_NodeMffcLabel( p->pObj ); - assert( nMffc > 0 ); - if ( nMffc == 1 ) - return 0; - - // initialize the first cut - pCut = p->pCuts; p->nCuts = 1; - pCut->nNodes = 0; - pCut->nNodesDup = 0; - pCut->nLeaves = 1; - pCut->pLeaves[0] = p->pObj->Id; - // assign the signature - Lpk_NodeCutSignature( pCut ); - - // perform the cut computation - for ( i = 0; i < p->nCuts; i++ ) - { - pCut = p->pCuts + i; - if ( pCut->nLeaves == 0 ) - continue; - - // try to expand the fanins of this cut - for ( k = 0; k < (int)pCut->nLeaves; k++ ) - { - // create a new cut - Lpk_NodeCutsOne( p, pCut, pCut->pLeaves[k] ); - // quit if the number of cuts has exceeded the limit - if ( p->nCuts == LPK_CUTS_MAX ) - break; - } - if ( p->nCuts == LPK_CUTS_MAX ) - break; - } - if ( p->nCuts == LPK_CUTS_MAX ) - p->nNodesOver++; - - // record the impact of this node - if ( p->pPars->fSatur ) - Lpk_NodeRecordImpact( p ); - - // compress the cuts by removing empty ones, those with negative Weight, and decomposable ones - p->nEvals = 0; - for ( i = 0; i < p->nCuts; i++ ) - { - pCut = p->pCuts + i; - if ( pCut->nLeaves < 2 ) - continue; - // compute the minimum number of LUTs needed to implement this cut - // V = N * (K-1) + 1 ~~~~~ N = Ceiling[(V-1)/(K-1)] = (V-1)/(K-1) + [(V-1)%(K-1) > 0] - pCut->nLuts = Lpk_LutNumLuts( pCut->nLeaves, p->pPars->nLutSize ); -// pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup - 1) / pCut->nLuts; //p->pPars->nLutsMax; - pCut->Weight = (float)1.0 * (pCut->nNodes - pCut->nNodesDup) / pCut->nLuts; //p->pPars->nLutsMax; - if ( pCut->Weight <= 1.001 ) -// if ( pCut->Weight <= 0.999 ) - continue; - pCut->fHasDsd = Lpk_NodeCutsCheckDsd( p, pCut ); - if ( pCut->fHasDsd ) - continue; - p->pEvals[p->nEvals++] = i; - } - if ( p->nEvals == 0 ) - return 0; - - // sort the cuts by Weight - do { - fChanges = 0; - for ( i = 0; i < p->nEvals - 1; i++ ) - { - pCut = p->pCuts + p->pEvals[i]; - pCut2 = p->pCuts + p->pEvals[i+1]; - if ( pCut->Weight >= pCut2->Weight - 0.001 ) - continue; - Temp = p->pEvals[i]; - p->pEvals[i] = p->pEvals[i+1]; - p->pEvals[i+1] = Temp; - fChanges = 1; - } - } while ( fChanges ); -/* - for ( i = 0; i < p->nEvals; i++ ) - { - pCut = p->pCuts + p->pEvals[i]; - printf( "Cut %3d : W = %5.2f.\n", i, pCut->Weight ); - } - printf( "\n" ); -*/ - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/lpkInt.h b/src/opt/lpk/lpkInt.h deleted file mode 100644 index 960599e4..00000000 --- a/src/opt/lpk/lpkInt.h +++ /dev/null @@ -1,246 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpkInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpkInt.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __LPK_INT_H__ -#define __LPK_INT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "abc.h" -#include "kit.h" -#include "if.h" -#include "lpk.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -#define LPK_SIZE_MAX 24 // the largest size of the function -#define LPK_CUTS_MAX 512 // the largest number of cuts considered - -typedef struct Lpk_Man_t_ Lpk_Man_t; -typedef struct Lpk_Cut_t_ Lpk_Cut_t; - -struct Lpk_Cut_t_ -{ - unsigned nLeaves : 6; // (L) the number of leaves - unsigned nNodes : 6; // (M) the number of nodes - unsigned nNodesDup : 6; // (Q) nodes outside of MFFC - unsigned nLuts : 6; // (N) the number of LUTs to try - unsigned unused : 6; // unused - unsigned fHasDsd : 1; // set to 1 if the cut has structural DSD (and so cannot be used) - unsigned fMark : 1; // multipurpose mark - unsigned uSign[2]; // the signature - float Weight; // the weight of the cut: (M - Q)/N(V) (the larger the better) - int Gain; // the gain achieved using this cut - int pLeaves[LPK_SIZE_MAX]; // the leaves of the cut - int pNodes[LPK_SIZE_MAX]; // the nodes of the cut -}; - -struct Lpk_Man_t_ -{ - // parameters - Lpk_Par_t * pPars; // the set of parameters - // current representation - Abc_Ntk_t * pNtk; // the network - Abc_Obj_t * pObj; // the node to resynthesize - // cut representation - int nMffc; // the size of MFFC of the node - int nCuts; // the total number of cuts - int nCutsMax; // the largest possible number of cuts - int nEvals; // the number of good cuts - Lpk_Cut_t pCuts[LPK_CUTS_MAX]; // the storage for cuts - int pEvals[LPK_CUTS_MAX]; // the good cuts - // visited nodes - Vec_Vec_t * vVisited; - // mapping manager - If_Man_t * pIfMan; - Vec_Int_t * vCover; - Vec_Vec_t * vLevels; - // temporary variables - int fCofactoring; // working in the cofactoring mode - int fCalledOnce; // limits the depth of MUX cofactoring - int nCalledSRed; // the number of called to SRed - int pRefs[LPK_SIZE_MAX]; // fanin reference counters - int pCands[LPK_SIZE_MAX]; // internal nodes pointing only to the leaves - Vec_Ptr_t * vLeaves; - // truth table representation - Vec_Ptr_t * vTtElems; // elementary truth tables - Vec_Ptr_t * vTtNodes; // storage for temporary truth tables of the nodes - Vec_Int_t * vMemory; - Vec_Int_t * vBddDir; - Vec_Int_t * vBddInv; - unsigned puSupps[32]; // the supports of the cofactors - unsigned * ppTruths[5][16]; - // variable sets - Vec_Int_t * vSets[8]; - Kit_DsdMan_t* pDsdMan; - // statistics - int nNodesTotal; // total number of nodes - int nNodesOver; // nodes with cuts over the limit - int nCutsTotal; // total number of cuts - int nCutsUseful; // useful cuts - int nGainTotal; // the gain in LUTs - int nChanges; // the number of changed nodes - int nBenefited; // the number of gainful that benefited from decomposition - int nMuxes; - int nDsds; - int nTotalNets; - int nTotalNets2; - int nTotalNodes; - int nTotalNodes2; - // counter of non-DSD blocks - int nBlocks[17]; - // runtime - int timeCuts; - int timeTruth; - int timeSupps; - int timeTruth2; - int timeTruth3; - int timeEval; - int timeMap; - int timeOther; - int timeTotal; - // runtime of eval - int timeEvalMuxAn; - int timeEvalMuxSp; - int timeEvalDsdAn; - int timeEvalDsdSp; - -}; - - -// internal representation of the function to be decomposed -typedef struct Lpk_Fun_t_ Lpk_Fun_t; -struct Lpk_Fun_t_ -{ - Vec_Ptr_t * vNodes; // the array of leaves and decomposition nodes - unsigned Id : 7; // the ID of this node - unsigned nVars : 5; // the number of variables - unsigned nLutK : 4; // the number of LUT inputs - unsigned nAreaLim : 5; // the area limit (the largest allowed) - unsigned nDelayLim : 9; // the delay limit (the largest allowed) - unsigned fSupports : 1; // supports of cofactors were precomputed - unsigned fMark : 1; // marks the MUX-based dec - unsigned uSupp; // the support of this component - unsigned puSupps[32]; // the supports of the cofactors - char pDelays[16]; // the delays of the inputs - char pFanins[16]; // the fanins of this function - unsigned pTruth[0]; // the truth table (contains room for three truth tables) -}; - -// preliminary decomposition result -typedef struct Lpk_Res_t_ Lpk_Res_t; -struct Lpk_Res_t_ -{ - int nBSVars; // the number of bound set variables - unsigned BSVars; // the bound set - int nCofVars; // the number of cofactoring variables - char pCofVars[4]; // the cofactoring variables - int nSuppSizeS; // support size of the smaller (decomposed) function - int nSuppSizeL; // support size of the larger (composition) function - int DelayEst; // estimated delay of the decomposition - int AreaEst; // estimated area of the decomposition - int Variable; // variable in MUX decomposition - int Polarity; // polarity in MUX decomposition -}; - -static inline int Lpk_LutNumVars( int nLutsLim, int nLutK ) { return nLutsLim * (nLutK - 1) + 1; } -static inline int Lpk_LutNumLuts( int nVarsMax, int nLutK ) { return (nVarsMax - 1) / (nLutK - 1) + (int)((nVarsMax - 1) % (nLutK - 1) > 0); } -static inline unsigned * Lpk_FunTruth( Lpk_Fun_t * p, int Num ) { assert( Num < 3 ); return p->pTruth + Kit_TruthWordNum(p->nVars) * Num; } - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// ITERATORS /// -//////////////////////////////////////////////////////////////////////// - -#define Lpk_CutForEachLeaf( pNtk, pCut, pObj, i ) \ - for ( i = 0; (i < (int)(pCut)->nLeaves) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pLeaves[i])), 1); i++ ) -#define Lpk_CutForEachNode( pNtk, pCut, pObj, i ) \ - for ( i = 0; (i < (int)(pCut)->nNodes) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i++ ) -#define Lpk_CutForEachNodeReverse( pNtk, pCut, pObj, i ) \ - for ( i = (int)(pCut)->nNodes - 1; (i >= 0) && (((pObj) = Abc_NtkObj(pNtk, (pCut)->pNodes[i])), 1); i-- ) -#define Lpk_SuppForEachVar( Supp, Var )\ - for ( Var = 0; Var < 16; Var++ )\ - if ( !(Supp & (1<nLutsMax <= 16 ); - assert( pPars->nVarsMax > 0 && pPars->nVarsMax <= 16 ); - p = ALLOC( Lpk_Man_t, 1 ); - memset( p, 0, sizeof(Lpk_Man_t) ); - p->pPars = pPars; - p->nCutsMax = LPK_CUTS_MAX; - p->vTtElems = Vec_PtrAllocTruthTables( pPars->nVarsMax ); - p->vTtNodes = Vec_PtrAllocSimInfo( 1024, Abc_TruthWordNum(pPars->nVarsMax) ); - p->vCover = Vec_IntAlloc( 1 << 12 ); - p->vLeaves = Vec_PtrAlloc( 32 ); - for ( i = 0; i < 8; i++ ) - p->vSets[i] = Vec_IntAlloc(100); - p->pDsdMan = Kit_DsdManAlloc( pPars->nVarsMax, 64 ); - p->vMemory = Vec_IntAlloc( 1024 * 32 ); - p->vBddDir = Vec_IntAlloc( 256 ); - p->vBddInv = Vec_IntAlloc( 256 ); - // allocate temporary storage for truth tables - nWords = Kit_TruthWordNum(pPars->nVarsMax); - p->ppTruths[0][0] = ALLOC( unsigned, 32 * nWords ); - p->ppTruths[1][0] = p->ppTruths[0][0] + 1 * nWords; - for ( i = 1; i < 2; i++ ) - p->ppTruths[1][i] = p->ppTruths[1][0] + i * nWords; - p->ppTruths[2][0] = p->ppTruths[1][0] + 2 * nWords; - for ( i = 1; i < 4; i++ ) - p->ppTruths[2][i] = p->ppTruths[2][0] + i * nWords; - p->ppTruths[3][0] = p->ppTruths[2][0] + 4 * nWords; - for ( i = 1; i < 8; i++ ) - p->ppTruths[3][i] = p->ppTruths[3][0] + i * nWords; - p->ppTruths[4][0] = p->ppTruths[3][0] + 8 * nWords; - for ( i = 1; i < 16; i++ ) - p->ppTruths[4][i] = p->ppTruths[4][0] + i * nWords; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_ManStop( Lpk_Man_t * p ) -{ - int i; - free( p->ppTruths[0][0] ); - Vec_IntFree( p->vBddDir ); - Vec_IntFree( p->vBddInv ); - Vec_IntFree( p->vMemory ); - Kit_DsdManFree( p->pDsdMan ); - for ( i = 0; i < 8; i++ ) - Vec_IntFree(p->vSets[i]); - if ( p->pIfMan ) - { - void * pPars = p->pIfMan->pPars; - If_ManStop( p->pIfMan ); - free( pPars ); - } - if ( p->vLevels ) - Vec_VecFree( p->vLevels ); - if ( p->vVisited ) - Vec_VecFree( p->vVisited ); - Vec_PtrFree( p->vLeaves ); - Vec_IntFree( p->vCover ); - Vec_PtrFree( p->vTtElems ); - Vec_PtrFree( p->vTtNodes ); - free( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/lpkMap.c b/src/opt/lpk/lpkMap.c deleted file mode 100644 index 698aeea1..00000000 --- a/src/opt/lpk/lpkMap.c +++ /dev/null @@ -1,205 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpkMap.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpkMap.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "lpkInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Transforms the decomposition graph into the AIG.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * Lpk_MapPrimeInternal( If_Man_t * pIfMan, Kit_Graph_t * pGraph ) -{ - Kit_Node_t * pNode; - If_Obj_t * pAnd0, * pAnd1; - int i; - // check for constant function - if ( Kit_GraphIsConst(pGraph) ) - return If_ManConst1(pIfMan); - // check for a literal - if ( Kit_GraphIsVar(pGraph) ) - return Kit_GraphVar(pGraph)->pFunc; - // build the AIG nodes corresponding to the AND gates of the graph - Kit_GraphForEachNode( pGraph, pNode, i ) - { - pAnd0 = Kit_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc; - pAnd1 = Kit_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc; - pNode->pFunc = If_ManCreateAnd( pIfMan, - If_NotCond( If_Regular(pAnd0), If_IsComplement(pAnd0) ^ pNode->eEdge0.fCompl ), - If_NotCond( If_Regular(pAnd1), If_IsComplement(pAnd1) ^ pNode->eEdge1.fCompl ) ); - } - return pNode->pFunc; -} - -/**Function************************************************************* - - Synopsis [Strashes one logic node using its SOP.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * Lpk_MapPrime( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) -{ - Kit_Graph_t * pGraph; - Kit_Node_t * pNode; - If_Obj_t * pRes; - int i; - // derive the factored form - pGraph = Kit_TruthToGraph( pTruth, nVars, p->vCover ); - if ( pGraph == NULL ) - return NULL; - // collect the fanins - Kit_GraphForEachLeaf( pGraph, pNode, i ) - pNode->pFunc = ppLeaves[i]; - // perform strashing - pRes = Lpk_MapPrimeInternal( p->pIfMan, pGraph ); - pRes = If_NotCond( pRes, Kit_GraphIsComplement(pGraph) ); - Kit_GraphFree( pGraph ); - return pRes; -} - -/**Function************************************************************* - - Synopsis [Prepares the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * Lpk_MapTree_rec( Lpk_Man_t * p, Kit_DsdNtk_t * pNtk, If_Obj_t ** ppLeaves, int iLit, If_Obj_t * pResult ) -{ - Kit_DsdObj_t * pObj; - If_Obj_t * pObjNew = NULL, * pObjNew2 = NULL, * pFansNew[16]; - unsigned i, iLitFanin; - - assert( iLit >= 0 ); - - // consider the case of a gate - pObj = Kit_DsdNtkObj( pNtk, Kit_DsdLit2Var(iLit) ); - if ( pObj == NULL ) - { - pObjNew = ppLeaves[Kit_DsdLit2Var(iLit)]; - return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ); - } - if ( pObj->Type == KIT_DSD_CONST1 ) - { - return If_NotCond( If_ManConst1(p->pIfMan), Kit_DsdLitIsCompl(iLit) ); - } - if ( pObj->Type == KIT_DSD_VAR ) - { - pObjNew = ppLeaves[Kit_DsdLit2Var(pObj->pFans[0])]; - return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ^ Kit_DsdLitIsCompl(pObj->pFans[0]) ); - } - if ( pObj->Type == KIT_DSD_AND ) - { - assert( pObj->nFans == 2 ); - pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL ); - pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL ); - if ( pFansNew[0] == NULL || pFansNew[1] == NULL ) - return NULL; - pObjNew = If_ManCreateAnd( p->pIfMan, pFansNew[0], pFansNew[1] ); - return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ); - } - if ( pObj->Type == KIT_DSD_XOR ) - { - int fCompl = Kit_DsdLitIsCompl(iLit); - assert( pObj->nFans == 2 ); - pFansNew[0] = Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[0], NULL ); - pFansNew[1] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, pObj->pFans[1], NULL ); - if ( pFansNew[0] == NULL || pFansNew[1] == NULL ) - return NULL; - fCompl ^= If_IsComplement(pFansNew[0]) ^ If_IsComplement(pFansNew[1]); - pObjNew = If_ManCreateXor( p->pIfMan, If_Regular(pFansNew[0]), If_Regular(pFansNew[1]) ); - return If_NotCond( pObjNew, fCompl ); - } - assert( pObj->Type == KIT_DSD_PRIME ); - p->nBlocks[pObj->nFans]++; - - // solve for the inputs - Kit_DsdObjForEachFanin( pNtk, pObj, iLitFanin, i ) - { - if ( i == 0 ) - pFansNew[i] = pResult? pResult : Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL ); - else - pFansNew[i] = Lpk_MapTree_rec( p, pNtk, ppLeaves, iLitFanin, NULL ); - if ( pFansNew[i] == NULL ) - return NULL; - } -/* - if ( !p->fCofactoring && p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize ) - { - pObjNew = Lpk_MapTreeMulti( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); - return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ); - } -*/ -/* - if ( (int)pObj->nFans > p->pPars->nLutSize ) - { - pObjNew2 = Lpk_MapTreeMux_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); -// if ( pObjNew2 ) -// return If_NotCond( pObjNew2, Kit_DsdLitIsCompl(iLit) ); - } -*/ - - // find best cofactoring variable - if ( p->pPars->nVarsShared > 0 && (int)pObj->nFans > p->pPars->nLutSize ) - { - pObjNew2 = Lpk_MapSuppRedDec_rec( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); - if ( pObjNew2 ) - return If_NotCond( pObjNew2, Kit_DsdLitIsCompl(iLit) ); - } - - pObjNew = Lpk_MapPrime( p, Kit_DsdObjTruth(pObj), pObj->nFans, pFansNew ); - - // add choice - if ( pObjNew && pObjNew2 ) - { - If_ObjSetChoice( If_Regular(pObjNew), If_Regular(pObjNew2) ); - If_ManCreateChoice( p->pIfMan, If_Regular(pObjNew) ); - } - return If_NotCond( pObjNew, Kit_DsdLitIsCompl(iLit) ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/lpkMulti.c b/src/opt/lpk/lpkMulti.c deleted file mode 100644 index 82cf3578..00000000 --- a/src/opt/lpk/lpkMulti.c +++ /dev/null @@ -1,495 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpkMulti.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpkMulti.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "lpkInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Records variable order.] - - Description [Increaments Order[x][y] by 1 if x should be above y in the DSD.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_CreateVarOrder( Kit_DsdNtk_t * pNtk, char pTable[][16] ) -{ - Kit_DsdObj_t * pObj; - unsigned uSuppFanins, k; - int Above[16], Below[16]; - int nAbove, nBelow, iFaninLit, i, x, y; - // iterate through the nodes - Kit_DsdNtkForEachObj( pNtk, pObj, i ) - { - // collect fanin support of this node - nAbove = 0; - uSuppFanins = 0; - Kit_DsdObjForEachFanin( pNtk, pObj, iFaninLit, k ) - { - if ( Kit_DsdLitIsLeaf( pNtk, iFaninLit ) ) - Above[nAbove++] = Kit_DsdLit2Var(iFaninLit); - else - uSuppFanins |= Kit_DsdLitSupport( pNtk, iFaninLit ); - } - // find the below variables - nBelow = 0; - for ( y = 0; y < 16; y++ ) - if ( uSuppFanins & (1 << y) ) - Below[nBelow++] = y; - // create all pairs - for ( x = 0; x < nAbove; x++ ) - for ( y = 0; y < nBelow; y++ ) - pTable[Above[x]][Below[y]]++; - } -} - -/**Function************************************************************* - - Synopsis [Creates commmon variable order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_CreateCommonOrder( char pTable[][16], int piCofVar[], int nCBars, int pPrios[], int nVars, int fVerbose ) -{ - int Score[16] = {0}, pPres[16]; - int i, y, x, iVarBest, ScoreMax, PrioCount; - - // mark the present variables - for ( i = 0; i < nVars; i++ ) - pPres[i] = 1; - // remove cofactored variables - for ( i = 0; i < nCBars; i++ ) - pPres[piCofVar[i]] = 0; - - // compute scores for each leaf - for ( i = 0; i < nVars; i++ ) - { - if ( pPres[i] == 0 ) - continue; - for ( y = 0; y < nVars; y++ ) - Score[i] += pTable[i][y]; - for ( x = 0; x < nVars; x++ ) - Score[i] -= pTable[x][i]; - } - - // print the scores - if ( fVerbose ) - { - printf( "Scores: " ); - for ( i = 0; i < nVars; i++ ) - printf( "%c=%d ", 'a'+i, Score[i] ); - printf( " " ); - printf( "Prios: " ); - } - - // derive variable priority - // variables with equal score receive the same priority - for ( i = 0; i < nVars; i++ ) - pPrios[i] = 16; - - // iterate until variables remain - for ( PrioCount = 1; ; PrioCount++ ) - { - // find the present variable with the highest score - iVarBest = -1; - ScoreMax = -100000; - for ( i = 0; i < nVars; i++ ) - { - if ( pPres[i] == 0 ) - continue; - if ( ScoreMax < Score[i] ) - { - ScoreMax = Score[i]; - iVarBest = i; - } - } - if ( iVarBest == -1 ) - break; - // give the next priority to all vars having this score - if ( fVerbose ) - printf( "%d=", PrioCount ); - for ( i = 0; i < nVars; i++ ) - { - if ( pPres[i] == 0 ) - continue; - if ( Score[i] == ScoreMax ) - { - pPrios[i] = PrioCount; - pPres[i] = 0; - if ( fVerbose ) - printf( "%c", 'a'+i ); - } - } - if ( fVerbose ) - printf( " " ); - } - if ( fVerbose ) - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Finds components with the highest priority.] - - Description [Returns the number of components selected.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_FindHighest( Kit_DsdNtk_t ** ppNtks, int * piLits, int nSize, int * pPrio, int * pDecision ) -{ - Kit_DsdObj_t * pObj; - unsigned uSupps[8], uSuppFanin, uSuppTotal, uSuppLarge; - int i, pTriv[8], PrioMin, iVarMax, nComps, fOneNonTriv; - - // find individual support and total support - uSuppTotal = 0; - for ( i = 0; i < nSize; i++ ) - { - pTriv[i] = 1; - if ( piLits[i] < 0 ) - uSupps[i] = 0; - else if ( Kit_DsdLitIsLeaf(ppNtks[i], piLits[i]) ) - uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ); - else - { - pObj = Kit_DsdNtkObj( ppNtks[i], Kit_DsdLit2Var(piLits[i]) ); - if ( pObj->Type == KIT_DSD_PRIME ) - { - pTriv[i] = 0; - uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[0] ); - } - else - { - assert( pObj->nFans == 2 ); - if ( !Kit_DsdLitIsLeaf(ppNtks[i], pObj->pFans[0]) ) - pTriv[i] = 0; - uSuppFanin = Kit_DsdLitSupport( ppNtks[i], pObj->pFans[1] ); - } - uSupps[i] = Kit_DsdLitSupport( ppNtks[i], piLits[i] ) & ~uSuppFanin; - } - assert( uSupps[i] <= 0xFFFF ); - uSuppTotal |= uSupps[i]; - } - if ( uSuppTotal == 0 ) - return 0; - - // find one support variable with the highest priority - PrioMin = ABC_INFINITY; - iVarMax = -1; - for ( i = 0; i < 16; i++ ) - if ( uSuppTotal & (1 << i) ) - if ( PrioMin > pPrio[i] ) - { - PrioMin = pPrio[i]; - iVarMax = i; - } - assert( iVarMax != -1 ); - - // select components, which have this variable - nComps = 0; - fOneNonTriv = 0; - uSuppLarge = 0; - for ( i = 0; i < nSize; i++ ) - if ( uSupps[i] & (1<pIfMan) ); - - // iterate over the nodes - if ( p->pPars->fVeryVerbose ) - printf( "Decision: " ); - for ( i = 0; i < nSize; i++ ) - { - if ( pDecision[i] ) - { - if ( p->pPars->fVeryVerbose ) - printf( "%d ", i ); - assert( piLits[i] >= 0 ); - pObj = Kit_DsdNtkObj( ppNtks[i], Kit_DsdLit2Var(piLits[i]) ); - if ( pObj == NULL ) - piLitsNew[i] = -2; - else if ( pObj->Type == KIT_DSD_PRIME ) - piLitsNew[i] = pObj->pFans[0]; - else - piLitsNew[i] = pObj->pFans[1]; - } - else - piLitsNew[i] = piLits[i]; - } - if ( p->pPars->fVeryVerbose ) - printf( "\n" ); - - // call again - pResPrev = Lpk_MapTreeMulti_rec( p, ppNtks, piLitsNew, piCofVar, nCBars, ppLeaves, nLeaves, pPrio ); - - // create new set of nodes - for ( i = 0; i < nSize; i++ ) - { - if ( pDecision[i] ) - pObjsNew[nCBars][i] = Lpk_MapTree_rec( p, ppNtks[i], ppLeaves, piLits[i], pResPrev ); - else if ( piLits[i] == -1 ) - pObjsNew[nCBars][i] = If_ManConst1(p->pIfMan); - else if ( piLits[i] == -2 ) - pObjsNew[nCBars][i] = If_Not( If_ManConst1(p->pIfMan) ); - else - pObjsNew[nCBars][i] = pResPrev; - } - - // create MUX using these outputs - for ( k = nCBars; k > 0; k-- ) - { - nSize /= 2; - for ( i = 0; i < nSize; i++ ) - pObjsNew[k-1][i] = If_ManCreateMux( p->pIfMan, pObjsNew[k][2*i+0], pObjsNew[k][2*i+1], ppLeaves[piCofVar[k-1]] ); - } - assert( nSize == 1 ); - return pObjsNew[0][0]; -} - -/**Function************************************************************* - - Synopsis [Prepares the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * Lpk_MapTreeMulti( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) -{ - static Counter = 0; - If_Obj_t * pResult; - Kit_DsdNtk_t * ppNtks[8] = {0}, * pTemp; - Kit_DsdObj_t * pRoot; - int piCofVar[4], pPrios[16], pFreqs[16] = {0}, piLits[16]; - int i, k, nCBars, nSize, nMemSize; - unsigned * ppCofs[4][8], uSupport; - char pTable[16][16] = {0}; - int fVerbose = p->pPars->fVeryVerbose; - - Counter++; -// printf( "Run %d.\n", Counter ); - - // allocate storage for cofactors - nMemSize = Kit_TruthWordNum(nVars); - ppCofs[0][0] = ALLOC( unsigned, 32 * nMemSize ); - nSize = 0; - for ( i = 0; i < 4; i++ ) - for ( k = 0; k < 8; k++ ) - ppCofs[i][k] = ppCofs[0][0] + nMemSize * nSize++; - assert( nSize == 32 ); - - // find the best cofactoring variables - nCBars = Kit_DsdCofactoring( pTruth, nVars, piCofVar, p->pPars->nVarsShared, 0 ); -// nCBars = 2; -// piCofVar[0] = 0; -// piCofVar[1] = 1; - - - // copy the function - Kit_TruthCopy( ppCofs[0][0], pTruth, nVars ); - - // decompose w.r.t. these variables - for ( k = 0; k < nCBars; k++ ) - { - nSize = (1 << k); - for ( i = 0; i < nSize; i++ ) - { - Kit_TruthCofactor0New( ppCofs[k+1][2*i+0], ppCofs[k][i], nVars, piCofVar[k] ); - Kit_TruthCofactor1New( ppCofs[k+1][2*i+1], ppCofs[k][i], nVars, piCofVar[k] ); - } - } - nSize = (1 << nCBars); - // compute DSD networks - for ( i = 0; i < nSize; i++ ) - { - ppNtks[i] = Kit_DsdDecompose( ppCofs[nCBars][i], nVars ); - ppNtks[i] = Kit_DsdExpand( pTemp = ppNtks[i] ); - Kit_DsdNtkFree( pTemp ); - if ( fVerbose ) - { - printf( "Cof%d%d: ", nCBars, i ); - Kit_DsdPrint( stdout, ppNtks[i] ); - } - } - - // compute variable frequences - for ( i = 0; i < nSize; i++ ) - { - uSupport = Kit_TruthSupport( ppCofs[nCBars][i], nVars ); - for ( k = 0; k < nVars; k++ ) - if ( uSupport & (1<pSupps[0] <= 0xFFFF ); - // undec nodes should be rotated in such a way that the first input has as many shared inputs as possible - Kit_DsdRotate( ppNtks[i], pFreqs ); - // print the resulting networks - if ( fVerbose ) - { - printf( "Cof%d%d: ", nCBars, i ); - Kit_DsdPrint( stdout, ppNtks[i] ); - } - } - - for ( i = 0; i < nSize; i++ ) - { - // collect the roots - pRoot = Kit_DsdNtkRoot(ppNtks[i]); - if ( pRoot->Type == KIT_DSD_CONST1 ) - piLits[i] = Kit_DsdLitIsCompl(ppNtks[i]->Root)? -2: -1; - else if ( pRoot->Type == KIT_DSD_VAR ) - piLits[i] = Kit_DsdLitNotCond( pRoot->pFans[0], Kit_DsdLitIsCompl(ppNtks[i]->Root) ); - else - piLits[i] = ppNtks[i]->Root; - } - - - // recursively construct AIG for mapping - p->fCofactoring = 1; - pResult = Lpk_MapTreeMulti_rec( p, ppNtks, piLits, piCofVar, nCBars, ppLeaves, nVars, pPrios ); - p->fCofactoring = 0; - - if ( fVerbose ) - printf( "\n" ); - - // verify the transformations - nSize = (1 << nCBars); - for ( i = 0; i < nSize; i++ ) - Kit_DsdTruth( ppNtks[i], ppCofs[nCBars][i] ); - // mux the truth tables - for ( k = nCBars-1; k >= 0; k-- ) - { - nSize = (1 << k); - for ( i = 0; i < nSize; i++ ) - Kit_TruthMuxVar( ppCofs[k][i], ppCofs[k+1][2*i+0], ppCofs[k+1][2*i+1], nVars, piCofVar[k] ); - } - if ( !Extra_TruthIsEqual( pTruth, ppCofs[0][0], nVars ) ) - printf( "Verification failed.\n" ); - - - // free the networks - for ( i = 0; i < 8; i++ ) - if ( ppNtks[i] ) - Kit_DsdNtkFree( ppNtks[i] ); - free( ppCofs[0][0] ); - - return pResult; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/lpkMux.c b/src/opt/lpk/lpkMux.c deleted file mode 100644 index ed046ad7..00000000 --- a/src/opt/lpk/lpkMux.c +++ /dev/null @@ -1,247 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpkMux.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpkMux.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "lpkInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Find the best cofactoring variable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Lpk_MapTreeBestCofVar( Lpk_Man_t * p, unsigned * pTruth, int nVars, unsigned * pCof0, unsigned * pCof1 ) -{ - int i, iBestVar, nSuppSizeCur0, nSuppSizeCur1, nSuppSizeCur, nSuppSizeMin; - // iterate through variables - iBestVar = -1; - nSuppSizeMin = KIT_INFINITY; - for ( i = 0; i < nVars; i++ ) - { - // cofactor the functiona and get support sizes - Kit_TruthCofactor0New( pCof0, pTruth, nVars, i ); - Kit_TruthCofactor1New( pCof1, pTruth, nVars, i ); - nSuppSizeCur0 = Kit_TruthSupportSize( pCof0, nVars ); - nSuppSizeCur1 = Kit_TruthSupportSize( pCof1, nVars ); - nSuppSizeCur = nSuppSizeCur0 + nSuppSizeCur1; - // skip cofactoring that goes above the limit - if ( nSuppSizeCur0 > p->pPars->nLutSize || nSuppSizeCur1 > p->pPars->nLutSize ) - continue; - // compare this variable with other variables - if ( nSuppSizeMin > nSuppSizeCur ) - { - nSuppSizeMin = nSuppSizeCur; - iBestVar = i; - } - } - // cofactor w.r.t. this variable - if ( iBestVar != -1 ) - { - Kit_TruthCofactor0New( pCof0, pTruth, nVars, iBestVar ); - Kit_TruthCofactor1New( pCof1, pTruth, nVars, iBestVar ); - } - return iBestVar; -} - -/**Function************************************************************* - - Synopsis [Maps the function by the best cofactoring.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * Lpk_MapTreeMux_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) -{ - unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 ); - unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 ); - If_Obj_t * pObj0, * pObj1; - Kit_DsdNtk_t * ppNtks[2]; - int iBestVar; - assert( nVars > 3 ); - p->fCalledOnce = 1; - // cofactor w.r.t. the best variable - iBestVar = Lpk_MapTreeBestCofVar( p, pTruth, nVars, pCof0, pCof1 ); - if ( iBestVar == -1 ) - return NULL; - // decompose the functions - ppNtks[0] = Kit_DsdDecompose( pCof0, nVars ); - ppNtks[1] = Kit_DsdDecompose( pCof1, nVars ); - if ( p->pPars->fVeryVerbose ) - { - printf( "Cofactoring w.r.t. var %c (%d -> %d+%d supp vars):\n", - 'a'+iBestVar, nVars, Kit_TruthSupportSize(pCof0, nVars), Kit_TruthSupportSize(pCof1, nVars) ); - Kit_DsdPrintExpanded( ppNtks[0] ); - Kit_DsdPrintExpanded( ppNtks[1] ); - } - // map the DSD structures - pObj0 = Lpk_MapTree_rec( p, ppNtks[0], ppLeaves, ppNtks[0]->Root, NULL ); - pObj1 = Lpk_MapTree_rec( p, ppNtks[1], ppLeaves, ppNtks[1]->Root, NULL ); - Kit_DsdNtkFree( ppNtks[0] ); - Kit_DsdNtkFree( ppNtks[1] ); - return If_ManCreateMux( p->pIfMan, pObj0, pObj1, ppLeaves[iBestVar] ); -} - - - -/**Function************************************************************* - - Synopsis [Implements support-reducing decomposition.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -If_Obj_t * Lpk_MapSuppRedDec_rec( Lpk_Man_t * p, unsigned * pTruth, int nVars, If_Obj_t ** ppLeaves ) -{ - Kit_DsdNtk_t * pNtkDec, * pNtkComp, * ppNtks[2], * pTemp; - If_Obj_t * pObjNew; - unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 ); - unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 ); - unsigned * pDec0 = Vec_PtrEntry( p->vTtNodes, 2 ); - unsigned * pDec1 = Vec_PtrEntry( p->vTtNodes, 3 ); - unsigned * pDec = Vec_PtrEntry( p->vTtNodes, 4 ); - unsigned * pCo00 = Vec_PtrEntry( p->vTtNodes, 5 ); - unsigned * pCo01 = Vec_PtrEntry( p->vTtNodes, 6 ); - unsigned * pCo10 = Vec_PtrEntry( p->vTtNodes, 7 ); - unsigned * pCo11 = Vec_PtrEntry( p->vTtNodes, 8 ); - unsigned * pCo0 = Vec_PtrEntry( p->vTtNodes, 9 ); - unsigned * pCo1 = Vec_PtrEntry( p->vTtNodes, 10 ); - unsigned * pCo = Vec_PtrEntry( p->vTtNodes, 11 ); - int TrueMint0, TrueMint1, FalseMint0, FalseMint1; - int uSubsets, uSubset0, uSubset1, iVar, iVarReused, i; - - // determine if supp-red decomposition exists - uSubsets = Lpk_MapSuppRedDecSelect( p, pTruth, nVars, &iVar, &iVarReused ); - if ( uSubsets == 0 ) - return NULL; - p->nCalledSRed++; - - // get the cofactors - Kit_TruthCofactor0New( pCof0, pTruth, nVars, iVar ); - Kit_TruthCofactor1New( pCof1, pTruth, nVars, iVar ); - - // get the bound sets - uSubset0 = uSubsets & 0xFFFF; - uSubset1 = uSubsets >> 16; - - // compute the decomposed functions - ppNtks[0] = Kit_DsdDecompose( pCof0, nVars ); - ppNtks[1] = Kit_DsdDecompose( pCof1, nVars ); - ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp ); - ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] ); Kit_DsdNtkFree( pTemp ); - Kit_DsdTruthPartial( p->pDsdMan, ppNtks[0], pDec0, uSubset0 ); - Kit_DsdTruthPartial( p->pDsdMan, ppNtks[1], pDec1, uSubset1 ); -// Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[0], uSubset0, iVarReused, pCo0, pDec0 ); -// Kit_DsdTruthPartialTwo( p->pDsdMan, ppNtks[1], uSubset1, iVarReused, pCo1, pDec1 ); - Kit_DsdNtkFree( ppNtks[0] ); - Kit_DsdNtkFree( ppNtks[1] ); -//Kit_DsdPrintFromTruth( pDec0, nVars ); -//Kit_DsdPrintFromTruth( pDec1, nVars ); - // get the decomposed function - Kit_TruthMuxVar( pDec, pDec0, pDec1, nVars, iVar ); - - // find any true assignments of the decomposed functions - TrueMint0 = Kit_TruthFindFirstBit( pDec0, nVars ); - TrueMint1 = Kit_TruthFindFirstBit( pDec1, nVars ); - assert( TrueMint0 >= 0 && TrueMint1 >= 0 ); - // find any false assignments of the decomposed functions - FalseMint0 = Kit_TruthFindFirstZero( pDec0, nVars ); - FalseMint1 = Kit_TruthFindFirstZero( pDec1, nVars ); - assert( FalseMint0 >= 0 && FalseMint1 >= 0 ); - - // cofactor the cofactors according to these minterms - Kit_TruthCopy( pCo00, pCof0, nVars ); - Kit_TruthCopy( pCo01, pCof0, nVars ); - for ( i = 0; i < nVars; i++ ) - if ( uSubset0 & (1 << i) ) - { - if ( FalseMint0 & (1 << i) ) - Kit_TruthCofactor1( pCo00, nVars, i ); - else - Kit_TruthCofactor0( pCo00, nVars, i ); - if ( TrueMint0 & (1 << i) ) - Kit_TruthCofactor1( pCo01, nVars, i ); - else - Kit_TruthCofactor0( pCo01, nVars, i ); - } - Kit_TruthCopy( pCo10, pCof1, nVars ); - Kit_TruthCopy( pCo11, pCof1, nVars ); - for ( i = 0; i < nVars; i++ ) - if ( uSubset1 & (1 << i) ) - { - if ( FalseMint1 & (1 << i) ) - Kit_TruthCofactor1( pCo10, nVars, i ); - else - Kit_TruthCofactor0( pCo10, nVars, i ); - if ( TrueMint1 & (1 << i) ) - Kit_TruthCofactor1( pCo11, nVars, i ); - else - Kit_TruthCofactor0( pCo11, nVars, i ); - } - - // derive the functions by composing them with the new variable (iVarReused) - Kit_TruthMuxVar( pCo0, pCo00, pCo01, nVars, iVarReused ); - Kit_TruthMuxVar( pCo1, pCo10, pCo11, nVars, iVarReused ); -//Kit_DsdPrintFromTruth( pCo0, nVars ); -//Kit_DsdPrintFromTruth( pCo1, nVars ); - - // derive the composition function - Kit_TruthMuxVar( pCo , pCo0 , pCo1 , nVars, iVar ); - - // process the decomposed function - pNtkDec = Kit_DsdDecompose( pDec, nVars ); - pNtkComp = Kit_DsdDecompose( pCo, nVars ); -//Kit_DsdPrint( stdout, pNtkDec ); -//Kit_DsdPrint( stdout, pNtkComp ); -//printf( "cofactored variable %c\n", 'a' + iVar ); -//printf( "reused variable %c\n", 'a' + iVarReused ); - - ppLeaves[iVarReused] = Lpk_MapTree_rec( p, pNtkDec, ppLeaves, pNtkDec->Root, NULL ); - pObjNew = Lpk_MapTree_rec( p, pNtkComp, ppLeaves, pNtkComp->Root, NULL ); - - Kit_DsdNtkFree( pNtkDec ); - Kit_DsdNtkFree( pNtkComp ); - return pObjNew; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/lpkSets.c b/src/opt/lpk/lpkSets.c deleted file mode 100644 index 90e46863..00000000 --- a/src/opt/lpk/lpkSets.c +++ /dev/null @@ -1,440 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpkSets.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpkSets.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "lpkInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Lpk_Set_t_ Lpk_Set_t; -struct Lpk_Set_t_ -{ - char iVar; // the cofactoring variable - char Over; // the overlap in supports - char SRed; // the support reduction - char Size; // the size of the boundset - unsigned uSubset0; // the first subset (with removed) - unsigned uSubset1; // the second subset (with removed) -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Recursively computes decomposable subsets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Lpk_ComputeSets_rec( Kit_DsdNtk_t * p, int iLit, Vec_Int_t * vSets ) -{ - unsigned i, iLitFanin, uSupport, uSuppCur; - Kit_DsdObj_t * pObj; - // consider the case of simple gate - pObj = Kit_DsdNtkObj( p, Kit_DsdLit2Var(iLit) ); - if ( pObj == NULL ) - return (1 << Kit_DsdLit2Var(iLit)); - if ( pObj->Type == KIT_DSD_AND || pObj->Type == KIT_DSD_XOR ) - { - unsigned uSupps[16], Limit, s; - uSupport = 0; - Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) - { - uSupps[i] = Lpk_ComputeSets_rec( p, iLitFanin, vSets ); - uSupport |= uSupps[i]; - } - // create all subsets, except empty and full - Limit = (1 << pObj->nFans) - 1; - for ( s = 1; s < Limit; s++ ) - { - uSuppCur = 0; - for ( i = 0; i < pObj->nFans; i++ ) - if ( s & (1 << i) ) - uSuppCur |= uSupps[i]; - Vec_IntPush( vSets, uSuppCur ); - } - return uSupport; - } - assert( pObj->Type == KIT_DSD_PRIME ); - // get the cumulative support of all fanins - uSupport = 0; - Kit_DsdObjForEachFanin( p, pObj, iLitFanin, i ) - { - uSuppCur = Lpk_ComputeSets_rec( p, iLitFanin, vSets ); - uSupport |= uSuppCur; - Vec_IntPush( vSets, uSuppCur ); - } - return uSupport; -} - -/**Function************************************************************* - - Synopsis [Computes the set of subsets of decomposable variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Lpk_ComputeSets( Kit_DsdNtk_t * p, Vec_Int_t * vSets ) -{ - unsigned uSupport, Entry; - int Number, i; - assert( p->nVars <= 16 ); - Vec_IntClear( vSets ); - Vec_IntPush( vSets, 0 ); - if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_CONST1 ) - return 0; - if ( Kit_DsdNtkRoot(p)->Type == KIT_DSD_VAR ) - { - uSupport = ( 1 << Kit_DsdLit2Var(Kit_DsdNtkRoot(p)->pFans[0]) ); - Vec_IntPush( vSets, uSupport ); - return uSupport; - } - uSupport = Lpk_ComputeSets_rec( p, p->Root, vSets ); - assert( (uSupport & 0xFFFF0000) == 0 ); - Vec_IntPush( vSets, uSupport ); - // set the remaining variables - Vec_IntForEachEntry( vSets, Number, i ) - { - Entry = Number; - Vec_IntWriteEntry( vSets, i, Entry | ((uSupport & ~Entry) << 16) ); - } - return uSupport; -} - -/**Function************************************************************* - - Synopsis [Prints the sets of subsets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Lpk_PrintSetOne( int uSupport ) -{ - unsigned k; - for ( k = 0; k < 16; k++ ) - if ( uSupport & (1<> 16) ); - // get the support reduction - nSuppRed = nSuppSize - 1 - nSuppOver; - // only consider support-reducing subsets - if ( nSuppRed <= 0 ) - continue; - // check if this support is already used - if ( TravId[uSupp] < nTravId ) - { - Used[nUsed++] = uSupp; - - TravId[uSupp] = nTravId; - SRed[uSupp] = nSuppRed; - Over[uSupp] = nSuppOver; - Parents[uSupp] = (k << 16) | i; - } - else if ( TravId[uSupp] == nTravId && SRed[uSupp] < nSuppRed ) - { - TravId[uSupp] = nTravId; - SRed[uSupp] = nSuppRed; - Over[uSupp] = nSuppOver; - Parents[uSupp] = (k << 16) | i; - } - } - - // find the minimum overlap - nMinOver = 1000; - for ( s = 0; s < nUsed; s++ ) - if ( nMinOver > Over[Used[s]] ) - nMinOver = Over[Used[s]]; - - - // collect the accumulated ones - for ( s = 0; s < nUsed; s++ ) - if ( Over[Used[s]] == nMinOver ) - { - // save the entry - if ( *pSize == nSizeLimit ) - return; - pEntry = pStore + (*pSize)++; - - i = Parents[Used[s]] & 0xFFFF; - k = Parents[Used[s]] >> 16; - - pEntry->uSubset0 = Vec_IntEntry(vSets0, i); - pEntry->uSubset1 = Vec_IntEntry(vSets1, k); - Entry = pEntry->uSubset0 | pEntry->uSubset1; - - // record the cofactoring variable - pEntry->iVar = iCofVar; - // set the bound set size - pEntry->Size = Kit_WordCountOnes( Entry & 0xFFFF ); - // get the number of overlapping vars - pEntry->Over = Kit_WordCountOnes( Entry & (Entry >> 16) ); - // get the support reduction - pEntry->SRed = pEntry->Size - 1 - pEntry->Over; - assert( pEntry->SRed > 0 ); - } -} - -/**Function************************************************************* - - Synopsis [Prints one set.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Lpk_MapSuppPrintSet( Lpk_Set_t * pSet, int i ) -{ - unsigned Entry; - Entry = pSet->uSubset0 | pSet->uSubset1; - printf( "%2d : ", i ); - printf( "Var = %c ", 'a' + pSet->iVar ); - printf( "Size = %2d ", pSet->Size ); - printf( "Over = %2d ", pSet->Over ); - printf( "SRed = %2d ", pSet->SRed ); - Lpk_PrintSetOne( Entry ); - printf( " " ); - Lpk_PrintSetOne( Entry >> 16 ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Evaluates the cofactors.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned Lpk_MapSuppRedDecSelect( Lpk_Man_t * p, unsigned * pTruth, int nVars, int * piVar, int * piVarReused ) -{ - static int nStoreSize = 256; - static Lpk_Set_t pStore[256], * pSet, * pSetBest; - Kit_DsdNtk_t * ppNtks[2], * pTemp; - Vec_Int_t * vSets0 = p->vSets[0]; - Vec_Int_t * vSets1 = p->vSets[1]; - unsigned * pCof0 = Vec_PtrEntry( p->vTtNodes, 0 ); - unsigned * pCof1 = Vec_PtrEntry( p->vTtNodes, 1 ); - int nSets, i, SizeMax;//, SRedMax; - unsigned Entry; - int fVerbose = p->pPars->fVeryVerbose; -// int fVerbose = 0; - - // collect decomposable subsets for each pair of cofactors - if ( fVerbose ) - { - printf( "\nExploring support-reducing bound-sets of function:\n" ); - Kit_DsdPrintFromTruth( pTruth, nVars ); - } - nSets = 0; - for ( i = 0; i < nVars; i++ ) - { - if ( fVerbose ) - printf( "Evaluating variable %c:\n", 'a'+i ); - // evaluate the cofactor pair - Kit_TruthCofactor0New( pCof0, pTruth, nVars, i ); - Kit_TruthCofactor1New( pCof1, pTruth, nVars, i ); - // decompose and expand - ppNtks[0] = Kit_DsdDecompose( pCof0, nVars ); - ppNtks[1] = Kit_DsdDecompose( pCof1, nVars ); - ppNtks[0] = Kit_DsdExpand( pTemp = ppNtks[0] ); Kit_DsdNtkFree( pTemp ); - ppNtks[1] = Kit_DsdExpand( pTemp = ppNtks[1] ); Kit_DsdNtkFree( pTemp ); - if ( fVerbose ) - Kit_DsdPrint( stdout, ppNtks[0] ); - if ( fVerbose ) - Kit_DsdPrint( stdout, ppNtks[1] ); - // compute subsets - Lpk_ComputeSets( ppNtks[0], vSets0 ); - Lpk_ComputeSets( ppNtks[1], vSets1 ); - // print subsets - if ( fVerbose ) - Lpk_PrintSets( vSets0 ); - if ( fVerbose ) - Lpk_PrintSets( vSets1 ); - // free the networks - Kit_DsdNtkFree( ppNtks[0] ); - Kit_DsdNtkFree( ppNtks[1] ); - // evaluate the pair - Lpk_ComposeSets( vSets0, vSets1, nVars, i, pStore, &nSets, nStoreSize ); - } - - // print the results - if ( fVerbose ) - printf( "\n" ); - if ( fVerbose ) - for ( i = 0; i < nSets; i++ ) - Lpk_MapSuppPrintSet( pStore + i, i ); - - // choose the best subset - SizeMax = 0; - pSetBest = NULL; - for ( i = 0; i < nSets; i++ ) - { - pSet = pStore + i; - if ( pSet->Size > p->pPars->nLutSize - 1 ) - continue; - if ( SizeMax < pSet->Size ) - { - pSetBest = pSet; - SizeMax = pSet->Size; - } - } -/* - // if the best is not choosen, select the one with largest reduction - SRedMax = 0; - if ( pSetBest == NULL ) - { - for ( i = 0; i < nSets; i++ ) - { - pSet = pStore + i; - if ( SRedMax < pSet->SRed ) - { - pSetBest = pSet; - SRedMax = pSet->SRed; - } - } - } -*/ - if ( pSetBest == NULL ) - { - if ( fVerbose ) - printf( "Could not select a subset.\n" ); - return 0; - } - else - { - if ( fVerbose ) - printf( "Selected the following subset:\n" ); - if ( fVerbose ) - Lpk_MapSuppPrintSet( pSetBest, pSetBest - pStore ); - } - - // prepare the return result - // get the remaining variables - Entry = ((pSetBest->uSubset0 >> 16) | (pSetBest->uSubset1 >> 16)); - // get the variables to be removed - Entry = Kit_BitMask(nVars) & ~(1<iVar) & ~Entry; - // make sure there are some - otherwise it is not supp-red - assert( Entry ); - // remember the first such variable - *piVarReused = Kit_WordFindFirstBit( Entry ); - *piVar = pSetBest->iVar; - return (pSetBest->uSubset1 << 16) | (pSetBest->uSubset0 & 0xFFFF); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/lpk_.c b/src/opt/lpk/lpk_.c deleted file mode 100644 index d8555e08..00000000 --- a/src/opt/lpk/lpk_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [lpk_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Fast Boolean matching for LUT structures.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - April 28, 2007.] - - Revision [$Id: lpk_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "lpkInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/lpk/module.make b/src/opt/lpk/module.make deleted file mode 100644 index 26a54894..00000000 --- a/src/opt/lpk/module.make +++ /dev/null @@ -1,11 +0,0 @@ -SRC += src/opt/lpk/lpkCore.c \ - src/opt/lpk/lpkAbcDec.c \ - src/opt/lpk/lpkAbcMux.c \ - src/opt/lpk/lpkAbcDsd.c \ - src/opt/lpk/lpkAbcUtil.c \ - src/opt/lpk/lpkCut.c \ - src/opt/lpk/lpkMan.c \ - src/opt/lpk/lpkMap.c \ - src/opt/lpk/lpkMulti.c \ - src/opt/lpk/lpkMux.c \ - src/opt/lpk/lpkSets.c diff --git a/src/opt/res/module.make b/src/opt/res/module.make deleted file mode 100644 index 52d8a315..00000000 --- a/src/opt/res/module.make +++ /dev/null @@ -1,7 +0,0 @@ -SRC += src/opt/res/resCore.c \ - src/opt/res/resDivs.c \ - src/opt/res/resFilter.c \ - src/opt/res/resSat.c \ - src/opt/res/resSim.c \ - src/opt/res/resStrash.c \ - src/opt/res/resWin.c diff --git a/src/opt/res/res.h b/src/opt/res/res.h deleted file mode 100644 index 3c3431bf..00000000 --- a/src/opt/res/res.h +++ /dev/null @@ -1,75 +0,0 @@ -/**CFile**************************************************************** - - FileName [res.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resynthesis package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: res.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __RES_H__ -#define __RES_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Res_Par_t_ Res_Par_t; -struct Res_Par_t_ -{ - // general parameters - int nWindow; // window size - int nGrowthLevel; // the maximum allowed growth in level after one iteration of resynthesis - int nSimWords; // the number of simulation words - int nCands; // the number of candidates to try - int fArea; // performs optimization for area - int fDelay; // performs optimization for delay - int fVerbose; // enable basic stats - int fVeryVerbose; // enable detailed stats -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== resCore.c ==========================================================*/ -extern int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars ); - - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/res/resCore.c b/src/opt/res/resCore.c deleted file mode 100644 index 27e9b3ea..00000000 --- a/src/opt/res/resCore.c +++ /dev/null @@ -1,415 +0,0 @@ -/**CFile**************************************************************** - - FileName [resCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resynthesis package.] - - Synopsis [Top-level resynthesis procedure.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: resCore.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "resInt.h" -#include "kit.h" -#include "satStore.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Res_Man_t_ Res_Man_t; -struct Res_Man_t_ -{ - // general parameters - Res_Par_t * pPars; - // specialized manager - Res_Win_t * pWin; // windowing manager - Abc_Ntk_t * pAig; // the strashed window - Res_Sim_t * pSim; // simulation manager - Sto_Man_t * pCnf; // the CNF of the SAT problem - Int_Man_t * pMan; // interpolation manager; - Vec_Int_t * vMem; // memory for intermediate SOPs - Vec_Vec_t * vResubs; // resubstitution candidates of the AIG - Vec_Vec_t * vResubsW; // resubstitution candidates of the window - Vec_Vec_t * vLevels; // levelized structure for updating - // statistics - int nWins; // the number of windows tried - int nWinNodes; // the total number of window nodes - int nDivNodes; // the total number of divisors - int nWinsTriv; // the total number of trivial windows - int nWinsUsed; // the total number of useful windows (with at least one candidate) - int nConstsUsed; // the total number of constant nodes under ODC - int nCandSets; // the total number of candidates - int nProvedSets; // the total number of proved groups - int nSimEmpty; // the empty simulation info - int nTotalNets; // the total number of nets - int nTotalNodes; // the total number of nodess - int nTotalNets2; // the total number of nets - int nTotalNodes2; // the total number of nodess - // runtime - int timeWin; // windowing - int timeDiv; // divisors - int timeAig; // strashing - int timeSim; // simulation - int timeCand; // resubstitution candidates - int timeSatTotal; // SAT solving total - int timeSatSat; // SAT solving (sat calls) - int timeSatUnsat; // SAT solving (unsat calls) - int timeSatSim; // SAT solving (simulation) - int timeInt; // interpolation - int timeUpd; // updating - int timeTotal; // total runtime -}; - -extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); - -extern int s_ResynTime; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocate resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Res_Man_t * Res_ManAlloc( Res_Par_t * pPars ) -{ - Res_Man_t * p; - p = ALLOC( Res_Man_t, 1 ); - memset( p, 0, sizeof(Res_Man_t) ); - assert( pPars->nWindow > 0 && pPars->nWindow < 100 ); - assert( pPars->nCands > 0 && pPars->nCands < 100 ); - p->pPars = pPars; - p->pWin = Res_WinAlloc(); - p->pSim = Res_SimAlloc( pPars->nSimWords ); - p->pMan = Int_ManAlloc( 512 ); - p->vMem = Vec_IntAlloc( 0 ); - p->vResubs = Vec_VecStart( pPars->nCands ); - p->vResubsW = Vec_VecStart( pPars->nCands ); - p->vLevels = Vec_VecStart( 32 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocate resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_ManFree( Res_Man_t * p ) -{ - if ( p->pPars->fVerbose ) - { - printf( "Reduction in nodes = %5d. (%.2f %%) ", - p->nTotalNodes-p->nTotalNodes2, - 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes ); - printf( "Reduction in edges = %5d. (%.2f %%) ", - p->nTotalNets-p->nTotalNets2, - 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets ); - printf( "\n" ); - - printf( "Winds = %d. ", p->nWins ); - printf( "Nodes = %d. (Ave = %5.1f) ", p->nWinNodes, 1.0*p->nWinNodes/p->nWins ); - printf( "Divs = %d. (Ave = %5.1f) ", p->nDivNodes, 1.0*p->nDivNodes/p->nWins ); - printf( "\n" ); - printf( "WinsTriv = %d. ", p->nWinsTriv ); - printf( "SimsEmpt = %d. ", p->nSimEmpty ); - printf( "Const = %d. ", p->nConstsUsed ); - printf( "WindUsed = %d. ", p->nWinsUsed ); - printf( "Cands = %d. ", p->nCandSets ); - printf( "Proved = %d.", p->nProvedSets ); - printf( "\n" ); - - PRTP( "Windowing ", p->timeWin, p->timeTotal ); - PRTP( "Divisors ", p->timeDiv, p->timeTotal ); - PRTP( "Strashing ", p->timeAig, p->timeTotal ); - PRTP( "Simulation ", p->timeSim, p->timeTotal ); - PRTP( "Candidates ", p->timeCand, p->timeTotal ); - PRTP( "SAT solver ", p->timeSatTotal, p->timeTotal ); - PRTP( " sat ", p->timeSatSat, p->timeTotal ); - PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); - PRTP( " simul ", p->timeSatSim, p->timeTotal ); - PRTP( "Interpol ", p->timeInt, p->timeTotal ); - PRTP( "Undating ", p->timeUpd, p->timeTotal ); - PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); - } - Res_WinFree( p->pWin ); - if ( p->pAig ) Abc_NtkDelete( p->pAig ); - Res_SimFree( p->pSim ); - if ( p->pCnf ) Sto_ManFree( p->pCnf ); - Int_ManFree( p->pMan ); - Vec_IntFree( p->vMem ); - Vec_VecFree( p->vResubs ); - Vec_VecFree( p->vResubsW ); - Vec_VecFree( p->vLevels ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Incrementally updates level of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels ) -{ - Abc_Obj_t * pObjNew, * pFanin; - int k; - // create the new node - pObjNew = Abc_NtkCreateNode( pObj->pNtk ); - pObjNew->pData = pFunc; - Vec_PtrForEachEntry( vFanins, pFanin, k ) - Abc_ObjAddFanin( pObjNew, pFanin ); - // replace the old node by the new node - // update the level of the node - Abc_NtkUpdate( pObj, pObjNew, vLevels ); -} - -/**Function************************************************************* - - Synopsis [Entrace into the resynthesis package.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars ) -{ - ProgressBar * pProgress; - Res_Man_t * p; - Abc_Obj_t * pObj; - Hop_Obj_t * pFunc; - Kit_Graph_t * pGraph; - Vec_Ptr_t * vFanins; - unsigned * puTruth; - int i, k, RetValue, nNodesOld, nFanins, nFaninsMax; - int clk, clkTotal = clock(); - - // start the manager - p = Res_ManAlloc( pPars ); - p->nTotalNets = Abc_NtkGetTotalFanins(pNtk); - p->nTotalNodes = Abc_NtkNodeNum(pNtk); - nFaninsMax = Abc_NtkGetFaninMax(pNtk); - - // perform the network sweep - Abc_NtkSweep( pNtk, 0 ); - - // convert into the AIG - if ( !Abc_NtkToAig(pNtk) ) - { - fprintf( stdout, "Converting to BDD has failed.\n" ); - Res_ManFree( p ); - return 0; - } - assert( Abc_NtkHasAig(pNtk) ); - - // set the number of levels - Abc_NtkLevel( pNtk ); - Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); - - // try resynthesizing nodes in the topological order - nNodesOld = Abc_NtkObjNumMax(pNtk); - pProgress = Extra_ProgressBarStart( stdout, nNodesOld ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - Extra_ProgressBarUpdate( pProgress, i, NULL ); - if ( !Abc_ObjIsNode(pObj) ) - continue; - if ( pObj->Id > nNodesOld ) - break; - - // create the window for this node -clk = clock(); - RetValue = Res_WinCompute( pObj, p->pPars->nWindow/10, p->pPars->nWindow%10, p->pWin ); -p->timeWin += clock() - clk; - if ( !RetValue ) - continue; - p->nWinsTriv += Res_WinIsTrivial( p->pWin ); - - if ( p->pPars->fVeryVerbose ) - { - printf( "%5d (lev=%2d) : ", pObj->Id, pObj->Level ); - printf( "Win = %3d/%3d/%4d/%3d ", - Vec_PtrSize(p->pWin->vLeaves), - Vec_PtrSize(p->pWin->vBranches), - Vec_PtrSize(p->pWin->vNodes), - Vec_PtrSize(p->pWin->vRoots) ); - } - - // collect the divisors -clk = clock(); - Res_WinDivisors( p->pWin, Abc_ObjRequiredLevel(pObj) - 1 ); -p->timeDiv += clock() - clk; - - p->nWins++; - p->nWinNodes += Vec_PtrSize(p->pWin->vNodes); - p->nDivNodes += Vec_PtrSize( p->pWin->vDivs); - - if ( p->pPars->fVeryVerbose ) - { - printf( "D = %3d ", Vec_PtrSize(p->pWin->vDivs) ); - printf( "D+ = %3d ", p->pWin->nDivsPlus ); - } - - // create the AIG for the window -clk = clock(); - if ( p->pAig ) Abc_NtkDelete( p->pAig ); - p->pAig = Res_WndStrash( p->pWin ); -p->timeAig += clock() - clk; - - if ( p->pPars->fVeryVerbose ) - { - printf( "AIG = %4d ", Abc_NtkNodeNum(p->pAig) ); - printf( "\n" ); - } - - // prepare simulation info -clk = clock(); - RetValue = Res_SimPrepare( p->pSim, p->pAig, Vec_PtrSize(p->pWin->vLeaves), 0 ); //p->pPars->fVerbose ); -p->timeSim += clock() - clk; - if ( !RetValue ) - { - p->nSimEmpty++; - continue; - } - - // consider the case of constant node - if ( p->pSim->fConst0 || p->pSim->fConst1 ) - { - p->nConstsUsed++; - - pFunc = p->pSim->fConst1? Hop_ManConst1(pNtk->pManFunc) : Hop_ManConst0(pNtk->pManFunc); - vFanins = Vec_VecEntry( p->vResubsW, 0 ); - Vec_PtrClear( vFanins ); - Res_UpdateNetwork( pObj, vFanins, pFunc, p->vLevels ); - continue; - } - -// printf( " " ); - - // find resub candidates for the node -clk = clock(); - if ( p->pPars->fArea ) - RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 1 ); - else - RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 0 ); -p->timeCand += clock() - clk; - p->nCandSets += RetValue; - if ( RetValue == 0 ) - continue; - -// printf( "%d(%d) ", Vec_PtrSize(p->pWin->vDivs), RetValue ); - - p->nWinsUsed++; - - // iterate through candidate resubstitutions - Vec_VecForEachLevel( p->vResubs, vFanins, k ) - { - if ( Vec_PtrSize(vFanins) == 0 ) - break; - - // solve the SAT problem and get clauses -clk = clock(); - if ( p->pCnf ) Sto_ManFree( p->pCnf ); - p->pCnf = Res_SatProveUnsat( p->pAig, vFanins ); - if ( p->pCnf == NULL ) - { -p->timeSatSat += clock() - clk; -// printf( " Sat\n" ); -// printf( "-" ); - continue; - } -p->timeSatUnsat += clock() - clk; -// printf( "+" ); - - p->nProvedSets++; -// printf( " Unsat\n" ); -// continue; -// printf( "Proved %d.\n", k ); - - // write it into a file -// Sto_ManDumpClauses( p->pCnf, "trace.cnf" ); - - // interpolate the problem if it was UNSAT -clk = clock(); - nFanins = Int_ManInterpolate( p->pMan, p->pCnf, 0, &puTruth ); -p->timeInt += clock() - clk; - if ( nFanins != Vec_PtrSize(vFanins) - 2 ) - continue; - assert( puTruth ); -// Extra_PrintBinary( stdout, puTruth, 1 << nFanins ); printf( "\n" ); - - // transform interpolant into the AIG - pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem ); - - // derive the AIG for the decomposition tree - pFunc = Kit_GraphToHop( pNtk->pManFunc, pGraph ); - Kit_GraphFree( pGraph ); - - // update the network -clk = clock(); - Res_UpdateNetwork( pObj, Vec_VecEntry(p->vResubsW, k), pFunc, p->vLevels ); -p->timeUpd += clock() - clk; - break; - } -// printf( "\n" ); - } - Extra_ProgressBarStop( pProgress ); - Abc_NtkStopReverseLevels( pNtk ); - -p->timeSatSim += p->pSim->timeSat; -p->timeSatTotal = p->timeSatSat + p->timeSatUnsat + p->timeSatSim; - - p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk); - p->nTotalNodes2 = Abc_NtkNodeNum(pNtk); - - // quit resubstitution manager -p->timeTotal = clock() - clkTotal; - Res_ManFree( p ); - -s_ResynTime += clock() - clkTotal; - // check the resulting network - if ( !Abc_NtkCheck( pNtk ) ) - { - fprintf( stdout, "Abc_NtkResynthesize(): Network check has failed.\n" ); - return 0; - } - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/res/resDivs.c b/src/opt/res/resDivs.c deleted file mode 100644 index cc75b90f..00000000 --- a/src/opt/res/resDivs.c +++ /dev/null @@ -1,285 +0,0 @@ -/**CFile**************************************************************** - - FileName [resDivs.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resynthesis package.] - - Synopsis [Collect divisors for the given window.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: resDivs.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "resInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Res_WinMarkTfi( Res_Win_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Adds candidate divisors of the node to its window.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_WinDivisors( Res_Win_t * p, int nLevDivMax ) -{ - Abc_Obj_t * pObj, * pFanout, * pFanin; - int k, f, m; - - // set the maximum level of the divisors - p->nLevDivMax = nLevDivMax; - - // mark the TFI with the current trav ID - Abc_NtkIncrementTravId( p->pNode->pNtk ); - Res_WinMarkTfi( p ); - - // mark with the current trav ID those nodes that should not be divisors: - // (1) the node and its TFO - // (2) the MFFC of the node - // (3) the node's fanins (these are treated as a special case) - Abc_NtkIncrementTravId( p->pNode->pNtk ); - Res_WinSweepLeafTfo_rec( p->pNode, p->nLevDivMax ); - Res_WinVisitMffc( p->pNode ); - Abc_ObjForEachFanin( p->pNode, pObj, k ) - Abc_NodeSetTravIdCurrent( pObj ); - - // at this point the nodes are marked with two trav IDs: - // nodes to be collected as divisors are marked with previous trav ID - // nodes to be avoided as divisors are marked with current trav ID - - // start collecting the divisors - Vec_PtrClear( p->vDivs ); - Vec_PtrForEachEntry( p->vLeaves, pObj, k ) - { - assert( (int)pObj->Level >= p->nLevLeafMin ); - if ( !Abc_NodeIsTravIdPrevious(pObj) ) - continue; - if ( (int)pObj->Level > p->nLevDivMax ) - continue; - Vec_PtrPush( p->vDivs, pObj ); - } - // add the internal nodes to the data structure - Vec_PtrForEachEntry( p->vNodes, pObj, k ) - { - if ( !Abc_NodeIsTravIdPrevious(pObj) ) - continue; - if ( (int)pObj->Level > p->nLevDivMax ) - continue; - Vec_PtrPush( p->vDivs, pObj ); - } - - // explore the fanouts of already collected divisors - p->nDivsPlus = 0; - Vec_PtrForEachEntry( p->vDivs, pObj, k ) - { - // consider fanouts of this node - Abc_ObjForEachFanout( pObj, pFanout, f ) - { - // stop if there are too many fanouts - if ( f > 20 ) - break; - // skip nodes that are already added - if ( Abc_NodeIsTravIdPrevious(pFanout) ) - continue; - // skip nodes in the TFO or in the MFFC of node - if ( Abc_NodeIsTravIdCurrent(pFanout) ) - continue; - // skip COs - if ( !Abc_ObjIsNode(pFanout) ) - continue; - // skip nodes with large level - if ( (int)pFanout->Level >= p->nLevDivMax ) - continue; - // skip nodes whose fanins are not divisors - Abc_ObjForEachFanin( pFanout, pFanin, m ) - if ( !Abc_NodeIsTravIdPrevious(pFanin) ) - break; - if ( m < Abc_ObjFaninNum(pFanout) ) - continue; - // add the node to the divisors - Vec_PtrPush( p->vDivs, pFanout ); - Vec_PtrPush( p->vNodes, pFanout ); - Abc_NodeSetTravIdPrevious( pFanout ); - p->nDivsPlus++; - } - } -/* - printf( "Node level = %d. ", Abc_ObjLevel(p->pNode) ); - Vec_PtrForEachEntryStart( p->vDivs, pObj, k, Vec_PtrSize(p->vDivs)-p->nDivsPlus ) - printf( "%d ", Abc_ObjLevel(pObj) ); - printf( "\n" ); -*/ -//printf( "%d ", p->nDivsPlus ); -} - -/**Function************************************************************* - - Synopsis [Marks the TFI cone of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_WinMarkTfi_rec( Res_Win_t * p, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i; - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return; - Abc_NodeSetTravIdCurrent( pObj ); - assert( Abc_ObjIsNode(pObj) ); - // visit the fanins of the node - Abc_ObjForEachFanin( pObj, pFanin, i ) - Res_WinMarkTfi_rec( p, pFanin ); -} - -/**Function************************************************************* - - Synopsis [Marks the TFI cone of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_WinMarkTfi( Res_Win_t * p ) -{ - Abc_Obj_t * pObj; - int i; - // mark the leaves - Vec_PtrForEachEntry( p->vLeaves, pObj, i ) - Abc_NodeSetTravIdCurrent( pObj ); - // start from the node - Res_WinMarkTfi_rec( p, p->pNode ); -} - -/**Function************************************************************* - - Synopsis [Marks the TFO of the collected nodes up to the given level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit ) -{ - Abc_Obj_t * pFanout; - int i; - if ( Abc_ObjIsCo(pObj) || (int)pObj->Level > nLevelLimit ) - return; - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return; - Abc_NodeSetTravIdCurrent( pObj ); - Abc_ObjForEachFanout( pObj, pFanout, i ) - Res_WinSweepLeafTfo_rec( pFanout, nLevelLimit ); -} - -/**Function************************************************************* - - Synopsis [Dereferences the node's MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_NodeDeref_rec( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin; - int i, Counter = 1; - if ( Abc_ObjIsCi(pNode) ) - return 0; - Abc_NodeSetTravIdCurrent( pNode ); - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - assert( pFanin->vFanouts.nSize > 0 ); - if ( --pFanin->vFanouts.nSize == 0 ) - Counter += Res_NodeDeref_rec( pFanin ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [References the node's MFFC.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_NodeRef_rec( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin; - int i, Counter = 1; - if ( Abc_ObjIsCi(pNode) ) - return 0; - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - if ( pFanin->vFanouts.nSize++ == 0 ) - Counter += Res_NodeRef_rec( pFanin ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Labels MFFC of the node with the current trav ID.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_WinVisitMffc( Abc_Obj_t * pNode ) -{ - int Count1, Count2; - assert( Abc_ObjIsNode(pNode) ); - // dereference the node (mark with the current trav ID) - Count1 = Res_NodeDeref_rec( pNode ); - // reference it back - Count2 = Res_NodeRef_rec( pNode ); - assert( Count1 == Count2 ); - return Count1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/res/resFilter.c b/src/opt/res/resFilter.c deleted file mode 100644 index f2ca41d3..00000000 --- a/src/opt/res/resFilter.c +++ /dev/null @@ -1,434 +0,0 @@ -/**CFile**************************************************************** - - FileName [resFilter.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resynthesis package.] - - Synopsis [Filtering resubstitution candidates.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: resFilter.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "resInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask ); -static int Res_FilterCriticalFanin( Abc_Obj_t * pNode ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Finds sets of feasible candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea ) -{ - Abc_Obj_t * pFanin, * pFanin2, * pFaninTemp; - unsigned * pInfo, * pInfoDiv, * pInfoDiv2; - int Counter, RetValue, i, i2, d, d2, iDiv, iDiv2, k; - - // check that the info the node is one - pInfo = Vec_PtrEntry( pSim->vOuts, 1 ); - RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); - if ( RetValue == 0 ) - { -// printf( "Failed 1!\n" ); - return 0; - } - - // collect the fanin info - pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 ); - RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); - if ( RetValue == 0 ) - { -// printf( "Failed 2!\n" ); - return 0; - } - - // try removing each fanin -// printf( "Fanins: " ); - Counter = 0; - Vec_VecClear( vResubs ); - Vec_VecClear( vResubsW ); - Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) - { - if ( fArea && Abc_ObjFanoutNum(pFanin) > 1 ) - continue; - // get simulation info without this fanin - pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) ); - RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); - if ( RetValue ) - { -// printf( "Node %4d. Candidate fanin %4d.\n", pWin->pNode->Id, pFanin->Id ); - // collect the nodes - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); - Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) - { - if ( k != i ) - { - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); - Vec_VecPush( vResubsW, Counter, pFaninTemp ); - } - } - Counter++; - if ( Counter == Vec_VecSize(vResubs) ) - return Counter; - } - } - - // try replacing each critical fanin by a non-critical fanin - Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) - { - if ( Abc_ObjFanoutNum(pFanin) > 1 ) - continue; - // get simulation info without this fanin - pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) ); - // go over the set of divisors - for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) - { - pInfoDiv = Vec_PtrEntry( pSim->vOuts, d ); - iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); - if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) ) - continue; - // collect the nodes - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); - // collect the remaning fanins and the divisor - Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) - { - if ( k != i ) - { - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); - Vec_VecPush( vResubsW, Counter, pFaninTemp ); - } - } - // collect the divisor - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); - Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); - Counter++; - if ( Counter == Vec_VecSize(vResubs) ) - return Counter; - } - } - - // consider the case when two fanins can be added instead of one - if ( Abc_ObjFaninNum(pWin->pNode) < nFaninsMax ) - { - // try to replace each critical fanin by two non-critical fanins - Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) - { - if ( Abc_ObjFanoutNum(pFanin) > 1 ) - continue; - // get simulation info without this fanin - pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << i) ); - // go over the set of divisors - for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) - { - pInfoDiv = Vec_PtrEntry( pSim->vOuts, d ); - iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); - // go through the second divisor - for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ ) - { - pInfoDiv2 = Vec_PtrEntry( pSim->vOuts, d2 ); - iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2); - if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) ) - continue; - // collect the nodes - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); - // collect the remaning fanins and the divisor - Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) - { - if ( k != i ) - { - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); - Vec_VecPush( vResubsW, Counter, pFaninTemp ); - } - } - // collect the divisor - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) ); - Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); - Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) ); - Counter++; - if ( Counter == Vec_VecSize(vResubs) ) - return Counter; - } - } - } - } - - // try to replace two nets by one - if ( !fArea ) - { - Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) - { - for ( i2 = i + 1; i2 < Abc_ObjFaninNum(pWin->pNode); i2++ ) - { - pFanin2 = Abc_ObjFanin(pWin->pNode, i2); - // get simulation info without these fanins - pInfo = Res_FilterCollectFaninInfo( pWin, pSim, (~(1 << i)) & (~(1 << i2)) ); - // go over the set of divisors - for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) - { - pInfoDiv = Vec_PtrEntry( pSim->vOuts, d ); - iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); - if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) ) - continue; - // collect the nodes - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); - // collect the remaning fanins and the divisor - Abc_ObjForEachFanin( pWin->pNode, pFaninTemp, k ) - { - if ( k != i && k != i2 ) - { - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); - Vec_VecPush( vResubsW, Counter, pFaninTemp ); - } - } - // collect the divisor - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); - Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); - Counter++; - if ( Counter == Vec_VecSize(vResubs) ) - return Counter; - } - } - } - } - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Finds sets of feasible candidates.] - - Description [This procedure is a special case of the above.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax ) -{ - Abc_Obj_t * pFanin; - unsigned * pInfo, * pInfoDiv, * pInfoDiv2; - int Counter, RetValue, d, d2, k, iDiv, iDiv2, iBest; - - // check that the info the node is one - pInfo = Vec_PtrEntry( pSim->vOuts, 1 ); - RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); - if ( RetValue == 0 ) - { -// printf( "Failed 1!\n" ); - return 0; - } - - // collect the fanin info - pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~0 ); - RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); - if ( RetValue == 0 ) - { -// printf( "Failed 2!\n" ); - return 0; - } - - // try removing fanins -// printf( "Fanins: " ); - Counter = 0; - Vec_VecClear( vResubs ); - Vec_VecClear( vResubsW ); - // get the best fanins - iBest = Res_FilterCriticalFanin( pWin->pNode ); - if ( iBest == -1 ) - return 0; - - // get the info without the critical fanin - pInfo = Res_FilterCollectFaninInfo( pWin, pSim, ~(1 << iBest) ); - RetValue = Abc_InfoIsOne( pInfo, pSim->nWordsOut ); - if ( RetValue ) - { -// printf( "Can be done without one!\n" ); - // collect the nodes - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); - Abc_ObjForEachFanin( pWin->pNode, pFanin, k ) - { - if ( k != iBest ) - { - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); - Vec_VecPush( vResubsW, Counter, pFanin ); - } - } - Counter++; -// printf( "*" ); - return Counter; - } - - // go through the divisors - for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) - { - pInfoDiv = Vec_PtrEntry( pSim->vOuts, d ); - iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); - if ( !Abc_InfoIsOrOne( pInfo, pInfoDiv, pSim->nWordsOut ) ) - continue; -//if ( Abc_ObjLevel(pWin->pNode) <= Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) ) -// printf( "Node level = %d. Divisor level = %d.\n", Abc_ObjLevel(pWin->pNode), Abc_ObjLevel( Vec_PtrEntry(pWin->vDivs, iDiv) ) ); - // collect the nodes - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); - // collect the remaning fanins and the divisor - Abc_ObjForEachFanin( pWin->pNode, pFanin, k ) - { - if ( k != iBest ) - { - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); - Vec_VecPush( vResubsW, Counter, pFanin ); - } - } - // collect the divisor - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); - Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); - Counter++; - - if ( Counter == Vec_VecSize(vResubs) ) - break; - } - - if ( Counter > 0 || Abc_ObjFaninNum(pWin->pNode) >= nFaninsMax ) - return Counter; - - // try to find the node pairs - for ( d = Abc_ObjFaninNum(pWin->pNode) + 2; d < Abc_NtkPoNum(pAig); d++ ) - { - pInfoDiv = Vec_PtrEntry( pSim->vOuts, d ); - iDiv = d - (Abc_ObjFaninNum(pWin->pNode) + 2); - // go through the second divisor - for ( d2 = d + 1; d2 < Abc_NtkPoNum(pAig); d2++ ) - { - pInfoDiv2 = Vec_PtrEntry( pSim->vOuts, d2 ); - iDiv2 = d2 - (Abc_ObjFaninNum(pWin->pNode) + 2); - - if ( !Abc_InfoIsOrOne3( pInfo, pInfoDiv, pInfoDiv2, pSim->nWordsOut ) ) - continue; - // collect the nodes - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,0) ); - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,1) ); - // collect the remaning fanins and the divisor - Abc_ObjForEachFanin( pWin->pNode, pFanin, k ) - { - if ( k != iBest ) - { - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,2+k) ); - Vec_VecPush( vResubsW, Counter, pFanin ); - } - } - // collect the divisor - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d) ); - Vec_VecPush( vResubs, Counter, Abc_NtkPo(pAig,d2) ); - Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv) ); - Vec_VecPush( vResubsW, Counter, Vec_PtrEntry(pWin->vDivs, iDiv2) ); - Counter++; - - if ( Counter == Vec_VecSize(vResubs) ) - break; - } - if ( Counter == Vec_VecSize(vResubs) ) - break; - } - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Finds sets of feasible candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -unsigned * Res_FilterCollectFaninInfo( Res_Win_t * pWin, Res_Sim_t * pSim, unsigned uMask ) -{ - Abc_Obj_t * pFanin; - unsigned * pInfo; - int i; - pInfo = Vec_PtrEntry( pSim->vOuts, 0 ); - Abc_InfoClear( pInfo, pSim->nWordsOut ); - Abc_ObjForEachFanin( pWin->pNode, pFanin, i ) - { - if ( uMask & (1 << i) ) - Abc_InfoOr( pInfo, Vec_PtrEntry(pSim->vOuts, 2+i), pSim->nWordsOut ); - } - return pInfo; -} - - -/**Function************************************************************* - - Synopsis [Returns the index of the most critical fanin.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_FilterCriticalFanin( Abc_Obj_t * pNode ) -{ - Abc_Obj_t * pFanin; - int i, iBest = -1, CostMax = 0, CostCur; - Abc_ObjForEachFanin( pNode, pFanin, i ) - { - if ( !Abc_ObjIsNode(pFanin) ) - continue; - if ( Abc_ObjFanoutNum(pFanin) > 1 ) - continue; - CostCur = Res_WinVisitMffc( pFanin ); - if ( CostMax < CostCur ) - { - CostMax = CostCur; - iBest = i; - } - } -// if ( CostMax > 0 ) -// printf( "<%d>", CostMax ); - return iBest; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/res/resInt.h b/src/opt/res/resInt.h deleted file mode 100644 index 5aae46cc..00000000 --- a/src/opt/res/resInt.h +++ /dev/null @@ -1,137 +0,0 @@ -/**CFile**************************************************************** - - FileName [resInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resynthesis package.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: resInt.h,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __RES_INT_H__ -#define __RES_INT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "res.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Res_Win_t_ Res_Win_t; -struct Res_Win_t_ -{ - // windowing parameters - Abc_Obj_t * pNode; // the node in the center - int nWinTfiMax; // the fanin levels - int nWinTfoMax; // the fanout levels - int nLevDivMax; // the maximum divisor level - // internal windowing parameters - int nFanoutLimit; // the limit on the fanout count of a TFO node (if more, the node is treated as a root) - int nLevTfiMinus; // the number of additional levels to search from TFO below the level of leaves - // derived windowing parameters - int nLevLeafMin; // the minimum level of a leaf - int nLevTravMin; // the minimum level to search from TFO - int nDivsPlus; // the number of additional divisors - // the window data - Vec_Ptr_t * vRoots; // outputs of the window - Vec_Ptr_t * vLeaves; // inputs of the window - Vec_Ptr_t * vBranches; // side nodes of the window - Vec_Ptr_t * vNodes; // internal nodes of the window - Vec_Ptr_t * vDivs; // candidate divisors of the node - // temporary data - Vec_Vec_t * vMatrix; // TFI nodes below the given node -}; - -typedef struct Res_Sim_t_ Res_Sim_t; -struct Res_Sim_t_ -{ - Abc_Ntk_t * pAig; // AIG for simulation - int nTruePis; // the number of true PIs of the window - int fConst0; // the node can be replaced by constant 0 - int fConst1; // the node can be replaced by constant 0 - // simulation parameters - int nWords; // the number of simulation words - int nPats; // the number of patterns - int nWordsIn; // the number of simulation words in the input patterns - int nPatsIn; // the number of patterns in the input patterns - int nBytesIn; // the number of bytes in the input patterns - int nWordsOut; // the number of simulation words in the output patterns - int nPatsOut; // the number of patterns in the output patterns - // simulation info - Vec_Ptr_t * vPats; // input simulation patterns - Vec_Ptr_t * vPats0; // input simulation patterns - Vec_Ptr_t * vPats1; // input simulation patterns - Vec_Ptr_t * vOuts; // output simulation info - int nPats0; // the number of 0-patterns accumulated - int nPats1; // the number of 1-patterns accumulated - // resub candidates - Vec_Vec_t * vCands; // resubstitution candidates - // statistics - int timeSat; -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== resDivs.c ==========================================================*/ -extern void Res_WinDivisors( Res_Win_t * p, int nLevDivMax ); -extern void Res_WinSweepLeafTfo_rec( Abc_Obj_t * pObj, int nLevelLimit ); -extern int Res_WinVisitMffc( Abc_Obj_t * pNode ); -/*=== resFilter.c ==========================================================*/ -extern int Res_FilterCandidates( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax, int fArea ); -extern int Res_FilterCandidatesArea( Res_Win_t * pWin, Abc_Ntk_t * pAig, Res_Sim_t * pSim, Vec_Vec_t * vResubs, Vec_Vec_t * vResubsW, int nFaninsMax ); -/*=== resSat.c ==========================================================*/ -extern void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins ); -extern int Res_SatSimulate( Res_Sim_t * p, int nPats, int fOnSet ); -/*=== resSim.c ==========================================================*/ -extern Res_Sim_t * Res_SimAlloc( int nWords ); -extern void Res_SimFree( Res_Sim_t * p ); -extern int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose ); -/*=== resStrash.c ==========================================================*/ -extern Abc_Ntk_t * Res_WndStrash( Res_Win_t * p ); -/*=== resWnd.c ==========================================================*/ -extern void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels ); -/*=== resWnd.c ==========================================================*/ -extern Res_Win_t * Res_WinAlloc(); -extern void Res_WinFree( Res_Win_t * p ); -extern int Res_WinIsTrivial( Res_Win_t * p ); -extern int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p ); - - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/res/resSat.c b/src/opt/res/resSat.c deleted file mode 100644 index dd0e7a23..00000000 --- a/src/opt/res/resSat.c +++ /dev/null @@ -1,407 +0,0 @@ -/**CFile**************************************************************** - - FileName [resSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resynthesis package.] - - Synopsis [Interface with the SAT solver.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: resSat.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "resInt.h" -#include "hop.h" -#include "satSolver.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl ); -extern int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl ); -extern int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Loads AIG into the SAT solver for checking resubstitution.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Res_SatProveUnsat( Abc_Ntk_t * pAig, Vec_Ptr_t * vFanins ) -{ - void * pCnf = NULL; - sat_solver * pSat; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i, nNodes, status; - - // make sure fanins contain POs of the AIG - pObj = Vec_PtrEntry( vFanins, 0 ); - assert( pObj->pNtk == pAig && Abc_ObjIsPo(pObj) ); - - // collect reachable nodes - vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize ); - - // assign unique numbers to each node - nNodes = 0; - Abc_AigConst1(pAig)->pCopy = (void *)nNodes++; - Abc_NtkForEachPi( pAig, pObj, i ) - pObj->pCopy = (void *)nNodes++; - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pCopy = (void *)nNodes++; - Vec_PtrForEachEntry( vFanins, pObj, i ) // useful POs - pObj->pCopy = (void *)nNodes++; - - // start the solver - pSat = sat_solver_new(); - sat_solver_store_alloc( pSat ); - - // add clause for the constant node - Res_SatAddConst1( pSat, (int)Abc_AigConst1(pAig)->pCopy, 0 ); - // add clauses for AND gates - Vec_PtrForEachEntry( vNodes, pObj, i ) - Res_SatAddAnd( pSat, (int)pObj->pCopy, - (int)Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); - Vec_PtrFree( vNodes ); - // add clauses for POs - Vec_PtrForEachEntry( vFanins, pObj, i ) - Res_SatAddEqual( pSat, (int)pObj->pCopy, - (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); - // add trivial clauses - pObj = Vec_PtrEntry(vFanins, 0); - Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // care-set - pObj = Vec_PtrEntry(vFanins, 1); - Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // on-set - - // bookmark the clauses of A - sat_solver_store_mark_clauses_a( pSat ); - - // duplicate the clauses - pObj = Vec_PtrEntry(vFanins, 1); - Sat_SolverDoubleClauses( pSat, (int)pObj->pCopy ); - // add the equality constraints - Vec_PtrForEachEntryStart( vFanins, pObj, i, 2 ) - Res_SatAddEqual( pSat, (int)pObj->pCopy, ((int)pObj->pCopy) + nNodes, 0 ); - - // bookmark the roots - sat_solver_store_mark_roots( pSat ); - - // solve the problem - status = sat_solver_solve( pSat, NULL, NULL, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 ); - if ( status == l_False ) - { - pCnf = sat_solver_store_release( pSat ); -// printf( "unsat\n" ); - } - else if ( status == l_True ) - { -// printf( "sat\n" ); - } - else - { -// printf( "undef\n" ); - } - sat_solver_delete( pSat ); - return pCnf; -} - -/**Function************************************************************* - - Synopsis [Loads AIG into the SAT solver for constrained simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Res_SatSimulateConstr( Abc_Ntk_t * pAig, int fOnSet ) -{ - sat_solver * pSat; - Vec_Ptr_t * vFanins; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i, nNodes; - - // start the array - vFanins = Vec_PtrAlloc( 2 ); - pObj = Abc_NtkPo( pAig, 0 ); - Vec_PtrPush( vFanins, pObj ); - pObj = Abc_NtkPo( pAig, 1 ); - Vec_PtrPush( vFanins, pObj ); - - // collect reachable nodes - vNodes = Abc_NtkDfsNodes( pAig, (Abc_Obj_t **)vFanins->pArray, vFanins->nSize ); - - // assign unique numbers to each node - nNodes = 0; - Abc_AigConst1(pAig)->pCopy = (void *)nNodes++; - Abc_NtkForEachPi( pAig, pObj, i ) - pObj->pCopy = (void *)nNodes++; - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pCopy = (void *)nNodes++; - Vec_PtrForEachEntry( vFanins, pObj, i ) // useful POs - pObj->pCopy = (void *)nNodes++; - - // start the solver - pSat = sat_solver_new(); - - // add clause for the constant node - Res_SatAddConst1( pSat, (int)Abc_AigConst1(pAig)->pCopy, 0 ); - // add clauses for AND gates - Vec_PtrForEachEntry( vNodes, pObj, i ) - Res_SatAddAnd( pSat, (int)pObj->pCopy, - (int)Abc_ObjFanin0(pObj)->pCopy, (int)Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); - Vec_PtrFree( vNodes ); - // add clauses for the first PO - pObj = Abc_NtkPo( pAig, 0 ); - Res_SatAddEqual( pSat, (int)pObj->pCopy, - (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); - // add clauses for the second PO - pObj = Abc_NtkPo( pAig, 1 ); - Res_SatAddEqual( pSat, (int)pObj->pCopy, - (int)Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); - - // add trivial clauses - pObj = Abc_NtkPo( pAig, 0 ); - Res_SatAddConst1( pSat, (int)pObj->pCopy, 0 ); // care-set - - pObj = Abc_NtkPo( pAig, 1 ); - Res_SatAddConst1( pSat, (int)pObj->pCopy, !fOnSet ); // on-set - - Vec_PtrFree( vFanins ); - return pSat; -} - -/**Function************************************************************* - - Synopsis [Loads AIG into the SAT solver for constrained simulation.] - - Description [Returns 1 if the required number of patterns are found. - Returns 0 if the solver ran out of time or proved a constant. - In the latter, case one of the flags, fConst0 or fConst1, are set to 1.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_SatSimulate( Res_Sim_t * p, int nPatsLimit, int fOnSet ) -{ - Vec_Int_t * vLits; - Vec_Ptr_t * vPats; - sat_solver * pSat; - int RetValue, i, k, value, status, Lit, Var, iPat; - int clk = clock(); - -//printf( "Looking for %s: ", fOnSet? "onset " : "offset" ); - - // decide what problem should be solved - Lit = toLitCond( (int)Abc_NtkPo(p->pAig,1)->pCopy, !fOnSet ); - if ( fOnSet ) - { - iPat = p->nPats1; - vPats = p->vPats1; - } - else - { - iPat = p->nPats0; - vPats = p->vPats0; - } - assert( iPat < nPatsLimit ); - - // derive the SAT solver - pSat = Res_SatSimulateConstr( p->pAig, fOnSet ); - pSat->fSkipSimplify = 1; - status = sat_solver_simplify( pSat ); - if ( status == 0 ) - { - if ( iPat == 0 ) - { -// if ( fOnSet ) -// p->fConst0 = 1; -// else -// p->fConst1 = 1; - RetValue = 0; - } - goto finish; - } - - // enumerate through the SAT assignments - RetValue = 1; - vLits = Vec_IntAlloc( 32 ); - for ( k = iPat; k < nPatsLimit; k++ ) - { - // solve with the assumption -// status = sat_solver_solve( pSat, &Lit, &Lit + 1, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 ); - status = sat_solver_solve( pSat, NULL, NULL, (sint64)10000, (sint64)0, (sint64)0, (sint64)0 ); - if ( status == l_False ) - { -//printf( "Const %d\n", !fOnSet ); - if ( k == 0 ) - { - if ( fOnSet ) - p->fConst0 = 1; - else - p->fConst1 = 1; - RetValue = 0; - } - break; - } - else if ( status == l_True ) - { - // save the pattern - Vec_IntClear( vLits ); - for ( i = 0; i < p->nTruePis; i++ ) - { - Var = (int)Abc_NtkPi(p->pAig,i)->pCopy; - value = (int)(pSat->model.ptr[Var] == l_True); - if ( value ) - Abc_InfoSetBit( Vec_PtrEntry(vPats, i), k ); - Lit = toLitCond( Var, value ); - Vec_IntPush( vLits, Lit ); -// printf( "%d", value ); - } -// printf( "\n" ); - - status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ); - if ( status == 0 ) - { - k++; - RetValue = 1; - break; - } - } - else - { -//printf( "Undecided\n" ); - if ( k == 0 ) - RetValue = 0; - else - RetValue = 1; - break; - } - } - Vec_IntFree( vLits ); -//printf( "Found %d patterns\n", k - iPat ); - - // set the new number of patterns - if ( fOnSet ) - p->nPats1 = k; - else - p->nPats0 = k; - -finish: - - sat_solver_delete( pSat ); -p->timeSat += clock() - clk; - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [Asserts equality of the variable to a constant.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_SatAddConst1( sat_solver * pSat, int iVar, int fCompl ) -{ - lit Lit = toLitCond( iVar, fCompl ); - if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Asserts equality of two variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_SatAddEqual( sat_solver * pSat, int iVar0, int iVar1, int fCompl ) -{ - lit Lits[2]; - - Lits[0] = toLitCond( iVar0, 0 ); - Lits[1] = toLitCond( iVar1, !fCompl ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) - return 0; - - Lits[0] = toLitCond( iVar0, 1 ); - Lits[1] = toLitCond( iVar1, fCompl ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) - return 0; - - return 1; -} - -/**Function************************************************************* - - Synopsis [Adds constraints for the two-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_SatAddAnd( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ) -{ - lit Lits[3]; - - Lits[0] = toLitCond( iVar, 1 ); - Lits[1] = toLitCond( iVar0, fCompl0 ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) - return 0; - - Lits[0] = toLitCond( iVar, 1 ); - Lits[1] = toLitCond( iVar1, fCompl1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) - return 0; - - Lits[0] = toLitCond( iVar, 0 ); - Lits[1] = toLitCond( iVar0, !fCompl0 ); - Lits[2] = toLitCond( iVar1, !fCompl1 ); - if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) - return 0; - - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/res/resSim.c b/src/opt/res/resSim.c deleted file mode 100644 index 5c1dd2b6..00000000 --- a/src/opt/res/resSim.c +++ /dev/null @@ -1,790 +0,0 @@ -/**CFile**************************************************************** - - FileName [resSim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resynthesis package.] - - Synopsis [Simulation engine.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "resInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocate simulation engine.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Res_Sim_t * Res_SimAlloc( int nWords ) -{ - Res_Sim_t * p; - p = ALLOC( Res_Sim_t, 1 ); - memset( p, 0, sizeof(Res_Sim_t) ); - // simulation parameters - p->nWords = nWords; - p->nPats = p->nWords * 8 * sizeof(unsigned); - p->nWordsIn = p->nPats; - p->nBytesIn = p->nPats * sizeof(unsigned); - p->nPatsIn = p->nPats * 8 * sizeof(unsigned); - p->nWordsOut = p->nPats * p->nWords; - p->nPatsOut = p->nPats * p->nPats; - // simulation info - p->vPats = Vec_PtrAllocSimInfo( 1024, p->nWordsIn ); - p->vPats0 = Vec_PtrAllocSimInfo( 128, p->nWords ); - p->vPats1 = Vec_PtrAllocSimInfo( 128, p->nWords ); - p->vOuts = Vec_PtrAllocSimInfo( 128, p->nWordsOut ); - // resub candidates - p->vCands = Vec_VecStart( 16 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Allocate simulation engine.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis ) -{ - srand( 0xABC ); - - assert( Abc_NtkIsStrash(pAig) ); - p->pAig = pAig; - p->nTruePis = nTruePis; - if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 ) - { - Vec_PtrFree( p->vPats ); - p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWordsIn ); - } - if ( Vec_PtrSize(p->vPats0) < nTruePis ) - { - Vec_PtrFree( p->vPats0 ); - p->vPats0 = Vec_PtrAllocSimInfo( nTruePis, p->nWords ); - } - if ( Vec_PtrSize(p->vPats1) < nTruePis ) - { - Vec_PtrFree( p->vPats1 ); - p->vPats1 = Vec_PtrAllocSimInfo( nTruePis, p->nWords ); - } - if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) ) - { - Vec_PtrFree( p->vOuts ); - p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut ); - } - // clean storage info for patterns - Abc_InfoClear( Vec_PtrEntry(p->vPats0,0), p->nWords * nTruePis ); - Abc_InfoClear( Vec_PtrEntry(p->vPats1,0), p->nWords * nTruePis ); - p->nPats0 = 0; - p->nPats1 = 0; - p->fConst0 = 0; - p->fConst1 = 0; -} - -/**Function************************************************************* - - Synopsis [Free simulation engine.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimFree( Res_Sim_t * p ) -{ - Vec_PtrFree( p->vPats ); - Vec_PtrFree( p->vPats0 ); - Vec_PtrFree( p->vPats1 ); - Vec_PtrFree( p->vOuts ); - Vec_VecFree( p->vCands ); - free( p ); -} - - -/**Function************************************************************* - - Synopsis [Sets random PI simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_InfoRandomBytes( unsigned * p, int nWords ) -{ - int i, Num; - for ( i = nWords - 1; i >= 0; i-- ) - { - Num = rand(); - p[i] = (Num & 1)? 0xff : 0; - p[i] = (p[i] << 8) | ((Num & 2)? 0xff : 0); - p[i] = (p[i] << 8) | ((Num & 4)? 0xff : 0); - p[i] = (p[i] << 8) | ((Num & 8)? 0xff : 0); - } -// Extra_PrintBinary( stdout, p, 32 ); printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Sets random PI simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimSetRandomBytes( Res_Sim_t * p ) -{ - Abc_Obj_t * pObj; - unsigned * pInfo; - int i; - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); - if ( i < p->nTruePis ) - Abc_InfoRandomBytes( pInfo, p->nWordsIn ); - else - Abc_InfoRandom( pInfo, p->nWordsIn ); - } -/* - // double-check that all are byte-patterns - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - if ( i == p->nTruePis ) - break; - pInfoC = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); - for ( k = 0; k < p->nBytesIn; k++ ) - assert( pInfoC[k] == 0 || pInfoC[k] == 0xff ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Sets random PI simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimSetDerivedBytes( Res_Sim_t * p, int fUseWalk ) -{ - Vec_Ptr_t * vPatsSource[2]; - int nPatsSource[2]; - Abc_Obj_t * pObj; - unsigned char * pInfo; - int i, k, z, s, nPats; - - // set several random patterns - assert( p->nBytesIn % 32 == 0 ); - nPats = p->nBytesIn/8; - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - if ( i == p->nTruePis ) - break; - Abc_InfoRandomBytes( Vec_PtrEntry(p->vPats, pObj->Id), nPats/4 ); - } - - // set special patterns - if ( fUseWalk ) - { - for ( z = 0; z < 2; z++ ) - { - // set the zero pattern - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - if ( i == p->nTruePis ) - break; - pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); - pInfo[nPats] = z ? 0xff : 0; - } - if ( ++nPats == p->nBytesIn ) - return; - // set the walking zero pattern - for ( k = 0; k < p->nTruePis; k++ ) - { - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - if ( i == p->nTruePis ) - break; - pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); - pInfo[nPats] = ((i == k) ^ z) ? 0xff : 0; - } - if ( ++nPats == p->nBytesIn ) - return; - } - } - } - - // decide what patterns to set first - if ( p->nPats0 < p->nPats1 ) - { - nPatsSource[0] = p->nPats0; - vPatsSource[0] = p->vPats0; - nPatsSource[1] = p->nPats1; - vPatsSource[1] = p->vPats1; - } - else - { - nPatsSource[0] = p->nPats1; - vPatsSource[0] = p->vPats1; - nPatsSource[1] = p->nPats0; - vPatsSource[1] = p->vPats0; - } - for ( z = 0; z < 2; z++ ) - { - for ( s = nPatsSource[z] - 1; s >= 0; s-- ) - { -// if ( s == 0 ) -// printf( "Patterns:\n" ); - // set the given source pattern - for ( k = 0; k < p->nTruePis; k++ ) - { - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - if ( i == p->nTruePis ) - break; - pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); - if ( (i == k) ^ Abc_InfoHasBit( Vec_PtrEntry(vPatsSource[z], i), s ) ) - { - pInfo[nPats] = 0xff; -// if ( s == 0 ) -// printf( "1" ); - } - else - { - pInfo[nPats] = 0; -// if ( s == 0 ) -// printf( "0" ); - } - } -// if ( s == 0 ) -// printf( "\n" ); - if ( ++nPats == p->nBytesIn ) - return; - } - } - } - // clean the rest - for ( z = nPats; z < p->nBytesIn; z++ ) - { - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - if ( i == p->nTruePis ) - break; - pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); - memset( pInfo + nPats, 0, p->nBytesIn - nPats ); - } - } -/* - // double-check that all are byte-patterns - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - if ( i == p->nTruePis ) - break; - pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); - for ( k = 0; k < p->nBytesIn; k++ ) - assert( pInfo[k] == 0 || pInfo[k] == 0xff ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Sets given PI simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo ) -{ - Abc_Obj_t * pObj; - unsigned * pInfo, * pInfo2; - int i, w; - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - if ( i == p->nTruePis ) - break; - pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); - pInfo2 = Vec_PtrEntry( vInfo, i ); - for ( w = 0; w < p->nWords; w++ ) - pInfo[w] = pInfo2[w]; - } -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) -{ - unsigned * pInfo, * pInfo1, * pInfo2; - int k, fComp1, fComp2; - // simulate the internal nodes - assert( Abc_ObjIsNode(pNode) ); - pInfo = Vec_PtrEntry(vSimInfo, pNode->Id); - pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); - pInfo2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode)); - fComp1 = Abc_ObjFaninC0(pNode); - fComp2 = Abc_ObjFaninC1(pNode); - if ( fComp1 && fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = ~pInfo1[k] & ~pInfo2[k]; - else if ( fComp1 && !fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = ~pInfo1[k] & pInfo2[k]; - else if ( !fComp1 && fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = pInfo1[k] & ~pInfo2[k]; - else // if ( fComp1 && fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = pInfo1[k] & pInfo2[k]; -} - -/**Function************************************************************* - - Synopsis [Simulates one CO node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) -{ - unsigned * pInfo, * pInfo1; - int k, fComp1; - // simulate the internal nodes - assert( Abc_ObjIsCo(pNode) ); - pInfo = Vec_PtrEntry(vSimInfo, pNode->Id); - pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); - fComp1 = Abc_ObjFaninC0(pNode); - if ( fComp1 ) - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = ~pInfo1[k]; - else - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = pInfo1[k]; -} - -/**Function************************************************************* - - Synopsis [Performs one round of simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimPerformRound( Res_Sim_t * p, int nWords ) -{ - Abc_Obj_t * pObj; - int i; - Abc_InfoFill( Vec_PtrEntry(p->vPats,0), nWords ); - Abc_AigForEachAnd( p->pAig, pObj, i ) - Res_SimPerformOne( pObj, p->vPats, nWords ); - Abc_NtkForEachPo( p->pAig, pObj, i ) - Res_SimTransferOne( pObj, p->vPats, nWords ); -} - - -/**Function************************************************************* - - Synopsis [Pads the extra space with duplicated simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords ) -{ - unsigned * pInfo; - int i, w, iWords; - assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) ); - // pad the first word - if ( nPats < 8 * sizeof(unsigned) ) - { - Vec_PtrForEachEntry( vPats, pInfo, i ) - if ( pInfo[0] & 1 ) - pInfo[0] |= ((~0) << nPats); - nPats = 8 * sizeof(unsigned); - } - // pad the empty words - iWords = nPats / (8 * sizeof(unsigned)); - Vec_PtrForEachEntry( vPats, pInfo, i ) - { - for ( w = iWords; w < nWords; w++ ) - pInfo[w] = pInfo[0]; - } -} - -/**Function************************************************************* - - Synopsis [Duplicates the simulation info to fill the space.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimDeriveInfoReplicate( Res_Sim_t * p ) -{ - unsigned * pInfo, * pInfo2; - Abc_Obj_t * pObj; - int i, j, w; - Abc_NtkForEachPo( p->pAig, pObj, i ) - { - pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); - pInfo2 = Vec_PtrEntry( p->vOuts, i ); - for ( j = 0; j < p->nPats; j++ ) - for ( w = 0; w < p->nWords; w++ ) - *pInfo2++ = pInfo[w]; - } -} - -/**Function************************************************************* - - Synopsis [Complement the simulation info if necessary.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimDeriveInfoComplement( Res_Sim_t * p ) -{ - unsigned * pInfo, * pInfo2; - Abc_Obj_t * pObj; - int i, j, w; - Abc_NtkForEachPo( p->pAig, pObj, i ) - { - pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); - pInfo2 = Vec_PtrEntry( p->vOuts, i ); - for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords ) - if ( Abc_InfoHasBit( pInfo, j ) ) - for ( w = 0; w < p->nWords; w++ ) - pInfo2[w] = ~pInfo2[w]; - } -} - -/**Function************************************************************* - - Synopsis [Prints output patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig ) -{ - Abc_Obj_t * pObj; - unsigned * pInfo2; - int i; - Abc_NtkForEachPo( pAig, pObj, i ) - { - pInfo2 = Vec_PtrEntry( p->vOuts, i ); - Extra_PrintBinary( stdout, pInfo2, p->nPatsOut ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Prints output patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimPrintNodePatterns( Res_Sim_t * p, Abc_Ntk_t * pAig ) -{ - unsigned * pInfo; - pInfo = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); - Extra_PrintBinary( stdout, pInfo, p->nPats ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Counts the number of patters of different type.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimCountResults( Res_Sim_t * p, int * pnDcs, int * pnOnes, int * pnZeros, int fVerbose ) -{ - unsigned char * pInfoCare, * pInfoNode; - int i, nTotal = 0; - pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); - pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); - for ( i = 0; i < p->nBytesIn; i++ ) - { - if ( !pInfoCare[i] ) - (*pnDcs)++; - else if ( !pInfoNode[i] ) - (*pnZeros)++; - else - (*pnOnes)++; - } - nTotal += *pnDcs; - nTotal += *pnZeros; - nTotal += *pnOnes; - if ( fVerbose ) - { - printf( "Dc = %7.2f %% ", 100.0*(*pnDcs) /nTotal ); - printf( "On = %7.2f %% ", 100.0*(*pnOnes) /nTotal ); - printf( "Off = %7.2f %% ", 100.0*(*pnZeros)/nTotal ); - } -} - -/**Function************************************************************* - - Synopsis [Counts the number of patters of different type.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimCollectPatterns( Res_Sim_t * p, int fVerbose ) -{ - Abc_Obj_t * pObj; - unsigned char * pInfoCare, * pInfoNode, * pInfo; - int i, j; - pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); - pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); - for ( i = 0; i < p->nBytesIn; i++ ) - { - // skip don't-care patterns - if ( !pInfoCare[i] ) - continue; - // separate offset and onset patterns - assert( pInfoNode[i] == 0 || pInfoNode[i] == 0xff ); - if ( !pInfoNode[i] ) - { - if ( p->nPats0 >= p->nPats ) - continue; - Abc_NtkForEachPi( p->pAig, pObj, j ) - { - if ( j == p->nTruePis ) - break; - pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); - assert( pInfo[i] == 0 || pInfo[i] == 0xff ); - if ( pInfo[i] ) - Abc_InfoSetBit( Vec_PtrEntry(p->vPats0, j), p->nPats0 ); - } - p->nPats0++; - } - else - { - if ( p->nPats1 >= p->nPats ) - continue; - Abc_NtkForEachPi( p->pAig, pObj, j ) - { - if ( j == p->nTruePis ) - break; - pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id ); - assert( pInfo[i] == 0 || pInfo[i] == 0xff ); - if ( pInfo[i] ) - Abc_InfoSetBit( Vec_PtrEntry(p->vPats1, j), p->nPats1 ); - } - p->nPats1++; - } - if ( p->nPats0 >= p->nPats && p->nPats1 >= p->nPats ) - break; - } - if ( fVerbose ) - { - printf( "| " ); - printf( "On = %3d ", p->nPats1 ); - printf( "Off = %3d ", p->nPats0 ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Verifies the last pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_SimVerifyValue( Res_Sim_t * p, int fOnSet ) -{ - Abc_Obj_t * pObj; - unsigned * pInfo, * pInfo2; - int i, value; - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - if ( i == p->nTruePis ) - break; - if ( fOnSet ) - { - pInfo2 = Vec_PtrEntry( p->vPats1, i ); - value = Abc_InfoHasBit( pInfo2, p->nPats1 - 1 ); - } - else - { - pInfo2 = Vec_PtrEntry( p->vPats0, i ); - value = Abc_InfoHasBit( pInfo2, p->nPats0 - 1 ); - } - pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); - pInfo[0] = value ? ~0 : 0; - } - Res_SimPerformRound( p, 1 ); - pObj = Abc_NtkPo( p->pAig, 1 ); - pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); - assert( pInfo[0] == 0 || pInfo[0] == ~0 ); - return pInfo[0] > 0; -} - -/**Function************************************************************* - - Synopsis [Prepares simulation info for candidate filtering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose ) -{ - int i, nOnes = 0, nZeros = 0, nDcs = 0; - if ( fVerbose ) - printf( "\n" ); - // prepare the manager - Res_SimAdjust( p, pAig, nTruePis ); - // estimate the number of patterns - Res_SimSetRandomBytes( p ); - Res_SimPerformRound( p, p->nWordsIn ); - Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose ); - // collect the patterns - Res_SimCollectPatterns( p, fVerbose ); - // add more patterns using constraint simulation - if ( p->nPats0 < 8 ) - { - if ( !Res_SatSimulate( p, 16, 0 ) ) - return p->fConst0 || p->fConst1; -// return 0; -// printf( "Value0 = %d\n", Res_SimVerifyValue( p, 0 ) ); - } - if ( p->nPats1 < 8 ) - { - if ( !Res_SatSimulate( p, 16, 1 ) ) - return p->fConst0 || p->fConst1; -// return 0; -// printf( "Value1 = %d\n", Res_SimVerifyValue( p, 1 ) ); - } - // generate additional patterns - for ( i = 0; i < 2; i++ ) - { - if ( p->nPats0 > p->nPats*7/8 && p->nPats1 > p->nPats*7/8 ) - break; - Res_SimSetDerivedBytes( p, i==0 ); - Res_SimPerformRound( p, p->nWordsIn ); - Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose ); - Res_SimCollectPatterns( p, fVerbose ); - } - // create bit-matrix info - if ( p->nPats0 < p->nPats ) - Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords ); - if ( p->nPats1 < p->nPats ) - Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords ); - // resimulate 0-patterns - Res_SimSetGiven( p, p->vPats0 ); - Res_SimPerformRound( p, p->nWords ); -//Res_SimPrintNodePatterns( p, pAig ); - Res_SimDeriveInfoReplicate( p ); - // resimulate 1-patterns - Res_SimSetGiven( p, p->vPats1 ); - Res_SimPerformRound( p, p->nWords ); -//Res_SimPrintNodePatterns( p, pAig ); - Res_SimDeriveInfoComplement( p ); - // print output patterns -// Res_SimPrintOutPatterns( p, pAig ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/res/resSim_old.c b/src/opt/res/resSim_old.c deleted file mode 100644 index 23ce29e4..00000000 --- a/src/opt/res/resSim_old.c +++ /dev/null @@ -1,521 +0,0 @@ -/**CFile**************************************************************** - - FileName [resSim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resynthesis package.] - - Synopsis [Simulation engine.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "resInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocate simulation engine.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Res_Sim_t * Res_SimAlloc( int nWords ) -{ - Res_Sim_t * p; - p = ALLOC( Res_Sim_t, 1 ); - memset( p, 0, sizeof(Res_Sim_t) ); - // simulation parameters - p->nWords = nWords; - p->nPats = 8 * sizeof(unsigned) * p->nWords; - p->nWordsOut = p->nPats * p->nWords; - p->nPatsOut = p->nPats * p->nPats; - // simulation info - p->vPats = Vec_PtrAllocSimInfo( 1024, p->nWords ); - p->vPats0 = Vec_PtrAllocSimInfo( 128, p->nWords ); - p->vPats1 = Vec_PtrAllocSimInfo( 128, p->nWords ); - p->vOuts = Vec_PtrAllocSimInfo( 128, p->nWordsOut ); - // resub candidates - p->vCands = Vec_VecStart( 16 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Allocate simulation engine.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig ) -{ - srand( 0xABC ); - - assert( Abc_NtkIsStrash(pAig) ); - p->pAig = pAig; - if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 ) - { - Vec_PtrFree( p->vPats ); - p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWords ); - } - if ( Vec_PtrSize(p->vPats0) < Abc_NtkPiNum(pAig) ) - { - Vec_PtrFree( p->vPats0 ); - p->vPats0 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords ); - } - if ( Vec_PtrSize(p->vPats1) < Abc_NtkPiNum(pAig) ) - { - Vec_PtrFree( p->vPats1 ); - p->vPats1 = Vec_PtrAllocSimInfo( Abc_NtkPiNum(pAig), p->nWords ); - } - if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) ) - { - Vec_PtrFree( p->vOuts ); - p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut ); - } - // clean storage info for patterns - Abc_InfoClear( Vec_PtrEntry(p->vPats0,0), p->nWords * Abc_NtkPiNum(pAig) ); - Abc_InfoClear( Vec_PtrEntry(p->vPats1,0), p->nWords * Abc_NtkPiNum(pAig) ); - p->nPats0 = 0; - p->nPats1 = 0; -} - -/**Function************************************************************* - - Synopsis [Free simulation engine.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimFree( Res_Sim_t * p ) -{ - Vec_PtrFree( p->vPats ); - Vec_PtrFree( p->vPats0 ); - Vec_PtrFree( p->vPats1 ); - Vec_PtrFree( p->vOuts ); - Vec_VecFree( p->vCands ); - free( p ); -} - - -/**Function************************************************************* - - Synopsis [Sets random PI simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimSetRandom( Res_Sim_t * p ) -{ - Abc_Obj_t * pObj; - unsigned * pInfo; - int i; - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); - Abc_InfoRandom( pInfo, p->nWords ); - } -} - -/**Function************************************************************* - - Synopsis [Sets given PI simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo ) -{ - Abc_Obj_t * pObj; - unsigned * pInfo, * pInfo2; - int i, w; - Abc_NtkForEachPi( p->pAig, pObj, i ) - { - pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); - pInfo2 = Vec_PtrEntry( vInfo, i ); - for ( w = 0; w < p->nWords; w++ ) - pInfo[w] = pInfo2[w]; - } -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) -{ - unsigned * pInfo, * pInfo1, * pInfo2; - int k, fComp1, fComp2; - // simulate the internal nodes - assert( Abc_ObjIsNode(pNode) ); - pInfo = Vec_PtrEntry(vSimInfo, pNode->Id); - pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); - pInfo2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode)); - fComp1 = Abc_ObjFaninC0(pNode); - fComp2 = Abc_ObjFaninC1(pNode); - if ( fComp1 && fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = ~pInfo1[k] & ~pInfo2[k]; - else if ( fComp1 && !fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = ~pInfo1[k] & pInfo2[k]; - else if ( !fComp1 && fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = pInfo1[k] & ~pInfo2[k]; - else // if ( fComp1 && fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = pInfo1[k] & pInfo2[k]; -} - -/**Function************************************************************* - - Synopsis [Simulates one CO node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ) -{ - unsigned * pInfo, * pInfo1; - int k, fComp1; - // simulate the internal nodes - assert( Abc_ObjIsCo(pNode) ); - pInfo = Vec_PtrEntry(vSimInfo, pNode->Id); - pInfo1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); - fComp1 = Abc_ObjFaninC0(pNode); - if ( fComp1 ) - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = ~pInfo1[k]; - else - for ( k = 0; k < nSimWords; k++ ) - pInfo[k] = pInfo1[k]; -} - -/**Function************************************************************* - - Synopsis [Performs one round of simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimPerformRound( Res_Sim_t * p ) -{ - Abc_Obj_t * pObj; - int i; - Abc_InfoFill( Vec_PtrEntry(p->vPats,0), p->nWords ); - Abc_AigForEachAnd( p->pAig, pObj, i ) - Res_SimPerformOne( pObj, p->vPats, p->nWords ); - Abc_NtkForEachPo( p->pAig, pObj, i ) - Res_SimTransferOne( pObj, p->vPats, p->nWords ); -} - -/**Function************************************************************* - - Synopsis [Processes simulation patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimProcessPats( Res_Sim_t * p ) -{ - Abc_Obj_t * pObj; - unsigned * pInfoCare, * pInfoNode; - int i, j, nDcs = 0; - pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); - pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); - for ( i = 0; i < p->nPats; i++ ) - { - // skip don't-care patterns - if ( !Abc_InfoHasBit(pInfoCare, i) ) - { - nDcs++; - continue; - } - // separate offset and onset patterns - if ( !Abc_InfoHasBit(pInfoNode, i) ) - { - if ( p->nPats0 >= p->nPats ) - continue; - Abc_NtkForEachPi( p->pAig, pObj, j ) - if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) ) - Abc_InfoSetBit( Vec_PtrEntry(p->vPats0, j), p->nPats0 ); - p->nPats0++; - } - else - { - if ( p->nPats1 >= p->nPats ) - continue; - Abc_NtkForEachPi( p->pAig, pObj, j ) - if ( Abc_InfoHasBit( Vec_PtrEntry(p->vPats, pObj->Id), i ) ) - Abc_InfoSetBit( Vec_PtrEntry(p->vPats1, j), p->nPats1 ); - p->nPats1++; - } - } -} - -/**Function************************************************************* - - Synopsis [Pads the extra space with duplicated simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords ) -{ - unsigned * pInfo; - int i, w, iWords; - assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) ); - // pad the first word - if ( nPats < 8 * sizeof(unsigned) ) - { - Vec_PtrForEachEntry( vPats, pInfo, i ) - if ( pInfo[0] & 1 ) - pInfo[0] |= ((~0) << nPats); - nPats = 8 * sizeof(unsigned); - } - // pad the empty words - iWords = nPats / (8 * sizeof(unsigned)); - Vec_PtrForEachEntry( vPats, pInfo, i ) - { - for ( w = iWords; w < nWords; w++ ) - pInfo[w] = pInfo[0]; - } -} - -/**Function************************************************************* - - Synopsis [Duplicates the simulation info to fill the space.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimDeriveInfoReplicate( Res_Sim_t * p ) -{ - unsigned * pInfo, * pInfo2; - Abc_Obj_t * pObj; - int i, j, w; - Abc_NtkForEachPo( p->pAig, pObj, i ) - { - pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); - pInfo2 = Vec_PtrEntry( p->vOuts, i ); - for ( j = 0; j < p->nPats; j++ ) - for ( w = 0; w < p->nWords; w++ ) - *pInfo2++ = pInfo[w]; - } -} - -/**Function************************************************************* - - Synopsis [Complement the simulation info if necessary.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimDeriveInfoComplement( Res_Sim_t * p ) -{ - unsigned * pInfo, * pInfo2; - Abc_Obj_t * pObj; - int i, j, w; - Abc_NtkForEachPo( p->pAig, pObj, i ) - { - pInfo = Vec_PtrEntry( p->vPats, pObj->Id ); - pInfo2 = Vec_PtrEntry( p->vOuts, i ); - for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords ) - if ( Abc_InfoHasBit( pInfo, j ) ) - for ( w = 0; w < p->nWords; w++ ) - pInfo2[w] = ~pInfo2[w]; - } -} - -/**Function************************************************************* - - Synopsis [Free simulation engine.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimReportOne( Res_Sim_t * p ) -{ - unsigned * pInfoCare, * pInfoNode; - int i, nDcs, nOnes, nZeros; - pInfoCare = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id ); - pInfoNode = Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id ); - nDcs = nOnes = nZeros = 0; - for ( i = 0; i < p->nPats; i++ ) - { - // skip don't-care patterns - if ( !Abc_InfoHasBit(pInfoCare, i) ) - { - nDcs++; - continue; - } - // separate offset and onset patterns - if ( !Abc_InfoHasBit(pInfoNode, i) ) - nZeros++; - else - nOnes++; - } - printf( "On = %3d (%7.2f %%) ", nOnes, 100.0*nOnes/p->nPats ); - printf( "Off = %3d (%7.2f %%) ", nZeros, 100.0*nZeros/p->nPats ); - printf( "Dc = %3d (%7.2f %%) ", nDcs, 100.0*nDcs/p->nPats ); - printf( "P0 = %3d ", p->nPats0 ); - printf( "P1 = %3d ", p->nPats1 ); - if ( p->nPats0 < 4 || p->nPats1 < 4 ) - printf( "*" ); - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints output patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig ) -{ - Abc_Obj_t * pObj; - unsigned * pInfo2; - int i; - Abc_NtkForEachPo( pAig, pObj, i ) - { - pInfo2 = Vec_PtrEntry( p->vOuts, i ); - Extra_PrintBinary( stdout, pInfo2, p->nPatsOut ); - printf( "\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Prepares simulation info for candidate filtering.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose ) -{ - int Limit; - // prepare the manager - Res_SimAdjust( p, pAig ); - // collect 0/1 simulation info - for ( Limit = 0; Limit < 10; Limit++ ) - { - Res_SimSetRandom( p ); - Res_SimPerformRound( p ); - Res_SimProcessPats( p ); - if ( !(p->nPats0 < p->nPats || p->nPats1 < p->nPats) ) - break; - } -// printf( "%d ", Limit ); - // report the last set of patterns -// Res_SimReportOne( p ); -// printf( "\n" ); - // quit if there is not enough -// if ( p->nPats0 < 4 || p->nPats1 < 4 ) - if ( p->nPats0 < 4 || p->nPats1 < 4 ) - { -// Res_SimReportOne( p ); - return 0; - } - // create bit-matrix info - if ( p->nPats0 < p->nPats ) - Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords ); - if ( p->nPats1 < p->nPats ) - Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords ); - // resimulate 0-patterns - Res_SimSetGiven( p, p->vPats0 ); - Res_SimPerformRound( p ); - Res_SimDeriveInfoReplicate( p ); - // resimulate 1-patterns - Res_SimSetGiven( p, p->vPats1 ); - Res_SimPerformRound( p ); - Res_SimDeriveInfoComplement( p ); - // print output patterns -// Res_SimPrintOutPatterns( p, pAig ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/res/resStrash.c b/src/opt/res/resStrash.c deleted file mode 100644 index fde842a4..00000000 --- a/src/opt/res/resStrash.c +++ /dev/null @@ -1,117 +0,0 @@ -/**CFile**************************************************************** - - FileName [resStrash.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resynthesis package.] - - Synopsis [Structural hashing of the nodes in the window.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: resStrash.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "resInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -extern Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pAig, Abc_Obj_t * pObjOld ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Structurally hashes the given window.] - - Description [The first PO is the observability condition. The second - is the node's function. The remaining POs are the candidate divisors.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Res_WndStrash( Res_Win_t * p ) -{ - Vec_Ptr_t * vPairs; - Abc_Ntk_t * pAig; - Abc_Obj_t * pObj, * pMiter; - int i; - assert( Abc_NtkHasAig(p->pNode->pNtk) ); -// Abc_NtkCleanCopy( p->pNode->pNtk ); - // create the network - pAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); - pAig->pName = Extra_UtilStrsav( "window" ); - // create the inputs - Vec_PtrForEachEntry( p->vLeaves, pObj, i ) - pObj->pCopy = Abc_NtkCreatePi( pAig ); - Vec_PtrForEachEntry( p->vBranches, pObj, i ) - pObj->pCopy = Abc_NtkCreatePi( pAig ); - // go through the nodes in the topological order - Vec_PtrForEachEntry( p->vNodes, pObj, i ) - { - pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj ); - if ( pObj == p->pNode ) - pObj->pCopy = Abc_ObjNot( pObj->pCopy ); - } - // collect the POs - vPairs = Vec_PtrAlloc( 2 * Vec_PtrSize(p->vRoots) ); - Vec_PtrForEachEntry( p->vRoots, pObj, i ) - { - Vec_PtrPush( vPairs, pObj->pCopy ); - Vec_PtrPush( vPairs, NULL ); - } - // mark the TFO of the node - Abc_NtkIncrementTravId( p->pNode->pNtk ); - Res_WinSweepLeafTfo_rec( p->pNode, (int)p->pNode->Level + p->nWinTfoMax ); - // update strashing of the node - p->pNode->pCopy = Abc_ObjNot( p->pNode->pCopy ); - Abc_NodeSetTravIdPrevious( p->pNode ); - // redo strashing in the TFO - Vec_PtrForEachEntry( p->vNodes, pObj, i ) - { - if ( Abc_NodeIsTravIdCurrent(pObj) ) - pObj->pCopy = Abc_ConvertAigToAig( pAig, pObj ); - } - // collect the POs - Vec_PtrForEachEntry( p->vRoots, pObj, i ) - Vec_PtrWriteEntry( vPairs, 2 * i + 1, pObj->pCopy ); - // add the miter - pMiter = Abc_AigMiter( pAig->pManFunc, vPairs ); - Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pMiter ); - Vec_PtrFree( vPairs ); - // add the node - Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), p->pNode->pCopy ); - // add the fanins - Abc_ObjForEachFanin( p->pNode, pObj, i ) - Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy ); - // add the divisors - Vec_PtrForEachEntry( p->vDivs, pObj, i ) - Abc_ObjAddFanin( Abc_NtkCreatePo(pAig), pObj->pCopy ); - // add the names - Abc_NtkAddDummyPiNames( pAig ); - Abc_NtkAddDummyPoNames( pAig ); - // check the resulting network - if ( !Abc_NtkCheck( pAig ) ) - fprintf( stdout, "Res_WndStrash(): Network check has failed.\n" ); - return pAig; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/res/resWin.c b/src/opt/res/resWin.c deleted file mode 100644 index a3648925..00000000 --- a/src/opt/res/resWin.c +++ /dev/null @@ -1,485 +0,0 @@ -/**CFile**************************************************************** - - FileName [resWin.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resynthesis package.] - - Synopsis [Windowing algorithm.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: resWin.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "resInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the window.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Res_Win_t * Res_WinAlloc() -{ - Res_Win_t * p; - // start the manager - p = ALLOC( Res_Win_t, 1 ); - memset( p, 0, sizeof(Res_Win_t) ); - // set internal parameters - p->nFanoutLimit = 10; - p->nLevTfiMinus = 3; - // allocate storage - p->vRoots = Vec_PtrAlloc( 256 ); - p->vLeaves = Vec_PtrAlloc( 256 ); - p->vBranches = Vec_PtrAlloc( 256 ); - p->vNodes = Vec_PtrAlloc( 256 ); - p->vDivs = Vec_PtrAlloc( 256 ); - p->vMatrix = Vec_VecStart( 128 ); - return p; -} - -/**Function************************************************************* - - Synopsis [Frees the window.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_WinFree( Res_Win_t * p ) -{ - Vec_PtrFree( p->vRoots ); - Vec_PtrFree( p->vLeaves ); - Vec_PtrFree( p->vBranches ); - Vec_PtrFree( p->vNodes ); - Vec_PtrFree( p->vDivs ); - Vec_VecFree( p->vMatrix ); - free( p ); -} - - - -/**Function************************************************************* - - Synopsis [Collect the limited TFI cone of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_WinCollectLeavesAndNodes( Res_Win_t * p ) -{ - Vec_Ptr_t * vFront; - Abc_Obj_t * pObj, * pTemp; - int i, k, m; - - assert( p->nWinTfiMax > 0 ); - assert( Vec_VecSize(p->vMatrix) > p->nWinTfiMax ); - - // start matrix with the node - Vec_VecClear( p->vMatrix ); - Vec_VecPush( p->vMatrix, 0, p->pNode ); - Abc_NtkIncrementTravId( p->pNode->pNtk ); - Abc_NodeSetTravIdCurrent( p->pNode ); - - // collect the leaves (nodes pTemp such that "p->pNode->Level - pTemp->Level > p->nWinTfiMax") - Vec_PtrClear( p->vLeaves ); - Vec_VecForEachLevelStartStop( p->vMatrix, vFront, i, 0, p->nWinTfiMax ) - { - Vec_PtrForEachEntry( vFront, pObj, k ) - { - Abc_ObjForEachFanin( pObj, pTemp, m ) - { - if ( Abc_NodeIsTravIdCurrent( pTemp ) ) - continue; - Abc_NodeSetTravIdCurrent( pTemp ); - if ( Abc_ObjIsCi(pTemp) || (int)(p->pNode->Level - pTemp->Level) > p->nWinTfiMax ) - Vec_PtrPush( p->vLeaves, pTemp ); - else - Vec_VecPush( p->vMatrix, p->pNode->Level - pTemp->Level, pTemp ); - } - } - } - if ( Vec_PtrSize(p->vLeaves) == 0 ) - return 0; - - // collect the nodes in the reverse order - Vec_PtrClear( p->vNodes ); - Vec_VecForEachLevelReverseStartStop( p->vMatrix, vFront, i, p->nWinTfiMax, 0 ) - { - Vec_PtrForEachEntry( vFront, pObj, k ) - Vec_PtrPush( p->vNodes, pObj ); - Vec_PtrClear( vFront ); - } - - // get the lowest leaf level - p->nLevLeafMin = ABC_INFINITY; - Vec_PtrForEachEntry( p->vLeaves, pObj, k ) - p->nLevLeafMin = ABC_MIN( p->nLevLeafMin, (int)pObj->Level ); - - // set minimum traversal level - p->nLevTravMin = ABC_MAX( ((int)p->pNode->Level) - p->nWinTfiMax - p->nLevTfiMinus, p->nLevLeafMin ); - assert( p->nLevTravMin >= 0 ); - return 1; -} - - - -/**Function************************************************************* - - Synopsis [Returns 1 if the node should be a root.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Res_WinComputeRootsCheck( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit ) -{ - Abc_Obj_t * pFanout; - int i; - // the node is the root if one of the following is true: - // (1) the node has more than fanouts than the limit - if ( Abc_ObjFanoutNum(pNode) > nFanoutLimit ) - return 1; - // (2) the node has CO fanouts - // (3) the node has fanouts above the cutoff level - Abc_ObjForEachFanout( pNode, pFanout, i ) - if ( Abc_ObjIsCo(pFanout) || (int)pFanout->Level > nLevelMax ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Recursively collects the root candidates.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_WinComputeRoots_rec( Abc_Obj_t * pNode, int nLevelMax, int nFanoutLimit, Vec_Ptr_t * vRoots ) -{ - Abc_Obj_t * pFanout; - int i; - assert( Abc_ObjIsNode(pNode) ); - if ( Abc_NodeIsTravIdCurrent(pNode) ) - return; - Abc_NodeSetTravIdCurrent( pNode ); - // check if the node should be the root - if ( Res_WinComputeRootsCheck( pNode, nLevelMax, nFanoutLimit ) ) - Vec_PtrPush( vRoots, pNode ); - else // if not, explore its fanouts - Abc_ObjForEachFanout( pNode, pFanout, i ) - Res_WinComputeRoots_rec( pFanout, nLevelMax, nFanoutLimit, vRoots ); -} - -/**Function************************************************************* - - Synopsis [Recursively collects the root candidates.] - - Description [Returns 1 if the only root is this node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_WinComputeRoots( Res_Win_t * p ) -{ - Vec_PtrClear( p->vRoots ); - Abc_NtkIncrementTravId( p->pNode->pNtk ); - Res_WinComputeRoots_rec( p->pNode, p->pNode->Level + p->nWinTfoMax, p->nFanoutLimit, p->vRoots ); - assert( Vec_PtrSize(p->vRoots) > 0 ); - if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode ) - return 0; - return 1; -} - - - -/**Function************************************************************* - - Synopsis [Marks the paths from the roots to the leaves.] - - Description [Returns 1 if the the node can reach a leaf.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_WinMarkPaths_rec( Abc_Obj_t * pNode, Abc_Obj_t * pPivot, int nLevelMin ) -{ - Abc_Obj_t * pFanin; - int i, RetValue; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pNode) ) - return 1; - if ( Abc_NodeIsTravIdPrevious(pNode) ) - return 0; - // assume that the node does not have access to the leaves - Abc_NodeSetTravIdPrevious( pNode ); - // skip nodes below the given level - if ( pNode == pPivot || (int)pNode->Level <= nLevelMin ) - return 0; - assert( Abc_ObjIsNode(pNode) ); - // check if the fanins have access to the leaves - RetValue = 0; - Abc_ObjForEachFanin( pNode, pFanin, i ) - RetValue |= Res_WinMarkPaths_rec( pFanin, pPivot, nLevelMin ); - // relabel the node if it has access to the leaves - if ( RetValue ) - Abc_NodeSetTravIdCurrent( pNode ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Marks the paths from the roots to the leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_WinMarkPaths( Res_Win_t * p ) -{ - Abc_Obj_t * pObj; - int i; - // mark the leaves - Abc_NtkIncrementTravId( p->pNode->pNtk ); - Abc_NtkIncrementTravId( p->pNode->pNtk ); - Vec_PtrForEachEntry( p->vLeaves, pObj, i ) - Abc_NodeSetTravIdCurrent( pObj ); - // traverse from the roots and mark the nodes that can reach leaves - // the nodes that do not reach leaves have previous trav ID - // the nodes that reach leaves have current trav ID - Vec_PtrForEachEntry( p->vRoots, pObj, i ) - Res_WinMarkPaths_rec( pObj, p->pNode, p->nLevTravMin ); -} - - - - -/**Function************************************************************* - - Synopsis [Recursively collects the roots.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_WinFinalizeRoots_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vRoots ) -{ - Abc_Obj_t * pFanout; - int i; - assert( Abc_ObjIsNode(pObj) ); - assert( Abc_NodeIsTravIdCurrent(pObj) ); - // check if the node has all fanouts marked - Abc_ObjForEachFanout( pObj, pFanout, i ) - if ( !Abc_NodeIsTravIdCurrent(pFanout) ) - break; - // if some of the fanouts are unmarked, add the node to the roots - if ( i < Abc_ObjFanoutNum(pObj) ) - Vec_PtrPushUnique( vRoots, pObj ); - else // otherwise, call recursively - Abc_ObjForEachFanout( pObj, pFanout, i ) - Res_WinFinalizeRoots_rec( pFanout, vRoots ); -} - -/**Function************************************************************* - - Synopsis [Finalizes the roots of the window.] - - Description [Roots of the window are the nodes that have at least - one fanout that it not in the TFO of the leaves.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_WinFinalizeRoots( Res_Win_t * p ) -{ - assert( !Abc_NodeIsTravIdCurrent(p->pNode) ); - // mark the node with the old traversal ID - Abc_NodeSetTravIdCurrent( p->pNode ); - // recollect the roots - Vec_PtrClear( p->vRoots ); - Res_WinFinalizeRoots_rec( p->pNode, p->vRoots ); - assert( Vec_PtrSize(p->vRoots) > 0 ); - if ( Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode ) - return 0; - return 1; -} - - -/**Function************************************************************* - - Synopsis [Recursively adds missing nodes and leaves.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_WinAddMissing_rec( Res_Win_t * p, Abc_Obj_t * pObj, int nLevTravMin ) -{ - Abc_Obj_t * pFanin; - int i; - // skip the already collected leaves, nodes, and branches - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return; - // if this is not an internal node - make it a new branch - if ( !Abc_NodeIsTravIdPrevious(pObj) ) - { - assert( Vec_PtrFind(p->vLeaves, pObj) == -1 ); - Abc_NodeSetTravIdCurrent( pObj ); - Vec_PtrPush( p->vBranches, pObj ); - return; - } - assert( Abc_ObjIsNode(pObj) ); // if this is a CI, then the window is incorrect! - Abc_NodeSetTravIdCurrent( pObj ); - // visit the fanins of the node - Abc_ObjForEachFanin( pObj, pFanin, i ) - Res_WinAddMissing_rec( p, pFanin, nLevTravMin ); - // collect the node - Vec_PtrPush( p->vNodes, pObj ); -} - -/**Function************************************************************* - - Synopsis [Adds to the window nodes and leaves in the TFI of the roots.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Res_WinAddMissing( Res_Win_t * p ) -{ - Abc_Obj_t * pObj; - int i; - // mark the leaves - Abc_NtkIncrementTravId( p->pNode->pNtk ); - Vec_PtrForEachEntry( p->vLeaves, pObj, i ) - Abc_NodeSetTravIdCurrent( pObj ); - // mark the already collected nodes - Vec_PtrForEachEntry( p->vNodes, pObj, i ) - Abc_NodeSetTravIdCurrent( pObj ); - // explore from the roots - Vec_PtrClear( p->vBranches ); - Vec_PtrForEachEntry( p->vRoots, pObj, i ) - Res_WinAddMissing_rec( p, pObj, p->nLevTravMin ); -} - - - - -/**Function************************************************************* - - Synopsis [Returns 1 if the window is trivial (without TFO).] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_WinIsTrivial( Res_Win_t * p ) -{ - return Vec_PtrSize(p->vRoots) == 1 && Vec_PtrEntry(p->vRoots, 0) == p->pNode; -} - -/**Function************************************************************* - - Synopsis [Computes the window.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Res_WinCompute( Abc_Obj_t * pNode, int nWinTfiMax, int nWinTfoMax, Res_Win_t * p ) -{ - assert( Abc_ObjIsNode(pNode) ); - assert( nWinTfiMax > 0 && nWinTfiMax < 10 ); - assert( nWinTfoMax >= 0 && nWinTfoMax < 10 ); - - // initialize the window - p->pNode = pNode; - p->nWinTfiMax = nWinTfiMax; - p->nWinTfoMax = nWinTfoMax; - - Vec_PtrClear( p->vBranches ); - Vec_PtrClear( p->vDivs ); - Vec_PtrClear( p->vRoots ); - Vec_PtrPush( p->vRoots, pNode ); - - // compute the leaves - if ( !Res_WinCollectLeavesAndNodes( p ) ) - return 0; - - // compute the candidate roots - if ( p->nWinTfoMax > 0 && Res_WinComputeRoots(p) ) - { - // mark the paths from the roots to the leaves - Res_WinMarkPaths( p ); - // refine the roots and add branches and missing nodes - if ( Res_WinFinalizeRoots( p ) ) - Res_WinAddMissing( p ); - } - - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/res/res_.c b/src/opt/res/res_.c deleted file mode 100644 index a50affd7..00000000 --- a/src/opt/res/res_.c +++ /dev/null @@ -1,50 +0,0 @@ -/**CFile**************************************************************** - - FileName [res_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Resynthesis package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 15, 2007.] - - Revision [$Id: res_.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "res.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/ret/module.make b/src/opt/ret/module.make deleted file mode 100644 index 4b14365e..00000000 --- a/src/opt/ret/module.make +++ /dev/null @@ -1,8 +0,0 @@ -SRC += src/opt/ret/retArea.c \ - src/opt/ret/retCore.c \ - src/opt/ret/retDelay.c \ - src/opt/ret/retFlow.c \ - src/opt/ret/retIncrem.c \ - src/opt/ret/retInit.c \ - src/opt/ret/retLvalue.c - diff --git a/src/opt/ret/retArea.c b/src/opt/ret/retArea.c deleted file mode 100644 index 5eec8e80..00000000 --- a/src/opt/ret/retArea.c +++ /dev/null @@ -1,540 +0,0 @@ -/**CFile**************************************************************** - - FileName [retArea.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Retiming package.] - - Synopsis [Min-area retiming.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Oct 31, 2006.] - - Revision [$Id: retArea.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "retInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose ); -static void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward ); -static void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); -static Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); -static void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ); - -extern Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs min-area retiming.] - - Description [Returns the number of latches reduced.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fVerbose ) -{ - Abc_Ntk_t * pNtkTotal = NULL, * pNtkBottom; - Vec_Int_t * vValuesNew = NULL, * vValues; - int nLatches = Abc_NtkLatchNum(pNtk); - int fOneFrame = 0; - assert( !fForwardOnly || !fBackwardOnly ); - // there should not be black boxes - assert( Abc_NtkIsSopLogic(pNtk) ); - assert( Abc_NtkLatchNum(pNtk) == Vec_PtrSize(pNtk->vBoxes) ); - // reorder CI/CO/latch inputs - Abc_NtkOrderCisCos( pNtk ); - // perform forward retiming - if ( !fBackwardOnly ) - { - if ( fOneFrame ) - Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose ); - else - while ( Abc_NtkRetimeMinAreaOne( pNtk, 1, fVerbose ) ); - } - // remember initial values - vValues = Abc_NtkCollectLatchValues( pNtk ); - // perform backward retiming - if ( !fForwardOnly ) - { - if ( fOneFrame ) - pNtkTotal = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose ); - else - while ( pNtkBottom = Abc_NtkRetimeMinAreaOne( pNtk, 0, fVerbose ) ) - pNtkTotal = Abc_NtkAttachBottom( pNtkTotal, pNtkBottom ); - } - // compute initial values - vValuesNew = Abc_NtkRetimeInitialValues( pNtkTotal, vValues, fVerbose ); - if ( pNtkTotal ) Abc_NtkDelete( pNtkTotal ); - // insert new initial values - Abc_NtkInsertLatchValues( pNtk, vValuesNew ); - if ( vValuesNew ) Vec_IntFree( vValuesNew ); - if ( vValues ) Vec_IntFree( vValues ); - // fix the COs (this changes the circuit structure) -// Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); - // check for correctness - if ( !Abc_NtkCheck( pNtk ) ) - fprintf( stdout, "Abc_NtkRetimeMinArea(): Network check has failed.\n" ); - // return the number of latches saved - return nLatches - Abc_NtkLatchNum(pNtk); -} - -/**Function************************************************************* - - Synopsis [Performs min-area retiming backward.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkRetimeMinAreaOne( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) -{ - Abc_Ntk_t * pNtkNew = NULL; - Vec_Ptr_t * vMinCut; - int nLatches = Abc_NtkLatchNum(pNtk); - // mark current latches and TFI(POs) - Abc_NtkRetimeMinAreaPrepare( pNtk, fForward ); - // run the maximum forward flow - vMinCut = Abc_NtkMaxFlow( pNtk, fForward, fVerbose ); -// assert( Vec_PtrSize(vMinCut) <= Abc_NtkLatchNum(pNtk) ); - // create new latch boundary if there is improvement - if ( Vec_PtrSize(vMinCut) < Abc_NtkLatchNum(pNtk) ) - { - pNtkNew = (Abc_Ntk_t *)1; - if ( fForward ) - Abc_NtkRetimeMinAreaInitValues( pNtk, vMinCut ); - else - pNtkNew = Abc_NtkRetimeMinAreaConstructNtk( pNtk, vMinCut ); - Abc_NtkRetimeMinAreaUpdateLatches( pNtk, vMinCut, fForward ); - } - // clean up - Vec_PtrFree( vMinCut ); - Abc_NtkCleanMarkA( pNtk ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Marks the cone with MarkA.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMarkCone_rec( Abc_Obj_t * pObj, int fForward ) -{ - Abc_Obj_t * pNext; - int i; - if ( pObj->fMarkA ) - return; - pObj->fMarkA = 1; - if ( fForward ) - { - Abc_ObjForEachFanout( pObj, pNext, i ) - Abc_NtkMarkCone_rec( pNext, fForward ); - } - else - { - Abc_ObjForEachFanin( pObj, pNext, i ) - Abc_NtkMarkCone_rec( pNext, fForward ); - } -} - -/**Function************************************************************* - - Synopsis [Marks the cone with MarkA.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkUnmarkCone_rec( Abc_Obj_t * pObj, int fForward ) -{ - Abc_Obj_t * pNext; - int i; - if ( !pObj->fMarkA || Abc_ObjIsLatch(pObj) ) - return; - pObj->fMarkA = 0; - if ( fForward ) - { - Abc_ObjForEachFanout( pObj, pNext, i ) - Abc_NtkUnmarkCone_rec( pNext, fForward ); - } - else - { - Abc_ObjForEachFanin( pObj, pNext, i ) - Abc_NtkUnmarkCone_rec( pNext, fForward ); - } -} - -/**Function************************************************************* - - Synopsis [Prepares the network for running MaxFlow.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeMinAreaPrepare( Abc_Ntk_t * pNtk, int fForward ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj, * pFanin; - int i, k; - if ( fForward ) - { - // mark the frontier - Abc_NtkForEachPo( pNtk, pObj, i ) - pObj->fMarkA = 1; - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - pObj->fMarkA = 1; - Abc_ObjFanin0(pObj)->fMarkA = 1; - } - // mark the nodes reachable from the PIs - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_NtkMarkCone_rec( pObj, fForward ); - // collect the unmarked fanins of the marked nodes - vNodes = Vec_PtrAlloc( 100 ); - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( pObj->fMarkA ) - Abc_ObjForEachFanin( pObj, pFanin, k ) - if ( !pFanin->fMarkA ) - Vec_PtrPush( vNodes, pFanin ); - // mark these nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->fMarkA = 1; - Vec_PtrFree( vNodes ); - } - else - { - // mark the frontier - Abc_NtkForEachPi( pNtk, pObj, i ) - pObj->fMarkA = 1; - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - pObj->fMarkA = 1; - Abc_ObjFanout0(pObj)->fMarkA = 1; - } - // mark the nodes reachable from the POs - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_NtkMarkCone_rec( pObj, fForward ); - } -} - -/**Function************************************************************* - - Synopsis [Compute initial values.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeMinAreaInitValues_rec( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return (int)pObj->pCopy; - Abc_NodeSetTravIdCurrent(pObj); - // consider the case of a latch output - if ( Abc_ObjIsBo(pObj) ) - { - assert( Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ); - pObj->pCopy = (void *)Abc_NtkRetimeMinAreaInitValues_rec( Abc_ObjFanin0(pObj) ); - return (int)pObj->pCopy; - } - assert( Abc_ObjIsNode(pObj) ); - // visit the fanins - Abc_ObjForEachFanin( pObj, pFanin, i ) - Abc_NtkRetimeMinAreaInitValues_rec( pFanin ); - // compute the value of the node - pObj->pCopy = (void *)Abc_ObjSopSimulate(pObj); - return (int)pObj->pCopy; -} - -/**Function************************************************************* - - Synopsis [Compute initial values.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeMinAreaInitValues( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) -{ - Abc_Obj_t * pObj; - int i; - // transfer initial values to pCopy and mark the latches - Abc_NtkIncrementTravId(pNtk); - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - pObj->pCopy = (void *)Abc_LatchIsInit1(pObj); - Abc_NodeSetTravIdCurrent( pObj ); - } - // propagate initial values - Vec_PtrForEachEntry( vMinCut, pObj, i ) - Abc_NtkRetimeMinAreaInitValues_rec( pObj ); - // unmark the latches - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_NodeSetTravIdPrevious( pObj ); -} - -/**Function************************************************************* - - Synopsis [Performs min-area retiming backward.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Obj_t * Abc_NtkRetimeMinAreaConstructNtk_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return pObj->pCopy; - Abc_NodeSetTravIdCurrent(pObj); - // consider the case of a latch output - if ( Abc_ObjIsBi(pObj) ) - { - pObj->pCopy = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) ); - return pObj->pCopy; - } - assert( Abc_ObjIsNode(pObj) ); - // visit the fanins - Abc_ObjForEachFanin( pObj, pFanin, i ) - Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, pFanin ); - // compute the value of the node - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_ObjForEachFanin( pObj, pFanin, i ) - Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); - return pObj->pCopy; -} - -/**Function************************************************************* - - Synopsis [Creates the network from computing initial state.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkRetimeMinAreaConstructNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj, * pObjNew; - int i; - // create new network - pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); - // map new latches into PIs of the new network - Abc_NtkIncrementTravId(pNtk); - Vec_PtrForEachEntry( vMinCut, pObj, i ) - { - pObj->pCopy = Abc_NtkCreatePi(pNtkNew); - Abc_NodeSetTravIdCurrent( pObj ); - } - // construct the network recursively - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - pObjNew = Abc_NtkRetimeMinAreaConstructNtk_rec( pNtkNew, Abc_ObjFanin0(pObj) ); - Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pObjNew ); - } - // unmark the nodes in the cut - Vec_PtrForEachEntry( vMinCut, pObj, i ) - Abc_NodeSetTravIdPrevious( pObj ); - // unmark the latches - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_NodeSetTravIdPrevious( pObj ); - // assign dummy node names - Abc_NtkAddDummyPiNames( pNtkNew ); - Abc_NtkAddDummyPoNames( pNtkNew ); - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkRetimeMinAreaConstructNtk(): Network check has failed.\n" ); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Updates the network after backward retiming.] - - Description [Assumes that fMarkA denotes all nodes reachabe from - the latches toward the cut.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeMinAreaUpdateLatches( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ) -{ - Vec_Ptr_t * vCis, * vCos, * vBoxes, * vBoxesNew, * vNodes, * vBuffers; - Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut, * pNext, * pBuffer; - int i, k; - // create new latches - Vec_PtrShrink( pNtk->vCis, Abc_NtkCiNum(pNtk) - Abc_NtkLatchNum(pNtk) ); - Vec_PtrShrink( pNtk->vCos, Abc_NtkCoNum(pNtk) - Abc_NtkLatchNum(pNtk) ); - vCis = pNtk->vCis; pNtk->vCis = NULL; - vCos = pNtk->vCos; pNtk->vCos = NULL; - vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL; - // transfer boxes - vBoxesNew = Vec_PtrAlloc(100); - Vec_PtrForEachEntry( vBoxes, pObj, i ) - if ( !Abc_ObjIsLatch(pObj) ) - Vec_PtrPush( vBoxesNew, pObj ); - // create or reuse latches - vNodes = Vec_PtrAlloc( 100 ); - vBuffers = Vec_PtrAlloc( 100 ); - Vec_PtrForEachEntry( vMinCut, pObj, i ) - { - if ( Abc_ObjIsCi(pObj) && fForward ) - { - pLatchOut = pObj; - pLatch = Abc_ObjFanin0(pLatchOut); - pLatchIn = Abc_ObjFanin0(pLatch); - assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) ); - // mark the latch as reused - Abc_NodeSetTravIdCurrent( pLatch ); - - // check if there are marked fanouts - // (these are fanouts to be connected to the latch input) - Abc_ObjForEachFanout( pObj, pNext, k ) - if ( pNext->fMarkA ) - break; - if ( k < Abc_ObjFanoutNum(pObj) ) - { - // add the buffer - pBuffer = Abc_NtkCreateNodeBuf( pNtk, Abc_ObjFanin0(pLatchIn) ); - Abc_ObjPatchFanin( pLatchIn, Abc_ObjFanin0(pLatchIn), pBuffer ); - Vec_PtrPush( vBuffers, pBuffer ); - // redirect edges to the unvisited fanouts of the node - Abc_NodeCollectFanouts( pObj, vNodes ); - Vec_PtrForEachEntry( vNodes, pNext, k ) - if ( pNext->fMarkA ) - Abc_ObjPatchFanin( pNext, pObj, pBuffer ); - } - assert( Abc_ObjFanoutNum(pObj) > 0 ); -// if ( Abc_ObjFanoutNum(pObj) == 0 ) -// Abc_NtkDeleteObj_rec( pObj, 0 ); - } - else if ( Abc_ObjIsCo(pObj) && !fForward ) - { - pLatchIn = pObj; - pLatch = Abc_ObjFanout0(pLatchIn); - pLatchOut = Abc_ObjFanout0(pLatch); - assert( Abc_ObjIsBo(pLatchOut) && Abc_ObjIsLatch(pLatch) && Abc_ObjIsBi(pLatchIn) ); - // mark the latch as reused - Abc_NodeSetTravIdCurrent( pLatch ); - assert( !Abc_ObjFanin0(pLatchIn)->fMarkA ); - } - else - { - pLatchOut = Abc_NtkCreateBo(pNtk); - pLatch = Abc_NtkCreateLatch(pNtk); - pLatchIn = Abc_NtkCreateBi(pNtk); - Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" ); - Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" ); - // connect - Abc_ObjAddFanin( pLatchOut, pLatch ); - Abc_ObjAddFanin( pLatch, pLatchIn ); - if ( fForward ) - { - pLatch->pData = (void *)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO); - // redirect edges to the unvisited fanouts of the node - Abc_NodeCollectFanouts( pObj, vNodes ); - Vec_PtrForEachEntry( vNodes, pNext, k ) - if ( !pNext->fMarkA ) - Abc_ObjPatchFanin( pNext, pObj, pLatchOut ); - } - else - { - // redirect edges to the visited fanouts of the node - Abc_NodeCollectFanouts( pObj, vNodes ); - Vec_PtrForEachEntry( vNodes, pNext, k ) - if ( pNext->fMarkA ) - Abc_ObjPatchFanin( pNext, pObj, pLatchOut ); - } - // connect latch to the node - Abc_ObjAddFanin( pLatchIn, pObj ); - } - Vec_PtrPush( vCis, pLatchOut ); - Vec_PtrPush( vBoxesNew, pLatch ); - Vec_PtrPush( vCos, pLatchIn ); - } - Vec_PtrFree( vNodes ); - // remove buffers - Vec_PtrForEachEntry( vBuffers, pObj, i ) - { - Abc_ObjTransferFanout( pObj, Abc_ObjFanin0(pObj) ); - Abc_NtkDeleteObj( pObj ); - } - Vec_PtrFree( vBuffers ); - // remove useless latches - Vec_PtrForEachEntry( vBoxes, pObj, i ) - { - if ( !Abc_ObjIsLatch(pObj) ) - continue; - if ( Abc_NodeIsTravIdCurrent(pObj) ) - continue; - pLatchOut = Abc_ObjFanout0(pObj); - pLatch = pObj; - pLatchIn = Abc_ObjFanin0(pObj); - if ( Abc_ObjFanoutNum(pLatchOut) > 0 ) - Abc_ObjTransferFanout( pLatchOut, Abc_ObjFanin0(pLatchIn) ); - Abc_NtkDeleteObj( pLatchOut ); - Abc_NtkDeleteObj( pObj ); - Abc_NtkDeleteObj( pLatchIn ); - } - // set the arrays - pNtk->vCis = vCis; - pNtk->vCos = vCos; - pNtk->vBoxes = vBoxesNew; - Vec_PtrFree( vBoxes ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/ret/retCore.c b/src/opt/ret/retCore.c deleted file mode 100644 index 47b2cbbc..00000000 --- a/src/opt/ret/retCore.c +++ /dev/null @@ -1,132 +0,0 @@ -/**CFile**************************************************************** - - FileName [retCore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Retiming package.] - - Synopsis [The core retiming procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Oct 31, 2006.] - - Revision [$Id: retCore.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "retInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -int timeRetime = 0; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Implementation of retiming.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose ) -{ - int nLatches = Abc_NtkLatchNum(pNtk); - int nLevels = Abc_NtkLevel(pNtk); - int RetValue = 0, clkTotal = clock(); - int nNodesOld, nLatchesOld; - assert( Mode > 0 && Mode < 7 ); - assert( !fForwardOnly || !fBackwardOnly ); - - // cleanup the network - nNodesOld = Abc_NtkNodeNum(pNtk); - nLatchesOld = Abc_NtkLatchNum(pNtk); - Abc_NtkCleanupSeq(pNtk, 0, 0, 0); - if ( nNodesOld > Abc_NtkNodeNum(pNtk) || nLatchesOld > Abc_NtkLatchNum(pNtk) ) - printf( "Cleanup before retiming removed %d dangling nodes and %d dangling latches.\n", - nNodesOld - Abc_NtkNodeNum(pNtk), nLatchesOld - Abc_NtkLatchNum(pNtk) ); - - // perform retiming - switch ( Mode ) - { - case 1: // forward - RetValue = Abc_NtkRetimeIncremental( pNtk, 1, 0, 0, fVerbose ); - break; - case 2: // backward - RetValue = Abc_NtkRetimeIncremental( pNtk, 0, 0, 0, fVerbose ); - break; - case 3: // min-area - RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose ); - break; - case 4: // min-delay - if ( !fBackwardOnly ) - RetValue += Abc_NtkRetimeIncremental( pNtk, 1, 1, fOneStep, fVerbose ); - if ( !fForwardOnly ) - RetValue += Abc_NtkRetimeIncremental( pNtk, 0, 1, fOneStep, fVerbose ); - break; - case 5: // min-area + min-delay - RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose ); - if ( !fBackwardOnly ) - RetValue += Abc_NtkRetimeIncremental( pNtk, 1, 1, 0, fVerbose ); - if ( !fForwardOnly ) - RetValue += Abc_NtkRetimeIncremental( pNtk, 0, 1, 0, fVerbose ); - break; - case 6: // Pan's algorithm - RetValue = Abc_NtkRetimeLValue( pNtk, 500, fVerbose ); - break; - default: - printf( "Unknown retiming option.\n" ); - break; - } - if ( fVerbose ) - { - printf( "Reduction in area = %3d. Reduction in delay = %3d. ", - nLatches - Abc_NtkLatchNum(pNtk), nLevels - Abc_NtkLevel(pNtk) ); - PRT( "Total runtime", clock() - clkTotal ); - } - timeRetime = clock() - clkTotal; - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Used for automated debugging.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeDebug( Abc_Ntk_t * pNtk ) -{ - extern int Abc_NtkSecFraig( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nFrames, int fVerbose ); - Abc_Ntk_t * pNtkRet; - assert( Abc_NtkIsLogic(pNtk) ); - Abc_NtkToSop( pNtk, 0 ); -// if ( !Abc_NtkCheck( pNtk ) ) -// fprintf( stdout, "Abc_NtkRetimeDebug(): Network check has failed.\n" ); -// Io_WriteBlifLogic( pNtk, "debug_temp.blif", 1 ); - pNtkRet = Abc_NtkDup( pNtk ); - Abc_NtkRetime( pNtkRet, 3, 0, 1, 0, 0 ); // debugging backward flow - return !Abc_NtkSecFraig( pNtk, pNtkRet, 10000, 3, 0 ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/ret/retDelay.c b/src/opt/ret/retDelay.c deleted file mode 100644 index bcfe3a2e..00000000 --- a/src/opt/ret/retDelay.c +++ /dev/null @@ -1,305 +0,0 @@ -/**CFile**************************************************************** - - FileName [retDelay.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Retiming package.] - - Synopsis [Incremental retiming for optimum delay.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Oct 31, 2006.] - - Revision [$Id: retDelay.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "retInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose ); -static int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical ); -static int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Retimes incrementally for minimum delay.] - - Description [This procedure cannot be called in the application code - because it assumes that the network is preprocessed by removing LIs/LOs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nIterLimit, int fForward, int fVerbose ) -{ - int IterBest, DelayBest; - int IterBest2, DelayBest2; - // try to find the best delay iteration on a copy - DelayBest = Abc_NtkRetimeMinDelayTry( pNtkCopy, fForward, 0, nIterLimit, &IterBest, fVerbose ); - if ( IterBest == 0 ) - return 1; - // perform the given number of iterations on the original network - DelayBest2 = Abc_NtkRetimeMinDelayTry( pNtk, fForward, 1, IterBest, &IterBest2, fVerbose ); - assert( DelayBest == DelayBest2 ); - assert( IterBest == IterBest2 ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns the best delay and the number of best iteration.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeMinDelayTry( Abc_Ntk_t * pNtk, int fForward, int fInitial, int nIterLimit, int * pIterBest, int fVerbose ) -{ - Abc_Ntk_t * pNtkNew = NULL; - Vec_Ptr_t * vCritical; - Vec_Int_t * vValues; - Abc_Obj_t * pObj; - int i, k, IterBest, DelayCur, DelayBest, DelayStart, LatchesBest; - // transfer intitial values - if ( fInitial ) - { - if ( fForward ) - Abc_NtkRetimeTranferToCopy( pNtk ); - else - { - // save initial value of the latches - vValues = Abc_NtkRetimeCollectLatchValues( pNtk ); - // start the network for initial value computation - pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk ); - } - } - -if ( fVerbose && !fInitial ) - printf( "Performing analysis:\n" ); - // find the best iteration - DelayBest = ABC_INFINITY; IterBest = 0; LatchesBest = Abc_NtkLatchNum(pNtk); - vCritical = Vec_PtrAlloc( 100 ); - for ( i = 0; ; i++ ) - { - // perform moves for the timing-critical nodes - DelayCur = Abc_NtkRetimeTiming( pNtk, fForward, vCritical ); - if ( i == 0 ) - DelayStart = DelayCur; - // record this position if it has the best delay - if ( DelayBest > DelayCur ) - { -if ( fVerbose && !fInitial ) - printf( "%s Iter = %3d. Delay = %3d. Latches = %5d. Delta = %6.2f. Ratio = %4.2f %%\n", - fForward ? "Fwd": "Bwd", i, DelayCur, Abc_NtkLatchNum(pNtk), - 1.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/(DelayBest-DelayCur), - 100.0*(Abc_NtkLatchNum(pNtk)-LatchesBest)/Abc_NtkLatchNum(pNtk)/(DelayBest-DelayCur) ); - - DelayBest = DelayCur; - IterBest = i; - LatchesBest = Abc_NtkLatchNum(pNtk); - } - // quit after timing analysis - if ( i == nIterLimit ) - break; - // skip if 10 interations did not give improvement - if ( i - IterBest > 20 ) - break; - // try retiming to improve the delay - Vec_PtrForEachEntry( vCritical, pObj, k ) - if ( Abc_NtkRetimeNodeIsEnabled(pObj, fForward) ) - Abc_NtkRetimeNode( pObj, fForward, fInitial ); - // share latches - if ( !fForward ) - Abc_NtkRetimeShareLatches( pNtk, fInitial ); - } - Vec_PtrFree( vCritical ); - // transfer the initial state back to the latches - if ( fInitial ) - { - if ( fForward ) - Abc_NtkRetimeTranferFromCopy( pNtk ); - else - { - Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose ); - Abc_NtkDelete( pNtkNew ); - Vec_IntFree( vValues ); - } - } -if ( fVerbose && !fInitial ) - printf( "%s : Starting delay = %3d. Final delay = %3d. IterBest = %2d (out of %2d).\n", - fForward? "Forward " : "Backward", DelayStart, DelayBest, IterBest, nIterLimit ); - *pIterBest = (nIterLimit == 1) ? 1 : IterBest; - return DelayBest; -} - -/**Function************************************************************* - - Synopsis [Returns the set of timing-critical nodes.] - - Description [Performs static timing analysis on the network. Uses - unit-delay model.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeTiming( Abc_Ntk_t * pNtk, int fForward, Vec_Ptr_t * vCritical ) -{ - Vec_Ptr_t * vLatches; - Abc_Obj_t * pObj, * pNext; - int i, k, LevelCur, LevelMax = 0; - // mark all objects except nodes - Abc_NtkIncrementTravId(pNtk); - vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( Abc_ObjIsLatch(pObj) ) - Vec_PtrPush( vLatches, pObj ); - if ( Abc_ObjIsNode(pObj) ) - continue; - pObj->Level = 0; - Abc_NodeSetTravIdCurrent( pObj ); - } - // perform analysis from CIs/COs - if ( fForward ) - { - Vec_PtrForEachEntry( vLatches, pObj, i ) - { - Abc_ObjForEachFanout( pObj, pNext, k ) - { - LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); - if ( LevelMax < LevelCur ) - LevelMax = LevelCur; - } - } - Abc_NtkForEachPi( pNtk, pObj, i ) - { - Abc_ObjForEachFanout( pObj, pNext, k ) - { - LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); - if ( LevelMax < LevelCur ) - LevelMax = LevelCur; - } - } - } - else - { - Vec_PtrForEachEntry( vLatches, pObj, i ) - { - LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward ); - if ( LevelMax < LevelCur ) - LevelMax = LevelCur; - } - Abc_NtkForEachPo( pNtk, pObj, i ) - { - LevelCur = Abc_NtkRetimeTiming_rec( Abc_ObjFanin0(pObj), fForward ); - if ( LevelMax < LevelCur ) - LevelMax = LevelCur; - } - } - // collect timing critical nodes, which should be retimed forward/backward - Vec_PtrClear( vCritical ); - Abc_NtkIncrementTravId(pNtk); - if ( fForward ) - { - Vec_PtrForEachEntry( vLatches, pObj, i ) - { - Abc_ObjForEachFanout( pObj, pNext, k ) - { - if ( Abc_NodeIsTravIdCurrent(pNext) ) - continue; - if ( LevelMax != (int)pNext->Level ) - continue; - // new critical node - Vec_PtrPush( vCritical, pNext ); - Abc_NodeSetTravIdCurrent( pNext ); - } - } - } - else - { - Vec_PtrForEachEntry( vLatches, pObj, i ) - { - Abc_ObjForEachFanin( pObj, pNext, k ) - { - if ( Abc_NodeIsTravIdCurrent(pNext) ) - continue; - if ( LevelMax != (int)pNext->Level ) - continue; - // new critical node - Vec_PtrPush( vCritical, pNext ); - Abc_NodeSetTravIdCurrent( pNext ); - } - } - } - Vec_PtrFree( vLatches ); - return LevelMax; -} - -/**Function************************************************************* - - Synopsis [Recursively performs timing analysis.] - - Description [Performs static timing analysis on the network. Uses - unit-delay model.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeTiming_rec( Abc_Obj_t * pObj, int fForward ) -{ - Abc_Obj_t * pNext; - int i, LevelCur, LevelMax = 0; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return pObj->Level; - Abc_NodeSetTravIdCurrent(pObj); - // visit the next nodes - if ( fForward ) - { - Abc_ObjForEachFanout( pObj, pNext, i ) - { - LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); - if ( LevelMax < LevelCur ) - LevelMax = LevelCur; - } - } - else - { - Abc_ObjForEachFanin( pObj, pNext, i ) - { - LevelCur = Abc_NtkRetimeTiming_rec( pNext, fForward ); - if ( LevelMax < LevelCur ) - LevelMax = LevelCur; - } - } -// printf( "Node %3d -> Level %3d.\n", pObj->Id, LevelMax + 1 ); - pObj->Level = LevelMax + 1; - return pObj->Level; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/ret/retFlow.c b/src/opt/ret/retFlow.c deleted file mode 100644 index 47ee8516..00000000 --- a/src/opt/ret/retFlow.c +++ /dev/null @@ -1,783 +0,0 @@ -/**CFile**************************************************************** - - FileName [retFlow.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Implementation of maximum flow (min-area retiming).] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Oct 31, 2006.] - - Revision [$Id: retFlow.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "retInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static inline int Abc_ObjSetPath( Abc_Obj_t * pObj, Abc_Obj_t * pNext ) { pObj->pCopy = pNext; return 1; } -static inline Abc_Obj_t * Abc_ObjGetPath( Abc_Obj_t * pObj ) { return pObj->pCopy; } -static inline Abc_Obj_t * Abc_ObjGetFanoutPath( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout; - int i; - assert( Abc_ObjGetPath(pObj) ); - Abc_ObjForEachFanout( pObj, pFanout, i ) - if ( Abc_ObjGetPath(pFanout) == pObj ) - return pFanout; - return NULL; -} -static inline Abc_Obj_t * Abc_ObjGetFaninPath( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanin; - int i; - assert( Abc_ObjGetPath(pObj) ); - Abc_ObjForEachFanin( pObj, pFanin, i ) - if ( Abc_ObjGetPath(pFanin) == pObj ) - return pFanin; - return NULL; -} -static inline Abc_Obj_t * Abc_ObjGetPredecessorBwd( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pNext; - int i; - Abc_ObjForEachFanout( pObj, pNext, i ) - if ( Abc_ObjGetPath(pNext) == pObj ) - return pNext; - Abc_ObjForEachFanin( pObj, pNext, i ) - if ( Abc_ObjGetPath(pNext) == pObj ) - return pNext; - return NULL; -} -static inline Abc_Obj_t * Abc_ObjGetPredecessorFwd( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pNext; - int i; - Abc_ObjForEachFanin( pObj, pNext, i ) - if ( Abc_ObjGetPath(pNext) == pObj ) - return pNext; - Abc_ObjForEachFanout( pObj, pNext, i ) - if ( Abc_ObjGetPath(pNext) == pObj ) - return pNext; - return NULL; -} - -static int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ); -static int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ); -static int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj ); -static int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj ); -//static int Abc_NtkMaxFlowBwdPath3_rec( Abc_Obj_t * pObj ); -static int Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin ); -static Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward ); -static void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ); -static int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ); -static void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ); -static void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Test-bench for the max-flow computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vMinCut; - Abc_Obj_t * pObj; - int i; - - // forward flow - Abc_NtkForEachPo( pNtk, pObj, i ) - pObj->fMarkA = 1; - Abc_NtkForEachLatch( pNtk, pObj, i ) - pObj->fMarkA = Abc_ObjFanin0(pObj)->fMarkA = 1; -// Abc_ObjFanin0(pObj)->fMarkA = 1; - vMinCut = Abc_NtkMaxFlow( pNtk, 1, 1 ); - Vec_PtrFree( vMinCut ); - Abc_NtkCleanMarkA( pNtk ); - - // backward flow - Abc_NtkForEachPi( pNtk, pObj, i ) - pObj->fMarkA = 1; - Abc_NtkForEachLatch( pNtk, pObj, i ) - pObj->fMarkA = Abc_ObjFanout0(pObj)->fMarkA = 1; -// Abc_ObjFanout0(pObj)->fMarkA = 1; - vMinCut = Abc_NtkMaxFlow( pNtk, 0, 1 ); - Vec_PtrFree( vMinCut ); - Abc_NtkCleanMarkA( pNtk ); - -} - -/**Function************************************************************* - - Synopsis [Implementation of max-flow/min-cut computation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) -{ - Vec_Ptr_t * vMinCut; - Abc_Obj_t * pLatch; - int Flow, FlowCur, RetValue, i; - int clk = clock(); - int fUseDirectedFlow = 1; - - // find the max-flow - Abc_NtkCleanCopy( pNtk ); - Flow = 0; - Abc_NtkIncrementTravId(pNtk); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - if ( fForward ) - { -// assert( !Abc_ObjFanout0(pLatch)->fMarkA ); - FlowCur = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) ); -// FlowCur = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 ); - Flow += FlowCur; - } - else - { - assert( !Abc_ObjFanin0(pLatch)->fMarkA ); - FlowCur = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) ); - Flow += FlowCur; - } - if ( FlowCur ) - Abc_NtkIncrementTravId(pNtk); - } - - if ( !fUseDirectedFlow ) - { - Abc_NtkIncrementTravId(pNtk); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - if ( fForward ) - { - // assert( !Abc_ObjFanout0(pLatch)->fMarkA ); - FlowCur = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) ); - Flow += FlowCur; - } - else - { - assert( !Abc_ObjFanin0(pLatch)->fMarkA ); - FlowCur = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) ); - Flow += FlowCur; - } - if ( FlowCur ) - Abc_NtkIncrementTravId(pNtk); - } - } -// Abc_NtkMaxFlowPrintFlow( pNtk, fForward ); - - // mark the nodes reachable from the latches - Abc_NtkIncrementTravId(pNtk); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - if ( fForward ) - { -// assert( !Abc_ObjFanout0(pLatch)->fMarkA ); - if ( fUseDirectedFlow ) - RetValue = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) ); -// RetValue = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 ); - else - RetValue = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) ); - } - else - { - assert( !Abc_ObjFanin0(pLatch)->fMarkA ); - if ( fUseDirectedFlow ) - RetValue = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) ); - else - RetValue = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) ); - } - assert( RetValue == 0 ); - } - - // find the min-cut with the smallest volume - vMinCut = Abc_NtkMaxFlowMinCut( pNtk, fForward ); - // verify the cut - if ( !Abc_NtkMaxFlowVerifyCut(pNtk, vMinCut, fForward) ) - printf( "Abc_NtkMaxFlow() error! The computed min-cut is not a cut!\n" ); - // make the cut retimable - Abc_NtkMaxFlowMinCutUpdate( pNtk, vMinCut, fForward ); - - // report the results - if ( fVerbose ) - { - printf( "L = %6d. %s max-flow = %6d. Min-cut = %6d. ", - Abc_NtkLatchNum(pNtk), fForward? "Forward " : "Backward", Flow, Vec_PtrSize(vMinCut) ); -PRT( "Time", clock() - clk ); - } - -// Abc_NtkMaxFlowPrintCut( pNtk, vMinCut ); - return vMinCut; -} - -/**Function************************************************************* - - Synopsis [Tries to find an augmenting path originating in this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMaxFlowBwdPath_rec( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pNext, * pPred; - int i; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return 0; - Abc_NodeSetTravIdCurrent(pObj); - // get the predecessor - pPred = Abc_ObjGetPredecessorBwd( pObj ); - // process node without flow - if ( !Abc_ObjGetPath(pObj) ) - { - // start the path if we reached a terminal node - if ( pObj->fMarkA ) - return Abc_ObjSetPath( pObj, (void *)1 ); - // explore the fanins - Abc_ObjForEachFanin( pObj, pNext, i ) - if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) ) - return Abc_ObjSetPath( pObj, pNext ); - Abc_ObjForEachFanout( pObj, pNext, i ) - if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec(pNext) ) - return Abc_ObjSetPath( pObj, pNext ); - return 0; - } - // pObj has flow - find the fanout with flow - if ( pPred == NULL ) - return 0; - // go through the successors of the predecessor - Abc_ObjForEachFanin( pPred, pNext, i ) - if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) ) - return Abc_ObjSetPath( pPred, pNext ); - Abc_ObjForEachFanout( pPred, pNext, i ) - if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowBwdPath_rec( pNext ) ) - return Abc_ObjSetPath( pPred, pNext ); - // try the fanout - if ( Abc_NtkMaxFlowBwdPath_rec( pPred ) ) - return Abc_ObjSetPath( pPred, NULL ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Tries to find an augmenting path originating in this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMaxFlowFwdPath_rec( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pNext, * pPred; - int i; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return 0; - Abc_NodeSetTravIdCurrent(pObj); - // get the predecessor - pPred = Abc_ObjGetPredecessorFwd( pObj ); - // process node without flow - if ( !Abc_ObjGetPath(pObj) ) - { - // start the path if we reached a terminal node - if ( pObj->fMarkA ) - return Abc_ObjSetPath( pObj, (void *)1 ); - // explore the fanins - Abc_ObjForEachFanout( pObj, pNext, i ) - if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) ) - return Abc_ObjSetPath( pObj, pNext ); - Abc_ObjForEachFanin( pObj, pNext, i ) - if ( pNext != pPred && !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec(pNext) ) - return Abc_ObjSetPath( pObj, pNext ); - return 0; - } - // pObj has flow - find the fanout with flow - if ( pPred == NULL ) - return 0; - // go through the successors of the predecessor - Abc_ObjForEachFanout( pPred, pNext, i ) - if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) ) - return Abc_ObjSetPath( pPred, pNext ); - Abc_ObjForEachFanin( pPred, pNext, i ) - if ( !Abc_ObjIsLatch(pNext) && Abc_NtkMaxFlowFwdPath_rec( pNext ) ) - return Abc_ObjSetPath( pPred, pNext ); - // try the fanout - if ( Abc_NtkMaxFlowFwdPath_rec( pPred ) ) - return Abc_ObjSetPath( pPred, NULL ); - return 0; -} - - -/**Function************************************************************* - - Synopsis [Tries to find an augmenting path originating in this edge.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMaxFlowFwdPath3_rec( Abc_Obj_t * pObj, Abc_Obj_t * pPrev, int fFanin ) -{ - Abc_Obj_t * pFanin, * pFanout; - int i; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return 0; - Abc_NodeSetTravIdCurrent(pObj); - // skip the fanin which already has flow - if ( fFanin && Abc_ObjGetPath(pPrev) ) - return 0; - // if the node has no flow, try to push through the fanouts - if ( !Abc_ObjGetPath(pObj) ) - { - // start the path if we reached a terminal node - if ( pObj->fMarkA ) - return Abc_ObjSetPath( pObj, (void *)1 ); - // try to push flow through the fanouts - Abc_ObjForEachFanout( pObj, pFanout, i ) - if ( Abc_NtkMaxFlowFwdPath3_rec(pFanout, pObj, 1) ) - return fFanin? Abc_ObjSetPath(pPrev, pObj) : 1; - } - // try to push through the fanins - Abc_ObjForEachFanin( pObj, pFanin, i ) - if ( !Abc_ObjIsLatch(pFanin) && Abc_NtkMaxFlowFwdPath3_rec(pFanin, pObj, 0) ) - return Abc_ObjSetPath( pFanin, NULL ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Tries to find an augmenting path originating in this node.] - - Description [This procedure works for directed graphs only!] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMaxFlowBwdPath2_rec( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout, * pFanin; - int i; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return 0; - Abc_NodeSetTravIdCurrent(pObj); - // process node without flow - if ( !Abc_ObjGetPath(pObj) ) - { - // start the path if we reached a terminal node - if ( pObj->fMarkA ) - return Abc_ObjSetPath( pObj, (void *)1 ); - // explore the fanins - Abc_ObjForEachFanin( pObj, pFanin, i ) - if ( Abc_NtkMaxFlowBwdPath2_rec(pFanin) ) - return Abc_ObjSetPath( pObj, pFanin ); - return 0; - } - // pObj has flow - find the fanout with flow - pFanout = Abc_ObjGetFanoutPath( pObj ); - if ( pFanout == NULL ) - return 0; - // go through the fanins of the fanout with flow - Abc_ObjForEachFanin( pFanout, pFanin, i ) - if ( Abc_NtkMaxFlowBwdPath2_rec( pFanin ) ) - return Abc_ObjSetPath( pFanout, pFanin ); - // try the fanout - if ( Abc_NtkMaxFlowBwdPath2_rec( pFanout ) ) - return Abc_ObjSetPath( pFanout, NULL ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Tries to find an augmenting path originating in this node.] - - Description [This procedure works for directed graphs only!] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMaxFlowFwdPath2_rec( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout, * pFanin; - int i; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return 0; - Abc_NodeSetTravIdCurrent(pObj); - // process node without flow - if ( !Abc_ObjGetPath(pObj) ) - { - // start the path if we reached a terminal node - if ( pObj->fMarkA ) - return Abc_ObjSetPath( pObj, (void *)1 ); - // explore the fanins - Abc_ObjForEachFanout( pObj, pFanout, i ) - if ( Abc_NtkMaxFlowFwdPath2_rec(pFanout) ) - return Abc_ObjSetPath( pObj, pFanout ); - return 0; - } - // pObj has flow - find the fanout with flow - pFanin = Abc_ObjGetFaninPath( pObj ); - if ( pFanin == NULL ) - return 0; - // go through the fanins of the fanout with flow - Abc_ObjForEachFanout( pFanin, pFanout, i ) - if ( Abc_NtkMaxFlowFwdPath2_rec( pFanout ) ) - return Abc_ObjSetPath( pFanin, pFanout ); - // try the fanout - if ( Abc_NtkMaxFlowFwdPath2_rec( pFanin ) ) - return Abc_ObjSetPath( pFanin, NULL ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Find minimum-volume minumum cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_NtkMaxFlowMinCut( Abc_Ntk_t * pNtk, int fForward ) -{ - Vec_Ptr_t * vMinCut; - Abc_Obj_t * pObj; - int i; - // collect the cut nodes - vMinCut = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - // node without flow is not a cut node - if ( !Abc_ObjGetPath(pObj) ) - continue; - // unvisited node is below the cut - if ( !Abc_NodeIsTravIdCurrent(pObj) ) - continue; - // add terminal with flow or node whose path is not visited - if ( pObj->fMarkA || !Abc_NodeIsTravIdCurrent( Abc_ObjGetPath(pObj) ) ) - Vec_PtrPush( vMinCut, pObj ); - } - return vMinCut; -} - -/**Function************************************************************* - - Synopsis [Marks the TFI cone with MarkA.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMaxFlowMarkCut_rec( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pNext; - int i; - if ( pObj->fMarkA ) - return; - pObj->fMarkA = 1; - Abc_ObjForEachFanin( pObj, pNext, i ) - Abc_NtkMaxFlowMarkCut_rec( pNext ); -} - -/**Function************************************************************* - - Synopsis [Visits the TFI up to marked nodes and collects marked nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMaxFlowCollectCut_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) -{ - Abc_Obj_t * pNext; - int i; - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return; - Abc_NodeSetTravIdCurrent(pObj); - if ( pObj->fMarkA ) - { - Vec_PtrPush( vNodes, pObj ); - return; - } - Abc_ObjForEachFanin( pObj, pNext, i ) - Abc_NtkMaxFlowCollectCut_rec( pNext, vNodes ); -} - -/**Function************************************************************* - - Synopsis [Updates the minimum cut to be retimable.] - - Description [This procedure also labels the nodes reachable from - the latches to the cut with fMarkA.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMaxFlowMinCutUpdate( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ) -{ - Abc_Obj_t * pObj, * pNext; - int i, k; - // clean marks - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->fMarkA = 0; - // set latch outputs - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_ObjFanout0(pObj)->fMarkA = 1; - // traverse from cut nodes - Vec_PtrForEachEntry( vMinCut, pObj, i ) - Abc_NtkMaxFlowMarkCut_rec( pObj ); - if ( fForward ) - { - // change mincut to be nodes with unmarked fanouts - Vec_PtrClear( vMinCut ); - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( !pObj->fMarkA ) - continue; - Abc_ObjForEachFanout( pObj, pNext, k ) - { - if ( pNext->fMarkA ) - continue; - Vec_PtrPush( vMinCut, pObj ); - break; - } - } - } - else - { - // change mincut to be marked fanins of the unmarked nodes - Vec_PtrClear( vMinCut ); - Abc_NtkIncrementTravId(pNtk); - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_NtkMaxFlowCollectCut_rec( Abc_ObjFanin0(pObj), vMinCut ); - // transfer the attribute - Abc_NtkForEachObj( pNtk, pObj, i ) - pObj->fMarkA = Abc_NodeIsTravIdCurrent(pObj); - // unmark the cut nodes - Vec_PtrForEachEntry( vMinCut, pObj, i ) - pObj->fMarkA = 0; - } -} - -/**Function************************************************************* - - Synopsis [Verifies the min-cut is indeed a cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMaxFlowVerifyCut_rec( Abc_Obj_t * pObj, int fForward ) -{ - Abc_Obj_t * pNext; - int i; - // skip visited nodes - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return 1; - Abc_NodeSetTravIdCurrent(pObj); - // visit the node - if ( fForward ) - { - if ( Abc_ObjIsCo(pObj) ) - return 0; - // explore the fanouts - Abc_ObjForEachFanout( pObj, pNext, i ) - if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) ) - return 0; - } - else - { - if ( Abc_ObjIsCi(pObj) ) - return 0; - // explore the fanins - Abc_ObjForEachFanin( pObj, pNext, i ) - if ( !Abc_NtkMaxFlowVerifyCut_rec(pNext, fForward) ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Verifies the min-cut is indeed a cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkMaxFlowVerifyCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut, int fForward ) -{ - Abc_Obj_t * pObj; - int i; - // mark the cut with the current traversal ID - Abc_NtkIncrementTravId(pNtk); - Vec_PtrForEachEntry( vMinCut, pObj, i ) - Abc_NodeSetTravIdCurrent( pObj ); - // search from the latches for a path to the COs/CIs - Abc_NtkForEachLatch( pNtk, pObj, i ) - { - if ( fForward ) - { - if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanout0(pObj), fForward ) ) - return 0; - } - else - { - if ( !Abc_NtkMaxFlowVerifyCut_rec( Abc_ObjFanin0(pObj), fForward ) ) - return 0; - } - } -/* - { - // count the volume of the cut - int Counter = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - Counter += Abc_NodeIsTravIdCurrent( pObj ); - printf( "Volume = %d.\n", Counter ); - } -*/ - return 1; -} - -/**Function************************************************************* - - Synopsis [Prints the flows.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMaxFlowPrintFlow( Abc_Ntk_t * pNtk, int fForward ) -{ - Abc_Obj_t * pLatch, * pNext, * pPrev; - int i; - if ( fForward ) - { - Vec_PtrForEachEntry( pNtk->vBoxes, pLatch, i ) - { - assert( !Abc_ObjFanout0(pLatch)->fMarkA ); - if ( Abc_ObjGetPath(Abc_ObjFanout0(pLatch)) == NULL ) // no flow through this latch - continue; - printf( "Path = " ); - for ( pNext = Abc_ObjFanout0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) ) - { - printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id ); - pPrev = pNext; - } - if ( !Abc_ObjIsPo(pPrev) ) - printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanout0(pPrev)), Abc_ObjFanout0(pPrev)->Id ); - printf( "\n" ); - } - } - else - { - Vec_PtrForEachEntry( pNtk->vBoxes, pLatch, i ) - { - assert( !Abc_ObjFanin0(pLatch)->fMarkA ); - if ( Abc_ObjGetPath(Abc_ObjFanin0(pLatch)) == NULL ) // no flow through this latch - continue; - printf( "Path = " ); - for ( pNext = Abc_ObjFanin0(pLatch); pNext != (void *)1; pNext = Abc_ObjGetPath(pNext) ) - { - printf( "%s(%d) ", Abc_ObjName(pNext), pNext->Id ); - pPrev = pNext; - } - if ( !Abc_ObjIsPi(pPrev) ) - printf( "%s(%d) ", Abc_ObjName(Abc_ObjFanin0(pPrev)), Abc_ObjFanin0(pPrev)->Id ); - printf( "\n" ); - } - } -} - -/**Function************************************************************* - - Synopsis [Prints the min-cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkMaxFlowPrintCut( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMinCut ) -{ - Abc_Obj_t * pObj; - int i; - printf( "Min-cut: " ); - Vec_PtrForEachEntry( vMinCut, pObj, i ) - printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id ); - printf( "\n" ); - printf( "Marked nodes: " ); - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( pObj->fMarkA ) - printf( "%s(%d) ", Abc_ObjName(pObj), pObj->Id ); - printf( "\n" ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/ret/retIncrem.c b/src/opt/ret/retIncrem.c deleted file mode 100644 index ba8104be..00000000 --- a/src/opt/ret/retIncrem.c +++ /dev/null @@ -1,464 +0,0 @@ -/**CFile**************************************************************** - - FileName [retIncrem.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Retiming package.] - - Synopsis [Incremental retiming in one direction.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Oct 31, 2006.] - - Revision [$Id: retIncrem.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "retInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs retiming in one direction.] - - Description [Currently does not retime over black boxes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int fOneStep, int fVerbose ) -{ - Abc_Ntk_t * pNtkCopy = NULL; - Vec_Ptr_t * vBoxes; - st_table * tLatches; - int nLatches = Abc_NtkLatchNum(pNtk); - int nIdMaxStart = Abc_NtkObjNumMax(pNtk); - int RetValue, nIterLimit; - if ( Abc_NtkNodeNum(pNtk) == 0 ) - return 0; - // reorder CI/CO/latch inputs - Abc_NtkOrderCisCos( pNtk ); - if ( fMinDelay ) - { - nIterLimit = fOneStep? 1 : 2 * Abc_NtkLevel(pNtk); - pNtkCopy = Abc_NtkDup( pNtk ); - tLatches = Abc_NtkRetimePrepareLatches( pNtkCopy ); - st_free_table( tLatches ); - } - // collect latches and remove CIs/COs - tLatches = Abc_NtkRetimePrepareLatches( pNtk ); - // share the latches - Abc_NtkRetimeShareLatches( pNtk, 0 ); - // save boxes - vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL; - // perform the retiming - if ( fMinDelay ) - Abc_NtkRetimeMinDelay( pNtk, pNtkCopy, nIterLimit, fForward, fVerbose ); - else - Abc_NtkRetimeOneWay( pNtk, fForward, fVerbose ); - if ( fMinDelay ) - Abc_NtkDelete( pNtkCopy ); - // share the latches - Abc_NtkRetimeShareLatches( pNtk, 0 ); - // restore boxes - pNtk->vBoxes = vBoxes; - // finalize the latches - RetValue = Abc_NtkRetimeFinalizeLatches( pNtk, tLatches, nIdMaxStart ); - st_free_table( tLatches ); - if ( RetValue == 0 ) - return 0; - // fix the COs -// Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); - // check for correctness - if ( !Abc_NtkCheck( pNtk ) ) - fprintf( stdout, "Abc_NtkRetimeForward(): Network check has failed.\n" ); - // return the number of latches saved - return nLatches - Abc_NtkLatchNum(pNtk); -} - -/**Function************************************************************* - - Synopsis [Prepares the network for retiming.] - - Description [Hash latches into their number in the original network.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -st_table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk ) -{ - st_table * tLatches; - Abc_Obj_t * pLatch, * pLatchIn, * pLatchOut, * pFanin; - int i, nOffSet = Abc_NtkBoxNum(pNtk) - Abc_NtkLatchNum(pNtk); - // collect latches and remove CIs/COs - tLatches = st_init_table( st_ptrcmp, st_ptrhash ); - Abc_NtkForEachLatch( pNtk, pLatch, i ) - { - // map latch into its true number - st_insert( tLatches, (void *)pLatch, (void *)(i-nOffSet) ); - // disconnect LI - pLatchIn = Abc_ObjFanin0(pLatch); - pFanin = Abc_ObjFanin0(pLatchIn); - Abc_ObjTransferFanout( pLatchIn, pFanin ); - Abc_ObjDeleteFanin( pLatchIn, pFanin ); - // disconnect LO - pLatchOut = Abc_ObjFanout0(pLatch); - pFanin = Abc_ObjFanin0(pLatchOut); - if ( Abc_ObjFanoutNum(pLatchOut) > 0 ) - Abc_ObjTransferFanout( pLatchOut, pFanin ); - Abc_ObjDeleteFanin( pLatchOut, pFanin ); - } - return tLatches; -} - -/**Function************************************************************* - - Synopsis [Finalizes the latches after retiming.] - - Description [Reuses the LIs/LOs for old latches.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nIdMaxStart ) -{ - Vec_Ptr_t * vCisOld, * vCosOld, * vBoxesOld, * vCisNew, * vCosNew, * vBoxesNew; - Abc_Obj_t * pObj, * pLatch, * pLatchIn, * pLatchOut; - int i, Index; - // create new arrays - vCisOld = pNtk->vCis; pNtk->vCis = NULL; vCisNew = Vec_PtrAlloc( 100 ); - vCosOld = pNtk->vCos; pNtk->vCos = NULL; vCosNew = Vec_PtrAlloc( 100 ); - vBoxesOld = pNtk->vBoxes; pNtk->vBoxes = NULL; vBoxesNew = Vec_PtrAlloc( 100 ); - // copy boxes and their CIs/COs - Vec_PtrForEachEntryStop( vCisOld, pObj, i, Vec_PtrSize(vCisOld) - st_count(tLatches) ) - Vec_PtrPush( vCisNew, pObj ); - Vec_PtrForEachEntryStop( vCosOld, pObj, i, Vec_PtrSize(vCosOld) - st_count(tLatches) ) - Vec_PtrPush( vCosNew, pObj ); - Vec_PtrForEachEntryStop( vBoxesOld, pObj, i, Vec_PtrSize(vBoxesOld) - st_count(tLatches) ) - Vec_PtrPush( vBoxesNew, pObj ); - // go through the latches - Abc_NtkForEachObj( pNtk, pLatch, i ) - { - if ( !Abc_ObjIsLatch(pLatch) ) - continue; - if ( Abc_ObjId(pLatch) >= (unsigned)nIdMaxStart ) - { - // this is a new latch - pLatchIn = Abc_NtkCreateBi(pNtk); - pLatchOut = Abc_NtkCreateBo(pNtk); - Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_out" ); - Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_in" ); - } - else - { - // this is an old latch - // get its number in the original order - if ( !st_lookup( tLatches, (char *)pLatch, (char **)&Index ) ) - { - printf( "Abc_NtkRetimeFinalizeLatches(): Internal error.\n" ); - return 0; - } - assert( pLatch == Vec_PtrEntry(vBoxesOld, Vec_PtrSize(vBoxesOld) - st_count(tLatches) + Index) ); - // reconnect with the old LIs/LOs - pLatchIn = Vec_PtrEntry( vCosOld, Vec_PtrSize(vCosOld) - st_count(tLatches) + Index ); - pLatchOut = Vec_PtrEntry( vCisOld, Vec_PtrSize(vCisOld) - st_count(tLatches) + Index ); - } - // connect - Abc_ObjAddFanin( pLatchIn, Abc_ObjFanin0(pLatch) ); - Abc_ObjPatchFanin( pLatch, Abc_ObjFanin0(pLatch), pLatchIn ); - if ( Abc_ObjFanoutNum(pLatch) > 0 ) - Abc_ObjTransferFanout( pLatch, pLatchOut ); - Abc_ObjAddFanin( pLatchOut, pLatch ); - // add to the arrays - Vec_PtrPush( vCisNew, pLatchOut ); - Vec_PtrPush( vCosNew, pLatchIn ); - Vec_PtrPush( vBoxesNew, pLatch ); - } - // free useless Cis/Cos - Vec_PtrForEachEntry( vCisOld, pObj, i ) - if ( !Abc_ObjIsPi(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 ) - Abc_NtkDeleteObj(pObj); - Vec_PtrForEachEntry( vCosOld, pObj, i ) - if ( !Abc_ObjIsPo(pObj) && Abc_ObjFaninNum(pObj) == 0 && Abc_ObjFanoutNum(pObj) == 0 ) - Abc_NtkDeleteObj(pObj); - // set the new arrays - pNtk->vCis = vCisNew; Vec_PtrFree( vCisOld ); - pNtk->vCos = vCosNew; Vec_PtrFree( vCosOld ); - pNtk->vBoxes = vBoxesNew; Vec_PtrFree( vBoxesOld ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Performs retiming one way, forward or backward.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeOneWay( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) -{ - Abc_Ntk_t * pNtkNew; - Vec_Int_t * vValues; - Abc_Obj_t * pObj; - int i, fChanges, nTotalMoves = 0, nTotalMovesLimit = 10000; - if ( fForward ) - Abc_NtkRetimeTranferToCopy( pNtk ); - else - { - // save initial values of the latches - vValues = Abc_NtkRetimeCollectLatchValues( pNtk ); - // start the network for initial value computation - pNtkNew = Abc_NtkRetimeBackwardInitialStart( pNtk ); - } - // try to move latches forward whenever possible - do { - fChanges = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - { - if ( !Abc_ObjIsNode(pObj) ) - continue; - if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) ) - { - Abc_NtkRetimeNode( pObj, fForward, 1 ); - fChanges = 1; - nTotalMoves++; - if ( nTotalMoves >= nTotalMovesLimit ) - { - printf( "Stopped after %d latch moves.\n", nTotalMoves ); - break; - } - } - } - } while ( fChanges && nTotalMoves < nTotalMovesLimit ); - // transfer the initial state back to the latches - if ( fForward ) - Abc_NtkRetimeTranferFromCopy( pNtk ); - else - { - Abc_NtkRetimeBackwardInitialFinish( pNtk, pNtkNew, vValues, fVerbose ); - Abc_NtkDelete( pNtkNew ); - Vec_IntFree( vValues ); - } - return 0; -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if retiming forward/backward is possible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward ) -{ - Abc_Obj_t * pNext; - int i; - assert( Abc_ObjIsNode(pObj) ); - if ( fForward ) - { - Abc_ObjForEachFanin( pObj, pNext, i ) - if ( !Abc_ObjIsLatch(pNext) ) - return 0; - } - else - { - Abc_ObjForEachFanout( pObj, pNext, i ) - if ( !Abc_ObjIsLatch(pNext) ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Retimes the node backward or forward.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial ) -{ - Abc_Ntk_t * pNtkNew = NULL; - Vec_Ptr_t * vNodes; - Abc_Obj_t * pNext, * pLatch; - int i; - vNodes = Vec_PtrAlloc( 10 ); - if ( fForward ) - { - // compute the initial value - if ( fInitial ) - pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj ); - // collect fanins - Abc_NodeCollectFanins( pObj, vNodes ); - // make the node point to the fanins fanins - Vec_PtrForEachEntry( vNodes, pNext, i ) - { - assert( Abc_ObjIsLatch(pNext) ); - Abc_ObjPatchFanin( pObj, pNext, Abc_ObjFanin0(pNext) ); - if ( Abc_ObjFanoutNum(pNext) == 0 ) - Abc_NtkDeleteObj(pNext); - } - // add a new latch on top - pNext = Abc_NtkCreateLatch(pObj->pNtk); - if ( Abc_ObjFanoutNum(pObj) > 0 ) - Abc_ObjTransferFanout( pObj, pNext ); - Abc_ObjAddFanin( pNext, pObj ); - // set the initial value - if ( fInitial ) - pNext->pCopy = pObj->pCopy; - } - else - { - // compute the initial value - if ( fInitial ) - { - pNtkNew = Abc_ObjFanout0(pObj)->pCopy->pNtk; - Abc_NtkDupObj( pNtkNew, pObj, 0 ); - Abc_ObjForEachFanout( pObj, pNext, i ) - { - assert( Abc_ObjFaninNum(pNext->pCopy) == 0 ); - Abc_ObjAddFanin( pNext->pCopy, pObj->pCopy ); - } - } - // collect fanouts - Abc_NodeCollectFanouts( pObj, vNodes ); - // make the fanouts fanouts point to the node - Vec_PtrForEachEntry( vNodes, pNext, i ) - { - assert( Abc_ObjIsLatch(pNext) ); - Abc_ObjTransferFanout( pNext, pObj ); - Abc_NtkDeleteObj( pNext ); - } - // add new latches to the fanins - Abc_ObjForEachFanin( pObj, pNext, i ) - { - pLatch = Abc_NtkCreateLatch(pObj->pNtk); - Abc_ObjPatchFanin( pObj, pNext, pLatch ); - Abc_ObjAddFanin( pLatch, pNext ); - // create buffer isomorphic to this latch - if ( fInitial ) - { - pLatch->pCopy = Abc_NtkCreateNodeBuf( pNtkNew, NULL ); - Abc_ObjAddFanin( pObj->pCopy, pLatch->pCopy ); - } - } - } - Vec_PtrFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Returns the number of compatible fanout latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeCheckCompatibleLatchFanouts( Abc_Obj_t * pObj ) -{ - Abc_Obj_t * pFanout; - int i, nLatches = 0, Init = -1; - Abc_ObjForEachFanout( pObj, pFanout, i ) - { - if ( !Abc_ObjIsLatch(pFanout) ) - continue; - if ( Init == -1 ) - { - Init = (int)pObj->pData; - nLatches++; - } - else if ( Init == (int)pObj->pData ) - nLatches++; - } - return nLatches; -} - -/**Function************************************************************* - - Synopsis [Retimes the node backward or forward.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pFanin, * pLatchTop, * pLatchCur; - int i, k; - vNodes = Vec_PtrAlloc( 10 ); - // consider latch fanins - Abc_NtkForEachObj( pNtk, pFanin, i ) - { - if ( Abc_NtkRetimeCheckCompatibleLatchFanouts(pFanin) <= 1 ) - continue; - // get the first latch - pLatchTop = NULL; - Abc_ObjForEachFanout( pFanin, pLatchTop, k ) - if ( Abc_ObjIsLatch(pLatchTop) ) - break; - assert( pLatchTop && Abc_ObjIsLatch(pLatchTop) ); - // redirect compatible fanout latches to the first latch - Abc_NodeCollectFanouts( pFanin, vNodes ); - Vec_PtrForEachEntry( vNodes, pLatchCur, k ) - { - if ( !Abc_ObjIsLatch(pLatchCur) ) - continue; - if ( pLatchCur == pLatchTop ) - continue; - if ( pLatchCur->pData != pLatchTop->pData ) - continue; - // connect the initial state - if ( fInitial ) - Abc_ObjAddFanin( pLatchCur->pCopy, pLatchTop->pCopy ); - // redirect the fanouts - Abc_ObjTransferFanout( pLatchCur, pLatchTop ); - Abc_NtkDeleteObj(pLatchCur); - } - } - Vec_PtrFree( vNodes ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/ret/retInit.c b/src/opt/ret/retInit.c deleted file mode 100644 index dcb71c60..00000000 --- a/src/opt/ret/retInit.c +++ /dev/null @@ -1,349 +0,0 @@ -/**CFile**************************************************************** - - FileName [retInit.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Retiming package.] - - Synopsis [Initial state computation for backward retiming.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Oct 31, 2006.] - - Revision [$Id: retInit.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "retInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes initial values of the new latches.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int fVerbose ) -{ - Vec_Int_t * vSolution; - Abc_Ntk_t * pNtkMiter, * pNtkLogic; - int RetValue, clk; - if ( pNtkCone == NULL ) - return Vec_IntDup( vValues ); - // convert the target network to AIG - pNtkLogic = Abc_NtkDup( pNtkCone ); - Abc_NtkToAig( pNtkLogic ); - // get the miter - pNtkMiter = Abc_NtkCreateTarget( pNtkLogic, pNtkLogic->vCos, vValues ); - if ( fVerbose ) - printf( "The miter for initial state computation has %d AIG nodes. ", Abc_NtkNodeNum(pNtkMiter) ); - // solve the miter - clk = clock(); - RetValue = Abc_NtkMiterSat( pNtkMiter, (sint64)500000, (sint64)50000000, 0, NULL, NULL ); - if ( fVerbose ) - { PRT( "SAT solving time", clock() - clk ); } - // analyze the result - if ( RetValue == 1 ) - printf( "Abc_NtkRetimeInitialValues(): The problem is unsatisfiable. DC latch values are used.\n" ); - else if ( RetValue == -1 ) - printf( "Abc_NtkRetimeInitialValues(): The SAT problem timed out. DC latch values are used.\n" ); - else if ( !Abc_NtkRetimeVerifyModel( pNtkCone, vValues, pNtkMiter->pModel ) ) - printf( "Abc_NtkRetimeInitialValues(): The computed counter-example is incorrect.\n" ); - // set the values of the latches - vSolution = RetValue? NULL : Vec_IntAllocArray( pNtkMiter->pModel, Abc_NtkPiNum(pNtkLogic) ); - pNtkMiter->pModel = NULL; - Abc_NtkDelete( pNtkMiter ); - Abc_NtkDelete( pNtkLogic ); - return vSolution; -} - -/**Function************************************************************* - - Synopsis [Computes the results of simulating one node.] - - Description [Assumes that fanins have pCopy set to the input values.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_ObjSopSimulate( Abc_Obj_t * pObj ) -{ - char * pCube, * pSop = pObj->pData; - int nVars, Value, v, ResOr, ResAnd, ResVar; - assert( pSop && !Abc_SopIsExorType(pSop) ); - // simulate the SOP of the node - ResOr = 0; - nVars = Abc_SopGetVarNum(pSop); - Abc_SopForEachCube( pSop, nVars, pCube ) - { - ResAnd = 1; - Abc_CubeForEachVar( pCube, Value, v ) - { - if ( Value == '0' ) - ResVar = 1 ^ ((int)Abc_ObjFanin(pObj, v)->pCopy); - else if ( Value == '1' ) - ResVar = (int)Abc_ObjFanin(pObj, v)->pCopy; - else - continue; - ResAnd &= ResVar; - } - ResOr |= ResAnd; - } - // complement the result if necessary - if ( !Abc_SopGetPhase(pSop) ) - ResOr ^= 1; - return ResOr; -} - -/**Function************************************************************* - - Synopsis [Verifies the counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i, Counter = 0; - assert( Abc_NtkIsSopLogic(pNtkCone) ); - // set the PIs - Abc_NtkForEachPi( pNtkCone, pObj, i ) - pObj->pCopy = (void *)pModel[i]; - // simulate the internal nodes - vNodes = Abc_NtkDfs( pNtkCone, 0 ); - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj ); - Vec_PtrFree( vNodes ); - // compare the outputs - Abc_NtkForEachPo( pNtkCone, pObj, i ) - pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; - Abc_NtkForEachPo( pNtkCone, pObj, i ) - Counter += (Vec_IntEntry(vValues, i) != (int)pObj->pCopy); - if ( Counter > 0 ) - printf( "%d outputs (out of %d) have a value mismatch.\n", Counter, Abc_NtkPoNum(pNtkCone) ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Transfer latch initial values to pCopy.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( Abc_ObjIsLatch(pObj) ) - pObj->pCopy = (void *)Abc_LatchIsInit1(pObj); -} - -/**Function************************************************************* - - Synopsis [Transfer latch initial values from pCopy.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( Abc_ObjIsLatch(pObj) ) - pObj->pData = (void *)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO); -} - -/**Function************************************************************* - - Synopsis [Transfer latch initial values to pCopy.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk ) -{ - Vec_Int_t * vValues; - Abc_Obj_t * pObj; - int i; - vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( Abc_ObjIsLatch(pObj) ) - Vec_IntPush( vValues, Abc_LatchIsInit1(pObj) ); - return vValues; -} - -/**Function************************************************************* - - Synopsis [Transfer latch initial values from pCopy.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ) -{ - Abc_Obj_t * pObj; - int i, Counter = 0; - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( Abc_ObjIsLatch(pObj) ) - pObj->pCopy = (void *)Counter++; - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( Abc_ObjIsLatch(pObj) ) - pObj->pData = (void *)(vValues? (Vec_IntEntry(vValues,(int)pObj->pCopy)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC); -} - -/**Function************************************************************* - - Synopsis [Transfer latch initial values to pCopy.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk ) -{ - Abc_Ntk_t * pNtkNew; - Abc_Obj_t * pObj; - int i; - // create the network used for the initial state computation - pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); - // create POs corresponding to the initial values - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( Abc_ObjIsLatch(pObj) ) - pObj->pCopy = Abc_NtkCreatePo(pNtkNew); - return pNtkNew; -} - -/**Function************************************************************* - - Synopsis [Transfer latch initial values to pCopy.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose ) -{ - Vec_Int_t * vValuesNew; - Abc_Obj_t * pObj; - int i; - // create PIs corresponding to the initial values - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( Abc_ObjIsLatch(pObj) ) - Abc_ObjAddFanin( pObj->pCopy, Abc_NtkCreatePi(pNtkNew) ); - // assign dummy node names - Abc_NtkAddDummyPiNames( pNtkNew ); - Abc_NtkAddDummyPoNames( pNtkNew ); - // check the network - if ( !Abc_NtkCheck( pNtkNew ) ) - fprintf( stdout, "Abc_NtkRetimeBackwardInitialFinish(): Network check has failed.\n" ); - // derive new initial values - vValuesNew = Abc_NtkRetimeInitialValues( pNtkNew, vValuesOld, fVerbose ); - // insert new initial values - Abc_NtkRetimeInsertLatchValues( pNtk, vValuesNew ); - if ( vValuesNew ) Vec_IntFree( vValuesNew ); -} - - -/**Function************************************************************* - - Synopsis [Cycles the circuit to create a new initial state.] - - Description [Simulates the circuit with random input for the given - number of timeframes to get a better initial state.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pObj; - int i, f; - assert( Abc_NtkIsSopLogic(pNtk) ); - srand( 0x12341234 ); - // initialize the values - Abc_NtkForEachPi( pNtk, pObj, i ) - pObj->pCopy = (void *)(rand() & 1); - Abc_NtkForEachLatch( pNtk, pObj, i ) - pObj->pCopy = (void *)Abc_LatchIsInit1(pObj); - // simulate for the given number of timeframes - vNodes = Abc_NtkDfs( pNtk, 0 ); - for ( f = 0; f < nFrames; f++ ) - { - // simulate internal nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->pCopy = (void *)Abc_ObjSopSimulate( pObj ); - // bring the results to the COs - Abc_NtkForEachCo( pNtk, pObj, i ) - pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; - // assign PI values - Abc_NtkForEachPi( pNtk, pObj, i ) - pObj->pCopy = (void *)(rand() & 1); - // transfer the latch values - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_ObjFanout0(pObj)->pCopy = Abc_ObjFanin0(pObj)->pCopy; - } - Vec_PtrFree( vNodes ); - // set the final values - Abc_NtkForEachLatch( pNtk, pObj, i ) - pObj->pData = (void *)(Abc_ObjFanout0(pObj)->pCopy ? ABC_INIT_ONE : ABC_INIT_ZERO); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/ret/retInt.h b/src/opt/ret/retInt.h deleted file mode 100644 index 51428bce..00000000 --- a/src/opt/ret/retInt.h +++ /dev/null @@ -1,80 +0,0 @@ -/**CFile**************************************************************** - - FileName [retInt.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Retiming package.] - - Synopsis [Internal declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Oct 31, 2006.] - - Revision [$Id: retInt.h,v 1.00 2006/10/31 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __RET_INT_H__ -#define __RET_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "abc.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== retArea.c ========================================================*/ -extern int Abc_NtkRetimeMinArea( Abc_Ntk_t * pNtk, int fForwardOnly, int fBackwardOnly, int fVerbose ); -/*=== retCore.c ========================================================*/ -extern int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose ); -/*=== retDelay.c ========================================================*/ -extern int Abc_NtkRetimeMinDelay( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkCopy, int nIterLimit, int fForward, int fVerbose ); -/*=== retDirect.c ========================================================*/ -extern int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int fForward, int fMinDelay, int fOneStep, int fVerbose ); -extern void Abc_NtkRetimeShareLatches( Abc_Ntk_t * pNtk, int fInitial ); -extern int Abc_NtkRetimeNodeIsEnabled( Abc_Obj_t * pObj, int fForward ); -extern void Abc_NtkRetimeNode( Abc_Obj_t * pObj, int fForward, int fInitial ); -extern st_table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk ); -extern int Abc_NtkRetimeFinalizeLatches( Abc_Ntk_t * pNtk, st_table * tLatches, int nIdMaxStart ); -/*=== retFlow.c ========================================================*/ -extern void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ); -extern Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose ); -/*=== retInit.c ========================================================*/ -extern Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkSat, Vec_Int_t * vValues, int fVerbose ); -extern int Abc_ObjSopSimulate( Abc_Obj_t * pObj ); -extern void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk ); -extern void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk ); -extern Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk ); -extern void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ); -extern Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk ); -extern void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose ); -/*=== retLvalue.c ========================================================*/ -extern int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/ret/retLvalue.c b/src/opt/ret/retLvalue.c deleted file mode 100644 index b4d9e946..00000000 --- a/src/opt/ret/retLvalue.c +++ /dev/null @@ -1,395 +0,0 @@ -/**CFile**************************************************************** - - FileName [retLvalue.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Retiming package.] - - Synopsis [Implementation of Pan's retiming algorithm.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Oct 31, 2006.] - - Revision [$Id: retLvalue.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "retInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// node status after updating its arrival time -enum { ABC_RET_UPDATE_FAIL, ABC_RET_UPDATE_NO, ABC_RET_UPDATE_YES }; - -// the internal procedures -static Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ); -static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose ); -static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose ); -static int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi ); -static int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi ); -static Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk ); -static int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose ); - -static inline int Abc_NodeComputeLag( int LValue, int Fi ) { return (LValue + (1<<16)*Fi)/Fi - (1<<16) - (int)(LValue % Fi == 0); } -static inline int Abc_NodeGetLValue( Abc_Obj_t * pNode ) { return (int)pNode->pCopy; } -static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { pNode->pCopy = (void *)Value; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Implements Pan's retiming algorithm.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeLValue( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ) -{ - Vec_Int_t * vLags; - int nLatches = Abc_NtkLatchNum(pNtk); - assert( Abc_NtkIsLogic( pNtk ) ); - // get the lags - vLags = Abc_NtkRetimeGetLags( pNtk, nIterLimit, fVerbose ); - // compute the retiming -// Abc_NtkRetimeUsingLags( pNtk, vLags, fVerbose ); - Vec_IntFree( vLags ); - // fix the COs -// Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); - // check for correctness - if ( !Abc_NtkCheck( pNtk ) ) - fprintf( stdout, "Abc_NtkRetimeLValue(): Network check has failed.\n" ); - // return the number of latches saved - return nLatches - Abc_NtkLatchNum(pNtk); -} - -/**Function************************************************************* - - Synopsis [Computes the retiming lags.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Abc_NtkRetimeGetLags( Abc_Ntk_t * pNtk, int nIterLimit, int fVerbose ) -{ - Vec_Int_t * vLags; - Vec_Ptr_t * vNodes, * vLatches; - Abc_Obj_t * pNode; - int i, FiMax, FiBest, RetValue, clk, clkIter; - char NodeLag; - - // get the upper bound on the clock period - FiMax = Abc_NtkLevel(pNtk); - - // make sure this clock period is feasible - vNodes = Abc_NtkDfs( pNtk, 0 ); - vLatches = Abc_ManCollectLatches( pNtk ); - if ( !Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiMax, nIterLimit, fVerbose ) ) - { - Vec_PtrFree( vNodes ); - printf( "Abc_NtkRetimeGetLags() error: The upper bound on the clock period cannot be computed.\n" ); - return Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); - } - - // search for the optimal clock period between 0 and nLevelMax -clk = clock(); - FiBest = Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, 0, FiMax, nIterLimit, fVerbose ); -clkIter = clock() - clk; - - // recompute the best l-values - RetValue = Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, FiBest, nIterLimit, fVerbose ); - assert( RetValue ); - - // fix the problem with non-converged delays - Abc_NtkForEachNode( pNtk, pNode, i ) - if ( Abc_NodeGetLValue(pNode) < -ABC_INFINITY/2 ) - Abc_NodeSetLValue( pNode, 0 ); - - // write the retiming lags - vLags = Vec_IntStart( Abc_NtkObjNumMax(pNtk) + 1 ); - Abc_NtkForEachNode( pNtk, pNode, i ) - { - NodeLag = Abc_NodeComputeLag( Abc_NodeGetLValue(pNode), FiBest ); - Vec_IntWriteEntry( vLags, pNode->Id, NodeLag ); - } -/* - Abc_NtkForEachPo( pNtk, pNode, i ) - printf( "%d ", Abc_NodeGetLValue(Abc_ObjFanin0(pNode)) ); - printf( "\n" ); - Abc_NtkForEachLatch( pNtk, pNode, i ) - printf( "%d/%d ", Abc_NodeGetLValue(Abc_ObjFanout0(pNode)), Abc_NodeGetLValue(Abc_ObjFanout0(pNode)) + FiBest ); - printf( "\n" ); -*/ - - // print the result -// if ( fVerbose ) - printf( "The best clock period is %3d. (Currently, network is not modified.)\n", FiBest ); -/* - { - FILE * pTable; - pTable = fopen( "iscas/seqmap__stats2.txt", "a+" ); - fprintf( pTable, "%d ", FiBest ); - fprintf( pTable, "\n" ); - fclose( pTable ); - } -*/ - Vec_PtrFree( vNodes ); - Vec_PtrFree( vLatches ); - return vLags; -} - -/**Function************************************************************* - - Synopsis [Performs binary search for the optimal clock period.] - - Description [Assumes that FiMin is infeasible while FiMax is feasible.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int FiMin, int FiMax, int nMaxIters, int fVerbose ) -{ - int Median; - assert( FiMin < FiMax ); - if ( FiMin + 1 == FiMax ) - return FiMax; - Median = FiMin + (FiMax - FiMin)/2; - if ( Abc_NtkRetimeForPeriod( pNtk, vNodes, vLatches, Median, nMaxIters, fVerbose ) ) - return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, FiMin, Median, nMaxIters, fVerbose ); // Median is feasible - else - return Abc_NtkRetimeSearch_rec( pNtk, vNodes, vLatches, Median, FiMax, nMaxIters, fVerbose ); // Median is infeasible -} - -/**Function************************************************************* - - Synopsis [Returns 1 if retiming with this clock period is feasible.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi, int nMaxIters, int fVerbose ) -{ - Abc_Obj_t * pObj; - int c, i, fConverged; - // set l-values of all nodes to be minus infinity, except PIs and constants - Abc_NtkForEachObj( pNtk, pObj, i ) - if ( Abc_ObjFaninNum(pObj) == 0 ) - Abc_NodeSetLValue( pObj, 0 ); - else - Abc_NodeSetLValue( pObj, -ABC_INFINITY ); - // update all values iteratively - fConverged = 0; - for ( c = 1; c <= nMaxIters; c++ ) - { - if ( !Abc_NtkRetimeUpdateLValue( pNtk, vNodes, vLatches, Fi ) ) - { - fConverged = 1; - break; - } - if ( Abc_NtkRetimePosOverLimit(pNtk, Fi) ) - break; - } - // report the results - if ( fVerbose ) - { - if ( !fConverged ) - printf( "Period = %3d. Iterations = %3d. Infeasible %s\n", Fi, c, (c > nMaxIters)? "(timeout)" : "" ); - else - printf( "Period = %3d. Iterations = %3d. Feasible\n", Fi, c ); - } -/* - // check if any AND gates have infinite delay - Counter = 0; - Abc_NtkForEachNode( pNtk, pObj, i ) - Counter += (Abc_NodeGetLValue(pObj) < -ABC_INFINITY/2); - if ( Counter > 0 ) - printf( "Warning: %d internal nodes have wrong l-values!\n", Counter ); -*/ - return fConverged; -} - -/**Function************************************************************* - - Synopsis [Performs one iteration of l-value computation for the nodes.] - - Description [Experimentally it was found that checking POs changes - is not enough to detect the convergence of l-values in the network.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeUpdateLValue( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vLatches, int Fi ) -{ - Abc_Obj_t * pObj, * pFanin; - int i, k, lValueNew, fChange; - // go through the nodes and detect change - fChange = 0; - Vec_PtrForEachEntry( vNodes, pObj, i ) - { - assert( Abc_ObjIsNode(pObj) ); - lValueNew = -ABC_INFINITY; - Abc_ObjForEachFanin( pObj, pFanin, k ) - { - if ( lValueNew < Abc_NodeGetLValue(pFanin) ) - lValueNew = Abc_NodeGetLValue(pFanin); - } - lValueNew++; - if ( Abc_NodeGetLValue(pObj) < lValueNew ) - { - Abc_NodeSetLValue( pObj, lValueNew ); - fChange = 1; - } - } - // propagate values through the latches - Vec_PtrForEachEntry( vLatches, pObj, i ) - Abc_NodeSetLValue( Abc_ObjFanout0(pObj), Abc_NodeGetLValue(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) - Fi ); - return fChange; -} - -/**Function************************************************************* - - Synopsis [Detects the case when l-values exceeded the limit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimePosOverLimit( Abc_Ntk_t * pNtk, int Fi ) -{ - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachPo( pNtk, pObj, i ) - if ( Abc_NodeGetLValue(Abc_ObjFanin0(pObj)) > Fi ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Collects latches in the topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Abc_ManCollectLatches_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLatches ) -{ - Abc_Obj_t * pDriver; - if ( !Abc_ObjIsLatch(pObj) ) - return; - // skip already collected latches - if ( Abc_NodeIsTravIdCurrent(pObj) ) - return; - Abc_NodeSetTravIdCurrent(pObj); - // get the driver node feeding into the latch - pDriver = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); - // call recursively if the driver looks like a latch output - if ( Abc_ObjIsBo(pDriver) ) - Abc_ManCollectLatches_rec( Abc_ObjFanin0(pDriver), vLatches ); - // collect the latch - Vec_PtrPush( vLatches, pObj ); -} - -/**Function************************************************************* - - Synopsis [Collects latches in the topological order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Abc_ManCollectLatches( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vLatches; - Abc_Obj_t * pObj; - int i; - vLatches = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachLatch( pNtk, pObj, i ) - Abc_ManCollectLatches_rec( pObj, vLatches ); - assert( Vec_PtrSize(vLatches) == Abc_NtkLatchNum(pNtk) ); - return vLatches; -} - -/**Function************************************************************* - - Synopsis [Implements the retiming given as the array of retiming lags.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Abc_NtkRetimeUsingLags( Abc_Ntk_t * pNtk, Vec_Int_t * vLags, int fVerbose ) -{ - Abc_Obj_t * pObj; - int fChanges, fForward, nTotalMoves, Lag, Counter, i; - // iterate over the nodes - nTotalMoves = 0; - do { - fChanges = 0; - Abc_NtkForEachNode( pNtk, pObj, i ) - { - Lag = Vec_IntEntry( vLags, pObj->Id ); - if ( !Lag ) - continue; - fForward = (Lag < 0); - if ( Abc_NtkRetimeNodeIsEnabled( pObj, fForward ) ) - { - Abc_NtkRetimeNode( pObj, fForward, 0 ); - fChanges = 1; - nTotalMoves++; - Vec_IntAddToEntry( vLags, pObj->Id, fForward? 1 : -1 ); - } - } - } while ( fChanges ); - if ( fVerbose ) - printf( "Total latch moves = %d.\n", nTotalMoves ); - // check if there are remaining lags - Counter = 0; - Abc_NtkForEachNode( pNtk, pObj, i ) - Counter += (Vec_IntEntry( vLags, pObj->Id ) != 0); - if ( Counter ) - printf( "Warning! The number of nodes with unrealized lag = %d.\n", Counter ); - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/ret/ret_.c b/src/opt/ret/ret_.c deleted file mode 100644 index 89625e17..00000000 --- a/src/opt/ret/ret_.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [ret_.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Retiming package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - Oct 31, 2006.] - - Revision [$Id: ret_.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "retInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/rwr/module.make b/src/opt/rwr/module.make deleted file mode 100644 index 077a3c01..00000000 --- a/src/opt/rwr/module.make +++ /dev/null @@ -1,7 +0,0 @@ -SRC += src/opt/rwr/rwrDec.c \ - src/opt/rwr/rwrEva.c \ - src/opt/rwr/rwrExp.c \ - src/opt/rwr/rwrLib.c \ - src/opt/rwr/rwrMan.c \ - src/opt/rwr/rwrPrint.c \ - src/opt/rwr/rwrUtil.c diff --git a/src/opt/rwr/rwr.h b/src/opt/rwr/rwr.h deleted file mode 100644 index f24f9535..00000000 --- a/src/opt/rwr/rwr.h +++ /dev/null @@ -1,169 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwr.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __RWR_H__ -#define __RWR_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#include "abc.h" -#include "cut.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -#define RWR_LIMIT 1048576/4 // ((1 << 20) - -typedef struct Rwr_Man_t_ Rwr_Man_t; -typedef struct Rwr_Node_t_ Rwr_Node_t; - -struct Rwr_Man_t_ -{ - // internal lookups - int nFuncs; // number of four var functions - unsigned short * puCanons; // canonical forms - char * pPhases; // canonical phases - char * pPerms; // canonical permutations - unsigned char * pMap; // mapping of functions into class numbers - unsigned short * pMapInv; // mapping of classes into functions - char * pPractical; // practical NPN classes - char ** pPerms4; // four-var permutations - // node space - Vec_Ptr_t * vForest; // all the nodes - Rwr_Node_t ** pTable; // the hash table of nodes by their canonical form - Vec_Vec_t * vClasses; // the nodes of the equivalence classes - Extra_MmFixed_t * pMmNode; // memory for nodes and cuts - // statistical variables - int nTravIds; // the counter of traversal IDs - int nConsidered; // the number of nodes considered - int nAdded; // the number of nodes added to lists - int nClasses; // the number of NN classes - // the result of resynthesis - int fCompl; // indicates if the output of FF should be complemented - void * pGraph; // the decomposition tree (temporary) - Vec_Ptr_t * vFanins; // the fanins array (temporary) - Vec_Ptr_t * vFaninsCur; // the fanins array (temporary) - Vec_Int_t * vLevNums; // the array of levels (temporary) - Vec_Ptr_t * vNodesTemp; // the nodes in MFFC (temporary) - // node statistics - int nNodesConsidered; - int nNodesRewritten; - int nNodesGained; - int nNodesBeg; - int nNodesEnd; - int nScores[222]; - int nCutsGood; - int nCutsBad; - int nSubgraphs; - // runtime statistics - int timeStart; - int timeCut; - int timeRes; - int timeEval; - int timeMffc; - int timeUpdate; - int timeTotal; -}; - -struct Rwr_Node_t_ // 24 bytes -{ - int Id; // ID - int TravId; // traversal ID - short nScore; - short nGain; - short nAdded; - unsigned uTruth : 16; // truth table - unsigned Volume : 8; // volume - unsigned Level : 6; // level - unsigned fUsed : 1; // mark - unsigned fExor : 1; // mark - Rwr_Node_t * p0; // first child - Rwr_Node_t * p1; // second child - Rwr_Node_t * pNext; // next in the table -}; - -// manipulation of complemented attributes -static inline bool Rwr_IsComplement( Rwr_Node_t * p ) { return (bool)(((unsigned long)p) & 01); } -static inline Rwr_Node_t * Rwr_Regular( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned long)(p) & ~01); } -static inline Rwr_Node_t * Rwr_Not( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned long)(p) ^ 01); } -static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_Node_t *)((unsigned long)(p) ^ (c)); } - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== rwrDec.c ========================================================*/ -extern void Rwr_ManPreprocess( Rwr_Man_t * p ); -/*=== rwrEva.c ========================================================*/ -extern int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable ); -extern void Rwr_ScoresClean( Rwr_Man_t * p ); -extern void Rwr_ScoresReport( Rwr_Man_t * p ); -/*=== rwrLib.c ========================================================*/ -extern void Rwr_ManPrecompute( Rwr_Man_t * p ); -extern Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute ); -extern Rwr_Node_t * Rwr_ManAddNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ); -extern int Rwr_ManNodeVolume( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 ); -extern void Rwr_ManIncTravId( Rwr_Man_t * p ); -/*=== rwrMan.c ========================================================*/ -extern Rwr_Man_t * Rwr_ManStart( bool fPrecompute ); -extern void Rwr_ManStop( Rwr_Man_t * p ); -extern void Rwr_ManPrintStats( Rwr_Man_t * p ); -extern void Rwr_ManPrintStatsFile( Rwr_Man_t * p ); -extern void * Rwr_ManReadDecs( Rwr_Man_t * p ); -extern Vec_Ptr_t * Rwr_ManReadLeaves( Rwr_Man_t * p ); -extern int Rwr_ManReadCompl( Rwr_Man_t * p ); -extern void Rwr_ManAddTimeCuts( Rwr_Man_t * p, int Time ); -extern void Rwr_ManAddTimeUpdate( Rwr_Man_t * p, int Time ); -extern void Rwr_ManAddTimeTotal( Rwr_Man_t * p, int Time ); -/*=== rwrPrint.c ========================================================*/ -extern void Rwr_ManPrint( Rwr_Man_t * p ); -/*=== rwrUtil.c ========================================================*/ -extern void Rwr_ManWriteToArray( Rwr_Man_t * p ); -extern void Rwr_ManLoadFromArray( Rwr_Man_t * p, int fVerbose ); -extern void Rwr_ManWriteToFile( Rwr_Man_t * p, char * pFileName ); -extern void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName ); -extern void Rwr_ListAddToTail( Rwr_Node_t ** ppList, Rwr_Node_t * pNode ); -extern char * Rwr_ManGetPractical( Rwr_Man_t * p ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/rwr/rwrDec.c b/src/opt/rwr/rwrDec.c deleted file mode 100644 index ef7af34f..00000000 --- a/src/opt/rwr/rwrDec.c +++ /dev/null @@ -1,150 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwrDec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Evaluation and decomposition procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwrDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwr.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Dec_Graph_t * Rwr_NodePreprocess( Rwr_Man_t * p, Rwr_Node_t * pNode ); -static Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * pGraph ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Preprocesses computed library of subgraphs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManPreprocess( Rwr_Man_t * p ) -{ - Dec_Graph_t * pGraph; - Rwr_Node_t * pNode; - int i, k; - // put the nodes into the structure - p->pMapInv = ALLOC( unsigned short, 222 ); - memset( p->pMapInv, 0, sizeof(unsigned short) * 222 ); - p->vClasses = Vec_VecStart( 222 ); - for ( i = 0; i < p->nFuncs; i++ ) - { - if ( p->pTable[i] == NULL ) - continue; - // consider all implementations of this function - for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext ) - { - assert( pNode->uTruth == p->pTable[i]->uTruth ); - assert( p->pMap[pNode->uTruth] >= 0 && p->pMap[pNode->uTruth] < 222 ); - Vec_VecPush( p->vClasses, p->pMap[pNode->uTruth], pNode ); - p->pMapInv[ p->pMap[pNode->uTruth] ] = p->puCanons[pNode->uTruth]; - } - } - // compute decomposition forms for each node and verify them - Vec_VecForEachEntry( p->vClasses, pNode, i, k ) - { - pGraph = Rwr_NodePreprocess( p, pNode ); - pNode->pNext = (Rwr_Node_t *)pGraph; - assert( pNode->uTruth == (Dec_GraphDeriveTruth(pGraph) & 0xFFFF) ); - } -} - -/**Function************************************************************* - - Synopsis [Preprocesses subgraphs rooted at this node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Rwr_NodePreprocess( Rwr_Man_t * p, Rwr_Node_t * pNode ) -{ - Dec_Graph_t * pGraph; - Dec_Edge_t eRoot; - assert( !Rwr_IsComplement(pNode) ); - // consider constant - if ( pNode->uTruth == 0 ) - return Dec_GraphCreateConst0(); - // consider the case of elementary var - if ( pNode->uTruth == 0x00FF ) - return Dec_GraphCreateLeaf( 3, 4, 1 ); - // start the subgraphs - pGraph = Dec_GraphCreate( 4 ); - // collect the nodes - Rwr_ManIncTravId( p ); - eRoot = Rwr_TravCollect_rec( p, pNode, pGraph ); - Dec_GraphSetRoot( pGraph, eRoot ); - return pGraph; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Edge_t Rwr_TravCollect_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, Dec_Graph_t * pGraph ) -{ - Dec_Edge_t eNode0, eNode1, eNode; - // elementary variable - if ( pNode->fUsed ) - return Dec_EdgeCreate( pNode->Id - 1, 0 ); - // previously visited node - if ( pNode->TravId == p->nTravIds ) - return Dec_IntToEdge( pNode->Volume ); - pNode->TravId = p->nTravIds; - // solve for children - eNode0 = Rwr_TravCollect_rec( p, Rwr_Regular(pNode->p0), pGraph ); - if ( Rwr_IsComplement(pNode->p0) ) - eNode0.fCompl = !eNode0.fCompl; - eNode1 = Rwr_TravCollect_rec( p, Rwr_Regular(pNode->p1), pGraph ); - if ( Rwr_IsComplement(pNode->p1) ) - eNode1.fCompl = !eNode1.fCompl; - // create the decomposition node(s) - if ( pNode->fExor ) - eNode = Dec_GraphAddNodeXor( pGraph, eNode0, eNode1, 0 ); - else - eNode = Dec_GraphAddNodeAnd( pGraph, eNode0, eNode1 ); - // save the result - pNode->Volume = Dec_EdgeToInt( eNode ); - return eNode; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/rwr/rwrEva.c b/src/opt/rwr/rwrEva.c deleted file mode 100644 index f46c16c0..00000000 --- a/src/opt/rwr/rwrEva.c +++ /dev/null @@ -1,587 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwrDec.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Evaluation and decomposition procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwrDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwr.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable ); -static int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ); -static int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut ); -static int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Performs rewriting for one node.] - - Description [This procedure considers all the cuts computed for the node - and tries to rewrite each of them using the "forest" of different AIG - structures precomputed and stored in the RWR manager. - Determines the best rewriting and computes the gain in the number of AIG - nodes in the final network. In the end, p->vFanins contains information - about the best cut that can be used for rewriting, while p->pGraph gives - the decomposition dag (represented using decomposition graph data structure). - Returns gain in the number of nodes or -1 if node cannot be rewritten.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwr_NodeRewrite( Rwr_Man_t * p, Cut_Man_t * pManCut, Abc_Obj_t * pNode, int fUpdateLevel, int fUseZeros, int fPlaceEnable ) -{ - int fVeryVerbose = 0; - Dec_Graph_t * pGraph; - Cut_Cut_t * pCut;//, * pTemp; - Abc_Obj_t * pFanin; - unsigned uPhase, uTruthBest, uTruth; - char * pPerm; - int Required, nNodesSaved, nNodesSaveCur; - int i, GainCur, GainBest = -1; - int clk, clk2;//, Counter; - - p->nNodesConsidered++; - // get the required times - Required = fUpdateLevel? Abc_ObjRequiredLevel(pNode) : ABC_INFINITY; - - // get the node's cuts -clk = clock(); - pCut = (Cut_Cut_t *)Abc_NodeGetCutsRecursive( pManCut, pNode, 0, 0 ); - assert( pCut != NULL ); -p->timeCut += clock() - clk; - -//printf( " %d", Rwr_CutCountNumNodes(pNode, pCut) ); -/* - Counter = 0; - for ( pTemp = pCut->pNext; pTemp; pTemp = pTemp->pNext ) - Counter++; - printf( "%d ", Counter ); -*/ - // go through the cuts -clk = clock(); - for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) - { - // consider only 4-input cuts - if ( pCut->nLeaves < 4 ) - continue; -// Cut_CutPrint( pCut, 0 ), printf( "\n" ); - - // get the fanin permutation - uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); - pPerm = p->pPerms4[ p->pPerms[uTruth] ]; - uPhase = p->pPhases[uTruth]; - // collect fanins with the corresponding permutation/phase - Vec_PtrClear( p->vFaninsCur ); - Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 ); - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - { - pFanin = Abc_NtkObj( pNode->pNtk, pCut->pLeaves[pPerm[i]] ); - if ( pFanin == NULL ) - break; - pFanin = Abc_ObjNotCond(pFanin, ((uPhase & (1< 0) ); - Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); - } - if ( i != (int)pCut->nLeaves ) - { - p->nCutsBad++; - continue; - } - p->nCutsGood++; - - { - int Counter = 0; - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - if ( Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) == 1 ) - Counter++; - if ( Counter > 2 ) - continue; - } - -clk2 = clock(); -/* - printf( "Considering: (" ); - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - printf( "%d ", Abc_ObjFanoutNum(Abc_ObjRegular(pFanin)) ); - printf( ")\n" ); -*/ - // mark the fanin boundary - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Abc_ObjRegular(pFanin)->vFanouts.nSize++; - - // label MFFC with current ID - Abc_NtkIncrementTravId( pNode->pNtk ); - nNodesSaved = Abc_NodeMffcLabelAig( pNode ); - // unmark the fanin boundary - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Abc_ObjRegular(pFanin)->vFanouts.nSize--; -p->timeMffc += clock() - clk2; - - // evaluate the cut -clk2 = clock(); - pGraph = Rwr_CutEvaluate( p, pNode, pCut, p->vFaninsCur, nNodesSaved, Required, &GainCur, fPlaceEnable ); -p->timeEval += clock() - clk2; - - // check if the cut is better than the current best one - if ( pGraph != NULL && GainBest < GainCur ) - { - // save this form - nNodesSaveCur = nNodesSaved; - GainBest = GainCur; - p->pGraph = pGraph; - p->fCompl = ((uPhase & (1<<4)) > 0); - uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut); - // collect fanins in the - Vec_PtrClear( p->vFanins ); - Vec_PtrForEachEntry( p->vFaninsCur, pFanin, i ) - Vec_PtrPush( p->vFanins, pFanin ); - } - } -p->timeRes += clock() - clk; - - if ( GainBest == -1 ) - return -1; -/* - if ( GainBest > 0 ) - { - printf( "Class %d ", p->pMap[uTruthBest] ); - printf( "Gain = %d. Node %d : ", GainBest, pNode->Id ); - Vec_PtrForEachEntry( p->vFanins, pFanin, i ) - printf( "%d ", Abc_ObjRegular(pFanin)->Id ); - Dec_GraphPrint( stdout, p->pGraph, NULL, NULL ); - printf( "\n" ); - } -*/ - -// printf( "%d", nNodesSaveCur - GainBest ); -/* - if ( GainBest > 0 ) - { - if ( Rwr_CutIsBoolean( pNode, p->vFanins ) ) - printf( "b" ); - else - { - printf( "Node %d : ", pNode->Id ); - Vec_PtrForEachEntry( p->vFanins, pFanin, i ) - printf( "%d ", Abc_ObjRegular(pFanin)->Id ); - printf( "a" ); - } - } -*/ -/* - if ( GainBest > 0 ) - if ( p->fCompl ) - printf( "c" ); - else - printf( "." ); -*/ - - // copy the leaves - Vec_PtrForEachEntry( p->vFanins, pFanin, i ) - Dec_GraphNode(p->pGraph, i)->pFunc = pFanin; -/* - printf( "(" ); - Vec_PtrForEachEntry( p->vFanins, pFanin, i ) - printf( " %d", Abc_ObjRegular(pFanin)->vFanouts.nSize - 1 ); - printf( " ) " ); -*/ -// printf( "%d ", Rwr_NodeGetDepth_rec( pNode, p->vFanins ) ); - - p->nScores[p->pMap[uTruthBest]]++; - p->nNodesGained += GainBest; - if ( fUseZeros || GainBest > 0 ) - { - p->nNodesRewritten++; - } - - // report the progress - if ( fVeryVerbose && GainBest > 0 ) - { - printf( "Node %6s : ", Abc_ObjName(pNode) ); - printf( "Fanins = %d. ", p->vFanins->nSize ); - printf( "Save = %d. ", nNodesSaveCur ); - printf( "Add = %d. ", nNodesSaveCur-GainBest ); - printf( "GAIN = %d. ", GainBest ); - printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum(p->pGraph) : 0 ); - printf( "Class = %d. ", p->pMap[uTruthBest] ); - printf( "\n" ); - } - return GainBest; -} - -/**Function************************************************************* - - Synopsis [Evaluates the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Dec_Graph_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Cut_Cut_t * pCut, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, int fPlaceEnable ) -{ - Vec_Ptr_t * vSubgraphs; - Dec_Graph_t * pGraphBest, * pGraphCur; - Rwr_Node_t * pNode, * pFanin; - int nNodesAdded, GainBest, i, k; - unsigned uTruth; - float CostBest, CostCur; - // find the matching class of subgraphs - uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); - vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); - p->nSubgraphs += vSubgraphs->nSize; - // determine the best subgraph - GainBest = -1; - CostBest = ABC_INFINITY; - Vec_PtrForEachEntry( vSubgraphs, pNode, i ) - { - // get the current graph - pGraphCur = (Dec_Graph_t *)pNode->pNext; - // copy the leaves - Vec_PtrForEachEntry( vFaninsCur, pFanin, k ) - Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; - // detect how many unlabeled nodes will be reused - nNodesAdded = Dec_GraphToNetworkCount( pRoot, pGraphCur, nNodesSaved, LevelMax ); - if ( nNodesAdded == -1 ) - continue; - assert( nNodesSaved >= nNodesAdded ); - - // evaluate the cut - if ( fPlaceEnable ) - { - extern float Abc_PlaceEvaluateCut( Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins ); - - float Alpha = 0.5; // ??? - float PlaceCost; - - // get the placement cost of the cut - PlaceCost = Abc_PlaceEvaluateCut( pRoot, vFaninsCur ); - - // get the weigted cost of the cut - CostCur = nNodesSaved - nNodesAdded + Alpha * PlaceCost; - - // do not allow uphill moves - if ( nNodesSaved - nNodesAdded < 0 ) - continue; - - // decide what cut to use - if ( CostBest > CostCur ) - { - GainBest = nNodesSaved - nNodesAdded; // pure node cost - CostBest = CostCur; // cost with placement - pGraphBest = pGraphCur; // subgraph to be used for rewriting - - // score the graph - if ( nNodesSaved - nNodesAdded > 0 ) - { - pNode->nScore++; - pNode->nGain += GainBest; - pNode->nAdded += nNodesAdded; - } - } - } - else - { - // count the gain at this node - if ( GainBest < nNodesSaved - nNodesAdded ) - { - GainBest = nNodesSaved - nNodesAdded; - pGraphBest = pGraphCur; - - // score the graph - if ( nNodesSaved - nNodesAdded > 0 ) - { - pNode->nScore++; - pNode->nGain += GainBest; - pNode->nAdded += nNodesAdded; - } - } - } - } - if ( GainBest == -1 ) - return NULL; - *pGainBest = GainBest; - return pGraphBest; -} - -/**Function************************************************************* - - Synopsis [Checks the type of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_CutIsBoolean_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves, int fMarkA ) -{ - if ( Vec_PtrFind(vLeaves, pObj) >= 0 || Vec_PtrFind(vLeaves, Abc_ObjNot(pObj)) >= 0 ) - { - if ( fMarkA ) - pObj->fMarkA = 1; - else - pObj->fMarkB = 1; - return; - } - assert( !Abc_ObjIsCi(pObj) ); - Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, fMarkA ); - Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, fMarkA ); -} - -/**Function************************************************************* - - Synopsis [Checks the type of the cut.] - - Description [Returns 1(0) if the cut is Boolean (algebraic).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwr_CutIsBoolean( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ) -{ - Abc_Obj_t * pTemp; - int i, RetValue; - Vec_PtrForEachEntry( vLeaves, pTemp, i ) - { - pTemp = Abc_ObjRegular(pTemp); - assert( !pTemp->fMarkA && !pTemp->fMarkB ); - } - Rwr_CutIsBoolean_rec( Abc_ObjFanin0(pObj), vLeaves, 1 ); - Rwr_CutIsBoolean_rec( Abc_ObjFanin1(pObj), vLeaves, 0 ); - RetValue = 0; - Vec_PtrForEachEntry( vLeaves, pTemp, i ) - { - pTemp = Abc_ObjRegular(pTemp); - RetValue |= pTemp->fMarkA && pTemp->fMarkB; - pTemp->fMarkA = pTemp->fMarkB = 0; - } - return RetValue; -} - - -/**Function************************************************************* - - Synopsis [Count the nodes in the cut space of a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_CutCountNumNodes_rec( Abc_Obj_t * pObj, Cut_Cut_t * pCut, Vec_Ptr_t * vNodes ) -{ - int i; - for ( i = 0; i < (int)pCut->nLeaves; i++ ) - if ( pCut->pLeaves[i] == pObj->Id ) - { - // check if the node is collected - if ( pObj->fMarkC == 0 ) - { - pObj->fMarkC = 1; - Vec_PtrPush( vNodes, pObj ); - } - return; - } - assert( Abc_ObjIsNode(pObj) ); - // check if the node is collected - if ( pObj->fMarkC == 0 ) - { - pObj->fMarkC = 1; - Vec_PtrPush( vNodes, pObj ); - } - // traverse the fanins - Rwr_CutCountNumNodes_rec( Abc_ObjFanin0(pObj), pCut, vNodes ); - Rwr_CutCountNumNodes_rec( Abc_ObjFanin1(pObj), pCut, vNodes ); -} - -/**Function************************************************************* - - Synopsis [Count the nodes in the cut space of a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwr_CutCountNumNodes( Abc_Obj_t * pObj, Cut_Cut_t * pCut ) -{ - Vec_Ptr_t * vNodes; - int i, Counter; - // collect all nodes - vNodes = Vec_PtrAlloc( 100 ); - for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) - Rwr_CutCountNumNodes_rec( pObj, pCut, vNodes ); - // clean all nodes - Vec_PtrForEachEntry( vNodes, pObj, i ) - pObj->fMarkC = 0; - // delete and return - Counter = Vec_PtrSize(vNodes); - Vec_PtrFree( vNodes ); - return Counter; -} - - -/**Function************************************************************* - - Synopsis [Returns depth of the cut.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwr_NodeGetDepth_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vLeaves ) -{ - Abc_Obj_t * pLeaf; - int i, Depth0, Depth1; - if ( Abc_ObjIsCi(pObj) ) - return 0; - Vec_PtrForEachEntry( vLeaves, pLeaf, i ) - if ( pObj == Abc_ObjRegular(pLeaf) ) - return 0; - Depth0 = Rwr_NodeGetDepth_rec( Abc_ObjFanin0(pObj), vLeaves ); - Depth1 = Rwr_NodeGetDepth_rec( Abc_ObjFanin1(pObj), vLeaves ); - return 1 + ABC_MAX( Depth0, Depth1 ); -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ScoresClean( Rwr_Man_t * p ) -{ - Vec_Ptr_t * vSubgraphs; - Rwr_Node_t * pNode; - int i, k; - for ( i = 0; i < p->vClasses->nSize; i++ ) - { - vSubgraphs = Vec_VecEntry( p->vClasses, i ); - Vec_PtrForEachEntry( vSubgraphs, pNode, k ) - pNode->nScore = pNode->nGain = pNode->nAdded = 0; - } -} - -static int Gains[222]; - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwr_ScoresCompare( int * pNum1, int * pNum2 ) -{ - if ( Gains[*pNum1] > Gains[*pNum2] ) - return -1; - if ( Gains[*pNum1] < Gains[*pNum2] ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ScoresReport( Rwr_Man_t * p ) -{ - extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); - int Perm[222]; - Vec_Ptr_t * vSubgraphs; - Rwr_Node_t * pNode; - int i, iNew, k; - unsigned uTruth; - // collect total gains - assert( p->vClasses->nSize == 222 ); - for ( i = 0; i < p->vClasses->nSize; i++ ) - { - Perm[i] = i; - Gains[i] = 0; - vSubgraphs = Vec_VecEntry( p->vClasses, i ); - Vec_PtrForEachEntry( vSubgraphs, pNode, k ) - Gains[i] += pNode->nGain; - } - // sort the gains - qsort( Perm, 222, sizeof(int), (int (*)(const void *, const void *))Rwr_ScoresCompare ); - - // print classes - for ( i = 0; i < p->vClasses->nSize; i++ ) - { - iNew = Perm[i]; - if ( Gains[iNew] == 0 ) - break; - vSubgraphs = Vec_VecEntry( p->vClasses, iNew ); - printf( "CLASS %3d: Subgr = %3d. Total gain = %6d. ", iNew, Vec_PtrSize(vSubgraphs), Gains[iNew] ); - uTruth = (unsigned)p->pMapInv[iNew]; - Extra_PrintBinary( stdout, &uTruth, 16 ); - printf( " " ); - Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[iNew] | ((unsigned)p->pMapInv[iNew] << 16) ); - Vec_PtrForEachEntry( vSubgraphs, pNode, k ) - { - if ( pNode->nScore == 0 ) - continue; - printf( " %2d: S=%5d. A=%5d. G=%6d. ", k, pNode->nScore, pNode->nAdded, pNode->nGain ); - Dec_GraphPrint( stdout, (Dec_Graph_t *)pNode->pNext, NULL, NULL ); - } - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/rwr/rwrExp.c b/src/opt/rwr/rwrExp.c deleted file mode 100644 index 2d00bb1c..00000000 --- a/src/opt/rwr/rwrExp.c +++ /dev/null @@ -1,333 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwrExp.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Computation of practically used NN-classes of 4-input cuts.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwrExp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwr.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Rwr_Man4_t_ Rwr_Man4_t; -struct Rwr_Man4_t_ -{ - // internal lookups - int nFuncs; // the number of four-var functions - unsigned short * puCanons; // canonical forms - int * pnCounts; // the counters of functions in each class - int nConsidered; // the number of nodes considered - int nClasses; // the number of NN classes -}; - -typedef struct Rwr_Man5_t_ Rwr_Man5_t; -struct Rwr_Man5_t_ -{ - // internal lookups - stmm_table * tTableNN; // the NN canonical forms - stmm_table * tTableNPN; // the NPN canonical forms -}; - -static Rwr_Man4_t * s_pManRwrExp4 = NULL; -static Rwr_Man5_t * s_pManRwrExp5 = NULL; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Collects stats about 4-var functions appearing in netlists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_Man4ExploreStart() -{ - Rwr_Man4_t * p; - p = ALLOC( Rwr_Man4_t, 1 ); - memset( p, 0, sizeof(Rwr_Man4_t) ); - // canonical forms - p->nFuncs = (1<<16); - // canonical forms, phases, perms - Extra_Truth4VarNPN( &p->puCanons, NULL, NULL, NULL ); - // counters - p->pnCounts = ALLOC( int, p->nFuncs ); - memset( p->pnCounts, 0, sizeof(int) * p->nFuncs ); - s_pManRwrExp4 = p; -} - -/**Function************************************************************* - - Synopsis [Collects stats about 4-var functions appearing in netlists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_Man4ExploreCount( unsigned uTruth ) -{ - assert( uTruth < (1<<16) ); - s_pManRwrExp4->pnCounts[ s_pManRwrExp4->puCanons[uTruth] ]++; -} - -/**Function************************************************************* - - Synopsis [Collects stats about 4-var functions appearing in netlists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_Man4ExplorePrint() -{ - FILE * pFile; - int i, CountMax, CountWrite, nCuts, nClasses; - int * pDistrib; - int * pReprs; - // find the max number of occurences - nCuts = nClasses = 0; - CountMax = 0; - for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ ) - { - if ( CountMax < s_pManRwrExp4->pnCounts[i] ) - CountMax = s_pManRwrExp4->pnCounts[i]; - nCuts += s_pManRwrExp4->pnCounts[i]; - if ( s_pManRwrExp4->pnCounts[i] > 0 ) - nClasses++; - } - printf( "Number of cuts considered = %8d.\n", nCuts ); - printf( "Classes occurring at least once = %8d.\n", nClasses ); - // print the distribution of classes - pDistrib = ALLOC( int, CountMax + 1 ); - pReprs = ALLOC( int, CountMax + 1 ); - memset( pDistrib, 0, sizeof(int)*(CountMax + 1) ); - for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ ) - { - pDistrib[ s_pManRwrExp4->pnCounts[i] ]++; - pReprs[ s_pManRwrExp4->pnCounts[i] ] = i; - } - - printf( "Occurence = %6d. Num classes = %4d. \n", 0, 2288-nClasses ); - for ( i = 1; i <= CountMax; i++ ) - if ( pDistrib[i] ) - { - printf( "Occurence = %6d. Num classes = %4d. Repr = ", i, pDistrib[i] ); - Extra_PrintBinary( stdout, (unsigned*)&(pReprs[i]), 16 ); - printf( "\n" ); - } - free( pDistrib ); - free( pReprs ); - // write into a file all classes above limit (5) - CountWrite = 0; - pFile = fopen( "npnclass_stats4.txt", "w" ); - for ( i = 0; i < s_pManRwrExp4->nFuncs; i++ ) - if ( s_pManRwrExp4->pnCounts[i] > 0 ) - { - Extra_PrintHex( pFile, i, 4 ); - fprintf( pFile, " %10d\n", s_pManRwrExp4->pnCounts[i] ); -// fprintf( pFile, "%d ", i ); - CountWrite++; - } - fclose( pFile ); - printf( "%d classes written into file \"%s\".\n", CountWrite, "npnclass_stats4.txt" ); -} - - - - -/**Function************************************************************* - - Synopsis [Collects stats about 4-var functions appearing in netlists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_Man5ExploreStart() -{ - Rwr_Man5_t * p; - p = ALLOC( Rwr_Man5_t, 1 ); - memset( p, 0, sizeof(Rwr_Man5_t) ); - p->tTableNN = stmm_init_table( st_numcmp, st_numhash ); - p->tTableNPN = stmm_init_table( st_numcmp, st_numhash ); - s_pManRwrExp5 = p; - -//Extra_PrintHex( stdout, Extra_TruthCanonNPN( 0x0000FFFF, 5 ), 5 ); -//printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Collects stats about 4-var functions appearing in netlists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_Man5ExploreCount( unsigned uTruth ) -{ - int * pCounter; - if ( !stmm_find_or_add( s_pManRwrExp5->tTableNN, (char *)uTruth, (char***)&pCounter ) ) - *pCounter = 0; - (*pCounter)++; -} - -/**Function************************************************************* - - Synopsis [Collects stats about 4-var functions appearing in netlists.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwt_Man5ExplorePrint() -{ - FILE * pFile; - stmm_generator * gen; - int i, CountMax, nCuts, Counter; - int * pDistrib; - unsigned * pReprs; - unsigned uTruth, uTruthC; - int clk = clock(); - Vec_Int_t * vClassesNN, * vClassesNPN; - - // find the max number of occurences - nCuts = 0; - CountMax = 0; - stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, (char **)&Counter ) - { - nCuts += Counter; - if ( CountMax < Counter ) - CountMax = Counter; - } - printf( "Number of cuts considered = %8d.\n", nCuts ); - printf( "Classes occurring at least once = %8d.\n", stmm_count(s_pManRwrExp5->tTableNN) ); - printf( "The largest number of occurence = %8d.\n", CountMax ); - - // print the distribution of classes - pDistrib = ALLOC( int, CountMax + 1 ); - pReprs = ALLOC( unsigned, CountMax + 1 ); - memset( pDistrib, 0, sizeof(int)*(CountMax + 1) ); - stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, (char **)&Counter ) - { - assert( Counter <= CountMax ); - pDistrib[ Counter ]++; - pReprs[ Counter ] = uTruth; - } - - for ( i = 1; i <= CountMax; i++ ) - if ( pDistrib[i] ) - { - printf( "Occurence = %6d. Num classes = %4d. Repr = ", i, pDistrib[i] ); - Extra_PrintBinary( stdout, pReprs + i, 32 ); - printf( "\n" ); - } - free( pDistrib ); - free( pReprs ); - - - // put them into an array - vClassesNN = Vec_IntAlloc( stmm_count(s_pManRwrExp5->tTableNN) ); - stmm_foreach_item( s_pManRwrExp5->tTableNN, gen, (char **)&uTruth, NULL ) - Vec_IntPush( vClassesNN, (int)uTruth ); - Vec_IntSortUnsigned( vClassesNN ); - - // write into a file all classes - pFile = fopen( "nnclass_stats5.txt", "w" ); - Vec_IntForEachEntry( vClassesNN, uTruth, i ) - { - if ( !stmm_lookup( s_pManRwrExp5->tTableNN, (char *)uTruth, (char **)&Counter ) ) - { - assert( 0 ); - } - Extra_PrintHex( pFile, uTruth, 5 ); - fprintf( pFile, " %10d\n", Counter ); - } - fclose( pFile ); - printf( "%d classes written into file \"%s\".\n", vClassesNN->nSize, "nnclass_stats5.txt" ); - - -clk = clock(); - // how many NPN classes exist? - Vec_IntForEachEntry( vClassesNN, uTruth, i ) - { - int * pCounter; - uTruthC = Extra_TruthCanonNPN( uTruth, 5 ); - if ( !stmm_find_or_add( s_pManRwrExp5->tTableNPN, (char *)uTruthC, (char***)&pCounter ) ) - *pCounter = 0; - if ( !stmm_lookup( s_pManRwrExp5->tTableNN, (char *)uTruth, (char **)&Counter ) ) - { - assert( 0 ); - } - (*pCounter) += Counter; - } - printf( "The numbe of NPN classes = %d.\n", stmm_count(s_pManRwrExp5->tTableNPN) ); -PRT( "Computing NPN classes", clock() - clk ); - - // put them into an array - vClassesNPN = Vec_IntAlloc( stmm_count(s_pManRwrExp5->tTableNPN) ); - stmm_foreach_item( s_pManRwrExp5->tTableNPN, gen, (char **)&uTruth, NULL ) - Vec_IntPush( vClassesNPN, (int)uTruth ); - Vec_IntSortUnsigned( vClassesNPN ); - - // write into a file all classes - pFile = fopen( "npnclass_stats5.txt", "w" ); - Vec_IntForEachEntry( vClassesNPN, uTruth, i ) - { - if ( !stmm_lookup( s_pManRwrExp5->tTableNPN, (char *)uTruth, (char **)&Counter ) ) - { - assert( 0 ); - } - Extra_PrintHex( pFile, uTruth, 5 ); - fprintf( pFile, " %10d\n", Counter ); - } - fclose( pFile ); - printf( "%d classes written into file \"%s\".\n", vClassesNPN->nSize, "npnclass_stats5.txt" ); - - - // can they be uniquely characterized? - -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/rwr/rwrLib.c b/src/opt/rwr/rwrLib.c deleted file mode 100644 index 1cdf350e..00000000 --- a/src/opt/rwr/rwrLib.c +++ /dev/null @@ -1,362 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwrLib.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwrLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwr.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ); -static void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Precomputes the forest in the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManPrecompute( Rwr_Man_t * p ) -{ - Rwr_Node_t * p0, * p1; - int i, k, Level, Volume; - int LevelOld = -1; - int nNodes; - - Vec_PtrForEachEntryStart( p->vForest, p0, i, 1 ) - Vec_PtrForEachEntryStart( p->vForest, p1, k, 1 ) - { - if ( LevelOld < (int)p0->Level ) - { - LevelOld = p0->Level; - printf( "Starting level %d (at %d nodes).\n", LevelOld+1, i ); - printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", - p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); - } - - if ( k == i ) - break; -// if ( p0->Level + p1->Level > 6 ) // hard -// break; - - if ( p0->Level + p1->Level > 5 ) // easy - break; - -// if ( p0->Level + p1->Level > 6 || (p0->Level == 3 && p1->Level == 3) ) -// break; - - // compute the level and volume of the new nodes - Level = 1 + ABC_MAX( p0->Level, p1->Level ); - Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); - // try four different AND nodes - Rwr_ManTryNode( p, p0 , p1 , 0, Level, Volume ); - Rwr_ManTryNode( p, Rwr_Not(p0), p1 , 0, Level, Volume ); - Rwr_ManTryNode( p, p0 , Rwr_Not(p1), 0, Level, Volume ); - Rwr_ManTryNode( p, Rwr_Not(p0), Rwr_Not(p1), 0, Level, Volume ); - // try EXOR - Rwr_ManTryNode( p, p0 , p1 , 1, Level, Volume + 1 ); - // report the progress - if ( p->nConsidered % 50000000 == 0 ) - printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", - p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); - // quit after some time - if ( p->vForest->nSize == RWR_LIMIT + 5 ) - { - printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", - p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); - goto save; - } - } -save : - - // mark the relevant ones - Rwr_ManIncTravId( p ); - k = 5; - nNodes = 0; - Vec_PtrForEachEntryStart( p->vForest, p0, i, 5 ) - if ( p0->uTruth == p->puCanons[p0->uTruth] ) - { - Rwr_MarkUsed_rec( p, p0 ); - nNodes++; - } - - // compact the array by throwing away non-canonical - k = 5; - Vec_PtrForEachEntryStart( p->vForest, p0, i, 5 ) - if ( p0->fUsed ) - { - p->vForest->pArray[k] = p0; - p0->Id = k++; - } - p->vForest->nSize = k; - printf( "Total canonical = %4d. Total used = %5d.\n", nNodes, p->vForest->nSize ); -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ) -{ - Rwr_Node_t * pOld, * pNew, ** ppPlace; - unsigned uTruth; - // compute truth table, level, volume - p->nConsidered++; - if ( fExor ) - { -// printf( "Considering EXOR of %d and %d.\n", p0->Id, p1->Id ); - uTruth = (p0->uTruth ^ p1->uTruth); - } - else - uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & - (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF; - // skip non-practical classes - if ( Level > 2 && !p->pPractical[p->puCanons[uTruth]] ) - return NULL; - // enumerate through the nodes with the same canonical form - ppPlace = p->pTable + uTruth; - for ( pOld = *ppPlace; pOld; ppPlace = &pOld->pNext, pOld = pOld->pNext ) - { - if ( pOld->Level < (unsigned)Level && pOld->Volume < (unsigned)Volume ) - return NULL; - if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume ) - return NULL; -// if ( pOld->Level < (unsigned)Level && pOld->Volume == (unsigned)Volume ) -// return NULL; - } -/* - // enumerate through the nodes with the opposite polarity - for ( pOld = p->pTable[~uTruth & 0xFFFF]; pOld; pOld = pOld->pNext ) - { - if ( pOld->Level < (unsigned)Level && pOld->Volume < (unsigned)Volume ) - return NULL; - if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume ) - return NULL; -// if ( pOld->Level < (unsigned)Level && pOld->Volume == (unsigned)Volume ) -// return NULL; - } -*/ - // count the classes - if ( p->pTable[uTruth] == NULL && p->puCanons[uTruth] == uTruth ) - p->nClasses++; - // create the new node - pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); - pNew->Id = p->vForest->nSize; - pNew->TravId = 0; - pNew->uTruth = uTruth; - pNew->Level = Level; - pNew->Volume = Volume; - pNew->fUsed = 0; - pNew->fExor = fExor; - pNew->p0 = p0; - pNew->p1 = p1; - pNew->pNext = NULL; - Vec_PtrPush( p->vForest, pNew ); - *ppPlace = pNew; - return pNew; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rwr_Node_t * Rwr_ManAddNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ) -{ - Rwr_Node_t * pNew; - unsigned uTruth; - // compute truth table, leve, volume - p->nConsidered++; - if ( fExor ) - uTruth = (p0->uTruth ^ p1->uTruth); - else - uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & - (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF; - // create the new node - pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); - pNew->Id = p->vForest->nSize; - pNew->TravId = 0; - pNew->uTruth = uTruth; - pNew->Level = Level; - pNew->Volume = Volume; - pNew->fUsed = 0; - pNew->fExor = fExor; - pNew->p0 = p0; - pNew->p1 = p1; - pNew->pNext = NULL; - Vec_PtrPush( p->vForest, pNew ); - // do not add if the node is not essential - if ( uTruth != p->puCanons[uTruth] ) - return pNew; - - // add to the list - p->nAdded++; - if ( p->pTable[uTruth] == NULL ) - p->nClasses++; - Rwr_ListAddToTail( p->pTable + uTruth, pNew ); - return pNew; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute ) -{ - Rwr_Node_t * pNew; - pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); - pNew->Id = p->vForest->nSize; - pNew->TravId = 0; - pNew->uTruth = uTruth; - pNew->Level = 0; - pNew->Volume = 0; - pNew->fUsed = 1; - pNew->fExor = 0; - pNew->p0 = NULL; - pNew->p1 = NULL; - pNew->pNext = NULL; - Vec_PtrPush( p->vForest, pNew ); - if ( fPrecompute ) - Rwr_ListAddToTail( p->pTable + uTruth, pNew ); - return pNew; -} - - - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode ) -{ - if ( pNode->fUsed || pNode->TravId == p->nTravIds ) - return; - pNode->TravId = p->nTravIds; - pNode->fUsed = 1; - Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p0) ); - Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p1) ); -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_Trav_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, int * pVolume ) -{ - if ( pNode->fUsed || pNode->TravId == p->nTravIds ) - return; - pNode->TravId = p->nTravIds; - (*pVolume)++; - if ( pNode->fExor ) - (*pVolume)++; - Rwr_Trav_rec( p, Rwr_Regular(pNode->p0), pVolume ); - Rwr_Trav_rec( p, Rwr_Regular(pNode->p1), pVolume ); -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwr_ManNodeVolume( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 ) -{ - int Volume = 0; - Rwr_ManIncTravId( p ); - Rwr_Trav_rec( p, p0, &Volume ); - Rwr_Trav_rec( p, p1, &Volume ); - return Volume; -} - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManIncTravId( Rwr_Man_t * p ) -{ - Rwr_Node_t * pNode; - int i; - if ( p->nTravIds++ < 0x8FFFFFFF ) - return; - Vec_PtrForEachEntry( p->vForest, pNode, i ) - pNode->TravId = 0; - p->nTravIds = 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/rwr/rwrMan.c b/src/opt/rwr/rwrMan.c deleted file mode 100644 index 87a080c7..00000000 --- a/src/opt/rwr/rwrMan.c +++ /dev/null @@ -1,318 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwrMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Rewriting manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwrMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwr.h" -#include "main.h" -#include "dec.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Rwr_Man_t * Rwr_ManStart( bool fPrecompute ) -{ - Dec_Man_t * pManDec; - Rwr_Man_t * p; - int clk = clock(); -clk = clock(); - p = ALLOC( Rwr_Man_t, 1 ); - memset( p, 0, sizeof(Rwr_Man_t) ); - p->nFuncs = (1<<16); - pManDec = Abc_FrameReadManDec(); - p->puCanons = pManDec->puCanons; - p->pPhases = pManDec->pPhases; - p->pPerms = pManDec->pPerms; - p->pMap = pManDec->pMap; - // initialize practical NPN classes - p->pPractical = Rwr_ManGetPractical( p ); - // create the table - p->pTable = ALLOC( Rwr_Node_t *, p->nFuncs ); - memset( p->pTable, 0, sizeof(Rwr_Node_t *) * p->nFuncs ); - // create the elementary nodes - p->pMmNode = Extra_MmFixedStart( sizeof(Rwr_Node_t) ); - p->vForest = Vec_PtrAlloc( 100 ); - Rwr_ManAddVar( p, 0x0000, fPrecompute ); // constant 0 - Rwr_ManAddVar( p, 0xAAAA, fPrecompute ); // var A - Rwr_ManAddVar( p, 0xCCCC, fPrecompute ); // var B - Rwr_ManAddVar( p, 0xF0F0, fPrecompute ); // var C - Rwr_ManAddVar( p, 0xFF00, fPrecompute ); // var D - p->nClasses = 5; - // other stuff - p->nTravIds = 1; - p->pPerms4 = Extra_Permutations( 4 ); - p->vLevNums = Vec_IntAlloc( 50 ); - p->vFanins = Vec_PtrAlloc( 50 ); - p->vFaninsCur = Vec_PtrAlloc( 50 ); - p->vNodesTemp = Vec_PtrAlloc( 50 ); - if ( fPrecompute ) - { // precompute subgraphs - Rwr_ManPrecompute( p ); -// Rwr_ManPrint( p ); - Rwr_ManWriteToArray( p ); - } - else - { // load saved subgraphs - Rwr_ManLoadFromArray( p, 0 ); -// Rwr_ManPrint( p ); - Rwr_ManPreprocess( p ); - } -p->timeStart = clock() - clk; - return p; -} - -/**Function************************************************************* - - Synopsis [Stops rewriting manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManStop( Rwr_Man_t * p ) -{ - if ( p->vClasses ) - { - Rwr_Node_t * pNode; - int i, k; - Vec_VecForEachEntry( p->vClasses, pNode, i, k ) - Dec_GraphFree( (Dec_Graph_t *)pNode->pNext ); - } - if ( p->vClasses ) Vec_VecFree( p->vClasses ); - Vec_PtrFree( p->vNodesTemp ); - Vec_PtrFree( p->vForest ); - Vec_IntFree( p->vLevNums ); - Vec_PtrFree( p->vFanins ); - Vec_PtrFree( p->vFaninsCur ); - Extra_MmFixedStop( p->pMmNode ); - FREE( p->pMapInv ); - free( p->pTable ); - free( p->pPractical ); - free( p->pPerms4 ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManPrintStats( Rwr_Man_t * p ) -{ - int i, Counter = 0; - for ( i = 0; i < 222; i++ ) - Counter += (p->nScores[i] > 0); - - printf( "Rewriting statistics:\n" ); - printf( "Total cuts tries = %8d.\n", p->nCutsGood ); - printf( "Bad cuts found = %8d.\n", p->nCutsBad ); - printf( "Total subgraphs = %8d.\n", p->nSubgraphs ); - printf( "Used NPN classes = %8d.\n", Counter ); - printf( "Nodes considered = %8d.\n", p->nNodesConsidered ); - printf( "Nodes rewritten = %8d.\n", p->nNodesRewritten ); - printf( "Gain = %8d. (%6.2f %%).\n", p->nNodesBeg-p->nNodesEnd, 100.0*(p->nNodesBeg-p->nNodesEnd)/p->nNodesBeg ); - PRT( "Start ", p->timeStart ); - PRT( "Cuts ", p->timeCut ); - PRT( "Resynthesis ", p->timeRes ); - PRT( " Mffc ", p->timeMffc ); - PRT( " Eval ", p->timeEval ); - PRT( "Update ", p->timeUpdate ); - PRT( "TOTAL ", p->timeTotal ); - -/* - printf( "The scores are:\n" ); - for ( i = 0; i < 222; i++ ) - if ( p->nScores[i] > 0 ) - { - extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); - printf( "%3d = %8d canon = %5d ", i, p->nScores[i], p->pMapInv[i] ); - Ivy_TruthDsdComputePrint( (unsigned)p->pMapInv[i] | ((unsigned)p->pMapInv[i] << 16) ); - } -*/ - printf( "\n" ); - -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManPrintStatsFile( Rwr_Man_t * p ) -{ - FILE * pTable; - pTable = fopen( "stats.txt", "a+" ); - fprintf( pTable, "%d ", p->nCutsGood ); - fprintf( pTable, "%d ", p->nSubgraphs ); - fprintf( pTable, "%d ", p->nNodesRewritten ); - fprintf( pTable, "%d", p->nNodesGained ); - fprintf( pTable, "\n" ); - fclose( pTable ); -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void * Rwr_ManReadDecs( Rwr_Man_t * p ) -{ - return p->pGraph; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Rwr_ManReadLeaves( Rwr_Man_t * p ) -{ - return p->vFanins; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwr_ManReadCompl( Rwr_Man_t * p ) -{ - return p->fCompl; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManAddTimeCuts( Rwr_Man_t * p, int Time ) -{ - p->timeCut += Time; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManAddTimeUpdate( Rwr_Man_t * p, int Time ) -{ - p->timeUpdate += Time; -} - -/**Function************************************************************* - - Synopsis [Stops the resynthesis manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManAddTimeTotal( Rwr_Man_t * p, int Time ) -{ - p->timeTotal += Time; -} - - -/**Function************************************************************* - - Synopsis [Precomputes AIG subgraphs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_Precompute() -{ - Rwr_Man_t * p; - p = Rwr_ManStart( 1 ); - Rwr_ManStop( p ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/rwr/rwrPrint.c b/src/opt/rwr/rwrPrint.c deleted file mode 100644 index 82ad2a90..00000000 --- a/src/opt/rwr/rwrPrint.c +++ /dev/null @@ -1,266 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwrCut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Cut computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwr.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Adds one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_Trav2_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, int * pVolume ) -{ - if ( pNode->fUsed || pNode->TravId == p->nTravIds ) - return; - pNode->TravId = p->nTravIds; - (*pVolume)++; - Rwr_Trav2_rec( p, Rwr_Regular(pNode->p0), pVolume ); - Rwr_Trav2_rec( p, Rwr_Regular(pNode->p1), pVolume ); -} - -/**Function************************************************************* - - Synopsis [Adds the node to the end of the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_GetBushVolume( Rwr_Man_t * p, int Entry, int * pVolume, int * pnFuncs ) -{ - Rwr_Node_t * pNode; - int Volume = 0; - int nFuncs = 0; - Rwr_ManIncTravId( p ); - for ( pNode = p->pTable[Entry]; pNode; pNode = pNode->pNext ) - { - if ( pNode->uTruth != p->puCanons[pNode->uTruth] ) - continue; - nFuncs++; - Rwr_Trav2_rec( p, pNode, &Volume ); - } - *pVolume = Volume; - *pnFuncs = nFuncs; -} - -/**Function************************************************************* - - Synopsis [Adds the node to the end of the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwr_GetBushSumOfVolumes( Rwr_Man_t * p, int Entry ) -{ - Rwr_Node_t * pNode; - int Volume, VolumeTotal = 0; - for ( pNode = p->pTable[Entry]; pNode; pNode = pNode->pNext ) - { - if ( pNode->uTruth != p->puCanons[pNode->uTruth] ) - continue; - Volume = 0; - Rwr_ManIncTravId( p ); - Rwr_Trav2_rec( p, pNode, &Volume ); - VolumeTotal += Volume; - } - return VolumeTotal; -} - -/**Function************************************************************* - - Synopsis [Prints one rwr node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_NodePrint_rec( FILE * pFile, Rwr_Node_t * pNode ) -{ - assert( !Rwr_IsComplement(pNode) ); - - if ( pNode->Id == 0 ) - { - fprintf( pFile, "Const1" ); - return; - } - - if ( pNode->Id < 5 ) - { - fprintf( pFile, "%c", 'a' + pNode->Id - 1 ); - return; - } - - if ( Rwr_IsComplement(pNode->p0) ) - { - if ( Rwr_Regular(pNode->p0)->Id < 5 ) - { - Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); - fprintf( pFile, "\'" ); - } - else - { - fprintf( pFile, "(" ); - Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); - fprintf( pFile, ")\'" ); - } - } - else - { - if ( Rwr_Regular(pNode->p0)->Id < 5 ) - { - Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); - } - else - { - fprintf( pFile, "(" ); - Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) ); - fprintf( pFile, ")" ); - } - } - - if ( pNode->fExor ) - fprintf( pFile, "+" ); - - if ( Rwr_IsComplement(pNode->p1) ) - { - if ( Rwr_Regular(pNode->p1)->Id < 5 ) - { - Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); - fprintf( pFile, "\'" ); - } - else - { - fprintf( pFile, "(" ); - Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); - fprintf( pFile, ")\'" ); - } - } - else - { - if ( Rwr_Regular(pNode->p1)->Id < 5 ) - { - Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); - } - else - { - fprintf( pFile, "(" ); - Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) ); - fprintf( pFile, ")" ); - } - } -} - -/**Function************************************************************* - - Synopsis [Prints one rwr node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_NodePrint( FILE * pFile, Rwr_Man_t * p, Rwr_Node_t * pNode ) -{ - unsigned uTruth; - fprintf( pFile, "%5d : ", pNode->Id ); - Extra_PrintHex( pFile, pNode->uTruth, 4 ); - fprintf( pFile, " tt=" ); - uTruth = pNode->uTruth; - Extra_PrintBinary( pFile, &uTruth, 16 ); -// fprintf( pFile, " cn=", pNode->Id ); -// uTruth = p->puCanons[pNode->uTruth]; -// Extra_PrintBinary( pFile, &uTruth, 16 ); - fprintf( pFile, " lev=%d", pNode->Level ); - fprintf( pFile, " vol=%d", pNode->Volume ); - fprintf( pFile, " " ); - Rwr_NodePrint_rec( pFile, pNode ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints one rwr node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManPrint( Rwr_Man_t * p ) -{ - FILE * pFile; - Rwr_Node_t * pNode; - unsigned uTruth; - int Limit, Counter, Volume, nFuncs, i; - pFile = fopen( "graph_lib.txt", "w" ); - Counter = 0; - Limit = (1 << 16); - for ( i = 0; i < Limit; i++ ) - { - if ( p->pTable[i] == NULL ) - continue; - if ( i != p->puCanons[i] ) - continue; - fprintf( pFile, "\nClass %3d. Func %6d. ", p->pMap[i], Counter++ ); - Rwr_GetBushVolume( p, i, &Volume, &nFuncs ); - fprintf( pFile, "Roots = %3d. Vol = %3d. Sum = %3d. ", nFuncs, Volume, Rwr_GetBushSumOfVolumes(p, i) ); - uTruth = i; - Extra_PrintBinary( pFile, &uTruth, 16 ); - fprintf( pFile, "\n" ); - for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext ) - if ( pNode->uTruth == p->puCanons[pNode->uTruth] ) - Rwr_NodePrint( pFile, p, pNode ); - } - fclose( pFile ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/rwr/rwrTemp.c b/src/opt/rwr/rwrTemp.c deleted file mode 100644 index 3ffbd408..00000000 --- a/src/opt/rwr/rwrTemp.c +++ /dev/null @@ -1,121 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwrCut.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Cut computation.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwr.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int pTruths[13719]; -static int pFreqs[13719]; -static int pPerm[13719]; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Rwr_TempCompare( int * pNum1, int * pNum2 ) -{ - int Freq1 = pFreqs[*pNum1]; - int Freq2 = pFreqs[*pNum2]; - if ( Freq1 < Freq2 ) - return 1; - if ( Freq1 > Freq2 ) - return -1; - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_Temp() -{ - char Buffer[32]; - int nFuncs = 13719; - int nEntries = 100; - unsigned uTruth; - int i, k; - FILE * pFile; - - pFile = fopen( "nnclass_stats5.txt", "r" ); - for ( i = 0; i < 13719; i++ ) - { - fscanf( pFile, "%s%d", Buffer, &pFreqs[i] ); - Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); - pTruths[i] = uTruth; - } - fclose( pFile ); - - for ( i = 0; i < 13719; i++ ) - pPerm[i] = i; - - qsort( (void *)pPerm, 13719, sizeof(int), - (int (*)(const void *, const void *)) Rwr_TempCompare ); - - - pFile = fopen( "5npn_100.blif", "w" ); - fprintf( pFile, "# Most frequent NPN classes of 5 vars.\n" ); - fprintf( pFile, ".model 5npn\n" ); - fprintf( pFile, ".inputs a b c d e\n" ); - fprintf( pFile, ".outputs" ); - for ( i = 0; i < nEntries; i++ ) - fprintf( pFile, " %02d", i ); - fprintf( pFile, "\n" ); - - for ( i = 0; i < nEntries; i++ ) - { - fprintf( pFile, ".names a b c d e %02d\n", i ); - uTruth = pTruths[pPerm[i]]; - for ( k = 0; k < 32; k++ ) - if ( uTruth & (1 << k) ) - { - Extra_PrintBinary( pFile, &k, 5 ); - fprintf( pFile, " 1\n" ); - } - } - fprintf( pFile, ".end\n" ); - fclose( pFile ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/rwr/rwrUtil.c b/src/opt/rwr/rwrUtil.c deleted file mode 100644 index b2add2bf..00000000 --- a/src/opt/rwr/rwrUtil.c +++ /dev/null @@ -1,659 +0,0 @@ -/**CFile**************************************************************** - - FileName [rwrUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [DAG-aware AIG rewriting package.] - - Synopsis [Various utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: rwrUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "rwr.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// precomputed data -#ifdef _WIN32 -unsigned short s_RwrPracticalClasses[]; -unsigned short s_RwtAigSubgraphs[]; -#else -static unsigned short s_RwrPracticalClasses[]; -static unsigned short s_RwtAigSubgraphs[]; -#endif - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Writes data.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManWriteToArray( Rwr_Man_t * p ) -{ - FILE * pFile; - Rwr_Node_t * pNode; - unsigned Entry0, Entry1; - int i, nEntries, clk = clock(); - // prepare the buffer - nEntries = p->vForest->nSize - 5; - pFile = fopen( "npn4_aig_array.txt", "w" ); - fprintf( pFile, "static unsigned short s_RwtAigSubgraphs[] = \n{" ); - for ( i = 0; i < nEntries; i++ ) - { - if ( i % 5 == 0 ) - fprintf( pFile, "\n " ); - pNode = p->vForest->pArray[i+5]; - Entry0 = (Rwr_Regular(pNode->p0)->Id << 1) | Rwr_IsComplement(pNode->p0); - Entry1 = (Rwr_Regular(pNode->p1)->Id << 1) | Rwr_IsComplement(pNode->p1); - Entry0 = (Entry0 << 1) | pNode->fExor; - Extra_PrintHex( pFile, Entry0, 4 ); - fprintf( pFile, "," ); - Extra_PrintHex( pFile, Entry1, 4 ); - fprintf( pFile, ", " ); - } - if ( i % 5 == 0 ) - fprintf( pFile, "\n " ); - Extra_PrintHex( pFile, 0, 4 ); - fprintf( pFile, "," ); - Extra_PrintHex( pFile, 0, 4 ); - fprintf( pFile, " \n};\n" ); - fclose( pFile ); - printf( "The number of nodes saved = %d. ", nEntries ); PRT( "Saving", clock() - clk ); -} - -/**Function************************************************************* - - Synopsis [Loads data.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManLoadFromArray( Rwr_Man_t * p, int fVerbose ) -{ - unsigned short * pArray = s_RwtAigSubgraphs; - Rwr_Node_t * p0, * p1; - unsigned Entry0, Entry1; - int Level, Volume, nEntries, fExor; - int i, clk = clock(); - - // reconstruct the forest - for ( i = 0; ; i++ ) - { - Entry0 = pArray[2*i + 0]; - Entry1 = pArray[2*i + 1]; - if ( Entry0 == 0 && Entry1 == 0 ) - break; - // get EXOR flag - fExor = (Entry0 & 1); - Entry0 >>= 1; - // get the nodes - p0 = p->vForest->pArray[Entry0 >> 1]; - p1 = p->vForest->pArray[Entry1 >> 1]; - // compute the level and volume of the new nodes - Level = 1 + ABC_MAX( p0->Level, p1->Level ); - Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); - // set the complemented attributes - p0 = Rwr_NotCond( p0, (Entry0 & 1) ); - p1 = Rwr_NotCond( p1, (Entry1 & 1) ); - // add the node -// Rwr_ManTryNode( p, p0, p1, Level, Volume ); - Rwr_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor ); - } - nEntries = i - 1; - if ( fVerbose ) - { - printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded ); - printf( "The number of nodes loaded = %d. ", nEntries ); PRT( "Loading", clock() - clk ); - } -} - - -/**Function************************************************************* - - Synopsis [Writes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManWriteToFile( Rwr_Man_t * p, char * pFileName ) -{ - FILE * pFile; - Rwr_Node_t * pNode; - unsigned * pBuffer; - int i, nEntries, clk = clock(); - // prepare the buffer - nEntries = p->vForest->nSize - 5; - pBuffer = ALLOC( unsigned, nEntries * 2 ); - for ( i = 0; i < nEntries; i++ ) - { - pNode = p->vForest->pArray[i+5]; - pBuffer[2*i + 0] = (Rwr_Regular(pNode->p0)->Id << 1) | Rwr_IsComplement(pNode->p0); - pBuffer[2*i + 1] = (Rwr_Regular(pNode->p1)->Id << 1) | Rwr_IsComplement(pNode->p1); - // save EXOR flag - pBuffer[2*i + 0] = (pBuffer[2*i + 0] << 1) | pNode->fExor; - - } - pFile = fopen( pFileName, "wb" ); - fwrite( &nEntries, sizeof(int), 1, pFile ); - fwrite( pBuffer, sizeof(unsigned), nEntries * 2, pFile ); - free( pBuffer ); - fclose( pFile ); - printf( "The number of nodes saved = %d. ", nEntries ); PRT( "Saving", clock() - clk ); -} - -/**Function************************************************************* - - Synopsis [Loads data.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ManLoadFromFile( Rwr_Man_t * p, char * pFileName ) -{ - FILE * pFile; - Rwr_Node_t * p0, * p1; - unsigned * pBuffer; - int Level, Volume, nEntries, fExor; - int i, clk = clock(); - - // load the data - pFile = fopen( pFileName, "rb" ); - if ( pFile == NULL ) - { - printf( "Rwr_ManLoadFromFile: Cannot open file \"%s\".\n", pFileName ); - return; - } - fread( &nEntries, sizeof(int), 1, pFile ); - pBuffer = ALLOC( unsigned, nEntries * 2 ); - fread( pBuffer, sizeof(unsigned), nEntries * 2, pFile ); - fclose( pFile ); - // reconstruct the forest - for ( i = 0; i < nEntries; i++ ) - { - // get EXOR flag - fExor = (pBuffer[2*i + 0] & 1); - pBuffer[2*i + 0] = (pBuffer[2*i + 0] >> 1); - // get the nodes - p0 = p->vForest->pArray[pBuffer[2*i + 0] >> 1]; - p1 = p->vForest->pArray[pBuffer[2*i + 1] >> 1]; - // compute the level and volume of the new nodes - Level = 1 + ABC_MAX( p0->Level, p1->Level ); - Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); - // set the complemented attributes - p0 = Rwr_NotCond( p0, (pBuffer[2*i + 0] & 1) ); - p1 = Rwr_NotCond( p1, (pBuffer[2*i + 1] & 1) ); - // add the node -// Rwr_ManTryNode( p, p0, p1, Level, Volume ); - Rwr_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor ); - } - free( pBuffer ); - printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded ); - printf( "The number of nodes loaded = %d. ", nEntries ); PRT( "Loading", clock() - clk ); -} - - -/**Function************************************************************* - - Synopsis [Adds the node to the end of the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Rwr_ListAddToTail( Rwr_Node_t ** ppList, Rwr_Node_t * pNode ) -{ - Rwr_Node_t * pTemp; - // find the last one - for ( pTemp = *ppList; pTemp; pTemp = pTemp->pNext ) - ppList = &pTemp->pNext; - // attach at the end - *ppList = pNode; -} - -/**Function************************************************************* - - Synopsis [Create practical classes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Rwr_ManGetPractical( Rwr_Man_t * p ) -{ - char * pPractical; - int i; - pPractical = ALLOC( char, p->nFuncs ); - memset( pPractical, 0, sizeof(char) * p->nFuncs ); - pPractical[0] = 1; - for ( i = 1; ; i++ ) - { - if ( s_RwrPracticalClasses[i] == 0 ) - break; - pPractical[ s_RwrPracticalClasses[i] ] = 1; - } - return pPractical; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -// the following 135 practical NPN classes of 4-variable functions were computed -// by considering all 4-input cuts appearing in IWLS, MCNC, and ISCAS benchmarks -static unsigned short s_RwrPracticalClasses[] = -{ - 0x0000, 0x0001, 0x0003, 0x0006, 0x0007, 0x000f, 0x0016, 0x0017, 0x0018, 0x0019, 0x001b, - 0x001e, 0x001f, 0x003c, 0x003d, 0x003f, 0x0069, 0x006b, 0x006f, 0x007e, 0x007f, 0x00ff, - 0x0116, 0x0118, 0x0119, 0x011a, 0x011b, 0x011e, 0x011f, 0x012c, 0x012d, 0x012f, 0x013c, - 0x013d, 0x013e, 0x013f, 0x0168, 0x0169, 0x016f, 0x017f, 0x0180, 0x0181, 0x0182, 0x0183, - 0x0186, 0x0189, 0x018b, 0x018f, 0x0198, 0x0199, 0x019b, 0x01a8, 0x01a9, 0x01aa, 0x01ab, - 0x01ac, 0x01ad, 0x01ae, 0x01af, 0x01bf, 0x01e9, 0x01ea, 0x01eb, 0x01ee, 0x01ef, 0x01fe, - 0x033c, 0x033d, 0x033f, 0x0356, 0x0357, 0x0358, 0x0359, 0x035a, 0x035b, 0x035f, 0x0368, - 0x0369, 0x036c, 0x036e, 0x037d, 0x03c0, 0x03c1, 0x03c3, 0x03c7, 0x03cf, 0x03d4, 0x03d5, - 0x03d7, 0x03d8, 0x03d9, 0x03dc, 0x03dd, 0x03de, 0x03fc, 0x0660, 0x0661, 0x0666, 0x0669, - 0x066f, 0x0676, 0x067e, 0x0690, 0x0696, 0x0697, 0x069f, 0x06b1, 0x06b6, 0x06f0, 0x06f2, - 0x06f6, 0x06f9, 0x0776, 0x0778, 0x07b0, 0x07b1, 0x07b4, 0x07bc, 0x07f0, 0x07f2, 0x07f8, - 0x0ff0, 0x1683, 0x1696, 0x1698, 0x169e, 0x16e9, 0x178e, 0x17e8, 0x18e7, 0x19e6, 0x1be4, - 0x1ee1, 0x3cc3, 0x6996, 0x0000 -}; - -static unsigned short s_RwtAigSubgraphs[] = -{ - 0x0008,0x0002, 0x000a,0x0002, 0x0008,0x0003, 0x000a,0x0003, 0x0009,0x0002, - 0x000c,0x0002, 0x000e,0x0002, 0x000c,0x0003, 0x000e,0x0003, 0x000d,0x0002, - 0x000c,0x0004, 0x000e,0x0004, 0x000c,0x0005, 0x000e,0x0005, 0x000d,0x0004, - 0x0010,0x0002, 0x0012,0x0002, 0x0010,0x0003, 0x0012,0x0003, 0x0011,0x0002, - 0x0010,0x0004, 0x0012,0x0004, 0x0010,0x0005, 0x0012,0x0005, 0x0011,0x0004, - 0x0010,0x0006, 0x0012,0x0006, 0x0010,0x0007, 0x0012,0x0007, 0x0011,0x0006, - 0x0016,0x0005, 0x0014,0x0006, 0x0016,0x0006, 0x0014,0x0007, 0x0016,0x0007, - 0x0015,0x0006, 0x0014,0x0008, 0x0016,0x0008, 0x0014,0x0009, 0x0016,0x0009, - 0x0015,0x0008, 0x0018,0x0006, 0x001a,0x0006, 0x0018,0x0007, 0x001a,0x0007, - 0x0019,0x0006, 0x0018,0x0009, 0x001a,0x0009, 0x0019,0x0008, 0x001e,0x0005, - 0x001c,0x0006, 0x001e,0x0006, 0x001c,0x0007, 0x001e,0x0007, 0x001d,0x0006, - 0x001c,0x0008, 0x001e,0x0008, 0x001c,0x0009, 0x001e,0x0009, 0x001d,0x0008, - 0x0020,0x0006, 0x0022,0x0006, 0x0020,0x0007, 0x0022,0x0007, 0x0021,0x0006, - 0x0020,0x0008, 0x0022,0x0008, 0x0020,0x0009, 0x0022,0x0009, 0x0021,0x0008, - 0x0024,0x0006, 0x0026,0x0006, 0x0024,0x0007, 0x0026,0x0007, 0x0025,0x0006, - 0x0026,0x0008, 0x0024,0x0009, 0x0026,0x0009, 0x0025,0x0008, 0x0028,0x0004, - 0x002a,0x0004, 0x0028,0x0005, 0x002a,0x0007, 0x0028,0x0008, 0x002a,0x0009, - 0x0029,0x0008, 0x002a,0x000b, 0x0029,0x000a, 0x002a,0x000f, 0x0029,0x000e, - 0x002a,0x0011, 0x002a,0x0013, 0x002c,0x0004, 0x002e,0x0004, 0x002c,0x0005, - 0x002c,0x0009, 0x002e,0x0009, 0x002d,0x0008, 0x002d,0x000c, 0x002e,0x000f, - 0x002e,0x0011, 0x002e,0x0012, 0x0030,0x0004, 0x0032,0x0007, 0x0032,0x0009, - 0x0031,0x0008, 0x0032,0x000b, 0x0032,0x000d, 0x0032,0x000f, 0x0031,0x000e, - 0x0032,0x0013, 0x0034,0x0004, 0x0036,0x0004, 0x0034,0x0005, 0x0036,0x0005, - 0x0035,0x0004, 0x0036,0x0008, 0x0034,0x0009, 0x0036,0x0009, 0x0035,0x0008, - 0x0036,0x000b, 0x0036,0x000d, 0x0036,0x0011, 0x0035,0x0010, 0x0036,0x0013, - 0x0038,0x0004, 0x0039,0x0004, 0x0038,0x0009, 0x003a,0x0009, 0x0039,0x0008, - 0x0038,0x000b, 0x003a,0x000b, 0x003a,0x000d, 0x003a,0x0011, 0x003a,0x0012, - 0x0038,0x0013, 0x003a,0x0013, 0x003c,0x0002, 0x003e,0x0002, 0x003c,0x0003, - 0x003e,0x0005, 0x003e,0x0007, 0x003c,0x0008, 0x003e,0x0008, 0x003c,0x0009, - 0x003e,0x0009, 0x003d,0x0008, 0x003e,0x000d, 0x003e,0x0011, 0x003e,0x0013, - 0x003e,0x0017, 0x003e,0x001b, 0x003e,0x001d, 0x0040,0x0002, 0x0042,0x0002, - 0x0042,0x0005, 0x0041,0x0006, 0x0042,0x0008, 0x0041,0x0008, 0x0042,0x000d, - 0x0042,0x0011, 0x0042,0x0015, 0x0042,0x0019, 0x0042,0x001b, 0x0042,0x001c, - 0x0041,0x001c, 0x0044,0x0002, 0x0046,0x0003, 0x0045,0x0004, 0x0046,0x0007, - 0x0045,0x0008, 0x0046,0x000b, 0x0046,0x000f, 0x0046,0x0013, 0x0045,0x0012, - 0x0046,0x0017, 0x0046,0x001b, 0x0046,0x0021, 0x0048,0x0002, 0x004a,0x0002, - 0x0048,0x0003, 0x004a,0x0003, 0x0049,0x0002, 0x0048,0x0008, 0x004a,0x0008, - 0x0048,0x0009, 0x004a,0x0009, 0x0049,0x0008, 0x004a,0x000b, 0x004a,0x000f, - 0x004a,0x0011, 0x004a,0x0012, 0x004a,0x0013, 0x004a,0x0015, 0x004a,0x0019, - 0x004a,0x001b, 0x004a,0x001d, 0x004c,0x0002, 0x004c,0x0003, 0x004d,0x0002, - 0x004c,0x0008, 0x004e,0x0008, 0x004c,0x0009, 0x004e,0x0009, 0x004d,0x0008, - 0x004c,0x000b, 0x004e,0x000b, 0x004c,0x000f, 0x004e,0x000f, 0x004e,0x0011, - 0x004c,0x0012, 0x004c,0x0013, 0x004e,0x0013, 0x004e,0x0015, 0x004c,0x0017, - 0x004e,0x0019, 0x004c,0x001b, 0x004e,0x001b, 0x004c,0x001c, 0x004c,0x001d, - 0x004e,0x001d, 0x0050,0x0004, 0x0052,0x0004, 0x0050,0x0006, 0x0052,0x0009, - 0x0052,0x000d, 0x0052,0x000f, 0x0052,0x0013, 0x0052,0x0017, 0x0052,0x0019, - 0x0052,0x001d, 0x0052,0x001f, 0x0052,0x0021, 0x0052,0x0023, 0x0052,0x0024, - 0x0052,0x0025, 0x0051,0x0024, 0x0052,0x0027, 0x0054,0x0004, 0x0056,0x0004, - 0x0054,0x0005, 0x0056,0x0006, 0x0054,0x0007, 0x0056,0x0011, 0x0056,0x001b, - 0x0056,0x001e, 0x0054,0x001f, 0x0056,0x001f, 0x0056,0x0020, 0x0054,0x0021, - 0x0055,0x0020, 0x0056,0x0024, 0x0054,0x0025, 0x0056,0x0025, 0x0055,0x0024, - 0x0054,0x0027, 0x0056,0x0027, 0x0055,0x0026, 0x005a,0x0007, 0x005a,0x0009, - 0x005a,0x000b, 0x005a,0x0015, 0x005a,0x001f, 0x0059,0x0020, 0x0058,0x0024, - 0x005a,0x0024, 0x005a,0x0027, 0x0059,0x0026, 0x005c,0x0004, 0x005e,0x0004, - 0x005c,0x0005, 0x005e,0x0006, 0x005c,0x0007, 0x005d,0x0006, 0x005e,0x000d, - 0x005e,0x0013, 0x005e,0x0017, 0x005c,0x001f, 0x005d,0x001e, 0x005e,0x0020, - 0x005e,0x0021, 0x005e,0x0022, 0x005e,0x0023, 0x005c,0x0024, 0x005e,0x0024, - 0x005c,0x0025, 0x005e,0x0025, 0x005d,0x0024, 0x005e,0x0026, 0x005e,0x0027, - 0x0062,0x0004, 0x0061,0x0004, 0x0062,0x0006, 0x0061,0x0006, 0x0060,0x000f, - 0x0060,0x0013, 0x0062,0x0013, 0x0060,0x0019, 0x0062,0x001c, 0x0060,0x001d, - 0x0062,0x001d, 0x0062,0x001f, 0x0060,0x0021, 0x0060,0x0023, 0x0062,0x0024, - 0x0060,0x0027, 0x0061,0x0026, 0x0064,0x0002, 0x0066,0x0002, 0x0064,0x0006, - 0x0066,0x0007, 0x0066,0x0009, 0x0066,0x000d, 0x0066,0x0013, 0x0066,0x0015, - 0x0066,0x0017, 0x0066,0x0019, 0x0066,0x001a, 0x0065,0x001a, 0x0066,0x001f, - 0x0066,0x0023, 0x0066,0x0027, 0x0066,0x002f, 0x0066,0x0030, 0x006a,0x0002, - 0x0068,0x0003, 0x0068,0x0006, 0x006a,0x0006, 0x006a,0x0011, 0x0068,0x0016, - 0x0068,0x0017, 0x006a,0x0017, 0x006a,0x001a, 0x006a,0x001b, 0x006a,0x0025, - 0x006a,0x002d, 0x006e,0x0003, 0x006e,0x0007, 0x006e,0x0009, 0x006e,0x000b, - 0x006e,0x0015, 0x006e,0x0016, 0x006e,0x0017, 0x006c,0x001a, 0x006e,0x001a, - 0x006e,0x001f, 0x006e,0x002b, 0x006e,0x0035, 0x0070,0x0002, 0x0070,0x0003, - 0x0072,0x0006, 0x0070,0x0007, 0x0071,0x0006, 0x0072,0x000b, 0x0072,0x000f, - 0x0072,0x0013, 0x0070,0x0015, 0x0071,0x0014, 0x0072,0x0017, 0x0072,0x0018, - 0x0070,0x0019, 0x0072,0x0019, 0x0070,0x001a, 0x0070,0x001b, 0x0072,0x001b, - 0x0071,0x001a, 0x0072,0x0021, 0x0072,0x0029, 0x0076,0x0002, 0x0076,0x0003, - 0x0075,0x0002, 0x0076,0x0006, 0x0074,0x0007, 0x0076,0x0007, 0x0075,0x0006, - 0x0076,0x000d, 0x0076,0x0011, 0x0076,0x0013, 0x0075,0x0014, 0x0076,0x0019, - 0x0076,0x001a, 0x0076,0x001b, 0x0075,0x001c, 0x0074,0x0023, 0x0075,0x0022, - 0x0074,0x0026, 0x0076,0x0026, 0x0074,0x0027, 0x0076,0x002b, 0x0076,0x002f, - 0x0078,0x0002, 0x0078,0x0004, 0x007a,0x0004, 0x007a,0x0005, 0x0079,0x0004, - 0x007a,0x0009, 0x007a,0x000a, 0x007a,0x000b, 0x007a,0x000d, 0x007a,0x000f, - 0x007a,0x0010, 0x007a,0x0011, 0x007a,0x0012, 0x007a,0x0013, 0x007a,0x0017, - 0x007a,0x001b, 0x007a,0x0021, 0x007a,0x0027, 0x007a,0x002b, 0x007a,0x002f, - 0x007a,0x0030, 0x0079,0x0034, 0x007a,0x0039, 0x007a,0x003a, 0x007e,0x0002, - 0x007c,0x0004, 0x007e,0x0004, 0x007e,0x000c, 0x007c,0x000d, 0x007e,0x0011, - 0x007e,0x0013, 0x007e,0x001b, 0x007e,0x0025, 0x007e,0x002d, 0x007e,0x0037, - 0x0082,0x0003, 0x0082,0x0005, 0x0082,0x0009, 0x0082,0x000b, 0x0080,0x0010, - 0x0082,0x0010, 0x0082,0x0012, 0x0082,0x0015, 0x0082,0x001f, 0x0082,0x002b, - 0x0082,0x0035, 0x0082,0x0039, 0x0082,0x003f, 0x0084,0x0002, 0x0086,0x0002, - 0x0084,0x0003, 0x0086,0x0003, 0x0085,0x0002, 0x0086,0x0004, 0x0084,0x0005, - 0x0085,0x0004, 0x0086,0x000a, 0x0084,0x000b, 0x0085,0x000a, 0x0086,0x000d, - 0x0086,0x000e, 0x0086,0x000f, 0x0084,0x0010, 0x0084,0x0011, 0x0086,0x0011, - 0x0085,0x0010, 0x0084,0x0012, 0x0084,0x0013, 0x0086,0x0013, 0x0085,0x0012, - 0x0086,0x0019, 0x0086,0x0023, 0x0086,0x0029, 0x0086,0x0033, 0x0086,0x0039, - 0x008a,0x0003, 0x0089,0x0002, 0x0088,0x0004, 0x008a,0x0004, 0x0088,0x0005, - 0x0089,0x0004, 0x008a,0x000b, 0x008a,0x0010, 0x0088,0x0011, 0x008a,0x0011, - 0x0089,0x0010, 0x0088,0x0012, 0x008a,0x0012, 0x0089,0x0012, 0x008a,0x0017, - 0x008a,0x001b, 0x0089,0x0020, 0x008a,0x0025, 0x0088,0x0027, 0x008a,0x002b, - 0x008a,0x002f, 0x008a,0x0039, 0x0088,0x003a, 0x008d,0x0044, 0x0092,0x0009, - 0x0092,0x0025, 0x0092,0x0029, 0x0092,0x002d, 0x0092,0x0033, 0x0092,0x0037, - 0x0092,0x003d, 0x0092,0x0041, 0x0095,0x0002, 0x0095,0x0004, 0x0095,0x0010, - 0x0095,0x0012, 0x0096,0x0021, 0x0096,0x0029, 0x0095,0x002e, 0x0096,0x0030, - 0x0096,0x0033, 0x0096,0x003a, 0x0096,0x0043, 0x009a,0x0008, 0x009a,0x0009, - 0x0099,0x0008, 0x009a,0x0011, 0x009a,0x0023, 0x009a,0x0033, 0x009a,0x003d, - 0x009a,0x0044, 0x009a,0x0045, 0x0099,0x0044, 0x009d,0x0002, 0x009e,0x0008, - 0x009c,0x0009, 0x009e,0x0009, 0x009d,0x0008, 0x009e,0x0011, 0x009d,0x0010, - 0x009e,0x001f, 0x009e,0x003f, 0x00a0,0x0009, 0x00a0,0x0011, 0x00a2,0x0030, - 0x00a2,0x0033, 0x00a6,0x0006, 0x00a6,0x0007, 0x00a6,0x0011, 0x00a6,0x0044, - 0x00a6,0x004b, 0x00aa,0x0007, 0x00aa,0x0015, 0x00ae,0x0006, 0x00ae,0x0011, - 0x00ae,0x001b, 0x00ae,0x0025, 0x00ae,0x003d, 0x00ae,0x0041, 0x00ae,0x0043, - 0x00ae,0x0045, 0x00b2,0x0006, 0x00b0,0x0007, 0x00b1,0x0006, 0x00b2,0x0017, - 0x00b1,0x0016, 0x00b0,0x0019, 0x00b2,0x0021, 0x00b2,0x003d, 0x00b5,0x004a, - 0x00ba,0x0009, 0x00ba,0x000f, 0x00bc,0x0009, 0x00be,0x0009, 0x00be,0x000f, - 0x00bd,0x000e, 0x00be,0x0017, 0x00c2,0x0009, 0x00c2,0x0019, 0x00c2,0x001f, - 0x00c2,0x0033, 0x00c6,0x0009, 0x00c5,0x000e, 0x00c6,0x0015, 0x00c6,0x0023, - 0x00c4,0x002d, 0x00c6,0x002f, 0x00c5,0x002e, 0x00c6,0x0045, 0x00ce,0x0007, - 0x00ce,0x0021, 0x00ce,0x0023, 0x00ce,0x0025, 0x00ce,0x0027, 0x00ce,0x0033, - 0x00ce,0x003d, 0x00d2,0x0006, 0x00d0,0x0015, 0x00d0,0x001b, 0x00d2,0x001b, - 0x00d1,0x001a, 0x00d0,0x001f, 0x00d2,0x0025, 0x00d1,0x0024, 0x00d2,0x0037, - 0x00d2,0x0041, 0x00d2,0x0045, 0x00d9,0x0044, 0x00e1,0x0004, 0x00e2,0x000d, - 0x00e2,0x0021, 0x00e0,0x003a, 0x00e6,0x003d, 0x00e6,0x0061, 0x00e6,0x0067, - 0x00e9,0x0004, 0x00ea,0x0008, 0x00ea,0x0009, 0x00ea,0x0039, 0x00e9,0x0038, - 0x00ea,0x003f, 0x00ec,0x000d, 0x00ee,0x000d, 0x00ee,0x0037, 0x00f2,0x003d, - 0x00f2,0x0062, 0x00f5,0x0002, 0x00fa,0x0017, 0x00fa,0x003d, 0x00fe,0x0006, - 0x00fd,0x0006, 0x00fc,0x0015, 0x00fe,0x001b, 0x00fc,0x0025, 0x00fe,0x0025, - 0x00fd,0x0024, 0x00fe,0x0041, 0x00fe,0x004d, 0x00fd,0x004e, 0x0101,0x0014, - 0x0106,0x004d, 0x010a,0x0009, 0x010a,0x000b, 0x0109,0x000a, 0x010a,0x004f, - 0x010a,0x0058, 0x010e,0x0008, 0x010c,0x0009, 0x010e,0x0009, 0x010d,0x0008, - 0x010e,0x000b, 0x010e,0x002b, 0x010d,0x002a, 0x010e,0x0035, 0x010e,0x003d, - 0x010e,0x003f, 0x010e,0x0049, 0x010e,0x0057, 0x010d,0x0056, 0x010d,0x0058, - 0x0111,0x0004, 0x0111,0x0006, 0x0110,0x0009, 0x0112,0x0009, 0x0111,0x0008, - 0x0112,0x002f, 0x0110,0x0035, 0x0110,0x0037, 0x0112,0x0039, 0x0112,0x003d, - 0x0112,0x003f, 0x0112,0x0045, 0x0111,0x0044, 0x0112,0x004b, 0x0112,0x0059, - 0x0112,0x0069, 0x0112,0x007f, 0x0116,0x0009, 0x0115,0x0008, 0x0114,0x000b, - 0x0116,0x000b, 0x0116,0x0058, 0x011a,0x0015, 0x011a,0x001f, 0x011a,0x002b, - 0x011a,0x003f, 0x011a,0x0049, 0x011a,0x0085, 0x011e,0x0007, 0x011e,0x0019, - 0x011e,0x001b, 0x011e,0x0023, 0x011e,0x0027, 0x011e,0x002f, 0x011e,0x0043, - 0x011e,0x004b, 0x011e,0x004e, 0x011e,0x004f, 0x011e,0x005f, 0x011e,0x0061, - 0x011e,0x0065, 0x011e,0x0083, 0x0122,0x0006, 0x0120,0x0007, 0x0122,0x0007, - 0x0121,0x0006, 0x0122,0x0049, 0x0121,0x004e, 0x0122,0x008f, 0x0125,0x0004, - 0x0124,0x0007, 0x0125,0x0006, 0x0124,0x001b, 0x0126,0x001b, 0x0126,0x0045, - 0x0126,0x0087, 0x0128,0x0007, 0x0129,0x0006, 0x012a,0x0019, 0x012a,0x003d, - 0x012a,0x0051, 0x012a,0x0065, 0x012a,0x0083, 0x012d,0x005a, 0x0132,0x0009, - 0x0132,0x008f, 0x0134,0x0009, 0x0135,0x003e, 0x013a,0x003d, 0x013a,0x0044, - 0x0139,0x0044, 0x013e,0x0009, 0x013d,0x0008, 0x013c,0x003d, 0x013c,0x0044, - 0x013c,0x0053, 0x013e,0x008f, 0x013e,0x0095, 0x0142,0x0044, 0x0142,0x0097, - 0x0142,0x009e, 0x0144,0x0007, 0x0148,0x0015, 0x0148,0x001c, 0x0148,0x001f, - 0x0148,0x0026, 0x0149,0x0086, 0x014d,0x0006, 0x014e,0x0044, 0x014d,0x0048, - 0x014e,0x009e, 0x0152,0x0009, 0x0151,0x00a6, 0x0155,0x0030, 0x015d,0x003a, - 0x0162,0x009e, 0x0164,0x000f, 0x0164,0x0013, 0x0169,0x000e, 0x0174,0x0009, - 0x0179,0x0008, 0x0180,0x0009, 0x0181,0x0044, 0x0186,0x0044, 0x0185,0x0044, - 0x018a,0x0068, 0x0195,0x004e, 0x01a6,0x0009, 0x01a5,0x0008, 0x01b1,0x003a, - 0x01c4,0x0029, 0x01c4,0x0030, 0x01ca,0x008f, 0x01ca,0x0095, 0x01cc,0x0029, - 0x01cc,0x0033, 0x01ce,0x003d, 0x01d6,0x00b2, 0x01d8,0x0009, 0x01d9,0x002a, - 0x01d9,0x0056, 0x01d9,0x00a4, 0x01dd,0x003a, 0x01e2,0x00b2, 0x01e6,0x0013, - 0x01e6,0x009f, 0x01e6,0x00ba, 0x01e6,0x00c0, 0x01e6,0x00d3, 0x01e6,0x00d5, - 0x01e6,0x00e5, 0x01e8,0x0005, 0x01f2,0x0013, 0x01f2,0x0095, 0x01f2,0x009f, - 0x01f2,0x00ba, 0x01f2,0x00c0, 0x01f2,0x00d3, 0x0202,0x008f, 0x0202,0x0095, - 0x0202,0x00f3, 0x0202,0x00f9, 0x020a,0x0044, 0x0209,0x00b4, 0x020e,0x0009, - 0x020d,0x0008, 0x020c,0x003d, 0x020c,0x0044, 0x020c,0x0053, 0x020e,0x008f, - 0x020e,0x0095, 0x020c,0x00b1, 0x020e,0x00f3, 0x020e,0x00f9, 0x0210,0x0013, - 0x0211,0x0024, 0x0210,0x0026, 0x0219,0x0004, 0x021e,0x008f, 0x021e,0x0095, - 0x0221,0x003a, 0x0230,0x0009, 0x0236,0x0009, 0x0234,0x0029, 0x0234,0x0030, - 0x0234,0x0033, 0x0234,0x003a, 0x0234,0x003d, 0x0234,0x0044, 0x0235,0x00a6, - 0x023a,0x0009, 0x023d,0x003a, 0x0245,0x0044, 0x0249,0x003a, 0x024e,0x009e, - 0x024e,0x0106, 0x0251,0x0026, 0x0258,0x0013, 0x0259,0x0024, 0x0258,0x0061, - 0x0259,0x0086, 0x0258,0x00c7, 0x0258,0x00df, 0x0259,0x00ec, 0x0258,0x00fc, - 0x025d,0x0024, 0x025d,0x00de, 0x0260,0x00f6, 0x0268,0x0009, 0x0269,0x0044, - 0x0268,0x00f3, 0x0268,0x00f9, 0x026d,0x003a, 0x0270,0x0068, 0x0275,0x003a, - 0x027a,0x0044, 0x0279,0x0044, 0x027e,0x007e, 0x0281,0x0044, 0x0285,0x0008, - 0x028d,0x0006, 0x028d,0x00d2, 0x0295,0x00cc, 0x0296,0x00f6, 0x0295,0x00f8, - 0x0299,0x0030, 0x029e,0x007e, 0x029d,0x0080, 0x02a6,0x008f, 0x02a6,0x0095, - 0x02aa,0x0029, 0x02aa,0x0030, 0x02b5,0x0008, 0x02b9,0x003a, 0x02bd,0x0004, - 0x02bd,0x00fc, 0x02c2,0x00b2, 0x02c1,0x00b4, 0x02c4,0x0029, 0x02c8,0x0029, - 0x02c8,0x0033, 0x02ca,0x003d, 0x02ce,0x0029, 0x02ce,0x0030, 0x02d2,0x0068, - 0x02d1,0x006a, 0x02d5,0x006a, 0x02d9,0x0008, 0x02de,0x012c, 0x02e2,0x012c, - 0x02e4,0x0009, 0x02e5,0x002a, 0x02e5,0x0056, 0x02e5,0x012c, 0x02ea,0x0029, - 0x02ea,0x0030, 0x02e9,0x0030, 0x02ec,0x0029, 0x02ec,0x0030, 0x02ee,0x012c, - 0x02f1,0x0068, 0x02f1,0x00b2, 0x02f1,0x0108, 0x02f1,0x012c, 0x02f6,0x0013, - 0x02f6,0x0015, 0x02f6,0x001f, 0x02f6,0x0030, 0x02f6,0x0065, 0x02f6,0x0067, - 0x02f6,0x009f, 0x02f6,0x00b6, 0x02f6,0x00b9, 0x02f6,0x00c0, 0x02f6,0x00cf, - 0x02f6,0x0107, 0x02f6,0x010b, 0x02f6,0x010f, 0x02f6,0x0115, 0x02f6,0x012d, - 0x02f6,0x0134, 0x02f6,0x0153, 0x02f6,0x0171, 0x02f6,0x0176, 0x02f8,0x0003, - 0x02fa,0x017b, 0x02fc,0x00ba, 0x02fc,0x00d3, 0x0302,0x0013, 0x0302,0x001f, - 0x0302,0x0030, 0x0302,0x005d, 0x0302,0x0065, 0x0302,0x0067, 0x0302,0x0099, - 0x0302,0x009f, 0x0302,0x00ad, 0x0302,0x00b9, 0x0302,0x00c0, 0x0302,0x00cf, - 0x0301,0x00d2, 0x0301,0x00fe, 0x0302,0x0107, 0x0302,0x010b, 0x0302,0x010f, - 0x0302,0x0117, 0x0302,0x0134, 0x0302,0x0153, 0x0302,0x0157, 0x0302,0x0176, - 0x0306,0x0029, 0x0308,0x00b2, 0x0309,0x00dc, 0x030d,0x00f8, 0x0312,0x00f3, - 0x0318,0x007e, 0x031d,0x0080, 0x0321,0x0008, 0x0321,0x0094, 0x0326,0x017b, - 0x0326,0x0181, 0x0329,0x012e, 0x032a,0x017b, 0x032a,0x0181, 0x032e,0x008f, - 0x032e,0x0095, 0x032e,0x00f3, 0x032e,0x00f9, 0x0332,0x0009, 0x0331,0x0008, - 0x0330,0x003d, 0x0330,0x0044, 0x0330,0x0053, 0x0332,0x008f, 0x0332,0x0095, - 0x0330,0x00b1, 0x0332,0x00f3, 0x0332,0x00f9, 0x0330,0x0127, 0x0332,0x017b, - 0x0332,0x0181, 0x033c,0x0013, 0x033c,0x001c, 0x033d,0x0086, 0x033d,0x00ec, - 0x033d,0x0172, 0x033e,0x019d, 0x0345,0x0002, 0x0344,0x008f, 0x0344,0x00f3, - 0x034d,0x0030, 0x0352,0x0033, 0x0354,0x0029, 0x0354,0x0030, 0x035a,0x0009, - 0x035a,0x017b, 0x035a,0x019b, 0x035a,0x01a2, 0x035e,0x0181, 0x0360,0x0009, - 0x0366,0x0009, 0x0364,0x0029, 0x0364,0x0030, 0x0364,0x0033, 0x0364,0x003a, - 0x0364,0x003d, 0x0364,0x0044, 0x0369,0x0030, 0x0370,0x0029, 0x0370,0x0030, - 0x0376,0x0033, 0x037a,0x0009, 0x037a,0x019b, 0x037a,0x01a2, 0x037c,0x0009, - 0x0382,0x0181, 0x0386,0x0009, 0x0384,0x0029, 0x0384,0x0030, 0x0384,0x0033, - 0x0384,0x003a, 0x0384,0x003d, 0x0384,0x0044, 0x038a,0x0044, 0x038a,0x009e, - 0x038a,0x0106, 0x038a,0x0198, 0x038d,0x010e, 0x038d,0x0152, 0x038d,0x0158, - 0x0392,0x009e, 0x0392,0x0106, 0x0392,0x0198, 0x0395,0x0086, 0x0395,0x009a, - 0x0395,0x00ec, 0x0395,0x0172, 0x0398,0x014e, 0x0398,0x0175, 0x0398,0x018d, - 0x039c,0x0023, 0x039c,0x0027, 0x039c,0x00ef, 0x039c,0x0139, 0x039c,0x0168, - 0x03a0,0x0019, 0x03a0,0x001d, 0x03a0,0x0023, 0x03a0,0x0027, 0x03a1,0x004e, - 0x03a4,0x0162, 0x03a4,0x0183, 0x03a8,0x0013, 0x03a8,0x0027, 0x03a8,0x0133, - 0x03a8,0x0148, 0x03a8,0x0181, 0x03ac,0x0013, 0x03ac,0x0027, 0x03b0,0x017b, - 0x03b0,0x0181, 0x03b4,0x004b, 0x03b4,0x00e0, 0x03b4,0x00fb, 0x03b8,0x000f, - 0x03b8,0x0013, 0x03b8,0x00ab, 0x03b8,0x00bf, 0x03b8,0x00d0, 0x03bd,0x00da, - 0x03bd,0x012c, 0x03c8,0x000f, 0x03c8,0x0013, 0x03c8,0x0019, 0x03c8,0x001d, - 0x03cd,0x0086, 0x03cd,0x00ec, 0x03cd,0x0172, 0x03d2,0x00e0, 0x03d2,0x00ef, - 0x03d2,0x0112, 0x03d2,0x0139, 0x03d2,0x0168, 0x03d6,0x017b, 0x03d6,0x0181, - 0x03da,0x0133, 0x03da,0x0148, 0x03e2,0x0023, 0x03e2,0x0027, 0x03e6,0x0027, - 0x03e6,0x0181, 0x03ee,0x017b, 0x03ee,0x0181, 0x03fe,0x003d, 0x0401,0x012a, - 0x0401,0x019e, 0x0405,0x01a0, 0x040a,0x000d, 0x040a,0x011f, 0x040a,0x016f, - 0x040d,0x012a, 0x0412,0x017b, 0x041a,0x0033, 0x041a,0x003d, 0x041a,0x0181, - 0x0421,0x0086, 0x0421,0x009a, 0x0421,0x00ec, 0x0421,0x0172, 0x042e,0x0205, - 0x043a,0x0205, 0x043e,0x017b, 0x0442,0x01f5, 0x044c,0x0007, 0x0452,0x0033, - 0x0452,0x01ce, 0x0452,0x01d0, 0x0452,0x01f1, 0x0452,0x01fb, 0x0452,0x0225, - 0x0454,0x0005, 0x045a,0x0033, 0x045a,0x0181, 0x045a,0x01ce, 0x045a,0x01d0, - 0x045a,0x01f1, 0x0469,0x01de, 0x046e,0x0181, 0x047a,0x01ce, 0x047a,0x01f1, - 0x0485,0x012c, 0x0489,0x012c, 0x0490,0x01d8, 0x0496,0x0033, 0x0496,0x003d, - 0x0498,0x008f, 0x0498,0x00f3, 0x049e,0x0044, 0x049e,0x0221, 0x04a1,0x0006, - 0x04a2,0x0044, 0x04a6,0x0221, 0x04a9,0x0004, 0x04ac,0x0027, 0x04b1,0x009a, - 0x04b6,0x0097, 0x04b8,0x0027, 0x04c6,0x0219, 0x04ca,0x017b, 0x04cc,0x004b, - 0x04d0,0x00ab, 0x04d6,0x017b, 0x04d8,0x000f, 0x04d8,0x0019, 0x04d8,0x0033, - 0x04d8,0x003d, 0x04de,0x003d, 0x04de,0x0103, 0x04de,0x018b, 0x04de,0x0231, - 0x04e2,0x0044, 0x04e2,0x009e, 0x04e2,0x0106, 0x04e2,0x0198, 0x04e5,0x01a4, - 0x04e5,0x01b6, 0x04ea,0x009e, 0x04ea,0x0106, 0x04ea,0x0198, 0x04ed,0x002e, - 0x04ed,0x0038, 0x04ed,0x00a2, 0x04f1,0x0086, 0x04f1,0x009a, 0x04f1,0x00ec, - 0x04f1,0x0172, 0x04f9,0x004e, 0x04f8,0x0229, 0x04f8,0x022d, 0x0500,0x023e, - 0x0504,0x0217, 0x0510,0x00f3, 0x0514,0x0043, 0x0514,0x004d, 0x0514,0x00c3, - 0x0514,0x013d, 0x0514,0x0215, 0x0514,0x0232, 0x0515,0x0260, 0x0519,0x002a, - 0x0518,0x0030, 0x0518,0x0067, 0x0518,0x00c9, 0x0518,0x01eb, 0x0518,0x01ef, - 0x051c,0x0139, 0x051c,0x0168, 0x0520,0x0027, 0x0526,0x014e, 0x0526,0x0175, - 0x0526,0x018d, 0x052d,0x0200, 0x0532,0x0021, 0x0532,0x00bf, 0x0532,0x00d0, - 0x0532,0x0239, 0x0532,0x0266, 0x053d,0x0024, 0x053d,0x00da, 0x054a,0x000f, - 0x054a,0x00ab, 0x054a,0x023a, 0x054e,0x0043, 0x054e,0x004d, 0x054e,0x00c3, - 0x054e,0x013d, 0x054e,0x0215, 0x054e,0x0232, 0x054e,0x029d, 0x0552,0x014e, - 0x0552,0x018d, 0x0556,0x00f3, 0x0556,0x01e4, 0x055a,0x0299, 0x055d,0x0086, - 0x055d,0x009a, 0x055d,0x00ec, 0x055d,0x0172, 0x0566,0x01dc, 0x0566,0x02a5, - 0x056d,0x020a, 0x057a,0x003d, 0x057a,0x01d4, 0x057a,0x01f3, 0x0579,0x025e, - 0x057e,0x0139, 0x057e,0x0168, 0x0581,0x0006, 0x0586,0x017b, 0x0586,0x0181, - 0x0586,0x028c, 0x0588,0x0007, 0x058e,0x0033, 0x058e,0x008f, 0x058e,0x01d0, - 0x058e,0x027c, 0x0590,0x0003, 0x0596,0x0033, 0x0596,0x008f, 0x0596,0x0095, - 0x0596,0x01d0, 0x0596,0x027c, 0x05a2,0x026f, 0x05a5,0x0284, 0x05aa,0x017b, - 0x05ac,0x0205, 0x05b2,0x008f, 0x05b6,0x017b, 0x05b8,0x01da, 0x05c1,0x0276, - 0x05c6,0x0248, 0x05c8,0x0247, 0x05c8,0x027e, 0x05cc,0x003d, 0x05cc,0x01d4, - 0x05cc,0x01f3, 0x05d0,0x014e, 0x05d0,0x018d, 0x05da,0x00f9, 0x05dd,0x0006, - 0x05de,0x0044, 0x05e5,0x002e, 0x05e6,0x02f1, 0x05ea,0x01d4, 0x05ea,0x01f3, - 0x05ea,0x022d, 0x05ed,0x0002, 0x05f6,0x0027, 0x05fa,0x0097, 0x05fc,0x003d, - 0x0602,0x003d, 0x0606,0x00f3, 0x060a,0x0027, 0x060e,0x003d, 0x060e,0x0103, - 0x060e,0x018b, 0x060e,0x0231, 0x060e,0x02d1, 0x0611,0x01fc, 0x0611,0x0234, - 0x061a,0x0287, 0x061d,0x0214, 0x0621,0x01d4, 0x062a,0x0027, 0x062a,0x022d, - 0x062e,0x009e, 0x062e,0x0106, 0x062e,0x0198, 0x0632,0x009e, 0x0632,0x0106, - 0x0632,0x0198, 0x0639,0x0042, 0x0639,0x00b2, 0x0639,0x0108, 0x063d,0x01f8, - 0x0641,0x0086, 0x0641,0x009a, 0x0641,0x00ec, 0x0641,0x0172, 0x0645,0x0044, - 0x0649,0x0042, 0x0648,0x0087, 0x0648,0x00ed, 0x0648,0x0173, 0x0649,0x01a0, - 0x0648,0x0241, 0x0648,0x026f, 0x0648,0x02df, 0x0648,0x0307, 0x064c,0x023a, - 0x064c,0x02b3, 0x0651,0x0062, 0x0650,0x0217, 0x0651,0x02ac, 0x0650,0x02d6, - 0x0655,0x0042, 0x065d,0x0042, 0x0664,0x02b1, 0x0664,0x02ce, 0x0669,0x0238, - 0x066d,0x002a, 0x066c,0x0039, 0x066d,0x01f6, 0x066c,0x0213, 0x066c,0x022e, - 0x066d,0x02a2, 0x066c,0x02e1, 0x0671,0x002a, 0x0670,0x0030, 0x0670,0x0067, - 0x0670,0x00c9, 0x0670,0x01eb, 0x0670,0x01ef, 0x0670,0x02c3, 0x0675,0x0020, - 0x0678,0x0133, 0x0678,0x0148, 0x067c,0x0027, 0x0681,0x023a, 0x0684,0x0021, - 0x0684,0x00bf, 0x0684,0x00d0, 0x0689,0x01fc, 0x068e,0x0162, 0x068e,0x0183, - 0x0691,0x0200, 0x0696,0x0023, 0x0696,0x00e0, 0x0696,0x00fb, 0x0696,0x0268, - 0x069a,0x0282, 0x069d,0x007e, 0x06a2,0x004b, 0x06a2,0x023e, 0x06a2,0x02dc, - 0x06a6,0x0097, 0x06aa,0x02b1, 0x06aa,0x02ce, 0x06ae,0x0039, 0x06ae,0x0213, - 0x06ae,0x022e, 0x06ae,0x02e1, 0x06b2,0x0162, 0x06b2,0x0183, 0x06b6,0x0023, - 0x06b6,0x00e0, 0x06b6,0x00fb, 0x06ba,0x008f, 0x06ba,0x01e4, 0x06be,0x034b, - 0x06c1,0x0086, 0x06c1,0x009a, 0x06c1,0x00ec, 0x06c1,0x0172, 0x06c6,0x01da, - 0x06c6,0x0280, 0x06c6,0x0351, 0x06ce,0x008f, 0x06d2,0x01e3, 0x06d2,0x0287, - 0x06d2,0x0353, 0x06d6,0x027a, 0x06d6,0x029b, 0x06da,0x0033, 0x06da,0x01ce, - 0x06da,0x01f1, 0x06de,0x0133, 0x06de,0x0148, 0x06e2,0x0021, 0x06e2,0x00bf, - 0x06e2,0x00d0, 0x06e5,0x023a, 0x06e9,0x0004, 0x06ee,0x028c, 0x06ee,0x0338, - 0x06f2,0x0328, 0x06f2,0x0330, 0x06f4,0x0005, 0x06f9,0x01e0, 0x06fe,0x0328, - 0x06fe,0x0330, 0x0702,0x003d, 0x0702,0x00f3, 0x0702,0x0330, 0x0704,0x0003, - 0x070a,0x003d, 0x070a,0x00f3, 0x070a,0x01d4, 0x070a,0x01f3, 0x070a,0x0330, - 0x0711,0x032a, 0x0711,0x032e, 0x0716,0x003d, 0x0718,0x0205, 0x0718,0x0282, - 0x071e,0x00f3, 0x0720,0x01dc, 0x0720,0x02a5, 0x0726,0x0324, 0x072a,0x028a, - 0x072a,0x02a7, 0x0729,0x031c, 0x0729,0x032a, 0x072e,0x003d, 0x072e,0x00f9, - 0x072e,0x022d, 0x072e,0x0248, 0x072e,0x02e4, 0x0730,0x003d, 0x0730,0x0247, - 0x0730,0x02e3, 0x0730,0x0324, 0x0732,0x0324, 0x0739,0x032e, 0x073e,0x003d, - 0x0740,0x003d, 0x0744,0x027a, 0x0744,0x029b, 0x0748,0x0033, 0x0748,0x01ce, - 0x0748,0x01f1, 0x074c,0x0162, 0x074c,0x0183, 0x0750,0x0023, 0x0750,0x00e0, - 0x0750,0x00fb, 0x0755,0x0246, 0x075a,0x0095, 0x075a,0x0397, 0x075d,0x0004, - 0x076a,0x03b3, 0x076d,0x0002, 0x0772,0x02fb, 0x0772,0x0301, 0x0772,0x0315, - 0x0772,0x0397, 0x0776,0x008f, 0x077e,0x0027, 0x078a,0x00a1, 0x0792,0x009d, - 0x0792,0x00c3, 0x0792,0x02fb, 0x0792,0x0301, 0x0792,0x0315, 0x0792,0x03bd, - 0x0796,0x0027, 0x0796,0x024f, 0x079e,0x009d, 0x07a6,0x009d, 0x07a6,0x02fb, - 0x07a6,0x0301, 0x07a6,0x0315, 0x07a6,0x03bd, 0x07aa,0x0027, 0x07aa,0x024f, - 0x07ae,0x009d, 0x07b9,0x004e, 0x07b8,0x0087, 0x07b8,0x00ed, 0x07b8,0x0173, - 0x07b8,0x0197, 0x07b9,0x021a, 0x07b9,0x02b8, 0x07b9,0x0364, 0x07be,0x0029, - 0x07be,0x0030, 0x07c0,0x017b, 0x07c6,0x017b, 0x07c8,0x00f3, 0x07ce,0x00f3, - 0x07d0,0x008f, 0x07d6,0x008f, 0x07d9,0x01e8, 0x07dd,0x0292, 0x07e2,0x0053, - 0x07e6,0x008f, 0x07e6,0x00f3, 0x07e6,0x017b, 0x07e8,0x0029, 0x07e8,0x0030, - 0x07ec,0x0021, 0x07ec,0x02ad, 0x07f2,0x0181, 0x07f2,0x0315, 0x07f4,0x0021, - 0x07f8,0x020f, 0x07fd,0x002e, 0x0800,0x008f, 0x0805,0x0006, 0x0809,0x03c2, - 0x080d,0x0084, 0x0812,0x0009, 0x0811,0x0008, 0x0812,0x00f3, 0x0812,0x00f9, - 0x0812,0x017b, 0x0812,0x0181, 0x0814,0x0033, 0x0818,0x0023, 0x081c,0x0285, - 0x0826,0x03bd, 0x082c,0x008f, 0x082c,0x017b, 0x0832,0x0043, 0x0832,0x011b, - 0x0832,0x01b3, 0x0832,0x01c3, 0x0835,0x032a, 0x0838,0x0085, 0x0839,0x032a, - 0x083e,0x0049, 0x083d,0x0084, 0x083e,0x02fb, 0x083e,0x0301, 0x083e,0x0315, - 0x083e,0x0397, 0x0842,0x0009, 0x0841,0x0008, 0x0844,0x0009, 0x0846,0x008f, - 0x084a,0x0033, 0x084e,0x0285, 0x0851,0x009a, 0x0856,0x00a1, 0x0859,0x031c, - 0x085d,0x00b2, 0x0861,0x0012, 0x0861,0x02cc, 0x0865,0x0058, 0x0865,0x007e, - 0x0869,0x004a, 0x0871,0x0010, 0x0876,0x003d, 0x0879,0x032c, 0x087e,0x0089, - 0x0882,0x0229, 0x0882,0x022d, 0x0882,0x02c7, 0x0882,0x02cb, 0x0886,0x0021, - 0x0886,0x02ad, 0x0885,0x0356, 0x088a,0x0017, 0x088a,0x020f, 0x0889,0x0354, - 0x088d,0x009c, 0x0892,0x0089, 0x0895,0x0246, 0x089a,0x03bd, 0x089e,0x008f, - 0x089e,0x02f9, 0x089e,0x0313, 0x08a1,0x032a, 0x08a6,0x0053, 0x08a6,0x0095, - 0x08a6,0x0397, 0x08a8,0x017b, 0x08ad,0x031a, 0x08b2,0x017b, 0x08b4,0x00f3, - 0x08b5,0x02a0, 0x08b8,0x0089, 0x08c1,0x0024, 0x08c4,0x00f3, 0x08c9,0x007e, - 0x08cd,0x007c, 0x08cd,0x0222, 0x08cd,0x0294, 0x08d1,0x003a, 0x08d6,0x0009, - 0x08d9,0x003a, 0x08dc,0x001f, 0x08e0,0x008f, 0x08e0,0x017b, 0x08e4,0x0009, - 0x08e8,0x01ed, 0x08ed,0x031c, 0x08f2,0x003d, 0x08f6,0x008f, 0x08f6,0x017b, - 0x08fa,0x0009, 0x08fe,0x003d, 0x0902,0x01e9, 0x0904,0x01e9, 0x0904,0x0381, - 0x090a,0x03b1, 0x090d,0x031a, 0x0910,0x0299, 0x0914,0x034b, 0x0919,0x0008, - 0x091c,0x0033, 0x091c,0x003d, 0x0920,0x0027, 0x0924,0x0027, 0x0924,0x01fb, - 0x092a,0x01ce, 0x092a,0x01f1, 0x092d,0x031c, 0x0930,0x001f, 0x0936,0x00c5, - 0x0938,0x00c5, 0x0938,0x0381, 0x093c,0x001b, 0x0942,0x017d, 0x094a,0x0027, - 0x094e,0x0027, 0x094e,0x01fb, 0x0952,0x03b1, 0x095a,0x0029, 0x095a,0x0030, - 0x095d,0x0030, 0x0961,0x0030, 0x0966,0x02f9, 0x0966,0x0313, 0x0968,0x02eb, - 0x096d,0x0008, 0x0970,0x017b, 0x0974,0x0033, 0x0979,0x0150, 0x097d,0x009a, - 0x0982,0x0293, 0x0984,0x0293, 0x0984,0x0379, 0x098a,0x02eb, 0x098e,0x0009, - 0x0992,0x003d, 0x0996,0x003d, 0x0999,0x0062, 0x099e,0x003d, 0x09a0,0x0027, - 0x09a5,0x0144, 0x09a8,0x02b5, 0x09ae,0x008f, 0x09ae,0x009d, 0x09b2,0x004d, - 0x09b2,0x0053, 0x09b2,0x00c3, 0x09b2,0x013d, 0x09b2,0x01c5, 0x09b2,0x0271, - 0x09b4,0x0025, 0x09ba,0x0033, 0x09ba,0x0079, 0x09bc,0x0015, 0x09c2,0x013f, - 0x09c4,0x013f, 0x09c4,0x0379, 0x09ca,0x02b5, 0x09cd,0x0006, 0x09da,0x0009, - 0x09d9,0x0008, 0x09dc,0x000b, 0x09dc,0x004f, 0x09dd,0x0086, 0x09e0,0x0009, - 0x09e6,0x00a1, 0x09e8,0x0009, 0x09ed,0x0086, 0x09f2,0x001f, 0x09f2,0x002f, - 0x09f2,0x0049, 0x09f2,0x006f, 0x09f2,0x0085, 0x09f2,0x0091, 0x09f2,0x00a9, - 0x09f2,0x00d3, 0x09f2,0x00d7, 0x09f2,0x011d, 0x09f2,0x0121, 0x09f2,0x0235, - 0x09f2,0x0393, 0x09f6,0x0324, 0x09f8,0x0049, 0x09f8,0x00a9, 0x09f8,0x011d, - 0x09fe,0x001f, 0x09fe,0x0029, 0x09fe,0x0033, 0x09fe,0x003d, 0x09fe,0x0085, - 0x09fe,0x008f, 0x09fe,0x00d3, 0x0a00,0x003d, 0x0a06,0x012d, 0x0a0e,0x00b3, - 0x0a10,0x000b, 0x0a10,0x0387, 0x0a16,0x0059, 0x0a18,0x0009, 0x0a1e,0x0043, - 0x0a24,0x0085, 0x0a2a,0x0009, 0x0a2d,0x0008, 0x0a32,0x028a, 0x0a32,0x02a7, - 0x0a31,0x031c, 0x0a35,0x032e, 0x0a39,0x0006, 0x0a3a,0x0105, 0x0a3a,0x024f, - 0x0a3c,0x0299, 0x0a42,0x01ed, 0x0a46,0x0299, 0x0a48,0x01ed, 0x0a4c,0x0059, - 0x0a52,0x000b, 0x0a52,0x0387, 0x0a56,0x000b, 0x0a5e,0x0009, 0x0a60,0x003d, - 0x0a66,0x0105, 0x0a6a,0x0195, 0x0a6c,0x000b, 0x0a76,0x0053, 0x0a78,0x0009, - 0x0a7a,0x008f, 0x0a82,0x0299, 0x0a86,0x01ed, 0x0a8a,0x0027, 0x0a8e,0x004b, - 0x0a92,0x003d, 0x0a95,0x0322, 0x0a99,0x0038, 0x0a99,0x0090, 0x0a9c,0x0061, - 0x0a9c,0x00c7, 0x0a9c,0x012d, 0x0a9c,0x016f, 0x0a9c,0x017d, 0x0a9c,0x02c9, - 0x0a9c,0x0383, 0x0aa1,0x0010, 0x0aa4,0x00b3, 0x0aa8,0x002f, 0x0aac,0x0027, - 0x0ab0,0x004b, 0x0ab4,0x0043, 0x0ab9,0x0090, 0x0abd,0x0010, 0x0ac4,0x0019, - 0x0acc,0x00f5, 0x0acc,0x022b, 0x0acc,0x037b, 0x0ad2,0x008f, 0x0ad2,0x01f1, - 0x0ad6,0x0324, 0x0ad9,0x0330, 0x0ade,0x008f, 0x0ade,0x01f1, 0x0ae0,0x017b, - 0x0ae4,0x008f, 0x0ae9,0x004e, 0x0aee,0x0027, 0x0af2,0x028a, 0x0af2,0x02a7, - 0x0af1,0x031c, 0x0af6,0x0027, 0x0af9,0x031c, 0x0afe,0x00e9, 0x0afe,0x02bb, - 0x0b02,0x000b, 0x0b06,0x00f5, 0x0b06,0x022b, 0x0b06,0x037b, 0x0b0a,0x003d, - 0x0000,0x0000 -}; - - diff --git a/src/opt/sim/module.make b/src/opt/sim/module.make deleted file mode 100644 index 54058402..00000000 --- a/src/opt/sim/module.make +++ /dev/null @@ -1,10 +0,0 @@ -SRC += src/opt/sim/simMan.c \ - src/opt/sim/simSat.c \ - src/opt/sim/simSeq.c \ - src/opt/sim/simSupp.c \ - src/opt/sim/simSwitch.c \ - src/opt/sim/simSym.c \ - src/opt/sim/simSymSat.c \ - src/opt/sim/simSymSim.c \ - src/opt/sim/simSymStr.c \ - src/opt/sim/simUtils.c diff --git a/src/opt/sim/sim.h b/src/opt/sim/sim.h deleted file mode 100644 index 7fcf5ae6..00000000 --- a/src/opt/sim/sim.h +++ /dev/null @@ -1,233 +0,0 @@ -/**CFile**************************************************************** - - FileName [sim.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Simulation package.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: sim.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __SIM_H__ -#define __SIM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - The ideas realized in this package are described in the paper: - "Detecting Symmetries in Boolean Functions using Circuit Representation, - Simulation, and Satisfiability". -*/ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Sym_Man_t_ Sym_Man_t; -struct Sym_Man_t_ -{ - // info about the network - Abc_Ntk_t * pNtk; // the network - Vec_Ptr_t * vNodes; // internal nodes in topological order - int nInputs; - int nOutputs; - // internal simulation information - int nSimWords; // the number of bits in simulation info - Vec_Ptr_t * vSim; // simulation info - // support information - Vec_Ptr_t * vSuppFun; // bit representation - Vec_Vec_t * vSupports; // integer representation - // symmetry info for each output - Vec_Ptr_t * vMatrSymms; // symmetric pairs - Vec_Ptr_t * vMatrNonSymms; // non-symmetric pairs - Vec_Int_t * vPairsTotal; // total pairs - Vec_Int_t * vPairsSym; // symmetric pairs - Vec_Int_t * vPairsNonSym; // non-symmetric pairs - // temporary simulation info - unsigned * uPatRand; - unsigned * uPatCol; - unsigned * uPatRow; - // temporary - Vec_Int_t * vVarsU; - Vec_Int_t * vVarsV; - int iOutput; - int iVar1; - int iVar2; - int iVar1Old; - int iVar2Old; - // internal data structures - int nSatRuns; - int nSatRunsSat; - int nSatRunsUnsat; - // pairs - int nPairsSymm; - int nPairsSymmStr; - int nPairsNonSymm; - int nPairsRem; - int nPairsTotal; - // runtime statistics - int timeStruct; - int timeCount; - int timeMatr; - int timeSim; - int timeFraig; - int timeSat; - int timeTotal; -}; - -typedef struct Sim_Man_t_ Sim_Man_t; -struct Sim_Man_t_ -{ - // info about the network - Abc_Ntk_t * pNtk; - int nInputs; - int nOutputs; - int fLightweight; - // internal simulation information - int nSimBits; // the number of bits in simulation info - int nSimWords; // the number of words in simulation info - Vec_Ptr_t * vSim0; // simulation info 1 - Vec_Ptr_t * vSim1; // simulation info 2 - // support information - int nSuppBits; // the number of bits in support info - int nSuppWords; // the number of words in support info - Vec_Ptr_t * vSuppStr; // structural supports - Vec_Ptr_t * vSuppFun; // functional supports - // simulation targets - Vec_Vec_t * vSuppTargs; // support targets - int iInput; // the input current processed - // internal data structures - Extra_MmFixed_t * pMmPat; - Vec_Ptr_t * vFifo; - Vec_Int_t * vDiffs; - int nSatRuns; - int nSatRunsSat; - int nSatRunsUnsat; - // runtime statistics - int timeSim; - int timeTrav; - int timeFraig; - int timeSat; - int timeTotal; -}; - -typedef struct Sim_Pat_t_ Sim_Pat_t; -struct Sim_Pat_t_ -{ - int Input; // the input which it has detected - int Output; // the output for which it was collected - unsigned * pData; // the simulation data -}; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#define SIM_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0)) -#define SIM_LAST_BITS(n) ((((n)&31) > 0)? (n)&31 : 32) - -#define SIM_MASK_FULL (0xFFFFFFFF) -#define SIM_MASK_BEG(n) (SIM_MASK_FULL >> (32-n)) -#define SIM_MASK_END(n) (SIM_MASK_FULL << (n)) -#define SIM_SET_0_FROM(m,n) ((m) & ~SIM_MASK_BEG(n)) -#define SIM_SET_1_FROM(m,n) ((m) | SIM_MASK_END(n)) - -// generating random unsigned (#define RAND_MAX 0x7fff) -#define SIM_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) - -// macros to get hold of bits in a bit string -#define Sim_SetBit(p,i) ((p)[(i)>>5] |= (1<<((i) & 31))) -#define Sim_XorBit(p,i) ((p)[(i)>>5] ^= (1<<((i) & 31))) -#define Sim_HasBit(p,i) (((p)[(i)>>5] & (1<<((i) & 31))) > 0) - -// macros to get hold of the support info -#define Sim_SuppStrSetVar(vSupps,pNode,v) Sim_SetBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) -#define Sim_SuppStrHasVar(vSupps,pNode,v) Sim_HasBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) -#define Sim_SuppFunSetVar(vSupps,Output,v) Sim_SetBit((unsigned*)(vSupps)->pArray[Output],(v)) -#define Sim_SuppFunHasVar(vSupps,Output,v) Sim_HasBit((unsigned*)(vSupps)->pArray[Output],(v)) -#define Sim_SimInfoSetVar(vSupps,pNode,v) Sim_SetBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) -#define Sim_SimInfoHasVar(vSupps,pNode,v) Sim_HasBit((unsigned*)(vSupps)->pArray[(pNode)->Id],(v)) -#define Sim_SimInfoGet(vInfo,pNode) ((unsigned *)((vInfo)->pArray[(pNode)->Id])) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== simMan.c ==========================================================*/ -extern Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose ); -extern void Sym_ManStop( Sym_Man_t * p ); -extern void Sym_ManPrintStats( Sym_Man_t * p ); -extern Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight ); -extern void Sim_ManStop( Sim_Man_t * p ); -extern void Sim_ManPrintStats( Sim_Man_t * p ); -extern Sim_Pat_t * Sim_ManPatAlloc( Sim_Man_t * p ); -extern void Sim_ManPatFree( Sim_Man_t * p, Sim_Pat_t * pPat ); -/*=== simSeq.c ==========================================================*/ -extern Vec_Ptr_t * Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords ); -extern Vec_Ptr_t * Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel ); -/*=== simSupp.c ==========================================================*/ -extern Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk ); -extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ); -/*=== simSym.c ==========================================================*/ -extern int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose ); -/*=== simSymSat.c ==========================================================*/ -extern int Sim_SymmsGetPatternUsingSat( Sym_Man_t * p, unsigned * pPattern ); -/*=== simSymStr.c ==========================================================*/ -extern void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * vSuppFun ); -/*=== simSymSim.c ==========================================================*/ -extern void Sim_SymmsSimulate( Sym_Man_t * p, unsigned * pPatRand, Vec_Ptr_t * vMatrsNonSym ); -/*=== simUtil.c ==========================================================*/ -extern Vec_Ptr_t * Sim_UtilInfoAlloc( int nSize, int nWords, bool fClean ); -extern void Sim_UtilInfoFree( Vec_Ptr_t * p ); -extern void Sim_UtilInfoAdd( unsigned * pInfo1, unsigned * pInfo2, int nWords ); -extern void Sim_UtilInfoDetectDiffs( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ); -extern void Sim_UtilInfoDetectNews( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ); -extern void Sim_UtilInfoFlip( Sim_Man_t * p, Abc_Obj_t * pNode ); -extern bool Sim_UtilInfoCompare( Sim_Man_t * p, Abc_Obj_t * pNode ); -extern void Sim_UtilSimulate( Sim_Man_t * p, bool fFirst ); -extern void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fType1, bool fType2 ); -extern void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset ); -extern void Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift ); -extern int Sim_UtilCountSuppSizes( Sim_Man_t * p, int fStruct ); -extern int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords ); -extern Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords ); -extern void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords ); -extern void Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords ); -extern void Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 ); -extern int Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords ); -extern int Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords ); -extern int Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords ); -extern int Sim_UtilCountAllPairs( Vec_Ptr_t * vSuppFun, int nSimWords, Vec_Int_t * vCounters ); -extern void Sim_UtilCountPairsAll( Sym_Man_t * p ); -extern int Sim_UtilMatrsAreDisjoint( Sym_Man_t * p ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/opt/sim/simMan.c b/src/opt/sim/simMan.c deleted file mode 100644 index 3b50ad84..00000000 --- a/src/opt/sim/simMan.c +++ /dev/null @@ -1,288 +0,0 @@ -/**CFile**************************************************************** - - FileName [simMan.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Simulation manager.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: simMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "sim.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Sym_Man_t * Sym_ManStart( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Sym_Man_t * p; - int i, v; - // start the manager - p = ALLOC( Sym_Man_t, 1 ); - memset( p, 0, sizeof(Sym_Man_t) ); - p->pNtk = pNtk; - p->vNodes = Abc_NtkDfs( pNtk, 0 ); - p->nInputs = Abc_NtkCiNum(p->pNtk); - p->nOutputs = Abc_NtkCoNum(p->pNtk); - // internal simulation information - p->nSimWords = SIM_NUM_WORDS(p->nInputs); - p->vSim = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 ); - // symmetry info for each output - p->vMatrSymms = Vec_PtrStart( p->nOutputs ); - p->vMatrNonSymms = Vec_PtrStart( p->nOutputs ); - p->vPairsTotal = Vec_IntStart( p->nOutputs ); - p->vPairsSym = Vec_IntStart( p->nOutputs ); - p->vPairsNonSym = Vec_IntStart( p->nOutputs ); - for ( i = 0; i < p->nOutputs; i++ ) - { - p->vMatrSymms->pArray[i] = Extra_BitMatrixStart( p->nInputs ); - p->vMatrNonSymms->pArray[i] = Extra_BitMatrixStart( p->nInputs ); - } - // temporary patterns - p->uPatRand = ALLOC( unsigned, p->nSimWords ); - p->uPatCol = ALLOC( unsigned, p->nSimWords ); - p->uPatRow = ALLOC( unsigned, p->nSimWords ); - p->vVarsU = Vec_IntStart( 100 ); - p->vVarsV = Vec_IntStart( 100 ); - // compute supports - p->vSuppFun = Sim_ComputeFunSupp( pNtk, fVerbose ); - p->vSupports = Vec_VecStart( p->nOutputs ); - for ( i = 0; i < p->nOutputs; i++ ) - for ( v = 0; v < p->nInputs; v++ ) - if ( Sim_SuppFunHasVar( p->vSuppFun, i, v ) ) - Vec_VecPush( p->vSupports, i, (void *)v ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sym_ManStop( Sym_Man_t * p ) -{ - int i; - Sym_ManPrintStats( p ); - if ( p->vSuppFun ) Sim_UtilInfoFree( p->vSuppFun ); - if ( p->vSim ) Sim_UtilInfoFree( p->vSim ); - if ( p->vNodes ) Vec_PtrFree( p->vNodes ); - if ( p->vSupports ) Vec_VecFree( p->vSupports ); - for ( i = 0; i < p->nOutputs; i++ ) - { - Extra_BitMatrixStop( p->vMatrSymms->pArray[i] ); - Extra_BitMatrixStop( p->vMatrNonSymms->pArray[i] ); - } - Vec_IntFree( p->vVarsU ); - Vec_IntFree( p->vVarsV ); - Vec_PtrFree( p->vMatrSymms ); - Vec_PtrFree( p->vMatrNonSymms ); - Vec_IntFree( p->vPairsTotal ); - Vec_IntFree( p->vPairsSym ); - Vec_IntFree( p->vPairsNonSym ); - FREE( p->uPatRand ); - FREE( p->uPatCol ); - FREE( p->uPatRow ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Prints the manager statisticis.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sym_ManPrintStats( Sym_Man_t * p ) -{ -// printf( "Inputs = %5d. Outputs = %5d. Sim words = %5d.\n", -// Abc_NtkCiNum(p->pNtk), Abc_NtkCoNum(p->pNtk), p->nSimWords ); - printf( "Total symm = %8d.\n", p->nPairsSymm ); - printf( "Structural symm = %8d.\n", p->nPairsSymmStr ); - printf( "Total non-sym = %8d.\n", p->nPairsNonSymm ); - printf( "Total var pairs = %8d.\n", p->nPairsTotal ); - printf( "Sat runs SAT = %8d.\n", p->nSatRunsSat ); - printf( "Sat runs UNSAT = %8d.\n", p->nSatRunsUnsat ); - PRT( "Structural ", p->timeStruct ); - PRT( "Simulation ", p->timeSim ); - PRT( "Matrix ", p->timeMatr ); - PRT( "Counting ", p->timeCount ); - PRT( "Fraiging ", p->timeFraig ); - PRT( "SAT ", p->timeSat ); - PRT( "TOTAL ", p->timeTotal ); -} - - -/**Function************************************************************* - - Synopsis [Starts the simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Sim_Man_t * Sim_ManStart( Abc_Ntk_t * pNtk, int fLightweight ) -{ - Sim_Man_t * p; - // start the manager - p = ALLOC( Sim_Man_t, 1 ); - memset( p, 0, sizeof(Sim_Man_t) ); - p->pNtk = pNtk; - p->nInputs = Abc_NtkCiNum(p->pNtk); - p->nOutputs = Abc_NtkCoNum(p->pNtk); - // internal simulation information - p->nSimBits = 2048; - p->nSimWords = SIM_NUM_WORDS(p->nSimBits); - p->vSim0 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 ); - p->fLightweight = fLightweight; - if (!p->fLightweight) { - p->vSim1 = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), p->nSimWords, 0 ); - // support information - p->nSuppBits = Abc_NtkCiNum(pNtk); - p->nSuppWords = SIM_NUM_WORDS(p->nSuppBits); - p->vSuppStr = Sim_ComputeStrSupp( pNtk ); - p->vSuppFun = Sim_UtilInfoAlloc( Abc_NtkCoNum(p->pNtk), p->nSuppWords, 1 ); - // other data - p->pMmPat = Extra_MmFixedStart( sizeof(Sim_Pat_t) + p->nSuppWords * sizeof(unsigned) ); - p->vFifo = Vec_PtrAlloc( 100 ); - p->vDiffs = Vec_IntAlloc( 100 ); - // allocate support targets (array of unresolved outputs for each input) - p->vSuppTargs = Vec_VecStart( p->nInputs ); - } - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the simulation manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_ManStop( Sim_Man_t * p ) -{ - Sim_ManPrintStats( p ); - if ( p->vSim0 ) Sim_UtilInfoFree( p->vSim0 ); - if ( p->vSim1 ) Sim_UtilInfoFree( p->vSim1 ); - if ( p->vSuppStr ) Sim_UtilInfoFree( p->vSuppStr ); -// if ( p->vSuppFun ) Sim_UtilInfoFree( p->vSuppFun ); - if ( p->vSuppTargs ) Vec_VecFree( p->vSuppTargs ); - if ( p->pMmPat ) Extra_MmFixedStop( p->pMmPat ); - if ( p->vFifo ) Vec_PtrFree( p->vFifo ); - if ( p->vDiffs ) Vec_IntFree( p->vDiffs ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Prints the manager statisticis.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_ManPrintStats( Sim_Man_t * p ) -{ -// printf( "Inputs = %5d. Outputs = %5d. Sim words = %5d.\n", -// Abc_NtkCiNum(p->pNtk), Abc_NtkCoNum(p->pNtk), p->nSimWords ); - printf( "Total func supps = %8d.\n", Sim_UtilCountSuppSizes(p, 0) ); - printf( "Total struct supps = %8d.\n", Sim_UtilCountSuppSizes(p, 1) ); - printf( "Sat runs SAT = %8d.\n", p->nSatRunsSat ); - printf( "Sat runs UNSAT = %8d.\n", p->nSatRunsUnsat ); - PRT( "Simulation ", p->timeSim ); - PRT( "Traversal ", p->timeTrav ); - PRT( "Fraiging ", p->timeFraig ); - PRT( "SAT ", p->timeSat ); - PRT( "TOTAL ", p->timeTotal ); -} - - - -/**Function************************************************************* - - Synopsis [Returns one simulation pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Sim_Pat_t * Sim_ManPatAlloc( Sim_Man_t * p ) -{ - Sim_Pat_t * pPat; - pPat = (Sim_Pat_t *)Extra_MmFixedEntryFetch( p->pMmPat ); - pPat->Output = -1; - pPat->pData = (unsigned *)((char *)pPat + sizeof(Sim_Pat_t)); - memset( pPat->pData, 0, p->nSuppWords * sizeof(unsigned) ); - return pPat; -} - -/**Function************************************************************* - - Synopsis [Returns one simulation pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_ManPatFree( Sim_Man_t * p, Sim_Pat_t * pPat ) -{ - Extra_MmFixedEntryRecycle( p->pMmPat, (char *)pPat ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/sim/simSat.c b/src/opt/sim/simSat.c deleted file mode 100644 index d514f7f2..00000000 --- a/src/opt/sim/simSat.c +++ /dev/null @@ -1,48 +0,0 @@ -/**CFile**************************************************************** - - FileName [simSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Simulation to determine functional support.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: simSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "sim.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/sim/simSeq.c b/src/opt/sim/simSeq.c deleted file mode 100644 index 49fb939f..00000000 --- a/src/opt/sim/simSeq.c +++ /dev/null @@ -1,171 +0,0 @@ -/**CFile**************************************************************** - - FileName [simSeq.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Simulation for sequential circuits.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: simUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "sim.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Simulates sequential circuit.] - - Description [Takes sequential circuit (pNtk). Simulates the given number - (nFrames) of the circuit with the given number of machine words (nWords) - of random simulation data, starting from the initial state. If the initial - state of some latches is a don't-care, uses random input for that latch.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Sim_SimulateSeqRandom( Abc_Ntk_t * pNtk, int nFrames, int nWords ) -{ - Vec_Ptr_t * vInfo; - Abc_Obj_t * pNode; - int i; - assert( Abc_NtkIsStrash(pNtk) ); - vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nWords * nFrames, 0 ); - // set the constant data - pNode = Abc_AigConst1(pNtk); - Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames, 1 ); - // set the random PI data - Abc_NtkForEachPi( pNtk, pNode, i ) - Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords * nFrames ); - // set the initial state data - Abc_NtkForEachLatch( pNtk, pNode, i ) - if ( Abc_LatchIsInit0(pNode) ) - Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 0 ); - else if ( Abc_LatchIsInit1(pNode) ) - Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nWords, 1 ); - else - Sim_UtilSetRandom( Sim_SimInfoGet(vInfo,pNode), nWords ); - // simulate the nodes for the given number of timeframes - for ( i = 0; i < nFrames; i++ ) - Sim_SimulateSeqFrame( vInfo, pNtk, i, nWords, (int)(i < nFrames-1) ); - return vInfo; -} - -/**Function************************************************************* - - Synopsis [Simulates sequential circuit.] - - Description [Takes sequential circuit (pNtk). Simulates the given number - (nFrames) of the circuit with the given model. The model is assumed to - contain values of PIs for each frame. The latches are initialized to - the initial state. One word of data is simulated.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Sim_SimulateSeqModel( Abc_Ntk_t * pNtk, int nFrames, int * pModel ) -{ - Vec_Ptr_t * vInfo; - Abc_Obj_t * pNode; - unsigned * pUnsigned; - int i, k; - vInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nFrames, 0 ); - // set the constant data - pNode = Abc_AigConst1(pNtk); - Sim_UtilSetConst( Sim_SimInfoGet(vInfo,pNode), nFrames, 1 ); - // set the random PI data - Abc_NtkForEachPi( pNtk, pNode, i ) - { - pUnsigned = Sim_SimInfoGet(vInfo,pNode); - for ( k = 0; k < nFrames; k++ ) - pUnsigned[k] = pModel[k * Abc_NtkPiNum(pNtk) + i] ? ~((unsigned)0) : 0; - } - // set the initial state data - Abc_NtkForEachLatch( pNtk, pNode, i ) - { - pUnsigned = Sim_SimInfoGet(vInfo,pNode); - if ( Abc_LatchIsInit0(pNode) ) - pUnsigned[0] = 0; - else if ( Abc_LatchIsInit1(pNode) ) - pUnsigned[0] = ~((unsigned)0); - else - pUnsigned[0] = SIM_RANDOM_UNSIGNED; - } - // simulate the nodes for the given number of timeframes - for ( i = 0; i < nFrames; i++ ) - Sim_SimulateSeqFrame( vInfo, pNtk, i, 1, (int)(i < nFrames-1) ); -/* - // print the simulated values - for ( i = 0; i < nFrames; i++ ) - { - printf( "Frame %d : ", i+1 ); - Abc_NtkForEachPi( pNtk, pNode, k ) - printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 ); - printf( " " ); - Abc_NtkForEachLatch( pNtk, pNode, k ) - printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 ); - printf( " " ); - Abc_NtkForEachPo( pNtk, pNode, k ) - printf( "%d", Sim_SimInfoGet(vInfo,pNode)[i] > 0 ); - printf( "\n" ); - } - printf( "\n" ); -*/ - return vInfo; -} - -/**Function************************************************************* - - Synopsis [Simulates one frame of sequential circuit.] - - Description [Assumes that the latches and POs are already initialized. - In the end transfers the data to the latches of the next frame.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SimulateSeqFrame( Vec_Ptr_t * vInfo, Abc_Ntk_t * pNtk, int iFrames, int nWords, int fTransfer ) -{ - Abc_Obj_t * pNode; - int i; - Abc_NtkForEachNode( pNtk, pNode, i ) - Sim_UtilSimulateNodeOne( pNode, vInfo, nWords, iFrames * nWords ); - Abc_NtkForEachPo( pNtk, pNode, i ) - Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 0 ); - if ( !fTransfer ) - return; - Abc_NtkForEachLatch( pNtk, pNode, i ) - Sim_UtilTransferNodeOne( pNode, vInfo, nWords, iFrames * nWords, 1 ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/sim/simSupp.c b/src/opt/sim/simSupp.c deleted file mode 100644 index f7048f4a..00000000 --- a/src/opt/sim/simSupp.c +++ /dev/null @@ -1,597 +0,0 @@ -/**CFile**************************************************************** - - FileName [simSupp.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Simulation to determine functional support.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: simSupp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "fraig.h" -#include "sim.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Sim_ComputeSuppRound( Sim_Man_t * p, bool fUseTargets ); -static int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, bool fUseTargets ); -static void Sim_ComputeSuppSetTargets( Sim_Man_t * p ); - -static void Sim_UtilAssignRandom( Sim_Man_t * p ); -static void Sim_UtilAssignFromFifo( Sim_Man_t * p ); -static void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int nCounters ); -static int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes structural supports.] - - Description [Supports are returned as an array of bit strings, one - for each CO.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk ) -{ - Vec_Ptr_t * vSuppStr; - Abc_Obj_t * pNode; - unsigned * pSimmNode, * pSimmNode1, * pSimmNode2; - int nSuppWords, i, k; - // allocate room for structural supports - nSuppWords = SIM_NUM_WORDS( Abc_NtkCiNum(pNtk) ); - vSuppStr = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nSuppWords, 1 ); - // assign the structural support to the PIs - Abc_NtkForEachCi( pNtk, pNode, i ) - Sim_SuppStrSetVar( vSuppStr, pNode, i ); - // derive the structural supports of the internal nodes - Abc_NtkForEachNode( pNtk, pNode, i ) - { -// if ( Abc_NodeIsConst(pNode) ) -// continue; - pSimmNode = vSuppStr->pArray[ pNode->Id ]; - pSimmNode1 = vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ]; - pSimmNode2 = vSuppStr->pArray[ Abc_ObjFaninId1(pNode) ]; - for ( k = 0; k < nSuppWords; k++ ) - pSimmNode[k] = pSimmNode1[k] | pSimmNode2[k]; - } - // set the structural supports of the PO nodes - Abc_NtkForEachCo( pNtk, pNode, i ) - { - pSimmNode = vSuppStr->pArray[ pNode->Id ]; - pSimmNode1 = vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ]; - for ( k = 0; k < nSuppWords; k++ ) - pSimmNode[k] = pSimmNode1[k]; - } - return vSuppStr; -} - -/**Function************************************************************* - - Synopsis [Compute functional supports.] - - Description [Supports are returned as an array of bit strings, one - for each CO.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Sim_Man_t * p; - Vec_Ptr_t * vResult; - int nSolved, i, clk = clock(); - - srand( 0xABC ); - - // start the simulation manager - p = Sim_ManStart( pNtk, 0 ); - - // compute functional support using one round of random simulation - Sim_UtilAssignRandom( p ); - Sim_ComputeSuppRound( p, 0 ); - - // set the support targets - Sim_ComputeSuppSetTargets( p ); -if ( fVerbose ) - printf( "Number of support targets after simulation = %5d.\n", Vec_VecSizeSize(p->vSuppTargs) ); - if ( Vec_VecSizeSize(p->vSuppTargs) == 0 ) - goto exit; - - for ( i = 0; i < 1; i++ ) - { - // compute patterns using one round of random simulation - Sim_UtilAssignRandom( p ); - nSolved = Sim_ComputeSuppRound( p, 1 ); - if ( Vec_VecSizeSize(p->vSuppTargs) == 0 ) - goto exit; - -if ( fVerbose ) - printf( "Targets = %5d. Solved = %5d. Fifo = %5d.\n", - Vec_VecSizeSize(p->vSuppTargs), nSolved, Vec_PtrSize(p->vFifo) ); - } - - // try to solve the support targets - while ( Vec_VecSizeSize(p->vSuppTargs) > 0 ) - { - // solve targets until the first disproved one (which gives counter-example) - Sim_SolveTargetsUsingSat( p, p->nSimWords/p->nSuppWords ); - // compute additional functional support - Sim_UtilAssignFromFifo( p ); - nSolved = Sim_ComputeSuppRound( p, 1 ); - -if ( fVerbose ) - printf( "Targets = %5d. Solved = %5d. Fifo = %5d. SAT runs = %3d.\n", - Vec_VecSizeSize(p->vSuppTargs), nSolved, Vec_PtrSize(p->vFifo), p->nSatRuns ); - } - -exit: -p->timeTotal = clock() - clk; - vResult = p->vSuppFun; - // p->vSuppFun = NULL; - Sim_ManStop( p ); - return vResult; -} - -/**Function************************************************************* - - Synopsis [Computes functional support using one round of simulation.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_ComputeSuppRound( Sim_Man_t * p, bool fUseTargets ) -{ - Vec_Int_t * vTargets; - int i, Counter = 0; - int clk; - // perform one round of random simulation -clk = clock(); - Sim_UtilSimulate( p, 0 ); -p->timeSim += clock() - clk; - // iterate through the CIs and detect COs that depend on them - for ( i = p->iInput; i < p->nInputs; i++ ) - { - vTargets = p->vSuppTargs->pArray[i]; - if ( fUseTargets && vTargets->nSize == 0 ) - continue; - Counter += Sim_ComputeSuppRoundNode( p, i, fUseTargets ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Computes functional support for one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, bool fUseTargets ) -{ - int fVerbose = 0; - Sim_Pat_t * pPat; - Vec_Int_t * vTargets; - Vec_Vec_t * vNodesByLevel; - Abc_Obj_t * pNodeCi, * pNode; - int i, k, v, Output, LuckyPat, fType0, fType1; - int Counter = 0; - int fFirst = 1; - int clk; - // collect nodes by level in the TFO of the CI - // this proceduredoes not collect the CIs and COs - // but it increments TravId of the collected nodes and CIs/COs -clk = clock(); - pNodeCi = Abc_NtkCi( p->pNtk, iNumCi ); - vNodesByLevel = Abc_DfsLevelized( pNodeCi, 0 ); -p->timeTrav += clock() - clk; - // complement the simulation info of the selected CI - Sim_UtilInfoFlip( p, pNodeCi ); - // simulate the levelized structure of nodes - Vec_VecForEachEntry( vNodesByLevel, pNode, i, k ) - { - fType0 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin0(pNode) ); - fType1 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin1(pNode) ); -clk = clock(); - Sim_UtilSimulateNode( p, pNode, 1, fType0, fType1 ); -p->timeSim += clock() - clk; - } - // set the simulation info of the affected COs - if ( fUseTargets ) - { - vTargets = p->vSuppTargs->pArray[iNumCi]; - for ( i = vTargets->nSize - 1; i >= 0; i-- ) - { - // get the target output - Output = vTargets->pArray[i]; - // get the target node - pNode = Abc_ObjFanin0( Abc_NtkCo(p->pNtk, Output) ); - // the output should be in the cone - assert( Abc_NodeIsTravIdCurrent(pNode) ); - - // skip if the simulation info is equal - if ( Sim_UtilInfoCompare( p, pNode ) ) - continue; - - // otherwise, we solved a new target - Vec_IntRemove( vTargets, Output ); -if ( fVerbose ) - printf( "(%d,%d) ", iNumCi, Output ); - Counter++; - // make sure this variable is not yet detected - assert( !Sim_SuppFunHasVar(p->vSuppFun, Output, iNumCi) ); - // set this variable - Sim_SuppFunSetVar( p->vSuppFun, Output, iNumCi ); - - // detect the differences in the simulation info - Sim_UtilInfoDetectDiffs( p->vSim0->pArray[pNode->Id], p->vSim1->pArray[pNode->Id], p->nSimWords, p->vDiffs ); - // create new patterns - if ( !fFirst && p->vFifo->nSize > 1000 ) - continue; - - Vec_IntForEachEntry( p->vDiffs, LuckyPat, k ) - { - // set the new pattern - pPat = Sim_ManPatAlloc( p ); - pPat->Input = iNumCi; - pPat->Output = Output; - Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) - if ( Sim_SimInfoHasVar( p->vSim0, pNodeCi, LuckyPat ) ) - Sim_SetBit( pPat->pData, v ); - Vec_PtrPush( p->vFifo, pPat ); - - fFirst = 0; - break; - } - } -if ( fVerbose && Counter ) -printf( "\n" ); - } - else - { - Abc_NtkForEachCo( p->pNtk, pNode, Output ) - { - if ( !Abc_NodeIsTravIdCurrent( pNode ) ) - continue; - if ( !Sim_UtilInfoCompare( p, Abc_ObjFanin0(pNode) ) ) - { - if ( !Sim_SuppFunHasVar(p->vSuppFun, Output, iNumCi) ) - { - Counter++; - Sim_SuppFunSetVar( p->vSuppFun, Output, iNumCi ); - } - } - } - } - Vec_VecFree( vNodesByLevel ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Sets the simulation targets.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_ComputeSuppSetTargets( Sim_Man_t * p ) -{ - Abc_Obj_t * pNode; - unsigned * pSuppStr, * pSuppFun; - int i, k, Num; - Abc_NtkForEachCo( p->pNtk, pNode, i ) - { - pSuppStr = p->vSuppStr->pArray[pNode->Id]; - pSuppFun = p->vSuppFun->pArray[i]; - // find vars in the structural support that are not in the functional support - Sim_UtilInfoDetectNews( pSuppFun, pSuppStr, p->nSuppWords, p->vDiffs ); - Vec_IntForEachEntry( p->vDiffs, Num, k ) - Vec_VecPush( p->vSuppTargs, Num, (void *)i ); - } -} - -/**Function************************************************************* - - Synopsis [Assigns random simulation info to the PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilAssignRandom( Sim_Man_t * p ) -{ - Abc_Obj_t * pNode; - unsigned * pSimInfo; - int i, k; - // assign the random/systematic simulation info to the PIs - Abc_NtkForEachCi( p->pNtk, pNode, i ) - { - pSimInfo = p->vSim0->pArray[pNode->Id]; - for ( k = 0; k < p->nSimWords; k++ ) - pSimInfo[k] = SIM_RANDOM_UNSIGNED; - } -} - -/**Function************************************************************* - - Synopsis [Sets the new patterns from fifo.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilAssignFromFifo( Sim_Man_t * p ) -{ - int fUseOneWord = 0; - Abc_Obj_t * pNode; - Sim_Pat_t * pPat; - unsigned * pSimInfo; - int nWordsNew, iWord, iWordLim, i, w; - int iBeg, iEnd; - int Counter = 0; - // go through the patterns and fill in the dist-1 minterms for each - for ( iWord = 0; p->vFifo->nSize > 0; iWord = iWordLim ) - { - ++Counter; - // get the pattern - pPat = Vec_PtrPop( p->vFifo ); - if ( fUseOneWord ) - { - // get the first word of the next series - iWordLim = iWord + 1; - // set the pattern for all PIs from iBit to iWord + p->nInputs - iBeg = p->iInput; - iEnd = ABC_MIN( iBeg + 32, p->nInputs ); -// for ( i = iBeg; i < iEnd; i++ ) - Abc_NtkForEachCi( p->pNtk, pNode, i ) - { - pNode = Abc_NtkCi(p->pNtk,i); - pSimInfo = p->vSim0->pArray[pNode->Id]; - if ( Sim_HasBit(pPat->pData, i) ) - pSimInfo[iWord] = SIM_MASK_FULL; - else - pSimInfo[iWord] = 0; - // flip one bit - if ( i >= iBeg && i < iEnd ) - Sim_XorBit( pSimInfo + iWord, i-iBeg ); - } - } - else - { - // get the number of words for the remaining inputs - nWordsNew = p->nSuppWords; -// nWordsNew = SIM_NUM_WORDS( p->nInputs - p->iInput ); - // get the first word of the next series - iWordLim = (iWord + nWordsNew < p->nSimWords)? iWord + nWordsNew : p->nSimWords; - // set the pattern for all CIs from iWord to iWord + nWordsNew - Abc_NtkForEachCi( p->pNtk, pNode, i ) - { - pSimInfo = p->vSim0->pArray[pNode->Id]; - if ( Sim_HasBit(pPat->pData, i) ) - { - for ( w = iWord; w < iWordLim; w++ ) - pSimInfo[w] = SIM_MASK_FULL; - } - else - { - for ( w = iWord; w < iWordLim; w++ ) - pSimInfo[w] = 0; - } - Sim_XorBit( pSimInfo + iWord, i ); - // flip one bit -// if ( i >= p->iInput ) -// Sim_XorBit( pSimInfo + iWord, i-p->iInput ); - } - } - Sim_ManPatFree( p, pPat ); - // stop if we ran out of room for patterns - if ( iWordLim == p->nSimWords ) - break; -// if ( Counter == 1 ) -// break; - } -} - -/**Function************************************************************* - - Synopsis [Get the given number of counter-examples using SAT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int Limit ) -{ - Fraig_Params_t Params; - Fraig_Man_t * pMan; - Abc_Obj_t * pNodeCi; - Abc_Ntk_t * pMiter; - Sim_Pat_t * pPat; - void * pEntry; - int * pModel; - int RetValue, Output, Input, k, v; - int Counter = 0; - int clk; - - p->nSatRuns = 0; - // put targets into one array - Vec_VecForEachEntryReverse( p->vSuppTargs, pEntry, Input, k ) - { - p->nSatRuns++; - Output = (int)pEntry; - - // set up the miter for the two cofactors of this output w.r.t. this input - pMiter = Abc_NtkMiterForCofactors( p->pNtk, Output, Input, -1 ); - - // transform the miter into a fraig - Fraig_ParamsSetDefault( &Params ); - Params.nSeconds = ABC_INFINITY; - Params.fInternal = 1; -clk = clock(); - pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 ); -p->timeFraig += clock() - clk; -clk = clock(); - Fraig_ManProveMiter( pMan ); -p->timeSat += clock() - clk; - - // analyze the result - RetValue = Fraig_ManCheckMiter( pMan ); - assert( RetValue >= 0 ); - if ( RetValue == 1 ) // unsat - { - p->nSatRunsUnsat++; - pModel = NULL; - Vec_PtrRemove( p->vSuppTargs->pArray[Input], pEntry ); - } - else // sat - { - p->nSatRunsSat++; - pModel = Fraig_ManReadModel( pMan ); - assert( pModel != NULL ); - assert( Sim_SolveSuppModelVerify( p->pNtk, pModel, Input, Output ) ); - -//printf( "Solved by SAT (%d,%d).\n", Input, Output ); - // set the new pattern - pPat = Sim_ManPatAlloc( p ); - pPat->Input = Input; - pPat->Output = Output; - Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) - if ( pModel[v] ) - Sim_SetBit( pPat->pData, v ); - Vec_PtrPush( p->vFifo, pPat ); -/* - // set the new pattern - pPat = Sim_ManPatAlloc( p ); - pPat->Input = Input; - pPat->Output = Output; - Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) - if ( pModel[v] ) - Sim_SetBit( pPat->pData, v ); - Sim_XorBit( pPat->pData, Input ); // add this bit in the opposite polarity - Vec_PtrPush( p->vFifo, pPat ); -*/ - Counter++; - } - // delete the fraig manager - Fraig_ManFree( pMan ); - // delete the miter - Abc_NtkDelete( pMiter ); - - // makr the input, which we are processing - p->iInput = Input; - - // stop when we found enough patterns -// if ( Counter == Limit ) - if ( Counter == 1 ) - return; - } -} - - -/**Function************************************************************* - - Synopsis [Saves the counter example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_NtkSimTwoPats_rec( Abc_Obj_t * pNode ) -{ - int Value0, Value1; - if ( Abc_NodeIsTravIdCurrent( pNode ) ) - return (int)pNode->pCopy; - Abc_NodeSetTravIdCurrent( pNode ); - Value0 = Sim_NtkSimTwoPats_rec( Abc_ObjFanin0(pNode) ); - Value1 = Sim_NtkSimTwoPats_rec( Abc_ObjFanin1(pNode) ); - if ( Abc_ObjFaninC0(pNode) ) - Value0 = ~Value0; - if ( Abc_ObjFaninC1(pNode) ) - Value1 = ~Value1; - pNode->pCopy = (Abc_Obj_t *)(Value0 & Value1); - return Value0 & Value1; -} - -/**Function************************************************************* - - Synopsis [Verifies that pModel proves the presence of Input in the support of Output.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output ) -{ - Abc_Obj_t * pNode; - int RetValue, i; - // set the PI values - Abc_NtkIncrementTravId( pNtk ); - Abc_NtkForEachCi( pNtk, pNode, i ) - { - Abc_NodeSetTravIdCurrent( pNode ); - if ( pNode == Abc_NtkCi(pNtk,Input) ) - pNode->pCopy = (Abc_Obj_t *)1; - else if ( pModel[i] == 1 ) - pNode->pCopy = (Abc_Obj_t *)3; - else - pNode->pCopy = NULL; - } - // perform the traversal - RetValue = 3 & Sim_NtkSimTwoPats_rec( Abc_ObjFanin0( Abc_NtkCo(pNtk,Output) ) ); -// assert( RetValue == 1 || RetValue == 2 ); - return RetValue == 1 || RetValue == 2; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/sim/simSwitch.c b/src/opt/sim/simSwitch.c deleted file mode 100644 index 218d4d59..00000000 --- a/src/opt/sim/simSwitch.c +++ /dev/null @@ -1,107 +0,0 @@ -/**CFile**************************************************************** - - FileName [simSwitch.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Computes switching activity of nodes in the ABC network.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: simSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "sim.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Sim_NodeSimulate( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords ); -static float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes switching activity using simulation.] - - Description [Computes switching activity, which is understood as the - probability of switching under random simulation. Assigns the - random simulation information at the CI and propagates it through - the internal nodes of the AIG.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Sim_NtkComputeSwitching( Abc_Ntk_t * pNtk, int nPatterns ) -{ - Vec_Int_t * vSwitching; - float * pSwitching; - Vec_Ptr_t * vNodes; - Vec_Ptr_t * vSimInfo; - Abc_Obj_t * pNode; - unsigned * pSimInfo; - int nSimWords, i; - - // allocate space for simulation info of all nodes - nSimWords = SIM_NUM_WORDS(nPatterns); - vSimInfo = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nSimWords, 0 ); - // assign the random simulation to the CIs - vSwitching = Vec_IntStart( Abc_NtkObjNumMax(pNtk) ); - pSwitching = (float *)vSwitching->pArray; - Abc_NtkForEachCi( pNtk, pNode, i ) - { - pSimInfo = Vec_PtrEntry(vSimInfo, pNode->Id); - Sim_UtilSetRandom( pSimInfo, nSimWords ); - pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords ); - } - // simulate the internal nodes - vNodes = Abc_AigDfs( pNtk, 1, 0 ); - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - pSimInfo = Vec_PtrEntry(vSimInfo, pNode->Id); - Sim_UtilSimulateNodeOne( pNode, vSimInfo, nSimWords, 0 ); - pSwitching[pNode->Id] = Sim_ComputeSwitching( pSimInfo, nSimWords ); - } - Vec_PtrFree( vNodes ); - Sim_UtilInfoFree( vSimInfo ); - return vSwitching; -} - -/**Function************************************************************* - - Synopsis [Computes switching activity of one node.] - - Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Sim_ComputeSwitching( unsigned * pSimInfo, int nSimWords ) -{ - int nOnes, nTotal; - nTotal = 32 * nSimWords; - nOnes = Sim_UtilCountOnes( pSimInfo, nSimWords ); - return (float)2.0 * nOnes * (nTotal - nOnes) / nTotal / nTotal; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/sim/simSym.c b/src/opt/sim/simSym.c deleted file mode 100644 index 71de5b05..00000000 --- a/src/opt/sim/simSym.c +++ /dev/null @@ -1,142 +0,0 @@ -/**CFile**************************************************************** - - FileName [simSym.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Simulation to determine two-variable symmetries.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: simSym.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "sim.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes two variable symmetries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_ComputeTwoVarSymms( Abc_Ntk_t * pNtk, int fVerbose ) -{ - Sym_Man_t * p; - Vec_Ptr_t * vResult; - int Result; - int i, clk, clkTotal = clock(); - - srand( 0xABC ); - - // start the simulation manager - p = Sym_ManStart( pNtk, fVerbose ); - p->nPairsTotal = p->nPairsRem = Sim_UtilCountAllPairs( p->vSuppFun, p->nSimWords, p->vPairsTotal ); - if ( fVerbose ) - printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", - p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); - - // detect symmetries using circuit structure -clk = clock(); - Sim_SymmsStructCompute( pNtk, p->vMatrSymms, p->vSuppFun ); -p->timeStruct = clock() - clk; - - Sim_UtilCountPairsAll( p ); - p->nPairsSymmStr = p->nPairsSymm; - if ( fVerbose ) - printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", - p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); - - // detect symmetries using simulation - for ( i = 1; i <= 1000; i++ ) - { - // simulate this pattern - Sim_UtilSetRandom( p->uPatRand, p->nSimWords ); - Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); - if ( i % 50 != 0 ) - continue; - // check disjointness - assert( Sim_UtilMatrsAreDisjoint( p ) ); - // count the number of pairs - Sim_UtilCountPairsAll( p ); - if ( i % 500 != 0 ) - continue; - if ( fVerbose ) - printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", - p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); - } - - // detect symmetries using SAT - for ( i = 1; Sim_SymmsGetPatternUsingSat( p, p->uPatRand ); i++ ) - { - // simulate this pattern in four polarities - Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); - Sim_XorBit( p->uPatRand, p->iVar1 ); - Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); - Sim_XorBit( p->uPatRand, p->iVar2 ); - Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); - Sim_XorBit( p->uPatRand, p->iVar1 ); - Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); - Sim_XorBit( p->uPatRand, p->iVar2 ); -/* - // try the previuos pair - Sim_XorBit( p->uPatRand, p->iVar1Old ); - Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); - Sim_XorBit( p->uPatRand, p->iVar2Old ); - Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); - Sim_XorBit( p->uPatRand, p->iVar1Old ); - Sim_SymmsSimulate( p, p->uPatRand, p->vMatrNonSymms ); -*/ - if ( i % 10 != 0 ) - continue; - // check disjointness - assert( Sim_UtilMatrsAreDisjoint( p ) ); - // count the number of pairs - Sim_UtilCountPairsAll( p ); - if ( i % 50 != 0 ) - continue; - if ( fVerbose ) - printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", - p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); - } - - // count the number of pairs - Sim_UtilCountPairsAll( p ); - if ( fVerbose ) - printf( "Total = %8d. Sym = %8d. NonSym = %8d. Remaining = %8d.\n", - p->nPairsTotal, p->nPairsSymm, p->nPairsNonSymm, p->nPairsRem ); -// Sim_UtilCountPairsAllPrint( p ); - - Result = p->nPairsSymm; - vResult = p->vMatrSymms; -p->timeTotal = clock() - clkTotal; - // p->vMatrSymms = NULL; - Sym_ManStop( p ); - return Result; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/sim/simSymSat.c b/src/opt/sim/simSymSat.c deleted file mode 100644 index 7690a891..00000000 --- a/src/opt/sim/simSymSat.c +++ /dev/null @@ -1,199 +0,0 @@ -/**CFile**************************************************************** - - FileName [simSymSat.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Satisfiability to determine two variable symmetries.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: simSymSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "sim.h" -#include "fraig.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Tries to prove the remaining pairs using SAT.] - - Description [Continues to prove as long as it encounters symmetric pairs. - Returns 1 if a non-symmetric pair is found (which gives a counter-example). - Returns 0 if it finishes considering all pairs for all outputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_SymmsGetPatternUsingSat( Sym_Man_t * p, unsigned * pPattern ) -{ - Vec_Int_t * vSupport; - Extra_BitMat_t * pMatSym, * pMatNonSym; - int Index1, Index2, Index3, IndexU, IndexV; - int v, u, i, k, b, out; - - // iterate through outputs - for ( out = p->iOutput; out < p->nOutputs; out++ ) - { - pMatSym = Vec_PtrEntry( p->vMatrSymms, out ); - pMatNonSym = Vec_PtrEntry( p->vMatrNonSymms, out ); - - // go through the remaining variable pairs - vSupport = Vec_VecEntry( p->vSupports, out ); - Vec_IntForEachEntry( vSupport, v, Index1 ) - Vec_IntForEachEntryStart( vSupport, u, Index2, Index1+1 ) - { - if ( Extra_BitMatrixLookup1( pMatSym, v, u ) || Extra_BitMatrixLookup1( pMatNonSym, v, u ) ) - continue; - p->nSatRuns++; - - // collect the support variables that are symmetric with u and v - Vec_IntClear( p->vVarsU ); - Vec_IntClear( p->vVarsV ); - Vec_IntForEachEntry( vSupport, b, Index3 ) - { - if ( Extra_BitMatrixLookup1( pMatSym, u, b ) ) - Vec_IntPush( p->vVarsU, b ); - if ( Extra_BitMatrixLookup1( pMatSym, v, b ) ) - Vec_IntPush( p->vVarsV, b ); - } - - if ( Sim_SymmsSatProveOne( p, out, v, u, pPattern ) ) - { // update the symmetric variable info - p->nSatRunsUnsat++; - Vec_IntForEachEntry( p->vVarsU, i, IndexU ) - Vec_IntForEachEntry( p->vVarsV, k, IndexV ) - { - Extra_BitMatrixInsert1( pMatSym, i, k ); // Theorem 1 - Extra_BitMatrixInsert2( pMatSym, i, k ); // Theorem 1 - Extra_BitMatrixOrTwo( pMatNonSym, i, k ); // Theorem 2 - } - } - else - { // update the assymmetric variable info - p->nSatRunsSat++; - Vec_IntForEachEntry( p->vVarsU, i, IndexU ) - Vec_IntForEachEntry( p->vVarsV, k, IndexV ) - { - Extra_BitMatrixInsert1( pMatNonSym, i, k ); // Theorem 3 - Extra_BitMatrixInsert2( pMatNonSym, i, k ); // Theorem 3 - } - - // remember the out - p->iOutput = out; - p->iVar1Old = p->iVar1; - p->iVar2Old = p->iVar2; - p->iVar1 = v; - p->iVar2 = u; - return 1; - - } - } - // make sure that the symmetry matrix contains only cliques - assert( Extra_BitMatrixIsClique( pMatSym ) ); - } - - // mark that we finished all outputs - p->iOutput = p->nOutputs; - return 0; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the variables are symmetric; 0 otherwise.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_SymmsSatProveOne( Sym_Man_t * p, int Out, int Var1, int Var2, unsigned * pPattern ) -{ - Fraig_Params_t Params; - Fraig_Man_t * pMan; - Abc_Ntk_t * pMiter; - int RetValue, i, clk; - int * pModel; - - // get the miter for this problem - pMiter = Abc_NtkMiterForCofactors( p->pNtk, Out, Var1, Var2 ); - // transform the miter into a fraig - Fraig_ParamsSetDefault( &Params ); - Params.fInternal = 1; - Params.nPatsRand = 512; - Params.nPatsDyna = 512; - Params.nSeconds = ABC_INFINITY; - -clk = clock(); - pMan = Abc_NtkToFraig( pMiter, &Params, 0, 0 ); -p->timeFraig += clock() - clk; -clk = clock(); - Fraig_ManProveMiter( pMan ); -p->timeSat += clock() - clk; - - // analyze the result - RetValue = Fraig_ManCheckMiter( pMan ); -// assert( RetValue >= 0 ); - // save the pattern - if ( RetValue == 0 ) - { - // get the pattern - pModel = Fraig_ManReadModel( pMan ); - assert( pModel != NULL ); -//printf( "Disproved by SAT: out = %d pair = (%d, %d)\n", Out, Var1, Var2 ); - // transfer the model into the pattern - for ( i = 0; i < p->nSimWords; i++ ) - pPattern[i] = 0; - for ( i = 0; i < p->nInputs; i++ ) - if ( pModel[i] ) - Sim_SetBit( pPattern, i ); - // make sure these variables have the same value (1) - Sim_SetBit( pPattern, Var1 ); - Sim_SetBit( pPattern, Var2 ); - } - else if ( RetValue == -1 ) - { - // this should never happen; if it happens, such is life - // we are conservative and assume that there is no symmetry -//printf( "STRANGE THING: out = %d %s pair = (%d %s, %d %s)\n", -// Out, Abc_ObjName(Abc_NtkCo(p->pNtk,Out)), -// Var1, Abc_ObjName(Abc_NtkCi(p->pNtk,Var1)), -// Var2, Abc_ObjName(Abc_NtkCi(p->pNtk,Var2)) ); - memset( pPattern, 0, sizeof(unsigned) * p->nSimWords ); - RetValue = 0; - } - // delete the fraig manager - Fraig_ManFree( pMan ); - // delete the miter - Abc_NtkDelete( pMiter ); - return RetValue; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/sim/simSymSim.c b/src/opt/sim/simSymSim.c deleted file mode 100644 index 2282825b..00000000 --- a/src/opt/sim/simSymSim.c +++ /dev/null @@ -1,173 +0,0 @@ -/**CFile**************************************************************** - - FileName [simSymSim.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Simulation to determine two-variable symmetries.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: simSymSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "sim.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Sim_SymmsCreateSquare( Sym_Man_t * p, unsigned * pPat ); -static void Sim_SymmsDeriveInfo( Sym_Man_t * p, unsigned * pPat, Abc_Obj_t * pNode, Vec_Ptr_t * vMatrsNonSym, int Output ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Detects non-symmetric pairs using one pattern.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SymmsSimulate( Sym_Man_t * p, unsigned * pPat, Vec_Ptr_t * vMatrsNonSym ) -{ - Abc_Obj_t * pNode; - int i, nPairsTotal, nPairsSym, nPairsNonSym; - int clk; - - // create the simulation matrix - Sim_SymmsCreateSquare( p, pPat ); - // simulate each node in the DFS order -clk = clock(); - Vec_PtrForEachEntry( p->vNodes, pNode, i ) - { -// if ( Abc_NodeIsConst(pNode) ) -// continue; - Sim_UtilSimulateNodeOne( pNode, p->vSim, p->nSimWords, 0 ); - } -p->timeSim += clock() - clk; - // collect info into the CO matrices -clk = clock(); - Abc_NtkForEachCo( p->pNtk, pNode, i ) - { - pNode = Abc_ObjFanin0(pNode); -// if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) ) -// continue; - nPairsTotal = Vec_IntEntry(p->vPairsTotal, i); - nPairsSym = Vec_IntEntry(p->vPairsSym, i); - nPairsNonSym = Vec_IntEntry(p->vPairsNonSym,i); - assert( nPairsTotal >= nPairsSym + nPairsNonSym ); - if ( nPairsTotal == nPairsSym + nPairsNonSym ) - continue; - Sim_SymmsDeriveInfo( p, pPat, pNode, vMatrsNonSym, i ); - } -p->timeMatr += clock() - clk; -} - -/**Function************************************************************* - - Synopsis [Creates the square matrix of simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SymmsCreateSquare( Sym_Man_t * p, unsigned * pPat ) -{ - unsigned * pSimInfo; - Abc_Obj_t * pNode; - int i, w; - // for each PI var copy the pattern - Abc_NtkForEachCi( p->pNtk, pNode, i ) - { - pSimInfo = Vec_PtrEntry( p->vSim, pNode->Id ); - if ( Sim_HasBit(pPat, i) ) - { - for ( w = 0; w < p->nSimWords; w++ ) - pSimInfo[w] = SIM_MASK_FULL; - } - else - { - for ( w = 0; w < p->nSimWords; w++ ) - pSimInfo[w] = 0; - } - // flip one bit - Sim_XorBit( pSimInfo, i ); - } -} - -/**Function************************************************************* - - Synopsis [Transfers the info to the POs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SymmsDeriveInfo( Sym_Man_t * p, unsigned * pPat, Abc_Obj_t * pNode, Vec_Ptr_t * vMatrsNonSym, int Output ) -{ - Extra_BitMat_t * pMat; - Vec_Int_t * vSupport; - unsigned * pSupport; - unsigned * pSimInfo; - int i, w, Index; - // get the matrix, the support, and the simulation info - pMat = Vec_PtrEntry( vMatrsNonSym, Output ); - vSupport = Vec_VecEntry( p->vSupports, Output ); - pSupport = Vec_PtrEntry( p->vSuppFun, Output ); - pSimInfo = Vec_PtrEntry( p->vSim, pNode->Id ); - // generate vectors A1 and A2 - for ( w = 0; w < p->nSimWords; w++ ) - { - p->uPatCol[w] = pSupport[w] & pPat[w] & pSimInfo[w]; - p->uPatRow[w] = pSupport[w] & pPat[w] & ~pSimInfo[w]; - } - // add two dimensions - Vec_IntForEachEntry( vSupport, i, Index ) - if ( Sim_HasBit( p->uPatCol, i ) ) - Extra_BitMatrixOr( pMat, i, p->uPatRow ); - // add two dimensions - Vec_IntForEachEntry( vSupport, i, Index ) - if ( Sim_HasBit( p->uPatRow, i ) ) - Extra_BitMatrixOr( pMat, i, p->uPatCol ); - // generate vectors B1 and B2 - for ( w = 0; w < p->nSimWords; w++ ) - { - p->uPatCol[w] = pSupport[w] & ~pPat[w] & pSimInfo[w]; - p->uPatRow[w] = pSupport[w] & ~pPat[w] & ~pSimInfo[w]; - } - // add two dimensions - Vec_IntForEachEntry( vSupport, i, Index ) - if ( Sim_HasBit( p->uPatCol, i ) ) - Extra_BitMatrixOr( pMat, i, p->uPatRow ); - // add two dimensions - Vec_IntForEachEntry( vSupport, i, Index ) - if ( Sim_HasBit( p->uPatRow, i ) ) - Extra_BitMatrixOr( pMat, i, p->uPatCol ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/sim/simSymStr.c b/src/opt/sim/simSymStr.c deleted file mode 100644 index d52c4328..00000000 --- a/src/opt/sim/simSymStr.c +++ /dev/null @@ -1,488 +0,0 @@ -/**CFile**************************************************************** - - FileName [simSymStr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Structural detection of symmetries.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: simSymStr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "sim.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define SIM_READ_SYMMS(pNode) ((Vec_Int_t *)pNode->pCopy) -#define SIM_SET_SYMMS(pNode,vVect) (pNode->pCopy = (Abc_Obj_t *)(vVect)) - -static void Sim_SymmsStructComputeOne( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int * pMap ); -static void Sim_SymmsBalanceCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); -static void Sim_SymmsPartitionNodes( Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesPis0, Vec_Ptr_t * vNodesPis1, Vec_Ptr_t * vNodesOther ); -static void Sim_SymmsAppendFromGroup( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodesPi, Vec_Ptr_t * vNodesOther, Vec_Int_t * vSymms, int * pMap ); -static void Sim_SymmsAppendFromNode( Abc_Ntk_t * pNtk, Vec_Int_t * vSymms0, Vec_Ptr_t * vNodesOther, Vec_Ptr_t * vNodesPi0, Vec_Ptr_t * vNodesPi1, Vec_Int_t * vSymms, int * pMap ); -static int Sim_SymmsIsCompatibleWithNodes( Abc_Ntk_t * pNtk, unsigned uSymm, Vec_Ptr_t * vNodesOther, int * pMap ); -static int Sim_SymmsIsCompatibleWithGroup( unsigned uSymm, Vec_Ptr_t * vNodesPi, int * pMap ); -static void Sim_SymmsPrint( Vec_Int_t * vSymms ); -static void Sim_SymmsTrans( Vec_Int_t * vSymms ); -static void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * vSymms, unsigned * pSupport ); -static int * Sim_SymmsCreateMap( Abc_Ntk_t * pNtk ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes symmetries for a single output function.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SymmsStructCompute( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMatrs, Vec_Ptr_t * vSuppFun ) -{ - Vec_Ptr_t * vNodes; - Abc_Obj_t * pTemp; - int * pMap, i; - - assert( Abc_NtkCiNum(pNtk) + 10 < (1<<16) ); - - // get the structural support - pNtk->vSupps = Sim_ComputeStrSupp( pNtk ); - // set elementary info for the CIs - Abc_NtkForEachCi( pNtk, pTemp, i ) - SIM_SET_SYMMS( pTemp, Vec_IntAlloc(0) ); - // create the map of CI ids into their numbers - pMap = Sim_SymmsCreateMap( pNtk ); - // collect the nodes in the TFI cone of this output - vNodes = Abc_NtkDfs( pNtk, 0 ); - Vec_PtrForEachEntry( vNodes, pTemp, i ) - { -// if ( Abc_NodeIsConst(pTemp) ) -// continue; - Sim_SymmsStructComputeOne( pNtk, pTemp, pMap ); - } - // collect the results for the COs; - Abc_NtkForEachCo( pNtk, pTemp, i ) - { -//printf( "Output %d:\n", i ); - pTemp = Abc_ObjFanin0(pTemp); - if ( Abc_ObjIsCi(pTemp) || Abc_AigNodeIsConst(pTemp) ) - continue; - Sim_SymmsTransferToMatrix( Vec_PtrEntry(vMatrs, i), SIM_READ_SYMMS(pTemp), Vec_PtrEntry(vSuppFun, i) ); - } - // clean the intermediate results - Sim_UtilInfoFree( pNtk->vSupps ); - pNtk->vSupps = NULL; - Abc_NtkForEachCi( pNtk, pTemp, i ) - Vec_IntFree( SIM_READ_SYMMS(pTemp) ); - Vec_PtrForEachEntry( vNodes, pTemp, i ) -// if ( !Abc_NodeIsConst(pTemp) ) - Vec_IntFree( SIM_READ_SYMMS(pTemp) ); - Vec_PtrFree( vNodes ); - free( pMap ); -} - -/**Function************************************************************* - - Synopsis [Recursively computes symmetries. ] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SymmsStructComputeOne( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, int * pMap ) -{ - Vec_Ptr_t * vNodes, * vNodesPi0, * vNodesPi1, * vNodesOther; - Vec_Int_t * vSymms; - Abc_Obj_t * pTemp; - int i; - - // allocate the temporary arrays - vNodes = Vec_PtrAlloc( 10 ); - vNodesPi0 = Vec_PtrAlloc( 10 ); - vNodesPi1 = Vec_PtrAlloc( 10 ); - vNodesOther = Vec_PtrAlloc( 10 ); - - // collect the fanins of the implication supergate - Sim_SymmsBalanceCollect_rec( pNode, vNodes ); - - // sort the nodes in the implication supergate - Sim_SymmsPartitionNodes( vNodes, vNodesPi0, vNodesPi1, vNodesOther ); - - // start the resulting set - vSymms = Vec_IntAlloc( 10 ); - // generate symmetries from the groups - Sim_SymmsAppendFromGroup( pNtk, vNodesPi0, vNodesOther, vSymms, pMap ); - Sim_SymmsAppendFromGroup( pNtk, vNodesPi1, vNodesOther, vSymms, pMap ); - // add symmetries from other inputs - for ( i = 0; i < vNodesOther->nSize; i++ ) - { - pTemp = Abc_ObjRegular(vNodesOther->pArray[i]); - Sim_SymmsAppendFromNode( pNtk, SIM_READ_SYMMS(pTemp), vNodesOther, vNodesPi0, vNodesPi1, vSymms, pMap ); - } - Vec_PtrFree( vNodes ); - Vec_PtrFree( vNodesPi0 ); - Vec_PtrFree( vNodesPi1 ); - Vec_PtrFree( vNodesOther ); - - // set the symmetry at the node - SIM_SET_SYMMS( pNode, vSymms ); -} - - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SymmsBalanceCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) -{ - // if the new node is complemented, another gate begins - if ( Abc_ObjIsComplement(pNode) ) - { - Vec_PtrPushUnique( vNodes, pNode ); - return; - } - // if pNew is the PI node, return - if ( Abc_ObjIsCi(pNode) ) - { - Vec_PtrPushUnique( vNodes, pNode ); - return; - } - // go through the branches - Sim_SymmsBalanceCollect_rec( Abc_ObjChild0(pNode), vNodes ); - Sim_SymmsBalanceCollect_rec( Abc_ObjChild1(pNode), vNodes ); -} - -/**Function************************************************************* - - Synopsis [Divides PI variables into groups.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SymmsPartitionNodes( Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesPis0, - Vec_Ptr_t * vNodesPis1, Vec_Ptr_t * vNodesOther ) -{ - Abc_Obj_t * pNode; - int i; - Vec_PtrForEachEntry( vNodes, pNode, i ) - { - if ( !Abc_ObjIsCi(Abc_ObjRegular(pNode)) ) - Vec_PtrPush( vNodesOther, pNode ); - else if ( Abc_ObjIsComplement(pNode) ) - Vec_PtrPush( vNodesPis0, pNode ); - else - Vec_PtrPush( vNodesPis1, pNode ); - } -} - -/**Function************************************************************* - - Synopsis [Makes the product of two partitions.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SymmsAppendFromGroup( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodesPi, Vec_Ptr_t * vNodesOther, Vec_Int_t * vSymms, int * pMap ) -{ - Abc_Obj_t * pNode1, * pNode2; - unsigned uSymm; - int i, k; - - if ( vNodesPi->nSize == 0 ) - return; - - // go through the pairs - for ( i = 0; i < vNodesPi->nSize; i++ ) - for ( k = i+1; k < vNodesPi->nSize; k++ ) - { - // get the two PI nodes - pNode1 = Abc_ObjRegular(vNodesPi->pArray[i]); - pNode2 = Abc_ObjRegular(vNodesPi->pArray[k]); - assert( pMap[pNode1->Id] != pMap[pNode2->Id] ); - assert( pMap[pNode1->Id] >= 0 ); - assert( pMap[pNode2->Id] >= 0 ); - // generate symmetry - if ( pMap[pNode1->Id] < pMap[pNode2->Id] ) - uSymm = ((pMap[pNode1->Id] << 16) | pMap[pNode2->Id]); - else - uSymm = ((pMap[pNode2->Id] << 16) | pMap[pNode1->Id]); - // check if symmetry belongs - if ( Sim_SymmsIsCompatibleWithNodes( pNtk, uSymm, vNodesOther, pMap ) ) - Vec_IntPushUnique( vSymms, (int)uSymm ); - } -} - -/**Function************************************************************* - - Synopsis [Add the filters symmetries from the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SymmsAppendFromNode( Abc_Ntk_t * pNtk, Vec_Int_t * vSymms0, Vec_Ptr_t * vNodesOther, - Vec_Ptr_t * vNodesPi0, Vec_Ptr_t * vNodesPi1, Vec_Int_t * vSymms, int * pMap ) -{ - unsigned uSymm; - int i; - - if ( vSymms0->nSize == 0 ) - return; - - // go through the pairs - for ( i = 0; i < vSymms0->nSize; i++ ) - { - uSymm = (unsigned)vSymms0->pArray[i]; - // check if symmetry belongs - if ( Sim_SymmsIsCompatibleWithNodes( pNtk, uSymm, vNodesOther, pMap ) && - Sim_SymmsIsCompatibleWithGroup( uSymm, vNodesPi0, pMap ) && - Sim_SymmsIsCompatibleWithGroup( uSymm, vNodesPi1, pMap ) ) - Vec_IntPushUnique( vSymms, (int)uSymm ); - } -} - -/**Function************************************************************* - - Synopsis [Returns 1 if symmetry is compatible with the group of nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_SymmsIsCompatibleWithNodes( Abc_Ntk_t * pNtk, unsigned uSymm, Vec_Ptr_t * vNodesOther, int * pMap ) -{ - Vec_Int_t * vSymmsNode; - Abc_Obj_t * pNode; - int i, s, Ind1, Ind2, fIsVar1, fIsVar2; - - if ( vNodesOther->nSize == 0 ) - return 1; - - // get the indices of the PI variables - Ind1 = (uSymm & 0xffff); - Ind2 = (uSymm >> 16); - - // go through the nodes - // if they do not belong to a support, it is okay - // if one belongs, the other does not belong, quit - // if they belong, but are not part of symmetry, quit - for ( i = 0; i < vNodesOther->nSize; i++ ) - { - pNode = Abc_ObjRegular(vNodesOther->pArray[i]); - fIsVar1 = Sim_SuppStrHasVar( pNtk->vSupps, pNode, Ind1 ); - fIsVar2 = Sim_SuppStrHasVar( pNtk->vSupps, pNode, Ind2 ); - - if ( !fIsVar1 && !fIsVar2 ) - continue; - if ( fIsVar1 ^ fIsVar2 ) - return 0; - // both belong - // check if there is a symmetry - vSymmsNode = SIM_READ_SYMMS( pNode ); - for ( s = 0; s < vSymmsNode->nSize; s++ ) - if ( uSymm == (unsigned)vSymmsNode->pArray[s] ) - break; - if ( s == vSymmsNode->nSize ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if symmetry is compatible with the group of PIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_SymmsIsCompatibleWithGroup( unsigned uSymm, Vec_Ptr_t * vNodesPi, int * pMap ) -{ - Abc_Obj_t * pNode; - int i, Ind1, Ind2, fHasVar1, fHasVar2; - - if ( vNodesPi->nSize == 0 ) - return 1; - - // get the indices of the PI variables - Ind1 = (uSymm & 0xffff); - Ind2 = (uSymm >> 16); - - // go through the PI nodes - fHasVar1 = fHasVar2 = 0; - for ( i = 0; i < vNodesPi->nSize; i++ ) - { - pNode = Abc_ObjRegular(vNodesPi->pArray[i]); - if ( pMap[pNode->Id] == Ind1 ) - fHasVar1 = 1; - else if ( pMap[pNode->Id] == Ind2 ) - fHasVar2 = 1; - } - return fHasVar1 == fHasVar2; -} - - - -/**Function************************************************************* - - Synopsis [Improvements due to transitivity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SymmsTrans( Vec_Int_t * vSymms ) -{ - unsigned uSymm, uSymma, uSymmr; - int i, Ind1, Ind2; - int k, Ind1a, Ind2a; - int j; - int nTrans = 0; - - for ( i = 0; i < vSymms->nSize; i++ ) - { - uSymm = (unsigned)vSymms->pArray[i]; - Ind1 = (uSymm & 0xffff); - Ind2 = (uSymm >> 16); - // find other symmetries that have Ind1 - for ( k = i+1; k < vSymms->nSize; k++ ) - { - uSymma = (unsigned)vSymms->pArray[k]; - if ( uSymma == uSymm ) - continue; - Ind1a = (uSymma & 0xffff); - Ind2a = (uSymma >> 16); - if ( Ind1a == Ind1 ) - { - // find the symmetry (Ind2,Ind2a) - if ( Ind2 < Ind2a ) - uSymmr = ((Ind2 << 16) | Ind2a); - else - uSymmr = ((Ind2a << 16) | Ind2); - for ( j = 0; j < vSymms->nSize; j++ ) - if ( uSymmr == (unsigned)vSymms->pArray[j] ) - break; - if ( j == vSymms->nSize ) - nTrans++; - } - } - - } - printf( "Trans = %d.\n", nTrans ); -} - - -/**Function************************************************************* - - Synopsis [Transfers from the vector to the matrix.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_SymmsTransferToMatrix( Extra_BitMat_t * pMatSymm, Vec_Int_t * vSymms, unsigned * pSupport ) -{ - int i, Ind1, Ind2, nInputs; - unsigned uSymm; - // add diagonal elements - nInputs = Extra_BitMatrixReadSize( pMatSymm ); - for ( i = 0; i < nInputs; i++ ) - Extra_BitMatrixInsert1( pMatSymm, i, i ); - // add non-diagonal elements - for ( i = 0; i < vSymms->nSize; i++ ) - { - uSymm = (unsigned)vSymms->pArray[i]; - Ind1 = (uSymm & 0xffff); - Ind2 = (uSymm >> 16); -//printf( "%d,%d ", Ind1, Ind2 ); - // skip variables that are not in the true support - assert( Sim_HasBit(pSupport, Ind1) == Sim_HasBit(pSupport, Ind2) ); - if ( !Sim_HasBit(pSupport, Ind1) || !Sim_HasBit(pSupport, Ind2) ) - continue; - Extra_BitMatrixInsert1( pMatSymm, Ind1, Ind2 ); - Extra_BitMatrixInsert2( pMatSymm, Ind1, Ind2 ); - } -} - -/**Function************************************************************* - - Synopsis [Mapping of indices into numbers.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Sim_SymmsCreateMap( Abc_Ntk_t * pNtk ) -{ - int * pMap; - Abc_Obj_t * pNode; - int i; - pMap = ALLOC( int, Abc_NtkObjNumMax(pNtk) ); - for ( i = 0; i < Abc_NtkObjNumMax(pNtk); i++ ) - pMap[i] = -1; - Abc_NtkForEachCi( pNtk, pNode, i ) - pMap[pNode->Id] = i; - return pMap; -} - - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/opt/sim/simUtils.c b/src/opt/sim/simUtils.c deleted file mode 100644 index b0660001..00000000 --- a/src/opt/sim/simUtils.c +++ /dev/null @@ -1,711 +0,0 @@ -/**CFile**************************************************************** - - FileName [simUtils.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Network and node package.] - - Synopsis [Various simulation utilities.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: simUtils.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "sim.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int bit_count[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates simulation information for all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Ptr_t * Sim_UtilInfoAlloc( int nSize, int nWords, bool fClean ) -{ - Vec_Ptr_t * vInfo; - int i; - assert( nSize > 0 && nWords > 0 ); - vInfo = Vec_PtrAlloc( nSize ); - vInfo->pArray[0] = ALLOC( unsigned, nSize * nWords ); - if ( fClean ) - memset( vInfo->pArray[0], 0, sizeof(unsigned) * nSize * nWords ); - for ( i = 1; i < nSize; i++ ) - vInfo->pArray[i] = ((unsigned *)vInfo->pArray[i-1]) + nWords; - vInfo->nSize = nSize; - return vInfo; -} - -/**Function************************************************************* - - Synopsis [Allocates simulation information for all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilInfoFree( Vec_Ptr_t * p ) -{ - free( p->pArray[0] ); - Vec_PtrFree( p ); -} - -/**Function************************************************************* - - Synopsis [Adds the second supp-info the first.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilInfoAdd( unsigned * pInfo1, unsigned * pInfo2, int nWords ) -{ - int w; - for ( w = 0; w < nWords; w++ ) - pInfo1[w] |= pInfo2[w]; -} - -/**Function************************************************************* - - Synopsis [Returns the positions where pInfo2 is 1 while pInfo1 is 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilInfoDetectDiffs( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ) -{ - int w, b; - unsigned uMask; - vDiffs->nSize = 0; - for ( w = 0; w < nWords; w++ ) - if ( uMask = (pInfo2[w] ^ pInfo1[w]) ) - for ( b = 0; b < 32; b++ ) - if ( uMask & (1 << b) ) - Vec_IntPush( vDiffs, 32*w + b ); -} - -/**Function************************************************************* - - Synopsis [Returns the positions where pInfo2 is 1 while pInfo1 is 0.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilInfoDetectNews( unsigned * pInfo1, unsigned * pInfo2, int nWords, Vec_Int_t * vDiffs ) -{ - int w, b; - unsigned uMask; - vDiffs->nSize = 0; - for ( w = 0; w < nWords; w++ ) - if ( uMask = (pInfo2[w] & ~pInfo1[w]) ) - for ( b = 0; b < 32; b++ ) - if ( uMask & (1 << b) ) - Vec_IntPush( vDiffs, 32*w + b ); -} - -/**Function************************************************************* - - Synopsis [Flips the simulation info of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilInfoFlip( Sim_Man_t * p, Abc_Obj_t * pNode ) -{ - unsigned * pSimInfo1, * pSimInfo2; - int k; - pSimInfo1 = p->vSim0->pArray[pNode->Id]; - pSimInfo2 = p->vSim1->pArray[pNode->Id]; - for ( k = 0; k < p->nSimWords; k++ ) - pSimInfo2[k] = ~pSimInfo1[k]; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the simulation infos are equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Sim_UtilInfoCompare( Sim_Man_t * p, Abc_Obj_t * pNode ) -{ - unsigned * pSimInfo1, * pSimInfo2; - int k; - pSimInfo1 = p->vSim0->pArray[pNode->Id]; - pSimInfo2 = p->vSim1->pArray[pNode->Id]; - for ( k = 0; k < p->nSimWords; k++ ) - if ( pSimInfo2[k] != pSimInfo1[k] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Simulates the internal nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilSimulate( Sim_Man_t * p, bool fType ) -{ - Abc_Obj_t * pNode; - int i; - // simulate the internal nodes - Abc_NtkForEachNode( p->pNtk, pNode, i ) - Sim_UtilSimulateNode( p, pNode, fType, fType, fType ); - // assign simulation info of the CO nodes - Abc_NtkForEachCo( p->pNtk, pNode, i ) - Sim_UtilSimulateNode( p, pNode, fType, fType, fType ); -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilSimulateNode( Sim_Man_t * p, Abc_Obj_t * pNode, bool fType, bool fType1, bool fType2 ) -{ - unsigned * pSimmNode, * pSimmNode1, * pSimmNode2; - int k, fComp1, fComp2; - // simulate the internal nodes - if ( Abc_ObjIsNode(pNode) ) - { - if ( fType ) - pSimmNode = p->vSim1->pArray[ pNode->Id ]; - else - pSimmNode = p->vSim0->pArray[ pNode->Id ]; - - if ( fType1 ) - pSimmNode1 = p->vSim1->pArray[ Abc_ObjFaninId0(pNode) ]; - else - pSimmNode1 = p->vSim0->pArray[ Abc_ObjFaninId0(pNode) ]; - - if ( fType2 ) - pSimmNode2 = p->vSim1->pArray[ Abc_ObjFaninId1(pNode) ]; - else - pSimmNode2 = p->vSim0->pArray[ Abc_ObjFaninId1(pNode) ]; - - fComp1 = Abc_ObjFaninC0(pNode); - fComp2 = Abc_ObjFaninC1(pNode); - if ( fComp1 && fComp2 ) - for ( k = 0; k < p->nSimWords; k++ ) - pSimmNode[k] = ~pSimmNode1[k] & ~pSimmNode2[k]; - else if ( fComp1 && !fComp2 ) - for ( k = 0; k < p->nSimWords; k++ ) - pSimmNode[k] = ~pSimmNode1[k] & pSimmNode2[k]; - else if ( !fComp1 && fComp2 ) - for ( k = 0; k < p->nSimWords; k++ ) - pSimmNode[k] = pSimmNode1[k] & ~pSimmNode2[k]; - else // if ( fComp1 && fComp2 ) - for ( k = 0; k < p->nSimWords; k++ ) - pSimmNode[k] = pSimmNode1[k] & pSimmNode2[k]; - } - else - { - assert( Abc_ObjFaninNum(pNode) == 1 ); - if ( fType ) - pSimmNode = p->vSim1->pArray[ pNode->Id ]; - else - pSimmNode = p->vSim0->pArray[ pNode->Id ]; - - if ( fType1 ) - pSimmNode1 = p->vSim1->pArray[ Abc_ObjFaninId0(pNode) ]; - else - pSimmNode1 = p->vSim0->pArray[ Abc_ObjFaninId0(pNode) ]; - - fComp1 = Abc_ObjFaninC0(pNode); - if ( fComp1 ) - for ( k = 0; k < p->nSimWords; k++ ) - pSimmNode[k] = ~pSimmNode1[k]; - else - for ( k = 0; k < p->nSimWords; k++ ) - pSimmNode[k] = pSimmNode1[k]; - } -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilSimulateNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset ) -{ - unsigned * pSimmNode, * pSimmNode1, * pSimmNode2; - int k, fComp1, fComp2; - // simulate the internal nodes - assert( Abc_ObjIsNode(pNode) ); - pSimmNode = Vec_PtrEntry(vSimInfo, pNode->Id); - pSimmNode1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); - pSimmNode2 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode)); - pSimmNode += nOffset; - pSimmNode1 += nOffset; - pSimmNode2 += nOffset; - fComp1 = Abc_ObjFaninC0(pNode); - fComp2 = Abc_ObjFaninC1(pNode); - if ( fComp1 && fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pSimmNode[k] = ~pSimmNode1[k] & ~pSimmNode2[k]; - else if ( fComp1 && !fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pSimmNode[k] = ~pSimmNode1[k] & pSimmNode2[k]; - else if ( !fComp1 && fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pSimmNode[k] = pSimmNode1[k] & ~pSimmNode2[k]; - else // if ( fComp1 && fComp2 ) - for ( k = 0; k < nSimWords; k++ ) - pSimmNode[k] = pSimmNode1[k] & pSimmNode2[k]; -} - -/**Function************************************************************* - - Synopsis [Simulates one node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilTransferNodeOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords, int nOffset, int fShift ) -{ - unsigned * pSimmNode, * pSimmNode1; - int k, fComp1; - // simulate the internal nodes - assert( Abc_ObjIsCo(pNode) ); - pSimmNode = Vec_PtrEntry(vSimInfo, pNode->Id); - pSimmNode1 = Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode)); - pSimmNode += nOffset + (fShift > 0)*nSimWords; - pSimmNode1 += nOffset; - fComp1 = Abc_ObjFaninC0(pNode); - if ( fComp1 ) - for ( k = 0; k < nSimWords; k++ ) - pSimmNode[k] = ~pSimmNode1[k]; - else - for ( k = 0; k < nSimWords; k++ ) - pSimmNode[k] = pSimmNode1[k]; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the simulation infos are equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_UtilCountSuppSizes( Sim_Man_t * p, int fStruct ) -{ - Abc_Obj_t * pNode, * pNodeCi; - int i, v, Counter; - Counter = 0; - if ( fStruct ) - { - Abc_NtkForEachCo( p->pNtk, pNode, i ) - Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) - Counter += Sim_SuppStrHasVar( p->vSuppStr, pNode, v ); - } - else - { - Abc_NtkForEachCo( p->pNtk, pNode, i ) - Abc_NtkForEachCi( p->pNtk, pNodeCi, v ) - Counter += Sim_SuppFunHasVar( p->vSuppFun, i, v ); - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of 1's in the bitstring.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_UtilCountOnes( unsigned * pSimInfo, int nSimWords ) -{ - unsigned char * pBytes; - int nOnes, nBytes, i; - pBytes = (unsigned char *)pSimInfo; - nBytes = 4 * nSimWords; - nOnes = 0; - for ( i = 0; i < nBytes; i++ ) - nOnes += bit_count[ pBytes[i] ]; - return nOnes; -} - -/**Function************************************************************* - - Synopsis [Counts the number of 1's in the bitstring.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Vec_Int_t * Sim_UtilCountOnesArray( Vec_Ptr_t * vInfo, int nSimWords ) -{ - Vec_Int_t * vCounters; - unsigned * pSimInfo; - int i; - vCounters = Vec_IntStart( Vec_PtrSize(vInfo) ); - Vec_PtrForEachEntry( vInfo, pSimInfo, i ) - Vec_IntWriteEntry( vCounters, i, Sim_UtilCountOnes(pSimInfo, nSimWords) ); - return vCounters; -} - -/**Function************************************************************* - - Synopsis [Returns random patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilSetRandom( unsigned * pPatRand, int nSimWords ) -{ - int k; - for ( k = 0; k < nSimWords; k++ ) - pPatRand[k] = SIM_RANDOM_UNSIGNED; -} - -/**Function************************************************************* - - Synopsis [Returns complemented patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilSetCompl( unsigned * pPatRand, int nSimWords ) -{ - int k; - for ( k = 0; k < nSimWords; k++ ) - pPatRand[k] = ~pPatRand[k]; -} - -/**Function************************************************************* - - Synopsis [Returns constant patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilSetConst( unsigned * pPatRand, int nSimWords, int fConst1 ) -{ - int k; - for ( k = 0; k < nSimWords; k++ ) - pPatRand[k] = 0; - if ( fConst1 ) - Sim_UtilSetCompl( pPatRand, nSimWords ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if equal.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_UtilInfoIsEqual( unsigned * pPats1, unsigned * pPats2, int nSimWords ) -{ - int k; - for ( k = 0; k < nSimWords; k++ ) - if ( pPats1[k] != pPats2[k] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if Node1 implies Node2.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_UtilInfoIsImp( unsigned * pPats1, unsigned * pPats2, int nSimWords ) -{ - int k; - for ( k = 0; k < nSimWords; k++ ) - if ( pPats1[k] & ~pPats2[k] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if Node1 v Node2 is always true.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_UtilInfoIsClause( unsigned * pPats1, unsigned * pPats2, int nSimWords ) -{ - int k; - for ( k = 0; k < nSimWords; k++ ) - if ( ~pPats1[k] & ~pPats2[k] ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Counts the total number of pairs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_UtilCountAllPairs( Vec_Ptr_t * vSuppFun, int nSimWords, Vec_Int_t * vCounters ) -{ - unsigned * pSupp; - int Counter, nOnes, nPairs, i; - Counter = 0; - Vec_PtrForEachEntry( vSuppFun, pSupp, i ) - { - nOnes = Sim_UtilCountOnes( pSupp, nSimWords ); - nPairs = nOnes * (nOnes - 1) / 2; - Vec_IntWriteEntry( vCounters, i, nPairs ); - Counter += nPairs; - } - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of entries in the array of matrices.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_UtilCountPairsOne( Extra_BitMat_t * pMat, Vec_Int_t * vSupport ) -{ - int i, k, Index1, Index2; - int Counter = 0; -// int Counter2; - Vec_IntForEachEntry( vSupport, i, Index1 ) - Vec_IntForEachEntryStart( vSupport, k, Index2, Index1+1 ) - Counter += Extra_BitMatrixLookup1( pMat, i, k ); -// Counter2 = Extra_BitMatrixCountOnesUpper(pMat); -// assert( Counter == Counter2 ); - return Counter; -} - -/**Function************************************************************* - - Synopsis [Counts the number of entries in the array of matrices.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_UtilCountPairsOnePrint( Extra_BitMat_t * pMat, Vec_Int_t * vSupport ) -{ - int i, k, Index1, Index2; - Vec_IntForEachEntry( vSupport, i, Index1 ) - Vec_IntForEachEntryStart( vSupport, k, Index2, Index1+1 ) - if ( Extra_BitMatrixLookup1( pMat, i, k ) ) - printf( "(%d,%d) ", i, k ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Counts the number of entries in the array of matrices.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilCountPairsAllPrint( Sym_Man_t * p ) -{ - int i, clk; -clk = clock(); - for ( i = 0; i < p->nOutputs; i++ ) - { - printf( "Output %2d :", i ); - Sim_UtilCountPairsOnePrint( Vec_PtrEntry(p->vMatrSymms, i), Vec_VecEntry(p->vSupports, i) ); - printf( "\n" ); - } -p->timeCount += clock() - clk; -} - -/**Function************************************************************* - - Synopsis [Counts the number of entries in the array of matrices.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sim_UtilCountPairsAll( Sym_Man_t * p ) -{ - int nPairsTotal, nPairsSym, nPairsNonSym, i, clk; -clk = clock(); - p->nPairsSymm = 0; - p->nPairsNonSymm = 0; - for ( i = 0; i < p->nOutputs; i++ ) - { - nPairsTotal = Vec_IntEntry(p->vPairsTotal, i); - nPairsSym = Vec_IntEntry(p->vPairsSym, i); - nPairsNonSym = Vec_IntEntry(p->vPairsNonSym,i); - assert( nPairsTotal >= nPairsSym + nPairsNonSym ); - if ( nPairsTotal == nPairsSym + nPairsNonSym ) - { - p->nPairsSymm += nPairsSym; - p->nPairsNonSymm += nPairsNonSym; - continue; - } - nPairsSym = Sim_UtilCountPairsOne( Vec_PtrEntry(p->vMatrSymms, i), Vec_VecEntry(p->vSupports, i) ); - nPairsNonSym = Sim_UtilCountPairsOne( Vec_PtrEntry(p->vMatrNonSymms,i), Vec_VecEntry(p->vSupports, i) ); - assert( nPairsTotal >= nPairsSym + nPairsNonSym ); - Vec_IntWriteEntry( p->vPairsSym, i, nPairsSym ); - Vec_IntWriteEntry( p->vPairsNonSym, i, nPairsNonSym ); - p->nPairsSymm += nPairsSym; - p->nPairsNonSymm += nPairsNonSym; -// printf( "%d ", nPairsTotal - nPairsSym - nPairsNonSym ); - } -//printf( "\n" ); - p->nPairsRem = p->nPairsTotal-p->nPairsSymm-p->nPairsNonSymm; -p->timeCount += clock() - clk; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sim_UtilMatrsAreDisjoint( Sym_Man_t * p ) -{ - int i; - for ( i = 0; i < p->nOutputs; i++ ) - if ( !Extra_BitMatrixIsDisjoint( Vec_PtrEntry(p->vMatrSymms,i), Vec_PtrEntry(p->vMatrNonSymms,i) ) ) - return 0; - return 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/phys/place/Makefile b/src/phys/place/Makefile deleted file mode 100644 index 1f700105..00000000 --- a/src/phys/place/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -TARGETS = place_test BookshelfView.class - -CFLAGS = -g -pedantic -Wall - -STATIC_LIBS = libhmetis.a -DYNAMIC_LIBS = -lm - -OBJECTS = place_test.o place_qpsolver.o place_base.o place_pads.o place_genqp.o place_gordian.o \ - place_partition.o place_legalize.o place_bin.o - - -# For hMetis free code, uncomment the following lines -# -# CFLAGS = -g -pedantic -Wall -DNO_HMETIS -# STATIC_LIBS = - - -all: $(TARGETS) - -%.o: %.c *.h - gcc $(CFLAGS) -c -o $@ $< - -place_test: $(OBJECTS) - gcc *.o $(STATIC_LIBS) $(DYNAMIC_LIBS) -o place_test - -BookshelfView.class: BookshelfView.java - javac BookshelfView.java - -clean: - rm -rf *.o place_test *.class *~ diff --git a/src/phys/place/README b/src/phys/place/README deleted file mode 100644 index d4f8ac8f..00000000 --- a/src/phys/place/README +++ /dev/null @@ -1,50 +0,0 @@ -/*===================================================================*/ -// -// GORDIAN-like placement package -// -// Aaron P. Hurst (ahurst@eecs.berkeley.edu) -// Addl code from Philip Chong (pchong@cadence.com) -// hMetis partitioner (www.cs.umn.edu/~metis) -// -/*===================================================================*/ - -1. Requirements - -An i386 Linux system (though others will certainly work with some tweaks). -A standard ANSI C development platform. - -The following are optional, but useful: - -- hMetis partitioner. This can be obtained from (www.cs.umn.edu/~metis) - Place (links to) the files "libhmetis.a" and "libhtmetis.h" in this directory. - Otherwise, #define NO_HMETIS in the file "place_gordian.h" -- Java SDK, if compiling BookshelfView is desired. -- Perl, if additional script utilities are desired. - -2. Descriptions of contents: - -place_base.h contains the basic data structures and "external" API. -place_gordian.h contains the "internal" API and configuration options. - -There are also several utilities: - -i) place_test - -Reads a netlist description in GSRC Bookshelf format, performs global placement, -and rewrites the placement file. An example usage: - -./place_test ac97_emap.nodes ac97_emap.nets ac97_emap.pl - -ii) BookshelfView - -A simple Java GUI to view the resulting placements. It has been tested with -Java 5 and 6. Usage: - -java BookshelfView ac97_emap.nodes ac97_emap.pl - -iii) hpwl - -A perl script to print the half-perimeter wirelength of a placement. Usage: - -./hpwl ac97_emap.nets ac97_emal.pl - diff --git a/src/phys/place/hpwl b/src/phys/place/hpwl deleted file mode 100644 index f69a1d05..00000000 --- a/src/phys/place/hpwl +++ /dev/null @@ -1,57 +0,0 @@ -#! /usr/bin/perl - -$netsfile = shift; -$plfile = shift; - -# ------------------------------ read placement - -open FILE, $plfile; -while () { - chop; - if (/(\w+)\s+([\-\d\.]+)\s+([\-\d\.]+)\s+\:/) { - $loc{$1} = "$2 $3"; - } -} -close FILE; - -open FILE, $netsfile; -while () { - chop; - $net = $2 if /NetDegree\s+\:\s+(\d+)\s+(\w+)/; - if (/(\w+)\s+(\w+)\s+\:/) { - $netconn{$net} .= "$1 "; - $cellconn{$1} .= "$net "; - } -} -close FILE; - -# ----------------------------- compute HPWL - -$hpwl = 0; -foreach $net (keys %netconn) { - @conns = split ' ',$netconn{$net}; - $min_x = $min_y = 1e12; - $max_x = $max_y = -1e12; - foreach $cell (@conns) { - if (!exists $loc{$cell}) { - print "WARNING: Unknown cell location: $cell\n"; - } else { - ($x, $y) = split ' ',$loc{$cell}; - $min_x = $x if $x < $min_x; - $min_y = $y if $y < $min_y; - $max_x = $x if $x > $max_x; - $max_y = $y if $y > $max_y; - } - } - - if ($min_x eq 1e12 or $min_y eq 1e12 or - $max_x eq -1e12 or $max_y eq -1e12) { - print "WARNING: Unbounded box\n"; - } else { - $hpwl = $hpwl + $max_x - $min_x + $max_y - $min_y; - } -} - -print "HPWL = "; -printf "%e",$hpwl; -print "\n"; diff --git a/src/phys/place/libhmetis.h b/src/phys/place/libhmetis.h deleted file mode 100644 index 051079d4..00000000 --- a/src/phys/place/libhmetis.h +++ /dev/null @@ -1,31 +0,0 @@ -// A. Hurst ahurst@eecs.berkeley.edu - -#ifndef LIBHMETIS_H_ -#define LIBHMETIS_H_ - -static void HMETIS_PartRecursive(int nvtxs, - int nhedges, - int *vwgts, - int *eptr, - int *eind, - int *hewgts, - int nparts, - int nbfactor, - int *options, - int *part, - int *edgecnt ) {} //; - - -static void HMETIS_PartKway(int nvtxs, - int nhedges, - int *vwgts, - int *eptr, - int *eind, - int *hewgts, - int nparts, - int nbfactor, - int *options, - int *part, - int *edgecnt ) {} //; - -#endif diff --git a/src/phys/place/module.make b/src/phys/place/module.make deleted file mode 100644 index 98930fbe..00000000 --- a/src/phys/place/module.make +++ /dev/null @@ -1,10 +0,0 @@ -SRC += src/phys/place/place_base.c \ - src/phys/place/place_bin.c \ - src/phys/place/place_genqp.c \ - src/phys/place/place_gordian.c \ - src/phys/place/place_legalize.c \ - src/phys/place/place_pads.c \ - src/phys/place/place_partition.c \ - src/phys/place/place_qpsolver.c \ - src/phys/place/place_io.c \ - src/phys/place/place_inc.c diff --git a/src/phys/place/place_base.c b/src/phys/place/place_base.c deleted file mode 100644 index 4e38f1d1..00000000 --- a/src/phys/place/place_base.c +++ /dev/null @@ -1,345 +0,0 @@ -/*===================================================================*/ -// -// place_base.c -// -// Aaron P. Hurst, 2003-2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#include -#include -#include -#include - -#include "place_base.h" -#include "place_gordian.h" - -// -------------------------------------------------------------------- -// Global variables -// -// -------------------------------------------------------------------- - -int g_place_numCells = 0; -int g_place_numNets = 0; -float g_place_rowHeight = 1.0; - -Rect g_place_coreBounds; -Rect g_place_padBounds; - -ConcreteCell **g_place_concreteCells = NULL; -int g_place_concreteCellsSize = 0; -ConcreteNet **g_place_concreteNets = NULL; -int g_place_concreteNetsSize = 0; - - -// -------------------------------------------------------------------- -// getNetBBox() -// -/// \brief Returns the bounding box of a net. -// -// -------------------------------------------------------------------- -Rect getNetBBox(const ConcreteNet *net) { - int t; - Rect r; - - assert(net); - - r.x = r.y = INT_MAX; - r.w = r.h = -INT_MAX; - for(t=0; tm_numTerms; t++) { - r.x = net->m_terms[t]->m_x < r.x ? net->m_terms[t]->m_x : r.x; - r.y = net->m_terms[t]->m_y < r.y ? net->m_terms[t]->m_y : r.y; - r.w = net->m_terms[t]->m_x > r.w ? net->m_terms[t]->m_x : r.w; - r.h = net->m_terms[t]->m_y > r.h ? net->m_terms[t]->m_y : r.h; - } - r.w -= r.x; r.h -= r.y; - return r; -} - - -// -------------------------------------------------------------------- -// getNetWirelength() -// -/// \brief Returns the half-perimeter wirelength of a net. -// -// -------------------------------------------------------------------- -float getNetWirelength(const ConcreteNet *net) { - Rect r; - - assert(net); - - r = getNetBBox(net); - return r.w+r.h; -} - - -// -------------------------------------------------------------------- -// getTotalWirelength() -// -/// \brief Returns the total HPWL of all nets. -// -// -------------------------------------------------------------------- -float getTotalWirelength() { - float r = 0; - int n; - for(n=0; nm_parent->m_width*cell->m_parent->m_height; -} - - -// -------------------------------------------------------------------- -// addConcreteNet() -// -/// \brief Adds a net to the placement database. -/// -/// The net object must already be allocated and the ID must be set -/// appropriately. -// -// -------------------------------------------------------------------- -void addConcreteNet(ConcreteNet *net) { - assert(net); - assert(net->m_id >= 0); - if (net->m_id >= g_place_concreteNetsSize) { - g_place_concreteNetsSize = (net->m_id > g_place_concreteNetsSize ? - net->m_id : g_place_concreteNetsSize); - g_place_concreteNetsSize *= 1.5; - g_place_concreteNetsSize += 20; - g_place_concreteNets = (ConcreteNet**)realloc(g_place_concreteNets, - sizeof(ConcreteNet*)*g_place_concreteNetsSize); - assert(g_place_concreteNets); - } - if (net->m_id >= g_place_numNets) { - memset(&(g_place_concreteNets[g_place_numNets]), 0, - sizeof(ConcreteNet*)*(net->m_id+1-g_place_numNets)); - g_place_numNets = net->m_id+1; - assert(g_place_numNets <= g_place_concreteNetsSize); - } - g_place_concreteNets[net->m_id] = net; -} - - -// -------------------------------------------------------------------- -// delConcreteNet() -// -/// Does not deallocate memory. -// -------------------------------------------------------------------- -void delConcreteNet(ConcreteNet *net) { - assert(net); - g_place_concreteNets[net->m_id] = 0; - while(!g_place_concreteNets[g_place_numNets-1]) g_place_numNets--; -} - - -// -------------------------------------------------------------------- -// addConcreteCell() -// -/// The cell object must already be allocated and the ID must be set -/// appropriately. -// -// -------------------------------------------------------------------- -void addConcreteCell(ConcreteCell *cell) { - assert(cell); - assert(cell->m_id >= 0); - if (cell->m_id >= g_place_concreteCellsSize) { - g_place_concreteCellsSize = (cell->m_id > g_place_concreteCellsSize ? - cell->m_id : g_place_concreteCellsSize); - g_place_concreteCellsSize *= 1.5; - g_place_concreteCellsSize += 20; - g_place_concreteCells = (ConcreteCell**)realloc(g_place_concreteCells, - sizeof(ConcreteCell*)*g_place_concreteCellsSize); - assert(g_place_concreteCells); - } - if (cell->m_id >= g_place_numCells) { - memset(&(g_place_concreteCells[g_place_numCells]), 0, - sizeof(ConcreteCell*)*(cell->m_id+1-g_place_numCells)); - g_place_numCells = cell->m_id+1; - } - g_place_concreteCells[cell->m_id] = cell; -} - - -// -------------------------------------------------------------------- -// delCellFromPartition() -// -// -------------------------------------------------------------------- -void delCellFromPartition(ConcreteCell *cell, Partition *p) { - int c; - bool found = false; - - assert(cell); - assert(p); - - for(c=0; cm_numMembers; c++) - if (p->m_members[c] == cell) { - p->m_members[c] = 0; - p->m_area -= getCellArea(cell); - found = true; - break; - } - - if (!found) return; - - if (!p->m_leaf) { - delCellFromPartition(cell, p->m_sub1); - delCellFromPartition(cell, p->m_sub2); - } -} - - -// -------------------------------------------------------------------- -// delConcreteCell() -// -/// \brief Removes a cell from the placement database. -/// -/// Does not deallocate memory. -/// -/// Important: does not modify nets that may point to this -/// cell. If these are connections are not removed, segmentation faults -/// and other nasty errors will occur. -// -// -------------------------------------------------------------------- -void delConcreteCell(ConcreteCell *cell) { - assert(cell); - g_place_concreteCells[cell->m_id] = 0; - while(!g_place_concreteCells[g_place_numCells-1]) g_place_numCells--; - - if (g_place_rootPartition) delCellFromPartition(cell, g_place_rootPartition); -} - - -// -------------------------------------------------------------------- -// netSortByX... -// -/// \brief Sorts nets by position of one of its corners. -// -/// These are for use with qsort(). -/// -/// Can tolerate pointers to NULL objects. -/// -// -------------------------------------------------------------------- -int netSortByL(const void *a, const void *b) { - const ConcreteNet *pa = *(const ConcreteNet **)a; - const ConcreteNet *pb = *(const ConcreteNet **)b; - Rect ba, bb; - - if (!pa && !pb) return 0; - else if (!pa) return -1; - else if (!pb) return 1; - ba = getNetBBox(pa), bb = getNetBBox(pb); - if (ba.x < bb.x) return -1; - if (ba.x > bb.x) return 1; - return 0; -} - -int netSortByR(const void *a, const void *b) { - const ConcreteNet *pa = *(const ConcreteNet **)a; - const ConcreteNet *pb = *(const ConcreteNet **)b; - Rect ba, bb; - - if (!pa && !pb) return 0; - else if (!pa) return -1; - else if (!pb) return 1; - ba = getNetBBox(pa), bb = getNetBBox(pb); - if (ba.x + ba.w < bb.x + bb.w) return -1; - if (ba.x + ba.w > bb.x + bb.w) return 1; - return 0; -} - -int netSortByB(const void *a, const void *b) { - const ConcreteNet *pa = *(const ConcreteNet **)a; - const ConcreteNet *pb = *(const ConcreteNet **)b; - Rect ba, bb; - - if (!pa && !pb) return 0; - else if (!pa) return -1; - else if (!pb) return 1; - ba = getNetBBox(pa), bb = getNetBBox(pb); - if (ba.y + ba.h < bb.y + bb.h) return -1; - if (ba.y + ba.h > bb.y + bb.h) return 1; - return 0; -} - -int netSortByT(const void *a, const void *b) { - const ConcreteNet *pa = *(const ConcreteNet **)a; - const ConcreteNet *pb = *(const ConcreteNet **)b; - Rect ba, bb; - - if (!pa && !pb) return 0; - else if (!pa) return -1; - else if (!pb) return 1; - ba = getNetBBox(pa), bb = getNetBBox(pb); - if (ba.y < bb.y) return -1; - if (ba.y > bb.y) return 1; - return 0; -} - -int netSortByID(const void *a, const void *b) { - const ConcreteNet *pa = *(const ConcreteNet **)a; - const ConcreteNet *pb = *(const ConcreteNet **)b; - - if (!pa && !pb) return 0; - else if (!pa) return -1; - else if (!pb) return 1; - if (pa->m_id < pb->m_id) return -1; - if (pa->m_id > pb->m_id) return 1; - return 0; -} - - -// -------------------------------------------------------------------- -// cellSortByX... -// -/// \brief Sorts cells by either position coordinate. -// -/// These are for use with qsort(). -/// -/// Can tolerate pointers to NULL objects. -// -// -------------------------------------------------------------------- -int cellSortByX(const void *a, const void *b) { - const ConcreteCell *pa = *(const ConcreteCell **)a; - const ConcreteCell *pb = *(const ConcreteCell **)b; - - if (!pa && !pb) return 0; - else if (!pa) return -1; - else if (!pb) return 1; - if (pa->m_x < pb->m_x) return -1; - if (pa->m_x > pb->m_x) return 1; - return 0; -} - -int cellSortByY(const void *a, const void *b) { - const ConcreteCell *pa = *(const ConcreteCell **)a; - const ConcreteCell *pb = *(const ConcreteCell **)b; - - if (!pa && !pb) return 0; - else if (!pa) return -1; - else if (!pb) return 1; - if (pa->m_y < pb->m_y) return -1; - if (pa->m_y > pb->m_y) return 1; - return 0; -} - -int cellSortByID(const void *a, const void *b) { - const ConcreteCell *pa = *(const ConcreteCell **)a; - const ConcreteCell *pb = *(const ConcreteCell **)b; - - if (!pa && !pb) return 0; - else if (!pa) return -1; - else if (!pb) return 1; - if (pa->m_id < pb->m_id) return -1; - if (pa->m_id > pb->m_id) return 1; - return 0; -} diff --git a/src/phys/place/place_base.h b/src/phys/place/place_base.h deleted file mode 100644 index e5e7ecef..00000000 --- a/src/phys/place/place_base.h +++ /dev/null @@ -1,137 +0,0 @@ -/*===================================================================*/ -// -// place_base.h -// -// Aaron P. Hurst, 2003-2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#if !defined(PLACE_BASE_H_) -#define PLACE_BASE_H_ - -// -------------------------------------------------------------------- -// Data structures -// -// -------------------------------------------------------------------- - -// --- a C++ bool-like type -//typedef char bool; -#ifndef bool -#define bool int -#endif - -#define true 1 -#define false 0 - - -// --- Rect - rectangle - -typedef struct Rect { - float x, y; - float w, h; -} Rect; - - -// --- AbstractCell - a definition of a cell type - -typedef struct AbstractCell { - char *m_label; // string description - - float m_width, m_height; // dimensions - - bool m_pad; // a pad (external I/O) cell? -} AbstractCell; - - -// --- ConcreteCell - a design object - -typedef struct ConcreteCell { - int m_id; // a unique ID (see below) - char *m_label; // string description - - AbstractCell *m_parent; // cell type - - bool m_fixed; // position is fixed? - float m_x, m_y; // center of cell - - int m_data; -} ConcreteCell; - - -// --- ConcreteNet - a design net - -typedef struct ConcreteNet { - int m_id; // a unique ID (see below) - - int m_numTerms; // num. of connected cells - ConcreteCell **m_terms; // connected cells - - float m_weight; // relative weight - - int m_data; -} ConcreteNet; - - -// A note about IDs - the IDs are non-nonegative integers. They need not -// be contiguous, but this is certainly a good idea, as they are stored -// in a non-sparse array. -// Cells and nets have separate ID spaces. - -// -------------------------------------------------------------------- -// Global variable prototypes -// -// -------------------------------------------------------------------- - -// NOTE: None of these need to be managed externally. - -extern int g_place_numCells; // number of cells -extern int g_place_numNets; // number of nets -extern float g_place_rowHeight; // height of placement row -extern Rect g_place_coreBounds; // border of placeable area - // (x,y) = corner -extern Rect g_place_padBounds; // border of total die area - // (x,y) = corner - -extern ConcreteCell **g_place_concreteCells; // all concrete cells -extern ConcreteNet **g_place_concreteNets; // all concrete nets - - -// -------------------------------------------------------------------- -// Function prototypes -// -// -------------------------------------------------------------------- - -void addConcreteNet(ConcreteNet *net); -void addConcreteCell(ConcreteCell *cell); -void delConcreteNet(ConcreteNet *net); -void delConcreteCell(ConcreteCell *cell); - -void globalPreplace(float utilization); -void globalPlace(); -void globalIncremental(); -void globalFixDensity(int numBins, float maxMovement); - -float fastEstimate(ConcreteCell *cell, - int numNets, ConcreteNet *nets[]); -float fastTopoPlace(int numCells, ConcreteCell *cells[], - int numNets, ConcreteNet *nets[]); - -Rect getNetBBox(const ConcreteNet *net); -float getNetWirelength(const ConcreteNet *net); -float getTotalWirelength(); -float getCellArea(const ConcreteCell *cell); - -void writeBookshelf(const char *filename); - -// comparative qsort-style functions -int netSortByL(const void *a, const void *b); -int netSortByR(const void *a, const void *b); -int netSortByB(const void *a, const void *b); -int netSortByT(const void *a, const void *b); -int netSortByID(const void *a, const void *b); -int cellSortByX(const void *a, const void *b); -int cellSortByY(const void *a, const void *b); -int cellSortByID(const void *a, const void *b); - -#endif diff --git a/src/phys/place/place_bin.c b/src/phys/place/place_bin.c deleted file mode 100644 index 86ec3506..00000000 --- a/src/phys/place/place_bin.c +++ /dev/null @@ -1,277 +0,0 @@ -/*===================================================================*/ -// -// place_bin.c -// -// Aaron P. Hurst, 2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#include -#include -#include -#include -#include - -//#define DEBUG - -#include "place_base.h" - -// -------------------------------------------------------------------- -// Global variables -// -// -------------------------------------------------------------------- - - -// -------------------------------------------------------------------- -// Function prototypes and local data structures -// -// -------------------------------------------------------------------- - -void spreadDensityX(int numBins, float maxMovement); -void spreadDensityY(int numBins, float maxMovement); - - -// -------------------------------------------------------------------- -// globalFixDensity() -// -/// Doesn't deal well with fixed cells in the core area. -// -------------------------------------------------------------------- -void globalFixDensity(int numBins, float maxMovement) { - - printf("QCLN-10 : \tbin-based density correction\n"); - - spreadDensityX(numBins, maxMovement); - // spreadDensityY(numBins, maxMovement); -} - - -// -------------------------------------------------------------------- -// spreadDensityX() -// -// -------------------------------------------------------------------- -void spreadDensityX(int numBins, float maxMovement) { - - int c, c2, c3, x, y; - float totalArea = 0; - int moveableCells = 0; - float yBinArea = 0, yCumArea = 0; - int yBinStart = 0, yBinCount = 0; - int xBinCount, xBinStart; - float xBinArea, xCumArea; - float lastOldEdge; - float lastNewEdge; - float curOldEdge, curNewEdge; - float stretch, w; - ConcreteCell *xCell, *yCell; - ConcreteCell **binCells; - ConcreteCell **allCells; - - binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); - allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); - - for(c=0; cm_fixed && !cell->m_parent->m_pad) { - allCells[moveableCells++] = cell; - totalArea += getCellArea(cell); - } - } - - // spread X - qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByY); - - y = 0; - - // for each y-bin... - for(c=0; c= totalArea*(y+1)/numBins && yBinArea > 0) { - memcpy(binCells, &(allCells[yBinStart]), sizeof(ConcreteCell*)*yBinCount); - qsort(binCells, yBinCount, sizeof(ConcreteCell*), cellSortByX); - -#if defined(DEBUG) - printf("y-bin %d count=%d area=%f\n",y,yBinCount, yBinArea); -#endif - - x = 0; - xBinCount = 0, xBinStart = 0; - xBinArea = 0, xCumArea = 0; - lastOldEdge = g_place_coreBounds.x; - lastNewEdge = g_place_coreBounds.x; - - // for each x-bin... - for(c2=0; c2m_x; - - printf("%.3f ", xCell->m_x); - - // have we filled up an x-bin? - if (xCumArea >= yBinArea*(x+1)/numBins && xBinArea > 0) { - curNewEdge = lastNewEdge + g_place_coreBounds.w*xBinArea/yBinArea; - - if (curNewEdge > g_place_coreBounds.x+g_place_coreBounds.w) - curNewEdge = g_place_coreBounds.x+g_place_coreBounds.w; - if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement; - if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement; - -#if defined(DEBUG) - printf("->\tx-bin %d count=%d area=%f (%f,%f)->(%f,%f)\n",x, xBinCount, xBinArea, - curOldEdge, lastOldEdge, curNewEdge, lastNewEdge); -#endif - - stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge); - - // stretch! - for(c3=xBinStart; c3m_x = lastNewEdge+(c3-xBinStart)*(curNewEdge-lastNewEdge); - else - binCells[c3]->m_x = lastNewEdge+(binCells[c3]->m_x-lastOldEdge)*stretch; - - // force within core - w = binCells[c3]->m_parent->m_width*0.5; - if (binCells[c3]->m_x-w < g_place_coreBounds.x) - binCells[c3]->m_x = g_place_coreBounds.x+w; - if (binCells[c3]->m_x+w > g_place_coreBounds.x+g_place_coreBounds.w) - binCells[c3]->m_x = g_place_coreBounds.x+g_place_coreBounds.w-w; - } - - lastOldEdge = curOldEdge; - lastNewEdge = curNewEdge; - x++; - xBinCount = 0; - xBinArea = 0; - xBinStart = c2+1; - } - } - - y++; - yBinCount = 0; - yBinArea = 0; - yBinStart = c+1; - } - } - - free(binCells); - free(allCells); -} - - -// -------------------------------------------------------------------- -// spreadDensityY() -// -// -------------------------------------------------------------------- -void spreadDensityY(int numBins, float maxMovement) { - - int c, c2, c3, x, y; - float totalArea = 0; - int moveableCells = 0; - float xBinArea = 0, xCumArea = 0; - int xBinStart = 0, xBinCount = 0; - int yBinCount, yBinStart; - float yBinArea, yCumArea; - float lastOldEdge; - float lastNewEdge; - float curOldEdge, curNewEdge; - float stretch, h; - ConcreteCell *xCell, *yCell; - ConcreteCell **binCells; - ConcreteCell **allCells; - - binCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); - allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); - - for(c=0; cm_fixed && !cell->m_parent->m_pad) { - allCells[moveableCells++] = cell; - totalArea += getCellArea(cell); - } - } - - // spread Y - qsort(allCells, moveableCells, sizeof(ConcreteCell*), cellSortByX); - - x = 0; - - // for each x-bin... - for(c=0; c= totalArea*(x+1)/numBins && xBinArea > 0) { - memcpy(binCells, &(allCells[xBinStart]), sizeof(ConcreteCell*)*xBinCount); - qsort(binCells, xBinCount, sizeof(ConcreteCell*), cellSortByY); - - // printf("x-bin %d count=%d area=%f\n",y,yBinCount, yBinArea); - - y = 0; - yBinCount = 0, yBinStart = 0; - yBinArea = 0, yCumArea = 0; - lastOldEdge = g_place_coreBounds.y; - lastNewEdge = g_place_coreBounds.y; - - // for each y-bin... - for(c2=0; c2m_y; - - // have we filled up an x-bin? - if (yCumArea >= xBinArea*(y+1)/numBins && yBinArea > 0) { - curNewEdge = lastNewEdge + g_place_coreBounds.h*yBinArea/xBinArea; - - if (curNewEdge > g_place_coreBounds.y+g_place_coreBounds.h) - curNewEdge = g_place_coreBounds.y+g_place_coreBounds.h; - if ((curNewEdge-curOldEdge)>maxMovement) curNewEdge = curOldEdge + maxMovement; - if ((curOldEdge-curNewEdge)>maxMovement) curNewEdge = curOldEdge - maxMovement; - - if (curOldEdge == lastOldEdge) continue; // hmmm - stretch = (curNewEdge-lastNewEdge)/(curOldEdge-lastOldEdge); - - // stretch! - for(c3=yBinStart; c3m_y = lastNewEdge+(binCells[c3]->m_y-lastOldEdge)*stretch; - - // force within core - h = binCells[c3]->m_parent->m_height; - if (binCells[c3]->m_y-h < g_place_coreBounds.y) - binCells[c3]->m_y = g_place_coreBounds.y+h; - if (binCells[c3]->m_y+h > g_place_coreBounds.y+g_place_coreBounds.h) - binCells[c3]->m_y = g_place_coreBounds.y+g_place_coreBounds.h-h; - } - - lastOldEdge = curOldEdge; - lastNewEdge = curNewEdge; - y++; - yBinCount = 0; - yBinArea = 0; - yBinStart = c2+1; - } - } - - x++; - xBinCount = 0; - xBinArea = 0; - xBinStart = c+1; - } - } - - free(binCells); - free(allCells); -} diff --git a/src/phys/place/place_genqp.c b/src/phys/place/place_genqp.c deleted file mode 100644 index 5b6c7027..00000000 --- a/src/phys/place/place_genqp.c +++ /dev/null @@ -1,309 +0,0 @@ -/*===================================================================*/ -// -// place_genqp.c -// -// Aaron P. Hurst, 2003-2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#include -#include -#include -#include -#include - -#include "place_base.h" -#include "place_qpsolver.h" -#include "place_gordian.h" - -// -------------------------------------------------------------------- -// Global variables -// -// -------------------------------------------------------------------- - -qps_problem_t *g_place_qpProb = NULL; - - -// -------------------------------------------------------------------- -// splitPenalty() -// -/// \brief Returns a weight for all of the edges in the clique for a multipin net. -// -// -------------------------------------------------------------------- -float splitPenalty(int pins) { - - if (pins > 1) { - return 1.0 + CLIQUE_PENALTY/(pins - 1); - // return pow(pins - 1, CLIQUE_PENALTY); - } - return 1.0 + CLIQUE_PENALTY; -} - - -// -------------------------------------------------------------------- -// constructQuadraticProblem() -// -/// \brief Constructs the matrices necessary to do analytical placement. -// -// -------------------------------------------------------------------- -void constructQuadraticProblem() { - int maxConnections = 1; - int ignoreNum = 0; - int n,t,c,c2,p; - ConcreteCell *cell; - ConcreteNet *net; - int *cell_numTerms = calloc(g_place_numCells, sizeof(int)); - ConcreteNet ***cell_terms = calloc(g_place_numCells, sizeof(ConcreteNet**)); - bool incremental = false; - int nextIndex = 1; - int *seen = calloc(g_place_numCells, sizeof(int)); - float weight; - int last_index; - - // create problem object - if (!g_place_qpProb) { - g_place_qpProb = malloc(sizeof(qps_problem_t)); - g_place_qpProb->area = NULL; - g_place_qpProb->x = NULL; - g_place_qpProb->y = NULL; - g_place_qpProb->fixed = NULL; - g_place_qpProb->connect = NULL; - g_place_qpProb->edge_weight = NULL; - } - - // count the maximum possible number of non-sparse entries - for(n=0; nm_numTerms > IGNORE_NETSIZE) { - ignoreNum++; - } - else { - maxConnections += net->m_numTerms*(net->m_numTerms-1); - for(t=0; tm_numTerms; t++) { - c = net->m_terms[t]->m_id; - p = ++cell_numTerms[c]; - cell_terms[c] = (ConcreteNet**)realloc(cell_terms[c], p*sizeof(ConcreteNet*)); - cell_terms[c][p-1] = net; - } - } - } - if(ignoreNum) { - printf("QMAN-10 : \t\t%d large nets ignored\n", ignoreNum); - } - - // initialize the data structures - g_place_qpProb->num_cells = g_place_numCells; - maxConnections += g_place_numCells + 1; - - g_place_qpProb->area = realloc(g_place_qpProb->area, - sizeof(float)*g_place_numCells);// "area" matrix - g_place_qpProb->edge_weight = realloc(g_place_qpProb->edge_weight, - sizeof(float)*maxConnections); // "weight" matrix - g_place_qpProb->connect = realloc(g_place_qpProb->connect, - sizeof(int)*maxConnections); // "connectivity" matrix - g_place_qpProb->fixed = realloc(g_place_qpProb->fixed, - sizeof(int)*g_place_numCells); // "fixed" matrix - - // initialize or keep preexisting locations - if (g_place_qpProb->x != NULL && g_place_qpProb->y != NULL) { - printf("QMAN-10 :\tperforming incremental placement\n"); - incremental = true; - } - g_place_qpProb->x = (float*)realloc(g_place_qpProb->x, sizeof(float)*g_place_numCells); - g_place_qpProb->y = (float*)realloc(g_place_qpProb->y, sizeof(float)*g_place_numCells); - - // form a row for each cell - // build data - for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) { - cell = g_place_concreteCells[c]; - - // fill in the characteristics for this cell - g_place_qpProb->area[c] = getCellArea(cell); - if (cell->m_fixed || cell->m_parent->m_pad) { - g_place_qpProb->x[c] = cell->m_x; - g_place_qpProb->y[c] = cell->m_y; - g_place_qpProb->fixed[c] = 1; - } else { - if (!incremental) { - g_place_qpProb->x[c] = g_place_coreBounds.x+g_place_coreBounds.w*0.5; - g_place_qpProb->y[c] = g_place_coreBounds.y+g_place_coreBounds.h*0.5; - } - g_place_qpProb->fixed[c] = 0; - } - - // update connectivity matrices - last_index = nextIndex; - for(n=0; nm_weight / splitPenalty(net->m_numTerms); - for(t=0; tm_numTerms; t++) { - c2 = net->m_terms[t]->m_id; - if (c2 == c) continue; - if (seen[c2] < last_index) { - // not seen - g_place_qpProb->connect[nextIndex-1] = c2; - g_place_qpProb->edge_weight[nextIndex-1] = weight; - seen[c2] = nextIndex; - nextIndex++; - } else { - // seen - g_place_qpProb->edge_weight[seen[c2]-1] += weight; - } - } - } - g_place_qpProb->connect[nextIndex-1] = -1; - g_place_qpProb->edge_weight[nextIndex-1] = -1.0; - nextIndex++; - } else { - // fill in dummy values for connectivity matrices - g_place_qpProb->connect[nextIndex-1] = -1; - g_place_qpProb->edge_weight[nextIndex-1] = -1.0; - nextIndex++; - } - - free(cell_numTerms); - free(cell_terms); - free(seen); -} - -typedef struct reverseCOG { - float x,y; - Partition *part; - float delta; -} reverseCOG; - - -// -------------------------------------------------------------------- -// generateCoGConstraints() -// -/// \brief Generates center of gravity constraints. -// -// -------------------------------------------------------------------- -int generateCoGConstraints(reverseCOG COG_rev[]) { - int numConstraints = 0; // actual num contraints - int cogRevNum = 0; - Partition **stack = malloc(sizeof(Partition*)*g_place_numPartitions*2); - int stackPtr = 0; - Partition *p; - float cgx, cgy; - int next_index = 0, last_constraint = 0; - bool isTrueConstraint = false; - int i, m; - float totarea; - ConcreteCell *cell; - - // each partition may give rise to a center-of-gravity constraint - stack[stackPtr] = g_place_rootPartition; - while(stackPtr >= 0) { - p = stack[stackPtr--]; - assert(p); - - // traverse down the partition tree to leaf nodes-only - if (!p->m_leaf) { - stack[++stackPtr] = p->m_sub1; - stack[++stackPtr] = p->m_sub2; - } else { - /* - cout << "adding a COG constraint for box " - << p->bounds.x << "," - << p->bounds.y << " of size" - << p->bounds.w << "x" - << p->bounds.h - << endl; - */ - cgx = p->m_bounds.x + p->m_bounds.w*0.5; - cgy = p->m_bounds.y + p->m_bounds.h*0.5; - COG_rev[cogRevNum].x = cgx; - COG_rev[cogRevNum].y = cgy; - COG_rev[cogRevNum].part = p; - COG_rev[cogRevNum].delta = 0; - - cogRevNum++; - } - } - - assert(cogRevNum == g_place_numPartitions); - - for (i = 0; i < g_place_numPartitions; i++) { - p = COG_rev[i].part; - assert(p); - g_place_qpProb->cog_x[numConstraints] = COG_rev[i].x; - g_place_qpProb->cog_y[numConstraints] = COG_rev[i].y; - totarea = 0.0; - for(m=0; mm_numMembers; m++) if (p->m_members[m]) { - cell = p->m_members[m]; - assert(cell); - - if (!cell->m_fixed && !cell->m_parent->m_pad) { - isTrueConstraint = true; - } - else { - continue; - } - g_place_qpProb->cog_list[next_index++] = cell->m_id; - totarea += getCellArea(cell); - } - if (totarea == 0.0) { - isTrueConstraint = false; - } - if (isTrueConstraint) { - numConstraints++; - g_place_qpProb->cog_list[next_index++] = -1; - last_constraint = next_index; - } - else { - next_index = last_constraint; - } - } - - free(stack); - - return --numConstraints; -} - - -// -------------------------------------------------------------------- -// solveQuadraticProblem() -// -/// \brief Calls quadratic solver. -// -// -------------------------------------------------------------------- -void solveQuadraticProblem(bool useCOG) { - int c; - - reverseCOG *COG_rev = malloc(sizeof(reverseCOG)*g_place_numPartitions); - - g_place_qpProb->cog_list = malloc(sizeof(int)*(g_place_numPartitions+g_place_numCells)); - g_place_qpProb->cog_x = malloc(sizeof(float)*g_place_numPartitions); - g_place_qpProb->cog_y = malloc(sizeof(float)*g_place_numPartitions); - - // memset(g_place_qpProb->x, 0, sizeof(float)*g_place_numCells); - // memset(g_place_qpProb->y, 0, sizeof(float)*g_place_numCells); - - qps_init(g_place_qpProb); - - if (useCOG) - g_place_qpProb->cog_num = generateCoGConstraints(COG_rev); - else - g_place_qpProb->cog_num = 0; - - g_place_qpProb->loop_num = 0; - - qps_solve(g_place_qpProb); - - qps_clean(g_place_qpProb); - - // set the positions - for(c = 0; c < g_place_numCells; c++) if (g_place_concreteCells[c]) { - g_place_concreteCells[c]->m_x = g_place_qpProb->x[c]; - g_place_concreteCells[c]->m_y = g_place_qpProb->y[c]; - } - - // clean up - free(g_place_qpProb->cog_list); - free(g_place_qpProb->cog_x); - free(g_place_qpProb->cog_y); - - free(COG_rev); -} diff --git a/src/phys/place/place_gordian.c b/src/phys/place/place_gordian.c deleted file mode 100644 index 2929bf95..00000000 --- a/src/phys/place/place_gordian.c +++ /dev/null @@ -1,160 +0,0 @@ -/*===================================================================*/ -// -// place_gordian.c -// -// Aaron P. Hurst, 2003-2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#include -#include -#include -#include -#include - -#include "place_gordian.h" -#include "place_base.h" - - -// -------------------------------------------------------------------- -// Global variables -// -// -------------------------------------------------------------------- - -int g_place_numPartitions; - - -// -------------------------------------------------------------------- -// globalPlace() -// -/// \brief Performs analytic placement using a GORDIAN-like algorithm. -// -/// Updates the positions of all non-fixed non-pad cells. -/// -// -------------------------------------------------------------------- -void globalPlace() { - bool completionFlag = false; - int iteration = 0; - - printf("PLAC-10 : Global placement (wirelength-driven Gordian)\n"); - - initPartitioning(); - - // build matrices representing interconnections - printf("QMAN-00 : \tconstructing initial quadratic problem...\n"); - constructQuadraticProblem(); - - // iterate placement until termination condition is met - while(!completionFlag) { - printf("QMAN-01 : \titeration %d numPartitions = %d\n",iteration,g_place_numPartitions); - - // do the global optimization in each direction - printf("QMAN-01 : \t\tglobal optimization\n"); - solveQuadraticProblem(!IGNORE_COG); - - // -------- PARTITIONING BASED CELL SPREADING ------ - - // bisection - printf("QMAN-01 : \t\tpartition refinement\n"); - if (REALLOCATE_PARTITIONS) reallocPartitions(); - completionFlag |= refinePartitions(); - - printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); - - iteration++; - } - - // final global optimization - printf("QMAN-02 : \t\tfinal pass\n"); - if (FINAL_REALLOCATE_PARTITIONS) reallocPartitions(); - solveQuadraticProblem(!IGNORE_COG); - printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); - - // clean up - sanitizePlacement(); - printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); - globalFixDensity(25, g_place_rowHeight*5); - printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); -} - - -// -------------------------------------------------------------------- -// globalIncremental() -// -/// \brief Performs analytic placement using a GORDIAN-like algorithm. -// -/// Requires a valid set of partitions. -/// -// -------------------------------------------------------------------- - -void globalIncremental() { - if (!g_place_rootPartition) { - printf("WARNING: Can not perform incremental placement\n"); - globalPlace(); - return; - } - - printf("PLAC-10 : Incremental global placement\n"); - - incrementalPartition(); - - printf("QMAN-00 : \tconstructing initial quadratic problem...\n"); - constructQuadraticProblem(); - - solveQuadraticProblem(!IGNORE_COG); - printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); - - // clean up - sanitizePlacement(); - printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); - globalFixDensity(25, g_place_rowHeight*5); - printf("QMAN-01 : \t\twirelength = %e\n", getTotalWirelength()); -} - - -// -------------------------------------------------------------------- -// sanitizePlacement() -// -/// \brief Moves any cells that are outside of the core bounds to the nearest location within. -// -// -------------------------------------------------------------------- -void sanitizePlacement() { - int c; - float order_width = g_place_rowHeight; - float x, y, edge, w, h; - - printf("QCLN-10 : \tsanitizing placement\n"); - - for(c=0; cm_fixed || cell->m_parent->m_pad) { - continue; - } - // the new locations of the cells will be distributed within - // a small margin inside the border so that ordering is preserved - order_width = g_place_rowHeight; - - x = cell->m_x, y = cell->m_y, - w = cell->m_parent->m_width, h = cell->m_parent->m_height; - - if ((edge=x-w*0.5) < g_place_coreBounds.x) { - x = g_place_coreBounds.x+w*0.5 + - order_width/(1.0+g_place_coreBounds.x-edge); - } - else if ((edge=x+w*0.5) > g_place_coreBounds.x+g_place_coreBounds.w) { - x = g_place_coreBounds.x+g_place_coreBounds.w-w*0.5 - - order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w); - } - if ((edge=y-h*0.5) < g_place_coreBounds.y) { - y = g_place_coreBounds.y+h*0.5 + - order_width/(1.0+g_place_coreBounds.y-edge); - } - else if ((edge=y+h*0.5) > g_place_coreBounds.y+g_place_coreBounds.h) { - y = g_place_coreBounds.y+g_place_coreBounds.h-h*0.5 - - order_width/(1.0+edge-g_place_coreBounds.x-g_place_coreBounds.w); - } - cell->m_x = x; - cell->m_y = y; - } -} diff --git a/src/phys/place/place_gordian.h b/src/phys/place/place_gordian.h deleted file mode 100644 index 67eb1479..00000000 --- a/src/phys/place/place_gordian.h +++ /dev/null @@ -1,78 +0,0 @@ -/*===================================================================*/ -// -// place_gordian.h -// -// Aaron P. Hurst, 2003-2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#if !defined(PLACE_GORDIAN_H_) -#define PLACE_GORDIAN_H_ - -#include "place_base.h" -#include "place_qpsolver.h" - -// Parameters for analytic placement -#define CLIQUE_PENALTY 1.0 -#define IGNORE_NETSIZE 20 - -// Parameters for partitioning -#define LARGEST_FINAL_SIZE 20 -#define PARTITION_AREA_ONLY true -#define REALLOCATE_PARTITIONS false -#define FINAL_REALLOCATE_PARTITIONS false -#define IGNORE_COG false -#define MAX_PARTITION_NONSYMMETRY 0.30 - -// Parameters for re-partitioning -#define REPARTITION_LEVEL_DEPTH 4 -#define REPARTITION_TARGET_FRACTION 0.15 -#define REPARTITION_FM false -#define REPARTITION_HMETIS true - -// Parameters for F-M re-partitioning -#define FM_MAX_BIN 10 -#define FM_MAX_PASSES 10 - -extern int g_place_numPartitions; - -extern qps_problem_t *g_place_qpProb; - -typedef struct Partition { - - int m_numMembers; - ConcreteCell **m_members; - Rect m_bounds; - bool m_done, - m_leaf, - m_vertical; - float m_area; - int m_level; - struct Partition *m_sub1, *m_sub2; -} Partition; - -extern Partition *g_place_rootPartition; - -void initPartitioning(); - -void incrementalPartition(); - -bool refinePartitions(); -void reallocPartitions(); -bool refinePartition(Partition *p); -void resizePartition(Partition *p); -void reallocPartition(Partition *p); - -void repartitionHMetis(Partition *parent); -void repartitionFM(Partition *parent); - -void partitionScanlineMincut(Partition *parent); -void partitionEqualArea(Partition *parent); - -void sanitizePlacement(); - -void constructQuadraticProblem(); -void solveQuadraticProblem(bool useCOG); - -#endif diff --git a/src/phys/place/place_inc.c b/src/phys/place/place_inc.c deleted file mode 100644 index 7e2d847c..00000000 --- a/src/phys/place/place_inc.c +++ /dev/null @@ -1,106 +0,0 @@ -/*===================================================================*/ -// -// place_inc.c -// -// Aaron P. Hurst, 2003-2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#include -#include -#include -#include - -#include "place_base.h" -#include "place_gordian.h" - -inline int sqHashId(int id, int max) { - return ((id * (id+17)) % max); -} - -#if 0 -// -------------------------------------------------------------------- -// fastPlace() -// -/// The first cell is assumed to be the "output". -// -------------------------------------------------------------------- -float fastPlace(int numCells, ConcreteCell *cells[], - int numNets, ConcreteNet *nets[]) { - - int n, t, c, i, local_id = 0, pass; - const int NUM_PASSES = 4; - int *cell_numTerms = calloc(numCells, sizeof(int)); - ConcreteNet **cell_terms; - ConcreteNet *net; - Rect outputBox; - - outputBox = getNetBBox(nets[0]); - - // assign local ids - // put cells in reasonable initial location - for(n=0; nm_numTerms; t++) - nets[n]->m_terms[t]->m_data = -1; - - for(c=0; cm_data = local_id; - cells[c]->m_x = outputBox.x + 0.5*outputBox.w; - cells[c]->m_y = outputBox.y + 0.5*outputBox.h; - } - - // build reverse map of cells to nets - for(n=0; nm_numTerms; t++) { - local_id = nets[n]->m_terms[t]->m_data; - if (local_id >= 0) - cell_numTerms[local_id]++; - } - - for(c=0; cm_numTerms; t++) { - local_id = nets[n]->m_terms[t]->m_data; - if (local_id >= 0) - cell_terms[cell_numTerms[local_id]++] = nets[n]; - } - - // topological order? - - // iterative linear - for(pass=0; passm_numTerms; t++); - } - } -} -#endif - -// -------------------------------------------------------------------- -// fastEstimate() -// -// -------------------------------------------------------------------- -float fastEstimate(ConcreteCell *cell, - int numNets, ConcreteNet *nets[]) { - float len = 0; - int n; - Rect box; - - assert(cell); - - for(n=0; nm_x < box.x) len += (box.x - cell->m_x); - if (cell->m_x > box.x+box.w) len += (cell->m_x-box.x-box.w); - if (cell->m_y < box.y) len += (box.x - cell->m_y); - if (cell->m_y > box.y+box.h) len += (cell->m_y-box.y-box.h); - } - - return len; -} diff --git a/src/phys/place/place_io.c b/src/phys/place/place_io.c deleted file mode 100644 index 8e24ef4a..00000000 --- a/src/phys/place/place_io.c +++ /dev/null @@ -1,94 +0,0 @@ -/*===================================================================*/ -// -// place_io.c -// -// Aaron P. Hurst, 2003-2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#include -#include -#include -#include -#include - -#include "place_base.h" - - -// -------------------------------------------------------------------- -// writeBookshelfNodes() -// -// -------------------------------------------------------------------- -void writeBookshelfNodes(const char *filename) { - - int c = 0; - int numNodes, numTerms; - - FILE *nodesFile = fopen(filename, "w"); - if (!nodesFile) { - printf("ERROR: Could not open .nodes file\n"); - exit(1); - } - - numNodes = numTerms = 0; - for(c=0; cm_parent->m_pad) - numTerms++; - } - - - - fprintf(nodesFile, "UCLA nodes 1.0\n"); - fprintf(nodesFile, "NumNodes : %d\n", numNodes); - fprintf(nodesFile, "NumTerminals : %d\n", numTerms); - - for(c=0; cm_id, - g_place_concreteCells[c]->m_parent->m_width, - g_place_concreteCells[c]->m_parent->m_height, - (g_place_concreteCells[c]->m_parent->m_pad ? " terminal" : "")); - } - - fclose(nodesFile); -} - - -// -------------------------------------------------------------------- -// writeBookshelfPl() -// -// -------------------------------------------------------------------- -void writeBookshelfPl(const char *filename) { - - int c = 0; - - FILE *plFile = fopen(filename, "w"); - if (!plFile) { - printf("ERROR: Could not open .pl file\n"); - exit(1); - } - - fprintf(plFile, "UCLA pl 1.0\n"); - for(c=0; cm_id, - g_place_concreteCells[c]->m_x, - g_place_concreteCells[c]->m_y, - (g_place_concreteCells[c]->m_fixed ? "\\FIXED" : "")); - } - - fclose(plFile); - -} - - -// -------------------------------------------------------------------- -// writeBookshelf() -// -// -------------------------------------------------------------------- -void writeBookshelf(const char *filename) { - writeBookshelfNodes("out.nodes"); - writeBookshelfPl("out.pl"); -} diff --git a/src/phys/place/place_legalize.c b/src/phys/place/place_legalize.c deleted file mode 100644 index 950902f4..00000000 --- a/src/phys/place/place_legalize.c +++ /dev/null @@ -1,23 +0,0 @@ -/*===================================================================*/ -// -// place_legalize.c -// -// Aaron P. Hurst, 2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#include -#include - -#include "place_base.h" - - -// -------------------------------------------------------------------- -// legalize() -// -// -------------------------------------------------------------------- -void legalize() { - // UNIMPLEMENTED -} - diff --git a/src/phys/place/place_pads.c b/src/phys/place/place_pads.c deleted file mode 100644 index 361fac7f..00000000 --- a/src/phys/place/place_pads.c +++ /dev/null @@ -1,141 +0,0 @@ -/*===================================================================*/ -// -// place_pads.c -// -// Aaron P. Hurst, 2003-2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#include -#include -#include -#include - -#include "place_base.h" - -// -------------------------------------------------------------------- -// globalPreplace() -// -/// \brief Place pad ring, leaving a core area to meet a desired utilization. -// -/// Sets the position of pads that aren't already fixed. -/// -/// Computes g_place_coreBounds and g_place_padBounds. Determines -/// g_place_rowHeight. -// -// -------------------------------------------------------------------- -void globalPreplace(float utilization) { - int i, c, h, numRows; - float coreArea = 0, totalArea = 0; - int padCount = 0; - float area; - ConcreteCell **padCells = NULL; - AbstractCell *padType = NULL; - ConcreteCell *cell; - float nextPos; - int remainingPads, northPads, southPads, eastPads, westPads; - - printf("PLAC-00 : Placing IO pads\n");; - - // identify the pads and compute the total core area - g_place_coreBounds.x = g_place_coreBounds.y = 0; - g_place_coreBounds.w = g_place_coreBounds.h = -INT_MAX; - - for(c=0; cm_parent->m_pad) { - padType = cell->m_parent; - } else { - coreArea += area; - g_place_rowHeight = cell->m_parent->m_height; - } - - if (cell->m_fixed) { - g_place_coreBounds.x = g_place_coreBounds.x < cell->m_x ? g_place_coreBounds.x : cell->m_x; - g_place_coreBounds.y = g_place_coreBounds.y < cell->m_y ? g_place_coreBounds.y : cell->m_y; - g_place_coreBounds.w = g_place_coreBounds.w > cell->m_x ? g_place_coreBounds.w : cell->m_x; - g_place_coreBounds.h = g_place_coreBounds.h > cell->m_y ? g_place_coreBounds.h : cell->m_y; - } else if (cell->m_parent->m_pad) { - padCells = realloc(padCells, sizeof(ConcreteCell **)*(padCount+1)); - padCells[padCount++] = cell; - } - totalArea += area; - } - if (!padType) { - printf("ERROR: No pad cells\n"); - exit(1); - } - g_place_padBounds.w -= g_place_padBounds.x; - g_place_padBounds.h -= g_place_padBounds.y; - - coreArea /= utilization; - - // create the design boundaries - numRows = sqrt(coreArea)/g_place_rowHeight+1; - h = numRows * g_place_rowHeight; - g_place_coreBounds.h = g_place_coreBounds.h > h ? g_place_coreBounds.h : h; - g_place_coreBounds.w = g_place_coreBounds.w > coreArea/g_place_coreBounds.h ? - g_place_coreBounds.w : coreArea/g_place_coreBounds.h; - // increase the dimensions by the width of the padring - g_place_padBounds = g_place_coreBounds; - if (padCount) { - printf("PLAC-05 : \tpreplacing %d pad cells\n", padCount); - g_place_padBounds.x -= padType->m_width; - g_place_padBounds.y -= padType->m_height; - g_place_padBounds.w = g_place_coreBounds.w+2*padType->m_width; - g_place_padBounds.h = g_place_coreBounds.h+2*padType->m_height; - } - - printf("PLAC-05 : \tplaceable rows : %d\n", numRows); - printf("PLAC-05 : \tcore dimensions : %.0fx%.0f\n", - g_place_coreBounds.w, g_place_coreBounds.h); - printf("PLAC-05 : \tchip dimensions : %.0fx%.0f\n", - g_place_padBounds.w, g_place_padBounds.h); - - remainingPads = padCount; - c = 0; - - // north pads - northPads = remainingPads/4; remainingPads -= northPads; - nextPos = 0; - for(i=0; im_x = g_place_padBounds.x+cell->m_parent->m_width*0.5 + nextPos; - cell->m_y = g_place_padBounds.y+cell->m_parent->m_height*0.5; - nextPos += (g_place_padBounds.w-padType->m_width) / northPads; - } - - // south pads - southPads = remainingPads/3; remainingPads -= southPads; - nextPos = 0; - for(i=0; im_x = g_place_padBounds.w+g_place_padBounds.x-cell->m_parent->m_width*0.5 - nextPos; - cell->m_y = g_place_padBounds.h+g_place_padBounds.y-cell->m_parent->m_height*0.5; - nextPos += (g_place_padBounds.w-2*padType->m_width) / southPads; - } - - // east pads - eastPads = remainingPads/2; remainingPads -= eastPads; - nextPos = 0; - for(i=0; im_x = g_place_padBounds.w+g_place_padBounds.x-cell->m_parent->m_width*0.5; - cell->m_y = g_place_padBounds.y+cell->m_parent->m_height*0.5 + nextPos; - nextPos += (g_place_padBounds.h-padType->m_height) / eastPads; - } - - // west pads - westPads = remainingPads; - nextPos = 0; - for(i=0; im_x = g_place_padBounds.x+cell->m_parent->m_width*0.5; - cell->m_y = g_place_padBounds.h+g_place_padBounds.y-cell->m_parent->m_height*0.5 - nextPos; - nextPos += (g_place_padBounds.h-padType->m_height) / westPads; - } - -} - diff --git a/src/phys/place/place_partition.c b/src/phys/place/place_partition.c deleted file mode 100644 index ea57cd1c..00000000 --- a/src/phys/place/place_partition.c +++ /dev/null @@ -1,1135 +0,0 @@ -/*===================================================================*/ -// -// place_partition.c -// -// Aaron P. Hurst, 2003-2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#include -#include -#include -#include -#include -#include -//#include -//#include - -#include "place_base.h" -#include "place_gordian.h" - -#if !defined(NO_HMETIS) -#include "libhmetis.h" -#endif - -// -------------------------------------------------------------------- -// Global variables -// -// -------------------------------------------------------------------- - -Partition *g_place_rootPartition = NULL; -ConcreteNet **allNetsR2 = NULL, - **allNetsL2 = NULL, - **allNetsB2 = NULL, - **allNetsT2 = NULL; - - -// -------------------------------------------------------------------- -// Function prototypes and local data structures -// -// -------------------------------------------------------------------- - -typedef struct FM_cell { - int loc; - int gain; - ConcreteCell *cell; - struct FM_cell *next, *prev; - bool locked; -} FM_cell; - -void FM_updateGains(ConcreteNet *net, int partition, int inc, - FM_cell target [], FM_cell *bin [], - int count_1 [], int count_2 []); - - -// -------------------------------------------------------------------- -// initPartitioning() -// -/// \brief Initializes data structures necessary for partitioning. -// -/// Creates a valid g_place_rootPartition. -/// -// -------------------------------------------------------------------- -void initPartitioning() { - int i; - float area; - - // create root partition - g_place_numPartitions = 1; - if (g_place_rootPartition) free(g_place_rootPartition); - g_place_rootPartition = malloc(sizeof(Partition)); - g_place_rootPartition->m_level = 0; - g_place_rootPartition->m_area = 0; - g_place_rootPartition->m_bounds = g_place_coreBounds; - g_place_rootPartition->m_vertical = false; - g_place_rootPartition->m_done = false; - g_place_rootPartition->m_leaf = true; - - // add all of the cells to this partition - g_place_rootPartition->m_members = malloc(sizeof(ConcreteCell*)*g_place_numCells); - g_place_rootPartition->m_numMembers = 0; - for (i=0; im_fixed) { - area = getCellArea(g_place_concreteCells[i]); - g_place_rootPartition->m_members[g_place_rootPartition->m_numMembers++] = - g_place_concreteCells[i]; - g_place_rootPartition->m_area += area; - } - } -} - - -// -------------------------------------------------------------------- -// presortNets() -// -/// \brief Sorts nets by corner positions. -// -/// Allocates allNetsX2 structures. -/// -// -------------------------------------------------------------------- -void presortNets() { - allNetsL2 = (ConcreteNet**)realloc(allNetsL2, sizeof(ConcreteNet*)*g_place_numNets); - allNetsR2 = (ConcreteNet**)realloc(allNetsR2, sizeof(ConcreteNet*)*g_place_numNets); - allNetsB2 = (ConcreteNet**)realloc(allNetsB2, sizeof(ConcreteNet*)*g_place_numNets); - allNetsT2 = (ConcreteNet**)realloc(allNetsT2, sizeof(ConcreteNet*)*g_place_numNets); - memcpy(allNetsL2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); - memcpy(allNetsR2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); - memcpy(allNetsB2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); - memcpy(allNetsT2, g_place_concreteNets, sizeof(ConcreteNet*)*g_place_numNets); - qsort(allNetsL2, g_place_numNets, sizeof(ConcreteNet*), netSortByL); - qsort(allNetsR2, g_place_numNets, sizeof(ConcreteNet*), netSortByR); - qsort(allNetsB2, g_place_numNets, sizeof(ConcreteNet*), netSortByB); - qsort(allNetsT2, g_place_numNets, sizeof(ConcreteNet*), netSortByT); -} - -// -------------------------------------------------------------------- -// refinePartitions() -// -/// \brief Splits large leaf partitions. -// -// -------------------------------------------------------------------- -bool refinePartitions() { - - return refinePartition(g_place_rootPartition); -} - - -// -------------------------------------------------------------------- -// reallocPartitions() -// -/// \brief Reallocates the partitions based on placement information. -// -// -------------------------------------------------------------------- -void reallocPartitions() { - - reallocPartition(g_place_rootPartition); -} - - -// -------------------------------------------------------------------- -// refinePartition() -// -/// \brief Splits any large leaves within a partition. -// -// -------------------------------------------------------------------- -bool refinePartition(Partition *p) { - bool degenerate = false; - int nonzeroCount = 0; - int i; - - assert(p); - - // is this partition completed? - if (p->m_done) return true; - - // is this partition a non-leaf node? - if (!p->m_leaf) { - p->m_done = refinePartition(p->m_sub1); - p->m_done &= refinePartition(p->m_sub2); - return p->m_done; - } - - // leaf... - // create two new subpartitions - g_place_numPartitions++; - p->m_sub1 = malloc(sizeof(Partition)); - p->m_sub1->m_level = p->m_level+1; - p->m_sub1->m_leaf = true; - p->m_sub1->m_done = false; - p->m_sub1->m_area = 0; - p->m_sub1->m_vertical = !p->m_vertical; - p->m_sub1->m_numMembers = 0; - p->m_sub1->m_members = NULL; - p->m_sub2 = malloc(sizeof(Partition)); - p->m_sub2->m_level = p->m_level+1; - p->m_sub2->m_leaf = true; - p->m_sub2->m_done = false; - p->m_sub2->m_area = 0; - p->m_sub2->m_vertical = !p->m_vertical; - p->m_sub2->m_numMembers = 0; - p->m_sub2->m_members = NULL; - p->m_leaf = false; - - // --- INITIAL PARTITION - - if (PARTITION_AREA_ONLY) - partitionEqualArea(p); - else - partitionScanlineMincut(p); - - resizePartition(p); - - // --- PARTITION IMPROVEMENT - - if (p->m_level < REPARTITION_LEVEL_DEPTH) { - if (REPARTITION_FM) - repartitionFM(p); - else if (REPARTITION_HMETIS) - repartitionHMetis(p); - } - - resizePartition(p); - - // fix imbalances due to zero-area cells - for(i=0; im_sub1->m_numMembers; i++) - if (p->m_sub1->m_members[i]) - if (getCellArea(p->m_sub1->m_members[i]) > 0) { - nonzeroCount++; - } - - // is this leaf now done? - if (nonzeroCount <= LARGEST_FINAL_SIZE) - p->m_sub1->m_done = true; - if (nonzeroCount == 0) - degenerate = true; - - nonzeroCount = 0; - for(i=0; im_sub2->m_numMembers; i++) - if (p->m_sub2->m_members[i]) - if (getCellArea(p->m_sub2->m_members[i]) > 0) { - nonzeroCount++; - } - - // is this leaf now done? - if (nonzeroCount <= LARGEST_FINAL_SIZE) - p->m_sub2->m_done = true; - if (nonzeroCount == 0) - degenerate = true; - - // have we found a degenerate partitioning? - if (degenerate) { - printf("QPART-35 : WARNING: degenerate partition generated\n"); - partitionEqualArea(p); - resizePartition(p); - p->m_sub1->m_done = true; - p->m_sub2->m_done = true; - } - - // is this parent now finished? - if (p->m_sub1->m_done && p->m_sub2->m_done) p->m_done = true; - - return p->m_done; -} - - -// -------------------------------------------------------------------- -// repartitionHMetis() -// -/// \brief Repartitions the two subpartitions using the hMetis min-cut library. -/// -/// The number of cut nets between the two partitions will be minimized. -// -// -------------------------------------------------------------------- -void repartitionHMetis(Partition *parent) { -#if defined(NO_HMETIS) - printf("QPAR_02 : \t\tERROR: hMetis not available. Ignoring.\n"); -#else - - int n,c,t, i; - float area; - int *edgeConnections = NULL; - int *partitionAssignment = (int *)calloc(g_place_numCells, sizeof(int)); - int *vertexWeights = (int *)calloc(g_place_numCells, sizeof(int)); - int *edgeDegree = (int *)malloc(sizeof(int)*(g_place_numNets+1)); - int numConnections = 0; - int numEdges = 0; - float initial_cut; - int targets = 0; - ConcreteCell *cell = NULL; - int options[9]; - int afterCuts = 0; - - assert(parent); - assert(parent->m_sub1); - assert(parent->m_sub2); - - printf("QPAR-02 : \t\trepartitioning with hMetis\n"); - - // count edges - edgeDegree[0] = 0; - for(n=0; nm_numTerms > 1) { - numConnections += g_place_concreteNets[n]->m_numTerms; - edgeDegree[++numEdges] = numConnections; - } - - if (parent->m_vertical) { - // vertical - initial_cut = parent->m_sub2->m_bounds.x; - - // initialize all cells - for(c=0; cm_x < initial_cut) - partitionAssignment[c] = 0; - else - partitionAssignment[c] = 1; - } - - // initialize cells in partition 1 - for(t=0; tm_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) { - cell = parent->m_sub1->m_members[t]; - vertexWeights[cell->m_id] = getCellArea(cell); - // pay attention to cells that are close to the cut - if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { - targets++; - partitionAssignment[cell->m_id] = -1; - } - } - - // initialize cells in partition 2 - for(t=0; tm_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) { - cell = parent->m_sub2->m_members[t]; - vertexWeights[cell->m_id] = getCellArea(cell); - // pay attention to cells that are close to the cut - if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { - targets++; - partitionAssignment[cell->m_id] = -1; - } - } - - } else { - // horizontal - initial_cut = parent->m_sub2->m_bounds.y; - - // initialize all cells - for(c=0; cm_y < initial_cut) - partitionAssignment[c] = 0; - else - partitionAssignment[c] = 1; - } - - // initialize cells in partition 1 - for(t=0; tm_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) { - cell = parent->m_sub1->m_members[t]; - vertexWeights[cell->m_id] = getCellArea(cell); - // pay attention to cells that are close to the cut - if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { - targets++; - partitionAssignment[cell->m_id] = -1; - } - } - - // initialize cells in partition 2 - for(t=0; tm_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) { - cell = parent->m_sub2->m_members[t]; - vertexWeights[cell->m_id] = getCellArea(cell); - // pay attention to cells that are close to the cut - if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { - targets++; - partitionAssignment[cell->m_id] = -1; - } - } - } - - options[0] = 1; // any non-default values? - options[1] = 3; // num bisections - options[2] = 1; // grouping scheme - options[3] = 1; // refinement scheme - options[4] = 1; // cycle refinement scheme - options[5] = 0; // reconstruction scheme - options[6] = 0; // fixed assignments? - options[7] = 12261980; // random seed - options[8] = 0; // debugging level - - edgeConnections = (int *)malloc(sizeof(int)*numConnections); - - i = 0; - for(n=0; nm_numTerms > 1) - for(t=0; tm_numTerms; t++) - edgeConnections[i++] = g_place_concreteNets[n]->m_terms[t]->m_id; - } - - HMETIS_PartRecursive(g_place_numCells, numEdges, vertexWeights, - edgeDegree, edgeConnections, NULL, - 2, (int)(100*MAX_PARTITION_NONSYMMETRY), - options, partitionAssignment, &afterCuts); - - /* - printf("HMET-20 : \t\t\tbalance before %d / %d ... ", parent->m_sub1->m_numMembers, - parent->m_sub2->m_numMembers); - */ - - // reassign members to subpartitions - parent->m_sub1->m_numMembers = 0; - parent->m_sub1->m_area = 0; - parent->m_sub2->m_numMembers = 0; - parent->m_sub2->m_area = 0; - parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members, - sizeof(ConcreteCell*)*parent->m_numMembers); - parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members, - sizeof(ConcreteCell*)*parent->m_numMembers); - - for(t=0; tm_numMembers; t++) if (parent->m_members[t]) { - cell = parent->m_members[t]; - area = getCellArea(cell); - if (partitionAssignment[cell->m_id] == 0) { - parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = cell; - parent->m_sub1->m_area += area; - } - else { - parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = cell; - parent->m_sub2->m_area += area; - } - } - /* - printf("after %d / %d\n", parent->m_sub1->m_numMembers, - parent->m_sub2->m_numMembers); - */ - - // cout << "HMET-21 : \t\t\tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl; - // cout << "HMET-22 : \t\t\tstarting cuts= " << beforeCuts << " final cuts= " << afterCuts << endl; - - free(edgeConnections); - free(vertexWeights); - free(edgeDegree); - free(partitionAssignment); -#endif -} - - -// -------------------------------------------------------------------- -// repartitionFM() -// -/// \brief Fiduccia-Matheyses mincut partitioning algorithm. -// -/// UNIMPLEMENTED (well, un-C-ified) -// -// -------------------------------------------------------------------- -void repartitionFM(Partition *parent) { -#if 0 - assert(!parent->leaf && parent->m_sub1->leaf && parent->m_sub2->leaf); - - // count of each net's number of cells in each bipartition - int count_1[m_design->nets.length()]; - memset(count_1, 0, sizeof(int)*m_design->nets.length()); - int count_2[m_design->nets.length()]; - memset(count_2, 0, sizeof(int)*m_design->nets.length()); - - FM_cell target[m_design->cells.length()]; - memset(target, 0, sizeof(FM_cell)*m_design->cells.length()); - FM_cell *bin[FM_MAX_BIN+1]; - FM_cell *locked = 0; - memset(bin, 0, sizeof(FM_cell *)*(FM_MAX_BIN+1)); - - int max_gain = 0; - int before_cuts = 0, current_cuts = 0; - double initial_cut; - int targets = 0; - long cell_id; - double halfArea = parent->m_area / 2.0; - double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY; - ConcreteNet *net; - - // INITIALIZATION - // select cells to partition - - if (parent->vertical) { - // vertical - - initial_cut = parent->m_sub2->m_bounds.x; - - // initialize all cells - for(h::list::iterator it = rootPartition->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - if ((*it)->temp_x < initial_cut) - target[cell_id].loc = -1; - else - target[cell_id].loc = -2; - target[cell_id].cell = *it; - target[cell_id].gain = 0; - } - - // initialize cells in partition 1 - for(h::list::iterator it = parent->m_sub1->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - // pay attention to cells that are close to the cut - if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { - targets++; - target[cell_id].loc = 1; - } - } - - // initialize cells in partition 2 - for(h::list::iterator it = parent->m_sub2->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - // pay attention to cells that are close to the cut - if (abs((*it)->temp_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) { - targets++; - target[cell_id].loc = 2; - } - } - - // count the number of cells on each side of the partition for every net - for(h::hash_map::iterator n_it = m_design->nets.begin(); !n_it; n_it++) { - for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++) - if (abs(target[(*p_it)->getCell()->getID()].loc) == 1) - count_1[net->getID()]++; - else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2) - count_2[net->getID()]++; - else if ((*p_it)->getCell()->temp_x < initial_cut) - count_1[net->getID()]++; - else - count_2[net->getID()]++; - if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++; - } - - } else { - // horizontal - - initial_cut = parent->m_sub2->m_bounds.y; - - // initialize all cells - for(h::list::iterator it = rootPartition->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - if ((*it)->temp_y < initial_cut) - target[cell_id].loc = -1; - else - target[cell_id].loc = -2; - target[cell_id].cell = *it; - target[cell_id].gain = 0; - } - - // initialize cells in partition 1 - for(h::list::iterator it = parent->m_sub1->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - // pay attention to cells that are close to the cut - if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { - targets++; - target[cell_id].loc = 1; - } - } - - // initialize cells in partition 2 - for(h::list::iterator it = parent->m_sub2->m_members.begin(); !it; it++) { - cell_id = (*it)->getID(); - // pay attention to cells that are close to the cut - if (abs((*it)->temp_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) { - targets++; - target[cell_id].loc = 2; - } - } - - // count the number of cells on each side of the partition for every net - for(h::hash_map::iterator n_it = m_design->nets.begin(); !n_it; n_it++) { - for(ConcretePinList::iterator p_it = (net = *n_it)->getPins().begin(); !p_it; p_it++) - if (abs(target[(*p_it)->getCell()->getID()].loc) == 1) - count_1[net->getID()]++; - else if (abs(target[(*p_it)->getCell()->getID()].loc) == 2) - count_2[net->getID()]++; - else if ((*p_it)->getCell()->temp_y < initial_cut) - count_1[net->getID()]++; - else - count_2[net->getID()]++; - if (count_1[net->getID()] > 0 && count_2[net->getID()] > 0) before_cuts++; - } - } - - // INITIAL GAIN CALCULATION - for(long id=0; id < m_design->cells.length(); id++) - if (target[id].loc > 0) { - assert(target[id].cell != 0); - assert(target[id].gain == 0); - - // examine counts for the net on each pin - for(ConcretePinMap::iterator p_it = target[id].cell->getPins().begin(); !p_it; p_it++) - if ((*p_it)->isAttached()) { - int n_id = (*p_it)->getNet()->getID(); - if (target[id].loc == 1 && count_1[n_id] == 1) target[id].gain++; - if (target[id].loc == 1 && count_2[n_id] == 0) target[id].gain--; - if (target[id].loc == 2 && count_1[n_id] == 0) target[id].gain--; - if (target[id].loc == 2 && count_2[n_id] == 1) target[id].gain++; - } - - assert(target[id].cell->getPins().length() >= abs(target[id].gain)); - - // add it to a bin - int bin_num = min(max(0, target[id].gain),FM_MAX_BIN); - max_gain = max(max_gain, bin_num); - - assert(bin_num >= 0 && bin_num <= FM_MAX_BIN); - target[id].next = bin[bin_num]; - target[id].prev = 0; - if (bin[bin_num] != 0) - bin[bin_num]->prev = &target[id]; - bin[bin_num] = &target[id]; - } - - // OUTER F-M LOOP - current_cuts = before_cuts; - int num_moves = 1; - int pass = 0; - while(num_moves > 0 && pass < FM_MAX_PASSES) { - pass++; - num_moves = 0; - - // check_list(bin, locked, targets); // DEBUG - - // move all locked cells back - int moved_back = 0; - while(locked != 0) { - FM_cell *current = locked; - current->locked = false; - - int bin_num = min(max(0, current->gain),FM_MAX_BIN); - max_gain = max(max_gain, bin_num); - - locked = current->next; - if (locked != 0) - locked->prev = 0; - - if (bin[bin_num] != 0) - bin[bin_num]->prev = current; - current->next = bin[bin_num]; - bin[bin_num] = current; - - moved_back++; - } - // cout << "\tmoved back: " << moved_back << endl; - // check_list(bin, locked, targets); // DEBUG - - max_gain = FM_MAX_BIN; - while(bin[max_gain] == 0 && max_gain > 0) max_gain--; - - // INNER F-M LOOP (single pass) - while(1) { - - int bin_num = FM_MAX_BIN; - FM_cell *current = bin[bin_num]; - - // look for next cell to move - while (bin_num > 0 && (current == 0 || - (current->loc==1 && current->cell->getArea()+parent->m_sub2->m_area > halfArea+areaFlexibility) || - (current->loc==2 && current->cell->getArea()+parent->m_sub1->m_area > halfArea+areaFlexibility))) { - - if (current == 0) current = bin[--bin_num]; else current = current->next; - } - if (bin_num == 0) - break; - - num_moves++; - current->locked = true; - // cout << "moving cell " << current->cell->getID() << " gain=" << current->gain << " pins= " << current->cell->getPins().length() << " from " << current->loc; - - // change partition marking and areas - if (current->loc == 1) { - current->loc = 2; - parent->m_sub1->m_area -= current->cell->getArea(); - parent->m_sub2->m_area += current->cell->getArea(); - - // update partition counts on all nets attached to this cell - for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); - !p_it; p_it++) { - - if (!(*p_it)->isAttached()) // ignore unattached pins - continue; - net = (*p_it)->getNet(); - - count_1[net->getID()]--; - count_2[net->getID()]++; - - // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]+1 << "/" << count_2[net->getID()]-1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl; - - // if net becomes critical, update gains on attached cells and resort bins - if (count_1[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); } - if (count_2[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); } - - // check_list(bin, locked, targets); // DEBUG - } - - } else { - current->loc = 1; - parent->m_sub2->m_area -= current->cell->getArea(); - parent->m_sub1->m_area += current->cell->getArea(); - - // update gains on all nets attached to this cell - for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); - !p_it; p_it++) { - - if (!(*p_it)->isAttached()) // ignore unattached pins - continue; - net = (*p_it)->getNet(); - count_2[net->getID()]--; - count_1[net->getID()]++; - - // cout << "\tnet " << net->getID() << " was " << count_1[net->getID()]-1 << "/" << count_2[net->getID()]+1 << " now " << count_1[net->getID()] << "/" << count_2[net->getID()] << endl; - - if (count_2[net->getID()] == 0) { current_cuts--; FM_updateGains(net, 2, -1, target, bin, count_1, count_2); } - if (count_1[net->getID()] == 1) { current_cuts++; FM_updateGains(net, 1, -1, target, bin, count_1, count_2); } - - // check_list(bin, locked, targets); // DEBUG - } - } - - //cout << " cuts=" << current_cuts << endl; - - // move current to locked - -/* - cout << "b=" << bin[bin_num] << " "; - cout << current->prev << "-> "; - if (current->prev == 0) - cout << "X"; - else cout << current->prev->next; - cout << "=" << current << "="; - if (current->next == 0) - cout << "X"; - else - cout << current->next->prev; - cout << " ->" << current->next << endl; -*/ - - if (bin[bin_num] == current) - bin[bin_num] = current->next; - if (current->prev != 0) - current->prev->next = current->next; - if (current->next != 0) - current->next->prev = current->prev; - -/* - cout << "b=" << bin[bin_num] << " "; - cout << current->prev << "-> "; - if (current->prev == 0) - cout << "X"; - else cout << current->prev->next; - cout << "=" << current << "="; - if (current->next == 0) - cout << "X"; - else - cout << current->next->prev; - cout << " ->" << current->next << endl; -*/ - - current->prev = 0; - current->next = locked; - if (locked != 0) - locked->prev = current; - locked = current; - - // check_list(bin, locked, targets); // DEBUG - - // update max_gain - max_gain = FM_MAX_BIN; - while(bin[max_gain] == 0 && max_gain > 0) max_gain--; - } - - // cout << "\tcurrent cuts= " << current_cuts << " moves= " << num_moves << endl; - } - - // reassign members to subpartitions - cout << "FIDM-20 : \tbalance before " << parent->m_sub1->m_members.length() << "/" - << parent->m_sub2->m_members.length() << " "; - parent->m_sub1->m_members.clear(); - parent->m_sub1->m_area = 0; - parent->m_sub2->m_members.clear(); - parent->m_sub2->m_area = 0; - for(h::list::iterator it = parent->m_members.begin(); !it; it++) { - if (target[(*it)->getID()].loc == 1 || target[(*it)->getID()].loc == -1) { - parent->m_sub1->m_members.push_back(*it); - parent->m_sub1->m_area += (*it)->getArea(); - } - else { - parent->m_sub2->m_members.push_back(*it); - parent->m_sub2->m_area += (*it)->getArea(); - } - } - cout << " after " << parent->m_sub1->m_members.length() << "/" - << parent->m_sub2->m_members.length() << endl; - - - cout << "FIDM-21 : \tloc: " << initial_cut << " targetting: " << targets*100/parent->m_members.length() << "%" << endl; - cout << "FIDM-22 : \tstarting cuts= " << before_cuts << " final cuts= " << current_cuts << endl; -#endif -} - -// ----- FM_updateGains() -// moves a cell between bins -#if 0 -void FM_updateGains(ConcreteNet *net, int partition, int inc, - FM_cell target [], FM_cell *bin [], - int count_1 [], int count_2 []) { - - for(ConcretePinList::iterator it = net->getPins().begin(); !it; it++) { - FM_cell *current = &(target[(*it)->getCell()->getID()]); - assert(current->cell != 0); - - int old_gain = current->gain; - current->gain = 0; - - // examine counts for the net on each pin - for(ConcretePinMap::iterator p_it = current->cell->getPins().begin(); !p_it; p_it++) - if ((*p_it)->isAttached()) { - int n_id = (*p_it)->getNet()->getID(); - if (current->loc == 1 && count_1[n_id] == 1) current->gain++; - if (current->loc == 1 && count_2[n_id] == 0) current->gain--; - if (current->loc == 2 && count_1[n_id] == 0) current->gain--; - if (current->loc == 2 && count_2[n_id] == 1) current->gain++; - } - - if (!current->locked) { - // remove cell from existing bin - int bin_num = min(max(0, old_gain),FM_MAX_BIN); - if (bin[bin_num] == current) - bin[bin_num] = current->next; - if (current->prev != 0) - current->prev->next = current->next; - if (current->next != 0) - current->next->prev = current->prev; - // add cell to correct bin - bin_num = min(max(0, current->gain),FM_MAX_BIN); - current->prev = 0; - current->next = bin[bin_num]; - if (bin[bin_num] != 0) - bin[bin_num]->prev = current; - bin[bin_num] = current; - } - } - -} -#endif - - -// -------------------------------------------------------------------- -// partitionEqualArea() -// -/// \brief Splits a partition into two halves of equal area. -// -// -------------------------------------------------------------------- -void partitionEqualArea(Partition *parent) { - float halfArea, area; - int i=0; - - // which way to sort? - if (parent->m_vertical) - // sort by X position - qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByX); - else - // sort by Y position - qsort(parent->m_members, parent->m_numMembers, sizeof(ConcreteCell*), cellSortByY); - - // split the list - halfArea = parent->m_area*0.5; - parent->m_sub1->m_area = 0.0; - parent->m_sub1->m_numMembers = 0; - parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members, - sizeof(ConcreteCell*)*parent->m_numMembers); - parent->m_sub2->m_area = 0.0; - parent->m_sub2->m_numMembers = 0; - parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members, - sizeof(ConcreteCell*)*parent->m_numMembers); - - for(; parent->m_sub1->m_area < halfArea; i++) - if (parent->m_members[i]) { - area = getCellArea(parent->m_members[i]); - parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = parent->m_members[i]; - parent->m_sub1->m_area += area; - } - for(; im_numMembers; i++) - if (parent->m_members[i]) { - area = getCellArea(parent->m_members[i]); - parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = parent->m_members[i]; - parent->m_sub2->m_area += area; - } - -} - - -// -------------------------------------------------------------------- -// partitionScanlineMincut() -// -/// \brief Scans the cells within a partition from left to right and chooses the min-cut. -// -// -------------------------------------------------------------------- -void partitionScanlineMincut(Partition *parent) { -#if 0 - int current_cuts = 0; - int minimum_cuts = INT_MAX; - ConcreteCell *minimum_location = NULL; - double currentArea = 0, halfArea = parent->m_area * 0.5; - double areaFlexibility = parent->m_area * MAX_PARTITION_NONSYMMETRY; - double newLine, oldLine = -DBL_MAX; - - for(ConcreteNetList::iterator n_it = m_design->nets.begin(); !n_it; n_it++) - (*n_it)->m_mark = 0; - for(h::list::iterator i = parent->m_members.begin(); - !i.isDone(); i++) { - assert(*i); - for(ConcretePinMap::iterator j = (*i)->getPins().begin(); - !j.isDone(); j++) { - assert(*j); - if((*j)->isAttached()) { - (*j)->getNet()->m_mark = 1; - } - } - } - - if (parent->vertical) { - parent->m_members.sort(sortByX); - int all1 = 0, all2 = 0; - h::list::iterator local = parent->m_members.begin(); - for(; !local.isDone(); local++) { - currentArea += (*local)->getArea(); - if (currentArea < halfArea-areaFlexibility) - continue; - if (currentArea > halfArea+areaFlexibility) - break; - newLine = (*local)->temp_x; - while(all1 < g_place_numNets && allNetsL2[all1]->getBoundingBox().left() <= newLine) { - if(allNetsL2[all1]->m_mark) { - current_cuts++; - } - all1++; - } - while(all2 < g_place_numNets && allNetsR2[all2]->getBoundingBox().right() <= newLine) { - if(allNetsR2[all2]->m_mark) { - current_cuts--; - } - all2++; - } - if (current_cuts < minimum_cuts) { - minimum_cuts = current_cuts; - minimum_location = *local; - } - oldLine = newLine; - } - } - else { - parent->m_members.sort(sortByY); - int all1 = 0, all2 = 0; - h::list::iterator local = parent->m_members.begin(); - for(; !local.isDone(); local++) { - currentArea += (*local)->getArea(); - if (currentArea < halfArea-areaFlexibility) - continue; - if (currentArea > halfArea+areaFlexibility) - break; - newLine = (*local)->temp_y; - while(all1 < g_place_numNets && allNetsB2[all1]->getBoundingBox().top() <= newLine) { - if(allNetsB2[all1]->m_mark) { - current_cuts++; - } - all1++; - } - while(all2 < g_place_numNets && allNetsT2[all2]->getBoundingBox().bottom() <= newLine) { - if(allNetsT2[all2]->m_mark) { - current_cuts--; - } - all2++; - } - if (current_cuts < minimum_cuts) { - minimum_cuts = current_cuts; - minimum_location = *local; - } - oldLine = newLine; - } - } - if (minimum_location == NULL) { - return partitionEqualArea(parent); - } - h::list::iterator it = parent->m_members.begin(); - parent->m_sub1->m_members.clear(); - parent->m_sub1->m_area = 0; - for(; *it != minimum_location; it++) { - parent->m_sub1->m_members.push_front(*it); - parent->m_sub1->m_area += (*it)->getArea(); - } - parent->m_sub2->m_members.clear(); - parent->m_sub2->m_area = 0; - for(; !it; it++) { - parent->m_sub2->m_members.push_front(*it); - parent->m_sub2->m_area += (*it)->getArea(); - } -#endif -} - - -// -------------------------------------------------------------------- -// reallocPartition() -// -/// \brief Reallocates a partition and all of its children. -// -// -------------------------------------------------------------------- -void reallocPartition(Partition *p) { - - if (p->m_leaf) { - return; - } - - // --- INITIAL PARTITION - - if (PARTITION_AREA_ONLY) - partitionEqualArea(p); - else - partitionScanlineMincut(p); - - resizePartition(p); - - // --- PARTITION IMPROVEMENT - if (p->m_level < REPARTITION_LEVEL_DEPTH) { - if (REPARTITION_HMETIS) - repartitionHMetis(p); - - resizePartition(p); - } - - reallocPartition(p->m_sub1); - reallocPartition(p->m_sub2); -} - - -// -------------------------------------------------------------------- -// resizePartition() -// -/// \brief Recomputes the bounding boxes of the child partitions based on their relative areas. -// -// -------------------------------------------------------------------- -void resizePartition(Partition *p) { - // compute the new bounding box - p->m_sub1->m_bounds.x = p->m_bounds.x; - p->m_sub1->m_bounds.y = p->m_bounds.y; - if (p->m_vertical) { - p->m_sub1->m_bounds.w = p->m_bounds.w*(p->m_sub1->m_area/p->m_area); - p->m_sub1->m_bounds.h = p->m_bounds.h; - p->m_sub2->m_bounds.x = p->m_bounds.x + p->m_sub1->m_bounds.w; - p->m_sub2->m_bounds.w = p->m_bounds.w*(p->m_sub2->m_area/p->m_area); - p->m_sub2->m_bounds.y = p->m_bounds.y; - p->m_sub2->m_bounds.h = p->m_bounds.h; - } else { - p->m_sub1->m_bounds.h = p->m_bounds.h*(p->m_sub1->m_area/p->m_area); - p->m_sub1->m_bounds.w = p->m_bounds.w; - p->m_sub2->m_bounds.y = p->m_bounds.y + p->m_sub1->m_bounds.h; - p->m_sub2->m_bounds.h = p->m_bounds.h*(p->m_sub2->m_area/p->m_area); - p->m_sub2->m_bounds.x = p->m_bounds.x; - p->m_sub2->m_bounds.w = p->m_bounds.w; - } -} - - -// -------------------------------------------------------------------- -// incrementalSubpartition() -// -/// \brief Adds new cells to an existing partition. Partition sizes/locations are unchanged. -/// -/// The function recurses, adding new cells to appropriate subpartitions. -// -// -------------------------------------------------------------------- -void incrementalSubpartition(Partition *p, ConcreteCell *newCells [], const int numNewCells) { - int c; - ConcreteCell **newCells1 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells), - **newCells2 = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*numNewCells); - int numNewCells1 = 0, numNewCells2 = 0; - float cut_loc; - - assert(p); - - // add new cells to partition list - p->m_members = (ConcreteCell**)realloc(p->m_members, - sizeof(ConcreteCell*)*(p->m_numMembers+numNewCells)); - memcpy(&(p->m_members[p->m_numMembers]), newCells, sizeof(ConcreteCell*)*numNewCells); - p->m_numMembers += numNewCells; - - // if is a leaf partition, finished - if (p->m_leaf) return; - - // split new cells into sub-partitions based on location - if (p->m_vertical) { - cut_loc = p->m_sub2->m_bounds.x; - for(c=0; cm_x < cut_loc) - newCells1[numNewCells1++] = newCells[c]; - else - newCells2[numNewCells2++] = newCells[c]; - } else { - cut_loc = p->m_sub2->m_bounds.y; - for(c=0; cm_y < cut_loc) - newCells1[numNewCells1++] = newCells[c]; - else - newCells2[numNewCells2++] = newCells[c]; - } - - if (numNewCells1 > 0) incrementalSubpartition(p->m_sub1, newCells1, numNewCells1); - if (numNewCells2 > 0) incrementalSubpartition(p->m_sub2, newCells2, numNewCells2); - - free(newCells1); - free(newCells2); -} - - -// -------------------------------------------------------------------- -// incrementalPartition() -// -/// \brief Adds new cells to an existing partition. Partition sizes/locations are unchanged. -/// -/// The function recurses, adding new cells to appropriate subpartitions. -// -// -------------------------------------------------------------------- -void incrementalPartition() { - int c = 0, c2 = 0; - int numNewCells = 0; - ConcreteCell **allCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells), - **newCells = (ConcreteCell **)malloc(sizeof(ConcreteCell*)*g_place_numCells); - - assert(g_place_rootPartition); - - // update cell list of root partition - memcpy(allCells, g_place_concreteCells, sizeof(ConcreteCell*)*g_place_numCells); - qsort(allCells, g_place_numCells, sizeof(ConcreteCell*), cellSortByID); - qsort(g_place_rootPartition->m_members, g_place_rootPartition->m_numMembers, - sizeof(ConcreteCell*), cellSortByID); - - // scan sorted lists and collect cells not in partitions - while(!allCells[c++]); - while(!g_place_rootPartition->m_members[c2++]); - - for(; cm_numMembers && - allCells[c]->m_id > g_place_rootPartition->m_members[c2]->m_id) c2++; - while(c < g_place_numCells && - (c2 >= g_place_rootPartition->m_numMembers || - allCells[c]->m_id < g_place_rootPartition->m_members[c2]->m_id)) { - // a new cell! - newCells[numNewCells++] = allCells[c]; - c++; - } - } - - printf("QPRT-50 : \tincremental partitioning with %d new cells\n", numNewCells); - if (numNewCells>0) incrementalSubpartition(g_place_rootPartition, newCells, numNewCells); - - free(allCells); - free(newCells); -} diff --git a/src/phys/place/place_qpsolver.c b/src/phys/place/place_qpsolver.c deleted file mode 100644 index 9df9c6dc..00000000 --- a/src/phys/place/place_qpsolver.c +++ /dev/null @@ -1,1270 +0,0 @@ -/*===================================================================*/ -// -// place_qpsolver.c -// -// Philip Chong -// pchong@cadence.com -// -/*===================================================================*/ - -#include -#include -#include -#include - -#include "place_qpsolver.h" - -#undef QPS_DEBUG - -#define QPS_TOL 1.0e-3 -#define QPS_EPS (QPS_TOL * QPS_TOL) - -#define QPS_MAX_TOL 0.1 -#define QPS_LOOP_TOL 1.0e-3 - -#define QPS_RELAX_ITER 180 -#define QPS_MAX_ITER 200 -#define QPS_STEPSIZE_RETRIES 2 -#define QPS_MINSTEP 1.0e-6 -#define QPS_DEC_CHANGE 0.01 - -#define QPS_PRECON -#define QPS_PRECON_EPS 1.0e-9 - -#undef QPS_HOIST - -#if defined(QPS_DEBUG) -#define QPS_DEBUG_FILE "/tmp/qps_debug.log" -#endif - -#if 0 - /* ii is an array [0..p->num_cells-1] of indices from cells of original - problem to modified problem variables. If ii[k] >= 0, cell is an - independent cell; ii[k], ii[k]+1 are the indices of the corresponding - variables for the modified problem. If ii[k] == -1, cell is a fixed - cell. If ii[k] <= -2, cell is a dependent cell; -(ii[k]+2) is the index - of the corresponding COG constraint. */ -int *ii; - - /* gt is an array [0..p->cog_num-1] of indices from COG constraints to - locations in the gl array (in qps_problem_t). gt[k] is the offset into - gl where the kth constraint begins. */ -int *gt; - - /* n is the number of variables in the modified problem. n should be twice - the number of independent cells. */ -int n; - -qps_float_t *cp; /* current location during CG iteration */ -qps_float_t f; /* value of cost function at p */ - -#endif - -/**********************************************************************/ - -static void -qps_settp(qps_problem_t * p) -{ - /* Fill in the p->priv_tp array with the current locations of all cells - (independent, dependent and fixed). */ - - int i; - int t, u; - int pr; - qps_float_t rx, ry; - qps_float_t ta; - - int *ii = p->priv_ii; - qps_float_t *tp = p->priv_tp; - qps_float_t *cp = p->priv_cp; - - /* do independent and fixed cells first */ - for (i = p->num_cells; i--;) { - t = ii[i]; - if (t >= 0) { /* indep cell */ - tp[i * 2] = cp[t]; - tp[i * 2 + 1] = cp[t + 1]; - } - else if (t == -1) { /* fixed cell */ - tp[i * 2] = p->x[i]; - tp[i * 2 + 1] = p->y[i]; - } - } - /* now do dependent cells */ - for (i = p->num_cells; i--;) { - if (ii[i] < -1) { - t = -(ii[i] + 2); /* index of COG constraint */ - ta = 0.0; - rx = 0.0; - ry = 0.0; - pr = p->priv_gt[t]; - while ((u = p->cog_list[pr++]) >= 0) { - ta += p->area[u]; - if (u != i) { - rx -= p->area[u] * tp[u * 2]; - ry -= p->area[u] * tp[u * 2 + 1]; - } - } - rx += p->cog_x[t] * ta; - ry += p->cog_y[t] * ta; - tp[i * 2] = rx / p->area[i]; - tp[i * 2 + 1] = ry / p->area[i]; - } - } - -#if (QPS_DEBUG > 5) - fprintf(p->priv_fp, "### qps_settp()\n"); - for (i = 0; i < p->num_cells; i++) { - fprintf(p->priv_fp, "%f %f\n", tp[i * 2], tp[i * 2 + 1]); - } -#endif -} - -/**********************************************************************/ - -static qps_float_t -qps_func(qps_problem_t * p) -{ - /* Return f(p). qps_settp() should have already been called before - entering here */ - - int j, k; - int pr; - qps_float_t jx, jy, tx, ty; - qps_float_t f; - qps_float_t w; - -#if !defined(QPS_HOIST) - int i; - int st; - qps_float_t kx, ky, sx, sy; - qps_float_t t; -#endif - - qps_float_t *tp = p->priv_tp; - - f = 0.0; - pr = 0; - for (j = 0; j < p->num_cells; j++) { - jx = tp[j * 2]; - jy = tp[j * 2 + 1]; - while ((k = p->priv_cc[pr]) >= 0) { - w = p->priv_cw[pr]; - tx = tp[k * 2] - jx; - ty = tp[k * 2 + 1] - jy; - f += w * (tx * tx + ty * ty); - pr++; - } - pr++; - } - p->f = f; - -#if !defined(QPS_HOIST) - /* loop penalties */ - pr = 0; - for (i = 0; i < p->loop_num; i++) { - t = 0.0; - j = st = p->loop_list[pr++]; - jx = sx = tp[j * 2]; - jy = sy = tp[j * 2 + 1]; - while ((k = p->loop_list[pr]) >= 0) { - kx = tp[k * 2]; - ky = tp[k * 2 + 1]; - tx = jx - kx; - ty = jy - ky; - t += tx * tx + ty * ty; - j = k; - jx = kx; - jy = ky; - pr++; - } - tx = jx - sx; - ty = jy - sy; - t += tx * tx + ty * ty; - t -= p->loop_max[i]; -#if (QPS_DEBUG > 5) - fprintf(p->priv_fp, "### qps_penalty() %d %f %f\n", - i, p->loop_max[i], t); -#endif - p->priv_lt[i] = t; - f += p->loop_penalty[i] * t; - pr++; - } -#endif /* QPS_HOIST */ - - if (p->max_enable) { - for (j = p->num_cells; j--;) { - f += p->priv_mxl[j] * (-tp[j * 2]); - f += p->priv_mxh[j] * (tp[j * 2] - p->max_x); - f += p->priv_myl[j] * (-tp[j * 2 + 1]); - f += p->priv_myh[j] * (tp[j * 2 + 1] - p->max_y); - } - } - -#if (QPS_DEBUG > 5) - fprintf(p->priv_fp, "### qps_func() %f %f\n", f, p->f); -#endif - return f; -} - -/**********************************************************************/ - -static void -qps_dfunc(qps_problem_t * p, qps_float_t * d) -{ - /* Set d to grad f(p). First computes partial derivatives wrt all cells - then finds gradient wrt only the independent cells. qps_settp() should - have already been called before entering here */ - - int i, j, k; - int pr = 0; - qps_float_t jx, jy, kx, ky, tx, ty; - int ji, ki; - qps_float_t w; - -#if !defined(QPS_HOIST) - qps_float_t sx, sy; - int st; -#endif - - qps_float_t *tp = p->priv_tp; - qps_float_t *tp2 = p->priv_tp2; - - /* compute partials and store in tp2 */ - for (i = p->num_cells; i--;) { - tp2[i * 2] = 0.0; - tp2[i * 2 + 1] = 0.0; - } - for (j = 0; j < p->num_cells; j++) { - jx = tp[j * 2]; - jy = tp[j * 2 + 1]; - while ((k = p->priv_cc[pr]) >= 0) { - w = 2.0 * p->priv_cw[pr]; - kx = tp[k * 2]; - ky = tp[k * 2 + 1]; - tx = w * (jx - kx); - ty = w * (jy - ky); - tp2[j * 2] += tx; - tp2[k * 2] -= tx; - tp2[j * 2 + 1] += ty; - tp2[k * 2 + 1] -= ty; - pr++; - } - pr++; - } - -#if !defined(QPS_HOIST) - /* loop penalties */ - pr = 0; - for (i = 0; i < p->loop_num; i++) { - j = st = p->loop_list[pr++]; - jx = sx = tp[j * 2]; - jy = sy = tp[j * 2 + 1]; - w = 2.0 * p->loop_penalty[i]; - while ((k = p->loop_list[pr]) >= 0) { - kx = tp[k * 2]; - ky = tp[k * 2 + 1]; - tx = w * (jx - kx); - ty = w * (jy - ky); - tp2[j * 2] += tx; - tp2[k * 2] -= tx; - tp2[j * 2 + 1] += ty; - tp2[k * 2 + 1] -= ty; - j = k; - jx = kx; - jy = ky; - pr++; - } - tx = w * (jx - sx); - ty = w * (jy - sy); - tp2[j * 2] += tx; - tp2[st * 2] -= tx; - tp2[j * 2 + 1] += ty; - tp2[st * 2 + 1] -= ty; - pr++; - } -#endif /* QPS_HOIST */ - - if (p->max_enable) { - for (j = p->num_cells; j--;) { - tp2[j * 2] += p->priv_mxh[j] - p->priv_mxl[j]; - tp2[j * 2 + 1] += p->priv_myh[j] - p->priv_myl[j]; - } - } - -#if (QPS_DEBUG > 5) - fprintf(p->priv_fp, "### qps_dfunc() partials\n"); - for (j = 0; j < p->num_cells; j++) { - fprintf(p->priv_fp, "%f %f\n", tp2[j * 2], tp2[j * 2 + 1]); - } -#endif - - /* translate partials to independent variables */ - for (j = p->priv_n; j--;) { - d[j] = 0.0; - } - for (j = p->num_cells; j--;) { - ji = p->priv_ii[j]; - if (ji >= 0) { /* indep var */ - d[ji] += tp2[j * 2]; - d[ji + 1] += tp2[j * 2 + 1]; - } - else if (ji < -1) { /* dependent variable */ - ji = -(ji + 2); /* get COG index */ - pr = p->priv_gt[ji]; - while ((k = p->cog_list[pr]) >= 0) { - ki = p->priv_ii[k]; - if (ki >= 0) { - w = p->priv_gw[pr]; -#if (QPS_DEBUG > 0) - assert(fabs(w - p->area[k] / p->area[j]) < 1.0e-6); -#endif - d[ki] -= tp2[j * 2] * w; - d[ki + 1] -= tp2[j * 2 + 1] * w; - } - pr++; - } - } - } - -#if (QPS_DEBUG > 5) - fprintf(p->priv_fp, "### qps_dfunc() gradient\n"); - for (j = 0; j < p->priv_n; j++) { - fprintf(p->priv_fp, "%f\n", d[j]); - } -#endif -} - -/**********************************************************************/ - -static void -qps_linmin(qps_problem_t * p, qps_float_t dgg, qps_float_t * h) -{ - /* Perform line minimization. p->priv_cp is the current location, h is - direction of the gradient. Updates p->priv_cp to line minimal position - based on formulas from "Handbook of Applied Optimization", Pardalos and - Resende, eds., Oxford Univ. Press, 2002. qps_settp() should have - already been called before entering here. Since p->priv_cp is changed, - p->priv_tp array becomes invalid following this routine. */ - - int i, j, k; - int pr; - int ji, ki; - qps_float_t jx, jy, kx, ky; - qps_float_t f = 0.0; - qps_float_t w; - -#if !defined(QPS_HOIST) - int st; - qps_float_t sx, sy, tx, ty; - qps_float_t t; -#endif - - qps_float_t *tp = p->priv_tp; - - /* translate h vector to partials over all variables and store in tp */ - for (i = p->num_cells; i--;) { - tp[i * 2] = 0.0; - tp[i * 2 + 1] = 0.0; - } - for (j = p->num_cells; j--;) { - ji = p->priv_ii[j]; - if (ji >= 0) { /* indep cell */ - tp[j * 2] = h[ji]; - tp[j * 2 + 1] = h[ji + 1]; - } - else if (ji < -1) { /* dep cell */ - ji = -(ji + 2); /* get COG index */ - pr = p->priv_gt[ji]; - while ((k = p->cog_list[pr]) >= 0) { - ki = p->priv_ii[k]; - if (ki >= 0) { - w = p->priv_gw[pr]; -#if (QPS_DEBUG > 0) - assert(fabs(w - p->area[k] / p->area[j]) < 1.0e-6); -#endif - tp[j * 2] -= h[ki] * w; - tp[j * 2 + 1] -= h[ki + 1] * w; - } - pr++; - } - } - } - - /* take product x^T Z^T C Z x */ - pr = 0; - for (j = 0; j < p->num_cells; j++) { - jx = tp[j * 2]; - jy = tp[j * 2 + 1]; - while ((k = p->priv_cc[pr]) >= 0) { - w = p->priv_cw[pr]; - kx = tp[k * 2] - jx; - ky = tp[k * 2 + 1] - jy; - f += w * (kx * kx + ky * ky); - pr++; - } - pr++; - } - -#if !defined(QPS_HOIST) - /* add loop penalties */ - pr = 0; - for (i = 0; i < p->loop_num; i++) { - t = 0.0; - j = st = p->loop_list[pr++]; - jx = sx = tp[j * 2]; - jy = sy = tp[j * 2 + 1]; - while ((k = p->loop_list[pr]) >= 0) { - kx = tp[k * 2]; - ky = tp[k * 2 + 1]; - tx = jx - kx; - ty = jy - ky; - t += tx * tx + ty * ty; - j = k; - jx = kx; - jy = ky; - pr++; - } - tx = jx - sx; - ty = jy - sy; - t += tx * tx + ty * ty; - f += p->loop_penalty[i] * t; - pr++; - } -#endif /* QPS_HOIST */ - -#if (QPS_DEBUG > 0) - assert(f); -#endif - - /* compute step size */ - f = (dgg / f) / 2.0; - for (j = p->priv_n; j--;) { - p->priv_cp[j] += f * h[j]; - } -#if (QPS_DEBUG > 5) - fprintf(p->priv_fp, "### qps_linmin() step %f\n", f); - for (j = 0; j < p->priv_n; j++) { - fprintf(p->priv_fp, "%f\n", p->priv_cp[j]); - } -#endif -} - -/**********************************************************************/ - -static void -qps_cgmin(qps_problem_t * p) -{ - /* Perform CG minimization. Mostly from "Numerical Recipes", Press et al., - Cambridge Univ. Press, 1992, with some changes to help performance in - our restricted problem domain. */ - - qps_float_t fp, gg, dgg, gam; - qps_float_t t; - int i, j; - - int n = p->priv_n; - qps_float_t *g = p->priv_g; - qps_float_t *h = p->priv_h; - qps_float_t *xi = p->priv_xi; - - qps_settp(p); - fp = qps_func(p); - qps_dfunc(p, g); - - dgg = 0.0; - for (j = n; j--;) { - g[j] = -g[j]; - h[j] = g[j]; -#if defined(QPS_PRECON) - h[j] *= p->priv_pcgt[j]; -#endif - dgg += g[j] * h[j]; - } - - for (i = 0; i < 2 * n; i++) { - -#if (QPS_DEBUG > 5) - fprintf(p->priv_fp, "### qps_cgmin() top\n"); - for (j = 0; j < p->priv_n; j++) { - fprintf(p->priv_fp, "%f\n", p->priv_cp[j]); - } -#endif - - if (dgg == 0.0) { - break; - } - qps_linmin(p, dgg, h); - qps_settp(p); - p->priv_f = qps_func(p); - if (fabs((p->priv_f) - fp) <= - (fabs(p->priv_f) + fabs(fp) + QPS_EPS) * QPS_TOL / 2.0) { - break; - } - fp = p->priv_f; - qps_dfunc(p, xi); - gg = dgg; - dgg = 0.0; - for (j = n; j--;) { - t = xi[j] * xi[j]; -#if defined(QPS_PRECON) - t *= p->priv_pcgt[j]; -#endif - dgg += t; - } - gam = dgg / gg; - for (j = n; j--;) { - g[j] = -xi[j]; - t = g[j]; -#if defined(QPS_PRECON) - t *= p->priv_pcgt[j]; -#endif - h[j] = t + gam * h[j]; - } - } -#if (QPS_DEBUG > 0) - fprintf(p->priv_fp, "### CG ITERS=%d %d %d\n", i, p->cog_num, p->loop_num); -#endif - if (i == 2 * n) { - fprintf(stderr, "### Too many iterations in qps_cgmin()\n"); -#if defined(QPS_DEBUG) - fprintf(p->priv_fp, "### Too many iterations in qps_cgmin()\n"); -#endif - } -} - -/**********************************************************************/ - -void -qps_init(qps_problem_t * p) -{ - int i, j; - int pr, pw; - -#if defined(QPS_DEBUG) - p->priv_fp = fopen(QPS_DEBUG_FILE, "a"); - assert(p->priv_fp); -#endif - -#if (QPS_DEBUG > 5) - fprintf(p->priv_fp, "### n=%d gn=%d ln=%d\n", p->num_cells, p->cog_num, - p->loop_num); - pr = 0; - fprintf(p->priv_fp, "### (c w) values\n"); - for (i = 0; i < p->num_cells; i++) { - fprintf(p->priv_fp, "net %d: ", i); - while (p->connect[pr] >= 0) { - fprintf(p->priv_fp, "(%d %f) ", p->connect[pr], p->edge_weight[pr]); - pr++; - } - fprintf(p->priv_fp, "(-1 -1.0)\n"); - pr++; - } - fprintf(p->priv_fp, "### (x y f) values\n"); - for (i = 0; i < p->num_cells; i++) { - fprintf(p->priv_fp, "cell %d: (%f %f %d)\n", i, p->x[i], p->y[i], - p->fixed[i]); - } -#if 0 - if (p->cog_num) { - fprintf(p->priv_fp, "### ga values\n"); - for (i = 0; i < p->num_cells; i++) { - fprintf(p->priv_fp, "cell %d: (%f)\n", i, p->area[i]); - } - } - pr = 0; - fprintf(p->priv_fp, "### gl values\n"); - for (i = 0; i < p->cog_num; i++) { - fprintf(p->priv_fp, "cog %d: ", i); - while (p->cog_list[pr] >= 0) { - fprintf(p->priv_fp, "%d ", p->cog_list[pr]); - pr++; - } - fprintf(p->priv_fp, "-1\n"); - pr++; - } - fprintf(p->priv_fp, "### (gx gy) values\n"); - for (i = 0; i < p->cog_num; i++) { - fprintf(p->priv_fp, "cog %d: (%f %f)\n", i, p->cog_x[i], p->cog_y[i]); - } -#endif -#endif /* QPS_DEBUG */ - - p->priv_ii = (int *)malloc(p->num_cells * sizeof(int)); - assert(p->priv_ii); - - p->max_enable = 0; - - p->priv_fopt = 0.0; - - /* canonify c and w */ - pr = pw = 0; - for (i = 0; i < p->num_cells; i++) { - while ((j = p->connect[pr]) >= 0) { - if (j > i) { - pw++; - } - pr++; - } - pw++; - pr++; - } - p->priv_cc = (int *)malloc(pw * sizeof(int)); - assert(p->priv_cc); - p->priv_cr = (int *)malloc(p->num_cells * sizeof(int)); - assert(p->priv_cr); - p->priv_cw = (qps_float_t*)malloc(pw * sizeof(qps_float_t)); - assert(p->priv_cw); - p->priv_ct = (qps_float_t*)malloc(pw * sizeof(qps_float_t)); - assert(p->priv_ct); - p->priv_cm = pw; - pr = pw = 0; - for (i = 0; i < p->num_cells; i++) { - p->priv_cr[i] = pw; - while ((j = p->connect[pr]) >= 0) { - if (j > i) { - p->priv_cc[pw] = p->connect[pr]; - p->priv_ct[pw] = p->edge_weight[pr]; - pw++; - } - pr++; - } - p->priv_cc[pw] = -1; - p->priv_ct[pw] = -1.0; - pw++; - pr++; - } - assert(pw == p->priv_cm); - - /* temp arrays for function eval */ - p->priv_tp = (qps_float_t *) malloc(4 * p->num_cells * sizeof(qps_float_t)); - assert(p->priv_tp); - p->priv_tp2 = p->priv_tp + 2 * p->num_cells; -} - -/**********************************************************************/ - -static qps_float_t -qps_estopt(qps_problem_t * p) -{ - int i, j, cell; - qps_float_t r; - qps_float_t *t1, *t2; - qps_float_t t; - - if (p->max_enable) { - r = 0.0; - t1 = (qps_float_t *) malloc(2 * p->num_cells * sizeof(qps_float_t)); -#if (QPS_DEBUG > 0) - assert(t1); -#endif - for (i = 2 * p->num_cells; i--;) { - t1[i] = 0.0; - } - j = 0; - for (i = 0; i < p->cog_num; i++) { - while ((cell = p->cog_list[j]) >= 0) { - t1[cell * 2] = p->cog_x[i]; - t1[cell * 2 + 1] = p->cog_y[i]; - j++; - } - j++; - } - t2 = p->priv_tp; - p->priv_tp = t1; - r = qps_func(p); - p->priv_tp = t2; - free(t1); - t = (p->max_x * p->max_x + p->max_y * p->max_y); - t *= p->num_cells; - for (i = p->num_cells; i--;) { - if (p->fixed[i]) { - r += t; - } - } - } - else { - r = p->priv_f; - } - if (p->loop_num) { - /* FIXME hacky */ - r *= 8.0; - } - return r; -} - -/**********************************************************************/ - -static void -qps_solve_inner(qps_problem_t * p) -{ - int i; - qps_float_t t; - qps_float_t z; - qps_float_t pm1, pm2, tp; - qps_float_t *tw; -#if defined(QPS_HOIST) - int j, k; - qps_float_t jx, jy, kx, ky, sx, sy, tx, ty; - int pr, st; -#endif - - tw = p->priv_cw; -#if defined(QPS_HOIST) - if (!p->loop_num) { - p->priv_cw = p->priv_ct; - } - else { - for(i=p->priv_cm; i--;) { - p->priv_cw[i] = p->priv_ct[i]; - } - /* augment with loop penalties */ - pr = 0; - for (i = 0; i < p->loop_num; i++) { - while ((j = p->priv_la[pr++]) != -1) { - if (j >= 0) { - p->priv_cw[j] += p->loop_penalty[i]; - } - } - pr++; - } - } -#else /* !QPS_HOIST */ - p->priv_cw = p->priv_ct; -#endif /* QPS_HOIST */ - - qps_cgmin(p); - - if (p->max_enable || p->loop_num) { - if (p->max_enable == 1 || (p->loop_num && p->loop_k == 0)) { - p->priv_eps = 2.0; - p->priv_fmax = p->priv_f; - p->priv_fprev = p->priv_f; - p->priv_fopt = qps_estopt(p); - p->priv_pn = 0; - p->loop_fail = 0; - } - else { - if (p->priv_f < p->priv_fprev && - (p->priv_fprev - p->priv_f) > - QPS_DEC_CHANGE * fabs(p->priv_fprev)) { - if (p->priv_pn++ >= QPS_STEPSIZE_RETRIES) { - p->priv_eps /= 2.0; - p->priv_pn = 0; - } - } - p->priv_fprev = p->priv_f; - if (p->priv_fmax < p->priv_f) { - p->priv_fmax = p->priv_f; - } - if (p->priv_f >= p->priv_fopt) { - p->priv_fopt = p->priv_fmax * 2.0; - p->loop_fail |= 2; -#if (QPS_DEBUG > 0) - fprintf(p->priv_fp, "### warning: changing fopt\n"); -#endif - } - } -#if (QPS_DEBUG > 0) - fprintf(p->priv_fp, "### max_stat %.2e %.2e %.2e %.2e\n", - p->priv_f, p->priv_eps, p->priv_fmax, p->priv_fopt); - fflush(p->priv_fp); -#endif - } - - p->loop_done = 1; - if (p->loop_num) { -#if (QPS_DEBUG > 0) - fprintf(p->priv_fp, "### begin_update %d\n", p->loop_k); -#endif - p->loop_k++; - -#if defined(QPS_HOIST) - /* calc loop penalties */ - pr = 0; - for (i = 0; i < p->loop_num; i++) { - t = 0.0; - j = st = p->loop_list[pr++]; - jx = sx = p->priv_tp[j * 2]; - jy = sy = p->priv_tp[j * 2 + 1]; - while ((k = p->loop_list[pr]) >= 0) { - kx = p->priv_tp[k * 2]; - ky = p->priv_tp[k * 2 + 1]; - tx = jx - kx; - ty = jy - ky; - t += tx * tx + ty * ty; - j = k; - jx = kx; - jy = ky; - pr++; - } - tx = jx - sx; - ty = jy - sy; - t += tx * tx + ty * ty; - p->priv_lt[i] = t - p->loop_max[i]; - pr++; - } -#endif /* QPS_HOIST */ - - /* check KKT conditions */ -#if (QPS_DEBUG > 1) - for (i = p->loop_num; i--;) { - if (p->loop_penalty[i] != 0.0) { - fprintf(p->priv_fp, "### penalty %d %.2e\n", i, p->loop_penalty[i]); - } - } -#endif - t = 0.0; - for (i = p->loop_num; i--;) { - if (p->priv_lt[i] > 0.0 || p->loop_penalty[i] > 0.0) { - t += p->priv_lt[i] * p->priv_lt[i]; - } - if (fabs(p->priv_lt[i]) < QPS_LOOP_TOL) { -#if (QPS_DEBUG > 4) - fprintf(p->priv_fp, "### skip %d %f\n", i, p->priv_lt[i]); -#endif - continue; - } - z = QPS_LOOP_TOL * p->loop_max[i]; - if (p->priv_lt[i] > z || (p->loop_k < QPS_RELAX_ITER && - p->loop_penalty[i] * p->priv_lt[i] < -z)) { - p->loop_done = 0; -#if (QPS_DEBUG > 1) - fprintf(p->priv_fp, "### not_done %d %f %f %f %f\n", i, - p->priv_lt[i], z, p->loop_max[i], p->loop_penalty[i]); -#endif - } -#if (QPS_DEBUG > 5) - else { - fprintf(p->priv_fp, "### done %d %f %f %f %f\n", i, - p->priv_lt[i], z, p->loop_max[i], p->loop_penalty[i]); - } -#endif - } - /* update penalties */ - if (!p->loop_done) { - t = p->priv_eps * (p->priv_fopt - p->priv_f) / t; - tp = 0.0; - for (i = p->loop_num; i--;) { - pm1 = p->loop_penalty[i]; -#if (QPS_DEBUG > 5) - fprintf(p->priv_fp, "### update %d %.2e %.2e %.2e %.2e %.2e\n", i, - t, p->priv_lt[i], t * p->priv_lt[i], pm1, p->loop_max[i]); -#endif - p->loop_penalty[i] += t * p->priv_lt[i]; - if (p->loop_penalty[i] < 0.0) { - p->loop_penalty[i] = 0.0; - } - pm2 = p->loop_penalty[i]; - tp += fabs(pm1 - pm2); - } -#if (QPS_DEBUG > 4) - fprintf(p->priv_fp, "### penalty mag %f\n", tp); -#endif - } - } - - p->max_done = 1; - if (p->max_enable) { -#if (QPS_DEBUG > 4) - fprintf(p->priv_fp, "### begin_max_update %d\n", p->max_enable); -#endif - t = 0.0; - for (i = p->num_cells; i--;) { - z = -(p->x[i]); - t += z * z; - if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER && - p->priv_mxl[i] * z < -QPS_MAX_TOL)) { - p->max_done = 0; -#if (QPS_DEBUG > 4) - fprintf(p->priv_fp, "### nxl %d %f %f\n", i, z, p->priv_mxl[i]); -#endif - } - z = (p->x[i] - p->max_x); - t += z * z; - if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER && - p->priv_mxh[i] * z < -QPS_MAX_TOL)) { - p->max_done = 0; -#if (QPS_DEBUG > 4) - fprintf(p->priv_fp, "### nxh %d %f %f\n", i, z, p->priv_mxh[i]); -#endif - } - z = -(p->y[i]); - t += z * z; - if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER && - p->priv_myl[i] * z < -QPS_MAX_TOL)) { - p->max_done = 0; -#if (QPS_DEBUG > 4) - fprintf(p->priv_fp, "### nyl %d %f %f\n", i, z, p->priv_myl[i]); -#endif - } - z = (p->y[i] - p->max_y); - t += z * z; - if (z > QPS_TOL || (p->max_enable < QPS_RELAX_ITER && - p->priv_myh[i] * z < -QPS_MAX_TOL)) { - p->max_done = 0; -#if (QPS_DEBUG > 4) - fprintf(p->priv_fp, "### nyh %d %f %f\n", i, z, p->priv_myh[i]); -#endif - } - } -#if (QPS_DEBUG > 4) - fprintf(p->priv_fp, "### max_done %d %f\n", p->max_done, t); -#endif - if (!p->max_done) { - t = p->priv_eps * (p->priv_fopt - p->priv_f) / t; - tp = 0.0; - for (i = p->num_cells; i--;) { - z = -(p->x[i]); - pm1 = p->priv_mxl[i]; - p->priv_mxl[i] += t * z; - if (p->priv_mxl[i] < 0.0) { - p->priv_mxl[i] = 0.0; - } - pm2 = p->priv_mxl[i]; - tp += fabs(pm1 - pm2); - - z = (p->x[i] - p->max_x); - pm1 = p->priv_mxh[i]; - p->priv_mxh[i] += t * z; - if (p->priv_mxh[i] < 0.0) { - p->priv_mxh[i] = 0.0; - } - pm2 = p->priv_mxh[i]; - tp += fabs(pm1 - pm2); - - z = -(p->y[i]); - pm1 = p->priv_myl[i]; - p->priv_myl[i] += t * z; - if (p->priv_myl[i] < 0.0) { - p->priv_myl[i] = 0.0; - } - pm2 = p->priv_myl[i]; - tp += fabs(pm1 - pm2); - - z = (p->y[i] - p->max_y); - pm1 = p->priv_myh[i]; - p->priv_myh[i] += t * z; - if (p->priv_myh[i] < 0.0) { - p->priv_myh[i] = 0.0; - } - pm2 = p->priv_myh[i]; - tp += fabs(pm1 - pm2); - } - } -#if (QPS_DEBUG > 4) - for (i = p->num_cells; i--;) { - fprintf(p->priv_fp, "### max_penalty %d %f %f %f %f\n", i, - p->priv_mxl[i], p->priv_mxh[i], p->priv_myl[i], p->priv_myh[i]); - } -#endif - p->max_enable++; - } - - if (p->loop_k >= QPS_MAX_ITER || p->priv_eps < QPS_MINSTEP) { - p->loop_fail |= 1; - } - - if (p->loop_fail) { - p->loop_done = 1; - } - - p->priv_cw = tw; -} - -/**********************************************************************/ - -void -qps_solve(qps_problem_t * p) -{ - int i, j; - int pr, pw; - qps_float_t bk; - int tk; - -#if defined(QPS_PRECON) - int c; - qps_float_t t; -#endif - -#if defined(QPS_HOIST) - int k; - int st; - int m1, m2; -#endif - - if (p->max_enable) { - p->priv_mxl = (qps_float_t *) - malloc(4 * p->num_cells * sizeof(qps_float_t)); - assert(p->priv_mxl); - p->priv_mxh = p->priv_mxl + p->num_cells; - p->priv_myl = p->priv_mxl + 2 * p->num_cells; - p->priv_myh = p->priv_mxl + 3 * p->num_cells; - for (i = 4 * p->num_cells; i--;) { - p->priv_mxl[i] = 0.0; - } - } - - /* flag fixed cells with -1 */ - for (i = p->num_cells; i--;) { - p->priv_ii[i] = (p->fixed[i]) ? (-1) : (0); - } - - /* read gl and set up dependent variables */ - if (p->cog_num) { - p->priv_gt = (int *)malloc(p->cog_num * sizeof(int)); - assert(p->priv_gt); - p->priv_gm = (qps_float_t*)malloc(p->cog_num * sizeof(qps_float_t)); - assert(p->priv_gm); - pr = 0; - for (i = 0; i < p->cog_num; i++) { - tk = -1; - bk = -1.0; - pw = pr; - while ((j = p->cog_list[pr++]) >= 0) { - if (!p->fixed[j]) { - /* use largest entry for numerical stability; see Gordian paper */ - if (p->area[j] > bk) { - tk = j; - bk = p->area[j]; - } - } - } - assert(bk > 0.0); - /* dependent variables have index=(-2-COG_constraint) */ - p->priv_ii[tk] = -2 - i; - p->priv_gt[i] = pw; - p->priv_gm[i] = bk; - } - p->priv_gw = (qps_float_t*)malloc(pr * sizeof(qps_float_t)); - assert(p->priv_gw); - pr = 0; - for (i = 0; i < p->cog_num; i++) { - while ((j = p->cog_list[pr]) >= 0) { - p->priv_gw[pr] = p->area[j] / p->priv_gm[i]; - pr++; - } - p->priv_gw[pr] = -1.0; - pr++; - } - } - - /* set up indexes from independent floating cells to variables */ - p->priv_n = 0; - for (i = p->num_cells; i--;) { - if (!p->priv_ii[i]) { - p->priv_ii[i] = 2 * (p->priv_n++); - } - } - p->priv_n *= 2; - -#if (QPS_DEBUG > 5) - for (i = 0; i < p->num_cells; i++) { - fprintf(p->priv_fp, "### ii %d %d\n", i, p->priv_ii[i]); - } -#endif - -#if defined(QPS_PRECON) - p->priv_pcg = (qps_float_t *) malloc(p->num_cells * sizeof(qps_float_t)); - assert(p->priv_pcg); - p->priv_pcgt = (qps_float_t *) malloc(p->priv_n * sizeof(qps_float_t)); - assert(p->priv_pcgt); - for (i = p->num_cells; i--;) { - p->priv_pcg[i] = 0.0; - } - pr = 0; - for (i = 0; i < p->num_cells; i++) { - while ((c = p->priv_cc[pr]) >= 0) { - t = p->priv_ct[pr]; - p->priv_pcg[i] += t; - p->priv_pcg[c] += t; - pr++; - } - pr++; - } - pr = 0; - for (i = 0; i < p->loop_num; i++) { - t = 2.0 * p->loop_penalty[i]; - while ((c = p->loop_list[pr++]) >= 0) { - p->priv_pcg[c] += t; - } - pr++; - } -#if (QPS_DEBUG > 6) - for (i = p->num_cells; i--;) { - fprintf(p->priv_fp, "### precon %d %.2e\n", i, p->priv_pcg[i]); - } -#endif - for (i = p->priv_n; i--;) { - p->priv_pcgt[i] = 0.0; - } - for (i = 0; i < p->num_cells; i++) { - c = p->priv_ii[i]; - if (c >= 0) { - t = p->priv_pcg[i]; - p->priv_pcgt[c] += t; - p->priv_pcgt[c + 1] += t; - } -#if 0 - else if (c < -1) { - pr = p->priv_gt[-(c+2)]; - while ((j = p->cog_list[pr++]) >= 0) { - ji = p->priv_ii[j]; - if (ji >= 0) { - w = p->area[j] / p->area[i]; - t = w * w * p->priv_pcg[i]; - p->priv_pcgt[ji] += t; - p->priv_pcgt[ji + 1] += t; - } - } - } -#endif - } - for (i = 0; i < p->priv_n; i++) { - t = p->priv_pcgt[i]; - if (fabs(t) < QPS_PRECON_EPS || fabs(t) > 1.0/QPS_PRECON_EPS) { - p->priv_pcgt[i] = 1.0; - } - else { - p->priv_pcgt[i] = 1.0 / p->priv_pcgt[i]; - } - } -#endif - - /* allocate variable storage */ - p->priv_cp = (qps_float_t *) malloc(4 * p->priv_n * sizeof(qps_float_t)); - assert(p->priv_cp); - - /* temp arrays for cg */ - p->priv_g = p->priv_cp + p->priv_n; - p->priv_h = p->priv_cp + 2 * p->priv_n; - p->priv_xi = p->priv_cp + 3 * p->priv_n; - - /* set values */ - for (i = p->num_cells; i--;) { - if (p->priv_ii[i] >= 0) { - p->priv_cp[p->priv_ii[i]] = p->x[i]; - p->priv_cp[p->priv_ii[i] + 1] = p->y[i]; - } - } - - if (p->loop_num) { - p->priv_lt = (qps_float_t *) malloc(p->loop_num * sizeof(qps_float_t)); - assert(p->priv_lt); -#if defined(QPS_HOIST) - pr = 0; - for (i=p->loop_num; i--;) { - while (p->loop_list[pr++] >= 0) { - } - pr++; - } - p->priv_lm = pr; - p->priv_la = (int *) malloc(pr * sizeof(int)); - assert(p->priv_la); - pr = 0; - for (i = 0; i < p->loop_num; i++) { - j = st = p->loop_list[pr++]; - while ((k = p->loop_list[pr]) >= 0) { - if (j > k) { - m1 = k; - m2 = j; - } - else { - assert(k > j); - m1 = j; - m2 = k; - } - pw = p->priv_cr[m1]; - while (p->priv_cc[pw] != m2) { -/* assert(p->priv_cc[pw] >= 0); */ - if (p->priv_cc[pw] < 0) { - pw = -2; - break; - } - pw++; - } - p->priv_la[pr-1] = pw; - j = k; - pr++; - } - if (j > st) { - m1 = st; - m2 = j; - } - else { - assert(st > j); - m1 = j; - m2 = st; - } - pw = p->priv_cr[m1]; - while (p->priv_cc[pw] != m2) { -/* assert(p->priv_cc[pw] >= 0); */ - if (p->priv_cc[pw] < 0) { - pw = -2; - break; - } - pw++; - } - p->priv_la[pr-1] = pw; - p->priv_la[pr] = -1; - pr++; - } -#endif /* QPS_HOIST */ - } - - do { - qps_solve_inner(p); - } while (!p->loop_done || !p->max_done); - - /* retrieve values */ - /* qps_settp() should have already been called at this point */ - for (i = p->num_cells; i--;) { - p->x[i] = p->priv_tp[i * 2]; - p->y[i] = p->priv_tp[i * 2 + 1]; - } -#if (QPS_DEBUG > 5) - for (i = p->num_cells; i--;) { - fprintf(p->priv_fp, "### cloc %d %f %f\n", i, p->x[i], p->y[i]); - } -#endif - - free(p->priv_cp); - if (p->max_enable) { - free(p->priv_mxl); - } - if (p->cog_num) { - free(p->priv_gt); - free(p->priv_gm); - free(p->priv_gw); - } - if(p->loop_num) { - free(p->priv_lt); -#if defined(QPS_HOIST) - free(p->priv_la); -#endif - } - -#if defined(QPS_PRECON) - free(p->priv_pcg); - free(p->priv_pcgt); -#endif -} - -/**********************************************************************/ - -void -qps_clean(qps_problem_t * p) -{ - free(p->priv_tp); - free(p->priv_ii); - free(p->priv_cc); - free(p->priv_cr); - free(p->priv_cw); - free(p->priv_ct); - -#if defined(QPS_DEBUG) - fclose(p->priv_fp); -#endif /* QPS_DEBUG */ -} - -/**********************************************************************/ diff --git a/src/phys/place/place_qpsolver.h b/src/phys/place/place_qpsolver.h deleted file mode 100644 index 08771d6b..00000000 --- a/src/phys/place/place_qpsolver.h +++ /dev/null @@ -1,140 +0,0 @@ -/*===================================================================*/ -// -// place_qpsolver.h -// -// Philip Chong -// pchong@cadence.com -// -/*===================================================================*/ - -#if !defined(_QPS_H) -#define _QPS_H - -#include - -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus */ - - typedef float qps_float_t; - - typedef struct qps_problem { - - /* Basic stuff */ - int num_cells; /* Total number of cells (both fixed and - floating) to be placed. */ - int *connect; /* Connectivity array. Must contain at least - num_cells elements with value -1. The - entries which precede the first element - with value -1 are the indices of the cells - which connect to cell 0; the entries - which lie between the first and second - elements with value -1 are the indices of - the cells which connect to cell 1; etc. - Example: cells 0 and 1 are connected - together, and 1 and 2 are connected as - well. *connect = { 1, -1, 0, 2, -1, 1, -1 - }. */ - qps_float_t *edge_weight; /* Same structure as connectivity array, but - giving the weights assigned to each edge - instead. */ - qps_float_t *x; /* num_cells element array which contains the - x-coordinates of the cells. This is used - for the initial values in the iterative - solution of floating cells, and for the - fixed location of fixed cells. */ - qps_float_t *y; /* num_cells element array of - y-coordinates. */ - int *fixed; /* num_cells element array with value 1 if - corresponding cell is fixed, 0 if - floating. */ - qps_float_t f; /* return value for sum-of-square - wirelengths. */ - - /* COG stuff */ - int cog_num; /* Number of COG constraints. */ - int *cog_list; /* Array indicating for each COG constraint - which cells belong to that constraint. - Format is similar to c array: there must - be at least cog_num elements with value - -1. The entries of cog_list preceding the - first -1 element are the indices of the - cells which belong to the first COG - constraint; etc. Example: cells 0 and 1 - belong to one COG constraint, cells 4 and - 5 belong to another. *cog_list= { 0, 1, - -1, 4, 5, -1 }. */ - qps_float_t *cog_x; /* cog_num element array whose values are the - x-coordinates for the corresponding COG - constraints. */ - qps_float_t *cog_y; /* cog_num element array whose values are the - y-coordinates for the corresponding COG - constraints. */ - qps_float_t *area; /* num_cells element array whose values are - the areas for the corresponding cells; - only useful with COG constraints. */ - - /* Loop constraint stuff */ - int loop_num; /* Number of loop constraints. */ - int *loop_list; /* Array with list of cells for each loop - constraint. Format is similar to cog_list. - */ - qps_float_t *loop_max; /* loop_num element array indicating maximum - distance for each loop. */ - qps_float_t *loop_penalty; /* loop_num element array indicating penalty - for each loop. */ - int loop_k; /* Current iteration for loop optimization. */ - int loop_done; /* Done flag for loop optimization. */ - int loop_fail; - - /* max_x/max_y stuff */ - qps_float_t max_x; /* max x location; only used in - constrained optimization. */ - qps_float_t max_y; /* max y location; only used in - constrained optimization. */ - int max_enable; /* Set to 1 after qps_init() to enable - max_x/max_y. */ - int max_done; /* Done flag for max optimization. */ - - /* Private stuff */ - int *priv_ii; - int *priv_cc, *priv_cr; - qps_float_t *priv_cw, *priv_ct; - int priv_cm; - int *priv_gt; - int *priv_la; - int priv_lm; - qps_float_t *priv_gm, *priv_gw; - qps_float_t *priv_g, *priv_h, *priv_xi; - qps_float_t *priv_tp, *priv_tp2; - int priv_n; - qps_float_t *priv_cp; - qps_float_t priv_f; - qps_float_t *priv_lt; - qps_float_t *priv_pcg, *priv_pcgt; - qps_float_t priv_fmax; - qps_float_t priv_fprev; - qps_float_t priv_fopt; - qps_float_t priv_eps; - int priv_pn; - qps_float_t *priv_mxl, *priv_mxh, *priv_myl, *priv_myh; - int priv_ik; - FILE *priv_fp; - - } qps_problem_t; - - /* call qps_init() as soon as the qps_problem_t has been set up */ - /* this initializes some private data structures */ - extern void qps_init(qps_problem_t *); - - /* call qps_solve() to solve the given qp problem */ - extern void qps_solve(qps_problem_t *); - - /* call qps_clean() when finished with the qps_problem_t */ - /* this discards the private data structures assigned by qps_init() */ - extern void qps_clean(qps_problem_t *); - -#if defined(__cplusplus) -} -#endif /* __cplusplus */ -#endif /* _QPS_H */ diff --git a/src/phys/place/place_test.c b/src/phys/place/place_test.c deleted file mode 100644 index ea706a09..00000000 --- a/src/phys/place/place_test.c +++ /dev/null @@ -1,360 +0,0 @@ -/*===================================================================*/ -// -// place_test.c -// -// Aaron P. Hurst, 2003-2007 -// ahurst@eecs.berkeley.edu -// -/*===================================================================*/ - -#include -#include -#include -#include -#include "place_base.h" - - -// -------------------------------------------------------------------- -// Hash type/functions -// -// -------------------------------------------------------------------- - -struct hash_element { - ConcreteCell *obj; - struct hash_element *next; -} hash_element; - -int hash_string(int hash_max, const char *str) { - unsigned int hash = 0; - int p; - for(p = 0; pm_label); - // printf("adding %s key = %d\n", cell->m_label, key); - struct hash_element *element = malloc(sizeof(struct hash_element)); - assert(element); - element->obj = cell; - element->next = hash[key]; - hash[key] = element; -} - -ConcreteCell *hash_find(struct hash_element **hash, int hash_max, const char *str) { - int key = hash_string(hash_max, str); - // printf("looking for %s key = %d\n", str, key); - struct hash_element *next = hash[key]; - while(next) { - if (!strcmp(str, next->obj->m_label)) - return next->obj; - next = next->next; - } - return 0; -} - -// -------------------------------------------------------------------- -// Global variables -// -// -------------------------------------------------------------------- - -struct hash_element **hash_cellname; - -int numCells = 0, numNets = 0; - -AbstractCell *abstractCells; -ConcreteCell *concreteCells; -ConcreteNet *concreteNets; - -// -------------------------------------------------------------------- -// Function implementations -// -// -------------------------------------------------------------------- - -void readBookshelfNets(char *filename) { - char *tok; - char buf[1024]; - const char *DELIMITERS = " \n\t:"; - int id = 0; - int t; - ConcreteCell *cell; - - FILE *netsFile = fopen(filename, "r"); - if (!netsFile) { - printf("ERROR: Could not open .nets file\n"); - exit(1); - } - - // line 1 : version - while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#')); - - // line 2 : number of nets - while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#')); - tok = strtok(buf, DELIMITERS); - tok = strtok(NULL, DELIMITERS); - numNets = atoi(tok); - printf("READ-20 : number of nets = %d\n", numNets); - concreteNets = malloc(sizeof(ConcreteNet)*numNets); - - // line 3 : number of pins - while (fgets(buf, 1024, netsFile) && (buf[0] == '\n' || buf[0] == '#')); - - // line XXX : net definitions - while(fgets(buf, 1024, netsFile)) { - if (buf[0] == '\n' || buf[0] == '#') continue; - - concreteNets[id].m_id = id; - concreteNets[id].m_weight = 1.0; - - tok = strtok(buf, DELIMITERS); - if (!!strcmp(tok, "NetDegree")) { - printf("%s\n",buf); - printf("ERROR: Incorrect format in .nets file\n"); - exit(1); - } - - tok = strtok(NULL, DELIMITERS); - concreteNets[id].m_numTerms = atoi(tok); - if (concreteNets[id].m_numTerms < 0 || - concreteNets[id].m_numTerms > 100000) { - printf("ERROR: Bad net degree\n"); - exit(1); - } - concreteNets[id].m_terms = malloc(sizeof(ConcreteCell*)* - concreteNets[id].m_numTerms); - - // read terms - t = 0; - while(t < concreteNets[id].m_numTerms && - fgets(buf, 1024, netsFile)) { - if (buf[0] == '\n' || buf[0] == '#') continue; - - // cell name - tok = strtok(buf, DELIMITERS); - cell = hash_find(hash_cellname, numCells, tok); - if (!cell) { - printf("ERROR: Could not find cell %s in .nodes file\n", tok); - exit(1); - } - concreteNets[id].m_terms[t] = cell; - t++; - } - - // add! - addConcreteNet(&(concreteNets[id])); - - id++; - } - - fclose(netsFile); -} - -void readBookshelfNodes(char *filename) { - char *tok; - char buf[1024]; - const char *DELIMITERS = " \n\t:"; - int id = 0; - - FILE *nodesFile = fopen(filename, "r"); - if (!nodesFile) { - printf("ERROR: Could not open .nodes file\n"); - exit(1); - } - - // line 1 : version - while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#')); - - // line 2 : num nodes - while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#')); - tok = strtok(buf, DELIMITERS); - tok = strtok(NULL, DELIMITERS); - numCells = atoi(tok); - printf("READ-10 : number of cells = %d\n", numCells); - concreteCells = malloc(sizeof(ConcreteCell)*numCells); - abstractCells = malloc(sizeof(AbstractCell)*numCells); - hash_cellname = calloc(numCells, sizeof(struct hash_element*)); - - // line 3 : num terminals - while (fgets(buf, 1024, nodesFile) && (buf[0] == '\n' || buf[0] == '#')); - - // line XXX : cell definitions - while(fgets(buf, 1024, nodesFile)) { - if (buf[0] == '\n' || buf[0] == '#') continue; - - tok = strtok(buf, DELIMITERS); - concreteCells[id].m_id = id;; - - // label - concreteCells[id].m_parent = &(abstractCells[id]); - concreteCells[id].m_label = malloc(sizeof(char)*strlen(tok)+1); - strcpy(concreteCells[id].m_label, tok); - abstractCells[id].m_label = concreteCells[id].m_label; - hash_add(hash_cellname, numCells, - &(concreteCells[id])); - - // dimensions - tok = strtok(NULL, DELIMITERS); - abstractCells[id].m_width = atof(tok); - tok = strtok(NULL, DELIMITERS); - abstractCells[id].m_height = atof(tok); - tok = strtok(NULL, DELIMITERS); - // terminal - abstractCells[id].m_pad = tok && !strcmp(tok, "terminal"); - - // add! - addConcreteCell(&(concreteCells[id])); - - // DEBUG - /* - printf("\"%s\" : %f x %f\n", concreteCells[id].m_label, - abstractCells[id].m_width, - abstractCells[id].m_height); - */ - id++; - } - - fclose(nodesFile); -} - -void readBookshelfPlacement(char *filename) { - char *tok; - char buf[1024]; - const char *DELIMITERS = " \n\t:"; - ConcreteCell *cell; - - FILE *plFile = fopen(filename, "r"); - FILE *netsFile = fopen(filename, "r"); - if (!plFile) { - printf("ERROR: Could not open .pl file\n"); - exit(1); - } - if (!netsFile) { - printf("ERROR: Could not open .nets file\n"); - exit(1); - } - - // line 1 : version - while (fgets(buf, 1024, plFile) && (buf[0] == '\n' || buf[0] == '#')); - - // line XXX : placement definitions - while(fgets(buf, 1024, plFile)) { - if (buf[0] == '\n' || buf[0] == '#') continue; - - tok = strtok(buf, DELIMITERS); - - // cell name - cell = hash_find(hash_cellname, numCells, tok); - if (!cell) { - printf("ERROR: Could not find cell %s in .nodes file\n",tok); - exit(1); - } - - // position - tok = strtok(NULL, DELIMITERS); - cell->m_x = atof(tok); - tok = strtok(NULL, DELIMITERS); - cell->m_y = atof(tok); - - // hfixed - cell->m_fixed = strtok(NULL, DELIMITERS) && - (tok = strtok(NULL, DELIMITERS)) && - !strcmp(tok, "\\FIXED"); - } - - fclose(plFile); -} - -void writeBookshelfPlacement(char *filename) { - int c = 0; - - FILE *plFile = fopen(filename, "w"); - if (!plFile) { - printf("ERROR: Could not open .pl file\n"); - exit(1); - } - - fprintf(plFile, "UCLA pl 1.0\n"); - for(c=0; cm_numTerms; t++) - if (net->m_terms[t] == cell) count++; - if (count) { - memcpy(old, net->m_terms, sizeof(ConcreteCell*)*net->m_numTerms); - net->m_terms = realloc(net->m_terms, - sizeof(ConcreteCell*)*(net->m_numTerms-count)); - t2 = 0; - for(t=0; tm_numTerms; t++) - if (old[t] != cell) net->m_terms[t2++] = old[t]; - net->m_numTerms -= count; - } - } - free(old); -} - -int main(int argc, char **argv) { - - if (argc != 4) { - printf("Usage: %s [nodes] [nets] [pl]\n", argv[0]); - exit(1); - } - - readBookshelfNodes(argv[1]); - readBookshelfNets(argv[2]); - readBookshelfPlacement(argv[3]); - - globalPreplace(0.8); - globalPlace(); - - // DEBUG net/cell removal/addition - /* - int i; - for(i=1000; i<2000; i++) { - delConcreteNet(g_place_concreteNets[i]); - delNetConnections(g_place_concreteCells[i]); - delConcreteCell(g_place_concreteCells[i]); - } - - ConcreteCell newCell[2]; - newCell[0].m_id = g_place_numCells+1; - newCell[0].m_x = 1000; - newCell[0].m_y = 1000; - newCell[0].m_fixed = false; - newCell[0].m_parent = &(abstractCells[1000]); - newCell[0].m_label = " "; - addConcreteCell(&newCell[0]); - newCell[1].m_id = g_place_numCells+3; - newCell[1].m_x = 1000; - newCell[1].m_y = 1000; - newCell[1].m_fixed = false; - newCell[1].m_parent = &(abstractCells[1000]); - newCell[1].m_label = " "; - addConcreteCell(&newCell[1]); - */ - - globalIncremental(); - - writeBookshelfPlacement(argv[3]); - - free(hash_cellname); - - return 0; -} diff --git a/src/sat/bsat/module.make b/src/sat/bsat/module.make deleted file mode 100644 index 563c8dfc..00000000 --- a/src/sat/bsat/module.make +++ /dev/null @@ -1,6 +0,0 @@ -SRC += src/sat/bsat/satMem.c \ - src/sat/bsat/satInter.c \ - src/sat/bsat/satSolver.c \ - src/sat/bsat/satStore.c \ - src/sat/bsat/satTrace.c \ - src/sat/bsat/satUtil.c diff --git a/src/sat/bsat/satInter.c b/src/sat/bsat/satInter.c deleted file mode 100644 index b52cd6c7..00000000 --- a/src/sat/bsat/satInter.c +++ /dev/null @@ -1,991 +0,0 @@ -/**CFile**************************************************************** - - FileName [satInter.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [SAT sat_solver.] - - Synopsis [Interpolation package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: satInter.c,v 1.4 2005/09/16 22:55:03 casem Exp $] - -***********************************************************************/ - -#include -#include -#include -#include -#include -#include "satStore.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// variable assignments -static const lit LIT_UNDEF = 0xffffffff; - -// interpolation manager -struct Int_Man_t_ -{ - // clauses of the problems - Sto_Man_t * pCnf; // the set of CNF clauses for A and B - // various parameters - int fVerbose; // verbosiness flag - int fProofVerif; // verifies the proof - int fProofWrite; // writes the proof file - int nVarsAlloc; // the allocated size of var arrays - int nClosAlloc; // the allocated size of clause arrays - // internal BCP - int nRootSize; // the number of root level assignments - int nTrailSize; // the number of assignments made - lit * pTrail; // chronological order of assignments (size nVars) - lit * pAssigns; // assignments by variable (size nVars) - char * pSeens; // temporary mark (size nVars) - Sto_Cls_t ** pReasons; // reasons for each assignment (size nVars) - Sto_Cls_t ** pWatches; // watched clauses for each literal (size 2*nVars) - // interpolation data - int nVarsAB; // the number of global variables - char * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB] - unsigned * pInters; // storage for interpolants as truth tables (size nClauses) - int nIntersAlloc; // the allocated size of truth table array - int nWords; // the number of words in the truth table - // proof recording - int Counter; // counter of resolved clauses - int * pProofNums; // the proof numbers for each clause (size nClauses) - FILE * pFile; // the file for proof recording - // internal verification - lit * pResLits; // the literals of the resolvent - int nResLits; // the number of literals of the resolvent - int nResLitsAlloc;// the number of literals of the resolvent - // runtime stats - int timeBcp; // the runtime for BCP - int timeTrace; // the runtime of trace construction - int timeTotal; // the total runtime of interpolation -}; - -// procedure to get hold of the clauses' truth table -static inline unsigned * Int_ManTruthRead( Int_Man_t * p, Sto_Cls_t * pCls ) { return p->pInters + pCls->Id * p->nWords; } -static inline void Int_ManTruthClear( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = 0; } -static inline void Int_ManTruthFill( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = ~0; } -static inline void Int_ManTruthCopy( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = q[i]; } -static inline void Int_ManTruthAnd( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] &= q[i]; } -static inline void Int_ManTruthOr( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= q[i]; } -static inline void Int_ManTruthOrNot( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= ~q[i]; } - -// reading/writing the proof for a clause -static inline int Int_ManProofGet( Int_Man_t * p, Sto_Cls_t * pCls ) { return p->pProofNums[pCls->Id]; } -static inline void Int_ManProofSet( Int_Man_t * p, Sto_Cls_t * pCls, int n ) { p->pProofNums[pCls->Id] = n; } - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocate proof manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Int_Man_t * Int_ManAlloc( int nVarsAlloc ) -{ - Int_Man_t * p; - // allocate the manager - p = (Int_Man_t *)malloc( sizeof(Int_Man_t) ); - memset( p, 0, sizeof(Int_Man_t) ); - // verification - p->nResLitsAlloc = (1<<16); - p->pResLits = malloc( sizeof(lit) * p->nResLitsAlloc ); - // parameters - p->fProofWrite = 0; - p->fProofVerif = 1; - return p; -} - -/**Function************************************************************* - - Synopsis [Count common variables in the clauses of A and B.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Int_ManGlobalVars( Int_Man_t * p ) -{ - Sto_Cls_t * pClause; - int Var, nVarsAB, v; - - // mark the variable encountered in the clauses of A - Sto_ManForEachClauseRoot( p->pCnf, pClause ) - { - if ( !pClause->fA ) - break; - for ( v = 0; v < (int)pClause->nLits; v++ ) - p->pVarTypes[lit_var(pClause->pLits[v])] = 1; - } - - // check variables that appear in clauses of B - nVarsAB = 0; - Sto_ManForEachClauseRoot( p->pCnf, pClause ) - { - if ( pClause->fA ) - continue; - for ( v = 0; v < (int)pClause->nLits; v++ ) - { - Var = lit_var(pClause->pLits[v]); - if ( p->pVarTypes[Var] == 1 ) // var of A - { - // change it into a global variable - nVarsAB++; - p->pVarTypes[Var] = -1; - } - } - } - - // order global variables - nVarsAB = 0; - for ( v = 0; v < p->pCnf->nVars; v++ ) - if ( p->pVarTypes[v] == -1 ) - p->pVarTypes[v] -= nVarsAB++; -//printf( "There are %d global variables.\n", nVarsAB ); - return nVarsAB; -} - -/**Function************************************************************* - - Synopsis [Resize proof manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Int_ManResize( Int_Man_t * p ) -{ - // check if resizing is needed - if ( p->nVarsAlloc < p->pCnf->nVars ) - { - // find the new size - if ( p->nVarsAlloc == 0 ) - p->nVarsAlloc = 1; - while ( p->nVarsAlloc < p->pCnf->nVars ) - p->nVarsAlloc *= 2; - // resize the arrays - p->pTrail = (lit *) realloc( p->pTrail, sizeof(lit) * p->nVarsAlloc ); - p->pAssigns = (lit *) realloc( p->pAssigns, sizeof(lit) * p->nVarsAlloc ); - p->pSeens = (char *) realloc( p->pSeens, sizeof(char) * p->nVarsAlloc ); - p->pVarTypes = (char *) realloc( p->pVarTypes, sizeof(char) * p->nVarsAlloc ); - p->pReasons = (Sto_Cls_t **)realloc( p->pReasons, sizeof(Sto_Cls_t *) * p->nVarsAlloc ); - p->pWatches = (Sto_Cls_t **)realloc( p->pWatches, sizeof(Sto_Cls_t *) * p->nVarsAlloc*2 ); - } - - // clean the free space - memset( p->pAssigns , 0xff, sizeof(lit) * p->pCnf->nVars ); - memset( p->pSeens , 0, sizeof(char) * p->pCnf->nVars ); - memset( p->pVarTypes, 0, sizeof(char) * p->pCnf->nVars ); - memset( p->pReasons , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars ); - memset( p->pWatches , 0, sizeof(Sto_Cls_t *) * p->pCnf->nVars*2 ); - - // compute the number of common variables - p->nVarsAB = Int_ManGlobalVars( p ); - // compute the number of words in the truth table - p->nWords = (p->nVarsAB <= 5 ? 1 : (1 << (p->nVarsAB - 5))); - - // check if resizing of clauses is needed - if ( p->nClosAlloc < p->pCnf->nClauses ) - { - // find the new size - if ( p->nClosAlloc == 0 ) - p->nClosAlloc = 1; - while ( p->nClosAlloc < p->pCnf->nClauses ) - p->nClosAlloc *= 2; - // resize the arrays - p->pProofNums = (int *) realloc( p->pProofNums, sizeof(int) * p->nClosAlloc ); - } - memset( p->pProofNums, 0, sizeof(int) * p->pCnf->nClauses ); - - // check if resizing of truth tables is needed - if ( p->nIntersAlloc < p->nWords * p->pCnf->nClauses ) - { - p->nIntersAlloc = p->nWords * p->pCnf->nClauses; - p->pInters = (unsigned *) realloc( p->pInters, sizeof(unsigned) * p->nIntersAlloc ); - } -// memset( p->pInters, 0, sizeof(unsigned) * p->nWords * p->pCnf->nClauses ); -} - -/**Function************************************************************* - - Synopsis [Deallocate proof manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Int_ManFree( Int_Man_t * p ) -{ -/* - printf( "Runtime stats:\n" ); -PRT( "BCP ", p->timeBcp ); -PRT( "Trace ", p->timeTrace ); -PRT( "TOTAL ", p->timeTotal ); -*/ - free( p->pInters ); - free( p->pProofNums ); - free( p->pTrail ); - free( p->pAssigns ); - free( p->pSeens ); - free( p->pVarTypes ); - free( p->pReasons ); - free( p->pWatches ); - free( p->pResLits ); - free( p ); -} - - - - -/**Function************************************************************* - - Synopsis [Prints the clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Int_ManPrintClause( Int_Man_t * p, Sto_Cls_t * pClause ) -{ - int i; - printf( "Clause ID = %d. Proof = %d. {", pClause->Id, Int_ManProofGet(p, pClause) ); - for ( i = 0; i < (int)pClause->nLits; i++ ) - printf( " %d", pClause->pLits[i] ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints the resolvent.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Int_ManPrintResolvent( lit * pResLits, int nResLits ) -{ - int i; - printf( "Resolvent: {" ); - for ( i = 0; i < nResLits; i++ ) - printf( " %d", pResLits[i] ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [Records the proof.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_PrintBinary__( FILE * pFile, unsigned Sign[], int nBits ) -{ - int Remainder, nWords; - int w, i; - - Remainder = (nBits%(sizeof(unsigned)*8)); - nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); - - for ( w = nWords-1; w >= 0; w-- ) - for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) - fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1< 0) ); -} - -/**Function************************************************************* - - Synopsis [Prints the interpolant for one clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Int_ManPrintInterOne( Int_Man_t * p, Sto_Cls_t * pClause ) -{ - printf( "Clause %2d : ", pClause->Id ); - Extra_PrintBinary__( stdout, Int_ManTruthRead(p, pClause), (1 << p->nVarsAB) ); - printf( "\n" ); -} - - - -/**Function************************************************************* - - Synopsis [Adds one clause to the watcher list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Int_ManWatchClause( Int_Man_t * p, Sto_Cls_t * pClause, lit Lit ) -{ - assert( lit_check(Lit, p->pCnf->nVars) ); - if ( pClause->pLits[0] == Lit ) - pClause->pNext0 = p->pWatches[lit_neg(Lit)]; - else - { - assert( pClause->pLits[1] == Lit ); - pClause->pNext1 = p->pWatches[lit_neg(Lit)]; - } - p->pWatches[lit_neg(Lit)] = pClause; -} - - -/**Function************************************************************* - - Synopsis [Records implication.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Int_ManEnqueue( Int_Man_t * p, lit Lit, Sto_Cls_t * pReason ) -{ - int Var = lit_var(Lit); - if ( p->pAssigns[Var] != LIT_UNDEF ) - return p->pAssigns[Var] == Lit; - p->pAssigns[Var] = Lit; - p->pReasons[Var] = pReason; - p->pTrail[p->nTrailSize++] = Lit; -//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Records implication.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Int_ManCancelUntil( Int_Man_t * p, int Level ) -{ - lit Lit; - int i, Var; - for ( i = p->nTrailSize - 1; i >= Level; i-- ) - { - Lit = p->pTrail[i]; - Var = lit_var( Lit ); - p->pReasons[Var] = NULL; - p->pAssigns[Var] = LIT_UNDEF; -//printf( "cancelling var %d\n", Var ); - } - p->nTrailSize = Level; -} - -/**Function************************************************************* - - Synopsis [Propagate one assignment.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Sto_Cls_t * Int_ManPropagateOne( Int_Man_t * p, lit Lit ) -{ - Sto_Cls_t ** ppPrev, * pCur, * pTemp; - lit LitF = lit_neg(Lit); - int i; - // iterate through the literals - ppPrev = p->pWatches + Lit; - for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) - { - // make sure the false literal is in the second literal of the clause - if ( pCur->pLits[0] == LitF ) - { - pCur->pLits[0] = pCur->pLits[1]; - pCur->pLits[1] = LitF; - pTemp = pCur->pNext0; - pCur->pNext0 = pCur->pNext1; - pCur->pNext1 = pTemp; - } - assert( pCur->pLits[1] == LitF ); - - // if the first literal is true, the clause is satisfied - if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) - { - ppPrev = &pCur->pNext1; - continue; - } - - // look for a new literal to watch - for ( i = 2; i < (int)pCur->nLits; i++ ) - { - // skip the case when the literal is false - if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] ) - continue; - // the literal is either true or unassigned - watch it - pCur->pLits[1] = pCur->pLits[i]; - pCur->pLits[i] = LitF; - // remove this clause from the watch list of Lit - *ppPrev = pCur->pNext1; - // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) - Int_ManWatchClause( p, pCur, pCur->pLits[1] ); - break; - } - if ( i < (int)pCur->nLits ) // found new watch - continue; - - // clause is unit - enqueue new implication - if ( Int_ManEnqueue(p, pCur->pLits[0], pCur) ) - { - ppPrev = &pCur->pNext1; - continue; - } - - // conflict detected - return the conflict clause - return pCur; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Propagate the current assignments.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Sto_Cls_t * Int_ManPropagate( Int_Man_t * p, int Start ) -{ - Sto_Cls_t * pClause; - int i; - int clk = clock(); - for ( i = Start; i < p->nTrailSize; i++ ) - { - pClause = Int_ManPropagateOne( p, p->pTrail[i] ); - if ( pClause ) - { -p->timeBcp += clock() - clk; - return pClause; - } - } -p->timeBcp += clock() - clk; - return NULL; -} - - -/**Function************************************************************* - - Synopsis [Writes one root clause into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Int_ManProofWriteOne( Int_Man_t * p, Sto_Cls_t * pClause ) -{ - Int_ManProofSet( p, pClause, ++p->Counter ); - - if ( p->fProofWrite ) - { - int v; - fprintf( p->pFile, "%d", Int_ManProofGet(p, pClause) ); - for ( v = 0; v < (int)pClause->nLits; v++ ) - fprintf( p->pFile, " %d", lit_print(pClause->pLits[v]) ); - fprintf( p->pFile, " 0 0\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Traces the proof for one clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Int_ManProofTraceOne( Int_Man_t * p, Sto_Cls_t * pConflict, Sto_Cls_t * pFinal ) -{ - Sto_Cls_t * pReason; - int i, v, Var, PrevId; - int fPrint = 0; - int clk = clock(); - - // collect resolvent literals - if ( p->fProofVerif ) - { - assert( (int)pConflict->nLits <= p->nResLitsAlloc ); - memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits ); - p->nResLits = pConflict->nLits; - } - - // mark all the variables in the conflict as seen - for ( v = 0; v < (int)pConflict->nLits; v++ ) - p->pSeens[lit_var(pConflict->pLits[v])] = 1; - - // start the anticedents -// pFinal->pAntis = Vec_PtrAlloc( 32 ); -// Vec_PtrPush( pFinal->pAntis, pConflict ); - - if ( p->pCnf->nClausesA ) - Int_ManTruthCopy( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pConflict), p->nWords ); - - // follow the trail backwards - PrevId = Int_ManProofGet(p, pConflict); - for ( i = p->nTrailSize - 1; i >= 0; i-- ) - { - // skip literals that are not involved - Var = lit_var(p->pTrail[i]); - if ( !p->pSeens[Var] ) - continue; - p->pSeens[Var] = 0; - - // skip literals of the resulting clause - pReason = p->pReasons[Var]; - if ( pReason == NULL ) - continue; - assert( p->pTrail[i] == pReason->pLits[0] ); - - // add the variables to seen - for ( v = 1; v < (int)pReason->nLits; v++ ) - p->pSeens[lit_var(pReason->pLits[v])] = 1; - - - // record the reason clause - assert( Int_ManProofGet(p, pReason) > 0 ); - p->Counter++; - if ( p->fProofWrite ) - fprintf( p->pFile, "%d * %d %d 0\n", p->Counter, PrevId, Int_ManProofGet(p, pReason) ); - PrevId = p->Counter; - - if ( p->pCnf->nClausesA ) - { - if ( p->pVarTypes[Var] == 1 ) // var of A - Int_ManTruthOr( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pReason), p->nWords ); - else - Int_ManTruthAnd( Int_ManTruthRead(p, pFinal), Int_ManTruthRead(p, pReason), p->nWords ); - } - - // resolve the temporary resolvent with the reason clause - if ( p->fProofVerif ) - { - int v1, v2; - if ( fPrint ) - Int_ManPrintResolvent( p->pResLits, p->nResLits ); - // check that the var is present in the resolvent - for ( v1 = 0; v1 < p->nResLits; v1++ ) - if ( lit_var(p->pResLits[v1]) == Var ) - break; - if ( v1 == p->nResLits ) - printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var ); - if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) ) - printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var ); - // remove this variable from the resolvent - assert( lit_var(p->pResLits[v1]) == Var ); - p->nResLits--; - for ( ; v1 < p->nResLits; v1++ ) - p->pResLits[v1] = p->pResLits[v1+1]; - // add variables of the reason clause - for ( v2 = 1; v2 < (int)pReason->nLits; v2++ ) - { - for ( v1 = 0; v1 < p->nResLits; v1++ ) - if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) ) - break; - // if it is a new variable, add it to the resolvent - if ( v1 == p->nResLits ) - { - if ( p->nResLits == p->nResLitsAlloc ) - printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n, pFinal->Id" ); - p->pResLits[ p->nResLits++ ] = pReason->pLits[v2]; - continue; - } - // if the variable is the same, the literal should be the same too - if ( p->pResLits[v1] == pReason->pLits[v2] ) - continue; - // the literal is different - printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id ); - } - } - -// Vec_PtrPush( pFinal->pAntis, pReason ); - } - - // unmark all seen variables -// for ( i = p->nTrailSize - 1; i >= 0; i-- ) -// p->pSeens[lit_var(p->pTrail[i])] = 0; - // check that the literals are unmarked -// for ( i = p->nTrailSize - 1; i >= 0; i-- ) -// assert( p->pSeens[lit_var(p->pTrail[i])] == 0 ); - - // use the resulting clause to check the correctness of resolution - if ( p->fProofVerif ) - { - int v1, v2; - if ( fPrint ) - Int_ManPrintResolvent( p->pResLits, p->nResLits ); - for ( v1 = 0; v1 < p->nResLits; v1++ ) - { - for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) - if ( pFinal->pLits[v2] == p->pResLits[v1] ) - break; - if ( v2 < (int)pFinal->nLits ) - continue; - break; - } - if ( v1 < p->nResLits ) - { - printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id ); - Int_ManPrintClause( p, pConflict ); - Int_ManPrintResolvent( p->pResLits, p->nResLits ); - Int_ManPrintClause( p, pFinal ); - } - } -p->timeTrace += clock() - clk; - - // return the proof pointer - if ( p->pCnf->nClausesA ) - { -// Int_ManPrintInterOne( p, pFinal ); - } - Int_ManProofSet( p, pFinal, p->Counter ); - return p->Counter; -} - -/**Function************************************************************* - - Synopsis [Records the proof for one clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Int_ManProofRecordOne( Int_Man_t * p, Sto_Cls_t * pClause ) -{ - Sto_Cls_t * pConflict; - int i; - - // empty clause never ends up there - assert( pClause->nLits > 0 ); - if ( pClause->nLits == 0 ) - printf( "Error: Empty clause is attempted.\n" ); - - // add assumptions to the trail - assert( !pClause->fRoot ); - assert( p->nTrailSize == p->nRootSize ); - for ( i = 0; i < (int)pClause->nLits; i++ ) - if ( !Int_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) - { - assert( 0 ); // impossible - return 0; - } - - // propagate the assumptions - pConflict = Int_ManPropagate( p, p->nRootSize ); - if ( pConflict == NULL ) - { - assert( 0 ); // cannot prove - return 0; - } - - // construct the proof - Int_ManProofTraceOne( p, pConflict, pClause ); - - // undo to the root level - Int_ManCancelUntil( p, p->nRootSize ); - - // add large clauses to the watched lists - if ( pClause->nLits > 1 ) - { - Int_ManWatchClause( p, pClause, pClause->pLits[0] ); - Int_ManWatchClause( p, pClause, pClause->pLits[1] ); - return 1; - } - assert( pClause->nLits == 1 ); - - // if the clause proved is unit, add it and propagate - if ( !Int_ManEnqueue( p, pClause->pLits[0], pClause ) ) - { - assert( 0 ); // impossible - return 0; - } - - // propagate the assumption - pConflict = Int_ManPropagate( p, p->nRootSize ); - if ( pConflict ) - { - // construct the proof - Int_ManProofTraceOne( p, pConflict, p->pCnf->pEmpty ); - if ( p->fVerbose ) - printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id ); - return 0; - } - - // update the root level - p->nRootSize = p->nTrailSize; - return 1; -} - -/**Function************************************************************* - - Synopsis [Propagate the root clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Int_ManProcessRoots( Int_Man_t * p ) -{ - Sto_Cls_t * pClause; - int Counter; - - // make sure the root clauses are preceeding the learnt clauses - Counter = 0; - Sto_ManForEachClause( p->pCnf, pClause ) - { - assert( (int)pClause->fA == (Counter < (int)p->pCnf->nClausesA) ); - assert( (int)pClause->fRoot == (Counter < (int)p->pCnf->nRoots) ); - Counter++; - } - assert( p->pCnf->nClauses == Counter ); - - // make sure the last clause if empty - assert( p->pCnf->pTail->nLits == 0 ); - - // go through the root unit clauses - p->nTrailSize = 0; - Sto_ManForEachClauseRoot( p->pCnf, pClause ) - { - // create watcher lists for the root clauses - if ( pClause->nLits > 1 ) - { - Int_ManWatchClause( p, pClause, pClause->pLits[0] ); - Int_ManWatchClause( p, pClause, pClause->pLits[1] ); - } - // empty clause and large clauses - if ( pClause->nLits != 1 ) - continue; - // unit clause - assert( lit_check(pClause->pLits[0], p->pCnf->nVars) ); - if ( !Int_ManEnqueue( p, pClause->pLits[0], pClause ) ) - { - // detected root level conflict - printf( "Error in Int_ManProcessRoots(): Detected a root-level conflict too early!\n" ); - assert( 0 ); - return 0; - } - } - - // propagate the root unit clauses - pClause = Int_ManPropagate( p, 0 ); - if ( pClause ) - { - // detected root level conflict - Int_ManProofTraceOne( p, pClause, p->pCnf->pEmpty ); - if ( p->fVerbose ) - printf( "Found root level conflict!\n" ); - return 0; - } - - // set the root level - p->nRootSize = p->nTrailSize; - return 1; -} - -/**Function************************************************************* - - Synopsis [Records the proof.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Int_ManPrepareInter( Int_Man_t * p ) -{ - // elementary truth tables - unsigned uTruths[8][8] = { - { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, - { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, - { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, - { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, - { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, - { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, - { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, - { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } - }; - Sto_Cls_t * pClause; - int Var, VarAB, v; - assert( p->nVarsAB <= 8 ); - - // set interpolants for root clauses - Sto_ManForEachClauseRoot( p->pCnf, pClause ) - { - if ( !pClause->fA ) // clause of B - { - Int_ManTruthFill( Int_ManTruthRead(p, pClause), p->nWords ); -// Int_ManPrintInterOne( p, pClause ); - continue; - } - // clause of A - Int_ManTruthClear( Int_ManTruthRead(p, pClause), p->nWords ); - for ( v = 0; v < (int)pClause->nLits; v++ ) - { - Var = lit_var(pClause->pLits[v]); - if ( p->pVarTypes[Var] < 0 ) // global var - { - VarAB = -p->pVarTypes[Var]-1; - assert( VarAB >= 0 && VarAB < p->nVarsAB ); - if ( lit_sign(pClause->pLits[v]) ) // negative var - Int_ManTruthOrNot( Int_ManTruthRead(p, pClause), uTruths[VarAB], p->nWords ); - else - Int_ManTruthOr( Int_ManTruthRead(p, pClause), uTruths[VarAB], p->nWords ); - } - } -// Int_ManPrintInterOne( p, pClause ); - } -} - -/**Function************************************************************* - - Synopsis [Computes interpolant for the given CNF.] - - Description [Returns the number of common variable found and interpolant. - Returns 0, if something did not work.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Int_ManInterpolate( Int_Man_t * p, Sto_Man_t * pCnf, int fVerbose, unsigned ** ppResult ) -{ - Sto_Cls_t * pClause; - int RetValue = 1; - int clkTotal = clock(); - - // check that the CNF makes sense - assert( pCnf->nVars > 0 && pCnf->nClauses > 0 ); - p->pCnf = pCnf; - p->fVerbose = fVerbose; - *ppResult = NULL; - - // adjust the manager - Int_ManResize( p ); - - // prepare the interpolant computation - Int_ManPrepareInter( p ); - - // construct proof for each clause - // start the proof - if ( p->fProofWrite ) - { - p->pFile = fopen( "proof.cnf_", "w" ); - p->Counter = 0; - } - - // write the root clauses - Sto_ManForEachClauseRoot( p->pCnf, pClause ) - Int_ManProofWriteOne( p, pClause ); - - // propagate root level assignments - if ( Int_ManProcessRoots( p ) ) - { - // if there is no conflict, consider learned clauses - Sto_ManForEachClause( p->pCnf, pClause ) - { - if ( pClause->fRoot ) - continue; - if ( !Int_ManProofRecordOne( p, pClause ) ) - { - RetValue = 0; - break; - } - } - } - - // stop the proof - if ( p->fProofWrite ) - { - fclose( p->pFile ); - p->pFile = NULL; - } - - if ( fVerbose ) - { - printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d. Ave = %.2f. Mem = %.2f Mb\n", - p->pCnf->nVars, p->pCnf->nRoots, p->pCnf->nClauses-p->pCnf->nRoots, p->Counter, - 1.0*(p->Counter-p->pCnf->nRoots)/(p->pCnf->nClauses-p->pCnf->nRoots), - 1.0*Sto_ManMemoryReport(p->pCnf)/(1<<20) ); -p->timeTotal += clock() - clkTotal; - } - - *ppResult = Int_ManTruthRead( p, p->pCnf->pTail ); - return p->nVarsAB; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/bsat/satMem.c b/src/sat/bsat/satMem.c deleted file mode 100644 index bb234f66..00000000 --- a/src/sat/bsat/satMem.c +++ /dev/null @@ -1,527 +0,0 @@ -/**CFile**************************************************************** - - FileName [satMem.c] - - PackageName [SAT solver.] - - Synopsis [Memory management.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: satMem.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "satMem.h" -#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Sat_MmFixed_t_ -{ - // information about individual entries - int nEntrySize; // the size of one entry - int nEntriesAlloc; // the total number of entries allocated - int nEntriesUsed; // the number of entries in use - int nEntriesMax; // the max number of entries in use - char * pEntriesFree; // the linked list of free entries - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -struct Sat_MmFlex_t_ -{ - // information about individual entries - int nEntriesUsed; // the number of entries allocated - char * pCurrent; // the current pointer to free memory - char * pEnd; // the first entry outside the free memory - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -struct Sat_MmStep_t_ -{ - int nMems; // the number of fixed memory managers employed - Sat_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc - int nMapSize; // the size of the memory array - Sat_MmFixed_t ** pMap; // maps the number of bytes into its memory manager -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates memory pieces of fixed size.] - - Description [The size of the chunk is computed as the minimum of - 1024 entries and 64K. Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Sat_MmFixed_t * Sat_MmFixedStart( int nEntrySize ) -{ - Sat_MmFixed_t * p; - - p = ALLOC( Sat_MmFixed_t, 1 ); - memset( p, 0, sizeof(Sat_MmFixed_t) ); - - p->nEntrySize = nEntrySize; - p->nEntriesAlloc = 0; - p->nEntriesUsed = 0; - p->pEntriesFree = NULL; - - if ( nEntrySize * (1 << 10) < (1<<16) ) - p->nChunkSize = (1 << 10); - else - p->nChunkSize = (1<<16) / nEntrySize; - if ( p->nChunkSize < 8 ) - p->nChunkSize = 8; - - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_MmFixedStop( Sat_MmFixed_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", - p->nEntrySize, p->nChunkSize, p->nChunks ); - printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", - p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Sat_MmFixedEntryFetch( Sat_MmFixed_t * p ) -{ - char * pTemp; - int i; - - // check if there are still free entries - if ( p->nEntriesUsed == p->nEntriesAlloc ) - { // need to allocate more entries - assert( p->pEntriesFree == NULL ); - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); - p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; - // transform these entries into a linked list - pTemp = p->pEntriesFree; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pEntriesFree; - // add to the number of entries allocated - p->nEntriesAlloc += p->nChunkSize; - } - // incrememt the counter of used entries - p->nEntriesUsed++; - if ( p->nEntriesMax < p->nEntriesUsed ) - p->nEntriesMax = p->nEntriesUsed; - // return the first entry in the free entry list - pTemp = p->pEntriesFree; - p->pEntriesFree = *((char **)pTemp); - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_MmFixedEntryRecycle( Sat_MmFixed_t * p, char * pEntry ) -{ - // decrement the counter of used entries - p->nEntriesUsed--; - // add the entry to the linked list of free entries - *((char **)pEntry) = p->pEntriesFree; - p->pEntriesFree = pEntry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Relocates all the memory except the first chunk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_MmFixedRestart( Sat_MmFixed_t * p ) -{ - int i; - char * pTemp; - - // deallocate all chunks except the first one - for ( i = 1; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - p->nChunks = 1; - // transform these entries into a linked list - pTemp = p->pChunks[0]; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // set the free entry list - p->pEntriesFree = p->pChunks[0]; - // set the correct statistics - p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; - p->nMemoryUsed = 0; - p->nEntriesAlloc = p->nChunkSize; - p->nEntriesUsed = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sat_MmFixedReadMemUsage( Sat_MmFixed_t * p ) -{ - return p->nMemoryAlloc; -} - - - -/**Function************************************************************* - - Synopsis [Allocates entries of flexible size.] - - Description [Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Sat_MmFlex_t * Sat_MmFlexStart() -{ - Sat_MmFlex_t * p; - - p = ALLOC( Sat_MmFlex_t, 1 ); - memset( p, 0, sizeof(Sat_MmFlex_t) ); - - p->nEntriesUsed = 0; - p->pCurrent = NULL; - p->pEnd = NULL; - - p->nChunkSize = (1 << 12); - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_MmFlexStop( Sat_MmFlex_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", - p->nChunkSize, p->nChunks ); - printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", - p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Sat_MmFlexEntryFetch( Sat_MmFlex_t * p, int nBytes ) -{ - char * pTemp; - // check if there are still free entries - if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) - { // need to allocate more entries - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - if ( nBytes > p->nChunkSize ) - { - // resize the chunk size if more memory is requested than it can give - // (ideally, this should never happen) - p->nChunkSize = 2 * nBytes; - } - p->pCurrent = ALLOC( char, p->nChunkSize ); - p->pEnd = p->pCurrent + p->nChunkSize; - p->nMemoryAlloc += p->nChunkSize; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pCurrent; - } - assert( p->pCurrent + nBytes <= p->pEnd ); - // increment the counter of used entries - p->nEntriesUsed++; - // keep track of the memory used - p->nMemoryUsed += nBytes; - // return the next entry - pTemp = p->pCurrent; - p->pCurrent += nBytes; - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sat_MmFlexReadMemUsage( Sat_MmFlex_t * p ) -{ - return p->nMemoryAlloc; -} - - - - - -/**Function************************************************************* - - Synopsis [Starts the hierarchical memory manager.] - - Description [This manager can allocate entries of any size. - Iternally they are mapped into the entries with the number of bytes - equal to the power of 2. The smallest entry size is 8 bytes. The - next one is 16 bytes etc. So, if the user requests 6 bytes, he gets - 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. - The input parameters "nSteps" says how many fixed memory managers - are employed internally. Calling this procedure with nSteps equal - to 10 results in 10 hierarchically arranged internal memory managers, - which can allocate up to 4096 (1Kb) entries. Requests for larger - entries are handed over to malloc() and then free()ed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Sat_MmStep_t * Sat_MmStepStart( int nSteps ) -{ - Sat_MmStep_t * p; - int i, k; - p = ALLOC( Sat_MmStep_t, 1 ); - p->nMems = nSteps; - // start the fixed memory managers - p->pMems = ALLOC( Sat_MmFixed_t *, p->nMems ); - for ( i = 0; i < p->nMems; i++ ) - p->pMems[i] = Sat_MmFixedStart( (8<nMapSize = (4<nMems); - p->pMap = ALLOC( Sat_MmFixed_t *, p->nMapSize+1 ); - p->pMap[0] = NULL; - for ( k = 1; k <= 4; k++ ) - p->pMap[k] = p->pMems[0]; - for ( i = 0; i < p->nMems; i++ ) - for ( k = (4<pMap[k] = p->pMems[i]; -//for ( i = 1; i < 100; i ++ ) -//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_MmStepStop( Sat_MmStep_t * p, int fVerbose ) -{ - int i; - for ( i = 0; i < p->nMems; i++ ) - Sat_MmFixedStop( p->pMems[i], fVerbose ); - free( p->pMems ); - free( p->pMap ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Creates the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Sat_MmStepEntryFetch( Sat_MmStep_t * p, int nBytes ) -{ - if ( nBytes == 0 ) - return NULL; - if ( nBytes > p->nMapSize ) - { -// printf( "Allocating %d bytes.\n", nBytes ); - return ALLOC( char, nBytes ); - } - return Sat_MmFixedEntryFetch( p->pMap[nBytes] ); -} - - -/**Function************************************************************* - - Synopsis [Recycles the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_MmStepEntryRecycle( Sat_MmStep_t * p, char * pEntry, int nBytes ) -{ - if ( nBytes == 0 ) - return; - if ( nBytes > p->nMapSize ) - { - free( pEntry ); - return; - } - Sat_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sat_MmStepReadMemUsage( Sat_MmStep_t * p ) -{ - int i, nMemTotal = 0; - for ( i = 0; i < p->nMems; i++ ) - nMemTotal += p->pMems[i]->nMemoryAlloc; - return nMemTotal; -} diff --git a/src/sat/bsat/satMem.h b/src/sat/bsat/satMem.h deleted file mode 100644 index 5c5ddd9c..00000000 --- a/src/sat/bsat/satMem.h +++ /dev/null @@ -1,78 +0,0 @@ -/**CFile**************************************************************** - - FileName [satMem.h] - - PackageName [SAT solver.] - - Synopsis [Memory management.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: satMem.h,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __SAT_MEM_H__ -#define __SAT_MEM_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//#include "leaks.h" -#include -#include - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Sat_MmFixed_t_ Sat_MmFixed_t; -typedef struct Sat_MmFlex_t_ Sat_MmFlex_t; -typedef struct Sat_MmStep_t_ Sat_MmStep_t; - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// fixed-size-block memory manager -extern Sat_MmFixed_t * Sat_MmFixedStart( int nEntrySize ); -extern void Sat_MmFixedStop( Sat_MmFixed_t * p, int fVerbose ); -extern char * Sat_MmFixedEntryFetch( Sat_MmFixed_t * p ); -extern void Sat_MmFixedEntryRecycle( Sat_MmFixed_t * p, char * pEntry ); -extern void Sat_MmFixedRestart( Sat_MmFixed_t * p ); -extern int Sat_MmFixedReadMemUsage( Sat_MmFixed_t * p ); -// flexible-size-block memory manager -extern Sat_MmFlex_t * Sat_MmFlexStart(); -extern void Sat_MmFlexStop( Sat_MmFlex_t * p, int fVerbose ); -extern char * Sat_MmFlexEntryFetch( Sat_MmFlex_t * p, int nBytes ); -extern int Sat_MmFlexReadMemUsage( Sat_MmFlex_t * p ); -// hierarchical memory manager -extern Sat_MmStep_t * Sat_MmStepStart( int nSteps ); -extern void Sat_MmStepStop( Sat_MmStep_t * p, int fVerbose ); -extern char * Sat_MmStepEntryFetch( Sat_MmStep_t * p, int nBytes ); -extern void Sat_MmStepEntryRecycle( Sat_MmStep_t * p, char * pEntry, int nBytes ); -extern int Sat_MmStepReadMemUsage( Sat_MmStep_t * p ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/sat/bsat/satSolver.c b/src/sat/bsat/satSolver.c deleted file mode 100644 index 439d9e76..00000000 --- a/src/sat/bsat/satSolver.c +++ /dev/null @@ -1,1358 +0,0 @@ -/************************************************************************************************** -MiniSat -- Copyright (c) 2005, Niklas Sorensson -http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ -// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko - -#include -#include -#include -#include - -#include "satSolver.h" - -//#define SAT_USE_SYSTEM_MEMORY_MANAGEMENT - -//================================================================================================= -// Debug: - -//#define VERBOSEDEBUG - -// For derivation output (verbosity level 2) -#define L_IND "%-*d" -#define L_ind sat_solver_dlevel(s)*3+3,sat_solver_dlevel(s) -#define L_LIT "%sx%d" -#define L_lit(p) lit_sign(p)?"~":"", (lit_var(p)) - -// Just like 'assert()' but expression will be evaluated in the release version as well. -static inline void check(int expr) { assert(expr); } - -static void printlits(lit* begin, lit* end) -{ - int i; - for (i = 0; i < end - begin; i++) - printf(L_LIT" ",L_lit(begin[i])); -} - -//================================================================================================= -// Random numbers: - - -// Returns a random float 0 <= x < 1. Seed must never be 0. -static inline double drand(double* seed) { - int q; - *seed *= 1389796; - q = (int)(*seed / 2147483647); - *seed -= (double)q * 2147483647; - return *seed / 2147483647; } - - -// Returns a random integer 0 <= x < size. Seed must never be 0. -static inline int irand(double* seed, int size) { - return (int)(drand(seed) * size); } - - -//================================================================================================= -// Predeclarations: - -static void sat_solver_sort(void** array, int size, int(*comp)(const void *, const void *)); - -//================================================================================================= -// Clause datatype + minor functions: - -struct clause_t -{ - int size_learnt; - lit lits[0]; -}; - -static inline int clause_size (clause* c) { return c->size_learnt >> 1; } -static inline lit* clause_begin (clause* c) { return c->lits; } -static inline int clause_learnt (clause* c) { return c->size_learnt & 1; } -static inline float clause_activity (clause* c) { return *((float*)&c->lits[c->size_learnt>>1]); } -static inline void clause_setactivity(clause* c, float a) { *((float*)&c->lits[c->size_learnt>>1]) = a; } - -//================================================================================================= -// Encode literals in clause pointers: - -static inline clause* clause_from_lit (lit l) { return (clause*)((unsigned long)l + (unsigned long)l + 1); } -static inline bool clause_is_lit (clause* c) { return ((unsigned long)c & 1); } -static inline lit clause_read_lit (clause* c) { return (lit)((unsigned long)c >> 1); } - -//================================================================================================= -// Simple helpers: - -static inline int sat_solver_dlevel(sat_solver* s) { return veci_size(&s->trail_lim); } -static inline vecp* sat_solver_read_wlist(sat_solver* s, lit l) { return &s->wlists[l]; } -static inline void vecp_remove(vecp* v, void* e) -{ - void** ws = vecp_begin(v); - int j = 0; - for (; ws[j] != e ; j++); - assert(j < vecp_size(v)); - for (; j < vecp_size(v)-1; j++) ws[j] = ws[j+1]; - vecp_resize(v,vecp_size(v)-1); -} - -//================================================================================================= -// Variable order functions: - -static inline void order_update(sat_solver* s, int v) // updateorder -{ - int* orderpos = s->orderpos; - double* activity = s->activity; - int* heap = veci_begin(&s->order); - int i = orderpos[v]; - int x = heap[i]; - int parent = (i - 1) / 2; - - assert(s->orderpos[v] != -1); - - while (i != 0 && activity[x] > activity[heap[parent]]){ - heap[i] = heap[parent]; - orderpos[heap[i]] = i; - i = parent; - parent = (i - 1) / 2; - } - heap[i] = x; - orderpos[x] = i; -} - -static inline void order_assigned(sat_solver* s, int v) -{ -} - -static inline void order_unassigned(sat_solver* s, int v) // undoorder -{ - int* orderpos = s->orderpos; - if (orderpos[v] == -1){ - orderpos[v] = veci_size(&s->order); - veci_push(&s->order,v); - order_update(s,v); -//printf( "+%d ", v ); - } -} - -static inline int order_select(sat_solver* s, float random_var_freq) // selectvar -{ - int* heap; - double* activity; - int* orderpos; - - lbool* values = s->assigns; - - // Random decision: - if (drand(&s->random_seed) < random_var_freq){ - int next = irand(&s->random_seed,s->size); - assert(next >= 0 && next < s->size); - if (values[next] == l_Undef) - return next; - } - - // Activity based decision: - - heap = veci_begin(&s->order); - activity = s->activity; - orderpos = s->orderpos; - - - while (veci_size(&s->order) > 0){ - int next = heap[0]; - int size = veci_size(&s->order)-1; - int x = heap[size]; - - veci_resize(&s->order,size); - - orderpos[next] = -1; - - if (size > 0){ - double act = activity[x]; - - int i = 0; - int child = 1; - - - while (child < size){ - if (child+1 < size && activity[heap[child]] < activity[heap[child+1]]) - child++; - - assert(child < size); - - if (act >= activity[heap[child]]) - break; - - heap[i] = heap[child]; - orderpos[heap[i]] = i; - i = child; - child = 2 * child + 1; - } - heap[i] = x; - orderpos[heap[i]] = i; - } - -//printf( "-%d ", next ); - if (values[next] == l_Undef) - return next; - } - - return var_Undef; -} - -//================================================================================================= -// Activity functions: - -static inline void act_var_rescale(sat_solver* s) { - double* activity = s->activity; - int i; - for (i = 0; i < s->size; i++) - activity[i] *= 1e-100; - s->var_inc *= 1e-100; -} - -static inline void act_var_bump(sat_solver* s, int v) { - s->activity[v] += s->var_inc; - if (s->activity[v] > 1e100) - act_var_rescale(s); - //printf("bump %d %f\n", v-1, activity[v]); - if (s->orderpos[v] != -1) - order_update(s,v); -} - -static inline void act_var_bump_factor(sat_solver* s, int v) { - s->activity[v] += (s->var_inc * s->factors[v]); - if (s->activity[v] > 1e100) - act_var_rescale(s); - //printf("bump %d %f\n", v-1, activity[v]); - if (s->orderpos[v] != -1) - order_update(s,v); -} - -static inline void act_var_decay(sat_solver* s) { s->var_inc *= s->var_decay; } - -static inline void act_clause_rescale(sat_solver* s) { - clause** cs = (clause**)vecp_begin(&s->learnts); - int i; - for (i = 0; i < vecp_size(&s->learnts); i++){ - float a = clause_activity(cs[i]); - clause_setactivity(cs[i], a * (float)1e-20); - } - s->cla_inc *= (float)1e-20; -} - - -static inline void act_clause_bump(sat_solver* s, clause *c) { - float a = clause_activity(c) + s->cla_inc; - clause_setactivity(c,a); - if (a > 1e20) act_clause_rescale(s); -} - -static inline void act_clause_decay(sat_solver* s) { s->cla_inc *= s->cla_decay; } - -//================================================================================================= -// Clause functions: - -/* pre: size > 1 && no variable occurs twice - */ -static clause* clause_new(sat_solver* s, lit* begin, lit* end, int learnt) -{ - int size; - clause* c; - int i; - - assert(end - begin > 1); - assert(learnt >= 0 && learnt < 2); - size = end - begin; -// c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float)); -#ifdef SAT_USE_SYSTEM_MEMORY_MANAGEMENT - c = (clause*)malloc(sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float)); -#else - c = (clause*)Sat_MmStepEntryFetch( s->pMem, sizeof(clause) + sizeof(lit) * size + learnt * sizeof(float) ); -#endif - - c->size_learnt = (size << 1) | learnt; - assert(((unsigned int)c & 1) == 0); - - for (i = 0; i < size; i++) - c->lits[i] = begin[i]; - - if (learnt) - *((float*)&c->lits[size]) = 0.0; - - assert(begin[0] >= 0); - assert(begin[0] < s->size*2); - assert(begin[1] >= 0); - assert(begin[1] < s->size*2); - - assert(lit_neg(begin[0]) < s->size*2); - assert(lit_neg(begin[1]) < s->size*2); - - //vecp_push(sat_solver_read_wlist(s,lit_neg(begin[0])),(void*)c); - //vecp_push(sat_solver_read_wlist(s,lit_neg(begin[1])),(void*)c); - - vecp_push(sat_solver_read_wlist(s,lit_neg(begin[0])),(void*)(size > 2 ? c : clause_from_lit(begin[1]))); - vecp_push(sat_solver_read_wlist(s,lit_neg(begin[1])),(void*)(size > 2 ? c : clause_from_lit(begin[0]))); - - return c; -} - - -static void clause_remove(sat_solver* s, clause* c) -{ - lit* lits = clause_begin(c); - assert(lit_neg(lits[0]) < s->size*2); - assert(lit_neg(lits[1]) < s->size*2); - - //vecp_remove(sat_solver_read_wlist(s,lit_neg(lits[0])),(void*)c); - //vecp_remove(sat_solver_read_wlist(s,lit_neg(lits[1])),(void*)c); - - assert(lits[0] < s->size*2); - vecp_remove(sat_solver_read_wlist(s,lit_neg(lits[0])),(void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[1]))); - vecp_remove(sat_solver_read_wlist(s,lit_neg(lits[1])),(void*)(clause_size(c) > 2 ? c : clause_from_lit(lits[0]))); - - if (clause_learnt(c)){ - s->stats.learnts--; - s->stats.learnts_literals -= clause_size(c); - }else{ - s->stats.clauses--; - s->stats.clauses_literals -= clause_size(c); - } - -#ifdef SAT_USE_SYSTEM_MEMORY_MANAGEMENT - free(c); -#else - Sat_MmStepEntryRecycle( s->pMem, (char *)c, sizeof(clause) + sizeof(lit) * clause_size(c) + clause_learnt(c) * sizeof(float) ); -#endif -} - - -static lbool clause_simplify(sat_solver* s, clause* c) -{ - lit* lits = clause_begin(c); - lbool* values = s->assigns; - int i; - - assert(sat_solver_dlevel(s) == 0); - - for (i = 0; i < clause_size(c); i++){ - lbool sig = !lit_sign(lits[i]); sig += sig - 1; - if (values[lit_var(lits[i])] == sig) - return l_True; - } - return l_False; -} - -//================================================================================================= -// Minor (solver) functions: - -void sat_solver_setnvars(sat_solver* s,int n) -{ - int var; - - if (s->cap < n){ - - while (s->cap < n) s->cap = s->cap*2+1; - - s->wlists = (vecp*) realloc(s->wlists, sizeof(vecp)*s->cap*2); - s->activity = (double*) realloc(s->activity, sizeof(double)*s->cap); - s->factors = (double*) realloc(s->factors, sizeof(double)*s->cap); - s->assigns = (lbool*) realloc(s->assigns, sizeof(lbool)*s->cap); - s->orderpos = (int*) realloc(s->orderpos, sizeof(int)*s->cap); - s->reasons = (clause**)realloc(s->reasons, sizeof(clause*)*s->cap); - s->levels = (int*) realloc(s->levels, sizeof(int)*s->cap); - s->tags = (lbool*) realloc(s->tags, sizeof(lbool)*s->cap); - s->trail = (lit*) realloc(s->trail, sizeof(lit)*s->cap); - } - - for (var = s->size; var < n; var++){ - vecp_new(&s->wlists[2*var]); - vecp_new(&s->wlists[2*var+1]); - s->activity [var] = 0; - s->factors [var] = 0; - s->assigns [var] = l_Undef; - s->orderpos [var] = veci_size(&s->order); - s->reasons [var] = (clause*)0; - s->levels [var] = 0; - s->tags [var] = l_Undef; - - /* does not hold because variables enqueued at top level will not be reinserted in the heap - assert(veci_size(&s->order) == var); - */ - veci_push(&s->order,var); - order_update(s, var); - } - - s->size = n > s->size ? n : s->size; -} - - -static inline bool enqueue(sat_solver* s, lit l, clause* from) -{ - lbool* values = s->assigns; - int v = lit_var(l); - lbool val = values[v]; -#ifdef VERBOSEDEBUG - printf(L_IND"enqueue("L_LIT")\n", L_ind, L_lit(l)); -#endif - - lbool sig = !lit_sign(l); sig += sig - 1; - if (val != l_Undef){ - return val == sig; - }else{ - // New fact -- store it. -#ifdef VERBOSEDEBUG - printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(l)); -#endif - int* levels = s->levels; - clause** reasons = s->reasons; - - values [v] = sig; - levels [v] = sat_solver_dlevel(s); - reasons[v] = from; - s->trail[s->qtail++] = l; - - order_assigned(s, v); - return true; - } -} - - -static inline void assume(sat_solver* s, lit l){ - assert(s->qtail == s->qhead); - assert(s->assigns[lit_var(l)] == l_Undef); -#ifdef VERBOSEDEBUG - printf(L_IND"assume("L_LIT")\n", L_ind, L_lit(l)); -#endif - veci_push(&s->trail_lim,s->qtail); - enqueue(s,l,(clause*)0); -} - - -static void sat_solver_canceluntil(sat_solver* s, int level) { - lit* trail; - lbool* values; - clause** reasons; - int bound; - int c; - - if (sat_solver_dlevel(s) <= level) - return; - - trail = s->trail; - values = s->assigns; - reasons = s->reasons; - bound = (veci_begin(&s->trail_lim))[level]; - - //////////////////////////////////////// - // added to cancel all assignments -// if ( level == -1 ) -// bound = 0; - //////////////////////////////////////// - - for (c = s->qtail-1; c >= bound; c--) { - int x = lit_var(trail[c]); - values [x] = l_Undef; - reasons[x] = (clause*)0; - } - - for (c = s->qhead-1; c >= bound; c--) - order_unassigned(s,lit_var(trail[c])); - - s->qhead = s->qtail = bound; - veci_resize(&s->trail_lim,level); -} - -static void sat_solver_record(sat_solver* s, veci* cls) -{ - lit* begin = veci_begin(cls); - lit* end = begin + veci_size(cls); - clause* c = (veci_size(cls) > 1) ? clause_new(s,begin,end,1) : (clause*)0; - enqueue(s,*begin,c); - - /////////////////////////////////// - // add clause to internal storage - if ( s->pStore ) - { - extern int Sto_ManAddClause( void * p, lit * pBeg, lit * pEnd ); - int RetValue = Sto_ManAddClause( s->pStore, begin, end ); - assert( RetValue ); - } - /////////////////////////////////// - - assert(veci_size(cls) > 0); - - if (c != 0) { - vecp_push(&s->learnts,c); - act_clause_bump(s,c); - s->stats.learnts++; - s->stats.learnts_literals += veci_size(cls); - } -} - - -static double sat_solver_progress(sat_solver* s) -{ - lbool* values = s->assigns; - int* levels = s->levels; - int i; - - double progress = 0; - double F = 1.0 / s->size; - for (i = 0; i < s->size; i++) - if (values[i] != l_Undef) - progress += pow(F, levels[i]); - return progress / s->size; -} - -//================================================================================================= -// Major methods: - -static bool sat_solver_lit_removable(sat_solver* s, lit l, int minl) -{ - lbool* tags = s->tags; - clause** reasons = s->reasons; - int* levels = s->levels; - int top = veci_size(&s->tagged); - - assert(lit_var(l) >= 0 && lit_var(l) < s->size); - assert(reasons[lit_var(l)] != 0); - veci_resize(&s->stack,0); - veci_push(&s->stack,lit_var(l)); - - while (veci_size(&s->stack) > 0){ - clause* c; - int v = veci_begin(&s->stack)[veci_size(&s->stack)-1]; - assert(v >= 0 && v < s->size); - veci_resize(&s->stack,veci_size(&s->stack)-1); - assert(reasons[v] != 0); - c = reasons[v]; - - if (clause_is_lit(c)){ - int v = lit_var(clause_read_lit(c)); - if (tags[v] == l_Undef && levels[v] != 0){ - if (reasons[v] != 0 && ((1 << (levels[v] & 31)) & minl)){ - veci_push(&s->stack,v); - tags[v] = l_True; - veci_push(&s->tagged,v); - }else{ - int* tagged = veci_begin(&s->tagged); - int j; - for (j = top; j < veci_size(&s->tagged); j++) - tags[tagged[j]] = l_Undef; - veci_resize(&s->tagged,top); - return false; - } - } - }else{ - lit* lits = clause_begin(c); - int i, j; - - for (i = 1; i < clause_size(c); i++){ - int v = lit_var(lits[i]); - if (tags[v] == l_Undef && levels[v] != 0){ - if (reasons[v] != 0 && ((1 << (levels[v] & 31)) & minl)){ - - veci_push(&s->stack,lit_var(lits[i])); - tags[v] = l_True; - veci_push(&s->tagged,v); - }else{ - int* tagged = veci_begin(&s->tagged); - for (j = top; j < veci_size(&s->tagged); j++) - tags[tagged[j]] = l_Undef; - veci_resize(&s->tagged,top); - return false; - } - } - } - } - } - - return true; -} - -static void sat_solver_analyze(sat_solver* s, clause* c, veci* learnt) -{ - lit* trail = s->trail; - lbool* tags = s->tags; - clause** reasons = s->reasons; - int* levels = s->levels; - int cnt = 0; - lit p = lit_Undef; - int ind = s->qtail-1; - lit* lits; - int i, j, minl; - int* tagged; - - veci_push(learnt,lit_Undef); - - do{ - assert(c != 0); - - if (clause_is_lit(c)){ - lit q = clause_read_lit(c); - assert(lit_var(q) >= 0 && lit_var(q) < s->size); - if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){ - tags[lit_var(q)] = l_True; - veci_push(&s->tagged,lit_var(q)); - act_var_bump(s,lit_var(q)); - if (levels[lit_var(q)] == sat_solver_dlevel(s)) - cnt++; - else - veci_push(learnt,q); - } - }else{ - - if (clause_learnt(c)) - act_clause_bump(s,c); - - lits = clause_begin(c); - //printlits(lits,lits+clause_size(c)); printf("\n"); - for (j = (p == lit_Undef ? 0 : 1); j < clause_size(c); j++){ - lit q = lits[j]; - assert(lit_var(q) >= 0 && lit_var(q) < s->size); - if (tags[lit_var(q)] == l_Undef && levels[lit_var(q)] > 0){ - tags[lit_var(q)] = l_True; - veci_push(&s->tagged,lit_var(q)); - act_var_bump(s,lit_var(q)); - if (levels[lit_var(q)] == sat_solver_dlevel(s)) - cnt++; - else - veci_push(learnt,q); - } - } - } - - while (tags[lit_var(trail[ind--])] == l_Undef); - - p = trail[ind+1]; - c = reasons[lit_var(p)]; - cnt--; - - }while (cnt > 0); - - *veci_begin(learnt) = lit_neg(p); - - lits = veci_begin(learnt); - minl = 0; - for (i = 1; i < veci_size(learnt); i++){ - int lev = levels[lit_var(lits[i])]; - minl |= 1 << (lev & 31); - } - - // simplify (full) - for (i = j = 1; i < veci_size(learnt); i++){ - if (reasons[lit_var(lits[i])] == 0 || !sat_solver_lit_removable(s,lits[i],minl)) - lits[j++] = lits[i]; - } - - // update size of learnt + statistics - s->stats.max_literals += veci_size(learnt); - veci_resize(learnt,j); - s->stats.tot_literals += j; - - // clear tags - tagged = veci_begin(&s->tagged); - for (i = 0; i < veci_size(&s->tagged); i++) - tags[tagged[i]] = l_Undef; - veci_resize(&s->tagged,0); - -#ifdef DEBUG - for (i = 0; i < s->size; i++) - assert(tags[i] == l_Undef); -#endif - -#ifdef VERBOSEDEBUG - printf(L_IND"Learnt {", L_ind); - for (i = 0; i < veci_size(learnt); i++) printf(" "L_LIT, L_lit(lits[i])); -#endif - if (veci_size(learnt) > 1){ - int max_i = 1; - int max = levels[lit_var(lits[1])]; - lit tmp; - - for (i = 2; i < veci_size(learnt); i++) - if (levels[lit_var(lits[i])] > max){ - max = levels[lit_var(lits[i])]; - max_i = i; - } - - tmp = lits[1]; - lits[1] = lits[max_i]; - lits[max_i] = tmp; - } -#ifdef VERBOSEDEBUG - { - int lev = veci_size(learnt) > 1 ? levels[lit_var(lits[1])] : 0; - printf(" } at level %d\n", lev); - } -#endif -} - - -clause* sat_solver_propagate(sat_solver* s) -{ - lbool* values = s->assigns; - clause* confl = (clause*)0; - lit* lits; - - //printf("sat_solver_propagate\n"); - while (confl == 0 && s->qtail - s->qhead > 0){ - lit p = s->trail[s->qhead++]; - vecp* ws = sat_solver_read_wlist(s,p); - clause **begin = (clause**)vecp_begin(ws); - clause **end = begin + vecp_size(ws); - clause **i, **j; - - s->stats.propagations++; - s->simpdb_props--; - - //printf("checking lit %d: "L_LIT"\n", veci_size(ws), L_lit(p)); - for (i = j = begin; i < end; ){ - if (clause_is_lit(*i)){ -// s->stats.inspects2++; - *j++ = *i; - if (!enqueue(s,clause_read_lit(*i),clause_from_lit(p))){ - confl = s->binary; - (clause_begin(confl))[1] = lit_neg(p); - (clause_begin(confl))[0] = clause_read_lit(*i++); - // Copy the remaining watches: -// s->stats.inspects2 += end - i; - while (i < end) - *j++ = *i++; - } - }else{ - lit false_lit; - lbool sig; - - lits = clause_begin(*i); - - // Make sure the false literal is data[1]: - false_lit = lit_neg(p); - if (lits[0] == false_lit){ - lits[0] = lits[1]; - lits[1] = false_lit; - } - assert(lits[1] == false_lit); - //printf("checking clause: "); printlits(lits, lits+clause_size(*i)); printf("\n"); - - // If 0th watch is true, then clause is already satisfied. - sig = !lit_sign(lits[0]); sig += sig - 1; - if (values[lit_var(lits[0])] == sig){ - *j++ = *i; - }else{ - // Look for new watch: - lit* stop = lits + clause_size(*i); - lit* k; - for (k = lits + 2; k < stop; k++){ - lbool sig = lit_sign(*k); sig += sig - 1; - if (values[lit_var(*k)] != sig){ - lits[1] = *k; - *k = false_lit; - vecp_push(sat_solver_read_wlist(s,lit_neg(lits[1])),*i); - goto next; } - } - - *j++ = *i; - // Clause is unit under assignment: - if (!enqueue(s,lits[0], *i)){ - confl = *i++; - // Copy the remaining watches: -// s->stats.inspects2 += end - i; - while (i < end) - *j++ = *i++; - } - } - } - next: - i++; - } - - s->stats.inspects += j - (clause**)vecp_begin(ws); - vecp_resize(ws,j - (clause**)vecp_begin(ws)); - } - - return confl; -} - -static inline int clause_cmp (const void* x, const void* y) { - return clause_size((clause*)x) > 2 && (clause_size((clause*)y) == 2 || clause_activity((clause*)x) < clause_activity((clause*)y)) ? -1 : 1; } - -void sat_solver_reducedb(sat_solver* s) -{ - int i, j; - double extra_lim = s->cla_inc / vecp_size(&s->learnts); // Remove any clause below this activity - clause** learnts = (clause**)vecp_begin(&s->learnts); - clause** reasons = s->reasons; - - sat_solver_sort(vecp_begin(&s->learnts), vecp_size(&s->learnts), &clause_cmp); - - for (i = j = 0; i < vecp_size(&s->learnts) / 2; i++){ - if (clause_size(learnts[i]) > 2 && reasons[lit_var(*clause_begin(learnts[i]))] != learnts[i]) - clause_remove(s,learnts[i]); - else - learnts[j++] = learnts[i]; - } - for (; i < vecp_size(&s->learnts); i++){ - if (clause_size(learnts[i]) > 2 && reasons[lit_var(*clause_begin(learnts[i]))] != learnts[i] && clause_activity(learnts[i]) < extra_lim) - clause_remove(s,learnts[i]); - else - learnts[j++] = learnts[i]; - } - - //printf("reducedb deleted %d\n", vecp_size(&s->learnts) - j); - - - vecp_resize(&s->learnts,j); -} - -static lbool sat_solver_search(sat_solver* s, sint64 nof_conflicts, sint64 nof_learnts) -{ - int* levels = s->levels; - double var_decay = 0.95; - double clause_decay = 0.999; - double random_var_freq = 0.02; - - sint64 conflictC = 0; - veci learnt_clause; - int i; - - assert(s->root_level == sat_solver_dlevel(s)); - - s->nRestarts++; - s->stats.starts++; - s->var_decay = (float)(1 / var_decay ); - s->cla_decay = (float)(1 / clause_decay); - veci_resize(&s->model,0); - veci_new(&learnt_clause); - - // use activity factors in every even restart - if ( (s->nRestarts & 1) && veci_size(&s->act_vars) > 0 ) - for ( i = 0; i < s->act_vars.size; i++ ) - act_var_bump_factor(s, s->act_vars.ptr[i]); - - for (;;){ - clause* confl = sat_solver_propagate(s); - if (confl != 0){ - // CONFLICT - int blevel; - -#ifdef VERBOSEDEBUG - printf(L_IND"**CONFLICT**\n", L_ind); -#endif - s->stats.conflicts++; conflictC++; - if (sat_solver_dlevel(s) == s->root_level){ - veci_delete(&learnt_clause); - return l_False; - } - - veci_resize(&learnt_clause,0); - sat_solver_analyze(s, confl, &learnt_clause); - blevel = veci_size(&learnt_clause) > 1 ? levels[lit_var(veci_begin(&learnt_clause)[1])] : s->root_level; - blevel = s->root_level > blevel ? s->root_level : blevel; - sat_solver_canceluntil(s,blevel); - sat_solver_record(s,&learnt_clause); - act_var_decay(s); - act_clause_decay(s); - - }else{ - // NO CONFLICT - int next; - - if (nof_conflicts >= 0 && conflictC >= nof_conflicts){ - // Reached bound on number of conflicts: - s->progress_estimate = sat_solver_progress(s); - sat_solver_canceluntil(s,s->root_level); - veci_delete(&learnt_clause); - return l_Undef; } - - if ( s->nConfLimit && s->stats.conflicts > s->nConfLimit || - s->nInsLimit && s->stats.inspects > s->nInsLimit ) - { - // Reached bound on number of conflicts: - s->progress_estimate = sat_solver_progress(s); - sat_solver_canceluntil(s,s->root_level); - veci_delete(&learnt_clause); - return l_Undef; - } - - if (sat_solver_dlevel(s) == 0 && !s->fSkipSimplify) - // Simplify the set of problem clauses: - sat_solver_simplify(s); - - if (nof_learnts >= 0 && vecp_size(&s->learnts) - s->qtail >= nof_learnts) - // Reduce the set of learnt clauses: - sat_solver_reducedb(s); - - // New variable decision: - s->stats.decisions++; - next = order_select(s,(float)random_var_freq); - - if (next == var_Undef){ - // Model found: - lbool* values = s->assigns; - int i; - veci_resize(&s->model, 0); - for (i = 0; i < s->size; i++) - veci_push(&s->model,(int)values[i]); - sat_solver_canceluntil(s,s->root_level); - veci_delete(&learnt_clause); - - /* - veci apa; veci_new(&apa); - for (i = 0; i < s->size; i++) - veci_push(&apa,(int)(s->model.ptr[i] == l_True ? toLit(i) : lit_neg(toLit(i)))); - printf("model: "); printlits((lit*)apa.ptr, (lit*)apa.ptr + veci_size(&apa)); printf("\n"); - veci_delete(&apa); - */ - - return l_True; - } - - assume(s,lit_neg(toLit(next))); - } - } - - return l_Undef; // cannot happen -} - -//================================================================================================= -// External solver functions: - -sat_solver* sat_solver_new(void) -{ - sat_solver* s = (sat_solver*)malloc(sizeof(sat_solver)); - memset( s, 0, sizeof(sat_solver) ); - - // initialize vectors - vecp_new(&s->clauses); - vecp_new(&s->learnts); - veci_new(&s->order); - veci_new(&s->trail_lim); - veci_new(&s->tagged); - veci_new(&s->stack); - veci_new(&s->model); - veci_new(&s->act_vars); - - // initialize arrays - s->wlists = 0; - s->activity = 0; - s->factors = 0; - s->assigns = 0; - s->orderpos = 0; - s->reasons = 0; - s->levels = 0; - s->tags = 0; - s->trail = 0; - - - // initialize other vars - s->size = 0; - s->cap = 0; - s->qhead = 0; - s->qtail = 0; - s->cla_inc = 1; - s->cla_decay = 1; - s->var_inc = 1; - s->var_decay = 1; - s->root_level = 0; - s->simpdb_assigns = 0; - s->simpdb_props = 0; - s->random_seed = 91648253; - s->progress_estimate = 0; - s->binary = (clause*)malloc(sizeof(clause) + sizeof(lit)*2); - s->binary->size_learnt = (2 << 1); - s->verbosity = 0; - - s->stats.starts = 0; - s->stats.decisions = 0; - s->stats.propagations = 0; - s->stats.inspects = 0; - s->stats.conflicts = 0; - s->stats.clauses = 0; - s->stats.clauses_literals = 0; - s->stats.learnts = 0; - s->stats.learnts_literals = 0; - s->stats.max_literals = 0; - s->stats.tot_literals = 0; - -#ifdef SAT_USE_SYSTEM_MEMORY_MANAGEMENT - s->pMem = NULL; -#else - s->pMem = Sat_MmStepStart( 10 ); -#endif - return s; -} - - -void sat_solver_delete(sat_solver* s) -{ - -#ifdef SAT_USE_SYSTEM_MEMORY_MANAGEMENT - int i; - for (i = 0; i < vecp_size(&s->clauses); i++) - free(vecp_begin(&s->clauses)[i]); - for (i = 0; i < vecp_size(&s->learnts); i++) - free(vecp_begin(&s->learnts)[i]); -#else - Sat_MmStepStop( s->pMem, 0 ); -#endif - - // delete vectors - vecp_delete(&s->clauses); - vecp_delete(&s->learnts); - veci_delete(&s->order); - veci_delete(&s->trail_lim); - veci_delete(&s->tagged); - veci_delete(&s->stack); - veci_delete(&s->model); - veci_delete(&s->act_vars); - free(s->binary); - - // delete arrays - if (s->wlists != 0){ - int i; - for (i = 0; i < s->size*2; i++) - vecp_delete(&s->wlists[i]); - - // if one is different from null, all are - free(s->wlists ); - free(s->activity ); - free(s->factors ); - free(s->assigns ); - free(s->orderpos ); - free(s->reasons ); - free(s->levels ); - free(s->trail ); - free(s->tags ); - } - - sat_solver_store_free(s); - free(s); -} - - -bool sat_solver_addclause(sat_solver* s, lit* begin, lit* end) -{ - lit *i,*j; - int maxvar; - lbool* values; - lit last; - - if (begin == end) return false; - - //printlits(begin,end); printf("\n"); - // insertion sort - maxvar = lit_var(*begin); - for (i = begin + 1; i < end; i++){ - lit l = *i; - maxvar = lit_var(l) > maxvar ? lit_var(l) : maxvar; - for (j = i; j > begin && *(j-1) > l; j--) - *j = *(j-1); - *j = l; - } - sat_solver_setnvars(s,maxvar+1); -// sat_solver_setnvars(s, lit_var(*(end-1))+1 ); - - //printlits(begin,end); printf("\n"); - values = s->assigns; - - // delete duplicates - last = lit_Undef; - for (i = j = begin; i < end; i++){ - //printf("lit: "L_LIT", value = %d\n", L_lit(*i), (lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)])); - lbool sig = !lit_sign(*i); sig += sig - 1; - if (*i == lit_neg(last) || sig == values[lit_var(*i)]) - return true; // tautology - else if (*i != last && values[lit_var(*i)] == l_Undef) - last = *j++ = *i; - } - - //printf("final: "); printlits(begin,j); printf("\n"); - - if (j == begin) // empty clause - return false; - - /////////////////////////////////// - // add clause to internal storage - if ( s->pStore ) - { - extern int Sto_ManAddClause( void * p, lit * pBeg, lit * pEnd ); - int RetValue = Sto_ManAddClause( s->pStore, begin, j ); - assert( RetValue ); - } - /////////////////////////////////// - - if (j - begin == 1) // unit clause - return enqueue(s,*begin,(clause*)0); - - // create new clause - vecp_push(&s->clauses,clause_new(s,begin,j,0)); - - - s->stats.clauses++; - s->stats.clauses_literals += j - begin; - - return true; -} - - -bool sat_solver_simplify(sat_solver* s) -{ - clause** reasons; - int type; - - assert(sat_solver_dlevel(s) == 0); - - if (sat_solver_propagate(s) != 0) - return false; - - if (s->qhead == s->simpdb_assigns || s->simpdb_props > 0) - return true; - - reasons = s->reasons; - for (type = 0; type < 2; type++){ - vecp* cs = type ? &s->learnts : &s->clauses; - clause** cls = (clause**)vecp_begin(cs); - - int i, j; - for (j = i = 0; i < vecp_size(cs); i++){ - if (reasons[lit_var(*clause_begin(cls[i]))] != cls[i] && - clause_simplify(s,cls[i]) == l_True) - clause_remove(s,cls[i]); - else - cls[j++] = cls[i]; - } - vecp_resize(cs,j); - } - - s->simpdb_assigns = s->qhead; - // (shouldn't depend on 'stats' really, but it will do for now) - s->simpdb_props = (int)(s->stats.clauses_literals + s->stats.learnts_literals); - - return true; -} - - -int sat_solver_solve(sat_solver* s, lit* begin, lit* end, sint64 nConfLimit, sint64 nInsLimit, sint64 nConfLimitGlobal, sint64 nInsLimitGlobal) -{ - sint64 nof_conflicts = 100; - sint64 nof_learnts = sat_solver_nclauses(s) / 3; - lbool status = l_Undef; - lbool* values = s->assigns; - lit* i; - - // set the external limits - s->nCalls++; - s->nRestarts = 0; - s->nConfLimit = 0; - s->nInsLimit = 0; - if ( nConfLimit ) - s->nConfLimit = s->stats.conflicts + nConfLimit; - if ( nInsLimit ) - s->nInsLimit = s->stats.inspects + nInsLimit; - if ( nConfLimitGlobal && (s->nConfLimit == 0 || s->nConfLimit > nConfLimitGlobal) ) - s->nConfLimit = nConfLimitGlobal; - if ( nInsLimitGlobal && (s->nInsLimit == 0 || s->nInsLimit > nInsLimitGlobal) ) - s->nInsLimit = nInsLimitGlobal; - - //printf("solve: "); printlits(begin, end); printf("\n"); - for (i = begin; i < end; i++){ - switch (lit_sign(*i) ? -values[lit_var(*i)] : values[lit_var(*i)]){ - case 1: /* l_True: */ - break; - case 0: /* l_Undef */ - assume(s, *i); - if (sat_solver_propagate(s) == NULL) - break; - // fallthrough - case -1: /* l_False */ - sat_solver_canceluntil(s, 0); - return l_False; - } - } - s->nCalls2++; - - s->root_level = sat_solver_dlevel(s); - - if (s->verbosity >= 1){ - printf("==================================[MINISAT]===================================\n"); - printf("| Conflicts | ORIGINAL | LEARNT | Progress |\n"); - printf("| | Clauses Literals | Limit Clauses Literals Lit/Cl | |\n"); - printf("==============================================================================\n"); - } - - while (status == l_Undef){ - double Ratio = (s->stats.learnts == 0)? 0.0 : - s->stats.learnts_literals / (double)s->stats.learnts; - - if (s->verbosity >= 1) - { - printf("| %9.0f | %7.0f %8.0f | %7.0f %7.0f %8.0f %7.1f | %6.3f %% |\n", - (double)s->stats.conflicts, - (double)s->stats.clauses, - (double)s->stats.clauses_literals, - (double)nof_learnts, - (double)s->stats.learnts, - (double)s->stats.learnts_literals, - Ratio, - s->progress_estimate*100); - fflush(stdout); - } - status = sat_solver_search(s, nof_conflicts, nof_learnts); - nof_conflicts = nof_conflicts * 3 / 2; //*= 1.5; - nof_learnts = nof_learnts * 11 / 10; //*= 1.1; - - // quit the loop if reached an external limit - if ( s->nConfLimit && s->stats.conflicts > s->nConfLimit ) - { -// printf( "Reached the limit on the number of conflicts (%d).\n", s->nConfLimit ); - break; - } - if ( s->nInsLimit && s->stats.inspects > s->nInsLimit ) - { -// printf( "Reached the limit on the number of implications (%d).\n", s->nInsLimit ); - break; - } - } - if (s->verbosity >= 1) - printf("==============================================================================\n"); - - sat_solver_canceluntil(s,0); - - //////////////////////////////////////////////// - if ( status == l_False && s->pStore ) - { - extern int Sto_ManAddClause( void * p, lit * pBeg, lit * pEnd ); - int RetValue = Sto_ManAddClause( s->pStore, NULL, NULL ); - assert( RetValue ); - } - //////////////////////////////////////////////// - return status; -} - - -int sat_solver_nvars(sat_solver* s) -{ - return s->size; -} - - -int sat_solver_nclauses(sat_solver* s) -{ - return vecp_size(&s->clauses); -} - - -int sat_solver_nconflicts(sat_solver* s) -{ - return (int)s->stats.conflicts; -} - -//================================================================================================= -// Clause storage functions: - -void sat_solver_store_alloc( sat_solver * s ) -{ - extern void * Sto_ManAlloc(); - assert( s->pStore == NULL ); - s->pStore = Sto_ManAlloc(); -} - -void sat_solver_store_write( sat_solver * s, char * pFileName ) -{ - extern void Sto_ManDumpClauses( void * p, char * pFileName ); - if ( s->pStore ) Sto_ManDumpClauses( s->pStore, pFileName ); -} - -void sat_solver_store_free( sat_solver * s ) -{ - extern void Sto_ManFree( void * p ); - if ( s->pStore ) Sto_ManFree( s->pStore ); - s->pStore = NULL; -} - -void sat_solver_store_mark_roots( sat_solver * s ) -{ - extern void Sto_ManMarkRoots( void * p ); - if ( s->pStore ) Sto_ManMarkRoots( s->pStore ); -} - -void sat_solver_store_mark_clauses_a( sat_solver * s ) -{ - extern void Sto_ManMarkClausesA( void * p ); - if ( s->pStore ) Sto_ManMarkClausesA( s->pStore ); -} - -void * sat_solver_store_release( sat_solver * s ) -{ - void * pTemp; - if ( s->pStore == NULL ) - return NULL; - pTemp = s->pStore; - s->pStore = NULL; - return pTemp; -} - -//================================================================================================= -// Sorting functions (sigh): - -static inline void selectionsort(void** array, int size, int(*comp)(const void *, const void *)) -{ - int i, j, best_i; - void* tmp; - - for (i = 0; i < size-1; i++){ - best_i = i; - for (j = i+1; j < size; j++){ - if (comp(array[j], array[best_i]) < 0) - best_i = j; - } - tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; - } -} - - -static void sortrnd(void** array, int size, int(*comp)(const void *, const void *), double* seed) -{ - if (size <= 15) - selectionsort(array, size, comp); - - else{ - void* pivot = array[irand(seed, size)]; - void* tmp; - int i = -1; - int j = size; - - for(;;){ - do i++; while(comp(array[i], pivot)<0); - do j--; while(comp(pivot, array[j])<0); - - if (i >= j) break; - - tmp = array[i]; array[i] = array[j]; array[j] = tmp; - } - - sortrnd(array , i , comp, seed); - sortrnd(&array[i], size-i, comp, seed); - } -} - -void sat_solver_sort(void** array, int size, int(*comp)(const void *, const void *)) -{ - double seed = 91648253; - sortrnd(array,size,comp,&seed); -} diff --git a/src/sat/bsat/satSolver.h b/src/sat/bsat/satSolver.h deleted file mode 100644 index 542b9895..00000000 --- a/src/sat/bsat/satSolver.h +++ /dev/null @@ -1,191 +0,0 @@ -/************************************************************************************************** -MiniSat -- Copyright (c) 2005, Niklas Sorensson -http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ -// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko - -#ifndef satSolver_h -#define satSolver_h - -#ifdef _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#endif - -#include "satVec.h" -#include "satMem.h" - -//================================================================================================= -// Simple types: - -// does not work for c++ -//typedef int bool; -#ifndef __cplusplus -#ifndef bool -#define bool int -#endif -#endif - -static const bool true = 1; -static const bool false = 0; - -typedef int lit; -typedef char lbool; - -#ifndef SINT64 -#define SINT64 - -#ifdef _WIN32 -typedef signed __int64 sint64; // compatible with MS VS 6.0 -#else -typedef long long sint64; -#endif - -#endif - -static const int var_Undef = -1; -static const lit lit_Undef = -2; - -static const lbool l_Undef = 0; -static const lbool l_True = 1; -static const lbool l_False = -1; - -static inline lit toLit (int v) { return v + v; } -static inline lit toLitCond(int v, int c) { return v + v + (c != 0); } -static inline lit lit_neg (lit l) { return l ^ 1; } -static inline int lit_var (lit l) { return l >> 1; } -static inline int lit_sign (lit l) { return l & 1; } -static inline int lit_print(lit l) { return lit_sign(l)? -lit_var(l)-1 : lit_var(l)+1; } -static inline lit lit_read (int s) { return s > 0 ? toLit(s-1) : lit_neg(toLit(-s-1)); } - - -//================================================================================================= -// Public interface: - -struct sat_solver_t; -typedef struct sat_solver_t sat_solver; - -extern sat_solver* sat_solver_new(void); -extern void sat_solver_delete(sat_solver* s); - -extern bool sat_solver_addclause(sat_solver* s, lit* begin, lit* end); -extern bool sat_solver_simplify(sat_solver* s); -extern int sat_solver_solve(sat_solver* s, lit* begin, lit* end, sint64 nConfLimit, sint64 nInsLimit, sint64 nConfLimitGlobal, sint64 nInsLimitGlobal); - -extern int sat_solver_nvars(sat_solver* s); -extern int sat_solver_nclauses(sat_solver* s); -extern int sat_solver_nconflicts(sat_solver* s); - -extern void sat_solver_setnvars(sat_solver* s,int n); - -struct stats_t -{ - sint64 starts, decisions, propagations, inspects, conflicts; - sint64 clauses, clauses_literals, learnts, learnts_literals, max_literals, tot_literals; -}; -typedef struct stats_t stats; - -extern void Sat_SolverWriteDimacs( sat_solver * p, char * pFileName, lit* assumptionsBegin, lit* assumptionsEnd, int incrementVars ); -extern void Sat_SolverPrintStats( FILE * pFile, sat_solver * p ); -extern int * Sat_SolverGetModel( sat_solver * p, int * pVars, int nVars ); -extern void Sat_SolverDoubleClauses( sat_solver * p, int iVar ); - -// trace recording -extern void Sat_SolverTraceStart( sat_solver * pSat, char * pName ); -extern void Sat_SolverTraceStop( sat_solver * pSat ); -extern void Sat_SolverTraceWrite( sat_solver * pSat, int * pBeg, int * pEnd, int fRoot ); - -// clause storage -extern void sat_solver_store_alloc( sat_solver * s ); -extern void sat_solver_store_write( sat_solver * s, char * pFileName ); -extern void sat_solver_store_free( sat_solver * s ); -extern void sat_solver_store_mark_roots( sat_solver * s ); -extern void sat_solver_store_mark_clauses_a( sat_solver * s ); -extern void * sat_solver_store_release( sat_solver * s ); - -//================================================================================================= -// Solver representation: - -struct clause_t; -typedef struct clause_t clause; - -struct sat_solver_t -{ - int size; // nof variables - int cap; // size of varmaps - int qhead; // Head index of queue. - int qtail; // Tail index of queue. - - // clauses - vecp clauses; // List of problem constraints. (contains: clause*) - vecp learnts; // List of learnt clauses. (contains: clause*) - - // activities - double var_inc; // Amount to bump next variable with. - double var_decay; // INVERSE decay factor for variable activity: stores 1/decay. - float cla_inc; // Amount to bump next clause with. - float cla_decay; // INVERSE decay factor for clause activity: stores 1/decay. - - vecp* wlists; // - double* activity; // A heuristic measurement of the activity of a variable. - lbool* assigns; // Current values of variables. - int* orderpos; // Index in variable order. - clause** reasons; // - int* levels; // - lit* trail; - - clause* binary; // A temporary binary clause - lbool* tags; // - veci tagged; // (contains: var) - veci stack; // (contains: var) - - veci order; // Variable order. (heap) (contains: var) - veci trail_lim; // Separator indices for different decision levels in 'trail'. (contains: int) - veci model; // If problem is solved, this vector contains the model (contains: lbool). - - int root_level; // Level of first proper decision. - int simpdb_assigns;// Number of top-level assignments at last 'simplifyDB()'. - int simpdb_props; // Number of propagations before next 'simplifyDB()'. - double random_seed; - double progress_estimate; - int verbosity; // Verbosity level. 0=silent, 1=some progress report, 2=everything - - stats stats; - - sint64 nConfLimit; // external limit on the number of conflicts - sint64 nInsLimit; // external limit on the number of implications - - veci act_vars; // variables whose activity has changed - double* factors; // the activity factors - int nRestarts; // the number of local restarts - int nCalls; // the number of local restarts - int nCalls2; // the number of local restarts - - Sat_MmStep_t * pMem; - - int fSkipSimplify; // set to one to skip simplification of the clause database - - // clause store - void * pStore; - - // trace recording - FILE * pFile; - int nClauses; - int nRoots; -}; - -#endif diff --git a/src/sat/bsat/satStore.c b/src/sat/bsat/satStore.c deleted file mode 100644 index 7c1d7132..00000000 --- a/src/sat/bsat/satStore.c +++ /dev/null @@ -1,437 +0,0 @@ -/**CFile**************************************************************** - - FileName [satStore.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [SAT solver.] - - Synopsis [Records the trace of SAT solving in the CNF form.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: satStore.c,v 1.4 2005/09/16 22:55:03 casem Exp $] - -***********************************************************************/ - -#include -#include -#include -#include -#include -#include "satStore.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Fetches memory.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Sto_ManMemoryFetch( Sto_Man_t * p, int nBytes ) -{ - char * pMem; - if ( p->pChunkLast == NULL || nBytes > p->nChunkSize - p->nChunkUsed ) - { - pMem = (char *)malloc( p->nChunkSize ); - *(char **)pMem = p->pChunkLast; - p->pChunkLast = pMem; - p->nChunkUsed = sizeof(char *); - } - pMem = p->pChunkLast + p->nChunkUsed; - p->nChunkUsed += nBytes; - return pMem; -} - -/**Function************************************************************* - - Synopsis [Frees memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sto_ManMemoryStop( Sto_Man_t * p ) -{ - char * pMem, * pNext; - if ( p->pChunkLast == NULL ) - return; - for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext ) - free( pMem ); - free( pMem ); -} - -/**Function************************************************************* - - Synopsis [Reports memory usage in bytes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sto_ManMemoryReport( Sto_Man_t * p ) -{ - int Total; - char * pMem, * pNext; - if ( p->pChunkLast == NULL ) - return 0; - Total = p->nChunkUsed; - for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext ) - Total += p->nChunkSize; - return Total; -} - - -/**Function************************************************************* - - Synopsis [Allocate proof manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Sto_Man_t * Sto_ManAlloc() -{ - Sto_Man_t * p; - // allocate the manager - p = (Sto_Man_t *)malloc( sizeof(Sto_Man_t) ); - memset( p, 0, sizeof(Sto_Man_t) ); - // memory management - p->nChunkSize = (1<<16); // use 64K chunks - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocate proof manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sto_ManFree( Sto_Man_t * p ) -{ - Sto_ManMemoryStop( p ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Adds one clause to the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sto_ManAddClause( Sto_Man_t * p, lit * pBeg, lit * pEnd ) -{ - Sto_Cls_t * pClause; - lit Lit, * i, * j; - int nSize; - - // process the literals - if ( pBeg < pEnd ) - { - // insertion sort - for ( i = pBeg + 1; i < pEnd; i++ ) - { - Lit = *i; - for ( j = i; j > pBeg && *(j-1) > Lit; j-- ) - *j = *(j-1); - *j = Lit; - } - // make sure there is no duplicated variables - for ( i = pBeg + 1; i < pEnd; i++ ) - if ( lit_var(*(i-1)) == lit_var(*i) ) - { - printf( "The clause contains two literals of the same variable: %d and %d.\n", *(i-1), *i ); - return 0; - } - // check the largest var size - p->nVars = STO_MAX( p->nVars, lit_var(*(pEnd-1)) + 1 ); - } - - // get memory for the clause - nSize = sizeof(Sto_Cls_t) + sizeof(lit) * (pEnd - pBeg); - pClause = (Sto_Cls_t *)Sto_ManMemoryFetch( p, nSize ); - memset( pClause, 0, sizeof(Sto_Cls_t) ); - - // assign the clause - pClause->Id = p->nClauses++; - pClause->nLits = pEnd - pBeg; - memcpy( pClause->pLits, pBeg, sizeof(lit) * (pEnd - pBeg) ); - - // add the clause to the list - if ( p->pHead == NULL ) - p->pHead = pClause; - if ( p->pTail == NULL ) - p->pTail = pClause; - else - { - p->pTail->pNext = pClause; - p->pTail = pClause; - } - - // add the empty clause - if ( pClause->nLits == 0 ) - { - if ( p->pEmpty ) - { - printf( "More than one empty clause!\n" ); - return 0; - } - p->pEmpty = pClause; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Mark all clauses added so far as root clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sto_ManMarkRoots( Sto_Man_t * p ) -{ - Sto_Cls_t * pClause; - p->nRoots = 0; - Sto_ManForEachClause( p, pClause ) - { - pClause->fRoot = 1; - p->nRoots++; - } -} - -/**Function************************************************************* - - Synopsis [Mark all clauses added so far as clause of A.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sto_ManMarkClausesA( Sto_Man_t * p ) -{ - Sto_Cls_t * pClause; - p->nClausesA = 0; - Sto_ManForEachClause( p, pClause ) - { - pClause->fA = 1; - p->nClausesA++; - } -} - - -/**Function************************************************************* - - Synopsis [Writes the stored clauses into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sto_ManDumpClauses( Sto_Man_t * p, char * pFileName ) -{ - FILE * pFile; - Sto_Cls_t * pClause; - int i; - // start the file - pFile = fopen( pFileName, "w" ); - if ( pFile == NULL ) - { - printf( "Error: Cannot open output file (%s).\n", pFileName ); - return; - } - // write the data - fprintf( pFile, "p %d %d %d %d\n", p->nVars, p->nClauses, p->nRoots, p->nClausesA ); - Sto_ManForEachClause( p, pClause ) - { - for ( i = 0; i < (int)pClause->nLits; i++ ) - fprintf( pFile, " %d", lit_print(pClause->pLits[i]) ); - fprintf( pFile, "\n" ); - } - fprintf( pFile, " 0\n" ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Reads one literal from file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Sto_ManLoadNumber( FILE * pFile, int * pNumber ) -{ - int Char, Number = 0, Sign = 0; - // skip space-like chars - do { - Char = fgetc( pFile ); - if ( Char == EOF ) - return 0; - } while ( Char == ' ' || Char == '\t' || Char == '\r' || Char == '\n' ); - // read the literal - while ( 1 ) - { - // get the next character - Char = fgetc( pFile ); - if ( Char == ' ' || Char == '\t' || Char == '\r' || Char == '\n' ) - break; - // check that the char is a digit - if ( (Char < '0' || Char > '9') && Char != '-' ) - { - printf( "Error: Wrong char (%c) in the input file.\n", Char ); - return 0; - } - // check if this is a minus - if ( Char == '-' ) - Sign = 1; - else - Number = 10 * Number + Char; - } - // return the number - *pNumber = Sign? -Number : Number; - return 1; -} - -/**Function************************************************************* - - Synopsis [Reads CNF from file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Sto_Man_t * Sto_ManLoadClauses( char * pFileName ) -{ - FILE * pFile; - Sto_Man_t * p; - Sto_Cls_t * pClause; - char pBuffer[1024]; - int nLits, nLitsAlloc, Counter, Number; - lit * pLits; - - // start the file - pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - printf( "Error: Cannot open input file (%s).\n", pFileName ); - return NULL; - } - - // create the manager - p = Sto_ManAlloc(); - - // alloc the array of literals - nLitsAlloc = 1024; - pLits = (lit *)malloc( sizeof(lit) * nLitsAlloc ); - - // read file header - p->nVars = p->nClauses = p->nRoots = p->nClausesA = 0; - while ( fgets( pBuffer, 1024, pFile ) ) - { - if ( pBuffer[0] == 'c' ) - continue; - if ( pBuffer[0] == 'p' ) - { - sscanf( pBuffer + 1, "%d %d %d %d", p->nVars, p->nClauses, p->nRoots, p->nClausesA ); - break; - } - printf( "Warning: Skipping line: \"%s\"\n", pBuffer ); - } - - // read the clauses - nLits = 0; - while ( Sto_ManLoadNumber(pFile, &Number) ) - { - if ( Number == 0 ) - { - int RetValue; - RetValue = Sto_ManAddClause( p, pLits, pLits + nLits ); - assert( RetValue ); - nLits = 0; - continue; - } - if ( nLits == nLitsAlloc ) - { - nLitsAlloc *= 2; - pLits = (lit *)realloc( pLits, sizeof(lit) * nLitsAlloc ); - } - pLits[ nLits++ ] = lit_read(Number); - } - if ( nLits > 0 ) - printf( "Error: The last clause was not saved.\n" ); - - // count clauses - Counter = 0; - Sto_ManForEachClause( p, pClause ) - Counter++; - - // check the number of clauses - if ( p->nClauses != Counter ) - { - printf( "Error: The actual number of clauses (%d) is different than declared (%d).\n", Counter, p->nClauses ); - Sto_ManFree( p ); - return NULL; - } - - free( pLits ); - fclose( pFile ); - return p; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/bsat/satStore.h b/src/sat/bsat/satStore.h deleted file mode 100644 index 346b59df..00000000 --- a/src/sat/bsat/satStore.h +++ /dev/null @@ -1,137 +0,0 @@ -/**CFile**************************************************************** - - FileName [pr.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Proof recording.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: pr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __PR_H__ -#define __PR_H__ - -/* - The trace of SAT solving contains the original clause of the problem - along with the learned clauses derived during SAT solving. - The first line of the resulting file contains 3 numbers instead of 2: - c -*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#endif - -#ifndef PRT -#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) -#endif - -#define STO_MAX(a,b) ((a) > (b) ? (a) : (b)) - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef unsigned lit; - -typedef struct Sto_Cls_t_ Sto_Cls_t; -struct Sto_Cls_t_ -{ - Sto_Cls_t * pNext; // the next clause - Sto_Cls_t * pNext0; // the next 0-watch - Sto_Cls_t * pNext1; // the next 0-watch - int Id; // the clause ID - unsigned fA : 1; // belongs to A - unsigned fRoot : 1; // original clause - unsigned fVisit : 1; // visited clause - unsigned nLits : 24; // the number of literals - lit pLits[0]; // literals of this clause -}; - -typedef struct Sto_Man_t_ Sto_Man_t; -struct Sto_Man_t_ -{ - // general data - int nVars; // the number of variables - int nRoots; // the number of root clauses - int nClauses; // the number of all clauses - int nClausesA; // the number of clauses of A - Sto_Cls_t * pHead; // the head clause - Sto_Cls_t * pTail; // the tail clause - Sto_Cls_t * pEmpty; // the empty clause - // memory management - int nChunkSize; // the number of bytes in a chunk - int nChunkUsed; // the number of bytes used in the last chunk - char * pChunkLast; // the last memory chunk -}; - -// variable/literal conversions (taken from MiniSat) -static inline lit toLit (int v) { return v + v; } -static inline lit toLitCond(int v, int c) { return v + v + (c != 0); } -static inline lit lit_neg (lit l) { return l ^ 1; } -static inline int lit_var (lit l) { return l >> 1; } -static inline int lit_sign (lit l) { return l & 1; } -static inline int lit_print(lit l) { return lit_sign(l)? -lit_var(l)-1 : lit_var(l)+1; } -static inline lit lit_read (int s) { return s > 0 ? toLit(s-1) : lit_neg(toLit(-s-1)); } -static inline int lit_check(lit l, int n) { return l >= 0 && lit_var(l) < n; } - -// iterators through the clauses -#define Sto_ManForEachClause( p, pCls ) for( pCls = p->pHead; pCls; pCls = pCls->pNext ) -#define Sto_ManForEachClauseRoot( p, pCls ) for( pCls = p->pHead; pCls && pCls->fRoot; pCls = pCls->pNext ) - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== satStore.c ==========================================================*/ -extern Sto_Man_t * Sto_ManAlloc(); -extern void Sto_ManFree( Sto_Man_t * p ); -extern int Sto_ManAddClause( Sto_Man_t * p, lit * pBeg, lit * pEnd ); -extern int Sto_ManMemoryReport( Sto_Man_t * p ); -extern void Sto_ManMarkRoots( Sto_Man_t * p ); -extern void Sto_ManMarkClausesA( Sto_Man_t * p ); -extern void Sto_ManDumpClauses( Sto_Man_t * p, char * pFileName ); -extern Sto_Man_t * Sto_ManLoadClauses( char * pFileName ); - -/*=== satInter.c ==========================================================*/ -typedef struct Int_Man_t_ Int_Man_t; -extern Int_Man_t * Int_ManAlloc( int nVarsAlloc ); -extern void Int_ManFree( Int_Man_t * p ); -extern int Int_ManInterpolate( Int_Man_t * p, Sto_Man_t * pCnf, int fVerbose, unsigned ** ppResult ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/sat/bsat/satTrace.c b/src/sat/bsat/satTrace.c deleted file mode 100644 index 111e8dfb..00000000 --- a/src/sat/bsat/satTrace.c +++ /dev/null @@ -1,109 +0,0 @@ -/**CFile**************************************************************** - - FileName [satTrace.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [SAT sat_solver.] - - Synopsis [Records the trace of SAT solving in the CNF form.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: satTrace.c,v 1.4 2005/09/16 22:55:03 casem Exp $] - -***********************************************************************/ - -#include -#include -#include "satSolver.h" - -/* - The trace of SAT solving contains the original clause of the problem - along with the learned clauses derived during SAT solving. - The first line of the resulting file contains 3 numbers instead of 2: - c -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Start the trace recording.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_SolverTraceStart( sat_solver * pSat, char * pName ) -{ - assert( pSat->pFile == NULL ); - pSat->pFile = fopen( pName, "w" ); - fprintf( pSat->pFile, " \n" ); - pSat->nClauses = 0; - pSat->nRoots = 0; -} - -/**Function************************************************************* - - Synopsis [Stops the trace recording.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_SolverTraceStop( sat_solver * pSat ) -{ - if ( pSat->pFile == NULL ) - return; - rewind( pSat->pFile ); - fprintf( pSat->pFile, "p %d %d %d", sat_solver_nvars(pSat), pSat->nClauses, pSat->nRoots ); - fclose( pSat->pFile ); - pSat->pFile = NULL; -} - - -/**Function************************************************************* - - Synopsis [Writes one clause into the trace file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_SolverTraceWrite( sat_solver * pSat, int * pBeg, int * pEnd, int fRoot ) -{ - if ( pSat->pFile == NULL ) - return; - pSat->nClauses++; - pSat->nRoots += fRoot; - for ( ; pBeg < pEnd ; pBeg++ ) - fprintf( pSat->pFile, " %d", lit_print(*pBeg) ); - fprintf( pSat->pFile, " 0\n" ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/bsat/satUtil.c b/src/sat/bsat/satUtil.c deleted file mode 100644 index 62f3c208..00000000 --- a/src/sat/bsat/satUtil.c +++ /dev/null @@ -1,234 +0,0 @@ -/**CFile**************************************************************** - - FileName [satUtil.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [C-language MiniSat solver.] - - Synopsis [Additional SAT solver procedures.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: satUtil.c,v 1.4 2005/09/16 22:55:03 casem Exp $] - -***********************************************************************/ - -#include -#include -#include "satSolver.h" -#include "extra.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct clause_t -{ - int size_learnt; - lit lits[0]; -}; - -static inline int clause_size( clause* c ) { return c->size_learnt >> 1; } -static inline lit* clause_begin( clause* c ) { return c->lits; } - -static void Sat_SolverClauseWriteDimacs( FILE * pFile, clause * pC, bool fIncrement ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Write the clauses in the solver into a file in DIMACS format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_SolverWriteDimacs( sat_solver * p, char * pFileName, lit* assumptionsBegin, lit* assumptionsEnd, int incrementVars ) -{ - FILE * pFile; - void ** pClauses; - int nClauses, i; - - // count the number of clauses - nClauses = p->clauses.size + p->learnts.size; - for ( i = 0; i < p->size; i++ ) - if ( p->levels[i] == 0 && p->assigns[i] != l_Undef ) - nClauses++; - - // start the file - pFile = fopen( pFileName, "wb" ); - if ( pFile == NULL ) - { - printf( "Sat_SolverWriteDimacs(): Cannot open the ouput file.\n" ); - return; - } - fprintf( pFile, "c CNF generated by ABC on %s\n", Extra_TimeStamp() ); - fprintf( pFile, "p cnf %d %d\n", p->size, nClauses ); - - // write the original clauses - nClauses = p->clauses.size; - pClauses = p->clauses.ptr; - for ( i = 0; i < nClauses; i++ ) - Sat_SolverClauseWriteDimacs( pFile, pClauses[i], incrementVars ); - - // write the learned clauses - nClauses = p->learnts.size; - pClauses = p->learnts.ptr; - for ( i = 0; i < nClauses; i++ ) - Sat_SolverClauseWriteDimacs( pFile, pClauses[i], incrementVars ); - - // write zero-level assertions - for ( i = 0; i < p->size; i++ ) - if ( p->levels[i] == 0 && p->assigns[i] != l_Undef ) - fprintf( pFile, "%s%d%s\n", - (p->assigns[i] == l_False)? "-": "", - i + (int)(incrementVars>0), - (incrementVars) ? " 0" : ""); - - // write the assumptions - if (assumptionsBegin) { - for (; assumptionsBegin != assumptionsEnd; assumptionsBegin++) { - fprintf( pFile, "%s%d%s\n", - lit_sign(*assumptionsBegin)? "-": "", - lit_var(*assumptionsBegin) + (int)(incrementVars>0), - (incrementVars) ? " 0" : ""); - } - } - - fprintf( pFile, "\n" ); - fclose( pFile ); -} - -/**Function************************************************************* - - Synopsis [Writes the given clause in a file in DIMACS format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_SolverClauseWriteDimacs( FILE * pFile, clause * pC, bool fIncrement ) -{ - lit * pLits = clause_begin(pC); - int nLits = clause_size(pC); - int i; - - for ( i = 0; i < nLits; i++ ) - fprintf( pFile, "%s%d ", (lit_sign(pLits[i])? "-": ""), lit_var(pLits[i]) + (int)(fIncrement>0) ); - if ( fIncrement ) - fprintf( pFile, "0" ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes the given clause in a file in DIMACS format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_SolverPrintStats( FILE * pFile, sat_solver * p ) -{ -// printf( "calls : %8d (%d)\n", (int)p->nCalls, (int)p->nCalls2 ); - printf( "starts : %8d\n", (int)p->stats.starts ); - printf( "conflicts : %8d\n", (int)p->stats.conflicts ); - printf( "decisions : %8d\n", (int)p->stats.decisions ); - printf( "propagations : %8d\n", (int)p->stats.propagations ); - printf( "inspects : %8d\n", (int)p->stats.inspects ); -// printf( "inspects2 : %8d\n", (int)p->stats.inspects2 ); -} - -/**Function************************************************************* - - Synopsis [Returns a counter-example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Sat_SolverGetModel( sat_solver * p, int * pVars, int nVars ) -{ - int * pModel; - int i; - pModel = ALLOC( int, nVars ); - for ( i = 0; i < nVars; i++ ) - { - assert( pVars[i] >= 0 && pVars[i] < p->size ); - pModel[i] = (int)(p->model.ptr[pVars[i]] == l_True); - } - return pModel; -} - -/**Function************************************************************* - - Synopsis [Duplicates all clauses, complements unit clause of the given var.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Sat_SolverDoubleClauses( sat_solver * p, int iVar ) -{ - clause * pClause; - lit Lit, * pLits; - int RetValue, nClauses, nVarsOld, nLitsOld, nLits, c, v; - // get the number of variables - nVarsOld = p->size; - nLitsOld = 2 * p->size; - // extend the solver to depend on two sets of variables - sat_solver_setnvars( p, 2 * p->size ); - // duplicate implications - for ( v = 0; v < nVarsOld; v++ ) - if ( p->assigns[v] != l_Undef ) - { - Lit = nLitsOld + toLitCond( v, p->assigns[v]==l_False ); - if ( v == iVar ) - Lit = lit_neg(Lit); - RetValue = sat_solver_addclause( p, &Lit, &Lit + 1 ); - assert( RetValue ); - } - // duplicate clauses - nClauses = vecp_size(&p->clauses); - for ( c = 0; c < nClauses; c++ ) - { - pClause = p->clauses.ptr[c]; - nLits = clause_size(pClause); - pLits = clause_begin(pClause); - for ( v = 0; v < nLits; v++ ) - pLits[v] += nLitsOld; - RetValue = sat_solver_addclause( p, pLits, pLits + nLits ); - assert( RetValue ); - for ( v = 0; v < nLits; v++ ) - pLits[v] -= nLitsOld; - } -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/bsat/satVec.h b/src/sat/bsat/satVec.h deleted file mode 100644 index d7fce5c0..00000000 --- a/src/sat/bsat/satVec.h +++ /dev/null @@ -1,83 +0,0 @@ -/************************************************************************************************** -MiniSat -- Copyright (c) 2005, Niklas Sorensson -http://www.cs.chalmers.se/Cs/Research/FormalMethods/MiniSat/ - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -associated documentation files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, publish, distribute, -sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or -substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT -NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT -OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**************************************************************************************************/ -// Modified to compile with MS Visual Studio 6.0 by Alan Mishchenko - -#ifndef satVec_h -#define satVec_h - -#include - -// vector of 32-bit intergers (added for 64-bit portability) -struct veci_t { - int size; - int cap; - int* ptr; -}; -typedef struct veci_t veci; - -static inline void veci_new (veci* v) { - v->size = 0; - v->cap = 4; - v->ptr = (int*)malloc(sizeof(int)*v->cap); -} - -static inline void veci_delete (veci* v) { free(v->ptr); } -static inline int* veci_begin (veci* v) { return v->ptr; } -static inline int veci_size (veci* v) { return v->size; } -static inline void veci_resize (veci* v, int k) { v->size = k; } // only safe to shrink !! -static inline void veci_push (veci* v, int e) -{ - if (v->size == v->cap) { - int newsize = v->cap * 2;//+1; - v->ptr = (int*)realloc(v->ptr,sizeof(int)*newsize); - v->cap = newsize; } - v->ptr[v->size++] = e; -} - - -// vector of 32- or 64-bit pointers -struct vecp_t { - int size; - int cap; - void** ptr; -}; -typedef struct vecp_t vecp; - -static inline void vecp_new (vecp* v) { - v->size = 0; - v->cap = 4; - v->ptr = (void**)malloc(sizeof(void*)*v->cap); -} - -static inline void vecp_delete (vecp* v) { free(v->ptr); } -static inline void** vecp_begin (vecp* v) { return v->ptr; } -static inline int vecp_size (vecp* v) { return v->size; } -static inline void vecp_resize (vecp* v, int k) { v->size = k; } // only safe to shrink !! -static inline void vecp_push (vecp* v, void* e) -{ - if (v->size == v->cap) { - int newsize = v->cap * 2;//+1; - v->ptr = (void**)realloc(v->ptr,sizeof(void*)*newsize); - v->cap = newsize; } - v->ptr[v->size++] = e; -} - - -#endif diff --git a/src/sat/csat/csat_apis.c b/src/sat/csat/csat_apis.c deleted file mode 100644 index 5872f5bc..00000000 --- a/src/sat/csat/csat_apis.c +++ /dev/null @@ -1,769 +0,0 @@ -/**CFile**************************************************************** - - FileName [csat_apis.h] - - PackageName [Interface to CSAT.] - - Synopsis [APIs, enums, and data structures expected from the use of CSAT.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 28, 2005] - - Revision [$Id: csat_apis.h,v 1.00 2005/08/28 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "abc.h" -#include "fraig.h" -#include "csat_apis.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -#define ABC_DEFAULT_CONF_LIMIT 0 // limit on conflicts -#define ABC_DEFAULT_IMP_LIMIT 0 // limit on implications - - -struct ABC_ManagerStruct_t -{ - // information about the problem - stmm_table * tName2Node; // the hash table mapping names to nodes - stmm_table * tNode2Name; // the hash table mapping nodes to names - Abc_Ntk_t * pNtk; // the starting ABC network - Abc_Ntk_t * pTarget; // the AIG representing the target - char * pDumpFileName; // the name of the file to dump the target network - Extra_MmFlex_t * pMmNames; // memory manager for signal names - // solving parameters - int mode; // 0 = resource-aware integration; 1 = brute-force SAT - Prove_Params_t Params; // integrated CEC parameters - // information about the target - int nog; // the numbers of gates in the target - Vec_Ptr_t * vNodes; // the gates in the target - Vec_Int_t * vValues; // the values of gate's outputs in the target - // solution - CSAT_Target_ResultT * pResult; // the result of solving the target -}; - -static CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars ); -static char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode ); - -// procedures to start and stop the ABC framework -extern void Abc_Start(); -extern void Abc_Stop(); - -// some external procedures -extern int Io_WriteBench( Abc_Ntk_t * pNtk, char * FileName ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates a new manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -ABC_Manager ABC_InitManager() -{ - ABC_Manager_t * mng; - Abc_Start(); - mng = ALLOC( ABC_Manager_t, 1 ); - memset( mng, 0, sizeof(ABC_Manager_t) ); - mng->pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); - mng->pNtk->pName = Extra_UtilStrsav("csat_network"); - mng->tName2Node = stmm_init_table(strcmp, stmm_strhash); - mng->tNode2Name = stmm_init_table(stmm_ptrcmp, stmm_ptrhash); - mng->pMmNames = Extra_MmFlexStart(); - mng->vNodes = Vec_PtrAlloc( 100 ); - mng->vValues = Vec_IntAlloc( 100 ); - mng->mode = 0; // set "resource-aware integration" as the default mode - // set default parameters for CEC - Prove_ParamsSetDefault( &mng->Params ); - // set infinite resource limit for the final mitering -// mng->Params.nMiteringLimitLast = ABC_INFINITY; - return mng; -} - -/**Function************************************************************* - - Synopsis [Deletes the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_ReleaseManager( ABC_Manager mng ) -{ - CSAT_Target_ResultT * p_res = ABC_Get_Target_Result( mng,0 ); - ABC_TargetResFree(p_res); - if ( mng->tNode2Name ) stmm_free_table( mng->tNode2Name ); - if ( mng->tName2Node ) stmm_free_table( mng->tName2Node ); - if ( mng->pMmNames ) Extra_MmFlexStop( mng->pMmNames ); - if ( mng->pNtk ) Abc_NtkDelete( mng->pNtk ); - if ( mng->pTarget ) Abc_NtkDelete( mng->pTarget ); - if ( mng->vNodes ) Vec_PtrFree( mng->vNodes ); - if ( mng->vValues ) Vec_IntFree( mng->vValues ); - FREE( mng->pDumpFileName ); - free( mng ); - Abc_Stop(); -} - -/**Function************************************************************* - - Synopsis [Sets solver options for learning.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_SetSolveOption( ABC_Manager mng, enum CSAT_OptionT option ) -{ -} - -/**Function************************************************************* - - Synopsis [Sets solving mode by brute-force SAT.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_UseOnlyCoreSatSolver( ABC_Manager mng ) -{ - mng->mode = 1; // switch to "brute-force SAT" as the solving option -} - -/**Function************************************************************* - - Synopsis [Adds a gate to the circuit.] - - Description [The meaning of the parameters are: - type: the type of the gate to be added - name: the name of the gate to be added, name should be unique in a circuit. - nofi: number of fanins of the gate to be added; - fanins: the name array of fanins of the gate to be added.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int ABC_AddGate( ABC_Manager mng, enum GateType type, char * name, int nofi, char ** fanins, int dc_attr ) -{ - Abc_Obj_t * pObj, * pFanin; - char * pSop, * pNewName; - int i; - - // save the name in the local memory manager - pNewName = Extra_MmFlexEntryFetch( mng->pMmNames, strlen(name) + 1 ); - strcpy( pNewName, name ); - name = pNewName; - - // consider different cases, create the node, and map the node into the name - switch( type ) - { - case CSAT_BPI: - case CSAT_BPPI: - if ( nofi != 0 ) - { printf( "ABC_AddGate: The PI/PPI gate \"%s\" has fanins.\n", name ); return 0; } - // create the PI - pObj = Abc_NtkCreatePi( mng->pNtk ); - stmm_insert( mng->tNode2Name, (char *)pObj, name ); - break; - case CSAT_CONST: - case CSAT_BAND: - case CSAT_BNAND: - case CSAT_BOR: - case CSAT_BNOR: - case CSAT_BXOR: - case CSAT_BXNOR: - case CSAT_BINV: - case CSAT_BBUF: - // create the node - pObj = Abc_NtkCreateNode( mng->pNtk ); - // create the fanins - for ( i = 0; i < nofi; i++ ) - { - if ( !stmm_lookup( mng->tName2Node, fanins[i], (char **)&pFanin ) ) - { printf( "ABC_AddGate: The fanin gate \"%s\" is not in the network.\n", fanins[i] ); return 0; } - Abc_ObjAddFanin( pObj, pFanin ); - } - // create the node function - switch( type ) - { - case CSAT_CONST: - if ( nofi != 0 ) - { printf( "ABC_AddGate: The constant gate \"%s\" has fanins.\n", name ); return 0; } - pSop = Abc_SopCreateConst1( mng->pNtk->pManFunc ); - break; - case CSAT_BAND: - if ( nofi < 1 ) - { printf( "ABC_AddGate: The AND gate \"%s\" no fanins.\n", name ); return 0; } - pSop = Abc_SopCreateAnd( mng->pNtk->pManFunc, nofi, NULL ); - break; - case CSAT_BNAND: - if ( nofi < 1 ) - { printf( "ABC_AddGate: The NAND gate \"%s\" no fanins.\n", name ); return 0; } - pSop = Abc_SopCreateNand( mng->pNtk->pManFunc, nofi ); - break; - case CSAT_BOR: - if ( nofi < 1 ) - { printf( "ABC_AddGate: The OR gate \"%s\" no fanins.\n", name ); return 0; } - pSop = Abc_SopCreateOr( mng->pNtk->pManFunc, nofi, NULL ); - break; - case CSAT_BNOR: - if ( nofi < 1 ) - { printf( "ABC_AddGate: The NOR gate \"%s\" no fanins.\n", name ); return 0; } - pSop = Abc_SopCreateNor( mng->pNtk->pManFunc, nofi ); - break; - case CSAT_BXOR: - if ( nofi < 1 ) - { printf( "ABC_AddGate: The XOR gate \"%s\" no fanins.\n", name ); return 0; } - if ( nofi > 2 ) - { printf( "ABC_AddGate: The XOR gate \"%s\" has more than two fanins.\n", name ); return 0; } - pSop = Abc_SopCreateXor( mng->pNtk->pManFunc, nofi ); - break; - case CSAT_BXNOR: - if ( nofi < 1 ) - { printf( "ABC_AddGate: The XNOR gate \"%s\" no fanins.\n", name ); return 0; } - if ( nofi > 2 ) - { printf( "ABC_AddGate: The XNOR gate \"%s\" has more than two fanins.\n", name ); return 0; } - pSop = Abc_SopCreateNxor( mng->pNtk->pManFunc, nofi ); - break; - case CSAT_BINV: - if ( nofi != 1 ) - { printf( "ABC_AddGate: The inverter gate \"%s\" does not have exactly one fanin.\n", name ); return 0; } - pSop = Abc_SopCreateInv( mng->pNtk->pManFunc ); - break; - case CSAT_BBUF: - if ( nofi != 1 ) - { printf( "ABC_AddGate: The buffer gate \"%s\" does not have exactly one fanin.\n", name ); return 0; } - pSop = Abc_SopCreateBuf( mng->pNtk->pManFunc ); - break; - default : - break; - } - Abc_ObjSetData( pObj, pSop ); - break; - case CSAT_BPPO: - case CSAT_BPO: - if ( nofi != 1 ) - { printf( "ABC_AddGate: The PO/PPO gate \"%s\" does not have exactly one fanin.\n", name ); return 0; } - // create the PO - pObj = Abc_NtkCreatePo( mng->pNtk ); - stmm_insert( mng->tNode2Name, (char *)pObj, name ); - // connect to the PO fanin - if ( !stmm_lookup( mng->tName2Node, fanins[0], (char **)&pFanin ) ) - { printf( "ABC_AddGate: The fanin gate \"%s\" is not in the network.\n", fanins[0] ); return 0; } - Abc_ObjAddFanin( pObj, pFanin ); - break; - default: - printf( "ABC_AddGate: Unknown gate type.\n" ); - break; - } - - // map the name into the node - if ( stmm_insert( mng->tName2Node, name, (char *)pObj ) ) - { printf( "ABC_AddGate: The same gate \"%s\" is added twice.\n", name ); return 0; } - return 1; -} - -/**Function************************************************************* - - Synopsis [This procedure also finalizes construction of the ABC network.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_Network_Finalize( ABC_Manager mng ) -{ - Abc_Ntk_t * pNtk = mng->pNtk; - Abc_Obj_t * pObj; - int i; - Abc_NtkForEachPi( pNtk, pObj, i ) - Abc_ObjAssignName( pObj, ABC_GetNodeName(mng, pObj), NULL ); - Abc_NtkForEachPo( pNtk, pObj, i ) - Abc_ObjAssignName( pObj, ABC_GetNodeName(mng, pObj), NULL ); - assert( Abc_NtkLatchNum(pNtk) == 0 ); -} - -/**Function************************************************************* - - Synopsis [Checks integraty of the manager.] - - Description [Checks if there are gates that are not used by any primary output. - If no such gates exist, return 1 else return 0.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int ABC_Check_Integrity( ABC_Manager mng ) -{ - Abc_Ntk_t * pNtk = mng->pNtk; - Abc_Obj_t * pObj; - int i; - - // check that there are no dangling nodes - Abc_NtkForEachNode( pNtk, pObj, i ) - { - if ( i == 0 ) - continue; - if ( Abc_ObjFanoutNum(pObj) == 0 ) - { -// printf( "ABC_Check_Integrity: The network has dangling nodes.\n" ); - return 0; - } - } - - // make sure everything is okay with the network structure - if ( !Abc_NtkDoCheck( pNtk ) ) - { - printf( "ABC_Check_Integrity: The internal network check has failed.\n" ); - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Sets time limit for solving a target.] - - Description [Runtime: time limit (in second).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_SetTimeLimit( ABC_Manager mng, int runtime ) -{ -// printf( "ABC_SetTimeLimit: The resource limit is not implemented (warning).\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_SetLearnLimit( ABC_Manager mng, int num ) -{ -// printf( "ABC_SetLearnLimit: The resource limit is not implemented (warning).\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_SetLearnBacktrackLimit( ABC_Manager mng, int num ) -{ -// printf( "ABC_SetLearnBacktrackLimit: The resource limit is not implemented (warning).\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_SetSolveBacktrackLimit( ABC_Manager mng, int num ) -{ - mng->Params.nMiteringLimitLast = num; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_SetSolveImplicationLimit( ABC_Manager mng, int num ) -{ -// printf( "ABC_SetSolveImplicationLimit: The resource limit is not implemented (warning).\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_SetTotalBacktrackLimit( ABC_Manager mng, uint64 num ) -{ - mng->Params.nTotalBacktrackLimit = num; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_SetTotalInspectLimit( ABC_Manager mng, uint64 num ) -{ - mng->Params.nTotalInspectLimit = num; -} -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -uint64 ABC_GetTotalBacktracksMade( ABC_Manager mng ) -{ - return mng->Params.nTotalBacktracksMade; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -uint64 ABC_GetTotalInspectsMade( ABC_Manager mng ) -{ - return mng->Params.nTotalInspectsMade; -} - -/**Function************************************************************* - - Synopsis [Sets the file name to dump the structurally hashed network used for solving.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_EnableDump( ABC_Manager mng, char * dump_file ) -{ - FREE( mng->pDumpFileName ); - mng->pDumpFileName = Extra_UtilStrsav( dump_file ); -} - -/**Function************************************************************* - - Synopsis [Adds a new target to the manager.] - - Description [The meaning of the parameters are: - nog: number of gates that are in the targets, - names: name array of gates, - values: value array of the corresponding gates given in "names" to be solved. - The relation of them is AND.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int ABC_AddTarget( ABC_Manager mng, int nog, char ** names, int * values ) -{ - Abc_Obj_t * pObj; - int i; - if ( nog < 1 ) - { printf( "ABC_AddTarget: The target has no gates.\n" ); return 0; } - // clear storage for the target - mng->nog = 0; - Vec_PtrClear( mng->vNodes ); - Vec_IntClear( mng->vValues ); - // save the target - for ( i = 0; i < nog; i++ ) - { - if ( !stmm_lookup( mng->tName2Node, names[i], (char **)&pObj ) ) - { printf( "ABC_AddTarget: The target gate \"%s\" is not in the network.\n", names[i] ); return 0; } - Vec_PtrPush( mng->vNodes, pObj ); - if ( values[i] < 0 || values[i] > 1 ) - { printf( "ABC_AddTarget: The value of gate \"%s\" is not 0 or 1.\n", names[i] ); return 0; } - Vec_IntPush( mng->vValues, values[i] ); - } - mng->nog = nog; - return 1; -} - -/**Function************************************************************* - - Synopsis [Initialize the solver internal data structure.] - - Description [Prepares the solver to work on one specific target - set by calling ABC_AddTarget before.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_SolveInit( ABC_Manager mng ) -{ - // check if the target is available - assert( mng->nog == Vec_PtrSize(mng->vNodes) ); - if ( mng->nog == 0 ) - { printf( "ABC_SolveInit: Target is not specified by ABC_AddTarget().\n" ); return; } - - // free the previous target network if present - if ( mng->pTarget ) Abc_NtkDelete( mng->pTarget ); - - // set the new target network -// mng->pTarget = Abc_NtkCreateTarget( mng->pNtk, mng->vNodes, mng->vValues ); - mng->pTarget = Abc_NtkStrash( mng->pNtk, 0, 1, 0 ); -} - -/**Function************************************************************* - - Synopsis [Currently not implemented.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_AnalyzeTargets( ABC_Manager mng ) -{ -} - -/**Function************************************************************* - - Synopsis [Solves the targets added by ABC_AddTarget().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -enum CSAT_StatusT ABC_Solve( ABC_Manager mng ) -{ - Prove_Params_t * pParams = &mng->Params; - int RetValue, i; - - // check if the target network is available - if ( mng->pTarget == NULL ) - { printf( "ABC_Solve: Target network is not derived by ABC_SolveInit().\n" ); return UNDETERMINED; } - - // try to prove the miter using a number of techniques - if ( mng->mode ) - RetValue = Abc_NtkMiterSat( mng->pTarget, (sint64)pParams->nMiteringLimitLast, (sint64)0, 0, NULL, NULL ); - else -// RetValue = Abc_NtkMiterProve( &mng->pTarget, pParams ); // old CEC engine - RetValue = Abc_NtkIvyProve( &mng->pTarget, pParams ); // new CEC engine - - // analyze the result - mng->pResult = ABC_TargetResAlloc( Abc_NtkCiNum(mng->pTarget) ); - if ( RetValue == -1 ) - mng->pResult->status = UNDETERMINED; - else if ( RetValue == 1 ) - mng->pResult->status = UNSATISFIABLE; - else if ( RetValue == 0 ) - { - mng->pResult->status = SATISFIABLE; - // create the array of PI names and values - for ( i = 0; i < mng->pResult->no_sig; i++ ) - { - mng->pResult->names[i] = Extra_UtilStrsav( ABC_GetNodeName(mng, Abc_NtkCi(mng->pNtk, i)) ); - mng->pResult->values[i] = mng->pTarget->pModel[i]; - } - FREE( mng->pTarget->pModel ); - } - else assert( 0 ); - - // delete the target - Abc_NtkDelete( mng->pTarget ); - mng->pTarget = NULL; - // return the status - return mng->pResult->status; -} - -/**Function************************************************************* - - Synopsis [Gets the solve status of a target.] - - Description [TargetID: the target id returned by ABC_AddTarget().] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -CSAT_Target_ResultT * ABC_Get_Target_Result( ABC_Manager mng, int TargetID ) -{ - return mng->pResult; -} - -/**Function************************************************************* - - Synopsis [Dumps the original network into the BENCH file.] - - Description [This procedure should be modified to dump the target.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_Dump_Bench_File( ABC_Manager mng ) -{ - Abc_Ntk_t * pNtkTemp, * pNtkAig; - char * pFileName; - - // derive the netlist - pNtkAig = Abc_NtkStrash( mng->pNtk, 0, 0, 0 ); - pNtkTemp = Abc_NtkToNetlistBench( pNtkAig ); - Abc_NtkDelete( pNtkAig ); - if ( pNtkTemp == NULL ) - { printf( "ABC_Dump_Bench_File: Dumping BENCH has failed.\n" ); return; } - pFileName = mng->pDumpFileName? mng->pDumpFileName: "abc_test.bench"; - Io_WriteBench( pNtkTemp, pFileName ); - Abc_NtkDelete( pNtkTemp ); -} - - - -/**Function************************************************************* - - Synopsis [Allocates the target result.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -CSAT_Target_ResultT * ABC_TargetResAlloc( int nVars ) -{ - CSAT_Target_ResultT * p; - p = ALLOC( CSAT_Target_ResultT, 1 ); - memset( p, 0, sizeof(CSAT_Target_ResultT) ); - p->no_sig = nVars; - p->names = ALLOC( char *, nVars ); - p->values = ALLOC( int, nVars ); - memset( p->names, 0, sizeof(char *) * nVars ); - memset( p->values, 0, sizeof(int) * nVars ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the target result.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void ABC_TargetResFree( CSAT_Target_ResultT * p ) -{ - if ( p == NULL ) - return; - if( p->names ) - { - int i = 0; - for ( i = 0; i < p->no_sig; i++ ) - { - FREE(p->names[i]); - } - } - FREE( p->names ); - FREE( p->values ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Dumps the target AIG into the BENCH file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * ABC_GetNodeName( ABC_Manager mng, Abc_Obj_t * pNode ) -{ - char * pName = NULL; - if ( !stmm_lookup( mng->tNode2Name, (char *)pNode, (char **)&pName ) ) - { - assert( 0 ); - } - return pName; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/csat/csat_apis.h b/src/sat/csat/csat_apis.h deleted file mode 100644 index b80eddbf..00000000 --- a/src/sat/csat/csat_apis.h +++ /dev/null @@ -1,222 +0,0 @@ -/**CFile**************************************************************** - - FileName [csat_apis.h] - - PackageName [Interface to CSAT.] - - Synopsis [APIs, enums, and data structures expected from the use of CSAT.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - August 28, 2005] - - Revision [$Id: csat_apis.h,v 1.5 2005/12/30 10:54:40 rmukherj Exp $] - -***********************************************************************/ - -#ifndef __ABC_APIS_H__ -#define __ABC_APIS_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - - -typedef struct ABC_ManagerStruct_t ABC_Manager_t; -typedef struct ABC_ManagerStruct_t * ABC_Manager; - - -// GateType defines the gate type that can be added to circuit by -// ABC_AddGate(); -#ifndef _ABC_GATE_TYPE_ -#define _ABC_GATE_TYPE_ -enum GateType -{ - CSAT_CONST = 0, // constant gate - CSAT_BPI, // boolean PI - CSAT_BPPI, // bit level PSEUDO PRIMARY INPUT - CSAT_BAND, // bit level AND - CSAT_BNAND, // bit level NAND - CSAT_BOR, // bit level OR - CSAT_BNOR, // bit level NOR - CSAT_BXOR, // bit level XOR - CSAT_BXNOR, // bit level XNOR - CSAT_BINV, // bit level INVERTER - CSAT_BBUF, // bit level BUFFER - CSAT_BMUX, // bit level MUX --not supported - CSAT_BDFF, // bit level D-type FF - CSAT_BSDFF, // bit level scan FF --not supported - CSAT_BTRIH, // bit level TRISTATE gate with active high control --not supported - CSAT_BTRIL, // bit level TRISTATE gate with active low control --not supported - CSAT_BBUS, // bit level BUS --not supported - CSAT_BPPO, // bit level PSEUDO PRIMARY OUTPUT - CSAT_BPO, // boolean PO - CSAT_BCNF, // boolean constraint - CSAT_BDC, // boolean don't care gate (2 input) -}; -#endif - - -//CSAT_StatusT defines the return value by ABC_Solve(); -#ifndef _ABC_STATUS_ -#define _ABC_STATUS_ -enum CSAT_StatusT -{ - UNDETERMINED = 0, - UNSATISFIABLE, - SATISFIABLE, - TIME_OUT, - FRAME_OUT, - NO_TARGET, - ABORTED, - SEQ_SATISFIABLE -}; -#endif - - -// to identify who called the CSAT solver -#ifndef _ABC_CALLER_ -#define _ABC_CALLER_ -enum CSAT_CallerT -{ - BLS = 0, - SATORI, - NONE -}; -#endif - - -// CSAT_OptionT defines the solver option about learning -// which is used by ABC_SetSolveOption(); -#ifndef _ABC_OPTION_ -#define _ABC_OPTION_ -enum CSAT_OptionT -{ - BASE_LINE = 0, - IMPLICT_LEARNING, //default - EXPLICT_LEARNING -}; -#endif - - -#ifndef _ABC_Target_Result -#define _ABC_Target_Result -typedef struct _CSAT_Target_ResultT CSAT_Target_ResultT; -struct _CSAT_Target_ResultT -{ - enum CSAT_StatusT status; // solve status of the target - int num_dec; // num of decisions to solve the target - int num_imp; // num of implications to solve the target - int num_cftg; // num of conflict gates learned - int num_cfts; // num of conflict signals in conflict gates - double time; // time(in second) used to solve the target - int no_sig; // if "status" is SATISFIABLE, "no_sig" is the number of - // primary inputs, if the "status" is TIME_OUT, "no_sig" is the - // number of constant signals found. - char** names; // if the "status" is SATISFIABLE, "names" is the name array of - // primary inputs, "values" is the value array of primary - // inputs that satisfy the target. - // if the "status" is TIME_OUT, "names" is the name array of - // constant signals found (signals at the root of decision - // tree), "values" is the value array of constant signals found. - int* values; -}; -#endif - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// create a new manager -extern ABC_Manager ABC_InitManager(void); - -// release a manager -extern void ABC_ReleaseManager(ABC_Manager mng); - -// set solver options for learning -extern void ABC_SetSolveOption(ABC_Manager mng, enum CSAT_OptionT option); - -// enable checking by brute-force SAT solver (MiniSat-1.14) -extern void ABC_UseOnlyCoreSatSolver(ABC_Manager mng); - - -// add a gate to the circuit -// the meaning of the parameters are: -// type: the type of the gate to be added -// name: the name of the gate to be added, name should be unique in a circuit. -// nofi: number of fanins of the gate to be added; -// fanins: the name array of fanins of the gate to be added -extern int ABC_AddGate(ABC_Manager mng, - enum GateType type, - char* name, - int nofi, - char** fanins, - int dc_attr); - -// check if there are gates that are not used by any primary ouput. -// if no such gates exist, return 1 else return 0; -extern int ABC_Check_Integrity(ABC_Manager mng); - -// THIS PROCEDURE SHOULD BE CALLED AFTER THE NETWORK IS CONSTRUCTED!!! -extern void ABC_Network_Finalize( ABC_Manager mng ); - -// set time limit for solving a target. -// runtime: time limit (in second). -extern void ABC_SetTimeLimit(ABC_Manager mng, int runtime); -extern void ABC_SetLearnLimit(ABC_Manager mng, int num); -extern void ABC_SetSolveBacktrackLimit(ABC_Manager mng, int num); -extern void ABC_SetLearnBacktrackLimit(ABC_Manager mng, int num); -extern void ABC_EnableDump(ABC_Manager mng, char* dump_file); - -extern void ABC_SetTotalBacktrackLimit( ABC_Manager mng, uint64 num ); -extern void ABC_SetTotalInspectLimit( ABC_Manager mng, uint64 num ); -extern uint64 ABC_GetTotalBacktracksMade( ABC_Manager mng ); -extern uint64 ABC_GetTotalInspectsMade( ABC_Manager mng ); - -// the meaning of the parameters are: -// nog: number of gates that are in the targets -// names: name array of gates -// values: value array of the corresponding gates given in "names" to be -// solved. the relation of them is AND. -extern int ABC_AddTarget(ABC_Manager mng, int nog, char**names, int* values); - -// initialize the solver internal data structure. -extern void ABC_SolveInit(ABC_Manager mng); -extern void ABC_AnalyzeTargets(ABC_Manager mng); - -// solve the targets added by ABC_AddTarget() -extern enum CSAT_StatusT ABC_Solve(ABC_Manager mng); - -// get the solve status of a target -// TargetID: the target id returned by ABC_AddTarget(). -extern CSAT_Target_ResultT * ABC_Get_Target_Result(ABC_Manager mng, int TargetID); -extern void ABC_Dump_Bench_File(ABC_Manager mng); - -// ADDED PROCEDURES: -extern void ABC_TargetResFree( CSAT_Target_ResultT * p ); - -extern void CSAT_SetCaller(ABC_Manager mng, enum CSAT_CallerT caller); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/sat/csat/module.make b/src/sat/csat/module.make deleted file mode 100644 index 5b71a03c..00000000 --- a/src/sat/csat/module.make +++ /dev/null @@ -1 +0,0 @@ -SRC += src/sat/csat/csat_apis.c diff --git a/src/sat/fraig/fraig.h b/src/sat/fraig/fraig.h deleted file mode 100644 index 1dad21e2..00000000 --- a/src/sat/fraig/fraig.h +++ /dev/null @@ -1,267 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraig.h] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [External declarations of the FRAIG package.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraig.h,v 1.18 2005/07/08 01:01:30 alanmi Exp $] - -***********************************************************************/ - -#ifndef __FRAIG_H__ -#define __FRAIG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -#ifndef SINT64 -#define SINT64 - -#ifdef _WIN32 -typedef signed __int64 sint64; // compatible with MS VS 6.0 -#else -typedef long long sint64; -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Fraig_ManStruct_t_ Fraig_Man_t; -typedef struct Fraig_NodeStruct_t_ Fraig_Node_t; -typedef struct Fraig_NodeVecStruct_t_ Fraig_NodeVec_t; -typedef struct Fraig_HashTableStruct_t_ Fraig_HashTable_t; -typedef struct Fraig_ParamsStruct_t_ Fraig_Params_t; -typedef struct Fraig_PatternsStruct_t_ Fraig_Patterns_t; -typedef struct Prove_ParamsStruct_t_ Prove_Params_t; - -struct Fraig_ParamsStruct_t_ -{ - int nPatsRand; // the number of words of random simulation info - int nPatsDyna; // the number of words of dynamic simulation info - int nBTLimit; // the max number of backtracks to perform - int nSeconds; // the timeout for the final proof - int fFuncRed; // performs only one level hashing - int fFeedBack; // enables solver feedback - int fDist1Pats; // enables distance-1 patterns - int fDoSparse; // performs equiv tests for sparse functions - int fChoicing; // enables recording structural choices - int fTryProve; // tries to solve the final miter - int fVerbose; // the verbosiness flag - int fVerboseP; // the verbosiness flag (for proof reporting) - int fInternal; // is set to 1 for internal fraig calls - int nConfLimit; // the limit on the number of conflicts - sint64 nInspLimit; // the limit on the number of inspections -}; - -struct Prove_ParamsStruct_t_ -{ - // general parameters - int fUseFraiging; // enables fraiging - int fUseRewriting; // enables rewriting - int fUseBdds; // enables BDD construction when other methods fail - int fVerbose; // prints verbose stats - // iterations - int nItersMax; // the number of iterations - // mitering - int nMiteringLimitStart; // starting mitering limit - float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration - // rewriting - int nRewritingLimitStart; // the number of rewriting iterations - float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration - // fraiging - int nFraigingLimitStart; // starting backtrack(conflict) limit - float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration - // last-gasp BDD construction - int nBddSizeLimit; // the number of BDD nodes when construction is aborted - int fBddReorder; // enables dynamic BDD variable reordering - // last-gasp mitering - int nMiteringLimitLast; // final mitering limit - // global SAT solver limits - sint64 nTotalBacktrackLimit; // global limit on the number of backtracks - sint64 nTotalInspectLimit; // global limit on the number of clause inspects - // global resources applied - sint64 nTotalBacktracksMade; // the total number of backtracks made - sint64 nTotalInspectsMade; // the total number of inspects made -}; - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// macros working with complemented attributes of the nodes -#define Fraig_IsComplement(p) (((int)((unsigned long) (p) & 01))) -#define Fraig_Regular(p) ((Fraig_Node_t *)((unsigned long)(p) & ~01)) -#define Fraig_Not(p) ((Fraig_Node_t *)((unsigned long)(p) ^ 01)) -#define Fraig_NotCond(p,c) ((Fraig_Node_t *)((unsigned long)(p) ^ (c))) - -// these are currently not used -#define Fraig_Ref(p) -#define Fraig_Deref(p) -#define Fraig_RecursiveDeref(p,c) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== fraigApi.c =============================================================*/ -extern Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p ); -extern Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p ); -extern Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p ); -extern Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p ); -extern Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p ); -extern Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p ); -extern int Fraig_ManReadInputNum ( Fraig_Man_t * p ); -extern int Fraig_ManReadOutputNum( Fraig_Man_t * p ); -extern int Fraig_ManReadNodeNum( Fraig_Man_t * p ); -extern Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p ); -extern Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i ); -extern Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i ); -extern char ** Fraig_ManReadInputNames( Fraig_Man_t * p ); -extern char ** Fraig_ManReadOutputNames( Fraig_Man_t * p ); -extern char * Fraig_ManReadVarsInt( Fraig_Man_t * p ); -extern char * Fraig_ManReadSat( Fraig_Man_t * p ); -extern int Fraig_ManReadFuncRed( Fraig_Man_t * p ); -extern int Fraig_ManReadFeedBack( Fraig_Man_t * p ); -extern int Fraig_ManReadDoSparse( Fraig_Man_t * p ); -extern int Fraig_ManReadChoicing( Fraig_Man_t * p ); -extern int Fraig_ManReadVerbose( Fraig_Man_t * p ); -extern int * Fraig_ManReadModel( Fraig_Man_t * p ); -extern int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ); -extern int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ); -extern int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ); -extern int Fraig_ManReadSatFails( Fraig_Man_t * p ); -extern int Fraig_ManReadConflicts( Fraig_Man_t * p ); -extern int Fraig_ManReadInspects( Fraig_Man_t * p ); - -extern void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed ); -extern void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack ); -extern void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse ); -extern void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ); -extern void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve ); -extern void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose ); -extern void Fraig_ManSetTimeToGraph( Fraig_Man_t * p, int Time ); -extern void Fraig_ManSetTimeToNet( Fraig_Man_t * p, int Time ); -extern void Fraig_ManSetTimeTotal( Fraig_Man_t * p, int Time ); -extern void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ); -extern void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames ); -extern void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode ); - -extern Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p ); -extern Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p ); -extern int Fraig_NodeReadNum( Fraig_Node_t * p ); -extern Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p ); -extern Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p ); -extern Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p ); -extern Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p ); -extern int Fraig_NodeReadNumRefs( Fraig_Node_t * p ); -extern int Fraig_NodeReadNumFanouts( Fraig_Node_t * p ); -extern int Fraig_NodeReadSimInv( Fraig_Node_t * p ); -extern int Fraig_NodeReadNumOnes( Fraig_Node_t * p ); -extern unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p ); -extern unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p ); - -extern void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData ); -extern void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData ); - -extern int Fraig_NodeIsConst( Fraig_Node_t * p ); -extern int Fraig_NodeIsVar( Fraig_Node_t * p ); -extern int Fraig_NodeIsAnd( Fraig_Node_t * p ); -extern int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ); - -extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -extern Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -extern Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -extern Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -extern Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_Node_t * pNodeT, Fraig_Node_t * pNodeE ); -extern void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew ); - -/*=== fraigMan.c =============================================================*/ -extern void Prove_ParamsSetDefault( Prove_Params_t * pParams ); -extern void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ); -extern void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams ); -extern Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ); -extern void Fraig_ManFree( Fraig_Man_t * pMan ); -extern void Fraig_ManPrintStats( Fraig_Man_t * p ); -extern Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p ); -extern int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ); -extern void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes ); - -/*=== fraigDfs.c =============================================================*/ -extern Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv ); -extern Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv ); -extern Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv ); -extern Fraig_NodeVec_t * Fraig_DfsReverse( Fraig_Man_t * pMan ); -extern int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv ); -extern int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -extern int Fraig_CountLevels( Fraig_Man_t * pMan ); - -/*=== fraigSat.c =============================================================*/ -extern int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit ); -extern int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit ); -extern void Fraig_ManProveMiter( Fraig_Man_t * p ); -extern int Fraig_ManCheckMiter( Fraig_Man_t * p ); -extern int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ); - -/*=== fraigVec.c ===============================================================*/ -extern Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap ); -extern void Fraig_NodeVecFree( Fraig_NodeVec_t * p ); -extern Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * p ); -extern Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p ); -extern int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p ); -extern void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin ); -extern void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew ); -extern void Fraig_NodeVecClear( Fraig_NodeVec_t * p ); -extern void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); -extern int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); -extern void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); -extern int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); -extern void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); -extern int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ); -extern Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p ); -extern void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ); -extern void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry ); -extern Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i ); -extern void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing ); -extern void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p ); - -/*=== fraigUtil.c ===============================================================*/ -extern void Fraig_ManMarkRealFanouts( Fraig_Man_t * p ); -extern int Fraig_ManCheckConsistency( Fraig_Man_t * p ); -extern int Fraig_GetMaxLevel( Fraig_Man_t * pMan ); -extern void Fraig_ManReportChoices( Fraig_Man_t * pMan ); -extern void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum ); -extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ); - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/sat/fraig/fraigApi.c b/src/sat/fraig/fraigApi.c deleted file mode 100644 index 79a7c224..00000000 --- a/src/sat/fraig/fraigApi.c +++ /dev/null @@ -1,297 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigApi.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Access APIs for the FRAIG manager and node.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigApi.c,v 1.2 2005/07/08 01:01:30 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Access functions to read the data members of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_ManReadVecInputs( Fraig_Man_t * p ) { return p->vInputs; } -Fraig_NodeVec_t * Fraig_ManReadVecOutputs( Fraig_Man_t * p ) { return p->vOutputs; } -Fraig_NodeVec_t * Fraig_ManReadVecNodes( Fraig_Man_t * p ) { return p->vNodes; } -Fraig_Node_t ** Fraig_ManReadInputs ( Fraig_Man_t * p ) { return p->vInputs->pArray; } -Fraig_Node_t ** Fraig_ManReadOutputs( Fraig_Man_t * p ) { return p->vOutputs->pArray; } -Fraig_Node_t ** Fraig_ManReadNodes( Fraig_Man_t * p ) { return p->vNodes->pArray; } -int Fraig_ManReadInputNum ( Fraig_Man_t * p ) { return p->vInputs->nSize; } -int Fraig_ManReadOutputNum( Fraig_Man_t * p ) { return p->vOutputs->nSize; } -int Fraig_ManReadNodeNum( Fraig_Man_t * p ) { return p->vNodes->nSize; } -Fraig_Node_t * Fraig_ManReadConst1 ( Fraig_Man_t * p ) { return p->pConst1; } -Fraig_Node_t * Fraig_ManReadIthNode( Fraig_Man_t * p, int i ) { assert ( i < p->vNodes->nSize ); return p->vNodes->pArray[i]; } -char ** Fraig_ManReadInputNames( Fraig_Man_t * p ) { return p->ppInputNames; } -char ** Fraig_ManReadOutputNames( Fraig_Man_t * p ) { return p->ppOutputNames; } -char * Fraig_ManReadVarsInt( Fraig_Man_t * p ) { return (char *)p->vVarsInt; } -char * Fraig_ManReadSat( Fraig_Man_t * p ) { return (char *)p->pSat; } -int Fraig_ManReadFuncRed( Fraig_Man_t * p ) { return p->fFuncRed; } -int Fraig_ManReadFeedBack( Fraig_Man_t * p ) { return p->fFeedBack; } -int Fraig_ManReadDoSparse( Fraig_Man_t * p ) { return p->fDoSparse; } -int Fraig_ManReadChoicing( Fraig_Man_t * p ) { return p->fChoicing; } -int Fraig_ManReadVerbose( Fraig_Man_t * p ) { return p->fVerbose; } -int * Fraig_ManReadModel( Fraig_Man_t * p ) { return p->pModel; } -// returns the number of patterns used for random simulation (this number is fixed for the FRAIG run) -int Fraig_ManReadPatternNumRandom( Fraig_Man_t * p ) { return p->nWordsRand * 32; } -// returns the number of dynamic patterns accumulated at runtime (include SAT solver counter-examples and distance-1 patterns derived from them) -int Fraig_ManReadPatternNumDynamic( Fraig_Man_t * p ) { return p->iWordStart * 32; } -// returns the number of dynamic patterns proved useful to distinquish some FRAIG nodes (this number is more than 0 after the first garbage collection of patterns) -int Fraig_ManReadPatternNumDynamicFiltered( Fraig_Man_t * p ) { return p->iPatsPerm; } -// returns the number of times FRAIG package timed out -int Fraig_ManReadSatFails( Fraig_Man_t * p ) { return p->nSatFailsReal; } -// returns the number of conflicts in the SAT solver -int Fraig_ManReadConflicts( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadBackTracks(p->pSat) : 0; } -// returns the number of inspections in the SAT solver -int Fraig_ManReadInspects( Fraig_Man_t * p ) { return p->pSat? Msat_SolverReadInspects(p->pSat) : 0; } - -/**Function************************************************************* - - Synopsis [Access functions to set the data members of the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManSetFuncRed( Fraig_Man_t * p, int fFuncRed ) { p->fFuncRed = fFuncRed; } -void Fraig_ManSetFeedBack( Fraig_Man_t * p, int fFeedBack ) { p->fFeedBack = fFeedBack; } -void Fraig_ManSetDoSparse( Fraig_Man_t * p, int fDoSparse ) { p->fDoSparse = fDoSparse; } -void Fraig_ManSetChoicing( Fraig_Man_t * p, int fChoicing ) { p->fChoicing = fChoicing; } -void Fraig_ManSetTryProve( Fraig_Man_t * p, int fTryProve ) { p->fTryProve = fTryProve; } -void Fraig_ManSetVerbose( Fraig_Man_t * p, int fVerbose ) { p->fVerbose = fVerbose; } -void Fraig_ManSetTimeToGraph( Fraig_Man_t * p, int Time ) { p->timeToAig = Time; } -void Fraig_ManSetTimeToNet( Fraig_Man_t * p, int Time ) { p->timeToNet = Time; } -void Fraig_ManSetTimeTotal( Fraig_Man_t * p, int Time ) { p->timeTotal = Time; } -void Fraig_ManSetOutputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppOutputNames = ppNames; } -void Fraig_ManSetInputNames( Fraig_Man_t * p, char ** ppNames ) { p->ppInputNames = ppNames; } - -/**Function************************************************************* - - Synopsis [Access functions to read the data members of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeReadData0( Fraig_Node_t * p ) { return p->pData0; } -Fraig_Node_t * Fraig_NodeReadData1( Fraig_Node_t * p ) { return p->pData1; } -int Fraig_NodeReadNum( Fraig_Node_t * p ) { return p->Num; } -Fraig_Node_t * Fraig_NodeReadOne( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p1; } -Fraig_Node_t * Fraig_NodeReadTwo( Fraig_Node_t * p ) { assert (!Fraig_IsComplement(p)); return p->p2; } -Fraig_Node_t * Fraig_NodeReadNextE( Fraig_Node_t * p ) { return p->pNextE; } -Fraig_Node_t * Fraig_NodeReadRepr( Fraig_Node_t * p ) { return p->pRepr; } -int Fraig_NodeReadNumRefs( Fraig_Node_t * p ) { return p->nRefs; } -int Fraig_NodeReadNumFanouts( Fraig_Node_t * p ) { return p->nFanouts; } -int Fraig_NodeReadSimInv( Fraig_Node_t * p ) { return p->fInv; } -int Fraig_NodeReadNumOnes( Fraig_Node_t * p ) { return p->nOnes; } -// returns the pointer to the random simulation patterns (their number is returned by Fraig_ManReadPatternNumRandom) -// memory pointed to by this and the following procedure is maintained by the FRAIG package and exists as long as the package runs -unsigned * Fraig_NodeReadPatternsRandom( Fraig_Node_t * p ) { return p->puSimR; } -// returns the pointer to the dynamic simulation patterns (their number is returned by Fraig_ManReadPatternNumDynamic or Fraig_ManReadPatternNumDynamicFiltered) -// if the number of patterns is not evenly divisible by 32, the patterns beyond the given number contain garbage -unsigned * Fraig_NodeReadPatternsDynamic( Fraig_Node_t * p ) { return p->puSimD; } - -/**Function************************************************************* - - Synopsis [Access functions to set the data members of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeSetData0( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData0 = pData; } -void Fraig_NodeSetData1( Fraig_Node_t * p, Fraig_Node_t * pData ) { p->pData1 = pData; } - -/**Function************************************************************* - - Synopsis [Checks the type of the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsConst( Fraig_Node_t * p ) { return (Fraig_Regular(p))->Num == 0; } -int Fraig_NodeIsVar( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi >= 0; } -int Fraig_NodeIsAnd( Fraig_Node_t * p ) { return (Fraig_Regular(p))->NumPi < 0 && (Fraig_Regular(p))->Num > 0; } -int Fraig_NodeComparePhase( Fraig_Node_t * p1, Fraig_Node_t * p2 ) { assert( !Fraig_IsComplement(p1) ); assert( !Fraig_IsComplement(p2) ); return p1->fInv ^ p2->fInv; } - -/**Function************************************************************* - - Synopsis [Returns a new primary input node.] - - Description [If the node with this number does not exist, - create a new PI node with this number.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_ManReadIthVar( Fraig_Man_t * p, int i ) -{ - int k; - if ( i < 0 ) - { - printf( "Requesting a PI with a negative number\n" ); - return NULL; - } - // create the PIs to fill in the interval - if ( i >= p->vInputs->nSize ) - for ( k = p->vInputs->nSize; k <= i; k++ ) - Fraig_NodeCreatePi( p ); - return p->vInputs->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [Creates a new PO node.] - - Description [This procedure may take a complemented node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManSetPo( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - // internal node may be a PO two times - Fraig_Regular(pNode)->fNodePo = 1; - Fraig_NodeVecPush( p->vOutputs, pNode ); -} - -/**Function************************************************************* - - Synopsis [Perfoms the AND operation with functional hashing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeAnd( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) -{ - return Fraig_NodeAndCanon( p, p1, p2 ); -} - -/**Function************************************************************* - - Synopsis [Perfoms the OR operation with functional hashing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeOr( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) -{ - return Fraig_Not( Fraig_NodeAndCanon( p, Fraig_Not(p1), Fraig_Not(p2) ) ); -} - -/**Function************************************************************* - - Synopsis [Perfoms the EXOR operation with functional hashing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeExor( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) -{ - return Fraig_NodeMux( p, p1, Fraig_Not(p2), p2 ); -} - -/**Function************************************************************* - - Synopsis [Perfoms the MUX operation with functional hashing.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeMux( Fraig_Man_t * p, Fraig_Node_t * pC, Fraig_Node_t * pT, Fraig_Node_t * pE ) -{ - Fraig_Node_t * pAnd1, * pAnd2, * pRes; - pAnd1 = Fraig_NodeAndCanon( p, pC, pT ); Fraig_Ref( pAnd1 ); - pAnd2 = Fraig_NodeAndCanon( p, Fraig_Not(pC), pE ); Fraig_Ref( pAnd2 ); - pRes = Fraig_NodeOr( p, pAnd1, pAnd2 ); - Fraig_RecursiveDeref( p, pAnd1 ); - Fraig_RecursiveDeref( p, pAnd2 ); - Fraig_Deref( pRes ); - return pRes; -} - - -/**Function************************************************************* - - Synopsis [Sets the node to be equivalent to the given one.] - - Description [This procedure is a work-around for the equivalence check. - Does not verify the equivalence. Use at the user's risk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeSetChoice( Fraig_Man_t * pMan, Fraig_Node_t * pNodeOld, Fraig_Node_t * pNodeNew ) -{ -// assert( pMan->fChoicing ); - pNodeNew->pNextE = pNodeOld->pNextE; - pNodeOld->pNextE = pNodeNew; - pNodeNew->pRepr = pNodeOld; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/fraig/fraigCanon.c b/src/sat/fraig/fraigCanon.c deleted file mode 100644 index 89bc924f..00000000 --- a/src/sat/fraig/fraigCanon.c +++ /dev/null @@ -1,218 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigCanon.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [AND-node creation and elementary AND-operation.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigCanon.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#include -#include "fraigInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [The internal AND operation for the two FRAIG nodes.] - - Description [This procedure is the core of the FRAIG package, because - it performs the two-step canonicization of FRAIG nodes. The first step - involves the lookup in the structural hash table (which hashes two ANDs - into a node that has them as fanins, if such a node exists). If the node - is not found in the structural hash table, an attempt is made to find a - functionally equivalent node in another hash table (which hashes the - simulation info into the nodes, which has this simulation info). Some - tricks used on the way are described in the comments to the code and - in the paper "FRAIGs: Functionally reduced AND-INV graphs".] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 ) -{ - Fraig_Node_t * pNodeNew, * pNodeOld, * pNodeRepr; - int fUseSatCheck; -// int RetValue; - - // check for trivial cases - if ( p1 == p2 ) - return p1; - if ( p1 == Fraig_Not(p2) ) - return Fraig_Not(pMan->pConst1); - if ( Fraig_NodeIsConst(p1) ) - { - if ( p1 == pMan->pConst1 ) - return p2; - return Fraig_Not(pMan->pConst1); - } - if ( Fraig_NodeIsConst(p2) ) - { - if ( p2 == pMan->pConst1 ) - return p1; - return Fraig_Not(pMan->pConst1); - } -/* - // check for less trivial cases - if ( Fraig_IsComplement(p1) ) - { - if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p1), p2 ) ) - { - if ( RetValue == -1 ) - pMan->nImplies0++; - else - pMan->nImplies1++; - - if ( RetValue == -1 ) - return p2; - } - } - else - { - if ( RetValue = Fraig_NodeIsInSupergate( p1, p2 ) ) - { - if ( RetValue == 1 ) - pMan->nSimplifies1++; - else - pMan->nSimplifies0++; - - if ( RetValue == 1 ) - return p1; - return Fraig_Not(pMan->pConst1); - } - } - - if ( Fraig_IsComplement(p2) ) - { - if ( RetValue = Fraig_NodeIsInSupergate( Fraig_Regular(p2), p1 ) ) - { - if ( RetValue == -1 ) - pMan->nImplies0++; - else - pMan->nImplies1++; - - if ( RetValue == -1 ) - return p1; - } - } - else - { - if ( RetValue = Fraig_NodeIsInSupergate( p2, p1 ) ) - { - if ( RetValue == 1 ) - pMan->nSimplifies1++; - else - pMan->nSimplifies0++; - - if ( RetValue == 1 ) - return p2; - return Fraig_Not(pMan->pConst1); - } - } -*/ - // perform level-one structural hashing - if ( Fraig_HashTableLookupS( pMan, p1, p2, &pNodeNew ) ) // the node with these children is found - { - // if the existent node is part of the cone of unused logic - // (that is logic feeding the node which is equivalent to the given node) - // return the canonical representative of this node - // determine the phase of the given node, with respect to its canonical form - pNodeRepr = Fraig_Regular(pNodeNew)->pRepr; - if ( pMan->fFuncRed && pNodeRepr ) - return Fraig_NotCond( pNodeRepr, Fraig_IsComplement(pNodeNew) ^ Fraig_NodeComparePhase(Fraig_Regular(pNodeNew), pNodeRepr) ); - // otherwise, the node is itself a canonical representative, return it - return pNodeNew; - } - // the same node is not found, but the new one is created - - // if one level hashing is requested (without functionality hashing), return - if ( !pMan->fFuncRed ) - return pNodeNew; - - // check if the new node is unique using the simulation info - if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 ) - { - pMan->nSatZeros++; - if ( !pMan->fDoSparse ) // if we do not do sparse functions, skip - return pNodeNew; - // check the sparse function simulation hash table - pNodeOld = Fraig_HashTableLookupF0( pMan, pNodeNew ); - if ( pNodeOld == NULL ) // the node is unique (it is added to the table) - return pNodeNew; - } - else - { - // check the simulation hash table - pNodeOld = Fraig_HashTableLookupF( pMan, pNodeNew ); - if ( pNodeOld == NULL ) // the node is unique - return pNodeNew; - } - assert( pNodeOld->pRepr == 0 ); - // there is another node which looks the same according to simulation - - // use SAT to resolve the ambiguity - fUseSatCheck = (pMan->nInspLimit == 0 || Fraig_ManReadInspects(pMan) < pMan->nInspLimit); - if ( fUseSatCheck && Fraig_NodeIsEquivalent( pMan, pNodeOld, pNodeNew, pMan->nBTLimit, 1000000 ) ) - { - // set the node to be equivalent with this node - // to prevent loops, only set if the old node is not in the TFI of the new node - // the loop may happen in the following case: suppose - // NodeC = AND(NodeA, NodeB) and at the same time NodeA => NodeB - // in this case, NodeA and NodeC are functionally equivalent - // however, NodeA is a fanin of node NodeC (this leads to the loop) - // add the node to the list of equivalent nodes or dereference it - if ( pMan->fChoicing && !Fraig_CheckTfi( pMan, pNodeOld, pNodeNew ) ) - { - // if the old node is not in the TFI of the new node and choicing - // is enabled, add the new node to the list of equivalent ones - pNodeNew->pNextE = pNodeOld->pNextE; - pNodeOld->pNextE = pNodeNew; - } - // set the canonical representative of this node - pNodeNew->pRepr = pNodeOld; - // return the equivalent node - return Fraig_NotCond( pNodeOld, Fraig_NodeComparePhase(pNodeOld, pNodeNew) ); - } - - // now we add another member to this simulation class - if ( pNodeNew->nOnes == 0 || pNodeNew->nOnes == (unsigned)pMan->nWordsRand * 32 ) - { - Fraig_Node_t * pNodeTemp; - assert( pMan->fDoSparse ); - pNodeTemp = Fraig_HashTableLookupF0( pMan, pNodeNew ); -// assert( pNodeTemp == NULL ); -// Fraig_HashTableInsertF0( pMan, pNodeNew ); - } - else - { - pNodeNew->pNextD = pNodeOld->pNextD; - pNodeOld->pNextD = pNodeNew; - } - // return the new node - assert( pNodeNew->pRepr == 0 ); - return pNodeNew; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/fraig/fraigChoice.c b/src/sat/fraig/fraigChoice.c deleted file mode 100644 index 896e5d2d..00000000 --- a/src/sat/fraig/fraigChoice.c +++ /dev/null @@ -1,241 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigTrans.c] - - PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] - - Synopsis [Adds the additive and distributive choices to the AIG.] - - Author [MVSIS Group] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - February 1, 2003.] - - Revision [$Id: fraigTrans.c,v 1.1 2005/02/28 05:34:34 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Adds choice nodes based on associativity.] - - Description [Make nLimit big AND gates and add all decompositions - to the Fraig.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManAddChoices( Fraig_Man_t * pMan, int fVerbose, int nLimit ) -{ -// ProgressBar * pProgress; - char Buffer[100]; - int clkTotal = clock(); - int i, nNodesBefore, nNodesAfter, nInputs, nMaxNodes; - int /*nMaxLevel,*/ nDistributive; - Fraig_Node_t *pNode, *pRepr; - Fraig_Node_t *pX, *pA, *pB, *pC, /* *pD,*/ *pN, /* *pQ, *pR,*/ *pT; - int fShortCut = 0; - - nDistributive = 0; - -// Fraig_ManSetApprox( pMan, 1 ); - - // NO functional reduction - if (fShortCut) Fraig_ManSetFuncRed( pMan, 0 ); - - // First we mark critical functions i.e. compute those - // nodes which lie on the critical path. Note that this - // doesn't update the required times on any choice nodes - // which are not the representatives -/* - nMaxLevel = Fraig_GetMaxLevel( pMan ); - for ( i = 0; i < pMan->nOutputs; i++ ) - { - Fraig_SetNodeRequired( pMan, pMan->pOutputs[i], nMaxLevel ); - } -*/ - nNodesBefore = Fraig_ManReadNodeNum( pMan ); - nInputs = Fraig_ManReadInputNum( pMan ); - nMaxNodes = nInputs + nLimit * ( nNodesBefore - nInputs ); - - printf ("Limit = %d, Before = %d\n", nMaxNodes, nNodesBefore ); - - if (0) - { - char buffer[128]; - sprintf (buffer, "test" ); -// Fraig_MappingShow( pMan, buffer ); - } - -// pProgress = Extra_ProgressBarStart( stdout, nMaxNodes ); -Fraig_ManCheckConsistency( pMan ); - - for ( i = nInputs+1; (i < Fraig_ManReadNodeNum( pMan )) - && (nMaxNodes > Fraig_ManReadNodeNum( pMan )); ++i ) - { -// if ( i == nNodesBefore ) -// break; - - pNode = Fraig_ManReadIthNode( pMan, i ); - assert ( pNode ); - - pRepr = pNode->pRepr ? pNode->pRepr : pNode; - //printf ("Slack: %d\n", Fraig_NodeReadSlack( pRepr )); - - // All the new associative choices we add will have huge slack - // since we do not redo timing, and timing doesnt handle choices - // well anyway. However every newly added node is a choice of an - // existing critical node, so they are considered critical. -// if ( (Fraig_NodeReadSlack( pRepr ) > 3) && (i < nNodesBefore) ) -// continue; - -// if ( pNode->pRepr ) -// continue; - - // Try ((ab)c), x = ab -> (a(bc)) and (b(ac)) - pX = Fraig_NodeReadOne(pNode); - pC = Fraig_NodeReadTwo(pNode); - if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX)) - { - pA = Fraig_NodeReadOne(Fraig_Regular(pX)); - pB = Fraig_NodeReadTwo(Fraig_Regular(pX)); - -// pA = Fraig_NodeGetRepr( pA ); -// pB = Fraig_NodeGetRepr( pB ); -// pC = Fraig_NodeGetRepr( pC ); - - if (fShortCut) - { - pT = Fraig_NodeAnd(pMan, pB, pC); - if ( !pT->pRepr ) - { - pN = Fraig_NodeAnd(pMan, pA, pT); -// Fraig_NodeAddChoice( pMan, pNode, pN ); - } - } - else - pN = Fraig_NodeAnd(pMan, pA, Fraig_NodeAnd(pMan, pB, pC)); - // assert ( Fraig_NodesEqual(pN, pNode) ); - - - if (fShortCut) - { - pT = Fraig_NodeAnd(pMan, pA, pC); - if ( !pT->pRepr ) - { - pN = Fraig_NodeAnd(pMan, pB, pT); -// Fraig_NodeAddChoice( pMan, pNode, pN ); - } - } - else - pN = Fraig_NodeAnd(pMan, pB, Fraig_NodeAnd(pMan, pA, pC)); - // assert ( Fraig_NodesEqual(pN, pNode) ); - } - - - // Try (a(bc)), x = bc -> ((ab)c) and ((ac)b) - pA = Fraig_NodeReadOne(pNode); - pX = Fraig_NodeReadTwo(pNode); - if (Fraig_NodeIsAnd(pX) && !Fraig_IsComplement(pX)) - { - pB = Fraig_NodeReadOne(Fraig_Regular(pX)); - pC = Fraig_NodeReadTwo(Fraig_Regular(pX)); - -// pA = Fraig_NodeGetRepr( pA ); -// pB = Fraig_NodeGetRepr( pB ); -// pC = Fraig_NodeGetRepr( pC ); - - if (fShortCut) - { - pT = Fraig_NodeAnd(pMan, pA, pB); - if ( !pT->pRepr ) - { - pN = Fraig_NodeAnd(pMan, pC, pT); -// Fraig_NodeAddChoice( pMan, pNode, pN ); - } - } - else - pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pB), pC); - // assert ( Fraig_NodesEqual(pN, pNode) ); - - if (fShortCut) - { - pT = Fraig_NodeAnd(pMan, pA, pC); - if ( !pT->pRepr ) - { - pN = Fraig_NodeAnd(pMan, pB, pT); -// Fraig_NodeAddChoice( pMan, pNode, pN ); - } - } - else - pN = Fraig_NodeAnd(pMan, Fraig_NodeAnd(pMan, pA, pC), pB); - // assert ( Fraig_NodesEqual(pN, pNode) ); - } - - -/* - // Try distributive transform - pQ = Fraig_NodeReadOne(pNode); - pR = Fraig_NodeReadTwo(pNode); - if ( (Fraig_IsComplement(pQ) && Fraig_NodeIsAnd(pQ)) - && (Fraig_IsComplement(pR) && Fraig_NodeIsAnd(pR)) ) - { - pA = Fraig_NodeReadOne(Fraig_Regular(pQ)); - pB = Fraig_NodeReadTwo(Fraig_Regular(pQ)); - pC = Fraig_NodeReadOne(Fraig_Regular(pR)); - pD = Fraig_NodeReadTwo(Fraig_Regular(pR)); - - // Now detect the !(xy + xz) pattern, store - // x in pA, y in pB and z in pC and set pD = 0 to indicate - // pattern was found - assert (pD != 0); - if (pA == pC) { pC = pD; pD = 0; } - if (pA == pD) { pD = 0; } - if (pB == pC) { pB = pA; pA = pC; pC = pD; pD = 0; } - if (pB == pD) { pB = pA; pA = pD; pD = 0; } - if (pD == 0) - { - nDistributive++; - pN = Fraig_Not(Fraig_NodeAnd(pMan, pA, - Fraig_NodeOr(pMan, pB, pC))); - if (fShortCut) Fraig_NodeAddChoice( pMan, pNode, pN ); - // assert ( Fraig_NodesEqual(pN, pNode) ); - } - } -*/ - if ( i % 1000 == 0 ) - { - sprintf( Buffer, "Adding choice %6d...", i - nNodesBefore ); -// Extra_ProgressBarUpdate( pProgress, i, Buffer ); - } - } - -// Extra_ProgressBarStop( pProgress ); - -Fraig_ManCheckConsistency( pMan ); - - nNodesAfter = Fraig_ManReadNodeNum( pMan ); - printf ( "Nodes before = %6d. Nodes with associative choices = %6d. Increase = %4.2f %%.\n", - nNodesBefore, nNodesAfter, ((float)(nNodesAfter - nNodesBefore)) * 100.0/(nNodesBefore - nInputs) ); - printf ( "Distributive = %d\n", nDistributive ); - -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/fraig/fraigFanout.c b/src/sat/fraig/fraigFanout.c deleted file mode 100644 index 789bffca..00000000 --- a/src/sat/fraig/fraigFanout.c +++ /dev/null @@ -1,175 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigFanout.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Procedures to manipulate fanouts of the FRAIG nodes.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigFanout.c,v 1.5 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -#ifdef FRAIG_ENABLE_FANOUTS - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Add the fanout to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout ) -{ - Fraig_Node_t * pPivot; - - // pFanins is a fanin of pFanout - assert( !Fraig_IsComplement(pFanin) ); - assert( !Fraig_IsComplement(pFanout) ); - assert( Fraig_Regular(pFanout->p1) == pFanin || Fraig_Regular(pFanout->p2) == pFanin ); - - pPivot = pFanin->pFanPivot; - if ( pPivot == NULL ) - { - pFanin->pFanPivot = pFanout; - return; - } - - if ( Fraig_Regular(pPivot->p1) == pFanin ) - { - if ( Fraig_Regular(pFanout->p1) == pFanin ) - { - pFanout->pFanFanin1 = pPivot->pFanFanin1; - pPivot->pFanFanin1 = pFanout; - } - else // if ( Fraig_Regular(pFanout->p2) == pFanin ) - { - pFanout->pFanFanin2 = pPivot->pFanFanin1; - pPivot->pFanFanin1 = pFanout; - } - } - else // if ( Fraig_Regular(pPivot->p2) == pFanin ) - { - assert( Fraig_Regular(pPivot->p2) == pFanin ); - if ( Fraig_Regular(pFanout->p1) == pFanin ) - { - pFanout->pFanFanin1 = pPivot->pFanFanin2; - pPivot->pFanFanin2 = pFanout; - } - else // if ( Fraig_Regular(pFanout->p2) == pFanin ) - { - pFanout->pFanFanin2 = pPivot->pFanFanin2; - pPivot->pFanFanin2 = pFanout; - } - } -} - -/**Function************************************************************* - - Synopsis [Add the fanout to the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove ) -{ - Fraig_Node_t * pFanout, * pFanout2, ** ppFanList; - // start the linked list of fanouts - ppFanList = &pFanin->pFanPivot; - // go through the fanouts - Fraig_NodeForEachFanoutSafe( pFanin, pFanout, pFanout2 ) - { - // skip the fanout-to-remove - if ( pFanout == pFanoutToRemove ) - continue; - // add useful fanouts to the list - *ppFanList = pFanout; - ppFanList = Fraig_NodeReadNextFanoutPlace( pFanin, pFanout ); - } - *ppFanList = NULL; -} - -/**Function************************************************************* - - Synopsis [Transfers fanout to a different node.] - - Description [Assumes that the other node currently has no fanouts.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeTransferFanout( Fraig_Node_t * pNodeFrom, Fraig_Node_t * pNodeTo ) -{ - Fraig_Node_t * pFanout; - assert( pNodeTo->pFanPivot == NULL ); - assert( pNodeTo->pFanFanin1 == NULL ); - assert( pNodeTo->pFanFanin2 == NULL ); - // go through the fanouts and update their fanins - Fraig_NodeForEachFanout( pNodeFrom, pFanout ) - { - if ( Fraig_Regular(pFanout->p1) == pNodeFrom ) - pFanout->p1 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p1) ); - else if ( Fraig_Regular(pFanout->p2) == pNodeFrom ) - pFanout->p2 = Fraig_NotCond( pNodeTo, Fraig_IsComplement(pFanout->p2) ); - } - // move the pointers - pNodeTo->pFanPivot = pNodeFrom->pFanPivot; - pNodeTo->pFanFanin1 = pNodeFrom->pFanFanin1; - pNodeTo->pFanFanin2 = pNodeFrom->pFanFanin2; - pNodeFrom->pFanPivot = NULL; - pNodeFrom->pFanFanin1 = NULL; - pNodeFrom->pFanFanin2 = NULL; -} - -/**Function************************************************************* - - Synopsis [Returns the number of fanouts of a node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pFanout; - int Counter = 0; - Fraig_NodeForEachFanout( pNode, pFanout ) - Counter++; - return Counter; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - -#endif - diff --git a/src/sat/fraig/fraigFeed.c b/src/sat/fraig/fraigFeed.c deleted file mode 100644 index 8a3cc6c7..00000000 --- a/src/sat/fraig/fraigFeed.c +++ /dev/null @@ -1,909 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigFeed.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Procedures to support the solver feedback.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigFeed.c,v 1.8 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ); -static int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ); -static void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); - -static void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ); -static Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * pMan ); -static int Fraig_GetSmallestColumn( int * pHits, int nHits ); -static int Fraig_GetHittingPattern( unsigned * pSims, int nWords ); -static void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ); -static void Fraig_FeedBackCheckTable( Fraig_Man_t * p ); -static void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ); -static void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ); - - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Initializes the feedback information.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBackInit( Fraig_Man_t * p ) -{ - p->vCones = Fraig_NodeVecAlloc( 500 ); - p->vPatsReal = Msat_IntVecAlloc( 1000 ); - p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); - p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); -} - -/**Function************************************************************* - - Synopsis [Processes the feedback from teh solver.] - - Description [Array pModel gives the value of each variable in the SAT - solver. Array vVars is the array of integer numbers of variables - involves in this conflict.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - int nVarsPi, nWords; - int i, clk = clock(); - - // get the number of PI vars in the feedback (also sets the PI values) - nVarsPi = Fraig_FeedBackPrepare( p, pModel, vVars ); - - // set the PI values - nWords = Fraig_FeedBackInsert( p, nVarsPi ); - assert( p->iWordStart + nWords <= p->nWordsDyna ); - - // resimulates the words from p->iWordStart to iWordStop - for ( i = 1; i < p->vNodes->nSize; i++ ) - if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) - Fraig_NodeSimulate( p->vNodes->pArray[i], p->iWordStart, p->iWordStart + nWords, 0 ); - - if ( p->fDoSparse ) - Fraig_TableRehashF0( p, 0 ); - - if ( !p->fChoicing ) - Fraig_FeedBackVerify( p, pOld, pNew ); - - // if there is no room left, compress the patterns - if ( p->iWordStart + nWords == p->nWordsDyna ) - p->iWordStart = Fraig_FeedBackCompress( p ); - else // otherwise, update the starting word - p->iWordStart += nWords; - -p->timeFeed += clock() - clk; -} - -/**Function************************************************************* - - Synopsis [Get the number and values of the PI variables.] - - Description [Returns the number of PI variables involved in this feedback. - Fills in the internal presence and value data for the primary inputs.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_FeedBackPrepare( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars ) -{ - Fraig_Node_t * pNode; - int i, nVars, nVarsPis, * pVars; - - // clean the presence flag for all PIs - for ( i = 0; i < p->vInputs->nSize; i++ ) - { - pNode = p->vInputs->pArray[i]; - pNode->fFeedUse = 0; - } - - // get the variables involved in the feedback - nVars = Msat_IntVecReadSize(vVars); - pVars = Msat_IntVecReadArray(vVars); - - // set the values for the present variables - nVarsPis = 0; - for ( i = 0; i < nVars; i++ ) - { - pNode = p->vNodes->pArray[ pVars[i] ]; - if ( !Fraig_NodeIsVar(pNode) ) - continue; - // set its value - pNode->fFeedUse = 1; - pNode->fFeedVal = !MSAT_LITSIGN(pModel[pVars[i]]); - nVarsPis++; - } - return nVarsPis; -} - -/**Function************************************************************* - - Synopsis [Inserts the new simulation patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_FeedBackInsert( Fraig_Man_t * p, int nVarsPi ) -{ - Fraig_Node_t * pNode; - int nWords, iPatFlip, nPatFlipLimit, i, w; - int fUseNoPats = 0; - int fUse2Pats = 0; - - // get the number of words - if ( fUse2Pats ) - nWords = FRAIG_NUM_WORDS( 2 * nVarsPi + 1 ); - else if ( fUseNoPats ) - nWords = 1; - else - nWords = FRAIG_NUM_WORDS( nVarsPi + 1 ); - // update the number of words if they do not fit into the simulation info - if ( nWords > p->nWordsDyna - p->iWordStart ) - nWords = p->nWordsDyna - p->iWordStart; - // determine the bound on the flipping bit - nPatFlipLimit = nWords * 32 - 2; - - // mark the real pattern - Msat_IntVecPush( p->vPatsReal, p->iWordStart * 32 ); - // record the real pattern - Fraig_BitStringSetBit( p->pSimsReal, p->iWordStart * 32 ); - - // set the values at the PIs - iPatFlip = 1; - for ( i = 0; i < p->vInputs->nSize; i++ ) - { - pNode = p->vInputs->pArray[i]; - for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) - if ( !pNode->fFeedUse ) - pNode->puSimD[w] = FRAIG_RANDOM_UNSIGNED; - else if ( pNode->fFeedVal ) - pNode->puSimD[w] = FRAIG_FULL; - else // if ( !pNode->fFeedVal ) - pNode->puSimD[w] = 0; - - if ( fUse2Pats ) - { - // flip two patterns - if ( pNode->fFeedUse && 2 * iPatFlip < nPatFlipLimit ) - { - Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip - 1 ); - Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip ); - Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, 2 * iPatFlip + 1 ); - iPatFlip++; - } - } - else if ( fUseNoPats ) - { - } - else - { - // flip the diagonal - if ( pNode->fFeedUse && iPatFlip < nPatFlipLimit ) - { - Fraig_BitStringXorBit( pNode->puSimD + p->iWordStart, iPatFlip ); - iPatFlip++; - // Extra_PrintBinary( stdout, &pNode->puSimD, 45 ); printf( "\n" ); - } - } - // clean the use mask - pNode->fFeedUse = 0; - - // add the info to the D hash value of the PIs - for ( w = p->iWordStart; w < p->iWordStart + nWords; w++ ) - pNode->uHashD ^= pNode->puSimD[w] * s_FraigPrimes[w]; - - } - return nWords; -} - - -/**Function************************************************************* - - Synopsis [Checks that the SAT solver pattern indeed distinquishes the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBackVerify( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - int fValue1, fValue2, iPat; - iPat = Msat_IntVecReadEntry( p->vPatsReal, Msat_IntVecReadSize(p->vPatsReal)-1 ); - fValue1 = (Fraig_BitStringHasBit( pOld->puSimD, iPat )); - fValue2 = (Fraig_BitStringHasBit( pNew->puSimD, iPat )); -/* -Fraig_PrintNode( p, pOld ); -printf( "\n" ); -Fraig_PrintNode( p, pNew ); -printf( "\n" ); -*/ -// assert( fValue1 != fValue2 ); -} - -/**Function************************************************************* - - Synopsis [Compress the simulation patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_FeedBackCompress( Fraig_Man_t * p ) -{ - unsigned * pSims; - unsigned uHash; - int i, w, t, nPats, * pPats; - int fPerformChecks = (p->nBTLimit == -1); - - // solve the covering problem - if ( fPerformChecks ) - { - Fraig_FeedBackCheckTable( p ); - if ( p->fDoSparse ) - Fraig_FeedBackCheckTableF0( p ); - } - - // solve the covering problem - Fraig_FeedBackCovering( p, p->vPatsReal ); - - - // get the number of additional patterns - nPats = Msat_IntVecReadSize( p->vPatsReal ); - pPats = Msat_IntVecReadArray( p->vPatsReal ); - // get the new starting word - p->iWordStart = FRAIG_NUM_WORDS( p->iPatsPerm + nPats ); - - // set the simulation info for the PIs - for ( i = 0; i < p->vInputs->nSize; i++ ) - { - // get hold of the simulation info for this PI - pSims = p->vInputs->pArray[i]->puSimD; - // clean the storage for the new patterns - for ( w = p->iWordPerm; w < p->iWordStart; w++ ) - p->pSimsTemp[w] = 0; - // set the patterns - for ( t = 0; t < nPats; t++ ) - if ( Fraig_BitStringHasBit( pSims, pPats[t] ) ) - { - // check if this pattern falls into temporary storage - if ( p->iPatsPerm + t < p->iWordPerm * 32 ) - Fraig_BitStringSetBit( pSims, p->iPatsPerm + t ); - else - Fraig_BitStringSetBit( p->pSimsTemp, p->iPatsPerm + t ); - } - // copy the pattern - for ( w = p->iWordPerm; w < p->iWordStart; w++ ) - pSims[w] = p->pSimsTemp[w]; - // recompute the hashing info - uHash = 0; - for ( w = 0; w < p->iWordStart; w++ ) - uHash ^= pSims[w] * s_FraigPrimes[w]; - p->vInputs->pArray[i]->uHashD = uHash; - } - - // update info about the permanently stored patterns - p->iWordPerm = p->iWordStart; - p->iPatsPerm += nPats; - assert( p->iWordPerm == FRAIG_NUM_WORDS( p->iPatsPerm ) ); - - // resimulate and recompute the hash values - for ( i = 1; i < p->vNodes->nSize; i++ ) - if ( Fraig_NodeIsAnd(p->vNodes->pArray[i]) ) - { - p->vNodes->pArray[i]->uHashD = 0; - Fraig_NodeSimulate( p->vNodes->pArray[i], 0, p->iWordPerm, 0 ); - } - - // double-check that the nodes are still distinguished - if ( fPerformChecks ) - Fraig_FeedBackCheckTable( p ); - - // rehash the values in the F0 table - if ( p->fDoSparse ) - { - Fraig_TableRehashF0( p, 0 ); - if ( fPerformChecks ) - Fraig_FeedBackCheckTableF0( p ); - } - - // check if we need to resize the simulation info - // if less than FRAIG_WORDS_STORE words are left, reallocate simulation info - if ( p->iWordPerm + FRAIG_WORDS_STORE > p->nWordsDyna ) - Fraig_ReallocateSimulationInfo( p ); - - // set the real patterns - Msat_IntVecClear( p->vPatsReal ); - memset( p->pSimsReal, 0, sizeof(unsigned)*p->nWordsDyna ); - for ( w = 0; w < p->iWordPerm; w++ ) - p->pSimsReal[w] = FRAIG_FULL; - if ( p->iPatsPerm % 32 > 0 ) - p->pSimsReal[p->iWordPerm-1] = FRAIG_MASK( p->iPatsPerm % 32 ); -// printf( "The number of permanent words = %d.\n", p->iWordPerm ); - return p->iWordStart; -} - - - - -/**Function************************************************************* - - Synopsis [Checks the correctness of the functional simulation table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBackCovering( Fraig_Man_t * p, Msat_IntVec_t * vPats ) -{ - Fraig_NodeVec_t * vColumns; - unsigned * pSims; - int * pHits, iPat, iCol, i; - int nOnesTotal, nSolStarting; - int fVeryVerbose = 0; - - // collect the pairs to be distinguished - vColumns = Fraig_FeedBackCoveringStart( p ); - // collect the number of 1s in each simulation vector - nOnesTotal = 0; - pHits = ALLOC( int, vColumns->nSize ); - for ( i = 0; i < vColumns->nSize; i++ ) - { - pSims = (unsigned *)vColumns->pArray[i]; - pHits[i] = Fraig_BitStringCountOnes( pSims, p->iWordStart ); - nOnesTotal += pHits[i]; -// assert( pHits[i] > 0 ); - } - - // go through the patterns - nSolStarting = Msat_IntVecReadSize(vPats); - while ( (iCol = Fraig_GetSmallestColumn( pHits, vColumns->nSize )) != -1 ) - { - // find the pattern, which hits this column - iPat = Fraig_GetHittingPattern( (unsigned *)vColumns->pArray[iCol], p->iWordStart ); - // cancel the columns covered by this pattern - Fraig_CancelCoveredColumns( vColumns, pHits, iPat ); - // save the pattern - Msat_IntVecPush( vPats, iPat ); - } - - // free the set of columns - for ( i = 0; i < vColumns->nSize; i++ ) - Fraig_MemFixedEntryRecycle( p->mmSims, (char *)vColumns->pArray[i] ); - - // print stats related to the covering problem - if ( p->fVerbose && fVeryVerbose ) - { - printf( "%3d\\%3d\\%3d ", p->nWordsRand, p->nWordsDyna, p->iWordPerm ); - printf( "Col (pairs) = %5d. ", vColumns->nSize ); - printf( "Row (pats) = %5d. ", p->iWordStart * 32 ); - printf( "Dns = %6.2f %%. ", vColumns->nSize==0? 0.0 : 100.0 * nOnesTotal / vColumns->nSize / p->iWordStart / 32 ); - printf( "Sol = %3d (%3d). ", Msat_IntVecReadSize(vPats), nSolStarting ); - printf( "\n" ); - } - Fraig_NodeVecFree( vColumns ); - free( pHits ); -} - - -/**Function************************************************************* - - Synopsis [Checks the correctness of the functional simulation table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_FeedBackCoveringStart( Fraig_Man_t * p ) -{ - Fraig_NodeVec_t * vColumns; - Fraig_HashTable_t * pT = p->pTableF; - Fraig_Node_t * pEntF, * pEntD; - unsigned * pSims; - unsigned * pUnsigned1, * pUnsigned2; - int i, k, m, w;//, nOnes; - - // start the set of columns - vColumns = Fraig_NodeVecAlloc( 100 ); - - // go through the pairs of nodes to be distinguished - for ( i = 0; i < pT->nBins; i++ ) - Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) - { - p->vCones->nSize = 0; - Fraig_TableBinForEachEntryD( pEntF, pEntD ) - Fraig_NodeVecPush( p->vCones, pEntD ); - if ( p->vCones->nSize == 1 ) - continue; - //////////////////////////////// bug fix by alanmi, September 14, 2006 - if ( p->vCones->nSize > 20 ) - continue; - //////////////////////////////// - - for ( k = 0; k < p->vCones->nSize; k++ ) - for ( m = k+1; m < p->vCones->nSize; m++ ) - { - if ( !Fraig_CompareSimInfoUnderMask( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0, p->pSimsReal ) ) - continue; - - // primary simulation patterns (counter-examples) cannot distinguish this pair - // get memory to store the feasible simulation patterns - pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - // find the pattern that distinguish this column, exept the primary ones - pUnsigned1 = p->vCones->pArray[k]->puSimD; - pUnsigned2 = p->vCones->pArray[m]->puSimD; - for ( w = 0; w < p->iWordStart; w++ ) - pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; - // store the pattern - Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); -// nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); -// assert( nOnes > 0 ); - } - } - - // if the flag is not set, do not consider sparse nodes in p->pTableF0 - if ( !p->fDoSparse ) - return vColumns; - - // recalculate their hash values based on p->pSimsReal - pT = p->pTableF0; - for ( i = 0; i < pT->nBins; i++ ) - Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) - { - pSims = pEntF->puSimD; - pEntF->uHashD = 0; - for ( w = 0; w < p->iWordStart; w++ ) - pEntF->uHashD ^= (pSims[w] & p->pSimsReal[w]) * s_FraigPrimes[w]; - } - - // rehash the table using these values - Fraig_TableRehashF0( p, 1 ); - - // collect the classes of equivalent node pairs - for ( i = 0; i < pT->nBins; i++ ) - Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) - { - p->vCones->nSize = 0; - Fraig_TableBinForEachEntryD( pEntF, pEntD ) - Fraig_NodeVecPush( p->vCones, pEntD ); - if ( p->vCones->nSize == 1 ) - continue; - - // primary simulation patterns (counter-examples) cannot distinguish all these pairs - for ( k = 0; k < p->vCones->nSize; k++ ) - for ( m = k+1; m < p->vCones->nSize; m++ ) - { - // get memory to store the feasible simulation patterns - pSims = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - // find the patterns that are not distinquished - pUnsigned1 = p->vCones->pArray[k]->puSimD; - pUnsigned2 = p->vCones->pArray[m]->puSimD; - for ( w = 0; w < p->iWordStart; w++ ) - pSims[w] = (pUnsigned1[w] ^ pUnsigned2[w]) & ~p->pSimsReal[w]; - // store the pattern - Fraig_NodeVecPush( vColumns, (Fraig_Node_t *)pSims ); -// nOnes = Fraig_BitStringCountOnes(pSims, p->iWordStart); -// assert( nOnes > 0 ); - } - } - return vColumns; -} - -/**Function************************************************************* - - Synopsis [Selects the column, which has the smallest number of hits.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_GetSmallestColumn( int * pHits, int nHits ) -{ - int i, iColMin = -1, nHitsMin = 1000000; - for ( i = 0; i < nHits; i++ ) - { - // skip covered columns - if ( pHits[i] == 0 ) - continue; - // take the column if it can only be covered by one pattern - if ( pHits[i] == 1 ) - return i; - // find the column, which requires the smallest number of patterns - if ( nHitsMin > pHits[i] ) - { - nHitsMin = pHits[i]; - iColMin = i; - } - } - return iColMin; -} - -/**Function************************************************************* - - Synopsis [Select the pattern, which hits this column.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_GetHittingPattern( unsigned * pSims, int nWords ) -{ - int i, b; - for ( i = 0; i < nWords; i++ ) - { - if ( pSims[i] == 0 ) - continue; - for ( b = 0; b < 32; b++ ) - if ( pSims[i] & (1 << b) ) - return i * 32 + b; - } - return -1; -} - -/**Function************************************************************* - - Synopsis [Cancel covered patterns.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_CancelCoveredColumns( Fraig_NodeVec_t * vColumns, int * pHits, int iPat ) -{ - unsigned * pSims; - int i; - for ( i = 0; i < vColumns->nSize; i++ ) - { - pSims = (unsigned *)vColumns->pArray[i]; - if ( Fraig_BitStringHasBit( pSims, iPat ) ) - pHits[i] = 0; - } -} - - -/**Function************************************************************* - - Synopsis [Checks the correctness of the functional simulation table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBackCheckTable( Fraig_Man_t * p ) -{ - Fraig_HashTable_t * pT = p->pTableF; - Fraig_Node_t * pEntF, * pEntD; - int i, k, m, nPairs; - int clk = clock(); - - nPairs = 0; - for ( i = 0; i < pT->nBins; i++ ) - Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) - { - p->vCones->nSize = 0; - Fraig_TableBinForEachEntryD( pEntF, pEntD ) - Fraig_NodeVecPush( p->vCones, pEntD ); - if ( p->vCones->nSize == 1 ) - continue; - for ( k = 0; k < p->vCones->nSize; k++ ) - for ( m = k+1; m < p->vCones->nSize; m++ ) - { - if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) - printf( "Nodes %d and %d have the same D simulation info.\n", - p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); - nPairs++; - } - } -// printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); -} - -/**Function************************************************************* - - Synopsis [Checks the correctness of the functional simulation table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_FeedBackCheckTableF0( Fraig_Man_t * p ) -{ - Fraig_HashTable_t * pT = p->pTableF0; - Fraig_Node_t * pEntF; - int i, k, m, nPairs; - - nPairs = 0; - for ( i = 0; i < pT->nBins; i++ ) - { - p->vCones->nSize = 0; - Fraig_TableBinForEachEntryF( pT->pBins[i], pEntF ) - Fraig_NodeVecPush( p->vCones, pEntF ); - if ( p->vCones->nSize == 1 ) - continue; - for ( k = 0; k < p->vCones->nSize; k++ ) - for ( m = k+1; m < p->vCones->nSize; m++ ) - { - if ( Fraig_CompareSimInfo( p->vCones->pArray[k], p->vCones->pArray[m], p->iWordStart, 0 ) ) - printf( "Nodes %d and %d have the same D simulation info.\n", - p->vCones->pArray[k]->Num, p->vCones->pArray[m]->Num ); - nPairs++; - } - } -// printf( "\nThe total of %d node pairs have been verified.\n", nPairs ); -} - -/**Function************************************************************* - - Synopsis [Doubles the size of simulation info.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ReallocateSimulationInfo( Fraig_Man_t * p ) -{ - Fraig_MemFixed_t * mmSimsNew; // new memory manager for simulation info - Fraig_Node_t * pNode; - unsigned * pSimsNew; - unsigned uSignOld; - int i; - - // allocate a new memory manager - p->nWordsDyna *= 2; - mmSimsNew = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); - - // set the new data for the constant node - pNode = p->pConst1; - pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); - pNode->puSimD = pNode->puSimR + p->nWordsRand; - memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); - memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); - - // copy the simulation info of the PIs - for ( i = 0; i < p->vInputs->nSize; i++ ) - { - pNode = p->vInputs->pArray[i]; - // copy the simulation info - pSimsNew = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); - memmove( pSimsNew, pNode->puSimR, sizeof(unsigned) * (p->nWordsRand + p->iWordStart) ); - // attach the new info - pNode->puSimR = pSimsNew; - pNode->puSimD = pNode->puSimR + p->nWordsRand; - // signatures remain without changes - } - - // replace the manager to free up some memory - Fraig_MemFixedStop( p->mmSims, 0 ); - p->mmSims = mmSimsNew; - - // resimulate the internal nodes (this should lead to the same signatures) - for ( i = 1; i < p->vNodes->nSize; i++ ) - { - pNode = p->vNodes->pArray[i]; - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - // allocate memory for the simulation info - pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); - pNode->puSimD = pNode->puSimR + p->nWordsRand; - // derive random simulation info - uSignOld = pNode->uHashR; - pNode->uHashR = 0; - Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); - assert( uSignOld == pNode->uHashR ); - // derive dynamic simulation info - uSignOld = pNode->uHashD; - pNode->uHashD = 0; - Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); - assert( uSignOld == pNode->uHashD ); - } - - // realloc temporary storage - p->pSimsReal = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); - memset( p->pSimsReal, 0, sizeof(unsigned) * p->nWordsDyna ); - p->pSimsTemp = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); - p->pSimsDiff = (unsigned *)Fraig_MemFixedEntryFetch( mmSimsNew ); -} - - -/**Function************************************************************* - - Synopsis [Generated trivial counter example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Fraig_ManAllocCounterExample( Fraig_Man_t * p ) -{ - int * pModel; - pModel = ALLOC( int, p->vInputs->nSize ); - memset( pModel, 0, sizeof(int) * p->vInputs->nSize ); - return pModel; -} - - -/**Function************************************************************* - - Synopsis [Saves the counter example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManSimulateBitNode_rec( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - int Value0, Value1; - if ( Fraig_NodeIsTravIdCurrent( p, pNode ) ) - return pNode->fMark3; - Fraig_NodeSetTravIdCurrent( p, pNode ); - Value0 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p1) ); - Value1 = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode->p2) ); - Value0 ^= Fraig_IsComplement(pNode->p1); - Value1 ^= Fraig_IsComplement(pNode->p2); - pNode->fMark3 = Value0 & Value1; - return pNode->fMark3; -} - -/**Function************************************************************* - - Synopsis [Simulates one bit.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManSimulateBitNode( Fraig_Man_t * p, Fraig_Node_t * pNode, int * pModel ) -{ - int fCompl, RetValue, i; - // set the PI values - Fraig_ManIncrementTravId( p ); - for ( i = 0; i < p->vInputs->nSize; i++ ) - { - Fraig_NodeSetTravIdCurrent( p, p->vInputs->pArray[i] ); - p->vInputs->pArray[i]->fMark3 = pModel[i]; - } - // perform the traversal - fCompl = Fraig_IsComplement(pNode); - RetValue = Fraig_ManSimulateBitNode_rec( p, Fraig_Regular(pNode) ); - return fCompl ^ RetValue; -} - - -/**Function************************************************************* - - Synopsis [Saves the counter example.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - int * pModel; - int iPattern; - int i, fCompl; - - // the node can be complemented - fCompl = Fraig_IsComplement(pNode); - // because we compare with constant 0, p->pConst1 should also be complemented - fCompl = !fCompl; - - // derive the model - pModel = Fraig_ManAllocCounterExample( p ); - iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->nWordsRand, 1 ); - if ( iPattern >= 0 ) - { - for ( i = 0; i < p->vInputs->nSize; i++ ) - if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimR, iPattern ) ) - pModel[i] = 1; -/* -printf( "SAT solver's pattern:\n" ); -for ( i = 0; i < p->vInputs->nSize; i++ ) - printf( "%d", pModel[i] ); -printf( "\n" ); -*/ - assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); - return pModel; - } - iPattern = Fraig_FindFirstDiff( p->pConst1, Fraig_Regular(pNode), fCompl, p->iWordStart, 0 ); - if ( iPattern >= 0 ) - { - for ( i = 0; i < p->vInputs->nSize; i++ ) - if ( Fraig_BitStringHasBit( p->vInputs->pArray[i]->puSimD, iPattern ) ) - pModel[i] = 1; -/* -printf( "SAT solver's pattern:\n" ); -for ( i = 0; i < p->vInputs->nSize; i++ ) - printf( "%d", pModel[i] ); -printf( "\n" ); -*/ - assert( Fraig_ManSimulateBitNode( p, pNode, pModel ) ); - return pModel; - } - FREE( pModel ); - return NULL; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/fraig/fraigInt.h b/src/sat/fraig/fraigInt.h deleted file mode 100644 index 9c6e0d47..00000000 --- a/src/sat/fraig/fraigInt.h +++ /dev/null @@ -1,451 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigInt.h] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Internal declarations of the FRAIG package.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigInt.h,v 1.15 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#ifndef __FRAIG_INT_H__ -#define __FRAIG_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//#include "leaks.h" -#include -#include -#include -#include -#include - -#include "fraig.h" -#include "msat.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -/* - The AIG node policy: - - Each node has its main number (pNode->Num) - This is the number of this node in the array of all nodes and its SAT variable number - - The PI nodes are stored along with other nodes - Additionally, PI nodes have a PI number, by which they are stored in the PI node array - - The constant node is has number 0 and is also stored in the array -*/ - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -// enable this macro to support the fanouts -#define FRAIG_ENABLE_FANOUTS -#define FRAIG_PATTERNS_RANDOM 2048 // should not be less than 128 and more than 32768 (2^15) -#define FRAIG_PATTERNS_DYNAMIC 2048 // should not be less than 256 and more than 32768 (2^15) -#define FRAIG_MAX_PRIMES 1024 // the maximum number of primes used for hashing - -// this parameter determines when simulation info is extended -// it will be extended when the free storage in the dynamic simulation -// info is less or equal to this number of words (FRAIG_WORDS_STORE) -// this is done because if the free storage for dynamic simulation info -// is not sufficient, computation becomes inefficient -#define FRAIG_WORDS_STORE 5 - -// the bit masks -#define FRAIG_MASK(n) ((~((unsigned)0)) >> (32-(n))) -#define FRAIG_FULL (~((unsigned)0)) -#define FRAIG_NUM_WORDS(n) (((n)>>5) + (((n)&31) > 0)) - -// maximum/minimum operators -#define FRAIG_MIN(a,b) (((a) < (b))? (a) : (b)) -#define FRAIG_MAX(a,b) (((a) > (b))? (a) : (b)) - -// generating random unsigned (#define RAND_MAX 0x7fff) -#define FRAIG_RANDOM_UNSIGNED ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())) - -// macros to get hold of the bits in a bit string -#define Fraig_BitStringSetBit(p,i) ((p)[(i)>>5] |= (1<<((i) & 31))) -#define Fraig_BitStringXorBit(p,i) ((p)[(i)>>5] ^= (1<<((i) & 31))) -#define Fraig_BitStringHasBit(p,i) (((p)[(i)>>5] & (1<<((i) & 31))) > 0) - -// macros to get hold of the bits in the support info -//#define Fraig_NodeSetVarStr(p,i) (Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] |= (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) -//#define Fraig_NodeHasVarStr(p,i) ((Fraig_Regular(p)->pSuppStr[((i)%FRAIG_SUPP_SIGN)>>5] & (1<<(((i)%FRAIG_SUPP_SIGN) & 31))) > 0) -#define Fraig_NodeSetVarStr(p,i) Fraig_BitStringSetBit(Fraig_Regular(p)->pSuppStr,i) -#define Fraig_NodeHasVarStr(p,i) Fraig_BitStringHasBit(Fraig_Regular(p)->pSuppStr,i) - -// copied from "util.h" for standaloneness -#ifndef ALLOC -# define ALLOC(type, num) \ - ((type *) malloc(sizeof(type) * (num))) -#endif - -#ifndef REALLOC -# define REALLOC(type, obj, num) \ - (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num))) -#endif - -#ifndef FREE -# define FREE(obj) \ - ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) -#endif - -// copied from "extra.h" for stand-aloneness -#define Fraig_PrintTime(a,t) printf( "%s = ", (a) ); printf( "%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) ) - -#define Fraig_HashKey2(a,b,TSIZE) (((unsigned)(a) + (unsigned)(b) * 12582917) % TSIZE) -//#define Fraig_HashKey2(a,b,TSIZE) (( ((unsigned)(a)->Num * 19) ^ ((unsigned)(b)->Num * 1999) ) % TSIZE) -//#define Fraig_HashKey2(a,b,TSIZE) ( ((unsigned)((a)->Num + (b)->Num) * ((a)->Num + (b)->Num + 1) / 2) % TSIZE) -// the other two hash functions give bad distribution of hash chain lengths (not clear why) - -#ifndef PRT -#define PRT(a,t) printf( "%s = ", (a) ); printf( "%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) ) -#endif - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Fraig_MemFixed_t_ Fraig_MemFixed_t; - -// the mapping manager -struct Fraig_ManStruct_t_ -{ - // the AIG nodes - Fraig_NodeVec_t * vInputs; // the array of primary inputs - Fraig_NodeVec_t * vNodes; // the array of all nodes, including primary inputs - Fraig_NodeVec_t * vOutputs; // the array of primary outputs (some internal nodes) - Fraig_Node_t * pConst1; // the pointer to the constant node (vNodes->pArray[0]) - - // info about the original circuit - char ** ppInputNames; // the primary input names - char ** ppOutputNames; // the primary output names - - // various hash-tables - Fraig_HashTable_t * pTableS; // hashing by structure - Fraig_HashTable_t * pTableF; // hashing by simulation info - Fraig_HashTable_t * pTableF0; // hashing by simulation info (sparse functions) - - // parameters - int nWordsRand; // the number of words of random simulation info - int nWordsDyna; // the number of words of dynamic simulation info - int nBTLimit; // the max number of backtracks to perform - int nSeconds; // the runtime limit for the miter proof - int fFuncRed; // performs only one level hashing - int fFeedBack; // enables solver feedback - int fDist1Pats; // enables solver feedback - int fDoSparse; // performs equiv tests for sparse functions - int fChoicing; // enables recording structural choices - int fTryProve; // tries to solve the final miter - int fVerbose; // the verbosiness flag - int fVerboseP; // the verbosiness flag - sint64 nInspLimit; // the inspection limit - - int nTravIds; // the traversal counter - int nTravIds2; // the traversal counter - - // info related to the solver feedback - int iWordStart; // the first word to use for simulation - int iWordPerm; // the number of words stored permanently - int iPatsPerm; // the number of patterns stored permanently - Fraig_NodeVec_t * vCones; // the temporary array of internal variables - Msat_IntVec_t * vPatsReal; // the array of real pattern numbers - unsigned * pSimsReal; // used for simulation patterns - unsigned * pSimsDiff; // used for simulation patterns - unsigned * pSimsTemp; // used for simulation patterns - - // the support information - int nSuppWords; - unsigned ** pSuppS; - unsigned ** pSuppF; - - // the memory managers - Fraig_MemFixed_t * mmNodes; // the memory manager for nodes - Fraig_MemFixed_t * mmSims; // the memory manager for simulation info - - // solving the SAT problem - Msat_Solver_t * pSat; // the SAT solver - Msat_IntVec_t * vProj; // the temporary array of projection vars - int nSatNums; // the counter of SAT variables - int * pModel; // the assignment, which satisfies the miter - // these arrays belong to the solver - Msat_IntVec_t * vVarsInt; // the temporary array of variables - Msat_ClauseVec_t * vAdjacents; // the temporary storage for connectivity - Msat_IntVec_t * vVarsUsed; // the array marking vars appearing in the cone - - // various statistic variables - int nSatCalls; // the number of times equivalence checking was called - int nSatProof; // the number of times a proof was found - int nSatCounter; // the number of times a counter example was found - int nSatFails; // the number of times the SAT solver failed to complete due to resource limit or prediction - int nSatFailsReal; // the number of times the SAT solver failed to complete due to resource limit - - int nSatCallsImp; // the number of times equivalence checking was called - int nSatProofImp; // the number of times a proof was found - int nSatCounterImp;// the number of times a counter example was found - int nSatFailsImp; // the number of times the SAT solver failed to complete - - int nSatZeros; // the number of times the simulation vector is zero - int nSatSupps; // the number of times the support info was useful - int nRefErrors; // the number of ref counting errors - int nImplies; // the number of implication cases - int nSatImpls; // the number of implication SAT calls - int nVarsClauses; // the number of variables with clauses - int nSimplifies0; - int nSimplifies1; - int nImplies0; - int nImplies1; - - // runtime statistics - int timeToAig; // time to transfer to the mapping structure - int timeSims; // time to compute k-feasible cuts - int timeTrav; // time to traverse the network - int timeFeed; // time for solver feedback (recording and resimulating) - int timeImply; // time to analyze implications - int timeSat; // time to compute the truth table for each cut - int timeToNet; // time to transfer back to the network - int timeTotal; // the total mapping time - int time1; // time to perform one task - int time2; // time to perform another task - int time3; // time to perform another task - int time4; // time to perform another task -}; - -// the mapping node -struct Fraig_NodeStruct_t_ -{ - // various numbers associated with the node - int Num; // the unique number (SAT var number) of this node - int NumPi; // if the node is a PI, this is its variable number - int Level; // the level of the node - int nRefs; // the number of references of the node - int TravId; // the traversal ID (use to avoid cleaning marks) - int TravId2; // the traversal ID (use to avoid cleaning marks) - - // general information about the node - unsigned fInv : 1; // the mark to show that simulation info is complemented - unsigned fNodePo : 1; // the mark used for primary outputs - unsigned fClauses : 1; // the clauses for this node are loaded - unsigned fMark0 : 1; // the mark used for traversals - unsigned fMark1 : 1; // the mark used for traversals - unsigned fMark2 : 1; // the mark used for traversals - unsigned fMark3 : 1; // the mark used for traversals - unsigned fFeedUse : 1; // the presence of the variable in the feedback - unsigned fFeedVal : 1; // the value of the variable in the feedback - unsigned fFailTfo : 1; // the node is in the TFO of the failed SAT run - unsigned nFanouts : 2; // the indicator of fanouts (none, one, or many) - unsigned nOnes : 20; // the number of 1's in the random sim info - - // the children of the node - Fraig_Node_t * p1; // the first child - Fraig_Node_t * p2; // the second child - Fraig_NodeVec_t * vFanins; // the fanins of the supergate rooted at this node -// Fraig_NodeVec_t * vFanouts; // the fanouts of the supergate rooted at this node - - // various linked lists - Fraig_Node_t * pNextS; // the next node in the structural hash table - Fraig_Node_t * pNextF; // the next node in the functional (simulation) hash table - Fraig_Node_t * pNextD; // the next node in the list of nodes based on dynamic simulation - Fraig_Node_t * pNextE; // the next structural choice (functionally-equivalent node) - Fraig_Node_t * pRepr; // the canonical functional representative of the node - - // simulation data - unsigned uHashR; // the hash value for random information - unsigned uHashD; // the hash value for dynamic information - unsigned * puSimR; // the simulation information (random) - unsigned * puSimD; // the simulation information (dynamic) - - // misc information - Fraig_Node_t * pData0; // temporary storage for the corresponding network node - Fraig_Node_t * pData1; // temporary storage for the corresponding network node - -#ifdef FRAIG_ENABLE_FANOUTS - // representation of node's fanouts - Fraig_Node_t * pFanPivot; // the first fanout of this node - Fraig_Node_t * pFanFanin1; // the next fanout of p1 - Fraig_Node_t * pFanFanin2; // the next fanout of p2 -#endif -}; - -// the vector of nodes -struct Fraig_NodeVecStruct_t_ -{ - int nCap; // the number of allocated entries - int nSize; // the number of entries in the array - Fraig_Node_t ** pArray; // the array of nodes -}; - -// the hash table -struct Fraig_HashTableStruct_t_ -{ - Fraig_Node_t ** pBins; // the table bins - int nBins; // the size of the table - int nEntries; // the total number of entries in the table -}; - -// getting hold of the next fanout of the node -#define Fraig_NodeReadNextFanout( pNode, pFanout ) \ - ( ( pFanout == NULL )? NULL : \ - ((Fraig_Regular((pFanout)->p1) == (pNode))? \ - (pFanout)->pFanFanin1 : (pFanout)->pFanFanin2) ) -// getting hold of the place where the next fanout will be attached -#define Fraig_NodeReadNextFanoutPlace( pNode, pFanout ) \ - ( (Fraig_Regular((pFanout)->p1) == (pNode))? \ - &(pFanout)->pFanFanin1 : &(pFanout)->pFanFanin2 ) -// iterator through the fanouts of the node -#define Fraig_NodeForEachFanout( pNode, pFanout ) \ - for ( pFanout = (pNode)->pFanPivot; pFanout; \ - pFanout = Fraig_NodeReadNextFanout(pNode, pFanout) ) -// safe iterator through the fanouts of the node -#define Fraig_NodeForEachFanoutSafe( pNode, pFanout, pFanout2 ) \ - for ( pFanout = (pNode)->pFanPivot, \ - pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout); \ - pFanout; \ - pFanout = pFanout2, \ - pFanout2 = Fraig_NodeReadNextFanout(pNode, pFanout) ) - -// iterators through the entries in the linked lists of nodes -// the list of nodes in the structural hash table -#define Fraig_TableBinForEachEntryS( pBin, pEnt ) \ - for ( pEnt = pBin; \ - pEnt; \ - pEnt = pEnt->pNextS ) -#define Fraig_TableBinForEachEntrySafeS( pBin, pEnt, pEnt2 ) \ - for ( pEnt = pBin, \ - pEnt2 = pEnt? pEnt->pNextS: NULL; \ - pEnt; \ - pEnt = pEnt2, \ - pEnt2 = pEnt? pEnt->pNextS: NULL ) -// the list of nodes in the functional (simulation) hash table -#define Fraig_TableBinForEachEntryF( pBin, pEnt ) \ - for ( pEnt = pBin; \ - pEnt; \ - pEnt = pEnt->pNextF ) -#define Fraig_TableBinForEachEntrySafeF( pBin, pEnt, pEnt2 ) \ - for ( pEnt = pBin, \ - pEnt2 = pEnt? pEnt->pNextF: NULL; \ - pEnt; \ - pEnt = pEnt2, \ - pEnt2 = pEnt? pEnt->pNextF: NULL ) -// the list of nodes with the same simulation and different functionality -#define Fraig_TableBinForEachEntryD( pBin, pEnt ) \ - for ( pEnt = pBin; \ - pEnt; \ - pEnt = pEnt->pNextD ) -#define Fraig_TableBinForEachEntrySafeD( pBin, pEnt, pEnt2 ) \ - for ( pEnt = pBin, \ - pEnt2 = pEnt? pEnt->pNextD: NULL; \ - pEnt; \ - pEnt = pEnt2, \ - pEnt2 = pEnt? pEnt->pNextD: NULL ) -// the list of nodes with the same functionality -#define Fraig_TableBinForEachEntryE( pBin, pEnt ) \ - for ( pEnt = pBin; \ - pEnt; \ - pEnt = pEnt->pNextE ) -#define Fraig_TableBinForEachEntrySafeE( pBin, pEnt, pEnt2 ) \ - for ( pEnt = pBin, \ - pEnt2 = pEnt? pEnt->pNextE: NULL; \ - pEnt; \ - pEnt = pEnt2, \ - pEnt2 = pEnt? pEnt->pNextE: NULL ) - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== fraigCanon.c =============================================================*/ -extern Fraig_Node_t * Fraig_NodeAndCanon( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -/*=== fraigFanout.c =============================================================*/ -extern void Fraig_NodeAddFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanout ); -extern void Fraig_NodeRemoveFaninFanout( Fraig_Node_t * pFanin, Fraig_Node_t * pFanoutToRemove ); -extern int Fraig_NodeGetFanoutNum( Fraig_Node_t * pNode ); -/*=== fraigFeed.c =============================================================*/ -extern void Fraig_FeedBackInit( Fraig_Man_t * p ); -extern void Fraig_FeedBack( Fraig_Man_t * p, int * pModel, Msat_IntVec_t * vVars, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -extern void Fraig_FeedBackTest( Fraig_Man_t * p ); -extern int Fraig_FeedBackCompress( Fraig_Man_t * p ); -extern int * Fraig_ManAllocCounterExample( Fraig_Man_t * p ); -extern int * Fraig_ManSaveCounterExample( Fraig_Man_t * p, Fraig_Node_t * pNode ); -/*=== fraigMan.c =============================================================*/ -extern void Fraig_ManCreateSolver( Fraig_Man_t * p ); -/*=== fraigMem.c =============================================================*/ -extern Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize ); -extern void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose ); -extern char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p ); -extern void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry ); -extern void Fraig_MemFixedRestart( Fraig_MemFixed_t * p ); -extern int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p ); -/*=== fraigNode.c =============================================================*/ -extern Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p ); -extern Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ); -extern Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ); -extern void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand ); -/*=== fraigPrime.c =============================================================*/ -extern int s_FraigPrimes[FRAIG_MAX_PRIMES]; -extern unsigned int Cudd_PrimeFraig( unsigned int p ); -/*=== fraigSat.c ===============================================================*/ -extern int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ); -/*=== fraigTable.c =============================================================*/ -extern Fraig_HashTable_t * Fraig_HashTableCreate( int nSize ); -extern void Fraig_HashTableFree( Fraig_HashTable_t * p ); -extern int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes ); -extern Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -extern Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -extern void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -extern int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand ); -extern int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ); -extern int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand ); -extern void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ); -extern void Fraig_TablePrintStatsS( Fraig_Man_t * pMan ); -extern void Fraig_TablePrintStatsF( Fraig_Man_t * pMan ); -extern void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan ); -extern int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv ); -/*=== fraigUtil.c ===============================================================*/ -extern int Fraig_NodeCountPis( Msat_IntVec_t * vVars, int nVarsPi ); -extern int Fraig_NodeCountSuppVars( Fraig_Man_t * p, Fraig_Node_t * pNode, int fSuppStr ); -extern int Fraig_NodesCompareSupps( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -extern int Fraig_NodeAndSimpleCase_rec( Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode ); -extern void Fraig_ManSelectBestChoice( Fraig_Man_t * p ); -extern int Fraig_BitStringCountOnes( unsigned * pString, int nWords ); -extern void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits ); -extern int Fraig_NodeIsExorType( Fraig_Node_t * pNode ); -extern int Fraig_NodeIsExor( Fraig_Node_t * pNode ); -extern int Fraig_NodeIsMuxType( Fraig_Node_t * pNode ); -extern Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE ); -extern int Fraig_ManCountExors( Fraig_Man_t * pMan ); -extern int Fraig_ManCountMuxes( Fraig_Man_t * pMan ); -extern int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ); -extern int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -extern Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ); -extern int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums ); -extern void Fraig_ManIncrementTravId( Fraig_Man_t * pMan ); -extern void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -extern int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -extern int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -/*=== fraigVec.c ===============================================================*/ -extern void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p ); - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/sat/fraig/fraigMan.c b/src/sat/fraig/fraigMan.c deleted file mode 100644 index 7fd937d5..00000000 --- a/src/sat/fraig/fraigMan.c +++ /dev/null @@ -1,540 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigMan.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Implementation of the FRAIG manager.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigMan.c,v 1.11 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -int timeSelect; -int timeAssign; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Sets the default parameters of the package.] - - Description [This set of parameters is tuned for equivalence checking.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Prove_ParamsSetDefault( Prove_Params_t * pParams ) -{ - // clean the parameter structure - memset( pParams, 0, sizeof(Prove_Params_t) ); - // general parameters - pParams->fUseFraiging = 1; // enables fraiging - pParams->fUseRewriting = 1; // enables rewriting - pParams->fUseBdds = 0; // enables BDD construction when other methods fail - pParams->fVerbose = 0; // prints verbose stats - // iterations - pParams->nItersMax = 6; // the number of iterations - // mitering - pParams->nMiteringLimitStart = 300; // starting mitering limit - pParams->nMiteringLimitMulti = 2.0; // multiplicative coefficient to increase the limit in each iteration - // rewriting (currently not used) - pParams->nRewritingLimitStart = 3; // the number of rewriting iterations - pParams->nRewritingLimitMulti = 1.0; // multiplicative coefficient to increase the limit in each iteration - // fraiging - pParams->nFraigingLimitStart = 2; // starting backtrack(conflict) limit - pParams->nFraigingLimitMulti = 8.0; // multiplicative coefficient to increase the limit in each iteration - // last-gasp BDD construction - pParams->nBddSizeLimit = 1000000; // the number of BDD nodes when construction is aborted - pParams->fBddReorder = 1; // enables dynamic BDD variable reordering - // last-gasp mitering -// pParams->nMiteringLimitLast = 1000000; // final mitering limit - pParams->nMiteringLimitLast = 0; // final mitering limit - // global SAT solver limits - pParams->nTotalBacktrackLimit = 0; // global limit on the number of backtracks - pParams->nTotalInspectLimit = 0; // global limit on the number of clause inspects -// pParams->nTotalInspectLimit = 100000000; // global limit on the number of clause inspects -} - -/**Function************************************************************* - - Synopsis [Prints out the current values of CEC engine parameters.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Prove_ParamsPrint( Prove_Params_t * pParams ) -{ - printf( "CEC enging parameters:\n" ); - printf( "Fraiging enabled: %s\n", pParams->fUseFraiging? "yes":"no" ); - printf( "Rewriting enabled: %s\n", pParams->fUseRewriting? "yes":"no" ); - printf( "BDD construction enabled: %s\n", pParams->fUseBdds? "yes":"no" ); - printf( "Verbose output enabled: %s\n", pParams->fVerbose? "yes":"no" ); - printf( "Solver iterations: %d\n", pParams->nItersMax ); - printf( "Starting mitering limit: %d\n", pParams->nMiteringLimitStart ); - printf( "Multiplicative coeficient for mitering: %.2f\n", pParams->nMiteringLimitMulti ); - printf( "Starting number of rewriting iterations: %d\n", pParams->nRewritingLimitStart ); - printf( "Multiplicative coeficient for rewriting: %.2f\n", pParams->nRewritingLimitMulti ); - printf( "Starting number of conflicts in fraiging: %d\n", pParams->nFraigingLimitMulti ); - printf( "Multiplicative coeficient for fraiging: %.2f\n", pParams->nRewritingLimitMulti ); - printf( "BDD size limit for bailing out: %.2f\n", pParams->nBddSizeLimit ); - printf( "BDD reordering enabled: %s\n", pParams->fBddReorder? "yes":"no" ); - printf( "Last-gasp mitering limit: %d\n", pParams->nMiteringLimitLast ); - printf( "Total conflict limit: %d\n", pParams->nTotalBacktrackLimit ); - printf( "Total inspection limit: %d\n", pParams->nTotalInspectLimit ); - printf( "Parameter dump complete.\n" ); -} - -/**Function************************************************************* - - Synopsis [Sets the default parameters of the package.] - - Description [This set of parameters is tuned for equivalence checking.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ParamsSetDefault( Fraig_Params_t * pParams ) -{ - memset( pParams, 0, sizeof(Fraig_Params_t) ); - pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info - pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info - pParams->nBTLimit = 99; // the max number of backtracks to perform - pParams->nSeconds = 20; // the max number of seconds to solve the miter - pParams->fFuncRed = 1; // performs only one level hashing - pParams->fFeedBack = 1; // enables solver feedback - pParams->fDist1Pats = 1; // enables distance-1 patterns - pParams->fDoSparse = 0; // performs equiv tests for sparse functions - pParams->fChoicing = 0; // enables recording structural choices - pParams->fTryProve = 1; // tries to solve the final miter - pParams->fVerbose = 0; // the verbosiness flag - pParams->fVerboseP = 0; // the verbose flag for reporting the proof - pParams->fInternal = 0; // the flag indicates the internal run - pParams->nConfLimit = 0; // the limit on the number of conflicts - pParams->nInspLimit = 0; // the limit on the number of inspections -} - -/**Function************************************************************* - - Synopsis [Sets the default parameters of the package.] - - Description [This set of parameters is tuned for complete FRAIGing.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ParamsSetDefaultFull( Fraig_Params_t * pParams ) -{ - memset( pParams, 0, sizeof(Fraig_Params_t) ); - pParams->nPatsRand = FRAIG_PATTERNS_RANDOM; // the number of words of random simulation info - pParams->nPatsDyna = FRAIG_PATTERNS_DYNAMIC; // the number of words of dynamic simulation info - pParams->nBTLimit = -1; // the max number of backtracks to perform - pParams->nSeconds = 20; // the max number of seconds to solve the miter - pParams->fFuncRed = 1; // performs only one level hashing - pParams->fFeedBack = 1; // enables solver feedback - pParams->fDist1Pats = 1; // enables distance-1 patterns - pParams->fDoSparse = 1; // performs equiv tests for sparse functions - pParams->fChoicing = 0; // enables recording structural choices - pParams->fTryProve = 0; // tries to solve the final miter - pParams->fVerbose = 0; // the verbosiness flag - pParams->fVerboseP = 0; // the verbose flag for reporting the proof - pParams->fInternal = 0; // the flag indicates the internal run - pParams->nConfLimit = 0; // the limit on the number of conflicts - pParams->nInspLimit = 0; // the limit on the number of inspections -} - -/**Function************************************************************* - - Synopsis [Creates the new FRAIG manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Man_t * Fraig_ManCreate( Fraig_Params_t * pParams ) -{ - Fraig_Params_t Params; - Fraig_Man_t * p; - - // set the random seed for simulation -// srand( 0xFEEDDEAF ); - srand( 0xDEADCAFE ); - - // set parameters for equivalence checking - if ( pParams == NULL ) - Fraig_ParamsSetDefault( pParams = &Params ); - // adjust the amount of simulation info - if ( pParams->nPatsRand < 128 ) - pParams->nPatsRand = 128; - if ( pParams->nPatsRand > 32768 ) - pParams->nPatsRand = 32768; - if ( pParams->nPatsDyna < 128 ) - pParams->nPatsDyna = 128; - if ( pParams->nPatsDyna > 32768 ) - pParams->nPatsDyna = 32768; - // if reduction is not performed, allocate minimum simulation info - if ( !pParams->fFuncRed ) - pParams->nPatsRand = pParams->nPatsDyna = 128; - - // start the manager - p = ALLOC( Fraig_Man_t, 1 ); - memset( p, 0, sizeof(Fraig_Man_t) ); - - // set the default parameters - p->nWordsRand = FRAIG_NUM_WORDS( pParams->nPatsRand ); // the number of words of random simulation info - p->nWordsDyna = FRAIG_NUM_WORDS( pParams->nPatsDyna ); // the number of patterns for dynamic simulation info - p->nBTLimit = pParams->nBTLimit; // -1 means infinite backtrack limit - p->nSeconds = pParams->nSeconds; // the timeout for the final miter - p->fFuncRed = pParams->fFuncRed; // enables functional reduction (otherwise, only one-level hashing is performed) - p->fFeedBack = pParams->fFeedBack; // enables solver feedback (the use of counter-examples in simulation) - p->fDist1Pats = pParams->fDist1Pats; // enables solver feedback (the use of counter-examples in simulation) - p->fDoSparse = pParams->fDoSparse; // performs equivalence checking for sparse functions (whose sim-info is 0) - p->fChoicing = pParams->fChoicing; // disable accumulation of structural choices (keeps only the first choice) - p->fTryProve = pParams->fTryProve; // disable accumulation of structural choices (keeps only the first choice) - p->fVerbose = pParams->fVerbose; // disable verbose output - p->fVerboseP = pParams->fVerboseP; // disable verbose output - p->nInspLimit = pParams->nInspLimit; // the limit on the number of inspections - - // start memory managers - p->mmNodes = Fraig_MemFixedStart( sizeof(Fraig_Node_t) ); - p->mmSims = Fraig_MemFixedStart( sizeof(unsigned) * (p->nWordsRand + p->nWordsDyna) ); - // allocate node arrays - p->vInputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary inputs - p->vOutputs = Fraig_NodeVecAlloc( 1000 ); // the array of primary outputs - p->vNodes = Fraig_NodeVecAlloc( 1000 ); // the array of internal nodes - // start the tables - p->pTableS = Fraig_HashTableCreate( 1000 ); // hashing by structure - p->pTableF = Fraig_HashTableCreate( 1000 ); // hashing by function - p->pTableF0 = Fraig_HashTableCreate( 1000 ); // hashing by function (for sparse functions) - // create the constant node - p->pConst1 = Fraig_NodeCreateConst( p ); - // initialize SAT solver feedback data structures - Fraig_FeedBackInit( p ); - // initialize other variables - p->vProj = Msat_IntVecAlloc( 10 ); - p->nTravIds = 1; - p->nTravIds2 = 1; - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManFree( Fraig_Man_t * p ) -{ - int i; - if ( p->fVerbose ) - { - if ( p->fChoicing ) Fraig_ManReportChoices( p ); - Fraig_ManPrintStats( p ); -// Fraig_TablePrintStatsS( p ); -// Fraig_TablePrintStatsF( p ); -// Fraig_TablePrintStatsF0( p ); - } - - for ( i = 0; i < p->vNodes->nSize; i++ ) - if ( p->vNodes->pArray[i]->vFanins ) - { - Fraig_NodeVecFree( p->vNodes->pArray[i]->vFanins ); - p->vNodes->pArray[i]->vFanins = NULL; - } - - if ( p->vInputs ) Fraig_NodeVecFree( p->vInputs ); - if ( p->vNodes ) Fraig_NodeVecFree( p->vNodes ); - if ( p->vOutputs ) Fraig_NodeVecFree( p->vOutputs ); - - if ( p->pTableS ) Fraig_HashTableFree( p->pTableS ); - if ( p->pTableF ) Fraig_HashTableFree( p->pTableF ); - if ( p->pTableF0 ) Fraig_HashTableFree( p->pTableF0 ); - - if ( p->pSat ) Msat_SolverFree( p->pSat ); - if ( p->vProj ) Msat_IntVecFree( p->vProj ); - if ( p->vCones ) Fraig_NodeVecFree( p->vCones ); - if ( p->vPatsReal ) Msat_IntVecFree( p->vPatsReal ); - if ( p->pModel ) free( p->pModel ); - - Fraig_MemFixedStop( p->mmNodes, 0 ); - Fraig_MemFixedStop( p->mmSims, 0 ); - - if ( p->pSuppS ) - { - FREE( p->pSuppS[0] ); - FREE( p->pSuppS ); - } - if ( p->pSuppF ) - { - FREE( p->pSuppF[0] ); - FREE( p->pSuppF ); - } - - FREE( p->ppOutputNames ); - FREE( p->ppInputNames ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Prepares the SAT solver to run on the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManCreateSolver( Fraig_Man_t * p ) -{ - extern int timeSelect; - extern int timeAssign; - assert( p->pSat == NULL ); - // allocate data for SAT solving - p->pSat = Msat_SolverAlloc( 500, 1, 1, 1, 1, 0 ); - p->vVarsInt = Msat_SolverReadConeVars( p->pSat ); - p->vAdjacents = Msat_SolverReadAdjacents( p->pSat ); - p->vVarsUsed = Msat_SolverReadVarsUsed( p->pSat ); - timeSelect = 0; - timeAssign = 0; -} - - -/**Function************************************************************* - - Synopsis [Deallocates the mapping manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManPrintStats( Fraig_Man_t * p ) -{ - double nMemory; - int clk = clock(); - nMemory = ((double)(p->vInputs->nSize + p->vNodes->nSize) * - (sizeof(Fraig_Node_t) + sizeof(unsigned)*(p->nWordsRand + p->nWordsDyna) /*+ p->nSuppWords*sizeof(unsigned)*/))/(1<<20); - printf( "Words: Random = %d. Dynamic = %d. Used = %d. Memory = %0.2f Mb.\n", - p->nWordsRand, p->nWordsDyna, p->iWordPerm, nMemory ); - printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", - p->nSatProof, p->nSatCounter, p->nSatFails, p->nSatFailsReal, p->nSatZeros ); - printf( "Nodes: Final = %d. Total = %d. Mux = %d. (Exor = %d.) ClaVars = %d.\n", - Fraig_CountNodes(p,0), p->vNodes->nSize, Fraig_ManCountMuxes(p), Fraig_ManCountExors(p), p->nVarsClauses ); - if ( p->pSat ) Msat_SolverPrintStats( p->pSat ); - Fraig_PrintTime( "AIG simulation ", p->timeSims ); - Fraig_PrintTime( "AIG traversal ", p->timeTrav ); - Fraig_PrintTime( "Solver feedback ", p->timeFeed ); - Fraig_PrintTime( "SAT solving ", p->timeSat ); - Fraig_PrintTime( "Network update ", p->timeToNet ); - Fraig_PrintTime( "TOTAL RUNTIME ", p->timeTotal ); - if ( p->time1 > 0 ) { Fraig_PrintTime( "time1", p->time1 ); } - if ( p->time2 > 0 ) { Fraig_PrintTime( "time2", p->time2 ); } - if ( p->time3 > 0 ) { Fraig_PrintTime( "time3", p->time3 ); } - if ( p->time4 > 0 ) { Fraig_PrintTime( "time4", p->time4 ); } -// PRT( "Selection ", timeSelect ); -// PRT( "Assignment", timeAssign ); -} - -/**Function************************************************************* - - Synopsis [Allocates simulation information for all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_UtilInfoAlloc( int nSize, int nWords, bool fClean ) -{ - Fraig_NodeVec_t * vInfo; - unsigned * pUnsigned; - int i; - assert( nSize > 0 && nWords > 0 ); - vInfo = Fraig_NodeVecAlloc( nSize ); - pUnsigned = ALLOC( unsigned, nSize * nWords ); - vInfo->pArray[0] = (Fraig_Node_t *)pUnsigned; - if ( fClean ) - memset( pUnsigned, 0, sizeof(unsigned) * nSize * nWords ); - for ( i = 1; i < nSize; i++ ) - vInfo->pArray[i] = (Fraig_Node_t *)(((unsigned *)vInfo->pArray[i-1]) + nWords); - vInfo->nSize = nSize; - return vInfo; -} - -/**Function************************************************************* - - Synopsis [Returns simulation info of all nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_ManGetSimInfo( Fraig_Man_t * p ) -{ - Fraig_NodeVec_t * vInfo; - Fraig_Node_t * pNode; - unsigned * pUnsigned; - int nRandom, nDynamic; - int i, k, nWords; - - nRandom = Fraig_ManReadPatternNumRandom( p ); - nDynamic = Fraig_ManReadPatternNumDynamic( p ); - nWords = nRandom / 32 + nDynamic / 32; - - vInfo = Fraig_UtilInfoAlloc( p->vNodes->nSize, nWords, 0 ); - for ( i = 0; i < p->vNodes->nSize; i++ ) - { - pNode = p->vNodes->pArray[i]; - assert( i == pNode->Num ); - pUnsigned = (unsigned *)vInfo->pArray[i]; - for ( k = 0; k < nRandom / 32; k++ ) - pUnsigned[k] = pNode->puSimR[k]; - for ( k = 0; k < nDynamic / 32; k++ ) - pUnsigned[nRandom / 32 + k] = pNode->puSimD[k]; - } - return vInfo; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if A v B is always true based on the siminfo.] - - Description [A v B is always true iff A' * B' is always false.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManCheckClauseUsingSimInfo( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ) -{ - int fCompl1, fCompl2, i; - - fCompl1 = 1 ^ Fraig_IsComplement(pNode1) ^ Fraig_Regular(pNode1)->fInv; - fCompl2 = 1 ^ Fraig_IsComplement(pNode2) ^ Fraig_Regular(pNode2)->fInv; - - pNode1 = Fraig_Regular(pNode1); - pNode2 = Fraig_Regular(pNode2); - assert( pNode1 != pNode2 ); - - // check the simulation info - if ( fCompl1 && fCompl2 ) - { - for ( i = 0; i < p->nWordsRand; i++ ) - if ( ~pNode1->puSimR[i] & ~pNode2->puSimR[i] ) - return 0; - for ( i = 0; i < p->iWordStart; i++ ) - if ( ~pNode1->puSimD[i] & ~pNode2->puSimD[i] ) - return 0; - return 1; - } - if ( !fCompl1 && fCompl2 ) - { - for ( i = 0; i < p->nWordsRand; i++ ) - if ( pNode1->puSimR[i] & ~pNode2->puSimR[i] ) - return 0; - for ( i = 0; i < p->iWordStart; i++ ) - if ( pNode1->puSimD[i] & ~pNode2->puSimD[i] ) - return 0; - return 1; - } - if ( fCompl1 && !fCompl2 ) - { - for ( i = 0; i < p->nWordsRand; i++ ) - if ( ~pNode1->puSimR[i] & pNode2->puSimR[i] ) - return 0; - for ( i = 0; i < p->iWordStart; i++ ) - if ( ~pNode1->puSimD[i] & pNode2->puSimD[i] ) - return 0; - return 1; - } -// if ( fCompl1 && fCompl2 ) - { - for ( i = 0; i < p->nWordsRand; i++ ) - if ( pNode1->puSimR[i] & pNode2->puSimR[i] ) - return 0; - for ( i = 0; i < p->iWordStart; i++ ) - if ( pNode1->puSimD[i] & pNode2->puSimD[i] ) - return 0; - return 1; - } -} - -/**Function************************************************************* - - Synopsis [Adds clauses to the solver.] - - Description [This procedure is used to add external clauses to the solver. - The clauses are given by sets of nodes. Each node stands for one literal. - If the node is complemented, the literal is negated.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManAddClause( Fraig_Man_t * p, Fraig_Node_t ** ppNodes, int nNodes ) -{ - Fraig_Node_t * pNode; - int i, fComp, RetValue; - if ( p->pSat == NULL ) - Fraig_ManCreateSolver( p ); - // create four clauses - Msat_IntVecClear( p->vProj ); - for ( i = 0; i < nNodes; i++ ) - { - pNode = Fraig_Regular(ppNodes[i]); - fComp = Fraig_IsComplement(ppNodes[i]); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); -// printf( "%d(%d) ", pNode->Num, fComp ); - } -// printf( "\n" ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/sat/fraig/fraigMem.c b/src/sat/fraig/fraigMem.c deleted file mode 100644 index 500431c6..00000000 --- a/src/sat/fraig/fraigMem.c +++ /dev/null @@ -1,246 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigMem.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Fixed-size-entry memory manager for the FRAIG package.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigMem.c,v 1.4 2005/07/08 01:01:31 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Fraig_MemFixed_t_ -{ - // information about individual entries - int nEntrySize; // the size of one entry - int nEntriesAlloc; // the total number of entries allocated - int nEntriesUsed; // the number of entries in use - int nEntriesMax; // the max number of entries in use - char * pEntriesFree; // the linked list of free entries - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Starts the internal memory manager.] - - Description [Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_MemFixed_t * Fraig_MemFixedStart( int nEntrySize ) -{ - Fraig_MemFixed_t * p; - - p = ALLOC( Fraig_MemFixed_t, 1 ); - memset( p, 0, sizeof(Fraig_MemFixed_t) ); - - p->nEntrySize = nEntrySize; - p->nEntriesAlloc = 0; - p->nEntriesUsed = 0; - p->pEntriesFree = NULL; - - if ( nEntrySize * (1 << 10) < (1<<16) ) - p->nChunkSize = (1 << 10); - else - p->nChunkSize = (1<<16) / nEntrySize; - if ( p->nChunkSize < 8 ) - p->nChunkSize = 8; - - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the internal memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_MemFixedStop( Fraig_MemFixed_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", - p->nEntrySize, p->nChunkSize, p->nChunks ); - printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", - p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Extracts one entry from the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Fraig_MemFixedEntryFetch( Fraig_MemFixed_t * p ) -{ - char * pTemp; - int i; - - // check if there are still free entries - if ( p->nEntriesUsed == p->nEntriesAlloc ) - { // need to allocate more entries - assert( p->pEntriesFree == NULL ); - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); - p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; - // transform these entries into a linked list - pTemp = p->pEntriesFree; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pEntriesFree; - // add to the number of entries allocated - p->nEntriesAlloc += p->nChunkSize; - } - // incrememt the counter of used entries - p->nEntriesUsed++; - if ( p->nEntriesMax < p->nEntriesUsed ) - p->nEntriesMax = p->nEntriesUsed; - // return the first entry in the free entry list - pTemp = p->pEntriesFree; - p->pEntriesFree = *((char **)pTemp); - return pTemp; -} - -/**Function************************************************************* - - Synopsis [Returns one entry into the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_MemFixedEntryRecycle( Fraig_MemFixed_t * p, char * pEntry ) -{ - // decrement the counter of used entries - p->nEntriesUsed--; - // add the entry to the linked list of free entries - *((char **)pEntry) = p->pEntriesFree; - p->pEntriesFree = pEntry; -} - -/**Function************************************************************* - - Synopsis [Frees all associated memory and resets the manager.] - - Description [Relocates all the memory except the first chunk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_MemFixedRestart( Fraig_MemFixed_t * p ) -{ - int i; - char * pTemp; - - // deallocate all chunks except the first one - for ( i = 1; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - p->nChunks = 1; - // transform these entries into a linked list - pTemp = p->pChunks[0]; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // set the free entry list - p->pEntriesFree = p->pChunks[0]; - // set the correct statistics - p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; - p->nMemoryUsed = 0; - p->nEntriesAlloc = p->nChunkSize; - p->nEntriesUsed = 0; -} - -/**Function************************************************************* - - Synopsis [Reports the memory usage.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_MemFixedReadMemUsage( Fraig_MemFixed_t * p ) -{ - return p->nMemoryAlloc; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/fraig/fraigNode.c b/src/sat/fraig/fraigNode.c deleted file mode 100644 index 6e3d3c7d..00000000 --- a/src/sat/fraig/fraigNode.c +++ /dev/null @@ -1,313 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigNode.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Implementation of the FRAIG node.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigNode.c,v 1.3 2005/07/08 01:01:32 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// returns the complemented attribute of the node -#define Fraig_NodeIsSimComplement(p) (Fraig_IsComplement(p)? !(Fraig_Regular(p)->fInv) : (p)->fInv) - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates the constant 1 node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeCreateConst( Fraig_Man_t * p ) -{ - Fraig_Node_t * pNode; - - // create the node - pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); - memset( pNode, 0, sizeof(Fraig_Node_t) ); - - // assign the number and add to the array of nodes - pNode->Num = p->vNodes->nSize; - Fraig_NodeVecPush( p->vNodes, pNode ); - pNode->NumPi = -1; // this is not a PI, so its number is -1 - pNode->Level = 0; // just like a PI, it has 0 level - pNode->nRefs = 1; // it is a persistent node, which comes referenced - pNode->fInv = 1; // the simulation info is complemented - - // create the simulation info - pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - pNode->puSimD = pNode->puSimR + p->nWordsRand; - memset( pNode->puSimR, 0, sizeof(unsigned) * p->nWordsRand ); - memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); - - // count the number of ones in the simulation vector - pNode->nOnes = p->nWordsRand * sizeof(unsigned) * 8; - - // insert it into the hash table - Fraig_HashTableLookupF0( p, pNode ); - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates a primary input node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeCreatePi( Fraig_Man_t * p ) -{ - Fraig_Node_t * pNode, * pNodeRes; - int i, clk; - - // create the node - pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); - memset( pNode, 0, sizeof(Fraig_Node_t) ); - pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - pNode->puSimD = pNode->puSimR + p->nWordsRand; - memset( pNode->puSimD, 0, sizeof(unsigned) * p->nWordsDyna ); - - // assign the number and add to the array of nodes - pNode->Num = p->vNodes->nSize; - Fraig_NodeVecPush( p->vNodes, pNode ); - - // assign the PI number and add to the array of primary inputs - pNode->NumPi = p->vInputs->nSize; - Fraig_NodeVecPush( p->vInputs, pNode ); - - pNode->Level = 0; // PI has 0 level - pNode->nRefs = 1; // it is a persistent node, which comes referenced - pNode->fInv = 0; // the simulation info of the PI is not complemented - - // derive the simulation info for the new node -clk = clock(); - // set the random simulation info for the primary input - pNode->uHashR = 0; - for ( i = 0; i < p->nWordsRand; i++ ) - { - // generate the simulation info - pNode->puSimR[i] = FRAIG_RANDOM_UNSIGNED; - // for reasons that take very long to explain, it makes sense to have (0000000...) - // pattern in the set (this helps if we need to return the counter-examples) - if ( i == 0 ) - pNode->puSimR[i] <<= 1; - // compute the hash key - pNode->uHashR ^= pNode->puSimR[i] * s_FraigPrimes[i]; - } - // count the number of ones in the simulation vector - pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); - - // set the systematic simulation info for the primary input - pNode->uHashD = 0; - for ( i = 0; i < p->iWordStart; i++ ) - { - // generate the simulation info - pNode->puSimD[i] = FRAIG_RANDOM_UNSIGNED; - // compute the hash key - pNode->uHashD ^= pNode->puSimD[i] * s_FraigPrimes[i]; - } -p->timeSims += clock() - clk; - - // insert it into the hash table - pNodeRes = Fraig_HashTableLookupF( p, pNode ); - assert( pNodeRes == NULL ); - // add to the runtime of simulation - return pNode; -} - -/**Function************************************************************* - - Synopsis [Creates a new node.] - - Description [This procedure should be called to create the constant - node and the PI nodes first.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeCreate( Fraig_Man_t * p, Fraig_Node_t * p1, Fraig_Node_t * p2 ) -{ - Fraig_Node_t * pNode; - int clk; - - // create the node - pNode = (Fraig_Node_t *)Fraig_MemFixedEntryFetch( p->mmNodes ); - memset( pNode, 0, sizeof(Fraig_Node_t) ); - - // assign the children - pNode->p1 = p1; Fraig_Ref(p1); Fraig_Regular(p1)->nRefs++; - pNode->p2 = p2; Fraig_Ref(p2); Fraig_Regular(p2)->nRefs++; - - // assign the number and add to the array of nodes - pNode->Num = p->vNodes->nSize; - Fraig_NodeVecPush( p->vNodes, pNode ); - - // assign the PI number - pNode->NumPi = -1; - - // compute the level of this node - pNode->Level = 1 + FRAIG_MAX(Fraig_Regular(p1)->Level, Fraig_Regular(p2)->Level); - pNode->fInv = Fraig_NodeIsSimComplement(p1) & Fraig_NodeIsSimComplement(p2); - pNode->fFailTfo = Fraig_Regular(p1)->fFailTfo | Fraig_Regular(p2)->fFailTfo; - - // derive the simulation info -clk = clock(); - // allocate memory for the simulation info - pNode->puSimR = (unsigned *)Fraig_MemFixedEntryFetch( p->mmSims ); - pNode->puSimD = pNode->puSimR + p->nWordsRand; - // derive random simulation info - pNode->uHashR = 0; - Fraig_NodeSimulate( pNode, 0, p->nWordsRand, 1 ); - // derive dynamic simulation info - pNode->uHashD = 0; - Fraig_NodeSimulate( pNode, 0, p->iWordStart, 0 ); - // count the number of ones in the random simulation info - pNode->nOnes = Fraig_BitStringCountOnes( pNode->puSimR, p->nWordsRand ); - if ( pNode->fInv ) - pNode->nOnes = p->nWordsRand * 32 - pNode->nOnes; - // add to the runtime of simulation -p->timeSims += clock() - clk; - -#ifdef FRAIG_ENABLE_FANOUTS - // create the fanout info - Fraig_NodeAddFaninFanout( Fraig_Regular(p1), pNode ); - Fraig_NodeAddFaninFanout( Fraig_Regular(p2), pNode ); -#endif - return pNode; -} - - -/**Function************************************************************* - - Synopsis [Simulates the node.] - - Description [Simulates the random or dynamic simulation info through - the node. Uses phases of the children to determine their real simulation - info. Uses phase of the node to determine the way its simulation info - is stored. The resulting info is guaranteed to be 0 for the first pattern.] - - SideEffects [This procedure modified the hash value of the simulation info.] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeSimulate( Fraig_Node_t * pNode, int iWordStart, int iWordStop, int fUseRand ) -{ - unsigned * pSims, * pSims1, * pSims2; - unsigned uHash; - int fCompl, fCompl1, fCompl2, i; - - assert( !Fraig_IsComplement(pNode) ); - - // get hold of the simulation information - pSims = fUseRand? pNode->puSimR : pNode->puSimD; - pSims1 = fUseRand? Fraig_Regular(pNode->p1)->puSimR : Fraig_Regular(pNode->p1)->puSimD; - pSims2 = fUseRand? Fraig_Regular(pNode->p2)->puSimR : Fraig_Regular(pNode->p2)->puSimD; - - // get complemented attributes of the children using their random info - fCompl = pNode->fInv; - fCompl1 = Fraig_NodeIsSimComplement(pNode->p1); - fCompl2 = Fraig_NodeIsSimComplement(pNode->p2); - - // simulate - uHash = 0; - if ( fCompl1 && fCompl2 ) - { - if ( fCompl ) - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (pSims1[i] | pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - else - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = ~(pSims1[i] | pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - } - else if ( fCompl1 && !fCompl2 ) - { - if ( fCompl ) - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (pSims1[i] | ~pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - else - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (~pSims1[i] & pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - } - else if ( !fCompl1 && fCompl2 ) - { - if ( fCompl ) - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (~pSims1[i] | pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - else - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (pSims1[i] & ~pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - } - else // if ( !fCompl1 && !fCompl2 ) - { - if ( fCompl ) - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = ~(pSims1[i] & pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - else - for ( i = iWordStart; i < iWordStop; i++ ) - { - pSims[i] = (pSims1[i] & pSims2[i]); - uHash ^= pSims[i] * s_FraigPrimes[i]; - } - } - - if ( fUseRand ) - pNode->uHashR ^= uHash; - else - pNode->uHashD ^= uHash; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/sat/fraig/fraigPrime.c b/src/sat/fraig/fraigPrime.c deleted file mode 100644 index 127ad478..00000000 --- a/src/sat/fraig/fraigPrime.c +++ /dev/null @@ -1,144 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigPrime.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [The table of the first 1000 primes.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigPrime.c,v 1.4 2005/07/08 01:01:32 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// The 1,024 smallest prime numbers used to compute the hash value -// http://www.math.utah.edu/~alfeld/math/primelist.html -int s_FraigPrimes[FRAIG_MAX_PRIMES] = { 2, 3, 5, -7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, -101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, -193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, -293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, -409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, -521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, -641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, -757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, -881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, -1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, -1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, -1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, -1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423, -1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, -1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597, 1601, -1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693, 1697, 1699, -1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, -1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, -1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, -2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, -2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267, -2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, -2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, -2467, 2473, 2477, 2503, 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, -2609, 2617, 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, -2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, -2797, 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, -2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011, 3019, 3023, -3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, -3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259, 3271, -3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347, 3359, 3361, 3371, 3373, -3389, 3391, 3407, 3413, 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, -3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, -3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, -3719, 3727, 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, -3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, -3943, 3947, 3967, 3989, 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, -4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, -4201, 4211, 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, -4289, 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423, -4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547, -4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, -4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759, 4783, 4787, 4789, -4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, -4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011, -5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101, 5107, 5113, 5119, 5147, -5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, -5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399, 5407, 5413, -5417, 5419, 5431, 5437, 5441, 5443, 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, -5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, -5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, -5749, 5779, 5783, 5791, 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, -5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007, -6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, -6131, 6133, 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229, 6247, -6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329, 6337, 6343, -6353, 6359, 6361, 6367, 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, -6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577, 6581, 6599, 6607, -6619, 6637, 6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, -6737, 6761, 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841, 6857, -6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971, -6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, -7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211, 7213, 7219, 7229, -7237, 7243, 7247, 7253, 7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, -7393, 7411, 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517, -7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573, 7577, 7583, 7589, 7591, 7603, -7607, 7621, 7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, -7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853, 7867, 7873, -7877, 7879, 7883, 7901, 7907, 7919, 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, -8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117, 8123, -8147, 8161 }; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function******************************************************************** - - Synopsis [Returns the next prime >= p.] - - Description [Copied from CUDD, for stand-aloneness.] - - SideEffects [None] - - SeeAlso [] - -******************************************************************************/ -unsigned int Cudd_PrimeFraig( unsigned int p) -{ - int i,pn; - - p--; - do { - p++; - if (p&1) { - pn = 1; - i = 3; - while ((unsigned) (i * i) <= p) { - if (p % i == 0) { - pn = 0; - break; - } - i += 2; - } - } else { - pn = 0; - } - } while (!pn); - return(p); - -} /* end of Cudd_Prime */ - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/fraig/fraigSat.c b/src/sat/fraig/fraigSat.c deleted file mode 100644 index 53057fc3..00000000 --- a/src/sat/fraig/fraigSat.c +++ /dev/null @@ -1,1455 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigSat.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Proving functional equivalence using SAT.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigSat.c,v 1.10 2005/07/08 01:01:32 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" -#include "math.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -static void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ); -static void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ); -static void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); -static void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); - -static void Fraig_SupergateAddClauses( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper ); -static void Fraig_SupergateAddClausesExor( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -static void Fraig_SupergateAddClausesMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -//static void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -static void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ); -static void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ); - -extern void * Msat_ClauseVecReadEntry( void * p, int i ); - -// The lesson learned seems to be that variable should be in reverse topological order -// from the output of the miter. The ordering of adjacency lists is very important. -// The best way seems to be fanins followed by fanouts. Slight changes to this order -// leads to big degradation in quality. - -static int nMuxes; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Checks equivalence of two nodes.] - - Description [Returns 1 iff the nodes are equivalent.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodesAreEqual( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit, int nTimeLimit ) -{ - if ( pNode1 == pNode2 ) - return 1; - if ( pNode1 == Fraig_Not(pNode2) ) - return 0; - return Fraig_NodeIsEquivalent( p, Fraig_Regular(pNode1), Fraig_Regular(pNode2), nBTLimit, nTimeLimit ); -} - -/**Function************************************************************* - - Synopsis [Tries to prove the final miter.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManProveMiter( Fraig_Man_t * p ) -{ - Fraig_Node_t * pNode; - int i, clk; - - if ( !p->fTryProve ) - return; - - clk = clock(); - // consider all outputs of the multi-output miter - for ( i = 0; i < p->vOutputs->nSize; i++ ) - { - pNode = Fraig_Regular(p->vOutputs->pArray[i]); - // skip already constant nodes - if ( pNode == p->pConst1 ) - continue; - // skip nodes that are different according to simulation - if ( !Fraig_CompareSimInfo( pNode, p->pConst1, p->nWordsRand, 1 ) ) - continue; - if ( Fraig_NodeIsEquivalent( p, p->pConst1, pNode, -1, p->nSeconds ) ) - { - if ( Fraig_IsComplement(p->vOutputs->pArray[i]) ^ Fraig_NodeComparePhase(p->pConst1, pNode) ) - p->vOutputs->pArray[i] = Fraig_Not(p->pConst1); - else - p->vOutputs->pArray[i] = p->pConst1; - } - } - if ( p->fVerboseP ) - { -// PRT( "Final miter proof time", clock() - clk ); - } -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the miter is unsat; 0 if sat; -1 if undecided.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManCheckMiter( Fraig_Man_t * p ) -{ - Fraig_Node_t * pNode; - int i; - FREE( p->pModel ); - for ( i = 0; i < p->vOutputs->nSize; i++ ) - { - // get the output node (it can be complemented!) - pNode = p->vOutputs->pArray[i]; - // if the miter is constant 0, the problem is UNSAT - if ( pNode == Fraig_Not(p->pConst1) ) - continue; - // consider the special case when the miter is constant 1 - if ( pNode == p->pConst1 ) - { - // in this case, any counter example will do to distinquish it from constant 0 - // here we pick the counter example composed of all zeros - p->pModel = Fraig_ManAllocCounterExample( p ); - return 0; - } - // save the counter example - p->pModel = Fraig_ManSaveCounterExample( p, pNode ); - // if the model is not found, return undecided - if ( p->pModel == NULL ) - return -1; - else - return 0; - } - return 1; -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_MarkTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return 0; - pNode->TravId = pMan->nTravIds; - // skip the PI node - if ( pNode->NumPi >= 0 ) - return 1; - // check the children - return Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p1) ) + - Fraig_MarkTfi_rec( pMan, Fraig_Regular(pNode->p2) ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_MarkTfi2_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return 0; - // skip the boundary node - if ( pNode->TravId == pMan->nTravIds-1 ) - { - pNode->TravId = pMan->nTravIds; - return 1; - } - pNode->TravId = pMan->nTravIds; - // skip the PI node - if ( pNode->NumPi >= 0 ) - return 1; - // check the children - return Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p1) ) + - Fraig_MarkTfi2_rec( pMan, Fraig_Regular(pNode->p2) ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_MarkTfi3_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return 1; - // skip the boundary node - if ( pNode->TravId == pMan->nTravIds-1 ) - { - pNode->TravId = pMan->nTravIds; - return 1; - } - pNode->TravId = pMan->nTravIds; - // skip the PI node - if ( pNode->NumPi >= 0 ) - return 0; - // check the children - return Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p1) ) * - Fraig_MarkTfi3_rec( pMan, Fraig_Regular(pNode->p2) ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_VarsStudy( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - int NumPis, NumCut, fContain; - - // mark the TFI of pNew - p->nTravIds++; - NumPis = Fraig_MarkTfi_rec( p, pNew ); - printf( "(%d)(%d,%d):", NumPis, pOld->Level, pNew->Level ); - - // check if the old is in the TFI - if ( pOld->TravId == p->nTravIds ) - { - printf( "* " ); - return; - } - - // count the boundary of nodes in pOld - p->nTravIds++; - NumCut = Fraig_MarkTfi2_rec( p, pOld ); - printf( "%d", NumCut ); - - // check if the new is contained in the old's support - p->nTravIds++; - fContain = Fraig_MarkTfi3_rec( p, pNew ); - printf( "%c ", fContain? '+':'-' ); -} - - -/**Function************************************************************* - - Synopsis [Checks whether two nodes are functinally equivalent.] - - Description [The flag (fComp) tells whether the nodes to be checked - are in the opposite polarity. The second flag (fSkipZeros) tells whether - the checking should be performed if the simulation vectors are zeros. - Returns 1 if the nodes are equivalent; 0 othewise.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsEquivalent( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit, int nTimeLimit ) -{ - int RetValue, RetValue1, i, fComp, clk; - int fVerbose = 0; - int fSwitch = 0; - - // make sure the nodes are not complemented - assert( !Fraig_IsComplement(pNew) ); - assert( !Fraig_IsComplement(pOld) ); - assert( pNew != pOld ); - - // if at least one of the nodes is a failed node, perform adjustments: - // if the backtrack limit is small, simply skip this node - // if the backtrack limit is > 10, take the quare root of the limit - if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) - { - p->nSatFails++; -// return 0; -// if ( nBTLimit > 10 ) -// nBTLimit /= 10; - if ( nBTLimit <= 10 ) - return 0; - nBTLimit = (int)sqrt(nBTLimit); -// fSwitch = 1; - } - - p->nSatCalls++; - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - Fraig_ManCreateSolver( p ); - // make sure the SAT solver has enough variables - for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) - Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); - - - -/* - { - Fraig_Node_t * ppNodes[2] = { pOld, pNew }; - extern void Fraig_MappingShowNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppRoots, int nRoots, char * pFileName ); - Fraig_MappingShowNodes( p, ppNodes, 2, "temp_aig" ); - } -*/ - - nMuxes = 0; - - - // get the logic cone -clk = clock(); -// Fraig_VarsStudy( p, pOld, pNew ); - Fraig_OrderVariables( p, pOld, pNew ); -// Fraig_PrepareCones( p, pOld, pNew ); -p->timeTrav += clock() - clk; - -// printf( "The number of MUXes detected = %d (%5.2f %% of logic). ", nMuxes, 300.0*nMuxes/(p->vNodes->nSize - p->vInputs->nSize) ); -// PRT( "Time", clock() - clk ); - -if ( fVerbose ) - printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) ); - - - // prepare variable activity - Fraig_SetActivity( p, pOld, pNew ); - - // get the complemented attribute - fComp = Fraig_NodeComparePhase( pOld, pNew ); -//Msat_SolverPrintClauses( p->pSat ); - - //////////////////////////////////////////// - // prepare the solver to run incrementally on these variables -//clk = clock(); - Msat_SolverPrepare( p->pSat, p->vVarsInt ); -//p->time3 += clock() - clk; - - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); - -//Msat_SolverWriteDimacs( p->pSat, "temp_fraig.cnf" ); - - // run the solver -clk = clock(); - RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit ); -p->timeSat += clock() - clk; - - if ( RetValue1 == MSAT_FALSE ) - { -//p->time1 += clock() - clk; - -if ( fVerbose ) -{ - printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); -PRT( "time", clock() - clk ); -} - - // add the clause - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - // continue solving the other implication - } - else if ( RetValue1 == MSAT_TRUE ) - { -//p->time2 += clock() - clk; - -if ( fVerbose ) -{ - printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); -PRT( "time", clock() - clk ); -} - - // record the counter example - Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); - -// if ( pOld->fFailTfo || pNew->fFailTfo ) -// printf( "*" ); -// printf( "s(%d)", pNew->Level ); - if ( fSwitch ) - printf( "s(%d)", pNew->Level ); - p->nSatCounter++; - return 0; - } - else // if ( RetValue1 == MSAT_UNKNOWN ) - { -p->time3 += clock() - clk; - -// if ( pOld->fFailTfo || pNew->fFailTfo ) -// printf( "*" ); -// printf( "T(%d)", pNew->Level ); - - // mark the node as the failed node - if ( pOld != p->pConst1 ) - pOld->fFailTfo = 1; - pNew->fFailTfo = 1; -// p->nSatFails++; - if ( fSwitch ) - printf( "T(%d)", pNew->Level ); - p->nSatFailsReal++; - return 0; - } - - // if the old node was constant 0, we already know the answer - if ( pOld == p->pConst1 ) - return 1; - - //////////////////////////////////////////// - // prepare the solver to run incrementally -//clk = clock(); - Msat_SolverPrepare( p->pSat, p->vVarsInt ); -//p->time3 += clock() - clk; - // solve under assumptions - // A = 0; B = 1 OR A = 0; B = 0 - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); - // run the solver -clk = clock(); - RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, nTimeLimit ); -p->timeSat += clock() - clk; - - if ( RetValue1 == MSAT_FALSE ) - { -//p->time1 += clock() - clk; - -if ( fVerbose ) -{ - printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); -PRT( "time", clock() - clk ); -} - - // add the clause - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - // continue solving the other implication - } - else if ( RetValue1 == MSAT_TRUE ) - { -//p->time2 += clock() - clk; - -if ( fVerbose ) -{ - printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); -PRT( "time", clock() - clk ); -} - - // record the counter example - Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); - p->nSatCounter++; - -// if ( pOld->fFailTfo || pNew->fFailTfo ) -// printf( "*" ); -// printf( "s(%d)", pNew->Level ); - if ( fSwitch ) - printf( "s(%d)", pNew->Level ); - return 0; - } - else // if ( RetValue1 == MSAT_UNKNOWN ) - { -p->time3 += clock() - clk; - -// if ( pOld->fFailTfo || pNew->fFailTfo ) -// printf( "*" ); -// printf( "T(%d)", pNew->Level ); - if ( fSwitch ) - printf( "T(%d)", pNew->Level ); - - // mark the node as the failed node - pOld->fFailTfo = 1; - pNew->fFailTfo = 1; -// p->nSatFails++; - p->nSatFailsReal++; - return 0; - } - - // return SAT proof - p->nSatProof++; - -// if ( pOld->fFailTfo || pNew->fFailTfo ) -// printf( "*" ); -// printf( "u(%d)", pNew->Level ); - - if ( fSwitch ) - printf( "u(%d)", pNew->Level ); - - return 1; -} - - -/**Function************************************************************* - - Synopsis [Checks whether pOld => pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsImplication( Fraig_Man_t * p, Fraig_Node_t * pOld, Fraig_Node_t * pNew, int nBTLimit ) -{ - int RetValue, RetValue1, i, fComp, clk; - int fVerbose = 0; - - // make sure the nodes are not complemented - assert( !Fraig_IsComplement(pNew) ); - assert( !Fraig_IsComplement(pOld) ); - assert( pNew != pOld ); - - p->nSatCallsImp++; - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - Fraig_ManCreateSolver( p ); - // make sure the SAT solver has enough variables - for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) - Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); - - // get the logic cone -clk = clock(); - Fraig_OrderVariables( p, pOld, pNew ); -// Fraig_PrepareCones( p, pOld, pNew ); -p->timeTrav += clock() - clk; - -if ( fVerbose ) - printf( "%d(%d) - ", Fraig_CountPis(p,p->vVarsInt), Msat_IntVecReadSize(p->vVarsInt) ); - - - // get the complemented attribute - fComp = Fraig_NodeComparePhase( pOld, pNew ); -//Msat_SolverPrintClauses( p->pSat ); - - //////////////////////////////////////////// - // prepare the solver to run incrementally on these variables -//clk = clock(); - Msat_SolverPrepare( p->pSat, p->vVarsInt ); -//p->time3 += clock() - clk; - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 0) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, !fComp) ); - // run the solver -clk = clock(); - RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 ); -p->timeSat += clock() - clk; - - if ( RetValue1 == MSAT_FALSE ) - { -//p->time1 += clock() - clk; - -if ( fVerbose ) -{ - printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); -PRT( "time", clock() - clk ); -} - - // add the clause - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pOld->Num, 1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNew->Num, fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); -// p->nSatProofImp++; - return 1; - } - else if ( RetValue1 == MSAT_TRUE ) - { -//p->time2 += clock() - clk; - -if ( fVerbose ) -{ - printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); -PRT( "time", clock() - clk ); -} - // record the counter example - Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pOld, pNew ); - p->nSatCounterImp++; - return 0; - } - else // if ( RetValue1 == MSAT_UNKNOWN ) - { -p->time3 += clock() - clk; - p->nSatFailsImp++; - return 0; - } -} - -/**Function************************************************************* - - Synopsis [Prepares the SAT solver to run on the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManCheckClauseUsingSat( Fraig_Man_t * p, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int nBTLimit ) -{ - Fraig_Node_t * pNode1R, * pNode2R; - int RetValue, RetValue1, i, clk; - int fVerbose = 0; - - pNode1R = Fraig_Regular(pNode1); - pNode2R = Fraig_Regular(pNode2); - assert( pNode1R != pNode2R ); - - // make sure the solver is allocated and has enough variables - if ( p->pSat == NULL ) - Fraig_ManCreateSolver( p ); - // make sure the SAT solver has enough variables - for ( i = Msat_SolverReadVarNum(p->pSat); i < p->vNodes->nSize; i++ ) - Msat_SolverAddVar( p->pSat, p->vNodes->pArray[i]->Level ); - - // get the logic cone -clk = clock(); - Fraig_OrderVariables( p, pNode1R, pNode2R ); -// Fraig_PrepareCones( p, pNode1R, pNode2R ); -p->timeTrav += clock() - clk; - - //////////////////////////////////////////// - // prepare the solver to run incrementally on these variables -//clk = clock(); - Msat_SolverPrepare( p->pSat, p->vVarsInt ); -//p->time3 += clock() - clk; - - // solve under assumptions - // A = 1; B = 0 OR A = 1; B = 1 - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, !Fraig_IsComplement(pNode1)) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, !Fraig_IsComplement(pNode2)) ); - // run the solver -clk = clock(); - RetValue1 = Msat_SolverSolve( p->pSat, p->vProj, nBTLimit, 1000000 ); -p->timeSat += clock() - clk; - - if ( RetValue1 == MSAT_FALSE ) - { -//p->time1 += clock() - clk; - -if ( fVerbose ) -{ - printf( "unsat %d ", Msat_SolverReadBackTracks(p->pSat) ); -PRT( "time", clock() - clk ); -} - - // add the clause - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1R->Num, Fraig_IsComplement(pNode1)) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2R->Num, Fraig_IsComplement(pNode2)) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); -// p->nSatProofImp++; - return 1; - } - else if ( RetValue1 == MSAT_TRUE ) - { -//p->time2 += clock() - clk; - -if ( fVerbose ) -{ - printf( "sat %d ", Msat_SolverReadBackTracks(p->pSat) ); -PRT( "time", clock() - clk ); -} - // record the counter example -// Fraig_FeedBack( p, Msat_SolverReadModelArray(p->pSat), p->vVarsInt, pNode1R, pNode2R ); - p->nSatCounterImp++; - return 0; - } - else // if ( RetValue1 == MSAT_UNKNOWN ) - { -p->time3 += clock() - clk; - p->nSatFailsImp++; - return 0; - } -} - - -/**Function************************************************************* - - Synopsis [Prepares the SAT solver to run on the two nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_PrepareCones( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ -// Msat_IntVec_t * vAdjs; -// int * pVars, nVars, i, k; - int nVarsAlloc; - - assert( pOld != pNew ); - assert( !Fraig_IsComplement(pOld) ); - assert( !Fraig_IsComplement(pNew) ); - // clean the variables - nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); - Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); - Msat_IntVecClear( pMan->vVarsInt ); - - pMan->nTravIds++; - Fraig_PrepareCones_rec( pMan, pNew ); - Fraig_PrepareCones_rec( pMan, pOld ); - - -/* - nVars = Msat_IntVecReadSize( pMan->vVarsInt ); - pVars = Msat_IntVecReadArray( pMan->vVarsInt ); - for ( i = 0; i < nVars; i++ ) - { - // process its connections - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); - printf( "%d=%d { ", pVars[i], Msat_IntVecReadSize(vAdjs) ); - for ( k = 0; k < Msat_IntVecReadSize(vAdjs); k++ ) - printf( "%d ", Msat_IntVecReadEntry(vAdjs,k) ); - printf( "}\n" ); - - } - i = 0; -*/ -} - -/**Function************************************************************* - - Synopsis [Traverses the cone, collects the numbers and adds the clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_PrepareCones_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pFanin; - Msat_IntVec_t * vAdjs; - int fUseMuxes = 1, i; - int fItIsTime; - - // skip if the node is aleady visited - assert( !Fraig_IsComplement(pNode) ); - if ( pNode->TravId == pMan->nTravIds ) - return; - pNode->TravId = pMan->nTravIds; - - // collect the node's number (closer to reverse topological order) - Msat_IntVecPush( pMan->vVarsInt, pNode->Num ); - Msat_IntVecWriteEntry( pMan->vVarsUsed, pNode->Num, 1 ); - if ( !Fraig_NodeIsAnd( pNode ) ) - return; - - // if the node does not have fanins, create them - fItIsTime = 0; - if ( pNode->vFanins == NULL ) - { - fItIsTime = 1; - // create the fanins of the supergate - assert( pNode->fClauses == 0 ); - if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) - { - pNode->vFanins = Fraig_NodeVecAlloc( 4 ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); - Fraig_SupergateAddClausesMux( pMan, pNode ); - } - else - { - pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); - Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); - } - assert( pNode->vFanins->nSize > 1 ); - pNode->fClauses = 1; - pMan->nVarsClauses++; - - // add fanins - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pNode->Num ); - assert( Msat_IntVecReadSize( vAdjs ) == 0 ); - for ( i = 0; i < pNode->vFanins->nSize; i++ ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); - Msat_IntVecPush( vAdjs, pFanin->Num ); - } - } - - // recursively visit the fanins - for ( i = 0; i < pNode->vFanins->nSize; i++ ) - Fraig_PrepareCones_rec( pMan, Fraig_Regular(pNode->vFanins->pArray[i]) ); - - if ( fItIsTime ) - { - // recursively visit the fanins - for ( i = 0; i < pNode->vFanins->nSize; i++ ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[i]); - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); - Msat_IntVecPush( vAdjs, pNode->Num ); - } - } -} - -/**Function************************************************************* - - Synopsis [Collect variables using their proximity from the nodes.] - - Description [This procedure creates a variable order based on collecting - first the nodes that are the closest to the given two target nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_OrderVariables( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - Fraig_Node_t * pNode, * pFanin; - int i, k, Number, fUseMuxes = 1; - int nVarsAlloc; - - assert( pOld != pNew ); - assert( !Fraig_IsComplement(pOld) ); - assert( !Fraig_IsComplement(pNew) ); - - pMan->nTravIds++; - - // clean the variables - nVarsAlloc = Msat_IntVecReadSize(pMan->vVarsUsed); - Msat_IntVecFill( pMan->vVarsUsed, nVarsAlloc, 0 ); - Msat_IntVecClear( pMan->vVarsInt ); - - // add the first node - Msat_IntVecPush( pMan->vVarsInt, pOld->Num ); - Msat_IntVecWriteEntry( pMan->vVarsUsed, pOld->Num, 1 ); - pOld->TravId = pMan->nTravIds; - - // add the second node - Msat_IntVecPush( pMan->vVarsInt, pNew->Num ); - Msat_IntVecWriteEntry( pMan->vVarsUsed, pNew->Num, 1 ); - pNew->TravId = pMan->nTravIds; - - // create the variable order - for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ ) - { - // get the new node on the frontier - Number = Msat_IntVecReadEntry(pMan->vVarsInt, i); - pNode = pMan->vNodes->pArray[Number]; - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - - // if the node does not have fanins, create them - if ( pNode->vFanins == NULL ) - { - // create the fanins of the supergate - assert( pNode->fClauses == 0 ); - // detecting a fanout-free cone (experiment only) -// Fraig_DetectFanoutFreeCone( pMan, pNode ); - - if ( fUseMuxes && Fraig_NodeIsMuxType(pNode) ) - { - pNode->vFanins = Fraig_NodeVecAlloc( 4 ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p1) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p1)->p2) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p1) ); - Fraig_NodeVecPushUnique( pNode->vFanins, Fraig_Regular(Fraig_Regular(pNode->p2)->p2) ); - Fraig_SupergateAddClausesMux( pMan, pNode ); -// Fraig_DetectFanoutFreeConeMux( pMan, pNode ); - - nMuxes++; - } - else - { - pNode->vFanins = Fraig_CollectSupergate( pNode, fUseMuxes ); - Fraig_SupergateAddClauses( pMan, pNode, pNode->vFanins ); - } - assert( pNode->vFanins->nSize > 1 ); - pNode->fClauses = 1; - pMan->nVarsClauses++; - - pNode->fMark2 = 1; // goes together with Fraig_SetupAdjacentMark() - } - - // explore the implication fanins of pNode - for ( k = 0; k < pNode->vFanins->nSize; k++ ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); - if ( pFanin->TravId == pMan->nTravIds ) // already collected - continue; - // collect and mark - Msat_IntVecPush( pMan->vVarsInt, pFanin->Num ); - Msat_IntVecWriteEntry( pMan->vVarsUsed, pFanin->Num, 1 ); - pFanin->TravId = pMan->nTravIds; - } - } - - // set up the adjacent variable information -// Fraig_SetupAdjacent( pMan, pMan->vVarsInt ); - Fraig_SetupAdjacentMark( pMan, pMan->vVarsInt ); -} - - - -/**Function************************************************************* - - Synopsis [Set up the adjacent variable information.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SetupAdjacent( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ) -{ - Fraig_Node_t * pNode, * pFanin; - Msat_IntVec_t * vAdjs; - int * pVars, nVars, i, k; - - // clean the adjacents for the variables - nVars = Msat_IntVecReadSize( vConeVars ); - pVars = Msat_IntVecReadArray( vConeVars ); - for ( i = 0; i < nVars; i++ ) - { - // process its connections - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); - Msat_IntVecClear( vAdjs ); - - pNode = pMan->vNodes->pArray[pVars[i]]; - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - - // add fanins - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); - for ( k = 0; k < pNode->vFanins->nSize; k++ ) -// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); - Msat_IntVecPush( vAdjs, pFanin->Num ); -// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); - } - } - // add the fanouts - for ( i = 0; i < nVars; i++ ) - { - pNode = pMan->vNodes->pArray[pVars[i]]; - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - - // add the edges - for ( k = 0; k < pNode->vFanins->nSize; k++ ) -// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); - Msat_IntVecPush( vAdjs, pNode->Num ); -// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); - } - } -} - - -/**Function************************************************************* - - Synopsis [Set up the adjacent variable information.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SetupAdjacentMark( Fraig_Man_t * pMan, Msat_IntVec_t * vConeVars ) -{ - Fraig_Node_t * pNode, * pFanin; - Msat_IntVec_t * vAdjs; - int * pVars, nVars, i, k; - - // clean the adjacents for the variables - nVars = Msat_IntVecReadSize( vConeVars ); - pVars = Msat_IntVecReadArray( vConeVars ); - for ( i = 0; i < nVars; i++ ) - { - pNode = pMan->vNodes->pArray[pVars[i]]; - if ( pNode->fMark2 == 0 ) - continue; -// pNode->fMark2 = 0; - - // process its connections -// vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); -// Msat_IntVecClear( vAdjs ); - - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - - // add fanins - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pVars[i] ); - for ( k = 0; k < pNode->vFanins->nSize; k++ ) -// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); - Msat_IntVecPush( vAdjs, pFanin->Num ); -// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); - } - } - // add the fanouts - for ( i = 0; i < nVars; i++ ) - { - pNode = pMan->vNodes->pArray[pVars[i]]; - if ( pNode->fMark2 == 0 ) - continue; - pNode->fMark2 = 0; - - if ( !Fraig_NodeIsAnd(pNode) ) - continue; - - // add the edges - for ( k = 0; k < pNode->vFanins->nSize; k++ ) -// for ( k = pNode->vFanins->nSize - 1; k >= 0; k-- ) - { - pFanin = Fraig_Regular(pNode->vFanins->pArray[k]); - vAdjs = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( pMan->vAdjacents, pFanin->Num ); - Msat_IntVecPush( vAdjs, pNode->Num ); -// Msat_IntVecPushUniqueOrder( vAdjs, pFanin->Num ); - } - } -} - - - - -/**Function************************************************************* - - Synopsis [Adds clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SupergateAddClauses( Fraig_Man_t * p, Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper ) -{ - int fComp1, RetValue, nVars, Var, Var1, i; - - assert( Fraig_NodeIsAnd( pNode ) ); - nVars = Msat_SolverReadVarNum(p->pSat); - - Var = pNode->Num; - assert( Var < nVars ); - for ( i = 0; i < vSuper->nSize; i++ ) - { - // get the predecessor nodes - // get the complemented attributes of the nodes - fComp1 = Fraig_IsComplement(vSuper->pArray[i]); - // determine the variable numbers - Var1 = Fraig_Regular(vSuper->pArray[i])->Num; - // check that the variables are in the SAT manager - assert( Var1 < nVars ); - - // suppose the AND-gate is A * B = C - // add !A => !C or A + !C - // fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, fComp1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 1) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - } - - // add A & B => C or !A + !B + C -// fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 ); - Msat_IntVecClear( p->vProj ); - for ( i = 0; i < vSuper->nSize; i++ ) - { - // get the predecessor nodes - // get the complemented attributes of the nodes - fComp1 = Fraig_IsComplement(vSuper->pArray[i]); - // determine the variable numbers - Var1 = Fraig_Regular(vSuper->pArray[i])->Num; - - // add this variable to the array - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var1, !fComp1) ); - } - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(Var, 0) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Adds clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SupergateAddClausesExor( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1, * pNode2; - int fComp, RetValue; - - assert( !Fraig_IsComplement( pNode ) ); - assert( Fraig_NodeIsExorType( pNode ) ); - // get nodes - pNode1 = Fraig_Regular(Fraig_Regular(pNode->p1)->p1); - pNode2 = Fraig_Regular(Fraig_Regular(pNode->p1)->p2); - // get the complemented attribute of the EXOR/NEXOR gate - fComp = Fraig_NodeIsExor( pNode ); // 1 if EXOR, 0 if NEXOR - - // create four clauses - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, !fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode->Num, !fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode1->Num, !fComp) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(pNode2->Num, fComp) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); -} - -/**Function************************************************************* - - Synopsis [Adds clauses to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SupergateAddClausesMux( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNodeI, * pNodeT, * pNodeE; - int RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; - - assert( !Fraig_IsComplement( pNode ) ); - assert( Fraig_NodeIsMuxType( pNode ) ); - // get nodes (I = if, T = then, E = else) - pNodeI = Fraig_NodeRecognizeMux( pNode, &pNodeT, &pNodeE ); - // get the variable numbers - VarF = pNode->Num; - VarI = pNodeI->Num; - VarT = Fraig_Regular(pNodeT)->Num; - VarE = Fraig_Regular(pNodeE)->Num; - // get the complementation flags - fCompT = Fraig_IsComplement(pNodeT); - fCompE = Fraig_IsComplement(pNodeE); - - // f = ITE(i, t, e) - - // i' + t' + f - // i' + t + f' - // i + e' + f - // i + e + f' - - // create four clauses - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 1) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarI, 0) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - - // two additional clauses - // t' & e' -> f' - // t & e -> f - - // t + e + f' - // t' + e' + f - - if ( VarT == VarE ) - { -// assert( fCompT == !fCompE ); - return; - } - - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 0^fCompT) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 0^fCompE) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 1) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - Msat_IntVecClear( p->vProj ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarT, 1^fCompT) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarE, 1^fCompE) ); - Msat_IntVecPush( p->vProj, MSAT_VAR2LIT(VarF, 0) ); - RetValue = Msat_SolverAddClause( p->pSat, p->vProj ); - assert( RetValue ); - -} - - - - - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_DetectFanoutFreeCone_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst ) -{ - // make the pointer regular - pNode = Fraig_Regular(pNode); - // if the new node is complemented or a PI, another gate begins - if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) ) - { - Fraig_NodeVecPushUnique( vSuper, pNode ); - return; - } - // go through the branches - Fraig_DetectFanoutFreeCone_rec( pNode->p1, vSuper, vInside, 0 ); - Fraig_DetectFanoutFreeCone_rec( pNode->p2, vSuper, vInside, 0 ); - // add the node - Fraig_NodeVecPushUnique( vInside, pNode ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -/* -void Fraig_DetectFanoutFreeCone( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_NodeVec_t * vFanins; - Fraig_NodeVec_t * vInside; - int nCubes; - extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside ); - - vFanins = Fraig_NodeVecAlloc( 8 ); - vInside = Fraig_NodeVecAlloc( 8 ); - - Fraig_DetectFanoutFreeCone_rec( pNode, vFanins, vInside, 1 ); - assert( vInside->pArray[vInside->nSize-1] == pNode ); - - nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside ); - -printf( "%d(%d)", vFanins->nSize, nCubes ); - Fraig_NodeVecFree( vFanins ); - Fraig_NodeVecFree( vInside ); -} -*/ - - - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_DetectFanoutFreeConeMux_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, Fraig_NodeVec_t * vInside, int fFirst ) -{ - // make the pointer regular - pNode = Fraig_Regular(pNode); - // if the new node is complemented or a PI, another gate begins - if ( (!fFirst && pNode->nRefs > 1) || Fraig_NodeIsVar(pNode) || !Fraig_NodeIsMuxType(pNode) ) - { - Fraig_NodeVecPushUnique( vSuper, pNode ); - return; - } - // go through the branches - Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p1, vSuper, vInside, 0 ); - Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p1)->p2, vSuper, vInside, 0 ); - Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p1, vSuper, vInside, 0 ); - Fraig_DetectFanoutFreeConeMux_rec( Fraig_Regular(pNode->p2)->p2, vSuper, vInside, 0 ); - // add the node - Fraig_NodeVecPushUnique( vInside, pNode ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_DetectFanoutFreeConeMux( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_NodeVec_t * vFanins; - Fraig_NodeVec_t * vInside; - int nCubes; - extern int Fraig_CutSopCountCubes( Fraig_Man_t * pMan, Fraig_NodeVec_t * vFanins, Fraig_NodeVec_t * vInside ); - - vFanins = Fraig_NodeVecAlloc( 8 ); - vInside = Fraig_NodeVecAlloc( 8 ); - - Fraig_DetectFanoutFreeConeMux_rec( pNode, vFanins, vInside, 1 ); - assert( vInside->pArray[vInside->nSize-1] == pNode ); - -// nCubes = Fraig_CutSopCountCubes( pMan, vFanins, vInside ); - nCubes = 0; - -printf( "%d(%d)", vFanins->nSize, nCubes ); - Fraig_NodeVecFree( vFanins ); - Fraig_NodeVecFree( vInside ); -} - - - -/**Function************************************************************* - - Synopsis [Collect variables using their proximity from the nodes.] - - Description [This procedure creates a variable order based on collecting - first the nodes that are the closest to the given two target nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_SetActivity( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - Fraig_Node_t * pNode; - int i, Number, MaxLevel; - float * pFactors = Msat_SolverReadFactors(pMan->pSat); - if ( pFactors == NULL ) - return; - MaxLevel = FRAIG_MAX( pOld->Level, pNew->Level ); - // create the variable order - for ( i = 0; i < Msat_IntVecReadSize(pMan->vVarsInt); i++ ) - { - // get the new node on the frontier - Number = Msat_IntVecReadEntry(pMan->vVarsInt, i); - pNode = pMan->vNodes->pArray[Number]; - pFactors[pNode->Num] = (float)pow( 0.97, MaxLevel - pNode->Level ); -// if ( pNode->Num % 50 == 0 ) -// printf( "(%d) %.2f ", MaxLevel - pNode->Level, pFactors[pNode->Num] ); - } -// printf( "\n" ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/fraig/fraigTable.c b/src/sat/fraig/fraigTable.c deleted file mode 100644 index b68bbe0e..00000000 --- a/src/sat/fraig/fraigTable.c +++ /dev/null @@ -1,657 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigTable.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Structural and functional hash tables.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigTable.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Fraig_TableResizeS( Fraig_HashTable_t * p ); -static void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_HashTable_t * Fraig_HashTableCreate( int nSize ) -{ - Fraig_HashTable_t * p; - // allocate the table - p = ALLOC( Fraig_HashTable_t, 1 ); - memset( p, 0, sizeof(Fraig_HashTable_t) ); - // allocate and clean the bins - p->nBins = Cudd_PrimeFraig(nSize); - p->pBins = ALLOC( Fraig_Node_t *, p->nBins ); - memset( p->pBins, 0, sizeof(Fraig_Node_t *) * p->nBins ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocates the supergate hash table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_HashTableFree( Fraig_HashTable_t * p ) -{ - FREE( p->pBins ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Looks up an entry in the structural hash table.] - - Description [If the entry with the same children does not exists, - creates it, inserts it into the table, and returns 0. If the entry - with the same children exists, finds it, and return 1. In both cases, - the new/old entry is returned in ppNodeRes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_HashTableLookupS( Fraig_Man_t * pMan, Fraig_Node_t * p1, Fraig_Node_t * p2, Fraig_Node_t ** ppNodeRes ) -{ - Fraig_HashTable_t * p = pMan->pTableS; - Fraig_Node_t * pEnt; - unsigned Key; - - // order the arguments - if ( Fraig_Regular(p1)->Num > Fraig_Regular(p2)->Num ) - pEnt = p1, p1 = p2, p2 = pEnt; - - Key = Fraig_HashKey2( p1, p2, p->nBins ); - Fraig_TableBinForEachEntryS( p->pBins[Key], pEnt ) - if ( pEnt->p1 == p1 && pEnt->p2 == p2 ) - { - *ppNodeRes = pEnt; - return 1; - } - // check if it is a good time for table resizing - if ( p->nEntries >= 2 * p->nBins ) - { - Fraig_TableResizeS( p ); - Key = Fraig_HashKey2( p1, p2, p->nBins ); - } - // create the new node - pEnt = Fraig_NodeCreate( pMan, p1, p2 ); - // add the node to the corresponding linked list in the table - pEnt->pNextS = p->pBins[Key]; - p->pBins[Key] = pEnt; - *ppNodeRes = pEnt; - p->nEntries++; - return 0; -} - - -/**Function************************************************************* - - Synopsis [Insert the entry in the functional hash table.] - - Description [If the entry with the same key exists, return it right away. - If the entry with the same key does not exists, inserts it and returns NULL. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_HashTableLookupF( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_HashTable_t * p = pMan->pTableF; - Fraig_Node_t * pEnt, * pEntD; - unsigned Key; - - // go through the hash table entries - Key = pNode->uHashR % p->nBins; - Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt ) - { - // if their simulation info differs, skip - if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->nWordsRand, 1 ) ) - continue; - // equivalent up to the complement - Fraig_TableBinForEachEntryD( pEnt, pEntD ) - { - // if their simulation info differs, skip - if ( !Fraig_CompareSimInfo( pNode, pEntD, pMan->iWordStart, 0 ) ) - continue; - // found a simulation-equivalent node - return pEntD; - } - // did not find a simulation equivalent node - // add the node to the corresponding linked list - pNode->pNextD = pEnt->pNextD; - pEnt->pNextD = pNode; - // return NULL, because there is no functional equivalence in this case - return NULL; - } - - // check if it is a good time for table resizing - if ( p->nEntries >= 2 * p->nBins ) - { - Fraig_TableResizeF( p, 1 ); - Key = pNode->uHashR % p->nBins; - } - - // add the node to the corresponding linked list in the table - pNode->pNextF = p->pBins[Key]; - p->pBins[Key] = pNode; - p->nEntries++; - // return NULL, because there is no functional equivalence in this case - return NULL; -} - -/**Function************************************************************* - - Synopsis [Insert the entry in the functional hash table.] - - Description [If the entry with the same key exists, return it right away. - If the entry with the same key does not exists, inserts it and returns NULL. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_HashTableLookupF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_HashTable_t * p = pMan->pTableF0; - Fraig_Node_t * pEnt; - unsigned Key; - - // go through the hash table entries - Key = pNode->uHashD % p->nBins; - Fraig_TableBinForEachEntryF( p->pBins[Key], pEnt ) - { - // if their simulation info differs, skip - if ( !Fraig_CompareSimInfo( pNode, pEnt, pMan->iWordStart, 0 ) ) - continue; - // found a simulation-equivalent node - return pEnt; - } - - // check if it is a good time for table resizing - if ( p->nEntries >= 2 * p->nBins ) - { - Fraig_TableResizeF( p, 0 ); - Key = pNode->uHashD % p->nBins; - } - - // add the node to the corresponding linked list in the table - pNode->pNextF = p->pBins[Key]; - p->pBins[Key] = pNode; - p->nEntries++; - // return NULL, because there is no functional equivalence in this case - return NULL; -} - -/**Function************************************************************* - - Synopsis [Insert the entry in the functional hash table.] - - Description [Unconditionally add the node to the corresponding - linked list in the table.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_HashTableInsertF0( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - Fraig_HashTable_t * p = pMan->pTableF0; - unsigned Key = pNode->uHashD % p->nBins; - - pNode->pNextF = p->pBins[Key]; - p->pBins[Key] = pNode; - p->nEntries++; -} - - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_TableResizeS( Fraig_HashTable_t * p ) -{ - Fraig_Node_t ** pBinsNew; - Fraig_Node_t * pEnt, * pEnt2; - int nBinsNew, Counter, i, clk; - unsigned Key; - -clk = clock(); - // get the new table size - nBinsNew = Cudd_PrimeFraig(2 * p->nBins); - // allocate a new array - pBinsNew = ALLOC( Fraig_Node_t *, nBinsNew ); - memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < p->nBins; i++ ) - Fraig_TableBinForEachEntrySafeS( p->pBins[i], pEnt, pEnt2 ) - { - Key = Fraig_HashKey2( pEnt->p1, pEnt->p2, nBinsNew ); - pEnt->pNextS = pBinsNew[Key]; - pBinsNew[Key] = pEnt; - Counter++; - } - assert( Counter == p->nEntries ); -// printf( "Increasing the structural table size from %6d to %6d. ", p->nBins, nBinsNew ); -// PRT( "Time", clock() - clk ); - // replace the table and the parameters - free( p->pBins ); - p->pBins = pBinsNew; - p->nBins = nBinsNew; -} - -/**Function************************************************************* - - Synopsis [Resizes the table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_TableResizeF( Fraig_HashTable_t * p, int fUseSimR ) -{ - Fraig_Node_t ** pBinsNew; - Fraig_Node_t * pEnt, * pEnt2; - int nBinsNew, Counter, i, clk; - unsigned Key; - -clk = clock(); - // get the new table size - nBinsNew = Cudd_PrimeFraig(2 * p->nBins); - // allocate a new array - pBinsNew = ALLOC( Fraig_Node_t *, nBinsNew ); - memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * nBinsNew ); - // rehash the entries from the old table - Counter = 0; - for ( i = 0; i < p->nBins; i++ ) - Fraig_TableBinForEachEntrySafeF( p->pBins[i], pEnt, pEnt2 ) - { - if ( fUseSimR ) - Key = pEnt->uHashR % nBinsNew; - else - Key = pEnt->uHashD % nBinsNew; - pEnt->pNextF = pBinsNew[Key]; - pBinsNew[Key] = pEnt; - Counter++; - } - assert( Counter == p->nEntries ); -// printf( "Increasing the functional table size from %6d to %6d. ", p->nBins, nBinsNew ); -// PRT( "Time", clock() - clk ); - // replace the table and the parameters - free( p->pBins ); - p->pBins = pBinsNew; - p->nBins = nBinsNew; -} - - -/**Function************************************************************* - - Synopsis [Compares two pieces of simulation info.] - - Description [Returns 1 if they are equal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CompareSimInfo( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand ) -{ - int i; - assert( !Fraig_IsComplement(pNode1) ); - assert( !Fraig_IsComplement(pNode2) ); - if ( fUseRand ) - { - // if their signatures differ, skip - if ( pNode1->uHashR != pNode2->uHashR ) - return 0; - // check the simulation info - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimR[i] != pNode2->puSimR[i] ) - return 0; - } - else - { - // if their signatures differ, skip - if ( pNode1->uHashD != pNode2->uHashD ) - return 0; - // check the simulation info - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimD[i] != pNode2->puSimD[i] ) - return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Find the number of the different pattern.] - - Description [Returns -1 if there is no such pattern] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_FindFirstDiff( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int fCompl, int iWordLast, int fUseRand ) -{ - int i, v; - assert( !Fraig_IsComplement(pNode1) ); - assert( !Fraig_IsComplement(pNode2) ); - // take into account possible internal complementation - fCompl ^= pNode1->fInv; - fCompl ^= pNode2->fInv; - // find the pattern - if ( fCompl ) - { - if ( fUseRand ) - { - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimR[i] != ~pNode2->puSimR[i] ) - for ( v = 0; v < 32; v++ ) - if ( (pNode1->puSimR[i] ^ ~pNode2->puSimR[i]) & (1 << v) ) - return i * 32 + v; - } - else - { - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimD[i] != ~pNode2->puSimD[i] ) - for ( v = 0; v < 32; v++ ) - if ( (pNode1->puSimD[i] ^ ~pNode2->puSimD[i]) & (1 << v) ) - return i * 32 + v; - } - } - else - { - if ( fUseRand ) - { - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimR[i] != pNode2->puSimR[i] ) - for ( v = 0; v < 32; v++ ) - if ( (pNode1->puSimR[i] ^ pNode2->puSimR[i]) & (1 << v) ) - return i * 32 + v; - } - else - { - for ( i = 0; i < iWordLast; i++ ) - if ( pNode1->puSimD[i] != pNode2->puSimD[i] ) - for ( v = 0; v < 32; v++ ) - if ( (pNode1->puSimD[i] ^ pNode2->puSimD[i]) & (1 << v) ) - return i * 32 + v; - } - } - return -1; -} - -/**Function************************************************************* - - Synopsis [Compares two pieces of simulation info.] - - Description [Returns 1 if they are equal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CompareSimInfoUnderMask( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ) -{ - unsigned * pSims1, * pSims2; - int i; - assert( !Fraig_IsComplement(pNode1) ); - assert( !Fraig_IsComplement(pNode2) ); - // get hold of simulation info - pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD; - pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD; - // check the simulation info - for ( i = 0; i < iWordLast; i++ ) - if ( (pSims1[i] & puMask[i]) != (pSims2[i] & puMask[i]) ) - return 0; - return 1; -} - -/**Function************************************************************* - - Synopsis [Compares two pieces of simulation info.] - - Description [Returns 1 if they are equal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_CollectXors( Fraig_Node_t * pNode1, Fraig_Node_t * pNode2, int iWordLast, int fUseRand, unsigned * puMask ) -{ - unsigned * pSims1, * pSims2; - int i; - assert( !Fraig_IsComplement(pNode1) ); - assert( !Fraig_IsComplement(pNode2) ); - // get hold of simulation info - pSims1 = fUseRand? pNode1->puSimR : pNode1->puSimD; - pSims2 = fUseRand? pNode2->puSimR : pNode2->puSimD; - // check the simulation info - for ( i = 0; i < iWordLast; i++ ) - puMask[i] = ( pSims1[i] ^ pSims2[i] ); -} - - -/**Function************************************************************* - - Synopsis [Prints stats of the structural table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_TablePrintStatsS( Fraig_Man_t * pMan ) -{ - Fraig_HashTable_t * pT = pMan->pTableS; - Fraig_Node_t * pNode; - int i, Counter; - - printf( "Structural table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); - for ( i = 0; i < pT->nBins; i++ ) - { - Counter = 0; - Fraig_TableBinForEachEntryS( pT->pBins[i], pNode ) - Counter++; - if ( Counter > 1 ) - { - printf( "%d ", Counter ); - if ( Counter > 50 ) - printf( "{%d} ", i ); - } - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints stats of the structural table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_TablePrintStatsF( Fraig_Man_t * pMan ) -{ - Fraig_HashTable_t * pT = pMan->pTableF; - Fraig_Node_t * pNode; - int i, Counter; - - printf( "Functional table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); - for ( i = 0; i < pT->nBins; i++ ) - { - Counter = 0; - Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) - Counter++; - if ( Counter > 1 ) - printf( "{%d} ", Counter ); - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints stats of the structural table.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_TablePrintStatsF0( Fraig_Man_t * pMan ) -{ - Fraig_HashTable_t * pT = pMan->pTableF0; - Fraig_Node_t * pNode; - int i, Counter; - - printf( "Zero-node table. Table size = %d. Number of entries = %d.\n", pT->nBins, pT->nEntries ); - for ( i = 0; i < pT->nBins; i++ ) - { - Counter = 0; - Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) - Counter++; - if ( Counter == 0 ) - continue; -/* - printf( "\nBin = %4d : Number of entries = %4d\n", i, Counter ); - Fraig_TableBinForEachEntryF( pT->pBins[i], pNode ) - printf( "Node %5d. Hash = %10d.\n", pNode->Num, pNode->uHashD ); -*/ - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Rehashes the table after the simulation info has changed.] - - Description [Assumes that the hash values have been updated after performing - additional simulation. Rehashes the table using the new hash values. - Uses pNextF to link the entries in the bins. Uses pNextD to link the entries - with identical hash values. Returns 1 if the identical entries have been found. - Note that identical hash values may mean that the simulation data is different.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_TableRehashF0( Fraig_Man_t * pMan, int fLinkEquiv ) -{ - Fraig_HashTable_t * pT = pMan->pTableF0; - Fraig_Node_t ** pBinsNew; - Fraig_Node_t * pEntF, * pEntF2, * pEnt, * pEntD2, * pEntN; - int ReturnValue, Counter, i; - unsigned Key; - - // allocate a new array of bins - pBinsNew = ALLOC( Fraig_Node_t *, pT->nBins ); - memset( pBinsNew, 0, sizeof(Fraig_Node_t *) * pT->nBins ); - - // rehash the entries in the table - // go through all the nodes in the F-lists (and possible in D-lists, if used) - Counter = 0; - ReturnValue = 0; - for ( i = 0; i < pT->nBins; i++ ) - Fraig_TableBinForEachEntrySafeF( pT->pBins[i], pEntF, pEntF2 ) - Fraig_TableBinForEachEntrySafeD( pEntF, pEnt, pEntD2 ) - { - // decide where to put entry pEnt - Key = pEnt->uHashD % pT->nBins; - if ( fLinkEquiv ) - { - // go through the entries in the new bin - Fraig_TableBinForEachEntryF( pBinsNew[Key], pEntN ) - { - // if they have different values skip - if ( pEnt->uHashD != pEntN->uHashD ) - continue; - // they have the same hash value, add pEnt to the D-list pEnt3 - pEnt->pNextD = pEntN->pNextD; - pEntN->pNextD = pEnt; - ReturnValue = 1; - Counter++; - break; - } - if ( pEntN != NULL ) // already linked - continue; - // we did not find equal entry - } - // link the new entry - pEnt->pNextF = pBinsNew[Key]; - pBinsNew[Key] = pEnt; - pEnt->pNextD = NULL; - Counter++; - } - assert( Counter == pT->nEntries ); - // replace the table and the parameters - free( pT->pBins ); - pT->pBins = pBinsNew; - return ReturnValue; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/fraig/fraigUtil.c b/src/sat/fraig/fraigUtil.c deleted file mode 100644 index 342a7111..00000000 --- a/src/sat/fraig/fraigUtil.c +++ /dev/null @@ -1,1034 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigUtil.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Various utilities.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigUtil.c,v 1.15 2005/07/08 01:01:34 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" -#include - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int bit_count[256] = { - 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, - 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 -}; - -static void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv ); -static int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_Dfs( Fraig_Man_t * pMan, int fEquiv ) -{ - Fraig_NodeVec_t * vNodes; - int i; - pMan->nTravIds++; - vNodes = Fraig_NodeVecAlloc( 100 ); - for ( i = 0; i < pMan->vOutputs->nSize; i++ ) - Fraig_Dfs_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), vNodes, fEquiv ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_DfsOne( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fEquiv ) -{ - Fraig_NodeVec_t * vNodes; - pMan->nTravIds++; - vNodes = Fraig_NodeVecAlloc( 100 ); - Fraig_Dfs_rec( pMan, Fraig_Regular(pNode), vNodes, fEquiv ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_DfsNodes( Fraig_Man_t * pMan, Fraig_Node_t ** ppNodes, int nNodes, int fEquiv ) -{ - Fraig_NodeVec_t * vNodes; - int i; - pMan->nTravIds++; - vNodes = Fraig_NodeVecAlloc( 100 ); - for ( i = 0; i < nNodes; i++ ) - Fraig_Dfs_rec( pMan, Fraig_Regular(ppNodes[i]), vNodes, fEquiv ); - return vNodes; -} - -/**Function************************************************************* - - Synopsis [Recursively computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_Dfs_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_NodeVec_t * vNodes, int fEquiv ) -{ - assert( !Fraig_IsComplement(pNode) ); - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return; - pNode->TravId = pMan->nTravIds; - // visit the transitive fanin - if ( Fraig_NodeIsAnd(pNode) ) - { - Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p1), vNodes, fEquiv ); - Fraig_Dfs_rec( pMan, Fraig_Regular(pNode->p2), vNodes, fEquiv ); - } - if ( fEquiv && pNode->pNextE ) - Fraig_Dfs_rec( pMan, pNode->pNextE, vNodes, fEquiv ); - // save the node - Fraig_NodeVecPush( vNodes, pNode ); -} - -/**Function************************************************************* - - Synopsis [Computes the DFS ordering of the nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CountNodes( Fraig_Man_t * pMan, int fEquiv ) -{ - Fraig_NodeVec_t * vNodes; - int RetValue; - vNodes = Fraig_Dfs( pMan, fEquiv ); - RetValue = vNodes->nSize; - Fraig_NodeVecFree( vNodes ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CheckTfi( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - assert( !Fraig_IsComplement(pOld) ); - assert( !Fraig_IsComplement(pNew) ); - pMan->nTravIds++; - return Fraig_CheckTfi_rec( pMan, pNew, pOld ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CheckTfi_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, Fraig_Node_t * pOld ) -{ - // check the trivial cases - if ( pNode == NULL ) - return 0; - if ( pNode->Num < pOld->Num && !pMan->fChoicing ) - return 0; - if ( pNode == pOld ) - return 1; - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return 0; - pNode->TravId = pMan->nTravIds; - // check the children - if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p1), pOld ) ) - return 1; - if ( Fraig_CheckTfi_rec( pMan, Fraig_Regular(pNode->p2), pOld ) ) - return 1; - // check equivalent nodes - return Fraig_CheckTfi_rec( pMan, pNode->pNextE, pOld ); -} - - -/**Function************************************************************* - - Synopsis [Returns 1 if pOld is in the TFI of pNew.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CheckTfi2( Fraig_Man_t * pMan, Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - Fraig_NodeVec_t * vNodes; - int RetValue; - vNodes = Fraig_DfsOne( pMan, pNew, 1 ); - RetValue = (pOld->TravId == pMan->nTravIds); - Fraig_NodeVecFree( vNodes ); - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Sets the number of fanouts (none, one, or many).] - - Description [This procedure collects the nodes reachable from - the POs of the AIG and sets the type of fanout counter (none, one, - or many) for each node. This procedure is useful to determine - fanout-free cones of AND-nodes, which is helpful for rebalancing - the AIG (see procedure Fraig_ManRebalance, or something like that).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManMarkRealFanouts( Fraig_Man_t * p ) -{ - Fraig_NodeVec_t * vNodes; - Fraig_Node_t * pNodeR; - int i; - // collect the nodes reachable - vNodes = Fraig_Dfs( p, 0 ); - // clean the fanouts field - for ( i = 0; i < vNodes->nSize; i++ ) - { - vNodes->pArray[i]->nFanouts = 0; - vNodes->pArray[i]->pData0 = NULL; - } - // mark reachable nodes by setting the two-bit counter pNode->nFans - for ( i = 0; i < vNodes->nSize; i++ ) - { - pNodeR = Fraig_Regular(vNodes->pArray[i]->p1); - if ( pNodeR && ++pNodeR->nFanouts == 3 ) - pNodeR->nFanouts = 2; - pNodeR = Fraig_Regular(vNodes->pArray[i]->p2); - if ( pNodeR && ++pNodeR->nFanouts == 3 ) - pNodeR->nFanouts = 2; - } - Fraig_NodeVecFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Creates the constant 1 node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_BitStringCountOnes( unsigned * pString, int nWords ) -{ - unsigned char * pSuppBytes = (unsigned char *)pString; - int i, nOnes, nBytes = sizeof(unsigned) * nWords; - // count the number of ones in the simulation vector - for ( i = nOnes = 0; i < nBytes; i++ ) - nOnes += bit_count[pSuppBytes[i]]; - return nOnes; -} - -/**Function************************************************************* - - Synopsis [Verify one useful property.] - - Description [This procedure verifies one useful property. After - the FRAIG construction with choice nodes is over, each primary node - should have fanins that are primary nodes. The primary nodes is the - one that does not have pNode->pRepr set to point to another node.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManCheckConsistency( Fraig_Man_t * p ) -{ - Fraig_Node_t * pNode; - Fraig_NodeVec_t * pVec; - int i; - pVec = Fraig_Dfs( p, 0 ); - for ( i = 0; i < pVec->nSize; i++ ) - { - pNode = pVec->pArray[i]; - if ( Fraig_NodeIsVar(pNode) ) - { - if ( pNode->pRepr ) - printf( "Primary input %d is a secondary node.\n", pNode->Num ); - } - else if ( Fraig_NodeIsConst(pNode) ) - { - if ( pNode->pRepr ) - printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); - } - else - { - if ( pNode->pRepr ) - printf( "Internal node %d is a secondary node.\n", pNode->Num ); - if ( Fraig_Regular(pNode->p1)->pRepr ) - printf( "Internal node %d has first fanin %d that is a secondary node.\n", - pNode->Num, Fraig_Regular(pNode->p1)->Num ); - if ( Fraig_Regular(pNode->p2)->pRepr ) - printf( "Internal node %d has second fanin %d that is a secondary node.\n", - pNode->Num, Fraig_Regular(pNode->p2)->Num ); - } - } - Fraig_NodeVecFree( pVec ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Prints the node.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_PrintNode( Fraig_Man_t * p, Fraig_Node_t * pNode ) -{ - Fraig_NodeVec_t * vNodes; - Fraig_Node_t * pTemp; - int fCompl1, fCompl2, i; - - vNodes = Fraig_DfsOne( p, pNode, 0 ); - for ( i = 0; i < vNodes->nSize; i++ ) - { - pTemp = vNodes->pArray[i]; - if ( Fraig_NodeIsVar(pTemp) ) - { - printf( "%3d : PI ", pTemp->Num ); - Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 ); - printf( " " ); - Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 ); - printf( " %d\n", pTemp->fInv ); - continue; - } - - fCompl1 = Fraig_IsComplement(pTemp->p1); - fCompl2 = Fraig_IsComplement(pTemp->p2); - printf( "%3d : %c%3d %c%3d ", pTemp->Num, - (fCompl1? '-':'+'), Fraig_Regular(pTemp->p1)->Num, - (fCompl2? '-':'+'), Fraig_Regular(pTemp->p2)->Num ); - Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimR, 20 ); - printf( " " ); - Fraig_PrintBinary( stdout, (unsigned *)&pTemp->puSimD, 20 ); - printf( " %d\n", pTemp->fInv ); - } - Fraig_NodeVecFree( vNodes ); -} - -/**Function************************************************************* - - Synopsis [Prints the bit string.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_PrintBinary( FILE * pFile, unsigned * pSign, int nBits ) -{ - int Remainder, nWords; - int w, i; - - Remainder = (nBits%(sizeof(unsigned)*8)); - nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); - - for ( w = nWords-1; w >= 0; w-- ) - for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) - fprintf( pFile, "%c", '0' + (int)((pSign[w] & (1< 0) ); - -// fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Sets up the mask.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_GetMaxLevel( Fraig_Man_t * pMan ) -{ - int nLevelMax, i; - nLevelMax = 0; - for ( i = 0; i < pMan->vOutputs->nSize; i++ ) - nLevelMax = nLevelMax > Fraig_Regular(pMan->vOutputs->pArray[i])->Level? - nLevelMax : Fraig_Regular(pMan->vOutputs->pArray[i])->Level; - return nLevelMax; -} - -/**Function************************************************************* - - Synopsis [Analyses choice nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_MappingUpdateLevel_rec( Fraig_Man_t * pMan, Fraig_Node_t * pNode, int fMaximum ) -{ - Fraig_Node_t * pTemp; - int Level1, Level2, LevelE; - assert( !Fraig_IsComplement(pNode) ); - if ( !Fraig_NodeIsAnd(pNode) ) - return pNode->Level; - // skip the visited node - if ( pNode->TravId == pMan->nTravIds ) - return pNode->Level; - pNode->TravId = pMan->nTravIds; - // compute levels of the children nodes - Level1 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p1), fMaximum ); - Level2 = Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pNode->p2), fMaximum ); - pNode->Level = 1 + FRAIG_MAX( Level1, Level2 ); - if ( pNode->pNextE ) - { - LevelE = Fraig_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); - if ( fMaximum ) - { - if ( pNode->Level < LevelE ) - pNode->Level = LevelE; - } - else - { - if ( pNode->Level > LevelE ) - pNode->Level = LevelE; - } - // set the level of all equivalent nodes to be the same minimum - if ( pNode->pRepr == NULL ) // the primary node - for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) - pTemp->Level = pNode->Level; - } - return pNode->Level; -} - -/**Function************************************************************* - - Synopsis [Resets the levels of the nodes in the choice graph.] - - Description [Makes the level of the choice nodes to be equal to the - maximum of the level of the nodes in the equivalence class. This way - sorting by level leads to the reverse topological order, which is - needed for the required time computation.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_MappingSetChoiceLevels( Fraig_Man_t * pMan, int fMaximum ) -{ - int i; - pMan->nTravIds++; - for ( i = 0; i < pMan->vOutputs->nSize; i++ ) - Fraig_MappingUpdateLevel_rec( pMan, Fraig_Regular(pMan->vOutputs->pArray[i]), fMaximum ); -} - -/**Function************************************************************* - - Synopsis [Reports statistics on choice nodes.] - - Description [The number of choice nodes is the number of primary nodes, - which has pNextE set to a pointer. The number of choices is the number - of entries in the equivalent-node lists of the primary nodes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManReportChoices( Fraig_Man_t * pMan ) -{ - Fraig_Node_t * pNode, * pTemp; - int nChoiceNodes, nChoices; - int i, LevelMax1, LevelMax2; - - // report the number of levels - LevelMax1 = Fraig_GetMaxLevel( pMan ); - Fraig_MappingSetChoiceLevels( pMan, 0 ); - LevelMax2 = Fraig_GetMaxLevel( pMan ); - - // report statistics about choices - nChoiceNodes = nChoices = 0; - for ( i = 0; i < pMan->vNodes->nSize; i++ ) - { - pNode = pMan->vNodes->pArray[i]; - if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) - { // this is a choice node = the primary node that has equivalent nodes - nChoiceNodes++; - for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) - nChoices++; - } - } - printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); - printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of EXOR/NEXOR gate.] - - Description [The node can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsExorType( Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1, * pNode2; - // make the node regular (it does not matter for EXOR/NEXOR) - pNode = Fraig_Regular(pNode); - // if the node or its children are not ANDs or not compl, this cannot be EXOR type - if ( !Fraig_NodeIsAnd(pNode) ) - return 0; - if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) ) - return 0; - if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) ) - return 0; - - // get children - pNode1 = Fraig_Regular(pNode->p1); - pNode2 = Fraig_Regular(pNode->p2); - assert( pNode1->Num < pNode2->Num ); - - // compare grandchildren - return pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] - - Description [The node can be complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsMuxType( Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1, * pNode2; - - // make the node regular (it does not matter for EXOR/NEXOR) - pNode = Fraig_Regular(pNode); - // if the node or its children are not ANDs or not compl, this cannot be EXOR type - if ( !Fraig_NodeIsAnd(pNode) ) - return 0; - if ( !Fraig_NodeIsAnd(pNode->p1) || !Fraig_IsComplement(pNode->p1) ) - return 0; - if ( !Fraig_NodeIsAnd(pNode->p2) || !Fraig_IsComplement(pNode->p2) ) - return 0; - - // get children - pNode1 = Fraig_Regular(pNode->p1); - pNode2 = Fraig_Regular(pNode->p2); - assert( pNode1->Num < pNode2->Num ); - - // compare grandchildren - // node is an EXOR/NEXOR - if ( pNode1->p1 == Fraig_Not(pNode2->p1) && pNode1->p2 == Fraig_Not(pNode2->p2) ) - return 1; - - // otherwise the node is MUX iff it has a pair of equal grandchildren - return pNode1->p1 == Fraig_Not(pNode2->p1) || - pNode1->p1 == Fraig_Not(pNode2->p2) || - pNode1->p2 == Fraig_Not(pNode2->p1) || - pNode1->p2 == Fraig_Not(pNode2->p2); -} - -/**Function************************************************************* - - Synopsis [Returns 1 if the node is EXOR, 0 if it is NEXOR.] - - Description [The node should be EXOR type and not complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsExor( Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1; - assert( !Fraig_IsComplement(pNode) ); - assert( Fraig_NodeIsExorType(pNode) ); - assert( Fraig_IsComplement(pNode->p1) ); - // get children - pNode1 = Fraig_Regular(pNode->p1); - return Fraig_IsComplement(pNode1->p1) == Fraig_IsComplement(pNode1->p2); -} - -/**Function************************************************************* - - Synopsis [Recognizes what nodes are control and data inputs of a MUX.] - - Description [If the node is a MUX, returns the control variable C. - Assigns nodes T and E to be the then and else variables of the MUX. - Node C is never complemented. Nodes T and E can be complemented. - This function also recognizes EXOR/NEXOR gates as MUXes.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeRecognizeMux( Fraig_Node_t * pNode, Fraig_Node_t ** ppNodeT, Fraig_Node_t ** ppNodeE ) -{ - Fraig_Node_t * pNode1, * pNode2; - assert( !Fraig_IsComplement(pNode) ); - assert( Fraig_NodeIsMuxType(pNode) ); - // get children - pNode1 = Fraig_Regular(pNode->p1); - pNode2 = Fraig_Regular(pNode->p2); - // find the control variable - if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) - { - if ( Fraig_IsComplement(pNode1->p1) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Fraig_Not(pNode2->p2); - *ppNodeE = Fraig_Not(pNode1->p2); - return pNode2->p1; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Fraig_Not(pNode1->p2); - *ppNodeE = Fraig_Not(pNode2->p2); - return pNode1->p1; - } - } - else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) - { - if ( Fraig_IsComplement(pNode1->p1) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Fraig_Not(pNode2->p1); - *ppNodeE = Fraig_Not(pNode1->p2); - return pNode2->p2; - } - else - { // pNode1->p1 is positive phase of C - *ppNodeT = Fraig_Not(pNode1->p2); - *ppNodeE = Fraig_Not(pNode2->p1); - return pNode1->p1; - } - } - else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) - { - if ( Fraig_IsComplement(pNode1->p2) ) - { // pNode2->p1 is positive phase of C - *ppNodeT = Fraig_Not(pNode2->p2); - *ppNodeE = Fraig_Not(pNode1->p1); - return pNode2->p1; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Fraig_Not(pNode1->p1); - *ppNodeE = Fraig_Not(pNode2->p2); - return pNode1->p2; - } - } - else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) - { - if ( Fraig_IsComplement(pNode1->p2) ) - { // pNode2->p2 is positive phase of C - *ppNodeT = Fraig_Not(pNode2->p1); - *ppNodeE = Fraig_Not(pNode1->p1); - return pNode2->p2; - } - else - { // pNode1->p2 is positive phase of C - *ppNodeT = Fraig_Not(pNode1->p1); - *ppNodeE = Fraig_Not(pNode2->p1); - return pNode1->p2; - } - } - assert( 0 ); // this is not MUX - return NULL; -} - -/**Function************************************************************* - - Synopsis [Counts the number of EXOR type nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManCountExors( Fraig_Man_t * pMan ) -{ - int i, nExors; - nExors = 0; - for ( i = 0; i < pMan->vNodes->nSize; i++ ) - nExors += Fraig_NodeIsExorType( pMan->vNodes->pArray[i] ); - return nExors; - -} - -/**Function************************************************************* - - Synopsis [Counts the number of EXOR type nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManCountMuxes( Fraig_Man_t * pMan ) -{ - int i, nMuxes; - nMuxes = 0; - for ( i = 0; i < pMan->vNodes->nSize; i++ ) - nMuxes += Fraig_NodeIsMuxType( pMan->vNodes->pArray[i] ); - return nMuxes; - -} - -/**Function************************************************************* - - Synopsis [Returns 1 if siminfo of Node1 is contained in siminfo of Node2.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeSimsContained( Fraig_Man_t * pMan, Fraig_Node_t * pNode1, Fraig_Node_t * pNode2 ) -{ - unsigned * pUnsigned1, * pUnsigned2; - int i; - - // compare random siminfo - pUnsigned1 = pNode1->puSimR; - pUnsigned2 = pNode2->puSimR; - for ( i = 0; i < pMan->nWordsRand; i++ ) - if ( pUnsigned1[i] & ~pUnsigned2[i] ) - return 0; - - // compare systematic siminfo - pUnsigned1 = pNode1->puSimD; - pUnsigned2 = pNode2->puSimD; - for ( i = 0; i < pMan->iWordStart; i++ ) - if ( pUnsigned1[i] & ~pUnsigned2[i] ) - return 0; - - return 1; -} - -/**Function************************************************************* - - Synopsis [Count the number of PI variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_CountPis( Fraig_Man_t * p, Msat_IntVec_t * vVarNums ) -{ - int * pVars, nVars, i, Counter; - - nVars = Msat_IntVecReadSize(vVarNums); - pVars = Msat_IntVecReadArray(vVarNums); - Counter = 0; - for ( i = 0; i < nVars; i++ ) - Counter += Fraig_NodeIsVar( p->vNodes->pArray[pVars[i]] ); - return Counter; -} - - - -/**Function************************************************************* - - Synopsis [Counts the number of EXOR type nodes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_ManPrintRefs( Fraig_Man_t * pMan ) -{ - Fraig_NodeVec_t * vPivots; - Fraig_Node_t * pNode, * pNode2; - int i, k, Counter, nProved; - int clk; - - vPivots = Fraig_NodeVecAlloc( 1000 ); - for ( i = 0; i < pMan->vNodes->nSize; i++ ) - { - pNode = pMan->vNodes->pArray[i]; - - if ( pNode->nOnes == 0 || pNode->nOnes == (unsigned)pMan->nWordsRand * 32 ) - continue; - - if ( pNode->nRefs > 5 ) - { - Fraig_NodeVecPush( vPivots, pNode ); -// printf( "Node %6d : nRefs = %2d Level = %3d.\n", pNode->Num, pNode->nRefs, pNode->Level ); - } - } - printf( "Total nodes = %d. Referenced nodes = %d.\n", pMan->vNodes->nSize, vPivots->nSize ); - -clk = clock(); - // count implications - Counter = nProved = 0; - for ( i = 0; i < vPivots->nSize; i++ ) - for ( k = i+1; k < vPivots->nSize; k++ ) - { - pNode = vPivots->pArray[i]; - pNode2 = vPivots->pArray[k]; - if ( Fraig_NodeSimsContained( pMan, pNode, pNode2 ) ) - { - if ( Fraig_NodeIsImplication( pMan, pNode, pNode2, -1 ) ) - nProved++; - Counter++; - } - else if ( Fraig_NodeSimsContained( pMan, pNode2, pNode ) ) - { - if ( Fraig_NodeIsImplication( pMan, pNode2, pNode, -1 ) ) - nProved++; - Counter++; - } - } - printf( "Number of candidate pairs = %d. Proved = %d.\n", Counter, nProved ); -PRT( "Time", clock() - clk ); - return 0; -} - - -/**Function************************************************************* - - Synopsis [Checks if pNew exists among the implication fanins of pOld.] - - Description [If pNew is an implication fanin of pOld, returns 1. - If Fraig_Not(pNew) is an implication fanin of pOld, return -1. - Otherwise returns 0.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsInSupergate( Fraig_Node_t * pOld, Fraig_Node_t * pNew ) -{ - int RetValue1, RetValue2; - if ( Fraig_Regular(pOld) == Fraig_Regular(pNew) ) - return (pOld == pNew)? 1 : -1; - if ( Fraig_IsComplement(pOld) || Fraig_NodeIsVar(pOld) ) - return 0; - RetValue1 = Fraig_NodeIsInSupergate( pOld->p1, pNew ); - RetValue2 = Fraig_NodeIsInSupergate( pOld->p2, pNew ); - if ( RetValue1 == -1 || RetValue2 == -1 ) - return -1; - if ( RetValue1 == 1 || RetValue2 == 1 ) - return 1; - return 0; -} - - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_CollectSupergate_rec( Fraig_Node_t * pNode, Fraig_NodeVec_t * vSuper, int fFirst, int fStopAtMux ) -{ - // if the new node is complemented or a PI, another gate begins -// if ( Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || Fraig_NodeIsMuxType(pNode) ) - if ( (!fFirst && Fraig_Regular(pNode)->nRefs > 1) || - Fraig_IsComplement(pNode) || Fraig_NodeIsVar(pNode) || - (fStopAtMux && Fraig_NodeIsMuxType(pNode)) ) - { - Fraig_NodeVecPushUnique( vSuper, pNode ); - return; - } - // go through the branches - Fraig_CollectSupergate_rec( pNode->p1, vSuper, 0, fStopAtMux ); - Fraig_CollectSupergate_rec( pNode->p2, vSuper, 0, fStopAtMux ); -} - -/**Function************************************************************* - - Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_CollectSupergate( Fraig_Node_t * pNode, int fStopAtMux ) -{ - Fraig_NodeVec_t * vSuper; - vSuper = Fraig_NodeVecAlloc( 8 ); - Fraig_CollectSupergate_rec( pNode, vSuper, 1, fStopAtMux ); - return vSuper; -} - - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_ManIncrementTravId( Fraig_Man_t * pMan ) -{ - pMan->nTravIds2++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeSetTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - pNode->TravId2 = pMan->nTravIds2; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsTravIdCurrent( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - return pNode->TravId2 == pMan->nTravIds2; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeIsTravIdPrevious( Fraig_Man_t * pMan, Fraig_Node_t * pNode ) -{ - return pNode->TravId2 == pMan->nTravIds2 - 1; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/fraig/fraigVec.c b/src/sat/fraig/fraigVec.c deleted file mode 100644 index ba3feecd..00000000 --- a/src/sat/fraig/fraigVec.c +++ /dev/null @@ -1,545 +0,0 @@ -/**CFile**************************************************************** - - FileName [fraigVec.c] - - PackageName [FRAIG: Functionally reduced AND-INV graphs.] - - Synopsis [Vector of FRAIG nodes.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 2.0. Started - October 1, 2004] - - Revision [$Id: fraigVec.c,v 1.7 2005/07/08 01:01:34 alanmi Exp $] - -***********************************************************************/ - -#include "fraigInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_NodeVecAlloc( int nCap ) -{ - Fraig_NodeVec_t * p; - p = ALLOC( Fraig_NodeVec_t, 1 ); - if ( nCap > 0 && nCap < 8 ) - nCap = 8; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( Fraig_Node_t *, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecFree( Fraig_NodeVec_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Duplicates the integer array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_NodeVec_t * Fraig_NodeVecDup( Fraig_NodeVec_t * pVec ) -{ - Fraig_NodeVec_t * p; - p = ALLOC( Fraig_NodeVec_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = p->nCap? ALLOC( Fraig_Node_t *, p->nCap ) : NULL; - memcpy( p->pArray, pVec->pArray, sizeof(Fraig_Node_t *) * pVec->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t ** Fraig_NodeVecReadArray( Fraig_NodeVec_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecReadSize( Fraig_NodeVec_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecGrow( Fraig_NodeVec_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( Fraig_Node_t *, p->pArray, nCapMin ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecShrink( Fraig_NodeVec_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecClear( Fraig_NodeVec_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecPush( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Fraig_NodeVecGrow( p, 16 ); - else - Fraig_NodeVecGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [Add the element while ensuring uniqueness.] - - Description [Returns 1 if the element was found, and 0 if it was new. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecPushUnique( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Fraig_NodeVecPush( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecPushOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1, * pNode2; - int i; - Fraig_NodeVecPush( p, pNode ); - // find the p of the node - for ( i = p->nSize-1; i > 0; i-- ) - { - pNode1 = p->pArray[i ]; - pNode2 = p->pArray[i-1]; - if ( pNode1 >= pNode2 ) - break; - p->pArray[i ] = pNode2; - p->pArray[i-1] = pNode1; - } -} - -/**Function************************************************************* - - Synopsis [Add the element while ensuring uniqueness in the order.] - - Description [Returns 1 if the element was found, and 0 if it was new. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecPushUniqueOrder( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == pNode ) - return 1; - Fraig_NodeVecPushOrder( p, pNode ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Inserts a new node in the order by arrival times.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecPushOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) -{ - Fraig_Node_t * pNode1, * pNode2; - int i; - Fraig_NodeVecPush( p, pNode ); - // find the p of the node - for ( i = p->nSize-1; i > 0; i-- ) - { - pNode1 = p->pArray[i ]; - pNode2 = p->pArray[i-1]; - if ( Fraig_Regular(pNode1)->Level <= Fraig_Regular(pNode2)->Level ) - break; - p->pArray[i ] = pNode2; - p->pArray[i-1] = pNode1; - } -} - -/**Function************************************************************* - - Synopsis [Add the element while ensuring uniqueness in the order.] - - Description [Returns 1 if the element was found, and 0 if it was new. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecPushUniqueOrderByLevel( Fraig_NodeVec_t * p, Fraig_Node_t * pNode ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == pNode ) - return 1; - Fraig_NodeVecPushOrderByLevel( p, pNode ); - return 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeVecPop( Fraig_NodeVec_t * p ) -{ - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecRemove( Fraig_NodeVec_t * p, Fraig_Node_t * Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - break; - assert( i < p->nSize ); - for ( i++; i < p->nSize; i++ ) - p->pArray[i-1] = p->pArray[i]; - p->nSize--; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecWriteEntry( Fraig_NodeVec_t * p, int i, Fraig_Node_t * Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Fraig_Node_t * Fraig_NodeVecReadEntry( Fraig_NodeVec_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecCompareLevelsIncreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) -{ - int Level1 = Fraig_Regular(*pp1)->Level; - int Level2 = Fraig_Regular(*pp2)->Level; - if ( Level1 < Level2 ) - return -1; - if ( Level1 > Level2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecCompareLevelsDecreasing( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) -{ - int Level1 = Fraig_Regular(*pp1)->Level; - int Level2 = Fraig_Regular(*pp2)->Level; - if ( Level1 > Level2 ) - return -1; - if ( Level1 < Level2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecCompareNumbers( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) -{ - int Num1 = Fraig_Regular(*pp1)->Num; - int Num2 = Fraig_Regular(*pp2)->Num; - if ( Num1 < Num2 ) - return -1; - if ( Num1 > Num2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Fraig_NodeVecCompareRefCounts( Fraig_Node_t ** pp1, Fraig_Node_t ** pp2 ) -{ - int nRefs1 = Fraig_Regular(*pp1)->nRefs; - int nRefs2 = Fraig_Regular(*pp2)->nRefs; - - if ( nRefs1 < nRefs2 ) - return -1; - if ( nRefs1 > nRefs2 ) - return 1; - - nRefs1 = Fraig_Regular(*pp1)->Level; - nRefs2 = Fraig_Regular(*pp2)->Level; - - if ( nRefs1 < nRefs2 ) - return -1; - if ( nRefs1 > nRefs2 ) - return 1; - return 0; -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecSortByLevel( Fraig_NodeVec_t * p, int fIncreasing ) -{ - if ( fIncreasing ) - qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), - (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsIncreasing ); - else - qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), - (int (*)(const void *, const void *)) Fraig_NodeVecCompareLevelsDecreasing ); -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecSortByNumber( Fraig_NodeVec_t * p ) -{ - qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), - (int (*)(const void *, const void *)) Fraig_NodeVecCompareNumbers ); -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Fraig_NodeVecSortByRefCount( Fraig_NodeVec_t * p ) -{ - qsort( (void *)p->pArray, p->nSize, sizeof(Fraig_Node_t *), - (int (*)(const void *, const void *)) Fraig_NodeVecCompareRefCounts ); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/sat/fraig/module.make b/src/sat/fraig/module.make deleted file mode 100644 index cc6eb9d3..00000000 --- a/src/sat/fraig/module.make +++ /dev/null @@ -1,12 +0,0 @@ -SRC += src/sat/fraig/fraigApi.c \ - src/sat/fraig/fraigCanon.c \ - src/sat/fraig/fraigFanout.c \ - src/sat/fraig/fraigFeed.c \ - src/sat/fraig/fraigMan.c \ - src/sat/fraig/fraigMem.c \ - src/sat/fraig/fraigNode.c \ - src/sat/fraig/fraigPrime.c \ - src/sat/fraig/fraigSat.c \ - src/sat/fraig/fraigTable.c \ - src/sat/fraig/fraigUtil.c \ - src/sat/fraig/fraigVec.c diff --git a/src/sat/msat/module.make b/src/sat/msat/module.make deleted file mode 100644 index 0dadfbe1..00000000 --- a/src/sat/msat/module.make +++ /dev/null @@ -1,13 +0,0 @@ -SRC += src/sat/msat/msatActivity.c \ - src/sat/msat/msatClause.c \ - src/sat/msat/msatClauseVec.c \ - src/sat/msat/msatMem.c \ - src/sat/msat/msatOrderJ.c \ - src/sat/msat/msatQueue.c \ - src/sat/msat/msatRead.c \ - src/sat/msat/msatSolverApi.c \ - src/sat/msat/msatSolverCore.c \ - src/sat/msat/msatSolverIo.c \ - src/sat/msat/msatSolverSearch.c \ - src/sat/msat/msatSort.c \ - src/sat/msat/msatVec.c diff --git a/src/sat/msat/msat.h b/src/sat/msat/msat.h deleted file mode 100644 index 53353ba6..00000000 --- a/src/sat/msat/msat.h +++ /dev/null @@ -1,172 +0,0 @@ -/**CFile**************************************************************** - - FileName [msat.h] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [External definitions of the solver.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msat.h,v 1.6 2004/05/12 06:30:20 satrajit Exp $] - -***********************************************************************/ - -#ifndef __MSAT_H__ -#define __MSAT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#ifdef bool -#undef bool -#endif - -#ifndef __MVTYPES_H__ -typedef int bool; -#endif - -typedef struct Msat_Solver_t_ Msat_Solver_t; - -// the vector of intergers and of clauses -typedef struct Msat_IntVec_t_ Msat_IntVec_t; -typedef struct Msat_ClauseVec_t_ Msat_ClauseVec_t; -typedef struct Msat_VarHeap_t_ Msat_VarHeap_t; - -// the return value of the solver -typedef enum { MSAT_FALSE = -1, MSAT_UNKNOWN = 0, MSAT_TRUE = 1 } Msat_Type_t; - -// representation of variables and literals -// the literal (l) is the variable (v) and the sign (s) -// s = 0 the variable is positive -// s = 1 the variable is negative -#define MSAT_VAR2LIT(v,s) (2*(v)+(s)) -#define MSAT_LITNOT(l) ((l)^1) -#define MSAT_LITSIGN(l) ((l)&1) -#define MSAT_LIT2VAR(l) ((l)>>1) - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== satRead.c ============================================================*/ -extern bool Msat_SolverParseDimacs( FILE * pFile, Msat_Solver_t ** p, int fVerbose ); -/*=== satSolver.c ===========================================================*/ -// adding vars, clauses, simplifying the database, and solving -extern bool Msat_SolverAddVar( Msat_Solver_t * p, int Level ); -extern bool Msat_SolverAddClause( Msat_Solver_t * p, Msat_IntVec_t * pLits ); -extern bool Msat_SolverSimplifyDB( Msat_Solver_t * p ); -extern bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * pVecAssumps, int nBackTrackLimit, int nTimeLimit ); -// printing stats, assignments, and clauses -extern void Msat_SolverPrintStats( Msat_Solver_t * p ); -extern void Msat_SolverPrintAssignment( Msat_Solver_t * p ); -extern void Msat_SolverPrintClauses( Msat_Solver_t * p ); -extern void Msat_SolverWriteDimacs( Msat_Solver_t * p, char * pFileName ); -// access to the solver internal data -extern int Msat_SolverReadVarNum( Msat_Solver_t * p ); -extern int Msat_SolverReadClauseNum( Msat_Solver_t * p ); -extern int Msat_SolverReadVarAllocNum( Msat_Solver_t * p ); -extern int * Msat_SolverReadAssignsArray( Msat_Solver_t * p ); -extern int * Msat_SolverReadModelArray( Msat_Solver_t * p ); -extern unsigned Msat_SolverReadTruth( Msat_Solver_t * p ); -extern int Msat_SolverReadBackTracks( Msat_Solver_t * p ); -extern int Msat_SolverReadInspects( Msat_Solver_t * p ); -extern void Msat_SolverSetVerbosity( Msat_Solver_t * p, int fVerbose ); -extern void Msat_SolverSetProofWriting( Msat_Solver_t * p, int fProof ); -extern void Msat_SolverSetVarTypeA( Msat_Solver_t * p, int Var ); -extern void Msat_SolverSetVarMap( Msat_Solver_t * p, Msat_IntVec_t * vVarMap ); -extern void Msat_SolverMarkLastClauseTypeA( Msat_Solver_t * p ); -extern void Msat_SolverMarkClausesStart( Msat_Solver_t * p ); -extern float * Msat_SolverReadFactors( Msat_Solver_t * p ); -// returns the solution after incremental solving -extern int Msat_SolverReadSolutions( Msat_Solver_t * p ); -extern int * Msat_SolverReadSolutionsArray( Msat_Solver_t * p ); -extern Msat_ClauseVec_t * Msat_SolverReadAdjacents( Msat_Solver_t * p ); -extern Msat_IntVec_t * Msat_SolverReadConeVars( Msat_Solver_t * p ); -extern Msat_IntVec_t * Msat_SolverReadVarsUsed( Msat_Solver_t * p ); -/*=== satSolverSearch.c ===========================================================*/ -extern void Msat_SolverRemoveLearned( Msat_Solver_t * p ); -extern void Msat_SolverRemoveMarked( Msat_Solver_t * p ); -/*=== satSolverApi.c ===========================================================*/ -// allocation, cleaning, and freeing the solver -extern Msat_Solver_t * Msat_SolverAlloc( int nVars, double dClaInc, double dClaDecay, double dVarInc, double dVarDecay, bool fVerbose ); -extern void Msat_SolverResize( Msat_Solver_t * pMan, int nVarsAlloc ); -extern void Msat_SolverClean( Msat_Solver_t * p, int nVars ); -extern void Msat_SolverPrepare( Msat_Solver_t * pSat, Msat_IntVec_t * vVars ); -extern void Msat_SolverFree( Msat_Solver_t * p ); -/*=== satVec.c ===========================================================*/ -extern Msat_IntVec_t * Msat_IntVecAlloc( int nCap ); -extern Msat_IntVec_t * Msat_IntVecAllocArray( int * pArray, int nSize ); -extern Msat_IntVec_t * Msat_IntVecAllocArrayCopy( int * pArray, int nSize ); -extern Msat_IntVec_t * Msat_IntVecDup( Msat_IntVec_t * pVec ); -extern Msat_IntVec_t * Msat_IntVecDupArray( Msat_IntVec_t * pVec ); -extern void Msat_IntVecFree( Msat_IntVec_t * p ); -extern void Msat_IntVecFill( Msat_IntVec_t * p, int nSize, int Entry ); -extern int * Msat_IntVecReleaseArray( Msat_IntVec_t * p ); -extern int * Msat_IntVecReadArray( Msat_IntVec_t * p ); -extern int Msat_IntVecReadSize( Msat_IntVec_t * p ); -extern int Msat_IntVecReadEntry( Msat_IntVec_t * p, int i ); -extern int Msat_IntVecReadEntryLast( Msat_IntVec_t * p ); -extern void Msat_IntVecWriteEntry( Msat_IntVec_t * p, int i, int Entry ); -extern void Msat_IntVecGrow( Msat_IntVec_t * p, int nCapMin ); -extern void Msat_IntVecShrink( Msat_IntVec_t * p, int nSizeNew ); -extern void Msat_IntVecClear( Msat_IntVec_t * p ); -extern void Msat_IntVecPush( Msat_IntVec_t * p, int Entry ); -extern int Msat_IntVecPushUnique( Msat_IntVec_t * p, int Entry ); -extern void Msat_IntVecPushUniqueOrder( Msat_IntVec_t * p, int Entry, int fIncrease ); -extern int Msat_IntVecPop( Msat_IntVec_t * p ); -extern void Msat_IntVecSort( Msat_IntVec_t * p, int fReverse ); -/*=== satHeap.c ===========================================================*/ -extern Msat_VarHeap_t * Msat_VarHeapAlloc(); -extern void Msat_VarHeapSetActivity( Msat_VarHeap_t * p, double * pActivity ); -extern void Msat_VarHeapStart( Msat_VarHeap_t * p, int * pVars, int nVars, int nVarsAlloc ); -extern void Msat_VarHeapGrow( Msat_VarHeap_t * p, int nSize ); -extern void Msat_VarHeapStop( Msat_VarHeap_t * p ); -extern void Msat_VarHeapPrint( FILE * pFile, Msat_VarHeap_t * p ); -extern void Msat_VarHeapCheck( Msat_VarHeap_t * p ); -extern void Msat_VarHeapCheckOne( Msat_VarHeap_t * p, int iVar ); -extern int Msat_VarHeapContainsVar( Msat_VarHeap_t * p, int iVar ); -extern void Msat_VarHeapInsert( Msat_VarHeap_t * p, int iVar ); -extern void Msat_VarHeapUpdate( Msat_VarHeap_t * p, int iVar ); -extern void Msat_VarHeapDelete( Msat_VarHeap_t * p, int iVar ); -extern double Msat_VarHeapReadMaxWeight( Msat_VarHeap_t * p ); -extern int Msat_VarHeapCountNodes( Msat_VarHeap_t * p, double WeightLimit ); -extern int Msat_VarHeapReadMax( Msat_VarHeap_t * p ); -extern int Msat_VarHeapGetMax( Msat_VarHeap_t * p ); - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// diff --git a/src/sat/msat/msatActivity.c b/src/sat/msat/msatActivity.c deleted file mode 100644 index 1cd795bd..00000000 --- a/src/sat/msat/msatActivity.c +++ /dev/null @@ -1,160 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatActivity.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [Procedures controlling activity of variables and clauses.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatActivity.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverVarBumpActivity( Msat_Solver_t * p, Msat_Lit_t Lit ) -{ - Msat_Var_t Var; - if ( p->dVarDecay < 0 ) // (negative decay means static variable order -- don't bump) - return; - Var = MSAT_LIT2VAR(Lit); - p->pdActivity[Var] += p->dVarInc; -// p->pdActivity[Var] += p->dVarInc * p->pFactors[Var]; - if ( p->pdActivity[Var] > 1e100 ) - Msat_SolverVarRescaleActivity( p ); - Msat_OrderUpdate( p->pOrder, Var ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverVarDecayActivity( Msat_Solver_t * p ) -{ - if ( p->dVarDecay >= 0 ) - p->dVarInc *= p->dVarDecay; -} - -/**Function************************************************************* - - Synopsis [Divide all variable activities by 1e100.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverVarRescaleActivity( Msat_Solver_t * p ) -{ - int i; - for ( i = 0; i < p->nVars; i++ ) - p->pdActivity[i] *= 1e-100; - p->dVarInc *= 1e-100; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverClaBumpActivity( Msat_Solver_t * p, Msat_Clause_t * pC ) -{ - float Activ; - Activ = Msat_ClauseReadActivity(pC); - if ( Activ + p->dClaInc > 1e20 ) - { - Msat_SolverClaRescaleActivity( p ); - Activ = Msat_ClauseReadActivity( pC ); - } - Msat_ClauseWriteActivity( pC, Activ + (float)p->dClaInc ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverClaDecayActivity( Msat_Solver_t * p ) -{ - p->dClaInc *= p->dClaDecay; -} - -/**Function************************************************************* - - Synopsis [Divide all constraint activities by 1e20.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverClaRescaleActivity( Msat_Solver_t * p ) -{ - Msat_Clause_t ** pLearned; - int nLearned, i; - float Activ; - nLearned = Msat_ClauseVecReadSize( p->vLearned ); - pLearned = Msat_ClauseVecReadArray( p->vLearned ); - for ( i = 0; i < nLearned; i++ ) - { - Activ = Msat_ClauseReadActivity( pLearned[i] ); - Msat_ClauseWriteActivity( pLearned[i], Activ * (float)1e-20 ); - } - p->dClaInc *= 1e-20; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatClause.c b/src/sat/msat/msatClause.c deleted file mode 100644 index 2ba8cd32..00000000 --- a/src/sat/msat/msatClause.c +++ /dev/null @@ -1,529 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatClause.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [Procedures working with SAT clauses.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatClause.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Msat_Clause_t_ -{ - int Num; // unique number of the clause - unsigned fLearned : 1; // 1 if the clause is learned - unsigned fMark : 1; // used to mark visited clauses during proof recording - unsigned fTypeA : 1; // used to mark clauses belonging to A for interpolant computation - unsigned nSize : 14; // the number of literals in the clause - unsigned nSizeAlloc : 15; // the number of bytes allocated for the clause - Msat_Lit_t pData[0]; -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Creates a new clause.] - - Description [Returns FALSE if top-level conflict detected (must be handled); - TRUE otherwise. 'pClause_out' may be set to NULL if clause is already - satisfied by the top-level assignment.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_ClauseCreate( Msat_Solver_t * p, Msat_IntVec_t * vLits, bool fLearned, Msat_Clause_t ** pClause_out ) -{ - int * pAssigns = Msat_SolverReadAssignsArray(p); - Msat_ClauseVec_t ** pvWatched; - Msat_Clause_t * pC; - int * pLits; - int nLits, i, j; - int nBytes; - Msat_Var_t Var; - bool Sign; - - *pClause_out = NULL; - - nLits = Msat_IntVecReadSize(vLits); - pLits = Msat_IntVecReadArray(vLits); - - if ( !fLearned ) - { - int * pSeen = Msat_SolverReadSeenArray( p ); - int nSeenId; - assert( Msat_SolverReadDecisionLevel(p) == 0 ); - // sorting literals makes the code trace-equivalent - // with to the original C++ solver - Msat_IntVecSort( vLits, 0 ); - // increment the counter of seen twice - nSeenId = Msat_SolverIncrementSeenId( p ); - nSeenId = Msat_SolverIncrementSeenId( p ); - // nSeenId - 1 stands for negative - // nSeenId stands for positive - // Remove false literals - - // there is a bug here!!!! - // when the same var in opposite polarities is given, it drops one polarity!!! - - for ( i = j = 0; i < nLits; i++ ) { - // get the corresponding variable - Var = MSAT_LIT2VAR(pLits[i]); - Sign = MSAT_LITSIGN(pLits[i]); // Sign=0 for positive - // check if we already saw this variable in the this clause - if ( pSeen[Var] >= nSeenId - 1 ) - { - if ( (pSeen[Var] != nSeenId) == Sign ) // the same lit - continue; - return 1; // two opposite polarity lits -- don't add the clause - } - // mark the variable as seen - pSeen[Var] = nSeenId - !Sign; - - // analize the value of this literal - if ( pAssigns[Var] != MSAT_VAR_UNASSIGNED ) - { - if ( pAssigns[Var] == pLits[i] ) - return 1; // the clause is always true -- don't add anything - // the literal has no impact - skip it - continue; - } - // otherwise, add this literal to the clause - pLits[j++] = pLits[i]; - } - Msat_IntVecShrink( vLits, j ); - nLits = j; -/* - // the problem with this code is that performance is very - // sensitive to the ordering of adjacency lits - // the best ordering requires fanins first, next fanouts - // this ordering is more convenient to make from FRAIG - - // create the adjacency information - if ( nLits > 2 ) - { - Msat_Var_t VarI, VarJ; - Msat_IntVec_t * pAdjI, * pAdjJ; - - for ( i = 0; i < nLits; i++ ) - { - VarI = MSAT_LIT2VAR(pLits[i]); - pAdjI = (Msat_IntVec_t *)p->vAdjacents->pArray[VarI]; - - for ( j = i+1; j < nLits; j++ ) - { - VarJ = MSAT_LIT2VAR(pLits[j]); - pAdjJ = (Msat_IntVec_t *)p->vAdjacents->pArray[VarJ]; - - Msat_IntVecPushUniqueOrder( pAdjI, VarJ, 1 ); - Msat_IntVecPushUniqueOrder( pAdjJ, VarI, 1 ); - } - } - } -*/ - } - // 'vLits' is now the (possibly) reduced vector of literals. - if ( nLits == 0 ) - return 0; - if ( nLits == 1 ) - return Msat_SolverEnqueue( p, pLits[0], NULL ); - - // Allocate clause: -// nBytes = sizeof(unsigned)*(nLits + 1 + (int)fLearned); - nBytes = sizeof(unsigned)*(nLits + 2 + (int)fLearned); -#ifdef USE_SYSTEM_MEMORY_MANAGEMENT - pC = (Msat_Clause_t *)ALLOC( char, nBytes ); -#else - pC = (Msat_Clause_t *)Msat_MmStepEntryFetch( Msat_SolverReadMem(p), nBytes ); -#endif - pC->Num = p->nClauses++; - pC->fTypeA = 0; - pC->fMark = 0; - pC->fLearned = fLearned; - pC->nSize = nLits; - pC->nSizeAlloc = nBytes; - memcpy( pC->pData, pLits, sizeof(int)*nLits ); - - // For learnt clauses only: - if ( fLearned ) - { - int * pLevel = Msat_SolverReadDecisionLevelArray( p ); - int iLevelMax, iLevelCur, iLitMax; - - // Put the second watch on the literal with highest decision level: - iLitMax = 1; - iLevelMax = pLevel[ MSAT_LIT2VAR(pLits[1]) ]; - for ( i = 2; i < nLits; i++ ) - { - iLevelCur = pLevel[ MSAT_LIT2VAR(pLits[i]) ]; - assert( iLevelCur != -1 ); - if ( iLevelMax < iLevelCur ) - // this is very strange - shouldn't it be??? - // if ( iLevelMax > iLevelCur ) - iLevelMax = iLevelCur, iLitMax = i; - } - pC->pData[1] = pLits[iLitMax]; - pC->pData[iLitMax] = pLits[1]; - - // Bumping: - // (newly learnt clauses should be considered active) - Msat_ClauseWriteActivity( pC, 0.0 ); - Msat_SolverClaBumpActivity( p, pC ); -// if ( nLits < 20 ) - for ( i = 0; i < nLits; i++ ) - { - Msat_SolverVarBumpActivity( p, pLits[i] ); -// Msat_SolverVarBumpActivity( p, pLits[i] ); -// p->pFreq[ MSAT_LIT2VAR(pLits[i]) ]++; - } - } - - // Store clause: - pvWatched = Msat_SolverReadWatchedArray( p ); - Msat_ClauseVecPush( pvWatched[ MSAT_LITNOT(pC->pData[0]) ], pC ); - Msat_ClauseVecPush( pvWatched[ MSAT_LITNOT(pC->pData[1]) ], pC ); - *pClause_out = pC; - return 1; -} - -/**Function************************************************************* - - Synopsis [Deallocates the clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClauseFree( Msat_Solver_t * p, Msat_Clause_t * pC, bool fRemoveWatched ) -{ - if ( fRemoveWatched ) - { - Msat_Lit_t Lit; - Msat_ClauseVec_t ** pvWatched; - pvWatched = Msat_SolverReadWatchedArray( p ); - Lit = MSAT_LITNOT( pC->pData[0] ); - Msat_ClauseRemoveWatch( pvWatched[Lit], pC ); - Lit = MSAT_LITNOT( pC->pData[1] ); - Msat_ClauseRemoveWatch( pvWatched[Lit], pC ); - } - -#ifdef USE_SYSTEM_MEMORY_MANAGEMENT - free( pC ); -#else - Msat_MmStepEntryRecycle( Msat_SolverReadMem(p), (char *)pC, pC->nSizeAlloc ); -#endif - -} - -/**Function************************************************************* - - Synopsis [Access the data field of the clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_ClauseReadLearned( Msat_Clause_t * pC ) { return pC->fLearned; } -int Msat_ClauseReadSize( Msat_Clause_t * pC ) { return pC->nSize; } -int * Msat_ClauseReadLits( Msat_Clause_t * pC ) { return pC->pData; } -bool Msat_ClauseReadMark( Msat_Clause_t * pC ) { return pC->fMark; } -int Msat_ClauseReadNum( Msat_Clause_t * pC ) { return pC->Num; } -bool Msat_ClauseReadTypeA( Msat_Clause_t * pC ) { return pC->fTypeA; } - -void Msat_ClauseSetMark( Msat_Clause_t * pC, bool fMark ) { pC->fMark = fMark; } -void Msat_ClauseSetNum( Msat_Clause_t * pC, int Num ) { pC->Num = Num; } -void Msat_ClauseSetTypeA( Msat_Clause_t * pC, bool fTypeA ) { pC->fTypeA = fTypeA; } - -/**Function************************************************************* - - Synopsis [Checks whether the learned clause is locked.] - - Description [The clause may be locked if it is the reason of a - recent conflict. Such clause cannot be removed from the database.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_ClauseIsLocked( Msat_Solver_t * p, Msat_Clause_t * pC ) -{ - Msat_Clause_t ** pReasons = Msat_SolverReadReasonArray( p ); - return (bool)(pReasons[MSAT_LIT2VAR(pC->pData[0])] == pC); -} - -/**Function************************************************************* - - Synopsis [Reads the activity of the given clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -float Msat_ClauseReadActivity( Msat_Clause_t * pC ) -{ - return *((float *)(pC->pData + pC->nSize)); -} - -/**Function************************************************************* - - Synopsis [Sets the activity of the clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClauseWriteActivity( Msat_Clause_t * pC, float Num ) -{ - *((float *)(pC->pData + pC->nSize)) = Num; -} - -/**Function************************************************************* - - Synopsis [Propages the assignment.] - - Description [The literal that has become true (Lit) is given to this - procedure. The array of current variable assignments is given for - efficiency. The output literal (pLit_out) can be the second watched - literal (if TRUE is returned) or the conflict literal (if FALSE is - returned). This messy interface is used to improve performance. - This procedure accounts for ~50% of the runtime of the solver.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_ClausePropagate( Msat_Clause_t * pC, Msat_Lit_t Lit, int * pAssigns, Msat_Lit_t * pLit_out ) -{ - // make sure the false literal is pC->pData[1] - Msat_Lit_t LitF = MSAT_LITNOT(Lit); - if ( pC->pData[0] == LitF ) - pC->pData[0] = pC->pData[1], pC->pData[1] = LitF; - assert( pC->pData[1] == LitF ); - // if the 0-th watch is true, clause is already satisfied - if ( pAssigns[MSAT_LIT2VAR(pC->pData[0])] == pC->pData[0] ) - return 1; - // look for a new watch - if ( pC->nSize > 2 ) - { - int i; - for ( i = 2; i < (int)pC->nSize; i++ ) - if ( pAssigns[MSAT_LIT2VAR(pC->pData[i])] != MSAT_LITNOT(pC->pData[i]) ) - { - pC->pData[1] = pC->pData[i], pC->pData[i] = LitF; - *pLit_out = MSAT_LITNOT(pC->pData[1]); - return 1; - } - } - // clause is unit under assignment - *pLit_out = pC->pData[0]; - return 0; -} - -/**Function************************************************************* - - Synopsis [Simplifies the clause.] - - Description [Assumes everything has been propagated! (esp. watches - in clauses are NOT unsatisfied)] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_ClauseSimplify( Msat_Clause_t * pC, int * pAssigns ) -{ - Msat_Var_t Var; - int i, j; - for ( i = j = 0; i < (int)pC->nSize; i++ ) - { - Var = MSAT_LIT2VAR(pC->pData[i]); - if ( pAssigns[Var] == MSAT_VAR_UNASSIGNED ) - { - pC->pData[j++] = pC->pData[i]; - continue; - } - if ( pAssigns[Var] == pC->pData[i] ) - return 1; - // otherwise, the value of the literal is false - // make sure, this literal is not watched - assert( i >= 2 ); - } - // if the size has changed, update it and move activity - if ( j < (int)pC->nSize ) - { - float Activ = Msat_ClauseReadActivity(pC); - pC->nSize = j; - Msat_ClauseWriteActivity(pC, Activ); - } - return 0; -} - -/**Function************************************************************* - - Synopsis [Computes reason of conflict in the given clause.] - - Description [If the literal is unassigned, finds the reason by - complementing literals in the given cluase (pC). If the literal is - assigned, makes sure that this literal is the first one in the clause - and computes the complement of all other literals in the clause. - Returns the reason in the given array (vLits_out). If the clause is - learned, bumps its activity.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClauseCalcReason( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_Lit_t Lit, Msat_IntVec_t * vLits_out ) -{ - int i; - // clear the reason - Msat_IntVecClear( vLits_out ); - assert( Lit == MSAT_LIT_UNASSIGNED || Lit == pC->pData[0] ); - for ( i = (Lit != MSAT_LIT_UNASSIGNED); i < (int)pC->nSize; i++ ) - { - assert( Msat_SolverReadAssignsArray(p)[MSAT_LIT2VAR(pC->pData[i])] == MSAT_LITNOT(pC->pData[i]) ); - Msat_IntVecPush( vLits_out, MSAT_LITNOT(pC->pData[i]) ); - } - if ( pC->fLearned ) - Msat_SolverClaBumpActivity( p, pC ); -} - -/**Function************************************************************* - - Synopsis [Removes the given clause from the watched list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClauseRemoveWatch( Msat_ClauseVec_t * vClauses, Msat_Clause_t * pC ) -{ - Msat_Clause_t ** pClauses; - int nClauses, i; - nClauses = Msat_ClauseVecReadSize( vClauses ); - pClauses = Msat_ClauseVecReadArray( vClauses ); - for ( i = 0; pClauses[i] != pC; i++ ) - assert( i < nClauses ); - for ( ; i < nClauses - 1; i++ ) - pClauses[i] = pClauses[i+1]; - Msat_ClauseVecPop( vClauses ); -} - -/**Function************************************************************* - - Synopsis [Prints the given clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClausePrint( Msat_Clause_t * pC ) -{ - int i; - if ( pC == NULL ) - printf( "NULL pointer" ); - else - { - if ( pC->fLearned ) - printf( "Act = %.4f ", Msat_ClauseReadActivity(pC) ); - for ( i = 0; i < (int)pC->nSize; i++ ) - printf( " %s%d", ((pC->pData[i]&1)? "-": ""), pC->pData[i]/2 + 1 ); - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes the given clause in a file in DIMACS format.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClauseWriteDimacs( FILE * pFile, Msat_Clause_t * pC, bool fIncrement ) -{ - int i; - for ( i = 0; i < (int)pC->nSize; i++ ) - fprintf( pFile, "%s%d ", ((pC->pData[i]&1)? "-": ""), pC->pData[i]/2 + (int)(fIncrement>0) ); - if ( fIncrement ) - fprintf( pFile, "0" ); - fprintf( pFile, "\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints the given clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClausePrintSymbols( Msat_Clause_t * pC ) -{ - int i; - if ( pC == NULL ) - printf( "NULL pointer" ); - else - { -// if ( pC->fLearned ) -// printf( "Act = %.4f ", Msat_ClauseReadActivity(pC) ); - for ( i = 0; i < (int)pC->nSize; i++ ) - printf(" "L_LIT, L_lit(pC->pData[i])); - } - printf( "\n" ); -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatClauseVec.c b/src/sat/msat/msatClauseVec.c deleted file mode 100644 index 04691cf2..00000000 --- a/src/sat/msat/msatClauseVec.c +++ /dev/null @@ -1,232 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatClauseVec.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [Procedures working with arrays of SAT clauses.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatClauseVec.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_ClauseVec_t * Msat_ClauseVecAlloc( int nCap ) -{ - Msat_ClauseVec_t * p; - p = ALLOC( Msat_ClauseVec_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( Msat_Clause_t *, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClauseVecFree( Msat_ClauseVec_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_Clause_t ** Msat_ClauseVecReadArray( Msat_ClauseVec_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_ClauseVecReadSize( Msat_ClauseVec_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClauseVecGrow( Msat_ClauseVec_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( Msat_Clause_t *, p->pArray, nCapMin ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClauseVecShrink( Msat_ClauseVec_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClauseVecClear( Msat_ClauseVec_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClauseVecPush( Msat_ClauseVec_t * p, Msat_Clause_t * Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Msat_ClauseVecGrow( p, 16 ); - else - Msat_ClauseVecGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_Clause_t * Msat_ClauseVecPop( Msat_ClauseVec_t * p ) -{ - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_ClauseVecWriteEntry( Msat_ClauseVec_t * p, int i, Msat_Clause_t * Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_Clause_t * Msat_ClauseVecReadEntry( Msat_ClauseVec_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatInt.h b/src/sat/msat/msatInt.h deleted file mode 100644 index 03903abe..00000000 --- a/src/sat/msat/msatInt.h +++ /dev/null @@ -1,306 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatInt.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [Internal definitions of the solver.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatInt.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __MSAT_INT_H__ -#define __MSAT_INT_H__ - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//#include "leaks.h" -#include -#include -#include -#include -#include -#include -#include "msat.h" - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// STRUCTURE DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -#ifdef _MSC_VER -typedef __int64 int64; -#else -typedef long long int64; -#endif - -// outputs the runtime in seconds -#define PRT(a,t) \ - printf( "%s = ", (a) ); printf( "%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC) ) - -// memory management macros -#define ALLOC(type, num) \ - ((type *) malloc(sizeof(type) * (num))) -#define REALLOC(type, obj, num) \ - ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ - ((type *) malloc(sizeof(type) * (num)))) -#define FREE(obj) \ - ((obj) ? (free((char *)(obj)), (obj) = 0) : 0) - -// By default, custom memory management is used -// which guarantees constant time allocation/deallocation -// for SAT clauses and other frequently modified objects. -// For debugging, it is possible use system memory management -// directly. In which case, uncomment the macro below. -//#define USE_SYSTEM_MEMORY_MANAGEMENT - -// internal data structures -typedef struct Msat_Clause_t_ Msat_Clause_t; -typedef struct Msat_Queue_t_ Msat_Queue_t; -typedef struct Msat_Order_t_ Msat_Order_t; -// memory managers (duplicated from Extra for stand-aloneness) -typedef struct Msat_MmFixed_t_ Msat_MmFixed_t; -typedef struct Msat_MmFlex_t_ Msat_MmFlex_t; -typedef struct Msat_MmStep_t_ Msat_MmStep_t; -// variables and literals -typedef int Msat_Lit_t; -typedef int Msat_Var_t; -// the type of return value -#define MSAT_VAR_UNASSIGNED (-1) -#define MSAT_LIT_UNASSIGNED (-2) -#define MSAT_ORDER_UNKNOWN (-3) - -// printing the search tree -#define L_IND "%-*d" -#define L_ind Msat_SolverReadDecisionLevel(p)*3+3,Msat_SolverReadDecisionLevel(p) -#define L_LIT "%s%d" -#define L_lit(Lit) MSAT_LITSIGN(Lit)?"-":"", MSAT_LIT2VAR(Lit)+1 - -typedef struct Msat_SolverStats_t_ Msat_SolverStats_t; -struct Msat_SolverStats_t_ -{ - int64 nStarts; // the number of restarts - int64 nDecisions; // the number of decisions - int64 nPropagations; // the number of implications - int64 nInspects; // the number of times clauses are vising while watching them - int64 nConflicts; // the number of conflicts - int64 nSuccesses; // the number of sat assignments found -}; - -typedef struct Msat_SearchParams_t_ Msat_SearchParams_t; -struct Msat_SearchParams_t_ -{ - double dVarDecay; - double dClaDecay; -}; - -// sat solver data structure visible through all the internal files -struct Msat_Solver_t_ -{ - int nClauses; // the total number of clauses - int nClausesStart; // the number of clauses before adding - Msat_ClauseVec_t * vClauses; // problem clauses - Msat_ClauseVec_t * vLearned; // learned clauses - double dClaInc; // Amount to bump next clause with. - double dClaDecay; // INVERSE decay factor for clause activity: stores 1/decay. - - double * pdActivity; // A heuristic measurement of the activity of a variable. - float * pFactors; // the multiplicative factors of variable activity - double dVarInc; // Amount to bump next variable with. - double dVarDecay; // INVERSE decay factor for variable activity: stores 1/decay. Use negative value for static variable order. - Msat_Order_t * pOrder; // Keeps track of the decision variable order. - - Msat_ClauseVec_t ** pvWatched; // 'pvWatched[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). - Msat_Queue_t * pQueue; // Propagation queue. - - int nVars; // the current number of variables - int nVarsAlloc; // the maximum allowed number of variables - int * pAssigns; // The current assignments (literals or MSAT_VAR_UNKOWN) - int * pModel; // The satisfying assignment - Msat_IntVec_t * vTrail; // List of assignments made. - Msat_IntVec_t * vTrailLim; // Separator indices for different decision levels in 'trail'. - Msat_Clause_t ** pReasons; // 'reason[var]' is the clause that implied the variables current value, or 'NULL' if none. - int * pLevel; // 'level[var]' is the decision level at which assignment was made. - int nLevelRoot; // Level of first proper decision. - - double dRandSeed; // For the internal random number generator (makes solver deterministic over different platforms). - - bool fVerbose; // the verbosity flag - double dProgress; // Set by 'search()'. - - // the variable cone and variable connectivity - Msat_IntVec_t * vConeVars; - Msat_IntVec_t * vVarsUsed; - Msat_ClauseVec_t * vAdjacents; - - // internal data used during conflict analysis - int * pSeen; // time when a lit was seen for the last time - int nSeenId; // the id of current seeing - Msat_IntVec_t * vReason; // the temporary array of literals - Msat_IntVec_t * vTemp; // the temporary array of literals - int * pFreq; // the number of times each var participated in conflicts - - // the memory manager - Msat_MmStep_t * pMem; - - // statistics - Msat_SolverStats_t Stats; - int nTwoLits; - int nTwoLitsL; - int nClausesInit; - int nClausesAlloc; - int nClausesAllocL; - int nBackTracks; -}; - -struct Msat_ClauseVec_t_ -{ - Msat_Clause_t ** pArray; - int nSize; - int nCap; -}; - -struct Msat_IntVec_t_ -{ - int * pArray; - int nSize; - int nCap; -}; - -//////////////////////////////////////////////////////////////////////// -/// GLOBAL VARIABLES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== satActivity.c ===========================================================*/ -extern void Msat_SolverVarDecayActivity( Msat_Solver_t * p ); -extern void Msat_SolverVarRescaleActivity( Msat_Solver_t * p ); -extern void Msat_SolverClaDecayActivity( Msat_Solver_t * p ); -extern void Msat_SolverClaRescaleActivity( Msat_Solver_t * p ); -/*=== satSolverApi.c ===========================================================*/ -extern Msat_Clause_t * Msat_SolverReadClause( Msat_Solver_t * p, int Num ); -/*=== satSolver.c ===========================================================*/ -extern int Msat_SolverReadDecisionLevel( Msat_Solver_t * p ); -extern int * Msat_SolverReadDecisionLevelArray( Msat_Solver_t * p ); -extern Msat_Clause_t ** Msat_SolverReadReasonArray( Msat_Solver_t * p ); -extern Msat_Type_t Msat_SolverReadVarValue( Msat_Solver_t * p, Msat_Var_t Var ); -extern Msat_ClauseVec_t * Msat_SolverReadLearned( Msat_Solver_t * p ); -extern Msat_ClauseVec_t ** Msat_SolverReadWatchedArray( Msat_Solver_t * p ); -extern int * Msat_SolverReadSeenArray( Msat_Solver_t * p ); -extern int Msat_SolverIncrementSeenId( Msat_Solver_t * p ); -extern Msat_MmStep_t * Msat_SolverReadMem( Msat_Solver_t * p ); -extern void Msat_SolverClausesIncrement( Msat_Solver_t * p ); -extern void Msat_SolverClausesDecrement( Msat_Solver_t * p ); -extern void Msat_SolverClausesIncrementL( Msat_Solver_t * p ); -extern void Msat_SolverClausesDecrementL( Msat_Solver_t * p ); -extern void Msat_SolverVarBumpActivity( Msat_Solver_t * p, Msat_Lit_t Lit ); -extern void Msat_SolverClaBumpActivity( Msat_Solver_t * p, Msat_Clause_t * pC ); -extern bool Msat_SolverEnqueue( Msat_Solver_t * p, Msat_Lit_t Lit, Msat_Clause_t * pC ); -extern double Msat_SolverProgressEstimate( Msat_Solver_t * p ); -/*=== satSolverSearch.c ===========================================================*/ -extern bool Msat_SolverAssume( Msat_Solver_t * p, Msat_Lit_t Lit ); -extern Msat_Clause_t * Msat_SolverPropagate( Msat_Solver_t * p ); -extern void Msat_SolverCancelUntil( Msat_Solver_t * p, int Level ); -extern Msat_Type_t Msat_SolverSearch( Msat_Solver_t * p, int nConfLimit, int nLearnedLimit, int nBackTrackLimit, Msat_SearchParams_t * pPars ); -/*=== satQueue.c ===========================================================*/ -extern Msat_Queue_t * Msat_QueueAlloc( int nVars ); -extern void Msat_QueueFree( Msat_Queue_t * p ); -extern int Msat_QueueReadSize( Msat_Queue_t * p ); -extern void Msat_QueueInsert( Msat_Queue_t * p, int Lit ); -extern int Msat_QueueExtract( Msat_Queue_t * p ); -extern void Msat_QueueClear( Msat_Queue_t * p ); -/*=== satOrder.c ===========================================================*/ -extern Msat_Order_t * Msat_OrderAlloc( Msat_Solver_t * pSat ); -extern void Msat_OrderSetBounds( Msat_Order_t * p, int nVarsMax ); -extern void Msat_OrderClean( Msat_Order_t * p, Msat_IntVec_t * vCone ); -extern int Msat_OrderCheck( Msat_Order_t * p ); -extern void Msat_OrderFree( Msat_Order_t * p ); -extern int Msat_OrderVarSelect( Msat_Order_t * p ); -extern void Msat_OrderVarAssigned( Msat_Order_t * p, int Var ); -extern void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var ); -extern void Msat_OrderUpdate( Msat_Order_t * p, int Var ); -/*=== satClause.c ===========================================================*/ -extern bool Msat_ClauseCreate( Msat_Solver_t * p, Msat_IntVec_t * vLits, bool fLearnt, Msat_Clause_t ** pClause_out ); -extern Msat_Clause_t * Msat_ClauseCreateFake( Msat_Solver_t * p, Msat_IntVec_t * vLits ); -extern Msat_Clause_t * Msat_ClauseCreateFakeLit( Msat_Solver_t * p, Msat_Lit_t Lit ); -extern bool Msat_ClauseReadLearned( Msat_Clause_t * pC ); -extern int Msat_ClauseReadSize( Msat_Clause_t * pC ); -extern int * Msat_ClauseReadLits( Msat_Clause_t * pC ); -extern bool Msat_ClauseReadMark( Msat_Clause_t * pC ); -extern void Msat_ClauseSetMark( Msat_Clause_t * pC, bool fMark ); -extern int Msat_ClauseReadNum( Msat_Clause_t * pC ); -extern void Msat_ClauseSetNum( Msat_Clause_t * pC, int Num ); -extern bool Msat_ClauseReadTypeA( Msat_Clause_t * pC ); -extern void Msat_ClauseSetTypeA( Msat_Clause_t * pC, bool fTypeA ); -extern bool Msat_ClauseIsLocked( Msat_Solver_t * p, Msat_Clause_t * pC ); -extern float Msat_ClauseReadActivity( Msat_Clause_t * pC ); -extern void Msat_ClauseWriteActivity( Msat_Clause_t * pC, float Num ); -extern void Msat_ClauseFree( Msat_Solver_t * p, Msat_Clause_t * pC, bool fRemoveWatched ); -extern bool Msat_ClausePropagate( Msat_Clause_t * pC, Msat_Lit_t Lit, int * pAssigns, Msat_Lit_t * pLit_out ); -extern bool Msat_ClauseSimplify( Msat_Clause_t * pC, int * pAssigns ); -extern void Msat_ClauseCalcReason( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_Lit_t Lit, Msat_IntVec_t * vLits_out ); -extern void Msat_ClauseRemoveWatch( Msat_ClauseVec_t * vClauses, Msat_Clause_t * pC ); -extern void Msat_ClausePrint( Msat_Clause_t * pC ); -extern void Msat_ClausePrintSymbols( Msat_Clause_t * pC ); -extern void Msat_ClauseWriteDimacs( FILE * pFile, Msat_Clause_t * pC, bool fIncrement ); -extern unsigned Msat_ClauseComputeTruth( Msat_Solver_t * p, Msat_Clause_t * pC ); -/*=== satSort.c ===========================================================*/ -extern void Msat_SolverSortDB( Msat_Solver_t * p ); -/*=== satClauseVec.c ===========================================================*/ -extern Msat_ClauseVec_t * Msat_ClauseVecAlloc( int nCap ); -extern void Msat_ClauseVecFree( Msat_ClauseVec_t * p ); -extern Msat_Clause_t ** Msat_ClauseVecReadArray( Msat_ClauseVec_t * p ); -extern int Msat_ClauseVecReadSize( Msat_ClauseVec_t * p ); -extern void Msat_ClauseVecGrow( Msat_ClauseVec_t * p, int nCapMin ); -extern void Msat_ClauseVecShrink( Msat_ClauseVec_t * p, int nSizeNew ); -extern void Msat_ClauseVecClear( Msat_ClauseVec_t * p ); -extern void Msat_ClauseVecPush( Msat_ClauseVec_t * p, Msat_Clause_t * Entry ); -extern Msat_Clause_t * Msat_ClauseVecPop( Msat_ClauseVec_t * p ); -extern void Msat_ClauseVecWriteEntry( Msat_ClauseVec_t * p, int i, Msat_Clause_t * Entry ); -extern Msat_Clause_t * Msat_ClauseVecReadEntry( Msat_ClauseVec_t * p, int i ); - -/*=== satMem.c ===========================================================*/ -// fixed-size-block memory manager -extern Msat_MmFixed_t * Msat_MmFixedStart( int nEntrySize ); -extern void Msat_MmFixedStop( Msat_MmFixed_t * p, int fVerbose ); -extern char * Msat_MmFixedEntryFetch( Msat_MmFixed_t * p ); -extern void Msat_MmFixedEntryRecycle( Msat_MmFixed_t * p, char * pEntry ); -extern void Msat_MmFixedRestart( Msat_MmFixed_t * p ); -extern int Msat_MmFixedReadMemUsage( Msat_MmFixed_t * p ); -// flexible-size-block memory manager -extern Msat_MmFlex_t * Msat_MmFlexStart(); -extern void Msat_MmFlexStop( Msat_MmFlex_t * p, int fVerbose ); -extern char * Msat_MmFlexEntryFetch( Msat_MmFlex_t * p, int nBytes ); -extern int Msat_MmFlexReadMemUsage( Msat_MmFlex_t * p ); -// hierarchical memory manager -extern Msat_MmStep_t * Msat_MmStepStart( int nSteps ); -extern void Msat_MmStepStop( Msat_MmStep_t * p, int fVerbose ); -extern char * Msat_MmStepEntryFetch( Msat_MmStep_t * p, int nBytes ); -extern void Msat_MmStepEntryRecycle( Msat_MmStep_t * p, char * pEntry, int nBytes ); -extern int Msat_MmStepReadMemUsage( Msat_MmStep_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// -#endif diff --git a/src/sat/msat/msatMem.c b/src/sat/msat/msatMem.c deleted file mode 100644 index 30bf4a96..00000000 --- a/src/sat/msat/msatMem.c +++ /dev/null @@ -1,529 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatMem.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [Memory managers borrowed from Extra.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatMem.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Msat_MmFixed_t_ -{ - // information about individual entries - int nEntrySize; // the size of one entry - int nEntriesAlloc; // the total number of entries allocated - int nEntriesUsed; // the number of entries in use - int nEntriesMax; // the max number of entries in use - char * pEntriesFree; // the linked list of free entries - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - -struct Msat_MmFlex_t_ -{ - // information about individual entries - int nEntriesUsed; // the number of entries allocated - char * pCurrent; // the current pointer to free memory - char * pEnd; // the first entry outside the free memory - - // this is where the memory is stored - int nChunkSize; // the size of one chunk - int nChunksAlloc; // the maximum number of memory chunks - int nChunks; // the current number of memory chunks - char ** pChunks; // the allocated memory - - // statistics - int nMemoryUsed; // memory used in the allocated entries - int nMemoryAlloc; // memory allocated -}; - - -struct Msat_MmStep_t_ -{ - int nMems; // the number of fixed memory managers employed - Msat_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc - int nMapSize; // the size of the memory array - Msat_MmFixed_t ** pMap; // maps the number of bytes into its memory manager -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates memory pieces of fixed size.] - - Description [The size of the chunk is computed as the minimum of - 1024 entries and 64K. Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_MmFixed_t * Msat_MmFixedStart( int nEntrySize ) -{ - Msat_MmFixed_t * p; - - p = ALLOC( Msat_MmFixed_t, 1 ); - memset( p, 0, sizeof(Msat_MmFixed_t) ); - - p->nEntrySize = nEntrySize; - p->nEntriesAlloc = 0; - p->nEntriesUsed = 0; - p->pEntriesFree = NULL; - - if ( nEntrySize * (1 << 10) < (1<<16) ) - p->nChunkSize = (1 << 10); - else - p->nChunkSize = (1<<16) / nEntrySize; - if ( p->nChunkSize < 8 ) - p->nChunkSize = 8; - - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_MmFixedStop( Msat_MmFixed_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", - p->nEntrySize, p->nChunkSize, p->nChunks ); - printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", - p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Msat_MmFixedEntryFetch( Msat_MmFixed_t * p ) -{ - char * pTemp; - int i; - - // check if there are still free entries - if ( p->nEntriesUsed == p->nEntriesAlloc ) - { // need to allocate more entries - assert( p->pEntriesFree == NULL ); - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - p->pEntriesFree = ALLOC( char, p->nEntrySize * p->nChunkSize ); - p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; - // transform these entries into a linked list - pTemp = p->pEntriesFree; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pEntriesFree; - // add to the number of entries allocated - p->nEntriesAlloc += p->nChunkSize; - } - // incrememt the counter of used entries - p->nEntriesUsed++; - if ( p->nEntriesMax < p->nEntriesUsed ) - p->nEntriesMax = p->nEntriesUsed; - // return the first entry in the free entry list - pTemp = p->pEntriesFree; - p->pEntriesFree = *((char **)pTemp); - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_MmFixedEntryRecycle( Msat_MmFixed_t * p, char * pEntry ) -{ - // decrement the counter of used entries - p->nEntriesUsed--; - // add the entry to the linked list of free entries - *((char **)pEntry) = p->pEntriesFree; - p->pEntriesFree = pEntry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [Relocates all the memory except the first chunk.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_MmFixedRestart( Msat_MmFixed_t * p ) -{ - int i; - char * pTemp; - - // deallocate all chunks except the first one - for ( i = 1; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - p->nChunks = 1; - // transform these entries into a linked list - pTemp = p->pChunks[0]; - for ( i = 1; i < p->nChunkSize; i++ ) - { - *((char **)pTemp) = pTemp + p->nEntrySize; - pTemp += p->nEntrySize; - } - // set the last link - *((char **)pTemp) = NULL; - // set the free entry list - p->pEntriesFree = p->pChunks[0]; - // set the correct statistics - p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; - p->nMemoryUsed = 0; - p->nEntriesAlloc = p->nChunkSize; - p->nEntriesUsed = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_MmFixedReadMemUsage( Msat_MmFixed_t * p ) -{ - return p->nMemoryAlloc; -} - - - -/**Function************************************************************* - - Synopsis [Allocates entries of flexible size.] - - Description [Can only work with entry size at least 4 byte long.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_MmFlex_t * Msat_MmFlexStart() -{ - Msat_MmFlex_t * p; - - p = ALLOC( Msat_MmFlex_t, 1 ); - memset( p, 0, sizeof(Msat_MmFlex_t) ); - - p->nEntriesUsed = 0; - p->pCurrent = NULL; - p->pEnd = NULL; - - p->nChunkSize = (1 << 12); - p->nChunksAlloc = 64; - p->nChunks = 0; - p->pChunks = ALLOC( char *, p->nChunksAlloc ); - - p->nMemoryUsed = 0; - p->nMemoryAlloc = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_MmFlexStop( Msat_MmFlex_t * p, int fVerbose ) -{ - int i; - if ( p == NULL ) - return; - if ( fVerbose ) - { - printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", - p->nChunkSize, p->nChunks ); - printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", - p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); - } - for ( i = 0; i < p->nChunks; i++ ) - free( p->pChunks[i] ); - free( p->pChunks ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Msat_MmFlexEntryFetch( Msat_MmFlex_t * p, int nBytes ) -{ - char * pTemp; - // check if there are still free entries - if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) - { // need to allocate more entries - if ( p->nChunks == p->nChunksAlloc ) - { - p->nChunksAlloc *= 2; - p->pChunks = REALLOC( char *, p->pChunks, p->nChunksAlloc ); - } - if ( nBytes > p->nChunkSize ) - { - // resize the chunk size if more memory is requested than it can give - // (ideally, this should never happen) - p->nChunkSize = 2 * nBytes; - } - p->pCurrent = ALLOC( char, p->nChunkSize ); - p->pEnd = p->pCurrent + p->nChunkSize; - p->nMemoryAlloc += p->nChunkSize; - // add the chunk to the chunk storage - p->pChunks[ p->nChunks++ ] = p->pCurrent; - } - assert( p->pCurrent + nBytes <= p->pEnd ); - // increment the counter of used entries - p->nEntriesUsed++; - // keep track of the memory used - p->nMemoryUsed += nBytes; - // return the next entry - pTemp = p->pCurrent; - p->pCurrent += nBytes; - return pTemp; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_MmFlexReadMemUsage( Msat_MmFlex_t * p ) -{ - return p->nMemoryAlloc; -} - - - - - -/**Function************************************************************* - - Synopsis [Starts the hierarchical memory manager.] - - Description [This manager can allocate entries of any size. - Iternally they are mapped into the entries with the number of bytes - equal to the power of 2. The smallest entry size is 8 bytes. The - next one is 16 bytes etc. So, if the user requests 6 bytes, he gets - 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. - The input parameters "nSteps" says how many fixed memory managers - are employed internally. Calling this procedure with nSteps equal - to 10 results in 10 hierarchically arranged internal memory managers, - which can allocate up to 4096 (1Kb) entries. Requests for larger - entries are handed over to malloc() and then free()ed.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_MmStep_t * Msat_MmStepStart( int nSteps ) -{ - Msat_MmStep_t * p; - int i, k; - p = ALLOC( Msat_MmStep_t, 1 ); - p->nMems = nSteps; - // start the fixed memory managers - p->pMems = ALLOC( Msat_MmFixed_t *, p->nMems ); - for ( i = 0; i < p->nMems; i++ ) - p->pMems[i] = Msat_MmFixedStart( (8<nMapSize = (4<nMems); - p->pMap = ALLOC( Msat_MmFixed_t *, p->nMapSize+1 ); - p->pMap[0] = NULL; - for ( k = 1; k <= 4; k++ ) - p->pMap[k] = p->pMems[0]; - for ( i = 0; i < p->nMems; i++ ) - for ( k = (4<pMap[k] = p->pMems[i]; -//for ( i = 1; i < 100; i ++ ) -//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Stops the memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_MmStepStop( Msat_MmStep_t * p, int fVerbose ) -{ - int i; - for ( i = 0; i < p->nMems; i++ ) - Msat_MmFixedStop( p->pMems[i], fVerbose ); - free( p->pMems ); - free( p->pMap ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Creates the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Msat_MmStepEntryFetch( Msat_MmStep_t * p, int nBytes ) -{ - if ( nBytes == 0 ) - return NULL; - if ( nBytes > p->nMapSize ) - { -// printf( "Allocating %d bytes.\n", nBytes ); - return ALLOC( char, nBytes ); - } - return Msat_MmFixedEntryFetch( p->pMap[nBytes] ); -} - - -/**Function************************************************************* - - Synopsis [Recycles the entry.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_MmStepEntryRecycle( Msat_MmStep_t * p, char * pEntry, int nBytes ) -{ - if ( nBytes == 0 ) - return; - if ( nBytes > p->nMapSize ) - { - free( pEntry ); - return; - } - Msat_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_MmStepReadMemUsage( Msat_MmStep_t * p ) -{ - int i, nMemTotal = 0; - for ( i = 0; i < p->nMems; i++ ) - nMemTotal += p->pMems[i]->nMemoryAlloc; - return nMemTotal; -} diff --git a/src/sat/msat/msatOrderH.c b/src/sat/msat/msatOrderH.c deleted file mode 100644 index 956e7fc6..00000000 --- a/src/sat/msat/msatOrderH.c +++ /dev/null @@ -1,405 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatOrder.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [The manager of variable assignment.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatOrder.c,v 1.0 2005/05/30 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -// the variable package data structure -struct Msat_Order_t_ -{ - Msat_Solver_t * pSat; // the SAT solver - Msat_IntVec_t * vIndex; // the heap - Msat_IntVec_t * vHeap; // the mapping of var num into its heap num -}; - -//The solver can communicate to the variable order the following parts: -//- the array of current assignments (pSat->pAssigns) -//- the array of variable activities (pSat->pdActivity) -//- the array of variables currently in the cone (pSat->vConeVars) -//- the array of arrays of variables adjucent to each(pSat->vAdjacents) - -#define HLEFT(i) ((i)<<1) -#define HRIGHT(i) (((i)<<1)+1) -#define HPARENT(i) ((i)>>1) -#define HCOMPARE(p, i, j) ((p)->pSat->pdActivity[i] > (p)->pSat->pdActivity[j]) -#define HHEAP(p, i) ((p)->vHeap->pArray[i]) -#define HSIZE(p) ((p)->vHeap->nSize) -#define HOKAY(p, i) ((i) >= 0 && (i) < (p)->vIndex->nSize) -#define HINHEAP(p, i) (HOKAY(p, i) && (p)->vIndex->pArray[i] != 0) -#define HEMPTY(p) (HSIZE(p) == 1) - -static int Msat_HeapCheck_rec( Msat_Order_t * p, int i ); -static int Msat_HeapGetTop( Msat_Order_t * p ); -static void Msat_HeapInsert( Msat_Order_t * p, int n ); -static void Msat_HeapIncrease( Msat_Order_t * p, int n ); -static void Msat_HeapPercolateUp( Msat_Order_t * p, int i ); -static void Msat_HeapPercolateDown( Msat_Order_t * p, int i ); - -extern int timeSelect; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the ordering structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_Order_t * Msat_OrderAlloc( Msat_Solver_t * pSat ) -{ - Msat_Order_t * p; - p = ALLOC( Msat_Order_t, 1 ); - memset( p, 0, sizeof(Msat_Order_t) ); - p->pSat = pSat; - p->vIndex = Msat_IntVecAlloc( 0 ); - p->vHeap = Msat_IntVecAlloc( 0 ); - Msat_OrderSetBounds( p, pSat->nVarsAlloc ); - return p; -} - -/**Function************************************************************* - - Synopsis [Sets the bound of the ordering structure.] - - Description [Should be called whenever the SAT solver is resized.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderSetBounds( Msat_Order_t * p, int nVarsMax ) -{ - Msat_IntVecGrow( p->vIndex, nVarsMax ); - Msat_IntVecGrow( p->vHeap, nVarsMax + 1 ); - p->vIndex->nSize = nVarsMax; - p->vHeap->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [Cleans the ordering structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderClean( Msat_Order_t * p, Msat_IntVec_t * vCone ) -{ - int i; - for ( i = 0; i < p->vIndex->nSize; i++ ) - p->vIndex->pArray[i] = 0; - for ( i = 0; i < vCone->nSize; i++ ) - { - assert( i+1 < p->vHeap->nCap ); - p->vHeap->pArray[i+1] = vCone->pArray[i]; - - assert( vCone->pArray[i] < p->vIndex->nSize ); - p->vIndex->pArray[vCone->pArray[i]] = i+1; - } - p->vHeap->nSize = vCone->nSize + 1; -} - -/**Function************************************************************* - - Synopsis [Checks that the J-boundary is okay.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_OrderCheck( Msat_Order_t * p ) -{ - return Msat_HeapCheck_rec( p, 1 ); -} - -/**Function************************************************************* - - Synopsis [Frees the ordering structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderFree( Msat_Order_t * p ) -{ - Msat_IntVecFree( p->vHeap ); - Msat_IntVecFree( p->vIndex ); - free( p ); -} - - - -/**Function************************************************************* - - Synopsis [Selects the next variable to assign.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_OrderVarSelect( Msat_Order_t * p ) -{ - // Activity based decision: -// while (!heap.empty()){ -// Var next = heap.getmin(); -// if (toLbool(assigns[next]) == l_Undef) -// return next; -// } -// return var_Undef; - - int Var; - int clk = clock(); - - while ( !HEMPTY(p) ) - { - Var = Msat_HeapGetTop(p); - if ( (p)->pSat->pAssigns[Var] == MSAT_VAR_UNASSIGNED ) - { -//assert( Msat_OrderCheck(p) ); -timeSelect += clock() - clk; - return Var; - } - } - return MSAT_ORDER_UNKNOWN; -} - -/**Function************************************************************* - - Synopsis [Updates J-boundary when the variable is assigned.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderVarAssigned( Msat_Order_t * p, int Var ) -{ -} - -/**Function************************************************************* - - Synopsis [Updates the order after a variable is unassigned.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var ) -{ -// if (!heap.inHeap(x)) -// heap.insert(x); - - int clk = clock(); - if ( !HINHEAP(p,Var) ) - Msat_HeapInsert( p, Var ); -timeSelect += clock() - clk; -} - -/**Function************************************************************* - - Synopsis [Updates the order after a variable changed weight.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderUpdate( Msat_Order_t * p, int Var ) -{ -// if (heap.inHeap(x)) -// heap.increase(x); - - int clk = clock(); - if ( HINHEAP(p,Var) ) - Msat_HeapIncrease( p, Var ); -timeSelect += clock() - clk; -} - - - - -/**Function************************************************************* - - Synopsis [Checks the heap property recursively.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_HeapCheck_rec( Msat_Order_t * p, int i ) -{ - return i >= HSIZE(p) || - ( HPARENT(i) == 0 || !HCOMPARE(p, HHEAP(p, i), HHEAP(p, HPARENT(i))) ) && - Msat_HeapCheck_rec( p, HLEFT(i) ) && Msat_HeapCheck_rec( p, HRIGHT(i) ); -} - -/**Function************************************************************* - - Synopsis [Retrieves the minimum element.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_HeapGetTop( Msat_Order_t * p ) -{ - int Result, NewTop; - Result = HHEAP(p, 1); - NewTop = Msat_IntVecPop( p->vHeap ); - p->vHeap->pArray[1] = NewTop; - p->vIndex->pArray[NewTop] = 1; - p->vIndex->pArray[Result] = 0; - if ( p->vHeap->nSize > 1 ) - Msat_HeapPercolateDown( p, 1 ); - return Result; -} - -/**Function************************************************************* - - Synopsis [Inserts the new element.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_HeapInsert( Msat_Order_t * p, int n ) -{ - assert( HOKAY(p, n) ); - p->vIndex->pArray[n] = HSIZE(p); - Msat_IntVecPush( p->vHeap, n ); - Msat_HeapPercolateUp( p, p->vIndex->pArray[n] ); -} - -/**Function************************************************************* - - Synopsis [Inserts the new element.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_HeapIncrease( Msat_Order_t * p, int n ) -{ - Msat_HeapPercolateUp( p, p->vIndex->pArray[n] ); -} - -/**Function************************************************************* - - Synopsis [Moves the entry up.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_HeapPercolateUp( Msat_Order_t * p, int i ) -{ - int x = HHEAP(p, i); - while ( HPARENT(i) != 0 && HCOMPARE(p, x, HHEAP(p, HPARENT(i))) ) - { - p->vHeap->pArray[i] = HHEAP(p, HPARENT(i)); - p->vIndex->pArray[HHEAP(p, i)] = i; - i = HPARENT(i); - } - p->vHeap->pArray[i] = x; - p->vIndex->pArray[x] = i; -} - -/**Function************************************************************* - - Synopsis [Moves the entry down.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_HeapPercolateDown( Msat_Order_t * p, int i ) -{ - int x = HHEAP(p, i); - int Child; - while ( HLEFT(i) < HSIZE(p) ) - { - if ( HRIGHT(i) < HSIZE(p) && HCOMPARE(p, HHEAP(p, HRIGHT(i)), HHEAP(p, HLEFT(i))) ) - Child = HRIGHT(i); - else - Child = HLEFT(i); - if ( !HCOMPARE(p, HHEAP(p, Child), x) ) - break; - p->vHeap->pArray[i] = HHEAP(p, Child); - p->vIndex->pArray[HHEAP(p, i)] = i; - i = Child; - } - p->vHeap->pArray[i] = x; - p->vIndex->pArray[x] = i; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatOrderJ.c b/src/sat/msat/msatOrderJ.c deleted file mode 100644 index 4db7ff7b..00000000 --- a/src/sat/msat/msatOrderJ.c +++ /dev/null @@ -1,472 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatOrder.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [The manager of variable assignment.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatOrder.c,v 1.0 2005/05/30 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -/* -The J-boundary (justification boundary) is defined as a set of unassigned -variables belonging to the cone of interest, such that for each of them, -there exist an adjacent assigned variable in the cone of interest. -*/ - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Msat_OrderVar_t_ Msat_OrderVar_t; -typedef struct Msat_OrderRing_t_ Msat_OrderRing_t; - -// the variable data structure -struct Msat_OrderVar_t_ -{ - Msat_OrderVar_t * pNext; - Msat_OrderVar_t * pPrev; - int Num; -}; - -// the ring of variables data structure (J-boundary) -struct Msat_OrderRing_t_ -{ - Msat_OrderVar_t * pRoot; - int nItems; -}; - -// the variable package data structure -struct Msat_Order_t_ -{ - Msat_Solver_t * pSat; // the SAT solver - Msat_OrderVar_t * pVars; // the storage for variables - int nVarsAlloc; // the number of variables allocated - Msat_OrderRing_t rVars; // the J-boundary as a ring of variables -}; - -//The solver can communicate to the variable order the following parts: -//- the array of current assignments (pSat->pAssigns) -//- the array of variable activities (pSat->pdActivity) -//- the array of variables currently in the cone (pSat->vConeVars) -//- the array of arrays of variables adjucent to each(pSat->vAdjacents) - -#define Msat_OrderVarIsInBoundary( p, i ) ((p)->pVars[i].pNext) -#define Msat_OrderVarIsAssigned( p, i ) ((p)->pSat->pAssigns[i] != MSAT_VAR_UNASSIGNED) -#define Msat_OrderVarIsUsedInCone( p, i ) ((p)->pSat->vVarsUsed->pArray[i]) - -// iterator through the entries in J-boundary -#define Msat_OrderRingForEachEntry( pRing, pVar, pNext ) \ - for ( pVar = pRing, \ - pNext = pVar? pVar->pNext : NULL; \ - pVar; \ - pVar = (pNext != pRing)? pNext : NULL, \ - pNext = pVar? pVar->pNext : NULL ) - -static void Msat_OrderRingAddLast( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar ); -static void Msat_OrderRingRemove( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar ); - -extern int timeSelect; -extern int timeAssign; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the ordering structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_Order_t * Msat_OrderAlloc( Msat_Solver_t * pSat ) -{ - Msat_Order_t * p; - p = ALLOC( Msat_Order_t, 1 ); - memset( p, 0, sizeof(Msat_Order_t) ); - p->pSat = pSat; - Msat_OrderSetBounds( p, pSat->nVarsAlloc ); - return p; -} - -/**Function************************************************************* - - Synopsis [Sets the bound of the ordering structure.] - - Description [Should be called whenever the SAT solver is resized.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderSetBounds( Msat_Order_t * p, int nVarsMax ) -{ - int i; - // add variables if they are missing - if ( p->nVarsAlloc < nVarsMax ) - { - p->pVars = REALLOC( Msat_OrderVar_t, p->pVars, nVarsMax ); - for ( i = p->nVarsAlloc; i < nVarsMax; i++ ) - { - p->pVars[i].pNext = p->pVars[i].pPrev = NULL; - p->pVars[i].Num = i; - } - p->nVarsAlloc = nVarsMax; - } -} - -/**Function************************************************************* - - Synopsis [Cleans the ordering structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderClean( Msat_Order_t * p, Msat_IntVec_t * vCone ) -{ - Msat_OrderVar_t * pVar, * pNext; - // quickly undo the ring - Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext ) - pVar->pNext = pVar->pPrev = NULL; - p->rVars.pRoot = NULL; - p->rVars.nItems = 0; -} - -/**Function************************************************************* - - Synopsis [Checks that the J-boundary is okay.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_OrderCheck( Msat_Order_t * p ) -{ - Msat_OrderVar_t * pVar, * pNext; - Msat_IntVec_t * vRound; - int * pRound, nRound; - int * pVars, nVars, i, k; - int Counter = 0; - - // go through all the variables in the boundary - Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext ) - { - assert( !Msat_OrderVarIsAssigned(p, pVar->Num) ); - // go though all the variables in the neighborhood - // and check that it is true that there is least one assigned - vRound = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( p->pSat->vAdjacents, pVar->Num ); - nRound = Msat_IntVecReadSize( vRound ); - pRound = Msat_IntVecReadArray( vRound ); - for ( i = 0; i < nRound; i++ ) - { - if ( !Msat_OrderVarIsUsedInCone(p, pRound[i]) ) - continue; - if ( Msat_OrderVarIsAssigned(p, pRound[i]) ) - break; - } -// assert( i != nRound ); -// if ( i == nRound ) -// return 0; - if ( i == nRound ) - Counter++; - } - if ( Counter > 0 ) - printf( "%d(%d) ", Counter, p->rVars.nItems ); - - // we may also check other unassigned variables in the cone - // to make sure that if they are not in J-boundary, - // then they do not have an assigned neighbor - nVars = Msat_IntVecReadSize( p->pSat->vConeVars ); - pVars = Msat_IntVecReadArray( p->pSat->vConeVars ); - for ( i = 0; i < nVars; i++ ) - { - assert( Msat_OrderVarIsUsedInCone(p, pVars[i]) ); - // skip assigned vars, vars in the boundary, and vars not used in the cone - if ( Msat_OrderVarIsAssigned(p, pVars[i]) || - Msat_OrderVarIsInBoundary(p, pVars[i]) ) - continue; - // make sure, it does not have assigned neighbors - vRound = (Msat_IntVec_t *)Msat_ClauseVecReadEntry( p->pSat->vAdjacents, pVars[i] ); - nRound = Msat_IntVecReadSize( vRound ); - pRound = Msat_IntVecReadArray( vRound ); - for ( k = 0; k < nRound; k++ ) - { - if ( !Msat_OrderVarIsUsedInCone(p, pRound[k]) ) - continue; - if ( Msat_OrderVarIsAssigned(p, pRound[k]) ) - break; - } -// assert( k == nRound ); -// if ( k != nRound ) -// return 0; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Frees the ordering structure.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderFree( Msat_Order_t * p ) -{ - free( p->pVars ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Selects the next variable to assign.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_OrderVarSelect( Msat_Order_t * p ) -{ - Msat_OrderVar_t * pVar, * pNext, * pVarBest; - double * pdActs = p->pSat->pdActivity; - double dfActBest; -// int clk = clock(); - - pVarBest = NULL; - dfActBest = -1.0; - Msat_OrderRingForEachEntry( p->rVars.pRoot, pVar, pNext ) - { - if ( dfActBest < pdActs[pVar->Num] ) - { - dfActBest = pdActs[pVar->Num]; - pVarBest = pVar; - } - } -//timeSelect += clock() - clk; -//timeAssign += clock() - clk; - -//if ( pVarBest && pVarBest->Num % 1000 == 0 ) -//printf( "%d ", p->rVars.nItems ); - -// Msat_OrderCheck( p ); - if ( pVarBest ) - { - assert( Msat_OrderVarIsUsedInCone(p, pVarBest->Num) ); - return pVarBest->Num; - } - return MSAT_ORDER_UNKNOWN; -} - -/**Function************************************************************* - - Synopsis [Updates J-boundary when the variable is assigned.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderVarAssigned( Msat_Order_t * p, int Var ) -{ - Msat_IntVec_t * vRound; - int i;//, clk = clock(); - - // make sure the variable is in the boundary - assert( Var < p->nVarsAlloc ); - // if it is not in the boundary (initial decision, random decision), do not remove - if ( Msat_OrderVarIsInBoundary( p, Var ) ) - Msat_OrderRingRemove( &p->rVars, &p->pVars[Var] ); - // add to the boundary those neighbors that are (1) unassigned, (2) not in boundary - // because for them we know that there is a variable (Var) which is assigned - vRound = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[Var]; - for ( i = 0; i < vRound->nSize; i++ ) - { - if ( !Msat_OrderVarIsUsedInCone(p, vRound->pArray[i]) ) - continue; - if ( Msat_OrderVarIsAssigned(p, vRound->pArray[i]) ) - continue; - if ( Msat_OrderVarIsInBoundary(p, vRound->pArray[i]) ) - continue; - Msat_OrderRingAddLast( &p->rVars, &p->pVars[vRound->pArray[i]] ); - } -//timeSelect += clock() - clk; -// Msat_OrderCheck( p ); -} - -/**Function************************************************************* - - Synopsis [Updates the order after a variable is unassigned.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderVarUnassigned( Msat_Order_t * p, int Var ) -{ - Msat_IntVec_t * vRound, * vRound2; - int i, k;//, clk = clock(); - - // make sure the variable is not in the boundary - assert( Var < p->nVarsAlloc ); - assert( !Msat_OrderVarIsInBoundary( p, Var ) ); - // go through its neigbors - if one of them is assigned add this var - // add to the boundary those neighbors that are not there already - // this will also get rid of variable outside of the current cone - // because they are unassigned in Msat_SolverPrepare() - vRound = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[Var]; - for ( i = 0; i < vRound->nSize; i++ ) - if ( Msat_OrderVarIsAssigned(p, vRound->pArray[i]) ) - break; - if ( i != vRound->nSize ) - Msat_OrderRingAddLast( &p->rVars, &p->pVars[Var] ); - - // unassigning a variable may lead to its adjacents dropping from the boundary - for ( i = 0; i < vRound->nSize; i++ ) - if ( Msat_OrderVarIsInBoundary(p, vRound->pArray[i]) ) - { // the neighbor is in the J-boundary (and unassigned) - assert( !Msat_OrderVarIsAssigned(p, vRound->pArray[i]) ); - vRound2 = (Msat_IntVec_t *)p->pSat->vAdjacents->pArray[vRound->pArray[i]]; - // go through its neighbors and determine if there is at least one assigned - for ( k = 0; k < vRound2->nSize; k++ ) - if ( Msat_OrderVarIsAssigned(p, vRound2->pArray[k]) ) - break; - if ( k == vRound2->nSize ) // there is no assigned vars, delete this one - Msat_OrderRingRemove( &p->rVars, &p->pVars[vRound->pArray[i]] ); - } -//timeSelect += clock() - clk; -// Msat_OrderCheck( p ); -} - -/**Function************************************************************* - - Synopsis [Updates the order after a variable changed weight.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderUpdate( Msat_Order_t * p, int Var ) -{ -} - - -/**Function************************************************************* - - Synopsis [Adds node to the end of the ring.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderRingAddLast( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar ) -{ -//printf( "adding %d\n", pVar->Num ); - // check that the node is not in a ring - assert( pVar->pPrev == NULL ); - assert( pVar->pNext == NULL ); - // if the ring is empty, make the node point to itself - pRing->nItems++; - if ( pRing->pRoot == NULL ) - { - pRing->pRoot = pVar; - pVar->pPrev = pVar; - pVar->pNext = pVar; - return; - } - // if the ring is not empty, add it as the last entry - pVar->pPrev = pRing->pRoot->pPrev; - pVar->pNext = pRing->pRoot; - pVar->pPrev->pNext = pVar; - pVar->pNext->pPrev = pVar; - - // move the root so that it points to the new entry -// pRing->pRoot = pRing->pRoot->pPrev; -} - -/**Function************************************************************* - - Synopsis [Removes the node from the ring.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_OrderRingRemove( Msat_OrderRing_t * pRing, Msat_OrderVar_t * pVar ) -{ -//printf( "removing %d\n", pVar->Num ); - // check that the var is in a ring - assert( pVar->pPrev ); - assert( pVar->pNext ); - pRing->nItems--; - if ( pRing->nItems == 0 ) - { - assert( pRing->pRoot == pVar ); - pVar->pPrev = NULL; - pVar->pNext = NULL; - pRing->pRoot = NULL; - return; - } - // move the root if needed - if ( pRing->pRoot == pVar ) - pRing->pRoot = pVar->pNext; - // move the root to the next entry after pVar - // this way all the additions to the list will be traversed first -// pRing->pRoot = pVar->pPrev; - // delete the node - pVar->pPrev->pNext = pVar->pNext; - pVar->pNext->pPrev = pVar->pPrev; - pVar->pPrev = NULL; - pVar->pNext = NULL; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatQueue.c b/src/sat/msat/msatQueue.c deleted file mode 100644 index 5938e042..00000000 --- a/src/sat/msat/msatQueue.c +++ /dev/null @@ -1,157 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatQueue.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [The manager of the assignment propagation queue.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatQueue.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -struct Msat_Queue_t_ -{ - int nVars; - int * pVars; - int iFirst; - int iLast; -}; - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates the variable propagation queue.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_Queue_t * Msat_QueueAlloc( int nVars ) -{ - Msat_Queue_t * p; - p = ALLOC( Msat_Queue_t, 1 ); - memset( p, 0, sizeof(Msat_Queue_t) ); - p->nVars = nVars; - p->pVars = ALLOC( int, nVars ); - return p; -} - -/**Function************************************************************* - - Synopsis [Deallocate the variable propagation queue.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_QueueFree( Msat_Queue_t * p ) -{ - free( p->pVars ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Reads the queue size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_QueueReadSize( Msat_Queue_t * p ) -{ - return p->iLast - p->iFirst; -} - -/**Function************************************************************* - - Synopsis [Insert an entry into the queue.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_QueueInsert( Msat_Queue_t * p, int Lit ) -{ - if ( p->iLast == p->nVars ) - { - int i; - assert( 0 ); - for ( i = 0; i < p->iLast; i++ ) - printf( "entry = %2d lit = %2d var = %2d \n", i, p->pVars[i], p->pVars[i]/2 ); - } - assert( p->iLast < p->nVars ); - p->pVars[p->iLast++] = Lit; -} - -/**Function************************************************************* - - Synopsis [Extracts an entry from the queue.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_QueueExtract( Msat_Queue_t * p ) -{ - if ( p->iFirst == p->iLast ) - return -1; - return p->pVars[p->iFirst++]; -} - -/**Function************************************************************* - - Synopsis [Resets the queue.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_QueueClear( Msat_Queue_t * p ) -{ - p->iFirst = 0; - p->iLast = 0; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatRead.c b/src/sat/msat/msatRead.c deleted file mode 100644 index 738562ef..00000000 --- a/src/sat/msat/msatRead.c +++ /dev/null @@ -1,268 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatRead.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [The reader of the CNF formula in DIMACS format.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatRead.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static char * Msat_FileRead( FILE * pFile ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Read the file into the internal buffer.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Msat_FileRead( FILE * pFile ) -{ - int nFileSize; - char * pBuffer; - // get the file size, in bytes - fseek( pFile, 0, SEEK_END ); - nFileSize = ftell( pFile ); - // move the file current reading position to the beginning - rewind( pFile ); - // load the contents of the file into memory - pBuffer = ALLOC( char, nFileSize + 3 ); - fread( pBuffer, nFileSize, 1, pFile ); - // terminate the string with '\0' - pBuffer[ nFileSize + 0] = '\n'; - pBuffer[ nFileSize + 1] = '\0'; - return pBuffer; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Msat_ReadWhitespace( char ** pIn ) -{ - while ((**pIn >= 9 && **pIn <= 13) || **pIn == 32) - (*pIn)++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Msat_ReadNotWhitespace( char ** pIn ) -{ - while ( !((**pIn >= 9 && **pIn <= 13) || **pIn == 32) ) - (*pIn)++; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void skipLine( char ** pIn ) -{ - while ( 1 ) - { - if (**pIn == 0) - return; - if (**pIn == '\n') - { - (*pIn)++; - return; - } - (*pIn)++; - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static int Msat_ReadInt( char ** pIn ) -{ - int val = 0; - bool neg = 0; - - Msat_ReadWhitespace( pIn ); - if ( **pIn == '-' ) - neg = 1, - (*pIn)++; - else if ( **pIn == '+' ) - (*pIn)++; - if ( **pIn < '0' || **pIn > '9' ) - fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", **pIn), - exit(1); - while ( **pIn >= '0' && **pIn <= '9' ) - val = val*10 + (**pIn - '0'), - (*pIn)++; - return neg ? -val : val; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static void Msat_ReadClause( char ** pIn, Msat_Solver_t * p, Msat_IntVec_t * pLits ) -{ - int nVars = Msat_SolverReadVarNum( p ); - int parsed_lit, var, sign; - - Msat_IntVecClear( pLits ); - while ( 1 ) - { - parsed_lit = Msat_ReadInt(pIn); - if ( parsed_lit == 0 ) - break; - var = abs(parsed_lit) - 1; - sign = (parsed_lit > 0); - if ( var >= nVars ) - { - printf( "Variable %d is larger than the number of allocated variables (%d).\n", var+1, nVars ); - exit(1); - } - Msat_IntVecPush( pLits, MSAT_VAR2LIT(var, !sign) ); - } -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static bool Msat_ReadDimacs( char * pText, Msat_Solver_t ** pS, bool fVerbose ) -{ - Msat_Solver_t * p; - Msat_IntVec_t * pLits; - char * pIn = pText; - int nVars, nClas; - while ( 1 ) - { - Msat_ReadWhitespace( &pIn ); - if ( *pIn == 0 ) - break; - else if ( *pIn == 'c' ) - skipLine( &pIn ); - else if ( *pIn == 'p' ) - { - pIn++; - Msat_ReadWhitespace( &pIn ); - Msat_ReadNotWhitespace( &pIn ); - - nVars = Msat_ReadInt( &pIn ); - nClas = Msat_ReadInt( &pIn ); - skipLine( &pIn ); - // start the solver - p = Msat_SolverAlloc( nVars, 1, 1, 1, 1, 0 ); - Msat_SolverClean( p, nVars ); - Msat_SolverSetVerbosity( p, fVerbose ); - // allocate the vector - pLits = Msat_IntVecAlloc( nVars ); - } - else - { - if ( p == NULL ) - { - printf( "There is no parameter line.\n" ); - exit(1); - } - Msat_ReadClause( &pIn, p, pLits ); - if ( !Msat_SolverAddClause( p, pLits ) ) - return 0; - } - } - Msat_IntVecFree( pLits ); - *pS = p; - return Msat_SolverSimplifyDB( p ); -} - -/**Function************************************************************* - - Synopsis [Starts the solver and reads the DIMAC file.] - - Description [Returns FALSE upon immediate conflict.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_SolverParseDimacs( FILE * pFile, Msat_Solver_t ** p, int fVerbose ) -{ - char * pText; - bool Value; - pText = Msat_FileRead( pFile ); - Value = Msat_ReadDimacs( pText, p, fVerbose ); - free( pText ); - return Value; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatSolverApi.c b/src/sat/msat/msatSolverApi.c deleted file mode 100644 index ee3507a6..00000000 --- a/src/sat/msat/msatSolverApi.c +++ /dev/null @@ -1,500 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatSolverApi.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [APIs of the SAT solver.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatSolverApi.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Msat_SolverSetupTruthTables( unsigned uTruths[][2] ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Simple SAT solver APIs.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_SolverReadVarNum( Msat_Solver_t * p ) { return p->nVars; } -int Msat_SolverReadClauseNum( Msat_Solver_t * p ) { return p->nClauses; } -int Msat_SolverReadVarAllocNum( Msat_Solver_t * p ) { return p->nVarsAlloc; } -int Msat_SolverReadDecisionLevel( Msat_Solver_t * p ) { return Msat_IntVecReadSize(p->vTrailLim); } -int * Msat_SolverReadDecisionLevelArray( Msat_Solver_t * p ) { return p->pLevel; } -Msat_Clause_t ** Msat_SolverReadReasonArray( Msat_Solver_t * p ) { return p->pReasons; } -Msat_Lit_t Msat_SolverReadVarValue( Msat_Solver_t * p, Msat_Var_t Var ) { return p->pAssigns[Var]; } -Msat_ClauseVec_t * Msat_SolverReadLearned( Msat_Solver_t * p ) { return p->vLearned; } -Msat_ClauseVec_t ** Msat_SolverReadWatchedArray( Msat_Solver_t * p ) { return p->pvWatched; } -int * Msat_SolverReadAssignsArray( Msat_Solver_t * p ) { return p->pAssigns; } -int * Msat_SolverReadModelArray( Msat_Solver_t * p ) { return p->pModel; } -int Msat_SolverReadBackTracks( Msat_Solver_t * p ) { return (int)p->Stats.nConflicts; } -int Msat_SolverReadInspects( Msat_Solver_t * p ) { return (int)p->Stats.nInspects; } -Msat_MmStep_t * Msat_SolverReadMem( Msat_Solver_t * p ) { return p->pMem; } -int * Msat_SolverReadSeenArray( Msat_Solver_t * p ) { return p->pSeen; } -int Msat_SolverIncrementSeenId( Msat_Solver_t * p ) { return ++p->nSeenId; } -void Msat_SolverSetVerbosity( Msat_Solver_t * p, int fVerbose ) { p->fVerbose = fVerbose; } -void Msat_SolverClausesIncrement( Msat_Solver_t * p ) { p->nClausesAlloc++; } -void Msat_SolverClausesDecrement( Msat_Solver_t * p ) { p->nClausesAlloc--; } -void Msat_SolverClausesIncrementL( Msat_Solver_t * p ) { p->nClausesAllocL++; } -void Msat_SolverClausesDecrementL( Msat_Solver_t * p ) { p->nClausesAllocL--; } -void Msat_SolverMarkLastClauseTypeA( Msat_Solver_t * p ) { Msat_ClauseSetTypeA( Msat_ClauseVecReadEntry( p->vClauses, Msat_ClauseVecReadSize(p->vClauses)-1 ), 1 ); } -void Msat_SolverMarkClausesStart( Msat_Solver_t * p ) { p->nClausesStart = Msat_ClauseVecReadSize(p->vClauses); } -float * Msat_SolverReadFactors( Msat_Solver_t * p ) { return p->pFactors; } - -/**Function************************************************************* - - Synopsis [Reads the clause with the given number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_Clause_t * Msat_SolverReadClause( Msat_Solver_t * p, int Num ) -{ - int nClausesP; - assert( Num < p->nClauses ); - nClausesP = Msat_ClauseVecReadSize( p->vClauses ); - if ( Num < nClausesP ) - return Msat_ClauseVecReadEntry( p->vClauses, Num ); - return Msat_ClauseVecReadEntry( p->vLearned, Num - nClausesP ); -} - -/**Function************************************************************* - - Synopsis [Reads the clause with the given number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_ClauseVec_t * Msat_SolverReadAdjacents( Msat_Solver_t * p ) -{ - return p->vAdjacents; -} - -/**Function************************************************************* - - Synopsis [Reads the clause with the given number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_IntVec_t * Msat_SolverReadConeVars( Msat_Solver_t * p ) -{ - return p->vConeVars; -} - -/**Function************************************************************* - - Synopsis [Reads the clause with the given number.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_IntVec_t * Msat_SolverReadVarsUsed( Msat_Solver_t * p ) -{ - return p->vVarsUsed; -} - - -/**Function************************************************************* - - Synopsis [Allocates the solver.] - - Description [After the solver is allocated, the procedure - Msat_SolverClean() should be called to set the number of variables.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_Solver_t * Msat_SolverAlloc( int nVarsAlloc, - double dClaInc, double dClaDecay, - double dVarInc, double dVarDecay, - bool fVerbose ) -{ - Msat_Solver_t * p; - int i; - - assert(sizeof(Msat_Lit_t) == sizeof(unsigned)); - assert(sizeof(float) == sizeof(unsigned)); - - p = ALLOC( Msat_Solver_t, 1 ); - memset( p, 0, sizeof(Msat_Solver_t) ); - - p->nVarsAlloc = nVarsAlloc; - p->nVars = 0; - - p->nClauses = 0; - p->vClauses = Msat_ClauseVecAlloc( 512 ); - p->vLearned = Msat_ClauseVecAlloc( 512 ); - - p->dClaInc = dClaInc; - p->dClaDecay = dClaDecay; - p->dVarInc = dVarInc; - p->dVarDecay = dVarDecay; - - p->pdActivity = ALLOC( double, p->nVarsAlloc ); - p->pFactors = ALLOC( float, p->nVarsAlloc ); - for ( i = 0; i < p->nVarsAlloc; i++ ) - { - p->pdActivity[i] = 0.0; - p->pFactors[i] = 1.0; - } - - p->pAssigns = ALLOC( int, p->nVarsAlloc ); - p->pModel = ALLOC( int, p->nVarsAlloc ); - for ( i = 0; i < p->nVarsAlloc; i++ ) - p->pAssigns[i] = MSAT_VAR_UNASSIGNED; -// p->pOrder = Msat_OrderAlloc( p->pAssigns, p->pdActivity, p->nVarsAlloc ); - p->pOrder = Msat_OrderAlloc( p ); - - p->pvWatched = ALLOC( Msat_ClauseVec_t *, 2 * p->nVarsAlloc ); - for ( i = 0; i < 2 * p->nVarsAlloc; i++ ) - p->pvWatched[i] = Msat_ClauseVecAlloc( 16 ); - p->pQueue = Msat_QueueAlloc( p->nVarsAlloc ); - - p->vTrail = Msat_IntVecAlloc( p->nVarsAlloc ); - p->vTrailLim = Msat_IntVecAlloc( p->nVarsAlloc ); - p->pReasons = ALLOC( Msat_Clause_t *, p->nVarsAlloc ); - memset( p->pReasons, 0, sizeof(Msat_Clause_t *) * p->nVarsAlloc ); - p->pLevel = ALLOC( int, p->nVarsAlloc ); - for ( i = 0; i < p->nVarsAlloc; i++ ) - p->pLevel[i] = -1; - p->dRandSeed = 91648253; - p->fVerbose = fVerbose; - p->dProgress = 0.0; -// p->pModel = Msat_IntVecAlloc( p->nVarsAlloc ); - p->pMem = Msat_MmStepStart( 10 ); - - p->vConeVars = Msat_IntVecAlloc( p->nVarsAlloc ); - p->vAdjacents = Msat_ClauseVecAlloc( p->nVarsAlloc ); - for ( i = 0; i < p->nVarsAlloc; i++ ) - Msat_ClauseVecPush( p->vAdjacents, (Msat_Clause_t *)Msat_IntVecAlloc(5) ); - p->vVarsUsed = Msat_IntVecAlloc( p->nVarsAlloc ); - Msat_IntVecFill( p->vVarsUsed, p->nVarsAlloc, 1 ); - - - p->pSeen = ALLOC( int, p->nVarsAlloc ); - memset( p->pSeen, 0, sizeof(int) * p->nVarsAlloc ); - p->nSeenId = 1; - p->vReason = Msat_IntVecAlloc( p->nVarsAlloc ); - p->vTemp = Msat_IntVecAlloc( p->nVarsAlloc ); - return p; -} - -/**Function************************************************************* - - Synopsis [Resizes the solver.] - - Description [Assumes that the solver contains some clauses, and that - it is currently between the calls. Resizes the solver to accomodate - more variables.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverResize( Msat_Solver_t * p, int nVarsAlloc ) -{ - int nVarsAllocOld, i; - - nVarsAllocOld = p->nVarsAlloc; - p->nVarsAlloc = nVarsAlloc; - - p->pdActivity = REALLOC( double, p->pdActivity, p->nVarsAlloc ); - p->pFactors = REALLOC( float, p->pFactors, p->nVarsAlloc ); - for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ ) - { - p->pdActivity[i] = 0.0; - p->pFactors[i] = 1.0; - } - - p->pAssigns = REALLOC( int, p->pAssigns, p->nVarsAlloc ); - p->pModel = REALLOC( int, p->pModel, p->nVarsAlloc ); - for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ ) - p->pAssigns[i] = MSAT_VAR_UNASSIGNED; - -// Msat_OrderRealloc( p->pOrder, p->pAssigns, p->pdActivity, p->nVarsAlloc ); - Msat_OrderSetBounds( p->pOrder, p->nVarsAlloc ); - - p->pvWatched = REALLOC( Msat_ClauseVec_t *, p->pvWatched, 2 * p->nVarsAlloc ); - for ( i = 2 * nVarsAllocOld; i < 2 * p->nVarsAlloc; i++ ) - p->pvWatched[i] = Msat_ClauseVecAlloc( 16 ); - - Msat_QueueFree( p->pQueue ); - p->pQueue = Msat_QueueAlloc( p->nVarsAlloc ); - - p->pReasons = REALLOC( Msat_Clause_t *, p->pReasons, p->nVarsAlloc ); - p->pLevel = REALLOC( int, p->pLevel, p->nVarsAlloc ); - for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ ) - { - p->pReasons[i] = NULL; - p->pLevel[i] = -1; - } - - p->pSeen = REALLOC( int, p->pSeen, p->nVarsAlloc ); - for ( i = nVarsAllocOld; i < p->nVarsAlloc; i++ ) - p->pSeen[i] = 0; - - Msat_IntVecGrow( p->vTrail, p->nVarsAlloc ); - Msat_IntVecGrow( p->vTrailLim, p->nVarsAlloc ); - - // make sure the array of adjucents has room to store the variable numbers - for ( i = Msat_ClauseVecReadSize(p->vAdjacents); i < p->nVarsAlloc; i++ ) - Msat_ClauseVecPush( p->vAdjacents, (Msat_Clause_t *)Msat_IntVecAlloc(5) ); - Msat_IntVecFill( p->vVarsUsed, p->nVarsAlloc, 1 ); -} - -/**Function************************************************************* - - Synopsis [Prepares the solver.] - - Description [Cleans the solver assuming that the problem will involve - the given number of variables (nVars). This procedure is useful - for many small (incremental) SAT problems, to prevent the solver - from being reallocated each time.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverClean( Msat_Solver_t * p, int nVars ) -{ - int i; - // free the clauses - int nClauses; - Msat_Clause_t ** pClauses; - - assert( p->nVarsAlloc >= nVars ); - p->nVars = nVars; - p->nClauses = 0; - - nClauses = Msat_ClauseVecReadSize( p->vClauses ); - pClauses = Msat_ClauseVecReadArray( p->vClauses ); - for ( i = 0; i < nClauses; i++ ) - Msat_ClauseFree( p, pClauses[i], 0 ); -// Msat_ClauseVecFree( p->vClauses ); - Msat_ClauseVecClear( p->vClauses ); - - nClauses = Msat_ClauseVecReadSize( p->vLearned ); - pClauses = Msat_ClauseVecReadArray( p->vLearned ); - for ( i = 0; i < nClauses; i++ ) - Msat_ClauseFree( p, pClauses[i], 0 ); -// Msat_ClauseVecFree( p->vLearned ); - Msat_ClauseVecClear( p->vLearned ); - -// FREE( p->pdActivity ); - for ( i = 0; i < p->nVars; i++ ) - p->pdActivity[i] = 0; - -// Msat_OrderFree( p->pOrder ); -// Msat_OrderClean( p->pOrder, p->nVars, NULL ); - Msat_OrderSetBounds( p->pOrder, p->nVars ); - - for ( i = 0; i < 2 * p->nVars; i++ ) -// Msat_ClauseVecFree( p->pvWatched[i] ); - Msat_ClauseVecClear( p->pvWatched[i] ); -// FREE( p->pvWatched ); -// Msat_QueueFree( p->pQueue ); - Msat_QueueClear( p->pQueue ); - -// FREE( p->pAssigns ); - for ( i = 0; i < p->nVars; i++ ) - p->pAssigns[i] = MSAT_VAR_UNASSIGNED; -// Msat_IntVecFree( p->vTrail ); - Msat_IntVecClear( p->vTrail ); -// Msat_IntVecFree( p->vTrailLim ); - Msat_IntVecClear( p->vTrailLim ); -// FREE( p->pReasons ); - memset( p->pReasons, 0, sizeof(Msat_Clause_t *) * p->nVars ); -// FREE( p->pLevel ); - for ( i = 0; i < p->nVars; i++ ) - p->pLevel[i] = -1; -// Msat_IntVecFree( p->pModel ); -// Msat_MmStepStop( p->pMem, 0 ); - p->dRandSeed = 91648253; - p->dProgress = 0.0; - -// FREE( p->pSeen ); - memset( p->pSeen, 0, sizeof(int) * p->nVars ); - p->nSeenId = 1; -// Msat_IntVecFree( p->vReason ); - Msat_IntVecClear( p->vReason ); -// Msat_IntVecFree( p->vTemp ); - Msat_IntVecClear( p->vTemp ); -// printf(" The number of clauses remaining = %d (%d).\n", p->nClausesAlloc, p->nClausesAllocL ); -// FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Frees the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverFree( Msat_Solver_t * p ) -{ - int i; - - // free the clauses - int nClauses; - Msat_Clause_t ** pClauses; -//printf( "clauses = %d. learned = %d.\n", Msat_ClauseVecReadSize( p->vClauses ), -// Msat_ClauseVecReadSize( p->vLearned ) ); - - nClauses = Msat_ClauseVecReadSize( p->vClauses ); - pClauses = Msat_ClauseVecReadArray( p->vClauses ); - for ( i = 0; i < nClauses; i++ ) - Msat_ClauseFree( p, pClauses[i], 0 ); - Msat_ClauseVecFree( p->vClauses ); - - nClauses = Msat_ClauseVecReadSize( p->vLearned ); - pClauses = Msat_ClauseVecReadArray( p->vLearned ); - for ( i = 0; i < nClauses; i++ ) - Msat_ClauseFree( p, pClauses[i], 0 ); - Msat_ClauseVecFree( p->vLearned ); - - FREE( p->pdActivity ); - FREE( p->pFactors ); - Msat_OrderFree( p->pOrder ); - - for ( i = 0; i < 2 * p->nVarsAlloc; i++ ) - Msat_ClauseVecFree( p->pvWatched[i] ); - FREE( p->pvWatched ); - Msat_QueueFree( p->pQueue ); - - FREE( p->pAssigns ); - FREE( p->pModel ); - Msat_IntVecFree( p->vTrail ); - Msat_IntVecFree( p->vTrailLim ); - FREE( p->pReasons ); - FREE( p->pLevel ); - - Msat_MmStepStop( p->pMem, 0 ); - - nClauses = Msat_ClauseVecReadSize( p->vAdjacents ); - pClauses = Msat_ClauseVecReadArray( p->vAdjacents ); - for ( i = 0; i < nClauses; i++ ) - Msat_IntVecFree( (Msat_IntVec_t *)pClauses[i] ); - Msat_ClauseVecFree( p->vAdjacents ); - Msat_IntVecFree( p->vConeVars ); - Msat_IntVecFree( p->vVarsUsed ); - - FREE( p->pSeen ); - Msat_IntVecFree( p->vReason ); - Msat_IntVecFree( p->vTemp ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Prepares the solver to run on a subset of variables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverPrepare( Msat_Solver_t * p, Msat_IntVec_t * vVars ) -{ - - int i; - // undo the previous data - for ( i = 0; i < p->nVarsAlloc; i++ ) - { - p->pAssigns[i] = MSAT_VAR_UNASSIGNED; - p->pReasons[i] = NULL; - p->pLevel[i] = -1; - p->pdActivity[i] = 0.0; - } - - // set the new variable order - Msat_OrderClean( p->pOrder, vVars ); - - Msat_QueueClear( p->pQueue ); - Msat_IntVecClear( p->vTrail ); - Msat_IntVecClear( p->vTrailLim ); - p->dProgress = 0.0; -} - -/**Function************************************************************* - - Synopsis [Sets up the truth tables.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverSetupTruthTables( unsigned uTruths[][2] ) -{ - int m, v; - // set up the truth tables - for ( m = 0; m < 32; m++ ) - for ( v = 0; v < 5; v++ ) - if ( m & (1 << v) ) - uTruths[v][0] |= (1 << m); - // make adjustments for the case of 6 variables - for ( v = 0; v < 5; v++ ) - uTruths[v][1] = uTruths[v][0]; - uTruths[5][0] = 0; - uTruths[5][1] = ~((unsigned)0); -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatSolverCore.c b/src/sat/msat/msatSolverCore.c deleted file mode 100644 index f9fee73c..00000000 --- a/src/sat/msat/msatSolverCore.c +++ /dev/null @@ -1,212 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatSolverCore.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [The SAT solver core procedures.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatSolverCore.c,v 1.2 2004/05/12 03:37:40 satrajit Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Adds one variable to the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_SolverAddVar( Msat_Solver_t * p, int Level ) -{ - if ( p->nVars == p->nVarsAlloc ) - Msat_SolverResize( p, 2 * p->nVarsAlloc ); - p->pLevel[p->nVars] = Level; - p->nVars++; - return 1; -} - -/**Function************************************************************* - - Synopsis [Adds one clause to the solver's clause database.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_SolverAddClause( Msat_Solver_t * p, Msat_IntVec_t * vLits ) -{ - Msat_Clause_t * pC; - bool Value; - Value = Msat_ClauseCreate( p, vLits, 0, &pC ); - if ( pC != NULL ) - Msat_ClauseVecPush( p->vClauses, pC ); -// else if ( p->fProof ) -// Msat_ClauseCreateFake( p, vLits ); - return Value; -} - -/**Function************************************************************* - - Synopsis [Returns search-space coverage. Not extremely reliable.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -double Msat_SolverProgressEstimate( Msat_Solver_t * p ) -{ - double dProgress = 0.0; - double dF = 1.0 / p->nVars; - int i; - for ( i = 0; i < p->nVars; i++ ) - if ( p->pAssigns[i] != MSAT_VAR_UNASSIGNED ) - dProgress += pow( dF, p->pLevel[i] ); - return dProgress / p->nVars; -} - -/**Function************************************************************* - - Synopsis [Prints statistics about the solver.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverPrintStats( Msat_Solver_t * p ) -{ - printf("C solver (%d vars; %d clauses; %d learned):\n", - p->nVars, Msat_ClauseVecReadSize(p->vClauses), Msat_ClauseVecReadSize(p->vLearned) ); - printf("starts : %lld\n", p->Stats.nStarts); - printf("conflicts : %lld\n", p->Stats.nConflicts); - printf("decisions : %lld\n", p->Stats.nDecisions); - printf("propagations : %lld\n", p->Stats.nPropagations); - printf("inspects : %lld\n", p->Stats.nInspects); -} - -/**Function************************************************************* - - Synopsis [Top-level solve.] - - Description [If using assumptions (non-empty 'assumps' vector), you must - call 'simplifyDB()' first to see that no top-level conflict is present - (which would put the solver in an undefined state. If the last argument - is given (vProj), the solver enumerates through the satisfying solutions, - which are projected on the variables listed in this array. Note that the - variables in the array may be complemented, in which case the derived - assignment for the variable is complemented.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_SolverSolve( Msat_Solver_t * p, Msat_IntVec_t * vAssumps, int nBackTrackLimit, int nTimeLimit ) -{ - Msat_SearchParams_t Params = { 0.95, 0.999 }; - double nConflictsLimit, nLearnedLimit; - Msat_Type_t Status; - int timeStart = clock(); - int64 nConflictsOld = p->Stats.nConflicts; - int64 nDecisionsOld = p->Stats.nDecisions; - -// p->pFreq = ALLOC( int, p->nVarsAlloc ); -// memset( p->pFreq, 0, sizeof(int) * p->nVarsAlloc ); - - if ( vAssumps ) - { - int * pAssumps, nAssumps, i; - - assert( Msat_IntVecReadSize(p->vTrailLim) == 0 ); - - nAssumps = Msat_IntVecReadSize( vAssumps ); - pAssumps = Msat_IntVecReadArray( vAssumps ); - for ( i = 0; i < nAssumps; i++ ) - { - if ( !Msat_SolverAssume(p, pAssumps[i]) || Msat_SolverPropagate(p) ) - { - Msat_QueueClear( p->pQueue ); - Msat_SolverCancelUntil( p, 0 ); - return MSAT_FALSE; - } - } - } - p->nLevelRoot = Msat_SolverReadDecisionLevel(p); - p->nClausesInit = Msat_ClauseVecReadSize( p->vClauses ); - nConflictsLimit = 100; - nLearnedLimit = Msat_ClauseVecReadSize(p->vClauses) / 3; - Status = MSAT_UNKNOWN; - p->nBackTracks = (int)p->Stats.nConflicts; - while ( Status == MSAT_UNKNOWN ) - { - if ( p->fVerbose ) - printf("Solving -- conflicts=%d learnts=%d progress=%.4f %%\n", - (int)nConflictsLimit, (int)nLearnedLimit, p->dProgress*100); - Status = Msat_SolverSearch( p, (int)nConflictsLimit, (int)nLearnedLimit, nBackTrackLimit, &Params ); - nConflictsLimit *= 1.5; - nLearnedLimit *= 1.1; - // if the limit on the number of backtracks is given, quit the restart loop - if ( nBackTrackLimit > 0 && (int)p->Stats.nConflicts - p->nBackTracks > nBackTrackLimit ) - break; - // if the runtime limit is exceeded, quit the restart loop - if ( nTimeLimit > 0 && clock() - timeStart >= nTimeLimit * CLOCKS_PER_SEC ) - break; - } - Msat_SolverCancelUntil( p, 0 ); - p->nBackTracks = (int)p->Stats.nConflicts - p->nBackTracks; -/* - PRT( "True solver runtime", clock() - timeStart ); - // print the statistics - { - int i, Counter = 0; - for ( i = 0; i < p->nVars; i++ ) - if ( p->pFreq[i] > 0 ) - { - printf( "%d ", p->pFreq[i] ); - Counter++; - } - if ( Counter ) - printf( "\n" ); - printf( "Total = %d. Used = %d. Decisions = %d. Imps = %d. Conflicts = %d. ", p->nVars, Counter, (int)p->Stats.nDecisions, (int)p->Stats.nPropagations, (int)p->Stats.nConflicts ); - PRT( "Time", clock() - timeStart ); - } -*/ - return Status; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatSolverIo.c b/src/sat/msat/msatSolverIo.c deleted file mode 100644 index 05b7f6a9..00000000 --- a/src/sat/msat/msatSolverIo.c +++ /dev/null @@ -1,177 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatSolverIo.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [Input/output of CNFs.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatSolverIo.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static char * Msat_TimeStamp(); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverPrintAssignment( Msat_Solver_t * p ) -{ - int i; - printf( "Current assignments are: \n" ); - for ( i = 0; i < p->nVars; i++ ) - printf( "%d", i % 10 ); - printf( "\n" ); - for ( i = 0; i < p->nVars; i++ ) - if ( p->pAssigns[i] == MSAT_VAR_UNASSIGNED ) - printf( "." ); - else - { - assert( i == MSAT_LIT2VAR(p->pAssigns[i]) ); - if ( MSAT_LITSIGN(p->pAssigns[i]) ) - printf( "0" ); - else - printf( "1" ); - } - printf( "\n" ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverPrintClauses( Msat_Solver_t * p ) -{ - Msat_Clause_t ** pClauses; - int nClauses, i; - - printf( "Original clauses: \n" ); - nClauses = Msat_ClauseVecReadSize( p->vClauses ); - pClauses = Msat_ClauseVecReadArray( p->vClauses ); - for ( i = 0; i < nClauses; i++ ) - { - printf( "%3d: ", i ); - Msat_ClausePrint( pClauses[i] ); - } - - printf( "Learned clauses: \n" ); - nClauses = Msat_ClauseVecReadSize( p->vLearned ); - pClauses = Msat_ClauseVecReadArray( p->vLearned ); - for ( i = 0; i < nClauses; i++ ) - { - printf( "%3d: ", i ); - Msat_ClausePrint( pClauses[i] ); - } - - printf( "Variable activity: \n" ); - for ( i = 0; i < p->nVars; i++ ) - printf( "%3d : %.4f\n", i, p->pdActivity[i] ); -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverWriteDimacs( Msat_Solver_t * p, char * pFileName ) -{ - FILE * pFile; - Msat_Clause_t ** pClauses; - int nClauses, i; - - nClauses = Msat_ClauseVecReadSize(p->vClauses) + Msat_ClauseVecReadSize(p->vLearned); - for ( i = 0; i < p->nVars; i++ ) - nClauses += ( p->pLevel[i] == 0 ); - - pFile = fopen( pFileName, "wb" ); - fprintf( pFile, "c Produced by Msat_SolverWriteDimacs() on %s\n", Msat_TimeStamp() ); - fprintf( pFile, "p cnf %d %d\n", p->nVars, nClauses ); - - nClauses = Msat_ClauseVecReadSize( p->vClauses ); - pClauses = Msat_ClauseVecReadArray( p->vClauses ); - for ( i = 0; i < nClauses; i++ ) - Msat_ClauseWriteDimacs( pFile, pClauses[i], 1 ); - - nClauses = Msat_ClauseVecReadSize( p->vLearned ); - pClauses = Msat_ClauseVecReadArray( p->vLearned ); - for ( i = 0; i < nClauses; i++ ) - Msat_ClauseWriteDimacs( pFile, pClauses[i], 1 ); - - // write zero-level assertions - for ( i = 0; i < p->nVars; i++ ) - if ( p->pLevel[i] == 0 ) - fprintf( pFile, "%s%d 0\n", ((p->pAssigns[i]&1)? "-": ""), i + 1 ); - - fprintf( pFile, "\n" ); - fclose( pFile ); -} - - -/**Function************************************************************* - - Synopsis [Returns the time stamp.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Msat_TimeStamp() -{ - static char Buffer[100]; - time_t ltime; - char * TimeStamp; - // get the current time - time( <ime ); - TimeStamp = asctime( localtime( <ime ) ); - TimeStamp[ strlen(TimeStamp) - 1 ] = 0; - strcpy( Buffer, TimeStamp ); - return Buffer; -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatSolverSearch.c b/src/sat/msat/msatSolverSearch.c deleted file mode 100644 index 11a6540c..00000000 --- a/src/sat/msat/msatSolverSearch.c +++ /dev/null @@ -1,629 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatSolverSearch.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [The search part of the solver.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatSolverSearch.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static void Msat_SolverUndoOne( Msat_Solver_t * p ); -static void Msat_SolverCancel( Msat_Solver_t * p ); -static Msat_Clause_t * Msat_SolverRecord( Msat_Solver_t * p, Msat_IntVec_t * vLits ); -static void Msat_SolverAnalyze( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_IntVec_t * vLits_out, int * pLevel_out ); -static void Msat_SolverReduceDB( Msat_Solver_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Makes the next assumption (Lit).] - - Description [Returns FALSE if immediate conflict.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_SolverAssume( Msat_Solver_t * p, Msat_Lit_t Lit ) -{ - assert( Msat_QueueReadSize(p->pQueue) == 0 ); - if ( p->fVerbose ) - printf(L_IND"assume("L_LIT")\n", L_ind, L_lit(Lit)); - Msat_IntVecPush( p->vTrailLim, Msat_IntVecReadSize(p->vTrail) ); -// assert( Msat_IntVecReadSize(p->vTrailLim) <= Msat_IntVecReadSize(p->vTrail) + 1 ); -// assert( Msat_IntVecReadSize( p->vTrailLim ) < p->nVars ); - return Msat_SolverEnqueue( p, Lit, NULL ); -} - -/**Function************************************************************* - - Synopsis [Reverts one variable binding on the trail.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverUndoOne( Msat_Solver_t * p ) -{ - Msat_Lit_t Lit; - Msat_Var_t Var; - Lit = Msat_IntVecPop( p->vTrail ); - Var = MSAT_LIT2VAR(Lit); - p->pAssigns[Var] = MSAT_VAR_UNASSIGNED; - p->pReasons[Var] = NULL; - p->pLevel[Var] = -1; -// Msat_OrderUndo( p->pOrder, Var ); - Msat_OrderVarUnassigned( p->pOrder, Var ); - - if ( p->fVerbose ) - printf(L_IND"unbind("L_LIT")\n", L_ind, L_lit(Lit)); -} - -/**Function************************************************************* - - Synopsis [Reverts to the state before last Msat_SolverAssume().] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverCancel( Msat_Solver_t * p ) -{ - int c; - assert( Msat_QueueReadSize(p->pQueue) == 0 ); - if ( p->fVerbose ) - { - if ( Msat_IntVecReadSize(p->vTrail) != Msat_IntVecReadEntryLast(p->vTrailLim) ) - { - Msat_Lit_t Lit; - Lit = Msat_IntVecReadEntry( p->vTrail, Msat_IntVecReadEntryLast(p->vTrailLim) ); - printf(L_IND"cancel("L_LIT")\n", L_ind, L_lit(Lit)); - } - } - for ( c = Msat_IntVecReadSize(p->vTrail) - Msat_IntVecPop( p->vTrailLim ); c != 0; c-- ) - Msat_SolverUndoOne( p ); -} - -/**Function************************************************************* - - Synopsis [Reverts to the state at given level.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverCancelUntil( Msat_Solver_t * p, int Level ) -{ - while ( Msat_IntVecReadSize(p->vTrailLim) > Level ) - Msat_SolverCancel(p); -} - - -/**Function************************************************************* - - Synopsis [Record a clause and drive backtracking.] - - Description [vLits[0] must contain the asserting literal.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_Clause_t * Msat_SolverRecord( Msat_Solver_t * p, Msat_IntVec_t * vLits ) -{ - Msat_Clause_t * pC; - int Value; - assert( Msat_IntVecReadSize(vLits) != 0 ); - Value = Msat_ClauseCreate( p, vLits, 1, &pC ); - assert( Value ); - Value = Msat_SolverEnqueue( p, Msat_IntVecReadEntry(vLits,0), pC ); - assert( Value ); - if ( pC ) - Msat_ClauseVecPush( p->vLearned, pC ); - return pC; -} - -/**Function************************************************************* - - Synopsis [Enqueues one variable assignment.] - - Description [Puts a new fact on the propagation queue and immediately - updates the variable value. Should a conflict arise, FALSE is returned. - Otherwise returns TRUE.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_SolverEnqueue( Msat_Solver_t * p, Msat_Lit_t Lit, Msat_Clause_t * pC ) -{ - Msat_Var_t Var = MSAT_LIT2VAR(Lit); - - // skip literals that are not in the current cone - if ( !Msat_IntVecReadEntry( p->vVarsUsed, Var ) ) - return 1; - -// assert( Msat_QueueReadSize(p->pQueue) == Msat_IntVecReadSize(p->vTrail) ); - // if the literal is assigned - // return 1 if the assignment is consistent - // return 0 if the assignment is inconsistent (conflict) - if ( p->pAssigns[Var] != MSAT_VAR_UNASSIGNED ) - return p->pAssigns[Var] == Lit; - // new fact - store it - if ( p->fVerbose ) - { -// printf(L_IND"bind("L_LIT")\n", L_ind, L_lit(Lit)); - printf(L_IND"bind("L_LIT") ", L_ind, L_lit(Lit)); - Msat_ClausePrintSymbols( pC ); - } - p->pAssigns[Var] = Lit; - p->pLevel[Var] = Msat_IntVecReadSize(p->vTrailLim); -// p->pReasons[Var] = p->pLevel[Var]? pC: NULL; - p->pReasons[Var] = pC; - Msat_IntVecPush( p->vTrail, Lit ); - Msat_QueueInsert( p->pQueue, Lit ); - - Msat_OrderVarAssigned( p->pOrder, Var ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Propagates the assignments in the queue.] - - Description [Propagates all enqueued facts. If a conflict arises, - the conflicting clause is returned, otherwise NULL.] - - SideEffects [The propagation queue is empty, even if there was a conflict.] - - SeeAlso [] - -***********************************************************************/ -Msat_Clause_t * Msat_SolverPropagate( Msat_Solver_t * p ) -{ - Msat_ClauseVec_t ** pvWatched = p->pvWatched; - Msat_Clause_t ** pClauses; - Msat_Clause_t * pConflict; - Msat_Lit_t Lit, Lit_out; - int i, j, nClauses; - - // propagate all the literals in the queue - while ( (Lit = Msat_QueueExtract( p->pQueue )) >= 0 ) - { - p->Stats.nPropagations++; - // get the clauses watched by this literal - nClauses = Msat_ClauseVecReadSize( pvWatched[Lit] ); - pClauses = Msat_ClauseVecReadArray( pvWatched[Lit] ); - // go through the watched clauses and decide what to do with them - for ( i = j = 0; i < nClauses; i++ ) - { - p->Stats.nInspects++; - // clear the returned literal - Lit_out = -1; - // propagate the clause - if ( !Msat_ClausePropagate( pClauses[i], Lit, p->pAssigns, &Lit_out ) ) - { // the clause is unit - // "Lit_out" contains the new assignment to be enqueued - if ( Msat_SolverEnqueue( p, Lit_out, pClauses[i] ) ) - { // consistent assignment - // no changes to the implication queue; the watch is the same too - pClauses[j++] = pClauses[i]; - continue; - } - // remember the reason of conflict (will be returned) - pConflict = pClauses[i]; - // leave the remaning clauses in the same watched list - for ( ; i < nClauses; i++ ) - pClauses[j++] = pClauses[i]; - Msat_ClauseVecShrink( pvWatched[Lit], j ); - // clear the propagation queue - Msat_QueueClear( p->pQueue ); - return pConflict; - } - // the clause is not unit - // in this case "Lit_out" contains the new watch if it has changed - if ( Lit_out >= 0 ) - Msat_ClauseVecPush( pvWatched[Lit_out], pClauses[i] ); - else // the watch did not change - pClauses[j++] = pClauses[i]; - } - Msat_ClauseVecShrink( pvWatched[Lit], j ); - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Simplifies the data base.] - - Description [Simplify all constraints according to the current top-level - assigment (redundant constraints may be removed altogether).] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -bool Msat_SolverSimplifyDB( Msat_Solver_t * p ) -{ - Msat_ClauseVec_t * vClauses; - Msat_Clause_t ** pClauses; - int nClauses, Type, i, j; - int * pAssigns; - int Counter; - - assert( Msat_SolverReadDecisionLevel(p) == 0 ); - if ( Msat_SolverPropagate(p) != NULL ) - return 0; -//Msat_SolverPrintClauses( p ); -//Msat_SolverPrintAssignment( p ); -//printf( "Simplification\n" ); - - // simplify and reassign clause numbers - Counter = 0; - pAssigns = Msat_SolverReadAssignsArray( p ); - for ( Type = 0; Type < 2; Type++ ) - { - vClauses = Type? p->vLearned : p->vClauses; - nClauses = Msat_ClauseVecReadSize( vClauses ); - pClauses = Msat_ClauseVecReadArray( vClauses ); - for ( i = j = 0; i < nClauses; i++ ) - if ( Msat_ClauseSimplify( pClauses[i], pAssigns ) ) - Msat_ClauseFree( p, pClauses[i], 1 ); - else - { - pClauses[j++] = pClauses[i]; - Msat_ClauseSetNum( pClauses[i], Counter++ ); - } - Msat_ClauseVecShrink( vClauses, j ); - } - p->nClauses = Counter; - return 1; -} - -/**Function************************************************************* - - Synopsis [Cleans the clause databased from the useless learnt clauses.] - - Description [Removes half of the learnt clauses, minus the clauses locked - by the current assignment. Locked clauses are clauses that are reason - to a some assignment.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverReduceDB( Msat_Solver_t * p ) -{ - Msat_Clause_t ** pLearned; - int nLearned, i, j; - double dExtraLim = p->dClaInc / Msat_ClauseVecReadSize(p->vLearned); - // Remove any clause below this activity - - // sort the learned clauses in the increasing order of activity - Msat_SolverSortDB( p ); - - // discard the first half the clauses (the less active ones) - nLearned = Msat_ClauseVecReadSize( p->vLearned ); - pLearned = Msat_ClauseVecReadArray( p->vLearned ); - for ( i = j = 0; i < nLearned / 2; i++ ) - if ( !Msat_ClauseIsLocked( p, pLearned[i]) ) - Msat_ClauseFree( p, pLearned[i], 1 ); - else - pLearned[j++] = pLearned[i]; - // filter the more active clauses and leave those above the limit - for ( ; i < nLearned; i++ ) - if ( !Msat_ClauseIsLocked( p, pLearned[i] ) && - Msat_ClauseReadActivity(pLearned[i]) < dExtraLim ) - Msat_ClauseFree( p, pLearned[i], 1 ); - else - pLearned[j++] = pLearned[i]; - Msat_ClauseVecShrink( p->vLearned, j ); -} - -/**Function************************************************************* - - Synopsis [Removes the learned clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverRemoveLearned( Msat_Solver_t * p ) -{ - Msat_Clause_t ** pLearned; - int nLearned, i; - - // discard the learned clauses - nLearned = Msat_ClauseVecReadSize( p->vLearned ); - pLearned = Msat_ClauseVecReadArray( p->vLearned ); - for ( i = 0; i < nLearned; i++ ) - { - assert( !Msat_ClauseIsLocked( p, pLearned[i]) ); - - Msat_ClauseFree( p, pLearned[i], 1 ); - } - Msat_ClauseVecShrink( p->vLearned, 0 ); - p->nClauses = Msat_ClauseVecReadSize(p->vClauses); - - for ( i = 0; i < p->nVarsAlloc; i++ ) - p->pReasons[i] = NULL; -} - -/**Function************************************************************* - - Synopsis [Removes the recently added clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverRemoveMarked( Msat_Solver_t * p ) -{ - Msat_Clause_t ** pLearned, ** pClauses; - int nLearned, nClauses, i; - - // discard the learned clauses - nClauses = Msat_ClauseVecReadSize( p->vClauses ); - pClauses = Msat_ClauseVecReadArray( p->vClauses ); - for ( i = p->nClausesStart; i < nClauses; i++ ) - { -// assert( !Msat_ClauseIsLocked( p, pClauses[i]) ); - Msat_ClauseFree( p, pClauses[i], 1 ); - } - Msat_ClauseVecShrink( p->vClauses, p->nClausesStart ); - - // discard the learned clauses - nLearned = Msat_ClauseVecReadSize( p->vLearned ); - pLearned = Msat_ClauseVecReadArray( p->vLearned ); - for ( i = 0; i < nLearned; i++ ) - { -// assert( !Msat_ClauseIsLocked( p, pLearned[i]) ); - Msat_ClauseFree( p, pLearned[i], 1 ); - } - Msat_ClauseVecShrink( p->vLearned, 0 ); - p->nClauses = Msat_ClauseVecReadSize(p->vClauses); -/* - // undo the previous data - for ( i = 0; i < p->nVarsAlloc; i++ ) - { - p->pAssigns[i] = MSAT_VAR_UNASSIGNED; - p->pReasons[i] = NULL; - p->pLevel[i] = -1; - p->pdActivity[i] = 0.0; - } - Msat_OrderClean( p->pOrder, p->nVars, NULL ); - Msat_QueueClear( p->pQueue ); -*/ -} - - - -/**Function************************************************************* - - Synopsis [Analyze conflict and produce a reason clause.] - - Description [Current decision level must be greater than root level.] - - SideEffects [vLits_out[0] is the asserting literal at level pLevel_out.] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverAnalyze( Msat_Solver_t * p, Msat_Clause_t * pC, Msat_IntVec_t * vLits_out, int * pLevel_out ) -{ - Msat_Lit_t LitQ, Lit = MSAT_LIT_UNASSIGNED; - Msat_Var_t VarQ, Var; - int * pReasonArray, nReasonSize; - int j, pathC = 0, nLevelCur = Msat_IntVecReadSize(p->vTrailLim); - int iStep = Msat_IntVecReadSize(p->vTrail) - 1; - - // increment the seen counter - p->nSeenId++; - // empty the vector array - Msat_IntVecClear( vLits_out ); - Msat_IntVecPush( vLits_out, -1 ); // (leave room for the asserting literal) - *pLevel_out = 0; - do { - assert( pC != NULL ); // (otherwise should be UIP) - // get the reason of conflict - Msat_ClauseCalcReason( p, pC, Lit, p->vReason ); - nReasonSize = Msat_IntVecReadSize( p->vReason ); - pReasonArray = Msat_IntVecReadArray( p->vReason ); - for ( j = 0; j < nReasonSize; j++ ) { - LitQ = pReasonArray[j]; - VarQ = MSAT_LIT2VAR(LitQ); - if ( p->pSeen[VarQ] != p->nSeenId ) { - p->pSeen[VarQ] = p->nSeenId; - - // added to better fine-tune the search - Msat_SolverVarBumpActivity( p, LitQ ); - - // skip all the literals on this decision level - if ( p->pLevel[VarQ] == nLevelCur ) - pathC++; - else if ( p->pLevel[VarQ] > 0 ) { - // add the literals on other decision levels but - // exclude variables from decision level 0 - Msat_IntVecPush( vLits_out, MSAT_LITNOT(LitQ) ); - if ( *pLevel_out < p->pLevel[VarQ] ) - *pLevel_out = p->pLevel[VarQ]; - } - } - } - // Select next clause to look at: - do { -// Lit = Msat_IntVecReadEntryLast(p->vTrail); - Lit = Msat_IntVecReadEntry( p->vTrail, iStep-- ); - Var = MSAT_LIT2VAR(Lit); - pC = p->pReasons[Var]; -// Msat_SolverUndoOne( p ); - } while ( p->pSeen[Var] != p->nSeenId ); - pathC--; - } while ( pathC > 0 ); - // we do not unbind the variables above - // this will be done after conflict analysis - - Msat_IntVecWriteEntry( vLits_out, 0, MSAT_LITNOT(Lit) ); - if ( p->fVerbose ) - { - printf( L_IND"Learnt {", L_ind ); - nReasonSize = Msat_IntVecReadSize( vLits_out ); - pReasonArray = Msat_IntVecReadArray( vLits_out ); - for ( j = 0; j < nReasonSize; j++ ) - printf(" "L_LIT, L_lit(pReasonArray[j])); - printf(" } at level %d\n", *pLevel_out); - } -} - -/**Function************************************************************* - - Synopsis [The search procedure called between the restarts.] - - Description [Search for a satisfying solution as long as the number of - conflicts does not exceed the limit (nConfLimit) while keeping the number - of learnt clauses below the provided limit (nLearnedLimit). NOTE! Use - negative value for nConfLimit or nLearnedLimit to indicate infinity.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_Type_t Msat_SolverSearch( Msat_Solver_t * p, int nConfLimit, int nLearnedLimit, int nBackTrackLimit, Msat_SearchParams_t * pPars ) -{ - Msat_Clause_t * pConf; - Msat_Var_t Var; - int nLevelBack, nConfs, nAssigns, Value; - int i; - - assert( Msat_SolverReadDecisionLevel(p) == p->nLevelRoot ); - p->Stats.nStarts++; - p->dVarDecay = 1 / pPars->dVarDecay; - p->dClaDecay = 1 / pPars->dClaDecay; - - // reset the activities - for ( i = 0; i < p->nVars; i++ ) - p->pdActivity[i] = (double)p->pFactors[i]; -// p->pdActivity[i] = 0.0; - - nConfs = 0; - while ( 1 ) - { - pConf = Msat_SolverPropagate( p ); - if ( pConf != NULL ){ - // CONFLICT - if ( p->fVerbose ) - { -// printf(L_IND"**CONFLICT**\n", L_ind); - printf(L_IND"**CONFLICT** ", L_ind); - Msat_ClausePrintSymbols( pConf ); - } - // count conflicts - p->Stats.nConflicts++; - nConfs++; - - // if top level, return UNSAT - if ( Msat_SolverReadDecisionLevel(p) == p->nLevelRoot ) - return MSAT_FALSE; - - // perform conflict analysis - Msat_SolverAnalyze( p, pConf, p->vTemp, &nLevelBack ); - Msat_SolverCancelUntil( p, (p->nLevelRoot > nLevelBack)? p->nLevelRoot : nLevelBack ); - Msat_SolverRecord( p, p->vTemp ); - - // it is important that recording is done after cancelling - // because canceling cleans the queue while recording adds to it - Msat_SolverVarDecayActivity( p ); - Msat_SolverClaDecayActivity( p ); - - } - else{ - // NO CONFLICT - if ( Msat_IntVecReadSize(p->vTrailLim) == 0 ) { - // Simplify the set of problem clauses: -// Value = Msat_SolverSimplifyDB(p); -// assert( Value ); - } - nAssigns = Msat_IntVecReadSize( p->vTrail ); - if ( nLearnedLimit >= 0 && Msat_ClauseVecReadSize(p->vLearned) >= nLearnedLimit + nAssigns ) { - // Reduce the set of learnt clauses: - Msat_SolverReduceDB(p); - } - - Var = Msat_OrderVarSelect( p->pOrder ); - if ( Var == MSAT_ORDER_UNKNOWN ) { - // Model found and stored in p->pAssigns - memcpy( p->pModel, p->pAssigns, sizeof(int) * p->nVars ); - Msat_QueueClear( p->pQueue ); - Msat_SolverCancelUntil( p, p->nLevelRoot ); - return MSAT_TRUE; - } - if ( nConfLimit > 0 && nConfs > nConfLimit ) { - // Reached bound on number of conflicts: - p->dProgress = Msat_SolverProgressEstimate( p ); - Msat_QueueClear( p->pQueue ); - Msat_SolverCancelUntil( p, p->nLevelRoot ); - return MSAT_UNKNOWN; - } - else if ( nBackTrackLimit > 0 && (int)p->Stats.nConflicts - p->nBackTracks > nBackTrackLimit ) { - // Reached bound on number of conflicts: - Msat_QueueClear( p->pQueue ); - Msat_SolverCancelUntil( p, p->nLevelRoot ); - return MSAT_UNKNOWN; - } - else{ - // New variable decision: - p->Stats.nDecisions++; - assert( Var != MSAT_ORDER_UNKNOWN && Var >= 0 && Var < p->nVars ); - Value = Msat_SolverAssume(p, MSAT_VAR2LIT(Var,0) ); - assert( Value ); - } - } - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatSort.c b/src/sat/msat/msatSort.c deleted file mode 100644 index 3b89d102..00000000 --- a/src/sat/msat/msatSort.c +++ /dev/null @@ -1,173 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatSort.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [Sorting clauses.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatSort.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Msat_SolverSortCompare( Msat_Clause_t ** ppC1, Msat_Clause_t ** ppC2 ); - -// Returns a random float 0 <= x < 1. Seed must never be 0. -static double drand(double seed) { - int q; - seed *= 1389796; - q = (int)(seed / 2147483647); - seed -= (double)q * 2147483647; - return seed / 2147483647; } - -// Returns a random integer 0 <= x < size. Seed must never be 0. -static int irand(double seed, int size) { - return (int)(drand(seed) * size); } - -static void Msat_SolverSort( Msat_Clause_t ** array, int size, double seed ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Msat_SolverSort the learned clauses in the increasing order of activity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverSortDB( Msat_Solver_t * p ) -{ - Msat_ClauseVec_t * pVecClauses; - Msat_Clause_t ** pLearned; - int nLearned; - // read the parameters - pVecClauses = Msat_SolverReadLearned( p ); - nLearned = Msat_ClauseVecReadSize( pVecClauses ); - pLearned = Msat_ClauseVecReadArray( pVecClauses ); - // Msat_SolverSort the array -// qMsat_SolverSort( (void *)pLearned, nLearned, sizeof(Msat_Clause_t *), -// (int (*)(const void *, const void *)) Msat_SolverSortCompare ); -// printf( "Msat_SolverSorting.\n" ); - Msat_SolverSort( pLearned, nLearned, 91648253 ); -/* - if ( nLearned > 2 ) - { - printf( "Clause 1: %0.20f\n", Msat_ClauseReadActivity(pLearned[0]) ); - printf( "Clause 2: %0.20f\n", Msat_ClauseReadActivity(pLearned[1]) ); - printf( "Clause 3: %0.20f\n", Msat_ClauseReadActivity(pLearned[2]) ); - } -*/ -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_SolverSortCompare( Msat_Clause_t ** ppC1, Msat_Clause_t ** ppC2 ) -{ - float Value1 = Msat_ClauseReadActivity( *ppC1 ); - float Value2 = Msat_ClauseReadActivity( *ppC2 ); - if ( Value1 < Value2 ) - return -1; - if ( Value1 > Value2 ) - return 1; - return 0; -} - - -/**Function************************************************************* - - Synopsis [Selection sort for small array size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverSortSelection( Msat_Clause_t ** array, int size ) -{ - Msat_Clause_t * tmp; - int i, j, best_i; - for ( i = 0; i < size-1; i++ ) - { - best_i = i; - for (j = i+1; j < size; j++) - { - if ( Msat_ClauseReadActivity(array[j]) < Msat_ClauseReadActivity(array[best_i]) ) - best_i = j; - } - tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; - } -} - -/**Function************************************************************* - - Synopsis [The original MiniSat sorting procedure.] - - Description [This procedure is used to preserve trace-equivalence - with the orignal C++ implemenation of the solver.] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_SolverSort( Msat_Clause_t ** array, int size, double seed ) -{ - if (size <= 15) - Msat_SolverSortSelection( array, size ); - else - { - Msat_Clause_t * pivot = array[irand(seed, size)]; - Msat_Clause_t * tmp; - int i = -1; - int j = size; - - for(;;) - { - do i++; while( Msat_ClauseReadActivity(array[i]) < Msat_ClauseReadActivity(pivot) ); - do j--; while( Msat_ClauseReadActivity(pivot) < Msat_ClauseReadActivity(array[j]) ); - - if ( i >= j ) break; - - tmp = array[i]; array[i] = array[j]; array[j] = tmp; - } - Msat_SolverSort(array , i , seed); - Msat_SolverSort(&array[i], size-i, seed); - } -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/msat/msatVec.c b/src/sat/msat/msatVec.c deleted file mode 100644 index 75f53047..00000000 --- a/src/sat/msat/msatVec.c +++ /dev/null @@ -1,495 +0,0 @@ -/**CFile**************************************************************** - - FileName [msatVec.c] - - PackageName [A C version of SAT solver MINISAT, originally developed - in C++ by Niklas Een and Niklas Sorensson, Chalmers University of - Technology, Sweden: http://www.cs.chalmers.se/~een/Satzoo.] - - Synopsis [Integer vector borrowed from Extra.] - - Author [Alan Mishchenko ] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - January 1, 2004.] - - Revision [$Id: msatVec.c,v 1.0 2004/01/01 1:00:00 alanmi Exp $] - -***********************************************************************/ - -#include "msatInt.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -static int Msat_IntVecSortCompare1( int * pp1, int * pp2 ); -static int Msat_IntVecSortCompare2( int * pp1, int * pp2 ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocates a vector with the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_IntVec_t * Msat_IntVecAlloc( int nCap ) -{ - Msat_IntVec_t * p; - p = ALLOC( Msat_IntVec_t, 1 ); - if ( nCap > 0 && nCap < 16 ) - nCap = 16; - p->nSize = 0; - p->nCap = nCap; - p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_IntVec_t * Msat_IntVecAllocArray( int * pArray, int nSize ) -{ - Msat_IntVec_t * p; - p = ALLOC( Msat_IntVec_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = pArray; - return p; -} - -/**Function************************************************************* - - Synopsis [Creates the vector from an integer array of the given size.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_IntVec_t * Msat_IntVecAllocArrayCopy( int * pArray, int nSize ) -{ - Msat_IntVec_t * p; - p = ALLOC( Msat_IntVec_t, 1 ); - p->nSize = nSize; - p->nCap = nSize; - p->pArray = ALLOC( int, nSize ); - memcpy( p->pArray, pArray, sizeof(int) * nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Duplicates the integer array.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_IntVec_t * Msat_IntVecDup( Msat_IntVec_t * pVec ) -{ - Msat_IntVec_t * p; - p = ALLOC( Msat_IntVec_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = p->nCap? ALLOC( int, p->nCap ) : NULL; - memcpy( p->pArray, pVec->pArray, sizeof(int) * pVec->nSize ); - return p; -} - -/**Function************************************************************* - - Synopsis [Transfers the array into another vector.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Msat_IntVec_t * Msat_IntVecDupArray( Msat_IntVec_t * pVec ) -{ - Msat_IntVec_t * p; - p = ALLOC( Msat_IntVec_t, 1 ); - p->nSize = pVec->nSize; - p->nCap = pVec->nCap; - p->pArray = pVec->pArray; - pVec->nSize = 0; - pVec->nCap = 0; - pVec->pArray = NULL; - return p; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_IntVecFree( Msat_IntVec_t * p ) -{ - FREE( p->pArray ); - FREE( p ); -} - -/**Function************************************************************* - - Synopsis [Fills the vector with given number of entries.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_IntVecFill( Msat_IntVec_t * p, int nSize, int Entry ) -{ - int i; - Msat_IntVecGrow( p, nSize ); - p->nSize = nSize; - for ( i = 0; i < p->nSize; i++ ) - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Msat_IntVecReleaseArray( Msat_IntVec_t * p ) -{ - int * pArray = p->pArray; - p->nCap = 0; - p->nSize = 0; - p->pArray = NULL; - return pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int * Msat_IntVecReadArray( Msat_IntVec_t * p ) -{ - return p->pArray; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_IntVecReadSize( Msat_IntVec_t * p ) -{ - return p->nSize; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_IntVecReadEntry( Msat_IntVec_t * p, int i ) -{ - assert( i >= 0 && i < p->nSize ); - return p->pArray[i]; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_IntVecWriteEntry( Msat_IntVec_t * p, int i, int Entry ) -{ - assert( i >= 0 && i < p->nSize ); - p->pArray[i] = Entry; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_IntVecReadEntryLast( Msat_IntVec_t * p ) -{ - return p->pArray[p->nSize-1]; -} - -/**Function************************************************************* - - Synopsis [Resizes the vector to the given capacity.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_IntVecGrow( Msat_IntVec_t * p, int nCapMin ) -{ - if ( p->nCap >= nCapMin ) - return; - p->pArray = REALLOC( int, p->pArray, nCapMin ); - p->nCap = nCapMin; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_IntVecShrink( Msat_IntVec_t * p, int nSizeNew ) -{ - assert( p->nSize >= nSizeNew ); - p->nSize = nSizeNew; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_IntVecClear( Msat_IntVec_t * p ) -{ - p->nSize = 0; -} - -/**Function************************************************************* - - Synopsis [] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_IntVecPush( Msat_IntVec_t * p, int Entry ) -{ - if ( p->nSize == p->nCap ) - { - if ( p->nCap < 16 ) - Msat_IntVecGrow( p, 16 ); - else - Msat_IntVecGrow( p, 2 * p->nCap ); - } - p->pArray[p->nSize++] = Entry; -} - -/**Function************************************************************* - - Synopsis [Add the element while ensuring uniqueness.] - - Description [Returns 1 if the element was found, and 0 if it was new. ] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_IntVecPushUnique( Msat_IntVec_t * p, int Entry ) -{ - int i; - for ( i = 0; i < p->nSize; i++ ) - if ( p->pArray[i] == Entry ) - return 1; - Msat_IntVecPush( p, Entry ); - return 0; -} - -/**Function************************************************************* - - Synopsis [Inserts the element while sorting in the increasing order.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_IntVecPushUniqueOrder( Msat_IntVec_t * p, int Entry, int fIncrease ) -{ - int Entry1, Entry2; - int i; - Msat_IntVecPushUnique( p, Entry ); - // find the p of the node - for ( i = p->nSize-1; i > 0; i-- ) - { - Entry1 = p->pArray[i ]; - Entry2 = p->pArray[i-1]; - if ( fIncrease && Entry1 >= Entry2 || - !fIncrease && Entry1 <= Entry2 ) - break; - p->pArray[i ] = Entry2; - p->pArray[i-1] = Entry1; - } -} - - -/**Function************************************************************* - - Synopsis [Returns the last entry and removes it from the list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_IntVecPop( Msat_IntVec_t * p ) -{ - assert( p->nSize > 0 ); - return p->pArray[--p->nSize]; -} - -/**Function************************************************************* - - Synopsis [Sorting the entries by their integer value.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Msat_IntVecSort( Msat_IntVec_t * p, int fReverse ) -{ - if ( fReverse ) - qsort( (void *)p->pArray, p->nSize, sizeof(int), - (int (*)(const void *, const void *)) Msat_IntVecSortCompare2 ); - else - qsort( (void *)p->pArray, p->nSize, sizeof(int), - (int (*)(const void *, const void *)) Msat_IntVecSortCompare1 ); -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_IntVecSortCompare1( int * pp1, int * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 < *pp2 ) - return -1; - if ( *pp1 > *pp2 ) // - return 1; - return 0; // -} - -/**Function************************************************************* - - Synopsis [Comparison procedure for two clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Msat_IntVecSortCompare2( int * pp1, int * pp2 ) -{ - // for some reason commenting out lines (as shown) led to crashing of the release version - if ( *pp1 > *pp2 ) - return -1; - if ( *pp1 < *pp2 ) // - return 1; - return 0; // -} - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/proof/pr.c b/src/sat/proof/pr.c deleted file mode 100644 index 2d1ab2d1..00000000 --- a/src/sat/proof/pr.c +++ /dev/null @@ -1,1263 +0,0 @@ -/**CFile**************************************************************** - - FileName [pr.c] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Proof recording.] - - Synopsis [Core procedures of the package.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: pr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#include -#include -#include -#include -#include -//#include "vec.h" -#include "pr.h" - -//////////////////////////////////////////////////////////////////////// -/// DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -typedef unsigned lit; - -typedef struct Pr_Cls_t_ Pr_Cls_t; -struct Pr_Cls_t_ -{ - unsigned uTruth; // interpolant - void * pProof; // the proof node -// void * pAntis; // the anticedents - Pr_Cls_t * pNext; // the next clause - Pr_Cls_t * pNext0; // the next 0-watch - Pr_Cls_t * pNext1; // the next 0-watch - int Id; // the clause ID - unsigned fA : 1; // belongs to A - unsigned fRoot : 1; // original clause - unsigned fVisit : 1; // visited clause - unsigned nLits : 24; // the number of literals - lit pLits[0]; // literals of this clause -}; - -struct Pr_Man_t_ -{ - // general data - int fProofWrite; // writes the proof file - int fProofVerif; // verifies the proof - int nVars; // the number of variables - int nVarsAB; // the number of global variables - int nRoots; // the number of root clauses - int nClauses; // the number of all clauses - int nClausesA; // the number of clauses of A - Pr_Cls_t * pHead; // the head clause - Pr_Cls_t * pTail; // the tail clause - Pr_Cls_t * pLearnt; // the tail clause - Pr_Cls_t * pEmpty; // the empty clause - // internal BCP - int nRootSize; // the number of root level assignments - int nTrailSize; // the number of assignments made - lit * pTrail; // chronological order of assignments (size nVars) - lit * pAssigns; // assignments by variable (size nVars) - char * pSeens; // temporary mark (size nVars) - char * pVarTypes; // variable type (size nVars) [1=A, 0=B, <0=AB] - Pr_Cls_t ** pReasons; // reasons for each assignment (size nVars) - Pr_Cls_t ** pWatches; // watched clauses for each literal (size 2*nVars) - int nVarsAlloc; // the allocated size of arrays - // proof recording - void * pManProof; // proof manager - int Counter; // counter of resolved clauses - // memory management - int nChunkSize; // the number of bytes in a chunk - int nChunkUsed; // the number of bytes used in the last chunk - char * pChunkLast; // the last memory chunk - // internal verification - lit * pResLits; // the literals of the resolvent - int nResLits; // the number of literals of the resolvent - int nResLitsAlloc;// the number of literals of the resolvent - // runtime stats - int timeBcp; - int timeTrace; - int timeRead; - int timeTotal; -}; - -#ifndef PRT -#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC)) -#endif - -// variable assignments -static const lit LIT_UNDEF = 0xffffffff; - -// variable/literal conversions (taken from MiniSat) -static inline lit toLit (int v) { return v + v; } -static inline lit toLitCond(int v, int c) { return v + v + (c != 0); } -static inline lit lit_neg (lit l) { return l ^ 1; } -static inline int lit_var (lit l) { return l >> 1; } -static inline int lit_sign (lit l) { return l & 1; } -static inline int lit_print(lit l) { return lit_sign(l)? -lit_var(l)-1 : lit_var(l)+1; } -static inline lit lit_read (int s) { return s > 0 ? toLit(s-1) : lit_neg(toLit(-s-1)); } -static inline int lit_check(lit l, int n) { return l >= 0 && lit_var(l) < n; } - -// iterators through the clauses -#define Pr_ManForEachClause( p, pCls ) for( pCls = p->pHead; pCls; pCls = pCls->pNext ) -#define Pr_ManForEachClauseRoot( p, pCls ) for( pCls = p->pHead; pCls != p->pLearnt; pCls = pCls->pNext ) -#define Pr_ManForEachClauseLearnt( p, pCls ) for( pCls = p->pLearnt; pCls; pCls = pCls->pNext ) - -// static procedures -static char * Pr_ManMemoryFetch( Pr_Man_t * p, int nBytes ); -static void Pr_ManMemoryStop( Pr_Man_t * p ); -static void Pr_ManResize( Pr_Man_t * p, int nVarsNew ); - -// exported procedures -extern Pr_Man_t * Pr_ManAlloc( int nVarsAlloc ); -extern void Pr_ManFree( Pr_Man_t * p ); -extern int Pr_ManAddClause( Pr_Man_t * p, lit * pBeg, lit * pEnd, int fRoot, int fClauseA ); -extern int Pr_ManProofWrite( Pr_Man_t * p ); - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -/**Function************************************************************* - - Synopsis [Allocate proof manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pr_Man_t * Pr_ManAlloc( int nVarsAlloc ) -{ - Pr_Man_t * p; - // allocate the manager - p = (Pr_Man_t *)malloc( sizeof(Pr_Man_t) ); - memset( p, 0, sizeof(Pr_Man_t) ); - // allocate internal arrays - Pr_ManResize( p, nVarsAlloc? nVarsAlloc : 256 ); - // set the starting number of variables - p->nVars = 0; - // memory management - p->nChunkSize = (1<<16); // use 64K chunks - // verification - p->nResLitsAlloc = (1<<16); - p->pResLits = malloc( sizeof(lit) * p->nResLitsAlloc ); - // parameters - p->fProofWrite = 0; - p->fProofVerif = 0; - return p; -} - -/**Function************************************************************* - - Synopsis [Resize proof manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pr_ManResize( Pr_Man_t * p, int nVarsNew ) -{ - // check if resizing is needed - if ( p->nVarsAlloc < nVarsNew ) - { - int nVarsAllocOld = p->nVarsAlloc; - // find the new size - if ( p->nVarsAlloc == 0 ) - p->nVarsAlloc = 1; - while ( p->nVarsAlloc < nVarsNew ) - p->nVarsAlloc *= 2; - // resize the arrays - p->pTrail = (lit *) realloc( p->pTrail, sizeof(lit) * p->nVarsAlloc ); - p->pAssigns = (lit *) realloc( p->pAssigns, sizeof(lit) * p->nVarsAlloc ); - p->pSeens = (char *) realloc( p->pSeens, sizeof(char) * p->nVarsAlloc ); - p->pVarTypes = (char *) realloc( p->pVarTypes, sizeof(char) * p->nVarsAlloc ); - p->pReasons = (Pr_Cls_t **)realloc( p->pReasons, sizeof(Pr_Cls_t *) * p->nVarsAlloc ); - p->pWatches = (Pr_Cls_t **)realloc( p->pWatches, sizeof(Pr_Cls_t *) * p->nVarsAlloc*2 ); - // clean the free space - memset( p->pAssigns + nVarsAllocOld, 0xff, sizeof(lit) * (p->nVarsAlloc - nVarsAllocOld) ); - memset( p->pSeens + nVarsAllocOld, 0, sizeof(char) * (p->nVarsAlloc - nVarsAllocOld) ); - memset( p->pVarTypes + nVarsAllocOld, 0, sizeof(char) * (p->nVarsAlloc - nVarsAllocOld) ); - memset( p->pReasons + nVarsAllocOld, 0, sizeof(Pr_Cls_t *) * (p->nVarsAlloc - nVarsAllocOld) ); - memset( p->pWatches + nVarsAllocOld, 0, sizeof(Pr_Cls_t *) * (p->nVarsAlloc - nVarsAllocOld)*2 ); - } - // adjust the number of variables - if ( p->nVars < nVarsNew ) - p->nVars = nVarsNew; -} - -/**Function************************************************************* - - Synopsis [Deallocate proof manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pr_ManFree( Pr_Man_t * p ) -{ - printf( "Runtime stats:\n" ); -PRT( "Reading ", p->timeRead ); -PRT( "BCP ", p->timeBcp ); -PRT( "Trace ", p->timeTrace ); -PRT( "TOTAL ", p->timeTotal ); - - Pr_ManMemoryStop( p ); - free( p->pTrail ); - free( p->pAssigns ); - free( p->pSeens ); - free( p->pVarTypes ); - free( p->pReasons ); - free( p->pWatches ); - free( p->pResLits ); - free( p ); -} - -/**Function************************************************************* - - Synopsis [Adds one clause to the watcher list.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Pr_ManWatchClause( Pr_Man_t * p, Pr_Cls_t * pClause, lit Lit ) -{ - assert( lit_check(Lit, p->nVars) ); - if ( pClause->pLits[0] == Lit ) - pClause->pNext0 = p->pWatches[lit_neg(Lit)]; - else - { - assert( pClause->pLits[1] == Lit ); - pClause->pNext1 = p->pWatches[lit_neg(Lit)]; - } - p->pWatches[lit_neg(Lit)] = pClause; -} - -/**Function************************************************************* - - Synopsis [Adds one clause to the manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pr_ManAddClause( Pr_Man_t * p, lit * pBeg, lit * pEnd, int fRoot, int fClauseA ) -{ - Pr_Cls_t * pClause; - lit Lit, * i, * j; - int nSize, VarMax; - - // process the literals - if ( pBeg < pEnd ) - { - // insertion sort - VarMax = lit_var( *pBeg ); - for ( i = pBeg + 1; i < pEnd; i++ ) - { - Lit = *i; - VarMax = lit_var(Lit) > VarMax ? lit_var(Lit) : VarMax; - for ( j = i; j > pBeg && *(j-1) > Lit; j-- ) - *j = *(j-1); - *j = Lit; - } - // make sure there is no duplicated variables - for ( i = pBeg + 1; i < pEnd; i++ ) - assert( lit_var(*(i-1)) != lit_var(*i) ); - // resize the manager - Pr_ManResize( p, VarMax+1 ); - } - - // get memory for the clause - nSize = sizeof(Pr_Cls_t) + sizeof(lit) * (pEnd - pBeg); - pClause = (Pr_Cls_t *)Pr_ManMemoryFetch( p, nSize ); - memset( pClause, 0, sizeof(Pr_Cls_t) ); - - // assign the clause - assert( !fClauseA || fRoot ); // clause of A is always a root clause - p->nRoots += fRoot; - p->nClausesA += fClauseA; - pClause->Id = p->nClauses++; - pClause->fA = fClauseA; - pClause->fRoot = fRoot; - pClause->nLits = pEnd - pBeg; - memcpy( pClause->pLits, pBeg, sizeof(lit) * (pEnd - pBeg) ); - - // add the clause to the list - if ( p->pHead == NULL ) - p->pHead = pClause; - if ( p->pTail == NULL ) - p->pTail = pClause; - else - { - p->pTail->pNext = pClause; - p->pTail = pClause; - } - - // mark the first learnt clause - if ( p->pLearnt == NULL && !pClause->fRoot ) - p->pLearnt = pClause; - - // add the empty clause - if ( pClause->nLits == 0 ) - { - if ( p->pEmpty ) - printf( "More than one empty clause!\n" ); - p->pEmpty = pClause; - } - return 1; -} - -/**Function************************************************************* - - Synopsis [Fetches memory.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -char * Pr_ManMemoryFetch( Pr_Man_t * p, int nBytes ) -{ - char * pMem; - if ( p->pChunkLast == NULL || nBytes > p->nChunkSize - p->nChunkUsed ) - { - pMem = (char *)malloc( p->nChunkSize ); - *(char **)pMem = p->pChunkLast; - p->pChunkLast = pMem; - p->nChunkUsed = sizeof(char *); - } - pMem = p->pChunkLast + p->nChunkUsed; - p->nChunkUsed += nBytes; - return pMem; -} - -/**Function************************************************************* - - Synopsis [Frees memory manager.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pr_ManMemoryStop( Pr_Man_t * p ) -{ - char * pMem, * pNext; - if ( p->pChunkLast == NULL ) - return; - for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext ) - free( pMem ); - free( pMem ); -} - -/**Function************************************************************* - - Synopsis [Reports memory usage in bytes.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pr_ManMemoryReport( Pr_Man_t * p ) -{ - int Total; - char * pMem, * pNext; - if ( p->pChunkLast == NULL ) - return 0; - Total = p->nChunkUsed; - for ( pMem = p->pChunkLast; pNext = *(char **)pMem; pMem = pNext ) - Total += p->nChunkSize; - return Total; -} - -/**Function************************************************************* - - Synopsis [Records the proof.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Extra_PrintBinary_( FILE * pFile, unsigned Sign[], int nBits ) -{ - int Remainder, nWords; - int w, i; - - Remainder = (nBits%(sizeof(unsigned)*8)); - nWords = (nBits/(sizeof(unsigned)*8)) + (Remainder>0); - - for ( w = nWords-1; w >= 0; w-- ) - for ( i = ((w == nWords-1 && Remainder)? Remainder-1: 31); i >= 0; i-- ) - fprintf( pFile, "%c", '0' + (int)((Sign[w] & (1< 0) ); -} - -/**Function************************************************************* - - Synopsis [Prints the interpolant for one clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pr_ManPrintInterOne( Pr_Man_t * p, Pr_Cls_t * pClause ) -{ - printf( "Clause %2d : ", pClause->Id ); - Extra_PrintBinary_( stdout, &pClause->uTruth, (1 << p->nVarsAB) ); - printf( "\n" ); -} - - - -/**Function************************************************************* - - Synopsis [Records implication.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline int Pr_ManEnqueue( Pr_Man_t * p, lit Lit, Pr_Cls_t * pReason ) -{ - int Var = lit_var(Lit); - if ( p->pAssigns[Var] != LIT_UNDEF ) - return p->pAssigns[Var] == Lit; - p->pAssigns[Var] = Lit; - p->pReasons[Var] = pReason; - p->pTrail[p->nTrailSize++] = Lit; -//printf( "assigning var %d value %d\n", Var, !lit_sign(Lit) ); - return 1; -} - -/**Function************************************************************* - - Synopsis [Records implication.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline void Pr_ManCancelUntil( Pr_Man_t * p, int Level ) -{ - lit Lit; - int i, Var; - for ( i = p->nTrailSize - 1; i >= Level; i-- ) - { - Lit = p->pTrail[i]; - Var = lit_var( Lit ); - p->pReasons[Var] = NULL; - p->pAssigns[Var] = LIT_UNDEF; -//printf( "cancelling var %d\n", Var ); - } - p->nTrailSize = Level; -} - -/**Function************************************************************* - - Synopsis [Propagate one assignment.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -static inline Pr_Cls_t * Pr_ManPropagateOne( Pr_Man_t * p, lit Lit ) -{ - Pr_Cls_t ** ppPrev, * pCur, * pTemp; - lit LitF = lit_neg(Lit); - int i; - // iterate through the literals - ppPrev = p->pWatches + Lit; - for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) - { - // make sure the false literal is in the second literal of the clause - if ( pCur->pLits[0] == LitF ) - { - pCur->pLits[0] = pCur->pLits[1]; - pCur->pLits[1] = LitF; - pTemp = pCur->pNext0; - pCur->pNext0 = pCur->pNext1; - pCur->pNext1 = pTemp; - } - assert( pCur->pLits[1] == LitF ); - - // if the first literal is true, the clause is satisfied - if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) - { - ppPrev = &pCur->pNext1; - continue; - } - - // look for a new literal to watch - for ( i = 2; i < (int)pCur->nLits; i++ ) - { - // skip the case when the literal is false - if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] ) - continue; - // the literal is either true or unassigned - watch it - pCur->pLits[1] = pCur->pLits[i]; - pCur->pLits[i] = LitF; - // remove this clause from the watch list of Lit - *ppPrev = pCur->pNext1; - // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) - Pr_ManWatchClause( p, pCur, pCur->pLits[1] ); - break; - } - if ( i < (int)pCur->nLits ) // found new watch - continue; - - // clause is unit - enqueue new implication - if ( Pr_ManEnqueue(p, pCur->pLits[0], pCur) ) - { - ppPrev = &pCur->pNext1; - continue; - } - - // conflict detected - return the conflict clause - return pCur; - } - return NULL; -} - -/**Function************************************************************* - - Synopsis [Propagate the current assignments.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pr_Cls_t * Pr_ManPropagate( Pr_Man_t * p, int Start ) -{ - Pr_Cls_t * pClause; - int i; - int clk = clock(); - for ( i = Start; i < p->nTrailSize; i++ ) - { - pClause = Pr_ManPropagateOne( p, p->pTrail[i] ); - if ( pClause ) - { -p->timeBcp += clock() - clk; - return pClause; - } - } -p->timeBcp += clock() - clk; - return NULL; -} - - -/**Function************************************************************* - - Synopsis [Prints the clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pr_ManPrintClause( Pr_Cls_t * pClause ) -{ - int i; - printf( "Clause ID = %d. Proof = %d. {", pClause->Id, (int)pClause->pProof ); - for ( i = 0; i < (int)pClause->nLits; i++ ) - printf( " %d", pClause->pLits[i] ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [Prints the resolvent.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pr_ManPrintResolvent( lit * pResLits, int nResLits ) -{ - int i; - printf( "Resolvent: {" ); - for ( i = 0; i < nResLits; i++ ) - printf( " %d", pResLits[i] ); - printf( " }\n" ); -} - -/**Function************************************************************* - - Synopsis [Writes one root clause into a file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pr_ManProofWriteOne( Pr_Man_t * p, Pr_Cls_t * pClause ) -{ - pClause->pProof = (void *)++p->Counter; - - if ( p->fProofWrite ) - { - int v; - fprintf( p->pManProof, "%d", (int)pClause->pProof ); - for ( v = 0; v < (int)pClause->nLits; v++ ) - fprintf( p->pManProof, " %d", lit_print(pClause->pLits[v]) ); - fprintf( p->pManProof, " 0 0\n" ); - } -} - -/**Function************************************************************* - - Synopsis [Traces the proof for one clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pr_ManProofTraceOne( Pr_Man_t * p, Pr_Cls_t * pConflict, Pr_Cls_t * pFinal ) -{ - Pr_Cls_t * pReason; - int i, v, Var, PrevId; - int fPrint = 0; - int clk = clock(); - - // collect resolvent literals - if ( p->fProofVerif ) - { - assert( (int)pConflict->nLits <= p->nResLitsAlloc ); - memcpy( p->pResLits, pConflict->pLits, sizeof(lit) * pConflict->nLits ); - p->nResLits = pConflict->nLits; - } - - // mark all the variables in the conflict as seen - for ( v = 0; v < (int)pConflict->nLits; v++ ) - p->pSeens[lit_var(pConflict->pLits[v])] = 1; - - // start the anticedents -// pFinal->pAntis = Vec_PtrAlloc( 32 ); -// Vec_PtrPush( pFinal->pAntis, pConflict ); - - if ( p->nClausesA ) - pFinal->uTruth = pConflict->uTruth; - - // follow the trail backwards - PrevId = (int)pConflict->pProof; - for ( i = p->nTrailSize - 1; i >= 0; i-- ) - { - // skip literals that are not involved - Var = lit_var(p->pTrail[i]); - if ( !p->pSeens[Var] ) - continue; - p->pSeens[Var] = 0; - - // skip literals of the resulting clause - pReason = p->pReasons[Var]; - if ( pReason == NULL ) - continue; - assert( p->pTrail[i] == pReason->pLits[0] ); - - // add the variables to seen - for ( v = 1; v < (int)pReason->nLits; v++ ) - p->pSeens[lit_var(pReason->pLits[v])] = 1; - - - // record the reason clause - assert( pReason->pProof > 0 ); - p->Counter++; - if ( p->fProofWrite ) - fprintf( p->pManProof, "%d * %d %d 0\n", p->Counter, PrevId, (int)pReason->pProof ); - PrevId = p->Counter; - - if ( p->nClausesA ) - { - if ( p->pVarTypes[Var] == 1 ) // var of A - pFinal->uTruth |= pReason->uTruth; - else - pFinal->uTruth &= pReason->uTruth; - } - - // resolve the temporary resolvent with the reason clause - if ( p->fProofVerif ) - { - int v1, v2; - if ( fPrint ) - Pr_ManPrintResolvent( p->pResLits, p->nResLits ); - // check that the var is present in the resolvent - for ( v1 = 0; v1 < p->nResLits; v1++ ) - if ( lit_var(p->pResLits[v1]) == Var ) - break; - if ( v1 == p->nResLits ) - printf( "Recording clause %d: Cannot find variable %d in the temporary resolvent.\n", pFinal->Id, Var ); - if ( p->pResLits[v1] != lit_neg(pReason->pLits[0]) ) - printf( "Recording clause %d: The resolved variable %d is in the wrong polarity.\n", pFinal->Id, Var ); - // remove this variable from the resolvent - assert( lit_var(p->pResLits[v1]) == Var ); - p->nResLits--; - for ( ; v1 < p->nResLits; v1++ ) - p->pResLits[v1] = p->pResLits[v1+1]; - // add variables of the reason clause - for ( v2 = 1; v2 < (int)pReason->nLits; v2++ ) - { - for ( v1 = 0; v1 < p->nResLits; v1++ ) - if ( lit_var(p->pResLits[v1]) == lit_var(pReason->pLits[v2]) ) - break; - // if it is a new variable, add it to the resolvent - if ( v1 == p->nResLits ) - { - if ( p->nResLits == p->nResLitsAlloc ) - printf( "Recording clause %d: Ran out of space for intermediate resolvent.\n, pFinal->Id" ); - p->pResLits[ p->nResLits++ ] = pReason->pLits[v2]; - continue; - } - // if the variable is the same, the literal should be the same too - if ( p->pResLits[v1] == pReason->pLits[v2] ) - continue; - // the literal is different - printf( "Recording clause %d: Trying to resolve the clause with more than one opposite literal.\n", pFinal->Id ); - } - } - -// Vec_PtrPush( pFinal->pAntis, pReason ); - } - - // unmark all seen variables -// for ( i = p->nTrailSize - 1; i >= 0; i-- ) -// p->pSeens[lit_var(p->pTrail[i])] = 0; - // check that the literals are unmarked -// for ( i = p->nTrailSize - 1; i >= 0; i-- ) -// assert( p->pSeens[lit_var(p->pTrail[i])] == 0 ); - - // use the resulting clause to check the correctness of resolution - if ( p->fProofVerif ) - { - int v1, v2; - if ( fPrint ) - Pr_ManPrintResolvent( p->pResLits, p->nResLits ); - for ( v1 = 0; v1 < p->nResLits; v1++ ) - { - for ( v2 = 0; v2 < (int)pFinal->nLits; v2++ ) - if ( pFinal->pLits[v2] == p->pResLits[v1] ) - break; - if ( v2 < (int)pFinal->nLits ) - continue; - break; - } - if ( v1 < p->nResLits ) - { - printf( "Recording clause %d: The final resolvent is wrong.\n", pFinal->Id ); - Pr_ManPrintClause( pConflict ); - Pr_ManPrintResolvent( p->pResLits, p->nResLits ); - Pr_ManPrintClause( pFinal ); - } - } -p->timeTrace += clock() - clk; - - // return the proof pointer - if ( p->nClausesA ) - { - Pr_ManPrintInterOne( p, pFinal ); - } - return p->Counter; -} - -/**Function************************************************************* - - Synopsis [Records the proof for one clause.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pr_ManProofRecordOne( Pr_Man_t * p, Pr_Cls_t * pClause ) -{ - Pr_Cls_t * pConflict; - int i; - - // empty clause never ends up there - assert( pClause->nLits > 0 ); - if ( pClause->nLits == 0 ) - printf( "Error: Empty clause is attempted.\n" ); - - // add assumptions to the trail - assert( !pClause->fRoot ); - assert( p->nTrailSize == p->nRootSize ); - for ( i = 0; i < (int)pClause->nLits; i++ ) - if ( !Pr_ManEnqueue( p, lit_neg(pClause->pLits[i]), NULL ) ) - { - assert( 0 ); // impossible - return 0; - } - - // propagate the assumptions - pConflict = Pr_ManPropagate( p, p->nRootSize ); - if ( pConflict == NULL ) - { - assert( 0 ); // cannot prove - return 0; - } - - // construct the proof - pClause->pProof = (void *)Pr_ManProofTraceOne( p, pConflict, pClause ); - - // undo to the root level - Pr_ManCancelUntil( p, p->nRootSize ); - - // add large clauses to the watched lists - if ( pClause->nLits > 1 ) - { - Pr_ManWatchClause( p, pClause, pClause->pLits[0] ); - Pr_ManWatchClause( p, pClause, pClause->pLits[1] ); - return 1; - } - assert( pClause->nLits == 1 ); - - // if the clause proved is unit, add it and propagate - if ( !Pr_ManEnqueue( p, pClause->pLits[0], pClause ) ) - { - assert( 0 ); // impossible - return 0; - } - - // propagate the assumption - pConflict = Pr_ManPropagate( p, p->nRootSize ); - if ( pConflict ) - { - // construct the proof - p->pEmpty->pProof = (void *)Pr_ManProofTraceOne( p, pConflict, p->pEmpty ); - printf( "Found last conflict after adding unit clause number %d!\n", pClause->Id ); - return 0; - } - - // update the root level - p->nRootSize = p->nTrailSize; - return 1; -} - -/**Function************************************************************* - - Synopsis [Propagate the root clauses.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pr_ManProcessRoots( Pr_Man_t * p ) -{ - Pr_Cls_t * pClause; - int Counter; - - // make sure the root clauses are preceeding the learnt clauses - Counter = 0; - Pr_ManForEachClause( p, pClause ) - { - assert( (int)pClause->fA == (Counter < (int)p->nClausesA) ); - assert( (int)pClause->fRoot == (Counter < (int)p->nRoots) ); - Counter++; - } - assert( p->nClauses == Counter ); - - // make sure the last clause if empty - assert( p->pTail->nLits == 0 ); - - // go through the root unit clauses - p->nTrailSize = 0; - Pr_ManForEachClauseRoot( p, pClause ) - { - // create watcher lists for the root clauses - if ( pClause->nLits > 1 ) - { - Pr_ManWatchClause( p, pClause, pClause->pLits[0] ); - Pr_ManWatchClause( p, pClause, pClause->pLits[1] ); - } - // empty clause and large clauses - if ( pClause->nLits != 1 ) - continue; - // unit clause - assert( lit_check(pClause->pLits[0], p->nVars) ); - if ( !Pr_ManEnqueue( p, pClause->pLits[0], pClause ) ) - { - // detected root level conflict - printf( "Pr_ManProcessRoots(): Detected a root-level conflict\n" ); - assert( 0 ); - return 0; - } - } - - // propagate the root unit clauses - pClause = Pr_ManPropagate( p, 0 ); - if ( pClause ) - { - // detected root level conflict - printf( "Pr_ManProcessRoots(): Detected a root-level conflict\n" ); - assert( 0 ); - return 0; - } - - // set the root level - p->nRootSize = p->nTrailSize; - return 1; -} - -/**Function************************************************************* - - Synopsis [Records the proof.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -void Pr_ManPrepareInter( Pr_Man_t * p ) -{ - unsigned uTruths[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; - Pr_Cls_t * pClause; - int Var, v; - - // mark the variable encountered in the clauses of A - Pr_ManForEachClauseRoot( p, pClause ) - { - if ( !pClause->fA ) - break; - for ( v = 0; v < (int)pClause->nLits; v++ ) - p->pVarTypes[lit_var(pClause->pLits[v])] = 1; - } - - // check variables that appear in clauses of B - p->nVarsAB = 0; - Pr_ManForEachClauseRoot( p, pClause ) - { - if ( pClause->fA ) - continue; - for ( v = 0; v < (int)pClause->nLits; v++ ) - { - Var = lit_var(pClause->pLits[v]); - if ( p->pVarTypes[Var] == 1 ) // var of A - { - // change it into a global variable - p->nVarsAB++; - p->pVarTypes[Var] = -1; - } - } - } - - // order global variables - p->nVarsAB = 0; - for ( v = 0; v < p->nVars; v++ ) - if ( p->pVarTypes[v] == -1 ) - p->pVarTypes[v] -= p->nVarsAB++; -printf( "There are %d global variables.\n", p->nVarsAB ); - - // set interpolants for root clauses - Pr_ManForEachClauseRoot( p, pClause ) - { - if ( !pClause->fA ) // clause of B - { - pClause->uTruth = ~0; - Pr_ManPrintInterOne( p, pClause ); - continue; - } - // clause of A - pClause->uTruth = 0; - for ( v = 0; v < (int)pClause->nLits; v++ ) - { - Var = lit_var(pClause->pLits[v]); - if ( p->pVarTypes[Var] < 0 ) // global var - { - if ( lit_sign(pClause->pLits[v]) ) // negative var - pClause->uTruth |= ~uTruths[ -p->pVarTypes[Var]-1 ]; - else - pClause->uTruth |= uTruths[ -p->pVarTypes[Var]-1 ]; - } - } - Pr_ManPrintInterOne( p, pClause ); - } -} - -/**Function************************************************************* - - Synopsis [Records the proof.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pr_ManProofWrite( Pr_Man_t * p ) -{ - Pr_Cls_t * pClause; - int RetValue = 1; - - // propagate root level assignments - Pr_ManProcessRoots( p ); - - // prepare the interpolant computation - if ( p->nClausesA ) - Pr_ManPrepareInter( p ); - - // construct proof for each clause - // start the proof - if ( p->fProofWrite ) - p->pManProof = fopen( "proof.cnf_", "w" ); - p->Counter = 0; - - // write the root clauses - Pr_ManForEachClauseRoot( p, pClause ) - Pr_ManProofWriteOne( p, pClause ); - - // consider each learned clause - Pr_ManForEachClauseLearnt( p, pClause ) - { - if ( !Pr_ManProofRecordOne( p, pClause ) ) - { - RetValue = 0; - break; - } - } - - if ( p->nClausesA ) - { - printf( "Interpolant: " ); - } - - - // stop the proof - if ( p->fProofWrite ) - { - fclose( p->pManProof ); - p->pManProof = NULL; - } - return RetValue; -} - -/**Function************************************************************* - - Synopsis [Reads clauses from file.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -Pr_Man_t * Pr_ManProofRead( char * pFileName ) -{ - Pr_Man_t * p = NULL; - char * pCur, * pBuffer = NULL; - int * pArray = NULL; - FILE * pFile; - int RetValue, Counter, nNumbers, Temp; - int nClauses, nClausesA, nRoots, nVars; - - // open the file - pFile = fopen( pFileName, "r" ); - if ( pFile == NULL ) - { - printf( "Count not open input file \"%s\".\n", pFileName ); - return NULL; - } - - // read the file - pBuffer = (char *)malloc( (1<<16) ); - for ( Counter = 0; fgets( pBuffer, (1<<16), pFile ); ) - { - if ( pBuffer[0] == 'c' ) - continue; - if ( pBuffer[0] == 'p' ) - { - assert( p == NULL ); - nClausesA = 0; - RetValue = sscanf( pBuffer + 1, "%d %d %d %d", &nVars, &nClauses, &nRoots, &nClausesA ); - if ( RetValue != 3 && RetValue != 4 ) - { - printf( "Wrong input file format.\n" ); - } - p = Pr_ManAlloc( nVars ); - pArray = (int *)malloc( sizeof(int) * (nVars + 10) ); - continue; - } - // skip empty lines - for ( pCur = pBuffer; *pCur; pCur++ ) - if ( !(*pCur == ' ' || *pCur == '\t' || *pCur == '\r' || *pCur == '\n') ) - break; - if ( *pCur == 0 ) - continue; - // scan the numbers from file - nNumbers = 0; - pCur = pBuffer; - while ( *pCur ) - { - // skip spaces - for ( ; *pCur && *pCur == ' '; pCur++ ); - // read next number - Temp = 0; - sscanf( pCur, "%d", &Temp ); - if ( Temp == 0 ) - break; - pArray[ nNumbers++ ] = lit_read( Temp ); - // skip non-spaces - for ( ; *pCur && *pCur != ' '; pCur++ ); - } - // add the clause - if ( !Pr_ManAddClause( p, pArray, pArray + nNumbers, Counter < nRoots, Counter < nClausesA ) ) - { - printf( "Bad clause number %d.\n", Counter ); - return NULL; - } - // count the clauses - Counter++; - } - // check the number of clauses - if ( Counter != nClauses ) - printf( "Expected %d clauses but read %d.\n", nClauses, Counter ); - - // finish - if ( pArray ) free( pArray ); - if ( pBuffer ) free( pBuffer ); - fclose( pFile ); - return p; -} - -/**Function************************************************************* - - Synopsis [Records the proof.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -/* -int Pr_ManProofCount_rec( Pr_Cls_t * pClause ) -{ - Pr_Cls_t * pNext; - int i, Counter; - if ( pClause->fRoot ) - return 0; - if ( pClause->fVisit ) - return 0; - pClause->fVisit = 1; - // count the number of visited clauses - Counter = 1; - Vec_PtrForEachEntry( pClause->pAntis, pNext, i ) - Counter += Pr_ManProofCount_rec( pNext ); - return Counter; -} -*/ - -/**Function************************************************************* - - Synopsis [Records the proof.] - - Description [] - - SideEffects [] - - SeeAlso [] - -***********************************************************************/ -int Pr_ManProofTest( char * pFileName ) -{ - Pr_Man_t * p; - int clk, clkTotal = clock(); - -clk = clock(); - p = Pr_ManProofRead( pFileName ); -p->timeRead = clock() - clk; - if ( p == NULL ) - return 0; - - Pr_ManProofWrite( p ); - - // print stats -/* - nUsed = Pr_ManProofCount_rec( p->pEmpty ); - printf( "Roots = %d. Learned = %d. Total = %d. Steps = %d. Ave = %.2f. Used = %d. Ratio = %.2f. \n", - p->nRoots, p->nClauses-p->nRoots, p->nClauses, p->Counter, - 1.0*(p->Counter-p->nRoots)/(p->nClauses-p->nRoots), - nUsed, 1.0*nUsed/(p->nClauses-p->nRoots) ); -*/ - printf( "Vars = %d. Roots = %d. Learned = %d. Resol steps = %d. Ave = %.2f. Mem = %.2f Mb\n", - p->nVars, p->nRoots, p->nClauses-p->nRoots, p->Counter, - 1.0*(p->Counter-p->nRoots)/(p->nClauses-p->nRoots), - 1.0*Pr_ManMemoryReport(p)/(1<<20) ); - -p->timeTotal = clock() - clkTotal; - Pr_ManFree( p ); - return 1; -} - - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - - diff --git a/src/sat/proof/pr.h b/src/sat/proof/pr.h deleted file mode 100644 index 1e71a2d3..00000000 --- a/src/sat/proof/pr.h +++ /dev/null @@ -1,65 +0,0 @@ -/**CFile**************************************************************** - - FileName [pr.h] - - SystemName [ABC: Logic synthesis and verification system.] - - PackageName [Proof recording.] - - Synopsis [External declarations.] - - Author [Alan Mishchenko] - - Affiliation [UC Berkeley] - - Date [Ver. 1.0. Started - June 20, 2005.] - - Revision [$Id: pr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] - -***********************************************************************/ - -#ifndef __PR_H__ -#define __PR_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -#define inline __inline // compatible with MS VS 6.0 -#endif - -//////////////////////////////////////////////////////////////////////// -/// INCLUDES /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// PARAMETERS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// BASIC TYPES /// -//////////////////////////////////////////////////////////////////////// - -typedef struct Pr_Man_t_ Pr_Man_t; - -//////////////////////////////////////////////////////////////////////// -/// MACRO DEFINITIONS /// -//////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////////////////// -/// FUNCTION DECLARATIONS /// -//////////////////////////////////////////////////////////////////////// - -/*=== pr.c ==========================================================*/ - -#ifdef __cplusplus -} -#endif - -#endif - -//////////////////////////////////////////////////////////////////////// -/// END OF FILE /// -//////////////////////////////////////////////////////////////////////// - diff --git a/src/sat/proof/stats.txt b/src/sat/proof/stats.txt deleted file mode 100644 index 470b1630..00000000 --- a/src/sat/proof/stats.txt +++ /dev/null @@ -1,66 +0,0 @@ -UC Berkeley, ABC 1.01 (compiled Jan 20 2007 16:47:34) -abc.rc: No such file or directory -Loaded "abc.rc" from the parent directory. -abc 01> test -Found last conflict after adding unit clause number 10229! -Roots = 7184. Learned = 3047. Total = 10231. Steps = 196361. Ave = 62.09. Used = 2224. Ratio = 0.73. -Runtime stats: -Reading = 0.03 sec -BCP = 0.32 sec -Trace = 0.06 sec -TOTAL = 0.43 sec -abc 01> test -Found last conflict after adding unit clause number 7676! -Roots = 6605. Learned = 1073. Total = 7678. Steps = 52402. Ave = 42.68. Used = 1011. Ratio = 0.94. -Runtime stats: -Reading = 0.01 sec -BCP = 0.02 sec -Trace = 0.02 sec -TOTAL = 0.06 sec -abc 01> test -Found last conflict after adding unit clause number 37868! -Roots = 15443. Learned = 22427. Total = 37870. Steps = 2365472. Ave = 104.79. Used = 19763. Ratio = 0.88. -Runtime stats: -Reading = 0.20 sec -BCP = 14.67 sec -Trace = 0.56 sec -TOTAL = 15.74 sec -abc 01> - - -abc 05> wb ibm_bmc/len25u_renc.blif -abc 05> ps -(no name) : i/o = 348/ 1 lat = 0 nd = 3648 bdd = 15522 lev = 246 -abc 05> sat -v -==================================[MINISAT]=================================== -| Conflicts | ORIGINAL | LEARNT | Progress | -| | Clauses Literals | Limit Clauses Literals Lit/Cl | | -============================================================================== -| 0 | 17413 54996 | 5804 0 0 0.0 | 0.000 % | -| 100 | 17413 54996 | 6384 100 606 6.1 | 0.417 % | -| 250 | 17413 54996 | 7023 250 1586 6.3 | 0.417 % | -| 476 | 17413 54996 | 7725 476 3288 6.9 | 0.417 % | -| 813 | 17413 54996 | 8498 813 7586 9.3 | 0.417 % | -| 1319 | 17403 54970 | 9347 1318 14848 11.3 | 0.442 % | -| 2078 | 17403 54970 | 10282 2076 40186 19.4 | 0.466 % | -| 3217 | 17397 54948 | 11310 3208 99402 31.0 | 0.466 % | -| 4926 | 17392 54930 | 12441 4911 131848 26.8 | 0.491 % | -| 7489 | 17392 54930 | 13686 7474 204217 27.3 | 0.491 % | -| 11336 | 17357 54829 | 15054 11310 332863 29.4 | 0.638 % | -| 17103 | 17346 54794 | 16559 9130 203029 22.2 | 0.687 % | -| 25752 | 17288 54606 | 18215 9083 176982 19.5 | 0.834 % | -| 38727 | 17266 54536 | 20037 12674 278949 22.0 | 0.883 % | -| 58188 | 17240 54453 | 22041 11905 255255 21.4 | 0.957 % | -============================================================================== -Start = 15. Conf = 79435. Dec = 130967. Prop = 24083434. Insp = 136774586. -Total runtime = 18.66 sec. Var select = 0.00 sec. Var update = 0.00 sec. -UNSATISFIABLE Time = 18.69 sec -abc 05> -abc 05> test -Found last conflict after adding unit clause number 96902! -Roots = 17469. Learned = 79435. Total = 96904. Steps = 9700042. Ave = 121.89. Used = 57072. Ratio = 0.72. -Runtime stats: -Reading = 1.26 sec -BCP = 204.99 sec -Trace = 2.85 sec -TOTAL = 209.85 sec \ No newline at end of file diff --git a/todo.txt b/todo.txt deleted file mode 100644 index 3ab59b8c..00000000 --- a/todo.txt +++ /dev/null @@ -1,26 +0,0 @@ -- required time support -- printing ABC version/platform in the output files -- fix gcc compiler warnings -- port "mfs" from MVSIS -- improve AIG rewriting package -- unify functional representation of local functions -- additional rewriting options for delay optimization -- experiment with yield-aware standard-cell mapping -- improving area recovery in integrated sequential synthesis -- high-effort logic synthesis for hard miters (cofactoring, Boolean division) -- mapping into MV cells -- SAT solver with linear constraints -- specialized synthesis for EXORs and large MUXes -- sequential AIG rewriting initial state computation -- placement-aware mapping -- sequential equivalence checking -- parser for Verilog netlists -- hierarchy manager (hierarchical BLIF/BLIF-MV parser) - -- required time based on all cuts -- comparing tts of differently derived the same cut -- area flow based AIG rewriting -- cut frontier adjustment - - - -- cgit v1.2.3